Tcl Source Code

Changes On Branch main
Login

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

Changes In Branch main Excluding Merge-Ins

This is equivalent to a diff from e784d77fd7 to a5b130a5fa

2024-11-23
12:06
Revert "leapDay" stuff. Too early for 9.0.1. Update documentation Leaf check-in: a5b130a5fa user: jan.nijtmans tags: trunk, main
2024-11-22
22:00
Revert "leapDay" stuff. Update documentation Closed-Leaf check-in: bb9e3560fd user: jan.nijtmans tags: bug-f2b5f89c0d
11:15
Remove support for leap-minutes (I thought I already removed that) check-in: b2ae97e2c3 user: jan.nijtmans tags: trunk, main
2020-10-30
14:09
Rename "trunk" to "main", but with new propagating tag "trunk" check-in: 40014cd0fa user: jan.nijtmans tags: trunk, main
2020-10-29
21:09
merge trunk check-in: b5e7f9da2b user: dgp tags: dgp-refactor
21:09
merge trunk check-in: 9ef0a76b94 user: dgp tags: dgp-properbytearray
21:08
merge trunk check-in: af4787a970 user: dgp tags: novem
11:40
Merge 8.7 Closed-Leaf check-in: e784d77fd7 user: jan.nijtmans tags: trunk
11:18
Merge 8.6 check-in: 642317cdbc user: jan.nijtmans tags: core-8-branch
2020-10-27
21:36
merge 8.7 check-in: de3076b8ab user: dgp tags: trunk

Changes to .fossil-settings/crlf-glob.

1


2
3

4

5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22

-
+
+


+

+


+



-









-
compat/zlib/contrib/dotzlib/DotZLib/UnitTests.cs
compat/zlib/contrib/dotzlib/readme.txt
compat/zlib/contrib/dotzlib/*.cs
compat/zlib/contrib/vstudio/readme.txt
compat/zlib/contrib/vstudio/*/zlib.rc
compat/zlib/contrib/vstudio/*/zlibvc.def
compat/zlib/contrib/vstudio/*/*.sln
compat/zlib/win32/zlib.def
compat/zlib/win32/*.txt
compat/zlib/win64/*.txt
compat/zlib/zlib.map
libtommath/*.dsp
libtommath/*.sln
libtommath/*.vcproj
tools/tcl.hpj.in
tools/tcl.wse.in
win/buildall.vc.bat
win/coffbase.txt
win/makefile.vc
win/rules.vc
win/rules-ext.vc
win/targets.vc
win/tcl.dsp
win/tcl.dsw
win/tcl.hpj.in

Changes to .fossil-settings/encoding-glob.

1
2
3
4
5
6
7
8
9

1
2
3
4
5
6
7

-







-
tools/tcl.hpj.in
tools/tcl.wse.in
win/buildall.vc.bat
win/coffbase.txt
win/makefile.vc
win/rules.vc
win/tcl.dsp
win/tcl.dsw
win/tcl.hpj.in

Changes to .fossil-settings/ignore-glob.

20
21
22
23
24
25
26
27


28
29
30
31
32
33
34
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
35







-
+
+







*/config.status
*/tclConfig.sh
*/tclsh*
*/tcltest*
*/versions.vc
*/version.vc
*/libtcl.vfs
*/libtcl_*.zip
*/libtcl*.zip
*/tclUuid.h
html
libtommath/bn.ilg
libtommath/bn.ind
libtommath/pretty.build
libtommath/tommath.src
libtommath/*.log
libtommath/*.pdf
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
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







+



+







+




+





libtommath/etc/*
libtommath/demo/*
libtommath/*.out
libtommath/*.tex
macosx/configure
unix/autoMkindex.tcl
unix/dltest.marker
unix/dltest/embtest
unix/dltest/*.bundle
unix/dltest/*.dll
unix/dltest/*.dylib
unix/dltest/*.exe
unix/dltest/*.o
unix/dltest/*.sl
unix/dltest/*.so
unix/tcl.pc
unix/tclIndex
unix/Tcl-Info.plist
unix/Tclsh-Info.plist
unix/pkgs8/*
unix/pkgs/*
win/Debug*
win/Release*
win/*.manifest
win/pkgs8/*
win/pkgs/*
win/coffbase.txt
win/tcl.hpj
win/nmakehlp.out
win/nmhlp-out.txt

Changes to .gitattributes.

18
19
20
21
22
23
24

25
26
27
28
29
30
31
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32







+







*.svg text
*.ts text
*.tcl text
*.test text

# Declare files that will always have CRLF line endings on checkout.
*.bat eol=crlf
*.cs eol=crlf
*.sln eol=crlf
*.vc eol=crlf

# Denote all files that are truly binary and should not be modified.
*.a binary
*.bmp binary
*.dll binary

Changes to .github/ISSUE_TEMPLATE.md.

1
2
3

1
2

3


-
+
Important Note
==========
Please do not file issues with Tcl on Github. They are unlikely to be noticed in a timely fashion. Tcl issues are hosted in the [tcl fossil repository on core.tcl.tk](https://core.tcl.tk/tcl/tktnew); please post them there.
Please do not file issues with Tcl on Github. They are unlikely to be noticed in a timely fashion. Tcl issues are hosted in the [tcl fossil repository on core.tcl-lang.org](https://core.tcl-lang.org/tcl/tktnew); please post them there.

Changes to .github/PULL_REQUEST_TEMPLATE.md.

1
2
3

1
2

3


-
+
Important Note
==========
Please do not file pull requests with Tcl on Github. They are unlikely to be noticed in a timely fashion. Tcl issues (including patches) are hosted in the [tcl fossil repository on core.tcl.tk](https://core.tcl.tk/tcl/tktnew); please post them there.
Please do not file pull requests with Tcl on Github. They are unlikely to be noticed in a timely fashion. Tcl issues (including patches) are hosted in the [tcl fossil repository on core.tcl-lang.org](https://core.tcl-lang.org/tcl/tktnew); please post them there.

Added .github/dependabot.yml.







1
2
3
4
5
6
+
+
+
+
+
+
version: 2
updates:
- package-ecosystem: "github-actions"
  directory: "/"
  schedule:
      interval: "weekly"

Added .github/workflows/linux-build.yml.



















































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
name: Linux
on:
  push:
    branches:
    - "main"
    - "core-8-branch"
    - "core-8-6-branch"
    tags:
    - "core-**"
permissions:
  contents: read
jobs:
  gcc:
    runs-on: ubuntu-22.04
    strategy:
      matrix:
        config:
          - ""
          - "CFLAGS=-DTCL_NO_DEPRECATED=1"
          - "--disable-shared"
          - "--disable-zipfs"
          - "--enable-symbols"
          - "--enable-symbols=mem"
          - "--enable-symbols=all"
          - "CFLAGS=-ftrapv"
          # Duplicated below
          - "CFLAGS=-m32 CPPFLAGS=-m32 LDFLAGS=-m32 --disable-64bit"
    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
      - name: Prepare
        run: |
          touch tclStubInit.c tclOOStubInit.c tclOOScript.h
        working-directory: generic
      - name: Configure ${{ matrix.config }}
        run: |
          mkdir "${HOME}/install dir"
          ./configure ${CFGOPT} "--prefix=$HOME/install dir" || (cat config.log && exit 1)
        env:
          CFGOPT: ${{ matrix.config }}
        timeout-minutes: 5
      - name: Build
        run: |
          make -j4 all
        timeout-minutes: 5
      - name: Build Test Harness
        run: |
          make -j4 tcltest
        timeout-minutes: 5
      - name: Info
        run: |
          ulimit -a || echo 'get limit failed'
          echo 'puts exe:\t[info nameofexecutable]\nver:\t[info patchlevel]\t[if {![catch tcl::build-info ret]} {set ret}]\nlib:\t[info library]\nplat:\t[lsort -dictionary -stride 2 [array get tcl_platform]]' | make runtest || echo 'get info failed'
      - name: Run Tests
        run: |
          make test
        env:
          ERROR_ON_FAILURES: 1
        timeout-minutes: 30
      - name: Test-Drive Installation
        run: |
          make install
        timeout-minutes: 5
      - name: Create Distribution Package
        run: |
          make dist
        timeout-minutes: 5
      - name: Convert Documentation to HTML
        run: |
          make html-tcl
        timeout-minutes: 5

Added .github/workflows/mac-build.yml.






















































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
name: macOS
on:
  push:
    branches:
    - "main"
    - "core-8-branch"
    - "core-8-6-branch"
    tags:
    - "core-**"
permissions:
  contents: read
jobs:
  xcode:
    runs-on: macos-14
    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
        env:
          CFLAGS: -arch x86_64 -arch arm64
        timeout-minutes: 15
      - name: Run Tests
        run: make -j4 test styles=develop
        env:
          ERROR_ON_FAILURES: 1
          MAC_CI: 1
        timeout-minutes: 15
  clang:
    runs-on: macos-14
    strategy:
      matrix:
        config:
          - ""
          - "--disable-shared"
          - "--disable-zipfs"
          - "--enable-symbols"
          - "--enable-symbols=mem"
          - "--enable-symbols=all"
    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 }}
        # Note that macOS is always a 64 bit platform
        run: ./configure --enable-dtrace --enable-framework ${CFGOPT} "--prefix=$HOME/install" || (cat config.log && exit 1)
        env:
          CFLAGS: -arch x86_64 -arch arm64
          CFGOPT: ${{ matrix.config }}
        timeout-minutes: 5
      - name: Build
        run: |
          make -j4 all tcltest
        env:
          CFLAGS: -arch x86_64 -arch arm64
        timeout-minutes: 15
      - name: Info
        run: |
          ulimit -a || echo 'get limit failed'
          echo 'puts exe:\t[info nameofexecutable]\nver:\t[info patchlevel]\t[if {![catch tcl::build-info ret]} {set ret}]\nlib:\t[info library]\nplat:\t[lsort -dictionary -stride 2 [array get tcl_platform]]' | make runtest || echo 'get info failed'
      - name: Run Tests
        run: |
          make test
        env:
          ERROR_ON_FAILURES: 1
          MAC_CI: 1
        timeout-minutes: 15

Added .github/workflows/onefiledist.yml.








































































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
name: Build Binaries
on:
  push:
    branches:
    - "main"
    - "core-8-branch"
    tags:
    - "core-**"
permissions:
  contents: read
jobs:
  linux:
    name: Linux
    runs-on: ubuntu-20.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
        run: ./configure --disable-symbols --disable-shared --enable-zipfs
        working-directory: unix
      - name: Build
        run: |
          make tclsh
          make shell SCRIPT="$VER_PATH $GITHUB_ENV"
          echo "TCL_ZIP=`pwd`/`echo libtcl*.zip`" >> $GITHUB_ENV
        working-directory: unix
      - name: Package
        run: |
          cp ../unix/tclsh tclsh${TCL_PATCHLEVEL}_snapshot
          chmod +x tclsh${TCL_PATCHLEVEL}_snapshot
          tar -cf tclsh${TCL_PATCHLEVEL}_snapshot.tar tclsh${TCL_PATCHLEVEL}_snapshot
        working-directory: 1dist
      - name: Info
        run: |
          ulimit -a || echo 'get limit failed'
          echo 'puts exe:\t[info nameofexecutable]\nver:\t[info patchlevel]\t[if {![catch tcl::build-info ret]} {set ret}]\nlib:\t[info library]\nplat:\t[lsort -dictionary -stride 2 [array get tcl_platform]]' | make runtest || echo 'get info failed'
      - name: Upload
        uses: actions/upload-artifact@v4
        with:
          name: Tclsh ${{ env.TCL_PATCHLEVEL }} Linux single-file build (snapshot)
          path: 1dist/*.tar
  macos:
    name: macOS
    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
          touch generic/tclStubInit.c generic/tclOOStubInit.c || true
          wget https://github.com/culler/macher/releases/download/v1.3/macher
          sudo cp macher /usr/local/bin
          sudo chmod a+x /usr/local/bin/macher
          echo "VER_PATH=$(cd tools; pwd)/addVerToFile.tcl" >> $GITHUB_ENV
          echo "CREATE_DMG=$(cd create-dmg;pwd)/create-dmg" >> $GITHUB_ENV
          echo "CFLAGS=-arch x86_64 -arch arm64" >> $GITHUB_ENV
      - name: Configure
        run: ./configure --disable-symbols --disable-shared --enable-zipfs
        working-directory: unix
      - name: Build
        run: |
          make -j4 tclsh
          make -j4 shell SCRIPT="$VER_PATH $GITHUB_ENV"
          echo "TCL_BIN=`pwd`/tclsh" >> $GITHUB_ENV
          echo "TCL_ZIP=`pwd`/`echo libtcl*.zip`" >> $GITHUB_ENV
        working-directory: unix
      - name: Package
        run: |
          mkdir contents
          cp $TCL_BIN contents/tclsh${TCL_PATCHLEVEL}_snapshot
          chmod +x contents/tclsh${TCL_PATCHLEVEL}_snapshot
          cat > contents/README.txt <<EOF
          This is a single-file executable developer preview of Tcl $TCL_PATCHLEVEL

          It is not intended as an official release at all, so it is unsigned and unnotarized.
          Use strictly at your own risk.

          To run it, you need to copy the executable out and run:
              xattr -d com.apple.quarantine tclsh${TCL_PATCHLEVEL}_snapshot
          to mark the executable as runnable on your machine.
          EOF
          $CREATE_DMG \
              --volname "Tcl $TCL_PATCHLEVEL (snapshot)" \
              --window-pos 200 120 \
              --window-size 800 400 \
              "Tcl-$TCL_PATCHLEVEL-(snapshot).dmg" \
              "contents/"
        working-directory: 1dist
      - name: Info
        run: |
          ulimit -a || echo 'get limit failed'
          echo 'puts exe:\t[info nameofexecutable]\nver:\t[info patchlevel]\t[if {![catch tcl::build-info ret]} {set ret}]\nlib:\t[info library]\nplat:\t[lsort -dictionary -stride 2 [array get tcl_platform]]' | make runtest || echo 'get info failed'
      - name: Upload
        uses: actions/upload-artifact@v4
        with:
          name: Tclsh ${{ env.TCL_PATCHLEVEL }} macOS single-file build (snapshot)
          path: 1dist/*.dmg
  win:
    name: Windows
    runs-on: windows-2019
    defaults:
      run:
        shell: msys2 {0}
    timeout-minutes: 10
    env:
      CC: gcc
      CFGOPT: --disable-symbols --disable-shared
    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
        run: ./configure $CFGOPT
        working-directory: win
      - name: Build
        run: |
          make binaries libraries
          echo "TCL_ZIP=`pwd`/`echo libtcl*.zip`" >> $GITHUB_ENV
        working-directory: win
      - name: Get Exact Version
        run: |
          ./tclsh*.exe $VER_PATH $GITHUB_ENV
        working-directory: win
      - name: Set Executable Name
        run: |
          cp ../win/tclsh*.exe tclsh${TCL_PATCHLEVEL}_snapshot.exe
        working-directory: 1dist
      - name: Info
        run: |
          ulimit -a || echo 'get limit failed'
          echo 'puts exe:\t[info nameofexecutable]\nver:\t[info patchlevel]\t[if {![catch tcl::build-info ret]} {set ret}]\nlib:\t[info library]\nplat:\t[lsort -dictionary -stride 2 [array get tcl_platform]]' | make runtest || echo 'get info failed'
      - name: Upload
        uses: actions/upload-artifact@v4
        with:
          name: Tclsh ${{ env.TCL_PATCHLEVEL }} Windows single-file build (snapshot)
          path: '1dist/*_snapshot.exe'

Added .github/workflows/win-build.yml.

















































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
name: Windows
on:
  push:
    branches:
    - "main"
    - "core-8-branch"
    - "core-8-6-branch"
    tags:
    - "core-**"
permissions:
  contents: read
env:
  ERROR_ON_FAILURES: 1
jobs:
  msvc:
    runs-on: windows-2022
    defaults:
      run:
        shell: powershell
        working-directory: win
    strategy:
      matrix:
        config:
          - ""
          - "CHECKS=nodep"
          - "OPTS=static"
          - "OPTS=noembed"
          - "OPTS=symbols"
          - "OPTS=symbols STATS=compdbg,memdbg"
    # 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
          if ($lastexitcode -ne 0) {
             throw "nmake exit code: $lastexitcode"
          }
        timeout-minutes: 5
      - name: Build Test Harness ${{ matrix.config }}
        run: |
          &nmake -f makefile.vc ${{ matrix.config }} tcltest
          if ($lastexitcode -ne 0) {
             throw "nmake exit code: $lastexitcode"
          }
        timeout-minutes: 5
      - name: Run Tests ${{ matrix.config }}
        run: |
          &nmake -f makefile.vc ${{ matrix.config }} test
          if ($lastexitcode -ne 0) {
             throw "nmake exit code: $lastexitcode"
          }
        timeout-minutes: 30
  gcc:
    runs-on: windows-2022
    defaults:
      run:
        shell: msys2 {0}
        working-directory: win
    strategy:
      matrix:
        config:
          - ""
          - "CFLAGS=-DTCL_NO_DEPRECATED=1"
          - "--disable-shared"
          - "--disable-zipfs"
          - "--enable-symbols"
          - "--enable-symbols=mem"
          - "--enable-symbols=all"
    # Using powershell means we need to explicitly stop on failure
    steps:
      - 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 }}
        run: |
          ./configure ${CFGOPT} "--prefix=$HOME/install dir" || (cat config.log && exit 1)
        env:
          CFGOPT: --enable-64bit ${{ matrix.config }}
        timeout-minutes: 5
      - name: Build
        run: make -j4 all
        timeout-minutes: 5
      - name: Build Test Harness
        run: make -j4 tcltest
        timeout-minutes: 5
      - name: Info
        run: |
          ulimit -a || echo 'get limit failed'
          echo 'puts exe:\t[info nameofexecutable]\nver:\t[info patchlevel]\t[if {![catch tcl::build-info ret]} {set ret}]\nlib:\t[info library]\nplat:\t[lsort -dictionary -stride 2 [array get tcl_platform]]' | make runtest || echo 'get info failed'
      - name: Run Tests
        run: make test
        timeout-minutes: 30

# If you add builds with Wine, be sure to define the environment variable
# CI_USING_WINE when running them so that broken tests know not to run.

Changes to .gitignore.

22
23
24
25
26
27
28
29

30
31
32
33


34
35
36
37
38
39
40
22
23
24
25
26
27
28

29
30
31
32

33
34
35
36
37
38
39
40
41







-
+



-
+
+







config.status
config.status.lineno
html
manifest.uuid
_FOSSIL_
*/tclConfig.sh
*/tclsh*
*/tcltest*
*/tcltest
*/versions.vc
*/version.vc
*/libtcl.vfs
*/libtcl_*.zip
*/libtcl*.zip
*/tclUuid.h
libtommath/bn.ilg
libtommath/bn.ind
libtommath/pretty.build
libtommath/tommath.src
libtommath/*.log
libtommath/*.pdf
libtommath/*.pl
48
49
50
51
52
53
54

55
56

57
58
59
60

61
62
63
64
65
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69







+


+




+





libtommath/etc/*
libtommath/demo/*
libtommath/*.out
libtommath/*.tex
macosx/configure
unix/autoMkindex.tcl
unix/dltest.marker
unix/dltest/embtest
unix/tcl.pc
unix/tclIndex
unix/pkgs8/*
unix/pkgs/*
win/Debug*
win/Release*
win/*.manifest
win/pkgs8/*
win/pkgs/*
win/coffbase.txt
win/tcl.hpj
win/nmakehlp.out
win/nmhlp-out.txt

Deleted .travis.yml.

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
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
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






















































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
language: c
addons:
  apt:
    sources:
      - ubuntu-toolchain-r-test
    packages:
      - binutils-mingw-w64-i686
      - binutils-mingw-w64-x86-64
      - gcc-mingw-w64
      - gcc-mingw-w64-base
      - gcc-mingw-w64-i686
      - gcc-mingw-w64-x86-64
      - gcc-multilib
jobs:
  include:
# Testing on Linux GCC
    - name: "Linux/GCC/Shared"
      os: linux
      dist: focal
      compiler: gcc
      env:
        - BUILD_DIR=unix
    - name: "Linux/GCC/Shared: UTF_MAX=3"
      os: linux
      dist: focal
      compiler: gcc
      env:
        - BUILD_DIR=unix
        - CFGOPT="CFLAGS=-DTCL_UTF_MAX=3"
    - name: "Linux/GCC/Shared: NO_DEPRECATED"
      os: linux
      dist: focal
      compiler: gcc
      env:
        - BUILD_DIR=unix
        - CFGOPT="CFLAGS=-DTCL_NO_DEPRECATED=1"
    - name: "Linux/GCC/Static"
      os: linux
      dist: focal
      compiler: gcc
      env:
        - CFGOPT="--disable-shared"
        - BUILD_DIR=unix
    - name: "Linux/GCC/Debug"
      os: linux
      dist: focal
      compiler: gcc
      env:
        - BUILD_DIR=unix
        - CFGOPT="--enable-symbols"
    - name: "Linux/GCC/Mem-Debug"
      os: linux
      dist: focal
      compiler: gcc
      env:
        - BUILD_DIR=unix
        - CFGOPT="--enable-symbols=mem"
# C++ build.
    - name: "Linux/G++/Shared"
      os: linux
      dist: focal
      compiler: g++
      env:
        - BUILD_DIR=unix
        - CFGOPT="CC=g++ CFLAGS=-Dregister=dont+use+register"
# Newer/Older versions of GCC
    - name: "Linux/GCC 10/Shared"
      os: linux
      dist: focal
      compiler: gcc-10
      addons:
        apt:
          packages:
            - g++-10
      env:
        - BUILD_DIR=unix
    - name: "Linux/GCC 5/Shared"
      os: linux
      dist: bionic
      compiler: gcc-5
      addons:
        apt:
          packages:
            - g++-5
      env:
        - BUILD_DIR=unix
# Testing on Linux Clang
    - name: "Linux/Clang/Shared"
      os: linux
      dist: focal
      compiler: clang
      env:
        - BUILD_DIR=unix
    - name: "Linux/Clang/Static"
      os: linux
      dist: focal
      compiler: clang
      env:
        - CFGOPT="--disable-shared"
        - BUILD_DIR=unix
    - name: "Linux/Clang/Debug"
      os: linux
      dist: focal
      compiler: clang
      env:
        - BUILD_DIR=unix
        - CFGOPT="--enable-symbols"
    - name: "Linux/Clang/Mem-Debug"
      os: linux
      dist: focal
      compiler: clang
      env:
        - BUILD_DIR=unix
        - CFGOPT="--enable-symbols=mem"
# Testing on Mac, various styles
    - name: "macOS/Clang/Xcode 12/Shared"
      os: osx
      osx_image: xcode12.2
      env:
        - BUILD_DIR=macosx
      install: []
      script: &mactest
        - make all
        # The styles=develop avoids some weird problems on OSX
        - make test styles=develop
    - name: "macOS/Clang/Xcode 12/Shared/Unix-like"
      os: osx
      osx_image: xcode12.2
      env:
        - BUILD_DIR=unix
        - CFGOPT="--enable-dtrace"
    - name: "macOS/Clang/Xcode 12/Shared/libtommath"
      os: osx
      osx_image: xcode12.2
      env:
        - BUILD_DIR=macosx
      install: []
      script: *mactest
      addons:
        homebrew:
          packages:
            - libtommath
    - name: "macOS/Clang++/Xcode 12/Shared"
      os: osx
      osx_image: xcode12.2
      env:
        - BUILD_DIR=unix
        - CFGOPT="CC=clang++ --enable-framework --enable-dtrace CFLAGS=-Dregister=dont+use+register CPPFLAGS=-D__private_extern__=extern"
      script:
        - make all tcltest
# Newer MacOS versions
    - name: "macOS/Clang/Xcode 12/Universal Apps/Shared"
      os: osx
      osx_image: xcode12u
      env:
        - BUILD_DIR=macosx
      install: []
      script: *mactest
# Older MacOS versions
    - name: "macOS/Clang/Xcode 11/Shared"
      os: osx
      osx_image: xcode11.7
      env:
        - BUILD_DIR=macosx
      install: []
      script: *mactest
    - name: "macOS/Clang/Xcode 10/Shared"
      os: osx
      osx_image: xcode10.3
      env:
        - BUILD_DIR=macosx
      install: []
      script: *mactest
    - name: "macOS/Clang/Xcode 9/Shared"
      os: osx
      osx_image: xcode9.4
      env:
        - BUILD_DIR=macosx
      install: []
      script: *mactest
    - name: "macOS/Clang/Xcode 8/Shared"
      os: osx
      osx_image: xcode8.3
      env:
        - BUILD_DIR=macosx
      install: []
      script: *mactest
# Test with mingw-w64 cross-compile
# Doesn't run tests because wine is only an imperfect Windows emulation
    - name: "Linux-cross-Windows/GCC/Shared/no test"
      os: linux
      dist: focal
      compiler: x86_64-w64-mingw32-gcc
      env:
        - BUILD_DIR=win
        - CFGOPT="--host=x86_64-w64-mingw32 --enable-64bit"
      script: &crosstest
        - make all tcltest
        # Include a high visibility marker that tests are skipped outright
        - >
          echo "`tput setaf 3`SKIPPED TEST: CROSS COMPILING`tput sgr0`"
# Test with mingw-w64 (32 bit) cross-compile
# Doesn't run tests because wine is only an imperfect Windows emulation
    - name: "Linux-cross-Windows-32/GCC/Shared/no test"
      os: linux
      dist: focal
      compiler: i686-w64-mingw32-gcc
      env:
        - BUILD_DIR=win
        - CFGOPT=--host=i686-w64-mingw32
      script: *crosstest
# Test on Windows with MSVC native
    - name: "Windows/MSVC/Shared"
      os: windows
      compiler: cl
      env: &vcenv
        - BUILD_DIR=win
        - VCDIR="/C/Program Files (x86)/Microsoft Visual Studio/2017/BuildTools/VC/Auxiliary/Build"
      before_install: &vcpreinst
        - rm -rf tests/safe-stock8*.test
        - touch generic/tclStubInit.c generic/tclOOStubInit.c generic/tclOOScript.h
        - PATH="$PATH:$VCDIR"
        - cd ${BUILD_DIR}
      install: []
      script:
        - cmd.exe //C vcvarsall.bat x64 '&&' nmake '-f' makefile.vc all tcltest
        - cmd.exe //C vcvarsall.bat x64 '&&' nmake '-f' makefile.vc test
    - name: "Windows/MSVC/Shared: NO_DEPRECATED"
      os: windows
      compiler: cl
      env: *vcenv
      before_install: *vcpreinst
      install: []
      script:
        - cmd.exe //C vcvarsall.bat x64 '&&' nmake 'OPTS=nodep' '-f' makefile.vc all tcltest
        - cmd.exe //C vcvarsall.bat x64 '&&' nmake 'OPTS=nodep' '-f' makefile.vc test
    - name: "Windows/MSVC/Static"
      os: windows
      compiler: cl
      env: *vcenv
      before_install: *vcpreinst
      install: []
      script:
        - cmd.exe //C vcvarsall.bat x64 '&&' nmake 'OPTS=static,msvcrt' '-f' makefile.vc all tcltest
        - cmd.exe //C vcvarsall.bat x64 '&&' nmake 'OPTS=static,msvcrt' '-f' makefile.vc test
    - name: "Windows/MSVC/Debug"
      os: windows
      compiler: cl
      env: *vcenv
      before_install: *vcpreinst
      install: []
      script:
        - cmd.exe //C vcvarsall.bat x64 '&&' nmake 'OPTS=symbols' '-f' makefile.vc all tcltest
        - cmd.exe //C vcvarsall.bat x64 '&&' nmake 'OPTS=symbols' '-f' makefile.vc test
    - name: "Windows/MSVC/Mem-Debug"
      os: windows
      compiler: cl
      env: *vcenv
      before_install: *vcpreinst
      install: []
      script:
        - cmd.exe //C vcvarsall.bat x64 '&&' nmake 'STATS=memdbg' '-f' makefile.vc all tcltest
        - cmd.exe //C vcvarsall.bat x64 '&&' nmake 'STATS=memdbg' '-f' makefile.vc test
# Test on Windows with MSVC native (32-bit)
    - name: "Windows/MSVC-x86/Shared"
      os: windows
      compiler: cl
      env: *vcenv
      before_install: *vcpreinst
      install: []
      script:
        - cmd.exe //C vcvarsall.bat x86 '&&' nmake '-f' makefile.vc all tcltest
        - cmd.exe //C vcvarsall.bat x86 '&&' nmake '-f' makefile.vc test
    - name: "Windows/MSVC-x86/Shared: NO_DEPRECATED"
      os: windows
      compiler: cl
      env: *vcenv
      before_install: *vcpreinst
      install: []
      script:
        - cmd.exe //C vcvarsall.bat x86 '&&' nmake 'OPTS=nodep' '-f' makefile.vc all tcltest
        - cmd.exe //C vcvarsall.bat x86 '&&' nmake 'OPTS=nodep' '-f' makefile.vc test
    - name: "Windows/MSVC-x86/Static"
      os: windows
      compiler: cl
      env: *vcenv
      before_install: *vcpreinst
      install: []
      script:
        - cmd.exe //C vcvarsall.bat x86 '&&' nmake 'OPTS=static,msvcrt' '-f' makefile.vc all tcltest
        - cmd.exe //C vcvarsall.bat x86 '&&' nmake 'OPTS=static,msvcrt' '-f' makefile.vc test
    - name: "Windows/MSVC-x86/Debug"
      os: windows
      compiler: cl
      env: *vcenv
      before_install: *vcpreinst
      install: []
      script:
        - cmd.exe //C vcvarsall.bat x86 '&&' nmake 'OPTS=symbols' '-f' makefile.vc all tcltest
        - cmd.exe //C vcvarsall.bat x86 '&&' nmake 'OPTS=symbols' '-f' makefile.vc test
    - name: "Windows/MSVC-x86/Mem-Debug"
      os: windows
      compiler: cl
      env: *vcenv
      before_install: *vcpreinst
      install: []
      script:
        - cmd.exe //C vcvarsall.bat x86 '&&' nmake 'STATS=memdbg' '-f' makefile.vc all tcltest
        - cmd.exe //C vcvarsall.bat x86 '&&' nmake 'STATS=memdbg' '-f' makefile.vc test
# Test on Windows with GCC native
    - name: "Windows/GCC/Shared"
      os: windows
      compiler: gcc
      env:
        - BUILD_DIR=win
        - CFGOPT="--enable-64bit"
      before_install: &makepreinst
        - rm -rf tests/safe-stock8*.test
        - touch generic/tclStubInit.c generic/tclOOStubInit.c generic/tclOOScript.h
        - choco install -y make zip
        - cd ${BUILD_DIR}
    - name: "Windows/GCC/Shared: UTF_MAX=3"
      os: windows
      compiler: gcc
      env:
        - BUILD_DIR=win
        - CFGOPT="--enable-64bit CFLAGS=-DTCL_UTF_MAX=3"
      before_install: *makepreinst
    - name: "Windows/GCC/Shared: NO_DEPRECATED"
      os: windows
      compiler: gcc
      env:
        - BUILD_DIR=win
        - CFGOPT="--enable-64bit CFLAGS=-DTCL_NO_DEPRECATED=1"
      before_install: *makepreinst
    - name: "Windows/G++/Shared"
      os: windows
      compiler: g++
      env:
        - BUILD_DIR=win
        - CFGOPT="CC=g++ --enable-64bit"
      before_install: *makepreinst
      script:
        - make all tcltest
    - name: "Windows/GCC/Static"
      os: windows
      compiler: gcc
      env:
        - BUILD_DIR=win
        - CFGOPT="--enable-64bit --disable-shared"
      before_install: *makepreinst
    - name: "Windows/GCC/Debug"
      os: windows
      compiler: gcc
      env:
        - BUILD_DIR=win
        - CFGOPT="--enable-64bit --enable-symbols"
      before_install: *makepreinst
    - name: "Windows/GCC/Mem-Debug"
      os: windows
      compiler: gcc
      env:
        - BUILD_DIR=win
        - CFGOPT="--enable-64bit --enable-symbols=mem"
      before_install: *makepreinst
# Test on Windows with GCC native (32-bit)
    - name: "Windows/GCC-x86/Shared"
      os: windows
      compiler: gcc
      env:
        - BUILD_DIR=win
      before_install: *makepreinst
    - name: "Windows/GCC-x86/Shared: UTF_MAX=3"
      os: windows
      compiler: gcc
      env:
        - BUILD_DIR=win
        - CFGOPT="CFLAGS=-DTCL_UTF_MAX=3"
      before_install: *makepreinst
    - name: "Windows/GCC-x86/Shared: NO_DEPRECATED"
      os: windows
      compiler: gcc
      env:
        - BUILD_DIR=win
        - CFGOPT="CFLAGS=-DTCL_NO_DEPRECATED=1"
      before_install: *makepreinst
    - name: "Windows/G++-x86/Shared"
      os: windows
      compiler: g++
      env:
        - BUILD_DIR=win
        - CFGOPT="CC=g++"
      before_install: *makepreinst
      script:
        - make all tcltest
    - name: "Windows/GCC-x86/Static"
      os: windows
      compiler: gcc
      env:
        - BUILD_DIR=win
        - CFGOPT="--disable-shared"
      before_install: *makepreinst
    - name: "Windows/GCC-x86/Debug"
      os: windows
      compiler: gcc
      env:
        - BUILD_DIR=win
        - CFGOPT="--enable-symbols"
      before_install: *makepreinst
    - name: "Windows/GCC-x86/Mem-Debug"
      os: windows
      compiler: gcc
      env:
        - BUILD_DIR=win
        - CFGOPT="--enable-symbols=mem"
      before_install: *makepreinst
# "make dist" only
    - name: "Linux: make dist"
      os: linux
      dist: focal
      compiler: gcc
      env:
        - BUILD_DIR=unix
      script:
        - make dist
before_install:
  - rm -rf tests/safe-stock8*.test
  - touch generic/tclStubInit.c generic/tclOOStubInit.c generic/tclOOScript.h
  - cd ${BUILD_DIR}
install:
  - mkdir "$HOME/install dir"
  - ./configure ${CFGOPT} "--prefix=$HOME/install dir" || (cat config.log && exit 1)
before_script:
  - export ERROR_ON_FAILURES=1
script:
  - make all tcltest || echo "Something wrong, maybe a hickup, let's try again"
  - make test
  - make install

Deleted ChangeLog.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
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
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
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
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
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
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
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
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
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
7079
7080
7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091
7092
7093
7094
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468
7469
7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499
7500
7501
7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520
7521
7522
7523
7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537
7538
7539
7540
7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647
7648
7649
7650
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692
7693
7694
7695
7696
7697
7698
7699
7700
7701
7702
7703
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952
7953
7954
7955
7956
7957
7958
7959
7960
7961
7962
7963
7964
7965
7966
7967
7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999
8000
8001
8002
8003
8004
8005
8006
8007
8008
8009
8010
8011
8012
8013
8014
8015
8016
8017
8018
8019
8020
8021
8022
8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047
8048
8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
8077
8078
8079
8080
8081
8082
8083
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
8148
8149
8150
8151
8152
8153
8154
8155
8156
8157
8158
8159
8160
8161
8162
8163
8164
8165
8166
8167
8168
8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
8193
8194
8195
8196
8197
8198
8199
8200
8201
8202
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
8233
8234
8235
8236
8237
8238
8239
8240
8241
8242
8243
8244
8245
8246
8247
8248
8249
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260
8261
8262
8263
8264
8265
8266
8267
8268
8269
8270
8271
8272
8273
8274
8275
8276
8277
8278
8279
8280
8281
8282
8283
8284
8285
8286
8287
8288
8289
8290
8291
8292
8293
8294
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316
8317
8318
8319
8320
8321
8322
8323
8324
8325
8326
8327
8328
8329
8330
8331
8332
8333
8334
8335
8336
8337
8338
8339
8340
8341
8342
8343
8344
8345
8346
8347
8348
8349
8350
8351
8352
8353
8354
8355
8356
8357
8358
8359
8360
8361
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371
8372
8373
8374
8375
8376
8377
8378
8379
8380
8381
8382
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414
8415
8416
8417
8418
8419
8420
8421
8422
8423
8424
8425
8426
8427
8428
8429
8430
8431
8432
8433
8434
8435
8436
8437
8438
8439
8440
8441
8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452
8453
8454
8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487
8488
8489
8490
8491
8492
8493
8494
8495
8496
8497
8498
8499
8500
8501
8502
8503
8504
8505
8506
8507
8508
8509
8510
8511
8512
8513
8514
8515
8516
8517
8518
8519
8520
8521
8522
8523
8524
8525
8526
8527
8528
8529
8530
8531
8532
8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544
8545
8546
8547
8548
8549
8550
8551
8552
8553
8554
8555
8556
8557
8558
8559
8560
8561
8562
8563
8564
8565
8566
8567
8568
8569
8570
8571
8572
8573
8574
8575
8576
8577
8578
8579
8580
8581
8582
8583
8584
8585
8586
8587
8588
8589
8590
8591
8592
8593
8594
8595
8596
8597
8598
8599
8600
8601
8602
8603
8604
8605
8606
8607
8608
8609
8610
8611
8612
8613
8614
8615
8616
8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628
8629
8630
8631
8632
8633
8634
8635
8636
8637
8638
8639
8640
8641
8642
8643
8644
8645
8646
8647
8648
8649
8650
8651
8652
8653
8654
8655
8656
8657
8658
8659
8660
8661
8662
8663
8664
8665
8666
8667
8668
8669
8670
8671
8672
8673
8674
8675
8676
8677
8678
8679
8680
8681
8682
8683
8684
8685
8686
8687
8688
8689
8690
8691
8692
8693
8694
8695
8696
8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707
8708
8709
8710
8711
8712
8713
8714
8715
8716
8717
8718
8719
8720
8721
8722
8723
8724
8725
8726
8727
8728
8729
8730
8731
8732
8733
8734
8735
8736
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746
8747
8748
8749
8750
8751
8752
8753
8754
8755
8756
8757
8758
8759
8760
8761
8762
8763
8764
8765
8766
8767
8768
8769
8770
8771
8772
8773
8774
8775
8776
8777
8778
8779
8780
8781
8782
8783
8784
8785
8786
8787
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
8798
8799
8800
8801
8802
8803
8804
8805
8806
8807
8808
8809
8810
8811
8812
8813
8814
8815
8816
8817
8818
8819
8820
8821
8822
8823
8824
8825
8826
8827
8828
8829
8830
8831
8832
8833
8834
8835
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847
8848
8849
8850
8851
8852
8853
8854
8855
8856
























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
A NOTE ON THE CHANGELOG:
Starting in early 2011, Tcl source code has been under the management of
fossil, hosted at https://core.tcl-lang.org/tcl/ .  Fossil presents a "Timeline"
view of changes made that is superior in every way to a hand edited log file.
Because of this, many Tcl developers are now out of the habit of maintaining
this log file.  You may still find useful things in it, but the Timeline is
a better first place to look now.
============================================================================

2013-09-19  Don Porter  <dgp@users.sourceforge.net>

	*** 8.6.1 TAGGED FOR RELEASE ***

	* generic/tcl.h:	Bump version number to 8.6.1.
	* library/init.tcl:
	* unix/configure.in:
	* win/configure.in:
	* unix/tcl.spec:
	* README:

	* unix/configure:	autoconf-2.59
	* win/configure:

2013-09-19  Donal Fellows  <dkf@users.sf.net>

	* doc/next.n (METHOD SEARCH ORDER): Bug [3606943]: Corrected
	description of method search order.

2013-09-18  Donal Fellows  <dkf@users.sf.net>

	Bump TclOO version to 1.0.1 for release.

2013-09-17  Donal Fellows  <dkf@users.sf.net>

	* generic/tclBinary.c (BinaryEncodeUu, BinaryDecodeUu): [Bug 2152292]:
	Corrected implementation of the core of uuencode handling so that the
	line length processing is correctly applied.
	***POTENTIAL INCOMPATIBILITY***
	Existing code that was using the old versions and working around the
	limitations will now need to do far less. The -maxlen option now has
	strict limits on the range of supported lengths; this is a limitation
	of the format itself.

2013-09-09  Donal Fellows  <dkf@users.sf.net>

	* generic/tclOOMethod.c (CloneProcedureMethod): [Bug 3609693]: Strip
	the internal representation of method bodies during cloning in order
	to ensure that any bound references to instance variables are removed.

2013-09-01  Donal Fellows  <dkf@users.sf.net>

	* generic/tclBinary.c (BinaryDecodeHex): [Bug b98fa55285]: Ensure that
	whitespace at the end of a string don't cause the decoder to drop the
	last decoded byte.

2013-08-03  Donal Fellows  <dkf@users.sf.net>

	* library/auto.tcl: [Patch 3611643]: Allow TclOO classes to be found
	by the autoloading mechanism.

2013-08-02  Donal Fellows  <dkf@users.sf.net>

	* generic/tclOODefineCmds.c (ClassSuperSet): Bug [9d61624b3d]: Stop
	crashes when emptying the superclass slot, even when doing elaborate
	things with metaclasses.

2013-08-01  Harald Oehlmann  <oehhar@users.sf.net>

	* tclUnixNotify.c (Tcl_InitNotifier): Bug [a0bc856dcd]: Start notifier
	thread again if we were forked, to solve Rivet bug 55153.

2013-07-05  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata/Africa/Casablanca:
	* library/tzdata/America/Asuncion:
	* library/tzdata/Antarctica/Macquarie:
	* library/tzdata/Asia/Gaza:
	* library/tzdata/Asia/Hebron:
	* library/tzdata/Asia/Jerusalem:
	http://www.iana.org/time-zones/repository/releases/tzdata2013d.tar.gz

2013-07-03  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tclXtNotify.c: Bug [817249]: bring tclXtNotify.c up to date with
	Tcl_SetNotifier() change.

2013-07-02  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tcl.m4:  Bug [32afa6e256]: dirent64 check is incorrect in tcl.m4
	* unix/configure: (thanks to Brian Griffin)

2013-06-27  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclConfig.c: Bug [9b2e636361]: Tcl_CreateInterp() needs
	* generic/tclMain.c:   initialized encodings.

2013-06-18  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclEvent.c: Bug [3611974]: InitSubsystems multiple thread
	issue.

2013-06-17  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/regc_locale.c: Bug [a876646efe]: re_expr character class
	[:cntrl:] should contain \u0000 - \u001f

2013-06-09  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmdsSZ.c (TclCompileTryCmd): [Bug 779d38b996]:
	Rewrote the [try] compiler to generate better code in some cases and
	to behave correctly in others; when an error happens during the
	processing of an exception-trap clause or a finally clause, the
	*original* return options are now captured in a -during option, even
	when fully compiled.

2013-06-05  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclExecute.c (INST_EXPAND_DROP): [Bugs 2835313, 3614226]:
	New opcode to allow resetting the stack to get rid of an expansion,
	restoring the stack to a known state in the process.
	* generic/tclCompile.c, generic/tclCompCmds.c: Adjusted the compilers
	for [break] and [continue] to get stack cleanup right in the majority
	of cases.
	* tests/for.test (for-7.*): Set of tests for these evil cases.

2013-06-04  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tcl.m4: Eliminate NO_VIZ macro as current zlib uses HAVE_HIDDEN
	instead. One more last-moment fix for FreeBSD by Pietro Cerutti

2013-06-03  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: fix for perf bug detected by Kieran
	(https://groups.google.com/forum/?fromgroups#!topic/comp.lang.tcl/vfpI3bc-DkQ),
	diagnosed by dgp to be a close relative of [Bug 781585], which was
	fixed by commit	[f46fb50cb3]. This bug was introduced by myself in
	commit [cbfe055d8c].

2013-06-03  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileBreakCmd, TclCompileContinueCmd):
	Added code to allow [break] and [continue] to be issued as a jump (in
	the most common cases) rather than using the more expensive exception
	processing path in the bytecode engine. [Bug 3614226]: Partial fix for
	the issues relating to cleaning up the stack when dealing with [break]
	and [continue].

2013-05-27 Harald Oehlmann  <oehhar@users.sf.net>

	* library/msgcat/msgcat.tcl: [Bug 3036566]: Also get locale from
	registry key HCU\Control Panel\Desktop : PreferredUILanguages to honor
	installed language packs on Vista+.
	Bumped msgcat version to 1.5.2

2013-05-22  Andreas Kupries  <andreask@activestate.com>

	* tclCompile.c: Removed duplicate const qualifier causing the HP
	native cc to error out.

2013-05-22  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclUtf.c (TclUtfCasecmp): [Bug 3613609]: Replace problematic
	uses of strcasecmp with a proper UTF-8-aware version. Affects both
	[lsearch -nocase] and [lsort -nocase].

2013-05-22  Donal K. Fellows  <dkf@users.sf.net>

	* doc/file.n: [Bug 3613671]: Added note to portability section on the
	fact that [file owned] does not produce useful results on Windows.

2013-05-20  Donal K. Fellows  <dkf@users.sf.net>

	* unix/tclUnixFCmd.c (DefaultTempDir): [Bug 3613567]: Corrected logic
	for checking return code of access() system call, which was inverted.

2013-05-19  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tcl.m4:     Fix for FreeBSD, and remove support for older
	* unix/configure:  FreeBSD versions. Patch by Pietro Cerutti.

2013-05-18  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmdsGR.c: Split tclCompCmds.c again to keep size of
	code down.

2013-05-16  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclBasic.c: Add panic in order to detect incompatible
	mingw32 sys/stat.h and sys/time.h headers.

2013-05-13  Jan Nijtmans  <nijtmans@users.sf.net>

	* compat/zlib/*: Upgrade to zlib 1.2.8

2013-05-10  Donal K. Fellows  <dkf@users.sf.net>

	Optimizations and general bytecode generation improvements.
	* generic/tclCompCmds.c (TclCompileAppendCmd, TclCompileLappendCmd):
	(TclCompileReturnCmd): Make these generate bytecode in more cases.
	(TclCompileListCmd): Make this able to push a literal when it can.
	* generic/tclCompile.c (TclSetByteCodeFromAny, PeepholeOptimize):
	Added checks to see if we can apply some simple cross-command-boundary
	optimizations, and defined a small number of such optimizations.
	(TclCompileScript): Added the special ability to compile the list
	command with expansion ([list {*}blah]) into bytecode that does not
	call an external command.

2013-05-06  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclStubInit.c: Add support for Cygwin64, which has a 64-bit
	* generic/tclDecls.h: "long" type. Binary compatibility with win64
	requires that all stub entries use 32-bit long's, therefore the need
	for various wrapper functions/macros. For Tcl 9 a better solution is
	needed, but that cannot be done without introducing binary
	incompatibility.

2013-04-30  Andreas Kupries  <andreask@activestate.com>

	* library/platform/platform.tcl (::platform::LibcVersion):
	* library/platform/pkgIndex.tcl: Followup to the 2013-01-30 change.
	The RE become too restrictive again. SuSe added a timestamp after the
	version. Loosened up a bit. Bumped package to version 1.0.12.

2013-04-29  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileArraySetCmd): Generate better code
	when the list of things to set is a literal.

2013-04-25  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclDecls.h: Implement Tcl_NewBooleanObj, Tcl_DbNewBooleanObj
	and Tcl_SetBooleanObj as macros using Tcl_NewIntObj, Tcl_DbNewLongObj
	and Tcl_SetIntObj. Starting with Tcl 8.5, this is exactly the same, it
	only eliminates code duplication.
	* generic/tclInt.h: Eliminate use of NO_WIDE_TYPE everywhere: It's
	exactly the same as TCL_WIDE_INT_IS_LONG

2013-04-19  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclDecls.h: Implement many Tcl_*Var* functions and
	Tcl_GetIndexFromObj as (faster/stack-saving) macros around resp their
	Tcl_*Var*2 equivalent and Tcl_GetIndexFromObjStruct.

2013-04-12  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclDecls.h: Implement Tcl_Pkg* functions as
	(faster/stack-saving) macros around Tcl_Pkg*Ex functions.

2013-04-08  Don Porter  <dgp@users.sourceforge.net>

	* generic/regc_color.c:	[Bug 3610026]: Stop crash when the number of
	* generic/regerrs.h:	"colors" in a regular expression overflows a
	* generic/regex.h:	short int.  Thanks to Heikki Linnakangas for
	* generic/regguts.h:	the report and the patch.
	* tests/regexp.test:

2013-04-04  Reinhard Max  <max@suse.de>

	* library/http/http.tcl (http::geturl): Allow URLs that don't have a
	path, but a query query, e.g. http://example.com?foo=bar
	* Bump the http package to 2.8.7.

2013-03-22  Venkat Iyer <venkat@comit.com>
	* library/tzdata/Africa/Cairo: Update to tzdata2013b.
	* library/tzdata/Africa/Casablanca:
	* library/tzdata/Africa/Gaborone:
	* library/tzdata/Africa/Tripoli:
	* library/tzdata/America/Asuncion:
	* library/tzdata/America/Barbados:
	* library/tzdata/America/Bogota:
	* library/tzdata/America/Costa_Rica:
	* library/tzdata/America/Curacao:
	* library/tzdata/America/Nassau:
	* library/tzdata/America/Port-au-Prince:
	* library/tzdata/America/Santiago:
	* library/tzdata/Antarctica/Palmer:
	* library/tzdata/Asia/Aden:
	* library/tzdata/Asia/Hong_Kong:
	* library/tzdata/Asia/Muscat:
	* library/tzdata/Asia/Rangoon:
	* library/tzdata/Asia/Shanghai:
	* library/tzdata/Atlantic/Bermuda:
	* library/tzdata/Europe/Vienna:
	* library/tzdata/Pacific/Easter:
	* library/tzdata/Pacific/Fiji:
	* library/tzdata/Asia/Khandyga: (new)
	* library/tzdata/Asia/Ust-Nera: (new)
	* library/tzdata/Europe/Busingen: (new)

2013-03-21  Don Porter  <dgp@users.sourceforge.net>

	* library/auto.tcl: [Bug 2102614]: Add ensemble indexing support to
	* tests/autoMkindex.test: [auto_mkindex].  Thanks Brian Griffin.

2013-03-19  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclFCmd.c: [Bug 3597000]: Consistent [file copy] result.
	* tests/fileSystem.test:

2013-03-19  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinFile.c: [Bug 3608360]: Incompatible behaviour of "file
	exists".

2013-03-18  Donal K. Fellows  <dkf@users.sf.net>

	* tests/cmdAH.test (cmdAH-19.12): [Bug 3608360]: Added test to ensure
	that we never ever allow [file exists] to do globbing.

2013-03-12  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tcl.m4: Patch by Andrew Shadura, providing better support for
	three architectures they have in Debian.

2013-03-11  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompile.c:	[Bugs 3607246,3607372]: Unbalanced refcounts
	* generic/tclLiteral.c:	of literals in the global literal table.

2013-03-06  Don Porter  <dgp@users.sourceforge.net>

	* generic/regc_nfa.c:	[Bugs 3604074,3606683]: Rewrite of the
	* generic/regcomp.c:	fixempties() routine (and supporting routines)
	to completely eliminate the infinite loop hazard. Thanks to Tom Lane
	for the much improved solution.

2013-02-28  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclLiteral.c:	Revise TclReleaseLiteral() to tolerate a NULL
	interp argument.

	* generic/tclCompile.c:	Update callers and revise mistaken comments.
	* generic/tclProc.c:

2013-02-27  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/regcomp.c:	[Bug 3606139]: missing error check allows
	* tests/regexp.test:    regexp to crash Tcl. Thanks to Tom Lane for
	providing the test-case and the patch.

2013-02-26  Donal K. Fellows  <dkf@users.sf.net>

	* tests/chanio.test (chan-io-28.7): [Bug 3605120]: Stop test from
	hanging when run standalone.

2013-02-26  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclObj.c: Don't panic if Tcl_ConvertToType is called for a
	type that doesn't have a setFromAnyProc, create a proper error message.

2013-02-25  Donal K. Fellows  <dkf@users.sf.net>

	* tests/binary.test (binary-41.*): [Bug 3605721]: Test independence
	fixes. Thanks to Rolf Ade for pointing out the problem.

2013-02-25  Don Porter  <dgp@users.sourceforge.net>

	* tests/assocd.test:	[Bugs 3605719,3605720]: Test independence.
	* tests/basic.test:	Thanks Rolf Ade for patches.

2013-02-23  Jan Nijtmans  <nijtmans@users.sf.net>

	* compat/fake-rfc2553.c: [Bug 3599194]: compat/fake-rfc2553.c is
	broken.

2013-02-22  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclAssembly.c:	Shift more burden of smart cleanup
	* generic/tclCompile.c:		onto the TclFreeCompileEnv() routine.
	Stop crashes when the hookProc raises an error.

2013-02-20  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclNamesp.c:	[Bug 3605447]: Make sure the -clear option
	* tests/namespace.test:	to [namespace export] always clears, whether
	or not new export patterns are specified.

2013-02-20  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinDde.c: [Bug 3605401]: Compiler error with latest mingw-w64
	headers.

2013-02-19  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclTrace.c:  [Bug 2438181]: Incorrect error reporting in
	* tests/trace.test:    traces. Test-case and fix provided by Poor
	Yorick.

2013-02-15  Don Porter  <dgp@users.sourceforge.net>

	* generic/regc_nfa.c:	[Bug 3604074]: Fix regexp optimization to
	* tests/regexp.test:	stop hanging on the expression
	((((((((a)*)*)*)*)*)*)*)* .  Thanks to Bjørn Grathwohl for discovery.

2013-02-14  Harald Oehlmann  <oehhar@users.sf.net>

	* library/msgcat/msgcat.tcl: [Bug 3604576]: Catch missing registry
	entry "HCU\Control Panel\International".
	Bumped msgcat version to 1.5.1

2013-02-11  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclZlib.c (ZlibTransformOutput): [Bug 3603553]: Ensure that
	data gets written to the underlying stream by compressing transforms
	when the amount of data to be written is one buffer's-worth; problem
	was particularly likely to occur when compressing large quantities of
	not-very-compressible data. Many thanks to Piera Poggio (vampiera) for
	reporting.

2013-02-09  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOBasic.c (TclOO_Object_VarName): [Bug 3603695]: Change
	the way that the 'varname' method is implemented so that there are no
	longer problems with interactions due to the resolver. Thanks to
	Taylor Venable <tcvena@gmail.com> for identifying the problem.

2013-02-08  Donal K. Fellows  <dkf@users.sf.net>

	* generic/regc_nfa.c (duptraverse): [Bug 3603557]: Increase the
	maximum depth of recursion used when duplicating an automaton in
	response to encountering a "wild" RE that hit the previous limit.
	Allow the limit (DUPTRAVERSE_MAX_DEPTH) to be set by defining its
	value in the Makefile. Problem reported by Jonathan Mills.

2013-02-05  Don Porter  <dgp@users.sourceforge.net>

	* win/tclWinFile.c:	[Bug 3603434]: Make sure TclpObjNormalizePath()
	properly declares "a:/" to be normalized, even when no "A:" drive is
	present on the system.

2013-02-05  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclLoadNone.c (TclpLoadMemory): [Bug 3433012]: Added dummy
	version of this function to use in the event that a platform thinks it
	can load from memory but cannot actually do so due to it being
	disabled at configuration time.

2013-02-04  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileArraySetCmd): [Bug 3603163]: Stop
	crash in weird case where [eval] is used to make [array set] get
	confused about whether there is a local variable table or not. Thanks
	to Poor Yorick for identifying a reproducible crashing case.

2013-01-30  Andreas Kupries  <andreask@activestate.com>

	* library/platform/platform.tcl (::platform::LibcVersion): See
	* library/platform/pkgIndex.tcl: [Bug 3599098]: Fixed the RE
	* unix/Makefile.in: extracting the version to avoid issues with
	* win/Makefile.in: recent changes to the glibc banner. Now targeting a
	less variable part of the string. Bumped package to version 1.0.11.

2013-01-28  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileArraySetCmd)
	(TclCompileArrayUnsetCmd, TclCompileDictAppendCmd)
	(TclCompileDictCreateCmd, CompileDictEachCmd, TclCompileDictIncrCmd)
	(TclCompileDictLappendCmd, TclCompileDictMergeCmd)
	(TclCompileDictUnsetCmd, TclCompileDictUpdateCmd)
	(TclCompileDictWithCmd, TclCompileInfoCommandsCmd):
	* generic/tclCompCmdsSZ.c (TclCompileStringMatchCmd)
	(TclCompileStringMapCmd): Improve the code generation in cases where
	full compilation is impossible but a full ensemble invoke is provably
	not necessary.

2013-01-26  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tclUnixCompat.c: [Bug 3601804]: platformCPUID segmentation
	fault on Darwin.

2013-01-23  Donal K. Fellows  <dkf@users.sf.net>

	* library/http/http.tcl (http::geturl): [Bug 2911139]: Do not do vwait
	for connect to avoid reentrancy problems (except when operating
	without a -command option). Internally, this means that all sockets
	created by the http package will always be operated in asynchronous
	mode.

2013-01-21  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.decls: Put back Tcl[GS]etStartupScript(Path|FileName)
	in private stub table, so extensions using this (like Tk 8.4) will
	continue to work in all Tcl 8.x versions. Extensions using this
	still cannot be compiled against Tcl 8.6 headers.

2013-01-18  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclPort.h: [Bug 3598300]: unix: tcl.h does not include
	sys/stat.h

2013-01-17  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (PushVarName): [Bug 3600328]: Added mechanism
	for suppressing compilation of variables when we couldn't cope with
	the results. Useful for some [array] subcommands.
	* generic/tclEnsemble.c (CompileToCompiledCommand): Must restore the
	compilation environment when a command compiler fails.

2013-01-16  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclZlib.c (TclZlibInit): [Bug 3601086]: Register the config
	info in the iso8859-1 encoding as that is guaranteed to be present.

2013-01-16  Jan Nijtmans  <nijtmans@users.sf.net>

	* Makefile.in:   Allow win32 build with -DTCL_NO_DEPRECATED, just as
	* generic/tcl.h: in the UNIX build. Define Tcl_EvalObj and
	* generic/tclDecls.h: Tcl_GlobalEvalObj as macros, even when
	* generic/tclBasic.c: TCL_NO_DEPRECATED is defined, so Tk can benefit
	from it too.

2013-01-14  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tcl.m4: More flexible search for win32 tclConfig.sh, backported
	from TEA (not actually used in Tcl, only for Tk)

2013-01-14  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.decls: Put back Tcl_[GS]etStartupScript in internal
	stub table, so extensions using this, compiled against 8.5 headers
	still run in Tcl 8.6.

2013-01-13  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* doc/fileevent.n: [Bug 3436609]: Clarify readable fileevent "false
	positives" in the case of multibyte encodings/transforms.

2013-01-13  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclIntDecls.h: If TCL_NO_DEPRECATED is defined, make sure
	that TIP #139 functions all are taken from the public stub table, even
	if the inclusion is through tclInt.h.

2013-01-12  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.decls: Put back TclBackgroundException in internal
	stub table, so extensions using this, compiled against 8.5 headers
	still run in Tcl 8.6.

2013-01-09  Jan Nijtmans  <nijtmans@users.sf.net>

	* library/http/http.tcl: [Bug 3599395]: http assumes status line is a
	proper Tcl list.

2013-01-08  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinFile.c: [Bug 3092089]: [file normalize] can remove path
	components.	[Bug 3587096]: win vista/7: "can't find init.tcl" when
	called via junction without folder list access.

2013-01-07  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclOOStubLib.c: Restrict the stub library to only use
	* generic/tclTomMathStubLib.c: Tcl_PkgRequireEx, Tcl_ResetResult and
	Tcl_AppendResult, not any other function. This puts least restrictions
	on eventual Tcl 9 stubs re-organization, and it works on the widest
	range of Tcl versions.

2013-01-06  Jan Nijtmans  <nijtmans@users.sf.net>

	* library/http/http.tcl: Don't depend on Spencer-specific regexp
	* tests/env.test: syntax (/u and /U) any more in unrelated places.
	* tests/exec.test:
	Bump http package to 2.8.6.

2013-01-04  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclEnsemble.c (CompileBasicNArgCommand): Added very simple
	compiler (which just compiles to a normal invoke of the implementation
	command) for many ensemble subcommands where we can prove that there
	is no way for scripts to detect the difference even through error
	handling or [info level]/[info frame]. This improves the code produced
	from some ensembles (e.g., [info], [string]) to the point where the
	ensemble is now not normally seen at the bytecode level at all.

2013-01-04  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclInt.h:      Insure that PURIFY builds cannot exploit the
	* generic/tclExecute.c:  Tcl stack to hide mem defects.

2013-01-03  Donal K. Fellows  <dkf@users.sf.net>

	* doc/fconfigure.n, doc/CrtChannel.3: Updated to reflect the fact that
	the minimum buffer size is one byte, not ten. Identified by Schelte
	Bron on the Tcler's Chat.

	* generic/tclExecute.c (TEBCresume:INST_INVOKE_REPLACE):
	* generic/tclEnsemble.c (TclCompileEnsemble): Added new mechanism to
	allow for more efficient dispatch of non-bytecode-compiled subcommands
	of bytecode-compiled ensembles. This can provide substantial speed
	benefits in some cases.

2013-01-02  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclEnsemble.c:  Remove stray calls to Tcl_Alloc and friends:
	* generic/tclExecute.c:   the core should only use ckalloc to allow
	* generic/tclIORTrans.c:  MEM_DEBUG to work properly.
	* generic/tclTomMathInterface.c:

2012-12-31  Donal K. Fellows  <dkf@users.sf.net>

	* doc/string.n: Noted the obsolescence of the 'bytelength',
	'wordstart' and 'wordend' subcommands, and moved them to later in the
	file.

2012-12-27  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclListObj.c: [Bug 3598580]: Tcl_ListObjReplace may release
	deleted elements too early.

2012-12-22  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclUtil.c: [Bug 3598150]: Stop leaking allocated space when
	objifying a zero-length DString. Spotted by afredd.

2012-12-21  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/dltest/pkgb.c:  Inline compat Tcl_GetDefaultEncodingDir.
	* generic/tclStubLib.c: Eliminate unnecessary static HasStubSupport()
	and isDigit() functions, just do the same inline.

2012-12-18  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmdsSZ.c (TclSubstCompile): Improved the sequence of
	instructions issued for [subst] when dealing with simple variable
	references.

2012-12-14  Don Porter  <dgp@users.sourceforge.net>

	*** 8.6.0 TAGGED FOR RELEASE ***

	* changes: updates for 8.6.0

2012-12-13  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclZlib.c:	Repair same issue with misusing the
	* tests/zlib.test:	'fire and forget' nature of Tcl_ObjSetVar2
	in the new TIP 400 implementation.

2012-12-13  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCmdAH.c:	(CatchObjCmdCallback): do not decrRefCount
	* tests/cmdAH.test:	the newValuePtr sent to Tcl_ObjSetVar2:
	TOSV2 is 'fire and forget', it decrs on its own.
	Fix for [Bug 3595576], found by andrewsh.

2012-12-13  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.h: Fix Tcl_DecrRefCount macro such that it doesn't
	access its objPtr parameter twice any more.

2012-12-11  Don Porter  <dgp@users.sourceforge.net>

	* generic/tcl.h:	Bump version number to 8.6.0.
	* library/init.tcl:
	* unix/configure.in:
	* win/configure.in:
	* unix/tcl.spec:
	* README:

	* unix/configure:	autoconf-2.59
	* win/configure:

2012-12-10  Donal K. Fellows  <dkf@users.sf.net>

	* tools/tcltk-man2html.tcl (plus-pkgs): Increased robustness of
	version number detection code to deal with packages whose names are
	prefixes of other packages.
	* unix/Makefile.in (dist): Added pkgs/package.list.txt to distribution
	builds to ensure that 'make html' will work better.

2012-12-09  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* tests/chan.test: Clean up unwanted eofchar side-effect of chan-4.6
	leading to a spurious "'" at end of chan.test under certain conditions
	(see [Bug 3389289] and [Bug 3389251]).

	* doc/expr.n: [Bug 3594188]: Clarifications about commas.

2012-12-08  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclIO.c: Fix busyloop at exit under TCL_FINALIZE_ON_EXIT
	when there are unflushed nonblocking channels.  Thanks Miguel for
	spotting.

2012-12-07  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/dltest/pkgb.c:  Turn pkgb.so into a Tcl9 interoperability test
        library: Whatever Tcl9 looks like, loading pkgb.so in Tcl 9 should
        either result in an error-message, either succeed, but never crash.

2012-11-28  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclZlib.c (ZlibStreamSubcmd): [Bug 3590483]: Use a mechanism
	for complex option resolution that has fewer problems with more
	finicky compilers.

2012-11-26  Reinhard Max  <max@suse.de>

	* unix/tclUnixSock.c: Factor out creation of the -sockname and
	-peername lists from TcpGetOptionProc() to TcpHostPortList().  Make it
	robust against implementations of getnameinfo() that error out if
	reverse mapping fails instead of falling back to the numeric
	representation.

2012-11-20  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclBinary.c (BinaryDecode64): [Bug 3033307]: Corrected
	handling of trailing whitespace when decoding base64. Thanks to Anton
	Kovalenko for reporting, and Andy Goth for the fix and tests.

2012-11-19  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclExecute.c (INST_STR_RANGE_IMM): [Bug 3588366]: Corrected
	implementation of bounds restriction for end-indexed compiled [string
	range]. Thanks to Emiliano Gavilan for diagnosis and fix.

2012-11-15  Jan Nijtmans  <nijtmans@users.sf.net>

	IMPLEMENTATION OF TIP#416

	New Options for 'load': -global and -lazy

	* generic/tcl.h:
	* generic/tclLoad.c
	* unix/tclLoadDl.c
	* unix/tclLoadDyld.c
	* tests/load.test
	* doc/Load.3
	* doc/load.n

2012-11-14  Donal K. Fellows  <dkf@users.sf.net>

	* unix/tclUnixFCmd.c (TclUnixOpenTemporaryFile): [Bug 2933003]: Factor
	out all the code to do temporary file creation so that it is possible
	to make it correct in one place. Allow overriding of the back-stop
	default temporary file location at compile time by setting the
	TCL_TEMPORARY_FILE_DIRECTORY #def to a string containing the directory
	name (defaults to "/tmp" as that is the most common default).

2012-11-13  Joe Mistachkin  <joe@mistachkin.com>

	* win/tclWinInit.c: also search for the library directory (init.tcl,
	encodings, etc) relative to the build directory associated with the
	source checkout.

2012-11-10  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:   re-enable bcc-tailcall, after fixing an
	* generic/tclExecute.c: infinite loop in the TCL_COMPILE_DEBUG mode


2012-11-07  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata/Africa/Casablanca:
	* library/tzdata/America/Araguaina:
	* library/tzdata/America/Bahia:
	* library/tzdata/America/Havana:
	* library/tzdata/Asia/Amman:
	* library/tzdata/Asia/Gaza:
	* library/tzdata/Asia/Hebron:
	* library/tzdata/Asia/Jerusalem:
	* library/tzdata/Pacific/Apia:
	* library/tzdata/Pacific/Fakaofo:
	* library/tzdata/Pacific/Fiji:		Import tzdata2012i.

2012-11-06  Donal K. Fellows  <dkf@users.sf.net>

	* library/http/http.tcl (http::Finish): [Bug 3581754]: Ensure that
	callbacks are done at most once to prevent problems with timeouts on a
	keep-alive connection (combined with reentrant http package use)
	causing excessive stack growth. Not a fix for the underlying problem,
	but ensures that pain will be mostly kept away from users.
	Bump http package to 2.8.5.

2012-11-05  Donal K. Fellows  <dkf@users.sf.net>

	Added bytecode compilation of many Tcl commands. Some of these are
	total compilations and some are only partial (i.e., only compile in
	some cases). The (sub-)commands affected are:
	* array: exists, set, unset
	* dict: create, exists, merge
	* format: (simple cases only)
	* info: commands, coroutine, level, object
	* info object: class, isa object, namespace
	* namespace: current, code, qualifiers, tail, which
	* regsub: (only cases convertable to simple [string map])
	* self: (only no-argument and [self object] cases)
	* string: first, last, map, range
	* tailcall:
	* yield:

	[This was work originally done on the 'dkf-compile-misc-info' branch.]

2012-11-05  Jan Nijtmans  <nijtmans@users.sf.net>

	IMPLEMENTATION OF TIP#413

	Align the [string trim] and [string is space] commands, such that
	[string trim] by default trims all characters for which [string is
	space] returns 1, augmented with the NUL character.

	* generic/tclUtf.c: Add NEL, BOM and two more characters to [string is
	space]
	* generic/tclCmdMZ.c: Modify [string trim] for Unicode modifications.
	* generic/regc_locale.c: Regexp engine must match [string is space]
	* doc/string.n
	* tests/string.test
	***POTENTIAL INCOMPATIBILITY***
	Code that relied on characters not previously trimmed being not
	removed will notice a difference; it is believed that this is rare,
	but a workaround to get the behavior in Tcl 8.5 is to use " \t\n\r" as
	an explicit trim set.

2012-10-31  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/Makefile.in:   Dde version number to 1.4.0, ready for Tcl 8.6.0rc1
	* win/makefile.vc
	* win/tclWinDde.c
	* library/dde/pkgIndex.tcl
	* tests/winDde.test

2012-10-24  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileDictUnsetCmd): Added compilation of
	the [dict unset] command (for scalar var in LVT only).

2012-10-23  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.h:       Add "flags" parameter from Tcl_LoadFile to
	* generic/tclIOUtil.c:    to various internal functions, so these
	* generic/tclLoadNone.c:  flags are available through the whole
	* unix/tclLoad*.c:        filesystem for (future) internal use.
	* win/tclWinLoad.c:

2012-10-17  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c (TclNRCoroutineObjCmd): insure that numlevels
	are properly set, fix bug discovered by dkf and reported at
	http://code.activestate.com/lists/tcl-core/12213/

2012-10-16  Donal K. Fellows  <dkf@users.sf.net>

	IMPLEMENTATION OF TIP#405

	New commands for applying a transformation to the elements of a list
	to produce another list (the [lmap] command) and to the mappings of a
	dictionary to produce another dictionary (the [dict map] command). In
	both cases, a [continue] will cause the skipping of an element/pair,
	and a [break] will terminate the construction early and successfully.

	* generic/tclCmdAH.c (Tcl_LmapObjCmd, TclNRLmapCmd): Implementation of
	the new [lmap] command, based on (and sharing much of) [foreach].
	* generic/tclDictObj.c (DictMapNRCmd): Implementation of the new [dict
	map] subcommand, based on (and sharing much of) [dict for].
	* generic/tclCompCmds.c (TclCompileLmapCmd, TclCompileDictMapCmd):
	Compilation engines for [lmap] and [dict map].

	IMPLEMENTATION OF TIP#400

	* generic/tclZlib.c: Allow the specification of a compression
	dictionary (a binary blob used to seed the compression engine) in both
	streams and channel transformations. Also some reorganization to allow
	for getting gzip header dictionaries and controlling buffering levels
	in channel transformations (allowing a trade-off between formal
	correctness and speed).
	(Tcl_ZlibStreamSetCompressionDictionary): New C API to allow setting
	the compression dictionary without using a Tcl script.

2012-10-14  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclDictObj.c: [Bug 3576509]: ::tcl::Bgerror crashes with
	* generic/tclEvent.c:    invalid arguments. Better fix, which helps
	for all Tcl_DictObjGet() calls in Tcl's source code.

2012-10-13  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclEvent.c: [Bug 3576509]: tcl::Bgerror crashes with invalid
	arguments

2012-10-06  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/Makefile.in: [Bug 2459774]: tcl/win/Makefile.in not compatible
	with msys 0.8.

2012-10-03  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclIO.c:	When checking for std channels being closed,
	compare the channel state, not the channel itself so that stacked
	channels do not cause trouble.

2012-09-26  Reinhard Max  <max@suse.de>

	* generic/tclIOSock.c (TclCreateSocketAddress): Work around a bug in
	getaddrinfo() on OSX that caused name resolution to fail for [socket
	-server foo -myaddr localhost 0].

2012-09-20  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/configure.in: New import libraries for zlib 1.2.7, usable for
	* win/configure:    all win32/win64 compilers
	* compat/zlib/win32/zdll.lib:
	* compat/zlib/win64/zdll.lib:

	* win/tclWinDde.c: [FRQ 3527238]: Full unicode support for dde. Dde
	version is now 1.4.0b2.
	***POTENTIAL INCOMPATIBILITY***

2012-09-19  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.h:  Make Tcl_Interp a fully opaque structure if
	TCL_NO_DEPRECATED is set (TIP 330 and 336).
	* win/nmakehlp.c: Let "nmakehlp -V" start searching digits after the
	found match (suggested by Harald Oehlmann).

2012-09-19  Harald Oehlmann  <oehhar@users.sf.net>

	IMPLEMENTATION OF TIP#412.

	* library/msgcat/msgcat.tcl:	dynamic locale change with mc file
	* library/clock.tcl:            load on locale change.
	clock uses new msgcat features.

2012-09-07  Harald Oehlmann  <oehhar@users.sf.net>

	*** 8.6b3 TAGGED FOR RELEASE ***

	IMPLEMENTATION OF TIP#404.

	* library/msgcat/msgcat.tcl:	[FRQ 3544988]: New commands [mcflset]
	* library/msgcat/pkgIndex.tcl:	and [mcflmset] to set mc entries with
	* unix/Makefile.in:		implicit message file locale.
	* win/Makefile.in:		Bump to 1.5.0.

2012-08-25  Donal K. Fellows  <dkf@users.sf.net>

	* library/msgs/uk.msg: [Bug 3561330]: Use the correct full name of
	March in Ukrainian. Thanks to Mikhail Teterin for reporting.

2012-08-23  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclBinary.c: [Bug 3496014]: Unecessary memset() in
	Tcl_SetByteArrayObj().

2012-08-20  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclPathObj.c:	[Bug 3559678]: Fix bad filename normalization
	when the last component is the empty string.

2012-08-20  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinPort.h:  Remove wrapper macro for ntohs(): unnecessary,
	because it doesn't require an initialized winsock_2 library. See:
	<http://msdn.microsoft.com/en-us/library/windows/desktop/ms740075%28v=vs.85%29.aspx>
	* win/tclWinSock.c:
	* generic/tclStubInit.c:

2012-08-17  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/nmakehlp.c: Add "-V<num>" option, in order to be able to detect
	partial version numbers.

2012-08-15  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/buildall.vc.bat: Only build the threaded builds by default
	* win/rules.vc:        Some code cleanup

2010-08-13  Stuart Cassoff  <stwo@users.sourceforge.net>

	* unix/tclUnixCompat.c: [Bug 3555454]: Rearrange a bit to quash
	'declared but never defined' compiler warnings.

2012-08-13  Jan Nijtmans  <nijtmans@users.sf.net>

	* compat/zlib/win64/zlib1.dll:  Add 64-bit build of zlib1.dll, and use
	* compat/zlib/win64/zdll.lib:   it for the dynamic mingw-w64 build.
	* win/Makefile.in:
	* win/configure.in:
	* win/configure:

2012-08-09  Reinhard Max  <max@suse.de>

	* tests/http.test: Fix http-3.29 for machines without IPv6 support.

2010-08-08  Stuart Cassoff  <stwo@users.sourceforge.net>

	* unix/tclUnixCompat.c: Change one '#ifdef' to '#if defined()' for
	improved consistency within the file.

2012-08-08  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclfileName.c: [Bug #1536227]: Cygwin network pathname
	* tests/fileName.test:   support

2012-08-07  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclIOUtil.c:	[Bug 3554250]: Overlooked one field of cleanup
	in the thread exit handler for the filesystem subsystem.

2012-07-31  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclInterp.c (Tcl_GetInterpPath):
	* unix/tclUnixPipe.c (TclGetAndDetachPids, Tcl_PidObjCmd):
	* win/tclWinPipe.c (TclGetAndDetachPids, Tcl_PidObjCmd):
	Purge use of Tcl_AppendElement, and corrected conversion of PIDs to
	integer objects.

2012-07-31  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/nmakehlp.c:  Add -Q option from sampleextension.
	* win/Makefile.in: [FRQ 3544967]: Missing objectfiles in static lib
	* win/makefile.vc: (Thanks to Jos Decoster).

2012-07-29  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/Makefile.in:  No longer build tcltest.exe to run the tests,
	but use tclsh86.exe in combination with tcltest86.dll to do that.
	* tests/*.test:     load tcltest86.dll if necessary.

2012-07-28  Jan Nijtmans  <nijtmans@users.sf.net>

	* tests/clock.test:    [Bug 3549770]: Multiple test failures running
	* tests/registry.test: tcltest outside build tree
	* tests/winDde.test:

2012-07-27  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclUniData.c:   Support Unicode 6.2 (Add Turkish lira sign)
	* generic/regc_locale.c:

2012-07-25  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* win/tclWinPipe.c: [Bug 3547994]: Abandon the synchronous Windows
	pipe driver to its fate when needed to honour TIP#398.

2012-07-24  Trevor Davel  <twylite@crypt.co.za>

	* win/tclWinSock.c: [Bug: 3545363]: Loop over multiple underlying file
	descriptors for a socket where required (TcpCloseProc, SocketProc).
	Refactor socket/descriptor setup to manage linked list operations in
	one place. Fix memory leak in socket close (TcpCloseProc) and related
	dangling pointers in SocketEventProc.

2012-07-19  Reinhard Max  <max@suse.de>

	* win/tclWinSock.c (TcpAccept): [Bug: 3545363]: Use a large enough
	buffer for accept()ing IPv6 connections. Fix conversion of host and
	port for passing to the accept proc to be independent of the IP
	version.

2012-07-23  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclIO.c: [Bug 3545365]: Never try a bg-flush  on a dead
	channel, just like before 2011-08-17.

2012-07-19  Joe Mistachkin  <joe@mistachkin.com>

	* generic/tclTest.c: Fix several more missing mutex-locks in
	TestasyncCmd.

2012-07-19  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclTest.c: [Bug 3544685]: Missing mutex-lock in
	TestasyncCmd since 2011-08-19. Unbounded gratitude to Stuart
	Cassoff for spotting it.

2012-07-17  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/makefile.vc: [Bug 3544932]: Visual studio compiler check fails

2012-07-16  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclUtil.c (UpdateStringOfEndOffset): [Bug 3544658]: Stop
	1-byte overrun in memcpy, that object placement rules made harmless
	but which still caused compiler complaints.

2012-07-16  Jan Nijtmans  <nijtmans@users.sf.net>

	* library/reg/pkgIndex.tcl:  Make registry 1.3 package dynamically
	loadable when ::tcl::pkgconfig is available.

2012-07-11  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinReg.c: [Bug 3362446]: registry keys command fails
	with 8.5/8.6. Follow Microsofts example better in order to prevent
	problems when using HKEY_PERFORMANCE_DATA.

2012-07-10  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tclUnixNotfy.c: [Bug 3541646]: Don't panic on triggerPipe
	overrun.

2012-07-10  Donal K. Fellows  <dkf@users.sf.net>

	* win/tclWinSock.c (InitializeHostName): Corrected logic that
	extracted the name of the computer from the gethostname call so that
	it would use the name on success, not failure. Also ensured that the
	buffer size is exactly that recommended by Microsoft.

2012-07-08  Reinhard Max  <max@suse.de>

	* library/http/http.tcl: [Bug 3531209]: Add fix and test for URLs that
	* tests/http.test: 	 contain literal IPv6 addresses.

2012-07-05  Don Porter  <dgp@users.sourceforge.net>

	* unix/tclUnixPipe.c:	[Bug 1189293]: Make "<<" binary safe.
	* win/tclWinPipe.c:

2012-07-03  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclUtil.c (TclDStringAppendObj, TclDStringAppendDString):
	* generic/tclInt.h (TclDStringAppendLiteral, TclDStringClear):
	* generic/tclCompile.h (TclDStringAppendToken): Added wrappers to make
	common cases of appending to Tcl_DStrings simpler to write. Prompted
	by looking at [FRQ 1357401] (these are an _internal_ implementation of
	that FRQ).

2012-06-29  Jan Nijtmans  <nijtmans@users.sf.net>

	* library/msgcat/msgcat.tcl:   Add tn, ro_MO and ru_MO to msgcat.

2012-06-29  Harald Oehlmann <oehhar@users.sf.net>

	* library/msgcat/msgcat.tcl:	[Bug 3536888]: Locale guessing of
	* library/msgcat/pkgIndex.tcl:	msgcat fails on (some) Windows 7. Bump
	* unix/Makefile.in:		to 1.4.5
	* win/Makefile.in:

2012-06-29  Donal K. Fellows  <dkf@users.sf.net>

	* doc/GetIndex.3: Reinforced the description of the requirement for
	the tables of names to index over to be static, following posting to
	tcl-core by Brian Griffin about a bug caused by Tktreectrl not obeying
	this rule correctly. This does not represent a functionality change,
	merely a clearer documentation of a long-standing constraint.

2012-06-26  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tcl.m4:       Let Cygwin shared build link with
	* unix/configure.in: zlib1.dll, not cygz.dll (two less
	* unix/configure:    dependencies on cygwin-specific dll's)
	* unix/Makefile.in:

2012-06-26  Reinhard Max  <max@suse.de>

	* generic/tclIOSock.c: Use EAI_SYSTEM only if it exists.
	* unix/tclUnixSock.c:

2012-06-25  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclFileSystem.h:	[Bug 3024359]: Make sure that the
	* generic/tclIOUtil.c:	per-thread cache of the list of file systems
	* generic/tclPathObj.c:	currently registered is only updated at times
	when no active loops are traversing it.  Also reduce the amount of
	epoch storing and checking to where it can make a difference.

2012-06-25  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdAH.c (EncodingDirsObjCmd): [Bug 3537605]: Do the right
	thing when reporting errors with the number of arguments.

2012-06-25  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclfileName.c: [Patch 1536227]: Cygwin network pathname
	* tests/fileName.test:   support.

2012-06-23  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tclUnixNotfy.c: [Bug 3508771]: Cygwin notifier for handling
	win32 events.

2012-06-22  Reinhard Max  <max@suse.de>

	* generic/tclIOSock.c: Rework the error message generation of [socket],
	* unix/tclUnixSock.c:  so that the error code of getaddrinfo is used
	* win/tclWinSock.c:    instead of errno unless it is EAI_SYSTEM.

2012-06-21  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinReg.c:	[Bug 3362446]: registry keys command fails
	* tests/registry.test:	with 8.5/8.6

2012-06-11  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c:	[Bug 3532959]: Make sure the lifetime
	* generic/tclProc.c:	management of entries in the linePBodyPtr
	* tests/proc.test:	hash table can tolerate either order of
	teardown, interp first, or Proc first.

2012-06-08  Don Porter  <dgp@users.sourceforge.net>

	* unix/configure.in:	Update autogoo for gettimeofday().
	* unix/tclUnixPort.h:	Thanks Joe English.
	* unix/configure:	autoconf 2.13

	* unix/tclUnixPort.h:	[Bug 3530533]: Centralize #include <pthread.h>
	* unix/tclUnixThrd.c:	in the tclUnixPort.h header so that old unix
	systems that need inclusion in all compilation units are supported.

2012-06-08  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinDde.c:    Revise the "null data" check: null strings are
	possible, but empty binary arrays are not.
	* tests/winDde.test:  Add test-case (winDde-9.4) for transferring
	null-strings with dde. Convert tests to tcltest-2 syntax.

2012-06-06  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclZlib.c (TclZlibInit): Declare that Tcl is publishing the
	zlib package (version 2.0) as part of its bootstrap process. This will
	have an impact on tclkit (which includes zlib 1.1) but otherwise be
	very low impact.

2012-06-06  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tclUnixInit.c: On Cygwin, use win32 API in stead of uname()
	to determine the tcl_platform variables.

2012-05-31  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclZlib.c:  [Bug 3530536]: zlib-7.4 fails on IRIX64
	* tests/zlib.test:
	* doc/zlib.n:         Document that [stream checksum] doesn't do
	what's expected for "inflate" and "deflate" formats

2012-05-31  Donal K. Fellows  <dkf@users.sf.net>

	* library/safe.tcl (safe::AliasFileSubcommand): Don't assume that
	slaves have corresponding commands, as that is not true for
	sub-subinterpreters (used in Tk's test suite).

	* doc/safe.n: [Bug 1997845]: Corrected formatting so that generated
	HTML can link properly.

	* tests/socket.test (socket*-13.1): Prevented intermittent test
	failure due to race condition.

2012-05-29  Donal K. Fellows  <dkf@users.sf.net>

	* doc/expr.n, doc/mathop.n: [Bug 2931407]: Clarified semantics of
	division and remainder operators.

2012-05-29  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinDde.c:    [Bug 3525762]: Encoding handling in dde.
	* win/Makefile.in:    Fix "make genstubs" when cross-compiling on UNIX

2012-05-28  Donal K. Fellows  <dkf@users.sf.net>

	* library/safe.tcl (safe::AliasFileSubcommand): [Bug 3529949]: Made a
	more sophisticated method for preventing information leakage; it
	changes references to "~user" into "./~user", which is safe.

2012-05-25  Donal K. Fellows  <dkf@users.sf.net>

	* doc/namespace.n, doc/Ensemble.3: [Bug 3528418]: Document what is
	going on with respect to qualification of command prefixes in ensemble
	subcommand maps.

	* generic/tclIO.h (SYNTHETIC_EVENT_TIME): Factored out the definition
	of the amount of time that should be waited before firing a synthetic
	event on a channel.

2012-05-25  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinDde.c: [Bug 473946]: Special characters were not correctly
	sent, now for XTYP_EXECUTE as well as XTYP_REQUEST.
	* win/Makefile.in: Fix "make genstubs" when cross-compiling on UNIX

2012-05-24  Jan Nijtmans  <nijtmans@users.sf.net>

	* tools/genStubs.tcl:  Take cygwin handling of X11 into account.
	* generic/tcl*Decls.h: re-generated
	* generic/tclStubInit.c:  Implement TclpIsAtty, Cygwin only.
	* doc/dde.n: Doc fix: "dde execute iexplore" doesn't work
	without -async, because iexplore doesn't return a value

2012-05-24  Jan Nijtmans  <nijtmans@users.sf.net>

	* tools/genStubs.tcl:   Let cygwin share stub table with win32
	* win/tclWinSock.c:     implement TclpInetNtoa for win32
	* generic/tclInt.decls: Revert most of [3caedf05df], since when
	  we let cygwin share the win32 stub table this is no longer necessary
	* generic/tcl*Decls.h:  re-generated
	* doc/dde.n:            1.3 -> 1.4

2012-05-23  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclZlib.c (ZlibTransformInput): [Bug 3525907]: Ensure that
	decompressed input is flushed through the transform correctly when the
	input stream gets to the end. Thanks to Alexandre Ferrieux and Andreas
	Kupries for their work on this.

2012-05-21  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclFileName.c:	When using Tcl_SetObjLength() calls to
	* generic/tclPathObj.c:		grow and shrink the objPtr->bytes
	buffer, care must be taken that the value cannot possibly become pure
	Unicode.  Calling Tcl_AppendToObj() has the possibility of making such
	a conversion.  Bug found while valgrinding the trunk.

2012-05-21  Jan Nijtmans  <nijtmans@users.sf.net>

	IMPLEMENTATION OF TIP#106

	* win/tclWinDde.c:		Added encoding-related abilities to
	* library/dde/pkgIndex.tcl:	the [dde] command. The dde package's
	* tests/winDde.test:		version is now 1.4.0.
	* doc/dde.n:

2012-05-20  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOBasic.c (TclOO_Class_Constructor): [Bug 2023112]: Cut
	the amount of hackiness in class constructors, and refactor some of
	the error message handling from [oo::define] to be saner in the face
	of odd happenings.

2012-05-17  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdMZ.c (Tcl_SwitchObjCmd): [Bug 3106532]: Corrected
	resulting indexes from -indexvar option to be usable with [string
	range]; this was always the intention (and is consistent with [regexp
	-indices] too).
	***POTENTIAL INCOMPATIBILITY***
	Uses of [switch -regexp -indexvar] that previously compensated for the
	wrong offsets (by subtracting 1 from the end indices) now do not need
	to do so as the value is correct.

	* library/safe.tcl (safe::InterpInit): Ensure that the module path is
	constructed in the correct order.
	(safe::AliasGlob): [Bug 2964715]: More extensive handling of what
	globbing is required to support package loading.

	* doc/expr.n: [Bug 3525462]: Corrected statement about what happens
	when comparing "0y" and "0x12"; the previously documented behavior was
	actually a subtle bug (now long-corrected).

2012-05-16  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdAH.c (TclMakeFileCommandSafe): [Bug 3445787]: Improve
	the compatibility of safe interpreters' version of 'file' with that of
	unsafe interpreters.
	* library/safe.tcl (::safe::InterpInit): Teach the safe-interp scripts
	about how to expose 'file' properly.

2012-05-13  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinDde.c:   Protect against receiving strings without ending
	\0, as external applications (or Tcl with TIP #106) could generate
	that.

2012-05-10  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinDde.c: [Bug 473946]: Special characters not correctly sent
	* library/dde/pkgIndex.tcl:  Increase version to 1.3.3

2012-05-10  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* {win,unix}/configure{,.in}: [Bug 2812981]: Clean up bundled
	packages' build directory from within Tcl's ./configure, to avoid
	stale configuration.

2012-05-09  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIORChan.c: [Bug 3522560]: Fixed the crash, enabled the
	test case. Modified [chan postevent] to properly inject the event(s)
	into the owner thread's event queue for execution in the correct
	context. Renamed the ForwardOpTo...Thread() function to match with our
	terminology.

	* tests/ioCmd.test: [Bug 3522560]: Added a test which crashes the core
	if it were not disabled as knownBug. For a reflected channel
	transfered to a different thread the [chan postevent] run in the
	handler thread tries to execute the owner threads's fileevent scripts
	by itself, wrongly reaching across thread boundaries.

2012-04-28  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclIO.c: Properly close nonblocking channels even when
	not flushing them.

2012-05-03  Jan Nijtmans  <nijtmans@users.sf.net>

	* compat/zlib/*: Upgrade to zlib 1.2.7 (pre-built dll is still 1.2.5,
	will be upgraded as soon as the official build is available)

2012-05-03  Don Porter  <dgp@users.sourceforge.net>

	* tests/socket.test:	[Bug 3428754]: Test socket-14.2 tolerate
	[socket -async] connection that connects synchronously.

	* unix/tclUnixSock.c:	[Bug 3428753]: Fix [socket -async] connections
	that manage to connect synchronously.

2012-05-02  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/configure.in:    Better detection and implementation for
	* generic/configure:       cpuid instruction on Intel-derived
	* generic/tclUnixCompat.c: processors, both 32-bit and 64-bit.
	* generic/tclTest.c:       Move cpuid testcase from win-specific to
	* win/tclWinTest.c:        generic tests, as it should work on all
	* tests/platform.test:     Intel-related platforms now.

2012-04-30  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* tests/ioCmd.test: [Bug 3522560]: Tame deadlocks in broken refchan
	tests.

2012-04-28  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	IMPLEMENTATION OF TIP#398

	* generic/tclIO.c: Quickly Exit with Non-Blocking Blocked Channels
	* tests/io.test  : *** POTENTIAL INCOMPATIBILITY ***
	* doc/close.n    : (compat flag available)

2012-04-27  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclPort.h:    Move CYGWIN-specific stuff from tclPort.h to
	* generic/tclEnv.c:     tclUnixPort.h, where it belongs.
	* unix/tclUnixPort.h:
	* unix/tclUnixFile.c:

2012-04-27  Donal K. Fellows  <dkf@users.sf.net>

	* library/init.tcl (auto_execok): Allow shell builtins to be detected
	even if they are upper-cased.

2012-04-26  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclStubInit.c:    Get rid of _ANSI_ARGS_ and CONST
	* generic/tclIO.c:
	* generic/tclIOCmd.c:
	* generic/tclTest.c:
	* unix/tclUnixChan.c:

2012-04-25  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclUtil.c (TclDStringToObj): Added internal function to make
	the fairly-common operation of converting a DString into an Obj a more
	efficient one; for long strings, it can just transfer the ownership of
	the buffer directly. Replaces this:
	   obj=Tcl_NewStringObj(Tcl_DStringValue(&ds),Tcl_DStringLength(&ds));
	   Tcl_DStringFree(&ds);
	with this:
	   obj=TclDStringToObj(&ds);

2012-04-24  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.decls:      [Bug 3508771]: load tclreg.dll in cygwin
				     tclsh
	* generic/tclIntPlatDecls.h: Implement TclWinGetSockOpt,
	* generic/tclStubInit.c:     TclWinGetServByName and TclWinCPUID for
	* generic/tclUnixCompat.c:   Cygwin.
	* unix/configure.in:
	* unix/configure:
	* unix/tclUnixCompat.c:

2012-04-18  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata/Africa/Casablanca:
	* library/tzdata/America/Port-au-Prince:
	* library/tzdata/Asia/Damascus:
	* library/tzdata/Asia/Gaza:
	* library/tzdata/Asia/Hebron: tzdata2012c

2012-04-16  Donal K. Fellows  <dkf@users.sf.net>

	* doc/FileSystem.3 (Tcl_FSOpenFileChannelProc): [Bug 3518244]: Fixed
	documentation of this filesystem callback function; it must not
	register its created channel - that's the responsibility of the caller
	of Tcl_FSOpenFileChannel - as that leads to reference leaks.

2012-04-15  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclEnsemble.c (NsEnsembleImplementationCmdNR):
	* generic/tclIOUtil.c (Tcl_FSEvalFileEx): Cut out levels of the C
	stack by going direct to the relevant internal evaluation function.

	* generic/tclZlib.c (ZlibTransformSetOption): [Bug 3517696]: Make
	flushing work correctly in a pushed compressing channel transform.

2012-04-12  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.decls:      [Bug 3514475]: Remove TclpGetTimeZone and
	* generic/tclIntDecls.h:     TclpGetTZName
	* generic/tclIntPlatDecls.h:
	* generic/tclStubInit.c:
	* unix/tclUnixTime.c:
	* unix/tclWinTilemc:

2012-04-11  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinInit.c:     [Bug 3448512]: clock scan "1958-01-01" fails
	* win/tcl.m4:           only in debug compilation.
	* win/configure:
	* unix/tcl.m4:          Use NDEBUG consistantly meaning: no debugging.
	* unix/configure:
	* generic/tclBasic.c:
	* library/dde/pkgIndex.tcl:  Use [::tcl::pkgconfig get debug] instead
	* library/reg/pkgIndex.tcl:  of [info exists ::tcl_platform(debug)]

2012-04-10  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tcl.h (TCL_DEPRECATED_API): [Bug 2458976]: Added macro that
	can be used to mark parts of Tcl's API as deprecated. Currently only
	used for fields of Tcl_Interp, which TIPs 330 and 336 have deprecated
	with a migration strategy; we want to encourage people to move away
	from those fields.

2012-04-09  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOODefineCmds.c (ClassVarsSet, ObjVarsSet): [Bug 3396896]:
	Ensure that the lists of variable names used to drive variable
	resolution will never have the same name twice.

	* generic/tclVar.c (AppendLocals): [Bug 2712377]: Fix problem with
	reporting of declared variables in methods. It's really a problem with
	how [info vars] interacts with variable resolvers; this is just a bit
	of a hack so it is no longer a big problem.

2012-04-04  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.c (Tcl_NewObjectInstance, TclNRNewObjectInstance):
	[Bug 3514761]: Fixed bogosity with automated argument description
	handling when constructing an instance of a class that is itself a
	member of an ensemble. Thanks to Andreas Kupries for identifying that
	this was a problem case at all!
	(Tcl_CopyObjectInstance): Fix potential bleed-over of ensemble
	information into [oo::copy].

2012-04-04  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinSock.c:	[Bug 510001]: TclSockMinimumBuffers needs
	* generic/tclIOSock.c:	platform implementation.
	* generic/tclInt.decls:
	* generic/tclIntDecls.h:
	* generic/tclStubInit.c:

2012-04-03  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclStubInit.c: Remove the TclpGetTZName implementation for
	* generic/tclIntDecls.h: Cygwin (from 2012-04-02 commit), re-generated
	* generic/tclIntPlatDecls.h:

2012-04-02  Donal K. Fellows  <dkf@users.sf.net>

	IMPLEMENTATION OF TIP#396.

	* generic/tclBasic.c (builtInCmds, TclNRYieldToObjCmd): Convert the
	formerly-unsupported yieldm and yieldTo commands into [yieldto].

2012-04-02  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.decls: [Bug 3508771]: load tclreg.dll in cygwin tclsh
	* generic/tclIntPlatDecls.h: Implement TclWinGetTclInstance,
	* generic/tclStubInit.c:     TclpGetTZName, and various more
	win32-specific internal functions for Cygwin, so win32 extensions
	using those can be loaded in the cygwin version of tclsh.

2012-03-30  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tcl.m4:        [Bug 3511806]: Compiler checks too early
	* unix/configure.in:  This change allows to build the cygwin and
	* unix/tclUnixPort.h: mingw32 ports of Tcl/Tk to build out-of-the-box
	* win/tcl.m4:         using a native or cross-compiler.
	* win/configure.in:
	* win/tclWinPort.h:
	* win/README          Document how to build win32 or win64 executables
	with Linux, Cygwin or Darwin.

2012-03-29  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclCmdMZ.c (StringIsCmd): Faster mem-leak free
	implementation of [string is entier].

2012-03-27  Donal K. Fellows  <dkf@users.sf.net>

	IMPLEMENTATION OF TIP#395.

	* generic/tclCmdMZ.c (StringIsCmd): Implementation of the [string is
	entier] check. Code by Jos Decoster.

2012-03-27  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.h:      [Bug 3508771]: Wrong Tcl_StatBuf used on MinGW.
	* generic/tclFCmd.c:  [Bug 2015723]: Duplicate inodes from file stat
	* generic/tclCmdAH.c: on windows (but now for cygwin as well).
	* generic/tclOODefineCmds.c: minor gcc warning
	* win/tclWinPort.h:   Use lower numbers, preventing integer overflow.
	Remove the workaround for mingw-w64 [Bug 3407992]. It's long fixed.

2012-03-27  Donal K. Fellows  <dkf@users.sf.net>

	IMPLEMENTATION OF TIP#397.

	* generic/tclOO.c (Tcl_CopyObjectInstance): [Bug 3474460]: Make the
	target object name optional when copying classes. [RFE 3485060]: Add
	callback method ("<cloned>") so that scripted control over copying is
	easier.
	***POTENTIAL INCOMPATIBILITY***
	If you'd previously been using the "<cloned>" method name, this now
	has a standard semantics and call interface. Only a problem if you are
	also using [oo::copy].

2012-03-26  Donal K. Fellows  <dkf@users.sf.net>

	IMPLEMENTATION OF TIP#380.

	* doc/define.n, doc/object.n, generic/tclOO.c, generic/tclOOBasic.c:
	* generic/tclOOCall.c, generic/tclOODefineCmds.c, generic/tclOOInt.h:
	* tests/oo.test: Switch definitions of lists of things in objects and
	classes to a slot-based approach, which gives a lot more flexibility
	and programmability at the script-level. Introduce new [::oo::Slot]
	class which is the implementation of these things.

	***POTENTIAL INCOMPATIBILITY***
	The unknown method handler now may be asked to deal with the case
	where no method name is provided at all. The default implementation
	generates a compatible error message, and any override that forces the
	presence of a first argument (i.e., a method name) will continue to
	function as at present as well, so this is a pretty small change.

	* generic/tclOOBasic.c (TclOO_Object_Destroy): Made it easier to do a
	tailcall inside a normally-invoked destructor; prevented leakage out
	to calling command.

2012-03-25  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.decls:      [Bug 3508771]: load tclreg.dll in cygwin
	* generic/tclIntPlatDecls.h: tclsh. Implement TclWinConvertError,
	* generic/tclStubInit.c:     TclWinConvertWSAError, and various more
	* unix/Makefile.in:          win32-specific internal functions for
	* unix/tcl.m4:               Cygwin, so win32 extensions using those
	* unix/configure:            can be loaded in the cygwin version of
	* win/tclWinError.c:         tclsh.

2012-03-23  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.decls:       Revert some cygwin-related signature
	* generic/tclIntPlatDecls.h:  changes from [835f8e1e9d] (2010-01-22).
	* win/tclWinError.c:          They were an attempt to make the cygwin
	                              port compile again, but since cygwin is
	                              based on unix this serves no purpose any
	                              more.
	* win/tclWinSerial.c:         Use EAGAIN in stead of EWOULDBLOCK,
	* win/tclWinSock.c:           because in VS10+ the value of
	                              EWOULDBLOCK is no longer the same as
	                              EAGAIN.
	* unix/Makefile.in:           Add tclWinError.c to the CYGWIN build.
	* unix/tcl.m4:
	* unix/configure:

2012-03-20  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.decls:         [Bug 3508771]: load tclreg.dll in cygwin
	* generic/tclInt.decls:      tclsh. Implement TclWinGetPlatformId,
	* generic/tclIntPlatDecls.h: Tcl_WinUtfToTChar, Tcl_WinTCharToUtf (and
	* generic/tclPlatDecls.h:    a dummy TclWinCPUID) for Cygwin, so win32
	* generic/tclStubInit.c:     extensions using those can be loaded in
	* unix/tclUnixCompat.c:      the cygwin version of tclsh.

2012-03-19  Venkat Iyer <venkat@comit.com>

	* library/tzdata/America/Atikokan: Update to tzdata2012b.
	* library/tzdata/America/Blanc-Sablon:
	* library/tzdata/America/Dawson_Creek:
	* library/tzdata/America/Edmonton:
	* library/tzdata/America/Glace_Bay:
	* library/tzdata/America/Goose_Bay:
	* library/tzdata/America/Halifax:
	* library/tzdata/America/Havana:
	* library/tzdata/America/Moncton:
	* library/tzdata/America/Montreal:
	* library/tzdata/America/Nipigon:
	* library/tzdata/America/Rainy_River:
	* library/tzdata/America/Regina:
	* library/tzdata/America/Santiago:
	* library/tzdata/America/St_Johns:
	* library/tzdata/America/Swift_Current:
	* library/tzdata/America/Toronto:
	* library/tzdata/America/Vancouver:
	* library/tzdata/America/Winnipeg:
	* library/tzdata/Antarctica/Casey:
	* library/tzdata/Antarctica/Davis:
	* library/tzdata/Antarctica/Palmer:
	* library/tzdata/Asia/Yerevan:
	* library/tzdata/Atlantic/Stanley:
	* library/tzdata/Pacific/Easter:
	* library/tzdata/Pacific/Fakaofo:
	* library/tzdata/America/Creston: (new)

2012-03-19  Reinhard Max  <max@suse.de>

	* unix/tclUnixSock.c (Tcl_OpenTcpServer): Use the values returned
	by getaddrinfo() for all three arguments to socket() instead of
	only using ai_family. Try to keep the most meaningful error while
	iterating over the result list, because using the last error can
	be misleading.

2012-03-15  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.h: [Bug 3288345]: Wrong Tcl_StatBuf used on Cygwin
	* unix/tclUnixFile.c:
	* unix/tclUnixPort.h:
	* win/cat.c:           Remove cygwin stuff no longer needed
	* win/tclWinFile.c:
	* win/tclWinPort.h:

2012-03-12  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinFile.c: [Bug 3388350]: mingw64 compiler warnings

2012-03-11  Donal K. Fellows  <dkf@users.sf.net>

	* doc/*.n, doc/*.3: A number of small spelling and wording fixes.

2012-03-08  Donal K. Fellows  <dkf@users.sf.net>

	* doc/info.n:   Various minor fixes (prompted by Andreas Kupries
	* doc/socket.n: detecting a spelling mistake).

2012-03-07  Andreas Kupries  <andreask@activestate.com>

	* library/http/http.tcl: [Bug 3498327]: Generate upper-case
	* library/http/pkgIndex.tcl: hexadecimal output for compliance
	* tests/http.test: with RFC 3986. Bumped version to 2.8.4.
	* unix/Makefile.in:
	* win/Makefile.in:

2012-03-06  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinPort.h: Compatibility with older Visual Studio versions.

2012-03-04  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclLoad.c: Patch from the cygwin folks
	* unix/tcl.m4:
	* unix/configure: (re-generated)

2012-03-02  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclBinary.c (Tcl_SetByteArrayObj): [Bug 3496014]: Only zero
	out the memory block if it is not being immediately overwritten. (Our
	caller might still overwrite, but we should at least avoid
	known-useless work.)

2012-02-29  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclIOUtil.c:	[Bug 3466099]: BOM in Unicode
	* generic/tclEncoding.c:
	* tests/source.test:

2012-02-23  Donal K. Fellows  <dkf@users.sf.net>

	* tests/reg.test (14.21-23): Add tests relating to Bug 1115587. Actual
	bug is characterised by test marked with 'knownBug'.

2012-02-17  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclIOUtil.c: [Bug 2233954]: AIX: compile error
	* unix/tclUnixPort.h:

2012-02-16  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclExecute.c (INST_LIST_RANGE_IMM): Enhance implementation
	so that shortening a (not multiply-referenced) list by lopping the end
	off with [lrange] or [lreplace] is efficient.

2012-02-15  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileLreplaceCmd): Added a compilation
	strategy for [lreplace] that tackles the cases which are equivalent to
	a static [lrange].
	(TclCompileLrangeCmd): Add compiler for [lrange] with constant indices
	so we can take advantage of existing TCL_LIST_RANGE_IMM opcode.
	(TclCompileLindexCmd): Improve coverage of constant-index-style
	compliation using technique developed for [lrange] above.

	(TclCompileDictForCmd): [Bug 3487626]: Fix crash in compilation of
	[dict for] when its implementation command is used directly rather
	than through the ensemble.

2012-02-09  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c:	Converted the memcpy() calls in append
	operations to memmove() calls.  This adds safety in the case of
	overlapping copies, and improves performance on some benchmarks.

2012-02-06  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclEnsemble.c: [Bug 3485022]: TclCompileEnsemble() avoid
	* tests/trace.test:	compile when exec traces set.

2012-02-06  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclTrace.c:  [Bug 3484621]: Ensure that execution traces on
	* tests/trace.test:    bytecoded commands bump the interp's compile
	epoch.

2012-02-02  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclUniData.c: [FRQ 3464401]: Support Unicode 6.1
	* generic/regc_locale.c:

2012-02-02  Don Porter  <dgp@users.sourceforge.net>

	* win/tclWinFile.c:	[Bugs 2974459,2879351,1951574,1852572,
	1661378,1613456]: Revisions to the NativeAccess() routine that queries
	file permissions on Windows native filesystems.  Meant to fix numerous
	bugs where [file writable|readable|executable] "lies" about what
	operations are possible, especially when the file resides on a Samba
	share.

2012-02-01  Donal K. Fellows  <dkf@users.sf.net>

	* doc/AddErrInfo.3: [Bug 3482614]: Documentation nit.

2012-01-30  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileCatchCmd): Added a more efficient
	bytecode generator for the case where 'catch' is used without any
	variable arguments; don't capture the result just to discard it.

2012-01-26  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCmdAH.c:		[Bug 3479689]: New internal routine
	* generic/tclFCmd.c:		TclJoinPath(). Refactor all the
	* generic/tclFileName.c:	*Join*Path* routines to give them more
	* generic/tclInt.h:		useful interfaces that are easier to
	* generic/tclPathObj.c:		manage getting the refcounts right.

2012-01-26  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclPathObj.c:	[Bug 3475569]: Add checks for unshared values
	before calls demanding them.  [Bug 3479689]: Stop memory corruption
	when shimmering 0-refCount value to "path" type.

2012-01-25  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.c (Tcl_CopyObjectInstance): [Bug 3474460]: When
	copying an object, make sure that the configuration of the variable
	resolver is also duplicated.

2012-01-22  Jan Nijtmans  <nijtmans@users.sf.net>

	* tools/uniClass.tcl:    [FRQ 3473670]: Various Unicode-related
	* tools/uniParse.tcl:    speedups/robustness. Enhanced tools to be
	* generic/tclUniData.c:  able to handle characters > 0xFFFF. Done in
	* generic/tclUtf.c:      all branches in order to simplify merges for
	* generic/regc_locale.c: new Unicode versions (such as 6.1)

2012-01-22  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclDictObj.c (DictExistsCmd): [Bug 3475264]: Ensure that
	errors only ever happen when insufficient arguments are supplied, and
	not when a path doesn't exist or a dictionary is poorly formatted (the
	two cases can't be easily distinguished).

2012-01-21  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.h:        [Bug 3474726]: Eliminate detection of struct
	* generic/tclWinPort.h: _stat32i64, just use _stati64 in combination
	* generic/tclFCmd.c:    with _USE_32BIT_TIME_T, which is the same
	* generic/tclTest.c:    then. Only keep _stat32i64 usage for cygwin,
	* win/configure.in:     so it will not conflict with cygwin's own
	* win/configure:	struct stat.

2012-01-21  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCmdMZ.c:	[Bug 3475667]: Prevent buffer read overflow.
	Thanks to "sebres" for the report and fix.

2012-01-17  Donal K. Fellows  <dkf@users.sf.net>

	* doc/dict.n (dict with): [Bug 3474512]: Explain better what is going
	on when a dictionary key and the dictionary variable collide.

2012-01-13  Donal K. Fellows  <dkf@users.sf.net>

	* library/http/http.tcl (http::Connect): [Bug 3472316]: Ensure that we
	only try to read the socket error exactly once.

2012-01-12  Donal K. Fellows  <dkf@users.sf.net>

	* doc/tclvars.n: [Bug 3466506]: Document more environment variables.

2012-01-09  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclUtf.c:      [Bug 3464428]: [string is graph \u0120] was
	* generic/regc_locale.c: wrong. Add table for Unicode [:cntrl:] class.
	* tools/uniClass.tcl:    Generate Unicode [:cntrl:] class table.
	* tests/utf.test:

2012-01-08  Kevin B. Kenny  <kennykb@acm.org>

	* library/clock.tcl (ReadZoneinfoFile): [Bug 3470928]: Corrected a bug
	* tests/clock.test (clock-56.4):        where loading zoneinfo would
	fail if one timezone abbreviation was a proper tail of another, and
	zic used the same bytes of the file to represent both of them. Added a
	test case for the bug, using the same data that caused the observed
	failure "in the wild."

2011-12-30  Venkat Iyer <venkat@comit.com>

	* library/tzdata/America/Bahia:		Update to Olson's tzdata2011n
	* library/tzdata/America/Havana:
	* library/tzdata/Europe/Kiev:
	* library/tzdata/Europe/Simferopol:
	* library/tzdata/Europe/Uzhgorod:
	* library/tzdata/Europe/Zaporozhye:
	* library/tzdata/Pacific/Fiji:

2011-12-23  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclUtf.c: [Bug 3464428]: [string is graph \u0120] is wrong.
	* generic/tclUniData.c:
	* generic/regc_locale.c:
	* tests/utf.test:
	* tools/uniParse.tcl:   Clean up some unused stuff, and be more robust
	against changes in UnicodeData.txt syntax

2011-12-13  Andreas Kupries  <andreask@activestate.com>

	* generic/tclCompile.c (TclInitAuxDataTypeTable): Extended to register
	the DictUpdateInfo structure as an AuxData type. For use by tbcload,
	tclcompiler.

2011-12-11  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/regc_locale.c: [Bug 3457031]: Some Unicode 6.0 chars not
	* tests/utf.test:        in [:print:] class

2011-12-07  Jan Nijtmans  <nijtmans@users.sf.net>

	* tools/uniParse.tcl:    [Bug 3444754]: string tolower \u01c5 is wrong
	* generic/tclUniData.c:
	* tests/utf.test:

2011-11-30  Jan Nijtmans  <nijtmans@users.sf.net>

	* library/tcltest/tcltest.tcl: [Bug 967195]: Make tcltest work
	when tclsh is compiled without using the setargv() function on mingw.

2011-11-29  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/Makefile.in: don't install tommath_(super)?class.h
	* unix/Makefile.in: don't install directories like 8.2 and 8.3
	* generic/tclTomMath.h: [Bug 2991415]: move include tclInt.h from
	* generic/tclTomMathInt.h: tclTomMath.h to tclTomMathInt.h

2011-11-25  Donal K. Fellows  <dkf@users.sf.net>

	* library/history.tcl (history): Simplify the dance of variable
	management used when chaining to the implementation command.

2011-11-22  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclExecute.c (TclCompileObj): Simplify and de-indent the
	logic so that it is easier to comprehend.

2011-11-22  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinPort.h: [Bug 3354324]: Windows: [file mtime] sets wrong
	* win/tclWinFile.c: time (VS2005+ only).
	* generic/tclTest.c:

2011-11-20  Joe Mistachkin  <joe@mistachkin.com>

	* tests/thread.test: Remove unnecessary [after] calls from the thread
	tests.  Make error message matching more robust for tests that may
	have built-in race conditions.  Test thread-7.26 must first unset all
	thread testing related variables.  Revise results of the thread-7.28
	through thread-7.31 tests to account for the fact they are canceled
	via a script sent to the thread asynchronously, which then impacts the
	error message handling.  Attempt to manually drain the event queue for
	the main thread after joining the test thread to make sure no stray
	events are processed at the wrong time on the main thread.  Revise all
	the synchronization and comparison semantics related to the thread id
	and error message.

2011-11-18  Joe Mistachkin  <joe@mistachkin.com>

	* tests/thread.test: Remove all use of thread::release from the thread
	7.x tests, replacing it with a script that can easily cause "stuck"
	threads to self-destruct for those test cases that require it.  Also,
	make the error message handling far more robust by keeping track of
	every asynchronous error.

2011-11-17  Joe Mistachkin  <joe@mistachkin.com>

	* tests/thread.test: Refactor all the remaining thread-7.x tests that
	were using [testthread].  Note that this test file now requires the
	very latest version of the Thread package to pass all tests.  In
	addition, the thread-7.18 and thread-7.19 tests have been flagged as
	knownBug because they cannot pass without modifications to the [expr]
	command, persuant to TIP #392.

2011-11-17  Joe Mistachkin  <joe@mistachkin.com>

	* generic/tclThreadTest.c: For [testthread cancel], avoid creating a
	new Tcl_Obj when the default script cancellation result is desired.

2011-11-11  Donal K. Fellows  <dkf@users.sf.net>

	* win/tclWinConsole.c: Refactor common thread handling patterns.

2011-11-11  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* tests/zlib.test: [Bug 3428756]: Use nonblocking writes in
	single-threaded IO tests to avoid deadlocks when going beyond OS
	buffers.  Tidy up [chan configure] flags across zlib.test.

2011-11-03  Donal K. Fellows  <dkf@users.sf.net>

	* unix/tclUnixCompat.c (TclpGetPwNam, TclpGetPwUid, TclpGetGrNam)
	(TclpGetGrGid): Use the elaborate memory management scheme outlined on
	http://www.opengroup.org/austin/docs/austin_328.txt to handle Tcl's
	use of standard reentrant versions of the passwd/group access
	functions so that everything can work on all BSDs. Problem identified
	by Stuart Cassoff.

2011-10-20  Don Porter  <dgp@users.sourceforge.net>

	* library/http/http.tcl:        Bump to version 2.8.3
	* library/http/pkgIndex.tcl:
	* unix/Makefile.in:
	* win/Makefile.in:

	* changes:	Updates toward 8.6b3 release.

2011-10-20  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclLiteral.c (TclInvalidateCmdLiteral): [Bug 3418547]:
	Additional code for handling the invalidation of literals.
	* generic/tclBasic.c (Tcl_CreateObjCommand, Tcl_CreateCommand)
	(TclRenameCommand, Tcl_ExposeCommand): The four additional places that
	need extra care when dealing with literals.
	* generic/tclTest.c (TestInterpResolverCmd): Additional test machinery
	for interpreter resolvers.

2011-10-18  Reinhard Max  <max@suse.de>

	* library/clock.tcl (::tcl::clock::GetSystemTimeZone): Cache the time
	zone only if it was detected by one of the expensive methods.
	Otherwise after unsetting TCL_TZ or TZ the previous value will still
	be used.

2011-10-15  Venkat Iyer <venkat@comit.com>

	* library/tzdata/America/Sitka: Update to Olson's tzdata2011l
	* library/tzdata/Pacific/Fiji:
	* library/tzdata/Asia/Hebron: (New)

2011-10-11  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinFile.c:    [Bug 2935503]: Incorrect mode field returned by
	[file stat] command.

2011-10-09  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileDictWithCmd): Corrected handling of
	qualified names, and added spacial cases for empty bodies (used when
	[dict with] is just used for extracting variables).

2011-10-07  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.h:        Fix gcc warnings (discovered with latest
	* generic/tclIORChan.c: mingw, based on gcc 4.6.1)
	* tests/env.test:       Fix env.test, when running under wine 1.3.

2011-10-06  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclDictObj.c (TclDictWithInit, TclDictWithFinish):
	* generic/tclCompCmds.c (TclCompileDictWithCmd): Experimental
	compilation for the [dict with] subcommand, using parts factored out
	from the interpreted version of the command.

2011-10-05  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinInt.h:   Remove tclWinProcs, as it is no longer
	* win/tclWin32Dll.c: being used.

2011-10-03  Venkat Iyer <venkat@comit.com>

	* library/tzdata/Africa/Dar_es_Salaam: Update to Olson's tzdata2011k
	* library/tzdata/Africa/Kampala:
	* library/tzdata/Africa/Nairobi:
	* library/tzdata/Asia/Gaza:
	* library/tzdata/Europe/Kaliningrad:
	* library/tzdata/Europe/Kiev:
	* library/tzdata/Europe/Minsk:
	* library/tzdata/Europe/Simferopol:
	* library/tzdata/Europe/Uzhgorod:
	* library/tzdata/Europe/Zaporozhye:
	* library/tzdata/Pacific/Apia:

2011-09-29  Donal K. Fellows  <dkf@users.sf.net>

	* tools/tcltk-man2html.tcl, tools/tcltk-man2html-utils.tcl: More
	refactoring so that more of the utility code is decently out of the
	way. Adjusted the header-material generator so that version numbers
	are only included in locations where there is room.

2011-09-28  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclOO.h:      [RFE 3010352]: make all TclOO API functions
	* generic/tclOODecls.h: MODULE_SCOPE
	* generic/tclOOIntDecls.h:

2011-09-27  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclIndexObj.c (Tcl_ParseArgsObjv): [Bug 3413857]: Corrected
	the memory management for the code parsing arguments when returning
	"large" numbers of arguments. Also unbroke the TCL_ARGV_AUTO_REST
	macro in passing.

2011-09-26  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdAH.c (TclMakeFileCommandSafe): [Bug 3211758]: Also
	make the main [file] command hidden by default in safe interpreters,
	because that's what existing code expects. This will reduce the amount
	which the code breaks, but not necessarily eliminate it...

2011-09-23  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclIORTrans.c: More revisions to get finalization of
	ReflectedTransforms correct, including adopting a "dead" field as was
	done in tclIORChan.c.

	* tests/thread.test:	Stop using the deprecated thread management
	commands of the tcltest package.  The test suite ought to provide
	these tools for itself.  They do not belong in a testing harness.

2011-09-22  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCmdIL.c:	Revise [info frame] so that it stops creating
	cycles in the iPtr->cmdFramePtr stack.

2011-09-22  Donal K. Fellows  <dkf@users.sf.net>

	* doc/re_syntax.n: [Bug 2903743]: Add more magic so that we can do at
	least something sane on Solaris.
	* tools/tcltk-man2html-utils.tcl (process-text): Teach the HTML
	generator how to handle this magic.

2011-09-21  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclThreadTest.c: Revise the thread exit handling of the
	[testthread] command so that it properly maintains the per-process
	data structures even when the thread exits for reasons other than the
	[testthread exit] command.

2011-09-21  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* unix/tclIO.c: [Bug 3412487]: Now short reads are allowed in
	synchronous fcopy, avoid mistaking them as nonblocking ones.

2011-09-21  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIORTrans.c (ForwardOpToOwnerThread): Fixed the missing
	initialization of the 'dsti' field. Reported by Don Porter, on chat.

2011-09-20  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclIORChan.c: Re-using the "interp" field to signal a dead
	channel (via NULL value) interfered with conditional cleanup tasks
	testing for "the right interp". Added a new field "dead" to perform
	the dead channel signalling task so the corrupted logic is avoided.

	* generic/tclIORTrans.c: Revised ReflectClose() and
	FreeReflectedTransform() so that we stop leaking ReflectedTransforms,
	yet free all Tcl_Obj values in the same thread that alloced them.

2011-09-19  Don Porter  <dgp@users.sourceforge.net>

	* tests/ioTrans.test:	Conversion from [testthread] to Thread package
	stops most memory leaks.

	* tests/thread.test:	Plug most memory leaks in thread.test.
	Constrain the rest to be skipped during `make valgrind'.  Tests using
	the [testthread cancel] testing command are leaky.  Corrections wait
	for either addition of [thread::cancel] to the Thread package, or
	improvements to the [testthread] testing command to make leak-free
	versions of these tests possible.

	* generic/tclIORChan.c:	Plug all memory leaks in ioCmd.test exposed
	* tests/ioCmd.test:	by `make valgrind'.
	* unix/Makefile.in:

2011-09-16  Jan Nijtmans  <nijtmans@users.sf.net>

	IMPLEMENTATION OF TIP #388

	* doc/Tcl.n:
	* doc/re_syntax.n:
	* generic/regc_lex.c:
	* generic/regcomp.c:
	* generic/regcustom.h:
	* generic/tcl.h:
	* generic/tclParse.c:
	* tests/reg.test:
	* tests/utf.test:

2011-09-16  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclProc.c (ProcWrongNumArgs): [Bugs 3400658,3408830]:
	Corrected the handling of procedure error messages (found by TclOO).

2011-09-16  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.h:        Don't change Tcl_UniChar type when
	* generic/regcustom.h:  TCL_UTF_MAX == 4 (not supported anyway)

2011-09-16  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclProc.c (ProcWrongNumArgs): [Bugs 3400658,3408830]:
	Ensemble-like rewriting of error messages is complex, and TclOO (in
	combination with iTcl) hits the most tricky cases.

	* library/http/http.tcl (http::geturl): [Bug 3391977]: Ensure that the
	-headers option overrides the -type option (important because -type
	has a default that is not always appropriate, and the header must not
	be duplicated).

2011-09-15  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompExpr.c: [Bug 3408408]: Partial improvement by sharing
	as literals the computed values of constant subexpressions when we can
	do so without incurring the cost of string rep generation.

2011-09-13  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclUtil.c:	[Bug 3390638]: Workaround broken Solaris
	Studio cc optimizer.  Thanks to Wolfgang S. Kechel.

	* generic/tclDTrace.d:	[Bug 3405652]: Portability workaround for
	broken system DTrace support.  Thanks to Dagobert Michelson.

2011-09-12  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinPort.h: [Bug 3407070]: tclPosixStr.c won't build with
	EOVERFLOW==E2BIG

2011-09-11  Don Porter  <dgp@users.sourceforge.net>

	* tests/thread.test:	Convert [testthread] use to Thread package use
	in thread-6.1.  Eliminates a memory leak in `make valgrind`.

	* tests/socket.test:	[Bug 3390699]: Convert [testthread] use to
	Thread package use in socket_*-13.1.  Eliminates a memory leak in
	`make valgrind`.

2011-09-09  Don Porter  <dgp@users.sourceforge.net>

	* tests/chanio.test:	[Bug 3389733]: Convert [testthread] use to
	* tests/io.test:	Thread package use in *io-70.1.  Eliminates a
	memory leak in `make valgrind`.

2011-09-07  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompExpr.c: [Bug 3401704]: Allow function names like
	* tests/parseExpr.test:	 influence(), nanobot(), and 99bottles() that
	have been parsed as missing operator syntax errors before with the
	form NUMBER + FUNCTION.
	***POTENTIAL INCOMPATIBILITY***

2011-09-06  Venkat Iyer <venkat@comit.com>

	* library/tzdata/America/Goose_Bay: Update to Olson's tzdata2011i
	* library/tzdata/America/Metlakatla:
	* library/tzdata/America/Resolute:
	* library/tzdata/America/St_Johns:
	* library/tzdata/Europe/Kaliningrad:
	* library/tzdata/Pacific/Apia:
	* library/tzdata/Pacific/Honolulu:
	* library/tzdata/Africa/Juba: (new)

2011-09-06  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.h:   [RFE 1711975]: Tcl_MainEx() (like Tk_MainEx())
	* generic/tclDecls.h:
	* generic/tclMain.c:

2011-09-02  Don Porter  <dgp@users.sourceforge.net>

	* tests/http.test:	Convert [testthread] use to Thread package use.
	Eliminates memory leak seen in `make valgrind`.

2011-09-01  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* unix/tclUnixSock.c: [Bug 3401422]: Cache script-level changes to the
	nonblocking flag of an async client socket in progress, and commit
	them on completion.

2011-09-01  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStrToD.c:	[Bug 3402540]: Corrections to TclParseNumber()
	* tests/binary.test:	to make it reject invalid Nan(Hex) strings.

	* tests/scan.test:	[scan Inf %g] is portable; remove constraint.

2011-08-30  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclInterp.c (SlaveCommandLimitCmd, SlaveTimeLimitCmd):
	[Bug 3398794]: Ensure that low-level conditions in the limit API are
	enforced at the script level through errors, not a Tcl_Panic. This
	means that interpreters cannot read their own limits (writing already
	did not work).

2011-08-30  Reinhard Max  <max@suse.de>

	* unix/tclUnixSock.c (TcpWatchProc): [Bug 3394732]: Put back the check
	for server sockets.

2011-08-29  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclIORTrans.c: Leak of ReflectedTransformMap.

2011-08-27  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c:  [RFE 3396731]: Revise the [string reverse]
	* tests/string.test:	implementation to operate on the representation
	that comes in, avoid conversion to other reps.

2011-08-23  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclIORChan.c:	[Bug 3396948]: Leak of ReflectedChannelMap.

2011-08-19  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclIORTrans.c: [Bugs 3393279, 3393280]: ReflectClose(.) is
	missing Tcl_EventuallyFree() calls at some of its exits.

	* generic/tclIO.c: [Bugs 3394654, 3393276]: Revise FlushChannel() to
	account for the possibility that the ChanWrite() call might recycle
	the buffer out from under us.

	* generic/tclIO.c: Preserve the chanPtr during FlushChannel so that
	channel drivers don't yank it away before we're done with it.

2011-08-19  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclTest.c: [Bug 2981154]: async-4.3 segfault.
	* tests/async.test:  [Bug 1774689]: async-4.3 sometimes fails.

2011-08-18  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclIO.c: [Bug 3096275]: Sync fcopy buffers input.

2011-08-18  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclUniData.c: [Bug 3393714]: Overflow in toupper delta
	* tools/uniParse.tcl:
	* tests/utf.test:

2011-08-17  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclIO.c:  [Bug 2946474]: Consistently resume backgrounded
	* tests/ioCmd.test: flushes+closes when exiting.

2011-08-17  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* doc/interp.n: Document TIP 378's one-way-ness.

2011-08-17  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclGet.c: [Bug 3393150]: Overlooked free of intreps.
	(It matters for bignums!)

2011-08-16  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompile.c: [Bug 3392070]: More complete prevention of
	Tcl_Obj reference cycles when producing an intrep of ByteCode.

2011-08-16  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclListObj.c (TclLindexList, TclLsetFlat): Silence warnings
	about (unreachable) cases of uninitialized variables.
	* generic/tclCmdIL.c (SelectObjFromSublist): Improve the generation of
	* generic/tclIndexObj.c (Tcl_ParseArgsObjv): messages through the use
	* generic/tclVar.c (ArrayStartSearchCmd):    of Tcl_ObjPrintf.

2011-08-15  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c: [Bug 3390272]: Leak of [info script] value.

2011-08-15  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclPosixStr.c:    [Bug 3388350]: mingw64 compiler warnings
	* win/tclWinPort.h:
	* win/configure.in:
	* win/configure:

2011-08-14  Jan Nijtmans  <nijtmans@users.sf.net>

	* doc/FindExec.3: [Patch 3124554]: Move WishPanic from Tk to Tcl
	* doc/Panic.3     Added Documentation

2011-08-12  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclPathObj.c:	[Bug 3389764]: Eliminate possibility that dup
	of a "path" value can create reference cycle.

2011-08-12  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclZlib.c (ZlibTransformOutput): [Bug 3390073]: Return the
	correct length of written data for a compressing transform.

2011-08-10 Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclTestObj.c: [Bug 3386721]: Allow multiple [load]ing of the
	Tcltest package.

2011-08-09 Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclBasic.c: [Bug 2919042]: Restore "valgrindability" of Tcl
	* generic/tclEvent.c: that was lost by the streamlining of [exit], by
	* generic/tclExecute.c: conditionally forcing a full Finalize:
	* generic/tclInt.h:  use -DPURIFY or ::env(TCL_FINALIZE_ON_EXIT)

2011-08-09 Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclCompCmds.c: [Bug 3386417]: Avoid a reference loop between
	* generic/tclInt.h:      the bytecode and its companion errostack
	* generic/tclResult.c:   when compiling a syntax error.

2011-08-09  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinConsole.c: [Bug 3388350]: mingw64 compiler warnings
	* win/tclWinDde.c:
	* win/tclWinPipe.c:
	* win/tclWinSerial.c:

2011-08-09  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.h: Change the signature of TclParseHex(), such that
	* generic/tclParse.c: it can now parse up to 8 hex characters.

2011-08-08  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclZlib.c (ZlibStreamCmd): Make the -buffersize option to
	'$zstream add' function correctly instead of having its value just be
	discarded unceremoniously. Also generate error codes from more of the
	code, not just the low-level code but also the Tcl infrastructure.

2011-08-07  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOInfo.c (InfoClassCallCmd): [Bug 3387082]: Plug memory
	leak in call chain introspection.

2011-08-06  Kevin B, Kenny  <kennykb@acm.org>

	* generic/tclAssemnbly.c: [Bug 3384840]: Plug another memory leak.
	* generic/tclStrToD.c: [Bug 3386975]: Plug another memory leak.

2011-08-05  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclStrToD.c: [Bug 3386975]: Plugged a memory leak in
	double->string conversion.

2011-08-05  Don Porter  <dgp@users.sourceforge.net>

	*** 8.6b2 TAGGED FOR RELEASE ***

	* changes:	Updates for 8.6b2 release.

2011-08-05  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclAssembly.c (AssembleOneLine): Ensure that memory isn't
	leaked when an unknown instruction is encountered. Also simplify code
	through use of Tcl_ObjPrintf in error message generation.

	* generic/tclZlib.c (ZlibTransformClose): [Bug 3386197]: Plug a memory
	leak found by Miguel with valgrind, and ensure that the correct
	direction's buffers are released.

2011-08-04  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclVar.c (TclPtrSetVar): Fix valgrind-detected error when
	newValuePtr is the interp's result obj.

2011-08-04  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclAssembly.c (FreeAssemblyEnv): [Bug 3384840]: Plug another
	possible memory leak due to over-complex code for freeing the table of
	labels.

2011-08-04  Reinhard Max  <max@suse.de>

	* generic/tclIOSock.c (TclCreateSocketAddress): Don't bother using
	AI_ADDRCONFIG for now, as it was causing problems in various
	situations.

2011-08-04  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclAssembly.c (AssembleOneLine, GetBooleanOperand)
	(GetIntegerOperand, GetListIndexOperand, FindLocalVar): [Bug 3384840]:
	A Tcl_Obj is allocated by GetNextOperand, so callers of it must not
	hold a reference to one in the 'out' parameter when calling it. This
	was causing a great many memory leaks.
	* tests/assemble.test (assemble-51.*): Added group of memory leak
	tests.

2011-08-02  Don Porter  <dgp@users.sourceforge.net>

	* changes:	Updates for 8.6b2 release.
	* tools/tcltk-man2html.tcl: Variable substitution botch.

2011-08-02  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclObj.c (Tcl_DbIncrRefCount, Tcl_DbDecrRefCount)
	(Tcl_DbIsShared): [Bug 3384007]: Fix the panic messages so they share
	what should be shared and have the right number of spaces.

2011-08-01  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclProc.c (TclProcCompileProc): [Bug 3383616]: Fix for leak
	of resolveInfo when recompiling procs. Thanks go to Gustaf Neumann for
	detecting the bug and providing the fix.

2011-08-01  Donal K. Fellows  <dkf@users.sf.net>

	* doc/tclvars.n (EXAMPLES): Added some examples of how some of the
	standard global variables can be used, following prompting by a
	request by Robert Hicks.

	* tools/tcltk-man2html.tcl (plus-pkgs): [Bug 3382474]: Added code to
	determine the version number of contributed packages from their
	directory names so that HTML documentation builds are less confusing.

2011-07-29  Donal K. Fellows  <dkf@users.sf.net>

	* tools/tcltk-man2html.tcl (ensemble_commands, remap_link_target):
	Small enhancements to improve cross-linking with contributed packages.
	* tools/tcltk-man2html-utils.tcl (insert-cross-references): Enhance to
	cope with contributed packages' C API.

2011-07-28  Reinhard Max  <max@suse.de>

	* unix/tcl.m4 (SC_TCL_IPV6): Fix AC_DEFINE invocation for
	NEED_FAKE_RFC2553.
	* unix/configure:	autoconf-2.59

2011-07-28  Don Porter  <dgp@users.sourceforge.net>

	* changes:	Updates for 8.6b2 release.

	* library/tzdata/Asia/Anadyr: Update to Olson's tzdata2011h
	* library/tzdata/Asia/Irkutsk:
	* library/tzdata/Asia/Kamchatka:
	* library/tzdata/Asia/Krasnoyarsk:
	* library/tzdata/Asia/Magadan:
	* library/tzdata/Asia/Novokuznetsk:
	* library/tzdata/Asia/Novosibirsk:
	* library/tzdata/Asia/Omsk:
	* library/tzdata/Asia/Sakhalin:
	* library/tzdata/Asia/Vladivostok:
	* library/tzdata/Asia/Yakutsk:
	* library/tzdata/Asia/Yekaterinburg:
	* library/tzdata/Europe/Kaliningrad:
	* library/tzdata/Europe/Moscow:
	* library/tzdata/Europe/Samara:
	* library/tzdata/Europe/Volgograd:
	* library/tzdata/America/Kralendijk: (new)
	* library/tzdata/America/Lower_Princes: (new)

2011-07-26  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.c (initScript): Ensure that TclOO is properly found by
	all the various package mechanisms (by adding a dummy ifneeded script)
	and not just some of them.

2011-07-21  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinPort.h: [Bug 3372130]: Fix hypot math function with MSVC10

2011-07-19  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclUtil.c:	[Bug 3371644]: Repair failure to properly handle
	* tests/util.test: (length == -1) scanning in TclConvertElement().
	Thanks to Thomas Sader and Alexandre Ferrieux.

2011-07-19  Donal K. Fellows  <dkf@users.sf.net>

	* doc/*.3, doc/*.n: Many small fixes to documentation as part of
	project to improve quality of generated HTML docs.

	* tools/tcltk-man2html.tcl (remap_link_target): More complete set of
	definitions of link targets, especially for major C API types.
	* tools/tcltk-man2html-utils.tcl (output-IP-list, cross-reference):
	Update to generation to produce proper HTML bulleted and enumerated
	lists.

2011-07-19 Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* doc/upvar.n: Undocument long gone limitation of [upvar].

2011-07-18  Don Porter  <dgp@users.sourceforge.net>

	* generic/tcl.h:	Bump version number to 8.6b2.
	* library/init.tcl:
	* unix/configure.in:
	* win/configure.in:
	* unix/tcl.spec:
	* tools/tcl.wse.in:
	* README:

	* unix/configure:	autoconf-2.59
	* win/configure:

2011-07-15  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompile.c: Avoid segfaults when RecordByteCodeStats() is
	called in a deleted interp.

	* generic/tclCompile.c: [Bug 467523, 3357771]: Prevent circular
	references in values with ByteCode intreps.  They can lead to memory
	leaks.

2011-07-14  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOCall.c (TclOORenderCallChain): [Bug 3365156]: Remove
	stray refcount bump that caused a memory leak.

2011-07-12  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclUnixSock.c:  [Bug 3364777]: Stop segfault caused by
	reading from struct after it had been freed.

2011-07-11  Joe Mistachkin  <joe@mistachkin.com>

	* generic/tclExecute.c: [Bug 3339502]: Correct cast for CURR_DEPTH to
	silence compiler warning.

2011-07-08  Donal K. Fellows  <dkf@users.sf.net>

	* doc/http.n: [FRQ 3358415]: State what RFC defines HTTP/1.1.

2011-07-07  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c: Add missing INT2PTR

2011-07-03  Donal K. Fellows  <dkf@users.sf.net>

	* doc/FileSystem.3: Corrected statements about ctime field of 'struct
	stat'; that was always the time of the last metadata change, not the
	time of creation.

2011-07-02  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclStrToD.c:
	* generic/tclTomMath.decls:
	* generic/tclTomMathDecls.h:
	* macosx/Tcl.xcode/project.pbxproj:
	* macosx/Tcl.xcodeproj/project.pbxproj:
	* tests/util.test:
	* unix/Makefile.in:
	* win/Makefile.in:
	* win/Makefile.vc:
	[Bug 3349507]: Fix a bug where bignum->double conversion is "round up"
	and not "round to nearest" (causing expr double(1[string repeat 0 23])
	not to be 1e+23).

2011-06-28  Reinhard Max  <max@suse.de>

	* unix/tclUnixSock.c (CreateClientSocket): [Bug 3325339]: Fix and
	simplify posting of the writable fileevent at the end of an
	asynchronous connection attempt. Improve comments for some of the
	trickery around [socket -async].

	* tests/socket.test: Adjust tests to the async code changes. Add more
	tests for corner cases of async sockets.

2011-06-22  Andreas Kupries  <andreask@activestate.com>

	* library/platform/pkgIndex.tcl: Updated to platform 1.0.10. Added
	* library/platform/platform.tcl: handling of the DEB_HOST_MULTIARCH
	* unix/Makefile.in: location change for libc.
	* win/Makefile.in:

	* generic/tclInt.h: Fixed the inadvertently committed disabling of
	stack checks, see my 2010-11-15 commit.

2011-06-22  Reinhard Max  <max@suse.de>

	Merge from rmax-ipv6-branch:
	* unix/tclUnixSock.c: Fix [socket -async], so that all addresses
	returned by getaddrinfo() are tried, not just the first one. This
	requires the event loop to be running while the async connection is in
	progress. ***POTENTIAL INCOMPATIBILITY***
	* tests/socket.test: Add a test for the above.
	* doc/socket: Document the fact that -async needs the event loop
	* generic/tclIOSock.c: AI_ADDRCONFIG is broken on HP-UX

2011-06-21  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclLink.c:	[Bug 3317466]: Prevent multiple links to a
	single Tcl variable when calling Tcl_LinkVar().

2011-06-13  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStrToD.c:  [Bug 3315098]: Mem leak fix from Gustaf
	Neumann.

2011-06-08  Andreas Kupries  <andreask@activestate.com>

	* generic/tclExecute.c: Reverted the fix for [Bug 3274728] committed
	on 2011-04-06 and replaced with one which is 64bit-safe. The existing
	fix crashed tclsh on Windows 64bit.

2011-06-08  Donal K. Fellows  <dkf@users.sf.net>

	* tests/fileSystem.test: Reduce the amount of use of duplication of
	complex code to perform common tests, and convert others to do the
	test result check directly using Tcltest's own primitives.

2011-06-06  Jan Nijtmans  <nijtmans@users.sf.net>

	* tests/socket.test: Add test constraint, so 6.2 and 6.3 don't fail
	when the machine does not have support for ip6. Follow-up to checkin
	from 2011-05-11 by rmax.

2011-06-02  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Removed TclCleanupLiteralTable(), and old
	* generic/tclInt.h:	band-aid routine put in place while a fix for
	* generic/tclLiteral.c:	[Bug 994838] took shape.  No longer needed.

2011-06-02  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclInt.h (TclInvalidateNsCmdLookup): [Bug 3185407]: Extend
	the set of epochs that are potentially bumped when a command is
	created, for a slight performance drop (in some circumstances) and
	improved semantics.

2011-06-01  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c: Using the two free data elements in NRCommand to
	store objc and objv - useful for debugging.

2011-06-01  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclUtil.c:   Fix for [Bug 3309871]: Valgrind finds: invalid
	read in TclMaxListLength().

2011-05-31  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInt.h:	  Use a complete growth algorithm for lists so
	* generic/tclListObj.c:	  that length limits do not overconstrain by a
	* generic/tclStringObj.c: factor of 2.  [Bug 3293874]: Fix includes
	* generic/tclUtil.c:	  rooting all growth routines by default on a
	common tunable parameter TCL_MIN_GROWTH.

2011-05-25  Don Porter  <dgp@users.sourceforge.net>

	* library/msgcat/msgcat.tcl:	Bump to msgcat 1.4.4.
	* library/msgcat/pkgIndex.tcl:
	* unix/Makefile.in:
	* win/Makefile.in:

2011-05-25  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.h (TCLOO_VERSION): Bump version.

	IMPLEMENTATION OF TIP#381.

	* doc/next.n, doc/ooInfo.n, doc/self.n, generic/tclOO.c,
	* generic/tclOOBasic.c, generic/tclOOCall.c, generic/tclOOInfo.c,
	* generic/tclOOInt.h, tests/oo.test, tests/ooNext2.test: Added
	introspection of call chains ([self call], [info object call], [info
	class call]) and ability to skip ahead in chain ([nextto]).

2011-05-24  Venkat Iyer <venkat@comit.com>

	* library/tzdata/Africa/Cairo: Update to Olson tzdata2011g

2011-05-24  Donal K. Fellows  <dkf@users.sf.net>

	* library/msgcat/msgcat.tcl (msgcat::mcset, msgcat::mcmset): Remove
	some useless code; [dict set] builds dictionary levels for us.

2011-05-17  Andreas Kupries  <andreask@activestate.com>

	* generic/tclCompile.c (TclFixupForwardJump): Tracked down and fixed
	* generic/tclBasic.c (TclArgumentBCEnter): the cause of a violation of
	my assertion that 'ePtr->nline == objc' in TclArgumentBCEnter.  When a
	bytecode was grown during jump fixup the pc -> command line mapping
	was not updated. When things aligned just wrong the mapping would
	direct command A to the data for command B, with a different number of
	arguments.

2011-05-11  Reinhard Max  <max@suse.de>

	* unix/tclUnixSock.c (TcpWatchProc): No need to check for server
	sockets here, as the generic server code already takes care of that.
	* tests/socket.test (accept): Add tests to make sure that this remains
	so.

2011-05-10  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInt.h:     New internal routines TclScanElement() and
	* generic/tclUtil.c:    TclConvertElement() are rewritten guts of
	machinery to produce string rep of lists.  The new routines avoid and
	correct [Bug 3173086].  See comments for much more detail.

	* generic/tclDictObj.c:         Update all callers.
	* generic/tclIndexObj.c:
	* generic/tclListObj.c:
	* generic/tclUtil.c:
	* tests/list.test:

2011-05-09  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclNamesp.c (NamespacePathCmd): Convert to use Tcl_Obj API
	* generic/tclPkg.c (Tcl_PackageObjCmd):   for result generation in
	* generic/tclTimer.c (Tcl_AfterObjCmd):   [after info], [namespace
	path] and [package versions].

2011-05-09  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclListObj.c:	Revise empty string tests so that we avoid
	potentially expensive string rep generations, especially for dicts.

2011-05-07  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclLoad.c (TclGetLoadedPackages): Convert to use Tcl_Obj API
	for result generation.

2011-05-07  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclInt.h: Fix USE_TCLALLOC so that it can be enabled without
	* unix/Makefile.in: editing the Makefile.

2011-05-05  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclListObj.c:	Stop generating string rep of dict when
	converting to list.  Tolerate NULL interps more completely.

2011-05-03  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclUtil.c:	Tighten Tcl_SplitList().
	* generic/tclListObj.c:	Tighten SetListFromAny().
	* generic/tclDictObj.c:	Tighten SetDictFromAny().
	* tests/join.test:
	* tests/mathop.test:

2011-05-02  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCmdMZ.c:	Revised TclFindElement() interface. The final
	* generic/tclDictObj.c:	argument had been bracePtr, the address of a
	* generic/tclListObj.c:	boolean var, where the caller can be told
	* generic/tclParse.c:	whether or not the parsed list element was
	* generic/tclUtil.c:	enclosed in braces.  In practice, no callers
	really care about that.  What the callers really want to know is
	whether the list element value exists as a literal substring of the
	string being parsed, or whether a call to TclCopyAndCollpase() is
	needed to produce the list element value.  Now the final argument is
	changed to do what callers actually need. This is a better fit for the
	calls in tclParse.c, where now a good deal of post-processing checking
	for "naked backslashes" is no longer necessary.
	***POTENTIAL INCOMPATIBILITY***
	For any callers calling in via the internal stubs table who really do
	use the final argument explicitly to check for the enclosing brace
	scenario.  Simply looking for the braces where they must be is the
	revision available to those callers, and it will backport cleanly.

	* tests/parse.test:	Tests for expanded literals quoting detection.

	* generic/tclCompCmdsSZ.c:	New TclFindElement() is also a better
	fit for the [switch] compiler.

	* generic/tclInt.h:	Replace TclCountSpaceRuns() with
	* generic/tclListObj.c:	TclMaxListLength() which is the function we
	* generic/tclUtil.c:	actually want.
	* generic/tclCompCmdsSZ.c:

	* generic/tclCompCmdsSZ.c: Rewrite of parts of the switch compiler to
	better use the powers of TclFindElement() and do less parsing on its
	own.

2011-04-28  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInt.h:	New utility routines:
	* generic/tclParse.c:	TclIsSpaceProc() and TclCountSpaceRuns()
	* generic/tclUtil.c:

	* generic/tclCmdMZ.c:	Use new routines to replace calls to isspace()
	* generic/tclListObj.c:	and their /* INTL */ risk.
	* generic/tclStrToD.c:
	* generic/tclUtf.c:
	* unix/tclUnixFile.c:

	* generic/tclStringObj.c:	Improved reaction to out of memory.

2011-04-27  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCmdMZ.c:	TclFreeIntRep() correction & cleanup.
	* generic/tclExecute.c:
	* generic/tclIndexObj.c:
	* generic/tclInt.h:
	* generic/tclListObj.c:
	* generic/tclNamesp.c:
	* generic/tclResult.c:
	* generic/tclStringObj.c:
	* generic/tclVar.c:

	* generic/tclListObj.c:	FreeListInternalRep() cleanup.

2011-04-21  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInt.h:	Use macro to set List intreps.
	* generic/tclListObj.c:

	* generic/tclCmdIL.c:	Limits on list length were too strict.
	* generic/tclInt.h:	Revised panics to errors where possible.
	* generic/tclListObj.c:
	* tests/lrepeat.test:

	* generic/tclCompile.c:	Make sure SetFooFromAny routines react
	* generic/tclIO.c:	reasonably when passed a NULL interp.
	* generic/tclIndexObj.c:
	* generic/tclListObj.c:
	* generic/tclNamesp.c:
	* generic/tclObj.c:
	* generic/tclProc.c:
	* macosx/tclMacOSXFCmd.c:

2011-04-21  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.h:       fix for [Bug 3288345]: Wrong Tcl_StatBuf
	* generic/tclInt.h:    used on MinGW. Make sure that all _WIN32
	* win/tclWinFile.c:    compilers use exactly the same layout
	* win/configure.in:    for Tcl_StatBuf - the one used by MSVC6 -
	* win/configure:       in all situations.

2011-04-19  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclConfig.c:	Reduce internals access in the implementation
	of [<foo>::pkgconfig list].

2011-04-18  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCmdIL.c:	Use ListRepPtr(.) and other cleanup.
	* generic/tclConfig.c:
	* generic/tclListObj.c:

	* generic/tclInt.h:	Define and use macros that test whether a Tcl
	* generic/tclBasic.c:	list value is canonical.
	* generic/tclUtil.c:

2011-04-18  Donal K. Fellows  <dkf@users.sf.net>

	* doc/dict.n: [Bug 3288696]: Command summary was confusingly wrong
	when it came to [dict filter] with a 'value' filter.

2011-04-16  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclFCmd.c (TclFileAttrsCmd): Add comments to make this code
	easier to understand. Added a panic to handle the case where the VFS
	layer does something odd.

2011-04-13  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclUtil.c:	[Bug 3285375]: Rewrite of Tcl_Concat*()
	routines to prevent segfaults on buffer overflow.  Build them out of
	existing primitives already coded to handle overflow properly.  Uses
	the new TclTrim*() routines.

	* generic/tclCmdMZ.c:	New internal utility routines TclTrimLeft()
	* generic/tclInt.h:	and TclTrimRight().  Refactor the
	* generic/tclUtil.c:	[string trim*] implementations to use them.

2011-04-13  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclVar.c: [Bug 2662380]: Fix crash caused by appending to a
	variable with a write trace that unsets it.

2011-04-13  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclUtil.c (Tcl_ConcatObj): [Bug 3285375]: Make the crash
	less mysterious through the judicious use of a panic. Not yet properly
	fixed, but at least now clearer what the failure mode is.

2011-04-12  Don Porter  <dgp@users.sourceforge.net>

	* tests/string.test:	Test for [Bug 3285472]. Not buggy in trunk.

2011-04-12  Venkat Iyer <venkat@comit.com>

	* library/tzdata/Atlantic/Stanley: Update to Olson tzdata2011f

2011-04-12  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c: Fix for [Bug 2440625], kbk's patch

2011-04-11  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:
	* tests/coroutine.test: [Bug 3282869]: Ensure that 'coroutine eval'
	runs the initial command in the proper context.

2011-04-11  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.h:    Fix for [Bug 3281728]: Tcl sources from 2011-04-06
	* unix/tcl.m4:      do not build on GCC9 (RH9)
	* unix/configure:

2011-04-08  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinPort.h: Fix for [Bug 3280043]: win2k: unresolved DLL
	* win/configure.in: imports.
	* win/configure

2011-04-06  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c (TclCompileObj): Earlier return if Tip280
	gymnastics not needed.

	* generic/tclExecute.c: Fix for [Bug 3274728]: making *catchTop an
	unsigned long.

2011-04-06  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tclAppInit.c:  Make symbols "main" and "Tcl_AppInit"
	MODULE_SCOPE: there is absolutely no reason for exporting them.
	* unix/tcl.m4:        Don't use -fvisibility=hidden with static
	* unix/configure      libraries (--disable-shared)

2011-04-06  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclFCmd.c, macosx/tclMacOSXFCmd.c, unix/tclUnixChan.c,
	* unix/tclUnixFCmd.c, win/tclWinChan.c, win/tclWinDde.c,
	* win/tclWinFCmd.c, win/tclWinLoad.c, win/tclWinPipe.c,
	* win/tclWinReg.c, win/tclWinSerial.c, win/tclWinSock.c: More
	generation of error codes (most platform-specific parts not already
	using Tcl_PosixError).

2011-04-05  Venkat Iyer <venkat@comit.com>

	* library/tzdata/Africa/Casablanca: Update to Olson's tzdata2011e
	* library/tzdata/America/Santiago:
	* library/tzdata/Pacific/Easter:
	* library/tzdata/America/Metlakatla: (new)
	* library/tzdata/America/North_Dakota/Beulah: (new)
	* library/tzdata/America/Sitka: (new)

2011-04-04  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.c, generic/tclOOBasic.c, generic/tclOODefineCmds.c
	* generic/tclOOInfo.c, generic/tclOOMethod.c: More generation of
	error codes (TclOO miscellany).

	* generic/tclCmdAH.c, generic/tclCmdIL.c: More generation of error
	codes (miscellaneous commands mostly already handled).

2011-04-04  Don Porter  <dgp@users.sourceforge.net>

	* README:	[Bug 3202030]: Updated README files, repairing broken
	* macosx/README:URLs and removing other bits that were clearly wrong.
	* unix/README:	Still could use more eyeballs on the detailed build
	* win/README:	advice on various plaforms.

2011-04-04  Donal K. Fellows  <dkf@users.sf.net>

	* library/init.tcl (tcl::mathfunc::rmmadwiw): Disable by default to
	make test suite work.

	* generic/tclBasic.c, generic/tclStringObj.c, generic/tclTimer.c,
	* generic/tclTrace.c, generic/tclUtil.c: More generation of error
	codes ([format], [after], [trace], RE optimizer).

2011-04-04  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclCmdAH.c:  Better error-message in case of errors
	* generic/tclCmdIL.c:  related to setting a variable. This fixes
	* generic/tclDictObj.c: a warning: "Why make your own error
	* generic/tclScan.c:   message? Why?"
	* generic/tclTest.c:
	* test/error.test:
	* test/info.test:
	* test/scan.test:
	* unix/tclUnixThrd.h:  Remove this unused header file.

2011-04-03  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclNamesp.c, generic/tclObj.c, generic/tclPathObj.c:
	* generic/tclPipe.c, generic/tclPkg.c, generic/tclProc.c:
	* generic/tclScan.c: More generation of error codes (namespace
	creation, path normalization, pipeline creation, package handling,
	procedures, [scan] formats)

2011-04-02  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclStrToD.c (QuickConversion): Replaced another couple
	of 'double' declarations with 'volatile double' to work around
	misrounding issues in mingw-gcc 3.4.5.

2011-04-02  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclInterp.c, generic/tclListObj.c, generic/tclLoad.c:
	More generation of errorCodes ([interp], [lset], [load], [unload]).

	* generic/tclEvent.c, generic/tclFileName.c: More generation of
	errorCode information (default [bgerror] and [glob]).

2011-04-01  Reinhard Max  <max@suse.de>

	* library/init.tcl: TIP#131 implementation.

2011-03-31  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclGetDate.y, generic/tclDate.c (TclClockOldscanObjCmd):
	More generation of errorCode information.

2011-03-28  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdMZ.c, generic/tclConfig.c, generic/tclUtil.c: More
	generation of errorCode information, notably when lists are mis-parsed

	* generic/tclCmdMZ.c (Tcl_RegexpObjCmd, Tcl_RegsubObjCmd): Use the
	error messages generated by the variable management code rather than
	creating our own.

2011-03-27  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c (TclNREvalObjEx): fix performance issue, notably
	apparent in tclbench's "LIST lset foreach". Many thanks to Twylite for
	patiently researching the issue and explaining it to me: a missing
	Tcl_ResetObjResult that causes unwanted sharing of the current result
	Tcl_Obj.

2011-03-26  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclNamesp.c (Tcl_Export, Tcl_Import, DoImport): More
	generation of errorCode information.

	* generic/tclCompExpr.c, generic/tclCompile.c, generic/tclExecute.c:
	* generic/tclListObj.c, generic/tclNamesp.c, generic/tclObj.c:
	* generic/tclStringObj.c, generic/tclUtil.c: Reduce the number of
	casts used to manage Tcl_Obj internal representations.

2011-03-24  Don Porter  <dgp@users.sourceforge.net>

	* generic/tcl.h (ckfree,etc.): Restored C++ usability to the memory
	allocation and free macros.

2011-03-24  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclFCmd.c (TclFileAttrsCmd): Ensure that any reference to
	temporary index tables is squelched immediately rather than hanging
	around to trip us up in the future.

2011-03-23  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclObj.c: Exploit HAVE_FAST_TSD for the deletion context in
	TclFreeObj()

2011-03-22  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclThreadAlloc.c: Simpler initialization of Cache under
	HAVE_FAST_TSD, from mig-alloc-reform.

2011-03-21  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tclLoadDl.c:    [Bug 3216070]: Loading extension libraries
	* unix/tclLoadDyld.c:  from embedded Tcl applications.
	***POTENTIAL INCOMPATIBILITY***
	For extensions which rely on symbols from other extensions being
	present in the global symbol table. For an example and some discussion
	of workarounds, see http://stackoverflow.com/q/8330614/301832

2011-03-21  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCkAlloc.c:
	* generic/tclInt.h: Remove one level of allocator indirection in
	non-memdebug builds, imported from mig-alloc-reform.

2011-03-20  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclThreadAlloc.c: Imported HAVE_FAST_TSD support from
	mig-alloc-reform. The feature has to be enabled by hand: no autoconf
	support has been added. It is not clear how universal a build using
	this will be: it also requires some loader support.

2011-03-17  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompExpr.c (ParseExpr): Generate errorCode information on
	failure to parse expressions.

2011-03-17  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclMain.c: [Patch 3124683]: Reorganize the platform-specific
	stuff in (tcl|tk)Main.c.

2011-03-16  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclCkalloc.c: [Bug 3197864]: Pointer truncation on Win64
	TCL_MEM_DEBUG builds.

2011-03-16  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Some rewrites to eliminate calls to isspace()
	* generic/tclParse.c:	and their /* INTL */ risk.
	* generic/tclProc.c:

2011-03-16  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tcl.m4:    Make SHLIB_LD_LIBS='${LIBS}' the default and
	* unix/configure: set to "" on per-platform necessary basis.
	Backported from TEA, but kept all original platform code which was
	removed from TEA.

2011-03-14  Kevin B. Kenny  <kennykb@acm.org>

	* tools/tclZIC.tcl (onDayOfMonth): Allow for leading zeroes in month
	and day so that tzdata2011d parses correctly.
	* library/tzdata/America/Havana:
	* library/tzdata/America/Juneau:
	* library/tzdata/America/Santiago:
	* library/tzdata/Europe/Istanbul:
	* library/tzdata/Pacific/Apia:
	* library/tzdata/Pacific/Easter:
	* library/tzdata/Pacific/Honolulu:  tzdata2011d

	* generic/tclAssembly.c (BBEmitInstInt1): Changed parameter data types
	in an effort to silence a MSVC warning reported by Ashok P. Nadkarni.
	Unable to test, since both forms work on my machine in VC2005, 2008,
	2010, in both release and debug builds.
	* tests/tclTest.c (TestdstringCmd): Restored MSVC buildability broken
	by [5574bdd262], which changed the effective return type of 'ckalloc'
	from 'char*' to 'void*'.

2011-03-13  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: remove TEBCreturn()

2011-03-12  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tcl.h (ckalloc,ckfree,ckrealloc): Moved casts into these
	macro so that they work with VOID* (which is a void* on all platforms
	which Tcl actually builds on) and unsigned int for the length
	parameters, removing the need for MANY casts across the rest of Tcl.
	Note that this is a strict source-level-only change, so size_t cannot
	be used (would break binary compatibility on 64-bit platforms).

2011-03-12  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinFile.c: [Bug 3185609]: File normalization corner case
	of ... broken with -DUNICODE

2011-03-11  Donal K. Fellows  <dkf@users.sf.net>

	* tests/unixInit.test: Make better use of tcltest2.

2011-03-10  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclBasic.c, generic/tclCompCmds.c, generic/tclEnsemble.c:
	* generic/tclInt.h, generic/tclNamesp.c, library/auto.tcl:
	* tests/interp.test, tests/namespace.test, tests/nre.test:
	Converted the [namespace] command into an ensemble. This has the
	consequence of making it vital for Tcl code that wishes to work with
	namespaces to _not_ delete the ::tcl namespace.
	***POTENTIAL INCOMPATIBILITY***

	* library/tcltest/tcltest.tcl (loadIntoSlaveInterpreter): Added this
	command to handle connecting tcltest to a slave interpreter. This adds
	in the hook (inside the tcltest namespace) that allows the tests run
	in the child interpreter to be reported as part of the main sequence
	of test results. Bumped version of tcltest to 2.3.3.
	* tests/init.test, tests/package.test: Adapted these test files to use
	the new feature.

	* generic/tclAlloc.c, generic/tclCmdMZ.c, generic/tclCompExpr.c:
	* generic/tclCompile.c, generic/tclEnv.c, generic/tclEvent.c:
	* generic/tclIO.c, generic/tclIOCmd.c, generic/tclIORChan.c:
	* generic/tclIORTrans.c, generic/tclLiteral.c, generic/tclNotify.c:
	* generic/tclParse.c, generic/tclStringObj.c, generic/tclUtil.c:
	* generic/tclZlib.c, unix/tclUnixFCmd.c, unix/tclUnixNotfy.c:
	* unix/tclUnixPort.h, unix/tclXtNotify.c: Formatting fixes, mainly to
	comments, so code better fits the style in the Engineering Manual.

2011-03-09  Donal K. Fellows  <dkf@users.sf.net>

	* tests/incr.test: Update more of the test suite to use Tcltest 2.

2011-03-09  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclNamesp.c:	[Bug 3202171]: Tighten the detector of nested
	* tests/namespace.test:	[namespace code] quoting that the quoted
	scripts function properly even in a namespace that contains a custom
	"namespace" command.

	* doc/tclvars.n:	Formatting fix.  Thanks to Pat Thotys.

2011-03-09  Donal K. Fellows  <dkf@users.sf.net>

	* tests/dstring.test, tests/init.test, tests/link.test: Update more of
	the test suite to use Tcltest 2.

2011-03-08  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclBasic.c: Fix gcc warnings: variable set but not used
	* generic/tclProc.c:
	* generic/tclIORChan.c:
	* generic/tclIORTrans.c:
	* generic/tclAssembly.c:  Fix gcc warning: comparison between signed
	and unsigned integer expressions

2011-03-08  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInt.h:	Remove TclMarkList() routine, an experimental
	* generic/tclUtil.c:	dead-end from the 8.5 alpha days.

	* generic/tclResult.c (ResetObjResult): [Bug 3202905]: Correct failure
	to clear invalid intrep.  Thanks to Colin McDonald.

2011-03-08  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclAssembly.c, tests/assemble.test: Migrate to use a style
	more consistent with the rest of Tcl.

2011-03-06  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c:	More replacements of Tcl_UtfBackslash() calls
	* generic/tclCompile.c:	with TclParseBackslash() where possible.
	* generic/tclCompCmdsSZ.c:
	* generic/tclParse.c:
	* generic/tclUtil.c:

	* generic/tclUtil.c (TclFindElement):	[Bug 3192636]: Guard escape
	sequence scans to not overrun the string end.

2011-03-05  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclParse.c (TclParseBackslash): [Bug 3200987]: Correct
	* tests/parse.test:	trunction checks in \x and \u substitutions.

2011-03-05  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c (TclStackFree): insure that the execStack
	satisfies "at most one free stack after the current one" when
	consecutive reallocs caused the creation of intervening stacks.

2011-03-05  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclAssembly.c (new file):
	* generic/tclBasic.c (Tcl_CreateInterp):
	* generic/tclInt.h:
	* tests/assemble.test (new file):
	* unix/Makefile.in:
	* win/Makefile.in:
	* win/makefile.vc:  Merged dogeen-assembler-branch into HEAD. Since
	all functional changes are in the tcl::unsupported namespace, there's
	no reason to sequester this code on a separate branch.

2011-03-05  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: Cleaner mem management for TEBCdata

	* generic/tclExecute.c:
	* tests/nre.test: Renamed BottomData to TEBCdata, so that the name
	refers to what it is rather than to its storage location.

	* generic/tclBasic.c:     Renamed struct TEOV_callback to the more
	* generic/tclCompExpr.c:  descriptive NRE_callback.
	* generic/tclCompile.c:
	* generic/tclExecute.c:
	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclIntDecls.h:
	* generic/tclTest.c:

2011-03-04  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOMethod.c (ProcedureMethodCompiledVarConnect)
	(ProcedureMethodCompiledVarDelete): [Bug 3185009]: Keep references to
	resolved object variables so that an unset doesn't leave any dangling
	pointers for code to trip over.

2011-03-01  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c (TclNREvalObjv): Missing a variable declaration
	in commented out non-optimised code, left for ref in checkin
	[b97b771b6d]

2011-03-03  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclResult.c (Tcl_AppendResultVA):	Use the directive
	USE_INTERP_RESULT [TIP 330] to force compat with interp->result
	access, instead of the improvised hack USE_DIRECT_INTERP_RESULT_ACCESS
	from releases past.

2011-03-01  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompCmdsSZ.c (TclCompileThrowCmd, TclCompileUnsetCmd):
	fix leaks

	* generic/tclBasic.c:       This is [Patch 3168398],
	* generic/tclCompCmdsSZ.c:  Joe Mistachkin's optimisation
	* generic/tclExecute.c:     of Tip #285
	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclIntDecls.h:
	* generic/tclInterp.c:
	* generic/tclOODecls.h:
	* generic/tclStubInit.c:
	* win/makefile.vc:

	* generic/tclExecute.c (ExprObjCallback): Fix object leak

	* generic/tclExecute.c (TEBCresume): Store local var array and
	constants in automatic vars to reduce indirection, slight perf
	increase

	* generic/tclOOCall.c (TclOODeleteContext): Added missing '*' so that
	trunk compiles.

	* generic/tclBasic.c (TclNRRunCallbacks): [Patch 3168229]: Don't do
	the trampoline dance for commands that do not have an nreProc.

2011-03-01  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.c (Tcl_NewObjectInstance, TclNRNewObjectInstance)
	(TclOOObjectCmdCore, FinalizeObjectCall):
	* generic/tclOOBasic.c (TclOO_Object_Destroy, AfterNRDestructor):
	* generic/tclOOCall.c (TclOODeleteContext, TclOOGetCallContext):
	Reorganization of call context reference count management so that code
	is (mostly) simpler.

2011-01-26  Donal K. Fellows  <dkf@users.sf.net>

	* doc/RegExp.3: [Bug 3165108]: Corrected documentation of description
	of subexpression info in Tcl_RegExpInfo structure.

2011-01-25  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclPreserve.c:  Don't miss 64-bit address bits in panic
				  message.
	* win/tclWinChan.c:       Fix various gcc-4.5.2 64-bit warning
	* win/tclWinConsole.c:    messages, e.g. by using full 64-bits for
	* win/tclWinDde.c:	  socket fd's
	* win/tclWinPipe.c:
	* win/tclWinReg.c:
	* win/tclWinSerial.c:
	* win/tclWinSock.c:
	* win/tclWinThrd.c:

2011-01-19  Jan Nijtmans  <nijtmans@users.sf.net>

	* tools/genStubs.tcl: [FRQ 3159920]: Tcl_ObjPrintf() crashes with
	* generic/tcl.decls   bad format specifier.
	* generic/tcl.h:
	* generic/tclDecls.h:

2011-01-18  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOMethod.c (PushMethodCallFrame): [Bug 3001438]: Make
	sure that the cmdPtr field of the procPtr is correct and relevant at
	all times so that [info frame] can report sensible information about a
	frame after a return to it from a recursive call, instead of probably
	crashing (depending on what else has overwritten the Tcl stack!)

2011-01-18  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclBasic.c:      Various mismatches between Tcl_Panic
	* generic/tclCompCmds.c:   format string and its arguments,
	* generic/tclCompCmdsSZ.c: discovered thanks to [Bug 3159920]
	* generic/tclCompExpr.c:
	* generic/tclEnsemble.c:
	* generic/tclPreserve.c:
	* generic/tclTest.c:

2011-01-17  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclIOCmd.c: [Bug 3148192]: Commands "read/puts" incorrectly
	* tests/chanio.test:  interpret parameters. Improved error-message
	* tests/io.test       regarding legacy form.
	* tests/ioCmd.test

2011-01-15  Kevin B. Kenny  <kennykb@acm.org>

	* doc/tclvars.n:
	* generic/tclStrToD.c:
	* generic/tclUtil.c (Tcl_PrintDouble):
	* tests/util.test (util-16.*): [Bug 3157475]: Restored full Tcl 8.4
	compatibility for the formatting of floating point numbers when
	$::tcl_precision is not zero. Added compatibility tests to make sure
	that excess trailing zeroes are suppressed for all eight major code
	paths.

2011-01-12  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinFile.c:   Use _vsnprintf in stead of vsnprintf, because
	MSVC 6 doesn't have it. Reported by andreask.
	* win/tcl.m4:         handle --enable-64bit=ia64 for gcc
	* win/configure.in:   more accurate test for correct <intrin.h>
	* win/configure:      (autoconf-2.59)
	* win/tclWin32Dll.c:  VS 2005 64-bit does not have intrin.h, and
	* generic/tclPanic.c: does not need it.

2011-01-07  Kevin B. Kenny  <kennykb@acm.org>

	* tests/util.test (util-15.*): Added test cases for floating point
	conversion of the largest denormal and the smallest normal number, to
	avoid any possibility of the failure suffered by PHP in the last
	couple of days. (They didn't fail, so no actual functional change.)

2011-01-05  Donal K. Fellows  <dkf@users.sf.net>

	* tests/package.test, tests/pkg.test: Coalesce these tests into one
	file that is concerned with the package system. Convert to use
	tcltest2 properly.
	* tests/autoMkindex.test, tests/pkgMkIndex.test: Convert to use
	tcltest2 properly.

2011-01-01  Donal K. Fellows  <dkf@users.sf.net>

	* tests/cmdAH.test, tests/cmdMZ.test, tests/compExpr.test,
	* tests/compile.test, tests/concat.test, tests/eval.test,
	* tests/fileName.test, tests/fileSystem.test, tests/interp.test,
	* tests/lsearch.test, tests/namespace-old.test, tests/namespace.test,
	* tests/oo.test, tests/proc.test, tests/security.test,
	* tests/switch.test, tests/unixInit.test, tests/var.test,
	* tests/winDde.test, tests/winPipe.test: Clean up of tests and
	conversion to tcltest 2. Target has been to get init and cleanup code
	out of the test body and into the -setup/-cleanup stanzas.

	* tests/execute.test (execute-11.1): [Bug 3142026]: Added test that
	fails (with a crash) in an unfixed memdebug build on 64-bit systems.

2010-12-31  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdIL.c (SortElement): Use unions properly in the
	definition of this structure so that there is no need to use nasty
	int/pointer type punning. Made it clearer what the purposes of the
	various parts of the structure are.

2010-12-31  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/dltest/*.c: [Bug 3148192]: Fix broken [load] tests by ensuring
	that the affected files are never compiled with -DSTATIC_BUILD.

2010-12-30  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c (GrowEvaluationStack): Off-by-one error in
	sizing the new allocation - was ok in comment but wrong in the code.
	Triggered by [Bug 3142026] which happened to require exactly one more
	than what was in existence.

2010-12-26  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdIL.c (Tcl_LsortObjCmd): Fix crash when multiple -index
	options are used. Simplified memory handling logic.

2010-12-20  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWin32Dll.c:    [Patch 3059922]: fixes for mingw64 - gcc4.5.1
	tdm64-1: completed for all environments.

2010-12-20  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/configure.in:   Explicitely test for intrinsics support in
	compiler, before assuming only MSVC has it.
	* win/configure:      (autoconf-2.59)
	* generic/tclPanic.c:

2010-12-19  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWin32Dll.c:    [Patch 3059922]: fixes for mingw64 - gcc4.5.1
	tdm64-1: Fixed for gcc, not yet for MSVC 64-bit.

2010-12-17  Stuart Cassoff  <stwo@users.sourceforge.net>

	* unix/Makefile.in:  Remove unwanted/obsolete 'ddd' target.

2010-12-17  Stuart Cassoff  <stwo@users.sourceforge.net>

	* unix/Makefile.in:	Clean up '.PHONY:' targets: Arrange those
				common to Tcl and Tk as in Tk's Makefile.in,
				add any missing ones and remove duplicates.

2010-12-17  Stuart Cassoff  <stwo@users.sourceforge.net>

	* unix/Makefile.in:  [Bug 2446711]: Remove 'allpatch' target.

2010-12-17  Stuart Cassoff  <stwo@users.sourceforge.net>

	* unix/Makefile.in:  [Bug 2537626]: Use 'rpmbuild', not 'rpm'.

2010-12-16  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclPanic.c:  [Patch 3124554]: Move WishPanic from Tk to Tcl
	* win/tclWinFile.c:    Better communication with debugger, if present.

2010-12-15  Kevin B. Kenny  <kennykb@acm.org>

	[dogeen-assembler-branch]

	* tclAssembly.c:
	* assemble.test: 	Reworked beginCatch/endCatch handling to
	enforce the more severe (but more correct) restrictions on catch
	handling that appeared in the discussion of [Bug 3098302] and in
	tcl-core traffic beginning about 2010-10-29.

2010-12-15  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclPanic.c:    Restore abort() as it was before.
	* win/tclWinFile.c:      [Patch 3124554]: Use ExitProcess() here, like
	in wish.

2010-12-14  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.h: [Bug 3137454]: Tcl CVS HEAD does not build on GCC 3.

2010-12-14  Reinhard Max  <max@suse.de>

	* win/tclWinSock.c (CreateSocket):         Swap the loops over
	* unix/tclUnixSock.c (CreateClientSocket): local and remote addresses,
	so that the system's address preference for the remote side decides
	which family gets tried first. Cleanup and clarify some of the
	comments.

2010-12-13  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.h:    [Bug 3135271]: Link error due to hidden
	* unix/tcl.m4:      symbols (CentOS 4.2)
	* unix/configure:   (autoconf-2.59)
	* win/tclWinFile.c:  Undocumented feature, only meant to be used by
	Tk_Main. See [Patch 3124554]: Move WishPanic from Tk to Tcl

2010-12-12  Stuart Cassoff  <stwo@users.sourceforge.net>

	* unix/tcl.m4: Better building on OpenBSD.
	* unix/configure: (autoconf-2.59)

2010-12-10  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.h:       [Bug 3129448]: Possible over-allocation on
	* generic/tclCkalloc.c: 64-bit platforms, part 2
	* generic/tclCompile.c:
	* generic/tclHash.c:
	* generic/tclInt.h:
	* generic/tclIO.h:
	* generic/tclProc.c:

2010-12-10 Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclIO.c: Make sure [fcopy -size ... -command ...] always
	* tests/io.test:   calls the callback asynchronously, even for size
			   zero.

2010-12-10  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclBinary.c:  Fix gcc -Wextra warning: missing initializer
	* generic/tclCmdAH.c:
	* generic/tclCmdIL.c:
	* generic/tclCmdMZ.c:
	* generic/tclDictObj.c:
	* generic/tclIndexObj.c:
	* generic/tclIOCmd.c:
	* generic/tclVar.c:
	* win/tcl.m4:               Fix manifest-generation for 64-bit gcc
				    (mingw-w64)
	* win/configure.in:         Check for availability of intptr_t and
				    uintptr_t
	* win/configure:            (autoconf-2.59)
	* generic/tclInt.decls:     Change 1st param of TclSockMinimumBuffers
	* generic/tclIntDecls.h:    to ClientData, and TclWin(Get|Set)SockOpt
	* generic/tclIntPlatDecls.h:to SOCKET, because on Win64 those are
	* generic/tclIOSock.c:	    64-bit, which does not fit.
	* win/tclWinSock.c:
	* unix/tclUnixSock.c:

2010-12-09  Donal K. Fellows  <dkf@users.sf.net>

	* tests/fCmd.test: Improve sanity of constraints now that we don't
	support anything before Windows 2000.

	* generic/tclCmdAH.c (TclInitFileCmd, TclMakeFileCommandSafe, ...):
	Break up [file] into an ensemble. Note that the ensemble is safe in
	itself, but the majority of its subcommands are not.
	* generic/tclFCmd.c (FileCopyRename,TclFileDeleteCmd,TclFileAttrsCmd)
	(TclFileMakeDirsCmd): Adjust these subcommand implementations to work
	inside an ensemble.
	(TclFileLinkCmd, TclFileReadLinkCmd, TclFileTemporaryCmd): Move these
	subcommand implementations from tclCmdAH.c, where they didn't really
	belong.
	* generic/tclIOCmd.c (TclChannelNamesCmd): Move to more appropriate
	source file.
	* generic/tclEnsemble.c (TclMakeEnsemble): Start of code to make
	partially-safe ensembles. Currently does not function as expected due
	to various shortcomings in how safe interpreters are constructed.
	* tests/cmdAH.test, tests/fCmd.test, tests/interp.test: Test updates
	to take into account systematization of error messages.

	* tests/append.test, tests/appendComp.test: Clean up tests so that
	they don't leave things in the global environment (detected when doing
	-singleproc testing).

2010-12-07  Donal K. Fellows  <dkf@users.sf.net>

	* tests/fCmd.test, tests/safe.test, tests/uplevel.test,
	* tests/upvar.test, tests/var.test: Convert more tests to tcltest2 and
	factor them to be easier to understand.

	* generic/tclStrToD.c: Tidy up code so that more #ifdef-fery is
	quarantined at the front of the file and function headers follow the
	modern Tcl style.

2010-12-06  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclBinary.c:  [Bug 3129448]: Possible over-allocation on
	* generic/tclCkalloc.c: 64-bit platforms.
	* generic/tclTrace.c:

2010-12-05  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tcl.m4: [Patch 3116490]: Cross-compile support for unix
	* unix/configure: (autoconf-2.59)

2010-12-03  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclUtil.c (TclReToGlob): Add extra check for multiple inner
	*s that leads to poor recursive glob matching, defer to original RE
	instead.  tclbench RE var backtrack.

2010-12-03  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclUtil.c:   Silence gcc warning when using -Wwrite-strings
	* generic/tclStrToD.c: Silence gcc warning for non-IEEE platforms
	* win/Makefile.in:  [Patch 3116490]: Cross-compile Tcl mingw32 on unix
	* win/tcl.m4:       This makes it possible to cross-compile Tcl/Tk for
	* win/configure.in: Windows (either 32-bit or 64-bit) out-of-the-box
	* win/configure:    on UNIX, using mingw-w64 build tools (If Itcl,
	tdbc and Thread take over the latest tcl.m4, they can do that too).

2010-12-01  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclStrToD.c (SetPrecisionLimits, TclDoubleDigits):
	[Bug 3124675]: Added meaningless initialization of 'i', 'ilim' and
	'ilim1' to silence warnings from the C compiler about possible use of
	uninitialized variables, Added a panic to the 'switch' that assigns
	them, to assert that the 'default' case is impossible.

2010-12-01  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclBasic.c: Fix gcc 64-bit warnings: cast from pointer to
	* generic/tclHash.c:  integer of different size.
	* generic/tclTest.c:
	* generic/tclThreadTest.c:
	* generic/tclStrToD.c: Fix gcc(-4.5.2) warning: 'static' is not at
	beginning of declaration.
	* generic/tclPanic.c: Allow Tcl_Panic() to enter the debugger on win32
	* generic/tclCkalloc.c: Use Tcl_Panic() in stead of duplicating the
	code.

2010-11-30  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclInt.decls, generic/tclInt.h, generic/tclIntDecls.h:
	* generic/tclStubInit.c: TclFormatInt restored at slot 24
	* generic/tclUtil.c (TclFormatInt): restore TclFormatInt func from
	2005-07-05 macro-ization. Benchmarks indicate it is faster, as a key
	int->string routine (e.g. int-indexed arrays).

2010-11-29 Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclBasic.c: Patch by Miguel, providing a
	[::tcl::unsupported::inject coroname command args], which prepends
	("injects") arbitrary code to a suspended coro's future resumption.
	Neat for debugging complex coros without heavy instrumentation.

2010-11-29  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclStrToD.c:
	* generic/tclTest.c:
	* generic/tclTomMath.decls:
	* generic/tclUtil.c:
	* tests/util.test:
	* unix/Makefile.in:
	* win/Makefile.in:
	* win/makefile.vc: Rewrite of Tcl_PrintDouble and TclDoubleDigits that
	(a) fixes a severe performance problem with floating point shimmering
	reported by Karl Lehenbauer, (b) allows TclDoubleDigits to generate
	the digit strings for 'e' and 'f' format, so that it can be used for
	tcl_precision != 0 (and possibly later for [format]), (c) fixes [Bug
	3120139] by making TclPrintDouble inherently locale-independent, (d)
	adds test cases to util.test for correct rounding in difficult cases
	of TclDoubleDigits where fixed- precision results are requested. (e)
	adds test cases to util.test for the controversial aspects of [Bug
	3105247]. As a side effect, two more modules from libtommath
	(bn_mp_set_int.c and bn_mp_init_set_int.c) are brought into the build,
	since the new code uses them.

	* generic/tclIntDecls.h:
	* generic/tclStubInit.c:
	* generic/tclTomMathDecls.h:	Regenerated.

2010-11-24  Donal K. Fellows  <dkf@users.sf.net>

	* tests/chanio.test, tests/iogt.test, tests/ioTrans.test: Convert more
	tests to tcltest2 and factor them to be easier to understand.

2010-11-20  Donal K. Fellows  <dkf@users.sf.net>

	* tests/chanio.test: Converted many tests to tcltest2 by marking the
	setup and cleanup parts as such.

2010-11-19  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWin32Dll.c: Fix gcc warnings: unused variable 'registration'
	* win/tclWinChan.c:
	* win/tclWinFCmd.c:

2010-11-18  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclAppInit.c: [FRQ 491789]: "setargv() doesn't support a unicode
	cmdline" now implemented for cygwin and mingw32 too.
	* tests/main.test: No longer disable tests Tcl_Main-1.4 and 1.6 on
	Windows, because those now work on all supported platforms.
	* win/configure.in:  Set NO_VIZ=1 when zlib is compiled in libtcl,
	this resolves compiler warnings in 64-bit and static builds.
	* win/configure (regenerated)

2010-11-18  Donal K. Fellows  <dkf@users.sf.net>

	* doc/file.n: [Bug 3111298]: Typofix.

	* tests/oo.test: [Bug 3111059]: Added testing that neatly trapped this
	issue.

2010-11-18  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclNamesp.c: [Bug 3111059]: Fix leak due to bad looping
	construct.

2010-11-17  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tcl.m4: [FRQ 491789]: "setargv() doesn't support a unicode
	cmdline" now implemented for mingw-w64
	* win/configure    (re-generated)

2010-11-16  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclAppInit.c:Bring compilation under mingw-w64 a bit closer
	* win/cat.c:       to reality. See for what's missing:
	* win/tcl.m4:      <https://sourceforge.net/apps/trac/mingw-w64/wiki/Unicode%20apps>
	* win/configure:   (re-generated)
	* win/tclWinPort.h: [Bug 3110161]: Extensions using TCHAR don't
	compile on VS2005 SP1

2010-11-15  Andreas Kupries  <andreask@activestate.com>

	* doc/interp.n: [Bug 3081184]: TIP #378.
	* doc/tclvars.n: Performance fix for TIP #280.
	* generic/tclBasic.c:
	* generic/tclExecute.c:
	* generic/tclInt.h:
	* generic/tclInterp.c:
	* tests/info.test:
	* tests/interp.test:

2010-11-10  Andreas Kupries  <andreask@activestate.com>

	* changes:	Updates for 8.6b2 release.

2010-11-09  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOMethod.c (ProcedureMethodVarResolver): [Bug 3105999]:
	* tests/oo.test:	Make sure that resolver structures that are
				only temporarily needed get squelched.

2010-11-05  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclMain.c: Thanks, Kevin, for the fix, but this how it was
	supposed to be (TCL_ASCII_MAIN is only supposed to be defined on
	WIN32).

2010-11-05  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclMain.c: Added missing conditional on _WIN32 around code
	that messes around with the definition of _UNICODE, to correct a badly
	broken Unix build from Jan's last commit.

2010-11-04  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclDecls.h:	[FRQ 491789]: "setargv() doesn't support a
	* generic/tclMain.c:	unicode cmdline" implemented for Tcl on MSVC++
	* doc/Tcl_Main.3:
	* win/tclAppInit.c:
	* win/makefile.vc:
	* win/Makefile.in:
	* win/tclWin32Dll.c:	Eliminate minor MSVC warning TCHAR -> char
				conversion

2010-11-04  Reinhard Max  <max@suse.de>

	* tests/socket.test: Run the socket tests three times with the address
	family set to any, inet, and inet6 respectively. Use constraints to
	skip the tests if a family is found to be unsupported or not
	configured on the local machine. Adjust the tests to dynamically adapt
	to the address family that is being tested.

	Rework some of the tests to speed them up by avoiding (supposedly)
	unneeded [after]s.

2010-11-04  Stuart Cassoff  <stwo@users.sourceforge.net>

	* unix/Makefile.in:	[Patch 3101127]: Installer Improvements.
	* unix/install-sh:

2010-11-04  Donal K. Fellows  <dkf@users.sf.net>

	* tests/error.test (error-19.13): Another variation on testing for
	issues in [try] compilation.

	* doc/Tcl.n (Variable substitution): [Bug 3099086]: Increase clarity
	of explanation of what characters are actually permitted in variable
	substitutions. Note that this does not constitute a change of
	behavior; it is just an improvement of explanation.

2010-11-04  Don Porter  <dgp@users.sourceforge.net>

	* changes:	Updates for 8.6b2 release.  (Thanks Andreas Kupries)

2010-11-03  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinFcmd.c:    [FRQ 2965056]: Windows build with -DUNICODE
	* win/tclWinFile.c:    (more clean-ups for pre-win2000 stuff)
	* win/tclWinReg.c:

2010-11-03  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdMZ.c (TryPostBody):  Ensure that errors when setting
	* tests/error.test (error-19.1[12]): message/opt capture variables get
					     reflected properly to the caller.

2010-11-03  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclCompCmds.c (TclCompileCatchCmd): [Bug 3098302]:
	* tests/compile.test (compile-3.6): Reworked the compilation of the
	[catch] command so as to avoid placing any code that might throw an
	exception (specifically, any initial substitutions or any stores to
	result or options variables) between the BEGIN_CATCH and END_CATCH but
	outside the exception range.  Added a test case that panics on a stack
	smash if the change is not made.

2010-11-01  Stuart Cassoff  <stwo@users.sourceforge.net>

	* library/safe.tcl:	Improved handling of non-standard module path
	* tests/safe.test:	lists, empty path lists in particular.

2010-11-01  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata/Asia/Hong_Kong:
	* library/tzdata/Pacific/Apia:
	* library/tzdata/Pacific/Fiji:   Olson's tzdata2010o.

2010-10-29  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclTimer.c:	[Bug 2905784]: Stop small [after]s from
				wasting CPU while keeping accuracy.

2010-10-28  Kevin B. Kenny  <kennykb@acm.org>

	[dogeen-assembler-branch]
	* generic/tclAssembly.c:
	* tests/assembly.test (assemble-31.*): Added jump tables.

2010-10-28  Don Porter  <dgp@users.sourceforge.net>

	* tests/http.test:	[Bug 3097490]: Make http-4.15 pass in
				isolation.

	* unix/tclUnixSock.c:	[Bug 3093120]: Prevent calls of
				freeaddrinfo(NULL) which can crash some
				systems.  Thanks Larry Virden.

2010-10-26  Reinhard Max  <max@suse.de>

	* Changelog.2008: Split off from Changelog.
	* generic/tclIOSock.c (TclCreateSocketAddress): The interp != NULL
	check is needed for ::tcl::unsupported::socketAF as well.

2010-10-26  Donal K. Fellows  <dkf@users.sf.net>

	* unix/tclUnixSock.c (TcpGetOptionProc): Prevent crash if interp is
	* win/tclWinSock.c (TcpGetOptionProc):   NULL (a legal situation).

2010-10-26  Reinhard Max  <max@suse.de>

	* unix/tclUnixSock.c (TcpGetOptionProc): Added support for
	::tcl::unsupported::noReverseDNS, which if set to any value, prevents
	[fconfigure -sockname] and [fconfigure -peername] from doing
	reverse DNS queries.

2010-10-24  Kevin B. Kenny  <kennykb@acm.org>

	[dogeen-assembler-branch]
	* generic/tclAssembly.c:
	* tests/assembly.test (assemble-17.15): Reworked branch handling so
	that forward branches can use jump1 (jumpTrue1, jumpFalse1). Added
	test cases that the forward branches will expand to jump4, jumpTrue4,
	jumpFalse4 when needed.

2010-10-23  Kevin B. Kenny  <kennykb@acm.org>

	[dogeen-assembler-branch]
	* generic/tclAssembly.h (removed):
				Removed file that was included in only one
				source file.
	* generictclAssembly.c:	Inlined tclAssembly.h.

2010-10-17  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* doc/info.n:            [Patch 2995655]:
	* generic/tclBasic.c:    Report inner contexts in [info errorstack]
	* generic/tclCompCmds.c:
	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c:
	* generic/tclInt.h:
	* generic/tclNamesp.c:
	* tests/error.test:
	* tests/result.test:

2010-10-20  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileDictForCmd): Update the compilation
	* generic/tclCompile.c (tclInstructionTable):	of [dict for] so that
	* generic/tclExecute.c (TEBCresume):		it no longer makes any
	use of INST_DICT_DONE now that's not needed, and make it clearer in
	the implementation of the instruction that it's just a deprecated form
	of unset operation. Followup to my commit of 2010-10-16.

2010-10-19  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclZlib.c (Tcl_ZlibStreamGet): [Bug 3081008]: Ensure that
	when a bytearray gets its internals entangled with zlib for more than
	a passing moment, that bytearray will never be shimmered away. This
	increases the amount of copying but is simple to get right, which is a
	reasonable trade-off.

	* generic/tclStringObj.c (Tcl_AppendObjToObj): Added some special
	cases so that most of the time when you build up a bytearray by
	appending, it actually ends up being a bytearray rather than
	shimmering back and forth to string.

	* tests/http11.test (check_crc): Use a simpler way to express the
	functionality of this procedure.

	* generic/tclZlib.c: Purge code that wrote to the object returned by
	Tcl_GetObjResult, as we don't want to do that anti-pattern no more.

2010-10-18  Jan Nijtmans  <nijtmans@users.sf.net>

	* tools/uniParse.tcl:   [Bug 3085863]: tclUniData was 9 years old;
	Ignore non-BMP characters and fix comment about UnicodeData.txt file.
	* generic/regcomp.c:    Fix comment
	* tests/utf.test:       Add some Unicode 6 testcases

2010-10-17  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* doc/info.n:           Document [info errorstack] faithfully.

2010-10-16  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclExecute.c (ReleaseDictIterator): Factored out the release
	of the bytecode-level dictionary iterator information so that the
	side-conditions on instruction issuing are simpler.

2010-10-15  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/reg_locale.c: [Bug 3085863]: tclUniData 9 years old: Updated
	* generic/tclUniData.c: Unicode tables to latest UnicodeData.txt,
	* tools/uniParse.tcl:   corresponding with Unicode 6.0 (except for
				out-of-range chars > 0xFFFF)

2010-10-13  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompile.c:	Alternative fix for [Bugs 467523,983660] where
	* generic/tclExecute.c:	sharing of empty scripts is allowed again.

2010-10-13  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinThrd.h: (removed) because it is just empty en used nowhere
	* win/tcl.dsp

2010-10-12  Jan Nijtmans  <nijtmans@users.sf.net>

	* tools/uniClass.tcl:    Spacing and comments: let uniClass.tcl
	* generic/regc_locale.c: generation match better the current
				 (hand-modified) regc_locale.c
	* tools/uniParse.tcl:    Generate proper const qualifiers for
	* generic/tclUniData.c:  tclUniData.c

2010-10-12  Reinhard Max  <max@suse.de>

	* unix/tclUnixSock.c (CreateClientSocket): [Bug 3084338]: Fix a
	memleak and refactor the calls to freeaddrinfo().

2010-10-11  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinDde.c:    [FRQ 2965056]: Windows build with -DUNICODE
	* win/tclWinReg.c:
	* win/tclWinTest.c:   More cleanups
	* win/tclWinFile.c:   Add netapi32 to the link line, so we no longer
	* win/tcl.m4:         have to use LoadLibrary to access those
			      functions.
	* win/makefile.vc:
	* win/configure:      (Re-generate with autoconf-2.59)
	* win/rules.vc        Update for VS10

2010-10-09  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: Fix overallocation of exec stack in TEBC (due
	to mixing numwords and numbytes)

2010-10-08  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclIOSock.c: On Windows, use gai_strerrorA

2010-10-06  Don Porter  <dgp@users.sourceforge.net>

	* tests/winPipe.test:	Test hygiene with makeFile and removeFile.

	* generic/tclCompile.c:	[Bug 3081065]: Prevent writing to the intrep
	* tests/subst.test:	fields of a freed Tcl_Obj.

2010-10-06  Kevin B. Kenny  <kennykb@acm.org>

	[dogeen-assembler-branch]

	* generic/tclAssembly.c:
	* generic/tclAssembly.h:
	* tests/assemble.test: Added catches. Still needs a lot of testing.

2010-10-02  Kevin B. Kenny  <kennykb@acm.org>

	[dogeen-assembler-branch]

	* generic/tclAssembly.c:
	* generic/tclAssembly.h:
	* tests/assemble.test: Added dictAppend, dictIncrImm, dictLappend,
	dictSet, dictUnset, nop, regexp, nsupvar, upvar, and variable.

2010-10-02  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclExecute.c (TEBCresume): [Bug 3079830]: Added invalidation
	of string representations of dictionaries in some cases.

2010-10-01  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclExecute.c (EvalStatsCmd): change 'evalstats' to return
	data to interp by default, or if given an arg, use that as filename to
	output to (accepts 'stdout' and 'stderr').  Fix output to print used
	inst count data.
	* generic/tclCkalloc.c: Change TclDumpMemoryInfo sig to allow objPtr
	* generic/tclInt.decls: as well as FILE* as output.
	* generic/tclIntDecls.h:

2010-10-01  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclBasic.c, generic/tclClock.c, generic/tclEncoding.c,
	* generic/tclEnv.c, generic/tclLoad.c, generic/tclNamesp.c,
	* generic/tclObj.c, generic/tclRegexp.c, generic/tclResolve.c,
	* generic/tclResult.c, generic/tclUtil.c, macosx/tclMacOSXFCmd.c:
	More purging of strcpy() from locations where we already know the
	length of the data being copied.

2010-10-01  Kevin B. Kenny  <kennykb@acm.org>

	[dogeen-assembler-branch]

	* tests/assemble.test:
	* generic/tclAssemble.h:
	* generic/tclAssemble.c:  Added listIn, listNotIn, and dictGet.

2010-09-30  Kevin B. Kenny  <kennykb@acm.org>

	[dogeen-assembler-branch]

	* tests/assemble.test:   Added tryCvtToNumeric and several more list
	* generic/tclAssemble.c: operations.
	* generic/tclAssemble.h:

2010-09-29  Kevin B. Kenny  <kennykb@acm.org>

	[dogeen-assembler-branch]

	* tests/assemble.test:   Completed conversion of tests to a
	* generic/tclAssemble.c: "white box" structure that follows the
	C code. Added missing safety checks on the operands of 'over' and
	'reverse' so that negative operand counts don't smash the stack.

2010-09-29  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/configure:	Re-generate with autoconf-2.59
	* win/configure:
	* generic/tclMain.c:	Make compilable with -DUNICODE as well

2010-09-28  Reinhard Max  <max@suse.de>

	TIP #162 IMPLEMENTATION

	* doc/socket.n:		Document the changes to the [socket] and
				[fconfigure] commands.

	* generic/tclInt.h:	Introduce TclCreateSocketAddress() as a
	* generic/tclIOSock.c:	replacement for the platform-dependent
	* unix/tclUnixSock.c:	TclpCreateSocketAddress() functions. Extend
	* unix/tclUnixChan.c:	the [socket] and [fconfigure] commands to
	* unix/tclUnixPort.h:	behave as proposed in TIP #162. This is the
	* win/tclWinSock.c:	core of what is required to support the use of
	* win/tclWinPort.h:	IPv6 sockets in Tcl.

	* compat/fake-rfc2553.c: A compat implementation of the APIs defined
	* compat/fake-rfc2553.h: in RFC-2553 (getaddrinfo() and friends) on
				 top of the existing gethostbyname() etc.
	* unix/configure.in:	 Test whether the fake-implementation is
	* unix/tcl.m4:		 needed.
	* unix/Makefile.in:	 Add a compile target for fake-rfc2553.

	* win/configure.in:	Allow cross-compilation by default.

	* tests/socket.test:	Improve the test suite to make more use of
	* tests/remote.tcl:	randomized ports to reduce interference with
				tests running in parallel or other services on
				the machine.

2010-09-28  Kevin B. Kenny  <kennykb@acm.org>

	[dogeen-assembler-branch]

	* tests/assemble.test: Added more "white box" tests.
	* generic/tclAssembly.c: Added the error checking and reporting
	for undefined labels. Revised code so that no pointers into the
	bytecode sequence are held (because the sequence can move!),
	that no Tcl_HashEntry pointers are held (because the hash table
	doesn't guarantee their stability!) and to eliminate the BBHash
	table, which is merely additional information indexed by jump
	labels and can just as easily be held in the 'label' structure.
	Renamed shared structures to CamelCase, and renamed 'label' to
	JumpLabel because other types of labels may eventually be possible.

2010-09-27  Kevin B. Kenny  <kennykb@acm.org>

	[dogeen-assembler-branch]

	* tests/assemble.test: Added more "white box" tests.
	* generic/tclAssembly.c: Fixed bugs exposed by the new tests.
	(a) [eval] and [expr] had incorrect stack balance computed if
	the arg was not a simple word. (b) [concat] accepted a negative
	operand count. (c) [invoke] accepted a zero or negative operand
	count. (d) more misspelt error messages.
	Also replaced a funky NRCallTEBC with the new call
	TclNRExecuteByteCode, necessitated by a merge with changes on the
	HEAD.

2010-09-26  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:    [Patch 3072080] (minus the itcl
	* generic/tclCmdIL.c:    update): a saner NRE.
	* generic/tclCompExpr.c:
	* generic/tclCompile.c:  This makes TclNRExecuteByteCode (ex TEBC)
	* generic/tclCompile.h:  to be a normal NRE citizen: it loses its
	* generic/tclExecute.c:  special status.
	* generic/tclInt.decls:  The logic flow within the BC engine is
	* generic/tclInt.h:      simplified considerably.
	* generic/tclIntDecls.h:
	* generic/tclObj.c:
	* generic/tclProc.c:
	* generic/tclTest.c:

	* generic/tclVar.c: Use the macro HasLocalVars everywhere

2010-09-26  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclOOMethod.c (ProcedureMethodVarResolver): avoid code
	duplication, let the runtime var resolver call the compiled var
	resolver.

2010-09-26  Kevin B. Kenny  <kennykb@acm.org>

	[dogeen-assembler-branch]

	* tests/assemble.test:	Added many new tests moving toward a more
	comprehensive test suite for the assembler.
	* generic/tclAssembly.c:	Fixed bugs exposed by the new tests:
	(a) [bitnot] and [not] had incorrect operand counts. (b)
	INST_CONCAT cannot concatenate zero objects. (c) misspelt error
	messages. (d) the "assembly code" internal representation lacked
	a duplicator, which caused double-frees of the Bytecode object
	if assembly code ever was duplicated.

2010-09-25  Kevin B. Kenny   <kennykb@acm.org>

	[dogeen-assembler-branch]

	* generic/tclAssembly.c:	Massive refactoring of the assembler
	* generic/tclAssembly.h:	to use a Tcl-like syntax (and use
	* tests/assemble.test:		Tcl_ParseCommand to parse it). The
	* tests/assemble1.bench:	refactoring also ensures that
	Tcl_Tokens in the assembler have string ranges inside the source
	code, which allows for [eval] and [expr] assembler directives
	that simply call TclCompileScript and TclCompileExpr recursively.

2010-09-24  Jeff Hobbs  <jeffh@ActiveState.com>

	* tests/stringComp.test: improved string eq/cmp test coverage
	* generic/tclExecute.c (TclExecuteByteCode): merge INST_STR_CMP and
	INST_STR_EQ/INST_STR_NEQ paths.  Speeds up eq/ne/[string eq] with
	obj-aware comparisons and eq/==/ne/!= with length equality check.

2010-09-24  Andreas Kupries  <andreask@activestate.com>

	* tclWinsock.c: [Bug 3056775]: Fixed race condition between thread and
	internal co-thread access of a socket's structure because of the
	thread not using the socketListLock in TcpAccept(). Added
	documentation on how the module works to the top.

2010-09-23  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclDecls.h: Make Tcl_SetPanicProc and Tcl_GetStringResult
	* unix/tclAppInit.c:  callable without stubs, just as Tcl_SetVar.
	* win/tclAppInit.c:

2010-09-23  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCmdAH.c:   Fix cases where value returned by
	* generic/tclEvent.c:   Tcl_GetReturnOptions() was leaked.
	* generic/tclMain.c:    Thanks to Jeff Hobbs for discovery of the
	anti-pattern to seek and destroy.

2010-09-23  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tclAppInit.c:  Make compilable with -DUNICODE (not activated
	* win/tclAppInit.c:   yet), many clean-ups in comments.

2010-09-22  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute: [Bug 3072640]: One more DECACHE_STACK_INFO() was
	missing.

	* tests/execute.test: Added execute-10.3 for [Bug 3072640]. The test
	causes a mem failure.

	* generic/tclExecute: Protect all possible writes to ::errorInfo or
	::errorCode with DECACHE_STACK_INFO(), as they could run traces. The
	new calls to be protected are Tcl_ResetResult(), Tcl_SetErrorCode(),
	IllegalExprOperandType(), TclExprFloatError(). The error was triggered
	by [Patch 3072080].

2010-09-22  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tcl.m4:		Add kernel32 to LIBS, so the link line for
	* win/configure:	mingw is exactly the same as for MSVC++.

2010-09-21  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclExecute.c (TclExecuteByteCode):
	* generic/tclOOMethod.c (ProcedureMethodCompiledVarConnect):
	* generic/tclVar.c (TclLookupSimpleVar, CompareVarKeys):
	* generic/tclPathObj.c (Tcl_FSGetNormalizedPath, Tcl_FSEqualPaths):
	* generic/tclIOUtil.c (TclFSCwdPointerEquals): peephole opt
	* generic/tclResult.c (TclMergeReturnOptions): Use memcmp where
	applicable as possible speedup on some libc variants.

2010-09-21  Kevin B. Kenny  <kennykb@acm.org>

	[BRANCH: dogeen-assembler-branch]

	* generic/tclAssembly.c (new file):
	* generic/tclAssembly.h:
	* generic/tclBasic.c (builtInCmds, Tcl_CreateInterp):
	* generic/tclInt.h:
	* tests/assemble.test (new file):
	* tests/assemble1.bench (new file):
	* unix/Makefile.in:
	* win/Makefile.in:
	* win/Makefile.vc:
		Initial commit of Ozgur Dogan Ugurlu's (SF user: dogeen)
		assembler for the Tcl bytecode language.

2010-09-21  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinFile.c:   Fix declaration after statement.
	* win/tcl.m4:         Add -Wdeclaration-after-statement, so this
	* win/configure:      mistake cannot happen again.
	* win/tclWinFCmd.c:   [Bug 3069278]: Breakage on head Windows
	* win/tclWinPipe.c:   triggered by install-tzdata, final fix

2010-09-20  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinFCmd.c: Eliminate tclWinProcs->useWide everywhere, since
	* win/tclWinFile.c: the value is always "1" on platforms >win95
	* win/tclWinPipe.c:

2010-09-19  Donal K. Fellows  <dkf@users.sf.net>

	* doc/file.n (file readlink): [Bug 3070580]: Typofix.

2010-09-18  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinFCmd.c [Bug 3069278]: Breakage on head Windows triggered
	by install-tzdata. Temporary don't compile this with -DUNICODE, while
	investigating this bug.

2010-09-16  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/tclWinFile.c: Remove define of FINDEX_INFO_LEVELS as all
	supported versions of compilers should now have it.

	* unix/Makefile.in: Do not pass current build env vars when using
	NATIVE_TCLSH in targets.

2010-09-16  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclDecls.h:    Make Tcl_FindExecutable() work in UNICODE
	* generic/tclEncoding.c: compiles (windows-only) as well as ASCII.
	* generic/tclStubInit.c: Needed for [FRQ 491789]: setargv() doesn't
	support a unicode cmdline.

2010-09-15  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclBinary.c (TclAppendBytesToByteArray): [Bug 3067036]: Make
	sure we never try to double zero repeatedly to get a buffer size. Also
	added a check for sanity on the size of buffer being appended.

2010-09-15  Don Porter  <dgp@users.sourceforge.net>

	* unix/Makefile.in:	Revise `make dist` target to tolerate the
	case of zero bundled packages.

2010-09-15  Jan Nijtmans  <nijtmans@users.sf.net>

	* tools/genStubs.tcl:   [Patch 3034251]: Backport ttkGenStubs.tcl
	* generic/tcl.decls:    features to genStubs.tcl. Make the "generic"
	* generic/tclInt.decls: argument in the *.decls files optional
	* generic/tclOO.decls:  (no change to any tcl*Decls.h files)
	* generic/tclTomMath.decls:
	This allows genStubs.tcl to generate the ttk stub files as well, while
	keeping full compatibility with existing *.decls files.

2010-09-14  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinPort.h:  Allow all Win2000+ API entries in Tcl
	* win/tclWin32Dll.c: Eliminate dynamical loading of advapi23 and
	kernel32 symbols.

2010-09-13  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinChan.c:      Various clean-ups, converting from
	* win/tclWinConsole.c:   tclWinProc->xxxProc directly to Xxx
	* win/tclWinInit.c:      (no change in functionality)
	* win/tclWinLoad.c:
	* win/tclWinSerial.c:
	* win/tclWinSock.c:
	* tools/genStubs.tcl:    Add scspec feature from ttkGenStubs.tcl
	  (no change in output for *Decls.h files)

2010-09-10  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWin32Dll.c: Partly revert yesterday's change, to make it work
	on VC++ 6.0 again.

2010-09-10  Donal K. Fellows  <dkf@users.sf.net>

	* doc/regsub.n: [Bug 3063568]: Fix for gotcha in example due to Tcl's
	special handling of backslash-newline. Makes example slightly less
	pure, but more useful.

2010-09-09  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/makefile.vc:   Mingw should always link with -ladvapi32.
	* win/tcl.m4:
	* win/configure:     (regenerated)
	* win/tclWinInt.h:   Remove ascii variant of tkWinPocs table, it is
	* win/tclWin32Dll.c: no longer necessary. Fix CreateProcess signature
	* win/tclWinPipe.c:  and remove unused GetModuleFileName and lstrcpy.
	* win/tclWinPort.h:  Mingw/cygwin fixes: <tchar.h> should always be
	included, and fix conflict in various macro values: Always force the
	same values as in VC++.

2010-09-08  Don Porter  <dgp@users.sourceforge.net>

	* win/tclWinChan.c:	[Bug 3059922]: #ifdef protections to permit
	* win/tclWinFCmd.c:     builds with mingw on amd64 systems. Thanks to
				"mescalinum" for reporting and testing.

2010-09-08  Andreas Kupries  <andreask@activestate.com>

	* doc/tm.n: Added underscore to the set of characters accepted in
	module names. This is true for quite some time in the code, this
	change catches up the documentation.

2010-09-03  Donal K. Fellows  <dkf@users.sf.net>

	* tools/tcltk-man2html.tcl (plus-pkgs): Improve the package
	documentation search pattern to support the doctoos-generated
	directory structure.
	* tools/tcltk-man2html-utils.tcl (output-name): Made this more
	resilient against misformatted NAME sections, induced by import of
	Thread package documentation into Tcl doc tree.

2010-09-02  Andreas Kupries  <andreask@activestate.com>

	* doc/glob.n: Fixed documentation ambiguity regarding the handling
	of -join.

	* library/safe.tcl (safe::AliasGlob): Fixed another problem, the
	option -join does not stop option processing in the core builtin, so
	the emulation must not do that either.

2010-09-01  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* library/safe.tcl (safe::AliasGlob): Moved the command extending the
	actual glob command with a -directory flag to when we actually have a
	proper untranslated path,

2010-09-01  Andreas Kupries  <andreask@activestate.com>

	* generic/tclExecute.c: [Bug 3057639]: Applied patch by Jeff to make
	* generic/tclVar.c:	the behaviour of lappend in bytecompiled mode
	* tests/append.test:	consistent with direct-eval and 'append'
	* tests/appendComp.test: generally. Added tests (append*-9.*)
	showing the difference.

2010-08-31  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/rules.vc:               Typo (thanks to Twylite discovering
				      this)
	* generic/tclStubLib.c:       Revert to previous version: MSVC++ 6.0
	* generic/tclTomMathStubLib.c:cannot handle the new construct.
	* generic/tcl.decls           [Patch 2997642]: Many type casts needed
	* generic/tclDecls.h:         when using Tcl_Pkg* API. Remaining part.
	* generic/tclPkg.c:
	* generic/tclBasic.c:
	* generic/tclTomMathInterface.c:
	* doc/PkgRequire.3

2010-08-31  Andreas Kupries  <andreask@activestate.com>

	* win/tcl.m4: Applied patch by Jeff fixing issues with the manifest
	handling on Win64.
	* win/configure: Regenerated.

2010-08-30  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:    [Bugs 3046594,3047235,3048771]: New
	* generic/tclCmdAH.c:    implementation for [tailcall] command: it now
	* generic/tclCmdMZ.c:    schedules the command and returns TCL_RETURN.
	* generic/tclExecute.c:  This fixes all issues with [catch] and [try].
	* generic/tclInt.h:      Thanks dgp for exploring the dark corners.
	* generic/tclNamesp.c:   More thorough testing is required.
	* tests/tailcall.test:

2010-08-30  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/Makefile.in:   [FRQ 2965056]: Windows build with -DUNICODE
	* win/rules.vc:
	* win/tclWinFCmd.c:  Make sure that allocated TCHAR arrays are
	* win/tclWinFile.c:  always properly aligned as wchar_t, and
	* win/tclWinPipe.c:  not bigger than necessary.
	* win/tclWinSock.c:
	* win/tclWinDde.c:   Those 3 files are not converted yet to be
	* win/tclWinReg.c:   built with -DUNICODE, so add a TODO.
	* win/tclWinTest.c:
	* generic/tcl.decls:  [Patch 2997642]: Many type casts needed when
	* generic/tclDecls.h: using Tcl_Pkg* API. Partly.
	* generic/tclPkg.c:
	* generic/tclStubLib.c: Demonstration how this change can benefit
				code.
	* generic/tclTomMathStubLib.c:
	* doc/PkgRequire.3:

2010-08-29  Donal K. Fellows  <dkf@users.sf.net>

	* doc/dict.n: [Bug 3046999]: Corrected cross reference to array
	manpage to refer to (correct) existing subcommand.

2010-08-26  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/configure, unix/tcl.m4: SHLIB_LD_LIBS='${LIBS}' for OSF1-V*.
	Add /usr/lib64 to set of auto-search dirs. [Bug 1230554]
	(SC_PATH_X): Correct syntax error when xincludes not found.

	* win/Makefile.in (VC_MANIFEST_EMBED_DLL VC_MANIFEST_EMBED_EXE):
	* win/configure, win/configure.in, win/tcl.m4: SC_EMBED_MANIFEST
	macro and --enable-embedded-manifest configure arg added to support
	manifest embedding where we know the magic.  Help prevents DLL hell
	with MSVC8+.

2010-08-24  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.decls: [Bug 3007895]: Tcl_(Find|Create)HashEntry
	* generic/tclHash.c: stub entries can never be called.
	* generic/tclDecls.h:
	* generic/tclStubInit.c: [Patch 2994165]: Change signature of
	Tcl_FSGetNativePath and TclpDeleteFile follow-up: move stub entry back
	to original location.

2010-08-23  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata/Africa/Cairo:
	* library/tzdata/Asia/Gaza: Olson's tzdata2010l.

2010-08-22  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclBasic.c:  [Patch 3009403]: Signature of Tcl_GetHashKey,
	* generic/tclBinary.c: Tcl_(Create|Find)HashEntry follow-up:
	* generic/tclCmdIL.c:  Remove many type casts which are no longer
	* generic/tclCompile.c:necessary as a result of this signature change.
	* generic/tclDictObj.c:
	* generic/tclEncoding.c:
	* generic/tclExecute.c:
	* generic/tclInterp.c:
	* generic/tclIOCmd.c:
	* generic/tclObj.c:
	* generic/tclProc.c:
	* generic/tclTest.c:
	* generic/tclTrace.c:
	* generic/tclUtil.c:
	* generic/tclVar.c:

2010-08-21  Donal K. Fellows  <dkf@users.sf.net>

	* doc/linsert.n: [Bug 3045123]: Make description of what is actually
	happening more accurate.

2010-08-21  Jan Nijtmans  <nijtmans@users.sf.net>

	* tools/genStubs.tcl: [Patch 3034251]: Backport ttkGenStubs.tcl
	features to genStubs.tcl, partly: Use void (*reserved$i)(void) = 0
	instead of void *reserved$i = NULL for unused stub entries, in case
	pointer-to-function and pointer-to-object are different sizes.
	* generic/tcl*Decls.h:   (regenerated)
	* generic/tcl*StubInit.c:(regenerated)

2010-08-20  Jan Nijtmans  <nijtmans@users.sf.net>

	* doc/Method.3:   Fix definition of Tcl_MethodType.

2010-08-19  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclTrace.c (TraceExecutionObjCmd, TraceCommandObjCmd)
	(TraceVariableObjCmd): [Patch 3048354]: Use memcpy() instead of
	strcpy() to avoid buffer overflow; we have the correct length of data
	to copy anyway since we've just allocated the target buffer.

2010-08-18  Jan Nijtmans  <nijtmans@users.sf.net>

	* tools/genStubs.tcl: [Patch 3034251]: Backport ttkGenStubs.tcl
	features to genStubs.tcl, partly: remove unneeded ifdeffery and put
	C++ guard around stubs pointer definition.
	* generic/*Decls.h:   (regenerated)

2010-08-18  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:   New redesign of [tailcall]: find
	* generic/tclExecute.c: errors early on, so that errorInfo
	* generic/tclInt.h:     contains the proper info [Bug 3047235]
	* generic/tclNamesp.c:

	* generic/tclCmdAH.c (TclNRTryObjCmd): [Bug 3046594]: Block
	tailcalling out of the body of a non-bc'ed [try].

	* generic/tclBasic.c:    Redesign of [tailcall] to
	* generic/tclCmdAH.c:    (a) fix [Bug 3047235]
	* generic/tclCompile.h:  (b) enable fix for [Bug 3046594]
	* generic/tclExecute.c:  (c) enable recursive tailcalls
	* generic/tclInt.h:
	* generic/tclNamesp.c:
	* tests/tailcall.test:

2010-08-18  Donal K. Fellows  <dkf@users.sf.net>

	* library/safe.tcl (AliasGlob): [Bug 3004191]: Restore safe [glob] to
	working condition.

2010-08-15  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclProc.c (ProcWrongNumArgs): [Bug 3045010]: Make the
	handling of passing the wrong number of arguments to [apply] somewhat
	less verbose when a lambda term is present.

2010-08-14  Jan Nijtmans  <nijtmans@users.sf.net>

	* compat/unicows:    Remove completely, see [FRQ 2819611].
	* doc/FileSystem.3: [Patch 2994165]: Change signature of
	* generic/tcl.decls  Tcl_FSGetNativePath and TclpDeleteFile
	* generic/tclDecls.h:
	* generic/tclIOUtil.c:
	* generic/tclStubInit.c:
	* generic/tclInt.h:
	* unix/tclUnixFCmd.c:
	* win/tclWinFCmd.c:
	* doc/Hash.3: [Patch 3009403]: Signature of Tcl_GetHashKey,
	* generic/tcl.h:     Tcl_(Create|Find)HashEntry

2010-08-11  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/ldAix: Remove ancient (pre-4.2) AIX support
	* unix/configure: Regen with ac-2.59
	* unix/configure.in, unix/tclConfig.sh.in, unix/Makefile.in:
	* unix/tcl.m4 (AIX): Remove the need for ldAIX, replace with
	-bexpall/-brtl.  Remove TCL_EXP_FILE (export file) and other baggage
	that went with it.  Remove pre-4 AIX build support.

2010-08-11  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c (TclNRYieldToObjCmd):
	* tests/coroutine.test: Fixed bad copypasta snafu. Thanks to Andy Goth
	for finding the bug.

2010-08-10  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclUtil.c (TclByteArrayMatch): Patterns may not be
	null-terminated, so account for that.

2010-08-09  Don Porter  <dgp@users.sourceforge.net>

	* changes:	Updates for 8.6b2 release.

2010-08-04  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/Makefile.in, win/makefile.bc, win/makefile.vc, win/tcl.dsp:
	* win/tclWinPipe.c (TclpCreateProcess):
	* win/stub16.c (removed): Removed Win9x tclpip8x.dll build and 16-bit
	application loader stub support.  Win9x is no longer supported.

	* win/tclWin32Dll.c (TclWinInit): Hard-enforce Windows 9x as an
	unsupported platform with a panic.  Code to support it still exists in
	other files (to go away in time), but new APIs are being used that
	don't exist on Win9x.

	* unix/tclUnixFCmd.c: Adjust license header as per
	ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change

	* license.terms: Fix DFARs note for number-adjusted rights clause

	* win/tclWin32Dll.c (asciiProcs, unicodeProcs):
	* win/tclWinLoad.c (TclpDlopen): 'load' use LoadLibraryEx with
	* win/tclWinInt.h (TclWinProcs): LOAD_WITH_ALTERED_SEARCH_PATH to
	prefer dependent DLLs in same dir as loaded DLL.

	* win/Makefile.in (%.${OBJEXT}): better implicit rules support

2010-08-04  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIORChan.c: [Bug 3034840]: Fixed reference counting in
	* generic/tclIORTrans.c: InvokeTclMethod and callers.
	* tests/ioTrans.test:

2010-08-03  Andreas Kupries  <andreask@activestate.com>

	* tests/var.test (var-19.1): [Bug 3037525]: Added test demonstrating
	the local hashtable deletion crash and fix.

	* tests/info.test (info-39.1): Added forward copy of test in 8.5
	branch about [Bug 2933089]. Should not fail, and doesn't, after
	updating the line numbers to the changed position.

2010-08-02  Kevin B. Kenny  <kennykb@users.sf.net>

	* library/tzdata/America/Bahia_Banderas:
	* library/tzdata/Pacific/Chuuk:
	* library/tzdata/Pacific/Pohnpei:
	* library/tzdata/Africa/Cairo:
	* library/tzdata/Europe/Helsinki:
	* library/tzdata/Pacific/Ponape:
	* library/tzdata/Pacific/Truk:
	* library/tzdata/Pacific/Yap:			Olson's tzdata2010k.

2010-08-02  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclVar.c: Correcting bad port of [Bug 3037525] fix

2010-07-28  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclVar.c: [Bug 3037525]: Lose fickle optimisation in
	TclDeleteVars (used for runtime-created locals) that caused crash.

2010-07-29  Jan Nijtmans  <nijtmans@users.sf.net>

	* compat/zlib/win32/README.txt: Official build of zlib1.dll 1.2.5 is
	* compat/zlib/win32/USAGE.txt:  finally available, so put it in.
	* compat/zlib/win32/zlib1.dll:

2010-07-25  Donal K. Fellows  <dkf@users.sf.net>

	* doc/http.n: Corrected description of location of one of the entries
	in the state array.

2010-07-24  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclDecls.h: [Bug 3029891]: Functions that don't belong in
	* generic/tclTest.c:  the stub table.
	* generic/tclBasic.c: From [Bug 3030870] make itcl 3.x built with
	pre-8.6 work in 8.6: Relax the relation between Tcl_CallFrame and
	CallFrame.

2010-07-16  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclBasic.c: Added more errorCode setting.

2010-07-15  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclExecute.c (TclExecuteByteCode): Ensure that [dict get]
	* generic/tclDictObj.c (DictGetCmd): always generates an errorCode on
	a failure to look up an entry.

2010-07-11  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* unix/configure: (regenerated)
	* unix/configure.in: For the NATIVE_TCLSH variable use the autoconf
	* unix/Makefile.in:  SC_PROG_TCLSH to try and find a locally installed
	native binary. This avoids manually fixing up when cross compiling. If
	there is not one, revert to using the build product.

2010-07-02  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInt.decs:	Reverted to the original TIP 337
	implementation on what to do with the obsolete internal stub for
	TclBackgroundException() (eliminate it!)
	* generic/tclIntDecls.h:	make genstubs
	* generic/tclStubInit.c:

2010-07-02  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.decls:  [Bug 803489]: Tcl_FindNamespace problem in
	* generic/tclIntDecls.h: the Stubs table
	* generic/tclStubInit.c:

2010-07-02  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclExecute.c (IllegalExprOperandType): [Bug 3024379]: Made
	sure that errors caused by an argument to an operator being outside
	the domain of the operator all result in ::errorCode being ARITH
	DOMAIN and not NONE.

2010-07-01  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/rules.vc:              [Bug 3020677]: wish can't link reg1.2
	* tools/checkLibraryDoc.tcl: formatting, spacing, cleanup unused
	* tools/eolFix.tcl:          variables; no change in generated output
	* tools/fix_tommath_h.tcl:
	* tools/genStubs.tcl:
	* tools/index.tcl:
	* tools/man2help2.tcl:
	* tools/regexpTestLib.tcl:
	* tools/tsdPerf.tcl:
	* tools/uniClass.tcl:
	* tools/uniParse.tcl:

2010-07-01  Donal K. Fellows  <dkf@users.sf.net>

	* doc/mathop.n: [Bug 3023165]: Fix typo that was preventing proper
	rendering of the exclusive-or operator.

2010-06-28  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclPosixStr.c: [Bug 3019634]: errno.h and tclWinPort.h have
	conflicting definitions. Added messages for ENOTRECOVERABLE, EOTHER,
	ECANCELED and EOWNERDEAD, and fixed various typing mistakes in other
	messages.

2010-06-25  Reinhard Max  <max@suse.de>

	* tests/socket.test: Prevent a race condition during shutdown of the
	remote test server that can cause a hang when the server is being run
	in verbose mode.

2010-06-24  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinPort.h: [Bug 3019634]: errno.h and tclWinPort.h have
	conflicting definitions.

		***POTENTIAL INCOMPATIBILITY***
	On win32, the correspondence between errno and the related error
	message, as handled by Tcl_ErrnoMsg() changes. The error message is
	kept the same, but the corresponding errno value might change.

2010-06-22  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdIL.c (Tcl_LsetObjCmd): [Bug 3019351]: Corrected wrong
	args message.

2010-06-21  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tclLoadDl.c:    Eliminate various unnecessary type casts, use
	* unix/tclLoadNext.c:  function typedefs whenever possible
	* unix/tclUnixChan.c:
	* unix/tclUnixFile.c:
	* unix/tclUnixNotfy.c:
	* unix/tclUnixSock.c:
	* unix/tclUnixTest.c:
	* unix/tclXtTest.c:
	* generic/tclZlib.c:   Remove hack needed for zlib 1.2.3 on win32

2010-06-18  Donal K. Fellows  <dkf@users.sf.net>

	* library/init.tcl (auto_execok): [Bug 3017997]: Add .cmd to the
	default list of extensions that we can execute interactively.

2010-06-16  Jan Nijtmans  <nijtmans@users.sf.net>

	* tools/loadICU.tcl:   [Bug 3016135]: Traceback using clock format
	* library/msgs/he.msg: with locale of he_IL.

	* generic/tcl.h:       Simplify Tcl_AppInit and *_Init definitions,
	* generic/tclInt.h:    spacing. Change TclpThreadCreate and
	* generic/tcl.decls:   Tcl_CreateThread signature, making clear that
	* generic/tclDecls.h:  "proc" is a function pointer, as in all other
	* generic/tclEvent.c:  "proc" function parameters.
	* generic/tclTestProcBodyObj.c:
	* win/tclWinThrd.c:
	* unix/tclUnixThrd.c:
	* doc/Thread.3:
	* doc/Class.3:         Fix Tcl_ObjectMetadataType definition.

2010-06-14  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/Makefile.in:    Fix compilation of xttest with 8.6 changes
	* unix/tclXtNotify.c:
	* unix/tclXtTest.c:
	* generic/tclPipe.c:   Fix gcc warning (with -fstrict-aliasing=2)
	* library/auto.tcl:    Spacing and style fixes.
	* library/history.tcl:
	* library/init.tcl:
	* library/package.tcl:
	* library/safe.tcl:
	* library/tm.tcl:

2010-06-13  Donal K. Fellows  <dkf@users.sf.net>

	* tools/tcltk-man2html.tcl (make-man-pages): [Bug 3015327]: Make the
	title of a manual page be stored relative to its resulting directory
	name as well as its source filename. This was caused by both Tcl and a
	contributed package ([incr Tcl]) defining an Object.3. Also corrected
	the joining of strings in titles to avoid extra braces.

2010-06-09  Andreas Kupries  <andreask@activestate.com>

	* library/platform/platform.tcl: Added OSX Intel 64bit
	* library/platform/pkgIndex.tcl: Package updated to version 1.0.9.
	* unix/Makefile.in:
	* win/Makefile.in:

2010-06-09  Jan Nijtmans  <nijtmans@users.sf.net>

	* tools/tsdPerf.c:    Fix export of symbol Tsdperf_Init, when using
	-fvisibility=hidden. Make two functions static, eliminate some
	unnecessary type casts.
	* tools/configure.in: Update to Tcl 8.6
	* tools/configure:    (regenerated)
	* tools/.cvsignore    new file

2010-06-07  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclExecute.c: Ensure proper reset of [info errorstack] even
	* generic/tclNamesp.c:  when compiling constant expr's with errors.

2010-06-05  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:   [Bug 3008307]: make callerPtr chains be
	* generic/tclExecute.c: traversable accross coro boundaries. Add the
	special coroutine CallFrame (partially reverting commit of
	2009-12-10), as it is needed for coroutines that do not push a CF, eg,
	those with [eval] as command. Thanks to Colin McCormack (coldstore)
	and Alexandre Ferrieux for the hard work on this.

2010-06-03  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclNamesp.c: Safer (and faster) computation of [uplevel]
	* tests/error.test:    offsets in TIP 348. Toplevel offsets no longer
	* tests/result.test:   overestimated.

2010-06-02  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclOO.h:  BUILD_tcloo is never defined (leftover)
	* win/makefile.bc:  Don't set BUILD_tcloo (leftover)
	See also entry below: 2008-06-01  Joe Mistachkin

2010-06-01  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclNamesp.c: Fix computation of [uplevel] offsets in TIP 348
	* tests/error.test:    Only depend on callerPtr chaining now.
	* tests/result.test:   Needed for upcoming coro patch.

2010-05-31  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclVar.c:        Eliminate some casts to (Tcl_HashTable *)
	* generic/tclExecute.c:
	* tests/fileSystem.test:   Fix filesystem-5.1 test failure on CYGWIN

2010-05-28  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.h: [Patch 3008541]: Order of TIP #348 fields in
	Interp structure

2010-05-28  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmdsSZ.c (IssueTryFinallyInstructions): [3007374]:
	Corrected error in handling of catch contexts to prevent crash with
	chained handlers.

	* generic/tclExecute.c (TclExecuteByteCode): Restore correct operation
	of instruction-level execution tracing (had been broken by NRE).

2010-05-27  Jan Nijtmans  <nijtmans@users.sf.net>

	* library/opt/optParse.tcl: Don't generate spaces at the end of a
	* library/opt/pkgIndex.tcl: line, eliminate ';' at line end, bump to
	* tools/uniParse.tcl:       v0.4.6
	* generic/tclUniData.c:
	* tests/opt.test:
	* tests/safe.test:

2010-05-21  Jan Nijtmans  <nijtmans@users.sf.net>

	* tools/installData.tcl: Make sure that copyDir only receives
	normalized paths, otherwise it might result in a crash on CYGWIN.
	Restyle according to the Tcl style guide.
	* generic/tclStrToD.c: [Bug 3005233]: Fix for build on OpenBSD vax

2010-05-19  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* tests/dict.test: Add missing tests for [Bug 3004007], fixed under
	the radar on 2010-02-24 (dkf): EIAS violation in list-dict conversions

2010-05-19  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/regcomp.c:     Don't use arrays of length 1, just use a
	* generic/tclFileName.c: single element then, it makes code more
	* generic/tclLoad.c:     readable. (Here it even prevents a type cast)

2010-05-17  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclStrToD.c: [Bug 2996549]: Failure in expr.test on Win32

2010-05-17  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdIL.c (TclInfoFrame): Change this code to use
	Tcl_GetCommandFullName rather than rolling its own. Discovered during
	the hunting of [Bug 3001438] but unlikely to be a fix.

2010-05-11  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinConsole.c: [Patch 2997087]: Unnecessary type casts.
	* win/tclWinDde.c:
	* win/tclWinLoad.c:
	* win/tclWinNotify.c:
	* win/tclWinSerial.c:
	* win/tclWinSock.c:
	* win/tclWinTime.c:
	* win/tclWinPort.h: Don't duplicate CYGWIN timezone #define from
			    tclPort.h

2010-05-07  Andreas Kupries  <andreask@activestate.com>

	* library/platform/platform.tcl: Fix cpu name for Solaris/Intel 64bit.
	* library/platform/pkgIndex.tcl: Package updated to version 1.0.8.
	* unix/Makefile.in:
	* win/Makefile.in:

2010-05-06  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclPkg.c:   Unnecessary type casts, see [Patch 2997087]

2010-05-04  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinNotify.c:	TCHAR-related fixes, making those two files
	* win/tclWinSock.c:	compile fine when TCHAR != char. Please see
	comments in [FRQ 2965056] (2965056-1.patch).

2010-05-03  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclIORChan.c:   Use "tclIO.h" and "tclTomMathDecls.h"
	* generic/tclIORTrans.c:  everywhere
	* generic/tclTomMath.h:
	* tools/fix_tommath_h.tcl:
	* libtommath/tommath.h:   Formatting (# should always be first char on
				  line)
	* win/tclAppInit.c:       For MINGW/CYGWIN, use GetCommandLineA
				  explicitly.
	* unix/.cvsignore:        Add pkg, *.dll

	* libtommath/tommath.h:       CONSTify various useful internal
	* libtommath/bn_mp_cmp_d.c:   functions (TclBignumToDouble, TclCeil,
	* libtommath/bn_mp_cmp_mag.c: TclFloor), and related tommath functions
	* libtommath/bn_mp_cmp.c:
	* libtommath/bn_mp_copy.c:
	* libtommath/bn_mp_count_bits.c:
	* libtommath/bn_mp_div_2d.c:
	* libtommath/bn_mp_mod_2d.c:
	* libtommath/bn_mp_mul_2d.c:
	* libtommath/bn_mp_neg.c:
	* generic/tclBasic.c:        Handle TODO: const correctness ?
	* generic/tclInt.h:
	* generic/tclStrToD.c:
	* generic/tclTomMath.decls:
	* generic/tclTomMath.h:
	* generic/tclTomMathDecls.h:

2010-04-30  Don Porter  <dgp@users.sourceforge.net>

	* generic/tcl.h:	Bump patchlevel to 8.6b1.2 to distinguish
	* library/init.tcl:	CVS snapshots from earlier snapshots as well
	* unix/configure.in:	as the 8.6b1 and 8.6b2 releases.
	* win/configure.in:

	* unix/configure:	autoconf-2.59
	* win/configure:

	* generic/tclBinary.c (TclAppendBytesToByteArray):	Add comments
	* generic/tclInt.h (TclAppendBytesToByteArray):	placing overflow
	protection responsibility on caller.  Convert "len" argument to signed
	int which any value already vetted for overflow issues will fit into.
	* generic/tclStringObj.c:	Update caller; standardize panic msg.

	* generic/tclBinary.c (UpdateStringOfByteArray): [Bug 2994924]:	Add
	panic when the generated string representation would grow beyond Tcl's
	size limits.

2010-04-30  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclBinary.c (TclAppendBytesToByteArray): Add extra armour
	against buffer overflows.

	* generic/tclBasic.c (NRInterpCoroutine): Corrected handling of
	* tests/coroutine.test (coroutine-6.4):   arguments to deal with
						  trickier cases.

2010-04-30  Miguel Sofer  <msofer@users.sf.net>

	* tests/coroutine.test: testing coroutine arguments after [yield]:
	check that only 0/1 allowed

2010-04-30  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclBasic.c (NRInterpCoroutine): Corrected handling of
	arguments to deal with trickier cases.

	* generic/tclCompCmds.c (TclCompileVariableCmd): Slightly tighter
	issuing of instructions.

	* generic/tclExecute.c (TclExecuteByteCode): Add peephole optimization
	of the fact that INST_DICT_FIRST and INST_DICT_NEXT always have a
	conditional jump afterwards.

	* generic/tclBasic.c (TclNRYieldObjCmd, TclNRYieldmObjCmd)
	(NRInterpCoroutine): Replace magic values for formal argument counts
	for coroutine command implementations with #defines, for an increase
	in readability.

2010-04-30  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclMain.c: Unnecessary TCL_STORAGE_CLASS re-definition. It
	was used for an ancient dummy reference to Tcl_LinkVar(), but that's
	already gone since 2002-05-29.

2010-04-29  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompExpr.c: Slight change in the literal sharing
	* generic/tclCompile.c:  mechanism to avoid shimmering of
	* generic/tclCompile.h:  command names.
	* generic/tclLiteral.c:

2010-04-29  Andreas Kupries  <andreask@activestate.com>

	* library/platform/platform.tcl: Another stab at getting the /lib,
	* library/platform/pkgIndex.tcl: /lib64 difference right for linux.
	* unix/Makefile.in:		 Package updated to version 1.0.7.
	* win/Makefile.in:

2010-04-29  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata/Antarctica/Macquarie:
	* library/tzdata/Africa/Casablanca:
	* library/tzdata/Africa/Tunis:
	* library/tzdata/America/Santiago:
	* library/tzdata/America/Argentina/San_Luis:
	* library/tzdata/Antarctica/Casey:
	* library/tzdata/Antarctica/Davis:
	* library/tzdata/Asia/Anadyr:
	* library/tzdata/Asia/Damascus:
	* library/tzdata/Asia/Dhaka:
	* library/tzdata/Asia/Gaza:
	* library/tzdata/Asia/Kamchatka:
	* library/tzdata/Asia/Karachi:
	* library/tzdata/Asia/Taipei:
	* library/tzdata/Europe/Samara:
	* library/tzdata/Pacific/Apia:
	* library/tzdata/Pacific/Easter:
	* library/tzdata/Pacific/Fiji:   Olson's tzdata2010i.

2010-04-29  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclBinary.c (TclAppendBytesToByteArray): [Bug 2992970]: Make
	* generic/tclStringObj.c (Tcl_AppendObjToObj): an append of a byte
	array to another into an efficent operation. The problem was the (lack
	of) a proper growth management strategy for the byte array.

2010-04-29  Jan Nijtmans  <nijtmans@users.sf.net>

	* compat/dirent2.h:	Include "tcl.h", not <tcl.h>, like everywhere
	* compat/dlfcn.h:	else, to ensure that the version in the Tcl
	* compat/stdlib.h:	distribution is used, not some version from
	* compat/string.h:	somewhere else.
	* compat/unistd.h:

2010-04-28  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/Makefile.in:	Remove unused @MAN2TCLFLAGS@
	* win/tclWinPort.h:	Move <limits.h> include from tclInt.h to
	* generic/tclInt.h:	tclWinPort.h, and eliminate unneeded
	* generic/tclEnv.c:	<stdlib.h>, <stdio.h> and <string.h>, which
				are already in tclInt.h
	* generic/regcustom.h:	Move "tclInt.h" from regcustom.h up to
	* generic/regex.h:	regex.h.
	* generic/tclAlloc.c:	Unneeded <stdio.h> include.
	* generic/tclExecute.c:	Fix gcc warning: comparison between signed and
				unsigned.

2010-04-28  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclInt.h (TclIsVarDirectUnsettable): Corrected flags so that
	deletion of traces is not optimized out...

	* generic/tclExecute.c (ExecuteExtendedBinaryMathOp)
	(TclCompareTwoNumbers,ExecuteExtendedUnaryMathOp,TclExecuteByteCode):
	[Patch 2981677]: Move the less common arithmetic operations (i.e.,
	exponentiation and operations on non-longs) out of TEBC for a big drop
	in the overall size of the stack frame for most code. Net effect on
	speed is minimal (slightly faster overall in tclbench). Also extended
	the number of places where TRESULT handling is replaced with a jump to
	dedicated code.

2010-04-27  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclExecute.c (TclExecuteByteCode): Rearrange location of an
	assignment to shorten the object code.

2010-04-27  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclIOUtil.c (Tcl_FSGetNativePath): [Bug 2992292]:
	tclIOUtil.c assignment type mismatch compiler warning
	* generic/regguts.h:     If tclInt.h or tclPort.h is already
	* generic/tclBasic.c:    included, don't include <limits.h>
	* generic/tclExecute.c:  again. Follow-up to [Bug 2991415]:
	* generic/tclIORChan.c:  tclport.h #included before limits.h
	* generic/tclIORTrans.c: See comments in [Bug 2991415]
	* generic/tclObj.c:
	* generic/tclOOInt.h:
	* generic/tclStrToD.c:
	* generic/tclTomMath.h:
	* generic/tclTomMathInterface.c:
	* generic/tclUtil.c:
	* compat/strtod.c:
	* compat/strtol.c:

2010-04-27  Kevin B. Kenny  <kennykb@acm.org>

	* unix/tclLoadDl.c (FindSymbol): [Bug 2992295]: Simplified the logic
	so that the casts added in Donal Fellows's change for the same bug are
	no longer necessary.

2010-04-26  Donal K. Fellows  <dkf@users.sf.net>

	* unix/tclLoadDl.c (FindSymbol): [Bug 2992295]: Added an explicit cast
	because auto-casting between function and non-function types is never
	naturally warning-free.

	* generic/tclStubInit.c:   Add a small amount of gcc-isms (with #ifdef
	* generic/tclOOStubInit.c: guards) to ensure that warnings are issued
	when these files are older than the various *.decls files.

2010-04-25  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:    Add unsupported [yieldm] command. Credit
	* generic/tclInt.h:      Lars Hellstrom for the basic idea.

2010-04-24  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:    Modify api of TclSpliceTailcall() to fix
	* generic/tclExecute.c:  [yieldTo], which had not survived the latest
	* generic/tclInt.h:      mods to tailcall. Thanks kbk for detecting
	the problem.

2010-04-23  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tclUnixPort.h: [Bug 2991415]: tclport.h #included before
	limits.h

2010-04-22  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclPlatDecls.h:  Move TCHAR fallback typedef from tcl.h to
	* generic/tcl.h:           tclPlatDecls.h (as suggested by dgp)
	* generic/tclInt.h:        fix typo
	* generic/tclIOUtil.c:     Eliminate various unnecessary
	* unix/tclUnixFile.c:      type casts.
	* unix/tclUnixPipe.c:
	* win/tclWinChan.c:
	* win/tclWinFCmd.c:
	* win/tclWinFile.c:
	* win/tclWinLoad.c:
	* win/tclWinPipe.c:

2010-04-20  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclTest.c:  Use function prototypes from the FS API.
	* compat/zlib/*:      Upgrade to zlib 1.2.5

2010-04-19  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclExecute.c (TclExecuteByteCode): Improve commenting and
	reduce indentation for the Invocation Block.

2010-04-18  Donal K. Fellows  <dkf@users.sf.net>

	* doc/unset.n: [Bug 2988940]: Fix typo.

2010-04-15  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinPort.h:       Move inclusion of <tchar.h> from
	* generic/tcl.h:          tclPlatDecls.h to tclWinPort.h, where it
	* generic/tclPlatDecls.h: belongs. Add fallback in tcl.h, so TCHAR is
				  available in win32 always.

2010-04-15  Donal K. Fellows  <dkf@users.sf.net>

	* doc/try.n: [Bug 2987551]: Fix typo.

2010-04-14  Andreas Kupries  <andreask@activestate.com>

	* library/platform/platform.tcl: Linux platform identification:
	* library/platform/pkgIndex.tcl: Check /lib64 for existence of files
	* unix/Makefile.in: matching libc* before accepting it as base
	* win/Makefile.in:  directory. This can happen on weirdly installed
	32bit systems which have an empty or partially filled /lib64 without
	an actual libc. Bumped to version 1.0.6.

2010-04-13  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinPort.h: Fix [Patch 2986105]: conditionally defining
	* win/tclWinFile.c: strcasecmp/strncasecmp
	* win/tclWinLoad.c: Fix gcc warning: comparison of unsigned expression
	>= 0 is always true

2010-04-08  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmdsSZ.c (TclSubstCompile): If the first token does
	not result in a *guaranteed* push of a Tcl_Obj on the stack, we must
	push an empty object. Otherwise it is possible to get to a 'concat1'
	or 'done' without enough values on the stack, resulting in a crash.
	Thanks to Joe Mistachkin for identifying a script that could trigger
	this case.

2010-04-07  Donal K. Fellows  <dkf@users.sf.net>

	* doc/catch.n, doc/info.n, doc/return.n: Formatting.

2010-04-06  Donal K. Fellows  <dkf@users.sf.net>

	* doc/Load.3: Minor corrections of formatting and cross links.

2010-04-06  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/configure:       (regenerate with autoconf-2.59)
	* unix/configure:
	* unix/installManPage: [Bug 2982540]: configure and install* script
	* unix/install-sh:     files should always have LF line ending.
	* doc/Load.3:          Fix signature of Tcl_LoadFile in documentation.

2010-04-05  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	TIP #348 IMPLEMENTATION

	* generic/tclBasic.c: [Patch 2868499]: Substituted error stack
	* generic/tclCmdIL.c:
	* generic/tclInt.h:
	* generic/tclNamesp.c:
	* generic/tclResult.c:
	* doc/catch.n:
	* doc/info.n:
	* doc/return.n:
	* tests/cmdMZ.test:
	* tests/error.test:
	* tests/execute.test:
	* tests/info.test:
	* tests/init.test:
	* tests/result.test:

2010-04-05  Donal K. Fellows  <dkf@users.sf.net>

	* unix/tcl.m4 (SC_ENABLE_THREADS): Flip the default for whether to
	* win/tcl.m4 (SC_ENABLE_THREADS):  build in threaded mode. Part of
	* win/rules.vc:			   TIP #364.

	* unix/tclLoadDyld.c (FindSymbol): Better human-readable error message
	generation to match code in tclLoadDl.c.

2010-04-04  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclIOUtil.c, unix/tclLoadDl.c: Minor changes to enforce
	Engineering Manual style rules.

	* doc/FileSystem.3, doc/Load.3: Documentation for TIP#357.

	* macosx/tclMacOSXBundle.c (OpenResourceMap): [Bug 2981528]: Only
	define this function when HAVE_COREFOUNDATION is defined.

2010-04-02  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.decls (Tcl_LoadFile): Add missing "const" in signature,
	* generic/tclIOUtil.c (Tcl_LoadFile): and some formatting fixes
	* generic/tclDecls.h:  (regenerated)

2010-04-02  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclIOUtil.c (Tcl_LoadFile): Corrections to previous commit
	* unix/tclLoadDyld.c (TclpDlopen):    to make it build on OSX.

2010-04-02  Kevin B. Kenny  <kennykb@acm.org>

	TIP #357 IMPLEMENTATION
	TIP #362 IMPLEMENTATION

	* generic/tclStrToD.c: [Bug 2952904]: Defer creation of the smallest
	floating point number until it is actually used. (This change avoids a
	bogus syslog message regarding a 'floating point software assist
	fault' on SGI systems.)

	* library/reg/pkgIndex.tcl:	[TIP #362]: Fixed first round of bugs
	* tests/registry.test:		resulting from the recent commits of
	* win/tclWinReg.c:		changes in support of the referenced
					TIP.

	* generic/tcl.decls:		[TIP #357]: First round of changes
	* generic/tclDecls.h:		to export Tcl_LoadFile,
	* generic/tclIOUtil.c:		Tcl_FindSymbol, and Tcl_FSUnloadFile
	* generic/tclInt.h:		to the public API.
	* generic/tclLoad.c:
	* generic/tclLoadNone.c:
	* generic/tclStubInit.c:
	* tests/fileSystem.test:
	* tests/load.test:
	* tests/unload.test:
	* unix/tclLoadDl.c:
	* unix/tclLoadDyld.c:
	* unix/tclLoadNext.c:
	* unix/tclLoadOSF.c:
	* unix/tclLoadShl.c:
	* unix/tclUnixPipe.c:
	* win/Makefile.in:
	* win/tclWinLoad.c:

2010-03-31  Donal K. Fellows  <dkf@users.sf.net>

	* doc/registry.n: Added missing documentation of TIP#362 flags.

	* doc/package.n: [Bug 2980210]: Document the arguments taken by
	the [package present] command correctly.

	* doc/Thread.3: Added some better documentation of how to create and
	use a thread using the C-level thread API, based on realization that
	no such tutorial appeared to exist.

2010-03-31  Jan Nijtmans  <nijtmans@users.sf.net>

	* test/cmdMZ.test:    [FRQ 2974744]: share exception codes (ObjType?):
	* test/error.test:    Revised test cases, making sure that abbreviated
	* test/proc-old.test: codes are checked resulting in an error, and
	                      checking for the exact error message.

2010-03-30  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIORChan.c (ReflectClose, ReflectInput, ReflectOutput,
	(ReflectSeekWide, ReflectWatch, ReflectBlock, ReflectSetOption,
	(ReflectGetOption, ForwardProc): [Bug 2978773]: Preserve
	ReflectedChannel* structures across handler invokations, to avoid
	crashes when the handler implementation induces nested callbacks and
	destruction of the channel deep inside such a nesting.

2010-03-30  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclObj.c (Tcl_GetCommandFromObj):     [Bug 2979402]: Reorder
	the validity tests on internal rep of a "cmdName" value to avoid
	invalid reads reported by valgrind.

2010-03-30  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclIndexObj:	[FRQ 2974744]: share exception codes
	* generic/tclResult.c:	further optimization, making use of indexType.
	* generic/tclZlib.c:    [Bug 2979399]: uninitialized value troubles

2010-03-30  Donal K. Fellows  <dkf@users.sf.net>

	TIP #362 IMPLEMENTATION

	* win/tclWinReg.c: [Patch 2960976]: Apply patch from Damon Courtney to
	* tests/registry.test:	allow the registry command to be told to work
	* win/Makefile.in:	with both 32-bit and 64-bit registries. Bump
	* win/configure.in:	version of registry package to 1.3.
	* win/makefile.bc:
	* win/makefile.vc:
	* win/configure:	autoconf-2.59

2010-03-29  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tcl.m4:            Only test for -visibility=hidden with gcc
	                          (Second remark in [Bug 2976508])
	* unix/configure:         regen

2010-03-29  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c:       Fix array overrun in test format-1.12
	caught by valgrind testing.

2010-03-27  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.h:	[FRQ 2974744]: share exception codes
	* generic/tclResult.c:	(ObjType?)
	* generic/tclCmdMZ.c:
	* generic/tclCompCmdsSZ.c:

2010-03-26  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclExecute.c: [Bug 2976508]: Tcl HEAD fails on HP-UX

2010-03-25  Donal K. Fellows  <dkf@users.sf.net>

	* unix/tclUnixFCmd.c (TclUnixCopyFile): [Bug 2976504]: Corrected
	number of arguments to fstatfs() call.

	* macosx/tclMacOSXBundle.c, macosx/tclMacOSXFCmd.c:
	* macosx/tclMacOSXNotify.c: Reduce the level of ifdeffery in the
	functions of these files to improve readability. They need to be
	audited for whether complexity can be removed based on the minimum
	supported version of OSX, but that requires a real expert.

2010-03-24  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclResult.c:  [Bug 2383005]: Revise [return -errorcode] so
	* tests/result.test:    that it rejects illegal non-list values.

2010-03-24  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOInfo.c (InfoObjectMethodTypeCmd)
	(InfoClassMethodTypeCmd): Added introspection of method types so that
	it is possible to find this info out without using errors.
	* generic/tclOOMethod.c (procMethodType): Now that introspection can
	reveal the name of method types, regularize the name of normal methods
	to be the name of the definition type used to create them.

	* tests/async.test (async-4.*): Reduce obscurity of these tests by
	putting the bulk of the code for them inside the test body with the
	help of [apply].

	* generic/tclCmdMZ.c (TryPostBody, TryPostHandler): Make sure that the
	[try] command does not trap unwinding due to limits.

2010-03-23  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCmdMZ.c:	[Bug 2973361]: Revised fix for computing
	indices of script arguments to [try].

2010-03-23  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclCmdMZ.c:      Make error message in "try" implementation
	* generic/tclCompCmdsSZ.c: exactly the same as the one in "return"
	* tests/error.test:
	* libtommath/mtests/mpi.c: Single "const" addition

2010-03-22  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCmdMZ.c:	[Bug 2973361]: Compute the correct integer
	values to identify the argument indices of the various script
	arguments to [try]. Passing in -1 led to invalid memory reads.

2010-03-20  Donal K. Fellows  <dkf@users.sf.net>

	* doc/exec.n: Make it a bit clearer that there is an option to run a
	pipeline in the background.

	* generic/tclIOCmd.c (Tcl_FcopyObjCmd):		Lift the restriction
	* generic/tclIO.c (TclCopyChannel, CopyData):	on the [fcopy] command
	* generic/tclIO.h (CopyState):			that forced it to only
	copy up to 2GB per script-level callback. Now it is anything that can
	fit in a (signed) 64-bit integer. Problem identified by Frederic
	Bonnet on comp.lang.tcl. Note that individual low-level reads and
	writes are still smaller as the optimal buffer size is smaller.

2010-03-20  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/stub16.c:         Don't hide that we use the ASCII API here.
	                        (does someone still use that?)
	* win/tclWinPipe.c:     2 unnecessary type casts.

2010-03-19  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmdsSZ.c (TclCompileThrowCmd): Added compilation for
	the [throw] command.

2010-03-18  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclListObj.c:	[Bug 2971669]: Prevent in overflow trouble in
	* generic/tclTestObj.c:	ListObjReplace operations. Thanks to kbk for
	* tests/listObj.test:	fix and test.

2010-03-18  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmdsSZ.c (IssueTryFinallyInstructions):
	[Bug 2971921]: Corrected jump so that it doesn't skip into the middle
	of an instruction! Tightened the instruction issuing. Moved endCatch
	calls closer to their point that they guard, ensuring correct ordering
	of result values.

2010-03-17  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIORTrans.c (ReflectInput, ReflectOutput)
	(ReflectSeekWide): [Bug 2921116]: Added missing TclEventuallyFree
	calls for preserved ReflectedTransform* structures. Reworked
	ReflectInput to preserve the structure for its whole life, not only in
	InvokeTclMethod.

	* generic/tclIO.c (Tcl_GetsObj): [Bug 2921116]: Regenerate topChan,
	may have been changed by a self-modifying transformation.

	* tests/ioTrans/test (iortrans-4.8, iortrans-4.9, iortrans-5.11)
	(iortrans-7.4, iortrans-8.3): New test cases.

2010-03-16  Jan Nijtmans  <nijtmans@users.sf.net>

	* compat/zlib/*:	Upgrade zlib to version 1.2.4.
	* win/makefile.vc:
	* unix/Makefile.in:
	* win/tclWinChan.c:	Don't cast away "const" without reason.

2010-03-12  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/makefile.vc: [Bug 2967340]: Static build was failing.
	* win/.cvsignore:

2010-03-10  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclTest.c:	Remove unnecessary '&' decoration for
	* generic/tclIOUtil.c:	function pointers
	* win/tclWin32Dll.c:	Double declaration of TclNativeDupInternalRep
	* unix/tclIOUtil.c:
	* unix/dltest/.cvsignore: Ignore *.so here

2010-03-09  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIORChan.c: [Bug 2936225]: Thanks to Alexandre Ferrieux
	* doc/refchan.n:    <ferrieux@users.sourceforge.net> for debugging and
	* tests/ioCmd.test: fixing the problem. It is the write-side
	equivalent to the bug fixed 2009-08-06.

2010-03-09  Don Porter  <dgp@users.sourceforge.net>

	* library/tzdata/America/Matamoros: New locale
	* library/tzdata/America/Ojinaga: New locale
	* library/tzdata/America/Santa_Isabel: New locale
	* library/tzdata/America/Asuncion:
	* library/tzdata/America/Tijuana:
	* library/tzdata/Antarctica/Casey:
	* library/tzdata/Antarctica/Davis:
	* library/tzdata/Antarctica/Mawson:
	* library/tzdata/Asia/Dhaka:
	* library/tzdata/Pacific/Fiji:
	Olson tzdata2010c.

2010-03-07  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclTest.c:	  Test that tclOO stubs are present in stub
				  library
	* generic/tclOOMethod.c:  Applied missing part of [Patch 2961556]
	* win/tclWinInt.h:	  Change all tclWinProcs signatures to use
	* win/tclWin32Dll.c:	  TCHAR* in stead of WCHAR*. This is meant
	* win/tclWinDde.c:	  as preparation to make [Enh 2965056]
	* win/tclWinFCmd.c:	  possible at all.
	* win/tclWinFile.c:
	* win/tclWinPipe.c:
	* win/tclWinSock.c:

2010-03-06  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclStubLib.c:	Remove presence of tclTomMathStubsPtr here.
	* generic/tclTest.c:	Test that tommath stubs are present in stub
				library.

2010-03-05  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclIORTrans.c (ForwardProc): [Bug 2964425]: When cleaning
	the stables, it is sometimes necessary to do more than the minimum. In
	this case, rationalizing the variables for a forwarded limit? method
	required removing an extra Tcl_DecrRefCount too.

	* generic/tclOO.h, generic/tclOOInt.h: [Patch 2961556]: Change TclOO
	to use the same style of function typedefs as Tcl, as this is about
	the last chance to get this right.

	***POTENTIAL INCOMPATIBILITY***
	Source code that uses function typedefs from TclOO will need to update
	variables and argument definitions so that pointers to the function
	values are used instead. Binary compatibility is not affected.

	* generic/*.c, generic/tclInt.h, unix/*.c, macosx/*.c: Applied results
	of doing a Code Audit. Principal changes:
	  * Use do { ... } while (0) in macros
	  * Avoid shadowing one local variable with another
	  * Use clearer 'foo.bar++;' instead of '++foo.bar;' where result not
	    required (i.e., semantically equivalent); clarity is increased
	    because it is bar that is incremented, not foo.
	  * Follow Engineering Manual rules on spacing and declarations

2010-03-04  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.c (ObjectRenamedTrace): [Bug 2962664]: Add special
	handling so that when the class of classes is deleted, so is the class
	of objects. Immediately.

	* generic/tclOOInt.h (ROOT_CLASS): Add new flag for specially marking
	the root class. Simpler and more robust than the previous technique.

2010-03-04  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclGetDate.y:    3 unnecessary MODULE_SCOPE
	* generic/tclDate.c:       symbols
	* generic/tclStubLib.c:    Split tommath stub lib
	* generic/tclTomMathStubLib.c:  in separate file.
	* win/makefile.bc:
	* win/Makefile.in:
	* win/makefile.vc:
	* win/tcl.dsp:
	* unix/Makefile.in:
	* unix/tcl.m4:          Cygwin only gives warning
	* unix/configure:       using -fvisibility=hidden
	* compat/strncasecmp.c: A few more const's
	* compat/strtod.c:
	* compat/strtoul.c:

2010-03-03  Andreas Kupries <andreask@activestate.com>

	* doc/refchan.n: Followup to ChangeLog entry 2009-10-07
	(generic/tclIORChan.c). Fixed the documentation to explain that errno
	numbers are operating system dependent, and reworked the associated
	example.

2010-03-02  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tcl.m4:     [FRQ 2959069]: Support for -fvisibility=hidden
	* unix/configure   (regenerated with autoconf-2.59)

2010-03-01  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* unix/tclUnixSock.c: Refrain from a possibly lengthy reverse-DNS
	lookup on 0.0.0.0 when calling [fconfigure -sockname] on an
	universally-bound (default) server socket.

	* generic/tclIndexObj.c: fix [AT 86258]: special-casing of empty
	tables when generating error messages for [::tcl::prefix match].

2010-02-28  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdIL.c: More additions of {TCL LOOKUP} error-code
	generation to various subcommands of [info] as part of long-term
	project to classify all Tcl's generated errors.

2010-02-28  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclStubInit.c: [Bug 2959713]: Link error with gcc 4.1

2010-02-27  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdMZ.c (StringFirstCmd, StringLastCmd): [Bug 2960021]:
	Only search for the needle in the haystack when the needle isn't
	larger than the haystack. Prevents an odd crash from sometimes
	happening when things get mixed up (a common programming error).

	* generic/tclMain.c (Tcl_Main): [Bug 801429]: Factor out the holding
	of the client-installed main loop function into thread-specific data.

	***POTENTIAL INCOMPATIBILITY***
	Code that previously tried to set the main loop from another thread
	will now fail. On the other hand, there is a fairly high probability
	that such programs would have been failing before due to the lack of
	any kind of inter-thread memory barriers guarding accesses to this
	part of Tcl's state.

2010-02-26  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c:   Split this file into two pieces to make it
	* generic/tclCompCmdsSZ.c: easier to work with. It's still two very
				   long files even after the split.

2010-02-26  Reinhard Max  <max@suse.de>

	* doc/safe.n: Name the installed file after the command it documents.
	Use "Safe Tcl" instead of the "Safe Base", "Safe Tcl" mixture.

2010-02-26  Donal K. Fellows  <dkf@users.sf.net>

	* unix/Makefile.in (NATIVE_TCLSH): Added this variable to allow for
	better control of what tclsh to use for various scripts when doing
	cross compiling. An imperfect solution, but works.

	* unix/installManPage: Remap non-alphanumeric sequences in filenames
	to single underscores (especially colons).

2010-02-26  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* tests/zlib.test: Add tests for [Bug 2818131] which was crashing with
	mismatched zlib algorithms used in combination with gets. This issue
	has been fixed by Andreas's last commit.

2010-02-25  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclHash.c:	[FRQ 2958832]: Further speed-up of the
	* generic/tclLiteral.c:	ouster-hash function.
	* generic/tclObj.c:
	* generic/tclCkalloc.c:	Eliminate various unnecessary (ClientData)
	* generic/tclTest.c:	type casts.
	* generic/tclTestObj.c:
	* generic/tclTestProcBodyObj.c:
	* unix/tclUnixTest.c:
	* unix/tclUnixTime.c:
	* unix/tclXtTest.c:

2010-02-24  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclDictObj.c (SetDictFromAny): Prevent the list<->dict
	* generic/tclListObj.c (SetListFromAny): conversion code from taking
	too many liberties. Stops loss of duplicate keys in some scenarios.
	Many thanks to Jean-Claude Wippler for finding this.

	* generic/tclExecute.c (TclExecuteByteCode): Reduce ifdef-fery and
	size of activation record. More variables shared across instructions
	than before.

	* doc/socket.n: [Bug 2957688]: Clarified that [socket -server] works
	with a command prefix. Extended example to show this in action.

2010-02-22  Andreas Kupries  <andreask@activestate.com>

	* generic/tclZlib.c (ZlibTransformInput): [Bug 2762041]: Added a hack
	to work around the general problem, early EOF recognition based on the
	base-channel, instead of the data we have ready for reading in the
	transform. Long-term we need a proper general fix (likely tracking EOF
	on each level of the channel stack), with attendant complexity.
	Furthermore, Z_BUF_ERROR can be ignored, and must be when feeding the
	zlib code with single characters.

2010-02-22  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tclUnixPort.h:   Remove unnecessary EXTERN's, which already are
	                        in the global stub table.
	* unix/configure.in:    Use @EXEEXT@ in stead of @EXT_SUFFIX@
	* unix/tcl.m4:
	* unix/Makefile.in:     Use -DBUILD_tcl for CYGWIN
	* unix/configure:       (regenerated)
	* unix/dltest/pkg*.c:   Use EXTERN to control CYGWIN exported symbols
	* generic/tclCmdMZ.c:   Remove some unnecessary type casts.
	* generic/tclCompCmds.c:
	* generic/tclTest.c:
	* generic/tclUtil.c:

2010-02-21  Mo DeJong  <mdejong@users.sourceforge.net>

	* tests/regexp.test: Add test cases back ported from Jacl regexp work.

2010-02-21  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclDate.c:    Some more const tables.
	* generic/tclGetDate.y:
	* generic/regc_lex.c:
	* generic/regerror.c:
	* generic/tclStubLib.c:
	* generic/tclBasic.c:   Fix [Bug 2954959] expr abs(0.0) is -0.0
	* tests/expr.test:

2010-02-20  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileStringLenCmd): Make [string length]
	of a constant string be handled better (i.e., handle backslashes too).

2010-02-19  Stuart Cassoff  <stwo@users.sourceforge.net>

	* tcl.m4: Correct compiler/linker flags for threaded builds on
	OpenBSD.
	* configure: (regenerated).

2010-02-19  Donal K. Fellows  <dkf@users.sf.net>

	* unix/installManPage: [Bug 2954638]: Correct behaviour of manual page
	installer. Also added armouring to check that assumptions about the
	initial state are actually valid (e.g., look for existing input file).

2010-02-17  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclHash.c (HashStringKey):	Restore these hash functions
	* generic/tclLiteral.c (HashString):	to use the classic algorithm.
	* generic/tclObj.c (TclHashObjKey):	Community felt normal case
	speed to be more important than resistance to malicious cases. For
	now, hashes that need to deal with the malicious case can use a custom
	hash table and install their own hash function, though that is not
	functionality exposed to the script level.

	* generic/tclCompCmds.c (TclCompileDictUpdateCmd): Stack depth must be
	correctly described when compiling a body to prevent crashes in some
	debugging modes.

2010-02-16  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.h: Change order of various struct members,
	fixing potential binary incompatibility with Tcl 8.5

2010-02-16  Donal K. Fellows  <dkf@users.sf.net>

	* unix/configure.in, generic/tclIOUtil.c (Tcl_Stat): Updated so that
	we do not assume that all unix systems have the POSIX blkcnt_t type,
	since OpenBSD apparently does not.

	* generic/tclLiteral.c (HashString): Missed updating to FNV in one
	place; the literal table (a copy of the hash table code...)

2010-02-15  Jan Nijtmans  <nijtmans@users.sf.net>

	* tools/genStubs.tcl:   Reverted earlier rename from tcl*Stubs to
	* generic/tclBasic.c:   tcl*ConstStubs, it's not necessary at all.
	* generic/tclOO.c:
	* generic/tclTomMathInterface.c:
	* generic/tclStubInit.c: (regenerated)
	* generic/tclOOStubInit.c: (regenerated)
	* generic/tclEnsemble.c:Fix signed-unsigned mismatch
	* win/tclWinInt.h:      make tclWinProcs "const"
	* win/tclWin32Dll.c:
	* win/tclWinFCmd.c:     Eliminate all internal Tcl_WinUtfToTChar
	* win/tclWinFile.c:     and Tcl_WinTCharToUtf calls, needed
	* win/tclWinInit.c:     for mslu support.
	* win/tclWinLoad.c:
	* win/tclWinPipe.c:
	* win/tclWinSerial.c:
	* win/.cvsignore:
	* compat/unicows/readme.txt:  [FRQ 2819611]: Add first part of MSLU
	* compat/unicows/license.txt: support.
	* compat/unicows/unicows.lib:

2010-02-15  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.c (AllocObject, SquelchedNsFirst, ObjectRenamedTrace):
	* generic/tclNamesp.c (Tcl_DeleteNamespace): [Bug 2950259]: Revised
	the namespace deletion code to provide an additional internal callback
	that gets triggered early enough in namespace deletion to allow TclOO
	destructors to run sanely. Adjusted TclOO to take advantage of this,
	so making tearing down an object by killing its namespace appear to
	work seamlessly, which is needed for Itcl. (Note that this is not a
	feature that will ever be backported to 8.5, and it remains not a
	recommended way of deleting an object.)

2010-02-13  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileSwitchCmd): Divided the [switch]
	compiler into three pieces (after the model of [try]): a parser, an
	instruction-issuer for chained tests, and an instruction-issuer for
	jump tables.

	* generic/tclEnsemble.c: Split the ensemble engine out into its own
	file rather than keeping it mashed together with the namespace code.

2010-02-12  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tcl.m4:		Use -pipe for gcc on win32
	* win/configure:	(mingw/cygwin) (regenerated)
	* win/.cvsignore:	Add .lib, .exp and .res here

2010-02-11  Mo DeJong  <mdejong@users.sourceforge.net>

	* tests/list.test: Add tests for explicit \0 in a string argument to
	the list command.

2010-02-11  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclIOCmd.c (Tcl_OpenObjCmd): [Bug 2949740]: Make sure that
	we do not try to put a NULL pipeline channel into binary mode.

2010-02-11  Mo DeJong  <mdejong@users.sourceforge.net>

	[Bug 2826551, Patch 2948425]: Assorted regexp bugs related to -all,
	-line and -start options and newlines.
	* generic/tclCmdMZ.c (Tcl_RegexpObjCmd): If -offset is given, treat it
	as the start of the line if the previous character was a newline. Fix
	nasty edge case where a zero length match would not advance the index.
	* tests/regexp.test: Add regression tests back ported from Jacl.
	Checks for a number of issues related to -line and newline handling. A
	few of tests were broken before the patch and continue to be broken,
	marked as knownBug.

2010-02-11  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.c (ObjectRenamedTrace): [Bug 2949397]: Prevent
	destructors from running on the two core class objects when the whole
	interpreter is being destroyed.

2010-02-09  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileTryCmd, IssueTryInstructions)
	(IssueTryFinallyInstructions): Added compiler for the [try] command.
	It is split into three pieces that handle the parsing of the tokens,
	the issuing of instructions for finally-free [try], and the issuing of
	instructions for [try] with finally; there are enough differences
	between the all cases that it was easier to split the code rather than
	have a single function do the whole thing.

2010-02-09  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* tools/genStubs.tcl: Remove dependency on 8.5+ idiom "in" in
	expressions.

2010-02-08  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclZlib.c (Tcl_ZlibDeflate, Tcl_ZlibInflate): [Bug 2947783]:
	Make sure that the result is an unshared object before appending to it
	so that nothing crashes if it is shared (use in Tcl code was not
	affected by this, but use from C was an issue).

2010-02-06  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclHash.c (HashStringKey):	Replace Tcl's crusty old hash
	* generic/tclObj.c (TclHashObjKey):	function with the algorithm
	due to Fowler, Noll and Vo. This is slightly faster (assuming the
	presence of hardware multiply) and has somewhat better distribution
	properties of the resulting hash values. Note that we only ever used
	the 32-bit version of the FNV algorithm; Tcl's core hash engine
	assumes that hash values are simple unsigned ints.

	***POTENTIAL INCOMPATIBILITY***
	Code that depends on hash iteration order (especially tests) may well
	be disrupted by this. Where a definite order is required, the fix is
	usually to just sort the results after extracting them from the hash.
	Where this is insufficient, the code that has ceased working was
	always wrong and was only working by chance.

2010-02-05  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileErrorCmd): Added compilation of the
	[error] command. No new bytecodes.

2010-02-05  Jan Nijtmans  <nijtmans@users.sf.net>

	* tools/genStubs.tcl:	Follow-up to earlier commit today:
	          Eliminate the need for an extra Stubs Pointer for adressing
	          a static stub table: Just change the exported table from
	          static to MODULE_SCOPE.
	* generic/tclBasic.c
	* generic/tclOO.c
	* generic/tclTomMathInterface.c
	* generic/tcl*Decls.h (regenerated)
	* generic/tclStubInit.c (regenerated)
	* generic/tclOOStubInit.c (regenerated)
	* generic/tclTest.c (minor formatting)

2010-02-05  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclVar.c: More consistency in errorcode generation.

	* generic/tclOOBasic.c (TclOO_Object_Destroy): Rewrote to be NRE-aware
	when calling destructors. Note that there is no guarantee that
	destructors will always be called in an NRE context; that's a feature
	of the 'destroy' method only.

	* generic/tclEncoding.c: Add 'const' to many function-internal vars
	that are never pointing to things that are written to.

2010-02-05  Jan Nijtmans  <nijtmans@users.sf.net>

	* tools/genStubs.tcl:	Follow-up to [2010-01-29] commit:
		prevent space within stub table function parameters if the
		parameter type is a pointer.
	* win/tclWinInt.h:	Minor Formatting
	* generic/tcl.h:	VOID -> void and other formatting
	* generic/tclInt.h:	Minor formatting
	* generic/tclInt.decls: Change signature of TclNRInterpProcCore,
	* generic/tclOO.decls:	and TclOONewProc(Instance|)MethodEx,
	* generic/tclProc.c:	indicating that errorProc is a function,
	* generic/tclOOMethod.c:pointer, and other formatting
	* generic/tcl*Decls.h:	(regenerated)
	* generic/tclVar.c:	gcc warning(line 3703): 'pattern' may be used
				uninitialized in this function
				gcc warning(line 3788): 'matched' may be used
				uninitialized in this function

2010-02-04  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclVar.c: Added more use of error-codes and reduced the
	stack overhead of older interfaces.
	(ArrayGetCmd): Stop silly crash when using a trivial pattern due to
	error in conversion to ensemble.
	(ArrayNamesCmd): Use the object RE interface for faster matching.

2010-02-03  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclVar.c (ArrayUnsetCmd): More corrections.

2010-02-02  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclVar.c: Turned the [array] command into a true ensemble.

	* generic/tclOO.c (AllocObject, MyDeleted): A slightly faster way to
	handle the deletion of [my] is with a standard delete callback. This
	is because it doesn't require an additional memory allocation during
	object creation. Also reduced the amount of string manipulation
	performed during object creation to further streamline memory
	handling; this is not backported to the 8.5 package as it breaks a
	number of abstractions.

	* generic/tclOOBasic.c (TclOO_Object_Destroy): [Bug 2944404]: Do not
	crash when a destructor deletes the object that is executing that
	destructor.

2010-02-01  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclVar.c (Tcl_ArrayObjCmd): [Bug 2939073]: Stop the [array
	unset] command from having dangling pointer problems when an unset
	trace deletes the element that is going to be processed next. Many
	thanks to Alexandre Ferrieux for the bulk of this fix.

	* generic/regexec.c (ccondissect, crevdissect): [Bug 2942697]: Rework
	these functions so that certain pathological patterns are matched much
	more rapidly. Many thanks to Tom Lane for dianosing this issue and
	providing an initial patch.

2010-01-30  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompile.c (tclInstructionTable):	Bytecode instructions
	* generic/tclCompCmds.c (TclCompileUnsetCmd):	to allow the [unset]
	* generic/tclExecute.c (TclExecuteByteCode):	command to be compiled
	with the compiler being a complete compilation for all compile-time
	decidable uses.

	* generic/tclVar.c (TclPtrUnsetVar): Var reference version of the code
	to unset a variable. Required for INST_UNSET bytecodes.

2010-01-29  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.h: [Bug 2942081]: Reverted Tcl_ThreadDataKey type change
				Changed some Tcl_CallFrame fields from "char *"
				to "void *". This saves unnecessary space on
				Cray's (and it's simply more correct).

	* tools/genStubs.tcl:	No longer generate a space after "*" and
				immediately after a function name, so the
				format of function definitions in tcl*Decls.h
				match all other tcl*.h header files.
	* doc/ParseArgs.3:	Change Tcl_ArgvFuncProc, Tcl_ArgvGenFuncProc
	* generic/tcl.h:	and GetFrameInfoValueProc to be function
	* generic/tclInt.h:	definitions, not pointers, for consistency
	* generic/tclOOInt.h:	with all other Tcl function definitions.
	* generic/tclIndexObj.c:
	* generic/regguts.h:	CONST -> const
	* generic/tcl.decls:	Formatting
	* generic/tclTomMath.decls: Formatting
	* generic/tclDecls.h:	(regenerated)
	* generic/tclIntDecls.h:
	* generic/tclIntPlatDecls.h:
	* generic/tclOODecls.h:
	* generic/tclOOIntDecls.h:
	* generic/tclPlatDecls.h:
	* generic/tclTomMathDecls.h:

2010-01-28  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOBasic.c (TclOO_Object_Destroy): Move the execution of
	destructors to a point where they can produce an error. This will not
	work for all destructors, but it does mean that more failing calls of
	them will be caught.
	* generic/tclOO.c (AllocObject, MyDeletedTrace, ObjectRenamedTrace):
	(ObjectNamespaceDeleted): Stop various ways of getting at commands
	with dangling pointers to the object. Also increases the reliability
	of calling of destructors (though most destructors won't benefit; when
	an object is deleted namespace-first, its destructors are not run in a
	nice state as the namespace is partially gone).

2010-01-25  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclOOStubInit.c:   Remove double includes (which causes a
	* generic/tclOOStubLib.c:    warning in CYGWIN compiles)
	* unix/.cvsignore:	     add confdefs.h

2010-01-22  Donal K. Fellows  <dkf@users.sf.net>

	* doc/proc.n: [Bug 1970629]: Define a bit better what the current
	namespace of a procedure is.

2010-01-22  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.decls:	     Don't use DWORD and HANDLE here.
	* generic/tclIntPlatDecls.h:
	* generic/tcl.h:	     Revert [2009-12-21] change, instead
	* generic/tclPort.h:	     resolve the CYGWIN inclusion problems by
	* win/tclWinPort.h:	     re-arranging the inclusions at other
				     places.
	* win/tclWinError.c
	* win/tclWinPipe.c
	* win/tcl.m4:		     Make cygwin configuration error into
	* win/configure.in:	     a warning: CYGWIN compilation works
	* win/configure:	     although there still are test failures.

2010-01-22  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclExecute.c (TclExecuteByteCode): Improve error code
	generation from some of the tailcall-related bits of TEBC.

2010-01-21  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompile.h: [Bug 2910748]: NRE-enable direct eval on BC
	* generic/tclExecute.c: spoilage.
	* tests/nre.test:

2010-01-19  Donal K. Fellows  <dkf@users.sf.net>

	* doc/dict.n: [Bug 2929546]: Clarify just what [dict with] and [dict
	update] are doing with variables.

2010-01-18  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c (CreateScriptRecord): [Bug 2918110]: Initialize
	the EventScriptRecord (esPtr) fully before handing it to
	Tcl_CreateChannelHandler for registration. Otherwise a reflected
	channel calling 'chan postevent' (== Tcl_NotifyChannel) in its
	'watchProc' will cause the function 'TclChannelEventScriptInvoker'
	to be run on an uninitialized structure.

2010-01-18  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclStringObj.c (Tcl_AppendFormatToObj): [Bug 2932421]: Stop
	the [format] command from causing argument objects to change their
	internal representation when not needed. Thanks to Alexandre Ferrieux
	for this fix.

2010-01-13  Donal K. Fellows  <dkf@users.sf.net>

	* tools/tcltk-man2html.tcl:	  More factoring out of special cases
	* tools/tcltk-man2html-utils.tcl: so that they are described outside
	the engine file. Now there is only one real set of special cases in
	there, to handle the .SO/.OP/.SE directives.

2010-01-13  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.h:      Fix TCL_LL_MODIFIER for Cygwin
	* generic/tclEnv.c:   Fix CYGWIN compilation problems,
	* generic/tclInt.h:   and remove some unnecessary
	* generic/tclPort.h:  double includes.
	* generic/tclPlatDecls.h:
	* win/cat.c:
	* win/tclWinConsole.c:
	* win/tclWinFCmd.c:
	* win/tclWinFile.c:
	* win/tclWinPipe.c:
	* win/tclWinSerial.c:
	* win/tclWinThrd.c:
	* win/tclWinPort.h:   Put win32 includes first
	* unix/tclUnixChan.c: Forgot one CONST change

2010-01-12  Donal K. Fellows  <dkf@users.sf.net>

	* tools/tcltk-man2html.tcl: Make the generation of the list of things
	to process the docs from simpler and more flexible. Also factored out
	the lists of special cases.

2010-01-10  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinDde.c:      VC++ 6.0 doesn't have
	* win/tclWinReg.c:      PDWORD_PTR
	* win/tclWinThrd.c:     Fix various minor gcc warnings.
	* win/tclWinTime.c:
	* win/tclWinConsole.c:  Put channel type definitions
	* win/tclWinChan.c:     in static const memory
	* win/tclWinPipe.c:
	* win/tclWinSerial.c:
	* win/tclWinSock.c:
	* generic/tclIOGT.c:
	* generic/tclIORChan.c:
	* generic/tclIORTrans.c:
	* unix/tclUnixChan.c:
	* unix/tclUnixPipe.c:
	* unix/tclUnixSock.c:
	* unix/configure:       (regenerated with autoconf 2.59)
	* tests/info.test:      Make test independant from
	                        tcltest implementation.

2010-01-10  Donal K. Fellows  <dkf@users.sf.net>

	* tests/namespace.test (namespace-51.17): [Bug 2898722]: Demonstrate
	that there are still bugs in the handling of resolution epochs. This
	bug is not yet fixed.

	* tools/tcltk-man2html.tcl:	  Split the man->html converter into
	* tools/tcltk-man2html-utils.tcl: two pieces for easier maintenance.
	Also made it much less verbose in its printed messages by default.

2010-01-09  Donal K. Fellows  <dkf@users.sf.net>

	* tools/tcltk-man2html.tcl: Added basic support for building the docs
	for contributed packages into the HTML versions. Prompted by question
	on Tcler's Chat by Tom Krehbiel. Note that there remain problems in
	the documentation generated due to errors in the contributed docs.

2010-01-05  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclPathObj.c (TclPathPart):   [Bug 2918610]: Correct
	* tests/fileName.test (filename-14.31): inconsistency between the
	string rep and the intrep of a path value created by [file rootname].
	Thanks to Vitaly Magerya for reporting.

2010-01-03  Donal K. Fellows  <dkf@users.sf.net>

	* unix/tcl.m4 (SC_CONFIG_CFLAGS): [Bug 1636685]: Use the configuration
	for modern FreeBSD suggested by the FreeBSD porter.

2010-01-03  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:	[Bug 2724403]: Fix leak of coroutines on
	* generic/tclCompile.h: namespace deletion. Added a test for this
	* generic/tclNamesp.c:	leak, and also a test for leaks on namespace
	* tests/coroutine.test: deletion.
	* tests/namespace.test:

2009-12-30  Donal K. Fellows  <dkf@users.sf.net>

	* library/safe.tcl (AliasSource): [Bug 2923613]: Make the safer
	* tests/safe.test (safe-8.9):	  [source] handle a [return] at the
					  end of the file correctly.

2009-12-30  Miguel Sofer  <msofer@users.sf.net>

	* library/init.tcl (unknown): [Bug 2824981]: Fix infinite recursion of
	::unknown when [set] is undefined.

2009-12-29  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclHistory.c (Tcl_RecordAndEvalObj): Reduce the amount of
	allocation and deallocation of memory by caching objects in the
	interpreter assocData table.

	* generic/tclObj.c (Tcl_GetCommandFromObj): Rewrite the logic so that
	it does not require making assignments part way through an 'if'
	condition, which was deeply unclear.

	* generic/tclInterp.c (Tcl_MakeSafe): [Bug 2895741]: Make sure that
	the min() and max() functions are supported in safe interpreters.

2009-12-29  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* generic/tclBinary.c:	[Bug 2922555]: Handle completely invalid input
	* tests/binary.test:	to the decode methods.

2009-12-28  Donal K. Fellows  <dkf@users.sf.net>

	* unix/Makefile.in (trace-shell, trace-test): [FRQ 1083288]: Added
	targets to allow easier tracing of shell and test invokations.

	* unix/configure.in: [Bug 942170]:	Detect the st_blocks field of
	* generic/tclCmdAH.c (StoreStatData):	'struct stat' correctly.
	* generic/tclFileName.c (Tcl_GetBlocksFromStat):
	* generic/tclIOUtil.c (Tcl_Stat):

	* generic/tclInterp.c (TimeLimitCallback): [Bug 2891362]: Ensure that
	* tests/interp.test (interp-34.13):	   the granularity ticker is
	reset when we check limits because of the time limit event firing.

2009-12-27  Donal K. Fellows  <dkf@users.sf.net>

	* doc/namespace.n (SCOPED SCRIPTS): [Bug 2921538]: Updated example to
	not be quite so ancient.

2009-12-25  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclCmdMZ.c:      CONST -> const
	* generic/tclParse.c

2009-12-23  Donal K. Fellows  <dkf@users.sf.net>

	* library/safe.tcl (AliasSource, AliasExeName): [Bug 2913625]: Stop
	information about paths from leaking through [info script] and [info
	nameofexecutable].

2009-12-23  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tcl.m4:		Install libtcl8.6.dll in bin directory
	* unix/Makefile.in:
	* unix/configure:	(regenerated)

2009-12-22  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdIL.c (Tcl_LsortObjCmd): [Bug 2918962]: Stop crash when
	-index and -stride are used together.

2009-12-21  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclThreadStorage.c: Fix gcc warning, using gcc-4.3.4 on
				      cygwin: missing initializer
	* generic/tclOOInt.h:	      Prevent conflict with DUPLICATE
				      definition in WINAPI's nb30.h
	* generic/rege_dfa.c:	      Fix macro conflict on CYGWIN: don't use
				      "small".
	* generic/tcl.h:	      Include <winsock2.h> before <stdio.h> on
				      CYGWIN
	* generic/tclPathObj.c
	* generic/tclPort.h
	* tests/env.test:	      Don't unset WINDIR and TERM, it has a
				      special meaning on CYGWIN (both in UNIX
				      and WIN32 mode!)
	* generic/tclPlatDecls.h:     Include <tchar.h> through tclPlatDecls.h
	* win/tclWinPort.h:	      stricmp -> strcasecmp
	* win/tclWinDde.c:	      _wcsicmp -> wcscasecmp
	* win/tclWinFile.c
	* win/tclWinPipe.c
	* win/tclWinSock.c
	* unix/tcl.m4:		      Add dynamic loading support to CYGWIN
	* unix/configure (regenerated)
	* unix/Makefile.in

2009-12-19  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:	[Bug 2917627]: Fix for bad cmd resolution by
	* tests/coroutine.test:	coroutines. Thanks to schelte for finding it.

2009-12-16  Donal K. Fellows  <dkf@users.sf.net>

	* library/safe.tcl (::safe::AliasGlob): Upgrade to correctly support a
	larger fraction of [glob] functionality, while being stricter about
	directory management.

2009-12-11  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclTest.c:	Fix gcc warning: ignoring return value of
	* unix/tclUnixNotify.c:	"write", declared with attribute
	* unix/tclUnixPipe.c:	warn_unused_result.
	* generic/tclInt.decls:	CONSTify functions TclpGetUserHome and
	* generic/tclIntDecls.h:TclSetPreInitScript (TIP #27)
	* generic/tclInterp.c:
	* win/tclWinFile.c:
	* unix/tclUnixFile.c:

2009-12-16  Donal K. Fellows  <dkf@users.sf.net>

	* doc/tm.n: [Bug 1911342]: Formatting rewrite to avoid bogus crosslink
	to the list manpage when generating HTML.

	* library/msgcat/msgcat.tcl (Init): [Bug 2913616]: Do not use platform
	tests that are not needed and which don't work in safe interpreters.

2009-12-14  Donal K. Fellows  <dkf@users.sf.net>

	* doc/file.n (file tempfile): [Bug 2388866]: Note that this only ever
	creates files on the native filesystem. This is a design feature.

2009-12-13  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:	Release TclPopCallFrame() from its
	* generic/tclExecute.c:	tailcall-management duties
	* generic/tclNamesp.c:

	* generic/tclBasic.c:	Moving TclBCArgumentRelease call from
	* generic/tclExecute.c:	TclNRTailcallObjCmd to TEBC, so that the
	pairing of the Enter and Release calls is clearer.

2009-12-12  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclTest.c (TestconcatobjCmd): [Bug 2895367]: Stop memory
	leak when testing. We don't need extra noise of this sort when
	tracking down real problems!

2009-12-11  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclBinary.c:	Fix gcc warning, using gcc-4.3.4 on cygwin
	* generic/tclCompExpr.c:warning: array subscript has type 'char'
	* generic/tclPkg.c:
	* libtommath/bn_mp_read_radix.c:
	* win/makefile.vc:	[Bug 2912773]: Revert to version 1.203
	* unix/tclUnixCompat.c:	Fix gcc warning: signed and unsigned type
				in conditional expression.

2009-12-11  Donal K. Fellows  <dkf@users.sf.net>

	* tools/tcltk-man2html.tcl (long-toc, cross-reference): [FRQ 2897296]:
	Added cross links to sections within manual pages.

2009-12-11  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:   [Bug 2806407]: Full nre-enabling of coroutines
	* generic/tclExecute.c:

	* generic/tclBasic.c: Small cleanup

	* generic/tclExecute.c: Fix panic in http11.test caused by buggy
	earlier commits in coroutine management.

2009-12-10  Andreas Kupries  <andreask@activestate.com>

	* generic/tclObj.c (TclContinuationsEnter): [Bug 2895323]: Updated
	comments to describe when the function can be entered for the same
	Tcl_Obj* multiple times. This is a continuation of the 2009-11-10
	entry where a memory leak was plugged, but where not sure if that was
	just a band-aid to paper over some other error. It isn't, this is a
	legal situation.

2009-12-10  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:   Reducing the # of moving parts for coroutines
	* generic/tclExecute.c: by delegating more to tebc; eliminate the
	special coroutine CallFrame.

2009-12-09  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c: [Bug 2901998]: Applied Alexandre Ferrieux's patch
	fixing the inconsistent buffered I/O. Tcl's I/O now flushes buffered
	output before reading, discards buffered input before writing, etc.

2009-12-09  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c: Ensure right lifetime of varFrame's (objc,objv)
	for coroutines.

	* generic/tclExecute.c: Code regrouping

2009-12-09  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclBasic.c: Added some of the missing setting of errorcode
	values.

2009-12-08  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c (TclStackFree): Improved panic msg.

2009-12-08  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:   Partial nre-enabling of coroutines. The
	* generic/tclExecute.c: initial call still requires its own
	* generic/tclInt.h:     instance of tebc, but on resume coros can
	execute in the caller's tebc.

	* generic/tclExecute.c (TEBC): Silence warning about pcAdjustment.

2009-12-08  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclExecute.c (TclExecuteByteCode): Make the dict opcodes
	more sparing in their use of C variables, to reduce size of TEBC
	activiation record a little bit.

2009-12-07  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c (TEBC): Grouping "slow" variables into structs,
	to reduce register pressure and help the compiler with variable
	allocation.

2009-12-07  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: Start cleaning the TEBC stables
	* generic/tclInt.h:

	* generic/tclCmdIL.c:   [Bug 2910094]: Fix by aku
	* tests/coroutine.test:

	* generic/tclBasic.c: Arrange for [tailcall] to be created with the
	other builtins: was being created in a separate call, leftover from
	pre-tip days.

2009-12-07  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStrToD.c: [Bug 2902010]: Correct conditional compile
	directives to better detect the toolchain that needs extra work for
	proper underflow treatment instead of merely detecting the MIPS
	platform.

2009-12-07  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c: [Patch 2910056]: Add ::tcl::unsupported::yieldTo
	* generic/tclInt.h:

2009-12-07  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdMZ.c (TryPostBody): [Bug 2910044]: Close off memory
	leak in [try] when a variable-free handler clause is present.

2009-12-05  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:   Small changes for clarity in tailcall
	* generic/tclExecute.c: and coroutine code.
	* tests/coroutine.test:

	* tests/tailcall.test: Remove some old unused crud; improved the
	stack depth tests.

	* generic/tclBasic.c:  Fixed things so that you can tailcall
	* generic/tclNamesp.c: properly out of a coroutine.
	* tests/tailcall.test:

	* generic/tclInterp.c: Fixed tailcalls for same-interp aliases (no
	test)

2009-12-03  Donal K. Fellows  <dkf@users.sf.net>

	* library/safe.tcl (::safe::AliasEncoding): Make the safe encoding
	command behave more closely like the unsafe one (for safe ops).
	(::safe::AliasGlob): [Bug 2906841]: Clamp down on evil use of [glob]
	in safe interpreters.
	* tests/safe.test: Rewrite to use tcltest2 better.

2009-12-02  Jan Nijtmans  <nijtmans@users.sf.net>

	* tools/genStubs.tcl:	Add support for win32 CALLBACK functions and
	remove obsolete "emitStubs" and "genStubs" functions.
	* win/Makefile.in:	Use tcltest86.dll for all tests, and add
	.PHONY rules to preemptively stop trouble that plagued Tk from hitting
	Tcl too.

2009-11-30  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.h:	Don't use EXPORT for Tcl_InitStubs
	* win/Makefile.in:	Better dependancies in case of static build.

2009-11-30  Donal K. Fellows  <dkf@users.sf.net>

	* doc/Tcl.n: [Bug 2901433]: Improved description of expansion to
	mention that it is using list syntax.

2009-11-27  Kevin B. Kenny  <kennykb@acm.org>

	* win/tclAppInit.c (Tcl_AppInit): [Bug 2902965]: Reverted Jan's change
	that added a call to Tcl_InitStubs. The 'tclsh' and 'tcltest' programs
	are providers, not consumers of the Stubs table, and should not link
	with the Stubs library, but only with the main Tcl library. (In any
	case, the presence of Tcl_InitStubs broke the build.)

2009-11-27  Donal K. Fellows  <dkf@users.sf.net>

	* doc/BoolObj.3, doc/Class.3, doc/CrtChannel.3, doc/DictObj.3:
	* doc/DoubleObj.3, doc/Ensemble.3, doc/Environment.3:
	* doc/FileSystem.3, doc/Hash.3, doc/IntObj.3, doc/Limit.3:
	* doc/Method.3, doc/NRE.3, doc/ObjectType.3, doc/PkgRequire.3:
	* doc/SetChanErr.3, doc/SetResult.3: [Patch 2903921]: Many small
	spelling fixes from Larry Virden.

	BUMP VERSION OF TCLOO TO 0.6.2. Too many people need accumulated small
	versions and bugfixes, so the version-bump removes confusion.

	* generic/tclOOBasic.c (TclOO_Object_LinkVar): [Bug 2903811]: Remove
	unneeded restrictions on who can usefully call this method.

2009-11-26  Donal K. Fellows  <dkf@users.sf.net>

	* unix/Makefile.in: Add .PHONY rules and documentation to preemptively
	stop trouble that plagued Tk from hitting Tcl too, and to make the
	overall makefile easier to understand. Some reorganization too to move
	related rules closer together.

2009-11-26  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/Makefile.in:	[Bug 2902965]: Fix stub related changes that
	* win/makefile.vc:	caused tclkit build to break.
	* win/tclAppInit.c
	* unix/tcl.m4
	* unix/Makefile.in
	* unix/tclAppInit.c
	* unix/configure:	(regenerated)

2009-11-25  Kevin B. Kenny  <kennykb@acm.org>

	* win/Makefile.in:	Added a 'test-tcl' rule that is identical to
	'test' except that it does not go spelunking in 'pkgs/'. (This rule
	has existed in unix/Makefile.in for some time.)

2009-11-25  Stuart Cassoff  <stwo@users.sf.net>

	* unix/configure.in:	[Patch 2892871]: Remove unneeded
	* unix/tcl.m4:		AC_STRUCT_TIMEZONE and use
	* unix/tclConfig.h.in:	AC_CHECK_MEMBERS([struct stat.st_blksize])
	* unix/tclUnixFCmd.c:	instead of AC_STRUCT_ST_BLKSIZE.
	* unix/configure:	Regenerated with autoconf-2.59.

2009-11-24  Andreas Kupries  <andreask@activestate.com>

	* library/tclIndex: Manually redone the part of tclIndex dealing with
	safe.tcl and tm.tcl. This part passes the testsuite. Note that
	automatic regeneration of this part is not possible because it wrongly
	puts 'safe::Setup' on the list, and wrongly leaves out 'safe::Log'
	which is more dynamically created than the generator expects.

	Further note that the file "clock.tcl" is explicitly loaded by
	"init.tcl", the first time the clock command is invoked. The relevant
	code can be found at line 172ff, roughly, the definition of the
	procedure 'clock'. This means none of the procedures of this file
	belong in the tclIndex. Another indicator that automatic regeneration
	of tclIndex is ill-advised.

2009-11-24  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.c (FinalizeAlloc, Tcl_NewObjectInstance):
	[Bug 2903011]: Make it an error to destroy an object in a constructor,
	and also make sure that an object is not deleted twice in the error
	case.

2009-11-24  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* tests/fCmd.test: [Bug 2893771]: Teach [file stat] to handle locked
	* win/tclWinFile.c: files so that [file exists] no longer lies.

2009-11-23  Kevin Kenny  <kennykb@acm.org>

	* tests/fCmd.test (fCmd-30.1): Changed registry location of the 'My
	Documents' folder to the one that's correct for Windows 2000, XP,
	Server 2003, Vista, Server 2008, and Windows 7. (See
	http://support.microsoft.com/kb/310746)

2009-11-23  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWinDde.c:	#undef STATIC_BUILD, in order to make sure
	* win/tclWinReg.c:	that Xxxxx_Init is always exported even when
	* generic/tclTest.c:	Tcl is built static (otherwise we cannot
				create a DLL).
	* generic/tclThreadTest.c: Make all functions static, except
				TclThread_Init.
	* tests/fCmd.test:	Enable fCmd-30.1 when registry is available.
	* win/tcl.m4:		Fix ${SHLIB_LD_LIBS} definition, fix conflicts
	* win/Makefile.in:	Simplifications related to tcl.m4 changes.
	* win/configure.in:	Between static libraries and import library on
				windows.
	* win/configure:	(regenerated)
	* win/makefile.vc:	Add stub library to necessary link lines.

2009-11-23  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclThreadTest.c (NewTestThread): [Bug 2901803]: Further
	machinations to get NewTestThread actually to launch the thread, not
	just compile.

2009-11-22  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclThreadTest.c (NewTestThread): [Bug 2901803]: Fix small
	error in function naming which blocked a threaded test build.

2009-11-19  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/Makefile.in:	Create tcltest86.dll as dynamic Tcltest
				package.
	* generic/tclTest.c:	Remove extraneous prototypes, follow-up to
	* generic/tclTestObj.c:	[Bug 2883850]
	* tests/chanio.test:	Test-cases for fixed [Bug 2849797]
	* tests/io.test:
	* tests/safe.test:	Fix safe-10.1 and safe-10.4 test cases, making
				the wrong assumption that Tcltest is a static
				package.
	* generic/tclEncoding.c:[Bug 2857044]: Updated freeIntRepProc routines
	* generic/tclVar.c:	so that they set the typePtr field to NULL so
				that the Tcl_Obj is not left in an
				inconsistent state.
	* unix/tcl.m4:		[Patch 2883533]: tcl.m4 support for Haiku OS
	* unix/configure:	autoconf-2.59

2009-11-19  Don Porter  <dgp@users.sourceforge.net>

	* unix/tclAppInit.c:	[Bug 2883850, 2900542]: Repair broken build of
	* win/tclAppInit.c:	the tcltest executable.

2009-11-19  Donal K. Fellows  <dkf@users.sf.net>

	* library/auto.tcl (tcl_findLibrary):
	* library/clock.tcl (MakeUniquePrefixRegexp, MakeParseCodeFromFields)
	(SetupTimeZone, ProcessPosixTimeZone):	Restored the use of a literal
	* library/history.tcl (HistAdd):	'then' when following a multi-
	* library/safe.tcl (interpConfigure):	line test expresssion. It's an
	* library/tm.tcl (UnknownHandler):	aid to readability then.

2009-11-19  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.h:      Make all internal initialization
	* generic/tclTest.c:     routines MODULE_SCOPE
	* generic/tclTestObj.c:
	* generic/tclTestProcBodyObj.c:
	* generic/tclThreadTest.c:
	* unix/Makefile.in:      Fix [Bug 2883850]: pkgIndex.tcl doesn't
	* unix/tclAppInit.c:     get created with static Tcl build
	* unix/tclXtTest.c:
	* unix/tclXtNotify.c:
	* unix/tclUnixTest.c:
	* win/Makefile.in:
	* win/tcl.m4:
	* win/configure:         (regenerated)
	* win/tclAppInit.c:
	* win/tclWinDde.c:       Always compile with Stubs.
	* win/tclWinReg.c:
	* win/tclWinTest.c:

2009-11-18  Jan Nijtmans  <nijtmans@users.sf.net>

	* doc/CrtChannel.3:	[Bug 2849797]: Fix channel name inconsistences
	* generic/tclIORChan.c:	as suggested by DKF.
	* generic/tclIO.c:	Minor *** POTENTIAL INCOMPATIBILITY ***
				because Tcl_CreateChannel() and derivatives
				now sometimes ignore their "chanName"
				argument.

	* generic/tclAsync.c:	Eliminate various gcc warnings (with -Wextra)
	* generic/tclBasic.c
	* generic/tclBinary.c
	* generic/tclCmdAH.c
	* generic/tclCmdIL.c
	* generic/tclCmdMZ.c
	* generic/tclCompile.c
	* generic/tclDate.c
	* generic/tclExecute.c
	* generic/tclDictObj.c
	* generic/tclIndexObj.c
	* generic/tclIOCmd.c
	* generic/tclIOUtil.c
	* generic/tclIORTrans.c
	* generic/tclOO.c
	* generic/tclZlib.c
	* generic/tclGetDate.y
	* win/tclWinInit.c
	* win/tclWinChan.c
	* win/tclWinConsole.c
	* win/tclWinNotify.c
	* win/tclWinReg.c
	* library/auto.tcl:		Eliminate "then" keyword
	* library/clock.tcl
	* library/history.tcl
	* library/safe.tcl
	* library/tm.tcl
	* library/http/http.tcl:	Eliminate unnecessary spaces
	* library/http1.0/http.tcl
	* library/msgcat/msgcat.tcl
	* library/opt/optparse.tcl
	* library/platform/platform.tcl
	* tools/tcltk-man2html.tcl
	* tools/tclZIC.tcl
	* tools/tsdPerf.c

2009-11-17  Andreas Kupries  <andreask@activestate.com>

	* unix/tclUnixChan.c (TtyParseMode): Partial undo of Donal's tidy-up
	from a few days ago (2009-11-9, not in ChangeLog). It seems that
	strchr is apparently a macro on AIX and reacts badly to pre-processor
	directives in its arguments.

2009-11-16  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclEncoding.c:  [Bug 2891556]: Fix and improve test to
	* generic/tclTest.c:	  detect similar manifestations in the future.
	* tests/encoding.test:    Add tcltest support for finalization.

2009-11-15  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/tclWinDde.c: Avoid gcc compiler warning by explicitly casting
	DdeCreateStringHandle argument.

2009-11-12  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c (CopyData): [Bug 2895565]: Dropped bogosity which
	* tests/io.test: used the number of _written_ bytes or character to
	update the counters for the read bytes/characters. New test io-53.11.
	This is a forward port from the 8.5 branch.

2009-11-11  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclClock.c (TclClockInit):    Do not create [clock] support
	commands in safe interps.

2009-11-11  Jan Nijtmans  <nijtmans@users.sf.net>

	* library/http/http.tcl (http::geturl): [Bug 2891171]: URL checking
	too strict when using multiple question marks.
	* tests/http.test
	* library/http/pkgIndex.tcl:  Bump to http 2.8.2
	* unix/Makefile.in:
	* win/Makefile.in:

2009-11-11  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclIO.c: Fix [Bug 2888099] (close discards ENOSPC error) by
	saving the errno from the first of two FlushChannel()s. Uneasy to
	test; might need specific channel drivers. Four-hands with aku.

2009-11-10  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* tests/winFCmd.test: Cleanup directories that have been set chmod
	000. On Windows7 and Vista we really have no access and these were
	getting left behind.
	A few tests were changed to reflect the intent of the test where
	setting a directory chmod 000 should prevent any modification. This
	restriction was ignored on XP but is honoured on Vista

2009-11-10  Andreas Kupries  <andreask@activestate.com>

	* generic/tclBasic.c: Plug another leak in TCL_EVAL_DIRECT evaluation.
	Forward port from Tcl 8.5 branch, change by Don Porter.

	* generic/tclObj.c: [Bug 2895323]: Plug memory leak in
	TclContinuationsEnter(). Forward port from Tcl 8.5 branch, change by
	Don Porter.

2009-11-09  Stuart Cassoff  <stwo@users.sf.net>

	* win/README: [bug 2459744]: Removed outdated Msys + Mingw info.

2009-11-09  Andreas Kupries  <andreask@activestate.com>

	* generic/tclBasic.c (TclEvalObjEx): Moved the #280 decrement of
	refCount for the file path out of the branch after the whole
	conditional, closing a memory leak. Added clause on structure type to
	prevent seg.faulting. Forward port from valgrinding the Tcl 8.5
	branch.

	* tests/info.test: Resolve ambiguous resolution of variable "res".
	Forward port from 8.5

2009-11-08  Donal K. Fellows  <dkf@users.sf.net>

	* doc/string.n (bytelength): Noted that this command is not a good
	thing to use, and suggested a better alternatve. Also factored out the
	description of the indices into its own section.

2009-11-07  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* tests/fCmd.test: [Bug 2891026]: Exclude tests using chmod 555
	directories on vista and win7. The current user has access denied and
	so cannot rename the directory without admin privileges.

2009-11-06  Andreas Kupries  <andreask@activestate.com>

	* library/safe.tcl (::safe::Setup): Added documentation of the
	contents of the state array. Also killed the 'InterpState' procedure
	with its upleveled variable/upvar combination, and replaced all uses
	with 'namespace upvar'.

2009-11-05  Andreas Kupries  <andreask@activestate.com>

	* library/safe.tcl: A series of patches which bring the SafeBase up to
	date with code guidelines, Tcl's features, also eliminating a number
	of inefficiencies along the way.
	(1) Changed all procedure names to be fully qualified.
	(2) Moved the procedures out of the namespace eval. Kept their
	locations. IOW, broke the namespace eval apart into small sections not
	covering the procedure definitions.
	(3) Reindented the code. Just lots of whitespace changes.
	Functionality unchanged.
	(4) Moved the multiple namespace eval's around. Command export at the
	top, everything else (var decls, argument parsing setup) at the
	bottom.
	(5) Moved the argument parsing setup into a procedure called when the
	code is loaded. Easier management of temporary data.
	(6) Replaced several uses of 'Set' with calls to the new procedure
	'InterpState' and direct access to the per-slave state array.
	(7) Replaced the remaining uses of 'Set' and others outside of the
	path/token handling, and deleted a number of procedures related to
	state array access which are not used any longer.
	(8) Converted the path token system to cache normalized paths and path
	<-> token conversions. Removed more procedures not used any longer.
	Removed the test cases 4.3 and 4.4 from safe.test. They were testing
	the now deleted command "InterpStateName".
	(9) Changed the log command setup so that logging is compiled out
	completely when disabled (default).
	(10) Misc. cleanup. Inlined IsInterp into CheckInterp, its only user.
	Consistent 'return -code error' for error reporting. Updated to use
	modern features (lassign, in/ni, dicts). The latter are used to keep a
	reverse path -> token map and quicker check of existence.
	(11) Fixed [Bug 2854929]: Recurse into all subdirs under all TM root
	dirs and put them on the access path.

2009-11-02  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata/Asia/Novokuznetsk: New tzdata locale for Kemerovo
	oblast', which now keeps Novosibirsk time and not Kranoyarsk time.
	* library/tzdata/Asia/Damascus: Syrian DST changes.
	* library/tzdata/Asia/Hong_Kong: Hong Kong historic DST corrections.
	Olson tzdata2009q.

2009-11-02  Donal K. Fellows  <dkf@users.sf.net>

	* doc/object.n (DESCRIPTION): Substantive revision to make it clearer
	what the fundamental semantics of an object actually are.

2009-11-01  Joe Mistachkin  <joe@mistachkin.com>

	* doc/Cancel.3: Minor cosmetic fixes.
	* win/makefile.vc: Make htmlhelp target work again.  An extra set of
	double quotes around the definition of the HTML help compiler tool
	appears to be required.  Previously, there was one set of double
	quotes around the definition of the tool and one around the actual
	invocation.  This led to confusion because it was the only such tool
	path to include double quotes around its invocation.  Also, it was
	somewhat inflexible in the event that somebody needed to override the
	tool command to include arguments.  Therefore, even though it may look
	"wrong", there are now two double quotes on either side of the tool
	path definition.  This fixes the problem that currently prevents the
	htmlhelp target from building and maintains flexibility in case
	somebody needs to override it via the command line or an environment
	variable.

2009-11-01  Joe English  <jenglish@users.sourceforge.net>

	* doc/Eval.3, doc/Cancel.3: Move TIP#285 routines out of Eval.3 into
	their own manpage.

2009-10-31  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclBasic.c (ExprRoundFunc): [Bug 2889593]: Correctly report
	the expected number of arguments when generating an error for round().

2009-10-30  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* tests/tcltest.test: When creating the notwritabledir we deny the
	current user access to delete the file. We must grant this right when
	we cleanup. Required on Windows 7 when the user does not automatically
	have administrator rights.

2009-10-29  Don Porter  <dgp@users.sourceforge.net>

	* generic/tcl.h:        Changed the typedef for the mp_digit type
	from:
		typedef unsigned long mp_digit;
	to:
		typedef unsigned int mp_digit;
	For 32-bit builds where "long" and "int" are two names for the same
	thing, this is no change at all.  For 64-bit builds, though, this
	causes the dp[] array of an mp_int to be made up of 32-bit elements
	instead of 64-bit elements.  This is a huge improvement because
	details elsewhere in the mp_int implementation cause only 28 bits of
	each element to be actually used storing number data.  Without this
	change bignums are over 50% wasted space on 64-bit systems.  [Bug
	2800740].

	***POTENTIAL INCOMPATIBILITY***
	For 64-bit builds, callers of routines with (mp_digit) or (mp_digit *)
	arguments *will*, and callers of routines with (mp_int *) arguments
	*may* suffer both binary and stubs incompatibilities with Tcl releases
	8.5.0 - 8.5.7.  Such possibilities should be checked, and if such
	incompatibilities are present, suitable [package require] requirements
	on the Tcl release should be put in place to keep such built code
	[load]-ing only in Tcl interps that are compatible.

2009-10-29  Donal K. Fellows  <dkf@users.sf.net>

	* tests/dict.test: Make variable-clean and simplify tests by utilizing
	the fact that dictionaries have defined orders.

	* generic/tclZlib.c (TclZlibCmd): Remove accidental C99-ism which
	reportedly makes the AIX native compiler choke.

2009-10-29  Kevin B. Kenny  <kennykb@acm.org>

	* library/clock.tcl (LocalizeFormat):
	* tests/clock.test (clock-67.1):
	[Bug 2819334]: Corrected a problem where '%%' followed by a letter in
	a format group could expand recursively: %%R would turn into %%H:%M:%S

2009-10-28  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclLiteral.c:	[Bug 2888044]: Fixed 2 bugs.
	* tests/info.test:	First, as noted in the comments of the
	TclCleanupLiteralTable routine, since the teardown of the intrep of
	one Tcl_Obj can cause the teardown of others in the same table, the
	full table cleanup must be done with care, but the code did not
	contain the same care demanded in the comment.  Second, recent
	additions to the info.test file had poor hygiene, leaving an array
	variable ::a lying around, which breaks later interp.test tests during
	a -singleproc 1 run of the test suite.

2009-10-28  Kevin B. Kenny  <kennykb@acm.org>

	* tests/fileName.test (fileName-20.[78]): Corrected poor test
	hygiene (failure to save and restore the working directory) that
	caused these two tests to fail on Windows (and [Bug 2806250] to be
	reopened).

2009-10-27  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclPathObj.c: [Bug 2884203]: Missing refcount on cached
	normalized path caused crashes.

2009-10-27  Kevin B. Kenny  <kennykb@acm.org>

	* library/clock.tcl (ParseClockScanFormat): [Bug 2886852]: Corrected a
	problem where [clock scan] didn't load the timezone soon enough when
	processing a time format that lacked a complete date.
	* tests/clock.test (clock-66.1):
	Added a test case for the above bug.
	* library/tzdata/America/Argentina/Buenos_Aires:
	* library/tzdata/America/Argentina/Cordoba:
	* library/tzdata/America/Argentina/San_Luis:
	* library/tzdata/America/Argentina/Tucuman:
	New DST rules for Argentina. (Olson's tzdata2009p.)

2009-10-26  Don Porter  <dgp@users.sourceforge.net>

	* unix/Makefile.in:	Remove $(PACKAGE).* and prototype from the
	`make distclean` target.  Completes 2009-10-20 commit.

2009-10-24  Kevin B. Kenny  <kennykb@acm.org>

	* library/clock.tcl (ProcessPosixTimeZone):
	Corrected a regression in the fix to [Bug 2207436] that caused
	[clock] to apply EU daylight saving time rules in the US.
	Thanks to Karl Lehenbauer for reporting this regression.
	* tests/clock.test (clock-52.4):
	Added a regression test for the above bug.
	* library/tzdata/Asia/Dhaka:
	* library/tzdata/Asia/Karachi:
	New DST rules for Bangladesh and Pakistan. (Olson's tzdata2009o.)

2009-10-23  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c (FlushChannel): Skip OutputProc for low-level
	0-length writes. When closing pipes which have already been closed
	not skipping leads to spurious SIG_PIPE signals. Reported by
	Mikhail Teterin <mi+thun@aldan.algebra.com>.

2009-10-22  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOBasic.c (TclOO_Object_VarName): [Bug 2883857]: Allow
	the passing of array element names through this method.

2009-10-21  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclPosixStr.c: [Bug 2882561]: Work around oddity on Haiku OS
	where SIGSEGV and SIGBUS are the same value.

	* generic/tclTrace.c (StringTraceProc): [Bug 2881259]: Added back cast
	to work around silly bug in MSVC's handling of auto-casting.

2009-10-20  Don Porter  <dgp@users.sourceforge.net>

	* unix/Makefile.in:	Removed the long outdated and broken targets
	package-* that were for building Solaris packages.  Appears that the
	pieces needed for these targets to function have never been present in
	the current era of Tcl development and belong completely to Tcl
	pre-history.

2009-10-19  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclIO.c:      [Patch 2107634]: Revised ReadChars and
	FilterInputBytes routines to permit reads to continue up to the string
	limits of Tcl values.  Before revisions, large read attempts could
	panic when as little as half the limiting value length was reached.
	Thanks to Sean Morrison and Bob Parker for their roles in the fix.

2009-10-18  Joe Mistachkin  <joe@mistachkin.com>

	* generic/tclObj.c (TclDbDumpActiveObjects, TclDbInitNewObj)
	(Tcl_DbIncrRefCount, Tcl_DbDecrRefCount, Tcl_DbIsShared):
	[Bug 2871908]: Enforce separation of concerns between the lineCLPtr
	and objThreadMap thread specific data members.

2009-10-18  Joe Mistachkin  <joe@mistachkin.com>

	* tests/thread.test (thread-4.[345]): [Bug 1565466]: Correct tests to
	save their error state before the final call to threadReap just in
	case it triggers an "invalid thread id" error.  This error can occur
	if one or more of the target threads has exited prior to the attempt
	to send it an asynchronous exit command.

2009-10-17  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclVar.c (UnsetVarStruct, TclDeleteNamespaceVars)
	(TclDeleteCompiledLocalVars, DeleteArray):
	* generic/tclTrace.c (Tcl_UntraceVar2): [Bug 2629338]: Stop traces
	that are deleted part way through (a feature used by tdom) from
	causing freed memory to be accessed.

2009-10-08  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclDictObj.c (DictIncrCmd): [Bug 2874678]: Don't leak any
	bignums when doing [dict incr] with a value.
	* tests/dict.test (dict-19.3): Memory leak detection code.

2009-10-07  Andreas Kupries  <andreask@activestate.com>

	* generic/tclObj.c: [Bug 2871908]: Plug memory leaks of objThreadMap
	and lineCLPtr hashtables.  Also make the names of the continuation
	line information initialization and finalization functions more
	consistent. Patch supplied by Joe Mistachkin <joe@mistachkin.com>.

	* generic/tclIORChan.c (ErrnoReturn): Replace hardwired constant 11
	with proper errno #define, EAGAIN. What was I thinking? The BSD's have
	a different errno assignment and break with the hardwired number.
	Reported by emiliano on the chat.

2009-10-06  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInterp.c (SlaveEval): Agressive stomping of internal reps
	was added as part of the NRE patch of 2008-07-13.  This doesn't appear
	to actually be needed, and it hurts quite a bit when large lists lose
	their intreps and require reparsing.  Thanks to Ashok Nadkarni for
	reporting the problem.

	* generic/tclTomMathInt.h (new): Public header tclTomMath.h had
	* generic/tclTomMath.h:	dependence on private headers, breaking use
	* generic/tommath.h:	by extensions [Bug 1941434].

2009-10-05  Andreas Kupries  <andreask@activestate.com>

	* library/safe.tcl (AliasGlob): Fixed conversion of catch to
	try/finally, it had an 'on ok msg' branch missing, causing a silent
	error immediately, and bogus glob results, breaking search for Tcl
	modules.

2009-10-04  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/tclMacOSXBundle.c:	[Bug 2569449]: Workaround CF memory
	* unix/tclUnixInit.c:		managment bug in Mac OS X 10.4 &
					earlier.

2009-10-02  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata/Africa/Cairo:
	* library/tzdata/Asia/Gaza:
	* library/tzdata/Asia/Karachi:
	* library/tzdata/Pacific/Apia:	Olson's tzdata2009n.

2009-09-29  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclDictObj.c:		[Bug 2857044]: Updated freeIntRepProc
	* generic/tclExecute.c:		routines so that they set the typePtr
	* generic/tclIO.c:		field to NULL so that the Tcl_Obj is
	* generic/tclIndexObj.c:	not left in an inconsistent state.
	* generic/tclInt.h:
	* generic/tclListObj.c:
	* generic/tclNamesp.c:
	* generic/tclOOCall.c:
	* generic/tclObj.c:
	* generic/tclPathObj.c:
	* generic/tclProc.c:
	* generic/tclRegexp.c:
	* generic/tclStringObj.c:

	* generic/tclAlloc.c:           Cleaned up various routines in the
	* generic/tclCkalloc.c:         call stacks for memory allocation to
	* generic/tclInt.h:             guarantee that any size values computed
	* generic/tclThreadAlloc.c:     are within the domains of the routines
	they get passed to.  [Bugs 2557696 and 2557796].

2009-09-28  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCmdMZ.c:	Replaced TclProcessReturn() calls with
	* tests/error.test:	Tcl_SetReturnOptions() calls as a simple fix
	for [Bug 2855247].  Thanks to Anton Kovalenko for the report and fix.
	Additional fixes for other failures demonstrated by new tests.

2009-09-27  Don Porter  <dgp@users.sourceforge.net>

	* tests/error.test (error-15.8.*):	Coverage tests illustrating
	flaws in the propagation of return options by [try].

2009-09-26  Donal K. Fellows  <dkf@users.sf.net>

	* unix/tclooConfig.sh, win/tclooConfig.sh: [Bug 2026844]: Added dummy
	versions of tclooConfig.sh that make it easier to build extensions
	against both Tcl8.5+TclOO-standalone and Tcl8.6.

2009-09-24  Don Porter  <dgp@users.sourceforge.net>

	TIP #356 IMPLEMENTATION

	* generic/tcl.decls:	Promote internal routine TclNRSubstObj()
	* generic/tclCmdMZ.c:	to public Tcl_NRSubstObj().  Still needs docs.
	* generic/tclCompile.c:
	* generic/tclInt.h:

	* generic/tclDecls.h:	make genstubs
	* generic/tclStubInit.c:

2009-09-23  Miguel Sofer  <msofer@users.sf.net>

	* doc/namespace.n: the description of [namespace unknown] failed
	to mention [namespace path]: fixed. Thx emiliano.

2009-09-21  Mo DeJong  <mdejong@users.sourceforge.net>

	* tests/regexp.test: Added check for error message from
	unbalanced [] in regexp. Added additional simple test cases
	of basic regsub command.

2009-09-21  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompile.c:	Correct botch in the conversion of
	Tcl_SubstObj().  Thanks to Kevin Kenny for detection and report.

2009-09-17  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompile.c:	Re-implement Tcl_SubstObj() as a simple
	* generic/tclParse.c:	wrapper around TclNRSubstObj().  This has
	* tests/basic.test:	the effect of caching compiled bytecode in
	* tests/parse.test:	the value to be substituted.  Note that
	Tcl_SubstObj() now exists only for extensions.  Tcl itself no longer
	makes any use of it.  Note also that TclSubstTokens() is now reachable
	only by Tcl_EvalEx() and Tcl_ParseVar() so tests aiming to test its
	functioning needed adjustment to still have the intended effect.

2009-09-16  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclObj.c:   Extended ::tcl::unsupported::representation.

2009-09-11  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Completed the NR-enabling of [subst].
	* generic/tclCmdMZ.c:	[Bug 2314561].
	* generic/tclCompCmds.c:
	* generic/tclCompile.c:
	* generic/tclInt.h:
	* tests/coroutine.test:
	* tests/parse.test:

2009-09-11  Donal K. Fellows  <dkf@users.sf.net>

	* tests/http.test: Added in cleaning up of http tokens for each test
	to reduce amount of global-variable pollution.

2009-09-10  Donal K. Fellows  <dkf@users.sf.net>

	* library/http/http.tcl (http::Event): [Bug 2849860]: Handle charset
	names in double quotes; some servers like generating them like that.

2009-09-07  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclParse.c:	[Bug 2850901]: Corrected line counting error
	* tests/into.test:	in multi-command script substitutions.

2009-09-07  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclExecute.c:	Fix potential uninitialized variable use and
	* generic/tclFCmd.c:	null dereference flagged by clang static
	* generic/tclProc.c:	analyzer.
	* generic/tclTimer.c:
	* generic/tclUtf.c:

	* generic/tclExecute.c:	Silence false positives from clang static
	* generic/tclIO.c:	analyzer about potential null dereference.
	* generic/tclScan.c:
	* generic/tclCompExpr.c:

2009-09-04  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompCmds.c (TclCompileSubstCmd): [Bug 2314561]:
	* generic/tclBasic.c:	Added a bytecode compiler routine for the
	* generic/tclCmdMZ.c:	[subst] command. This is a partial solution to
	* generic/tclCompile.c:	the need to NR-enable [subst] since bytecode
	* generic/tclCompile.h:	execution is already NR-enabled. Two new
	* generic/tclExecute.c:	bytecode instructions, INST_NOP and
	* generic/tclInt.h:	INST_RETURN_CODE_BRANCH were added to support
	* generic/tclParse.c:	the new routine.  INST_RETURN_CODE_BRANCH is
	* tests/basic.test:	likely to be useful in any future effort to
	* tests/info.test:	add a bytecode compiler routine for [try].
	* tests/parse.test:

2009-09-03  Donal K. Fellows  <dkf@users.sf.net>

	* doc/LinkVar.3: [Bug 2844962]: Added documentation of issues relating
	to use of this API in a multi-threaded environment.

2009-09-01  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIORTrans.c (ReflectInput): Remove error response to
	0-result from method 'limit?' of transformations. Return the number of
	copied bytes instead, which is possibly nothing. The latter then
	triggers EOF handling in the higher layers, making the 0-result of
	limit? the way to inject artificial EOF's into the data stream.

2009-09-01  Don Porter  <dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl:  Bump to tcltest 2.3.2 after revision
	* library/tcltest/pkgIndex.tcl: to verbose error message.
	* unix/Makefile.in:
	* win/Makefile.in:

2009-08-27  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c:       [Bug 2845535]: A few more string
	overflow cases in [format].

2009-08-25  Andreas Kupries  <andreask@activestate.com>

	* generic/tclBasic.c (Tcl_CreateInterp, Tcl_EvalTokensStandard)
	(Tcl_EvalEx, TclEvalEx, TclAdvanceContinuations, TclNREvalObjEx):
	* generic/tclCmdMZ.c (Tcl_SwitchObjCmd, TclListLines):
	* generic/tclCompCmds.c (*):
	* generic/tclCompile.c (TclSetByteCodeFromAny, TclInitCompileEnv)
	(TclFreeCompileEnv, TclCompileScript, TclCompileTokens):
	* generic/tclCompile.h (CompileEnv):
	* generic/tclInt.h (ContLineLoc, Interp):
	* generic/tclObj.c (ThreadSpecificData, ContLineLocFree)
	(TclThreadFinalizeObjects, TclInitObjSubsystem, TclContinuationsEnter,
	(TclContinuationsEnterDerived, TclContinuationsCopy, TclFreeObj)
	(TclContinuationsGet):
	* generic/tclParse.c (TclSubstTokens, Tcl_SubstObj):
	* generic/tclProc.c (TclCreateProc):
	* generic/tclVar.c (TclPtrSetVar):
	* tests/info.test (info-30.0-24):

	Extended the parser, compiler, and execution engine with code and
	attendant data structures tracking the position of continuation lines
	which are not visible in the resulting script Tcl_Obj*'s, to properly
	account for them while counting lines for #280.

2009-08-24  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclInt.h: Annotate Tcl_Panic as noreturn for clang static
	analyzer in PURIFY builds, replacing preprocessor/assert technique.

	* macosx/tclMacOSXNotify.c: Fix multiple issues with nested event loops
	when CoreFoundation notifier is running in embedded mode. (Fixes
	problems in TkAqua Cocoa reported by Youness Alaoui on tcl-mac)

2009-08-21  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclFileName.c: Correct regression in [Bug 2837800] fix.
	* tests/fileName.test:

2009-08-20  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclFileName.c: [Bug 2837800]: Correct the result produced by
	[glob */test] when * matches something like ~foo.

	* generic/tclPathObj.c: [Bug 2806250]: Prevent the storage of strings
	starting with ~ in the "tail" part (normPathPtr field) of the path
	intrep when PATHFLAGS != 0.  This establishes the assumptions relied
	on elsewhere that the name stored there is a relative path.  Also
	refactored to make an AppendPath() routine instead of the cut/paste
	stanzas that were littered throughout.

2009-08-20  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdIL.c (TclNRIfObjCmd): [Bug 2823276]: Make [if]
	NRE-safe on all arguments when interpreted.
	(Tcl_LsortObjCmd): Close off memory leak.

2009-08-19  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdAH.c (TclNRForObjCmd, etc.): [Bug 2823276]: Make [for]
	and [while] into NRE-safe commands, even when interpreted.

2009-08-18  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclPathObj.c: [Bug 2837800]: Added NULL check to prevent
	* tests/fileName.test:  crashes during [glob].

2009-08-16  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/dltest/pkge.c:  const addition
	* unix/tclUnixThrd.c:  Use <pthread.h> in stead of "pthread.h"
	* win/tclWinDde.c:     Eliminate some more gcc warnings
	* win/tclWinReg.c:
	* generic/tclInt.h:    Change ForIterData, make it const-safe.
	* generic/tclCmdAH.c:

2009-08-12  Don Porter  <dgp@users.sourceforge.net>

	TIP #353 IMPLEMENTATION

	* doc/NRE.3:		New public routine Tcl_NRExprObj() permits
	* generic/tcl.decls:	extension commands to evaluate Tcl expressions
	* generic/tclBasic.c:	in NR-enabled command procedures.
	* generic/tclCmdAH.c:
	* generic/tclExecute.c:
	* generic/tclInt.h:
	* generic/tclObj.c:
	* tests/expr.test:

	* generic/tclDecls.h:		make genstubs
	* generic/tclStubInit.c:

2009-08-06  Andreas Kupries  <andreask@activestate.com>

	* doc/refchan.n [Bug 2827000]: Extended the implementation of
	* generic/tclIORChan.c: reflective channels (TIP 219, method
	* tests/ioCmd.test: 'read'), enabling handlers to signal EAGAIN to
	indicate 'no data, but not at EOF either', and other system
	errors. Updated documentation, extended testsuite (New test cases
	iocmd*-23.{9,10}).

2009-08-02  Miguel Sofer  <msofer@users.sf.net>

	* tests/coroutine.test: fix testfile cleanup

2009-08-02  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclObj.c (Tcl_RepresentationCmd): Added an unsupported
	command for reporting the representation of an object. Result string
	is deliberately a bit obstructive so that people are not encouraged to
	make code that depends on it; it's a debugging tool only!

	* unix/tclUnixFCmd.c (GetOwnerAttribute, SetOwnerAttribute)
	(GetGroupAttribute, SetGroupAttribute): [Bug 1942222]: Stop calling
	* unix/tclUnixFile.c (TclpGetUserHome): endpwent() and endgrent();
	they've been unnecessary for ages.

2009-08-02  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tclWin32Dll.c: Eliminate TclWinResetInterfaceEncodings, since it
	* win/tclWinInit.c:  does exactly the same as TclWinEncodingsCleanup,
	* win/tclWinInt.h:   make sure that tclWinProcs and
			     tclWinTCharEncoding are always set and reset
			     concurrently.
	* win/tclWinFCmd.c:  Correct check for win95

2009-07-31  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c: [Bug 2830354]:	Corrected failure to
	* tests/format.test:		grow buffer when format spec request
	large width floating point values.  Thanks to Clemens Misch.

2009-07-26  Donal K. Fellows  <dkf@users.sf.net>

	* library/auto.tcl (tcl_findLibrary, auto_mkindex):
	* library/package.tcl (pkg_mkIndex, tclPkgUnknown, MacOSXPkgUnknown):
	* library/safe.tcl (interpAddToAccessPath, interpDelete, AliasGlob):
	(AliasSource, AliasLoad, AliasEncoding):
	* library/tm.tcl (UnknownHandler): Simplify by swapping some [catch]
	gymnastics for use of [try].

2009-07-26 Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* tools/genStubs.tcl: Forced LF translation when generating .h's to
	avoid spurious diffs when regenerating on a Windows box.

2009-07-26  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/Makefile.in: [Bug 2827066]: msys build --enable-symbols broken
	* win/tcl.m4:	   And modified the same for unicows.dll, as a
	* win/configure:   preparation for [Enh 2819611].

2009-07-25  Donal K. Fellows  <dkf@users.sf.net>

	* library/history.tcl (history): Reworked the history mechanism in
	terms of ensembles, rather than the ad hoc ensemble-lite mechanism
	used previously.

2009-07-24  Donal K. Fellows  <dkf@users.sf.net>

	* doc/self.n (self class): [Bug 2704302]: Add some text to make it
	clearer how to get the name of the current object's class.

2009-07-23  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c (Tcl_GetChannelHandle): [Bug 2826248]: Do not crash
	* generic/tclPipe.c (FileForRedirect): for getHandleProc == NULL, this
	is allowed. Provide a nice error message in the bypass area. Updated
	caller to check the bypass for a mesage. Bug reported by Andy
	Sonnenburg <andy22286@users.sourceforge.net>

2009-07-23  Joe Mistachkin  <joe@mistachkin.com>

	* generic/tclNotify.c: [Bug 2820349]: Ensure that queued events are
	freed once processed.

2009-07-22  Jan Nijtmans  <nijtmans@users.sf.net>

	* macosx/tclMacOSXFCmd.c: CONST -> const
	* generic/tclGetDate.y:
	* generic/tclDate.c:
	* generic/tclLiteral.c: (char *) cast in ckfree call
	* generic/tclPanic.c: [Feature Request 2814786]: remove TclpPanic
	* generic/tclInt.h
	* unix/tclUnixPort.h
	* win/tclWinPort.h

2009-07-22 Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclEvent.c: [Bug 2001201 again]: Refined the 20090617 patch
	on [exit] streamlining, so that it now correctly calls thread exit
	handlers for the calling thread, including <Destroy> bindings in Tk.

2009-07-21  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata/Asia/Dhaka:
	* library/tzdata/Indian/Mauritius: Olson's tzdata2009k.

2009-07-20  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdMZ.c (StringIsCmd): Reorganize so that [string is] is
	more efficient when parsing things that are correct, at a cost of
	making the empty string test slightly more costly. With this, the cost
	of doing [string is integer -strict $x] matches [catch {expr {$x+0}}]
	in the successful case, and greatly outstrips it in the failing case.

2009-07-19  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.decls, generic/tclOO.c (Tcl_GetObjectName): Expose a
	function for efficiently returning the current name of an object.

2009-07-18  Daniel Steffen  <das@users.sourceforge.net>

	* unix/Makefile.in: Define NDEBUG in optimized (non-symbols) build to
	disable NRE assert()s and threaded allocator range checks.

2009-07-16  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBinary.c:	Removed unused variables.
	* generic/tclCmdIL.c:
	* generic/tclCompile.c:
	* generic/tclExecute.c:
	* generic/tclHash.c:
	* generic/tclIOUtil.c:
	* generic/tclVar.c:

	* generic/tclBasic.c:	Silence compiler warnings about ClientData.
	* generic/tclProc.c:

	* generic/tclScan.c:    Typo in ACCEPT_NAN configuration.

	* generic/tclStrToD.c:  [Bug 2819200]: Set floating point control
	register on MIPS systems so that the gradual underflow expected by Tcl
	is in effect.

2009-07-15  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclInt.h (Namespace):		   Added machinery to allow
	* generic/tclNamesp.c (many functions):	   reduction of memory used
	* generic/tclResolve.c (BumpCmdRefEpochs): by namespaces. Currently
	#ifdef'ed out because of compatibility concerns.

	* generic/tclInt.decls: Added four functions for better integration
	with itcl-ng.

2009-07-14  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclInt.h (TclNRSwitchObjCmd):
	* generic/tclBasic.c (builtInCmds):
	* generic/tclCmdMZ.c (Tcl_SwitchObjCmd):
	* tests/switch.test (switch-15.1):
	[Bug 2821401]: Make non-bytecoded [switch] command aware of NRE.

2009-07-13  Andreas Kupries  <andreask@activestate.com>

	* generic/tclCompile.c (TclInitCompileEnv, EnterCmdWordIndex)
	(TclCleanupByteCode, TclCompileScript):
	* generic/tclExecute.c (TclCompileObj, TclExecuteByteCode):
	* tclCompile.h (ExtCmdLoc):
	* tclInt.h (ExtIndex, CFWordBC, CmdFrame):
	* tclBasic.c (DeleteInterpProc, TclArgumentBCEnter)
	(TclArgumentBCRelease, TclArgumentGet, SAVE_CONTEXT)
	(RESTORE_CONTEXT, NRCoroutineExitCallback, TclNRCoroutineObjCmd):
	* generic/tclCmdAH.c (TclNRForObjCmd, TclNRForIterCallback,
	(ForNextCallback):
	* generic/tclCmdMZ.c (TclNRWhileObjCmd):

	Extended the bytecode compiler initialization to recognize the
	compilation of whole files (NRE enabled 'source' command) and switch
	to the counting of absolute lines in that case.

	Further extended the bytecode compiler to track the start line in the
	generated information, and modified the bytecode execution to
	recompile an object if the location as per the calling context doesn't
	match the location saved in the bytecode. This part could be optimized
	more by using more memory to keep all possibilities which occur
	around, or by just adjusting the location information instead of a
	total recompile.

	Reworked the handling of literal command arguments in bytecode to be
	saved (compiler) and used (execution) per command (See the
	TCL_INVOKE_STK* instructions), and not per the whole bytecode. This,
	and the previous change remove the problems with location data caused
	by literal sharing (across whole files, but also proc bodies).
	Simplified the associated datastructures (ExtIndex is gone, as is the
	function EnterCmdWordIndex).

	The last change causes the hashtable 'lineLABCPtr' to be state which
	has to be kept per coroutine, like the CmdFrame stack. Reworked the
	coroutine support code to create, delete and switch the information as
	needed. Further reworked the tailcall command as well, it has to pop
	its own arguments when run in a bytecode context to keep a proper
	stack in 'lineLABCPtr'.

	Fixed the mishandling of line information in the NRE-enabled 'for' and
	'while' commands introduced when both were made to share their
	iteration callbacks without taking into account that the loop body is
	found in different words of the command. Introduced a separate data
	structure to hold all the callback information, as we went over the
	limit of 4 direct client-data values for NRE callbacks.

	The above fixes [Bug 1605269].

2009-07-12  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdMZ.c (StringIndexCmd, StringEqualCmd, StringCmpCmd):
	* generic/tclExecute.c (TclExecuteByteCode): [Bug 2637173]: Factor out
	* generic/tclInt.h (TclIsPureByteArray):     the code to determine if
	* generic/tclUtil.c (TclStringMatchObj):     it is safe to work with
	byte arrays directly, so that we get the check correct _once_.

	* generic/tclOOCall.c (TclOOGetCallContext): [Bug 1895546]: Changed
	* generic/tclOO.c (TclOOObjectCmdCore):	     the way that the cache is
	managed so that when itcl does cunning things, those cunning things
	can be cached properly.

2009-07-11  Donal K. Fellows  <dkf@users.sf.net>

	* doc/vwait.n: Substantially increased the discussion of issues and
	work-arounds relating to nested vwaits, following discussion on the
	tcl-core mailing list on the topic.

2009-07-10  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* tests/zlib.test:   ZlibTransformClose may be called with a NULL
	* generic/tclZlib.c: interpreter during finalization and
	Tcl_SetChannelError requires a list. Added some tests to ensure error
	propagation from the zlib library to the interp.

2009-07-09  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* tests/zlib.test: [Bug 2818131]: Added tests and fixed a typo that
	broke [zlib push] for deflate format.

2009-07-09  Donal K. Fellows  <dkf@users.sf.net>

	* compat/mkstemp.c (mkstemp): [Bug 2819227]: Use rand() for random
	numbers as it is more portable.

2009-07-05  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclZlib.c (ZlibTransformWatch): Correct the handling of
	events so that channel transforms work with things like an asynch
	[chan copy]. Problem reported by Pat Thoyts.

2009-07-01  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* win/tclWinInt.h:   [Bug 2806622]: Handle the GetUserName API call
	* win/tclWin32Dll.c: via the tclWinProcs indirection structure. This
	* win/tclWinInit.c:  fixes a problem obtaining the username when the
	USERNAME environment variable is unset.

2009-06-30  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclInt.h:		Add assert macros for clang static
	* generic/tclPanic.c:		analyzer and redefine Tcl_Panic to
	* generic/tclStubInit.c:	assert after panic in clang PURIFY
					builds.

	* generic/tclCmdIL.c:		Add clang assert for false positive
					from static analyzer.

2009-06-26  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Tcl-Common.xcconfig:	 Update projects for Xcode 3.1 and
	* macosx/Tcl.xcode/*:		 3.2, standardize on gcc 4.2, remove
	* macosx/Tcl.xcodeproj/*:	 obsolete configurations and pre-Xcode
	* macosx/Tcl.pbproj/* (removed): project.

	* macosx/README:		 Update project docs, cleanup.

	* unix/Makefile.in:		 Update dist target for project
					 changes.

2009-06-24  Donal K. Fellows  <dkf@users.sf.net>

	* tests/oo.test (oo-19.1): [Bug 2811598]: Make more resilient.

2009-06-24  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* tests/http11.test: [Bug 2811492]: Clean up procs after testing.

2009-06-18  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCkalloc.c (MemoryCmd): [Bug 988703]:
	* generic/tclObj.c (ObjData, TclFinalizeThreadObjects): Add mechanism
	for discovering what Tcl_Objs are allocated when built for memory
	debugging. Developed by Joe Mistachkin.

2009-06-17 Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclEvent.c: Applied a patch by George Peter Staplin
	drastically reducing the ambition of [exit] wrt finalization, and
	thus solving many multi-thread teardown issues. [Bugs 2001201,
	486399, and possibly 597575, 990457, 1437595, 2750491]

2009-06-15  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c: sprintf() -> Tcl_ObjPrintf() conversion.

2009-06-15  Reinhard Max  <max@suse.de>

	* unix/tclUnixPort.h: Move all socket-related code from tclUnixChan.c
	* unix/tclUnixChan.c: to tclUnixSock.c.
	* unix/tclUnixSock.c:

2009-06-15  Donal K. Fellows  <dkf@users.sf.net>

	* tools/tcltk-man2html.tcl (make-man-pages): [Patch 557486]: Apply
	last remaining meaningful part of this patch, a clean up of some
	closing tags.

2009-06-13  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompile.c: [Bug 2802881]: The value stashed in
	* generic/tclProc.c:    iPtr->compiledProcPtr when compiling a proc
	* tests/execute.test:   survives too long. We only need it there long
	enough for the right TclInitCompileEnv() call to re-stash it into
	envPtr->procPtr.  Once that is done, the CompileEnv controls.  If we
	let the value of iPtr->compiledProcPtr linger, though, then any other
	bytecode compile operation that takes place will also have its
	CompileEnv initialized with it, and that's not correct.  The value is
	meant to control the compile of the proc body only, not other compile
	tasks that happen along.  Thanks to Carlos Tasada for discovering and
	reporting the problem.

2009-06-10  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c:       [Bug 2801413]: Revised [format] to not
	overflow the integer calculations computing the length of the %ll
	formats of really big integers.  Also added protections so that
	[format]s that would produce results overflowing the maximum string
	length of Tcl values throw a normal Tcl error instead of a panic.

	* generic/tclStringObj.c:	[Bug 2803109]: Corrected failures to
	deal with the "pure unicode" representation of an empty string.
	Thanks to Julian Noble for reporting the problem.

2006-06-09  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclGetDate.y: Fixed a thread safety bug in the generated
	* library/clock.tcl:    Bison parser (needed a %pure-parser
	* tests/clock.test:     declaration to avoid static variables).
				Discovered that the %pure-parser declaration
	                        allowed for returning the Bison error message
	                        to the Tcl caller in the event of a syntax
	                        error, so did so.
	* generic/tclDate.c: bison 2.3

2006-06-08  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata/Asia/Dhaka: New DST rule for Bangladesh. (Olson's
	tzdata2009i.)

2009-06-08  Donal K. Fellows  <dkf@users.sf.net>

	* doc/copy.n: Fix error in example spotted by Venkat Iyer.

2009-06-02  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclExecute.c: Replace dynamically-initialized table with a
	table of static constants in the lookup table for exponent operator
	computations that fit in a 64 bit integer result.

	* generic/tclExecute.c: [Bug 2798543]: Corrected implementations and
	selection logic of the INST_EXPON instruction.

2009-06-01  Don Porter  <dgp@users.sourceforge.net>

	* tests/expr.test:      [Bug 2798543]: Added many tests demonstrating
	the broken cases.

009-05-30  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata/Africa/Cairo:
	* library/tzdata/Asia/Amman: Olson's tzdata2009h.

2009-05-29  Andreas Kupries  <andreask@activestate.com>

	* library/platform/platform.tcl: Fixed handling of cpu ia64,
	* library/platform/pkgIndex.tcl: taking ia64_32 into account
	* unix/Makefile.in: now. Bumped version to 1.0.5. Updated the
	* win/Makefile.in: installation commands.

2009-05-26 Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* doc/expr.n: Fixed documentation of the right-associativity of
	the ** operator. (spotted by kbk)

2009-05-14  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOInfo.c (InfoObjectNsCmd): Added introspection mechanism
	for finding out what an object's namespace is. Experience suggests
	that it is just too useful to be able to do without it.

2009-05-12  Donal K. Fellows  <dkf@users.sf.net>

	* doc/vwait.n: Added more words to make it clear just how bad it is to
	nest [vwait]s.

	* compat/mkstemp.c: Add more headers to make this file build on IRIX
	6.5. Thanks to Larry McVoy for this.

2009-05-08  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.c (TclNRNewObjectInstance):  [Bug 2414858]: Add a
	* generic/tclBasic.c (TclPushTailcallPoint): marker to the stack of
	NRE callbacks at the right point so that tailcall works correctly in a
	constructor.

	* tests/exec.test (cat): [Bug 2788468]: Adjust the scripted version of
	cat so that it does not perform transformations on the data it is
	working with, making it more like the standard Unix 'cat' program.

2009-05-07  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclObj.c (Tcl_GetCommandFromObj): [Bug 2785893]: Ensure that
	a command in a deleted namespace can't be found through a cached name.

	* generic/tclBasic.c:    Let coroutines start with a much smaller
	* generic/tclCompile.h:  stack: 200 words (previously was 2000, the
	* generic/tclExecute.c:  same as interps).

2009-05-07  Donal K. Fellows  <dkf@users.sf.net>

	* tests/env.test (printenvScript, env-4.3, env-4.5): [Bug 1513659]:
	* tests/exec.test (exec-2.6): These tests had subtle dependencies on
	being on platforms that were either ISO 8859-1 or UTF-8. Stabilized
	the results by forcing the encoding.

2009-05-06  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCmdMZ.c:	[Bug 2582327]: Improve overflow error message
	from [string repeat].

	* tests/interp.test: interp-20.50 test for Bug 2486550.

2009-05-04  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.c (InitFoundation, AllocObject, AllocClass):
	* generic/tclOODefineCmds.c (InitDefineContext): Make sure that when
	support namespaces are deleted, nothing bad can subsequently happen.
	Issue spotted by Don Porter.

2009-05-03  Donal K. Fellows  <dkf@users.sf.net>

	* doc/Tcl.n: [Bug 2538432]: Clarified exact treatment of ${arr(idx)}
	form of variable substitution. This is not a change of behavior, just
	an improved description of the current situation.

2009-04-30  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c (TclObjInvoke): [Bug 2486550]: Make sure that a
	null objProc is not used, use Tcl_NRCallObjProc instead.

2009-05-01  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/configure.in   Fix 64-bit detection for zlib on Win64
	* win/configure      (regenerated)

2009-04-28  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/tcl.m4, unix/configure (SC_CONFIG_CFLAGS): harden the check to
	add _r to CC on AIX with threads.

2009-04-27  Donal K. Fellows  <dkf@users.sf.net>

	* doc/concat.n (EXAMPLES): [Bug 2780680]: Rewrote so that the spacing
	of result messages is correct. (The exact way they were wrong was
	different when rendered through groff or as HTML, but it was still
	wrong both ways.)

2009-04-27  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclIndexObj.c:  Reset internal INTERP_ALTERNATE_WRONG_ARGS
	* generic/tclIOCmd.c:     flag inside the Tcl_WrongNumArgs function,
	                          so the caller no longer has to do the reset.

2009-04-24  Stuart Cassoff  <stwo@users.sf.net>

	* unix/Makefile.in: [Patch 2769530]: Don't chmod/exec installManPage.

2009-04-19  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* library/http/http.tcl: [Bug 2715421]: Removed spurious newline added
	* tests/http11.test:     after POST and added tests to detect excess
	* tests/httpd11.tcl:     bytes being POSTed.
	* library/http/pkgIndex.tcl:
	* makefiles:             package version now 2.8.1

2009-04-15  Donal K. Fellows  <dkf@users.sf.net>

	* doc/chan.n, doc/close.n: Tidy up documentation of TIP #332.

2009-04-14  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata/Asia/Karachi: Updated rules for Pakistan Summer
				       Time (Olson's tzdata2009f)

2009-04-11  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOMethod.c (InvokeForwardMethod): Clarify the resolution
	behaviour of the name of the command that is forwarded to: it's now
	resolved using the object's namespace as context, which is much more
	useful than the previous (somewhat random) behaviour of using the
	caller's current namespace.

2009-04-10  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* library/http/http.tcl:     Improved HTTP/1.1 support and added
	* library/http/pkgIndex.tcl: specific HTTP/1.1 testing to ensure
	* tests/http11.test:         we handle chunked+gzip for the various
	* tests/httpd11.test:        modes (normal, -channel and -handler)
	* makefiles:                 package version set to 2.8.0

2009-04-10  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tclUnixChan.c:		TclUnixWaitForFile(): use FD_* macros
	* macosx/tclMacOSXNotify.c:	to manipulate select masks (Cassoff).
					[FRQ 1960647] [Bug 3486554]

	* unix/tclLoadDyld.c:		Use RTLD_GLOBAL instead of RTLD_LOCAL.
					[Bug 1961211]

	* macosx/tclMacOSXNotify.c:	revise CoreFoundation notifier to allow
					embedding into applications that
					already have a CFRunLoop running and
					want to run the tcl event loop via
					Tcl_ServiceModeHook(TCL_SERVICE_ALL).

	* macosx/tclMacOSXNotify.c:	add CFRunLoop based Tcl_Sleep() and
	* unix/tclUnixChan.c:		TclUnixWaitForFile() implementations
	* unix/tclUnixEvent.c:		and disable select() based ones in
					CoreFoundation builds.

	* unix/tclUnixNotify.c:		simplify, sync with tclMacOSXNotify.c.

	* generic/tclInt.decls: 	add TclMacOSXNotifierAddRunLoopMode()
	* generic/tclIntPlatDecls.h:	internal API, regen.
	* generic/tclStubInit.c:

	* unix/configure.in (Darwin):	use Darwin SUSv3 extensions if
					available; remove /Network locations
					from default tcl package search path
					(NFS mounted locations and thus slow).
	* unix/configure:		autoconf-2.59
	* unix/tclConfig.h.in:		autoheader-2.59

	* macosx/tclMacOSXBundle.c:	on Mac OS X 10.4 and later, replace
					deprecated NSModule API by dlfcn API.

2009-04-10  Donal K. Fellows  <dkf@users.sf.net>

	* doc/StringObj.3: [Bug 2089279]: Corrected example so that it works
	on 64-bit machines as well.

2009-04-10  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* tests/http.test: [Bug 26245326]: Added specific check for problem
	* tests/httpd: (return incomplete HTTP response header).

2009-04-08  Kevin B. Kenny  <kennykb@acm.org>

	* tools/tclZIC.tcl: Always emit files with Unix line termination.
	* library/tzdata: Olson's tzdata2009e

2009-04-09  Don Porter  <dgp@users.sourceforge.net>

	* library/http/http.tcl:	[Bug 26245326]: Handle incomplete
	lines in the "connecting" state. Thanks to Sergei Golovan.

2009-04-08  Andreas Kupries  <andreask@activestate.com>

	* library/platform/platform.tcl: Extended the darwin sections to add
	* library/platform/pkgIndex.tcl: a kernel version number to the
	* unix/Makefile.in: identifier for anything from Leopard (10.5) on up.
	* win/Makefile.in: Extended patterns for same. Extended cpu
	* doc/platform.n: recognition for 64bit Tcl running on a 32bit kernel
	on a 64bit processor (By Daniel Steffen). Bumped version to 1.0.4.
	Updated Makefiles.

2009-04-08  Don Porter  <dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl:  [Bug 2570363]: Converted [eval]s (some
	* library/tcltest/pkgIndex.tcl: unsafe!) to {*} in tcltest package.
	* unix/Makefile.in:     => tcltest 2.3.1
	* win/Makefile.in:

2009-04-07  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c:	Correction so that value of
	TCL_GROWTH_MIN_ALLOC is everywhere expressed in bytes as comment
	claims.

2009-04-04  Donal K. Fellows  <dkf@users.sf.net>

	* doc/vwait.n: [Bug 1910136]: Extend description and examples to make
	it clearer just how this command interprets variable names.

2009-03-30  Don Porter  <dgp@users.sourceforge.net>

	* doc/Alloc.3: [Bug 2556263]:	Size argument is "unsigned int".

2009-03-27  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclPathObj.c (TclPathPart): [Bug 2710920]: TclPathPart()
	* tests/fileName.test:	was computing the wrong results for both [file
	dirname] and [file tail] on "path" arguments with the PATHFLAGS != 0
	intrep and with an empty string for the "joined-on" part.

2009-03-25  Jan Nijtmans  <nijtmans@users.sf.net>

	* doc/tclsh.1:		 Bring doc and tools in line with
	* tools/installData.tcl: http://wiki.tcl.tk/812
	* tools/str2c
	* tools/tcltk-man2html.tcl

2009-03-25  Donal K. Fellows  <dkf@users.sf.net>

	* doc/coroutine.n: [Bug 2152285]: Added basic documentation for the
	coroutine and yield commands.

2009-03-24  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOBasic.c (TclOOSelfObjCmd): [Bug 2704302]: Make 'self
	class' better defined in the context of objects that change class.

	* generic/tclVar.c (Tcl_UpvarObjCmd): [Bug 2673163] (ferrieux)
	* generic/tclProc.c (TclObjGetFrame): Make the upvar command more able
	to handle its officially documented syntax.

2009-03-22  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c: [Bug 2502037]: NR-enable the handling of unknown
	commands.

2009-03-21  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:   Fixed "leaks" in aliases, imports and
	* generic/tclInt.h:     ensembles. Only remaining known leak is in
	* generic/tclInterp.c:  ensemble unknown dispatch (as it not
	* generic/tclNamesp.c:  NR-enabled)
	* tests/tailcall.test:

	* tclInt.h: comments

	* tests/tailcall.test: Added tests to show that [tailcall] does not
	currently always execute in constant space: interp-alias, ns-imports
	and ensembles "leak" as of this commit.

	* tests/nre.test: [foreach] has been NR-enabled for a while, the test
	was marked 'knownBug': unmark it.

	* generic/tclBasic.c:   Fix for (among others) [Bug 2699087]
	* generic/tclCmdAH.c:   Tailcalls now perform properly even from
	* generic/tclExecute.c: within [eval]ed scripts.
	* generic/tclInt.h:     More tests missing, as well as proper
	exploration and testing of the interaction with "redirectors" like
	interp-alias (suspect that it does not happen in constant space)
	and pure-eval commands.

	* generic/tclExecute.c: Proper fix for [Bug 2415422]. Reenabled
	* tests/nre.test:       the failing assertion that was disabled on
	2008-12-18: the assertion is correct, the fault was in the
	management of expansions.

	* generic/tclExecute.c:  Fix both test and code for tailcall
	* tests/tailcall.test:   from within a compiled [eval] body.

	* tests/tailcall.test: Slightly improved tests

2009-03-20  Don Porter  <dgp@users.sourceforge.net>

	* tests/stringObj.test:         [Bug 2597185]: Test stringObj-6.9
	checks that Tcl_AppendStringsToObj() no longer crashes when operating
	on a pure unicode value.

	* generic/tclExecute.c (INST_CONCAT1):  [Bug 2669109]: Panic when
	appends overflow the max length of a Tcl value.

2009-03-19  Miguel Sofer  <msofer@users.sf.net>

	* generic/tcl.h:
	* generic/tclInt.h:
	* generic/tclBasic.c:
	* generic/tclExecute.c:
	* generic/tclNamesp.c (Tcl_PopCallFrame): Rewritten tailcall
	implementation, ::unsupported::atProcExit is (temporarily?) gone. The
	new approach is much simpler, and also closer to being correct. This
	commit fixes [Bug 2649975] and [Bug 2695587].

	* tests/coroutine.test:    Moved the tests to their own files,
	* tests/tailcall.test:     removed the unsupported.test. Added
	* tests/unsupported.test:  tests for the fixed bugs.

2009-03-19  Donal K. Fellows  <dkf@users.sf.net>

	* doc/tailcall.n: Added documentation for tailcall command.

2009-03-18  Don Porter  <dgp@users.sourceforge.net>

	* win/tclWinFile.c (TclpObjNormalizePath):	[Bug 2688184]:
	Corrected Tcl_Obj leak. Thanks to Joe Mistachkin for detection and
	patch.

	* generic/tclVar.c (TclLookupSimpleVar):	[Bug 2689307]: Shift
	all calls to Tcl_SetErrorCode() out of TclLookupSimpleVar and onto its
	callers, where control with TCL_LEAVE_ERR_MSG flag is more easily
	handled.

2009-03-16  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdMZ.c (TryPostBody): [Bug 2688063]: Extract information
	from list before getting rid of last reference to it.

2009-03-15  Joe Mistachkin  <joe@mistachkin.com>

	* generic/tclThread.c: [Bug 2687952]: Modify fix for TSD leak to match
	* generic/tclThreadStorage.c: Tcl 8.5 (and prior) allocation semantics

2009-03-15  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclThreadStorage.c (TSDTableDelete):	[Bug 2687952]: Ensure
	* generic/tclThread.c (Tcl_GetThreadData):	that structures in
	Tcl's TSD system are all freed. Use the correct matching allocator.

	* generic/tclPosixStr.c (Tcl_SignalId,Tcl_SignalMsg): [Patch 1513655]:
	Added support for SIGINFO, which is present on BSD platforms.

2009-03-14  Donal K. Fellows  <dkf@users.sf.net>

	* unix/tcl.pc.in (new file):		[Patch 2243948] (hat0)
	* unix/configure.in, unix/Makefile.in: Added support for reporting
	Tcl's public build configuration via the pkg-config system. TEA is
	still the official mechanism though, in part because pkg-config is not
	universally supported across all Tcl's supported platforms.

2009-03-11  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c (TclNRCoroutineObjCmd): fix Tcl_Obj leak.
	Diagnosis and fix thanks to GPS.

2009-03-09  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdMZ.c (Tcl_TryObjCmd, TclNRTryObjCmd): Moved the
	implementation of [try] from Tcl code into C. Still lacks a bytecode
	version, but should be better than what was before.

2009-03-04  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclZlib.c (TclZlibCmd): Checksums are defined to be unsigned
	32-bit integers, use Tcl_WideInt to pass to scripts. [Bug 2662434]
	(ZlibStreamCmd, ChanGetOption): A few other related corrections.

2009-02-27  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.decls:    [Bug 218977]: Tcl_DbCkfree needs return value
	* generic/tclCkalloc.c
	* generic/tclDecls.h:   (regenerated)
	* generic/tclInt.decls: don't use CONST84/CONST86 here
	* generic/tclCompile.h: don't use CONST86 here, comment fixing.
	* generic/tclIO.h:      don't use CONST86 here, comment fixing.
	* generic/tclIntDecls.h (regenerated)

2009-02-25  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclUtil.c (TclStringMatchObj):	[Bug 2637173]: Revised
	the branching on the strObj->typePtr so that untyped values get
	converted to the "string" type and pass through the Unicode matcher.
	[Bug 2613766]: Also added checks to only perform "bytearray"
	optimization on pure bytearray values.

	* generic/tclCmdMZ.c:	Since Tcl_GetCharLength() has its own
	* generic/tclExecute.c:	optimizations for the tclByteArrayType, stop
	having the callers do them.

2009-02-24  Donal K. Fellows  <dkf@users.sf.net>

	* doc/clock.n, doc/fblocked.n, doc/format.n, doc/lsort.n,
	* doc/pkgMkIndex.n, doc/regsub.n, doc/scan.n, doc/tclvars.n:
	General minor documentation improvements.

	* library/http/http.tcl (geturl, Eof): Added support for 8.6's built
	in zlib routines.

2009-02-22  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* tests/lrange.test:	Revert commits of 2008-07-23. Those were speed
	* tests/binary.test:	tests, that are inherently brittle.

2009-02-21  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c:	Several revisions to the shimmering
	patterns between Unicode and UTF string reps.  Most notably the
	call: objPtr = Tcl_NewUnicodeObj(...,0); followed by a loop of calls:
	Tcl_AppendUnicodeToObj(objPtr, u, n); will now grow and append to
	the Unicode representation.  Before this commit, the sequence would
	convert each append to UTF and perform the append to the UTF rep.
	This is puzzling and likely a bug.  The performance of [string map]
	is significantly improved by this change (according to the MAP
	collection of benchmarks in tclbench).  Just in case there was some
	wisdom in the old ways that I missed, I left in the ability to restore
	the old patterns with a #define COMPAT 1 at the top of the file.

2009-02-20  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclPathObj.c:	[Bug 2571597]: Fixed mistaken logic in
	* tests/fileName.test:	TclFSGetPathType() that assumed (not
	"absolute") => "relative". This is a false assumption on Windows,
	where "volumerelative" is another possibility.

2009-02-18  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c:	Simplify the logic of the
	Tcl_*SetObjLength() routines.

	* generic/tclStringObj.c:	Rewrite GrowStringBuffer() so that it
	has parallel structure with GrowUnicodeBuffer().  The revision permits
	allocation attempts to continue all the way up to failure, with no
	gap. It also directly manipulates the String and Tcl_Obj internals
	instead of inefficiently operating via Tcl_*SetObjLength() with all of
	its extra protections and underdocumented special cases.

	* generic/tclStringObj.c:	Another round of simplification on
	the allocation macros.

2009-02-17  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/tcl.m4, win/configure: Check if cl groks _WIN64 already to
	avoid CC manipulation that can screw up later configure checks.
	Use 'd'ebug runtime in 64-bit builds.

2009-02-17  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c:	Pare back the length of the unicode
	array in a non-extended String struct to one Tcl_UniChar, meant to
	hold the terminating NUL character.  Non-empty unicode strings are
	then stored by extending the String struct by stringPtr->maxChars
	additional slots in that array with sizeof(Tcl_UniChar) bytes per
	slot. This revision makes the allocation macros much simpler.

	* generic/tclStringObj.c:	Factor out common GrowUnicodeBuffer()
	and solve overflow and growth algorithm fallbacks in it.

	* generic/tclStringObj.c:	Factor out common GrowStringBuffer().

	* generic/tclStringObj.c:	Convert Tcl_AppendStringsToObj into
	* tests/stringObj.test:		a radically simpler implementation
	where we just loop over calls to Tcl_AppendToObj.  This fixes [Bug
	2597185].  It also creates a *** POTENTIAL INCOMPATIBILITY *** in
	that T_ASTO can now allocate more space than is strictly required,
	like all the other Tcl_Append* routines.  The incompatibility was
	detected by test stringObj-6.5, which I've updated to reflect the
	new behavior.

	* generic/tclStringObj.c:	Revise buffer growth implementation
	in ExtendStringRepWithUnicode.  Use cheap checks to determine that
	no reallocation is necessary without cost of computing the precise
	number of bytes needed.  Also make use of the string growth algortihm
	in the case of repeated appends.

2009-02-16  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclZlib.c:	Hack needed for official zlib1.dll build.
	* win/configure.in:	fix [Feature Request 2605263] use official
	* win/Makefile.in:	zlib build.
	* win/configure:	(regenerated)
	* compat/zlib/zdll.lib:	new files
	* compat/zlib/zlib1.dll:

	* win/Makefile.in:  [Bug 2605232]: tdbc doesn't build when Tcl is
	compiled with --disable-shared.

2009-02-15  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c:	[Bug 2603158]: Added protections from
	* generic/tclTestObj.c:		invalid memory accesses when we append
	* tests/stringObj.test:		(some part of) a Tcl_Obj to itself.
	Added the appendself and appendself2 subcommands to the
	[teststringobj] testing command and added tests to the test suite.

	* generic/tclStringObj.c:	Factor out duplicate code from
	Tcl_AppendObjToObj.

	* generic/tclStringObj.c:	Replace the 'size_t uallocated' field
	of the String struct, storing the number of bytes allocated to store
	the Tcl_UniChar array, with an 'int maxChars' field, storing the
	number of Tcl_UniChars that may be stored in the allocated space.
	This reduces memory requirement a small bit, and makes some range
	checks simpler to code.
	* generic/tclTestObj.c:	Replace the [teststringobj ualloc] testing
	* tests/stringObj.test:	command with [teststringobj maxchars] and
	update the tests.

	* generic/tclStringObj.c:	Removed limitation in
	Tcl_AppendObjToObj where the char length of the result was only
	computed if the appended string was all single byte characters.
	This limitation was in place to dodge a bug in Tcl_GetUniChar.
	With that bug gone, we can take advantage of always recording the
	length of append results when we know it.

2009-02-14  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c:	Revisions so that we avoid creating
	the strange representation of an empty string with
	objPtr->bytes == NULL and stringPtr->hasUnicode == 0.  Instead in
	the situations where that was being created, create a traditional
	two-legged stork representation (objPtr->bytes = tclEmptyStringRep
	and stringPtr->hasUnicode = 1).  In the situations where the strange
	rep was treated differently, continue to do so by testing
	stringPtr->numChars == 0 to detect it.  These changes make the code
	more conventional so easier for new maintainers to pick up.  Also
	sets up further simplifications.

	* generic/tclTestObj.c:	Revise updates to [teststringobj] so we don't
	get blocked by MODULE_SCOPE limits.

2009-02-12  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c:	Rewrites of the routines
	Tcl_GetCharLength, Tcl_GetUniChar, Tcl_GetUnicodeFromObj,
	Tcl_GetRange, and TclStringObjReverse to use the new macro, and
	to more simply and clearly split the cases depending on whether
	a valid unicode rep is present or needs to be created.
	New utility routine UnicodeLength(), to compute the length of unicode
	buffer arguments when no length is passed in, with built-in
	overflow protection included.  Update three callers to use it.

	* generic/tclInt.h:	New macro TclNumUtfChars meant to be a faster
	replacement for a full Tcl_NumUtfChars() call when the string has all
	single-byte characters.

	* generic/tclStringObj.c:	Simplified Tcl_GetCharLength by
	* generic/tclTestObj.c:		removing code that did nothing.
	Added early returns from Tcl_*SetObjLength when the desired length
	is already present; adapted test command to the change.

	* generic/tclStringObj.c:	Re-implemented AppendUtfToUnicodeRep
	so that we no longer pass through Tcl_DStrings which have their own
	sets of problems when lengths overflow the int range.  Now AUTUR and
	FillUnicodeRep share a common core routine.

2009-02-12  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOODefineCmds.c (TclOOGetDefineCmdContext): Use the
	correct field in the Interp structure for retrieving the frame to get
	the context object so that people can extend [oo::define] without deep
	shenanigans. Bug found by Federico Ferri.

2009-02-11  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c:	Re-implemented AppendUnicodeToUtfRep
	so that we no longer pass through Tcl_DStrings which have their own
	sets of problems when lengths overflow the int range.  Now AUTUR and
	UpdateStringOfString share a common core routine.

	* generic/tclStringObj.c:	Changed type of the 'allocated' field
	* generic/tclTestObj.c:		of the String struct (and the
	TestString counterpart) from size_t to int since only int values are
	ever stored in it.

2009-02-10  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclEncoding.c: Eliminate some unnessary type casts
	* generic/tclEvent.c:    some internal const decorations
	* generic/tclExecute.c:  spacing
	* generic/tclIndexObj.c:
	* generic/tclInterp.c:
	* generic/tclIO.c:
	* generic/tclIOCmd.c:
	* generic/tclIORChan.c:
	* generic/tclIOUtil.c:
	* generic/tclListObj.c:
	* generic/tclLiteral.c:
	* generic/tclNamesp.c:
	* generic/tclObj.c:
	* generic/tclOOBasic.c:
	* generic/tclPathObj.c:
	* generic/tclPkg.c:
	* generic/tclProc.c:
	* generic/tclRegexp.c:
	* generic/tclScan.c:
	* generic/tclStringObj.c:
	* generic/tclTest.c:
	* generic/tclTestProcBodyObj.c:
	* generic/tclThread.c:
	* generic/tclThreadTest.c:
	* generic/tclTimer.c:
	* generic/tclTrace.c:
	* generic/tclUtil.c:
	* generic/tclVar.c:
	* generic/tclStubInit.c: (regenerated)

2009-02-10  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tcl.m4: [Bug 2502365]: Building of head on HPUX is broken when
	using the native CC.
	* unix/configure: (autoconf-2.59)

2009-02-10  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclObj.c (Tcl_GetString):	Added comments and validity
	checks following the call to an UpdateStringProc.

	* generic/tclStringObj.c: Reduce code duplication in Tcl_GetUnicode*.
	Restrict AppendUtfToUtfRep to non-negative length appends.
	Convert all Tcl_InvalidateStringRep() calls into macros.
	Simplify Tcl_AttemptSetObjLength by removing unreachable code.
	Simplify SetStringFromAny() by removing unreachable and duplicate code.
	Simplify Tcl_SetObjLength by removing unreachable code.
	Removed handling of (objPtr->bytes != NULL) from UpdateStringOfString,
	which is only called when objPtr->bytes is NULL.

2009-02-09  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclCompile.c: [Bug 2555129]: const compiler warning (as
	error) in tclCompile.c

2009-02-07  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclZlib.c (TclZlibCmd): [Bug 2573172]: Ensure that when
	invalid subcommand name is given, the list of valid subcommands is
	produced. This gives a better experience when using the command
	interactively.

2009-02-05  Joe Mistachkin  <joe@mistachkin.com>

	* generic/tclInterp.c: [Bug 2544618]: Fix argument checking for
	[interp cancel].
	* unix/Makefile.in: Fix build issue with zlib on FreeBSD (and possibly
	other platforms).

2009-02-05  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdMZ.c (StringIndexCmd, StringRangeCmd, StringLenCmd):
	Simplify the implementation of some commands now that the underlying
	string API knows more about bytearrays.

	* generic/tclExecute.c (TclExecuteByteCode): [Bug 2568434]: Make sure
	that INST_CONCAT1 will not lose string reps wrongly.

	* generic/tclStringObj.c (Tcl_AppendObjToObj): Special-case the
	appending of one bytearray to another, which can be extremely rapid.
	Part of scheme to address [Bug 1665628] by making the basic string
	operations more efficient on byte arrays.
	(Tcl_GetCharLength, Tcl_GetUniChar, Tcl_GetRange): More special casing
	work for bytearrays.

2009-02-04  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c: [Bug 2561794]: Added overflow protections to
	the AppendUtfToUtfRep routine to either avoid invalid arguments and
	crashes, or to replace them with controlled panics.

	* generic/tclCmdMZ.c:	[Bug 2561746]: Prevent crashes due to int
	overflow of the length of the result of [string repeat].

2009-02-03  Jan Nijtmans  <nijtmans@users.sf.net>

	* macosx/tclMacOSXFCmd.c: Eliminate some unnessary type casts
	* unix/tclLoadDyld.c:	  some internal const decorations
	* unix/tclUnixCompat.c:	  spacing
	* unix/tclUnixFCmd.c
	* unix/tclUnixFile.c
	* win/tclWinDde.c
	* win/tclWinFCmd.c
	* win/tclWinInit.c
	* win/tclWinLoad.c
	* win/tclWinPipe.c
	* win/tclWinReg.c
	* win/tclWinTest.c
	* generic/tclBasic.c
	* generic/tclBinary.c
	* generic/tclCmdAH.c
	* generic/tclCmdIL.c
	* generic/tclCmdMZ.c
	* generic/tclCompCmds.c
	* generic/tclDictObj.c

2009-02-03  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclObj.c (tclCmdNameType): [Bug 2558422]: Corrected the type
	of this structure so that extensions that write it (yuk!) will still
	be able to function correctly.

2009-02-03  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c (SetUnicodeObj):	[Bug 2561488]:
	Corrected failure of Tcl_SetUnicodeObj() to panic on a shared object.
	Also factored out common code to reduce duplication.

	* generic/tclObj.c (Tcl_GetStringFromObj): Reduce code duplication.

2009-02-02  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInterp.c:	Reverted the conversion of [interp] into an
	* tests/interp.test:	ensemble.  Such conversion is not necessary
	* tests/nre.test:	(or even all that helpful) in the NRE-enabling
	of [interp invokehidden], and it has other implications -- including
	significant forkage of the 8.5 and 8.6 implementations -- that are
	better off avoided if there's no gain.

	* generic/tclStringObj.c (STRING_NOMEM):  [Bug 2494093]: Add missing
	cast of NULL to (char *) that upsets some compilers.

	* generic/tclStringObj.c (Tcl_(Attempt)SetObjLength):	[Bug 2553906]:
	Added protections against callers asking for negative lengths.  It is
	likely when this happens that an integer overflow is to blame.

2009-02-01  David Gravereaux  <davygrvy@pobox.com>

	* win/makefile.vc: Allow nmake flags such as -a (rebuild all) to pass
	down to the pkgs targets, too.

2009-01-30  Donal K. Fellows  <dkf@users.sf.net>

	* doc/chan.n: [Bug 1216074]: Added another extended example.

	* doc/refchan.n: Added an example of how to build a scripted channel.

2009-01-29  Donal K. Fellows  <dkf@users.sf.net>

	* tests/stringObj.test: [Bug 2006888]: Remove non-ASCII chars from
	non-comment locations in the file, making it work more reliably in
	locales with a non-Latin-1 default encoding.

	* generic/tclNamesp.c (Tcl_FindCommand): [Bug 2519474]: Ensure that
	the path is not searched when the TCL_NAMESPACE_ONLY flag is given.

	* generic/tclOODecls.h (Tcl_OOInitStubs): [Bug 2537839]: Make the
	declaration of this macro work correctly in the non-stub case.

2009-01-29  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInterp.c:	Convert the [interp] command into a
	* tests/interp.test:	[namespace ensemble].  Work in progress
	* tests/nre.test:	to NRE-enable the [interp invokehidden]
	subcommand.

2009-01-29  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclNamesp.c (TclMakeEnsemble): [Bug 2529117]: Make this
	function behave more sensibly when presented with a fully-qualified
	name, rather than doing strange stuff.

2009-01-28  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclBasic.c (TclInvokeObjectCommand): Made this understand
	what to do if it ends up being used on a command with no objProc; that
	shouldn't happen, but...

	* generic/tclNamesp.c (TclMakeEnsemble): [Bug 2529157]: Made this
	understand NRE command implementations better.
	* generic/tclDictObj.c (DictForCmd): Eliminate unnecessary command
	implementation.

2009-01-27  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOODefineCmds.c (Tcl_ClassSetConstructor):
	[Bug 2531577]: Ensure that caches of constructor chains are cleared
	when the constructor is changed.

2009-01-26  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclInt.h:   [Bug 1028264]: WSACleanup() too early.
	* generic/tclEvent.c: The fix introduces "late exit handlers" for
	* win/tclWinSock.c:   similar late process-wide cleanups.

2009-01-26  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* win/tclWinSock.c: [Bug 2446662]: Resync Win behavior on RST with
	that of unix (EOF).

2009-01-26  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclZlib.c (ChanClose): [Bug 2536400]: Only generate error
	messages in the interpreter when the thread is not being closed down.

2009-01-23  Donal K. Fellows  <dkf@users.sf.net>

	* doc/zlib.n: Added a note that 'zlib push' is reversed by 'chan pop'.

2009-01-22  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclCompile.h:	CONSTify TclPrintInstruction (TIP #27)
	* generic/tclCompile.c
	* generic/tclInt.h:	CONSTify TclpNativeJoinPath (TIP #27)
	* generic/tclFileName.c
	* generic/tcl.decls:	{unix win} is equivalent to {generic}
	* generic/tclInt.decls
	* generic/tclDecls.h:	(regenerated)
	* generic/tclIntDecls.h
	* generic/tclGetDate.y:	Single internal const decoration.
	* generic/tclDate.c:

2009-01-22  Kevin B. Kenny  <kennykb@acm.org>

	* unix/tcl.m4: Corrected a typo ($(SHLIB_VERSION) should be
	${SHLIB_VERSION}).
	* unix/configure: Autoconf 2.59

2009-01-21  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIORChan.c (ReflectClose): [Bug 2458202]:
	* generic/tclIORTrans.c (ReflectClose): Closing a channel may supply
	NULL for the 'interp'. Test for finalization needs to be different,
	and one place has to pull the interp out of the channel instead.

2009-01-21  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c: New fix for [Bug 2494093] replaces the
	flawed attempt committed 2009-01-09.

2009-01-19  Kevin B. Kenny  <kennykb@acm.org>

	* unix/Makefile.in: [Patch 907924]:Added a CONFIG_INSTALL_DIR
	* unix/tcl.m4:      parameter so that distributors can control where
	tclConfig.sh goes. Made the installation of 'ldAix' conditional upon
	actually being on an AIX system. Allowed for downstream packagers to
	customize SHLIB_VERSION on BSD-derived systems. Thanks to Stuart
	Cassoff for his help.
	* unix/configure: Autoconf 2.59

2009-01-19  David Gravereaux  <davygrvy@pobox.com>

	* win/build.vc.bat: Improved tools detection and error message
	* win/makefile.vc: Reorganized the $(TCLOBJ) file list into seperate
	parts for easier maintenance. Matched all sources built using -GL to
	both $(lib) and $(link) to use -LTCG and avoid a warning message.
	Addressed the over-building nature of the htmlhelp target by moving
	from a pseudo target to a real target dependent on the entire docs/
	directory contents.
	* win/nmakehlp.c: Removed -g option and GrepForDefine() func as it
	isn't being used anymore. The -V option method is much better.

2009-01-16  Don Porter  <dgp@users.sourceforge.net>

	* generic/tcl.h:	Bump patchlevel to 8.6b1.1 to distinguish
	* library/init.tcl:	CVS snapshots from the 8.6b1 and 8.6b2 releases
	* unix/configure.in:	and to deal with the fact that the 8.6b1
	* win/configure.in:	version of init.tcl will not [source] in the
	HEAD version of Tcl.

	* unix/configure:	autoconf-2.59
	* win/configure:

2009-01-14  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c (Tcl_DeleteCommandFromToken):	Reverted most
	of the substance of my 2009-01-12 commit. NULLing the objProc field of
	a Command when deleting it is important so that tests for certain
	classes of commands don't return false positives when applied to
	deleted command tokens. Overall change is now just replacement of a
	false comment with a true one.

2009-01-13  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tcl.m4: [Bug 2502365]: Building of head on HPUX is broken when
	using the native CC.
	* unix/configure (autoconf-2.59)

2009-01-13  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdMZ.c (Tcl_ThrowObjCmd):	Move implementation of [throw]
	* library/init.tcl (throw):		to C from Tcl.

2009-01-12  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c (Tcl_DeleteCommandFromToken): One consequence of
	the NRE rewrite is that there are now situations where a NULL objProc
	field in a Command struct is perfectly normal. Removed an outdated
	comment in Tcl_DeleteCommandFromToken that claimed we use
	cmdPtr->objPtr==NULL as a test of command validity. In fact we use
	cmdPtr->flags&CMD_IS_DELETED to perform that test. Also removed the
	setting to NULL, since any extension following the advice of the old
	comment is going to be broken by NRE anyway, and needs to shift to
	flag-based testing (or stop intruding into such internal matters).
	Part of [Bug 2486550].

2009-01-09  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c (STRING_SIZE): [Bug 2494093]: Corrected
	failure to limit memory allocation requests to the sizes that can be
	supported by Tcl's memory allocation routines.

2009-01-09  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclNamesp.c (NamespaceEnsembleCmd): [Bug 1558654]: Error out
	when someone gives wrong # of args to [namespace ensemble create].

2009-01-08  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c (STRING_UALLOC): [Bug 2494093]: Added missing
	parens required to get correct results out of things like
	STRING_UALLOC(num + append).

2009-01-08  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclDictObj.c, generic/tclIndexObj.c, generic/tclListObj.c,
	* generic/tclObj.c, generic/tclStrToD.c, generic/tclUtil.c,
	* generic/tclVar.c: Generate errorcodes for the error cases which
	approximate to "I can't interpret that string as one of those" and
	"You gave me the wrong number of arguments".

2009-01-07  Donal K. Fellows  <dkf@users.sf.net>

	* doc/dict.n: [Tk Bug 2491235]: Added more examples.

	* tests/oo.test (oo-22.1): Adjusted test to be less dependent on the
	specifics of how [info frame] reports general frame information, and
	instead to focus on what methods add to it; that's really what the
	test is about anyway.

2009-01-06  Don Porter  <dgp@users.sourceforge.net>

	* tests/stringObj.test:	Revise tests that demand a NULL Tcl_ObjType
	in certain values to construct those values with [testdstring] so
	there's no lack of robustness depending on the shimmer history of
	shared literals.

2009-01-06  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclDictObj.c (DictIncrCmd): Corrected twiddling in internals
	of dictionaries so that literals can't get destroyed.

	* tests/expr.test: [Bug 2006879]: Eliminate non-ASCII char.

	* generic/tclOOInfo.c (InfoObjectMethodsCmd,InfoClassMethodsCmd):
	[Bug 2489836]: Only delete pointers that were actually allocated!

	* generic/tclOO.c (TclNRNewObjectInstance, Tcl_NewObjectInstance):
	[Bug 2481109]: Perform search for existing commands in right context.

2009-01-05  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdMZ.c (TclNRSourceObjCmd): [Bug 2412068]: Make
	* generic/tclIOUtil.c (TclNREvalFile):    implementation of the
	[source] command be NRE enabled so that [yield] inside a script
	sourced in a coroutine can work.

2009-01-04  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdAH.c: Tidy up spacing and code style.

2009-01-03  Kevin B. Kenny  <kennykb@acm.org>

	* library/clock.tcl (tcl::clock::add): Fixed error message formatting
	in the case where [clock add] is presented with a bad switch.
	* tests/clock.test (clock-65.1) Added a test case for the above
	problem [Bug 2481670].

2009-01-02  Donal K. Fellows  <dkf@users.sf.net>

	* unix/tcl.m4 (SC_CONFIG_CFLAGS): [Bug 878333]: Force the use of the
	compatibility version of mkstemp() on IRIX.
	* unix/configure.in, unix/Makefile.in (mkstemp.o):
	* compat/mkstemp.c (new file): [Bug 741967]: Added a compatibility
	implementation of the mkstemp() function, which is apparently needed
	on some platforms.

	******************************************************************
	*** CHANGELOG ENTRIES FOR 2008 IN "ChangeLog.2008"             ***
	*** CHANGELOG ENTRIES FOR 2006-2007 IN "ChangeLog.2007"        ***
	*** CHANGELOG ENTRIES FOR 2005 IN "ChangeLog.2005"             ***
	*** CHANGELOG ENTRIES FOR 2004 IN "ChangeLog.2004"             ***
	*** CHANGELOG ENTRIES FOR 2003 IN "ChangeLog.2003"             ***
	*** CHANGELOG ENTRIES FOR 2002 IN "ChangeLog.2002"             ***
	*** CHANGELOG ENTRIES FOR 2001 IN "ChangeLog.2001"             ***
	*** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000"             ***
	*** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" ***
	******************************************************************

Deleted ChangeLog.1999.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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










































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
1999-12-22  Jeff Hobbs  <hobbs@scriptics.com>

	* changes: updated changes file
	* tools/tclSplash.bmp: updated to show 8.3

1999-12-21  Jeff Hobbs  <hobbs@scriptics.com>

	* README:
	* generic/tcl.h:
	* mac/README:
	* unix/configure.in:
	* tools/tcl.wse.in:
	* win/README.binary:
	* win/configure.in: updated to patch level 8.3b1

	* unix/Makefile.in: added -srcdir=... for 'make html'

	* doc/Hash.3: fixed reference to ckfree [Bug 3912]
	* doc/RegExp.3: fixed calling params for Tcl_RegExecFromObj
	* doc/open.n: fixed minor formatting errors
	* doc/string.n: fixed minor formatting errors

	* doc/lsort.n: added -unique docs
	* tests/cmdIL.test:
	* generic/tclCmdIL.c: added -unique option to lsort

	* generic/tclThreadTest.c: changed thread ids to longs [Bug 3902]

	* mac/tclMacOSA.c: fixed applescript for I18N [Bug 3644]

	* win/mkd.bat:
	* win/rmd.bat: removed necessity of tag.txt [Bug 3874]

	* win/tclWinThrd.c: changed CreateThread to _beginthreadex and
	ExitThread to _endthreadex

1999-12-12  Jeff Hobbs  <hobbs@scriptics.com>

	* doc/glob.n:
	* tests/fileName.test:
	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclIntDecls.h:
	* generic/tclStubInit.c:
	* generic/tclEncoding.c:
	* generic/tclFileName.c:
	* mac/tclMacFile.c:
	* unix/tclUnixFile.c:
	* win/tclWinFile.c: enhanced the glob command with the new options
	-types -path -directory and -join. Deprecated TclpMatchFiles with
	TclpMatchFilesTypes, extended TclGlob and TclDoGlob and added
	GlobTypeData structure. [Bug 2363]

1999-12-10  Jeff Hobbs  <hobbs@scriptics.com>

	* tests/var.test:
	* generic/tclCompile.c: fixed problem where setting to {} array would
	intermittently not work. [Bug 3339] (Fontaine)

	* generic/tclCmdMZ.c:
	* generic/tclExecute.c: optimized INST_TRY_CVT_TO_NUMERIC to recognize
	boolean objects. [Bug 2815] (Spjuth)

	* tests/info.test:
	* tests/parseOld.test:
	* generic/tclCmdAH.c:
	* generic/tclProc.c: changed Tcl_UplevelObjCmd (uplevel) and
	Tcl_EvalObjCmd (eval) to use TCL_EVAL_DIRECT in the single arg case as
	well, to take advantage of potential pure list input optimization.
	This means that it won't get byte compiled though, which should be
	acceptable.
	* generic/tclBasic.c: made Tcl_EvalObjEx pure list object aware in the
	TCL_EVAL_DIRECT case for efficiency.
	* generic/tclUtil.c: made Tcl_ConcatObj pure list object aware, and
	return a list object in that case [Bug 2098 2257]

	* generic/tclMain.c: changed Tcl_Main to not constantly reuse the
	commandPtr object (interactive case) as it could be shared. (Fellows)

	* unix/configure.in:
	* unix/tcl.m4:
	* unix/tclUnixPipe.c: removed checking for compatible vfork function
	and use of the vfork function. Modern VM systems rarely suffer any
	performance degradation when fork is used, and it solves multiple
	problems with vfork. Users that still want vfork can add -Dfork=vfork
	to the compile flags. [Bug 942 2228 1312]

1999-12-09  Jeff Hobbs  <hobbs@scriptics.com>

	* win/aclocal.m4: made it just include tcl.m4

	* doc/exec.n:
	* doc/open.n:
	* win/tclWin32Dll.c:
	* win/tclWinChan.c:
	* win/tclWinFCmd.c:
	* win/tclWinInit.c:
	* win/tclWinPipe.c:
	* win/tclWinSock.c: removed all code that supported Win32s. It was no
	longer officially supported, and likely didn't work anyway.
	* win/makefile.vc: removed 16 bit stuff, cleaned up.

	* win/tcl16.rc:
	* win/tclWin16.c:
	* win/winDumpExts.c: these files have been removed from the source
	tree (no longer necessary to build)

1999-12-07  Jeff Hobbs  <hobbs@scriptics.com>

	* tests/io.test: removed 'knownBug' tests that were for unsupported0,
	which is now fcopy (that already has tests)

	* mac/tclMacPort.h: added utime.h include

	* generic/tclDate.c:
	* unix/Makefile.in: fixed make gendate to swap const with CONST so it
	uses the Tcl defined CONST type [Bug 3521]

	* generic/tclIO.c: removed panic that could occur in FlushChannel when
	a "blocking" channel would receive EAGAIN, instead treating it the
	same as non-blocking. [Bug 3773]

	* generic/tclUtil.c: fixed Tcl_ScanCountedElement to not step beyond
	the end of the counted string. [Bug 3336]

1999-12-03  Jeff Hobbs  <hobbs@scriptics.com>

	* doc/load.n: added note about NT's buggy handling of './' with
	LoadLibrary

	* library/http2.1/http.tcl: fixed error handling in http::Event. [Bug
	3752]

	* tests/env.test: removed knownBug limitation from working test
	* tests/all.tcl: ensured that ::tcltest::testsDirectory would be set
	to an absolute path

	* tests/expr-old.test:
	* tests/parseExpr.test:
	* tests/string.test:
	* generic/tclGet.c:
	* generic/tclInt.h:
	* generic/tclObj.c:
	* generic/tclParseExpr.c:
	* generic/tclUtil.c:
	* generic/tclExecute.c: added TclCheckBadOctal routine to enhance
	error message checking for when users use invalid octal numbers (like
	08), as well as replumbed the Expr*Funcs with a new VerifyExprObjType
	to simplify type handling. [Bug 2467]

	* tests/expr.test:
	* generic/tclCompile.c: fixed 'bad code length' error for 'expr +
	{[incr]}' case, with new test case [Bug 3736] and seg fault on 'expr
	+ {[error]}' (different cause) that was caused by a correct
	optimization that didn't correctly track how it was modifying the
	source string in the opt. The optimization was removed, which means
	that:
		expr 1 + {[string length abc]}
	will be not be compiled inline as before, but this should be written:
		expr {1 + [string length abc]}
	which will be compiled inline for speed. This prevents:
		expr 1 + {[mindless error]}
	from seg faulting, and only affects optimizations for degenerate cases
	[Bug 3737]

1999-12-01  Scott Redman <redman@scriptics.com>

	* generic/tcl.decls:
	* generic/tclMain.c:
	* unix/tclAppInit.c:
	* win/tclAppInit.c: Added two new internal functions,
	TclSetStartupScriptFileName() and TclGetStartupScriptFileName() and
	added hooks into the main() code for supporting TclPro and other "big"
	shells more easily without requiring a copy of the main() code.

	* generic/tclEncoding.c:
	* generic/tclEvent.c: Moved encoding-related startup code from
	tclEvent.c into the more appropriate tclEncoding.c.

1999-11-30  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclIO.c: fix from Kupries for	Tcl_UnstackChannel that
	correctly handles resetting translation and encoding.

	* generic/tclLoad.c: #def'd out the unloading of DLLs at finalize time
	for Unix in TclFinalizeLoad. [Bug 2560 3373] Should be parametrized
	to allow for user to specify unload or not.

	* win/tclWinTime.c: fixed handling of %Z on NT for time zones that
	don't have DST.

1999-11-29  Jeff Hobbs  <hobbs@scriptics.com>

	* library/dde1.1/pkgIndex.tcl:
	* library/reg1.0/pkgIndex.tcl: added supported for debugged versions
	of the libraries

	* unix/tclUnixPipe.c: fixed PipeBlockModeProc to properly set
	isNonBlocking flag on pipe. [Bug 1356 710]
	removed spurious fcntl call from PipeBlockModeProc

	* tests/scan.test:
	* generic/tclScan.c: fixed scan where %[..] didn't match anything and
	added test case. [Bug 3700]

1999-11-24  Jeff Hobbs  <hobbs@scriptics.com>

	* doc/open.n:
	* win/tclWinSerial.c: adopted patch from Schroedter to handle
	fconfigure $sock -lasterror on Windows. [RFE 3368]

	* generic/tclCmdIL.c: made SORTMODE_INTEGER work with Longs [Bug 3652]

1999-11-23  Scott Stanton  <stanton@scriptics.com>

	* library/tcltest1.0/tcltest.tcl: Fixed bug where tcltest output went
	to stdout instead of the specified output file in some cases.

1999-11-19  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclProc.c: backed out change from 1999-11-18 as it could
	affect return string from upvar as well.

	* tools/tcl.wse.in: added tcltest1.0 library to distribution list

	* doc/http.n:
	* library/http2.1/http.tcl:
	* library/http2.1/pkgIndex.tcl: updated http package to 2.2

1999-11-18  Jeff Hobbs  <hobbs@scriptics.com>

	* unix/tcl.m4: added defined for _THREAD_SAFE in --enable-threads
	case; added check for pthread_mutex_init in libc; in AIX case, with
	--enable-threads ${CC}_r is used; fixed flags when using gcc on SCO

	* generic/tclProc.c: corrected error reporting for default case at the
	global level for uplevel command.

	* generic/tclIOSock.c: changed int to size_t type for len in
	TclSockMinimumBuffers.

	* generic/tclCkalloc.c: fixed Tcl_DbCkfree to return a value on NULL
	input. [Bug 3400]

	* generic/tclStringObj.c: fixed support for passing in negative length
	to Tcl_SetUnicodeObj, et al handling routines. [Bug 3380]

	* doc/scan.n:
	* tests/scan.test:
	* generic/tclScan.c: finished support for inline scan by supporting
	XPG identifiers.

	* doc/http.n:
	* library/http2.1/http.tcl: added register and unregister commands to
	http:: package (better support for tls/SSL), as well as -type argument
	to http::geturl. [RFE 2617]

	* generic/tclBasic.c: removed extra decr of numLevels in Tcl_EvalObjEx
	that could cause seg fault. (mjansen@wendt.de)

	* generic/tclEvent.c: fixed possible lack of MutexUnlock in
	Tcl_DeleteExitHandler. [Bug 3545]

	* unix/tcl.m4: Added better pthreads library check and inclusion of
	_THREAD_SAFE in --enable-threads case
	Added support for gcc config on SCO

	* doc/glob.n: added note about ..../ glob behavior on Win9*
	* doc/tcltest.n: fixed minor example errors. [Bug 3551]

1999-11-17 Brent Welch <welch@scriptics.com>

	* library/http2.1/http.tcl: Correctly fixed the -timeout problem
	mentioned in the 10-29 change. Also added error handling for failed
	writes on the socket during the protocol.

1999-11-09  Jeff Hobbs  <hobbs@scriptics.com>

	* doc/open.n: corrected docs for 'a' open mode.

	* generic/tclIOUtil.c: changed Tcl_Alloc to ckalloc

	* generic/tclInt.h:
	* generic/tclObj.c: rolled back changes from 1999-10-29
	Purify noted new leaks with that code

	* generic/tclParse.c: added code in Tcl_ParseBraces to test for
	possible unbalanced open brace in a comment

	* library/init.tcl: removed the installed binary directory from the
	auto_path variable

	* tools/tcl.wse.in: updated to 8.3a1, fixed install of twind.tcl and
	koi8-r.enc files

	* unix/tcl.m4: added recognition of pthreads library for AIX

1999-10-29  Brent Welch <welch@scriptics.com>

	* generic/tclInt.h: Modified the TclNewObj and TclDecrRefCount in two
	ways. First, in the case of TCL_THREADS, we do not use the special
	Tcl_Obj allocator because that is a source of lock contention. Second,
	general code cleanup to eliminate duplicated code. In particular,
	TclDecrRefCount now uses TclFreeObj instead of duplicating that code,
	so it is now identical to Tcl_DecrRefCount.

	* generic/tclObj.c: Changed Tcl_NewObj so it uses the TclNewObj macro
	instead of duplicating the code. Adjusted TclFreeObj so it understands
	the TCL_THREADS case described above.

	* library/http2.1/http.tcl: Fixed a bug in the handling of the
	state(status) variable when the -timeout flag is specified. Previously
	it was possible to leave the status undefined instead of empty, which
	caused errors in http::status

1999-10-28  Jeff Hobbs  <hobbs@scriptics.com>

	* unix/aclocal.m4: made it just include tcl.m4

	* library/tcltest1.0/tcltest.tcl: updated makeFile to return full
	pathname of file created

	* generic/tclStringObj.c: fixed Tcl_AppendStringsToObjVA so it only
	iterates once over the va_list (avoiding a memcpy of it, which is not
	portable).

	* generic/tclEnv.c: fixed possible ABR error in environ array

	* tests/scan.test:
	* generic/tclScan.c: added support for use of inline scan, XPG3
	currently not included

	* tests/incr.test:
	* tests/set.test:
	* generic/tclCompCmds.c: fixed improper bytecode handling of 'eval
	{set array($unknownvar) 5}' (also for incr). [Bug 3184]

	* win/tclWinTest.c: added testvolumetype command, as atime is
	completely ignored for Windows FAT file systems
	* win/tclWinPort.h: added sys/utime.h to includes
	* unix/tclUnixPort.h: added utime.h to includes
	* doc/file.n:
	* tests/cmdAH.test:
	* generic/tclCmdAH.c: added time arguments to atime and mtime file
	command methods (support 'touch' functionality)

1999-10-20  Jeff Hobbs  <hobbs@scriptics.com>

	* unix/tclUnixNotfy.c: fixed event/io threading problems by making
	triggerPipe non-blocking. [Bug 2792]

	* library/tcltest1.0/tcltest.tcl:
	* generic/tclThreadTest.c: fixed mem leaks in threads

	* generic/tclResult.c: fixed Tcl_AppendResultVA so it only iterates
	once over the va_list (avoiding a memcpy of it, which is not
	portable).

	* generic/regc_color.c: fixed mem leak and assertion, from HS

	* generic/tclCompile.c: removed savedChar trick that appeared to be
	causing a segv when the literal table was released

	* tests/string.test:
	* generic/tclCmdMZ.c: fixed [string index] to return ByteArrayObj when
	indexing into one (test case string-5.16). [Bug 2871]

	* library/http2.1/http.tcl: protected gets with catch. [Bug 2665]

1999-10-19  Jennifer Hom  <jenn@scriptics.com>

	* tests/tcltest.test:
	* doc/tcltest.n:
	* library/tcltest1.0/tcltest.tcl: Removed the extra return at the end
	of the tcltest.tcl file, added version information about tcl.

	Applied patches sent in by Andreas Kupries to add helper procs for
	debug output, add 3 new flags (-testsdir, -load, -loadfile), and
	internally refactors common code for dealing with paths into separate
	procedures. [Bug 2838, 2842]

	Merged code from core-8-2-1 branch that changes the checks for the
	value of tcl_interactive to also incorporate a check for the existence
	of the variable.

	* tests/autoMkindex.test:
	* tests/pkgMkIndex.test: Explicitly cd to ::tcltest::testsDirectory at
	the beginning of the test run

	* tests/basic.test: Use version information defined in tcltest instead
	of hardcoded version number

	* tests/socket.test: package require tcltest before attempting to use
	variable defined in tcltest namespace

	* tests/unixInit.test:
	* tests/unixNotfy.test: Added explicit exits needed to avoid problems
	when the tests area run in wish.

1999-10-12  Jim Ingham  <jingham@scriptics.com>

	* mac/tclMacLoad.c: Stupid bug - we converted the filename to
	external, but used the unconverted version.
	* mac/tclMacFCmd.c: Fix a merge error in the bug fix for [Bug 2869]

1999-10-12  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/regc_color.c:
	* generic/regc_cvec.c:
	* generic/regc_lex.c:
	* generic/regc_locale.c:
	* generic/regcomp.c:
	* generic/regcustom.h:
	* generic/regerrs.h:
	* generic/regex.h:
	* generic/regexec.c:
	* generic/regguts.h:
	* generic/tclRegexp.c:
	* generic/tclTest.c:
	* tests/reg.test: updated to Henry Spencer's new regexp engine
	(mid-Sept 99). Should greatly reduce stack space reqs.

	* library/tcltest1.0/pkgIndex.tcl: fixed procs in pkgIndex.tcl file

	* generic/tclEnv.c: fixed mem leak with putenv and DStrings
	* doc/Encoding.3: corrected docs
	* tests/basic.test: updated test cases for 8.3
	* tests/encoding.test: fixed test case that change system encoding to
	a double-byte one (this causes a bogus mem read error for purify)
	* unix/Makefile.in: purify has to use -best-effort to instrument
	* unix/tclAppInit.c: identified potential mem leak when compiling
	tcltest (not critical)
	* unix/tclUnixPipe.c: fixed mem leak in TclpCreateProcess when doing
	alloc between vfork and execvp.
	* unix/tclUnixTest.c: fixed mem leak in findexecutable test command

1999-10-05  Jeff Hobbs  <hobbs@scriptics.com>

	* {win,mac,unix,tools,}/README:
	* win/README.binary:
	* win/makefile.vc:
	* {win,unix}/configure.in:
	* generic/tcl.h:
	* library/init.tcl: updated to 8.3a1 from 8.2.0.

	* library/http2.1/http.tcl: fixed possible use of global c var.

	* win/tclWinReg.c: fixed registry command to properly 'get'
	HKEY_PERFORMANCE_DATA root key data. Needs more work.

	* generic/tclNamesp.c:
	* generic/tclVar.c:
	* generic/tclCmdIL.c: fixed comment typos

	* mac/tclMacFCmd.c: fixed filename stuff to support UTF-8. [Bug 2869]

	* win/tclWinSerial.c: changed SerialSetOptionProc to return TCL_OK by
	default. (patch from Rolf Schroedter)

1999-09-21  Jennifer Hom  <jenn@scriptics.com>

	* library/tcltest1.0/tcltest.tcl: Applied patches sent in by Andreas
	Kupries to fix typos in comments and ::tcltest::grep, fix hook
	redefinition problems, and change "string compare" to "string equal".
	[Bug 2836, 2837, 2839, 2840]

1999-09-20  Jeff Hobbs  <hobbs@scriptics.com>

	* tests/env.test:
	* unix/Makefile.in: added support for AIX LIBPATH env var. [Bug 2793]
	removed second definition of INCLUDE_INSTALL_DIR (the one that
	referenced @includedir@) [Bug 2805]
	* unix/dltest/Makefile.in: added -lc to LIBS. [Bug 2794]

1999-09-16  Jeff Hobbs  <hobbs@scriptics.com>

	* tests/timer.test: changed after delay in timer test 6.29 from 1 to
	10. [Bug 2796]

	* tests/pkg.test:
	* generic/tclPkg.c: fixed package version check to disallow 1.2..3
	[Bug 2539]

	* unix/Makefile.in: fixed gendate target - this never worked since RCS
	was intro'd.
	* generic/tclGetDate.y: updated to reflect previous changes to
	tclDate.c (leap year calc) and added CEST and UCT time zone
	recognition. Fixed 4 missing UCHAR() casts. [Bug 2717, 954, 1245,
	1249]

	* generic/tclCkalloc.c: changed Tcl_DumpActiveMemory to really dump to
	stderr and close it [Bug 725] and changed Tcl_Ckrealloc and
	Tcl_Ckfree to not bomb when NULL was passed in [Bug 1719] and changed
	Tcl_Alloc, et al to not panic when a alloc request for zero came
	through and NULL was returned (valid on AIX, Tru64) [Bug 2795, etc]

	* tests/clock.test:
	* doc/clock.n:
	* generic/tclClock.c: added -milliseconds switch to clock clicks to
	guarantee that the return value of clicks is in the millisecs
	granularity. [Bug 2682, 1332]

1999-09-15  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclIOCmd.c: fixed potential core dump in conjunction with
	stacked channels with result obj manipulation in Tcl_ReadChars. [Bug
	2623]

	* tests/format.test:
	* generic/tclCmdAH.c: fixed translation of %0#s in format. [Bug 2605]

	* doc/msgcat.n: fixed \\ bug in example. [Bug 2548]

	* unix/tcl.m4:
	* unix/aclocal.m4: added fix for FreeBSD-[1-2] recognition [Bug 2070]
	and fix for IRIX SHLIB_LB_LIBS. [Bug 2610]

	* doc/array.n:
	* tests/var.test:
	* tests/set.test:
	* generic/tclVar.c: added an array unset operation, with docs and
	tests. Variation of [Bug 1775]. Added fix in TclArraySet to check
	when trying to set in a non-existent namespace. [Bug 2613]

1999-09-14  Jeff Hobbs  <hobbs@scriptics.com>

	* tests/linsert.test:
	* doc/linsert.n:
	* generic/tclCmdIL.c: fixed end-int interpretation of linsert to
	correctly calculate value for end, added test and docs. [Bug 2693]

	* doc/regexp.n:
	* doc/regsub.n:
	* tests/regexp.test:
	* generic/tclCmdMZ.c: add -start switch to regexp and regsub with docs
	and tests

	* doc/switch.n: added proper use of comments to example.
	* generic/tclCmdMZ.c: changed switch to complain when an error occurs
	that seems to be due to a misplaced comment.

	* generic/tclCmdMZ.c: fixed illegal ref for \[0-9] substitutions in
	regsub. [Bug 2723]

	* generic/tclCmdMZ.c: changed [string equal] to return an Int type
	object (was a Boolean)

1999-09-01  Jennifer Hom  <jenn@scriptics.com>

	* library/tcltest1.0/tcltest.tcl: Process command-line arguments only
	::tcltest doesn't have a child namespace (requires that command-line
	args are processed in that namespace)

1999-09-01  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclParseExpr.c: changed '"' to '\"' to make FreeBSD happy.
	[Bug 2625]
	* generic/tclProc.c: moved static buf to better location and changed
	static msg that would overflow in ProcessProcResultCode [Bug 2483]
	and added Tcl_DStringFree to Tcl_ProcObjCmd. Also reworked size of
	static buffers.
	* tests/stringObj.test: added test 9.11
	* generic/tclStringObj.c: changed Tcl_AppendObjToObj to properly
	handle the 1-byte dest and mixed src case where both had had Unicode
	string len checks made on them. [Bug 2678]
	* unix/aclocal.m4:
	* unix/tcl.m4: adjusted fix from 8-21 to add -bnoentry to the AIX-*
	case and readjusted the range

1999-08-31  Jennifer Hom  <jenn@scriptics.com>

	* library/tcltest1.0/tcltest.tcl:
	* doc/tcltest.n:
	* tests/README: Modified testConstraints variable so that it isn't
	unset every time ::tcltest::initConstraints is called and cleaned up
	documentation in the README file and the man page.

1999-08-27  Jennifer Hom  <jenn@scriptics.com>

	* tests/env.test:
	* tests/exec.test:
	* tests/io.test:
	* tests/event.test:
	* tests/tcltest.test: Added 'exit' calls to scripts that the tests
	themselves write, and removed accidental checkin of knownBugThreaded
	constraints for Solaris and Linux.

	* library/tcltest1.0/tcltest.tcl: Modified tcltest so that variables
	are only initialized to their default values if they did not
	previously exist.

1999-08-26  Jennifer Hom  <jenn@scriptics.com>

	* tests/tcltest.test:
	* library/tcltest1.0/tcltest.tcl: Added a -args flag that sets a
	variable named ::tcltest::parameters based on whatever's being sent in
	as the argument to the -args flag.

1999-08-23  Jennifer Hom  <jenn@scriptics.com>

	* tests/tcltest.test: Added additional tests for -tmpdir, marked all
	tests that use exec as unixOrPc.

	* tests/encoding.test:
	* tests/interp.test:
	* tests/macFCmd.test:
	* tests/parseOld.test:
	* tests/regexp.test: Applied patches from Jim Ingham to add encoding
	to a Mac only interp test, change an error message in macFCmd.tet, put
	a comment in parseOld.test, fix tests using the testencoding path
	command, and put unixOrPc constraints on tests that use exec.

1999-08-21  Jeff Hobbs  <hobbs@scriptics.com>

	* unix/aclocal.m4: Changed AIX-4.[2-9] check to AIX-4.[1-9] [Bug 1909]

1999-08-20  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclPosixStr.c: fixed typo. [Bug 2592]

	* doc/*: fixed various nroff bugs in man pages. [Bug 2503 2588]

1999-08-19  Jeff Hobbs  <hobbs@scriptics.com>

	* win/README.binary: fixed version info and some typos. [Bug 2561]

	* doc/interp.n: updated list of commands available in a safe
	interpreter. [Bug 2526]

	* generic/tclIO.c: changed Tcl_GetChannelNames* to use style guide
	headers (pleases HP cc)

1999-08-18  Jeff Hobbs  <hobbs@scriptics.com>

	* doc/Eval.3: fixed doc on input args. [Bug 2114]

	* doc/OpenFileChnl.3:
	* doc/file.n:
	* tests/cmdAH.test:
	* tclIO.c:
	* tclCmdAH.c: added "file channels ?pattern?" tcl command, with
	associated Tcl_GetChannelNames and Tcl_GetChannelNamesEx public C APIs
	(added to tcl.decls as well), with docs and tests.

	* tests/expr.test:
	* generic/tclCompile.c: add TCL_TOKEN_VARIABLE to the part types that
	cause differed compilation for exprs, to correct the expr
	double-evaluation problem for vars. Added test cases. Related to [Bug
	732]

	* unix/Makefile.in: changed the dependency structure so that install-*
	is dependent on * (ie - install-binaries is dependent on binaries).

	* library/auto.tcl:
	* library/init.tcl:
	* library/ldAout.tcl:
	* library/package.tcl:
	* library/safe.tcl:
	* library/word.tcl:
	* library/http2.1/http.tcl:
	* library/msgcat1.0/msgcat.tcl: updated libraries to better Tcl style
	guide (no more string comparisons with == or !=, spacing changes).

1999-08-05  Jim Ingham  <jingham@cygnus.com>

	* mac/tclMacProjects.sea.hqx: Rearrange the projects so that the build
	directory is separate from the sources. Much more convenient!

1999-08-13  Scott Redman <redman@scriptics.com>

	* /: 8.2.0 tagged for final release

1999-08-12  Scott Stanton  <stanton@scriptics.com>

	* win/Makefile.in: Added COMPILE_DEBUG_FLAGS macro to make it easier
	to turn on compiler tracing.

	* tests/parse.test:
	* generic/tclParse.c: Fixed bug in Tcl_EvalEx where the termOffset was
	not being updated in cases where the evaluation returned a non TCL_OK
	error code. [Bug 2535]

1999-08-12  Scott Redman  <redman@scriptics.com>

	* win/tclWinSerial.c: Applied patch from Petteri Kettunen to remove
	compiler warning.

1999-08-10  Scott Redman  <redman@scriptics.com>

	* generic/tclAlloc.c:
	* generic/tclCmdIL.c:
	* generic/tclIO.c:
	* generic/tclThread.c:
	* win/tclWinThrd.c:
	* unix/tclUnixThrd.c: Fixed Brent's changes so that they work on
	Windows (and he fixed the bug in the Unix thread implementation).

1999-08-09  Brent Welch  <welch@scriptics.com>

	* generic/tcl.decls:
	* generic/tclAlloc.c:
	* generic/tclCkalloc.c:
	* generic/tclCmdIL.c:
	* generic/tclDecls.h:
	* generic/tclIO.c:
	* generic/tclInt.decls:
	* generic/tclIntDecls.h:
	* generic/tclStubInit.c:
	* generic/tclVar.c:
	* mac/tclMacThrd.c:
	* unix/tclUnixThrd.c:
	* win/tclWinThrd.c: Added use of Tcl_GetAllocMutex to tclAlloc.c and
	tclCkalloc.c so they can be linked against alternate thread packages.
	Added Tcl_GetChannelNames to tclIO.c. Added TclVarTraceExists hook so
	"info exists" triggers read traces exactly like it did in Tcl 7.6.
	Stubs table changes to reflect new internal and external APIs.

1999-08-09  Jeff Hobbs  <hobbs@scriptics.com>

	* tests/string.test: added largest_int proc to adapt for >32 bit
	machines and int overflow testing.
	* tests/tcltest.test: fixed minor error in 8.2 result (from dgp)

	* doc/Object.3: clarified Tcl_DecrRefCount docs. [Bug 1952]
	* doc/array.n: clarified array pattern docs. [Bug 1330]
	* doc/clock.n: fixed clock docs. [Bug 693]
	* doc/lindex.n: clarified to account for new end-int behavior.
	* doc/string.n: fixed formatting errors. [Bug 2188 2189]
	* doc/tclvars.n: fixed doc error. [Bug 2042]
	* library/init.tcl: fixed path handling in auto_execok (it could miss
	including the normal path on some Windows machines). [Bug 1276]

1999-08-05  Jeff Hobbs  <hobbs@scriptics.com>

	* doc/tclvars.n: Made it clear that tcl_pkgPath was not set for
	Windows (already mentioned in init.tcl). [Bug 2455]
	* generic/tclLiteral.c: fixed reference to bytes that might not be
	null terminated (using objPtr->bytes, which is). [Bug 2496]
	* library/http2.1/http.tcl: Made use of "i" in init section use local
	var and start at 0 (was 1). [Bug 2502]

1999-08-04  Scott Stanton  <stanton@scriptics.com>

	* tests/reg.test: Added test for REG_EXPECT bug fixed by Henry's
	patch.

	* generic/regc_nfa.c:
	* generic/regcomp.c:
	* generic/rege_dfa.c:
	* generic/regexec.c:
	* generic/regguts.h: Applied patches supplied by Henry Spencer to
	greatly enhance the performance of certain classes of regular
	expressions. [Bug 2440, 2447]

1999-08-03  Scott Redman  <redman@scriptics.com>

	* win/tclWinInt.h: Remove function declarations in header that was
	moved to tclInt.decls file in previous changes.

1999-08-02  Scott Redman  <redman@scriptics.com>

	* unix/configure.in:
	* win/configure.in: Change beta level to b2.

	* generic/tcl.h:
	* generic/tcl.decls:
	* generic/tclDecls.h:
	* generic/tclInt.h:
	* generic/tclInt.decls:
	* generic/tclIntDecls.h:
	* generic/tclRegexp.h:
	* generic/tclStubInit.c: Move some exported public and internal
	functions to the stub tables. Removed functions that are in the stub
	tables (from this and previous changes) from the original header
	files.

1999-08-01  Scott Redman  <redman@scriptics.com>

	* win/tclWinSock.c: Added comment block to SocketThread() function.
	Added code to avoid calling TerminateThread(), but instead to send a
	message to the socket event window to tell it to terminate its thread.

1999-07-30  Jennifer Hom  <jenn@scriptics.com>

	* tests/tcltest.test:
	* library/tcltest1.0/tcltest.tcl: Exit with non-zero status if there
	were problems with the way the test suite was started (e.g. wrong #
	arguments).

1999-07-30  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclInt.decls: added declaractions necessary for the Tcl test
	code to work wth stubs. [Bug 2445]

1999-07-30  Scott Redman  <redman@scriptics.com>

	* win/tclWinPipe.c:
	* win/Makefile.in: Fixing launching of 16-bit apps on Win9x from wish.
	The command line was primed with tclpip82.dll, but it was ignored.
	Fixed that, then fixed the gmake makefile to build tclpip82.dll as an
	executable.

	* win/tclWinSock.c: Applied small patch to get thread-specific data
	after initializing the socket driver.

	* unix/tclUnixThrd.c: Applied patch to fix threads on Irix 6.5. Patch
	from James Dennett. [Bug 2450]

	* tests/info.test: Enable test for tclParse.c change (info complete).

1999-07-30  Jeff Hobbs  <hobbs@scriptics.com>

	* tclIO.c: added fix for Kupries' trf patch. [Bug 2386]

	* tclParse.c: fixed bug in info complete regarding nested square
	brackets. [Bug 2382, 2466]

1999-07-29  Scott Redman  <redman@scriptics.com>

	* win/tclWinChan.c: Allow tcl to open CON and NUL, even for std
	channels. Checking for bad/unusable std channels was moved to Tk since
	its only purpose was to check whether to use the Tk Console Window for
	the std channels. [Bug 2393 2392 2209 2458]

	* unix/mkLinks.tcl: Applied patch to avoid linking pack.n to
	pack-old.n. Patch from Don Porter. [Bug 2469]

	* doc/Encoding.n: Applied patch to fix typo in .SH NAME line. Patch
	from Don Porter. [Bug 2451]

	* win/tclWinSock.c: Free Win32 Event handles when destroying the
	socket helper thread.

1999-07-28  Jennifer Hom  <jenn@scriptics.com>

	* tests/tcltest.test:
	* library/tcltest1.0/tcltest.tcl: Fixed the condition under which
	::tcltest::PrintError had an infinite loop problem and added a test
	case for it. Added an optional argument to ::tcltest::getMatchingFiles
	telling it where to search for test files.

1999-07-27  Scott Redman  <redman@scriptics.com>

	* tools/tclSplash.bmp: Updated Windows installer bitmap to ready
	Tcl/Tk Version 8.2.

1999-07-26  Scott Redman  <redman@scriptics.com>

	* tests/tcltest.test: Need to close the new core file, there seems to
	be a hang in threaded WinNT if the file isn't closed. Open issue, need
	to fix that hang.

	* tests/httpold.test: Add time delay in response from Http server so
	that test cases can properly detect timeout conditions with threads
	enabled on multi-CPU WinNT.

	* tests/winFCmd.test: Test case winFcmd-1.33 was looking for
	c:\windows, which may not exist. Instead, create a new directory on
	c:\ and use it for the test.

	* win/tclWinConsole.c:
	* win/tclWinPipe.c:
	* win/tclWinSock.c: Fix terminating helper threads by holding any
	mutexes from the primary thread while waiting for the helper thread to
	terminate. Without these changes, the test suite hangs on WinNT with 2
	CPUs and threads enabled. Open issue, seems to be a sporadic hang on
	dual CPU systems still (very rare).

1999-07-26  Jennifer Hom  <jenn@scriptics.com>

	* tests/tcltest.test:
	* library/tcltest1.0/tcltest.tcl:
	* doc/tcltest.n: Cleaned up code in ::tcltest::PrintError, revised
	documentation, and added tests for the tcltest package.

1999-07-23  Scott Redman  <redman@scriptics.com>

	* tests/info.test:
	* generic/tclParse.c: Removed patch for info command, breaks test
	cases on Unix. Patch was bad and needs to be redone properly. [Bug
	2382]

1999-07-22  Scott Redman  <redman@scriptics.com>

	* Changed version to 8.2b2.

	* win/tclWinSock.c: Fixed hang with threads enabled, fixed semaphores
	with threads disabled.

	* win/safe.test: Fixed safe-6.3 with threads enabled.

	* win/Makefile.in: Fixed calling of tcltest to fix safe.test failures
	due to path TCL_LIBRARY path.

	* win/tclWinPort.h: Block out include of sys/*.h in order to build
	extensions with MetroWerks compiler for Win32. [Bug 2385]

	* generic/tclCmdMZ.c:
	* generic/tclIO.c: Fix ANSI-style prototypes based on patch from
	Ulrich Ring. [Bug 2391]

	* unix/Makefile.in: Need to make install-sh executable before calling
	(with chmod +x). [Bug 2413]

	* tests/var.test:
	* generic/tclVar.c: Fixed bug that caused a seg. fault when using
	"array set a(b) {}", which is a bad array name anyway. Now the "array
	set" command will return an error in this case. Added test case and
	fixed existing test. [Bug 2427]

1999-07-21  Scott Redman  <redman@scriptics.com>

	* tests/info.test:
	* generic/tclParse.c: Applied patch to fix "info complete" for the
	string {[a [b]}. Patch from Peter Spjuth. [Bug 2382]

	* doc/Utf.3:
	* generic/tcl.decls:
	* generic/tclDecls.h:
	* generic/tclUtf.c: Changed function declarations in
	non-platform-specific public APIs to use "unsigned long" instead of
	"size_t", which may not be defined on certain compilers (rather than
	include sys/types.h, which may not exist).

	* unix/Makefile.in: Added the Windows configure script to the
	distribution file list, already shipping configure.in and the .m4
	files, but needed the configure script itself.

	* win/makefile.vc: Changed version number of DDE package in VC++
	makefile to use 1.1 instead of 1.0.

	* doc/open.n: Added documentation of \\.\comX notation for opening
	serial ports on Windows (alternative to comX:).

	* tests/ioCmd.test:
	* doc/open.n:
	* win/tclWinSerial.c: Applied patch from Rolf Schroedter to add
	-pollinterval option to fconfigure to modify the maxblocktime used in
	the fileevent polling. Added documentation and fixed the test case as
	well.

	* win/tclWinSock.c: Modified 8.1.0 version of the Win32 socket driver
	to move the handling of the socket event window in a separate thread.
	It also turned out that Win95 & Win98 were, in some cases, getting
	multiple FD_ACCEPTs but only handling one. Added a count for the
	FD_ACCEPT to take care of this. Tested on NT4 SP3, NT4 SP4, Win95, and
	Win98. [Bug 2178 2256 2259 2329 2323 2355]

1999-07-21  Jerry Peek  <jpeek@scriptics.com>

	* README: Small tweaks to clean up typos and wording.

1999-07-20  Melissa Hirschl  <hershey@matisse.scriptics.com>

	* generic/tclInitScript.h:
	* unix/tclUnixInit.c: merged code with 8.0.5. We now use an
	intermediate global tcl var "tclDefaultLibrary" to keep the
	"tcl_library" var from being set by the default value in the Makefile.
	Also fixed a bug in which caused the value of TCL_LIBRARY env var to
	be ignored.
	* unix/tclWinInit.c: just updated some comments.

1999-07-19  Melissa Hirschl  <hershey@matisse.scriptics.com>

	* library/http2.1/http.tcl: updated -useragent text to say version
	2.1.

1999-07-16  Scott Redman  <redman@scriptics.com>

	* generic/tcl.decls:
	* generic/tclDecls.h:
	* generic/tclStubInit.c: Add Tcl_SetNotifier to stub table. [Bug 2364]

	* unix/aclocal.m4:
	* unix/tcl.m4: Add check for Alpha/Linux to correct the IEEE floating
	flag to the compiler, should be -mieee. Patch from Don Porter.

	* tools/tcl.hpj.in: Change version number of .cnt file referenced in
	.HPJ file.

1999-07-15  Scott Redman  <redman@scriptics.com>

	* tools/tcl.wse.in: Fixed naming of target files for Windows.

1999-07-14  Jerry Peek  <jpeek@scriptics.com>

	* doc/re_syntax.n: Deleted sentence as suggested by Scott S.

1999-07-12  Jerry Peek  <jpeek@scriptics.com>

	* doc/re_syntax.n: Removed two notes to myself (oops), cleaned up
	wording, fixed changebars, made two examples easier to read.

1999-07-11  Scott Redman  <redman@scriptics.com>

	* win/makefile.vc: Since the makefile.vc should continue to work while
	we're working out bugs/issues in the new TEA-style
	autoconf/configure/gmake build mechanism for Windows, the version
	numbers of the Tcl libraries need to remain in sync. Modified the
	version numbers in the makefile to reflect the change to 8.2b1.

1999-07-09  Scott Redman  <redman@scriptics.com>

	* win/configure.in: Eval DLLSUFFIX, LIBSUFFIX, and EXESUFFIX in the
	configure script so that substitutions get expanded before being
	placed in the Makefile. The "d" portion for debug libraries and DLLs
	was not being set properly.

1999-07-08  Scott Stanton  <stanton@scriptics.com>

	* tests/string.test:
	* generic/tclCmdMZ.c: Fixed bug in string range bounds checking code.

1999-07-08  Jennifer Hom  <jenn@scriptics.com>

	* doc/tcltest.n:
	* library/tcltest1.0/tcltest.tcl: Removed -asidefromdir and
	-relateddir flags, removed unused ::tcltest::dotests proc, cleaned up
	implementation of core file checking, and fixed the code that checks
	for 1-letter flag abbreviations.

1999-07-08  Scott Stanton  <stanton@scriptics.com>

	* win/Makefile.in: Added tcltest target so runtest works properly.
	Added missing names to the clean/distclean targets.

	* tests/reg.test:
	* generic/rege_dfa.c: Applied fix supplied by Henry Spencer for bug in
	DFA state caching under lookahead conditions. [Bug 2318]

1999-07-07  Scott Stanton  <stanton@scriptics.com>

	* doc/fconfigure.n: Clarified default buffering behavior for the
	standard channels. [Bug 2335]

1999-07-06  Scott Redman  <redman@scriptics.com>

	* win/tclWinSerial.c: New implementation of serial port driver from
	Rolf Shroedter (Rolf.Schroedter@dlr.de) that allows more than one byte
	to be read from the port. Implemented using polling instead of
	threads, there is a max. 10ms latency between checking the port for
	file events. [Bug 1980 2217]

1999-07-06  Brent Welch  <welch@scriptics.com>

	* library/http2.0/http.tcl: Fixed the -timeout option so it handles
	timeouts that occur during connection attempts to hosts that are down
	(the only case that really matters!)

1999-07-03  Brent Welch  <welch@scriptics.com>

	* doc/ChnlStack.3:
	* generic/tcl.decls:
	* generic/tclIO.c: Added a new variant of the "Trf patch" from Andreas
	Kupres that adds new C APIs Tcl_StackChannel, Tcl_UnstackChannel, and
	Tcl_GetStackedChannel.

1999-07-03  Brent Welch  <welch@scriptics.com>

	* generic/tclNotify.c:
	* unix/tclUnixNotfy.c:
	* unix/tclXtTest.c:
	* unix/tclXtNotify.c:
	* win/tclWinNotify.c:
	* mac/tclMacNotify.c: Added Tcl_SetNotifier and the associated hook
	points in the notifiers to be able to replace the notifier calls at
	runtime. The Xt notifier and test program use this hook.

1999-07-03  Brent Welch  <welch@scriptics.com>

	* generic/tclParse.c: Changed parsing of variable names to allow empty
	array names. Now "$(foo)" is a variable reference! Previous you had to
	use something like $::(foo), which is slower. This change is requested
	by Jean-Luc Fontaine for his STOOOP package.

1999-07-01  Scott Redman  <redman@scriptics.com>

	* generic/tclCmdAH.c:
	* generic/tclFCmd.c: Call TclStat instead of TclpStat in order to
	allow Tcl_Stat hooks to work properly.

1999-06-29  Jennifer Hom  <jenn@scriptics.com>

	* library/tcltest1.0/pkgIndex.tcl:
	* library/tcltest1.0/tcltest.tcl:
	* doc/tcltest.n:
	* tests/all.tcl: Added -preservecore, -limitconstraints, -help, -file,
	-notfile, -relateddir and -asidefromdir flags to the tcltest package
	along with exported proc ::tcltest::getMatchingFiles. The
	documentation was modified to match and all.tcl was modified to use
	the new functionality instead of implementing -file itself.

1999-06-28  Scott Redman  <redman@scriptics.com>

	* generic/tclIndexObj.c:
	* doc/GetIndex.3:
	* tests/binary.test:
	* tests/winDde.test: Applied patch from Peter Hardie (with changes) to
	fix problem with Tcl_GetIndexFromObj() when the key being passed is
	the empty string. It used to match "" and return TCL_OK, but it should
	have returned TCL_ERROR instead. Added test case to "binary" and "dde"
	commands to check the behavior. Added documentation note as well.

1999-06-26  Scott Redman  <redman@scriptics.com>

	* win/tclWinDde.c: Applied patch from Peter Hardie to add poke command
	to dde. Also rev'd version of dde package to 1.1. [Bug 1738]

1999-06-25  Jennifer Hom  <jenn@scriptics.com>

	* unix/Makefile.in:
	* win/Makefile.in:
	* library/tcltest1.0/pkgIndex.tcl:
	* library/tcltest1.0/tcltest.tcl:
	* library/tcltest1.0: Added initial implementation of the Tcl test
	harness package. This package was based on the defs.tcl file that was
	part of the tests directory. Reversed the way that tests were
	evaluated to fix a problem with false passes.

	* doc/tcltest.n: Added documentation for the tcltest package.

	* tests/README:
	* tests/defs.tcl:
	* tests/all.tcl: Modified all test files (tests/*.test) and all.tcl to
	use the new tcltest package and removed references to the defs.tcl
	file. Modified the README file to point to the man page for tcltest.

1999-06-25  Scott Stanton  <stanton@scriptics.com>

	* tests/reg.test:
	* generic/regexec.c: Fixed bugs in non-greedy quantifiers.

1999-06-23  Jerry Peek  <jpeek@scriptics.com>

	* doc/re_syntax.n:
	* doc/switch.n:
	* doc/lsearch.n:
	* doc/RegExp.3:
	* doc/regexp.n:
	* doc/regsub.n: Moved information about syntax of 8.1 regular
	expressions from regexp(n) manpage into new re_syntax(n) page. Added
	pointers from other manpages to new re_syntax(n) page.

1999-06-23  Scott Stanton  <stanton@scriptics.com>

	* unix/Makefile.in: Changed install-doc to install-man.

	* tools/uniParse.tcl:
	* tools/uniClass.tcl:
	* tools/README:
	* tests/string.test:
	* generic/regc_locale.c:
	* generic/tclUniData.c:
	* generic/tclUtf.c:
	* doc/string.n: Updated Unicode character tables to reflect latest
	Unicode 2.1 data. Also rationalized "regexp" and "string is"
	definitions of character classes.

1999-06-21  Scott Stanton  <stanton@scriptics.com>

	* unix/tclUnixThrd.c (TclpThreadCreate): Fixed memory leak where
	thread attributes were not being released. [Bug 2254]

1999-06-17  Scott Stanton  <stanton@scriptics.com>

	* tests/regexp.test:
	* generic/tclCmdMZ.c:
	* generic/tclCmdIL.c: Changed to use new regexp interfaces. Added
	-expanded, -line, -linestop, and -lineanchor switches to regsub.

	* doc/RegExp.3: Documented the new regexp interfaces and the
	compile/execute flags.

	* generic/tclTest.c:
	* generic/tclRegexp.h:
	* generic/tclRegexp.c:
	* generic/tcl.h:
	* generic/tcl.decls: Renamed Tcl_RegExpMatchObj to Tcl_RegExpExecObj
	and added a new Tcl_RegExpMatchObj that is equivalent to
	Tcl_RegExpMatch. Added public macros for the regexp compile/execute
	flags. Changed to store either an object pointer or a string pointer
	in the TclRegexp structure. Changed to avoid adding a reference to the
	object or copying the string.

	* generic/regcomp.c: lint

	* tests/reg.test:
	* generic/regex.h:
	* generic/regc_lex.c: Added REG_BOSONLY flag to allow Expect to
	iterate through a string an only find matches that start at the
	current position within the string.

1999-06-16  Michael Thomas  <wart@scriptics.com>

	* unix/configure.in:
	* unix/Makefile.in:
	* unix/tcl.m4:
	* unix/aclocal.m4: Numerous build changes to make Tcl conform to the
	proposed TEA spec

1999-06-16  Melissa Hirschl  <hershey@matisse.scriptics.com>

	* generic/tclVar.c (Tcl_VariableObjCmd): fixed premature increment in
	loop that was causing out-of-bounds reads on array "varName".

1999-06-16  Scott Stanton  <stanton@scriptics.com>

	* tests/execute.test:
	* generic/tclExecute.c (TclExecuteByteCode): Fixed crash caused by a
	bug in INST_LOAD_SCALAR1 where the scalar index was read as a signed 1
	byte value instead of unsigned. [Bug 2243]

1999-06-14  Melissa Hirschl  <hershey@matisse.scriptics.com>

	* doc/StringObj.3
	* test/stringObj.test
	* unix/Makefile.in
	* win/Makefile.in
	* win/makefile.vc
	* generic/tclStringObj.c:
	Merged String and Unicode object types. Added new functions to the
	puplic API: Tcl_NewUnicodeObj, Tcl_SetUnicodeObj, Tcl_GetUnicode,
	Tcl_GetUniChar, Tcl_GetCharLength, Tcl_GetRange,
	Tcl_AppendUnicodeToObj.

1999-06-09  Scott Stanton  <stanton@scriptics.com>

	* generic/tclUnicodeObj.c: Lots of cleanup and simplification. Fixed
	several memory bugs. Added TclAppendUnicodeToObj.

	* generic/tclInt.h: Added declarations for various Unicode string
	functions.

	* generic/tclRegexp.c:
	* generic/tclCmdMZ.c: Changed to use new Unicode string interfaces for
	better performance.

	* generic/tclRegexp.h:
	* generic/tclRegexp.c:
	* generic/tcl.h:
	* generic/tcl.decls: Added Tcl_RegExpMatchObj and Tcl_RegExpGetInfo
	calls to access lower level regexp API. These features are needed by
	Expect. This is a preliminary implementation pending final review and
	cleanup.

	* generic/tclCmdMZ.c:
	* tests/string.test: Fixed bug where string map failed on null strings

	* generic/regexec.c:
	* unix/tclUnixNotfy.c: lint

	* tools/genStubs.tcl: Changed to always write output in LF mode.

1999-06-08  Scott Stanton  <stanton@scriptics.com>

	* win/tclWinSock.c: Rolled back to the 8.1.0 implementation because of
	serious problems with the new driver. Basically no incoming socket
	connections would be reported to a server port. The 8.1.1 code needs
	to be redesigned and fixed correctly.

1999-06-07  Melissa Hirschl  <hershey@matisse.scriptics.com>

	* tests/string.test:
	* generic/tclVar.c (Tcl_SetVar2Ex):
	* generic/tclStringObj.c (Tcl_AppendObjToObj):
	* generic/tclCmdMZ.c (Tcl_StringObjCmd): optimized the string index,
	string length, string range, and append command in cases where the
	object's internal rep is a bytearray. Objects with other internal reps
	are converted to have the new unicode internal rep.

	* unix/Makefile.in:
	* win/Makefile.in:
	* win/Makefile.vc:
	* tests/unicode.test:
	* generic/tclInt.h:
	* generic/tclObj.c:
	* generic/tclUnicodeObj.c: added a new object type to store the
	unicode representation of a string.

	* generic/tclTestObj.c: added the objtype option to the testobj
	command. This option returns the name of the type of internal rep an
	object has.

1999-06-04  Scott Stanton  <stanton@scriptics.com>

	* win/configure.in:
	* win/Makefile.in: Windows build now handles static/dynamic
	debug/nodebug builds and supports the standard targets using Cygwin
	user tools plus GNU make and autoconf.

1999-06-03  Scott Stanton  <stanton@scriptics.com>

	* generic/tclCmdMZ.c (Tcl_StringObjCmd):
	* tests/string.test: Fixed bug where string equal/compare -nocase
	reported wrong result on null strings. [Bug 2138]

1999-06-02  Scott Stanton  <stanton@scriptics.com>

	* generic/tclUtf.c (Tcl_UtfNcasecmp): Fixed incorrect computation of
	relative ordering. [Bug 2135]

1999-06-01  Scott Stanton  <stanton@scriptics.com>

	* unix/configure.in: Fixed various small configure.in patches
	submitted by Jan Nijtmans. [Bug 2121]

	* tests/reg.test:
	* generic/regc_color.c:
	* generic/regc_cvec.c:
	* generic/regc_lex.c:
	* generic/regc_locale.c:
	* generic/regc_nfa.c:
	* generic/regcomp.c:
	* generic/regcustom.h:
	* generic/rege_dfa.c:
	* generic/regerror.c:
	* generic/regerrs.h:
	* generic/regex.h:
	* generic/regexec.c:
	* generic/regfree.c:
	* generic/regfronts.c:
	* generic/regguts.h:
	* generic/tclCmdMZ.c:
	* generic/tclRegexp.c:
	* generic/tclRegexp.h:
	* generic/tclTest.c: Applied Henry Spencer's latest regexp patches
	that fix an infinite loop bug and add support for testing whether a
	string could match with additional input. [Bug 2117]

1999-05-28  Scott Stanton  <stanton@scriptics.com>

	* generic/tclObj.c: Changed to eliminate use of isupper/tolower in
	favor of the Unicode versions.

	* win/Makefile.in:
	* win/configure.in: Added preliminary TEA implementation.

	* win/tclWinDde.c: Fixed bug where dde calls were being passed an
	invalid dde handle because Initialize had not been called. [Bug 2124]

1999-05-26  Scott Redman  <redman@scriptic.com>

	* generic/tclThreadTest.c: Fixed race condition in testthread code
	that showed up in the WinNT test suite intermittently.

	* win/tclWinSock.c: Fixed a hang in the WinNT socket driver, wake up
	the socket thread every 100ms to check for events on the sockets that
	did not wake up the thread (race condition).

1999-05-24  Scott Stanton  <stanton@scriptics.com>

	* tools/genStubs.tcl: Changed to allow a list of platforms instead of
	just one at a time.

	* generic/tcl.decls:
	* generic/tclCmdMZ.c:
	* generic/tclDecls.h:
	* generic/tclInt.decls:
	* generic/tclIntDecls.h:
	* generic/tclPort.h:
	* generic/tclStubInit.c:
	* generic/tclStubLib.c: Various header file related changes and other
	lint to try to get the Mac builds working.

1999-05-21  Scott Redman  <redman@scriptics.com>

	* win/tclWinPipe.c: Fix bug when launching command.com on Win95/98.
	Need to wait for the procInfo.hProcess of the process that was
	created, not the hProcess of the current process. [Bug 2105]

1999-05-20  Scott Redman  <redman@scriptics.com>

	* library/init.tcl: Add the directory where the executable is, and the
	../lib directory relative to that, to the auto_path variable.

1999-05-19  Scott Stanton  <stanton@scriptics.com>

	Merged in various changes submitted by Jeff Hobbs:

	* generic/tcl.decls:
	* generic/tclUtf.c: Added Tcl_UniCharIs* functions for control, graph,
	print, and punct classes.

	* generic/tclUtil.c:
	* doc/StrMatch.3: Added Tcl_StringCaseMatch() implementation to
	support case-insensitive globbing.

	* doc/string.n:
	* unix/mkLinks:
	* tests/string.test:
	* generic/tclCmdMZ.c: Added additional character class tests, added
	-nocase switch to "string match", changed string first/last to use
	offsets.

1999-05-19  Scott Redman  <redman@scriptics.com>

	* generic/tcl.h: Add extern "C" block around entire header file for
	C++ compilers to fix linkage issues. Submitted by Don Porter and Paul
	Duffin.

	* generic/tclRegexp.c: Fix bug when the regexp cache is empty and an
	empty pattern is used in regexp ( such as {} or "" ).

1999-05-18  Scott Stanton  <stanton@scriptics.com>

	* win/tclWinChan.c: Modified initialization code to avoid inherenting
	closed or invalid channels. If the standard input is anything other
	than a console, file, serial port, or pipe, then we fall back to the
	standard Tk window console.

1999-05-14  Scott Stanton  <stanton@scriptics.com>

	* generic/tclCmdAH.c (Tcl_ForObjCmd): Fixed crash caused by failure to
	reset the result before evaluating the test expression.

1999-05-14  Bryan Surles  <surles@scriptics.com>

	* generic/tclBasic.c (Tcl_CreateInterp): Added introspection variable
	for threaded interps. If the interp was compiled with threads enabled,
	the tcl_platform(threaded) variable will exist.

1999-05-14  Scott Redman  <redman@scriptics.com>

	* generic/tclDate.c: Applied patch to fix 100-year and 400-year
	boundaries in leap year code, from Isaac Hollander. [Bug 2066]

1999-05-13  Scott Stanton  <stanton@scriptics.com>

	* unix/Makefile.in:
	* unix/tclAppInit.c: Minor cleanup related to Xt notifier.

	* unix/tclUnixInit.c (TclpSetInitialEncodings): Tcl now looks for an
	encoding subfield in the LANG/LC_ALL variables in cases where the
	locale is not found in the locale table. Ensure that setlocale() is
	called at least once so X11 will initialize properly. Also, forces the
	LC_NUMERIC locale to be "C" so numeric processing in scripts is not
	affected by the current locale setting. [Bug 1989]

	* generic/tclRegexp.c: Increased per-thread regexp cache to 30 slots.
	This seems to be about the right number for larger applications like
	exmh. [Bug 1063]

1999-05-12  Scott Stanton  <stanton@scriptics.com>

	* doc/tclsh.1: Updated references to rc script names to accurately
	reflect the platform differences on Windows.

	* tests/regexp.test:
	* generic/tclInt.h:
	* generic/tclBasic.c:
	* generic/tclRegexp.h:
	* generic/tclRegexp.c: Replaced the per-interpreter regexp cache with
	a per-thread cache. Changed the Regexp object to take advantage of
	this extra cache. Added a reference count to the TclRegexp type so
	regexps can be shared by multiple objects. Removed the per-interp
	regexp cache from the interpreter. Now regexps can be used with no
	need for an interpreter. [Bug 1063]

	* win/tclWinInit.c (TclpSetVariables): Avoid calling GetUserName if
	the value can be determined from the USERNAME environment variable.
	GetUserName is very slow.

1999-05-07  Scott Stanton  <stanton@scriptics.com>

	* win/winDumpExts.c:
	* win/makefile.vc: Removed incorrect patch. [Bug 1998]

	* generic/tcl.decls: Replaced const with CONST.

	* generic/tclResult.c (Tcl_AppendResultVA):
	* generic/tclStringObj.c (Tcl_AppendStringsToObjVA): Fixed to copy
	arglist using memcpy instead of assignment so it works properly on
	OS/390. [Bug 1997]

	* generic/tclLoadNone.c: Updated to use current interfaces, added
	TclpUnloadFile. [Bug 2003]

	* win/winDumpExts.c:
	* win/makefile.vc: Changed to emit library name in defs file. [Bug
	1998]

	* unix/configure.in: Added fix for OS/390. [Bug 1976]

1999-05-06  Scott Stanton  <stanton@scriptics.com>

	* tests/string.test:
	* generic/tclCmdMZ.c:
	* doc/string.n: Fixed bug in string equal/compare code when using
	-length option. Cleaned up docs a bit more.

	* tests/http.test: Unset "data" array before running tests to avoid
	failures due to previous tests.

	* doc/string.n:
	* tests/cmdIL.test:
	* tests/cmdMZ.test:
	* tests/error.test:
	* tests/ioCmd.test:
	* tests/lindex.test:
	* tests/linsert.test:
	* tests/lrange.test:
	* tests/lreplace.test:
	* tests/string.test:
	* tests/cmdIL.test:
	* generic/tclUtil.c:
	* generic/tclCmdMZ.c: Replaced "string icompare/iequal" with -nocase
	and -length switches to "string compare/equal". Added a -nocase option
	to "string map". Changed index syntax to allow integer or
	end?-integer? instead of a full expression. This is much simpler with
	safeTcl scripts since it avoids double substitution issues.

	* doc/Utf.3:
	* generic/tclStubInit.c:
	* generic/tclDecls.h:
	* generic/tclUtf.c:
	* generic/tcl.decls: Added Tcl_UtfNcmp and Tcl_UtfNcasecmp.

1999-05-05  Scott Stanton  <stanton@scriptics.com>

	* win/makefile.vc: Added encoding directory to install-libraries
	target.

1999-05-03  Scott Stanton  <stanton@scriptics.com>

	* doc/string.n:
	* tests/cmdMZ.test:
	* tests/string.test:
	* generic/tclCmdMZ.c (Tcl_StringObjCmd): Changed "string length" to
	avoid regenerating the string rep of a ByteArray object.

	* tests/cmdIL.test:
	* tests/cmdMZ.test:
	* tests/error.test:
	* tests/lindex.test:
	* tests/linsert.test:
	* tests/lrange.test:
	* tests/lreplace.test:
	* tests/string.test:
	* generic/tclCmdMZ.c (Tcl_StringObjCmd):
	* generic/tclUtil.c (TclGetIntForIndex): Applied Jeff Hobbs's string
	patch which includes the following changes [Bug 1845]:
	- string compare now takes optional length arg (for strncmp behavior)
	- added string equal (just a few lines of code blended in with string
	  compare)
	- added string icompare/iequal for case-insensitive comparisons
	- string index's index can now be ?end[+-]?expression
	  I made this change in the private TclGetIntForIndex, which means
	  that the list commands also benefit, as well as string range, et al.
	- added [string repeat string count]
	  Repeats given string number of times
	- added string replace, string equiv to lreplace
	  (quasi opposite of string range):
		string replace first last ?string?
	  Example of use, replacing end of string with ... should the string
	  be more than 16 chars long:
		string replace $string 16 end "..."
	  This just returns the string len < 16, so it will only affect the
	  long strings.
	- added optional first and last args to string to*
	  This allows you to just affect certain regions of a string with the
	  command (like just capping the first letter). I found the original
	  totitle to be too draconian to be useful.
	- added [string map charMap string]
	  where charMap is a {from to from to} list that equates to what one
	  might get from [array get]. Each and can be multiple chars (or none
	  at all). For Tcl/CGI users, this is a MAJOR speed booster.

	* generic/tclParse.c (Tcl_ParseCommand): Changed to avoid modifying
	eval'ed strings that are already null terminated. [Bug 1793]

	* tests/binary.test:
	* generic/tclBinary.c (DupByteArrayInternalRep): Fixed bug where type
	was not being set in duplicated object. [Bug 1975, 2047]

1999-04-30  Scott Stanton  <stanton@scriptics.com>

	* Changed version to 8.1.1.

1999-04-30  Scott Stanton  <stanton@scriptics.com>

	* Merged changes from 8.1.0 branch:

	* generic/tclParse.c: Fixed memory leak in CommandComplete.

	* generic/tclPlatDecls.h:
	* generic/tclIntPlatDecls.h:
	* generic/tclIntDecls.h:
	* generic/tclDecls.h:
	* tools/genStubs.tcl: Added 'extern "C" {}' block around the stub
	table pointer declaration so the stub library can be used from C++.
	[Bug 1934]

	* Lots of documentation and other release engineering fixes.

1999-04-28  Scott Stanton  <stanton@scriptics.com>

	* mac/tclMacResource.c:
	* generic/tclListObj.c:
	* generic/tclObj.c:
	* generic/tclStringObj.c: Changed to avoid freeing the string
	representation before freeing the internal rep. This helps with
	debugging since the string rep will still be valid when the free proc
	is invoked.

1999-04-27  Scott Stanton  <stanton@scriptics.com>

	* generic/tclLiteral.c (TclHideLiteral): Fixed so hidden literals get
	duplicated to avoid accidental sharing in the global object table.

1999-04-23  Scott Stanton  <stanton@scriptics.com>

	* generic/tclStubInit.c:
	* tools/genStubs.tcl: Changed to avoid the need for forward
	declarations in stub initializers.

1999-04-23  Scott Stanton  <stanton@scriptics.com>

	* library/encoding/koi8-r.enc:
	* tools/encoding/koi8-r.txt: Added support for the koi8-r Cyrillic
	encoding. [Bug 1771]

1999-04-22  Scott Stanton  <stanton@scriptics.com>

	* win/tclWinFCmd.c:
	* win/tclWin32Dll.c: Changed uses of "try" to "__try", since that is
	the actual keyword. This eliminates the need for some -D flags from
	the makefile.

	* generic/tclPort.h: Added include of tcl.h since it defines various
	Windows macros that are needed before deciding which platform porting
	file to use.

	* generic/tclEvent.c: lint

	* win/tclWinInit.c (TclpInitPlatform): Added call to TclWinInit when
	building a static library since DllMain will not be invoked. This
	could break old code that explicitly called TclWinInit, but should be
	simpler in the long run.

1999-04-22  Scott Stanton  <stanton@scriptics.com>

	* generic/tclInt.h:
	* generic/tclInt.decls:
	* generic/tclCompile.c: Added TclSetByteCodeFromAny that takes a hook
	procedure to invoke after compilation but before the byte codes are
	emitted. This makes it possible to do postprocessing on the compiled
	byte codes before the ByteCode is generated.

	* generic/tclLiteral.c: Added TclHideLiteral and TclAddLiteralObj to
	make it possible to create local unshared literal objects.

	* win/tclWinInit.c:
	* unix/tclUnixInit.c: Changed initial search path to match that
	found used by tcl_findLibrary.

1999-04-22  Scott Redman  <redman@scriptics.com>

	* win/tclWinPort.h:
	* win/tclWinSock.c: Added code to use WinSock 2.0 API on NT to avoid
	creating a window to handle sockets. API not available on Win95 and
	needs to be fixed on Win98, until then continue to use the older
	(window-based) scheme on those two OSes.

1999-04-15  Scott Stanton  <stanton@scriptics.com>

	* Merged 8.1 back into the main trunk

1999-04-13  Scott Stanton  <stanton@scriptics.com>

	* library/encoding/gb2312.enc:
	* library/encoding/euc-cn.enc:
	* tools/encoding/gb2312.txt:
	* tools/encoding/cp950.txt:
	* tools/encoding/Makefile: Restored the double byte definition of
	GB2312 and added the EUC-CN encoding. EUC-CN is a variant of GB2312
	that shifts the characters into bytes with the high bit set and
	includes ASCII as a subset. [Bug 632]

1999-04-13  Scott Redman  <redman@scriptics.com>

	* win/tclWinSock.c: Apply patch to allow write access to a socket if
	FD_WRITE is sent but FD_CONNECT is not. Some strange problem with
	either Win32 or a socket driver. [Bug 1664 1776]

1999-04-09  Scott Redman  <redman@scriptics.com>

	* unix/tclUnixNotfy.c: Fixed notifier deadlock situation when the pipe
	used to talk back notifier thread is filled with data. When calling
	the write() function to feed data down that pipe, unlock the
	notifierMutex to allow the notifier to wake up again. Found as a
	result of the focus.test for Tk hanging. [Bug 1700]

1999-04-06  Scott Stanton  <stanton@scriptics.com>

	* tests/unixNotfy.test: Fixed hang in tests when built with thread
	support.

	* tests/httpold.test: Fixed broken test that didn't wait long enough
	for events to arrive.

	* tests/unixInit.test: Fixed race condition in test.

	* tests/unixInit.test:
	* tests/fileName.test: Minor test nits.

	* unix/tclUnixInit.c (TclpSetInitialEncodings): Fixed bad initial
	encoding string.

1999-04-06  Bryan Surles  <surles@scriptics.com>

	* generic/tclVar.c:
	* generic/tclEnv.c: Moved the "array set" C level code into a common
	routine (TclArraySet). The TclSetupEnv routine now uses this API to
	create an env array w/ no elements.

	* generic/tclEnv.c:
	* generic/tclWinInit.h:
	* generic/tclUnixInit.h:
	* generic/tclInt.h: Made the Env module I18N compliant. Changed the
	FindVariable routine to TclpFindVariable, that now does a case
	insensitive string comparison on Windows, and not on UNIX. [Bug 1299,
	1500]

1999-04-05  Scott Stanton  <stanton@scriptics.com>

	* tests/io.test: Minor test cleanup.

	* generic/tclEncoding.c (Tcl_CreateEncoding): Minor lint to make it
	easier to compile on Digital-unix. [Bug 1659]

	* unix/configure.in:
	* unix/tclUnixPort.h: Applied patch for OS/390 to handle lack of
	sys/param.h. [Bug 1725]

	* unix/configure.in: Fixed BSD/OS 4.* configuration to support shared
	libraries properly. [Bug 1730]

1999-04-05  Scott Redman  <redman@scriptics.com>

	* win/tclWinDde.c: decrease timeout value for DDE calls to 30k. [Bug
	1639]

	* generic/tcl.decls:
	* generic/tcl.h:
	* generic/tclDecls.h:
	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclIntDecls.h:
	* generic/tclStubInit.c:
	* generic/tclUtil.c: Added more functions to the Tcl stubs table,
	including all Tcl_ functions not already in it (except Cmd functions)
	and Tcl_GetCwd() and Tcl_Chdir() (new functions).

	* tests/safe.test:
	* doc/safe.n:
	* generic/tclBasic.c:
	* library/safe.tcl: The encoding command is not safe as-is, so create
	a safe alias to mask out the "encoding system <name>" but allow all
	other uses including "encoding system". Added test cases and updated
	the man page for Safe Tcl.

1999-04-05  Scott Stanton  <stanton@scriptics.com>

	* tests/winTime.test:
	* win/tclWinTime.c: Fixed crash in clock command that occurred when
	manipulating negative time values in timezones east of GMT. [Bug
	1142, 1458]

	* tests/platform.test:
	* tests/fileName.test: Fixed broken tests.

	* generic/tclFileName.c: Moved global regexps into thread local
	storage.

	* tests/socket.test: Changed so tests don't reuse sockets, since
	Windows is slow to release sockets.

	* win/tclWinConsole.c:
	* win/tclWinPipe.c:
	* win/tclWinSerial.c: Fixed race condition where background threads
	were terminated while they still held a lock in the notifier.

1999-04-02  Scott Stanton  <stanton@scriptics.com>

	* tests/http.test: Fixed bad test initialization code.

	* generic/tclThreadTest.c (ThreadExitProc): Fixed bug where static
	memory was being returned instead of a dynamically allocated result in
	error cases.

1999-04-02  Scott Redman  <redman@scriptics.com>

	* doc/dde.n:
	* tools/tcl.wse.in:
	* win/makefile.vc:
	* win/pkgIndex.tcl:
	* win/tclWinDde.c: Add new DDE package, code removed from Tk now
	separated into its own package. Changed DDE-based send code into "dde
	eval" command. Can be loaded into tclsh (not just wish). Windows only.

1999-04-02  Scott Stanton  <stanton@scriptics.com>

	* tests/expr.test:
	* tests/for-old.test:
	* tests/for.test:
	* tests/foreach.test:
	* tests/format.test:
	* tests/httpold.test:
	* tests/if.test:
	* tests/init.test:
	* tests/interp.test:
	* tests/while.test: Added some tests for known bugs (marked with
	knownBug constraint), and cleaned up a few bad tests.

	* generic/regc_locale.c:
	* generic/regcustom.h:
	* generic/tcl.decls:
	* generic/tclCmdIL.c:
	* generic/tclCmdMZ.c:
	* generic/tclInt.h:
	* generic/tclRegexp.c:
	* generic/tclScan.c:
	* generic/tclTest.c:
	* generic/tclUtf.c:
	* win/tclWinFCmd.c:
	* win/tclWinFile.c: Made various Unicode utility functions public. The
	following functions were made public and added to the stubs table:
		Tcl_UtfToUniCharDString, Tcl_UniCharToUtfDString,
		Tcl_UniCharLen, Tcl_UniCharNcmp, Tcl_UniCharIsAlnum,
		Tcl_UniCharIsAlpha, Tcl_UniCharIsDigit, Tcl_UniCharIsLower,
		Tcl_UniCharIsSpace, Tcl_UniCharIsUpper, Tcl_UniCharIsWordChar

1999-04-01  Scott Stanton  <stanton@scriptics.com>

	* tests/registry.test:
	* win/tclWinReg.c: Internationalized the registry code. It now uses
	Unicode interfaces on NT. [Bug 1197]

	* tests/parse.test:
	* generic/tclParse.c: Fixed crash due to multiple frees in parser
	during error cleanup when parsing commands with more tokens than will
	fit in the static area of the parse structure. [Bug 1681]

	* generic/tclInt.h: Removed duplicate declarations.

	* generic/tclInt.decls:
	* generic/tcl.decls: Added Tcl_WinUtfToTChar and Tcl_WinTCharToUtf to
	the tclPlat table.

1999-04-01  Scott Redman  <redman@scriptics.com>

	* generic/tcl.decls:
	* generic/tcl.h:
	* generic/tclBasic.c:
	* generic/tclDecls.h:
	* generic/StubInit.c:
	* tools/genStubs.tcl:
	* unix/Makefile.in:
	* win/makefile.vc: Applied patch from Jan Nijtmans to fix Ultrix
	multiple symbol definition problem. Now, even Tcl includes a copy of
	the Tcl stub library. Also fixed TCL_MEM_DEBUG mode (for Tk).

1999-03-31  Scott Redman  <redman@scriptics.com>

	* win/tclWinConsole.c: WinNT has a bug when reading a single character
	from the console. Rewrote the code for the console to read an entire
	line at a time using the reader thread.

1999-03-30  Scott Stanton  <stanton@scriptics.com>

	* unix/Makefile.in: Removed trailing backslash that broke the "depend"
	target.

	* unix/tclUnixInit.c (TclpSetInitialEncodings): Changed to avoid
	calling setlocale(). We now look directly at env(LANG) and
	env(LC_CTYPE) instead. [Bug 1636]

	* generic/tclFileName.c:
	* generic/tclDecls.h:
	* generic/tcl.decls: Removed CONST from Tcl_JoinPath and
	Tcl_TranslateFileName because it changes the signature of Tcl_JoinPath
	in an incompatible manner.

	* generic/tclInt.h:
	* generic/tclLoad.c (TclFinalizeLoad):
	* generic/tclEvent.c (Tcl_Finalize): Defer unloading of loadable
	modules until all exit handlers have been invoked. [Bug 998, 1273,
	1573, 1593]

1999-03-29  Scott Stanton  <stanton@scriptics.com>

	* generic/tclFileName.c:
	* generic/tclDecls.h:
	* generic/tcl.decls: Added CONST to Tcl_JoinPath and
	Tcl_TranslateFileName.

1999-03-29  Scott Redman  <redman@scriptics.com>

	* tools/genStubs.tcl:
	* unix/configure.in:
	* unix/Makefile.in:
	* win/makefile.vc:
	* generic/tcl.h:
	* generic/tclBasic.c:
	* generic/tclDecls.h:
	* generic/tclIntDecls.h:
	* generic/tclPlatDecls.h:
	* generic/tclIntPlatDecls.h: Removed the stub functions and changed
	the stub macros to just use the name without params. Pass &tclStubs
	into the interp (don't use tclStubsPtr because of collisions with the
	stubs on Solaris).

1999-03-27  Scott Redman  <redman@scriptics.com>

	* win/makefile.bc: Removed makefile for Borland compiler, no longer
	supported.

1999-03-26  Scott Redman  <redman@scriptics.com>

	* win/tclWinSerial.c:
	* win/tclWinConsole.c:
	* win/tclWinPipe.c: Don't close the Win32 handle for a channel if it's
	a stdio handle (GetStdHandle()) during shutdown of a thread to prevent
	it from destroying the stdio of other threads.

1999-03-26  Suresh Ankolekar  <suresh@scriptics.com>

	* unix/configure.in: --nameble-shared is now the default and build Tcl
	as a shared library; specify --disable-shared to build a static Tcl
	library and shell.

1999-03-25  Scott Stanton  <stanton@scriptics.com>

	* tests/interp.test:
	* generic/tclInterp.c (AliasObjCmd): Changed so aliases are invoked at
	current scope in the target interpreter instead of at the global
	scope. This was an incompatibility introduced in 8.1 that is being
	removed. [Bug 1153, 1556]

	* library/encoding/big5.enc:
	* library/encoding/gb2312.enc:
	* tools/encoding/big5.enc:
	* tools/encoding/gb2312.enc: Added ASCII to big5 and gb2312 encodings.
	[Bug 632]

	* generic/tclPkg.c (Tcl_PkgRequireEx): Fixed broken clientData
	initialization in package code.

	* unix/Makefile.in (dist): Added tcl.decls and tclInt.decls to source
	distribution. [Bug 1571]

	* doc/Thread.3: Updated documentation of Tcl_MutexLock to indicate
	that the recursive locking behavior is undefined. On Windows, it does
	not block, on Unix it deadlocks. [Bug 1275]

1999-03-24  Scott Stanton  <stanton@scriptics.com>

	* tests/execute.test:
	* generic/tclExecute.c (TclExecuteByteCode): Fixed expression code
	that incorrectly returned floating point values for integers if the
	internal rep happened to be a double. Now we check to see if the
	object has a string rep that looks like an integer before using the
	double internal rep. [Bug 1516]

1999-03-24  Scott Redman  <redman@scriptics.com>

	* generic/tclAlloc.c:
	* generic/tclEncoding.c:
	* generic/tclProc.c:
	* unix/tclUnixTime.c:
	* win/tclWinSerial.c: Fixed compilation warnings/errors for VC++ 5.0
	and 6.0 and HP-UX native compiler without -Aa or -Ae. [Bug 1323 1518
	1324 1583 1585 1586]

	* win/tclWinSock.c: Make sockets thread-safe on Windows. The current
	implementation uses windows to handle events on the socket, one for
	each thread (thread local storage). Previously, there was only one
	window shared between threads, which didn't work. [Bug 1326]

1999-03-23  Scott Stanton  <stanton@scriptics.com>

	* tools/tcl.wse: Fixed file association to look in the right place for
	the wish icon. [Bug 1544]

	* tests/winNotify.test:
	* tests/ioCmd.test:
	* tests/event.test: Changed to use new style conditionals.

	* tests/encoding.test: Fixed nonportable test.

	* unix/dltest/configure.in:
	* unix/dltest/Makefile.in: Added missing DBGX macros. [Bug 1564]

	* tests/winNotify.test:
	* mac/tclMacNotify.c:
	* win/tclWinNotify.c:
	* unix/tclUnixNotfy.c:
	* generic/tclNotify.c: Added a new Tcl_ServiceModeHook interface that
	is invoked whenever the service mode changes. This is needed to allow
	the Windows notifier to create a communication window the first time
	Tcl is about to enter an external modal event loop instead of at
	startup time. This will avoid the various problems that people have
	been seeing where the system hangs when tclsh is running outside of
	the event loop. [Bug 783]

	* generic/tclInt.h:
	* generic/tcl.decls: Renamed TclpAlertNotifier back to
	Tcl_AlertNotifier since it is part of the public notifier driver API.

1999-03-23  Scott Redman  <redman@scriptics.com>

	* win/tclWinSerial.c: Fixed problem with fileevent on the serial port
	and nonblocking mode. Gets no longer hangs, fileevents fire whenever
	there is any character data on the port.

	* tests/winConsole.test:
	* win/tclWinConsole.c: Fixed problem with fileevents and gets from a
	console stdin. Previously, fileevents were firing before an entire
	line was available for reading, which meant that when you did a gets
	or read, it blocked (even in nonblocking mode). Now, it should work
	the same as Unix: fileevents fire when an entire line is ready, and
	gets and read do not block in non-blocking mode. Added an interactive
	test case to check for this.

1999-03-22  Scott Stanton  <stanton@scriptics.com>

	* tests/reg.test:
	* generic/regc_color.c: Applied regexp bug fix from Henry Spencer.

1999-03-19  Scott Redman  <redman@scriptics.com>

	* generic/tclCmdIL.c: Fixed the initialization of an array so that the
	Sun 5.0 C compiler wouldn't complain.

	* unix/configure.in: Added support for --enable-64bit. For now, this
	is only supported on Solaris 7 64bit (SunOS 5.7) using the Sun
	compiler (not gcc).

1999-03-18  Scott Stanton  <stanton@scriptics.com>

	* win/tclWinChan.c (TclpOpenFileChannel, Tcl_MakeFileChannel): Changed
	to only test for console or comm handles when the type is
	FILE_TYPE_CHAR to avoid useless tests on simple files. Also reordered
	tests so consoles are tested first as this is more common.

	* win/makefile.vc: Regularized usage of mkd and rmd and rm.

	* library/encoding/shiftjis.enc:
	* tools/encoding/shiftjis.txt: Missing/incorrect characters in
	shift-jis table. [Bug 1008, 1526]

	* generic/tclInt.decls:
	* generic/tcl.decls: Eliminated use of "string" and "list" from
	argument lists to avoid conflicts with C++ STL. [Bug 1181]

	* win/tclWinFile.c (TclpMatchFiles): Changed to ignore the
	FS_CASE_IS_PRESERVED bit and always return exactly what we get from
	the system.

1999-03-17  Scott Stanton  <stanton@GASPODE>

	* win/README.binary:
	* win/README:
	* unix/configure.in:
	* generic/tcl.h:
	* README: Updated version to 8.1b3.

1999-03-14  Scott Stanton  <stanton@GASPODE>

	* win/tclWinConsole.c:
	* win/tclWinPipe.c:
	* win/tclWinSerial.c: Changed so channel drivers wait for the
	reader/writer threads to exit before returning during a close
	operation. This ensures that the main thread is the last thread to
	exit, so the process return value is set properly.

	* generic/tclIntDecls.h:
	* generic/tclIntPlatDecls.h:
	* generic/tclIntPlatStubs.c:
	* generic/tclIntStubs.c:
	* generic/tclPlatDecls.h:
	* generic/tclPlatStubs.c:
	* generic/tclStubInit.c:
	* generic/tclStubs.c: Fixed bad eol characters.

	* generic/tclInt.decls: Changed "const" to "CONST" in declarations for
	better portability.

	* generic/tcl.decls: Renamed panic and panicVA to Tcl_Panic and
	Tcl_PanicVA in the stub files.

	* generic/tclInterp.c (Tcl_MakeSafe): Remove tcl_platform(user) from
	safe interps.

1999-03-11  Scott Stanton  <stanton@GASPODE>

	* unix/Makefile.in:
	* unix/configure.in: Include compat files in the stub library in
	addition to the main library. Compat files are now built for dynamic
	use in all cases.

	* generic/tcl.h: Changed magic number so it doesn't match the plus
	patch, at Jan's request.

	* unix/tclConfig.sh.in:
	* unix/dltest/Makefile.in:
	* unix/dltest/configure.in:
	* unix/dltest/pkga.c:
	* unix/dltest/pkgb.c:
	* unix/dltest/pkgc.c:
	* unix/dltest/pkgd.c:
	* unix/dltest/pkge.c:
	* unix/dltest/pkgf.c: Changed package tests to build against the stubs
	library.

1999-03-10  Scott Stanton  <stanton@GASPODE>

	* generic/tcl.h:
	* generic/tcl.decls: Changed Tcl_ReleaseType from an enum to macros so
	it can be used in .rc files. Added Tcl_GetString.

	* mac/tclMacNotify.c:
	* generic/tclNotify.c:
	* generic/tclInt.h:
	* win/tclWinNotify.c:
	* generic/tcl.h: Renamed Tcl_AlertNotifier to TclpAlertNotifier.

	* generic/tclInt.decls: Added TclWinAddProcess to make it possible for
	expect to use Tcl_WaitForPid(). This patch is from Gordon Chaffee.

	* mac/tclMacPort.h:
	* win/tclWinInit.c:
	* unix/tclUnixPort.h:
	* generic/tclAsync.c: Added TclpAsyncMark to fix bug in async handling
	on Windows where async events don't wake up the event loop. This patch
	comes from Gordon Chaffee.

	* generic/tcl.decls: Fixed declarations of reserved slots.

1999-03-10  Scott Redman  <redman@scriptic.com>

	* generic/tclCompile.h: Ensure that the ByteCode struct is binary
	compatible with the version in 8.0.6.

	* generic/tcl.h:
	* generic/tclBasic.c: Add Tcl_GetVersion() function to the public C
	API to allow programs to check the version number of the Tcl library
	at runtime. Also added an enum to clarify the release level (alpha,
	beta, final).

1999-03-09  Scott Stanton  <stanton@GASPODE>

	* Integrated changes from Tcl 8.0 including:
		stubs mechanism
		configure patches from Jan Nijtmans
		rename of panic to Tcl_Panic

1999-03-08  Lee Bernhard  <lfb@scriptics.com>

	* win/tclWin32Dll.c: Removed Dll instance from thread-local storage.

1999-03-08  Scott Stanton  <stanton@GASPODE>

	* generic/tcl.h: Moved Tcl_Mutex, etc. macros above the inclusion of
	tclDecls.h to avoid macro conflicts.

	* generic/tclInt.h:
	* generic/regc_color.c:
	* generic/regcomp.c:
	* generic/tclCmdIL.c:
	* generic/tclCmdAH.c:
	* generic/tclIOCmd.c:
	* generic/tclParse.c:
	* generic/tclStringObj.c:
	* unix/tclUnixNotfy.c: Cleaned up various compiler warnings,
	eliminated UCHAR bugs.

	* unix/tclUnixNotfy.c:
	* unix/tclUnixThrd.c:
	* generic/tclThreadTest.c:
	* mac/tclMacThrd.c: Changed TclpCondition*() to Tcl_Condition*().

	* INTEGRATED PATCHES FROM 8.0.6:

	* generic/tcl.decls:
	* generic/tcl.h:
	* generic/tclBasic.c:
	* generic/tclDecls.h:
	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclIntDecls.h:
	* generic/tclIntPlatDecls.h:
	* generic/tclIntPlatStubs.c:
	* generic/tclIntStubs.c:
	* generic/tclPlatDecls.h:
	* generic/tclPlatStubs.c:
	* generic/tclStubInit.c:
	* generic/tclStubLib.c:
	* generic/tclStubs.c:
	* tools/genStubs.tcl:
	* unix/configure.in:
	* unix/Makefile.in:
	* unix/tclConfig.sh.in:
	* win/makefile.vc:
	* win/tclWinPort.h: Added Tcl stubs implementation. There are now two
	new macros USE_TCL_STUBS and USE_TCL_STUB_PROCS that enable use of
	stubs and disable stub macros respectively. All of the public and
	private function declarations from tcl.h and tclInt.h have moved into
	the *.decls files and the *Stubs.c and *Decls.h files are generated
	using the genStubs.tcl script.

	* unix/Makefile.in:
	* unix/configure.in:
	* unix/ldAix: Enhanced AIX shared library support.

	* win/tclWinSock.c: Removed a bunch of extraneous PASCAL FAR
	attributes from internal functions.

	* win/tclWinReg.c: Changed registry package to use stubs mechanism so
	it no longer depends on the specific version of Tcl.

	* doc/AddErrInfo.3:
	* doc/Eval.3:
	* doc/PkgRequire.3:
	* doc/SetResult.3:
	* doc/StringObj.3:
	* generic/tcl.h:
	* generic/tclBasic.c:
	* generic/tclPanic.c:
	* generic/tclStringObj.c:
	* generic/tclUtil.c:
	* unix/mkLinks: Added va_list versions of all VARARGS functions so
	they can be invoked from the stub functions.

	* doc/package.n:
	* doc/PkgRequire.3:
	* generic/tclPkg.c: Added Tcl_PkgProvideEx, Tcl_RequireEx,
	Tcl_PresentEx, and Tcl_PkgPresent. Added "package present" command.

	* generic/tclFileName.c:
	* mac/tclMacFile.c:
	* mac/tclMacShLib.exp:
	* unix/tclUnixFile.c:
	* win/tclWinFile.c: Changed so TclGetUserHome is defined on all
	platforms, even though it is currently a noop on mac and windows, and
	renamed it to TclpGetUserHome.

	* generic/tclPanic.c:
	* generic/panic.c: Renamed panic to Tcl_Panic.

1999-02-25  Scott Redman  <redman@scriptics.com>

	* win/makefile.vc: Added tclWinConsole.c and tclWinSerial.c

	* win/tclWinConsole.c: New code to properly deal with fileevents and
	nonblocking mode on consoles.

	* win/tclWinSerial.c: New code to properly deal with fileevents and
	nonblocking mode on serial ports.

	* win/tclWinPipe.c:
	* win/tclWinPort.h: Exported functions to allow creation of pipe
	channels from tclWinChan.c

	* win/tclWinChan.c: Check the type of a channel, including for the
	standard (stdin/stdout/stderr), and use the correct channel type to
	create the channel (file, serial, console, or pipe).

1999-02-11  Scott Stanton  <stanton@GASPODE>

	* README:
	* generic/tcl.h:
	* win/README.binary:
	* win/README:
	* unix/configure.in:
	* mac/README: Updated version numbers to 8.1b2.

1999-02-10  Scott Stanton  <stanton@GASPODE>

	* library/auto.tcl: Fixed auto_mkindex so it handles .tbc files. Did
	some general cleanup to handle bad eval statements that didn't use
	"list".

	* unix/mkLinks:
	* doc/SetVar.3:
	* generic/tcl.h:
	* generic/tclVar.c: Restored Tcl_ObjGetVar2 and Tcl_ObjSetVar2 from
	8.0. Renamed Tcl_Get/SetObjVar2 to Tcl_GetVar2Ex and Tcl_SetVar2Ex.

1999-02-10  Scott Stanton  <stanton@GASPODE>

	INTEGRATED PATCHES FROM 8.0.5b2:

	* test/winPipe.test: Changed to remove echoArgs.tcl temporary file
	when done.

	* tests/cmdAH.test:
	* generic/tclFileName.c (TclGetExtension): Changed behavior so the
	split happens at the last period in the name instead of the first
	period of the last run of periods. So, "foo..o" is split into "foo."
	and ".o" now. [Bug 1126]

	* win/makefile.vc: Added better support for paths with spaces in the
	name. Added .lib and support .dlls to the install-binaries target.
	Added generate of a pkgIndex.tcl script to the install-libraries
	target.

	* win/tclAppInit.c:
	* unix/tclAppInit.c:
	* mac/tclMacAppInit.c:
	* generic/tclTest.c: Changed some EXTERN declarations to extern since
	they are not defining exported interfaces. This avoids generating
	useless declspec() attributes and makes the windows makefile simpler.

	* generic/tcl.h: Moved Tcl_AppInit declaration to end and cleared out
	TCL_STORAGE_CLASS so it is not declared with a declspec().

	* tests/interp.test:
	* generic/tclInterp.c (DeleteAlias): Changed to use
	Tcl_DeleteCommandFromToken so we handle renames properly. This avoids
	senseless panic. [Bug 736]

	* unix/tclUnixChan.c:
	* win/tclWinSock.c:
	* doc/socket.n: Applied Gordon Chaffee's patch to handle failures
	during asynchronous socket connection operations. This adds a new
	"-error" fconfgure option to socket channels. [Bug 893]

	* generic/tclProc.c:
	* generic/tclNamesp.c:
	* generic/tclInt.h:
	* generic/tclCmdIL.c:
	* generic/tclBasic.c:
	* generic/tclVar.c: Applied patch from Viktor Dukhovni to rationalize
	TCL_LEAVE_ERR_MSG behavior when creating variables.

	* generic/tclVar.c: Fixed bug in namespace tail computation. Fixed bug
	where upvar could resurrect a namespace variable whose namespace had
	been deleted.

	* generic/tclCompile.c (TclCompileExprCmd): Eliminated yet another
	bogus optimization in expression compilation.

	* unix/configure.in: Added branch for BSD/OS-4* to shared library case
	statement. [Bug 975]
	Fixed to correctly handle IRIX 6.5 n32 library support. [Bug 1117]

	* win/winDumpExts.c: Patched to be pickier about stripping @'s. [Bug
	920]

	* library/http2.0/http.tcl: Added catch around eof test in CopyDone
	since the user may have already called http::reset. [Bug 1108]

	* unix/configure.in: Changed Linux and IRIX to set SHLIB_LIBS to LIBS
	so shared libraries are linked with the system libraries. [Bug 1018]

	* generic/tclCompile.c (CompileExprWord): Fixed exception stack
	overflow bug caused by missing statement. [Bug 928]

	* generic/tclIOCmd.c:
	* generic/tclBasic.c: Objectified the "open" command. [Bug 1113]

	* generic/tclPosixStr.c (Tcl_ErrnoId, Tcl_ErrnoMsg): When using egcs,
	ENOTSUP and EOPNOTSUPP are the same, so now we handle that case. [Bug
	1137]

	* library/init.tcl: Various small changes requested by Jan Nijtmans.
	- If the variable $tcl_library contains the empty string, this empty
	  string will be put in $auto_path. This is not useful at all, it only
	  slows down later package processing.
	- If the variable tcl_pkgPath is not set, the "unset __dir" fails.
	  Thich makes init.tcl totally unusable. Better put a "catch" around
	  it.
	- In the function tcl_findLibraries, the "string match" function only
	  works correctly if $tcl_patchLevel is in one of the forms "?.?a?",
	  "?.?b?" or "?.?.?". Could a "regexp" be used instead, then it allows
	  anything to be appended to the patchLevel string. And it is more
	  efficient.
	- The tclPkgSetup function assumes that if $type != "load" then the
	  type must be "source". This needn't be true. Some users want to add
	  their own setup types.
	[RFE 1138] [Bug 978]

	* win/tclWinReg.c:
	* doc/registry.n: Added support for HKEY_PERFORMANCE_DATA and
	HKEY_DYN_DATA keys. [Bug 1109]

	* win/tclWinInit.c (TclPlatformInit): Added code to ensure tcl_pkgPath
	is set to "" when no registry entry is found. [Bug 978]

1999-02-01  Scott Stanton  <stanton@GASPODE>

	* generic/tclBasic.c:
	* generic/tclCmdAH.c:
	* generic/tclCmdIL.c:
	* generic/tclCmdMZ.c:
	* generic/tclExecute.c:
	* generic/tclHistory.c:
	* generic/tclIO.c:
	* generic/tclIOUtil.c:
	* generic/tclInterp.c:
	* generic/tclMain.c:
	* generic/tclNamesp.c:
	* generic/tclParse.c:
	* generic/tclProc.c:
	* generic/tclTest.c:
	* generic/tclTimer.c:
	* generic/tcl.h: Made eval interfaces compatible with 8.0 by renaming
	Tcl_EvalObj to Tcl_EvalObjEx, renaming Tcl_Eval2 to Tcl_EvalEx and
	restoring Tcl_EvalObj and Tcl_GlobalEvalObj interfaces so they match
	Tcl 8.0.

1999-01-28  Scott Stanton  <stanton@GASPODE>

	* Merged Tcl 8.0.5b1 changes.

	* generic/tclUtil.c (Tcl_DStringSetLength): Changed so the buffer
	overallocates in a manner similar to Tcl_DStringAppend. This should
	improve performance for TclUniCharToUtfDString.

1998-12-11    === Tcl 8.1b1 Release ===

1998-12-10  Scott Stanton  <stanton@GASPODE>

	* Fixed lots of files that used TCL_THREAD instead of TCL_THREADS.

	* generic/tclEncoding.c (Tcl_FreeEncoding): Moved most of the code
	into a static FreeEncoding routine that does not grab the
	encodingMutex to avoid deadlocks/races when called from other routines
	that already have the mutex.

1998-12-09  Scott Stanton  <stanton@GASPODE>

	* library/msgcat1.0/msgcat.tcl: Fixed bad export list, fixed so all
	locale strings are converted to lower case, including file names.

	* generic/regcomp.c (makescan): Fixed bug in longest match case that
	caused anchored patterns to fail. [Bug 897]

1998-12-08  Scott Stanton  <stanton@GASPODE>

	* library/msgcat1.0/msgcat.tcl: changed mc to invoke mcunknown in the
	calling context, changed locale lookups to be case insensitive

1998-12-07  Scott Stanton  <stanton@GASPODE>

	* generic/tclAlloc.c (TclpRealloc): Fixed a memory allocation bug
	where big blocks that were reallocated into a different heap location
	were not being placed into the bigBlocks list. [Bug 933]

	* tests/msgcat.test: Added message catalog test suite.

	* library/msgcat1.0/msgcat.tcl: minor bug fixes, integrated latest
	changes from Mark Harrison.

1998-12-04  Scott Stanton  <stanton@GASPODE>

	* library/msgcat1.0/msgcat.tcl: Changed code to conform to Tcl coding
	standards. Changed to use file join for portability.

	* library/msgcat1.0: Added initial implementaion of Tcl message
	catalog package contributed by Mark Harrison.

1998-12-03  Scott Stanton  <stanton@GASPODE>

	* win/tclWinPipe.c (BuildCommandLine): Fixed bug that kept arguments
	containing spaces from being properly quoted.

	* tests/defs: Changed so auto_path is set to only contain the Tcl
	library directory. This keeps the tests from accidentally picking up
	stuff in installed packages.

	* generic/tclUtil.c (Tcl_StringMatch): Changed to match 8.0 behavior
	in corner case where there is no closing bracket.

1998-12-02  Scott Stanton  <stanton@GASPODE>

	* win/tclWinPipe.c (TclpCreateCommandChannel): Changed reader/writer
	threads to have THREAD_PRIORITY_HIGHEST so they will have a chance to
	run whenever there is something to do.

	* generic/tclIO.c (WriteBytes, WriteChars): Fixed so extraneous
	flushes do not happen in line mode.
	(TranslateOutputEOL): Made translation more efficient in line mode and
	fixed a buffer overflow bug in CRLF translation. [Bug 887]

1998-12-02  Brent Welch  <welch@SAGE>

	* Updated patchlevel to 8.1b1

1998-12-02  Scott Stanton  <stanton@GASPODE>

	* generic/regc_color.c (subcolor): Added check for error case to avoid
	an out of bounds array reference.

	* generic/tclCmdAH.c (Tcl_EncodingObjCmd): Changed to avoid using
	Tcl_DStringResult because it is not binary clean.

	* generic/tclParse.c (Tcl_ParseCommand): Fixed bug in comment parsing
	where a trailing comment looked like an incomplete command.

1998-12-02  Brent Welch  <welch@SAGE>

	* Merged changes from 8.0.4, especially the new pkg_mkIndex

1998-12-01  Scott Stanton  <stanton@GASPODE>

	* generic/tclIO.c (Tcl_ReadChars): Added a call to UpdateInterest so
	we don't block when there is data sitting in the buffers.

	* generic/tclTest.c (TestevalobjvObjCmd): Updated for EvalObjv change.

	* tests/parse.test: Updated tests for EvalObjv change.

	* generic/tclParse.c (EvalObjv, Tcl_EvalObjv): Changed Tcl_EvalObjv
	interface to remove string and length arguments, preserved original
	interface as EvalObjv for internal use.

	* generic/tcl.h: Changed Tcl_EvalObjv interface to remove string and
	length arguments.

	* doc/Eval.3: Updated documentation for Tcl_EvalObjv to remove string
	and length arguments.

	* generic/tclCompCmds.c (TclCompileForeachCmd): Fixed code that
	corrupted the exceptDepth value in the compile environment when
	foreach failed to compile inline. [Bug 884]

	* library/encoding/euc-kr.enc:
	* library/encoding/ksc5601.enc:
	* tools/encoding/ksc5601.txt:
	* unix/tclUnixInit.c: Added support for Korean EUC.

	* win/tclWinChan.c (TclpGetDefaultStdChannel): added check for a
	failure during Tcl_MakeFileChannel.

1998-11-30  Scott Stanton  <stanton@GASPODE>

	* unix/tclUnixNotfy.c (Tcl_WaitForEvent): Fixed hang that occurs when
	trying to close a pipe that is currently being waited on by the
	notifier thread. [Bug 607]

	* unix/tclUnixFCmd.c (GetPermissionsAttribute): Increase size of
	returnString buffer to avoid overflow. [Bug 584]

	* generic/tclThreadTest.c (TclThreadSend): Fixed memory leak due to
	use of TCL_VOLATILE instead of TCL_DYNAMIC.

	* generic/tclThread.c (TclRememberSyncObject): Fixed memory leak
	caused by failure to reuse condition variables.

	* unix/tclUnixNotfy.c (Tcl_AlertNotifier, Tcl_WaitForEvent,
	(NotifierThreadProc, Tcl_InitNotifier): Fixed race condition caused by
	incorrect use of condition variables when sending messages between
	threads. [Bug 607]

	* generic/tclTestObj.c (TeststringobjCmd): MAX_STRINGS was off by one
	so the strings array was too small.

	* generic/tclCkalloc.c (Tcl_DbCkfree): Moved mutex lock so
	ValidateMemory is done inside the mutex to avoid a race condition when
	validate_memory is enabled. [Bug 880]

1998-11-23  Scott Stanton  <stanton@GASPODE>

	* regexec.c: more performance tuning from Henry Spencer.

1998-11-17  Scott Stanton  <stanton@GASPODE>

	* tclScan.c: moved "scan" implementation out of tclCmdMZ.c and added
	Unicode support. This required a complete reimplementation of the
	command to avoid using scanf(), which isn't Unicode aware. Two new
	features were added in the process: %n to return the current number of
	characters consumed, and XPG3-style %n$ argument order specifiers
	similar to those provided by the "format" command. [Bug 833]

	* tclAlloc.c: changed so allocated memory is always 8-byte aligned to
	improve memory performance and to ensure that it will work on systems
	that don't like accessing 4-byte aligned values (e.g. Solaris and
	HP-UX). [Bug 834]

1998-11-06  Scott Stanton  <stanton@GASPODE>

	* tclVar.c (TclGetIndexedScalar): Fixed bug 796, var name was getting
	lost before being passed to CallTraces.

1998-10-21  Scott Stanton  <stanton@GASPODE>

	* added "encoding" command

	* Moved internal regexp declarations from tclInt.h to tclRegexp.h

	* integrated regexp updates from Henry Spencer

1998-10-15  Scott Stanton  <stanton@GASPODE>

	* tclUtf.c: added Unicode character table support

	* tclInt.h: added TclUniCharIsWordChar

	* tclCmdMZ.c (Tcl_StringObjCmd): added "totitle" subcommand, changed
	"wordend" and "wordstart" to properly handle Unicode word characters
	and connector punctuation

1998-10-05  Scott Stanton  <stanton@GASPODE>

	* auto.tcl, package.tcl: fixed SCCS strings

	* tclIndex: updated index to reflect 8.1 files

	* tclCompile.c (TclCompileScript): changed to avoid modifying the
	input string in place because name lookup operations could have
	arbitrary side effects

	* tclInterp.c: added guard against deleting current interpreter

	* tclMacFile.c, tclUnixFile.c, tclWinFile.c, tclFileName.c: added
	warnings around code that modifies strings in place

	* tclExecute.c: fixed off-by-one copying error, fixed merge bugs

	* tclEvent.c: changed so USE_TCLALLOC is tested for value instead of
	definition

	* tclCompCmds.c: replaced SCCS strings, added warnings around code
	that modifies strings in place

	* interp.test: added test for interp deleting itself

1998-09-30  Scott Stanton  <stanton@GASPODE>

	* makefile.vc: fixed so TCL_LIBRARY is set before running tcltest

	* tclWin32Dll.c: removed TclpFinalize, cleanup of merges

Deleted ChangeLog.2000.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
2000-12-14  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclExecute.c:
	* tests/expr-old.test: Re-wrote Tcl's [expr rand()] and [expr
	srand($seed)] implementations, fixing a range error on some 64-bit
	platforms. Added tests that detect the bug. The rewrite changes the
	seed -> sequence map on 64-bit platforms, only for seed >= 2^31, a
	slight incompatibility. [Bug 121072, Patch 102781]

2000-12-10  Don Porter  <dgp@users.sourceforge.net>

	* library/init.tcl:
	* library/msgcat/msgcat.tcl:
	* library/msgcat/pkgIndex.tcl:
	* library/opt/optparse.tcl:
	* library/opt/pkgIndex.tcl: Where [uplevel] is used in a proc to
	evaluate a Tcl built-in command in the caller's context, the built-in
	commands are now fully namespace-qualified. This prevents problems
	when the caller context is in a namespace where the built-in command
	name has been used by a command in the namespace. (For example,
	[::ns::set] might be called instead of the intended [::set]). [Bug
	119422, Patch 102545]

2000-12-09  Jeff Hobbs  <jhobbs@interwoven.com>

	* win/tclWinTime.c (CalibrationThread): added lint return value to
	prevent compiler warning. [Bug 125005]

	* docs/scan.n:
	* tests/scan.test:
	* generic/tclScan.c (Tcl_ScanObjCmd): changed %o and %x to use strtoul
	instead of strtol to correctly preserve scan<>format conversion of
	large integers. [Patch 102663, Bug 124600]

	* generic/tclExecute.c (TclExecuteByteCode): Commited patch fixing
	handling of {!<boolean>} in expressions. [Patch 102702]

2000-12-08  Jeff Hobbs  <jhobbs@interwoven.com>

	* library/init.tcl: Added support for PATHEXT variable in auto_execok,
	recognizing the proper set of executable extensions on Windows. [Patch
	102719]

2000-12-08  Andreas Kupries  <a.kupries@westend.com>

	* generic/tclEncoding.c (LoadTableEncoding): Changed dangerous code to
	something less critical. This fixes [Bug 119417], part A without
	affecting the speed when loading encodings.

2000-12-08  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/open.n: Added xref to fconfigure and advice on the opening of
	binary files. Should help prevent a recurrence of bugs like [Bug
	124558]

2000-12-07  Jeff Hobbs  <jhobbs@interwoven.com>

	* generic/tcl.h: added note about need to updated
	library/dde/pkgIndex.tcl with minor version increment.

	* library/dde/pkgIndex.tcl: updated to use 84 version to reflect the
	makefile. Should probably be updated to use its real version at some
	point. [Patch 102560, Bug 119421]

2000-12-06  Eric Melski  <ericm@ajubasolutions.com>

	* generic/tcl.h (attemptckalloc): Fixed typo for #define of
	attemptckalloc (was defined to Tcl_AttempDbCkalloc, should have been
	Tcl_AttemptDbCkalloc). [Bug 124384]

	* generic/tclCkalloc.c: Added TCL_MEM_DEBUG versions of
	Tcl_AttemptDbCkrealloc and Tcl_AttemptDbCkalloc. [Bug 124384].

2000-11-24  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclExecute.c (TclExecuteByteCode): Logical negation "!"  can
	now handle string booleans, provided those values are placed in
	variables.

	* tests/expr.test (expr-13.17): Check that [expr {!$var}] can negate
	the string-versions of booleans "yes", "false", etc.

	* library/tcltest/tcltest.tcl (getMatchingFiles,
	(getMatchingDirectories):
	* tools/man2html.tcl (doDir):
	* tools/man2help.tcl (doDir):
	* library/package.tcl (tclPkgUnknown,tclMacPkgSearch):
	* library/safe.tcl (AddSubDirs): [glob] uses -directory instead of
	unsafe [file join]. [Bug 123313]

	* generic/tclIndexObj.c:
	* generic/tclTestObj.c (TestindexobjCmd): Changed internal
	representation of index objects to fix [Bug 119082]; fix shouldn't be
	visible to outside world...

	* generic/tclTest.c (TestGetIndexFromObjStructObjCmd):
	* tests/indexObj.test: (indexObj-6.*) Added to test for presence of
	[Bug 119082].

2000-11-23  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclCmdIL.c (Tcl_LsortObjCmd): Fixed memory leak from [Bug
	119398]

	* library/init.tcl (unknown): Added specific level parameters to
	all uplevel invokations to boost performance; didn't dare touch
	the "namespace inscope" stuff though, since it looks sensitive
	to me!  Should fix [Bug 123217], though testing is tricky...

2000-11-21  Andreas Kupries  <a.kupries@westend.com>

	All of the changes below are described in TIP #7 ~ Specification and
	result from the application of the patch contained therein. Creator of
	the patch is Kevin Kenny <kennykb@crd.ge.com>. The patch used here is
	actually a bit different. Two MS specific constant values (format
	FOOui64) were replaced with a more portable formatting of the values
	and an additional cast to LONGLONG. My cross-compiling gcc was unable
	to process the original form. [Patch 102459]

	* tclWinTime.c: Add to the static data a set of variables that manage
	the phase-locked techniques, including a ''CRITICAL_SECTION'' to guard
	them so that multi-threaded code is stable.

	* tclWinTime.c: Modify ''TclpGetSeconds'' to call ''TclpGetTime'' and
	return the 'seconds' portion of the result. This change is necessary
	to make sure that the two times are consistent near the rollover from
	one second to another.

	* tclWinTime.c: Modify ''TclpGetClicks'' to use TclpGetTime to
	determine the click count as a number of microseconds.

	* tclWinTime.c: Modify ''TclpGetTime'' to return the time as M*Q+B,
	where Q is the result of ''QueryPerformanceCounter'', and M and B are
	variables maintained by the phase-locked loop to keep the result as
	close as possible to the system clock. The ''TclpGetTime'' call will
	also launch the phase-lock management in a separate thread the first
	time that it is invoked. If the performance counter is unavailable, or
	if its frequency is not one of the two common 8254-compatible rates,
	then ''TclpGetTime'' will return the result of ''ftime'' as it does in
	Tcl 8.3.2.

	* tclWinTime.c: Add the clock calibration procedure. The calibration
	is somewhat complex; to save space, the reader is referred to the
	reference implementation for the details of how the time base and
	frequency are maintained.

	* tclWinNotify.c: Modify ''Tcl_Sleep'' to test that the process has,
	in fact, slept for the requisite time by calling ''TclpGetTime'' and
	comparing with the desired time. Otherwise, roundoff errors may cause
	the process to awaken early.

	* tclWinTest.c: Add a ''testwinclock'' command. This command returns a
	four element list comprising the seconds and microseconds portions of
	the system clock and the seconds and microseconds portions of the Tcl
	clock.

	* winTime.test: Add to the test suite a test that makes sure that the
	Tcl clock stays within 1.1 ms of the system clock over the duration of
	the test.

2000-11-21  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/global.n:
	* doc/upvar.n:
	* doc/variable.n: Improved documentation to mention that variables so
	created are listed in [info locals] and added a few more cross-links
	between these commands. [Bug 119387]

2000-11-17  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/safe.test: (safe-4.3):
	* generic/tclVar.c (TclLookupVar): Changed again. Now passes all the
	tests, though one needed modifying since it required the wrong answer.
	(Why on earth do we have inline modification of argument strings? This
	sort of thing is horrendous to debug and doesn't work well in a
	multithreaded environment!) [Bug 119192]

	* tests/var.test: (var-1.19) If my attempts to fix the problem aren't
	right yet, my attempts to describe it look pretty good to me...

2000-11-16  Andreas Kupries  <a.kupries@westend.com>

	* win/tclWinPort.h (line 69): Changed reference to winsock2.h into
	winsock.h. This was a leftover from a foray into using winsock version
	2 (History lesson from Scott Redman and Jeff Hobbs). This code was no
	problem when compiling Tcl itself, but could trip extensions. [Bug
	122568]

2000-11-15  Jeff Hobbs  <jeff.hobbs@acm.org>

	* unix/Makefile.in: removed bp.c references (hasn't existed in a long
	time). Corrected 'make dist' to make dist with unversioned library
	directories (same as out of cvs), so make install works correctly with
	either source tree.

2000-11-15  Jeff Hobbs  <jeff.hobbs@acm.org>

	* generic/tclVar.c (TclLookupVar): reverted fix below as it broke all
	other array unset error reporting.  Bug 119192 is still open.

2000-11-15  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclVar.c (TclLookupVar): Changed references to part2 to use
	elName instead in various error message generating spots. [Bug 119192]

2000-11-03  David Gravereaux  <davygrvy@ajubasolutions.com>

	* win/.cvsignore: Removed 'configure' from the glob list now that it's
	included.

2000-11-03  Jeff Hobbs  <hobbs@ajubasolutions.com>

	8.4a2 RELEASE

	* unix/Makefile.in (install-libraries, dist):
	* win/makefile.vc (install-libraries):
	* win/Makefile.in (install-libraries): updated to install unversioned
	library directories into versioned directories.

	* tools/tcl.wse.in: updated for unversioning of library dirs

	* unix/mkLinks: updated mkLinks with latest doc updates

	* doc/Tcl_Main.3: added docs for Tcl_SetMainLoop

	* generic/tclStubInit.c:
	* generic/tclDecls.h:
	* generic/tcl.decls: added Tcl_SetMainLoop proc that allows people to
	set a main loop that will run for tclsh.
	* generic/tcl.h: added Tcl_MainLoopProc typedef
	* generic/tclMain.c (Tcl_SetMainLoop, StdinProc, Prompt): new
	StdinProc and Prompt static procs and Tcl_SetMainLoop stubs proc. The
	first two handle a fileevent based prompt (taken from tkMain.c).
	Tcl_SetMainLoop enables the interactive setting of a main loop
	procedure. This enables Tk to be a loadable package.

2000-11-02  David Gravereaux  <davygrvy@ajubasolutions.com>

	* generic/tclEvent.c: tclLibraryPath Tcl_Obj didn't have a way to
	share its data among threads. This caused Tcl_Init() to always fail in
	threads. Added a way to pass the data around with a global char*.
	[BUG: 5301]

2000-11-02  Jeff Hobbs  <hobbs@ajubasolutions.com>

	* unix/configure:
	* unix/dltest/configure:
	* win/configure:
	* tools/configure: checked in configure scripts so people doing CVS
	checkouts aren't required to have autoconf. Changes to configure.in in
	the future will require the corresponding configure script to also be
	re-autoconf'ed and checked in.

	* win/makefile.vc:
	* win/tcl.m4: makefile fixes for Win64 support

	* generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): minor cast
	changes.

2000-11-01  Jeff Hobbs  <hobbs@ajubasolutions.com>

	* unix/tcl.m4: removed use of -lbsd and -ldl for AIX-5.

	* tests/subst.test: added tests for non-zero return code handling by
	subst.
	* generic/tclParse.c (Tcl_EvalEx): corrected handling of non-zero,
	non-error return code cases for subst. [Bug 119829]

	* generic/tclVar.c (TclVarTraceExists): Corrected excessive mem use
	when info exists was called on a non-existent array element. [Bug
	119213, 119336]

2000-10-30  David Gravereaux  <davygrvy@ajubasolutions.com>

	* win/configure.in:
	* win/Makefile.in:
	* win/makefile.vc:
	* win/tcl.rc:
	* win/tclsh.rc: Added logic to derive filenames better in the resource
	scripts based on compile options.

2000-10-30  Jeff Hobbs  <hobbs@ajubasolutions.com>

	* unix/tclUnixInit.c: added default encoding map from "ja_JP.eucJP" to
	"euc-jp". (takahashi)

	* tests/clock.test: corrected clock-2.* test numbering

	* unix/configure.in (SC_TCL_LINK_LIBS): removed code that was
	commented out (it had been moved to tcl.m4's SC_TCL_LINK_LIBS
	already).

	* unix/tcl.m4: consolidated gettimeofday check for AIX.

2000-10-27  Jeff Hobbs  <hobbs@ajubasolutions.com>

	* unix/configure.in:
	* unix/tcl.m4: added support for AIX-5.

	* generic/tclIO.c (Tcl_NotifyChannel): removed #ifdef around code for
	old channel structures, placed preserve/release around statePtr
	* generic/tclIO.c (CloseChannel): the statePtr for a channel was not
	being freed when the last channel in a stack was freed, causing a mem
	leak.

	* unix/tclUnixChan.c: updated channel types to strict
	TCL_CHANNEL_VERSION_2 style to avoid compiler warnings. They work
	either way, but this avoids compiler warnings (that worries people).

2000-10-27  Jennifer Hom  <jenn@ajubasolutions.com>

	* library/tcltest1.0/tcltest.tcl: Removed a cd into the test directory
	in runAllTests that screwed up the temporary directory setting,
	effectively preventing users from running tests on multiple platforms
	at the same time.

2000-10-26  David Gravereaux <davygrvy@ajubasolutions.com>

	* win/tclWinFile.c (TclpMatchFilesTypes): NULL was being set to "attr"
	which was a DWORD. Changed NULL to zero because a 'void *' can't be
	set to a DWORD to avoid the compiler warning.

2000-10-24  Jennifer Hom  <jenn@ajubasolutions.com>

	* tests/all.tcl: Removed support for tcltest 1.0.

	* tests/tcltest.test:
	* library/tcltest1.0/tcltest.tcl:
	* library/tcltest1.0/pkgIndex.tcl:
	* docs/tcltest.n: Moved tcltest2 code so that it's the standard
	version of tcltest. Removed all tcltest2 files (tests/tcltest2.test,
	library/tcltest1.0/tcltest2.tcl, docs/tcltest2.n).

2000-10-20  Jeff Hobbs  <hobbs@ajubasolutions.com>

	* win/tclWinFile.c (TclpMatchFilesTypes): made the stat call only
	occur when necessary (for 'glob' command). Significantly speeds up
	glob command from 8.3. [BUG: 6216]

2000-10-19  Jennifer Hom  <jenn@ajubasolutions.com>

	* library/tcltest1.0/tcltest2.tcl:
	* tests/tcltest2
	* doc/tcltest2.n: Code and documentation cleanup. Modified -verbose to
	take list of keywords as well as string of letters. Removed Tcl
	version information from tcltest. Removed tcltest::grep from tcltest
	package. Added optional 3rd directory argument to
	makeFile/makeDirectory and removeFile/removeDirectory.

	* tests/basic.test: Changed references to tcltest::tclVersion to
	hardcoded numbers.
	* generic/tcl.h: Changed reference to tcltest2.tcl and tcltest.tcl in
	comments to tests/basic.test.

2000-10-06  David Gravereaux  <davygrvy@ajubasolutions.com>

	* win/tclWinChan.c: moved Win2K bug case test with GetStdHandle() from
	TclpGetDefaultStdChannel into Tcl_MakeFileChannel to enable a more
	general method in detecting invalid OS handles rather than just a
	specific known case. [BUG: 5971]

2000-10-06  Jeff Hobbs  <hobbs@ajubasolutions.com>

	* tests/cmdAH.test: extra tests for 'file channels' that include
	multiple interpreter tests and channel sharing
	* generic/tclIO.c (Tcl_GetChannelNamesEx): corrected function (and
	consequently 'file channels') to return channels that are actually
	registered for this specific interp, rather than this thread.

	* doc/CrtChannel.3: fixed spelling mistakes

2000-09-29  Jennifer Hom  <jenn@ajubasolutions.com>

	* library/tcltest1.0/tcltest2.tcl:
	* tests/tcltest2.test:
	* doc/tcltest2.n: Modified the new form of the test command to accept
	both attribute-value pairs and command line options. Updated the tests
	and the documentation for this new format. Also changed the option
	names for the test command.

2000-09-29  Jeff Hobbs  <hobbs@scriptics.com>

	* win/tclWinSerial.c (SerialGetOptionProc): corrected reporting of
	space parity on Windows (Eason) [Bug 6057].

	* win/Makefile.in: commented use of TESTFLAGS
	* unix/Makefile.in: added TESTFLAGS to test target to conform with
	Windows makefile and TEA style.

	* tests/stack.test: prevented possible crash on systems with low
	default stacksize (Tru64, AIX) in infinite recursion test. A solution
	to check remaining stack space in the core is best, but hard to do in
	a cross-platform manner.

	* generic/tclIOGT.c (FLUSH_DELAY): renamed DELAY define to FLUSH_DELAY
	to avoid defn conflict using Tru64's cc.

2000-09-28  Jeff Hobbs  <hobbs@ajubasolutions.com>

	* tools/tcl.wse.in: added tclPlatDecls.h and tkPlatDecls.h to the
	Windows .exe install.

	* tests/fCmd.test (fCmd-6.20): corrected test to remove c:/tcl8975@
	after creating it.

	* tests/fileName.test: cleaned up the testing of glob patterns for
	c:/globTest (Windows) to directly create/remove directory.

2000-09-27  Jeff Hobbs  <hobbs@ajubasolutions.com>

	* generic/tcl.decls:
	* generic/tclIO.c: updated Tcl_IsChannelShared,
	Tcl_IsChannelRegistered, Tcl_CutChannel, Tcl_SpliceChannel,
	Tcl_IsChannelExisting, and Tcl_ClearChannelHandlers to conform to the
	new stacked channel implementation. Their stub slots were also moved
	to give preference to the new 8.3.2 stub functions. This will cause an
	incompatibility with 8.4a1 only.
	(StopCopy): fixed a bug introduced by a partial fix in 8.3.2 that
	didn't set nonBlocking correctly when resetting the flags for the
	write side. [Bug: 6261]

	* doc/ChnlStack.3:
	* doc/CrtChannel.3:
	* generic/tcl.decls:
	* generic/tcl.h:
	* generic/tclDecls.h:
	* generic/tclIO.c:
	* generic/tclIO.h:
	* generic/tclIOGT.c:
	* generic/tclInt.decls:
	* generic/tclIntDecls.h:
	* generic/tclStubInit.c:
	* generic/tclTest.c:
	* tests/iogt.test:
	* unix/Makefile.in:
	* win/Makefile.in:
	* win/makefile.vc:
	* win/tclConfig.sh.in:
	* win/tclWinChan.c:
	* win/tclWinConsole.c:
	* win/tclWinPipe.c:
	* win/tclWinSerial.c:
	* win/tclWinSock.c: Up-port of changes made in 8.3.2 to 8.4a2 code
	base. Most of these changes relate to the rewrite of the stacked
	channel implementation, with a few config related fixes.

	Following is an asynchronous include of the applicable ChangeLog
	entries from 8.3.2.

	********************************************************
	** START OF ASYNCHRONOUS UP-PORT LOG (8.3.2 -> 8.4a2) **
	********************************************************

2000-08-07  Jeff Hobbs  <hobbs@scriptics.com>

	* doc/ChnlStack.3:
	* doc/CrtChannel.3: updated the docs to be aware of the
	TCL_CHANNEL_VERSION_2 style of Tcl channels.

	* generic/tclIO.c (Tcl_CreateChannel): added assertion to verify that
	the new channel versioning will be binary compatible with older
	channel drivers.

2000-08-05  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclIOGT.c (TclChannelTransform): fixed segfault that would
	occur when transforming a channel with a proc that did not yet exist.
	(Kupries)

	* generic/tclTest.c (TestChannelCmd): added some lint init'ing of
	statePtr and chan vars.

2000-07-26  Jeff Hobbs  <hobbs@scriptics.com>

	Merged core-8-3-1-io-rewrite back into core-8-3-1-branch. The
	core-8-3-1-io-rewrite branch should now be considered defunct.

	* generic/tclStubInit.c:
	* generic/tclDecls.h:
	* generic/tcl.decls:
	* generic/tcl.h:
	* generic/tclIO.c: moved the Tcl_Channel* macros from tcl.h to tclIO.c
	and made them proper stubbed functions. These are: Tcl_ChannelName,
	Tcl_ChannelVersion, Tcl_ChannelBlockModeProc, Tcl_ChannelCloseProc,
	Tcl_ChannelClose2Proc, Tcl_ChannelInputProc, Tcl_ChannelOutputProc,
	Tcl_ChannelSeekProc, Tcl_ChannelSetOptionProc,
	Tcl_ChannelGetOptionProc, Tcl_ChannelWatchProc,
	Tcl_ChannelGetHandleProc, Tcl_ChannelFlushProc, and
	Tcl_ChannelHandlerProc. These should be used to access the
	Tcl_ChannelType structure instead of direct pointer dereferencing.

	* tests/iogt.test: added RCS string, marked tests 2.* to be unixOnly
	due to underlying system differences.

2000-07-25 Andreas Kupries <a.kupries@westend.com>

	* tests/iogt.test: (line 866f) New tests iogt-6.[01], highlighting
	buffering trouble when stacking and unstacking transformations.
	iogt-6.0 is solved, see the changes below. iogt-6.1 remains, for now,
	due to the perceived complexity of solutions.

	* generic/tclIO.h: (line 139f) struct Channel, added a buffer queue,
	to hold data pushed back when stacking a transformation.

	* generic/tclIO.c:
	(line 91f, line 7434f) New internal function 'CopyBuffer'.  Derived
	from 'CopyAndTranslateBuffer', with translation removed.
	(line 1025f, line 1212f): Initialization of new queue.
	(line 1164f, Tcl_StackChannel): Pushback of input queue.
	(line 1293f, Tcl_UnstackChannel): Discard input and pushback.
	(line 3748f, Tcl_ReadRaw): Modified to use data in the push back area
	before going to the driver. Uses 'CopyBuffer', s.a.
	(line 4702f, GetInput): Modified to use data in the push back area
	before going to the driver.
 	(line 4867f, Tcl_Seek): Modified to take pushback of the topmost
	channel in a stack into account.
	(line 5620f, Tcl_InputBuffered): See above. Added
	'Tcl_ChannelBuffered'. Analog to 'Tcl_InputBuffered' but for the
	buffer area in the channel.

	* generic/tcl.decls: New public API 'Tcl_ChannelBuffered'. S.a.

2000-07-17  Jeff Hobbs  <hobbs@scriptics.com>

	* unix/Makefile.in:
	* win/Makefile.in:
	* win/makefile.vc: added tclIOGT.c to objects list to compile.

	* generic/tclStubInit.c:
	* generic/tclIntDecls.h:
	* generic/tclInt.decls: commented out internal decls for
	TclTestChannelCmd and TclTestChannelEventCmd as they were moved to
	tclTest.c. Added new decls for TclChannelEventScriptInvoker and
	TclChannelTransform.

	* generic/tclIO.c (CloseChannel): stopped masking out of the
	TCL_READABLE|TCL_WRITABLE bits from the state flags in CloseChannel,
	instead adding extra intelligence to CheckChannelErrors with a new
	CHANNEL_RAW_MODE bit for special behavior when called from Raw channel
	APIs.

2000-07-13  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclIO.c (StackSetBlockMode): moved set of chanPtr outside of
	blockModeProc check to avoid infinite loop when blockModeProc was
	NULL. Updated TransformSeekProc to not call Tcl_Seek directly
	(Kupries).

	* win/tclWinChan.c: updated fileChannelType to v2 channel struct
	* win/tclWinConsole.c: updated consoleChannelType to v2 channel struct
	* win/tclWinPipe.c: updated pipeChannelType to v2 channel struct
	* win/tclWinSerial.c: updated serialChannelType to v2 channel struct
	* win/tclWinSock.c: updated tcpChannelType to v2 channel struct

2000-07-11  Brent Welch	<welch@ajubasolutions.com>

	* win/tclConfig.sh.in (TCL_LIBS): Cleaned up unix-specific autoconf
	variables.

2000-07-11  Jeff Hobbs  <hobbs@scriptics.com>

	* tests/iogt.test: made tests [345].0 not run by default as they were
	failing in the new design, but I'm not convinced that the returned
	result isn't correct.

	* generic/tclDecls.h:
	* generic/tclStubInit.c:
	* generic/tcl.decls: added Tcl_GetTopChannel C API that returns the
	current top channel of a channel stack. Tcl_GetChannel was changed
	earlier to return the bottommost channel of a stack because that is
	the one that is guaranteed to stay around the longest, and this was
	needed to compensate for certain operations that want to look at the
	state of the main channel. Most channel APIs already compensate for
	grabbing the top, so it shouldn't be needed often.

	* generic/tclIO.c (Tcl_StackChannel, Tcl_UnstackChannel): Added
	flushing of buffers (Kupries), removed use of DownChannel macro, added
	Tcl_GetTopChannel public API to get to the top channel of the channel
	stack (necessary for TLS). Rewrote Tcl_NotifyChannel for new channel
	design (Kupries). Did some code cleanup in the transform code.
	tclIO.c must still be broken into bits (separate out test code and
	giot code, create tclIO.h).

2000-07-10  Andreas Kupries <a.kupries@westend.com>

	* tests/iogt.test: Reverted some earlier changes as a fix by Jeff
	revived the original and correct behaviour. IOW, the tests showed a
	genuine error and I didn't see it :(.

	* generic/tclIO.c (Tcl_Read|Write_Raw): Changed to directly use the
	drivers and not DoRead|DoWrite. The latter use the buffering system,
	encoding and eol-translation and this wreaks havoc with the data going
	through the transformations. Both procedures use CheckForchannelErrors
	and let it believe that there is no background copy in progress or
	else stacked channels could not be used for that.

	* generic/tclIO.c (TclCopyChannel, CopyData): Moved access to the
	topmost channel from the first to the second procedure to make the
	decision about that at the last possible time (Callbacks can change
	the stacking).

	test suite: failures of iogt-[345].0

2000-07-06  Jeff Hobbs  <hobbs@scriptics.com>

	* tests/iogt.test: new tests for stacked channel stuff based off new
	'testchannel transform|unstack' code (Kupries IOGT extension).
	* generic/tcl.decls:
	* generic/tcl.h:
	* generic/tclDecls.h:
	* generic/tclStubsInit.c:
	* generic/tclIO.c: complete rewrite of Tcl Channel code for stacked
	channels. Channels are now designed to work in a more stacked fashion
	with a shared ChannelState data structure.

2000-06-02  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclIO.c (CloseChannel): removed the &ing out of
	(TCL_READABLE|TCL_WRITABLE) from the flags, as CloseChannel does this
	on the next pass through for the top channel, and it appeared to be
	causing hangs by not allowing the final flush.

2000-06-01  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclIO.c (CloseChannel): Rewrote CloseChannel code to unstack
	a channel during the close process. Fixed a refcount bug in
	Tcl_UnstackChannel. [Bug: 5623]
	(CloseChannel): further extended CloseChannel in the stacked case to
	effect certain operations on the next channel that would have been
	done in Tcl_Close.  Also added CHANNEL_CLOSED and removed
	(TCL_READABLE|TCL_WRITABLE) bits from chanPtr->flags. Changed final
	reset of the WatchProc to check the chanDownPtr's (next) interestMask.

	******************************************************
	** END OF ASYNCHRONOUS UP-PORT LOG (8.3.2 -> 8.4a2) **
	******************************************************

2000-09-20  Jeff Hobbs  <hobbs@scriptics.com>

	* tests/socket.test: removed doTestsWithRemoteServer constraint from
	socket-12.*. It requires 'exec', not a remote server. Cleaned up some
	coding errors.

2000-09-20  Jennifer Hom  <jenn@ajubasolutions.com>

	* library/tcltest1.0/pkgIndex.tcl: Updated to load tcltest 2.0.
	* library/tcltest1.0/tcltest2.tcl: New version of tcltest.
	Cleanup of command line parsing: allows users to specify command line
	arguments through an environment variable named TCLTEST_OPTIONS [RFE:
	3748], does not respond to incorrect arguments, and forces usage of
	entire flag name when using command line arguments. Defines accessor
	procs for all tcltest variables. Allows users to use 'return' in test
	scripts. Allow users to specify whether test files should be sourced
	or run in a separate process. 'all.tcl' code moved to tcltest package.
	'test' proc modified to use attribute-value pairs. Allow users to
	specify what return codes, output, and errors can be compared and
	whether these values should be compared using regexp, glob, or exact
	matching. makeDirectory & removeDirectory now operate with respect to
	temporaryDirectory [Bug: 6001]. Test results from tests run in slave
	interpreters are now included in test totals [Bug: 1493]. Test files
	that return error values are now reported.
	* tests/all.tcl: Added code to check for the tcltest version loaded;
	modified to figure out which tests to run based on the tcltest version
	loaded.
	* tests/tcltest.test: Modified to explicitly load version 1.0 of
	tcltest.
	* tests/tcltest2.test: New test suite for tcltest; includes all of the
	old tests plus new ones reflecting changes made for version 2.0.
	* tests/cmdAH.test: Added singleTestInterp constraint to cmdAH-31.2;
	this test does not run if tests aren't sourced into a single
	interpreter.
	* tests/socket.test: Fixed two tests that were referencing variables
	outside of scope.

	* tools/tcl.wse.in: Added code to install tcltest2.tcl.

	* doc/tcltest2.n: New documentation for tcltest version 2.0. Removes
	documentation for tcltest namespace variables. Adds documentation for
	new tcltest procs.

	* unix/mkLinks: Added code to link to tcltest2.n.

	* generic/tcl.h: Added comment to modify tcltest2.tcl as well as
	tcltest.tcl for version changes.

2000-09-19  Eric Melski  <ericm@ajubasolutions.com>

	* generic/tclCmdMZ.c (Tcl_RegexpObjCmd): When using -all, all attempts
	after the first to match the regexp against the string should include
	the TCL_REG_NOTBOL flag, to avoid erroneously matching ^ in the middle
	of the string. Added code to set this flag after the first pass
	through the matching loop. [Bug: 6284].

2000-09-19  David Gravereaux  <davygrvy@ajubasolutions.com>

	* doc/Eval.3: Added a note about the script argument to Tcl_Eval()
	should be in UTF-8 or risk implied conversion errors when possible
	combinations of upper ascii can be valid UTF-8 special codes.

2000-09-17  Eric Melski  <ericm@ajubasolutions.com>

	* tests/cmdIL.test: Added a test for fix for [Bug: 6212].

	* generic/tclCmdIL.c (Tcl_LsortObjCmd): Applied patch from [Bug:
	6212], which corrected an error in the handling of the -index option.

2000-09-14  Eric Melski  <ericm@ajubasolutions.com>

	* doc/Alloc.3: Added entries for Tcl_AttemptAlloc, Tcl_AttempRealloc.

	* doc/StringObj.3: Added entry for Tcl_AttemptSetObjLength.

	* generic/tclDecls.h:
	* generic/tclStubInit.c: Regen'ed stubs files from new tcl.decls.

	* generic/tcl.decls: Added stubs for the Tcl_Attempt* memory
	allocators and for Tcl_AttemptSetObjLength.

	* generic/tcl.h: Added #define's for attemptckalloc, attemptckrealloc,
	which map to the Tcl_Attempt* memory allocators.

	* generic/tclCkalloc.c: Added non-panic'ing versions of Tcl_Alloc,
	Tcl_Realloc, etc.; these are called Tcl_AttemptAlloc,
	Tcl_AttemptRealloc, etc. These are used by Tcl_AttemptSetObjLength and
	the string obj append functions.

	* generic/tclStringObj.c: Modified string growth algorithm to use
	doubling algorithm as long as possible, and only fall back when that
	fails. Added Tcl_AttemptSetObjLength, and modified
	AppendUnicodeToUnicodeRep, AppendUtfToUtfRep, and
	Tcl_AppendStringsToObjVA to support this.

2000-09-07  David Gravereaux <davygrvy@ajubasolutions.com>

	* win/.cvsignore: changed the glob patterns a bit to exclude VC++
	project conversion backups.

	* win/tclWinPipe.c: Stage-1 bug fix for TR#2460 "exec leaks memory".
	Added more logic around the close-down of the pipe reader thread so as
	to avoid, at all cost, a TerminateThread. Most cases with exec are
	fixed, but I don't consider 2460 done yet. Closing down the read side
	of a pipe before the child process, doesn't really fit the windows
	model. [BUG: 2460]

2000-09-07  Jeff Hobbs  <hobbs@scriptics.com>

	* doc/trace.n: minor doc cleanup

2000-09-06  André Pönitz <poenitz@htwm.de>

	* doc/*.n: added or changed "SEE ALSO:" section

2000-09-06  Jeff Hobbs  <hobbs@scriptics.com>

	* win/tclWinLoad.c (TclpLoadFile): added special message for
	ERROR_PROC_NOT_FOUND exception in loading a dll.
	* win/tclWinError.c: changed ERROR_PROC_NOT_FOUND to map from ESRCH
	(POSIX: no such process) to EINVAL because there is no good mapping
	for "procedure not found".

	* README:
	* generic/tcl.h:
	* library/tcltest1.0/tcltest.tcl:
	* tools/tcl.wse.in:
	* tools/tcltk-man2html.tcl:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/README.binary:
	* win/configure.in: updated patchlevel to 8.4a2

	* unix/tclUnixPipe.c (TclpCreateProcess): Removed WNOHANG from
	Tcl_WaitPid call in error case of process creation on Unix, as it
	would lead to defunct processes. [Bug: 6148]

	* tests/string.test: extended string repeat tests
	* generic/tclCmdMZ.c (Tcl_StringObjCmd): changed STR_REPEAT to
	preallocate the full space of the final string, avoided repeated
	appends.

	* doc/source.n:
	* doc/Eval.3: added extra note about how to safe use ^Z in code, as it
	is now a cross-platform (was just Windows) EOF char.

2000-09-05  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclHash.c: fixed pedantic warning of incorrectly placed
	#endif

	* generic/tclExecute.c (TclExecuteByteCode): INST_STR_INDEX fixed
	pedantic cast warning.
	Corrected support for building with -DTCL_COMPILE_STATS.
	Added efficiency check of object equality.

2000-08-29  Eric Melski  <ericm@ajubasolutions.com>

	* generic/tclStringObj.c: Applied patch from Gerhard Hintermayer to
	provide a more conservative string growth algorithm for strings larger
	than one megabyte; this allows more efficient use of memory for very
	large strings.

2000-08-25  Eric Melski  <ericm@ajubasolutions.com>

	* tests/trace.test: Extended array tracing tests.

	* doc/trace.n: Clarified information about when array traces will be
	fired.

	* generic/tclVar.c (Tcl_ArrayObjCmd): Corrected call to CallTraces
	(for TCL_TRACE_ARRAY) to only be called when the variable is either an
	array or is undefined, to ensure that array traces do not fire for
	scalar variables.

2000-08-24  Eric Melski  <ericm@ajubasolutions.com>

	* doc/man.macros: Tweaked tab settings for .SO (Standard Options)
	sections, based on suggestion from Peter Spjuth.

2000-08-24  Mo DeJong  <mdejong@redhat.com>

	* unix/README: Update to account for removal of --enable-gcc.
	* unix/configure.in:
	* unix/tcl.m4 (SC_ENABLE_GCC): Remove --enable-gcc option.
	* win/README: Add note about building with Cygwin.
	* win/configure.in:
	* win/tcl.m4 (SC_ENABLE_GCC): Remove --enable-gcc option. Remove quick
	hack that provided cross compile support for windows builds.

2000-08-24  Eric Melski  <ericm@ajubasolutions.com>

	Overall change: Added support for command rename/delete traces and new
	trace syntax, from patch from Vince Darley. Added support for array
	traces for variables. [RFE: 5048, 5967].

	* doc/trace.n: Updated documentation for new syntax; flagged old
	syntax as deprecated; added documentation for command rename/delete
	traces and variable array traces.

	* tests/trace.test: Updated tests for new trace syntax; new tests for
	command rename/delete traces; new tests for array traces.

	* generic/tclVar.c: Support for new trace syntax; support for
	TCL_TRACE_ARRAY.

	* generic/tclStubInit.c:
	* generic/tclDecls.h:
	* generic/tcl.decls: Stub functions for command rename/delete traces.

	* generic/tcl.h:
	* generic/tclInt.h:
	* generic/tclBasic.c: Support for command traces.

	* generic/tclCmdMZ.c (TclTraceVariableObjCmd): Patched to support new
	[trace] syntax:
	trace {add|remove|list} {variable|command} name ops command
	Added support for command traces (rename, delete operations).
	Added support for TCL_TRACE_ARRAY at Tcl level (array operation for
	variable traces).

2000-08-20  Eric Melski  <ericm@ajubasolutions.com>

	* generic/tclVar.c: Added check for non-arrays for [array statistics]
	command (patch from Mark Patton).

2000-08-19  David Gravereaux <davygrvy@ajubasolutions.com>

	* generic/tclPlatDecls.h: without a previous '#include <windows.h>',
	tclPlatDecls.h can't be parsed due to a missing definition of TCHAR.
	Added a check to include it when not defined.

	***POSSIBLE OBSCURE BUG*** could be caused when the compile flags for
	the core happen to be different than a project who uses these publics
	regarding -D_MBCS and -D_UNICODE. This added check might have to be
	revisited later with a better understanding of the reprocusions. I
	think TCHAR should be replaced with it's expansion.

2000-08-18  David Gravereaux <davygrvy@ajubasolutions.com>

	* win/.cvsignore (added): provides a cleaner build environment with
	graphical CVS clients.

2000-08-15  Eric Melski  <ericm@ajubasolutions.com>

	* library/tcltest1.0/tcltest.tcl: Set debug level in
	tcltest::restoreState to 2, for consistancy with the debug level in
	tcltest::saveState [Bug: 4505].

2000-08-14  Eric Melski  <ericm@ajubasolutions.com>

	* win/makefile.vc:
	* win/Makefile.in:
	* unix/Makefile.in: Added tclPlatDecls.h to the list of installed
	headers, for more complete stubs support. [Bug: 5241].

	* generic/tcl.h: Added #include "tclPlatDecls.h" to get
	platform-specific stubs declarations (Tcl_WinTCharToUtf, etc)
	[Bug: 5241].

	* README: Updated link for instructions on compiling Tcl from sources
	to point to correct location (http://dev.scriptics.com/doc/... instead
	of http://dev.scriptics.com/support/...).

2000-08-11  Eric Melski  <ericm@ajubasolutions.com>

	* generic/tclEnv.c (TclUnsetEnv): Changed declaration of length
	variable from "unsigned int" to "int", to match usage when passed to
	TclpFindVariable [Bug: 6126].

2000-08-10  Eric Melski  <ericm@ajubasolutions.com>

	* library/msgcat1.0/pkgIndex.tcl: Bumped version number to 1.2 [Bug:
	6100].

	* library/msgcat1.0/msgcat.tcl: Removed erroneous [package forget] in
	msgcat namespace initializer. Bumped version number to 1.2 [Bug: 6100]

2000-08-10  David Gravereaux <davygrvy@ajubasolutions.com>

	* generic/tclObj.c: r1.15 accidentally changed a global mutex name
	tclObjMutex to ObjMutex.  Put the correct name back.

2000-08-07  Eric Melski  <ericm@ajubasolutions.com>

	* tests/indexObj.test: Added tests using the [testwrongnumargs]
	command to test Tcl_WrongNumArgs.

	* generic/tclTest.c (TestWrongNumArgsObjCmd): Added test function for
	the Tcl_WrongNumArgs function.

	* generic/tclIndexObj.c (Tcl_WrongNumArgs): Corrected algorithm to not
	insert a space before the message component when objc == 0 [Bug: 6078]

2000-07-27  Mo DeJong  <mdejong@redhat.com>

	* win/configure.in: TCL_STUB_LIB_FLAG should not include ${TCL_DBGX}
	in win/tclConfig.sh, fix that.

2000-07-25  David Gravereaux  <davygrvy@ajubasolutions.com>

	* doc/Async.3:
	* generic/tclAsync.c:
	* generic/tclInt.decls:
	* generic/tclIntPlatDecls.h:
	* generic/tclStubInit.c:
	* generic/tclTest.c:
	* mac/tclMacPort.h:
	* unix/tclUnixPort.h:
	* win/tclWinInit.c: Thread-safe rewrite for tclAsync.c. Added notifier
	alerting on all platforms as it was only working on Win before.
	Removed older Win hacks that would end-up waking the wrong notifier in
	the presence of a threaded build. All tests pass as before. New test
	cases will be added soon for the new behavior. [BUG: 5791]

2000-07-25  Eric Melski  <ericm@ajubasolutions.com>

	* generic/tclVar.c (CallTraces): Added check for VAR_TRACE_ACTIVE on
	the array containing the variable before executing traces on that
	array, to conform with normal variable traces and the documentation,
	which states that while executing a trace, other traces on that
	variable are disabled. [Bug: 6049].

	* win/tclWinPipe.c (BuildCommandLine): Added Tcl_DStringFree call to
	prevent potential memory leaks [Bug: 6041].

2000-07-24  Eric Melski  <ericm@ajubasolutions.com>

	* doc/msgcat.n: Added documentation about the selection of the default
	locale on Windows.

2000-07-23  Joe English  <jenglish@flightlab.com>

	* doc/AddErrInfo.3:
	* doc/ChnlStack.3:
	* doc/Exit.3:
	* doc/GetIndex.3:
	* doc/Notifier.3:
	* doc/Object.3:
	* doc/RegExp.3:
	* doc/SetResult.3:
	* doc/SplitList.3:
	* doc/Thread.3:  Added missing entries to NAME section.

	* doc/AddErrInfo.3:
	* doc/CrtObjCmd.3:
	* doc/RecEvalObj.3: Changed Tcl_EvalObj to Tcl_EvalObjEx

2000-07-21  Eric Melski  <ericm@ajubasolutions.com>

	* generic/tclStubInit.c:
	* generic/tclObj.c:
	* generic/tclInt.h:
	* generic/tclHash.c:
	* generic/tclDecls.h:
	* generic/tcl.h:
	* generic/tcl.decls:
	* doc/Hash.3: Reapplied patch from Paul Duffin to extend hash tables
	to allow custom key types, such as Tcl_Obj *'s, and others.

	* doc/binary.n: Noted that the example in the introduction assumes a
	32-bit system [Bug: 6035].

2000-07-21  Mo DeJong  <mdejong@redhat.com>

	* win/configure.in: Define ${prefix} and ${exec_prefix} like
	unix/configure.in. Fix or add TCL_SRC_DIR, TCL_STUB_LIB_FILE,
	TCL_STUB_LIB_FLAG, TCL_BUILD_STUB_LIB_SPEC, TCL_STUB_LIB_SPEC,
	TCL_BUILD_STUB_LIB_PATH, TCL_STUB_LIB_PATH.

2000-07-20  Eric Melski  <ericm@ajubasolutions.com>

	* generic/tclStubInit.c:
	* generic/tclObj.c:
	* generic/tclInt.h:
	* generic/tclHash.c:
	* generic/tclDecls.h:
	* generic/tcl.h:
	* generic/tcl.decls:
	* doc/Hash.3: Reverted patch from Paul Duffin to extend hash tables to
	allow custom key types, such as Tcl_Obj *'s, and others; it seems to
	break Tk.

2000-07-19  Eric Melski  <ericm@ajubasolutions.com>

	* generic/tclStubInit.c:
	* generic/tclObj.c:
	* generic/tclInt.h:
	* generic/tclHash.c:
	* generic/tclDecls.h:
	* generic/tcl.h:
	* generic/tcl.decls:
	* doc/Hash.3: Applied patch from Paul Duffin to extend hash tables to
	allow custom key types, such as Tcl_Obj *'s, and others.

	* tests/pkgMkIndex.test: Added tests for pkg_compareExtension.

	* library/package.tcl: Enhanced pkg_compareExtension to handle Unixes
	which tack the version number on to the end of library names (eg,
	foo.so.1.2); such filenames will be correctly matched. (Patch from
	Vince Darley).

	* win/makefile.vc: Applied patch from Don Porter to provide better
	nmake support for NT/Alpha [RFE: 5938].

2000-07-18  Mo DeJong  <mdejong@redhat.com>

	* unix/configure.in:
	* unix/tcl.m4:
	* win/tcl.m4: Properly quote arguments to m4 macros. This allows Tcl
	to work with the new version of autoconf.

2000-07-18  Eric Melski  <ericm@ajubasolutions.com>

	* tests/opt.test: Removed references to Lfirst, Lrest functions.

	* library/opt0.4/optparse.tcl: Applied patch from Chris Nelson, which
	replaces the [Lfirst] function with an inline [lindex ... 0] and
	[Lrest] with [lrange ... 1 end], for better performance. [RFE: 6019]

2000-07-18  Eric Melski  <ericm@scriptics.com>

	* compat/string.h: Fixed function prototypes for strpbrk and strtok
	[Bug: 6020].

2000-07-17  David Gravereaux  <davygrvy@ajubasolutions.com>

	* win/tclWinChan.c: Win2K OS bug with GetStdHandle(STD_OUTPUT_HANDLE)
	giving the wrong answer. This made TclpGetDefaultStdChannel grab what
	it thought was a valid native stdout handle. Added a new WriteFile()
	test to make sure it's really valid. This OS bug doesn't affect the
	shells. Only -subsystem:windows (aka WinMain) application that
	dynamically load tclXX.dll [BUG: 5971]

2000-07-17  Eric Melski  <ericm@scriptics.com>

	* library/msgcat1.0/msgcat.tcl:
	* doc/msgcat.n:
	* tests/msgcat.test: Applied patches from Chris Nelson, to provide the
	mcmset function, which allows the translator to set multiple string
	translations in a single function call, rather than requiring many
	calls to mcset. [RFE: 6000, 5993]. In addition, these patches correct
	mcload to use utf-8 encoding on when reading message catalog files,
	and provides for better default behavior for determining the locale on
	a Windows system.

2000-07-17  Mo DeJong  <mdejong@redhat.com>

	* unix/tcl.m4 (SC_ENABLE_GCC): Don't set CC=gcc before running
	AC_PROG_CC if CC is already set.

2000-07-13  André Pönitz <poenitz@mathematik.tu-chemnitz.de>

	* doc/lappend.n:
	* doc/lindex.n:
	* doc/linsert.n:
	* doc/list.n:
	* doc/llength.n:
	* doc/lrange.n:
	* doc/lreplace.n:
	* doc/lsearch.n:
	* doc/lsort.n: Added SEE ALSO sections.

2000-07-07  Mo DeJong  <mdejong@redhat.com>

	* win/configure.in: Fix definition of TCL_SRC_DIR so that it matches
	the Unix version.
	* win/tclConfig.sh.in: Removed duplicate variables.

2000-07-06  Eric Melski  <ericm@scriptics.com>

	* tests/msgcat.test:
	* library/msgcat1.0/msgcat.tcl: Applied patch from Christian Krone, to
	provide extended args support for msgcat::unknown, which is used for
	strings without a known translation in the current locale [Bug: 5984].

2000-06-29  Eric Melski  <ericm@scriptics.com>

	* doc/msgcat.n: Doc's for mcmax function.

	* library/msgcat1.0/msgcat.tcl: Applied patches from Laurent Duperval,
	to add mcmax function, which computes the length of the longest of
	several translated strings. Bumped version number to 1.1.

2000-06-27  Eric Melski  <ericm@scriptics.com>

	* tests/stringObj.test: Tweaked tests to avoid hardcoded high-ASCII
	characters (which will fail in multibyte locales); instead used \uXXXX
	syntax. [Bug: 3842].

2000-06-26  Eric Melski  <ericm@scriptics.com>

	* doc/package.n: Corrected information about [package forget]
	arguments [Bug: 5418].

2000-06-23  Eric Melski  <ericm@scriptics.com>

	* doc/Hash.3: Added documentation patch for Tcl_Obj *'s as keys in Tcl
	hash tables [RFE: 5934].

	* generic/tcl.h:
	* generic/tclHash.c: Applied patch from [RFE: 5934], which extends Tcl
	hash tables to allow Tcl_Obj *'s as the key.

2000-06-20  Eric Melski  <ericm@ajubasolutions.com>

	* tests/opt.test:
	* library/opt0.4/optparse.tcl: Applied patch from [Bug: 5922], which
	corrected an incorrect use of [string match].

	* unix/tclConfig.sh.in:
	* win/tclConfig.sh.in: Applied patch from [Bug: 5921], which corrects a
	typo in the comments in these files.

2000-06-19  Eric Melski  <ericm@scriptics.com>

	* doc/RegExp.3: Replaced instances of "Tcl_GetRegExpInfo" with
	"Tcl_RegExpGetInfo", the correct name of the function [Bug: 5901].

2000-06-13  Eric Melski  <ericm@scriptics.com>

	* win/tcl.m4:
	* win/configure.in:
	* win/Makefile.in: Applied patch from [RFE: 5844], to extend support
	for mingw compile environment on Windows.

	* win/tclWinDde.c:
	* win/tclWinInit.c:
	* win/tclWinNotify.c:
	* win/tclWinPipe.c:
	* win/tclWinReg.c:
	* win/tclWinThrd.c: Applied patch from [Bug: 5794], to fix compiler
	warnings when using mingw on Windows.

2000-05-31  Jeff Hobbs  <hobbs@scriptics.com>

	* tests/set-old.test:
	* doc/unset.n:
	* generic/tclVar.c (Tcl_UnsetObjCmd): added -nocomplain and -- options
	to unset, to allow for a silent unset operation.

2000-05-31  Eric Melski  <ericm@scriptics.com>

	* generic/tclVar.c (Tcl_ArrayObjCmd): Added support for regexp and
	exact matching for [array names] command. [RFE: 3684].

	* doc/array.n: Added documentation for [array names
	-exact/-regexp/-glob] [RFE: 3684].

	* tests/set-old.test: Added tests for [array names
	-exact/-regexp/-glob] [RFE: 3684].

2000-06-06  Jeff Hobbs  <hobbs@scriptics.com>

	8.4a1 RELEASE

	* generic/tclExecute.c (TclExecuteByteCode INST_STR_CMP): added test
	of iResult return from memcmp, as memcmp isn't required to return only
	-1,0,1.

2000-06-03  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): Corrected caching
	of the index ptr to account for offsets != sizeof(char *). [Bug: 5153]

2000-05-29  Sandeep Tamhankar <sandeep@scriptics.com>

	* tests/http.test
	* doc/http.n
	* library/http2.3/http.tcl: Fixed bug 5741, where unsuccessful geturl
	calls sometimes leaked memory and resources (sockets). Also, switched
	around some of the logic so that http::wait never throws an exception.
	This is because in an asynchronous geturl, the command callback will
	probably end up doing all the error handling anyway, and in an
	asynchronous situation, the user expects to check the state when the
	transaction completes, as opposed to being thrown an exception.	For
	the http package, this menas the user can check http::status for
	"error" and http::error for the error message after doing the
	http::wait.

2000-05-27  Jeff Hobbs  <hobbs@scriptics.com>

	* tests/info.test:
	* doc/info.n:
	* generic/tclIOUtil.c (Tcl_EvalFile):
	* generic/tclCmdIL.c (InfoScriptCmd): added ability to set the info
	script return value [info script ?newFileName?]. This will be
	beneficial for virtual file system programs. [Bug: 4225]

2000-05-26  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclCmdMZ.c (Tcl_RegsubObjCmd): reworked to operate in
	Unicode, tweaked for performance.
	(Tcl_StringObjCmd) changed STR_FIRST/STR_LAST error message to
	something more understandable, reworked STR_FIRST, STR_LAST, STR_MAP,
	STR_MATCH, STR_RANGE, STR_REPLACE to operate in Unicode. Removed
	inneffectual STR_RANGE "special" ByteArray support. Optimized STR_MAP
	algorithm, especially optimized for one-pair case. Fixed possible mem
	overrun in STR_INDEX bytearray case.

	* generic/tclCompExpr.c: changed INST_STREQ -> INST_STR_EQ,
	INST_STRNEQ -> INST_STR_NEQ
	* generic/tclCompile.c: added streq, strneq, strcmp, strlen &
	strmatch to the compiled stats instructionTable
	* generic/tclCompile.h: added instructions INST_STR_CMP,
	INST_STR_INDEX, INST_STR_MATCH
	* generic/tclCompCmds.c: added byte compiler support for [string
	compare|match|index].
	* generic/tclExecute.c: Changed INST_STR_(N)EQ to return an Int object
	and not bother trying to reuse the top stack object. Added
	INST_STR_CMP, INST_STR_INDEX, INST_STR_MATCH bytecode ops. Extended
	evalstats output info with Tcl_IsShared stat info.

	* generic/tclInt.h:
	* generic/tclObj.c (Tcl_DbIsShared): added support for checking result
	of Tcl_IsShared in evalstats (TCL_COMPILE_STATS).

	* generic/tclStringObj.c (Tcl_AppendUnicodeToObj): removed dead code.
	(AppendUnicodeToUnicodeRep) removed overallocation by extra
	sizeof(Tcl_UniChar) multiplier.

	* tests/string.test: added string map tests for the one-pair case,
	corrected tests to reflect improved error messages in first/last.
	Added tests against mem overrun in string index bytearray case.

2000-05-23  Eric Melski  <ericm@scriptics.com>

	* generic/tclInt.h: Added function prototypes for TclCompileStringCmd
	and TclCompileReturnCmd.

	* generic/tclCompile.h: Added definition of INST_STRLEN opcode and
	updated LAST_INST_OPCODE value.

	* generic/tclBasic.c: Added information about TclCompileStringCmd and
	TclCompileReturnCmd to BuiltInCmds table.

	* generic/tclExecute.c (TclExecuteByteCode): Added support for the
	INST_STRLEN opcode.

	* generic/tclCompCmds.c (TclCompileStringCmd): Basic implementation of
	byte-compiled [string] command. Not all subcommands are implemented;
	those that are not an out-line compiled.

	(TclCompileReturnCmd): Byte-compiled implementation of [return]
	command. Only "simple" returns are byte-compiled; in particular, if
	the -code, -errorinfo or -errorcode flags are used, the command is not
	byte-compiled.

2000-05-22  Jeff Hobbs  <hobbs@scriptics.com>

	* doc/scan.n:
	* doc/array.n: minor doc fixes [Bug: 5396]

	* generic/tclEnv.c: cast cleanup [Bug: 5624]
	* win/tclWinConsole.c: cast and header cleanup [Bug: 5625]
	* win/tclWinSerial.c: cast cleanup [Bug: 5626]
	* win/tclWinFCmd.c: cast cleanup [Bug: 5627]

2000-05-19  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclTest.c:
	* generic/tclIO.c: moved channel test commands from tclIO.c to
	tclTest.c.
	* generic/tclIO.h: new file, split out from tclIO.c to allow test
	commands to be moved to tclTest.c.

	* generic/tclStubInit.c:
	* generic/tclIntDecls.h:
	* generic/tclInt.decls: removed TclTestChannel*Cmd from internal stubs
	table and added TclChannelEventScriptInvoker to the internal stubs
	table so it can be used from the test code.

2000-05-18  Eric Melski  <ericm@scriptics.com>

	* tests/clock.test: Added test for "2 days 2 hours ago" style
	specifications.

	* generic/tclDate.c: Regenerated from tclGetDate.y.

	* generic/tclGetDate.y: Tweaked grammar to properly handle the "ago"
	keyword when it follows multiple relative unit specifiers, as in "2
	days 2 hours ago". [Bug: 5497]

2000-05-18  Jeff Hobbs  <hobbs@scriptics.com>

	* win/{tcl.m4,Makefile.in,configure.in}: added support for mingw
	compile env and cross-compiling. [Bug: 5499]

	* generic/tclClock.c (FormatClock): correct code to handle locale
	specific return values from strftime, if any. [Bug: 3345]

	* unix/tclUnixInit.c (TclpSetInitialEncodings): attempt to correct
	setlocale calls for XIM support and locale issues. [BUG: 5422 3345
	4236 2522 2521]

2000-05-17  Jeff Hobbs  <hobbs@scriptics.com>

	* library/init.tcl (auto_import): added check to see if a valid
	pattern was coming in, to avoid simple error cases [Bug: 3326]

	* doc/regsub.n: correct regsub docs [Bug: 5346]

2000-05-15  Eric Melski  <ericm@scriptics.com>

	* library/history.tcl: Corrected an off-by-one error in HistIndex,
	which was causing [history redo] to start its search at the wrong
	event index. [Bug: 1269].

2000-05-10  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclPosixStr.c (Tcl_SignalMsg): clarified #defines for Linux
	on Sparc to compile correctly. [Bug: 5364]

	* doc/namespace.n:
	* tests/namespace.test:
	* generic/tclNamesp.c (Tcl_NamespaceObjCmd): added 'namespace exists'
	command. [Bug: 4665]

	* doc/source.n:
	* doc/Eval.3:
	* tests/source.test:
	* generic/tclIOUtil.c (Tcl_EvalFile): added explicit \32 (^Z) eofchar
	(affects Tcl_EvalFile in C, "source" in Tcl). This was implicit on
	Windows already, and is now cross-platform to allow for scripted
	documents.

2000-05-09  Andreas Kupries  <a.kupries@westend.com>
	operating as proxy for David Gravereaux <davygrvy@pobox.com>

	* win/tclWinThrd.c (TclpInitLock, TclpMasterLock): Added missing
	initialization of joinLock.

2000-05-09  Eric Melski  <ericm@scriptics.com>

	* tests/lsearch.test:
	* doc/lsearch.n:
	* generic/tclCmdIL.c (Tcl_LsearchObjCmd): Extended [lsearch] to
	support sorted list searching and typed list searching. [RFE: 4098].

2000-05-08  Jeff Hobbs  <hobbs@scriptics.com>

	* doc/expr.n:
	* tests/expr.test:
	* tests/expr-old.test: added tests for 'eq' and 'ne'
	* generic/tclExecute.c:
	* generic/tclCompile.h: added INST_STREQ and INST_STRNEQ opcodes that
	do strict string comparisons.
	* generic/tclCompExpr.c: added 'eq' and 'ne' string comparison
	operators.
	* generic/tclParseExpr.c (GetLexeme): added 'eq' and 'ne' expr parse
	terms (string (in)equality check).

	* generic/tclCmdIL.c (Tcl_LinsertObjCmd): made use of
	Tcl_DuplicateObj where code was otherwise duplicated. Made special
	case of inserting one element at the end work again (where index ==
	len).
	(Tcl_LreplaceObjCmd): moved Tcl_DuplicateObj call lower and cleaned
	up use of other arguments.

	* generic/tclObj.c (Tcl_DuplicateObj): simplified code to call
	TclInitStringRep, which the code was just duplicating in part.

	* doc/Utf.3:
	* generic/tclStubInit.c:
	* generic/tcl.decls:
	* generic/tclDecls.h:
	* generic/tclUtf.c: Added new functions Tcl_UniCharNcasecmp and
	Tcl_UniCharCaseMatch (unicode parallel to Tcl_StringCaseMatch)
	* generic/tclUtil.c: rewrote Tcl_StringCaseMatch algorithm for
	optimization and made Tcl_StringMatch just call Tcl_StringCaseMatch
	* tests/string.test: extended string match tests

2000-05-08  Eric Melski  <ericm@scriptics.com>

	* tests/set-old.test:
	* doc/array.n:
	* generic/tclVar.c: Added [array statistics] command [RFE: 4557]

2000-05-06  Andreas Kupries <a.kupries@westend.com>
	operating as proxy for David Gravereaux <davygrvy@pobox.com>

	* tclThreadJoin.c: Fixed several places with missing a & in arguments
	to calls of Tcl_Mutex(Un)lock and Tcl_ConditionNotify functions.

2000-05-02  Jeff Hobbs  <hobbs@scriptics.com>

	* README:
	* generic/tcl.h:
	* library/init.tcl:
	* library/reg1.0/pkgIndex.tcl:
	* library/tcltest1.0/tcltest.tcl:
	* mac/README:
	* tools/tcl.hpj.in:
	* tools/tcl.wse.in:
	* unix/README:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/README:
	* win/README.binary:
	* win/configure.in:
	* win/makefile.vc:
	* win/tcl.m4: updated patchlevel to 8.4a1

	* tests/compile.test:
	* tests/init.test:
	* tests/proc.test:
	* tests/proc-old.test:
	* tests/rename.test:
	* generic/tclProc.c: reworked error return for procedures with
	incorrect args to be like the C Tcl_WrongNumArgs, where a "wrong #
	args: ..." message is printed out with the args list.

	* unix/Makefile.in: add tclsh.ico and tcl.spec to dist target

2000-05-02  Andreas Kupries <a.kupries@westend.com>

	Overall changes:
	  (1) Implementation of joinable threads for all platforms.
	  (2) Additional API's for channels. Required to allow the thread
	      extension to move channels between threads.

	* generic/tcl.decls (lines 1360f): Added Tcl_JoinThread,
	Tcl_IsChannelShared, Tcl_IsChannelRegistered, Tcl_CutChannel,
	Tcl_SpliceChannel, Tcl_IsChannelExisting and Tcl_ClearChannelHandlers
	(slots 394 to 400).

	* generic/tclIO.c: Implemented Tcl_IsChannelRegistered,
	Tcl_IsChannelShared, Tcl_CutChannel, Tcl_SpliceChannel,
	Tcl_IsChannelExisting and Tcl_ClearChannelHandlers.  Tcl_CutChannel
	uses code from CloseChannel. Replaced this code by a call to
	Tcl_CutChannel. Replaced several code fragments adding channels to
	the channel list with calls to Tcl_SpliceChannel. Removed now unused
	variables from CloseChannel and Tcl_UnstackChannel.
	Tcl_ClearChannelHandlers uses code from Tcl_Close. Replaced this code
	by a call to Tcl_ClearChannelHandlers. Removed now unused variables
	from Tcl_Close. Added the subcommands 'cut', 'forgetch', 'splice' and
	'isshared' to the test code (TclTestChannelCmd).

	* unix/tclUnixThread.c: Implemented Tcl_JoinThread using the
	pthread-functionality.

	* win/tclWinThrd.c: Fixed several small typos in comments.
	Implemented Tcl_JoinThread using a platform independent emulation
	layer (see generic/tclThreadJoin.c below). Added 'joinLock' to
	serialize Tcl_CreateThread and TclpExitThread to prevent a race for
	joinable threads.

	* mac/tclMacThrd.c: Implemented Tcl_JoinThread using a platform
	independent emulation layer (see generic/tclThreadJoin.c below). Due
	to the cooperative nature of threading on this platform the race
	mentioned above is not present.

	* generic/tclThreadJoin.c: New file. Contains a platform independent
	emulation layer helping in the implementation of joinable threads for
	the win and mac platforms.

	* generic/tclInt.h: Added declarations for TclJoinThread,
	TclRememberJoinableThread and TclSignalExitThread. These procedures
	define the API of the emulation layer for joinable threads (see
	generic/tclThreadJoin.c above).

	* win/Makefile.in:
	* win/makefile.vc: Added generic/tclTheadJoin.o to the rules.

	* mac/: I don't know to which file generic/tclTheadJoin.o has to be
	added to so that it compiles. Sorry.

	* unix/tclUnixChan.c: #ifdef'd the thread-local list of file channels
	as it prevents us from transfering channels. To restore this we may
	need an extended interface to drivers in the future. Target:
	9.0. Found while testing the new transfer of channels. The information
	in this list for a channel was left behind and then crashed the system
	during finalization.

	* generic/tclThreadTest.c: Added -joinable flag to 'testthread
	create'. Added subcommand 'testthread join'.

	* doc/CrtChannel.3: Added documentation for Tcl_IsChannelRegistered,
	Tcl_IsChannelShared, Tcl_CutChannel, Tcl_SpliceChannel,
	Tcl_IsChannelExisting and Tcl_ClearChannelHandlers.

	* doc/Thread.3: Added documentation for Tcl_JoinThread.

	* tests/thread.test: Added tests for joining of threads.

2000-04-27  Eric Melski  <ericm@scriptics.com>

	* doc/library.n: Added entries for auto_qualify and auto_import
	[Bug: 1271].

	* doc/Init.3: Manual entry for Tcl_Init [Bug: 1820].

	* doc/expr.n: Added documentation for each of the math library
	functions that expr supports [Bug: 1054].

2000-04-26  Eric Melski  <ericm@scriptics.com>

	* doc/memory.n: Man page for Tcl "memory" command, which is created
	when TCL_MEM_DEBUG is defined at compile time.

	* doc/TCL_MEM_DEBUG.3: Man page with overall information about
	TCL_MEM_DEBUG usage.

	* doc/DumpActiveMemory.3: Man page for Tcl_DumpActiveMemory,
	Tcl_InitMemory, and Tcl_ValidateAllMemory [Bug: 1816, 1835].

	* generic/tclCkalloc.c: Fixed some function headers.

	* unix/mkLinks: Regen'd with new mkLinks.tcl.

	* unix/mkLinks.tcl: Fixed indentation, made link setup more
	intelligent (only do one existance test per man page, instead of one
	per function).

	* doc/library.n: Fixed .SH NAME macro to include each function
	documented on the page, so that mkLinks will know about the functions
	listed there, and so that the Windows help file index will get set up
	correctly [Bug: 1898, 5273].

2000-04-26  Jeff Hobbs  <hobbs@scriptics.com>

	8.3.1 RELEASE

	* README:
	* mac/README:
	* tools/tcl.wse.in:
	* unix/README:
	* unix/tcl.spec:
	* win/README:
	* win/README.binary: Updating URLs to reference dev.scriptics.com

2000-04-25  Jeff Hobbs  <hobbs@scriptics.com>

	* unix/Makefile.in:
	* win/Makefile.in:
	* win/makefile.vc: updated for http change and some cleanup
	* library/http2.[13]: moved dir http2.1 to http2.3 to match version

	* doc/Utf.3: clarified docs for Tcl_(UniChar|Utf)AtIndex

	* unix/tclUnixThrd.c: removed {}s around PTHREAD_MUTEX_INITIALIZER
	[Bug: 5254]

	* unix/tclLoadDyld.c (TclpLoadFile): removed use of interp->result

2000-04-25  Eric Melski  <ericm@scriptics.com>

	* unix/mkLinks:
	* doc/AddErrInfo.3: Added information about Tcl_LogCommandInfo
	[Bug: 1818].

2000-04-24  Eric Melski  <ericm@scriptics.com>

	* unix/mkLinks:
	* doc/OpenFileChnl.3: Added man entry for Tcl_Ungets [Bug: 1834].

	* unix/mkLinks:
	* doc/SourceRCFile.3: Man page for Tcl_SourceRCFile [Bug: 1833].

	* unix/mkLinks:
	* doc/ParseCmd.3: Added documentation for Tcl_ParseVar [Bug: 1828].

2000-04-24  Jeff Hobbs  <hobbs@scriptics.com>

	* unix/tclUnixNotfy.c (Tcl_FinalizeNotifier, NotifierThreadProc):
	added write of 'q' into triggerPipe for notifier in threaded case, so
	that Tcl doesn't hang when children are still running [Bug: 4139]

	* unix/tclUnixThrd.c (Tcl_MutexLock): minor comment fixes.

2000-04-23  Jim Ingham  <jingham@cygnus.com>

	These changes make some error handling marginally better for Mac
	sockets. It is still somewhat flakey, however.

	* mac/tclMacSock.c (TcpClose): Add timeouts to the close - these don't
	seem to be honored, however. Use a separate PB for the release, since
	an async connect socket will still be using the original buffer. Make
	sure TCPRelease returns noErr before freeing the recvBuff. If the call
	returns an error, then the buffer is not right.
	* mac/tclMacSock.c (CreateSocket): Add timeouts to the async create.
	These don't seem to trigger, however. Sigh...
	* mac/tclMacSock.c (WaitForSocketEvent): If an TCP_ASYNC_CONNECT
	socket errors out, then return EWOULDBLOCK & error out.
	* mac/tclMacSock.c (NotifyRoutine): Added a NotifyRoutine for
	experimenting with MacTCP.

2000-04-22  Jim Ingham <jingham@cygnus.com>

	* library/package.tcl (tclPkgUnknown): Fixed a typo in the Mac package
	search part of tclPkgUnknown.

2000-04-21  Sandeep Tamhankar <sandeep@scriptics.com>

	* library/http2.1/http.tcl: Fixed a newly introduced bug where if
	there's a -command callback and something goes wrong, geturl threw an
	exception, called the callback, and unset the token. I changed it so
	that it will not call the callback when throwing an exception (so the
	caller only finds out about a given error from one place).  Also,
	fixed http::ncode so that it actually gives you back the http return
	code (i.e. 200, 404, etc.) instead of the first digit of the version
	of HTTP being used (i.e. 1).

2000-04-21  Brent Welch <welch@scriptics.com>

	* library/http2.1/http.tcl: More thrashing with the "server closes
	without reading post data" scenario. Reverted to the previous filevent
	configuratiuon, which seems to work better with small amounts of post
	data.

2000-04-20  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclAlloc.c: wrapped caddr_t define to not be done on Unix
	* unix/tclUnixPort.h: added Tclp*Alloc defines to allow the use of
	USE_TCLALLOC on Unix. [Bug: 4731]

2000-04-19  Jeff Hobbs  <hobbs@scriptics.com>

	* library/dde1.1/pkgIndex.tcl:
	* library/reg1.0/pkgIndex.tcl:
	* win/tclWinChan.c:
	* win/tclWinThrd.c: converted CRLF to LF the */tcl.hpj.in files were
	not converted, as it confuses hcw locally. [Bug: 5096]

	* win/Makefile.in: expanded cleanup target for help files

	* doc/Thread.3: minor macro cleanup

	* generic/tclFileName.c (SplitUnixPath): added support for QNX node
	ids.

2000-04-18  Jeff Hobbs  <hobbs@scriptics.com>

	* README:
	* generic/tcl.h:
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/configure.in:
	* win/README.binary: bumped version to 8.3.1

	* win/tcl.hpj.in: updated copyright date

	* generic/tclEnv.c: environment support for Mac OS/X
	* unix/tclUnixPort.h: environment support for Mac OS/X
	* unix/tclLoadDyld.c: new file for Mac OS/X dl functions
	* unix/Makefile.in: added install-strip target; bindir, libdir,
	mandir, includedir vars; tclLoadDyld.c target [Bug: 2527]

	* unix/tclUnixChan.c (CreateSocket): force a socket back into blocking
	mode (default state) after a -async connect succeeds. [Bug: 4388]

	* generic/tclEvent.c (TclInitSubsystems): Moved tclLibraryPath to
	thread-local storage to prevent thread-related race condition.
	[Bug: 5033]
	* unix/tclAppInit.c (main): removed #ifdef TCL_TEST that sets the
	library path as it was unnecessary and conflicts with move of
	tclLibraryPath to thread-local storage.

2000-04-18  Scott Redman  <redman@scriptics.com>

	* win/Makefile.in:
	* win/tcl.rc:
	* win/tclsh.rc:
	* win/tclsh.ico:  Modified copyright dates in Windows resource files.
	Added an icon for tclsh.exe.

2000-04-17  Brent Welch <welch@scriptics.com>

	* generic/tcl.h, generic/tclThreadTest.c, unix/tclUnixThrd.c,
	* win/tclWinThread.c, mac/tclMacThread.c: Added Tcl_CreateThreadType
	and TCL_RETURN_THREAD_TYPE macros for declaring the NewThread callback
	proc.

2000-04-14  Jeff Hobbs  <hobbs@scriptics.com>

	* unix/tclUnixChan.c (TtyParseMode): Only allow setting mark/space
	parity on platforms that support it [Bug: 5089]

	* generic/tclBasic.c (Tcl_GetVersion): adjusted use of major/minor to
	not conflict with global decl on some systems [Bug: 2882]

	* doc/AppInit.3:
	* doc/Async.3:
	* doc/BackgdErr.3:
	* doc/CrtChannel.3:
	* doc/CrtInterp.3:
	* doc/CrtMathFnc.3:
	* doc/DString.3:
	* doc/Eval.3:
	* doc/ExprLong.3:
	* doc/GetInt.3:
	* doc/GetOpnFl.3:
	* doc/Interp.3:
	* doc/LinkVar.3:
	* doc/OpenFileChnl.3:
	* doc/OpenTcp.3:
	* doc/PkgRequire.3:
	* doc/RecordEval.3:
	* doc/SetResult.3:
	* doc/SplitList.3:
	* doc/StaticPkg.3:
	* doc/TraceVar.3:
	* doc/Translate.3:
	* doc/UpVar.3:
	* doc/load.n: removed or updated references to interp->result use.

2000-04-13  Jeff Hobbs  <hobbs@scriptics.com>

	* doc/regexp.n: doc clarification [Bug: 5037]
	* doc/update.n: typo fix [Bug: 4996]

	* unix/tcl.m4 (SC_ENABLE_THREADS): enhanced the detection of
	pthread_mutex_init [Bug: 4359] and (SC_CONFIG_CFLAGS) added
	--enable-64bit-vis switch for Sparc VIS compilation [Bug: 4995]

2000-04-12  Jeff Hobbs  <hobbs@scriptics.com>

	* doc/dde.n: corrected dde poke docs. [Bug: 4991]

2000-04-11  Eric Melski  <ericm@scriptics.com>

	* win/tclWinPipe.c: Added "CONST" keyword to declaration of char
	*native in TclpCreateTempFile, to supress compiler warnings.

2000-04-10  Brent Welch <welch@scriptics.com>

	* generic/tcl.h: Fixed Tcl_CreateThread declaration.
	* library/tcltest1.0/tcltest.tcl: Fixed the "mainThread"
	initialization to work with either testthread or the thread extension
	* unix/tclUnixThrd.c: Fixed compiler warning when compiling with
	-DTCL_THREADS

2000-04-10  Eric Melski  <ericm@scriptics.com>

	* win/tclWinPipe.c (TclpCreateTempFile): Added conversion of contents
	string from UTF to native encoding [Bug: 4030].

	* tests/regexp.test: Added tests for infinite looping in [regexp
	-all].

	* generic/tclCmdMZ.c: Fixed infinite loop bug with [regexp -all]
	[Bug: 4981].

	* tests/*.test: Changed all occurrences of "namespace import
	::tcltest" to "namespace import -force ::tcltest" [Bug: 3948].

2000-04-09  Brent Welch <welch@scriptics.com>

	* lib/httpd2.1/http.tcl: Worked on the "server closes before reading
	post data" case, which unfortunately causes different error cases on
	Solaris, which can read the reply, and Linux and Windows, which cannot
	read anything. This is all in the loop-back case - client and server
	on the same host. Also unified the error handling so the "ioerror"
	status goes away and errors are reflected in a more uniform way.
	Updated the man page to document the behavior.

2000-04-09  Jeff Hobbs  <hobbs@scriptics.com>

	* tests/reg.test (matchexpected): corrected tests to use tcltest
	constraint types to skip certain tests.

	* generic/tclBasic.c (Tcl_SetCommandInfo): comment fix

	* unix/tclUnixThrd.c (Tcl_CreateThread): moved TCL_THREADS ifdef
	inside of func as it is declared for non-threads builds as well. In
	the non-threads case, it always returns TCL_ERROR (couldn't create
	thread).

2000-04-08  Andreas Kupries <a.kupries@westend.com>

	* Overall change: Definition of a public API for the creation of
	new threads.

	* generic/tclInt.h (line 1802f): Removed the definition of
	'TclpThreadCreate'. (line 793f) Removed the definition of
	'Tcl_ThreadCreateProc'.

	* generic/tcl.h (line 388f): Readded the definition of
	'Tcl_ThreadCreateProc'. Added Win32 stuff send in by David Graveraux
	<davygrvy@bigfoot.com> to that too (__stdcall, ...). Added macros for
	the default stacksize and allowed flags.

	* generic/tcl.decls (line 1356f): Added definition of
	'Tcl_CreateThread', slot 393 of the stub table. Two new arguments in
	the public API, for stacksize and flags.

	* win/tclWinThrd.c:
	* mac/tclMacThrd.c: Renamed TclpThreadCreate to Tcl_CreateThread,
	added handling of the stacksize. Flags are currently ignored.

	* unix/tclUnixThrd.c: See above, but handles joinable flag. Ignores
	the specified stacksize if the macro HAVE_PTHREAD_ATTR_SETSTACKSIZE is
	not defined.

	* generic/tclThreadTest.c (line 363): See below.

	* unix/tclUnixNotfy.c (line 210): Adapted to the changes above. Uses
	default stacksize and no flags now.

	* unic/tcl.m4 (line 382f): Added a check for
	'pthread_attr_setstacksize' to detect platforms not implementing this
	feature of pthreads. If it is implemented, configure will define the
	macro HAVE_PTHREAD_ATTR_SETSTACKSIZE (See unix/tclUnixThrd.c too).

	* doc/Thread.3: Added Tcl_CreateThread and its arguments to the list
	of described functions. Removed stuff about not providing a public
	C-API for thread-creation.

2000-04-07  Jeff Hobbs  <hobbs@scriptics.com>

	* doc/binary.n: clarified docs on sign extension in binary scan [Bug:
	3466]

	* library/tcltest1.0/tcltest.tcl (initConstraints): removed win32s
	references (no longer supported)

	* tests/fCmd.test: marked test 8.1 knownBug because it is dangerous on
	poorly configured systems [Bug: 3881] and added 8.2 to keep essence of
	8.1 tested.

2000-04-05  Andreas Kupries <a.kupries@westend.com>

	* generic/tclIO.c (Tcl_UnstackChannel, line 1831): Forcing interest
	mask to the correct value after an unstack and re-initialization of
	the notifier via the watchProc. Without this the first fileevent after
	an unstack will come through and be processed, but no more. [Bug: ??].

2000-03-04  Brent Welch  <welch@scriptics.com>

	* {win,unix}/Makefile.in: added dependency of tclStubInit.c on
	tcl.decls and tclInt.decls
	* generic/tclThread.c: Tweak so this compiles w/out TCL_THREADS
	* generic/{tcl.decls,tclStubInit.c}:  Just touched the tcl.decls and
	regenerated the tclStubInit.c file

2000-03-29  Sandeep Tamhankar <sandeep@scriptics.com>

	* library/http2.1/http.tcl: For the -querychannel option, fconfigure
	the socket to be binary so that we don't translate anything while
	reading the data. This is because we determine the content length of
	the data on the channel by using seek (to the end of the file) and
	tell on the file handle, and we need the content-length to match the
	amount of data actually sent, and translation can affect the number of
	bytes posted.

2000-04-03  Andreas Kupries <a.kupries@westend.com>

	* Overall change: Definition of public API's for the finalization of
	conditions and mutexes. [Bug: 4199].

	* generic/tclInt.h: Removed definitions of TclFinalizeMutex and
	TclFinalizeCondition.

	* generic/tcl.decls: Added declarations of Tcl_MutexFinalize and
	Tcl_ConditionFinalize.

	* generic/tclThread.c: Renamed TclFinalizeMutex to Tcl_MutexFinalize.
	Renamed TclFinalizeCondition to Tcl_ConditionFinalize.

	* generic/tclNotify.c: Changed usage of TclFinalizeMutex to
	Tcl_MutexFinalize.

	* unix/tclUnixNotfy.c:
	* generic/tclThreadTest.c: Changed usages of TclFinalizeCondition to
	Tcl_ConditionFinalize.

	* generic/tcl.h: Added empty macros for Tcl_MutexFinalize and
	Tcl_ConditionFinalize, to be used when the core is compiled without
	threads.

	* doc/Thread.3:	Added description the new API's.

2000-04-03  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclCmdIL.c (InfoVarsCmd): checked for non-NULL procPtr to
	prevent itcl info override crash [Bug: 4064]

	* tests/foreach.test:
	* tests/namespace.test:
	* tests/var.test: Added lsorts to avoid random sorted return
	problems. [Bug: 2682]

	* tests/fileName.test: fixed 14.1 test fragility [Bug: 1482]

	* tools/man2help2.tcl: fixed winhelp cross-linking error [Bug: 4156]
	improved translation to winhelp [Bug: 3679]

	* unix/Makefile.in (MAN_INSTALL_DIR): patch to accept --mandir
	correctly [Bug: 4085]

	* unix/dltest/pkg[a-e].c: Cleaned up test packages [Bug: 2293]

2000-04-03  Eric Melski  <ericm@scriptics.com>

	* unix/tclUnixFCmd.c (SetGroupAttribute):
	* unix/tclUnixFCmd.c (SetOwnerAttribute): Added (uid_t) and (gid_t)
	casts to avoid compiler warnings.

2000-03-31  Eric Melski  <ericm@scriptics.com>

	* generic/tclGet.c (Tcl_GetDouble): Added additional conditions to
	error test (previously only errno was checked, but the return value of
	strtod() should be checked as well). [Bug: 4118]

	* tests/exec.test: Added test for proper conversion of UTF data when
	used with "<< $dataWithUTF" on exec's.

	* unix/tclUnixPipe.c (TclpCreateTempFile): Added
	Tcl_UtfToExternalDString call, so that if there is UTF content in the
	string it will be properly converted to the system encoding before
	being written [Bug: 4030].
	(TclpCreateTempFile): Added a check on the return value of tmpnam;
	some systems (Linux, for example) will start to return NULL after
	tmpnam has been called TMP_MAX times; not checking for this can have
	bad results (overwriting temp files, core dumps, etc.)

2000-03-30  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclBasic.c (Tcl_DeleteCommandFromToken): Added comments
	noting the need to pair ckalloc with ckfree. [Bug: 4262]

	* generic/tclInt.decls:
	* generic/tclIntPlatDecls.h:
	* generic/tclStubInit.c:
	* win/tclWin32Dll.c: removed TclWinSynchSpawn (vestige of Win32s
	support).

	* win/tclWinReg.c: made use of TclWinGetPlatformId instead of getting
	info again

	* win/tclWinPort.h:
	* win/Makefile.in:
	* win/configure.in:
	* win/tcl.m4: Added support for gcc/mingw on Windows [Bug: 4234]

2000-03-29  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclCompile.c (TclCleanupByteCode): made ByteCode cleanup
	more aware of TCL_BYTECODE_PRECOMPILED flagged structs (gen'd by
	tbcload), to correctly clean them up.

	* generic/tclClock.c (FormatClock): moved check for empty format
	earlier, commented 0 result return value

2000-03-29  Sandeep Tamhankar <sandeep@scriptics.com>

	* library/http2.1/http.tcl: Removed an unnecessary fileevent statement
	from the error processing part of the Write method. Also, fixed two
	potential memory leaks in wait and reset, in which the state array
	wasn't being unset before throwing an exception. Prior to this
	version, Brent checked in a fix to catch a fileevent statement that
	was sometimes causing a stack trace when geturl was called with
	-timeout. I believe Brent's fix is necessary because TLS closes bad
	sockets for secure connections, and the fileevent was trying to act on
	a socket that no longer existed.

2000-03-27  Jeff Hobbs  <hobbs@scriptics.com>

	* tests/httpd: removed unnecessary 'puts stderr "Post Dispatch"'

	* tests/namespace.test:
	* generic/tclNamesp.c (Tcl_Export): added a uniq'ing test to the
	export list so only one instance of each export pattern would exist in
	the list.

	* generic/tclExecute.c (TclExecuteByteCode): optimized case for the
	empty string in ==/!= comparisons

2000-03-27  Eric Melski  <ericm@scriptics.com>

	* unix/tclUnixChan.c: Added (off_t) type casts in lseek() call [Bug:
	4409].

	* unix/tclLoadAout.c:
	* unix/tclUnixPipe.c: Added (off_t) type casts in lseek() calls [Bug:
	4410].

2000-03-22  Sandeep Tamhankar <sandeep@scriptics.com>

	* library/http2.1/http.tcl: Fixed a bug where string query data that
	was bigger than queryblocksize would get duplicate characters at block
	boundaries.

2000-03-22  Sandeep Tamhankar <sandeep@scriptics.com>

	* library/http2.1/http.tcl: Fixed bug 4463, where we were getting a
	stack trace if we tried to publish a project to a good host but a port
	where there was no server listening.  It turned out the problem was a
	stray fileevent that needed to be cleared.  Also, fixed a bug where
	http::code could stack trace if called on a bad token (one which
	didn't represent a successful geturl) by adding an http element to the
	state array in geturl.

2000-03-21  Eric Melski  <ericm@scriptics.com>

	* tests/clock.test: Modified some tests that were not robust with
	respect to the time zone in which they were run and were thus failing.

	* doc/clock.n: Clarified meaning of -gmt with respect to -base when
	used with [clock scan] (-gmt does not affect the interpretation of
	-base).

2000-03-19  Sandeep Tamhankar <sandeep@scriptics.com>

	* library/http2.1/http.tcl: geturl used to throw an exception when the
	connection failed; I accidentally returned a token with the error
	info, breaking backwards compatibility. I changed it back to throwing
	an exception, but unsetting the state array first (thus still
	eliminating the original memory leak problem).

2000-03-19  Sandeep Tamhankar <sandeep@scriptics.com>

	* library/http2.1/http.tcl: Added -querychannel option and altered
	some of Brent's modifications to allow asynchronous posts (via
	-command). Also modified -queryprogress so that it calls the query
	callback as <callback> <token> <total size> <current size> to be
	consistent with -progress. Added -queryblocksize option with default
	8192 bytes for post blocksize. Fixed a bunch of potential memory leaks
	for the case when geturl receives bad args or can't open a socket,
	etc. Overall, the package really rocks now.

	* doc/http.n: Added -queryblocksize, -querychannel, and
	-queryprogress. Also, changed the description of -blocksize, which
	states that the -progress callback will be called for each block, to
	now qualify that with an "if -progress is specified".

	* tests/http.test: Added a querychannel test for synchronous and
	asynchronous posts, altered the queryprogress test such that the
	callback conforms to the -progress format. Also, had to use the
	-queryblocksize option to do the post 16K at a time to match Brent's
	expected results (and to test that -queryblocksize works).

2000-03-15  Brent Welch <welch@scriptics.com>

	* library/http2.1/http.tcl: Added -queryprogress callback to
	http::geturl and also changed it so that writing the post data is
	event driven if the queryprogress callback or a timeout is given.
	This allows a timeout to occur when writing lots of post data. The
	queryprogress callback is called after each block of query data is
	posted. It has the same signature as the -progress callback.

2000-03-06  Eric Melski  <ericm@scriptics.com>

	* library/package.tcl: Applied patch from Bug: 2570; rather than
	setting geometry of slave interp to 0x0 when Tk was loaded, it now
	does "wm withdraw .". Both remove the main window from the display,
	but the former caused some internal structures to get initialized to
	zero, which caused crashes with some extensions.

2000-03-02  Jeff Hobbs  <hobbs@scriptics.com>

	* library/package.tcl (tclPkgUnknown): extended to allow recognizes
	changes in the auto_path while sourcing in other pkgIndex.tcl files

	* doc/FindExec.3: fixed doc for declaration of Tcl_FindExecutable
	[Bug: 4275]

	* generic/tclFileName.c (Tcl_TranslateFileName): Applied patch from
	Newman to significantly speedup file split/join on Windows (replaces
	regexp with custom parser). [Bug: 2867]

	* win/README.binary: change mailing lists from @consortium.org to
	@scriptics.com [Bug: 4173]

2000-02-28  Eric Melski  <ericm@scriptics.com>

	* tests/clock.test: Added test for ISO bases < 100000

	* generic/tclDate.c: (generated on Solaris)
	* generic/tclGetDate.y: Changed condition for deciding if a number is
	an ISO 8601 base from number >= 100000 to numberOfDigits >= 6.
	Previously it would fail to recognize 000000 as an ISO base.

2000-02-14  Eric Melski  <ericm@scriptics.com>

	* unix/Makefile.in: Added rpm target to generate Tcl binary RPM.

	* unix/tcl.spec: RPM specification file for a Tcl binary RPM for
	Linux.

2000-02-10  Jeff Hobbs  <hobbs@scriptics.com>

	8.3.0 RELEASE

	* changes: updated for 8.3.0 release

	* doc/load.n: added notes about dll load errors on Windows

	* unix/README:
	* unix/Makefile.in (dist): removed porting.notes and porting.old from
	distribution and CVS.  The information was very outdated. Now refer to
	http://dev.scriptics.com/services/support/platforms.html

	* tests/unixInit.test: fixed japanese LANG encoding test [Bug: 3549]

	* unix/configure.in:
	* unix/tcl.m4: correct CFLAG_WARNING setting, fixed gcc config for
	AIX, added -export-dynamic to LDFLAGS for FreeBSD-3+ [Bug: 2998]

	* win/tclWinLoad.c (TclpLoadFile): improved error message for load
	failures, could perhaps be even more intelligent.

2000-02-09  Jim Ingham	 <jingham@cygnus.com>

	* mac/tclMacSock.c: Don't panic when you get an error closing an async
	socket. This doesn't seem to hurt anything, and we return the error so
	the caller can do the right thing.

	New Files:
	* mac/MW_TclHeader.h:
	* mac/MW_TclTestHeader.h:
	* mac/MW_TclTestHeader.pch:
	* mac/MW_TclAppleScriptHeader.h: More convenient to use .h prefix
	files in the preference panels...

	The above are curtesy of Daniel Steffen (steffen@math.mq.edu.au)

2000-02-08  Eric Melski  <ericm@scriptics.com>

	* tests/clock.test: Added tests for "next monthname" constructs.
	* generic/tclDate.c:
	* generic/tclGetDate.y (Message): Added a grammar rule for "next
	monthname" so that we can handle "next january" and similar constructs
	(bug #4146).

2000-02-08  Jeff Hobbs  <hobbs@scriptics.com>

	* README:
	* tools/tcl.wse.in:
	* unix/configure.in:
	* win/configure.in:
	* win/README:
	* win/README.binary:
	* generic/tcl.h (TCL_RELEASE_SERIAL): Moved to 8.3.0 patchlevel

	* doc/library.n:
	* library/auto.tcl: fixed crufty puts code and docs [Bug: 4122]

	* library/tcltest1.0/tcltest.tcl: correctly protected searchDirectory
	list to allow dirnames with spaces

	* unix/tcl.m4: changed all -fpic to -fPIC

	* generic/tclDecls.h:
	* generic/tcl.decls: change Tcl_GetOpenFile to use decl of 'int
	forWriting' instead of 'int write' to avoid shadowing [Bug: 4121]

	* tests/httpold.test: changed test script to source in the httpd
	server procs from httpd instead of having its own set.

	* tests/httpd: improved query support in test httpd to handle fix in
	http.tcl. [Bug: 4089 change 2000-02-01]

	* unix/README: fixed notes about --enable-shared and add note about
	--disable-shared.

2000-02-07  Eric Melski  <ericm@scriptics.com>

	* tests/package.test:
	* library/tclIndex:
	* library/package.tcl: Renamed ::package namespace to ::pkg.

2000-02-03  Eric Melski <ericm@scriptics.com>

	* doc/Package.n:
	* doc/packagens.n: Renamed Package.n -> packagens.n because Windows
	can't deal with case-sensitive names.

2000-02-02  Jeff Hobbs  <hobbs@scriptics.com>

	* tests/regexp.test: added tests for -all and -inline switches
	* doc/regexp.n: added docs for -all and -inline switches
	* generic/tclCmdMZ.c (Tcl_RegexpObjCmd): added extra comments for new
	-all and -inline switches to regexp command

2000-02-01  Eric Melski  <ericm@scriptics.com>

	* library/init.tcl: Applied patch from rfe 1734 regarding auto_load
	errors not setting error message and errorInfo properly.

2000-02-01  Jeff Hobbs  <hobbs@scriptics.com>

	* win/Makefile.in (install-*): reduced verbosity of install

	* generic/tclFileName.c (Tcl_JoinPath): improved support for special
	QNX node id prefixes in pathnames [Bug: 4053]

	* library/http1.0/http.tcl:
	* library/http2.1/http.tcl: The query data POSTed was newline
	terminated when it shouldn't be altered [Bug: 4089]

2000-01-31  Eric Melski  <ericm@scriptics.com>

	* tests/package.test:
	* library/tclIndex:
	* library/package.tcl: Added ::package namespace and ::package::create
	function.

	* library/init.tcl: Fixed problem with auto_load and determining if
	commands were loaded.

	* library/auto.tcl: "Fixed" issues with $ in files to be auto indexed.

	* doc/Package.n: New man page for package::create function.

	* doc/pkgMkIndex.n: Added additional information.

	* doc/library.n: Added additional qualification regarding auto_mkindex.

2000-01-28  Eric Melski  <ericm@scriptics.com>

	* tests/pkg/magicchar2.tcl:
	* tests/autoMkindex.test: Test for auto loader fix (bug #2480).

	* library/init.tcl: auto_load was using [info commands $name] to
	determine if a given command was available; if the command name had *
	or [] it, this would fail because info commands uses glob-style
	matching. This is fixed. (Bug #2480).

	* tests/pkg/spacename.tcl:
	* tests/pkgMkIndex.test: Tests for fix for bug #2360.

	* library/package.tcl: Fixed to extract only the first element of the
	list returned by auto_qualify (bug #2360).

	* tests/pkg/magicchar.tcl:
	* tests/autoMkindex.test: Test for fix for bug #2611.

	* library/auto.tcl: Fixed the regular expression that performs $
	escaping before sourcing a file to index. It was erroneously adding \
	escapes even to $'s that were already escaped, effectively
	"un-escaping" those $'s. (bug #2611).

2000-01-27  Eric Melski  <ericm@scriptics.com>

	* tests/autoMkindex.test:
	* library/auto.tcl: Applied patch (with slight modification) from bug
	#2701: auto_mkIndex uses platform dependent file paths. Added test for
	fix.

2000-01-27  Jennifer Hom  <jenn@scriptics.com>

	* library/tcltest1.0/tcltest.tcl: Changed NormalizePath to
	normalizePath and exported it as a public proc. This proc creates an
	absolute path given the name of the variable containing the path to
	modify. The path is modified in place.
	* library/tcltest1.0/pkgIndex.tcl: Added normalizePath.
	* tests/all.tcl: Changed code to use normalizePath.

2000-01-27  Eric Melski  <ericm@scriptics.com>

	* tests/pkg/samename.tcl: test file for bug #1983

	* tests/pkgMkIndex.test:
	* doc/pkgMkIndex.n:
	* library/package.tcl: Per rfe #4097, optimized creation of direct
	load packages to bypass computing the list of commands added by the
	new package. Also made direct loading the default, and added a -lazy
	option.
	Fixed bug #1983, dealing with pkg_mkIndex incorrectly handling
	situations with two procs by the same name but in different namespaces
	(ie, foo::baz and bar::baz).

2000-01-26  Eric Melski  <ericm@scriptics.com>

	* generic/tclNamesp.c: Undid fix for #956, which broke backwards
	compatibility.

	* doc/variable.n:
	* doc/trace.n:
	* doc/namespace.n:
	* doc/info.n: Added further information about differences between
	"namespace which" and "info exists".

	* doc/SetErrno.3: Added descriptions of ErrnoId() and ErrnoMsg()
	functions.

2000-01-25  Jeff Hobbs  <hobbs@scriptics.com>

	* unix/tcl.m4: modified EXTRA_CFLAGS to add -DHAVE_TZSET for OSF1-V*
	and ULTRIX-4.* when not using gcc. Also added higher min stack size
	for OSF1-V* when building with threads. [Bug: 4063]

	* generic/tclClock.c (FormatClock): inlined resultPtr, as it
	conflicted with var creation for HAVE_TZSET #def [Bug: 4063]

	* generic/tclCmdIL.c (Tcl_LsortObjCmd): fixed potential leak when
	calling lsort -command with bad command [Bug: 4067]

	* generic/tclFileName.c (Tcl_JoinPath): added support for special QNX
	node id prefixes in pathnames [Bug: 4053]

	* doc/ListObj.3: clarified Tcl_ListObjGetElements docs [Bug: 4080]

	* doc/glob.n: clarified Mac path separator determination docs.

	* win/makefile.vc: added some support for building helpfile on Windows

2000-01-23  Jeff Hobbs  <hobbs@scriptics.com>

	* library/init.tcl (auto_execok): added 'start' to list of recognized
	built-in commands for COMSPEC on NT. [Bug: 2858]

	* unix/tclUnixPort.h: moved include of <utime.h> lower since some
	systems (UTS) require sys/types.h to be included first [Bug: 4031]

	* unix/tclUnixChan.c (CreateSocketAddress): changed comparison with -1
	to 0xFFFFFFFF, to ensure 32 bit comparison even on 64 bit systems.
	[Bug: 3878]

	* generic/tclFileName.c: improved guessing of path separator for the
	Mac. (Darley)

	* generic/tclInt.h:
	* generic/tcl.decls: moved Tcl_ProcObjCmd to stubs table [Bug: 3827]
	and removed 'register' from stub definition of
	Tcl_AppendUnicodeToObj [Bug: 4038]

2000-01-21  Eric Melski  <ericm@scriptics.com>

	* unix/mkLinks:
	* doc/GetHostName.3: Man page for Tcl_GetHostName (bug #1817).

	* doc/lreplace.n: Corrected man page with respect to treatment of
	empty lists, and "prettied up" the page. (bug #1705).

2000-01-20  Eric Melski  <ericm@scriptics.com>

	* tests/namespace.test: Added test for undefined variables with
	namespace which (bug #956).

	* generic/tclNamesp.c: Added check for undefined variables in
	NamespaceWhichCmd (bug #956).

	* tests/var.test: Added tests for corrected variable behavior (bug
	#981).

	* doc/upvar.n: Expanded explanation of upvar behavior with respect to
	variable traces. (bugs 3917 1433 2110).

	* generic/tclVar.c: Changed behavior of variable command when name
	refers to an element in an array (ie, "variable foo(x)") to always
	return an error, regardless of existance of that element in the array
	(now behavior is consistant with docs too) (bug #981).

2000-01-20  Jeff Hobbs  <hobbs@scriptics.com>

	* generic/tclCmdIL.c (InfoBodyCmd): made [info body] return a string
	if the body has been bytecompiled.
	* generic/tclBasic.c (Tcl_EvalObjEx): added pedantic check for
	originating proc body of bytecompiled code, #def'd out as the change
	for [info body] should make it unnecessary

	* unix/tclUnixNotfy.c (Tcl_InitNotifier): added cast for tsdPtr

	* tests/set.test: added test for complex array elem name compiling
	* generic/tclCompCmds.c (TclCompileSetCmd): Fixed parsing of array
	elements during compiling, and slightly optimised same [Bug: 3889]

	* doc/tclvars.n: added definitions for tcl_(non)wordchars

	* doc/vwait.n: added notes about requirement for vwait var being
	globally scoped [Bug: 3329]

	* library/word.tcl: changed tcl_(non)wordchars settings to use new
	unicode regexp char class escapes instead of char sequences

2000-01-14  Eric Melski  <ericm@scriptics.com>

	* tests/var.test: Added a test for the array multiple delete
	protection in Tcl_UnsetVar2.

	* generic/tclVar.c: Added protection in Tcl_UnsetVar2 against attempts
	to multiply delete arrays when unsetting them (bug #3453). This could
	happen if there was an unset trace on an array element and the trace
	proc made a global or upvar link to the array, and then the array was
	unset at the global level. See the bug reference for more information.

	* unix/tclUnixTime.c: New clock format format.

	* compat/strftime.c: New clock format format.

	* generic/tclGetDate.y: New clock scan format.

2000-01-13  Jeff Hobbs  <hobbs@scriptics.com>

	* changes: updated changes file to reflect 8.3b2 mods

	* README:
	* generic/tcl.h:
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.m4:
	* win/README.binary:
	* win/configure.in: updated to patchlevel 8.3b2

	* generic/regexec.c: added var initialization to prevent compiler
	warning

2000-01-13  Eric Melski  <ericm@scriptics.com>

	* tests/cmdIL.test: Added tests for lsort -dictionary with characters
	that occur between Z and a in ASCII.

	* generic/tclCmdIL.c: Modified DictionaryCompare function (used by
	lsort -dictionary) to do upper/lower case equivalency before doing
	character comparisons, instead of after. This fixes bug #1357, in
	which lsort -dictionary [list ` AA c CC] and lsort -dictionary [list
	AA c ` CC] gave different (and both wrong) results.

2000-01-12  Eric Melski  <ericm@scriptics.com>

	* tests/clock.test: Added tests for "next <day-of-week>" and
	"<day-of-week>"
	Added tests for "monday 1 week ago", etc, from RFE #3671.

	* doc/tests/clock.test: Added numerous tests for clock scan.

	* doc/generic/tclGetDate.y: Fixed some shift/reduce conflicts in clock
	grammar.

	* doc/doc/clock.n: Added documentation for new supported clock scan
	formats and additional explanation of daylight savings time correction
	algorithm.

2000-01-12  Jeff Hobbs  <hobbs@scriptics.com>

	* doc/file.n:
	* tests/unixFCmd.test:
	* unix/tclUnixFCmd.c: added support for symbolic permissions setting
	in SetPermissionsAttribute (file attr $file -perm ...) [Bug: 3970]

	* generic/tclClock.c: fixed support for 64bit handling of clock values
	[Bug: 1806]

	* generic/tclThreadTest.c: upped a buffer size to hold double

	* tests/info.test:
	* generic/tclCmdIL.c: fixed 'info procs ::namesp::*' behavior (Dejong)

	* generic/tclNamesp.c: made imported commands also import their
	compile proc [Bug: 2100]

	* tests/expr.test:
	* unix/Makefile.in:
	* unix/configure.in:
	* unix/tcl.m4: recognize strtod bug on Tru64 v5.0 [Bug: 3378] and
	added tests to prevent unnecessary chmod +x in sources while
	installing, as well as more intelligent setsockopt/gethostbyname
	checks [Bug: 3366, 3389]

	* unix/tclUnixThrd.c: added compile time support (through use of the
	TCL_THREAD_STACK_MIN define) for increasing the default stack size for
	a thread. [Bug: 3797, 1966]

2000-01-11  Eric Melski  <ericm@scriptics.com>

	* generic/tclGetDate.y: Added comments for the Convert function. Added
	a fix for daylight savings time handling for relative time spans of
	days, weeks or fortnights. (bug 3441, 3868).

	* generic/tclDate.c: Fixed compiler warning issues.

2000-01-10  Jeff Hobbs  <hobbs@scriptics.com>

	* compat/waitpid.c: use pid_t type instead of int [Bug: 3999]

	* tests/utf.test: fixed test that allowed \8 as octal value
	* generic/tclUtf.c: changed Tcl_UtfBackslash to not allow non-octal
	digits (8,9) in \ooo substs. [Bug: 3975]

	* generic/tcl.h: noted need to change win/tcl.m4 and
	tools/tclSplash.bmp for minor version changes

	* library/http2.1/http.tcl: trim value for $state(meta) key

	* unix/tclUnixFile.c: fixed signature style on functions

	* unix/Makefile.in: made sure tcl.m4 would be installed with dist

	* unix/tcl.m4: added ELF support for NetBSD [Bug: 3959]

2000-01-10  Eric Melski  <ericm@scriptics.com>

	* generic/tclGetDate.y: Added rules for ISO 8601 formats (BUG #847):
	CCYY-MM-DD
	CCYYMMDD
	YY-MM-DD
	YYMMDD
	CCYYMMDDTHHMMSS
	CCYYMMDD HHMMSS
	CCYYMMDDTHH:MM:SS
	Fixed "clock scan <number>" to scan the number as an hour for the
	current day, rather than a minute after 00:00 for the current day
	(bug #2732).

2000-01-07  Eric Melski  <ericm@scriptics.com>

	* generic/tclClock.c: Changed switch in Tcl_ClockObjCmd to use
	enumerated values instead of constants. (ie, COMMAND_SCAN instead of
	3).

Deleted ChangeLog.2001.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
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
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629













































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
2001-12-28  Jeff Hobbs  <jeffh@ActiveState.com>

	* library/init.tcl: make sure env(COMSPEC) on Windows is executed with
	the right case, as it may otherwise fail inexplicably.

2001-12-28  Don Porter <dgp@users.sourceforge.net>

	* generic/tclCkalloc.c (MemoryCmd, TclFinalizeMemorySubsystem): Added
	the [memory onexit] command, intended to replace [checkmem].

	* doc/DumpActiveMemory.3:
	* doc/memory.n: Updated documentation for [memory] and related
	matters. [Bug 487677]

	* mac/tclMacBOAMain.c (Tcl_Main, CheckmemCmd): Removed all the
	machinery for the [checkmem] command that is completely duplicated by
	code in generic/tclCkalloc.c.

	* generic/tclBinary.c:
	* generic/tclListObj.c:
	* generic/tclObj.c:
	* generic/tclStringObj.c: Removed references to [checkmem] in
	comments, referencing [memory active] instead, since it is
	documented.

2001-12-28  Daniel Steffen <das@users.sourceforge.net>

	* mac/tclMacInit.c:
	* mac/tclMacTclCode.r: synced up tclInit features to unix/win:
	implemented TclSetPreInitScript support, use of existing tclInit proc
	if defined, check of default encoding dir if set. Changed script
	library resource names to lowercase (i.e. same as corresponding
	files). Used Tcl_JoinPath instead of string append. Check that system
	encoding could be loaded before utf translating the LibraryPath.
	* mac/tclMacApplication.r:
	* mac/tclMacLibrary.r:
	* mac/tclMacOSA.r:
	* mac/tclMacResource.r: minor version resources cleanup

2001-12-21  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/tcl.m4 (SC_PATH_TCLCONFIG, SC_PATH_TKCONFIG):
	Search for config file using exec_prefix instead of prefix when no
	--with-tcl or --with-tk argument is used. [Bug 492418]

2001-12-21  Daniel Steffen <das@users.sourceforge.net>

	* unix/tcl.m4: fixed incorrect SHLIB_LD_LIBS setting for MacOSX /
	Darwin.
	* unix/configure: Regen.
	* unix/mkLinks.tcl: improved case-insensitive filesystem support.
	* unix/mkLinks: Regen.

2001-12-19  Don Porter <dgp@users.sourceforge.net>

	* unix/Makefile.in (dist): corrected use of eolFix.tcl on working
	files. It should operate on distributed files. [Bug 495120]

2001-12-19  David Gravereaux <davygrvy@pobox.com>

	* tools/tcl.wse.in: Fix for [Bug 495120]. tcl.wse.in was stored in cvs
	with improper <eol>. This resulted in corrupted <eol> when checked-out
	on translating CVS clients such as windows (CRCRLF) and mac (CRCR).

2001-12-19  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure:
	* unix/tcl.m4 (SC_CONFIG_CFLAGS): Update SunOS 5.[0-6] target so that
	correct linker options are passed to gcc or ld. [Tk Bug 220863]

2001-12-19  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/README: Update to account for changes in the unix/dltest
	directory, the way autoconf is run, and the new "make shell" target.

2001-12-19  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/Makefile.in: Rename dltest to dlpkgs to fix problem where lib
	files were not getting built because dltest/ directory already
	existed.

2001-12-19  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/tclWinSerial.c (SerialCheckProc): corrected time calculations to
	be unsigned. (schroedter)

2001-12-18  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/Makefile.in: Define new dltest target that simply does a cd to
	dltest/ before running make. There is no need for the separate
	configure script that was previously being used.
	* unix/configure: Regen.
	* unix/configure.in: Subst into dltest/Makefile.
	* unix/dltest/Makefile.in: Define LIBS using DL_LIBS, LIBS, and
	MATH_LIBS variables instead of TCL_LIBS variable from tclConfig.sh.
	* unix/dltest/README: Update readme to account for new configure free
	implementation.
	* unix/dltest/configure: Removed.
	* unix/dltest/configure.in: Removed.

2001-12-18  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tcl.h (TCL_STUB_MAGIC): Added cast to force type to be an
	int and get rid of a persistent and pointless warning with SunPro
	compiler.

	* generic/tclCkalloc.c (Tcl_AttemptDbCkalloc,Tcl_AttemptDbCkrealloc):
	* generic/tcl.decls (Tcl_AttemptDbCkalloc,Tcl_AttemptDbCkrealloc):
	Made the file parameters to these functions into CONST char *, like
	they always should have been to match the other Tcl*Db* API functions.

2001-12-17  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* Applied [Bug 219311] on behalf of Rolf Schroedter
	<schroedter@users.sourceforge.net> to prevent fcopy on serial ports
	from flooding the event queue.

2001-12-11  Miguel Sofer  <msofer@users.sourceforge.net>

	* doc/CrtInterp.3:
	* generic/tclBasic.c: docs and comments corrections. [Bug 493412]
	Bug & patch by Don Porter.

2001-12-14  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* win/tclWinNotify.c (Tcl_FinalizeNotifier): Stop Tcl on Windows from
	crashing when shutdown from a non-Tcl thread. Fixes [Bug 217982]
	[orig. 5804] reported by Hugh Vu and Gene Leache. I'm not convinced
	that the shutdown process is right even with this, but it was
	definitely wrong without...

2001-12-13  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* win/tclWinSock.c (TcpGetOptionProc): Fix for [Bug 478565] reported
	by an unknown person. Bypasses all calls to "gethostbyaddr" for
	address "0.0.0.0" to prevent delays on Win/NT.

2001-12-12  Jeff Hobbs  <jeffh@ActiveState.com>

	* doc/Preserve.3: doc'd TCL_DYNAMIC use. [Patch 483989] (porter)

2001-12-12  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* generic/tclIO.c (Tcl_GetsObj): Applied patch for [Bug 491341] as
	provided by Don Porter <dgp@users.sourceforge.net>. Fixes the
	assumption of having an empty Tcl_Obj to work with.

2001-12-11  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclCompCmds.c:
	* generic/tclCompile.c:
	* generic/tclExecute.c: consistency patch, to make all instructions
	that pop a variable number of Tcl_Obj's off the execution stack take
	the number of popped objects as first operand. Modified *only* the new
	instructions INST_LIST_INDEX_MULTI and INST_LSET_FLAT, so this has no
	effect on bytecodes generated up to tcl8.4a3 inclusive.

	* generic/tclExecute.c: fix debug messages in INST_LSET_LIST.

	* generic/tclCompCmds.c (TclCompileLindexCmd):
	* generic/tclCompExpr.c (CompileMathFuncCall): removed the last two
	overestimates of the necessary stack depth for bytecodes in the fix of
	[Bug 483611]

2001-12-10  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* unix/tclUnixPipe.c (TclpCreateProcess): Applied Don Porter's patch
	fixing [Bug 437489].

2001-12-10  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclEvent.c:
	* tests/event.test: fix background error reporting in the absence of a
	bgerror proc [Bug 219142].

2001-12-10  Don Porter <dgp@users.sourceforge.net>

	* doc/Access.3:
	* doc/CrtChannel.3:
	* doc/DString.3:
	* doc/ExprLong.3:
	* doc/FileSystem.3:
	* doc/GetStdChan.3:
	* doc/OpenFileChnl.3:
	* doc/StdChannels.3:
	* doc/TCL_MEM_DEBUG.3:
	* doc/Tcl_Main.3:
	* doc/Utf.3:
	* doc/file.n:
	* doc/tclsh.1:  Several typo and formatting corrections discovered
	during conversion to TMML. Thanks to Joe English. [Patch 490514]
	* unix/mkLinks: 'make mklinks'

2001-12-10  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclCompCmds.c:
	* generic/tclCompExpr.c:
	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c:
	* generic/tclProc.c: fixed the calculation of the maximal stack depth
	required by bytecodes. [Bug 483611]

2001-12-07  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclVar.c:
	* tests/trace.test: restored consistency in refCount accounting by
	array traces [Bug 4484339], submitted by Don Porter.

2001-12-06  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/parseExpr.test, tests/for.test, tests/expr.test:
	* tests/expr-old.test, tests/compile.test, tests/compExpr.test
	* tests/compExpr-old.test: Kept up to date with syntax errors.
	* generic/tclParseExpr.c (ParsePrimaryExpr): Rewrote to give even
	better syntax errors in the fairly common case of an identifier
	without decorations by guessing based on the currently available
	functions. Also made messages consistent between memdebug and ordinary
	builds.

2001-12-05  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclVar.c:
	* tests/trace.test: new algorithm for [array get], safe when there are
	traces that modify the array. [Bug 449893]

2001-12-04  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/compExpr-old.test, tests/compExpr.test, tests/compile.test:
	* tests/expr-old.test, tests/expr.test, tests/for.test:
	* tests/while.test, tests/if.test: Rewrite to handle more specific
	syntax errors.
	* tests/parseExpr.test: Rewrite to get rid of dup test numbers and
	handle more specific syntax errors.
	* generic/tclParseExpr.c (LogSyntaxError): Added a detail message
	argument to help explain what the syntax error is.
	(Tcl_ParseExpr, ParseCondExpr, ParsePrimaryExpr): Added detail
	messages.
	(UNKNOWN_CHAR): New lexeme for characters that are always illegal in
	expressions outside strings.

2001-12-03  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/expr.n: Various documentation improvements in relation to the
	function calls. Includes fix for [Bug 487704] submitted by Devin Eyre.

2001-12-03  David Gravereaux <davygrvy@pobox.com>

	* win/makefile.vc: Some install target bugs repaired along with
	$(TCLSTUBLIB) added to the dependencies rather than implicit through
	the dde and reg extensions which don't happen to always require it for
	some build types.

2001-11-30  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclVar.c: Tcl_Preserve'ing VarTrace structures to avoid
	memory corruption. Patch for [Bug 484334] provided by Don Porter

2001-11-29  Miguel Sofer  <msofer@users.sourceforge.net>

	* tests/namespace.test: modified namespace-41.2, added 41.3
	{knownbug} after discussion with Don Porter and Kevin Kenny.

2001-11-29  Miguel Sofer  <msofer@users.sourceforge.net>

	* tests/namespace.test: added namespace-41.2, a simpler test for
	[Bug 231259]

2001-11-29  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclBinary.c (BINARY_SCAN_MAX_CACHE, Tcl_BinaryObjCmd,
	(ScanNumber): Added caching scheme to reduce number of object
	allocations when doing scans of large repetitive binary strings. See
	comments in file for reasoning behind implementation. Suggested by
	Miguel Sofer in [Patch 429916], but independently implemented.

2001-11-28  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/regsub.n, doc/regexp.n: Converted dangling references to
	METASYNTAX section into references to the re_syntax manual page.

2001-11-27  D. Richard Hipp   <drh@hwaci.com>

	* win/tclWinFCmd.c: Fix a coredump in the filename normalizer code for
	Win95/98.

2001-11-27  David Gravereaux <davygrvy@pobox.com>

	* win/makefile.vc: Removed the Tk reference for the 'winhelp' target.
	Converge at install will need to be the solution for Tk and all other
	extensions.

2001-11-27  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/cmdAH.test (cmdAH-24.2): Made test less sensitive to OS
	preemption, but perfection isn't practical. [Bug 463189, reported by
	Don Porter]

	* tests/switch.test (switch-9.*): Added tests to exercise more of the
	argument checking.  (switch-7.2,switch-7.3): Test changed behaviour
	slightly.
	* generic/tclCmdMZ.c (Tcl_SwitchObjCmd): Reworked argument parsing to
	be stricter about what it accepts. This should make uses of the
	[switch] command be more maintainable. [Bug 475397, reported by Don
	Porter]

2001-11-26  Don Porter <dgp@users.sourceforge.net>

	* generic/tclIntPlatDecls.h: 'make genstubs' after changes in
	2001-11-23 commit from Daniel Steffen.

2001-11-24  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/Makefile.in: Add comments to better describe TCL_EXE and when
	it should be available.
	* win/Makefile.in: Add TCL_EXE variable to be used by rules like `make
	genstubs`. Don't set TCL_LIBRARY before running `make genstubs` since
	we will be running with a tclsh from the PATH not the one we build.

2001-11-24  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/configure: Regen.
	* win/tcl.m4 (SC_CONFIG_CFLAGS): Add comctl32.lib to wish link libs.
	This change was originally added to Tk on 2001-11-09 but was not
	committed to Tcl.

2001-11-23  Daniel Steffen <das@users.sourceforge.net>

	* unix/Makefile.in:
	* unix/configure.in:
	* unix/install-sh:
	* unix/mkLinks:
	* unix/mkLinks.tcl:
	* unix/tclLoadDyld.c:
	* unix/tclMtherr.c: Mac OSX support: build system, dynamic code loading
	and support for case-insensitive filesystems in mkLinks. [Patch 435258]

2001-11-23  Daniel Steffen <das@users.sourceforge.net>

	Up-port to 8.4 of mac code changes for 8.3.3 & various new changes for
	8.4, some already backported to 8.3.4. [Patch 435658]

	* generic/tclObj.c: added #include to fix missing prototype errors

	* generic/tcl.h: MAC_TCL: addition of ConditionalMacros.h and use of
	DLLIMPORT and DLLEXPORT like on other platforms. ( => no longer need
	the .exp files and can remove use of #pragma export that never worked
	well)
	removed line continuation in #if clause as this breaks the mac
	resource compiler (note that *.r files include tcl.h)

	* mac/tclMacFile.c: fixed bug in permission checking code

	* mac/tclMacLoad.c: corrected utf-8 handling, comparison of package
	names to code fragment names changed to only match on the length of
	package name, this allows for fragment names with version numbers
	appended.

	* mac/tclMacInt.h:
	* generic/tclInt.h:
	* mac/tclMacTime.c:
	* generic/tclIOUtil.c: moved declaration of TclpGetGMTOffset()

	* mac/tclMacShLib.exp:
	* mac/tclMacOSA.exp:
	* mac/tclMacMSLPrefix.h: removed files

	* unix/Makefile.in: removed reference to .exp files

	* mac/MW_TclBuildLibHeader.h:
	* mac/MW_TclBuildLibHeader.pch:
	* mac/MW_TclHeaderCommon.h:
	* mac/MW_TclStaticHeader.h:
	* mac/MW_TclStaticHeader.pch: new precompiled header files

	* mac/MW_TclAppleScriptHeader.pch:
	* mac/MW_TclHeader.pch:
	* mac/MW_TclTestHeader.pch:
	* mac/tclMacCommonPch.h: revised precompiled header handling: now
	include a common header file 'MW_TclHeaderCommon.h' from all .pch
	files, the .pch files themselves now only setup #defines (e.g.
	BUILD_tcl, STATIC_BUILD, TCL_DEBUG, TCL_THREADS) like in makefiles on
	other platforms.

	* mac/tclMac.h:
	* mac/tclMacPort.h:
	* mac/tclMacInt.h: use of BUILD_tcl and TCL_STORAGE_CLASS like on other
	platforms, standardize #include'd files to what's done on other
	platforms, removed use of #pragma export.

	* mac/tcltkMacBuildSupport.sea.hqx: new archive of mac build support
	files & suggested build environment directory hierarchy:
	'Building MacTclTk' & 'CW Pro6 changes' readme's.
	projects for MoreFiles 1.5.2 static & shared libraries.
	project & sources for 'pseudoCarbonSupport', see below.
	included XML versions of the projects for CW Pro5 or Pro7 users.

	* mac/tclMacProjects.sea.hqx: updated mac build project files:
	build support for CodeWarrior Pro6, UnivIntf 3.4 & shared runtime
	libraries: the MSL libraries and MoreFiles are no longer compiled into
	Tcl.shlb, all non-static binaries now use the Pro6 shared runtime
	libraries and MoreFiles.shlb.  These shlbs are merged into the standard
	Wish and TclShell, but 3rd party applications linking with Tcl.shlb or
	Tk.shlb need to setup access to them.  (see the "(sh-ppc)" targets
	for how to do this.)
	included XML versions of the projects for CW Pro5 or Pro7 users.
	use compat/strtod.c instead of MSL's strtod()
	use WASTE versions of MSL for tcl test target to avoid text buffer
	cutoff at 32k.
	Merging the full MSL.shlb and the other shlbs into Wish & TclShell
	makes them a bit larger than before, use unmerged binaries to avoid
	copying the shared code with every application, e.g. when deploying
	numerous Wish based droplets.
	Note that using CW Pro5 to compile extensions is in principle still
	possible, but need to link with Pro6 runtime libraries.
	Tclapplescript now loads and runs on CFM68k.
	Highly experimental "pseudoCarbon" support for Tcl only on OS 8/9:
	binaries in "Build:(Carbon):" link against CarbonLib instead of
	InterfaceLib, however the actual code has not been carbonized! i.e. it
	will not run on OSX and may not even run properly with CarbonLib.
	This should in principle allow you to build & test OS9 CFM Carbon
	binaries that need to link with Tcl.shlb. On OSX you can use the
	native Tcl.framework, but you have to build a MachO binary as there
	is no CFM glue lib for Tcl.framework.
	the library pseudoCarbonSupport.shlb manually loads the symbols from
	InterfaceLib that are not in CarbonLib but are needed by the
	uncarbonized code in Tcl.shlb and TclShell.

	* generic/tclMain.c: MAC_TCL: workaround for broken/non-standard isatty
	on MW Pro6, #include <unistd.h> instead of defining isatty

	* mac/tclMacPort.h: MW Pro6 changes for MSL fcntl.h, stat.h & isatty

	* mac/tclMacAppInit.c: add EXTERN to InstallConsole to enable DLL
	export via the TCL_STORAGE_CLASS mechanism.

	* mac/tclMacFCmd.c: fix for FSpDirectoryCopy API change

	* mac/tclMacLibrary.c: emit compile time error when
	TCL_REGISTER_LIBRARY and USE_TCL_STUBS are both defined at the same
	time in an extension, this use is not currently supported and will
	result in a crash when dynamically loading the extension.

	* mac/tclMacApplication.r:
	* mac/tclMacLibrary.r:
	* mac/tclMacOSA.r:
	* mac/tclMacResource.r: fixed obsolete copyrights/dates in version
	strings; updated version strings to standard usage; added support for
	'(Support Libraries)' subfolder for shared runtime libraries in
	unmerged binaries; commented out demo setting of "Tcl Environment
	Variables"; reorganized resources among these files to avoid multiple
	copies in applications and shared libraries, the script libraries are
	now no longer duplicated in Tclsh but are only included in the
	resources of Tcl.shlb.

	* mac/tclMacChan.c:
	* mac/tclMacSock.c: cast for *BlockMode

	* mac/tclMacUtil.c:
	* mac/tclMacMath.h: removed obsolete hypot() definition

	* generic/tclIntPlatDecls.h:
	* generic/tclInt.decls:
	* generic/tclStubInit.c:
	* mac/tclMacNotify.c:
	* mac/tclMacOSA.c:
	* mac/tclMacUtil.c:
	* generic/tclThreadTest.c: renamed routines conflicting with standard
	Apple or MoreFiles headers (at compile or link time):
	GetGlobalMouse         -> GetGlobalMouseTcl
	FSpGetDirectoryID      -> FSpGetDirectoryIDTcl
	FSpOpenResFileCompat   -> FSpOpenResFileCompatTcl
	FSpCreateResFileCompat -> FSpCreateResFileCompatTcl
	NewThread              -> NewTestThread
	the renamed MoreFiles *Tcl routines are just wrappers calling into the
	MoreFiles DLL.

	* mac/tclMacCommonPch.h:
	* mac/tclMacThrd.c:
	* mac/tclMacPanic.c: removed OLDROUTINENAMES define, renamed obsolete
	apple API names to modern equivalents; UH3.4 support: added #include
	<ControlDefinitions.h>, updated New*Proc() calls to New*UPP().

	* mac/tclMacUnix.c: added missing (Tcl_Obj ***) cast to
	Tcl_ListObjGetElements call

	* mac/tclMacAlloc.c: modernized TclpSysAlloc() to use temporary memory
	instead of system heap memory when available (MacOS >= 7.5 and
	possibly earlier, use of system heap has been discouraged for a long
	time and has many disadvantages, e.g. memory isn't paged out, and
	errors can very easily bring the system down); fixed crashing bug in
	TclpSysRealloc() and CleanUpExitProc() where memory was being accessed
	after having been deallocated; fixed memory leak in (de)allocation
	code (for every block ever allocated with TclpSysAlloc, a Ptr was
	leaked), if temporary memory is available, don't track allocated
	memory, instead use RecoverHandle() to get Handle from Ptr, otherwise
	use doubly linked list to correctly track memory and free all
	allocated memory; added new option for ConfigureMemory:
	MEMORY_DONT_USE_TEMPMEM, disables use of temporary memory even when it
	would be available, only necessary when writing e.g. a driver (using
	tcl??); increased fraction of application heap reserved for OS
	routines to 512K

	* compat/strftime.c:
	* mac/tclMacTime.c:
	* mac/tclMacPort.h:
	* generic/tclInt.decls:
	* generic/tclIntPlatDecls.h:
	* generic/tclStubInit.c: timezone support for mac via TclpGetTZName()
	like on windows, using an inverse timezone table adapted from
	tclDate.c to map gmtoffset in seconds gotten from the MacOS APIs to a
	timezone string, as there is no good way to get this info from MacOS.
	I had to make up some unusual timezones and arbitrarily decide on the
	most standard of the multiple choices available for every timezone.

	* generic/tclExecute.c: workaround for a MSL bug/misfeature: for very
	small floats, MSL can return errno ERANGE but a non-zero value (<
	LDBL_MIN however)

	* mac/tclMacAppInit.c: support for WASTE text library using temporary
	memory, setting has no effect if WASTE is not used.

	* mac/tclMacPanic.c: removed duplicate code from generic/tclPanic.c
	and added that file to projects instead.

	* tests/all.tcl: set tcltest::singleProcess 1 as multiple processes
	are not available on the mac.

	* tests/cmdAH.test: access time not available on the mac, skip the
	atime touch test

	* tests/appendComp.test:
	* tests/cmdMZ.test:
	* tests/compile.test:
	* tests/exec.test:
	* tests/fileName.test:
	* tests/lset.test:
	* tests/namespace.test:
	* tests/tcltest.test: added missing cleanups/tests/catches that caused
	tests to fail on the mac.

	* doc/tclvars.n: doc bug, env(PWD) should be env(HOME) [Bug 463834]

2001-11-21  Don Porter	<dgp@users.sourceforge.net>

	* tests/trace.test (trace-8.8): Corrected test for Bug 219393.

	* generic/tclBasic.c (Tcl_DeleteCommandFromToken,CallCommandTraces):
	* generic/tclCmdMZ>c (Tcl_UntraceCommand):  Added Tcl_Preserve and
	Tcl_Release calls to prevent deletion of CommandTrace structures until
	all callers are done using them, preventing memory corruption. [Bug
	453805]

2001-11-20  Kevin B. Kenny  <kennykb@users.sourceforge.net>

	* doc/GetTime.3 (Tcl_GetTime):
	* generic/tcl.decls (Tcl_GetTime):
	* generic/tclClock.c (Tcl_ClockObjCmd):
	* generic/tclCompile.c (TclCleanupByteCode, TclInitByteCodeObj):
	* generic/tclCmdMZ.c (Tcl_TimeObjCmd):
	* generic/tclUtil.c (TclpGetTime):
	* generic/tclTest.c (GetTimesCmd):
	* generic/tclTimer.c (Tcl_CreateTimerHandler, TimerSetupProc,
	(TimerCheckProc, TimerHandlerEventProc):
	* mac/tclMacNotify.c (Tcl_SetTimer):
	* mac/tclMacShLib.exp (Tcl_GetTime):
	* mac/tclMacTime.c (Tcl_GetTime):
	* unix/tclUnixChan.c (TclUnixWaitForFile):
	* unix/tclUnixEvent.c (Tcl_Sleep):
	* unix/tclUnixThrd.c (Tcl_ConditionWait):
	* unix/tclUnixTime.c (Tcl_GetTime):
	* win/tclWinNotify.c (Tcl_Sleep):
	* win/tclWinTest.c (TestwinclockCmd):
	* win/tclWinTime.c (TclpGetSeconds, TclpGetClicks, Tcl_GetTime):
	Changed all uses of TclpGetTime to Tcl_GetTime. Added Tcl_GetTime to
	the Stubs table and the library documentation. Added a TclpGetTime in
	tclUtil.c for backward compatibility of extensions. [Patch 483500,
	TIP#73]

	* generic/tclCmdMZ.c (Tcl_TimeObjCmd): Corrected an error in the
	[time] command that caused incorrect results to be returned if the
	total duration of all iterations exceeded 2**31 microseconds. [Bug
	478847]

	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclStubInit.h: Reran 'make genstubs'

2001-11-20  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclBasic.c
	* generic/tclCompile.h:
	* generic/tclExecute.c: moving all code relative to bytecodes from
	tclBasic.c to tclExecute.c - the functions RecordTracebackInfo and
	Tcl_ExprObj went to tclExecute.c, and new interface function was
	defined (TclCompEvalObj).
	The final objective of this sequence of moves is to provide a clean,
	clear-cut interface between Tcl's core and the compiler/engine
	subsystem.

2001-11-20  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclBasic.c
	* generic/tclCompile.h:
	* generic/tclExecute.c: factoring out of common code in tclBasic.c
	(new function TclInterpReady defined: it resets the interp's result,
	then checks that it hasn't been deleted and that the nesting level is
	acceptable). Passed the responsibility of calling it to the *callers*
	of TclEvalObjvInternal.

2001-11-20  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclBasic.c
	* generic/tclExecute.c: a better variant of the previous-to-last
	commit (restoring numLevels computations). The managing of the levels
	now has to be done by the *callers* of TclEvalObjvInternal

2001-11-20  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c: missing variable declaration under
	TCL_COMPILE_DEBUG.

2001-11-20  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c:
	* generic/tclProc.c: restoring the computations of iPtr->numLevels to
	the original logic (previous to buggy modifs on 2001-11-16).

2001-11-20  Jeff Hobbs  <jeffh@ActiveState.com>

	* tools/eolFix.tcl (new-file):
	* unix/Makefile.in: added EOL correction for Windows bat files to
	dist target. [Bug 219409] (davygrvy)

	* unix/tclUnixInit.c (TclpSetInitialEncodings): update of patch from
	2001-11-16 that uses the old Tcl encoding check mechanism as a
	fallback to the original. Also added a TCL_DEFAULT_ENCODING #define
	(defaults to iso8859-1). Tcl will first try setlocale and nl_langinfo,
	and if that fails, guess based on certain LANG|LC_* env vars. [Patch
	418645]

2001-11-19  David Gravereaux <davygrvy@pobox.com>

	* win/buildall.vc.bat:  Added useful comments.

2001-11-19  Miguel Sofer  <msofer@users.sourceforge.net>

	* tests/compile.test: added a test for bug [Bug 483309]

2001-11-19  Vince Darley  <vincentdarley@users.sourceforge.net>

	* win/tclWinFile.c:
	* win/tclWinFCmd.c:
	* win/tclWin32Dll.c:
	* doc/file.n:
	* tests/winFCmd.test: improved speed of file normalization for
	Win95/98, and clarified docs on differences in file normalization
	between NT/2000 and the older operating systems. Added test to ensure
	normalization is correct.

2001-11-19  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclBasic.c:
	* generic/tclParse.c: Code reorganisation. Moved all evaluation
	functions from tclParse.c to tclBasic.c, so that now tclParse.c deals
	exclusively with parsing and all evaluations are done by code in
	tclBasic.c. The functions moved are: TclEvalObjvInternal,
	Tcl_EvalObjv, Tcl_LogCommandInfo, Tcl_EvalTokensStandard,
	Tcl_EvalTokens, Tcl_EvalEx, Tcl_Eval, Tcl_EvalObj and
	Tcl_GlobalEvalObj.

2001-11-19  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/trace.test (trace-8.8): Added adapted version of [Bug 219393]
	as new test; the test won't reliably show up the old problem unless it
	is being run under something like Purify, but something is better than
	nothing...

	* generic/tclVar.c (Tcl_TraceVar2, Tcl_UntraceVar2): Added missing
	mask bits for trace result type and a check for a nonsense flag
	combination.
	* generic/tclCmdMZ.c (TraceVarProc): Added missing test for NULL when
	deleting a trace that doesn't cause an error.

	* doc/TraceVar.3: Added documentation for change due to TIP#68.

	* generic/tclCmdMZ.c (TraceVarInfo): Removed problematic errMsg field
	from structure.
	(TraceVarProc): Removed references to errMsg field and changed
	handling of errors so that they returned a Tcl_Obj* containing the
	error string. This minimizes the number of calls to the memory
	management subsystem.
	(TclTraceCommandObjCmd, TraceCommandProc): Removed references to
	errMsg field which was never used in command traces in any case.
	(Tcl_TraceObjCmd, TclTraceVariableObjCmd): Removed references to
	errMsg field and made variable traces register with
	TCL_TRACE_RESULT_OBJECT bit set.

	* generic/tcl.h (TCL_TRACE_RESULT_DYNAMIC,TCL_TRACE_RESULT_OBJECT):
	New constants to define how to handle the strings returned from trace
	callbacks [TIP#68]
	* generic/tclVar.c (CallTraces, Tcl_GetVar2Ex, TclGetIndexedScalar,
	(TclGetElementOfIndexedArray, Tcl_SetVar2Ex, TclSetIndexedScalar,
	(TclSetElementOfIndexedArray, Tcl_UnsetVar2, Tcl_ArrayObjCmd,
	(TclDeleteVars, TclDeleteCompiledLocalVars, DeleteArray,
	(TclVarTraceExists): Support for those new trace flags.

2001-11-19  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclCompCmds.c: patch for [Bug 483309] (petasis).

2001-11-16  Kevin B. Kenny  <kennykb@users.sourceforge.net>

	* generic/tclListObj.c: removed a C++-style comment that was
	inadvertently left in the source code.

2001-11-16  Jeff Hobbs  <jeffh@ActiveState.com>

	* tests/interp.test:
	* generic/tclInterp.c (SlaveObjCmd): Corrected argument checking for
	'$interp alias|aliases|issafe'. [Patch 479560] (thoyts, hobbs)

	* unix/tclUnixInit.c: added HAVE_LANGINFO code block.
	* unix/configure: regened
	* unix/configure.in: added SC_ENABLE_LANGINFO call
	* unix/tcl.m4: made SHLIB_LD_LIBS='${LIBS}' for FreeBSD* (meyer)
	Added modified version of Wagner patch to make use of nl_langinfo
	where possible to determine Unix platform encoding, instead of the
	inflexible built-in system. This is used by default when possible, and
	can be disabled with --enable-langinfo=no. [Patch 418645] (hobbs,
	wagner)

2001-11-16  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclCompile.h:
	* generic/tclExecute.c:
	* generic/tclObj.c: moved Tcl_GetCommandFromObj and all defining code
	for tclCmdNameType objects to tclObj.c (from tclExecute.c). This code
	has nothing to do with bytecodes.

2001-11-16  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclBasic.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c:
	* generic/tclParse.c:
	* generic/tclProc.c:
	* tests/stack.test: consolidation of duplicated code (in
	TclExecuteByteCode and EvalObjv); renaming of EvalObjv to TclEvalObjv
	as it is not static anymore; restored consistency of level counts
	between compiled and directly evaled code. [Bug 480896]

2001-11-12  David Gravereaux <davygrvy@pobox.com>

	* win/makefile.vc:
	* win/rules.vc:  Small bug fixes.

	* win/README: added some docs pointing to the docs in makefile.vc for
	it's use.

2001-10-17  Kevin B. Kenny  <kennykb@users.sourceforge.net>

	* doc/lappend.n:
	* doc/lindex.n:
	* doc/linsert.n:
	* doc/list.n:
	* doc/llength.n:
	* doc/lrange.n:
	* doc/lsearch.n:
	* doc/lset.n (new-file):
	* doc/lsort.n:
	* generic/tclBasic.c (builtInCmds, Tcl_EvalObjEx):
	* generic/tclCmdIL.c (Tcl_LindexObjCmd, Tcl_LindexList):
	(Tcl_LindexFlat, Tcl_LsetObjCmd):
	* generic/tclCompCmds.c (Tcl_CompileLindexCmd, Tcl_CompileLsetCmd):
	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c (TclExecuteByteCode):
	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclIntDecls.h:
	* generic/tclListObj.c (TclLsetList, TclLsetFlat, TclSetListElement):
	* generic/tclObj.c (TclInitObjSubsystem):
	* generic/tclStubInit.c:
	* generic/tclTestObj.c (TestobjCmd):
	* generic/tclUtil.c (TclGetIntForIndex, SetEndOffsetFromAny):
	* generic/tclVar.c (Tcl_LappendObjCmd):
	* tests/lindex.test:
	* tests/lset.test (new-file):
	* tests/lsetComp.test (new-file):
	* tests/obj.test:
	* tests/string.test:
	* tests/stringComp.test:
	Reference implementation of TIP's #22, #33 and #45. Adds the ability
	of the [lindex] command to have multiple index arguments, and adds the
	[lset] command. Both commands are byte-code compiled. [Patch 471874]
	(work by Kenny, commited by Hobbs)

2001-11-12  David Gravereaux <davygrvy@pobox.com>

	* win/buildall.vc.bat(new):
	* win/makefile.vc:  Small fix with deriving the "OriginalFilename"
	string in the .rc scripts. Added a quick batchfile for building the
	entire thing.

2001-11-12  Jeff Hobbs  <jeffh@ActiveState.com>

	* doc/FileSystem.3:
	* doc/file.n:
	* doc/tcltest.n: converted use of \' to more reasonable format.

2001-11-10  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/Makefile.in:
	* win/Makefile.in: Add "make gdb" target. This target can run tclsh
	inside either gdb or insight.

2001-11-10  David Gravereaux <davygrvy@pobox.com>

	* win/makefile.vc:  Added a check to make sure one runs the makefile
	from the /win directory only.

	* win/mkd.bat:
	* win/rmd.bat:  Changes from Llyod Lim for better stability.
	[Patch 456759]

2001-11-09  David Gravereaux <davygrvy@pobox.com>

	* win/makefile.vc:
	* win/tcl.dsp:  winhelp target fixes for non-NT systems. It seems
	NMAKE under these remembers changed directories during commands. A new
	tcltest feature from Peter Spjuth <peter.spjuth@space.se> to specify a
	pattern file from the commandline and redirecting output to a file
	when not under NT with it's scrollback console. Then it replays it,
	piped through more. Added 2 new static "configurations" to tcl.dsp.
	I could keep adding more, but I think we should leave it up to the
	user for customizing it.

	Sticky-points left:  'profile' option.

2001-11-09  Jeff Hobbs  <jeffh@ActiveState.com>

	* doc/FileSystem.3:
	* doc/StdChannels.3:
	* doc/file.n:
	* doc/tcltest.n:
	* tools/man2help.tcl:
	* tools/man2help2.tcl: fixed winhelp generation problems
	[Patch 480268]

	* unix/configure:
	* unix/tcl.m4: added -lc to AIX libs, fixed path to ldAix

2001-11-09  Don Porter	<dgp@users.sourceforge.net>

	* tests/var.test:
	* generic/tclVar.c: Corrected bug in [global] when dealing with
	variable names matching :*. [Bug 480176]

2001-11-08  Mo DeJong  <mdejong@users.sourceforge.net>

	Fixup stack size under OSF1. [Patch 474790]

	* unix/configure: Regen.
	* unix/tcl.m4: Add HAVE_PTHREAD_ATTR_SETSTACKSIZE define to
	EXTRA_CFLAGS to adjust initial stack size.

2001-11-08  Mo DeJong  <mdejong@users.sourceforge.net>

	Enable thread support under FreeBSD. [Bug 473708]

	* unix/configure: Regen.
	* unix/tcl.m4 (SC_ENABLE_THREADS): Check for pthread functions in
	libc_r and enable thread support if found.
	* unix/dltest/Makefile.in: Set SHLIB_LD_LIBS and use it in the
	Makefile to properly link a shared library.

2001-11-08  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/Makefile.in:
	* unix/dltest/Makefile.in: Avoid adding libc to the LIBS variable
	since it is not needed when linking with CC. If required when linking
	with LD it should be done on a case by case basis in tcl.m4.

2001-11-08  David Gravereaux <davygrvy@pobox.com>

	* win/rules.vc:
	* win/makefile.vc:  Fixed install target to adjust for the different
	build types. Added a 'linkexten' option to link the win extensions
	inside the shell when built static. Placed win/tclAppInit.c patch in
	SF patch DB for approval. 'profile' option not hooked in yet.
	Everything else know is done.

	* win/tcl.dsp(new):
	* win/tcl.dsw(new):  Simple MsDev stub project files that calls
	makefile.vc. Will help run Tcl in the debugger easier without
	confusing MsDev for where the .pdb files are.

2001-11-07  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/Makefile.in:
	* win/Makefile.in: Print a message indicating that the user should run
	"make genstubs" when the generated tclStubInit.c file is out of date.
	We can't regenerate automatically since there may be no tclsh on the
	system and that would cause bootstrap problems. [Bug 465874]

2001-11-07  Mo DeJong  <mdejong@users.sourceforge.net>

	Define TCL_INCLUDE_SPEC in tclConfig.sh. It should be included by
	extensions that need to find Tcl include headers in the install
	location. The user can override the include install dir with
	--includedir so we need to record this information for extensions.
	[Bug 421835]

	* unix/configure: Regen.
	* unix/configure.in: Define TCL_INCLUDE_SPEC.
	* unix/tclConfig.sh.in: Define TCL_INCLUDE_SPEC.
	* win/configure: Regen.
	* win/configure.in: Define TCL_INCLUDE_SPEC.
	* win/tclConfig.sh.in: Define TCL_INCLUDE_SPEC.

2001-11-07  David Gravereaux <davygrvy@pobox.com>

	* win/rules.vc:
	* win/makefile.vc: Dropped the NOMSVCRT macro and put it on the option
	list instead. It makes more sense to me this way as NOMSVCRT=0 would
	only be the valid setting. Fixed the dde and reg extension for
	building static. Improved, but not perfected, the winhelp target.

2001-11-07  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/README: Change minimum VC++ version to 5.X since 4.X is known
	not to work.
	Indicate that Mingw is required and building with Cygwin gcc is not
	supported. Include instructions that indicate how to install Mingw and
	what URLs folks should use to download the supported version of Mingw.
	* win/configure: Regen.
	* win/configure.in: Error out if user tries to compile the Windows
	version of Tcl with Cygwin gcc. Users should compile with Mingw gcc
	instead.

2001-11-06  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* generic/tclIO.c (ReadChars): Fixed [Bug 478856] reported by Stuart
	Cassoff <stwo@users.sourceforge.net>. The bug caused loss of
	fileevents when [read]ing less data from the channel than buffered.
	Due to an empty input buffer the flag CHANNEL_NEED_MORE_DATA was set
	but never reset, causing the I/O system to wait for more data instead
	of using a timer to synthesize fileevents and to flush the pending
	data out of the buffers.

2001-11-06  David Gravereaux <davygrvy@pobox.com>

	* win/rules.vc (new):
	* win/makefile.vc:  Complete over/under rewrite to support numerous
	build options all from the commandline itself without needing to edit
	the makefile. Now requires vcvars32.bat to be run prior to running
	nmake for bootstraping the environment. Fully doc'd usage for it is in
	makefile.vc. Commentary welcome. Sticky points left are:

	1) winhelp target shows errors in the converting script.
	2) .rc scripts aren't getting the right #defines to build the correct
	   "OriginalFilename" strings. (have patch, won't commit yet)
	3) Naming convention with suffixes describing the buildtype are 'tsdx'
	   which will need public acceptance. ie. tclsh84tsx.exe is a (t)
	   threaded shell (s) statically linked to the core and (x) uses
	   msvcrt instead of libcmt.

2001-11-04  Vince Darley  <vincentdarley@users.sourceforge.net>

	* library/init.tcl: made filesystem fallback proc ::tcl::CopyDirectory
	more robust to vagaries of non-native filesystems.

2001-11-02  Vince Darley  <vincentdarley@users.sourceforge.net>

	* doc/file.n:
	* generic/tclIOUtil.c: updated documentation and comments to clarify
	behaviour of 'file copy' wrt soft links.

2001-10-29  Vince Darley  <vincentdarley@users.sourceforge.net>

	* win/tclWinFile.c: fix to '-types {f r}' bug in TclpMatchInDirectory
	(which could cause a UMR, as well as returning wrong results). Also
	improved API for 'stat' to resolve [Bug 219258].
	* win/tclWin32Dll.c
	* win/tclWinInt.h: addition of improved stat API to internal lookup
	table.
	* tests/fileName.test: two new tests for the above bug.
	* generic/tclIOUtil.c: some cleanup of comments and #ifdefs

2001-10-29  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* unix/tclUnixFile.c (TclpMatchInDirectory): Argument to access() was
	entryPtr->d_name instead of nativeEntry which failed when trying to
	check access for files in other than the current directory. [Bug
	475941, reported by Georgios Petasis]

2001-10-25  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* unix/tclUnixChan.c: Added stateUpdated member to struct TtyState.
	(TtyCloseProc,TtySetOptionProc,TtyInit): Use stateUpdated member of
	TtyState to decide whether it is necessary to reset a serial port when
	Tcl closes it. Blindly resetting can cause Tcl to be sent an
	unexpected SIGTSTP when it is executing in the background [Bug 471374,
	reported by Chris Nelson]

2001-10-22  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* doc/ObjectType.3: Minor documentation fix, reported by David N.
	Welton <davidw@users.sourceforge.net> directly to me.

2001-10-22  Vince Darley  <vincentdarley@users.sourceforge.net>

	* win/tclWinFCmd.c: fix to stop test suite from hanging process under
	some versions of WinNT. [Bug 466102] (Kevin Kenny)

2001-10-18  Jeff Hobbs  <jeffh@ActiveState.com>

	* tests/clock.test (clock-8.1):
	* generic/tclDate.c (RelativeMonth):
	* generic/tclGetDate.y (RelativeMonth): corrected off-by-one-day error
	in clock scan with relative months and years during swing hours. [Bug
	413397, Patch 414024] (lavana)

2001-10-18  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclIOUtil.c: fix to bug in Tcl_FSChdir shown up by recent
	tclkit builds.

2001-10-17  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/tclUnixPipe.c (PipeInputProc, PipeOutputProc): do immediate
	retry when error is returned with errno == EINTR. [Bug 415131] (leger)

2001-10-16  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/tclLoadAout.c (TclGuessPackageName): removed unused vars and
	fixed warnings. [Bug 446622] (lim)

2001-10-15  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclProc.c: changing a memcmp to strncmp to avoid a memory
	error detected by purify (thanks Jeff); modify style to agrre with the
	style guide.

2001-10-15  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* generic/tclInt.decls (TclExpandCodeArray,TclGetInstructionTable):
	Added to internal stubs table. Tclcompiler (Tclpro project) needs them
	if used as loadable package under Windows. Changed signatures. We
	don't want to describe compiler internal structures in "tclInt.h".

	* generic/tclCompile.h: S.a. Removed function declarations.
	* generic/tclCompile.c: S.a. Adapted to changed signatures.

2001-10-15  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/configure:
	* unix/configure.in:
	* win/configure:
	* win/configure.in:
	* win/tcl.m4: reworked to be a little cleaner in comparison to each
	other, and to AC_SUBST even empty vars for win/tclConfig.sh

	* generic/tclFileName.c: minor code cleanup

	* generic/tcl.h: moved #define of WIN32 to tcl.h where __WIN32__ is
	defined and added #ifndef check.

	* doc/open.n: moved all fconfigure option docs to fconfigure.n
	* doc/fconfigure.n: added serial config options

	* win/tclWinChan.c:
	* win/tclWinPort.h:
	* win/tclWinSerial.c: added TIP #35 Windows enhancements for serial
	configuration. [Patch 438509] (schroedter)

2001-10-15  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFCmd.c: fix to memory leak in TclFileDeleteCmd on
	certain error conditions.
	* doc/FileSystem.3: fix to typo.

2001-10-12  Jeff Hobbs  <jeffh@ActiveState.com>

	* library/encoding/ebcdic.enc:
	* tools/encoding/ebcdic.txt: EBCDIC charset mapping.
	[Patch 219323] (nijtmans)

	* library/encoding/tis-620.enc:
	* tools/encoding/tis-620.txt: TIS-620 charset mapping.
	[Patch 467423] (poonlap)

	* tests/http.test: added removeFile for outdata

	* tests/ioCmd.test: added catch around file removal, as Windows file
	locking throws errors.

	* tests/socket.test (socket-7.2): corrected to work on Win2K.

2001-10-12  Miguel Sofer  <msofer@users.sourceforge.net>

	* tests/compile.test: new tests for [Bug 467523]; they are only
	effective if TCL_MEM_DEBUG was set during compilation.

2001-10-11  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclLiteral.c (TclReleaseLiteral): insured that
	self-referential bytecodes are properly cleaned up on interpreter
	deletion [Bug 467523] (Ronnie Brunner)

2001-10-10  David Gravereaux  <davygrvy@pobox.com>

	* win/tclWinPort.h:  #include <winsock2.h> needed to get moved to
	after #include <windows.h> or wierd misunderstandings took place when
	-D_WIN32_WINNT=0x0400 is set for outside code that requires knowledge
	of Tcl innards. General header macro magic applied liberally...

2001-10-10  Don Porter	<dgp@users.sourceforge.net>

	* tests/unixInit.test:	Corrected restore of ::env(LANG).

2001-10-09  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclFileName.c (Tcl_SplitPath): corrected mem leak intro'd
	with VFS code where the result obj from Tcl_FSSplitPath was not
	getting freed.

2001-10-09  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclLiteral.c: (TclReleaseLiteral) reverted previous patch
	for [Bug 467523] - cure is worse than the illness.

2001-10-05  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclLiteral.c: (TclReleaseLiteral) insured that
	self-referential bytecodes are properly cleaned up on interpreter
	deletion. [Bug 467523] (Ronnie Brunner)

2001-10-04  Jeff Hobbs  <jeffh@ActiveState.com>

	* tools/configure:
	* tools/configure.in: noted 8.4 as default Tcl version

	* library/encoding/cp936.enc:
	* library/encoding/cp949.enc:
	* library/encoding/cp950.enc:
	* library/encoding/iso8859-16.enc:
	* library/encoding/macCroatian.enc:
	* library/encoding/macCyrillic.enc:
	* library/encoding/macGreek.enc:
	* library/encoding/macIceland.enc:
	* library/encoding/macRoman.enc:
	* library/encoding/macTurkish.enc:
	* tools/encoding/cp1250.txt:
	* tools/encoding/cp1251.txt:
	* tools/encoding/cp1252.txt:
	* tools/encoding/cp1253.txt:
	* tools/encoding/cp1254.txt:
	* tools/encoding/cp1255.txt:
	* tools/encoding/cp1256.txt:
	* tools/encoding/cp1257.txt:
	* tools/encoding/cp1258.txt:
	* tools/encoding/cp874.txt:
	* tools/encoding/cp932.txt:
	* tools/encoding/cp936.txt:
	* tools/encoding/cp949.txt:
	* tools/encoding/cp950.txt:
	* tools/encoding/iso8859-1.txt:
	* tools/encoding/iso8859-10.txt:
	* tools/encoding/iso8859-13.txt:
	* tools/encoding/iso8859-14.txt:
	* tools/encoding/iso8859-15.txt:
	* tools/encoding/iso8859-16.txt:
	* tools/encoding/iso8859-2.txt:
	* tools/encoding/iso8859-3.txt:
	* tools/encoding/iso8859-4.txt:
	* tools/encoding/iso8859-5.txt:
	* tools/encoding/iso8859-6.txt:
	* tools/encoding/iso8859-7.txt:
	* tools/encoding/iso8859-8.txt:
	* tools/encoding/iso8859-9.txt:
	* tools/encoding/koi8-r.txt:
	* tools/encoding/macCentEuro.txt:
	* tools/encoding/macCroatian.txt:
	* tools/encoding/macCyrillic.txt:
	* tools/encoding/macGreek.txt:
	* tools/encoding/macIceland.txt:
	* tools/encoding/macRoman.txt:
	* tools/encoding/macTurkish.txt:
	Updated encodings with latest mappings from www.unicode.org. This did
	not include some Mac encodings that have special multi-unichar
	translations now (like symbols, dingbats and japanese). Also does not
	include big5, gb or euc* as those have different formats in the latest
	Unicode version that need new conversion tools. Not all related .enc
	files changed as some had been updates separately.

2001-10-03  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclEvent.c (Tcl_FinalizeThread): moved freeing of
	tclLibraryPath to before the thread exit handlers are called. Slight
	modification to change on 2001-09-24.

2001-10-01  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/configure: regen'ed
	* win/tcl.m4:
	* win/makefile.vc: added Win64 SDK RC1 compilation support
	* win/Makefile.in: added $(LDFLAGS_CONSOLE) to TCLSH, TCLTEST and
	PIPE_DLL_FILE targets to get the link flags

	* win/tclWinInit.c: minor 64bit casts

2001-10-01  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclCmdIL.c:
	* generic/tclCmdMZ.c:
	* generic/tclParseExpr.c: removed unnecessary inclusion of
	tclCompile.h and made a small modification in (InfoBodyCmd) to improve
	the isolation of the compiler/engine subsystem.

2001-09-29  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclIOUtil.c:
	* doc/FileSystem.3: corrected and clarified documentation for
	'Tcl_FSListVolumes(Proc)'. No code changes.

2001-09-28  Miguel Sofer  <msofer@users.sourceforge.net>

	* doc/FindExec.3: added a comment not to change the working directory
	before calling Tcl_GetNameOfExecutable. [Bug 219215]

2001-09-28  Kevin Kenny   <kennykb@users.sourceforge.net>

	* generic/tclIO.c: added two more '(ClientData)' casts on calls to
	Tcl_Preserve and Tcl_Release -- ones that Vince apparently missed.

2001-09-28  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/lsort.n: Improved doc...
	* generic/tclCmdIL.c (Tcl_LsortObjCmd, SortCompare): Made
	offset-from-end indexing work, and factored out some "magic numbers"
	for easier understanding. [Bug 465674]
	* tests/cmdIL.test (cmdIL-1.26): Added test for offset-from-end
	indexing for lsort.

2001-09-28  Vince Darley  <vincentdarley@users.sourceforge.net>

	* win/tclWinFCmd.c:
	* unix/tclUnixFCmd.c: fix to performance issue reported by jcw in
	which 'access("")' is called unnecessarily when normalizing any
	absolute path.
	* generic/tclIO.c: added '(ClientData)' cast to calls to
	Tcl_(Preserve|Release) newly introduced, fixing compile error on
	Windows.

2001-09-27  Don Porter  <dgp@users.sourceforge.net>

	* doc/FileSystem.3 (Tcl_FSLoadFile):
	* generic/tcl.decls (Tcl_FSLoadFile):
	* generic/tcl.h (Tcl_FSLoadFileProc):
	* generic/tclInt.h (TclpLoadFile):
	* generic/tclIOUtil.c (Tcl_FSLoadFile):
	* generic/tclLoadNone.c (TclpLoadFile):
	* generic/tclTest.c (TestReportLoadFile):
	* library/ldAout.tcl:
	* mac/tclMacLoad.c (TclpLoadFile):
	* unix/tclLoadAix.c (TclpLoadFile):
	* unix/tclLoadAout.c (TclpLoadFile):
	* unix/tclLoadDl.c (TclpLoadFile):
	* unix/tclLoadDld.c (TclpLoadFile):
	* unix/tclLoadDyld.c (TclpLoadFile):
	* unix/tclLoadNext.c (TclpLoadFile):
	* unix/tclLoadOSF.c (TclpLoadFile):
	* unix/tclLoadShl.c (TclpLoadFile):
	* win/tclWinLoad.c (TclpLoadFile):
	* win/tclWinFCmd.c (DoRemoveJustDirectory):  More CONST poisoning
	fixes from the 2001-09-24 TIP 27 changes. CONST-ified Tcl_FSLoadFile
	and TclpLoadFile. Report and patch from Kevin Kenny. [Bug 465833]

	* generic/tclIO.c (ChannelTimerProc):  Added Tcl_Preserve() and
	Tcl_Release() to fix segfault introduced by the 2001-09-26 changes.
	[Bug 465494]

	* doc/TCL_MEM_DEBUG.3:  Updated out-of-date reference to #define
	GUARD_SIZE.

	* doc/UpVar.3 (Tcl_UpVar,Tcl_UpVar2):
	* generic/tcl.decls (Tcl_UpVar,Tcl_UpVar2):
	* generic/tclInt.decls (TclFindProc,TclGetFrame):
	* generic/tclInt.h (TclFindProc,TclGetFrame,TclLookupVar,
	(TclPrecTraceProc,TclProcInterpProc}):
	* generic/tclProc.c (TclGetFrame,TclFindProc):
	* generic/tclVar.c (Tcl_UpVar,Tcl_UpVar2,MakeUpvar):  Updated APIs in
	generic/tclProc.c and generic/tclVar.c according to the guidelines of
	TIP 27. [Patch 465442]

	* generic/tclDecls.h:
	* generic/tclIntDecls.h: make genstubs

2001-09-26  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* doc/fileevent.n: Accepted [Patch 465279] adding an example to the
	fileevent manpage. Minor modifications to get a better formatting.
	Report and patch by David N. Welton <davidw@users.sourceforge.net>.

	* The changes below fix [Bug 462317] where Expect tried to read more
	than was in the buffers and then blocked in the OS call as its pty
	channel driver provides no blockmodeproc through which the OS could be
	notified of blocking-behaviour. Because of this the general I/O core
	has to take more care than usual to preserve the semantics of
	non-blocking channels.

	The problem was reported by "Kevin O'Gorman" <kevin@kosmanor.com>.

	* generic/tclIO.c (Tcl_ReadRaw): Do not read from the driver if the
	channel is non-blocking and the fileevent causing the read was
	generated by a timer. We do not know if there is data available from
	the OS. Instead of going to the OS for more and potentially blocking
	we simply signal EWOULDBLOCK to the higher levels to cause the system
	to wait for true fileevents.
	(GetInput): Same as before.
	(ChannelTimerProc): Added set and clear of CHANNEL_TIMER_FEV.

	* generic/tclIO.h (CHANNEL_TIMER_FEV): New flag for channels. Is set
	if a fileevent was generated by a timer, the channel is not blocking
	and the driver did not provide a blockmodeproc. In that case the I/O
	core has to be especially careful about going to the driver for more
	data.

2001-09-26  Don Porter  <dgp@users.sourceforge.net>

	* doc/SplitPath.3 (Tcl_GetPathType):
	* generic/tcl.decls (Tcl_GetPathType):
	* generic/tclFileName.c (Tcl_GetPathType):
	* win/tclWinFile.c (TclpMatchInDirectory, NativeStat):  Vince Darley
	reports the 2001-09-24 TIP 27 changes left the win directory CONST
	poisoned. These changes should fix that.

	* generic/tclDecls.h: make genstubs

2001-09-25  Don Porter  <dgp@users.sourceforge.net>

	* doc/GetInt.3:
	* generic/tclInt.h (TclGetLong deleted):
	* generic/tcl.decls:
	* generic/tclInt.decls:
	* generic/tclGet.c:  Updated APIs in generic/tclGet.c according to the
	guidelines of TIP 27. [Patch 464674]

	* generic/tclDecls.h:
	* generic/tclIntDecls.h: make genstubs

2001-09-25  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclVar.c: removed comments referring to unused flag
	TCL_PARSE_PART1.

2001-09-24  Don Porter  <dgp@users.sourceforge.net>

	* doc/Concat.3:
	* doc/DString.3:
	* doc/SplitList.3:
	* generic/tclInt.h (TclCheckBadOctal):
	* generic/tcl.decls:
	* generic/tclInt.decls:
	* generic/tclEncoding.c (OpenEncodingFile):
	* generic/tclMain.c (Tcl_Main):
	* generic/tclUtil.c:
	* unix/tclLoadDl.c (TclpLoadFile):  Updated APIs in generic/tclUtil.c
	according to the guidelines of TIP 27. [Patch 464553]

	* generic/tclDecls.h:
	* generic/tclIntDecls.h: make genstubs

2001-09-24  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	The change below fixes [Bug 464380]. The bug was reported by Ronnie
	Brunner <rbrunner@users.sourceforge.net>. He also provided the patch.

	* generic/tclEvent.c (Tcl_Finalize): Moved release of 'tclLibraryPath'
	to Tcl_FinalizeThread.
	(Tcl_FinalizeThread): See above, new place for release of
	'tclLibraryPath'.

2001-09-24  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tools/encoding/cp1252.txt: File was missing part of the encoding
	[euro, ZCaron and zcaron].

	* doc/OpenFileChnl.3: Add docs for Tcl_OutputBuffered; remove some old
	changebars.

2001-09-21  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclExecute.c (TclExecuteByteCode): corrected INST_STR_CMP
	else case for strings to pass true utf char length to Tcl_UtfNCmp.

2001-09-20  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/tclWinInit.c: added extra processor definitions. (mstacy)

	* win/tclWinSock.c (SocketThread): corrected pointer cast for _WIN64.

	* win/tclWinNotify.c: removed unnecessary winsock include (it is
	already in from tclWinPort.h).

	* win/tclWinPort.h: changed winsock.h include to winsock2.h. Reverses
	change from 2000-11-16, but is necessary for WIN64. Extensions should
	comply with defined OS words, or use #ifndef.

2001-09-20  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/socket.test: removed dependence on being run from same dir as
	remote.tcl, which only now needs to be in the same dir as this file.
	[Bug 219326]

2001-09-19  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclTest.c (TestcmdtokenCmd): corrected pointer
	storage/retrieval for 64bit machines.

	* generic/tclCmdAH.c (Tcl_FormatObjCmd):
	* generic/tclScan.c (Tcl_ScanObjCmd): corrected handling of format and
	scan on 64-bit machines. [Bug 412696] (rmax)

	* unix/configure: regen'ed
	* unix/tcl.m4: added --enable-64bit support for HP-11 with the 64-bit
	kernel.

	* tests/basic.test:
	* tests/cmdInfo.test: improved skip reporting of missing commands

	* tests/winFCmd.test: simplified error check for winFCmd-7.9

	* tests/winPipe.test: removed obsolete cat16 tests

	* generic/tclExecute.c (TclExecuteByteCode): fixed invalid usage of
	valuePtr in TRACE_WITH_OBJ in INST_EVAL_STK case. [Bug 462594] Changed
	INST_STR_CMP instruction to promote to Unicode strings only when one
	of the strings is already of Unicode type.

	* generic/tclExecute.c (TclExecuteByteCode):
	* generic/tclCompile.c (instructionTable):
	* generic/tclCompCmds.c (TclCompileStringCmd): INST_STR_MATCH -
	Updated to Int1 instruction type and added special case to use
	INST_STR_EQ instead when no glob chars are specified in a static
	string.

	* tests/{for.test,foreach.test,if.test,while.test}:
	* generic/tclCompCmds.c (TclCompileForCmd, TclCompileForeachCmd,
	TclCompileIfCmd, TclCompileWhileCmd): Corrected the overaggressive
	compiling of loop bodies enclosed in ""s.  [Bug 219166] (msofer)

2001-09-19  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c: insured that execution stack errors are also
	detected at abnormal returns.

2001-09-19  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/socket.n: Added documentation to mention what happens when a
	server socket is created with port=0. Removed an old change bar, and
	no new change bar because Tcl has always behaved this way as it is
	really a poorly-documented standards-defined OS feature.

	* tests/util.test (util-8.1): Test derived from code to detect the
	problem, but the test always works in the C locale, so beware if you
	are maintaining the code.
	* generic/tclUtil.c (TclNeedSpace): Rewrote to be UTF-8 aware. [Bug
	411825, but not that patch which would have added extra spaces if
	there was a real non-ASCII space involved.]

2001-09-18 Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* generic/tclIOCmd.c (Tcl_PutsObjCmd): Rewritten to have saner and
	faster argument handling. [Bug 123552], [Patch 402564] (fellows)

2001-09-18  Don Porter  <dgp@users.sourceforge.net>

	* unix/configure: Regen.
	* unix/tcl.m4 (SC_CONFIG_CFLAGS): On Linux, disable inlining when one
	of the compat/*.c routines is to be linked in. [Patch 440891]

2001-09-17  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tcl.h: removed forced #define USE_TCLALLOC 1 for Windows.
	This means the native system allocator will be used by default. This
	should be binary and source compatible with extensions, as Tcl_Alloc
	is a properly stubbed function.

2001-09-17  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c: corrected small bug in [Patch 456668] - the
	varFramePtr was not restored in one possible exit.

2001-09-17  Miguel Sofer  <msofer@users.sourceforge.net>

	* doc/tclvars.n:
	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c:
	* generic/tclProc.c: disabled all compile and execution tracing
	functionality in standard builds; TCL_COMPILE_DEBUG is now necessary
	to enable it. [Bug 451858]

2001-09-14  Andreas Kupries <andreas_kupries@users.sourceforge.net>

	* doc/gets.n:
	* doc/read.n:
	* doc/puts.n:
	* doc/flush.n:
	* doc/fconfigure.n:
	* doc/flush.n:
	* doc/eof.n:
	* doc/seek.n:
	* doc/tell.n:
	* doc/close.n:
	* doc/fileevent.n: Added references to the Tcl standard channels. Item
	[219250], reported by David LeBlanc <whisper@oz.net>. Thanks to
	Christopher Nelson <chris@pinebush.com> for doing editorial work.

2001-09-13  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* win/Makefile.in:
	* win/configure.in:
	* win/makefile.bc:
	* win/makefile.vc:
	* library/dde/pkgIndex.tcl: Fixed version numbers from bogus tcl
	versions to independent versions for dde and registry packages.

2001-09-13  Jeff Hobbs  <jeffh@ActiveState.com>

	* tests/regexp.test (regexp-20.1):
	* generic/tclCmdMZ.c (Tcl_RegsubObjCmd): had to adjust fix from
	2001-08-06 to actually duplicate the objects in certain cases. This is
	really a place where feather would have been essential. [Bug 461322]

	* generic/tclUtf.c (Tcl_UtfPrev): corrected to return the proper
	location when the middle of a UTF-8 byte was passed in [Tk Bug 450504]

	* ChangeLog.1999:
	* ChangeLog: broke changes from 199x into ChangeLog.1999 to reduce
	size of the main ChangeLog.

2001-09-13  Andreas Kupries <andreas_kupries@users.sourceforge.net>

	* tests/ioCmd.test: Changed the computation of the result for
	iocmd-8.1[123] so that the tests work for single- and multi-process
	execution of the testsuite. Depending on the choice of the user stdout
	is a tty or not and thus reports different channel options. Fixes
	[460993] reported by Don Porter.

2001-09-13  Miguel Sofer  <msofer@users.sourceforge.net>

	* doc/ParseCmd.3:
	* generic/tcl.decls:
	* generic/tclCmdMZ.c (Tcl_SubstObjCmd):
	* generic/tclDecls.h:
	* generic/tclParse.c:
	* generic/tclStubInit.c:
	* tests/parse.test: Deprecate the use of Tcl_EvalTokens, replaced by
	the new Tcl_EvalTokensStandard. The new function performs the same
	duties but adheres to the standard return convention for Tcl
	evaluations; the deprecated function could only return TCL_OK or
	TCL_ERROR, which caused [Bug 219384] and [Bug 455151]. This patch
	implements [TIP 56].

2001-09-12  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure: Regen.
	* unix/tcl.m4: Invert the logic that checks for $GCC. Instead of
	checking for "$GCC" = "no" we check for "$GCC" != "yes" or simply swap
	the true and false blocks of code in an if statement. That way if GCC
	is set to "" everything will still work. [Bug 460991]

2001-09-12  Don Porter <msofer@users.sourceforge.net>

	* tests/appendComp.test:
	* tests/lsearch.test:
	* tests/namespace.test:
	* tests/rename.test:
	* tests/split.test:  Corrected tests to better isolate tests in one
	file from influencing tests in other files. [Bug 460591]

2001-09-12  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tcl.decls: reserved stub #481 for the implementation of
	[TIP 56]

2001-09-11  Andreas Kupries <andreas_kupries@users.sourceforge.net>

	* doc/OpenFileChnl.3: Added documentation for Tcl_WriteRaw and
	Tcl_ReadRaw [Bug 414929].

	* doc/CrtChannel.3: Added documentation for Tcl_ChannelBuffered and
	Tcl_GetTopChannel [Bug 414929].

	* The changes below are a fix for [Bug 219253].

	* tests/socket.test: Removed _most_ instances of hardwired port
	numbers for listening sockets. Remaining are the ports in all tests
	with constraint 'doTestsWithRemoteServer'. These seem to be designed
	for a more controlled environment and are usually skipped when running
	the testsuite.

	* tests/io.test: Removed all instances of hardwired port numbers for
	listening sockets.

2001-09-10  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclEvent.c (TclInExit): Corrected handling of tsd in late
	stages of finalization. [Bug 419449] (darley)

	* tests/stack.test:
	* generic/tclInterp.c (AliasObjCmd): Check the numLevels to ensure
	that we aren't hitting some alias loop condition. [Bug 443184]

2001-09-10  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure: Regen.
	* unix/tcl.m4 (SC_CONFIG_CFLAGS): Don't include . characters in the
	Tcl library name when building on FreeBSD 3.X and later systems.
	[Patch 450725]

2001-09-10  Andreas Kupries <andreas_kupries@users.sourceforge.net>

	* doc/tclsh.1:
	* doc/Tcl_Main.3:
	* doc/CrtChannel.3:
	* doc/OpenFileChnl.3:
	* doc/GetStdChan.3: Enhanced the manpages with cross-references to
	the new manpage and more explanations how these functions deal with
	the standard channels in various situations.

	* doc/StdChannels.3: New manpage describing handling of the standard
	channels by the Tcl library. [Bug 402725]

2001-09-10  Don Porter <dgp@users.sourceforge.net>

	* unix/mkLinks (Tcl_FSLink): Updated to reflect 2001-08-23 file system
	changes.

	* unix/tclLoadShl.c:  Added #include of tclInt.h; access to Tcl
	internals, notably TclpUnloadFile(), is required. Thanks to Bob
	Techentin for report and patch. [Bug 459305]

	* generic/tclInitScript.h (initScript):
	* win/tclWinInit.c (TCL_REGISTRY_KEY, TclpSetVariables):  Removed
	vestiges of Tcl's old initialization from registry variables. [Bug
	455645]

2001-09-10  Andreas Kupries <andreas_kupries@users.sourceforge.net>

	* generic/tclInt.decls: Also added 'TclWinFlushDirtyChannels' to the
	  internal platform specific stub table.

	* win/tclWinFile.c (TclpObjStat): Now added the call to
	'TclWinFlushDirtyChannels' to this function. I don't know where my
	head was last thursday (2001-09-06), but the call was actually added
	to 'TclpObjChdir', i.e. the implementation of [cd]. Corrected this
	now. Thanks to Vince Darley for spotting this.

2001-09-10  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclProc.c:
	* tests/proc.test: made [proc] bytecompile a no-op for procs defined
	with _args_ as single argument and an empty body. [FRQ 451441]

2001-09-09  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/Makefile.in:
	* win/Makefile.in: Use () around variable name instead of {}. Use
	TCLTEST variable directly instead of depending on the tcltest alias.

2001-09-09  David Gravereaux <davygrvy@pobox.com>

	* generic/tcl.h:
	* generic/tclPlatDecls.h: Reminder from David Cuthbert
	<dacut@kanga.org> that I hadn't finished the Borland compatibility
	stuff. [Patch 436116]

2001-09-09  Mo DeJong  <mdejong@users.sourceforge.net>

	* tests/cmdAH.test: Modify cmdAH-20.5 and cmdAH-24.8 to display the
	file atime or mtime results if the test fails.

2001-09-08  David Gravereaux <davygrvy@pobox.com>

	* win/mkd.bat:
	* win/rmd.bat: made these text files, text files again. [Patch 451333]

2001-09-08  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/mkd.bat:
	* win/rmd.bat: Apply binary property (cvs admin -kb) to files and
	convert to CRLF linefeed format to fix the VC++ build. [Bug 219409]

2001-09-08 Vince Darley <vincentdarley@users.sourceforge.net>

	* generic/tclInt.h:
	* generic/tclFCmd.c:
	* doc/FileSystem.3:
	* generic/tclIOUtil.c: removed Tcl_FSCopyFile fallback to channel
	copying, since the channels will not have access to interpreters and
	the channel copying currently requires an interp. Code which required
	cross-platform copies always has interpreters, so that solves the
	problem. Fixes bug in TclKit.

2001-09-07  David Gravereaux <davygrvy@pobox.com>

	* win/tcl.m4: Added -link50compat option so a VC6 linker makes a VC5
	(pre sp3) compatible import library. [Bug 219257]

2001-09-07  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/tclWinThrd.c (TclpThreadExit): Cast status argument to
	_endthreadex to unsigned instead of DWORD to match the Win32 function
	prototype.

2001-09-06  Andreas Kupries <andreas_kupries@users.sourceforge.net>

	* All the changes below serve to fix bug [219148] which reports a 80x
	performance hit for file I/O on Win* systems. On my system it was
	closer to a 120x hit. Problem report by Uwe Traum <no email address
	available>.

	The fix goes like this: The obstacle is 'FlushFileBuffers', executed
	whenever Tcl writes data to the OS, as Tcl has to wait for the disk to
	complete I/O, and disks are slow. We remove that obstacle. This opens
	another problem, [file size] reports back wrong numbers. So for [file
	size] we add the call back in. As optimization we keep track of the
	channels which were written to and flush only these.

	* win/tclWinFile.c (TclpObjStat): Added a call to
	'TclWinFlushDirtyChannels'. This ensures that [file size] and related
	commands report the correct size of a file even if Tcl has recently
	written to it. Unixoid OS's always report the correct size even for
	files with pending data, but Win* syssystem don't. They only report
	what is actually on disk.

	* win/tclWinInt.h: Added declaration of 'TclWinFlushDirtyChannels',
	making it available to other parts of the tcl core.

	* win/tclWinChan.c (TclWinFlushDirtyChannels): New, internal,
	procedure. Goes through the list of open file channels and forces the
	OS to flush its file buffers for all which were written to since the
	last call of this function. This is an expensive operation as Tcl has
	to wait for the OS to complete actual writes to the disk.

	(FileInfo): Added dirty flag required by the procedure above.

	(FileOutputProc): Removed flushing of file buffers, setting the dirty
	flag instead. This means that the previously incurred delays do not
	happen anymore.

	(TclWinOpenFileChannel): Added initialization of 'dirty' flag.

2001-09-06  Jeff Hobbs  <jeffh@ActiveState.com>

	* doc/http.n: noted -binary, charset and coding state keys.
	* tests/http.test:
	* library/http/pkgIndex.tcl:
	* library/http/http.tcl (geturl): correctly get charset parameter
	and convert text according to specified encoding (if known). RFC
	iso8859-1 is used by default. Also recognize Content-encoding to see
	if we should do binary translation. Added a CYA -binary switch for the
	cases that were missed. [Bugs 219211, 219399]

	* tests/ioUtil.test: changed to make better use of constraints and
	remove knownBug constraints that weren't valid.

2001-09-06  Don Porter  <dgp@users.sourceforge.net>

	* tests/unixInit.test (unixInit-3.2): Updated test to support newer
	HP-UX releases that properly report euc-jp as the system encoding for
	Japanese. Bug report and patch verification by Bob Techentin. [Bug
	453883]

	* doc/http.n:
	* library/http/*.tcl:
	* tools/tcl.wse.in:
	* tools/tclmin.wse:
	* unix/Makefile.in:
	* win/{Mm}akefile.*:  Updated http package to version 2.4, reflecting
	the new features just added.

2001-09-06 Vince Darley <vincentdarley@users.sourceforge.net>

	* generic/tclTest.c: tests of old-fs hooks no longer cause problems in
	threaded builds. Also removed unused unload proc.
	* generic/tcl.decls:
	* generic/tclIOUtilc: added Tcl_FSMountsChanged so that a vfs can
	inform the filesystem that the filesystem epoch must be changed (since
	cached filesystems may now be incorrect). Fixes problem running tclvfs
	extension.
	* library/tcltest/tcltest.tcl: if tests aren't in a native filesystem,
	then don't use pipes to run them. [Bug 458741]

2001-09-06  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tcl.decls (479 generic):
	* generic/tclIO.c (Tcl_Seek,Tcl_Tell,Tcl_OutputBuffered): Added public
	function to return the size of the output buffer and reworked other
	channel functions to use this shared functionality and that of
	Tcl_InputBuffered() too. [TIP#49, Rolf Schroedter]

2001-09-05  David Gravereaux <davygrvy@pobox.com>

	* generic/tclPlatDecls.h:  Another small trim finalizing Borland
	support.

	* win/tclWinPipe.c:
	* win/tclWinPort.h:  More Borland compatibility fixes. Changed EDQUOT
	#define from 49 to 69. Borland had a clash as it was already using
	this number. Upon advice from Helmut Giese, EDQUOT has been found in
	other header files #defined as 69. [Patch 436116]

	* win/.cvsignore:  A few more glob patterns added.

	* win/makefile.bc (new):  Borland lives once more! rejoice..
	* generic/tclAlloc.c: Small Borland compatibility fix.
	* win/tclWinTime.c:  More Borland compatibility fixes. [Patch 436116]

2001-09-05 Vince Darley <vincentdarley@users.sourceforge.net>

	* tests/winFCmd.test: made notWin2000 constraint false if not running
	on Windows at all.

2001-09-04  David Gravereaux <davygrvy@pobox.com>

	* win/tclWinThrd.c:  Revisited _beginthreadex() stuff. Instead of
	assuming a c-runtime implimentation of _beginthreadex normal, I
	reversed the logic to not assume, and use when is by explicitly
	needing to add runtimes that support it such as Borland.

	* generic/tcl.h:
	* generic/tclPlatDecls.h:  Borland compatibility change so ClientData
	was properly typed as a void* and TCHAR would not be defined twice.

	* generic/tcl.h:  Removed a small mistake from before. Changes to the
	EXTERN macro for proper Borland compatibility will have to see a TIP.
	What's this with the MS compiler:

		__declspec(dllexport) int func (int a, int b);

	will have to be this with Borland:

		int __cdecl __export func (int a, int b);

	The order of the attribute needs to be after the return type.

2001-09-04  Don Porter  <dgp@users.sourceforge.net>

	* compat/strtod.c (strtod):  Fixed failure to handle expressions like
	3eq2 and failure to set errno on overflow. [Bug 440894]

2001-09-04  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclProc.c:
	* tests/proc.test: made [proc] check that formal args have simple
	names. [Bug 458548]

2001-09-04 Vince Darley <vincentdarley@users.sourceforge.net>

	Minor bug fixes in filesystem, plus small vfs changes as a result of
	enabling the test filesystem to work properly.
	* tests/fileName.test: ensure new test cleans up after itself
	* doc/filename.n:
	* generic/tclFileName.c: improved Mac path handling and document why
	[Bug 421842] on Windows handling of UNC paths is not valid.
	Documentation and code now much clearer on what is and is not a UNC
	path.
	* doc/FileSystem.3:
	* unix/tclUnixPipe.c:
	* generic/tclFCmd.c:
	* generic/tclIOUtil.c: fixed error message, fixed [Bug 453512] about
	dangerous use of tmpnam, replaced with mkstemp. Documented all the
	changes.
	* generic/tclTest.c: made test vfs fully functional as a 'reporting
	filesystem'.
	* generic/tcl.stubs:
	* generic/tcl.h:
	* generic/tclInt.h:
	* generic/tclIOUtil.c:
	* doc/file.n:
	* various platform-specific 'TclpLoadFile': fixed comments about
	unload behaviour, and completed objectification of loading. Required
	change to Tcl_Filesystem lookup table, so incompatible with 8.4a3, but
	not older versions of Tcl. The change also allows 'link' and
	'reporting' filesystems to function correctly when loading files.
	Implementation of 'file delete -force' copes with case where cwd is
	inside the directory. Moved overlooked Tcl_FSGetPathType from internal
	to external API. Made sure filesystems which are registered and then
	unregistered are only freed when all references to them are gone.
	Documented changes.
	* unix/tclUnixFCmd.c: when deleting directories recursively, make sure
	permissions are ok. Together with the above, this fixes [Bug 219139]
	* tests/winFCmd.test: differentiated test results for win2k versus
	not. This fixes [Bug: 219239]
	* tests/fCmd.test: added tests for 'file delete -force' where the cwd
	is inside, and when permissions are inadequate.

2001-09-04  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclCompile.c: fixed incorrect operands for INST_LIST [Bug
	458241] (David Cuthbert, dacut@users.sourceforge.net)

2001-09-03  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclExecute.c (TclExecuteByteCode): fixed missing comma in
	debug macro.

2001-09-03  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/ExprLongObj.3: Fixed error in documentation of argument type to
	Tcl_ExprObj [Bug 457435]

2001-09-02  David Gravereaux <davygrvy@pobox.com>

	* win/tclWinThrd.c:  Portability fix for Cygwin who's c-runtime,
	not surprisingly, doesn't have the MSVCRT specific _beginthreadex /
	_endthreadex pair. This might have to be revisited for proper Borland,
	lcc32, Watcom and other support as well. [Patch 444255]

	* win/tclWinThrd.c:  Moved FinalizeConditionEvent() proto to within
	the main #ifdef TCL_THREADS block to avoid mingw warning about it
	being there but unused.

	* win/makefile.vc:  Added -Zl (zee el) to tclStubLib.c compile line to
	make sure the tclstub84.lib static library is built without requiring
	a specific C-runtime library at link-time for the end-use developer.
	It has been noted on c.l.t that this trips many first time users
	trying to make extensions. [Patch 403533]

2001-08-31  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclInt.h: added TclCompileListCmd header
	* generic/tclBasic.c: added TclCompileListCmd compile proc
	* generic/tclCompCmds.c (TclCompileListCmd): function to compile the
	'list' command at parse time.
	* generic/tclExecute.c (TclExecuteByteCode): definition of INST_LIST
	bytecode.

	* doc/StringObj.3: added words of warning to use Tcl_ResetResult with
	the Tcl_Append* functions.

	* tests/compile.test: added compile-11.* interp result checks
	* generic/tclUtil.c (TclGetIntForIndex): added Tcl_ResetResult before
	Tcl_AppendStringsToObj to prevent shared object crash when called from
	bcc instruction. The Tcl_Append* calls that append to the result
	object that are invoked by bcc insts must remember to call
	Tcl_ResetResult because the bcc doesn't do this for us. [Bug 456892]

2001-08-30  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclIndexObj.c: fixed some casting problems that upset Crays.
	[Bug 419528] (andreasen)

2001-08-30  Don Porter  <dgp@users.sourceforge.net>

	* generic/tcl.h: Silence warning from Sun compiler. [Bug 454374]

2001-08-30  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c: allow cached fully-qualified command names to
	be usable from different namespaces within the same interpreter
	without forcing a new lookup. This speeds up scripts that pass command
	names in variables ("this" in some OO packages). [Patch 456668]

2001-08-30 Vince Darley <vincentdarley@users.sourceforge.net>

	Further fs updates. After examining the most common Tcl extensions
	(TclX, BLT, Tk, TclPro, Mktclapp), it has been determined that only
	TclpGetCwd and the Access/Stat/Open insert/delete hooks of the
	internal fs functions are ever used. The remaining functions from
	Tcl's internal interfaces have therefore been removed, since Tcl now
	exports a more suitable public API (Tcl_FS...)

	* generic/tclInt.stubs:
	* generic/tclInt.h: updated for removed internal functions. Some new
	internal functions have been put in tclInt.h (and not exported in the
	stub table because good public equivalents exist).
	* generic/tclTest.c: some test functions used the internal private
	APIs. These tests have been retained, but modified to use public APIs.
	Also objectified the internal filesystem tests.
	* win/tclWinFile.c: removed TclpStat, TclpAccess and refactored code
	to use NativeAccess, NativeStat. This should speed up stat, access and
	glob commands.
	* win/tclWinFCmd.c: removed all TclpCopy/Rename/Delete File/Directory
	string-based procedures which aren't used any more. Improved
	efficiency of some other procedures. Ensure that filename conversions
	with a NULL interp do not crash Tcl.
	* mac/tclMacFCmd.c: wrapped long lines and cleaned up
	TclpObjNormalizePath, removed all TclpCopy/Rename/Delete
	File/Directory string-based procedures which aren't used any more.
	* mac/tclMacFile.c: removed obsolete TclpStat, TclpAccess, TclpChdir,
	etc.
	* unix/tclUnixFCmd.c: removed use of TclpAccess, removed all
	TclpCopy/Rename/Delete File/Directory string-based procedures which
	aren't used any more.
	* unix/tclUnixFile.c: removed obsolete TclpStat, TclpAccess,
	TclpChdir, etc.
	* tcl(Unix|Mac|Win)Chan.c: objectified TclpOpenFileChannel.
	* various 'load' implementations all objectified.
	* generic/tclFileName.c: removed redundant code.
	* generic/tclIOUtil.c: removed TclStat, TclAccess, TclpListVolumes.
	Fix to MatchInDirectory at the root of a volume. Also improved some
	documentation, and improved default path joining behaviour for virtual
	filesystems, especially regarding '~'.
	* tests/fileName.test: added tests to check for bugs fixed above.
	* doc/FileName.3: improved documentation

2001-08-30  David Gravereaux <davygrvy@pobox.com>

	* generic/tclAsync.c:
	* generic/tclEvent.c:
	* generic/tclInt.h: Improper cleanup of asyncMutex in tclAsync.c
	repaired. TclFinalizeSynchronization() was trying to remove a
	registered mutex that was dumped earlier when the TSD it was stored in
	was cleared. This was only surfacing on *nix. Windows was being masked
	by mutexes not actually being returned to the system! That was
	repaired in a previous patch. Needed to add a private
	TclFinalizeAsync() to tclAsync.c and called from Tcl_FinalizeThread().
	Pheww.. Is this done yet? [Bug 414419] requested by Rob Ratcliff
	<rrr6399@futuretek.com>

2001-08-28  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclCompCmds.c (TclPushVarName): noted 'static' defn.
	[Bug 453872]

2001-08-26  Don Porter <dgp@users.sourceforge.net>

	* library/auto.tcl (tcl_findLibrary):
	* tests/unixInit.test (unixInit-2.{1,9}):
	* unix/tclUnixInit.c (TclpInitLibraryPath):
	* win/tclWinInit.c (TclpInitLibraryPath):  Corrected inconsistency
	between  the search path for script libraries and the directory name
	$DISTNAME into which distributions built by 'make test' unpack. [Bug
	455642]

2001-08-24  Jeff Hobbs  <jeffh@ActiveState.com>

	* tests/stringComp.test: added string-1.3
	* generic/tclCompCmds.c (TclCompileStringCmd): changed to return
	TCL_OUT_LINE_COMPILE instead of TCL_ERROR when compiling and an
	unknown string method is called. This is necessary as the string
	command may be never called, or not until 'string' is redefined.

2001-08-24 Vince Darley <vincentdarley@users.sourceforge.net>

	* doc/glob.n: documented windows-style path issue with glob.
	[Bug 219392]
	* doc/filename.n: documented windows path/file length limitation.
	[Bug 454597]

2001-08-24  Don Porter <dgp@users.sourceforge.net>

	* tests/unixInit.test (unixInit-2.9): Corrected expected result to
	match Tcl's quirky construction of its init library path.

2001-08-23  Andreas Kupries <andreas_kupries@users.sourceforge.net>

	* win/tclWinPipe.c (BuildCommandLine): Fixed [Bug 432499]. Part of the
	code used the non-absolute path to the executable to determine
	quoting. This failed if the absolute path contained spaces, but the
	application name itself not. This bug caused no trouble on Win NT 5,
	but does for other variants in the Win* family. Report and fix due to
	Ken Poole <kenpoole@users.sourceforge.net>.

2001-08-23  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/configure:
	* unix/tcl.m4: added QNX-6 build support. [Bug 219410] (loverso)

	* unix/tclUnixFCmd.c:
	* generic/tclIOUtil.c:
	* generic/tclFileName.c: corrected minor compiler warnings.

2001-08-23 Vince Darley <vincentdarley@users.sourceforge.net>

	Variety of small filesystem and vfs issues fixed or improved. The new
	fs code allows many new opportunities for efficiency improvements
	through the objectified API. The main changes integrated here are such
	efficiency improvements. Some limitations of the original
	implementation have also now been lifted. Meanwhile a variety of fs
	bugs (some old, some new) have also been fixed.

	* generic/tclFileName.c: Made Tcl_FSSplitPath more efficient, and
	removed some static string-based procedures which are no longer used.
	Much more objectification. Tcl_FSJoinPath is now very efficient and
	more aware of virtual filesystems. Clarified where the Mac-specific
	code attempts to interpret Unix-style paths. Modified TclDoGlob to use
	lstat not access to fix [Bug 434876] (L. Virden)

	* tcl(Win|Unix|Mac)FCmd.c:
	* tcl(Win|Unix|Mac)File.c: replaced TclpListVolumes with
	TclpObjListVolumes with different signature, updated code due to more
	efficient signature of Tcl_FSGetTranslatedPath. Used cached native
	paths where possible to improve efficiency -- this was completed on
	MacOS, but on Unix and Win the traversal functions make the task much
	more complex, so there are still some improvements possible there.
	Removed unused TclpNormalizePath which had been left in tclWinFCmd.c.
	Objectified all 'file attributes' functions. Fixed the new [Bug
	451571, Bruce Stephens] which is most obvious on Unix, but could occur
	on MacOS or Windows. This bug actually existed in Tcl 8.3.x but was
	only made obvious by the recent filesystem overhaul when the code was
	exercised more heavily.
	* tests/fileName.test: Three new tests to exercise the above bug, and
	make sure it is fixed correctly.
	* unix/tclUnixFile.c: avoid panic in glob when a link doesn't point
	anywhere. It would probably be good to define exactly what Tcl should
	do in circumstances like these, and make sure mac/win/unix all behave
	accordingly. [Bug 417111] (Hemang Lavana). Also fixed
	misleading/obsolete comment in the code.
	* generic/tcl.stubs: changed signature of Tcl_FSGetTranslatedPath and
	added Tcl_FSGetTranslatedStringPath.
	These changes allow further optimisations in the FS code.
	* generic/tcl.h: changed signature of Tcl_FSListVolumes so that it
	doesn't require a Tcl interpreter plus result. Renamed Tcl_FSReadLink
	to Tcl_FSLink with additional argument so we can support making links
	in the future. [Patch: 450340]
	* generic/tclInt.h: added declaration for TclpObjListVolumes.
	Objectified internal call signatures for 'file attributes' functions,
	and added an internal objectified get path type function.
	* generic/tclIOUtil.c: added the moved function TclpListVolumes which
	calls platform specific code (needed for backwards compatibility), and
	improved efficiency of parts of the FS (particularly file
	normalization). Much less copying and memory allocation is required
	now. added new GetPathType so that changes in 'file volumes' can
	actually affect files' types, and objectified more code. Made current
	code work with test suite artificially changing current platform.
	Added 'static' keywords where required.
	* generic/tclIO.c:
	* generic/tclTest.c: Added 'static' keywords, fixing [Bug 453872] (Bob
	Techentin)
	* generic/tclCmdAH.c: file command implementation updated for API
	changes, removed unnecessary special-case SplitPath static function,
	since it no longer helps prevent code duplication. Moved setting of
	interpreter result to each individual location that actually required
	it, to avoid very large code separation between reading and setting
	the result.
	* doc/FileSystem.3: updated documentation for the new or changed APIs,
	and clarified some issues.
	* doc/SplitPath.3: added pointer to newer APIs in FileSystem.3
	* doc/filename.n: clarified current implementation of tilde support on
	Mac/Win.  [Bug 453514] (Sergey Kuzmin)
	* doc/glob.n: improved documentation for '-directory' and '-path'
	options.

	There are now many private, obsolete, platform-specific 'Tclp'
	string-based filesystem APIs which could be removed. We should check
	whether any of these are used by extensions and, at least in Tcl 9,
	remove them.

	The above changes signify a ***POTENTIAL INCOMPATIBILITY*** with
	8.4a3, since signatures of two functions in the new API have changed,
	but not with older versions of Tcl.

2001-08-23  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclBinary.c (FormatNumber): Extract a long from the object
	and not an int, to stop [binary format] from being unable to format
	some input numbers on architectures where sizeof(int) is less than
	sizeof(long) (particularly Alpha). [tiprender Bug 441861]

	* tests/format.test: Converted conditional execution of tests into a
	test constraint.

2001-08-22  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/Makefile.in:
	* win/makefile.vc: updated install target for dde1.2
	* doc/dde.n: fixed dde man page (which was totally incorrect).
	* tests/winDde.test:
	* win/tclWinDde.c (Tcl_DdeObjCmd): added -binary option to dde request
	command to allow for returning binary data. [Bug 227482]
	Updated dde to 1.2

	* tests/tcltest.test: added unixExecs constraint to files that used
	'grep' in the test. [Bug 453143]

	* library/tcltest/tcltest.tcl: fixed stdio constraint test. [Patch
	454050] (stanton)
	Simplified unixExecs constraint test.

2001-08-22  Don Porter <dgp@users.sourceforge.net>

	* tests/ioUtil.test (ioUtil-3.*): Corrected errors in tests revealed
	by fix of overagressive compiler. [Bug 451200]

2001-08-21  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclCompCmds.c:
	* tests/compile.test: Fixed overagressive compilation of [catch]: it
	was catching errors at substitution time. [Bug 219184]

2001-08-21  Jeff Hobbs  <jeffh@ActiveState.com>

	* tests/tcltest.test (tcltest-12.2): fixed test that would break when
	env vars weren't Tcl list friendly [Patch 454046] (stanton)

2001-08-20  Jeff Hobbs  <jeffh@ActiveState.com>

	* library/http/http.tcl (geturl): added port number to Host: header to
	comply with HTTP/1.1 spec (RFC 2068). [Bug 452217]

2001-08-16  David Gravereaux <davygrvy@pobox.com>

	* tools/tcl.wse.in:
	* tools/tcl.hpj.in:
	* win/tcl.hpj.in:  Removed -kb storage in CVS to ensure these text
	files are checked-out in the translation mode CVS is in. Setting these
	as binary as part of an effort to make sure they are always in CRLF,
	no matter what the CVS translation, is bypassing how CVS works and is
	confusing.

	* tools/genStubs.tcl:  Removed LF-only output. Having to reconvert
	back to CRLF before committing to CVS was giving me a headache. [Bug
	451333]

	* win/makefile.vc: replaced $(WINDIR) with $(include32) for the
	.rc.res inference rule. winver.h wasn't getting included. [Bug 445630]

2001-08-14  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclBasic.c: make the intial maxNestingDepth of an
	interpreter be MAX_NESTING_DEPTH instead of a hardwired value. [Bug
	232564]

2001-08-13  Miguel Sofer  <msofer@users.sourceforge.net>

	* tests/trace.test: Corrected test numbers. [Bug 449794]

2001-08-12  Mo DeJong  <mdejong@redhat.com>

	* unix/configure: Regen.
	* unix/configure.in:
	* unix/tcl.m4: Use GCC variable set by AC_PROG_CC instead of defining
	our own using_gcc variable.

2001-08-11  Vince Darley <vincentdarley@users.sourceforge.net>

	Variety of small issues introduced by the vfs code fixed:
	* generic/tclIOUtil.c: uninitialised read.
	* generic/tclFCmd.c: possible memory leak in file delete with error
	condition.

2001-08-10  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclVar.c:
	* tests/trace.test: Insure that [array] traces work correctly for
	undefined variables. [Bug 449094]

2001-08-09  Mo DeJong  <mdejong@redhat.com>

	* unix/Makefile.in: Delete the unused getcwd.o target. [Bug 440942]

2001-08-08  Don Porter <dgp@users.sourceforge.net>

	* library/dde/pkgIndex.tcl:
	* library/http/http.tcl:
	* library/http/pkgIndex.tcl:
	* library/msgcat/msgcat.tcl:
	* library/msgcat/pkgIndex.tcl:
	* library/opt/optparse.tcl:
	* library/opt/pkgIndex.tcl:
	* library/reg/pkgIndex.tcl:
	* library/tcltest/tcltest.tcl:
	* library/tcltest/pkgIndex.tcl: Added checks for package dependencies.
	Bumped patchlevels of changed packages: http 2.3.2, msgcat 1.2.2,
	opt 0.4.3, tcltest 2.0.1. [Patch 448931]

	* README:
	* generic/tcl.h:
	* tools/tcl.wse.in:
	* unix/configure:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/README.binary:
	* win/configure:
	* win/configure.in: Bumped up patchlevel to 8.4a4 to distinguish CVS
	snapshots from the 8.4a3 release. This does not necessarily mean there
	will be an 8.4a4 release. [Bug 448938]

2001-08-06  Jeff Hobbs  <jeffh@ActiveState.com>

	8.4a3 RELEASE

	* changes:
	* README:
	* mac/README:
	* unix/README:
	* win/README.binary: updated for 8.4a3 release

	* generic/tclFileName.c (Tcl_FSSplitPath): update to Tcl style guide.

	* generic/tclFCmd.c (FileCopyRename): fixed mem leak in introduction
	of vfs code where a new Tcl_Obj wasn't freed.

	* generic/tclCmdMZ.c (Tcl_RegexpObjCmd, Tcl_RegsubObjCmd): reordered
	the retrieval of arguments to avoid shimmering bug when the pattern
	and string referenced the same object.

	* unix/configure: regenerated
	* unixE/tcl.m4: added GNU (HURD) configuration target.
	[Patch 442974] (brinkmann)

	* win/README: made note of URL for Windows compilation notes

	* win/tclWinThrd.c (TclpFinalizeMutex, TclpFinalizeCondition): added
	DeleteCriticalSection calls for cleanup [Patch 419683]

	* unix/tclUnixPipe.c (TclpCreateTempFile): fixed use of tmpnam,
	which is dangerous. [Patch 442636] (lim)
	The use of tmpnam in TclpTempFileName must still be changed.

	* tests/http.test (http-4.14): fixed variable error return.
	[Bug 424252]

2001-08-03  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/configure: regenerated
	* win/tcl.m4: fixed DLLSUFFIX definition to always be ${DBGX}.dll.
	This is necessary for TEA compliant builds that build shared against a
	static-built Tcl.
	* win/Makefile.in ($(TCLSH)): added $(TCL_STUB_LIB_FILE) to build
	target, otherwise it wouldn't get generated in a static build.

2001-08-06  Andreas Kupries <andreas_kupries@users.sourceforge.net>

	* generic/tclIOCmd.c (Tcl_GetsObjCmd): Applied patch from [Bug 442665]
	to fix the bug reported by it. The function can corrupt a freed object
	if it is called with objc == 3. This is because it retrieves resultPtr
	and does not increment its reference count, but then calls
	Tcl_ObjSetVar2, which causes the retrieved resultPtr object to be
	released.

2001-08-06  Don Porter <dgp@users.sourceforge.net>

	* doc/tclsh.1: Added note that the tclsh program is frequently
	installed with the Tcl version numer as part of the name. [Patch
	402725]

	* generic/tclPkg.c:
	* tests/pkg.test:  [package forget] now forgets all of the package
	arguments it receives, not stopping when a package is not found. [Bug
	415273]

2001-08-02  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclIOUtil.c (Tcl_FSMatchInDirectory): corrected
	uninitialized value.

2001-08-02  Mo DeJong  <mdejong@redhat.com>

	* generic/tclPlatDecls.h:
	* win/tclWinPort.h: Revert <tchar.h> related changes made to improve
	Cygwin support on 2001-07-18. This change ended up breaking the VC++
	build because of conflicts between Windows APIs and internal Tk APIs.

2001-08-01  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/tclUnixFCmd.c: minor casts to eliminate warnings. (lim)
	[Patch 440218]

	* tests/parseOld.test: changed some tests that required testwordend to
	exist to skip in a proper tcltest manner. [Bug 442663]

	* library/http/http.tcl (http::mapReply): the regsub'ing of \n and \t
	to escape them was unnecessary.

2001-07-31  Vince Darley <vincentdarley@users.sourceforge.net>

	Changes from TIP#17 "Redo Tcl's filesystem"
	The following files were impacted:
	* doc/Access.3:
	* doc/FileSystem.3:
	* doc/OpenFileChnl.3:
	* doc/file.n:
	* doc/glob.n:
	* generic/tcl.decls:
	* generic/tcl.h:
	* generic/tclCmdAH.c:
	* generic/tclCmdIL.c:
	* generic/tclCmdMZ.c:
	* generic/tclDate.c:
	* generic/tclDecls.h:
	* generic/tclEncoding.c:
	* generic/tclFCmd.c:
	* generic/tclFileName.c:
	* generic/tclGetDate.y:
	* generic/tclIO.c:
	* generic/tclIOCmd.c:
	* generic/tclIOUtil.c:
	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclIntDecls.h:
	* generic/tclLoad.c:
	* generic/tclStubInit.c:
	* generic/tclTest.c:
	* generic/tclUtil.c:
	* library/init.tcl:
	* mac/tclMacFCmd.c:
	* mac/tclMacFile.c:
	* mac/tclMacInit.c:
	* mac/tclMacPort.h:
	* mac/tclMacResource.c:
	* mac/tclMacTime.c:
	* tests/cmdAH.test:
	* tests/event.test:
	* tests/fCmd.test:
	* tests/fileName.test:
	* tests/io.test:
	* tests/ioCmd.test:
	* tests/proc-old.test:
	* tests/registry.test:
	* tests/unixFCmd.test:
	* tests/winDde.test:
	* tests/winFCmd.test:
	* unix/mkLinks:
	* unix/tclUnixFCmd.c:
	* unix/tclUnixFile.c:
	* unix/tclUnixInit.c:
	* unix/tclUnixPipe.c:
	* win/tclWinFCmd.c:
	* win/tclWinFile.c:
	* win/tclWinInit.c:
	* win/tclWinPipe.c:

2001-07-24  Mo DeJong  <mdejong@redhat.com>

	* win/tclWinThrd.c (Tcl_CreateThread): Close Windows HANDLE returned
	by _beginthreadex. The MS documentation states that this handle is not
	closed by a later call to _endthreadex.

2001-07-21  Don Porter  <dgp@users.sourceforge.net>

	* doc/pkgMkindex.n:
	* library/package.tcl:  Corrected documentation and usage message of
	[pkg_mkIndex].

2001-07-18  Mo DeJong  <mdejong@redhat.com>

	* generic/tclPlatDecls.h: Define TCHAR by including windows.h instead
	of tchar.h since Cygwin does not support the tchar.h header. Include
	CHECK_UNICODE_CALLS logic from tclWinPort.h.
	* win/tclWinPort.h: Remove CHECK_UNICODE_CALLS logic. Remove include
	of windows.h since this now done it tclPlatDecls.h.
	* win/tclWinReg.c: Remove duplicate include of windows.h.

2001-07-18  Andreas Kupries <andreas_kupries@users.sourceforge.net>

	* generic/tclIO.c: Aftermath to [Bug 427196]. Squash empty buffers if
	they are smaller than the requested buffersize, to prevent reusage of
	old buffers and to honor changes in the requested buffersize made by
	the user.

2001-07-17  Mo DeJong  <mdejong@redhat.com>

	* win/tclWinFile.c (TclpReadlink): Add Cygwin specific definition for
	the TclpReadlink function. This method implements reading of symbolic
	links when build with Cygwin.

2001-07-17  Mo DeJong  <mdejong@redhat.com>

	* win/tclWinPort.h: Add Cygwin specific defines for environ and
	timezone variables.

2001-07-17  Andreas Kupries <andreas_kupries@users.sourceforge.net>

	* generic/tclIO.c (GetInput): Fixed [Bug 427196]. Memory was
	overwritten because a buffer was used after a change of the requested
	buffersize together with that requested buffersize and not its actual
	size, which was smaller. Note that the continous reuse of the smaller
	buffer negatively impacts performance. The system never allocates a
	buffer with the newly requested bigger buffersize.

2001-07-16  Mo DeJong  <mdejong@redhat.com>

	* generic/tcl.h: Define __WIN32__ when __CYGWIN__ or __MINGW32__ is
	defined.
	* generic/tclAlloc.c: Define caddr_t when compiling with VC++ or
	mingw. This type is already defined when compiling with Cygwin.

2001-07-16  Mo DeJong  <mdejong@redhat.com>

	* win/tclWinConsole.c:
	* win/tclWinPipe.c:
	* win/tclWinPort.h:
	* win/tclWinSerial.c:
	* win/tclWinThrd.c:
	Remove unnecessary #includes of dos.h, direct.h, and tchar.h. This
	will help the Cygwin porting effort since these headers do not exist
	under Cygwin.

2001-07-16  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/tclWinPipe.c (PipeClose2Proc): constrained the mutex lock to
	just the TerminateThread call and waiting for termination. (jsmith)

	* generic/tclCmdMZ.c: Removed extra copy of the SCAN_* macros
	#defined in generic/tclScan.c. [Bug 441230] (porter)

2001-07-12  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/unixInit.test (unixInit-2.8): Added extra constraint,
	notInstalledInTmp, to stop this test from damaging installations in
	/tmp; not much fun to have to reinstall the Tcl library every time you
	run the test suite!

	* tests/subst.test (subst-10.*): Updated tests to check new behaviour
	for 'break' in command substitutions.
	(subst-1.2,subst-7.1): Error messages changed.
	* doc/SubstObj.3: New file, to document Tcl_SubstObj.
	* doc/subst.n: Improved and updated documentation for 'subst' to help
	support the changed behaviour.
	* generic/tcl.decls (generic-437): Declaration for Tcl_SubstObj
	* generic/tcl.h (TCL_SUBST_*): Added flags for Tcl_SubstObj.
	* generic/tclCmdMZ.c (Tcl_SubstObj,Tcl_SubstObjCmd): Divided into two
	parts to allow people to access the innards of 'subst' and changed the
	behaviour when command substitutions do a 'break' to be different from
	'continue'. Also now works with objects, which allows for some nifty
	optimisations with variable substitutions and a slight improvement
	with command substitutions. [TIP#36]

2001-07-10  Mo DeJong  <mdejong@redhat.com>

	* unix/Makefile.in: Add AR variable for use in STLIB_LD.
	* unix/configure: Regen.
	* unix/configure.in: Use STLIB_LD when defining MAKE_LIB and
	MAKE_STUB_LIB. Subst RANLIB and AR.
	* unix/tcl.m4 (SC_CONFIG_CFLAGS): Add doc comment about STLIB_LD
	command. Check ${AR} env var when setting STLIB_LD and delay
	evaluation until make time.
	* win/configure: Regen.
	* win/tcl.m4 (SC_CONFIG_CFLAGS): Delay evaluation of ${AR} in STLIB_LD
	and add flags to better match the Unix implementation. Don't bother
	defining AR when using VC++ since it is not used.

2001-07-06  Mo DeJong  <mdejong@redhat.com>

	* win/configure: Regen.
	* win/tcl.m4 (SC_CONFIG_CFLAGS): Pass -e _WinMain@16 in addition to
	the -mwindows flag to work around a problem with ld when it
	incorrectly use main() as the executable entry point when both
	WinMain() and main() are available.

2001-07-06  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/cmdAH.test: Added leading zero to file modes to work around
	fault in HPUX strtol() which ignores the base parameter. [Bug 438808]

2001-07-05  Mo DeJong  <mdejong@redhat.com>

	* win/Makefile.in: Subst DEPARG directly instead of relying on a
	variable. This will make Cygwin builds faster since an extra exec will
	be avoided.
	* win/configure: Regen.
	* win/configure.in: Subst DEPARG.
	* win/tcl.m4 (SC_CONFIG_CFLAGS): Move AC_MSG_CHECKING after the
	AC_CHECK_PROG so that status messages do not get mixed together. Set
	DEPARG based on the results of the cygpath check so that we avoid
	using an extra exec when it is not needed. Use ac_cv_cygwin status
	flag instead of looking at the output of gcc -v, which works in the
	case where -mno-cygwin is set in the CFLAGS.

2001-07-04  Jeff Hobbs  <jeffh@ActiveState.com>

	* README:
	* mac/README:
	* unix/README:
	* win/README:
	* win/README.binary: updated READMEs with purls

2001-07-03  Mo DeJong  <mdejong@redhat.com>

	* win/Makefile.in: Remove PATHTYPE variable.
	* win/configure: Regen.
	* win/configure.in: Don't subst PATHTYPE.
	* win/tcl.m4 (SC_CONFIG_CFLAGS): Remove PATHTYPE variable. Set CYGPATH
	to "cygpath -w" if the cygpath executable is found on the path. This
	approach works for native Cygwin builds and cross compiles.

2001-07-03  Jeff Hobbs  <jeffh@ActiveState.com>

	* tests/var.test:
	* generic/tclVar.c (Tcl_VariableObjCmd): added patch to check for
	number of args. [Patch 426038]

	* generic/tclVar.c (Tcl_GetVar2Ex): added ability to recognize
	TCL_TRACE_READS flags to cause creation of part1 in TclLookupVar to
	make sure newly created array will get read traces triggered
	appropriately. This is called by Tcl_ObjGetVar2, Tcl_GetVar, and
	Tcl_GetVar2.
	(TclSetIndexedScalar, TclSetElementOfIndexedArray): added read trace
	triggering for lappend case.
	(Tcl_LappendObjCmd): pass TCL_TRACE_READS to Tcl_ObjGetVar2 to trigger
	possible read traces for new arrays.

	* generic/tclExecute.c (TclExecuteByteCode): added TCL_TRACE_READS
	flag to INST_LAPPEND(_ARRAY)_STK case to trigger read traces for newly
	created arrays. Removed unnecessary #ifdef for TCL_COMPILE_DEBUG in
	INST_LOAD_SCALAR1 case.

	* tests/append.test:
	* tests/appendComp.test: added tests for read trace triggering for
	append and lappend.

2001-07-03  Mo DeJong  <mdejong@redhat.com>

	* tests/clock.test (clock-2.5): Adjust test so that it passes when the
	time slice is 60 msecs, now passes under Windows 98.

2001-07-03  Mo DeJong  <mdejong@redhat.com>

	* win/tcl.m4 (SC_CONFIG_CFLAGS): Don't pass the v flag to ${AR} when
	using gcc, verbose output is not needed.

2001-07-03  Don Porter  <dgp@users.sourceforge.net>

	* tests/unixInit.test (unixInit-2.8):  Changed test back to using
	installation layout, adding comments explaining why the test writes to
	the directories it does, and checks to avoid destroying other files in
	/tmp.

2001-07-03  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/unixInit.test (unixInit-1.2): Fixed faults reported in
	[Bug 438070] - well, at least enough to work on Solaris - and added
	comments that should make what is going on in the test clearer.

2001-07-02  Jeff Hobbs  <jeffh@ActiveState.com>

	* tests/util.test: added util-4.6
	* generic/tclUtil.c (Tcl_ConcatObj): Corrected walking backwards over
	utf-8 chars. [Bug 227512]

2001-07-02  Don Porter  <dgp@users.sourceforge.net>

	* tests/unixInit.test (unixInit-2.8):  Corrected test for all absolute
	pathnames in library path when executable is installed near root
	directory to use correct development directory layout. [Bug 438014]

	* tests/unixInit.test (unixInit-2.9):
	* unix/tclUnixInit.c (TclpInitLibraryPath):
	* win/tclWinInit.c (TclpInitLibraryPath):  Corrected buggy
	construction of search path entries relative to executable. Added test
	for bad construction. [Bug 438014]

2001-06-28  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclNamesp.c: Correction to faulty patch from [Bug 231259]

2001-06-28  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/unixInit.test (unixInit-1.2): Modified so as not to require a
	local echo service, which fails on many systems which have that turned
	off for security reasons...

2001-06-27  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclInt.h:
	* generic/tclObj.c:
	* unix/Makefile.in: added a -DPURIFY mode that makes Tcl_Obj's
	allocated and free singularly (instead of in alloc in blocks and never
	free) to allow checkers like Purify to operate better.

	* library/encoding/koi8-u.enc: added koi8-u (Ukranian variant)
	encoding.

	* tests/subst.test:
	* generic/tclUtf.c (Tcl_UtfBackslash): Corrected backslash handling of
	multibyte utf-8 chars. [Bug 217987]

	* generic/tclCmdIL.c (InfoProcsCmd): fixed potential mem leak in info
	procs that created objects without using them.

	* generic/tclCompCmds.c (TclCompileStringCmd): fixed mem leak when
	string command failed to parse the subcommand.

	* doc/interp.n:
	* doc/unknown.n: updated notes about what is in a safe interp. [Bug
	218605]

2001-06-27  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/event.test (event-11.5): Removed hard-coded port number which
	could fail on some systems. [Bug 436727]

2001-06-26  Mo DeJong  <mdejong@redhat.com>

	* unix/Makefile.in:
	* win/Makefile.in: Add `make shell` target. This target will set the
	proper env vars before invoking tclsh from the build directory.

2001-06-26  Mo DeJong  <mdejong@redhat.com>

	* win/Makefile.in: Use : to separate VPATH entries. This works for
	both Cygwin builds and cross builds, the VPSEP variable is simply
	unneeded complexity.
	* win/configure: Regen.
	* win/configure.in: Don't subst VPSEP.
	* win/tcl.m4 (SC_CONFIG_CFLAGS): Remove VPSEP variable.

2001-06-26  Mo DeJong  <mdejong@redhat.com>

	* unix/configure: Regen.
	* unix/configure.in: Fix last checkin by removing export since that
	only works in bash.
	* win/configure: Regen.
	* win/configure.in: Ditto.

2001-06-26  Mo DeJong  <mdejong@redhat.com>

	* unix/configure: Regen.
	* unix/configure.in: Set CFLAGS to "" if the user did not set CFLAGS
	in the env. This keeps AC_PROG_CC from adding "-g -O2" to the CFLAGS
	by default.
	* win/configure: Regen.
	* win/configure.in: Ditto.

2001-06-25  Mo DeJong  <mdejong@redhat.com>

	* win/configure: Regen.
	* win/configure.in: Use RC_DEFINE flag from tcl.m4.
	* win/tcl.m4 (SC_CONFIG_CFLAGS): Set RC_DEFINE flag based on the
	compiler in use.

2001-06-25  Mo DeJong  <mdejong@redhat.com>

	* win/tcl.m4 (SC_CONFIG_CFLAGS): Link to the imm32 library when
	building with mingw gcc.

2001-06-25  Mo DeJong  <mdejong@redhat.com>

	* win/configure: Regen.
	* win/tcl.m4 (SC_CONFIG_CFLAGS): When building with gcc, don't attempt
	to link with LD or support dllwrap. Simply require a recent version of
	Cygwin gcc or Mingw gcc that supports -shared. When linking, use gcc
	instead of ld since gcc automatically includes libs like -lmsvcrt.

2001-06-22  Mo DeJong  <mdejong@redhat.com>

	* win/configure: Regen.
	* win/configure.in: Add resource compiler fix from 8.3.3 to fix
	compiling with mingw.

2001-06-22  Mo DeJong  <mdejong@redhat.com>

	* win/configure: Regen.
	* win/tcl.m4: Fix silly typo in last checkin.

2001-06-22  Mo DeJong  <mdejong@redhat.com>

	* unix/Makefile.in: Set CFLAGS to @CFLAGS@ and @CFLAGS_DEFAULT@. Set
	LDFLAGS to @LDFLAGS@ and @LDFLAGS_DEFAULT@. Add LDFLAGS_DEBUG and
	LDFLAGS_OPTIMIZE to match the way CFLAGS_DEFAULT works. This will
	support user set CFLAGS or LDFLAGS at configure time.
	* unix/configure: Regen.
	* unix/configure.in: Don't set CFLAGS to CFLAGS_DEFAULT, instead
	subst CFLAGS_DEFAULT into the Makefile. Add AC_SUBST for
	CFLAGS_DEFAULT, LDFLAGS_DEFAULT, LDFLAGS_DEBUG, and LDFLAGS_OPTIMIZE.
	* unix/tcl.m4 (SC_ENABLE_SYMBOLS): Modify LDFLAGS_DEFAULT so that it
	uses a Makefile variable just like CFLAGS_DEFAULT.
	* win/Makefile.in: Set CFLAGS to @CFLAGS@ and @CFLAGS_DEFAULT@. Set
	LDFLAGS to @LDFLAGS@ and @LDFLAGS_DEFAULT@. This will support user set
	CFLAGS or LDFLAGS at configure time.
	* win/configure: Regen.
	* win/configure.in: Don't set CFLAGS or LDFLAGS, instead subst
	CFLAGS_DEFAULT and LDFLAGS_DEFAULT into the Makefile.
	* win/tcl.m4 (SC_ENABLE_SYMBOLS): Modify LDFLAGS_DEFAULT so that it
	uses a Makefile variable just like CFLAGS_DEFAULT.

2001-06-22  Mo DeJong  <mdejong@redhat.com>

	* win/configure:
	* win/tcl.m4 (SC_CONFIG_CFLAGS): Don't set LDFLAGS_DEBUG to -g or
	LDFLAGS_OPTIMIZE to -O when compiling with gcc. These flags are not
	needed and can cause problems with the Cygwin version of ld.

2001-06-18  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/unixInit.test (unixInit-1.2,unixInit-2.8): Added test for code
	described below, and fixed a couple of errors that caused problems
	during testing; the code to determine the installedTcl constraint was
	wrong, and test unixInit-2.8 assumed that /tmp/lib was free for use
	and could be deleted, which clashed nastily with my installation and
	made other tests fail unnecessarily!

	* unix/tclUnixChan.c (TtyInit,TclpOpenFileChannel,
	(Tcl_MakeFileChannel,TclpGetDefaultStdChannel): Alterations so that
	the standard channels - stdin, stdout and stderr - have the correct
	type and fconfigure options. This required making the initialisation
	of serial lines a little more sophisticated to make the console behave
	correctly in interactive mode... [Bug 219137 and duplicates]

2001-06-16  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclPanic.c (Tcl_PanicVA):
	* mac/tclMacAppInit.c (main):
	* mac/tclMacPanic.c (TclpPanic):
	* unix/tclUnixPort.h:
	* win/tclWinPort.h: Replaced TclMacSetPanic with TclpPanic for setting
	a platform-specific panic handler. TclpPanic is NULL on Unix and
	Windows. Fixes broken wish on Mac due to earlier patches. [Patch
	415648]

	* generic/tclIntPlatDecls.h:
	* generic/tclStubInit.c: `make gentubs` after above changes.

2001-06-13  Don Porter  <dgp@users.sourceforge.net>

	* mac/tclMacAppInit.c (main, Macintosh_Init):
	* mac/tclMacBOAAppInit.c (main):
	* mac/tclMacPanic.c: Applied patches from Dan Steffen correcting
	problems on the Macintosh in the 2001-06-08 changes.

2001-06-12  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/regexp.test (regexp-18.12):
	* generic/tclCmdMZ.c (Tcl_RegexpObjCmd): Fixed so that submatches
	that do not match always have index pair {-1 -1} [Bug 219232]

2001-06-08  Don Porter  <dgp@users.sourceforge.net>

	* generic/tcl.h:
	* generic/tcl.decls:
	* generic/tclPanic.c: Added CONST to Tcl_*Panic* public interfaces.
	[Patch 415648, TIP 27]

	* generic/tclInt.decls:
	* mac/tclMacAppInit.c (main):
	* mac/tclMacBOAAppInit.c (main):
	* mac/tclMacPanic.c: Modified special Mac implementations of
	Tcl_*Panic* to be exact copies of the generic implementations. Added
	TclMacSetPanic. The generic implementations should be used directly,
	rather than copies, but that requires further changes by someone
	familiar with the Mac build systems. [Patch 415648]

	* generic/tclDecls.h:
	* generic/tclIntPlatDecls.h:
	* generic/tclStubInit.c: `make gentubs` after above changes.

	* doc/Panic.3:
	* unix/mkLinks:  New file documenting Tcl_*Panic* public interfaces,
	followed by `make mklinks`. [Patch 415648, Bug 219170, Bug 414936]

2001-06-03  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclUtil.c (Tcl_DStringAppendElement): patch to save an
	extra strlen call. [Bug 428572]

2001-05-30  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclExecute.c (TclExecuteByteCode): Added two casts to
	INST_STR_CMP implementation to get rid of a couple warnings from the
	SUNWspro C compiler.

	* generic/tclBasic.c (Tcl_GetMathFuncInfo,Tcl_ListMathFuncs):
	* generic/tclCmdIL.c (Tcl_InfoObjCmd,InfoFunctionsCmd):
	* generic/tcl.decls (generic table, positions 435+436):
	* tests/info.test:
	* doc/CrtMathFnc.3:
	* doc/info.n: Changes due to TIP #15 "Functions to List and Detail
	Math Functions"

2001-05-28  Jeff Hobbs  <jeffh@ActiveState.com>

	* library/init.tcl (unknown): removed errant " in error message

2001-05-27  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/regc_locale.c: updated character class range data for
	Unicode v3.1.0 compliance.
	* generic/tclUniData.c: regenerated from Unicode v3.1.0 data file (new
	as of 2001-05-16). This brings Tcl to current unicode compliance.

	* tests/utf.test: added tests to check unicode 3 compliance

	* unix/Makefile.in (tclUtf.o): added tclUniData.c dependency.

	* tools/uniClass.tcl: added comments to output format and the script
	for clarification.

	* tools/uniParse.tcl: corrected filename output and GetDelta macro to
	use 'info' as param (was 'infO')

2001-05-26  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclVar.c (tclArraySearchType,SetArraySearchObj,
	(ParseSearchId): Added code to speed up array searching by reducing
	the amount of parsing needed for searchIds.

	* generic/tclObj.c (TclInitObjSubsystem):
	* generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct):
	* generic/tclNamesp.c (TclInitNamespaceSubsystem):
	* generic/tclInt.h: Moved some Tcl_ObjType initialisation to
	TclInitObjSubsystem to be with the bulk of the rest. [Patch 424851]
	Committed by Miguel Sofer <mig@utdt.edu>

2001-05-23  Jeff Hobbs  <jeffh@ActiveState.com>

	* tests/io.test: changed io-52.[9-11] to not be platform sensitive
	with EOL translation.

	* library/encoding/cp1250.enc:
	* library/encoding/cp1251.enc:
	* library/encoding/cp1252.enc:
	* library/encoding/cp1253.enc:
	* library/encoding/cp1254.enc:
	* library/encoding/cp1255.enc:
	* library/encoding/cp1256.enc:
	* library/encoding/cp1257.enc:
	* library/encoding/cp1258.enc:
	* library/encoding/cp874.enc:
	* library/encoding/iso8859-6.enc:
	* library/encoding/iso8859-7.enc:
	* library/encoding/iso8859-8.enc:
	* library/encoding/iso8859-10.enc (new):
	* library/encoding/iso8859-13.enc (new):
	* library/encoding/iso8859-14.enc (new): updated encoding tables based
	on http://www.unicode.org/Public/MAPPINGS/. (kuhn)

2001-05-23  Mo DeJong  <mdejong@redhat.com>

	* unix/tcl.m4 (SC_PATH_TCLCONFIG): Fix comments, and typo in cached
	variable name.

2001-05-23  Mo DeJong  <mdejong@redhat.com>

	* unix/tcl.m4 (SC_LOAD_TKCONFIG): Remove use of undefined TCLCONFIG
	variable and call AC_MSG_RESULT to print the checking result.
	* win/tcl.m4: Ditto.

2001-05-22  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclObj.c (TclAllocateFreeObjects): simplified
	objSizePlusPadding to use sizeof(Tcl_Obj) (max) Corrected use of
	tclObjsAlloced/Freed/Shared in TCL_MEM_DEBUG compile.

2001-05-22  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c: removed Tcl_DuplicateObj in INST_DUP

2001-05-21  Jeff Hobbs  <jeffh@ActiveState.com>

	* tests/tcltest.test (tcltest-19.1): fixed failing test that was
	getting affected by Windows env handling of empty valued elements.

	* unix/tcl.m4: added more common install directories in which to
	search for *Config.sh. [Bug 419812]

	* tests/cmdMZ.test (cmdMZ-1.4): added notLinux constraint to test to
	prevent failure message on Linux due to OS caching bug.

	* tests/httpd (httpdRespond): added response to timeout value in query
	string.

	* tests/http.test: removed unused notLinux constraint setting

	* generic/tclRegexp.c (Tcl_RegExpExecObj): added use of
	Tcl_GetUnicodeFromObj.

2001-05-19  Andreas Kupries <andreas_kupries@users.sourceforge.net>

	* Note that "tclbench" (see project "tcllib") was extended with
	performance benchmarks for [fcopy] too.

	* doc/fcopy.n: Updated to reflect the extended behaviour of 'fcopy'.

	* tests/io.test: Added tests 'io-52.9', 'io-52.10' and 'io-52.11' to
	test the handling of encodings by 'fcopy' / 'TclCopychannel'. [Bug
	209210]

	* generic/tclIO.c: Split of both 'Tcl_ReadChars' and 'Tcl_WriteChars'
	into a public error checking and an internal working part. The public
	functions now use the new internal ones. The new functions are
	'DoReadChars' and 'DoWriteChars'. Extended 'CopyData' to use the new
	functions 'DoXChars' when required by the encodings on the input and
	output channels. [Bug 209210]

2001-05-16  Jeff Hobbs  <jeffh@ActiveState.com>

	* library/history.tcl (tcl::HistAdd): prevent empty calls from being
	added to the history (arndt)

	* tests/error.test: updated error-1.3 message to account for string
	index being compiled at toplevel.
	* tests/appendComp.test:
	* tests/stringComp.test: new files for extended bytecode testing

	* generic/tclBasic.c: added new CompileProc invocations to basic
	command initialization.
	* generic/tclCompCmds.c: added new compile commands for append,
	lappend, lindex and llength. Refactored set and incr compile commands
	to use new TclPushVarName function for handling the varname component
	during compilation (also used by append and lappend). Changed string
	compile command to compile toplevel code as well (when possible).
	* generic/tclCompile.c: added new instruction enums
	* generic/tclCompile.h: added debug info for new instructions
	* generic/tclExecute.c (TclExecuteByteCode): moved elemPtr to toplevel
	var (oft-used). Added definitions for new bytecode instructions
	INST_LIST_INDEX, INST_LIST_LENGTH, INST_APPEND_SCALAR1,
	INST_APPEND_SCALAR4, INST_APPEND_ARRAY1, INST_APPEND_ARRAY4,
	INST_APPEND_ARRAY_STK, INST_APPEND_STK, INST_LAPPEND_SCALAR1,
	INST_LAPPEND_SCALAR4, INST_LAPPEND_ARRAY1, INST_LAPPEND_ARRAY4,
	INST_LAPPEND_ARRAY_STK, INST_LAPPEND_STK.
	Refactored repititious code for reuse with INST_LOAD_STK (same as
	INST_LOAD_SCALAR_STK), INST_STORE_STK (same as INST_STORE_SCALAR_STK).
	Updated INST_STR_CMP with style of fix of 2001-04-06 Fellows
	[Bug 219201] as that fix only affected the runtime eval'ed "string"
	(string compare is normally byte-compiled now). We may want to back
	these out for speed in the future, noting the problems with \x00
	comparisons in the docs.
	* generic/tclInt.h: declarations for new compile commands.
	* generic/tclVar.c: change TclGetIndexedScalar,
	TclGetElementOfIndexedArray, TclSetElementOfIndexedArray and
	TclSetIndexedScalar to use flags. The Set functions now support
	TCL_APPEND_ELEMENT and TCL_LIST_ELEMENT as well.
	* generic/tclInt.decls:
	* generic/tclIntDecls.h: minor signature changes for above.

	* generic/tclCmdMZ.c: made use of new Tcl_GetUnicodeFromObj.

2001-05-16  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/console.n: Deleted. Put it in the wrong source tree! D'oh!

2001-05-15  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tcl.decls:
	* generic/tclDecls.h:
	* generic/tclStubInit.c:
	* generic/tclStringObj.c (Tcl_GetUnicodeFromObj): new function to
	parallel Tcl_GetStringFromObj (fix of an API oversight).

	* unix/tclUnixPipe.c: updated pipeChannelType to TCL_CHANNEL_VERSION_2
	type specification.

	* tests/fileName.test: corrected tests not to fail on win when a
	C:/test dir exists.

	* generic/tclFileName.c (ExtractWinRoot): corrected ABR error

2001-05-15  Miguel Sofer  <msofer@users.sourceforge.net>

	* tests/lindex.test: added test for nested braces [Patch 423617]

2001-05-15  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclInt.h:
	* generic/tclNamesp.c: invalidate all bytecodes in a namespace if a
	new command shadows a bytecoded command.
	* tests/namespace.test:
	Patched from [Bug 231259]

2001-05-15  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/console.n: Created. It seems very odd to me that the console
	implementation is part of the Tcl distribution and not part of Tk, but
	given the location of the source, the documentation must obviously
	match up...

2001-05-14  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclCmdMZ.c (Tcl_StringObjCmd):
	* tests/string.test (string-4.14): Negative string indices should not
	be added as offsets to the result of [string first] but instead be
	treated as referring to the start of the string. [Bug 423581]

2001-05-11  Mo DeJong  <mdejong@redhat.com>

	* unix/Makefile.in: Add a LDFLAGS variable to the Makefile instead of
	directly substing @LDFLAGS@.
	* unix/configure: Regen.
	* unix/tcl.m4: Fix CFLAGS_DEFAULT so that the name of a Makefile
	variable is passed as @CFLAGS@.
	* win/Makefile.in: Move the setting of CFLAGS higher up in the
	Makefile.
	* win/configure: Regen.
	* win/configure.in: Use dnl to comment out macros so that they are not
	accidently expanded.
	* win/tcl.m4: Fix CFLAGS_DEFAULT so that the name of a Makefile
	variable is passed as @CFLAGS@.

2001-05-07  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c: insure different rand() seeds in different
	threads. [Bug 416643]

2001-05-03  Jeff Hobbs  <jeffh@ActiveState.com>

	* tests/tcltest.test: removed extraneous 'c' (doh!) [Bug: 414031]

	* tools/tcltk-man2html.tcl: removed use of 'exec' for portability and
	fixed up code.

2001-05-03  Don Porter  <dgp@users.sourceforge.net>

	* doc/library.n:
	* library/init.tcl:
	* tests/autoMkindex.t*: Modified [auto_import] to apply pattern
	matching in the [namespace import] style. [Bug 420186]
	***POTENTIAL INCOMPATIBILITY*** for any callers of [auto_import] from
	outside Tcl that expect the pattern matching to be like that of
	[string match].

2001-05-03  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclParse.c:
	* tests/namespace.test: Insure consistent behaviour of the [unknown]
	command: when a command is unknown, it is always processed by
	[::unknown], ignoring any namespace proc which happens to be called
	"unknown" [Patch 421166, Bug 420507]

2001-05-02  Don Porter  <dgp@users.sourceforge.net>

	* tools/genStubs.tcl: Add a package require of Tcl 8 at the beginning
	of the script so that the script will print a descriptive error
	message when run in an old Tcl 7 shell.

2001-04-27  Kevin Kenny	<kennykb@crd.ge.com>

	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclCmdIL.c:
	* generic/tclProc.c:
	* generic/tclVar.c: Added another collection of missing CONSTs related
	to TclGetNamespaceForQualName.
	* generic/tclIntDecls.h: Regenerated.

2001-04-25  Mo DeJong  <mdejong@redhat.com>

	* unix/configure: Regen.
	* unix/tcl.m4: Subst TCL_THREADS into tclConfig.sh.
	* unix/tclConfig.sh.in: Add TCL_THREADS variable.
	* win/configure: Regen.
	* win/tcl.m4: Subst TCL_THREADS into tclConfig.sh.
	* win/tclConfig.sh.in: Add TCL_THREADS variable.

2001-04-25  Mo DeJong  <mdejong@redhat.com>

	* unix/configure: Regen.
	* unix/configure.in: Use $@ in MAKE_LIB and MAKE_STUB_LIB commands
	instead of using a delayed subst variable. Replace instances of
	STUB_LIB_FILE with TCL_STUB_LIB_FILE.

2001-04-25  Mo DeJong  <mdejong@redhat.com>

	* unix/Makefile.in: Use TCL_STUB_LIB_FILE instead of STUB_LIB_FILE.
	* unix/configure: Regen.
	* unix/configure.in: Don't subst STUB_LIB_FILE, use TCL_STUB_LIB_FILE
	instead.

2001-04-25  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tools/encoding/iso8859-15.txt:
	* library/encoding/iso8859-15.enc: Oops! Got the full encoding wrong.
	Should be fixed now...

	* tools/encoding/iso8859-15.txt:
	* library/encoding/iso8859-15.enc:
	* tools/tcl.wse.in: Added ISO 8859-15 (a.k.a. Latin-1 + Euro currency
	symbol) support.

	* generic/tclNamesp.c:
	* generic/tclBasic.c (TclRenameCommand): Missing CONST from several
	declarations relating to use of TclGetNamespaceForQualName

2001-04-24  Kevin B. Kenny    <kennykb@acm.org>

	* doc/AssocData.3:
	* doc/CrtCommand.3:
	* doc/CrtMathFnc.3:
	* doc/CrtObjCmd.3:
	* doc/ExprLong.3:
	* generic/tclBasic.c:
	* generic/tclCmdMZ.c:
	* doc/CrtSlave.3:
	* generic/tclNamesp.c:
	* generic/tcl.decls:
	* generic/tcl.h:
	* generic/tclInt.decls:
	* generic/tclInt.h: (TIP #27) Another round of CONST changes, this
	time adding CONST to the API's exported from tclBasic.c. [Patch
	415179]
	***POTENTIAL INCOMPATIBILITY*** from 8.4a2, in which Vince Darley's
	changes to command tracing were added. A const has been added to the
	type signature of one of the parameters to Tcl_CommandTraceProc.

2001-04-10  Kevin B. Kenny    <kennykb@acm.org>

	* unix/tclUnixTime.c: Altered code to use memcpy instead of
	structure assigments in an effort to achieve better K&R
	compatibility.

2001-04-10  Kevin B. Kenny    <kennykb@acm.org>

	* unix/tclUnixTime.c: Fixed silly typo in calls to 'gmtime' and
	'localtime' that broke the Linux build.

2001-04-09  Kevin B. Kenny    <kennykb@acm.org>

	* unix/tclLoadShl.c: Added DYNAMIC_PATH to the load flags so that the
	SHLIB_PATH will be searched for other libraries. [Bug 219140]

2001-04-09  Kevin B. Kenny    <kennykb@acm.org>

	* unix/tcl.m4: Added _REENTRANT to Solaris build so that thread safe
	library routines are included.
	* unix/configure: Re-ran 'autoconf' with changed tcl.m4
	* tclUnixTime.c: Modified for thread safety of 'gmtime' and
	'localtime' system calls. [Bugs 219136 and 232558]

2001-04-09  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/expr.test (expr-21.*): Tests to check below fix.
	* generic/tclParseExpr.c (GetLexeme): Now recognises the
	non-numeric boolean literals for what they are. It no longer makes
	sense for anyone to create functions with the same name as one of
	them, but this was true in 7.* as well [Bug 217777; finally!]

2001-04-07  Miguel Sofer <msofer@users.sourceforge.net>

	* generic/tclExecute.c: Avoid panic when there are extra items in the
	tcl stack. [Bug 406709, Patch 414470]
	* tests/foreach.test: test to exercise the patch

2001-04-07  Miguel Sofer <msofer@users.sourceforge.net>

	* doc/namespace.n: document correct functionality
	* generic/tclNamesp.c: corrected behaviour of [namespace code]
	[Bug 219385, Patch 403530]
	* library/init.tcl:
	* tests/namespace-old.test: test correct functionality
	* tests/namespace.test: test correct functionality

2001-04-07  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* unix/Makefile.in (checkdoc): New target, checking the definitions as
	found in the compiled library against the manpages to find
	undocumented public functionality.

	* unix/mkLinks: Updated to include the new manpage.

	* doc/UniCharIsAlpha.3: New manpage documenting the Unicode
	character classification APIs. [Bug 218720]

2001-04-07  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* unix/mkLinks: Updated to incorporate the changes below.

	* doc/StringObj.3: Added 'Tcl_AttemptSetObjLength' to the NAME
	section. [Bug 414435]

	* doc/Alloc.3: Added both 'Tcl_AttemptAlloc' and 'Tcl_AttemptRealloc'
	to the NAME section. [Bug 414435]

	* doc/Utf.3: Added both 'Tcl_UniCharCaseMatch' and
	'Tcl_UniCharNcasecmp' to the NAME section. [Bug 414435]

2001-04-06  Don Porter  <dgp@users.sourceforge.net>

	* library/init.tcl:
	* tests/init.test:  Modified processing of $::errorInfo by [unknown]
	when the auto-loaded command throws an error to better cover the
	tracks of auto-loading. [Bug 219280, Patch 403551]

2001-04-06  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/read.n: Added section on "USE WITH SERIAL PORTS" to resolve
	[Bug 219402]

	* tests/string.test (string-2.30): Test for this case
	* generic/tclCmdMZ.c (Tcl_StringObjCmd, STR_COMPARE branch): Fixed
	problem caused by Utf-rep of \x00 being more than Utf-rep of \x01
	fooling memcmp by forcing everything through Utf-based comparisons.
	Added optimizations for case where objects have a string/unicode-rep
	or a bytearray-rep (i.e. where we can perform comparisons on
	fixed-size units). [Bug 219201]
	* generic/tclUtf.c (Tcl_UtfNcmp): Corrected seriously erroneous
	comment.

2001-04-05  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* doc/Macintosh.3: Removed duplicates from .SH line. [Bug 413983]

2001-04-05  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclCmdMZ.c (Tcl_StringObjCmd): Fixed so will compile
	with K&R compilers. [Patch 413844, Bug 413847]

2001-04-04  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclMain.c:  Patch from Kevin Kenny to restore support of
	pre-ANSI compilers. [Bug 413846, Patch 413842]

2001-04-04  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* unix/mkLinks: Updated to contain the new manpage.

	* doc/Environment.3: New manpage, describes Tcl_PutEnv. [Bug 219171]

	* doc/Macintosh.3: New manpage describing the macintosh specific parts
	of the public API. [Bug 219169]

2001-04-04  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/configure:
	* unix/tcl.m4: extended test of termios vs. termio vs. sgtty to
	better detect result on Linux and when certain configure
	redirections are being used. [Patch 402923; Bug 227412, 219194] (max)

2001-04-04  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* generic/tclTest.c:
	* tests/io.tests: TIP #10 followup correcting a problem with the
	original patch because of the lack of 'testthread id' for a
	non-threaded compilation.

2001-04-04  Kevin Kenny <kennykb@acm.org>

	* doc/ByteArrObj.3:
	* doc/DumpActiveMemory.3:
	* doc/InitStubs.3:
	* doc/PkgRequire.3:
	* doc/StringObj.3:
	* generic/tcl.decls:
	* generic/tcl.h:
	* generic/tclBinary.c:
	* generic/tclCkalloc.c:
	* generic/tclDecls.h:
	* generic/tclListObj.c:
	* generic/tclObj.c:
	* generic/tclPkg.c:
	* generic/tclStringObj.c:
	* generic/tclStubLib.c: (TIP#27) Changed a number of Tcl API's to
	accept "CONST char*" in place of simple "char*". (kennykb) [Patch
	404026]

2001-04-04  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclListObj.c (Tcl_SetListObj): set objPtr->length = 0 in
	empty object case to maintain sanctity of Tcl_Obj bytes/length
	pairing. [Patch 405998] (porter)

2001-04-03  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* unix/mkLinks: Added 'Signal.3', 'Tcl_WaitPid'.

	* doc/DetachPids.3: Added description of 'Tcl_WaitPid' [Bug 219173].

	* doc/Signal.3: New man page describing the public API procedures
	'Tcl_SignalId' and 'Tcl_SignalMsg'. [Bug 219172]

2001-04-02  Jeff Hobbs  <jeffh@ActiveState.com>

	* README:
	* win/README:
	* win/README.binary: further notes corrections.

	* win/configure:
	* win/tcl.m4 (SHLIB_LD):  added -incremental:no. [Bug 219381]

2001-04-01  Jeff Hobbs  <jeffh@ActiveState.com>

	* README:
	* mac/README:
	* win/README:
	* win/README.binary:
	* unix/README: updated patchlevel information to 8.4a3 and updated
	links and notes.

	* generic/tcl.h:
	* tools/tcl.wse.in:
	* win/configure.in (VER):
	* win/configure:
	* unix/configure:
	* unix/configure.in (VER):
	* unix/tcl.spec: updated patchlevel information to 8.4a3

2001-03-30  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclCkalloc.c (TclFinalizeMemorySubsystem): set curTagPtr
	to NULL to allow for reuse.
	* generic/tclEvent.c (Tcl_Finalize): moved the tsdPtr initialization
	inside the subsystemsInitialized check to prevent it potentially
	getting called twice during finalization.
	[Patch 403532, Bug 219391] (wu)

	* generic/tclThreadTest.c (Tcl_ThreadObjCmd): cast fixes
	* generic/tclTest.c (TestChannelCmd): added cast to mollify Windows
	debug build.

	* win/tclWinSock.c (SocketEventProc): Fixed race condition in
	readability of socket on Windows. [Patch 410674, Bug 219205, 219333]

	* win/tcl.m4: added imm32.lib to LIBS_GUI for Tk IME support.

	* win/Makefile.in (install-libraries): removed extra \s that broke
	the target.
	(install-doc): improved install-* targets to use their base build
	dependency.

2001-03-30  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* All of the changes below belong to TIP #10 [Tcl I/O Enhancement:
	Thread-Aware Channels]. See also [Patch 403358] at SF.

	* generic/tclIO.h (struct ChannelState, line 236f): Extended the
	structure with a new field of type 'Tcl_ThreadId' to hold the id of
	the thread currently managing all channels with this state.

	Note: This structure is shared by all channels in a stack of
	transformations.

	* generic/tclIO.c (Tcl_CreateChannel, lines 1058-1065): Modified to
	store the Id of the current thread in the 'ChannelState' of the new
	channel.

	* generic/tclIO.c (Tcl_SpliceChannel, lines 2265-2270): Modified in
	the same manner as 'Tcl_CreateChannel' as the channel will be managed
	by the current thread afterward.

	* generic/tclIO.c   (Tcl_GetChannelThread, lines 1478-1503):
	* generic/tcl.decls (Tcl_GetChannelThread, lines 1504-1506): New API
	function to retrieve the Id of the managing thread from a channel.
	Implementation and declaration.

	* generic/tclTest.c (TestChannelCmd, lines 4520-4532): Added
	subcommand 'mthread' to query a channel about its managing thread.

2001-03-29  Mo DeJong  <mdejong@redhat.com>

	* tests/interp.test: Print out warning when testinterpdelete command
	is not defined. Add tests that checks to make sure a child interp
	inherits the parent's cwd.

2001-03-29  Jeff Hobbs  <jeffh@gimlet.activestate.com>

	* doc/tcltest.n: corrected incorrect macro usage.

	* doc/lsort.n: corrected unbalanced nroff macros.

	* unix/tclUnixPipe.c (TclpCreateTempFile): prevent potential race
	condition and security leak in tmp filename creation.
	[Patch 402924] (max)

	* unix/configure:
	* unix/tcl.m4: corrected IRIX-5.x config to not use -n32.
	[Patch 403626] (english)

	* unix/tclUnixThrd.c (Tcl_ConditionWait): fixed handling of timeout
	for threads (corrects excessive CPU usage issue for Tk on Unix in
	threaded Tcl environment). [Bug 411603] (ruppert)

2001-03-29  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/lsort.n: Added some notes that clarify the behaviour of
	[lsort] as well as a whole bunch of examples.  [Bug 219202]

2001-03-27  Jeff Hobbs  <jeffh@gimlet.activestate.com>

	* doc/Alloc.3: corrected docs to note that Tcl_Attempt* return char
	*'s, not ints. [Bug 411388]

	* tests/regexp.test (regexp-19.1):
	* generic/tclCmdMZ.c (Tcl_RegsubObjCmd): fixed handling of nulls in
	subspec value.

2001-03-26  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclDecls.h (Tcl_InitCustomHashTable):  Correction to patch
	from 2001-01-18;  tclDecls.h was not generated using 'make genstubs'.

2001-03-26  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* win/tclWinInt.h (tclWinTCharEncoding): Removed as now a static
	variable in win/tclWin32Dll.c instead.

2001-03-23  Jeff Hobbs  <jeffh@activestate.com>

	* generic/tclVar.c (Tcl_ArrayObjCmd): Corrected retrieval of resultPtr
	to prevent possible corruption.

	* generic/tclNamesp.c (Tcl_Import): Correctly freed a DString.
	[Patch 403755] (lavana)

2001-03-15  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/set-old.test (set-old-7.2): Changed error behaviour of
	[unset] to agree with documentation, so must change test as well.

2001-03-14  Don Porter  <dgp@users.sourceforge.net>

	* library/package.tcl (pkg_mkIndex):  Added patch from Vince Darley to
	make [pkg_mkIndex -verbose] even more verbose. [Bug 219349, Patch
	403529]

2001-03-13  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/info.n: Improved documentation for [info hostname]. [Bug 403840]

	* generic/tclVar.c (Tcl_UnsetObjCmd): Made command behave as
	documented [issue remaining from Bug 405769]

	* generic/tclCmdMZ.c (Tcl_StringObjCmd): A missing {return TCL_OK;}
	was causing memory corruption. [Bug 408002]

	* generic/tclExecute.c (TclDeleteExecEnv, GrowEvaluationStack,
	(TclExecuteByteCode): Added some casts to ClientData that are
	apparently needed on some architectures.

2001-03-12  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/string.test: Fixed some test numberings and added a test.
	[Patch 403229]

2001-03-06  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclVar.c (Tcl_UnsetObjCmd): Rewrote argument parser to avoid
	a read off the end of the argument array that could occur when
	executing something like [unset -nocomplain] was executed. Improved
	the error message given when not enough arguments are given (-nocomplain
	should obviously be *before* --, not after it) and also modified the
	test suite to take account of that and the documentation to use the
	same improvement. [Bug 405769]

2001-03-02  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclExecute.c (TclExecuteByteCode): Fixed bug that could pass
	pointers to freed memory to command implementations, which most
	obviously caused some weird behaviour with [info level], but could
	have caused problems with user code and command traces too. [Bug
	404865, Patch 405436]

2001-02-23  msofer  <msofer@users.sourceforge.net>

	* no changes; fixing up the missing comment in the previous one.
	Sorry.

2001-02-23  msofer  <msofer@ant.utdt>

	* /cvsroot/tcl/tcl/tests/execute.test: added test for evaluation of an
	expression in a variable; evals once by compiling, second time using
	the previous compilation

2001-02-18  Kevin B. Kenny  <kennykb@acm.org>

	* doc/clock.n: Updated documentation to reflect the addition of
	compat/strftime.c, including the correct formatting of ISO-8601:1988
	fiscal week number (%V).

2001-02-15  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclCmdMZ.c (Tcl_SplitObjCmd): Improved efficiency of
	splitting strings into individual characters by adding hash so that
	only one Tcl_Obj per character is created. Improves performance of
	splitting of short strings and makes a huge difference to splitting of
	long strings, such as is done in the mime package in tcllib. [Bug
	131523]

2001-01-31  Don Porter  <dgp@users.sourceforge.net>

	* win/makefile.vc (install-libraries):  Corrected misdirected install
	directory for the msgcat 1.2 package.

2001-01-30  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclIO.c (CopyData): Moved code that updates the count of how
	many bytes are left to copy. Corrects bug that when writing occurs in
	the background, the copy loop could be escaped without updating the
	count, causing CopyData() to try to copy more bytes than the toRead
	value originally passed to TclCopyChannel(), leading to hangs and
	misreporting of number of bytes copied. [Bug 118203, Patch 103432]

2001-01-18  Andreas Kupries  <a.kupries@westend.com>

	Everything below belongs together, it fixes [Bug 123153]

	* generic/tcl.h (line 342): A bit more explanation about the default
	value for TCL_PRESERVE_BINARY_COMPATABILITY.

	* generic/tcl.h (line 1208): Define the macro 'Tcl_InitHashTable' only
	when TCL_PRESERVE_BINARY_COMPATIBILITY is not set as it kills binary
	compatibility to 8.3 and earlier versions. This is the main part of
	the patch/change.

	* generic/tcl.decls (line 1469):
	* generic/tclHash.c (Tcl_InitHashTable):
	* generic/tclHash.c (Tcl_InitHashTableEx):
	* generic/tclObj.c (Tcl_InitObjHashTable): Changed
	'Tcl_InitHashTableEx' to 'Tcl_InitCustomHashTable'. This change is
	more of an estethical nature, replacing the ubiquitous 'Ex' suffix
	with a more meaningful name. The introduced binary incompatibility is
	deemed acceptable as it is between alpha versions.  Updated callers.

	* doc/Hash.3:
	* unix/mkLinks: Changed 'Tcl_InitHashTableEx' to
	'Tcl_InitCustomHashTable'.

2001-01-10  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/winPipe.test (winpipe-1.20):
	* tests/winDde.test (createChildProcess):
	* tests/pkgMkIndex.test (pkgtest::createIndex): Removed assumption
	that paths contain no spaces which causes problems with both [eval]
	and [open |...] due to the well-known differences between lists and
	strings. Fixes [Bug 119406]

2001-01-04  Don Porter  <dgp@users.sourceforge.net>

	* tests/unixInit.test:
	* unix/tclUnixInit.c (TclpInitLibraryPath):
	* win/tclWinInit.c (TclpInitLibraryPath):  Several entries in the
	library path ($tcl_libPath) are determined relative to the absolute
	path of the executable. When the executable is installed in or near
	the root directory of the file system, relative pathnames were being
	incorrectly generated, and in the worst case, memory access violations
	were crashing the program. [Bug 119416, Patch 102972]

	******************************************************************
	*** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000"             ***
	*** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" ***
	******************************************************************

Deleted ChangeLog.2002.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
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
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
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
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
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
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
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741





































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
2002-12-18  David Gravereaux  <davygrvy@pobox.com>

	* win/makefile.vc: some uses of xcopy swapped to the @$(CPY) macro.
	Reported by Joe Mistachkin <joe@mistachkin.com>.

2002-12-17  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclNotify.c (TclFinalizeNotifier, Tcl_SetServiceMode):
	(Tcl_ThreadAlert): Check that the stub functions are non-NULL before
	calling them. They could be set to NULL by Tcl_SetNotifier.

2002-12-16  David Gravereaux  <davygrvy@pobox.com>

	* generic/tclPipe.c (TclCleanupChildren):
	* tests/winPipe.test:
	* win/tclWinPipe.c (Tcl_WaitPid):
	* win/tclWinTest.c:  Gave Tcl_WaitPid the ability to return a Win32
	exception code translated into a posix style SIG*. This allows [close]
	to report "CHILDKILLED" without the meaning getting lost in a
	truncated exit code. In TclCleanupChildren(), TclpGetPid() had to get
	moved to before Tcl_WaitPid() as the the handle is removed from the
	list taking away the ability to get the process id after the wait is
	done. This shouldn't effect the unix implimentaion unless waitpid is
	called with a pid of zero, meaning "any". I don't think it is..

2002-12-13  Don Porter  <dgp@users.sourceforge.net>

	* unix/configure.in:	Updated configure of CVS snapshots to reflect
	* win/configure.in:	the 8.4.1.1 patchlevel.

	* unix/configure:	autoconf
	* win/configure		autoconf

2002-12-11  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclProc.c (ProcessProcResultCode): Fix failure to propagate
	negative return codes up the call stack. [Bug 647307]
	* tests/proc.test (proc-6.1): Test for Bug 647307

	* generic/tclParseExpr.c (TclParseInteger):  Return 1 for the string
	"0x" (recognize leading "0" as an integer). [Bug 648441]
	* tests/parseExpr.test (parseExpr-19.1): Test for Bug 648441.

2002-12-09  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/tclWinThrd.c (TclpMasterUnlock):
	* generic/tclThread.c (TclFinalizeThreadData): TclpMasterUnlock must
	exist and be called unconditional of TCL_THREADS. [Bug 651139]

2002-12-08  David Gravereaux  <davygrvy@pobox.com>

	* win/tclWinSock.c (SocketThreadExitHandler, InitSockets):  Check
	that the tsdPtr is valid before dereferencing as we call it from the
	exit handler, too [Bug 650353]. Another WSAStartup() loaded version
	comparison byte swap issue fixed. Although 0x0101 byte swapped is
	still 0x0101, properly claiming which is major/minor is more correct.

2002-12-06  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclStubInit.c: regen
	* generic/tclIntPlatDecls.h: regen
	* generic/tclInt.decls: added TclWinResetInterface

	* win/tclWin32Dll.c (TclWinResetInterfaces):
	* win/tclWinInit.c (TclpSetInitialEncodings, WinEncodingsCleanup):
	add exit handler that resets the encoding information to a state where
	we can reuse Tcl. Following these changes, it is possible to reuse Tcl
	(following Tcl_FindExecutable or Tcl_CreateInterp) following a
	Tcl_Finalize.

	* generic/tclIOUtil.c (TclFinalizeFilesystem): reset statics to their
	original values on finalize to allow reuse of the library.

2002-12-04  David Gravereaux  <davygrvy@pobox.com>

	* win/tclWinPipe.c: reverted back to -r1.27 due to numerous test
	failures that need to be resolved first. The idea was good, but the
	details aren't.

2002-12-04  David Gravereaux  <davygrvy@pobox.com>

	* win/tclWinPipe.c (Tcl_WaitPid):  When a process exits with an
	exception, pass this notice on to the caller with a SIG* code rather
	than truncating the exit code and missing the meaning. This allows
	TclCleanupChildren() to report "CHILDKILLED".

	This has a different behavior than unix in that closing the read pipe
	to a process sends the SIGPIPE signal which is returned as a SIGPIPE
	exit status. On windows, we send the process a CTRL_BREAK_EVENT and
	get back a CONTROL_C_EXIT which is documented to mean a SIGINT which
	seems wrong as a system, but is the correct exit status.

2002-12-04  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclIOUtil.c: fix to redirected 'load' in virtual filesystem
	for some Unix systems.

	* generic/tclEvent.c: the filesystem must be cleaned up before the
	encoding subsystem because it needs access to encodings. Fixes crash
	on exit observed in embedded applications.

	* generic/tclTestObj.c: patch omitted from previous change of
	2002-11-13

2002-12-03  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclStubLib.c (Tcl_InitStubs): prevent the cached check of
	tclStubsPtr to allow for repeated load/unload of the Tcl dll by
	hosting apps. [Bug 615304]

2002-12-03  David Gravereaux  <davygrvy@pobox.com>

	* win/tclAppInit.c (sigHandler): Protect from trying to close a NULL
	handle.

	* win/tclWinPipe.c (PipeClose2Proc, TclpCreateProcess): Send a real
	Win32 signal (CTRL_C_EVENT) when the read channel is brought down to
	alert the child to close on its side. Start the process with
	CREATE_NEW_PROCESS_GROUP to allow the ability to send these signals.
	The following test case now brings down the child without the use of
	an external [kill] command.

	% set p [open "|[info name]" w+]
	file8d5380
	% pid $p
	2876
	% close $p     <- now doesn't block in Tcl_WaitPid()
	%

	* win/tclWinPipe.c (PipeClose2Proc): Changed CTRL_C_EVENT to
	CTRL_BREAK_EVENT as it can't be ignored by the child and proved to
	work on [open "|netstat 1" w+] where CTRL_C_EVENT didn't.

2002-11-27  David Gravereaux  <davygrvy@pobox.com>

	* win/tclWinPort.h: Don't turn off winsock prototypes!  TclX didn't
	like it. Even though the core doesn't use the prototypes, do offer
	them.

	* win/tclWinSock.c: Removed shutdown() from the function table as it
	wasn't referenced anywhere and cleaned-up some casting that that
	wasn't needed.

	* win/tclWinSock.c: WSAStartup() loaded version comparison error which
	resulted in 2.0 looking less than 1.1.

	* win/tclWinChan.c (Tcl_MakeFileChannel): return of DuplicateHandle()
	incorrectly used. [Bug 618852]

2002-11-26  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclEncoding.c (TclFinalizeEncodingSubsystem): properly
	cleanup all encodings by using Tcl_FirstHashEntry in the while loop.

	* unix/Makefile.in (valgrind): add simple valgrind target

	* tests/exec.test: unset path var to allow singleproc testing

	* generic/tclInterp.c (AliasCreate): preserve/release interps to
	prevent possible FMR error in bad alias cases.

2002-11-26  David Gravereaux  <davygrvy@pobox.com>

	* win/tclWinPort.h:
	* win/tclWinSock.c:  This patch does two things:

	1) Cleans-up the winsock typedefs by using the typedefs provided by
	winsock2.h. This has no effect on how winsock is initialized; just
	makes the source code easier to read. [Patch 561305 561301]

	2) Revamps how the socket message handler thread is brought up and
	down to allow for cleaner exits without the use of TerminateThread().
	TerminateThread is evil. No attempt has been made to resolve [Bug
	593810] which may need a new channel driver version for adding a
	registering function within the transfered thread to init the handler
	thread. IOW, initialization of the TSD structure is getting bypassed
	through the thread extension's [thread::transfer] command.

2002-11-26  David Gravereaux  <davygrvy@pobox.com>

	* win/tclWinConsole.c:
	* win/tclWinPipe.c:
	* win/tclWinSerial.c:
	* win/tclWinSock.c:
	* win/tclWinThrd.c:
	* win/tclWinTime.c:  General cleanup of all worker threads used by the
	channel drivers. Eliminates the normal case where the worker thread is
	terminated ('cept the winsock one). Instead, use kernel events to
	signal a clean exit. Only when the worker thread is blocked on an I/O
	call is the thread terminated. Essentially, this makes all other
	channel worker threads behave like the PipeReaderThread() function for
	it's cleaner exit behavior. This appears to fix [Bug 597924] but needs
	3rd party confirmation to close the issue.

2002-11-26  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/README: Update msys build env URL. This release #4 build both
	tcl and tk without problems.

2002-11-22  Jeff Hobbs  <jeffh@ActiveState.com>

	* library/init.tcl:         code cleanup to reduce use of
	* library/opt/optparse.tcl: string compare

	* tests/interp.test: interp-14.4
	* generic/tclInterp.c (TclPreventAliasLoop): prevent seg fault when
	creating an alias command over the interp name. [Bug 641195]

2002-11-18  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclUtil.c (SetEndOffsetFromAny): handle integer offset
	after the "end-" prefix.

	* generic/get.test:
	* generic/string.test:
	* generic/tclObj.c (SetIntFromAny, SetWideIntFromAny):
	* generic/tclGet.c (TclGetLong, Tcl_GetInt): simplify sign handling
	before calling strtoul(l). [Bug 634856]

2002-11-18  David Gravereaux  <davygrvy@pobox.com>

	* win/tclWinThrd.c (Tcl_CreateThread/TclpThreadExit): Fixed improper
	compiler macros that missed the VC++ compiler. This resulted in VC++
	builds using CreateThread()/ExitThread() in place of the proper
	_beginthreadex()/_endthreadex(). This was a large error and am
	surprised I missed seeing it earlier.

2002-11-13  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/regexpComp.test: added tests 22.*
	* generic/tclCompCmds.c (TclCompileRegexpCmd): add left and right
	anchoring (^ and $) recognition and check starting or ending .* to
	extend the number of REs that can be compiled to string match or
	string equal.

2002-11-13  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclCmdMZ.c:
	* tests/trace.test: applied patch from Hemang Levana to fix [Bug
	615043] in execution traces with 'return -code error'.

	* generic/tclTestObj.c:
	* tests/stringObj.test: added 'knownBug' test for [Bug 635200]
	* generic/tclStringObj.c: corrected typos in comments

	* generic/tclFileName.c:
	* tests/fileName.test: applied patch for bug reported against tclvfs
	concerning handling of Windows serial ports like 'com1', 'lpt3' by the
	virtual filesystem code.

	* doc/RegExp.3: clarification of the 'extendMatch' return values.

2002-11-11  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclUtil.c (Tcl_Backslash): use TclUtfToUniChar.
	(Tcl_StringCaseMatch): use TclUtfToUniChar and add further
	optimizations for the one-byte/char case.

	* generic/tclUtf.c: make use of TclUtfToUniChar macro throughout the
	functions, and add extra optimization to Tcl_NumUtfChars for
	one-byte/char case.

	* generic/tclVar.c (DisposeTraceResult, CallVarTraces): add proper
	static declarations.

	* generic/tclStringObj.c (Tcl_GetCharLength): optimize for the ascii
	char case.
	(Tcl_GetUniChar): remove unnecessary use of Tcl_UtfToUniChar.
	(FillUnicodeRep): Use TclUtfToUniChar.

	* generic/tclHash.c (HashStringKey): move string++ lower to save an
	instruction.

	* generic/tclExecute.c (TclExecuteByteCode): improve INST_STR_CMP to
	use memcmp in the one-byte/char case, also use direct index for
	INST_STR_INDEX in that case.

	* generic/tclEncoding.c (UtfToUtfProc, UtfToUnicodeProc):
	(TableFromUtfProc, EscapeFromUtfProc): Use TclUtfToUniChar.
	(UnicodeToUtfProc, TableToUtfProc): add 1-byte char optimizations for
	Tcl_UniCharToUtf call. These improve encoded channel conversion speeds
	by up to 20%.

	* tests/split.test: added 1-char string split tests
	* generic/tclCmdMZ.c (Tcl_SplitObjCmd): Use TclUtfToUniChar. Also
	added a special case for single-ascii-char splits.
	(Tcl_StringObjCmd): Use TclUtfToUniChar. For STR_RANGE, support
	getting ranges of ByteArrays (reverts change from 2000-05-26).
	(TraceExecutionProc) add proper static declaration.

	* generic/tclInt.h: add macro version of Tcl_UtfToUniChar
	(TclUtfToUniChar) that does the one-byte utf-char check without
	calling Tcl_UtfToUniChar, for use by the core. This brings notable
	speedups for primarily ascii string handling.

	* generic/tcl.h (TCL_PATCH_LEVEL): bump to 8.4.1.1 for patchlevel
	only. This interim number will only be reflected by [info patchlevel].

2002-11-11  Kevin Kenny  <kennykb@acm.org>

	* doc/Tcl.n: Corrected indentation of the new language. Oops.

2002-11-10  Kevin Kenny <kennykb@acm.org>

	* doc/Tcl.n: Added language to the Endekalogue to make it clear that
	substitutions always take place from left to right. [Bug 635644]

2002-11-06  Mo DeJong  <mdejong@users.sourceforge.net>

	* changes: Note TclInExit TclInThreadExit changes.
	* generic/tclEvent.c (TclInExit, TclInThreadExit): Split out
	functionality of TclInExit to make it clear which one should be called
	in each situation.
	* generic/tclInt.decls: Declare TclInThreadExit.
	* generic/tclIntDecls.h: Regen.
	* generic/tclStubInit.c: Regen.
	* mac/tclMacChan.c (StdIOClose):
	* unix/tclUnixChan.c (FileCloseProc):
	* win/tclWinChan.c (FileCloseProc):
	* win/tclWinConsole.c (ConsoleCloseProc):
	* win/tclWinPipe.c (TclpCloseFile):
	* win/tclWinSerial.c (SerialCloseProc): Invoke the new TclInThreadExit
	method instead of TclInExit.

2002-11-06  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure: Regen.
	* unix/tcl.m4 (SC_CONFIG_CFLAGS): Generate a fatal configure error if
	no ar program can be found on the path. [Bug 582039]
	* win/configure: Regen.
	* win/configure.in: Check that AR, RANLIB, and RC are found on the
	path when building with gcc.

2002-11-03  David Gravereaux <davygrvy@pobox.com>

	* win/tclAppInit.c:  Calls Registry_Init() and Dde_Init() when
	STATIC_BUILD and TCL_USE_STATIC_PACKAGES macros are set.

	* win/makefile.vc:
	* win/rules.vc:  linkexten option now sets the TCL_USE_STATIC_PACKAGES
	macro which also adds the registry and dde object files to the link
	of the shell. [Patch 479697] Also factored some additional macros that
	will be helpful for extension authors. Version grepping of tcl.h will
	need to be added to complete this.

	* win/buildall.vc.bat: Added more descriptive commentary.

2002-11-01  David Gravereaux <davygrvy@pobox.com>

	* win/tclWinReg.c:  Changed the Tcl_PkgProvide() line to declare the
	registry extension at version 1.1 from 1.0.

2002-10-31  Andreas Kupries  <andreask@activestate.com>

	* library/word.tcl: Changed $tcl_platform to $::tcl_platform to avoid
	possible scope trouble.

2002-10-29  Vince Darley  <vincentdarley@users.sourceforge.net>

	* win/tclWinInt.h:
	* win/tclWin32Dll.c: added comments about certain NULL function
	pointers which will be filled in when Tcl_FindExecutable is called, so
	that users don't report invalid bugs on this topic. (No code changes
	at all).

2002-10-29  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tclLoadDyld.c (TclpFindSymbol): pass all dyld error messages
	upstream [Bug 627546].

2002-10-28  Andreas Kupries  <andreask@activestate.com>

	* library/dde/pkgIndex.tcl:
	* library/reg/pkgIndex.tcl: Changed the hardwired debug suffix (d) to
	the correct suffix (g).

2002-10-28  Don Porter  <dgp@users.sourceforge.net>

	* library/auto.tcl:	Converted the Mac-specific [package unknown]
	* library/init.tcl:	behavior to use a chaining mechanism to extend
	* library/package.tcl:	the default [tclPkgUnknown]. [Bug 627660]
	* library/tclIndex:	[Patch 624509] (steffen)

2002-10-26  David Gravereaux <davygrvy@pobox.com>

	* win/makefile.vc: xcopy on NT 4.0 doesn't support the /Y switch
	(overwrite). Added logic to handle this. [Bug 618019]

2002-10-23  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclInt.h: Removed definitions of obsolete HistoryEvent and
	HistoryRev structures (the history mechanism has been written in Tcl
	for some time now.)

2002-10-22  Jeff Hobbs  <jeffh@ActiveState.com>

	*** 8.4.1 TAGGED FOR RELEASE ***

	* changes: updated for 8.4.1 release

	* win/Makefile.in: removed @MEM_DEBUG_FLAGS@ subst.
	* win/configure: regen
	* win/configure.in: removed SC_ENABLE_MEMDEBUG call
	* win/tcl.m4: replaced SC_ENABLE_MEMDEBUG with a more intelligent
	SC_ENABLE_SYMBOLS that takes yes|no|mem|compile|all as options now.

2002-10-22  Daniel Steffen  <das@users.sourceforge.net>

	* library/auto.tcl (tcl_findLibrary):
	* library/package.tcl (tclPkgUnknown): on macosx, search inside the
	Resources/Scripts subdirectory of any potential package directory.
	* macosx/Tcl.pbproj/project.pbxproj: add standard Frameworks dirs to
	TCL_PACKAGE_PATH make argument.
	* unix/tclUnixInit.c (TclpSetVariables): on macosx, add embedded
	framework dirs to tcl_pkgPath: @executable_path/../Frameworks and
	@executable_path/../PrivateFrameworks (if they exist), as well as the
	dirs in DYLD_FRAMEWORK_PATH (if set). [Patch 624509]
	use standard MAXPATHLEN instead of literal 1024

2002-10-22  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/StringObj.3, doc/Object.3: Documented that Tcl_Obj's standard
	string form is a modified UTF-8; apparently, this was not mentioned
	anywhere in the main docs, and lead to [Bug 624919].

2002-10-21  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Tcl.pbproj/project.pbxproj: bumped version to 8.4.1
	* generic/tcl.h: Added reminder comment to edit
	macosx/Tcl.pbproj/project.pbxproj when version number changes.

2002-10-18  Jeff Hobbs  <jeffh@ActiveState.com>

	* library/reg/pkgIndex.tcl:
	* win/configure:
	* win/configure.in:
	* win/Makefile.in:
	* win/makefile.vc:
	* win/makefile.bc:    Updated to reg1.1

	* doc/registry.n:      Added support for broadcasting changes to the
	* tests/registry.test: registry Environment. Noted proper code in the
	* win/tclWinReg.c:     docs. [Patch 625453]

	* unix/Makefile.in (dist): add any mac/tcl*.sea.hqx files

2002-10-17  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclVar.c:	Fixed code that check for proper # of args to
	* tests/var.test:	[array names]. Added test. [Bug 624755]

2002-10-16  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/configure:                 add workaround for cygwin windres
	* win/tcl.m4 (SC_CONFIG_CFLAGS): problem. [Patch 624010] (howell)

2002-10-15  Jeff Hobbs  <jeffh@ActiveState.com>

	* README: added archives.tcl.tk note

	* unix/configure:
	* unix/tcl.m4: Correct AIX-5 ppc build flags. Correct HP 11 64-bit gcc
	building. [Patch 601051] (martin)

2002-10-15  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclCmdMZ.c:
	* tests/trace.test: applied patch from Hemang Levana to fix [Bug
	615043] in execution traces with idle tasks firing.

2002-10-14  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclEnv.c (Tcl_PutEnv): correct possible mem leak. [Patch
	623269] (brouwers)

2002-10-11  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tcl.h: Need a different strategy through the maze of
	#defines to let people building with Cygwin build correctly. Also made
	some comments less misleading...

2002-10-10  Jeff Hobbs  <jeffh@ActiveState.com>

	* README: fixed minor nits [Bug 607776] (virden)

	* win/configure:
	* win/tcl.m4: enable USE_THREAD_ALLOC (new threaded allocator) by
	default in cygwin configure on Windows.

2002-10-10  Don Porter  <dgp@users.sourceforge.net>

	* doc/Tcl.n:	Clarified that namespace separators are legal in the
			variable names during $-subtitution. [Bug 615139]

	* doc/regexp.n:	Typo correction. Thanks Ronnie Brunner. [Bug 606826]

2002-10-10  Vince Darley  <vincentdarley@users.sourceforge.net>

	* unix/tclLoadAout.c
	* unix/tclLoadDl.c
	* unix/tclLoadDld.c
	* unix/tclLoadDyld.c
	* unix/tclLoadNext.c
	* unix/tclLoadOSF.c
	* unix/tclLoadShl.c
	* win/tclWinLoad.c: allow either full paths or simply dll names to be
	specified when loading files (the latter will be looked up by the OS
	on your PATH/LD_LIBRARY_PATH as appropriate). Fixes [Bug 611108]

2002-10-09  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/README: doc'ed --enable-symbols options.
	* unix/Makefile.in: removed @MEM_DEBUG_FLAGS@ subst.
	* unix/configure: regen
	* unix/configure.in: removed SC_ENABLE_MEMDEBUG call
	* unix/tcl.m4: replaced SC_ENABLE_MEMDEBUG with a more intelligent
	SC_ENABLE_SYMBOLS that takes yes|no|mem|compile|all as options now.

2002-10-09  Kevin B. Kenny  <kennykb@acm.org>

	* win/tclWinTime.c: Added code to set an exit handler that terminates
	the thread that calibrates the performance counter, so that the thread
	won't outlive unloading the Tcl DLL. [Bug 620735]

2002-10-09  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/binary.n: More clarification of [binary scan]'s behaviour.

2002-10-09  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclIntDecls.h: fixed botched regen.

2002-10-09  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclInt.decls: made TclSetPreInitScript() declaration
	generic as it is used on mac & aqua as well.
	* generic/tclIntDecls.h:
	* generic/tclStubInit.c: regen.
	* generic/tclCompile.h: added prototype for TclCompileVariableCmd.

	* mac/tclMacPort.h: removed incorrect <fcntl.h> definitions and
	obsolete <stat.h> definitions.
	* mac/tclMacChan.c: removed obsolete GetOpenMode() and replaced
	associated constants with the <fcntl.h> analogues (they existing defs
	were inconsistent with <fcntl.h> which was causing havoc when
	Tcl_GetOpenMode was used instead of private GetOpenMode).

	* mac/tclMacFCmd.c: removed GenerateUniqueName(), use equivalent (and
	identically named) routine from MoreFiles instead.

	* mac/tclMacLoad.c: CONSTification, fixes to Vince's last changes.

	* mac/tclMacFile.c:
	* mac/tclMacTest.c:
	* mac/tclMacUnix.c: CONSTification.

	* mac/tclMacOSA.c: CONSTification, sprintf fixes, UH 3.4.x changes;
	fix for missing autoname token from TclOSACompileCmd. (bdesgraupes)
	* mac/AppleScript.html(AppleScript delete): doc fix. (bdesgraupes)

	* mac/tcltkMacBuildSupport.sea.hqx: updated MoreFiles to 1.5.3,
	updated build instructions for 8.4.
	* mac/tclMacProjects.sea.hqx: rebuilt archive.

2002-10-09  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/Alloc.3: Added a note to mention that attempting to allocate a
	zero-length block can return NULL. [Tk Bug 619544]

2002-10-04  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/binary.n: Doc improvements [Patch 616480]

	* tests/fCmd.test, tests/winFCmd.test:
	* tools/eolFix.tcl, tools/genStubs.tcl: [file exist] -> [file exists]
	Thanks to David Welton.

2002-10-03  Don Porter  <dgp@users.sourceforge.net>

	* doc/tcltest.n: fixed typo [Bug 618018]. Thanks to "JJM".

2002-10-03  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tools/man2help2.tcl:
	* tests/http.test, tests/httpd, tests/httpold.test:
	* tests/env.test, tests/binary.test, tests/autoMkindex.test:
	* library/init.tcl, library/http/http.tcl: [info exist] should really
	be [info exists]. [Bug 602566]

	* doc/lsearch.n: Better specification of what happens when -sorted is
	mixed with other options. [Bug 617816]

2002-10-01  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclProc.c (TclCreateProc): mask out VAR_UNDEFINED for
	precompiled locals to support 8.3 precompiled code.
	(Tcl_ProcObjCmd): correct 2002-09-26 fix to look for tclProcBodyType.

2002-10-01  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/socket.n: Mentioned that ports may be specified as serivce names
	as well as integers. [Bug 616843]

2002-09-30  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclCompCmds.c (TclCompileRegexpCmd): correct the checking
	for bad re's that didn't terminate the re string. Resultant compiles
	were correct, but much slower than necessary.

2002-09-29  David Gravereaux <davygrvy@pobox.com>

	* win/tclAppInit.c: Added proper exiting conditions using Win32
	console signals. This handles the existing lack of a Ctrl+C exit to
	call exit handlers when built for thread support. Also, properly
	handles exits from other conditions such as CTRL_CLOSE_EVENT,
	CTRL_LOGOFF_EVENT, and CTRL_SHUTDOWN_EVENT signals. In all cases,
	exit handlers will be called. [Bug 219355]

	* win/makefile.vc: Added missing tclThreadAlloc.c to the build rules
	and defines USE_THREAD_ALLOC when TCL_THREADS is defined to get the
	new behavior by default.

2002-09-27  Don Porter  <dgp@users.sourceforge.net>

	* README:		Bumped to version 8.4.1 to avoid confusion of
	* generic/tcl.h:	CVS snapshots with the actual 8.4.0 release.
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/configure.in:

	* unix/configure:	autoconf
	* win/configure:

2002-09-26  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/configure: regen.
	* unix/tcl.m4: improve AIX-4/5 64bit compilation support.

	* generic/tclProc.c (Tcl_ProcObjCmd): correct overeager optimization
	of noop proc to handle the precompiled case. (sofer)

	* unix/ldAix (nmopts): add -X32_64 to make it work for 32 or 64bit
	mode compilation.

	* library/encoding/koi8-u.enc: removed extraneous spaces that confused
	encoding reader. [Bug 615115]

	* unix/Makefile.in: generate source dists with -src designator and do
	not generate .Z anymore (just .gz and .zip).

2002-09-18  Mumit Khan <khan@nanotech.wisc.edu>

	Added basic Cygwin support.

	* win/tcl.m4 (SC_PATH_TCLCONFIG): Support one-tree build.
	(SC_PATH_TKCONFIG): Likewise.
	(SC_PROG_TCLSH): Likewise.
	(SC_CONFIG_CFLAGS): Assume real Cygwin port and remove -mno-cygwin
	flags. Add -mwin32 to extra_cflags and extra_ldflags. Remove ``-e
	_WinMain@16'' from LDFLAGS_WINDOW.
	* win/configure.in: Allow Cygwin build.
	(SEH test): Define to be 1 instead of empty value.
	(EXCEPTION_DISPOSITION): Add test.
	* win/configure: Regenerate.

	* generic/tcl.h: Don't explicitly define __WIN32__ for Cygwin, let the
	user decide whether to use Windows or POSIX personality.
	(TCL_WIDE_INT_TYPE, TCL_LL_MODIFIER, struct Tcl_StatBuf): Define for
	Cygwin.
	* generic/tclEnv.c (Tcl_CygwinPutenv): putenv replacement for Cygwin.
	* generic/tclFileName.c (Tcl_TranslateFileName): Convert POSIX to
	native format.
	(TclDoGlob): Likewise.
	* generic/tclPlatDecls.h (TCHAR): Define for Cygwin.
	* win/tclWinPort.h (putenv, TclpSysAlloc, TclpSysFree,
	(TclpSysRealloc): Define for Cygwin.

2002-09-26  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Makefile: preserve environment value of INSTALL_ROOT. When
	embedding only use deployment build. Force relink before embedded
	build to ensure new linker flags are picked up.

	* macosx/Tcl.pbproj/project.pbxproj: add symbolic links to debug lib,
	stub libs and tclConfig.sh in framework toplevel. Configure target
	dependency fix. Fix to 'clean' action. Added private tcl headers to
	framework. Install tclsh symbolic link. Html doc build works when no
	installed tclsh available. Made html doc structure in framework more
	like in Apple frameworks.

2002-09-24  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* unix/tcl.m4 (SC_TCL_64BIT_FLAGS): Yet more robust 64-bit value
	detection to close [Bug 613117] on more systems.

	* generic/tclCompile.c (TclPrintSource): More CONSTifying.
	* generic/tclExecute.c (EvalStatsCmd): Object-ify to reduce warnings.
	Thanks to 'CoderX2' on the chat for bringing this to my attention...

	* unix/tcl.m4: Forgot to define TCL_WIDE_INT_IS_LONG at the
	appropriate moment. I believe this is the cause of [Bug 613117]

	* doc/lset.n: Changed 'list' to 'varName' for consistency with lappend
	documentation. Thanks to Glenn Jackman [Bug 611719]

2002-09-22  Don Porter  <dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl:  Corrected [puts -nonewline] within
	test bodies. Thanks to Harald Kirsch. [Bug 612786, Patch 612788] Also
	corrected reporting of body return code. Thanks to David Taback [Bug
	611922]
	* library/tcltest/pkgIndex.tcl: Bump to version 2.2.1.
	* tests/tcltest.test: added tests for these bugs.

2002-09-15  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure: Regen.
	* unix/tcl.m4 (SC_CONFIG_CFLAGS): Add PEEK_XCLOSEIM define under
	Linux. This is used by Tk to double check that an X input context is
	cleaned up before it is closed.

2002-09-12  David Gravereaux <davygrvy@pobox.com>

	* win/coffbase.txt: Added BLT to the virtual base address listings
	table should BLT's build tools decide to use it.

2002-09-12  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tcl.h:
	* mac/tclMacApplication.r:
	* mac/tclMacLibrary.r:
	* mac/tclMacResource.r: unified use of the two equivalent resource
	compiler header inclusion defines RC_INVOKED and RESOURCE_INCLUDED,
	now use RC_INVOKED throughout.

2002-09-10  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/README: Add note about building extensions with the same
	compiler Tcl was built with. [Tk Bug 592096]

2002-09-10  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Tcl.pbproj/project.pbxproj: disabled building html
	documentation during embedded build.

2002-09-10  Daniel Steffen  <das@users.sourceforge.net>

	* unix/Makefile.in: added DYLIB_INSTALL_DIR variable for macosx and
	set it to default value ${LIB_RUNTIME_DIR}
	* unix/tcl.m4 (Darwin): use DYLIB_INSTALL_DIR instead of
	LIB_RUNTIME_DIR in the -install_name argument to ld.
	* unix/configure: regen.

	* macosx/Tcl.pbproj/project.pbxproj:
	* macosx/Makefile: added support for building Tcl as an embedded
	framework, i.e. using an dyld install_name containing
	@executable_path/../Frameworks via the new DYLIB_INSTALL_DIR
	unix/Makefile variable.

2002-09-10  Jeff Hobbs  <jeffh@ActiveState.com>

	*** 8.4.0 TAGGED FOR RELEASE ***

2002-09-06  Don Porter  <dgp@users.sourceforge.net>

	* doc/file.n:  Format correction, and clarified [file normalize]
	returns an absolute path.

	* doc/tcltest.n:  Added examples section, as long promised.

2002-09-06  Reinhard Max  <max@suse.de>

	* tests/tcltest.test: Added nonRoot flag to tests 8.3, 8.4, and 8.12.

2002-09-05  Don Porter  <dgp@users.sourceforge.net>

	* doc/tcltest.n:  Clarified phrasing.

	* generic/tclBasic.c (TclRenameCommand,CallCommandTraces):
	* tests/trace.test (trace-27.1): Corrected memory leak when a rename
	trace deleted the command being traced. Test added. Thanks to Hemang
	Lavana for the fix. [Bug 604609]

	* generic/tclVar.c (TclDeleteVars):  Corrected logic for setting the
	TCL_INTERP_DESTROYED flag when calling variable traces. [Tk Bug 605121]

2002-09-04  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclVar.c (DeleteArray): leak plug [Bug 604239]. Thanks to
	dkf and dgp for the long and difficult discussion in the chat.

2002-09-03  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclVar.c (Tcl_UpVar2): code cleanup to not use goto

	* unix/configure: remove -pthread from LIBS on FreeBSD in thread
	* unix/tcl.m4:    enabled build. [Bug 602849]

2002-09-03  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclInterp.c (AliasCreate): a Tcl_Obj was leaked on error
	return from TclPreventAliasLoop.

2002-09-03  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Tcl.pbproj/project.pbxproj: Bumped version number to 8.4.0
	and updated copyright info.

2002-09-03  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclVar.c (Tcl_UpVar2): a Tcl_Obj was being leaked on error
	return from TclGetFrame.

2002-09-03  Don Porter  <dgp@users.sourceforge.net>

	* changes:  Updated changes for 8.4.0 release.

2002-09-02  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/tclUnixFile.c (TclpObjLink): removed unnecessary/unfreed extra
	native char*.

	* unix/tclUnixChan.c (Tcl_MakeTcpClientChannel): make sure to init
	flags field of TcpState ptr to 0.

	* unix/configure:
	* unix/tcl.m4: added 64-bit gcc compilation support on HP-11.
	[Patch 601051] (martin)

	* README:		Bumped version number to 8.4.0
	* generic/tcl.h:
	* tools/tcl.wse.in:
	* unix/configure:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/README.binary:
	* win/configure:
	* win/configure.in:

	* generic/tclInterp.c (SlaveCreate): make sure that the memory and
	checkmem commands are initialized in non-safe slave interpreters when
	TCL_MEM_DEBUG is used. [Bug 583445]

	* win/tclWinConsole.c (ConsoleCloseProc): only wait on writable pipe
	if there was something to write. This may prevent infinite wait on
	exit.

	* tests/exec.test: marked exec-18.1 unixOnly until the Windows
	incompatibility (in the test, not the core) can be resolved.

	* tests/http.test (http-3.11): added close $fp that was causing an
	error on Windows because the file was not closed before deleting.

	* unix/tclUnixInit.c (Tcl_MacOSXGetLibraryPath): made this static
	function only appear when HAVE_CFBUNDLE is defined.

2002-08-31  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tcl.m4: added TK_SHLIB_LD_EXTRAS analogue of existing
	TCL_SHLIB_LD_EXTRAS for linker settings only used when linking Tk.

	* unix/configure: regen

2002-08-31  Daniel Steffen  <das@users.sourceforge.net>

	*** macosx-8-4-branch merged into the mainline [Patch 602770] ***

	* generic/tcl.decls: added new macosx specific entry to stubs table.

	* tools/genStubs.tcl: added generation of platform guards for
	macosx. This is a little more complex than it seems, because MacOS X
	IS "unix" plus a little bit, for the purposes of Tcl. BUT
	unfortunately, Tk uses "unix" to mean X11. So added platform keys for
	macosx (the little added to "unix"), "aqua" and "x11" to distinguish
	these for Tk.

	* generic/tcl.h: added a #ifnded RESOURCE_INCLUDED so that tcl.h can
	be passed to the resource compiler.

	* generic/tcl.h:
	* generic/tclNotify.c: added a few Notifier procs, to be able to
	modify more bits of the Tcl notifier dynamically. Required to get Mac
	OS X Tk to live on top of the Tcl Unix threaded notifier. Changes the
	size of the Tcl_NotifierProcs structure, but doesn't move any elements
	around.

	* unix/tclUnixNotfy.c: moved the call to Tcl_ConditionNotify till
	AFTER we are done mucking with the pointer swap. Fixes cases where the
	thread waiting on the condition wakes & accesses the waitingListPtr
	before it gets reset, causing a hang.

	* library/auto.tcl (tcl_findLibrary): added checking the directories
	in the tcl_pkgPath for library files on macosx to enable support of
	the standard Mac OSX library locations.

	* unix/Makefile.in:
	* unix/configure.in:
	* unix/tcl.m4: added MAC_OSX_DIR. Added PLAT_OBJS to the OBJS: there
	are some MacOS X specific files now for Tcl, and when I get the
	resource & applescript stuff ported over, and restore support for
	FindFiles, etc, there will be a few more. Added LD_LIBRARY_PATH_VAR
	configure variable to avoid having to set all possible LD_LIBRARY_PATH
	analogues on all platforms. LD_LIBRARY_PATH_VAR is "LD_LIBRARY_PATH"
	by default, "LIBPATH" on AIX, "SHLIB_PATH" on HPUX and
	"DYLD_LIBRARY_PATH" on Mac OSX. Added configure option to package Tcl
	as a framework on Mac OSX.

	* macosx/tclMacOSXBundle.c (new): support for finding Tcl extension
	packaged as 'bundles' in the standard Mac OSX library locations.

	* unix/tclUnixInit.c: added support for findig the tcl script library
	inside Tcl packaged as a framework on Mac OSX.

	* macosx/Tcl.pbproj/jingham.pbxuser (new):
	* macosx/Tcl.pbproj/project.pbxproj (new): project for Apple's
	ProjectBuilder IDE.

	* macosx/Makefile (new): simple makefile for building the project from
	the command line via the ProjectBuilder tool 'pbxbuild'.

	* unix/configure:
	* generic/tclStubInit.c:
	* generic/tclPlatDecls.h: regen

2002-08-29  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* win/tclWinThrd.c (TclpFinalizeThreadData, TclWinFreeAllocCache):
	Applied patch for [Bug 599428], provided by Miguel Sofer
	<msofer@users.sourceforge.net>.

2002-08-28  David Gravereaux <davygrvy@pobox.com>

	* generic/tclEnv.c:
	* unix/configure.in:
	* win/tclWinPort.h:  putenv() on some systems copies the buffer rather
	than taking reference to it. This causes memory leaks and is know to
	effect mswindows (msvcrt) and NetBSD 1.5.2 . This patch tests for this
	behavior and turns on -DHAVE_PUTENV_THAT_COPIES=1 when approriate.
	Thanks to David Welton for assistance. [Bug 414910]

	* unix/configure: regen'd

2002-08-28  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/eval.n: Added mention of list command and corrected "SEE ALSO".

	* unix/configure.in: Cache handling of ac_cv_type_socklen_t was wrong.
	[Bug 600931] reported by John Ellson. Fixed by putting the brackets
	where they belong.

2002-08-26  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclCompCmds.c: fix for [Bug 599788] (error in element name
	causing segfault), reported by Tom Wilkason. Fixed by copying the
	tokens instead of the source string.

2002-08-26  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclThreadAlloc.c: small optimisation, reducing the new
	allocator's overhead.

2002-08-23  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclObj.c (USE_THREAD_ALLOC): fixed leak [Bug 597936]. Thanks
	to Zoran Vasiljevic.

2002-08-23  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclThreadAlloc.c (USE_THREAD_ALLOC): moving objects between
	caches as a block, instead of one-by-one.

2002-08-22  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclBasic.c:
	* generic/tclCmdMZ.c: fix for freed memory r/w in delete traces [Bug
	589863], patch by Hemang Lavana.

2002-08-20  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* win/Makefile.in (CFLAGS):
	* unix/Makefile.in (MEM_DEBUG_FLAGS): Added usage of @MEM_DEBUG_FLAGS@.
	* win/configure.in:
	* unix/configure.in: Added usage of SC_ENABLE_MEMDEBUG.
	* win/tcl.m4:
	* unix/tcl.m4: Added macro SC_ENABLE_MEMDEBUG. Allows a user of
	configure to (de)activate memory validation and debugging
	(TCL_MEM_DEBUG). No need to modify the makefile anymore.

2002-08-20  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCkalloc.c:	CONSTified MemoryCmd and CheckmemCmd.

	* README:		Bumped version number to 8.4b3 to distinguish
	* generic/tcl.h:	HEAD from the 8.4b2 release.
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/README.binary:
	* win/configure.in:

	* unix/configure:	autoconf
	* win/configure:

	* library/http/http.tcl:	Corrected installation directory of
	* library/msgcat/msgcat.tcl:	the package tcltest 2.2. Added
	* library/opt/optparse.tcl:	comments in other packages to remind
	* library/tcltest/tcltest.tcl:	that installation directories need
	* unix/Makefile.in:		updates to match increasing version
	* win/Makefile.in:		numbers. [Bug 597450]
	* win/makefile.bc:
	* win/makefile.vc:

2002-08-19  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* unix/tclUnixTest.c (TestfilehandlerCmd): Changed readable/writable
	to the more common readable|writable. Fixes [Bug 596034] reported by
	Larry Virden <lvirden@users.sourceforge.net>.

2002-08-16  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/fCmd.test: Added test to make sure that the cause of the
	problem is detectable with an unpatched Tcl.
	* doc/ObjectType.3: Added note on the root cause of this problem to
	the documentation, since it is possible for user code to trigger this
	sort of behaviour too.
	* generic/tclIOUtil.c (SetFsPathFromAny): Objects should only have
	their old representation deleted when we know that we are about to
	install a new one. This stops a weird TclX bug under Linux with
	certain kinds of memory debugging enabled which essentally came down
	to a double-free of a string.

2002-08-14  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclInt.h:
	* generic/tclObj.c: (code cleanup) factored the parts in the macros
	TclNewObj() / TclDecrRefCount() into a common part for all
	memory allocators and two new macros TclAllocObjStorage() /
	TclFreeObjStorage() that are specific to each allocator and fully
	describe the differences. Removed allocator-specific code from
	tclObj.c by using the macros.

2002-08-12  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclCmdMZ.c: fixing UMR in delete traces, [Bug 589863].

2002-08-08  David Gravereaux <davygrvy@pobox.com>

	* tools/man2help.tcl: Fixed $argv handling bug where if -bitmap wasn't
	specified $argc was off by one.

2002-08-08  Miguel Sofer  <msofer@users.sourceforge.net>

	* tests/uplevel.test: added 6.1 to test [uplevel] with shadowed
	commands [Bug 524383]

	* tests/subst.test: added 5.8-10 as further tests for [Bug 495207]

2002-08-08  Don Porter  <dgp@users.sourceforge.net>

	* tests/README: Noted removal of defs.tcl.

2002-08-08  Jeff Hobbs  <jeffh@ActiveState.com>

	* doc/lsearch.n: corrected lsearch docs to use -inline in examples.

	*** 8.4b2 TAGGED FOR RELEASE ***

	* tests/fCmd.test:
	* tests/unixFCmd.test: updated tests for new link copy behavior.
	* generic/tclFCmd.c (CopyRenameOneFile): changed the behavior to
	follow links to endpoints and copy that file/directory instead of just
	copying the surface link. This means that trying to copy a link that
	has no endpoint (danling link) is an error. [Patch 591647] (darley)
	(CopyRenameOneFile): this is currently disabled by default until
	further issues with such behavior (like relative links) can be
	handled correctly.

	* tests/README: slight wording improvements

2002-08-07  Miguel Sofer  <msofer@users.sourceforge.net>

	* docs/BoolObj.3: added description of valid string reps for a
	boolean object. [Bug 584794]
	* generic/tclObj.c: optimised Tcl_GetBooleanFromObj and
	SetBooleanFromAny to avoid parsing the string rep when it can be
	avoided. [Bugs 584650, 472576]

2002-08-07  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclCompile.h:
	* generic/tclObj.c: making tclCmdNameType static ([Bug 584567], Don
	Porter).

2002-08-07  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclObj.c (Tcl_NewObj): added conditional code for
	USE_THREAD_ALLOC; objects allocated through Tcl_NewObj() were
	otherwise being leaked. [Bug 587488] reported by Sven Sass.

2002-08-06  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclInt.decls:
	* unix/tclUnixThrd.c: Added stubs and implementations for
	non-threaded build for the tclUnixThrd.c procs TclpReaddir,
	TclpLocaltime, TclpGmtime and TclpInetNtoa. Fixes link errors in
	stubbed & threaded extensions that include tclUnixPort.h and use any
	of the procs readdir, localtime, gmtime or inet_ntoa (e.g. TclX 8.4)
	[Bug 589526]
	* generic/tclIntPlatDecls.h:
	* generic/tclStubInit.c: Regen.

2002-08-05  Don Porter  <dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl:	The setup and cleanup scripts are now
	* library/tcltest/pkgIndex.tcl:	skipped when a test is skipped, fixing
	* tests/tcltest.test:		[Bug 589859]. Test for bug added, and
	corrected tcltest package bumped to version 2.2.

	* generic/tcl.decls:	Restored Tcl_Concat to return (char *). Like
	* generic/tclDecls.h:	Tcl_Merge, it transfers ownership of a dynamic
	* generic/tclUtil.c:	allocated string to the caller.

2002-08-04  Don Porter  <dgp@users.sourceforge.net>

	* doc/CmdCmplt.3:	Applied Patch 585105 to fully CONST-ify all
	* doc/Concat.3:		remaining public interfaces of Tcl. Notably,
	* doc/CrtCommand.3:	the parser no longer writes on the string it
	* doc/CrtSlave.3:	is parsing, so it is no longer necessary for
	* doc/CrtTrace.3:	Tcl_Eval() to be given a writable string. Also
	* doc/Eval.3:		the refactoring of the Tcl_*Var* routines by
	* doc/ExprLong.3:	by Miguel Sofer is included, so that the
	* doc/LinkVar.3:	"part1" argument for them no longer needs to
	* doc/ParseCmd.3:	be writable either.
	* doc/SetVar.3:
	* doc/TraceVar.3:
	* doc/UpVar.3:		Compatibility support has been enhanced so
	* generic/tcl.decls:	that a #define of USE_NON_CONST will remove
	* generic/tcl.h:	all possible source incompatibilities with the
	* generic/tclBasic.c:	8.3 version of the header file(s). The new
	* generic/tclCmdMZ.c:	#define of USE_COMPAT_CONST now does what
	* generic/tclCompCmds.c:USE_NON_CONST used to do -- disable only those
	* generic/tclCompExpr.c:new CONST's that introduce irreconcilable
	* generic/tclCompile.c:	incompatibilities.
	* generic/tclCompile.h:
	* generic/tclDecls.h:	Several bugs are also fixed by this patch.
	* generic/tclEnv.c:	[Bugs 584051,580433] [Patches 585105,582429]
	* generic/tclEvent.c:
	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclIntDecls.h:
	* generic/tclInterp.c:
	* generic/tclLink.c:
	* generic/tclObj.c:
	* generic/tclParse.c:
	* generic/tclParseExpr.c:
	* generic/tclProc.c:
	* generic/tclTest.c:
	* generic/tclUtf.c:
	* generic/tclUtil.c:
	* generic/tclVar.c:
	* mac/tclMacTest.c:
	* tests/expr-old.test:
	* tests/parseExpr.test:
	* unix/tclUnixTest.c:
	* unix/tclXtTest.c:
	* win/tclWinTest.c:

2002-08-01  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c: bugfix (reading freed memory). Testsuite
	passed on linux/i386, compile-13.1 hung on linux/alpha.

2002-08-01  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c: added a reference count for the complete
	execution stack, instead of Tcl_Preserve/Tcl_Release.

2002-08-01  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tclCkalloc.c (TclFinalizeMemorySubsystem): Don't lock the
	ckalloc mutex before invoking the Tcl_DumpActiveMemory function since
	it also locks the same mutex. This code is only executed when "memory
	onexit filename" has been executed and Tcl is compiled with
	-DTCL_MEM_DEBUG.

2002-08-01  Reinhard Max  <max@suse.de>

	* win/tclWinPort.h: The windows headers don't provide socklen_t, so we
	have to do it.

2002-07-31  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclInt.h (USE_THREAD_ALLOC): for unshared objects,
	TclDecrRefCount now frees the internal rep before the string rep -
	just like the non-macro Tcl_DecrRefCount/TclFreeObj [Bug 524802]. For
	the other allocators the fix was done on 2002-03-06.

2002-07-31  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclInterp.c: signed/unsigned comparison warning fixed
	(Vince Darley).

2002-07-31  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* unix/tcl.m4 (SC_BUGGY_STRTOD): Enabled caching of test results.

	* unix/tcl.m4 (SC_BUGGY_STRTOD): Solaris 2.8 still has a buggy
	strtod() implementation; make sure we detect it.

	* tests/expr.test (expr-22.*): Marked as non-portable because it seems
	that these tests have an annoying tendency to fail in unexpected ways.
	[Bugs 584825, 584950, 585986]

2002-07-30  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* tests/io.test:
	* generic/tclIO.c (WriteChars): Added flag to break out of loop if
	nothing of the input is consumed at all, to prevent infinite looping
	of called with a non-UTF-8 string. Fixes Bug 584603 (partially). Added
	new test "io-60.1". Might need additional changes to Tcl_Main so that
	unprintable results are printed as binary data.

2002-07-29  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/Makefile.in: Use CC_SEARCH_FLAGS instead of LD_SEARCH_FLAGS
	when linking with ${CC}.
	* unix/configure: Regen.
	* unix/configure.in: Don't subst CC_SEARCH_FLAGS or LD_SEARCH_FLAGS
	since this is now done in tcl.m4.
	* unix/tcl.m4 (SC_CONFIG_CFLAGS): Document and set CC_SEARCH_FLAGS
	whenever LD_SEARCH_FLAGS is set. [Patch 588290]

2002-07-29  Reinhard Max  <max@suse.de>

	* unix/tcl.m4 (SC_SERIAL_PORT): Fixed detection for cases when
                                        configure's stdin is not a tty.

	* unix/tclUnixPort.h:
	* generic/tclIOSock.c:          Changed size_t to socklen_t in
                                        socket-related function calls.

	* unix/configure.in:            Added test and fallback definition
                                        for socklen_t.

	* unix/configure:               generated.

2002-07-29  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclObj.c: fixed a comment

	* generic/tcl.h:
	* generic/tclBasic.c:
	* generic/tclInterp.c: added the new flag TCL_EVAL_INVOKE to the
	interface of the Tcl_Eval* functions, removing the
	TCL_EVAL_NO_TRACEBACK added yesterday: alias invocations not only
	require no tracebacks, but also look up the command name in the global
	scope - see new test interp-9.4
	* tests/interp.test: added 9.3 to test for safety of aliases to hidden
	commands, 9.4 to test for correct command lookup scope.

2002-07-29  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/regc_locale.c (cclass): [[:xdigit:]] is only a defined
	concept on western characters, so should not allow any unicode digit,
	and hence number of ranges in [[:xdigit:]] is fixed.
	* tests/reg.test: Added test to detect the bug.
	* generic/regc_cvec.c (newcvec): Corrected initial size value in
	character vector structure. [Bug 578363] Many thanks to
	pvgoran@users.sf.net for tracking this down.

2002-07-28  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tcl.h:
	* generic/tclBasic.c: added the new flag TCL_EVAL_NO_TRACEBACK to the
	interface of the Tcl_Eval* functions. Modified the error message for
	too many nested evaluations.
	* generic/tclInterp.h: changed the Alias struct to be of variable
	length and store the prefix arguments directly (instead of a pointer
	to a Tcl_Obj list). Made AliasObjCmd call Tcl_EvalObjv instead of
	TclObjInvoke - thus making aliases trigger execution traces [Bug
	582522].
	* tests/interp.test:
	* tests/stack.test: adapted to the new error message.
	* tests/trace.test: added tests for aliases firing the exec traces.

2002-07-27  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/Makefile.in: Revert fix for Tcl bug 529801 since it was
	incorrect and broke the build on other systems. Fix [Bug 587299]. Add
	MAJOR_VERSION, MINOR_VERSION, PATCH_LEVEL, SHLIB_LD_FLAGS,
	SHLIB_LD_LIBS, CC_SEARCH_FLAGS, LD_SEARCH_FLAGS, and LIB_FILE
	variables to support more generic library build/install rules.
	* unix/configure: Regen.
	* unix/configure.in: Move AC_PROG_RANLIB into tcl.m4. Move shared
	build test and setting of MAKE_LIB and MAKE_STUB_LIB into tcl.m4. Move
	subst of a number of variables into tcl.m4 where they are defined.
	* unix/tcl.m4 (SC_ENABLE_SYMBOLS, SC_CONFIG_CFLAGS): Subst vars where
	they are defined. Add MAKE_LIB, MAKE_STUB_LIB, INSTALL_LIB, and
	INSTALL_STUB_LIB rules to deal with the ugly details of running ranlib
	on static libs at build and install time. Replace TCL_SHLIB_LD_EXTRAS
	with SHLIB_LD_FLAGS and use it when building a shared library.
	* unix/tclConfig.sh.in: Add TCL_CC_SEARCH_FLAGS.

2002-07-26  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c: fixed Tcl_Obj leak in code corresponding to
	the macro NEXT_INST_V(x, 0, 1) [Bug 587495].

2002-07-26  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclVar.c (TclObjLookupVar): leak fix and improved comments.

2002-07-26  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclVar.c (TclLookupVar): removed early returns that
	prevented the parens from being restored. Also removed goto label as
	it was not necessary.

2002-07-24  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c:
	* tests/expr-old.test: fix for erroneous error messages in [expr],
	[Bug 587140] reported by Martin Lemburg.

2002-07-25  Joe English  <jenglish@users.sourceforge.net>

	* generic/tclProc.c: fix for [Tk Bug 219218] "error handling with
	bgerror in Tk"

2002-07-24  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c: restoring full TCL_COMPILE_DEBUG
	functionality.

2002-07-24  Don Porter  <dgp@users.sourceforge.net>

	* tests/unixInit.test: relaxed unixInit-3.1 to accept iso8859-15 as a
	valid C encoding. [Bug 575336]

2002-07-24  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c: restoring the tcl_traceCompile functionality
	while I repair tcl_traceExec. The core now compiles and runs also
	under TCL_COMPILE_DEBUG, but execution in the bytecode engine can
	still not be traced.

2002-07-24  Daniel Steffen  <das@users.sourceforge.net>

	* unix/Makefile.in:
	* unix/configure.in: corrected fix for [Bug 529801]: ranlib only
	needed for static builds on Mac OS X.
	* unix/configure: Regen.
	* unix/tclLoadDyld.c: fixed small bugs introduced by Vince,
	implemented library unloading correctly (needs OS X 10.2).

2002-07-23  Joe English  <jenglish@users.sourceforge.net>

	* doc/OpenFileChnl.3: (Updates from Larry Virden)
	* doc/open.n:
	* doc/tclsh.1: Fix section numbers in Unix man page references.
	* doc/lset.n:  In EXAMPLES section, include command to set the initial
	value used in subsequent examples.
	* doc/http.n: Package version updated to 2.4.

2002-07-23  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure: Regen.
	* unix/tcl.m4 (SC_CONFIG_CFLAGS): Enable 64 bit compilation when using
	the native compiler on a 64 bit version of IRIX. [Bug 219220]

2002-07-23  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/Makefile.in: Combine ranlib tests and avoid printing unless
	ranlib is actually run.

2002-07-23  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/tcl.m4 (SC_PATH_X): Set XINCLUDES to "" instead of "# no
	special path needed" or "# no include files found" when x headers
	cannot be located.

2002-07-22  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclIOUtil.c: made tclNativeFilesystem static (since 07-19
	changes removed its usage elsewhere), and added comments about its
	usage.
	* generic/tclLoad.c:
	* generic/tcl.h:
	* generic/tcl.decls:
	* doc/FileSystem.3: converted last load-related ClientData parameter
	to Tcl_LoadHandle opaque structure, removing a couple of casts in the
	process.

	* generic/tclInt.h: removed tclNativeFilesystem declaration since it
	is now static again.

2002-07-22  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/expr.test (expr-22.*): Added tests to help detect the
	corrected handling.
	* generic/tclExecute.c (IllegalExprOperandType): Improved error
	message generated when attempting to manipulate Inf and NaN values.
	* generic/tclParseExpr.c (GetLexeme): Allowed parser to recognise
	'Inf' as a floating-point number. [Bug 218000]

2002-07-21  Don Porter  <dgp@users.sourceforge.net>

	* tclIOUtil.c: Silence compiler warning. [Bug 584408].

2002-07-19  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclIOUtil.c: fix to GetFilesystemRecord
	* win/tclWinFile.c:
	* unix/tclUnixFile.c: fix to subtle problem with links shown up by
	latest tclkit builds.

2002-07-19  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure:
	* unix/configure.in:
	* win/configure:
	* win/configure.in: Add AC_PREREQ(2.13) in an attempt to make it more
	clear that the configure scripts must be generated with autoconf
	version 2.13. [Bug 583573]

2002-07-19  Vince Darley  <vincentdarley@users.sourceforge.net>

	* unix/Makefile.in: fix to build on MacOS X [Bug 529801], bug report
	and fix from jcw.

2002-07-19  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* win/tclWinSerial.c (no_timeout): Made this variable static.

	* generic/tclExecute.c, generic/tclCompile.c, generic/tclBasic.c:
	* generic/tclCompile.h (builtinFuncTable, instructionTable): Added
	prefix to these symbols because they are visible outside the Tcl
	library.

	* generic/tclCompExpr.c (operatorTable):
	* unix/tclUnixTime.c (tmKey):
	* generic/tclIOUtil.c (theFilesystemEpoch, filesystemWantToModify,
	filesystemIteratorsInProgress, filesystemOkToModify): Made these
	variables static.

	* unix/tclUnixFile.c:		Renamed nativeFilesystem to
	* win/tclWinFile.c:		tclNativeFilesystem and declared
	* generic/tclIOUtil.c:		it properly in tclInt.h
	* generic/tclInt.h:

	* generic/tclUtf.c (totalBytes): Made this array static and const.

	* generic/tclParse.c (typeTable): Made this array static and const.
	(Tcl_ParseBraces): Simplified error handling case so that scans are
	only performed when needed, and flags are simpler too.

	* license.terms: Added AS to list of copyright holders; it's only
	fair for the current gatekeepers to be listed here!

	* tests/cmdMZ.test: Renamed constraint for clarity. [Bug 583427]
	Added tests for the [time] command, which was previously only
	indirectly tested!

2002-07-18  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclInt.h:
	* generic/tcl.h:
	* */*Load*.c: added comments on changes of 07/17 and replaced
	clientData with Tcl_LoadHandle in all locations.

	* generic/tclFCmd.c:
	* tests/fileSystem.test: fixed a 'knownBug' with 'file attributes ""'
	* tests/winFCmd.test:
	* tests/winPipe.test:
	* tests/fCmd.test:
	* tessts/winFile.test: added 'pcOnly' constraint to some tests to make
	for more useful 'tests skipped' log from running all tests on
	non-Windows platforms.

2002-07-17  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclBasic.c (CallCommandTraces): delete traces now receive
	the FQ old name of the command. [Bug 582532] (Don Porter)

2002-07-18  Vince Darley  <vincentdarley@users.sourceforge.net>

	* tests/ioUtil.test: added constraints to 1.4,2.4 so they don't run
	outside of tcltest. [Bugs 583276, 583277]

2002-07-17  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclVar.c (DupParsedVarName): nasty bug fixed, reported by
	Vince Darley.

2002-07-17  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclVar.c (TclPtrIncrVar): missing CONST in declarations,
	inconsistent with tclInt.h. Thanks to Vince Darley for reporting, boo
	to gcc for not complaining.

2002-07-17  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclInt.h:
	* generic/tclIOUtil.c:
	* generic/tclLoadNone.c:
	* unix/tclLoadAout.c:
	* unix/tclLoadDl.c:
	* unix/tclLoadDld.c:
	* unix/tclLoadDyld.c:
	* unix/tclLoadNext.c:
	* unix/tclLoadOSF.c:
	* unix/tclLoadShl.c:
	* mac/tclMacLoad.c:
	* win/tclWinLoad.c: modified to move more functionality to the generic
	code and avoid duplication. Partial replacement of internal uses of
	clientData with opaque Tcl_LoadHandle. A little further work still
	needed, but significant changes are done.

2002-07-17  D. Richard Hipp    <drh@hwaci.com>

	* library/msgcat/msgcat.tcl: fix a comment that was causing problems
	for programs (ex: mktclapp) that embed the initialization scripts in
	strings.

2002-07-17  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclInt.decls:
	* generic/tclIntDecls.h:
	* generic/tclStubInit.c:
	* generic/tclVar.c: removing the now redundant functions to access
	indexed variables: Tcl(Get|Set|Incr)IndexedScalar() and
	Tcl(Get|Set|Incr)ElementOfIndexedArray().

2002-07-17  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclExecute.c (TclExecuteByteCode): Minor fixes to make this
	file compile with SunPro CC...

2002-07-17  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c: modified to do variable lookup explicitly, and
	then either inlining the variable access or else calling the new
	TclPtr(Set|Get|Incr)Var functions in tclVar.c
	* generic/tclInt.h: declare some functions previously local to
	tclVar.c for usage by TEBC.
	* generic/tclVar.c: removed local declarations; moved all special
	accessor functions for indexed variables to the end of the file -
	they are unused and ready for removal, but left there for the time
	being as they are in the internal stubs table.

	** WARNING FOR BYTECODE MAINTAINERS **
	TCL_COMPILE_DEBUG is currently not functional; will be fixed ASAP.

2002-07-16  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/Makefile.in:
	* win/Makefile.in: Add a more descriptive warning in the event `make
	genstubs` needs to be rerun.

2002-07-16  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/Makefile.in: Use dltest.marker file to keep track of when the
	dltest package is up to date. This fixes [Bug 575768] since tcltest is
	no longer linked every time.
	* unix/dltest/Makefile.in: Create ../dltest.marker after a successful
	`make all` run in dltest.

2002-07-16  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure: Regen.
	* unix/configure.in: Remove useless subst of TCL_BIN_DIR.

2002-07-15  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclVar.c: inaccurate comment fixed

2002-07-15  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclBasic.c (Tcl_AddObjErrorInfo):
	* generic/tclExecute.c (TclUpdateReturnInfo):
	* generic/tclInt.h:
	* generic/tclProc.c:
	Added two Tcl_Obj to the ExecEnv structure to hold the fully qualified
	names "::errorInfo" and "::errorCode" to cache the addresses of the
	corresponding variables. The two most frequent setters of these
	variables now profit from the new variable name caching.

2002-07-15  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclVar.c: refactorisation to reuse already looked-up Var
	pointers; definition of three new Tcl_Obj types to cache variable name
	parsing and lookup for later reuse; modification of internal functions
	to profit from the caching.

	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclIntDecls.h:
	* generic/tclNamesp.c: adding CONST qualifiers to variable names
	passed to Tcl_FindNamespaceVar and to variable resolvers; adding CONST
	qualifier to the 'msg' argument to TclLookupVar. Needed to avoid code
	duplication in the new tclVar.c code.

	* tests/set-old.test:
	* tests/var.test: slight modification of error messages due to the
	modifications in the tclVar.c code.

2002-07-15  Don Porter  <dgp@users.sourceforge.net>

	* tests/unixInit.test:	Improved constraints to protect /tmp. [Bug
	581403]

2002-07-15  Vince Darley  <vincentdarley@users.sourceforge.net>

	* tests/winFCmd.test: renamed 'win2000' and 'notWin2000' to more
	appropriate constraint names.
	* win/tclWinFile.c: updated comments to reflect 07-11 changes.
	* win/tclWinFCmd.c: made ConvertFileNameFormat static again, since no
	longer used in tclWinFile.c
	* mac/tclMacFile.c: completed TclpObjLink implementation which was
	previously lacking.
	* generic/tclIOUtil.c: comment cleanup and code speedup.

2002-07-14  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInt.h:	Removed declarations that duplicated entries
	in the (internal) stub table.

	* library/tcltest/tcltest.tcl:  Corrected errors in handling of
	configuration options -constraints and -limitconstraints.

	* README:		Bumped HEAD to version 8.4b2 so we can
	* generic/tcl.h:	distinguish it from the 8.4b1 release.
	* tools/tcl.wse.in:
	* unix/configure*:
	* unix/tcl.spec:
	* win/README.binary:
	* win/configure*:

2002-07-11  Vince Darley  <vincentdarley@users.sourceforge.net>

	* doc/file.n:
	* win/tclWinFile.c: on Win 95/98/ME the long form of the path is used
	as a normalized form. This is required because short forms are not a
	robust representation. The file normalization function has been sped
	up, but more performance gains might be possible, if speed is still an
	issue on these platforms.

2002-07-11  Don Porter  <dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl: Corrected reaction to existing but
	false ::tcl_interactive.

	* doc/Hash.3: Overlooked CONST documentation update.

2002-07-11  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclCkalloc.c: ckalloc() and friends take the block size as
	an unsigned, so we should use %ud when reporting it in fprintf() and
	panic().

2002-07-11  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclCompile.c: now setting local vars undefined at compile
	time, instead of waiting until the proc is initialized.
	* generic/tclProc.c: use macro TclSetVarUndefined instead of directly
	setting the flag.

2002-07-11  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/cmdAH.test: [file attr -perm] is Unix-only, so add [catch]
	when not inside a suitably-protected test.

2002-07-10  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/unixFCmd.test, tests/fileName.test:
	* tests/fCmd.test: Removed [exec] of Unix utilities that have
	equivalents in standard Tcl. [Bug 579268] Also simplified some of
	unixFCmd.test while I was at it.

2002-07-10  Don Porter  <dgp@users.sourceforge.net>

	* tests/tcltest.test:  Greatly reduced the number of [exec]s, using
	slave interps instead.
	* library/tcltest/tcltest.tcl:  Fixed bug uncovered in the conversion
	where a message was written to stdout instead of [outputChannel].

	* tests/basic.test:	Cleaned up, constrained, and reduced the
	* tests/compile.test:	amount of [exec] usage in the test suite.
	* tests/encoding.test:
	* tests/env.test:
	* tests/event.test:
	* tests/exec.test:
	* tests/io.test:
	* tests/ioCmd.test:
	* tests/regexp.test:
	* tests/regexpComp.test:
	* tests/socket.test:
	* tests/tcltest.test:
	* tests/unixInit.test:
	* tests/winDde.test:
	* tests/winPipe.test:

2002-07-10  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/cmdAH.test: Removed [exec] of Unix utilities. [Bug 579211]

	* tests/expr.test: Added tests to make sure that this works.
	* generic/tclExecute.c (ExprCallMathFunc): Functions should also be
	able to return wide-ints. [Bug 579284]

2002-07-08  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* tests/socket.test: Fixed [Bug 578164]. The original reason for the
	was a DNS outage while running the testsuite. Changed [info hostname]
	to 127.0.0.1 to bypass DNS, knowing that we operate on the local host.

2002-07-08  Don Porter  <dgp@users.sourceforge.net>

	* doc/tcltest.n:		Fixed incompatibility in [viewFile].
	* library/tcltest/tcltest.tcl:	Corrected docs. Bumped to 2.2.1.
	* library/tcltest/pkgIndex.tcl: [Bug 578163]

2002-07-08  Vince Darley  <vincentdarley@users.sourceforge.net>

	* tests/cmdAH.test:
	* tests/fCmd.test:
	* tests/fileName.test: tests which rely on 'file link' need a
	constraint so they don't run on older Windows OS. [Bug 578158]
	* generic/tclIOUtil.c:
	* generic/tcl.h:
	* generic/tclInt.h:
	* generic/tclTest.c:
	* mac/tclMacChan.c:
	* unix/tclUnixChan.c:
	* win/tclWinChan.c:
	* doc/FileSystem.3: cleaned up internal handling of
	Tcl_FSOpenFileChannel to remove duplicate code, and make writing
	external vfs's clearer and easier. No functionality change. Also
	clarify that objects with refCount zero should not be passed in to the
	Tcl_FS API, and prevent segfaults from occuring on such user errors.
	[Bug 578617]

2002-07-06  Don Porter  <dgp@users.sourceforge.net>

	* tests/pkgMkIndex.test:  Constrained tests of [load] package indexing
	to those platforms where the testing shared libraries have been built.
	[Bug 578166]

2002-07-05  Don Porter  <dgp@users.sourceforge.net>

	* changes: added recent changes

2002-07-05  Reinhard Max  <max@suse.de>

	* generic/tclClock.c (FormatClock): Convert the format string to utf-8
	before calling TclpStrftime, so that non-ASCII characters don't get
	mangled when the result string is being converted back.
	* tests/clock.test: Added a test for that.

2002-07-05  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* unix/Makefile.in (ro-test,ddd,GDB,DDD): Created new targets to
	allow running the test suite with a read-only current directory,
	running under ddd instead of gdb, and factored out some executable
	names for broken sites (like mine) where gdb and ddd are installed
	with non-standard names...

	* tests/httpold.test: Altered test names to httpold-* to avoid clashes
	with http.test, and stopped tests from failing when the current
	directory is not writable...

	* tests/event.test:		Stop these tests from failing when the
	* tests/ioUtil.test:		current directory is not writable...
	* tests/regexp.test:
	* tests/regexpComp.test:
	* tests/source.test:
	* tests/unixFile.test:
	* tests/unixNotfy.test:

	* tests/unixFCmd.test:		Trying to make these test-files not
	* tests/macFCmd.test:		bomb out with an error when the
	* tests/http.test:		current directory is not writable...
	* tests/fileName.test:
	* tests/env.test:

2002-07-05  Jeff Hobbs  <jeffh@ActiveState.com>

	*** 8.4b1 TAGGED FOR RELEASE ***

2002-07-04  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/cmdMZ.test (cmdMZ-1.4):
	* tests/cmdAH.test: More fixing of writable-current-dir assumption.
	[Bug 575824]

2002-07-04  Miguel Sofer  <msofer@users.sourceforge.net>

	* tests/basic.test: Same issue as below; fixed [Bug 575817]

2002-07-04  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* tests/socket.test:
	* tests/winPipe.test:
	* tests/pid.test: Fixed [Bug 575848]. See below for a description the
	general problem.

	* All the bugs below are instances of the same problem: The testsuite
	assumes [pwd] = [temporaryDirectory] and writable.

	* tests/iogt.test: Fixed [Bug 575860].
	* tests/io.test:   Fixed [Bug 575862].
	* tests/exec.test:
	* tests/ioCmd.test: Fixed [Bug 575836].

2002-07-03  Don Porter  <dgp@users.sourceforge.net>

	* tests/pkg1/direct1.tcl: removed
	* tests/pkg1/pkgIndex.tcl: removed
	* tests/pkgMkIndex.test:  Imported auxilliary files from tests/pkg1
	into the test file pkgMkIndex.test itself. Formatting fixes.

	* unix/Makefile.in: removed tests/pkg/* from `make dist`

	* tests/pkg/circ1.tcl: removed
	* tests/pkg/circ2.tcl: removed
	* tests/pkg/circ3.tcl: removed
	* tests/pkg/global.tcl: removed
	* tests/pkg/import.tcl: removed
	* tests/pkg/pkg1.tcl: removed
	* tests/pkg/pkg2_a.tcl: removed
	* tests/pkg/pkg2_b.tcl: removed
	* tests/pkg/pkg3.tcl: removed
	* tests/pkg/pkg4.tcl: removed
	* tests/pkg/pkg5.tcl: removed
	* tests/pkg/pkga.tcl: removed
	* tests/pkg/samename.tcl: removed
	* tests/pkg/simple.tcl: removed
	* tests/pkg/spacename.tcl: removed
	* tests/pkg/std.tcl: removed
	* tests/pkgMkIndex.test: Fixed [Bug 575857] where this test file
	expected to be able to write to [file join [testsDirectory] pkg]. Part
	of the fix was to import several auxilliary files into the test file
	itself.

	* tests/main.test:	Cheap fix for [Bugs 575851, 575858]. Avoid
	* tests/tcltest.test:	non-writable . by [cd [temporaryDirectory]].

	* library/auto.tcl: Fix [tcl_findLibrary] to be sure it sets $varName
	only if a successful library script is found. [Bug 577033]

2002-07-03  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclCompCmds.c (TclCompileCatchCmd): return
	TCL_OUT_LINE_COMPILE instead of TCL_ERROR: let the failure happen at
	runtime so that it can be caught [Bug 577015].

2002-07-02  Joe English  <jenglish@users.sourceforge.net>

	* doc/tcltest.n: Markup fixes, spellcheck.

2002-07-02  Don Porter  <dgp@users.sourceforge.net>

	* doc/tcltest.n: more refinements of the documentation.

	* library/tcltest/tcltest.tcl: Added trace to be sure the stdio
	constraint is updated whenever the [interpreter] changes.

	* doc/tcltest.n:		Reverted [makeFile] and [viewFile] to
	* library/tcltest/tcltest.tcl:	their former behavior, and documented
	* tests/cmdAH.test:		it. Corrected misspelling of hook
	* tests/event.test:		procedure. Restored tests.
	* tests/http.test:
	* tests/io.test:

	* library/tcltest/tcltest.tcl: Simplified logic of [GetMatchingFiles]
	and [GetMatchingDirectories], removing special case processing.

	* doc/tcltest.n: More documentation updates. Reference sections are
	complete. Only examples need adding.

2002-07-02  Vince Darley  <vincentdarley@users.sourceforge.net>

	* tests/fCmd.test:
	* generic/tclCmdAH.c: clearer error msgs for 'file link', as per the
	man page.

2002-07-01  Joe English  <jenglish@users.sourceforge.net>

	* doc/Access.3:
	* doc/AddErrInfo.3:
	* doc/Alloc.3:
	* doc/Backslash.3:
	* doc/CrtChannel.3:
	* doc/CrtSlave.3:
	* doc/Encoding.3:
	* doc/Eval.3:
	* doc/FileSystem.3:
	* doc/Notifier.3:
	* doc/OpenFileChnl.3:
	* doc/ParseCmd.3:
	* doc/RegExp.3:
	* doc/Tcl_Main.3:
	* doc/Thread.3:
	* doc/TraceCmd.3:
	* doc/Utf.3:
	* doc/WrongNumArgs.3:
	* doc/binary.n:
	* doc/clock.n:
	* doc/expr.n:
	* doc/fconfigure.n:
	* doc/glob.n:
	* doc/http.n:
	* doc/interp.n:
	* doc/lsearch.n:
	* doc/lset.n:
	* doc/msgcat.n:
	* doc/packagens.n:
	* doc/pkgMkIndex.n:
	* doc/registry.n:
	* doc/resource.n:
	* doc/safe.n:
	* doc/scan.n:
	* doc/tclvars.n:  Spell-check, fixed typos (Updates from Larry Virden).

2002-07-01  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* unix/tcl.m4 (SC_CONFIG_CFLAGS): Made Solaris use gcc for linking
	when building with gcc to resolve problems with undefined symbols
	being present when tcl library used with non-gcc linker at later
	stage. Symbols were compiler-generated, so it is the compiler's
	business to define them. [Bug 541181]

2002-07-01  Don Porter  <dgp@users.sourceforge.net>

	* doc/tcltest.n: more work in progress updating tcltest docs.

	* library/tcltest/tcltest.tcl: Change [configure -match] to stop
	treating an empty list as a list of the single pattern "*". Changed
	the default value to [list *] so default operation remains the same.

	* tests/pkg/samename.tcl: restored. needed by pkgMkIndex.test.

	* library/tcltest/tcltest.tcl: restored writeability testing of
	-tmpdir, augmented by a special exception for the deafault value.

2002-07-01  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/concat.n: Documented the *real* behaviour of [concat]!

2002-06-30  Don Porter  <dgp@users.sourceforge.net>

	* doc/tcltest.n: more work in progress updating tcltest docs.

	* tests/README:		Updated the instructions on running and
	* tests/cmdMZ.test:	adding to the test suite. Also updated
	* tests/encoding.test:	several tests, mostly to correctly create
	* tests/fCmd.test:	and destroy any temporary files in the
	* tests/info.test:	[temporaryDirectory] of tcltest.
	* tests/interp.test:

	* library/tcltest/tcltest.tcl:	Stopped checking for writeability of
	-tmpdir value because no default directory can be guaranteed to be
	writeable.

	* tests/autoMkindex.tcl: removed.
	* tests/pkg/samename.tcl: removed.
	* tests/pkg/magicchar.tcl: removed.
	* tests/pkg/magicchar2.tcl: removed.
	* tests/autoMkindex.test: Updated auto_mkIndex tests to use [makeFile]
	and [removeFile] so tests are done in [temporaryDirecotry] where write
	access is guaranteed.

	* library/tcltest/tcltest.tcl:	Fixed [makeFile] and [viewFile] to
	* tests/cmdAH.test:		accurately reflect a file's contents.
	* tests/event.test:		Updated tests that depended on buggy
	* tests/http.test:		behavior. Also added warning messages
	* tests/io.test:		to "-debug 1" operations to debug test
	* tests/iogt.test:		calls to (make|remove)(File|Directory)

	* unix/mkLinks: `make mklinks` on 6-27 commits.

2002-06-28  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclCompile.h: modified the macro TclEmitPush to not call its
	first argument repeatedly or pass it to other macros, [Bug 575194]
	reported by Peter Spjuth.

2002-06-28  Don Porter  <dgp@users.sourceforge.net>

	* docs/tcltest.n:	Doc revisions in progress.
	* library/tcltest/tcltest.tcl: Corrected -testdir default value. Was
	not reliable, and disagreed with docs! Thanks to Hemang Lavana. [Bug
	575150]

2002-06-28  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* unix/tclUnixThrd.c:	Renamed the Tcl_Platform* #defines to TclOS*
	* unix/tclUnixPipe.c:	because they are only used internally. Also
	* unix/tclUnixFile.c:	stopped double-#def of TclOSlstat [Bug 566099,
	* unix/tclUnixFCmd.c:	post-rename]
	* unix/tclUnixChan.c:
	* unix/tclUnixPort.h:

	* doc/string.n: Improved documentation for [string last] along lines
	described in [Bug 574799] so it indicates that the supplied index
	marks the end of the search space.

2002-06-27  Don Porter  <dgp@users.sourceforge.net>

	* doc/dde.n:		Work in progress updating the documentation
	* doc/http.n:		of the packages that come bundled with
	* doc/msgcat.n:		the Tcl source distribution, notably tcltest.
	* doc/registry.n:
	* doc/tcltest.n:

	* library/tcltest/tcltest.tcl:  Made sure that the TCLTEST_OPTIONS
	environment variablle configures tcltest at package load time.

2002-06-26  Vince Darley  <vincentdarley@users.sourceforge.net>

	* tests/fileSystem.test:
	* generic/tclIOUtil.c: fix to handling of empty paths "" which are not
	claimed by any filesystem [Bug 573758]. Ensure good error messages
	are given in all cases.
	* tests/cmdAH.test:
	* unix/tclUnixFCmd.c: fix to bug reported as part of [Patch 566669].
	Thanks to Taguchi, Takeshi for the report.

2002-06-26  Reinhard Max  <max@suse.de>

	* unix/tclUnixTime.c: Make [clock format] respect locale settings.
	* tests/clock.test:   [Bug 565880]. ***POTENTIAL INCOMPATIBILITY***

2002-06-26  Miguel Sofer  <msofer@users.sourceforge.net>

	* doc/CrtInterp.3:
	* doc/StringObj.3: clarifications by Don Porter, [Bug 493995] and [Bug
	500930].

2002-06-24  Don Porter  <dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl:	Corrected suppression of -verbose skip
	* tests/tcltest.test:		and start by [test -output]. Also
	corrected test suite errors exposed by corrected code. [Bug 564656]

2002-06-25  Reinhard Max  <max@suse.de>

	* unix/tcl.m4:       New macro SC_CONFIG_MANPAGES.
	* unix/configure.in: Added support for symlinks and compression when
	* unix/Makefile.in:  installing the manpages. [Patch 518052]
	* unix/mkLinks.tcl:  Default is still hardlinks and no compression.

	* unix/mkLinks:      generated
	* unix/configure:

	* unix/README:       Added documentation for the new features.

	* unix/tcl.m4 (SC_PATH_TCLCONFIG): Replaced ${exec_prefix}/lib by
	${libdir}.

2002-06-25  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclUtil.c (TclGetIntForIndex): Fix of critical [Bug 533364]
	generated when the index is bad and the result is a shared object. The
	T_ASTO(T_GOR, ...) idiom likely exists elsewhere though. Also removed
	some cruft that just complicated things to no advantage.
	(SetEndOffsetFromAny): Same fix, though this wasn't on the path
	excited by the bug.

2002-06-24  Don Porter  <dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl:	Implementation of TIP 101. Adds abd
	* tests/parseOld.test:		exports a [configure] command from
	* tests/tcltest.test:		tcltest.

2002-06-22  Don Porter  <dgp@users.sourceforge.net>

	* changes: updated changes file for 8.4b1 release.

	* library/tcltest/tcltest.tcl:	Corrections to tcltest and the Tcl
	* tests/basic.test:		test suite so that a test with options
	* tests/cmdInfo.test:		-constraints knownBug
	* tests/compile.test:		-limitConstraints 1 only tests the
	* tests/encoding.test:		knownBug tests. Mostly involves
	* tests/env.test:		replacing direct access to the
	* tests/event.test:		testConstraints array with calls to
	* tests/exec.test:		the testConstraint command (which
	* tests/execute.test:		requires tcltest version 2)
	* tests/fCmd.test:
	* tests/format.test:
	* tests/http.test:
	* tests/httpold.test:
	* tests/ioUtil.test:
	* tests/link.test:
	* tests/load.test:
	* tests/namespace.test:
	* tests/pkgMkIndex.test:
	* tests/reg.test:
	* tests/result.test:
	* tests/scan.test:
	* tests/stack.test:

2002-06-22  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tools/tcl.wse.in (Disk Label), unix/tcl.spec (version):
	* win/README.binary, README, win/configure.in, unix/configure.in:
	* generic/tcl.h (TCL_RELEASE_*, TCL_PATCH_LEVEL): Bump to beta1.

2002-06-21  Joe English  <jenglish@users.sourceforge.net>

	* generic/tclCompExpr.c:
	* generic/tclParseExpr.c: LogSyntaxError() should reset the
	interpreter result [Bug 550142 "Tcl_ExprObj -> abort"]

2002-06-21  Don Porter  <dgp@users.sourceforge.net>

	* unix/Makefile.in:	Updated all package install directories
	* win/Makefile.in:	to match current Major.minor versions
	* win/makefile.bc:	of the packages. Added tcltest package
	* win/makefile.vc:	to installation on Windows.

	* library/init.tcl:  Corrected comments and namespace style issues.
	Thanks to Bruce Stephens. [Bug 572025]

2002-06-21  Vince Darley  <vincentdarley@users.sourceforge.net>

	* tests/cmdAH.test:          Added TIP#99 implementation of 'file
	* tests/fCmd.test:           link'. Supports creation of symbolic and
	* tests/fileName.test:       hard links in the native filesystems and
	* tests/fileSystem.test:     in vfs's, when the individual filesystem
	* generic/tclTest.c:         supports the concept.
	* generic/tclCmdAH.c:
	* generic/tclIOUtil.c:
	* generic/tcl.h:
	* generic/tcl.decls:
	* doc/FileSystem.3:
	* doc/file.n:
	* mac/tclMacFile.c:
	* unix/tclUnixFile.c:
	* win/tclWinFile.c: Also enhanced speed of 'file normalize' on
	Windows.

2002-06-20  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclBasic.c (TclEvalObjvInternal): fix for [Bug 571385] in
	the implementation of TIP#62 (command tracing). Vince Darley, Hemang
	Lavana & Don Porter: thanks.

2002-06-20  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c (TclCompEvalObj): clarified and simplified the
	logic for compilation/recompilation.

2002-06-19  Joe English  <jenglish@users.sourceforge.net>

	* doc/file.n: Fixed indentation. No substantive changes.

2002-06-19  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclCmdMZ.c (Tcl_RegexpObjCmd): get the resultPtr again as
	the Tcl_ObjSetVar2 may cause the result to change. [Patch 558324]
	(watson)

2002-06-19  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c (TEBC): removing unused "for(;;)" loop;
	improved comments; re-indentation.

2002-06-18  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c (TEBC):
	- elimination of duplicated code in the non-immediate INST_INCR
	  instructions.
	- elimination of 103 (!) TclDecrRefCount macros. The different
	  instructions now jump back to a common "DecrRefCount zone" at the
	  top of the loop. The macro "ADJUST_PC" was replaced by two macros
	  "NEXT_INST_F" and "NEXT_INST_V" that take three params
	  (pcAdjustment, # of stack objects to discard, resultObjPtr handling
	  flag). The only instructions that retain a TclDecrRefCount are
	  INST_POP (for speed), the common code for the non-immediate
	  INST_INCR, INST_FOREACH_STEP and the two INST_LSET.

	The object size of tclExecute.o was reduced by approx 20% since the
	start of the consolidation drive, while making room for some peep-hole
	optimisation at runtime.

2002-06-18  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c (TEBC, INST_DONE): small bug in the panic code
	for tcl-stack corruption.

2002-06-17  David Gravereaux <davygrvy@pobox.com>

	Trims to support the removal of RESOURCE_INCLUDED from rc scripts from
	[FRQ 565088].

	* generic/tcl.h: moved the #ifndef RC_INVOKED start block up in the
	file. rc scripts don't need to know thread mutexes.

	* win/tcl.rc:
	* win/tclsh.rc: removed the #define RESOURCE_INCLUDED to let the
	built-in -DRC_INVOKED to the work.

2002-06-17  Jeff Hobbs  <jeffh@ActiveState.com>

	* doc/CrtTrace.3:        Added TIP#62 implementation of command
	* doc/trace.n:           execution tracing [FRQ 462580] (lavana).
	* generic/tcl.h:         This includes enter/leave tracing as well
	* generic/tclBasic.c:    as inter-procedure stepping.
	* generic/tclCmdMZ.c:
	* generic/tclCompile.c:
	* generic/tclExecute.c:
	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclIntDecls.h:
	* generic/tclStubInit.c:
	* generic/tclVar.c:
	* tests/trace.test:

2002-06-17  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* win/tclWinPipe.c (BuildCommandLine): Fixed [Bug 554068] ([exec] on
	windows did not treat { in filenames well.). Bug reported by Vince
	Darley <vincentdarley@users.sourceforge.net>, patch provided by Vince
	too.

2002-06-17  Joe English  <jenglish@users.sourceforge.net>

	* generic/tcl.h: #ifdef logic for K&R C backwards compatibility
	changed to assume modern C by default. See [FRQ 565088] for full
	details.

2002-06-17  Don Porter  <dgp@users.sourceforge.net>

	* doc/msgcat.n: Corrected en_UK references to en_GB. UK is not a
	country designation recognized in ISO 3166.

	* library/msgcat/msgcat.tcl:  More Windows Registry locale codes from
	Bruno Haible.

	* doc/msgcat.n:
	* library/msgcat/msgcat.tcl:
	* library/msgcat/pkgIndex.tcl:
	* tests/msgcat.test:  Revised locale initialization to interpret
	environment variable locale values according to XPG4, and to recognize
	the LC_ALL and LC_MESSAGES values over that of LANG. Also added many
	Windows Registry locale values to those recognized by msgcat. Revised
	tests and docs. Bumped to version 1.3. Thanks to Bruno Haible for the
	report and assistance crafting the solution. [Bug 525522, 525525]

2002-06-16  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclCompile.c (TclCompileTokens): a better algorithm for the
	previous bug fix.

2002-06-16  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclCompile.c (TclCompileTokens):
	* tests/compile.test: [Bug 569438] in the processing of dollar
	variables; report by Georgios Petasis.

2002-06-16  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c: bug in the consolidation of the INCR_..._STK
	instructions; the bug could not be exercised as the (faulty)
	instruction INST_INCR_ARRAY_STK was never compiled-in (related to [Bug
	569438]).

2002-06-14  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c (TclExecuteByteCode): runtime peep-hole
	optimisation of variables (INST_STORE, INST_INCR) and commands
	(INST_INVOKE); faster check for the existence of a catch.
	(TclExecuteByteCode): runtime peep-hole optimisation of comparisons.
	(TclExecuteByteCode): runtime peep-hole optimisation of INST_FOREACH -
	relies on peculiarities of the code produced by the bytecode compiler.

2002-06-14  David Gravereaux <davygrvy@pobox.com>

	* win/rules.vc: The test for compiler optimizations was in error.
	Thanks goes to Roy Terry <royterry@earthlink.net> for his assistance
	with this.

2002-06-14  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/trace.n, tests/trace.test:
	* generic/tclCmdMZ.c (Tcl_TraceObjCmd,TclTraceCommandObjCmd)
	(TclTraceVariableObjCmd): Changed references to "trace list" to
	"trace info" as mandated by TIP#102.

2002-06-13  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c (TclExecuteByteCode): consolidated code for the
	conditional branch instructions.

2002-06-13  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c (TclExecuteByteCode): fixed the previous patch;
	wouldn't compile with TCL_COMPILE_DEBUG set.

2002-06-13  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c (TclExecuteByteCode): consolidated the handling
	of exception returns to INST_INVOKE and INST_EVAL, as well as most of
	the code for INST_CONTINUE and INST_BREAK, in the new jump target
	"processExceptionReturn".

2002-06-13  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c (TclExecuteByteCode): consolidated variable
	handling opcodes, replaced redundant code with some 'goto'. All
	store/append/lappend opcodes on the same data type now share the main
	code; same with incr opcodes.
	* generic/tclVar.c: added the bit TCL_TRACE_READS to the possible
	flags to Tcl_SetVar2Ex - it causes read traces to be fired prior to
	setting the variable. This is used in the core for [lappend].

	***NOTE*** the usage of TCL_TRACE_READS in Tcl_(Obj)?GetVar.* is not
	documented; there, it causes the call to create the variable if it
	does not exist. The new usage in Tcl_(Obj)?SetVar.* remains
	undocumented too ...

2002-06-13  Vince Darley  <vincentdarley@users.sourceforge.net>

	* tests/fCmd.test:
	* tests/winFile.test:
	* tests/fileSystem.test:
	* generic/tclTest.c:
	* generic/tclCmdAH.c:
	* generic/tclIOUtil.c:
	* doc/FileSystem.3:
	* mac/tclMacFile.c:
	* unix/tclUnixFile.c:
	* win/tclWinFile.c: fixed up further so both compiles and actually
	works with VC++ 5 or 6.
	* win/tclWinInt.h:
	* win/tclWin32Dll.c: cleaned up code and vfs tests and added tests for
	the internal changes of 2002-06-12, to see whether WinTcl on NTFS can
	coexist peacefully with links in the filesystem. Added new test
	command 'testfilelink' to enable the newer code to be tested.
	* tests/fCmd.test: (made certain tests of 'testfilelink' not run on
	unix).

2002-06-12  Miguel Sofer  <msofer@users.sourceforge.net>

	* tclBasic.c (Tcl_DeleteTrace): fixed [Bug 568123] (thanks to Hemang
	Lavana)

2002-06-12  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/tclWinFile.c: corrected the symbolic link handling code to allow
	it to compile. Added real definition of REPARSE_DATA_BUFFER (found in
	winnt.h). Most of the added definitions appear to have correct,
	cross-Win-version equivalents in winnt.h and should be removed, but
	just making things "work" for now.

2002-06-12  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclIOUtil.c:
	* generic/tcl.decls:
	* generic/tclDecls.h: made code for Tcl_FSNewNativePath agree with man
	pages.

	* doc/FileSystem.3: clarified the circumstances under which certain
	functions are called in the presence of symlinks.

	* win/tclWinFile.c:
	* win/tclWinPort.h:
	* win/tclWinInt.h:
	* win/tclWinFCmd.c:  Fix for Windows to allow 'file lstat', 'file
	type', 'glob -type l', 'file copy', 'file delete', 'file normalize',
	and all VFS code to work correctly in the presence of symlinks
	(previously Tcl's behaviour was not very well defined). This also
	fixes possible serious problems in all versions of WinTcl where 'file
	delete' on a NTFS symlink could delete the original, not the symlink.
	Note: symlinks cannot yet be created in pure Tcl.

2002-06-11  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclBasic.c:
	* generic/tclCompCmds.c:
	* generic/tclInt.h: reverted the new compilation functions; replaced
	by a more general approach described below.

	* generic/tclCompCmds.c:
	* generic/tclCompile.c: made *all* compiled variable access attempts
	create an indexed variable - even get or incr without previous set.
	This allows indexed access to local variables that are created and set
	at runtime, for example by [global], [upvar], [variable], [regexp],
	[regsub].

2002-06-11  Miguel Sofer  <msofer@users.sourceforge.net>

	* doc/global.n:
	* doc/info.n:
	* test/info.test:
	* generic/tclCmdIL.c: fix for [Bug 567386], [info locals] was
	reporting some linked variables.

	* generic/tclBasic.c:
	* generic/tclCompCmds.c:
	* generic/tclInt.h: added compile functions for [global], [variable]
	and [upvar]. They just declare the new local variables, the commands
	themselves are not compiled-in. This gives a notably faster read
	access to these linked variables.

2002-06-11  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c: optimised algorithm for exception range
	lookup; part of [Patch 453709].

2002-06-10  Vince Darley  <vincentdarley@users.sourceforge.net>

	* unix/tclUnixFCmd.c: fixed [Bug 566669]
	* generic/tclIOUtil.c: improved and sped up handling of native paths
	(duplication and conversion to normalized paths), particularly on
	Windows.
	* modified part of above commit, due to problems on Linux. Will
	re-examine bug report and evaluate more closely.

2002-06-07  Don Porter  <dgp@users.sourceforge.net>

	* tests/tcltest.test:  More corrections to test suite so that tests of
	failing [test]s don't show up themselves as failing tests.

2002-06-07  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclExecute.c: Tidied up headers in relation to float.h to
	cut the cruft and ensure DBL_MAX is defined since doubles seem to be
	the same size everywhere; if the assumption isn't true, the variant
	platforms had better have run configure...

	* unix/tclUnixPort.h (EOVERFLOW): Added code to define it if it
	wasn't previously defined. Also some other general tidying and adding
	of comments. [Bugs 563122, 564595]
	* compat/tclErrno.h: Added definition for EOVERFLOW copied from
	Solaris headers; I've been unable to find any uses of EFTYPE, which
	was the error code previously occupying the slot, in Tcl, or any
	definition of it in the Solaris headers.

2002-06-06  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/dltest/Makefile.in: Remove hard coded CFLAGS=-g and add
	CFLAGS_DEBUG, CFLAGS_OPTIMIZE, and CFLAGS_DEFAULT varaibles. [Bug
	565488]

2002-06-06  Don Porter  <dgp@users.sourceforge.net>

	* tests/tcltest.test:  Corrections to test suite so that tests of
	failing [test]s don't show up themselves as failing tests.

	* tests/io.test: Fixed up namespace variable resolution issues
	revealed by running test suite with "-singleproc 1".

	* doc/tcltest.n:
	* library/tcltest/tcltest.tcl:
	* tests/tcltest.test: Several updates to tcltest.
	  1) changed to lazy initialization of test constraints
	  2) deprecated [initConstraintsHook]
	  3) repaired badly broken [limitConstraints].
	  4) deprecated [threadReap] and [mainThread]
	[Patch 512214, Bug 558742, Bug 461000, Bug 534903]

2002-06-06  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tclUnixThrd.c (TclpReaddir, TclpLocaltime, TclpGmtime): added
	mutex wrapped calls to readdir, localtime & gmtime in case their
	thread-safe *_r counterparts are not available.
	* unix/tcl.m4: added configure check for readdir_r
	* unix/tcl.m4 (Darwin): set TCL_DEFAULT_ENCODING to utf-8 on MacOSX
	(where posix file apis expect utf-8, not iso8859-1).
	* unix/configure: regen
	* unix/Makefile.in: set DYLD_LIBRARY_PATH in parallel to
	LD_LIBRARY_PATH for MacOSX dynamic linker.
	* generic/tclEnv.c (TclSetEnv): fix env var setting on MacOSX (adapted
	from [Patch 524352] by jkbonfield).

2002-06-05  Don Porter  <dgp@users.sourceforge.net>

	* doc/Tcl_Main.3: Documented $tcl_rcFileName and added more
	clarifications about the intended use of Tcl_Main(). [Bug 505651]

2002-06-05  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclFileName.c (TclGlob): mac specific fix to recent changes
	in 'glob -tails' handling.
	* mac/tclMacPort.h:
	* mac/tclMacChan.c: fixed TIP#91 bustage.
	* mac/tclMacResource.c (Tcl_MacConvertTextResource): added utf
	conversion of text resource contents.
	* tests/macFCmd.test (macFCmd-1.2): allow CWIE creator.

2002-06-04  Don Porter  <dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl:
	* tests/init.test:
	* tests/tcltest.test:	Added more TIP 85 tests from Arjen Markus.
	Converted tcltest.test to use a private namespace. Fixed bugs in
	[tcltest::Eval] revealed by calling [tcltest::test] from a non-global
	namespace, and namespace errors in init.test.

2002-06-04  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/README: Update msys+mingw URL.

2002-06-03  Don Porter  <dgp@users.sourceforge.net>

	* doc/tcltest.n:
	* library/tcltest/tcltest.tcl:
	* library/tcltest/pkgIndex.tcl:
	* tests/tcltest.test:  Implementation of TIP 85. Allows tcltest users
	to add new legal values of the -match option to [test], associating
	each with a Tcl command that does the matching of expected results
	with actual results of tests. Thanks to Arjen Markus. => tcltest 2.1
	[Patch 521362]

2002-06-03  Miguel Sofer  <msofer@users.sourceforge.net>

	* doc/namespace.n: added description of [namepace forget] behaviour
	for unqualified patterns. [Bug 559268]

2002-06-03  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c: reverting an accidental modification in the
	last commit.

2002-06-03  Miguel Sofer  <msofer@users.sourceforge.net>

	* doc/Tcl.n: clarify the empty variable name issue ([Bug 549285]
	reported by Tom Krehbiel, patch by Don Porter).

2002-05-31  Don Porter  <dgp@users.sourceforge.net>

	* library/package.tcl:  Fixed leak of slave interp in [pkg_mkIndex].
	Thanks to Helmut for report. [Bug 550534]

	* tests/io.test:
	* tests/main.test:  Use the "stdio" constraint to control whether an
	[open "|[interpreter]"] is attempted.

	* generic/tclExecute.c (TclMathInProgress,TclExecuteByteCode
	(ExprCallMathFunc):
	* generic/tclInt.h (TclMathInProgress):
	* unix/Makefile.in (tclMtherr.*):
	* unix/configure.in (NEED_MATHERR):
	* unix/tclAppInit.c (matherr):
	* unix/tclMtherr.c (removed file):
	* win/tclWinMtherr.c (_matherr): Removed internal routine
	TclMathInProgress and Unix implementation of matherr(). These are now
	obsolete, dealing with very old versions of the C math library.
	Windows version is retained in case Borland compilers require it, but
	it is inactive. Thanks to Joe English. [Bug 474335, Patch 555635]

	* unix/configure: regen

2002-05-30  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclCompExpr.c:
	* generic/tclCompile.c:
	* generic/tclCompile.h: removed exprIsJustVarRef and
	exprIsComparison from the ExprInfo and CompileEnv structs. These
	were set, but not used since dec 1999 [Bug 562383].

2002-05-30  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFileName.c (TclGlob): fix to longstanding 'knownBug' in
	fileName tests 15.2-15.4, and fix to a new Tcl 8.4 bug in certain uses
	of 'glob -tails'.
	* tests/fileName.test: removed 'knownBug' flag from some tests, added
	some new tests for above bugs.

2002-05-29  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/configure: regen'ed
	* unix/configure.in: replaced bigendian check with autoconf standard
	AC_C_BIG_ENDIAN, which defined WORDS_BIGENDIAN on bigendian systems.
	* generic/tclUtf.c (Tcl_UniCharNcmp):
	* generic/tclInt.h (TclUniCharNcmp): use WORDS_BIGENDIAN instead of
	TCL_OPTIMIZE_UNICODE_COMPARE to enable memcmp alternative.

	* generic/tclExecute.c (TclExecuteByteCode INST_STR_CMP):
	* generic/tclCmdMZ.c (Tcl_StringObjCmd): changed the case for choosing
	the Tcl_UniCharNcmp compare to when both objs are of StringType, as
	benchmarks show that is the optimal check (both bigendian and
	littleendian systems).

2002-05-29  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclMain.c: Removed "dummy" reference to Tcl_LinkVar. It is
	no longer needed since Tcl_Main() now actually calls Tcl_LinkVar().
	Thanks to Joe English for pointing that out.

2002-05-29  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclExecute.c (TclExecuteByteCode):
	* generic/tclCmdMZ.c (Tcl_StringObjCmd): Use the macro version.
	* generic/tclInt.h (TclUniCharNcmp): Optimised still further with a
	macro for use in sensitive places like tclExecute.c

	* generic/tclUtf.c (Tcl_UniCharNcmp): Use new flag to figure out when
	we can use an optimal comparison scheme, and default to the old scheme
	in other cases which is at least safe.
	* unix/configure.in (TCL_OPTIMIZE_UNICODE_COMPARE): New optional flag
	that indicates when we can use memcmp() to compare Unicode strings
	(i.e. when the high-byte of a Tcl_UniChar precedes the low-byte.)

2002-05-29  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclInt.decls:
	* generic/tclIntDecls.h:
	* generic/tclStubInit.c:
	* generic/tclUtf.c: added TclpUtfNcmp2 private command that
	mirrors Tcl_UtfNcmp, but takes n in bytes, not utf-8 chars. This
	provides a faster alternative for comparing utf strings	internally.
	(Tcl_UniCharNcmp, Tcl_UniCharNcasecmp): removed the explicit end of
	string check as it wasn't correct for the function (by doc and logic).

	* generic/tclCmdMZ.c (Tcl_StringObjCmd): reworked the string equal
	comparison code to use TclpUtfNcmp2 as well as short-circuit for
	equal objects or unequal length strings in the equal case.
	Removed the use of goto and streamlined the other parts.

	* generic/tclExecute.c (TclExecuteByteCode): added check for object
	equality in the comparison instructions. Added short-circuit for !=
	length strings in INST_EQ, INST_NEQ and INST_STR_CMP. Reworked
	INST_STR_CMP to use TclpUtfNcmp2 where appropriate, and only use
	Tcl_UniCharNcmp when at least one of the objects is a Unicode obj with
	no utf bytes.

	* generic/tclCompCmds.c (TclCompileStringCmd): removed error creation
	in code that no longer throws an error.

	* tests/string.test:
	* tests/stringComp.test: added more string comparison checks.

	* tests/clock.test: better qualified 9.1 constraint check for %s.

2002-05-28  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclThreadAlloc.c (TclpRealloc, TclpFree): protect
	against the case when NULL is based.

	* tests/clock.test: added clock-9.1
	* compat/strftime.c:
	* generic/tclClock.c:
	* generic/tclInt.decls:
	* generic/tclIntDecls.h:
	* unix/tclUnixTime.c: fix for Windows msvcrt mem leak caused by using
	an env(TZ) setting trick for in clock format -gmt 1. This also makes
	%s seem to work correctly with -gmt 1 as well as making it a lot
	faster by avoid the env(TZ) hack. TclpStrftime now takes useGMT as an
	arg. [Bug 559376]

2002-05-28  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclIOUtil.c: fixes to Tcl_FSLoadFile when called on a file
	inside a vfs. This should avoid leaving temporary files sitting
	around on exit. [Bug 545579]

2002-05-27  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* win/tclWinError.c: Added comment on conversion of
	ERROR_NEGATIVE_SEEK because that is a mapping that really belongs,
	and not a catch-all case.
	* win/tclWinPort.h (EOVERFLOW): Should be either EFBIG or EINVAL
	* generic/tclPosixStr.c (Tcl_ErrnoId, Tcl_ErrnoMsg): EOVERFLOW can
	potentially be a synonym for EINVAL.

2002-05-24  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	=== Changes due to TIP#91 ===

	* win/tclWinPort.h: Added declaration of EOVERFLOW.
	* doc/CrtChannel.3: Added documentation of wideSeekProc.
	* generic/tclIOGT.c (TransformSeekProc, TransformWideSeekProc):
	Adapted to use the new channel mechanism.
	* unix/tclUnixChan.c (FileSeekProc, FileWideSeekProc): Renamed
	FileSeekProc to FileWideSeekProc and created new FileSeekProc which
	has the old-style interface and which errors out with EOVERFLOW when
	the returned file position can't fit into the return type (int for
	historical reasons).
	* win/tclWinChan.c (FileSeekProc, FileWideSeekProc): Renamed
	FileSeekProc to FileWideSeekProc and created new FileSeekProc which
	has the old-style interface and which errors out with EOVERFLOW when
	the returned file position can't fit into the return type (int for
	historical reasons).
	* mac/tclMacChan.c (FileSeek): Reverted to old interface; Macs lack
	large-file support because I can't see how to add it.
	* generic/tclIO.c (Tcl_Seek, Tcl_Tell): Given these functions
	knowledge of the new arrangement of channel types.
	(Tcl_ChannelVersion): Added recognition of new version code.
	(HaveVersion): New function to do version checking.
	(Tcl_ChannelBlockModeProc, Tcl_ChannelFlushProc)
	(Tcl_ChannelHandlerProc): Made these functions use HaveVersion for
	ease of future maintainability.
	(Tcl_ChannelBlockModeProc): Obvious lookup function.
	* generic/tcl.h (Tcl_ChannelType): New wideSeekProc field, and
	seekProc type restored to old interpretation.
	(TCL_CHANNEL_VERSION_3): New channel version.

2002-05-24  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* tests/winPipe.test: Applied patch for [Bug 549617]. Patch and bug
	report by Kevin Kenny <kennykb@users.sourceforge.net>.

	* win/tclWinSock.c (TcpWatchProc): Fixed [Bug 557878]. We are not
	allowed to mess with the watch mask if the socket is a server socket.
	I believe that the original reporter is George Peter Staplin.

2002-05-21  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure: Regen.
	* unix/configure.in: Invoke SC_ENABLE_SHARED before calling
	SC_CONFIG_CFLAGS so that the SHARED_BUILD variable can be checked
	inside SC_CONFIG_CFLAGS.
	* unix/tcl.m4 (SC_CONFIG_CFLAGS): Pass -non_shared instead of -shared
	to ld when configured with --disable-shared under OSF. [Bug 540390]

2002-05-20  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclInt.h: added prototype for TclpFilesystemPathType().
	* mac/tclMacChan.c: use MSL provided creator type if available instead
	of the default 'MPW '.

2002-05-16  Joe English  <jenglish@users.sf.net>

	* doc/CrtObjCmd.3: Added Tcl_GetCommandFromObj, Tcl_GetCommandFullName
	[Bugs 547987, 414921]

2002-05-14  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* unix/tclUnixChan.c (TtyOutputProc): #if/#endif-ed this function out
	to stop compiler warnings. Also much general tidying of comments in
	this file and removal of whitespace from blank lines.

2002-05-13  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* unix/tclUnixChan.c (SETBREAK): Solaris thinks ioctl() takes a signed
	second argument, and Linux thinks ioctl() takes an unsigned second
	argument. So need a longer definition of this macro to get neither to
	spew warnings...

2002-05-13  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclEvent.c:
	* generic/tclIOUtil.c:
	* generic/tclInt.h: clean up all memory allocated by the filesystem,
	via introduction of 'TclFinalizeFilesystem'.
	Move TclFinalizeLoad into TclFinalizeFilesystem so we can be sure it
	is called at just the right time.
	Fix bad comment also. [Bug 555078 and 'fs' part of 543549]
	* win/tclWinChan.c: fix comment referring to wrong function.

2002-05-10  Don Porter  <dgp@users.sourceforge.net>

	* tests/load.test:
	* tests/safe.test:
	* tests/tcltest.test: Corrected some list-quoting issues and other
	matters that cause tests to fail when the patch includes special
	characters. Report from Vince Darley. [Bug 554068]

2002-05-08    David Gravereaux <davygrvy@pobox.com>

	* doc/file.n:
	* tools/man2tcl.c:
	* tools/man2help2.tcl:  Thanks to Peter Spjuth
	<peter.spjuth@space.se>, again. My prior fix for single-quote macro
	mis-understanding was wrong. Reverted to reimpliment the 'macro2' proc
	which handles single-quote macros and restored file.n text arrangement
	to avoid single-quotes on the first line. Sorry for all the confusion.

2002-05-08  David Gravereaux <davygrvy@pobox.com>

	* tools/man2tcl.c:
	* tools/man2help2.tcl: Proper source of macro error misunderstanding
	single-quote as the leading macro command found and repaired.

	* doc/file.n: Reverted to prior state before I messed with it.

2002-05-08  Don Porter  <dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl: Corrected [uplevel] quoting when
	[source]-ing test script in subdirectories.
	* tests/fileName.test:
	* tests/load.test:
	* tests/main.test:
	* tests/tcltest.test:
	* tests/unixInit.test: Fixes to test suite when there's a space in the
	working path. Thanks to Kevin Kenny.

2002-05-07  David Gravereaux <davygrvy@pobox.com>

	-- Changes from Peter Spjuth <peter.spjuth@space.se>
	* tools/man2tcl.c: Increased line buffer size and a bail-out if that
	should ever be over-run.
	* tools/man2help.tcl: Include Courier New font in rtf header.
	* tools/man2help2.tcl: Improved handling of CS/CE fields. Use Courier
	New for code samples and indent better.

	* doc/file.n:
	* doc/TraceCmd.3:  winhelp conversion tools where understanding
	a ' as the first character on a line to be an unknown macro.
	Not knowing how to repair tools/man2tcl.c, I decided to rearrange
	the text in the docs instead.

2002-05-07  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFileName.c: fix to similar segfault when using 'glob
	-types nonsense -dir dirname -join * *'. [Bug 553320]

	* doc/FileSystem.3: further documentation on vfs.
	* tests/cmdAH.test:
	* tests/fileSystem.test:
	* tests/pkgMkindex.test: Fix to testsuite bugs when running out of
	directory whose name contains '{' or '['.

2002-05-07  Miguel Sofer  <msofer@users.sourceforge.net>

	* tests/basic.test: Fix for [Bug 549607]
	* tests/encoding.test: Fix for [Bug 549610]
	These are testsuite bugs that caused failures when the filename
	contained spaces. Report & fix by Kevin Kenny.

2002-05-02  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFileName.c: fix to freeing a bad object (i.e. segfault)
	when using 'glob -types nonsense -dir dirname'.
	* generic/tclWinFile.c: fix to [Bug 551306], also wrapped some long
	lines.
	* tests/fileName.test: added several tests for the above bugs.
	* doc/FileSystem.3: clarified documentation on refCount requirements
	of the object returned by the path type function.
	* generic/tclIOUtil.c:
	* win/tclWinFile.c:
	* unix/tclUnixFile.c:
	* mac/tclMacFile.c: moved TclpFilesystemPathType to the platform-
	specific directories, so we can add missing platform-specific
	implementations. On Windows, 'file system' now returns useful results
	like "native NTFS", "native FAT" for that system. Unix and MacOS still
	only return "native".
	* doc/file.n: clarified documentation.
	* tests/winFile.test: test for 'file system' returning correct values.
	* tests/fileSystem.test: test for 'file system' returning correct
	values. Clean up after failed previous test run.

2002-04-26  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/configure:
	* unix/tcl.m4: change HP-11 SHLIB_LD_LIBS from "" to ${LIBS} so that
	the .sl knows its dependent libs.

2002-04-26  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/obj.test (obj-11.[56]): Test conversion to boolean more
	thoroughly.
	* generic/tclObj.c (SetBooleanFromAny): Was not calling an integer
	parsing function on native 64-bit platforms! [Bug 548686]

2002-04-24  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclInt.h: corrected TclRememberJoinableThread decl to use
	VOID instead of void.
	* generic/tclThreadJoin.c: noted that this code isn't needed on Unix.

2002-04-23  Jeff Hobbs  <jeffh@ActiveState.com>

	* doc/exec.n:
	* doc/tclvars.n: doc updates [Patch 509426] (gravereaux)

2002-04-24  Daniel Steffen  <das@users.sourceforge.net>

	* mac/tclMacResource.r: added check of TCLTK_NO_LIBRARY_TEXT_RESOURCES
	#define to allow disabling the inclusion of the tcl library code in
	the resource fork of Tcl executables and shared libraries.

2002-04-23  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/TraceCmd.3: New file that documents Tcl_CommandTraceInfo,
	Tcl_TraceCommand and Tcl_UntraceCommand [Bug 414927]

2002-04-22  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclAlloc.c:
	* generic/tclInt.h:
	* generic/tclThreadAlloc.c (new):
	* unix/Makefile.in:
	* unix/tclUnixThrd.c:
	* win/Makefile.in:
	* win/tclWinInt.h:
	* win/tclWinThrd.c: added new threaded allocator contributed by AOL
	that significantly reduces lock contention when multiple threads are
	in use. Only Windows and Unix implementations are ready, and the
	Windows one may need work. It is only used by default on Unix for now,
	and requires that USE_THREAD_ALLOC be defined (--enable-threads on
	Unix will define this).

	* generic/tclIOUtil.c (Tcl_FSRegister, Tcl_FSUnregister): corrected
	calling of Tcl_ConditionWait to ensure that there would be a condition
	to wait upon.

	* generic/tclCmdAH.c (Tcl_FileObjCmd): added cast in FILE_SIZE.

	* win/tclWinFCmd.c (DoDeleteFile): check return of setattr API calls
	in file deletion for correct Win32 API handling.

	* win/Makefile.in: correct dependencies for shell, gdb, runtest
	targets.

	* doc/clock.n:
	* compat/strftime.c (_fmt): change strftime to correctly handle
	localized %c, %x and %X on Windows. Added some notes about how the
	other values could be further localized.

2002-04-19  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclMain.c (Tcl_Main):  Free the memory allocated for the
	startup script path. [Bug 543549]

	* library/msgcat/msgcat.tcl:  [mcmax] wasn't using the caller's
	namespace when determining the max translated length. Also made
	revisions for better use of namespace variables and more efficient
	[uplevel]s.

	* doc/msgcat.n:
	* library/msgcat/msgcat.tcl:
	* library/msgcat/pkgIndex.tcl:  Added [mcload] to the export list of
	msgcat; bumped to 1.2.3. [Bug 544727]

2002-04-20  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclInt.decls:
	* generic/tclIntPlatDecls.h:
	* generic/tclStubInit.c:
	* mac/tclMacFCmd.c:
	* mac/tclMacFile.c:
	* mac/tclMacUtil.c: Modified TclpObjNormalizePath to be alias file
	aware, and replaced various calls to FSpLocationFrom*Path by calls to
	new alias file aware versions FSpLLocationFrom*Path. The alias file
	aware routines don't resolve the last component of a path if it is an
	alias. This allows [file copy/delete] etc. to act correctly on alias
	files. (c.f. discussion in [Bug 511666])

2002-04-19  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/lindex.test (lindex-3.7):
	* generic/tclUtil.c (TclGetIntForIndex): Stopped indexes from hitting
	wide ints. [Bug 526717]

2002-04-18  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclNamesp.c:
	* tests/info.test: [Bug 545325] info level didn't report namespace
	eval, bug report by Richard Suchenwirth.

2002-04-18  Don Porter  <dgp@users.sourceforge.net>

	* doc/subst.n:  Clarified documentation on handling unusual return
	codes during substitution, and on variable substitutions implied by
	command substitution, and vice versa. [Bug 536838]

2002-04-18  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclCmdIL.c (InfoBodyCmd):
	* tests/info.test (info-2.6): Proc bodies without string reps would
	report as empty. [Bug 545644]

	* generic/tclCmdMZ.c (Tcl_SubstObj): More clarification for comment on
	behaviour when substitutions are not well-formed, prompted by [Bug
	536831]; alas, removing the ill-defined behaviour is a lot of work.

2002-04-18  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c:
	* tests/expr-old.test: fix for [Bug 542588] (Phil Ehrens), where "too
	large integers" were reported as "floating-point value" in [expr]
	error messages.

2002-04-17  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclEncoding.c (EscapeFromUtfProc):
	* generic/tclIO.c (WriteChars, Tcl_Close): corrected the handling of
	outputting end escapes for escape-based encodings.
	[Bug 526524] (yamamoto)

2002-04-17  Don Porter  <dgp@users.sourceforge.net>

	* doc/tcltest.n:  Removed [saveState] and [restoreState] from tcltest
	2 documentation, effectively deprecating them. [Bug 495660]
	* library/tcltest/tcltest.tcl: Made separate export for commands kept
	only for tcltest 1 compatibility.

	* tests/iogt.test: Revised to run tests in a namespace, rather than
	use the useless and buggy [saveState] and [restoreState] commands of
	tcltest. Updated to use tcltest 2 as well. [Patch 544911]

2002-04-16  Don Porter  <dgp@users.sourceforge.net>

	* tests/io.test: Revised to run tests in a namespace, rather than use
	the useless and buggy [saveState] and [restoreState] commands of
	tcltest. Updated to use tcltest 2 as well. [Patch 544546]

2002-04-15  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclProc.c:
	* tests/proc-old.test: Improved stack trace for TCL_BREAK and
	TCL_CONTINUE returns from procs. Patch by Don Porter [Bug 536955].

	* generic/tclExecute.c:
	* tests/compile.test: made bytecodes check for a catch before
	returning; the compiled [return] is otherwise non-catchable. [Bug
	542142] reported by Andreas Kupries.

2002-04-15  Don Porter  <dgp@users.sourceforge.net>

	* tests/socket.test:  Increased timeout values so that tests have
	time to successfully complete even on slow/busy machines. [Bug 523470]

	* doc/tcltest.n:
	* library/tcltest/tcltest.tcl:
	* tests/tcltest.test:  Revised [tcltest::test] to return errors when
	called with invalid syntax and to accept exactly two arguments as
	documented. Improved error messages. [Bug 497446, Patch 513983]
	***POTENTIAL INCOMPATIBILITY***: Incompatible with previous tcltest
	2.* releases, found only in alpha releases of Tcl 8.4.

2002-04-11  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclNotify.c (TclFinalizeNotifier): remove remaining
	unserviced events on finalization.

	* win/tcl.m4: Enabled COFF as well as CV style debug info with
	--enable-symbols to allow Dr. Watson users to see function info. More
	info on debugging levels can be obtained at:
	http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp

	* tests/ioCmd.test: fixed iocmd-8.15 to have mac and unixPc variants.

	* generic/tclParse.c (Tcl_ParseVar): conditionally incr obj refcount
	to prevent possible mem leak.

2002-04-08  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tcl.h: no <sys/types.h> on mac.
	* mac/tclMacFile.c: minor fixes to Vince's changes from 03-24.
	* mac/tclMacOSA.c:
	* mac/tclMacResource.c: added missing Tcl_UtfToExternalDString
	conversions of resource file names.
	* mac/tclMacSock.c (TcpGetOptionProc): fixed bug introduced by Andreas
	on 02-25; changed strcmp's to strncmp's so that option comparison
	behaves like on other platforms.
	* mac/tcltkMacBuildSupport.sea.hqx (CW Pro6 changes): added support to
	allow Tk to hookup C library stderr/stdout to TkConsole.
	* tests/basic.test:
	* tests/cmdAH.test:
	* tests/encoding.test:
	* tests/fileSystem.test:
	* tests/ioCmd.test: fixed tests failing on mac: check for existence of
	[exec], changed some result strings.

2002-04-06  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/tclUnixFCmd.c (Realpath): added a little extra code to
	initialize a realpath arg when compiling in PURIFY mode in order to
	prevent spurious purify warnings. We should really create our own
	realpath implementation, but this will at least quiet purify for now.

2002-04-05  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCmdMZ.c (Tcl_SubstObj):
	* tests/subst.test:  Corrected [subst] so that return codes TCL_BREAK
	and TCL_CONTINUE returned by variable substitution have the same
	effect as when those codes are returned by command substitution. [Bug
	536879]

2002-04-03  Jeff Hobbs  <jeffh@ActiveState.com>

	* library/tcltest/tcltest.tcl: added getMatchingFiles back (alias to
	GetMatchingFiles), which was a public function in tcltest 1.0.

2002-04-01  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclEnv.c:
	* generic/tclIOUtil.c: invalidate filesystem cache when the user
	changes env(HOME). Fixes [Bug 535621]. Also cleaned up some of the
	documentation.
	* tests/fileSystem.test: added test for bug just fixed.

2002-04-01  Kevin Kenny  <kennykb@acm.org>

	* win/tclWinTime.c (Tcl_GetTime): made the checks of clock frequency
	more permissive to cope with the fact that Win98SE is observed to
	return 1.19318 in place of 1.193182 for the performance counter
	frequency.

2002-03-29  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclCmdMZ.c (Tcl_TraceObjCmd, TraceVarProc)
	(TraceCommandProc, TclTraceCommandObjCmd):  corrected potential
	double-free of traces on variables by flagging in Trace*Proc that it
	will free the var in case the eval wants to delete the var trace as
	well. [Bug 536937] Also converted Tcl_UntraceVar -> Tcl_UntraceVar2
	and Tcl_Eval to Tcl_EvalEx in Trace*Proc for slight efficiency
	improvement.

2002-03-29  Don Porter  <dgp@users.sourceforge.net>

	* doc/AllowExc.3:
	* generic/tclBasic.c (Tcl_EvalObjv,Tcl_EvalEx,Tcl_EvalObjEx):
	* generic/tclCompile.h (TclCompEvalObj):
	* generic/tclExecute.c (TclCompEvalObj,TclExecuteByteCode):
	* tests/basic.test: Corrected problems with Tcl_AllowExceptions having
	influence over the wrong scope of Tcl_*Eval* calls. Patch from Miguel
	Sofer. Report from Jean-Claude Wippler. [Bug 219181]

2002-03-28  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclVar.c: Refactored CallTraces to collect repeated handling
	of its returned value into CallTraces itself.

2002-03-28  David Gravereaux <davygrvy@pobox.com>

	* tools/feather.bmp:
	* tools/man2help.tcl:
	* tools/man2help2.tcl:
	* win/makefile.vc: More winhelp target fixups. Added a feather bitmap
	to the non-scrollable area and changed the color to be yellow from a
	plain white. The colors can be whatever we want them to be, but
	thought I would start with something bold. [Bug 527941]

	* doc/SetVar.3:
	* doc/TraceVar.3:
	* doc/UpVar.3:  .AP macro syntax repair.

2002-03-27  David Gravereaux <davygrvy@pobox.com>

	* tools/man2help.tcl:
	* win/makefile.vc:  winhelp target now copies all needed files from
	tools/ to a workarea under $(OUT_DIR) and builds it from there. No
	build cruft is left in tools/ anymore. All paths used in man2help.tcl
	are now relative to where the script is. [Bug 527941]

2002-03-27  David Gravereaux <davygrvy@pobox.com>

	* win/.cvsignore:
	* win/buildall.vc.bat:
	* win/coffbase.txt:
	* win/makefile.vc:
	* win/nmakehlp.c (new):
	* win/rules.vc:  First draft fix for [Bug 527941]. More changes need
	to done to the makehelp target to get to stop leaving build files in
	the tools/ directory. This does not address the syntax errors in the
	man files. Having the contents of tcl.hpj(.in) inside makefile.vc
	allows for version numbers to be replaced with macros.

	The new nmakehlp.c is built by rules.vc in preprocessing and removes
	the need to use tricky shell syntax that wasn't compatible on Win9x
	systems. Clean targets made Win9x complient. This is a first draft
	repair for [Bug 533862].

2002-03-28  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclBasic.c (Tcl_EvalEx): passing the correct commandSize to
	TclEvalObjvInternal. [Bug 219362], fix by David Knoll.

2002-03-28  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclBasic.c (Tcl_EvalEx):
	* tests/basic.test: avoid exceptional returns at level 0. [Bug 219181]

2002-03-27  Don Porter  <dgp@users.sourceforge.net>

	* doc/tcltest.n ([mainThread]):
	* library/tcltest/tcltest.tcl:
	* tests/tcltest.test:  Major code cleanup to deal with whitespace,
	coding conventions, and namespace issues, with several minor bugs
	fixed in the process.

	* tests/main.test: Added missing [after cancel]s.

2002-03-25  Don Porter  <dgp@users.sourceforge.net>

	* tests/main.test: Removed workarounds for Bug 495977.

	* library/tcltest/tcltest.tcl:  Keep the value of $::auto_path
	unchanged, so that the tcltest package can test code that depends on
	auto-loading. If a testing application needs $::auto_path pruned, it
	should do that itself. [Bug 495726]
	Improve the processing of the -constraints option to [test] so that
	constraint lists can have arbitrary whitespace, and non-lists don't
	blow things up. [Bug 495977]
	Corrected faulty variable initialization. [Bug 534845]

2002-03-25  Miguel Sofer  <msofer@users.sourceforge.net>

	* doc/CrtTrace.3: small doc correction
	* generic/tclBasic.c (Tcl_DeleteTrace): Allow NULL callback on trace
	deletions. [Bug 534728] (Hemang Lavana)

2002-03-24  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclBasic.c (Tcl_EvalObjv): replaced obscure, incorrect code
	as described in [Bug 533907] (Don Porter).

2002-03-24  Don Porter  <dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl:  Use [interpreter] to set/query the
	executable currently running the tcltest package. [Bug 454050]

	* library/tcltest/tcltest.tcl:  Allow non-proc commands to be used as
	the customization hooks. [Bug 495662]

2002-03-24  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFilename.c:
	* generic/tclFCmd.c:
	* generic/tclTest.c:
	* generic/tcl.h:
	* generic/tclIOUtil.c:
	* win/tclWinFile.c:
	* win/tclWinFCmd.c:
	* win/tclWinPipe.c:
	* unix/tclUnixFile.c:
	* unix/tclUnixFCmd.c:
	* mac/tclMacFile.c:
	* doc/FileSystem.3:
	* doc/file.n:
	* tests/cmdAH.test:
	* tests/fileName.test:
	* tests/fileSystem.test: (new file)
	* tests/winFCmd.test: fix [Bug 511666] and [Bug 511658], and improved
	documentation of some aspects of the filesystem, particularly
	'Tcl_FSMatchInDirectory' which now might match a single file/directory
	only, and 'file normalize' which wasn't very clear before. Removed
	inconsistency betweens docs and the Tcl_Filesystem structure. Also
	fixed [Bug 523217] and corrected file normalization on Unix so that
	it expands symbolic links. Added some new tests of the filesystem
	code (in the new file 'fileSystem.test'), and some extra tests for
	correct handling of symbolic links. Fix to [Bug 530960] which shows up
	on Win98. Made comparison with ".com" case insensitive in tclWinPipe.c

	***POTENTIAL INCOMPATIBILITY***: But only between alpha releases
	(users of the new Tcl_Filesystem lookup table in Tcl 8.4a4 need to
	handle the new way in which Tcl may call Tcl_FSMatchInDirectory, and
	'file normalize' on unix now behaves correctly). Only known impact is
	with the 'tclvfs' extension.

2002-03-22  Miguel Sofer  <msofer@users.sourceforge.net>

	* tests/basic.test (basic-46.1): adding test for [Bug 533758], fixed
	earlier today.

2002-03-22  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/tclWinInt.h: moved undef of TCL_STORAGE_CLASS. [Bug 478579]

2002-03-22  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclBasic.c (Tcl_EvalObjEx):
	* generic/tclExecute.c (TclCompEvalObj): fixed the errorInfo for
	return codes other than (TCL_OK, TCL_ERROR) to runLevel 0.[Bug 533758]
	Removed the static RecordTracebackInfo(), as its functionality is
	easily replicated by Tcl_LogCommandInfo. Bug and redundancy noted by
	Don Porter.

2002-03-21  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/expr.n: Improved documentation for ceil and floor. [Bug 530535]

2002-03-20  Don Porter  <dgp@users.sourceforge.net>

	* doc/SetVar.3:
	* doc/TraceVar.3:
	* doc/UpVar.3:
	* generic/tcl.h (Tcl_VarTraceProc):
	* generic/tcl.decls (Tcl_GetVar2, Tcl_SetVar2, Tcl_TraceVar2,
	(Tcl_UnsetVar2, Tcl_UntraceVar2, Tcl_UpVar2, Tcl_VarTraceInfo2,
	(Tcl_GetVar2Ex, TclSetVar2Ex):
	* generic/tclCmdMZ.c (TraceVarProc):
	* generic/tclEnv.c (EnvTraceProc):
	* generic/tclEvent.c (VwaitVarProc):
	* generic/tclInt.decls (TclLookupVar,TclPrecTraceProc):
	* generic/tclLink.c (LinkTraceProc):
	* generic/tclUtil.c (TclPrecTraceProc):
	* generic/tclVar.c (CallTraces, MakeUpvar, VarErrMsg, TclLookupVar,
	(Tcl_GetVar2, Tcl_SetVar2, Tcl_TraceVar2, Tcl_UnsetVar2,
	(Tcl_UntraceVar2, Tcl_UpVar2, Tcl_VarTraceInfo2, Tcl_GetVar2Ex,
	(TclSetVar2Ex): Updated interfaces of generic/tclVar.c according to
	TIP 27. In particular, the "part2" arguments were CONSTified. [Patch
	532642]
	* generic/tclDecls.h:
	* generic/tclIntDecls.h: make genstubs

2002-03-15  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/compile.test (compile-12.3): Test to detect bug 530320.
	* generic/tclCompile.c (TclCompileTokens): Fixed buffer overrun
	reported in bug 530320.

2002-03-14  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/configure: Regen.
	* win/configure.in: Add configure time test for SEH support in the
	compiler.
	* win/tclWin32Dll.c (ESP, EBP, TclpCheckStackSpace,
	(_except_checkstackspace_handler):
	* win/tclWinChan.c (ESP, EBP, Tcl_MakeFileChannel,
	(_except_makefilechannel_handler):
	* win/tclWinFCmd.c (ESP, EBP, DoRenameFile, DoCopyFile,
	(_except_dorenamefile_handler, _except_docopyfile_handler):
	Implement SEH support under gcc using inline asm. Tcl and Tk should
	now compile with Mingw 1.1. [Patch 525746]

2002-03-14  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/tclWinFCmd.c (DoRenameFile, DoCopyFile): Handle an SEH exception
	with EXCEPTION_EXECUTE_HANDLER instead of restarting the faulting
	instruction with EXCEPTION_CONTINUE_EXECUTION. [Bug 466102] provides
	an example of how restarting could send Tcl into an infinite loop.
	[Patch 525746]

2002-03-11  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/tclWinFCmd.c (DoRenameFile, DoCopyFile, DoDeleteFile,
	(DoRemoveJustDirectory): Make sure we don't pass NULL or "" as a path
	name to Win32 API functions since this was crashing under Windows 98.

2002-03-11  Don Porter  <dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl:
	* library/tcltest/pkgIndex.tcl: Bumped tcltest package to 2.0.2.

2002-03-11  Mo DeJong  <mdejong@users.sourceforge.net>

	* library/tcltest/tcltest.tcl (getMatchingFiles): Pass a proper list
	to foreach to avoid munging a Windows patch like D:\Foo\Bar into
	D:FooBar before the glob.

2002-03-11  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tclEncoding.c: Fix typo in comment.
	* generic/tclIO.c (DoReadChars, ReadBytes, ReadChars): Use NULL value
	instead of pointer set to NULL to make things more clear. Reorder
	arguments so that they match the function signatures. Cleanup little
	typos and add more descriptive comment.

2002-03-08  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/README: Update to indicate that Mingw 1.1 is required to build
	Tcl. Add section describing new msys based build process. Update
	Cygwin build instructions so users know where to find Mingw 1.1.

2002-03-08  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/tclWinFCmd.c (DoCopyFile): correctly set retval to TCL_OK.

2002-03-07  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/tclWin32Dll.c (TclpCheckStackSpace):
	* win/tclWinFCmd.c (DoRenameFile, DoCopyFile): Replace hard coded
	constants with Win32 symbolic names. Move control flow statements out
	of __try blocks since the documentation indicates it is frowned upon.

2002-03-07  Don Porter  <dgp@users.sourceforge.net>

	* doc/interp.n:
	* generic/tclInterp.c (Tcl_InterpObjCmd, SlaveObjCmd,
	(SlaveRecursionLimit):
	* generic/tclTest.c:
	* tests/interp.test: Added the [interp recursionlimit] command to
	set/query the recursion limit of an interpreter. Proposal and
	implementation from Stephen Trier. [TIP 87, Patch 522849]

2002-03-06  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tcl.h, tools/tcl.wse.in, unix/configure.in,
	* unix/tcl.spec, win/README.binary, win/configure.in, README:
	Bumped patchlevel; this might need to change in the future, but it
	will help us distinguish between the CVS version and the most recent
	released version.

2002-03-06  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclInt.h: for unshared objects, TclDecrRefCount now frees
	the internal rep before the string rep - just like the non-macro
	Tcl_DecrRefCount/TclFreeObj. [Bug 524802]

2002-03-06  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/lsearch.n: Documentation of new features, plus examples.
	* tests/lsearch.test: Tests of new features.
	* generic/tclCmdIL.c (Tcl_LsearchObjCmd): TIP#80 support. See
	http://purl.org/tcl/tip/80 for details.

2002-03-05  Jeff Hobbs  <jeffh@ActiveState.com>

	*** 8.4a4 TAGGED FOR RELEASE ***

	* unix/tclUnixChan.c: initial remedy for [Bug 525783] flush problem
	introduced by TIP #35. This may not satisfy true serial channels, but
	it restores the correct flushing of std* channels on exit.

	* unix/README: added --enable-langinfo doc.

	* unix/tcl.spec:
	* tools/tcl.wse.in: fixed URL refs to use www.tcl.tk or SF.

2002-03-04  Jeff Hobbs  <jeffh@ActiveState.com>

	* README:
	* mac/README:
	* unix/Makefile.in:
	* unix/README:
	* win/README:
	* win/README.binary: updated to use www.tcl.tk URL.

	* unix/Makefile.in: added older ChangeLogs to dist target.

	* tests/io.test:
	* tests/encoding.test: corrected iso2022 encoding results.
	added encoding-24.*
	* generic/tclEncoding.c (EscapeFromUtfProc): corrected output of
	escape codes as per RFC 1468. [Patch 474358] (taguchi)
	(TclFinalizeEncodingSubsystem): corrected potential double-free
	when encodings were finalized on exit. [Bugs 219314, 524674]

2002-03-01  Jeff Hobbs  <jeffh@ActiveState.com>

	* library/encoding/iso2022-jp.enc:
	* library/encoding/iso2022.enc:
	* tools/encoding/iso2022-jp.esc:
	* tools/encoding/iso2022.esc: gave <ESC>$B precedence over <ESC>$@,
	based on comments (point 1) in [Bug 219283] (rfc 1468)

	* tests/encoding.test: added encoding-23.* tests
	* generic/tclIO.c (FilterInputBytes): reset the TCL_ENCODING_START
	flags in the ChannelState when using 'gets'. [Bug 523988]
	Also reduced the value of ENCODING_LINESIZE from 30 to 20 as this
	seems to improve the performance of 'gets' according to tclbench.

2002-02-28  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclCmdMZ.c (TraceCommandProc): ensure that TraceCommandInfo
	structure was also deleted when a command was deleted to prevent a
	mem leak.

	* generic/tclBasic.c (Tcl_CreateObjTrace): set tracePtr->flags
	correctly.

	* generic/tclTimer.c (TimerExitProc): remove remaining events in
	tls on thread exit.

2002-02-28  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclNamesp.c: allow cached fully-qualified namespace names to
	be usable from different namespaces within the same interpreter
	without forcing a new lookup [Patch 458872].

2002-02-28  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclExecute.c: Replaced a few direct stack accesses with the
	POP_OBJECT() macro [Bug 507181] (Don Porter).

2002-02-27  Don Porter  <dgp@users.sourceforge.net>

	* doc/GetIndex.3:
	* generic/tcl.decls (Tcl_GetIndexFromObjStruct):
	* generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct):  Revised the
	prototype of the Tcl_GetIndexFromObjStruct to take its struct table as
	a (CONST VOID *) argument, better describing what it is, maintaining
	source compatibility, and adding CONST correctness according to TIP
	27. Thanks to Joe English for an elegant solution. [Bug 520304]

	* generic/tclDecls.h: make genstubs

	* generic/tclMain.c (Tcl_Main,StdinProc):  Corrected some reference
	count management errors on the interactive command Tcl_Obj found by
	Purify. Thanks to Jeff Hobbs for the report and assistance.

2002-02-27  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclBasic.c (Tcl_EvalTokensStandard): corrected mem leak in
	error case.

	* generic/tclTest.c (TestStatProc[123]): correct harmless UMRs.

	* generic/tclLink.c (Tcl_LinkVar): correct mem leak in error case.

2002-02-27  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* tests/socket.test (2.7): Accepted and applied patch for [Bug 523470]
	provided by Don Porter <dgp@users.sourceforge.net> to avoid timing
	problems in that test.

	* unix/tclUnixChan.c (TclpOpenFileChannel): Added code to regonize
	"/dev/tty" (by name) and to not handle it as tty / serial line. This
	is the controlling terminal and is special. Setting it into raw mode
	as is done for other tty's is a bad idea. This is a hackish fix for
	expect [Bug 520624]. The fix has limitation: Tcl_MakeFileChannel
	handles tty's specially too, but is unable to recognize /dev/tty as it
	only gets a file descriptor, and no name for it.

2002-02-26  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclCmdAH.c (StoreStatData): corrected mem leak.

	* generic/tclCmdMZ.c (Tcl_RegsubObjCmd): prevent obj leak in
	remedial regsub case.

	* generic/tclFileName.c (Tcl_TranslateFileName): decr refcount for
	error case to prevent mem leak.

	* generic/tclVar.c (Tcl_ArrayObjCmd): removed extra obj allocation.

	* unix/tclUnixSock.c (Tcl_GetHostName): added an extra
	gethostbyname check to guard against failure with truncated
	names returned by uname.

	* unix/configure:
	* unix/tcl.m4 (SC_SERIAL_PORT): added sys/modem.h check and defined
	_XOPEN_SOURCE_EXTENDED for HP-11 to get updated header decls.

	* unix/tclUnixChan.c: added Unix implementation of TIP #35, serial
	port support. [Patch 438509] (schroedter)

2002-02-26  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclCmpCmds.c: (bugfix to the bugfix, hopefully the last)
	Bugfix to the new [for] compiling code: was setting a exceptArray
	parameter using another param which wasn't yet initialised, thus
	filling it with noise.

2002-02-25  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* mac/tclMacSock.c (TcpGetOptionProc): Changed to recognize the option
	"-error". Essentially ignores the option, always returning an empty
	string.

2002-02-25  Jeff Hobbs  <jeffh@ActiveState.com>

	* doc/Alloc.3:
	* doc/LinkVar.3:
	* doc/ObjectType.3:
	* doc/PkgRequire.3:
	* doc/Preserve.3:
	* doc/TCL_MEM_DEBUG.3: Updated documentation to describe the ckalloc,
	ckfree, ckrealloc, attemptckalloc, and attemptckrealloc macros, and
	to accurately describe when and how they are used. [Bug 497459] (dgp)

	* generic/tclHash.c (AllocArrayEntry, AllocStringEntry):
	Before invoking ckalloc when creating a Tcl_HashEntry,
	check that the amount of memory being allocated is
	at least as large as sizeof(Tcl_HashEntry). The previous
	code was allocating memory regions that were one
	or two bytes short. [Bug 521950] (dejong)

2002-02-25  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclBasic.c (Tcl_EvalEx): avoiding a buffer overrun
	reported by Joe English, and restoring tcl7.6 behaviour for
	[subst]: badly terminated nested scripts will raise an error
	and not be evaluated. [Bug 495207]

2002-02-25  Don Porter  <dgp@users.sourceforge.net>

	* unix/tclUnixPort.h: corrected strtoll prototype mismatch on Tru64.
	* compat/strtod.c (strtod): simplified #includes
	* compat/strtol.c (strtol): gather result in a long before returning
	as a long: necessary on platforms where sizeof(int) != sizeof(long).

2002-02-25  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tclLoadDyld.c: updated to use Mac OS X 10.1 dyld APIs that
	have more libdl-like semantics. [Bug 514392]

2002-02-25  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclCompCmds: fixing a bug in patch dated 2002-02-22, in the
	code for [for] and [while]. Under certain conditions, for long bodies,
	the exception range parameters were badly computed. Tests forthcoming:
	I still can't reproduce the conditions in the testsuite (!), although
	the bug (with assorted segfault or panic!)  can be triggered from the
	console or with the new parse.bench in tclbench.

2002-02-25  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* compat/strtoul.c, compat/strtol.c, compat/strtod.c: Added UCHAR,
	CONST and #includes to clean up GCC output.

2002-02-23  Don Porter  <dgp@users.sourceforge.net>

	* compat/strtoull.c (strtoull):
	* compat/strtoll.c (strtoll):
	* compat/strtoul.c (strtoul): Fixed failure to handle leading
	sign symbols '+' and '-' and '0X' and raise overflow errors.
	[Bug 440916]  Also corrects prototype and errno problems.

2002-02-23  Mo DeJong  <mdejong@users.sourceforge.net>

	* configure: Regen.
	* unix/tcl.m4 (SC_CONFIG_CFLAGS): Link with -n32 instead of -32 when
	building on IRIX64-6.* system. [Bug 521707]

2002-02-22  Don Porter <dgp@users.sourceforge.net>

	* generic/tclInt.h:
	* generic/tclObj.c: renamed global variable emptyString ->
	tclEmptyString because it is no longer static.
	* generic/tclPkg.c: Fix for panic when library is loaded on a
	platform without backlinking without proper use of stubs. [Bug 476537]

2002-02-22  Jeff Hobbs  <jeffh@ActiveState.com>

	* tests/regexpComp.test: updated regexp-11.[1-4] to match changes in
	regexp.test for new regsub syntax

	* unix/configure:
	* unix/tcl.m4: added --enable-64bit support for AIX-4 (using -q64
	flag) when using IBM's xlc compiler.

	* tests/safe.test: updated safe-8.5 and safe-8.7
	* library/safe.tcl (CheckFileName): removed the limit on
	sourceable file names (was only *.tcl or tclIndex files with no more
	than one dot and 14 chars). There is enough internal protection in a
	safe interpreter already. [Tk Bug 521560]

2002-02-22  Miguel Sofer  <msofer@users.sourceforge.net>

	* generic/tclCompCmds: [FR 465811]. Optimising [if], [for] and [while]
	for constant conditions; in addition, [for] and [while] are now
	compiled with the "loop rotation" optimisation (thanks to Kevin
	Kenny).

2002-02-22  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	--- TIP#76 CHANGES ---
	* generic/tclCmdMZ.c (Tcl_RegsubObjCmd): Final-argument-less
	[regsub] returns the modified string.
	* doc/regsub.n: Updated docs.
	* tests/regexp.test: Updated and added tests.

	* compat/strtoll.c (strtoll):
	* compat/strtoull.c (strtoull):
	* unix/tclUnixPort.h:
	* win/tclWinPort.h: Const-ing 64-bit compatibility declarations. Note
	that the return pointer is non-const because it is entirely legal for
	the functions to be called from somewhere that owns the string being
	passed. Fixes problem reported by Larry Virden.

2002-02-21  David Gravereaux <davygrvy@pobox.com>

	* win/mkd.bat (removed):
	* win/coffbase.txt (new):
	* win/makefile.bc:
	* win/makefile.vc:  Changed the 'setup' target to stop using the
	mkd.bat file and just make the directory right in the rule. Same
	change to makefile.bc. Neither configure.in nor Makefile.in use it.

	coffbase.txt will be the master list for our "prefered base addresses"
	set by the linker. This should improve load-time (NT only) by avoiding
	relocations. Submissions to the list by extension authors are
	encouraged.

	Added a 'tidy' target to compliment 'clean' and 'hose' to remove just
	the outputs. Also removed the $(winlibs) macro as it wasn't being
	used.

	Stuff left to do:
	1) get the winhelp target to stop building in the tools/ directory.
	2) stop using rmd.bat
	3) add more dependacy rules.

	* win/tclAppInit.c:  Reverted back to -r1.6, as the header file change
	to tclPort.h won't allow for easy embedded support outside of the
	source dist. Thanks to Don Porter for pointing this out to me.

2002-02-21  David Gravereaux <davygrvy@pobox.com>

	* win/makefile.vc:
	* win/rules.vc:  Added a new "loimpact" option that sets the
	-ws:aggressive linker option. Off by default. It's said to keep the
	heap use low at the expense of alloc speed.

	* win/tclAppInit.c: Changed #include "tcl.h" to be tclPort.h to remove
	the raw windows.h include. tclPort.h brings in windows.h already and
	lessens the pre-compiled-header mush and the randomly useless #pragma
	comment (lib,...) references throughout the big windows.h tree (as
	observed at high linker warning levels).

2002-02-21  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tcl.h: Better guessing of LP64/ILP32 architecture, but now
	sensitive to presence of (suitable) <limits.h>

2002-02-20  Don Porter <dgp@users.sourceforge.net>

	* generic/tcl.decls (Tcl_RegExpRange,Tcl_GetIndexFromObjStruct):
	Overlooked a few source incompatibilities. Now using CONST84.
	* generic/tclDecls.h: make genstubs
	* generic/tcl.h (Tcl_CmdObjTraceProc): silence warning from Sun
	Workshop compiler.

2002-02-20  David Gravereaux <davygrvy@pobox.com>

	* win/buildall.vc.bat:
	* win/makefile.vc:
	* win/rules.vc: General clean-ups. Added compiler and linker tests for
	a) the pentium 0x0F errata, b) optimizing (not all have this), and c)
	linker v6 section alignment confusion. All these are tested first to
	make sure any D4002 or LNK1117 warnings aren't displayed. The pentium
	0x0F errata is a recommended switch. The v5 linker's section alignment
	default is 512, but the v6 linker was changed to 4096 in an attempt to
	speed loading on Win98. I changed the default to always be 512 across
	both linkers, unless linking statically, then 4096 is used for the
	claimed speed effect. Using a 512 alignment saves 12k bytes of dead
	space in the DLL.

	Added IA64 B-stepping errata switch when the compiler supports it.

	Added profiling to $(lflags) when requested and also removed the
	explict -entry option as the default works fine as is.

	Removed win/tclWinInit.c from the special case section to let it use
	the common implicit rule as the $(EXTFLAGS) macro it had was never
	referenced anywhere.

2002-02-20  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tcl.h: Added code to guess the correct settings for
	TCL_WIDE_INT_IS_LONG and TCL_WIDE_INT_TYPE when configure doesn't tell
	us them, as can happen with extensions.

2002-02-19  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/format.n: Updated docs to list the specification.
	* generic/tclCmdAH.c (Tcl_FormatObjCmd): Made behaviour on 64-bit
	platforms correctly meet the specification, that %d works with the
	native word-sized integer, instead of trying to guess (wrongly)
	from the value being passed.

2002-02-19  Don Porter <dgp@users.sourceforge.net>

	* changes: First draft of updated changes for 8.4a4 release.

2002-02-15  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/tclUnixPort.h: add strtoll/strtoull declarations for
	platforms that do not define them.

	* generic/tclIndexObj.c (STRING_AT): removed ptrdiff_t cast and
	use of VOID* in default case (GNU-ism).

2002-02-15  Kevin Kenny  <kennykb@acm.org>

	* compat/strtoll.c:
	* compat/strtoul.c:
	* compat/strtoull.c:
	* generic/tclIOUtil.c:
	* generic/tclPosixStr.c:
	* generic/tclTest.c:
	* generic/tclTestObj.c:
	* tests/get.test:
	* win/Makefile.vc: Further tweaks to the TIP 72 patch to make it
	compile under VC++.

2002-02-15  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* tclExecute.c:
	* tclIOGT.c:
	* tclIndexObj.c: Touchups to the TIP 72 patch to make it compileable
	under Windows again. The changes are not complete, there is one nasty
	regarding _stati64

2002-02-15  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	+----------------------+
	| TIP #72 IMPLEMENTED. |
	+----------------------+

	There are a lot of changes from this TIP, so please see
	http://purl.org/tcl/tip/72.html for discussion of
	backward-compatibility issues, but the main ones modifications are in:

	* generic/tcl.h: New types.
	* generic/tcl.decls: New public functions.
	* generic/tclExecute.c: 64-bit aware bytecode engine.
	* generic/tclBinary.c: 64-bit handling in [binary] command.
	* generic/tclScan.c: 64-bit handling in [scan] command.
	* generic/tclCmdAH.c: 64-bit handling in [file] and [format]
	commands.
	* generic/tclBasic.c: New "wordSize" entry in ::tcl_platform.
	* generic/tclFCmd.c: Large-file support (with many consequences.)
	* generic/tclIO.c: Large-file support (with many consequences.)
	* compat/strtoll.c, compat/strtoull.c: New support functions.
	* unix/tcl.m4, unix/configure: 64-bit support and greatly enhanced
	cacheing.

	Most other changes, including all those in doc/* and test/* as well as
	the majority in the platform directories, follow on from these.

	Also coming out of the woodwork:
	* generic/tclIndex.c: Better support for Cray PVP.
	* win/tclWinMtherr.c: Better Borland support.

	Note that, in a number of places through the Unix part of the platform
	support, there are Tcl_Platform* references. These are expanded into
	the correct way to call that particular underlying function, i.e. with
	or without a '64' suffix, and should be used by people working on the
	core in preference to the API functions they overlay so that the code
	remains portable depending on the presence or absence of 64-bit
	support on the underlying platform.

	***POTENTIAL INCOMPATIBILITY***: Extracted from the TIP

	SUMMARY OF INCOMPATIBILITIES AND FIXES
	======================================

	The behaviour of expressions containing constants that appear positive
	but which have a negative internal representation will change, as
	these will now usually be interpreted as wide integers. This is always
	fixable by replacing the constant with int(constant).

	Extensions creating new channel types will need to be altered as
	different types are now in use in those areas. The change to the
	declaration of Tcl_FSStat and Tcl_FSLstat (which are the new preferred
	API in any case) are less serious as no non-alpha releases have been
	made yet with those API functions.

	Scripts that are lax about the use of the l modifier in format and
	scan will probably need to be rewritten. This should be very uncommon
	though as previously it had absolutely no effect.

	Extensions that create new math functions that take more than one
	argument will need to be recompiled (the size of Tcl_Value changes),
	and functions that accept arguments of any type (TCL_EITHER) will need
	to be rewritten to handle wide integer values. (I do not expect this
	to affect many extensions at all.)

2002-02-14  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* generic/tclIOCmd.c (Tcl_GetsObjCmd): Trivial fix for [Bug 517503], a
	memory leak reported by Miguel Sofer <msofer@users.sf.net>. The leak
	happens if an error occurs for "set var [gets $chan]" and leak one
	empty object.

2002-02-12  David Gravereaux <davygrvy@pobox.com>

	* djgpp/ (new directory)
	* djgpp/Makefile (new):
	* unix/tclAppInit.c:
	* unix/tclMtherr.c:
	* unix/tclUnixFCmd.c:
	* unix/tclUnixFile.c:
	* unix/tclUnixInit.c:
	* unix/tclUnixPort.h:  Early stage of DJGPP support for building Tcl
	on DOS. Dynamic loading isn't working, yet. Requires watt32 for the
	TCP/IP stack. No autoconf, yet. Barely tested, but makes a working exe
	that runs Tcl in protected-mode, flat memory. [exec] and pipes will
	need the most work as multi-tasking on DOS has to be carefully.

2002-02-10  Kevin Kenny  <kennykb@acm.org>

	* doc/CrtObjCmd.3:
	* doc/CrtTrace.3:
	* generic/tcl.decls:
	* generic/tcl.h:
	* generic/tclBasic.c:
	* generic/tclInt.h:
	* generic/tclTest.c:
	* tests/basic.test: Added Tcl_CreateObjTrace,
	Tcl_GetCommandInfoFromToken and Tcl_SetCommandInfoFromToken.
	(TIPs #32 and #79.)

	* generic/tclDecls.h:
	* generic/tclStubInit.c: Regenerated Stubs tables.

2002-02-08  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/configure:
	* unix/tcl.m4: added -pthread for FreeBSD to EXTRA_CFLAGS and
	LDFLAGS. Also triggered nodots only for FreeBSD-3. Added
	AC_DEFINE(_POSIX_PTHREAD_SEMANTICS) for Solaris.

	* unix/tclUnixPort.h:
	* unix/tclUnixThrd.c: added thread-safe versions of readdir,
	localtime, gmtime and inet_ntoa for threaded build. (jgdavidson)

	* generic/tclScan.c (Tcl_ScanObjCmd): prevented ckfree being called on
	a pointer to NULL.

2002-02-07  Don Porter <dgp@users.sourceforge.net>

	* doc/DString.3:
	* doc/Encoding.3:
	* doc/GetCwd.3:
	* doc/SplitPath.3:
	* doc/Translate.3:
	* doc/Utf.3:
	* generic/tcl.decls:
	* generic/tcl.h:
	* generic/tclEncoding.c:
	* generic/tclEnv.c:
	* generic/tclFileName.c:
	* generic/tclIOUtil.c:
	* generic/tclUtf.c:
	* generic/tclUtil.c:
	* mac/tclMacInit.c:
	* unix/tclUnixFile.c:
	* unix/tclUnixInit.c:
	* unix/tclUnixPipe.c:
	* win/tclWin32Dll.c:
	* win/tclWinFCmd.c:
	* win/tclWinFile.c:
	* win/tclWinInit.c: Partial TIP 27 rollback. Following routines
	restored to return (char *): Tcl_DStringAppend,
	Tcl_DStringAppendElement, Tcl_JoinPath, Tcl_TranslateFileName,
	Tcl_ExternalToUtfDString, Tcl_UtfToExternalDString,
	Tcl_UniCharToUtfDString, Tcl_GetCwd, Tcl_WinTCharToUtf. Also restored
	Tcl_WinUtfToTChar to return (TCHAR *) and Tcl_UtfToUniCharDString to
	return (Tcl_UniChar *). Modified some callers. This change recognizes
	that Tcl_DStrings are de-facto white-box objects.

	* generic/tclDecls.h:
	* generic/tclPlatDecls.h: make genstubs

	* generic/tclCmdMZ.c: corrected use of C++-style comment.

2002-02-06  Jeff Hobbs  <jeffh@ActiveState.com>

	* tests/scan.test:
	* generic/tclScan.c (Tcl_ScanObjCmd): corrected scan 0x... %x handling
	that didn't accept the 0x as a prelude to a base 16 number. [Bug
	495213]

	* generic/tclCompCmds.c (TclCompileRegexpCmd): made early check for
	bad RE to stop checking further.

	* generic/tclCmdMZ.c (Tcl_RegsubObjCmd): added special case to search
	for simple 'string map' style regsub calls. Delayed creation of
	resultPtr object until an initial match is made, as the input string
	object can then be reused for no matches.
	(Tcl_StringObjCmd): optimization improvements to the STR_MAP
	algorithm for zero-length and nocase cases.

	* tests/regexp.test:
	* tests/regexpComp.test: extra code coverage tests.

	* tests/string.test: added 10.18 and 10.19 extra tests.

	* generic/regc_locale.c (casecmp): slight performance improvement.

2002-02-05  Don Porter <dgp@users.sourceforge.net>

	* library/http/http.tcl:
	* library/http/pkgIndex.tcl:  Corrected use of http::error when
	::error was intended. Bump to http 2.4.2.

2002-02-04  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* unix/tclUnixChan.c (FileOutputProc): Fixed [bug 465765] reported by
	Dale Talcott <daletalcott@users.sourceforge.net>. Avoid writing
	nothing into a file as STREAM based implementations will consider this
	a EOF (if the file is a pipe). Not done in the generic layer as this
	type of writing is actually useful to check the state of a socket.

	* doc/open.n: Fixed [Bug 511540], added cross-reference to 'pid' as
	the command to use to retrieve the pid of a command pipeline created
	via 'open'.

2002-02-01  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclCmdMZ.c (Tcl_RegexpObjCmd): handle quirky about case
	earlier to avoid shimmering problem.

2002-02-01  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* tests/io.test: io-39.22 split into two tests, one platform
	dependent, the other not. -eofchar is not empty on the windows
	platform.

2002-02-01  Vince Darley <vincentdarley@users.sourceforge.net>

	* generic/tclTest.c: fix to picky windows compiler problem with the
	'MainLoop' function declaration.

2002-01-31  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* win/tclWinFCmd.c: TIP 27: Applied patch fixing CONST warnings on
	behalf of Don Porter <dgp@users.sourceforge.net>.

2002-01-30  Don Porter <dgp@users.sourceforge.net>

	* generic/tcl.decls:
	* generic/tcl.h:
	* generic/tclInt.h: For each interface identified in the TIP 27
	changes below as a POTENTIAL INCOMPATIBILITY, the source of the
	incompatibility has been parameterized so that it can be removed. When
	compiling extension code against the Tcl header files, use the
	compiler flag -DUSE_NON_CONST to remove the irresolvable source
	incompatibilities introduced by the TIP 27 changes. Resolvable changes
	are left for extension authors to resolve.
	* generic/tclDecls.h: make genstubs

2002-01-30  Vince Darley <vincentdarley@users.sourceforge.net>

	* doc/FileSystem.3: added documentation for 3 public functions which
	had been overlooked. [Bug 507701]
	* unix/mkLinks: make mklinks

2002-01-29  Jeff Hobbs  <jeffh@ActiveState.com>

	* tests/regexpComp.test:
	* generic/tclCompCmds.c (TclCompileRegexpCmd): enhanced to support
	-nocase and -- options.

2002-01-28  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/tcl.m4 (SC_LOAD_TCLCONFIG):
	* win/tcl.m4 (SC_LOAD_TCLCONFIG): Set TCL_LIB_SPEC, TCL_STUB_LIB_SPEC,
	and TCL_STUB_LIB_PATH to the values of TCL_BUILD_LIB_SPEC,
	TCL_BUILD_STUB_LIB_SPEC, and TCL_BUILD_STUB_LIB_PATH when tclConfig.sh
	is loaded from the build directory. A Tcl extension should make use of
	the non-build versions of these variables since they will work in both
	cases. This modification was described in TIP 34.

2002-01-28  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/tclWinReg.c (regConnectRegistryProc,RecursiveDeleteKey)
	(DeleteKey,GetKeyNames,GetType,GetValue,OpenSubKey,SetValue):
	redid the CONSTification as previous changes caused failing tests.

	* tests/regexpComp.test (new):
	* generic/tclInt.h:
	* generic/tclBasic.c: added TclCompileRegexpCmd entry
	* generic/tclCompCmds.c (TclCompileStringCmd): corrected to return
	TCL_OUT_LINE_COMPILE instead of TCL_ERROR for parsing errors, so
	it only throws the error for runtime compile, in case the user
	modifies 'string'.
	(TclCompileRegexpCmd): first try at a byte-compiled regexp command. It
	handles static strings and ^$ bounded static strings.
	(TclCompileAppendCmd): made TclPushVarName call always use
	TCL_CREATE_VAR as numWords is always > 2 at that point.

	* generic/tclExecute.c (TclExecuteByteCode:INST_LIST): correct
	possibly dangerous decr in macro call.

	* win/tclWinInit.c (TclpFindVariable): CONSTification touch-up

	* win/tclWinReg.c (OpenSubKey): corrected bug introduced in
	CONSTification that dropped pointer reference.

	* ChangeLog.2000 (new file):
	* ChangeLog: broke changes from 2000 into ChangeLog.2000 to reduce
	size of the main ChangeLog.

2002-01-28  David Gravereaux <davygrvy@pobox.com>

	* generic/tclPlatDecls.h:  Added preprocessor logic to force a
	typedef of TCHAR when __STDC__ is defined when using the uncommon
	-Za compiler switch with the microsoft compiler.

2002-01-27  Don Porter <dgp@users.sourceforge.net>

	* doc/package.n: Documented global namespace context for script
	evaluation by [package require].

2002-01-27  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclInt.decls:
	* generic/tclIntPlatDecls.h:
	* mac/tclMacChan.c:
	* mac/tclMacFCmd.c:
	* mac/tclMacFile.c:
	* mac/tclMacInit.c:
	* mac/tclMacLoad.c:
	* mac/tclMacResource.c:
	* mac/tclMacSock.c: TIP 27 CONSTification induced changes

	* tests/event.test:
	* tests/main.test: added catches/constraints to test that
	use features that don't exist on the mac.

2002-01-25  Mo DeJong  <mdejong@users.sourceforge.net>

	Make -eofchar and -translation options read only for server sockets.
	[Bug 496733]

	* generic/tclIO.c (Tcl_GetChannelOption, Tcl_SetChannelOption):
	Instead of returning nothing for the -translation option on a server
	socket, always return "auto". Return the empty string enclosed in
	quotes for the -eofchar option on a server socket. Fixup -eofchar
	usage message so that it matches the implementation.
	* tests/io.test: Add -eofchar tests and -translation tests to ensure
	options are read only on server sockets.
	* tests/socket.test: Update tests to account for -eofchar and
	-translation option changes.

2002-01-25  Don Porter <dgp@users.sourceforge.net>

	* compat/strstr.c (strstr):
	* generic/tclCmdAH.c (Tcl_FormatObjCmd):
	* generic/tclCmdIL.c (InfoNameOfExecutableCmd):
	* generic/tclEnv.c (ReplaceString):
	* generic/tclFileName.c (ExtractWinRoot):
	* generic/tclIO.c (FlushChannel,Tcl_BadChannelOption):
	* generic/tclStringObj.c (AppendUnicodeToUtfRep):
	* generic/tclThreadTest.c (TclCreateThread):
	* generic/tclUtf.c (Tcl_UtfPrev):
	* mac/tclMacFCmd.c (TclpObjListVolumes):
	* mac/tclMacResource.c (TclMacRegisterResourceFork,
	(BuildResourceForkList):
	* win/tclWinInit.c (AppendEnvironment):  Sought out and eliminated
	instances of CONST-casting that are no longer needed after the
	TIP 27 effort.

	* Following is [Patch 501006]
	* generic/tclInt.decls (Tcl_AddInterpResolvers, Tcl_Export,
	(Tcl_FindNamespace, Tcl_GetInterpResolvers, Tcl_ForgetImport,
	(Tcl_Import, Tcl_RemoveInterpResolvers):
	* generic/tclNamesp.c (Tcl_Export, Tcl_Import, Tcl_ForgetImport,
	(Tcl_FindNamespace):
	* generic/tclResolve.c (Tcl_AddInterpResolvers,Tcl_GetInterpResolvers,
	(Tcl_RemoveInterpResolvers): Updated APIs in generic/tclResolve.c and
	generic/tclNamesp.c according to the guidelines of TIP 27.
	* generic/tclIntDecls.h: make genstubs

	* Following is [Patch 505630]
	* doc/AddErrorInfo.3:
	* generic/tcl.decls (Tcl_LogCommandInfo):
	* generic/tclBasic.c (Tcl_LogCommandInfo): Updated interfaces
	of generic/tclBasic.cc according to TIP 27.
	* generic/tclDecls.h: make genstubs

	* Following is [Patch 506818]
	* doc/Hash.3:
	* generic/tcl.decls (Tcl_HashStats):
	* generic/tclHash.c (Tcl_HashStats):  Updated APIs of generic/tclHash.c
	according to guidelines of TIP 27.
	* generic/tclDecls.h: make genstubs
	* generic/tclVar.c (Tcl_ArrayObjCmd): Updated callers.

	* Following is [Patch 506807]
	* doc/ObjectType.3:
	* generic/tcl.decls (Tcl_GetObjType):
	* generic/tclObj.c (Tcl_GetObjType): Updated APIs of generic/tclObj.c
	according to guidelines of TIP 27.
	* generic/tclDecls.h: make genstubs

	* Following is [Patch 507304]
	* doc/Encoding.3:
	* generic/tcl.decls (Tcl_WinUtfToTChar,Tcl_WinTCharToUtf):
	* win/tclWin32Dll.c (Tcl_WinUtfToTChar,Tcl_WinTCharToUtf):
	Updated interfaces in win/tclWin32Dll.c according to TIP 27.
	* generic/tclPlatDecls.h: make genstubs
	* generic/tclIOUtil.c (TclpNativeToNormalized):
	* win/tclWinFCmd.c (TclpObjNormalizePath):
	* win/tclWinFile.c (TclpFindExecutable,TclpMatchInDirectory,
	(NativeIsExec,NativeStat):
	* win/tclWinLoad.c (TclpLoadFile):
	* win/tclWinPipe.c (TclpOpenFile,ApplicationType):
	* win/tclWinReg.c (regConnectRegistryProc,RecursiveDeleteKey,DeleteKey,
	(GetKeyNames,GetType,GetValue,OpenSubKey,SetValue):
	* win/tclWinSerial.c (SerialSetOptionProc): Update callers.

	* Following is [Patch 505072]
	* doc/Concat.3:
	* doc/Encoding.3:
	* doc/Filesystem.3:
	* doc/Macintosh.3:
	* doc/OpenFileChnl.3
	* doc/SetResult.3:
	* doc/SetVar.3:
	* doc/SplitList.3:
	* doc/SplitPath.3:
	* doc/Translate.3:
	* generic/tcl.h (Tcl_FSMatchInDirectoryProc):
	* generic/tclInt.h (TclpMatchInDirectory):
	* generic/tcl.decls (Tcl_Concat,Tcl_GetStringResult,Tcl_GetVar,
	(Tcl_GetVar2,Tcl_JoinPath,Tcl_Merge,Tcl_OpenCommandChannel,Tcl_SetVar,
	(Tcl_SetVar2,Tcl_SplitList,Tcl_SplitPath,Tcl_TranslateFileName,
	(Tcl_ExternalToUtfDString,Tcl_GetEncodingName,Tcl_UtfToExternalDString,
	(Tcl_GetDefaultEncodingDir,Tcl_SetDefaultEncodingDir,
	(Tcl_FSMatchInDirectory,Tcl_MacEvalResource,Tcl_MacFindResource):
	* generic/tclInt.decls (TclCreatePipeline,TclGetEnv,TclpGetCwd,
	(TclpCreateProcess):
	* mac/tclMacFile.c (TclpGetCwd):
	* generic/tclEncoding.c (Tcl_GetDefaultEncodingDir,
	(Tcl_SetDefaultEncodingDir,Tcl_GetEncodingName,
	(Tcl_ExternalToUtfDString,Tcl_UtfToExternalDString, OpenEncodingFile,
	(LoadEscapeEncoding):
	* generic/tclFileName.c (DoTildeSubst,Tcl_JoinPath,Tcl_SplitPath,
	(Tcl_TranslateFileName):
	* generic/tclIOUtil.c (Tcl_FSMatchInDirectory):
	* generic/tclPipe.c (FileForRedirect,TclCreatePipeline,
	(Tcl_OpenCommandChannel):
	* generic/tclResult.c (Tcl_GetStringResult):
	* generic/tclUtil.c (Tcl_Concat,Tcl_SplitList,Tcl_Merge):
	* generic/tclVar.c (Tcl_GetVar,Tcl_GetVar2,Tcl_SetVar,Tcl_SetVar2):
	* mac/tclMacResource.c (Tcl_MacEvalResource,Tcl_MacFindResource):
	Updated interfaces of generic/tclEncoding, generic/tclFilename.c,
	generic/tclIOUtil.c, generic/tclPipe.c, generic/tclResult.c,
	generic/tclUtil.c, generic/tclVar.c and mac/tclMacResource.c according
	to TIP 27. Tcl_TranslateFileName rewritten as wrapper around VFS-aware
	version.
	***POTENTIAL INCOMPATIBILITY***
	Includes source incompatibilities: argv arguments of Tcl_Concat,
	Tcl_JoinPath, Tcl_OpenCommandChannel, Tcl_Merge; argvPtr arguments of
	Tcl_SplitList and Tcl_SplitPath.
	* generic/tclDecls.h:
	* generic/tclIntDecls.h: make genstubs

	* generic/tclCkalloc.c (MemoryCmd):
	* generic/tclClock.c (FormatClock):
	* generic/tclCmdAH.c (Tcl_CaseObjCmd,Tcl_EncodingObjCmd,Tcl_FileObjCmd):
	* generic/tclCmdIL.c (InfoLibraryCmd,InfoPatchLevelCmd,
	(InfoTclVersionCmd):
	* generic/tclCompCmds.c (TclCompileForeachCmd):
	* generic/tclCompCmds.h (TclCompileForeachCmd):
	* generic/tclCompile.c (TclFindCompiledLocal):
	* generic/tclEnv.c (TclSetupEnv,TclSetEnv,Tcl_PutEnv,TclGetEnv,
	(EnvTraceProc):
	* generic/tclEvent.c (Tcl_BackgroundError):
	* generic/tclIO.c (Tcl_BadChannelOption,Tcl_SetChannelOption):
	* generic/tclIOCmd.c (Tcl_ExecObjCmd,Tcl_OpenObjCmd):
	* generic/tclIOSock.c (TclSockGetPort):
	* generic/tclIOUtil.c (SetFsPathFromAny):
	* generic/tclLink.c (LinkTraceProc):
	* generic/tclMain.c (Tcl_Main):
	* generic/tclNamesp.c (TclTeardownNamespace):
	* generic/tclProc.c (TclCreateProc):
	* generic/tclTest.c (TestregexpObjCmd,TesttranslatefilenameCmd,
	(TestchmodCmd,GetTimesCmd,TestsetCmd,TestOpenFileChannelProc1,
	(TestOpenFileChannelProc2,TestOpenFileChannelProc3,AsyncHandlerProc,
	(TestpanicCmd):
	* generic/tclThreadTest.c (ThreadErrorProc,ThreadEventProc):
	* generic/tclUtil.c (TclPrecTraceProc):
	* mac/tclMacFCmd.c (GetFileSpecs):
	* mac/tclMacFile.c (TclpMatchInDirectory):
	* mac/tclMacInit.c (TclpInitLibraryPath,Tcl_SourceRCFile):
	* mac/tclMacOSA.c (tclOSAStore,tclOSALoad):
	* mac/tclMacResource.c (Tcl_MacEvalResource):
	* unix/tclUnixFCmd.c (TclpObjNormalizePath):
	* unix/tclUnixFile.c (TclpMatchInDirectory,TclpGetUserHome,TclpGetCwd,
	(TclpReadLink):
	* unix/tclUnixInit.c (TclpInitLibraryPath,TclpSetVariables,
	(Tcl_SourceRCFile):
	* unix/tclUnixPipe.c (TclpOpenFile,TclpCreateTempFile,
	(TclpCreateProcess):
	* win/tclWinFile.c (TclpGetCwd,TclpMatchInDirectory):
	* win/tclWinInit.c (TclpInitLibraryPath,Tcl_SourceRCFile,
	(TclpSetVariables):
	* win/tclWinPipe.c (TclpCreateProcess): Updated callers.

2002-01-24  Don Porter <dgp@users.sourceforge.net>

	* generic/tclIOUtil.c (SetFsPathFromAny):  Corrected tilde-substitution
	of pathnames where > 1 separator follows the ~. [Bug 504950]

2002-01-24  Jeff Hobbs  <jeffh@ActiveState.com>

	* library/http/pkgIndex.tcl:
	* library/http/http.tcl: don't add port in default case to handle
	broken servers. http bumped to 2.4.1  [Bug 504508]

2002-01-23  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* unix/mkLinks: Regenerated.
	* doc/CrtChannel.3:
	* doc/ChnlStack.3: Moved documentation for 'Tcl_GetTopChannel' from
	'CrtChannel' to 'ChnlStack'. Added documentation of
	'Tcl_GetStackedChannel'. [Bug 506147] reported by Mark Patton
	<msp@users.sourceforge.net>.

2002-01-23  Don Porter <dgp@users.sourceforge.net>

	* win/tclWinFile.c (NativeAccess,NativeStat,NativeIsExec,
	(TclpGetUserHome):
	* win/tclWinPort.h (TclWinSerialReopen):
	* win/tclWinSerial.c (TclWinSerialReopen):
	* win/tclWinSock.c (Tcl_OpenTcpServer):  Corrections to earlier TIP 27
	changes. Thanks to Andreas Kupries for the feedback.
	* generic/tclPlatDecls.h: make genstubs

	* doc/GetHostName.3:
	* doc/GetOpnFl.3:
	* doc/OpenTcp.3:
	* tcl.decls (Tcl_GetHostName,Tcl_GetOpenFile,Tcl_OpenTcpClient,
	(Tcl_OpenTclServer):
	* mac/tclMacSock.c (CreateSocket,Tcl_OpenTcpClient,Tcl_OpenTcpServer,
	(Tcl_GetHostName,GetHostFromString):
	* unix/tclUnixChan.c (CreateSocket,CreateSocketAddress,
	(Tcl_OpenTcpClient,Tcl_OpenTcpServer,Tcl_GetOpenFile):
	* unix/tclUnixSock.c (Tcl_GetHostName):
	* win/tclWinSock.c (CreateSocket,CreateSocketAddress,
	(Tcl_OpenTcpClient,Tcl_OpenTcpServer,Tcl_GetHostName):
	Updated socket interfaces according to TIP 27.
	* generic/tclCmdIL.c (InfoHostnameCmd): Updated callers.
	* generic/tclDecls.h: make genstubs

2002-01-21  David Gravereaux <davygrvy@pobox.com>

	* generic/tclLoadNone.c: TclpLoadFile() didn't match proto of typedef
	Tcl_FSLoadFileProc. OK'd by vincentdarley. [Patch 502488]

2002-01-21  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* generic/tclIO.c (WriteChars): Fix for [Bug 506297], reported by
	Martin Forssen <ruric@users.sourceforge.net>. The encoding chosen in
	the script exposing the bug writes out three intro characters when
	TCL_ENCODING_START is set, but does not consume any input as
	TCL_ENCODING_END is cleared. As some output was generated the
	enclosing loop calls UtfToExternal again, again with START set. Three
	more characters in the out and still no use of input ... To break this
	infinite loop we remove TCL_ENCODING_START from the set of flags after
	the first call (no condition is required, the later calls remove an
	unset flag, which is a no-op). This causes the subsequent calls to
	UtfToExternal to consume and convert the actual input.

2002-01-21  Don Porter <dgp@users.sourceforge.net>

	* generic/tclTest.c: Converted declarations of TestReport file system
	to more portable form. [Bug 501417]

	* generic/tcl.decls (Tcl_TraceCommand,Tcl_UntraceCommand,
	(Tcl_CommandTraceInfo):
	* generic/tclCmdMZ.c (Tcl_TraceCommand,Tcl_UntraceCommand,
	(Tcl_CommandTraceInfo): Updated APIs in generic/tclCmdMZ.c according
	to the guidelines of TIP 27.
	* generic/tclDecls.h: make genstubs

2002-01-18  Don Porter <dgp@users.sourceforge.net>

	* win/tclWinChan.c:
	* win/tclWinFCmd.c:
	* win/tclWinFile.c: Overlooked callers of Tcl_FSGetNativePath

	* win/tclWinDde.c:
	* win/tclWinReg.c: Overlooked callers of Tcl_GetIndexFromObj

2002-01-18  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclThreadTest.c:
	* mac/tclMacChan.c:
	* mac/tclMacFCmd.c:
	* mac/tclMacFile.c:
	* mac/tclMacLoad.c:
	* mac/tclMacResource.c: TIP 27 CONSTification broke the mac build in a
	number of places.

2002-01-17  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* generic/tclIOCmd.c (Tcl_GetsObjCmd): Fixed [Bug 504642] as reported
	by Brian Griffin <bgriffin@users.sourceforge.net>, using his
	patch. Before the patch the generic I/O layer held an unannounced
	reference to the interp result to store the read line into. This
	unfortunately has disastrous results if the channel driver executes a
	tcl script to perform its operation, this freeing the interp
	result. In that case we are dereferencing essentially a dangling
	reference. It is not truly dangling because the object is in the free
	list, but this only causes us to smash the free list and have the
	error occur later somewhere else. The patch simply creates a new
	object for the line and later sets it into the interp result when we
	are done with reading.

2002-01-16  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/tcl.m4 (SC_LOAD_TCLCONFIG):
	* win/tcl.m4 (SC_LOAD_TCLCONFIG): Subst TCL_DBGX into
	TCL_STUB_LIB_FILE and TCL_STUB_LIB_FLAG variables so that an extension
	does not need to subst TCL_DBGX into its makefile. [Tk Bug 504356]

2002-01-16  Don Porter <dgp@users.sourceforge.net>

	* doc/FileSystem.3:
	* doc/GetCwd.3:
	* doc/GetIndex.3:
	* generic/tcl.decls (Tcl_GetIndexFromObj, Tcl_GetIndexFromObjStruct,
	(Tcl_GetCwd, Tcl_FSFileAttrStrings, Tcl_FSGetNativePath,
	(Tcl_FSGetTranslatedStringPath):
	* generic/tcl.h (Tcl_FSFileAttrStringsProc):
	* generic/tclFCmd.c (TclFileAttrsCmd):
	* generic/tclIOUtil.c (Tcl_GetCwd,NativeFileAttrStrings,
	(Tcl_FSFileAttrStrings,Tcl_FSGetTranslatedStringPath,
	(Tcl_FSGetNativePath):
	* generic/tclIndexObj.c (Tcl_GetIndexFromObj,
	(Tcl_GetIndexFromObjStruct):
	More TIP 27 updates in tclIOUtil.c and tclIndexObj.c that were
	overlooked before. [Patch 504671]
	***POTENTIAL INCOMPATIBILITY***
	Includes a source incompatibility in the tablePtr arguments of the
	Tcl_GetIndexFromObj* routines.
	* generic/tclDecls.h: make genstubs

	* generic/tclBinary.c (Tcl_BinaryObjCmd):
	* generic/tclClock.c (Tcl_ClockObjCmd):
	* generic/tclCmdAH.c (Tcl_EncodingObjCmd, Tcl_FileObjCmd):
	* generic/tclCmdIL.c (Tcl_InfoObjCmd,Tcl_LsearchObjCmd,Tcl_LsortObjCmd):
	* generic/tclCmdMZ.c (Tcl_TraceObjCmd,Tcl_RegexpObjCmd,Tcl_RegsubObjCmd,
	(Tcl_StringObjCmd,Tcl_SubstObjCmd,Tcl_SwitchObjCmd,
	(TclTraceCommandObjCmd,TclTraceVariableObjCmd):
	* generic/tclCompCmds.c (TclCompileStringCmd):
	* generic/tclEvent.c (Tcl_UpdateObjCmd):
	* generic/tclFileName.c (Tcl_GlobObjCmd):
	* generic/tclIO.c (Tcl_FileEventObjCmd):
	* generic/tclIOCmd.c (Tcl_SeekObjCmd,Tcl_ExecObjCmd,Tcl_SocketObjCmd,
	(Tcl_FcopyObjCmd):
	* generic/tclInterp.c (Tcl_InterpObjCmd,SlaveObjCmd):
	* generic/tclNamesp.c (Tcl_NamespaceObjCmd):
	* generic/tclPkg.c (Tcl_PackageObjCmd):
	* generic/tclTest.c (Tcltest_Init,TestencodingObjCmd,TestgetplatformCmd,
	(TestlocaleCmd,TestregexpObjCmd,TestsaveresultCmd,
	(TestGetIndexFromObjStructObjCmd,TestReportFileAttrStrings):
	* generic/tclTestObj.c (TestindexObjCmd,TeststringObjCmd):
	* generic/tclTimer.c (Tcl_AfterObjCmd):
	* generic/tclVar.c (Tcl_ArrayObjCmd):
	* mac/tclMacFCmd.c (SetFileFinderAttributes):
	* unix/tclUnixChan.c (TclpOpenFileChannel):
	* unix/tclUnixFCmd.c (tclpFileAttrStrings):
	* unix/tclUnixFile.c (TclpObjAccess,TclpObjChdir,TclpObjStat,
	(TclpObjLstat):
	* win/tclWinFCmd.c (tclpFileAttrStrings): Updated callers.

	* doc/RegExp.3:
	* doc/Utf.3:
	* generic/tcl.decls:
	* generic/tclInt.decls:
	* generic/tclRegexp.c:
	* generic/tclUtf.c:  Updated APIs in generic/tclUtf.c and
	generic/tclRegexp.c according to the guidelines of TIP 27.
	[Patch 471509]

	* generic/regc_locale.c (element,cclass):
	* generic/tclCmdMZ.c (Tcl_StringObjCmd):
	* generic/tclFileName.c (TclpGetNativePathType,SplitMacPath):
	* generic/tclIO.c (ReadChars):
	* mac/tclMacLoad.c (TclpLoadFile):
	* win/tclWinFile.c (TclpGetUserHome): Updated callers.

	* generic/tclDecls.h:
	* generic/tclIntDecls.h: make genstubs

	* doc/ParseCmd.3 (Tcl_ParseVar):
	* generic/tcl.decls (Tcl_ParseVar):
	* generic/tclParse.c (Tcl_ParseVar):
	* generic/tclTest.c (TestparsevarObjCmd): Updated APIs in
	generic/tclParse.c according to the guidelines of TIP 27. Updated
	callers. [Patch 501046]
	* generic/tclDecls.h: make genstubs

	* generic/tcl.decls (Tcl_RecordAndEval):
	* generic/tclDecls.h: make genstubs
	* generic/tclHistory.c (Tcl_RecordAndEval): Updated APIs in
	generic/tclHistory.c according to the guidelines of TIP 27.
	[Patch 504091]

	* doc/CrtSlave.3:
	* generic/tcl.decls (Tcl_CreateAlias, Tcl_CreateAliasObj,
	(Tcl_CreateSlave, Tcl_GetAlias, Tcl_GetAliasObj, Tcl_GetSlave):
	* generic/tclInterp.c (Tcl_CreateAlias, Tcl_CreateAliasObj,
	(Tcl_CreateSlave, Tcl_GetAlias, Tcl_GetAliasObj, Tcl_GetSlave):
	Updated APIs in the file generic/tclInterp.c according to the
	guidelines of TIP 27. [Patch 501371]
	***POTENTIAL INCOMPATIBILITY***
	Includes a source incompatibility in the targetCmdPtr arguments of the
	Tcl_GetAlias* routines.

	* generic/tclDecls.h: make genstubs

2002-01-15  Don Porter <dgp@users.sourceforge.net>

	* doc/SetErrno.3 (Tcl_ErrnoMsg): Corrected documentation for
	Tcl_ErrnoMsg; it takes an integer argument. Thanks to Georgios
	Petasis. [Bug 468183]

	* doc/AddErrInfo.3 (Tcl_PosixError):
	* doc/Eval.3 (Tcl_EvalFile):
	* doc/FileSystem.c (Tcl_FSOpenFileChannel,Tcl_FSOpenFileChannelProc):
	* doc/OpenFileChnl.3 (Tcl_OpenFileChannel):
	* doc/SetErrno.3 (Tcl_ErrnoId,Tcl_ErrnoMsg):
	* doc/Signal.3 (Tcl_SignalId,Tcl_SignalMsg):
	* generic/tcl.decls (Tcl_ErrnoId,TclErrnoMsg,Tcl_EvalFile,
	(Tcl_OpenFileChannel,Tcl_PosixError,Tcl_SignalId,Tcl_SignalMsg,
	(Tcl_FSOpenFileChannel):
	* generic/tcl.h (Tcl_FSOpenFileChannelProc):
	* generic/tclIO.c (FlushChannel):
	* generic/tclIOUtil.c (Tcl_OpenFileChannel,Tcl_EvalFile,TclGetOpenMode,
	(Tcl_PosixError,Tcl_FSOpenFileChannel):
	* generic/tclInt.decls (TclGetOpenMode):
	* generic/tclInt.h (TclOpenFileChannelProc_,TclGetOpenMode,
	(TclpOpenFileChannel):
	* generic/tclPipe.c (TclCleanupChildren):
	* generic/tclPosixStr.c (Tcl_ErrnoId,Tcl_ErrnoMsg,Tcl_SignalId,
	(Tcl_SignalMsg):
	* generic.tclTest.c (PretendTclpOpenFileChannel,
	(TestOpenFileChannelProc1,TestOpenFileChannelProc2,
	(TestOpenFileChannelProc3,TestReportOpenFileChannel):
	* mac/tclMacChan.c (TclpOpenFileChannel):
	* unix/tclUnixChan.c (TclpOpenFileChannel):
	* win/tclWinChan.c (TclpOpenFileChannel): Updated APIs in
	generic/tclIOUtil.c and generic/tclPosixStr.c according to the
	guidelines of TIP 27. Updated callers. [Patch 499196]

	* generic/tclDecls.h:
	* generic/tclIntDecls.h: make genstubs

	* doc/CrtChannel.3:
	* doc/OpenFileChnl.3:
	* generic/tcl.decls:
	* generic/tclIO.h:
	* generic/tclIO.c (DoWrite, Tcl_RegisterChannel, Tcl_GetChannel,
	(Tcl_CreateChannel, Tcl_GetChannelName, CloseChannel, Tcl_Write,
	(Tcl_WriteRaw, Tcl_Ungets, Tcl_BadChannelOption, Tcl_GetChannelOption,
	(Tcl_SetChannelOption, Tcl_GetChannelNamesEx, Tcl_ChannelName):
	Updated APIs in the file generic/tclIO.c according to the guidelines
	of TIP 27. Several minor documentation corrections as well.
	[Patch 503565]
	* generic/tclDecls.h: make genstubs

	* generic/tcl.h (Tcl_DriverOutputProc, Tcl_DriverGetOptionProc,
	(Tcl_DriverSetOptionProc):
	* generic/tclIOGT.c (TransformOutputProc, TransformGetOptionProc,
	(TransformSetOptionProc):
	* mac/tclMacChan.c (FileOutput, StdIOOutput):
	* man/tclMacSock.c (TcpGetOptionProc, TcpOutput):
	* unix/tclUnixChan.c (FileOutputProc, TcpGetOptionProc, TcpOutputProc,
	(TtyGetOptionProc, TtySetOptionProc):
	* unix/tclUnixPipe.c (PipeOuputProc):
	* win/tclWinChan.c (FileOutputProc):
	* win/tclWinConsole.c (ConsleOutputProc):
	* win/tclWinPipe.c (PipeOuputProc):
	* win/tclWinSerial.c (SerialOutputProc, SerialGetOptionProc,
	(SerialSetOptionProc):
	* win/tclWinSock.c (TcpGetOptionProc, TcpOutput): Updated channel
	driver interface according to the guidelines of TIP 27. See also
	[Bug 500348].

	* doc/CrtChannel.3:
	* generic/tcl.h:
	* generic/tclIO.c:
	* generic/tclIO.h:
	* generic/tclInt.h:
	* tools/checkLibraryDoc.tcl:
	Moved Tcl_EolTranslation enum declaration from generic/tcl.h to
	generic/tclInt.h (renamed to TclEolTranslation). It is not used
	anywhere in Tcl's public interface.

2002-01-14  Don Porter <dgp@users.sourceforge.net>

	* doc/GetIndex.3:
	* doc/WrongNumArgs.3:
	* generic/tcl.decls (Tcl_GetIndexFromObj, Tcl_GetIndexFromObjStruct,
	(Tcl_WrongNumArgs):
	* generic/tclIndexObj.c (Tcl_GetIndexFromObj,Tcl_GetIndexFromObjStruct,
	(Tcl_WrongNumArgs): Updated APIs in the file generic/tclIndexObj.c
	according to the guidelines of TIP 27. [Patch 501491]
	* generic/tclDecls.h: make genstubs

2002-01-11  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure: Regen.
	* unix/configure.in:
	* win/configure: Regen.
	* win/configure.in: Use ${libdir} instead of ${exec_prefix}/lib
	to properly support the --libdir option to configure. [Bug 489370]

2002-01-11  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* win/tclWinSerial.c (SerialSetOptionProc): Applied patch for [Bug
	500348] supplied by Rolf Schroedter <schroedter@users.sf.net>. The
	function modified the contents of the the 'value' string and now does
	not do this anymore. This is a followup to the change made on
	2001-12-17.

2002-01-11  David Gravereaux <davygrvy@pobox.com>

	* win/makefile.vc: Removed -GD compiler option. It was intended for
	future use, but MS is again changing the future at their whim. The
	D4002 warning was harmless though, but someone using VC .NET logged it
	as a concern. [Bug 501565]

2002-01-11  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/Makefile.in: Burn Tcl build directory into tcltest executable
	to avoid crashes caused by ld loading a previously installed version
	of the tcl shared library. [Bug 218110]

2002-01-10  Don Porter <dgp@users.sourceforge.net>,
	Kevin Kenny <kennykb@users.sourceforge.net>

	* unix/tclLoadDld.c (TclpLoadFile):  syntax error: unbalanced parens.
	Kevin notes that it's far from clear that this file is ever included
	in an actual build; Linux without dlopen appears to be a nonexistent
	configuration.

2002-01-08  Don Porter <dgp@users.sourceforge.net>,
	Kevin Kenny <kennykb@users.sourceforge.net>

	* doc/StaticPkg.3 (Tcl_StaticPackage):
	* generic/tcl.decls (Tcl_StaticPackage):
	* generic/tclDecls.h (Tcl_StaticPackage):
	* generic/tclInt.decls (TclGuessPackageName):
	* generic/tclInt.h (TclGuessPackageName):
	* generic/tclLoad.c (Tcl_StaticPackage):
	* generic/tclLoadNone.c (TclGuessPackageName):
	* mac/tclMacLoad.c (TclGuessPackageName):
	* unix/tclLoadAout.c (TclGuessPackageName):
	* unix/tclLoadDl.c (TclGuessPackageName):
	* unix/tclLoadDld.c (TclGuessPackageName):
	* unix/tclLoadDyld.c (TclGuessPackageName):
	* unix/tclLoadNext.c (TclGuessPackageName):
	* unix/tclLoadOSF.c (TclGuessPackageName):
	* unix/tclLoadShl.c (TclGuessPackageName):
	* win/tclWinLoad.c (TclGuessPackageName):  Updated APIs in the files
	*/tcl*Load*.c according to the guidelines of TIP 27. [Patch 501096]

2002-01-09  Don Porter <dgp@users.sourceforge.net>

	* generic/tclTest.c (MainLoop):
	* tests/main.test (Tcl_Main-1.{3,4,5,6}):  Corrected some non-portable
	tests from the new Tcl_Main changes. Thanks to Kevin Kenny.

2002-01-07  Don Porter <dgp@users.sourceforge.net>

	* generic/tclEvent.c (TclInExit):
	* generic/tclIOUtil.c (SetFsPathFromAbsoluteNormalized,
	(SetFsPathFromAny,Tcl_FSNewNativePath,DupFsPathInternalRep):
	* generic/tclListObj.c (TclLsetList,TclLsetFlat):  Added some type
	casts to satisfy picky compilers.

	* generic/tclMain.c:  Bug fix: neglected the NULL case in
	TclGetStartupScriptFileName(). Broke Tk/wish.

2002-01-05  Don Porter <dgp@users.sourceforge.net>

	* doc/Tcl_Main.3:
	* generic/tclMain.c:  Substantial rewrite and expanded documentation
	of Tcl_Main to correct a number of bugs and flaws:

	  - Interactive Tcl_Main can now enter a main loop, exit that loop and
	    continue interactive operations. The loop may even exit in the
	    midst of interactive command typing without loss of the partial
	    command. [Bugs 486453, 474131]
	  - Tcl_Main now gracefully handles deletion of its master
	    interpreter.
	  - Interactive Tcl_Main can now operate with non-blocking stdin
	  - Interactive Tcl_Main can now detect EOF on stdin even in
	    mid-command. [Bug 491341]
	  - Added VFS-aware internal routines for managing the startup script
	    selection.
	  - Tcl variable 'tcl_interactive' is now linked to C variable 'tty'
	    so that one can disable/enable interactive prompts at the script
	    level when there is no startup script. This is meant for use by
	    the test suite.
	  - Consistent use of the Tcl libraries standard channels as returned
	    by Tcl_GetStdChannel(); as opposed to the channels named 'stdin',
	    'stdout', and 'stderr' in the master interp, which can be
	    different or unavailable.
	  - Tcl_Main now calls Tcl_Exit() if evaluation of [exit] in the
	    master interpreter returns, assuring Tcl_Main does not return.
	  - Documented Tcl_Main's absence from public stub table
	  - Documented that Tcl_Main does not return.
	  - Documented Tcl variables set by Tcl_Main.
	  - All prompts are done from a single procedure, Prompt.
	  - Use of Tcl_Obj-enabled interfaces everywhere.

	* generic/tclInt.decls (TclGetStartupScriptPath,
	(TclSetStartupScriptPath): New internal VFS-aware routines for
	managing the startup script of Tcl_Main.
	* generic/tclIntDecls.h:
	* generic/tclStubInit.c: make genstubs

	* generic/tclTest.c (TestsetmainloopCmd,TestexitmainloopCmd,
	(Tcltest_Init,TestinterpdeleteCmd):
	* tests/main.test (new):  Added new file to test suite that thoroughly
	tests generic/tclMain.c; added some new test commands for testing
	Tcl_SetMainLoop().

2002-01-04  Don Porter <dgp@users.sourceforge.net>

	* doc/Alloc.3:
	* doc/Concat.3:
	* doc/CrtMathFnc.3:
	* doc/Hash.3:
	* doc/Interp.3:
	* doc/LinkVar.3:
	* doc/ObjectType.3:
	* doc/PkgRequire.3:
	* doc/Preserve.3:
	* doc/SetResult.3:
	* doc/SplitList.3:
	* doc/SplitPath.3:
	* doc/TCL_MEM_DEBUG.3: Updated documentation to describe the ckalloc,
	ckfree, ckrealloc, attemptckalloc, and attemptckrealloc macros, and
	to accurately describe when and how they are used. [Bug 497459]

	* generic/tclThreadJoin.c (TclRememberJoinableThread,TclJoinThread):
	Replaced Tcl_Alloc and Tcl_Free calls with ckalloc and ckfree so that
	memory debugging is supported.

2002-01-04  Daniel Steffen <das@users.sourceforge.net>

	* mac/tclMacTime.c (TclpGetTZName): fix for daylight savings TZName bug

2002-01-03  Don Porter <dgp@users.sourceforge.net>

	* doc/FileSystem.3:
	* generic/tclIOUtil.c: Updated some old uses of "fileName" to
	new VFS terminology, "pathPtr".

2002-01-03  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/basic.test (basic-39.4): Greatly simplified test while
	still leaving it so that it crashes when run without the fix to
	the [foreach] implementation.
	* generic/tclCmdAH.c (Tcl_ForeachObjCmd): Stopped [Bug 494348] from
	happening by not trying to be so clever with cacheing; if nothing
	untoward is happening anyway, the less efficient technique will
	only add a few instruction cycles (one function call and a few
	derefs/assigns per list per iteration, with no change in the
	number of tests) and if something odd *is* going on, the code is
	now far more robust.

	* tests/basic.test (basic-39.4): Reproducable script from [Bug 494348]

2002-01-02  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/util.test (Wrapper_Tcl_StringMatch,util-5.*): Rewrote so the
	test is performed with the right internal function since [string
	match] no longer uses Tcl_StringCaseMatch internally.

	* tests/string.test (string-11.51):
	* generic/tclUtf.c (Tcl_UniCharCaseMatch):
	* generic/tclUtil.c (Tcl_StringCaseMatch): Fault with matching
	case-insensitive non-ASCII patterns containing upper case characters.
	[Bug 233257]

	******************************************************************
	*** CHANGELOG ENTRIES FOR 2001 IN "ChangeLog.2001"             ***
	*** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000"             ***
	*** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" ***
	******************************************************************

Deleted ChangeLog.2003.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
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
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349





















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
2003-12-25  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/tclWin32Dll.c (DllMain): Add HAVE_NO_SEH blocks in place of
	__try and __except statements to support gcc builds. This is needed
	after David's changes on 2003-12-21. [Patch 858493]

2003-12-23  David Gravereaux <davygrvy@pobox.com>

	* generic/tclAlloc.c:	All uses of 'panic' (the macro) changed to
	* generic/tclBasic.c:	'Tcl_Panic' (the function). The #define of
	* generic/tclBinary.c:	panic in tcl.h clearly states it is deprecated
	* generic/tclCkalloc.c:	in the comments. [Patch 865264]
	* generic/tclCmdAH.c:
	* generic/tclCmdIL.c:
	* generic/tclCmdMZ.c:
	* generic/tclCompCmds.c:
	* generic/tclCompExpr.c:
	* generic/tclCompile.c:
	* generic/tclConfig.c:
	* generic/tclDictObj.c:
	* generic/tclEncoding.c:
	* generic/tclEvent.c:
	* generic/tclExecute.c:
	* generic/tclHash.c:
	* generic/tclInterp.c:
	* generic/tclIO.c:
	* generic/tclIOCmd.c:
	* generic/tclIOUtil.c:
	* generic/tclListObj.c:
	* generic/tclLiteral.c:
	* generic/tclNamesp.c:
	* generic/tclObj.c:
	* generic/tclParse.c:
	* generic/tclPathObj.c:
	* generic/tclPkg.c:
	* generic/tclPreserve.c:
	* generic/tclProc.c:
	* generic/tclStringObj.c:
	* generic/tclTest.c:
	* generic/tclThreadAlloc.c:
	* generic/tclTimer.c:
	* generic/tclTrace.c:
	* generic/tclVar.c:
	* mac/tclMacChan.c:
	* mac/tclMacOSA.c:
	* mac/tclMacResource.c:
	* mac/tclMacSock.c
	* mac/tclMacThrd.c:
	* unix/tclUnixChan.c:
	* unix/tclUnixNotfy.c:
	* unix/tclUnixThrd.c:
	* unix/tclXtNotify.c:
	* win/tclWin32Dll.c:
	* win/tclWinChan.c:
	* win/tclWinFCmd.c:
	* win/tclWinNotify.c:
	* win/tclWinPipe.c:
	* win/tclWinSock.c:
	* win/tclWinThrd.c:

	* generic/tclInt.h:  Deprecated use of Tcl_Ckalloc changed to
	Tcl_Alloc in the TclAllocObjStorage macro.

2003-12-22  David Gravereaux <davygrvy@pobox.com>

	* win/nmakehlp.c:
	* win/rules.vc:  New feature for extensions that use rules.vc. Now
	reads header files for version strings. No more hard coding
	TCL_VERSION = 8.5 and having to edit it when you swap cores.

	* win/makefile.vc: VERSION macro now set by reading tcl.h for it.

	* generic/tcl.h: Removed note that makefile.vc needs to have a version
	number changed.

2003-12-21  David Gravereaux <davygrvy@pobox.com>

	* win/tclWin32Dll.c: Structured Exception Handling added around
	Tcl_Finalize called from DllMain's DLL_PROCESS_DETACH. We can't be
	100% assured that Tcl is being unloaded by the OS in a stable
	condition and we need to protect the exit handlers should the stack be
	in a hosed state. AT&T style assembly for SEH under MinGW has not been
	added yet. This is a first part change for [Patch 858493]

2003-12-17  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclBinary.c (DeleteScanNumberCache): fixed crashing bug when
	numeric scan-value cache contains NULL value.

2003-12-17  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclCmdAH.c:
	* unix/tclUnixFile.c:
	* win/tclWinFCmd.c:
	* tests/fCmd.test:
	* tests/fileSystem.test:
	* doc/file.n: final fix to support for relative links and its
	implications on normalization and other parts of the filesystem code.
	Fixes [Bug 859251] and some Windows problems with recursive file
	delete/copy and symbolic links.

2003-12-17  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclPathObj.c:
	* tests/fileSystem.test: fix and tests for [Bug 860402] in new file
	normalization code.

2003-12-17  Zoran Vasiljevic  <zv@archiware.com>

	* generic/tclIOUtil.c: fixed 2 memory (object) leaks. [Bug 839519]

	* generic/tclPathObj.c: fixed Tcl_FSGetTranslatedPath to always return
	properly refcounted path object. [Bug 861515]

2003-12-16  Vince Darley  <vincentdarley@users.sourceforge.net>

	* tests/fCmd.test: marking fCmd-9.14.2, as nonPortable, since on
	Solaris one can change the name of the current directory with 'file
	rename'.
	* doc/FileSystem.3: clarified documentation on ownership of return
	objects/strings of some Tcl_FS* calls.

2003-12-16  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclThreadAlloc.c (binfo): Made variable file-local.

2003-12-15  David Gravereaux <davygrvy@pobox.com>

	* win/tcl.rc:
	* win/tclsh.rc: Slight modification to the STRINGIFY macro to support
	Borland's rc tool.

	* win/tclWinFile.c (TclpUtime) : utimbuf struct not a problem with
	Borland.

	* win/tclWinTime.c (TclpGetDate) : Borland's localtime() has a slight
	behavioral difference.

	From Helmut Giese <hgiese@ratiosoft.com> [Patch 758097].

2003-12-14  David Gravereaux <davygrvy@pobox.com>

	* generic/tclInt.decls: commented-out entry for TclpCheckStackSpace,
	removing it from the Stubs table. It's already declared in tclInt.h
	and labeled as a function that is not to be exported. Regened tables.

2003-12-14  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclCmdMZ.c (Tcl_SwitchObjCmd): TIP#75 Implementation
	* tests/switch.test:	Can now get submatch information when using
	* doc/switch.n:		-regexp matching in [switch].

2003-12-14  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclPathObj.c: complete rewrite of generic file normalization
	code to cope with links followed by '..'. [Bug 849514], and parts of
	[Bug 859251]

2003-12-12  David Gravereaux <davygrvy@pobox.com>

	* win/tclWinChan.c: Win32's SetFilePointer() takes LONGs not DWORDs (a
	signed/unsigned mismatch). Redid local vars to avoid all casting
	except where truly required.

2003-12-12  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclCmdAH.c: fix to normalization of non-existent user name
	('file normalize ~nobody') [Bug 858937]
	* doc/file.n: clarify behaviour of 'file link' when the target is not
	an absolute path.
	* doc/filename.n: correct documentation to say that Windows Tcl does
	handle '~user', for recent Windows releases, and clarified distinction
	between MacOS 'classic' and MacOS X.
	* doc/glob.n: clarification of glob's behaviour when returning
	filenames starting with a '~'.

	* tests/fileSystem.test:
	* tests/fileName.test: new tests added for the normalization problem
	above and other recentlt reported issues.

	* win/tclWinFile.c: corrected unclear comments

	* unix/tclUnixFile.c: allow creation of relative links. [Bug 833713]

2003-12-11  David Gravereaux <davygrvy@pobox.com>

	* win/tclWinSock.c (SocketThreadExitHandler) : added a TerminateThread
	fallback just in case the socket handler thread is really in a paused
	state. This can happen when Tcl is being unloaded by the OS from an
	exception handler. See MSDN docs on DllMain, it states this behavior.

2003-12-09  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/configure:
	* unix/tcl.m4: updated OpenBSD build configuration based on
	[Patch #775246] (cassoff)

2003-12-09  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* unix/tclUnixPort.h:	#ifdef'd out declarations of errno which are
	* tools/man2tcl.c:	known to cause problems with recent glibc.
				[Bug 852369]

2003-12-09  Vince Darley  <vincentdarley@users.sourceforge.net>

	* win/tclWinFile.c: fix to NT file permissions code [Bug 855923]
	* tests/winFile.test: added tests for NT file permissions - patch and
	test scripts supplied by Benny.

	* tests/winFCmd.test: fixed one test for when not running in C:/

2003-12-02  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclBinary.c (DeleteScanNumberCache, ScanNumber): Made the
	numeric scan-value cache have proper references to the objects within
	it so strange patterns of writes won't cause references to freed
	objects. Thanks to Paul Obermeir for the report. [Bug 851747]

2003-12-01  Miguel Sofer <msofer@users.sf.net>

	* doc/lset.n: fix typo [Bug 852224]

2003-11-24  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclParse.c:	Corrected faulty check for trailing white
	space in {expand} parsing. Thanks Andreas Leitgeb. [Bug 848262]
	* tests/parse.test: 	New tests for the bug.

2003-11-24  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclPathObj.c: fix to [Bug 845778] - Infinite recursion on
	[cd] (Windows only bug), for which new tests have just been added.

2003-11-21  Don Porter	<dgp@users.sourceforge.net>

	* tests/winFCmd.test (winFCmd-16.10,11): Merged new tests from
	core-8-4-branch.

2003-11-20  Miguel Sofer <msofer@users.sf.net>

	* generic/tclVar.c: fix flag bit collision between LOOKUP_FOR_UPVAR
	and TCL_PARSE_PART1 (deprecated) [Bug 835020]

2003-11-19  Don Porter	<dgp@users.sourceforge.net>

	* tests/compile.test (compile-16.22.0):	Improved test for the recent
	fix for Bug 845412.

2003-11-19  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclCompile.c (TclCompileScript): Added a guard for the
	expansion code so that long non-expanding commands don't get expansion
	infrastructure inserted in them, especially when that infrastructure
	isn't initialised. [Bug 845412]

2003-11-18  David Gravereaux <davygrvy@pobox.com>

	* contrib/djgpp/Makefile:		Changes from Victor Wagner
	* contrib/djgpp/langinfo.c (new):	<vitus@45.free.net> for better
	* contrib/djgpp/langinfo.h (new):	DJGPP support.
	* unix/tclUnixInit.c:			.
	* unix/tclUnixChan.c:			.
	* unix/tclUnixFCmd.c:			.

2003-11-17  Don Porter	<dgp@users.sourceforge.net>

	* tests/reg.test: Added tests for [Bugs 230589, 504785, 505048, 840258]
	recently fixed by 2003-11-15 commit to regcomp.c by Pavel Goran. His
	notes on the fix: This bug results from an error in code that splits
	states into "progress" and "no-progress" ones. This error causes an
	interesting situation with the pre-collected single-linked list of
	states to be splitted: many items were added to the list, but only
	several of them are accessible from the list beginning, since the
	"tmp" member of struct state (which is used here to hold a pointer to
	the next list item) gets overwritten, which results in a "looped"
	chain. As a result, not all of states are splitted, and one state is
	splitted two times, causing incorrect "no-progress" flag values.

2003-11-16  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclExecute.c (TclExecuteByteCode): Make sure that
	Tcl_AsyncInvoke is called regularly when processing bytecodes.
	* generic/tclTest.c (AsyncThreadProc, TestasyncCmd): Extended testing
	harness to send an asynchronous marking without relying on UNIX
	signals.
	* tests/async.test (async-4.*): Tests to check that async events are
	handled by the bytecode core. [Bug 746722]

2003-11-15  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclTest.c (TestHashSystemHashCmd): Removed 'const' modifier
	from hash type structure; it should be const and the hash code assumes
	it behaves like const, but that's not how the API is defined. Like
	this, we are following in the same footsteps as Tcl_RegisterObjType()
	which has the same conditions on its argument. Stops VC++5.2 warning.
	[Bug 842511]

2003-11-14  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclHash.c (Tcl_DeleteHashTable,Tcl_HashStats,RebuildTable):
	* generic/tclTest.c (TestHashSystemHashCmd): TIP#138 implementation,
	* tests/misc.test:	plus a new chunk of stuff to test the hash
				functions more thoroughly in the test suite.
				[Patch 731356, modified]

	* doc/Tcl.n: Updated Tcl version number and changebars.

2003-11-14  Don Porter	<dgp@users.sourceforge.net>

	* doc/ParseCmd.3:	Implementation of TIP 157.  Adds recognition
	* doc/Tcl.n:		of the new leading {expand} syntax on words.
	* generic/tcl.h:	Parses such words as the new Tcl_Token type
	* generic/tclBasic.c:	TCL_TOKEN_EXPAND_WORD. Updated Tcl_EvalEx and
	* generic/tclCompile.c: the bytecode compiler/execution engine to
	* generic/tclCompile.h:	recognize the new token type. New opcodes
	* generic/tclExecute.c:	INST_LIST_VERIFY and INST_INVOKE_EXP and a new
	* generic/tclParse.c:	operand type OPERAND_ULIST1 are defined. Docs
	* generic/tclTest.c:	and tests are included.
	* tests/basic.test:
	* tests/compile.test:
	* tests/parse.test:

	* library/auto.tcl:	Replaced several [eval]s used to perform
	* library/package.tcl:	argument expansion with the new syntax. In the
	* library/safe.tcl:	test files lindex.test and lset.test, replaced
	* tests/cmdInfo.test:	use of [eval] to force direct string
	* tests/encoding.test:	evaluation with use of [testevalex] which more
	* tests/execute.test:	directly and robustly serves the same purpose.
	* tests/fCmd.test:
	* tests/http.test:
	* tests/init.test:
	* tests/interp.test:
	* tests/io.test:
	* tests/ioUtil.test:
	* tests/iogt.test:
	* tests/lindex.test:
	* tests/lset.test:
	* tests/namespace-old.test:
	* tests/namespace.test:
	* tests/pkg.test:
	* tests/pkgMkIndex.test:
	* tests/proc.test:
	* tests/reg.test:
	* tests/trace.test:
	* tests/upvar.test:
	* tests/winConsole.test:
	* tests/winFCmd.test:

2003-11-12  Jeff Hobbs  <jeffh@ActiveState.com>

	* tests/cmdMZ.test (cmdMZ-1.4): change to nonPortable as more systems
	are using permissions caching, and this isn't really a Tcl controlled
	issue.

2003-11-11  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/configure:
	* unix/tcl.m4: improve AIX --enable-64bit handling
	remove -D__NO_STRING_INLINES -D__NO_MATH_INLINES from CFLAGS_OPTIMIZE
	on Linux. Make default opt -O2 (was -O).

2003-11-11  David Gravereaux <davygrvy@pobox.com>

	* contrib/djgpp/Makefile:  Suggested changes from vitus@45.free.net
	(Victor Wagner)

	* unix/tclUnixPort.h:  added socklen_t typedef for DJGPP

2003-11-10  Don Porter	<dgp@users.sourceforge.net>

	* unix/tclUnixInit.c (TclpInitLibraryPath):
	* win/tclWinInit.c (TclpInitLibraryPath):	Fix for [Bug 832657]
	that should not run afoul of startup constraints.

	* library/dde/pkgIndex.tcl:	Added safeguards so that registry and
	* library/reg/pkgIndex.tcl:	dde packages are not offered on
	* win/tclWinDde.c:		non-Windows platforms. Bumped to
	* win/tclWinReg.c:		registry 1.1.3 and dde 1.3.
	* win/Makefile.in:
	* win/configure.in:
	* win/makefile.bc:
	* win/makefile.vc:

	* win/configure:	autoconf (2.57)

2003-11-10  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tests/cmdIL.test: Stopped cmdIL-5.5 from stomping over the test
	command, and updated the tests to use some tcltest2 features in
	relation to cleanup. [Bug 838384]

2003-11-10  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclCmdAH.c:
	* tests/fCmd.test: fix to misleading error message in 'file link'.
	[Bug 836208]

2003-11-07  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclIOUtil.c: fix to compiler warning/error with some
	compilers. [Bug 835918]

2003-11-07  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Makefile: optimized builds define NDEBUG to turn off
	ThreadAlloc range checking.

2003-11-05  Don Porter	<dgp@users.sourceforge.net>

	* tests/unixInit.test (unixInit-2.10):  New test to expose [Bug 832657]
	failure of TclpInitLibraryPath() to properly handle .. in the path
	of the executable.

2003-11-04  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Makefile: added 'test' target.

2003-11-03  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclIOUtil.c
	* generic/tclInt.h: added comments and re-arranged code to clarify
	distinction between Tcl_LoadHandle, ClientData for 'load'ed code, and
	point out limitations of the design introduced with Tcl 8.4.

	* unix/tclUnixFile.c: fix to memory leak

	* generic/tclCmdIL.c: removed warning on Windows.

2003-11-01  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclCmdIL.c (Tcl_LrepeatObjCmd): Check for sensible list
	lengths and allow for soft failure of the memory subsystem in the
	[lconcat] command [Bug 829027]. Uses direct list creation to avoid
	extra copies when working near the limit of available memory. Also
	reorganized to encourage optimizing compilers to optimize heavily.
	* generic/tclListObj.c (TclNewListObjDirect): New list constructor
	that does not copy the array of objects. Useful for creating
	potentially very large lists or where you are about to throw away the
	array argument which is being used in its entirety.

2003-10-28  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c (NEXT_INST macros): replaced macro variable
	"result" by "resultHandling" to avoid confusion.

2003-10-23  Andreas Kupries  <andreask@activestate.com>

	* unix/tclUnixChan.c (Tcl_MakeFileChannel): Applied [Patch 813606]
	fixing [Bug 813087]. Detection of sockets was off for Mac OS X which
	implements pipes as local sockets. The new code ensures that only IP
	sockets are detected as such.

	* win/tclWinSock.c (TcpWatchProc): Watch for FD_CLOSE too when asked
	for writable events by the generic layer.
	(SocketEventProc): Generate a writable event too when a close is
	detected.

	  Together the changes fix [Bug 599468].

2003-10-23  Vince Darley  <vincentdarley@users.sourceforge.net>

	* tests/resource.test:
	* mac/tclMacResource.c: fix to resource freeing problem in 'resource'
	command reported by Bernard Desgraupes.

	* doc/FileSystem.3: updated documentation for 'glob' fix on 2003-10-13
	below

2003-10-22  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclCmdAH.c (Tcl_FileObjCmd): Changed FILE_ prefix to FCMD_
	to stop symbol/#def clashes on Cygwin/Mingw32 on NT. [Bug 822528]

2003-10-21   Daniel Steffen  <das@users.sourceforge.net>

	* tools/tcltk-man2html.tcl: fixed incorrect html generated for
	.IP/.TP lists, now use <DL><DT>...<DD>...<P><DT>...<DD>...</DL>
	instead of illegal  <DL><P><DT>...<DD>...<P><DT>...<DD>...</DL>.
	Added skipping of directives directly after .TP to avoid them being
	used as item descriptions, e.g. .TP\n.VS in clock.n.

2003-10-21  Andreas Kupries  <andreask@pliers.activestate.com>

	* win/tclWinPipe.c (BuildCommandLine): Applied the patch coming with
	[Bug 805605] to the code, fixing the incorrect use of ispace noted by
	Ronald Dauster <ronaldd@users.sourceforge.net>.

2003-10-20  Kevin B. Kenny  <kennykb@users.sourceforge.net>

	* doc/msgcat.n:
	* library/msgcat/msgcat.tcl (mclocale,mcload):
	* tools/tcl.wse.in:
	* unix/Makefile.in:     Implementation of TIP#156, add a "root locale"
	* win/makefile.bc:      to the 'msgcat' package. Advanced msgcat
	* win/Makefile.in:      version number to 1.4
	* win/Makefile.vc:

2003-10-15  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclCmdIL.c (SortInfo,etc): Reorganized so that SortInfo
	carries an array of integer indices instead of a Tcl list. This nips
	shimmering problems in the bud and simplifies SelectObjFromSublist at
	the cost of making setup slightly more complex. [Bug 823768]

2003-10-14  David Gravereaux <davygrvy@pobox.com>

	* win/tclAppInit.c (sigHandler): Punt gracefully if exitToken has
	already been destroyed.

2003-10-14  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclCmdMZ.c:
	* tests/regexp.test: fix to [Bug 823524] in regsub; added three new
	tests.

2003-10-14  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c (TclAppendObjToErrorInfo):	New internal routine
	that appends a Tcl_Obj to the errorInfo, saving the caller the trouble
	of extracting the string rep.

	* generic/tclStringObj.c (TclAppendLimitedToObj):	New internal
	routine that supports truncated appends with optional ellipsis marking.
	This single routine supports UTF-8-safe truncated appends needed in
	several places throughout the Tcl source code, mostly for error and
	stack messages. Clean fix for [Bug 760872].

	* generic/tclInt.h:	Declarations for new internal routines.

	* generic/tclCmdMZ.c:	Updated callers to use the new routines.
	* generic/tclCompExpr.c:
	* generic/tclCompile.c:
	* generic/tclExecute.c:
	* generic/tclIOUtil.c:
	* generic/tclNamesp.c:
	* generic/tclObj.c:
	* generic/tclParseExpr.c:
	* generic/tclProc.c:
	* generic/tclStringObj.c:
	* mac/tclMacResource.c:

	* library/init.tcl:	Updated ::errorInfo cleanup in [unknown] to
	reflect slight modifications to Tcl_LogCommandInfo(). Corrects failing
	init-4.* tests.

2003-10-14  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	TIP#127 IMPLEMENTATION FROM JOE MICHAEL SCHLENKER

	* generic/tclCmdIL.c (SelectObjFromSublist): Element selection engine.
	* generic/tclCmdIL.c (Tcl_LsearchObjCmd, Tcl_LsortObjCmd):
	* tests/lsearch.test:	Set up and use of element selection engine,
	* tests/cmdIL.test:	plus tests and documentation.
	* doc/lsearch.n:	Based on [Patch 693836]
	* doc/lsort.n:

2003-10-13  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tcl.h:
	* generic/tclFileName.c:
	* generic/tclIOUtil.c:
	* generic/tclPathObj.c:
	* generic/tclTest.c:
	* mac/tclMacFile.c:
	* tests/fileName.test: better tests for [Bug 813273]
	* unix/tclUnixFCmd.c:
	* unix/tclUnixFile.c:
	* win/tclWin32Dll.c:
	* win/tclWinFCmd.c:
	* win/tclWinFile.c:
	* win/tclFileInt.h:

	Fixed [Bug 800106] in which 'glob' was incapable of merging the
	results of a directory listing (real or virtual) and any virtual
	filesystem mountpoints in that directory (the latter were ignored).
	This meant boundaries between different filesystems were not seamless
	(e.g. 'glob */*' across a filesystem boundary was wrong). Added new
	entry to Tcl_GlobTypeData in a totally backwards compatible way. To
	allow listing of mounts, registered filesystems must support the
	'TCL_GLOB_TYPE_MOUNT' flag. If this is not supported (e.g. in tclvfs
	1.2) then mounts will simply not be listed for that filesystem.

	Fixed [Bug 749876] 'file writable/readable/etc' (NativeAccess) using
	correct permission checking code for Windows NT/2000/XP where more
	complex user-based security/access priveleges are available,
	particularly on shared volumes. The performance impact of this extra
	checking will need further investigation. Note: Win 95,98,ME have no
	support for this.

	Also made better use of normalized rather than translated paths in the
	platform specific code.

2003-10-12  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/tclUnixTest.c (TestalarmCmd): don't bother checking return
	value of alarm. [Bug #664755] (english)

2003-10-09  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* win/makefile.vc:  Applied patches for bug #801467 by Joe Mistachkin
	* win/tclAppInit.c: to fix incompatible TCL_MEM_DEBUG handling in
	* generic/tclObj.c: Win32 VC builds.

2003-10-08  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Save and restore the iPtr->flag bits that
	control the state of errorCode and errorInfo management when calling
	"leave" execution traces, so that all error information of the traced
	command is still available whether traced or not. [Bug 760947]
	Thanks to Yahalom Emet.

2003-10-08  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclTest.c (TestNumUtfCharsCmd): Command to allow finer
	access to Tcl_NumUtfChars for testing.
	* generic/tclUtf.c (Tcl_NumUtfChars): Corrected string length
	determining when the length parameter is negative; the terminator is a
	zero byte, not (necessarily) a \u0000 character. [Bug 769812]

2003-10-07  Don Porter	<dgp@users.sourceforge.net>

	* tests/cmdAH.test:
	* tests/exec.test:		Corrected temporary file management
	* tests/fileSystem.test:	issues uncovered by -debug 1 test
	* tests/io.test:		operations. Also backported some
	* tests/ioCmd.test:		other fixes from the HEAD.
	* tests/main.test:
	* tests/pid.test:		[Bugs 675605, 675655, 675659]
	* tests/socket.test:
	* tests/source.test:

	* tests/fCmd.test:	Run tests with the [temporaryDirectory] as the
	current directory, so that tests can depend on ability to write files.
	[Bug 575837]

	* doc/OpenFileChnl.3:	Updated Tcl_Tell and Tcl_Seek documentation to
	reflect that they now return Tcl_WideInt (TIP 72). [Bug 787537]

	* tests/io.test:	Corrected several tests that failed when paths
	* tests/ioCmd.test:	included regexp-special chars. [Bug 775394]

2003-10-06  Jeff Hobbs	<jeffh@ActiveState.com>

	* win/configure:
	* win/tcl.m4: removed incorrect checks for existence of optimization.
	TCL_CFG_OPTIMIZED is now defined whenever the user does not build with
	--enable-symbols.

2003-10-06  Don Porter	<dgp@users.sourceforge.net>

	* tests/regexp.test:		Matched [makeFile] with [removeFile].
	* tests/regexpComp.test:	[Bug 675652]

	* tests/fCmd.test (fCmd-8.2):	Test only that tilde-substitution
	happens, not for any particular result. [Bug 685991]

	* unix/tcl.m4 (SC_PATH_TCLCONFIG):	Corrected search path so that
	alpha and beta releases of Tcl are not favored. [Bug 608698]

	* tests/reg.test:	Corrected duplicate test names.
	* tests/resource.test:	[Bugs 710370, 710358]
	* tests/dict.test:

	* tests/dict.test:	Updated [package require tcltest] lines to
	* tests/fileSystem.test:	indiciate that these test files
	* tests/lrepeat.test:	use features of tcltest 2.  [Bug 706114]
	* tests/notify.test:
	* tests/parseExpr.test:
	* tests/unixNotfy.test:
	* tests/winDde.test:

2003-10-04  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c (TEBC):
	* tests/execute.test (execute-8.2): fix for [Bug 816641] - faulty
	execution and catch stack management.

2003-10-03  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Fixed error in ref count management of command
	* generic/tclCmdMZ.c:	and execution traces that caused access to
	freed memory in trace-32.1. [Bug 811483]

2003-10-02  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclTrace.c: Corrected comingling of introspection results of
	[trace info command] and [trace info execution]. [Bug 807243]
	Thanks to Mark Saye.

2003-10-01  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Makefile: fixed redo prebinding bug when DESTDIR="".
	* mac/tclMacResource.c: fixed possible NULL dereference (bdesgraupes).

2003-09-29  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclPathObj.c:
	* tests/fileName.test: fix to inconsistent handling of backslash
	path separators on Windows in 'file join' [Bug 813273]

2003-09-29  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclPathObj.c (TclNativePathInFilesystem,TclFSGetPathType):
	* generic/tclIOUtil.c (TclNativeDupInternalRep,TclGetPathType): Rename
	to make sure function names won't interfere with other non-Tcl code
	(reported by George Staplin)

	TIP#121 IMPLEMENTATION FROM JOE MISTACHKIN

	* generic/tclEvent.c (Tcl_SetExitProc,Tcl_Exit): Implementation of
	application exit handler scheme.
	* generic/tcl.decls (Tcl_SetExitProc): Public declaration.
	* doc/Exit.3: Documentation of new API function.

	TIP#112 IMPLEMENTATION

	* generic/tclNamesp.c: Core of implementation.
	* generic/tclInt.h (Namespace,TclInvalidateNsCmdLookup): Add command
	list epoch counter and list of ensembles to namespace structure, and
	define a macro to ease update of the epoch counter.
	* generic/tclBasic.c (Tcl_CreateObjCommand,etc.): Update epoch counter
	when list of commands in a namespace changes.
	* generic/tclObj.c (TclInitObjSubsystem): Register ensemble subcommand
	type.
	* tests/namespace.test (42.1-47.6): Tests.
	* doc/namespace.n: Documentation.

	* library/http/http.tcl (geturl): Correctly check the type of
	boolean-valued options. [Bug 811170]

	* unix/tcl.m4 (SC_ENABLE_FRAMEWORK): Added note to make it clearer
	that this is an OSX feature, not a general Unix feature. [Bug 619440]

2003-09-28  David Gravereaux <davygrvy@pobox.com>

	* win/tclWinPipe.c: The windows port of expect can call
	TclWinAddProcess before any of the other pipe functions. Added a
	missing PipeInit() call to make sure the initialization happens.

2003-09-25  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Makefile: ensure SYMROOT exists if OBJROOT is overridden on
	command line. Replaced explict use of /usr/bin by ${BINDIR}.

2003-09-24  Vince Darley  <vincentdarley@users.sourceforge.net>

	* library/package.tcl (tcl::MacPkgUnknown, tcl::MacOSXPkgUnknown):
	Minor performance tweaks to reduce the number of [file] invocations.
	Meant to improve startup times, at least a little bit. (The generic
	equivalent patch was applied on 2003-02-21).

2003-09-24  Vince Darley  <vincentdarley@users.sourceforge.net>

	* trace.test: removed 'knownBug' from a test which doesn't illustrate
	a bug, just a bad test.

2003-09-23  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c:
	* generic/tclInt.h: changed the evaluation-stack addressing mode, from
	array-style to pointer-style; the catch stack and evaluation stack are
	now contiguous in memory. [Patch 457449]

2003-09-23  Don Porter  <dgp@users.sourceforge.net>

	* tests/trace.test (trace-31,32-*):  Added tests for [Bug 807243] and
	[Bug 811483].

	* library/init.tcl (auto_load, auto_import):  Expanded Eric Melski's
	2000-01-28 fix for [Bug 218871] to all potentially troubled uses of
	[info commands] on input data, where glob-special characters could
	cause problems.

2003-09-20  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/expr.test (expr-23.4): Prevented accidental wrapping round of
	exponential operation; it isn't portable, and not what I intended to
	test either. [Bug 808244]

2003-09-19  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c: adding (DE)CACHE_STACK_INFO() pairs to protect
	all calls that may cause traces on ::errorInfo or ::errorCode to
	corrupt the stack. [Bug 804681]

2003-09-17  Vince Darley  <vincentdarley@users.sourceforge.net>

	* tclPathObj.c: fix to test-suite problem introduced by the bug fix
	below. No problem in ordinary code, just test suite code which
	manually adjusts tclPlatform. [Bug 808247]

2003-09-16  Vince Darley  <vincentdarley@users.sourceforge.net>

	* doc/filename.n: documentation of Windows-specific feature as
        discussed in [Bug 541989]
	* generic/tclPathObj.c: fix for normalization of volume-relative paths
	[Bug 767834]
        * tests/winFCmd.test: new tests for both of the above.
	* tests/cmdAH.test: fix for AFS problem in test suite [Bug 748960]

2003-09-13  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	TIP#123 IMPLEMENTATION BASED ON WORK BY ARJEN MARKUS

	* generic/tclCompile.h (INST_EXPON):		Implementation of
	* generic/tclCompile.c (tclInstructionTable):	exponential operator.
	* generic/tclCompExpr.c (operatorTable):
	* generic/tclParseExpr.c (ParseExponentialExpr, GetLexeme):
	* generic/tclExecute.c (TclExecuteByteCode, ExponWide, ExponLong):
	(IllegalExprOperandType):
	* tests/expr.test:
	* tests/compExpr-old.test:
	* doc/expr.n:

2003-09-10  Don Porter  <dgp@users.sourceforge.net>

	* library/opt/optparse.tcl:	Latest revisions caused [OptGuessType]
	to guess "int" instead of "string" for empty strings. Missed the
	required "-strict" option to [string is]. Thanks to Revar Desmera.
	[Bug 803968]

2003-09-08  David Gravereaux <davygrvy@pobox.com>

	* win/tclWinLoad.c (TclpDlopen): Changed the error message for
	ERROR_PROC_NOT_FOUND to be a bit more helpful in giving us clues.
	"can't find specified procedure" means a function in the import table,
	for implicit loading, couldn't be resolved and that's why the load
	failed.

2003-09-04  Don Porter  <dgp@users.sourceforge.net>

	* doc/Tcl_Main.3:
	* doc/FileSystem.3:				Implementation of
	* doc/source.n:					TIPs 137/151. Adds a
	* doc/tclsh.1:					-encoding option to
	* generic/tcl.decls:				the [source] command
	* generic/tclCmdMZ.c (Tcl_SourceObjCmd):	and a new C routine,
	* generic/tclIOUtil.c (Tcl_FSEvalFileEx):	Tcl_FSEvalFileEx(),
	* generic/tclMain.c (Tcl_Main):			that provides C access
	* mac/tclMacResource.c (Tcl_MacSourceObjCmd):	to the same function.
	* tests/cmdMZ.test:				Also adds command line
	* tests/main.test:	option handling in Tcl_Main() so that tclsh
	* tests/source.test:	and other apps built on Tcl_Main() respect a
	-encoding command line option before a script filename. Docs and tests
	updated as well. [Patch 742683]
	This is a ***POTENTIAL INCOMPATIBILITY*** only for those C programs
	that embed Tcl, build on Tcl_Main(), and make use of Tcl_Main's former
	ability to pass a leading "-encoding" option to interactive shell
	operations.

	* generic/tclInt.decls:				Added internal stub
	* generic/tclMain.c (Tcl*StartupScript*):	table entries for two
	new functions Tcl_SetStartupScript() and Tcl_GetStartupScript() that
	set/get the path and encoding for the startup script to be evaluated
	by either Tcl_Main() or Tk_Main(). Given public names in anticipation
	of their exposure by a followup TIP.

	* generic/tclDecls.h:		make genstubs
	* generic/tclIntDecls.h:
	* generic/tclStubInit.c:

2003-09-04  Don Porter  <dgp@users.sourceforge.net>

	* doc/SplitList.3:	Implementation of TIP 148.  Fixes [Bug 489537].
	* generic/tcl.h:	Updated Tcl_ConvertCountedElement() to quote
	* generic/tclUtil.c:	the leading "#" character of all list elements
	unless the TCL_DONT_QUOTE_HASH flag is passed in.

	* generic/tclDictObj.c:	Updated Tcl_ConvertCountedElement() callers
	* generic/tclListObj.c:	to pass in the TCL_DONT_QUOTE_HASH flags
	* generic/tclResult.c:	when appropriate.

2003-08-31  Don Porter  <dgp@users.sourceforge.net>

	* doc/return.n:	Updated [return] docs to cover new TIP 90 features.

	* doc/break.n:		Added SEE ALSO references to return.n
	* doc/continue.n:

2003-09-01  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/Namespace.3: Basic documentation for the TIP#139 functions. This
	will need improving, but the basic bits are there at least.

2003-08-31  Don Porter  <dgp@users.sourceforge.net>

	* doc/catch.n:	Updated [catch] docs to cover new TIP 90 features.

2003-08-29  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCmdAH.c:	Corrected bug in TIP 90 implementation where
	* tests/cmdMZ.test:	the default -errorcode NONE value was not
	copied into the return options dictionary. This correction modified
	one test result.

2003-08-27  David Gravereaux <davygrvy@pobox.com>

	* compat/strftime.c (_fmt): Removed syst array intializer that
	couldn't take variables within it under the watcom compiler:
	'Initializers must be constant'. I believe Borland has this strictness
	as well. VC++ must be non-standard about this.

	Changed Win32 platform #ifdef from 'WIN32' to '__WIN32__' as this is
	the correct one to use across the Tcl sources. Even though we do force
	it in tcl.h, the true parent one is __WIN32__.

	Added missing CONST'ification usage to match prototype listed in
	tclInt.decls.

	* win/tclWinPort.h:  Added a block for OpenWatcom adjustments that
	fixes 1) the same issue Mo did for MinGW lack of missing LPFN_*
	typedefs in their WINE derived <winsock2.h> and 2) The need to be
	strict about how the char type needs to be signed by default.

	* win/tclWinSock.c:  Added OpenWatcom to the commentary about the
	#ifdef HAVE_NO_LPFN_DECLS block.

	* win/tclWinTime.c:  Changed use of '_timezone' to 'timezone' as this
	difference is already adjusted for in tclWinPort.h. Removed
	unreferenced posixEpoch file-scope global.

	* win/tclWinFile.c (WinReadLinkDirectory): Fix for 'Initializers must
	be constant' with the driveSpec array using OpenWatcom.

2003-08-27  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclUtil.c:	Corrected [Bug 411825] and other bugs in
	TclNeedSpace() where non-breaking space (\u00A0) and backslash-escaped
	spaces were handled incorrectly.
	* tests/util.test:	Added new tests util-8.[2-6].

2003-08-26  David Gravereaux <davygrvy@pobox.com>

	* generic/tcl.h: Added some support for the LCC-Win32 compiler.
	Unfortunetly, this compiler has a bug in its preprocessor and can't
	build Tcl even with this minor patch. Also added some support for the
	OpenWatcom compiler. A new win/makefile.wc to follow soon.

2003-08-25  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tools/genStubs.tcl (genStubs::makeDecl): A more subtle way of
	generating stubbed declarations allows us to have declarations of a
	function in multiple interfaces simultaneously.

	* generic/tcl.decls: Duplicated some namespace declarations from
	tclInt.decls here, as mandated by TIP #139. This is OK since the
	declarations match and will end up using the declarations in the
	public code from now on because of #include ordering. Keeping the old
	declarations in tclInt.decls; there's no need to gratuitously break
	compatibility for those extensions which are already clients of the
	namespace code.

2003-08-23  Zoran Vasiljevic  <zoran@archiwrae.com>

	* generic/tclIOUtil.c: merged fixes for thread-unsafe handling of
	filesystem records [Bug 753315]. This also fixed the [Bug 788780]
	* generic/tclPathObj.c: merged fixes for thread-unsafe handling of
	filesystem records. [Bug 753315]

	* generic/tclFileSystem.h: merged fixes for thread-unsafe handling of
	filesystem records. [Bug 753315]

2003-08-19  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* win/tclWinSerial.c (SerialErrorStr): Fixed a syntax error created in
	the previous code cleanup.

2003-08-19  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* win/tclWinSerial.c: Adjusted commenting and spacing usage to follow
	the principles of the Style Guide better.

2003-08-18  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/configure: Regen.
	* win/tcl.m4 (SC_ENABLE_SYMBOLS): Use test instead of -eq, which does
	not work. [Bug 781109]

2003-08-13  Chengye Mao <chengye.geo@yahoo.com>

	* win/tclWinPipe.c: fixed a bug in BuildCommandLine. This bug built a
	command line with a missing space between tclpipe.dll and the
	following arguments. It caused error in Windows 98 when exec
	command.com (e.g. dir). [Bug 789040]

2003-08-11  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	TIP #136 IMPLEMENTATION from Simon Geard <simon.geard@ntlworld.com>
	* generic/tclCmdIL.c (Tcl_LrepeatObjCmd): Adapted version of Simon's
	* doc/lrepeat.n:			  patch, updated to the HEAD
	* tests/lrepeat.test:			  and matching the core style.
	* generic/tclBasic.c (buildIntCmds):	Splice into core.
	* generic/tclInt.h:
	* doc/list.n:				Cross-reference.

2003-08-06  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/tclWinInit.c: recognize amd64 and ia32_on_win64 cpus.

2003-08-06  Don Porter  <dgp@users.sourceforge.net>

	* library/msgcat/msgcat.tcl:	Added escape so that non-Windows
	* library/msgcat/pkgIndex.tcl:	platforms do not try to use the
	registry package. This can save a costly and pointless package search.
	Bumped to 1.3.1. Thanks to Dave Bodenstab. [Bug 781609]

2003-08-05  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c (INST_INVOKE, INST_EVAL, INST_PUSH_RESULT):
	added a Tcl_ResetResult(interp) at each point where the interp's
	result is pushed onto the stack, to avoid keeping an extra reference
	that may cause costly Tcl_Obj duplication. Detected by Franco Violi,
	analyzed by Peter Spjuth and Donal Fellows. [Bug 781585]

2003-07-28  Vince Darley  <vincentdarley@users.sourceforge.net>

	* doc/FileSystem.3:
	* doc/Translate.3: better documentation of Tcl_TranslateFileName and
	related functions. [Bug 775220]

2003-07-24  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tcl.h: Revert change made on 2003-07-21 since it made the
	sizeof(Tcl_Obj) different for regular vs mem debug builds.
	* generic/tclInt.h: Define TclDecrRefCount in terms of
	Tcl_DbDecrRefCount which removes one layer of inderection.
	* generic/tclObj.c (TclDbInitNewObj, Tcl_DbIncrRefCount,
	(Tcl_DbDecrRefCount, Tcl_DbIsShared): Define ThreadSpecificData that
	contains a hashtable. The table is used to ensure that a Tcl_Obj is
	only acted upon in the thread that allocated it. This checking code is
	enabled only when mem debug and threads are enabled.

2003-07-24  Don Porter  <dgp@users.sourceforge.net>

	* tests/async.test:	Added several tests that demonstrate [Bug
	* tests/basic.test:	489537], Tcl's longstanding failure to
	* tests/dict.test:	properly quote any leading '#' character when
	* tests/dstring.test:	generating the string rep of a list so that
	* tests/list.test:	the comment-power of that character is hidden
	* tests/parse.test:	from any [eval], in order to satisfy the
	* tests/util.test:	documentation that [list] does [eval]-safe
				quoting.

2003-07-24  Reinhard Max  <max@suse.de>

	* library/package.tcl: Fixed a typo that broke pkg_mkIndex -verbose.
	* tests/pkgMkIndex.test: Added a test for [pkg_mkIndex -verbose].

	* ChangeLog.2002 (new file):
	* ChangeLog: broke changes from 2002 into ChangeLog.2002 to reduce
	size of the main ChangeLog.

2003-07-23  Daniel Steffen  <das@users.sourceforge.net>

	* unix/Makefile.in: changes to html-tcl & html-tk targets for
	compatibility with non-gnu makes.

	* unix/Makefile.in: added macosx/README to dist target.

2003-07-23  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* win/tclWinReg.c (OpenSubKey): Fixed bug 775976 which causes the
	registry set command to fail when built with VC7.
	* library/reg/pkgIndex.tcl: Incremented the version to 1.1.2.

2003-07-21  Mo DeJong  <mdejong@users.sourceforge.net>

	Check that the thread incrementing or decrementing the ref count of a
	Tcl_Obj is the thread that originally allocated the thread. This fail
	fast behavior will catch programming errors that allow a single
	Tcl_Obj to be accessed from multiple threads.

	* generic/tcl.h (Tcl_Obj): Add allocThread member to Tcl_Obj. This
	member records the thread id the Tcl_Obj was allocated. It is used to
	check that any future ref count incr or decr is done from the same
	thread that allocated the Tcl_Obj. This member is defined only when
	threads and mem debug are enabled.
	* generic/tclInt.h (TclNewObj, TclDbNewObj, TclDecrRefCount):
	Define TclNewObj and TclDbNewObj using TclDbInitNewObj when mem debug
	is enabled. This fixes a problem where TclNewObj calls did not work
	the same as TclDbNewObj when mem debug was enabled.
	* generic/tclObj.c (TclDbInitNewObj, Tcl_DbIncrRefCount,
	(Tcl_DbDecrRefCount): Add new helper to init Tcl_Obj members when mem
	debug is enabled. Init the allocThread member in TclDbInitNewObj and
	check it in Tcl_DbIncrRefCount and Tcl_DbDecrRefCount to make sure a
	Tcl_Obj allocated in one thread is not being acted upon in another
	thread.

2003-07-21  Vince Darley  <vincentdarley@users.sourceforge.net>

	* test/cmdAH.test: ensure certain tests run in local filesystem. [Bug
	748960]

2003-07-18  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Makefile: added option to allow installing manpages in
	addition to default html help.

2003-07-18  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/Utf.3: Tightened up documentation of Tcl_UtfNext and Tcl_UtfPrev
	to better match the behaviour. [Bug 769895]

2003-07-18  Jeff Hobbs  <jeffh@ActiveState.com>

	* library/http/pkgIndex.tcl: upped to http v2.4.4
	* library/http/http.tcl: add support for user:pass info in URL.
	* tests/http.test:       [Bug 759888] (shiobara)

2003-07-18  Don Porter  <dgp@users.sourceforge.net>

	* doc/tcltest.n:                Restored the [Eval] proc to replace
	* library/tcltest/tcltest.tcl:  the [::puts] command when either the
	-output or -error option for [test] is in use, in order to capture
	data written to the output or error channels for comparison against
	what is expected.  This is easier to document and agrees better with
	most user expectations than the previous attempt to replace [puts]
	only in the caller's namespace.  Documentation made more precise on
	the subject.  [Bug 706359]

	* doc/AddErrInfo.3:	Improved consistency of documentation by
	* doc/CrtTrace.3:      	using "null" everywhere to refer to the
	* doc/Encoding.3:      	character '\0', and using "NULL" everywhere
	* doc/Eval.3:          	to refer to the value of a pointer that points
	* doc/GetIndex.3:      	to nowhere. Also dropped references to ASCII
	* doc/Hash.3:          	that are no longer true, and standardized on
	* doc/LinkVar.3:       	the hyphenated spelling of "null-terminated".
	* doc/Macintosh.3:
	* doc/OpenFileChnl.3:
	* doc/SetVar.3:
	* doc/StringObj.3:
	* doc/Utf.3:

	* doc/CrtSlave.3 (Tcl_MakeSafe):  Removed warning about possible
	deprecation (no TIP on that).

2003-07-17  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tclUnixFCmd.c: fix for compilation errors on platforms where
	configure detects non-functional chflags(). [Bug 748946]

	* macosx/Makefile: Rewrote buildsystem for Mac OS X framework build
	to be purely make driven; in order to become independent of Apple's
	closed-source IDE and build tool. The changes are intended to be
	transparent to the Makefile user, all existing make targets and cmd
	line variable overrides should continue to work. Changed build to only
	include tcl specific html help in Tcl.framework, the tk specific html
	help is now included in Tk.framework. Added var to allow overriding of
	tclsh used during html help building (Landon Fuller).

	* macosx/Tcl.pbproj/project.pbxproj:
	* macosx/Tcl.pbproj/jingham.pbxuser: Changed to purely call through to
	the make driven buildsystem; Tcl.framework is no longer assembled by
	ProjectBuilder.
	Set default SYMROOT in target options to simplify setting up PB
	(manually setting common build folder for tcl & tk no longer needed).

	* tools/tcltk-man2html.tcl: Added options to allow building only the
	tcl or tk html help files; the default behaviour with none of the new
	options is to build both, as before.

	* unix/Makefile.in: Added targets for building only the tcl or tk help

	* macosx/README (new): Tcl specific excerpts of tk/macosx/README.

	* generic/tcl.h: Updated reminder comment about editing
	macosx/Tcl.pbproj/project.pbxproj when version number changes.

2003-07-16  Mumit Khan  <khan@nanotech.wisc.edu>

	* generic/tclPathObj.c (SetFsPathFromAny): Add Cygwin specific code to
	convert POSIX filename to native format.
	* generic/tclFileName.c (Tcl_TranslateFileName): And remove from here.
	(TclDoGlob): Adjust for cygwin and append / for dirs instead of \
	* win/tclWinFile.c (TclpObjChdir): Use chdir on Cygwin.
	[Patch 679315]

2003-07-16  Jeff Hobbs  <jeffh@ActiveState.com>

	* library/safe.tcl (FileInAccessPath): normalize paths before
	comparison. [Bug 759607] (myers)

	* unix/tclUnixNotfy.c (NotifierThreadProc): correct size of found and
	word vars from int to long. [Bug 767578] (hgo)

	* generic/tcl.h:       Add recognition of -DTCL_UTF_MAX=6 on the make
	* generic/regcustom.h: line to support UCS-4 mode. No config arg at
	this time, as it is not the recommended build mode.

	* generic/tclPreserve.c: In Result and Preserve'd routines, do not
	* generic/tclUtil.c:     assume that ckfree == free, as that is not
	* generic/tclResult.c:   always true. [Bug 756791] (fuller)

2003-07-16  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/CrtSlave.3 (Tcl_MakeSafe): Updated documentation to strongly
	discourage use. IMHO code outside the core that uses this function is
	a bug... [Bug 655300]

2003-07-16  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclFileName.c (Tcl_GlobObjCmd):	[Bug 771840]
	* generic/tclPathObj.c (Tcl_FSConvertToPathType):[Bug 771947]
	* unix/tclUnixFCmd.c (GetModeFromPermString):	[Bug 771949]
	Silence compiler warnings about unreached lines.

	* library/tcltest/tcltest.tcl (ProcessFlags):	Corrected broken call
	* library/tcltest/pkgIndex.tcl:			to [lrange]. Bumped to
	version 2.2.4. [Bug 772333]

2003-07-15  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/dltest/pkga.c (Pkga_EqObjCmd): Fix typo that was causing a
	crash in load.test.

2003-07-15  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/array.n: Make sure docs are synched with the 8.4 release.

2003-07-15  Don Porter  <dgp@users.sourceforge.net>

	* doc/http.n:  Updated SYNOPSIS to match actual syntax of commands.
	[Bug 756112]

	* unix/dltest/pkga.c:	Updated to not use Tcl_UtfNcmp and counted
	strings instead of strcmp (not defined in any #include'd header) and
	presumed NULL-terminated strings.

	* generic/tclCompCmds.c (TclCompileIfCmd):  Prior fix of Bug 711371 on
	2003-04-07 introduced a buffer overflow. Corrected. [Bug 771613]

2003-07-15  Kevin B. Kenny  <kennykb@acm.org>

	* win/rules.vc: Added a missing $(OPTDEFINES) which broke the build if
	STATS=memdbg was specified.

2003-07-15  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclCmdIL.c (SortCompare): Cleared up confusing error
	message. [Bug 771539]

2003-07-11  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/binary.test (binary-46.*): Tests to help enforce the current
	behaviour.
	* doc/binary.n: Documented that [binary format a] and [binary scan a]
	do encoding conversion by dropping high bytes, unlike the rest of the
	core. [Bug 735364]

2003-07-11  Don Porter  <dgp@users.sourceforge.net>

	* library/package.tcl:  Corrected [pkg_mkIndex] bug reported on
	comp.lang.tcl. The indexer was searching for newly indexed packages
	instead of newly provided packages.

2003-07-08  Vince Darley  <vincentdarley@users.sourceforge.net>

	* tests/winFCmd.test: fix for five tests under win98 [Bug 767679]

2003-07-07  Jeff Hobbs  <jeffh@ActiveState.com>

	* doc/array.n: add examples from Welton

2003-06-23  Vince Darley  <vincentdarley@users.sourceforge.net>

	* doc/file.n: clarification of 'file tail' behaviour [Bug 737977]

2003-07-04  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/expr.n: Tighten up the wording of some operations. [Bug 758488]

	* tests/cmdAH.test: Made tests of [file mtime] work better on FAT
	filesystems. [Patch 760768]  Also a little general cleanup.

	* generic/tclCmdMZ.c (Tcl_StringObjCmd): Made [string map] accept
	dictionaries for maps.  This is much trickier than it looks, since map
	entry ordering is significant. [Bug 759936]

	* generic/tclVar.c (Tcl_ArrayObjCmd, TclArraySet): Made [array get]
	and [array set] work with dictionaries, producing them and consuming
	them. Note that for compatibility reasons, you will never get a dict
	from feeding a string literal to [array set] since that alters the
	trace behaviour of "multi-key" sets. [Bug 759935]

2003-06-23  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclTrace.c: fix to Window debug build compilation error.

2003-06-27  Don Porter  <dgp@users.sourceforge.net>

	* tests/init.test: Added [cleanupTests] to report results of tests
	* tests/pkg.test:  that run in slave interps.  [Bugs 761334,761344]

	* tests/http.test: Used more reliable path to find httpd script.

2003-06-25  Don Porter  <dgp@users.sourceforge.net>

	* tests/init.test:  Added tests init-4.6.* to illustrate [Bug 760872]

2003-06-25  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclTrace.c: New file, factoring out of virtually all the
	various trace-related things from tclBasic.c and tclCmdMZ.c with the
	goal of making this a separate maintenance area.

2003-06-25  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure: Regen.
	* unix/tcl.m4 (SC_CONFIG_CFLAGS): Add -ieee when compiling with cc and
	add -mieee when compiling with gcc under OSF1-V5 "Tru64" systems. [Bug
	748957]

2003-06-24  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/encoding.n: Corrected the docs to say that [source] uses the
	system encoding, which it always did anyway (since 8.1) [Bug 742100]

2003-06-24  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclHash.c (Tcl_HashStats): Prevented occurrence of
	division-by-zero problems.  [Bug 759749]

2003-06-24  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/tclUnixPort.h: #undef inet_ntoa before #define to avoid
	compiler warning under freebsd. [Bug 745844]

2003-06-23  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* doc/dde.n:                 Committed TIP #135 which changes the
	* win/tclWinDde.c:           -exact option to -force. Also cleaned a
	* tests/winDde.test:         bug in the tests.
	* library/dde/pkgIndex.tcl:  Incremented version to 1.2.5

	* doc/dde.n:                 Committed TIP #120 which provides the
	* win/tclWinDde.c:           dde package for safe interpreters.
	* tests/winDde.test:         Incremented package version to 1.2.4
	* library/dde/pkgIndex.tcl:

2003-06-23  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFCmd.c: fix to bad error message when trying to do 'file
	copy foo ""'. [Bug 756951]
	* tests/fCmd.test: added two new tests for the bug.

	* win/tclWinFile.c:
	* win/tclWin32Dll.c: recommitted some filesystem globbing speed-ups,
	but disabled some on the older Win 95/98/ME where they don't seem to
	work.

	* doc/FileSystem.3: documentation fix [Bug 720634]

2003-06-18  Miguel Sofer <msofer@users.sf.net>

	* generic/tclNamesp.c (Tcl_Export): removed erroneous comments. [Bug
	756744]

2003-06-17  Vince Darley  <vincentdarley@users.sourceforge.net>

	* win/makefile.vc:  fixes to check-in below so compilation now works
	again on Windows.

	* generic/tclCmdMZ.c:
	* tests/regexp.test: fixing of bugs related to regexp and regsub
	matching of empty strings. Addition of a number of new tests. [Bug
	755335]

2003-06-16  Andreas Kupries  <andreask@activestate.com>

	* win/Makefile.in:  Haven't heard back from David for a week. Now
	* win/configure:    committing the remaining changes.
	* win/configure.in: Note: In active contact with Helmut Giese about
	* win/makefile.vc:  the borland relatedchanges. This part will see
	* win/rules.vc:     future updates.
	* win/tcl.m4:
	* win/makefile.bc:

2003-06-10  Andreas Kupries  <andreask@activestate.com>

	* generic/tclConfig.c (ASSOC_KEY): Changed the key to
	"tclPackageAboutDict" (tcl prefix) to make collisions with the keys of
	other packages more unlikely.

2003-06-10  Miguel Sofer <msofer@users.sf.net>

	* generic/tclBasic.c:
	* generic/tclExecute.c: let TclExecuteObjvInternal call
	TclInterpReady instead of relying on its callers to do so; fix for the
	part of [Bug 495830] that is new in 8.4.
	* tests/interp.test: Added tests 18.9 (knownbug) and 18.10

2003-06-09  Andreas Kupries  <andreask@activestate.com>

	* generic/tcl.decls:  Ported the changes from the
	* generic/tcl.h:      'tip-59-implementation' branch into the CVS
	* generic/tclBasic.c: head. Regenerated stub table. Regenerated the
	* generic/tclInt.h:   configure's scripts, with help from Joe English.
	* generic/tclDecls.h:
	* generic/tclStubInit.c:
	* generic/tclConfig.c:
	* generic/tclPkgConfig.c:
	* unix/Makefile.in:
	* unix/configure.in:  The changes in the windows section are not yet
	* unix/tcl.m4:        committed, they await feedback from David
	* unix/mkLinks:       Gravereaux.
	* doc/RegConfig.3:
	* mac/tclMacPkgConfig.c:
	* tests/config.test:

2003-06-09  Don Porter  <dgp@users.sourceforge.net>

	* string.test (string-4.15): Added test for [string first] bug
	reported in Tcl 8.3, where test for all-single-byte-encoded strings
	was not reliable.

2003-06-04  Joe Mistachkin  <joe@mistachkin.com>

	* tools/man2help.tcl: Added duplicate help section checking and
	* tools/index.tcl:    corrected a comment typo for the getTopics proc
	in index.tcl. [Bug 748700]

2003-06-02  Vince Darley  <vincentdarley@users.sourceforge.net>

	* win/tclWinFCmd.c:
	* tests/fCmd.test: fix to [Bug #747575] in which a bad error message
	is given when trying to rename a busy directory to one with the same
	prefix, but not the same name. Added three new tests.

2003-05-23  D. Richard Hipp <drh@hwaci.com>

	* win/tclWinTime.c: Add tests to detect and avoid a division by zero
	in the windows precision timer calibration logic.

2003-05-23  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclObj.c (tclCmdNameType):  Converted internal rep
	management of the cmdName Tcl_ObjType the opposite way, to always use
	the twoPtrValue instead of always using the otherValuePtr. Previous
	fix on 2003-05-12 broke several extensions that wanted to poke around
	with the twoPtrValue.ptr2 value of a cmdName Tcl_Obj, like TclBlend
	and e4graph. [Bug 726018]
	Thanks to George Petasis for the bug report and Jacob Levy for testing
	assistance.

2003-05-23  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/mkLinks: Set the var S to "" at the top of the file to avoid
	error when user has set S to something. [Tk Bug 739833]

2003-05-22  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Tcl.pbproj/project.pbxproj: added missing references to new
	source files tclPathObj.c and tclMacOSXFCmd.c.

	* macosx/tclMacOSXBundle.c: fixed a problem that caused only the first
	call to Tcl_MacOSXOpenVersionedBundleResources() for a given bundle
	identifier to succeed. This caused the tcl runtime library not to be
	found in all interps created after the inital one.

2003-05-19  Kevin B. Kenny  <kennykb@hippolyta>

	* unix/tclUnixTime.c: Corrected a bug in conversion of non-ASCII
	chars in the format string.

2003-05-19  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Tcl.pbproj/project.pbxproj: changed tclConfig.sh location in
	versioned framework subdirectories to be identical to location in
	framework toplevel; fixed stub library symbolic links to be tcl
	version specific.

	* unix/tclUnixTime.c: fixed typo.

2003-05-18  Kevin Kenny  <kennykb@acm.org>

	* compat/strftime.c:  Modified TclpStrftime to return its result in
	* generic/tclClock.c: UTF-8 encoding, and removed the conversion from
	* mac/tclMacTime.c:   system encoding to UTF-8 from [clock format].
	* unix/tclUnixTime.c: Needed to avoid double conversion of the
	* win/tclWinTime.c:   timezone name on Windows systems. [Bug 624408]

2003-05-16  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* library/dde/pkgIndex.tcl:  Applied TIP #130 which provides for
	* tests/winDde.test:         unique dde server names. Added some more
	* win/tclWinDde.c:           tests. Fixes [Bug 219293]

	* doc/dde.n: Updated documentation re TIP #130.
	* tests/winDde.test: Applied patch for [Bug 738929] by KKB and changed
	to new-style tests.

2003-05-16  Kevin B. Kenny  <kennykb@acm.org>

	* unix/Makefile.in:	Removed one excess source file tclDToA.c

2003-05-16  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Tcl.pbproj/project.pbxproj: updated copyright year.

2003-05-15  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclGetDate.y: added further hackery to the yacc
	* generic/tclDate.c:    post-processing to arrange for the code to set
	* unix/Makefile.in:     up exit handlers to free the stacks. [Bug
				736425]

2003-05-15  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/tclWinFile.c (TclpMatchInDirectory): revert glob code to r1.44
	as 2003-04-11 optimizations broke Windows98 glob'ing.

	* doc/socket.n: nroff font handling correction

	* library/encoding/gb2312-raw.enc (new): This is the original
	gb2312.enc renamed to allow for it to still be used. This is needed by
	Tk (unix) because X fonts with gb2312* charsets really do want the
	original gb2312 encoding. [Bug 557030]

2003-05-14  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclCmdAH.c (Tcl_FormatObjCmd): Stop unwarranted demotion of
	wide values to longs by formatting of int values. [Bug 699060]

2003-05-14  Jeff Hobbs  <jeffh@ActiveState.com>

	* library/encoding/gb2312.enc: copy euc-cn.enc over original
	gb2312.enc. gb2312.enc appeared to not work as expected, and most uses
	of gb2312 really mean euc-cn (which may be the cause of the problem).
	[Bug 557030]

2003-05-14  Daniel Steffen  <das@users.sourceforge.net>

	Implementation of TIP 118:

	* generic/tclFCmd.c (TclFileAttrsCmd): return the list of attributes
	that can be retrieved without error for a given file, instead of
	aborting the whole command when any error occurs.

	* unix/tclUnixFCmd.c: added support for new file attributes and for
	copying Mac OS X file attributes & resource fork during [file copy].

	* generic/tclInt.decls: added declarations of new external commands
	needed by new file attributes support in tclUnixFCmd.c.

	* macosx/tclMacOSXFCmd.c (new): Mac OS X specific implementation of
	new file attributes and of attribute & resource fork copying.

	* mac/tclMacFCmd.c: added implementation of -rsrclength attribute &
	fixes to other attributes for consistency with OSX implementation.

	* mac/tclMacResource.c: fixes to OSType handling.

	* doc/file.n: documentation of [file attributes] changes.

	* unix/configure.in: check for APIs needed by new file attributes.

	* unix/Makefile.in:
	* unix/tcl.m4: added new platform specifc tclMacOSXFCmd.c source.

	* unix/configure:
	* generic/tclStubInit.c:
	* generic/tclIntPlatDecls.h: regen.

	* tools/genStubs.tcl: fixes to completely broken code trying to
	prevent overlap of "aqua", "macosx", "x11" and "unix" stub entries.

	* tests/unixFCmd.test: added tests of -readonly attribute.

	* tests/macOSXFCmd.test (new): tests of macosx file attributes and of
	preservation of attributes & resource fork during [file copy].

	* tests/macFCmd.test: restore -readonly attribute of test dir, as
	otherwise its removal can fail on unices supporting -readonly.

2003-05-13  David Gravereaux <davygrvy@pobox.com>

	* generic/tclEnv.c: Another putenv() copy behavior problem repaired
	when compiling on windows and using microsoft's runtime. [Bug 736421]

2003-05-13  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclIOUtil.c: ensure cd is thread-safe.
	[Bug 710642] (vasiljevic)

2003-05-13  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclEvent.c (Tcl_Finalize): Removed unused variable to reduce
	compiler warnings. [Bug 664745]

2003-05-13  Joe Mistachkin  <joe@mistachkin.com>

	* generic/tcl.decls:  Changed Tcl_JoinThread parameter name from
	* generic/tclDecls.h: "id" to "threadId". [Bug 732477]
	* unix/tclUnixThrd.c:
	* win/tclWinThrd.c:
	* mac/tclMacThrd.c:

2003-05-13  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tcl.decls:
	* macosx/tclMacOSXBundle.c: added extended version of the
	Tcl_MacOSXOpenBundleResources() API taking an extra version number
	argument: Tcl_MacOSXOpenVersionedBundleResources(). This is needed to
	be able to access bundle resources in versioned frameworks such as Tcl
	and Tk, otherwise if multiple versions were installed, only the latest
	version's resources could be accessed. [Bug 736774]

	* unix/tclUnixInit.c (Tcl_MacOSXGetLibraryPath): use new versioned
	bundle resource API to get tcl runtime library for TCL_VERSION. [Bug
	736774]

	* generic/tclPlatDecls.h:
	* generic/tclStubInit.c: regen.

	* unix/tclUnixPort.h: worked around the issue of realpath() not
	being thread-safe on Mac OS X by defining NO_REALPATH for threaded
	builds on Mac OS X. [Bug 711232]

2003-05-12  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/cmdAH.test: General clean-up of tests so that all
	tcltest-specific commands are protected by constraints and all
	platforms see the same number of tests. [Bug 736431]

2003-05-12  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInterp.c: (AliasObjCmd):   Added refCounting of the words
	* tests/interp.test (interp-33.1):      of the target of an interp
	alias during its execution. Also added test. [Bug 730244]

	* generic/tclBasic.c (TclInvokeObjectCommand):  objv[argc] is no
	longer set to NULL (Tcl_CreateObjCommand docs already say that it
	should not be accessed).

	* tests/cmdMZ.test:  Forgot to import [temporaryDirectory].

	* generic/tclObj.c (tclCmdNameType):  Corrected variable use of the
	otherValuePtr or the twoPtrValue.ptr1 fields to store a
	(ResolvedCmdName *) as the internal rep. [Bug 726018]

	* doc/Eval.3:  Corrected prototype for Tcl_GlobalEvalObj [Bug 727622].

2003-05-12  Miguel Sofer <msofer@users.sf.net>

	* generic/tclVar.c (TclObjLookupVar): [Bug 735335] temporary fix,
	disabling usage of tclNsVarNameType.
	* tests/var.test (var-15.1): test for [Bug 735335]

2003-05-10  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/tclWinSerial.c (SerialCloseProc): correct mem leak on closing a
	Windows serial port [Bug 718002] (schroedter)

	* generic/tclCmdMZ.c (Tcl_StringObjCmd): prevent string repeat crash
	when overflow sizes were given (throws error). [Bug 714106]

2003-05-09  Joe Mistachkin <joe@mistachkin.com>

	* generic/tclThreadAlloc.c (TclFreeAllocCache): Fixed memory leak
	caused by treating cachePtr as a TLS index. [Bug 731754]

	* win/tclAppInit.c (Tcl_AppInit): Fixed memory leaks caused by not
	freeing the memory allocated by setargv and the async handler created
	by Tcl_AppInit. An exit handler has been created that takes care of
	both leaks. In addition, Tcl_AppInit now uses ckalloc instead of
	Tcl_Alloc to allow for easier leak tracking and to be more consistent
	with the rest of the Tcl core. [Bugs 733156, 733221]

	* tools/encoding/txt2enc.c (main): Fixed memory leak caused by failing
	to free the memory used by the toUnicode array of strings [Bug 733221]

2003-05-09  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c (TclCompileScript):
	* tests/compile.test (compile-3.5): corrected wrong test and
	behaviour in the earlier fix for [Bug 705406]; Don Porter reported
	this as [Bug 735055], and provided the solution.

2003-05-09  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclCmdMZ.c (Tcl_ReturnObjCmd): The array of strings passed
	to Tcl_GetIndexFromObj must be NULL terminated. [Bug 735186]
	Thanks to Joe Mistachkin for spotting this.

2003-05-07  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/trace.n: Fixed very strange language in the documentation for
	'trace add execution'. [Bug 729821]

	* generic/tclCmdMZ.c (Tcl_TraceObjCmd): Made error message for 'trace
	info' more consistent with documentation. [Bug 706961]

	* generic/tclDictObj.c (DictInfoCmd): Fixed memory leak caused by
	confusion about string ownership.  [Bug 731706]

2003-05-05  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c:		Implementation of TIP 90, which
	* generic/tclCmdAH.c:		extends the [catch] and [return]
	* generic/tclCompCmds.c:	commands to enable creation of a
	* generic/tclExecute.c:		proc that is a replacement for
	* generic/tclInt.h:		[return]. [Patch 531640]
	* generic/tclProc.c:
	* generic/tclResult.c:
	* tests/cmdAH.test:
	* tests/cmdMZ.test:
	* tests/error.test:
	* tests/proc-old.test:

	* library/tcltest/tcltest.tcl: The -returnCodes option to [test]
	failed to recognize the symbolic name "ok" for return code 0.

2003-05-05  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclBasic.c (Tcl_HideCommand): Fixed error message for
	grammar and spelling.

2003-04-28  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclDictObj.c (DictIncrCmd): Updated to reflect the behaviour
	with wide increments of the normal [incr] command.
	* generic/tclInt.decls: Added TclIncrWideVar2 to internal stub table
	and cleaned up.
	* tests/incr.test (incr-3.*):
	* generic/tclVar.c (TclIncrWideVar2, TclPtrIncrWideVar):
	* generic/tclExecute.c (TclExecuteByteCode):
	* generic/tclCmdIL.c (Tcl_IncrObjCmd): Make [incr] work when trying to
	increment by wide values. [Bug 728838]

	* generic/tclCompCmds.c (TclCompileSwitchCmd): Default mode of
	operation of [switch] is exact matching. [Bug 727563]

2003-04-25  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c:  Tcl_EvalObjv() failed to honor the
	TCL_EVAL_GLOBAL flag when resolving command names. Tcl_EvalEx passed a
	string rep including leading whitespace and comments to
	TclEvalObjvInternal().

2003-04-25  Andreas Kupries  <andreask@activestate.com>

	* win/tclWinThrd.c: Applied SF patch #727271. This patch changes the
	code to catch any errors returned by the windows functions handling
	TLS ASAP instead of waiting to get some mysterious crash later on due
	to bogus pointers. Patch provided by Joe Mistachkin.

	This is a stop-gap measure to deal with the low number of ?TLS slots
	provided by some of the variants of Windows (60-80).

2003-04-24  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFileName.c: fix to bug reported privately by Jeff where,
	for example, 'glob -path {[tcl]} *' gets confused by the leading
	special character (which is escaped internally), and instead lists
	files in '/'. Bug only occurs on Windows where '\' is also a directory
	separator.
	* tests/fileName.test: added test for the above bug.

2003-04-22  Andreas Kupries  <andreask@activestate.com>

	* The changes below fix SF bugs [593810], and [718045].

	* generic/tclIO.c (Tcl_CutChannel, Tcl_SpliceChannel): Invoke
	TclpCutSockChannel and TclpSpliceSockChannel.

	* generic/tclInt.h: Declare TclpCutSockChannel and
	TclpSpliceSockChannel.

	* unix/tclUnixSock.c (TclpCutSockChannel, TclpSpliceSockChannel):
	Dummy functions, on unix the sockets are _not_ handled specially.

	* mac/tclMacSock.c (TclpCutSockChannel, TclpSpliceSockChannel):
	* win/tclWinSock.c (TclpCutSockChannel, TclpSpliceSockChannel): New
	functions to handle socket specific cut/splice operations: auto-init
	of socket system for thread on splice, management of the module
	internal per-thread list of sockets, management of association of
	sockets with HWNDs for event notification.

	* win/tclWinSock.c (NewSocketInfo): Extended initialization
	assignments to cover all items of the structure. During debugging of
	the new code mentioned above I found that two fileds could contain
	bogus data.

	* win/tclWinFile.c: Added #undef HAVE_NO_FINDEX_ENUMS before
	definition because when compiling in debug mode the compiler complains
	about a redefinition, and this warning is also treated as an error.

2003-04-21  Don Porter  <dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl:  When the return code of a test does
	not meet expectations, report that as the reason for test failure, and
	do not attempt to check the test result for correctness. [Bug 725253]

2003-04-18  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/tclWinInt.h (VER_PLATFORM_WIN32_CE): conditionally define.
	* win/tclWinInit.c: recognize Windows CE as a Win platform. This just
	recognizes CE - full support will come later.

	* win/configure: regen
	* win/configure.in (SHELL): force it to /bin/sh as autoconf 2.5x
	uses /bin/bash, which can fail to find exes in the path (ie: lib).

	* generic/tclExecute.c (ExprCallMathFunc): remove incorrect
	extraneous cast from Tcl_WideAsDouble.

2003-04-18  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/open.n:		Moved serial port options from [fconfigure] to
	* doc/fconfigure.n:	[open] as it is up to the creator of a channel
				to describe the channel's special config
				options. [Bug 679010]

2003-04-16  Don Porter  <dgp@users.sourceforge.net>

	* generic/tcl.h:	Made changes so that the "wideInt" Tcl_ObjType
	* generic/tclObj.c:	is defined on all platforms, even those where
	* generic/tclPort.h:	TCL_WIDE_INT_IS_LONG is defined. Also made the
	Tcl_Value struct have a wideValue field on all platforms. This is a
	***POTENTIAL INCOMPATIBILITY*** for TCL_WIDE_INT_IS_LONG platforms
	because that struct changes size. This is the same TIP 72
	incompatibility that was seen on other platforms at the 8.4.0 release,
	when this change should have happened as well. [Bug 713562]

	* generic/tclInt.h:  New internal macros TclGetWide() and
	TclGetLongFromWide() to deal with both forms of the "wideInt"
	Tcl_ObjType, so that conditional TCL_WIDE_INT_IS_LONG code is confined
	to the header file.

	* generic/tclCmdAH.c:	Replaced most coding that was conditional
	* generic/tclCmdIL.c:	on TCL_WIDE_INT_IS_LONG with code that
	* generic/tclExecute.c: works across platforms, sometimes using
	* generic/tclTest.c:	the new macros above to do it.
	* generic/tclUtil.c:
	* generic/tclVar.c:

2003-04-17  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/socket.n: Added a paragraph to remind people to specify their
	encodings when using sockets. [Bug 630621]

2003-04-16  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/CrtMathFnc.3: Functions also have to deal with wide ints, but
	this was not documented. [Bug 709720]

2003-04-16  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclPathObj.c: removed undesired 'static' for function which
	is now shared (previously it was duplicated).

2003-04-15  Joe English  <jenglish@users.sourceforge.net>

	* doc/namespace.n: added example section "SCOPED SCRIPTS", supplied by
	Kevin Kenny. [Bug 219183]

2003-04-15  Kevin Kenny  <kennykb@acm.org>

	* makefile.vc: Updated makefile.vc to conform with Mo DeJong's changes
	to Makefile.in and tclWinPipe.c on 2003-04-14. Now passes TCL_PIPE_DLL
	in place of TCL_DBGX.
	* win/tclWinTime.c: Corrected use of types to make compilation
	compatible with VC++5.

2003-04-15  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclIOUtil.c: finished check-in from yesterday, removing
	duplicate function definition.

2003-04-14  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclClock.c:	Corrected compiler warnings.
	* generic/tclTest.c:

2003-04-14  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/Makefile.in: Don't define TCL_DBGX symbol for every compile.
	Instead, define TCL_PIPE_DLL only when compiling tclWinPipe.c. This
	will break other build systems, so they will need to remove the
	TCL_DBGX define and replace it with a define for TCL_PIPE_DLL.
	* win/tclWinPipe.c (TclpCreateProcess): Remove PREFIX_IDENT and
	DEBUG_IDENT from top of file. Use TCL_PIPE_DLL passed in from build
	env instead of trying to construct the dll name from already defined
	symbols. This approach is more flexible and better in the long run.

2003-04-14  Kevin Kenny  <kennykb@acm.org>

	* win/tclWinFile.c: added conditionals to restore compilation on
	VC++6, which was broken by recent changes.

2003-04-14  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclIOUtil.c:
	* generic/tclPathObj.c:
	* generic/tclFileSystem.h: overlooked one function which was
	duplicated, so this is now shared between modules.
	* win/tclWinFile.c: allow this file to compile with VC++ 5.2 again
	since Mingw build fixes broke that.

2003-04-13  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/configure: Regen.
	* win/configure.in: Add check for FINDEX_INFO_LEVELS from winbase.h,
	known to be a problem in VC++ 5.2. Define HAVE_NO_FINDEX_ENUMS if the
	define does not exist.
	* win/tclWinFile.c: Put declarations for FINDEX_INFO_LEVELS and
	FINDEX_SEARCH_OPS inside a check for HAVE_NO_FINDEX_ENUMS so that
	these are not declared twice. This fixes the Mingw build.
	* win/tclWinTime.c: Rework the init of timeInfo so that the number or
	initializers matches the declaration. This was broken under Mingw. Add
	cast to avoid compile warning when calling the AccumulateSample
	function.

2003-04-12  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/Makefile.in (GENERIC_OBJS): add missing tclPathObj.c

2003-04-12  Kevin Kenny  <kennykb@acm.org>

	* doc/clock.n:
	* generic/tclClock.c (Tcl_ClockObjCmd):
	* tests/clock.test: Implementation of TIP #124. Also renumbered test
	cases to avoid duplicates. [Bug 710310]
	* tests/winTime.test:
	* win/tclWinTest.c (TestwinclockCmd, TestwinsleepCmd):
	* win/tclWinTime.c (Tcl_WinTime, UpdateTimeEachSecond,
	(ResetCounterSamples, AccumulateSample, SAMPLES, TimeInfo): Made
	substantial changes to the phase-locked loop (replaced an IIR filter
	with an FIR one) in a quest for improved loop stability (Bug not
	logged at SF, but cited in private communication from Jeff Hobbs).

2003-04-11  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCmdMZ.c (Tcl_StringObjCmd,STR_IS_INT):  Corrected
	inconsistent results of [string is integer] observed on systems where
	sizeof(long) != sizeof(int). [Bug 718878]
	* tests/string.test: Added tests for Bug 718878.
	* doc/string.n: Clarified that [string is integer] accepts 32-bit
	integers.

2003-04-11  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c (UpdateInterest): When dropping interest in
	TCL_READABLE now dropping interest in TCL_EXCEPTION too. This fixes a
	bug where Expect detects eof on a file prematurely on solaris 2.6 and
	higher. A much more complete explanation is in the code itself (40
	lines of comments for a one-line change :)

2003-04-11  Vince Darley  <vincentdarley@users.sourceforge.net>

	* tests/cmdAH.test: fix test suite problem if /home is a symlink. [Bug
	703264]
	* generic/tclIOUtil.c: fix bad error message with 'cd ""'. [Bug
	704917]
	* win/tclWinFile.c, win/tclWin32Dll.c:
	* win/tclWinInt.h: allow Tcl to differentiate between reparse points
	which are symlinks and mounted volumes, and correctly handle the
	latter. This involves some elaborate code to find the actual drive
	letter (if possible) corresponding to a mounted volume. [Bug 697862]
	* tests/fileSystem.test: add constraints to stop tests running in
	ordinary tcl interpreter. [Bug 705675]

	* generic/tclIOUtil.c:
	* generic/tclPathObj.c: (new file)
	* generic/tclFileSystem.h: (new file)
	* win/makefile.vc:
	Split path object handling out of the virtual filesystem layer, into
	tclPathObj.c. This refactoring cleans up the internal filesystem code,
	and will make any future optimisations and forthcoming better
	thread-safety much easier.

	* generic/tclTest.c:
	* tests/reg.test: added some 'knownBug' tests for problems in Tcl's
	regexp code with the TCL_REG_CAN_MATCH flag (see Bug 703709). Code too
	impenetrable to fix right now, but a fix is needed for tip113 to work
	correctly.

	* tests/fCmd.test
	* win/tclWinFile.c: added some filesystem optimisation to the 'glob'
	implementation, and some new tests.

	* generic/tclCmdMZ.c: fix typo in comment

	* tests/winFile.test:
	* tests/ioUtil.test:
	* tests/unixFCmd.test: renumbered tests with duplicate numbers. [Bug
	710361]

2003-04-10  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/binary.n: Fixed typo in [binary format w] desc. [Bug 718543]

2003-04-08  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclCmdAH.c (Tcl_ErrorObjCmd): Strings are only empty if
	they have zero length, not if their first byte is zero, so fix test
	guarding Tcl_AddObjErrorInfo to take this into account. [Bug
	reported by Don Porter; no bug-id.]

2003-04-07  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompCmds.c (TclCompileIfCmd):  Corrected string limits of
	arguments interpolated in error messages. [Bug 711371]

	* generic/tclCmdMZ.c (TraceExecutionProc):  Added missing
	Tcl_DiscardResult() call to avoid memory leak.

2003-04-07  Donal K. Fellows  <zzcgudf@ernie.mvc.mcc.ac.uk>

	* generic/tclDictObj.c (Tcl_DictObjCmd): Stopped compilers from
	moaning about switch fall-through.  [Bug 716327]
	(DictFilterCmd): Yet more warning killing, this time reported by
	Miguel Sofer by private chat.

2003-04-07  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/dict.test (dict-2.6):
	* generic/tclDictObj.c (Tcl_NewDictObj, Tcl_DbNewDictObj): Oops!
	Failed to fully initialise the Dict structure.
	(DictIncrCmd): Moved valueAlreadyInDictionary label to stop compiler
	complaints. [Bug 715751]

	* generic/tclDictObj.c (DictIncrCmd): Followed style in the rest of
	the core by commenting out wide-specific operations on platforms where
	wides are longs, and used longs more thoroughly than ints through
	[dict incr] anyway to forestall further bugs.
	* generic/tclObj.c: Made sure there's always a tclWideIntType
	implementation available, not that it is always useful. [Bug 713562]

2003-04-05  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclDictObj.c: Removed commented out notes on declarations to
	be moved to elsewhere in the Tcl core.

	* generic/tclInt.h:	Final stages of plumbing in.
	* generic/tclBasic.c:
	* generic/tclObj.c (TclInitObjSubsystem):

	* unix/Makefile.in, win/Makefile.in, win/makefile.[bv]c: Build support.
	* generic/tcl.decls: Added dict public API to stubs table.
	* generic/tcl.h (Tcl_DictSearch): Added declaration of structure to
	allow user code to iterate over dictionaries.

	* doc/DictObj.3:	New files containing dictionary implementation
	* doc/dict.n:		documentation and tests as as mandated by TIP
	* generic/tclDictObj.c: #111.
	* tests/dict.test:

2003-04-03  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure:
	* unix/tcl.m4 (SC_CONFIG_CFLAGS): Don't set TCL_LIBS if it is already
	set to support use of TCL_LIBS var from tclConfig.sh in the Tk
	configure script.

2003-04-03  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/Makefile.in: Don't subst MATH_LIBS, LIBS, and DL_LIBS
	separately. Instead, just subst TCL_LIBS since it includes the
	others.
	* unix/configure: Regen.
	* unix/tcl.m4 (SC_CONFIG_CFLAGS, SC_TCL_LINK_LIBS): Set and subst
	TCL_LIBS in SC_CONFIG_CFLAGS instead of SC_TCL_LINK_LIBS. Don't subst
	MATH_LIBS since it is now covered by TCL_LIBS.
	* unix/tclConfig.sh.in: Use TCL_LIBS instead of DL_LIBS, LIBS, and
	MATH_LIBS.
	* unix/dltest/Makefile.in: Ditto.

2003-04-03  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompCmds.c (TclCompileReturnCmd):  Now that [return]
	compiles to INST_RETURN, it is safe to compile even outside a proc.

2003-04-02  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/configure: Regen.
	* win/configure.in: Set stub lib flag based on new LIBFLAGSUFFIX
	variable.
	* win/tcl.m4 (SC_CONFIG_CFLAGS): Set new LIBFLAGSUFFIX that works like
	LIBSUFFIX, it is used when creating library names. The previous
	implementation would generate -ltclstub85 instead of -ltclstub85s when
	configured with --disable-shared.

2003-04-02  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclParse.c (TclSubstTokens):  Moved declaration of
	utfCharBytes to beginning of procedure so that it does not go out of
	scope (get free()d) while append is still pointing to it. [Bugs
	703167, 713754]

2003-04-01  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure: Regen.
	* unix/tcl.m4 (SC_CONFIG_CFLAGS): Check for inet_ntoa in -lbind inside
	the BeOS block since doing it later broke the build under SuSE 7.3.
	[Bug 713128]

2003-04-01  Don Porter  <dgp@users.sourceforge.net>

	* tests/README:  Direct [source] of *.test files is no longer
	recommended. The tests/*.test files should only be evaluated under the
	control of the [runAllTests] command in tests/all.tcl.

	* generic/tclExecute.c (INST_RETURN):  Bytecompiled [return] failed to
	reset iPtr->returnCode, causing tests parse-18.17 and parse-18.21 to
	fail strangely.
	* tests/parse.test (parse-18.21):  Corrected now functioning test.
	Added further coverage tests.

2003-03-31  Don Porter  <dgp@users.sourceforge.net>

	* tests/parse.test (parse-18.*):  Coverage tests for the new
	implementation of Tcl_SubstObj(). Note that tests parse-18.17 and
	parse-18.21 demonstrate some bugs left to fix in the current code.

2003-03-27  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure: Regen.
	* unix/tcl.m4 (SC_CONFIG_CFLAGS): Use -Wl,--export-dynamic instead of
	-rdynamic for LDFLAGS. The -rdynamic is not documented so it seems
	better to pass the --export-dynamic flag to the linker. [Patch 573395]

2003-03-27  Miguel Sofer <msofer@users.sf.net>

	* tests/encoding.test:
	* tests/proc-old.test:
	* tests/set-old.test: Altered test numers to eliminate duplicates,
	[Bugs 710313, 710320, 710352]

2003-03-27  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/parseOld.test:	Altered test numers to eliminate duplicates.
	* tests/parse.test:	[Bugs 710365, 710369]
	* tests/expr-old.test:
	* tests/expr.test:

	* tests/utf.test:	Altered test numers to eliminate duplicates.
	* tests/trace.test:	[Bugs 710322, 710327, 710349, 710363]
	* tests/lsearch.test:
	* tests/list.test:
	* tests/info.test:
	* tests/incr-old.test:
	* tests/if-old.test:
	* tests/format.test:
	* tests/foreach.test:

2003-03-26  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure: Regen.
	* unix/tcl.m4 (SC_CONFIG_CFLAGS, SC_TCL_LINK_LIBS): Add BeOS system to
	SC_CONFIG_CFLAGS. Check for inet_ntoa in -lbind, needed for BeOS.

2003-03-26  Don Porter  <dgp@users.sourceforge.net>

	* doc/tcltest.n:
	* library/tcltest/tcltest.tcl:  Added reporting during [configure
	-debug 1] operations to warn about multiple uses of the same test
	name. [FRQ 576693]

	* tests/msgcat.test (msgcat-2.2.1): changed test name to avoid
	duplication. [Bug 710356]

	* unix/dltest/pkg?.c:  Changed all Tcl_InitStubs calls to pass
	argument exact = 0, so that rebuilds are not required when Tcl
	bumps to a new version.  [Bug 701926]

2003-03-24  Miguel Sofer <msofer@users.sf.net>

	* generic/tclVar.c:
	* tests/var.test: fixing ObjMakeUpvar's lookup algorithm for the
	created local variable. [Bug 631741] (Chris Darroch) and [Bug 696893]
	(David Hilker)

2003-03-24  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* library/dde/pkgIndex.tcl: bumped version to 1.2.2 in tclWinDde.c,
	now adding here too.

2003-03-22  Kevin Kenny  <kennykb@acm.org>

	* library/dde/pkgIndex.tcl:
	* library/reg/pkgIndex.tcl: Fixed a bug where [package require dde]
	or [package require registry] attempted to load the release version
	of the DLL into a debug build. [Bug 708218] Thanks to Joe Mistachkin
	for the patch.
	* win/makefile.vc: Added quoting around the script name in the 'test'
	target; Joe Mistachkin insists that he has a configuration that fails
	to launch tcltest without it, and it appears harmless otherwise.

2003-03-22  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* win/tclWinDde.c: Make dde services conform the the documentation
	such that giving only a topic name really returns all services with
	that topic. [Bug 219155]
	Prevent hangup caused by dde server applications failing to process
	messages. [Bug 707822]
	* tests/winDde.test: Corrected labels and added a test for search by
	topic name.

2003-03-20  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInt.h (tclOriginalNotifier):
	* generic/tclStubInit.c (tclOriginalNotifier):
	* mac/tclMacNotify.c (Tcl_SetTimer,Tcl_WaitForEvent):
	* unix/tclUnixNotfy.c (Tcl_SetTimer,Tcl_WaitForEvent,
	(Tcl_CreateFileHandler,Tcl_DeleteFileHandler):
	* win/tclWinNotify.c (Tcl_SetTimer,Tcl_WaitForEvent):  Some linkers
	apparently use a different representation for a pointer to a function
	within the same compilation unit and a pointer to a function in a
	different compilation unit. This causes checks like those in the
	original notifier procedures to fall into infinite loops. The fix is
	to store pointers to the original notifier procedures in a struct
	defined in the same compilation unit as the stubs tables, and compare
	against those values. [Bug 707174]

	* generic/tclInt.h:  Removed definition of ParseValue struct that is
	no longer used.

2003-03-19  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c:
	* tests/compile.test: bad command count on TCL_OUT_LINE_COMPILE.
	[Bug 705406] (Don Porter)

2003-03-19  Don Porter  <dgp@users.sourceforge.net>

	* library/auto.tcl:		Replaced [regexp] and [regsub] with
	* library/history.tcl:		[string map] where possible.  Thanks
	* library/ldAout.tcl:		to David Welton. [Bugs 667456,667558]
	* library/safe.tcl:		Bumped to http 2.4.3, opt 0.4.5, and
	* library/http/http.tcl:	tcltest 2.2.3.
	* library/http/pkgIndex.tcl:
	* library/opt/optparse.tcl:
	* library/opt/pkgIndex.tcl:
	* library/tcltest/tcltest.tcl:
	* library/tcltest/pkgIndex.tcl:
	* tools/genStubs.tcl:
	* tools/tcltk-man2html.tcl:
	* unix/mkLinks.tcl:

	* doc/Eval.3 (Tcl_EvalObjEx):			Corrected CONST and
	* doc/ParseCmd.3 (Tcl_EvalTokensStandard):	return type errors in
	documentation. [Bug 683994]

	* generic/tclCompCmds.c (TclCompileReturnCmd):  Alternative fix for
	* generic/tclCompile.c (INST_RETURN):	[Bug 633204] that uses a new
	* generic/tclCompile.h (INST_RETURN):	bytecode INST_RETURN to
	* generic/tclExecute.c (INST_RETURN):	properly bytecode the [return]
	command to something that returns TCL_RETURN.

2003-03-18  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/configure: Regen.
	* win/configure.in: Don't run the AC_CYGWIN macro since it uses
	AC_CANONICAL_HOST under autoconf 2.5X. Just check to see if __CYGWIN__
	is defined by the compiler and set the ac_cv_cygwin variable based on
	that. [Bug 705912]

2003-03-18  Kevin Kenny  <kennykb@users.sourceforge.net>

	* tests/registry.test: Changed the conditionals to avoid an abort if
	[testlocale] is missing, as when running the test in tclsh rather than
	tcltest. [Bug 705677]

2003-03-18  Daniel Steffen  <das@users.sourceforge.net>

	* tools/tcltk-man2html.tcl: added support for building 'make html'
	from inside distribution directories named with 8.x.x version numbers.
	tcltk-man2html now uses the latest tcl8.x.x resp. tk8.x.x directories
	found inside its --srcdir argument.

2003-03-17  Mo DeJong  <mdejong@users.sourceforge.net>

	* tests/format.test: Renumber tests, a bunch of tests all had the same
	id.

2003-03-17  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/lsearch.n:	Altered documentation of -ascii options so
	* doc/lsort.n:		they don't specify that they operate on ASCII
				strings, which they never did anyway. [Bug
				703807]

2003-03-14  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclCmdAH.c (Tcl_FormatObjCmd): Only add the modifier that
	indicates we've got a wide int when we're formatting in an integer
	style.  Stops some libc's from going mad. [Bug 702622] Also tidied
	whitespace.

2003-03-13  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/tcl.m4 (SC_WITH_TCL): Port version number fix that was made in
	tk instead of tcl sources.

2003-03-13  Mo DeJong  <mdejong@users.sourceforge.net>

	Require autoconf 2.57 or newer, see TIP 34 for a detailed explanation
	of why this is good. This will no doubt break the build on some
	platforms, let the flaming begin.

	* tools/configure: Regen with autoconf 2.57.
	* tools/configure.in: Require autoconf 2.57.
	* unix/configure: Regen with autoconf 2.57.
	* unix/configure.in: Require autoconf 2.57.
	Apply AC_LIBOBJ changes from patch 529884.
	* unix/tcl.m4: Ditto.
	* win/configure: Regen with autoconf 2.57.
	* win/configure.in: Require autoconf 2.57.
	Don't subst LIBOBJS since this happens by default, this avoids an
	autoconf error.

2003-03-12  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c (Tcl_EvalTokensStandard):
	* generic/tclCmdMZ.c (Tcl_SubstObj):
	* generic/tclCompCmds.c (TclCompileSwitchCmd):
	* generic/tclCompExpr.c (CompileSubExpr):
	* generic/tclCompile.c (TclSetByteCodeFromAny,TclCompileScript,
	(TclCompileTokens,TclCompileCmdWord):
	* generic/tclCompile.h (TclCompileScript):
	* generic/tclExecute.c (TclCompEvalObj):
	* generic/tclInt.h (Interp,TCL_BRACKET_TERM,TclSubstTokens):
	* generic/tclParse.c (ParseTokens,Tcl_SubstObj,TclSubstTokens):
	* tests/subst.test (2.4, 8.7, 8.8, 11.4, 11.5):
	Substantial refactoring of Tcl_SubstObj to make use of the same
	parsing and substitution procedures as normal script evaluation.
	Tcl_SubstObj() moved to tclParse.c. New routine TclSubstTokens()
	created in tclParse.c which implements all substantial functioning of
	Tcl_EvalTokensStandard(). TclCompileScript() loses its "nested"
	argument, the Tcl_Interp struct loses its termOffset field and the
	TCL_BRACKET_TERM flag in the evalFlags field, all of which were only
	used (indirectly) by Tcl_SubstObj(). Tests subst-8.7,8.8,11.4,11.5
	modified to accomodate the only behavior change: reporting of parse
	errors now takes precedence over [return] and [continue] exceptions.
	All other behavior should remain compatible. [RFE 536831,684982] [Bug
	685106]

	* generic/tcl.h:        Removed TCL_PREFIX_IDENT and TCL_DEBUG_IDENT
	* win/tclWinPipe.c:     from tcl.h -- they are not part of Tcl's
	public interface.  Put them in win/tclWinPipe.c where they are used.

	* generic/tclInterp.c (Tcl_InterpObjCmd):       Corrected and added
	* tests/interp.test (interp-2.13):              test for option
	parsing beyond objc for [interp create --]. Thanks to Marco Maggi.
	[Bug 702383]

2003-03-11  Kevin Kenny  <kennykb@users.sourceforge.net>

	* win/makefile.vc: Added two missing uses of $(DBGX) so that
	tclpip8x.dll loads without panicking on Win9x.

2003-03-09  Kevin Kenny  <kennykb@users.sourceforge.net>

	* generic/tclTest.c (TestChannelCmd): Removed an unused local variable
	that caused compilation problems on some platforms.

2003-03-08  Don Porter  <dgp@users.sourceforge.net>

	* doc/tcltest.n:  Added missing "-body" to example. Thanks to Helmut
	Giese. [Bug 700011]

2003-03-07  Mo DeJong  <mdejong@users.sourceforge.net>

	* tests/io.test:
	* tests/ioCmd.test: Define a fcopy constraint and add it to the
	constraint list of any test that depends on the fcopy command. This is
	only useful to Jacl which does not support fcopy.

2003-03-07  Mo DeJong  <mdejong@users.sourceforge.net>

	* tests/encoding.test: Name temp files *.tcltestout instead of *.out
	so that when they are removed later, we don't accidently toast any
	files named *.out that the user has created in the build directory.

2003-03-07  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclCmdAH.c (Tcl_FileObjCmd): Fix the setting of a file's
	mtime and atime on 64-bit platforms. [Bug 698146]

2003-03-06  Mo DeJong  <mdejong@users.sourceforge.net>

	* tests/io.test: Doh! Undo accidental commenting out of a couple of
	tests.

2003-03-06  Mo DeJong  <mdejong@users.sourceforge.net>

	* tests/io.test: Define a fileevent constraint and add it to the
	constraint list of any test that depends on the fileevent command.
	This is only useful to Jacl which does not support fileevent.

2003-03-06  Mo DeJong  <mdejong@users.sourceforge.net>

	* tests/io.test: Define an openpipe constraint and add it to the
	constraint list of any test that creates a pipe using the open
	command. This is only useful to Jacl which does not support pipes.

2003-03-06  Don Porter  <dgp@users.sourceforge.net>

	* generic/TclUtf.c (Tcl_UniCharNcasecmp):       Corrected failure to
	* tests/utf.test (utf-25.*):    properly compare Unicode strings of
	different case in a case insensitive manner.  [Bug 699042]

2003-03-06  Kevin Kenny  <kennykb@users.sourceforge.net>

	* generic/tclCompCmds.c (TclCompileSwitchCmd):
	Replaced a non-portable 'bzero' with a portable 'memset'. [Bug 698442]

2003-03-06  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tclIO.c (Tcl_Seek, Tcl_OutputBuffered): If there is data
	buffered in the statePtr->curOutPtr member then set the BUFFER_READY
	flag in Tcl_Seek. This is needed so that the next call to FlushChannel
	will write any buffered bytes before doing the seek. The existing code
	would set the BUFFER_READY flag inside the Tcl_OutputBuffered
	function. This was a programming error made when Tcl_OutputBuffered
	was originally created in CVS revision 1.35. The setting of the
	BUFFER_READY flag should not have been included in the
	Tcl_OutputBuffered function.
	* generic/tclTest.c (TestChannelCmd): Use the Tcl_InputBuffered and
	Tcl_OutputBuffered util methods to query the amount of buffered input
	and output.

2003-03-06  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tclIO.c (Tcl_Flush): Compare the nextAdded member of the
	ChannelBuffer to the nextRemoved member to determine if any output has
	been buffered. The previous check against the value 0 seems to have
	just been a coding error. See other methods like Tcl_OutputBuffered
	for examples where nextAdded is compared to nextRemoved to find the
	number of bytes buffered.

2003-03-06  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tclIO.c (Tcl_GetsObj): Check that the eol pointer has not
	gone past the end of the string when in auto translation mode and the
	INPUT_SAW_CR flag is set. The previous code worked because the end of
	string value \0 was being compared to \n, this patch just skips that
	pointless check.

2003-03-06  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tclIO.c (WriteBytes, WriteChars, Tcl_GetsObj, ReadBytes):
	Rework calls to TranslateOutputEOL to make it clear that a boolean
	value is being returned. Add some comments in an effort to make the
	code more clear. This patch makes no functional changes.

2003-03-06  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tclIO.c (Tcl_SetChannelOption): Invoke the
	Tcl_SetChannelBufferSize method as a result of changing the
	-buffersize option to fconfigure. The previous implementation used
	some inlined code that reset the buffer size to the default size
	instead of ignoring the request as implemented in
	Tcl_SetChannelBufferSize.
	* tests/io.test: Update test case so that it actually checks the
	implementation of Tcl_SetChannelBufferSize.

2003-03-05  David Gravereaux  <davygrvy@pobox.com>

	* win/rules.vc: updated default tcl version to 8.5.

2003-03-05  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* generic/tclCompCmds.c (TclCompileSwitchCmd): First attempt at a
	bytecode-compiled switch command. It only handles the most common case
	of switching, but that should be enough for this to speed up a lot of
	people's code. It is expected that the speed gains come from two
	things: better handling of the switch itself, and integrated
	compilation of the arms instead of embedding separate bytecode
	sequences (i.e. better local variable handling.)
	* tests/switch.test (switch-10.*): Tests of both uncompiled and
	compiled switch behaviour. [Patch #644819]

	* generic/tclCompile.h (TclFixupForwardJumpToHere): Additional macro
	to make the most common kind of jump fixup a bit easier.

2003-03-04  Don Porter	<dgp@users.sourceforge.net>

	* README:				Bumped version number of
	* generic/tcl.h:			Tcl to 8.5a0.
	* library/init.tcl:
	* mac/README:
	* macosx/Tcl.pbproj/project.pbxproj:
	* tests/basic.test:
	* tools/configure.in:
	* tools/tcl.hpj.in:
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/README:
	* win/README.binary:
	* win/configure.in:
	* win/makefile.bc:
	* win/makefile.vc:
	* win/tcl.m4:

	* tools/configure:	autoconf
	* unix/configure:
	* win/configure:

2003-03-03  Jeff Hobbs  <jeffh@ActiveState.com>

	*** 8.4.2 TAGGED FOR RELEASE ***

2003-03-03  Daniel Steffen  <das@users.sourceforge.net>

	Mac OS Classic specific fixes:
	* generic/tclIOUtil.c (TclNewFSPathObj): on TCL_PLATFORM_MAC, skip
	potential directory separator at the beginning of addStrRep.
	* mac/tclMacChan.c (OpenFileChannel, CommonWatch): followup fixes to
	cut and splice implementation for file channels.
	* mac/tclMacFile.c (TclpUtime): pass native path to utime().
	* mac/tclMacFile.c (TclpObjLink): correctly implemented creation of
	alias files via new static proc CreateAliasFile().
	* mac/tclMacPort.h: define S_ISLNK macro to fix stat'ing of links.
	* mac/tclMacUtil.c (FSpLocationFromPathAlias): fix to enable stat'ing
	of broken links.

2003-03-03  Kevin Kenny  <kennykb@users.sourceforge.net>

	* win/Makefile.vc: corrected bug introduced by 'g' for debug builds.

2003-03-03  Don Porter	<dgp@users.sourceforge.net>

	* library/dde/pkgIndex.tcl:	dde bumped to version 1.2.1 for
	* win/tclWinDde.c:		bundled release with Tcl 8.4.2

	* library/reg/pkgIndex.tcl:	registry bumped to version 1.1.1 for
	* win/tclWinReg.c:		bundled release with Tcl 8.4.2

	* library/opt/pkgIndex.tcl:	updated package index to version 0.4.4

2003-02-28  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/configure:
	* win/configure.in: check for 'g' for debug build type, not 'd'.
	* win/rules.vc (DBGX): correct to use 'g' for nmake win makefile to
	match the cygwin makefile for debug builds. [Bug 635107]

2003-02-28  Vince Darley  <vincentdarley@users.sourceforge.net>

	* doc/file.n: subcommand is 'file volumes' not 'file volume'

2003-02-27  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclIOUtil.c (MakeFsPathFromRelative): removed dead code
	check of typePtr (darley).

	* tests/winTime.test: added note about PCI hardware dependency issues
	with high performance clock.

2003-02-27  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/lsearch.test (lsearch-10.7):
	* generic/tclCmdIL.c (Tcl_LsearchObjCmd): Stopped -start option from
	causing an option when used with an empty list. [Bug 694232]

2003-02-26  Chengye Mao <chengye.geo@yahoo.com>

	* win/tclWinInit.c: fixed a bug in TclpSetVariables by initializing
	dwUserNameLen with the sizeof(szUserName) before calling GetUserName.
	Don't know if this bug has been recorded: it caused crash in starting
	Tcl or wish in Windows.

2003-02-26  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclCmdMZ.c (TraceCommandProc): Fix mem leak when deleting a
	command that had trace on it. [Bug 693564] (sofer)

2003-02-25  Don Porter	<dgp@users.sourceforge.net>

	* doc/pkgMkIndex.n:	Modified [pkg_mkIndex] to use -nocase matching
	* library/package.tcl:	of -load patterns, to better accomodate common
	user errors due to confusion between [package names] names and [info
	loaded] names.

2003-02-25  Andreas Kupries  <andreask@pliers.activestate.com>

	* tests/pid.test: See below [Bug 678412].
	* tests/io.test: Made more robust against spaces in paths [Bug 678400]

2003-02-25  Miguel Sofer <msofer@users.sf.net>

	* tests/execute.test: cleaning up testobj's at the end, to avoid
	  leak warning by valgrind.

2003-02-22  Zoran Vasiljevic  <zoran@archiwrae.com>

	* generic/tclEvent.c (Tcl_FinalizeThread): Fix [Bug 571002]

2003-02-21  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* tests/binary.test (binary-44.[34]):
	* generic/tclBinary.c (ScanNumber): Fixed problem with unwanted
	sign-bit propagation when scanning wide ints. [Bug 690774]

2003-02-21  Daniel Steffen  <das@users.sourceforge.net>

	* mac/tclMacChan.c (TclpCutFileChannel, TclpSpliceFileChannel):
	Implemented missing cut and splice procs for file channels.

2003-02-21  Don Porter  <dgp@users.sourceforge.net>

	* library/package.tcl (tclPkgUnknown):  Minor performance tweaks to
	reduce the number of [file] invocations. Meant to improve startup
	times, at least a little bit. [Patch 687906]

2003-02-20  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tcl.m4:
	* unix/tclUnixPipe.c: (macosx) use vfork() instead of fork() to create
	new processes, as recommended by Apple (vfork can be up to 100 times
	faster thank fork on macosx).
	* unix/configure: regen.

2003-02-20  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclEncoding.c (LoadTableEncoding):
	* library/encoding/cp932.enc:      Correct jis round-trip encoding
	* library/encoding/euc-jp.enc:     by adding 'R' type to .enc files.
	* library/encoding/iso2022-jp.enc: [Patch 689341] (koboyasi, taguchi)
	* library/encoding/jis0208.enc:
	* library/encoding/shiftjis.enc:
	* tests/encoding.test:

	* unix/tclUnixChan.c (Tcl_MakeTcpClientChannel): add
	MakeTcpClientChannelMode that takes actual mode flags to avoid hang on
	OS X (may be OS X bug, but patch works x-plat). [Bug 689835] (steffen)

2003-02-20  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/regsub.n: Typo fix [Bug 688943]

2003-02-19  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/tclUnixThrd.c (TclpReaddir):
	* unix/tclUnixPort.h: update to Bug 689100 patch to ensure that there
	is a defined value of MAXNAMLEN (aka NAME_MAX in POSIX) and that we
	have some buffer allocated.

2003-02-19  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclStringObj.c: restored Tcl_SetObjLength() side-effect of
	always invalidating unicode rep (if the obj has a string rep). Added
	hasUnicode flag to String struct, allows decoupling of validity of
	unicode rep from buffer size allocated to it (improves memory
	allocation efficiency). [Bugs 686782, 671138, 635200]

	* macosx/Tcl.pbproj/project.pbxproj:
	* macosx/Makefile: reworked embedded build to no longer require
	relinking but to use install_name_tool instead to change the
	install_names for embedded frameworks. [Bug 644510]

	* macosx/Tcl.pbproj/project.pbxproj: preserve mod dates when running
	'make install' to build framework (avoids bogus rebuilds of dependent
	frameworks because tcl headers appear changed).

	* tests/ioCmd.test (iocmd-1.8): fix failure when system encoding is
	utf-8: use iso8859-1 encoding explicitly.

2003-02-18  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c (TclCompileExprWords): remove unused variable
	"range" [Bug 664743]
	* generic/tclExecute.c (ExprSrandFunc): remove unused variable
	"result" [Bug 664743]
	* generic/tclStringObj.c (UpdateStringOfString): remove unused
	variable "length" [Bug 664751]
	* tests/execute.test (execute-7.30): fix for [Bug 664775]

2003-02-18  Andreas Kupries  <andreask@activestate.com>

	* unix/tcl.m4: [Bug #651811] Added definition of _XOPEN_SOURCE and
	linkage of 'xnet' library to HP 11 branch. This kills a lot of
	socket-related failures in the testsuite when Tcl was compiled in 64
	bit mode (both PA-RISC 2.0W, and IA 64).

	* unix/configure: Regenerated.

2003-02-18  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclIO.c (HaveVersion): correctly decl static

	* unix/tclUnixThrd.c (TclpReaddir): reduce size of name string in tsd
	to NAME_MAX instead of PATH_MAX. [Bug 689100] (waters)

2003-02-18  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure: Regen.
	* unix/tcl.m4 (SC_ENABLE_THREADS): Make sure -lpthread gets passed on
	the link line when checking for the pthread_attr_setstacksize symbol.

2003-02-18  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclTest.c: cleanup of new 'simplefs' test code, and better
	documentation.

2003-02-17  Miguel Sofer <msofer@users.sf.net>

	* generic/tclBasic.c (TclRenameCommand): fixing error in previous
	commit.

2003-02-17  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclExecute.c (TclExecuteByteCode INST_STR_MATCH):
	* generic/tclCmdMZ.c (Tcl_StringObjCmd STR_MATCH):
	* generic/tclUtf.c (TclUniCharMatch):
	* generic/tclInt.decls:  add private TclUniCharMatch function that
	* generic/tclIntDecls.h: does string match on counted unicode
	* generic/tclStubInit.c: strings. Tcl_UniCharCaseMatch has the failing
	* tests/string.test:     that it can't handle strings or patterns with
	* tests/stringComp.test: embedded NULLs. Added tests that actually try
	strings/pats with NULLs. TclUniCharMatch should be TIPed and made
	public in the next minor version rev.

2003-02-17  Miguel Sofer <msofer@users.sf.net>

	* generic/tclBasic.c (TclRenameCommand): 'oldFullName' object was not
	being freed on all function exits, causing a memory leak. [Bug 684756]

2003-02-17  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tclIO.c (Tcl_GetsObj): Minor change so that eol is only
	assigned at the top of the TCL_TRANSLATE_AUTO case block. The other
	cases assign eol so this does not change any functionality.

2003-02-17  Kevin Kenny  <kennykb@users.sourceforge.net>

	* tests/notify.test: Removed Windows line terminators. [Bug 687913].

2003-02-15  Miguel Sofer <msofer@users.sf.net>

	* generic/tclBasic.c (Tcl_EvalEx):
	* generic/tclCompExpr.c (CompileSubExpr):
	* generic/tclCompile.c (TclCompileScript):
	* generic/tclParse.c (Tcl_ParseCommand, ParseTokens):
	* generic/tclParseExpr.c (ParsePrimaryExpr):
	* tests/basic.test (47.1):
	* tests/main.test (3.4):
	* tests/misc.test (1.2):
	* tests/parse.test (6.18):
	* tests/parseExpr.test (15.35):
	* tests/subst.test (8.6): Don Porter's fix for bad parsing of nested
	scripts. [Bug 681841]

2003-02-15  Kevin Kenny  <kennykb@users.sourceforge.net>

	* tests/notify.test (new-file):
	* generic/tclTest.c (TclTest_Init, EventtestObjCmd, EventtestProc,
	(EventTestDeleteProc):
	* generic/tclNotify.c (Tcl_DeleteEvents): Fixed Tcl_DeleteEvents not
	to get a pointer smash when deleting the last event in the queue.
	Added test code in 'tcltest' and a new file of test cases
	'notify.test' to exercise this functionality; several of the new test
	cases fail for the original code and pass for the corrected code. [Bug
	673714]

	* unix/tclUnixTest.c (TestfilehandlerCmd): Corrected a couple of typos
	in error messages. [Bug 596027]

2003-02-14  Jeff Hobbs  <jeffh@ActiveState.com>

	* README:		Bumped to version 8.4.2.
	* generic/tcl.h:
	* tools/tcl.wse.in:
	* unix/configure:
	* unix/configure.in:
	* unix/tcl.m4:
	* unix/tcl.spec:
	* win/README.binary:
	* win/configure:
	* win/configure.in:
	* macosx/Tcl.pbproj/project.pbxproj:

	* generic/tclStringObj.c (Tcl_GetCharLength): perf tweak

	* unix/tcl.m4: correct HP-UX ia64 --enable-64bit build flags

2003-02-14  Kevin Kenny  <kennykb@users.sourceforge.net>

	* win/tclWinTime.c: Added code to test and compensate for forward
	leaps of the performance counter. See the MSDN Knowledge Base article
	Q274323 for the hardware problem that makes this necessary on certain
	machines.
	* tests/winTime.test: Revised winTime-2.1 - it had a tolerance of
	thousands of seconds, rather than milliseconds. (What's six orders of
	magnitude among friends?) Both the above changes are triggered by a
	problem reported at:
	http://aspn.activestate.com/ASPN/Mail/Message/ActiveTcl/1536811
	although the developers find it difficult to believe that it accounts
	for the observed behavior and suspect a fault in the RTC chip.

2003-02-13  Kevin Kenny  <kennykb@users.sourceforge.net>

	* win/tclWinInit.c: Added conversion from the system encoding to
	tcl_platform(user), so that it works with non-ASCII7 user names. [Bug
	685926]

	* doc/tclsh.1: Added language to describe the handling of the
	end-of-file character \u001a embedded in a script file. [Bug 685485]

2003-02-11  Vince Darley  <vincentdarley@users.sourceforge.net>

	* tests/fileName.test:
	* unix/tclUnixFile.c: fix for [Bug 685445] when using 'glob -l' on
	broken symbolic links. Added two new tests for this bug.

2003-02-11  Kevin Kenny  <kennykb@users.sourceforge.net>

	* tests/http.test: Corrected a problem where http-4.14 would fail when
	run in an environment with a proxy server. Replaced references to
	scriptics.com by tcl.tk.

2003-02-11  Jeff Hobbs  <jeffh@ActiveState.com>

	* tests/lsearch.test:
	* generic/tclCmdIL.c (Tcl_LsearchObjCmd): protect against the case
	that lsearch -regepx list and pattern objects are equal.

	* tests/stringObj.test:
	* generic/tclStringObj.c (Tcl_GetCharLength): correct ascii char opt
	of 2002-11-11 to not stop early on \x00. [Bug 684699]

	* tests.parse.test: remove excess EOF whitespace

	* generic/tclParse.c (CommandComplete): more paranoid check to break
	on (p >= end) instead of just (p == end).

2003-02-11  Miguel Sofer <msofer@users.sf.net>

	* generic/tclParse.c (CommandComplete):
	* tests/parse.test: fix for [Bug 684744], by Don Porter.

2003-02-11  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclIOUtil.c (Tcl_FSJoinPath, Tcl_FSGetNormalizedPath):
	(UpdateStringOfFsPath): revert the cwdLen == 0 check and instead
	follow a different code path in Tcl_FSJoinPath.
	(Tcl_FSConvertToPathType, Tcl_FSGetNormalizedPath):
	(Tcl_FSGetFileSystemForPath): Update string rep of path objects before
	freeing the internal object. (darley)

	* tests/fileSystem.test: added test 8.3
	* generic/tclIOUtil.c (Tcl_FSGetNormalizedPath):
	(UpdateStringOfFsPath): handle the cwdLen == 0 case

	* unix/tclUnixFile.c (TclpMatchInDirectory): simplify the hidden file
	match check.

2003-02-10  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/configure:
	* win/configure.in: Generate error when attempting to build under
	Cygwin. The Cygwin port of Tcl/Tk does not build and people are filing
	bug reports under the mistaken impression that someone is actually
	maintaining the Cygwin port. A post to comp.lang.tcl asking someone to
	volunteer as an area maintainer has generated no results. Closing bugs
	680840, 630199, and 634772 and marking as "Won't fix".

2003-02-10  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/append.n: Return value was not documented. [Bug 683188]

2003-02-10  Vince Darley  <vincentdarley@users.sourceforge.net>

	* doc/FileSystem.3:
	* generic/tclIOUtil.c:
	* generic/tclInt.h:
	* tests/fileSystem.test:
	* unix/tclUnixFCmd.c:
	* unix/tclUnixFile.c:
	* win/tclWinFile.c: further filesystem optimization, applying [Patch
	682500]. In particular, these code examples are faster now:
	    foreach f $flist { if {[file exists $f]} {file stat $f arr;...}}
	    foreach f [glob -dir $dir *] { # action and/or recursion on $f }
	    cd $dir
	    foreach f [glob *] { # action and/or recursion on $f }
	    cd ..

	* generic/tclTest.c: Fix for [Bug 683181] where test suite left files
	in 'tmp'.

2003-02-08  Jeff Hobbs  <jeffh@ActiveState.com>

	* library/safe.tcl: code cleanup of eval and string comp use.

2003-02-07  Vince Darley  <vincentdarley@users.sourceforge.net>

	* win/tclWinFCmd.c: cleanup long lines
	* win/tclWinFile.c: sped up pure 'glob' by a factor of 2.5
	('foreach f [glob *] { file exists $f }' is still slow)
	* tests/fileSystem.text:
	* tests/fileName.test: added new tests to ensure correct behaviour in
	optimized filesystem code.

2003-02-07  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclTest.c:
	* tests/fileSystem.text: fixed test 7.2 to avoid a possible crash, and
	not change the pwd.

	* tests/http.text: added comment to test 4.15, that it may fail if you
	use a proxy server.

2003-02-06  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tclCompCmds.c (TclCompileIncrCmd):
	* tests/incr.test: Don't include the text "(increment expression)" in
	the errorInfo generated by the compiled version of the incr command
	since it does not match the message generated by the non-compiled
	version of incr. It is also not possible to match this error output
	under Jacl, which does not support a compiler.

2003-02-06  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tclExecute.c (TclExecuteByteCode): When an error is
	encountered reading the increment value during a compiled call to
	incr, add a "(reading increment)" error string to the errorInfo
	variable. This makes the errorInfo variable set by the compiled incr
	command match the value set by the non-compiled version.
	* tests/incr-old.test: Change errorInfo result for the compiled incr
	command case to match the modified implementation.
	* tests/incr.test: Add tests to make sure the compiled and
	non-compiled errorInfo messages are the same.

2003-02-06  Don Porter  <dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl:  Filename arguments to [outputChannel]
	and [errorChannel] (also -outfile and -errfile) were [open]ed but
	never [closed]. Also, [cleanupTests] could remove output or error
	files. [Bug 676978].
	* library/tcltest/pkgIndex.tcl: Bumped to version 2.2.2.

2003-02-05  Mo DeJong  <mdejong@users.sourceforge.net>

	* tests/interp.test:
	* tests/set-old.test: Run test cases that depend on hash order through
	lsort so that the tests also pass under Jacl. Does not change test
	results under Tcl.

2003-02-04  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclIOUtil.c:
	* generic/tclEvent.c:
	* generic/tclInt.h:
	* mac/tclMacFCmd.c:
	* unix/tclUnixFCmd.c:
	* win/tclWin32Dll.c:
	* win/tclWinFCmd.c:
	* win/tclWinInit.c:
	* win/tclWinInt.h:
	* tests/fileSystem.test: fix to finalization/unloading/encoding issues
	to make filesystem much less dependent on encodings for its cleanup,
	and therefore allow it to be finalized later in the exit process. This
	fixes fileSystem.test-7.1. Also fixed one more bug in setting of
	modification dates of files which have undergone cross-platform
	copies. [Patch 676271]

	* tests/basic.test:
	* tests/exec.test:
	* tests/fileName.test:
	* tests/io.test: fixed some test failures when tests are run from a
	directory containing spaces.

	* tests/fileSystem.test:
	* generic/tclTest.c: added regression test for the modification date
	setting of cross-platform file copies.

2003-02-03  Kevin Kenny  <kennykb@users.sourceforge.net>

	* generic/tclBasic.c: Changed [trace add command] so that 'rename'
	callbacks get fully qualified names of the command. [Bug 651271].
	***POTENTIAL INCOMPATIBILITY***
	* tests/trace.test: Modified the test cases for [trace add command] to
	expect fully qualified names on the 'rename' callbacks. Added a case
	for renaming a proc within a namespace.
	* doc/trace.n: Added language about use of fully qualified names in
	trace callbacks.

2003-02-01  Kevin Kenny  <kennykb@users.sourceforge.net>

	* generic/tclCompCmds.c: Removed an unused variable that caused
	compiler warnings on SGI. [Bug 664379]

	* generic/tclLoad.c: Changed the code so that if Tcl_StaticPackage is
	called to report the same package as being loaded in two interps, it
	shows up in [info loaded {}] in both of them (previously, it didn't
	appear in the static package list in the second).

	* tests/load.test Added regression test for the above bug. [Bug
	670042]

	* generic/tclClock.c: Fixed a bug that incorrectly allowed [clock
	clicks {}] and [clock clicks -] to be accepted as if they were [clock
	clicks -milliseconds].

	* tests/clock.test: Added regression tests for the above bug. [Bug
	675356]

	* tests/unixNotfy.test: Added cleanup of working files. [Bug 675609]

	* doc/Tcl.n: Added headings to the eleven paragraphs, to improve
	formatting in the tools that attempt to extract tables of contents
	from the manual pages. [Bug 627455]

	* generic/tclClock.c: Expanded mutex protection around the setting of
	env(TZ) and the thread-unsafe call to tzset(). [Bug 656660]

2003-01-31  Don Porter  <dgp@users.sourceforge.net>

	* tests/tcltest.test: Cleaned up management of file/directory
	creation/deletion to improve "-debug 1" output. [Bug 675614]
	The utility [slave] command failed to properly [list]-quote a
	constructed [open] command, causing failure when the pathname
	contained whitespace. [Bug 678415]

	* tests/main.test: Stopped main.test from deleting existing file. Test
	suite should not delete files that already exist. [Bug 675660]

2003-01-28  Don Porter  <dgp@users.sourceforge.net>

	* tests/main.test: Constrain tests that do not work on Windows. [Bug
	674387]

2003-01-28  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclIOUtil.c: fix to setting modification date in
	TclCrossFilesystemCopy. Also added 'panic' in
	Tcl_FSGetFileSystemForPath under illegal calling circumstances which
	lead to hard-to-track-down bugs.

	* generic/tclTest.c: added test suite code to allow exercising a
	vfs-crash-on-exit bug in Tcl's finalization caused by the encodings
	being cleaned up before unloading occurs.
	* tests/fileSystem.test: added new 'knownBug' test 7.1 to demonstrate
	the crash on exit.

2003-01-28  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tcl.h: Add TCL_PREFIX_IDENT and TCL_DEBUG_IDENT, used only
	by TclpCreateProcess.
	* unix/Makefile.in: Define TCL_DBGX.
	* win/Makefile.in: Define TCL_DBGX.
	* win/tclWinPipe.c (TclpCreateProcess): Check that the Tcl pipe dll
	actually exists in the Tcl bin directory and panic if it is not found.
	Incorporate TCL_DBGX into the Tcl pipe dll name. This fixes a really
	mysterious error that would show up when exec'ing a 16 bit application
	under Win95 or Win98 when Tcl was compiled with symbols. The error
	seemed to indicate that the executable could not be found, but it was
	actually the Tcl pipe dll that could not be found.

2003-01-26  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/README: Update msys+mingw URL to release 6. This version bundles
	gcc 3.

2003-01-26  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/configure: Regen.
	* win/configure.in: Add test that checks to see if the compiler can
	cast to a union type.
	* win/tclWinTime.c: Squelch compiler warning about union initializer
	by casting to union type when compiling with gcc.

2003-01-25  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tclIO.c (Tcl_CutChannel, Tcl_SpliceChannel): Invoke
	TclpCutFileChannel and TclpSpliceFileChannel.
	* generic/tclInt.h: Declare TclpCutFileChannel and
	TclpSpliceFileChannel.
	* unix/tclUnixChan.c (FileCloseProc, TclpOpenFileChannel,
	(Tcl_MakeFileChannel, TclpCutFileChannel, TclpSpliceFileChannel):
	Implement thread load data cut and splice for file channels. This
	avoids an invalid memory ref when compiled with -DDEPRECATED.
	* win/tclWinChan.c (FileCloseProc, TclpCutFileChannel,
	(TclpSpliceFileChannel): Implement thread load data cut and splice for
	file channels. This avoids an invalid memory ref that was showing up
	in the thread extension.

2003-01-25  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/tclWin32Dll.c (TclpCheckStackSpace, squelch_warnings):
	* win/tclWinChan.c (Tcl_MakeFileChannel, squelch_warnings):
	* win/tclWinFCmd.c (DoRenameFile, DoCopyFile, squelch_warnings):
	Re-implement inline ASM SEH handlers for gcc. The esp and ebp
	registers are now saved on the stack instead of in global variables so
	that the code is thread safe. Add additional checks when TCL_MEM_DEBUG
	is defined to be sure the values were recovered from the stack
	properly. Remove squelch_warnings functions and add a dummy call in
	the handler methods to squelch compiler warnings.

2003-01-25  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/configure:
	* win/configure.in: Define HAVE_ALLOCA_GCC_INLINE when we detect that
	no alloca function is found in malloc.h and we are compiling with GCC.
	Remove HAVE_NO_ALLOC_DECL define.
	* win/tclWin32Dll.c (TclpCheckStackSpace): Don't define alloca as a
	cdecl function. Doing this caused a tricky runtime bug because the
	_alloca function expects the size argument to be passed in a register
	and not on the stack. To fix this problem, we use inline ASM when
	compiling with gcc to invoke _alloca with the size argument loaded
	into a register.

2003-01-24  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/tclWinDde.c (Dde_Init): clarified use of tsdPtr.
	(DdeServerProc): better refcount handling of returnPackagePtr.

	* generic/tclEvent.c (Tcl_Finalize): revert finalize change on
	2002-12-04 to correct the issue with extensions that have TSD needing
	to finalize that before they are unloaded. This issue needs further
	clarification.

	* tests/unixFCmd.test: only do groups check on unix

2003-01-24  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclStringObj.c: proper fixes for Tcl_SetObjLength and
	Tcl_AttemptSetObjectLength dealing with string objects with both
	pure-unicode and normal internal representations. Previous fix didn't
	handle all cases correctly.
	* generic/tclIO.c: Add 'Tcl_GetString()' to ensure the object has a
	valid 'objPtr->bytes' field before manipulating it directly.

	This fixes [Bug 635200] and [Bug 671138], but may reduce performance
	of Unicode string handling in some cases. A further patch will be
	applied to address this, once the code is known to be correct.

2003-01-24  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/configure: Regen.
	* win/configure.in: Add test to see if alloca is undefined in
	malloc.h.
	* win/tclWin32Dll.c (TclpCheckStackSpace): Rework the SEH exception
	handler logic to avoid using the stack since alloca will modify the
	stack. This was causing a nasty bug that would set the exception
	handler to 0 because it tried to pop the previous exception handler
	off the top of the stack.

2003-01-23  Donal K. Fellows  <fellowsd@cs.man.ac.uk>

	* doc/lset.n: Fixed fault in return values from lset in documentation
	examples [SF Bug #658463] and tidied up a bit at the same time.

2003-01-21  Joe English  <jenglish@users.sourceforge.net>

	* doc/namespace.n (namespace inscope): Clarified documentation
	[Patch 670110]

2003-01-21  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/configure: Regen.
	* win/tcl.m4 (SC_CONFIG_CFLAGS): Set SHLIB_SUFFIX so that
	TCL_SHLIB_SUFFIX will be set to a useful value in the generated
	tclConfig.sh. Set SHLIB_LD_LIBS to "" or '${LIBS}' based on the
	--enable-shared flag. This matches the UNIX implementation.

2003-01-18  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclCkalloc.c: change %ud to %u as appropriate.

2003-01-17  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/tclWinDde.c (DdeServerProc): Deallocate the Tcl_Obj returned by
	ExecuteRemoteObject if it was not saved in a connection object.

2003-01-17  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tcl.h: Revert earlier change that defined TCL_WIDE_INT_TYPE
	as long long and TCL_LL_MODIFIER as L when compiling with mingw. This
	change ended up causing some test case failures when compiling with
	mingw.
	* generic/tclObj.c (UpdateStringOfWideInt): Describe the warning
	generated by mingw and why it needs to be ignored so that someone is
	not tempted to "fix" this problem again in the future.

2003-01-16  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclStringObj.c: Tcl_SetObjLength fix for when the object has
	a unicode string rep. [Bug 635200]
	* tests/stringObj.test: removed 'knownBug' constraint from test 14.1
	now that this bug is fixed.

	* generic/tclInt.h:
	* generic/tclBasic.c:
	* generic/tclCmdMZ.z:
	* tests/trace.test: execution and command tracing bug fixes and
	cleanup. In particular fixed [Bug 655645], [Bug 615043], [Bug 571385]
	  - fixed some subtle cleanup problems with tracing. This required
	    replacing Tcl_Preserve/Tcl_Release with a more robust refCount
	    approach. Solves at least one known crash caused by memory
	    corruption.
	  - fixed some confusion in the code between new style traces (Tcl
	    8.4) and the very limited 'Tcl_CreateTrace' which existed before.
	  - made behaviour consistent with documentation (several tests even
	    contradicted the documentation before).
	  - fixed some minor error message details
	  - added a number of new tests

2003-01-16  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/tclWinSerial.c (SerialOutputProc): add casts for bytesWritten to
	allow strict compilation (no warnings).

	* tests/winDde.test:
	* win/tclWinDde.c (Tcl_DdeObjCmd): Prevent crash when empty service
	name is passed to 'dde eval' and goto errorNoResult in request and
	poke error cases to free up any allocated data.

2003-01-16  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/tclWin32Dll.c (squelch_warnings): Squelch compiler warnings from
	SEH ASM code.
	* win/tclWinChan.c (squelch_warnings): Squelch compiler warnings from
	SEH ASM code.
	* win/tclWinDde.c: Add casts to avoid compiler warnings. Pass pointer
	to DWORD instead of int to avoid compiler warnings.
	* win/tclWinFCmd.c (squelch_warnings): Add casts and fixup decls to
	avoid compiler warnings. Squelch compiler warnings from SEH ASM code.
	* win/tclWinFile.c: Add casts and fixup decls to avoid compiler
	warnings. Remove unused variable.
	* win/tclWinNotify.c: Declare as DWORD instead of int to avoid
	compiler warning.
	* win/tclWinReg.c: Add casts to avoid compiler warning. Fix assignment
	in if expression bug.
	* win/tclWinSerial.c: Add casts to avoid compiler warnings. Remove
	unused variable.
	* win/tclWinSock.c: Add casts and fixup decls to avoid compiler
	warnings.

2003-01-14  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclClock.c (FormatClock): corrected typo that incorrectly
	conditionally defined savedTZEnv and savedTimeZone.

2003-01-13  Mo DeJong  <mdejong@users.sourceforge.net>

	Fix mingw build problems and compiler warnings.

	* generic/tcl.h: Add if defined(__MINGW32__) check to code that sets
	the TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER.
	* generic/tclClock.c (FormatClock): Don't define savedTimeZone and
	savedTZEnv if we are not going to use them.
	* generic/tclEnv.c: Add cast to avoid warning.
	* win/tclWinChan.c: Use DWORD instead of int to avoid compiler warning
	* win/tclWinThrd.c: Only define allocLock, allocLockPtr, and dataKey
	when TCL_THREADS is defined. This avoid a compiler warning about
	unused variables.

2003-01-12  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/README: Update msys + mingw URL, the new release includes the
	released 1.0.8 version of msys which includes a number of bug fixes.

2003-01-12  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/configure: Regen.
	* win/tcl.m4 (SC_CONFIG_CFLAGS): Pull in addition of shell32.lib to
	LIBS_GUI that was added to the Tk tcl.m4 but never made it back into
	the Tcl version.

2003-01-12  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tcl.h: Skip Tcl's define of CHAR, SHORT, and LONG when
	HAVE_WINNT_IGNORE_VOID is defined. This avoids a bunch of compiler
	warnings when building with Cygwin or Mingw.
	* win/configure: Regen.
	* win/configure.in: Define HAVE_WINNT_IGNORE_VOID when we detect a
	winnt.h that still defines CHAR, SHORT, and LONG when VOID has already
	been defined.
	* win/tcl.m4 (SC_LOAD_TCLCONFIG): Subst the TCL_DEFS loaded from
	tclConfig.sh so that Tcl defines can make it into the Tk Makefile.

2003-01-12  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/configure: Regen.
	* win/configure.in: Check for typedefs like LPFN_ACCEPT in winsock2.h
	and define HAVE_NO_LPFN_DECLS if not found.
	* win/tclWinSock.c: Define LPFN_* typedefs if HAVE_NO_LPFN_DECLS is
	defined. This fixes the build under Mingw and Cygwin, it was broken by
	the changes made on 2002-11-26.

2003-01-10  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclIOUtil.c:
	* win/tclWinInt.h:
	* win/tclWinInit.c: fix to new WinTcl crash on exit with vfs,
	introduced on 2002-12-06. Encodings must be cleaned up after the
	filesystem.

	* win/makefile.vc: fix to minor VC++ 5.2 syntax problem

2003-01-09  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompCmds.c (TclCompileReturnCmd):  Corrected off-by-one
	problem with recent commit. [Bug 633204]

2003-01-09  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFileName.c: remove unused variable 'macSpecialCase'
	[Bug 664749]

	* generic/tclIOUtil.c:
	* generic/tclInt.h:
	* unix/tclUnixFile.c:
	* mac/tclMacFile.c:
	* win/tclWinFile.c:
	* win/tclWinInt.h:
	* win/tclWin32Dll.c:
	* tests/cmdAH.test: fix to non-ascii chars in paths when setting mtime
	and atime through 'file (a|m)time $path $time'. [Bug 634151]

2003-01-08  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclExecute.c (TclExprFloatError):  Use the IS_NAN macro for
	greater clarity of code.

2003-01-07  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompCmds.c (TclCompileReturnCmd):
	* tests/compile.test:	Corrects failure of bytecompiled [catch
	{return}] to have result TCL_RETURN (not TCL_OK) [Bug 633204]. This
	patch is a workaround for 8.4.X. A new opcode INST_RETURN is a better
	long term solution for 8.5 and later.

2003-01-04  David Gravereaux  <davygrvy@pobox.com>

	* win/makefile.vc:
	* win/rules.vc:  Fixed INSTALLDIR macro problem that blanked itself by
	accident causing the install target to put the tree at the root of the
	drive built on. Whoops..

	Renamed the 'linkexten' option to be 'staticpkg'. Added 'thrdalloc' to
	allow the switching _on_ of the thread allocator. Under testing, I
	found it not to be benificial under windows for the purpose of the
	application I was using it for. It was more important for this app
	that resources for tcl threads be returned to the system rather than
	saved/moved to the global recycler. Be extra clean or extra fast for
	the default threaded build? Let's move to clean and allow it to be
	switched on for users who find it benificial for their use of threads.

	******************************************************************
	*** CHANGELOG ENTRIES FOR 2002 IN "ChangeLog.2002"             ***
	*** CHANGELOG ENTRIES FOR 2001 IN "ChangeLog.2001"             ***
	*** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000"             ***
	*** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" ***
	******************************************************************

Deleted ChangeLog.2004.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
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
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
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
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
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
2004-12-29  Jeff Hobbs	<jeffh@ActiveState.com>

	* win/tcl.m4, win/configure: update MSVC CFLAGS_OPT to -O2, remove -Gs
	(included in -O2) and -GD (outdated). Use "link -lib" instead of "lib"
	binary and remove -YX for MSVC7 portability. Add -fomit-frame-pointer
	for gcc OPT compiles. [Bug 1092952, 1091967] Align LIBS_GUI with Tk
	head needs.

2004-12-29  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclDate.c: Regen
	* generic/tclGetDate.y (TclDatelex): Fixed a problem where a
	four-digit group with >=2 leading zeroes appeared to be a two-digit
	group, leading to misinterpreting the time 0012 as 1200. [Bug 1090413]
	* library/clock.tcl: Added code to interpret correctly months outside
	the range 01-12 as reduced modulo 12 with a corresponding adjustment
	to the year. [Bug 1092789]
	* tests/clock.test: Added regression test cases for the above two bugs
	* unix/Makefile.in: Added --no-lines to the 'bison' command line to
	* win/Makefile.in: help constrain the number of diffs in a cvs checkin

2004-12-24  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c:
	* generic/tclInt.h:
	* generic/tclLiteral.c:
	* generic/tclProc.c:
	Avoid sharing cmdName literals accross namespaces, and generalise
	usage of the TclRegisterNewLiteral macro. [Patch 1090905]

2004-12-20  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c: moved TclInitCompiledLocals to tclProc.c
	* generic/tclProc.c: new static InitCompiledLocals to allow for a
	single pass over the proc's arguments at proc load time (instead of
	two as previously). TclObjInterpProc() now allocates the
	compiledLocals on the tcl execution stack, using the new
	TclStackAlloc/Free functions.

2004-12-16  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclInterp.c (Tcl_LimitSetTime, TimeLimitCallback):
	(TclLimitRemoveAllHandlers, TclInitLimitSupport): Set a timer event to
	trigger when the time limit runs out. All the time limit actually does
	is check to see if the time limit has been exceeded, but this is
	enough to fix [Bug 1085023].
	* generic/tclInt.h (struct Interp): Added a field to hold the token
	for the timer event handler associated with the current time limit.
	* generic/tclEvent.c (Tcl_UpdateObjCmd, Tcl_VwaitObjCmd): Add error
	message when limit exceeded.
	* tests/interp.test (interp-34.[89]): Check that time limits handle
	the two cases reported in [Bug 1085023]

	* generic/tclTimer.c (TclCreateAbsoluteTimerHandler): New internal
	function that allows setting a timer handler that will be triggered at
	(or after) a specific time instead of at some number of milliseconds
	in the future. This is a candidate for future exposure via a TIP.

2004-12-15  Miguel Sofer <msofer@users.sf.net>

	* generic/tclBasic.c:
	* generic/tclExecute.c:
	* generic/tclInt.decls:
	* generic/tclIntDecls.h:
	* generic/tclNamesp.c:
	* generic/tclProc.c:
	* generic/tclStubInit.c:
	* generic/tclTest.c: Added two new functions to allocate memory from
	the execution stack (TclStackAlloc, TclStackFree). Added functions
	TclPushStackFrame and TclPopStackFrame that do the work of
	Tcl_PushCallFrame and Tcl_PopCallFrame, but using frames allocated in
	the execution stack - i.e., heap instead of C-stack. The core uses
	these two new functions exclusively; the old ones remain for backwards
	compat, as at least two popular extensions (itcl, xotcl) are known to
	use them.

2004-12-14  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCmdIL.c:
	* generic/tclInt.h:
	* generic/tclProc.c:
	* generic/tclVar.c: changing the isProcCallFrame field of the
	CallFrame struct from a 0/1 field to flags. Should be perfectly
	backwards compatible.

2004-12-14  Don Porter	<dgp@users.sourceforge.net>

	* unix/configure.in: Added special processing to remove "$U" from
	libraries in the LIBOBJS value. This is an auto-make-ism we need to
	avoid. [Bug 1081541]

	* unix/configure: autoconf-2.57

2004-12-13  Don Porter	<dgp@users.sourceforge.net>

	* generic/tcl.h: Restored extern "C" guards so that C++ code sees
	function pointer typedef linkage consistent with earlier Tcl releases.
	[Bug 1082349]

	* generic/tclEncoding.c: Plugged some memory leaks. Thanks to Rolf Ade
	* generic/tclUtil.c:	 for reports and testing [Bug 1083082]

2004-12-13  Kevin B. Kenny  <kennykb@acm.org>

	* doc/clock.n: Clarify that the [clock scan] command does not accept
	the full range of ISO8601 point-in-time formats. [Bug 1075433]

2004-12-12  Miguel Sofer <msofer@users.sf.net>

	* generic/tclVar.c (TclArrayObjCmd - ARRAY_NAMES): leaking an object
	[Bug 1084111] - thanks to Rolf Ade.

2004-12-12  Miguel Sofer <msofer@users.sf.net>

	* generic/tclObj.c (TclSetCmdNameObj): special handling for fully
	qualified command names (as in fix [Patch 456668]).

2004-12-11  Miguel Sofer <msofer@users.sf.net>

	* generic/tclInt.h:
	* generic/tclNamesp.c: converting the static function
	GetNamespaceFromObj() to MODULE_SCOPE TclGetNamespaceFromObj().

2004-12-10  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tools/tcl.wse.in, unix/tcl.spec, win/README.binary, README:
	* win/configure.in, unix/configure.in, generic/tcl.h:
	Bumped version number to 8.5a3 to distinguish HEAD of CVS development
	from the recent 8.5a2 release.

2004-12-10  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c (TclInitCompiledLocals):
	* generic/tclCompile.h:
	* generic/tclInt.h:
	* generic/tclProc.c (TclObjInterpProc, TclCreateProc): optimised
	loops that initialise a proc's arguments and compiled local
	variables, removing tests from inner loops.

2004-12-10  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclInt.h: Move ensemble API decls here from tclNamesp.c

2004-12-09  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclNamesp.c (TclMakeEnsembleCmd, TclSetEnsemble*)
	(TclSetEnsemble*, TclFindEnsemble): Build an internal API for creating
	and manipulating ensembles; they can be deleted using the normal
	command-deletion API.

	* doc/Async.3: Reword for better grammar, better nroff and get the
	flag name right. (Reported by David Welton.)

2004-12-07  Don Porter	<dgp@users.sourceforge.net>

	* tests/unixInit.test (2.1-4): Added constraints so that when a value
	of TCL_LIBRARY is required for process initialization, we skip the
	tests that mess with that value.

2004-12-07  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	*** 8.5a2 TAGGED FOR RELEASE ***

	* unix/Makefile.in: add library/{tzdata,msgs} to dist target (kbk)

	* doc/foreach.n: Adjust tabs to be friendlier to some HTML
	converters. [Bug 1078760]

2004-12-06  Jeff Hobbs	<jeffh@ActiveState.com>

	* unix/tclUnixNotfy.c (NotifierThreadProc): init numFdBits
	[Bug 1079286]

	* doc/error.n, doc/SaveResult.3, doc/Thread.3: minor nroff typos

2004-12-06  Don Porter	<dgp@users.sourceforge.net>

	* tests/safe.test:	Trim auto_path to improve performance [1080039]

	* tests/msgcat.test:	makeFile/removeFile cleanup [1079117]

2004-12-04  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclEncoding.c:	Different fix for [Bug 1077005].
	* generic/tclEvent.c:	Broke apart TclpSetInitialEncodings() on
	* generic/tclInt.h:	Windows into TclpSetInterfaces(), that is
	* unix/tclUnixInit.c:	fundamentally essential, and the initialization
	* win/tclWinInit.c:	of the system encoding, which is not. Made
	the TclpSetInterfaces call part of TclInitSubsystems so it cannot be
	overlooked.

2004-12-03  Jeff Hobbs	<jeffh@ActiveState.com>

	* changes: updated for 8.5a2 release

2004-12-02  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclUtil.c (TclSetProcessGlobalValue): Handle the case where
	a ProcessGlobalValue might be assigned to itself.

	* generic/tclEncoding.c (MakeFileMap): Correct refcounting errors
	managing values returned by TclPathPart (with refCount of 1!) that led
	to a memory leak. [Bug 1077474].

2004-12-02  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclPathObj.c:  fix and new tests for [Bug 1074671] to ensure
	* tests/fileSystem.test: tilde paths are not returned specially by
	'glob'.

2004-12-02  Kevin B. Kenny  <kennykb@acm.org>

	* win/Makefile.in: Added a 'sed' in the setting of ROOT_DIR_NATIVE to
	compensate for a bug in cygpath (at least version 1.36) that leaves a
	trailing backslash on the end of the converted path.

2004-12-02  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclInterp.c (Alias,Target,Master): Rewrote these so that the
	aliases that refer to an interpreter are stored in a list and not a
	hashtable (which was only ever a convenience, and forced the use of a
	global mutex to generate keys!) [FRQ 1077210]
	* generic/tclNamesp.c (numNsCreated): Moved into thread-local storage
	to remove a global mutex. [FRQ 1077210]

2004-12-01  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclUtil.c (TclGetProcessGlobalValue): Narrowed the scope of
	mutex locks.

	* generic/tclUtil.c:		Updated Tcl_GetNameOfExecutable() to
	* generic/tclEncoding.c:	make use of a ProcessGlobalValue for
	* generic/tclEvent.c:		storing the executable name. Added
	internal routines Tcl(Get|Set)ObjNameOfExecutable() to access that
	storage in Tcl_Obj, rather than string format.

	* unix/tclUnixFile.c:	Rewrote TclpFindExecutable() to use
	* win/tclWinFile.c:	TclSetObjNameOfExecutable to store the
	executable name it computes.

	* generic/tclInt.h:	Added internal stub entries for
	* generic/tclInt.decls: TclpFindExecutable and
	Tcl(Get|Set)ObjNameOfExecutable.

	* generic/tclIntDecls.h: make genstubs
	* generic/tclStubInit.c:

	* generic/tclCmdIL.c:	Retrieve executable name in Tcl_Obj form
	* win/tclWinPipe.c:	instead of string form.

	* unix/tclUnixTest.c:	Update [testfindexecutable] command to use new
	internal interfaces.

	* generic/tclEncoding.c:	Moved TclpSetInitialEncodings() call
	from Tcl_FindExecutable() into TclInitEncodingSubsystem(). This is
	important on Windows where it establishes whether the "ascii" or
	"unicode" set of system routines will be used, and that needs to be
	done earlier to support filesystem operations. [Bug 1077005]

2004-12-01  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tests/winDde.test: Rewritten to use tcltest2 features more
	thoroughly (reducing the [catch] count!) and fix the problem with
	winDde-6.1 being out of synch with the implementation.

2004-11-30  Don Porter	<dgp@users.sourceforge.net>

	* library/init.tcl ([unknown]): Restored the save/restore of the
	variables ::errorCode and ::errorInfo. This is needed when the
	[::bgerror] command is auto-loaded (as it is by Tk).

	Patch 976520 reworks several of the details involved with
	startup/initialization of the Tcl library, focused on the activities
	of Tcl_FindExecutable().

	* generic/tclIO.c:	Removed bogus claim in comment that encoding
	"iso8859-1" is "built-in" to Tcl.

	* generic/tclInt.h:	Created a new struct ProcessGlobalValue,
	* generic/tclUtil.c:	routines Tcl(Get|Set)ProcessGlobalValue, and
	function type TclInitProcessGlobalValueProc. Together, these take care
	of the housekeeping for "values" (things that can be held in a
	Tcl_Obj) that are global across a whole process. That is, they are
	shared among multiple threads, and epoch and mutex protection must
	govern the validity of cached copies maintained in each thread.

	* generic/tclNotify.c:	Modified TclInitNotifier() to tolerate being
	called multiple times in the same thread.
	* generic/tclEvent.c:	Dropped the unused argv0 argument to
	TclInitSubsystems(). Removed machinery to unsure only one
	TclInitNotifier() call per thread, now that that is safe. Converted
	Tcl(Get|Set)LibraryPath to use a ProcessGlobalValue, and moved them to
	tclEncoding.c.
	* generic/tclBasic.c:	Updated caller.

	* generic/tclInt.h:	TclpFindExecutable now returns void.
	* unix/tclUnixFile.c:
	* win/tclWinFile.c:
	* win/tclWinPipe.c:

	* generic/tclEncoding.c: Built new encoding search initialization on a
	foundation of ProcessGlobalValues, exposing new routines
	Tcl(Get|Set)EncodingSearchPath. A cache of a map from encoding name to
	directory pathname keeps track of where encodings are available for
	loading. Tcl_FindExecutable greatly simplified into just three
	function calls. The "library path" is now misnamed, as its only
	remaining purpose is as a foundation for the default encoding search
	path.

	* generic/tclInterp.c:	Inlined the initScript that is evaluated by
	Tcl_Init(). Added verification after initScript evaluation that Tcl
	can find its installed *.enc files, and that it has initialized
	[encoding system] in agreement with what the environment expects.
	[tclInit] no longer driven by the value of $::tcl_libPath; it largely
	constructs its own search path now, rather than attempt to share one
	with the encoding system.

	* unix/tclUnixInit.c:	TclpSetInitialEncodings factored so that a new
	* win/tclWinInit.c:	routine TclpGetEncodingNameFromEnvironment can
	reveal that Tcl thinks the [encoding system] should be, even when an
	incomplete encoding search path, or a missing *.enc file won't allow
	that initialization to succeed. TclpInitLibraryPath reworked as an
	initializer of a ProcessGlobalValue.

	* unix/tclUnixTest.c:	Update implementations of [testfindexecutable],
	[testgetdefenc], and [testsetdefenc].

	* tests/unixInit.test:	Corrected tests to operate properly even when
	a value of TCL_LIBRARY is required to find encodings.

	* generic/tclInt.decls: New internal stubs: TclGetEncodingSearchPath,
	TclSetEncodingSearchPath, TclpGetEncodingNameFromEnvironment. These
	are candidates for public exposure by future TIPs.

	* generic/tclIntDecls.h: make genstubs
	* generic/tclStubInit.c:

	* generic/tclTest.c:	Updated [testencoding] to use
	* tests/encoding.test:	Tcl(Get|Set)EncodingSearchPath.	 Updated tests.

2004-11-30  Kevin B. Kenny  <kennykb@acm.org>

	* library/clock.tcl: Corrected the regular expressions that match a
	time zone to allow for time zones specified as +HH or -HH.
	* tests/clock.test: Added regression test case for the above issue.
	Thanks to Rolf Ade for reporting this issue [http://wiki.tcl.tk/13094]
	* win/tclWinDde.c (Tcl_DdeObjCmd): Corrected a typo that caused a
	compilation failure on VC++.

2004-11-29  Andreas Kupries <andreask@activestate.com>

	* win/Makefile.in (install-libraries): Brought entry '2004-10-26 Don
	Porter (Tcl Modules)' into the windows world, actually the
	win/configure buildsystem. The other windows buildsystems (.vc, .bc)
	still have to be updated as well.

2004-11-26  Andreas Kupries <andreask@activestate.com>

	* win/tclWinDde.c (ExecuteRemoteObject): Removed bogus semicolon found
	at the end of the header for the function definition, terminating it
	early and preventing a compile. This is likely a fix for '2004-11-25
	Donal'. I have to conclude that it is also unknown if the other
	changes to this file actually pass the testsuite. Running testsuite
	... They don't. winDde-6.1 fails. This is only a message discrepance,
	i.e. not too bad. Leaving resolution of that to Pat and Donal.

2004-11-26  Don Porter	<dgp@users.sourceforge.net>

	* library/auto.tcl (tcl_findLibrary): Made sure the uniquifying
	operations on the search path does not also normalize. [Bug 1072136]

2004-11-26  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* unix/configure.in: Simplify the code to check for correctness of
	strstr, strtoul and strtod.
	* unix/tcl.m4 (SC_TCL_CHECK_BROKEN_FUNC): Split a complex stanza out
	of configure.in into its own function. Also force it to do the right
	thing with cacheing of results of AC_TRY_RUN to deal with issue raised
	in [Patch 1073524]

	* doc/foreach.n: Added simple example. [FRQ 1073334]

2004-11-25  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclProc.c (TclObjInterpProc):	    Make it so that only
	* generic/tclIndexObj.c (Tcl_WrongNumArgs): [proc] instances do
	* tests/indexObj.test (indexObj-5.7):	    quoting of their first
	arguments, so keeping [Bug 942757] fixed and making [Bug 1066837] be
	fixed as well. Done with a load of #ifdef-ery because this hack is so
	ugly nobody should keep it around once Itcl's fixed.

2004-11-25  Reinhard Max  <max@suse.de>

	* tests/tcltest.test: The order in which [glob] returns the file names
	is undefined, so tests should not depend on it.

2004-11-25  Zoran Vasiljevic <vasiljevic@users.sf.net>

	* doc/Thread.3:
	* doc/Notifier.3: Added changes from the core-8-4-branch

2004-11-25  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/dde.n: Synchronized the documentation of the commands with the
	header of the docs and what the package actually does. Thanks to
	Andreas Kupries for spotting this.
	* win/tclWinDde.c (Tcl_DdeObjCmd): Much cleanup of argument parsing
	code.

2004-11-24  David Gravereaux <davygrvy@pobox.com>

	* generic/tclPort.h: Relative include of tclWinPort.h returned as it
	was requiring me set -I$(tcl_root)/win for my extensions that need to
	include tclInt.h and doesn't appear to serve any purpose for windows
	builds.

2004-11-24  Kevin B. Kenny  <kennykb@acm.org>

	* unix/tcl.m4 (SC_ENABLE_THREADS): Corrected bad check for 3-argument
	readdir_r [Bug 1001325].
	* unix/configure: Regenerated.
	* unix/tclUnixNotfy.c: Corrected all uses of 'select' to manage their
	masks using the FD_CLR, FD_ISSET, FD_SET, and FD_ZERO macros rather
	than bit-whacking that failed under Solaris-Sparc-64. [Bug 1071807]
	* win/tclWinInit.c (TclpInitLibraryPath): Removed unused vars 'pathc'
	and 'pathv' that caused compilation problems on VC++ with
	--enable-symbols.

2004-11-24  Don Porter	<dgp@users.sourceforge.net>

	* unix/tcl.m4 (SC_ENABLE_THREADS): Corrected failure to determine the
	number of arguments for readdir_r on SunOS systems. [Bug 1071701]

	* unix/configure:	autoconf-2.57

	* generic/tclCmdIL.c (InfoVarsCmd):	Corrected segfault in new
	* tests/info.test (info-19.6):	trivial matching branch [Bug 1072654]

2004-11-24  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tools/man2html.tcl, tools/man2html1.tcl: Update to use Tcl 8.4.
	* tools/man2html2.tcl: Fix broken .SS handling.

2004-11-23  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* unix/Makefile.in: Add (commented-out) code to integrate tclConfig.h
	into the dependency tree and 'make distclean'. [Bug 1068171]

	* generic/tclResult.c (Tcl_AppendResultVA): Remove call to
	Tcl_GetStringResult to speed up repeated calls to Tcl_AppendResult
	with the side effect that code that wants to access interp->result
	should always call Tcl_GetStringResult first. See [Patch 1041072]
	discussion for more details.

2004-11-22  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure: Regen.
	* unix/tcl.m4 (SC_TCL_64BIT_FLAGS): Define HAVE_TYPE_OFF64_T only when
	off64_t, open64(), and lseek64() are defined. IRIX 5.3 is known to not
	include an open64 function. [Bug 1030465]

2004-11-22  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure: Regen.
	* unix/tcl.m4 (SC_ENABLE_THREADS): Check for a 2 argument version of
	readdir_r that is known to exists under IRIX 5.3.
	* unix/tclUnixThrd.c (TclpReaddir): Use either 2 arg or 3 arg version
	of readdir_r. [Bug 1001325]

2004-11-22  Don Porter	<dgp@users.sourceforge.net>

	* unix/tclUnixInit.c (TclpInitLibraryPath): Purged dead code that used
	* win/tclWinInit.c (TclpInitLibraryPath):  to extend the "library
	path". Search path construction for init.tcl is now done within the
	[tclInit] proc.
	* generic/tclInterp.c:	Restored several directories to the search
	* tests/unixInit.test:	path used to locate init.tcl within [tclInit].
	This change does not restore any directories to the encoding search
	path, so should still avoid the price of an unreasonably large number
	of filesystem accesses during encoding initialization at startup
	[Bug 976438]

2004-11-22  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclPathObj.c: fix and new test for [Bug 1043129] in the
	* tests/fileSystem.test: treatment of backslashes in file join on
	Windows.

2004-11-21  Don Porter	<dgp@users.sourceforge.net>

	* doc/AddErrInfo.3:	Typo corrections (Thanks Daniel South).
	* doc/interp.n:

2004-11-19  Don Porter	<dgp@users.sourceforge.net>

	* doc/AddErrInfo.3:	Docs for Tcl_(Get|Set)ReturnOptions. [TIP 227]

	* doc/AddErrInfo.3:
	* doc/Async.3:		Documentation updates to replace references
	* doc/BackgdErr.3:	to global variable ::errorInfo and ::errorCode
	* doc/SaveResult.3:	and to the ::bgerror command with references
	* doc/after.n:		to their preferred replacements, the
	* doc/bgerror.n:	-errorinfo and -errorcode return options,
	* doc/error.n:		the Tcl_*InterpState routines, and the
	* doc/exec.n:		[interp bgerror] command.
	* doc/exit.n:
	* doc/fileevent.n:
	* doc/interp.n:
	* doc/return.n:
	* doc/tclvars.n:
	* doc/update.n:

	* tests/unixInit.test: Removed "knownBug" constraints to prompt bug
	fixing before 8.5a2 release.

2004-11-19  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Makefile:
	* unix/configure.in:
	* unix/tclUnixInit.c (MacOSXGetLibraryPath): changed detection of tcl
	framework build when determining tclLibPath from overloaded
	TCL_LIBRARY to configuration define TCL_FRAMEWORK. [Bug 1068088]

	* unix/configure: autoconf-2.57
	* unix/tclConfig.h.in: autoheader-2.57

2004-11-18  Don Porter	<dgp@users.sourceforge.net>

	* doc/SaveResult.3:	Documentation for Tcl_*InterpState (TIP 226).

	* generic/tclEvent.c (HandleBgErrors):	Simplified program flow.

	* tests/basic.test:	Updated functional (not testing) uses of
	* tests/io.test:	[bgerror] to make use of [interp bgerror].
	* tests/socket.test:
	* tests/timer.test:

	* tests/interp.test (interp-36.*):	[interp bgerror] tests.

	* generic/tclInterp.c:	Corrected [interp bgerror] error messages.

2004-11-18  Reinhard Max  <max@suse.de>

	* unix/tcl.m4 (SC_CONFIG_MANPAGES): Applied an improved version of
	* unix/configure.in:		    [Patch 996085], that introduces
	* unix/Makefile.in:		    --enable-man-suffix.

	* unix/installManPage:		    added
	* unix/mkLinks.tcl:		    removed
	* unix/mkLinks:			    removed
	* unix/configure:		    generated

	* unix/Makefile.in:		    Don't install tclConfig.h .

2004-11-17  Don Porter	<dgp@users.sourceforge.net>

	* unix/configure.in: The change below reveals that the public data
	type Tcl_StatBuf relies on config information. For now, disabled the
	use of the tclConfig.h file until its full impact on Tcl's interface
	can be assessed.

	* unix/configure:	autoconf-2.57

	* generic/tcl.h:	Moved the #include "tclConfig.h" out of
	* generic/tclInt.h:	tcl.h.	The config settings are not part of
	* generic/tclPort.:	the public interface, and having it there
	breaks compiled against uninstalled Tcl and extensions using
	autoconf-2.5*.

2004-11-16  Jeff Hobbs	<jeffh@ActiveState.com>

	* unix/tclUnixChan.c (TtySetOptionProc): fixed crash configuring
	-ttycontrol on a channel. [Bug 1067708]

2004-11-16  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclIOUtil.c (TclFSEpochOk): There were two code paths via
	which the thread copy of filesystemEpoch could be synched with the
	master copy, but only one kept the filesystem list cache up to date.
	Fix routes everything through a single code path. [Bug 1035775].

2004-11-16  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* unix/tcl.m4 (SC_CONFIG_CFLAGS): Stop architecture flags to 'ld' from
	getting lost when [load] is disabled. [Bug 1016796]

2004-11-16  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tcl.h:
	* unix/configure.in: changed HAVE_CONFIG_H to HAVE_TCL_CONFIG_H.

	* unix/configure: autoconf-2.57

2004-11-15  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclInt.h: Added comment warning that the old ERR_IN_PROGRESS
	and ERROR_CODE_SET flag values should not be re-used for the sake of
	those extensions that have accessed them.

	* generic/tclCmdMZ.c (Tcl_TraceObjCmd): Fixed Bug 1065378 which failed
	* tests/trace.test (trace-33.1):	to permit a variable trace
	created with [trace variable] to be destroyed with [trace remove].
	Thanks to Keith Vetter for the report.

2004-11-15  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/tclvars.n: Added section to documentation on global variables
	that are specific to tclsh and wish. [Patch 1065732]

2004-11-12  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclEncoding.c (TableFromUtfProc): correct crash condition
	when TCL_UTF_MAX == 6. [Bug 1004065]

2004-11-12  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/interp.n: Basic documentation of the TIP#221 API.

2004-11-12  Don Porter	<dgp@users.sourceforge.net>

	TIP #221 IMPLEMENTATION
	* generic/tclBasic.c:	Define [::tcl::Bgerror] in new interps.
	* generic/tclEvent.c:	Update Tcl_BackgroundError to make use of the
				registered [interp bgerror] command.
	* generic/tclInterp.c:	New [interp bgerror] subcommand.
	* tests/interp.test:	syntax tests updated.

	TIP #226 IMPLEMENTATION
	* generic/tcl.decls:	Stubs for Tcl_(Save|Restore|Discard)InterpState
	* generic/tcl.h:	New public opaque type, Tcl_InterpState.
	* generic/tclInt.h:	Drop old private declarations. Add
				Tcl(Get|Set)BgErrorHandler
	* generic/tclResult.c:	Tcl_*InterpState implementations.
	* generic/tclDictObj.c:	Update callers.
	* generic/tclIOGT.c:
	* generic/tclTrace.c:

	TIP #227 IMPLEMENTATION
	* generic/tcl.decls:	Stubs for Tcl_(Get|Set)ReturnOptions.
	* generic/tclInt.h:	Drop old private declarations.
	* generic/tclResult.c:	Tcl_*ReturnOptions implementations.
	* generic/tclCmdAH.c:	Update callers.
	* generic/tclMain.c:

	* generic/tclDecls.h:	make genstubs
	* generic/tclStubInit.c:

	* unix/tclAppInit.c:	Removed tclConfig.h #include, now that tcl.h
				takes care of it for us.

	* generic/tclInt.h:	Moved verification of ptrdiff_t typedef from
	* generic/tclExecute.c: multiple .c files into one common header where
	* generic/tclVar.c:	it is verifiably after tclConfig.h inclusion.

2004-11-12  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tcl.h:
	* generic/tclInt.h:
	* unix/Makefile.in: include tclConfig.h from tcl.h and install it as a
	public header. Normalized compiler include path order to
	-I${BUILD_DIR} -I${UNIX_DIR} -I${GENERIC_DIR}.

	* unix/dltest/Makefile.in: add ${BUILD_DIR}/.. to include path to pick
	up tclConfig.h.

	* unix/tclUnixInit.c: moved check for HAVE_CFBUNDLE define after
	#include "tclInt.h" to ensure tclConfig.h has been included.

2004-11-12  Reinhard Max  <max@suse.de>

	* unix/config.h.in:
	* unix/tclConfig.h.in:	renamed

	* unix/Makefile.in:	Completed support for config header,
	* unix/configure.in:	fixed building outside of the unix dir,
	* unix/tclAppinit.c:	and reflected the name change of config.h.
	* generic/tclInt.h:

	* unix/configure:	generated

2004-11-12  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* unix/config.h.in:	Allow configure to put all the C #defs into
	* unix/configure.in:	a file (called config.h) so that Unix builds
	* unix/tcl.m4:		now take far fewer lines of scrollback to
	* unix/Makefile.in:	proceed (making it less likely that any errors
	* generic/tclInt.h:	or warnings will get missed).
	* unix/tclAppInit.c:	Part of the TIP#34 upgrades.

	* unix/tcl.m4, unix/tclUnixPort.h: Check for pthread_attr_get_np in
	<pthread.h> before forcing the use of <pthread_np.h> to make things
	work on NetBSD 2.0. [Bug 1064882]

	* doc/binary.n, doc/upvar.n: More minor fixes.

2004-11-12  Daniel Steffen  <das@users.sourceforge.net>

	* doc/CrtChannel.3:
	* doc/Interp.3:
	* doc/Limit.3:
	* doc/binary.n:
	* doc/dict.n:
	* doc/tm.n:
	* doc/upvar.n: fixed *roff errors uncovered by running 'make html'.

	* tools/tcltk-man2html.tcl: added faked support for bullet point
	lists, i.e. *nroff ".IP \(bu" syntax.

2004-11-11  Daniel Steffen  <das@users.sourceforge.net>

	* tests/fCmd.test:
	* unix/tclUnixFCmd.c (TraverseUnixTree): added option to rewind() the
	readdir() loop whenever the source hierarchy has been modified by
	traverseProc (e.g. by deleting files); this is required to ensure
	complete traversal of the source hierarchy on certain filesystems like
	HFS+. Added test for failing recursive delete on Mac OS X that was due
	to this. [Bug 1034337]

	* generic/tclListObj.c (Tcl_ListObjReplace): use memmove() instead of
	manual copy loop to shift list elements. Decreases time spent in
	Tcl_ListObjReplace() from 5.2% to 1.7% of overall runtime of tclbench
	on a ppc 7455 (i.e. 200% speed increase). [Patch 1064243]

	* generic/tclHash.c: hoisted some constant pointer dereferences out of
	loops to eliminate redundant loads that the gcc optimizer didn't deal
	with. Decreases time spend in Tcl_FindHashEntry() by 10% over a full
	run of the tcl testuite on a ppc 7455. [Patch 1064243]

	* tests/fileName.test:
	* tests/fileSystem.test:
	* tests/io.test:
	* tests/msgcat.test:
	* tests/tcltest.test:
	* tests/unixInit.test: fixed bugs causing failures when running tests
	with -tmpdir arg not set to working dir.

	* macosx/Makefile: corrected path to html help inside framework.
	Prevent parallel make from building several targets at the same time.

	* macosx/tclMacOSXFCmd.c (struct fileinfobuf): force struct to be
	packed to prevent failures when builing with -malign=natural.

2004-11-10  Andreas Kupries <andreask@activestate.com>

	* unix/tclUnixChan.c: [Bug 727786]. Exterminated the code marked
	DEPRECATED. This code has not been used in over a year now, and we
	have no complaints.

2004-11-08  David Gravereaux <davygrvy@pobox.com>

	* win/tclWinPipe.c: The pipe channel driver now respects the -blocking
	option when closing is the same way the UNIX side works. This is to
	avoid a hung shell when exiting due to open pipes that refuse to close
	in a graceful manner.
	* doc/open.n: Added a note about -blocking 0 and lack of exit status
	as it had never been documented. [Bug 947693]

	***POTENTIAL INCOMPATIBILITY***

	Scripts that use async pipes on windows, must (like the UNIX side) set
	-blocking to 1 before calling [close] to receive the exit status.

2004-11-07  David Gravereaux <davygrvy@pobox.com>

	* tests/winFile.test: added contraint to winFile-4.0 to prevent it
	being run on NT4 [Bug 981829]

2004-11-05  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tests/reg.test: Major reorganization so that this file is much
	easier for a normal Tcl maintainer to comprehend. The test flags are
	still very cryptic, but they appear to have to be that way. The number
	of skipped tests has increased, but now the skipped tests have much
	more meaningful content.

	* tests/tm.test (genpaths): Add a [file normalize] so we pick up
	Windows drive letters, etc. [Bug 1053568]

2004-11-04  Don Porter	<dgp@users.sourceforge.net>

	* changes:	Updates toward an 8.5a2 release.

2004-11-03  Kevin B. Kenny  <kennykb@acm.org>

	* library/clock.tcl (FreeScan): Fixed a bug where scanning "Monday"
	with a base time other than midnight incorrectly carried the base time
	forward.

	* test/clock.test (clock-33.{5,5a}): Made the test failure more
	informative.

	* tests/clock.test (clock-34.{28,44,45,46}): Removed 'knownBug'
	constraints from tests that no longer fail.

	Thanks to Don Porter for reporting these.

2004-11-03  David Gravereaux <davygrvy@pobox.com>

	* generic/tcl.h:		Moved the preprocessor logic
	* generic/tclDecls.h:		from tclInt.h of setting the
	* generic/tclInt.h:		TCL_STORAGE_CLASS macro to the
	* generic/tclIntDecls.h:	tcl*Decls.h files now that no
	* generic/tclIntPlatDecls.h:	use of EXTERN is left in tclInt.h.
	* generic/tclPlatDecls.h:	Proto for Tcl_Main moved in tcl.h
	* win/tclWinPort.h:		to prior the inclusion of the Stubs
	headers as they are now resetting TCL_STORAGE_CLASS. Removed
	extraineous reset from tclWinPort.h. [Patch 1055668]

	* generic/tclCompile.h: Removed extrainious reset of TCL_STORAGE_CLASS
	missed in my last edit.

2004-11-03  Don Porter	<dgp@users.sourceforge.net>

	* library/init.tcl ([unknown]): Corrections to the 2004-10-25 mods to
	Aunt ??? in [unknown]. Flaws revealed by Itcl test suite, which still
	apparently relies on this brokenness. Also added comment suggesting
	the error message that any code using this hack *ought* to receive in
	reply.

	* generic/tclTrace.c (TclCallVarTraces):  Improved ability to debug
	* tests/incr-old.test (incr-old-2.6):	  errors during variable
	* tests/incr.test (incr-{1,2}.28):	  traces by preserving the
	* tests/set.test (set-{2,4}.4):		  -errorinfo data.
	* tests/trace.test (trace-33.1):	  [Bug 527164]

2004-11-02  David Gravereaux <davygrvy@pobox.com>

	* generic/tclInt.h: added a check for #ifdef __cplusplus around the
	#define of MODULE_SCOPE. About the only time it would be problem is
	when someone is statically linking to Tcl and accessing internals from
	a C++ file and has name mangling issues from the lack of "C" after
	'extern' [Patch 1055668].
	* generic/tclCompile.h: Exchanged use of the EXTERN macro to the new
	MODULE_SCOPE macro. Lowered exported internals count by 35. [Patch
	1055668]
	* win/tclWinInt.h:
	* win/tclWinPort.h: exported internals dropped by a count of 14.
	* generic/tclFileSystem.h: Added use of MODULE_SCOPE on protos.
	* generic/tclRegexp.h: manipulating TCL_STORAGE_CLASS unnecessary.

2004-11-02  Don Porter	<dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl:		Corrected some misleading
	* tests/tcltest.test (tcltest-26.1,2):	displays of ::errorInfo and
	::errorCode information when the -setup, -body, and/or -cleanup scripts
	return an unexpected return code. Thanks to Robert Seeger for the fix.
	[RFE 1017151].

2004-11-02  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclExecute.c (TclExecuteByteCode): Improved version of the
	NaN fix from Miguel Sofer. [Bug 761471]

2004-11-02  Kevin Kenny	 <kennykb@acm.org>

	* library/tzdata/America/Cuiaba: Change to DST rules for
	* library/tzdata/America/Havana: autumn of 2004.
	[ftp://elsie.nci.nih.gov/pub/tzdata2004g.tar.gz]

	* tools/tclZIC.tcl: Updated to be compatible with recent changes in
	library/clock.tcl.

2004-11-02  Vince Darley  <vincentdarley@users.sourceforge.net>

	* win/tclWinFile.c: Simplify TclpUtime to use Tcl_FSGetNativePath, and
	add comments.

2004-11-02  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclInt.h: Change uses of EXTERN to MODULE_SCOPE (defined in
	this file too to be 'extern' if not overridden) as nothing declared in
	tclInt.h is supposed to be visible outside the Tcl core. If there *is*
	anything that extensions are actually using, we can open this up later
	on. [Patch 1055668]

	* doc/CrtChannel.3 (Tcl_GetChannelMode): Add synopsis. [Bug 1058446]

2004-11-01  Kevin B. Kenny  <kennykb@acm.org>

	* win/tclWinFile.c (FromCTime, TclpUtime): Replaced a call to the
	Posix 'utime' function with calls to Windows-API equivalents, to avoid
	a bug where the VC++ versions misconvert times across a Daylight
	Saving Time boundary. [Bug 926106]
	* win/tclWinInt.h (TclWinProcs):
	* win/tclWin32Dll.c (asciiProcs, unicodeProcs): Removed now-unused
	reference to 'utime'.
	* tests/cmdAH.test (cmdAH-24.12): Added test case for the above bug.

2004-11-01  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclExecute.c (TclExecuteByteCode): Make INST_EQ and friends
	handle NaN correctly in all cases. [Bug 761471]

	* generic/tclNamesp.c (NamespaceInscopeCmd): Make the error message
	generation the same as in NamespaceEvalCmd().
	(Tcl_Import): Rationalized to use Tcl_EvalObjv().

2004-10-31  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tests/io.test (io-40.3): Convert umask2 test constraint into a form
	that most people will be able to satisfy.

	* tests/cmdAH.test (cmdAH-8.45): Removed broken test constraint. It
	didn't do what it was intended to do, and it implied the other correct
	constraint. [Bug 1053908]

	* generic/tclCmdIL.c (InfoGlobalsCmd):
	* tests/info.test (info-8.4): Strip leading global-namespace
	specifiers from the pattern argument. [Bug 1057461]

2004-10-30  Kevin Kenny	 <kennykb@acm.org>

	* generic/clock.c: Replaced WIN32 macro with __WIN32__. [Bug 1054357].
	Thanks to David Gravereaux for the patch.
	* win/tclWinFile.c: Removed a long-standing bug that causes incorrect
	conversion between file time and UTC time if the file time is recorded
	in a different Daylight Saving Time status than the current one. [Bug
	926106]

2004-10-29  Don Porter	<dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl:	Correct reaction to errors in the
	obsolete processCmdLineArgsHook.	[Bug 1055673]
	* library/tcltest/pkgIndex.tcl:	Bump to tcltest 2.2.7
	* unix/Makefile.in:
	* tests/all.tcl:	Update to use [tcltest::configure].

2004-10-29  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* library/tm.tcl (::tcl::tm::*): Use the core proc engine to generate
	the wrong-num-args error messages for the path ensemble.

	Ensembles can now (sometimes) rewrite the error messages of their
	subcommands so they appear more like the arguments that the user
	passed to the ensemble. Below is a description of changes involved in
	doing this.

	* tests/namespace.test (namespace-50.*): Tests of ensemble subcommand
	error message rewriting.
	* generic/tclProc.c (TclObjInterpProc): Make procedures implement
	their wrong-num-args message using Tcl_WrongNumArgs instead of
	something baked-at-home.
	* generic/tclNamesp.c (TclIsEnsemble, NsEnsembleImplementationCmd):
	Added test of ensemble-hood (available to rest of core) and made
	ensembles set up the rewriting for Tcl_WrongNumArgs to take advantage
	of.
	* generic/tclInt.h (Interp.ensembleRewrite): Extra fields.
	* generic/tclIndexObj.c (Tcl_WrongNumArgs): Add knowledge of what is
	going on in ensembles' command rewriting so this command can generate
	the right error message itself.
	* generic/tclBasic.c (Tcl_CreateInterp, TclEvalObjvInternal): Added
	code to initialize (as empty) the rewriting fields and reset them when
	we leak outside an ensemble implementation.

2004-10-28  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c (INST_START_CMD):
	* tests/execute.test (execute-8.3): fix for execution stack corruption
	[Bug 1055676]. Credit dgp for detective work and fix.

2004-10-27  Don Porter	<dgp@users.sourceforge.net>

	* tests/socket.test (socket-13.1):	Balanced [makeFile] and
	[removeFile] commands.

	* tests/clock.test:	Correct duplicate test names.
	* tests/namespace.test:
	* tests/string.test:
	* tests/io.test (io-50.4):	Use namespace variables.

2004-10-27  David Gravereaux <davygrvy@pobox.com>

	* generic/tclInt.decls:	  The following 9 functions were moved from
	* generic/tclInt.h:	  tclInt.h to the private/int Stubs table for
	* generic/tclIntDecls.h:  use by the test suite. As tclTest.obj is
	* generic/tclStubInit.c:  linked to the shell, these functions need
	"blessed" status so as to always be exported from the library. Being
	placed in the Stubs table guarantees this [Bug 1054748]:
		TclpObjRemoveDirectory,	TclpObjCopyDirectory,
		TclpObjCreateDirectory,	TclpObjDeleteFile,
		TclpObjCopyFile,	TclpObjRenameFile,
		TclpObjStat,		TclpObjAccess,
		TclpOpenFileChannel

	* tests/registry.test:	Fixed test files to load the correct
	* tests/winDde.test:	registry and dde packages by using the info
	* win/Makefile.in:	from makefiles to tell tcltest where to load
	* win/makefile.vc:	them from. This avoids grabbing the wrong
	package from $auto_path which might be the install point rather than
	the dev location. Kudos to Jennifer Hom for adding -load and
	-loadfile to the tcltest package. [Bug 926088]

	* win/tclWinThrd.c (TclFinalizeLock): release the critical section
	before deleting it. [Bug 731778]

	* generic/tcl.h: Removed the file level 'extern "C" {' and the
	coresponding closing block as it serves no purpose given that all the
	function prototypes have the proper extern usage already.

	* unix/tclAppInit.c:	When built as tcltest, TclThread_Init was
	* win/tclAppInit.c:	getting called twice. First by Tcltest_Init,
	then again in Tcl_AppInit. The call from Tcl_AppInit is now removed.

2004-10-27  Andreas Kupries <andreask@activestate.com>

	* tests/tm.test:  Expanded on the testsuite entered by Donal.
	* library/tm.tcl: Even found bugs, these have been corrected.

2004-10-26  Kevin Kenny <kennykb@acm.org>

	* tests/format.test (format-19.1): Additional regression test for [Bug
	868489].

2004-10-27  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/*.n: Many small general documentation fixes.

2004-10-26  David Gravereaux <davygrvy@pobox.com>

	* generic/tclPipe.c (TclCleanupChildren): bad cast of resolvedPid
	caused PIDs on win95 to go negative. winpipe-4.2 brought this to the
	surface. Fixed with sprintf in place of TclFormatInt. Thanks to hgiese
	[Patch 767676]

2004-10-26  Andreas Kupries <andreask@activestate.com>

	* library/tm.tcl (::tcl::tm::Defaults): Added a second [file dirname]
	around the location of the executable. This fixes [Bug 1038705].
	Instable of a bogus "foo/bin/lib" we now have the correct "foo/lib" as
	a base path for modules.

2004-10-26  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclParse.c (Tcl_SubstObj):	Fix for failed subst-12.3 test
	* tests/subst.test (subst-12.3-5):	More tests for Bug 1036649.

	* unix/Makefile.in (install-libraries): Updated the installation of
	the http, msgcat, and tcltest packages to install as Tcl Modules on
	Unix systems. Other platform Makefiles still need updating. [Patch
	1054370]

	* tests/basic.test:	Added missing constraints.
	* tests/compile.test:
	* tests/fileSystem.test:

	* tests/init.test (init-2.8):	Updated to not rely on http package.

2004-10-26  Miguel Sofer <msofer@users.sf.net>

	* generic/tclInt.h:
	* generic/tclVar.c: removed more direct references to the VAR flags,
	replaced with access macros.

2004-10-26  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/expr.n: Clarified that non-num/non-bool literals require
	quoting. [Bug 1027849]. Also listed booleans as acceptable values.

2004-10-26  Kevin B. Kenny <kennykb@acm.org>

	* library/clock.tcl (FreeScan): Fixed a bug that caused relative days
	of the week in free-form [clock scan] to be evaluated in the wrong
	time zone.
	* tests/clock.test (clock-31.[456]): Made sure that there isn't an
	env(TZ) or env(TCL_TZ) lying around that will override the time zone
	that we're trying to establish with the simulated registry.
	Both problems reported as [Bug 1054101].

2004-10-25  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/string.n (map): Rewrote to clarify that we don't just map single
	characters. [Bug 1048005]
	* doc/info.n (procs): Clarified that the pattern argument may have
	namespace separators in it. [Bug 1047928]

	* tests/cmdAH.test (cmdAH-8.45): Simplify in the hope that the reasons
	for [Bug 1053908] will become clearer.

2004-10-25  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c (IllegalExprOperandType,TclExecuteByteCode):
	Removed several DECACHE_INFO/CACHE_INFO pairs that are no longer
	needed for protection because routines like Tcl_SetErrorCode() and
	Tcl_AddErrorInfo() can no longer re-enter bytecode execution.

	* generic/tclResult.c (TclProcessReturn): Bug fix. Be sure that a
	missing -errorinfo option when code == TCL_ERROR causes the errorInfo
	field to get reset.

	* tests/thread.test (thread-4.4): Test depended on a ::errorInfo value
	initialized to "". Added code to test to setup that requirement.

	* library/auto.tcl:	Purged Tcl's script library of all
	* library/clock.tcl:	remaining references to global vars
	* library/init.tcl:	::errorInfo and ::errorCode.

	* generic/tclMain.c (Tcl_Main): Updated to make use of
	TclGetReturnOptions instead of ::errorInfo variable.

	* generic/tclInterp.c (tclInit): Bug fix. Access dict variables with
	[dict get], not array syntax.

2004-10-25  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tests/tm.test: Rewrote the tests to actually perform syntax checks
	on the public API. Added a new test (currently failing) to indicate
	that the test suite is not complete yet.
	* library/tm.tcl (path): Rewrote to turn this command into an ensemble
	to make it faster and simpler.

2004-10-24  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCmdIL.c:
	* generic/tclExecute.c:
	* generic/tclInt.h:
	* generic/tclTrace.c: defined new macros to get/set the flags of
	variables. The only files that still access the flag values directly
	are tclCompCmds.c, tclCompile.c, tclProc.c and tclVar.c

2004-10-24  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c (Tcl_LogCommandInfo,Tcl_AddObjErrorInfo): Shift
	the initialization of errorCode to NONE to more central location.

	* generic/tclEvent.c (BgError,Tcl_BackgroundError,HandleBgErrors):
	Rewrite to build on the new TclGet/SetReturnOptions routines.

	* generic/tclResult.c (TclGetReturnOptions): Add call to
	Tcl_AddObjErrorInfo to be sure error fields are initialized.

	* generic/tclResult.c (TclTransferResult): Rewrite to build on the new
	TclGet/SetReturnOptions routines.

2004-10-22  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/tm.n: Tightened up the documentation.
	* tests/tm.test: Created (with partially dummy content) so TIP#189 can
	be marked Final.

	* generic/tclNamesp.c (NsEnsembleImplementationCmd): Make ensembles
	cut their implementations out of error traces. This is the right thing
	to do more often than not.

2004-10-22  Kevin B. Kenny  <kennykb@acm.org>

	* library/clock.tcl: Fixed a typo where the fallback time zone became
	::localtime instead of :localtime. Fixed a bug where time zone names
	containing hyphens could not be loaded.
	* tests/clock.test: Added regression test cases that covers both bugs.
	Thanks to Todd M. Helfter <tmh@jumpgate.itsp.purdue.edu> for finding
	these bugs.

2004-10-22  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclExecute.c (TclCompEvalObj, Tcl_ExprObj):
	* generic/tclProc.c (TclProcCompileProc): Always call object
	freeIntRepProc's in the same way.

2004-10-22  Miguel Sofer <msofer@users.sf.net>

	* generic/tclVar.c: fixed bug in commit of 2004-07-23, which was
	causing a leak of Proc structures and failure of compile-12.1. Two
	lines were 'zombies' from the previous way localVarNames worked.
	Credit dgp for finding this.

2004-10-21  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclInt.h (Interp):
	* generic/tclBasic.c (Tcl_CreateInterp,Tcl_DeleteInterp):
	* generic/tclResult.c (GetKeys,ReleaseKeys,etc.): Moved the key values
	of the return options dictionary out of private fields of the Interp
	struct and into thread-static values managed in tclResult.c.

	* generic/tclCmdAH.c (Tcl_CatchObjCmd, Tcl_ErrorObjCmd): Updated to
	call the new TclGet/SetReturnOptions routines to do much of their
	work.

	* generic/tclInt.h (TclGetReturnOptions,TclSetReturnOptions):
	* generic/tclResult.c (TclGetReturnOptions,TclSetReturnOptions): New
	utility routines to get/set the return options of an interp. Intent is
	that these routines will be converted to public routines after TIP
	approval.

	* generic/tclCmdMZ.c (TclProcessReturn,TclMergeReturnOptions):
	* generic/tclResult.c (TclProcessReturn,TclMergeReturnOptions): Move
	internal utility routines from tclCmdMZ.c to tclResult.c.

	* generic/tclBasic.c (Tcl_CreateInterp, Tcl_DeleteInterp):
	* generic/tclResult.c (TclTransferResult): Rework so that
	iPtr->returnOpts can be NULL when there are no special options.

	* generic/tclResult.c (TclRestoreInterpState): Plug potential memory
	leak.

2004-10-21  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclBasic.c: Various changes to [clock format] that,
	* generic/tclClock.c: together, make it roughly twice as fast
	* generic/tclInt.h:   while all tests in the test suite
	* library/clock.tcl:  continue to pass.

2004-10-20  Andreas Kupries <andreask@activestate.com>

	* win/Makefile.in (install-msgs):   Fixed a problem with the
	* win/Makefile.in (install-tzdata): installation of timezone data and
	message catalogs. They used the installed tcl library directory, not
	the source library. Before it was installed. Switched to source lib
	dir. Thanks to Kevin for the help in figuring this out.

2004-10-20  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclThreadTest.c (ThreadEventProc): Corrected subtle bug
	where the returned (char *) from Tcl_GetStringResult(interp) continued
	to be used without copying or refcounting, while activity on the
	interp continued. That's not safe, and recent changes demonstrated the
	lack of safety with failing tests thread-4.3 and thread-4.5.

2004-10-19  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclDictObj.c (DictWithCmd): Make sure all paths (that are
	not themselves error paths) do not lose the result code.

2004-10-19  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclInt.h (Tcl*InterpState):		New internal routines
	* generic/tclResult.c (Tcl*InterpState):	TclSaveInterpState,
	TclRestoreInterpState, and TclDiscardInterpState are superior
	replacements for Tcl_(Save|Restore|Discard)Result. Intent is that
	these routines will be converted to public routines after TIP
	approval. Interfaces for these routines were shamelessly stolen from
	Itcl.

	* generic/tclBasic.c (TclEvalObjvInternal):
	* generic/tclDictObj.c (DictUpdateCmd, DictWithCmd):
	* generic/tclIOGT.c (ExecuteCallback):
	* generic/tclTrace.c (Trace*Proc,TclCheck*Traces,TclCallVarTraces):
	Callers of Tcl_*Result updated to call the new routines. The calls
	were relocated in several cases to perform save/restore operations
	only when needed.

	* generic/tclEvent.c (HandleBgErrors):
	* generic/tclFCmd.c (CopyRenameOneFile): Calls to Tcl_*Result that
	were eliminated because they appeared to serve no useful purpose,
	typically saving/restoring an error message, only to throw it away.

2004-10-18  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c (Tcl_CreateInterp,Tcl_DeleteInterp):
	* generic/tclCmdAH.c (Tcl_CatchObjCmd):
	* generic/tclCmdMZ.c (TclMergeReturnOptions,TclProcessReturn):
	* generic/tclCompCmds.c (TclCompileReturnCmd):
	* generic/tclExecute.c (TclCompEvalObj):
	* generic/tclInt.h (Interp):
	* generic/tclProc.c (TclUpdateReturnInfo): Place primary storage of
	the -level and -code information in private fields of the Interp
	struct, rather than in a DictObj. This should significantly improve
	performance of TclUpdateReturnInfo.

2004-10-17  Miguel Sofer <msofer@users.sf.net>

	* generic/tclResult.c: removed unused variable [Bug 1048588]. Thanks
	to Daniel South.

2004-10-15  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCmdMZ.c (TclProcessReturn):	Now that primary
	* generic/tclProc.c (TclUpdateReturnInfo):	storage for the
	errorInfo and errorCode values are internal fields, we can set them at
	the time of the [return] command, and not have to wait until the
	specified number of "-level"s have popped.

	* generic/tclBasic.c (Tcl_CreateInterp, Tcl_DeleteInterp)
	(TclEvalObjvInternal, Tcl_LogCommandInfo, TclAddObjErrorInfo):
	* generic/tclCmdAH.c (Tcl_CatchObjCmd):
	* generic/tclEvent.c (BgError, ErrAssocData, Tcl_BackgroundError)
	(HandleBgErrors, BgErrorDeleteProc):
	* generic/tclExecute.c (TclCreateExecEnv, TclDeleteExecEnv):
	* generic/tclIOUtil.c (comments only):
	* generic/tclInt.h (ExecEnv,Interp, ERR_IN_PROGRESS):
	* generic/tclInterp.c ([tclInit]):
	* generic/tclMain.c (comments only):
	* generic/tclNamesp.c (Tcl_CreateNamespace, Tcl_DeleteNamespace)
	(TclTeardownNamespace):
	* generic/tclProc.c (TclUpdateReturnInfo):
	* generic/tclResult.c (Tcl_ResetResult, TclTransferResult):
	* generic/tclTrace.c (CallVarTraces):
	Reworked management of the "errorInfo" data of an interp. That
	information is now primarily stored in a new private (Tcl_Obj *) field
	of the Interp struct, rather than using a global variable ::errorInfo
	as the primary storage. The ERR_IN_PROGRESS flag bit value is no
	longer required to manage the value in its new location, and is
	removed. Variable traces are established to support compatibility for
	any code expecting the ::errorInfo variable to hold the information.

	***POTENTIAL INCOMPATIBILITY***
	Code that sets traces on the ::errorInfo variable may notice a
	difference in timing of the firing of those traces. Code that uses the
	value ERR_IN_PROGRESS.

2004-10-14  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	TIP#217 IMPLEMENTATION

	* generic/tclCmdIL.c (Tcl_LsortObjCmd): Add -indices option from James
	Salsman. [Patch 1017532]

	* generic/tclUtil.c (TclMatchIsTrivial): Detect degenerate cases of
	glob matching that let us avoid scanning through hash tables.
	* generic/tclCmdIL.c (InfoCommandsCmd, InfoGlobalsCmd, InfoProcsCmd):
	(InfoVarsCmd): Use this to speed up some [info] subcommands.

2004-10-12  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata/America/Campo_Grande:
	* library/tzdata/America/Cuiaba:
	* library/tzdata/America/Sao_Paulo
	* library/tzdata/America/Argentina/Mendoza:
	* library/tzdata/America/Argentina/San_Juan:
	Synchronized to Olson's 'tzdata2004e'.

2004-10-08  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	TIP#201 AND TIP#212 IMPLEMENTATIONS

	* doc/dict.n, doc/expr.n: Documentation for new functionality.
	* tests/expr.test: Basic tests of 'in' and 'ni' behaviour.
	* tests/dict.test (dict-21.*,dict-22.*): Tests for [dict update] and
	[dict with].
	* generic/tclExecute.c (TclExecuteByteCode): Implementation of the
	INST_LIST_IN and INST_LIST_NOT_IN bytecodes.
	* generic/tclParseExpr.c (GetLexeme): Parse the 'in' and 'ni'
	operators for TIP#201.
	* generic/tclDictObj.c (DictUpdateCmd,DictWithCmd): Core of
	implementation of TIP#212; docs and tests still to do...

2004-10-07  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclTest.c (TestsetobjerrorcodeCmd):  Simplified.

2004-10-07  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFileName.c:
	* generic/tclFileSystem.h:
	* generic/tclIOUtil.c:
	* generic/tclPathObj.c:
	* unix/tclUnixFile.c:
	* win/tclWinFile.c:
	* tests/fileName.test:
	* tests/winFCmd.test: code reorganization for better generic/platform
	code splitting [Bug 925620] removing the need for several #ifdef's,
	and tests and fix for an unreported Windows glob problem ('glob -dir
	C: -tails *').

2004-10-07  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* *.3: Convert CONST to const and VOID to void so we document how
	people should actually use the Tcl API and not the compatibility hacks
	that it has to have.

	* doc/man.macros, *.3: Update .AS macro so it can know how wide to
	make the third column of the argument list. Update documentation for C
	API (only users) to take advantage of this.

	* doc/FileSystem.3: Formatting fixes for greater documentation
	clarity.

2004-10-06  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclFileName.c (DoGlob, TclGlob): Stop messy sharing of
	interpreter result and instead use a private object for collecting the
	result of the glob. This simplifies TclGlob quite a lot.
	* generic/tclIOUtil.c (Tcl_FSMatchInDirectory): Simplify by removing
	some nesting. Also standardize variable names.
	(FsAddMountsToGlobResult): Force updates to the list to be done
	in-place, putting a side-condition of non-shared-ness on the resultPtr
	argument to Tcl_FSMatchInDirectory, but everything would have broken
	before if that was shared *anyway*.

	* generic/tclEncoding.c (LoadTableEncoding): Removed reference to Tcl
	interpreter; it wasn't needed as direct object use is more efficient.

	* generic/tclPathObj.c: Made this file follow the style rules in the
	Engineering Manual more closely, and also take advantage of the
	internal object manipulation macros more.

	* generic/tclCmdMZ.c (Tcl_SwitchObjCmd): Reorganized to have fewer
	magic flag variables and to separate the code that scans for a match
	from the code that processes a match body.

2004-10-06  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:
	* generic/tclBinary.c:
	* generic/tclCmdAH.c:
	* generic/tclCmdIL.c:
	* generic/tclCmdMZ.c:
	* generic/tclCompExpr.c:
	* generic/tclDictObj.c:
	* generic/tclEncoding.c:
	* generic/tclExecute.c:
	* generic/tclFCmd.c:
	* generic/tclHistory.c:
	* generic/tclIndexObj.c:
	* generic/tclInterp.c:
	* generic/tclIO.c:
	* generic/tclIOCmd.c:
	* generic/tclNamesp.c:
	* generic/tclObj.c:
	* generic/tclPkg.c:
	* generic/tclResult.c:
	* generic/tclScan.c:
	* generic/tclTimer.c:
	* generic/tclTrace.c:
	* generic/tclUtil.c:
	* generic/tclVar.c:
	* unix/tclUnixFCmd.c:
	* unix/tclUnixPipe.c:
	* win/tclWinDde.c:
	* win/tclWinFCmd.c:
	* win/tclWinPipe.c:
	* win/tclWinReg.c:
	It is a poor practice to directly set or append to the value of the
	objResult of an interp, because that value might be shared, and in
	that circumstance a Tcl_Panic() will be the result. Searched for
	example of this practice and replaced with safer alternatives, often
	using the Tcl_AppendResult() routine that dkf just rehabilitated.
	* library/dde/pkgIndex.tcl: Bump to dde 1.3.1
	* library/reg/pkgIndex.tcl: Bump to registry 1.1.5

2004-10-06  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/SetResult.3: Made Tcl_AppendResult non-deprecated; better that
	people use it than most of the common alternatives!
	* generic/tclResult.c (Tcl_AppendResultVA): Make this work better with
	Tcl_Objs. [Patch 1041072]
	(Tcl_SetResult, Tcl_AppendElement): Change string to stringPtr to
	avoid C++ keywords.

2004-10-05  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c (TclObjInvoke): More simplification of the
	TclObjInvoke routine toward unification with the rest of the
	evaluation stack.

	* generic/tclBasic.c (Tcl_CreateInterp, Tcl_DeleteInterp)
	(TclEvalObjvInternal, Tcl_LogCommandInfo):
	* generic/tclCmdAH.c (Tcl_CatchObjCmd):
	* generic/tclEvent.c (BgError, Tcl_BackgroundError, HandleBgErrors):
	* generic/tclInt.h (Interp, ERROR_CODE_SET):
	* generic/tclNamesp.c (Tcl_CreateNamespace, Tcl_DeleteNamespace)
	(TclTeardownNamespace):
	* generic/tclResult.c (Tcl_ResetResult, Tcl_SetObjErrorCode)
	(TclTransferResult):
	* generic/tclTrace.c (CallVarTraces):
	Reworked management of the "errorCode" data of an interp. That
	information is now primarily stored in a new private (Tcl_Obj *) field
	of the Interp struct, rather than using a global variable ::errorCode
	as the primary storage. The ERROR_CODE_SET flag bit value is no longer
	required to manage the value in its new location, and is removed.
	Variable traces are established to support compatibility for any code
	expecting the ::errorCode variable to hold the information.

	***POTENTIAL INCOMPATIBILITY***
	Code that sets traces on the ::errorCode variable may notice a
	difference in timing of the firing of those traces.

	* generic/tclNamesp.c (Tcl_PopCallFrame): Removed Bug 1038021
	workaround. That bug is now fixed.

2004-10-04  Kevin B. Kenny  <kennykb@acm.org>

	* tests/clock.test (clock-34.*): Removed an antibug that forced
	comparison of [clock scan] results with the :localtime time zone. Now
	that [clock scan] uses the current time zone instead, the antibug
	caused several tests to fail. [Bug 1038554]

2004-10-04  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclParseExpr.c (GetLexeme): Ensure that the 'eq' and 'ne'
	operators are followed by non-alphabetic characters so lexemes can't
	run together. [Bug 884830]

	* doc/DictObj.3, doc/dict.n: Clarified that a dictionary is not
	order-preserving. [Bug 1032243] Also added another example to show off
	more ways of using a dictionary and a few other formatting
	improvements.

2004-10-02  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclDictObj.c (TraceDictPath, Tcl_DictObjPutKeyList): Add
	support for automatic creation of dictionary paths since that is what
	everyone seems to actually expect of the API! [Bug 1037235]
	(Tcl_DictObjNext): Make calling this after Tcl_DictObjDone non-fatal
	as that simplifies a number of internal APIs. This doesn't break any
	existing working code as it is a case which previously caused a panic.

2004-10-02  Don Porter	<dgp@users.sourceforge.net>

	* tests/namespace.test (namespace-8.7):	Another test for save/restore
	of ::errorInfo and ::errorCode during global namespace teardown.

2004-10-01  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclProc.c (TclObjGetFrame, Tcl_UplevelObjCmd):
	* generic/tclVar.c (Tcl_UpvarObjCmd): Cache stackframe level
	references in the level object for speed.

2004-09-30  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c (Tcl_CreateInterp):
	* generic/tclInt.h (Interp): Removed the flag bit value
	EXPR_INITIALIZED. It was set during interp creation and never tested.
	Whatever purpose it had is in the past.

	* generic/tclBasic.c (Tcl_EvalObjEx):	Removed the flag bit value
	* generic/tclInt.h (Interp):	        USE_EVAL_DIRECT. It was used
	* generic/tcLTest.c (TestevalexObjCmd): only in the testing command
	* tests/parser.test (parse-9.2):        [testevalex] and nothing in
	the test suite made use of the capability it enabled.

	* generic/tclBasic.c (Tcl_AddObjErrorInfo): More re-organization
	* generic/tclCmdAH.c (Tcl_ErrorObjCmd):	    of the management of
	* generic/tclCmdMZ.c (TclProcessReturn):    the errorCode value.
	* tests/error.test (error-6.4-9):

	* generic/tclNamespace.c (TclTeardownNamespace): Tcl_Obj-ified
	* tests/namespace.test (namespace-8.5,6):	 the save/restore of
	::errorInfo and ::errorCode during global namespace teardown. Revised
	the comment to clarify why this is done, and added tests that will
	fail if this is not done.

	* generic/tclResult.c (TclTransferResult): Added safety checks so that
	unexpected undefined ::errorInfo or ::errorCode will not lead to a
	segfault.

	* generic/tclTrace.c (TclCallVarTraces):  Save/restore the flag values
	* tests/var.test (var-16.1):	          that define part of the
	interpreter state during variable traces. [Bug 1038021].

2004-09-30  Miguel Sofer <msofer@users.sf.net>

	* tests/subst.test (12.1-2): added tests for [Bug 1036649]

2004-09-29  Don Porter	<dgp@users.sourceforge.net>

	* tests/basic.test (49.*): New tests for TCL_EVAL_GLOBAL.

2004-09-29  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclVar.c (TclObjLookupVar, TclObjLookupVar):
	(TclObjUnsetVar2, SetArraySearchObj):
	* generic/tclUtil.c (SetEndOffsetFromAny):
	* generic/tclStringObj.c (Tcl_SetStringObj):
	(Tcl_SetUnicodeObj, SetStringFromAny):
	* generic/tclResult.c (ResetObjResult):
	* generic/tclRegexp.c (Tcl_GetRegExpFromObj):
	* generic/tclPathObj.c (TclFSMakePathRelative, SetFsPathFromAny):
	(TclFSMakePathFromNormalized, Tcl_FSNewNativePath):
	* generic/tclObj.c (TclFreeObj, Tcl_SetBooleanObj, SetBooleanFromAny):
	(Tcl_SetDoubleObj, SetDoubleFromAny, Tcl_SetIntObj):
	(SetIntOrWideFromAny, Tcl_SetLongObj, SetWideIntFromAny):
	(Tcl_SetWideIntObj, TclSetCmdNameObj, SetCmdNameFromAny):
	* generic/tclNamesp.c (SetNsNameFromAny, MakeCachedEnsembleCommand):
	* generic/tclListObj.c (Tcl_SetListObj, SetListFromAny):
	* generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct):
	* generic/tclDictObj.c (SetDictFromAny):
	* generic/tclCompile.c (TclInitByteCodeObj):
	* generic/tclBinary.c (Tcl_SetByteArrayObj, SetByteArrayFromAny):
	* generic/tclInt.h (TclFreeIntRep): Factorize out deletion of object
	internal representation to a shared macro, so simplifying much code.

2004-09-27  Miguel Sofer <msofer@users.sf.net>

	* generic/tclBasic.c (TclObjInvoke): fix for bogus gcc warning about
	uninitialised variable.

2004-09-27  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Removed internal routines TclInvoke,
	* generic/tclInt.decls: TclGlobalInvoke, TclObjInvokeGlobal and the
	* tests/basic.test:	portion of TclObjInvoke that handles calls
	without TCL_INVOKE_HIDDEN enabled. None of this code is called any
	longer within the core, and the superior public interface,
	Tcl_EvalObjv, is available for any external callers.

	* generic/tclIntDecls.h:	make genstubs
	* generic/tclStubInit.c:

	* generic/tclEvent.c (HandleBgErrors): Updated [bgerror] invocations
	to make use of Tcl_Obj based routines, dropping the calls to
	TclGlobalInvoke()

2004-09-27  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFileName.c:
	* generic/tclFileSystem.h:
	* generic/tclIOUtil.c:
	* generic/tclPathObj.c:
	* tests/cmdAH.test:
	* tests/fileSystem.test:
	* tests/winFCmd.test: fix to bad error message with 'cd' on windows,
	when permissions are inadequate [Bug 1035462] and to treatment of a
	volume-relative pwd on Windows [Bug 1018980].

	* doc/FileSystem.3: added missing Tcl_GlobTypeData documentation [Bug
	935853]

2004-09-27  Kevin Kenny	 <kennykb@acm.org>

	* compat/strftime.c (Removed):
	* generic/tclClock.c (removed TclClockOldscanObjCmd):
	* generic/tclDate.c (Regenerated):
	* generic/tclGetDate.y:
	* generic/tclInt.decls (removed TclGetDate and TclpStrftime):
	* generic/tclInt.h (removed TclGetDateInfo):
	* generic/tclIntDecls.h (Regenerated):
	* generic/tclStubInit.c (Regenerated):
	* library/clock.tcl:
	* unix/tclUnixTime.c (removed TclpStrftime):
	* win/Makefile.in:
	* win/makefile.bc:
	* win/makefile.bc:
	* win/tcl.dsp:
	Continued refactoring of [clock] for TIP 173 changes. Broke the
	free-form parser apart so that the Bison parser is responsible for
	only parsing, while clock.tcl handles relative times like "next
	Thursday", "next January". This change is needed to make timezones
	other than :localtime and :Etc/UTC work with free-form scanning. This
	change closes out the issue identified as being "for another day" in
	my log message of 2004-09-08. The refactored code also eliminates the
	last known references to TclpStrftime and TclGetDate, so those
	routines (including compat/strftime.c) have been removed. The
	refactoring also has the benefit that all storage in the Bison parser
	is now on the C stack, eliminating any need for mutex protection
	around [clock scan]. Also, changed the Makefiles so that 'make
	gendate' is available on Windows as well as Unix.

	* generic/tclCmdAH.c (Tcl_FormatObjCmd): Removed some grubby
	* generic/tclObj.c (SetBooleanFromAny):	 work-around code that was
	needed only because of Bug 868489.

	* generic/tclBasic.c (TclObjInvoke): Removed three unused variables to
	silence a compiler warning in VC++.

2004-09-27  Vince Darley  <vincentdarley@users.sourceforge.net>

	* doc/FileSystem.3: fix to small typo.

2004-09-26  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompCmds.c:
	* generic/tclCompExpr.c:
	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclInt.h:
	* generic/tclProc.c:
	* tests/compExpr-old.test:
	* tests/compExpr.test:
	* tests/expr.test:
	* tests/for.test:
	* tests/if.test:
	* tests/incr.test:
	* tests/while.test:
	Report compilation errors at runtime, [Patch 1033689] by dgp.

2004-09-23  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/dltest/Makefile.in (clean): Fixup make clean rule so that it
	does not delete all files when SHLIB_SUFFIX is set to the empty string
	in a static build. [Bug 1016726]

2004-09-23  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Corrections to the 2004-09-21 commit
	* generic/tclExecute.c:	regarding ERR_ALREADY_LOGGED. That commit
	* generic/tclNamesp.c:	caused Tk test send-10.7 to fail. Added
	* tests/namespace.test (25.7,8): tests in the Tcl test suite
	* tests/pkg.test (2.25,26):	 to catch this error without the aid
	of Tk in the future.

	* generic/tclCmdAH.c (Tcl_ExprObjCmd):	Simplified the TclObjCmdProc
	of [expr] with a call to Tcl_ConcatObj.

2004-09-22  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCmdMZ.c (TclProcessReturn):	Support the -errorline
	* generic/tclCompile.c (TclCompileScript):	option to [return].
	* tests/compile.test (16.23.*):	Use that capability to defer reporting
	* tests/misc.test (1.2):	of parse errors until runtime. Updated
	tests to reflect change. [Bug 1032805]

2004-09-22  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c (INST_START_CMD):
	* tests/proc.test (7.2-3): fix for [Bug 729692] was incorrect whenever
	a loop exception was returned.

2004-09-22  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata/America/Montevideo: Updated to reflect
	ftp://elsie.nci.nih.gov/pub/tzdata2004d.tar.gz. (Changes to
	Asia/Jerusalem were in the comments only.) [Routine maintenance - no
	bug] Spanish-language description of the change at
	http://www.presidencia.gub.uy/decretos/2004091502.htm

2004-09-21  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompCmds.c:	Tolerate [append] syntax errors
	* tests/appendComp.test (8.1):	at compile time, and allow runtime to
	raise the error (or succeed if a redefined [append] allows).

	* generic/tclBasic.c:	Reworked management of the interp flag
	* generic/tclCompile.c:	ERR_ALREADY_LOGGED, to reduce its exposure.
	* generic/tclExecute.c: Still left several referebces that are just
	* generic/tclNamesp.c:	too nice on performace to do away with.	These
	changes also resolve an inconsistency in the ::errorInfo values
	produced by [namespace eval x error foo bar] and [namespace eval x
	{error foo bar}].

	* generic/tclExecute.c (TclCompEvalObj):	Simplified the
	TclCompEvalObj routine. Much housekeeping now reliably happens
	elsewhere. [Patch 1031949]

2004-09-21  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/interp.n: Tighten up wording on how [interp eval] and [interp
	invokehidden] operate w.r.t. stack frames. [Bug 926590]

2004-09-20  Don Porter	<dgp@users.sourceforge.net>

	* tests/error.test (error-6.2,3):	Added more tests to verify
	::errorCode setting by/after a [catch].

2004-09-19  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCmdAH.c: removed outdated comment [Bug 1029518].

2004-09-18  David Gravereaux <davygrvy@pobox.com>

	* win/tclAppInit.c: Dde package can load into a safe interp. Claim
	this fact for the Tcl_StaticPackage() call when the shell is built
	with the TCL_USE_STATIC_PACKAGES option.

2004-09-18  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclExecute.c (TEBC-INST_LSHIFT,INST_RSHIFT): Ensure that
	large shifts end up shifting correctly. [Bug 868467]

	* doc/FileSystem.3, doc/OpenFileChnl.3: More documentation fixes from
	Mikhail Kolesnitchenko. [Patch 1022527]
	* doc/*: Standardize highlighting of symbols defined in tcl.h

2004-09-17  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c (Tcl_AddObjErrorInfo, Tcl_LogCommandInfo):
	* generic/tclCmdAH.c ([catch], [error]):
	* generic/tclCmdMZ.c ([return]):
	* generic/tclProc.c (TclUpdateReturnInfo):
	* generic/tclResult.c (Tcl_SetErrorCodeVA, Tcl_SetObjErrorCode)
	(TclTransferResult):	Refactored so that all errorCode setting flows
	through Tcl_SetObjErrorCode(). This greatly reduces the number of
	different places in the code that need to know details about an
	internal bitflag field of the Interp struct. Also places errorCode
	setting in one place for easier future mods.

2004-09-17  Kevin B.Kenny  <kennykb@acm.org>

	* generic/tclDate.c:	Revised tclGetDate.y to use bison instead of
	* generic/tclGetDate.y: yacc to build the parser, eliminating all the
	* generic/tclInt.h:	complicated hackery involving 'sed'
	* unix/Makefile.in:	postprocessing. Rebuilt the parser.

2004-09-14  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclClock.c (ClockOldscanObjCmd): Silenced a compiler warning
	(long passed as a param where unsigend long was expected). 'Unsigned
	long' is wrong, but the fix is really to change the signature of
	TclGetDate to return a structure of its 'yy' variables and then do the
	remaining work inside clock.tcl. But, as I said on 2004-09-08, that's
	a job for another day. [Bug 1027993]

2004-09-10  Miguel Sofer <msofer@users.sf.net>

	* doc/interp.n:
	* generic/tclInterp.c (TclPreventAliasLoop, AliasCreate):
	* tests/interp.test (17.4-6, 19.3-4): fixing problems with renaming of
	aliases [Bugs 707104 1026493]. Fix designed by dgp.

2004-09-13  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclNamesp.c (NsEnsembleImplementationCmd): Add token field
	to internal rep of EnsembleCmdRep structure so that we can check it to
	see if the subcommand object is really being used with the same
	ensemble. [Bug 1026903]

2004-09-11  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclClock.c (TclMktimeObjCmd): Corrected a bad check for
	error return from 'mktime'.
	* generic/tclObj.c (Tcl_GetIntFromObj): Corrected a problem where
	demoting a wide to an int failed on a big-endian machine. [Bug
	1026125].
	* tests/clock.test (clock-43.1): Added regression test for error
	return from 'mktime'.

2004-09-11  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c (INST_CONCAT1): fix for [Bug 1025834]; avoid
	unnecessary string copies.

2004-09-10  David Gravereaux <davyrgvy@pobox.com>

	* tests/tcltest.test: tcltest-12.3-4 needed to have
	::tcltest::loadScript set to empty in their -setup

2004-09-10  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclObj.c (SetIntOrWideFromAny): Rewritten integral value
	parsing code so that values do not flip so easily between numeric
	representations. Thanks to KBK for this! [Bug 868489]

	* generic/tclIO.c (Tcl_Seek): Make sure wide seeks do not fail to set
	::errorCode on error. [Bug 1025359]

2004-09-10  Andreas Kupries  <andreask@activestate.com>

	* generic/tcl.h: Micro formatting fixes.
	* generic/tclIOGT.c: Channel version fixed, must be 3, to have
	wideseekProc. Thanks to David Graveraux <davygrvy@pobox.com>.

2004-09-11  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclNamespace.c (TclGetNamespaceForQualName): Resolved
	longstanding inconsistency in the treatment of the TCL_NAMESPACE_ONLY
	flag revealed by testing the 2004-09-09 commits against Itcl.
	TCL_NAMESPACE_ONLY now acts as specified in the pre-function comment,
	forcing resolution in the passed in context namespace. It has been
	incorrectly forcing resolution in the interp's current namespace.

2004-09-10  Kevin Kenny	 <kennykb@acm.org>

	* library/clock.tcl: Fixed a bug where %z always put a plus sign on
	the time zone in :localtime.
	* tests/clock.test: Added test case for the above bug.

2004-09-10  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c (INST_CONCAT1): added a peephole optimisation
	for concatting an empty string. This enables replacing the idiom 'K $x
	[set x {}]' by '$x[set x {}]' for fastest execution.

2004-09-09  David Gravereaux <davygrvy@pobox.com>

	* win/tclWinConsole.c: Calls to WriteFile and WriteConsoleA changed to
	WriteConsole for simplicity.

2004-09-09  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclNamesp.c (Tcl_ForgetImport):	Corrected faulty

	* tests/namespace.test: logic that relied exclusively on string
	matching and failed in the presence of [rename]s. [Bug 560297] Also
	corrected faulty prevention of [namespace import] cycles. [Bug 1017299]

2004-09-08  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c (Tcl_CreateInterp):	Removed obsolete field
	for storing the string-based command procedure of built-in commands.
	We no longer have any string-based built-in commands!

2004-09-08  Kevin B. Kenny <kennykb@acm.org>

	* compat/strftime.c (_conv): Corrected a problem where hour 0 would
	format as a blank format group with %k.
	* doc/clock.n: Corrected a buglet in the header information. [Bug
	1024058]
	* generic/tclClock.c (TclClockMktimeObjCmd): Fixed a bug where the
	month was scanned incorrectly in -timezone :localtime.
	* tests/clock.test (clock-34.*,clock-40.1, clock-41.1): Adjusted the
	clock-34.* test cases so that the consistency check is performed in
	:localtime rather than the current time zone. This change allows
	dealing with issues where the C library has a different idea of DST
	conversion than Tcl. (Real fix would be to break TclGetDate into
	separate parser and time converter, and do the time conversion in
	clock.tcl. That's for another day.) Added regression test case for the
	bug where month was scanned incorrectly in -timezone :localtime. [Bug
	1023779] Added regression test case for %k at the zero hour.

2004-09-07  David Gravereaux <davygrvy@pobox.com>

	* win/makefile.vc: some quoting needed to be removed as it was
	breaking with VC7. [Bug 1023150]

2004-09-07  Kevin B. Kenny  <kennykb@acm.org>

	* doc/clock.n: Documented the default -format, and changed references
	to a (nonexistent) msgcat command to refer to the msgcat package. [Bug
	1023870]
	* generic/tclTimer.c: Removed a premature optimisation that attempted
	to store the assoc data in the client data; the optimisation caused a
	bug that [after] would overwrite its imports. [Bug 1016167]
	* library/clock.tcl (InitTZData, ClearCaches): Changed so that the
	in-memory time zone :UTC (and its aliases) always gets reinitialised,
	in case tzdata is absent. [Bug 1019537, 1023779]
	* library/tzdata/*: Regenerated.
	* tests/clock.test (clock-31.*, clock-39.1): Corrected a problem where
	the 'system' locale tests fail on a non-English Windows machine. [Bug
	1023761]. Added a test to make sure that alias time zones load
	correctly. [Bug 1023779].
	* tests/timer.test (timer-1.1, timer-2.1): Changed to (one hopes!) be
	more resilient on an overloaded system, if [after 200] sleeps for 300
	ms or longer.
	* tools/tclZIC.tcl (writeLinks): Corrected a problem where alias time
	zone names were written incorrectly, causing them to fail to load at
	run time. [Bug 1023779].
	* win/tclWinTime.c (Tcl_GetTime): Eliminated CPUID tests on Win64 -
	assuming that HAL vendors now do a better job of keeping the
	performance counters synchronized among CPU's. [Bug 1020445]

2004-09-06  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/tclvars.n, doc/tcltest.n, doc/tclsh.1, doc/safe.n, doc/expr.n
	* doc/WrongNumArgs.3, doc/Utf.3, doc/TraceVar.3, doc/Thread.3
	* doc/TCL_MEM_DEBUG.3, doc/SubstObj.3, doc/StdChannels.3
	* doc/SetResult.3, doc/RegExp.3, doc/RegConfig.3, doc/RecEvalObj.3
	* doc/PrintDbl.3, doc/ParseCmd.3, doc/Panic.3, doc/ObjectType.3
	* doc/Object.3, doc/Namespace.3, doc/Interp.3, doc/IntObj.3
	* doc/Hash.3, doc/GetOpnFl.3, doc/GetIndex.3, doc/Eval.3
	* doc/Encoding.3, doc/DoubleObj.3, doc/DictObj.3, doc/CrtTimerHdlr.3
	* doc/CrtObjCmd.3, doc/CrtMathFnc.3, doc/CrtCommand.3, doc/CrtChannel.3
	* doc/ChnlStack.3, doc/ByteArrObj.3, doc/AssocData.3, doc/Alloc.3:
	More documentation fixes from Mikhail Kolesnitchenko. [Patch 1022527]

2004-09-03  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* unix/tclUnixFCmd.c: Stop NULL interp arguments from triggering a
	crash when an error happens. [Bug 1020538]

2004-09-02  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/lsearch.n: Clarified meaning of -dictionary. [Bug 759545]

2004-09-02  Vince Darley  <vincentdarley@users.sourceforge.net>

	* win/makefile.vc: clock.tcl needs to be installed.

2004-09-01  Jeff Hobbs	<jeffh@ActiveState.com>

	* win/tclWinReg.c (BroadcastValue): WIN64 cast corrections

	* win/tclWinDde.c (DdeClientWindowProc):
	(DdeServicesOnAck, DdeEnumWindowsCallback): WIN64 corrections

	* win/tclWin32Dll.c (TclWinCPUID): need _asm for WIN64 (Itanium),
	until we have it, just return unknown. [Bug 1020445]

2004-09-01  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/regsub.n, doc/RegConfig.3, doc/Environment.3:
	* doc/CrtChannel.3, doc/safe.n: Use correct abbreviations.

2004-08-31  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/trace.n, doc/socket.n, doc/registry.n, doc/pid.n:
	* doc/namespace.n, doc/msgcat.n, doc/lsort.n, doc/lsearch.n:
	* doc/linsert.n, doc/info.n, doc/http.n, doc/history.n:
	* doc/format.n, doc/file.n, doc/exec.n, doc/dde.n, doc/clock.n:
	* doc/catch.n, doc/binary.n: More spelling and grammar fixes from
	Mikhail Kolesnitchenko. [Patch 1018486]

2004-08-31  Vince Darley  <vincentdarley@users.sourceforge.net>

	* doc/FileSystem.3:
	* generic/tclIOUtil.c: Clarified documentation regarding ability of a
	filesystem to say that it doesn't support a given operation using the
	EXDEV posix error code (copyFileProc, renameFileProc, etc), and
	updated one piece of code to ensure correct behaviour when an
	operation is not supported [Bug 1017072]

	* tests/fCmd.test: fix to test suite problem [Bug 1002884]

2004-08-31  Daniel Steffen  <das@users.sourceforge.net>

	* unix/Makefile.in (install-libraries): portable sh fix.

2004-08-30  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclCmdMZ.c (Tcl_StringObjCmd): Stop [string map] from
	crashing when its map and input string are the same object.

2004-08-27  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclNamesp.c (FindEnsemble): Factor out the code to convert a
	command name into an ensemble configuration and add support for
	ignoring [namespace import] link chains. [Bug 1017022]
	(NamespaceWhichCmd): Rework to use newer option parsing API.

2004-08-27  Daniel Steffen  <das@users.sourceforge.net>

	* unix/Makefile.in: added customization of default module path roots
	via TCL_MODULE_PATH makefile variable.
	* macosx/Makefile: add platform standard locations to default module
	path roots. [Patch 942881]

	* tests/env.test: macosx fixes.

2004-08-25  Don Porter	<dgp@users.sourceforge.net>

	* tests/timer.test (timer-10.1):	Test for Bug 1016167.
	* generic/tclTimer.c: Workaround for situation when a [namespace
	import] causes the objv[0] value to be something other than what
	Tcl_AfterObjCmd expects. [Bug 1016167].

2004-08-25  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclNamesp.c (NsEnsembleImplementationCmd): Use the ensemble
	command token to get the name of the ensemble for passing to the
	-unknown handler instead of relying on objv[0], which may contain
	useless info in the presence of [namespace import]. Problem found by
	Don Porter when investigating [Bug 1016167].

2004-08-24  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclProc.c:		The routine TclProcInterpProc was a
	* generic/tclTestProcBodyObj.c: specific instance of the general
	service already provided by TclObjInvokeProc. Removed
	TclProcInterpProc and TclGetInterpProc from the code...

	* generic/tclInt.decls:	...and from the internal stubs table.
	* generic/tclIntDecls.h
	* generic/tclStubInit.c

2004-08-24  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/string.n: Added clarifying note.

2004-08-23  Don Porter	<dgp@users.sourceforge.net>

	* library/auto.tcl:	Updated [tcl_findLibrary] search path to
	include any [<pkg>::pkgconfig get scriptdir,runtime] directory, as
	well as the $::auto_path. [RFE 695441]

2004-08-21  Kevin B. Kenny  <kennykb@acm.org>

	* tests/clock.test (clock-38.1): Changed TZ setting to specify CET in
	excruciating detail to deal with systems that lack the Posix defaults
	for DST changes (and to be formally correct with the change dates for
	CET).

2004-08-19  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclScan.c (Tcl_ScanObjCmd, ValidateFormat): Ensure that the
	%ld conversion works correctly on 64-bit platforms. [Bug 1011860]

2004-08-19  Kevin Kenny	 <kennykb@acm.org>

	* library/clock.tcl (format): Changed default timezone format from
	alphabetic to numeric to produce scannable times in more locales.
	* tests/clock.test (clock-37.1): Removed now-unused 'needPST'
	constraint and the comments that refer to it.

2004-08-18  Andreas Kupries  <andreask@activestate.com>

	* library/init.tcl: Integrated TIP #189. We source a separate file
	(see below), instead of inlining the contents of that file. This
	should beeasier to maintain, and easier to backport/install in 8.4
	installations.

	Note: Usage of Tcl Modules is restricted to non-safe interps. It
	cannot be loaded into a safe interp.

	* library/tm.tcl: New file, the v2 reference implementation for TIP
	#189, Tcl Modules.

	* doc/tm.n: New file, documentation for Tcl Modules, based on the TIP.

	* unix/mkLinks: Regenerated.
	* win/makefile.vc: Added tm.tcl to list of files to install.

2004-08-18  Kevin Kenny	 <kennykb@acm.org>

	* tests/httpd (httpdRespond): Corrected an abuse of the [clock]
	command that caused test failures for some values of [clock clicks].

	* doc/clock.n
	* generic/tclBasic.c (Tcl_CreateInterp, Tcl_HideUnsafeCommands):
	* generic/tclClock.c (all):
	* generic/tclInt.h:
	* generic/tclInterp.c (CreateSlave):
	* library/clock.tcl: (new file)
	* library/init.tcl (clock):
	* library/msgs/*.msg:(new files)
	* library/tzdata/*:
	* library/tzdata/*/*:
	* library/tzdata/*/*/*: (new files)
	* tools/installData.tcl: (new file)
	* tools/loadICU.tcl: (new file)
	* tools/makeTestCases.tcl: (new file)
	* tools/tclZIC.tcl: (new file)
	* unix/Makefile.in:
	* unix/configure: (regenerated)
	* unix/tcl.m4:
	* tests/clock.test (all):
	* win/Makefile.in:
	* win/Makefile.vc:
		Implementation of TIPs #173 and #209.

	The [clock] command is now a Tcl ensemble, with most of its
	functionality written in Tcl and callouts to C code only to access
	low-level functions such as localtime, mktime and tzset.

	In addition to the functionality changes called out in the two TIPs,
	it is worth noting that the [clock] command in a safe slave
	interpreter is now an alias to the [clock] command in the master, and
	that [clock] is otherwise not expected to function entirely correctly
	in safe interps. C code that simply does Tcl_MakeSafe needs to be
	aware that [clock] may need special handling. (It appears unlikely
	that such code actually exists.)

	One incompatibility of note is that if the time zone cannot be
	determined from the TZ, TCL_TZ environment variables, or from the
	Windows control panel, so that the C library must be used for date and
	time conversions, then times outside the range of time_t will fail;
	they used to return bad data silently.

	Many thanks to all the many people who assisted with testing,
	debugging, criticism of the specification, and localisation. Deserving
	of particular mention are Joe English, Clif Flynt, Donal K. Fellows,
	Jeff Hobbs, Cameron Laird, Arjen Markus, Reinhard Max, Christopher
	Nelson, Steve Offutt, Donald G. Porter, Pascal Scheffers, Peter da
	Silva and Richard Suchenwirth-Bauersachs.

	*** POTENTIAL INCOMPATIBILITY ***

2004-08-16  Miguel Sofer <msofer@users.sf.net>

	* doc/SetVar.3:
	* generic/tclTest.c (TestseterrorcodeCmd):
	* generic/tclVar.c (TclPtrSetVar):
	* tests/result.test (result-4.*, result-5.*): [Bug 1008314] detected
	and fixed by dgp.

2004-08-13  Don Porter	<dgp@users.sourceforge.net>

	* library/msgcat/msgcat.tcl:	Added checks to prevent [mclocale]
	* tests/msgcat.test:	from registering filesystem paths to possibly
	malicious code to be evaluated by a later [mcload].

2004-08-10  Zoran Vasiljevic <vasiljevic@users.sf.net>

	* unix/tclUnixThrd.c (TclpThreadCreate): changed handling of the
	returned thread ID since broken on 64-bit systems (Cray). Thanks to
	Rob Ratcliff for reporting the bug.

2004-08-03  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclNamesp.c (MakeCachedEnsembleCommand): Initialize the
	epoch field cached in the subcommand. [Bug 989298]
	(NsEnsembleImplementationCmd): Plug a leak (thanks to Miguel Sofer for
	spotting it with valgrind) and reduce the number of goto labels to
	make the code clearer.

2004-08-02  Don Porter	<dgp@users.sourceforge.net>

	* library/package.tcl (pkg_mkIndex):	Updated [pkg_mkIndex] to make
	use of [glob -directory $dir -tails] and return options.

	TIP#207 IMPLEMENTATION

	* doc/interp.n:		Added support for a -namespace option to the
	* generic/tclBasic.c:	[interp invokehidden] command.	Also added an
	* generic/tclInt.h:	internal routine TclObjInvokeNamespace() and
	* generic/tclInterp.c:	corrected the flag names TCL_FIND_ONLY_NS and
	* generic/tclNamesp.c:	TCL_CREATE_NS_IF_UNKNOWN that are passed to the
	* generic/tclTrace.c:	internal routine TclGetNamespaceForQualName().
	* tests/interp.test:	[Patch 981841]

	* generic/tclLiteral.c (TclCleanupLiteralTable):	Corrected
	* tests/compile.test (compile-12.4):	flawed deletion of literal
	internal reps that could lead to accessing of freed memory. Thanks to
	Kevin Kenny for test case and fix [Bug 1001997].

2004-07-30  Don Porter	<dgp@users.sourceforge.net>

	* tests/safe.test (safe-2.1):  Disabled senseless test.	 [Bug 999612]

	* library/auto.tcl (auto_reset):  Removed "protected" list of commands
	from [auto_reset]. All entries in the auto_index can be re-loaded.
	* library/package.tcl: Updated comment to reflect 2004-07-28 commit.

	* generic/tclEvent.c (Tcl_Finalize):	Re-organized Tcl_Finalize so
	that Tcl_ExitProc's that call Tcl_Finalize recursively do not cause
	deadlock. [Patch 999084 fixes Tk Bug 714956]

2004-07-30  Daniel Steffen  <das@users.sourceforge.net>

	* unix/configure:
	* unix/tcl.m4 (SC_CONFIG_CFLAGS): Darwin: instead of setting PLAT_OBJS
	to explict object files in tcl.m4, refer to MAC_OSX_OBJS makefile var.
	* unix/Makefile.in: added MAC_OSX_OBJS variable.

2004-07-29  Don Porter	<dgp@users.sourceforge.net>

	* library/package.tcl: [::pkg::create] is now an alias. Test safe-2.1
	will now fail until Bug 999612 is corrected.

2004-07-28  Don Porter	<dgp@users.sourceforge.net>

	* library/package.tcl:		Moved private command
	* library/tclIndex:		[pkg_compareExtension] into ::tcl::Pkg.
	* tests/pkg_mkIndex.test:	Also moved implementation of
	[::pkg::create] to [::tcl::Pkg::Create].

2004-07-25  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* tests/io.test: Make io-61.1 create file as binary to pass on Win32

2004-07-23  Miguel Sofer <msofer@users.sf.net>

	* generic/tclVar.c: simplify tclLocalVarNameType, removing the
	reference to the corresponding proc. The reference is now seen as
	unnecessary, and it may cause leaking circular references under some
	circumstances (see for example [Bug 994838]).

2004-07-22  Don Porter	<dgp@users.sourceforge.net>

	* tests/eofchar.data (removed): Test io-61.1 now generates its own
	* tests/io.test:	file of test data as needed.

2004-07-20  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclEvent.c:	    Correct threaded obj allocator to
	* generic/tclInt.h:	    fully cleanup on exit and allow for
	* generic/tclThreadAlloc.c: reinitialization. [Bug 736426]
	* unix/tclUnixThrd.c:	    (mistachkin, kenny)
	* win/tclWinThrd.c:

2004-07-21  Kevin Kenny	 <kennykb@acm.org>

	* generic/tclBasic.c (DeleteInterpProc):
	* generic/tclLiteral.c (TclCleanupLiteralTable):
	* generic/tclInt.h: added a TclCleanupLiteralTable function, called
	from DeleteInterpProc, that frees internal representations of shared
	literals early when an interpreter is being deleted. This change
	corrects a number of memory mismanagement issues in the cases where
	the internal representation of one literal contains a reference to
	another, and avoids conditions such as resolved variable names
	referring to procedure and namespace contexts that no longer exist.
	[Bug 994838]

2004-07-20  Daniel Steffen  <das@users.sourceforge.net>

	* unix/Makefile.in:
	* win/Makefile.in: added 'install-private-headers' makefile target to
	allow optionally installing private tcl headers. [FR 922727]

	* macosx/Makefile: use new 'install-private-headers' target to install
	private headers into framework. [FR 922727]

	* unix/tclUnixFile.c (NativeMatchType): added support for readonly
	matching of user immutable files (where available).

	* macosx/tclMacOSXBundle.c: dynamically acquire address for
	CFBundleOpenBundleResourceMap symbol, since it is only present in full
	CoreFoundation on Mac OS X and not in CFLite on pure Darwin.

2004-07-19  Zoran Vasiljevic <vasiljevic@users.sf.net>

	* win/tclwinThrd.c: redefined MASTER_LOCK to call TclpMasterLock.
	Fixes [Bug 987967]

2004-07-17  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclIOUtil.c: fix to rare 'cd' infinite loop in normalization
	with vfs [Bug 991420].
	* tests/fileSystem.test: added test for above bug.

	* doc/FileSystem.3: clarified documentation of posix error codes in
	'remove directory' FS proc - 'EEXIST' is used to signify a non-empty
	directory error (bug reported against tclvfs).

2004-07-16  Jeff Hobbs	<jeffh@ActiveState.com>

	* unix/Makefile.in, unix/tcl.m4:     move (C|LD)FLAGS after their
	* unix/configure.in, unix/configure: _DEFAULT to allow for env setting
	to override m4 switches. Move SC_MISSING_POSIX_HEADERS up and
	consolidate calls to limit redundancy in configure.
	(CFLAGS_WARNING): Remove -Wconversion
	(SC_ENABLE_THREADS): Set m4 to force threaded build when built against
	a threaded Tcl core.

2004-07-16  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIOCmd.c (Tcl_FcopyObjCmd): Corrected a typo in the
	generation of error messages and simplified by reusing data in a
	variable instead of retrieving the string again. Fixes [Bug 835289].

	* doc/OpenFileChnl.3: Added description of the behaviour of
	Tcl_ReadChars when its 'charsToRead' argument is set to -1. Fixes [Bug
	934511].

	* doc/CrtCommand.3: Added note that the arguments given to the command
	proc of a Tcl_CreateCommand are in utf-8 since Tcl 8.1. Closing [Patch
	414778].

	* doc/ChnlStack.3: Removed the declaration that the interp argument to
	Tcl_(un)StackChannel can be NULL. This fixes [Bug 881220], reported by
	Marco Maggi <marcomaggi@users.sourceforge.net>.

	* tests/socket.test: Accepted two new testcases by Stuart Casoff
	<stwo@users.sourceforge.net> checking that -server and -async don't go
	together [Bug 796534].

	* unix/tclUnixNotfy.c (NotifierThreadProc): Accepted Joe Mistachkin's
	patch for [Bug 990500], properly closing the notifier thread when its
	exits.

2004-07-15  Andreas Kupries  <andreask@activestate.com>

	* unix/tclUnixThrd.c (TclpFinalizeMutex): Accepted Joe Mistachkin's
	patch for [Bug 990453], closing leakage of mutexes. They were not
	destroyed properly upon finalization.

2004-07-15  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.h (CHANNEL_INCLOSE):	   New flag. Set in
	* generic/tclIO.c (Tcl_UnregisterChannel): 'Tcl_Close' while the
	* generic/tclIO.c (Tcl_Close):		   close callbacks are
	run. Checked in 'Tcl_Close' and 'Tcl_Unregister' to prevent recursive
	call of 'close' in the close-callbacks. This is a possible error made
	by implementors of virtual filesystems based on 'tclvfs', thinking
	that they have to close the channel in the close handler for the
	filesystem.

2004-07-14  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c:
	* generic/tclIO.h:
	* Not reverting, but #ifdef'ing the changes from May 19, 2004 out of
	the core. This removes the ***POTENTIAL INCOMPATIBILITY*** for channel
	drivers it introduced. This has become possible due to Expect gaining
	a BlockModeProc and now handling blockingg and non-blocking modes
	correctly. Thus [SF Tcl Bug 943274] is still fixed if a recent enough
	version of Expect is used.

	* doc/CrtChannel.3: Added warning about usage of a channel without a
	BlockModeProc.

2004-07-15  Andreas Kupries  <andreask@pliers.activestate.com>

	* generic/tclIOCmd.c (Tcl_PutsObjCmd): Added length check to the old
	depreceated newline syntax, to ensure that only "nonewline" is
	accepted. [Tcl SF Bug 985869], reported by Joe Mistachkin
	<mistachkin@users.sourceforge.net>.

2004-07-15  Zoran Vasiljevic <vasiljevic@users.sf.net>

	* generic/tclEvent.c (Tcl_Finalize): stuffed memory leak incurred by
	re-initializing of TSD slots after the last call to
	TclFinalizeThreadData (done from within Tcl_FinalizeThread()). We
	basically just repeat the TclFinalizeThreadData() once more before
	tearing down TSD keys in TclFinalizeSynchronization(). There should be
	more elaborate mechanism in place for handling such issues, based on
	thread cleanup handlers registered on the OS level. Such change
	requires much more work and would also require TIP because some
	visible parts of Tcl API would have to be modified. In the meantime,
	this will do.

	* generic/tclNotify.c (TclFinalizeNotifier): Added conditional
	notifier finalization based on the fact that an TclInitNotifier has
	been called for the current thread. This fixes the [Bug 770053] again.
	Hopefully this time w/o unwanted side-effects.

2004-07-15  Kevin Kenny	 <kennykb@acm.org>

	* generic/tclLiteral.c (TclReleaseLiteral): Removed unused variable
	'codePtr' to silence a message from VC++.

2004-07-15  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c (TclCompileScript):
	* generic/tclLiteral.c (TclReleaseLiteral): fix for [Bug 467523],
	which resurfaced with the latest changes. The previous strategy was to
	have special code in TclReleaseLiteral to handle the self-references
	generated by empty scripts. The new approach avoids the self-reference
	altogether, by having empty scripts return an unshared literal.

2004-07-15  Zoran Vasiljevic <vasiljevic@users.sf.net>

	* generic/tclEvent.c (NewThreadProc): Backout of changes to fix the
	[Bug 770053]. See SF bugreport for more info.

2004-07-11  Miguel Sofer <msofer@users.sf.net>

	* generic/tclBasic.c (Tcl_EvalEx): leak fix by dgp, release
	objv[objectsUsed] on error.

2004-07-11  Miguel Sofer <msofer@users.sf.net>

	* generic/tclParse.c (Tcl_SubstObj): leak fix by dgp, release result
	on error.

2004-07-11  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclNamesp.c (BuildEnsembleConfig): Don't forget to clean out
	references when deleting the hash table.
	* generic/tclDictObj.c (Tcl_DictObjRemoveKeyList): Oops, forgot to
	delete value object when removing the hash entry. [Bug 989093 in part]

2004-07-11  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c (TEBC): fixed leak of expandNestList objs when
	there is an error while an expansion is in progress (code added at
	checkForCatch).

2004-07-11  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclIOUtil.c: fix to 'cd' bug when vfs is active [tclvfs Bug
	986944] - this bug recently introduced by some threading fixes. Need
	to work out how to add tests for this.

2004-07-10  Kevin Kenny	 <kennykb@acm.org>

	* tests/clock.test (clock-2.11): Changed the test so that it isn't an
	infinite loop when run under valgrind on a slow virtual machine.
	Thanks to Miguel Sofer for the bug report. Also put in code to restore
	env(LC_TIME) after tests complete, silencing a warning from 'make
	TESTFLAGS="-debug 1" test'.

2004-07-08  Miguel Sofer <msofer@users.sf.net>

	* generic/tclBasic.c (DeleteInterpProc): reverted the modification of
	3 days ago, as the leak of [Bug 983660] is now handled by the change
	in TclCleanupByteCode.
	* generic/tclCompile.c (TclCleanupByteCode): let each bytecode remove
	its references to literals at interp deletion, without updating the
	dying literal table.
	* generic/tclLiteral.c (TclDeleteLiteralTable): with the above change
	to TclCleanupByteCode, this function now removes a single reference to
	the literal object and cleans up its own structures.

2004-07-08  Kevin Kenny	 <kennykb@acm.org>

	* win/tclWinInit.c (AppendEnvironment): Silenced a compilation warning
	about a type mismatch.

2004-07-07  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c (TclCompileScript): fix for [Bug 458361].
	Single-word scripts are compiled with an unshared cmdName to avoid
	shimmering between bytecode and cmdName reps.

2004-07-07  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCmdMZ.c (TclMergeReturnOptions):  Simplified logic and
	removed potential memory leak. [Bug 986257].

2004-07-07  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tools/man2help2.tcl (setTabs, IPmacro): Added support for the more
	advanced *roff macros used in Tk's doc/bind.n

	* generic/tclObj.c (TclInitObjSubsystem): Declare all current object
	types.

2004-07-06  Don Porter	<dgp@users.sourceforge.net>

	* tests/cmdMZ.test (cmdMZ-return-2.17): Added a test that a word
	containing backslash-quoted value is treated correctly.

	* generic/tclCompile.c (TclWordKnownAtCompileTime): [Bug 986196]
	Corrected flaw above and the flaw that caused TCL_TOKEN_SIMPLE_WORDs
	to have their original word value copied ( "{a b}" ) rather than the
	actual value ( "a b" ). Thanks to Kevin Kenny for report and tests.

2004-07-06  Kevin B. Kenny  <kennykb@acm.org>

	* tests/cmdMZ.test (cmdMZ-return-2.15,cmdMZ-return-2.16): Added a test
	that a return code containing spaces is correctly returned.

2004-07-06  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tools/man2html2.tcl (IPmacro, setTabs): Added support for the more
	advanced *roff macros used in Tk's doc/bind.n

2004-07-05  Miguel Sofer <msofer@users.sf.net>

	* generic/tclBasic.c (DeleteInterpProc): fix for [Bug 983660], found
	by pspjuth. Tear down the global namespace before freeing the interp
	handle, to allow the bytecodes to free their non-shared literals.
	* generic/tclLiteral.c (TclReleaseLiteral): moved special code for
	self-ref so that it is also used for non-shared literals. Possible bug
	found by inspection.

2004-07-03  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c (ExprRoundFunc):
	* tests/expr-old.test (39.1): added support for wide integers to
	round(); [Bug 908375], reported by Hemang Lavana.

2004-07-03  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.h:
	* generic/tclInt.decls:
	* generic/tclIntDecls.h:
	* generic/tclStubInit.c: Moved declaration of TclCompEvalObj() from
	tclCompile.h to the internal stubs table, for compiler
	experimentation.

2004-07-02  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/regcomp.c (stid): correct minor pointer size error

	* generic/tclPipe.c (TclCreatePipeline): applied TIP #202 patch that
	* doc/exec.n, tests/exec.test:		 adds 2>@1 as a special case
	redirection of stderr to the result output.

2004-07-02  Kevin B. Kenny  <kennykb@acm.org>

	* tests/io.test: Changed several tests to run the event loop rather
	than just calling [update] periodically, avoiding intermittent
	failures (usually in io-29.32) that stemmed from unreaped processes on
	Windows.
	* tests/winPipe.test (winpipe-1.11): Fixed a bug that caused test to
	fail if the path name of the working directory contained whitespace
	[Bug 678430]

2004-07-01  Vince Darley  <vincentdarley@users.sourceforge.net>

	* tests/fileSystem.test: Added test for [Bug 970529]

2004-07-01  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* win/README.binary, win/README: Updated references to Tcl and Tk 8.4
	to point to 8.5 instead. Thanks to Theo Verelst for spotting this.
	* generic/tcl.h: Added note to help prevent those changes from getting
	missed in the future.

	* doc/Namespace.3, doc/load.n, doc/Limit.3: Typo fixes and remove
	duplicate documentation. [Bug 983146]

2004-06-30  Don Porter	<dgp@users.sourceforge.net>

	* tests/fileSystem.test: Minor correction to new fileSystem-9.X tests
	so that they clean up temporary directories correctly.

2004-06-30  Vince Darley  <vincentdarley@users.sourceforge.net>

	* doc/filename.n: clarified behaviour concerning trailing slashes in
	filenames [Bug 971976]

	* win/tclWinFile.c:
	* tests/fileSystem.test: fix and tests for [Bug 979879]

2004-06-30  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	TIP#188 IMPLEMENTATION

	* doc/string.n, tests/string.test:	 Add 'wideinteger' to things
	* generic/tclCmdMZ.c (Tcl_StringObjCmd): that can be tested for with
	the [string is] subcommand. [Patch 940915, by Kevin Kenny]

2004-06-29  Don Porter	<dgp@users.sourceforge.net>

	* win/tclWinInit.c:	Corrected reference counting flaw in recent
	changes. Thanks to Pat Thoyts. [Bug 981893].

2004-06-29  Vince Darley  <vincentdarley@users.sourceforge.net>

	* win/tclWin32Dll.c: fix to compilation with VC++ 5.2

2004-06-29  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* library/safe.tcl: Make sure that the temporary variable is local to
	the namespace and not inadvertently global. [Bug 981733]

2004-06-24  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tests/unixNotfy.test: Modified constraints so that testing with a
	threaded tclsh (not tcltest) will not hang.

2004-06-23  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclThreadStorage.c: Corrected type casting errors that led
	to calculation of a negative index value, thus accesses outside the
	threadStorageCache array, thus memory corruption. Crash observed on
	Mac OS X platform.

2004-06-23  Joe Mistachkin  <joe@mistachkin.com>

	* generic/tclThread.c: Implements platform independent thread storage
	* generic/tclThreadStorage.c: mechanism and fixes associated bugs on
	platforms where there is limited thread local storage space
	(Win98/WinNT4). [Patch 976496]

	* generic/tclInt.decls:
	* generic/tclIntDecls.h: Added thread storage functions to the
	* generic/tclStubInit.c: internal stubs table.

	* unix/Makefile.in:
	* unix/configure:
	* unix/tcl.m4:
	* win/makefile.vc:
	* win/rules.vc:
	* win/Makefile.in: Modified the unix, VC++, and Cygwin build systems
	* win/configure: to include the new "tclThreadStorage.c" and the new
	* win/tcl.m4: USE_THREAD_STORAGE define.

2004-06-23  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* tests/io.test: Added -force to 18.1 and 18.2. This was failing on
	WinXP.

	* tests/winFCmd.test: Added a cleanup to winFCmd-16.11 to avoid a
	failure in 16.12.

	* tests/eofchar.data: Added -kb option to ensure a binary checkout to
	win32 systems. This fixes a failure in io-61.1

	* win/makefile.vc: fix for [Bug 977369] about launching tclsh to
	generate a tclConfig.sh with the nmake build system

2004-06-23  Kevin B. Kenny  <kennykb@acm.org>

	* tests/winDde.test (createChildProcess): Added a 200-ms delay (with
	the event loop live) when shutting down the test DDE server process.
	With the delay in place, nuisance failures of tests winDde-4.2, -6.5,
	and -6.6 appear to be much less frequent. [Bug 957449]

2004-06-23  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tests/*.test: Standardize use of platform constraints.

	* unix/tclUnixInit.c (GetStackSize, TclpCheckStackSpace):
	* unix/tclUnixThrd.c (TclpThreadGetStackSize): Added code to check
	whether the C stack is about to be exceeded, from [Patch 746378] by
	Joe Mistachkin but with substantial revisions.

2004-06-22  Kevin Kenny	 <kennykb@acm.org>

	* generic/tclEvent.c (NewThreadProc): Fixed broken build on Windows
	caused by missing TCL_THREAD_CREATE_RETURN.

	* tests/stack.test (stack-3.1): Corrected nuisance error in threaded
	builds.

2004-06-22  Zoran Vasiljevic <vasiljevic@users.sf.net>

	* generic/tclEvent.c:
	* generic/tclInt.h:
	* unix/tclUnixNotfy.c:
	* unix/tclUnixThrd.c:
	* win/tclWinThrd.c: [Bug 770053]. See bug report for more information
	about what it does.

	* tests/unixNotfy.test: rewritten to use tcltest::threadReap to
	gracefully wait for the test thread to exit. Otherwise we got a race
	condition with main thread exiting before the test thread. This
	exposed the long-standing Tcl lib issue with resource
	garbage-collection on application exit.

2004-06-21  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/tclWin32Dll.c (DllMain, _except_dllmain_detach_handler)
	(TclpCheckStackSpace, _except_checkstackspace_handler)
	(TclWinCPUID, _except_TclWinCPUID_detach_handler):
	* win/tclWinChan.c (Tcl_MakeFileChannel)
	(_except_makefilechannel_handler):
	* win/tclWinFCmd.c (DoRenameFile, _except_dorenamefile_handler)
	(DoCopyFile, _except_docopyfile_handler):
	Rework pushing of exception handler function pointer so that compiling
	with gcc -O3 works. Remove empty function call to avoid compiler
	warning. Mark the DllMain function as noinline to avoid compiler error
	from duplicated asm labels in generated code.

2004-06-21  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclThreadAlloc.c (Ptr2Block): Rewrote so as to maximize the
	chance of detecting and reporting a memory inconsistency without
	relying on things being consistent. [Bug 975895]

2004-06-18  Don Porter	<dgp@users.sourceforge.net>

	* tests/load.test:	Relaxed strictness of error message matching
	for test load-2.3 so that it will pass on Mac OSX.

	* generic/tclEncoding.c: Static TclFindEncodings -> FindEncodings.
	* generic/tclInt.h:	Updated TclpFindExecutable() so that failed
	* generic/tclUtil.c:	attempts to find the executable are saved
	* unix/tclUnixFile.c:	just as successful finds are. [Patch 966053]
	* unix/tclUnixTest.c:

2004-06-18  Kevin B. Kenny  <kennykb@acm.org>

	* tests/winFCmd.test (winFCmd-16.12): Changed test to compute the
	target directory, so as not to fail if the user's HOME isn't the root.

2004-06-19  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tcl.m4: autoconf 2.5 fixes in Darwin section.
	* unix/configure: autoconf-2.57

2004-06-18  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* unix/tclUnixInit.c (localeTable): Added some more locale to encoding
	mapping info from Jim Huang <jserv@kaffe.org>

	* generic/tclInt.h (PendingObjData,TclFreeObjMacro,etc):
	* generic/tclObj.c (TclFreeObj): Added scheme for making TclFreeObj()
	avoid blowing up the C stack when freeing up very large object trees.
	[Bug 886231]

	* win/tclWinInit.c (SetDefaultLibraryDir): Fix logic, simplify and add
	comments.

2004-06-17  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclObj.c:	Added missing space in panic message.

	* win/tclWinInit.c:	Inform [tclInit] about the default library
	directory via the ::tclDefaultLibrary variable. This should correct a
	problem with my 2004-06-11 commit. Better solutions still in the
	works. Thanks to Joe Mistachkin for pointing out the breakage.

2004-06-16  Don Porter	<dgp@users.sourceforge.net>

	* doc/library.n:	Moved variables ::auto_oldpath and
	* library/auto.tcl:	::unknown_pending into ::tcl namespace.
	* library/init.tcl:	[Bugs 808319, 948794]

2004-06-15  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/binary.n: Added some notes to the documentation of the 'a'
	format to address the point raised in [RFE 768852].

2004-06-15  Jeff Hobbs	<jeffh@ActiveState.com>

	* unix/tclConfig.sh.in (TCL_EXTRA_CFLAGS): set to @CFLAGS@, which is
	the configure-time CFLAGS. Addendum to m4 change on 2004-05-26.

2004-06-14  Kevin Kenny	 <kennykb@acm.org>

	* win/Makefile.in: Corrected compilation flags for tclPkgConfig.c so
	that it doesn't require Stubs.
	* generic/tclBasic.c (Tcl_CreateInterp): Removed comment stating that
	TclInitEmbeddedConfigurationInformation needs Stubs; with the change
	above, the comment is now erroneous.

2004-06-11  Don Porter	<dgp@users.sourceforge.net>

	* doc/Encoding.3:	Removed bogus claims about tcl_libPath.

	* generic/tclInterp.c (Tcl_Init):	Stopped setting the
	tcl_libPath variable. [tclInit] can get all its directories without it.

	* tests/unixInit.test:	Modified test code that made use of
	tcl_libPath variable.

	* unix/tclUnixInit.c:	Stopped setting the tclDefaultLibrary variable,
	execept on the Mac OS X platform with HAVE_CFBUNDLE. In that
	configuration we should seek some way to make use of the TIP 59
	facilities and get rid of that usage of tclDefaultLibrary as well.

	* generic/tclInterp.c:	Updated [tclInit] to make $env(TCL_LIBRARY) an
	absolute path, and to include the scriptdir,runtime configuration value
	on the search path for init.tcl.

	* unix/tclUnixInit.c:	The routines Tcl_Init() and TclSourceRCFile()
	* win/tclWinInit.c:	had identical implementations for both win and
	* generic/tclInterp.c:	unix. Moved to a single generic implementation.
	* generic/tclMain.c:
	* library/init.tcl:
	* generic/tclInitScript.h (removed):
	* unix/Makefile.in:
	* win/tcl.dsp:

	* unix/configure.in:	Updated TCL_PACKAGE_PATH value to handle
	* win/configure.in:	--libdir configuration.

	* unix/configure.in:	autoconf-2.57
	* win/configure.in:

	* generic/tclBasic.c (Tcl_CreateInterp): Moved call to
	TclInitEmbeddedConfigurationInformation() earlier in
	Tcl_CreateInterp() so that other parts of interp creation and
	initialization may access and use the config values.

2004-06-11  Kevin Kenny	 <kennykb@acm.org>

	* win/tclAppInit.c: Restored the 'setargv' procedure when compiling
	with mingw. Apparently, the command line parsing in mingw doesn't work
	as well as that in vc++, and the result was (1) that winPipe-8.19
	failed, and (2) that 'make test' would work at all only with
	TESTFLAGS='-singleproc 1'. [Bug 967195]

2004-06-10  Zoran Vasiljevic <vasiljevic@users.sf.net>

	* generic/tclIOUtil.c: removed forceful setting of the private cached
	current working directory rep from within the Tcl_FSChdir(). We
	delegate this task to the Tcl_FSGetCwd() which does this task anyway.
	The relevant code is still present but disabled temporarily until the
	change proves correct. The Tcl test suite passes all test with the
	given change so I suppose it is good enough.

2004-06-10  Don Porter	<dgp@users.sourceforge.net>

	* unix/tclUnixInit.c (TclpInitLibraryPath):	Disabled addition of
	* win/tclWinInit.c (TclpInitLibraryPath):	relative-to-executable
	directories to the library search path. A first step in reform of
	Tcl's startup process.

	***POTENTIAL INCOMPATIBILITY***
	Attempts to directly run ./tclsh or ./tcltest out of a build directory
	will either fail, or will make use of an installed script library in
	preference to the one in the source tree. Use `make shell` or `make
	runtest` instead.

	* tests/unixInit.test:	Modified tests to suit above changes.

	* generic/tclPathObj.c:	Corrected [file tail] results when operating
	on a path produced by TclNewFSPathObj(). [Bug 970529]

2004-06-09  Zoran Vasiljevic <vasiljevic@users.sf.net>

	* generic/tclIOUtil.c: partially corrected [Bug 932314]. Also
	corrected return values of Tcl_FSChdir() to reflect those of the
	underlying platform-specific call. Originally, return codes were mixed
	with those of Tcl.

2004-06-08  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c:
	* generic/tclExecute.c: handle warning [Bug 969066]

2004-06-08  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclHash.c (RebuildTable): Move declaration of variable so it
	is only declared when it is used. [Bug 969068]

2004-06-07  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/lsearch.n: Added correct option to example. [Bug 968219]

2004-06-05  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tcl.h: Corrected Tcl_WideInt declarations so that the mingw
	build works again.
	* generic/tclDecls.h:			Changes to the tests for clock
	* generic/tclInt.decls:			frequency in Tcl_WinTime so
	* generic/tclIntDecls.h:		that any clock frequency is
	* generic/tclIntPlatDecls.h:		accepted provided that all
	* generic/tclPlatDecls.h:		CPU's in the system share a
	* generic/tclStubInit.c:		common chip, and hence,
	* tests/platform.test (platform-1.3):	presumably, a common clock.
	* win/tclWin32Dll.c (TclWinCPUID):	This change necessitated a
	* win/tclWinTest.c (TestwincpuidCmd)	small burst of assembly code
	* win/tclWinTime.c (Tcl_GetTime):	to read CPU ID information,
	which was added as TclWinCPUID in the internal Stubs. To test this
	code in the common case of a single-processor machine, a
	'testwincpuid' command was added to tclWinTest.c, and a test case in
	platform.test. Thanks to Jeff Godfrey and Richard Suchenwirth for
	reporting this bug. [Bug 976722]

2004-06-04  Don Porter	<dgp@users.sourceforge.net>

	* generic/tcl.h:	Restored #include <stdio.h> to tcl.h,
	rejecting the "fix" for "Bug" 945570. Tcl_FSSeek() needs the values of
	SEEK_SET, etc. and too many extensions rely on tcl.h providing stdio.h
	for them.

2004-06-02  Jeff Hobbs	<jeffh@ActiveState.com>

	* win/tclWinFile.c (TclpFindExecutable): when using GetModuleFileNameA
	(Win9x), convert from CP_ACP to WCHAR then convert back to utf-8.
	Adjunct to 2004-04-07 fix.

2004-06-02  David Gravereaux <davygrvy@pobox.com>

	* tests/winPipe.test (winpipe-6.1): blocking set to 1 before closing
	to ensure we get an exitcode. The windows pipe channel driver doesn't
	differentiate between a blocking and non-blocking close just yet, but
	will soon. Part of [Bug 947693]

2004-06-02  Vince Darley  <vincentdarley@users.sourceforge.net>

	* doc/file.n: fix to documentation of 'file volumes' (Bug 962435)

2004-06-01  David Gravereaux <davygrvy@pobox.com>

	* win/makefile.vc: check for either MSDEVDIR or MSVCDIR being in the
	environment, for VC7. [Bug 942214]

	* generic/tclIO.c (Tcl_SetChannelOption): -buffersize wasn't
	understanding hexidecimal notation nor was reporting number conversion
	errors. The behavior to silently ignore settings outside the
	acceptable range of Tcl_SetChannelBufferSize (<10 or >1M) is
	unchanged. This silent ignoring behavior might be up for review soon.

2004-05-30  David Gravereaux <davygrvy@pobox.com>

	* win/tclWinPipe.c:
	* win/tclWinPort.h:  Reworked the win implementation of Tcl_WaitPid to
	support exitcodes in the 'signed short' range. Even though this range
	is non-portable, it is valid on windows. Detection of exception codes
	are now more accurate. Previously, an application that exited with
	ExitProcess((DWORD)-1); was improperly reported as exiting with
	SIGABRT.

2004-05-30  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclInterp.c: Added comments describing the purposes of each
	function in the limit implementation and rewrote the names of some
	non-public functions for greater clarity of purpose.
	* doc/interp.n: Added note about what happens when a limited
	interpreter creates a slave interpreter.
	* doc/Limit.3: Added manual page for the resource limit subsystem's C
	API. [Bug 953903]

2004-05-29  Joe English	 <jenglish@users.sourceforge.net>

	* doc/global.n, doc/interp.n, doc/lrange.n: Fix minor markup errors.

2004-05-28  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/*.n: Added examples to many (too many to list) more man pages.

2004-05-25  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c:
	* generic/tclVar.c: using (ptrdiff_t) instead of (int) casting to
	correct compiler warnings [Bug 961657], reported by Bob Techentin.

2004-05-27  Kevin B. Kenny  <kennykb@acm.org>

	* tests/clock.test: Added a single test for the presence of %G in
	[clock format], and conditioned out the clock-10.x series if they're
	all going to fail because of a broken strftime() call. [Bug 961714]

2004-05-27  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclHash.c (CompareStringKeys): Added #ifdef to allow people
	to instruct this function to use strcmp(). [FRQ 951168]

	* generic/tclVar.c: Moved declarations into #if guards so they only
	happen when required.
	* unix/tclUnixPort.h: Guard declaration of strtod() so it is only
	enabled when we don't have a declaration in stdlib.h
	* unix/tclUnixThrd.c (Tcl_CreateThread):	Added declarations
	* unix/tclUnixTest.c (AlarmHandler):		and casts so that
	* unix/tclUnixChan.c (TtyModemStatusStr):	all functions are
	* generic/tclScan.c (Tcl_ScanObjCmd):		defined before use
	* generic/tclDictObj.c (InvalidateDictChain):	and no cross-type
	* generic/tclCmdMZ.c (Tcl_StringObjCmd):	uses are performed.

	The overall effect is to make building with gcc with the additional
	flags -Wstrict-prototypes -Wmissing-prototypes produce no increase in
	the total number of warnings (except for main(), which is undeclared
	for traditional reasons.)

2004-05-26  Jeff Hobbs	<jeffh@ActiveState.com>

	* unix/Makefile.in:  Rework configure ordering to TCL_LINK_LIBS,
	* unix/tcl.m4:	     ENABLE_SHARED, CONFIG_CFLAGS, & ENABLE_SYMBOLS
	* unix/configure:    before TCL_EARLY_FLAGS and TCL_64BIT_FLAGS
	* unix/configure.in: (about 400 lines earlier) in configure.in. This
	forces CFLAGS configuration to be done before many tests, which is
	needed for 64-bit builds and may affect other builds. Also make
	CONFIG_CFLAGS append to CFLAGS directly instead of using EXTRA_CFLAGS,
	and have LDFLAGS append to any existing value. [Bug 874058]
	* unix/dltest/Makefile.in: change EXTRA_CFLAGS to DEFS

2004-05-26  Don Porter	<dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl:	Correction to debug prints and testing
	* library/tcltest/pkgIndex.tcl:	if TCLTEST_OPTIONS value. Corrected
	* tests/tcltest.test:		double increment of numTestFiles in
	-singleproc 1 configurations. Updated tcltest-19.1 to tcltest 2.1
	behavior. Corrected tcltest-25.3 to not falsely report a failure in
	tcltest.test. Bumped to tcltest 2.2.6. [Bugs 960560, 960926]

2004-05-25  Jeff Hobbs	<jeffh@ActiveState.com>

	* doc/http.n (http::config): add -urlencoding option (default utf-8)
	* library/http/http.tcl:     that specifies encoding conversion of
	* library/http/pkgIndex.tcl: args for http::formatQuery. Previously
	* tests/http.test:	     undefined, RFC 2718 says it should be
	utf-8. 'http::config -urlencoding {}' returns previous behavior, which
	will throw errors processing non-latin-1 chars. Bumped http package to
	2.5.0.

2004-05-25  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclInterp.c (DeleteScriptLimitCallback): Move all deletion
	of script callback hash table entries to happen here so the entries
	are correctly removed at the right time. [Bug 960410]

2004-05-25  Miguel Sofer <msofer@users.sf.net>

	* docs/global.n: added details for qualified variable names [Bug
	959831]

2004-05-25  Miguel Sofer <msofer@users.sf.net>

	* generic/tclNamesp.c (Tcl_FindNamespaceVar):
	* tests/namespace.test (namespace-17.10-12): reverted commit of
	2004-05-23 and removed the tests, as it interferes with the varname
	resolver and there are apps that break (AlphaTk). A fix will have to
	wait for Tcl9.

	* generic/tclVar.c: Caching of namespace variables disabled: no simple
	way was found to avoid interfering with the resolver's idea of
	variable existence. A cached varName may keep a variable's name in the
	namespace's hash table, which is the resolver's criterion for
	existence.

	* tests/namespace.c (namespace-17.10): testing for interference
	between varname caching and name resolver.

2004-05-25  Kevin Kenny	 <kennykb@acm.org>

	* tests/winFCmd.test: Correct test for the presence of a CD-ROM so
	that it doesn't misdetect some other sort of filesystem with a
	write-protected root as being a CD-ROM drive. [Bug 918267]

2004-05-25  Don Porter	<dgp@users.sourceforge.net>

	* tests/winPipe.test:	Protect against path being set
	* tests/unixInit.test:	Unset path when done.
	* tests/unload.test (unload-3.1): Verify [pkgb_sub] does not exist.
	Delete interps when done.
	* tests/stringComp.test:	stop re-use of string.test test names
	* tests/regexpComp.test:	stop re-use of regexp.test test names
	* tests/namespace.test (namespace-46.3): Verify [p] does not exist.
	* tests/http.test:	Clear away the custom [bgerror] when done.
	* tests/io.test:	Take care to use namespace variables.
	* tests/autoMkindex.test (autoMkindex-5.2): Use variable "result"
	that gets cleaned up.
	* tests/exec.test:	Clean up the "path" array.
	* tests/interp.test (interp-9.3): Initialize res, so prior values
	cannot make the test fail.
	* tests/execute.test (execute-8.1):  Updated to remove the trace set
	on ::errorInfo. When left in place, that trace can cause later tests
	to fail.

2004-05-25  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclBasic.c: Removed references to Tcl_RenameCommand from
	* generic/tcl.h:      comments. [Bug 848440, second part]

	* tests/fCmd.test: Rewrote tests that failed consistently on NFS so
	they either succeed (through slightly more liberal matching of the
	results) or are constrained to not run. [Bug 931312]

	* doc/bgerror.n: Use idiomatic open flags for working with log
	files. [Bug 959602]

2004-05-24  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclExecute.c (VerifyExprObjType): use GET_WIDE_OR_INT to
	properly have tclIntType used for smaller values. This corrects [TclX
	Bug 896727] and any other 3rd party extension that created math
	functions but was not yet WIDE_INT aware in them.

2004-05-24  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclInterp.c (TclInitLimitSupport): Made limits work on
	platforms where sizeof(void*)!=sizeof(int). [Bug 959193]

2004-05-24 Miguel Sofer <msofer@users.sf.net>

	* doc/set.n: accurate description of name resolution process,
	referring to namespace.n for details [Bug 959180]

2004-05-23  Miguel Sofer <msofer@users.sf.net>

	* generic/tclNamesp.c (Tcl_FindNamespaceVar): [Bug 959052] fixed,
	insuring that no "zombie" variables are found.
	* generic/tclVar.c (TclLookupSimpleVar): comments re [Bug 736729]
	(predecessor of [Bug 959052]) removed.
	* tests/namespace.test: added tests 17.10-12

	The patch modifies non-documented behaviour, and passes every test in
	the testsuite. However, scripts relying on the old behaviour may
	break.
	Note that the only behaviour change concerns the creative writing of
	unset variables. More precisely, which variable will be created when
	neither a namespace variable nor a global variable by that name
	exists, as defined by [info vars]. The new behaviour is that the
	namespace resolution process deems a variable to exist exactly when
	[info vars] finds it - ie, either it has value, or else it was "fixed"
	by a call to [variable].
	Note: this patch was removed on 2002-05-25.

2004-05-22  Miguel Sofer <msofer@users.sf.net>

	* generic/tclVar.c (TclObjLookupVar, TclObjUnsetVar2): fix for new (in
	tcl8.4) exteriorisations of [Bug 736729] due to the use of
	tclNsVarNameType obj types. Reenabling the use of this objType ("VAR
	ref absolute" benchmark down to 66 ms, from 230). Added comments in
	TclLookupSimpleVar explaining my current understanding of [Bug
	736729].

2004-05-22  Miguel Sofer <msofer@users.sf.net>

	* generic/tclVar.c: fix for [Bug 735335]. The use of tclNsVarNameType
	objs is still disabled, pending resolution of [Bug 736729].

2004-05-21  Miguel Sofer <msofer@users.sf.net>

	* tests/namespace.test (namespace-41.3): removed the {knownBug}
	constraint: [Bug 231259] is closed since nov 2001, and the fix of [Bug
	729692] (INST_START_CMD) makes the test succeed.

2004-05-21  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclExecute.c (TclExecuteByteCode): Move a few declarations a
	short distance so pre-C99 compilers can cope. Also fix so
	TCL_COMPILE_DEBUG path compiles...

2004-05-21  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c (TclExecuteByteCode): reorganised TEBC
	automatic variables, defining them in tight blocks instead of at the
	function level. This has three purposes:
	- it simplifies the analysis of individual instructions
	- it is preliminary work to the non-recursive engine
	- it allows a better register allocation by the optimiser; under
	gcc3.3, this results in up to 10% runtime in some tests

2004-05-20  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclInterp.c (TclLimitRemoveAllHandlers):
	* generic/tclBasic.c (DeleteInterpProc):
	* tests/interp.test (interp-34.7): Ensure that all limit callbacks are
	deleted when their interpreters are deleted. [Bug 956083]

2004-05-19  Kevin B. Kenny  <kennykb@acm.org>

	* win/tclWinFile.c (TclpMatchInDirectory): fix for an issue where
	there was a sneak path from Tcl_DStringFree to SetErrorCode(0). The
	result was that the error code could be reset between a call to
	FindFirstFileEx and the check of its status return, leading to a
	bizarre error return of {POSIX unknown {No error}}. (Found in
	unplanned test - no incident logged at SourceForge.)

2004-05-19  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tests/interp.test (interp-34.3): Rewrite this test to see if a time
	limit can catch a tight bytecode loop, a maximally aggressive
	denial-of-service attack.
	* generic/tclInterp.c (Tcl_LimitCheck): Fix the sense of checks to see
	whether a time limit has been extended.

	* tests/*.test: Many minor fixes, including ensuring that every test
	is run (so constraints control whether the test is doing anything) and
	making sure that constraints are always set using the API instead of
	poking around inside tcltest's internal datastructures. Also got rid
	of all trailing whitespace lines from the test suite!

2004-05-19  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c: Fixed [SF Tcl Bug 943274]. This is the same problem
	* generic/tclIO.h: as [SF Tcl Bug 462317], see ChangeLog entry
	2001-09-26. The fix done at that time is incomplete. It is possible to
	get around it if the actual read operation is defered and not executed
	in the event handler itself. Instead of tracking if we are in an read
	caused by a synthesized fileevent we now track if the OS has delivered
	a true event = actual data and bypass the driver if a read finds that
	there is no actual data waiting. The flag is cleared by a short or
	full read.

	***POTENTIAL INCOMPATIBILITY*** for channel drivers.

2004-05-17  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclPathObj.c: fix to (Bug 956063) in 'file dirname'.
	* tests/cmdAH.test: added test for this bug.

	* doc/FileSystem.3: better documentation of refCount requirements of
	some FS functions (Bug 956126)

2004-05-19  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclTest.c (TestgetintCmd): Made the tests in get.test check
	* tests/get.test:		     Tcl_GetInt() since the core now
					     avoids that function.

2004-05-18  Kevin B. Kenny  <kennykb@acm.org>

	* compat/strftime.c (_fmt, ISO8601Week):
	* doc/clock.n:
	* tests/clock.test: Major rework to the handling of ISO8601 week
	numbers. Now passes all the %G and %V test cases on Windows, Linux and
	Solaris [Bugs 500285, 500389, and 852944]

2004-05-18  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/append.n, doc/upvar.n: Added example.

2004-05-18  David Gravereaux <davygrvy@pobox.com>

	* win/makefile.vc: now generates a tclConfig.sh from Pat Thoyts [Patch
	909911]

2004-05-18  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/lsearch.n: Improve clarity (based on [Patch 955361] by Peter
	Spjuth)

	* tools/man2help2.tcl (macro,SHmacro): Added support for subsection
	(.SS) header macros.

	* doc/interp.n: Added user documentation for the TIP#143 resource
	limits and some examples.

	* generic/tclInterp.c (Tcl_LimitCheck, Tcl_LimitTypeReset): Reset the
	limit-exceeded flag when removing a limit.

2004-05-18  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c (TclExecuteByteCode): added comments to
	classify the variables according to their use in TEBC.

2004-05-17  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/global.n, doc/uplevel.n: Added an example.

	* tests/info.test (info-3.1): Corrected test result back to what it
	used to be in Tcl 7.* now that command counts are being correctly kept

	* generic/tclExecute.c (TEBC:INST_START_CMD): Make sure that the
	command-count is always advanced. Allows TIP#143 limits to tell that
	work is being done.

	* doc/list.n: Updated example to fit with the unified format.
	* doc/seek.n: Added some examples.

2004-05-17  Vince Darley  <vincentdarley@users.sourceforge.net>

	* win/tclWinFile.c:
	* tests/cmdAH.test: fix to (Bug 954263) where 'file executable' was
	case-sensitive.

2004-05-17  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/OpenFileChnl.3: Documented type of 'offset' argument to Tcl_Seek
	was wrong. [Bug 953374]

2004-05-16  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c (TclExecuteByteCode): remove one level of
	indirection for compiledLocals addressing.

2004-05-16  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c (INST_CALL_FUNC1): bugfix; restored
	(DE)CACHE_STACK_INFO pair around the call - the user defined math
	function could cause a recursive call to TEBC.

2004-05-16  Miguel Sofer <msofer@users.sf.net>

	* generic/tclBasic.c (Tcl_DeleteInterp):
	* generic/tclExecute.c (INST_START_CMD): interp deletion now modifies
	the compileEpoch, eliminating the need for the check for interp
	deletion in INST_START_CMD.

2004-05-16  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.h:
	* generic/tclCompile.c:
	* generic/tclExecute.c: changed implementation of {expand}, last
	chance while in alpha as ...

	***POTENTIAL INCOMPATIBILITY***
	Scripts precompiled with ProComp under previous tcl8.5a versions may
	malfunction due to changed instruction numbers for
	INST_LIST_INDEX_IMM, INST_LIST_RANGE_IMM and INST_START_CMD.

2004-05-14  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclInt.decls:	     Promoted TclpLocaltime and TclpGmtime
	* generic/tclIntDecls.h:     from Unix-specific stubs to the generic
	* generic/tclIntPlatDecls.h: internal Stubs table. Reran 'genstubs'
	* generic/tclStubInit.c:
	* unix/tclUnixPort.h:

	* generic/tclClock.c: Changed a buggy 'GMT' timezone specification
			      to the correct 'GMT0'. [Bug 922848]

	* unix/tclUnixThrd.c: Moved TclpGmtime and TclpLocaltime to
			      unix/tclUnixTime.c where they belong.

	* unix/tclUnixTime.c (TclpGmtime, TclpLocaltime, TclpGetTimeZone,
			      ThreadSafeGMTime [removed],
			      ThreadSafeLocalTime [removed],
			      SetTZIfNecessary, CleanupMemory):
	Restructured to make sure that the same mutex protects all calls to
	localtime, gmtime, and tzset. Added a check in front of those calls to
	make sure that the TZ env var hasn't changed since the last call to
	tzset, and repeat tzset if necessary. [Bug 942078] Removed a buggy
	test of the Daylight Saving Time information in 'gettimeofday' in
	favor of applying 'localtime' to a known value. [Bug 922848]

	* tests/clock.test (clock-3.14): Added test to make sure that changes
	to $env(TZ) take effect immediately.

	* win/tclWinTime.c (TclpLocaltime, TclpGmtime): Added porting layer
	for 'localtime' and 'gmtime' calls.

2004-05-14  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c:
	* generic/tclCompile.h: the math functions receive a pointer to top of
	the stack (tosPtr) instead of the execution environment (eePtr). First
	step towards a change in the execution stack management - it is now
	only used within TEBC.

2004-05-13  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	TIP#143 IMPLEMENTATION

	* generic/tclExecute.c (TclCompEvalObj, TclExecuteByteCode):
	* generic/tclBasic.c (TclEvalObjvInternal): Enable limit checking.
	* generic/tclInterp.c (Tcl_Limit*): Public limit API.
	* generic/tcl.decls:
	* tests/interp.test: Basic tests of command limits.

	* doc/binary.n:		TIP#129 IMPLEMENTATION [Patch 858211]
	* generic/tclBinary.c:	Note that the test suite probably has many more
	* tests/binary.test:	failures now due to alterations in constraints.

2004-05-12  Miguel Sofer <msofer@users.sf.net>

	Optimisations for INST_START_CMD [Bug 926164].
	* generic/tclCompile.c (TclCompileScript): avoid emitting
	INST_START_CMD as the first instruction in a bytecoded Tcl_Obj. It is
	not needed, as the checks are done before calling TEBC.
	* generic/tclExecute.c (TclExecuteByteCode): runtime peephole
	optimisation: check at INST_POP if the next instruction is
	INST_START_CMD, in which case we fall through.

2004-05-11  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/split.n, doc/join.n: Updated examples and added more.

2004-05-11  Vince Darley  <vincentdarley@users.sourceforge.net>

	* doc/glob.n: documented behaviour of symbolic links with 'glob -types
	d' (Bug 951489)

2004-05-11  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/scan.n: Updated the examples to be clearer about their relevance
	to the scan command.

2004-05-10  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/scan.n: Added examples.

2004-05-10  David Gravereaux <davygrvy@pobox.com>

	* win/tclWinPipe.c (BuildCommandLine): Moved non-obvious appending
	logic to outside the loop and added commentary for its purpose. Also
	use the existence of contents in the linePtr rather than the scratch
	DString post the append, as this more clear.

	(TclpCreateProcess): When under NT, with no console, and executing a
	DOS application, the path priming does not need an ending space as
	BuildCommandLine() will do this for us.

2004-05-08  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFileName.c:
	* generic/tclIOUtil.c: remove some compiler warnings on MacOS X.

2004-05-07  Chengye Mao <chengye.geo@yahoo.com>

	* win/tclWinPipe.c: refixed bug 789040 re-entered in rev 1.41. Let's
	be careful and don't re-enter previously fixed bugs.

2004-05-08  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/format.n: Added examples.

2004-05-07  Miguel Sofer <msofer@users.sf.net>

	* doc/unset.n: added upvar.n to the "see also" list

2004-05-07  Reinhard Max  <max@suse.de>

	* generic/tclEncoding.c:
	* tests/encoding.test: added support and tests for translating
	embedded null characters between real nullbytes and the internal
	representation on input/output [Bug 949905].

2004-05-07  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFileName.c:
	* generic/tclIOUtil.c:
	* generic/tclFileSystem.h:
	* tests/fileSystem.test: fix for [Bug 943995], in which vfs-registered
	root volumes were not handled correctly as glob patterns in all
	circumstances.

2004-05-06  Miguel Sofer <msofer@users.sf.net>

	* generic/tclInt.h:
	* generic/tclObj.c (TclFreeObj): made TclFreeObj use the new macro
	TclFreeObjMacro(), so that the allocation and freeing of Tcl_Obj is
	defined in a single spot (the macros in tclInt.h), with the exception
	of the TCL_MEM_DEBUG case.
	The #ifdef logic for the corresponding macros has been reformulated to
	make it clearer.

2004-05-05  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/break.n, doc/continue.n, doc/for.n, doc/while.n: More examples.

2004-05-05  Don Porter	<dgp@users.sourceforge.net>

	* tests/unixInit.test (unixInit-2.10):	Test correction for Mac OSX.
	Be sure to consistently compare normalized path names. Thanks to
	Steven Abner (tauvan). [Bug 948177]

2004-05-05  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/CrtObjCmd.3: Remove reference to Tcl_RenameCommand; there is no
	such API. [Bug 848440]

2004-05-05  David Gravereaux <davygrvy@pobox.com>

	* win/tclWinSock.c (SocketEventProc) : connect errors should fire both
	the readable and writable handlers because this is how it works on
	UNIX [Bug 794839]

	* generic/tclEncoding.c (TclFinalizeEncodingSubsystem):
	FreeEncoding(systemEncoding); moved to before the hash table iteration
	as it was causing a double free attempt under some conditions.

	* win/coffbase.txt: Added the tls extension to the list of preferred
	load addresses.

2004-05-04  Jeff Hobbs	<jeffh@ActiveState.com>

	* tests/fileSystem.test (filesystem-1.39): replace 'file volumes'
	* tests/fileName.test (filename-12.9,10):  lindex with direct C:/
	hard-coded because A:/ was being used and that is empty for most.

	* tests/winFCmd.test (winFCmd-16.12): test volumerelative $HOME

2004-05-04  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclAlloc.c:		Make sure Tclp*Alloc* routines get
	* generic/tclInt.h:		declared in the TCL_MEM_DEBUG and
	* generic/tclThreadAlloc.c:	TCL_THREADS configuration. [Bug 947564]

	* tests/tcltest.test:	Test corrections for Mac OSX. Thanks to Steven
	Abner (tauvan). [Bug 947440]

2004-05-04  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclEvent.c (TclSetLibraryPath): Suppress a warning.

2004-05-03  Andreas Kupries  <andreask@activestate.com>

	* Applied [Patch 868853], fixing a mem leak in TtySetOptionProc.
	Report and Patch provided by Stuart Cassoff <stwo@users.sf.net>.

2004-05-03  Miguel Sofer <msofer@users.sf.net>

	* generic/tclProc.c (TclCreateProc): comments corrected.

2004-05-03  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c (TclCompileScript): setting the compilation
	namespace outside of the loop.

2004-05-03  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c:
	* generic/tclInt.h: reverted fix for [Bug 926445] of 2004-04-02,
	restoring TCL_ALIGN to the header file. Todd Helfter reported that the
	macro is required by tbcload.

2004-05-03  Kevin Kenny	 <kennykb@acm.org>

	* win/tclWin32Dll.c (TclpCheckStackSpace):
	* tests/stack.test (stack-3.1): Fix for undetected stack overflow in
	TclReExec on Windows. [Bug 947070]

2004-05-03  Don Porter	<dgp@users.sourceforge.net>

	* library/init.tcl:	Corrected unique prefix matching of
	interactive command completion in [unknown]. [Bug 946952]

2004-05-02  Miguel Sofer <msofer@users.sf.net>

	* generic/tclProc.c (TclObjInvokeProc):
	* tests/proc.test (proc-3.6): fix for bad quoting of multi-word proc
	names in error messages [Bug 942757]

2004-04-30  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/glob.n, doc/incr.n, doc/set.n:	More examples.
	* doc/if.n, doc/rename.n, doc/time.n:

2004-04-30  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclInt.h:		Replaced Kevin Kenny's temporary
	* generic/tclThreadAlloc.c:	fix for Bug 945447 with a cleaner,
	more permanent replacement.

2004-04-30  Kevin B. Kenny   <kennykb@acm.org>

	* generic/tclThreadAlloc.c: Added a temporary (or so I hope!)
	inclusion of "tclWinInt.h" to avoid problems when compiling on
	Win32-VC++ with --enable-threads. [Bug 945447]

2004-04-30  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/puts.n: Added a few examples.

2004-04-29  Don Porter	<dgp@users.sourceforge.net>

	* tests/execute.test (execute-8.2):	Avoid crashes when there is
	limited system stack space (threads-enabled).

2004-04-28  Miguel Sofer <msofer@users.sf.net>

	* doc/global.n:
	* doc/upvar.n:
	* generic/tclVar.c (ObjMakeUpvar):
	* tests/upvar.test (upvar-8.11):
	* tests/var.test (var-3.11): Avoid creation of unusable variables:
	[Bug 600812] [TIP 184].

2004-04-28  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/lsearch.n: Fixed fault in documentation of -index option [943448]

2004-04-26  Don Porter	<dgp@users.sourceforge.net>

	* unix/tclUnixFCmd.c (TclpObjNormalizePath):  Corrected improper
	positioning of returned checkpoint. [Bug 941108]

2004-04-26  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/open.n, doc/close.n: Updated (thanks to David Welton) to be
	clearer about pipeline errors and added example to open(n) that shows
	simple pipeline use. [Patches 941377,941380]

	* doc/DictObj.3: Added warning about the use of Tcl_DictObjDone and an
	example of use of iteration. [Bug 940843]

	* doc/Thread.3: Reworked to remove references to testing interfaces
	and instead promote the use of the Thread package. [Patch 932527]
	Also reworked and reordered the page for better readability.

2004-04-25  Don Porter	<dgp@users.sourceforge.net>

	* generic/tcl.h:	Removed obsolete declarations and #include's.
	* generic/tclInt.h:	[Bugs 926459, 926486]

2004-04-24  David Gravereaux <davygrvy@pobox.com>

	* win/tclWin32Dll.c (DllMain): Added DisableThreadLibraryCalls() for
	the DLL_PROCESS_ATTACH case. We're not interested in knowing about
	DLL_THREAD_ATTACH, so disable the notices.

2004-04-24  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclPort.h:
	* macosx/Makefile:
	* unix/Makefile.in: followup on tcl header reform [FR 922727]: removed
	use of relative #include paths in tclPort.h to allow installation of
	private headers outside of tcl source tree; added 'unix' dir to
	compiler header search path; add newly required tcl private headers to
	Tcl.framework on Mac OSX.

2004-04-23  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c (Tcl_SetChannelOption): Fixed [SF Tcl Bug 930851].
	When changing the eofchar we have to zap the related flags to prevent
	them from prematurely aborting the next read.

2004-04-25  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclPathObj.c: fix to [Bug 940281]. Tcl_FSJoinPath will now
	always return a valid Tcl_Obj when the input is valid.
	* generic/tclIOUtil.c: fix to [Bug 931823] for a more consistent
	Tcl_FSPathSeparator() implementation which allows filesystems not to
	implement their Tcl_FSFilesystemSeparatorProc if they wish to use the
	default '/'. Also fixed associated memory leak seen with, e.g., tclvfs
	package.
	* doc/FileSystem.3: documented Tcl_FSJoinPath return values more
	clearly, and Tcl_FSFilesystemSeparatorProc requirements.

2004-04-23  David Gravereaux <davygrvy@pobox.com>

	* win/tclWin32Dll.c: Removed my mistake from 4/19 of adding an exit
	handler to TclWinInit. TclWinEncodingsCleanup called from
	TclFinalizeFilesystem does the Tcl_FreeEncoding for us.

	* win/tclWinChan.c (Tcl_MakeFileChannel): Case for CloseHandle
	returning zero and not throwing a
	RaiseException(EXCEPTION_INVALID_HANDLE) now being done.

2004-04-22  David Gravereaux <davygrvy@pobox.com>

	* generic/tclEvent.c: TclSetLibraryPath's use of caching the stringrep
	of the pathPtr object to TclGetLibraryPath called from another thread
	was ineffective if the original's stringrep had been invalidated as
	what happens when it gets muted to a list.

	* win/tclWinTime.c: If the Tcl_ExitProc (StopCalibration) is called
	from the stack frame of DllMain's PROCESS_DETACH, the wait operation
	should timeout and continue.

	* generic/tclInt.h:
	* generic/tclThread.c:
	* generic/tclEvent.c:
	* unix/tclUnixThrd.c:
	* win/tclWinThrd.c: Provisions made so masterLock, initLock, allocLock
	and joinLock mutexes can be recovered during Tcl_Finalize.

2004-04-22  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/switch.n: Reworked the examples to be more systematically named
	and to cover some TIP#75 capabilities.

	* doc/cd.n: Documentation clarification from David Welton.

	* doc/exec.n: Added some examples, Windows ones from Arjen Markus and
	Unix ones by myself.

2004-04-21  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/Hash.3: Added note to Tcl_{First,Next}HashEntry docs that
	deleting the element they return is supported (and is in fact the only
	safe update you can do to the structure of a hashtable while an
	iteration is going over it.)

	* doc/bgerror.n: Added example from David Welton. [Patch 939473]

	* doc/after.n: Added examples from David Welton. [Patch 938820]

2004-04-19  David Gravereaux <davygrvy@pobox.com>

	* win/tclWin32Dll.c: Added an exit handler in TclWinInit() so
	tclWinTCharEncoding could be freed during Tcl_Finalize().

	* generic/tclEncoding.c: Added FreeEncoding(systemEncoding) in
	TclFinalizeEncodingSubsystem because its ref count was incremented in
	TclInitEncodingSubsystem.

2004-04-19  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/read.n: Added example from David Welton. [Patch 938056]

2004-04-19  Kevin B. Kenny   <kennykb@acm.org>

	* generic/tclObj.c (Tcl_GetDoubleFromObj) Corrected "short circuit"
	conversion of int to double. Reported by Jeff Hobbs on the Tcl'ers
	Chat.

2004-04-16  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/lreplace.n, doc/lrange.n, doc/llength.n:	More examples for
	* doc/linsert.n, doc/lappend.n:			the documentation.

2004-04-16  Vince Darley  <vincentdarley@users.sourceforge.net>

	* doc/FileSystem.3: Corrected documentation of Tcl_FSUtime, and the
	corresponding filesystem driver Tcl_FSUtimeProc. [Bug 935838]

2004-04-16  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/socket.n: Added example from [Patch 936245].
	* doc/gets.n: Added example based on [Patch 935911].

2004-04-15  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclClock.c (Tcl_ClockObjCmd): Minor fault in a [clock
	clicks] error message.

2004-04-07  Jeff Hobbs	<jeffh@ActiveState.com>

	* win/tclWinInit.c (TclpSetInitialEncodings): note that WIN32_CE is
	also a unicode platform.
	* generic/tclEncoding.c (TclFindEncodings, Tcl_FindExecutable):
	* generic/tclInt.h:			    Correct handling of UTF
	* unix/tclUnixInit.c (TclpInitLibraryPath): data that is actually
	* win/tclWinFile.c (TclpFindExecutable):    "clean", allowing the
	* win/tclWinInit.c (TclpInitLibraryPath):   loading of Tcl from paths
	that contain multi-byte chars on Windows [Bug 920667]

	* win/configure:    define TCL_LIB_FLAG, TCL_BUILD_LIB_SPEC,
	* win/configure.in: TCL_LIB_SPEC, TCL_PACKAGE_PATH in tclConfig.sh.

2004-04-06  Don Porter	<dgp@users.sourceforge.net>

	Patch 922727 committed.	 Implements three changes:

	* generic/tclInt.h:	Reworked the Tcl header files into a clean
	* unix/tclUnixPort.h:	hierarchy where tcl.h < tclPort.h < tclInt.h
	* win/tclWinInt.h:	and every C source file should #include
	* win/tclWinPort.h:	at most one of those files to satisfy its
	declaration needs. tclWinInt.h and tclWinPort.h also better organized
	so that tclWinPort.h includes the Windows implementation of
	cross-platform declarations, while tclWinInt.h makes declarations that
	are available on Windows only.

	* generic/tclBinary.c (TCL_NO_MATH):	Deleted the generic/tclMath.h
	* generic/tclMath.h (removed):		header file. The internal Tcl
	* macosx/Makefile (PRIVATE_HEADERS):	header, tclInt.h, has a
	* win/tcl.dsp:				#include <math.h> directly,
	and file external to Tcl needing libm should do the same.

	* win/Makefile.in (WIN_OBJS):	Deleted the win/tclWinMtherr.c file.
	* win/makefile.bc (TCLOBJS):	It's a vestige from matherr() days
	* win/makefile.vc (TCLOBJS):	gone by.
	* win/tcl.dsp:
	* win/tclWinMtherr.c (removed):

	End Patch 922727.

	* tests/unixInit.test (unixInit-3.1):	Default encoding on Darwin
	systems is utf-8. Thanks to Steven Abner (tauvan). [Bug 928808]

2004-04-06  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tests/cmdAH.test (cmdAH-18.2): Added constraint because
	access(...,X_OK) is defined to be permitted to be meaningless when
	running as root, and OSX exhibits this. [Bug 929892]

2004-04-02  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c:
	* generic/tclInt.h: removed the macro TCL_ALIGN() from tclInt.h,
	replaced by the static macro ALIGN() in tclCompile.c [Bug 926445]

2004-04-02  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.h: removed redundant #ifdef _TCLINT [Bug 928415],
	reported by tauvan.

2004-04-02  Don Porter	<dgp@users.sourceforge.net>

	* tests/tcltest.test: Corrected constraint typos: "nonRoot" ->
	"notRoot". Thanks to Steven Abner (tauvan). [Bug 928353]

2004-04-01  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclInt.h:  Removed obsolete tclBlockTime* declarations. [Bug
	926454]

2004-04-01  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclIOUtil.c: Fix to privately reported vfs bug with 'glob
	-type d -dir . *' across a vfs boundary. No tests for this are
	currently possible without effectively moving tclvfs into Tcl's test
	suite.

2004-03-31  Don Porter	<dgp@users.sourceforge.net>

	* doc/msgcat.n:	Clarified message catalog file encodings. [Bug 811457]
	* library/msgcat/msgcat.tcl: Updated internals to make use of [dict]s
	to store message catalog data and to use [source -encoding utf-8] to
	access catalog files. Thanks to Michael Sclenker. [Patch 875055, RFE
	811459] Corrected [mcset] to be able to successfully set a translation
	to the empty string. [mcset $loc $src {}] was incorrectly set the $loc
	translation of $src back to $src. Also changed [ConvertLocale] to
	minimally require a non-empty "language" part in the locale value. If
	not, an error raised prompts [Init] to keep looking for a valid locale
	value, or ultimately fall back on the "C" locale. [Bug 811461].
	* library/msgcat/pkgIndex.tcl:	Bump to msgcat 1.4.1.

2004-03-30  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclHash.c (HashStringKey): Cleaned up. This function is not
	faster, but it is a little bit clearer.
	* generic/tclLiteral.c (HashString): Applied logic from HashObjKey.
	* generic/tclObj.c (HashObjKey): Rewrote to fix fault which hashed
	every single-character object to the same hash bucket. The new code is
	shorter, simpler, clearer, and (happily) faster.

2004-03-30  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c (TEBC): reverting to the previous method for
	async tests in TEBC, as the new method turned out to be too costly.
	Async tests now run every 64 instructions.

2004-03-30  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c:	    New instruction code INST_START_CMD that
	* generic/tclCompile.h:	    allows checking the bytecode's validity
	* generic/tclExecute.c:	    [Bug 729692] and the interp's readyness
	* tests/interp.test (18.9): [Bug 495830] before running the command.
	* tests/proc.test (7.1):    It also changes the mechanics of the async
	* tests/rename.test (6.1):  tests in TEBC, doing it now at command
	start instead of every 16 instructions.

2004-03-30  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFileName.c:  Fix to Windows glob where the pattern is a
	* generic/tclIOUtil.c:	  volume relative path or a network share [Bug
	* tests/fileName.test:	  898238]. On windows 'glob' will now return
	* tests/fileSystem.test:  the results of 'glob /foo/bar' and 'glob
	\\foo\\bar' as 'C:/foo/bar', i.e. a correct absolute path (rather than
	a volume relative path).

	Note that the test suite does not test commands like
	'glob //Machine/Shared/*' (on a network share).

2004-03-30  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclPathObj.c:	  Fix to filename bugs recently
	* tests/fileName.test:	  introduced [Bug 918320].

2004-03-29  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclMain.c (Tcl_Main, StdinProc):	Append newline only
	* tests/basic.test (basic-46.1):		to incomplete scripts
	as part of multi-line script construction. Do not add an extra
	trailing newline to the complete script. [Bug 833150]

2004-03-28  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c (TclCompileScript): corrected possible segfault
	when a compilation returns TCL_OUTLINE_COMPILE after having grown the
	compile environment [Bug 925121].

2004-03-27  Miguel Sofer <msofer@users.sf.net>

	* doc/array.n: added documentation for trace-realted behaviour of
	'array get' [Bug 449893]

2004-03-26  Don Porter	<dgp@users.sourceforge.net>

	* README:		Bumped version number to 8.5a2 to distinguish
	* tools/tcl.wse.in:	HEAD of CVS development from the recent 8.5a1
	* unix/configure.in:	release.
	* unix/tcl.spec:
	* win/README.binary:
	* win/configure.in:

	* unix/configure:	autoconf-2.57
	* win/configure:

2004-03-26  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclPathObj.c:	  Fix to Windows-only volume relative path
	* tests/fileSystem.test:  normalization. [Bug 923568]. Also fixed
	another volume relative bug found while testing.

2004-03-24  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclNamesp.c (NsEnsembleImplementationCmd): Fix messed up
	handling of strncmp result which just happened to work in some libc
	implementations. [Bug 922752]

2004-03-23  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/StringObj.3: Inverted the sense of the documentation of how the
	bytes parameter is documented to match behaviour. [Bug 921464]

2004-03-19  Kevin B. Kenny   <kennykb@acm.org>

	* compat/strtoll.c:
	* compat/strtoull.c:
	* generic/tclIntDecls.h:
	* generic/tclMain.c:
	* generic/tclObj.c:
	* win/tclWinDde.c:
	* win/tclWinReg.c:
	* win/tclWinTime.c:	   Made HEAD build on Windows VC++ again.

2004-03-19  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclIntDecls.h: Made HEAD build on Solaris again by applying
	fix recommended by Don Porter.

2004-03-18  Reinhard Max  <max@suse.de>

	* generic/tclIntDecls.h: Removed TclpTime_t. It wasn't really needed,
	* generic/tclInt.h:	 but caused warnings related to
	* generic/tclInt.decls:	 strict aliasing with GCC 3.3.
	* generic/tclClock.c:
	* generic/tclDate.c:
	* generic/tclGetDate.y:
	* win/tclWinTime.c:
	* unix/tclUnixTime.c:

	* generic/tclNamesp.c:	 Added temporary pointer variables to work
	* generic/tclStubLib.c:	 around warnings related to
	* unix/tclUnixChan.c:	 strict aliasing with GCC 3.3.

	* unix/tcl.m4:		 Removed -Wno-strict-aliasing.

2004-03-18  Daniel Steffen  <das@users.sourceforge.net>

	Removed support for Mac OS Classic platform [Patch 918142]

	* README:
	* compat/string.h:
	* doc/Encoding.3:
	* doc/FileSystem.3:
	* doc/Init.3:
	* doc/Macintosh.3 (removed):
	* doc/OpenFileChnl.3:
	* doc/OpenTcp.3:
	* doc/SourceRCFile.3:
	* doc/Thread.3:
	* doc/clock.n:
	* doc/exec.n:
	* doc/fconfigure.n:
	* doc/file.n:
	* doc/filename.n:
	* doc/glob.n:
	* doc/open.n:
	* doc/puts.n:
	* doc/resource.n (removed):
	* doc/safe.n:
	* doc/source.n:
	* doc/tclvars.n:
	* doc/unload.n:
	* generic/README:
	* generic/tcl.decls:
	* generic/tcl.h:
	* generic/tclAlloc.c:
	* generic/tclBasic.c:
	* generic/tclCmdAH.c:
	* generic/tclDate.c:
	* generic/tclDecls.h:
	* generic/tclFCmd.c:
	* generic/tclFileName.c:
	* generic/tclGetDate.y:
	* generic/tclIOCmd.c:
	* generic/tclIOUtil.c:
	* generic/tclInitScript.h:
	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclIntDecls.h:
	* generic/tclIntPlatDecls.h:
	* generic/tclMain.c:
	* generic/tclMath.h:
	* generic/tclNotify.c:
	* generic/tclPathObj.c:
	* generic/tclPlatDecls.h:
	* generic/tclPort.h:
	* generic/tclStubInit.c:
	* generic/tclTest.c:
	* generic/tclThreadJoin.c:
	* library/auto.tcl:
	* library/init.tcl:
	* library/package.tcl:
	* library/safe.tcl:
	* library/tclIndex:
	* mac/AppleScript.html (removed):
	* mac/Background.doc (removed):
	* mac/MW_TclAppleScriptHeader.h (removed):
	* mac/MW_TclAppleScriptHeader.pch (removed):
	* mac/MW_TclBuildLibHeader.h (removed):
	* mac/MW_TclBuildLibHeader.pch (removed):
	* mac/MW_TclHeader.h (removed):
	* mac/MW_TclHeader.pch (removed):
	* mac/MW_TclHeaderCommon.h (removed):
	* mac/MW_TclStaticHeader.h (removed):
	* mac/MW_TclStaticHeader.pch (removed):
	* mac/MW_TclTestHeader.h (removed):
	* mac/MW_TclTestHeader.pch (removed):
	* mac/README (removed):
	* mac/bugs.doc (removed):
	* mac/libmoto.doc (removed):
	* mac/morefiles.doc (removed):
	* mac/porting.notes (removed):
	* mac/tclMac.h (removed):
	* mac/tclMacAETE.r (removed):
	* mac/tclMacAlloc.c (removed):
	* mac/tclMacAppInit.c (removed):
	* mac/tclMacApplication.r (removed):
	* mac/tclMacBOAAppInit.c (removed):
	* mac/tclMacBOAMain.c (removed):
	* mac/tclMacChan.c (removed):
	* mac/tclMacCommonPch.h (removed):
	* mac/tclMacDNR.c (removed):
	* mac/tclMacEnv.c (removed):
	* mac/tclMacExit.c (removed):
	* mac/tclMacFCmd.c (removed):
	* mac/tclMacFile.c (removed):
	* mac/tclMacInit.c (removed):
	* mac/tclMacInt.h (removed):
	* mac/tclMacInterupt.c (removed):
	* mac/tclMacLibrary.c (removed):
	* mac/tclMacLibrary.r (removed):
	* mac/tclMacLoad.c (removed):
	* mac/tclMacMath.h (removed):
	* mac/tclMacNotify.c (removed):
	* mac/tclMacOSA.c (removed):
	* mac/tclMacOSA.r (removed):
	* mac/tclMacPanic.c (removed):
	* mac/tclMacPkgConfig.c (removed):
	* mac/tclMacPort.h (removed):
	* mac/tclMacProjects.sea.hqx (removed):
	* mac/tclMacResource.c (removed):
	* mac/tclMacResource.r (removed):
	* mac/tclMacSock.c (removed):
	* mac/tclMacTclCode.r (removed):
	* mac/tclMacTest.c (removed):
	* mac/tclMacThrd.c (removed):
	* mac/tclMacThrd.h (removed):
	* mac/tclMacTime.c (removed):
	* mac/tclMacUnix.c (removed):
	* mac/tclMacUtil.c (removed):
	* mac/tcltkMacBuildSupport.sea.hqx (removed):
	* tests/all.tcl:
	* tests/binary.test:
	* tests/cmdAH.test:
	* tests/cmdMZ.test:
	* tests/fCmd.test:
	* tests/fileName.test:
	* tests/fileSystem.test:
	* tests/interp.test:
	* tests/io.test:
	* tests/ioCmd.test:
	* tests/load.test:
	* tests/macFCmd.test (removed):
	* tests/osa.test (removed):
	* tests/resource.test (removed):
	* tests/socket.test:
	* tests/source.test:
	* tests/unload.test:
	* tools/cvtEOL.tcl (removed):
	* tools/genStubs.tcl:
	* unix/Makefile.in:
	* unix/README:
	* unix/mkLinks:
	* unix/tcl.spec:
	* win/README.binary:
	* win/tcl.dsp:

2004-03-17  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/lsearch.n: Improved examples on the advanced capabilities of
	lsearch (with the right options, set element removal can be done)
	following discussion on tkchat.

2004-03-16  Don Porter	<dgp@users.sourceforge.net>

	* doc/catch.n:	Compiled [catch] no longer fails to catch syntax
	errors. Removed the claims in the documentation that it does.
	* doc/return.n:	Updated example to use [dict merge].

2004-03-16  Jeff Hobbs	<jeffh@ActiveState.com>

	* unix/configure, unix/tcl.m4: add -Wno-strict-aliasing for GCC to
	suppress useless type puning warnings.

2004-03-16  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/file.n: *roff formatting fix. [Bug 917171]

2004-03-15  David Gravereaux <davygrvy@pobox.com>

	* win/tclWinNotify.c: Fixed a mistake where the return value of
	MsgWaitForMultipleObjectsEx for "a message is in the queue" wasn't
	accurate. I removed the check on the case result==(WAIT_OBJECT_0 + 1)
	This was having the error of falling into GetMessage and waiting there
	by accident, which wasn't alertable through Tcl_AlertNotifier. I'll do
	some more study on this and try to find-out why.

2004-03-12  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	IMPLEMENTATION OF TIP#163
	* generic/tclDictObj.c (DictMergeCmd):	This is based on work by Joe
	* tests/dict.test (dict-20.*):		English in Tcl [FRQ 745851]
	* doc/dict.n:				but not exactly.

2004-03-10  Kevin B. Kenny <kennykb@acm.org>

	* generic/tclGetDate.y (TclGetDate): Fix so that [clock scan
	<timeOfDay> -gmt true] uses the GMT base date instead of the local
	one. [Bug 913513]
	* tests/clock.test: Added test cases for wrong ISO8601 week number
	[Bug 500285] and wrong GMT base date [Bug 913513]. Several tests still
	fail on Windows, and these are actual faults in [clock scan]. Fix is
	still pending.
	* generic/tclDate.c: Regenerated.

2004-03-08  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFileName.c:  Fix to 'glob -path' near the root
	* tests/fileName.test:	  of the filesystem. [Bug 910525]

2004-03-08  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclParse.c (TclParseInit):	Modified TclParseInit so
	* generic/tclTest.c ([testexprparser]): that Tcl_Parse initialization
	conforms to documented promised about what fields will not be
	modified by what Tcl_Parse* routines. [Bug 910595]

2004-03-05  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/configure: Regen.
	* win/configure.in: Check for define of MWMO_ALERTABLE in winuser.h.
	* win/tclWinPort.h: If MWMO_ALERTABLE is not defined in winuser.h then
	define it. This is needed for Mingw.

2004-03-05  Kevin B. Kenny <kennykb@acm.org>

	* generic/tclTest.c: Modified TesteventObjCmd to use a
	Tcl_QueuePosition in place of an 'int' for the enumerated queue
	position, to avoid a compiler warning on SGI. [Bug 771960]

2004-03-05  Kevin B. Kenny <kennykb@acm.org>

	* tests/registry.test: Applied fix from [Patch 910174] to make the test
	for an English-language system include any country code, rather than
	just English-United States.1252. Thanks to Pat Thoyts for the changes.

2004-03-04  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* tests/registry.test: Applied fixed from [Bug 766159] to skip two
	tests on Win98 that depend on a Unicode registry (NT specific).

2004-03-04  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclInt.h (TclParseInit):	Factored the common code
	* generic/tclParse.c (TclParseInit):	for initializing a Tcl_Parse
	* generic/tclParseExpr.c:		struct into one routine.

2004-03-04  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* library/reg/pkgIndex.tcl:  Added TIP #100 support to the
	* win/tclWinReg.c:	     registry package [patch 903831]
	This provides a Windows test of the TIP #100 mechanism and a sample to
	show how unloading an extension can be done.

2004-03-04  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* unix/dltest/pkgua.c: Fix minor syntax problems. [Bug 909288]

2004-03-03  Jeff Hobbs	<jeffh@ActiveState.com>

	*** 8.5a1 TAGGED FOR RELEASE ***

	* changes: updated for 8.5a1

2004-03-03  David Gravereaux <davygrvy@pobox.com>

	* win/makefile.vc: default environment variable for VC++ is %MSDevDir%
	not %MSVCDir%, although vcvars32.bat sets both.

	* win/tclWinNotify.c (Tcl_WaitForEvent) : Allows an idling notifier to
	service "Asynchronous Procedure Calls" from its wait state. Only
	useful for extension authors who decide they might want to try
	"completion routines" with WriteFileEx(), as an example. From
	experience, I recommend that "completion ports" should be used instead
	as the execution of the callbacks are more managable.

2004-03-01  Jeff Hobbs	<jeffh@ActiveState.com>

	* README:	    update patchlevel to 8.5a1
	* generic/tcl.h:
	* tools/tcl.wse.in, tools/tclSplash.bmp:
	* unix/configure, unix/configure.in, unix/tcl.spec:
	* win/README.binary, win/configure, win/configure.in:

	* unix/tcl.m4: update HP-11 build libs setup

2004-03-01  Don Porter	<dgp@users.sourceforge.net>

	* unix/tcl.m4 (SC_CONFIG_CFLAGS):	Allow 64-bit enabling on
	IRIX64-6.5* systems. [Bug 218561]
	* unix/configure:	autoconf-2.57

	* generic/tclTrace.c (TclCheckInterpTraces):	The TIP 62
	* generic/tclTest.c (TestcmdtraceCmd):	implementation introduced a
	* tests/trace.test (trace-29.10):	bug by testing the CallFrame
	level instead of the iPtr->numLevels level when deciding what traces
	created by Tcl_Create(Obj)Trace to call. Added test to expose the
	error, and made fix. [FRQ 462580]

2004-02-28  Vince Darley  <vincentdarley@users.sourceforge.net>

	* tests/fileSystem.test: fix to Tcl Bug 905163.
	* tests/fileName.test: fix to Tcl Bug 904705.

	* doc/{various}.n: removed 'the the' typos.

2004-02-26  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Makefile: fixed copyright year in Tcl.framework Info.plist

2004-02-25  Don Porter	<dgp@users.sourceforge.net>

	* tests/basic.test:	Made several tests more robust to the
	* tests/cmdMZ.test:	list-quoting of path names that might contain
	* tests/exec.test:	Tcl-special chars like { or [. Should help us
	* tests/io.test:	sort out [Bug 554068]
	* tests/pid.test:
	* tests/socket.test:
	* tests/source.test:
	* tests/unixInit.test:

2004-02-25  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclLoad.c (Tcl_LoadObjCmd): Missing dereference caused
	segfault with non-loadable extension. [Bug 904307]

	* unix/tclUnixChan.c (TcpGetOptionProc): Stop memory leak with very
	long hostnames. [Bug 888777]

2004-02-25  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* win/tclWinDde.c: Removed some gcc warnings - except for the
	-Wconversion warning for GetGlobalAtomName. gcc is just wrong about
	this.

2004-02-24  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	IMPLEMENTATION OF TIP#100 FROM GEORGIOS PETASIS
	* generic/tclLoad.c (Tcl_UnloadObjCmd): Implementation.
	* tests/unload.test:			Test suite.
	* unix/dltest/pkgua.c:			Helper for test suite.
	* doc/unload.n:				Documentation.
	Also assorted changes (mostly small) to several other files.

2004-02-23  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/regc_locale.c (cclass): Buffer was having its size reset
	instead of being released => memleak. [Bug 902562]

2004-02-21  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclLoad.c (Tcl_LoadObjCmd): Fixed memory leak due to an
	improper error exit route.

2004-02-20  David Gravereaux <davygrvy@pobox.com>

	* win/tclWinSock.c (SocketThreadExitHandler): Don't call
	TerminateThread when WaitForSingleObject returns a timeout.
	Tcl_Finalize called from DllMain will pause all threads. Trust that
	the thread will get the close notice at a later time if it does ever
	wake up before being cleaned up by the system anyway.

2004-02-17  Don Porter	<dgp@users.sourceforge.net>

	* doc/tcltest.n:
	* library/tcltest/tcltest.tcl:	Changed -verbose default value to
	{body error} so that detailed information on unexpected errors in
	tests is provided by default, even after the fix for [Bug 725253]

2004-02-17  Jeff Hobbs	<jeffh@ActiveState.com>

	* tests/unixInit.test (unixInit-7.1):
	* unix/tclUnixInit.c (TclpInitPlatform): ensure the std fds exist to
	prevent crash condition [Bug 772288]

2004-02-17  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclCompCmds.c (TclCompileSwitchCmd): Bozo mistake in memory
	releasing order when in an error case. [Bug 898910]

2004-02-16  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclTrace.c (TclTraceExecutionObjCmd)
	(TclTraceCommandObjCmd): fix possible mem leak in trace info.

2004-02-12  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/tclWinInit.c (AppendEnvironment): Use the tail component of the
	passed in lib path instead of just blindly using lib+4. That worked
	when lib was "lib/..." but fails for other values. Thanks go to
	Patrick Samson for pointing this out.

2004-02-10  David Gravereaux  <davygrvy@pobox.com>

	* win/nmakehlp.c: better macro grepping logic.

2004-02-07  David Gravereaux  <davygrvy@pobox.com>

	* win/makefile.vc:
	* win/rules.vc:
	* win/tcl.rc:
	* win/tclsh.rc: Added an 'unchecked' option to the OPTS macro so a
	core built with symbols can be linked to the non-debug enabled C
	run-time. As per discussion with Kevin Kenny. Called like this:

		nmake -af makefile.vc OPTS=unchecked,symbols

	This clarifies the meaning of the 'g' naming suffix to mean only that
	the binary requires the debug enabled C run-time. Whether the binary
	contains symbols or not is a different condition.

2004-02-06  Don Porter	<dgp@users.sourceforge.net>

	* doc/clock.n:	Removed reference to non-existent [file ctime].

2004-02-05  David Gravereaux  <davygrvy@pobox.com>

	* docs/tclvars.n: Added clarification of the tcl_platform(debug) var
	that it only refers to the flavor of the C run-time, and not whether
	the core contains symbols.

2004-02-05  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclFileName.c (SkipToChar): Corrected CONST and type-casting
	issues that caused compiler warnings.

2004-02-04  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCmdAH.c (StoreStatData): Removed improper refcount
	decrement of the varName parameter. This error was causing segfaults
	following test cmdAH-28.7.

	* library/tcltest/tcltest.tcl: Corrected references to non-existent
	$name variable in [cleanupTests]. [Bug 833637]

2004-02-03  Don Porter	<dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl:	Corrected parsing of single command
	line argument (option with missing value) [Bug 833910]
	* library/tcltest/pkgIndex.tcl:	Bump to version 2.2.5.

2004-02-02  David Gravereaux <davygrvy@pobox.com>

	* generic/tclIO.c (Tcl_Ungets): Fixes improper filling of the channel
	buffer. This is the buffer before the splice. [Bug 405995]

2004-02-01  David Gravereaux <davygrvy@pobox.com>

	* tests/winPipe.test: more pass-thru commandline verifications.
	* win/tclWinPipe.c (BuildCommandLine): Special case quoting for '{'
	not required by the c-runtimes's parse_cmdline().
	* win/tclAppInit.c: Removed our custom setargv() in favor of the work
	provided by the c-runtime. [Bug 672938]

	* win/nmakehlp.c: defensive techniques to avoid static buffer
	overflows and a couple envars upsetting invokations of cl.exe and
	link.exe. [Bug 885537]

	* tests/winPipe.test: Added proof that BuildCommandLine() is not doing
	the "N backslashes followed a quote -> insert N * 2 + 1 backslashes
	then a quote" rule needed for the crt's parse_cmdline().
	* win/tclWinPipe.c: Fixed BuildCommandLine() to pass the new cases.

2004-01-30  David Gravereaux <davygrvy@pobox.com>

	* win/makefile.vc: Use the -GZ compiler switch when building for
	symbols. This is supposed to emulate the release build better to avoid
	hiding problems that only show themselves in a release build.

2004-01-29  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclPathObj.c: fix to [Bug 883143] in file normalization

2004-01-29  Vince Darley  <vincentdarley@users.sourceforge.net>

	* doc/file.n:
	* generic/tclFCmd.c
	* generic/tclTest.c
	* library/init.tcl
	* mac/tclMacFile.c
	* tests/fileSystem.test: fix to [Bug 886352] where 'file copy -force'
	had inconsistent behaviour wrt target files with insufficient
	permissions, particular from vfs->native fs. Behaviour of '-force' is
	now always consistent (and now consistent with behaviour of 'file
	delete -force'). Added new tests and documentation and cleaned up the
	'simplefs' test filesystem.

	* generic/tclIOUtil.c
	* unix/tclUnixFCmd.c
	* unix/tclUnixFile.c
	* win/tclWinFile.c: made native filesystems more robust to C code
	which asks for mount lists.

	* generic/tclPathObj.c: fix to [Bug 886607] removing warning/error
	with some compilers.

2004-01-28  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclObj.c (SetBooleanFromAny): Rewrite to do more efficient
	string->bool conversion.
	Many other minor whitespace/style fixes to this file too.

2004-01-27  David Gravereaux <davygrvy@pobox.com>

	* win/nmakehlp.c: Use '.\nul' as the sourcefile name instead of 'nul'
	so VC 5.2 doesn't try searching the path for it and failing with a
	possible dialogbox popping up about having to add a CD to an empty
	drive. Also added a SetErrorMode() call to disable any dialogs that
	cl.exe or link.exe might create. [Bug 885537]

2004-01-22  Vince Darley  <vincentdarley@users.sourceforge.net>

	* doc/file.n: clarified documentation of 'file system' [Bug 883825]
	* tests/fCmd.test: improved test result in failure case.

2004-01-22  Vince Darley  <vincentdarley@users.sourceforge.net>

	* tests/fileSystem.test: 3 new tests
	* generic/tclPathObj.c: fix to [Bug 879555] in file normalization.
	* doc/filename.n: small clarification to Windows behaviour with
	filenames like '.....', 'a.....', '.....a'.

	* generic/tclIOUtil.c: slight improvement to native cwd caching on
	Windows.

2004-01-21  David Gravereaux <davygrvy@pobox.com>

	* doc/Panic.3:	Mentions of 'panic' and 'panicVA' removed from the
	documentation.

2004-01-21  Vince Darley  <vincentdarley@users.sourceforge.net>

	* doc/FileSystem.3:
	* generic/tcl.decls:
	* generic/tclCmdAH.c
	* generic/tclDecls.h
	* generic/tclFCmd.c
	* generic/tclFileName.c
	* generic/tclFileSystem.h
	* generic/tclIOUtil.c
	* generic/tclInt.decls
	* generic/tclInt.h
	* generic/tclIntDecls.h
	* generic/tclPathObj.c
	* generic/tclStubInit.c
	* generic/tclTest.c
	* mac/tclMacFile.c
	* tests/fileName.test
	* tests/fileSystem.test
	* tests/winFCmd.test
	* unix/tclUnixFile.c
	* win/tclWin32Dll.c
	* win/tclWinFCmd.c
	* win/tclWinFile.c
	* win/tclWinInt.h

	Three main issues accomplished: (1) cleaned up variable names in the
	filesystem code so that 'pathPtr' is used throughout. (2) applied a
	round of filesystem optimisation with better handling and caching of
	relative and absolute paths, requiring fewer conversions. (3)
	clarifications to the documentation, particularly regarding the
	acceptable refCounts of objects. Some new tests added. Tcl benchmarks
	show a significant improvement over 8.4.5, and on Windows typically a
	small improvement over 8.3.5 (Unix still appears to require
	optimisation). TCL_FILESYSTEM_VERSION_2 introduced, but for internal
	use only. There should be no public incompatibilities from these
	changes. Thanks to dgp for extensive testing.

2004-01-19  David Gravereaux <davygrvy@pobox.com>

	* win/tclWinPipe.c (Tcl_WaitPid): Fixed a thread-safety problem with
	the process list. The delayed cut operation after the wait was going
	stale by being outside the list lock. It now cuts within the lock and
	does a locked splice for when it needs to instead. [Bug 859820]

2004-01-18  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclCompile.c, generic/tclCompile.h: Two new opcodes,
	INST_LIST_INDEX_IMM and INST_LIST_RANGE_IMM, that have operand(s) of
	new type OPERAND_IDX4 which represents indexes into things like lists
	(and perhaps other things eventually.)
	* generic/tclExecute.c (TclExecuteByteCode): Implementation of the new
	opcodes. INST_LIST_INDEX_IMM does a simple [lindex] with either front-
	or end-based simple indexing. INST_LIST_RANGE_IMM does an [lrange]
	with front- or end-based simple indexing for both the reference to the
	first and last items in the range.
	* generic/tclCompCmds.c (TclCompileLassignCmd): Generate bytecode for
	the [lassign] command.

2004-01-17  David Gravereaux <davygrvy@pobox.com>

	* win/tclWinInit.c: added #pragma comment(lib, "advapi32.lib") when
	compiling under VC++ so we don't need to specify it when linking.

2004-01-17  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclCmdIL.c (Tcl_LassignObjCmd): Add more shimmering
	protection for when the list is also one of the variables.

	BASIC IMPLEMENTATION OF TIP#57
	* generic/tclCmdIL.c (Tcl_LassignObjCmd): Implementation of the
	[lassign] command that takes full advantage of Tcl's object API.
	* doc/lassign.n: New file documenting the command.
	* tests/cmdIL.test (cmdIL-6.*): Test suite for the command.

2004-01-15  David Gravereaux <davygrvy@pobox.com>

	* win/tclWinReg.c: Placed the requirement for advapi.lib into the
	object file itself with #pragma comment (lib, ...) when built with
	VC++. This will simplify linking for users of the static library.

	* win/rules.vc: Added new 'fullwarn' to the CHECKS commandline macro;
	sets $(FULLWARNINGS).

	* win/makefile.vc: Removed 'advapi.lib' from $(baselibs). Added new
	logic to crank-up the warning levels for both compile and link when
	$(FULLWARNINGS) is set. Some clean-up with how the resource files are
	built and how -DTCL_USE_STATIC_PACKAGES is sent when compiling the
	shells.

	* win/tclAppInit.c: Small change in how TCL_USE_STATIC_PACKAGES is
	used.

	* win/tcl.rc:
	* win/tclsh.rc: Some clean-up with how the resource files are built.
	Fixed 'OriginalFilename' problem that still thought a debug suffix was
	still 'd', now is 'g'.

2004-01-14  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclDictObj.c (TraceDictPath, DictExistsCmd): Adjusted
	behaviour of [dict exists] so a failure to look up a dictionary along
	the path of dicts doesn't trigger an error. This is how it was
	documented to behave previously... [Bug 871387]

	* generic/tclDictObj.c: Assorted dict fixes from Peter Spjuth relating
	to [Bug 876170].
	(SetDictFromAny): Make sure that lists retain their ordering even when
	converted to dictionaries and back.
	(TraceDictPath): Correct object reference count handling!
	(DictReplaceCmd, DictRemoveCmd): Stop object leak.
	(DictIncrCmd,DictLappendCmd,DictAppendCmd,DictSetCmd,DictUnsetCmd):
	Simpler handling of reference counts when assigning to variables.
	* tests/dict.test (dict-19.2): Memory leak stress test

2004-01-13  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCmdMZ.c (Tcl_SwitchObjCmd):  Silence compiler warnings.

	Patch 876451: restores performance of [return]. Also allows forms such
	as [return -code error $msg] to be bytecompiled.

	* generic/tclInt.h:	Factored Tcl_ReturnObjCmd() into two pieces:
	* generic/tclCmdMZ.c:	TclMergeReturnOptions(), which can parse the
	options to [return], check their validity, and create the
	corresponding return options dictionary, and TclProcessReturn(), which
	takes that return options dictionary and performs the [return]
	operation.

	* generic/tclCompCmds.c: Rewrote TclCompileReturnCmd() to call
	TclMergeReturnOptions() at compile time so the return options
	dictionary is computed at compile time (when it is fully known). The
	dictionary is pushed on the stack along with the result, and the code
	and level values are included in the bytecode as operands. Also
	supports optimized compilation of un-[catch]ed [return]s from procs
	with default options into the INST_DONE instruction.

	* generic/tclExecute.c: Rewrote INST_RETURN instruction to retrieve
	the code and level operands, pop the return options from the stack,
	and call TclProcessReturn() to perform the [return] operation.

	* generic/tclCompile.h:	New utilities include TclEmitInt4 macro
	* generic/tclCompile.c:	and TclWordKnownAtCompileTime().

	End Patch 876451.

	* generic/tclFileName.c (Tcl_GlobObjCmd): Latest changes to management
	of the interp result by Tcl_GetIndexFromObj() exposed improper interp
	result management in the [glob] command procedure. Corrected by
	adopting the Tcl_SetObjResult(Tcl_NewStringObj) pattern. This stopped
	a segfault in test filename-11.36. [Bug 877677]

2004-01-13  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct, Tcl_WrongNumArgs):
	Create fresh objects instead of using the one currently in the
	interpreter, which isn't guaranteed to be fresh and unshared. The cost
	for the core will be minimal because of the object cache, and this
	fixes [Bug 875395].

2004-01-12  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompExpr.c (CompileLandOrLorExpr): cosmetic changes.

2004-01-12  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompExpr.c (CompileLandOrLorExpr): new logic, fewer
	instructions. As a side effect, the instructions INST_LOR and
	INST_LAND are now never used.
	* generic/tclExecute.c (INST_JUMP*): small optimisation; fix a bug in
	debug code.

2004-01-11  David Gravereaux <davygrvy@pobox.com>

	* win/tclWinThrd.c (Tcl_ConditionNotify): condPtr must be dereferenced
	to see if there are waiters else uninitialized datum is manipulated.
	[Bug 849007 789338 745068]

2004-01-09  David Gravereaux <davygrvy@pobox.com>

	* generic/tcl.h: Renamed and deprecated #defines moved to within the
	#ifndef TCL_NO_DEPRECATED block. This allows us to build Tcl to check
	for deprecated functions in use, such as panic() and Tcl_Ckalloc(). By
	request from DKF. Extensions that build with -DTCL_NO_DEPRECATED now
	have these macros as restricted.
	***POTENTIAL INCOMPATIBILITY***

	* win/makefile.vc:
	* win/rules.vc:	 Added -DTCL_NO_DEPRECATED usage to makefile.vc.
	Called like this:   nmake -af makefile.vc CHECKS=nodep

2004-01-09  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclIOUtil.c: fix to infinite loop in TclFinalizeFilesystem
	[Bug 873311]

	******************************************************************
	*** CHANGELOG ENTRIES FOR 2003 IN "ChangeLog.2003"	       ***
	*** CHANGELOG ENTRIES FOR 2002 IN "ChangeLog.2002"	       ***
	*** CHANGELOG ENTRIES FOR 2001 IN "ChangeLog.2001"	       ***
	*** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000"	       ***
	*** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" ***
	******************************************************************

Deleted ChangeLog.2005.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
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
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822














































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
2005-12-30  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclStubLib.c: Corrected a typo in "missing Stubs table
	pointer."

2005-12-27  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tcl.decls:  Destubbed TclTomMathInitializeStubs - it is in
	* generic/tcl.h:      the stub library, not the main shared
	* generic/tclBasic.c: library. Exported Tcl_InitBignumFromDouble.
	* generic/tclExecute.c:
	* generic/tclInt.h:
	* generic/tclStrToD.c:

	* generic/tclDecls.h:
	* generic/tclStubLib.c:
	* generic/tclStubInit.c: Regenerated.

	* generic/clock.tcl: Reverted to using the time zone abbreviation and
	not its name to "stop the bleeding" on [Bug 1386377]. This is *not* a
	good long-term solution, but there may not be one.

	* libtommath/bn_mp_sqrt.c: Improved the initial approximation to the
	square root, roughly doubling the speed of the routine. (This is a
	local change that needs to be communicated to Tom.)

	* win/Makefile.in: Corrected a bug where tommath_class.h and
	tommath_superclass.h were not installed, making it impossible for
	client code to compile against the tommath stubs.

	* library/tzdata: Updated to Olson's tzdata2005r. (Latest changes to
	Daylight Saving Time in Canada, plus redefinition of the Posix-style
	zones [e.g., EST5EDT] to be locale-independent.)

	* libtommath: Updated to Tom St.Denis's release 0.37.

2005-12-20  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclThreadAlloc.c (Tcl_GetMemoryInfo): Format values as longs
	and not ints, so they are less likely to wrap on 64-bit machines.

2005-12-19  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCmdMZ.c:	Modified [string is double] to use
	* tests/string.test:	TclParseNumber() to parse trailing whitespace.
	Ensures consistency, and makes it easier to cleanup after invalid
	internal reps left behind by parsing [Bugs 1360532 1382287].

	* generic/tclParseExpr.c:	Added TCL_PARSE_NO_WHITESPACE to
	* generic/tclScan.c:	TclParseNumber() calls since [scan] and [expr]
	* tests/scan.test:	parsing don't want spaces in parsed numbers.

	* generic/tclInt.h:	Added TCL_PARSE_NO_WHITESPACE flag to the
	* generic/tclStrToD.c:	TclParseNumber() interface.

2005-12-19  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* doc/Tcl.n: Clarify what is going on in variable substitution
	following thread on comp.lang.tcl.

2005-12-18  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclCompCmds.c (TclCompileDictCmd): Ensure that we only do an
	'endCatch' when there's a preceding 'beginCatch'. [Bug 1382528] Many
	thanks to Anton Kovalenko for finding this and pointing out that it was
	a catch stack handling problem!

2005-12-14  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclIOUtil.c: workaround gcc warning "comparison is always
	* generic/tclTest.c:   false due to limited range of data type".

	* macosx/Tcl.xcode/project.pbxproj:
	* macosx/Tcl.xcodeproj/project.pbxproj:
	* unix/Makefile.in: add new tclTomMath* files.

	* generic/tclBasic.c: replace panic with Tcl_Panic.

2005-12-13  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tcl.decls:    Added changes to export an additional stubs
	* generic/tclBasic.c:   table to represent the 'libtommath' routines
	* generic/tclDecls.h:   that Tcl uses and export them to callers.
	* generic/tclInt.decls: Reran 'genstubs'
	* generic/tclInt.h:
	* generic/tclIntDecls.h:
	* generic/tclIntPlatDecls.h:
	* generic/tclStubInit.c:
	* generic/tclStubLib.c:
	* generic/tclTomMath.decls:
	* generic/tclTomMath.h:
	* generic/tclTomMathDecls.h:
	* generic/tclTomMathInterface.c:
	* generic/tommath.h:
	* tools/fix_tommath_h.tcl:
	* unix/Makefile.in:
	* win/Makefile.in:
	* win/makefile.vc:

	* generic/tclClock.c:   Made changes to silence a number of compiler
	* generic/tclIO.c:	warnings when building with mingw.
	* generic/tclIORChan.c:
	* generic/tclLink.c:
	* generic/tclListObj.c:
	* generic/tclObj.c:
	* generic/tclParseExpr.c:
	* generic/tclProc.c:
	* generic/tclTimer.c:
	* win/tclWinChan.c:
	* win/tclWinConsole.c:
	* win/tclWinDde.c:
	* win/tclWinFCmd.c:
	* win/tclWinFile.c:
	* win/tclWinReg.c:
	* win/tclWinSock.c:

2005-12-13  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclExecute.c (TEBC:DICT_FIRST,DICT_DONE): Only decrease the
	references to the dictionary once the iteration completes. Do this by
	storing the dict in the iterator context variable. [Bug 1379349] Thanks
	to Ulrich Ring and Tobias Hippler for finding this.

2005-12-12  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/tcl.m4, unix/configure: Fix sh quoting error reported in
	bash-3.1+ [Bug 1377619] (schafer)

2005-12-12  Kevin B. Kenny  <kennykb@acm.org>

	* doc/mathfunc.n: Changed two examples from the incorrect 'tcl::math::'
	to 'tcl::mathfunc::' [Bug 1378818]

2005-12-09  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/configure: Regen.
	* win/tcl.m4 (SC_CONFIG_CFLAGS): Define MACHINE for gcc builds. The
	lack of a definition of this variable in the manifest file was causing
	a runtime error in wish built with gcc.

2005-12-09  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* tests/lsearch.test (lsearch-10.8..10):  If the -start is off the end,
	* generic/tclCmdIL.c (Tcl_LsearchObjCmd): searching should find nothing
	at all. [Bug 1374778]

2005-12-08  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/Makefile.in, win/makefile.vc: Add Win x64 and CE build support
	* win/tcl.m4, win/configure:        CE still requires C code fixes.

	* generic/tcl.h: use struct __stat64 (not _stat64) for MSC_VER >= 1400
	(i.e. latest Platform SDK).

2005-12-07  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* doc/socket.n: Cross-referenced the socket documentation better to the
	fconfigure documentation on the topic of asynch sockets.
	* doc/fconfigure.n: Added keyword to documentation of -blocking option
	so that people looking for "asynch" can find it as well.

2005-12-05  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tclUnixPort.h (Darwin): fix incorrect __DARWIN_UNIX03 configure
	overrides that were originally copied from Darwin CVS (rdar://3693001)

2005-12-05  Kevin B. Kenny  <kennykb@acm.org>

	* tools/tclZIC.tcl: Updated to reflect changes in calling sequence when
	GetJulianDateFromEraYearMonthDay moved to C.
	* library/tzdata: Regenerated from Olson's tzdata2005p.tar.gz - the
	'systemv' changes appear not to affect Tcl's processing of the dates.

2005-12-05  Daniel Steffen  <das@users.sourceforge.net>

	* unix/configure.in: move check for fts API to configure.in and run it
	* unix/tcl.m4:       on all platforms, since Linux glibc2 and *BSDs
	also have this; using fts is more efficient than a recursive
	opendir/readdir.
	* unix/tclUnixFCmd.c (TraverseUnixTree): add support to fts code for
	platforms with stat64.
	* unix/configure:
	* unix/tclConfig.h.in: regen.

2005-12-05  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/configure:     Use fts file API on Darwin if available.
	* unix/tcl.m4:        Addresses file delete issues in readdir noted
	* unix/tclUnixFCmd.c: in [Bug 1034337]. (steffen)
	Remove redundant stat call for each file in DoCopyFile. (steffen)

2005-12-02  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclClock.c: Moved a tiny bit more of [clock format] from run
	* library/clock.tcl: time to compile time, and fixed a l10n bug in the
	process. [Bug 1371446]. Also, conditoned the call to SetupTimeZone to
	speed the common case where TZData($timezone) already exists, and
	achieved a puny speedup by making ::tcl::clock::getenv not throw
	errors.
	* unix/Makefile.in: Made some changes to support a 'make' command that
	is present on some antiquated versions of Solaris.

2005-12-01  Kevin B. Kenny  <kennykb@acm.org>

	* library/clock.tcl: Continued rationalizing the code, eliminating
	numerous redundant [mc] calls. Added another time boost by precompiling
	a [::format] command to do the bulk of the work of [clock format].

2005-12-01  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* unix/Makefile.in: Add remaining dependency info. While automated
	maintenance of this information would be good, having it at all is much
	better than a poke in the eye with a sharp stick...

2005-12-01  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclClock.c: fix warning.

	* unix/tcl.m4 (Darwin): fix error when MACOSX_DEPLOYMENT_TARGET unset
	* unix/configure: regen.

2005-11-30  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* unix/Makefile.in: Add dependency information relating to tclCompile.h
	since when the list of opcodes changes it is usually useful to rebuild
	everything that depends on it (but which is nonetheless a small
	fraction of the total set of Tcl source files).

	***POTENTIAL INCOMPATIBILITY*** for bytecode savers/loaders. See below

	* generic/tclCompCmds.c (TclCompileSwitchCmd): Arrange for very simple
	[switch] invokations to be compiled into hash lookups into jump tables;
	only a very specific kind of [switch] can be safely compiled this way,
	but that happens to be the most common kind. This makes around 5-10%
	difference to the speed of execution of clock.test.
	* generic/tclExecute.c (TEBC:INST_JUMP_TABLE): New instruction to allow
	for jumps to locations looked up in a hashtable. Requires a new AuxData
	type, tclJumptableInfoType (supported by the functions DupJumptableInfo
	and FreeJumptableInfo in tclCompCmds.c) so anything that saves bytecode
	containing this *must* be updated!

2005-11-30  Kevin Kenny  <kennykb@acm.org>

	* generic/tclClock.c: Fixed a bad refcount in previous commit that led
	to a corrupted heap. Also silenced a warning that some compilers gave
	about the excessively long constant for JULIAN_SEC_POSIX_EPOCH. Also
	fixed a bug where [clock format] would fail in the :localtime zone for
	times before the Posix Epoch. Thanks to Miguel Sofer for pointing out
	all of these. Also rationalized the code a little bit by moving parts
	of [clock scan] into C, eliminating some code that was duplicated in
	the C and Tcl layers.

2005-11-29  Kevin Kenny  <kennykb@acm.org>

	* generic/tclBasic.c:	Moved a big part of [clock format] down
	* generic/tclClock.c:   to the C level in order to make it go faster.
	* generic/tclInt.h:     Preliminary measurements suggest that it
	* generic/clock.tcl:    more than doubles in speed with this change.

2005-11-29  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclCmdIL.c (Tcl_LsearchObjCmd): Allow [lsearch -regexp] to
	process REs that contain backreferences. This expensive mode of
	operation is only used if the RE would otherwise cause a compilation
	failure. [Bug 1366683]

2005-11-28  Kevin Kenny  <kennykb@acm.org>

	* tools/tclZIC.tcl (convertTimeOfDay): Corrected a typo that caused
	wrong DST transitions in any time zone where the transition is
	specified as local Standard Time (as opposed to wall-clock or UTC).
	(Also updated the code to be bignum-safe.)
	* tests/clock.test (clock-51.1): Added regression test for the above.
	* library/tzdata: Updated to Olson's 'tzdata2005o' (changes for Cuba,
	Nicaragua, Jordan, and Georgia) and regenerated. Thanks to Paul
	Mackerras for reporting this problem.

2005-11-27  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tcl.m4 (Darwin): add 64bit support, check for Tiger copyfile(),
	add CFLAGS to SHLIB_LD to support passing -isysroot in env(CFLAGS) to
	configure (flag can't be present twice, so can't be in both CFLAGS and
	LDFLAGS during configure), don't use -prebind when deploying on 10.4,
	define TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING (rdar://3171542).
	(SC_ENABLE_LANGINFO, SC_TIME_HANDLER): add/fix caching, fix obsolete
	autoconf macros. Sync with tk/unix/tcl.m4.

	* unix/configure.in: fix obsolete autoconf macros, sync gratuitous
	formatting/ordering differences with tk/unix/configure.in.

	* unix/Makefile.in: add CFLAGS to tclsh/tcltest link to make executable
	linking the same as during configure (needed to avoid losing any linker
	relevant flags in CFLAGS, in particular flags that cannot be in
	LDFLAGS). Avoid concurrent linking of tclsh and compiling of
	tclTestInit.o or xtTestInit.o during parallel make.
	(checkstubs, checkdoc, checkexports): dependency and Darwin fixes
	(dist): add new macosx files.

	* unix/tclLoadDyld.c (TclpDlopen): use NSADDIMAGE_OPTION_WITH_SEARCHING
	on second NSAddImage only. [Bug 1204237]
	(TclGuessPackageName): should not be MODULE_SCOPE.
	(TclpLoadMemory): ppc64 and endian (i386) fixes, add support for
	loading universal (fat) bundles from memory.

	* unix/tclUnixFCmd.c:
	* macosx/tclMacOSXFCmd.c: ppc64 and endian (i386) fixes.
	(TclMacOSXCopyFileAttributes): add support for new Tiger copyfile() API
	to enable copying of xattrs & ACLs by [file copy].

	* generic/tcl.h: add Darwin specifc configure overrides for TCL_WIDE
	defines to support fat compiles of ppc and ppc64 at the same time,
	(replaces Darwin CVS fix by emoy, rdar://3693001). add/correct location
	of version numbers in macosx files.

	* generic/tclInt.h: clarify fat compile comment.

	* unix/tclUnixPort.h: add Darwin specifc configure overrides to support
	fat compiles, where configure runs only once for multiple architectures
	(replaces Darwin CVS fix by emoy, rdar://3693001).

	* macosx/tclMacOSXBundle.c:
	* macosx/tclMacOSXNotify.c:
	* unix/tclUnixNotfy.c:
	* unix/tclUnixPort.h: fix #include order to support compile time
	override of HAVE_COREFOUNDATION in tclUnixPort.h when building for
	ppc64

	* macosx/Tcl.pbproj/default.pbxuser (new file):
	* macosx/Tcl.pbproj/jingham.pbxuser:
	* macosx/Tcl.pbproj/project.pbxproj:
	* macosx/Tcl.xcode/default.pbxuser (new file):
	* macosx/Tcl.xcode/project.pbxproj (new file):
	* macosx/Tcl.xcodeproj/default.pbxuser (new file):
	* macosx/Tcl.xcodeproj/project.pbxproj (new file): new/updated
	projects for Xcode 2.2 on 10.4, Xcode 1.5 on 10.3 & ProjectBuilder on
	10.2, with native tcltest targets and support for universal (fat)
	compiles.

	* macosx/README: clarification/cleanup, document new Xcode projects and
	universal (fat) builds via CFLAGS (i.e. all of ppc ppc64 i386 at once).

	* unix/Makefile.in:
	* unix/aclocal.m4:
	* unix/configure.in:
	* unix/dltest/Makefile.in:
	* macosx/configure.ac (new file): add support for inclusion of
	unix/configure.in by macosx/configure.ac, allows generation of a config
	headers enabled configure script in macosx (required by Xcode
	projects).

	* macosx/GNUmakefile: rename from Makefile to avoid overwriting by
	configure run in tcl/macosx, add support for reusing configure cache,
	build target fixes, remove GENERIC_FLAGS override now handled by
	tcl.m4.

	* generic/tcl.decls: add Tcl_Main declaration as comment to avoid
	'checkstubs' target complaining about it missing from stubs.

	* generic/regex.h:
	* generic/tclDate.c:
	* generic/tclEnv.c:
	* generic/tclGetDate.y:
	* generic/tclIOUtil.c:
	* generic/tclObj.c:
	* generic/tclStubInit.c:
	* generic/tclStubLib.c:
	* generic/tclPathObj.c:
	* generic/tclThreadAlloc.c:
	* generic/tclThreadStorage.c:
	* generic/tclTrace.c:
	* generic/tclVar.c:
	* generic/tommath.h:
	* tools/fix_tommath_h.tcl:
	* unix/tclUnixFCmd.c: ensure externally visible symbols not contained
	in stubs table are declared as MODULE_SCOPE (or as static if not used
	outside of own source file). These changes allow 'make checkstubs' to
	complete without error on Darwin with gcc 4.

	* generic/rege_dfa.c (getvacant):
	* generic/regexec.c (cfind):
	* generic/tclCompExpr.c (CompileSubExpr):
	* generic/tclNamesp.c (NamespaceEnsembleCmd):
	* unix/tclUnixChan.c (TclUnixWaitForFile): initialise variables to
	silence gcc 4 warnings.

	* generic/tclExecute.c (TclExecuteByteCode): fix unused variable
	warning when NO_WIDE_TYPE is defined.

	* generic/regguts.h: only #define NDEBUG if not already #defined.

	* unix/tclUnixNotfy.c:
	* macosx/tclMacOSXNotify.c: sync whitespace & comments.

	* unix/tclUnixPort.h:
	* win/tclWinPort.h: remove declaration of obsolete&unused TclpMutex
	API.

	* unix/configure:
	* unix/tclConfig.h.in: regen.

2005-11-21  Andreas Kupries  <andreask@activestate.com>

	* unix/Makefile.in (install-libraries): Updated Makefile to new
	* win/Makefile.in (install-libraries):  version of the http package.
	This fixes the ifneeded/provide mismatch reported when trying to
	require http. Should we maybe try to automatically extract the version
	number from the http code to prevent future breakage ?

	This follows the update of the version number by dgp on Nov 15 (No
	entry found in the ChangeLog).

2005-11-20  Joe English  <jenglish@users.sourceforge.net>

	* generic/tclStubLib.c: Don't set tclStubsPtr to 0 when
	Tcl_PkgRequireEx() fails [Fix for [Bug 1091431] "Tcl_InitStubs failure
	crashes wish"]

2005-11-18  Miguel Sofer  <msofer@users.sf.net>

	* tests/trace.test (trace-34.5): [Bug 1047286], added a second test
	illustrating the role of "ns in callStack" in the ns's visibility
	during deletion traces.

2005-11-18  Kevin B. Kenny  <kennykb@acm.org>

	* doc/clock.n: Restored several missing lines near the %w format group
	so that %w and %W are documented with their actual behaviour. [Bug
	1359183]

2005-11-18  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclIO.c (TclFinalizeIOSubsystem): preserve statePtr until we
	retrieve the next statePtr from it.

2005-11-18  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclObj.c (GetBignumFromObj): replace NULL with
	tclEmptyStringRep to stop memcpy from complaining in a debug build
	(the corresponding branch is eliminated by the optimiser otherwise).

2005-11-18  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c (TclFinalizeIOSubsystem): Applied Pat Thoyts' patch
	for [Bug 1359094]. This moves the retrieval of the next channel state
	to the end of the loop, as the called closeproc may close other
	channels, i.e. modify the list we are iterating, invalidating any
	pointer retrieved earlier.

2005-11-18  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclListObj.c:	Restored the SetListFromAny routine to the
	* generic/tclObj.c:	"list" Tcl_ObjType, and restored the
	Tcl_RegisterObjType() call for "list". This addresses the needs of some
	"bridge" extensions to examine whether the Tcl_ObjType of a Tcl_Obj is
	that of the "list" Tcl_ObjType.

2005-11-18  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* library/http/http.tcl (http::geturl): Improved syntactic validation
	of URLs, and better error messages in some cases. [Bug 1358369]

2005-11-17  Miguel Sofer  <msofer@users.sf.net>

	* tests/namespace.test: fix comment

2005-11-14  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStrToD.c:	More data in the "can't happen" Tcl_Panic to
	aid debugging.

	* generic/tclBasic.c (CallCommandTraces): Save/restore the interp
	result during traces to fix [Bug 1355342].

2005-11-13  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclInt.h:
	* generic/tclNamesp.c:
	* tests/namespace.test: fix for [Bug 1354540] and [Bug 1355942]. The
	new tests 7.3-6 and the modified 51.13 fail due to the unrelated [Bug
	1355342]

	* tests/trace.test: added tests 20.13-16 for [Bug 1355342]

2005-11-12  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c (Tcl_DeleteCommandFromToken):
	* generic/tclObj.c (Tcl_GetCommandFromObj): more partial fixes for
	[Bug 1354540] - making sure that cached references to a command being
	deleted cannot be made reusable by a delete trace.

2005-11-12  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclNamesp.c (Tcl_FindCommand): Do not find commands in dead
	namespaces on the path. Partial fix for [Bug 1354540].

2005-11-11  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInt.h:	Revised TclParseNumber interface to enable
	* generic/tclScan.c:	revision to the [scan] command implementation
	* generic/tclStrToD.c:	to permit tests scan-4.44,55 to pass again.
	[Bug 1348067].

2005-11-11  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c (Tcl_DeleteCommandFromToken):
	* generic/tclObj.c (Tcl_GetCommandFromObj): bump the cmd epoch early
	to insure that cached references to this command are invalidated.
	Partial fix for [Bug 1352734] - at least insures that namespace-51.13
	does not cause a panic. The test is still marked as knownbug, pending
	resolution of what is actually the correct return value ([Bug
	1354540])

2005-11-09  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclTimer.c: Changed [after] so that it behaves correctly
	* tests/timer.test:   with negative arguments [Bug 1350293] and
	arguments that overflow a 32-bit word. [Bug 1350291]

2005-11-08  Don Porter  <dgp@users.sourceforge.net>

	* tests/compile.test:	Updated tests with changed behavior
	* tests/execute.test:	due to addition of bignums.
	* tests/expr-old.test:
	* tests/expr.test:
	* tests/parseExpr.test:
	* tests/platform.test:
	* tests/string.test:

2005-11-08  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/tclUnixFCmd.c (MAX_READDIR_UNLINK_THRESHOLD): reduce to 130
	based on errors seen on OS X 10.3 with lots of links in a dir.
	[Bug 1034337 followup]

2005-11-09  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* unix/Makefile.in (gdb-test): Added a new target to make it easier to
	run the test suite inside a debugger.

2005-11-08  Don Porter  <dgp@users.sourceforge.net>

	* tests/compExpr-old.test:	Updated tests with changed behavior due
	to addition of bignums.

	* tests/expr.test:      Portable tests expr-46.13-18 [Bug 1341368]

	* generic/tclPkg.c:	Corrected inconsistencies in the value returned
	* tests/pkg.test:	by Tcl_PkgRequire(Ex) so that the returned
	values will always agree with what is stored in the package database.
	This way repeated calls to Tcl_PkgRequire(Ex) have the same results.
	Thanks to Hemang Lavana. [Bug 1162286].

2005-11-08  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclTrace.c (TraceVarEx): Factor out heart of Tcl_TraceVar2
	(TclTraceVariableObjCmd,TraceVarProc): Use the new internal API to
	arrange for the clientData to be cleaned up at the same time as the
	rest of the main trace record. This simplifies the code a bit at the
	same time.

2005-11-07  Miguel Sofer  <msofer@users.sf.net>

	* tests/trace.test (trace-13.2-4): added tests to detect leak, see [Bug
	1348775]. The recently added trace-8.9 test is now 13.4.

2005-11-07  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* tests/dict.test (dict-19.2): arrange for the stress testing code to
	only stress test the dict code and not the trace code as well. [Bug
	1342858]

2005-11-05  Miguel Sofer  <msofer@users.sf.net>

	* tests/trace.test (trace-8.9): added test to detect leak, see [Bug
	1348775].

2005-11-04  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* win/tclWinPort.h:  Applied [Patch 1267871] by Matt Newman for
	* win/tclWinPipe.c:  extended error code support on Windows.
	* tests/exec.test:   Tests for extended error codes.
	* generic/tclPipe.c: Permit long codes (platform macros permitting).

2005-11-04  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBinary.c:
	* generic/tclCmdAH.c:
	* generic/tclCmdIL.c:
	* generic/tclCmdMZ.c:
	* generic/tclDictObj.c:
	* generic/tclExecute.c:
	* generic/tclIOCmd.c:
	* generic/tclLink.c:
	* generic/tclTest.c:
	* generic/tclVar.c: fix for [Bug 1334947]. The functions TclPtrSetVar,
	Tcl_ObjSetVar2 and Tcl_SetVar2Ex now always consume the newValuePtr
	argument - i.e., they will free a 0-refCount object if they failed to
	set the variable. Fixed all callers in the core.

2005-11-04  Kevin Kenny  <kennykb@acm.org>

	* generic/tclGetDate.y: Added abbreviations for the Korean
	* library/clock.tcl:    timezone. [Patch 1298737]
	* generic/tclDate.c:    Regenerated.

	* tools/findBadExternals.tcl: Added this script, which locates external
	symbols that do not begin with 'Tcl' or 'tcl' and hence might be in
	conflict with other link libraries. Thanks to George Peter Staplin for
	the idea and the initial version of the script. [Bug 1263012]

	* unix/Makefile.in: Trimmed a bunch of fat out of the tommath/
	directory in 'make dist'. [RFE 1333318]

	* unix/tcl.m4: Added code to enable [load] on LynxOS. Thanks to
	heidibr@users.sf.net for the patch. [Bug 1163896]. Removed the last
	vestiges of GNU dld from the Unix build [RFE 1071992].

	* unix/tclLoadDld.c: Removed.
	* unix/configure: Regenerated.

2005-11-04  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclInt.h:
	* generic/tclNamesp.c:
	* generic/tclVar.c:
	* tests/trace.test: fix for [Bugs 1338280/1337229]; changed to use the
	same approach as the 8.4 patch in the ticket (i.e., removed the patch
	committed on 2005-31-10).

2005-11-03  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* win/tclWin32Dll.c:   Applied [Patch 1256872] to provide unicode
	* win/tclWinConsole.c: support in the console on suitable systems.
	* win/tclWinInt.h:     Patch by Anton Kovalenko

2005-11-02  Pat Thoyts  <patthoyts@users.sourceforge.net>

	Applied [Patch 1096916] to support building with MSVC 8.
	* generic/regerror.c: Avoid use of reserved word.
	* generic/tcl.h:      Select the right Tcl_Stat structure
	* generic/tclDate.c:  Casts to handle 64 bit time_t case.
	* tests/env.test:     Include essential envvar on Win32
	* win/nmakehlp.c:     Handle new return codes.
	* win/makefile.vc:    Use the selected options.
	* win/rules.vc:       Check options are applicable
	* win/tclWinPort.h:   Disable deprecated function warnings
	* win/tclWinSock.c:   Provide default value to avoid warning.
	* win/tclWinTime.c:   Add casts to handle 64bit time_t type.

2005-11-01  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclTrace.c (TclCheckExecutionTraces): Corrected mistaken
	assumption that all command traces are set at the script level.
	Report/fix from Jacques H. de Villiers. [Bug 1337941]

	* tests/unixNotfy.test (1.1,2):	Update error message whitespace to
	match changes in code.

	* tests/expr-old.test (expr-32.52): Use int(.) to restrict result of
	left shift to the C long range.

	* expr.test (expr-46.13): Added test that illustrates shortcoming of
	[Patch 1340260].

2005-10-31  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclNamesp.c: fix for [Bugs 1338280/1337229]. Thanks Don.
	* tests/trace.test: fix duplicate test numbers

2005-10-31  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* win/tclWinSerial.c (SerialSetOptionProc): Cleaned up option parsing
	to produce more informative error messages and separate error and
	non-error code paths better.
	* tests/ioCmd.test (iocmd-8-19): Updated.

2005-10-29  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclTrace.c (TraceVarProc): [Bug 1337229], partial fix. Ensure
	that a second call with TCL_TRACE_DESTROYED does not lead to a second
	call to Tcl_EventuallyFree(). It is still true that that second call
	should not happen, so the bug is not completely fixed.
	* tests/trace.test (test-18.3-4): added tests for [Bug 1337229] and
	[Bug 1338280].

2005-10-23  Vince Darley  <vincentdarley@sourceforge.net>

	* generic/tclFileName.c: fix to memory leak in glob [Bug 1335006] Obj
	leak detection and patch by Eric Melbardis.

	* tests/fCmd.test:
	* win/tclWinFile.c: where appropriate windows API is available, try to
	set 'nlink' and 'ino' stat fields (previously they were always 0). [Bug
	1325803]

2005-10-22  Miguel Sofer  <msofer@users.sf.net>

	* tests/foreach.test (foreach-8.1): added test for [Bug 1189274]

2005-10-22  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c (INST_INCR_*): fixed [Bug 1334570]. Obj leak
	detection and patch by Eric Melbardis.

2005-10-21  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclStrToD.c (RefineApproximation): Plugged a memory leak
	where two intermediate results were not freed on one return path. [Bug
	1334461]. Thanks to Eric Melbardis for the patch.

2005-10-21  Donal K. Fellows  <dkf@users.sf.net>

	* doc/binary.n: Clarify that virtually all code that uses the 'h'
	format in [binary scan] should be using the 'H' format instead. It is
	nearly always a bug to use the other!

2005-10-20  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclListObj.c (TclLsetFlat):
	* tests/lset.test (lset-10.3): fixed handling of unshared lists with
	shared sublists, [Bug 1333036] reported by neuronstorm.

2005-10-19  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclIORChan.c (PassReceivedError,PassReceivedErrorInterp):
	Fix crash caused by passing -1 as the length to TclNewStringObj(). Only
	Tcl_NewStringObj (the function call, not the macro) handles that sort
	of thing correctly. This makes ioCmd.test pass again.

2005-10-19  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclClock.c:		Removed some dead code.
	* generic/tclCmdIL.c:
	* generic/tclCompCmds.c:
	* generic/tclDictObj.c:
	* generic/tclExecute.c:
	* generic/tclLiteral.c:
	* generic/tclParseExpr.c:
	* generic/tclScan.c:
	* generic/tclUtil.c:
	* generic/tclVar.c:

2005-10-19  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclIORChan.c: General cleanup, removing checks that are
	unnecessary due to the general contracts of other functions in the
	core, converting to using ANSI declarations, etc. Note that nearly the
	whole file has changed, but it is often just cosmetic.

2005-10-19  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c (INST_DICT_APPEND, INST_DICT_LAPPEND): fixed
	faulty peephole optimisation that can cause crashes, [Bug 1331475]
	reported by Aric Bills.

2005-10-18  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclExecute.c: Added optimization for I32L64 systems to avoid
	using bignums to perform int multiplies. The improvement shows up most
	dramatically in tclbench's matrix.bench.

2005-10-15  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclExecute.c:	Restored some optimizations of the
	INST_INCR_SCALAR1_IMM opcode.

2005-10-14  Zoran Vasiljevic  <vasiljevic@users.sourceforge.net>

	* generic/tclIO.c (Tcl_ClearChannelHandlers): removed change dated
	2005-10-04 (see below). Look into [Bug 1323992] for detailed
	discussion.

	* generic/tcl.h: Fixed bad definition of CRTEXPORT which should have
	been CRTIMPORT rather. This broke compilation of generic/tclMain.c and
	was probably introduced by mistake while applying the fix for [Bug
	1256937] below.

2005-10-14  Kevin Kenny  <kennykb@acm.org>

	* generic/tclExecute.c (TclIncrObj, TclExecuteByteCode): Tidied up a
	couple of infelicitous do {...} while(0) constructs.

2005-10-14  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* generic/tcl.h:     Fix for [Bug 1256937] - correctly decorate
	* generic/tclMain.c: imported functions from msvcrt in static builds.

2005-10-13  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tests/format.test: "Forward"-port of test updates relating to [Bug
	1284178]. The bug itself was fixed by TIP#237.

2005-10-13  Zoran Vasiljevic  <vasiljevic@users.sourceforge.net>

	* generic/tclIO.c (Tcl_ClearChannelHandlers): temporary ifdef
	TCL_THREADS changes done to de-activate pending event processing when
	channel is being closed/cutted.

2005-10-13  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclExecute.c:	Removed obsolete use of NO_ERRNO_H.
	* tools/man2tcl.c:
	* unix/tcl.m4:
	* unix/tclConfig.h.in:
	* win/configure.in:

	* unix/configure:	autoconf-2.59
	* win/configure:

	* compat/tclErrno.h:	Removed obsolete file.

	* generic/tclStrToD.c (TclParseNumber): Missing goto caused crash when
	parsing "Na". [Bug 1325833]

2005-10-12  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclExecute.c (GetNumberFromObj):	Restored some lost
	optimizations for empty string values. We avoid cost of a call to
	TclParseNumber just to tell us an empty string isn't a number.

2005-10-12  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclPathObj.c (SetFsPathFromAny): TclGetString macro must not
	be combined with post-increment arguments. [Bug 1325099]

2005-10-12  Kevin Kenny  <kennykb@acm.org>

	* generic/tclExecute.c (Tcl_ExecuteByteCode, TclIncrObj): Several
	common cases inlined in hopes of gaining a little performance in [incr]

2005-10-10  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompCmds.c: New convenience macro CompileTokens().

2005-10-10  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclExecute.c: Corrections to the NO_WIDE_TYPE build. Also
	added missing "break" to a switch that broke wide XOR operations.

2005-10-10  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclInterp.c (DeleteScriptLimitCallback)
	(SetScriptLimitCallback): Improve the interlocking between the script
	limit callback record and the hash table of current such records, to
	prevent crashes in callbacks that create callbacks.
	(Tcl_LimitSetTime): Reset the correct flag. Problem reported by
	Nicolas Castagne <castagne@imag.fr> on comp.lang.tcl

2005-10-10  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: Fixing errors in last commit. (Two commits, the
	second removes wrong comment).

2005-10-09  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:
	* generic/tclExecute.c:
	* generic/tclStrToD.c:
	* generic/tclStringObj.c: Initialise variables to avoid compiler
	warnings ([Bug 1320818] among others).

2005-10-08  Don Porter  <dgp@users.sourceforge.net>

	TIP#237 IMPLEMENTATION

	[kennykb-numerics-branch] Resynchronized with the HEAD; at this
	checkpoint [-rkennykb-numerics-branch-20051008], the HEAD and
	kennykb-numerics-branch contain identical code.

	[kennykb-numerics-branch]	Merge updates from HEAD

	* generic/tclExecute.c: More performance macros and special handling of
	the wide integer type for performance on 32-bit systems.

2005-10-07  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclExecute.c:	Macro GetNumberFromObj() is version of
	TclGetNumberFromObj() that saves a function call for common uses.

	* generic/tclInt.h:	Made #undef NO_WIDE_TYPE the default on 32-bit
	systems. Being able to use 64-bit values without leaping to mp_int
	should help with performance.

	* generic/tclObj.c:	Bug fixes in the #undef NO_WIDE_TYPE
	* generic/tclExecute.c:	configuration.

	* generic/tclExecute.c: Improved performance of comparison opcodes and
	bitwise operations and removed yet more dead code.

2005-10-07  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/tclUnixFCmd.c (TraverseUnixTree): Adjust 2004-11-11 change to
	* tests/fCmd.test (fCmd-20.2):           account for NFS special files
	with a readdir rewind threshold. [Bug 1034337]

2005-10-06  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclExecute.c:	Improved performance of INST_RSHIFT and
	INST_LSHIFT.

2005-10-05  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclExecute.c: Improved performance of INST_MULT, INST_DIV,
	INST_ADD, and INST_SUB and replaced a "goto... label" with a "break
	from loop" in TclIncrObj() and removed some dead code.

2005-10-05  Andreas Kupries  <andreask@activestate.com>

	* generic/tclPipe.c (TclCreatePipeline): Fixed [Bug 1109294]. Applied
	the patch provided by David Gravereaux.

	* doc/CrtChannel.3: Fixed [Bug 1104682], by application of David
	Welton's patch for it, and added a note about wideSeekProc.

	* generic/tclIORChan.c (RcClose): Removed unreachable panic/return
	statements. This fixes the remainder of [Bug 1286256].

2005-10-05  Jeff Hobbs  <jeffh@ActiveState.com>

	* tests/env.test (env-6.1):
	* win/tclWinPort.h: define USE_PUTENV_FOR_UNSET 1
	* generic/tclEnv.c (TclSetEnv, TclUnsetEnv): add USE_PUTENV_FOR_UNSET
	to existing USE_PUTENV define to account for various systems that have
	putenv(), but can't unset env vars with it. Note difference between
	Windows and Linux for actually unsetting the env var (use of '=').
	Correct the resizing of the environ array. We assume that we are in
	full ownership, but that's not correct.[Bug 979640]

2005-10-04  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]
	* generic/tclExecute.c: Updated TclIncrObj() to more efficiently add
	native long integers. Also updated IllegalExprOperandType and the
	INST_UMINUS, INST_UPLUS, INST_BITNOT, and INST_TRY_CVT_TO_NUMERIC
	sections for performance.

	* generic/tclBasic.c: Updated more callers to make use of
	TclGetNumberFromObj. Removed some dead code.

2005-10-04  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/tclWinSerial.c (SerialSetOptionProc): free argv [Bug 1067708]

	* tests/http.test:              do not URI encode -._~ according
	* library/http/http.tcl (init): to RFC3986. [Bug 1182373] (aho)

	* unix/tclLoadShl.c (TclpDlopen): use DYNAMIC_PATH on second shl_load
	only. [Bug 1204237]

	* doc/scan.n: scan %[] requires "one or more chars" [Bug 1277503]

	* tests/winFile.test (getuser): allow valid Windows usernames. [Bug
	1311285]

	* generic/tclParse.c (Tcl_ParseCommand): add code that recognizes {} in
	addition to {expand} for word expansion (make with
	-DALLOW_EMPTY_EXPAND).

2005-10-04  Zoran Vasiljevic  <vasiljevic@users.sourceforge.net>

	* generic/tclIO.c (Tcl_ClearChannelHandlers): now deletes any
	outstanding timer for the channel. Also, prevents events still in the
	event queue from triggering on the current channel.

	* generic/tclTimer.c (Tcl_DeleteTimerHandler): bail out early if passed
	NULL argument.

2005-10-03  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclBasic.c:	Re-implemented ExprRoundFunc and
	ExprEntierFunc to use TclGetNumberFromObj.

	* generic/tclInt.h:	Added new routine TclGetNumberFromObj to
	* generic/tclObj.c:	provide efficient access to the actual
	internal rep of a numeric Tcl_Obj without conversions.

2005-10-03  Kevin Kenny  <kennykb@acm.org>

	* tools/loadICU.tcl:  Changed the file names of message catalogs to
			      lowercase.
	* tools/makeTestCases.tcl:
	* library/tzdata/*:   Olson's tzdata2005n.tar.gz. Includes new DST
	rules for USA and a number of changes to other locales.
	* tests/clock.test:   Regenerated for new US DST rules.

2005-09-30  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclMain.c: Separate encoding conversion of command line
	arguments from list formatting. [Bug 1306162].

2005-09-30  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclStringObj.c:	Bug fix: Missing cast to large enough
	integral size before << operations led to broken [format %llx] results.
	Thanks to Robert Henry for reporting the bug.

2005-09-29  Jeff Hobbs  <jeffh@ActiveState.com>

	* doc/mathfunc.n:   implementation for TIP #255, expr min/max
	* library/init.tcl:
	* tests/info.test, tests/expr-old.test:

2005-09-27  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tcl.h:	Changed name of the new Tcl_Obj intrep field
	* generic/tclObj.c:	from "bignumValue" to "ptrAndLongRep" as
	* generic/tclProc.c:	described in TIP 237, and more suitable for
	other more general uses.

2005-09-27  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* tests/binary.test (binary-14.18): Added test for [Bug 1116542] though
	the bug itself was already fixed by unrelated changes.

2005-09-26  Kevin Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch] Merge updates from HEAD.

2005-09-26  Kevin Kenny  <kennykb@acm.org>

	* libtommath/:                   Updated to release 0.36.
	* generic/tommath.h:             Regenerated.
	* generic/tclTomMathInterface.h: Added ten missing aliases for mp_*
	functions to avoid namespace pollution in Tcl's exported symbols. [Bug
	1263012]

2005-09-23  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* unix/Makefile.in:	Added -DMP_PREC=4 switch to all compiles so
	* win/Makefile.in:	that minimum memory requirements of mp_int's
	* win/makefile.vc:	will not be quite so large. [Bug 1299153].

	* generic/tclStrToD.c:	Fixed memory leak. [Bug 1299803].
	* generic/tclObj.c:

2005-09-20  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclExecute.c:	Revise TclIncrObj() to call
	Tcl_GetBignumAndClearObj.

	* generic/tcl.decls:	Add Tcl_GetBignumAndClearObj.
	* generic/tclObj.c:

	* generic/tclDecls.h:	make genstubs
	* generic/tclStubInit.c:

2005-09-16  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclInt.h:		 Added TclBNInitBigNumFromWideInt() so
	* generic/tclTomMathInterface.c: that every caller isn't required to
	duplicate the sign logic to use the unsigned interface.

	* generic/tclBasic.c:	Reduce the number of places where Tcl intrudes
	* generic/tclExecute.c:	into the internal format details of the mp_int
	* generic/tclObj.c:	struct.
	* generic/tclStrToD.c:
	* generic/tcLStringObj.c:

	* generic/tclTomMath.h:	Added mp_cmp_d to routines from libtommath
	* unix/Makefile.in:	used by Tcl.
	* win/Makefile.in:
	* win/makefile.vc:

	* libtommath/bn_mp_add_d.c: Bug fix. For mp_add_d(&a, d, &c), when &a
	has the value -d, then the value &c computed should be zero, but
	mp_add_d was producing an inconsistent zero value with a sign field of
	MP_NEG, something like a value of -0, which other routines in
	libtommath can't handle.

	* generic/tclExecute.c:	Dropped all creation of "bigOne" values and
	just use tommath routines that accept the value "1" directly.

2005-09-15  Miguel Sofer  <msofer@users.sf.net>

	* doc/ParseCmd.3: copy/paste fix [Bug 1292427]

2005-09-15  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]	Merge updates from HEAD.

	* generic/tclStringObj.c (TclAppendFormattedObjs):	Revision to
	eliminate one round of string copying.

	* generic/tclBasic.c:	More callers of TclObjPrintf and
	* generic/tclCkalloc.c:	TclFormatToErrorInfo.
	* generic/tclCmdMZ.c:
	* generic/tclExecute.c:
	* generic/tclIORChan.c:
	* generic/tclMain.c:
	* generic/tclProc.c:
	* generic/tclTimer.c:
	* generic/tclUtil.c:
	* unix/tclUnixFCmd.c

	* unix/configure:	autoconf-2.59

2005-09-15  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* unix/tcl.m4 (SC_TCL_EARLY_FLAGS): Added extra hack to allow Tcl to
	transparently open large files on RHEL 3. [Bug 1287638]

2005-09-14  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c:	Bug fixes: ObjPrintfVA needed to
	support "*" fields and needed to interpret precision limits on %s
	conversions as a maximum number of bytes, not Tcl_UniChars, to take
	from the (char *) argument.

	* generic/tclBasic.c:	Updated several callers to use
	* generic/tclCkalloc.c: TclFormatToErrorInfo() and/or
	* generic/tclCmdAH.c:	TclObjPrintf().
	* generic/tclCmdIL.c:
	* generic/tclCmdMZ.c:
	* generic/tclDictObj.c:
	* generic/tclExecute.c:
	* generic/tclIORChan.c:
	* generic/tclIOUtil.c:
	* generic/tclNamesp.c:
	* generic/tclProc.c:

	* library/init.tcl:	Keep [unknown] in sync with errorInfo
	formatting rules.

2005-09-13  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c:	First caller of TclFormatToErrorInfo.

	* generic/tclInt.h:		Using stdarg.h conventions, add more
	* generic/tclStringObj.c:	fixed arguments to TclFormatObj() and
	TclObjPrintf(). Added new routine TclFormatToErrorInfo().

	* generic/tcl.h:	Explicitly standardized on the use of stdarg.h
	* generic/tclBasic.c:	conventions for functions with variable number
	* generic/tclInt.h:	of arguments. Support for varargs.h has been
	* generic/tclPanic.c:	implicitly gone for some time now. All
	* generic/tclResult.c:	TCL_VARARGS* macros purged from Tcl sources,
	* generic/tclStringObj.c:	leaving only some deprecated #define's
	* tools/genStubs.tcl:	in tcl.h for the sake of older extensions.

	* generic/tclDecls.h:	make genstubs

	* doc/AddErrInfo.3:	Replaced all documented requirement for use of
	* doc/Eval.3:		TCL_VARARGS_START() with requirement for use of
	* doc/Panic.3:		va_start().
	* doc/SetResult.3:
	* doc/StringObj.3:

2005-09-12  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]	Merge updates from HEAD.

	* generic/tclCmdAH.c:		Added support for the "ll" width
	* generic/tclStringObj.c:	specifier to [format].

	* generic/tclStringObj.c (TclAppendFormattedObjs):	Bug fix: make
	sure %ld formats force the collection of a wide value, when the value
	could be a different long.

2005-09-09  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIORChan.c (RcDecodeEventMask): Added missing type
	declaration for the parameter 'mask'. This fixes the [Bug 1286256]. The
	other warning can be removed only by removing the panic/return code.

2005-09-09  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]	Merge updates from HEAD.

2005-09-09  Kevin Kenny  <kennykb@acm.org>

	* generic/tclStringObj.c:  Added two missing casts to silence messages
	from MSVC6.

2005-09-09  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInt.h:		New internal routine TclObjPrintf()
	* generic/tclStringObj.c:	is similar to TclFormatObj() but
	accepts arguments in non-Tcl_Obj format.

	* generic/tclInt.h:		New internal routines TclFormatObj()
	* generic/tclStringObj.c:	and TclAppendFormattedObjs() to offer
	sprintf()-like means to append to Tcl_Obj. Work in progress toward
	[RFE 572392].

	* generic/tclCmdAH.c:	Compiler directive NEW_FORMAT when #define'd
	directs the [format] command to be implemented in terms of the new
	TclAppendFormattedObjs() routine.

2005-09-08  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	TIP#254 IMPLEMENTATION

	* generic/tclLink.c (LinkTraceProc,ObjValue): Added many new of C var
	* generic/tcl.h:			      to link to, making it
	* doc/LinkVar.3:			      easier to seamlessly
	* generic/tclTest.c (TestlinkCmd):	      couple C code and Tcl
	* tests/link.test:			      scripts in an
	application. [Patch 1242844]

2005-09-07  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclUtf.c (Tcl_UniCharToUtf):	Corrected handling of negative
	* tests/utf.test (utf-1.5):	    Tcl_UniChar input value. Incorrect
	handling was producing byte sequences outside of Tcl's legal internal
	encoding. [Bug 1283976].

2005-09-06  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclInt.h (List): Added flag to keep track of whether a list
	* generic/tclListObj.c:    with a string rep is provably canonical.
	* generic/tclUtil.c (Tcl_ConcatObj):  Do efficient concatenation and
	* generic/tclBasic.c (Tcl_EvalObjEx): evaluation when the list is
	canonical, and not just when the list is pure. This should make the
	"pure list" hacking introduced in 8.3 much more robust.

2005-09-05  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclObj.c (pendingObjDataKey): Added missing 'static' to stop
	symbol from leaking outside the Tcl library. [Bug 1263012]

2005-09-02  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclScan.c:	Bug fix: The %o, %x, %i formats of [scan] must
	not accept any 0b or 0o prefixes. [scan $s %o] must continue to work
	even with KILL_OCTAL enabled.

	* generic/tclInt.h:	Added TCL_PARSE_SCAN_PREFIXES to the flags
	* generic/tclStrToD.c:	accepted by TclParseNumber.

2005-09-01  Andreas Kupries  <andreask@activestate.com>

	* unix/tclUnixSock.c (InitializeHostName): Synchronized use of static
	modifier in declaration and definition of function.

	* unix/tclUnixChan.c (FileTruncateProc): Synchronized use of static
	modifier in declaration and definition of function.

	* generic/tclResult.c (ReleaseKeys): Synchronized use of static
	modifier in declaration and definition of function.

	* generic/tclListObj.c (NewListIntRep): Synchronized use of static
	modifier in declaration and definition of function.

	* generic/tclEncoding.c (InitializeEncodingSearchPath): Synchronized
	use of static modifier in declaration and definition of function.

	* generic/tclEncoding.c (FillEncodingFileMap): Synchronized use of
	static modifier in declaration and definition of function.

	* generic/tclIORChan.c (RcNewHandle): Synchronized use of static
	modifier in declaration and definition of function.

2005-09-01  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclObj.c:	TclParseNumber calls meant to parse an integer
	value now pass the TCL_PARSE_INTEGER_ONLY flag.

	* generic/tclScan.c:	Extended [scan] to accept the %lld, %llo, %llx,
	and %lli formats. Numeric scanning is now done via TclParseNumber calls

	* generic/tclInt.h:	Extended TclParseNumber to accept new flag
	* generic/tclStrToD.c:	values TCL_PARSE_INTEGER_ONLY,
	TCL_PARSE_OCTAL_ONLY, and TCL_PARSE_HEXIDECIMAL_ONLY, to give caller
	more control over the parsing rules.

2005-08-31  Vince Darley  <vincentdarley@sourceforge.net>

	* doc/FileSystem.3:
	* unix/tclUnixFile.c:
	* windows/tclWinFile.c: clarify that Tcl_FSMatchInDirectory may be
	called with a NULL interpreter, and fix the code so this is allowed.
	Tcl's core itself (tclEncoding.c:FillEncodingFileMap()) calls this
	with a NULL interpreter.

2005-08-30  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclObj.c:	Extended bignum support to include bignums so
	large they will not pack into a Tcl_Obj. When they outgrow Tcl's string
	rep length limits, a panic will result.

	* generic/tclTomMath.h:	Added mp_sqrt to routines from
	* unix/Makefile.in:	libtommath used by Tcl.
	* win/Makefile.in:
	* win/makefile.vc:

	* generic/tclBasic.c:	Extended sqrt(.) so that range covers the
	entire double range, accepting as many bignums in the domain as that
	will allow.

2005-08-29  Andreas Kupries  <andreask@activestate.com>

	* library/tm.tcl (::tcl::tm::roots): Accepted Don Porter's patch for
	[Bug 1189657]. Syncs the implementation to the specification (TIP #189)

2005-08-29  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]	Merge updates from HEAD.

	* generic/tclBasic.c:	Restored round(.) to the Tcl 8.4 rules.

2005-08-29  Kevin Kenny  <kennykb@acm.org>

	* generic/tclBasic.c (ExprMathFunc): Restored "round away from zero"
	* tests/expr.test (expr-46.*):       behaviour to the "round" function.
	Added test cases for the behavior, including the awkward case of a
	number whose fractional part is 1/2-1/2ulp. [Bug 1275043]

2005-08-26  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c: Moved Tcl_{Cut,Splice}Channel to
	{Cut,Splice}Channel for internal use, and created new public functions
	for Tcl_{Cut,Splice}Channel which walk the whole stack of
	transformations and invoke the necessary thread actions. Added code to
	Tcl_(Un)StackChannel to properly invoke the thread actions when pushing
	and popping transformations on/from a channel.

2005-08-26  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclNamesp.c (NamespaceEnsembleCmd): Reset the result after
	creating an ensemble to clear any result object sharing (potentially
	caused by delete traces) so that we can safely return the name of the
	ensemble. Previously, this caused crashes in Snit's test suite.

2005-08-25  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclListObj.c (UpdateStringOfList): Stop uncontrolled and
	unsafe crashes from happening when working with very large string
	representations. [Bug 1267380]

	* generic/tclExecute.c (TEBC:INST_DICT_LAPPEND): Stop dropping a
	duplicated object on the floor, which was a memory leak (and a wrong
	result too). Thanks to Andreas Kupries for reporting this.

2005-08-25  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch] Merge updates from HEAD

	* generic/tclExecute.c: Bug fix. INST_RSHIFT: shift of negative values
	produced incorrect results.

	* generic/tclExecute.c: Bug fix. INST_*SHIFT opcodes stack management.
	[expr 0<<6] should be 0, not 6.

	* generic/tclBasic.c: Extended the domain of round(.) to all non-Inf,
	non-NaN doubles, using bignums for the result as needed.

2005-08-24  Andreas Kupries  <andreask@activestate.com>

	TIP#219 IMPLEMENTATION

	* doc/SetChanErr.3: ** New File **. Documentation of the new channel
	API functions.
	* generic/tcl.decls:  Stub declarations of the new channel API.
	* generic/tclDecls.h: Regenerated
	* generic/tclStubInit.c:

	* tclIORChan.c: ** New File **. Implementation of the reflected
	channel.
	* generic/tclInt.h: Integration of reflected channel and new error
	* generic/tclIO.c:  propagation into the generic I/O core.
	* generic/tclIOCmd.c:
	* generic/tclIO.h:
	* library/init.tcl:

	* tests/io.test:    Extended testsuite.
	* tests/ioCmd.test:
	* tests/chan.test:
	* generic/tclTest.c:
	* generic/tclThreadTest.c:

	* unix/Makefile.in: Integration into the build machinery.
	* win/Makefile.in:
	* win/Makefile.vc:

2005-08-24  Kevin Kenny  <kennykb@acm.org>

	* generic/tclStrToD.c (Tcl_DoubleDigits): Fixed the corner cases of
	* tests/binary.test (binary-65.*)         formatting floating point
	numbers with the largest and smallest possible significands, and added
	test cases for them.

2005-08-24  Kevin Kenny  <kennykb@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclExecute.c: Corrected some TRACE bugs that prevented
	compilation with --enable-symbols=all.
	* generic/tclStrToD.c: Revised commentary to prepare for a renaming of
	the file, removed some dead code, and fixed a bug where
	TclBignumToDouble failed on huge negative numbers.
	* tests/binary.test (binary-65.*): Added missing 'ieeeFloatingPoint'
	to large/small significand tests.
	* tests/expr.test (expr-45.*) Added missing braces around expressions.

2005-08-24  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclBasic.c:	Revised implementation of the ceil(.) and
	* generic/tclInt.h:	floor(.) math functions in light of the
	* generic/tclStrToD.c:	revised comparison operators, so that it is
	always true that ($x <= ceil($x)) and ($x >= floor($x)). The simple
	approach of "convert to double and call ceil() or floor()" could not
	guarantee that.

	* generic/tclExecute.c:	Bug fix: TclBignumToDouble return -Inf when
	appropriate. Removed declarations of removed routines.

	* generic/tclExecute.c: Revised the type promotion rules of the
	comparison operators so that they form proper equivalence classes over
	the set of numeric strings.

2005-08-23  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure.in:
	* win/configure: Regen.
	* win/configure.in: Update minimum autoconf version to 2.59.

2005-08-23  Kevin Kenny  <kennykb@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclCmdMZ.c (Tcl_StringObjCmd):
	* generic/tclInt.h:
	* generic/tclObj.c (Tcl_GetBooleanFromObj, SetDoubleFromAny,
	Tcl_GetLongFromObj, Tcl_GetWideIntFromObj, Tcl_GetBignumFromObj):
	* generic/tclParseExpr.c (GetLexeme):
	* generic/tclScan.c (Tcl_ScanObjCmd):
	* generic/tclStrToD.c (TclParseNumber):
	* tests/binary.test (binary-62.1-65.7):
	* tests/expr.test (expr-40.1-42.1):
	* scan.test (scan-14.1,14.2):
	Modified Tcl_ParseNumber to accept an argument to force interpretation
	as decimal, and modified [scan] to use it. Corrected a bug where Not a
	Number with hexadecimal information bits returned consistently
	incorrect values. #ifdef-ed out some code that is needed only for IBM
	hexadecimal floating point. Fixed bugs in code to handle the corner
	cases of smallest and largest significands. Added test cases to improve
	test coverage in generic/tclStrToD.c. Added test cases for 0b notation
	(TIP #114). Removed TclStrToD, and the static functions that it calls,
	which are now dead code (TclParseNumber now does all input
	floating-point conversions.)

2005-08-23  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclStrToD.c:	Bug fix: set shift magnitude properly whether
	we're expanding to mp_int type or not.

	* generic/tclExecute.c:	Bug fix: ACCEPT_NAN under INST_UMINUS.

	* generic/tclStrToD.c:	New macros TIP_114_FORMATS and KILL_OCTAL to
	configure acceptance of 0o and 0b numbers and rejection of "leading
	zero as octal".

	* generic/tclBasic.c:	Re-used the guts of int(.) and wide(.) math
	functions to perform conversions in OldMathFuncProc.

	* generic/tclBasic.c:	Support for ACCEPT_NAN.
	* generic/tclExecute.c:

	* generic/tclInt.decls:	Restored TclExprFloatError to internal stubs
	* generic/tclBasic.c:	table, and moved definition back to
	* generic/tclExecute.c:	tclExecute.c from tclBasic.c to handle #undef
	ACCEPT_NAN.

	* generic/tclIntDecls.h:	make genstubs
	* generic/tclStubInit.c:

	* generic/tclInt.h:	New internal macros TclIsNaN and TclIsInfinite
	* generic/tclBasic.c:	replace the IS_NAN and IS_INF macros scattered
	* generic/tclExecute.c:	here and there.
	* generic/tclObj.c:
	* generic/tclStrToD.c:
	* generic/tclUtil.c:

2005-08-22  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tclConfig.h.in: autoheader-2.59.

2005-08-22  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclInt.h:	New ACCEPT_NAN macro to mark code that
	* generic/tclCmdAH.c:	supports or disables accepting of the NaN
	* generic/tclExecute.c:	value at various points.
	* generic/tclLink.c:

	* generic/tclStrToD.c:	Bug fix. Parsing of +/- Infinity was reversed.

	* generic/tclTestObj.c:	Disabled unused [testconvertobj] command.

	* generic/tclBasic:	Added [expr {entier(.)}]. Rewrote int(.) and
	wide(.) to use the same guts, accepting all non-Inf doubles as
	arguments.

	* generic/tclInt.h:	New routine TclInitBignumFromDouble.
	* generic/tclStrToD.c:	Modified to return code and write error
	message.

	* generic/tclInt.h:	TCL_WIDE_INT_IS_LONG implies NO_WIDE_TYPE.
	* generic/tclObj.c:	Removed now unnecessary tests of the
	* generic/tclStrToD.c:	TCL_WIDE_INT_IS_LONG definition.

	* generic/tclInt.h:	New internal routine TclSetBignumIntRep
	* generic/tclObj.c:	consolidates packing of bignum value into a
	* generic/tclStrToD.c:	Tcl_Obj within one source code file.

	* tests/expr.test:	Corrected the wideIs64bit constraint.
	* tests/format.test:
	* tests/scan.test:

2005-08-21  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclInt.h:		Moved TclParseInteger to tclUtil.c and
	* generic/tclParseExpr.c:	made it static.
	* generic/tclUtil.c:

	* generic/tclInt.decls:	Moved TclExprFloatError to tclBasic.c and made
	* generic/tclBasic.c:	it static.
	* generic/tclExecute.c:

	* generitc/tclIntDecls.h:	make genstubs
	* generic/tclStubInit.c:

	* generic/tclExecute.c:	errno, IS_NAN, IS_INF, LLD no longer called in
	this file; dropped/disabled support for them.

	* generic/tclCompExpr.c:	errno no longer used in these files;
	* generic/tclParseExpr.c:	dropped support "hack" for it.

	* generic/tclStrToD.c:	Disabled out of date support "hack" for errno.

	* generic/tclBasic.c:	Eliminated VerifyExprObjType. Initialize errno
	to zero in OldMathFuncProc.

2005-08-19  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclBasic.c:	Updated OldMathFuncProc and ExprAbsFunc to do
	less invasion into numeric Tcl_Obj internals. Made ExprDoubleFunc,
	ExprIntFunc, ExprWideFunc, and ExprRoundFunc bignum-aware. Revised
	ExprSrandFunc error message.

	* generic/tclProc.c:	Wrapped a few tclWideIntType uses in
	* generic/tclCmdMZ.c:	#ifndef NO_WIDE_TYPE.

	* generic/tclInt.h:	#define'd NO_WIDE_TYPE.

	* generic/tclVar.c:	Replaced TclPtrIncrVar and TclPtrIncrWideVar
	* generic/tclInt.h:	with TclPtrIncrObjVar and replaced TclIncrVar2
	* generic/tclInt.decls:	and TclIncrWideVar2 with TclIncrObjVar2. New
	routines call on TclIncrObj to do the work.

	* generic/tclIntDecls.h:	make genstubs
	* generic/tclStubInit.c:

	* generic/tclCmdIL.c:	Rework Tcl_IncrObjCmd and the INST_*INCR*
	* generic/tclExecute.c:	opcodes to use the new routines.

2005-08-18  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclExecute.c:		Fixed string rep invalidation bug in
	* tests/dict.test (dict-11.17):	INST_DICT_INCR_IMM rewrite.

	* generic/tclDictObj.c:	DictIncrCmd rewrite to use TclIncrObj.

	* generic/tclInt.h:	TclIncrObj static -> internal
	* generic/tclExecute.c:

2005-08-17  George Peter Staplin  <GeorgePS@XMission.com>

	* generic/tclBasic.c: eliminate a namespace clash caused by
	BuiltinFuncTable not being static.

	* generic/tclObj.c: fix a namespace clash caused by a missing
	static for pendingObjData.

2005-08-17  Kevin Kenny  <kennykb@acm.org>

	* generic/tclEvent.c (Tcl_Finalize): Removed a copy-and-paste accident
	that caused a (mostly harmless) double finalize of the load and
	filesystem subsystems.
	* tests/clock.test: Eliminated the bad test clock-43.1, and split
	clock-50.1 into two tests, with a more permissive check on the error
	message for an out-of-range value.

2005-08-17  Kevin Kenny  <kennykb@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclBasic.c (Tcl_Expr{Long,Double}{,Obj}): Updated to
	* generic/tclTest.c:                                deal with
	* tests/expr-old.test:                              bignums (well,
	* tests/expr.test:                                  mostly).
	Added a missing "errno=0;" in ExprUnaryFunc so that spurious error
	returns aren't detected.
	Added test cases for Tcl_Expr* and Tcl_Expr*Obj because there was very
	poor test coverage in those areas.
	* generic/tclParseExpr.c: Reworked parsing of numbers to call
	TclParseNumber rather than trying to do things locally.
	* generic/tclStrToD.c: Corrected a comment. Changed so that *endPtrPtr
	does not include any trailing whitespace.

2005-08-17  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclExecute.c: New routine TclIncrObj to centralize the
	increment operation needed in many places. Updated INST_DICT_INCR_IMM
	to make use of it.

2005-08-16  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclExecute.c:	Made bit shifting opcodes and INST_MOD
	bignum-aware.

	* tests/scan.test:	Making << bignum-aware means that repeated
	* tests/string.test:	left shifting cannot turn a positive into a
	negative. Revised [int_range] and [largest_int] utility commands in the
	test suite that relied on that happening. Without revision they became
	infinite loops.

	* generic/tclExecute.c:	Made binary bitwise opcodes bignum-aware.

	* generic/tclTomMath.h:	Added mp_or and mp_xor to routines from
	* unix/Makefile.in:	libtommath used by Tcl.
	* win/Makefile.in:
	* win/makefile.vc:

2005-08-15  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]	Updates from HEAD.
	* generic/tclExecute.c:	More revisions to IllegalExprOperandType.
	Merged INST_BITNOT with INST_UMINUS and make it bignum-aware according
	to the rule: ~a = -a - 1. Disabled unused code and noted more TODOs.

	* generic/tclInt.decls: Disabled TclLooksLikeInt() and all callers.
	* generic/tclUtil.c:
	* generic/tclCompCmds.c:

	* generic/tclBasic.c:	Rewrite of VerifyExprObjType().

	* generic/tclIntDecls.h:	make genstubs
	* generic/tclStubInit.c:

	* generic/tclExecute.c: Updated execution of comparison bytecodes to
	be bignum-aware, routing string compares through INST_STR_CMP.

2005-08-14  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclExecute.c: Updated execution of arithmetic bytecodes to
	be bignum-aware, and to allow calculations on NaN to produce a NaN
	result. INST_UMINUS updated to call mp_neg.

	* generic/tclTomMath.h:	Added mp_and, mp_expt_d, and mp_neg to
	* unix/Makefile.in:	routines from libtommath used by Tcl.
	* win/Makefile.in:
	* win/makefile.vc:

2005-08-13  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclObj.c:	Extended Bignum auto-narrowing to auto-narrow
	to tclWideIntType when appropriate; this helps keep things working as
	the bytecode execution code is migrated to supporting bignums.

	* generic/tclExecute.c:	Major overhaul of IllegalExprOperandType.
	Changed several TclNewFooObj() calls to more logically appropriate
	ones. Added several TODO comments marking opportunies for future work.
	Made more use of the eePtr->constants. Made INST_UMINUS bignum aware.

2005-08-12  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclExecute.c: Simplify doCondJump. Use eePtr->constants as
	result of INST_DICT_NEXT, INST_LAND, and INST_LOR. Separate INST_LNOT
	from INST_UMINUS and simplify.

2005-08-12  Kevin Kenny  <kennykb@acm.org>

	* generic/tclClock.c (MktimeObjCmd):
	* library/clock.tcl (GetSystemTimeZone, LoadZoneinfoFile)
	(ReadZoneinfoFile):
	* tests/clock.test (clock-50.1):
	Added functionality to read /etc/localtime if it exists, so that Tcl's
	time can track system time on Linux even if TZ is not set. Changed
	::tcl::clock::Mktime to check for failure, and added a test case that
	mimics failure but is really success.

2005-08-11  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclExecute.c: Rewrite of INST_LAND/INST_LOR to take advantage
	of loss of "pure double" issues. Merged INST_UPLUS with
	INST_TRY_CVT_TO_NUMERIC and updated to use improved rules for impure
	"double"s as well.

	* generic/tclStrToD.c:	Restored conditional generation of
	tclWideIntType values by TclParseNumber so that Tcl's not completely
	broken while bignum calculation support is incomplete. The NO_WIDE_TYPE
	macro can be used to disable this.

	* generic/tclBasic.c (ExprAbsFunc): First pass making [expr abs(.)]
	bignum-aware.

2005-08-11  Kevin Kenny  <kennykb@acm.org>

	* generic/tclEvent.c:         Eliminated the USE_THREAD_STORAGE option
	* generic/tclInt.h:           (which is on in every build generated by
	* generic/tclThread.c:        by the standard configurator).
	* generic/tclThreadStorage.c: Eliminated the code for thread specific
	* unix/configure:             data without USE_THREAD_STORAGE and
	* unix/tcl.m4:                radically refactored the code for
	* unix/tclConfig.h.in:        USE_THREAD_STORAGE so that it has fewer
	* unix/tclUnixThrd.c:         dependencies on the order of
	* win/configure:              finalization. (Also, made 'make
	* win/Makefile.in:            distclean' on Windows clean just a little
	* win/rules.vc:               bit cleaner.)
	* win/tcl.m4:
	* win/tclWinThrd.c:

2005-08-10  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclTomMath.h:	Added mp_shrink, mp_to_unsigned_bin,
	* unix/Makefile.in:	mp_to_unsigned_bin_n, and mp_unsigned_bin_size
	* win/Makefile.in:	to routines from libtommath used by Tcl.
	* win/makefile.vc:

	* generic/tommath.h:	make gentommath_h

	* generic/tclObj.c:	Substantial rewrite to make all number parsing
	flow through TclParseNumber(). Also established the NO_WIDE_TYPE and
	BIGNUM_AUTO_NARROW #ifdef's to help track the assumptions of different
	portions of the code.

	* generic/tclInt.h:	Added NO_WIDE_TYPE #ifdefs

2005-08-10  Kevin Kenny  <kennykb@acm.org>

	* generic/tclEvent.c (Tcl_Finalize): Pushed Tcl_FinalizeLoad and
	Tcl_ResetFilesystem down after Tcl_FinalizeThreadAlloc because we can't
	unload DLL's until after their TSD keys are finalized. (Note that we'll
	still see aborts if an unloaded DLL has TSD - that still needs to be
	fixed.

	* tests/compExpr-old.test (compExpr-3.8): Made tests conditional on
	* tests/expr.test (expr-3.8):             'unix' because they get
	stack overflows on Win32 threaded builds,

2005-08-09  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclPathObj.c: fix to [file rootname] bug in optimized code
	path reported on comp.lang.tcl.

2005-08-08  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]

	* generic/tclObj.c:	Replaced some goto's with loops and started
	use of BIGNUM_AUTO_NARROW and NO_WIDE_TYPE.

2005-08-06  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclThreadStorage.c: Stop exposing the guts of the thread
	storage system through the internal stubs table. Client code should
	always use the standard API.

2005-08-05  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch]
	* generic/tclObj.c:	Rewrote Tcl_GetDoubleFromObj().

2005-08-05  Donal K. Fellows  <dkf@users.sf.net>

	* unix/tclUnixInit.c (localeTable): Solaris uses a non-standard name
	for the cp1251 charset. Thanks to Victor Wagner for reporting this.
	[Bug 1252475]

2005-08-05  Kevin Kenny  <kennykb@users.sourceforge.net>

	* win/makefile.vc: Removed unused file ldAout.tcl.
	* win/makefile.bc: [Bug 1244361]

	* tests/binary.test: Cleaned up testing for scanning of NaN. [Bug
	1246264]

	* generic/tclBasic.c (ExprAbsFunc): Added code to handle the corner
	* tests/expr.test (expr-38.1):      case of applying 'abs' to the
	smallest 32-bit integer. [Bug 1241572]

2005-08-04  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c (CloseChannel): Fixed comment nit, added apparently
	missing word to complete a sentence.

	* generic/tclObj.c (Tcl_DbDecrRefCount): Fixed whitespace nit in panic
	message.

2005-08-04  Don Porter  <dgp@users.sourceforge.net>

	[kennykb-numerics-branch] Updated from HEAD

	* generic/tclObj.c:	Rewrote Tcl_GetBooleanFromObj() and supporting
	routines to make use of TclParseNumber. This reduces the potential
	number of times a string value must be scanned.

	* generic/tclObj.c:	Simplified routines that manage the typeTable.
	Deleted the UpdateStringOfBoolean() routine, that can never be called.

2005-08-03  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompExpr.c:	Untangled some dependencies in the
	* generic/tclEvent.c:		order of finalization routines.
	* generic/tclInt.h:		[Bug 1251399]
	* generic/tclObj.c:

2005-08-02  Don Porter	<dgp@users.sourceforge.net>

	[kennykb-numerics-branch] Updated from HEAD

2005-07-30  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tclLoadDyld.c (TclpDlopen, TclpLoadMemory): workarounds for
	bugs/changes in behaviour in Mac OS X 10.4 Tiger.

2005-07-29  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdIL.c (InfoGlobalsCmd): Even in high-speed mode, still
	have to take care with non-existant variables. [Bug 1247135]

2005-07-28  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/README: Update link to msys_mingw8.zip.

2005-07-28  Don Porter	<dgp@users.sourceforge.net>

	* tests/compExpr-old.test:	Still more conversion of "nonPortable"
	* tests/error.test:		tests into tests with constraints that
	* tests/expr-old.test:		describe the limits of their
	* tests/expr.test:		portability. Also more consolidation
	* tests/fileName.test:		of constraint synonyms.
	* tests/format.test:		wideis64bit, 64bitInts => wideIs64bit
	* tests/get.test:		wideIntegerUnparsed => wideIs32bit
	* tests/load.test:		wideIntExpressions => wideBiggerThanInt
	* tests/obj.test:
	* tests/parseExpr.test:		Dropped "roundOffBug" constraint that
	* tests/string.test:		protected from buggy sprintf.

2005-07-28  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclPipe.c (TclCreatePipeline): Arrange for POSIX systems to
	* unix/tclUnixPipe.c (TclpOpenFile):	 use the O_APPEND flag for
	* tests/exec.test (exec-19.1):		 files opened in a pipeline
	like ">>this". Note that Windows cannot support such access; there is
	no equivalent flag on the handle that can be set at the kernel-call
	level. The test is unix-specific in every way. [Bug 1245953]

2005-07-27  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclUtil.c:	Converted the $::tcl_precision value to be kept
	per-thread to prevent different threads from stomping on each others'
	formatting prescriptions.

	***POTENTIAL INCOMPATIBILITY*** Multi-threaded programs that set the
	value of ::tcl_precision will now have to set it in each thread.

	* tests/expr.test:	Consolidated equivalent constraints into
	* tests/fileName.test:	single definitions and (more precise) names:
	* tests/get.test:	longis32bit, 32bit, !intsAre64bit => longIs32bit
	* tests/listObj.test:	empty => emptyTest; winOnly => win
	* tests/obj.test:	intsAre64bit => longIs64bit
	Also updated some "nonPortable" tests to use constraints that mark
	precisely what about them isn't portable, so the tests can run where
	they work.

	* library/init.tcl ([unknown]): Corrected return code handling in the
	portions of [unknown] that expand incomplete commands during
	interactive operations. [Bug 1214462].

2005-07-26  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure: Regen.
	* unix/configure.in: Check for a $prefix/share directory and add it the
	the package if found. This will check for Tcl packages in
	/usr/local/share when Tcl is configured with the default dist install.
	[Patch 1231015]

2005-07-26  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c (Tcl_CallWhenDeleted):	Converted to use
	per-thread counter, rather than a process global one that required
	mutex protection. [RFE 1077194]

	* generic/tclNamesp.c (TclTeardownNamespace):	Re-ordering so that
	* tests/trace.test (trace-34.4):	command delete traces fire
	while the command still exists. [Bug 1047286]

2005-07-24  Mo DeJong  <mdejong@users.sourceforge.net>

	* unix/configure: Regen.
	* unix/tcl.m4 (SC_PROG_TCLSH, SC_BUILD_TCLSH):
	* win/configure: Regen.
	* win/tcl.m4 (SC_PROG_TCLSH, SC_BUILD_TCLSH): Split confused search
	for tclsh on PATH and build and install locations into two macros.
	SC_PROG_TCLSH searches just the PATH. SC_BUILD_TCLSH determines the
	name of the tclsh executable in the Tcl build directory. [Bug 1160114]
	[Patch 1244153]

2005-07-23  Don Porter	<dgp@users.sourceforge.net>

	* library/auto.tcl:	Updates to the Tcl script library to make use
	* library/history.tcl:	of Tcl 8.4 features. Forward port of
	* library/init.tcl:	appropriate portions of [Patch 1237755].
	* library/package.tcl:
	* library/safe.tcl:
	* library/word.tcl:

2005-07-23  Mo DeJong  <mdejong@users.sourceforge.net>

	* tests/string.test: Add string is tests for functionality that was not
	tested.
	* win/README: Update msys + mingw URL. Remove old Cygwin + mingw info.

2005-07-23  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c (INST_DICT_*): stop 2 compiler warnings for
	uninitialised variables.

2005-07-23  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclExecute.c (TEBC:INST_DICT_INCR_IMM): Fix the incrementor
	to work correctly with wide values.

2005-07-21  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileDictCmd): First run at a compiler
	* generic/tclExecute.c (TclExecuteByteCode): for dictionaries. Also
	added an instruction to support 'finally'-like clauses, exposed more of
	the dict guts to the rest of the core, and defined a few tests to
	exercise more obscure parts of the compiler's operation that were bugs
	during development.

2005-07-21  Kevin B. Kenny  <kennykb@acm.org>

	* library/ldAout.tcl (***REMOVED***):	Removed support for ancient
	* unix/configure:			BSD's, IRIX 4, RISCos and
	* unix/Makefile.in:			Ultrix. Removed two files whose
	* unix/tcl.m4:				code is used only on those
	* unix/tclLoadAout.c (***REMOVED***):	antique platforms.

	***POTENTIAL INCOMPATIBILITY*** if anyone actually uses those
	platforms; it is to be noted though, that an error in the installer has
	actually not caused a necessary file to be installed on those platforms
	in several releases, and nobody's complained.

2005-07-16  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclStrToD.c (RefineResult):  Plugged a stupid memory leak in
	RefineResult (called from Tcl_StrToD). [Tk Bug 1227781]

2005-07-15  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclClock.c (TclClockLocaltimeObjCmd,ThreadSafeLocalTime):
	* library/clock.tcl (GuessWindowsTimeZone, ClearCaches):
	* tests/clock.test (clock-49.1, clock-49.2):
	Handle correctly the case where localtime() returns NULL to report a
	conversion error. Also handle the case where the Windows registry
	contains timezone values that can be mapped to a tzdata file name but
	the corresponding file does not exist or is corrupted, by falling back
	on a Posix timezone string instead; this last case will avoid calls to
	localtime() in starpacks on Windows. [Bug 1237907]

2005-07-14  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclCompile.c: Update to follow style guidelines.
	(TclPrintInstruction): Reorganize to do better printing out of bytecode
	with far fewer "special hacks" for particular opcodes.
	* generic/tclCompile.h: Requires two new opcode types.

2005-07-13  Don Porter	<dgp@users.sourceforge.net>

	* unix/tclUnixSock.c:	Use a ProcessGlobalValue to store the value
	* win/tclWinSock.c:	returned by Tcl_GetHostName() ([info
	hostname]). Also re-order initialization of the value on Windows to
	favor GetComputerName() over gethostname() as a source of the
	information.

2005-07-12  Kevin Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch] Updated from HEAD

	* generic/tclCmdMZ.c (Tcl_StringObjCmd):
	* generic/tclInt.h:
	* generic/tclObj.c (Tcl_GetDoubleFromObj, SetDoubleFromAny)
	(Tcl_GetIntFromObj, SetIntOrWideFromAny):
	* generic/tclStrToD.c (TclParseNumber, etc.):
	* tclTomMathInterface.c (TclBNInitBignumFromWideUInt):
	* tests/obj.test (obj-1.1, obj-2.2, obj-3.1, obj-3.2):

	Initial attempt at an implementation of TIP #249, comprising a unified
	parser and modifications to the Tcl_Get*FromObj routines to use it.
	Further integration of the parser is necessary and planned.

2005-07-12  Donal K. Fellows  <dkf@users.sf.net>

	* doc/lsearch.n: Clarify documentation of -exact option; wording was
	open to misinterpretation by non-English speakers.

2005-07-11  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclExecute.c: General style cleanup.

2005-07-08  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tclExecute.c (TclExecuteByteCode): Reimplement long and wide
	type integer division and modulus operations so that the smallest and
	largest integer values are handled properly. The divide operation is
	more efficient since it no longer does a modulus or negation and only
	checks for a remainder when the quotient will be a negative number.
	The modulus operation is now a bit more complex because of a number of
	special cases dealing with the smallest and largest integers.
	* tests/expr.test: Add test cases for division and modulus operations
	on the smallest and largest integer values for 32 and 64 bit types.
	[Patch 1230205]

2005-07-06  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclLink.c:	Simplified LinkTraceProc [Bug 1208108].

2005-07-05  Don Porter	<dgp@users.sourceforge.net>

	* unix/Makefile.in:	Purged use of TCLTESTARGS [RFE 1161550].

	* generic/tclUtil.c:	Converted TclFormatInt() into a macro.
	* generic/tclInt.decls:	[RFE 1194015]
	* generic/tclInt.h:

	* generic/tclIntDecls.h:	make genstubs
	* generic/tclStubInit.c:

	* generic/tclNamesp.c:	Allow for [namespace import] of a command
	* tests/namespace.test:	over a previous [namespace import] of itself
	without throwing an error. [RFE 1230597]

2005-07-04  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclDictObj.c (DictForCmd, DictFilterCmd): Interlocking of
	dictionary internal representations is now done in the core of the dict
	iterator. Purge the last attempts at doing it at a higher level as they
	didn't work and were no longer needed.

2005-07-01  Zoran Vasiljevic  <vasiljevic@users.sourceforge.net>

	* unix/tclUnixNotfy.c: protect against spurious wake-ups while waiting
	on the condition variable when tearing down the notifier thread [Bug
	1222872].

2005-06-28  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tclExecute.c (TclExecuteByteCode): When parsing an integer
	operand for a unary minus expression operator, check for a wide integer
	that is actually LONG_MIN. If found, convert back to a long int type.
	* tests/expr.test: Add constraint for 32bit long int type and 64bit
	wide int type. Add tests that parse the smallest/largest long int and
	wide int values.

2005-06-24  Kevin Kenny  <kennykb@acm.org>

	* generic/tclEvent.c (Tcl_Finalize):
	* generic/tclInt.h:
	* generic/tclPreserve.c (TclFinalizePreserve): Changed the finalization
	logic so that Tcl_Preserve finalizes after exit handlers run; a lot of
	code called from Tk's exit handlers presumes that Tcl_Preserve will
	still work even from an exit handler.

2005-06-24  Don Porter	<dgp@users.sourceforge.net>

	* library/auto.tcl:	Make file safe to re-[source] without
	destroying registered auto_mkindex_parser hooks.

2005-06-23  Kevin Kenny  <kennykb@acm.org>

	* win/tclWinChan.c: More rewriting of __asm__ blocks that implement
	* win/tclWinFCmd.c: SEH in GCC, because mingw's gcc 3.4.2 is not as
	forgiving of violations committed by the old code and caused panics.
	[Bug 1225957]

2005-06-23  Daniel Steffen  <das@users.sourceforge.net>

	* tools/tcltk-man2html.tcl: fixed useversion glob pattern to accept
	multi-digit patchlevels.

2005-06-22  Don Porter	<dgp@users.sourceforge.net>

	* win/tclWinFile.c: Potential buffer overflow. [Bug 1225571] Thanks to
	Pat Thoyts for discovery and fix.

2005-06-22  Kevin Kenny  <kennykb@acm.org>

	* generic/tclInt.h:			    Changed the finalization
	* generic/tclEvent.c (Tcl_Finalize):	    logic to defer the
	* generic/tclIO.c (TclFinalizeIOSubsystem): shutdown of the pipe
	* unix/tclUnixPipe.c (TclFinalizePipes):    management until after all
	* win/tclWinPipe.c (TclFinalizePipes):	    channels have been closed,
	in order to avoid a situation where the Windows PipeCloseProc2 would
	re-establish the exit handler after exit handlers had already run,
	corrupting the heap. [Bug 1225727] Also corrected a potential read of
	uninitialized memory in PipeClose2Proc [Bug 1225044]

2005-06-21  Andreas Kupries  <andreask@activestate.com>

	* generic/tclInt.h: Followup to change made on 2005-06-18 by Daniel
	Steffen. There are compilers (*) who error out on the redefinition of
	WORDS_BIGENDIAN. We have to undef the previous definition (on the
	command line) first to make this acceptable. (*): AIX native.

2005-06-21  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclFileName.c: Changed [file split] and [file join] to treat
	Windows drive letters similarly to ~ syntax and make sure that they
	appear with "./" in front when they are in intermediate components of
	the path. [Bug 1194458]
	* tests/fileName.test: Added test for the above bug.

2005-06-21  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Added missing walk of the list of active
	* generic/tclTrace.c:	traces to cleanup references to traces being
	* generic/tclInt.h:	deleted. [Bug 1201035] Made the walk of the
	* tests/trace.test (trace-34.*): active trace list aware of the
	direction of trace scanning, so the proper correction can be made.
	[Bug 1224585]

2005-06-21  Donal K. Fellows  <dkf@users.sf.net>

	* unix/tcl.m4 (SC_ENABLE_SYMBOLS): Only enable the 'compile' special
	debugging feature when requested in configure.in; removes irrelevant
	junk from the configure files of extensions that use Tcl's tcl.m4.

2005-06-20  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompile.h (INST_PUSH_RETURN_OPTIONS): New opcode to allow
	* generic/tclCompCmds.c (TclCompileCatchCmd):	   compilation of
	* generic/tclCompile.c:				   TIP#90 catch [Bug
	* generic/tclExecute.c (TclExecuteByteCode):	   1219112]

	* generic/tclCompCmds.c (TclCompileSwitchCmd): Ensure we spill to the
	command form in all cases where it generates an error.

2005-06-20  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tclCmdMZ.c (Tcl_SwitchObjCmd): Generate an error if a mode
	argument like -exact is passed more than once to the switch command.
	The previous implementation silently accepted invalid switch
	invocations like [switch -exact -glob $str ...].
	* tests/for.test: Check some error cases when invoking continue and
	break inside a for loop next script.
	* tests/switch.test: Add checks for shortened version of a mode
	argument like -exact. Add test for more than one mode argument. Add
	test for odd case of passing a variable as a body script.

2005-06-18  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclInt.h: ensure WORDS_BIGENDIAN is defined correctly with
	fat compiles on Darwin (i.e. ppc and i386 at the same time), the
	configure AC_C_BIGENDIAN check is not sufficient in this case because a
	single run of the compiler builds for two architectures with different
	endianness.

	* unix/tcl.m4 (Darwin): add -headerpad_max_install_names to LDFLAGS to
	ensure we can always relocate binaries with install_name_tool.

	* unix/configure: autoconf-2.59

2005-06-18  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclCmdAH.c (Tcl_FormatObjCmd): Fix for [Bug 1154163]; only
	* tests/format.test: insert 'l' modifier when it is needed.

2005-06-17  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclTimer.c (AfterDelay): Split out the code to manage
	synchronous-delay [after] commands.
	* tests/interp.test (interp-34.10): Time limits and synch-delay [after]
	did not mix well... [Bug 1221395]

2005-06-14  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclBasic.c (Tcl_DeleteCommandFromToken): Only delete a
	* tests/namespace.test (namespace-49.2): command from the hashtable on
	reentrant processing if it has not been already deleted; at least three
	deletes of the same command are possible. [Bug 1220058]
	* generic/tclTrace.c (TraceCommandProc): Remove bogus error message
	creation when traces trigger in situations where the command has
	already been deleted.

2005-06-13  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFCmd.c: correct fix to file mkdir 2005-06-09 [Bug 1219176]

2005-06-12  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c: Factor out some common idioms into named forms
	for greater clarity.

2005-06-10  Donal K. Fellows  <dkf@users.sf.net>

	* doc/chan.n: Fold in the descriptive parts of the documentation for
	all the commands that [chan] builds on top of.

2005-06-09  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFCmd.c: fix to race condition in file mkdir [Bug 1217375]
	* doc/glob.n: improve glob documentation [Bug 1190891]

2005-06-09  Donal K. Fellows  <dkf@users.sf.net>

	* doc/expr.n, doc/mathfunc.n: Fix minor typos [Bug 1211078] and add
	mention of distinctly-relevant [namespace path] subcommand.

2005-06-07  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclInt.h:		Reduced the Tcl_ObjTypes "index",
	* generic/tclIndexObj.c:	"ensembleCmd", "localVarName", and
	* generic/tclNamesp.c:		"levelReference" to file static scope.
	* generic/tclProc.c:
	* generic/tclVar.c:

	* generic/tclObj.c:	Restored registration of the "procbody"
	Tcl_ObjType, as required by the tclcompiler application.

	* generic/tclDecls.h:		make genstubs
	* generic/tclStubInit.c:

2005-06-07  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclIO.c (Tcl_ChannelTruncateProc): Stop proliferation of
	* generic/tcl.h:			     channel type versions
	* doc/CrtChannel.3:			     following advice from AKu

	Bump patchlevel to a4 to distinguish from a3 release.

	* generic/tclInt.h (INTERP_TRACE_IN_PROGRESS): Add flag so the error
	* generic/tclIndexObj.c (Tcl_WrongNumArgs):    messages from ensembles
	* generic/tclIOCmd.c (Tcl_ReadObjCmd):	       can be correct.

	TIP#208 IMPLEMENTATION

	* library/init.tcl: Create the chan ensemble.
	* tests/chan.test: Rudimentary test suite.
	* doc/chan.n: General documentation.

	TRUNCATION API (part of TIP#208)
	* generic/tcl.h, generic/tcl.decls: Declaration of the API.
	* doc/CrtChannel.3, doc/OpenFileChnl.3: Documentation of the API.
	* generic/tclBasic.c (Tcl_CreateInterp): Create the mapping into Tcl.
	* generic/tclIOCmd.c (TclChanTruncateObjCmd): Implementation of
	Tcl-level truncation API.
	* generic/tclIO.c (Tcl_TruncateChannel): Generic C-level truncation API
	implementation.
	* unix/tclUnixChan.c (FileTruncateProc): Basic implementation of
	truncating driver.

	* win/tclWinChan.c (FileTruncateProc): Added implementation of file
	truncation for Windows.
	* tests/chan.test (chan-15.2): Added real test of truncation.

2005-06-06  Kevin B. Kenny  <kennykb@acm.org>

	* win/tclWin32Dll.c: Corrected another buglet in the assembly code for
	stack probing on Win32/gcc. [Bug 1213678]
	* generic/tclObj,c: Added missing 'static' on definition of
	UpdateStringOfBignum, and removed a 'switch' on a 'long long' operand
	(which HP-UX native 'cc' seems unable to handle). [Bug 1215775]

2005-06-04  Jeff Hobbs	<jeffh@ActiveState.com>

	*** 8.5a3 TAGGED FOR RELEASE ***

	* unix/Makefile.in (dist): add libtommath

2005-06-03  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* library/parray.tcl (parray): Only generate the sorted list of element
	names once. Thanks to Andreas Leitgeb for spotting this.

2005-06-03  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Makefile: fixed 'embedded' target.

2005-06-02  Jeff Hobbs	<jeffh@ActiveState.com>

	* unix/Makefile.in (html): add BUILD_HTML_FLAGS optional var
	* tools/tcltk-man2html.tcl: add a --useversion to prevent confusion
	when multiple Tcl source dirs exist.

2005-06-01  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	For compatibility with earlier Tcl releases,
	* generic/tclResult.c:	when a command procedure simply does a
	* generic/tclTest.c:	"return TCL_RETURN;" we must interpret that
	* tests/result.test:	the same as
	"return Tcl_SetReturnOptions(interp, Tcl_NewObj());"  [Bug 1209759].

2005-06-01  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclCompCmds.c (TclCompileSwitchCmd): Allow compilation of
	-nocase -glob [switch]es (only one we know how to compile).

	TIP#241 IMPLEMENTATION from Joe Mistachkin

	* generic/tclCmdIL.c (Tcl_LsearchObjCmd, Tcl_LsortObjCmd):
	* generic/tclCmdMZ.c (Tcl_SwitchObjCmd): Implementation of -nocase
	option for [lsearch], [lsort] and [switch] commands.
	* win/tclWinPort.h: Win uses nonstandard function names...
	* tests/cmdIL.test, tests/lsearch.test, tests/switch.test: Tests
	* doc/lsearch.n, doc/lsort.n, doc/switch.n: Docs

	* generic/tclCompCmds.c (TclCompileLindexCmd): Compile the most common
	case of [lindex] more efficiently.

	* unix/tclUnixNotfy.c (Tcl_FinalizeNotifier): Pass the correct number
	of arguments to Tcl_JoinThread.

2005-05-31  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* unix/configure.in, unix/tcl.m4: Standardize generation of help
	messages to always use AC_HELP_STRING and always (except for --with-tcl
	and --with-tk, where the default is complex) say what the default is.

2005-05-31  Zoran Vasiljevic  <vasiljevic@users.sourceforge.net>

	* unix/tclUnixNotfy.c: the notifier thread is now created as joinable
	thread and it is properly joined in Tcl_FinalizeNotifier. This is an
	attempt to fix the [Bug 1082283].

2005-05-30  Zoran Vasiljevic  <vasiljevic@users.sf.net>

	* win/tclWinThrd.c: Fixed [Bug 1204064]

2005-05-30  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	TIP #229 IMPLEMENTATION

	* generic/tclNamesp.c (Tcl_FindCommand, TclResetShadowedCmdRefs)
	(NamespacePathCmd, SetNsPath, UnlinkNsPath, TclInvalidateNsPath):
	Implementation of the [namespace path] command and the command name
	resolution engine.
	* doc/info.n, doc/namespace.n: Doc updates.
	* tests/namespace.test (namespace-51.*): Test updates.
	* generic/tclResolve.c (BumpCmdRefEpochs, Tcl_SetNamespaceResolvers):
	* generic/tclBasic.c (Tcl_CreateCommand, Tcl_CreateObjCommand): Ensure
	that people don't see stale paths.
	* generic/tclInt.h (Namespace, NamespacePathEntry): Structure defs.
	* generic/tclCmdIL.c (InfoCommandsCmd): Updates to [info commands].

2005-05-26  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Makefile: moved & corrected EMBEDDED_BUILD check.

	* unix/configure.in: corrected framework finalization to softlink stub
	library to Versions/8.x subdir instead of Versions/Current.
	* unix/configure: autoconf-2.59

2005-05-25  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclCmdMZ.c (Tcl_TimeObjCmd): add necessary cast

2005-05-25  Don Porter	<dgp@users.sourceforge.net>

	TIP#182 IMPLEMENTATION	[Patch 1165062]

	* doc/mathfunc.n:	New built-in math function bool().
	* generic/tclBasic.c:
	* tests/expr.test:
	* tests/info.test:

2005-05-24  Don Porter	<dgp@users.sourceforge.net>

	* library/init.tcl:	Updated [unknown] to be sure the [return]
	* tests/init.test:	options from an auto-loaded command are seen
	correctly by the caller.

2005-05-24  Daniel Steffen  <das@users.sourceforge.net>

	* tests/env.test: added DYLD_FRAMEWORK_PATH to the list of env vars
	that need to be handled specially.

	* macosx/Makefile:
	* macosx/README:
	* macosx/Tcl-Info.plist.in (new file):
	* unix/Makefile.in:
	* unix/configure.in:
	* unix/tcl.m4:
	* unix/tclUnixInit.c: moved all Darwin framework build support from
	macosx/Makefile into the standard unix configure/make buildsystem, the
	macosx/Makefile is no longer required to build Tcl.framework (but its
	functionality is still available for backwards compatibility).
	* unix/configure: autoconf-2.59

	* generic/tclIOUtil.c (TclLoadFile):
	* generic/tclInt.h:
	* unix/tcl.m4:
	* unix/tclLoadDyld.c: added support for [load]ing .bundle binaries in
	addition to .dylib's: .bundle's can be [unload]ed (unlike .dylib's),
	and can be [load]ed from memory, e.g. directly from VFS without needing
	to be written out to a temporary location first. [Bug 1202209]
	* unix/configure: autoconf-2.59
	* unix/tclConfig.h.in: autoheader-2.59

	* generic/tclCmdMZ.c (Tcl_TimeObjCmd): change [time] called with a
	count > 1 to return a string with a float value instead of a rounded
	off integer. [Bug 1202178]

	* doc/expr.n:
	* doc/string.n: fixed roff syntax complaints from 'make html'.

2005-05-20  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclParseExpr.c:	Corrected parser to recognize all
	boolean literals accepted by Tcl_GetBoolean, including prefixes like
	"y" and "f", and to allow "eq" and "ne" as function names in the proper
	context. [Bug 1201589].

2005-05-19  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclBasic.c (TclEvalObjvInternal): Rewrite for greater
	clarity; although 'goto' is Bad, the contortions you have to go through
	to avoid it can be worse...

2005-05-19  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/tclMacOSXNotify.c (Tcl_InitNotifier): fixed crashing CFRelease
	of runLoopSource in Tcl_InitNotifier (reported by Zoran):
	CFRunLoopAddSource doesn't CFRetain, so can only CFRelease the
	runLoopSource in Tcl_FinalizeNotifier.

2005-05-18  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c (Tcl_ExprBoolean):	Rewrite as wrapper around
	Tcl_ExprBooleanObj.

	* generic/tclCmdMZ.c ([string is boolean/true/false]): Rewrite dropping
	string-based Tcl_GetBoolean call, so that internal reps are kept for
	subsequent quick boolean operations.

	* generic/tclExecute.c:	Dropped most special handling of the "boolean"
	Tcl_ObjType, since that type should now be rarely encountered.

	* doc/BoolObj.3:	Rewrite of documentation dropping many details
	about the internals of Tcl_Objs. Shorter documentation focuses on the
	function and use of the routines.

	* generic/tclInt.h:	Revision to the "boolean" Tcl_ObjType, so that
	* generic/tclObj.c:	only string values like "yes" and "false" are
	* tests/obj.test:	kept as the "boolean" Tcl_ObjType. The string
	values "0" and "1" are kept as "int" Tcl_ObjType, which also produce
	quick calls to Tcl_GetBooleanFromObj(). Since this internal change
	means a Tcl_ConvertToType to a "boolean" Tcl_ObjType might not produce
	a Tcl_Obj of type "boolean", the registration of the "boolean" type is
	also removed.
	***POTENTIAL INCOMPATIBILITY***
	For callers of Tcl_GetObjType on the type name "boolean".

2005-05-17  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclObj.c (TclInitObjSubsystem):	Removed the
	* tests/listObj.test:	registration of the Tcl_ObjType's "list",
	* tests/obj.test:	"procbody", "index", "ensembleCommand",
	"localVarName", and "levelReference". The only reason to register a
	Tcl_ObjType is to have it returned by Tcl_GetObjType, and the only
	reason for that is to retrieve a (Tcl_ObjType *) to pass to
	Tcl_ConvertToType(). None of the types above can support a
	Tcl_ConvertToType() call; they panic. Better not to offer something
	than to lead users into a panic.
	***POTENTIAL INCOMPATIBILITY***
	For callers of Tcl_GetObjType on the type names listed above.

2005-05-15  Kevin Kenny  <kennykb@users.sourceforge.net>

	* win/tclWin32Dll.c: conditioned definition of EXCEPTION_REGISTRATION
	structures on HAVE_NO_SEH, to fix a bug in buildability on MSVC.

2005-05-14  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclInt.decls:
	* generic/tclTest.c:
	* generic/tclUtil.c:
	* win/tclWin32Dll.c: fixed link error due to direct access by tclTest.c
	to the MODULE_SCOPE tclPlatform global: renamed existing
	TclWinGetPlatform() accessor to TclGetPlatform() and moved it to
	generic code so that it can be used by on all platforms where
	MODULE_SCOPE is enforced.

	* macosx/tclMacOSXBundle.c:
	* unix/tclUnixInit.c:
	* unix/tcl.m4 (Darwin): made use of CoreFoundation API configurable and
	added test of CoreFoundation availablility to allow building on ppc64,
	replaced HAVE_CFBUNDLE by HAVE_COREFOUNDATION; test for availability of
	Tiger or later OSSpinLockLock API.

	* unix/tclUnixNotfy.c:
	* unix/Makefile.in:
	* macosx/tclMacOSXNotify.c (new file): when CoreFoundation is
	available, use new CFRunLoop based notifier: allows easy integration
	with other event loops on Mac OS X, in particular the TkAqua Carbon
	event loop is now integrated via a standard tcl event source (instead
	of TkAqua upon loading having to finalize the exsting notifier and
	replace it with its custom version). [Patch 1202052]

	* tests/unixNotfy.test: don't run unthreaded tests on Darwin since
	notifier may be using threads even in unthreaded core.

	* unix/tclUnixPort.h:
	* unix/tcl.m4 (Darwin): test for thread-unsafe realpath during
	configure, as Darwin 7 and later realpath is threadsafe.

	* macosx/Makefile: enable configure caching.

	* unix/configure.in: wrap tclConfig.h header in #ifndef _TCLCONFIG so
	that it can be included more than once without warnings from gcc4.0 (as
	happens e.g. when including both tclInt.h and tclPort.h)

	* macosx/tclMacOSXBundle.c:
	* unix/tclUnixChan.c:
	* unix/tclLoadDyld.c:
	* unix/tclUnixInit.c: fixed gcc 4.0 warnings.

	* unix/configure: autoconf-2.59
	* unix/tclConfig.h.in: autoheader-2.59

	* generic/tclIntDecls.h:
	* generic/tclIntPlatDecls.h:
	* generic/tclStubInit.c: make genstubs

2005-05-13  Kevin Kenny  <kennykb@acm.org>

	* win/tclWin32Dll.c: Further rework of the SEH logic. All
	EXCEPTION_REGISTRATION records are now in the activation record rather
	than pushed on the stack.

2005-05-13  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Dropped the TCL_NO_MATH configuration. It's
	* generic/tclBinary.c:	believed this has not been working in a long
	* generic/tclExecute.c: time. Tcl needs math.h. [RFE 1200680]
	* unix/Makefile.in:

2005-05-12  Kevin Kenny  <kennykb@acm.org>

	* doc/mathfunc.n: Changed NAME line to match the name of the page.

2005-05-11  Kevin Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch] Resynchronized with the HEAD; at this
	checkpoint [-rkennykb-numerics-branch-20050511], the HEAD and
	kennykb-numerics-branch contain identical code.

2005-05-11  Kevin Kenny  <kennykb@acm.org>

	* generic/tclStrToD.c (TclStrToD, RefineResult, ParseNaN): Changed the
	code to cast 'char' to UCHAR explicitly when using ctype macros, to
	silence complaints from the Solaris compiler.

2005-05-10  Jeff Hobbs	<jeffh@ActiveState.com>

	* unix/tclUnixFCmd.c: add lint attr to enum to satisfy strictly
	compliant compilers that don't like trailing ,s.

	* tests/string.test: string-10.[21-30]
	* generic/tclCmdMZ.c (Tcl_StringObjCmd): add extra checks to prevent
	possible UMR in unichar cmp function for string map.

2005-05-10  Kevin Kenny  <kennykb@acm.org>

	* generic/tclBinary.c (FormatNumber): Fixed a bug where NaN's resulted
	in reads of uninitialized memory when using 'd', 'q', or 'Q' format.
	* generic/tclStrToD.c (ParseNaN, TclFormatNaN): Added code to handle
	the peculiarities of HP's PA_RISC, which uses a different 'quiet' bit
	in NaN from everyone else.
	* libtommath/tommath_superclass.h: Corrected C++-style comment.

2005-05-10  Kevin Kenny  <kennykb@acm.org>

	Merged all changes on kennykb-numerics-branch back into the HEAD.
	TIP's 132 and 232 are now Final.

2005-05-10  Kevin Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch] Merged changes from HEAD.

2005-05-10  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c (ExponLong, ExponWide):
	* tests/expr.test (expr-23.34/35): fixed special case 'i**0' for i>0
	[Bug 1198892]

2005-05-09  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch]
	* win/tclWin32Dll.c (TclpCheckStackSpace, TclWinCPUID): Reworked
	structured event handling to function even with -fomit-frame-pointers.

2005-05-08  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch]
	* generic/tclStrToD.c: Made code more portable by finding a workaround
	for MSVC's 'volatile' issue that does not require conditional
	compilation.
	* win/tclWin32Dll.c (TclWinCPUID): Removed structured event handling
	from the GCC code since (a) bad code is generated by the instruction
	scheduling with -O2, and (b) it's not needed on any reasonably modern
	CPU.

2005-05-07  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch]
	* generic/tclEvent.c:  Moved initialization of tclStrToD.c's
	* generic/tclInt.h:    static constants into a procedure called
	* generic/tclStrToD.c: from TclInitSubsystems to avoid double checked
	locking protocol. Cleaned up an issue where MSVC ignored the
	'volatile' specifier, causing incorrect comparison of an underflowed
	number against zero.

2005-05-06  Jeff Hobbs	<jeffh@ActiveState.com>

	* unix/tcl.m4, unix/configure: correct Solaris 10 (5.10) check and add
	support for x86_64 Solaris cc builds.

2005-05-05  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch] Merged with HEAD.

2005-05-05  Kevin B. Kenny  <kennykb@acm.org>

	* win/tclWinThrd.c:  Corrected a compilation error on the
			     --enable-threads configuration.

2005-05-05  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclInt.decls:	Converted TclMatchIsTrivial to a macro.
	* generic/tclInt.h:
	* generic/tclUtil.c:
	* generic/tclIntDecls.h:	`make genstubs`
	* generic/tclStubInit.c:
	* generic/tclBasic.c:	Added callers of TclMatchIsTrivial where a
	* generic/tclCmdIL.c:	search can be done more efficiently when it is
	* generic/tclCompCmds.c:recognized that a pattern match is really an
	* generic/tclDictObj.c:	exact match. [Patch 1076088]
	* generic/tclIO.c:
	* generic/tclNamesp.c:
	* generic/tclVar.c:

	* generic/tclCompCmds.c:	Factored common efficiency trick into a
	macro named CompileWord.

	* generic/tclCompCmds.c:	Replaced all instance of
	* generic/tclCompile.c:		TCL_OUT_LINE_COMPILE with TCL_ERROR.
	* generic/tclInt.h:		Now that we've eradicated the mistaken
	* tests/appendComp.test:	notion of a "compile-time error", we
	can use the TCL_ERROR return code to signal any failure to produce
	bytecode.

2005-05-03  Don Porter	<dgp@users.sourceforge.net>

	* doc/DString.3:	Eliminated use of identifier "string" in Tcl's
	* doc/Environment.3:	public C API to avoid conflict/confusion with
	* doc/Eval.3:		the std::string of C++.
	* doc/ExprLong.3, doc/ExprLongObj.3, doc/GetInt.3, doc/GetOpnFl.3:
	* doc/ParseCmd.3, doc/RegExp.3, doc/SetResult.3, doc/StrMatch.3:
	* doc/Utf.3, generic/tcl.decls, generic/tclBasic.c, generic/tclEnv.c:
	* generic/tclGet.c, generic/tclParse.c, generic/tclParseExpr.c:
	* generic/tclRegexp.c, generic/tclResult.c, generic/tclUtf.c:
	* generic/tclUtil.c, unix/tclUnixChan.c:

	* generic/tclDecls.h:	`make genstubs`

2005-05-02  Don Porter	<dgp@users.sourceforge.net>

	* generic/tcl.decls:
	* generic/tclBasic.c:	Simplified implementation of Tcl_ExprString.
	* tests/expr-old.test:

	* generic/tclDecls.h:	`make genstubs`

2005-04-30  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tclUnixNotfy.c: applied dkf's tkMacOSXNotify.c cleanup changes.

2005-04-29  Don Porter	<dgp@users.sourceforge.net>

	TIP#176 IMPLEMENTATION	[Patch 1165695]

	* generic/tclUtil.c:	Extended TclGetIntForIndex to recognize index
	formats including end+integer and integer+/-integer.

	* generic/tclCmdMZ.c:	Extended the -start switch of [regexp] and
	[regsub] to accept all index formats known by TclGetIntForIndex.

	* doc/lindex.n:		Updated docs to note new index formats.
	* doc/linsert.n, doc/lrange.n, doc/lreplace.n, doc/lsearch.n:
	* doc/lset.n, doc/lsort.n, doc/regexp.n, doc/regsub.n, doc/string.n:

	* tests/cmdIL.test:	Updated tests.
	* tests/compile.test, tests/lindex.test, tests/linsert.test:
	* tests/lrange.test, tests/lreplace.test, tests/lsearch.test:
	* tests/lset.test, tests/regexp.test, tests/regexpComp.test:
	* tests/string.test, tests/stringComp.test, tests/util.test:

2005-04-28  Don Porter	<dgp@users.sourceforge.net>

	* tests/unixInit.test (7.1): Alternative fix for the 2004-11-11 commit.

2005-04-27  Don Porter	<dgp@users.sourceforge.net>

	* library/init.tcl:	Corrected flaw in interactive command
	* tests/main.test:	auto-completion. [Bug 1191409].

	TIP#183 IMPLEMENTATION	[Patch 577093]

	* generic/tclIOUtil.c (TclGetOpenModeEx):	New routine.
	* generic/tclInt.h:

	* generic/tclIO.c (Tcl_OpenObjCmd):	Support for "b" and
	* doc/open.n:		"BINARY" in "access" argument to [open].
	* tests/ioCmd.test:

2005-04-26  Kevin B. Kenny  <kennykb@users.sourceforge.net>

	* generic/tclBinary.c (FormatNumber): Dredge the NaN out of the
	internal representation if Tcl_GetDoubleFromObj returns TCL_ERROR on a
	NaN.

	* generic/tclObj.c (Tcl_GetDoubleFromObj): Restored silent
	overflow/underflow behaviour that the merge of 2004-04-25 messed up.
	Thanks to Don Porter for calling attention to this bug. Also removed an
	uninitialised memory reference in this function that valgrind caught.
	Also changed to return TCL_ERROR on a pure NaN.

	* generic/tclStrToD.c (RefineResult): Added a test for the initial
	approximation being HUGE_VAL; this test avoids EDOM being returned from
	ldexp on some platforms on input values exceeding the floating point
	range.

	* tests/expr.test (expr-29.*, expr-30.*): Added further tests of
	overflow/underflow on input conversions.

2005-04-25  Kevin B. Kenny  <kennykb@users.sourceforge.net>

	[kennykb-numerics-branch] Merged with HEAD.

	* doc/CrtMathFunc.n:		Revised documentation for TIP 232

2005-04-25  Daniel Steffen  <das@users.sourceforge.net>

	* compat/string.h: fixed memchr() protoype for __APPLE__ so that we
	build on Mac OS X 10.1 again.

	* generic/tclNotify.c (TclFinalizeNotifier): fixed notifier not being
	finalized in unthreaded core (was testing for notifier initialization
	in current thread by checking thread id != 0 but thread id is always 0
	in untreaded core).

	* win/tclWinNotify.c (Tcl_WaitForEvent):
	* unix/tclUnixNotfy.c (Tcl_WaitForEvent): don't call ScaleTimeProc for
	zero wait times (as specified in TIP 233).

	* unix/Makefile.in: added @PLAT_SRCS@ to SRCS and split out NOTIFY_SRCS
	from UNIX_SRCS for parity with UNIX_OBJS & NOTIFY_OBJS.

	* unix/tcl.m4 (Darwin): added configure checks for recently added
	linker flags -single_module and -search_paths_first to allow building
	with older tools (and on Mac OS X 10.1), use -single_module in SHLIB_LD
	and not just T{CL,K}_SHLIB_LD_EXTRAS, added unexporting from Tk of
	symbols from libtclstub to avoid duplicate symbol warnings, added
	PLAT_SRCS definition for Mac OS X, defined MODULE_SCOPE to
	__private_extern__.
	(SC_MISSING_POSIX_HEADERS): added caching of dirent.h check.

	* unix/configure: autoconf-2.59

2005-04-25  Kevin B. Kenny  <kennykb@users.sourceforge.net>

	* library/tzdata/America/Boise:
	* library/tzdata/America/Chicago:
	* library/tzdata/America/Denver
	* library/tzdata/America/Indianapolis:
	* library/tzdata/America/Los_Angeles:
	* library/tzdata/America/Louisville:
	* library/tzdata/America/Managua:
	* library/tzdata/America/New_York:
	* library/tzdata/America/Phoenix:
	* library/tzdata/America/Port-au-Prince:
	* library/tzdata/America/Indiana/Knox:
	* library/tzdata/America/Indiana/Marengo:
	* library/tzdata/America/Indiana/Vevay:
	* library/tzdata/America/Kentucky/Monticello:
	* library/tzdata/America/North_Dakota/Center:
	* library/tzdata/Asia/Tehran:
	Olson's tzdata2005i. Corrects exact time at which Standard Time was
	adopted in the US (generally, noon, Standard Time, rather than noon,
	Local Mean Time). Adopts new civil rules for Nicaragua and Iran.

2005-04-25  Don Porter	<dgp@users.sourceforge.net>

	* library/init.tcl:	Use "ni" and "in" operators.

2005-04-25  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: fix for [Bug 1189274].

2005-04-24  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclLiteral.c:	Silence compiler warnings.
	* generic/tclObj.c:	[Bug 1188863].

2005-04-22  Don Porter	<dgp@users.sourceforge.net>

	The 2005-04-21 changes to Tcl_GetBooleanFromObj were done to bring it
	into agreement with its docs. Further investigation reveals it was the
	docs that were incorrect.

	* doc/BoolObj.3:	Corrections to the documentation of
	Tcl_GetBooleanFromObj to bring it into agreement with what this public
	interface has always done, including noting the difference in function
	between Tcl_GetBooleanFromObj and Tcl_GetBoolean.

	* generic/tclGet.c:	Revised Tcl_GetBoolean to no longer be a
	wrapper around Tcl_GetBooleanFromObj (different function!).

	* generic/tclObj.c:	Removed TclGetTruthValueFromObj routine that
	was added yesterday. Revisions so that only Tcl_GetBoolean-approved
	values get the "boolean" Tcl_ObjType. This retains the fix for [Bug
	1187123].
	* tests/string.test:	Test string-23.0 for Bug 1187123.

	* generic/tclInt.h:	Revert most recent change.
	* generic/tclBasic.c:
	* generic/tclCompCmds.c:
	* generic/tclDictObj.c:
	* generic/tclExecute.c:
	* tests/obj.test:

2005-04-21  Don Porter	<dgp@users.sourceforge.net>

	* doc/GetInt.3:	Convert argument "string" to "str" to agree with code.
	Also clarified a few details on int and double formats.
	* generic/tclGet.c:	Radical code simplification. Converted
	Tcl_GetFoo() routines into wrappers around Tcl_GetFooFromObj(). Reduces
	code duplication, and the resulting potential for inconsistency.

	* generic/tclObj.c:	Several changes:

	- Re-ordered error detection code so all values with trailing garbage
	  receive a "not an integer" message instead of an "integer too large"
	  message.
	- Removed inactive code meant to deal with strtoul* routines that fail
	  to parse leading signs. All of them do, and if any are detected that
	  do not, the correct fix is replacement with compat/strtoul*.c, not a
	  lot of special care by the callers.
	- Tcl_GetDoubleFromObj now avoids shimmering away a "wideInt" intrep.
	- Fixed Tcl_GetBooleanFromObj to agree with its documentation and with
	  Tcl_GetBoolean, accepting only "0" and "1" and not other numeric
	  strings. [Bug 1187123]
	- Added new private routine TclGetTruthValueFromObj to perform the more
	  permissive conversion of numeric values to boolean that is needed by
	  the [expr] machinery.

	* generic/tclInt.h (TclGetTruthValueFromObj):	New routine.
	* generic/tclExecute.c:	Updated callers to call new routine.
	* generic/tclBasic.c:	Updated callers to call new routine.
	* generic/tclCompCmds.c:	Updated callers to call new routine.
	* generic/tclDictObj.c:	Updated callers to call new routine.
	* tests/obj.test:	Corrected bad tests that actually expected
	values like "47" and "0xAC" to be accepted as booleans.

	* generic/tclLiteral.c: Disabled the code that forces some literals
	into the "int" Tcl_ObjType during registration. We can re-enable it if
	this change causes trouble, but it seems more sensible to let Tcl's
	"on-demand" shimmering rule, and not try to pre-guess things.

2005-04-20  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch]
	* doc/expr.n:
	* doc/mathfunc.n (new file):	Revised documentation for TIP 232

2005-04-20  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclGet.c (Tcl_GetInt):	Corrected error that did not
	* generic/tclObj.c (Tcl_GetIntFromObj): permit 0x80000000 to be
	recognized as an integer on TCL_WIDE_INT_IS_LONG systems [Bug 1090869].

2005-04-20  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclFileName.c: Silenced a compiler warning about '/*' within
	a comment.

2005-04-19  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Added unsupported command
	* generic/tclCmdAH.c:	[::tcl::unsupported::EncodingDirs] to permit
	* generic/tclInt.h:	query/set of the encoding search path at
	* generic/tclInterp.c:	the script level. Updated init.tcl to make
	* library/init.tcl:	use of the new command. Also updated several
	coding practices in init.tcl ("eq" for [string equal], etc.)

2005-04-19  Kevin B. Kenny  <kennykb@acm.org>

	* library/clock.tcl (Initialize): Put initialization code into a proc
	to avoid inadvertently clobbering global variables. [Bug 1185933]
	* tests/clock.test (clock-48.1): Added regression test for the above
	bug.
	Thanks to Ulrich Ring for reporting this bug.

2005-04-16  Miguel Sofer  <msofer@users.sf.net>

	* generic/Var.c (Tcl_ArrayObjCmd - ARRAY_NAMES): fix Tcl_Obj leak. [Bug
	1084111]

2005-04-16  Zoran Vasiljevic  <vasiljevic@users.sf.net>

	* generic/tclIOUtil.c: force clenaup of the interp result in
	TclLoadFile(). Some implementations of TclpFindSymbol() will seed the
	interp result with error message when unable to find the requested
	symbol (this is not considered to be an error).

	Set of changes correcting huge memory waste (not a leak) when a thread
	exits. This has been introduced in 8.4.7 within an attempt to correctly
	cleanup after ourselves when Tcl library is being unloaded with the
	Tcl_Finalize() call.

	This fixes the [Bug 1178445]

	* generic/tclInt.h: added prototypes for TclpFreeAllocCache() and
	TclFreeAllocCache()

	* generic/tclThreadAlloc.c: modified TclFinalizeThreadAlloc() to
	explicitly call TclpFreeAllocCache with the NULL-ptr as argument
	signalling cleanup of private tsd key used only by the threading
	allocator.

	* unix/tclUnixThrd.c: fixed TclpFreeAllocCache() to recognize when
	being called with NULL argument. This is a signal for it to clean up
	the tsd key associated with the threading allocator.

	* win/tclWinThrd.c: renamed TclWinFreeAllocCache to TclpFreeAllocCache
	and fixed to recognize when being called with NULL argument. This is a
	signal for it to clean up the tsd key associated with the threading
	allocator.

2005-04-13  Don Porter	<dgp@users.sourceforge.net>

	* tests/unixInit.test:	Disabled obsolete tests and removed code
	* tests/encoding.test:	that supported them.
	* generic/tclInterp.c:

	* library/init.tcl:	Use auto-loading to bring in Tcl Module support
	* library/tclIndex:	as needed. This reduces startup time by
	* library/tm.tcl:	delaying this initialization to a later time.

2005-04-15  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: missing semicolons caused failure to compile
	with TCL_COMPILE_DEBUG.

2005-04-13  David Gravereaux  <davygrvy@pobox.com>

	* generic/tclIO.c (Tcl_SetChannelBufferSize): Lowest size limit
	* tests/io.test:	changed from ten bytes to one byte. Need for
	* tests/iogt.test:	this change was proven by Ross Cartlidge
	<rossc@cisco.com> where [read stdin 1] was grabbing 10 bytes followed
	by starting a child process that was intended to continue reading from
	stdin. Even with -buffersize set to one, nine chars were getting lost
	by the buffersize over reading for the native read() caused by [read].

2005-04-13  Don Porter	<dgp@users.sourceforge.net>

	* unix/tclUnixInit.c (TclpGetEncodingNameFromEnvironment): Reversed
	order of verifying candidate [encoding system] value, checking against
	a table in memory first before calling Tcl_GetEncoding and potentially
	scanning through the filesystem. Also ordered the table so that a
	binary search could be used within it. Improves startup time a bit more
	on some systems.

2005-04-13  Kevin B. Kenny  <kennykb@acm.org>

	* library/clock.n: Added a missing '--' on several [switch] commands to
	improve performance of [clock format] and related operations. [FRQ
	1182459]

2005-04-13  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* doc/fcopy.n: Improved documentation on copying binary files, added an
	example and mentioned the use of [file copy].
	* doc/fconfigure.n: Improved documentation of -encoding binary option.
	This is all following comments from Steve Manning <steve@manning.net>
	on comp.lang.tcl that the current documentation was not clear.

2005-04-13  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompile.c:Commented out the functions
	TclPrintInstruction(), TclPrintObject() and TclPrintSource() when not
	debugging the compiler, as they are never called in that case.

2005-04-12  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclInterp.c:	Corrected bad syntax of Tcl_Panic() call.

	* generic/tclUtil.c (TclGetProcessGlobalValue):	More robust handling
	of bad TclInitProcessGlobalValueProc behavior; an immediate panic
	rather than a mysterious crash later.

	* generic/tclEncoding.c:	Several changes to the way the
	encodingFileMap cache is maintained. Previously, it was attempted to
	keep the file map filled and up to date with changes in the encoding
	search path. This contributed to slow startup times since it required
	an expensive "glob" operation to fill the cache. Now the validity of
	items in the cache are checked at the time they are used, so the cache
	is permitted to fall out of sync with the encoding search path. Only
	[encoding names] and Tcl_GetEncodingNames() now pay the full expense.
	[Bug 1177363]

2005-04-12  Kevin B. Kenny  <kennykb@acm.org>

	* compat/strstr.c: Added default definition of NULL to accommodate
	building on systems with badly broken headers. [Bug 1175161]

2005-04-11  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* tools/tclZIC.tcl: Rewrote to take advantage of more features of Tcl
	8.5 (on which it was dependent anyway). Also added a [package require]
	line to formalize the relationship.

2005-04-11  Kevin Kenny  <kennykb@users.sf.net>

	[kennykb-numerics-branch] Merged with HEAD. Updated to libtommath 0.35.

	* generic/tclBasic.c: Attempted to repeat changes that applied to
	tclExecute.c in Miguel Sofer's commit of 2005-04-01, together with
	(possibly) a few more uses of his new object creation macros. Also
	plugged a memory leak in TclObjInvoke. [Bug 1180368]

2005-04-10  Kevin Kenny  <kennykb@acm.org>

	* library/tzdata/America/Montevideo:
	* library/tzdata/Asia/Almaty:
	* library/tzdata/Asia/Aqtau:
	* library/tzdata/Asia/Aqtobe:
	* library/tzdata/Asia/Baku:
	* library/tzdata/Asia/Jerusalem:
	* library/tzdata/Asia/Oral:
	* library/tzdata/Asia/Qyzylorda:
	* library/tzdata/Indian/Chagos:
	* library/tzdata/Indian/Cocos:		Olson's tzdata2005h

2005-04-10  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c (TclObjInvoke):	Plug memory leak. [Bug 1180368]

2005-04-09  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: fix possible leak of expansion Tcl_Objs

2005-04-09  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/README: updated requirements for OS & developer tool versions
	and other small fixes/cleanup.

	* generic/tclListObj.c (Tcl_ListObjIndex): added missing NULL return
	when getting index from an empty list.

	* unix/tcl.m4 (Darwin): added -single_module linker flag to
	TCL_SHLIB_LD_EXTRAS and TK_SHLIB_LD_EXTRAS.
	* unix/configure: autoconf-2.59

2005-04-08  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclInt.h (TclGetEncodingFromObj):	 New function to
	* generic/tclEncoding.c (TclGetEncodingFromObj): retrieve a
	Tcl_Encoding value, as well as cache it in the internal rep of a new
	"encoding" Tcl_ObjType.
	* generic/tclCmdAH.c (Tcl_EncodingObjCmd):	Updated to call new
	function so that Tcl_Encoding's used by [encoding convert*] routines
	are not freed too quickly. [Bug 1077262]

2005-04-08  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileSwitchCmd): Rewritten to be able to
	handle the other form of [switch] and generate slightly simpler (but
	longer) code.

2005-04-06  Donal K. Fellows  <dkf@users.sf.net>

	* doc/upvar.n, doc/unset.n, doc/tell.n, doc/tclvars.n, doc/subst.n:
	* doc/seek.n, doc/scan.n, doc/regsub.n, doc/registry.n, doc/regexp.n:
	* doc/read.n, doc/puts.n, doc/pkgMkIndex.n, doc/open.n, doc/lreplace.n:
	* doc/lrange.n, doc/load.n, doc/llength.n, doc/linsert.n, doc/lindex.n:
	* doc/lappend.n, doc/info.n, doc/gets.n, doc/format.n, doc/flush.n:
	* doc/fileevent.n, doc/file.n, doc/fblocked.n, doc/close.n:
	* doc/array.n, doc/Utf.3, doc/TraceVar.3, doc/StrMatch.3, doc/RegExp.3:
	* doc/PrintDbl.3, doc/OpenTcp.3, doc/OpenFileChnl.3, doc/Object.3:
	* doc/Notifier.3, doc/LinkVar.3, doc/IntObj.3, doc/Interp.3:
	* doc/GetOpnFl.3, doc/GetIndex.3, doc/Eval.3, doc/CrtMathFnc.3:
	* doc/CrtFileHdlr.3, doc/CrtCommand.3, doc/CrtChannel.3:
	* doc/Backslash.3: Purge old .VS/.VE macro instances.

	* tools/man2html2.tcl (IPmacro): Rewrote to understand what .IP really
	is (.IP and .TP are really just two ways of doing the same thing).
	Change below made this relevant.
	* doc/re_syntax.n: Change some uses of .TP to .IP to work around bugs
	in various *roff implementations. Also reworded the atom descriptions
	slightly.

2005-04-05  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c (ExprSrandFunc):  Replaced incursions into the
	* generic/tclUtil.c (TclGetIntForIndex): intreps of numeric types with
	simpler calls of Tcl_GetIntFromObj and Tcl_GetLongFromObj, now that
	those routines are better behaved wrt shimmering. [Patch 1177219]

2005-04-05  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclInt.h:
	* generic/tclObj.c: Change in TclDecrRefCount and TclFreeObj, to speed
	up the freeing of simple Tcl_Obj [Patch 1174551]

2005-04-04  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: small opts in obj handling

2005-04-02  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclVar.c: converted a few function calls to macros.

2005-04-01  Miguel Sofer  <msofer@users.sf.net>

	* doc/ListObj.3:
	* generic/tclBasic.c:
	* generic/tclCmdIL.c:
	* generic/tclConfig.c:
	* generic/tclExecute.c:
	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclIntDecls.h:
	* generic/tclListObj.c:
	* generic/tclStubInit.c:
	* generic/tclVar.c: Changed the internal representation of lists to
	(a) reduce the malloc/free calls at list creation (from 2 to 1), (b)
	reduce the cost of handling empty lists (we now never create a list
	internal rep for them), (c) allow refcounting of the list internal rep.
	The latter permits insuring that the pointers returned by
	Tcl_ListObjGetElements remain valid even if the object shimmers away
	from its original list type. This is [Patch 1158008]

	* generic/tclExecute.c:
	* generic/tclInt.h:
	* generic/tclObj.c:
	* generic/tclStringObj.c:
	(1) defined new internal macros for creating and setting frequently
	used obj types (int,long, wideInt, double, string). Changed TEBC to use
	eg 'TclNewIntObj(objPtr, i)' to avoid the function call in 'objPtr =
	Tcl_NewIntObj(i)'
	(2) ExecEnv now stores two Tcl_Obj* pointing to the constants "0" and
	"1", for use by TEBC.
	(3) slight reduction in cost of INST_START_CMD

2005-03-31  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c (INST_JUMP_TRUE/FALSE): replaced "test and
	branch" with "compute index into table"

2005-03-30  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* doc/FileSystem.3: Defined loadHandle argument. [Bug 1172401]

2005-03-29  Jeff Hobbs	<jeffh@ActiveState.com>

	* win/tcl.m4, win/configure: do not require cygpath in macros to allow
	msys alone as an alternative.

2005-03-24  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompile.h:	Move the TclInterpReady() declaration from
	* generic/tclInt.h:	tclCompile.h to tclInt.h. Should have been done
	as part of the 1115904 bug fix on 2005-03-18.

	* generic/tclThreadTest.c:	Stop providing the phony package
	"Thread 1.0" when the [::testthread] command is defined. It's never
	used by anything, and conflicts with loading the real "Thread" package.

2005-03-18  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompCmds.c (TclCompileIncrCmd):	Corrected checks for
	immediate operand usage to permit leading space and sign characters.
	Restores more efficient bytecode for [incr x -1] that got lost in the
	CONST string reforms of Tcl 8.4. [Bug 1165671]

	* generic/tclBasic.c (Tcl_EvalEx):	Restored recursion limit
	* generic/tclParse.c (TclSubstTokens):	testing in nested command
	* tests/basic.test (basic-46.4):	substitutions within direct
	* tests/parse.test (parse-19.*):	script evaluation (Tcl_EvalEx)
	that got lost in the parser reforms of Tcl 8.1. Added tests for correct
	behavior. [Bug 1115904]

2005-03-15  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFileName.c:
	* win/tclWinFile.c:
	* tests/winFCMd.test: fix to 'file pathtype' and 'file norm' failures
	on reserved filenames like 'COM1:', etc.

2005-03-15  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* unix/tcl.m4:	  Updated the OpenBSD configuration and regenerated
	* unix/configure: the configure script.

2005-03-15  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch] Merged with HEAD.

	* generic/tclBasic.c (many):
	* generic/tclCompExpr.c (CompileMathFuncCall):
	* generic/tclCompile.h:
	* generic/tclExecute.c (many):
	* generic/tclParseExpr.c (ParsePrimaryExpr):
	* tests/compExpr-old.test:
	* tests/compExpr.test:
	* tests/compile.test:
	* tests/expr-old.test:
	* tests/expr.test:
	* tests/for.test:
	* tests/parseExpr.test: Initial implementation of TIP #232.

	* generic/tclObj.c (Tcl_DbNewBignumObj): Fixed typo that broke
	--enable-symbols=mem build
	* tests/binary.test (binary-40.3, binary-40.6): Corrected tests to
	allow NaN(7ffffffffffff).

2005-03-14  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: fixed INST_PUSH1's debugging code (wrong obj
	ref passed to TRACE_WITH_OBJ).

2005-03-14  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompile.c: fixed INST_RETURN's stack effect in
	tclInstructionTable (-1 instead of -2)

2005-03-10  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompCmds.c: removed debugging line

2005-03-10  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclTrace.c (TclCheckInterpTraces):	Corrected mistaken cast
	of ClientData to (TraceCommandInfo *) when not warranted. Thanks to
	Yuri Victorovich for the report. [Bug 1153871]
	* generic/tcl.h:	Moved flag values TCL_TRACE_ENTER_EXEC and
	* generic/tclInt.h:	TCL_TRACE_LEAVE_EXEC from public interface into
	private. Should be used only by internal workings of execution traces.

2005-03-09  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch] Merged from HEAD.

	* doc/PrintDbl.3:
	* doc/tclVars.n: Documented new semantics for tcl_precision.
	* generic/tclExecute.c (Tcl_ExecuteByteCode): Removed the check for
	division-by-zero on IEEE-754 machines.
	* generic/tclUtil.c (Tcl_PrintDouble): Corrected bug where numbers in
	the range [1e-4 .. 1.) were printed incorrectly.
	* tests/compExpr-old.test (compExpr-old-11.13): Revised test case for
	division by zero.
	* tests/expr-old.test (expr-34.11, expr-34.12): Revised test cases for
	overflow in pow() to deal with infinities.
	* tests/expr.test (expr-11.13, expr-29.1, expr-29.2): Revised test case
	for division by zero and for underflow on input conversions.
	* tests/parseExpr.test (parseExpr-16.11): Revised test case for
	overflow on input conversion.
	* tests/string.test (string-6.38 deleted): Removed test case for
	underflow on input conversion, which is no longer an error.
	* tests/util.test (util-10.*): Added test case for the bug in tclUtil.c

2005-03-08  Jeff Hobbs	<jeffh@ActiveState.com>

	* win/makefile.vc: clarify necessary defined vars that can come from
	MSVC or the Platform SDK.

2005-03-07  Donal K. Fellows  <dkf@users.sf.net>

	* doc/string.n: Minor typo. [Bug 1158247]

2005-03-07  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: new peephole optimisation for INST_PUSH1; fixed
	the peephole opt in INST_POP so that it is not used when
	TCL_COMPILE_DEBUG is defined.

2005-03-04  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch]

	* generic/tclCmdMZ.c: Changed [scan] to treat out-of-range floating
	point values as infinities and zeroes.
	* generic/tclExecute.c: Changed [expr] to be permissive about
	infinities, allowing them to propagate.
	* generic/tclGet.c: Changed Tcl_GetDouble to be permissive about
	over/underflow.
	* generic/tclObj.c: Changed SetDoubleFromAny to be permissive about
	over/underflow.
	* generic/tclParseExpr.c: Made [expr] permissive about input numbers
	out of range.

2005-03-03  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch]

	* generic/tclInt.h:
	* generic/tclStrToD.c (Tcl_DoubleDigits, TclFormatNaN):
	* generic/tclUtil.c (Tcl_PrintDouble): Changed the signature of
	TclDoubleDigits so that it accepts a pointer to the signum of the
	argument, and returns the signum via that pointer. Added very hacky
	code to handle IEEE signed zeroes in Tcl_DoubleDigits. (It can't be
	done other than as a hack until C9x; C89 simply doesn't deal with the
	concept of -0.0). Added output conversion of tagged NaN values.
	* generic/tclBinary.c (FormatNumber): Changed to allow [binary format]
	to handle NaN.
	* tests/binary.test (binary-60.1): Added a quick-n-dirty test to make
	sure that NaN's can be scanned and formatted.
	* generic/tclParseExpr.c (GetLexeme, ParseMaxDoubleLength): Modified so
	that tagged NaN (e.g., NaN(DEADBEEF)) can be recognized.

2005-03-02  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch] Merged with HEAD as of 2005-02-23.

	* generic/tclExecute.c: Broadened test for NaN to work on Windows.
	* generic/tclInt.h:
	* generic/tclStrToD.c (Tcl_DoubleDigits):
	* generic/tclUtil.c (Tcl_PrintDouble, TclPrecTraceProc): Added
	Tcl_DoubleDigits to format 'double' numbers with the minimum number of
	significant digits to yield correct rounding. Modified tcl_precision
	to accept 0 as a precision (meaning "minimum digits"), and made 0 the
	default. [TIP #132]
	* generic/tclObj.c: Made NaN's throw an error in Tcl_GetDoubleFromObj.
	* unix/Makefile.in:
	* win/Makefile.in:
	* win/makefile.vc: Added libtommath/bn_mp_init_set.c to the build.
	* libtommath/tommath.h (mp_iseven): Fixed a bug that caused zero to
	test 'odd'.
	* generic/tommath.h: Regenerated.
	* tests/binary.test:
	* tests/expr-old.test:
	* tests/expr.test:
	* tests/scan.test: Corrected a number of tests that depended on
	tcl_precision, and removed the {eformat} condition from tests that no
	longer require it.
	* tests/util.test: Corrected a number of tests that depended on
	tcl_precision, and removed the {eformat} condition from tests that no
	longer require it. Added a series of tests for correct rounding in
	Tcl_PrintDouble. [TIP #132].

2005-03-01  David N. Welton  <davidw@dedasys.com>

	* doc/CrtSlave.3: Changed to Tcl_Object to Tcl_Obj in the man page.

2005-02-24  Don Porter	<dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl:	Better use of [glob -types] to avoid
	* tests/tcltest.test:	failed attempts to [source] a directory, and
	similar matters. Thanks to "mpettigr". [Bug 1119798]

	* library/tcltest/pkgIndex.tcl: Bump to tcltest 2.2.8
	* unix/Makefile.in:
	* win/Makefile.in:

2005-02-23  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/CrtChannel.3 (THREADACTIONPROC): Formatting fix. [Bug 1149605]

2005-02-17  Jeff Hobbs	<jeffh@ActiveState.com>

	* win/tclWinFCmd.c (TraverseWinTree): use wcslen on wchar, not
	Tcl_UniCharLen.

2005-02-16  Miguel Sofer  <msofer@users.sf.net>

	* doc/variable.n: fix for [Bug 1124160], variables are detected by
	[info vars] but not by [info locals].

2005-02-11  Jeff Hobbs	<jeffh@ActiveState.com>

	* unix/Makefile.in: remove SHLIB_LD_FLAGS (only for AIX, inlined into
	* unix/tcl.m4:	    SHLIB_LD). Combine AIX-* and AIX-5 branches in
	* unix/configure:   SC_CONFIG_CFLAGS. Correct gcc builds for AIX-4+
	and HP-UX-11. autoconf-2.59 gen'd.

2005-02-11  Miguel Sofer  <msofer@users.sf.net>

	* tests/basic.test (basic-26.3): new test

2005-02-10  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c (Tcl_EvalObjEx):
	* tests/basic.test (basic-26.2): preserve the arguments passed to TEOV
	in the pure-list branch, in case the list shimmers away. Fix for [Bug
	1119369], reported by Peter MacDonald.

2005-02-10  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFileName.c: fix for test failures introduced on 2005-01-17
	[Bug 1119092]

2005-02-10  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/binary.n: Made the documentation of sign bit masking and [binary
	scan] consistent. [Bug 1117017]

2005-02-08  David N. Welton  <davidw@dedasys.com>

	* doc/CrtChannel.3: Typo: return->returns.

2005-02-06  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch]

	* generic/tclStrToD.c (TclStrToD, SafeLdExp): Added code to manage the
	FPU precision on gcc+x86. Enabled fast conversion of floats with small
	exponents now that precision is correct.
	* tests/expr.test: Corrected test for the smallest representible value
	to the right IEEE values.

2005-02-06  David N. Welton  <davidw@dedasys.com>

	* doc/Thread.3: One-word grammar fix.

2005-02-05  David N. Welton  <davidw@dedasys.com>

	* doc/Thread.3: Fixed sentence describing flags for Tcl_CreateThread.

	* doc/FileSystem.3: Cleaned up typo in Tcl_FSNewNativePath
	documentation.

	* generic/tclPathObj.c: Cleaned up typo in comment.

2005-02-03  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch]

	* generic/tclStrToD.c (TclStrToD, RefineResult, SafeLdExp): Added code
	to ensure that 'ldexp' is never called with a value that will underflow
	* tests/expr.test: Added tests for the smallest representible value,
	and rounding between it and zero. (The tests reflect current
	behaviour; plan is to change the specification of Tcl so that input
	conversion of doubles underflows silently.)

2005-02-02  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tclProc.c (TclInitCompiledLocals): Add check for type of the
	framePtr->procPtr->bodyPtr passed to TclInitCompiledLocals and panic if
	it is not the correct type. If the body of the proc is not of the
	compiled byte code type then the code will crash. This was discovered
	while tracking down a crash in Itcl, that crash is fixed by Itcl patch
	1115085.

2005-02-01  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch]  Merged with HEAD as of today.

	* generic/tclInt.decls: Changed numbers of new stubs to resolve a
	conflict.
	* generic/tclInt.h: Added new TclStrToD routine that replaces the
	native 'strtod' throughout Tcl.
	* generic/tclCmdMZ (Tcl_StringObjCmd):
	* generic/tclGet.c (Tcl_GetDouble):
	* generic/tclObj.c (SetBooleanFromAny, SetDoubleFromAny):
	* generic/tclParseExpr.c (GetLexeme):
	* generic/tclScan.c (Tcl_ScanObjCmd): Replaced all uses of the native
	'strtod' with a TclStrToD routine that performs correct rounding and
	handles denormals.
	* generic/tclStrToD.c: (new file)
	New scanning function for extracting 'double' from a string that rounds
	correctly, and handles denormals and infinities.
	* unix/Makefile.in:
	* win/Makefile.in:
	* win/makefile.vc:
	Added tclStrToD.c and the tommath routines that support it.

	These changes represent a partial implementation of TIP #132. Output
	conversion of floating point numbers, and proper handling of infinities
	within expressions, still need to be addressed.

2005-02-01  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c (TclCompEvalObj): Removed stray statement left
	behind in prior code reorganization.

2005-01-31  Don Porter	<dgp@users.sourceforge.net>

	* unix/configure:	autoconf-2.57

2005-01-30  Joe English  <jenglish@users.sourceforge.net>

	* unix/configure.in: Restored two double-evals that were removed in the
	DBGX purge; these are still needed on some platforms to account for
	TCL_TRIM_DOTS. [Bug 1112654]

	* unix/configure: NOT REGENERATED: only have autoconf 2.59 here, need
	to find someone with autoconf 2.57.

2005-01-28  Jeff Hobbs	<jeffh@ActiveState.com>

	* unix/configure, unix/tcl.m4: add solaris 64-bit gcc build support.
	[Bug 1021871]

2005-01-28  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tests/expr-old.test (expr-old-37.2): Added test for [Bug 1109484]

2005-01-27  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclBasic.c (Tcl_ExprBoolean, Tcl_ExprDouble)
	(Tcl_ExprLong): Fix to recognize Tcl_WideInt type. [Bug 1109484]

2005-01-26  Andreas Kupries  <andreask@activestate.com>

	TIP#218 IMPLEMENTATION

	* generic/tclDecls.h:	Regenerated from tcl.decls.
	* generic/tclStubInit.c:

	* doc/CrtChannel.3:	Documentation of extended API,
	* generic/tcl.decls:	extended testsuite, and
	* generic/tcl.h:	implementation. Removal of old
	* generic/tclIO.c:	driver-specific TclpCut/Splice
	* generic/tclInt.h:	functions. Replaced with generic
	* tests/io.test:	thread-action calls through the
	* unix/tclUnixChan.c:	new hooks. Update of all builtin
	* unix/tclUnixPipe.c:	channel drivers to version 4.
	* unix/tclUnixSock.c:	Windows drivers extended to
	* win/tclWinChan.c:	manage thread state in a thread
	* win/tclWinConsole.c:	action handler.
	* win/tclWinPipe.c:
	* win/tclWinSerial.c:
	* win/tclWinSock.c:

2005-01-25  Don Porter	<dgp@users.sourceforge.net>

	* library/auto.tcl:	Updated [auto_reset] to clear auto-loaded
	commands in namespaces other than :: and to clear auto-loaded commands
	that do not happen to be procs. [Bug 1101670]
	***POTENTIAL INCOMPATIBILITY***

2005-01-25  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tcl.m4 (Darwin): fixed bug with static build linking to dynamic
	library in /usr/lib etc instead of linking to static library earlier in
	search path. [Bug 956908] Removed obsolete references to Rhapsody.
	* unix/configure: autoconf-2.57

2005-01-21  Andreas Kupries  <andreask@activestate.com>

	* generic/tclStubInit.c: Regenerated the stubs support code from the
	* generic/tclDecls.h:	 modified tcl.decls (TIP #233, see below).

	* doc/GetTime.3:       Implemented TIP #233, i.e. the
	* generic/tcl.decls:   'Virtualization of Tcl's Sense of Time'.
	* generic/tcl.h:       Declared, implemented, and documented the
	* generic/tclInt.h:    specified new API functions. Moved the
	* unix/tclUnixEvent.c: native (OS) access to time information
	* unix/tclUnixNotfy.c: into standard handler functions. Inserted
	* unix/tclUnixTime.c:  hooks calling on the handlers where native
	* win/tclWinNotify.c:  access was done before, and where scaling
	* win/tclWinTime.c:    between domains (real/virtual) is required.

2005-01-21  Andreas Kupries  <andreask@activestate.com>

	* generic/tclThread.c: Typo police. Fixed some nits
	* generic/tclCmdAH.c:  in header comments of functions.
	* generic/tclBasic.c:  (Missing --).
	* generic/tclFileName.c:

2005-01-21  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/FileSystem.3: Add missing ARGUMENTS section definitions for
	arguments to Tcl_FSLink. [Bug 1106272]

2005-01-21  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch]

	* unix/Makefile.in: Updated Makefile to build libtommath on Unix as
	well as Windows. [Bug 1106865]

	* generic/tclTestObj.c (TestbignumobjCmd): Silenced a compiler warning
	about a mismatched 'const'.

2005-01-20  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch] Development checkpoint.

	* compat/strtoll.c:	Reverted to HEAD.
	* compat/strtoull.c:
	* doc/Ensemble.3:
	* generic/tclBasic.c:
	* generic/tclCmdIL.c:
	* generic/tclNamesp.c:
	* generic/tclPathObj.c:
	* generic/tclPort.h:
	* unix/configure:
	* unix/configure.in:
	* unix/tcl.m4:
	* win/configure:
	* win/configure.in:
	* win/rules.vc:
	* win/tcl.m4:

	* generic/tcl.h: Added declarations for bignum types, and for a
	'bignumValue' in the Tcl_Obj structure.
	* generic/tclInt.h: Added declarations of interface procedures for
	memory allocation in libtommath.

	* generic/tcl.decls: Added new interface to bignum objects.
	* generic/tclInt.decls: Added internal stubs for bignum routines used
	by the test code in tclTestObj.c.

	* generic/tclDecls/h: Regen.
	* generic/tclIntDecls.h:
	* generic/tclStubInit.h:

	* tools/fix_tommath_h.tcl: (New file) Script to edit
	libtommath/tommath.h and produce generic/tommath.h so that storage
	classes, allocation routines, and data types conform to Tcl's
	conventions.
	* generic/tommath.h: (New file) Generated by the above.

	* generic/tclTomMath.h: (New file) Additional declarations to be
	included in tommath.h when building Tcl.

	* generic/tclTomMathInterface.c: (New file) Small 'glue' routines
	adapting tommath's API to Tcl.

	* libtommath/bn_fast_s_mp_mul_digs.c:
	* libtommath/bn_mp_mul_d.c:
	* libtommath/bn_mp_read_radix.c:
	* libtommath/tommath.h: Applied suggested changes from Tom St Denis
	that correct an off-by-one error in single-digit multiplication
	(leading to a pointer smash if uncorrected) and change the string
	argument to 'mp_read_radix' from 'char*' to 'const char*'.

	* libtommath/bn_mp_radix_size.c: Local patch to ensure that sufficient
	memory is requested even if the number has a single digit.

	* libtommath/bn_mp_read_radix.c: Local patch to return MP_VAL if the
	input string contains an invalid character.

	* generic/tclObj.c: Added accessor functions for bignums.
	* generic/tclTestObj.c: Added a 'testbignumobj' command to exercise the
	accessor functions for bignums.

	* win/Makefile.in: Added rules for making libtommath.

2005-01-19  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	TIP#235 IMPLEMENTATION

	* doc/Ensemble.3: Documentation for the new public API.
	* generic/tclNamesp.c (Tcl_CreateEnsemble,...): Rename of
	* generic/tcl.decls:		existing API into TIPped form.

2005-01-19  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/tclWinChan.c (FileCloseProc): Invoke TclpCutFileChannel() to
	remove a FileInfo from the thread local list before deallocating it.
	This should have been done via an earlier call to Tcl_CutChannel, but I
	was running into a crash in the next call to Tcl_CutChannel during the
	I/O finalization stage.

2005-01-18  Kevin Kenny  <kennykb@acm.org>

	* library/tzdata/GMT+0:
	* library/tzdata/GMT-0:
	* library/tzdata/GMT0:
	* library/tzdata/Greenwich:
	* library/tzdata/Navajo:
	* library/tzdata/Universal:
	* library/tzdata/Zulu:
	* library/tzdata/America/Asuncion:
	* library/tzdata/America/Rosario:
	* library/tzdata/Asia/Jerusalem:
	* library/tzdata/Brazil/Acre:
	Routine update per Olson's tzdata2005c. Removed links to links
	(Greenwich in several aliases; Navajo; Acre). Updated Paraguayan DST
	rules and "best guess" at this year's Israeli rules.

2005-01-17  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFileName.c: fix for glob failure on Windows shares [Bug
	1100542].

	* doc/pkgMkIndex.n: added documentation that 'pkg_mkIndex -lazy' is not
	a good idea. [Bug 1101678]

2005-01-14  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tests/compile.test (compile-17.1): Document known issue with binding
	time of compiled command interpretations in [expr].

	* generic/tclIOUtil.c (TclFSFileAttrIndex): New helper function so that
	we don't need to hard-code attribute indexes. [Bug 1100671]

2005-01-13  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/string.n: Removed the term 'set' from the documentation of the
	[string trim] commands, as it caused confusion.

2005-01-12  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* unix/tcl.m4 (SC_PATH_{TCL,TK}CONFIG): Added code to detect the case
	when the --with-tcl/--with-tk arguments point to the config scripts
	themselves and not their directory. If this is the case, they now
	complain but keep working. [FRQ 951247]
	* unix/configure:	autoconf-2.57

2005-01-10  Joe English  <jenglish@users.sourceforge.net>

	* unix/Makefile.in, unix/configure.in, unix/tcl.m4,
	* unix/tclConfig.sh.in, unix/dltest/Makefile.in:
	Remove ${DBGX}, ${TCL_DBGX} from Tcl build system [Patch 1081595].
	* unix/configure: regenerated

2005-01-10  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* unix/tclUnixFCmd.c (TclUnixCopyFile): Convert u_int to unsigned to
	make clashes with types in standard C headers less of a problem. [Bug
	1098829]

2005-01-09  Joe English  <jenglish@users.sourceforge.net>

	* unix/tclUnixThrd.c, unix/tclUnixPort.h: Remove readdir_r() and
	related #ifdeffery (see [Bug 1095909]).
	* unix/tcl.m4, unix/tclConfig.h.in: Don't check for HAVE_READDIR_R.
	* unix/configure: Regenerated.

2005-01-06  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* library/http/http.tcl (http::mapReply): Significant performance
	enhancement by using [string map] instead of [regsub]/[subst], and
	update version requirement to Tcl8.4. [Bug 1020491]

2005-01-05  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/lsearch.n, doc/re_syntax.n: Convert to other form of emacs mode
	control comment to prevent problems with old versions of man. [Bug
	1085127]

2005-01-05  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* tests/winDde.test: Fixed broken test result.

2005-01-05  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclInt.h, generic/tclPort.h: Move the #include of tclConfig.h
	*first* before any reference to tcl.h so that the build configuration
	is loaded before the first reference to any system headers. Issue
	reported by Art Haas on tcl-core.

2005-01-04  Don Porter	<dgp@users.sourceforge.net>

	* tests/fCmd.test (fCmd-18.10):	Added notNetworkFilesystem constraint.
	[Bug 456665]

	******************************************************************
	*** CHANGELOG ENTRIES FOR 2004 IN "ChangeLog.2004"	       ***
	*** CHANGELOG ENTRIES FOR 2003 IN "ChangeLog.2003"	       ***
	*** CHANGELOG ENTRIES FOR 2002 IN "ChangeLog.2002"	       ***
	*** CHANGELOG ENTRIES FOR 2001 IN "ChangeLog.2001"	       ***
	*** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000"	       ***
	*** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" ***
	******************************************************************

Deleted ChangeLog.2007.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
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
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
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
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
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
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
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921

































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
2007-12-31  Donal K. Fellows  <dkf@users.sf.net>

	* doc/dict.n: Clarified meaning of dictionary values following
	discussion on comp.lang.tcl.

2007-12-26  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCmdIL.c: More [lsort] data handling streamlines. The
	function MergeSort is gone, essentially inlined into Tcl_LsortObjCmd.
	It is not a straight inlining, two loops over all lists elements where
	merged in the process: the linked list elements are now built and
	merged into the temporary sublists in the same pass.

2007-12-25  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCmdIL.c: More [lsort] data handling streamlines. Extra
	mem reqs of latest patches removed, restored to previous mem profile.
	Improved -unique handling, now eliminating repeated elems immediately
	instead of marking them to avoid reinsertion at the end.

2007-12-23  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclCompCmds.c (TclCompileRegexpCmd):	TCL_REG_NOSUB cannot
	* tests/regexp.test (regexp-22.2):		be used because it
	* tests/regexpComp.test:	[Bug 1857126]	disallows backrefs.

2007-12-21  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCmdIL.c: Speed patch for lsort. [Patch 1856994]

2007-12-21  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCmdIL.c (Tcl_LsortObjCmd, Tcl_LsearchObjCmd): Avoid
	calling SelectObjFromSublist when there are no sublists.

2007-12-21  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCmdIL.c (Tcl_LsortObjCmd): Preallocate a listObj of
	sufficient length for the sorted list instead of growing it. Second
	commit replaces calls to Tcl_ListObjAppenElement with direct access to
	the internal rep.

2007-12-19  Don Porter	<dgp@users.sourceforge.net>

	*** 8.5.0 TAGGED FOR RELEASE ***

	* changes:		Updated for 8.5.0 release.

2007-12-19  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclCompCmds.c (TclCompileSwitchCmd):	update switch -regexp
	* tests/switch.test-14.*:			compilation to pass
	the cflags to INST_REGEXP (changed on 12-07). Added tests for switch
	-regexp compilation (need more). [Bug 1854399]

2007-12-18  Don Porter	<dgp@users.sourceforge.net>

	* changes:		Updated for 8.5.0 release.

2007-12-18  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/regguts.h, generic/regc_color.c, generic/regc_nfa.c:
	Fixes for problems created when processing regular expressions that
	generate very large automata. An enormous number of thanks to Will
	Drewry <wad_at_google.com>, Tavis Ormandy <taviso_at_google.com>,
	and Tom Lane <tgl_at_sss.pgh.pa.us> from the Postgresql crowd for
	their help in tracking these problems down. [Bug 1810264]

2007-12-17  Don Porter	<dgp@users.sourceforge.net>

	* changes:		Updated for 8.5.0 release.

2007-12-17  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclAlloc.c:
	* generic/tclExecute.c:
	* generic/tclInt.h:
	* generic/tclThreadAlloc.c: Fix alignment for memory returned by
	TclStackAlloc; insure that all memory allocators align to 16-byte
	boundaries on 64 bit platforms [Bug 1851832, 1851524]

2007-12-14  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclIOUtil.c (FsAddMountsToGlobResult): fix the tail
	conversion of vfs mounts. [Bug 1602539]

	* win/README: updated notes

2007-12-14  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* tests/winFile.test: Fixed tests for win2k with long machine name

2007-12-14  Pat Thoyts <patthoyts@users.sourceforge.net>

	* win/nmakehlp.c:  Support compilation with MSVC9 for AMD64.
	* win/makefile.vc:

2007-12-13  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* doc/trace.n: Clarified documentation of enterstep and leavestep
	traces, including adding example. [Bug 614282, 1701540, 1755984]

2007-12-12  Don Porter	<dgp@users.sourceforge.net>

	* doc/IntObj.3:	Update docs for the Tcl_GetBignumAndClearObj() ->
	Tcl_TakeBignumFromObj() revision [TIP 298]. Added docs for the
	Tcl_InitBignumFromDouble() routine. [Bug 1446971]

	* changes:		Updated for 8.5.0 release.

2007-12-10  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclUtil.c (TclReToGlob): reduce escapes in conversion
	when not necessary

	* generic/tclInt.decls:	 move TclByteArrayMatch and TclReToGlob
	* generic/tclIntDecls.h: to tclInt.h from stubs.
	* generic/tclStubInit.c: Add flags var to TclByteArrayMatch for
	* generic/tclInt.h:	 future extensibility
	* generic/tcl.h:  define TCL_MATCH_EXACT doc for Tcl_StringCaseMatch.
	* doc/StrMatch.3: It is compatible with existing usage.
	* generic/tclExecute.c (INST_STR_MATCH): flag for TclByteArrayMatch
	* generic/tclUtil.c (TclByteArrayMatch, TclStringMatchObj):
	* generic/tclRegexp.c (Tcl_RegExpExecObj):
	* generic/tclCmdMZ.c (StringMatchCmd): Use TclStringMatchObj
	* tests/string.test (11.9.* 11.10.*): more tests

2007-12-10  Joe English	 <jenglish@users.sourceforge.net>

	* doc/string.n, doc/UniCharIsAlpha.3: Fix markup errors.
	* doc/CrtCommand.3, doc/CrtMathFnc.3, doc/FileSystem.3,
	* doc/GetStdChan.3, doc/OpenFileChnl.3, doc/SetChanErr.3,
	* doc/eval.n, doc/filename.n: Consistency: Move "KEYWORDS" section
	after "SEE ALSO".

2007-12-10  Daniel Steffen  <das@users.sourceforge.net>

	* tools/genStubs.tcl:		fix numerous issues handling 'macosx',
					'aqua' or 'x11' entries interleaved
					with 'unix' entries [Bug 1834288]; add
					genStubs::export command
					[Tk FR 1716117]; cleanup formatting.

	* generic/tcl.decls:		use new genstubs 'export' command to
	* generic/tclInt.decls:		mark exported symbols not in stubs
	* generic/tclTomMath.decls:	table [Tk FR 1716117]; cleanup
					formatting.

	* generic/tclDecls.h:		regen with new genStubs.tcl.
	* generic/tclIntDecls.h:	[Bug 1834288]
	* generic/tclIntPlatDecls.h:
	* generic/tclPlatDecls.h:
	* generic/tclStubInit.c:

2007-12-09  Jeff Hobbs	<jeffh@ActiveState.com>

	* tests/io.test, tests/chanio.test (io-73.1): Make sure to invalidate
	* generic/tclIO.c (SetChannelFromAny):	      internal rep only after
	validating channel rep. [Bug 1847044]

2007-12-08  Donal K. Fellows  <dkf@users.sf.net>

	* doc/expr.n, doc/mathop.n: Improved the documentation of the
	operators. [Bug 1823622]

	* generic/tclBasic.c (builtInCmds): Corrected list of hidden and
	* doc/interp.n (SAFE INTERPRETERS): exposed commands so that the
	documentation and reality now match. [Bug 1662436]

2007-12-07  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclExecute.c (TclExecuteByteCode INST_REGEXP):
	* generic/tclCompCmds.c (TclCompileRegexpCmd): Pass correct RE
	compile flags at compile time, and use TCL_REG_NOSUB.

	* generic/tclIOCmd.c (FinalizeIOCmdTSD, Tcl_PutsObjCmd): cache
	stdout channel object for [puts $str] calls.

2007-12-06  Don Porter	<dgp@users.sourceforge.net>

	* README:	Remove mention of dead comp.lang.tcl.announce
	newsgroup. [Bug 1846433]

	* unix/README:	Mention the stub library created by `make` and warn
	about the effect of embedded paths in the installed binaries.
	Thanks to Larry Virden. [Bug 1794084]

	* doc/AddErrInfo.3:	Documentation for the new routines in TIP 270.
	* doc/Interp.3:
	* doc/StringObj.3:

2007-12-06  Don Porter	<dgp@users.sourceforge.net>

	* doc/namespace.n:	Documentation for zero-argument form of
	[namespace import] (TIP 261) [Bug 1596416]

2007-12-06  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclInt.h: add TclGetChannelFromObj decl
	(TclMatchIsTrivial): simplify TclMatchIsTrivial to remove ] check.

2007-12-06  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>


	* generic/tclBasic.c (Tcl_CreateInterp): Simplify the setting up of
	* generic/tclIOCmd.c (TclInitChanCmd):	 the [chan] ensemble. This
	* library/init.tcl:			 gets rid of quite a bit of
	code and makes it possible to understand the whole with less effort.

	* generic/tclCompCmds.c (TclCompileEnsemble): Ensure that the right
	number of tokens are copied. [Bug 1845320]

	* generic/tclNamesp.c (TclMakeEnsemble): Added missing release of a
	DString. [Bug 1845397]

2007-12-05  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclIO.h:    Create Tcl_Obj for Tcl channels to reduce
	* generic/tclIO.c:    overhead in lookup by Tcl_GetChannel. New
	* generic/tclIOCmd.c: TclGetChannelFromObj for internal use.
	* generic/tclIO.c (WriteBytes, WriteChars): add opt check to avoid
	EOL translation when not linebuffered or using lf. [Bug 1845092]

2007-12-05  Miguel Sofer  <msofer@users.sf.net>

	* tests/stack.test: made the tests for stack overflow not care
	about which mechanism caused the error (interp's recursion limit
	or C-stack depth detector).

2007-12-05  Jeff Hobbs	<jeffh@ActiveState.com>

	* win/configure, win/tcl.m4 (LIBS_GUI): mingw needs -lole32
	-loleaut32 but not msvc for Tk's [send]. [Bug 1844749]

2007-12-05  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclCmdIL.c (Tcl_LsearchObjCmd): Prevent shimmering crash
	when -exact and -integer/-real are mixed. [Bug 1844789]

2007-12-03  Donal K. Fellows  <dkf@users.sf.net>

	* unix/tclUnixChan.c (CreateSocketAddress): Add extra #ifdef-fery to
	make code compile on BSD 5. [Bug 1618235, again]

2007-12-03  Don Porter	<dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl:	Bump tcltest to version 2.3.0 so that
	* library/tcltest/pkgIndex.tcl: we release a stable tcltest with a
	* unix/Makefile.in:	stable Tcl.
	* win/Makefile.in:

2007-12-03  Jeff Hobbs	<jeffh@ActiveState.com>

	* win/configure, win/tcl.m4 (LIBS_GUI): remove ole32.lib oleaut32.lib

2007-12-03  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclCompCmds.c (TclCompileSwitchCmd): Adjusted the [switch]
	* generic/tclCmdMZ.c (Tcl_SwitchObjCmd):       command so that when
	passed two arguments, no check for options are performed. This is OK
	since in the two-arg case, detecting an option would definitely lead
	to a syntax error. [Patch 1836519]

2007-11-29  Jeff Hobbs	<jeffh@ActiveState.com>

	* win/makefile.vc: add ws2_32.lib to baselibs
	* win/configure, win/tcl.m4: add ws2_32.lib / -lws2_32 to build.
	* win/tclWinSock.c: remove dyn loading of winsock, assume that it is
	always available now.

2007-11-29  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclWinSock.c (InitializeHostName):	Correct error in
	buffer length tracking. After gethostname() writes into a buffer,
	convert only the written string to internal encoding, not the whole
	buffer.

2007-11-28  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclConfig.c:	Corrected failure of the [::foo::pkgconfig]
	command to clean up registered configuration data when the query
	command is deleted from the interp. [Bug 983501]

	* generic/tclNamesp.c (Tcl_SetEnsembleMappingDict):	Added checks
	that the dict value passed in is in the format required to make the
	internals of ensembles work. [Bug 1436096]

	* generic/tclIO.c:	Simplify test and improve accuracy of error
	message in latest changes.

2007-11-28  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* generic/tclIO.c: -eofchar must support no eofchar.

2007-11-27  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c: remove unneeded call in Tcl_CreateInterp, add
	comments.

2007-11-27  Don Porter	<dgp@users.sourceforge.net>

	* win/tclWinSock.c:	Add mising encoding conversion of the [info
	hostname] value from the system encoding to Tcl's internal encoding.

	* doc/chan.n:		"Fix" the limitation on channel -eofchar
	* doc/fconfigure.n:	values to single byte characters by
	* generic/tclIO.c:	documenting it and making it fail loudly.
	* tests/chan.test:	Thanks to Stuart Cassoff for contributing the
				fix. [Bug 800753]

2007-11-26  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:
	* generic/tclInt.h:
	* unix/tclUnixInit.c:
	* unix/tclUnixThrd.c: Fix stack checking via workaround for bug in
	glibc's pthread_attr_get_np, patch from [Bug 1815573]. Many thanks to
	Sergei Golovan (aka Teo) for detecting the bug and helping diagnose
	and develop the fix.

2007-11-24  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileDictAppendCmd): Fix bug in [dict
	append] compiler which caused strange stack corruption. [Bug 1837392]

2007-11-23  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIORChan.c: Fixed a problem with reflected channels. 'chan
	postevent' is defined to work only from within the interpreter
	containing the handler command. Sensible, we want only handler
	commands to use it. It identifies the channel by handle. The channel
	moves to a different interpreter or thread. The interpreter containing
	the handler command doesn't know the channel any longer. 'chan
	postevent' fails, not finding the channel any longer. Uhm.

	Fixed by creating a second per-interpreter channel table, just for
	reflected channels, where each interpreter remembers for which
	reflected channels it has the handler command. This info does not move
	with the channel itself. The table is updated by 'chan create', and
	used by 'chan postevent'.

	* tests/ioCmd.test: Updated the testsuite.

2007-11-23  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclVar.c (Tcl_ArrayObjCmd): handle the right data for
	* tests/var.test (var-14.2):	      [array names $var -glob $ptn]

2007-11-23  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclCmdMZ.c (String*Cmd, TclInitStringCmd): Rebuilt [string]
	* generic/tclCompCmds.c (TclCompileString*Cmd): as an ensemble.

2007-11-22  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclDictObj.c (Dict*Cmd,TclInitDictCmd): Rebuilt the [dict]
	* generic/tclCompCmds.c (TclCompileDict*Cmd): command as an ensemble.

2007-11-22  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclCmdMZ.c (Tcl_StringObjCmd): Rewrote the [string] and
	* generic/tclDictObj.c (Tcl_DictObjCmd): [dict] implementations to be
	ready for conversion to ensembles.

	* tests/string.test (string-12.22): Flag shimmering bug found in
	[string range].

2007-11-21  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileEnsemble): Rewrote the ensemble
	compiler to remove many of the limitations. Can now compile scripts
	that use unique prefixes of subcommands, and which have mappings of a
	command to multiple words (provided the first is a compilable command
	of course).

2007-11-21  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclNamesp.c (TclMakeEnsemble): Factor out the code to set up
	a core ensemble from a table of information about subcommands, ready
	for reuse within the core.

	* generic/various: Start to return more useful Error codes, currently
	mainly on assorted lookup failures.

2007-11-20  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclDictObj.c: Changed the underlying implementation of the
	hash table used in dictionaries to additionally keep all entries in
	the hash table in a linked list, which is only ever added to at the
	end. This makes iteration over all entries in the dictionary in
	key insertion order a trivial operation, and so cleans up a great deal
	of complexity relating to dictionary representation and stability of
	iteration order.

	***POTENTIAL INCOMPATIBILITY***
	For any code that depended on the (strange) old iteration order.

	* generic/tclConfig.c (QueryConfigObjCmd): Correct usage of
	Tcl_WrongNumArgs.

2007-11-19  Don Porter	<dgp@users.sourceforge.net>

	*** 8.5b3 TAGGED FOR RELEASE ***

	* README:		Bump version number to 8.5b3.
	* generic/tcl.h:
	* library/init.tcl:
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/configure.in:

	* unix/configure:	autoconf (2.59)
	* win/configure:

	* changes:		Updated for 8.5b3 release.

2007-11-19  Kevin Kenny	 <kennykb@users.sourceforge.net>

	* library/tzdata/Africa/Cairo:
	* library/tzdata/America/Campo_Grande:
	* library/tzdata/America/Caracas:
	* library/tzdata/America/Cuiaba:
	* library/tzdata/America/Havana:
	* library/tzdata/America/Sao_Paulo:
	* library/tzdata/Asia/Damascus:
	* library/tzdata/Asia/Gaza:
	* library/tzdata/Asia/Tehran:  Olson's tzdata2007i imported.

2007-11-18  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclExecute.c (TclExecuteByteCode:INST_EXIST_*): Fix read
	traces not firing on non-existent array elements. [Bug 1833522]

2007-11-16  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclCmdIL.c (TclInitInfoCmd): Rename the implementation
	commands for [info] to be something more "expected".

	* generic/tclCompCmds.c (TclCompileInfoExistsCmd): Compiler for the
	[info exists] subcommand.
	(TclCompileEnsemble): Cleaned up version of ensemble compiler that was
	in TclCompileInfoCmd, but which is now much more generally applicable.

	* generic/tclInt.h (ENSEMBLE_COMPILE): Added flag to allow for cleaner
	turning on and off of ensemble bytecode compilation.

	* generic/tclCompile.c (TclCompileScript): Add the cmdPtr to the list
	of arguments passed to command compilers.

2007-11-15  Don Porter	<dgp@users.sourceforge.net>

	* generic/regc_nfa.c:	Fixed infinite loop in the regexp compiler.
	[Bug 1810038]

	* generic/regc_nfa.c:	Corrected looping logic in fixempties() to
	avoid wasting time walking a list of dead states. [Bug 1832612]

2007-11-15  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclNamesp.c (NamespaceEnsembleCmd): Must pass a non-NULL
	interp to Tcl_SetEnsemble* functions.

	* doc/re_syntax.n: Try to make this easier to read. It's still a very
	difficult manual page!

	* unix/tcl.m4 (SC_CONFIG_CFLAGS): Allow people to turn off the -rpath
	option to their linker if they so desire. This is a configuration only
	recommended for (some) vendors. Relates to [Patch 1231022].

2007-11-15  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* win/tclWin32Dll.c: Prefer UINT_PTR to DWORD_PTR when casting
	pointers to integer types for greater portability. [Bug 1831253]

2007-11-15  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Tcl.xcodeproj/project.pbxproj: add new chanio.test.
	* macosx/Tcl.xcode/project.pbxproj:

2007-11-14  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclCompile.c (TclCompileScript): Ensure that we get our
	count in our INST_START_CMD calls right, even when there's a failure
	to compile a command directly.

	* generic/tclNamesp.c (Tcl_SetEnsembleSubcommandList)
	(Tcl_SetEnsembleMappingDict):		Special code to make sure that
	* generic/tclCmdIL.c (TclInitInfoCmd):	[info exists] is compiled
	right while not allowing changes to the ensemble to cause havok.

	* generic/tclCompCmds.c (TclCompileInfoCmd): Simple compiler for the
	[info] command that only handles [info exists].

	* generic/tclExecute.c (TclExecuteByteCode:INST_EXIST_*): New
	instructions to allow the testing of whether a variable exists.

2007-11-14  Andreas Kupries  <andreask@activestate.com>

	* tests/chanio.test: New file. This is essentially a duplicate of
	'io.test', with all channel commands converted to their 'chan xxx'
	notation.
	* tests/io.test: Fixed typo in test description.

2007-11-14  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/regc*.c: Eliminate multi-char collating element code
	completely. Simplifies the code quite a bit. If people still want the
	full code, it will remain on the 8.4 branch. [Bug 1831425]

2007-11-13  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclCompCmds.c (TclCompileRegexpCmd): clean up comments, only
	free dstring on OK from TclReToGlob.
	(TclCompileSwitchCmd): simplify TclReToGlob usage.

2007-11-14  Donal K. Fellows  <dkf@users.sf.net>

	* generic/regc*.c: #ifdef/comment out the code that deals with
	multi-character collating elements, which have never been supported.
	Cuts the memory consumption of the RE compiler. [Bug 1831425]

2007-11-13  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileSwitchCmd, TclCompileRegexpCmd):
	Extend [switch] compiler to handle regular expressions as long as
	things are not too complex. Fix [regexp] compiler so that non-trivial
	literal regexps get fed to INST_REGEXP.

	* doc/mathop.n: Clarify definitions of some operations.

2007-11-13  Miguel Sofer  <msofer@users.sf.net>

	* unix/tclUnixInit.c: the TCL_NO_STACK_CHECK was being incorrectly
	undefined here; this should be set (or not) in the compile options, it
	is used elsewhere and needs to be consistent.

2007-11-13  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* unix/tcl.m4:		Added autoconf goo to detect and make use of
	* unix/configure.in:	getaddrinfo and friends.
	* unix/configure:	(regenerated)

2007-11-13  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* unix/tclUnixCompat.c (TclpGetHostByName): The six-argument form of
	getaddressbyname_r() uses the fifth argument to indicate whether the
	lookup succeeded or not on at least one platform. [Bug 1618235]

2007-11-13  Don Porter	<dgp@users.sourceforge.net>

	* generic/regcomp.c:	Convert optst() from expensive no-op to a
	cheap no-op.

2007-11-13  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* unix/tclUnixChan.c (CreateSocketAddress): Rewrote to use the
	thread-safe version of gethostbyname() by forward-porting the code
	used in 8.4, and added rudimentary support for getaddrinfo() (not
	enabled by default, as no autoconf-ery written). Part of fix for [Bug
	1618235].

2007-11-12  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclGet.c (Tcl_Get, Tcl_GetInt): revert use of TclGet* macros
	due to compiler warning. These cases won't save time either.

	* generic/tclUtil.c (TclReToGlob): add more comments, set interp
	result if specified on error.

2007-11-12  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:		New macro TclResetResult, new iPtr
	* generic/tclExecute.c:		flag bit INTERP_RESULT_UNCLEAN:
	* generic/tclInt.h:		shortcut for Tcl_ResetResult for the
	* generic/tclProc.c:		"normal" case: TCL_OK, no return
	* generic/tclResult.c:		options, no errorCode nor errorInfo,
	* generic/tclStubLib.c:		return at normal level. [Patch
	* generic/tclUtil.c:		1830184]

	THIS PATCH WAS REVERTED: initial (mis)measurements overstated the
	perfomance wins, which turn out to be tiny. Not worth the
	complication.

2007-11-11  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclCompCmds.c, generic/tclCompile.c, generic/tclCompile.h:
	* generic/tclExecute.c, generic/tclInt.decls, generic/tclIntDecls.h:
	* generic/tclRegexp.c, generic/tclRegexp.h: Add INST_REGEXP and fully
	* generic/tclStubInit.c, generic/tclUtil.c: compiled [regexp] for the
	* tests/regexpComp.test:     [Bug 1830166]  simple cases. Also added
	TclReToGlob function to convert RE to glob patterns and use these in
	the possible cases.

2007-11-11  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclResult.c (ResetObjResult): clarify the logic.

	* generic/tclBasic.c:		Increased usage of macros to detect
	* generic/tclBinary.c:		and take advantage of objTypes. Added
	* generic/tclClock.c:		macros TclGet(Int|Long)FromObj,
	* generic/tclCmdAH.c:		TclGetIntForIndexM & TclListObjLength,
	* generic/tclCmdIL.c:		modified TclListObjGetElements.
	* generic/tclCmdMZ.c:
	* generic/tclCompCmds.c:	The TclGetInt* macros are only a
	* generic/tclCompExpr.c:	shortcut on platforms where 'long' is
	* generic/tclCompile.c:		'int'; it may be worthwhile to extend
	* generic/tclDictObj.c:		their functionality to other cases.
	* generic/tclExecute.c:
	* generic/tclGet.c:		As this patch touches many files it
	* generic/tclIO.c:		has been recorded as [Patch 1830038]
	* generic/tclIOCmd.c:		in order to facilitate reviewing.
	* generic/tclIOGT.c:
	* generic/tclIndexObj.c:
	* generic/tclInt.h:
	* generic/tclInterp.c:
	* generic/tclListObj.c:
	* generic/tclLiteral.c:
	* generic/tclNamesp.c:
	* generic/tclObj.c:
	* generic/tclParse.c:
	* generic/tclProc.c:
	* generic/tclRegexp.c:
	* generic/tclResult.c:
	* generic/tclScan.c:
	* generic/tclStringObj.c:
	* generic/tclUtil.c:
	* generic/tclVar.c:

2007-11-11  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tclUnixTime.c (TclpWideClicksToNanoseconds): Fix issues with
	* generic/tclInt.h:				    int64_t overflow.

	* generic/tclBasic.c:	Fix stack check failure case if stack grows up
	* unix/tclUnixInit.c:	Simplify non-crosscompiled case.

	* unix/configure:	autoconf-2.59
	* unix/tclConfig.h.in:	autoheader-2.59

2007-11-10  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: Fast path for INST_LIST_INDEX when the index
	is not a list.

	* generic/tclBasic.c:
	* unix/configure.in:
	* unix/tclUnixInit.c: Detect stack grwoth direction at compile time,
	only fall to runtime detection when crosscompiling.

	* unix/configure: autoconf 2.61

	* generic/tclBasic.c:
	* generic/tclInt.h:
	* tests/interp.test:
	* unix/tclUnixInit.c:
	* win/tclWin32Dll.c: Restore simpler behaviour for stack checking, not
	adaptive to stack size changes after a thread is launched. Consensus
	is that "nobody does that", and so it is not worth the cost. Improved
	failure comments (mistachkin).

2007-11-10  Kevin Kenny	 <kennykb@acm.org>

	* win/tclWin32Dll.c: Rewrote the Windows stack checking algorithm to
	use information from VirtualQuery to determine the bound of the stack.
	This change fixes a bug where the guard page of the stack was never
	restored after an overflow. It also eliminates a nasty piece of
	assembly code for structured exception handling on mingw. It
	introduces an assumption that the stack is a single memory arena
	returned from VirtualAlloc, but the code in MSVCRT makes the same
	assumption, so it should be fairly safe.

2007-11-10  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:
	* generic/tclInt.h:
	* unix/tclUnixInit.c:
	* unix/tclUnixPort.h:
	* win/tclWin32Dll.c: Modify the stack checking algorithm to recheck in
	case of failure. The working assumptions are now that (a) a thread's
	stack is never moved, and (b) a thread's stack can grow but not
	shrink. Port to windows - could be more efficient, but is already
	cheaper than it was.

2007-11-09  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclResult.c (ResetObjResult): new shortcut.

	* generic/tclAsync.c:
	* generic/tclBasic.c:
	* generic/tclExecute.c:
	* generic/tclInt.h:
	* generic/tclUnixInit.c:
	* generic/tclUnixPort.h: New fields in interp (ekeko!) to cache TSD
	data that is accessed at each command invocation, access macros to
	replace Tcl_AsyncReady and TclpCheckStackSpace by much faster variants
	[Patch 1829248]

2007-11-09  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclInt.decls, generic/tclIntDecls.h: Use unsigned char for
	* generic/tclExecute.c, generic/tclUtil.c:     TclByteArrayMatch and
	don't allow a nocase option. [Bug 1828296]
	For INST_STR_MATCH, ignore pattern type for TclByteArrayMatch case.

	* generic/tclBinary.c (Tcl_GetByteArrayFromObj): check type before
	func jump (perf).

2007-11-07  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclStubInit.c:		     Added TclByteArrayMatch
	* generic/tclInt.decls:			     for efficient glob
	* generic/tclIntDecls.h:		     matching of ByteArray
	* generic/tclUtil.c (TclByteArrayMatch):     Tcl_Objs, used in
	* generic/tclExecute.c (TclExecuteByteCode): INST_STR_MATCH. [Bug
						     1827996]

	* generic/tclIO.c (TclGetsObjBinary): Add an efficient binary path for
					      [gets].
	(DoWriteChars): Special case for 1-byte channel write.

2007-11-06  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclEncoding.c: Version of the embedded iso8859-1 encoding
	handler that is faster (functions to do the encoding know exactly what
	they're doing instead of pulling it from a table, though the table
	itself has to be retained for use by shift encodings that depend on
	iso8859-1). [Patch 1826906], committing for dkf.

2007-11-05  Andreas Kupries  <andreask@activestate.com>

	* generic/tclConfig.c (Tcl_RegisterConfig): Modified to not extend the
	config database if the encoding provided by the user is not found
	(venc == NULL). Scripts expecting the data will error out, however we
	neither crash nor provide bogus information. See [Bug 983509] for more
	discussion.

	* unix/tclUnixChan.c (TtyGetOptionProc): Accepted [Patch 1823576]
	provided by Stuart Cassof <stwo@users.sourceforge.net>. The patch adds
	the necessary utf/external conversions to the handling of the
	arguments of option -xchar which will allow the use of \0 and similar
	characters.

2007-11-03  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclTest.c (TestSetCmd2):
	* generic/tclVar.c (TclObjLookupVarEx):
	* tests/set.test (set-5.1): Fix error branch when array name looks
	like array element (code not normally exercised).

2007-11-01  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tools/tcltk-man2html.tcl (output-directive): Convert .DS/.DE pairs
	into tables since that is now all that they are used for.

	* doc/RegExp.3: Clarified documentation of RE flags. [Bug 1167840]

	* doc/refchan.n: Adjust internal name to be consistent with the file
	name for reduced user confusion. After comment by Dan Steffen.

	* generic/tclCmdMZ.c (Tcl_StringObjCmd, UniCharIsAscii): Remember, the
	NUL character is in ASCII too. [Bug 1808258]

	* doc/file.n: Clarified use of [file normalize]. [Bug 1185154]

2007-10-30  Don Porter	<dgp@users.sourceforge.net>

	* generic/tcl.h:	Bump version number to 8.5b2.1 to distinguish
	* library/init.tcl:	CVS development snapshots from the 8.5b2
	* unix/configure.in:	release.
	* unix/tcl.spec:
	* win/configure.in:

	* unix/configure:	autoconf (2.59)
	* win/configure:

2007-10-30  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/expr.n, doc/mathfunc.n: Improve documentation to try to make
	clearer what is going on.

	* doc/interp.n: Shorten the basic descriptive text for some interp
	subcommands so Solaris nroff doesn't truncate them. [Bug 1822268]

2007-10-30  Donal K. Fellows  <dkf@users.sf.net>

	* tools/tcltk-man2html.tcl (output-widget-options): Enhance the HTML
	generator so that it can produce multi-line option descriptions.

2007-10-28  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclUtil.c (Tcl_ConcatObj): optimise for some of the
	concatenees being empty objs. [Bug 1447328]

2007-10-28  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclEncoding.c (TclInitEncodingSubsystem): Hard code the
	iso8859-1 encoding, as it's needed for more than just text (especially
	binary encodings...) Note that other encodings rely on the encoding
	being a table encoding (!) so we can't use more efficient encoding
	mapping functions.

2007-10-27  Donal K. Fellows  <dkf@users.sf.net>

	* generic/regc_lex.c (lexescape): Close off one of the problems
	mentioned in [Bug 1810264].

2007-10-27  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclNamesp.c (Tcl_FindCommand): insure that FQ command names
	are searched from the global namespace, ie, bypassing resolvers of the
	current namespace. [Bug 1114355]

	* doc/apply.n: fixed example [Bug 1811791]
	* doc/namespace.n: improved example [Bug 1788984]
	* doc/AddErrInfo.3: typo [Bug 1715087]
	* doc/CrtMathFnc.3: fixed Tcl_ListMathFuncs entry [Bug 1672219]

	* generic/tclCompile.h:
	* generic/tclInt.h: moved declaration of TclSetCmdNameObj from
	tclCompile.h to tclInt.h, reverting linker [Bug 1821159] caused by
	commit of 2007-10-11 (both I and gcc missed one dep).

	* generic/tclVar.c: try to preserve Tcl_Objs when doing variable
	lookups by name, partially addressing [Bug 1793601].

2007-10-27  Donal K. Fellows  <dkf@users.sf.net>

	* tools/tcltk-man2html.tcl (make-man-pages, htmlize-text)
	(process-text): Make the man->HTML scraper work better.

2007-10-26  Don Porter	<dgp@users.sourceforge.net>

	*** 8.5b2 TAGGED FOR RELEASE ***

	* changes:		Updated for 8.5b2 release.

	* doc/*.1:		Revert doc changes that broke
	* doc/*.3:		`make html` so we can get the release
	* doc/*.n:		out the door.

	* README:		Bump version number to 8.5b2.
	* generic/tcl.h:
	* library/init.tcl:
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/configure.in:

	* unix/configure:	autoconf (2.59)
	* win/configure:

2007-10-26  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tools/man2help2.tcl, tools/man2tcl.c: Made some of the tooling code
	to do man->other formats work better with current manpage set. Long
	way still to go.

2007-10-25  Zoran Vasiljevic <vasiljevic@users.sourceforge.net>

	* generic/tclThread.c: Added TclpMasterLock/Unlock arround calls to
	ForgetSyncObject in Tcl_MutexFinalize and Tcl_ConditionFinalize to
	prevent from garbling the internal lists that track sync objects. [Bug
	1726873]

2007-10-24  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tools/man2html2.tcl (macro): Added support for converting the new
	macros into HTML.

	* doc/man.macros (QW,PQ,QR,MT): New macros that hide the ugly mess
	needed to get proper GOOBE quoting in the manual pages.
	* doc/*.n, doc/*.3, doc/*.1: Lots of changes to take advantage of the
	new macros.

2007-10-20  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompile.c:	  Fix comments.
	* generic/tclExecute.c:

2007-10-18  David Gravereaux <davygrvy@pobox.com>

	* tools/mkdepend.tcl: sort the dep list for a more humanly readable
	output.

2007-10-18  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclResult.c (TclMergeReturnOptions):	Make sure any -code
	values get pulled out of the dictionary, even if they are integer
	valued.

	* generic/tclCompCmds.c (TclCompileReturnCmd):	Added code to more
	optimally compile [return -level 0 $x] to "push $x". [RFE 1794073]

	* compat/tmpnam.c (removed):	The routine tmpnam() is no longer
	* unix/Makefile.in:	called by Tcl source code. Remove autogoo the
	* unix/configure.in:	supplied a replacement version on systems
	* win/tcl.dsp:		where the routine was not available. [RFE
	1811848]

	* unix/configure:	autoconf-2.59

	* generic/tcl.h:	Remove TCL_LL_MODIFIER_SIZE. [RFE 1811837]

2007-10-17  David Gravereaux <davygrvy@pobox.com>

	* tools/mkdepend.tcl:	Improved defense from malformed object list
	infile.

2007-10-17  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* tools/man2html2.tcl: Convert .DS/.DE into HTML tables, not
	preformatted text.

2007-10-17  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclCompExpr.c: Moved a misplaced declaration that blocked
				 compilation on VC++.
	* generic/tclExecute.c: Silenced several VC++ compiler warnings about
				converting 'long' to 'unsigned short'.

2007-10-16  David Gravereaux <davygrvy@pobox.com>

	* win/makefile.vc: removed old dependency cruft that is no longer
	needed.

2007-10-15  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclIOCmd.c:	Revise [open] so that it interprets leading
	zero strings passed as the "permissions" argument as octal numbers,
	even if Tcl itself no longer parses integers in that way.

	* unix/tclUnixFCmd.c:	Revise the "-permissions" [file attribute] so
	that it interprets leading zero strings as octal numbers, even if Tcl
	itself no longer parses integers in that way.

	* generic/tclCompExpr.c:	Corrections to code that produces
	* generic/tclUtil.c:		extended "bad octal" error messages.

	* tests/cmdAH.test:	Test revisions so that tests pass whether or
	* tests/cmdIL.test:	not Tcl parses leading zero strings as octal.
	* tests/compExpr-old.test:
	* tests/compExpr.test:
	* tests/compile.test:
	* tests/expr-old.test:
	* tests/expr.test:
	* tests/incr.test:
	* tests/io.test:
	* tests/lindex.test:
	* tests/link.test:
	* tests/mathop.test:
	* tests/parseExpr.test:
	* tests/set.test:
	* tests/string.test:
	* tests/stringComp.test:

2007-10-15  David Gravereaux <davygrvy@pobox.com>

	* tools/mkdepend.tcl:	Produces usable output. Include path problem
	* win/makefile.vc:	fixed. Never fight city hall when it comes to
	levels of quoting issues.

2007-10-15  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclParse.c (Tcl_ParseBraces): fix for possible read after
	the end of buffer. [Bug 1813528] (Joe Mistachkin)

2007-10-14  David Gravereaux <davygrvy@pobox.com>

	* tools/mkdepend.tcl (new):  Initial stab at generating automatic
	* win/makefile.vc:	     dependencies.

2007-10-12  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* win/makefile.vc:  Mine all version information from headers.
	* win/rules.vc:	    Sync tcl and tk and bring extension versions
	* win/nmakehlp.c:   closer together. Try and avoid using tclsh to do
			    substitutions as we may cross compile.
	* win/coffbase.txt: Added offsets for snack dlls.

2007-10-11  David Gravereaux <davygrvy@pobox.com>

	* win/makefile.vc:  Fixed my bad spelling mistakes from years back.
	Dedependency, duh!  Rather funny.

2007-10-11  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCmdMZ.c:	Correct [string is (wide)integer] failure
	* tests/string.test:	to report correct failindex values for
	non-decimal integer strings. [Bug 1805887]

	* compat/strtoll.c (removed):	The routines strtoll() and strtoull()
	* compat/strtoull.c (removed):	are no longer called by the Tcl source
	* generic/tcl.h:	code. (Their functionality has been replaced
	* unix/Makefile.in:	by TclParseNumber().) Remove outdated comments
	* unix/configure.in:	and mountains of configury autogoo that
	* unix/tclUnixPort.h:	allegedly support the mythical systems where
	* win/Makefile.in:	these routines might not have been available.
	* win/makefile.bc:
	* win/makefile.vc:
	* win/tclWinPort.h:

	* unix/configure:	autoconf-2.59

2007-10-11  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclObj.c: remove superfluous #include of tclCompile.h

2007-10-08  George Peter Staplin <georgeps@xmission.com>

	* doc/Hash.3: Correct the valid usage of the flags member for the
	Tcl_HashKeyType. It should be 0 or more of the flags mentioned.

2007-10-02  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tcl.h (Tcl_DecrRefCount): Update change from 2006-05-29 to
	make macro more warning-robust in unbraced if code.

2007-10-02  Don Porter	<dgp@users.sourceforge.net>

	[core-stabilizer-branch]

	* README:		Bump version number to 8.5.0
	* generic/tcl.h:
	* library/init.tcl:
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/configure.in:

	* unix/configure:	autoconf (2.59)
	* win/configure:

2007-10-02  Andreas Kupries  <andreask@activestate.com>

	* library/tclIndex: Added 'tcl::tm::path' to the tclIndex. This fixes
	[Bug 1806422] reported by Don Porter.

2007-09-25  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclProc.c (Tcl_DisassembleObjCmd): Define a command,
	::tcl::unsupported::disassemble, which can disassemble procedures,
	lambdas and general scripts.
	* generic/tclCompile.c (TclDisassembleByteCodeObj): Split apart the
	code to print disassemblies of bytecode so that there is reusable code
	that spits it out in a Tcl_Obj and then that code is used when doing
	tracing.

2007-09-20  Don Porter	<dgp@users.sourceforge.net>

	*** 8.5b1 TAGGED FOR RELEASE ***

	* changes: updates for 8.5b1 release.

2007-09-19  Don Porter	<dgp@users.sourceforge.net>

	* README:		Bump version number to 8.5b1
	* generic/tcl.h:	Merge from core-stabilizer-branch.
	* library/init.tcl:	Stabilizing toward 8.5b1 release now done on
	* tools/tcl.wse.in:	the HEAD. core-stabilizer-branch is now
	* unix/configure.in:	suspended.
	* unix/tcl.spec:
	* win/configure.in:

2007-09-19  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* generic/tclStubLib.: Replaced isdigit with internal implementation.

2007-09-18  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclStubLib.c:	Remove C library calls from Tcl_InitStubs() so
	* win/makefile.vc:	that we don't need the C library linked in to
	libtclStub.

2007-09-17  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* win/makefile.vc: Add crt flags for tclStubLib now it uses C-library
			   functions.

2007-09-17  Joe English	 <jenglish@users.sourceforge.net>

	* tcl.m4: use '${CC} -shared' instead of 'ld -Bshareable' to build
	shared libraries on current NetBSDs. [Bug 1749251]
	* unix/configure: regenerated (autoconf-2.59).

2007-09-17  Don Porter	<dgp@users.sourceforge.net>

	* unix/Makefile.in:	Update `make dist` so that tclDTrace.d is
	included in the source code distribution.

	* generic/tcl.h:	Revised Tcl_InitStubs() to restore Tcl 8.4
	* generic/tclPkg.c:	source compatibility with callers of
	* generic/tclStubLib.c:	Tcl_InitStubs(interp, TCL_VERSION, 1). [Bug
	1578344]

2007-09-17  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclTrace.c (Tcl_TraceObjCmd, TraceExecutionObjCmd)
	(TraceCommandObjCmd, TraceVariableObjCmd):   Generate literal values
	* generic/tclNamesp.c (NamespaceCodeCmd):    more efficiently using
	* generic/tclFCmd.c (CopyRenameOneFile):     TclNewLiteralStringObj
	* generic/tclEvent.c (TclSetBgErrorHandler): macro.

2007-09-15  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tcl.m4:	replace all direct references to compiler by ${CC} to
			enable CC overriding at configure & make time; run
			check for visibility "hidden" with all compilers;
			quoting fixes from TEA tcl.m4.
	(SunOS-5.1x):	replace direct use of '/usr/ccs/bin/ld' in SHLIB_LD by
			'cc' compiler driver.
	* unix/configure: autoconf-2.59

2007-09-14  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclBasic.c (Tcl_CreateObjCommand): Only invalidate along the
	namespace path once; that is enough. [Bug 1519940]

2007-09-14  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclDTrace.d (new file): Add DTrace provider for Tcl; allows
	* generic/tclCompile.h:		  tracing of proc and command entry &
	* generic/tclBasic.c:		  return, bytecode execution, object
	* generic/tclExecute.c:		  allocation and more; with
	* generic/tclInt.h:		  essentially zero cost when tracing
	* generic/tclObj.c:		  is inactive; enable with
	* generic/tclProc.c:		  --enable-dtrace configure arg
	* unix/Makefile.in:		  (disabled by default, will only
	* unix/configure.in:		  enable if DTrace is present). [Patch
	1793984]

	* macosx/GNUmakefile:		  Enable DTrace support.
	* macosx/Tcl-Common.xcconfig:
	* macosx/Tcl.xcodeproj/project.pbxproj:

	* generic/tclCmdIL.c:	Factor out core of InfoFrameCmd() into
				internal TclInfoFrame() for use by DTrace
				probes.

	* unix/configure: autoconf-2.59
	* unix/tclConfig.h.in: autoheader-2.59

2007-09-12  Don Porter	<dgp@users.sourceforge.net>

	* unix/Makefile.in:	Perform missing updates of the tcltest Tcl
	* win/Makefile.in:	Module installed filename that should have
	been part of the bump to tcltest 2.3b1. Thanks Larry Virden.

2007-09-12  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* win/makefile.vc, win/rules.vc, win/nmakehlp.c: Use nmakehlp to
	substitute values for tclConfig.sh (helps cross-compiling).

2007-09-11  Don Porter	<dgp@users.sourceforge.net>

	* library/tcltest/tcltest.tcl:	Accept underscores and colons in
	* library/tcltest/pkgIndex.tcl: constraint names. Properly handle
	constraint expressions that return non-numeric boolean results like
	"false". Bump to tcltest 2.3b1. [Bug 1772989; RFE 1071322]
	* tests/info.test:	Disable fragile tests.

	* doc/package.n:	Restored the functioning of [package require
	* generic/tclPkg.c:	-exact] to be compatible with Tcl 8.4. [Bug
	* tests/pkg.test:	1578344]

2007-09-11  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompCmds.c (TclCompileDictCmd-update):
	* generic/tclCompile.c (tclInstructionTable):
	* generic/tclExecute.c (INST_DICT_UPDATE_END): fix stack management in
	compiled [dict update]. [Bug 1786481]

	***POTENTIAL INCOMPATIBILITY***
	Scripts that were precompiled on earlier versions of 8.5 and use [dict
	update] will crash. Workaround: recompile.

2007-09-11  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclExecute.c: Corrected an off-by-one error in the setting
	of MaxBaseWide for certain powers. [Bug 1767293 - problem reported in
	comments when bug was reopened]

2007-09-10  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclLink.c (Tcl_UpdateLinkedVar): guard against var being
	unlinked. [Bug 1740631] (maros)

2007-09-10  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompile.c: fix tclInstructionTable entry for
	dictUpdateEnd

	* generic/tclExecute.c: remove unneeded setting of 'cleanup' variable
	before jumping to checkForCatch.

2007-09-10  Don Porter	<dgp@users.sourceforge.net>

	* doc/package.n:	Restored the document parallel syntax of the
	* generic/tclPkg.c:	[package present] and [package require]
	* tests/pkg.test:	commands. [Bug 1723675]

2007-09-09  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclInt.h:	Removed the "nsName" Tcl_ObjType from the
	* generic/tclNamesp.c:	registered set. Revised the management of the
	* generic/tclObj.c:	intrep of that Tcl_ObjType. Revised the
	* tests/obj.test:	TclGetNamespaceFromObj() routine to return
	TCL_ERROR and write a consistent error message when a namespace is not
	found. [Bug 1588842. Patch 1686862]

	***POTENTIAL INCOMPATIBILITY***
	For callers of Tcl_GetObjType() on the name "nsName".

	* generic/tclExecute.c: Update TclGetNamespaceFromObj() callers.
	* generic/tclProc.c:

	* tests/apply.test:		Updated tests to expect new consistent
	* tests/namespace-old.test:	error message when a namespace is not
	* tests/namespace.test:		found.
	* tests/upvar.test:

	* generic/tclCompCmds.c:	Use the new INST_REVERSE instruction
	* tests/mathop.test:	to correct the compiled versions of math
	operator commands. [Bug 1724437]

	* generic/tclCompile.c: New bytecode instruction INST_REVERSE to
	* generic/tclCompile.h: reverse the order of N items at the top of
	* generic/tclExecute.c: stack.

	* generic/tclCompCmds.c (TclCompilePowOpCmd):	Make a separate
	routine to compile ** to account for its different associativity.

2007-09-08  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclVar.c (Tcl_SetVar2, TclPtrSetVar): [Bug 1710710] fixed
	correctly, reverted fix of 2007-05-01.

2007-09-08  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclDictObj.c (DictUpdateCmd, DictWithCmd): Plug a hole that
	* generic/tclExecute.c (TEBC,INST_DICT_UPDATE_END): allowed a careful
	* tests/dict.test (dict-21.16,21.17,22.11): attacker to craft a dict
	containing a recursive link to itself, violating one of Tcl's
	fundamental datatype assumptions and causing a stack crash when the
	dict was converted to a string. [Bug 1786481]

2007-09-07  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclEvent.c ([::tcl::Bgerror]):	Corrections to Tcl's
	* tests/event.test:	default [interp bgerror] handler so that when
	it falls back to a hidden [bgerror] in a safe interp, it gets the
	right error context data. [Bug 1790274]

2007-09-07  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclProc.c (TclInitCompiledLocals): the refCount of resolved
	variables was being managed without checking if they were Var or
	VarInHash: itcl [Bug 1790184]

2007-09-06  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclResult.c (Tcl_GetReturnOptions):	Take care that a
	* tests/init.test:	non-TCL_ERROR code doesn't cause existing
	-errorinfo, -errorcode, and -errorline entries to be omitted.
	* generic/tclEvent.c:	With -errorInfo no longer lost, generate more
	complete ::errorInfo when calling [bgerror] after a non-TCL_ERROR
	background exception.

2007-09-06  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclInterp.c (Tcl_Init):	Removed constraint on ability
	to define a custom [tclInit] before calling Tcl_Init(). Until now the
	custom command had to be a proc. Now it can be any command.

	* generic/tclInt.decls: New internal routine TclBackgroundException()
	* generic/tclEvent.c:	that for the first time permits non-TCL_ERROR
	exceptions to trigger [interp bgerror] handling. Closes a gap in TIP
	221. When falling back to [bgerror] (which is designed only to handle
	TCL_ERROR), convert exceptions into errors complaining about the
	exception.

	* generic/tclInterp.c:	Convert Tcl_BackgroundError() callers to call
	* generic/tclIO.c:	TclBackgroundException().
	* generic/tclIOCmd.c:
	* generic/tclTimer.c:

	* generic/tclIntDecls.h:	make genstubs
	* generic/tclStubInit.c:

2007-09-06  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Tcl.xcode/project.pbxproj: discontinue unmaintained support
	* macosx/Tcl.xcode/default.pbxuser: for Xcode 1.5; replace by Xcode2
	project for use on Tiger (with Tcl.xcodeproj to be used on Leopard).

	* macosx/Tcl.xcodeproj/project.pbxproj: updates for Xcode 2.5 and 3.0.
	* macosx/Tcl.xcodeproj/default.pbxuser:
	* macosx/Tcl.xcode/project.pbxproj:
	* macosx/Tcl.xcode/default.pbxuser:
	* macosx/Tcl-Common.xcconfig:

	* macosx/README: document project changes.

2007-09-05  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Removed support for the unmaintained
	* generic/tclExecute.c: -DTCL_GENERIC_ONLY configuration. [Bug
	* unix/Makefile.in:	1264623]

2007-09-04  Don Porter	<dgp@users.sourceforge.net>

	* unix/Makefile.in:	It's unreliable to count on the release
	manager to remember to `make genstubs` before `make dist`. Let the
	Makefile remember the dependency for us.

	* unix/Makefile.in:	Corrections to `make dist` dependencies to be
	sure that macosx/configure gets generated whenever it does not exist.

2007-09-03  Kevin B, Kenny  <kennykb@acm.org>

	* library/tzdata/Africa/Cairo:
	* library/tzdata/America/Grand_Turk:
	* library/tzdata/America/Port-au-Prince:
	* library/tzdata/America/Indiana/Petersburg:
	* library/tzdata/America/Indiana/Tell_City:
	* library/tzdata/America/Indiana/Vincennes:
	* library/tzdata/Antarctica/McMurdo:
	* library/tzdata/Australia/Adelaide:
	* library/tzdata/Australia/Broken_Hill:
	* library/tzdata/Australia/Currie:
	* library/tzdata/Australia/Hobart:
	* library/tzdata/Australia/Lord_Howe:
	* library/tzdata/Australia/Melbourne:
	* library/tzdata/Australia/Sydney:
	* library/tzdata/Pacific/Auckland:
	* library/tzdata/Pacific/Chatham: Olson's tzdata2007g.

	* generic/tclListObj.c (TclLindexFlat):
	* tests/lindex.test (lindex-17.[01]):	Added code to detect the error
	when a script does [lindex {} end foo]; an overaggressive optimisation
	caused this call to return an empty object rather than an error.

2007-09-03  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclObj.c (TclInitObjSubsystem): restore registration of the
	"wideInt" Tcl_ObjType for compatibility with 8.4 extensions that
	access the tclWideIntType Tcl_ObjType; add setFromAnyProc for
	tclWideIntType.

2007-09-02  Donal K. Fellows  <dkf@users.sf.net>

	* doc/lsearch.n: Added note that order of results with the -all option
	is that of the input list. It always was, but this makes it crystal.

2007-08-30  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompile.c: Added fflush() calls following all callers of
	* generic/tclExecute.c: TclPrintByteCodeObj() so that tcl_traceCompile
	output is less likely to get mangled when writes to stdout interleave
	with other code.

2007-08-28  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c:	Use a table lookup in ParseLexeme() to
	determine lexemes with single-byte representations.

	* generic/tclBasic.c:	Used unions to better clarify overloading of
	* generic/tclCompExpr.c:	the fields of the OpCmdInfo and
	* generic/tclCompile.h:		TclOpCmdClientData structs.

2007-08-27  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c:	Call TclCompileSyntaxError() when
	expression syntax errors are found when compiling expressions. With
	this in place, convert TclCompileExpr to return void, since there's no
	longer any need to report TCL_ERROR.
	* generic/tclCompile.c: Update callers.
	* generic/tclExecute.c:

	* generic/tclCompCmds.c:	New routine TclCompileSyntaxError()
	* generic/tclCompile.h: to directly compile bytecodes that report a
	* generic/tclCompile.c: syntax error, rather than (ab)use a call to
	TclCompileReturnCmd. Also, undo the most recent commit that papered
	over some issues with that (ab)use. New routine produces a new opcode
	INST_SYNTAX, which is a minor variation of INST_RETURN_IMM. Also a bit
	of constification.

	* generic/tclCompile.c: Move the deallocation of local LiteralTable
	* generic/tclCompExpr.c:	entries into TclFreeCompileEnv().
	* generic/tclExecute.c: Update callers.

	* generic/tclCompExpr.c:	Force numeric and boolean literals in
	expressions to register with their intreps intact, even if that means
	overwriting existing intreps in already registered literals.

2007-08-25  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclExecute.c (TclExecuteByteCode): Added code to handle
	* tests/expr.test (expr-23.48-53)	     integer exponentiation
	that results in 32- and 64-bit integer results, avoiding calls to wide
	integer exponentiation routines in this common case. [Bug 1767293]

	* library/clock.tcl (ParseClockScanFormat): Modified code to allow
	* tests/clock.test (clock-60.*):	    case-insensitive matching
	of time zone and month names. [Bug 1781282]

2007-08-24  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c:	Register literals found in expressions
	* tests/compExpr.test:	to restore literal sharing. Preserve numeric
	intreps when literals are created for the first time. Correct memleak
	in ExecConstantExprTree() and add test for the leak.

2007-08-24  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompile.c: replaced copy loop that tripped some compilers
	with memmove. [Bug 1780870]

2007-08-23  Don Porter	<dgp@users.sourceforge.net>

	* library/init.tcl ([auto_load_index]): Delete stray "]" that created
	an expr syntax error (masked by a [catch]).

	* generic/tclCompCmds.c (TclCompileReturnCmd):	Added crash protection
	to handle callers other than TclCompileScript() failing to meet the
	initialization assumptions of the TIP 280 code in CompileWord().

	* generic/tclCompExpr.c:	Suppress the attempt to convert to
	numeric when pre-compiling a constant expression indicates an error.

2007-08-22  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c (TEBC): disable the new shortcut to frequent
	INSTs for debug builds. REVERTED (collision with alternative fix)

2007-08-21  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclMain.c:	Corrected the logic of dropping the last
	* tests/main.test:	newline from an interactively typed command.
	[Bug 1775878]

2007-08-21  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* tests/thread.test: thread-4.4: clear ::errorInfo in the thread as a
	message is left here from init.tcl on windows due to no tcl_pkgPath.

2007-08-20  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c (INST_SUB): fix usage of the new macro for
	overflow detection in sums, adapt to subtraction. Lengthy comment
	added.

2007-08-19  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclExecute.c (Overflowing, TclIncrObj, TclExecuteByteCode):
	Encapsulate Miguel's last change in a more mnemonic macro.

2007-08-19  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: changed the check for overflow in sums,
	reducing objsize, number of branches and cache misses (according to
	cachegrind). Non-overflow for s=a+b:
	previous
	  ((a >= 0 || b >= 0 || s < 0) && (s >= 0 || b < 0 || a < 0))
	now
	  (((a^s) >= 0) || ((a^b) < 0))
	This expresses: "a and s have the same sign or else a and b have
	different sign".

2007-08-19  Donal K. Fellows  <dkf@users.sf.net>

	* doc/interp.n (RESOURCE LIMITS): Added text to better explain why
	time limits are described using absolute times. [Bug 1752148]

2007-08-16  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclVar.c: improved localVarNameType caching to leverage
	the new availability of Tcl_Obj in variable names, avoiding string
	comparisons to verify that the cached value is usable.

	* generic/tclExecute.c: check the two most frequent instructions
	before the switch. Reduces both runtime and obj size a tiny bit.

2007-08-16  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c:	Added a "constant" field to the OpNode
	struct (again "free" due to alignment requirements) to mark those
	subexpressions that are completely known at compile time. Enhanced
	CompileExprTree() and its callers to precompute these constant
	subexpressions at compile time. This resolves the issue raised in [Bug
	1564517].

2007-08-15  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclIOUtil.c (TclGetOpenModeEx): Only set the O_APPEND flag
	* tests/ioUtil.test (ioUtil-4.1):	  on a channel for the 'a'
	mode and not for 'a+'. [Bug 1773127]

2007-08-14  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c (INST_INVOKE*): peephole opt, do not get the
	interp's result if it will be pushed/popped.

2007-08-14  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Use fully qualified variable names for
	* tests/thread.test:	::errorInfo and ::errorCode so that string
	* tests/trace.test:	reported to variable traces are fully
	qualified in agreement with Tcl 8.4 operations.

2007-08-14  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tclLoadDyld.c: use dlfcn API on Mac OS X 10.4 and later; fix
	issues with loading from memory on intel and 64bit; add debug messages

	* tests/load.test: add test load-10.1 for loading from vfs.

	* unix/dltest/pkga.c:		whitespace & comment cleanup, remove
	* unix/dltest/pkgb.c:		unused pkgf.c.
	* unix/dltest/pkgc.c:
	* unix/dltest/pkge.c:
	* unix/dltest/pkgf.c (removed):
	* unix/dltest/pkgua.c:
	* macosx/Tcl.xcodeproj/project.pbxproj:

2007-08-13  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c: Provide DECACHE/CACHE protection to the
	* tests/trace.test:	Tcl_LogCommandInfo() call. [Bug 1773040]

2007-08-12  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCmdMZ.c (Tcl_SplitObjCmd): use TclNewStringObj macro
	instead of calling the function.

	* generic/tcl_Obj.c (TclAllocateFreeObjects): remove unneeded memset
	to 0 of all allocated objects.

2007-08-10  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclInt.h: remove redundant ops in TclNewStringObj macro.

2007-08-10  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclInt.h: fix the TclSetVarNamespaceVar macro, was causing a
	leak.

2007-08-10  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c:	Revise CompileExprTree() to use the
	OpNode mark field scheme of tree traversal. This eliminates the need
	to use magic values in the left and right fields for that purpose.
	Also stop abusing the left field within ParseExpr() to store the
	number of arguments in a parsed function call. CompileExprTree() now
	determines that for itself at compile time. Then reorder code to
	eliminate duplication.

2007-08-09  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclProc.c (TclCreateProc): better comments on the required
	varflag values when loading precompiled procs.

	* generic/tclExecute.c (INST_STORE_ARRAY):
	* tests/trace.test (trace-2.6): whole array write traces on compiled
	local variables were not firing. [Bug 1770591]

2007-08-08  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclProc.c (InitLocalCache): reference firstLocalPtr via
	procPtr. codePtr->procPtr == NULL exposed by tbcload.

2007-08-08  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c: Corrected failure to compile/link in the
	-DNO_WIDE_TYPE configuration.

	* generic/tclExecute.c: Corrected improper use of bignum arguments to
	* tests/expr.test:	*SHIFT operations. [Bug 1770224]

2007-08-07  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclInt.h: remove comments refering to VAR_SCALAR, as that
	flag bit does not exist any longer.
	* generic/tclProc.c (InitCompiledLocals): removed optimisation for
	non-resolved case, as the function is never called in that case.
	Renamed the function to InitResolvedLocals to calrify the point.

	* generic/tclInt.decls:	  Exporting via stubs to help xotcl adapt to
	* generic/tclInt.h:	  VarReform.
	* generic/tclIntDecls.h:
	* generic/tclStubInit.c:

2007-08-07  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclEnv.c:	improve environ handling on Mac OS X (adapted
	* unix/tclUnixPort.h:	from Apple changes in Darwin tcl-64).

	* unix/Makefile.in:	add support for compile flags specific to
				object files linked directly into executables.

	* unix/configure.in (Darwin): only use -seg1addr flag when prebinding;
	use -mdynamic-no-pic flag for object files linked directly into exes;
	support overriding TCL_PACKAGE_PATH/TCL_MODULE_PATH in environment.

	* unix/configure: autoconf-2.59

2007-08-06  Don Porter	<dgp@users.sourceforge.net>

	* tests/parseExpr.test: Update source file name of expr parser code.

	* generic/tclCompExpr.c:	Added a "mark" field to the OpNode
	struct, which is used to guide tree traversal. This field costs
	nothing since alignement requirements used the memory already.
	Rewrote ConvertTreeToTokens() to use the new field, which permitted
	consolidation of utility routines CopyTokens() and
	GenerateTokensForLiteral().

2007-08-06  Kevin B. Kenny  <kennykb@users.sf.net>

	* generic/tclGetDate.y: Added a cast to the definition of YYFREE to
				silence compiler warnings.
	* generic/tclDate.c:	Regenerated
	* win/tclWinTest.c:	Added a cast to GetSecurityDescriptorDacl call
				to silence compiler warnings.

2007-08-04  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclInt.decls:	  Exporting via stubs to help itcl adapt to
	* generic/tclInt.h:	  VarReform. Added localCache initialization
	* generic/tclIntDecls.h:  to TclInitCompiledLocals (which only exists
	* generic/tclProc.c:	  for itcl).
	* generic/tclStubInit.c:
	* generic/tclVar.c:

2007-08-01  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* library/word.tcl: Rewrote for greater efficiency. [Bug 1764318]

2007-08-01  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* generic/tclInt.h:	Added a TclOffset macro ala Tk_Offset to
	* generic/tclVar.c:	abstract out 'offsetof' which may not be
	* generic/tclExceute.c: defined (eg: msvc6).

2007-08-01  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclVar.c (TclCleanupVar): fix [Bug 1765225], thx Larry
	Virden.

2007-07-31  Miguel Sofer  <msofer@users.sf.net>

	* doc/Hash.3:
	* generic/tclHash.c:
	* generic/tclObj.c:
	* generic/tclThreadStorage.c: (changes part of the patch below)
	Stop Tcl_CreateHashVar from resetting hPtr->clientData to NULL after
	calling the allocEntryProc for a custom table.

	* generic/tcl.h:
	* generic/tclBasic.c:
	* generic/tclCmdIL.c:
	* generic/tclCompCmds.c:
	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c:
	* generic/tclHash.c:
	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclIntDecls.h:
	* generic/tclLiteral.c:
	* generic/tclNamesp.c:
	* generic/tclObj.c:
	* generic/tclProc.c:
	* generic/tclThreadStorage.c:
	* generic/tclTrace.c:
	* generic/tclVar.c: VarReform [Patch 1750051]

	*** POTENTIAL INCOMPATIBILITY *** (tclInt.h and tclCompile.h)
	Extensions that access internals defined in tclInt.h and/or
	tclCompile.h may lose both binary and source compatibility. The
	relevant changes are:
	1. 'struct Var' is completely changed, all acceses to its internals
	   (either direct or via the TclSetVar* and TclIsVar* macros) will
	   malfunction. Var flag values and semantics changed too.
	2. 'struct Bytecode' has an additional field that has to be
	   initialised to NULL
	3. 'struct Namespace' is larger, as the varTable is now one pointer
	   larger than a Tcl_HashTable. Direct access to its fields will
	   malfunction.
	4. 'struct CallFrame' grew one more field (the second such growth with
	   respect to Tcl8.4).
	5. API change for the functions TclFindCompiledLocal, TclDeleteVars
	   and many internal functions in tclVar.c

	Additionally, direct access to variable hash tables via the standard
	Tcl_Hash* interface is to be considered as deprecated. It still works
	in the present version, but will be broken by further specialisation
	of these hash tables. This concerns especially the table of array
	elements in an array, as well as the varTable field in the Namespace
	struct.

2007-07-31  Miguel Sofer  <msofer@users.sf.net>

	* unix/configure.in: allow use of 'inline' in Tcl sources. [Patch
	* win/configure.in:  1754128]
	* win/makefile.vc:   Regen with autoconf 2.61

2007-07-31  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* unix/tclUnixInit.c (TclpSetVariables): Use the thread-safe getpwuid
	replacement to fill the tcl_platform(user) field as it is not subject
	to spoofing. [Bug 681877]

	* unix/tclUnixCompat.c: Simplify the #ifdef logic.

	* unix/tclUnixChan.c (FileWatchProc): Fix test failures.

2007-07-30  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* unix/tclUnixChan.c (SET_BITS, CLEAR_BITS): Added macros to make this
	file clearer.

2007-07-24  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c (TEOvI, GetCommandSource):
	* generic/tclExecute.c (TEBC, TclGetSrcInfoForCmd):
	* generic/tclInt.h:
	* generic/tclTrace.c (TclCheck(Interp|Execution)Traces):
	Removed the need for TEBC to inspect the command before calling TEOvI,
	leveraging the TIP 280 infrastructure. Moved the generation of a
	correct nul-terminated command string away from the trace code, back
	into TEOvI/GetCommandSource.

2007-07-20  Andreas Kupries  <andreask@activestate.com>

	* library/platform/platform.tcl: Fixed bug in 'platform::patterns'
	* library/platform/pkgIndex.tcl: where identifiers not matching
	* unix/Makefile.in: the special linux and solaris forms would not
	* win/Makefile.in: get 'tcl' as an acceptable platform added to
	* doc/platform.n: the result. Bumped package to version 1.0.3 and
	* doc/platform_shell.n: updated documentation and Makefiles. Also
	fixed bad version info in the documentation of platform::shell.

2007-07-19  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclParse.c:	In contexts where interp and parsePtr->interp
	might be different, be sure to use the latter for error reporting.
	Also pulled the interp argument back out of ParseTokens() since we
	already had a parsePtr->interp to work with.

2007-07-18  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c:	Removed unused arguments and variables

2007-07-17  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c (ParseExpr):	While adding comments to
	explain the operations of ParseExpr(), made significant revisions to
	the code so it would be easier to explain, and in the process made the
	code simpler and clearer as well.

2007-07-15  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c:	More commentary.
	* tests/parseExpr.test:		Several tests of syntax error messages
	to check that when expression substrings are truncated they leave
	visible the context relevant to the reported error.

2007-07-12  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c:	Factored out, corrected, and commented
	common code for reporting syntax errors in LEAF elements.

2007-07-11  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompCmds.c (TclCompileWhileCmd):
	* generic/tclCompile.c (TclCompileScript):
	Corrected faulty avoidance of INST_START_CMD when the first opcode in
	a script is within a loop (as produced by 'while 1'), so that the
	corresponding command is properly counted. [Bug 1752146]

2007-07-11  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c:	Added a "parseOnly" flag argument to
	ParseExpr() to indicate whether the caller is Tcl_ParseExpr(), with an
	end goal of filling a Tcl_Parse with Tcl_Tokens representing the
	parsed expression, or TclCompileExpr() with the goal of compiling and
	executing the expression. In the latter case, more aggressive
	conversion of QUOTED and BRACED lexeme to literals is done. In the
	former case, all such conversion is avoided, since Tcl_Token
	production would revert it anyway. This enables simplifications to the
	GenerateTokensForLiteral() routine as well.

2007-07-10  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c:	Added a field for operator precedence
	to be stored directly in the parse tree. There's no memory cost to
	this addition, since that memory would have been lost to alignment
	issues anyway. Also, converted precedence definitions and lookup
	tables to use symbolic constants instead of raw number for improved
	readability, and continued extending/improving/correcting comments.
	Removed some unused counter variables. Renamed some variables for
	clarity and replaced some cryptic logic with more readable macros.

2007-07-09  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c:	Revision so that the END lexeme never
	gets inserted into the parse tree. Later tree traversal never reaches
	it since its location in the tree is not variable. Starting and
	stopping with the START lexeme (node 0) is sufficient. Also finished
	lexeme code commentary.

	* generic/tclCompExpr.c:	Added missing creation and return of
	the Tcl_Parse fields that indicate error conditions. [Bug 1749987]

2007-07-05  Don Porter	<dgp@users.sourceforge.net>

	* library/init.tcl (unknown):	Corrected inconsistent error message
	in interactive [unknown] when empty command is invoked. [Bug 1743676]

2007-07-05  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclNamesp.c (SetNsNameFromAny):
	* generic/tclObj.c (SetCmdNameFromAny): Avoid unnecessary
	ckfree/ckalloc when the old structs can be reused.

2007-07-04  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclNamesp.c: Fix case where a FQ cmd or ns was being cached
	* generic/tclObj.c:    in a different interp, tkcon. [Bug 1747512]

2007-07-03  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c:	Revised #define values so that there
	is now more expansion room to define more BINARY operators.

2007-07-02  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclHash.c (CompareStringKeys): Always use the strcmp()
	version; the operation is functionally equivalent, the speed is
	identical (up to measurement limitations), and yet the code is
	simpler. [FRQ 951168]

2007-07-02  Don Porter	<dgp@users.sourceforge.net>

	* generic/tcl.h:	Removed TCL_PRESERVE_BINARY_COMPATIBILITY and
	* generic/tclHash.c:	any code enabled when it is set to 0. We will
	* generic/tclStubInit.c:	always want to preserve binary compat
	of the structs that appear in the interface through the 8.* series of
	releases, so it's pointless to drag around this never-enabled
	alternative.

	* generic/tclIO.c:	Removed dead code.
	* unix/tclUnixChan.c:

	* generic/tclCompExpr.c:	Removed dead code, old implementations
	* generic/tclEvent.c:	of expr parsing and compiling, including the
	* generic/tclInt.h:	routine TclFinalizeCompilation().

2007-06-30  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdIL.c (Tcl_LsortObjCmd): Plug a memory leak caused by a
	missing Tcl_DecrRefCount on an error path. [Bug 1717186]

2007-06-30  Zoran Vasiljevic <vasiljevic@users.sourceforge.net>

	* generic/tclThread.c: Prevent RemeberSyncObj() from growing the sync
	object lists by reusing already free'd slots, if possible. See
	discussion on Bug 1726873 for more information.

2007-06-29  Donal K. Fellows  <dkf@users.sf.net>

	* doc/DictObj.3 (Tcl_DictObjDone): Improved documentation of this
	function to make it clearer how to use it. [Bug 1710795]

2007-06-29  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclAlloc.c:		on Darwin, ensure memory allocated by
	* generic/tclThreadAlloc.c:	the custom TclpAlloc()s is aligned to
	16 byte boundaries (as is the case with the Darwin system malloc).

	* generic/tclGetDate.y: use ckalloc/ckfree instead of malloc/free.
	* generic/tclDate.c:	bison 1.875e

	* generic/tclBasic.c (TclEvalEx): fix warnings.

	* macosx/Tcl.xcodeproj/project.pbxproj: better support for renamed tcl
	* macosx/Tcl.xcodeproj/default.pbxuser: source dir; add 10.5 SDK build
	* macosx/Tcl-Common.xcconfig:		config; remove tclMathOp.c.

	* macosx/README: document Tcl.xcodeproj changes.

2007-06-28  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:		Removed dead code, including the
	* generic/tclExecute.c:		entire file tclMathOp.c.
	* generic/tclInt.h:
	* generic/tclMathOp.c (removed):
	* generic/tclTestObj.c:
	* win/tclWinFile.c:

	* unix/Makefile.in:	Updated to reflect deletion of tclMathOp.c.
	* win/Makefile.in:
	* win/makefile.bc:
	* win/makefile.vc:

2007-06-28  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* generic/tclBasic.c:	  Silence constness warnings for TclStackFree
	* generic/tclCompCmds.c:  when building with msvc.
	* generic/tclFCmd.c:
	* generic/tclIOCmd.c:
	* generic/tclTrace.c:

2007-06-28  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclVar.c (UnsetVarStruct): fix possible segfault.

2007-06-27  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclTrace.c:	Corrected broken trace reversal logic in
	* generic/tclTest.c:	TclCheckInterpTraces that led to infinite loop
	* tests/trace.test:	when multiple Tcl_CreateTrace traces were set
	and one of them did not fire due to level restrictions. [Bug 1743931]

2007-06-26  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c (TclEvalEx):	Moved some arrays from the C
	stack to the Tcl stack.

2007-06-26  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclVar.c (UnsetVarStruct): more streamlining.

2007-06-25  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c: Safety checks to avoid crashes in the
	TclStack* routines when called with an incompletely initialized
	interp. [Bug 1743302]

2007-06-25  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclVar.c (UnsetVarStruct): fixing incomplete change, more
	streamlining.

2007-06-24  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclVar.c (TclDeleteCompiledLocalVars): removed inlining that
	ended up not really optimising (limited benchmarks). Now calling
	UnsetVarStruct (streamlined old code is #ifdef'ed out, in case better
	benchmarks do show a difference).

	* generic/tclVar.c (UnsetVarStruct): fixed a leak introduced in last
	commit.

2007-06-23  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclVar.c (UnsetVarStruct, TclDeleteVars): made the logic
	slightly clearer, eliminated some duplicated code.

	*** POTENTIAL INCOMPATIBILITY *** (tclInt.h and Var struct users)
	The core never builds VAR_LINK variable to have traces. Such a
	"monster", should one exist, will now have its unset traces called
	*before* it is unlinked.

2007-06-23  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/tclMacOSXNotify.c (AtForkChild): don't call CoreFoundation
	APIs after fork() on systems where that would lead to an abort().

2007-06-22  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c: Revised TclStackRealloc() signature to better
	* generic/tclInt.h:	parallel (and fall back on) Tcl_Realloc.

	* generic/tclNamesp.c (TclResetShadowesCmdRefs):	Replaced
	ckrealloc based allocations with TclStackRealloc allocations.

	* generic/tclCmdIL.c:	More conversions to use TclStackAlloc.
	* generic/tclScan.c:

2007-06-21  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	 Move most instances of the Tcl_Parse struct
	* generic/tclCompExpr.c: off the C stack and onto the Tcl stack. This
	* generic/tclCompile.c:	 is a rather large struct (> 3kB).
	* generic/tclParse.c:

2007-06-21  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c (TEOvI):		Made sure that leave traces
	* generic/tclExecute.c (INST_INVOKE):	that were created during
	* tests/trace.test (trace-36.2):	execution of an originally
	untraced command do not fire [Bug 1740962], partial fix.

2007-06-21  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tcl.h, generic/tclCompile.h, generic/tclCompile.c: Remove
	references in comments to obsolete {expand} notation. [Bug 1740859]

2007-06-20  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclVar.c: streamline namespace vars deletion: only compute
	the variable's full name if the variable is traced.

2007-06-20  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclInt.decls: Revised the interfaces of the routines
	* generic/tclExecute.c: TclStackAlloc and TclStackFree to make them
	easier for callers to use (or more precisely, harder to misuse).
	TclStackFree now takes a (void *) argument which is the pointer
	intended to be freed. TclStackFree will panic if that's not actually
	the memory the call will free. TSA/TSF also now tolerate receiving
	(interp == NULL), in which case they simply fall back to be calls to
	Tcl_Alloc/Tcl_Free.

	* generic/tclIntDecls.h:	make genstubs

	* generic/tclBasic.c:	Updated callers
	* generic/tclCmdAH.c:
	* generic/tclCmdIL.c:
	* generic/tclCompCmds.c:
	* generic/tclCompExpr.c:
	* generic/tclCompile.c:
	* generic/tclFCmd.c:
	* generic/tclFileName.c:
	* generic/tclIOCmd.c:
	* generic/tclIndexObj.c:
	* generic/tclInterp.c:
	* generic/tclNamesp.c:
	* generic/tclProc.c:
	* generic/tclTrace.c:
	* unix/tclUnixPipe.c:

2007-06-20  Jeff Hobbs	<jeffh@ActiveState.com>

	* tools/tcltk-man2html.tcl: revamp of html doc output to use CSS,
	standardized headers, subheaders, dictionary sorting of names.

2007-06-18  Jeff Hobbs	<jeffh@ActiveState.com>

	* tools/tcltk-man2html.tcl: clean up copyright merging and output.
	clean up coding constructs.

2007-06-18  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCmdIL.c (InfoFrameCmd):
	* generic/tclCmdMZ.c (Tcl_SwitchObjCmd):
	* generic/tclCompile.c (TclInitCompileEnv):
	* generic/tclProc.c (Tcl_ProcObjCmd, SetLambdaFromAny): Moved the
	CmdFrame off the C stack and onto the Tcl stack.

	* generic/tclExecute.c (TEBC):	Moved the CmdFrame off the C stack and
	onto the Tcl stack, between the catch and the execution stacks

2007-06-18  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c (TclEvalEx,TclEvalObjEx):	Moved the CmdFrame off
	the C stack and onto the Tcl stack.

2007-06-17  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclProc.c (TclObjInterpProcCore): Minor fixes to make
	* generic/tclExecute.c (TclExecuteByteCode): compilation debugging
	builds work again. [Bug 1738542]

2007-06-16  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclProc.c (TclObjInterpProcCore): Use switch instead of a
	chain of if's for a modest performance gain and a little more clarity.

2007-06-15  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompCmds.c:  Simplified [variable] compiler and executor.
	* generic/tclExecute.c:	  Missed updates to "there is always a valid
	frame".

	* generic/tclCompile.c: reverted TclEvalObjvInternal and INST_INVOKE
	* generic/tclExecute.c: to essentially what they were previous to the
	* generic/tclBasic.c:	commit of 2007-04-03 [Patch 1693802] and the
	subsequent optimisations, as they break the new trace tests described
	below.

	* generic/trace.test: added tests 36 to 38 for dynamic trace creation
	and addition. These tests expose a change in dynamics due to a recent
	round of optimisations. The "correct" behaviour is not described in
	docs nor TIP 62.

2007-06-14  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclInt.decls:	  Modif to the internals of TclObjInterpProc
	* generic/tclInt.h:	  to reduce stack consumption and improve task
	* generic/tclIntDecls.h:  separation. Changes the interface of
	* generic/tclProc.c:	  TclObjInterpProcCore (patching TclOO
	simultaneously).

	* generic/tclProc.c (TclObjInterpProcCore): simplified obj management
	in wrongNumArgs calls.

2007-06-14  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompile.c: SetByteCodeFromAny() can no longer return any
	* generic/tclExecute.c: code other than TCL_OK, so remove code that
	* generic/tclProc.c:	formerly handled exceptional codes.

2007-06-13  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c (TclCompEvalObj): missed update to "there is
	always a valid frame".

	* generic/tclProc.c (TclObjInterpProcCore): call TEBC directly instead
	of going through TclCompEvalObj - no need to check the compilation's
	freshness, this has already been done. This improves speed and should
	also provide some relief to [Bug 1066755].

2007-06-12  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclBasic.c (Tcl_CreateInterp): Turn the [info] command into
	* generic/tclCmdIL.c (TclInitInfoCmd):	 an ensemble, making it easier
	for third-party code to plug into.

	* generic/tclIndexObj.c (Tcl_WrongNumArgs):
	* generic/tclNamesp.c, generic/tclInt.h (tclEnsembleCmdType): Make
	Tcl_WrongNumArgs do replacement correctly with ensembles and other
	sorts of complex replacement strategies.

2007-06-11  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c:	 comments added to explain iPtr->numLevels
	management.

	* generic/tclNamesp.c:	 tweaks to Tcl_GetCommandFromObj and
	* generic/tclObj.c:	 TclGetNamespaceFromObj; modified the usage of
	structs ResolvedCmdName and ResolvedNsname so that the field refNsPtr
	is NULL for fully qualified names.

2007-06-10  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:	 Further TEOvI split, creating a new
	* generic/tclCompile.h:	 TclEvalObjvKnownCommand() function to handle
	* generic/tclExecute.c:	 commands that are already known and are not
	traced. INST_INVOKE now calls into this function instead of inlining
	parts of TEOvI. Same perf, better isolation.

	***POTENTIAL INCOMPAT*** There is a subtle issue with the timing of
	execution traces that is changed here - first change appeared in my
	commit of 2007-04-03 [Patch 1693802], which caused some divergence
	between compiled and non-compiled code.
	***THIS CHANGE IS UNDER REVIEW***

2007-06-10  Jeff Hobbs	<jeffh@ActiveState.com>

	* README: updated links. [Bug 1715081]

	* generic/tclExecute.c (TclExecuteByteCode): restore support for
	INST_CALL_BUILTIN_FUNC1 and INST_CALL_FUNC1 bytecodes to support 8.4-
	precompiled sources (math functions). [Bug 1720895]

2007-06-10  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclInt.h:
	* generic/tclNamesp.c:
	* generic/tclObj.c:
	* generic/tclvar.c: new macros TclGetCurrentNamespace() and
	TclGetGlobalNamespace(); Tcl_GetCommandFromObj and
	TclGetNamespaceFromObj rewritten to make the logic clearer; slightly
	faster too.

2007-06-09  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c (INST_INVOKE): isolated two vars to the small
	block where they are actually used.

	* generic/tclObj.c (Tcl_GetCommandFromObj): rewritten to make the
	logic clearer; slightly faster too.

	* generic/tclBasic.c:	Split TEOv in two, by separating a processor
	for non-TCL_OK returns. Also split TEOvI in a full version that
	handles non-existing and traced commands, and a separate shorter
	version for the regular case.

	* generic/tclBasic.c:	Moved the generation of command strings for
	* generic/tclTrace.c:	traces: previously in Tcl_EvalObjv(), now in
	TclCheck[Interp|Execution]Traces(). Also insured that the strings are
	properly NUL terminated at the correct length. [Bug 1693986]

	***POTENTIAL INCOMPATIBILITY in internal API***
	The functions TclCheckInterpTraces() and TclCheckExecutionTraces() (in
	internal stubs) used to be noops if the command string was NULL, this
	is not true anymore: if the command string is NULL, they generate an
	appropriate string from (objc,objv) and use it to call the traces. The
	caller might as well not call them with a NULL string if he was
	expecting a noop.

	* generic/tclBasic.c:	Extend usage of TclLimitReady() and
	* generic/tclExecute.c: (new) TclLimitExceeded() macros.
	* generic/tclInt.h:
	* generic/tclInterp.c:

	* generic/tclInt.h:	New TclCleanupCommandMacro for core usage.
	* generic/tclBasic.c:
	* generic/tclExecute.c:
	* generic/tclObj.c:

2007-06-09 Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Tcl.xcodeproj/project.pbxproj: add new Tclsh-Info.plist.in.

2007-06-08  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdMZ.c (Tcl_StringObjCmd): Changed [string first] and
	* doc/string.n: [string last] so that they have clearer descriptions
	for those people who know the adage about needles and haystacks. This
	follows suggestions on comp.lang.tcl...

2007-06-06  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclParse.c: fix for uninit read. [Bug 1732414]

2007-06-06  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Tcl.xcodeproj/project.pbxproj: add settings for Fix&Continue.

	* unix/configure.in (Darwin):		add plist for tclsh; link the
	* unix/Makefile.in  (Darwin):		Tcl and tclsh plists into
	* macosx/Tclsh-Info.plist.in (new):	their binaries in all cases.
	* macosx/Tcl-Common.xcconfig:

	* unix/tcl.m4 (Darwin): fix CF checks in fat 32&64bit builds.
	* unix/configure: autoconf-2.59

2007-06-05  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Added interp flag value ERR_LEGACY_COPY to
	* generic/tclInt.h:	control the timing with which the global
	* generic/tclNamesp.c:	variables ::errorCode and ::errorInfo get
	* generic/tclProc.c:	updated after an error. This keeps more
	* generic/tclResult.c:	precise compatibility with Tcl 8.4.
	* tests/result.test (result-6.2):	[Bug 1649062]

2007-06-05  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclInt.h:
	* generic/tclExecute.c: Tcl-stack reform, [Patch 1701202]

2007-06-03  Daniel Steffen  <das@users.sourceforge.net>

	* unix/Makefile.in: add datarootdir to silence autoconf-2.6x warning.

2007-05-30  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Removed code that dealt with
	* generic/tclCompile.c: TCL_TOKEN_EXPAND_WORD tokens representing
	* generic/tclCompile.h: expanded literal words. These sections were
	mostly in place to enable [info frame] to discover line information in
	expanded literals. Since the parser now generates a token for each
	post-expansion word referring to the right location in the original
	script string, [info frame] gets all the data it needs.

	* generic/tclInt.h:	Revised the parser so that it never produces
	* generic/tclParse.c:	TCL_TOKEN_EXPAND_WORD tokens when parsing an
	* tests/parse.test:	expanded literal word; that is, something like
	{*}{x y z}. Instead, generate the series of TCL_TOKEN_SIMPLE_WORD
	tokens to represent the words that expansion of the literal string
	produces. [RFE 1725186]

2007-05-29  Jeff Hobbs	<jeffh@ActiveState.com>

	* unix/tclUnixThrd.c (Tcl_JoinThread): fix for 64-bit handling of
	pthread_join exit return code storage. [Bug 1712723]

2007-05-22  Don Porter	<dgp@users.sourceforge.net>

	[core-stabilizer-branch]

	* unix/configure:	autoconf-2.59 (FC6 fork)
	* win/configure:

	* README:		Bump version number to 8.5b1
	* generic/tcl.h:
	* library/init.tcl:
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/configure.in:

2007-05-18  Don Porter	<dgp@users.sourceforge.net>

	* unix/configure:	autoconf-2.59 (FC6 fork)
	* win/configure:

	* README:		Bump version number to 8.5a7
	* generic/tcl.h:
	* library/init.tcl:
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/configure.in:

	* generic/tclParse.c:	Disable and remove the ALLOW_EXPAND sections
	* tests/info.test:	that continued to support the deprecated
	* tests/mathop.test:	{expand} syntax. Updated the few remaining
	users of that syntax in the test suite.

2007-05-17  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclExecute.c (TclLimitReady): Created a macro version of
	Tcl_LimitReady just for TEBC, to reduce the amount of times that the
	bytecode engine calls out to external functions on the critical path.
	* generic/tclInterp.c (Tcl_LimitReady): Added note to remind anyone
	doing maintenance that there is a macro version to update.

2007-05-17  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tcl.decls: workaround 'make checkstubs' failures from
	tclStubLib.c MODULE_SCOPE revert. [Bug 1716117]

2007-05-16  Joe English	 <jenglish@users.sourceforge.net>

	* generic/tclStubLib.c:	 Change Tcl_InitStubs(), tclStubsPtr, and the
	auxilliary stubs table pointers back to public visibility.

	These symbols need to be exported so that stub-enabled extensions may
	be statically linked into an extended tclsh or Big Wish with a
	dynamically-linked libtcl. [Bug 1716117]

2007-05-15  Don Porter	<dgp@users.sourceforge.net>

	* win/configure:	autoconf-2.59 (FC6 fork)

	* library/reg/pkgIndex.tcl:	Bump to registry 1.2.1 to account for
	* win/configure.in:		[Bug 1682211] fix.
	* win/makefile.bc:
	* win/tclWinReg.c:

2007-05-11  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* generic/tclInt.h: Removed TclEvalObjEx and TclGetSrcInfoForPc from
	tclInt.h now they are in the internal stubs table.

2007-05-09  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclInt.h:	TclFinalizeThreadAlloc() is always defined, so
	make sure it is also always declared (with MODULE_SCOPE).

2007-05-09  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclInt.h: fix warning when building threaded with -DPURIFY.

	* macosx/Tcl.xcodeproj/project.pbxproj: add 'DebugUnthreaded' &
	* macosx/Tcl.xcodeproj/default.pbxuser: 'DebugLeaks' configs and env
	var settings needed to run the 'leaks' tool.

2007-05-07  Don Porter	<dgp@users.sourceforge.net>

	[Tcl Bug 1706140]

	* generic/tclLink.c (LinkTraceProc):	Update Tcl_VarTraceProcs so
	* generic/tclNamesp.c (Error*Read):	they call Tcl_InterpDeleted()
	* generic/tclTrace.c (Trace*Proc):	for themselves, and do not
	* generic/tclUtil.c (TclPrecTraceProc): rely on (frequently buggy)
	setting of the TCL_INTERP_DESTROYED flag by the trace core.

	* generic/tclVar.c:	Update callers of TclCallVarTraces to not pass
	in the TCL_INTERP_DESTROYED flag. Also apply filters so that public
	routines only pass documented flag values down to lower level routines

	* generic/tclTrace.c (TclCallVarTraces):	The setting of the
	TCL_INTERP_DESTROYED flag is now done entirely within the
	TclCallVarTraces routine, the only place it can be done right.

2007-05-06  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclInt.h (ExtraFrameInfo): Create a new mechanism for
	* generic/tclCmdIL.c (InfoFrameCmd): conveying what information needs
	to be added to the results of [info frame] to replace the hack that
	was there before.
	* generic/tclProc.c (Tcl_ApplyObjCmd): Use the new mechanism for the
	[apply] command, the only part of Tcl itself that needs it (so far).

	* generic/tclInt.decls (TclEvalObjEx, TclGetSrcInfoForPc): Expose
	these two functions through the internal stubs table, necessary for
	extensions that need to integrate deeply with TIP#280.

2007-05-05  Donal K. Fellows  <dkf@users.sf.net>

	* win/tclWinFile.c (TclpGetUserHome):	Squelch type-pun warnings in
	* win/tclWinInit.c (TclpSetVariables):	Win-specific code not found
	* win/tclWinReg.c (AppendSystemError):	during earlier work on Unix.

2007-05-04  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclIO.c (TclFinalizeIOSubsystem): Added an initializer to
	silence a spurious gcc warning about use of an uninitialized
	variable.
	* tests/encoding.test: Modified so that encoding tests happen in a
	private namespace, to avoid polluting the global one. This problem was
	discovered when running the test suite '-singleproc 1 -skip exec.test'
	because the 'path' variable in encoding.test conflicted with the one
	in io.test.
	* tests/io.test: Made more of the working variables private to the
	namespace.

2007-05-02  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclTest.c (SimpleMatchInDirectory): Corrected a refcount
	imbalance that affected the filesystem-[147]* tests in the test suite.
	Thanks to Don Porter for the patch. [Bug 1710707]
	* generic/tclPathObj.c (Tcl_FSJoinPath, Tcl_FSGetNormalizedPath):
	Corrected several memory leaks that caused refcount imbalances
	resulting in memory leaks on Windows. Thanks to Joe Mistachkin for the
	patch.

2007-05-01  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclVar.c (TclPtrSetVar): fixed leak whenever newvaluePtr had
	refCount 0 and was used for appending (but not lappending). Thanks to
	mistachkin and kbk. [Bug 1710710]

2007-05-01  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclIO.c (DeleteChannelTable): Made changes so that
	DeleteChannelTable tries to close all open channels, not just the
	first. [Bug 1710285]
	* generic/tclThread.c (TclFinalizeSynchronization): Make sure that TSD
	blocks get freed on non-threaded builds. [Bug 1710825]
	* tests/utf.test (utf-25.1--utf-25.4): Modified tests to clean up
	after the 'testobj' extension to avoid spurious reports of memory
	leaks.

2007-05-01  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCmdMZ.c (STR_MAP): When [string map] has a pure dict map,
	a missing Tcl_DictObjDone() call led to a memleak. [Bug 1710709]

2007-04-30  Daniel Steffen  <das@users.sourceforge.net>

	* unix/Makefile.in: add 'tclsh' dependency to install targets that
	rely on tclsh, fixes parallel 'make install' from empty build dir.

2007-04-30  Andreas Kupries <andreask@gactivestate.com>

	* generic/tclIO.c (FixLevelCode): Corrected reference count
	mismanagement of newlevel, newcode. Changed to allocate the Tcl_Obj's
	as late as possible, and only when actually needed. [Bug 1705778, leak
	K29]

2007-04-30  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclProc.c (Tcl_ProcObjCmd, SetLambdaFromAny): Corrected
	reference count mismanagement on the name of the source file in the
	TIP 280 code. [Bug 1705778, leak K02 among other manifestations]

2007-04-25  Donal K. Fellows  <dkf@users.sf.net>

	*** 8.5a6 TAGGED FOR RELEASE ***

	* generic/tclProc.c (TclObjInterpProcCore): Only allocate objects for
	error message generation when associated with argument names that are
	really used. [Bug 1705778, leak K15]

2007-04-25  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclIOUtil.c (Tcl_FSChdir): Changed the memory management so
	that the path returned from Tcl_FSGetNativePath is not duplicated
	before being stored as the current directory, to avoid a memory leak.
	[Bug 1705778, leak K01 among other manifestations]

2007-04-25  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c (ParseExpr):	Revised to be sure that an
	error return doesn't prevent all literals getting placed on the
	litList to be returned to the caller for freeing. Corrects some
	memleaks. [Bug 1705778, leak K23]

2007-04-25  Daniel Steffen  <das@users.sourceforge.net>

	* unix/Makefile.in (dist): add macosx/*.xcconfig files to src dist;
	copy license.terms to dist macosx dir; fix autoheader bits.

2007-04-24  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclListObj.c: reverting [Patch 738900] (committed on
	2007-04-20). Causes some Tk test breakage of unknown importance, but
	the impact of the patch itself is likely to be so small that it does
	not warrant investigation at this time.

2007-04-24  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclDictObj.c (DictKeysCmd): Rewrote so that the lock on the
	internal representation of a dict is only set when necessary. [Bug
	1705778, leak K04]
	(DictFilterCmd): Added code to drop the lock in the trivial match
	case. [Bug 1705778, leak K05]

2007-04-24  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclBinary.c: Addressed several code paths where the error
	return from the 'binary format' command leaked the result buffer.
	* generic/tclListObj.c (TclLsetFlat): Fixed a bug where the new list
	under construction was leaked in the error case. [Bug 1705778, leaks
	K13 and K14]

2007-04-24  Jeff Hobbs	<jeffh@ActiveState.com>

	* unix/Makefile.in (dist): add platform library package to src dist

2007-04-24  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c (ParseExpr): Memory leak in error case; the
	literal Tcl_Obj was not getting freed. [Bug 1705778, leak #1 (new)]

	* generic/tclNamesp.c (Tcl_DeleteNamespace):	Corrected flaw in the
	flag marking scheme to be sure that global namespaces are freed when
	their interp is deleted. [Bug 1705778]

2007-04-24  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclExecute.c (TclExecuteByteCode): Plugged six memory leaks
	in bignum arithmetic.
	* generic/tclIOCmd.c (Tcl_ReadObjCmd): Plugged a leak of the buffer
	object if the physical read returned an error and the bypass area had
	no message.
	* generic/tclIORChan.c (TclChanCreateObjCmd): Plugged a leak of the
	return value from the "initialize" method of a channel handler.
	(All of the above under [Bug 1705778])

2007-04-23  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclCkalloc.c: fix warnings from gcc build configured with
	* generic/tclCompile.c: --enable-64bit --enable-symbols=all.
	* generic/tclExecute.c:

	* unix/tclUnixFCmd.c: add workaround for crashing bug in fts_open()
	* unix/tclUnixInit.c: without FTS_NOSTAT on 64bit Darwin 8 or earlier.

	* unix/tclLoadDyld.c (TclpLoadMemory): fix (void*) arithmetic.

	* macosx/Tcl-Common.xcconfig: enable more warnings.

	* macosx/Tcl.xcodeproj/project.pbxproj: add 'DebugMemCompile' build
	configuration that calls configure with --enable-symbols=all; override
	configure check for __attribute__((__visibility__("hidden"))) in Debug
	configuration to restore availability of ZeroLink.

	* macosx/tclMacOSXNotify.c: fix warnings.

	* macosx/tclMacOSXFCmd.c: const fixes.

	* macosx/Tcl-Common.xcconfig:	fix whitespace.
	* macosx/Tcl-Debug.xcconfig:
	* macosx/Tcl-Release.xcconfig:
	* macosx/README:

	* macosx/GNUmakefile:		fix/add copyright and license refs.
	* macosx/tclMacOSXBundle.c:
	* macosx/Tcl-Info.plist.in:
	* macosx/Tcl.xcode/project.pbxproj:
	* macosx/Tcl.xcodeproj/project.pbxproj:

	* unix/configure.in: install license.terms into Tcl.framework.
	* unix/configure: autoconf-2.59

2007-04-23  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclVar.c (UnsetVarStruct):	Make sure the
	TCL_INTERP_DESTROYED flags gets passed to unset trace routines so they
	can respond appropriately. [Bug 1705778, leak #9]

2007-04-23  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompile.c (TclFreeCompileEnv): Tip 280's new field
	extCmdMapPtr was not being freed. [Bug 1705778, leak #1]

2007-04-23  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclCompCmds.c (TclCompileUpvarCmd): Plugged a memory leak in
	'upvar' when compiling (a) upvar outside a proc, (b) upvar with a
	syntax error, or (c) upvar where the frame index is not known at
	compile time.
	* generic/tclCompExpr.c (ParseExpr): Plugged a memory leak when
	parsing expressions that contain syntax errors.
	* generic/tclEnv.c (ReplaceString): Clear memory correctly when
	growing the cache to avoid reads of uninitialised data.
	* generic/tclIORChan.c (TclChanCreateObjCmd, FreeReflectedChannel):
	Plugged two memory leaks.
	* generic/tclStrToD.c (AccumulateDecimalDigit): Fixed a mistake where
	we'd run beyond the end of the 'pow10_wide' array if a number begins
	with a string of more than 'maxpow10_wide' zeroes.
	* generic/tclTest.c (Testregexpobjcmd): Removed an invalid access
	beyond the end of 'objv' in 'testregexp -about'.
	All of these issues reported under [Bug 1705778] - detected with the
	existing test suite, no new regression tests required.

2007-04-22  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclVar.c (TclDeleteNamespaceVars): fixed access to freed
	memory detected by valgrind: Tcl_GetCurrentNamespace was being
	called after freeing root CallFrame (on interp deletion).

2007-04-20  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclListObj.c (SetListFromAny): avoid discarding internal
	reps of objects converted to singleton lists. [Patch 738900]

2007-04-20  Kevin B. Kenny  <kennykb@acm.org>

	* doc/clock.n: Corrected a silly error (transposed 'uppercase' and
	'lowercase' in clock.n. [Bug 1656002]
	Clarified that [clock scan] does not recognize a locale's alternative
	calendar.
	Deleted an entirely superfluous (and also incorrect) remark about the
	effect of Daylight Saving Time on relative times in [clock scan]. [Bug
	1582951]
	* library/clock.tcl: Corrected an error in skipping over the %Ey field
	on input.
	* library/msgs/ja.msg:
	* tools/loadICU.tcl: Corrected several localisation faults in the
	Japanese locale (most notably, incorrect dates for the Emperors'
	eras). Many thanks to SourceForge user 'nyademo' for pointing this out
	and developing a fix. [Bug 1637471]
	* generic/tclPathObj.c: Corrected a 'const'ness fault that caused
	bitter complaints from MSVC.
	* tests/clock.test (clock-40.1, clock-58.1, clock-59.1): Corrected a
	test case that depended on ":localtime" being able to handle dates
	prior to the Posix epoch. [Bug 1618445] Added a test case for the
	dates of the Japanese emperors. [Bug 1637471] Added a regression test
	for military time zone input conversion. [Bug 1586828]
	* generic/tclGetDate.y (MilitaryTable): Fixed an ancient bug where the
	military NZA time zones had the signs reversed. [Bug 1586828]
	* generic/tclDate.c: Regenerated.
	* doc/Notifier.3: Documented Tcl_SetNotifier and Tcl_ServiceModeHook.
	Quite against my better judgment. [Bug 414933]
	* generic/tclBasic.c, generic/tclCkalloc.c, generic/tclClock.c:
	* generic/tclCmdIL.c, generic/tclCmdMZ.c, generic/tclFCmd.c:
	* generic/tclFileName.c, generic/tclInterp.c, generic/tclIO.c:
	* generic/tclIOUtil.c, generic/tclNamesp.c, generic/tclObj.c:
	* generic/tclPathObj.c, generic/tclPipe.c, generic/tclPkg.c:
	* generic/tclResult.c, generic/tclTest.c, generic/tclTestObj.c:
	* generic/tclVar.c, unix/tclUnixChan.c, unix/tclUnixTest.c:
	* win/tclWinLoad.c, win/tclWinSerial.c: Replaced commas in varargs
	with string concatenation where possible. [Patch 1515234]
	* library/tzdata/America/Tegucigalpa:
	* library/tzdata/Asia/Damascus: Olson's tzdata 2007e.

2007-04-19  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/regcomp.c, generic/regc_cvec.c, generic/regc_lex.c,
	* generic/regc_locale.c: Improve the const-correctness of the RE
	compiler.

2007-04-18  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c (INST_LSHIFT): fixed a mistake introduced in
	version 1.266 ('=' became '=='), which effectively turned the block
	that handles native shifts into dead code. This explains why the
	testsuite did not pick this mistake. Rewrote to make the intention
	clear.

	* generic/tclInt.h (TclDecrRefCount): change the order of the
	branches, use empty 'if ; else' to handle use in unbraced outer
	if/else conditions (as already done in tcl.h)

	* generic/tclExecute.c: slight changes in Tcl_Obj management.

2007-04-17  Kevin B. Kenny  <kennykb@acm.org>

	* library/clock.tcl: Fixed the naming of
	::tcl::clock::ReadZoneinfoFile because (yoicks!) it was in the global
	namespace.
	* doc/clock.n: Clarified the cases in which legacy time zone is
	recognized. [Bug 1656002]

2007-04-17  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: fixed checkInterp logic [Bug 1702212]

2007-04-16  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* various (including generic/tclTest.c): Complete the purge of K&R
	function definitions from manually-written code.

2007-04-15  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclCompCmds.c: added a cast to silence a compiler error on
	VC2005.
	* library/clock.tcl: Restored unique-prefix matching of keywords on
	the [clock] command. [Bug 1690041]
	* tests/clock.test: Added rudimentary test cases for unique-prefix
	matching of keywords.

2007-04-14  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: removed some code at INST_EXPAND_SKTOP that
	duplicates functionality already present at checkForCatch.

2007-04-12  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: new macros OBJ_AT_TOS, OBJ_UNDER_TOS,
	OBJ_AT_DEPTH(n) and CURR_DEPTH that remove all direct references to
	tosPtr from TEBC (after initialisation and the code at the label
	cleanupV_pushObjResultPtr).

2007-04-11  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompCmds.c: moved all exceptDepth management to the
	macros - the decreasing half was managed by hand.

2007-04-10  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclInt.h (TclNewLiteralStringObj): New macro to make
	allocating literal string objects (i.e. objects whose value is a
	constant string) easier and more efficient, by allowing the omission
	of the length argument. Based on [Patch 1529526] (afredd)
	* generic/*.c: Make use of this (in many files).

2007-04-08  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompile (tclInstructionTable): Fixed bugs in description
	of dict instructions.

2007-04-07  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompile (tclInstructionTable): Fixed bug in description
	of INST_START_COMMAND.

	* generic/tclExecute.c (TEBC): Small code reduction.

2007-04-06  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c (TEBC):
	* generic/tclNamespace.c (NsEnsembleImplementationCmd):
	* generic/tclProc.c (InitCompiledLocals, ObjInterpProcEx)
	(TclObjInterpProcCore, ProcCompileProc): Code reordering to reduce
	branching and improve branch prediction (assume that forward branches
	are typically not taken).

2007-04-03  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: INST_INVOKE optimisation. [Patch 1693802]

2007-04-03  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclNamesp.c:	Revised ErrorCodeRead and ErrorInfoRead trace
	routines so they guarantee the ::errorCode and ::errorInfo variable
	always appear to exist. [Bug 1693252]

2007-04-03  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclInt.decls:	 Moved TclGetNamespaceFromObj() to the
	* generic/tclInt.h:	 internal stubs table; regen.
	* generic/tclIntDecls.h:
	* generic/tclStubInit.c:

2007-04-02  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:	  Added bytecode compilers for the variable
	* generic/tclCompCmds.c:  linking commands: 'global', 'variable',
	* generic/tclCompile.h:	  'upvar', 'namespace upvar' [Patch 1688593]
	* generic/tclExecute.c:
	* generic/tclInt.h:
	* generic/tclVar.c:

2007-04-02  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Replace arrays on the C stack and ckalloc
	* generic/tclExecute.c: calls with TclStackAlloc calls to use memory
	* generic/tclFCmd.c:	on Tcl's evaluation stack.
	* generic/tclFileName.c:
	* generic/tclIOCmd.c:
	* generic/tclIndexObj.c:
	* generic/tclInterp.c:
	* generic/tclNamesp.c:
	* generic/tclTrace.c:
	* unix/tclUnixPipe.c:

2007-04-01  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompile.c (TclCompileScript, TclPrintInstruction):
	* generic/tclExecute.c (TclExecuteByteCode): Changed the definition of
	INST_START_CMD so that it knows how many commands start at the current
	location. This makes the interpreter command counter correct without
	requiring a large number of instructions to be issued. (See my change
	from 2007-01-19 for what triggered this.)

2007-03-30  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompile.c:
	* generic/tclCompExpr.c:
	* generic/tclCompCmds.c:	Replace arrays on the C stack and
	ckalloc calls with TclStackAlloc calls to use memory on Tcl's
	evaluation stack.

	* generic/tclCmdMZ.c:	Revised [string to* $s $first $last]
	implementation to reduce number of allocs/copies.

	* tests/string.test:  More [string reverse] tests.

2007-03-30  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: optimise the lookup of elements of indexed
	arrays.

2007-03-29  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclProc.c (Tcl_ApplyObjCmd):
	* tests/apply.test (9.3): Fixed Tcl_Obj leak on error return; an
	unneeded ref to lambdaPtr was being set and not released on an error
	return path.

2007-03-28  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCmdMZ.c (STR_REVERSE):	Implement the actual [string
	reverse] command in terms of the new TclStringObjReverse() routine.

	* generic/tclInt.h (TclStringObjReverse):	New internal routine
	* generic/tclStringObj.c (TclStringObjReverse): that implements the
	[string reverse] operation, making use of knowledge/surgery of the
	String intrep to minimize the number of allocs and copies needed to do
	the job.

2007-03-27  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCmdMZ.c (STR_MAP): Replace ckalloc calls with
	TclStackAlloc calls.

2007-03-24  Zoran Vasiljevic <vasiljevic@users.sourceforge.net>

	* win/tclWinThrd.c: Thread exit handler marks the current thread as
	un-initialized. This allows exit handlers that are registered later to
	re-initialize this subsystem in case they need to use some sync
	primitives (cond variables) from this file again.

2007-03-23  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c (DeleteInterpProc): pop the root frame pointer
	before deleting the global namespace [Bug 1658572]

2007-03-23  Kevin B. Kenny  <kennykb@acm.org>

	* win/Makefile.in: Added code to keep a Cygwin path name from leaking
	into LIBRARY_DIR when doing 'make test' or 'make runtest'.

2007-03-22  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCmdAH.c (Tcl_ForeachObjCmd):	Replaced arrays on the
	C stack and ckalloc calls with TclStackAlloc calls to use memory on
	Tcl's evaluation stack.

	* generic/tclExecute.c: Revised GrowEvaluationStack to take an
	argument specifying the growth required by the caller, so that a
	single reallocation / copy is the most that will ever be needed even
	when required growth is large.

2007-03-21  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c: More ckalloc -> ckrealloc conversions.
	* generic/tclLiteral.c:
	* generic/tclNamesp.c:
	* generic/tclParse.c:
	* generic/tclPreserve.c:
	* generic/tclStringObj.c:
	* generic/tclUtil.c:

2007-03-20  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclEnv.c:	Some more ckalloc -> ckrealloc replacements.
	* generic/tclLink.c:

2007-03-20  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclDate.c: Rebuilt, despite Donal Fellows's comment when
	committing it that no rebuild was required.
	* generic/tclGetDate.y: According to Donal Fellows, "Introduce modern
	formatting standards; no need for rebuild of tclDate.c."

	* library/tzdata/America/Cambridge_Bay:
	* library/tzdata/America/Havana:
	* library/tzdata/America/Inuvik:
	* library/tzdata/America/Iqaluit:
	* library/tzdata/America/Pangnirtung:
	* library/tzdata/America/Rankin_Inlet:
	* library/tzdata/America/Resolute:
	* library/tzdata/America/Yellowknife:
	* library/tzdata/Asia/Choibalsan:
	* library/tzdata/Asia/Dili:
	* library/tzdata/Asia/Hovd:
	* library/tzdata/Asia/Jakarta:
	* library/tzdata/Asia/Jayapura:
	* library/tzdata/Asia/Makassar:
	* library/tzdata/Asia/Pontianak:
	* library/tzdata/Asia/Ulaanbaatar:
	* library/tzdata/Europe/Istanbul: Upgraded to Olson's tzdata2007d.

	* generic/tclListObj.c (TclLsetList, TclLsetFlat):
	* tests/lset.test: Changes to deal with shared internal representation
	for lists passed to the [lset] command. Thanks to Don Porter for
	fixing this issue. [Bug 1677512]

2007-03-19  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompile.c: Revise the various expansion routines for
	CompileEnv fields to use ckrealloc() where appropriate.

	* generic/tclBinary.c (Tcl_SetByteArrayLength): Replaced ckalloc() /
	memcpy() sequence with ckrealloc() call.

	* generic/tclBasic.c (Tcl_CreateMathFunc):	Replaced some calls to
	* generic/tclEvent.c (Tcl_CreateThread):	Tcl_Alloc() with calls
	* generic/tclObj.c (UpdateStringOfBignum):	to ckalloc(), which
	* unix/tclUnixTime.c (SetTZIfNecessary):	better supports memory
	* win/tclAppInit.c (setargv):			debugging.

2007-03-19  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* doc/regsub.n: Corrected example so that it doesn't recommend
	potentially unsafe practice. Many thanks to Konstantin Kushnir
	<chpock@gmail.com> for reporting this.

2007-03-17  Kevin B. Kenny  <kennykb@acm.org>

	* win/tclWinReg.c (GetKeyNames): Size the buffer for enumerating key
	names correctly, so that Unicode names exceeding 127 chars can be
	retrieved without crashing. [Bug 1682211]
	* tests/registry.test (registry-4.9): Added test case for the above
	bug.

2007-03-15  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tclIOUtil.c (Tcl_Stat): Reimplement workaround to avoid gcc
	warning by using local variables. When the macro argument is of type
	long long instead of long, the incorrect warning is not generated.

2007-03-15  Mo DeJong  <mdejong@users.sourceforge.net>

	* win/Makefile.in: Fully qualify LIBRARY_DIR so that `make test` does
	not depend on working dir.

2007-03-15  Mo DeJong  <mdejong@users.sourceforge.net>

	* tests/parse.test: Add two backslash newline parse tests.

2007-03-12  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c (INST_FOREACH_STEP4):	Make private copy of
	* tests/foreach.test (foreach-10.1):	value list to be assigned to
	variables so that shimmering of that list doesn't lead to invalid
	pointers. [Bug 1671087]

	* generic/tclEvent.c (HandleBgErrors):	Make efficient private copy
	* tests/event.test (event-5.3): of the command prefix for the interp's
	background error handling command to avoid panics due to pointers to
	memory invalid after shimmering. [Bug 1670155]

	* generic/tclNamesp.c (NsEnsembleImplementationCmd):	Make efficient
	* tests/namespace.test (namespace-42.8):	private copy of the
	command prefix as we invoke the command appropriate to a particular
	subcommand of a particular ensemble to avoid panic due to shimmering
	of the List intrep. [Bug 1670091]

	* generic/tclVar.c (TclArraySet):	Make efficient private copy of
	* tests/var.test (var-17.1):	the "list" argument to [array set] to
	avoid crash due to shimmering invalidating pointers. [Bug 1669489]

2007-03-12  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclCmdIL.c (Tcl_LsortObjCmd): Fix problems with declaration
	positioning and memory leaks. [Bug 1679072]

2007-03-11  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdIL.c (Tcl_LreverseObjCmd): Ensure that a list is
	correctly reversed even if its internal representation is shared
	without the object itself being shared. [Bug 1675044]

2007-03-10  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCmdIL (Tcl_LsortObjCmd): changed fix to [Bug 1675116] to
	use the cheaper TclListObjCopy() instead of Tcl_DuplicateObj().

2007-03-09  Andreas Kupries  <andreask@activestate.com>

	* library/platform/shell.tcl: Made more robust if an older platform
	* library/platform/pkgIndex.tcl: package is present in the inspected
	* unix/Makefile.in: shell. Package forget it to prevent errors. Bumped
	* win/Makefile.in: package version to 1.1.3, and updated the Makefiles
	installing it as Tcl Module.

2007-03-09  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclCmdIL.c (Tcl_LsortObjCmd): Handle tricky case with loss
	* tests/cmdIL.test (cmdIL-1.29):	of list rep during sorting due
	to shimmering. [Bug 1675116]

2007-03-09  Kevin B. Kenny  <kennykb@acm.org>

	* library/clock.tcl (ReadZoneinfoFile): Added Y2038 compliance to the
	code for version-2 'zoneinfo' files.
	* tests/clock.test (clock-56.3): Added a test case for Y2038 and
	'zoneinfo'. Modified test initialisation to use the
	'loadTestedCommands' function of tcltest to bring in the correct path
	for the registry library.

2007-03-08  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclListObj.c (TclLsetList):	Rewrite so that the routine
	itself does not do any direct intrep surgery. Better isolates those
	things into the implementation of the "list" Tcl_ObjType.

2007-03-08  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclListObj.c (TclLindexList, TclLindexFlat): Moved these
	functions to tclListObj.c from tclCmdIL.c to mirror the way that the
	equivalent functions for [lset]'s guts are arranged.

2007-03-08  Kevin B. Kenny  <kennykb@acm.org>

	* library/clock.tcl: Further tweaks to the Windows time zone table
	(restoring missing Mexican time zones). Added rudimentary handling of
	version-2 'zoneinfo' files. Update US DST rules so that zones such as
	'EST5EDT' get the correct transition dates.
	* tests/clock.test: Added rudimentary test cases for 'zoneinfo'
	parsing. Adjusted several tests that depended on obsolete US DST
	transition rules.

2007-03-07  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/tclMacOSXNotify.c: add spinlock debugging and sanity checks.

	* macosx/Tcl.xcodeproj/project.pbxproj: ensure gcc version used by
	* macosx/Tcl.xcodeproj/default.pbxuser: Xcode and configure/make are
	* macosx/Tcl-Common.xcconfig:		consistent and independent of
	gcc_select default and CC env var; fixes for Xcode 3.0.

	* unix/tcl.m4 (Darwin): s/CFLAGS/CPPFLAGS/ in macosx-version-min check
	* unix/configure: autoconf-2.59

2007-03-07  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCmdIL.c (TclLindex*):	Rewrites to make efficient
	private copies of the list and indexlist arguments, so we can operate
	on the list elements directly with no fear of shimmering effects.
	Replaces defensive coding schemes that are otherwise required. End
	result is that TclLindexList is entirely a wrapper around
	TclLindexFlat, which is now the core engine of all [lindex]
	operations.

	* generic/tclObj.c (Tcl_AppendAllObjTypes):	Converted to simpler
	list validity test.

2007-03-07  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclRegexp.c (TclRegAbout): Generate information about a
	regexp as a Tcl_Obj instead of as a string, which is more efficient.

2007-03-07  Kevin B. Kenny  <kennykb@acm.org>

	* library/clock.tcl: Adjusted Windows time zone table to handle new US
	DST rules by locale rather than as Posix time zone spec.
	* tests/clock.test (clock-39.6, clock-49.2, testclock::registry):
	Adjusted tests to simulate new US rules.
	* library/tzdata/America/Indiana/Winamac:
	* library/tzdata/Europe/Istanbul:
	* library/tzdata/Pacific/Easter:
	Olson's tzdata2007c.

2007-03-05  Andreas Kupries  <andreask@activestate.com>

	* library/platform/shell.tcl (::platform::shell::RUN): In the case of
	* library/platform/pkgIndex.tcl: a failure put the captured stderr
	* unix/Makefile.in: into the error message to aid in debugging. Bumped
	* win/Makefile.in: package version to 1.1.2, and updated the makefiles
	installing it as Tcl Module.

2007-03-03  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclLink.c (LinkedVar): Added macro to conceal at least some
	of the pointer hackery.

2007-03-02  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCmdIL.c (Tcl_LreverseObjCmd):	Added missing
	TclInvalidateStringRep() call when we directly manipulate the intrep
	of an unshared "list" Tcl_Obj. [Bug 1672585]

	* generic/tclCmdIL.c (Tcl_JoinObjCmd):	Revised [join] implementation
	to append Tcl_Obj's instead of strings. [RFE 1669420]

	* generic/tclCmdIL.c (Info*Cmd):	Code simplifications and
	optimizations.

2007-03-02  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclCompile.c (TclPrintInstruction): Added a scheme to allow
	* generic/tclCompile.h (AuxDataPrintProc):    aux-data to be printed
	* generic/tclCompCmds.c (Print*Info):	      out for debugging. For
	this to work, immediate operands referring to aux-data must be
	identified as such in the instruction descriptor table using
	OPERAND_AUX4 (all are always 4 bytes).

	* generic/tclExecute.c (TclExecuteByteCode): Rewrote the compiled
	* generic/tclCompCmds.c (TclCompileDictCmd): [dict update] so that it
	* generic/tclCompile.h (DictUpdateInfo):     stores critical
	* tests/dict.test (dict-21.{14,15}):	     non-varying data in an
	aux-data value instead of a (shimmerable) literal. [Bug 1671001]

2007-03-01  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCmdIL.c (Tcl_LinsertObjCmd):	Code simplifications
	and optimizations.

	* generic/tclCmdIL.c (Tcl_LreplaceObjCmd):	Code simplifications
	and optimizations.

	* generic/tclCmdIL.c (Tcl_LrangeObjCmd):	Rewrite in the same
	spirit; avoid shimmer effects rather than react to them.

	* generic/tclCmdAH.c (Tcl_ForeachObjCmd):	Stop throwing away
	* tests/foreach.test (foreach-1.14):	useful error information when
	loop variable sets fail.

	* generic/tclCmdIL.c (Tcl_LassignObjCmd):	Rewrite to make an
	efficient private copy of the list argument, so we can operate on the
	list elements directly with no fear of shimmering effects. Replaces
	defensive coding schemes that are otherwise required.

	* generic/tclCmdAH.c (Tcl_ForeachObjCmd):	Rewrite to make
	efficient private copies of the variable and value lists, so we can
	operate on them without any special shimmer defense coding schemes.

2007-03-01  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclCompCmds.c (TclCompileForeachCmd): Prevent an unexpected
	* tests/foreach.test (foreach-9.1):		infinite loop when the
	variable list is empty and the foreach is compiled. [Bug 1671138]

2007-02-26  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIORChan.c (FreeReflectedChannel): Added the missing
	refcount release between NewRC and FreeRC for the channel handle
	object, spotted by Don Porter. [Bug 1667990]

2007-02-26  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCmdAH.c (Tcl_ForeachObjCmd):	Removed surplus
	copying of the objv array that used to be a workaround for [Bug
	404865]. That bug is long fixed.

2007-02-24  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Use new interface in Tcl_EvalObjEx so that the
	recounting logic of the List internal rep need not be repeated there.
	Better encapsulation of internal details.

	* generic/tclInt.h:	New internal routine TclListObjCopy() used
	* generic/tclListObj.c: to efficiently do the equivalent of [lrange
	$list 0 end]. After some experience with this, might be a good
	candidate for exposure as a public interface. It's useful for callers
	of Tcl_ListObjGetElements() who want to control the ongoing validity
	of the returned objv pointer.

2007-02-22  Andreas Kupries  <andreask@activestate.com>

	* tests/pkg.test: Added tests for the case of an alpha package
	satisfying a require for the regular package, demonstrating a corner
	case specified in TIP#280. More notes in the comments to the test.

2007-02-20  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.decls: Added "const" specifiers in TclSockGetPort
	* generic/tclIntDecls.h: regenerated
	* generic/*.c:
	* unix/tclUnixChan.c
	* unix/tclUnixPipe.c
	* win/tclWinPipe.c
	* win/tclWinSock.c: Added many "const" specifiers in implementation.

2007-02-20  Don Porter	<dgp@users.sourceforge.net>

	* doc/tcltest.n:	Typo fix. [Bug 1663539]

2007-02-20  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* generic/tclFileName.c:  Handle extended paths on Windows NT and
	* generic/tclPathObj.c:	  above. These have a \\?\ prefix. [Bug
	* win/tclWinFile.c:	  1479814]
	* tests/winFCmd.test:	  Tests for extended path handling.

2007-02-19  Jeff Hobbs	<jeffh@ActiveState.com>

	* unix/tcl.m4: use SHLIB_SUFFIX=".so" on HP-UX ia64 arch.
	* unix/configure: autoconf-2.59

	* generic/tclIOUtil.c (Tcl_FSEvalFileEx): safe incr of objPtr ref.

2007-02-18  Donal K. Fellows  <dkf@users.sf.net>

	* doc/chan.n, doc/clock.n, doc/eval.n, doc/exit.n, doc/expr.n:
	* doc/interp.n, doc/open.n, doc/platform_shell.n, doc/pwd.n:
	* doc/refchan.n, doc/regsub.n, doc/scan.n, doc/tclvars.n, doc/tm.n:
	* doc/unload.n: Apply [Bug 1610310] to fix typos. Thanks to Larry
	Virden for spotting them.

	* doc/interp.n: Partial fix of [Bug 1662436]; rest requires some
	policy decisions on what should and shouldn't be safe commands from
	the "new in 8.5" set.

2007-02-13  Kevin B. Kenny  <kennykb@acm.org>

	* tools/fix_tommath_h.tcl: Further tweaking for the x86-64. The change
	is to make 'mp_digit' be an 'unsigned int' on that platform; since
	we're using only 32 bits of it, there's no reason to make it a 64-bit
	'unsigned long.'
	* generic/tclTomMath.h: Regenerated.

2007-02-13  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/re_syntax.n: Corrected description of 'print' class [Bug
	1614687] and enhanced description of 'graph' class.

2007-02-12  Kevin B. Kenny  <kennykb@acm.org>

	* tools/fix_tommath_h.tcl: Added code to patch out a check for
	__x86_64__ that caused Tommath to use __attributes(TI)__ for the
	mp_word type. Tetra-int's simply fail on too many gcc-glibc-OS
	combinations to be ready for shipment today, even if they work for
	some of us. This change allows reversion of das's change of 2006-08-18
	that accomplised the same thing on Darwin. [Bugs 1601380, 1603737,
	1609936, 1656265]
	* generic/tclTomMath.h: Regenerated.
	* library/tzdata/Africa/Asmara:
	* library/tzdata/Africa/Asmera:
	* library/tzdata/America/Nassau:
	* library/tzdata/Atlantic/Faeroe:
	* library/tzdata/Atlantic/Faroe:
	* library/tzdata/Australia/Eucla:
	* library/tzdata/Pacific/Easter: Rebuilt from Olson's tzdata2007b.

2007-02-09  Joe Mistachkin  <joe@mistachkin.com>

	* win/nmakehlp.c: Properly cleanup after nmakehlp, including the
	* win/makefile.vc: vcX0.pch file.

2007-02-08  Jeff Hobbs	<jeffh@ActiveState.com>

	* unix/tclUnixInit.c (TclpCheckStackSpace): do stack size checks with
	unsigned size_t to correctly validate stackSize in the 2^31+ range.
	[Bug 1654104]

2007-02-08  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclNamesp.c:	Corrected broken logic in Tcl_DeleteNamespace
	* tests/namespace.test: introduced in Patch 1577278 that caused
	[namespace delete ::] to be effective only at level #0. New test
	namespace-7.7 should prevent similar error in the future [Bug 1655305]

2007-02-06  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclNamesp.c:	Corrected broken implementation of the
	* tests/namespace.test: TclMatchIsTrivial optimization on [namespace
	children $namespace $pattern].

2007-02-04  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tcl.m4: use gcc4's __attribute__((__visibility__("hidden"))) if
	available to define MODULE_SCOPE effective on all platforms.
	* unix/configure.in: add caching to -pipe and zoneinfo checks.
	* unix/configure: autoconf-2.59
	* unix/tclConfig.h.in: autoheader-2.59

2007-02-03  Joe Mistachkin  <joe@mistachkin.com>

	* win/rules.vc: Fix platform specific file copy macros for downlevel
	Windows.

2007-01-29  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclResult.c: Added optimization case to TclTransferResult to
	cover common case where there's big savings over the fully general
	path. Thanks to Peter MacDonald. [Bug 1626518]

	* generic/tclLink.c:	Broken linked float logic corrected. Thanks to
	Andy Goth. [Bug 1602538]

	* doc/fcopy.n:	Typo fix. [Bug 1630627]

2007-01-28  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Tcl.xcodeproj/project.pbxproj:	  extract build settings that
	* macosx/Tcl.xcodeproj/default.pbxuser:	  were common to multiple
	* macosx/Tcl-Common.xcconfig (new file):  configurations into external
	* macosx/Tcl-Debug.xcconfig (new file):	  xcconfig files; add extra
	* macosx/Tcl-Release.xcconfig (new file): configurations for building
	with SDKs and 64bit; convert legacy jam-based 'Tcl' target to native
	target with single script phase; correct syntax of build setting
	references to use $() throughout.

	* macosx/README: document new Tcl.xcodeproj configurations; other
	minor updates/corrections.

	* generic/tcl.h: update location of version numbers in macosx files.

	* macosx/Tcl.xcode/project.pbxproj: restore 'tcltest' target to
	* macosx/Tcl.xcode/default.pbxuser: working order by replicating
	applicable changes to Tcl.xcodeproj since 2006-07-20.

2007-01-25  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tcl.m4: integrate CPPFLAGS into CFLAGS as late as possible and
	move (rather than duplicate) -isysroot flags from CFLAGS to CPPFLAGS
	to avoid errors about multiple -isysroot flags from some older gcc
	builds.

	* unix/configure: autoconf-2.59

2007-01-22  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* compat/memcmp.c (memcmp): Reworked so that arithmetic is never
	performed upon void pointers, since that is illegal. [Bug 1631017]

2007-01-19  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclCompile.c (TclCompileScript): Reduce the frequency with
	which we issue INST_START_CMD, making bytecode both more compact and
	somewhat faster. The optimized case is where we would otherwise be
	issuing a sequence of those instructions; in those cases, it is only
	ever the first one encountered that could possibly trigger.

2007-01-19  Joe Mistachkin  <joe@mistachkin.com>

	* tools/man2tcl.c: Include stdlib.h for exit() and improve comment
	detection.
	* win/nmakehlp.c: Update usage.
	* win/makefile.vc: Properly build man2tcl.c for MSVC8.

2007-01-19  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/tclMacOSXFCmd.c (TclMacOSXSetFileAttribute): on some versions
	of Mac OS X, truncate() fails on resource forks, in that case use
	open() with O_TRUNC instead.

	* macosx/tclMacOSXNotify.c: accommodate changes to prototypes of
	OSSpinLock(Un)Lock API.

	* macosx/Tcl.xcodeproj/project.pbxproj: ensure HOME and USER env vars
	* macosx/Tcl.xcodeproj/default.pbxuser: are defined when running
						testsuite from Xcode.

	* tests/env.test: add extra system env vars that need to be preserved
	on some Mac OS X versions for testsuite to work.

	* unix/Makefile.in:  Move libtommath defines into configure.in to
	* unix/configure.in: avoid replicating them across multiple
	* macosx/Tcl.xcodeproj/project.pbxproj: buildsystems.

	* unix/tcl.m4: ensure CPPFLAGS env var is used when set. [Bug 1586861]
	(Darwin): add -isysroot and -mmacosx-version-min flags to CPPFLAGS
	when present in CFLAGS to avoid discrepancies between what headers
	configure sees during preprocessing tests and compiling tests.

	* unix/configure: autoconf-2.59
	* unix/tclConfig.h.in: autoheader-2.59

2007-01-18  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclCompile.c (TclCompileScript): Make sure that when parsing
	an expanded literal fails, a correct bytecode sequence is still
	issued. [Bug 1638414]. Also make sure that the start of the expansion
	bytecode sequence falls inside the span of bytecodes for a command.
	* tests/compile.test (compile-16.24): Added test for [Bug 1638414]

2007-01-17  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclIO.c: Added macros to make usage of ChannelBuffers
	clearer.

2007-01-11  Joe English	 <jenglish@users.sourceforge.net>

	* win/tcl.m4(CFLAGS_WARNING): Remove "-Wconversion". This was removed
	from unix/tcl.m4 2004-07-16 but not from here.
	* win/configure: Regenerated.

2007-01-11  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* win/makefile.vc: Fixes to work better on Win98. Read version numbers
	* win/nmakehlp.c:  from package index file to avoid keeping numbers in
	* win/rules.vc:	   the makefile where they may become de-synchronized.

2007-01-10  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/regcomp.c (compile, freev):	     Define a strategy for
	* generic/regexec.c (exec):		     managing the internal
	* generic/regguts.h (AllocVars, FreeVars):   vars of the RE engine to
	* generic/regcustom.h (AllocVars, FreeVars): reduce C stack usage.
	This will make Tcl as a whole much less likely to run out of stack
	space...

2007-01-09  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclCompCmds.c (TclCompileLindexCmd):
	* tests/lindex.test (lindex-9.2): Fix silly bug that ended up
	sometimes compiling list arguments in the wrong order. [Bug 1631364]

2007-01-03  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclDate.c: Regenerated to recover a lost fix from patthoyts.
	[Bug 1618523]

2006-12-26  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tclIO.c (Tcl_GetsObj): Avoid checking for for the LF in a
	possible CRLF sequence when EOF has already been found.

2006-12-26  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tclEncoding.c (EscapeFromUtfProc): Clear the
	TCL_ENCODING_END flag when end bytes are written. This fix keep this
	method from writing escape bytes for an encoding like iso2022-jp
	multiple times when the escape byte overlap with the end of the IO
	buffer.
	* tests/io.test: Add test for escape byte overlap issue.

2006-12-19  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* unix/tclUnixThrd.c (Tcl_GetAllocMutex, TclpNewAllocMutex): Add
	intermediate variables to shut up unwanted warnings. [Bug 1618838]

2006-12-19  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tclUnixThrd.c (TclpInetNtoa): fix for 64 bit.

	* unix/tcl.m4 (Darwin): --enable-64bit: verify linking with 64bit
	-arch flag succeeds before enabling 64bit build.
	* unix/configure: autoconf-2.59

2006-12-17  Daniel Steffen  <das@users.sourceforge.net>

	* tests/macOSXLoad.test (new file): add testing of .bundle loading and
	* tests/load.test:		    unloading on Darwin (in addition
	* tests/unload.test:		    to existing tests of .dylib
	loading).
	* macosx/Tcl.xcodeproj/project.pbxproj: add building of dltest
	binaries so that testsuite run from Xcode can use them; fix testsuite
	run script
	* unix/configure.in:	   add support for building dltest binaries as
	* unix/dltest/Makefile.in: .bundle (in addition to .dylib) on Darwin.
	* unix/Makefile.in: add stub lib dependency to dltest target.
	* unix/configure: autoconf-2.59

	* tests/append.test: fix cleanup failure when all tests are skipped.

	* tests/chan.test (chan-16.9): cleanup chan event handler to avoid
	causing error in event.test when running testsuite with -singleproc 1.

	* tests/info.test: add !singleTestInterp constraint to tests that fail
	when running testsuite with -singleproc 1. [Bug 1605269]

2006-12-14  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* doc/string.n: Fix example. [Bug 1615277]

2006-12-12  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c:	Now that the new internal structs are
	in use to support operator commands, might as well make them the
	default for [expr] as well and avoid passing every parsed expression
	through the inefficient Tcl_Token array format. This addresses most
	issues in [RFE 1517602]. Assuming no performance disasters result from
	this, much dead code supporting the other implementation might now be
	removed.

	* generic/tclBasic.c:	Final step routing all direct evaluation forms
	* generic/tclCompExpr.c: of the operator commands through TEBC,
	* generic/tclCompile.h: dropping all the routines in tclMathOp.c.
	* generic/tclMathOp.c:	Still needs Engineering Manual attention.

2006-12-11  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Another step with all sorting operator
	* generic/tclCompExpr.c: commands now routing through TEBC via
	* generic/tclCompile.h: TclSortingOpCmd().

2006-12-08  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	 Another step down the path of re-using
	* generic/tclCompExpr.c: TclExecuteByteCode to implement the TIP 174
	* generic/tclCompile.h: commands instead of using a mass of code
	* generic/tclMathOp.c:	duplication. Now all operator commands that
	* tests/mathop.test:	demand exactly one operation are implemented
	via TclSingleOpCmd and a call to TEBC.

	* generic/tclCompExpr.c: Revised implementation of TclInvertOpCmd to
	* generic/tclMathOp.c:	perform a bytecode compile / execute sequence.
	This demonstrates a path toward avoiding mountains of code duplication
	in tclMathOp.c and tclExecute.c.

	* generic/tclCompile.h: Change TclExecuteByteCode() from static to
	* generic/tclExecute.c: MODULE_SCOPE so all files including
	tclCompile.h may call it.

	* generic/tclMathOp.c:	More revisions to make tests pass.
	* tests/mathop.test:

2006-12-08  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclNamesp.c (TclTeardownNamespace): Ensure that dying
	namespaces unstitch themselves from their referents. [Bug 1571056]
	(NsEnsembleImplementationCmd): Silence GCC warning.

	* tests/mathop.test: Full tests for & | and ^ operators

2006-12-08  Daniel Steffen  <das@users.sourceforge.net>

	* library/tcltest/tcltest.tcl: use [info frame] for "-verbose line".

2006-12-07  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompCmds.c:	Additional commits correct most
	* generic/tclExecute.c:		failing tests illustrating bugs
	* generic/tclMathOp.c:		uncovered in [Patch 1578137].

	* generic/tclBasic.c:	Biggest source of TIP 174 failures was that
	the commands were not [namespace export]ed from the ::tcl::mathop
	namespace. More bits from [Patch 1578137] correct that.

	* tests/mathop.test:	Commmitted several new tests from Peter Spjuth
	found in [Patch 1578137]. Many failures now demonstrate issues to fix
	in the TIP 174 implementation.

2006-12-07  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* tests/mathop.test: Added tests for ! ~ eq operators.
	* generic/tclMathOp.c (TclInvertOpCmd): Add in check for non-integral
	numeric values.
	* generic/tclCompCmds.c (CompileCompareOpCmd): Factor out the code
	generation for the chained comparison operators.

2006-12-07  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* tests/exec.test: Fixed line endings (caused win32 problems).

2006-12-06  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompCmds.c:	Revised and consolidated into utility
	* tests/mathop.test:		routines some of routines that compile
	the new TIP 174 commands. This corrects some known bugs. More to come.

2006-12-06  Kevin B. Kenny  <kennykb@acm.org>

	* tests/expr.test (expr-47.12): Improved error reporting in hopes of
	having more information to pursue [Bug 1609936].

2006-12-05  Andreas Kupries  <andreask@activestate.com>

	TIP#291 IMPLEMENTATION

	* generic/tclBasic.c: Define tcl_platform element for pointerSize.
	* doc/tclvars.n:

	* win/Makefile.in: Added installation instructions for the platform
	* win/makefile.vc: package. Added the platform package.
	* win/makefile.bc:
	* unix/Makefile.in:

	* tests/platform.test:
	* tests/safe.test:

	* library/platform/platform.tcl:
	* library/platform/shell.tcl:
	* library/platform/pkgIndex.tcl:

	* doc/platform.n:
	* doc/platform_shell.n:

2006-12-05  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclPkg.c:	When no requirements are supplied to a
	* tests/pkg.test:	[package require $pkg] and [package unknown]
	is invoked to find a satisfying package, pass the requirement argument
	"0-" (which means all versions are acceptable). This permits a
	registered [package unknown] command to call [package vsatisfies
	$testVersion {*}$args] without any special handling of the empty $args
	case. This fixes/avoids a bug in [::tcl::tm::UnknownHandler] that was
	causing old TM versions to be provided in preference to newer TM
	versions. Thanks to Julian Noble for discovering the issue.

2006-12-04  Donal K. Fellows  <dkf@users.sf.net>

	TIP#267 IMPLEMENTATION

	* generic/tclIOCmd.c (Tcl_ExecObjCmd): Added -ignorestderr option,
	* tests/exec.test, doc/exec.n:	       loosely from [Patch 1476191]

2006-12-04  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c:	Added implementation for the
	CompileExprTree() routine that can produce expression bytecode
	directly from internal structures with no need to pass through the
	Tcl_Token array representation. Still disabled by default. #undef
	USE_EXPR_TOKENS to try it out.

2006-12-03  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c:	Added expr parsing routines that
	produce a different set of internal structures representing the parsed
	expression, as well as routines that go on to convert those structures
	into the traditional Tcl_Token array format. Use of these routines is
	currently disabled. #undef PARSE_DIRECT_EXPR_TOKENS to enable them.
	These routines will only become really useful when more routines that
	compile directly from the new internal structures are completed.

2006-12-02  Donal K. Fellows  <dkf@users.sf.net>

	* doc/file.n: Clarification of [file pathtype] docs. [Bug 1606454]

2006-12-01  Kevin B. Kenny	 <kennykb@acm.org>

	* libtommath/bn_mp_add.c:	Corrected the effects of a
	* libtommath/bn_mp_div.c:	bollixed 'cvs merge' operation
	* libtommath/bncore.c:		that inadvertently committed some
	* libtommath/tommath_class.h:	half-developed code.

	TIP#299 IMPLEMENTATION

	* doc/mathfunc.n:	Added isqrt() function to docs
	* generic/tclBasic.c:	Added isqrt() math function (ExprIsqrtFunc)
	* tests/expr.test (expr-47.*): Added tests for isqrt()
	* tests/info.test (info-20.2): Added isqrt() to expected math funcs.

2006-12-01  Don Porter	<dgp@users.sourceforge.net>

	* tests/chan.test:	Correct timing sensitivity in new test. [Bug
	1606860]

	TIP#287 IMPLEMENTATION

	* doc/chan.n:		New subcommand [chan pending].
	* generic/tclBasic.c:	Thanks to Michael Cleverly for proposal
	* generic/tclInt.h:	and implementation.
	* generic/tclIOCmd.c:
	* library/init.tcl:
	* tests/chan.test:
	* tests/ioCmd.test:

	TIP#298 IMPLEMENTATION

	* generic/tcl.decls: Tcl_GetBignumAndClearObj -> Tcl_TakeBignumFromObj
	* generic/tclObj.c:

	* generic/tclDecls.h:	make genstubs
	* generic/tclStubInit.c:

	* generic/tclExecute.c: Update callers.
	* generic/tclMathOp.c:

2006-11-30  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata: Olson's tzdata2006p.
	* libtommath/bn_mp_sqrt.c: Fixed a bug where the initial approximation
	to the square root could be on the wrong side, causing failure of
	convergence.

2006-11-29  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c (Tcl_AppendObjToErrorInfo):  Added
	Tcl_DecrRefCount() on the objPtr argument to plug memory leaks. This
	makes the routine a consumer, which makes it easiest to use.

2006-11-28  Andreas Kupries  <andreask@activestate.com>

	* generic/tclBasic.c: TIP #280 implementation.
	* generic/tclCmdAH.c:
	* generic/tclCmdIL.c:
	* generic/tclCmdMZ.c:
	* generic/tclCompCmds.c:
	* generic/tclCompExpr.c:
	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c:
	* generic/tclIOUtil.c:
	* generic/tclInt.h:
	* generic/tclInterp.c:
	* generic/tclNamesp.c:
	* generic/tclObj.c:
	* generic/tclProc.c:
	* tests/compile.test:
	* tests/info.test:
	* tests/platform.test:
	* tests/safe.test:

2006-11-27  Kevin B. Kenny  <kennykb@acm.org>

	* unix/tclUnixChan.c (TclUnixWaitForFile):
	* tests/event.test (event-14.*): Corrected a bug where
	TclUnixWaitForFile would present select() with the wrong mask on an
	LP64 machine if a fd number exceeds 32. Thanks to Jean-Luc Fontaine
	for reporting and diagnosing. [Bug 1602208]

2006-11-27  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c (TclIncrObj):	Correct failure to detect
	floating-point increment values. Thanks to William Coleda [Bug
	1602991]

2006-11-26  Donal K. Fellows  <dkf@users.sf.net>

	* tests/mathop.test, doc/mathop.n: More bits and pieces of the TIP#174
	implementation. Note that the test suite is not yet complete.

2006-11-26  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tcl.m4 (Linux): --enable-64bit support.	[Patch 1597389]
	* unix/configure: autoconf-2.59			[Bug 1230558]

2006-11-25  Donal K. Fellows  <dkf@users.sf.net>

	TIP#174 IMPLEMENTATION

	* generic/tclMathOp.c (new file): Completed the implementation of the
	interpreted versions of all the tcl::mathop commands. Moved to a new
	file to make tclCompCmds.c more focused in purpose.

2006-11-23  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (Tcl*OpCmd, TclCompile*OpCmd):
	* generic/tclBasic.c (Tcl_CreateInterp): Partial implementation of
	TIP#174; the commands are compiled, but (mostly) not interpreted yet.

2006-11-22  Donal K. Fellows  <dkf@users.sf.net>

	TIP#269 IMPLEMENTATION

	* generic/tclCmdMZ.c (Tcl_StringObjCmd): Implementation of the [string
	* tests/string.test (string-25.*):	 is list] command, based on
	* doc/string.n:				 work by Joe Mistachkin, with
	enhancements by Donal Fellows for better failindex behaviour.

2006-11-22  Don Porter	<dgp@users.sourceforge.net>

	* tools/genWinImage.tcl (removed):	Removed two files used in
	* win/README.binary (removed):	production of binary distributions
	for Windows, a task we no longer perform. [Bug 1476980]
	* generic/tcl.h:	Remove mention of win/README.binary in comment

	* generic/tcl.h:	Moved TCL_REG_BOSONLY #define from tcl.h to
	* generic/tclInt.h:	tclInt.h. Only know user is Expect, which
	already #include's tclInt.h. No need to continue greater exposure.
	[Bug 926500]

2006-11-20  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclBasic.c (Tcl_CreateInterp, TclHideUnsafeCommands):
	* library/init.tcl: Refactored the [chan] command's guts so that it
	does not use aliases to global commands, making the code more robust.

2006-11-17  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c (INST_EXPON):	Corrected crash on
	[expr 2**(1<<63)]. Was operating on cleared bignum Tcl_Obj.

2006-11-16  Donal K. Fellows  <dkf@users.sf.net>

	* doc/apply.n, doc/chan.n: Added examples.

2006-11-15  Don Porter	<dgp@users.sourceforge.net>

	TIP#270 IMPLEMENTATION

	* generic/tcl.decls:		New public routines Tcl_ObjPrintf,
	* generic/tclStringObj.c:	Tcl_AppendObjToErrorInfo, Tcl_Format,
	* generic/tclInt.h:		Tcl_AppendLimitedToObj,
	Tcl_AppendFormatToObj and Tcl_AppendPrintfToObj. Former internal
	versions removed.

	* generic/tclDecls.h:		make genstubs
	* generic/tclStubInit.c:

	* generic/tclBasic.c:		Updated callers.
	* generic/tclCkalloc.c:
	* generic/tclCmdAH.c:
	* generic/tclCmdIL.c:
	* generic/tclCmdMZ.c:
	* generic/tclCompExpr.c:
	* generic/tclCompile.c:
	* generic/tclDictObj.c:
	* generic/tclExecute.c:
	* generic/tclIORChan.c:
	* generic/tclIOUtil.c:
	* generic/tclMain.c:
	* generic/tclNamesp.c:
	* generic/tclObj.c:
	* generic/tclPkg.c:
	* generic/tclProc.c:
	* generic/tclStrToD.c:
	* generic/tclTimer.c:
	* generic/tclUtil.c:
	* unix/tclUnixFCmd.c:

	* tools/genStubs.tcl:	Updated script to no longer produce the
	_ANSI_ARGS_ wrapper in generated declarations. Also revised to accept
	variadic prototypes with more than one fixed argument. (This is
	possible since TCL_VARARGS and its limitations are no longer in use).
	* generic/tcl.h:	Some reordering so that macro definitions do
	not interfere with the now _ANSI_ARGS_-less stub declarations.

	* generic/tclDecls.h:		make genstubs
	* generic/tclIntDecls.h:
	* generic/tclIntPlatDecls.h:
	* generic/tclPlatDecls.h:
	* generic/tclTomMathDecls.h:

2006-11-15  Donal K. Fellows  <dkf@users.sf.net>

	* doc/ChnlStack.3, doc/CrtObjCmd.3, doc/GetIndex.3, doc/OpenTcp.3:
	* doc/chan.n, doc/fconfigure.n, doc/fcopy.n, doc/foreach.n:
	* doc/history.n, doc/http.n, doc/library.n, doc/lindex.n:
	* doc/lrepeat.n, doc/lreverse.n, doc/pkgMkIndex.n, doc/re_syntax.n:
	Convert \fP to \fR so that man-page scrapers have an easier time.

2006-11-14  Don Porter	<dgp@users.sourceforge.net>

	TIP#261 IMPLEMENTATION

	* generic/tclNamesp.c:	[namespace import] with 0 arguments
	introspects the list of imported commands.

2006-11-13  Kevin B. Kenny  <kennykb@users.sourceforge.net>

	* generic/tclThreadStorage.c (Tcl_InitThreadStorage):
	(Tcl_FinalizeThreadStorage): Silence a compiler warning about
	presenting a volatile pointer to 'memset'.

2006-11-13  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclIO.c:	When [gets] on a binary channel needs to use
	the "iso8859-1" encoding, save a copy of that encoding per-thread to
	avoid repeated freeing and re-loading of it from the file system. This
	replaces the cached copy of this encoding that the platform
	initialization code used to keep in pre-8.5 releases.

2006-11-13  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclCompExpr.c:	Fix gcc warnings about 'cast to/from
	* generic/tclEncoding.c:	pointer from/to integer of different
	* generic/tclEvent.c:		size' on 64-bit platforms by casting
	* generic/tclExecute.c:		to intermediate types
	* generic/tclHash.c:		intptr_t/uintptr_t via new PTR2INT(),
	* generic/tclIO.c:		INT2PTR(), PTR2UINT() and UINT2PTR()
	* generic/tclInt.h:		macros. [Patch 1592791]
	* generic/tclProc.c:
	* generic/tclTest.c:
	* generic/tclThreadStorage.c:
	* generic/tclTimer.c:
	* generic/tclUtil.c:
	* unix/configure.in:
	* unix/tclUnixChan.c:
	* unix/tclUnixPipe.c:
	* unix/tclUnixPort.h:
	* unix/tclUnixTest.c:
	* unix/tclUnixThrd.c:

	* unix/configure: autoconf-2.59
	* unix/tclConfig.h.in: autoheader-2.59

2006-11-12  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclInt.h, generic/tclInt.decls: Transfer TclPtrMakeUpvar and
	TclObjLookupVar to the internal stubs table.

2006-11-10  Daniel Steffen  <das@users.sourceforge.net>

	* tests/fCmd.test (fCmd-6.26): fix failure when env(HOME) path
	contains symlinks.

	* macosx/Tcl.xcodeproj/project.pbxproj: remove tclParseExpr.c; when
	running testsuite from inside Xcdoe, skip stack-3.1 (it only fails
	under those circumstances).

	* unix/tcl.m4 (Darwin): suppress linker arch warnings when building
	universal for both 32 & 64 bit and no 64bit CoreFoundation is
	available; sync with tk tcl.m4 change.
	* unix/configure.in: whitespace.
	* unix/configure: autoconf-2.59

2006-11-09  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclParseExpr.c (removed):	Moved all the code of
	* generic/tclCompExpr.c:	tclParseExpr.c into tclCompExpr.c.
	* unix/Makefile.in:	This sets the stage for expr compiling to work
	* win/Makefile.in:	directly with the full parse tree structures,
	* win/makefile.bc:	and not have to pass through the information
	* win/makefile.vc:	lossy format of an array of Tcl_Tokens.
	* win/tcl.dsp:

2006-11-09  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	TIP#272 IMPLEMENTATION

	* generic/tclCmdMZ.c (Tcl_StringObjCmd):    Implementation of the
	* tests/string.test, tests/stringComp.test: [string reverse] command
	* doc/string.n:				    from TIP#272.

	* generic/tclCmdIL.c (Tcl_LreverseObjCmd): Implementation of the
	* generic/tclBasic.c, generic/tclInt.h:	   [lreverse] command from
	* tests/cmdIL.test (cmdIL-7.*):		   TIP#272.
	* doc/lreverse.n:

2006-11-08  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclIO.c, generic/tclPkg.c: Style & clarity rewrites.

2006-11-07  Andreas Kupries  <andreask@activestate.com>

	* unix/tclUnixFCmd.c (CopyFile): Added code to fall back to a
	hardwired default block size should the filesystem report a bogus
	value. [Bug 1586470]

2006-11-04  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclStringObj.c:	Changed Tcl_ObjPrintf() response to an
	invalid format specifier string. No longer panics; now produces an
	error message as output.

	TIP#274 IMPLEMENTATION

	* generic/tclParseExpr.c:	Exponentiation operator is now right
	* tests/expr.test:		associative. [Patch 1556802]

2006-11-03  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c (TEOVI): fix por possible leak of a Command in
	the presence of execution traces that delete it.

	* generic/tclBasic.c (TEOVI):
	* tests/trace.test (trace-21.11): fix for [Bug 1590232], execution
	traces may cause a second command resolution in the wrong namespace.

2006-11-03  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* tests/event.test (event-11.5):	Rewrote tests to stop Tcl from
	* tests/io.test (multiple tests):	opening sockets that are
	* tests/ioCmd.test (iocmd-15.1,16,17):	reachable from outside hosts
	* tests/iogt.test (__echo_srv__.tcl):	where not necessary. This is
	* tests/socket.test (multiple tests):	noticably annoying on some
	* tests/unixInit.test (unixInit-1.2):	systems (e.g., Windows).

2006-11-02  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Tcl.xcodeproj/project.pbxproj: check autoconf/autoheader exit
	status and stop build if they fail.

2006-11-02  Jeff Hobbs	<jeffh@ActiveState.com>

	* doc/ParseCmd.3, doc/Tcl.n, doc/eval.n, doc/exec.n:
	* doc/fconfigure.n, doc/interp.n, doc/unknown.n:
	* library/auto.tcl, library/init.tcl, library/package.tcl:
	* library/safe.tcl, library/tm.tcl, library/msgcat/msgcat.tcl:
	* tests/all.tcl, tests/basic.test, tests/cmdInfo.test:
	* tests/compile.test, tests/encoding.test, tests/execute.test:
	* tests/fCmd.test, tests/http.test, tests/init.test:
	* tests/interp.test, tests/io.test, tests/ioUtil.test:
	* tests/iogt.test, tests/namespace-old.test, tests/namespace.test:
	* tests/parse.test, tests/pkg.test, tests/pkgMkIndex.test:
	* tests/proc.test, tests/reg.test, tests/trace.test:
	* tests/upvar.test, tests/winConsole.test, tests/winFCmd.test:
	* tools/tclZIC.tcl:
	* generic/tclParse.c (Tcl_ParseCommand): Replace {expand} with {*}
	officially (TIP #293). Leave -DALLOW_EXPAND=0|1 option to keep
	{expand} syntax for transition users. [Bug 1589629]

2006-11-02  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclBasic.c, generic/tclInterp.c, generic/tclProc.c: Silence
	warnings from gcc over signed/unsigned and TclStackAlloc().
	* generic/tclCmdMZ.c: Update to more compact and clearer coding style.

2006-11-02  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCmdAH.c:	Further revisions to produce the routines
	* generic/tclInt.h:	TclFormat() and TclAppendFormatToObj() that
	* generic/tclNamesp.c:	accept (objc, objv) arguments rather than
	* generic/tclStringObj.c:	any varargs stuff.

	* generic/tclBasic.c:	Further revised TclAppendPrintToObj() and
	* generic/tclCkalloc.c: TclObjPrintf() routines to panic when unable
	* generic/tclCmdAH.c:	to complete their formatting operations,
	* generic/tclCmdIL.c:	rather than report an error message. This
	* generic/tclCmdMZ.c:	means an interp argument for error message
	* generic/tclDictObj.c: recording is no longer needed, further
	* generic/tclExecute.c: simplifying the interface for callers.
	* generic/tclIORChan.c:
	* generic/tclIOUtil.c:
	* generic/tclInt.h:
	* generic/tclMain.c:
	* generic/tclNamesp.c:
	* generic/tclParseExpr.c:
	* generic/tclPkg.c:
	* generic/tclProc.c:
	* generic/tclStringObj.c:
	* generic/tclTimer.c:
	* generic/tclUtil.c:
	* unix/tclUnixFCmd.c:

2006-11-02  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* tests/winPipe.test (winpipe-4.[2345]): Made robust when run in
	directory with spaces in its name.

	* generic/tclCmdAH.c: Clean up uses of cast NULLs.

	* generic/tclInterp.c (AliasObjCmd): Added more explanatory comments.

	* generic/tclBasic.c (TclEvalObjvInternal): Rewrote so that comments
	are relevant and informative once more. Also made the unknown handler
	processing use the Tcl execution stack for working space, and not the
	general heap.

2006-11-01  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tclUnixPort.h: ensure MODULE_SCOPE is defined before use, so
	that tclPort.h can once again be included without tclInt.h.

	* generic/tclEnv.c (Darwin): mark _environ symbol as unexported even
	when MODULE_SCOPE != __private_extern__.

2006-10-31  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Refactored and renamed the routines
	* generic/tclCkalloc.c: TclObjPrintf, TclFormatObj, and
	* generic/tclCmdAH.c:	TclFormatToErrorInfo to a new set of routines
	* generic/tclCmdIL.c:	TclAppendPrintfToObj, TclAppendFormatToObj,
	* generic/tclCmdMZ.c:	TclObjPrintf, and TclObjFormat, with the
	* generic/tclDictObj.c: intent of making the latter list, plus
	* generic/tclExecute.c: TclAppendLimitedToObj and
	* generic/tclIORChan.c: TclAppendObjToErrorInfo, public via a revised
	* generic/tclIOUtil.c:	TIP 270.
	* generic/tclInt.h:
	* generic/tclMain.c:
	* generic/tclNamesp.c:
	* generic/tclParseExpr.c:
	* generic/tclPkg.c:
	* generic/tclProc.c:
	* generic/tclStringObj.c:
	* generic/tclTimer.c:
	* generic/tclUtil.c:
	* unix/tclUnixFCmd.c:

2006-10-31  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c, generic/tcl.h, generic/tclInterp.c:
	* generic/tclNamesp.c: removing the flag bit TCL_EVAL_NOREWRITE, the
	last remnant of the callObjc/v fiasco. It is not needed, as it is now
	always set and checked or'ed with TCL_EVAL_INVOKE.

2006-10-31  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* win/rules.vc: Fix for [Bug 1582769] - options conflict with VC2003.

2006-10-31  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclBasic.c, generic/tclNamesp.c, generic/tclProc.c:
	* generic/tclInt.h: Removed the callObjc and callObjv fields from the
	Interp structure. They did not function correctly and made other parts
	of the core amazingly complex, resulting in a substantive change to
	[info level] behaviour. [Bug 1587618]
	* library/clock.tcl: Removed use of [info level 0] for calculating the
	command name as used by the user and replace with a literal. What's
	there now is sucky, but at least appears to be right to most users.
	* tests/namespace.test (namespace-42.7,namespace-47.1): Reverted
	changes to these tests.
	* tests/info.test (info-9.11,info-9.12): Added knownBug constraint
	since these tests require a different behaviour of [info level] than
	is possible because of other dependencies.

2006-10-30  Jeff Hobbs	<jeffh@ActiveState.com>

	* tools/tcltk-man2html.tcl (option-toc): handle any kind of options
	defined toc section (needed for ttk docs)

2006-10-30  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c (TEOVI): insured that the interp's callObjc/v
	fields are restored after traces run, as they be spoiled. This was
	causing a segfault in tcllib's profiler tests.

2006-10-30  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c (INST_MOD): Corrected improper testing of the
	* tests/expr.test:		   sign of bignums when applying Tcl's
	division rules. Thanks to Peter Spjuth. [Bug 1585704]

2006-10-29  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclNamesp.c (EnsembleImplementationCmd):
	* tests/namespace.test (47.7-8): reverted a wrong "optimisation" that
	completely broke snit; added two tests.

2006-10-28  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclProc.c (ObjInterpProcEx, TclObjInterpProcCore): Split the
	core of procedures to make it easier to build procedure-like code
	without going through horrible contortions. This is the last critical
	component to make advanced OO systems workable as simple loadable
	extensions. TOIPC is now in the internal stub table.
	(MakeProcError, MakeLambdaError): Refactored ProcessProcResultCode to
	be simpler, some of which goes to TclObjInterpProcCore, and the rest
	of which is now in these far simpler routines which just do errorInfo
	stack generation for different types of procedure-like entity.
	* tests/apply.test (apply-5.1): Updated to expect the more informative
	form of message.

2006-10-27  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclVar.c (HasLocalVars): New macro to make various bits and
	pieces cleaner.

	* generic/tclNamesp.c (TclSetNsPath): Expose SetNsPath() through
	internal stubs table with semi-external name.

	* generic/tclInt.h (CallFrame): Add a field for handling context data
	for extensions (like object systems) that should be tied to a call
	frame (and not a command or interpreter).

	* generic/tclBasic.c (TclRenameCommand): Change to take CONST args;
	they were only ever used in a constant way anyway, so this appears to
	be a spot that was missed during TIP#27 work.

2006-10-26  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclProc.c (SetLambdaFromAny): minor change, eliminate
	redundant call to Tcl_GetString (thanks aku).

	* generic/tclInterp.c (ApplyObjCmd):
	* generic/tclNamesp.c (EnsembleImplementationCmd): replaced ckalloc
	(heap) with TclStackAlloc (execution stack).

2006-10-24  Miguel Sofer  <msofer@users.sf.net>

	* tests/info.test (info-9.11-12): tests for [Bug 1577492]
	* tests/apply.test (apply-4.3-5): tests for [Bug 1574835]

	* generic/tclProc.c (ObjInterpProcEx): disable itcl hacks for calls
	from ApplyObjCmd (islambda==1), as they mess apply's error messages
	[Bug 1583266]

2006-10-23  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclProc.c (ApplyObjCmd): fix wrong#args for apply by using
	the ensemble rewrite engine. [Bug 1574835]
	* generic/tclInterp.c (AliasObjCmd): previous commit missed usage of
	TCL_EVAL_NOREWRITE for aliases.

	* generic/tclBasic.c (TclEvalObjvInternal): removed redundant check
	for ensembles. [Bug 1577628]

	* library/clock.tcl (format, scan): corrected wrong # args messages to
	* tests/clock.test (3.1, 34.1):	    make use of the new rewrite
	capabilities of [info level]

	* generic/tcl.h:	   Lets TEOV update the iPtr->callObj[cv] new
	* generic/tclBasic.c:	   fields, except when the flag bit
	* generic/tclInt.h:	   TCL_EVAL_NOREWRITE is present. These values
	* generic/tclNamesp.c:	   are used by Tcl_PushCallFrame to initialise
	* generic/tclProc.c:	   the frame's obj[cv] fields, and allows
	* tests/namespace.test:	   [info level] to know and use ensemble
	rewrites. [Bug 1577492]

	***POTENTIAL INCOMPATIBILITY***
	The return value from [info level 0] on interp alias calls is changed:
	previously returned the target command (including curried values), now
	returns the source - what was actually called.

2006-10-23  Miguel Sofer  <msofer@users.sf.net>

	* generic/tcl.h:	   Modified the Tcl call stack so there is
	* generic/tclBasic.c:	   always a valid CallFrame, even at level 0
	* generic/tclCmdIL.c:	   [Patch 1577278]. Most of the changes
	* generic/tclInt.h:	   involve removing tests for a NULL
	* generic/tclNamesp.c:	   iPtr->(var)framePtr. There is now a
	* generic/tclObj.c:	   CallFrame pushed at interp creation with a
	* generic/tclProc.c:	   pointer to it stored in iPtr->rootFramePtr.
	* generic/tclTrace.c:	   A second unused field in Interp is
	* generic/tclVar.c:	   hijacked to enable further functionality,
	currently unused (but with several FRQs depending on it).

	***POTENTIAL INCOMPATIBILITY***
	Any user that includes tclInt.h and needs to determine if it is
	running at level 0 should change (iPtr->varFramePtr == NULL) to
	(iPtr->varFramePtr == iPtr->rootFramePtr).

2006-10-23  Don Porter	<dgp@users.sourceforge.net>

	* README:		Bump version number to 8.5a6
	* generic/tcl.h:
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/README.binary:
	* win/configure.in:

	* unix/configure:	autoconf-2.59
	* win/configure:

2006-10-21  Miguel Sofer  <msofer@users.sf.net>

	* generic/tcl.h, generic/tclHash.c: Tcl_FindHashEntry now calls
	Tcl_CreateHashEntry with a newPtr set to NULL: this would have caused
	a segfault previously and eliminates duplicated code. A macro has been
	added to tcl.h (only used when TCL_PRESERVE_BINARY_COMPATABALITY is
	not set - i.e., not by default).

2006-10-20  Reinhard Max  <max@tclers.tk>

	* unix/configure.in: Added autodetection for OS-supplied timezone
	* unix/Makefile.in:  files and configure switches to override the
	* unix/configure:    detected default.

2006-10-20  Daniel Steffen  <das@users.sourceforge.net>

	*** 8.5a5 TAGGED FOR RELEASE ***

	* tools/tcltk-man2html.tcl: add support for alpha & beta versions to
	useversion glob pattern. [Bug 1579941]

2006-10-18  Don Porter	<dgp@users.sourceforge.net>

	* changes:		8.5a5 release date set

	* doc/Encoding.3:	Missing doc updates (mostly Table of
	* doc/Ensemble.3:	Contents) exposed by `make checkdoc`
	* doc/FileSystem.3:
	* doc/GetTime.3:
	* doc/PkgRequire.3:

2006-10-17  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclInterp.c (ApplyObjCmd): fixed bad error in 2006-10-12
	commit: interp released too early. Spotted by mistachkin.

2006-10-16  Miguel Sofer  <msofer@users.sf.net>

	* tclProc.c (SetLambdaFromAny):
	* tests/apply.test (9.1-9.2): plugged intrep leak [Bug 1578454],
	found by mjanssen.

2006-10-16  Andreas Kupries  <andreask@activestate.com>

	* generic/tclBasic.c: Moved TIP#219 cleanup to DeleteInterpProc.

2006-10-16  Daniel Steffen  <das@users.sourceforge.net>

	* changes: updates for 8.5a5 release.

	* unix/tclUnixThrd.c (TclpThreadGetStackSize): Darwin: fix for main
	thread, where pthread_get_stacksize_np() returns incorrect info.

	* macosx/GNUmakefile: don't redo prebinding of non-prebound binaires.

2006-10-16  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclPkg.c (ExactRequirement):	Plugged memory leak. Also
	changed Tcl_Alloc()/Tcl_Free() calls to ckalloc()/ckfree() for easier
	memory debugging in the future. [Bug 1568373]

	* library/tcltest/tcltest.tcl:	Revise tcltest bump to 2.3a1.
	* library/tcltest/pkgIndex.tcl: This permits more features to be
	* unix/Makefile.in:	added to tcltest before we reach version 2.3.0
	* win/Makefile.in:	best timed to match the release of Tcl 8.5.0.
	* win/makefile.vc:	This also serves as a demo of TIP 268 features

2006-10-13  Colin McCormack <coldstore@users.sf.net>

	* win/tclWinFile.c: corrected erroneous attempt to protect against
	NULL return from Tcl_FSGetNormalizedPath per [Bug 1548263] causing
	[Bug 1575837].
	* win/tclWinFile.c: alfredd supplied patch to fix [Bug 1575837]

2006-10-13  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tclUnixThrd.c (TclpThreadGetStackSize): on Darwin, use
	* unix/tcl.m4: pthread_get_stacksize_np() API to get thread stack size
	* unix/configure: autoconf-2.59
	* unix/tclConfig.h.in: autoheader-2.59

2006-10-12  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclInterp.c (ApplyObjCmd):
	* tests/interp.test (interp-14.5-10): made [interp alias] use the
	ensemble rewrite machinery to produce better error messages [Bug
	1576006]

2006-10-12  David Gravereaux <davygrvy@pobox.com>

	* win/nmakehlp.c: Replaced all wnsprintf() calls with snprintf().
	wnsprintf was not in my shwlapi header file (VC++6)

2006-10-11  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclPkg.c (Tcl_PackageRequireEx):	Corrected crash when
	argument version=NULL passed in.

2006-10-10  Don Porter	<dgp@users.sourceforge.net>

	* changes:	Updates for 8.5a5 release.

	* generic/tclNamespace.c (TclTeardownNamespace):  After the
	commandPathSourceList of a namespace is cleared, set the
	commandPathSourceList to NULL so we don't try to walk the list a
	second time, possibly after it is freed. [Bug 1566526]
	* tests/namespace.test (namespace-51.16):	Added test.

2006-10-09  Miguel Sofer  <msofer@users.sf.net>

	* doc/UpVar.3: brough the docs in accordance to the code. Ever since
	8.0, Tcl_UpVar(2)? accepts TCL_NAMESPACE_ONLY as a flag value, and
	var-3.4 tests for proper behaviour. The docs only allowed 0 and
	TCL_GLOBAL_ONLY. [Bug 1574099]

2006-10-09  Miguel Sofer  <msofer@users.sf.net>

	* tests/*.test: updated all tests to refer explicitly to the global
	variables ::errorInfo, ::errorCode, ::env and ::tcl_platform: many
	were relying on the alternative lookup in the global namespace, that
	feature is tested specifically in namespace and variable tests.

	The modified testfiles are: apply.test, basic.test, case.test,
	cmdIL.test, cmdMZ.test, compExpr-old.test, error.test, eval.test,
	event.test, expr.test, fileSystem.test, for.test, http.test, if.test,
	incr-old.test, incr.test, interp.test, io.test, ioCmd.test, load.test,
	misc.test, namespace.test, parse.test, parseOld.test, pkg.test,
	proc-old.test, set.test, switch.test, tcltest.test, thread.test,
	var.test, while-old.test, while.test.

2006-10-06  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* win/rules.vc: [Bug 1571954] avoid /RTCc flag with MSVC8

2006-10-06  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* doc/binary.n:	       TIP #275: Support unsigned values in binary
	* generic/tclBinary.c: command. Tests and documentation updated.
	* tests/binary.test:

2006-10-05  Andreas Kupries  <andreask@activestate.com>

	* library/tm.tcl: Fixed bug in TIP #189 implementation, now allowing
	'_' in module names.

2006-10-05  Jeff Hobbs	<jeffh@ActiveState.com>

	* library/http/http.tcl (http::geturl): only do geturl url rfc 3986
	validity checking if $::http::strict is true (default true for 8.5).
	[Bug 1560506]

	* generic/tcl.h: note limitation on changing Tcl_UniChar size
	* generic/tclEncoding.c (UtfToUnicodeProc, UnicodeToUtfProc):
	* tests/encoding.test (encoding-16.1): fix alignment issues in
	unicode <> utf conversion procs. [Bug 1122671]

2006-10-05  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclVar.c (Tcl_LappendObjCmd):
	* tests/append.test(4.21-22): fix for longstanding [Bug 1570718],
	lappending nothing to non-list. Reported by lvirden

2006-10-04  Kevin B. Kenny  <kennykb@acm.org>

	* tzdata/: Olson's tzdata2006m.

2006-10-01  Kevin B. Kenny  <kennykb@acm.org>

	* tests/clock.test (clock-49.2): Removed a locale dependency that
	caused a spurious failure in the German locale. [Bug 1567956]

2006-10-01  Miguel Sofer  <msofer@users.sf.net>

	* doc/Eval.3 (TclEvalObjv): added note on refCount management for the
	elements of objv. [Bug 730244]

2006-10-01  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* win/tclWinFile.c: Handle possible missing define.

	* win/tclWinFile.c (TclpUtime): [Bug 1420432] file mtime fails for
	* tests/cmdAH.test:		directories on windows

	* tests/winFile.test: Handle Msys environment a little differently in
	getuser function. [Bug 1567956]

2006-09-30  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclUtil.c (Tcl_SplitList): optimisation, [Patch 1344747] by
	dgp.

	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclIntDecls.h:
	* generic/tclObj.c:
	* generic/tclStubInit.c: added an internal function TclObjBeingDeleted
	to provide info as to the reason for the loss of an internal rep. [FR
	1512138]

	* generic/tclCompile.c:
	* generic/tclHistory.c:
	* generic/tclInt.h:
	* generic/tclProc.c: made Tcl_RecordAndEvalObj not call "history" if
	it has been redefined to an empty proc, in order to reduce the noise
	when debugging [FR 1190441]. Moved TclCompileNoOp from tclProc.c to
	tclCompile.c

2006-09-28  Andreas Kupries  <andreask@activestate.com>

	* generic/tclPkg.c (CompareVersions): Bugfix. Check string lengths
	* tests/pkg.test: before comparison. The shorter string is the smaller
	number. Added testcases as well. Interestingly all existing test cases
	for vcompare compared numbers of the same length with each other. [Bug
	1563836]

2006-09-28  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclIO.c (Tcl_GetsObj): added two test'n'panic guards for
	possible NULL derefs, [Bug 1566382] and coverity #33.

2006-09-27  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c: Corrected error in INST_LSHIFT in the
	* tests/expr.test:	calculation done to determine whether a shift
	in the (long int) type is possible. The calculation had literal value
	"1" where it needed a value "1L" to compute the correct result. Error
	detected via testing with the math::bigfloat package [Bug 1567222]

	* generic/tclPkg.c (CompareVersion):	Flatten strcmp() results to
	{-1, 0, 1} to match expectations of CompareVersion() callers.

2006-09-27  Miguel Sofer  <msofer@users.sf.net>

	* generic/regc_color.c (singleton):
	* generic/regc_cvec.c (addmcce):
	* generic/regcomp.c (compile, dovec): the static function addmcce does
	nothing when called with two NULL pointers; the only call is by
	compile with two NULL pointers (regcomp.c #includes regc_cvec.c).
	Large parts (all?) the code for mcce (multi character collating
	element) that we do not use is ifdef'ed out with the macro
	REGEXP_MCCE_ENABLE.
	This silences coverity bugs 7, 16, 80

	* generic/regc_color.c (uncolorchain):
	* generic/regc_nfa.c (freearc): changed tests and asserts to
	equivalent formulation, designed to avoid an explicit comparison to
	NULL and satisfy coverity that 6 and 9 are not bugs.

2006-09-27  Andreas Kupries  <andreask@activestate.com>

	* tests/pkg.test: Added test for version comparison at the 32bit
	boundary. [Bug 1563836]

	* generic/tclPkg.c: Rewrote CompareVersion to perform string
	comparison instead of numeric. This breaks through the 32bit limit on
	version numbers. See code for details (handling of leading zeros,
	signs, etc.). un-CONSTed some arguments of CompareVersions,
	RequirementSatisfied, and AllRequirementsSatisfied. The new compare
	modifies the string (temporary string terminators). All callers use
	heap-allocated ver-intreps, so we are good with that. [Bug 1563836]

2006-09-27  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclFileName.c (TclGlob): added a panic for a call with
	TCL_GLOBMODE_TAILS and pathPrefix==NULL. This would cause a segfault,
	as found by coverity #26.

2006-09-26  Kevin B. Kenny  <kennykb@acm.org>

	* doc/Encoding.3:	 Added covariant 'const' qualifier for the
	* generic/tcl.decls:	 Tcl_EncodingType argument to
	* generic/tclEncoding.c: Tcl_CreateEncoding. [Further TIP#27 work.]
	* generic/tclDecls.h:	 Reran 'make genstubs'.

2006-09-26  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* win/makefile.vc:  Additional compiler flags and amd64 support.
	* win/nmakehlp.c:
	* win/rules.vc:

2006-09-26  Don Porter	<dgp@users.sourceforge.net>

	* generic/tcl.h:	As 2006-09-22 commit from Donal K. Fellows
	demonstrates, "#define NULL 0" is just wrong, and as a quotable chat
	figure observed, "If NULL isn't defined, we're not using a C compiler"
	Improper fallback definition of NULL removed.

2006-09-25  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* generic/tcl.h:	More fixing which struct stat to refer to.
	* generic/tclGetDate.y: Some casts from time_t to int required.
	* generic/tclTimer.c:	Tcl_Time structure members are longs.
	* win/makefile.vc:	Support for varying compiler options
	* win/rules.vc:		and build to platform-specific subdirs.

2006-09-25  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c (Tcl_StackChannel): Fixed [Bug 1564642], aka
	coverity #51. Extended loop condition, added checking for NULL to
	prevent seg.fault.

2006-09-25  Andreas Kupries  <andreask@activestate.com>

	* doc/package.n: Fixed nits reported by Daniel Steffen in the TIP#268
	changes.

2006-09-25  Kevin B. Kenny   <kennykb@acm.org>

	* generic/tclNotify.c (Tcl_DeleteEvents): Simplified the code in hopes
	of making the invariants clearer and proving to Coverity that the
	event queue memory is managed correctly.

2006-09-25  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclNotify.c (Tcl_DeleteEvents): Make it clear what happens
	when the event queue is mismanaged. [Bug 1564677], coverity bug #10.

2006-09-24  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclParse.c (Tcl_ParseCommand): also return an error if
	start==NULL and numBytes<0. This is coverity's bug #20

	* generic/tclStringObj.c (STRING_SIZE): fix allocation for 0-length
	strings. This is coverity's bugs #54-5

2006-09-22  Andreas Kupries  <andreask@activestate.com>

	* generic/tclInt.h: Moved TIP#268's field 'packagePrefer' to the end
	of the structure, for better backward compatibility.

2006-09-22  Andreas Kupries  <andreask@activestate.com>

	TIP#268 IMPLEMENTATION

	* generic/tclDecls.h:	 Regenerated from tcl.decls.
	* generic/tclStubInit.c:

	* doc/PkgRequire.3: Documentation of extended API, extended testsuite.
	* doc/package.n:
	* tests/pkg.test:

	* generic/tcl.decls: Implementation.
	* generic/tclBasic.c:
	* generic/tclConfig.c:
	* generic/tclInt.h:
	* generic/tclPkg.c:
	* generic/tclTest.c:
	* generic/tclTomMathInterface.c:
	* library/init.tcl:
	* library/package.tcl:
	* library/tm.tcl:

2006-09-22  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclThreadTest.c (TclCreateThread): Use NULL instead of 0 as
	end-of-strings marker to Tcl_AppendResult; the difference matters on
	64-bit machines. [Bug 1562528]

2006-09-21  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclUtil.c:	Dropped ParseInteger() routine. TclParseNumber
	covers the task just fine.

2006-09-19  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclEvent.c (Tcl_VwaitObjCmd): Rewrite so that an exceeded
	limit trapped in a vwait cannot cause a dangerous dangling trace.

2006-09-19  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c (INST_EXPON):	Native type overflow detection
	* tests/expr.test:	was completely broken. Falling back on use of
	bignums for all non-trivial ** calculations until
	native-type-constrained special cases can be done carefully and
	correctly. [Bug 1561260]

2006-09-15  Jeff Hobbs	<jeffh@ActiveState.com>

	* library/http/http.tcl:      Change " " -> "+" url encoding mapping
	* library/http/pkgIndex.tcl:  to " " -> "%20" as per RFC 3986.
	* tests/http.test (http-5.1): bump http to 2.5.3
	* unix/Makefile.in:
	* win/Makefile.in:

2006-09-12  Andreas Kupries  <andreask@activestate.com>

	* unix/configure.in (HAVE_MTSAFE_GETHOST*): Modified to recognize
	HP-UX 11.00 and beyond as having mt-safe implementations of the
	gethost functions.
	* unix/configure: Regenerated, using autoconf 2.59

	* unix/tclUnixCompat.c (PadBuffer): Fixed bug in calculation of the
	increment needed to align the pointer, and added documentation
	explaining why the macro is implemented as it is.

2006-09-11  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* win/rules.vc:	   Updated to install http, tcltest and msgcat as
	* win/makefile.vc: Tcl Modules (as per Makefile.in).
	* win/makefile.vc: Added tommath_(super)class headers.

2006-09-11  Andreas Kupries  <andreask@activestate.com>

	* unix/Makefile.in (install-libraries): Fixed typo tcltest 2.3.9 ->
	2.3.0.

2006-09-11  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tclUnixCompat.c: make compatLock static and only declare it
	when it will actually be used; #ifdef parts of TSD that are not always
	needed; adjust #ifdefs to cover all possible cases; fix whitespace.

2006-09-11  Andreas Kupries  <andreask@activestate.com>

	* tests/msgcat.test: Bumped version in auxiliary files as well.
	* doc/msgcat.n:

2006-09-11  Kevin B. Kenny  <kennykb@acm.org>

	* unix/Makefile.in:	Bumped msgcat version to 1.4.2 to be
	* win/Makefile.in:	consistent with dgp's commits of 2006-09-10.

2006-09-11  Don Porter	<dgp@users.sourceforge.net>

	* library/msgcat/msgcat.tcl:	Removed some unneeded [uplevel]s.

2006-09-10  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c:		Corrected INST_EXPON flaw that treated
	* tests/expr.test:		$x**1 as $x**3. [Bug 1555371]

	* doc/tcltest.n:		Bump to version tcltest 2.3.0 to
	* library/tcltest/pkgIndex.tcl: account for new "-verbose line"
	* library/tcltest/tcltest.tcl:	feature.
	* unix/Makefile.in:
	* win/Makefile.in:
	* win/makefile.bc:
	* win/makefile.vc:

	* library/msgcat/msgcat.tcl:	Bump to version msgcat 1.4.2 to
	* library/msgcat/pkgIndex.tcl:	account for modifications.

2006-09-10  Daniel Steffen  <das@users.sourceforge.net>

	* library/msgcat/msgcat.tcl (msgcat::Init): on Darwin, add fallback of
	* tests/msgcat.test:			    default msgcat locale to
	* unix/tclUnixInit.c (TclpSetVariables):    current CFLocale
	identifier if available (via private ::tcl::mac::locale global, set at
	interp init when on Mac OS X 10.3 or later with CoreFoundation).

	* library/tcltest/tcltest.tcl: add 'line' verbose level: prints source
	* doc/tcltest.n:	       file line information of failing tests.

	* macosx/Tcl.xcodeproj/project.pbxproj: add new tclUnixCompat.c file;
	revise tests target to use new tcltest 'line' verbose level.

	* unix/configure.in: add descriptions to new AC_DEFINEs for MT-safe.
	* unix/tcl.m4: add caching to new SC_TCL_* macros for MT-safe wrappers
	* unix/configure: autoconf-2.59
	* unix/tclConfig.h.in: autoheader-2.59

2006-09-08  Zoran Vasiljevic <vasiljevic@users.sourceforge.net>

	* unix/tclUnixCompat.c: Added fallback to gethostbyname() and
	gethostbyaddr() if the implementation is known to be MT-safe
	(currently for Darwin 6 or later only).

	* unix/configure.in: Assume gethostbyname() and gethostbyaddr() are
	MT-safe starting with Darwin 6 (Mac OSX 10.2).

	* unix/configure: Regenerated with autoconf V2.59

2006-09-08  Andreas Kupries  <andreask@activestate.com>

	* unix/tclUnixCompat.c: Fixed conditions for CopyArray/CopyString, and
	CopyHostent. Also fixed bad var names in TclpGetHostByName.

2006-09-07  Zoran Vasiljevic <vasiljevic@users.sourceforge.net>

	* unix/tclUnixCompat.c: Added fallback to MT-unsafe library calls if
	TCL_THREADS is not defined.
	Fixed alignment of arrays copied by CopyArray() to be on the
	sizeof(char *) boundary.

2006-09-07  Zoran Vasiljevic <vasiljevic@users.sourceforge.net>

	* unix/tclUnixChan.c:	Rewritten MT-safe wrappers to return ptrs to
	* unix/tclUnixCompat.c: TSD storage making them all look like their
	* unix/tclUnixFCmd.c:	MT-unsafe pendants API-wise.
	* unix/tclUnixPort.h:
	* unix/tclUnixSock.c:

2006-09-06  Zoran Vasiljevic <vasiljevic@users.sourceforge.net>

	* unix/tclUnixChan.c: Added TCL_THREADS ifdef'ed usage of MT-safe
	* unix/tclUnixFCmd.c: calls like: getpwuid, getpwnam, getgrgid,
	* unix/tclUnixSock.c: getgrnam, gethostbyname and gethostbyaddr.
	* unix/tclUnixPort.h: See [Bug 999544]
	* unix/Makefile.in:
	* unix/configure.in:
	* unix/tcl.m4:
	* unix/configure: Regenerated.

	* unix/tclUnixCompat.c: New file containing MT-safe implementation of
	some library calls.

2006-09-04  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c:	Removed much complexity that is no
	longer needed.

	* tests/main.text (Tcl_Main-4.4):	Test corrected to not be
	timing sensitive to the Bug 1481986 fix. [Bug 1550858]

2006-09-04  Jeff Hobbs	<jeffh@ActiveState.com>

	* doc/package.n: correct package example

2006-08-31  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompExpr.c:	Corrected flawed logic for disabling
	the INST_TRY_CVT_TO_NUMERIC instruction at the end of an expression
	when function arguments contain operators. [Bug 1541274]

	* tests/expr-old.test:	The remaining failing tests reported in
	* tests/expr.test:	[Bug 1381715] are all new in Tcl 8.5, so
	there's really no issue of compatibility with Tcl 8.4 result to deal
	with. Fixed by updating tests to expect 8.5 results.

2006-08-29  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclParseExpr.c:	Dropped the old expr parser.

2006-08-30  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclBasic.c (Tcl_CreateInterp): init iPtr->threadId

	* win/tclWinChan.c [Bug 819667] Improve logic for identifying COM
	ports.

	* generic/tclIOGT.c (ExecuteCallback):
	* generic/tclPkg.c (Tcl_PkgRequireEx): replace Tcl_GlobalEval(Obj)
	with more efficient Tcl_Eval(Obj)Ex

	* unix/Makefile.in (valgrindshell): add valgrindshell target and
	update default VALGRINDARGS. User can override, or add to it with
	VALGRIND_OPTS env var.

	* generic/tclFileName.c (DoGlob): match incrs with decrs.

2006-08-29  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclParseExpr.c:	Use the "parent" field of orphan
	ExprNodes to store the closure of left pointers. This lets us avoid
	repeated re-scanning leftward for the left boundary of subexpressions,
	which in worst case led to near O(N^2) runtime.

2006-08-29  Joe Mistachkin  <joe@mistachkin.com>

	* unix/tclUnixInit.c: Fixed the issue (typo) that was causing
	* unix/tclUnixThrd.c (TclpThreadGetStackSize): stack.test to fail on
	FreeBSD (and possibly other Unix platforms).

2006-08-29  Colin McCormack  <coldstore@users.sourceforge.net>

	* generic/tclIOUtil.c:	Added test for NULL return from
	* generic/tclPathObj.c: Tcl_FSGetNormalizedPath which was causing
	* unix/tclUnixFile.c:	segv's per [Bug 1548263]
	* win/tclWinFCmd.c:
	* win/tclWinFile.c:

2006-08-28  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata/America/Havana:      Regenerated from Olson's
	* library/tzdata/America/Tegucigalpa: tzdata2006k.
	* library/tzdata/Asia/Gaza:

2006-08-28  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclStringObj.c:	Revised ObjPrintfVA to take care to
	* generic/tclParseExpr.c:	copy only whole characters when doing
	%s formatting. This relieves callers of TclObjPrintf() and
	TclFormatToErrorInfo() from needing to fix arguments to character
	boundaries. Tcl_ParseExpr() simplified by taking advantage. [Bug
	1547786]

	* generic/tclStringObj.c:	Corrected TclFormatObj's failure to
	count up the number of arguments required by examining the format
	string. [Bug 1547681]

2006-08-27  Joe Mistachkin  <joe@mistachkin.com>

	* generic/tclClock.c (ClockClicksObjCmd): Fix nested macro breakage
	with TCL_MEM_DEBUG enabled. [Bug 1547662]

2006-08-26  Miguel Sofer  <msofer@users.sf.net>

	* doc/namespace.n:
	* generic/tclNamesp.c:
	* tests/upvar.test: bugfix, docs clarification and new tests for
	[namespace upvar] as follow up to [Bug 1546833], reported by Will
	Duquette.

2006-08-24  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata: Regenerated, including several new files, from
	Olson's tzdata2006j.
	* library/clock.tcl:
	* tests/clock.test: Removed an early testing hack that allowed loading
	'registry' from the build tree rather than an installed one. This is a
	workaround for [Bug 15232730], which remains open because it's a
	symptom of a deeper underlying problem.

2006-08-23  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclParseExpr.c:	Minimal collection of new tests
	* tests/parseExpr.test:		testing the error messages of the new
	expr parser. Several bug fixes and code simplifications that appeared
	during that effort.

2006-08-21  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclIOUtil.c:	Revisions to complete the thread finalization
	of the cwdPathPtr. [Bug 1536142]

	* generic/tclParseExpr.c:	Revised mistaken call to
	TclCheckBadOctal(), so both [expr 08] and [expr 08z] have same
	additional info in error message.

	* tests/compExpr-old.test:	Update existing tests to not fail with
	* tests/compExpr.test:		the new expr parser.
	* tests/compile.test:
	* tests/expr-old.test:
	* tests/expr.test:
	* tests/for.test:
	* tests/if.test:
	* tests/parseExpr.test:
	* tests/while.test:

2006-08-21  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* win/Makefile.in (gdb): Make this target work so that debugging an
	msys build is possible.

2006-08-21  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/tclMacOSXNotify.c (Tcl_WaitForEvent): if the run loop is
	already running (e.g. if Tcl_WaitForEvent was called recursively),
	re-run it in a custom run loop mode containing only the source for the
	notifier thread, otherwise wakeups from other sources added to the
	common run loop modes might get lost.

	* unix/tclUnixNotfy.c (Tcl_WaitForEvent): on 64-bit Darwin,
	pthread_cond_timedwait() appears to have a bug that causes it to wait
	forever when passed an absolute time which has already been exceeded
	by the system time; as a workaround, when given a very brief timeout,
	just do a poll on that platform. [Bug 1457797]

	* generic/tclClock.c (ClockClicksObjCmd): add support for Darwin
	* generic/tclCmdMZ.c (Tcl_TimeObjCmd):	  nanosecond resolution timer
	* generic/tclInt.h:			  to [clock clicks] and [time]
	* unix/configure.in (Darwin):		  when TCL_WIDE_CLICKS defined
	* unix/tclUnixTime.c (TclpGetWideClicks, TclpWideClicksToNanoseconds):
	* unix/configure: autoconf-2.59
	* unix/tclConfig.h.in: autoheader-2.59

	* unix/tclUnixPort.h (Darwin): override potentially faulty configure
	detection of termios availability in all cases, since termios is known
	to be present on all Mac OS X releases since 10.0. [Bug 497147]

2006-08-18  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tcl.m4 (Darwin): add support for --enable-64bit on x86_64, for
	universal builds including x86_64, for 64-bit CoreFoundation on
	Leopard and for use of -mmacosx-version-min instead of
	MACOSX_DEPLOYMENT_TARGET
	* unix/configure: autoconf-2.59
	* unix/tclConfig.h.in: autoheader-2.59

	* generic/tcl.h:	  add fixes for building on Leopard and
	* unix/tclUnixPort.h:	  support for 64-bit CoreFoundation on Leopard
	* macosx/tclMacOSXFCmd.c:

	* unix/tclUnixPort.h: on Darwin x86_64, disable use of vfork as it
	causes execve to fail intermittently. (rdar://4685553)

	* generic/tclTomMath.h: on Darwin 64-bit, for now disable use of
	128-bit arithmetic through __attribute__ ((mode(TI))), as it leads to
	link errors due to missing fallbacks. (rdar://4685527)

	* macosx/Tcl.xcodeproj/project.pbxproj: add x86_64 to universal build,
	switch native release targets to use DWARF with dSYM, Xcode 3.0
	changes
	* macosx/README: updates for x86_64 and Xcode 2.4.

	* macosx/Tcl.xcodeproj/default.pbxuser: add test suite target that
	* macosx/Tcl.xcodeproj/project.pbxproj: runs the tcl test suite at
	build time and shows clickable test suite errors in the GUI build
	window.

	* tests/macOSXFCmd.test: fix use of deprecated resource fork paths.

	* unix/tclUnixInit.c (TclpInitLibraryPath): move code that is only
	needed when TCL_LIBRARY is defined to run only in that case.

	* generic/tclLink.c (LinkTraceProc): fix 64-bit signed-with-unsigned
	comparison warning from gcc4 -Wextra.

	* unix/tclUnixChan.c (TclUnixWaitForFile): with timeout < 0, if
	select() returns early (e.g. due to a signal), call it again instead
	of returning a timeout result. Fixes intermittent event-13.8 failures.

2006-08-17  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclCompile.c:		Revised the new set of expression
	* generic/tclParseExpr.c:	parse error messages.

2006-08-16  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclParseExpr.c:	Replace PrecedenceOf() function with
	prec[] static array.

2006-08-14  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* library/clock.tcl (::tcl::clock::add): Added missing braces to
	clockval validation code. Pointed out on comp.lang.tcl.

2006-08-11  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclNamesp.c: Improvements in buffer management to make
	namespace creation faster. Plus selected other minor improvements to
	code quality. [Patch 1352382]

2006-08-10  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	Misc patches to make code more efficient. [Bug 1530474] (afredd)
	* generic/*.c, macosx/tclMacOSXNotify.c, unix/tclUnixNotfy.c,
	* win/tclWinThrd.c: Tidy up invokations of Tcl_Panic() to promote
	string constant sharing and consistent style.
	* generic/tclBasic.c (Tcl_CreateInterp): More efficient handling of
	* generic/tclClock.c (TclClockInit):	 registration of commands not
						 in global namespace.
	* generic/tclVar.c (Tcl_UnsetObjCmd): Remove unreachable clause.

2006-08-09  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclEncoding.c:	Replace buffer copy in for loop with
	call to memcpy(). Thanks to afredd. [Patch 1530262]

2006-08-09  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclCmdIL.c (Tcl_LassignObjCmd): Make the wrong#args message
	a bit more consistent with those used elsewhere. [Bug 1534628]

	* generic/tclDictObj.c (DictForCmd): Stop crash when attempting to
	iterate over an invalid dictionary. [Bug 1531184]

	* doc/ParseCmd.3, doc/expr.n, doc/set.n, doc/subst.n, doc/switch.n:
	* doc/tclvars.n: Ensure that uses of [expr] in documentation examples
	are also good style (with braces) unless otherwise necessary. [Bug
	1526581]

2006-08-03  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tclUnixPipe.c (TclpCreateProcess): for USE_VFORK: ensure
	standard channels are initialized before vfork() so that the child
	doesn't potentially corrupt global state in the parent's address space

	* tests/compExpr-old.test: add 'oldExprParser' constraint to all tests
	* tests/compExpr.test:	   that depend on the exact format of the
	* tests/compile.test:	   error messages of the pre-2006-07-05
	* tests/expr-old.test:	   expression parser. The constraint is on by
	* tests/expr.test:	   default (i.e those tests still fail), but
	* tests/for.test:	   can be turned off by passing '-constraints
	* tests/if.test:	   newExprParser' to tcltest, which will skip
	* tests/parseExpr.test:	   the 196 failing tests in the testsuite that
	* tests/while.test:	   are caused by the new expression parser
	error messages.

2006-07-31  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclClock.c (ConvertLocalToUTCUsingC): Corrected a regression
	that caused dates before 1969 to be one day off in the :localtime time
	zone if TZ is not set. [Bug 1531530]

2006-07-30  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclClock.c (GetJulianDayFromEraYearMonthDay): Corrected
	several errors in converting dates before the Common Era [Bug 1426279]
	* library/clock.tcl: Corrected syntax errors in generated code for %EC
	%Ey, and %W format groups [Bug 1505383]. Corrected a bug in cache
	management for format strings containing [glob] metacharacters [Bug
	1494664]. Corrected several errors in formatting/scanning of years
	prior to the Common Era, and added the missing %EE format group to
	indicate the era.
	* tools/makeTestCases.tcl: Added code to make sure that %U and %V
	format groups are included in the tests. (The code depends on %U and
	%V formatting working correctly when 'makeTestCases.tcl' is run,
	rather than making a completely independent check.) Added tests for
	[glob] metacharacters in strings. Added tests for years prior to the
	Common Era.
	* tests/clock.test: Rebuilt with new test cases for all the above.

2006-07-30  Joe English	 <jenglish@users.sourceforge.net>

	* doc/AppInit.3: Fix typo [Bug 1496886]

2006-07-26  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c: Corrected flawed overflow detection in
	* tests/expr.test:	INST_EXPON that caused [expr 2**64] to return
	0 instead of the same value as [expr 1<<64].

2006-07-24  Don Porter	<dgp@users.sourceforge.net>

	* win/tclWinSock.c:	Correct un-initialized Tcl_DString. Thanks to
	afredd. [Bug 1518166]

2006-07-21  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c:
	* tests/execute.test (execute-9.1): dgp's fix for [Bug 1522803].

2006-07-20  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/tclMacOSXNotify.c (Tcl_InitNotifier, Tcl_WaitForEvent):
	create notifier thread lazily upon first call to Tcl_WaitForEvent()
	rather than in Tcl_InitNotifier(). Allows calling exeve() in processes
	where the event loop has not yet been run (Darwin's execve() fails in
	processes with more than one thread), in particular allows embedders
	to call fork() followed by execve(), previously the pthread_atfork()
	child handler's call to Tcl_InitNotifier() would immediately recreate
	the notifier thread in the child after a fork.

	* macosx/tclMacOSXFCmd.c (TclMacOSXCopyFileAttributes):	   add support
	* macosx/tclMacOSXNotify.c (Tcl_InitNotifier):		   for weakly
	* unix/tclUnixInit.c (Tcl_GetEncodingNameFromEnvironment): importing
	symbols not available on OSX 10.2 or 10.3, enables binaires built on
	later OSX versions to run on earlier ones.
	* macosx/Tcl.xcodeproj/project.pbxproj: enable weak-linking; turn on
						extra warnings.
	* macosx/README: document how to enable weak-linking; cleanup.
	* unix/tclUnixPort.h: add support for weak-linking; conditionalize
	AvailabilityMacros.h inclusion; only disable realpath on 10.2 or
	earlier when threads are enabled.
	* unix/tclLoadDyld.c (TclpLoadMemoryGetBuffer): change runtime Darwin
	* unix/tclUnixInit.c (TclpInitPlatform):	release check to use
							global initialized
							once
	* unix/tclUnixFCmd.c (DoRenameFile, TclpObjNormalizePath): add runtime
	Darwin release check to determine if realpath is threadsafe.
	* unix/configure.in: add check on Darwin for compiler support of weak
	* unix/tcl.m4:	     import and for AvailabilityMacros.h header; move
	Darwin specific checks & defines that are only relevant to the tcl
	build out of tcl.m4; restrict framework option to Darwin; clean up
	quoting and help messages.
	* unix/configure: autoconf-2.59
	* unix/tclConfig.h.in: autoheader-2.59

	* generic/regc_locale.c (cclass):
	* generic/tclExecute.c (TclExecuteByteCode):
	* generic/tclIOCmd.c (Tcl_ExecObjCmd):
	* generic/tclListObj.c (NewListIntRep):
	* generic/tclObj.c (Tcl_GetLongFromObj, Tcl_GetWideIntFromObj)
	(FreeBignum, Tcl_SetBignumObj):
	* generic/tclParseExpr.c (Tcl_ParseExpr):
	* generic/tclStrToD.c (TclParseNumber):
	* generic/tclStringObj.c (TclAppendFormattedObjs):
	* unix/tclLoadDyld.c (TclpLoadMemory):
	* unix/tclUnixPipe.c (TclpCreateProcess): fix signed-with-unsigned
	comparison and other warnings from gcc4 -Wextra.

2006-07-13  Andreas Kupries <andreask@activestate.com>

	* unix/tclUnixPort.h: Added the inclusion of <AvailabilityMacros.h>.
	The missing header caused the upcoming #if conditions to wrongly
	exclude realpath, causing file normalize to ignore symbolic links in
	the path.

2006-07-11  Zoran Vasiljevic <vasiljevic@users.sourceforge.net>

	* generic/tclAsync.c: Made Tcl_AsyncDelete() more tolerant when called
	after all thread TSD has been garbage-collected.

2006-07-05  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclParseExpr.c:	Completely new expression parser that
	builds a parse tree instead of operating with deep recursion. This
	corrects reports of stack-blowing crashes parsing long expressions
	[Bug 906201] and replaces a fundamentally O(N^2) algorithm with an
	O(N) one [RFE 903765]. The new parser is better able to generate error
	messages that clearly report both the nature and context of the syntax
	error [Bugs 1029267, 1381715]. For now, the code for the old parser is
	still present and can be activated with a "#define OLD_EXPR_PARSER
	1". This is for the sake of a clean implementation patch, and for ease
	of benchmarking. The new parser is non-recursive, so much lighter in
	stack consumption, but it does use more heap, so there may be cases
	where parsing of long expressions that succeeded with the old parser
	will lead to out of memory panics with the new one. There are still
	more improvements possible on that point, though significant progress
	may require changes to the Tcl_Token specifications documented for the
	public Tcl_Parse*() routines.
	***POTENTIAL INCOMPATIBILITY*** for any callers that rely on the exact
	(usually terrible) error messages generated by the old parser. This
	includes a large number of tests in the test suite.

	* generic/tclInt.h:		Replaced TclParseWhiteSpace() with
	* generic/tclParse.c:		TclParseAllWhiteSpace() which is what
	* generic/tclParseExpr.c:	all the callers really needed.
	Breaking whitespace runs at newlines is useful only to the command
	parsing function, and it can call the file scoped routine
	ParseWhiteSpace() to do that.

	* tests/expr-old.test:	Removed knownBug constraints that masked
	* tests/expr.test:	failures due to revised error messages.
	* tests/parseExpr.test:

2006-06-20  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclIOUtil.c:	Changed default configuration to
	* generic/tclInt.decls: #undef USE_OBSOLETE_FS_HOOKS which disables
	* generic/tclTest.c:	access to the Tcl 8.3 internal routines for
	hooking into filesystem operations. Everyone ought to have migrated to
	Tcl_Filesystems by now.
	***POTENTIAL INCOMPATIBILITY*** for any code still stuck in the
	pre-Tcl_Filesystem era.

	* generic/tclIntDecls.h:	make genstubs
	* generic/tclStubInit.c:

	* generic/tclStrToD.c:	Removed dead code that permitted disabling of
	recognition of the new 0b and 0o numeric formats.

	* generic/tclExecute.c: Removed dead code that implemented alternative
	* generic/tclObj.c:	design where numeric values did not
	automatically narrow to the smallest Tcl_ObjType required to hold them

	* generic/tclCmdAH.c:	Removed dead code that was old implementation
	of [format].

2006-06-14  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tclUnixPort.h (Darwin): support MAC_OS_X_VERSION_MAX_ALLOWED
	define from AvailabilityMacros.h: override configure detection and
	only use API available in the indicated OS version or earlier.

2006-06-14  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* doc/format.n, doc/scan.n: Added examples for converting between
	characters and their numeric interpretations following user prompting.

2006-06-13  Donal K. Fellows  <dkf@users.sf.net>

	* unix/tclLoadDl.c (TclpDlopen): Workaround for a compiler bug in Sun
	Forte 6. [Bug 1503729]

2006-06-06  Don Porter	<dgp@users.sourceforge.net>

	* doc/GetStdChan.3:	Added recommendation that each call to
	Tcl_SetStdChannel() be accompanied by a call to Tcl_RegisterChannel().

2006-06-05  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* doc/Alloc.3: Added documentation of promise that Tcl_Realloc(NULL,x)
	is the same as Tcl_Alloc(x), as discussed in comp.lang.tcl. Also fixed
	nonsense sentence to say something meaningful.

2006-05-29  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tcl.h (Tcl_DecrRefCount): use if/else construct to allow
	placement in unbraced outer if/else conditions. (jcw)

2006-05-27  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/tclMacOSXNotify.c: implemented pthread_atfork() handler that
	* unix/tcl.m4 (Darwin):	    recreates CoreFoundation state and
	notifier thread in the child after a fork(). Note that pthread_atfork
	is available starting with Tiger only. Because vfork() is used by the
	core on Darwin, [exec]/[open] are not affected by this fix, only
	extensions or embedders that call fork() directly (such as TclX).
	However, this only makes fork() safe from corefoundation tcl with
	--disable-threads; as on all platforms, forked children may deadlock
	in threaded tcl due to the potential for stale locked mutexes in the
	child. [Patch 923072]

	* unix/configure: autoconf-2.59
	* unix/tclConfig.h.in: autoheader-2.59

2006-05-24  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* unix/tcl.m4 (SC_CONFIG_SYSTEM): Fixed quoting of command script to
	awk; it was a rarely used branch, but it was wrong. [Bug 1494160]

2006-05-23  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* doc/chan.n, doc/refchan.n: Tighten up the documentation to follow a
	slightly more consistent style with regard to argument capitalization.

2006-05-13  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclProc.c (ProcCompileProc): When a bump of the compile
	epoch forces the re-compile of a proc body, take care not to overwrite
	any Proc struct that may be referred to on the active call stack. Note
	that the fix will not be effective for code that calls the private
	routine TclProcCompileProc() directly. [Bug 1482718]

2006-05-13  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclEvent.c (HandleBgErrors): fix leak. [Coverity issue 86]

2006-05-05  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclMain.c (Tcl_Main):		Corrected flaw that required
	* tests/main.test: (Tcl_Main-4.5):	processing of one interactive
	command before passing control to the loop routine registered with
	Tcl_SetMainLoop(). [Bug 1481986]

2006-05-04  Don Porter	<dgp@users.sourceforge.net>

	* README:		Bump version number to 8.5a5
	* generic/tcl.h:
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/README.binary:
	* win/configure.in:

	* unix/configure:	autoconf-2.59
	* win/configure:

	* generic/tclBasic.c (ExprSrandFunc): Restore acceptance of wide/big
	* doc/mathfunc.n: integer values by srand(). [Bug 1480509]

2006-04-26  Don Porter	<dgp@users.sourceforge.net>

	*** 8.5a4 TAGGED FOR RELEASE ***

	* changes:	Updates for another RC.

	* generic/tclBinary.c:	Revised the handling of the Q and q format
	* generic/tclInt.h:	specifiers for [binary] to account for the
	* generic/tclStrToD.c:	"middle endian" floating point format used in
	Nokia N770.

2006-04-25  Don Porter	<dgp@users.sourceforge.net>

	* doc/DoubleObj.3:	More doc updates for TIP 237.
	* doc/expr.n:
	* doc/format.n:
	* doc/mathfunc.n:
	* doc/scan.n:
	* doc/string.n:

	* generic/tclScan.c:	[scan $s %u] is documented to accept only
	* tests/scan.test:	decimal formatted integers. Fixed to match.

2006-04-19  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclStrToD.c: Added code to support the "middle endian"
	floating point format used in the Nokia N770's software-based floating
	point. Thanks to Bruce Johnson for reporting this bug, originally on
	http://wiki.tcl.tk/15408.
	* library/clock.tcl: Fixed a bug with Daylight Saving Time and Posix
	time zone specifiers reported by Martin Lemburg in
	http://groups.google.com/group/comp.lang.tcl/browse_thread/thread/9a8b15a4dfc0b7a0
	(and not at SourceForge).
	* tests/clock.test: Added test case for the above bug.

2006-04-18  Donal K. Fellows  <dkf@users.sf.net>

	* doc/IntObj.3: Minor review fixes, including better documentation of
	the behaviour of Tcl_GetBignumAndClearObj.

2006-04-17  Don Porter	<dgp@users.sourceforge.net>

	* doc/IntObj.3: Documentation changes to account for TIP 237 changes.
	* doc/Object.3: [Bug 1446971]

2006-04-12  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/regc_locale.c (cclass): Redefined the meaning of [:print:]
	to be exactly UNICODE letters, numbers, punctuation, symbols and
	spaces (*not* whitespace). [Bug 1376892]

2006-04-11  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclTrace.c:	Stop some interference between enter traces
	* tests/trace.test:	and enterstep traces. [Bug 1458266]

2006-04-07  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclPathObj.c: Yet another revised fix for the [Bug 1379287]
	* tests/fileSystem.test:	family of path normalization bugs.

2006-04-06  Jeff Hobbs	<jeffh@ActiveState.com>

	* generic/tclRegexp.c (FinalizeRegexp): full reset data to indicate
	readiness for reinitialization.

2006-04-06  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct):	It seems there
	* tests/indexObj.test:	are extensions that rely on the prior behavior
	* doc/GetIndex.3:	that the empty string cannot succeed as a
	unique prefix matcher, so I'm restoring Donal Fellows's solution.
	Added mention of this detail to the documentation. [Bug 1464039]

	* tests/compExpr-old.test:	Updated testmathfunctions constraint
	* tests/compExpr.test:		to post-TIP-232 world.
	* tests/expr-old.test:
	* tests/expr.test:
	* tests/info.test:

	* tests/indexObj.test:	Corrected other test errors revealed by
	* tests/upvar.test:	testing outside the tcltest application.

	* generic/tclPathObj.c: Revised fix for the [Bug 1379287] family of
	path normalization bugs.

2006-04-06  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tcl.m4: removed TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
	define on Darwin. [Bug 1457515]
	* unix/configure: autoconf-2.59
	* unix/tclConfig.h.in: autoheader-2.59

2006-04-05  Don Porter	<dgp@users.sourceforge.net>

	* win/tclWinInit.c:	More careful calls to Tcl_DStringSetLength()
	* win/tclWinSock.c:	to avoid creating invalid DString states. Bump
	* win/tclWinDde.c:	to version 1.3.2. [RFE 1366195]
	* library/dde/pkgIndex.tcl:

	* library/reg/pkgIndex.tcl:	Bump to registry 1.2 because
	* win/tclWinReg.c:	Registry_Unload() is a new public routine
	* win/Makefile.in:	compared to the 1.1.* releases.

	* win/configure.in:	Bump package version numbers.
	* win/configure:	autoconf 2.59

2006-04-05  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): Allow empty
	strings to be matched by the Tcl_GetIndexFromObj machinery, in the
	same manner as any other key. [Bug 1464039]

2006-04-03  Andreas Kupries <andreask@activestate.com>

	* generic/tclIO.c (ReadChars): Added check, panic and commentary to a
	piece of code which relies on BUFFER_PADDING to create enough space at
	the beginning of each buffer for the insertion of partial multibyte
	data at the beginning of a buffer. Commentary explains why this code
	is OK, and the panic is as a precaution if someone twiddled the
	BUFFER_PADDING into uselessness.

	* generic/tclIO.c (ReadChars): Temporarily suppress the use of
	TCL_ENCODING_END set when EOF was reached while the buffer we are
	converting is not truly the last buffer in the queue. Together with
	the Utf bug below it was possible to completely wreck the buffer data
	structures, eventually crashing Tcl. [Bug 1462248]

	* generic/tclEncoding.c (UtfToUtfProc): Stop accessing memory beyond
	the end of the input buffer when TCL_ENCODING_END is set and the last
	bytes of the buffer start a multi-byte sequence. This bug contributed
	to [Bug 1462248].

2006-03-30  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: remove unused var and silence gcc warning

2006-03-29  Jeff Hobbs	<jeffh@ActiveState.com>

	* win/Makefile.in: convert _NATIVE paths to use / to avoid ".\"
	path-as-escape issue.

2006-03-29  Don Porter	<dgp@users.sourceforge.net>

	* changes:	Updates for another RC.

	* generic/tclPathObj.c:	 More fixes for path normalization when /../
	* tests/fileSystem.test: tries to go beyond root.[Bug 1379287]

	* generic/tclExecute.c: Revised INST_MOD implementation to do
	calculations in native types as much as possible, moving to mp_ints
	only when necessary.

2006-03-28  Jeff Hobbs	<jeffh@ActiveState.com>

	* win/tclWinPipe.c (TclpCreateProcess): change panics to Tcl errors
	and do proper refcounting of noe objPtr. [Bug 1194429]

	* unix/tcl.m4, win/tcl.m4: []-quote AC_DEFUN functions.

2006-03-28  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Tcl.xcode/default.pbxuser:	add '-singleproc 1' cli arg to
	* macosx/Tcl.xcodeproj/default.pbxuser: tcltest to ease test debugging

	* macosx/Tcl.xcode/project.pbxproj:	removed $prefix/share from
	* macosx/Tcl.xcodeproj/project.pbxproj: TCL_PACKAGE_PATH as per change
	to unix/configure.in of 2006-03-13.

	* unix/tclUnixFCmd.c (TclpObjNormalizePath): deal with *BSD/Darwin
	realpath() converting relative paths into absolute paths [Bug 1064247]

2006-03-28  Vince Darley  <vincentdarley@sourceforge.net>

	* generic/tclIOUtil.c: fix to nativeFilesystemRecord comparisons
	(lesser part of [Bug 1064247])

2006-03-27  Pat Thoyts	<patthoyts@users.sourceforge.net>

	* win/tclWinTest.c:	Fixes for [Bug 1456373] (mingw-gcc issue)

2006-03-27  Andreas Kupries <andreask@activestate.com>

	* doc/CrtChannel.3:    Added TCL_CHANNEL_VERSION_5, made it the
	* generic/tcl.h:       version where the "truncateProc" is defined at,
	* generic/tclIO.c:     and moved all channel drivers of Tcl to v5.
	* generic/tclIOGT.c, generic/tclIORChan.c, unix/tclUnixChan.c:
	* unix/tclUnixPipe.c, win/tclWinChan.c, win/tclWinConsole.c:
	* win/tclWinPipe.c, win/tclWinSerial.c, win/tclWinSock.c:

2006-03-27  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c: Merge INST_MOD computation in with the
	INST_?SHIFT instructions, which also operate only on two integral
	values. Also corrected flaw that made INST_BITNOT of wide values
	require mp_int calculations. Also corrected type that missed optimized
	handling of the tclBooleanType by the TclGetBooleanFromObj macro.

	* changes:	Updates for another RC.

2006-03-25  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c: Corrections to INST_EXPON detection of
	overflow to use mp_int calculations.

2006-03-24  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclExecute.c (TclExecuteByteCode): Added a couple of missing
	casts to 'int' that were affecting compilablity on VC6.

2006-03-24  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclEncoding.c: Reverted latest change [Bug 506653] since it
	reportedly killed test performance on Windows.

	* generic/tclExecute.c: Revised INST_EXPON implementation to do
	calculations in native types as much as possible, moving to mp_ints
	only when necessary.

2006-03-23  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c: Merged INST_EXPON handling in with the other
	binary operators that operate on all number types (INST_ADD, etc.).

	* tests/env.test: With case preserved (see 2006-03-21 commit) be sure
	to do case-insensitive filtering. [Bug 1457065]

2006-03-23  Reinhard Max  <max@suse.de>

	* unix/tcl.spec: Cleaned up and completed the spec file. An RPM can
	now be built from the tcl source distribution with "rpmbuild -tb
	<tarball>"

2006-03-22  Reinhard Max  <max@suse.de>

	* tests/stack.test: Run the stack tests in subshells, so that they are
	reported as failed tests rather than bugs in the test suite if the
	recursion causes a segfault.

2006-03-21  Don Porter	<dgp@users.sourceforge.net>

	* changes:	Updates for another RC.

	* generic/tclStrToD.c:	One of the branches of AccumulateDecimalDigit
	* tests/parseExpr.test: did not. [Bug 1451233]

	* tests/env.test:	Preserve case of saved env vars. [Bug 1409272]

2006-03-21  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclInt.decls:	 implement globbing for HFS creator & type
	* macosx/tclMacOSXFCmd.c:codes and 'hidden' flag, as documented in
	* tests/macOSXFCmd.test: glob.n; objectified OSType handling in [glob]
	* unix/tclUnixFile.c:	 and [file attributes]; fix globbing for
	hidden files with pattern==NULL arg. [Bug 823329]
	* generic/tclIntPlatDecls.h:
	* generic/tclStubInit.c: make genstubs

2006-03-20  Andreas Kupries <andreask@activestate.com>

	* win/Makefile.in (install-libraries): Generate tcl8/8.4 directory
	under Windows as well (cygwin Makefile). Related entry: 2006-03-07,
	dgp. This moved the installation of http from 8.2 to 8.4, partially. A
	fix of the required directory creation was done for unix on Mar 10,
	without entry in the Changelog. This entry is for the fix of the
	directory creation under Windows.

	* unix/installManPage: There is always one even more broken "sed".
	Moved the # comment starting character in the sed script to the
	beginning of their respective lines. The AIX sed will not recognize
	them as comments otherwise :( The actual text stays indented for
	better association with the commands they belong to.

2006-03-20  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* tests/cmdAH.test, tests/fCmd.test, tests/unixFCmd.test:
	* tests/winFCmd.test: Cleanup of some test constraint handling, and a
	few other minor issues.

2006-03-18  Vince Darley  <vincentdarley@sourceforge.net>

	* generic/tclFileName.c:
	* doc/FileSystem.3:
	* tests/fileName.test: Fix to [Bug 1084705] so that 'glob -nocomplain'
	finally agrees with its documentation and doesn't swallow genuine
	errors.

	***POTENTIAL INCOMPATIBILITY*** for scripts that assumed '-nocomplain'
	removes the need for 'catch' to deal with non-understood path names.

	Small optimisation to implementation of pattern==NULL case of TclGlob,
	and clarification to the documentation. [Tclvfs bug 1405317]

2006-03-18  Vince Darley  <vincentdarley@sourceforge.net>

	* tests/fCmd.test: added knownBug test case for [Bug 1394972]

	* tests/winFCmd.test:
	* tests/tcltest.test: corrected tests to better account for behaviour
	of writable/non-writable directories on Windows 2000/XP. This, with
	the previous patches, closes [Bug 1193497]

2006-03-17  Andreas Kupries <andreask@activestate.com>

	* doc/chan.n: Updated with documentation for the commands 'chan
	create' and 'chan postevent' (TIP #219).

	* doc/refchan.n: New file. Documentation of the command handler API
	for reflected channels (TIP #219).

2006-03-17  Joe Mistachkin <joe@mistachkin.com>

	* unix/tclUnixPort.h: Include pthread.h prior to pthread_np.h [Bug
	1444692]

	* win/tclWinTest.c: Corrected typo of 'initializeMutex' that prevented
	successful compilation.

2006-03-16  Andreas Kupries <andreask@activestate.com>

	* doc/open.n: Documented the changed behaviour of 'a'ppend mode.

	* tests/io.test (io-43.1 io-44.[1234]): Rewritten to be self-contained
	with regard to setup and cleanup. [Bug 681793]

	* generic/tclIOUtil.c (TclGetOpenMode): Added the flag O_APPEND to the
	list of POSIX modes used when opening a file for 'a'ppend. This
	enables the proper automatic seek-to-end-on-write by the OS. See [Bug
	680143] for longer discussion.

	* tests/ioCmd.test (iocmd-13.7.*): Extended the testsuite to check the
	new handling of 'a'.

2006-03-15  Andreas Kupries <andreask@activestate.com>

	* tests/socket.test: Extended the timeout in socket-11.11 from 10 to
	40 seconds to allow for really slow machines. Also extended
	actual/expected results with value of variable 'done' to make it
	clearer when a test fails due to a timeout. [Bug 792159]

2006-03-15  Vince Darley  <vincentdarley@sourceforge.net>

	* win/fCmd.test: add proper test constraints so the new tests don't
	run on Unix.

2006-03-14  Andreas Kupries <andreask@activestate.com>

	* generic/tclPipe.c (TclCreatePipeline): Modified the processing of
	pipebars to fail if the last bar is followed only by redirections.
	[Bug 768659]

2006-03-14  Andreas Kupries <andreask@activestate.com>

	* doc/fconfigure.n: Clarified that -translation is binary is reported
	as lf when queried, because it is identical to lf, except for the
	special additional behaviour when setting it. [Bug 666770]

2006-03-14  Andreas Kupries <andreask@activestate.com>

	* doc/clock.n: Removed double-quotes around section title NAME; not
	needed.
	* unix/installManpage: Reverted part to handle double-quotes in
	section NAME, chokes older sed installations.

2006-03-14  Andreas Kupries <andreask@activestate.com>

	* library/tm.tcl (::tcl::tm::Defaults): Fixed handling of environment
	variable TCLX.y_TM_PATH, bad variable reference. Thanks to Julian
	Noble. [Bug 1448251]

2006-03-14  Vince Darley  <vincentdarley@sourceforge.net>

	* win/tclWinFile.c: updated patch to deal with 'file writable' issues
	on Windows XP/2000.
	* generic/tclTest.c:
	* unix/tclUnixTest.c:
	* win/tclWinTest.c:
	* tests/fCmd.test: updated test suite to deal with correct permissions
	setting and differences between XP/2000 and 95/98 3 tests still fail;
	to be dealt with shortly

2006-03-13  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclEncoding.c: Report error when an escape encoding is
	missing one of its sub-encodings. [Bug 506653]

	* unix/configure.in:	Revert change from 2005-07-26 that sometimes
	* unix/configure:	added $prefix/share to the tcl_pkgPath. See
	[Patch 1231015]. autoconf-2.59.

2006-03-10  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclProc.c (ObjInterpProcEx):
	* tests/apply.test (apply-5.1): Fix [apply] error messages so that
	they quote the lambda expression. [Bug 1447355]

2006-03-10  Zoran Vasiljevic  <vasiljevic@users.sourceforge.net>

	-- Summary of changes fixing [Bug 1437595] --

	* generic/tclEvent.c: Cosmetic touches and identation
	* generic/tclInt.h: Added TclpFinalizeSockets() call.

	* generic/tclIO.c: Calls TclpFinalizeSockets() as part of the
	TclFinalizeIOSubsystem().

	* unix/tclUnixSock.c: Added no-op TclpFinalizeSockets().

	* win/tclWinPipe.c, win/tclWinSock.c: Finalization of sockets/pipes is
	now solely done in TclpFinalizeSockets() and TclpFinalizePipes() and
	not over the thread-exit handler, because the order of actions the Tcl
	generic core will impose may result in cores/hangs if the thread exit
	handler tears down corresponding subsystem(s) too early.

2006-03-10  Vince Darley  <vincentdarley@sourceforge.net>

	* win/tclWinFile.c: previous patch breaks tests, so removed.

2006-03-09  Vince Darley  <vincentdarley@sourceforge.net>

	* win/tclWinFile.c: fix to 'file writable' in certain XP directories.
	Thanks to fvogel and jfg. [Patch 1344540] Modified patch to make use
	of existing use of getSecurityProc.

2006-03-08  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclExecute.c: Complete missing bit of TIP 215 implementation
	* tests/incr.test:

2006-03-07  Joe English	 <jenglish@users.sourceforge.net>

	* unix/tcl.m4: Set SHLIB_LD_FLAGS='${LIBS}' on NetBSD, as per the
	other *BSD variants. [Bug 1334613]
	* unix/configure: Regenerated.

2006-03-07  Don Porter	<dgp@users.sourceforge.net>

	* changes:	Update in prep. for 8.5a4 release.

	* unix/Makefile.in:	Package http 2.5.2 requires Tcl 8.4, so the
	* win/Makefile.in:	*.tm installation has to be placed in an "8.4"
	directory, not an "8.2" directory.

2006-03-06  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Revised handling of TCL_EVAL_* flags to
	* tests/parse.test:	simplify TclEvalObjvInternal and to correct
	the auto-loading of alias targets (parse-8.12). [Bug 1444291]

2006-03-03  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclPathObj.c: Revised yesterday's fix for [Bug 1379287] to
	work on Windows.

	* generic/tclObj.c:	Compatibility support for existing code that
	calls Tcl_GetObjType("boolean").

2006-03-02  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclPathObj.c:		Fix for failed normalization of paths
	* tests/fileSystem.test:	with /../ that lead back to the root
	of the filesystem, like /foo/.. [Bug 1379287]

2006-03-01  Reinhard Max  <max@suse.de>

	* unix/installManPage: Fix the script for manpages that have quotes
	around the .SH arguments, as doctools produces them. [Bug 1292145]
	Some minor cleanups and improvements.

2006-02-28  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Corrections to be sure that TCL_EVAL_GLOBAL
	* tests/namespace.test: evaluations act the same as [uplevel #0]
	* tests/parse.test:	evaluations, even when execution traces or
	* tests/trace.test:	invocations of [::unknown] are present. [Bug
	1439836]

2006-02-22  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Corrected a few bugs in how [namespace
	* tests/namespace.test: unknown] interacts with TCL_EVAL_* flags.
	[Patch 958222]

2006-02-17  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclIORChan.c: Revised error message generation and handling
	* tests/ioCmd.test:	of exceptional return codes in the channel
	reflection layer. [Bug 1372348]

2006-02-16  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclIndexObj.c:	Disallow the "ambiguous" error message
	* tests/indexObj.test:		when TCL_EXACT matching is requested.
	* tests/ioCmd.test:

2006-02-15  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclIO.c:	Made several routines tolerant of
	* generic/tclIORChan.c: interp == NULL arguments. [Bug 1380662]
	* generic/tclIOUtil.c:

2006-02-09  Don Porter	<dgp@users.sourceforge.net>

	TIP#215 IMPLEMENTATION

	* doc/incr.n:		Revised [incr] to auto-initialize when varName
	* generic/tclExecute.c: argument is unset. [Patch 1413115]
	* generic/tclVar.c:
	* tests/compile.test:
	* tests/incr-old.test:
	* tests/incr.test:
	* tests/set.test:

	* tests/main.test (Tcl_Main-6.7):	Improved robustness of
	command auto-completion test. [Bug 1422736]

2006-02-08  Donal K. Fellows  <dkf@users.sf.net>

	* doc/Encoding.3, doc/encoding.n: Updates due to review at request of
	Don Porter. Mostly minor changes.

2006-02-08  Don Porter	<dgp@users.sourceforge.net>

	TIP#258 IMPLEMENTATION

	* doc/Encoding.3:	New subcommand [encoding dirs].
	* doc/encoding.n:	New routine Tcl_GetEncodingNameFromEnvironment
	* generic/tcl.decls:	Made public:
	* generic/tclBasic.c:	TclGetEncodingFromObj
	* generic/tclCmdAH.c:		-> Tcl_GetEncodingFromObj
	* generic/tclEncoding.c:TclGetEncodingSearchPath
	* generic/tclInt.decls:		-> Tcl_GetEncodingSearchPath
	* generic/tclInt.h:	TclSetEncodingSearchPath
	* generic/tclTest.c:		-> Tcl_SetEncodingSearchPath
	* library/init.tcl:	Removed commands:
	* tests/cmdAH.test:		[tcl::unsupported::EncodingDirs]
	* tests/encoding.test:		[testencoding path] (Tcltest)
	* unix/tclUnixInit.c:	[Patch 1413934]
	* win/tclWinInit.c:

	* generic/tclDecls.h:	make genstubs
	* generic/tclIntDecls.h:
	* generic/tclStubInit.c:

2006-02-01  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclProc.c: minor improvements to [apply]
	* tests/apply.test: new tests; apply-5.1 currently fails to indicate
	missing work in error reporting

2006-02-01  Don Porter	<dgp@users.sourceforge.net>

	TIP#194 IMPLEMENTATION

	* doc/apply.n:	(New file)	New command [apply]. [Patch 944803]
	* doc/uplevel.n:
	* generic/tclBasic.c:
	* generic/tclInt.h:
	* generic/tclProc.c:
	* tests/apply.test: (New file)
	* tests/proc-old.test:
	* tests/proc.test:

	TIP#181 IMPLEMENTATION

	* doc/Namespace.3:	New command [namespace unknown]. New public C
	* doc/namespace.n:	routines Tcl_(Get|Set)NamespaceUnknownHandler.
	* doc/unknown.n:	[Patch 958222]
	* generic/tcl.decls:
	* generic/tclBasic.c:
	* generic/tclInt.h:
	* generic/tclNamesp.c:
	* tests/namespace.test:

	* generic/tclDecls.h:	make genstubs
	* generic/tclStubInit.c:

	TIP#250 IMPLEMENTATION

	* doc/namespace.n:	New command [namespace upvar]. [Patch 1275435]
	* generic/tclInt.h:
	* generic/tclNamesp.c:
	* generic/tclVar.c:
	* tests/namespace.test:
	* tests/upvar.test:

2006-01-26  Donal K. Fellows  <dkf@users.sf.net>

	* doc/dict.n: Fixed silly bug in example. Thanks to Heiner Marxen
	<heiner.marxen@unsel.de> for catching this! [Bug 1415725]

2006-01-26  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* unix/tclUnixChan.c (TclpOpenFileChannel): Tidy up and comment the
	mess to do with setting up serial channels. This (deliberately) breaks
	a broken FreeBSD port, indicates what we're really doing, and reduces
	the amount of conditional compilation sections for better maintenance.

2006-01-25  Donal K. Fellows  <dkf@users.sf.net>

	* unix/tclUnixInit.c (TclpInitPlatform): Improved conditions on when
	to update the FP rounding mode on FreeBSD, taken from FreeBSD port.

2006-01-23  Donal K. Fellows  <dkf@users.sf.net>

	* tests/string.test (string-12.21): Added test for [Bug 1410553] based
	on original bug report.

2006-01-23  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclStringObj.c: fixed incorrect handling of internal rep in
	Tcl_GetRange. Thanks to twylite and Peter Spjuth. [Bug 1410553]

	* generic/tclProc.c: fixed args handling for precompiled bodies [Bug
	1412695]; thanks to Uwe Traum.

2006-01-16  Reinhard Max  <max@suse.de>

	* generic/tclPipe.c (FileForRedirect): Prevent nameString from being
	freed without having been initialized.
	* tests/exec.test: Added a test for the above.

2006-01-12  Zoran Vasiljevic  <vasiljevic@users.sourceforge.net>

	* generic/tclPathObj.c (Tcl_FSGetInternalRep): backported patch from
	core-8-4-branch. A freed pointer has been overwritten causing all
	sorts of coredumps.

2006-01-12  Vince Darley  <vincentdarley@sourceforge.net>

	* win/tclWinFile.c: fix to sharing violation [Bug 1366227]

2006-01-11  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Moved Tcl_LogCommandInfo from tclBasic.c to
	* generic/tclNamesp.c:	tclNamesp.c to get access to identifier with
	* tests/error.test (error-7.0): file scope. Added check for traces on
	::errorInfo, and when present fall back to contruction of the stack
	trace in the variable so that write trace notification timings are
	compatible with earlier Tcl releases. This reduces, but does not
	completely eliminate the ***POTENTIAL INCOMPATIBILITY*** created by
	the 2004-10-15 commit. [Bug 1397843]

2006-01-10  Daniel Steffen  <das@users.sourceforge.net>

	* unix/configure:    add caching, use AC_CACHE_CHECK instead of
	* unix/configure.in: AC_CACHE_VAL where possible, consistent message
	* unix/tcl.m4:	     quoting, sync relevant tclconfig/tcl.m4 changes
	and gratuitous formatting differences, fix SC_CONFIG_MANPAGES with
	default argument, Darwin improvements to SC_LOAD_*CONFIG.

2006-01-09  Don Porter	<dgp@users.sourceforge.net>

	* generic/tclNamesp.c (NamespaceInscopeCmd):	[namespace inscope]
	* tests/namespace.test: commands were not reported by [info level].
	[Bug 1400572]

2006-01-09  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* generic/tclTrace.c: Stop exporting the guts of the trace command;
	nothing outside this file needs to see it. [Bug 971336]

2006-01-05  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* unix/tcl.m4 (TCL_CONFIG_SYSTEM): Factor out the code to determine
	the operating system version number, as it was replicated in several
	places.

2006-01-04  David Gravereaux  <davygrvy@pobox.com>

	* win/tclAppInit.c: WIN32 native console signal handler removed. This
	was found to be interfering with TWAPI extension one. IMO, special
	services such as signal handlers should best be done with extensions
	to the core after discussions on c.l.t. about Roy Terry's tclsh
	children of a real windows service shell.

	******************************************************************
	*** CHANGELOG ENTRIES FOR 2005 IN "ChangeLog.2005"	       ***
	*** CHANGELOG ENTRIES FOR 2004 IN "ChangeLog.2004"	       ***
	*** CHANGELOG ENTRIES FOR 2003 IN "ChangeLog.2003"	       ***
	*** CHANGELOG ENTRIES FOR 2002 IN "ChangeLog.2002"	       ***
	*** CHANGELOG ENTRIES FOR 2001 IN "ChangeLog.2001"	       ***
	*** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000"	       ***
	*** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" ***
	******************************************************************

Deleted ChangeLog.2008.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
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
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796




















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
2008-12-31  Don Porter  <dgp@users.sourceforge.net>

	* unix/Makefile.in:	Set TCLLIBPATH in SHELL_ENV so that targets
	like `make shell` have access to builds of bundled packages.

2008-12-28  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclZlib.c (Tcl_ZlibStreamPut): Plug a memory leak.

2008-12-27  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclZlib.c (ZlibStreamCmd): Fix compilation consistency. [Bug
	* generic/tcl.decls:		     2470237]

	* generic/tclZlib.c (Tcl_ZlibStreamGet): Corrected the semantics of
	this function to be useful to the PNG implementation. If the argument
	object is empty, this gives the previous semantics.
	(Tcl_ZlibStreamChecksum): Corrected name to be less misleading; it
	only produced Adler-32 checksums when the stream was processing the
	right type of compressed data format.
	(Tcl_ZlibAdler32, Tcl_ZlibCRC32): Corrected types so that they work
	naturally with the results of Tcl_GetByteArrayFromObj().
	*** POTENTIAL INCOMPATIBILITY *** for all above changes, but very
	unlikely to be difficult for anyone to deal with.

2008-12-26  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tcl.decls: Tidy up the commenting style, adding markers for
	each of the big release points under TCT stewardship and noting the
	general purpose of each TIP that added C API. Overall effect is to
	make this file much more informative to read without having to spend
	effort correlating with TIPs and ChangeLogs.

2008-12-23  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/Makefile.in:	Fix build of zlib objects with msvc
	* win/tcl.m4:
	* win/configure:	autoconf-2.59

2008-12-23  Donal K. Fellows  <dkf@users.sf.net>

	* win/Makefile.in: Handle file extensions correctly. [Bug 2459725]

2008-12-22  Pat Thoyts  <patthoyts@users.sourceforge.net>

	*** 8.6b1 TAGGED FOR RELEASE ***

	* win/makefile.vc: Ensure pkgs directories are suitable and quote the
			   paths. [Bug 2458395]

2008-12-22  Joe Mistachkin  <joe@mistachkin.com>

	* tools/man2help2.tcl: Added support for "\(mi" nroff macro. [Bug
	2330040]

2008-12-22  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* win/makefile.vc: Support the pkgs tree in the NMAKE builds.

2008-12-21  Daniel Steffen  <das@users.sourceforge.net>

	* unix/Makefile.in:	Fix broken build of bundled packages when path
				to build dir contains spaces by switching to
				relative paths to toplevel build dir.

	* unix/configure.in:	Preserve configure environment variables for
				sub-configures of bundled packages; reuse
				configure cache file for sub-configures.

	* unix/configure:	autoconf-2.59

2008-12-21  Donal K. Fellows  <dkf@users.sf.net>

	* doc/TclZlib.3: Fix minor typo. [Bug 2455165]

2008-12-20  Kevin B. Kenny  <kennykb@acm.org>

	* win/Makefile.in:	Renamed the static library libtcl86s.a to
	* win/configure.in:	have a name distinct from the import library
				libtcl86.a. This renaming dodges an ancient
				bug in the Makefile revealed by the last
				commit where the $(TCL_LIB_FILE) rule can
				fire to try to build the static library in a
				--enable-shared build (and create a static
				library that subsequently fails to link).
				Revised the zlib objects so that they are
				built directly into the build dir, without
				building an intermediate static library.
				*** POTENTIAL INCOMPATIBILITY *** for
				embedders who link to the static library, but
				I couldn't figure out how to sort this out
				any other way.
	* win/configure:	Autoconf 2.59

2008-12-20  Donal K. Fellows  <dkf@users.sf.net>

	* win/Makefile.in: Minor updates to make building work better with
	msys on Windows. (Apparently the gcc used doesn't like a / at the end
	of a -I argument...)

2008-12-20  Don Porter  <dgp@users.sourceforge.net>

	* changes:	Updates for 8.6b1 release.

2008-12-20  Daniel Steffen  <das@users.sourceforge.net>

	* unix/Makefile.in:	Make package install directory of bundled
	* unix/configure.in:	packages configurable via PACKAGE_DIR makefile
				variable (set to platform-specific default).

	* unix/Makefile.in (*-packages): Ensure toplevel targets fail if
				sub-make/configure fails; fix quoting when
				builddir path contains spaces.

	* macosx/GNUmakefile:	Add install-packages to install targets.

	* unix/configure:	autoconf-2.59

2008-12-19  Don Porter  <dgp@users.sourceforge.net>

	* doc/NRE.3:		Formatting errors found by `make html`
	* doc/Tcl_Main.3:
	* doc/zlib.n:

	* tests/chanio.test:	Add missing [removeFile] cleanups.
	* tests/io.test:	Add missing [close $f] to io-73.2.

	* unix/Makefile.in:	Update `make dist' target to include the files
	from the compat/zlib directory as well as all the bundled packages
	found under the pkgs directory, according to their individual `make
	dist' targets. Change includes breaking a `configure-packages' target
	out of the `packages` target.

	* README:		Bump version number to 8.6b1
	* generic/tcl.h:
	* library/init.tcl:
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/configure.in:

	* unix/configure:	autoconf-2.59
	* win/configure:

2008-12-19  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.decls: CONSTify TclGetLoadedPackages second param
	* generic/tclLoad.c
	* generic/tclIntDecls.h (regenerated)

2008-12-19  Kevin Kenny  <kennykb@acm.org>

	* generic/tclExecute.c:	Fix compile warnings when --enable-symbols=all

	* win/configure.in:
	* win/Makefile.in: Added build of packages in the 'pkgs/' directory.
	* win/configure: Autoconf 2.59

2008-12-19  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* win/makefile.vc: Added build of compat/zlib

2008-12-18  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c (Tcl_CloseEx, CloseWrite, CloseChannelPart)
	(ChanCloseHalf): Rewrite the half-close to properly flush the channel,
	like is done for a full close, going through FlushChannel, and using
	the flag BG_FLUSH_SCHEDULED (async flush during close). New functions
	CloseWrite, CloseChannelPart, new flag CHANNEL_CLOSEDWRITE.

	* tests/chanio.test (chanio-28.[67]): Reactivated these tests.
	Replaced tclsh -> [interpreter] to get correct executable for the pipe
	process, and added after cancel to kill the fail timers when we are
	done. Removed the explicits calls to [flush], now that [close] handles
	this correctly.

2008-12-18  Don Porter  <dgp@users.sourceforge.net>

	* tests/chanio.test:	Replaced [chan event] handlers that returned
	TCL_RETURN return code, with more conventional ones that return TCL_OK
	to suppress otherwise strange writes of outdated $::errorInfo values
	to stderr. [Bug 2444274]

	* generic/tclExecute.c:	Disabled apparently faulty assertion. [Bug
	2415422]

2008-12-18  Donal K. Fellows  <dkf@users.sf.net>

	* unix/configure.in, unix/Makefile.in: Autoconf wizardry.
	* compat/zlib/*: Import of zlib 1.2.3. The license is directly
	compatible with Tcl's. This import omits the obsolete and contributed
	parts (i.e. selected directories) and the supplied examples.

	* generic/tclZlib.c:	First implementation of the compressing and
	* doc/zlib.n:		decompressing channel transformations.
	* tests/zlib.test (zlib-8.*):

2008-12-18  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.decls:	VOID -> void
	* generic/tclInt.decls:
	* compat/dlfcn.h:
	* generic/tclDecls.h:	(regenerated)
	* generic/tclIntDecls.h:

2008-12-18  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	TIP #332 IMPLEMENTATION - Half-Close for Bidirectional Channels

	* doc/close.n, generic/tclIO.c, generic/tclIOCmd.c:
	* unix/tclUnixChan.c, unix/tclUnixPipe.c, win/tclWinSock.c:
	* generic/tcl.decls, generic/tclDecls.h, generic/tclStubInit.c:
	* tests/chan.test, tests/chanio.test, tests/ioCmd.test:

2008-12-17  Donal K. Fellows  <dkf@users.sf.net>

	* doc/SetChanErr.3: General improvements in nroff rendering and some
	corrections to language issues.

2008-12-17  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclResult.c:	   Move variable "length" inside if()
	* generic/tclStringObj.c:  Don't use ckfree((void *)...) but
	* generic/tclVar.c:	   ckfree((char *)...)
	* generic/tclZlib.c
	* generic/tclBasic.c

2008-12-17  Donal K. Fellows  <dkf@users.sf.net>

	* tests/namespace.test (namespace-28.1):	Make tests not
	* tests/namespace-old.test (namespace-old-9.5): dependent on the
	global namespace's particular imports. [Bug 2433936]

2008-12-17  Don Porter  <dgp@users.sourceforge.net>

	* unix/Makefile.in:	Modify the distclean-packages target so that
	empty build directories are deleted.

	* unix/Makefile.in:	Add build support for collections of TEA
	* unix/configure.in:	packages found under the pkgs directory.
	[Patch 1163406]. Still needs porting to Windows.

	* unix/configure:	autoconf-2.59

2008-12-17  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tcl.h, generic/tclZlib.c: Removed undocumented flag.

2008-12-16  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclThreadTest.c: Eliminate -Wwrite-strings warnings in
				   --enable-threads build.
	* generic/tclExecute.c:	   Use TclNewLiteralStringObj()
	* unix/tclUnixFCmd.c:	   Use TclNewLiteralStringObj()
	* win/tclWinFCmd.c:	   Use TclNewLiteralStringObj()

2008-12-16  Donal K. Fellows  <dkf@users.sf.net>

	TIP #329 IMPLEMENTATION

	* tests/error.test: Tests for the new commands.
	* doc/throw.n, doc/try.n: Documentation of the new commands.
	* library/init.tcl (throw, try): Implementation of commands documented
	in TIP. This implementation is in Tcl and is a stop-gap until
	higher-performance ones can be written.

2008-12-16  Don Porter  <dgp@users.sourceforge.net>

	* generic/tcl.h:	Add TIP 338 routines to stub table.
	* generic/tcl.decls:	[Bug 2431338]

	* generic/tclDecls.h:	make genstubs
	* generic/tclStubInit.c:

2008-12-15  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclExecute.c (TEBC:INST_DICT_GET): Make sure that the result
	is empty when generating an error message. [Bug 2431847]

2008-12-15  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclBinary.c:	Redefine non-strict decoding to ignore only
	* doc/binary.n:		whitespace. [Bug 2380293]
	* tests/binary.test:

2008-12-15  Don Porter  <dgp@users.sourceforge.net>

	* doc/AddErrInfo.3:	Documented Tcl_(Set|Get)ErrorLine (TIP 336).
	* doc/CrtCommand.3:	Various other documentation updates to
	* doc/CrtInterp.3:	reflect the lack of access to Tcl_Interp
	* doc/Interp.3:		fields by default.
	* doc/SetResult.3:
	* doc/tcl.decls:

	TIP #338 IMPLEMENTATION

	* doc/AppInit.c:	Made routines Tcl_SetStartupScript and
	* doc/Tcl_Main.3:	Tcl_GetStartupScript public. Removed all
	* generic/tcl.h:	internal stub access to Tcl*Startup* routines,
	* generic/tclInt.decls:	and removed their implementations. Their
	* generic/tclMain.c:	function can now be completely performed with
				the new public interface.
	*** POTENTIAL INCOMPATIBILITY for callers of the internal
	    Tcl*Startup* routines. ***

	* generic/tclIntDecls.h:	make genstubs
	* generic/tclStubInit.c:
	* generic/tclDecls.h:

2008-12-14  Donal K. Fellows  <dkf@users.sf.net>

	* tests/zlib.test: Added constraint so that tests don't fail where
	they cannot work due to zlib support being missing.

	* unix/configure.in, win/configure.in: Improve the autodetection code.
	* win/tcl.m4 (SC_CONFIG_CFLAGS): Remove the assumption of the presence
	of zlib library on Windows.
	* win/makefile.vc, win/makefile.bc: Add support for building tclZlib.o
	but only in stubbed-out mode for now.

2008-12-13  Donal K. Fellows  <dkf@users.sf.net>

	* doc/TclZlib.3: Basic documentation of the C-level API.
	* doc/zlib.n: Substantially improve documentation of Tcl-level API.
	* generic/tclZlib.c (ZlibCmd): Flesh out the argument parsing for the
	command to integrate with channels.

2008-12-12  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclZlib.c (Tcl_ZlibInflate): Change PATH_MAX to MAXPATHLEN,
	since MSVC doesn't have PATH_MAX.

	* doc/clock.n:	Document new DST fallback rules.
	* library/clock.tcl (ProcessPosixTimeZone): Fix time change in Eastern
	Europe (not 3:00 but 4:00 local time). [Bug 2207436]

2008-12-12  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclZlib.c, unix/configure.in: Added stubs to use when the
	version of zlib is not capable enough, and automagic to detect when
	that is the case. [Bug 2421265]

2008-12-12  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* unix/tclUnixNotfy.c: Fix missing CLOEXEC on internal pipes [2417695]
	* unix/tclUnixPipe.c:  Fix missing CLOEXEC on [chan pipe] fds.

2008-12-12  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclZlib.c (Tcl_ZlibDeflate): Add a bit of extra space for
	the gzip header. [Bug 2419061]
	(Tcl_ZlibInflate): Ensure that gzip header extraction is done
	correctly.

2008-12-12  Kevin Kenny  <kennykb@acm.org>

	TIP #322 IMPLEMENTATION

	* doc/NRE.3 (new file): Added documentation of the published API for
	Non-Recursive Evaluation (NRE).

2008-12-11  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclZlib.c: Eliminate warning: different 'const' qualifiers
	with msvc compiler. A few more 'const' optimizations.
	* win/tcl.m4: Fix Windows build (msvc) for TIP #234 implementation
	* win/Makefile.in:
	* win/configure:

2008-12-11  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c (SetChannelFromAny and related): Modified the
	* tests/io.test: internal representation of the tclChannelType to
	contain not only the ChannelState pointer, but also a reference to
	the interpreter it was made in. Invalidate and recompute the
	internal representation when it is used in a different interpreter,
	like cmdName intrep's. Added testcase. [Bug 2407783]

2008-12-11  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclZlib.c (ConvertError): Factor out code to turn zlib
	errors into Tcl errors.

	* doc/zlib.n: Added a start at the documentation. Still very rough.

2008-12-11  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/Makefile.in: Fix Windows build (mingw) for TIP #234
	implementation (additionally, first make sure that zlib is available,
	and rename the standard zdll.lib to libz.a, but at least this works so
	far).

2008-12-11  Donal K. Fellows  <dkf@users.sf.net>

	* tests/zlib.test: Start of test suite for zlib command.

2008-12-11  Jan Nijtmans  <nijtmans@users.sf.net>

	* library/clock.tcl (ProcessPosixTimeZone): Fallback to European time
	zone DST rules, when the timezone is between 0 and -12. [Bug 2207436]
	* tests/clock.test (clock-52.[23]): Test cases for [Bug 2207436]

2008-12-11  Donal K. Fellows  <dkf@users.sf.net>

	TIP #234 IMPLEMENTATION

	* generic/tclZlib.c: A very preliminary hack at an interface to the
	zlib library, based on code from Pascal Scheffers.
	WARNING! The C API may be subect to change without much warning! USE
	AT YOUR OWN RISK!

2008-12-10  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata/*: Update from Olson's tzdata2008i.

2008-12-10  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	TIP #343 IMPLEMENTATION - A Binary Specifier for [format/scan]

	* doc/format.n
	* doc/scan.n
	* generic/tclInt.h
	* generic/tclScan.c
	* generic/tclStrToD.c
	* generic/tclStringObj.c
	* tests/format.test
	* tests/scan.test

2008-12-10  Donal K. Fellows  <dkf@users.sf.net>

	TIP #341 IMPLEMENTATION

	* generic/tclDictObj.c (DictFilterCmd): Made key and value filtering
	* tests/dict.test, doc/dict.n:		accept arbitrary numbers of
						glob arguments.

2008-12-09  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.decls: Restore source and binary compatibility for
				TIP #337 implementation. (When it is _that_
				simple, there is no excuse not to do it! :-))
	* generic/tclIntDecls.h:	make genstubs
	* generic/tclStubInit.c:

2008-12-09  Don Porter  <dgp@users.sourceforge.net>

	TIP #337 IMPLEMENTATION

	* doc/BackgdErr.3:	Converted internal routine
	* doc/interp.n:		TclBackgroundException() into public routine
	* generic/tcl.decls:	Tcl_BackgroundException().
	* generic/tclEvent.c:
	* generic/tclInt.decls:

	* generic/tclDecls.h:	make genstubs
	* generic/tclIntDecls.h:
	* generic/tclStubInit.c:

	* generic/tclIO.c:	Update callers.
	* generic/tclIOCmd.c:
	* generic/tclInterp.c:
	* generic/tclTimer.c:
	*** POTENTIAL INCOMPATIBILITY only for extensions using the converted
	    internal routine ***

2008-12-09  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclIO.c (ChanClose,ChanRead,...): Factored out some of the
	code to connect to channel drivers that was common in multiple
	locations so as to make code more readable.

2008-12-06  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdAH.c (FileTempfileCmd): Force temporary files to be
	created in the native filesystem. Attempting to provide a template
	that puts it elsewhere will result in the directory part of the
	template being ignored. Partial address of [Bug 2388866] concerns.

2008-12-05  Donal K. Fellows  <dkf@users.sf.net>

	TIP #335 IMPLEMENTATION

	* generic/tclBasic.c (Tcl_InterpActive): Added function for working
	* doc/CrtInterp.3:			 out if an interp is in use.

	TIP #307 IMPLEMENTATION

	* generic/tclResult.c (Tcl_TransferResult): Renamed function from
	* generic/tcl.decls:			    TclTransferResult. Added
	* doc/SetResult.3:			    to public stubs table.

2008-12-04  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclPathObj.c (Tcl_FSGetNormalizedPath):	Added another
	flag value TCLPATH_NEEDNORM to mark those intreps which need more
	complete normalization attention for correct results. [Bug 2385549]

2008-12-03  Donal K. Fellows  <dkf@users.sf.net>

	* win/tclWinPipe.c (TclpOpenTemporaryFile): Avoid an infinite loop due
	to GetTempFileName/CreateFile interaction. [Bug 2380318]

2008-12-03  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclFileName.c (DoGlob):    One of the Tcl_FSMatchInDirectory
	calls did not have its return code checked. This caused error messages
	returned by some Tcl_Filesystem drivers to be swallowed.

2008-12-02  Don Porter  <dgp@users.sourceforge.net>

	TIP #336 IMPLEMENTATION

	* generic/tcl.decls:	New routines Tcl_(Get|Set)ErrorLine.
	* generic/tcl.h:	Dropped default access to interp->errorLine.
	* generic/tclCmdAH.c:	Restore it with -DUSE_INTERP_ERRORLINE.
	* generic/tclCmdMZ.c:	Updated callers.
	* generic/tclDictObj.c:
	* generic/tclIOUtil.c:
	* generic/tclNamesp.c:
	* generic/tclOOBasic.c:
	* generic/tclOODefinedCmds.c:
	* generic/tclOOMethod.c:
	* generic/tclProc.c:
	* generic/tclResult.c:
	*** POTENTIAL INCOMPATIBILITY for C code directly using the
	    interp->errorLine field ***

	* generic/tclDecls.h:	make genstubs
	* generic/tclStubInit.c:

2008-12-02  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c (TclFinalizeIOSubsystem): Replaced Alexandre
	Ferrieux's first patch for [Bug 2270477] with a gentler version, also
	supplied by him.

2008-12-01  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclParse.c:  Coding standards fixups.

2008-12-01  Donal K. Fellows  <dkf@users.sf.net>

	* tests/cmdAH.test (cmdAH-32.6): Test was not portable; depended on a
	C API function not universally available. [Bug 2371623]

2008-11-30  Kevin B. Kenny  <kennykb@acm.org>

	* library/clock.tcl (format, ParseClockScanFormat): Added a [string
	map] to get rid of namespace delimiters before caching a scan or
	format procedure. [Bug 2362156]
	* tests/clock.test (clock-64.[12]): Added test cases for the bug that
	was tickled by a namespace delimiter inside a format string.

2008-11-29  Donal K. Fellows  <dkf@users.sf.net>

	TIP #210 IMPLEMENTATION

	* generic/tclCmdAH.c (FileTempfileCmd):
	* unix/tclUnixFCmd.c (TclpOpenTemporaryFile, DefaultTempDir):
	* win/tclWinPipe.c (TclpOpenTemporaryFile):
	* doc/file.n, tests/cmdAH.test: Implementation of [file tempfile]. I
	do not claim that this is a brilliant implementation, especially on
	Windows, but it covers the main points.

	* generic/tclThreadStorage.c: General revisions to make code clearer
	and more like the style used in the rest of the core. Includes adding
	more comments and explanation of what is going on. Reduce the amount
	of locking required.

2008-11-27  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tcl.h:	Alternate fix for [Bug 2251175]: missing
	* generic/tclCompile.c:	backslash substitution on expanded literals.
	* generic/tclParse.c:
	* generic/tclTest.c:
	* tests/parse.test:

2008-11-26  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclIndexObj.c:   Eliminate warning: unused variable
	* generic/tclTest.c:	   A few more (harmless) Tcl_SetResult
				   eliminations.

2008-11-26  Kevin B. Kenny  <kennykb@acm.org>

	* library/tclIndex: Removed reference to no-longer-extant procedure
			    'tclLdAout'.
	* doc/library.n: Corrected mention of 'auto_exec' to 'auto_execok'.
	[Patch 2114900] thanks to Stuart Cassoff <stwo@users.sf.net>

2008-11-25  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclIndexObj.c: Eliminate 3 calls to Tcl_SetResult, as
	* generic/tclIO.c:	 examples how it should have been done.
	* generic/tclTestObj.c:	 purpose: contribute in the TIP #340
				 discussion.

2008-11-25  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c (TclFinalizeIOSubsystem): Applied Alexandre
	Ferrieux's patch for [Bug 2270477] to prevent infinite looping during
	finalization of channels not bound to interpreters.

2008-11-25  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclTest.c: Don't assume that Tcl_SetResult sets
	interp->result, especially not in a DString test, in preparation for
	TIP #340

2008-11-24  Donal K. Fellows  <dkf@users.sf.net>

	* tools/tcltk-man2html.tcl: Improvements to tackle tricky aspects of
	cross references and new entities to map. [Bug 2330040]

2008-11-19  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclThreadTest.c: Convert Tcl_SetResult(......, TCL_DYNAMIC)
	to Tcl_SetResult(......, TCL_VOLATILE), in preparation for TIP #340

2008-11-17  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.decls:	Fix signature and implementation of
	* generic/tclDecls.h:	Tcl_HashStats, such that it conforms to the
	* generic/tclHash.c:	documentation. [Bug 2308236]
	* generic/tclVar.c:
	* doc/Hash.3:
	* generic/tclDictObj.c: Convert Tcl_SetResult call to
	Tcl_SetObjResult.

2008-11-17  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* tests/for.test: Check for uncompiled-for-continue [Bug 2186888]
	fixed earlier.

	* generic/tcl.h:	 Fix [Bug 2251175]: missing backslash
	* generic/tclCompCmds.c: substitution on expanded literals.
	* generic/tclCompile.c
	* generic/tclParse.c
	* generic/tclTest.c
	* tests/compile.test
	* tests/parse.test

2008-11-16  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclTest.c: Replace two times Tcl_SetResult with
	Tcl_SetObjResult, a little simplification in preparation for the TIP
	#340 patch.

2008-11-13  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.h:	Rename static function FSUnloadTempFile to
	* generic/tclIOUtil.c:	TclFSUnloadTempFile, needed in tclLoad.c

	* generic/tclLoad.c:	Fixed [Bug 2269431]: Load of shared
				objects leaves temporary files on windows.

2008-11-12  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* tests/registry.test: Use HKCU to avoid requiring admin access for
	registry testing on Vista/Server2008

2008-11-11  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclNamesp.c:	Eliminate warning: passing arg 4 of
				Tcl_SplitList from incompatible pointer type.
	* win/tcl.m4:	Reverted change from 2008-11-06 (was under the
			impression that "-Wno-implicit-int" added an extra
			warning)
	* win/configure: (regenerated)
	* unix/tcl.m4:	Use -O2 as gcc optimization compiler flag, and get rid
			of -Wno-implicit-int for UNIX.
	* unix/configure: (regenerated)

2008-11-10  Andreas Kupries  <andreask@activestate.com>

	* doc/platform_shell.n: Fixed [Bug 2255235], reported by Ulrich
	* library/platform/pkgIndex.tcl: Ring <uring@users.sourceforge.net>.
	* library/platform/shell.tcl: Updated the LOCATE command in the
	* library/tm.tcl:   package 'platform::shell' to handle the new form
	* unix/Makefile.in: of 'provide' commands generated by tm.tcl. Bumped
	* win/Makefile.in:  package to version 1.1.4. Added cross-references
	to the relevant parts of the code to avoid future desynchronization.

2008-11-07  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* generic/tclInt.h:    Applied [Patch 2215022] from Duoas to clean up
	* generic/tclBinary.c: the binary ensemble initiailization code.
	* generic/tclNamesp.c: Extends the TclMakeEnsemble to do
	* doc/ByteArrObj.3:    sub-ensembles from tables.

2008-11-06  Jan Nijtmans  <nijtmans@users.sf.net>

	* win/tcl.m4:	    Add "-Wno-implicit-int" flag for gcc, as on UNIX
	* win/configure:    (regenerated)
	* generic/tclIO.c:  Eliminate an 'array index out of bounds' warning
			    on HP-UX.

2008-11-04  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclPort.h: Remove the ../win/ header dir as the build system
	already has it, and it confuses builds when used with private headers
	installed.

2008-11-01  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.h (TCLOO_VERSION): Bump version of TclOO.

2008-10-31  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOBasic.c (TclOONRUpcatch): Reworked the code that does
	* generic/tclOO.c (InitFoundation):	 class constructor handling so
	that it is more robust and runs the constructor call in the context of
	the caller of the class's constructor method. Needed because the
	previously used code did not work at all after applying the fix below;
	no Tcl existing command could reliably do what was needed any more.

	* generic/tclOODefineCmds.c (GetClassInOuterContext): Rework and
	factor out the code to resolve class names in definitions so that
	classes are resolved from the perspective of the caller of the
	[oo::define] command, rather than from the oo::define namespace! This
	makes much code simpler by reducing how often fully-qualified names
	are required (previously always in practice, so no back-compat issues
	exist). [Bug 2200824]

2008-10-28  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclCompile.h: CONSTify TclDTraceInfo
	* generic/tclBasic.c:
	* generic/tclProc.c:
	* generic/tclEnv.c:	Eliminate some -Wwrite-strings warnings
	* generic/tclLink.c:

2008-10-27  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclEncoding.c:	Use "iso8859-1" and not "identity" as
	the default and original [encoding system] value. Since "iso8859-1" is
	built in to the C source code for Tcl now, there's no availability
	issue, and it has the good feature of "identity" that we must have
	("bytes in" == "bytes out") without the bad feature of "identity"
	("broken as designed") that makes us want to abandon it. [RFE 2008609]
	*** POTENTIAL INCOMPATIBILITY for older releases of Tclkit and any
	other code expecting a particular value for Tcl's default system
	encoding ***

2008-10-24  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* library/http/http.tcl: Fixed a failure to read SHOUTcast streams
	with the new 2.7 package. Introduced a new intial state as the first
	response may not be HTTP*.

2008-10-23  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCmdAH.c (ForNextCallback): handle TCL_CONTINUE in the for
	body. [Bug 2186888]

2008-10-22  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tcl.h:	      CONST -> const and white-spacing
	* generic/tclCompile.h:
	* generic/tclEncoding.c:
	* generic/tclStubInit.c:
	* generic/tclStubLib.c:
	* generic/tcl.decls
	* generic/tclInt.decls
	* generic/tclTomMath.decls
	* generic/tclDecls.h:	      (regenerated)
	* generic/tclIntDecls.h:      (regenerated)
	* generic/tclIntPlatDecls.h:  (regenerated)
	* generic/tclOODecls.h:	      (regenerated)
	* generic/tclOOIntDecls.h:    (regenerated)
	* generic/tclPlatDecls.h:     (regenerated)
	* generic/tclTomMathDecls.h:  (regenerated)
	* generic/tclIntDecls.h:      (regenerated)
	* tools/genStubs.tcl:	      CONST -> const and white-spacing

2008-10-19  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclProc.c:	Reset -level and -code values to defaults
	after they are used. [Bug 2152286]

2008-10-19  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclBasic.c (TclInfoCoroutineCmd): Added code to make this
	check for being invoked in a syntactically correct way.

	* doc/info.n: Added documentation of [info coroutine].

	* doc/prefix.n: Improved the documentation by fixing formatting,
	adding good-practice recommendations and cross-references, etc.

2008-10-17  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclOO.decls:		CONST -> const.
	* generic/tclOODecls.h:		(regenerated)
	* generic/tclOOIntDecls.h:	(regenerated)

2008-10-17  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIORTrans.c (DeleteReflectedTransformMap): Removed debug
	output in C++ comment.

2008-10-17  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompile.h:	Declare the internal tclInstructionTable to
	* generic/tclExecute.c:	simply be "const", not CONST86.

	* generic/tclCmdAH.c:	whitespace.
	* generic/tclCmdIL.c:	Uninitialized variable warning.
	* generic/tclTest.c:	const correctness warning.

2008-10-17  Donal K. Fellows  <dkf@users.sf.net>

	* doc/*: Many very small formatting fixes.
	* doc/{glob,http,if}.n: More substantial reformatting for clarity.
	* doc/split.n: Remove mention of defunct c.l.t.announce

2008-10-16  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/regc_locale.c: Add "const" to many internal const tables.
	* generic/tclClock.c:	 No functional or API change.
	* generic/tclCmdIL.c
	* generic/tclConfig.c
	* generic/tclDate.c
	* generic/tclEncoding.c
	* generic/tclEvent.c
	* generic/tclExecute.c
	* generic/tclFileName.c
	* generic/tclGetDate.y
	* generic/tclInterp.c
	* generic/tclIO.c
	* generic/tclIOCmd.c
	* generic/tclIORChan.c
	* generic/tclIORTrans.c
	* generic/tclLoad.c
	* generic/tclObj.c
	* generic/tclOOBasic.c
	* generic/tclOOCall.c
	* generic/tclOOInfo.c
	* generic/tclPathObj.c
	* generic/tclPkg.c
	* generic/tclResult.c
	* generic/tclStringObj.c
	* generic/tclTest.c
	* generic/tclTestObj.c
	* generic/tclThreadTest.c
	* generic/tclTimer.c
	* generic/tclTrace.c
	* macosx/tclMacOSXFCmd.c
	* win/cat.c
	* win/tclWinInit.c
	* win/tclWinTest.c

2008-10-16  Don Porter  <dgp@users.sourceforge.net>

	* library/init.tcl:	Revised [unknown] so that it carefully
	preserves the state of the ::errorInfo and ::errorCode variables at
	the start of auto-loading and restores that state before the
	autoloaded command is evaluated. [Bug 2140628]

2008-10-15  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.h:	Add "const" to many internal const tables, so
	* generic/tclBinary.c:	those will be put by the C-compiler in the
	* generic/tclCompile.c:	TEXT segment in stead of the DATA segment.
	* generic/tclDictObj.c: This makes those tables sharable in shared
	* generic/tclHash.c:	libraries.
	* generic/tclListObj.c:
	* generic/tclNamesp.c:
	* generic/tclObj.c:
	* generic/tclProc.c:
	* generic/tclRegexp.c:
	* generic/tclStringObj.c:
	* generic/tclUtil.c:
	* generic/tclVar.c:

2008-10-14  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclCmdAH.c:	Fix minor compiler warnings when compiling
	* generic/tclCmdMZ.c:	with -Wwrite-strings.
	* generic/tclIndexObj.c:
	* generic/tclProc.c:
	* generic/tclStubLib.c:
	* generic/tclUtil.c:
	* win/tclWinChan.c:
	* win/tclWinDde.c:
	* win/tclWinInit.c:
	* win/tclWinReg.c:
	* win/tclWinSerial.c:

2008-10-14  Donal K. Fellows  <dkf@users.sf.net>

	* doc/binary.n: Formatting fix.

2008-10-14  Don Porter  <dgp@users.sourceforge.net>

	* README:		Bump version number to 8.6a4
	* generic/tcl.h:
	* library/init.tcl:
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/configure.in:

	* unix/configure:	autoconf-2.59
	* win/configure:

	* generic/tclExecute.c:	Fix compile warnings when --enable-symbols=all

	* generic/tclCmdIL.c:	Fix write to unallocated memory whenever
	[lrepeat] returns an empty list.

2008-10-14  Donal K. Fellows  <dkf@users.sf.net>

	* doc/chan.n, doc/fconfigure.n: Added even more emphatic text to
	direct people to the correct manual pages for specific channel types,
	suitable for the hard-of-reading. Following discussion on tcl-core.

2008-10-13  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* win/tclWinThrd.c (TclpThreadCreate): We need to initialize the
	thread id variable to 0 as on 64 bit windows this is a pointer sized
	field while windows only fills it with a 32 bit value. The result is
	an inability to join the threads as the ids cannot be matched.

	* generic/tclTest.c (TestNRELevels): Set array to the right size.

2008-10-13  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOInfo.c (InfoClassDestrCmd): Handle error case.

	* generic/tclOOInt.h: Added macro magic to make things work with
	Objective C. [Bug 2163447]

2008-10-12  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompile.c: Fix bug in srcDelta encoding within ByteCodes.
	The bug can only be triggered under conditions that cannot happen in
	Tcl, but were met during development of L. Thanks go to Robert Netzer
	for diagnosis and fix.

2008-10-10  Don Porter  <dgp@users.sourceforge.net>

	*** 8.6a3 TAGGED FOR RELEASE ***

	* changes:	Updates for 8.6a3 release.

2008-10-10  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOODefineCmds.c (TclOODefineUnexportObjCmd)
	(TclOODefineExportObjCmd): Corrected export/unexport record synthesis.
	[Bug 2155658]

2008-10-08  Jan Nijtmans  <nijtmans@users.sf.net>

	* unix/tclUnixChan.c:	Fix minor compiler warning.
	* unix/tcl.m4:		Fix for [Bug 2073255]
	* unix/configure:	Regenerated

2008-10-08  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic (TclInfoCoroutineCmd):
	* tests/unsupported.test: Arrange for [info coroutine] to return {}
	when a coroutine is running but the resume command has been deleted.
	[Bug 2153080]

2008-10-08  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclTrace.c:	Corrected handling of errors returned by
	variable traces so that the errorInfo value contains the original
	error message. [Bug 2151707]

	* generic/tclVar.c:	Revised implementation of TclObjVarErrMsg so
	that error message construction does not disturb an existing
	iPtr->errorInfo that may be in progress.

2008-10-07  Donal K. Fellows  <dkf@users.sf.net>

	* doc/binary.n: Added better documentation of the [binary encode] and
	[binary decode] subcommands.

2008-10-07  Miguel Sofer  <msofer@users.sf.net>

	TIP #327,#328 IMPLEMENTATIONS

	* generic/tclBasic.c:	   Move [tailcall], [coroutine] and
	* generic/tclCmdIL.c:	   [yield] out of ::tcl::unsupported
	* tclInt.h:
	* tests/info.test:	   and into global scope: TIPs #327
	* tests/unsupported.test:  and #328

2008-10-07  Donal K. Fellows  <dkf@users.sf.net>

	* doc/chan.n, doc/transchan.n: Documented the channel transformation
	API of TIP #230.

2008-10-06  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* tests/winFCmd.test: Fixed some erroneous tests on Vista+.
	* generic/tclFCmd.c: Fix constness for msvc of last commit

2008-10-06  Joe Mistachkin  <joe@mistachkin.com>

	* tools/man2tcl.c: Added missing line from patch by Harald Oehlmann.
	[Bug 1934200]

2008-10-05  Jan Nijtmans  <nijtmans@users.sf.net>

	* doc/FileSystem.3:	CONSTified Tcl_FSFileAttrStringsProc
	* generic/tclFCmd.c:	and tclpFileAttrStrings. This allows
	* generic/tclIOUtil.c:	FileSystems to report their attributes
	* generic/tclTest.c:	as const strings, without worrying that
	* unix/tclUnixFCmd.c:	Tcl modifies them (which Tcl should not
	* win/tclWinFCmd.c:	do anyway, but the API didn't indicate that)
	* generic/tcl.decls
	* generic/tclDecls.h:	regenerated
	* generic/tcl.h:	Make sure that if CONST84 is defined as empty,
				CONST86 should be defined as empty as well
				(unless overridden). This change complies with
				TIP #27
	*** POTENTIAL INCOMPATIBILITY ***

2008-10-05  Kevin B, Kenny  <kennykb@acm.org>

	* libtommath/bn_mp_sqrt.c (bn_mp_sqrt): Handle the case where a
	* tests/expr.test (expr-47.13):		number's square root is
	between n<<DIGIT_BIT and n<<DIGIT_BIT+1. [Bug 2143288]
	Thanks to Malcolm Boffey (malcolm.boffey@virgin.net) for the patch.

	TIP #331 IMPLEMENTATION

	* doc/lset.n:
	* generic/tclListObj.c (TclLsetFlat):
	* tests/lset.test: Modified the [lset] command so that it allows for
	an index of 'end+1', which has the effect of appending an element to
	the list.

2008-10-05  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclInt.decls:	 CONSTified the AuxDataType argument
	* generic/tclCompCmds.c: of TclCreateAuxData and
	* generic/tclCompile.c:	 TclRegisterAuxDataType and the return
	* generic/tclCompile.h:	 values of TclGetAuxDataType and
	* generic/tclExecute.c:	 TclGetInstructionTable
	* generic/tclIntDecls.h:		regenerated
	This change complies with TIP #27 (even though it only involves
	internal function, so this is not even necessary).

2008-10-05  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclIndexObj.c (TclInitPrefixCmd): Make the [tcl::prefix]
	into an exported command. [Bug 2144595]

2008-10-04  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdIL.c (InfoFrameCmd):	Improved hygiene of result
	* generic/tclRegexp.c (TclRegAbout):	handling.

2008-10-04  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/tclLoad.c: Make sure that any library which doesn't have an
	unloadproc is only really unloaded when no library code is executed
	yet. [Bug 2059262]

2008-10-04  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOInfo.c (GetClassFromObj): Factor out the code to parse
	a Tcl_Obj and get a class. Also make result handling hygienic.
	* generic/tclOOBasic.c (TclOOSelfObjCmd): Better hygiene of results,
	and stop allocating quite so much memory by sharing special "method"
	names.

2008-10-04  Jan Nijtmans  <nijtmans@users.sf.net>

	* doc/ChnlStack.3:	CONSTified the typePtr argument
	* doc/CrtChannel.3:	of Tcl_CreateChannel and Tcl_StackChannel
	* generic/tcl.decls:	and the return value of Tcl_GetChannelType
	* generic/tcl.h
	* generic/tclIO.h
	* generic/tclIO.c
	* generic/tclDecls.h:	regenerated
	This change complies with TIP #27.

	* doc/Hash.3:		CONSTified the typePtr argument
	* generic/tcl.decls:	of Tcl_InitCustomHashTable.
	* generic/tcl.h
	* generic/tclHash.c
	* generic/tclDecls.h:	regenerated
	This change complies with TIP #27.

	* doc/RegConfig.3:	CONSTified the configuration argument
	* generic/tcl.decls:	of Tcl_RegisterConfig.
	* generic/tcl.h
	* generic/tclConfig.c
	* generic/tclPkgConfig.c
	* generic/tclDecls.h:	regenerated
	This change complies with TIP #27.

	* doc/GetIndex.3:	CONSTified the tablePtr argument
	* generic/tcl.decls:	of Tcl_GetIndexFromObj.
	* generic/tclIndexObj.c
	* generic/tclDecls.h:	regenerated
	This change complies with TIP #27.

2008-10-03  Miguel Sofer  <msofer@users.sf.net>

	* tests/stack.test:
	* unix/tclUnixTest.c: Removed test command teststacklimit and the
	corresponding constraint: it is not needed with NRE

2008-10-03  Donal K. Fellows  <dkf@users.sf.net>

	TIP #195 IMPLEMENTATION

	* generic/tclIndexObj.c (TclGetIndexFromObjList, PrefixMatchObjCmd)
	* doc/prefix.n, tests/string.test: Added [tcl::prefix] command for
	working with prefixes of strings at the Tcl level. [Patch 1040206]

	TIP #265 IMPLEMENTATION

	* generic/tclIndexObj.c (Tcl_ParseArgsObjv, PrintUsage):
	* generic/tcl.h (Tcl_ArgvInfo):	Added function for simple parsing of
	* doc/ParseArgs.3 (new file):	optional arguments to commands. Still
	needs tests and the like. [FRQ 1446696] Note that some of the type
	signatures are changed a bit from the proposed implementation so that
	they better reflect codified good practice for argument order.

2008-10-02  Andreas Kupries  <andreask@activestate.com>

	* tests/info.test (info-23.3): Updated output of the test to handle
	the NRE-enabled eval and the proper propagation of location
	information through it. [Bug 2017632]

	* doc/info.n: Rephrased the documentation of 'info frame' for positive
	numbers as level argument. [Bug 2134049]

	* tests/info.test (info-22.8): Made pattern for file containing
	tcltest less specific to accept both .tcl and .tm variants of the file
	during matching. [Bug 2129828]

2008-10-02  Don Porter  <dgp@users.sourceforge.net>

	TIP #330 IMPLEMENTATION

	* generic/tcl.h:	Remove the "result" and "freeProc" fields
	* generic/tclBasic.c:	from the default public declaration of the
	* generic/tclResult.c:	Tcl_Interp struct. Code should no longer
	* generic/tclStubLib.c:	be accessing these fields. Access can be
	* generic/tclTest.c:	restored by defining USE_INTERP_RESULT, but
	* generic/tclUtil.c:	that should only be a temporary migration aid.
	*** POTENTIAL INCOMPATIBILITY ***

2008-10-02  Joe Mistachkin  <joe@mistachkin.com>

	* doc/info.n: Fix unmatched font change.
	* doc/tclvars.n: Fix unmatched font change.
	* doc/variable.n: Fix unmatched font change.
	* tools/man2help2.tcl: Integrated patch from Harald Oehlmann.
	[Bug 1934272]
	* tools/man2tcl.c: Increase MAX_LINE_SIZE to fix "Too long line" error.
	* win/buildall.vc.bat: Prefer the HtmlHelp target over the WinHelp
	target. [Bug 2072891]
	* win/makefile.vc: Fix the HtmlHelp and WinHelp targets to not be
	mutually exclusive.

2008-09-29  Don Porter  <dgp@users.sourceforge.net>

	TIP #323 IMPLEMENTATION (partial)

	* doc/glob.n:		Revise [glob] to accept zero patterns.
	* generic/tclFileName.c:
	* tests fileName.test:

	* doc/linsert.n:	Revise [linsert] to accept zero elements.
	* generic/tclCmdIL.c:
	* tests/linsert.test:

2008-09-29  Donal K. Fellows  <dkf@users.sf.net>

	TIP #326 IMPLEMENTATION

	* generic/tclCmdIL.c (Tcl_LsortObjCmd): Added -stride option to carry
	* doc/lsort.n, tests/cmdIL.test:	out sorting of lists where the
	elements are grouped. Adapted from [Patch 2082681]

	TIP #313 IMPLEMENTATION

	* generic/tclCmdIL.c (Tcl_LsearchObjCmd): Added -bisect option to
	* doc/lsearch.n, tests/lsearch.test:	  allow the finding of the
	place to insert an element in a sorted list when that element is
	not already there. [Patch 1894241]

	TIP #318 IMPLEMENTATION

	* generic/tclCmdMZ.c (StringTrimCmd,StringTrimLCmd,StringTrimRCmd):
	Update the default set of trimmed characters to include some from the
	larger UNICODE space. Factor out the default trim set into a macro so
	that it is easier to keep them in synch.

2008-09-28  Donal K. Fellows  <dkf@users.sf.net>

	TIP #314 IMPLEMENTATION

	* generic/tclCompCmds.c (TclCompileEnsemble)
	* generic/tclNamesp.c (NamespaceEnsembleCmd)
	(Tcl_SetEnsembleParameterList, Tcl_GetEnsembleParameterList)
	(NsEnsembleImplementationCmdNR):
	* generic/tcl.decls, doc/Ensemble.3, doc/namespace.n
	* tests/namespace.test: Allow the handling of a (fixed) number of
	formal parameters between an ensemble's command and subcommand at
	invokation time. [Patch 1901783]

2008-09-28  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:	   Fix the numLevels computations on
	* generic/tclInt.h:	   coroutine yield/resume
	* tests/unsupported.test:

2008-09-27  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclFileName.c (Tcl_GetBlock*FromStat): Made this work
	acceptably when working with OSes that don't support reporting the
	block size from the stat() call. [Bug 2130726]

	* generic/tclCmdIL.c (Tcl_LrepeatObjCmd): Improve the handling of the
	case where the combination of number of elements and repeat count
	causes the resulting list to be too large. [Bug 2130992]

2008-09-26  Don Porter  <dgp@users.sourceforge.net>

	TIP #323 IMPLEMENTATION (partial)

	* doc/lrepeat.n:	Revise [lrepeat] to accept both zero
	* generic/tclCmdIL.c:	repetitions and zero elements to be repeated.
	* tests/lrepeat.test:

	* doc/object.n:		Revise standard oo method [my variable] to
	* generic/tclOOBasic.c:	accept zero variable names.
	* tests/oo.test:

	* doc/tm.n:		Revise [tcl::tm::path add] and
	* library/tm.tcl:	[tcl::tm::path remove] to accept zero paths.
	* tests/tm.test:

	* doc/namespace.n:	Revise [namespace upvar] to accept zero
	* generic/tclNamesp.c:	variable names.
	* tests/upvar.test:

	* doc/lassign.n:	Revise [lassign] to accept zero variable names.
	* generic/tclCmdIL.c:
	* tests/cmdIL.test:

2008-09-26  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.h (TCLOO_VERSION): Bump the version.

2008-09-25  Don Porter  <dgp@users.sourceforge.net>

	TIP #323 IMPLEMENTATION (partial)

	* doc/global.n:		Revise [global] to accept zero variable names.
	* doc/variable.n:	Revise [variable] likewise.
	* generic/tclVar.c:
	* tests/proc-old.test:
	* tests/var.test:

	* doc/global.n: Correct false claim about [info locals].

2008-09-25  Donal K. Fellows  <dkf@users.sf.net>

	TIP #315 IMPLEMENTATION

	* tests/platform.test:	Update tests to expect revised results
	* tests/safe.test:	corresponding to the TIP 315 change.

	* unix/tclUnixInit.c, win/tclWinInit.c (TclpSetVariables):
	* doc/tclvars.n (tcl_platform): Define what character is used for
	separating PATH-like lists. Forms part of the tcl_platform array.

	* generic/tclOOCall.c (InitCallChain, IsStillValid):
	* tests/oo.test (oo-25.2): Revise call chain cache management so that
	it takes into account class-wide caching correctly. [Bug 2120903]

2008-09-24  Don Porter  <dgp@users.sourceforge.net>

	TIP #323 IMPLEMENTATION (partial)

	* doc/file.n:		Revise [file delete] and [file mkdir] to
	* generic/tclCmdAH.c:	accept zero "pathname" arguments (the
	* generic/tclFCmd.c:	no-op case).
	* tests/cmdAH.test:
	* tests/fCmd.test:

2008-09-24  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOMethod.c (DBPRINT): Remove obsolete debugging macro.
	[Bug 2124814]

	TIP #316 IMPLEMENTATION

	* generic/tcl.decls, generic/tclFileName.c (Tcl_GetSizeFromStat, etc):
	* doc/FileSystem.3: Added reader functions for Tcl_StatBuf.

2008-09-23  Donal K. Fellows  <dkf@users.sf.net>

	* doc/Method.3: Corrected documentation. [Patch 2082450]

	* doc/lreverse.n, mathop.n, regexp.n, regsub.n: Make sure that the
	initial line of the manpage includes nothing that chokes old versions
	of man. [Bug 2118123]

2008-09-22  Donal K. Fellows  <dkf@users.sf.net>

	TIP #320 IMPLEMENTATION

	* generic/tclOODefineCmds.c (TclOODefineVariablesObjCmd):
	* generic/tclOOInfo.c (InfoObjectVariablesCmd, InfoClassVariablesCmd):
	* generic/tclOOMethod.c (TclOOSetupVariableResolver, etc):
	* doc/define.n, doc/ooInfo.n, benchmarks/cps.tcl:
	* tests/oo.test (oo-26.*): Allow the declaration of the common
	variables used in methods of a class or object. These are then mapped
	in using a variable resolver. This makes many class declarations much
	simpler overall, encourages good usage of variable names, and also
	boosts speed a bit.

	* generic/tclOOMethod.c (TclOOGetMethodBody): Factor out the code to
	get the body of a procedure-like method. Reduces the amount of "poking
	inside the abstraction" that is done by the introspection code.

2008-09-22  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* doc/chan.n: Clean up paragraph order.

2008-09-18  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c (NEXT_INST_F):
	* generic/tclInt.h (TCL_CT_ASSERT): New compile-time assertions,
	adapted from www.pixelbeat.org/programming/gcc/static_assert.html

2008-09-17  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInt.h: Correct the TclGetLongFromObj, TclGetIntFromObj,
	and TclGetIntForIndexM macros so that they retrieve the longValue
	field from the internalRep instead of casting the otherValuePtr field
	to type long.

2008-09-17  Miguel Sofer  <msofer@users.sf.net>

	* library/init.tcl: Export min and max commands from the mathfunc
	namespace. [Bug 2116053]

2008-09-16  Joe Mistachkin  <joe@mistachkin.com>

	* generic/tclParse.c: Move TclResetCancellation to be called on
	returning to level 0, as opposed to it being called on starting a
	substitution at level 0.

2008-09-16  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c: Move TclResetCancellation to be called on
	returning to level 0, as opposed to it being called on starting a
	command at level 0. Add a call on returning via Tcl_EvalObjEx to fix
	[Bug 2114165].

2008-09-10  Donal K. Fellows  <dkf@users.sf.net>

	* doc/binary.n: Added partial documentation of [binary encode] and
	[binary decode].

	* tests/binary.test,cmdAH.test,cmdIL.test,cmdMZ.test,fileSystem.test:
	More use of tcltest2 to simplify the tests as exposed to people.
	* tests/compile.test (compile-18.*): Added *some* tests of the
	disassmbler, though not of its output format.

2008-09-10  Miguel Sofer  <msofer@users.sf.net>

	* tests/nre.test: Add missing constraints; enable test of foreach
	recursion.

	* generic/tclBasic.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c (INST_EVAL_STK): Wrong numLevels when evaling a
	canonical list. [Bug 2102930]

2008-09-10  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclListObj.c (Tcl_ListObjGetElements): Make this list->dict
	transformation - encountered when using [foreach] with dicts - not as
	expensive as it was before. Spotted by Kieran Elby and reported on
	tcl-core.

2008-09-08  Donal K. Fellows  <dkf@users.sf.net>

	* tests/append.test, appendComp.test, cmdAH.test: Use the powers of
	tcltest2 to make these files simpler.

2008-09-07  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompile.c (TclCompileTokens):
	* generic/tclExecute.c (CompileExprObj): Fix a perf bug (found by Alex
	Ferrieux) where some variables in the LVT where not being accessed by
	index. Fix missing localCache management in compiled expressions found
	while analyzing the bug.

2008-09-07  Miguel Sofer  <msofer@users.sf.net>

	* doc/namespace.n: Fix [Bug 2098441]

2008-09-04  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclTrace.test (TraceVarProc):
	* generic/unsupported.test: Insure that unset traces are run even when
	the coroutine is unwinding. [Bug 2093947]

	* generic/tclExecute.c (CACHE_STACK_INFO):
	* tests/unsupported.test: Restore execEnv's bottomPtr. [Bug 2093188]

2008-09-02  Don Porter  <dgp@users.sourceforge.net>

	* generic/tcl.h:	Stripped "callers" of the _ANSI_ARGS_ macro
	* compat/dirent2.h:	to support a TCL_NO_DEPRECATED build.
	* compat/dlfcn.h:
	* unix/tclUnixPort.h:

	* generic/tcl.h:	Removed the conditional #define of
	_ANSI_ARGS_ that would support pre-prototype C compilers. Since
	_ANSI_ARGS_ is no longer used in tclDecls.h, it's clear no one
	compiling against Tcl 8.5 headers is making use of a -DNO_PROTOTYPES
	configuration.

2008-09-02  Donal K. Fellows  <dkf@users.sf.net>

	* tests/socket.test: Rewrote so as to use tcltest2 better.

2008-09-01  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCmdAH.c:	   NRE-enabling [eval]; eval scripts are now
	* generic/tclOOBasic.c:	   bytecompiled. Adapted recursion limit tests
	* tests/interp.test:	   that were relying on eval not being
	* tests/nre.test:	   compiled. Part of the [Bug 2017632] project.
	* tests/unsupported.test:

2008-09-01  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOMethod.c (InvokeProcedureMethod):
	* generic/tclOO.c (ObjectRenamedTrace): Arrange for only methods that
	involve callbacks into the Tcl interpreter to be skipped when the
	interpreter is being torn down. Allows the semantics of destructors in
	a dying interpreter to be more useful when they're implemented in C.

2008-08-29  Donal K. Fellows  <dkf@users.sf.net>

	* unix/Makefile.in: Ensure that all TclOO headers get installed.
	* win/Makefile.in:  [Bug 2082299]
	* win/makefile.bc:
	* win/makefile.vc:

2008-08-28  Don Porter  <dgp@users.sourceforge.net>

	* README:		Bump version number to 8.6a3
	* generic/tcl.h:
	* library/init.tcl:
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/configure.in:

	* unix/configure:	autoconf-2.59
	* win/configure:

2008-08-27  Donal K. Fellows  <dkf@users.sf.net>

	* doc/tclvars.n, doc/library.n: Ensured that these two manual pages
	properly cross-reference each other. Issue reported on Tcler's Chat.

2008-08-26  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c (InfoCoroutine):
	* tests/unsupported.test: New command that returns the FQN of the
	currently executing coroutine. Lives as infoCoroutine under
	unsupported, but is designed to become a subcommand of [info]

2008-08-23  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c (NRInterpCoroutine): Store the caller's eePtr,
	stop assuming the coroutine is invoked from the same execEnv where it
	was created.

2008-08-24  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCmdAH.c (TclNRForeachCmd): Converted the [foreach]
	command to have an NRE-aware non-compiled implementation. Part of the
	[Bug 2017632] project. Also restructured the code so as to manage its
	temporary memory more efficiently.

2008-08-23  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:	  Removed unused var; fixed function pointer
	* generic/tclOOInt.h:	  declarations (why did gcc start complaining
	* generic/tclOOMethod.c:  all of a sudden?)
	* generic/tclProc.c:

2008-08-23  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclInt.h (EnsembleImplMap): Added extra field to make it
	* generic/tclNamesp.c (TclMakeEnsemble): easier to build non-recursive
	ensembles in the core.

	* generic/tclDictObj.c (DictForNRCmd): Converted the [dict for]
	command to have an NRE-aware non-compiled implementation. Part of the
	[Bug 2017632] project.

2008-08-22  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:
	* generic/tclExecute.c: Set special errocodes: COROUTINE_BUSY,
	COROUTINE_CANT_YIELD, COROUTINE_ILLEGAL_YIELD.

2008-08-22  Don Porter  <dgp@users.sourceforge.net>

	*** 8.6a2 TAGGED FOR RELEASE ***

	* changes:	Updates for 8.6a2 release.

	* generic/tcl.h:	Drop use of USE_COMPAT85_CONST. That added
	indirection without value. Use -DCONST86="" to engage source compat
	support for code written for 8.5 headers.

	* generic/tclUtil.c (TclReToGlob):	Added missing set of the
	*exactPtr value to really fix [Bug 2065115]. Also avoid possible
	DString overflow.
	* tests/regexpComp.test:	Correct duplicate test names.

2008-08-21  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:	  Previous fix, now done right.
	* generic/tclCmdIL.c:
	* generic/tclInt.h:
	* tests/unsupported.test:

2008-08-21  Jeff Hobbs  <jeffh@ActiveState.com>

	* tests/regexp.test, tests/regexpComp.test: Correct re2glob ***=
	* generic/tclUtil.c (TclReToGlob):	    translation from exact
	to anywhere-in-string match. [Bug 2065115]

2008-08-21  Don Porter  <dgp@users.sourceforge.net>

	* generic/tcl.h:	Reduced the use of CONST86 and eliminated
	* generic/tcl.decls:	the use of CONST86_RETURN to support source
	code compatibility with Tcl 8.5 on those public routines passing
	(Tcl_Filesystem *), (Tcl_Timer *), and (Tcl_Objtype *) values which
	have been const-ified. What remains is the minimum configurability
	needed to support code written for pre-8.6 headers via the new
	-DUSE_COMPAT85_CONST compiler directive.
	*** POTENTIAL INCOMPATIBILITY ***

	* generic/tclDecls.h:	make genstubs

2008-08-21  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:	Fix the cmdFrame level count in
	* generic/tclCmdIL.c:	coroutines. Fix small bug on coroutine
	* generic/tclInt.h:	rewind.

2008-08-21  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclProc.c (Tcl_DisassembleObjCmd): Added ability to
	disassemble TclOO methods. The code to do this is very ugly.

2008-08-21  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* generic/tclOOMethod.c: Added casts to make MSVC happy
	* generic/tclBasic.c:

2008-08-20  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.c (AllocObject): Suppress compilation of commands in
	the namespace allocated for each object.
	* generic/tclOOMethod.c (PushMethodCallFrame): Restore some of the
	hackery that makes calling methods of classes fast. Fixes performance
	problem introduced by the fix of [Bug 2037727].

	* generic/tclCompile.c (TclCompileScript):    Allow the suppression of
	* generic/tclInt.h (NS_SUPPRESS_COMPILATION): compilation of commands
	* generic/tclNamesp.c (Tcl_CreateNamespace):  from a namespace or its
	children.

2008-08-20  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclTest.c (TestconcatobjCmd):	Fix use of internal-only
	TclInvalidateStringRep macro. [Bug 2057479]

2008-08-17  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:	   Implementation of [coroutine] and [yield]
	* generic/tclCmdAH.c:	   commands (in tcl::unsupported).
	* generic/tclCompile.h:
	* generic/tclExecute.c:
	* generic/tclInt.h:
	* tests/unsupported.test:

	* generic/tclTest.c (TestconcatobjCmd):
	* generic/tclUtil.c (Tcl_ConcatObj):
	* tests/util.test (util-4.7):
	Fix [Bug 1447328]; the original "fix" turned Tcl_ConcatObj() into a
	hairy monster. This was exposed by [Bug 2055782]. Additionally,
	Tcl_ConcatObj could corrupt its input under certain conditions!

	*** NASTY BUG FIXED ***

2008-08-16  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: Better cmdFrame management

2008-08-14  Don Porter  <dgp@users.sourceforge.net>

	* tests/fileName.test:	Revise new tests for portability to case
	insensitive filesystems.

2008-08-14  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclBasic.c (TclNREvalObjv, Tcl_NRCallObjProc):
	* generic/tclProc.c (TclNRInterpProcCore, InterpProcNR2):
	DTrace probes for NRE. [Bug 2017160]

	* generic/tclBasic.c (TclDTraceInfo):	Add two extra arguments to
	* generic/tclCompile.h:			DTrace 'info' probes for tclOO
	* generic/tclDTrace.d:			method & class/object info.

	* generic/tclCompile.h:	Add support for debug logging of DTrace
	* generic/tclBasic.c:	'proc', 'cmd' and 'inst' probes (does _not_
				require a platform with DTrace).

	* generic/tclCmdIL.c (TclInfoFrame):	Check fPtr->line before
						dereferencing as line info may
						not exists when TclInfoFrame()
						is called from a DTrace probe.

	* tests/fCmd.test (fCmd-6.23):	Made result matching robust when test
					workdir and /tmp are not on same FS.

	* unix/tclUnixThrd.c:		Remove unused TclpThreadGetStackSize()
	* generic/tclInt.h:		and related ifdefs and autoconf tests.
	* unix/tclUnixPort.h:		[Bug 2017264] (jenglish)
	* unix/tcl.m4:

	* unix/Makefile.in:		Ensure Makefile shell is /bin/bash for
	* unix/configure.in (SunOS):	DTrace-enabled build on Solaris.
					(followup to 2008-06-12) [Bug 2016584]

	* unix/tcl.m4 (SC_PATH_X):	Check for libX11.dylib in addition to
					libX11.so et al.

	* unix/configure:		autoconf-2.59
	* unix/tclConfig.h.in:		autoheader-2.59

2008-08-13  Miguel Sofer  <msofer@users.sf.net>

	* tests/nre.test: Added test for large {*}-expansion effects

2008-08-13  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclFileName.c:	Fix for errors handling -types {}
	* tests/fileName.test:		option to [glob]. [Bug 1750300]
	Thanks to Matthias Kraft and George Peter Staplin.

2008-08-12  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclOOInfo.c (InfoObjectDefnCmd, InfoObjectMixinsCmd):
	Fix # args displayed. [Bug 2048676]

2008-08-08  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclOOMethod.c (PushMethodCallFrame):	Added missing check
	for bytecode validity. [Bug 2037727]

	* generic/tclProc.c (TclProcCompileProc):	On recompile of a
	proc, clear away any entries on the CompiledLocal list from the
	previous compile. This will prevent compile of temporary variables in
	the proc body from growing the localCache arbitrarily large.

	* README:		Bump version number to 8.6a2
	* generic/tcl.h:
	* library/init.tcl:
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/configure.in:

	* unix/configure:	autoconf-2.59
	* win/configure:

	* changes:	Updates for 8.6a2 release.

2008-08-11  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* library/http/http.tcl: Remove 8.5 requirement.
	* library/http/pkgIndex.tcl:
	* unix/Makefile.in:
	* win/Makefile.in:
	* win/makefile.vc:

2008-08-11  Andreas Kupries  <andreask@activestate.com>

	* library/tm.tcl: Added a 'package provide' command to the generated
	ifneeded scripts of Tcl Modules, for early detection of conflicts
	between the version specified through the file name and a 'provide'
	command in the module implementation, if any. Note that this change
	also now allows Tcl Modules to not provide a 'provide' command at all,
	and declaring their version only through their filename.

	* generic/tclProc.c (Tcl_ProcObjCmd): Fixed memory leak triggered by
	* tests/proc.test: procbody::test::proc. See [Bug 2043636]. Added a
	test case demonstrating the leak before the fix. Fixed a few spelling
	errors in test descriptions as well.

2008-08-11  Don Porter  <dgp@users.sourceforge.net>

	* library/http/http.tcl:	Bump http version to 2.7.1 to account
	* library/http/pkgIndex.tcl:	for [Bug 2046486] bug fix. This
	* unix/Makefile.in:		release of http now requires a
	* win/Makefile.in:		dependency on Tcl 8.5 to be able to
	* win/makefile.bc:		use the unsigned formats in the
	* win/makefile.vc:		[binary scan] command.

2008-08-11  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* library/http/http.tcl: CRC field from zlib data should be treated as
	unsigned for 64bit support. [Bug 2046846]

2008-08-10  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclProc.c: Completely removed ProcCompileProc, which was a
	fix for [Bug 1482718]. This is not needed at least since varReform,
	where the local variable data at runtime is read from the CallFrame
	and/or the LocalCache.

2008-08-09  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:	Slight cleanup
	* generic/tclCompile.h:
	* generic/tclExecute.c:

2008-08-09  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclExecute.c:	Fix warnings.

	* generic/tclOOMethod.c (PushMethodCallFrame):	Fix uninitialized efi
							name field.

	* tests/lrange.test (lrange-1.17):	Add test cleanup; whitespace.

2008-08-08  Don Porter  <dgp@users.sourceforge.net>

	* changes:	Updates for 8.6a2 release.

2008-08-08  Kevin Kenny  <kennykb@acm.org>

	* library/tzdata/CET:
	* library/tzdata/MET:
	* library/tzdata/Africa/Casablanca:
	* library/tzdata/America/Eirunepe:
	* library/tzdata/America/Rio_Branco:
	* library/tzdata/America/Santarem:
	* library/tzdata/America/Argentina/San_Luis:
	* library/tzdata/Asia/Karachi:
	* library/tzdata/Europe/Belgrade:
	* library/tzdata/Europe/Berlin:
	* library/tzdata/Europe/Budapest:
	* library/tzdata/Europe/Sofia:
	* library/tzdata/Indian/Mauritius:  Olson's tzdata2008e.

2008-08-07  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:	Fix tailcalls falling out of tebc into
	* generic/tclExecute.c: Tcl_EvalEx. [Bug 2017946]
	* generic/tclInt.h:

2008-08-06  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclOO.c:	Revised TclOO's check for an interp being
	deleted during handling of object command deletion. The old code was
	relying on documented features of command delete traces that do not in
	fact work. [Bug 2039178]

	* tests/oo.test (oo-26.*):	Added tests that demonstrate failure
	of TclOO to check for various kinds of invalid bytecode during method
	dispatch. [Bug 2037727]

2008-08-06  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclVar.c (TclLookupSimpleVar): Fix bug that the core could
	not trigger before TclOO: the number of locals was being read from the
	Proc, which can under some circumstance be out of sync with the
	localCache's. Found by dgp while investigating [Bug 2037727].

	* library/init.tcl (::unknown): Removed the [namespace inscope]
	hack that was maintained for Itcl

	*** POTENTIAL INCOMPATIBILITY *** for Itcl
	Itcl users will need a new release with Itcl's [Patch 2040295], or
	else load the tiny script in that patch by themselves (rewrite
	::unknown). Note that it is a script-only patch.

2008-08-05  Joe English  <jenglish@users.sourceforge.net>

	* unix/tclUnixChan.c: Streamline async connect logic [Patch 1994512]

2008-08-05  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: Fix for [Bug 2038069] by dgp.
	* tests/execute.test:

2008-08-04  Miguel Sofer  <msofer@users.sf.net>

	* tests/nre.test: Added tests for [if], [while] and [for]. A test
	for [foreach] has been added and marked as knownbug, awaiting for it
	to be NR-enabled.

	* generic/tclBasic.c:	   Made atProcExit commands run
	* generic/tclCompile.h:	   unconditionally, streamlined
	* generic/tclExecute.c:	   atProcExit/tailcall processing in TEBC.
	* generic/tclProc.c:
	* tests/unsupported.test:

2008-08-04  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclExecute.c: Stopped faulty double-logging of errors to
	* tests/execute.test:	stack trace when a compile epoch bump triggers
	fallback to direct evaluation of commands in a compiled script.
	[Bug 2037338]

2008-08-03  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:	   New unsupported command atProcExit that
	* generic/tclCompile.h:	   shares the implementation with tailcall.
	* generic/tclExecute.c:	   Fixed a segfault in tailcalls. Tests added.
	* generic/tclInt.h:
	* generic/tclInterp.c:
	* generic/tclNamesp.c:
	* tests/unsupported.test:

2008-08-02  Miguel Sofer  <msofer@users.sf.net>

	* tests/NRE.test (removed):	Migrated tests to standard locations,
	* tests/nre.test (new):		separating core functionality from the
	* tests/unsupported.test (new):	experimental commands.

2008-08-01  Jeff Hobbs  <jeffh@ActiveState.com>

	* doc/Exit.3:			Do not call Tcl_Finalize implicitly
	* generic/tclEvent.c:		on DLL_PROCESS_DETACH as it may lead
	* win/tclWin32Dll.c (DllMain):	to issues and the user should be
	explicitly calling Tcl_Finalize before unloading regardless. Clarify
	the docs to note the explicit need in embedded use.

2008-08-01  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Revised timing of the CmdFrame stack
	* tests/info.test:	management in TclEvalEx so that the CmdFrame
	will still be on the stack at the time Tcl_LogCommandInfo is called to
	append another level of -errorinfo information. Sets the stage to add
	file and line data to the stack trace. Added test to check that [info
	frame] functioning remains unchanged by the revision.

2008-07-31  Miguel Sofer  <msofer@users.sf.net>

	* tests/NRE.test:  Replaced all deep-recursing tests by shallower
	tests that actually measure the C-stack depth. This makes them
	bearable again (even under memdebug) and avoid crashing on failure.

	* generic/tclBasic.c:	NR-enabling [catch], [if] and [for] and
	* generic/tclCmdAH.c:	[while] (the script, not the tests)
	* generic/tclCmdIL.c:
	* generic/tclCmdMZ.c:
	* generic/tclInt.h:
	* tests/NRE.test:

	* generic/tclBasic.c:	Moved the few remaining defs from tclNRE.h to
	* generic/tclDictObj.c: tclInt.h, eliminated inclusion of tclNRE.h
	* generic/tclExecute.c: everywhere.
	* generic/tclInt.h:
	* generic/tclInterp.c:
	* generic/tclNRE.h (removed):
	* generic/tclNamesp.c:
	* generic/tclOOBasic.c:
	* generic/tclOOInt.h:
	* generic/tclProc.c:
	* generic/tclTest.c:
	* unix/Makefile.in:

2008-07-30  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:	 Improved tailcalls.
	* generic/tclCompile.h:
	* generic/tclExecute.c:
	* generic/tclTest.c:
	* tests/NRE.test:

	* generic/tclBasic.c (TclNREvalObjEx): New comments and code reorg
	to clarify what is happening.

	* generic/tclBasic.c: Guard against the value of iPtr->evalFlags
	changing between the times where TEOV and TEOV_exception run. Thanks
	dgp for catching this.

2008-07-29  Miguel Sofer  <msofer@users.sf.net>

	* tests/NRE.test: New tests that went MIA in the NRE revamping

	* generic/tclBasic.c:	Clean up
	* generic/tclNRE.h:
	* generic/tclExecute.c:

	* generic/tclBasic.c:	Made use of the thread's alloc cache stored in
	* generic/tclInt.h:	the ekeko at interp creation to avoid hitting
	* generic/tclNRE.h:	the TSD each time an NRE callback is pushed or
	* generic/tclThreadAlloc.c: pulled; the approach is suitably general
	to extend to every other obj allocation where an interp is know; this
	is left for some other time, requires a lot of grunt work.

	* generic/tclExecute.c:	 Fix [Bug 2030670] that cause TclStackRealloc
	to panic on rare corner cases. Thx ajpasadyn for diagnose and patch.

	* generic/tcl.decls:	 Completely revamped NRE implementation, with
	* generic/tclBasic.c:	 (almost) unchanged API.
	* generic/tclCompile.h:
	* generic/tclExecute.c:	 TEBC will require a bit of a facelift, but
	* generic/tclInt.decls:	 TEOV at least looks great now. There are new
	* generic/tclInt.h:	 tests (incomplete!) to verify that execution
	* generic/tclInterp.c:	 is indeed in the same TEBC instance, at the
	* generic/tclNRE.h:	 same level in all stacks involved. Tailcalls
	* generic/tclNamesp.c:	 are still a bit leaky, still deserving to be
	* generic/tclOOBasic.c:	 in tcl::unsupported.
	* generic/tclOOMethod.c:
	* generic/tclProc.c:	 Uninit'd var warnings in TEBC with -O2, no
	* generic/tclTest.c:	 warnings otherwise.

2008-07-28  Jan Nijtmans  <nijtmans@users.sf.net>

	* doc/FileSystem.3:		CONSTified many functions using
	* generic/tcl.decls:		Tcl_FileSystem which all are supposed
	* generic/tclDecls.h:		to be a constant, but this was not
	* generic/tclFileSystem.h:	reflected in the API: Tcl_FSData,
	* generic/tclIOUtil.c:		Tcl_FSGetInternalRep, Tcl_FSRegister,
	* generic/tclPathObj.c:		Tcl_FSNewNativePath, Tcl_FSUnregister,
	* generic/tclTest.c:		Tcl_FSGetFileSystemForPath ...
	This change complies with TIP #27.
	***POTENTIAL INCOMPATIBILITY***

2008-07-28  Andreas Kupries  <andreask@activestate.com>

	* generic/tclBasic.c: Added missing ref count when creating an empty
	string as path (TclEvalEx). In 8.4 the missing code caused panics in
	the testsuite. It doesn't in 8.5. I am guessing that the code path
	with the missing the incr-refcount is not invoked any longer. Because
	the bug in itself is certainly the same.

2008-07-27  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOMethod.c (PushMethodCallFrame): Remove hack that should
	have gone when this code was merged into Tcl.

2008-07-27  Jan Nijtmans  <nijtmans@users.sf.net>

	* doc/Object.3:		CONSTified 3 functions using Tcl_ObjType
	* doc/ObjectType.3:	which all are supposed to be a constant, but
	* generic/tcl.decls:	this was not reflected in the API:
	* generic/tcl.h:	Tcl_RegisterObjType, Tcl_ConvertToType,
	* generic/tclDecls.h:	Tcl_GetObjType
	* generic/tclObj.c:	Introduced a CONST86_RETURN, so extensions
	* generic/tclCompCmds.c: which use Tcl_ObjType directly can be
	* generic/tclOOMethod.c: modified to compile against both Tcl 8.5 and
	* generic/tclTestobj.c:	Tcl 8.6. tclDecls.h regenerated
	This change complies with TIP #27.
	***POTENTIAL INCOMPATIBILITY***

2008-07-25  Andreas Kupries  <andreask@activestate.com>

	* test/info.test: More work on singleTestInterp usability. [1605269]

	* tests/info.test: Tests 38.* added, exactly testing the tracking of
	location for uplevel scripts. Resolved merge conflict on info-37.0,
	switched !singleTestInterp constraint to glob matching instead. Ditto
	info-22.8, removed constraint, more glob matching, and reduced the
	depth of the stack we check. More is coming, right now I want to
	commit the bug fixes.

	* tests/oo.test: Updated oo-22.1 for expanded location tracking.

	* generic/tclCompile.c (TclInitCompileEnv): Reorganized the
	initialization of the #280 location information to match the flow in
	TclEvalObjEx to get more absolute contexts.

	* generic/tclBasic.c (TclEvalObjEx): Added missing cleanup of extended
	location information.

2008-07-25  Daniel Steffen  <das@users.sourceforge.net>

	* tests/info.test (info-37.0): Add !singleTestInterp constraint;
	(info-22.8, info-23.0): switch to glob matching to avoid sensitivity
	to tcltest.tcl line number changes, remove knownBug constraint, fix
	expected result. [Bug 1605269]

2008-07-24  Jan Nijtmans  <nijtmans@users.sf.net>

	* doc/Notifier.3:      CONSTified 4 functions in the Notifier which
	* doc/Thread.3:	       all have a Tcl_Time* in it which is supposed
	* generic/tcl.decls:   to be a constant, but this was not reflected
	* generic/tcl.h:       reflected in the API:
	* generic/tclDecls.h:	    Tcl_SetTimer, Tcl_WaitForEvent,
	* generic/tclNotify.c:	    Tcl_ConditionWait, Tcl_SetMaxBlockTime
	* macosx/tclMacOSXNotify.c:
	* generic/tclThread.c: Introduced a CONST86, so extensions which have
	* unix/tclUnixNotfy.c: have their own Notifier (are there any?) can
	* unix/tclUnixThrd.c:  can be modified to compile against both Tcl
	* win/tclWinNotify.c:  Tcl 8.5 and Tcl 8.6
	* win/tclWinThrd.c:    Regenerated tclDecls.h with "make stubs".
	This change complies with TIP #27
	***POTENTIAL INCOMPATIBILITY***

2008-07-23  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* tests/lrange.test: Added relative speed test to check for lrange
	in-place optimization committed 2008-06-30.
	* tests/binary.test: Added relative speed test to check for pure byte
	array CONCAT1 optimization committed 2008-06-30.

2008-07-23  Andreas Kupries  <andreask@activestate.com>

	* tests/info.test: Reordered the tests to have monotonously increasing
	numbers.

	* generic/tclBasic.c: Modified TclArgumentGet to reject pure lists
	* generic/tclCmdIL.c: immediately, without search. Reworked setup of
	* generic/tclCompile.c: eoFramePtr, doesn't need the line information,
	* tests/info.test: more sensible to have everything on line 1 when
	eval'ing a pure list. Updated the users of the line information to
	special case this based on the frame type (i.e.
	TCL_LOCATION_EVAL_LIST). Added a testcase demonstrating the new
	behaviour.

2008-07-23  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c (GetCommandSource): Added comment with
	explanation and warning for waintainers.

2008-07-22  Andreas Kupries  <andreask@activestate.com>

	* generic/tclCompile.c: Made the new TclEnterCmdWordIndex static, and
	* generic/tclCompile.h: ansified.

	* generic/tclBasic.c: Ansified the new functions. Added missing
	function comments.

	* generic/tclBasic.c: Reworked the handling of bytecode literals for
	* generic/tclCompile.c: #280 to fix the abysmal performance for deep
	* generic/tclCompile.h: recursion, replaced the linear search through
	* generic/tclExecute.c: the whole stack with another hashtable and
	* generic/tclInt.h: simplified the data structure used by the compiler
	by using an array instead of a hashtable. Incidentially this also
	fixes the memory leak reported via [Bug 2024937].

2008-07-22  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:	 Added numLevels field to CommandFrame, let
	* generic/tclExecute.c:	 GetCommandSource use it. This solves [Bug
	* generic/tclInt.h:	 2017146]. Thx dgp for the analysis.

2008-07-21  Andreas Kupries  <andreask@activestate.com>

	* generic/tclBasic.c: Extended the existing TIP #280 system (info
	* generic/tclCmdAH.c: frame), added the ability to track the absolute
	* generic/tclCompCmds.c: location of literal procedure arguments, and
	* generic/tclCompile.c: making this information available to uplevel
	* generic/tclCompile.h: eval, and siblings. This allows proper
	* generic/tclInterp.c: tracking of absolute location through custom
	* generic/tclInt.h: (Tcl-coded) control structures based on uplevel,
	* generic/tclNamesp.c: etc.
	* generic/tclProc.c:
	* tests/info.test:

2008-07-21  Jan Nijtmans  <nijtmans@users.sf.net>

	* generic/*.c: Fix [2021443] inconsistant "wrong # args" messages
	* win/tclWinReg.c
	* win/tclWinTest.c
	* tests/*.test

2008-07-21  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	TIP #304 IMPLEMENTATION

	* generic/tcl.decls:	Public API
	* generic/tclIOCmds.c:	Generic part
	* unix/tclUnixPipe.c:	OS part
	* win/tclWinPipe.c:	OS part
	* tests/chan.test:	[chan pipe] tests
	* tests/ioCmd.test:	Modernized checks
	* tests/ioTrans.test:

2008-07-21  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* generic/tclFCmd.c:  Inodes on windows are unreliable. [Bug 2015723]
	* tests/winFCmd.test: test rename with inode collision

2008-07-21  Miguel Sofer  <msofer@users.sf.net>

	* generic/tcl.decls:	  Changed the implementation of
	* generic/tclBasic.c:	  [namespace import]; removed
	* generic/tclDecls.h:	  Tcl_NRObjProc, replaced with
	* generic/tclExecute.c:	  Tcl_NRCmdSwap (proposed public
	* generic/tclInt.h:	  NRE API). This should fix
	* generic/tclNRE.h:	  [Bug 582506].
	* generic/tclNamesp.c:
	* generic/tclStubInit.c:

	* generic/tclBasic.c:	 NRE: enabled calling NR commands
	* generic/tclExecute.c:	 from the callbacks. Completely
	* generic/tclInt.h:	 redone tailcall implementation
	* generic/tclNRE.h:	 using the new feature. [Bug 2021489]
	* generic/tclProc.c:
	* tests/NRE.test:

2008-07-20  Kevin B. Kenny  <kenykb@acm.org>

	* tests/fileName.test: Repaired the failing test fileName-15.7 from
	dkf's commit earlier today.

2008-07-20  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclDictObj.c (SetDictFromAny): Make the list->dict
	transformation a bit more efficient; modern dicts are ordered and so
	we can round-trip through lists without needing the string rep at all.
	* generic/tclListObj.c (SetListFromAny): Make the dict->list
	transformation not lossy of internal representations and hence more
	efficient. [Bug 2008248] (ajpasadyn) but using a more efficient patch.

	* tests/fileName.test: Revise to reduce the obscurity of tests. In
	particular, all tests should now produce informative messages on
	failure and the quantity of [catch]-based obscurity is now greatly
	reduced; non-erroring is now checked for directly.

2008-07-19  Donal K. Fellows  <dkf@users.sf.net>

	* tests/env.test: Add LANG to the list of variables that are not
	touched by the environment variable tests, so that subprocesses can
	get their system encoding correct.

	* tests/exec.test, tests/env.test: Rewrite so that non-ASCII
	characters are not used in the final comparison. Part of fixing [Bug
	1513659].

2008-07-18  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:	 Optimization: replace calls to
	* generic/tclDictObj.c:	 Tcl_NRAddCallback with the macro
	* generic/tclExecute.c:	 TclNRAddCallback.
	* generic/tclInterp.c:
	* generic/tclNRE.h:
	* generic/tclNamesp.c:
	* generic/tclOO.c:
	* generic/tclOOBasic.c:
	* generic/tclOOCall.c:
	* generic/tclOOInt.h:
	* generic/tclOOMethod.c:
	* generic/tclProc.c:

2008-07-18  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.c (TclNRNewObjectInstance, FinalizeAlloc):
	* generic/tclOOBasic.c (TclOO_Class_Create, TclOO_Class_CreateNs)
	(TclOO_Class_New, FinalizeConstruction, AddConstructionFinalizer):
	NRE-enablement of the class construction methods.

2008-07-18  Miguel Sofer  <msofer@users.sf.net>

	* tests/NRE.test:  Added basic tests for deep TclOO calls

	* generic/tcl.decls:	   Change the public api prefix from
	* generic/tcl.h:	   TclNR_foo to Tcl_NRfoo
	* generic/tclBasic.c:
	* generic/tclDecls.h:
	* generic/tclDictObj.c:
	* generic/tclExecute.c:
	* generic/tclInterp.c:
	* generic/tclNRE.h:
	* generic/tclNamesp.c:
	* generic/tclOO.c:
	* generic/tclOOBasic.c:
	* generic/tclOOCall.c:
	* generic/tclOOMethod.c:
	* generic/tclProc.c:
	* generic/tclStubInit.c:

2008-07-18  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOBasic.c (TclOO_Object_Eval, FinalizeEval): NRE-enable
	the oo::object.eval method.

2008-07-18  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclDictObj.c (DictWithCmd, DictUpdateCmd): Fix refcounting
	bugs that caused crashes [Bug 2017857].

	* generic/tclBasic.c (TclNREvalObjEx): Streamline the management of
	the command frame (opt).

2008-07-17  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclDictObj.c (DictWithCmd, FinalizeDictWith): Split the
	implementation of [dict with] so that it works with NRE.
	(DictUpdateCmd, FinalizeDictUpdate): Similarly for the non-compiled
	version of [dict update].

2008-07-16  George Peter Staplin  <georgeps@users.sf.net>

	* win/tclWinThrd.c: Test for TLS_OUT_OF_INDEXES to make certain that
	thread key creation is successful.

2008-07-16  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.c, generic/tclOOInt.h, generic/tclOOBasic.c:
	* generic/tclOOCall.c, generic/tclOOMethod.c: NRE-enable the TclOO
	implementation in Tcl. No change to public APIs, except that method
	implementations can now be NRE-aware if they choose (which normal
	methods and forwards are). On the other hand, callers of
	TclOOInvokeObject (which is only in the internal stub table) will need
	to deal with the fact that it's only safe to call inside an NRE-aware
	context.
	***POTENTIAL INCOMPATIBILITY***

2008-07-15  Miguel Sofer  <msofer@users.sf.net>

	* tests/NRE.test:	Better constraint for testing the existence of
	* tests/stack.test:	teststacklimit, to insure that the test suite
				runs under tclsh.

	* generic/tclParse.c: Fixing incomplete reversion of "fix" for [Bug
	2017583], missing TclResetCancellation call.

2008-07-15  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclBasic.c (Tcl_CancelEval): Fix blunder. [Bug 2018603]

	* doc/DictObj.3: Fix error in example. [Bug 2016740]

	* generic/tclNamesp.c (EnsembleUnknownCallback): Factor out some of
	the more complex parts of the ensemble code to make it easier to
	understand and hence to permit tighter compilation of code on the
	critical path.

2008-07-14  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclParse.c: Reverting the "fix" for [Bug 2017583], numLevel
	* tests/parse.test:   management and TclInterpReady check seems to be
			      necessary after all.

2008-07-14  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclProc.c (TclNRApplyObjCmd, TclObjInterpProcCore):
	* generic/tclBasic.c (TclNR_AddCallback, TclEvalObjv_NR2):
	* generic/tclNRE.h (TEOV_callback): Change the callback storage type
	to use an array, so guaranteeing correct inter-member spacing and
	memory layout.

2008-07-14  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c:	 Remove unneeded TclInterpReady calls
	* generic/tclParse.c:

	* generic/tclBasic.c.:	 Embedded Tcl_Canceled() calls into
	* generic/tclExecute.c:	 TclInterpReady().
	* generic/tclParse.c:

	* generic/tclVar.c: Fix error message

	* generic/tclParse.c: Remove unnecessary numLevel management
	* tests/parse.test:   [Bug 2017583]

	* generic/tclBasic.c.:	 NRE left too many calls to
	* generic/tclExecute.c:	 TclResetCancellation lying around: it
	* generic/tclProc.c:	 only needs to be called prior to any
				 iPtr->numLevels++. Thanks mistachkin.

	* generic/tclBasic.c: TclResetCancellation() calls were misplaced
	(merge mishap); stray //. Thanks patthoyts.

	* generic/tclInt.h: The new macros TclSmallAlloc and TclSmallFree
	were badly defined under mem debugging [Bug 2017240] (thx das)

2008-07-13  Miguel Sofer  <msofer@users.sf.net>

	NRE implementation [Patch 2017110]

	* generic/tcl.decls:	 The NRE infrastructure
	* generic/tcl.h:
	* generic/tclBasic.c:
	* generic/tclCmdAH.c:
	* generic/tclCompile.h:
	* generic/tclDecls.h:
	* generic/tclExecute.c:
	* generic/tclHistory.c:
	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclIntDecls.h:
	* generic/tclNRE.h:
	* generic/tclStubInit.c:
	* unix/Makefile.in:

	* generic/tclInterp.c:	 NRE-enabling: procs, lambdas, uplevel,
	* generic/tclNamesp.c:	 same-interp aliases, ensembles, imports
	* generic/tclProc.c:	 and namespace_eval.

	* generic/tclTestProcBodyObj.c: New NRE specific tests (few, but
	* tests/NRE.test:		note that the thing is actually
					tested by the whole testsuite.

	* tests/interp.test:	 Fixed numLevel counting.
	* tests/parse.test:
	* tests/stack.test:

	* unix/configure:	 Removing support for the hacky nonportable
	* unix/configure.in:	 stack check: it is not needed anymore, Tcl
	* unix/tclConfig.h.in:	 is very thrifty on the C stack.
	* unix/tclUnixInit.c:
	* unix/tclUnixTest.c:
	* win/tclWin32Dll.c:

2008-07-08  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclGet.c:	Corrected out of date comments and removed
	* generic/tclInt.decls:	internal routine TclGetLong() that's no
	longer used. If an extension is using this from the internal stubs
	table, it can shift to the public routine Tcl_GetLongFromObj() or
	can request addition of a public Tcl_GetLong().
	***POTENTIAL INCOMPATIBILITY***

	* generic/tclIntDecls.h:	make genstubs
	* generic/tclStubInit.c:

2008-07-08  Donal K. Fellows  <dkf@users.sf.net>

	* doc/CrtInterp.3: Tighten up the descriptions of behaviour to make
	this page easier to read for a "Tcl 8.6" audience.

2008-07-07  Andreas Kupries  <andreask@activestate.com>

	* generic/tclCmdIL.c (InfoFrameCmd): Fixed unsafe idiom of setting
	the interp result found by Don Porter.

2008-07-07  Donal K. Fellows  <dkf@users.sf.net>

	* doc/regexp.n, doc/regsub.n: Correct examples. [Bug 1982642]

2008-07-06  Donal K. Fellows  <dkf@users.sf.net>

	* doc/lindex.n: Improve examples.

2008-07-03  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIORChan.c (InvokeTclMethod): Fixed the memory leak
	reported in [Bug 1987821]. Thanks to Miguel for the report and Don
	Porter for tracking the cause down.

2008-07-03  Don Porter  <dgp@users.sourceforge.net>

	* library/package.tcl:	Removed [file readable] testing from
	[tclPkgUnknown] and friends. We find out soon enough whether a file is
	readable when we try to [source] it, and not testing before allows us
	to workaround the bugs on some common filesystems where [file
	readable] lies to us. [Patch 1969717]

2008-07-01  Donal K. Fellows  <dkf@users.sf.net>

	* generic/regc_nfa.c (duptraverse): Impose a maximum stack depth on
	the single most recursive part of the RE engine. The actual maximum
	may need tuning, but that needs a system with a small stack to carry
	out. [Bug 1905562]

	* tests/string.test: Eliminate non-ASCII characters from the actual
	test script. [Bug 2006884]

2008-06-30  Donal K. Fellows  <dkf@users.sf.net>

	* doc/ObjectType.3: Clean up typedef formatting.

2008-06-30  Don Porter  <dgp@users.sourceforge.net>

	* doc/ObjectType.3:	Updated documentation of the Tcl_ObjType
	struct to match expectations of Tcl 8.5. [Bug 1917650]

2008-06-30  Alexandre Ferrieux  <ferrieux@users.sourceforge.net>

	* generic/tclCmdIL.c: Lrange cleanup and in-place optimization. [Patch
	1890831]

	* generic/tclExecute.c: Avoid useless String conversion for CONCAT1 of
	pure byte arrays. [Patch 1953758]

2008-06-29  Donal K. Fellows  <dkf@users.sf.net>

	* doc/*.1, doc/*.3, doc/*.n: Many small updates, purging out of date
	change bars and cleaning up the formatting of typedefs. Added a few
	missing bits of documentation in the process.

2008-06-29  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclPathObj.c:	 Plug memory leak in [Bug 1999176] fix. Thanks
	to Rolf Ade for detecting.

2008-06-29  Donal K. Fellows  <dkf@users.sf.net>

	* doc/interp.n: Corrected order of subcommands. [Bug 2004256]
	Removed obsolete (i.e. 8.5) .VS/.VE pairs.

	* doc/object.n (EXAMPLES): Fix incorrect usage of oo::define to be
	done with oo::objdefine instead. [Bug 2004480]

2008-06-28  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclPathObj.c:	 Plug memory leak in [Bug 1972879] fix. Thanks
	to Rolf Ade for detecting and Dan Steffen for the fix. [Bug 2004654]

2008-06-26  Andreas Kupries  <andreask@activestate.com>

	* unix/Makefile.in: Followup to my change of 2008-06-25, make code
	generated by the Makefile and put into the installed tm.tcl
	conditional on interpreter safeness as well. Thanks to Daniel Steffen
	for reminding me of that code.

2008-06-25  Don Porter  <dgp@users.sourceforge.net>

	*** 8.6a1 TAGGED FOR RELEASE ***

	* changes:	Updates for 8.6a1 release.

	* generic/tclOO.h:	Bump to TclOO 0.5.

2008-06-25  Andreas Kupries  <andreask@activestate.com>

	* library/tm.tcl:   Modified the handling of Tcl Modules and of the
	* library/safe.tcl: Safe Base to interact nicely with each other,
	* library/init.tcl: enabling requiring Tcl Modules in safe
	* tests/safe.test:  interpreters. [Bug 1999119]

2008-06-25  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* win/rules.vc: Fix versions of dde and registry dlls
	* win/makefile.vc: Fix problem building with staticpkg option

2008-06-24  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclPathObj.c: Fixed some internals management in the "path"
	Tcl_ObjType for the empty string value. Problem led to a crash in the
	command [glob -dir {} a]. [Bug 1999176]

2008-06-24  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* doc/fileevent.n: Fix examples and comment on eof use. [Bug 1995063]

2008-06-23  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclPathObj.c: Fixed bug in Tcl_GetTranslatedPath() when
	operating on the "Special path" variant of the "path" Tcl_ObjType
	intrep. A full normalization was getting done, in particular, coercing
	relative paths to absolute, contrary to what the function of producing
	the "translated path" is supposed to do. [Bug 1972879]

2008-06-20  Don Porter  <dgp@users.sourceforge.net>

	* changes:	Updates for 8.6a1 release.

	* generic/tclInterp.c:	Fixed completely boneheaded mistake that
	* tests/interp.test:	[interp bgerror $slave] and [$slave bgerror]
	would always act like [interp bgerror {}]. [Bug 1999035]

	* tests/chanio.test:	Corrected flawed tests revealed by a -debug 1
	* tests/cmdAH.test:	-singleproc 1 test suite run.
	* tests/event.test:
	* tests/interp.test:
	* tests/io.test:
	* tests/ioTrans.test:
	* tests/namespace.test:

	* tests/encoding.test:	Make failing tests pass again. [Bug 1972867]

2008-06-19  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.c (Tcl_ObjectContextInvokeNext): Corrected 'next' (at
	* tests/oo.test (oo-7.8):	end of a call chain) to make it
	* doc/next.n:			consistent with the TIP. [Bug 1998244]

	* generic/tclOOCall.c (AddSimpleClassChainToCallContext): Make sure
	* tests/oo.test (oo-14.8): that class mixins are processed in the
	documented order. [Bug 1998221]

2008-06-19  Don Porter  <dgp@users.sourceforge.net>

	* changes:	Updates for 8.6a1 release.

	* README:		Bump version number to 8.6a1
	* generic/tcl.h:
	* library/init.tcl:
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/configure.in:

	* unix/configure:	autoconf-2.59
	* win/configure:

2008-06-17  Andreas Kupries  <andreask@activestate.com>

	* generic/tclClock.c (ClockConvertlocaltoutcObjCmd): Removed left
	over debug output.

2008-06-17  Andreas Kupries  <andreask@activestate.com>

	* doc/tm.n: Followup to changelog entry 2008-03-18 regarding
	::tcl::tm::Defaults. Updated the documentation to not only mention the
	new (underscored) form of environment variable names, but make it the
	encouraged form as well. [Bug 1914604]

2008-06-17  Kevin Kenny  <kennykb@acm.org>

	* generic/tclClock.c (ConvertLocalToUTC):
	* tests/clock.test (clock-63.1): Fixed a bug where the internal
	ConvertLocalToUTC command segfaulted if passed a dictionary without
	the 'localSeconds' key. To the best of my knowledge, the bug was not
	observable in the [clock] command itself.

2008-06-16  Andreas Kupries  <andreask@activestate.com>

	* generic/tclCmdIL.c (TclInfoFrame): Moved the code looking up the
	* tests/info.test: information for key 'proc' out of the
	TCL_LOCATION_BC branch to after the switch, this is common to all
	frame types. Updated the testsuite to match. This was exposed by the
	2008-06-08 commit (Miguel), switching uplevel from direct eval to
	compilation. [Bug 1987851]

2008-06-16  Andreas Kupries  <andreask@activestate.com>

	* tests/ioTrans.test (iortrans-11.*): Fixed same issue as for
	iortrans.tf-11.*, cleanup of temp file, making this a followup to the
	entry on 2008-06-10 by myself.

2008-06-13  David Gravereaux  <davygrvy@pobox.com>

	* win/rules.vc: SYMBOLS macro is now being set to zero when $(OPTS) is
	not available.
	* win/makefile.vc: The Stubs source files (tclStubLib.c and
	tclOOStubLib.c) should not be compiled with the -GL flag.

2008-06-13  Joe Mistachkin  <joe@mistachkin.com>

	TIP #285 IMPLEMENTATION

	* doc/Eval.3: Added documentation for the Tcl_CancelEval and
	Tcl_Canceled functions and the TCL_CANCEL_UNWIND flag bit.
	* doc/after.n: Corrected the spelling of 'canceled' in the
	documentation.
	* doc/interp.n: Added documentation for [interp cancel].
	* generic/tcl.decls: Added the Tcl_CancelEval and Tcl_Canceled
	functions to the stubs table.
	* generic/tcl.h: Added the TCL_CANCEL_UNWIND flag bit.
	* generic/tclBasic.c: The bulk of the script cancellation
	functionality is defined here. Added code to initialize and manage the
	script cancellation hash table in a thread-safe manner. Reset script
	cancellation flags prior to increasing the nesting level (if the
	nesting level is currently zero) and always cooperatively check for
	script cancellation near the start of TclEvalObjvInternal and after
	invoking async handlers.
	* generic/tclDecls.h: Regenerated.
	* generic/tclEvent.c: Call TclFinalizeEvaluation during finalization
	to cleanup the script cancellation hash table. During [vwait], always
	cooperatively check for script cancellation. Corrected the spelling of
	'canceled' in comments to be consistent with the documentation.
	* generic/tclExecute.c: Reset script cancellation flags prior to
	increasing the nesting level (if the nesting level is currently zero)
	and always cooperatively check for script cancellation after invoking
	async handlers. Prevent [catch] from catching script cancellation when
	the TCL_CANCEL_UNWIND flag is set (similar to the manner used by TIP
	143 when a limit has been exceeded).
	* generic/tclInt.decls: Added TclResetCancellation to the internal
	stubs table.
	* generic/tclInt.h: Added asyncCancel and asyncCancelMsg fields to the
	private Interp structure. Added private interp flag value CANCELED to
	help control script cancellation.
	* generic/tclIntDecls.h: Regenerated.
	* generic/tclInterp.c (Tcl_InterpObjCmd): Added [interp cancel]
	subcommand.
	* generic/tclNotify.c (Tcl_DeleteEventSource): Corrected the spelling
	of 'canceled' in comments to be consistent with the documentation.
	* generic/tclParse.c: Reset script cancellation flags prior to
	* generic/tclProc.c: increasing the nesting level (if the nesting
	level is currently zero) and cooperatively check for script
	cancellation prior to evaluating commands.
	* generic/tclStubInit.c: Regenerated.
	* generic/tclThreadTest.c (Tcl_ThreadObjCmd): Added script
	cancellation support ([testthread cancel]).
	Modified [testthread id] to allow querying of the 'main' thread ID.
	Corrected comments to reflect the actual command syntax. Made
	[testthread wait] cooperatively check for script cancellation. Added
	[testthread event] to allow for processing one pending event without
	blocking.
	* generic/tclTimer.c: Delay for a maximum of 500 milliseconds prior to
	checking for async handlers and script cancellation.
	* tests/cmdAH.test: Changed [interp c] to [interp create].
	* tests/interp.test: Added and fixed tests for [interp cancel].
	* tests/thread.test: Added tests for script cancellation via
	[testthread cancel].
	* tools/man2help2.tcl: Fixed problems with WinHelp target (see
	* tools/man2tcl.c: [Bug 1934200], [Bug 1934265], and [Bug 1934272]).
	* win/makefile.vc: Added 'pdbs' option for Windows build rules to
	* win/rules.vc:	   allow for non-debug builds with full symbols.
	* win/tcl.hpj.in: Corrected version for WinHelp target.
	* win/tclWinNotify.c: Used SleepEx and WaitForSingleObjectEx on
	* win/tclWinThrd.c: Windows because they are alertable.

2008-06-12  Daniel Steffen  <das@users.sourceforge.net>

	* unix/Makefile.in:		Add complete deps on tclDTrace.h.

	* generic/tclOO.c:		Use TclOOStubs hooks field to retrieve
	* generic/tclOODecls.h:		TclOOIntStubs pointer. [Bug 1980953]
	* generic/tclOOIntDecls.h:
	* generic/tclOOStubInit.c:
	* generic/tclOOStubLib.c:

	* generic/tclIORTrans.c:	Fix signed <-> unsigned cast warnings.

	* unix/Makefile.in:		Clean generated tclDTrace.h file.
	* unix/configure.in (SunOS):	Fix static DTrace-enabled build.

	* unix/tcl.m4 (SunOS-5.11): Fix 64bit amd64 support with gcc & Sun cc.
	* unix/configure: autoconf-2.59

	* macosx/Tcl.xcodeproj/project.pbxproj:	Add tclIORTrans.c; updates and
						cleanup for Xcode 3.1/Leopard.
	* macosx/Tcl.xcode/project.pbxproj:	Sync Tcl.xcodeproj changes.
	* macosx/README:			Document new build configs.

2008-06-10  Joe English  <jenglish@users.sourceforge.net>

	* generic/tclEncoding.c(UtfToUtfProc): Avoid unwanted sign extension
	when converting incomplete UTF-8 sequences. See [Bug 1908443] for
	details.

2008-06-10  Andreas Kupries  <andreask@activestate.com>

	* tests/ioTrans.test (iortrans.tf-6.1): Fixed the [Bug 1988552],
	reported by Kevin. Have to close the channel before removal of the
	file. Fixed same bug in test 'iortrans.tf-11.0', after fixing missing
	cleanup of the file in 'iortrans.tf-11.*'. Lastly fixed the names of
	the threaded tests 'iortrans-8.*' to the correct 'iortrans.tf-8.*'.

2008-06-09  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* generic/tclIORTrans.c (ReflectInput): Fixed a bug triggered by Pat
	Thoyts <patthoyts@users.sourceforge.net>. Reset the EOF flag after
	draining the Tcl level into the result buffer, to make sure that the
	result buffer will be drained as well by repeated calls to
	ReflectInput should it contain more than one buffer-full of data.
	Without that reset the higher I/O system will not call on ReflectInput
	anymore due to the assumed EOF, thus losing the data which did not fit
	in the buffer of the call which caused the eof and drain.

2008-06-09  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOCall.c (TclOOGetSortedMethodList): Plug memory leak
	that occurred when all methods were hidden. [Bug 1987817]

2008-06-08  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:	   Compilation of uplevel scripts, allow
	* generic/tclCompCmds.c:   non-body compiled scripts to access the
	* generic/tclCompile.c:	   LVT (but not to extend it) and enable the
	* generic/tclCompile.h:	   canonical list opt to sidestep the
	* generic/tclExecute.c:	   compiler. [Patch 1973096]
	* generic/tclProc.c:
	* tests/uplevel.test:

2008-06-06  Andreas Kupries  <andreask@activestate.com>

	TIP #230 IMPLEMENTATION

	* generic/tclIOCmd.c: Integration of transform commands into 'chan'
			      ensemble.
	* generic/tclInt.h: Definitions of the transform commands.
	* generic/tclIORTrans.c: Implementation of the reflection transforms.
	* tests/chan.test:  Tests updated for new sub-commands of 'chan'.
	* tests/ioCmd.test: Tests updated for new sub-commands of 'chan'.
	* tests/ioTrans.test: Whole new set of tests for the reflection
			      transform.
	* unix/Makefile.in: Integration of new files into build rules.
	* win/Makefile.in:  Integration of new files into build rules.
	* win/makefile.vc:  Integration of new files into build rules.

	NOTE: The file 'tclIORTrans.c' has a lot of code in common with the
	      file 'tclIORChan.c', as that made it much easier to develop the
	      reference implementation as a separate module. Now that the
	      transforms have been committed the one thing left to do is to go
	      over both modules and see which of the common parts we can
	      factor out and share.

2008-06-04  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* generic/tclBinary.c: TIP #317 implementation
	* tests/binary.test:

2008-06-02  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclOO.c (ReleaseClassContents): Fix the one remaining
	valgrind complaint about oo.test, caused by failing to protect the
	Object as well as the Class corresponding to a subclass being deleted
	and hence getting a freed-memory read when attempting to delete the
	class command. [Bug 1981001]

2008-06-01  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOOMethod.c (Tcl_NewMethod): Complete the fix of [Bug
	1981001], previous fix was incomplete though helpful in telling me
	where to look.

2008-06-01  Joe Mistachkin  <joe@mistachkin.com>

	* win/Makefile.in: Add tclOO genstubs to Windows makefiles and remove
	* win/makefile.vc: -DBUILD_tcloo because it is no longer required.

2008-06-01  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclOODecls.h:	   Added the swizzling of DLLEXPORT and
	* generic/tclOOIntDecls.h: DLLIMPORT needed to make EXTERN work.

	* generic/tclDictObj.c:	 Added missing initializers to the ensemble
				 map to silence a compiler warning. Thanks to
				 George Peter Staplin for the report.

	* generic/tclOOMethod.c: Fix a bug where the refcount of a method was
				 reset if the method was redefined while there
				 was an active invocation. [Bug 1981001]

2008-06-01  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.decls, unix/Makefile.in (genstubs): Make generation of
	stub tables correct.
	* generic/tclOO{Decls.h,IntDecls.h,StubInit.c,StubLib.c}: Fixes to
	make the generation work correctly, removing subtle differences
	between output of different versions of stub generator.

2008-06-01  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclOOStubLib.c:	Ensure use of tcl stubs; include in
	* unix/Makefile.in:		stub lib; disable broken tclOO
					genstubs

	* generic/tclOO.c:		Make tclOO stubs tables 'static const'
	* generic/tclOODecls.h:		and stub table pointers MODULE_SCOPE
	* generic/tclOOIntDecls.h:	(change generated files manually
	* generic/tclOOStubInit.c:	pending genstubs support for tclOO).
	* generic/tclOOStubLib.c:

	* generic/tclOO.c:		Fix warnings for 'int<->ptr
	* generic/tclOOCall.c:		conversion' and 'signed vs unsigned
	* generic/tclOOMethod.c:	comparison'.

	* tests/msgcat.test:	Fix for ::tcl::mac::locale with @modifier.

	* tools/tsdPerf.tcl:	Use [info sharedlibextension]

	* unix/tclConfig.h.in:	autoheader-2.59

	* macosx/Tcl.xcodeproj/project.pbxproj:	Add new tclOO files; add debug
	* macosx/README:			configs with corefoundation
						disabled and with gcov; update
						to Xcode 3.1.

2008-05-31  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclOO.c (InitFoundation): Correct reference counting for
	strings used when creating the constructor for classes.
	* generic/tclOOMethod.c (TclOODelMethodRef): Correct fencepost error
	in reference counting of method implementation structures.
	* tests/oo.test (oo-0.5): Added a test to detect a memory leak problem
	relating to disposal of the core object system.

	TIP#257 IMPLEMENTATION

	* generic/tclBasic.c, generic/tclOOInt.h: Correct declarations.
	* win/Makefile.in, win/makefile.bc, win/makefile.vc: Build support for
	Win32, from Joe Mistachkin. [Patch 1980861]

	* generic/tclOO*, doc/*, tests/oo.test: Port of implementation of
	TclOO to sit directly inside Tcl. Note that this is incomplete (e.g.
	no build support yet for Windows).

2008-05-26  Jeff Hobbs  <jeffh@ActiveState.com>

	* tests/io.test (io-53.9): Need to close chan before removing file.

2008-05-26  Donal K. Fellows  <dkf@users.sf.net>

	* win/makefile.bc:		    Remove deprecated winhelp target.
	* win/Makefile.in, win/makefile.vc: It didn't work correctly anyway.

2008-05-23  Andreas Kupries  <andreask@activestate.com>

	* win/tclWinChan.c (FileWideSeekProc): Accepted a patch by Alexandre
	Ferrieux <ferrieux@users.sourceforge.net> to fix the [Bug 1965787].
	'tell' now works for locations > 2 GB as well instead of going
	negative.

	* generic/tclIO.c (Tcl_SetChannelBufferSize): Accepted a patch by
	* tests/io.test: Alexandre Ferrieux <ferrieux@users.sourceforge.net>
	* tests/chanio.test: to fix the [Bug 1969953]. Buffersize outside of
	the supported range are now clipped to nearest boundary instead of
	ignored.

2008-05-22  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclNamesp.c (Tcl_LogCommandInfo):	Restored ability to
	handle the argument value length = -1. Thanks to Chris Darroch for
	discovering the bug and providing the fix. [Bug 1968245]

2008-05-21  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclParse.c (ParseComment):	The new TclParseAllWhiteSpace
	* tests/parse.test (parse-15.60):	routine has no mechanism to
	return the "incomplete" status of "\\\n" so calling this routine
	anywhere that can be reached within a Tcl_ParseCommand() call is a
	mistake. In particular, ParseComment() must not use it. [Bug 1968882]

2008-05-20  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclNamesp.c (Tcl_SetNamespaceUnknownHandler): Corrected odd
	logic for handling installation of namespace unknown handlers which
	could lead too very strange things happening in the error case.

2008-05-16  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompile.c: Fix crash with tcl_traceExec. Found and fixed
	by Alexander Pasadyn. [Bug 1964803]

2008-05-15  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* win/makefile.vc: We should use the thread allocator for threaded
	* win/rules.vc:	   builds. Added 'tclalloc' option to disable.

2008-05-09  George Peter Staplin  <georgeps@xmission.com>

	* tools/tsdPerf.c:	A loadable Tcl extension for testing TSD
	performance.
	* tools/tsdPerf.tcl:	A simplistic tool that uses the thread
	extension and tsdPerf.so to get some performance metrics by,
	simulating, simple TSD contention.

2008-05-09  George Peter Staplin  <georgeps@xmission.com>

	* generic/tcl.h:	Make Tcl_ThreadDataKey a void *.
	* generic/tclInt.h:	Change around some function names and add some
	new per-platform declarations for thread-specific data functions.
	* generic/tclThread.c:	Make use of of the new function names that no
	longer have a Tclp prefix.
	* generic/tclThreadStorage.c: Replace the core thread-specific data
	(TSD) mechanism with an array offset solution that eliminates the hash
	tables, and only uses one slot of native TSD. Many thanks to Kevin B.
	Kenny for his help with this.

	* unix/tclUnixThrd.c:	Add platform-specific TSD functions for use by
	* win/tclWinThrd.c:	tclThreadStorage.c.

2008-05-09  Kevin B. Kenny  <kennykb@acm.org>

	* tests/dict.test (dict-19.2): Corrected a bug where the test was
	changed to use [apply] instead of a temporary proc, but the cleanup
	script still attempted to delete the temporary proc.

2008-05-07  Donal K. Fellows  <dkf@cspool38.cs.man.ac.uk>

	* generic/tclCompCmds.c (TclCompileDictAppendCmd): Fix silly off-by
	one error that caused a crash every time a compiled 'dict append' with
	more than one argument was used. Found by Colin McCormack.

2008-05-02  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* generic/tclBasic.c:	 Converted the [binary] command into an
	* generic/tclBinary.c:	 ensemble.
	* generic/tclInt.h:
	* test/binary.test:	 Updated the error tests for ensemble errors.

	* generic/tclFileName.c: Reverted accidental commit of TIP 316 APIs.

2008-04-27  Donal K. Fellows  <dkf@users.sf.net>

	* */*.c: A large tranche of getting rid of pre-C89-isms; if your
	compiler doesn't support things like proper function declarations,
	'void' and 'const', borrow a proper one when building Tcl. (The header
	files allow building things that link against Tcl with really ancient
	compilers still; the requirement is just when building Tcl itself.)

2008-04-26  Zoran Vasiljevic  <vasiljevic@users.sourceforge.net>

	* generic/tclAsync.c: Tcl_AsyncDelete(): panic if attempt to locate
	handler token fails. Happens when some other thread attempts to delete
	somebody else's token.

	Also, panic early if we find out the wrong thread attempting to delete
	the async handler (common trap). As, only the one that created the
	handler is allowed to delete it.

2008-04-24  Andreas Kupries  <andreask@activestate.com>

	* tests/ioCmd.test: Extended testsuite for reflected channel
	implementation. Added test cases about how it handles if the rug is
	pulled out from under a channel (= killing threads, interpreters
	containing the tcl command for a channel, and channel sitting in a
	different interpreter/thread.)

	* generic/tclIORChan.c: Fixed the bugs exposed by the new testcases,
	redone most of the cleanup and exit handling.

2008-04-21  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclIOUtil.c:		Removed all code delimited by
	* generic/tclTest.c:		USE_OBSOLETE_FS_HOOKS, completing
	* tests/ioCmd.test:		the deprecation path for these
	* tests/ioUtil.test (removed):	obsolete interfaces. (Code was active
	in Tcl 8.4, present but enabled only by customized compile switch in
	Tcl 8.5, and now completely gone for Tcl 8.6). Also removed all tests
	relevant only to the removed interfaces.

2008-04-19  George Peter Staplin  <georgeps@xmission.com>

	* doc/Ensemble.3: Fix a typo: s/defiend/defined/
	Thanks to hat0 for spotting this.

2008-04-16  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclInt.h:		Make stubs tables 'static const' and
	* generic/tclStubInit.c:	export only module-scope pointers to
	* generic/tclStubLib.c:		the main stubs tables (for package
	* tools/genStubs.tcl:		initialization). [Patch 1938497]
	* generic/tclBasic.c (Tcl_CreateInterp):
	* generic/tclTomMathInterface.c (TclTommath_Init):

	* generic/tclInt.h:		Revise Tcl_SetNotifier() to use a
	* generic/tclNotify.c:		module-scope hooks table instead of
	* generic/tclStubInit.c:	runtime stubs-table modification;
	* macosx/tclMacOSXNotify.c:	ensure all hookable notifier functions
	* win/tclWinNotify.c:		check for hooks; remove hook checks in
	* unix/tclUnixNotfy.c:		notifier API callers. [Patch 1938497]

2008-04-15  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c (CopyData):	Applied another patch by Alexandre
	* io.test (io-53.8a):		Ferrieux <ferrieux@users.sf.net>,
	* chanio.test (chan-io-53.8a):	to shift EOF handling to the async
	part of the command if a callback is specified, should the channel be
	at EOF already when fcopy is called. Testcase by myself.

2008-04-15  Daniel Steffen  <das@users.sourceforge.net>

	* unix/Makefile.in:	Adjust tclDTrace.h dependencies for removal
				of tclStubLib.o from TCL_OBJS. [Bug 1942795]

2008-04-14  Kevin B. Kenny  <kennykb@acm.org>

	* unix/tclUnixTime.c (NativeGetTime): Removed obsolete use of
	'struct timezone' in the call to 'gettimeofday'. [Bug 1942197]

	* tests/clock.test (clock-33.5, clock-33.5a, clock-33.8, clock-33.8a):
	Added comments to the test that it can fail on a heavily loaded
	system.

2008-04-10  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIOCmd.c (Tcl_FcopyObjCmd): Keeping check for negative
	values, changed to not be an error, but behave like the special value
	-1 (copy all, default).

	* tests/iocmd.test (iocmd-15.{12,13}): Removed.

	* tests/io.test (io-52.5{,a,b}): Reverted last change, added
	* tests/chanio.test (chan-io-52.5{,a,b}): comment regarding the
	meaning of -1, added two more testcases for other negative values,
	and input wrapped to negative.

2008-04-09  Donal K. Fellows  <dkf@users.sf.net>

	* tests/{fCmd,unixFCmd,winFCmd,winFile}.test: Tidying up of the test
	suite to make better use of tcltest2 and be clearer about what is
	being tested.

	* win/Makefile.in (html): Added target for doing convenient
	documentation builds, mirroring the one from unix/Makefile.

2008-04-09  Andreas Kupries  <andreask@activestate.com>

	* tests/chanio.test (chan-io-52.5): Removed '-size -1' from test,
	* tests/io.test (io-52.5): does not seem to have any bearing, and was
	an illegal value. Test case is not affected by the value of -size,
	test flag restoration and that evrything was properly copied.

	* generic/tclIOCmd.c (Tcl_FcopyObjCmd): Added checking of -size value
	* tests/ioCmd.test (iocmd-15.{13,14}): to reject negative values, and
	values overflowing 32-bit signed. Basic patch by Alexandre Ferrieux
	<ferrieux@users.sourceforge.net>, with modifications from me to
	separate overflow from true negative value. Extended testsuite. [Bug
	1557855]

2008-04-09  Daniel Steffen  <das@users.sourceforge.net>

	* tests/chanio.test (chan-io-53.8,53.9,53.10): Fix typo & quoting for
	* tests/io.test (io-53.8,53.9,53.10):	       spaces in builddir path

2008-04-08  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c: Added comments to the alignment macros used in
	GrowEvaluationStack() and friends.

2008-04-08  Daniel Steffen  <das@users.sourceforge.net>

	* tools/genStubs.tcl:	Revert erroneous 2008-04-02 change marking
				*StubsPtr as EXTERN instead of extern.

	* generic/tclDecls.h:	make genstubs
	* generic/tclIntDecls.h:
	* generic/tclIntPlatDecls.h:
	* generic/tclPlatDecls.h:
	* generic/tclTomMathDecls.h:

2008-04-07  Andreas Kupries  <andreask@activestate.com>

	* tests/io.test (io-53.10): Testcase for bi-directional fcopy.
	* tests/chanio.test:
	* generic/tclIO.c: Additional changes to data structures for fcopy and
	* generic/tclIO.h: channels to perform proper cleanup in case of a
	channel having two background copy operations running as is now
	possible.

	* generic/tclIO.c (BUSY_STATE, CheckChannelErrors, TclCopyChannel):
	New macro, and the places using it. This change allows for
	bi-directional fcopy on channels. Thanks to Alexandre Ferrieux
	<ferrieux@users.sourceforge.net> for the patch. [Bug 1350564]

2008-04-07  Reinhard Max  <max@suse.de>

	* generic/tclStringObj.c (Tcl_AppendFormatToObj): Fix [format {% d}]
	so that it behaves the same way as in 8.4 and as C's printf().
	* tests/format.test: Add a test for '% d' and '%+d'.

2008-04-05  Kevin B. Kenny  <kennykb@acm.org>

	* win/tclWinFile.c: (WinSymLinkDirectory): Fixed a problem that Tcl
	was creating an NTFS junction point (IO_REPARSE_TAG_MOUNT_POINT) but
	filling in the union member for a Vista symbolic link. We had gotten
	away with this error because the union member
	(SymbolicLinkReparseBuffer) was misdefined in this file and in the
	'winnt.h' in early versions of MinGW. MinGW 3.4.2 has the correct
	definition of SymbolicLinkReparseBuffer, exposing the mismatch, and
	making tests cmdAH-19.4.1, fCmd-28.*, and filename-11.* fail.
	* tests/chanio.test (chan-io-53.9):
	* tests/io.test (io-53.9): Made test cleanup robust against the
	possibility of slow process shutdown on Windows.

	* win/tcl.m4: Added -D_CRT_SECURE_NO_DEPRECATE and
	-DCRT_NONSTDC_NO_DEPRECATE to the MSVC compilation flags so that the
	compilation doesn't barf on perfectly reasonable Posix system calls.
	* win/configure: Manually patched (don't have the right autoconf to
	hand).

2008-04-04  Andreas Kupries  <andreask@activestate.com>

	* tests/io.test (io-53.9): Added testcase for [Bug 780533], based
	* tests/chanio.test: on Alexandre's test script. Also fixed problem
	with timer in preceding test, was not canceled properly in the ok case

2008-04-04  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIORChan.c (ReflectOutput): Allow zero return from write
	when input was zero-length anyway. Otherwise keept it an error, and
	separate the message from 'written too much'.

	* tests/ioCmd.test (iocmd-24.6): Testcase updated for changed message.

	* generic/tclIORChan.c (ReflectClose): Added missing removal of the
	now closed channel from the reflection map. Before we could crash the
	system by invoking 'chan postevent' on a closed reflected channel,
	dereferencing the dangling pointer in the map.

	* tests/ioCmd.test (iocmd-31.8): Testcase for the above.

2008-04-03  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c (CopyData): Applied patch [Bug 1932639] to
	* tests/io.test: prevent fcopy from calling -command synchronously
	* tests/chanio.test: the first time. Thanks to Alexandre Ferrieux
	<ferrieux@users.sourceforge.net> for report and patch.

2008-04-02  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tcl.decls:	Remove 'export' declarations of symbols now
				only in libtclstub and no longer in libtcl.

	* generic/tclStubLib.c:	Make symbols in libtclstub.a MODULE_SCOPE to
	* tools/genStubs.tcl:	avoid exporting them from libraries that link
				with -ltclstub; constify tcl*StubsPtr and stub
				table hook pointers. [Bug 1819422]

	* generic/tclDecls.h:	make genstubs
	* generic/tclIntDecls.h:
	* generic/tclIntPlatDecls.h:
	* generic/tclPlatDecls.h:
	* generic/tclStubInit.c:
	* generic/tclTomMathDecls.h:

2008-04-02  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c (CopyData): Applied patch for fcopy problem [Bug
	780533], with many thanks to Alexandre Ferrieux
	<ferrieux@users.sourceforge.net> for tracking it down and providing a
	solution. Still have to convert his test script into a proper test
	case.

2008-04-01  Andreas Kupries  <andreask@activestate.com>

	* generic/tclStrToD.c: Applied patch for [Bug 1839067] (fp rounding
	* unix/tcl.m4:	       setup on solaris x86, native cc), provided by
			       Michael Schlenker.

2008-04-01  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStubLib.c:	Removed needless #ifdef complexity.

	* generic/tclStubLib.c (Tcl_InitStubs):	Added missing error message.
	* generic/tclPkg.c (Tcl_PkgInitStubsCheck):

	* README:		Bump version number to 8.6a0
	* generic/tcl.h:
	* library/init.tcl:
	* macosx/Tcl-Common.xcconfig:
	* macosx/Tcl.pbproj/default.pbxuser:
	* macosx/Tcl.pbproj/project.pbxproj:
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/README:
	* win/configure.in:
	* win/makefile.bc:
	* win/tcl.m4:

	* unix/configure:	autoconf-2.59
	* win/configure:

	* generic/tclBasic.c:	Revised stubs-generation tool and interp
	* tools/genStubs.tcl:	creation so that "tclStubsPtr" is not present
	* unix/Makefile.in:	in libtcl.so, but is present only in
	* win/Makefile.in:	libtclstub.a. This tightens up the rules for
	* win/makefile.bc:	users of the stubs interfaces. [Bug 1819422]
	* win/makefile.vc:

	* generic/tclDecls.h:	make genstubs
	* generic/tclIntDecls.h:
	* generic/tclIntPlatDecls.h:
	* generic/tclPlatDecls.h:
	* generic/tclTomMathDecls.h:

2008-03-30  Kevin Kenny  <kennykb@acm.org>

	* generic/tclInt.h (TclIsNaN):
	* unix/configure.in: Added code to the configurator to check for a
			     standard isnan() macro and use it if one is
			     found. This change avoids bugs where the test of
			     ((d) != (d)) is optimized away by an
			     overaggressive compiler. [Bug 1783544]
	* generic/tclObj.c: Added missing #include <math.h> needed to locate
			    isnan() after the above change.

	* unix/configure: autoconf-2.61

	* tests/mathop.test (mathop-25.9, mathop-25.14): Modified tests to
	deal with (slightly buggy) math libraries in which pow() returns an
	incorrectly rounded result. [Bug 1808174]

2008-03-26  Don Porter  <dgp@users.sourceforge.net>

	*** 8.5.2 TAGGED FOR RELEASE ***

	* generic/tcl.h:	Bump to 8.5.2 for release.
	* library/init.tcl:
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/configure.in:

	* unix/configure:	autoconf-2.59
	* win/configure:

	* changes:		Updated for 8.5.2 release.

2008-03-28  Donal K. Fellows  <dkf@users.sf.net>

	* tests/fCmd.test: Substantial rewrite to use many more tcltest
	features. Great reduction in quantity of [catch] gymnastics. Several
	buggy tests fixed, including one where the result of the previous test
	was being checked!

2008-03-27  Kevin B. Kenny  <kennykb@acm.org>

	* library/tzdata/America/Marigot:
	* library/tztata/America/St_Barthelemy:
	* library/tzdata/America/Argentina/San_Luis:
	* library/tzdata/Asia/Ho_Chi_Minh:
	* library/tzdata/Asia/Kolkata:	(new files)
	* library/tzdata/America/Caracas:
	* library/tzdata/America/Havana:
	* library/tzdata/America/Santiago:
	* library/tzdata/America/Argentina/Buenos_Aires:
	* library/tzdata/America/Argentina/Catamarca:
	* library/tzdata/America/Argentina/Cordoba:
	* library/tzdata/America/Argentina/Jujuy:
	* library/tzdata/America/Argentina/La_Rioja:
	* library/tzdata/America/Argentina/Mendoza:
	* library/tzdata/America/Argentina/Rio_Gallegos:
	* library/tzdata/America/Argentina/San_Juan:
	* library/tzdata/America/Argentina/Tucuman:
	* library/tzdata/America/Argentina/Ushuaia:
	* library/tzdata/Asia/Baghdad:
	* library/tzdata/Asia/Calcutta:
	* library/tzdata/Asia/Damascus:
	* library/tzdata/Asia/Saigon:
	* library/tzdata/Pacific/Easter:
		Changes up to and including Olson's tzdata2008b.

2008-03-27  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tcl.m4 (SunOS-5.1x): Fix 64bit support for Sun cc. [Bug
	1921166]

	* unix/configure: autoconf-2.59

2008-03-26  Don Porter  <dgp@users.sourceforge.net>

	* changes:		Updated for 8.5.2 release.

2008-03-24  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* generic/tclBinary.c: [Bug 1923966] - crash in binary format
	* tests/binary.test:   Added tests for the above crash condition.

2008-03-21  Donal K. Fellows  <dkf@users.sf.net>

	* doc/switch.n: Clarified documentation in respect of two-argument
	invokation. [Bug 1899962]

	* tests/switch.test: Added more tests of regexp-mode compilation of
	the [switch] command. [Bug 1854435]

2008-03-20  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tcl.h, generic/tclThreadAlloc.c: Tidied up the declarations
	of Tcl_GetMemoryInfo so that it is always defined. Will panic when
	called against a Tcl that was previously built without it at all,
	which is OK because that also indicates a serious mismatch between
	memory configuration options.

2008-03-19  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tcl.h, generic/tclThreadAlloc.c (Tcl_GetMemoryInfo): Make
	sure this function is available when direct linking. [Bug 1868171]

	* tests/reg.test (reg-33.14): Marked nonPortable because some
	environments have small default stack sizes. [Bug 1905562]

2008-03-18  Andreas Kupries  <andreask@activestate.com>

	* library/tm.tcl (::tcl::tm::UnknownHandler): Changed 'source' to
	'source -encoding utf-8'. This fixes a portability problem of Tcl
	Modules pointed out by Don Porter. By using plain 'source' we were at
	the mercy of 'encoding system', making modules less portable than they
	could be. The exact scenario: A writes a TM in some weird encoding
	which is A's system encoding, distributes it, and somewhere else it
	cannot be read/used because the system encoding is different. Forcing
	the use of utf-8 makes the module portable.

	***INCOMPATIBILITY*** for all Tcl Modules already written in non-utf-8
	compatible encodings.

2008-03-18  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclExecute.c:	Patch from Miguel Sofer to correct the
	alignment of memory allocated by GrowEvaluationStack(). [Bug 1914503]

2008-03-18  Andreas Kupries  <andreask@activestate.com>

	* library/tm.tcl (::tcl::tm::Defaults): Modified handling of
	environment variables. Solution slightly different than proposed in
	the report. Using the underscored form TCLX_y_TM_PATH even if
	TCLX.y_TM_PATH exists. Also using a loop to cut prevent code
	replication. [Bug 1914604]

2008-03-16  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileDictForCmd): Correct the handling
	of stack space calculation (the jump pattern used was confusing the
	simple-minded code doing the calculations). [Bug 1903325]

	* doc/lreplace.n: Clarified documentation of what happens with
	negative indices. [Bug 1905809] Added example, tidied up formatting.

2008-03-14  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c (OldMathFuncProc):	Same workaround protection
	from bad TclStackAlloc() alignment. Thanks George Peter Staplin.

	* generic/tclCmdIL.c (Tcl_LsortObjCmd):	Use ckalloc() to allocate
	SortElement arrays instead of TclStackAlloc() which isn't getting
	alignment right. Workaround for [Bug 1914503].

2008-03-14  Reinhard Max  <max@suse.de>

	* generic/tclTest.c:  Ignore the return value of write() when we are
	* unix/tclUnixPipe.c: about to exit anyways.

2008-03-13  Daniel Steffen  <das@users.sourceforge.net>

	* unix/configure.in: Use backslash-quoting instead of double-quoting
	* unix/tcl.m4:	     for lib paths in tclConfig.sh. [Bug 1913622]
	* unix/configure:    autoconf-2.59

2008-03-13  Don Porter  <dgp@users.sourceforge.net>

	* changes:		Updated for 8.5.2 release.

	* generic/tclStrToD.c:	Resolve identifier conflict over "pow10" with
	libm in Cygwin and DJGPP. Thanks to Gordon Schumacher and Philip
	Moore. [Patch 1800636]

2008-03-12  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Tcl.xcodeproj/project.pbxproj:	Add support for Xcode 3.1
	* macosx/Tcl.xcodeproj/default.pbxuser:	CODE_SIGN_IDENTITY and
	* macosx/Tcl-Common.xcconfig:		'xcodebuild install'.

2008-03-12  Andreas Kupries  <andreask@activestate.com>

	* doc/info.n: Replaced {expand} with {*}.

2008-03-12  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/Makefile.in (install-libraries):	Bump http to 2.7
	* win/Makefile.in (install-libraries):	Added -myaddr option to allow
	* library/http/http.tcl (http::geturl):	control of selected socket
	* library/http/pkgIndex.tcl:		interface. [Bug 559898]
	* doc/http.n, tests/http.test:		Added -keepalive and
	-protocol 1.1 with chunked transfer encoding support. [Bug 1063703,
	1470377, 219225] (default keepalive is 0)
	Added ability to override Host in -headers. [Bug 928154]
	Added -strict option to control URL validation on per-call basis.
	[Bug 1560506]

2008-03-11  Jeff Hobbs  <jeffh@ActiveState.com>

	* library/http/http.tcl (http::geturl): Add -method option to support
	* tests/http.test (http-3.1):		http PUT and DELETE requests.
	* doc/http.n:				[Bug 1599901, 862554]

	* library/http/http.tcl: Whitespace changes, code cleanup. Allow http
	to be re-sourced without overwriting http state.

2008-03-11  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclEncoding.c (LoadEscapeEncoding): Avoid leaking escape
	sub-encodings, fixes encoding-11.1 failing after iso2022-jp loaded.
	[Bug 1893053]

	* macosx/tclMacOSXNotify.c: Avoid using CoreFoundation after fork() on
	Darwin 9 even when TclpCreateProcess() uses vfork().

	* macosx/Tcl.xcodeproj/project.pbxproj:	Add support for Xcode 3.1 and
	* macosx/Tcl.xcodeproj/default.pbxuser:	configs for building with
	* macosx/Tcl-Common.xcconfig:		gcc-4.2 and llvm-gcc-4.2.

	* unix/tclUnixPort.h:			Workaround vfork() problems in
						llvm-gcc-4.2.1 -O4 build.

	* unix/tclUnixPort.h:			Move MODULE_SCOPE compat
						define to top. [Bug 1911102]

	* macosx/GNUmakefile:			Fix quoting to allow paths
	* macosx/Tcl-Common.xcconfig:		to ${builddir} and
	* unix/Makefile.in:			${INSTALL_ROOT} to contain
	* unix/configure.in:			spaces.
	* unix/install-sh:
	* unix/tcl.m4:
	* tests/ioCmd.test:

	* unix/configure:			autoconf-2.59

	* unix/Makefile.in (install-strip):	Strip non-global symbols from
						dynamic library.

	* unix/tclUnixNotfy.c:			Fix warning.

	* tests/exec.test (exec-9.7):		Reduce timing sensitivity
	* tests/socket.test (socket-2.11):	(esp. on multi-proc machines).

	* tests/fCmd.test (fCmd-9.4):		Skip on Darwin 9 (xfail).

2008-03-11  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclVar.c (TclDeleteNamespaceVars):
	* tests/var.test (var-8.2): Unset traces on vars should be called with
	a FQ named during namespace deletion. This was causing infinite loops
	when unset traces recreated the var, as reported by Julian Noble. [Bug
	1911919]

2008-03-10  Don Porter  <dgp@users.sourceforge.net>

	* changes:		Updated for 8.5.2 release.

	* doc/http.n:	Revised to indicate that [package require http 2.5.5]
	is needed to get all the documented commands ([http::meta]).

	* generic/tclEvent.c (TclDefaultBgErrorHandlerObjCmd):	Added error
	* tests/event.test (event-5.*):	checking to protect against callers
	passing invalid return options dictionaries. [Bug 1901113]

	* generic/tclBasic.c (ExprAbsFunc):	Revised so that the abs()
	* tests/expr.test:	function and the [::tcl::mathfunc::abs]
	command do not return the value of -0, or equivalent values with more
	alarming string reps like -1e-350. [Bug 1893815]

2008-03-07  Andreas Kupries  <andreask@activestate.com>

	* generic/tclResult.c (ReleaseKeys): Workaround for [Bug 1904907].
	Reset the return option keys to NULL to allow full re-initialization
	by GetKeys(). This introduces a memory leak for the key objects, but
	gets us around a crash in the finalization of reflected channels when
	handling returns, either at compile- or runtime. In both cases we
	access the keys after they have been released by their thread exit
	handler. A proper fix is entangled with the untangling of the
	finalization ordering and attendant issues. For now we choose the
	lesser evil.

2008-03-07  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclExecute.c (Tcl_ExprObj):	Revised expression bytecode
	compiling so that bytecodes invalid due to changing context or due to
	the difference between expressions and scripts are not reused. [Bug
	1899164]

	* generic/tclCmdAH.c:	Revised direct evaluation implementation of
	[expr] so that [expr $e] caches compiled bytecodes for the expression
	as the intrep of $e.

	* tests/execute.test (execute-6.*):	More tests checking that
	script bytecode is invalidated in the right situations.

2008-03-07  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* win/configure.in: Add AC_HEADER_STDC to support msys/win64.

2008-03-06  Donal K. Fellows  <dkf@users.sf.net>

	* doc/namespace.n: Minor tidying up. [Bug 1909019]

2008-03-04  Don Porter  <dgp@users.sourceforge.net>

	* tests/execute.test (6.3,4):	Added tests for [Bug 1899164].

2008-03-03  Reinhard Max  <max@suse.de>

	* unix/tclUnixChan.c: Fix mark and space parity on Linux, which uses
	CMSPAR instead of PAREXT.

2008-03-02  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclNamesp.c (GetNamespaceFromObj):
	* tests/interp.test (interp-28.2): Spoil the intrep of an nsNameType
	obj when the reference crosses interpreter boundaries.

2008-02-29  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclResult.c (Tcl_SetReturnOptions):	Revised the refcount
	management of Tcl_SetReturnOptions to become that of a conventional
	Consumer routine. Thanks to Peter Spjuth for pointing out the
	difficulties calling Tcl_SetReturnOptions with non-0-count value for
	options.
	* generic/tclExecute.c (INST_RETURN_STK): Revised the one caller
	within Tcl itself which passes a non-0-count value to
	Tcl_SetReturnOptions().

	* generic/tclBasic.c (Tcl_AppendObjToErrorInfo):	Revised the
	refcount management of Tcl_AppendObjToErrorInfo to become that of a
	conventional Consumer routine. This preserves the ease of use for the
	overwhelming common callers who pass in a 0-count value, but makes the
	proper call with a non-0-count value less surprising.
	* generic/tclEvent.c (TclDefaultBgErrorHandlerObjCmd):	Revised the
	one caller within Tcl itself which passes a non-0-count value to
	Tcl_AppendObjToErrorInfo().

2008-02-28  Joe English  <jenglish@users.sourceforge.net>

	* unix/tclPort.h, unix/tclCompat.h, unix/tclUnixChan.h: Reduce scope
	of <sys/filio.h> and <sys/ioctl.h> #includes. [Patch 1903339]

2008-02-28  Joe English  <jenglish@users.sourceforge.net>

	* unix/tclUnixChan.c, unix/tclUnixNotfy.c, unix/tclUnixPipe.c:
	Consolidate all code conditionalized on -DUSE_FIONBIO into one place.
	* unix/tclUnixPort.h, unix/tclUnixCompat.c: New routine
	TclUnixSetBlockingMode(). [Patch 1903339]

2008-02-28  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c (TclEvalObjvInternal):	Plug memory leak when
	an enter trace deletes or changes the command, prompting a reparsing.
	Don't let the second pass lose commandPtr value allocated during the
	first pass.

	* generic/tclCompExpr.c (ParseExpr):	Plug memory leak in error
	message generation.

	* generic/tclStringObj.c (Tcl_AppendFormatToObj): [format %llx $big]
	leaked an mp_int.

	* generic/tclCompCmds.c (TclCompileReturnCmd):	The 2007-10-18 commit
	to optimize compiled [return -level 0 $x] [RFE 1794073] introduced a
	memory leak of the return options dictionary. Fixing that.

2008-02-27  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* library/http/http.tcl: [Bug 705956] - fix inverted logic when
	cleaning up socket error in geturl.

2008-02-27  Kevin B. Kenny  <kennykb@acm.org>

	* doc/clock.n: Corrected minor indentation gaffe in the penultimate
	paragraph. [Bug 1898025]
	* generic/tclClock.c (ParseClockFormatArgs): Changed to check that the
	clock value is in the range of a 64-bit integer. [Bug 1862555]
	* library/clock.tcl (::tcl::clock::format, ::tcl::clock::scan,
	(::tcl::clock::add, ::tcl::clock::LocalizeFormat): Fixed bugs in
	caching of localized strings that caused weird results when localized
	date/time formats were used. [Bug 1902423]
	* tests/clock.test (clock-61.*, clock-62.1): Regression tests for [Bug
	1862555] and [Bug 1902423].

2008-02-26  Joe English  <jenglish@users.sourceforge.net>

	* generic/tclIOUtil.c, unix/tclUnixPort.h, unix/tclUnixChan.c:
	Remove dead/unused portability-related #defines and unused conditional
	code. See [Patch 1901828] for discussion.

2008-02-26  Joe English  <jenglish@users.sourceforge.net>

	* generic/tclIORChan.c (enum MethodName),
	* generic/tclCompExpr.c (enum Marks): More stray trailing ","s

2008-02-26  Joe English  <jenglish@users.sourceforge.net>

	* unix/configure.in(socklen_t test): Define socklen_t as "int" if
	missing, not "unsigned". Use AC_TRY_COMPILE instead of
	AC_EGREP_HEADER.
	* unix/configure: regenerated.

2008-02-26  Joe English  <jenglish@users.sourceforge.net>

	* generic/tclCompile.h: Remove stray trailing "," from enum
	InstOperandType definition (C99ism).

2008-02-26  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclUtil.c (TclReToGlob): Fix the handling of the last star
	* tests/regexpComp.test:	   possibly being escaped in
	determining right anchor. [Bug 1902436]

2008-02-26  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* library/http/pkgIndex.tcl: Set version 2.5.5
	* library/http/http.tcl:     It is better to do the [eof] check after
	trying to read from the socket. No clashes found in testing. Added
	http::meta command to access the http headers. [Bug 1868845]

2008-02-22  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* library/http/pkgIndex.tcl: Set version 2.5.4
	* library/http/http.tcl:     Always check that the state array exists
	in the http::status command. [Bug 1818565]

2008-02-13  Don Porter  <dgp@users.sourceforge.net>

	* generic/tcl.h:	Bump version number to 8.5.2b1 to distinguish
	* library/init.tcl:	CVS development snapshots from the 8.5.1 and
	* unix/configure.in:	8.5.2 releases.
	* unix/tcl.spec:
	* win/configure.in:
	* README

	* unix/configure:	autoconf (2.59)
	* win/configure:

2008-02-12  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclCompCmds.c (TclCompileSwitchCmd): Corrected logic for
	* tests/switch.test (switch-10.15): handling -nocase compilation; the
	-exact -nocase option cannot be compiled currently. [Bug 1891827]

	* unix/README: Documented missing configure flags. [Bug 1799011]

2008-02-06  Kevin B. Kenny  <kennykb@acm.org>

	* doc/clock.n (%N): Corrected an error in the explanation of the %N
	format group.
	* generic/tclClock.c (ClockParseformatargsObjCmd):
	* library/clock.tcl (::tcl::clock::format):
	* tests/clock.test (clock-1.0, clock-1.4):
	Performance enhancements in [clock format] (moving the analysis of
	$args into C code, holding on to Tcl_Objs with resolved command names,
	[lassign] in place of [foreach], avoiding [namespace which] for
	command resolution).

2008-02-04  Don Porter  <dgp@users.sourceforge.net>

	*** 8.5.1 TAGGED FOR RELEASE ***

	* changes:		Updated for 8.5.1 release.

	* generic/tcl.h:	Bump to 8.5.1 for release.
	* library/init.tcl:
	* tools/tcl.wse.in:
	* unix/configure.in:
	* unix/tcl.spec:
	* win/configure.in:

	* unix/configure:	autoconf-2.59
	* win/configure:

2008-02-04  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclExecute.c (INST_CONCAT1): Fix optimisation for in-place
	concatenation (was going over String type)

2008-02-02  Daniel Steffen  <das@users.sourceforge.net>

	* unix/configure.in (Darwin):	Correct Info.plist year substitution
					in non-framework builds.

	* unix/configure:		autoconf-2.59

2008-01-30  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclInterp.c (Tcl_GetAlias): Fix for [Bug 1882373], thanks go
	to an00na.

2008-01-30  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* tools/tcltk-man2html.tcl: Reworked manual page scraper to do a
	proper job of handling references to Ttk options. [Tk Bug 1876493]

2008-01-29  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/man.macros (SO, SE): Adjusted macros so that it is possible for
	Ttk to have its "standard options" on a manual page that is not called
	"options". [Tk Bug 1876493]

2008-01-25  Don Porter  <dgp@users.sourceforge.net>

	* changes:		Updated for 8.5.1 release.

2008-01-23  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInt.h:		New macro TclGrowParseTokenArray() to
	* generic/tclCompCmds.c:	simplify code that might need to grow
	* generic/tclCompExpr.c:	an array of Tcl_Tokens in the parsePtr
	* generic/tclParse.c:		field of a Tcl_Parse. Replaces the
	TclExpandTokenArray() routine via replacing:
		int needed = parsePtr->numTokens + growth;
		while (needed > parsePtr->tokensAvailable) {
		    TclExpandTokenArray(parsePtr);
		}
	with:
		TclGrowParseTokenArray(parsePtr, growth);
	This revision merged over from dgp-refactor branch.

	* generic/tclCompile.h:	Demote TclCompEvalObj() from internal stubs to
	* generic/tclInt.decls:	a MODULE_SCOPE routine declared in
	tclCompile.h.

	* generic/tclIntDecls.h:	make genstubs
	* generic/tclStubInit.c:

2008-01-22  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclTimer.c (AfterProc):	Replace Tcl_EvalEx() with
	Tcl_EvalObjEx() to evaluate [after] callbacks. Part of trend to favor
	compiled execution over direct evaluation.

2008-01-22  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCmdIl.c (Tcl_LreverseObjCmd):
	* tests/cmdIL.test (cmdIL-7.7): Fix crash on reversing an empty list.
	[Bug 1876793]

2008-01-20  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/README: Minor typo fixes [Bug 1853072]

	* generic/tclIO.c (TclGetsObjBinary): Operate on topmost channel.
	[Bug 1869405] (Ficicchia)

2008-01-17  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompExpr.c:	Revision to preserve parsed intreps of
	numeric and boolean literals when compiling expressions with (optimize
	== 1).

2008-01-15  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclCompExpr.c: Add an 'optimize' argument to
	* generic/tclCompile.c:	 TclCompileExpr() to profit from better
	* generic/tclCompile.h:	 literal management according to usage.
	* generic/tclExecute.c:

	* generic/tclCompExpr.c: Fix literal leak in exprs [Bug 1869989] (dgp)
	* generic/tclExecute.c:
	* tests/compExpr.test:

	* doc/proc.n: Changed wording for access to non-local variables; added
	mention to [namespace upvar]. Lame attempt at dealing with
	documentation. [Bug 1872708]

2008-01-15  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:	 Replacing 'operator' by 'op' in the def of
	* generic/tclCompExpr.c: struct TclOpCmdClientData to accommodate C++
	* generic/tclCompile.h:	 compilers. [Bug 1855644]

2008-01-13  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/tclWinSerial.c (SerialCloseProc, TclWinOpenSerialChannel): Use
	critical section for read & write side. [Bug 1353846] (newman)

2008-01-11  Miguel Sofer  <msofer@users.sf.net>

	* unix/tclUnixThrd.c (TclpThreadGetStackSize): Restore stack checking
	functionality in freebsd. [Bug 1850424]

	* unix/tclUnixThrd.c (TclpThreadGetStackSize): Fix for crash in
	freebsd. [Bug 1860425]

2008-01-10  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclStringObj.c (Tcl_AppendFormatToObj):  Correct failure to
	* tests/format.test:	account for big.used == 0 corner case in the
	%ll(idox) format directives. [Bug 1867855]

2008-01-09  George Peter Staplin  <georgeps@xmission.com>

	* doc/vwait.n: Add a missing be to fix a typo.

2008-01-04  Jeff Hobbs  <jeffh@ActiveState.com>

	* tools/tcltk-man2html.tcl (make-man-pages): Make man page title use
	more specific info on lhs to improve tabbed browser view titles.

2008-01-02  Donal K. Fellows  <dkf@users.sf.net>

	* doc/binary.n: Fixed documentation bug reported on tcl-core, and
	reordered documentation to discourage people from using the hex
	formatter that is hardly ever useful.

2008-01-02  Don Porter  <dgp@users.sourceforge.net>

	* generic/tcl.h:	Bump version number to 8.5.1b1 to distinguish
	* library/init.tcl:	CVS development snapshots from the 8.5.0 and
	* unix/configure.in:	8.5.1 releases.
	* unix/tcl.spec:
	* win/configure.in:
	* README

	* unix/configure:	autoconf (2.59)
	* win/configure:

	******************************************************************
	*** CHANGELOG ENTRIES FOR 2006-2007 IN "ChangeLog.2007"	       ***
	*** CHANGELOG ENTRIES FOR 2005 IN "ChangeLog.2005"	       ***
	*** CHANGELOG ENTRIES FOR 2004 IN "ChangeLog.2004"	       ***
	*** CHANGELOG ENTRIES FOR 2003 IN "ChangeLog.2003"	       ***
	*** CHANGELOG ENTRIES FOR 2002 IN "ChangeLog.2002"	       ***
	*** CHANGELOG ENTRIES FOR 2001 IN "ChangeLog.2001"	       ***
	*** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000"	       ***
	*** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" ***
	******************************************************************

Changes to README.md.

1
2
3

4
5
6
7

8








9
10
11
12
13
14
15
1
2

3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23


-
+




+
-
+
+
+
+
+
+
+
+







# README:  Tcl

This is the **Tcl 9.0a2** source distribution.
This is the **Tcl 9.0.1** source distribution.

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

9.0 (production release, daily build)
[![Build Status](https://travis-ci.org/tcltk/tcl.svg?branch=master)](https://travis-ci.org/tcltk/tcl)
[![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)
[![Build Status](https://github.com/tcltk/tcl/actions/workflows/mac-build.yml/badge.svg?branch=main)](https://github.com/tcltk/tcl/actions/workflows/mac-build.yml?query=branch%3Amain)
<br>
8.7 (in development, daily build)
[![Build Status](https://github.com/tcltk/tcl/actions/workflows/linux-build.yml/badge.svg?branch=core-8-branch)](https://github.com/tcltk/tcl/actions/workflows/linux-build.yml?query=branch%3Acore-8-branch)
[![Build Status](https://github.com/tcltk/tcl/actions/workflows/win-build.yml/badge.svg?branch=core-8-branch)](https://github.com/tcltk/tcl/actions/workflows/win-build.yml?query=branch%3Acore-8-branch)
[![Build Status](https://github.com/tcltk/tcl/actions/workflows/mac-build.yml/badge.svg?branch=core-8-branch)](https://github.com/tcltk/tcl/actions/workflows/mac-build.yml?query=branch%3Acore-8-branch)

## Contents
 1. [Introduction](#intro)
 2. [Documentation](#doc)
 3. [Compiling and installing Tcl](#build)
 4. [Development tools](#devtools)
 5. [Tcl newsgroup](#complangtcl)
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
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







-
+





-
+





-
+

-
+







When paired with the Tk toolkit, Tcl provides the fastest and most powerful
way to create GUI applications that run on PCs, Unix, and Mac OS X.
Tcl can also be used for a variety of web-related tasks and for creating
powerful command languages for applications.

Tcl is maintained, enhanced, and distributed freely by the Tcl community.
Source code development and tracking of bug reports and feature requests
takes place at [core.tcl-lang.org](https://core.tcl-lang.org/).
take place at [core.tcl-lang.org](https://core.tcl-lang.org/).
Tcl/Tk release and mailing list services are [hosted by
SourceForge](https://sourceforge.net/projects/tcl/)
with the Tcl Developer Xchange hosted at
[www.tcl-lang.org](https://www.tcl-lang.org).

Tcl is a freely available open source package.  You can do virtually
Tcl is a freely available open-source package.  You can do virtually
anything you like with it, such as modifying it, redistributing it,
and selling it either in whole or in part.  See the file
`license.terms` for complete information.

## <a id="doc">2.</a> Documentation
Extensive documentation is available at our website.
Extensive documentation is available on our website.
The home page for this release, including new features, is
[here](https://www.tcl.tk/software/tcltk/9.0.html).
[here](https://www.tcl-lang.org/software/tcltk/9.0.html).
Detailed release notes can be found at the
[file distributions page](https://sourceforge.net/projects/tcl/files/Tcl/)
by clicking on the relevant version.

Information about Tcl itself can be found at the [Developer
Xchange](https://www.tcl-lang.org/about/).
There have been many Tcl books on the market.  Many are mentioned in
84
85
86
87
88
89
90
91

92
93
94

95
96
97

98
99
100

101
102
103
104
105
106
107
92
93
94
95
96
97
98

99
100
101

102
103
104

105
106
107

108
109
110
111
112
113
114
115







-
+


-
+


-
+


-
+







## <a id="build">3.</a> Compiling and installing Tcl
There are brief notes in the `unix/README`, `win/README`, and `macosx/README`
about compiling on these different platforms.  There is additional information
about building Tcl from sources
[online](https://www.tcl-lang.org/doc/howto/compile.html).

## <a id="devtools">4.</a> Development tools
ActiveState produces a high quality set of commercial quality development
ActiveState produces a high-quality set of commercial quality development
tools that is available to accelerate your Tcl application development.
Tcl Dev Kit builds on the earlier TclPro toolset and provides a debugger,
static code checker, single-file wrapping utility, bytecode compiler and
static code checker, single-file wrapping utility, bytecode compiler, and
more.  More information can be found at

	http://www.ActiveState.com/Tcl
	https://www.activestate.com/products/tcl/

## <a id="complangtcl">5.</a> Tcl newsgroup
There is a USENET news group, "`comp.lang.tcl`", intended for the exchange of
There is a USENET newsgroup, "`comp.lang.tcl`", intended for the exchange of
information about Tcl, Tk, and related applications.  The newsgroup is a
great place to ask general information questions.  For bug reports, please
see the "Support and bug fixes" section below.

## <a id="wiki">6.</a> Tcl'ers Wiki
There is a [wiki-based open community site](https://wiki.tcl-lang.org/)
covering all aspects of Tcl/Tk.

Deleted changes.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
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
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
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
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
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
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
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
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
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
7079
7080
7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091
7092
7093
7094
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468
7469
7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499
7500
7501
7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520
7521
7522
7523
7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537
7538
7539
7540
7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647
7648
7649
7650
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692
7693
7694
7695
7696
7697
7698
7699
7700
7701
7702
7703
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952
7953
7954
7955
7956
7957
7958
7959
7960
7961
7962
7963
7964
7965
7966
7967
7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999
8000
8001
8002
8003
8004
8005
8006
8007
8008
8009
8010
8011
8012
8013
8014
8015
8016
8017
8018
8019
8020
8021
8022
8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047
8048
8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
8077
8078
8079
8080
8081
8082
8083
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
8148
8149
8150
8151
8152
8153
8154
8155
8156
8157
8158
8159
8160
8161
8162
8163
8164
8165
8166
8167
8168
8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
8193
8194
8195
8196
8197
8198
8199
8200
8201
8202
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
8233
8234
8235
8236
8237
8238
8239
8240
8241
8242
8243
8244
8245
8246
8247
8248
8249
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260
8261
8262
8263
8264
8265
8266
8267
8268
8269
8270
8271
8272
8273
8274
8275
8276
8277
8278
8279
8280
8281
8282
8283
8284
8285
8286
8287
8288
8289
8290
8291
8292
8293
8294
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316
8317
8318
8319
8320
8321
8322
8323
8324
8325
8326
8327
8328
8329
8330
8331
8332
8333
8334
8335
8336
8337
8338
8339
8340
8341
8342
8343
8344
8345
8346
8347
8348
8349
8350
8351
8352
8353
8354
8355
8356
8357
8358
8359
8360
8361
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371
8372
8373
8374
8375
8376
8377
8378
8379
8380
8381
8382
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414
8415
8416
8417
8418
8419
8420
8421
8422
8423
8424
8425
8426
8427
8428
8429
8430
8431
8432
8433
8434
8435
8436
8437
8438
8439
8440
8441
8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452
8453
8454
8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487
8488
8489
8490
8491
8492
8493
8494
8495
8496
8497
8498
8499
8500
8501
8502
8503
8504
8505
8506
8507
8508
8509
8510
8511
8512
8513
8514
8515
8516
8517
8518
8519
8520
8521
8522
8523
8524
8525
8526
8527
8528
8529
8530
8531
8532
8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544
8545
8546
8547
8548
8549
8550
8551
8552
8553
8554
8555
8556
8557
8558
8559
8560
8561
8562
8563
8564
8565
8566
8567
8568
8569
8570
8571
8572
8573
8574
8575
8576
8577
8578
8579
8580
8581
8582
8583
8584
8585
8586
8587
8588
8589
8590
8591
8592
8593
8594
8595
8596
8597
8598
8599
8600
8601
8602
8603
8604
8605
8606
8607
8608
8609
8610
8611
8612
8613
8614
8615
8616
8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628
8629
8630
8631
8632
8633
8634
8635
8636
8637
8638
8639
8640
8641
8642
8643
8644
8645
8646
8647
8648
8649
8650
8651
8652
8653
8654
8655
8656
8657
8658
8659
8660
8661
8662
8663
8664
8665
8666
8667
8668
8669
8670
8671
8672
8673
8674
8675
8676
8677
8678
8679
8680
8681
8682
8683
8684
8685
8686
8687
8688
8689
8690
8691
8692
8693
8694
8695
8696
8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707
8708
8709
8710
8711
8712
8713
8714
8715
8716
8717
8718
8719
8720
8721
8722
8723
8724
8725
8726
8727
8728
8729
8730
8731
8732
8733
8734
8735
8736
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746
8747
8748
8749
8750
8751
8752
8753
8754
8755
8756
8757
8758
8759
8760
8761
8762
8763
8764
8765
8766
8767
8768
8769
8770
8771
8772
8773
8774
8775
8776
8777
8778
8779
8780
8781
8782
8783
8784
8785
8786
8787
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
8798
8799
8800
8801
8802
8803
8804
8805
8806
8807
8808
8809
8810
8811
8812
8813
8814
8815
8816
8817
8818
8819
8820
8821
8822
8823
8824
8825
8826
8827
8828
8829
8830
8831
8832
8833
8834
8835
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847
8848
8849
8850
8851
8852
8853
8854
8855
8856
8857
8858
8859
8860
8861
8862
8863
8864
8865
8866
8867
8868
8869
8870
8871
8872
8873
8874
8875
8876
8877
8878
8879
8880
8881
8882
8883
8884
8885
8886
8887
8888
8889
8890
8891
8892
8893
8894
8895
8896
8897
8898
8899
8900
8901
8902
8903
8904
8905
8906
8907
8908
8909
8910
8911
8912
8913
8914
8915
8916
8917
8918
8919
8920
8921
8922
8923
8924
8925
8926
8927
8928
8929
8930
8931
8932
8933
8934
8935
8936
8937
8938
8939
8940
8941
8942
8943
8944
8945
8946
8947
8948
8949
8950
8951
8952
8953
8954
8955
8956
8957
8958
8959
8960
8961
8962
8963
8964
8965
8966
8967
8968
8969
8970
8971
8972
8973
8974
8975
8976
8977
8978
8979
8980
8981
8982
8983
8984
8985
8986
8987
8988
8989
8990
8991
8992
8993
8994
8995
8996
8997
8998
8999
9000
9001
9002
9003
9004
9005
9006
9007
9008
9009
9010
9011
9012
9013
9014
9015
9016
9017
9018
9019
9020
9021
9022
9023
9024
9025
9026
9027
9028
9029
9030
9031
9032
9033
9034
9035
9036
9037
9038
9039
9040
9041
9042
9043
9044
9045
9046
9047
9048
9049
9050
9051
9052
9053
9054
9055
9056
9057
9058
9059
9060
9061
9062
9063
9064
9065
9066
9067
9068
9069
9070
9071
9072
9073
9074
9075
9076
9077
9078
9079
9080
9081
9082
9083
9084
9085
9086
9087
9088
9089
9090
9091
9092
9093
9094
9095
9096
9097
9098
9099
9100
9101
9102
9103
9104
9105
9106
9107
9108
9109
9110
9111
9112
9113
9114
9115
9116
9117
9118
9119
9120
9121
9122
9123
9124
9125
9126
9127
9128
9129
9130
9131
9132
9133
9134
9135
9136
9137
9138
9139
9140
9141
9142






















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Recent user-visible changes to Tcl:

1. No more [command1] [command2] construct for grouping multiple
commands on a single command line.

2. Semi-colon now available for grouping commands on a line.

3. For a command to span multiple lines, must now use backslash-return
at the end of each line but the last.

4. "Var" command has been changed to "set".

5. Double-quotes now available as an argument grouping character.

6. "Return" may be used at top-level.

7. More backslash sequences available now.  In particular, backslash-newline
may be used to join lines in command files.

8. New or modified built-in commands:  case, return, for, glob, info,
print, return, set, source, string, uplevel.

9. After an error, the variable "errorInfo" is filled with a stack
trace showing what was being executed when the error occurred.

10. Command abbreviations are accepted when parsing commands, but
are not recommended except for purely-interactive commands.

11. $, set, and expr all complain now if a non-existent variable is
referenced.

12. History facilities exist now.  See Tcl.man and Tcl_RecordAndEval.man.

13. Changed to distinguish between empty variables and those that don't
exist at all.  Interfaces to Tcl_GetVar and Tcl_ParseVar have changed
(NULL return value is now possible).  *** POTENTIAL INCOMPATIBILITY ***

14. Changed meaning of "level" argument to "uplevel" command (1 now means
"go up one level", not "go to level 1"; "#1" means "go to level 1").
*** POTENTIAL INCOMPATIBILITY ***

15. 3/19/90 Added "info exists" option to see if variable exists.

16. 3/19/90 Added "noAbbrev" variable to prohibit command abbreviations.

17. 3/19/90 Added extra errorInfo option to "error" command.

18. 3/21/90 Double-quotes now only affect space:  command, variable,
and backslash substitutions still occur inside double-quotes.
*** POTENTIAL INCOMPATIBILITY ***

19. 3/21/90 Added support for \r.

20. 3/21/90 List, concat, eval, and glob commands all expect at least
one argument now.  *** POTENTIAL INCOMPATIBILITY ***

21. 3/22/90 Added "?:" operators to expressions.

22. 3/25/90 Fixed bug in Tcl_Result that caused memory to get trashed.

------------------- Released version 3.1 ---------------------

23. 3/29/90 Fixed bug that caused "file a.b/c ext" to return ".b/c".

24. 3/29/90 Semi-colon is not treated specially when enclosed in
double-quotes.

------------------- Released version 3.2 ---------------------

25. 4/16/90 Rewrote "exec" not to use select or signals anymore.
Should be more Sys-V compatible, and no slower in the normal case.

26. 4/18/90 Rewrote "glob" to eliminate GNU code (there's no GNU code
left in Tcl, now), and added Tcl_TildeSubst procedure.  Added automatic
tilde-substitution in many commands, including "glob".

------------------- Released version 3.3 ---------------------

27. 7/11/90 Added "Tcl_AppendResult" procedure.

28. 7/20/90 "History" with no options now defaults to "history info"
rather than to "history redo".  Although this is a backward incompatibility,
it should only be used interactively and thus shouldn't present any
compatibility problems with scripts.

29. 7/20/90 Added "Tcl_GetInteger", "Tcl_GetDouble", and "Tcl_GetBoolean"
procedures.

30. 7/22/90 Removed "Tcl_WatchInterp" procedure:  doesn't seem to be
necessary, since the same effect can be achieved with the deletion
callbacks on individual commands.  *** POTENTIAL INCOMPATIBILITY ***

31. 7/23/90 Added variable tracing:  Tcl_TraceVar, Tcl_UnTraceVar,
and Tcl_VarTraceInfo procedures, "trace" command.

32. 8/9/90 Mailed out list of all bug fixes since 3.3 release.

33. 8/29/90 Fixed bugs in Tcl_Merge relating to backslashes and
semi-colons.  Mailed out patch.

34. 9/3/90 Fixed bug in tclBasic.c: quotes weren't quoting ]'s.
Mailed out patch.

35. 9/19/90 Rewrote exec to always use files both for input and
output to the process.  The old pipe-based version didn't work if
the exec'ed process forked a child and then exited:  Tcl waited
around for stdout to get closed, which didn't happen until the
grandchild exited.

36. 11/5/90 ERR_IN_PROGRESS flag wasn't being cleared soon enough
in Tcl_Eval, allowing error messages from different commands to
pile up in $errorInfo.  Fixed by re-arranging code in Tcl_Eval that
re-initializes result and ERR_IN_PROGRESS flag.  Didn't mail out
patch:  changes too complicated to describe.

37. 12/19/90 Added Tcl_VarEval procedure as a convenience for
assembling and executing Tcl commands.

38. 1/29/91 Fixed core leak in Tcl_AddErrorInfo.  Also changed procedure
and Tcl_Eval so that first call to Tcl_AddErrorInfo need not come from
Tcl_Eval.

----------------- Released version 5.0 with Tk ------------------

39. 4/3/91 Removed change bars from manual entries, leaving only those
that came after version 3.3 was released.

40. 5/17/91 Changed tests to conform to Mary Ann May-Pumphrey's approach.

41. 5/23/91 Massive revision to Tcl parser to simplify the implementation
of string and floating-point support in expressions.  Newlines inside
[] are now treated as command separators rather than word separators
(this makes newline treatment consistent throughout Tcl).
*** POTENTIAL INCOMPATIBILITY ***

42. 5/23/91 Massive rewrite of expression code to support floating-point
values and simple string comparisons.  The C interfaces to expression
routines have changed (Tcl_Expr is replaced by Tcl_ExprLong, Tcl_ExprDouble,
etc.), but all old Tcl expression strings should be accepted by the new
expression code.
*** POTENTIAL INCOMPATIBILITY ***

43. 5/23/91 Modified tclHistory.c to check for negative "keep" value.

44. 5/23/91 Modified Tcl_Backslash to handle backslash-newline.  It now
returns 0 to indicate that a backslash sequence should be replaced by
no character at all.
*** POTENTIAL INCOMPATIBILITY ***

45. 5/29/91 Modified to use ANSI C function prototypes.  Must set
"USE_ANSI" switch when compiling to get prototypes.

46. 5/29/91 Completed test suite by providing tests for all of the
built-in Tcl commands.

47. 5/29/91 Changed Tcl_Concat to eliminate leading and trailing
white-space in each of the things it concatenates and to ignore
elements that are empty or have only white space in them.  This
produces cleaner output from the "concat" command.
*** POTENTIAL INCOMPATIBILITY ***

48. 5/31/91 Changed "set" command and Tcl_SetVar procedure to return
new value of variable.

49. 6/1/91 Added "while" and "cd" commands.

50. 6/1/91 Changed "exec" to delete the last character of program
output if it is a newline.  In most cases this makes it easier to
process program-generated output.
*** POTENTIAL INCOMPATIBILITY ***

51. 6/1/91 Made sure that pointers are never used after freeing them.

52. 6/1/91 Fixed bug in TclWordEnd where it wasn't dealing with
[] inside quotes correctly.

53. 6/8/91 Fixed exec.test to accept return values of either 1 or
255 from "false" command.

54. 7/6/91 Massive overhaul of variable management.  Associative
arrays now available, along with "unset" command (and Tcl_UnsetVar
procedure).  Variable traces have been completely reworked:
interfaces different both from Tcl and C, and multiple traces may
exist on same variable.  Can no longer redefine existing local
variable to be global.  Calling sequences have changed slightly
for Tcl_GetVar and Tcl_SetVar ("global" is now "flags"). Tcl_SetVar
can fail and return a NULL result.  New forms of variable-manipulation
procedures:  Tcl_GetVar2, Tcl_SetVar2, etc.  Syntax of variable
$-notation changed to support array indexing.
*** POTENTIAL INCOMPATIBILITY ***

55. 7/6/91 Added new list-manipulation procedures:  Tcl_ScanElement,
Tcl_ConvertElement, Tcl_AppendElement.

56. 7/12/91 Created new procedure Tcl_EvalFile, which does most of the
work of the "source" command.

57. 7/20/91 Major reworking of "exec" command to allow pipelines,
more redirection, background.  Added new procedures Tcl_Fork,
Tcl_WaitPids, Tcl_DetachPids, and Tcl_CreatePipeline.  The old
"< input" notation has been replaced by "<< input" ("<" is for
redirection from a file).  Also handles error returns and abnormal
terminations (e.g. signals) differently.
*** POTENTIAL INCOMPATIBILITY ***

58. 7/21/91 Added "append" and "lappend" commands.

59. 7/22/91 Reworked error messages and manual entries to use
?x? as the notation for an optional argument x, instead of [x].  The
bracket notation was often confused with the use of brackets for
command substitution.  Also modified error messages to be more
consistent.

60. 7/23/91 Tcl_DeleteCommand now returns an indication of whether
or not the command actually existed, and the "rename" command uses
this information to return an error if an attempt is made to delete
a non-existent command.
*** POTENTIAL INCOMPATIBILITY ***

61. 7/25/91 Added new "errorCode" mechanism, along with procedures
Tcl_SetErrorCode, Tcl_UnixError, and Tcl_ResetResult.  Renamed
Tcl_Return to Tcl_SetResult, but left a #define for Tcl_Return to
avoid compatibility problems.

62. 7/26/91 Extended "case" command with alternate syntax where all
patterns and commands are together in a single list argument:  makes
it easier to write multi-line case statements.

63. 7/27/91 Changed "print" command to perform tilde-substitution on
the file name.

64. 7/27/91 Added "tolower", "toupper", "trim", "trimleft", and "trimright"
options to "string" command.

65. 7/29/91 Added "atime", "mtime", "size", and "stat" options to "file"
command.

66. 8/1/91 Added "split" and "join" commands.

67. 8/11/91 Added commands for file I/O, including "open", "close",
"read", "gets", "puts", "flush", "eof", "seek", and "tell".

68. 8/14/91 Switched to use a hash table for command lookups.  Command
abbreviations no longer have direct support in the Tcl interpreter, but
it should be possible to simulate them with the auto-load features
described below.  The "noAbbrev" variable is no longer used by Tcl.
*** POTENTIAL INCOMPATIBILITY ***

68.5 8/15/91 Added support for "unknown" command, which can be used to
complete abbreviations, auto-load library files, auto-exec shell
commands, etc.

69. 8/15/91 Added -nocomplain switch to "glob" command.

70. 8/20/91 Added "info library" option and TCL_LIBRARY #define.  Also
added "info script" option.

71. 8/20/91 Changed "file" command to take "option" argument as first
argument (before file name), for consistency with other Tcl commands.
*** POTENTIAL INCOMPATIBILITY ***

72. 8/20/91 Changed format of information in $errorInfo variable:
comments such as
    ("while" body line 1)
are now on separate lines from commands being executed.
*** POTENTIAL INCOMPATIBILITY ***

73. 8/20/91 Changed Tcl_AppendResult so that it (eventually) frees
large buffers that it allocates.

74. 8/21/91 Added "linsert", "lreplace", "lsearch", and "lsort"
commands.

75. 8/28/91 Added "incr" and "exit" commands.

76. 8/30/91 Added "regexp" and "regsub" commands.

77. 9/4/91 Changed "dynamic" field in interpreters to "freeProc" (procedure
address).  This allows for alternative storage managers.
*** POTENTIAL INCOMPATIBILITY ***

78. 9/6/91 Added "index", "length", and "range" options to "string"
command.  Added "lindex", "llength", and "lrange" commands.

79. 9/8/91 Removed "index", "length", "print" and "range" commands.
"Print" is redundant with "puts", but less general, and the other
commands are replaced with the new commands described in change 78
above.
*** POTENTIAL INCOMPATIBILITY ***

80. 9/8/91 Changed history revision to occur even when history command
is nested;  needed in order to allow "history" to be invoked from
"unknown" procedure.

81. 9/13/91 Changed "panic" not to use vfprintf (it's uglier and less
general now, but makes it easier to run Tcl on systems that don't
have vfprintf).  Also changed "strerror" not to redeclare sys_errlist.

82. 9/19/91 Lots of changes to improve portability to different UNIX
systems, including addition of "config" script to adapt Tcl to the
configuration of the system it's being compiled on.

83. 9/22/91 Added "pwd" command.

84. 9/22/91 Renamed manual pages so that their filenames are no more
than 14 characters in length, moved to "doc" subdirectory.

85. 9/24/91 Redid manual entries so they contain the supplemental
macros that they need;  can just print with "troff -man" or "man"
now.

86. 9/26/91 Created initial version of script library, including
a version of "unknown" that does auto-loading, auto-execution, and
abbreviation expansion.  This library is used by tclTest
automatically.  See the "library" manual entry for details.

----------------- Released version 6.0, 9/26/91 ------------------

87. 9/30/91 Made "string tolower" and "string toupper" check case
before converting:  on some systems, "tolower" and "toupper" assume
that character already has particular case.

88. 9/30/91 Fixed bug in Tcl_SetResult:  wasn't always setting freeProc
correctly when called with NULL value.  This tended to cause memory
allocation errors later.

89. 10/3/91 Added "upvar" command.

90. 10/4/91 Changed "format" so that internally it converts %D to %ld,
%U to %lu, %O to %lo, and %F to %f.  This eliminates some compatibility
problems on some machines without affecting behavior.

91. 10/10/91 Fixed bug in "regsub" that caused core dumps with the -all
option when the last match wasn't at the end of the string.

92. 10/17/91 Fixed problems with backslash sequences:  \r support was
incomplete and \f and \v weren't supported at all.

93. 10/24/91 Added Tcl_InitHistory procedure.

94. 10/24/91 Changed "regexp" to store "-1 -1" in subMatchVars that
don't match, rather than returning an error.

95. 10/27/91 Modified "regexp" to return actual strings in matchVar
and subMatchVars instead of indices.  Added "-indices" switch to cause
indices to be returned.
*** POTENTIAL INCOMPATIBILITY ***

96. 10/27/91 Fixed bug in "scan" where it used hardwired constants for
sizes of floats and doubles instead of using "sizeof".

97. 10/31/91 Fixed bug in tclParse.c where parse-related error messages
weren't being storage-managed correctly, causing spurious free's.

98. 10/31/91 Form feed and vertical tab characters are now considered
to be space characters by the parser.

99. 10/31/91 Added TCL_LEAVE_ERR_MSG flag to procedures like Tcl_SetVar.

100. 11/7/91 Fixed bug in "case" where "in" argument couldn't be omitted
if all case branches were embedded in a single list.

101. 11/7/91 Switched to use "pid_t" and "uid_t" and other official
POSIC types and function prototypes.

----------------- Released version 6.1, 11/7/91 ------------------

102. 12/2/91 Modified Tcl_ScanElement and Tcl_ConvertElement in several
ways.  First, allowed caller to request that only backslashes be used
(no braces).  Second, made Tcl_ConvertElement more aggressive in using
backslashes for braces and quotes.

103. 12/5/91 Added "type", "lstat", and "readlink" options to "file"
command, plus added new "type" element to output of "stat" and "lstat"
options.

104. 12/10/91 Manual entries had first lines that caused "man" program
to try weird preprocessor.  Added blank comment lines to fix problem.

105. 12/16/91 Fixed a few bugs in auto_mkindex proc:  wasn't handling
errors properly, and hadn't been upgraded for new "regexp" syntax.

106. 1/2/92 Fixed bug in "file" command where it didn't properly handle
a file names containing tildes where the indicated user doesn't exist.

107. 1/2/92 Fixed lots of cases in tclUnixStr.c where two different
errno symbols (e.g. EWOULDBLOCK and EAGAIN) have the same number;  Tcl
will only use one of them.

108. 1/2/92 Lots of changes to configuration script to handle many more
systems more gracefully.  E.g. should now detect the bogus strtoul that
comes with AIX and substitute Tcl's own version instead.

----------------- Released version 6.2, 1/10/92 ------------------

109. 1/20/92 Config didn't have code to actually use "uid_t" variable
to set TCL_UIT_T #define.

110. 2/10/92 Tcl_Eval didn't properly reset "numLevels" variable when
too-deep recursion occurred.

111. 2/29/92 Added "on" and "off" to keywords accepted by Tcl_GetBoolean.

112. 3/19/92 Config wasn't installing default version of strtod.c for
systems that don't have one in libc.a.

113. 3/23/92 Fixed bug in tclExpr.c where numbers with leading "."s,
like 0.75, couldn't be properly substituted into expressions with
variable or command substitution.

114. 3/25/92 Fixed bug in tclUnixAZ.c where "gets" command wasn't
checking to make sure that it was able to write the variable OK.

115. 4/16/92 Fixed bug in tclUnixAZ.c where "read" command didn't
compute file size right for device files.

116. 4/23/92 Fixed but in tclCmdMZ.c where "trace vinfo" was overwriting
the trace command.

----------------- Released version 6.3, 5/1/92 ------------------

117. 5/1/92 Added Tcl_GlobalEval.

118. 6/1/92 Changed auto-load facility to source files at global level.

119. 6/8/92 Tcl_ParseVar wasn't always setting termPtr after errors, which
sometimes caused core dumps.

120. 6/21/92 Fixed bug in initialization of regexp pattern cache.  This
bug caused segmentation violations in regexp commands under some conditions.

121. 6/22/92 Changed implementation of "glob" command to eliminate
trailing slashes on directory names:  they confuse some systems.  There
shouldn't be any user-visible changes in functionality except for names
in error messages not having trailing slashes.

122. 7/2/92 Fixed bug that caused 'string match ** ""' to return 0.

123. 7/2/92 Fixed bug in Tcl_CreateCmdBuf where it wasn't initializing
the buffer to an empty string.

124. 7/6/92 Fixed bug in "case" command where it used NULL pattern string
after errors in the "default" clause.

125. 7/25/92 Speeded up auto_load procedure:  don't reread all the index
files unless the path has changed.

126. 8/3/92 Changed tclUnix.h to define MAXPATHLEN from PATH_MAX, not
_POSIX_PATH_MAX.

----------------- Released version 6.4, 8/7/92 ------------------

127. 8/10/92 Changed tclBasic.c so that comment lines can be continued by
putting a backslash before the newline.

128. 8/21/92 Modified "unknown" to allow the source-ing of a file for
an auto-load to trigger other nested auto-loads, as long as there isn't
any recursion on the same command name.

129. 8/25/92 Modified "format" command to allow " " and "+" flags, and
allow flags in any order.

130. 9/14/92 Modified Tcl_ParseVar so that it doesn't actually attempt
to look up the variable if "noEval" mode is in effect in the interpreter
(it just parses the name).  This avoids the errors that used to occur
in statements like "expr {[info exists foo] && $foo}".

131. 9/14/92 Fixed bug in "uplevel" command where it didn't output the
correct error message if a level was specified but no command.

132. 9/14/92 Renamed manual entries to have extensions like .3 and .n,
and added "install" target to Makefile.

133. 9/18/92 Modified "unknown" command to emulate !!, !<num>, and
^<old>^<new> csh history substitutions.

134. 9/21/92 Made the config script cleverer about figuring out which
switches to pass to "nm".

135. 9/23/92 Fixed tclVar.c to be sure to copy flags when growing variables.
Used to forget about traces in progress and make extra recursive calls
on trace procs.

136. 9/28/92 Fixed bug in auto_reset where it was unsetting variables
that might not exist.

137. 10/7/92 Changed "parray" library procedure to print any array
accessible to caller, local or global.

138. 10/15/92 Fixed bug where propagation of new environment variable
values among interpreters took N! time if there exist N interpreters.

139. 10/16/92 Changed auto_reset procedure so that it also deletes any
existing procedures that are in the auto_load index (the assumption is
that they should be re-loaded to get the latest versions).

140. 10/21/92 Fixed bug that caused lists to be incorrectly generated
for elements that contained backslash-newline sequences.

141. 12/9/92 Added support for TCL_LIBRARY environment variable:  use
it as library location if it's present.

142. 12/9/92 Added "info complete" command, Tcl_CommandComplete procedure.

143. 12/16/92 Changed the Makefile to check to make sure "config" has been
run (can't run config directly from the Makefile because it modifies the
Makefile;  thus make has to be run again after running config).

----------------- Released version 6.5, 12/17/92 ------------------

144. 12/21/92 Changed config to look in several places for libc file.

145. 12/23/92 Added "elseif" support to if.  Also, "then", "else", and
"elseif" may no longer be abbreviated.
*** POTENTIAL INCOMPATIBILITY ***

146. 12/28/92 Changed "puts" and "read" to support initial "-nonewline"
switch instead of additional "nonewline" argument.  The old form is
still supported, but it is discouraged and is no longer documented.
Also changed "puts" to make the file argument default to stdout: e.g.
"puts foo" will print foo on standard output.

147. 1/6/93 Fixed bug whereby backslash-newline wasn't working when
typed interactively, or in "info complete".

148. 1/22/93 Fixed bugs in "lreplace" and "linsert" where close
quotes were being lost from last element before replacement or
insertion.

149. 1/29/93 Fixed bug in Tcl_AssembleCmd where it wasn't requiring
a newline at the end of a line before considering a command to be
complete.  The bug caused some very long lines in script files to
be processed as multiple separate commands.

150. 1/29/93 Various changes in Makefile to add more configuration
options, simplify installation, fix bugs (e.g. don't use -f switch
for cp), etc.

151. 1/29/93 Changed "name1" and "name2" identifiers to "part1" and
"part2" to avoid name conflicts with stupid C++ implementations that
use "name1" and "name2" in a reserved way.

152. 2/1/93 Added "putenv" procedure to replace the standard system
version so that it will work correctly with Tcl's environment handling.

----------------- Released version 6.6, 2/5/93 ------------------

153. 2/10/93 Fixed bugs in config script:  missing "endif" in libc loop,
and tried to use strncasecmp.c instead of strcasecmp.c.

154. 2/10/93 Makefile improvements:  added RANLIB variable for easier
Sys-V configuration, added SHELL variable for SGI systems.

----------------- Released version 6.7, 2/11/93 ------------------

153. 2/6/93 Changes in backslash processing:
    - \Cx, \Mx, \CMx, \e sequences no longer special
    - \<newline> also eats up any space after the newline, replacing
      the whole sequence with a single space character
    - Hex sequences like \x24 are now supported, along with ANSI C's \a.
    - "format" no longer does backslash processing on its format string
    - there is no longer any special meaning to a 0 return value from
      Tcl_Backslash
    - unknown backslash sequences, like (e.g. \*), are replaced with
      the following character (e.g. *), instead of just treating the
      backslash as an ordinary character.
*** POTENTIAL INCOMPATIBILITY ***

154. 2/6/93 Updated all copyright notices.  The meaning hasn't changed
at all but the wording does a better job of protecting U.C. from
liability (according to U.C. lawyers, anyway).

155. 2/6/93 Changed "regsub" so that it overwrites the result variable
in all cases, even if there is no match.
*** POTENTIAL INCOMPATIBILITY ***

156. 2/8/93 Added support for XPG3 %n$ conversion specifiers to "format"
command.

157. 2/17/93 Fixed bug in Tcl_Eval where errors due to infinite
recursion could result in core dumps.

158. 2/17/93 Improved the auto-load mechanism to deal gracefully (i.e.
return an error) with a situation where a library file that supposedly
defines a procedure doesn't actually define it.

159. 2/17/93 Renamed Tcl_UnixError procedure to Tcl_PosixError, and
changed errorCode variable usage to use POSIX as keyword instead of
UNIX.
*** POTENTIAL INCOMPATIBILITY ***

160. 2/19/93 Changes to exec and process control:
    - Added support for >>, >&, >>&, |&, <@, >@, and >&@ forms of redirection.
    - When exec puts processes into background, it returns a list of
      their pids as result.
    - Added support for <file, >file, etc. (i.e. no space between
      ">" and file name.
    - Added -keepnewline option.
    - Deleted Tcl_Fork and Tcl_WaitPids procedures (just use fork and
      waitpid instead).
    - Added waitpid compatibility procedure for systems that don't have
      it.
    - Added Tcl_ReapDetachedProcs procedure.
    - Changed "exec" to return an error if there is stderr output, even
      if the command returns a 0 exit status (it's always been documented
      this way, but the implementation wasn't correct).
    - If a process returns a non-zero exit status but doesn't generate
      any diagnostic output, then Tcl generates an error message for it.
*** POTENTIAL INCOMPATIBILITY ***

161. 2/25/93 Fixed two memory-management problems having to do with
managing the old result during variable trace callbacks.

162. 3/1/93 Added dynamic string library:  Tcl_DStringInit, Tcl_DStringAppend,
Tcl_DStringFree, Tcl_DStringResult, etc.

163. 3/1/93 Modified glob command to only return the names of files that
exist, and to only return names ending in "/" if the file is a directory.
*** POTENTIAL INCOMPATIBILITY ***

164. 3/19/93 Modified not to use system calls like "read" directly,
but instead to use special Tcl procedures that retry automatically
if interrupted by signals.

165. 4/3/93 Eliminated "noSep" argument to Tcl_AppendElement, plus
TCL_NO_SPACE flag for Tcl_SetVar and Tcl_SetVar2.
*** POTENTIAL INCOMPATIBILITY ***

166. 4/3/93 Eliminated "flags" and "termPtr" arguments to Tcl_Eval.
*** POTENTIAL INCOMPATIBILITY ***

167. 4/3/93 Changes to expressions:
    - The "expr" command now accepts multiple arguments, which are
      concatenated together with space separators.
    - Integers aren't automatically promoted to floating-point if they
      overflow the word size:  errors are generated instead.
    - Tcl can now handle "NaN" and other special values if the underlying
      library procedures handle them.
    - When printing floating-point numbers, Tcl ensures that there is a "."
      or "e" in the number, so it can't be treated as an integer accidentally.
      The procedure Tcl_PrintDouble is available to provide this function
      in other contexts.  Also, the variable "tcl_precision" can be used
      to set the precision for printing (must be a decimal number giving
      digits of precision).
    - Expressions now support transcendental and other functions, e.g. sin,
      acos, hypot, ceil, and round.  Can add new math functions with
      Tcl_CreateMathFunc().
    - Boolean expressions can now have any of the string values accepted
      by Tcl_GetBoolean, such as "yes" or "no".
*** POTENTIAL INCOMPATIBILITY ***

168. 4/5/93 Changed Tcl_UnsetVar and Tcl_UnsetVar2 to return TCL_OK
or TCL_ERROR instead of 0 or -1.
*** POTENTIAL INCOMPATIBILITY ***

169. 4/5/93 Eliminated Tcl_CmdBuf structure and associated procedures;
can use Tcl_DStrings instead.
*** POTENTIAL INCOMPATIBILITY ***

170. 4/8/93 Changed interface to Tcl_TildeSubst to use a dynamic
string for buffer space.  This makes the procedure re-entrant and
thread-safe, whereas it wasn't before.
*** POTENTIAL INCOMPATIBILITY ***

171. 4/14/93 Eliminated tclHash.h, and moved everything from it to
tcl.h
*** POTENTIAL INCOMPATIBILITY ***

172. 4/15/93 Eliminated Tcl_InitHistory, made "history" command always
be part of interpreter.
*** POTENTIAL INCOMPATIBILITY ***

173. 4/16/93 Modified "file" command so that "readable" option always
exists, even on machines that don't support symbolic links (always returns
same error as if the file wasn't a symbolic link).

174. 4/26/93 Fixed bugs in "regsub" where ^ patterns didn't get handled
right (pretended not to match when it really did, and looped infinitely
if -all was specified).

175. 4/29/93 Various improvements in the handling of variables:
    - Can create variables and array elements during a read trace.
    - Can delete variables during traces (note: unset traces will be
      invoked when this happens).
    - Can upvar to array elements.
    - Can retarget an upvar to another variable by re-issuing the
      upvar command with a different "other" variable.

176. 5/3/93 Added Tcl_GetCommandInfo, which returns info about a Tcl
command such as whether it exists and its ClientData.  Also added
Tcl_SetCommandInfo, which allows any of this information to be modified
and also allows a command's delete procedure to have a different
ClientData value than its command procedure.

177. 5/5/93 Added Tcl_RegExpMatch procedure.

178. 5/6/93 Fixed bug in "scan" where it didn't properly handle
%% conversion specifiers.  Also changed "scan" to use Tcl_PrintDouble
for printing real values.

179. 5/7/93 Added "-exact", "-glob", and "-regexp" options to "lsearch"
command to allow different kinds of pattern matching.

180. 5/7/93 Added many new switches to "lsort" to control the sorting
process: "-ascii", "-integer", "-real", "-command", "-increasing",
and "-decreasing".

181. 5/10/93 Changes to file I/O:
    - Modified "open" command to support a list of POSIX access flags
      like {WRONLY CREAT TRUNC} in addition to current fopen-style
      access modes.  Also added "permissions" argument to set permissions
      of newly-created files.
    - Fixed Scott Bolte's bug (can close stdin etc. in application and
      then re-open them with Tcl commands).
    - Exported access to Tcl's file table with new procedures Tcl_EnterFile
      and Tcl_GetOpenFile.

182. 5/15/93 Added new "pid" command, which can be used to retrieve
either the current process id or a list of the process ids in a
pipeline opened with "open |..."

183. 6/3/93 Changed to use GNU autoconfig for configuration instead of
the home-brew "config" script.  Also made many other configuration-related
changes, such as using <unistd.h> instead of explicitly declaring system
calls in tclUnix.h.

184. 6/4/93 Fixed bug where core-dumps could occur if a procedure
redefined itself (the memory for the procedure's body could get
reallocated in the middle of evaluating the body);  implemented
simple reference count mechanism.

185. 6/5/93 Changed tclIndex file format in two ways:  (a) it's now
eval-ed instead of parsed, which makes it 3-4x faster; (b) the entries
in auto_index are now commands to evaluate, which allows commands to
be loaded in different ways such as dynamic-loading of C code.  The
old tclIndex file format is still supported.

186. 6/7/93 Eliminated tclTest program, added new "tclsh" program
that is more like wish (allows script files to be invoked automatically
using "#!/usr/local/bin/tclsh", makes arguments available to script,
etc.).  Added support for Tcl_AppInit plus default version;  this
allows new Tcl applications to be created without modifying the
main program for tclsh.

187. 6/7/93 Fixed bug in TclWordEnd that kept backslash-newline from
working correctly in some cases during interactive input.

188. 6/9/93 Added Tcl_LinkVar and related procedures, which automatically
keep a Tcl variable in sync with a C variable.

189. 6/16/93 Increased maximum nesting depth from 100 to 1000.

190. 6/16/93 Modified "trace var" command so that error messages from
within traces are returned properly as the result of the variable
access, instead of the generic "access disallowed by trace command"
message.

191. 6/16/93 Added Tcl_CallWhenDeleted to provide callbacks when an
interpreter is deleted (same functionality as Tcl_WatchInterp, which
used to exist in versions before 6.0).

193. 6/16/93 Added "-code" argument to "return" command;  it's there
primarily for completeness, so that procedures implementing control
constructs can reflect exceptional conditions back to their callers.

194. 6/16/93 Split up Tcl.n to make separate manual entries for each
Tcl command.  Tcl.n now contains a summary of the language syntax.

195. 6/17/93 Added new "switch" command to replace "case": allows
alternate forms of pattern matching (exact, glob, regexp), replaces
pattern lists with single patterns (but you can use "-" bodies to
share one body among several patterns), eliminates "in" noise word.
"Case" command is now obsolete.

196. 6/17/93 Changed the "exec", "glob", "regexp", and "regsub" commands
to include a "--" switch.  All initial arguments starting with "-" are now
treated as switches unless a "--" switch is present to end the list.
*** POTENTIAL INCOMPATIBILITY ***

197. 6/17/93 Changed auto-exec so that the subprocess gets stdin, stdout,
and stderr from the parent.  This allows truly interactive sub-processes
(e.g. vi) to be auto-exec'ed from a tcl shell command line.

198. 6/18/93 Added patchlevel.h, for use in coordinating future patch
releases, and also added "info patchlevel" command to make the patch
level available to Tcl scripts.

199. 6/19/93 Modified "glob" command so that a leading "//" in a name
gets left as is (this is needed for systems like Apollos where "//" is
the super-root;  Tcl used to collapse the two slashes into a single
slash).

200. 7/7/93 Added Tcl_SetRecursionLimit procedure so that the maximum
allowable nesting depth can be controlled for an interpreter from C.

----------------- Released version 7.0 Beta 1, 7/9/93 ------------------

201. 7/12/93 Modified Tcl_GetInt and tclExpr.c so that full-precision
unsigned integers can be specified without overflow errors.

202. 7/12/93 Configuration changes:  eliminate leading blank line in
configure script;  provide separate targets in Makefile for installing
binary and non-binary information; check for size_t and a few other
potentially missing typedefs; don't put tclAppInit.o into libtcl.a;
better checks for matherr support.

203. 7/14/93 Changed tclExpr.c to check the termination pointer before
errno after strtod calls, to avoid problems with some versions of
strtod that set errno in unexpected ways.

204. 7/16/93 Changed "scan" command to be more ANSI-conformant:
eliminated %F, %D, etc., added code to ignore "l", "h", and "L"
modifiers but always convert %e, %f, and %g with implicit "l";
also added support for %u and %i.  Also changed "format" command
to eliminate %D, %U, %O, and add %i.
*** POTENTIAL INCOMPATIBILITY ***

205. 7/17/93 Changed "uplevel" and "upvar" so that they can be used
from global level to global level:  this used to generate an error.

206. 7/19/93 Renamed "setenv", "putenv", and "unsetenv" procedures
to avoid conflicts with system procedures with the same names.  If
you want Tcl's procedures to override the system procedures, do it
in the Makefile (instructions are in the Makefile).
*** POTENTIAL INCOMPATIBILITY ***

----------------- Released version 7.0 Beta 2, 7/21/93 ------------------

207. 7/21/93 Fixed bug in tclVar.c where freed memory was accidentally
used if a procedure returned an element of a local array.

208. 7/22/93 Fixed bug in "unknown" where it didn't properly handle
errors occurring in the "auto_load" procedure, leaving its state
inconsistent.

209. 7/23/93 Changed exec's ">2" redirection operator to "2>" for
consistency with sh.  This is incompatible with earlier beta releases
of 7.0 but not with pre-7.0 releases, which didn't support either
operator.

210. 7/28/93 Changed backslash-newline handling so that the resulting
space character *is* treated as a word separator unless the backslash
sequence is in quotes or braces.  This is incompatible with 7.0b1
and 7.0b2 but is more compatible with pre-7.0 versions that the b1
and b2 releases were.

211. 7/28/93 Eliminated Tcl_LinkedVarWritable, added TCL_LINK_READ_ONLY to
Tcl_LinkVar to accomplish same purpose.  This change is incompatible
with earlier beta releases, but not with releases before Tcl 7.0.

212. 7/29/93 Renamed regexp C functions so they won't clash with POSIX
regexp functions that use the same name.

213. 8/3/93 Added "-errorinfo" and "-errorcode" options to "return"
command: these allow for much better handling of the errorInfo
and errorCode variables in some cases.

214. 8/12/93 Changed "expr" so that % always returns a remainder with
the same sign as the divisor and absolute value smaller than the
divisor.

215. 8/14/93 Turned off auto-exec in "unknown" unless the command
was typed interactively.  This means you must use "exec" when
invoking subprocesses, unless it's a command that's typed interactively.
*** POTENTIAL INCOMPATIBILITY ***

216. 8/14/93 Added support for tcl_prompt1 and tcl_prompt2 variables
to tclMain.c:  makes prompts user-settable.

217. 8/14/93 Added asynchronous handlers (Tcl_AsyncCreate etc.) so
that signals can be taken cleanly by Tcl applications.

218. 8/16/93 Moved information about open files from the interpreter
structure to global variables so that a file can be opened in one
interpreter and read or written in another.

219. 8/16/93 Removed ENV_FLAGS from Makefile, so that there's no
official support for overriding setenv, unsetenv, and putenv.

220. 8/20/93 Various configuration improvements:  coerce chars
to unsigned chars before using macros like isspace;  source ~/.tclshrc
file during initialization if it exists and program is running
interactively;  allow there to be directories in auto_path that don't
exist or don't have tclIndex files (ignore them); added Tcl_Init
procedure and changed Tcl_AppInit to call it.

221. 8/21/93 Fixed bug in expr where "+", "-", and " " were all
getting treated as integers with value 0.

222. 8/26/93 Added "tcl_interactive" variable to tclsh.

223. 8/27/93 Added procedure Tcl_FilePermissions to return whether a
given file can be read or written or both.  Modified Tcl_EnterFile
to take a permissions mask rather than separate read and write arguments.

224. 8/28/93 Fixed performance bug in "glob" command (unnecessary call
to "access" for each file caused a 5-10x slow-down for big directories).

----------------- Released version 7.0 Beta 3, 8/28/93 ------------------

225. 9/9/93 Renamed regexp.h to tclRegexp.h to avoid conflicts with system
include file by same name.

226. 9/9/93 Added Tcl_DontCallWhenDeleted.

227. 9/16/93 Changed not to call exit C procedure directly;  instead
always invoke "exit" Tcl command so that application can redefine the
command to do additional cleanup.

228. 9/17/93 Changed auto-exec to handle names that contain slashes
(i.e. don't use PATH for them).

229. 9/23/93 Fixed bug in "read" and "gets" commands where they didn't
clear EOF conditions.

----------------- Released version 7.0, 9/29/93 ------------------

230. 10/7/93 "Scan" command wasn't properly aligning things in memory,
so segmentation faults could arise under some circumstances.

231. 10/7/93 Fixed bug in Tcl_ConvertElement where it forgot to
backslash leading curly brace when creating lists.

232. 10/7/93 Eliminated dependency of tclMain.c on tclInt.h and
tclUnix.h, so that people can copy the file out of the Tcl source
directory to make modified private versions.

233. 10/8/93 Fixed bug in auto-loader that reversed the priority order
of entries in auto_path for new-style index files.  Now things are
back to the way they were before 3.0:  first in auto_path is always
highest priority.

234. 10/13/93 Fixed bug where Tcl_CommandComplete didn't recognize
comments and treat them as such.  Thus if you typed the line
    # {
interactively, Tcl would think that the command wasn't complete and
wait for more input before evaluating the script.

235. 10/14/93 Fixed bug where "regsub" didn't set the output variable
if the input string was empty.

236. 10/23/93 Fixed bug where Tcl_CreatePipeline didn't close off enough
file descriptors in child processes, causing children not to exit
properly in some cases.

237. 10/28/93 Changed "list" and "concat" commands not to generate
errors if given zero arguments, but instead to just return an empty
string.

----------------- Released version 7.1, 11/4/93 ------------------

Note: there is no 7.2 release.  It was flawed and was thus withdrawn
shortly after it was released.

238. 11/10/93 TclMain.c didn't compile on some systems because of
R_OK in call to "access".  Changed to eliminate call to "access".

----------------- Released version 7.3, 11/26/93 ------------------

239. 11/6/93 Modified "lindex", "linsert", "lrange", and "lreplace"
so that "end" can be specified as an index.

240. 11/6/93 Modified "append" and "lappend" to allow only two
words total (i.e., nothing to append) without generating an error.

241. 12/2/93 Changed to use EAGAIN as the errno for non-blocking
I/O instead of EWOULDBLOCK:  this should fix problem where non-blocking
I/O didn't work correctly on System-V systems.

242. 12/22/93 Fixed bug in expressions where cancelled evaluation
wasn't always working correctly (e.g. "set one 1; eval {1 || 1/$one}"
failed with a divide by zero error).

243. 1/6/94 Changed TCL_VOLATILE definition from -1 to the address of
a dummy procedure Tcl_Volatile, since -1 causes portability problems on
some machines (e.g., Crays).

244. 2/4/94 Added support for unary plus.

245. 2/17/94 Changed Tcl_RecordAndEval and "history" command to
call Tcl_GlobalEval instead of Tcl_Eval.  Otherwise, invocation of
these facilities in nested procedures can cause unwanted results.

246. 2/17/94 Fixed bug in tclExpr.c where an expression such as
"expr {"12398712938788234-1298379" != ""}" triggers an integer
overflow error for the number in quotes, even though it isn't really
a proper integer anyway.

247. 2/19/94 Added new procedure Tcl_DStringGetResult to move result
from interpreter to a dynamic string.

248. 2/19/94 Fixed bug in Tcl_DStringResult that caused it to overwrite
the contents of a static result in some situations.  This can cause
bizarre errors such as variables suddenly having empty values.

249. 2/21/94 Fixed bug in Tcl_AppendElement, Tcl_DStringAppendElement,
and the "lappend" command that caused improper omission of a separator
space in some cases.  For example, the script
    set x "abc{"; lappend x "def"
used to return the result "abc{def" instead of "abc{ def".

250. 3/3/94 Tcl_ConvertElement was outputting empty elements as \0 if
TCL_DONT_USE_BRACES was set.  This depends on old pre-7.0 meaning of
\0, which is no longer in effect, so it didn't really work.  Changed
to output empty elements as {} always.

251. 3/3/94 Renamed Tcl_DStringTrunc to Tcl_DStringSetLength and extended
it so that it can be used to lengthen a string as well as shorten it.
Tcl_DStringTrunc is defined as a macro for backward compatibility, but
it is deprecated.

252. 3/3/94 Added Tcl_AllowExceptions procedure.

253. 3/13/94 Fixed bug in Tcl_FormatCmd that could cause "format"
to mis-behave on 64-bit Big-Endian machines.

254. 3/13/94 Changed to use vfork instead of fork on systems where
vfork exists.

255. 3/23/94 Fixed bug in expressions where ?: didn't associate
right-to-left as they should.

256. 4/3/94 Fixed "exec" to flush any files used in >@ or >&@
redirection in exec, so that data buffered for them is written
before any new data added by the subprocess.

257. 4/3/94 Added "subst" command.

258. 5/20/94 The tclsh main program is now called Tcl_Main;  tclAppInit.c
has a "main" procedure that calls Tcl_Main.  This makes it easier to use
Tcl with C++ programs, which need their own main programs, and it also
allows an application to prefilter the argument list before calling
Tcl_Main.
*** POTENTIAL INCOMPATIBILITY ***

259. 6/6/94 Fixed bug in procedure returns where the errorInfo variable
could get truncated if an unset trace was invoked as part of returning
from the procedure.

260. 6/13/94 Added "wordstart" and "wordend" options to "string" command.

261. 6/27/94 Fixed bug in expressions where they didn't properly cancel
the evaluation of math functions in &&, ||, and ?:.

262. 7/11/94 Incorrect boolean values, like "ogle", weren't being
handled properly.

263. 7/15/94 Added Tcl_RegExpCompile, Tcl_RegExpExec, and Tcl_RegExpRange,
which provide lower-level access to regular expression pattern matching.

264. 7/22/94 Fixed bug in "glob" command where "glob -nocomplain ~bad_user"
would complain about a missing user.  Now it doesn't complain anymore.

265. 8/4/94 Fixed bug with linked variables where they didn't behave
correctly when accessed via upvars.

266. 8/17/94 Fixed bug in Tcl_EvalFile where it didn't clear interp->result.

267. 8/31/94 Modified "open" command so that errors in exec-ing
subprocesses are returned by the open immediately, rather than
being delayed until the "close" is executed.

268. 9/9/94 Modified "expr" command to generate errors for integer
overflow (includes addition, subtraction, negation, multiplication,
division).

269. 9/23/94 Modified "regsub" to return a count of the number of
matches and replacements, rather than 0/1.

279. 10/4/94 Added new features to "array" command:
    - added "get" and "set" commands for easy conversion between arrays
      and lists.
    - added "exists" command to see if a variable is an array, changed
      "names" and "size" commands to treat a non-existent array (or scalar
      variable) just like an empty one.
    - added pattern option to "names" command.

280. 10/6/94 Modified Tcl_SetVar2 so that read traces on variables get
called during append operations.

281. 10/20/94 Fixed bug in "read" command where reading from stdin
required two control-D's to stop the reading.

282. 11/3/94 Changed "expr" command to use longs for division just like
all other expr operators;  it previously used ints for division.

283. 11/4/94 Fixed bugs in "unknown" procedure:  it wasn't properly
handling exception returns from commands that were executed after
being auto-loaded.

----------------- Released version 7.4b1, 12/23/94 ------------------

284. 12/26/94 Fixed "install" target in Makefile (couldn't always
find install program).

285. 12/26/94 Added strcncasecmp procedure to compat directory.

286. 1/3/95 Fixed all procedure calls to explicitly cast arguments:
implicit conversions from prototypes (especially integer->double)
don't work when compiling under non-ANSI compilers.  Tcl is now clean
under gcc -Wconversion.

287. 1/4/95 Fixed problem in Tcl_ArrayCmd where same name was used for
both a label and a variable;  caused problems on several older compilers,
making array command misbehave and causing many errors in Tcl test suite.

----------------- Released version 7.4b2, 1/12/95 ------------------

288. 2/9/95 Modified Tcl_CreateCommand to return a token, and added
Tcl_GetCommandName procedure.  Together, these procedures make it possible
to track renames of a command.

289. 2/13/95 Fixed bug in expr where "089" was interpreted as a
floating-point number rather than a bogus octal number.
*** POTENTIAL INCOMPATIBILITY ***

290. 2/14/95 Added code to Tcl_GetInt and Tcl_GetDouble to check for
overflows when reading in numbers.

291. 2/18/95 Changed "array set" to stop after first error, rather than
continuing after error.

292. 2/20/95 Upgraded to use autoconf version 2.2.

293. 2/20/95 Fixed core dump that could occur in "scan" command if a
close bracket was omitted.

294. 2/27/95 Changed Makefile to always use install-sh for installations:
there's just too much variation among "install" system programs, which
makes installation flakey.

----------------- Released version 7.4b3, 3/24/95 ------------------

3/25/95 (bug fix) Changed "install" to "./install" in Makefile so that
"make install" will work even when "." isn't in the search path.

3/29/95 (bug fix) Fixed bug where the auto-loading mechanism wasn't
protecting the values of the errorCode and errorInfo variables.

3/29/95 (new feature) Added optional pattern argument to "parray" procedure.

3/29/95 (bug fix) Made the full functionality of
    "return -code ... -errorcode ..."
work not just inside procedures, but also in sourced files and at
top level.

4/6/95 (new feature) Added "pattern" option to "array names" command.

4/18/95 (bug fix) Fixed bug in parser where it didn't allow backslash-newline
immediately after an argument in braces or quotes.

4/19/95 (new feature) Added tcl_library variable, which application can
set to override default library directory.

4/30/95 (bug fix) During trace callbacks for array elements, the variable
name used in the original reference would be temporarily modified to
separate the array name and element name;  if the trace callback used
the same name string, it would get the wrong name (the array name without
element).  Fixed to restore the variable name before making trace
callbacks.

4/30/95 (new feature) Added -nobackslashes, -nocommands, and -novariables
switches to "subst" command.

5/4/95 (new feature) Added TCL_EVAL_GLOBAL flag to Tcl_RecordAndEval.

5/5/95 (bug fix)  Format command would overrun memory when printing
integers with very large precision, as in "format %.1000d 0".

5/5/95 (portability improvement) Changed to use BSDgettimeofday on
IRIX machines, to avoid compilation problems with the gettimeofday
declaration.

5/6/95 (bug fix) Changed manual entries to use the standard .TH
macro instead of a custom .HS macro;  the .HS macro confuses index
generators like makewhatis.

5/9/95 (bug fix) Modified configure script to check for Solaris bug
that makes vfork unreliable (core dumps result if vforked child
changes a signal handler);  will use fork instead of vfork if the
bug is present.

6/5/95 (bug fix) Modified "lsort" command to disallow recursive calls
to lsort from a comparison function.  This is needed because qsort
is not reentrant.

6/5/95 (bug fix) Undid change 243 above:  changed TCL_VOLATILE and
TCL_DYNAMIC back to integer constants rather than procedure addresses.
This was needed because procedure addresses can have multiple values
under some dynamic loading systems (e.g. SunOS 4.1 and Windows).

6/8/95 (feature change) Modified interface to Tcl_Main to pass in the
address of the application-specific initialization procedure.
Tcl_AppInit is no longer hardwired into Tcl_Main.  This is needed
in order to make Tcl a shared library.

6/8/95 (feature change) Modified Makefile so that the installed versions
of tclsh and libtcl.a have version number in them (e.g. tclsh7.4 and
libtcl7.4.a) and the library directory name also has an embedded version
number (e.g., /usr/local/lib/tcl7.4).  This should make it easier for
Tcl 7.4 to coexist with earlier versions.

----------------- Released version 7.4b4, 6/16/95 ------------------

6/19/95 (bug fix) Fixed bugs in tclCkalloc.c that caused core dumps
if TCL_MEM_DEBUG was enabled on word-addressed machines such as Crays.

6/21/95 (feature removal) Removed overflow checks for integer arithmetic:
they just cause too much trouble (e.g. for random  number generators).

6/28/95 (new features) Added tcl_patchLevel and tcl_version variables,
for consistency with Tk.

6/29/95 (bug fix) Fixed problem in Tcl_Eval where it didn't record
the right termination character if a script ended with a comment.  This
caused erroneous output for the following command, among others:
puts "[
expr 1+1
# duh!
]"

6/29/95 (message change) Changed the error message for ECHILD slightly
to provide a hint about why the problem is occurring.

----------------- Released version 7.4, 7/1/95 ------------------

7/18/95 (bug fix) Changed "lreplace" so that nothing is deleted if
the last index is less than the first index or if the last index
is < 0.

7/18/95 (bug fix) Fixed bugs with backslashes in comments:
Tcl_CommandComplete (and "info complete") didn't properly handle
strings ending in backslash-newline, and neither Tcl_CommandComplete
nor the Tcl parser handled other backslash sequences right, such
as two backslashes before a newline.

7/19/95 (bug fix) Modified Tcl_DeleteCommand to delete the hash table
entry for the command before invoking its callback.  This is needed in
order to deal with reentrancy.

7/22/95 (bug fix) "exec" wasn't reaping processes correctly after
certain errors (e.g. if the name of the executable was bogus, as
in "exec foobar").

7/27/95 (bug fix) Makefile.in wasn't using the LIBS variable provided
by the "configure" script.  This caused problems on some SCO systems.

7/27/95 (bug fix) The version of strtod in fixstrtod.c didn't properly
handle the case where endPtr == NULL.

----------------- Released patch 7.4p1, 7/29/95 -----------------------

8/4/95 (bug fix) C-level trace callbacks for variables were sometimes
receiving the PART1_NOT_PARSED flag, which could cause errors in
subsequent Tcl library calls using the flags. (JO)

8/4/95 (bug fix) Calls to toupper and tolower weren't using the
UCHAR macros, which caused trouble in non-U.S. locales. (JO)

8/10/95 (new feature) Added the "load" command for dynamic loading of
binary packages, and the Tcl_PackageInitProc prototype for package
initialization procedures. (JO)

8/23/95 (new features) Added "info sharedlibextension" and
"info nameofexecutable" commands, plus Tcl_FindExtension procedure. (JO)

8/25/95 (bug fix) If the target of an "upvar" was non-existent but
had traces set, the traces were silently lost.  Change to generate
an error instead. (JO)

8/25/95 (bug fix) Undid change from 7/19, so that commands can stay
around while their deletion callbacks execute.  Added lots of code to
handle all of the reentrancy problems that this opens up. (JO)

8/25/95 (bug fix) Fixed core dump that could occur in TclDeleteVars
if there was an upvar from one entry in the table to the next entry
in the same table. (JO)

8/28/95 (bug fix) Exec wasn't handling bad user names properly, as
in "exec ~bogus_user/foo". (JO)

8/29/95 (bug fixes) Changed backslash-newline handling to correct two
problems:
    - Only spaces and tabs following the backslash-newline are now
      absorbed as part of the backslash-newline.  Newlinew are no
      longer absorbed (add another backslash if you want to absorb
      another newline).
    - TclWordEnd returns the character just before the backslash in
      the sequence as the end of the sequence;  it used to not consider
      the backslash-newline as a word separator. (JO)

8/31/95 (new feature) Changed man page installation (with "mkLinks"
script) to create additional links for manual pages corresponding to
each of the procedure and command names described in the pages. (JO)

9/10/95 Reorganized Tcl sources for Windows and Mac ports.  All sources
are now in subdirectories:  "generic" contains sources that work on all
platforms, "windows", "mac", and "unix" directories contain platform-
specific sources.  Some UNIX sources are also used on other platforms. (SS)

9/10/95 (feature change) Eliminated exported global variables (they
don't work with Windows DLLs).  Replaced tcl_AsyncReady and
tcl_FileCloseProc with procedures Tcl_AsyncReady() and
Tcl_SetFileCloseProc().  Replaced C variable tcl_RcFileName with
a Tcl variable tcl_rcFileName. (SS)
*** POTENTIAL INCOMPATIBILITY ***

9/11/95 (new feature) Added procedure Tcl_SetPanicProc to override
the default implementation of "panic". (SS)

9/11/95 (new feature) Added "interp" command to allow creation of
new interpreters and execution of untrusted scripts.  Added many new
procedures, such as Tcl_CreateSlave, Tcl_CreateAlias,and Tcl_MakeSafe,
to provide C-level access to the interpreter facility. This mechanism
now provides almost all of the generic functions of Borenstein's and
Rose's Safe-Tcl (but not any Tk or email-related stuff).  (JL)

9/11/95 (feature change) Changed file management so that files are
no longer shared between interpreters:  a file cannot normally be
referenced in one interpreter if it was opened in another.  This
feature is needed to support safe interpreters.  Added Tcl_ShareHandle()
procedure for allowing files to be shared, and added "interp" argument
to Tcl_FilePermissions procedure. (JL)
*** POTENTIAL INCOMPATIBILITY ***

9/11/95 (new feature) Added "AssocData" mechanism, whereby extensions
can associate their own data with an interpreter and get called back
when the interpreter is deleted.  This is visible at C level via the
procedures Tcl_SetAssocData and Tcl_GetAssocData.  (JL)

9/11/95 (new feature) Added Tcl_ErrnoMsg to translate an errno value
into a human-readable string.  This is now used instead of calling
strerror because strerror mesages vary dramatically from platform
to platform, which messes up Tcl tests.  Tcl_ErrnoMsg uses the standard
POSIX messages for all the common signals, and calls strerror for
signals it doesn't understand.

----------------- Released patch 7.4p2, 9/15/95 -----------------------

----------------- Released 7.5a1, 9/15/95 -----------------------

9/22/95 (bug fix) Changed auto_mkindex to create tclIndex files that
handle directories whose paths might contain spaces. (RJ)

9/27/95 (bug fix) The "format" command didn't check for huge or negative
width specifiers, which could cause core dumps. (JO)

9/27/95 (bug fix) Core dumps could occur if an interactive command typed
to tclsh returned a very long result for tclsh to print out.  The bug is
actually in printf (in Solaris 2.3 and 2.4, at least);  switched to use
puts instead.  (JO)

9/28/95 (bug fix) Changed makefile.bc to eliminate a false dependency
for tcl1675.dll on the Borland run time library. (SS)

9/28/95 (bug fix) Fixed tcl75.dll so it looks for tcl1675.dll instead
of tcl16.dll. (SS)

9/28/95 (bug fix) Tcl was not correctly detecting the difference
between Win32s and Windows '95. (SS)

9/28/95 (bug fix) "exec" was not passing environment changes to child
processes under Windows. (SS)

9/28/95 (bug fix) Changed Tcl to ensure that open files are not passed
to child processes under Windows. (SS)

9/28/95 (bug fix) Fixed Windows '95 and NT versions of exec so it can
handle both console and windows apps.   (SS)

9/28/95 (bug fix) Fixed Windows version of exec so it no longer leaves
temp files lying around.  Also changed it so the temp files are
created in the appropriate system dependent temp directory. (SS)

9/28/95 (bug fix) Eliminated source dependency on the Win32s Universal
Thunk header file, since it is not bundled with VC++. (SS)

9/28/95 (bug fix) Under Windows, Tcl now constructs the HOME
environment variable from HOMEPATH and HOMEDRIVE when HOME is not
already set. (SS)

9/28/95 (bug fix) Added support for "info nameofexecutable" and "info
sharedlibextension" to the Windows version. (SS)

9/28/95 (bug fix) Changed tclsh to correctly parse command line
arguments so that backslashes are preserved under Windows. (SS)

9/29/95 (bug fix) Tcl 7.5a1 treated either return or newline as end
of line in "gets", which caused lines ending in CRLF to be treated as
two separate lines.  Changed to allow only character as end-of-line:
carriage return on Macs, newline elsewhere. (JO)

9/29/95 (new feature) Changed to install "configInfo" file in same
directory as library scripts.  It didn't used to get installed. (JO)

9/29/95 (bug fix) Tcl was not converting Win32 errors into POSIX
errors under some circumstances. (SS)

10/2/95 (bug fix) Safe interpreters no longer get initialized with
a call to Tcl_Init(). (JL)

10/1/95 (new feature) Added "tcl_platform" global variable to provide
environment information such as the instruction set and operating
system. (JO)

10/1/95 (bug fix) "exec" command wasn't always generating the
"child process exited abnormally" message when it should have.  (JO)

10/2/95 (bug fix) Changed "mkLinks.tcl" so that the scripts it generates
won't create links that overwrite original manual entries (there was
a problem where pack-old.n was overwriting pack.n).  (JO)

10/2/95 (feature change) Changed to use -ldl for dynamic loading under
Linux if it is available, but fall back to -ldld if it isn't.  (JO)

10/2/95 (bug fix) File sharing was causing refcounts to reach 0
prematurely for stdin, stdout and stderr, under some circumstances. (JL)

10/2/95 (platform support) Added support for Visual C++ compiler on
Windows, Windows '95 and Windows NT, code donated by Gordon Chaffee. (JL)

10/3/95 (bug fix) Tcl now frees any libraries that it loads before it
exits. (SS)

10/03/95 (bug fix) Fixed bug in Macintosh ls command where the -l
and -C options would fail in anything but the HOME directory. (RJ)

----------------- Released 7.5a2, 10/6/95 -----------------------

10/10/95 (bug fix) "file dirnam /." was returning ":" on UNIX instead
of "/". (JO)

10/13/95 (bug fix) Eliminated dependency on MKS toolkit for generating
the tcl.def file from Borland object files. (SS)

10/17/95 (new features) Moved the event loop from Tcl to Tk, made major
revisions along the way:
    - New Tcl commands:  after, update, vwait (replaces "tkwait variable").
    - "tkerror" is now replaced with "bgerror".
    - The following procedures are similar to their old Tk counterparts:
      Tcl_DoOneEvent, Tcl_Sleep, Tcl_DoWhenIdle, Tcl_CancelIdleCall,
      Tcl_CreateFileHandler, Tcl_DeleteFileHandler, Tcl_CreateTimerHandler,
      Tcl_DeleteTimerHandler, Tcl_BackgroundError.
    - Revised notifier, add new concept of "event source" with the following
      procedures:  Tcl_CreateEventSource, Tcl_DeleteEventSource,
      Tcl_WatchFile, Tcl_SetMaxBlockTime, Tcl_FileReady, Tcl_QueueEvent,
      Tcl_WaitForEvent. (JO)

10/31/95 (new features) Implemented cross platform file name support to make
it easier to write cross platform scripts.  Tcl now understands 4 file naming
conventions: Windows (both DOS and UNC), Mac, Unix, and Network.  The network
convention is a new naming mechanism that can be used to paths in a platform
independent fashion.  See the "file" command manual page for more details.
The primary interfaces changes are:
    - All Tcl commands that expect a file name now accept both network and
      native form.
    - Two new "file" subcommands, "nativename" and "networkname", provide a
      way to convert between network and native form.
    - Renamed Tcl_TildeSubst to Tcl_TranslateFileName, and changed it so that
      it always returns a filename in native form.  Tcl_TildeSubst is defined
      as a macro for backward compatibility, but it is deprecated. (SS)

11/5/95 (new feature) Made "tkerror" and "bgerror" synonyms, so that
either name can be used to manipulate the command (provides temporary
backward compatibility for existing scripts that use tkerror). (JO)

11/5/95 (new feature) Added exit handlers and new C procedures
Tcl_CreateExitHandler, Tcl_DeleteExitHandler, and Tcl_Exit. (JO)

11/6/95 (new feature) Added pid command for Macintosh version of
Tcl (it didn't previously exist on the Mac). (RJ)

11/7/95 (new feature) New generic IO facility and support for IO to
files, pipes and sockets based on a common buffering scheme. Support
for asynchronous (non-blocking) IO and for event driver IO. Support
for automatic (background) asynchronous flushing and asynchronous
closing of channels. (JL)

11/7/95 (new feature)  Added new commands "fconfigure" and "fblocked"
to support new I/O features such as nonblocking I/O.  Added "socket"
command for creating TCP client and server sockets. (JL).

11/7/95 (new feature) Complete set of C APIs to the new generic IO
facility:
    - Opening channels: Tcl_OpenFileChannel, Tcl_OpenCommandChannel,
      Tcl_OpenTcpClient, Tcl_OpenTcpServer.
    - I/O procedures on channels, which roughly mirror the ANSI C stdio
      library:  Tcl_Read, Tcl_Gets, Tcl_Write, Tcl_Flush, Tcl_Seek,
      Tcl_Tell, Tcl_Close, Tcl_Eof, Tcl_InputBlocked, Tcl_GetChannelOption,
      Tcl_SetChannelOption.
    - Extension mechanism for creating new kinds of channels:
      Tcl_CreateChannel, Tcl_GetChannelInstanceData, Tcl_GetChannelType,
      Tcl_GetChannelName, Tcl_GetChannelFile, Tcl_RegisterChannel,
      Tcl_UnregisterChannel, Tcl_GetChannel.
    - Event-driven I/O on channels: Tcl_CreateChannelHandler,
      Tcl_DeleteChannelHandler. (JL)

11/7/95 (new feature) Channel driver interface specification to allow
new types of channels to be added easily to Tcl. Currently being used
in three drivers - for files, pipes and TCP-based sockets. (JL).

11/7/95 (new feature) interp delete now takes any number of path
names of interpreters to delete, including zero. (JL).

11/8/95 (new feature) implemented 'info hostname' and Tcl_GetHostName
command to get host name of machine on which the Tcl process is running. (JL)

11/9/95 (new feature) Implemented file APIs for access to low level files
on each system. The APIs are: Tcl_CloseFile, Tcl_OpenFile, Tcl_ReadFile,
Tcl_WriteFile and Tcl_SeekFile. Also implemented Tcl_WaitPid which waits
in a system dependent manner for a child process. (JL)

11/9/95 (new feature) Added Tcl_UpdateLinkedVar procedure to force a
Tcl variable to be updated after its C variable changes. (JO)

11/9/95 (bug fix) The glob command has been totally reimplemented so
that it can support different file name conventions.  It now handles
Windows file names (both UNC and drive-relative) properly.  It also
supports nested braces correctly now. (SS)

11/13/95 (bug fix) Fixed Makefile.in so that configure can be run
from a clean directory separate from the Tcl source tree, and compilations
can be performed there. (JO)

11/14/95 (bug fix) Fixed file sharing between interpreters and file
transferring between interpreters to correctly manage the refcount so that
files are closed when the last reference to them is discarded. (JL)

11/14/95 (bug fix) Fixed gettimeofday implementation for the
Macintosh.  This fixes several timing related bugs. (RJ)

11/17/95 (new feature) Added missing support for info nameofexecutable
on the Macintosh. (RJ)

11/17/95 (bug fix) The Tcl variables argc argv and argv0 now return
something reasonable on the Mac.  (RJ)

11/22/95 (new feature) Implemented "auto-detect" mode for end of line
translations. On input, standalone "\r" mean MAC mode, standalone "\n"
mean Unix mode and "\r\n" means Windows mode. On output, the mode is
modified to whatever the platform specific mode for that platform is. (JL)

11/24/95 (feature change) Replaced "configInfo" file with tclConfig.sh,
which is more complete and uses slightly different names.  Also
arranged for tclConfig.sh to be installed in the platform-specific
library directory instead of Tcl's script library directory. (JO)
*** POTENTIAL INCOMPATIBILITY with Tcl 7.5a2, but not with Tcl 7.4 ***

----------------- Released patch 7.4p3, 11/28/95 -----------------------

12/5/95 (new feature) Added Tcl_File facility to support platform-
independent file handles.  Changed all interfaces that used Unix-
style integer fd's to use Tcl_File's instead. (SS)
*** POTENTIAL INCOMPATIBILITY ***

12/5/95 (new feature) Added a new "clock" command to Tcl.  The command
allows you to get the current "clicks" or seconds & allows you to
format or scan human readable time/date strings. (RJ)

12/18/95 (new feature) Moved Tk_Preserve, Tk_Release, and Tk_EventuallyFree
to Tcl, renamed to Tcl_Preserve, Tcl_Release, and Tcl_EventuallyFree. (JO)

12/18/95 (new feature) Added new "package" command and associated
procedures Tcl_PkgRequire and Tcl_PkgProvide.   Also wrote
pkg_mkIndex library procedure to create index files from binaries
and scripts. (JO)

12/20/95 (new feature) Added Tcl_WaitForFile procedure. (JO)

12/21/95 (new features) Made package name argument to "load" optional
(Tcl will now attempt to guess the package name if necessary).  Also
added Tcl_StaticPackage and support in "load" for statically linked
packages.  (JO)

12/22/95 (new feature) Upgraded the foreach command to accept multiple
loop variables and multiple value lists.  This lets you iterate over
multiple lists in parallel, and/or assign multiple loop variables from
one value list during each iteration. The only potential compatibility
problem is with scripts that used loop variables with a name that could be
construed to be a list of variable names (i.e. contained spaces).  (BW)

1/5/96 (new feature) Changed tclsh so it builds as a console mode
application under Windows.  Now tclsh can be used from the command
line with pipes or interactively.  Note that this only works under
Windows 95 or NT. (SS)

1/17/96 (new feature) Modified Makefile and configure script to allow
Tcl to be compiled as a shared library:  use the --enable-shared option
when configuing.  (JO)

1/17/96 (removed obsolete features)  Removed the procedures Tcl_EnterFile
and Tcl_GetOpenFile:  these no longer make sense with the new I/O system. (JL)
*** POTENTIAL INCOMPATIBILITY ***

1/19/96 (bug fixes) Prevented formation of circular aliases, through the
Tcl 'interp alias' command and through the 'rename' command, as well as
through the C API Tcl_CreateAlias. (JL)

1/19/96 (bug fixes) Fixed several bugs in direct deletion of interpreters
with Tcl_DeleteInterp when the interpreter is a slave; fixes based on a
patch received from Viktor Dukhovni of ESM. (JL)

1/19/96 (new feature) Implemented on-close handlers for channels; added
the C APIs Tcl_CreateCloseHandler and Tcl_DeleteCloseHandler. (JL)

1/19/96 (new feature) Implemented portable error reporting mechanism; added
the C APIs Tcl_SetErrno and Tcl_GetErrno. (JL)

1/24/96 (bug fix) Unknown command processing properly invokes external
commands under Windows NT and Windows '95 now. (SS)

1/23/96 (bug fix) Eliminated extremely long startup times under Windows '95.
The problem was a result of the option database initialization code that
concatenated $HOME with /.Xdefaults, resulting in a // in the middle of the
file name.  Under Windows '95, this is incorrectly interpreted as a UNC
path.  They delays came from the network timeouts needed to determine that
the file name was invalid.  Tcl_TranslateFileName now suppresses duplicate
slashes that aren't at the beginning of the file name. (SS)

1/25/96 (bug fix) Changed exec and open to create children so they are
attached to the application's console if it exists. (SS)

1/31/96 (bug fix) Fixed command line parsing to handle embedded
spaces under Windows. (SS)

----------------- Released 7.5b1, 2/1/96 -----------------------

2/7/96 (bug fix) Fixed off by one error in argument parsing code under
Windows. (SS)

2/7/96 (bug fix) Fixed bugs in VC++ makefile that improperly
initialized the tcl75.dll.  Fixed bugs in Borland makefile that caused
build failures under Windows NT. (SS)

2/9/96 (bug fix) Fixed deadlock problem in AUTO end of line translation
mode which would cause a socket server with several concurrent clients
writing in CRLF mode to hang. (JL)

2/9/96 (API change) Replaced -linemode option to fconfigure with a
new -buffering option, added "none" setting to enable immediate write. (JL)
*** INCOMPATIBILITY with b1 ***

2/9/96 (new feature) Added C API Tcl_InputBuffered which returns the count
of bytes currently buffered in the input buffer of a channel, and o for
output only channels. (JL)

2/9/96 (new feature) Implemented asynchronous connect for sockets. (JL)

2/9/96 (new feature) Added C API Tcl_SetDefaultTranslation to set (per
channel) the default end of line translation mode. This is the mode that
will be installed if an output operation is done on the channel while it is
still in AUTO mode. (JL)

2/9/96 (bug fix) Changed Tcl_OpenCommandChannel interface to properly
handle all of the combinations of stdio inheritance in background
pipelines.  See the Tcl_OpenFileChannel(3) man page for more
info.  This change fixes the bug where exec of a background pipeline
was not getting passed the stdio handles properly. (SS)

2/9/96 (bug fix) Removed the new Tcl_CreatePipeline interface, and
restored the old version for Unix platforms only.  All new code should
use Tcl_CreateCommandChannel instead. (SS)

2/9/96 (bug fix) Changed Makefile.in to use -L and -ltcl7.5 for Tcl
library so that shared libraries are more likely to be found correctly
on more platforms. (JO)

2/13/96 (new feature) Added C API Tcl_SetNotifierData and
Tcl_GetNotifierData to allow notifier and channel driver writers to
associate data with a Tcl_File.  The result of this change is that
Tcl_GetFileInfo now always returns an OS file handle, and Tcl_GetFile
can be used to construct a Tcl_File for an externally constructed OS
handle. (SS)

2/13/96 (bug fix) Changed Windows socket implementation so it doesn't
set SO_REUSEADDR on server sockets.  Now attempts to create a server
socket on a port that is already in use will be properly identified
and an error will be generated. (SS)

2/13/96 (bug fix) Fixed problems with DLL initialization under Visual
C++ that left the C run time library uninitialized. (SS)

2/13/96 (bug fix) Fixed Windows socket initialization so it loads
winsock the first time it is used, rather than at the time tcl75.dll
is loaded.  This should fix the bug where the modem immediately starts
trying to connect to a service provider when wish or tclsh are
started. (SS)

2/13/96 (new feature) Added C APIs Tcl_MakeFileChannel and
Tcl_MakeTcpClientChannel to wrap up existing fds and sockets into
channels. Provided implementations on Unix and Windows. (JL)

2/13/96 (bug fix) Fixed bug with seek leaving EOF and BLOCKING set. (JL)

2/14/96 (bug fix) Fixed reentrancy problem in fileevent handling
and made it more robust in the face of errors. (JL)

2/14/96 (feature change) Made generic IO level emulate blocking mode if the
channel driver is unable to provide it, e.g. if the low level device is
always nonblocking. Thus, now blocking behavior is an advisory setting for
channel drivers and can be ignored safely if the channel driver is unable
to provide it. (JL)

2/15/96 (new feature) Added "binary" end of line translation mode, which is
a synonym of "lf" mode. (JL)

2/15/96 (bug fix) Fixed reentrancy problem in fileevent handling vs
deletion of channel event handlers. (JL)

2/15/96 (bug fix) Fixed bug in event handling which would cause a
nonblocking channel to not see further readable events after the first
readable event that had insufficient input. (JL)

2/17/96 (bug fix) "info complete" didn't properly handle comments
in nested commands. (JO)

2/21/96 (bug fix) "exec" under Windows NT/95 did not properly handle
very long command lines (>200 chars). (SS)

2/21/96 (bug fix) Sockets could get into an infinite loop if a read
event arrived after all of the available data had been read. (SS)

2/22/96 (bug fix) Added cast of st_size elements to (long) before
sprintf-ing in "file size" command.  This is needed to handle systems
like NetBSD with 64-bit file offsets.  (JO)

----------------- Released 7.5b2, 2/23/96 -----------------------

2/23/96 (bug fix) TCL_VARARGS macro in tcl.h wasn't defined properly
when compiling with C++.  (JO)

2/24/96 (bug fix) Removed dependencies on Makefile in the UNIX Makefile:
this caused problems on some platforms (like Linux?). (JO)

2/24/96 (bug fix) Fixed configuration bug that made Tcl not compile
correctly on Linux machines with neither -ldl or -ldld. (JO)

2/24/96 (new feature) Added a block of comments and definitions to
Makefile.in to make it easier to have Tcl's TclSetEnv etc. replace
the library procedures setenv etc, so that calls to setenv etc. in
the application automatically update the Tcl "env" variable. (JO)

2/27/96 (feature change) Added optional Tcl_Interp * argument (may be NULL)
to C API Tcl_Close and simplified closing of command channels. (JL)
*** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 ***

2/27/96 (feature change) Added optional Tcl_Interp * argument (may be NULL)
to C type definition Tcl_DriverCloseProc; modified all channel drivers to
implement close procedures that accept the additional argument. (JL)
*** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 ***

2/28/96 (bug fix) Fixed memory leak that could occur if an upvar
referred to an element of an array in the same stack frame as the
upvar. (JO)

2/29/96 (feature change) Modified both Tcl_DoOneEvent and Tcl_WaitForEvent
so that they return immediately in cases where they would otherwise
block forever (e.g. if there are no event handlers of any sort). (JO)

2/29/96 (new feature) Added C APIs Tcl_GetChannelBufferSize and
Tcl_SetChannelBufferSize to set and retrieve the size, in bytes, for
buffers allocated to store input or output in a channel. (JL)

2/29/96 (new feature) Added option -buffersize to Tcl fconfigure command
to allow Tcl scripts to query and set the size of channel buffers. (JL)

2/29/96 (feature removed) Removed channel driver function to specify
the buffer size to use when allocating a buffer. Removed the C typedef
for Tcl_DriverBufferSizeProc. Channels are now created with a default
buffer size of 4K. (JL)
*** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 ***

2/29/96 (feature change) The channel driver function for setting blocking
mode on the device may now be NULL. If the generic code detects that the
function is NULL, operations that set the blocking mode on the channel
simply succeed. (JL)

3/2/96 (bug fix) Fixed core dump that could occur if a syntax error
(such as missing close paren) occurred in an array reference with a
very long array name. (JO)

3/4/96 (bug fix) Removed code in the "auto_load" procedure that deletes
all existing auto-load information whenever the "auto_path" variable
is changed.  Instead, new information adds to what was already there.
Otherwise, changing the "auto_path" variable causes all package-
related information to be lost.  If you really want to get rid of
existing auto-load information, use auto_reset before setting auto_path. (JO)

3/5/96 (new feature) Added version suffix to shared library names so that
Tcl will compile under NetBSD and FreeBSD (I hope).  (JO)

3/6/96 (bug fix) Cleaned up error messages in new I/O system to correspond
more closely to old I/O system. (JO)

3/6/96 (new feature) Added -myaddr and -myport options to the socket
command, removed -tcp and -- options.  This lets clients and servers
choose a particular interface.  Also changed the default server address
from the hostname to INADDR_ANY.  The server accept callback now gets
passed the client's port as well as IP address.  The C interfaces for
Tcl_OpenTcpClient and Tcl_OpenTcpServer have changed to support the
above changes. (BW)
*** POTENTIAL INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 ***

3/6/96 (changed feature) The library function auto_mkindex will now
default to using the pattern "*.tcl" if no pattern is given. (RJ)

3/6/96 (bug fix) The socket channel code for the Macintosh has been
rewritten to use native MacTcp.  (RJ)

3/7/96 (new feature) Added Tcl_SetStdChannel and Tcl_GetStdChannel
interfaces to allow applications to explicitly set and get the global
standard channels. (SS)

3/7/96 (bug fix) Tcl did close not the file descriptors associated
with "stdout", etc. when the corresponding channels were closed.  (SS)

3/7/96 (bug fix) Reworked shared library and dynamic loading stuff to
try to get it working under AIX.  Added new @SHLIB_LD_LIBS@ autoconf
symbol as part of this.  AIX probably doesn't work yet, but it should
be a lot closer. (JO)

3/7/96 (feature change) Added Tcl_ChannelProc typedef and changed the
signature of Tcl_CreateChannelHandler and Tcl_DeleteChannelHandler to take
Tcl_ChannelProc arguments instead of Tcl_FileProc arguments. This change
should not affect any code outside Tcl because the signatures of
Tcl_ChannelProc and Tcl_FileProc are compatible. (JL)

3/7/96 (API change) Modified signature of Tcl_GetChannelOption to return
an int instead of char *, and to take a Tcl_DString * argument. Modified
the implementation so that the option name can be NULL, to mean that the
call should retrieve a list of alternating option names and values. (JL)
*** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 ***

3/7/96 (API change) Added Tcl_DriverSetOptionProc, Tcl_DriverGetOptionProc
typedefs, added two slots setOptionProc and getOptionProc to the channel
type structure. These may be NULL to indicate that the channel type does
not support any options. (JL)
*** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 ***

3/7/96 (feature change) stdin, stdout and stderr can now be put into
nonblocking mode. (JL)

3/8/96 (feature change) Eliminated dependence on the registry for
finding the Tcl library files. (SS)

----------------- Released 7.5b3, 3/8/96 -----------------------

3/12/96 (feature improvement) Modified startup script to look in several
different places for the Tcl library directory.  This should allow Tcl
to find the libraries under all but the weirdest conditions, even without
the TCL_LIBRARY environment variable being set. (JO)

3/13/96 (bug fix) Eliminated use of the "linger" option from the Windows
socket implementation. (JL)

3/13/96 (new feature) Added -peername and -sockname options for fconfigure
for socket channels. Code contributed by John Haxby of HP. (JL)

3/13/96 (bug fix) Fixed panic and core dump that would occur if the accept
callback script on a server socket encountered an error. (JL)

3/13/96 (feature change) Added -async option to the Tcl socket command.
If the command is creating a client socket and the flag is present, the
client is connected asynchronously. If the option is absent (the default),
the client socket is connected synchronously, and the command returns only
when the connection has been completed or failed. This change was suggested
by Mark Diekhans. (JL)

3/13/96 (feature change) Modified the signature of Tcl_OpenTcpClient to
take an additional int argument, async. If nonzero, the client is connected
to the server asynchronously. If the value is zero, the connection is made
synchronously, and the call to Tcl_OpenTcpClient returns only when the
connection fails or succeeds. This change was suggested by Mark Diekhans. (JL)
*** INCOMPATIBILITY with Tcl 7.5b3, but not with Tcl 7.4 ***

3/14/96 (bug fix) "tclsh bogus_file_name" didn't print an error message. (JO)

3/14/96 (bug fix) Added new procedures to tclCkalloc.c so that libraries
and applications can be compiled with TCL_MEM_DEBUG even if Tcl isn't
(however, the converse is still not true).  Patches provided by Jan
Nijtmans. (JO)

3/15/96 (bug fix) Marked standard IO handles of a process as close-on-exec
to fix bug in Ultrix where exec was not sharing standard IO handles with
subprocesses. Fix suggested by Mark Diekhans. (JL)

3/15/96 (bug fix) Fixed asynchronous close mechanism so that it closes the
channel instead of leaking system resources. The manifestation was that Tcl
would eventually run out of file descriptors if it was handling a large
number of nonblocking sockets or pipes with high congestion. (JL)

3/15/96 (bug fix) Fixed tests so that they no longer leak file descriptors.
The manifestation was that Tcl would eventually run out of file descriptors
if the tests were rerun many times (> a hundred times on Solaris). (JL)

3/15/96 (bug fix) Fixed channel creation code so that it never creates
unnamed channels. This would cause a panic and core dump when the channel
was closed. (JL)

3/16/96 (bug fixes) Made lots of changes in configuration stuff to get
Tcl working under AIX (finally).  Tcl should now support the "load"
command under AIX and should work either with or without shared
libraries for Tcl and Tk. (JO)

3/21/96 (configuration improvement) Changed configure script so it
doesn't use version numbers (as in -ltcl7.5 and libtcl7.5.so) under
SunOS 4.1, where they don't work anyway.  (JO)

3/22/96 (new feature) Added C API Tcl_InterpDeleted that allows extension
writers to discover when an interpreter is being deleted. (JL)

3/22/96 (bug fix) The standard IO channels are now added to each
trusted interpreter as soon as the interpreter is created. This ensures
against the bug where a child would do IO before the master had done any,
and then the child is destroyed - the standard IO channels would be then
closed and the master would be unable to do any IO. (JL)

3/22/96 (bug fix) Made Tcl more robust against interpreter deletion, by
using Tcl_Preserve, Tcl_Release and Tcl_EventuallyFree to split the process
of interpreter deletion into two distinct phases. Also went through all of
Tcl and added calls to Tcl_Preserve and Tcl_Delete where needed. (JL)

3/22/96 (bug fix) Fixed several places where C code was reading and writing
into freed memory, especially during interpreter deletion. (JL)

3/22/96 (bug fix) Fixed very deep bug in Tcl_Release that caused memory to
be freed twice if the release callback did Tcl_Preserve and Tcl_Release on
the same memory as the chunk currently being freed. (JL)

3/22/96 (bug fix) Removed several memory leaks that would cause memory
buildup on half-K chunks in the generic IO level. (JL)

3/22/96 (bug fix) Fixed several core dumps which occurred when new
AssocData was being created during the cleanups in interpreter deletion.
The solution implemented now is to loop repeatedly over the AssocData until
none is left to clean up. (JL)

3/22/96 (bug fix) Fixed a bug in event handling which caused an infinite
loop if there were no files being watched and no timer. Fix suggested by
Jan Nijtmans. (JL)

3/22/96 (bug fix) Fixed Tcl_CreateCommand, Tcl_DeleteCommand to be more
robust if the interpreter is being deleted. Also fixed several order
dependency bugs in Tcl_DeleteCommand which kicked in when an interpreter
was being deleted. (JL)

3/26/96 (bug fix) Upon a "short read", the generic code no longer calls
the driver for more input. Doing this caused blocking on some platforms
even on nonblocking channels. Bug and fix courtesy Mark Roseman. (JL)

3/26/96 (new feature) Added 'package Tcltest' which is present only in
test versions of Tcl; this allows the testing commands to be loaded into
new interpreters besides the main one. (JL)

3/26/96 (restored feature) Recreated the Tcl_GetOpenFile C API. You can
now get a FILE * from a registered channel; Unix only. (JL)

3/27/96 (bug fix) The regular expression code did not support more
than 9 subexpressions.  It now supports up to 20. (SS)

4/1/96 (bug fixes) The CHANNEL_BLOCKED bit was being left on on a short
read, so that fileevents wouldn't fire correctly. Bug reported by Mark
Roseman.(JL, RJ)

4/1/96 (bug fix) Moved Tcl_Release to match Tcl_Preserve exactly, in
tclInterp.c; previously interpreters were being freed only conditionally
and sometimes not at all. (JL)

4/1/96 (bug fix) Fixed error reporting in slave interpreters when the
error message was being generated directly by C code. Fix suggested by
Viktor Dukhovni of ESM. (JL)

4/2/96 (bug fixes) Fixed a series of bugs in Windows sockets that caused
events to variously get lost, to get sent multiple times, or to be ignored
by the driver. The manifestation was blocking if the channel is blocking,
and either getting EAGAIN or infinite loops if the channel is nonblocking.
This series of bugs was found by Ian Wallis of Cisco. Now all tests (also
those that were previously commented out) in socket.test pass.  (JL, SS)

4/2/96 (feature change/bug fix) Eliminated network name support in
favor of better native name support.  Added "file split", "file join",
and "file pathtype" commands.  See the "file" man page for more
details. (SS)
*** INCOMPATIBILITY with Tcl 7.5b3, but not with Tcl 7.4 ***

4/2/96 (bug fix) Changed implementation of auto_mkindex so tclIndex
files will properly handle path names in a cross platform context. (SS)

4/5/96 (bug fix) Fixed Tcl_ReadCmd to use the channel buffer size as the
chunk size it reads, instead of a fixed 4K size. Thus, on large reads, the
user can set the channel buffer size to a large size and the read will
occur orders of magnitude faster. For example, on a 2MB file, reading in 4K
chunks took 34 seconds, while reading in 1MB chunks took 1.5 seconds (on a
SS-20). Problem identified and fix suggested by John Haxby of HP. (JL)

4/5/96 (bug fix) Fixed socket creation code to invoke gethostbyname only if
inet_addr failed (very unlikely). Before this change the order was reversed
and this made things much slower than they needed to be (gethostbyname
generally requires an RPC, which is slow). Problem identified and fix
suggested by John Loverso of OSF. (JL)

4/9/96 (feature change) Modified "auto" translation mode so that it
recognizes any of "\n", "\r" and "\r\n" in input as end of line, so
that a file can have mixed end-of-line sequences. It now outputs
the platform specific end of line sequence on each platform for files and
pipes, and for sockets it produces crlf in output on all platforms. (JL)
*** INCOMPATIBILITY with Tcl 7.5b3, but not with Tcl 7.4 ***

4/11/96 (new feature) Added -eofchar option to Tcl_SetChannelOption to allow
setting of an end of file character for input and output. If an input eof
char is set, it is recognized as EOF and further input from the channel is
not presented to the caller. If an output eof char is set, on output, that
byte is appended to the channel when it is closed. On Unix and Macintosh,
all channels start with no eof char set for input or output. On Windows,
files and pipes start with input and output eof chars set to Crlt-Z (ascii
26), and sockets start with no input or output eof char. (JL)
*** INCOMPATIBILITY with Tcl 7.5b3, but not with Tcl 7.4 ***

4/17/96 (bug fix) Fixed series of bugs with handling of crlf sequence split
across buffer boundaries in input, in AUTO mode. (JL, BW)

4/17/96 (test suite improvement) Fixed test suite so that tests that
depend on the availability of Unix commands such as echo, cat and others
are not run if these commands are not present. (JL)

4/17/96 (test suite improvement) The socket test now automatically starts,
on platformst that support exec, a separate process for remote testsing. (JL)

----------------- Released 7.5, 4/21/96 -----------------------

5/1/96 (bug fix) "file tail ~" did not correctly return the tail
portion of the user's home directory. (SS)

5/1/96 (bug fix) Fixed bug in TclGetEnv where it didn't lookup environment
variables correctly:  could confuse "H" and "HOME", for example.  (JO)

5/1/96 (bug fix) Changed to install tclConfig.sh under "make install-binaries",
not "make install-libraries".  (JO)

5/2/96 (bug fix) Changed pkg_mkIndex not to attempt to "load" a file unless
it has the standard shared library extension.  On SunOS, attempts to load
Tcl scripts cause the whole application to be aborted (there's no way to
get the error back into Tcl).  (JO)

5/7/96 (bug fix) Moved initScript in tclUnixInit.c to writable memory to
avoid potential core dumps. (JO)

5/7/96 (bug fix) Auto_reset procedure was removing procedure from init.tcl,
such as pkg_mkIndex.  (JO)

5/7/96 (bug fix) Fixed cast on socket address resolution code that
would cause a failure to connect on Dec Alphas. (JL)

5/7/96 (bug fix) Added "time", "subst" and "fileevent" commands to set of
commands available in a safe interpreter. (JL)

5/13/96 (bug fix) Preventing OS level handles for stdin, stdout and stderr
from being implicitly closed when the last reference to the standard
channel containing that handle is discarded when an interpreter is deleted.
Explicitly closing standard channels by using "close" still works. (JL)

5/21/96 (bug fix) Do not create channels for stdin, stdout and stderr on
Unix if the devices are closed. This prevents a duplicate channel name
panic later on when the fd is used to open a channel and the channel is
registered in an interpreter. (JL)

5/23/96 (bug fix) Fixed bug that prevented the use of standard channels in
interpreters created after the last interpreter was destroyed. In the sequence

	interp = Tcl_CreateInterp();
	Tcl_DeleteInterp(interp);
	interp = Tcl_CreateInterp();

channels for stdio would not be available in the second interpreter. (JL)

5/23/96 (bug fix) Fixed bug that allowed Tcl_MakeFileChannel to create new
channels with Tcl_Files in them that are already used by another channel.
This would cause core dumps when the Tcl_Files were being freed twice. (JL)

5/23/96 (bug fix) Fixed a logical timing bug that caused a standard channel
to be removed from the standard channel table too early when the channel
was being closed. If the channel was being flushed asynchronously, it could
get recreated before being actually destroyed, and the recreated channel
would contain the same Tcl_File as the one being closed, leading to
dangling pointers and core dumps. (JL)

5/27/96 (bug fix) Fixed a bug in Tcl_GetChannelOption which caused it to
always return a list of one element, a list of the settings, for
-translation and -eofchar options. Now correctly returns the value
described by the documentation (Mark Diekhans found this, thanks!). (JL)

5/30/96 (bug fix) Fixed a couple of syntax errors in io.test. (JL)

5/30/96 (bug fix) If a fileevent scripts gets an error, delete it before
causing a background error. This is to allow the error handler to reinstall
the fileevent and to prevent infinite loops if the event loop is reentered
in the error handler. (JL)

5/31/96 (bug fix) Channels now will get properly flushed on exit. (JL)

6/5/96 (bug fix) Changed Tcl_Ckalloc, Tcl_Ckfree, and Tcl_Ckrealloc to
Tcl_Alloc, Tcl_Free, and Tcl_Realloc.  Added documentation for these
routines now that they are officially supported.  Extension writers
should use these routines instead of free() and malloc(). (SS)

6/10/96 (bug fix) Changes the Tcl close command so that it no longer
waits on nonblocking pipes for the piped processes to exit; instead it
reaps them in the background. (JL)

6/11/96 (bug fix) Increased the length of the listen queue for server
sockets on Unix from 5 to 100. Some OSes will disregard this and reset it
to 5, but we should try to get as long a queue as we can, for performance
reasons. (JL)

6/11/96 (bug fix) Fixed windows sockets bug that caused a cascade of events
if the fileevent script read less than was available. Now reading less than
is available does not cause a flood of Tcl events. (JL, SS)

6/11/96 (bug fix) Fixed bug in background flushing on closed channels that
would prevent the last buffer from getting flushed. (JL)

6/13/96 (bug fix) Fixed bug in Windows sockets that caused a core dump if
a DLL linked with tcl.dll and referred to e.g. ntohs() without opening a
Tcl socket. The problem was that the indirection table was not being
initialized. (JL)

6/13/96 (bug fix) Fixed OS level resource leak that would occur when a
Tcl channel was still registered in some interpreter when the process
exits. Previously the channel was not being closed and the OS level handles
were not being released; the output was being flushed but the device was
not being closed. Now the device is properly closed. This was only a
problem on Win3.1 and MacOS. (JL, SS)

6/28/96 (bug fix) Fixed bug where transient errors were leaving an error
code around, so that it would erroneously get reported later. This bug was
exercised intermittently by closing a channel to a file on a very loaded
NFS server, or to a socket whose other end blocked. (JL, BW)

7/3/96 (bug fix) Fileevents declared in an interpreter are now deleted
when the channel is closed in that interpreter. Before this fix, the
fileevent would hang around until the channel is completely closed, and
would cause errors if events happened before the channel was closed. This
could happen in two cases: first if the channel is shared between several
interpreters, and second if an async flush is in progress that prevents the
channel from being closed until the flush finishes. (JL)

7/10/96 (bug fix) Fixed bugs in both "lrange" and "lreplace" commands
where too much white space was being removed. For example, the command
		lreplace {\}\     hello} end end
was returning "\}\", losing the significant space in the first list
element and corrupting the list. (JO)

7/20/96 (bug fix) The procedure pkg_mkIndex didn't work properly for
extensions that depend on Tk, because it didn't load Tk into the child
interpreter before loading the extension.  Now it loads Tk if Tk is
present in the parent. (JO)

7/23/96 (bug fix) Added compat version of strftime to fix crashes
resulting from bad implementations under Windows. (SS)

7/23/96 (bug fix) Standard implementations of gmtime() and localtime()
under Windows did not handle dates before 1970, so they were replaced
with a revised implementation. (SS)

7/23/96 (bug fix) Tcl would crash on exit under Borland 5.0 because
the global environ pointer was left pointing to freed memory. (SS)

7/29/96 (bug fix) Fixed memory leak in Tcl_LoadCmd that could occur if
a package's AppInit procedure called Tcl_StaticPackage to register
static packages. (JO)

8/1/96 (bug fix) Fixed a series of bugs in Windows sockets so that async
writebehind in the presence of read event handlers now works, and so that
async writebehind also works on sockets for which a read event handler was
declared and whose channels were then closed before the async write
finished. The bug was reported by John Loverso and Steven Wahl,
independently, test case supplied by John Loverso. (JL)

----------------- Released patch 7.5p1, 8/2/96 -----------------------

5/8/96 (new feature) Added Tcl_GetChannelMode C API for retrieving whether
a channel is open for reading and writing. (JL)

5/8/96 (API changes) Revised C APIs for channel drivers:
    - Removed all Tcl_Files from channel driver interface; you can now have
      channels that are not based on Tcl_Files.
    - Added channelReadyProc and watchChannelProc procedures to interface;
      these are used to implement event notification for channels.
    - Added getFileProc to channel driver, to allow the generic IO code
      to retrieve a Tcl_File from a channel (presumably if the channel
      uses Tcl_Files they will be stored inside its instanceData). (JL)
*** INCOMPATIBILITY with Tcl 7.5 ***

5/8/96 (API change) The Tcl_CreateChannel C API was modified to not take
Tcl_File arguments, and instead to take a mask specifying whether the
channel is readable and/or writable. (JL)
*** INCOMPATIBILITY with Tcl 7.5 ***

6/3/96 (bug fix) Made Tcl_SetVar2 robust against the case where the value
of the variable is a NULL pointer instead of "". (JL)

6/17/96 (bug fix) Fixed "reading uninitialized memory" error reported by
Purify, in Tcl_Preserve/Tcl_Release. (JL)

8/9/96 (bug fix) Fixed bug in init.tcl that caused incorrect error message
if the act of autoloading a procedure caused the procedure to be invoked
again. (JO)

8/9/96 (bug fix) Configure script produced bad library names and extensions
under SunOS and a few other platforms if the --disable-load switch was used.
(JO)

8/9/96 (bug fix) Tcl_UpdateLinkedVar generated an error if the variable
being updated was read-only. (JO)

8/14/96 (bug fix) The macintosh now supports synchronous socket
connections.  Other minor bugs were also fixed. (RJ)

8/15/96 (configuration improvement) Changed the file patchlevel.h
to be tclPatch.h.  This avoids conflict with the Tk file and is now
in 8.3 format on the Windows platform. (RJ)

8/20/96 (bug fix) Fixed core dump in interp alias command for interpreters
created with Tcl_CreateInterp (as opposed to with Tcl_CreateSlave). (JL)

8/20/96 (bug fix) No longer masking ECONNRESET on Windows sockets so
that the higher level of the IO mechanism sees the error instead of
entering an infinite loop. (JL)

8/20/96 (bug fix) Destroying the last interpreter no longer closes the
standard channels. (JL)

8/20/96 (bug fix) Closing one of the stdin, stdout or stderr channels and
then opening a new channel now correctly assigns the new channel as the
standard channel that was closed. (JL)

8/20/96 (bug fix) Added code to unix/tclUnixChan.c for using ioctl with
FIONBIO instead of fcntl with O_NONBLOCK, for those versions of Unix where
either O_NONBLOCK is not supported or implemented incorrectly. (JL)

8/21/96 (bug fix) Fixed "file extension" so it correctly returns the
extension on files like "foo..c" as "..c" instead of ".c". (SS)

8/22/96 (bug fix) If environ[] contains static strings, Tcl would core
dump in TclSetupEnv because it was trying to write NULLs into the actual
data in environ[]. Now we instead copy as appropriate. (JL)

8/22/96 (added impl) Added missing implementation of Tcl_MakeTcpClientChannel
for Windows platform. Code contributed by Mark Diekhans. (JL)

8/22/96 (new feature) Added a new memory allocator for the Macintosh
version of Tcl.  It's quite a bit faster than MetroWerk's version. (RJ)

8/26/96 (documentation update) Removed old change bars (for all changes
in Tcl 7.5 and earlier releases) from manual entries. (JO)

8/27/96 (enhancement) The exec and open commands behave better and work in
more situations under Windows NT and Windows 95.  Documentation describes
what is still lacking. (CS)

8/27/96 (enhancement) The Windows makefiles will now compile even if the
compiler is not in the path and/or the compiler's environment variables
have not been set up. (CS)

8/27/96 (configuration improvement) The Windows resource files are
automatically updated when the version/patch level changes.  The header file
now has a comment that reminds the user which other files must be manually
updated when the version/patch level changes. (CS)

8/28/96 (new feature) Added file manipulation features (copy, rename, delete,
mkdir) that are supported on all platforms. They are implemented as
subcommands to the "file" command. See the documentation for the "file"
command for more information. (JH)

----------------- Released 7.6b1, 8/30/96 -----------------------

9/3/96 (bug fix) Simplified code so that standard channels are created
lazily, they are added to an interpreter lazily, and they are never added
to a safe interpreter. (JL)

9/3/96 (bug fix) Closing a channel after closing a standard channel, e.g.
stdout, would cause the implicit recreation of that standard channel. (JL)

9/3/96 (new feature) Now calling Tcl_RegisterChannel with a NULL
interpreter increments the refcount so that code outside any interpreter
can use channels that are also registered in interpreters, without worrying
that the channel may turn into a dangling pointer at any time. Calling
Tcl_UnregisterChannel with a NULL interpreter only decrements the recount
so that code outside any interpreter can safely declare it is no longer
interested in a channel. (JL)

9/4/96 (new features) Two changes to dynamic loading:
    - If the file name is empty in the "load" command and there is no
      statically loaded version of the package, a dynamically loaded
      version will be used if there is one.
    - Tcl_StaticPackage ignores redundant calls for the same package. (JO)

9/6/96 (bug fix) Platform specific procedures for manipulating files are
no longer macros and have been prefixed with "Tclp", such as TclpRenameFile.
Unix file code now handles symbolic links and other special files correctly.
The semantics of file copy and file rename has been changed so that if
a target directory exists, the source files will NOT be merged with the
existing files. (JH)

9/6/96 (bug fix) If standard channel is NULL, because Tcl cannot connect
to the standard channel, do not increment the refcount. The channel can
be NULL if there is for example no standard input. (JL)

9/6/96 (portability improvement) Changed parsing of backslash sequences
like \n to translate directly to absolute values like 0xA instead of
letting the compiler do the translation.  This guarantees that the
translation is done the same everywhere. (JO)

9/9/96 (bug fix) If channel is opened and not associated with any
interpreter, but Tcl decides to use it as one of the standard channels, it
became impossible to close the channel with Tcl_Close -- instead you had
to call Tcl_UnregisterChannel. Fixed now so that it's safe to call
Tcl_Close even when Tcl is using the channel as one of the standard ones. (JL)

9/11/96 (feature change) The Tcl library is now placed in the Tcl
shared libraries resource.  You no longer need to place the Tcl files
in your applications explicitly.  (RJ)

9/11/96 (feature change) Extensions no longer automatically have the
resource fork of the extension opened for it.  Instead you need to
use the tclMacLibrary.c file in your extension.  (RJ)
*** POTENTIAL INCOMPATIBILITY ***

9/12/96 (bug fix) The extension loading mechanism on the Macintosh now
looks at the 'cfrg' resource to determine where to load the code
fragment from.  This means FAT fragments should now work. (RJ)

9/18/96 (enhancement) The exec and open commands behave better and work in
more situations under Windows 3.X.  Documentation describes what is still
lacking.  (CS)

9/19/96 (bug fix) Fixed a panic which would occur if you delete a
non-existent alias before any aliases are created. Now instead correctly
returns an error that the alias is not found. (JL)

9/19/96 (bug fix) Slave interpreters could rename aliases and they would
not get deleted when the alias was being redefined. This led to dangling
pointers etc. (JL)

9/19/96 (bug fix) Fixed a panic where a hash table entry was being deleted
twice during alias management operations. (JL)

9/19/96 (bug fix) Fixed bug in event loop that could cause the input focus
in Tk to get confused during menu traversal, among other problems.  The
problem was related to handling of the "marker" when its event was
deleted. (JO)

9/26/96 (bug fix) Windows was losing EOF on a socket if the FD_CLOSE event
happened to precede any left over FD_READ events. Now correctly remembers
seeing FD_CLOSE, so that trailing FD_READ events are not discarded if they
do not contain any data. This allows Tcl to correctly get a zero read and
notice EOF. (JL)

9/26/96 (bug fix) Was not resetting READABLE state properly on sockets
under Windows if the driver discarded an FD_READ event because no data was
present. Now correctly resets the state. (JL)

9/30/96 (bug fix) Made EOF sticky on Windows sockets, so that fileevent
readable will fire repeatedly until the socket is closed. Previously the
fileevent fired only once. This could lead to never-closed connections if
the Tcl script in the fileevent wasn't closing the socket immediately. (JL)

10/2/96 (new feature) Improved the package loader:
    - Added new variable tcl_pkgPath, which holds the default
      directories under which packages are normally installed (each
      package goes in a separate subdirectory of a directory in
      $tcl_pkgPath).  These directories are included in auto_path by
      default.
    - Changed the package auto-loader to look for pkgIndex.tcl files
      not only in the auto_path directories but also in their immediate
      children.  This should make it easier to install and uninstall
      packages (don't have to change auto_path or merge pkgIndex.tcl
      files). (JO)

10/3/96 (bug fix) Changed tclsh to look for tclshrc.tcl instead of
tclsh.rc on startup under Windows.  This is more consistent with wish and
uses the right extension. (SS)
*** POTENTIAL INCOMPATIBILITY ***

10/8/96 (bug fix) Convertclock does not parse 24-hour times of the
form "hhmm" correctly when hour = 00.  In the parse code, hour must be
>= 100 for minutes to be non-zero.  Thanks to Lint LaCour for this
bug fix. (RJ)

10/11/96 (bug fix) Under Windows, the pid command returned the process
handle instead of the process id. (SS)

----------------- Released 7.6, 10/16/96 -----------------------

10/29/96 (bug fix) Under Windows, sockets would consume 100% CPU time after
the first accept(), due to a typo. (JL)

10/29/96 (bug fix) Incorrect refcount management caused standard channels
not to get deleted at process exit or DLL unload time, causing a memory
leak of upwards of 20K each time. (JL)

11/7/96 (bug fix) Auto-exec didn't work on file names that contained
spaces. (JO)

11/8/96 (bug fix) Fixed core dump that would occur if more than one call
to Tcl_DeleteChannelHandler was made to delete a given channel handler. (JL)

11/8/96 (bug fix) Fixed test for return value in Tcl_Seek and Tcl_SeekCmd
to only treat -1 as error, instead of all negative numbers. (JL)

11/12/96 (bug fix) Do not blocking waiting for processes at the end of a
pipe during exit cleanup. (JL)

11/12/96 (bug fix) If we are in exit cleanup, do not close the system level
file descriptors 0, 1 and 2. Previously they were being closed which is
incorrect, in the embedded case. This led to weird behavior for programs
that want to interpose on I/O through the standard file descriptors (e.g.
Netscape Navigator). (JL)

11/15/96 (bug fix) Fixed core dump on Windows sockets due to dependency on
deletion order at exit. Now all socket functions check to see if sockets
are (still) initialized, before calling through function pointers. Before,
they would call and might end up calling unloaded object code. (JL)

11/15/96 (bug fix) Fixed core dump in Windows socket initialization routine
if sockets were not installed on the system. Before, it was not properly
checking the result of attempting to load the socket DLL, so it would call
through uninitialized function pointers. (JL)

11/15/96 (bug fix) Fixed memory leak in Windows sockets which left socket
DLL handle open and could hold the socket DLL in memory uneccessarily,
until a reboot. (JL)

12/4/96 (bug fix) Fixed bug in Macintosh socket code that could result
in lost data if a client was closed too soon after sending data. (RJ)

12/17/96 (bug fix) Fixed deadlock bug in Windows sockets due to losing an
event. This was happening because of an interaction between buffering and
nonblocking mode on sockets. Now switched to sockets being blocking by
default, so we are also no longer emulating blocking through a private
event loop. (JL)

1/21/97 (performance bug fix) Client TCP connections were slow to create
because getservbyname was always called on the port.  Now this is only
done if Tcl_GetInt fails. (BW)

1/21/97 (configuration fix) Made it possible to override TCL_PACKAGE_PATH
during make.  Previously it was only set during autoconf process.

1/29/97 (bug fix) Fixed some problems with the clock command that
impacted how dates were scaned after the year 2000. (RJ)

----------------- Released 7.6p2, 1/31/97 -----------------------

2/5/97 (bug fix) Fixed a bug where in CR-LF translation mode, \r bytes
in the input stream were not being handled correctly. (JL)

2/24/97 (bug fix) Fix bug with exec under Win32s not being able to create
stderr file which caused all execs to fail.  Fixed temp file leak under
Win32s.  Fixed optional parameter bug with SearchPath that only happened
under Win32s 1.25. (CCS)

----------------------------------------------------------
Changes for Tcl 7.6 go above this line.
Changes for Tcl 7.7 go below this line.
----------------------------------------------------------

5/8/96 (new feature) Added Tcl_Ungets C API for putting a sequence of bytes
into a channel's input buffer. This can be used for "push" model channels
where the input is obtained via callbacks instead of by request of the
generic IO code. No Tcl procedure yet. (JL)

11/15/96 (new feature) Implemented hidden commands. New C APIs:
	Tcl_HideCommand		-- hides an existing exposed command.
	Tcl_ExposeCommand	-- exposes an existing hidden command.
New tcl APIs:
	interp invokehidden	-- invokes a hidden command in a slave.
	interp hide		-- hides an existing exposed command.
	interp expose		-- exposes an existing hidden command.
	interp hidden		-- returns a list of hidden commands.
The implementation of Safe Tcl now uses the new hidden commands facility
to implement the safe base, instead of deleting the commands from a safe
interpreter. (JL)

11/15/96 (new feature) Implemented the safe base, a mechanism for
installing and requesting security policies, purely in Tcl code. Overloads
the package command to also allow an interpreter to "require" a policy. The
following new library commands are provided:
	tcl_safeCreateInterp	-- creates a slave an initializes the
				   policy mechanism.
	tcl_safeInitInterp	-- initializes an existing slave with the
				   policy mechanism.
	tcl_safeDeleteInterp	-- deletes a slave and deinitializes the
				   policy mechanism.
Added a new file to the library, safeinit.tcl, to hold implementation. (JL)
On 7/9/97, removed the policy loading mechanism from the Safe Base. Left
only the Safe Base aliases dealing with auto-loading and source. (JL)

12/6/96 (new feature) Implemented Tcl_Finalize, an API that should be
called by a process when it is done using Tcl. This API runs all the exit
handlers to allow them to clean up resources etc. (JL)

12/17/96 (new feature) Add an http Tcl script package to the Tcl library.
This package implements the client side of HTTP/1.0; the GET, HEAD,
and POST requests. (BW)

1/21/97 (new feature) Added a "marktrusted" subcommand to the "interp" and
to the interpreter object command. It removes the "safe" mark on an
interpreter and disables hard-wired checks for safety in the C sources. (JL)

1/21/97 (removed feature) Removed "vwait" from set of commands available in
a safe interpreter. (JL)

2/11/97 (new feature, bug fix) http package.  Added -accept to http_config
so you can set the Accept header.  Added -handler option to http_get so
you can supply your own data handler.  Also fixed POST operation to
set the correct MIME type on the request. (BW)

----------------------------------------------------------
Changes for Tcl 7.7 go above this line.
Changes for Tcl 8.0 go below this line.
----------------------------------------------------------

9/17/96 (bug fix) Using "upvar" it was possible to turn an array element
into an array itself.  Changed to disallow this; it was quirky and didn't
really work correctly anyway. (JO)

10/21/96 (new feature) The core of the Tcl interpreter has been replaced
with an on-the-fly compiler that translates Tcl scripts to bytecoded
instructions; a new interpreter then executes the bytecodes. The compiler
introduces only a few minor changes at the level of Tcl scripts. The biggest
changes are to expressions and lists.
    - A second level of substitutions is no longer done for expressions.
      This substantially improves their execution time. This means that
      the expression "$x*4" produces a different result than in the past
      if x is "$y+2". Fortunately, not much code depends on the old
      two-level semantics. Some expressions that do, such as
      "expr [join $list +]" can be recoded to work in Tcl8.0 by adding
      an eval: e.g., "eval expr [join $list +]".
    - Lists are now completely parsed on the first list operation to
      create a faster internal representation. In the past, if you had a
      misformed list but the erroneous part was after the point you
      inserted or extracted an element, then you never saw an error.
      In Tcl8.0 an error will be reported. This should only effect
      incorrect programs that took advantage of behavior of the old
      implementation that was not documented in the man pages.
Other changes to Tcl scripts are discussed in the web page at
http://www.scriptics.com/doc/compiler.html. (BL)
*** POTENTIAL INCOMPATIBILITY ***

10/21/96 (new feature) In earlier versions of Tcl, strings were used as a
universal representation; in Tcl 8.0 strings are replaced with Tcl_Obj
structures ("objects") that can hold both a string value and an internal
form such as a binary integer or compiled bytecodes. The new objects make it
possible to store information in efficient internal forms and avoid the
constant translations to and from strings that occurred with the old
interpreter. There are new many new C APIs for managing objects. Some of the
new library procedures for objects (such as Tcl_EvalObj) resemble existing
string-based procedures (such as Tcl_Eval) but take advantage of the
internal form stored in Tcl objects for greater speed. Other new procedures
manage objects and allow extension writers to define new kinds of objects.
See the manual entries doc/*Obj*.3 (BL)

10/24/96 (bug fix) Fixed memory leak on exit caused by some IO related
data structures not being deallocated on exit because their refcount was
artificially boosted. (JL)

10/24/96 (bug fix) Fixed core dump in Tcl_Close if called with NULL
Tcl_Channel. (JL)

11/19/96 (new feature) Added library procedures for finding word
breaks in strings in a platform specific manner.  See the library.n
manual entry for more information. (SS)

11/22/96 (feature improvements) Added support for different levels of
tracing during bytecode compilation and execution. This should help in
tracking down suspected problems with the compiler or with converting
existing code to use Tcl8.0. Two global Tcl variables, traceCompile
and traceExec, can be set to generate tracing information in stdout:
    - traceCompile: 0  no tracing (default)
                    1  trace compilations of top level commands and procs
                    2  trace and display instructions for all compilations
    - traceExec:    0  no tracing
                    1  trace only calls to Tcl procs
                    2  trace invocations of all commands including procs
                    3  detailed trace showing the result of each instruction
traceExec >= 2 provides a one line summary of each called command and
its arguments. Commands that have been "compiled away" such as set are
not shown. (BL)

11/30/96 (bug fix) The command "info nameofexecutable" could sometimes
return the name of a directory. (JO)

11/30/96 (feature improvements) Changed the code in library/init.tcl
that reads in pkgIndex.tcl so that (a) it reads the files from child
directories before those in the parent, so that the parent gets
precedence, and (b) it doesn't quit if there is an error in a
pkgIndex.tcl file;  instead, it prints an error message on standard
error and continues. (JO)

10/5/96 (feature improvements) Partial implementation of binary string
support: the ability for Tcl string values to contain embedded null bytes.
Changed the Tcl object-based APIs to take a byte pointer and length pair
instead of a null-terminated C string. Modified several object type managers
to support binary strings but not, for example, the list type manager.
Existing string-based C APIs are unchanged and will truncate binary
strings. Compiled scripts containing nulls are also truncated. (BL)

12/12/96 (feature change) Removed the commands "cp", "mkdir", "mv",
"rm", and "rmdir" from the Macintosh version of Tcl.  They were never
officially supported and their functionality is now available via
the file command. (RJ)

----------------- Released 8.0a1, 12/20/96 -----------------------

1/7/97 (bug fix) Under Windows, "file stat c:" was returning error instead
of stat for current dir on c: drive.

1/10/97 (new feature) Added Tcl_GetIndexFromObj procedure for quick
lookups of keyword arguments. (JO)

1/12/97 (new feature) Serial IO channel drivers for Windows and Unix,
available by using Tcl open command to open pseudo-files like "com1:" or
"/dev/ttya".  New option to Tcl fconfigure command for serial files:
"-mode baud,parity,data,stop" to specify baud rate, parity, data bits, and
stop bits.  Serial IO is not yet available on Mac.

1/16/97 (feature change) Restored the Tcl7.x "two level substitution
semantics" for expressions. Expressions not enclosed in braces are
implemented, in general, by calling the expr command procedure
(Tcl_ExprObjCmd) at runtime after the Tcl interpreter has already done a
first round of substitutions. This is slow (about Tcl7.x speed) because new
code for the expression is generally compiled each time. However, if the
expression has only variable substitutions (and not command substitutions),
"optimistic" fast code is generated inline. This inline code will fail if a
second round of substitutions is needed (i.e., if the value of a substituted
variable itself requires more substitutions). The optimistic code will
catch the error and back off to call the slower but guaranteed correct
expr command procedure. (BL)

1/16/97 (feature improvements) Added Tcl_ExprLongObj and Tcl_ExprDoubleObj
to round out expression-related procedures. (BL)

1/16/97 (feature change) Under Windows, at startup the environment variables
"path", "comspec", and "windir" in any capitalization are converted
automatically to upper case.  The PATH variable could be spelled as path,
Path, PaTh, etc. and it makes programming rather annoying.  All other
environment variables are left alone. (CS)

1/20/97 (new features) Rewrote the "lsort" command:
    - The new version is based on reentrant merge sort code provided
      by Richard Hipp, so it eliminates the reentrancy and stability
      problems with the old qsort-based implementation.
    - The new version supports a -dictionary option for sorting, and
      it also supports a -index option for sorting lists using one
      element for comparison.
    - The new version is an object command, so it works well with the
      Tcl compiler, especially in conjunction with the new -index
      option.  When the -index option is used, this version of lsort
      is more than 100 times faster than the Tcl 7.6 lsort, which had
      to use the -command option to get the same effect. (JO)

1/20/97 (feature improvements) Added the improved debugging support for Tcl
objects prototyped by Karl Lehenbauer <karl@hammer1.ops.NeoSoft.com>.
If TCL_MEM_DEBUG is defined, the object creation calls use Tcl_DbCkalloc
directly in order to record the caller's source file name and line
number. (BL)

1/21/97 (removed feature) Desupported the tcl_precision variable: if
set, it is ignored.  Tcl now uses the full 17 digits of precision when
converting real numbers to strings (with the new object system real
numbers are rarely converted to strings so there is no efficiency
disadvantage to printing all 17 digits; the new scheme improves
accuracy and simplifies several APIs). (JO)
*** POTENTIAL INCOMPATIBILITY ***

1/21/97 (feature change) Removed the "interp" argument for the
procedures Tcl_GetStringFromObj, Tcl_StringObjAppend, and
Tcl_StringObjAppendObj.  Also removed the "interp" argument for
the updateStringProc procedure in Tcl_ObjType structures.  With
the tcl_precision changes above, these are no longer needed. (JO)
*** POTENTIAL INCOMPATIBILITY with Tcl 8.0a1, but not with Tcl 7.6 ***

1/22/97 (bug fix) Fixed http.tcl so that http_reset does not result in
an extra call to the command callback.  In addition, if the transaction
gets a premature eof, the state(status) is "eof", not "ok". (BW)

----------------- Released 8.0a2, 1/24/97 -----------------------

1/29/97 (feature change) Changed how two digit years are parsed in the
clock command.  The old interface just added 1900 which will seem
broken by the year 2000.  The new scheme follows the POSIX standard
and treats dates 70-99 as 1970-1999 and dates 00-38 as 2000-2038.  All
other two digit dates are undefined. (RJ)
*** POTENTIAL INCOMPATIBILITY ***

2/4/97 (bug fix) Fixed bug in clock code that dealt with relative
dates.  Using the relative month code you could get an invalid date
because it jumped into a non-existant day.  (For example, Jan 31
to Feb 31.)  The code now will return the last valid day of the
month in these situations.  Thanks to Hume Smith for sending in
this bug fix.  (RJ)

2/10/97 (feature change) Eliminated Tcl_StringObjAppend and
Tcl_StringObjAppendObj procedures, replaced them with Tcl_AppendToObj
and Tcl_AppendStringsToObj procedures.  Added new procedure
Tcl_SetObjLength. (JO)
*** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2, but not with Tcl 7.6 ***

2/10/97 (new feature) Added Tcl_WrongNumArgs procedure for generating
error messages about incorrect number of arguments. (JO)

2/11/97 (new feature, bug fix) http package.  Added -accept to http_config
so you can set the Accept header.  Added -handler option to http_get so
you can supply your own data handler.  Also fixed POST operation to
set the correct MIME type on the request. (BW)

2/22/97 (bug fix) Fixed bug that caused $tcl_platform(osVersion) to be
computed incorrectly under AIX. (JO)

2/25/97 (new feature, feature change) Added support for both int and long
integer objects. Added Tcl_NewLongObj/Tcl_GetLongFromObj/Tcl_SetLongFromObj
procedures and renamed the Tcl_Obj internalRep intValue member to
longValue. Tcl_GetIntFromObj now checks for integer values too large to
represent as non-long integers. Changed Tcl_GetAllObjTypes to
Tcl_AppendAllObjTypes. (BL)

3/5/97 (new feature) Added new Tcl_SetListObj procedure to round out
collection of procedures that set the type and value of existing Tcl
objects. (BL)

3/6/97 (new feature) Added -global flag for interp invokehidden. (JL)

3/6/97 (new feature, feature change) Added isNativeObjectProc field to the
Tcl_CmdInfo structure to indicate (when 1) if the command has an
object-based command procedure. Removed the nameLength arg from
Tcl_CreateObjCommand since command names can't contain null characters. (BL)

3/6/97 (bug fix) Fixed bug in "unknown" procedure that caused auto-
loading to fail on commands whose names begin with digits. (JO)

3/7/97 (bug fix) Auto-loading now works in Safe Base. Safe interpreters
only accept the Version 2 and onwards tclIndex files. (JL)

3/13/97 (bug fix) Fixed core dump due to interaction between aliases and
hidden commands. Bug found by Lindsay Marshall. (JL)

3/14/97 (bug fix) Fixed mac bugs relating to time.  The -gmt option
now adjusts the time in the correct direction.  (Thanks to Ed Hume for
reporting a fix to this problem.)  Also fixed file "mtime" etc. to
return times from GMT rather than local time zone.  (RJ)

3/18/97 (feature change) Declaration of objv in Tcl_ObjCmdProc function
changed from "Tcl_Obj *objv[]" to "Tcl_Obj *CONST objv[]".  All Tcl object
commands changed to use new declaration of objv.  Naive translation of
string-based command procs to object-based command procs could very easily
have yielded code where the contents of the objv array were changed.  This
is not a problem with string-based command procs, but doing something as
simple as objv[2] = objv[3] would corrupt the runtime stack and cause Tcl to
crash.  Introduced CONST in declaration of objv so that attempted assignment
of new pointer values to elements of the objv array will be caught by the
compiler. (CCS)
*** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2 ***

3/19/97 (bug fix) Fixed panic due to object sharing. The root cause was
that old code was using Tcl_ResetResult instead of Tcl_ResetObjResult. (JL)

3/20/97 (new feature) Added a new subcommand for the file
command. file attributes filename can give a list of platform-specific
options (such as file/creator type on the Mac, permissions on Unix) or
set the values of them. Added a new subcommand for the file
command. file nativename name gives back the platform-specific form
for the file. This is useful when the filename is needed to pass to
the OS, such as exec under Windows 95 or AppleScript on the Mac. For
more info, see file.n. (SRP)

3/24/97 (removed feature) Removed the tcl_safePolicyPath procedure. Now
the policy path is computed from the auto_path by appending the directory
'policies' to each element. Also fixed several bugs in automatic tracking
of auto_path by computed policy path. (JL)
*** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2 but not with Tcl 7.6 ***

4/8/97 (new feature) If the variable whose name is passed to lappend doesn't
already exist, and there are no value arguments, lappend now creates the
variable with an empty value instead of returning an error. Change suggested
by Tom Tromey. (BL)

4/9/97 (feature change) Changed the name of the TCL_PART1_NOT_PARSED flag to
TCL_PARSE_PART1. (BL)
*** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2 but not with Tcl 7.6 ***

4/10/97 (bug fixes) Fixed various compilation-related bugs:
    - "UpdateStringOfCmdName should never be invoked" panic.
    - Bad code generated for expressions not in {}'s inside catch commands.
    - Segmentation fault in some command procedures when two argument
      object pointers refer to the same object.
    - Second level of substitutions were never done for expressions not
      in {}'s that consist of a single variable reference: e.g.,
      "set x 27; set bool {$x}; if $bool {puts foo}" would fail with error.
    - Bad code generated when code storage was grown while compiling some
      expressions: ones with compilation errors or consisting of only a
      variable reference.
    - Bugs involving multiple interpreters: wasn't checking that a
      procedure's code was compiled for the same interpreter as the one
      executing it, and didn't invalidate code on hidden-exposed command
      transitions.
    - "Bad stack top" panic when executing scripts that require a huge
      amount of stack space.
    - Incorrect sharing of code for procedure bodies, and procedure code
      deallocated before last execution of the procedure finished.
    - Fixed compilation of expression words in quotes. For example,
      if "0 < 3" {puts foo}.
    - Fixed performance bug in array set command with large assignments.
    - Tcl_SetObjLength segmentation fault setting length of empty object.
    - If Tcl_SetObjectResult was passed the same object as the interpreter's
      result object, it freed the object instead of doing nothing. Bug fix
      by Michael J. McLennan.
    - Tcl_ListObjAppendList inserted elements from the wrong list. Bug fix
      by Michael J. McLennan.
    - Segmentation fault if empty variable list was specified in a foreach
      command. Bug fix by Jan Nijtmans.
    - NULL command name was always passed to Tcl_CreateTrace callback
      procedure.
    - Wrong string representation generated for the value LONG_MIN.
      For example, expr 1<<31 printed incorrectly on a 32 bit machine.
    - "set {a($x)} 1" stored value in wrong variable.
    - Tcl_GetBooleanFromObj was not checking for garbage after a numeric
      value.
    - Garbled "bad operand type" error message when evaluating expressions
      not surrounded by {}'s. (BL)

4/16/97 (new feature) The expr command now has the "rand()" and
"srand()" functions for getting random numbers in expr. (RJ)

4/23/97 (bug fix) Fixed core dump in bgerror when the error handler command
deletes the current interpreter. Found by Juergen Schoenwald. (JL)

4/23/97 (feature change) The notifier interfaces have been redesigned
to make embedding in applications with external event loops possible.
A number of interfaces in the notifier and the channel drivers have
changed.  Refer to the Notifier.3 and CrtChannel.3 manual entries for
more details. (SS)
*** POTENTIAL INCOMPATIBILITY ***

4/23/97 (removed feature) The Tcl_File interfaces have been removed.
The Tcl_CreateFileHandler/Tcl_DeleteFileHandler interfaces now take
Unix fd's and are only supported on the Unix platform.
Tcl_GetChannelFile has been replaced with Tcl_GetChannelHandle.
Tcl_MakeFileChannel now takes a platform specific file handle. (SS)
*** POTENTIAL INCOMPATIBILITY ***

4/23/97 (removed feature) The modal timeout interface has been
removed (Tcl_CreateModalTimeout/Tcl_DeleteModalTimeout) (SS)
*** POTENTIAL INCOMPATIBILITY ***

4/23/97 (feature change) Channel drivers are now required to correctly
implement blocking behavior when they are in blocking mode. (SS)
*** POTENTIAL INCOMPATIBILITY ***

4/23/97 (new feature) Added the "binary" command for manipulating
binary strings. Also, changed the "puts", "gets", and "read" commands
to preserve embedded nulls.  (SS)

4/23/97 (new feature) Added tcl_platform(byteOrder) element to the
tcl_platform array to identify the native byte order for the current
host. (SS)

4/23/97 (bug fix) Fixed bug in date parsing around year boundaries. (SS)

4/24/97 (bug fix) In the process of copying a file owned by another user,
Tcl was changing the owner of the copy back to the owner of the original
file, therefore causing further file operations to fail because the current
user didn't own the copy anymore.  The owner of the copy is now left as the
current user. (CCS)

4/24/97 (feature change) Under Windows, don't automatically uppercase the
environment variable "windir" -- it's supposed to be lower case.  (CCS)

4/29/97 (new feature) Added namespace support based on a namespace
implementation by Michael J. McLennan of Lucent Technologies. A namespace
encapsulates a collection of commands and variables to ensure that they
won't interfere the commands and variables of other namespaces. The global
namespace holds all global variables and commands. Additional namespaces are
created with the new namespace command. The new variable command lets you
create Tcl variables inside a namespace. The names of Tcl variables and
commands may now be qualified by the name of the namespace containing them.
The key namespace-related commands are summarized below:
    - namespace ?eval? name arg ?arg...?
         Used to define the commands and variables in a namespace.
         Optionally creates the namespace.
    - namespace export ?-clear? ?pattern pattern...?
         Specifies which commands are exported from a namespace. These
         are the ones that can be imported into another namespace.
    - namespace import ?-force? ?pattern pattern...?
         Makes the specified commands accessible in the current namespace.
    - namespace current
         Returns the name of the current namespace.
    - variable name ?value? ?name ?value?...?
         Creates one or more namespace variables. (BTL)

5/1/97 (bug fix) Under Windows, file times were reported in GMT.  Should be
reported in local time. (CCS)

5/2/97 (feature change) Changed the name of the two Tcl variables used for
tracing bytecode compilation and execution to tcl_traceCompile and
tcl_traceExec respectively. These variables are now documented in the
tclvars man page. (BL)

5/5/97 (new feature) Support "end" as the index for "lsort -index". (BW)

5/5/97 (bug fixes) Cleaned up the way the http package resets connections (BW)

5/8/97 (feature change) Newly created Tcl objects now have a reference count
of zero instead of one. This simplifies C code that stores newly created
objects in Tcl variables or in data structures such as list objects. That C
code must increment the new object's reference count since the variable or
data structure will contain a long-term reference to the object. Formerly,
when new objects started out with reference count one, it was necessary to
decrement the new object's reference count after the store to make sure it
was left with the correct value; this is no longer necessary. (BL)

5/9/97 (new feature) Added the Tcl_GetsObj interface that takes an
object reference instead of a dynamic string (as in Tcl_Gets). (SS)

5/12/97 (new feature) Added Tcl_CreateAliasObj and Tcl_GetAliasObj C APIs
to allow an alias command to be created with a vector of Tcl_Obj structures
and to get the vector back later. (JL)

5/12/97 (feature change) Changed Tcl_ExposeCommand and Tcl_HideCommand to
leave an object result instead of a string result. (JL)

5/14/97 (feature change) Improved the handling of the interpreter result.
This is still either an object or a string, but the two values are now kept
consistent unless some C code reads or writes interp->result directly. See
the SetResult man page for details. Removed the Tcl_ResetObjResult
procedure. (BL)
*** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2 ***

5/16/97 (new feature) Added "fcopy" command to move data between
channels.  Refer to the manual page for more information.  Removed the
"unsupported0" command since it is obsolete now.  (SS)

5/16/97 (new feature) Added Tcl_GetStringResult procedure to allow programs
to get an interpreter's result as a string. If the result was previously set
to an object, this procedure will convert the object to a string. Use of
Tcl_GetStringResult is intended to replace direct access to interp->result,
which is not safe. (BL)

5/20/97 (new features) Fixed "fcopy" to return the number of bytes
transferred in the blocking case.  Updated the http package to use
fcopy instead of unsupported0.  Added -timeout and -handler options to
http_get.  http_get is now blocking by default.  It is only non-blocking
if you supply a -command argument. (BW)

5/22/97 (bug fix) Fixed several bugs in the "lsort" command having to do
with the -dictionary option and the presence of numbers embedded in the
strings.  (JO)

----------------- Released 8.0b1, 5/27/97 -----------------------

6/2/97 (bug fix) Fixed bug in startup code that caused a problem in
finding the library files when they are installed in a directory
containing a space in the name. (SS)

6/2/97 (bug fix) Fixed bug in Unix notifier where the select mask was
not being cleared under some circumstances. (SS)

6/4/97 (bug fix) Fixed bug that prevented creation of Tk widgets in
namespaces. Tcl_CreateObjCommand and Tcl_CreateCommand now always create
commands in the global namespace unless the command names are qualified. Tcl
procedures continue to be created in the current namespace by default. (BL)

6/6/97 (new features) Added new namespace API procedures
Tcl_AppendExportList and Tcl_Export to allow C code to get and set a
namespace's export list. (BL)

6/11/97 (new feature) Added Tcl_ConcatObj. This object-based routine
parallels the string-based routine Tcl_Concat. (SRP)

6/11/97 (new feature) Added Tcl_SetObjErrorCode. This object-based
routines parallels the string-based routine Tcl_SetErrorCode. (SRP)

6/12/97 (bug fix) Fix the "unknown" procedure so that wish under Windows
will exec an external program, instead of always complaining "console1 not
opened for writing". (CCS)

6/12/97 (bug fix) Fixed core dump experienced by the following simple
script:
	interp create x
	x alias exec exec
	interp delete x
This panic was caused by not installing the new CmdDeleteProc when exec
got redefined by the alias creation step. Reported by Lindsay Marshal (JL)

6/13/97 (new features) Tcl objects newly created by Tcl_NewObj now have a
string representation that points to a shared heap string of length 1. (They
used to have NULL bytes and typePtr fields. This was treated as a special
case to indicate an empty string, but made type manager implementations
complex and error prone.) The new procedure Tcl_InvalidateStringRep is used
to mark an object's string representation invalid and to free any storage
associated with the old string representation. (BL)
*** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl7.6 ***

6/16/97 (bug fix) Tcl_ScanCountedElement could leave braces unmatched
if the string ended with a backslash. (JO)

6/17/97 (bug fix) Fixed channel event bug where readable events would be
lost during recursive events loops if the input buffers contained
data. (SS)

6/17/97 (bug fix) Fixed bug in Windows socket code that didn't
reenable read events in the case where an external entity is also
reading from the socket. (SS)

6/18/97 (bug fix) Changed initial setting of the notifier service mode
to TCL_SERVICE_NONE to avoid unexpected event handling during
initialization. (SS)

6/19/97 (bug fix/feature change) The command callback to fcopy is now
called in case of errors during the background copy.  This adds a second,
optional argument to the callback that is the error string.  The callback
in case of errors is required for proper cleanup by the user of fcopy. (BW)
*** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl 7.6 ***

6/19/97 (bug fix) Fixed a panic due to the following four line script:
	interp create x
	x alias foo bar
	x eval rename foo blotz
	x alias foo {}
The problem was that the interp code was not using the actual current name
of the command to be deleted as a result of un-aliasing foo. (JL)

6/19/97 (feature change) Pass interp down to the ChannelOption and
driver specific calls so system errors can be differentiated from syntax
ones. Changed Tcl_DriverGetOptionProc type. Affects Tcl_GetChannelOption,
TcpGetOptionProc,  TtyGetOptionProc, etc. (DL)
*** POTENTIAL INCOMPATIBILITY ***

6/19/97 (new feature) Added Tcl_BadChannelOption for use by by driver
specific option procedures (Set and Get) to return a complete and
meaningful error message. (DL)

6/19/97 (bug fixes) If a system call error occurs while doing an
fconfigure on tcp or tty/com channel: return the appropriate error
message (instead of the syntax error one or none). (Fixed for Unix and
most of the Win and Mac drivers). (DL)

6/20/97 (feature change) Eval is no longer assumed as the subcommand name
in namespace commands: you must now write "namespace eval nsName {...}".
Abbreviations of namespace subcommand names are now allowed. (BL)
*** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl7.6 ***

6/20/97 (feature change) Changed the errorInfo traceback message for
compilation errors from "invoked from within" to "while compiling". (BL)

6/20/97 (bug fixes) Fixed various compilation-related bugs:
    - "UpdateStringOfCmdName should never be called" and
      "UpdateStringOfByteCode should never be called" panics.
    - Segfault in TclObjInterpProc getting procedure name after evaluation
      stack is reallocated (grown).
    - Could not use ":" at end of variable and command names.
    - Bad code generated for while and for commands with test expressions
      enclosed in quotes: e.g., "set i 0; while "$i > 5" {}".
    - Command trace procedures would crash if they did a Tcl_EvalObj that
      reallocated the evaluation stack.
    - Break and continue commands did not reset the interpreter result.
    - The Tcl_ExprXXX routines, both string- or object-based, always
      modified the interpreter result even if there was no error.
    - The argument parsing procedure used by several compile procedures
      always treated "]" as end of a command: e.g., "set a ]" would fail.
    - Changed errorInfo traceback message for compilation errors from
      "invoked from within" to "while compiling".
    - Problem initializing Tcl object managers during interpreter creation.
    - Added check and error message if formal parameter to a procedure is
      an array element. (BL)

6/23/97 (new feature) Added "registry" package to allow manipulation
of the Windows system registry.  See manual entry for details. (SS)

6/24/97 (feature change) Converted http to a package and added the
http1.0 subdirectory of the Tcl script library.  This means you have
to do a "package require http" to use this, as advertised in the man page. (BW)
*** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl 7.6 ***

6/24/97 (bug fix) Ensure that Tcl_Set/GetVar C APIs, when called without
TCL_LEAVE_ERR_MSG, don't touch the interp result. (DL)

6/26/97 (feature change) Changed name of Tcl_ExprStringObj to
Tcl_ExprObj. (BL)
*** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl 7.6 ***

----------------- Released 8.0b2, 6/30/97 -----------------------

7/1/97 (new feature) TCL_BUILD_SHARED flag set in tclConfig.sh
when Tcl has been built with --enable-shared. A new tclLibObjs
make target, echoing the list of the .o's needed to build a tcl
library, is now provided. (DL)

7/1/97 (feature change) compat/getcwd.c removed and changed the
only place where getcwd is used so a new USEGETWD flag selects
the use of the replacement "getwd". Adding this flag is recommended
for SunOS 4 (because getcwd on SunOS 4 uses a pipe to pwd(1)!). (DL)

7/7/97 (feature change) The split command now supports binary data (i.e.,
null characters in strings). (BL)

7/7/97 (bug fix) string first returned the wrong result if the first
argument string was empty. (BL)

7/8/97 (bug fix) Fixed core dump in fcopy that could occur when a command
callback was supplied and an error or eof condition caused no background
activity.  A refcount bug triggered a panic in Tcl_ListObjAppendElement. (BW)

7/8/97 (bug fix) Relaxed the pattern matching on http_get so you do not
need a trailing path component.  You can now get away with just
http_get www.scriptics.com					(BW)

7/9/97 (bug fix) Creating anonymous interpreters no longer smashes existing
commands with names similar to the generated name. Previously creating an
anonymous interpreter could smash an existing command, now it skips until
it finds a command name that isn't being used. (JL)

7/9/97 (feature change) Removed the policy management mechanism from the
Safe Base; left the aliases to source and load modules, and to do a limited
form of the "file" command. See entry of 11/15/96. (JL)

7/9/97 (bug fixes) Fixed various compilation-related bugs:
    - Line numbers in errorInfo now are the same as those in Tcl7.6 unless
there are compilation errors. Compilation error messages now include the
entire command in error.
    - Trailing ::s after namespace names weren't being ignored.
    - Could not refer to an namespace variable with an empty name using a
name of the form "n::". (BL)

7/9/97 (bug fix) Fixed bug in Tcl_Export that prevented you from exporting
from other than the current namespace. (BL)

7/9/97 (bug fix) env.test was removing env var needed for proper finding
of libraries in child process. (DL)

7/10/97 (bug fixes/new feature) Cleanup in Tcl_MakeSafe. Less information
is leaked to safe interps. Error message fixes for interp sub commands.
Likewise changes in safealias.tcl; tcl_safeCreateInterp can now be called
without argument to generate the slave name (like in interp create). (DL)

7/10/97 (bug fixes) Bytecode compiler now generates more detailed
command location information: subcommands as well as commands now have
location information. This means command trace procedures now get the
correct source string for each command in their command parameter. (BL)

7/22/97 (bug fixes) Performance improvement in Safe interpreters
handling. Added new mask value to (tclInt.h) Interp.flags record. (DL)

7/22/97 (bug fix) Fixed panic in 'interp target {} foo'. This bug
was present since Tcl 7.6. (JL)

7/22/97 (bug fix) Fixed bug in compilation of procedures in namespaces: the
procedure's namespace must be used to look up compile procedures, not the
current namespace. (BL)

7/22/97 (bug fix) Use of the -channel option of http_get was not setting
the end of line translations mode on the channel, so copying binary data
with the -channel option was corrupting the result on non-unix platforms. (BW)

7/22/97 (bug fixes) file commands and ~user (seg fault and other
improper returns). (DL)

7/23/97 (feature change) Reenabled "vwait" in Safe Base. (JL)

7/23/97 (bug fixes) Fixed two bugs involving read traces on array variables
in procedures: trace procedures were sometimes not called, and reading
nonexistant array elements didn't create undefined element variables that
could later be defined by trace procedures. (BL)

7/24/97 (bug fix) Windows memory allocation performance was
superlinear in some cases.  Made the Mac allocator generic and changed
both the Mac and Windows platforms to use the new allocator instead of
malloc and free. (SS)

7/24/97 - 8/12/97 (bug fixes/change of features) Completely revamped safe
sourcing/loading (see safe.n) to hide pathnames, use virtual
paths tokens instead, improved security in several respects and made it
more tunable. Multi level interp loading can work too now. Package auto
loading now works in safe interps as long as the package directory is in
the auto_path (no deep crawling allowed in safe interps). (DL)
*** POTENTIAL INCOMPATIBILITY with previous alpha and beta releases ***

7/24/97 (bug fixes) Made Tcl_SetVar* and Tcl_NewString* treat a NULL value
as an empty string. (This fixes hairy crash case where you would crash
because load command for other interps assumed presence of
errorInfo...). (DL)

7/28/97 (bug fix) Fixed pkg_mkIndex to understand namespaces.  It will
use the export list of a namespace and create auto_index entries for
all export commands.  Those names are in their fully qualified form in the
auto_index.  Therefore, I tweaked unknown to try both $cmd and ::$cmd.
Also fixed pkg_mkIndex so you can have "package require" commands inside
your packages.  These commands are ignored, which is mostly ok except
when you must load another package before loading yours because of
linking dependencies. (BW)

7/28/97 (bug fix) A variable created by the variable command now persists
until the namespace is destroyed or the variable is unset. This is true even
if the variable has not been initialized; these variables used to be
destroyed if an error occurred when accessing them. In addition, the "info
vars" command lists uninitialized namespace variables, while the "info
exists" command returns 0 for them. (BL)

7/29/97 (feature change)  Changed the http package to use the ::http
namespace. http_get renamed to http::geturl, http_config renamed to
http::config, http_formatQuery renamed to http::formatQuery.
It now provides the 2.0 version of the package.
The 1.0 version is still available with the old names.
*** POTENTIAL INCOMPATIBILITY with Tcl 8.0b2 but not with Tcl 7.6 ***

7/29/97 (bug fix, new feature) Tcl_Main now uses Tcl objects internally to
preserve NULLs in commands and command output. Added new API procedure
Tcl_RecordAndEvalObj that resembles Tcl_RecordAndEval but takes an object
containing a command. (BL)

7/30/97 (bug fix) Tcl freed strings in the environ array even if it
did not allocate them. (SS)

7/30/97 (bug fix) If a procedure is renamed into a different namespace, it
now executes in the context of that namespace. (BL)

7/30/97 (bug fix) Prevent renaming of commands into and from namespaces as
part of hiding them. (JL)

7/31/97 (feature change) Moved the history command from C to tcl.
This uses the ::history namespace.  The "words" and "substitute" options
are no longer supported.  In addition, the "keep" option without a value
returns the current keep limit.  There is a new "clear" option.
The unknown command now supports !! again. (BW)
*** POTENTIAL INCOMPATIBILTY  ***

7/30/97 (bug fix) Made sure that a slave can not fool the master into
hiding the wrong command. Made sure we don't crash in hiding + namespaces
issues. (DL)

8/4/97 (bug fix) Concat, eval, uplevel, and similar commands were
incorrectly trimming trailing space characters from their arguments
even when the space characters were preceded by a backslash. (JO)

8/4/97 (bug fix) Removed the hard link between bgerror and tkerror.
Only bgerror is supported in tcl core. Tk will still look for a
tkerror but using regular tcl code for that feature. (DL)
*** POTENTIAL INCOMPATIBILTY with code relying on the hard link ***

8/6/97 (bug fix) Reduced size required for compiled bytecodes by using a
more compact encoding for the command pc-to-source map. (BL)

8/6/97 (new feature) Added support for additional compilation and execution
statistics when Tcl is compiled with the TCL_COMPILE_STATS flag. (BL)

8/7/97 (bug fix) Expressions not in {}s that have a comparison operator as
the topmost operator must be compiled out-of-line (call the expr cmd at
runtime) to properly support expr's two-level substitution semantics. An
example is "set a 2; set b {$a}; puts [expr $b == 2]". (BL)

8/11/97 (bug fix) The catch command would sometimes crash if a variable name
was given and the bytecode evaluation stack was grown when executing the
argument script. (BL)

8/12/97 (feature change) Reinstated the variable tcl_precision to control
the number of digits used when floating-point values are converted to
strings, with default of 12 digits.  However, had to make tcl_precision
shared among all interpreters (except that safe interpreters can't
modify it).  This makes the Tcl 8.0 behavior almost identical to 7.6
except that the default precision is 12 instead of 6. (JO)
*** POTENTIAL INCOMPATIBILITY ***

----------------- Released 8.0, 8/18/97 -----------------------

8/19/97 (bug fix) Minimal fix for glob -nocomplain bugs:
"glob -nocomplain unreadableDir/*" was generating an anonymous
error. More in depth fixes will come with 8.1. (DL).

8/20/97 (bug fix) Removed check for FLT_MIN in binary command so
underflow conditions are handled by the compiler automatic
conversions. (SS)

8/20/97 (bug fixes) Fixed several compilation-related bugs:
    - Array cmd wasn't detecting arrays that, while compiled, do not yet
      exist (e.g., are marked undefined since they haven't been assigned
      to yet).
    - The GetToken procedure in tclCompExpr.c wasn't recognizing properly
      whether an integer token was invalid. For example, "0x$" is not
      a valid integer.
    - Performance bug in TclExecuteByteCode: the size of its stack frame
      was reduced by over 20% by moving errorInfo code elsewhere.
    - Uninitialized memory read error in tclCompile.c. (BL)

8/21/97 (bug fix) safe::interpConfigure now behave like Tk widget's
configure : it changes only the options you provide and you can get
the current value of any single option. New ?-nested boolean? and
?-statics boolean? for all safe::interp* commands but we still
accept (upward compatibility) the previously defined non valued
flags ?-noStatics? and ?-nestedLoadOk?. Improved the documentation. (DL).

8/22/97 (bug fix) Updated PrintDbl.3 to reflect the fact that the
tcl_precision variable is still used and that it is now shared by all
interpreters. (BL)

8/25/97 (bug fix) Fixed array access bug in IllegalExprOperandType
procedure in tclExecute.c: it was not properly supporting the || and &&
operators. (BL)

8/27/97 (bug fix) In cases where a channel handler was created with an
empty event mask while data was still buffered in the channel, the
channel code would get stuck spinning on a timer that would starve
idle handlers.  This mostly happened in Tk when reading from stdin. (SS)

9/4/97 (bug fix) Slave interps now inherit the maximum recursion limit
of their parent instead of starting back at the default. {nb: this still
does not prevent stack overflow by multi-interps recursion or aliasing} (DL)

9/11/97 (bug fix) An uninitialized variable in Tcl_WaitPid caused
pipes to fail to report eof properly under Windows. (SS)

9/12/97 (bug fix) "exec" was misidentifying some DOS executables as not
executable. (CCS)

9/14/97 (bug fix) Was using the wrong structure in sizeof operation in
tclUnixChan.c. (JL)

9/15/97 (bug fix) Fixed notifier to break out of do-one-event loop if
Tcl_WaitForEvent returns 1, so that callers of Tcl_DoOneEvent will get
a chance to check whether the event just handled is significant. This
affected mainly recursive calls to Tcl_VWaitCmd; these did not get a
chance to notice that the variable they were waiting for has been set
and thus they didn't terminate the vwait. (JL, DL, SS)

9/15/97 (bug fix) Alignment problems in "binary format" would cause a
crash on some platforms when formatting floating point numbers. (SS)

9/15/97 (bug fix) Fixed bug in Macintosh socket code.  Now passes all
tests in socket.test that are not platform specific. (Thanks to Mark
Roseman for the pointer on the fix.)  (RJ)

9/18/97 (bug fix) Fixed bug -dictionary option of lsort that could
cause the compare function to run off the end of an array if the
number only contained 0's. (Thanks to Greg Couch for the report.) (RJ)

9/18/97 (bug fix) TclFinalizeEnvironment was not cleaning up
properly. (DL, JI)

9/18/97 (bug fix) Fixed long-standing bug where an "array get" command
did not trigger traces on the array or its elements. (BL)

9/18/97 (bug fixes) Fixed compilation-related bugs:
    - Fixed errorInfo traceback information for toplevel coomands that
      contain nested commands.
    - In the expr command, && and || now accept boolean operands as well
      as numeric ones. (BL)

9/22/97 (bug fix) Fixed bug that prevented translation modes from being
set independently for input and output on sockets if input was "auto". (JL)

9/24/97 (bug fix) Tcl_EvalFile(3) and thus source(n) now works fine on
files containing NUL chars. (DL)

9/26/97 (bug fix) Fixed use of uninitialized memory in the environ array
that later could cause random core dumps. Applies to all platforms. (JL)

9/26/97 (bug fix) Fixed use of uninitialized memory in socket address data
structure under some circumstances. This could cause random core dumps.
This applies only to Unix. (JL)

9/26/97 (bug fix) Opening files on PC-NFS volumes would cause a hang
until the system timed after the file was closed. (SS)

10/6/97 (bug fix) The join(n) command, though objectified, was loosing
NULs in the joinString and in list elements after the 2nd one.
Now you can "join $list \0" for instance. (DL)

10/9/97 (bug fix) Under windows, if env(TMP) or env(TEMP) referred to a
non-existent directory, exec would fail when trying to create its temporary
files. (CCS)

10/9/97 (bug fix) Under mac and windows, "info hostname" would crash if
sockets were installed but the hostname could not be determined anyhow.
Tcl_GetHostName() was returning NULL when it should have been returning
an empty string. (CCS)

10/10/97 (bug fix) "file attribute /" returned error on windows. (CCS)

10/10/97 (bug fix) Fixed the auto_load procedure to handle procedures
defined in namespaces better.  Also fixed pgk_mkIndex so it sees procedures
defined in nested namespaces.  Index entries are still only made for
exported procedures. (BW)

10/13/97 (bug fix) On unix, for files with unknown group or owner
attributes, querying the "file attributes" would return an error rather than
returning the group's or owner's id number, although tha command accepts
numbers when setting the file's group or owner.  (CCS)

10/22/97 (bug fix) "fcopy" did not eval the callback script at the
global scope. (SS)

10/22/97 (bug fix) Fixed the signature of the CopyDone callback used in
the http package(s) so they can handle error cases properly. (BW)

10/28/97 (bug fixes) Fixed a problem where lappend would free the Tcl object
in a variable if a Tcl_ObjSetVar2 failed because of an error calling a trace
on the variable. (BL)

10/28/97 (bug fix) Changed binary scan to properly handle sign
extension of integers on 64-bit or larger machines. (SS)

11/3/97 (bug fixes) Fixed several bugs:
    - expressions such as "expr ($x)" must be compiled out-of-line
      (call the expr command procedure at runtime) to ensure the correct
      behavior when "$x" is an expression such as "5+10".
    - "array set a {}" now creates a new array var with an empty array
      value if the var didn't already exist.
    - "lreplace $foo end end" no longer returns an error (just an empty
      list) if foo is empty.
    - upvar will no longer create a variable in a namespace that refers
      to a variable in a procedure.
    - deleting a command trace within a command trace callback would
      make the code that calls traces to reference freed memory.
    - significantly sped up "string first" and "string last" (fix from
      darrel@gemstone.com).
    - seg fault in Tcl_NewStringObj() when a NULL is passed as the byte
      pointer argument and Tcl is compiled with -DTCL_MEM_DEBUG.
    - documentation and error msg fixes. (BL)

11/3/97 (bug fix) Fixed a number of I/O bugs related to word sizes on
64-bit machines. (SS)

11/6/97 (bug fix) The exit code of the first process created by Tcl
on Windows was not properly reported due to an initialization
problem. (SS)

----------------- Released 8.0p1, 11/7/97 -----------------------

11/19/97 (bug fix) Fixed bug in linsert where it sometimes accidently
cleared out a shared argument list object. (BL).

11/19/97 (bug fix) Autoloading in namespaces was not working properly.
auto_mkindex is still not really namespace aware but most common
cases should now be handled properly (see init.test). (BW, DL)

11/20/97 (enhancement) Made the changes required by the new Apple
Universal Headers V.3.0, so that Tcl will compile with CW Pro 2.

11/24/97 (bug fix) Fixed tests in clock test suite that needed the
-gmt flag set.  Thanks to Jan Nijtmans for reporting the problem. (RJ)

----------------- Released 8.0p2, 11/25/97 -----------------------

12/3/97 (bug fix/optimization) Removed uneeded and potentially dangerous
instances of double evaluations if "if" and "expr" statements from
the library files. It is recommended that unless you need a double
evaluation you always use "expr {...}" instead of "expr ..." and
"if {...} ..." instead of "if ... ...". It will also be faster
thanks to the byte compiler. (DL)

---- Shipped as part of the plugin2.0b5 as 8.0p2Plugin1, Dec 8th 97 ----

12/8/97 (bug fix) Need to protect the newly accepted channel in an
accept callback on a socket, otherwise the callback may close it and
cause an error, which would cause the C code to attempt to close the
now deleted channel. Bumping the refcount assures that the channel sticks
around to be really closed in this case. (JL)

12/8/97 (bug fix) Need to protect the channel in a fileevent so that it
is not deleted before the fileevent handler returns. (CS, JL)

12/18/97 (bug fix) In the opt argument parsing package: if the description
had only flags, the "too many arguments" case was not detected. The default
value was not used for the special "args" ending argument. (DL)

1/15/98 (improvement) Moved common part of initScript in common file.
Moved windows specific initialization to init.tcl so you can initialize
Tcl in windows without having to call Tcl_Init which is now only
searching for init.tcl {back ported from 8.1}. (DL)

---- Shipped as part of the plugin as 8.0p2Plugin2, Jan 15th 98 ----

5/27/98 (bug fix) Windows socket driver did not notice new data arriving
on nonblocking sockets until the event loop was entered. (SS)

5/27/98 (bug fix) Windows socket driver used FIONREAD, which is not
supported correctly by WinSock. (SS)

6/9/98 (bug fix) Generic channel code failed to report readable file
events on buffered data that was left behind by a gets or read that
did not consume all available data. (SS)

6/18/98 (bug fix) Compilation of loop expressions was too aggressive
and incorrectly inlined non-literal expressions. (SS)

6/18/98 (bug fix) "info var" and "info locals" incorrectly reported
the existence of compiler temporary variables. (SS)

6/18/98 (bug fix) Dictionary sorting used signed character
comparisons. (SS)

6/18/98 (bug fix) Compile procs corrupted the exception stack in some
cases. (SS)

6/18/98 (bug fix) Array set had erratic behavior when initializing a
variable from an empty value list. (SS)

6/18/98 (bug fix) The Windows registry package had a bad bounds check
that could lead to a crash. (SS)

6/18/98 (bug fix) The foreach compile proc did not correctly handle
non-local variable references. (SS)

6/25/98 (new features) Added name resolution hooks to support [incr Tcl].
There are new internal Tcl_*Resolver* APIs to add, query and remove the hooks.
With this changes it should be possible to dynamically load [incr Tcl]
as an extension. (MM)

7/1/97 (bug fix) The commands "info args, body, default, procs" did
not correctly handle imported procedures. (RJ)

7/6/98 (improvement) pkg_mkIndex now implements the "package require"
command.  This makes it possible to create index files for packages
that require another package and then execute code from that package in
their file. Previously, this would throw an error because the required
package had not been loaded.  The -nopkgrequied flag is provided to
revert back to the old functionality. (EMS)

7/6/98 (improvement) back-ported the -direct flag from 8.1 into
pkg_mkIndex.  This results in pkgIndex.tcl files that contain direct
source or load commands instead of tclPkgSetup commands. (EMS)

7/6/98 (improvement) made changes to the AuxData items structures to support
storage of compiled scripts on disk. Also some related minor changes in
the compilation and execution engine. (EMS)

6/4/98 (enhancement) Added new internal routines to support inserting
and deleting from the stat, access, and open-file-channel mechanisms.
TclAccessInsertProc, TclStatInsertProc, & TclOpenFileChannelInsertProc
insert pointers to such routines; TclAccessDeleteProc, TclStatDeleteProc,
& TclOpenFileChannelDeleteProc delete pointers to such routines.  See
the file generic/tclIOUtils.c for more details. (SKS)

7/1/98 (enhancement) Added a new internal C variable
tclPreInitScript.  This is a pointer to a string that may hold an
initialization script; If this pointer is non-NULL it is evaluated in
Tcl_Init() prior to the built-in initialization script defined in the
file generic/tclInitScript.h.  (SKS)

7/6/98 (bug fix) Removed dead code in PlatformInitExitHandler so that
the TCL_LIBRARY value can be safely patched in binaries. (BW)

7/24/98 (enhancement) Incorporated a new version of auto_mkindex that
can support the [incr Tcl] class structures.  This version will index
all procedures in a source file, not just those where "proc" starts
at the beginning of the line.  If you want the old behavior, use the
auto_mkindex_old procedure. (MM)

7/24/98 (feature change) Changed the Windows registry key to be
HKEY_LOCAL_MACHINE\Software\Scriptics\Tcl\8.0, and to store the path
in the default value instead of "Root".  Also, this key can be
specified at compile time in case Tcl is being used in a different
context where it needs an alternate library path from the standard Tcl
installation. (SS)

7/24/98 (feature change) Changed the search order for init.tcl.  The
tcl_library variable can now be set before calling Tcl_Init to avoid
doing any searches.  If it isn't set, then Tcl checks
env(TCL_LIBRARY), the static value set at compile time, an install
directory relative to the executable, a source directory relative to
the executable, and a tcl directory relative to the source heirarchy
containing the executable.  See the comment at the top of
generic/tclInitScript.h for more details. (SS)

7/27/98 (config change) Changed the use of the DBGX flag in configure.in
and the makefile to be TCL_DBGX.  Users of tclConfig.sh may need to pass
this through their configure files with AC_SUBST. (BW)

729/98 (bug fix) Changed [info body] to return a copy of the body of a
compiled procedure instead of the body itself, to avoid invalidation
of the internal rep and loss of the byte-codes. (EMS)

8/5/98 (bug fix) The platform init code could walk off the end of a
buffer when reading the PkgPath registry value on Windows. (SS)

8/5/98 (Windows makefile change) Introduced a set of macros to deal with
exporting symbols when compiling DLLS on Windows. See win/README for
details. (EMS)

8/5/98 (addendum) Added a second Windows registry key under
HKEY_LOCAL_MACHINE\Software\Scriptics\Tcl\8.0, named "pkgPath".
This is a multi-string value used to initialize the tcl_pkgPath
variable. This is required if extension DLLs are in architecture specific
subdirectories. (SS)

8/6/98 (new feature) Added tcl_findLibrary to init.tcl for use by
extensions, including Tk.  This searches in a canonical way for
an extensions library directory and initialization file. (BW)

8/10/98 (bug fix) Imported commands used to get lost if the target
of the import was redefined.  Tcl_CreateCommand and Tcl_CreateObjCommand
were updated to restore import links. (Note that if you rename a command,
the import links move to the new name, and if you delete a command then
the import links get lost. These semantics have not changed.) (MC)

-------- Released 8.0.3 to the Tcl Consortium CD-ROM project, 8/10/98 ------

9/3/98 (bug fix) Tcl_Realloc was failing under Windows because the
GlobalReAlloc API was not correctly re-allocating blocks that were
32k+.  The fix was to use newer Win32 APIs (HeapAlloc, HeapFree, and
HeapReAlloc.) (BS)

10/5/98 (bug fix) Fixed bug in pkg_mkIndex that caused some files that do
a "package require" of packages in the Tcl libraries to give a warning like
	warning: "xx.tcl" provides more than one package ({xx 2.0} {yy 0.3})
and generate a broken pkgIndex.tcl file. (EMS)

10/5/98 (bug fix) Pkg_mkIndex was not doing a case-insensitive comparison
of extensions to determine whether to load or source a file. Thus, under
Windows, MYDLLNAME.DLL was sourced, and mydllname.dll loaded. (EMS)

10/5/98 (new feature) Created a new Tcl_Obj type, "procbody". This object's
internal representation holds a pointer to a Proc structure. Extended
TclCreateProc to take both strings and "procbody". (EMS)

10/13/98 (bug fix) The "info complete" command can now handle strings
with NULLs embedded.  Thanks to colin@field.medicine.adelaide.edu.au
for providing this fix. (RJ)

10/13/98 (bug fix) The "lsort -dictionary" command did not properly
handle some numbers starting with 0.  Thanks to Richard Hipp
<drh@acm.org> for submitting the fix to Scriptics. (RJ)

10/13/98 (bug fix) The function Tcl_SetListObj was creating an invalid
Tcl_Obj if the list had zero elements (despite what the comments said
it would do).  Thanks to Sebastian Wangnick for reporting the
problem. (RJ)

10/20/98 (new feature) Added tcl_platform(debug) element to the
tcl_platform array on Windows platform.  The existence of the debug
element of the tcl_platform array indicates that the particular Tcl
shell has been compiled with debug information.  Using
"info exists tcl_platform(debug)" a Tcl script can direct the
interpreter to load debug versions of DLLs with the load
command. (SKS)

10/20/98 (feature change) The Makefile and configure scripts have been
changed for IRIX to build n32 binaries instead of the old 32 abi
format.  If you have extensions built with the o32 abi's you will need
to update them to n32 for them to work with Tcl.  (RJ)
*** POTENTIAL INCOMPATIBILITY ***

10/23/98 (bug fix) tcl_findLibrary had a stray ] in one of the
pathnames it searched for the initialization script.  tclInitScript.h
was incorrectly adding the parent of tcl_library to tcl_pkgPath.  This
logic was moved into init.tcl, and the initialization of auto_path was
documented.  Thanks to Donald Porter and Tom Silva for related
patches. (BW)

10/29/98 (bug fix) Fixed Tcl_NotifyChannel to use Tcl_Preserve instead
of Tcl_RegisterChannel so that 1) unregistered channels do not get
closed after their first fileevent, and 2) errors that occur during
close in a fileevent script are actually reflected by the close
command. (BW)

10/30/98 (bug fix) Overhaul of pkg_mkIndex to deal with transitive
package requires and packages split among scripts and binary files.
Also fixed ommision of global for errorInfo in tcl_findLibrary. (BW)

11/08/98 (bug fix) Fixed the resource command to always detect
the case where a file is opened a second time with the same
permissions.  IM claims that this will always cause the same
FileRef to be returned, but in MacOS 8.1+, this is no longer the case,
so we have to test for this explicitly. (JI)

11/10/98 (feature change) When compiling with Metrowerk's MSL, use the
exit function from MSL rather than ExitToShell.  This allows MSL to
clean up its temporary files. Thanks to Vince Darley for this
improvement. (JI)

----------------- Released 8.0.4, 11/19/98 -------------------------

11/20/98 (bug fix) Handle possible NULL return in TclGetStdFiles. (RJ)

11/20/98 (bug fix) The dltests would not build on SGI.  They reported
that you could not mix n32 with 032 binaries.  The configure script
has been modified to get the EXTRA_CFLAGS from the tcl configure
script.  [Bug id: 840] (RJ)

12/3/98 (bug fix) Windows NT creates sockets so they are inheritable
by default.  Fixed socket code so it turns off this bit right after
creation so sockets aren't kept open by exec'ed processes. [Bug: 892]
Thanks to Kevin Kenny for this fix.  (SS)

1/11/98 (bug fix)  On HP, "info sharedlibextension" was returning
empty string on static apps.  It now always returns ".sl".  (RJ)

1/28/99 (configure change) Now support -pipe option on gcc.  (RJ)

2/2/99 (bug fix) Fixed initialization problem on Windows where no
searching for init.tcl would be performed if the registry keys were
missing.  (stanton)

2/2/99 (bug fix) Added support for HKEY_PERFORMANCE_DATA and
HKEY_DYN_DATA keys in the "registry" command. (stanton)

2/2/99 (bug fix) ENOTSUP and EOPNOTSUPP clashed on some Linux
variants. (stanton)

2/2/99 (enhancement) The "open" command has been changed to use the
object interfaces. (stanton)

2/2/99 (bug fix) In some cases Tcl would crash due to an overflow of
the exception stack resulting from a missing byte code in some
expressions. (stanton)

2/2/99 (bug fix) Changed configure so Linux and IRIX shared libraries
are linked with the system libraries. (stanton)

2/2/99 (bug fix) Added support for BSDI 4.x (BSD/OS-4*) to the
configure script. (stanton)

2/2/99 (bug fix) Fixed bug where upvar could resurrect a namespace
variable after the namespace had been deleted. (stanton)

2/2/99 (bug fix) In some cases when creating variables, the
interpreter result was being modified even if the TCL_LEAVE_ERR_MSG
flag was set. (stanton)

2/2/99 (bug fix & new feature) Changed the socket drivers to properly
handle failures during an async socket connection.  Added a new
fconfigure option "-error" to retrieve the failure message.  See the
socket.n manual entry for details. (stanton)

2/2/99 (bug fix) Deleting a renamed interp alias could result in a
panic. (stanton)

2/2/99 (feature change/bug fix) Changed the behavior of "file
extension" so that it splits at the last period.  Now the extension of
a file like "foo..o" is ".o" instead of "..o" as in previous versions.
*** POTENTIAL INCOMPATIBILITY ***

----------------- Released 8.0.5, 3/9/99 -------------------------

======== Changes for 8.0 go above this line ========
======== Changes for 8.1 go below this line ========

6/18/97 (new feature) Tcl now supports international character sets:
    - All C APIs now accept UTF-8 strings instead of iso8859-1 strings,
      wherever you see "char *", unless explicitly noted otherwise.
    - All Tcl strings represented in UTF-8, which is a convenient
      multi-byte encoding of Unicode.  Variable names, procedure names,
      and all other values in Tcl may include arbitrary Unicode characters.
      For example, the Tcl command "string length" returns how many
      Unicode characters are in the argument string.
    - For Java compatibility, embedded null bytes in C strings are
      represented as \xC080 in UTF-8 strings, but the null byte at the end
      of a UTF-8 string remains \0.  Thus Tcl strings once again do not
      contain null bytes, except for termination bytes.
    - For Java compatibility, "\uXXXX" is used in Tcl to enter a Unicode
      character.  "\u0000" through "\uffff" are acceptable Unicode
      characters.
    - "\xXX" is used to enter a small Unicode character (between 0 and 255)
      in Tcl.
    - Tcl automatically translates between UTF-8 and the normal encoding for
      the platform during interactions with the system.
    - The fconfigure command now supports a -encoding option for specifying
      the encoding of an open file or socket.  Tcl will automatically
      translate between the specified encoding and UTF-8 during I/O.
      See the directory library/encoding to find out what encodings are
      supported (eventually there will be an "encoding" command that
      makes this information more accessible).
    - There are several new C APIs that support UTF-8 and various encodings.
      See Utf.3 for procedures that translate between Unicode and UTF-8
      and manipulate UTF-8 strings. See Encoding.3 for procedures that
      create new encodings and translate between encodings.  See
      ToUpper.3 for procedures that perform case conversions on UTF-8
      strings.

9/18/97 (enhancement) Literal objects are now shared by the ByteCode
structures created when compiled different scripts. This saves up to 45%
of the total memory needed for all literals. (BL)

9/24/97 (bug fixes) Fixed Tcl_ParseCommand parsing of backslash-newline
sequences at start of command words. Suppressed Tcl_EvalDirect error logging
if non-TCL_OK result wasn't an error. (BL)

10/17/97 (feature enhancement) "~username" now refers to the users' home
directory on Windows (previously always returned failure). (CCS)

10/20/97 (implementation change) The Tcl parser has been completely rewritten
to make it more modular.  It can now be used to parse a script without actually
executing it.  The APIs for the new parser are not correctly exported, but
they will eventually be exported and augmented with Tcl commands so that
Tcl scripts can parse other Tcl scripts. (JO)

10/21/97 (API change) Added "flags" argument to Tcl_EvalObj, removed
Tcl_GlobalEvalObj procedure.  Added new procedures Tcl_Eval2 and
Tcl_EvalObjv. (JO)
*** POTENTIAL INCOMPATIBILITY ***

10/22/97 (API change) Renamed Tcl_ObjSetVar2 and Tcl_ObjGetVar2 to
Tcl_SetObjVar2 and Tcl_GetObjVar2 (for consistency with other C APIs)
and changed the name arguments to be strings instead of objects.  (JO)
*** POTENTIAL INCOMPATIBILITY ***

10/27/97 (enhancement) Bytecode compiler rewritten to use the new Tcl
parser. (BL)

11/3/97 (New routines) Added Tcl_AppendObjToObj, which appends the
string rep of one Tcl_Obj to another. Added Tcl_GetIndexFromObjStruct,
which is similar to Tcl_GetIndexFromObj, except that you can give an
offset between strings. This allows Tcl_GetIndexFromObjStruct to be
called with a table of records which have strings in them. (SRP)

12/4/97 (enhancement) New Tcl expression parser added. Added new procedure
Tcl_ParseExpr and new token types TCL_TOKEN_SUB_EXPR and
TCL_TOKEN_OPERATOR. Expression compiler is reimplemented to use this
parser. (BL)

12/9/97 (bug fix) Tcl_EvalObj() increments/decrements the refcount of the
script object to prevent the object from deleting itself while in the
middle of being evaluated. (CCS)

12/9/97 (bug fix) Memory leak in Tcl_GetsObjCmd(). (CCS)

12/11/97 (bug fix) Environment array leaked memory when compiled with
Visual C++. (SS)

12/11/97 (bug fix) File events and non-blocking I/O did not work on
pipes under Windows.  Changed to use threads to achieve non-blocking
behavior. (SS)

12/18/97 (bug fixes) Fixed segfault in "namespace import"; importing a
procedure that causes a cycle now returns an error. Modified "info procs",
"info args", "info body", and "info default" to return information about
imported procedures as well as procedures defined in a namespace. (BL)

12/19/97 (enhancement) Added new Tcl_GetString() procedure that can be used
in place of Tcl_GetStringFromObj() if the string representation's length
isn't needed. (BL)

12/18/97 (bug fix) In the opt argument parsing package: if the description
had only flags, the "too many arguments" case was not detected. The default
value was not used for the special "args" ending argument. (DL)

1/7/98 (clean up) Moved everything not absolutly necessary out of init.tcl
procs now in auto.tcl and package.tcl can be autoloaded if needed. (DL)

1/7/98 (enhancement) tcltest made at install time will search for it's
init.tcl where it is, even when using virtual path compilation. (DL)

1/8/98 (os bug workaround) when needed, using a replacement for memcmp so
string compare "char with high bit set" "char w/o high bit set" returns
the expected value on all platforms. (DL)

1/8/98 (unix portability/configure) building from .../unix/targetName/
subdirectories and simply using "../configure" should now work fine. (DL)

1/14/98 (enhancement) Added new regular expression package that
supports AREs, EREs, and BREs.  The new package includes new escape
characters, meta-syntax, and character classes inside brackets.
Regexps involving backslashes may behave differently.  (MH)
*** POTENTIAL INCOMPATIBILITY ***

1/16/98 (os workaround) Under windows, "file volume" was causing chatter
and/or several seconds of hanging when querying empty floppy drives.
Changed implementation to call an empirically-derived function that doesn't
cause this. (CCS)

1/16/98 (enhancement) Converted regular expressions to a Tcl_Obj type so
their compiled form gets cached automatically.  Reduced NSUBEXP from 100
to 20. (BW)

1/16/98 (documentation) Change unclear documentation and comments for
functions like Tcl_TranslateFileName() and Tcl_ExternalToUtfDString().  Now
it explicitly says they take an uninitialized or free DString.  A DString
that is "empty" or "not holding anything" could have been interpreted as one
currently with a zero length, but with a large dynamically allocated buffer.
(CCS)

----------------- Released 8.1a1, 1/22/98 -----------------------

1/28/98 (new feature) Added a "-direct" optional flag to pkg_mkIndex
to generate direct loading package indexes (such those you need
if you use namespaces and plan on using namespace import just after
package require). pkg_mkIndex still has limitations regarding
package dependencies but errors are now ignored and with -direct, correct
package indexes can be generated even if there are dependencies as long
as the "package provide" are done early enough in the files. (DL)

1/28/98 (enhancement) Performance tuning of regexp and regsub. (CCS)

1/28/98 (bug fix) regexp and regsub with "-indices" returned the byte-offsets
of the characters in the UTF-8 representation, not the character offsets
themselves. (CCS)

1/28/98 (bug fix) "clock format 0 -format %Z -gmt 1" would return the local
timezone string instead of "GMT" on Solaris and Windows.

1/28/98 (bug fix) Restore tty settings when closing serial device on Unix.
This is good behavior when closing real serial devices, essential when
closing the pseudo-device /dev/tty because the user's terminal settings
would be left useless, in raw mode, when tcl quit. (CCS)

1/28/98 (bug fix) Tcl_OpenCommandChannel() was modifying the contents of the
argv array passed to it, causing problems for any caller that wanted to
continue to use the argv array after calling Tcl_OpenCommandChannel(). (CCS)

2/1/98 (bug fix) More bugs with %Z in format string argument to strftime():
1. Borland always returned empty string.
2. MSVC always returned the timezone string for the current time, not the
   timezone string for the specified time.
3. With MSVC, "clock format 0 -format %Z -gmt 1" would return "GMT" the first
   time it was called, but would return the current timezone string on all
   subsequent calls. (CCS)

2/1/98 (bug fix) "file stat" was broken on Windows.
1. "file stat" of a root directory (local or network) or a relative path that
   resolved to a root directory (c:. when in pwd was c:/) was returning error.
2. "file stat" on a regular file (S_IFREG), the st_mode was sign extended to
   a negative int if the platform-dependant type "mode_t" was declared as a
   short instead of an unsigned short.
3. "file stat" of a network directory, the st_dev was incorrectly reported
   as the id of the last accessed local drive rather than the id of the
   network drive. (CCS)

2/1/98 (bug fix) "file attributes" of a relative path that resolved to a
root directory was returning error. (CCS)

2/1/98 (bug fix) Change error message when "file attribute" could not
determine the attributes for a file.  Previously it would return different
error messages on Unix vs.  Windows vs. Mac. (CCS)

2/4/98 (bug fixes) Fixed several instances of bugs where the parser/compiler
would reach outside the range of allocated memory. Improved the array
lookup algorithm in set compilation. (DL)

2/5/98 (change) The TCL_PARSE_PART1 flag for Set/Get(Obj)Var2 C APIs is now
deprecated and ignored. The part1 is always parsed when the part2 argument
is NULL. This is to avoid a pattern of errors for extension writers converting
from string based Tcl_SetVar() to new Tcl_SetObjVar2() and who could easily
forget to provide the flag and thus get code working for normal variables
but not for array elements. The performance hit is minimal. A side effect
of that change is that is is no longer possible to create scalar variables
that can't be accessed by tcl scripts because of their invalid name
(ending with parenthesis). Likewise it is also parsed and checked to
ensure that you don't create array elements of array whose name is a valid
array element because they would not be accessible from scripts anyway.
Note: There is still duplicate array elements parsing code. (DL)
*** POTENTIAL INCOMPATIBILITY ***

2/11/98 (bug fix) Sharing objects between interps, such as by "interp
eval" or "send" could cause a crash later when dereferencing an interp
that had been deleted, given code such as:
	set a {set x y}
	interp create foo
	interp eval foo $a
	interp delete foo
	unset a
Interp "foo" was gone, but "a" had a internal rep consisting of bytecodes
containing a dangling pointer to "foo".  Unsetting "a" would attempt to
return resources back to "foo", causing a crash as random memory was
accessed.  The lesson is that that if an object's internal rep depends on
an interp (or any other data structure) it must preserve that data in
some fashion. (CCS)

2/11/98 (enhancement) The "interp" command was returning inconsistent error
messages when the specified slave interp could not be found. (CCS)

2/11/98 (bug fix) Result codes like TCL_BREAK and TCL_CONTINUE were not
propagating through the master/slave interp boundaries, such as "interp
eval" and "interp alias".  TCL_OK, TCL_ERROR, and non-standard codes like
teh integer 57 work.  There is still a question as to whether TCL_RETURN
can/should propagate. (CCS)

2/11/98 (bug fix) TclCompileScript() was derefering memory 1 byte before
start of the string to compile, looking for ']'. (CCS,DL)

2/11/98 (bug fix) Tcl_Eval2() was derefering memory 1 byte before start
of the string to eval, looking for ']'. (CCS,DL)

2/11/98 (bug fix) Compiling "set a(b" was running off end of string. (CCS,DL)

2/11/98 (bug fix) Windows initialization code was dereferencing
uninitialized memory if TCL_LIBRARY environment didn't exist. (CCS)

2/11/98 (bug fix) Windows "registry" command was dereferencing
uninitialized memory when constructing the $errorCode for a failed
registry call. (CCS)

2/11/98 (enhancement) Eliminate the TCL_USE_TIMEZONE_VAR definition from
configure.in, because it was the same information as the already existing
HAVE_TM_ZONE definition.  The lack of HAVE_TM_ZONE is used to work around a
Solaris and Windows bug where "clock format [clock sec] -format %Z -gmt 1"
produces the local timezone string instead of "GMT". (CCS)

2/11/98 (bug fix) Memleaks and dereferencing of uninitialized memory in
regexp if an error occurred while compiling a regular expression. (CCS).

2/18/98 (new feature) Added mutexes and thread local storage in order
to make Tcl thread safe.  For testing purposes, there is a testthread
command that creates a new thread and an interpreter inside it.  See
thread.test for examples, but this script-level interface is not fixed.
Each thread has its own notifier instance to manage its own events,
and threads can post messages to each other's message queue.
This uses pthreads on UNIX, and native thread support on other platforms.
You enable this by configuring with --enable-threads.  Note that at
this time *Tk* is still not thread safe. Special thanks to
Richard Hipp: his earlier implementation inspired this work. (BW, SS, JI)

2/18/98 (hidden feature change) The way the env() array is shared among
interpreters changed.  Updates to env used to trigger write traces in
other interpreters.  This undocumented feature is no longer implemented.
Instead, variable tracing is used to keep the C-level environ array in sync
with the Tcl-level env array. This required adding TCL_TRACE_ARRAY support
to Tcl_TraceVar2 so that array names works properly. (BW)
*** POTENTIAL INCOMPATIBILITY ***

2/18/98 (enhancement) Conditional compilation for unix systems (e.g.,
IRIX, SCO) that use f_bsize instead of st_blksize to determine disk block
size. (CCS)

2/23/98 (bug fix) Fixed the emulation of polling selects in the threaded
version of the Unix notifier.  The bug was showing up on a multiprocessor
as starvation of the notifier thread. (BW)

----------------- Released 8.1a2, Feb 23 1998 -----------------------

9/22/98 (bug fix) Changed the value of TCL_TRACE_ARRAY so it no longer
conflicts with the deprecated TCL_PARSE_PART1 flag.  This should
improve portability of C code. (stanton)

10/6/98 (bug fix) The compile procedure for "if" incorrectly attempted
to match against the literal string "if", resulting in a stack
overflow when "::if" was compiled.  It also would incorrectly accept
"if" instead of "elsif" in later clauses.  (stanton)

10/15/98 (new feature) Added a "totitle" subcommand to the "string"
command to convert strings to capitalize the first character of a string
and lowercase all of the other characters. (stanton)

10/15/98 (bug fix) Changed regexp and string commands to properly
handle case folding according to the Unicode character
tables. (stanton)

10/21/98 (new feature) Added an "encoding" command to facilitate
translations of strings between different character encodings.  See
the encoding.n manual entry for more details. (stanton)

11/3/98 (bug fix) The regular expression character classification
syntax now includes Unicode characters in the supported
classes. (stanton)

11/6/98 (bug fix) Variable traces were causing crashes when upvar
variables went out of scope. [Bug: 796] (stanton)

11/9/98 (bug fix) "format" now correctly handles multibyte characters
in %s format strings. (stanton)

11/10/98 (new feature) "regexp" now accepts three new switches
("-line", "-lineanchor", and "-linestop") that control how regular
expressions treat line breaks. See the regexp manual entry for more
details. (stanton)

11/17/98 (bug fix) "scan" now correctly handles Unicode
characters. (stanton)

11/17/98 (new feature) "scan" now supports XPG3 position specifiers
and the "%n" conversion character.  See the "scan" manual entry for
more details. (stanton)

11/17/98 (bug fix) The Tcl memory allocator now returns 8-byte aligned
chunks of memory which improves performance on Windows and avoids
crashes on other platforms. [Bug: 834] (stanton)

11/23/98 (bug fix) Applied various regular expression performance bug
fixes supplied by Henry Spencer. (stanton)

11/30/98 (bug fix) Fixed various thread related race conditions. [Bug:
880 & 607] (stanton)

11/30/98 (bug fix) Fixed a number of memory overflow and leak
bugs. [Bug: 584] (stanton)

12/1/98 (new feaure) Added support for Korean encodings. (stanton)

12/1/98 (feature change) Changed the Tcl_EvalObjv interface to remove
the string and length arguments.
*** POTENTIAL INCOMPATIBILITY with previous alpha releases ***

12/2/98 (bug fix) Fixed various bugs related to line feed
translation. [Bug: 887] (stanton)

12/4/98 (new feature) Added a message catalog facility to help with
localizing Tcl scripts.  Thanks to Mark Harrison for contributing the
initial implementation of the "msgcat" package. (stanton)

12/7/98 (bug fix) The memory allocator was failing to update the
block list for large memory blocks that were reallocated into a
different address. [Bug: 933] (stanton)

----------------- Released 8.1b1, Dec 10 1998 -----------------------

12/22/98 (performance improvement) Improved the -command option of the
lsort command to better use the object system for improved
performance (about 5x speed up).  Thanks to Syd Polk for suppling the
patch. [RFE: 726] (rjohnson)

2/10/99 (bug fix) Restored the Tcl_ObjSetVar2/Tcl_ObjGetVar2
interfaces from 8.0 and renamed the Tcl_GetObjVar2/Tcl_SetObjVar2
interfaces to Tcl_GetVar2Ex and Tcl_SetVar2Ex.  This should provide
better compatibility with 8.0. (stanton)
*** POTENTIAL INCOMPATIBILITY with previous alpha/beta releases ***

2/10/99 (bug fix) Made the eval interfaces compatible with 8.0 by
renaming Tcl_EvalObj to Tcl_EvalObjEx, renaming Tcl_Eval2 to
Tcl_EvalEx and restoring Tcl_EvalObj and Tcl_GlobalEvalObj interfaces
so they match Tcl 8.0. (stanton)
*** POTENTIAL INCOMPATIBILITY with previous alpha/beta releases ***

2/25/99 (bug fix/new feature) On Windows, the channel drivers for
consoles and serial ports now completely support file events. (redman)

3/5/99 (bug fix) Integrated patches to fix various configure problems
that affected HP-UX-11, 64-bit IRIX, Linux, and Solaris. (stanton)

3/9/99 (bug fix) Integrated various AIX related patches to improve
support for shared libraries. (stanton)

3/9/99 (new feature) Added tcl_platform(user) to provide a portable
way to get the name of the current user. (welch)

3/9/99 (new feature) Integrated the stub library mechanism contributed
by Jan Nijtmans, Paul Duffin, and Jean-Claude Wippler.  This feature
should make it possible to write extensions that support multiple
versions of Tcl simultaneously.  It also makes it possible to
dynamically load extensions into statically linked interpreters.  This
patch includes the following changes:
      -	Added a Tcl_InitStubs() interface
      -	Added Tcl_PkgProvideEx, Tcl_PkgRequireEx, Tcl_PkgPresentEx,
      	and Tcl_PkgPresent.
      - Added va_list versions of all VARARGS functions so they can be
	invoked from wrapper functions.
See the manual for more information. (stanton)


3/10/99 (feature change) Replaced Tcl_AlertNotifier with
Tcl_ThreadAlert since the Tcl_AlertNotifier function relied on passing
internal data structures. (stanton)
*** POTENTIAL INCOMPATIBILITY with previous alpha/beta releases ***

3/10/99 (new feature) Added a Tcl_GetVersion API to make it easier to
check the Tcl version and patch level from C. (redman)

3/14/99 (feature change) Tried to unify the TclpInitLibrary path
routines to look in similar places from Windows to UNIX.  The new
library search path is: TCL_LIBRARY, TCL_LIBRARY/../tcl8.1, relative
to DLL (Windows Only) relative to installed executable, relative to
develop executable, and relative to compiled-in in location (UNIX
Only.)  This fix included:
    - Defining a TclpFindExecutable
    - Moving Tcl_FindExecutable to a common area in tclEncoding.c
    - Modifying the TclpInitLibraryPath routines.
(surles)

3/14/99 (feature change) Added hooks for TclPro Wrapper to initialize
the location of the encoding files and libraries.  This fix included:
    - Adding the TclSetPerInitScript routine.
    - Modifying the Tcl_Init routines to evaluate the non-NULL
      pre-init script.
    - Adding the Tcl_SetdefaultEncodingDir and Tcl_GetDefaultEncodingDir
      routines.
    - Modifying the TclpInitLibrary routines to append the default
      encoding dir.
(surles)

3/14/99 (feature change) Test suite now uses "test" namespace to
define the test procedure and other auxiliary procedures as well as
global variables.
    - Global array testConfige is now called ::test::testConfig.
    - Global variable VERBOSE is now called ::test::verbose, and
      ::test::verbose no longer works with numerical values.  We've
      switched to a bitwise character string.  You can set
      ::test::verbose by using the -verbose option on the Tcl command
      line.
    - Global variable TESTS is now called ::test::matchingTests, and
      can be set on the Tcl command line via the -match option.
    - There is now a ::test::skipTests variable (works similarly to
      ::test::matchTests) that can be set on the Tcl command line via
      the -match option.
    - The test suite can now be run in any working directory.  When
      you run "make test", the working directory is nolonger switched
      to ../tests.
(hirschl)
*** POTENTIAL INCOMPATIBILITY ***

--------------- Released 8.1b2, March 16, 1999 ----------------------

3/18/99 (bug fix) Fixed missing/incorrect characters in shift-jis table
(stanton)

3/18/99 (feature change) The glob command ignores the
FS_CASE_IS_PRESERVED bit on file systesm and always returns
exactly what it gets from the system. (stanton)
*** POTENTIAL INCOMPATIBILITY ***

3/19/99 (new feature) Added support for --enable-64bit.  For now,
this is only supported on Solaris 7 64bit (SunOS 5.7) using the Sun
compiler. (redman)

3/23/99 (bug fix) Fixed fileevents and gets on Windows consoles and
serial devices so that non-blocking channels do not block on partial
input lines.  (redman)

3/23/99 (bug fix) Added a new Tcl_ServiceModeHook interface.
This is used on Windows to avoid the various problems that people
have been seeing where the system hangs when tclsh is running
outside of the event loop. As part of this, renamed
TclpAlertNotifier back to Tcl_AlertNotifier since it is public.
(stanton)

3/23/99 (feature change) Test suite now uses "tcltest" namespace to
define the test procedure and other auxiliary procedures as well as
global variables.  The previously chosen "test" namespace was thought
to be too generic and likely to create conflits.
(hirschl)
*** POTENTIAL INCOMPATIBILITY ***

3/24/99 (bug fix) Make sockets thread safe on Windows.
(redman)

3/24/99 (bug fix) Fix cases where expr would incorrect return
a floating point value instead of an integer. (stanton)

3/25/99 (bug fix) Added ASCII to big5 and gb2312 encodings.
(stanton)

3/25/99 (feature change) Changed so aliases are invoked at current
scope in the target interpreter instead of at the global scope.  This
was an incompatibility introduced in 8.1 that is being removed.
(stanton)
*** POTENTIAL INCOMPATIBILITY with previous beta releases ***

3/26/99 (feature change) --enable-shared is now the default and build
Tcl as a shared library; specify --disable-shared to build a static Tcl
library and shell.
*** POTENTIAL INCOMPATIBILITY ***

3/29/99 (bug fix)  Removed the stub functions and changed the stub
macros to just use the name without params. Pass &tclStubs into the
interp (don't use tclStubsPtr because of collisions with the stubs on
Solaris). (redman)

3/30/99 (bug fix) Loadable modules are now unloaded at the last
possible moment during Tcl_Finalize to fix various exit-time crashes.
(welch)

3/30/99 (bug fix) Tcl no longer calls setlocale().  It looks at
env(LANG) and env(LC_TYPE) instead.  (stanton)

4/1/99 (bug fix) Fixed the Ultrix multiple symbol definition problem.
Now, even Tcl includes a copy of the Tcl stub library. (redman)

4/1/99 (bug fix) Internationalized the registry package.

4/1/99 (bug fix) Changed the implemenation of Tcl_ConditionWait and
Tcl_ConditionNotify on Windows.  The new algorithm eliminates a race
condition and was suggested by Jim Davidson. (welch)

4/2/99 (new apis)  Made various Unicode utility functions public.
Tcl_UtfToUniCharDString, Tcl_UniCharToUtfDString, Tcl_UniCharLen,
Tcl_UniCharNcmp, Tcl_UniCharIsAlnum, Tcl_UniCharIsAlpha,
Tcl_UniCharIsDigit, Tcl_UniCharIsLower, Tcl_UniCharIsSpace,
Tcl_UniCharIsUpper, Tcl_UniCharIsWordChar, Tcl_WinUtfToTChar,
Tcl_WinTCharToUtf (stanton)

4/2/99 (feature change) Add new DDE package and removed the Tk
send command from the Windows version.  Changed DDE-based send
code into "dde eval" command.  The DDE package can be loaded
into tclsh, not just wish.  Windows only. (redman)

4/5/99 (bug fix) Changed safe-tcl so that the encoding command
is an alias that masks out the "encoding system" subcommand.
(redman)

4/5/99 (bug fix) Configure patches to improve support for
OS/390 and BSD/OS 4.*. (stanton)

4/5/99 (bug fix) Fixed crash in the clock command that occurred
with negative time values in timezones east of GMT. (stanton)

4/6/99 (bug fix) Moved the "array set" C level code into a common
routine (TclArraySet).  The TclSetupEnv routine now uses this API to
create an env array w/ no elements.  This fixes the bug caused when
every environ varaible is removed, and the Tcl env variable is
synched.  If no environ vars existed, the Tcl env var would never be
created. (surles)

4/6/99 (bug fix) Made the Env module I18N compliant. (surles)

4/6/99 (bug fix) Changed the FindVariable routine to TclpFindVariable,
that now does a case insensitive string comparison on Windows, and not
on UNIX. (surles)

--------------- Released 8.1b3, April 6, 1999 ----------------------

4/9/99 (bug fix)  Fixed notifier deadlock situation when the pipe used
to talk back notifier thread is filled with data.  Found as a result of the
focus.test for Tk hanging. (redman)

4/13/99 (bug fix) Fixed bug where socket -async combined with
fileevent for writing did not work under Windows NT. (redman)

4/13/99 (encoding fix) Restored the double byte definition of GB2312
and added the EUC-CN encoding.  EUC-CN is a variant of GB2312 that
shifts the characters into bytes with the high bit set and includes
ASCII as a subset. (stanton)

4/27/99 (bug fix) Added 'extern "C" {}' block around the stub table
pointer declaration so the stub library can be used from C++. (stanton)

--------------- Released 8.1 final, April 29, 1999 ----------------------

4/22/99 (bug fix) Changed Windows NT socket implementation to avoid
creating a communication window.  This avoids the problem where the
system hangs waiting for tclsh to respond to a system-wide synchronous
broadcast (e.g. if you change system colors). (redman)

4/22/99 (bug fix) Added call to TclWinInit from TclpInitPlatform when
building a static library since DllMain will not be invoked.  This
could break old code that explicitly called TclWinInit, but should be
simpler in the long run. (stanton)
*** POTENTIAL INCOMPATIBILITY ***

4/23/99 (bug fix) Added support for the koi8-r Cyrillic
encoding. [Bug: 1771] (stanton)

4/28/99 (bug fix) Changed internal Tcl_Obj usage to avoid freeing the
internal representation after the string representation has been
freed.  This makes it easier to debug extensions. (stanton)

4/30/99 (bug fix) Fixed a memory leak in CommandComplete. (stanton)

5/3/99 (bug fix) Fixed a bug where the Tcl_ObjType was not being set
in a duplicated Tcl_Obj. [Bug: 1975, 2047] (stanton)

5/3/99 (bug fix) Changed Tcl_ParseCommand to avoid modifying eval'ed
strings that are already null terminated.  [Bug: 1793] (stanton)

5/3/99 (new feature) Applied Jeff Hobbs's string patch which includes
the following changes:
    - added new subcommands: equal, repeat, map, is, replace
    - added -length option to "string compare|equal"
    - added -nocase option to "string compare|equal|match"
    - string and list indices can be an integer or end?-integer?.
    - added optional first and last index args to string toupper, et al.
See the string.n manual entry for more details about the new string
features.  [Bug: 1845] (stanton)

5/6/99 (new feature) Added Tcl_UtfNcmp and Tcl_UtfNcasecmp to make Utf
string comparision easier. (stanton)

5/7/99 (bug fix) Improved OS/390 support. [Bug: 1976, 1997] (stanton)

5/12/99 (bug fix) Changed Windows initialization code to avoid using
GetUserName system call in favor of the env(USERNAME) variable.  This
provides a significant startup speed improvement. (stanton)

5/12/99 (bug fix) Replaced the per-interpreter regexp cache with a
per-thread cache.  Changed the Regexp object to take advantage of this
extra cache.  Added a reference count to the TclRegexp type so regexps
can be shared by multiple objects.  Removed the per-interp regexp cache
from the interpreter.  Now regexps can be used with no need for an
interpreter. This set of changes should provide significant speed
improvements for many Tcl scripts.  [Bug: 1063] (stanton)

5/14/99 (bug fix) Durining initialization on Unix, Tcl now extracts the
encoding subfield from the LANG/LC_ALL environment variables in cases
where the locale is not found in the built-in locale table.  It also
attempts to initialize the locale subsystem so X11 is happy. [Bug: 1989]
(stanton)

5/14/99 (bug fix) Applied the patch to fix 100-year and 400-year
boundaries in leap year code, from Isaac Hollander.  [Bug: 2066] (redman)

5/14/99 (bug fix) Fixed a crash caused by a failure to reset the result
before evaluating the test expression in an uncompiled for
statement. (stanton)

5/18/99 (bug fix) Modified initialization code on Windows to avoid
inherenting closed or invalid channels.  If the standard input is
anything other than a console, file, serial port, or pipe, then we fall
back to the standard Tk window console. (stanton)

5/19/99 (bug fix) Added an extern "C" block around the entire tcl.h
header file to avoid C++ linkage issues. (redman)

5/19/99 (new feature) Applied Jeff Hobb's patch to add
Tcl_StringCaseMatch to support case insensitive glob style matching and
Tcl_UniCharIs* character classification functions. (stanton)

5/20/99 (bug fix) Added the directory containing the executuble and the
../lib directory relative to that to the auto_path variable. (redman)

--------------- Released 8.1.1, May 25, 1999 ----------------------

5/21/99 (bug fix) Fixed launching command.com on Win95/98, no longer
hangs. [Bug: 2105] (redman)

5/28/99 (bug fix) Fixed bug where dde calls were being passed an
invalid dde handle. [Bug: 2124] (stanton)

6/1/99  (bug fix) Small configure.in patches. [Bug: 2121] (stanton)

6/1/99  (bug fix) Applied latest regular expression patches to fix an
infinite loop bug and add support for testing whether a string could
match with additional input. [Bug: 2117] (stanton)

6/2/99  (bug fix) Fixed incorrect computation of relative ordering in
Utf case-insensitive comparison. [Bug: 2135] (stanton)

6/3/99  (bug fix) Fxied bug where string equal/compare -nocase
reported wrong result on null strings. [Bug: 2138] (stanton)

6/4/99  (new feature) Windows build now uses Cygwin tools plus GNU
make and autoconf to build static/dynamic and debug/nodebug. (stanton)

6/7/99  (new feature) Optimized string index, length, range, and
append commands. Added a new Unicode object type. (hershey)

6/8/99  (bug fix) Rolled back Windows socket driver to 8.1.0
version. (stanton)

6/9/99  (new feature) Added Tcl_RegExpMatchObj and Tcl_RegExpGetInfo
to public Tcl API, these functions are needed by Expect.  Changed
tools/genStubs.tcl to always write output in LF mode. (stanton)

6/14/99 (new feature) Merged string and Unicode object types.  Added
new public Tcl API functions:  Tcl_NewUnicodeObj, Tcl_SetUnicodeObj,
Tcl_GetUnicode, Tcl_GetUniChar, Tcl_GetCharLength, Tcl_GetRange,
Tcl_AppendUnicodeToObj. (hershey)

6/16/99 (new feature) Changed to conform to TEA specification, added
tcl.m4 and aclocal.m4 macro libraries for configure.  (wart)

6/17/99 (new feature) Added new regexp interfaces: -expanded, -line,
-linestop, and -lineanchor switches.  Renamed Tcl_RegExpMatchObj to
Tcl_RegExpExecObj and added new Tcl_RegExpMatchObj that is equivalent
to Tcl_RegExpMatch.  Added public macros for regexp flags.  Added
REG_BOSONLY flag to allow Expect to iterate through a string and only
find matches that start at the current position within the
string. (stanton)

6/21/99 (bug fix) Fixed memory leak in TclpThreadCreate where thread
attributes were not being released.  [Bug: 2254] (stanton)

6/23/99 (new feature) Updated Unicode character tables to reflect
Unicode 2.1 data. (stanton)

6/25/99 (new feature) Fixed bugs in non-greedy quantifiers for regular
expression code. (stanton)

6/25/99 (new feature) Added initial implementation of new Tcl test
harness package.  Modified test files to use new tcltest package.
(jenn)

6/26/99 (new feature) Applied patch from Peter Hardie to add poke
command to dde and changed the dde package version number to
1.1. (redman)

6/28/99 (bug fix) Applied patch from Peter Hardie to fix problem in
Tcl_GetIndexFromObj() when the key being passed is the empty string.
[Bug: 1738] (redman)

6/29/99 (new feature) Added options to tcltest package: -preservecore,
-limitconstraints, -help, -file, -notfile, and flags.  (jenn)

7/3/99  (new feature) Changed parsing of variable names to allow empty
array names.  Now "$(foo)" is a variable reference.  Previously you
had to use something line $::(foo), which is slower.  This change was
requested by Jean-Luc Fontaine for his STOOOP package. (welch)

7/3/99  (new feature) Added Tcl_SetNotifier (public API) and
associated hook points in the notifiers to be able to replace the
notifier calls at runtime. The Xt notifier and test program use this
hook.  (welch)

7/3/99  (new feature) Added a new variant of the "Trf core patch" from
Andreas Kupries that adds new C APIs Tcl_StackChannel,
Tcl_UnstackChannel, and Tcl_GetStackedChannel.  This allows the Trf
extension to work without applying patches to the Tcl core. (welch)

7/6/99  (new feature) Added -timeout option to http.tcl to handle
timeouts that occur during connection attempts to hosts that are
down. (welch)

7/6/99  (bug fix) Applied new implementation of the Windows serial
port driver from Rolf Schroedter that fixes reading only one byte from
the port at a time.  Uses polling every 10ms to implement
fileevents. [Bug: 1980 2217] (redman)

7/8/99  (bug fix) Applied fix for bug in DFA state caching under
lookahead conditions (regular expressions).  [Bug: 2318] (stanton)

7/8/99  (bug fix) Fixed bug in string range bounds checking
code. (stanton)

--------------- Released 8.2b1, July 14, 1999 ----------------------

7/16/99 (bug fix) Added Tcl_SetNotifier to stub table. [Bug: 2364]
Added check for Alpha/Linux to correct the IEEE  floating point flag,
patch from Don Porter. (redman)

7/20/99 (bug fix) Merged 8.0.5 code to handle tcl_library properly,
also fixed a bug that caused TCL_LIBRARY to be ignored. (hershey)

7/21/99 (bug fix) Implemented modified socket driver for Windows that
uses a thread to manage the socket event window.  Code works the same
on all supported versions of Windows and was based on original 8.1.0
code.  [Bug: 2178 2256 2259 2329 2323 2355] (redman)

7/21/99 (new feature) Applied patch from Rolf Schroedter to add
-pollinterval option to fconfigure for Windows serial ports.  Allows
the maxblocktime to be modified to control how often serial ports are
checked for fileevents.  Also added documentation for \\.\comX
notation for opening serial ports on Windows.  (redman)

7/21/99 (bug fix) Changed APIs in stub tables to use "unsigned long"
instead of the platform-specific "size_t", primarily after SunOS 4
users could no longer compile. (redman)

7/22/99 (bug fix) Fixed crashing during "array set a(b) {}".
[Bug: 2427] (redman)

7/22/99 (bug fix) The install-sh script must be given execute
permissions prior to running.  [Bug: 2413] (redman)

7/22/99 (bug fix) Applied patch from Ulrich Ring to remove ANSI-style
prototypes in the code.  [Bug: 2391] (redman)

7/22/99 (bug fix) Added #if blocks around #includes of sys/*.h header
files, to allow an extension author on Windows to use the MetroWerks
compiler. [Bug: 2385] (redman)

7/22/99 (bug fix) Fixed running the safe.test test suite, one change
to the Windows Makefile.in to fix paths and another in safe.test to
check for the tcl_platform(threaded) variable properly. (redman)

7/22/99 (bug fix) Fixed hanging in new Win32 socket driver with
threads enabled. (redman)

7/26/99 (bug fix) Fixed terminating of helper threads by holding any
mutexes from the primary thread while waiting for the helper thread to
terminate.  Fixes dual-CPU WinNT hangs, only one rare sporadic hang
that still exists with dual-CPU WinNT.  Also fixed test cases so that
they would not depend as much on timing for dual-CPU WinNT. (redman)

7/27/99 (bug fix) Some test suite cleanup. (jenn)

7/29/99 (bug fix) Applied patch to fix typo in .SH NAME line in
doc/Encoding.n [Bug: 2451].  Applied patch to avoid linking pack.n to
pack-old.n [Bug: 2469]. Patches from Don Porter. (redman)

7/29/99 (bug fix) Allow tcl to open CON and NUL, even for redirection
of std channels.  [Bug: 2393 2392 2209 2458] (redman)

7/30/99 (bug fix) Applied fixed Trf patch from Andreas Kupries.
[Bug: 2386] (hobbs)

7/30/99 (bug fix) Fixed bug in info complete. [Bug: 2383 2466] (hobbs)

7/30/99 (bug fix) Applied patch to fix threading on Irix 6.5, patch
provided by James Dennett.  [Bug: 2450] (redman)

7/30/99 (bug fix) Fixed launching of 16bit applications on Win9x from
wish.  The command line was being primed with tclpip82.dll, but it was
ignored later.

7/30/99 (bug fix) Added functions to stub table, patch provided by Jan
Nijtmans. [Bug: 2445] (hobbs)

8/1/99  (bug fix) Changed Windows socket driver to terminate threads
by sending a message to the window rather than calling
TerminateThread(), which seems to leak about 4k from the helper
thread's stack space. (redman)

--------------- Released 8.2b2, August 5, 1999 ----------------------

8/4/99 (bug fix) Applied patches supplied by Henry Spencer to greatly
enhance performance of certain classes of regular expressions.
[Bug: 2440 2447] (stanton)

8/5/99 (doc change) Made it clear that tcl_pkgPath was not set for
Windows. [Bug: 2455] (hobbs)

8/5/99 (bug fix) Fixed reference to bytes that might not be null
terminated in tclLiteral.c. [Bug: 2496] (hobbs)

8/5/99 (bug fix) Fixed typo in http.tcl. [Bug: 2502] (hobbs)

8/9/99 (bug fix) Fixed test suite to handle larger integers
(64bit). Patch from Don Porter. (hobbs)

8/9/99 (documentation fix) Clarified Tcl_DecrRefCount docs
[Bug: 1952]. Clarified array pattern docs [Bug: 1330]. Fixed clock docs
[Bug: 693]. Fixed formatting errors [Bug: 2188 2189]. Fixed doc error
in tclvars.n [Bug: 2042]. (hobbs)

8/9/99 (bug fix) Fixed path handling in auto_execok [Bug: 1276] (hobbs)

8/9/99 (internal api change) Removed the TclpMutexLock and TclpMutexUnlock
APIs and added a new exported api, Tcl_GetAllocMutex. These APIs are all for
the mutex used in the simple memory allocators.  By making this change
we are able to substitute different implementations of the thread-related
APIs without having to recompile the Tcl core. (welch)

8/9/99 (new C API) Tcl_GetChannelNames returns a list of open channel
names in the interpreter result.  Still no Tcl-level version of this,
but server-like applications can use this to clean up files without
deleting interpreters. (welch)

8/9/99 (bug fix) Traces were not firing on "info exists", which used to
happen in Tcl 7.6 and earlier. An "info exists" now fires a read trace,
if defined.  This makes it possible to fully implement variables that
are defined via traces. (welch)

8/10/99 (bug fix) Fixed Brent's changes so that they work on
Windows. (redman)

--------------- Released 8.2b3, August 11, 1999 ----------------------

8/12/99 (Mac) Rearrange projects in tclMacProjects.sea.hqx so that the
build directory is separate from the sources. (Jim Ingham)

8/12/99 (bug fix) Fixed bug in Tcl_EvalEx where the termOffset was not
being updated in cases where the evaluation returned a non TCL_OK
error code. [Bug: 2535] (stanton)

--------------- Released 8.2.0, August 17, 1999 ----------------------

9/21/99 (config fixes) fixed several AIX configuration issues.  gcc and
threading may still cause problems on AIX. (hobbs)

9/21/99 (bug fix) fixed expr double-eval problem. [Bug: 732] (hobbs)

9/21/99 (bug fix) fixed static buffer overflow problem. [Bug: 2483] (hobbs)

9/21/99 (bug fix) fixed end-int linsert interpretation. [Bug: 2693] (hobbs)

9/21/99 (bug fix) fixed bug when setting array in non-existent
namespace. [Bug: 2613] (hobbs)

--- Released 8.2.1, October 04, 1999 --- See ChangeLog for details ---

10/30/99 (feature enhancement) new regexp engine from Henry Spencer
was patched in - should greatly reduce stack space usage. (spencer)

10/30/99 (bug fix) fixed Purify reported memory leaks in findexecutable
test command, TclpCreateProcess on Unix, in handling of C environ array,
and in testthread code.  No more known (reported) mem leaks for Tcl
built using gcc on Solaris 2.5.1.  Also none reported for Tcl on NT
(using Purify 6.0). (hobbs)

10/30/99 (bug fix) fixed improper bytecode handling of
'eval {set array($unknownvar) 5}' (also for incr) (hobbs)

10/30/99 (bug fix) fixed event/io threading problems by making
triggerPipe non-blocking (nick kisserbeth)

10/30/99 (bug fix) fixed Tcl_AppendStringsToObjVA and Tcl_AppendResultVA
to only	iterates once over the va_list (avoiding non-portable memcpy).
(joe english, hobbs)

10/30/99 (bug fix) removed savedChar trick in tclCompile.c that appeared
to be causing a segv when the literal table was released.
[Bug: 2459, 2515] (David Whitehouse)

10/30/99 (bug fix) fixed [string index] to return ByteArrayObj
when indexing into one (test case string-5.16) [Bug: 2871] (hobbs)

10/30/99 (bug fix) fixes for mac UTF filename handling (ingham)

--- Released 8.2.2, November 04, 1999 --- See ChangeLog for details ---

11/19/99 (feature enhancement) bug fixes for http package as well as
patch required by TLS (SSL) extension that adds http::(un)register
and -type to http::geturl.  Up'd http pkg version to 2.2.

11/19/99 (bug fix) removed extra decr of numLevels in Tcl_EvalObjEx
that could cause seg fault (mjansen@wendt.de)

11/19/99 (bug fixes) numerous minor big fixes, including correcting the
installation of the koi8-r encoding and tcltest1.0 on Windows.

11/30/99 (bug fix) fixes scan where %[..] didn't match anything

11/30/99 (bug fix) fixed setting of isNonBlocking flag in PipeBlockModeProc
so you can now close a non-blocking channel without waiting.

11/30/99 (bug work-around) prevented the unloading of DLLs for Unix in
TclFinalizeLoad.  This stops the seg fault on exit that some users would
see (ie with oratcl) when using DLLs that do nasty things like register
atexit handlers.

12/07/99 (bug fix) fixes for 'expr + {[incr]}' and 'expr + {[error]}'
cases (different causes).

--- Released 8.2.3, December 16, 1999 --- See ChangeLog for details ---

1999-09-14 (feature enhancement) added -start switch to regexp and regsub.

1999-09-15 (feature enhancement) add 'array unset' command.

1999-09-15 (feature enhancement) rewrote runtime libraries to use new
string functions

1999-08-18 (feature enhancement) added 'file channels' command, along with
Tcl_GetChannelNames(Ex) public C APIs.

1999-10-19 (feature enhancement) enhanced tcltest package

1999-09-16 (feature enhancement) added -milliseconds switch to 'clock clicks'

1999-10-28 (feature enhancement) added support for inline 'scan'

1999-10-28 (feature enhancement) added support for touch functionality by
extendeding 'file atime' and 'file mtime' to take an optional time argument

1999-11-24 (feature enhancement) added 'fconfigure $sock -lasterror'
command to Windows to query the last error received on a serial socket.

1999-11-30 (bug fix) fixed handling of %Z on NT for timezones that don't
have DST

1999-12-03 (feature enhancement) improved error message in bad octal cases
and improper use of comments. (hobbs)

1999-12-07 (bug fix) fixed Tcl_ScanCountedElement to not step
beyond the end of the counted string

1999-12-09 (feature enhancement) removed all references to 16 bit
compatibility code for Windows (hobbs)

1999-12-10 (bug fix) removed check for vfork - Tcl now uses only fork in
exec. (hobbs)

1999-12-10 (optimization) changed Tcl_ConcatObj to return a list
object when it receives all pure list objects as input (used by 'concat'),
added optimizations in Tcl_EvalObjEx for pure list case, and optimized
INST_TRY_CVT_TO_NUMERIC in TclExecuteByteCode for boolean objects.
(oakley, hobbs)

1999-12-12 (feature enhancement) enhanced glob command with -type, -path,
-directory and -join switches. (darley, hobbs)

1999-12-21 (bug fix) changed CreateThread to _beginthreadex and
ExitThread to _endthreadex to prevent 4K mem leak (gravereaux)

1999-12-21 (bug fix) fixed applescript for I18N

1999-12-21 (feature enhancement) added -unique option to lsort (hobbs)

1999-12-21 (bug fix) changed thread ids to longs (for 64bit systems)

--- Released 8.3b1, December 22, 1999 --- See ChangeLog for details ---

2000-01-10 (feature enhancement) clock scan now supports the common
ISO 8601 date/time formats.  See docs for details. (melski)

2000-01-10 (bug fix) prevented \ooo substitution from accepting
non-octal digits [Bug: 3975] (hobbs)

2000-01-11 (bug fix) fixed improper handling of DST by clock when
using relative times (like "1 month" or "tomorrow"). (melski)

2000-01-12 (bug fix) improved build support for Tru64 v5, NetBSD
and Reliant Unix (hobbs)

2000-01-12 (bug fix) made imported commands also import their
compile procedure (duffin)

2000-01-12 (bug fix) fixed 'info procs ::namesp::*' behavior to return
procs in a namespace (dejong)

2000-01-12 (feature enhancement) added support for setting permissions
symbolicly (like chmod) in [file attributes $file -permissions ...] (schoebel)

2000-01-13 (bug fix) fixed lsort -dictionary problem when sorting
characters between 'Z' and 'a' (flawed upper/lower comparison logic) (melski)

--- Released 8.3b2, January 13, 2000 --- See ChangeLog for details ---

2000-01-14 (feature enhancement) clock format %Q added, clock scan updated

2000-01-20 (bug fix) corrected complex array elem compiling (Spjuth)

2000-01-20 (bug fix) made [info body] always return a string type arg,
to prevent possible misuse of bytecodes in the wrong context (hobbs)

2000-01-20 (bug fixes) several fixes to variable handling to prevent
possible crashes, and further definition of correct behavior (melski)

2000-01-25 (bug fixes) improved QNX, Ultrix and OSF1 (Tru64) config and
compatibility (edge, furukawa)

2000-01-25 (bug fix) fixed mem leak when calling lsort with a bad -command
argument (hobbs)

2000-01-27 (feature enhancement) package mechanism overhaul: changed
behavior of pkg_mkIndex to do -direct by default, added -lazy option.
Fixed pkg_mkIndex to handle odd proc names and auto_mkIndex to use platform
independent file paths.  Other fixes for odd package quirks.  Added
::pkg namespace and ::pkg::create helper function. (melski)

2000-02-01 (bug fix) fixed problem where http POST would send one extra
newline (vasiljevic)

2000-02-02 (feature enhancement) added docs for new regexp -inline and
-all switches. (hobbs)

2000-02-08 (bug fix) corrected handling of "next monthname" in clock scan
(melski)

2000-02-09 (bug fix) restored Mac source to build readiness and prevented
mac panic from an error when closing an async socket (steffen, ingham)

2000-02-10 (feature enhancement) improved error reporting for failed
loads on Windows (dejong, hobbs)

--- Released 8.3.0, February 10, 2000 --- See ChangeLog for details ---

2000-03 (bug fixes, feature enhancement) overhaul of http package for
proper handling of async callbacks (new options), version is now at 2.3
(tamhankar, welch)

2000-03 (performance enhancement) speedup in Windows filename handling (newman)
and ==/!= empty string in exprs. (hobbs)

2000-03-27 (bug fix) added uniq'ing test to namespace export list to
prevent unnecessary mem growth (hobbs)

2000-03-29 (bug fix) fixed mem leak when repeatedly sourcing the same
bytecompiled (tbc) code repeatedly across different interpreters (hobbs)

2000-03-29 (config enhancement) improved build support for gcc/mingw on
Windows (nijtmans, hobbs) and added RPM target (melski)

2000-03-31 (bug fix) corrected data encoding problem when using
"exec << $data" construct (melski)

2000-04 (feature enhancement) overhaul of threading mechanism to better
support tcl level thread command (new APIs Tcl_ConditionFinalize,
Tcl_MutexFinalize, Tcl_CreateThread, etc, all docs in Thread.3).
(kupries, graveraux)
This enables the tcl level thread extension. (welch)

2000-04-10 (bug fix) fixed infinite loop case in regexp -all (melski)

2000-04-13 (config enhancement) added support for --enable-64bit-vis
Sparc target. (hobbs)

2000-04-18 (bug fix) moved tclLibraryPath to thread-local storage to fix
possible race condition on MP machines (hobbs)

2000-04-18 (config enhancement) added MacOS X build target and
tclLoadDyld.c dl type. (sanchez)

2000-04-23 (bug fix) several Mac socket fixes (ingham)

2000-04-24 (bug fix) fixed hang in threaded Unix case when backgrounded
exec process was running (dejong)

--- Released 8.3.1, April 26, 2000 --- See ChangeLog for details ---

2000-04-26 (doc fix) updated/added documentation for many API's and
commands (melski)

2000-05-02 (feature enhancement) added support for joinable threads;
extended API's for channels to allow channels to move between threads
(kupries)

2000-05-02 (feature enhancement) changed error return for procedures
with incorrect args to be like the Tcl_WrongNumArgs API, with a "wrong
# args: ..." message printed, with an args list (hobbs)

2000-05-08 (feature enhancement) added [array statistics] command

2000-05-08 (performance enhancement) rewrote Tcl_StringCaseMatch
algorithm for better performance; this affects the [string match]
command; added "eq" and "ne" operands to expr, for testing
string equality and inequality (hobbs)

2000-05-09 (feature enhancement) extended [lsearch] to support sorted
list searches and typed list searches (melski)

2000-05-10 (feature enhancement) added [namespace exists] command
(darley)

2000-05-18 (build enhancement) added support for mingw compile env and
cross-compiling (dejong)

2000-05-18 (bug fix) corrected clock grammar to properly handle the
"ago" keyword when it follows multiple relative unit specifiers
(melski)

2000-05-22 (compile fix) type cast cleanups (dejong)

2000-05-23 (performance enhancement) added byte-compiled
implementation of [return] command and [string] command (melski)

2000-05-26 (performance enhancement) extended byte-compiled [string]
command with support for [string compare/index/match] (hobbs)

2000-05-27 (feature enhancement) added ability to set [info script]
return value ([info script ?newFileName?]) (welch)

2000-05-31 (feature enhancement) added support for regexp and exact
pattern matching for [array names] (gazetta)

2000-05-31 (feature enhancement) added -nocomplain and -- flags to
[unset] to allow for silent unset operation (hobbs)

--- Released 8.4a1, June 6, 2000 --- See ChangeLog for details ---

2000-05-29 (bug fix) corrected resource cleanup in http error cases.
Improved handling of error cases in http. (tamhankar)

2000-07 (feature rewrite) complete rewrite of the Tcl IO channel subsystem
to correct problems (hangs, core dumps) with the initial stacked channel
implementation.  The new system has many more tests for robustness and
scalability.  There are new C APIs (see Tcl_CreateChannel), but only
stacked channel drivers are affected (ie: TLS, Trf, iogt).  The iogt
extension has been added to the core test code to test the system.
(hobbs, kupries)
	**** POTENTIAL INCOMPATABILITY ****

2000-07 (build improvements) cleanup of the makefiles and configure scripts
to correct support for building under gcc for Windows. (dejong)

2000-08-07 (bug fix) corrected sizeof error in Tcl_GetIndexFromObjStruct.
(perkins)

2000-08-07 (bug fix) correct off-by-one error in HistIndex, which was
causing [history redo] to start its search at the wrong event index. (melski)

2000-08-07 (bug fix) corrected setlocale calls for XIM support and locale
issues in startup. (takahashi)

2000-08-07 (bug fix) correct code to handle locale specific return values
from strftime, if any. (wagner)

2000-08-07 (bug fix) tweaked grammar to properly handle the "ago" keyword
when it follows multiple relative unit specifiers, as in
"2 days 2 hours ago". (melski)

2000-08-07 (doc fixes) numerous doc fixes to correct SEE ALSO and NAME
sections. (english)

2000-08-07 (bug fix) new man pages memory.n, TCL_MEM_DEBUG.3, Init.3 and
DumpActiveMemory.3. (melski)

--- Released 8.3.2, August 9, 2000 --- See ChangeLog for details ---

2000-06 thru 2000-11 (build improvements) Added support for mingw (gcc on
Windows), AIX-5 and Win64 builds (dejong, hobbs)

2000-06-23 (feature enhancement) ability to use Tcl_Obj *s as hash keys (duffin)

2000-06-29 (new features) added [mcmax] and [mcmset] and extended [unknown] in
msgcat package (duperval, krone, nelson)
=> msgcat 1.1

2000-08 thru 2000-09 added tclPlatDecls.h to default install (melski, hobbs)

2000-08-24 (new feature) Enhanced trace syntax to add:
	trace {add|remove|list} {variable|command} name ops command
(darley, melski)

2000-09-06 (cross-platform feature) Set ^Z (\32) as default EOF char. (hobbs)

2000-09-07 partial fix for bug 2460 to prevent exec mem leak on Windows for the
common case (gravereaux)

2000-09-14 Improved string allocation growth for large strings (hintermayer,
melski)

2000-09-14 New non-panic'ing mem allocation functions Tcl_AttemptAlloc,
Tcl_AttemptRealloc, Tcl_AttemptSetObjLength (melski)

2000-09-20 (new features) completely new, enhanced syntax in tcltest package.
Backwards compatable with tcltest v1. (hom)
=> tcltest 2.0

2000-09-27 (bug fix) fixed a bug introduced by a partial fix in 8.3.2 that
didn't set nonBlocking correctly when resetting the flags for the write
side (mem leak) Correct mem leak in channels when statePtr was released
(hobbs)

2000-09-29 (bug fix) corrected reporting of space parity on Windows (Eason)

2000-10-06 (bug fix) corrected [file channels] to only return channels in
the current interpreter (hobbs)

2000-10-20 (performance enhancement) call stat only when necessary in 'glob' to
speed up command significantly in base cases (hobbs)

2000-10-27 Fixed mem leak in Tcl_CreateChannel. Re-purified core via test
suites.  (hobbs)

2000-10-30 (new feature) add "ja_JP.eucJP" map to "euc-jp" encoding (takahashi)

2000-11-01 (mem leak) Corrected excessive mem use of info exists on a
non-existent array element (hobbs)

2000-11-02 (bug fix) Corrected sharing of tclLibraryPath in threaded
environment (gravereaux)

2000-11-03 (new feature) Tcl_SetMainLoop enables defining an event loop for
tclsh.  This enables Tk as a truly loadable package. (hobbs)

--- Released 8.4a2, November 3, 2000 --- See ChangeLog for details ---

2000-09-27 (bug fix) fixed a bug introduced by a partial fix in 8.3.2 that
didn't set nonBlocking correctly when resetting the flags for the write
side (mem leak) Correct mem leak in channels when statePtr was released
(hobbs)

2000-09-29 (bug fix) corrected reporting of space parity on Windows (Eason)

2000-10-06 (bug fix) corrected [file channels] to only return channels in
the current interpreter (hobbs)

2000-10-20 (performance enhancement) call stat only when necessary in 'glob' to
speed up command significantly in base cases (hobbs)

2000-11-01 (mem leak) Corrected excessive mem use of info exists on a
non-existent array element (hobbs)

2000-11-02 (bug fix) Corrected sharing of tclLibraryPath in threaded
environment (gravereaux)

2000-11-23 (mem leak) fixed potential memory leak in error case of lsort
(fellows)

2000-12-09 (feature enhancement) changed %o and %x to use strtoul instead
of strtol to correctly preserve scan<>format conversion of large integers
(hobbs)
Fixed handling of {!<boolean>} in expressions (hobbs, fellows)

2000-12-14 (feature enhancement) improved (s)rand for 64-bit platforms
(porter)

2001-01-04 (bug fix) corrected parsing of $tcl_libPath at startup on
Windows (porter)

2001-01-30 (bug fix) Fixed possible hangs in fcopy. (porter)

2001-02-15 (performance enhancement) improved efficiency of [string split]
(fellows)

2001-03-13 (bug fix) Correctly possible memory corruption in string map {}
$str (fellows)

2001-03-29 (bug fix) prevent potential race condition and security leak in
tmp filename creation on Unix. (max)
Fixed handling of timeout for threads (corrects excessive CPU usage issue
for Tk on Unix in threaded Tcl environment). (ruppert)

2001-03-30 (bug fix) corrected Windows memory error on exit (wu)
Fixed race condition in readability of socket on Windows.

2001-04-03 (doc fixes) numerous doc corrections and clarifications.
Update of READMEs.

2001-04-04 (build improvements) redid Mac build structure (steffen)
Corrected IRIX-5* configure (english).  Added support for AIX-5 (hobbs).
Added support for Win64 (hobbs).

--- Released 8.3.3, April 6, 2001 --- See ChangeLog for details ---

2000-11-23 (new feature)[TIP 7] higher resolution timer on Windows (kenny)

2001-01-18 (new feature) Tcl_InitHashTableEx renamed to Tcl_InitCustomHashTable
(kupries)

2001-03-30 (new feature)[TIP 10] support for thread-aware/hot channels (kupries)

2001-04-06 (new feature)[219280] auto-loading hidden in ::errorInfo (porter)

2001-04-07 (bug fix)[406709] corrected panic when extra items left on the
byte compiler execution stack (sofer)

2001-04-09 (bug fix)[219136,232558] improved use of thread-safe functions in
unix time commands (kenny)

2001-04-24 (new feature)[TIP 27] started CONST-ification of the Tcl APIs (kenny)

2001-05-03 (new feature) [auto_import] now matches patterns like
[namespace import], not like [string match] (porter)
        **** POTENTIAL INCOMPATABILITY ****

2001-05-07 (new feature)[416643] distinct srand() seed per interp (sofer)

2001-05-15 (new feature) new Tcl_GetUnicodeFromObj API (hobbs)

2001-05-16 (performance enhancement) byte-compiled versions of [lappend],
[append] simple cases (hobbs)

2001-05-23 (new feature) added ISO-8859-15 and koi8-u encodings, updated other
encoding tables based on http://www.unicode.org/Public/MAPPINGS/ (kuhn)

2001-05-27 (new feature) updated to Unicode 3.1.0 data set (still using 16
bits for Tcl_UniChar though) (hobbs)

2001-05-30 (new feature)[TIP 15] Tcl_GetMathFuncInfo, Tcl_ListMathFuncs,
Tcl_InfoObjCmd, InfoFunctionsCmd APIs (fellows)

2001-06-08 (bug fix,feature enhancement)[219170,414936] all Tcl_Panic
definitions brought into agreement (porter)

2001-06-12 (bug fix)[219232] regexp returned non-matching sub-pairs to have
index pair {-1 -1} (fellows)

2001-06-27 (bug fix)[217987] corrected backslash substitution of non-ASCII
characters.  (hobbs, riefenstahl)

2001-06-28 (bug fix)[231259] failure to re-compile after cmd shadowing (sofer)

2001-07-02 (bug fix)[227512] corrected [concat] treatment of UTF-8 strings
(hobbs, barras)

2001-07-12 (new feature)[TIP 36] Tcl_SubstObj API (fellows)

2001-07-16 (bug fix) corrected thread-enabled pipe closing on Windows
(hobbs, jsmith)

2001-07-18 (bug fix)[427196] corrected memory overwrite error when buffer size
of a channel is changed after channel use has already begun (kupries, porter)

2001-07-31 (new feature)[TIP 17] TclFS* APIs provide new virtual file
system.  This includes the addition of 'file normalize', 'file system',
'file separator' and 'glob -tails' (darley)

2001-08-06 (bug fix) removed use of tmpnam in TclpCreateTempFile on Unix (lim)

 * improved build support for IRIX, GNU HURD, Mac OS 9 and OS X

 * configure scripts revamped for better support of cygwin and gcc on
   Windows (mdejong)

 * corrected several minor errors noted by Purify (hobbs)

--- Released 8.4a3, August 6, 2001 --- See ChangeLog for details ---

2001-06-27 (bug fix)[217987] corrected backslash substitution of non-ASCII
characters.  (hobbs, riefenstahl)

2001-06-28 (bug fix)[231259] failure to re-compile after cmd shadowing (sofer)

2001-07-02 (bug fix)[227512] corrected [concat] treatment of UTF-8 strings
(hobbs, barras)

2001-07-16 (bug fix) corrected thread-enabled pipe closing on Windows
(hobbs, jsmith)

2001-07-18 (bug fix)[427196] corrected memory overwrite error when buffer size
of a channel is changed after channel use has already begun (kupries, porter)

2001-08-06 (bug fix)[442665] corrected object reference counting in [gets]
(jikamens)

2001-08-06 (new feature) added GNU (HURD) configuration target. (brinkmann)

2001-08-07 (bug fix)[406709] corrected panic when extra items left on the
byte compiler execution stack (see test foreach-5.5) (sofer, tallneil, jstrot)

2001-08-08 (new features) updated packages msgcat 1.1.1, opt 0.4.3,
tcltest 1.0.1, dependencies checked (porter)

2001-08-20 (new feature)[452217] http 2.3.2: include port number in Host: header
to comply with HTTP/1.1 spec (RFC 2068)  (hobbs, tils)

2001-08-23 (new feature) added QNX-6 build support (loverso)

2001-08-23 (bug fix) corrected handling of spaces in path name passed to
[exec] on Windows (kenpoole)

2001-08-24 (bug fix) corrected [package forget] stopping on non-existent
package (porter)

2001-08-24 (bug fix) corrected construction of script library search path
relative to executable (porter)

2001-08-24 (bug fix) [auto_import] now matches patterns like
[namespace import], not like [string match] (porter)
        **** POTENTIAL INCOMPATABILITY ****

2001-08-27 (new feature) added Tcl_SetMainLoop() to enable loading Tk as a
true package (hobbs)

2001-08-30 (bug fix) build support for Crays (andreasen)

2001-09-01 (bug fix) rewrite of Tcl_Async* APIs to better manage thread
cleanup  (gravereaux)

2001-09-06 (new feature) http 2.4: honor the Content-encoding and charset
parameters; add -binary switch for forcing the issue (hobbs, saoukhi, orwell)
=> http 2.4

2001-09-06 (performance enhancement) rewrite of file I/O flush management on
Windows.  Approximately 100x speedup for some operations. (kupries, traum)

2001-09-10 (bug fix) corrected finalization error in TclInExit (darley)

2001-09-10 (bug fix) protect against alias loops (hobbs)

2001-09-12 (bug fix) added missing #include in tclLoadShl.c (techentin)

2001-09-12 (bug fix) script library path construction on Windows no longer
uses registry, nor adds the current working directory to the path (porter)

2001-09-12 (bug fix) correct bugs in compatibility strtod() (porter)

2001-09-13 (bug fix) Tcl_UtfPrev now returns the proper location when the
middle of a UTF-8 byte is passed in (hobbs)

2001-09-19 (bug fix) [format] and [scan] corrected for 64-bit machines (rmax)

2001-09-19 (new feature) --enable-64-bit support for HP-11. (hobbs)

2001-09-19 (new feature) native memory allocator now default on Windows
(hobbs)

2001-09-20 (new feature) WIN64 support and extra processor definitions
(hobbs, mstacy)

2001-09-26 (bug fix) corrected potential deadlock in channels that do not
provide a BlockModeProc (kupries, kogorman)

2001-10-03  (new feature) WIN64 build support (hobbs)

2001-10-03 (bug fix) correction in thread finalization (rbrunner)

2001-10-04 (new feature) updated encodings with latest mappings from
www.unicode.org (hobbs)

2001-10-11 (bug fix) corrected cleanup of self-referential bytecodes at
interpreter deletion (sofer, rbrunner)

2001-10-16 (new feature) config support for MacOSX / Darwin (steffen)

2001-10-16 (new feature, Mac) change in binary extension format from MachO
bundles to standard .dylib dynamic libraries like on other unices.
        *** POTENTIAL INCOMPATIBILITY ***

2001-10-18 (bug fix) corrected off-by-one-day error in clock scan with
relative months and years during swing hours. (lavana)

--- Released 8.3.4, October 19, 2001 --- See ChangeLog for details ---

2001-08-21 (bug fix)[219184] overagressive compilation of [catch] (sofer)

2001-08-22 (new feature)[227482] [dde request -binary] (hobbs)
=> dde 1.2

2001-08-30 (performance enhancement)[456668] fully qualified command names use
cached Command for all namespaces, avoiding repeated lookups (sofer)

2001-08-31 (performance enhancement) bytecompiled [list] (hobbs)

2001-09-02 (bug fix)[403553] Add -Zl to VC++ compile line for tclStubLib to
avoid any specific C-runtime library dependence. (gravereaux)

2001-09-05 (new feature) restored support for Borland compiler (gravereaux)

2001-09-05 (new feature)[TIP 49] Tcl_OutputBuffered API (schroedter, fellows)

2001-09-07 (new feature) restored VC++ 5.0 compatibility (gravereaux)

2001-09-10 (performance enhancement)[TIP 53,451441] [proc foo args {}] now
compiles to 0 bytecodes (sofer)

2001-09-13 (new feature)[TIP 56] Tcl_EvalTokensStandard API (sofer)

2001-09-13 (new feature) Old ChangeLog entries => ChangeLog.1999 (hobbs)

2001-09-17 (new feature) compiling with TCL_COMPILE_DEBUG now required to
enable all compile and execution tracing (sofer)
        *** POTENTIAL INCOMPATIBILITY ***

2001-09-19 (bug fix)[411825] made TclNeedSpace UTF-8 aware (fellows)

2001-09-19 (bug fix)[219166] overagressive compilation of "quoted" bodies of
[for], [foreach], [if], and [while] (sofer)

2001-09-19 (performance enhancement) bytecompiled [string match] (hobbs)

2001-10-15 (new feature)[TIP 35] serial channel configuration: Win (schroedter)

2001-11-06 (bug fix)[478856] loss of fileevents due to short reads (kupries)

2001-11-06 (new feature) revitalized makefile.vc (gravereaux)

2001-11-07 (new feature) Cygwin gcc support dropped.  Use mingw (dejong)
        *** POTENTIAL INCOMPATIBILITY ***

2001-11-07 (new feature) Support --include-dir= and --libdir= options to
configure.  Store in tclConfig.sh as TCL_INCLUDE_SPEC and TCL_LIB_SPEC.
(dejong)
        *** POTENTIAL INCOMPATIBILITY ***

2001-11-08 (new feature) Enable --enable-threads on FreeBSD (dejong)

2001-11-08 (new feature) New make target 'make gdb' (dejong)

2001-11-09 (bug fix)[480176] [global] mishandled varnames matching :* (porter)

2001-11-12 (new feature)[TIP 22,33,45] new command [lset],
[lindex] extended to accept multiple indices. (kenny, hobbs)

2001-11-16 (new feature) new configure option --enable-langinfo=no.
By default, nl_langinfo() is used on Unix to determine system encoding.
Tcl's built-in system is used only if that fails, or configured with
--enable-langinfo=no. (hobbs, wagner)

2001-11-19 (new feature)[TIP 62] A Tcl_VarTraceProc can now return Tcl_Obj *
or a dynamic string as well as a static string to indicate an error (fellows)

2001-11-19 (new feature)[TIP 73] Tcl_GetTime API (kenny)

2001-11-19 (bug fix)[478847] overflows in [time] of >2**31 microseconds (kenny)

2001-11-29 (performance enhancement) caching scheme added to [binary scan]
(fellows)

2001-12-05 (new feature) new algorithm for [array get] adds safety when read
traces modify the array. (sofer)
        *** POTENTIAL INCOMPATIBILITY ***

2001-12-10 (bug fix)[490514] doc fixes (porter,english)

2001-12-18 (new feature) removed unix/dltest/configure; unix/configure does
all (dejong)

2001-12-19 (new feature) New make target 'make shell' (dejong)

2001-12-21 (new feature) MaxOSX / Darwin support (steffen)

2001-12-28 (new feature) new command [memory onexit] replaces [checkmem] when
compiled with TCL_MEM_DEBUG.  Added documentation. (porter)
        *** POTENTIAL INCOMPATIBILITY ***

2001-12-28 (bug fix) proper case in [auto_execok] use of $env(COMPSPEC) (hobbs)

2002-01-05 (feature rewrite) Tcl_Main() rewritten and documentation improved.
Interactive operation and event loop operation (via Tcl_SetMainLoop) now
interleave cleanly.  Also more robust against strange happenings. (porter)

2002-01-17 (bug fix)[504642] Tcl_Obj refCounts in [gets] (griffen,kupries)

2002-01-21 (bug fix)[506297] infinite loop writing in iso2022-jap encoding
(forssen,kupries)

2002-01-24 (HTTP server bug workaround)[504508] leave the default port out
of the Host: header value
=> http 2.4.1 (hobbs)

2002-01-25 (new feature)[496733] socket options -eofchar and -translation
return read-only values (dejong)

2002-01-28 (new feature) Old ChangeLog entries => ChangeLog.20900 (hobbs)

2002-01-28 (performance enhancement) bytecompiled [regexp] for trivial cases
that amount to string matching.  Also -nocase and --. (hobbs)

2002-02-05 (bug fix) [http::error] called when [::error] intended
=> http 2.4.2 (porter)

2002-02-05 (bug fix)[465765] avoid zero-byte writes to STREAMs
(talcott,kupries)

2002-02-06 (performance enhancement) [regsub] special cases that map to
[string map] detected. (hobbs)

2002-02-06 (bug fix)[495213] [scan] accept 0x as prefix of base 16 value
(hobbs)

2002-02-10 (new feature)[TIP 32,79] Tcl_CreateObjTrace API (kenny)

2002-02-12 (new feature) partial support for DJGPP Tcl on DOS (gravereaux)

2002-02-14 (mem leak) Fixed leaking an empty Tcl_Obj when [gets $chan]
errored out. (kupries, sofer)

2002-02-15 (new feature)[TIP 72] support for 64-bit integer values on
32-bit platforms and ability to work with >2GiB files.  Extends many
commands.  See ChangeLog and TIP for details.
	*** POTENTIAL INCOMPATIBILITY ***

2002-02-22 (bug fix)[476537] Fix panic when loading shared library without
proper use of stubs on platform without backlinking (porter)

2002-02-22 (new feature)  64-bit support for xlc compiler on AIX-4 (hobbs)

2002-02-22 (new feature)[521560] Removed limits on filename length and
format [source]able through the Safe Base (hobbs)

2002-02-22 (performance enhancement) optimized bytecodes for [if], [for],
[while] and constant conditions (sofer)

2002-02-22 (new feature)[TIP 76] [regsub] can now return result (fellows)

2002-02-25 (bug fix)[495207] buffer overrun when closing ] left out of
argument to [subst] (sofer, english)

2002-02-25 (bug fix)[514392] [load] updated for Mac OS X 10.1 (steffen)

2002-02-26 (bug fix) [info hostname] choked on names >31 characters (hobbs)

2002-02-26 (new feature)[TIP 35] serial channel configuration: Unix
(schroedter, hobbs)

2002-02-25 (bug fix)[483575] [fconfigure ... -error] now no-op on Mac (kupries)

2002-02-28 (performance enhancement)[458872] fully qualified command names use
cached Command for all namespaces, avoiding repeated lookups (sofer)

 * (new feature)[TIP 27] completed CONST-ification of TCL APIs.
Added compiler macro USE_NON_CONST to keep using those old API prototypes
that present irreconcilable source incompatibilities with header files
of prior Tcl releases.  Others will need to be reconciled.
        *** POTENTIAL INCOMPATIBILITY ***

2002-03-04 (bug fix)[474358, 218099, 219314, 524674] fixed several problems
related to the handling of iso2022 text and finalization of escape-based
encodings. (taguchi, takahashi, hobbs)

--- Released 8.4a4, March 5, 2002 --- See ChangeLog for details ---

2002-03-06 (new feature)[TIP 80] expanded [lsearch] options (wilkason, fellows)

2002-03-07 (new feature)[TIP 87] [interp recursionlimit] (trier)

2002-03-08 (platform feature) mingw 1.1 build favored (dejong)

2002-03-20 (new feature)[TIP 27] CONST-ified variable access functions (porter)

2002-03-24 (bug fix)[511666,511658,523217,530960] expanded
Tcl_FSMatchInDirectory to handle assorted [glob] bugs in VFS. (darley)
        *** POTENTIAL INCOMPATIBILITY with prior 8.4a releases ***

2002-03-25 (bug fix)[495726] stopped tcltest disabling of auto-loading (porter)

2002-03-25 (bug fix)[495977] allow \n in test constraints (porter)

2002-03-27 (platform support)[527941,533862] VC/winhelp/W9X (spjuth,
gravereaux)

2002-03-28 (bug fix)[219181] exception at level 0 issues (sofer)

2002-03-28 (bug fix)[219362] command termination; Tcl_CreateTrace (knoll,sofer)

2002-04-05 (bug fix)[536879] exceptions during variable subst (porter)

2002-04-15 (bug fix)[497446,513983] tcltest syntax errors now raised (porter)
	***POTENTIAL INCOMPATIBILITY with prior tcltest 2.0.* (8.4aX)***

2002-04-17 (bug fix)[495660] [(save|restore)state] deprecated (porter)

2002-04-17 (bug fix)[526524] escape-based encodings corrected (yamamoto, hobbs)

2002-04-18 (bug fix)[542588] [expr] error msgs improved (ehrens, sofer)

2002-04-18 (bug fix)[545325] [info level $level] now returns [namespace eval]
as documented (suchenwirth,sofer)

2002-04-19 (bug fix)[544727] export [mcload]; ns context of [mcmax] (porter)
=> msgcat 1.2.3

2002-04-22 (performance enhancement) threaded memory allocator (AOL, hobbs)

2002-04-24 (new feature) TCLTK_NO_LIBRARY_TEXT_RESOURCES #define disables
inclusion of tcl library code in resource fork on Mac.  (steffen)

2002-05-21 (platform support) static libs on OSF (dejong)

2002-05-24 (bug fix)[557878] set encoding on listening socket (staplin,
kupries)

2002-05-24 (new feature)[TIP 91] Tcl_Seek compatibility (fellows)

2002-05-28 (bug fix)[545579] VFS [load] left temp file (darley)

2002-05-28 (bug fix)[559376] plug timezone env leak on Windows (hobbs)

2002-05-29 (performance enhancement) [string compare] optimized (hobbs,fellows)

2002-05-31 (bug fix)[550534] plug interp leak in [pkg_mkIndex] (helmut)

2002-05-31 (dead code)[474335,555635] removed all use of matherr() (english)
        *** POTENTIAL INCOMPATIBILITY ***

2002-06-04 (new feature)[TIP 85,521362] custom result match in tcltest
(markus, porter)
=> tcltest 2.1

2002-06-06 (bug fix)[524352] encoding, threading, and environment issues on
MacOSX (steffen)

2002-06-06 (bug fix)[512214,558742,512214,461000] lazy initialization of
tcltest constraints (porter)

2002-06-07 (bug fix)[563122,564595] EOVERFLOW definitions (fellows)

2002-06-11 (bug fix)[567386] [info locals] corrections (sofer)

2002-06-14 (new feature)[TIP 102] [trace list] renamed [trace info] (fellows)

2002-06-17 (new feature)[525522,525525] msgcat support for XPG4 locales;
examination of LC_ALL, LC_MESSAGES environment variables (haible, porter)
=> msgcat 1.3

2002-06-17 (new feature)[565088] header files assume modern C compiler by
default; older compilers may need configuration (english)
        *** POTENTIAL INCOMPATIBILITY ***

2002-06-17 (bug fix)[554068] [exec] argument quoting on Windows (darley)

2002-06-17 (new feature)[TIP 62,462580] command execution traces (lavana)

2002-06-19 (bug fix)[558324] regexp sets a linked variable (watson)

 * (performance enhancment) optimizations of bytecode execution (sofer)

2002-06-21 (new feature)[TIP 99,562970] new [file link] command (darley)

2002-06-24 (new feature)[TIP 101] new [tcltest::configure] command (porter)
=> tcltest 2.2

2002-06-25 (new feature) --enable-man-symlinks and --enable-man-compression
options to configure (max)

2002-06-26 (bug fix)[565880] [clock format] now respects locale (max)
        *** POTENTIAL INCOMPATIBILITY ***

2002-07-03 (bug fix)[577015] [catch] catches even compile errors (sofer)

--- Released 8.4b1, July 5, 2002 --- See ChangeLog for details ---

2002-07-08 (bug fix) restored compatibility of [viewFile] in tcltest (porter)

2002-07-11 (bug fix) [file normalize] returns long form on Win 95/98/ME (darley)

2002-07-15 (performance enhancment) variable operations rewritten to store
	and use cached Var pointers (sofer)

2002-07-22 (bug fix)[218000] Inf and Nan are floating-point values (fellows)

2002-07-23 (platform support)[219220] 64-bit compile on IRIX (dejong)

2002-07-25 (bug fix)[219218] return codes in background errors (english)

2002-07-28 (bug fix)[582522] alias fires exec traces (sofer)

2002-07-29 (bug fix)[578363] regexp (fellows,pvgoran)

2002-07-30 (bug fix)[584603] WriteChars infinite loop non-UTF-8 string (kupries)

2002-08-04 (new feature)[584051,580433,585105,582429][TIP 27] Tcl interfaces
	are now fully CONST-ified.  Use the symbols USE_NON_CONST or
	USE_COMPAT_CONST to select interfaces with fewer changes.
        *** POTENTIAL INCOMPATIBILITY ***

2002-08-05 (bug fix)[589859] tcltest setup and cleanup scripts skipped when
	test body is skipped (porter)
	=> tcltest 2.2

2002-08-07 (bug fix)[587488] mem leak with USE_THREAD_ALLOC (sofer,sass)

2002-08-07 (feature enhancement)[584794,584650,472576] boolean values
	are no longer always re-parsed from string. (sofer)

Many internal bugs fixed.
Considerable cleanup of the test suite.

--- Released 8.4b2, August 9, 2002 --- See ChangeLog for details ---

2002-08-20 (new feature) --enable-memdebug configure option (kupries)

2002-08-23 (bug fix)[597936] mem leak with USE_THREAD_ALLOC (sofer,zoran)

2002-08-26 (bug fix)[599788] segfault in compiler (sofer,wilkason)

2002-08-28 (bug fix)[414910] avoid mem leaks accessing environment variables
	on Windows (welton,gravereaux)

2002-08-31 (platform support)[TIP 108] Mac OS X port (steffen,ingham)

2002-09-02 (platfrom support) 64-bit compile on HP-11 (martin)

--- Released 8.4.0, September 10, 2002 --- See ChangeLog for details ---

2002-09-18 (platform support) Updated support for compiling with Cygwin and
either mingw or gcc. (khan, howell, dejong)

2002-09-22 (bug fix)[612786, 611922] Corrected [puts -nonewline] within
test bodies. Also corrected reporting of body return code.  Updated tcltest
to v2.2.1.

2002-09-24 (bug fix)[613117] More robust 64-bit wide integer value
detection (fellows)

2002-09-26 (bug fix) correct overeager optimization of noop proc to handle
the precompiled case. (sofer, hobbs)

2002-09-26 (bug fix)[615115] removed extraneous spaces in koi8-u.enc that
confused encoding reader.

2002-09-29 (bug fix)[219355] Added proper exiting conditions using Win32
console signals.  This handles the existing lack of a Ctrl+C exit to call
exit handlers when built for thread support.  Also, properly handles exits
from other conditions such as CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and
CTRL_SHUTDOWN_EVENT signals.  In all cases, exit handlers will be called.
(gravereaux)

2002-09-30 (bug fix) improve the checking for bad regular expressions
during regexp compilation.  Resultant compiles were correct, but much
slower than necessary. (hobbs)

2002-10-01 (bug fix) fix precompiled locals to support 8.3 precompiled
code. (hobbs)

2002-10-09 (bug fix)[620735] Added code to set an exit handler on Windows
that terminates the thread that calibrates the performance counter, so that
the thread won't outlive unloading the Tcl DLL. (kenny)

2002-10-09 (build support) all --enable-symbols to take the enhanced
options yes|no|mem|compile|all. (hobbs)

2002-10-10 (build support) enable USE_THREAD_ALLOC (new threaded allocator)
by default on Windows. (hobbs, gravereaux)

2002-10-14 (bug fix)[623269] correct possible mem leak in
Tcl_PutEnv. (brouwers)

2002-10-15 (bug fix)[615043] fix in execution traces with idle tasks
firing. (lavana)

2002-10-15 (platform support) Correct AIX-5 ppc and 4/5 64-bit build flags.
Correct HP 11 64-bit gcc building. (martin, hobbs)

2002-10-17 (bug fix)[624755] Fixed code that check for proper # of args to
[array names] (porter)

2002-10-18 (feature enhancement)[625453] Added support for broadcasting
changes to the registry Environment on Windows.  Updated registry package
to v1.1. (hobbs)

2002-10-22 (platform support)[624509] On macosx, add embedded framework
dirs to tcl_pkgPath: @executable_path/../Frameworks and
@executable_path/../PrivateFrameworks (if they exist), as well as the dirs
in DYLD_FRAMEWORK_PATH (if set). (steffen)

--- Released 8.4.1, October 22, 2002 --- See ChangeLog for details ---

2002-10-28 (bug fix)[627660] [package unknown] chaining for platform specifics

2002-10-29 (bug fix)[627546] verbose [load] (dyld) error mesages on MacOSX

2002-11-01 (bug fix) [package provide registry] consistent versions.

2002-11-06 (bug fix)[582039] missing ar program -> configuration error

2002-11-06 (feature enhancement) added new TclInThreadExit function to
test for thread exit vs whole process exit condition. The TclInExit
function now correctly returns 1 during Tcl_Finalize processing.
        *** POTENTIAL INCOMPATIBILITY ***

2002-11-13 (bug fix)[615043] some execution traces were not firing

2002-11-18 (bug fix)[634856] multiple signs no longer accepted as valid integer
[string is integer ++1] => 0
        *** POTENTIAL INCOMPATIBILITY ***

2002-11-26 (bug fix)[593810,597924] clean exit of channel worker threads on Win

2002-11-28 (new feature) `make valgrind` target

2002-12-03 (bug fix)[615304] repeated load/unload of Tcl now possible

2002-12-11 (bug fix)[647307] negative return codes now propagated by procs

2002-12-11 (bug fix)[648441] syntax error in [expr 0x] now detected.

2003-01-07 (bug fix)[633204] [catch {return}] => 2 (not 0)

2003-01-09 (bug fix)[634151] [file (a|m)time $nonASCIIpath $time] now works

2003-01-16 (bug fix) dde eval with {} service name does not crash.
=> dde 1.2.1

2003-01-16 (bug fix)[635200,655645,615043,571385] many command trace fixes

2003-01-31 (bug fix)[675614,678415,676978] tcltest conflicts in cleanup
and -outfile; also failure in space-containing path; also missing [close]
=> tcltest 2.2.2

2003-02-01 (bug fix)[670042] corrected [info loaded {}] for static
packages in multiple interps.

2003-02-01 (bug fix)[675356] [clock clicks {}]; [clock clicks -] - syntax errs

2003-02-01 (bug fix)[656660] MT-safety for [clock format]

2003-02-03 (bug fix)[651271] command rename traces get fully-qualified names
        *** POTENTIAL INCOMPATIBILITY ***

2003-02-07 (performance improvement) [glob] on Windows is 2.5 times faster

2003-02-07 (feature change) lack of Cygwin support indicated by config error

2003-02-11 (bug fix)[684744] [info complete] stopped by \x00

2003-02-11 (bug fix)[685445] [glob -types l] missed broken symlinks on Unix

2003-02-11 (bug fix) [lsearch -regexp $a $a] doesn't crash

2003-02-13 (bug fix)[685926] accept non-ASCII7 for tcl_platform(user) on Win

2003-02-15 (bug fix)[673714] stop crash when Tcl_DeleteEvents deletes last

2003-02-15 (bug fix)[681841] parser missed some missing ] syntax errors

2003-02-17 (bug fix)[684756] memory leak during command rename plugged

2003-02-18 (bug fix)[689100] reduced per-thread memory overhead

2003-02-18 (platform support)[651811] use xnet library on HP 11 (64 bit).

2003-02-20 (bug fix)[Patch 689341] correct jis round-trip encoding

2003-02-20 (bug fix)[689835] stop MacOSX hang trying to read a write-only pipe

2003-02-07 (performance improvement) [tclPkgUnknown]: fewer vfs calls

2003-02-18 (platform support) cut and splice procs for file channels on Mac

2003-02-21 (bug fix)[690774] [binary scan] failed on some wide ints

2003-02-22 (bug fix)[571002] plugged data leak during thread exit

2003-02-25 (feature change) [pkg_mkIndex -load]: case-insensitive match
        *** POTENTIAL INCOMPATIBILITY ***

2003-02-27 (bug fix)[694232] stop [lsearch -start 0 {} x] segfault

--- Released 8.4.2, March 3, 2003 --- See ChangeLog for details ---

2003-03-06 (bug fix)[699042] Correct case-insensitive unicode string
comparison in Tcl_UniCharNcasecmp

2003-03-11 (bug fix) Corrected loading of tclpip8x.dll on Win9x

2003-03-12 (bug fix)[702383] Corrected parsing of interp create --

2003-03-12 (bug fix)[685106] Correct Tcl_SubstObj handling of \x00 bytes

2003-03-14 (bug fix)[702622 699060] Correct wide int issues in 'format'

2003-03-14 (bug fix)[698146] Remove assumption that file times and longs
are the same size.

2003-03-18 (bug fix)[697862] Allow Tcl to differentiate between reparse
points which are symlinks and mounted drives on Windows

2003-03-19 (bug fix)[705406] Bad command count on TCL_OUT_LINE_COMPILE

2003-03-20 (bug fix)[707174] Store pointers to notifier funcs in a struct
to work around some platform linker issues

2003-03-22 (bug fix)[708218] Load correct (non-)debug dll for dde or
registry

2003-03-24 (bug fix)[631741 696893] Fixing ObjMakeUpvar's lookup algorithm
for the created local variable

2003-04-07 (bug fix)[713562] Make sure that tclWideIntType is defined and
somewhat sensible everywhere

2003-04-07 (bug fix)[711371] Corrected string limits of arguments
interpolated in error messages for 'if'

2003-04-11 (bug fix)[718878] Corrected inconsistent results of
[string is integer] observed on systems where sizeof(long) != sizeof(int)

2003-04-12 (bug fix) Substantial changes to the Windows clock synch
phase-locked loop in a quest for improved loop stability

2003-04-16 [713562] Made changes so that the "wideInt" Tcl_ObjType is
defined on all platforms, even those where TCL_WIDE_INT_IS_LONG is defined.
Also made the Tcl_Value struct have a wideValue field on all platforms.
Potential incompatibility for TCL_WIDE_INT_IS_LONG platforms because that
struct changes size.
        *** POTENTIAL INCOMPATIBILITY ***

2003-04-25 (bug fix)[727271] Catch any errors returned by the Windows
functions handling TLS ASAP instead of waiting to get some mysterious crash
later on due to bogus pointers.

2003-04-29 (bug fix) Correct 'glob -path {[tcl]} *', where leading
special character instead lists files in '/'.  Bug only occurs on Windows
where '\' is also a directory separator.

2003-05-09 (bug fix)[731754] Fixed memory leak in threaded allocator on
Windows caused by treating cachePtr as a TLS index

2003-05-10 (bug fix)[710642] Ensure cd is thread-safe

2003-05-10 (bug fix)[718002] Correct mem leak on closing a Windows serial
port

2003-05-10 (bug fix)[714106] Prevent string repeat crash when overflow
sizes were given (throws error).

2003-05-13 (feature enhancement)[736774] Use new versioned bundle resource
API to get tcl runtime library for TCL_VERSION on Mac OS X.

2003-05-13 (bug fix)[711232] Worked around the issue of realpath() not
being thread-safe on Mac OS X by defining NO_REALPATH for threaded builds
on Mac OS X.

2003-05-14 (bug fix)[557030] Correct handling of the gb2312 encoding by
making it an alias of the euc-cn encoding and creating a gb2312-raw
encoding for the original.  Most uses of gb2312 really mean euc-cn.

2003-05-14 (bug fix)[736421] Corrected another putenv() copy behavior
problem when compiling on Windows and using Microsoft's runtime.

--- Released 8.4.3, May 20, 2003 --- See ChangeLog for details ---

2003-05-23 (bug fix)[726018] reverted internals change to the
'cmdName' Tcl_ObjType that broke several extensions (TclBlend, e4graph...)
in the 8.4.3 release.

2003-06-10 (bug fix)[495830] stop eval of bytecode in deleted interp.

2003-06-17 (bug fix) corrections to regexp when matching emtpy string.

2003-06-25 (bug fix)[748957] -*ieee compiler flags for Tru64 builds.

2003-07-11 (bug fix) [pkg_mkIndex] indexes provided packages, not indexed ones.

2003-07-15 (feature enhancement) MacOSX build system rewrite.

2003-07-15 (bug fix)[771613] corrected segfault in [if] (buffer overflow)

2003-07-16 (bug fix)[756791] corrected assumption that Tcl_Free == free

2003-07-16 (feature enhancement) -DTCL_UTF_MAX=6 compile option forces
internal UCS-4 representation of Unicode (default is recommended UCS-2).

2003-07-16 (bug fix)[767578] 64-bit corrections in thread notifier.

2003-07-16 (bug fix)[759607] Safe Base tests normalized paths.

2003-07-16 (feature enhancement)[Patch 679315] improved Cygwin path support

2003-07-18 (bug fix)[706359] corrected broken -output option of [tcltest::test]
=> tcltest 2.4.4

2003-07-18 (bug fix)[753315] MT-safety of VFS records.

2003-07-18 (bug fix)[759888] support for user:pass in URL by [http::geturl]
=> http 2.4.4

Improved documentation, new tests, and some code cleanup.
[655300, 720634, 735364, 748700, 756112, 756744, 756951, 758488, 760768,
763312, 769895, 771539, 771840, 771947, 771949, 772333]

--- Released 8.4.4, July 22, 2003 --- See ChangeLog for details ---

2003-07-23 (bug fix)[775976] fix registry compilation for VC7.

2003-08-05 (enhancement)[781585] Use Tcl_ResetResult in bytecodes to
prevent potential costly Tcl_Obj duplication.

2003-08-06 (bug fix)[781609] prevent non-Windows platforms from trying to
use the registry package inside msgcat.

2003-08-27 (bug fix)[411825] Fix TclNeedSpace to handle non-breaking space
(\u00A0) and backslash escapes correctly.

2003-09-01 (bug fix)[788780] Fix thread-safety issues in filesystem records.

2003-09-19 (bug fix)[804681] Protect ::errorInfo and ::errorCode traces
from corrupting stack.

2003-09-23 (bug fix)[218871] Fix handling of glob-sensitive chars in
auto_load and auto_import.

2003-10-03 (bug fix)[811483] Fixed refcount management for command and
execution traces.

2003-10-04 (bug fix)[789040] Fixed exec command.com error for Win9x.

2003-10-06 (bug fix)[767834, 813273] Fixed volumerelative file
normalization and 'file join' inconsistencies.

2003-10-08 (bug fix)[769812] Fix Tcl_NumUtfChars string length calculation
when negative parameter is given.

2003-10-22 (bug fix)[800106] Handle VFS mountpoints inside glob'd dirs.

2003-10-22 (bug fix)[599468] Watch for FD_CLOSE too on Windows when
asked for writable events by the generic layer.

2003-10-23 (bug fix)[813606] Detect OS X pipes correctly.

2003-11-05 (bug fix)[832657] Allow .. in libpath initialization.

2003-11-11 (bug fix) Improve AIX-64 build configuration.

2003-11-17 (bug fix)[230589, 504785, 505048, 703709, 840258] fixes to
various odd regexp "can't happen" bugs.

--- Released 8.4.5, November 20, 2003 --- See ChangeLog for details ---

2003-12-02 (bug fix)[851747] object sharing fix in [binary scan]

2003-12-09 (platform support)[852369] update errno usage for recent glibc

2003-12-12 (bug fix)[858937] fix for [file normalize ~nobody]

2003-12-17 (bug fix)[839519] fixed two memory leaks (vasiljevic)

2004-01-09 (bug fix)[873311] fixed infinite loop in TclFinalizeFilesystem

2004-02-02 (bug fix)[405995] Tcl_Ungets buffer filling fix

2004-02-04 (bug fix)[833910] tcltest command line option parsing error
=> tcltest 2.4.5

2004-02-04 (bug fix)[833637] code error in tcltest -preservecore operation

2004-02-12 (feature enhancement) update HP-11 build libs setup

2004-02-17 (bug fix)[849514,859251] corrected [file normailze] of $link/..

2004-02-17 (bug fix)[772288] Unix std channels forced to exist at startup.

2004-02-17 (new default) tcltest::configure -verbose {body error}

2004-02-19 (bug fix) init.tcl search path with unusual --libdir (samson)

2004-02-25 (bug fix)[554068] stopped broken [exec] quoting of { (gravereaux)

2004-02-25 (bug fix)[888777] plugged memory leak with long host names (cassoff)

2004-03-01 (bug fix)[462580] corrected level interpretation of Tcl_CreateTrace

2004-03-01 (platform support)[218561] Allow 64-bit configure on IRIX64-6.5*

--- Released 8.4.6, March 1, 2004 --- See ChangeLog for details ---

Changes to 8.5a1 include all changes to the 8.4 line through 8.4.6,
plus the following, which focuses on the high-level feature changes
in this changeset (new minor version) rather than bug fixes:

 * refactored IO code to split FS path code into generic/tclPathObj.c
  and generic/tclFileSystem.h

 * refactored trace code into generic/tclTrace.c

 * configure scripts now require autoconf 2.57 for regeneration

 * updated runtime library scripts to use newer Tcl code features
   (like replacing regsub with string map)

 * improve robustness of tcltest test suite across environments

 * changed the bytecode evaluation-stack addressing mode, from array-style
   to pointer-style; the catch stack and evaluation stack are now
   contiguous in memory

 * switch command is now byte-compiled

 * enhanced checking in 'file' command for Windows NT file permissions

 * [TIP #57] new 'lassign' command (adopted from TclX)

 * [TIP #75] switch -regexp now provides submatch info

 * [TIP #90] extended 'catch' and 'return' to enable creation of procs
   that are a true replacement for 'return'

 * [TIP #100] new 'unload' command (can unload DLLs loaded via 'load',
   requires the extension writer to support it)

 * [TIP #111] new 'dict' command.  Several commands have been updated
   to handle the list form of dicts implicitly at the C level where
   only lists were previously accepted

 * [TIP #112] 'namespace ensemble' command addition allows for ensembles
   that build on the namespace abstraction

 * [TIP #118] file attributes -readonly option for unices that support
   chflags(), support Mac Classic attribute options on OS X, add
   -rsrclength for OS X, enhance file copy on OS X to copy finder
   attributes and resource forks transparently

 * [TIP #120] enable dde in safe interpreters
 * [TIP #130] enable unique dde server names on Windows
 * [TIP #135] change dde servername -exact option to -force
=> dde 1.3

 * [TIP #121] new Tcl_SetExitProc C API to control application shutdown

 * [TIP #123] expr ** exponentiation operator

 * [TIP #124] 'clock clicks -milliseconds' now returns a wide integer and a
   new 'clock clicks -microseconds' returns a wide integer, representing
   the number of microseconds, both since the Posix epoch

 * [TIP #127] added 'lsearch -index' option

 * [TIP #136] added 'lrepeat' command

 * [TIP #137/151] Add -encoding option to 'source' command and main tclsh
   executable.
     *** POTENTIAL INCOMPATIBILITY ***
   For Tcl embedders that build on Tcl_Main() and make use of Tcl_Main's
   former ability to pass a leading "-encoding" option to interactive shell
   operations, this will now be consumed by Tcl.

 * [TIP #138] New TCL_HASH_KEY_SYSTEM_HASH option for Tcl hash tables

 * [TIP #139] documented portions of Tcl's namespace C APIs

 * [TIP #148] correct [list]-quoting of the '#' character
     *** POTENTIAL INCOMPATIBILITY ***
   For scripts that assume a particular (buggy) string rep for lists.

 * [TIP #156] add "root locale" to msgcat
=> msgcat 1.4

 * [TIP #157] leading {expand} syntax on words to cause argument expansion.
   This is a safer/cleaner alternative to the use of 'eval'.

--- Released 8.5a1, March 3, 2004 --- See ChangeLog for details ---

2004-03-04 (new feature) registry package is [unload]able (thoyts)
=> registry 1.1.4

2004-03-08 (bug fix)[910525] [glob -path] in root directory (darley)

2004-03-12 (new feature)[TIP 163] [dict merge] (english, fellows)

2004-03-18 (platform support) support for Mac Classic removed (steffen)

2004-03-28 (bug fix)[925121] corrected segfault in bc compiler (sofer)

2004-03-30 (bug fix)[495830,729692] bytecode execution checks
each command/interp validity before executing. (sofer)

2004-03-31 (bug fix)[811457] support translation to "" (porter)
2004-03-31 (bug fix)[811461] ignore locales with no "language" part (porter)
=> msgcat 1.4.1

2004-04-01 (bug fix) make [glob -type d -dir . *] work across VFS boundary

2004-04-06 (clean up) refactored Tcl header file #include order.  Might
create need for changes in extensions that #include private headers.
Changed source code files should work with older Tcl as well.  See ChangeLog.
     *** POTENTIAL INCOMPATIBILITY ***

2004-04-07 (bug fix)[920667] install into any Unicode path on Win (hobbs)

2004-04-07 (platform support) properly substitute more values in Windows
tclConfig.sh (hobbs)

2004-04-23 (bug fix)[930851] reset channel EOF when eofchar changes (kupries)

2004-04-28 (bug fix)[600812][TIP 184] [upvar 0 scalar array(foo)] raises error

2004-05-03 (bug fix)[947070] stack overflow prevention on Win (kenny)

2004-05-03 (bug fix)[868853] fix leak in [fconfigure $serial -xchar] (cassoff)

2004-05 (bug fix)[928353,929892,928808,947440,948177] test fixes: OSX (abner)

2004-05-05 (bug fix)[794839] socket connect error -> r/w fileevents
(gravereaux)

2004-05-07 (bug fix)[949905] corrected utf-8 encoding of \u0000 on I/O (max)

2004-05-13 (new feature)[TIP 129] [binary scan tnmrRqQ] (markus, fellows)

2004-05-13 (new feature)[TIP 142] [interp limit] (fellows)

2004-05-14 (bug fix)[940278,922848] [clock] notices $::env(TZ) changes,
gmt works on all platforms. (kenny, welton, glessner)

2004-05-16 (feature rewrite) bytecode execution of {expand} changed
        *** POTENTIAL INCOMPATIBILITY with prior 8.5a releases ***

2004-05-18 (platform support) makefile.vc now generates tclConfig.sh (thoyts)

2004-05-18 (bug fix)[500285,500389,852944] [clock %G %V] ISO8601 week numbers
(kenny)

2004-05-22 (bug fix)[735335,736729] variable name resolution error (sofer)

2004-05-24 (bug fix) support for non-WIDE_INT aware math functions (hobbs)

2004-05-25 (new feature) [http::config -urlencoding] (hobbs)
=> http 2.5.0

2004-05-26 (bug fix)[960926] file count doubled when -singleproc 1 (porter)
=> tcltest 2.2.6

2004-05-26 (bug fix)[874058] improved build configuration on 64-bit systems.
Corrects Tcl_StatBuf definition issues.  (hobbs)

2004-05-30 (platform support) Win: allow signed short exit codes (gravereaux)

2004-06-05 (bug fix)[976722] hi-res clock fixes: Win
(godfrey, suchenwirth, kenny)
2004-06-10 (bug fix)[932314] bad return values from Tcl_FSChdir() (vasiljevic)

2004-06-18 (platform support) regonize more unix locales (huang)

2004-06-18 (bug fix) prevent stack overflow from long free() chains (fellows)

2004-06-21 (platform support) exceptions w/ gcc -O3 on Win (dejong)

2004-06-23 (feature rewrite)[976496] thread local storage done with hash
tables to avoid system limits (mistachkin)

2004-06-29 (bug fix)[981733] SafeBase global pollution (fellows)

2004-06-30 (new feature)[TIP 188] [string is wideinteger] (kenny)

2004-07-02 (new feature)[TIP 202] pipe redirection 2>@1 (hobbs)

2004-07-03 (bug fix)[908375] round() wide integer support (lavana, sofer)

2004-07-07 (bug fix)[458361] shimmer of single-word scripts suppressed (sofer)

2004-07-15 (bug fix)[770053] crash in thread finalize of notifier (vasiljevic)

2004-07-15 (bug fix)[990453] plug mutex leaks on reinit
(mistachkin, vasiljevic)

2004-07-16 (bug fix)[990500] clean exit of notifier thread
(mistachkin, kupries)

2004-07-19 (bug fix)[987967] improved self-init of mutexes on Win (vasiljevic)

2004-07-20 (bug fix) pure Darwin/CFLite support (steffen)

2004-07-20 (bug fix)[736426] plug leaky allocator reinit (mistachkin, kenny)

2004-07-30 (bug fix)[999084] no deadlock in re-entrant Tcl_Finalize (porter)

2004-08-02 (new feature)[TIP 207] [interp invokehidden -namespace] (porter)

2004-08-10 (bug fix) thread IDs on 64-bit systems (ratcliff,vasiljevic)

2004-08-13 (bug fix) avoid malicious code acceptance by [mclocale] (porter)
=> msgcat 1.3.3

2004-08-16 (bug fix)[1008314] Tcl_SetVar TCL_LIST_ELEMENT (sofer,porter)

2004-08-18 (new feature)[TIP 173,209] complete [clock] rewrite (kenny)
	*** POTENTIAL INCOMPATIBILITY ***

2004-08-18 (new feature)[TIP 189] package loading for Tcl Modules (kupries)

2004-08-19 (bug fix)[1011860] [scan %ld] fix on LP64 (fellows,porter)

2004-08-23 (bug fix)[695441] extend [tcl_findLibrary] search path to include
		$::auto_path and [pkgconfig get scriptdir,runtime] (porter)

2004-08-27 (platform support) TCL_MODULE_PATH values for Mac OSX (steffen)

2004-08-27 (bug fix)[1017022] recognize imported ensembles (fellows)

2004-08-30 (bug fix) [string map $x $x] crash (fellows)

2004-09-01 (bug fix)[1020445] WIN64 support (hobbs)

2004-09-03 (bug fix)[1020538] crash in [file copy] (violi,fellows)

2004-09-07 (bug fix)[1016167] [after] overwrites its imports (kenny)

2004-09-08 (bug fix) fixed [clock format 0 -format %k] (kenny)

2004-09-09 (bug fix)[560297] fixed broken [namespace forget] logic (porter)

2004-09-09 (bug fix)[1017299] fixed [namespace import] cycle prevention
(porter)

2004-09-10 (performance) $x[set x {}] is now fast [K $x [set x {}]] (sofer)

2004-09-10 (bug fix)[868489] better control over int <-> wideInt
(fellows,kenny)

2004-09-10 (bug fix)[1025359] POSIX errorCode from wide seeks (kupries,fellows)

2004-09-10 (bug fix)[707104,1026493] fix [rename] of [interp alias] (porter)

2004-09-18 (bug fix)[868467] fix [expr 5>>32] => 0, not 5 (hintermayer,fellows)

2004-09-21 (bug fix) consistent errorinfo from [namespace eval x error foo bar]
		and [namespace eval c {error foo bar}] (porter)

2004-09-22 (feature change) syntax errors not reported at compile time;
		deferred to runtime.  Support [return -errorline]. (porter)

2004-09-23 (bug fix)[1016726] fix `make clean` in static config
(leitgeb,dejong)

2004-09-22 (feature change) report all compile errors at runtime (porter)

2004-09-29 (bug fix)[1036649] syntax error in [subst] => buffer overflow
(sofer)

2004-09-30 (bug fix)[1038021] save/restore error state: var traces (porter)

2004-10-01 (performance) stackframe level values in internal reps (fellows)

2004-10-01 (feature change)[1037235] auto-create [dict] key paths (fellows)

2004-10-04 (bug fix)[884830] eq and ne parse in expr (fellows)

2004-10-05 (reform) errorInfo, errorCode management (porter)
	*** POTENTIAL INCOMPATIBILITY for traces on those vars ***

2004-10-06 (feature change)[1041072] re-bless and enhance Tcl_AppendResult
(dkf)

2004-10-06 (reform) more robust interp result appends (porter)
=> dde 1.3.1
=> registry 1.1.5

2004-10-06 (reform) re-write of [glob] guts (fellows)

2004-10-07 (reform)[925620] improved platform split of VFS code (darley)

2004-10-08 (new feature)[TIP 201] "in" and "ni" expr operators (fellows)

2004-10-08 (new feature)[TIP 212] [dict update]; [dict with] (fellows)

2004-10-08 (bug fix)[954263] case insensitive [file exec] for Win
(hobbs,darley)

2004-10-14 (performance) [info commands/globals/procs/vars $pattern] faster
                when $pattern is trivial (fellows)

2004-10-14 (new feature)[TIP 217] [lsort -indices] (salsman,fellows)

2004-10-24 (reform) replaced bit flag values with macros for Var handling
	*** POTENTIAL INCOMPATIBILITY for accesses to Var internals ***

2004-10-26 (new feature)[1054370] install msgcat, http, tcltest as TM's
(porter)

2004-10-26 (bug fix)[767676] negative PIDs with pipes (giese,gravereaux)

2004-10-27 (bug fix)[731778] stop critical section leaks
(mistachkin,gravereaux)

2004-10-27 (bug fix)[926088] -load option to find tested packages (gravereaux)

2004-10-28 (bug fix)[1030548] restore the --enable-symbols --enable-threads
build on Win (mistachkin,kenny,kupries)

2004-10-29 (bug fix)[1055673] fix command line syntax error message (porter)
=> tcltest 2.2.7

2004-10-30 (bug fix)[926106] fix [file mtime] DST anomaly (kenny)

2004-10-31 (bug fix)[1057461] fix [info globals ::varName] (fellows)

2004-11-02 (bug fix)[761471] fix [expr {NaN == NaN}] (sofer)

2004-11-02 (bug fix)[1017151] misleading errorInfo after tests (seeger,porter)

2004-11-03 (bug fix)[527164] preserve errorinfo from var traces (porter)

2004-11-08 (bug fix){947693] Made -blocking option of channel during [close]
consistent on Windows with Unix (gravereaux)
	*** POTENTIAL INCOMPATIBILITY ***

2004-11-11 (bug fix)[1034337] recursive file delete, MacOSX (steffen)

2004-11-12 (new feature)[TIP 221] [interp bgerror] (porter)

2004-11-12 (new feature)[TIP 226] Tcl_(Save|Restore|Discard)InterpState
(porter)

2004-11-12 (new feature)[TIP 227] Tcl_(Get|Set)ReturnOptions (porter)

2004-11-12 (bug fix)[1004065] stop crash when TCL_UTF_MAX==6 (hobbs,porter)

2004-11-15 (bug fix)[10653678] [trace variable],[trace remove] interop (porter)

2004-11-16 (bug fix)[1067709] crash in [fconfigure -ttycontrol] (hobbs)

2004-11-18 (new feature) configure options --enable-man-suffix (max)

2004-11-22 (bug fix)[1030465] Improve HAVE_TYPE_OFF64_T check (dejong)

2004-11-22 (bug fix)[1043129] Fixed the treatment of backslashes in file
join on Windows (darley)

2004-11-22 (bug fix)[976438] Move init.tcl search path construction to
tclInit (porter)

2004-11-24 (bug fix)[1072654] Fixed segfault in info vars trivial
matching branch (new in 8.4.8) (porter)

2004-11-24 (bug fix)[1001325, 1071701] Fixed readdir_r detection and usage
(dejong, kenny, porter)

2004-11-24 (bug fix)[1071807] Fixed all uses of 'select' to use standard
macros rather than older bit-whacking style (kenny)

2004-11-26 (bug fix)[1073524] Simplify the code to check for correctness of
strstr, strtoul and strtod on unix (fellows)

2004-11-26 (bug fix)[1072136] Remove file normalize on tcl_findLibrary
search path uniqification added in 8.4.8 (porter)

2004-11-30 (bug fix)[976520] Rework startup/initialization of the Tcl
library, encoding search initialization, and Tcl_FindExecutable structure.
[tclInit] no longer driven by the value of $::tcl_libPath (TCLLIBPATH).
(porter)
	*** POTENTIAL INCOMPATIBILITY : makes encoding names case sensitive
	    on Windows, where they have been case insensitive ***

2004-12-02 (bug fix)[1074671] Ensure tilde paths are not returned specially
by 'glob' (darley)

Doc improvements [759545,926590,935853,1017072,1018486,1022527,1027849,
	1032243,1047928,1048005,1058446,1062647,1065732,1073334,etc.]
Test suite expansion [1036649,1001997,etc.]

--- Released 8.5a2, December 7, 2004 --- See ChangeLog for details ---

2004-12-13 (bug fix)[1083082] encoding memory leaks (ade,porter)

2004-12-13 (bug fix)[1082349] restored C++ extension support (porter)

2004-12-14 (bug fix)[1081541] workaround automake-ism "$U" (porter)

2004-12-15 (new feature) CallFrames on execution, not C, stack (sofer)

2004-12-16 (bug fix)[1085023] [interp limit] support in [vwait], etc. (fellows)

2004-12-29 (bug fix)[1090413] make [clock scan 0030] work (morian,kenny)

2004-12-29 (bug fix)[1092789] make [clock scan 10000] work (porter,kenny)

2004-12-29 (platform support)[1092952,1091967] MSVC7, gcc OPT compiles (hobbs)

2005-01-06 (performance)[1020491] [http::mapReply] (fellows)
=> http 2.5.1

2005-01-09 (bug fix)[1095909] stopped use of readdir_r (english)

2005-01-10 (enhancement)[1081595] stopped use of TCL_DBGX (english)

2005-01-17 (bug fix)[1100542] [glob] of Windows shares (schar,darley)

2005-01-19 (new feature)[TIP 235] C API for ensembles (fellows)

2005-01-21 (new feature)[TIP 233] virtual time (kupries)

2005-01-25 (bug fix)[1101670] [auto_reset] update for [namespace] (porter)
***POTENTIAL INCOMPATIBILITY***
May cause re-[source]-ing of files that have not anticipated that before.

2005-01-27 (new feature)[TIP 218] Tcl_Channel API update for threads (kupries)

2005-01-27 (bug fix)[1109484] Tcl_Expr* updates for Tcl_WideInt (hobbs)

2005-01-28 (platform support)[1021871] Solaris gcc 64-bit support (hobbs)

2005-02-10 (bug fix)[1119369] Tcl_EvalObjEx: avoid shimmer loss of List intrep
(sofer,macdonald)

2005-02-11 (platform support) correct gcc builds for AIX-4+, HP-UX-11 (hobbs)

2005-02-24 (bug fix)[1119798] prevent [source $directory] (porter,mpettigr)
=> tcltest 2.2.8

2005-03-10 (bug fix)[1153871] bad ClientData cast (porter,victorovich)

2005-03-15 (platform support) OpenBSD ports patch (thoyts)

2005-03-18 (bug fix)[1115904] restore recursion limit in direct eval (porter)

2005-03-24 (bug fix) stop conflict between Tcltest and Thread packages (porter)

2005-03-29 (platform support) allow msys builds without cygwin (hobbs)

2005-04-01 (internal change)[1158008]  internal rep of "list" Tcl_Obj's
now uses a refcounted struct (sofer)
***POTENTIAL INCOMPATIBILITY***
For any code that goes poking into the internals of "list" Tcl_Obj's

2005-04-05 (performance)[1174551] Tcl_DecrRefCount of Tcl_Obj "chains" (sofer)

2005-04-08 (performance)[1077262] better Tcl_Encoding cache lifetimes (porter)

2005-04-10 (bug fix)[1180368] [interp invokehidden] mem leak (kenny,porter)

2005-04-12 (performance)[1177363] startup encoding file scan (porter)

2005-04-12 (performance)[1182459] [clock format] (kenny)

2005-04-13 (bug fix) min buffer size dropped from 10 to 1 byte (gravereaux)

2005-04-16 (bug fix)[1178445] fix memory waste at thread exit (vasiljevic)

2004-04-16 (bug fix)[1084111] [array names] memory leak (ade,sofer)

2005-04-19 (bug fix)[1185933] [clock] init clobbered global vars (ring,kenny)

2005-04-19 (new feature) [::tcl::unsupported::EncodingDirs] - unsupported
command to set search path for encoding files (porter)

2005-04-20 (bug fix)[1090869] Tcl_GetInt accept 0x80000000, 64-bit
(porter,singh)

2005-04-22 (bug fix)[1187123] [string is boolean] respect EIAS (porter)

2005-04-25 (enhancement) update to tzdata2005i (kenny)

2005-04-25 (platform support) builds on Mac OS X 10.1 (steffen)

2005-04-27 (new feature)[TIP 183] [open $f {... BINARY ...}] (porter)

2005-04-29 (new feature)[TIP 176] simple index arithmetic (porter)

2005-05-06 (platform support) x86_64 Solarix cc and Solaris 10 builds (hobbs)

2005-05-10 (bug fix)[1198892] [expr {i**0}] error (kaitschu,markus)

2005-05-10 (new feature)[TIP 132] floating-point conversion to string (kenny)
***POTENTIAL INCOMPATIBILITY***
For scripts that rely on (tcl_precision==12) number formatting

2005-05-10 (new feature)[TIP 232] math functions as commands (kenny)
***POTENTIAL INCOMPATIBILITY***
Tcl_GetMathFuncInfo functioning is reduced; routine is now deprecated

2005-05-13 (feature removed) TCL_NO_MATH compiler directive (porter)

2005-05-14 (platform support) Mac OSX: configurable CoreFoundation API
(steffen)

2005-05-14 (platform support) Mac OSX: use realpath when threadsafe (steffen)

2005-05-17 (feature removed) Tcl_ObjType's "list", "procbody", "index",
"ensembleCommand", "localVarName", "levelReference, "boolean" are no
longer registered (porter)
***POTENTIAL INCOMPATIBILITY***
For any callers of Tcl_GetObjType on those strings

2005-05-20 (bug fix)[1201589] boolean literal prefix in expressions (porter)

2005-05-24 (platform support) Darwin build support merged into unix (steffen)

2005-05-24 (new feature)[1202209] Mac OSX: support [load] of .bundle binaries
Can support [load] from memory as well (steffen)

2005-05-24 (new feature)[1202178] [time] returns non-integer result (steffen)

2005-05-25 (new feature)[TIP 182] [expr {bool(...)}] (mistachkin,porter)

2005-05-30 (new feature)[TIP 229] [namespace path] (fellows)

2005-05-31 (bug fix)[1082283] Unix: notifier thread now joinable (vasiljevic)

2005-06-01 (new feature)[TIP 241] -nocase: lsort, lsearch, switch (mistachkin)

2005-06-01 (bug fix)[1209759] "return TCL_RETURN;" could cause panic (porter)

Documentation improvements [1075433,1085127,1117017,1124160,1149605,etc.]

--- Released 8.5a3, June 4, 2005 --- See ChangeLog for details ---

2005-06-06 (bug fix)[1213678] Windows/gcc: crash in stack.test (kenny)

2005-06-07 (new feature)[TIP 208] [chan] and [chan truncate] (fellows)

2005-06-07 (revert) Restored registration of "procbody" Tcl_ObjType (porter)
Reduces the ***POTENTIAL INCOMPATIBILITY*** from 2005-05-17.

2005-06-13 (bug fix)[1217375,1219176] [file mkdir] race (diekhans,darley)

2005-06-14 (bug fix)[1220058] [namespace delete] crash (duquette,fellows)

2005-06-17 (bug fix)[1221395] Tcl_LimitSetTime able to break [vwait] (fellows)

2005-06-18 (bug fix)[1154163] [format %h] on 64-bit OS's (kraft,fellows)

2005-06-21 (bug fix)[1201035,1224585] execution trace crashes (porter)

2005-06-21 (bug fix)[1194458] Windows: [file split] (kenny,porter)

2005-06-22 (bug fix)[1225727] Windows: pipe finalization crash (kenny)

2005-06-22 (bug fix)[1225571] Windows: [file pathtype] buffer overflow (thoyts)

2005-06-22 (bug fix)[1225044] Windows: UMR in pipe close (kenny)

2005-06-23 (bug fix)[1225957] Windows/gcc: crashes in assembler code (kenny)

2005-06-24 (bug fix) make Tcl_Preserve safe in Tk exit handlers (kenny)

2005-07-01 (bug fix)[1222872] notifier spurious wake-up protection (vasiljevic)

2005-07-05 (bug fix)[1230597] allow idempotent [namespace import] (porter)

2005-07-15 (bug fix)[1237907] localtime() => NULL => crash (kenny)

2005-07-21 (dropped support) IRIX 4, RISCos, Ultrix, and ancient BSD (kenny)
***POTENTIAL INCOMPATIBILITY***

2005-07-22 (enhancement)[1237755] 8.4 features in script library (fradin,porter)

2005-07-24 (new feature) configure macros SC_PROG_TCLSH, SC_BUILD_TCLSH (dejong)
2005-07-26 (bug fix)[1047286] cmd delete traces during namespace delete (porter)

2005-07-26 (new unix feature)[1231015] ${prefix}/share on ::tcl_pkgPath (dejong)
***POTENTIAL INCOMPATIBILITY***

2005-07-27 (bug fix)[1214462] [unknown] can return exceptions (porter)

2005-07-27 (new feature) value of ::tcl_precision now kept per-thread (porter)
***POTENTIAL INCOMPATIBILITY***

2005-07-28 (unix bug fix)[1245953] O_APPEND for >> redirection (fellows)

2005-07-29 (bug fix)[1247135] [info globals] return only existing vars (fellows)

2005-07-30 (new Darwin feature) TCL_LOAD_FROM_MEMORY configuration (steffen)

2005-08-05 (bug fix)[1241572] correct [expr abs($LONG_MIN)] (kenny)

2005-08-05 (Solaris bug fix)[1252475] recognize cp1251 encoding (wagner,fellows)

2005-08-11 (config options) eliminated USE_THREAD_STORAGE option (kenny)

2005-08-23 (toolchain support) autoconf-2.59 now required (dejong)

2005-08-24 (new feature)[TIP 219] reflected channels ([chan create]) (kupries)

2005-08-25 (bug fix)[1267380] [lrepeat] buffer overflow prevention (fellows)

2005-08-26 (bug fix) fix [namespace ensemble] crashes in Snit (fellows)

2005-08-29 (bug fix)[1275043] restore round() away from zero (kenny)

2005-08-29 (bug fix)[1189657] correct [tcl::tm::roots] (porter)

2005-09-07 (bug fix)[1283976] invalid [format %c -1] result (porter)

2005-09-08 (new feature)[1242844][TIP 254] new types for Tcl_LinkVar (fellows)

2005-09-07 (toolchain support) deprecate TCL_VARARGS*; stdarg.h assumed (porter)
***POTENTIAL INCOMPATIBILITY***

2005-09-15 (RHEL bug fix)[1287638] support open >2GB files RHEL 3 (palan)

2005-09-08 (new feature)[TIP 255] [expr min()] and [expr max()] (hobbs)

2005-09-30 (bug fix)[1306162] $argv encoding and list formatting (porter)

2005-10-04 (bug fix)[1067708] [fconfigure -ttycontrol] leak (hobbs)

2005-10-04 (bug fix)[1182373] [http::mapReply] update to RFC 3986 (aho,hobbs)
=> http 2.5.2

2005-10-04 (HPUX bug fix)[1204237] shl_load() and DYNAMIC_PATH (collins,hobbs)

2005-10-05 (bug fix)[979640] buffer overrun mixing putenv(), ::env (bold,hobbs)

2005-10-08 (new feature)[TIP 237] unlimited range for integers (kenny,porter)
***POTENTIAL INCOMPATIBILITY*** for any code that relies on implicit truncation
of integer calculations to the range of a C long

2005-10-14 (platform support)[1256937] MSVC++ static builds (thoyts)

2005-10-19 (bug fix)[1331475] [dict append] crash (bills,sofer)

2005-10-20 (bug fix)[1333036] [lset] shared sublist handling (sofer)

2005-10-23 (bug fix)[1335006] memleack in [glob] (melbardis,darley)

2005-10-23 (bug fix)[1325803] Win: [file stat] on links (bonilla,darley)

2005-11-01 (bug fix)[1337941] Tcl_TraceCommand() -> crash (devilliers,porter)

2005-11-02 (platform support)[1256937] MSVC 8 support (thoyts)

2005-11-03 (new Win NT/XP feature) Unicode console support (kovalenko,thoyts)

2005-11-04 (bug fix)[1337229,1338280] [namespace delete] / unset traces (sofer)

2005-11-04 (enhancement) Korean timezone abbreviations (kenny)

2005-11-04 (platform support)[1163896] LynxOS [load] (heidibr)

2005-11-04 (bug fix)[1334947] value refcount error in var setting (sofer)

2005-11-04 (Win enhancement)[1267871] extended exit codes (newman,thoyts)

2005-11-07 (bug fix)[1348775] unset trace memory leak (sofer)

2005-11-08 (bug fix)[1162286] [package require] checks that the script
registered by [package ifneeded] provides the version it claims (lavana,porter)
*** POTENTIAL INCOMPATIBILITY ***

2005-11-09 (bug fix)[1350293,1350291] [after $negative $script] fixed (kenny)

2005-11-12 (bug fix)[1352734,1354540,1355942,1355342] [namespace delete]
issues with [namespace path] and command delete traces (sofer,fellows)

2005-11-18 (bug fix)[1358369] URL parsing standards compliance (wu,fellows)
=> http 2.5.2

2005-11-18 (revert) Restored registration of "list" Tcl_ObjType (porter)
Reduces the ***POTENTIAL INCOMPATIBILITY*** from 2005-05-17.

2005-11-18 (bug fix)[1359094] Tclkit crash (thoyts, kupries)

2005-11-20 (bug fix)[1091431] Tcl_InitStubs failure crashes wish (english)

2005-11-27 (platform support) Darwin 64bit, Tiger copyfile(), and
Max OSX universal binaries support (steffen)

2005-11-28 (bug fix) [clock] DST transition error (mackerras,kenny)

2005-11-29 (bug fix)[1366683] [lsearch -regexp] backrefs (cleverly,fellows)

2005-11-30 (performance) recoded portions of [clock] in C (kenny)

2005-11-30 (enhancement) improved bytecode compiling of [switch] (fellows)
*** POTENTIAL INCOMPATIBILITY ***
For loading bytecode compiled and saved by earlier 8.5alpha releases

2005-12-05 (Darwin bug fix)[1034337] NFS recursive file delete (steffen)

2005-12-08 (platform support) Win x64 build (hobbs)

2005-12-09 (bug fix)[1374778] [lsearch -start $pastEnd] => -1 (fellows)

2005-12-12 (bug fix)[1377619] configure syntax error exposed in bash-3.1 (hobbs)

2005-12-13 (bug fix)[1379349] [dict for] CoW error (ring,hippler,fellows)

2005-12-18 (bug fix)[1382528] [dict for {k v} {} {}] crash (kovalenko,fellows)

2005-12-27 clock tzdata updated to Olson's tzdata2005r (kenny)

2005-12-27 libtommath updated to release 0.37 (kenny)

2006-01-09 (bug fix)[1480572] [info level $l] => "namespace inscope" (porter)

2006-01-11 (compat support)[1397843] when ::errorInfo is traced, fall back to
old pattern of stack trace construction (porter).
Reduces the ***POTENTIAL INCOMPATIBILITY*** from 2004-10-05.

2006-01-12 (bug fix)[1366227] Win: [file stat] sharing violation (darley)

2006-01-23 (bug fix)[1410553] Tcl_GetRange Unicode confusion (twylite,spjuth)

2006-01-23 (bug fix)[1412695] args handling in precompiled procs (traum,sofer)

2006-02-01 (new feature)[1275435][TIP 250] [namespace upvar] (sofer)

2006-02-01 (new feature)[958222][TIP 181] [namespace unknown] (madden)

2006-02-01 (new feature)[944803][TIP 194] [apply] (mistachkin)

2006-02-08 (new feature)[1413934][TIP 258] [encoding dirs], etc. (porter)

2006-02-09 (new feature)[1413115][TIP 215] auto-init [incr] (leitgeb)

2006-03-02 (bug fix)[1379287] norm of paths with /../ back to root (porter)

2006-03-03 (compat support) Restored registration of a "boolean" Tcl_ObjType
(porter)
Reduces the ***POTENTIAL INCOMPATIBILITY*** from 2005-05-17.

2006-03-06 (bug fix)[1439836,1444291] fix TCL_EVAL_{GLOBAL,INVOKE} handling
when auto-loading or exec traces are present (porter)

2006-03-10 (bug fix)[1437595] Win socket finalize with threads (vasiljevic)

2006-03-13 (revert 2005-07-26 change) ${prefix}/share on ::tcl_pkgPath (porter)

2006-03-14 (bug fix)[1448251] TCLX.y_TM_PATH handling (noble, kupries)

2006-03-14 (bug fix)[768659] pipeline error when last command missing (kupries)

2006-03-18 (bug fix)[1193497] Win porting of [file writable] (darley,vogel)

2006-03-18 (bug fix)[1084705] [glob -nocomplain] silence empty result only,
no other errors (darley)
***POTENTIAL INCOMPATIBILITY***

2006-03-21 (platform enhancement)[823329] HFS globbing support (steffen)

2006-03-23 (platform support) updated tcl.spec file (max)

2006-03-28 (bug fix)[1064247] BSD: path normalization with realpath() (steffen)

2006-04-03 (bug fix)[1462248] crash reading utf-8 chars spanning multiple
buffers at end of file (kraft,kupries)

2006-04-05 (bug fix)[1464039] Tcl_GetIndexFromObj: empty key (fellows)

2006-04-05 (bug fix) overdue dde, registry  patchelevel increments (porter)
=> dde 1.3.2
=> registry 1.2

2006-04-06 (bug fix)[1457515] TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
removed (steffen)

2006-04-11 (bug fix)[1458266] enter/enterstep trace interference (leunissen)

2006-04-12 (feature change)[1376892] revised definition of [:print:] (fellows)

(platform support) Use of _ANSI_ARGS_ purged.  ANSI compiler required (fellows)

Documentation improvements [1211078,1190891,1292427,1277503,1104682,1359183,
1415725,666770]

--- Released 8.5a4, April 27, 2006 --- See ChangeLog for details ---

2006-05-04 (bug fix)[1480509] srand() accept wide input (porter,afredd)

2006-05-05 (bug fix)[1481986] interactive Tcl_Main blocks main loop (porter,lin)

2006-05-13 (bug fix)[1482718] proc re-compile: preserve the previous
bytecode while references still on the stack (porter,ryazanov)

2006-05-27 (bug fix)[923072] Darwin: made unthreaded CoreFoundation notifier
naked-fork safe on Tiger (steffen)

2006-06-20 (internal change) Dropped the internal routines used to hook into
filesystem operations back in the pre-Tcl_Filesystem days. (porter)
***POTENTIAL INCOMPATIBILITY***
For extensions and programs that have never migrated to the supported Tcl 8.4
interface for virtual filesystems

2006-07-05 (enhancement) Expression parser rewrite avoids stack overflow,
reduces from O(N^2) to O(N) complexity, and greatly improves syntas error
messages (porter)
***POTENTIAL INCOMPATIBILITY***
For any code relying on exact error messages.

2006-07-20 (platform support) Mac OS X weak linking (steffen)

2006-07-20 (bug fix) Darwin: execve() works iff event loop not yet run (steffen)

2006-07-24 (bug fix)[1518166] Uninitialized Tcl_DString (afredd)

2006-07-30 (bug fix)[1426279,1505383,1494664,1531530] [clock] fixes (kenny)

2006-08-09 (bug fix)[1531184] [dict for {file stat} x {}] crash (fellows)

2006-08-10 (bug fix)[1538262,1530474] code cleanup; optimizations (afredd)

2006-08-18 (bug fix) intermittent failures in TclUnixWaitForFile() (steffen)

2006-08-18 (platform support) Darwin x86_64 (steffen)

2006-08-21 (bug fix)[1457797] Darwin 64-bit notifier hang (steffen)

2006-08-21 (bug fix) Darwin: recursively called event loop (steffen)

2006-08-21 (enhancement) Darwin: nanosec resolution clicks and [time] (steffen)

2006-08-28 (bug fix)[1547681] TclFormatObj count arguments (mistachkin,porter)

2006-08-28 (bug fix) stack.test failure on FreeBSD (mistachkin)

2006-08-30 (bug fix)[1548263] filesystem segfaults (hobbs,mccormack)

2006-08-31 (bug fix)[1541274] [expr {sqrt(-1)}] => -NaN (suchenwirth,porter)

2006-09-06 (bug fix)[999544] use of MT-safe system calls (vasiljevic)

2006-09-10 (platform support) Darwin: msgcat use CFLocale (steffen)
=> msgcat 1.4.2

2006-09-10 (new feature) tcltest option: -verbose line (steffen)
=> tcltest 2.3a1

2006-09-19 (bug fix)[1555271,1561260] Several ** operator bugs (porter)

2006-09-22 (bug fix)[1562528] NULL terminates variadic calls (fellows,ryazanov)

2006-09-22 (new feature)[1520767][TIP 268] [package] alpha/beta version;
[package require] ranges, [package prefer] selection mode (kupries)

2006-09-26 (platform support) MSVC8 AMD64 support (thoyts)

2006-09-27 (bug fix)[1567222] bignum << errors (porter)

2006-09-30 (enhancement)[1190441] quiet no-op [history] (sofer)

2006-10-04 clock tzdata updated to Olson's tzdata2006m (kenny)

2006-10-05 (bug fix)[1570718] make [lappend $nonList] complain (sofer,virden)

2006-10-05 (bug fix)[1122671] alignment fixes in unicode encoding routines
(hobbs,staplin)

2006-10-05 (enhancement) Allow "_" in Tcl Module filenames (kupries)

2006-10-05 (new feature) [set ::http::strict 0] (default value is 1) to disable
URL validity checking against RFC 2986 (hobbs)
=> http 2.5.3

2006-10-06 (new feature)[1565751][TIP 275] [binary scan] unsigned (thoyts)

2006-10-10 (bug fix)[1566526] crash cleaning up [namespace path] data (porter)

2006-10-12 (bug fix)[1576006] better error messages from [interp alias] (sofer)

2006-10-13 (platform support) get stack size on Darwin (steffen)

--- Released 8.5a5, October 20, 2006 --- See ChangeLog for details ---

2006-10-20 (configure change) Added autodetection for OS-supplied timezone
files (max)

2006-10-23 (enhancement)[1577278] Ensure the Tcl call stack always has a
CallFrame, even at level 0 (sofer)
	*** POTENTIAL INCOMPATIBILITY for users of tclInt.h ***

2006-10-23 (enhancement)[1577492] Tcl_PushCallFrame and [info level]
enhanced for ensemble rewrites (sofer)
	*** POTENTIAL INCOMPATIBILITY for [info level 0] on interp alias ***

2006-11-02 (feature change)[TIP 293] Replace {expand} with {*} (hobbs)
	*** POTENTIAL INCOMPATIBILITY with previous 8.5 alphas only ***

2006-11-04 (new feature)[TIP 274] Exponentiation operator is right
associative (porter)

2006-11-09 (new feature)[TIP 272] Added [lreverse] and [string reverse]
commands (fellows)

2006-11-14 (new feature)[TIP 261] [namespace import] returns list of
imported commands (porter)

2006-11-15 (new feature)[TIP 270] New C routines Tcl_ObjPrintf,
Tcl_AppendObjToErrorInfo, Tcl_Format, Tcl_AppendLimitedToObj,
Tcl_AppendFormatToObj, Tcl_AppendPrintfToObj (porter)

2006-11-22 (feature change) Moved TCL_REG_BOSONLY from tcl.h to tclInt (porter)

2006-11-22 (new feature)[TIP 269] Added [string is list] classification
command (mistackin, fellows)

2006-11-25 (new feature)[TIP 174] Added commands corresponding to most
expr operators in ::tcl::mathop (fellows)

2006-11-26 (platform support)[1230558] --enable-64bit on more systems (steffen)

2006-11-27 (bug fix)[1602208] Fix 64-bit handling of select() on unix where
fd was greater than 32 (fontaine, kenny)

2006-11-28 (new feature)[TIP 280] Added [info frame] command for more
Tcl-level debugging information (kupries)

2006-12-01 (feature change)[TIP 298] Change Tcl_GetBignumAndClearObj to
Tcl_TakeBignumFromObj (porter)

2006-12-01 (new feature)[TIP 287] Added [chan pending] subcommand (cleverly)

2006-12-01 (new feature)[TIP 299] Added isqrt() expr operator (kenny)

2006-12-04 (new feature)[TIP 267] Added -ignorestderr option to exec (fellows)

2006-12-05 (new feature)[TIP 291] ::tcl_platform(pointerSize) key (kupries)

2007-01-11 (configure change) Remove "-Wconversion" from deflt CFLAGS (english)

2007-01-25 (configure change) Ensure CPPFLAGS env var is used when set (steffen)

2007-02-19 (configure change) Use SHLIB_SUFFIX=".so" on HP-UX IA64 (was
".sl") (hobbs)

2007-02-20 (bug fix)[1479814] Handle Windows NT \\?\... extended paths (thoyts)

2007-03-01 (bug fix)[1671138] Fix infinite loop in compiled foreach with an
empty list (fellows)

2007-03-07 (enhancement) Improved Windows time zone tables to handle new US
DST rules (kenny)

2007-03-09 (enhancement) Improved Y2038 compliance of zoneinfo files (kenny)

2007-04-02 (enhancement) Added bytecode compilation for global, variable,
upvar and namespace upvar (sofer)

2007-04-20 (bug fix) Improve clock localization for Japanese locale (kenny)

2007-04-20 (enhancement) Document Tcl_SetNotifier & Tcl_ServiceModeHook (kenny)

2007-04-23 (bug fix) fts_open() crash on 64bit Darwin 8 or earlier (steffen)

--- Released 8.5a6, April 25, 2007 --- See ChangeLog for details ---

2007-04-30 (bug fix)[1705778] many valgrind-detected leaks corrected

2007-05-01 (bug fix)[1710709] leak in [string map] (porter)

2007-05-02 (bug fix)[1710707] leaks in filesystem paths (mistachkin,kenny)

2007-05-18 (feature change) {expand} syntax support removed. (porter)
	*** POTENTIAL INCOMPATIBILITY with previous 8.5 alphas only ***

2007-05-29 (bug fix)[1712723] Joinable thread death on 64-bit (virden,hobbs)

2007-05-30 (feature change)[1725186] When expanded literals are parsed,
(example: {*}{1 2 3}), TCL_TOKEN_EXPAND_WORD token is no longer returned.
Tokens reflecting the expansion are returned instead. (porter)
	*** POTENTIAL INCOMPATIBILITY with previous 8.5 alphas only ***

2007-06-06 (platform support) Darwin: add plist to tclsh (steffen)

2007-06-12 (enhancement) [info] is now a [namespace ensemble] (fellows)

2007-06-20 (enhancement) better `make html` results (hobbs)

2007-06-21 (feature change)[1740962] leave traces created during execution
of traced command do not fire (sofer)
	*** POTENTIAL INCOMPATIBILITY ***

2007-06-23 (bug fix) Darwin: prevent post-fork() abort() (steffen)

2007-06-27 (bug fix)[1743941] Infinite loop in Tcl_CreateTrace traces (porter)

2007-06-29 (enhancement) Tcl_Alloc alignment on Darwin (steffen)

2007-06-30 (bug fix)[1726873] crash in thread sync objects (vasiljevic,twylite)

2007-06-30 (bug fix)[1717186] [lsort -command \{ $l] leak (afredd,fellows)

2007-07-05 (bug fix)[1743676] no command named "" error message (porter,virden)

2007-07-11 (bug fix)[1752146] [while 1 {}] & [interp limit] on commands (sofer)

2007-07-31 (bug fix)[681877] tcl_platform(user) from system, not env (fellows)

2007-07-31 (enhancement)[1750051] space efficiency of Tcl variables (sofer)
	*** POTENTIAL INCOMPATIBILITY for C code that accesses internal
	Tcl structs Var, Bytecode, Namespace, or CallFrame. ***

2007-08-01 (enhancement)[1764318] word.tcl proc rewrites (petasis,fellows)

2007-08-08 (bug fix)[1770224] [tcl::mathop::>> $big1 $big2] errors (porter)

2007-08-14 (platform support) Darwin [load] from VFS on intel & 64bit (steffen)

2007-08-15 (bug fix)[1773127] corrected open mode "a+" (rottman,fellows)

2007-08-16 (bug fix)[1773040] ::errorInfo trace crash (janssen,porter)

2007-08-16 (performance)[1564517] pre-compile constant expressions (porter)

2007-08-21 (bug fix)[1775878] 'puts \' in interactive tclsh failed to move to
prompt for continuation line (porter)

2007-08-25 (bug fix)[1781282] [clock scan] case senstivity (kenny)

2007-08-25 (performance)[1767293] ** on native integer types (kenny)

2007-09-03 clock tzdata updated to Olson's tzdata2007g (kenny)

2007-09-06 (platform support) Darwin: drop support for Xcode 1.5 project, add
project for Xcode 3.0 (steffen)

2007-09-08 (bug fix)[1786481] nested [dict update] crash (fellows)

2007-09-08 (bug fix)[1710710] TclPtrSetVar leak (mistachkin,sofer)

2005-09-09 (feature removed) Tcl_ObjType "nsName" no longer registered (porter)
	*** POTENTIAL INCOMPATIBILITY for Tcl_GetObjType("nsName") ***

2007-09-10 (bug fix)[1740631] Linked variable unlink prevention (maros,hobbs)

2007-09-11 (bug fix)[1786481] [dict update] stack management (sofer)
	*** POTENTIAL INCOMPATIBILITY with previous 8.5 alpha bytecode only ***

2007-09-11 (bug fix)[1578344] [package require -exact] 8.4 compat (porter)
	*** POTENTIAL INCOMPATIBILITY with previous 8.5 alphas only ***

2007-09-11 (bug fix)[1772989,1071322] Support _, : in test constraints (porter)
=> tcltest 2.3b1

2007-09-11 (platform support) Windows AMD64 support (thoyts)

2007-09-14 (enhancement)[1793984] DTrace provider for Tcl (steffen)

2007-09-14 (bug fix)[1519940] surplus ns path invalidation (fellows,bauer)

2007-09-15 (platform support) SunOS-5.1x link with cc, not ld (steffen)

2007-09-17 (platform support)[1748251] Fix NetBSD link failures (english)

(bug fix)[1066755] Several stack efficiency efforts increases recursion limit
on Windows to be larger than the default [interp recursionlimit] value

--- Released 8.5b1, September 26, 2007 --- See ChangeLog for details ---

2007-10-02 (bug fix)[1806422] proper [tcl::tm::path] autoload (porter)

2007-10-02 (bug fix) Improve Tcl_DecrRefCount() robustness (staplin)

2007-10-11 (bug fix)[1805887] [string is int -failindex] for 0o, 0b (porter)

2007-10-15 (bug fix)[1813528] Tcl_ParseBraces read past buffer (mistachkin)

2007-10-25 (bug fix)[1726873] intermittent crash in threads (vasiljevic)

--- Released 8.5b2, October 26, 2007 --- See ChangeLog for details ---

2007-10-27 (bug fix)[1821159] fixed broken compile on x86_64 (sofer)

2007-10-27 (bug fix)[1810264] stop panic in RE lexer (fellows)

2007-10-28 (enhancement)[1826906] Embed iso8859-1 encoding in libtcl (fellows)

2007-11-01 (bug fix)[1808258] [string is ascii \000] (fellows)

2007-11-05 (bug fix)[1823576] [fconfigure $serial -xchar \000] (cassof)

2007-11-07 (performance)[1827996] binary glob matching (hobbs)

2007-11-07 (performance) binary [gets] (hobbs)

2007-11-09 (performance)[1829248] interp state reset (sofer)

2007-11-10 (performance) stack checking (sofer)

2007-11-10 (performance) list indexing bytecode (sofer)

2007-11-11 (performance)[1830038] macros to fetch Tcl_Obj intreps (sofer)

2007-11-11 (performance)[1830166] RE bytecode for simple cases (hobbs)

2007-11-13 (performance) [switch] & [regexp] use RE bytecode (hobbs, fellows)

2007-11-14 (performance) bytecode for [info exists] (fellows)

2007-11-15 (new feature)[1231022] configure option: --disable-rpath (fellows)

2007-11-15 (bug fix)[1810038] infinite loop in RE compiler (lane,porter)

Many significant documentation improvements (fellows, sofer)

--- Released 8.5b3, November 19, 2007 --- See ChangeLog for details ---

2007-11-20 (enhancement) string rep of dict has stable order (fellows)

2007-11-21 (enhancement) compiled ensemble support (fellows)

2007-11-22 (enhancement) [dict] is now an ensemble (fellows)

2007-11-23 (enhancement) [string] is now an ensemble (fellows)

2007-11-26 (bug fix)[1815573] Correct stack checking failure (sofer,golovan)

2007-11-27 (bug fix)[800753] Document single byte char limit for
[chan configure -eofchar] (cassoff)

2007-12-03 (enhancement)[1836519] [switch $val $body] safe/fast (fellows,spjuth)

2007-12-03 (release) tcltest package bump to 2.3.0 (porter)

2007-12-03 (bug fix)[1618235] fix BSD compile errors (fellows)

2007-12-05 (bug fix)[1844789] fix [lsearch -exact -integer] crash (fellows)

2007-12-05 (performance)[1845092] Tcl_ObjType for channel names (hobbs)

2007-12-14 (bug fix)[1602539] NUL pollution in [glob] result (hobbs)

2007-12-17 (bug fix)[1851832,1851524] memory alignment correction (sofer)

2007-12-18 (bug fix)[1810264] revised regexp engine to prevent debilitating
over-consumption of resources (drewry,lane,ormandy,fellows)

Several documentation and release notes improvements

--- Released 8.5.0, December 20, 2007 --- See ChangeLog for details ---

2007-12-23 (bug fix)[1857126] restore backref support to regexps (hobbs)

2007-12-26 (enhancement)[1856994] [lsort] performance (sofer)

2008-01-10 (bug fix)[1867855] fix [format %lli 0] crash (porter)

2008-01-11 (bug fix)[1850424,1860425] stack checking on *bsd (sofer,noble)

2008-01-13 (bug fix)[1353846] crash in read-only serial (hobbs,newman)

2008-01-15 (bug fix)[1869989] mem leak; expr literals (porter,melbardis)

2008-01-20 (bug fix)[1869405] binary [gets]; stacked channels (hobbs,ficicchia)

2008-01-22 (bug fix)[1867855] fix [lreverse {}] crash (sofer,madden)

2008-01-30 (bug fix)[1882373] fix Tcl_GetAlias pointer code (an00na)

Several documentation and release notes improvements

--- Released 8.5.1, February 5, 2008 --- See ChangeLog for details ---

2008-02-06 (enhancement) [clock format] performance (kenny)

2008-02-12 (bug fix)[1891827] compiled [switch -nocase] error (fellows)

2008-02-22 (bug fix)[1818565] missing state array in http::status (thoyts)
=> http 2.5.4

2008-02-26 (bug fix)[1868845] corrected [eof] ordering (thoyts)

2008-02-26 (new feature) [http::meta] command (thoyts)
=> http 2.5.5

2008-02-26 (bug fix)[1902436] fixed regexps ending in \* (hobbs)

2008-02-27 (bug fix)[1862555,1902423] [clock] range & l10n (kenny)

2008-02-28 (bug fix) [return -level 0] memory leak (porter)

2008-02-28 (bug fix) [format %llx $big] memory leak (porter)

2008-02-28 (bug fix) expression parser error message memory leak (porter)

2008-02-28 (bug fix) memory leak when enter trace modifies command (porter)

2008-02-29 (enhancement) Consumer refcounting for Tcl_SetReturnOptions()
and Tcl_AddObjToErrorInfo() (spjuth,porter)
	*** POTENTIAL INCOMPATIBILITY ***

2008-03-07 (bug fix)[1899164] Avoid expr and script bytecode confusion (porter)

2008-03-07 (bug fix)[1904907] finalize crash in Tcl_GetReturnOptions (kupries)

2008-03-10 (bug fix)[1893815] expr {abs(-1e-350)} => -0.0 (porter)

2008-03-10 (bug fix)[1901113] crash in [tcl::Bgerror {} {}] (madden,porter)

2008-03-11 (bug fix)[1911919] unset trace inf loop in namespace delete (sofer)

2008-03-12 (new feature) some HTTP 1.1 support in http (and more!) (hobbs)
=> http 2.7

2008-03-13 (enhancement) support space in INSTALL_ROOT or $builddir (steffen)

2008-03-16 (bug fix)[1903325] bytecode stack space prediction crash (fellows)

2008-03-18 (bug fix)[1914604] Tcl Modules: encoding fixed to utf-8; environment
variables without "." added to customization hooks (kupries)
	*** POTENTIAL INCOMPATIBILITY ***

2008-03-18 (bug fix)[1914503] alignment of TclStackAlloc() return (sofer)\

2008-03-20 (bug fix)[1868171] expose Tcl_GetMemoryInfo (for AOLserver) (fellows)

2008-03-24 (bug fix)[1923966] crash in [binary format x0s] (thoyts)

2008-03-27 (platform support)[1921166] Solaris 64bit build fixes (steffen)

2008-03-27 clock tzdata updated to Olson's tzdata2008b (kenny)

--- Released 8.5.2, March 28, 2008 --- See ChangeLog for details ---

2008-03-30 (bug fix)[1783544] more robust TclIsNaN() (kenny,teterin)

2008-04-01 (interface)[1819422] tclStubsPtr no longer in libtcl (porter)
	*** POTENTIAL INCOMPATIBILITY ***

2008-04-01 (bug fix)[1839067] FP round fix for Solaris/x86 (kupries,schlenker)

2008-04-02 (bug fix)[780533,1932639] [fcopy] callbacks unreliable (ferrieux)

2008-04-02 (interface)[1819422] libtclstub symbols MODULE_SCOPE (steffen)

2008-04-04 (bug fix) [chan postevent] crash (kupries)

2008-04-07 (bug fix) Fix broken [format {% d}] (max)

2008-04-07 (bug fix)[1350564] Bi-directional [fcopy] now supported (ferrieux)

2008-04-16 (bug fix)[1938497] Tcl_SetNotifier() fixes (steffen)

2008-04-16 (interface)[1938497] make stubs tables 'static const' (steffen)

2008-05-02 (new feature) [binary] is now a [namespace ensemble] (thoyts)

2008-05-07 (bug fix) [dict append] crash (mccormack,fellows)

2008-05-21 (bug fix)[1968882] [info complete "\\\n"] => 0 (porter)

2008-05-22 (bug fix)[1968245] Tcl_LogCommandInfo() accept length=-1 (darroch)

2008-05-23 (bug fix)[1965787] 32-bit overflow in [tell] result (ferrieux)

2008-05-31 (new feature)[TIP 257]  [oo::*] commands from TclOO (fellows)

2008-06-04 (new feature)[TIP 317] [binary encode]; [binary decode] (thoyts)

2008-06-06 (new feature)[TIP 230] [chan push]; [chan pop] (kupries)

2008-06-08 (enhancement)[1973096] bytecompiled [uplevel] scripts (sofer)

2008-06-12 (platform support) Solaris static build with DTrace (steffen)

2008-06-12 (platform support) Solaris/amd64 gcc 64bit support (steffen)

2008-06-13 (new feature)[TIP 285] [interp cancel]; Tcl_CancelEval() (mistachkin)

2008-06-20 (bug fix)[1999035] make [interp bgerror $i] act in $i (porter)

2008-06-23 (bug fix)[1972879] bad path intrep caching (porter)

2008-06-24 (bug fix)[1999176] crash in [glob -dir {} a] (porter)

2008-06-25 (bug fix)[1999119] Support TM packages in Safe Base (kupries)

--- Released 8.6a1, June 25, 2008 --- See ChangeLog for details ---

2008-06-29 (bug fix)[2004480] plug memory leaks (ade,porter,steffen)

2008-07-01 (enhancement)[1905562] embed recursion limit in RE engine (fellows)

2008-07-03 (bug fix)[1969717] fix package finding on Samba shares (jos)

2008-07-03 (bug fix)[1987821] mem leak in [seek] on reflected chan (kupries)

2008-07-13 (enhancement)[2017110] new Non-Recursive Evaluation implementation
enables deep Tcl evaluation stacks without deep C stacks. (sofer)

2008-07-20 (enhancement)[2008248] dict->list preserve item intreps (pasadyn)

2008-07-21 (bug fix)[582506] imported cmds now fire execution traces (sofer)

2008-07-21 (bug fix)[2015723] [file] bad use of inodes on Windows (thoyts)

2008-07-21 (new feature)[TIP 304] [chan pipe] (ferrieux)

2008-07-21 (bug fix)[2021443] more consistent "wrong # args" msgs (nijtmans)

2008-07-21 (enhancement) [info frame] returns file data in more cases (kupries)

2008-07-29 (bug fix)[2030670] fix rare panic in TclStackFree (pasadyn,sofer)

2008-08-01 Tcl_Finalize() no longer called implicitly on DLL_PROCESS_DETACH.

2008-08-05 (enhancement)[1994512] async connect logic simplified (jenglish)

2008-08-06 (bug fix)[2040295] stopped supplying a workaround for bugs
in Itcl's use of [namespace code].  Itcl now supplies its own workaround.
	*** POTENTIAL INCOMPATIBILITY for older Itcl releases ***

2008-08-06 (bug fix)[2039178] repaired guard against dispatching oo methods
in a deleted interp. (porter)

2008-08-08 tzdata updated to Olson's tzdata2008e (kenny)

2008-08-11 (bug fix)[2046846] 64bit support for http zlib crc (thoyts)
=> http 2.7.1

2008-08-11 (enhancement) automatic [package provide] for TMs (kupries)

2008-08-17 (bug fix)[2055782] crash involving Tcl_ConcatObj (sofer)

2008-08-21 (new feature) CONST-ified Tcl routines passing (Tcl_ObjType *),
(Tcl_Filesystem *), or (Tcl_Timer *) arguments (nijtmans,porter)
	*** POTENTIAL INCOMPATIBILITY ***

2008-08-21 (bug fix)[2065115] Restored ***= regexp functioning (hobbs,porter)

--- Released 8.6a2, August 25, 2008 --- See ChangeLog for details ---

2008-08-29 (bug fix)[2082299] Install TclOO header files (fellows)

2008-09-01 oo methods called during interp deletion no longer skipped if
they do not need the dying interp (fellows)

2008-09-02 (support) Dropped support for pre-ANSI compilers.  (porter)

2008-09-04 (bug fix)[2093947] var unset trace in coroutine (fellows,sofer)

2008-09-10 (enhancement) efficient list->dict conversion (elby,fellows)

2008-09-10 (bug fix)[2102930] faulty numLevels count (madden,sofer)

2008-09-16 (bug fix)[2114165] eval failure following cancel (sofer)

2008-09-17 (bug fix)[2116053] export [min] and [max] from tcl::mathfunc (sofer)

2008-09-22 (new feature)[TIP 320] oo common variable declaration (fellows)

2008-09-24 (new feature)[TIP 316] portable access to Tcl_StatBuf (fellows)

2008-09-24 (new feature)[TIP 323] [file delete], [file mkdir] zero pathNames (porter)

2008-09-25 (new feature)[TIP 315] new var: tcl_platform(pathSeparator) (vu,fellows)

2008-09-25 (new feature)[TIP 323] [global], [variable] zero varNames (porter)

2008-09-26 (new feature)[TIP 323] [lassign], [namespace upvar], [my variable] zero varNames (porter)

2008-09-26 (new feature)[TIP 323] [tcl::tm::path add|remove] zero pathNames (porter)

2008-09-26 (new feature)[TIP 323] [lrepeat] zero elements; zero repeats (porter)

2008-09-27 (bug fix)[2130992] prevent overflow crash in [lrepeat] (fellows)

2008-09-28 (new feature)[TIP 314] ensemble parameters before subcommand (hellström,fellows)

2008-09-29 (new feature)[TIP 318] revised defaults for [string trim] (poser)
	*** POTENTIAL INCOMPATIBILITY ***

2008-09-29 (new feature)[TIP 313] [lsearch -bisect] (spjuth)

2008-09-29 (new feature)[TIP 326] [lsort -stride] (elby)

2008-09-29 (new feature)[TIP 323] [linsert] zero elements (porter)

2008-09-29 (new feature)[TIP 323] [glob] zero patterns (porter)

2008-10-02 (new feature)[TIP 330] interp->result access disabled (kenny)
	*** POTENTIAL INCOMPATIBILITY ***

2008-10-03 (new feature)[TIP 265] Tcl_ParseArgv() (bromley)

2008-10-03 (new feature)[TIP 195] [tcl::prefix] (spjuth)

2008-10-04 (new feature) CONST-ified Tcl routines Tcl_GetIndexFromObj,
Tcl_RegisterConfig, Tcl_InitCustomHashTable, and routines passing
(Tcl_ChannelType *). (nijtmans)
	*** POTENTIAL INCOMPATIBILITY ***

2008-10-04 (bug fix)[2059262] unload only libraries marked unloadable (nijtmans)
	*** POTENTIAL INCOMPATIBILITY ***

2008-10-05 (new feature)[TIP 331] [lset listVar end+1 $value] (kenny)

2008-10-05 (bug fix)[2143288] correct bad isqrt() results (boffey,kenny)

2008-10-05 (new feature) CONST-ified return value of the
Tcl_FSFileAttrStringsProc prototype. (nijtmans)
	*** POTENTIAL INCOMPATIBILITY for Tcl_Filesystems ***

2008-10-07 (new feature)[TIP 327] [tailcall] (sofer)

2008-10-07 (new feature)[TIP 328] [coroutine],[yield],[info coroutine] (sofer)

2008-10-08 (bug fix)[2151707] fix stack trace from variable trace (porter)

2008-10-10 (bug fix)[2155658] crash in oo method export (fellows)

--- Released 8.6a3, October 10, 2008 --- See ChangeLog for details ---

2008-10-13 (bug fix) Fix ability to join threads on 64-bit Windows (thoyts)

2008-10-23 (bug fix)[2186888] Direct-eval [for] handling of [continue] was
broken by NRE reform (sofer,porter)

2008-10-24 (bug fix) fix failure to read SHOUTcast streams (thoyts)
=> http 2.7.2

2008-10-27 (enhancement) system encoding at startup is now "iso8859-1", and
no longer "identity".  Use of identity encoding minimized (porter)
	*** POTENTIAL INCOMPATIBILITY ***

2008-10-31 (bug fix)[2200824] revised [oo::define] to include caller
context when resolving names. (nassau,fellows)

2008-11-10 (bug fix)[2255235] [platform::shell::LOCATE] update (ring,kupries)
=> platform::shell 1.1.4

2008-11-13 (bug fix)[2269431] VFS [load] -> tempfile litter (ficicchia,nijtmans)

2008-11-26 (bug fix)[2114900] updated tclIndex file (cassoff,kenny)

2008-11-27 (bug fix)[2251175] [{*}{\{}] errors (hellström,ferrieux,porter)

2008-11-29 (new feature)[TIP 210] [file tempfile] (techentin,fellows)

2008-11-30 (bug fix)[2362156] [clock]: colon in format string (mizuno,kenny)

2008-12-02 (bug fix)[2270477] hang in channel finalization (ferrieux,kupries)

2008-12-02 (new feature)[TIP 336] Tcl_*ErrorLine() routines.  Direct access
to the errorLine field of the interp struct denied by default. (porter)
	*** POTENTIAL INCOMPATIBILITY ***
	*** Define USE_INTERP_ERRORLINE to restore access for legacy code ***

2008-12-04 (bug fix)[2385549] [file normalize] failed on some paths (porter)

2008-12-05 (new feature)[TIP 307] Tcl_TransferResult() (leunissen,fellows)

2008-12-05 (new feature)[TIP 335] Tcl_InterpActive() (mistachkin,fellows)

2008-12-09 (new feature)[TIP 337] Tcl_BackgroundException() (porter)

2008-12-10 (new feature)[TIP 341] >1 [dict filter] patterns (hellström,fellows)

2008-12-10 (new feature)[TIP 343] [format %b $n] [scan $s %b] (ferrieux)

2008-12-10 tzdata updated to Olson's tzdata2008i (kenny)

2008-12-11 (new feature)[TIP 234] [zlib] and Tcl_Zlib*() (sheffers,fellows)

2008-12-11 (bug fix)[2407783] spoil ChannelState when channel name passes
among multiple interps (kupries)

2008-12-12 (new feature)[TIP 322] Tcl_NR*() routines to enabled non-recursive
evaluation in extensions (sofer,kenny)

2008-12-09 (new feature)[TIP 338] Tcl_*StartupScript() (porter)
	*** POTENTIAL INCOMPATIBILITY for callers of Tcl*Startup* routines ***

2008-12-16 (new feature)[TIP 329] [try] [throw] (davel,fellows)

2008-12-17 (new feature)[TIP 308] package tdbc 1.0b1 (kenny)

2008-12-18 (new feature)[TIP 332] [close $chan read|write] (ferrieux)

2008-12-18 (bug fix)[2444274] panic in long commands from {*} (goth,porter)

--- Released 8.6b1, December 19, 2008 --- See ChangeLog for details ---

2008-12-27 [TIP 234] Tcl_Zlib* interface revisions (fellows)
	*** INCOMPATIBILITY with interface of 8.6b1 ***

2009-01-02 (platform support)[878333] IRIX compat for mkstemp() (fellows)

2009-01-03 (bug fix)[2481670] [clock add] error message (talvo)

2009-01-05 (bug fix)[2412068] NR-enable [source] (fellows)

2009-01-06 (bug fix)[2489836] crash unknown method dispatch (nadkarni,fellows)

2009-01-06 (bug fix)[2481109] fix context of instance name check (fellows)

2009-01-08 (enhancement) more -errorcode values (fellows)

2009-01-19 (new feature) CONFIG_INSTALL_DIR - where tclConfig.sh goes (cassoff)

2009-01-19 (platform support) better tools for BSD ports (cassoff)

2009-01-21 (bug fix)[2458202] exit crash with [chan create]d channel (kupries)

2009-01-26 (bug fix)[2446662] uniformly declare EOF on RST on sockets (ferrieux)

2009-01-26 (bug fix)[1028264] delay WSACleanup() from under our feet (ferrieux)

2009-01-29 (bug fix)[2519474] Tcl_FindCommand() bug exposed by oo (fellows)

2009-01-29 (bug fix)[2537939] Fix Tcl_OOInitStubs() for no-stubs build (fellows)

2009-02-04 (bug fix)[2561746] [string repeat] overflow crash (porter)

2009-02-05 (enhancement) optimize string operations on bytearrays (fellows)

2009-02-12 (bug fix) enable simpler [oo::define] extension (ferri,fellows)

2009-02-15 (bug fix)[2603158] Tcl_AppendObjToObj: append to self crash (porter)

2009-02-17 (platform support) MSVC and _WIN64 (hobbs)

2009-02-20 (bug fix)[2571597] [file pathtype /a] wrong result (nadkarni,porter)

2009-03-03 (bug fix)[2662434] [zlib crc32] result now unsigned (gavilan,fellows)

2009-03-15 (platform support) translate SIGINFO where defined (BSD) (teterin)

2009-03-15 (bug fix)[2687952] TSD struct memleak (mistachkin)

2009-03-18 (bug fix)[2688184] memleak in [file normalize] (mistachkin)

2009-03-20 (bug fix)[2597185] crash in Tcl_AppendStringToObj (porter)

2009-03-20 (bug fix)[2561794,2669109,2494093,2553906] string overflow (porter)

2009-03-22 (bug fix)[2502037] NR-enable [namespace unknown] (sofer)

2009-03-27 (bug fix)[2710920] [file dirname|tail /foo/] errors (epler,porter)

2009-04-08 (bug fix)[2570363] unsafe [eval]s in tcltest (bron,porter)
=> tcltest 2.3.1

2009-04-08 (platform support) more Darwin kernel patterns (steffen)
=> platform 1.0.4

2009-04-09 (bug fix)[26245326] [http::geturl] connection failures (golovan)
=> http 2.7.3

2009-04-10 (new feature) Darwin: embeddable CoreFoundation notifier (steffen)

2009-04-10 (bug fix)[1961211]  Darwin [load] back-compatibility (steffen)

2009-04-09 (new feature) http chunked+gzip modes (thoyts)
=> http 2.8.0

2009-04-11 (enhancement) clarified cmd name resolution in oo forwards (fellows)

20009-04-19 (bug fix)[2715421] http: excess bytes after POST (thoyts)
=> http 2.8.1

2009-04-30 (bug fix)[2486550] coroutine in [interp invokehidden] (sofer)

2009-05-07 (bug fix)[2785893] find command in deleted namespace (sofer)

2009-05-08 (bug fix)[2414858] tailcall in oo constructor (fellows)

2009-05-14 (new subcommand)[TIP 354] [info object namespace] (fellows)

2009-05-29 (platform support) account for ia64_32 (kupries)
=> platform 1.0.5

2009-06-02 (bug fix)[2798543] incorrect [expr] integer ** results (porter)

2009-06-10 (bug fix)[2801413] overflow in [format] (porter)

2009-06-13 (bug fix)[2802881] corrected compile env context (tasada,porter)

2009-06-17 (redesign) reduced ambition of [exit] finalization with aim to
avoid otherwise very tricky multi-thread finalization bugs. (staplin,ferrieux)
	*** POTENTIAL INCOMPATIBILITY for exit handlers ***

2009-06-26 (platform support) updates for Xcode 3.1 & 3.2 (steffen)

2009-06-30 (platform support) clang static analyzer macros (steffen)

2009-07-01 (bug fix)[2806622] Win: bad tcl_platform(user) value (thoyts)

2009-07-05 (bug fix) zlib support asynch [chan copy] on chan transform (fellows)

2009-07-12 (bug fix)[1895546] TclOO support for Itcl 4 method caching (fellows)

2009-07-13 (bug fix)[1605269] NR-related [info frame] fixes (kupries)

2009-07-14 (bug fix)[2821401] NR-enable direct eval [switch] (kenny)

2009-07-16 (bug fix)[2819200] underflow settings on MIPS systems (porter)

2009-07-19 (interface)[TIP 354] new routine Tcl_GetObjectName() (fellows)

2009-07-20 (performance) favor [string is] success cases over empty (fellows)

2009-07-22 (interface) removed TclpPanic() routine (nijtmans)

2009-07-23 (bug fix)[2820349] plug event leak in notifier (mistachkin)

2009-07-24 (bug fix)[2826248] crash in Tcl_GetChannelHandle (sonnenburg,kupries)

2009-07-31 (bug fix)[2830354] overflow in [format] (misch,porter)

2009-08-06 (bug fix)[2827000] reflected channels can signal EGAIN (kupries)

2009-08-12 (new feature)[TIP 353] Tcl_NRExprObj() (porter)

2009-08-20 (bug fix)[2823276] NR-enable [if], [for], [while] (fellows)

2009-08-20 (bug fix)[2806250] EIAS violation in ~foo pathnames (porter)

2009-08-21 (bug fix)[2837800] [glob */foo] return ./~x/foo (porter)

2009-08-24 (bug fix) nested event loop notifier w/TkAqua Cocoa (alaoui,steffen)

2009-08-25 (bug fix) [info frame] account for continuation lines (kupries)

2009-08-27 (bug fix)[2845535] overflows in [format] (porter)

2009-09-01 (bug fix) improved error message in tcltest (porter)
=> tcltest 2.3.2

2009-09-11 (bug fix)[2849860] http handle "quoted" charset value (fellows)
=> http 2.7.4

2009-09-11 (enhancement)[2314561] [subst] now bytecompiled, NR-enabled (porter)

2009-09-24 (new feature)[TIP 356] Tcl_NRSubstObj() (porter)

2009-10-04 (bug fix)[2569449] Core Foundation memory bug in Tiger (steffen)

2009-10-06 (bug fix) repair intrep loss in slave interp evaluations
introduced by first versions of the NRE conversion (nadkarni,porter)

2009-10-06 (bug fix)[1941434] broken tclTomMath.h includes (porter)

2009-10-07 (bug fix)[2871908] leaked hash table (mistachkin,kupries)

2009-10-08 (bug fix)[2874678] bignum leak in [dict incr] (fellows)

2009-10-17 (bug fix)[2629338] crash in var unset traces (raney,fellows)

2009-10-19 (bug fix)[2107634] extend [read] and [gets] to Tcl string limits
(morrison,parker,porter)

2009-10-21 (bug fix)[2882561] Haiku OS signal support (morrison,fellows)

2009-10-22 (bug fix)[2883857] [my varname arr(index)] (boudaillier,fellows)

2009-10-23 (bug fix) 0-length writes: spurious SIG_PIPE (teterin,kupries)

2009-10-24 Broken DST applied EU rules to US zones (lehenbauer,kenny)

2009-10-29 (bug fix)[2800740] halved bignum memory on 64-bit systems (porter)
        *** POTENTIAL INCOMPATIBILITY ***

2009-11-05 (bug fix)[2854929] TM search path support in Safe Base (kupries)

2009-11-05 (enhancement) rewrite of the Safe Base commands (kupries)

2009-11-11 (bug fix)[2888099] [close] loses ENOSPC error (khomoutov,ferrieux)

2009-11-11 (bug fix)[2891171] RFC 3986 compliance for ? in URL (nijtmans)
=> http 2.8.2

2009-11-12 (bug fix)[2895565] [fcopy -size] miscounts when converting encodings
(kupries)

2009-11-16 (bug fix)[2891556] encoding finalization crash (mistachkin,ferrieux)

2009-11-18 (bug fix)[2849797] consistent names for std chans (nijtmans,fellows)
        *** POTENTIAL INCOMPATIBILITY ***

2009-11-19 (enhancement) [load]able Tcltest extension (nijtmans)

2009-11-24 (bug fix)[2893771] [file stat] on Win locked files (thoyts)

2009-11-24 (bug fix)[2903011] crash call destructor from constructor (fellows)

2009-12-03 (bug fix)[2906841] Safe Base [glob ../*] fixes (fellows)

2009-12-09 (bug fix)[2901998] consistent I/O buffering (ferrieux,kupries)

2009-12-11 (bug fix)[2806407] NR-enabled coroutines (sofer)

2009-12-16 (bug fix)[2913616] msgcat: improved safe interp support (fellows)
=> msgcat 1.4.3

2009-12-22 (bug fix)[2918962] [lsort -index -stride] crash (moore,fellows)

2009-12-23 (bug fix)[2913625] [info script/nameof] in safe interps (fellows)

2009-12-28 (bug fix)[2891362] enable time limit in child interps (fellows)

2009-12-29 (bug fix)[2922555] [binary decode hex { }] crash (thoyts)

2009-12-29 (bug fix)[2895741] enable min(), max() in safe interps (fellows)

2009-12-30 (bug fix)[2824981] guard [unknown] against [set] undef (sofer)

2010-01-05 (bug fix)[2918610] [file rootname] corruption (magerya,porter)

2010-01-18 (bug fix)[2932421] less [format %s] shimmer (ferrieux)

2010-01-18 (bug fix)[2918110] [chan postevent] crash (bron,kupries)

2010-01-21 (bug fix)[2910748] NR-enable epoch fallback direct eval (sofer)

2010-01-30 (enhancement) [unset] now bytecompiled (fellows)

2010-02-01 (bug fix)[2942697] faster match: some pathological regexp patterns
(lane,fellows)

2010-02-01 (bug fix)[2939073] [array unset] unset trace crash (ferrieux)

2010-02-02 (bug fix)[2944404] crash in oo destructor (fellows)

2010-02-02 (new feature) [array] is now a [namespace ensemble] (fellows)

2010-02-05 (enhancement) [error] now bytecompiled (fellows)

2010-02-08 (bug fix)[2947783] Tcl_Zlib*flate fail on shared values (fellows)

2010-02-09 (enhancement) [try] now bytecompiled (fellows)

2010-02-11 (bug fix)[2826551] line-sensitive matching in regexp (dejong)

2010-02-11 (bug fix)[2949740] [open |noSuch rb] crash (kovalenko,fellows)

2010-02-15 (bug fix)[2950259] harden (delete obj ns -> delete obj) (fellows)

2010-02-21 (bug fix)[2954959] get sign of abs($zero) right (nijtmans)

2010-02-22 (bug fix)[2762041] zlib chan transforms read EOF too early (kupries)

2010-02-27 (bug fix)[801429] Tcl_SetMainLoop() thread safety (fellows)
        *** POTENTIAL INCOMPATIBILITY ***

2010-03-02 (enhancement) -fvisibility-hidden build support (nijtmans)

2010-03-04 (bug fix)[2962664] [oo::class destroy] crash (fellows)

2010-03-05 (interface) TclOO typedefs for function pointers (fellows)
        *** POTENTIAL INCOMPATIBILITY ***

2010-03-09 (bug fix)[2936225] stop [chan copy] to slow channel consuming all
memory with buffer backup (ferrieux)

2010-03-17 (bug fix)[2921116] crash in chan transfrom teardown (kupries)

2010-03-19 (enhancement) [throw] now bytecompiled (fellows)

2010-03-20 (enhancement) permit [fcopy] of > 2**31 bytes (fellows)

2010-03-24 (new feature) [info object methodtype] (fellows)

2010-03-24 (bug fix)[2383005] [return -errorcode] reject non-list (porter)

2010-03-25 (bug fix)[2976504] broken fstatfs() call (reeuwijk,fellows)

2010-03-30 (new feature)[TIP 362] [registry -32bit|-64bit] (courtney,fellows)
=> registry 1.3

2010-03-30 (bug fix)[2978773] refchan mem preservation (kupries)

2010-04-02 (new feature)[TIP 357] Tcl_LoadFile, Tcl_FindSymbol, etc. (kenny)

2010-04-05 (configure change)[TIP 364] default build: --enable-threads (fellows)
        *** POTENTIAL INCOMPATIBILITY ***

2010-04-02 (new feature)[TIP 348] [info errorstack], [return -errorstack]
(ferrieux)

2010-04-20 (enhancement) update bundled zlib to 1.2.5 (nijtmans)

2010-04-29 (enhancement)[2992970] optimize bytearray appends (fellows)

2010-05-19 (bug fix)[3004007] dict/list shimmer w/o string rep loss (fellows)

2010-06-09 (bug fixes) platform: several fixes for 64 bit systems (kupries)
=> platform 1.0.9

2010-06-16 (bug fix)[3016135] [clock format] in he_IL locale (nijtmans)

2010-06-18 (bug fix)[3017997] Add .cmd to file extensions for [exec] (fellows)

2010-06-28 (bug fix)[3019634] support errno.h changes in MSVC++ 2010 (nijtmans)
        *** POTENTIAL INCOMPATIBILITY ***

2010-07-02 (enhancement) -errorcode for [expr] domain errors (fellows)

2010-07-28 (bug fix)[3037525] crash deleting vars @ callframe pop (sofer)

2010-08-04 (bug fix)[3034840] mem corrupt when refchan loses interp (kupries)

2010-08-04 (enhancement) Win [load] use LOAD_WITH_ALTERED_SEARCH_PATH (hobbs)

2010-08-04 (platform support) panic on detection of win9x system (hobbs)
        *** POTENTIAL INCOMPATIBILITY ***

2010-08-10 (fix) Handle non-null-terminated bytearrys in glob matching (hobbs)

2010-08-11 (fix) copy-paste bug in [yield] implementation (sofer, goth)

2010-08-11 (platform) Drop pre-aix 4.2 support, ldAix (hobbs)

2010-08-14 (frq)[2819611] changed signatures of hash fnctions, delete-file, and get-native-path (nijtmans)
        *** POTENTIAL INCOMPATIBILITY ***

2010-08-15 (bug fix)[3045010] tweaked error message for wrong#args of lambda's (fellows)

2010-08-18 (bug fix)[3004191] fixed safe [glob] (fellows)

2010-08-21 (patch)[3034251] genStubs steal features of ttkGenStubs (nijtmans)

2010-08-26 (bug fix)[1230554] configure, OSF-1 problems, windows manifest issues (hobbs)

2010-08-30 (bug fix) [3046594,3047235,3048771] reimplemented tailcall (sofer)

2010-08-31 fixed manifest handling on windows (hobbs, kupries)

2010-08-31 windows makefile and stub changes (nijtmans)

2010-09-01 (bug fix)[3057639] compiled lappend trace consistency (hobbs,kupries)
        *** POTENTIAL INCOMPATIBILITY ***

2010-09-01 fixed safe glob handling of -directory (kupries)

2010-09-02 fixed safe glob handling of -join (kupries)

2010-09-08 (bug fix)[3059922] build with mingw on amd64 (porter, mescalinum)

2010-09-15 (bug fix)[3067036] stop hang in bytearray append (fellows)

2010-09-22 unified set of link libraries between mingw and vc (nijtmans)

2010-09-22 (bug fix)[3072640] protect writes to ::error* variables (sofer)

2010-09-23 fix leak of return options [catch $err m constant] (porter, hobbs)

2010-09-24 (bugfix)[3056775] fixed race condition in windows sockets (kupries)

2010-09-24 (performance) string eq/cmp (hobbs)

2010-09-26 (patch)[3072080] rewritten NRE core (sofer)

2010-09-28 (new feature)[TIP 162] implementation of ipv6 sockets (max)

2010-10-02 (bug fix)[3079830] properly invalidate string rep of dicts (fellows)

2010-10-06 (bug fix)[3081065] fix writing to freed Tcl_Obj (porter)

2010-10-08 fix in ipv6 code on windows (nijtmans)

2010-10-09 fixed overallocation of execution stack (sofer)

2010-10-11 windows unicode changes (nijtmans)

2010-10-12 (bug fix)[3084338] fixed meamleak in ipv6 code (max)

2010-10-13 (bug fix)[467523,983660] alt fix allows empty literal share (porter)

2010-10-15 (bugfix)[3085863] updated unicode tables (nijtmans)
        *** POTENTIAL INCOMPATIBILITY ***

2010-10-16 refactored implementation of dict iteration (fellows)

2010-10-17 (patch)[2995655] report inner contexts on error stack (ferrieux)

2010-10-19 (bug fix)[3081008] fixed bytearray zlib interaction (fellows)

2010-10-19 improved crc, appending to bytearray (fellows)

2010-10-20 improved compilation of [dict for] (fellows)

2010-10-26 Added private support to disable reverse dns (max)

2010-10-26 Prevent crashes when querying socket options (fellows, max)

2010-10-28 (bug fix)[3093120] prevent freeaddrinfo(NULL) (porter, virden)

2010-10-29 (bug fix)[2905784] stop cycle waste in short [after] (ferrieux)

2010-11-01 tzdata updated to Olson's tzdata2010o (kenny)

2010-11-04 (bug fix)[3099086] Clarified docs of var substitution (fellows)

2010-11-04 improved install targets (cassof)

2010-11-04 improved testing of sockets (max)

2010-11-05 (frq)[491789] setargv/unicode cmdline for MSVC (nijtmans)

2010-11-09 (bug fix)[3105999] fixed memleak in OO var resolver (fellows)

2010-11-15 (TIP 378)[3081184] improved TIP 280 performance (kupries)

2010-11-16 (platform) VS 2005 SP1 MSVC compiler (nijtmans)

2010-11-18 (bug fix)[3111059] leak in [namespace delete] w coroutines (sofer)

2010-11-28 [3120139,3105247] Tcl_PrintDouble improvements (kenny)

2010-11-29 (new cmd) [tcl::unsupported::inject] (ferrieux,sofer)

2010-11-30 (enhancement) Restore TclFormatInt for performance (hobbs)

2010-12-09 (new feature) [file] is now a [namespace ensemble] (fellows)

2010-12-19 (bug fix) [fcopy -size 1 -command] asynchronous (ferrieux)

2010-12-12 (platform) OpenBSD build improvements (cassoff)

2010-12-17 (platform) Revisions to support rpm 4.4.2 (cassoff)

2010-12-27 (bug fix) crash in [lsort] w multiple -index options (fellows)

2010-12-30 (bug fix)[3142026] GrowEvaluationStack OBOE (harder,sofer)

2011-01-18 (bug fix)[3001438] [info frame -1] crash (mccormack,fellows)

2011-03-01 (performance)[3168398] optimize [interp cancel] (mistachkin)

2011-03-05 (bug fix)[3185009] crash in OO variables (danckaert,fellows)

2011-03-05 (new cmd) [tcl::unsupported::assemble] (ugurlu,kenny)

2011-03-06 (bug fix)[3200987,3192636] parser buffer overruns (porter)

2011-03-08 (bug fix)[3202905] failed intrep release of interp result (mccormack)

2011-03-09 (bug fix)[3202171] repair [namespace inscope] optimizer (porter)

2011-03-10 (new version) better tcltest reporting from child interps (fellows)
=> tcltest 2.3.3

2011-03-10 (new feature) [namespace] is now a [namespace ensemble] (fellows)

2011-03-12 (interface) reduce casting by ckalloc(), ckfree() callers (fellows)

2011-03-14 (bug fix) Fixes from libtommath 0.42.0 release (fellows)

2011-03-21 (bug fix)[3216070] [load] extension from embed Tcl apps (nijtmans)
	***POTENTIAL INCOMPATIBILITY***

2011-03-27 (performance) NRE: LIST lset foreach benchmark (twylite)

2011-04-11 (bug fix)[3282869] coroutine + eval + locals crash (ferrieux,sofer)

2011-04-13 (bug fix)[2662380] crash when variable append trace unsets (sofer)

2011-04-13 (bug fix)[3285375] Buffer overflow in [concat] (porter)

2011-05-02 (internals change) revised TclFindElement() interface (porter)
	*** POTENTIAL INCOMPATIBILITY ***

2011-05-05 (enhancement) dict->list w/o string rep generation (porter)

2011-05-10 (bug fix)[3173086] Crash parsing long lists (rogers,porter)

2011-05-24 (enhancement) msgcat internal improvements (fellows)
=> msgcat 1.4.4

2011-05-25 (TIP 381) [info object|class call] [self call] [nextto] (fellows)

2011-05-31 (bug fix)[3293874] let lists grow all the way to the limit (porter)

2011-06-02 (bug fix)[3185407] cmd resolution epoch flaw (nadkarni,fellows)

2011-06-13 (bug fix)[3315098] mem leak generating double string rep (neumann)

2011-06-22 (new feature) DEB_HOST_MULTIARCH support (kupries)
=> platform 1.0.10

2011-07-15 (bug fix)[3357771] Prevent circular refs in bytecode (porter)

2011-07-28 tzdata updated to Olson's tzdata2011h (porter)

2011-08-01 (bug fix)[3383616] memleak exposed by XOTcl (neumann,sofer)

Many more Tcl built-in command errors now set an -errorcode.

--- Released 8.6b2, August 8, 2011 --- See ChangeLog for details ---

2011-07-02 (bug fix)[3349507] correct double(1[string repeat 0 23]) (kenny)

2011-07-19 (bug fix)[3371644] Tcl_ConvertElement() segfault (sader, ferrieux)

2011-07-21 (bug fix)[3372130] hypot(.) segfault (nijtmans)

2011-08-12 (bug fix)[3389764] memleaks due to reference cycles in dup'd paths

2011-08-15 (bug fix)[3390272] leak of [info script] value (porter)

2011-08-17 (bug fix)[3393150] bignum leaks in Tcl_Get*() routines (porter)

2011-08-18 (bug fix)[3393714] [string toupper] overflow (nijtmans)

2011-08-30 (bug fix)[3398794] panic in interp limit setting (gavlian,fellows)

2011-09-08 (bug fix)[3401704] revised expr parser to permit function names
like "nano()" instead of parsing as "nan o()" with missing op (duquette,porter)
	*** POTENTIAL INCOMPATIBILITY ***

2011-09-10 (bug fix)[3400658] wrong num args msg with TclOO (rsooltan,fellows)

2011-09-13 (bug fix)[3390638] solaris studio cc workaround (kechel,porter)

2011-09-13 (bug fix)[3405652] DTrace workaround (michelson,porter)

2011-09-16 (bug fix)[3391977] -headers overrides -type (ziegenhagen,fellows)
=> http 2.8.3

2011-09-16 (TIP 388) New \Uhhhhhhhh syntax (nijtmans)

2011-10-06 (enhancement) bytecode compile [dict with] (fellows)

2011-10-11 (bug fix)[2935503] [file stat] returns bad mode (nadkarni,nijtmans)

2011-10-20 (bug fix)[3418547] cmd lits and custom resolvers (soberning,fellows)

2011-10-31 (bug fix)[3414754] EIAS violation in fs paths (porter)

2011-11-22 (bug fix)[3354324] Win: [file mtime] sets wrong time (nijtmans)

2011-11-30 (bug fix)[967195] Simply args passed to child processes (nijtmans)
=> tcltest 2.3.4

2011-12-07 (bug fix)[3444754] fix [string tolower \u01C5] (nijtmans)

2011-12-11 (update)[3457031] Update [[:print:]] to Unicode 6.0 (nijtmans)

2011-12-24 (bug fix)[3464428] fix [string is graph \u0120] (nijtmans)

2012-01-08 (bug fix)[3470928] zoneinfo trouble with Windhoek data file (kenny)

2012-01-13 (bug fix)[3472316] fix retrieval of socket error (fellows)

2012-01-21 (bug fix)[3475667] [regexp] buffer read overflow (sebres)

2012-01-22 (bug fix)[3475264] [dict exists] return 0, not error (fellows)

2012-01-25 (bug fix)[3474460] [oo::copy] var resolution list (fellows)

2012-01-26 (bug fix)[3475569,3479689] mem corrupt in fs path (sebres,porter)

2012-01-30 (enhancement) improve bytecode compile of [catch] (fellows)

2012-02-02 (bug fix)[2974459,2879351,1951574,1852572,1661378,1613456] Fix
problems where [file *able] would return false results on Win/Samba (porter)

2012-02-06 (bug fix)[3484621] bump bytecode epoch on exec traces (kuhn,sofer)

2012-02-15 (bug fix)[3487626] crash compiling [dict for] (fellows)

2012-02-15 (enhancement) bytecode compile [lrange],[lreplace] (fellows)

2012-02-17 (bug fix)[2233954] compile problem on AIX & Android (nijtmans)

2012-02-29 (bug fix)[3466099] BOM in Unicode (nijtmans)

2012-03-07 (bug fix)[3498327] RFC 3986 compliance (kupries)

2012-03-26 (TIP 380) New builtin class [oo::Slot] (fellows)
	*** POTENTIAL INCOMPATIBILITY ***

2012-03-27 (TIP 397) <cloned> method to extend [oo::copy] (fellows)
	*** POTENTIAL INCOMPATIBILITY ***

2012-03-27 (TIP 395) New subcommand [string is entier] (fellows)

2012-04-02 (TIP 396) New command [yieldto] (fellows)

2012-04-04 (bug fix)[3514761] crash combining objects and ensembles (fellows)

2012-04-09 (bug fix)[2712377] [info vars] and oo variables (fellows)

2012-04-09 (bug fix)[3396896] no dups in oo var lists (fellows)

2012-04-11 (bug fix)[3448512] [clock scan 1958-01-01] fail on Win (nijtmans)

2012-04-15 (bug fix)[3517696] fix flush of zlib chan xform (fellows)

2012-04-18 tzdata updated to Olson's tzdata2012c (kenny)

2012-04-28 (TIP 398) exit non-blocking chan without flush (ferrieux)
	*** POTENTIAL INCOMPATIBILITY ***

2012-05-02 (enhancement) Better use of Intel cpuid instruction (nijtmans)

2012-05-03 (bug fix)[3428753] Unbreak synchronous [socket -async] (porter)

2012-05-10 (bug fix)[2812981] force consistent config of Tcl+pkgs (ferrieux)

2012-05-10 (bug fix)[473946] correct send of special characters (nijtmans)

2012-05-17 (bug fix)[3445787] fix [file] ensemble in Safe Base (fellows)

2012-05-17 (bug fix)[2964715] fix [glob] in Safe Base (fellows)

2012-05-17 (bug fix)[3106532] proper [switch -indexvar] values (fellows)
	*** POTENTIAL INCOMPATIBILITY ***

2012-05-21 (TIP 106) New -binary option to [dde execute|poke] (oehlmann)
=> dde 1.4.0

2012-05-23 (bug fix)[3525907] [zlib push decompress] & [chan event]
(fellows,ferrieux,kupries)

2012-05-28 (bug fix)[3529949] Protect ~ paths in Safe Base (fellows)

2012-06-21 (bug fix)[3362446] [registry keys] failure (nijtmans)
=> registry 1.3.0

2012-06-25 (bug fix)[3537605] [encoding dirs a b] error message (fellows)

2012-06-25 (bug fix)[3024359] crash when multi-thread concurrent [file system]
and Tcl_FSMountsChanged(). (porter)

2012-06-29 (bug fix)[3536888] fix locale guessing (oehlmann,nijtmans)

2012-07-05 (bug fix)[1189293] make "<<" redirect binary safe (porter)

2012-07-08 (bug fix)[3531209] accept IPv6 URLs (max)
=> http 2.8.4

2012-07-24 (bug fix) stop mem corruption in stacked channel events (max,porter)

2012-07-25 (bug fix)[3546275] [auto_execok] search match [exec] (danckaert)

2012-07-27 (update)[3464401] Support Unicode 6.2 (nijtmans)

2012-08-20 (bug fix)[3559678] [file normalize] EIAS failure (phao,dgp)

2012-08-25 (bug fix)[3561330] Ukranian translation of "March" (teterin)

2012-09-07 (TIP 404) New msgcat commands [mcflset], [mcflmset] (oehlmann)
=> msgcat 1.5.0

Many revisions to better support a Cygwin environment (nijtmans)

Dropped support for OS X versions less than 10.4 (Tiger) (fellows)

--- Released 8.6b3, September 18, 2012 --- See ChangeLog for details ---

2012-09-20 (enhancement) full Unicode support (nijtmans)
=> dde 1.4.0

2012-09-20 (enhancement) update bundled zlib to 1.2.7 (nijtmans)

2012-10-03 (bug fix) exit panic on stacked std channel (griffin,porter)

2012-10-14 (bug fix) [tcl::Bgerror] crash on non-dict options (nijtmans)

2012-10-16 (TIP 400) New [zlib] options to set compression dict (fellows)

2012-10-16 (TIP 405) New commands [lmap] and [dict map] (fellows)

2012-10-24 (enhancement) [dict unset] now bytecompiled (fellows)

2012-11-05 (TIP 413) Revisions to default [string trim*] trimset (nijtmans)
	*** POTENTIAL INCOMPATIBILITY ***

2012-11-05 (enhancement) Now bytecompiled: [array exists], [array set],
[array unset], [dict create], [dict exists], [dict merge], [format],
[info commands], [info coroutine], [info level], [info object],
[namespace current], [namespace code], [namespace qualifiers], [namespace tail],
[namespace which], [regsub], [self], [string first], [string last],
[string map], [string range], [tailcall], [yield]. (fellows)

2012-11-06 (bug fix)[3581754] avoid multiple callback on keep-alive (fellows)
=> http 2.8.5

2012-11-07 tzdata updated to Olson's tzdata2012i (kenny)

2012-11-13 (bug fix)[3567063] thread fp settings from master (mistachkin)

2012-11-14 (bug fix)[2933003] tempfile creation in $TMPDIR (fellows)

2012-11-15 (TIP 416) New [load] options -global and -lazy (nijtmans)

2012-11-20 (bug fix)[3033307] base64 trail whitespace (kovalenko,goth)

2012-12-03 (bug fix) [configure] query broke init from argv (porter)
=> tcltest 2.3.5

2012-12-13 (bug fix)[3595576] crash: [catch {} -> noSuchNs::var] (sofer,porter)

2012-12-13 (bug fix) crash: [zlib gunzip $data -header noSuchNs::var] (porter)

--- Released 8.6.0, December 20, 2012 --- See ChangeLog for details ---

2012-12-22 (bug fix)[3598150] DString to Tcl_Obj memleak (afredd)

2012-12-27 (bug fix)[3598580] Tcl_ListObjReplace() refcount fix (nijtmans)

2013-01-04 (bug fix) memleak in [format] compiler (fellows)

2013-01-08 (bug fix)[3092089,3587096] [file normalize] on junction points

2013-01-09 (bug fix)[3599395] status line processing (nijtmans)
2013-01-23 (bug fix)[2911139] repair async connection management (fellows)
=> http 2.8.6

2013-01-26 (bug fix)[3601804] Darwin segfault platformCPUID (nijtmans)

2013-01-28 (enhancement) improve ensemble bytecode (fellows)

2013-01-30 (enhancement) selected script code improvements (fradin)
=> tcltest 2.3.6

2013-01-30 (bug fix)[3599098] update to handle glibc banner changes (kupries)
=> platform 1.0.11

2013-01-31 (bug fix)[3598282] make install DESTDIR support (cassoff)

2013-02-05 (bug fix)[3603434] [file normalize a:/] flaw in VFS (porter,griffin)

2013-02-09 (bug fix)[3603695] $obj varname resolution rules (venable,fellows)

2013-02-11 (bug fix)[3603553] zlib flushing errors (vampiera,fellows)

2013-02-14 (bug fix)[3604576] msgcat use of Windows registry (oehlmann,nijtmans)
=> msgcat 1.5.1

2013-02-19 (bug fix)[2438181] report errors in trace handlers (yorick)

2013-02-21 (bug fix)[3605447] unbreak [namespace export -clear] (porter)

2013-02-23 (bug fix)[3599194] fallback IPv6 routines (afredd,max)

2013-02-27 (bug fix)[3606139] stop crash in [regexp] (lane)

2013-03-03 (bug fix)[3606258] major serial port update (english)

2013-03-06 (bug fix)[3606683] [regexp (((((a)*)*)*)*)* {}] hangs
(grathwohl,lane,porter)

2013-03-12 (enhancement) better build support for Debian arch (shadura)

2013-03-19 (bug fix)[2893771] [file stat] on locked files (thoyts,nijtmans)

2013-03-21 (bug fix)[2102614] [auto_mkindex] ensemble support (griffin)

2013-03-27 Tcl_Zlib*() routines tolerate NULL interps (porter

2013-04-04 (bug fix) Support URLs with query but no path (max)
=> http 2.8.7

2013-04-08 (bug fix)[3610026] regexp crash on color overflow (linnakangas)

2013-04-29 (enhancement) [array set] compile improvement (fellows)

2013-04-30 (enhancement) broaden glibc version detection (kupries)
=> platform 1.0.12

2013-05-06 (platform support) Cygwin64 (nijtmans)

2013-05-15 (enhancement) Improved [list {*}...] compile (fellows)

2013-05-16 (platform support) mingw-4.0 (nijtmans)

2013-05-19 (platform support) FreeBSD updates (cerutti)

2013-05-20 (bug fix)[3613567] access error temp file creation (keene)

2013-05-20 (bug fix)[3613569] temp file open fail can crash [load] (keene)

2013-05-22 (bug fix)[3613609] [lsort -nocase] failed on non-ASCII (fellows)

2013-05-28 (bug fix)[3036566] Use language packs (Vista+) locale (oehlmann)
=> msgcat 1.5.2

2013-05-29 (bug fix)[3614102] [apply {{} {list [if 1]}}] stack woes (porter)

2013-06-03 Restored lost performance appending to long strings (elby,porter)

2013-06-05 (bug fix)[2835313] [while 1 {foo [continue]}] crash (fellows)

2013-06-17 (bug fix)[a876646] [:cntrl:] includes \x00 to \x1f (nijtmans)

2013-06-27 (bug fix)[983509] missing encodings for config values (nijtmans)

2013-06-27 (bug fix)[34538b] apply DST in 2099 (lang)

2013-07-02 (bug fix)[32afa6] corrected dirent64 check (griffin)

2013-07-06 tzdata updated to Olson's tzdata2013d (kenny)

2013-07-10 (bug fix)[86fb5e] [info frame] in compiled ensembles (porter)

2013-07-18 (bug fix)[1c17fb] revisd syntax errorinfo that shows error (porter)

2013-07-26 (bug fix)[6585b2] regexp {(\w).*?\1} abb (lane)

2013-07-29 [string is space \u202f] => 1 (nijtmans)

2013-08-01 [a0bc85] Limited support for fork with threads (for Rivet) (nijtmans)

2013-08-01 (bug fix)[1905562] RE recursion limit increased to support
reported usage of large expressions (porter)

2013-08-02 (bug fix)[9d6162] superclass slot empty crash (vdgoot,fellows)

2013-08-03 (enhancement)[3611643] [auto_mkindex] support TclOO (fellows)

2013-08-14 (bug fix)[a16752] Missing command delete callbacks (porter)

2013-08-15 (bug fix)[3610404] reresolve traced forwards (porter)

2013-08-15 Errors from execution traces become errors of the command (porter)

2013-08-23 (bug fix)[8ff0cb9] Tcl_NR*Eval*() schedule only, as doc'd (porter)

2013-08-29 (bug fix)[2486550] enable [interp invokehidden {} yield] (porter)

2013-09-01 (bug fix)[b98fa55] [binary decode] fail on whitespace (reche,fellows)

2013-09-07 (bug fix)[86ceb4] have tm path favor first provider (neumann,porter)

2013-09-09 (bug fix)[3609693] copied object member variable confusion (fellows)
=> TclOO 1.0.1

2013-09-17 (bug fix)[2152292] [binary encode uuencode] corrected (fellows)

2013-09-19 (bug fix)[3487626] segfaults in [dict] compilers (porter)

2013-09-19 (bug fix)[31661d2] mem leak in [lreplace] (ade,porter)

Many optmizations, improvements, and tightened stack management in bytecode.

--- Released 8.6.1, September 20, 2013 --- https://core.tcl-lang.org/tcl/ for details

2013-09-27 (enhancement) improved ::env synchronization (fellows)

2013-10-20 (bug fix)[2835313] segfault from
[apply {{} {while 1 {a {*}[return -level 0 -code continue]}}}] (fellows)

2013-10-22 (bug fix)[3556215] [scan %E%G%X] support (fellows)

2013-10-25 (bug fix)[3eb2ec1] upper case scheme names in url. (nijtmans)
=> http 2.8.8

2013-10-29 (bug fix)[414d103] HP-UX: restore [exec] in threaded Tcl (nijtmans)

2013-11-04 (bug fix) C++ friendly stubs struct declarations (nijtmans)

2013-11-05 (bug fix)[426679e] OpenBSD man page rendering (nijtmans)

2013-11-12 (bug fix)[5425f2c] [fconfigure -error] breaks [socket -async]

2013-11-20 (bug fix) Improved environment variable management (nijtmans)
=> tcltest 2.3.7

2013-11-21 (platforms) Support for Windows 8.1 (nijtmans)

2013-12-06 (RFE) improved [foreach] bytecode (fellows)

2013-12-10 (RFE) improved [lmap] bytecode (sofer)

2013-12-11 (RFE) improved [catch] bytecode (sofer)

2013-12-18 (bug fix)[0b874c3] SEGV [coroutine X coroutine Y info frame] (porter)

2013-12-20 (RFE) reduced numeric conversion in bytecode (sofer)

2014-01-07 (RFE) compilers for  [concat], [linsert], [namespace origin],
[next], [string replace], [string tolower], [string totitle], [string toupper],
[string trim], [string trimleft], [string trimright] (fellows)

2014-01-22 (RFE) compilers for [nextto], [yieldto] (fellows)

2014-02-02 (RFE) compiler for [string is] (fellows)

2014-02-06 (bug fix)[a4494e2] panic in test namespace-13.2 (porter)

2014-03-20 (bug fix)[2f7cbd0] FreeBSD 10.0 build failure (nijtmans)

2014-03-26 (RFE)[b42b208] Cygwin: [file attr -readonly -archive -hidden -system]
(nijtmans)

2014-03-27 (bug fix) segfault iocmd-23.11 (porter)

2014-04-02 (bug fix)[581937a] Win: readable event on async connect failure

2014-04-04 (bug fix)[581937a,97069ea] async socket connect fail (oehlmann)

2014-04-10 (bug fix)[792641f] Win: no \ in normalized path (nijtmans)

2014-04-11 (bug fix)[3118489] protect NUL in filenames (nijtmans)

2014-04-15 (bug fix)[88aef05] segfault iocmd-21.20 (porter)

2014-04-16 (update) Win: use Winsock 2.2 (nijtmans)

2014-04-16 (bug fix)[d19a30d] segfault clock-67.[23] (sebres)

2014-04-21 (bug fix) segfault iocmd-21.2[12] (porter)

2014-04-22 (bug fix) segfault iogt-2.4 (porter)

2014-04-23 (bug fix)[3493120] memleak in thread exit

2014-05-08 refactoring of core I/O functions (porter)

2014-05-09 (bug fix)[3389978] Win: extended paths support (nijtmans)

2014-05-09 (bug fix) segfault iocmd-32.1 (porter)

2014-05-11 (bug fix)[6d2f249] nested ensemble compile failure (fellows)

2014-05-17 (RFE)[47d6625] wideint support in [lsearch -integer] [lsort -integer] (nijtmans)
	*** POTENTIAL INCOMPATIBILITY ***

2014-05-20 (bug fix) Stop eof and blocked state leaking thru stacks (porter)
        *** POTENTIAL INCOMPATIBILITY ***

2014-05-20 (bug fix)[13d3af3] Win: socket -async tried only first IP address

2014-05-28 (platforms) work around systems that fail when a shared library
is deleted after it is [load]ed (kupries)

2014-05-31 (bug fix) chan events on pipes must be on proper ends (porter)

2014-06-04 (bug fix) socket-2.12 (porter)

2014-06-05 (bug fix) io-12.6 (kupries,porter)

2014-06-15 (RFE)[1b0266d] [dict replace|remove] return canonical dict (fellows)
        *** POTENTIAL INCOMPATIBILITY ***

2014-06-16 (bug fix) socket-2.13 workaround broken select() (porter)

2014-06-20 (bug fix)[b47b176] iortrans.tf-11.0 (porter)

2014-06-22 (RFE)[2f9df4c] -cleanup scripts before -out compare (nijtmans)

2014-07-04 (update) Update Unicode data to 7.0 (nijtmans)
        *** POTENTIAL INCOMPATIBILITY ***

2014-07-08 (bug) [chan push] converts blocked writes to error (aspect,porter)

2014-07-10 (bug fix)[7368d2] memleak Tcl_SetVar2(..,TCL_APPEND_VALUE) (porter)
        *** POTENTIAL INCOMPATIBILITY ***

2014-07-11 (bug) leaks in SetFsPathFromAny, [info frame] (porter)

2014-07-15 (bug) compress dict leak in zlib xform channel close (porter)

2014-07-17 (bug fix)[9969cf8] leak trace data in coroutine deletion (porter)

2014-07-18 (RFE)[b43f2b4] fix [lappend] multi performance collapse (fellows)

2014-07-19 (bug fix)[75b8433] memleak managing oo instance lists (porter)

2014-07-21 (bug fix)[e6477e1] memleak in AtForkChild() (porter)

2014-07-22 (bug fix)[12b0997] memleak in iocmd.tf-32.0 (porter)

2014-07-28 (RFE) Optimized binary [chan copy] by moving buffers (porter)

2014-07-30 (enhancement) use refcounts, not Tcl_Preserve to manage lifetime
of Tcl_Channel  (porter)
        *** POTENTIAL INCOMPATIBILITY ***

2014-07-31 (bug fix)[a84a720] double free in oo chain deletion (porter)

2014-08-01 (bug fix)[e75faba] SEGV [apply {{} {namespace upvar a b [x]}}] (porter)

2014-08-01 (update) "macosx*-i386-x86_64" "macosx-universal" no longer compatible (kupries)
=> platform 1.0.13

2014-08-12 tzdata updated to Olson's tzdata2014f (kenny)

2014-08-17 (bug fix)[7d52e11] [info class subclasses oo::object] should
include ::oo::class (fellows)

2014-08-25 (TIP 429) New command [string cat] (leitgeb,ferrieux)

--- Released 8.6.2, August 27, 2014 --- https://core.tcl-lang.org/tcl/ for details

2014-08-28 (bug)[b9e1a3] Correct Method Search Order (nadkarni,fellows)
=> TclOO 1.0.3
        *** POTENTIAL INCOMPATIBILITY ***

2014-09-05 (bug)[ccc2c2] Regression [lreplace {} 1 1] (bron,fellows)

2014-09-08 (bug)<oo-1.18.2> Crash regression in [oo::class destroy] (porter)

2014-09-09 (bug)[84af11] Regress [regsub -all {\(.*} a(b) {}] (fellows)

2014-09-10 (bug)[cee90e] [try {} on ok {} - on return {} {}] panic (porter)

2014-09-20 (feature) [tcl::unsupported::getbytecode] disassember (fellows)

2014-09-27 (enhancement) [string cat] bytecode optimization (leitgeb,ferrieux)

2014-09-27 (bug)[82521b] segfault in mangled bytecode (ogilvie,sofer)

2014-10-02 (bug)[bc5b79] Hang in some [read]s of limited size (rogers,porter)

2014-10-03 (bug)[bc1a96] segfault in [array set] of traced array (tab,porter)

2014-10-08 (bug)[59a2e7] MSVC14 compile support (dower,nijtmans)

2014-10-10 (bug)[ed29c4] [fcopy] treats [blocked] as error (rowen,porter)

2014-10-10 (bug)[bf7135] regression in Tcl_Write() interface (porter)

2014-10-18 (bug)[10dc6d] fix [gets] on non-blocking channels (fassel,porter)

2014-10-26 Support for Windows 10 (nijtmans)

2014-10-31 (bug)[dcc034] restore [open comX: r+] (lll,nijtmans)

2014-11-05 (bug)[214cc0] Restore [lappend v] return value (sayers,porter)

2014-11-06 (bug)[5adc35] Stop forcing EOF to be permanent (porter)

--- Released 8.6.3, November 12, 2014 --- https://core.tcl-lang.org/tcl/ for details

2014-11-21 (bug)[743338] Win: socket error encoding (ladayaroslav,nijtmans)

2014-12-01 (bug) restore tbcload/tclcompiler support (kupries)

2014-12-03 (bug)[0c043a] Fix compiled [set var($) val] (porter)

2014-12-04 (bug)[d2ffcc] Limit $... and bareword parsing to ASCII (ladayaroslav,porter)
        *** POTENTIAL INCOMPATIBILITY ***

2014-12-06 (bug)[c6cd4a] Win: hang in async socket connection (shults,nadkarni)

2014-12-10 tzdata updated to Olson's tzdata2014j (venkat)

2014-12-13 fix header files installation on OS X (houben)

2014-12-17 (TIP 427) [fconfigure $h -connecting, -peername, -sockname] (oehlmann,rmax)

2014-12-18 (bug)[af08c8] Crash in full finalize encoding teardown (porter)

2014-12-18 (bug)[7c187a] [chan copy] crash (io-53.17) (benno,porter)

2015-01-26 (bug)[df0848] Trouble with INFINITY macro (dower,nijtmans)

2015-01-29 (bug) Stop crashes when extension var resolvers misbehave (porter)

2015-01-29 (bug)[088727] [read] past EOF (io-73.4) (fenugrec,porter)

2015-02-11 tzdata updated to Olson's tzdata2015a (venkat)

2015-02-20 (bug)[32b615] Fix compiled [lreplace] (lreplace-4.[345]) (aspect)

2015-03-10 (enhancement) Revise OS X notifier for better Cocoa (walzer)
        *** POTENTIAL INCOMPATIBILITY ***

--- Released 8.6.4, March 12, 2015 --- https://core.tcl-lang.org/tcl/ for details

2015-03-19 (bug)[e66e44] Win: Ctrl-C/Ctrl-Break in console not EOF (nadkarni)

2015-03-21 (bug)[d87cb1] Proper tailcall from compiled ensembles (sofer)

2015-04-23 (bug)[19ea02] Win: shared read from linked dirs (bogdan,oehhar)

2015-04-24 (bug)[879a07] Incomplete chars @ buffer ends (leunissen,porter)

2015-04-29 (bug)[894da1] Hang flushing blocking channels (yorick)

2015-05-14 (enhance)[b9d043] Default use of gzip transfer encoding (fellows)
=> http 2.8.9
        *** POTENTIAL INCOMPATIBILITY ***

2015-05-15 (bug)[9dd1bd] destructor [self] after failed constructor (calvo,fellows)

2015-05-15 (bug)[0f42ff] [tailcall] combined with [next] (aspect,fellows)

2015-05-18 (bug)[c11a51] http: race condition in -accept option (fellows)

2015-05-19 (enhance) More pure lists from compiled [list] (porter,fellows)

2015-05-27 (enhancement) Relax memdebug constraint on extensions (kupries)

2015-06-03 (bug)[268b23] crash in traced [expr] (execute-11.2)(tomkinson,porter)

2015-06-11 (bug)[478c44] Memleak in zlib compresion errors (mistachkin)

2015-06-16 (bug)[e770d9] Higher baud on serial channels (woods,nijtmans)

2015-06-18 (update) Update Unicode data to 8.0 (nijtmans)
        *** POTENTIAL INCOMPATIBILITY ***

2015-06-18 (bug)[a4cb3f] compiled [lreplace] handling of end (bron,aspect)

2015-06-23 (enhance) Use Unicode SendMessageTimeout() (nijtmans)
=> registry 1.3.1

2015-06-25 (TIP 412) msgcat dynamic locale change and package private locale (oehlmann)
=> msgcat 1.6.0

2015-07-05 (bug)[a0ece9] crash in traced [expr] (execute-11.3) (hans,porter)

2015-07-10 (TIP 436) [info object isa] favors 'false' over error (fellows)
=> TclOO 1.0.4

2015-07-15 (bug)[b1534b][9bad63] writes beyond buffer bounds (hanno,porter)

2015-07-18 (bug)[a3309d] Memleak in compiled [unset a($i)] (jeff,porter)

2015-07-23 (bug)[57945b] lock in forking/multi-threading (neumann,mistachkin)

2015-07-29 (bug)[3e7eca] Allocation overflow in expr parsing (rickyb,porter)

2015-07-30 (bug)[f00009] Win: Memleak in [file] (rp,sebres)

2015-07-31 (bug) Correct problems found in Coverity audit (sofer)

2015-08-19 (bug)[00189c] MSVC 14: semi-static UCRT support (dower,nijtmans)

2015-08-26 (bug)[0df7a1] Tolerate getcwd() failures (cato,nijtmans)

2015-09-21 (bug)[1115587][a3c350][d7ea9f][0e0e15][187d7f] Many fixes and
improvements to regexp engine from Postgres (lane,porter,fellows,seltenreich)

2015-09-23 (enhance) hash lookup microoptimization (hipp)

2015-09-23 (bug)[e0a7b3] Input buffer draining & file events (griffin,porter)

2015-09-29 (bug)[219866] Cygwin support error (yorick,nijtmans)
=> platform 1.0.14

2015-10-06 (bug)[b42a85] Win: [file normalize ~user] wrong dir (nadkarni)

2015-10-21 (bug)[1080042][8f2450] More regexp from Postgres (lane,porter)

2015-10-23 (bug)[4a0c16] [clock] react to msgcat locale change (oehlmann)

2015-11-10 (bug)[261a8a] Overflow segfault in I/O translation (brooks,porter)

2015-11-20 (bug)[40f628] ListObjReplace callers fail to detect max (porter)

2015-11-30 (enhance)[32c574] Improve list growth performance (brooks,porter)

2015-12-11 (bug)[c9eb6b] tolerate unset ::env(TZ) (gahr, nijtmans)

2016-01-29 (TIP 440) tcl_platform(engine) -- Tcl implementation (mistachkin)

2016-02-03 (bug)[25842c] stream [zlib deflate] fails with 0 input (ade,fellows)

2016-02-04 (bug)[3d96b7][593baa][cf74de] crashes in OO teardown (porter,fellows)

2016-02-22 (bug)[9b4702] [info exists env(missing)] kills trace (nijtmans)

--- Released 8.6.5, February 29, 2016 --- https://core.tcl-lang.org/tcl/ for details

2016-03-01 (bug)[803042] mem leak due to reference cycle (porter)

2016-03-08 (bug)[bbc304] reflected watch race condition (porter)

2016-03-17 (bug)[fadc99] compile-5.3 (rodriguez,porter)

2016-03-17 (enhancement)[1a25fd] compile [variable ${ns}::v] (porter)

2016-03-20 (bug)[1af8de] crash in compiled [string replace] (harder,fellows)

2016-03-21 (bug)[d30718] segv in notifier finalize (hirofumi,nijtmans)

2016-03-23 (enhancement)[7d0db7] parallel make (yarda,nijtmans)

2016-03-23 [f12535] enable test bindings customization (vogel,nijtmans)

2016-04-04 (bug)[47ac84] compiled [lreplace] fixes (aspect,ferrieux,fellows)
        *** POTENTIAL INCOMPATIBILITY ***

2016-04-08 (bug)[866368] RE \w includes 'Punctuation Connector' (nijtmans)

2016-04-08 (bug)[2538f3] Win crash Tcl_OpenTcpServer() (griffin)

2016-04-10 [07d13d] Restore TclBlend support lost in 8.6.1 (buratti)

2016-05-13 (bug)[3154ea] Mem corruption in assembler exceptions (tkob,kenny)

2016-05-13 (bug) registry package support any Unicode env (nijtmans)
=> registry 1.3.2

2016-05-21 (bug)[f7d4e] [namespace delete] performance (fellows)

2016-06-02 (TIP 447) execution time verbosity option (cerutti)
=> tcltest 2.4.0

2016-06-16 (bug)[16828b] crash due to [vwait] trace undo fail (dah,porter)

2016-06-16 (enhancement)[4b61af] good [info frame] from more cases (beric)

2016-06-21 (bug)[c383eb] crash in [glob -path a] (oehlmann,porter)

2016-06-21 (update) Update Unicode data to 9.0 (nijtmans)
        *** POTENTIAL INCOMPATIBILITY ***

2016-06-22 (bug)[16896d] Tcl_DString tolerate append to self. (dah,porter)

2016-06-23 (bug)[d55322] crash in [dict update] (yorick,fellows)

2016-06-27 (bug)[dd260a] crash in [chan configure -dictionary] (madden,aspect)

2016-07-02 (bug)[f961d7] usage message with parameters with spaces (porter)
        *** POTENTIAL INCOMPATIBILITY ***

2016-07-02 (enhancement)[09fabc] Sort order of -relateddir (lanam)

2016-07-07 (bug)[5d7ca0] Win: [file executable] for .cmd and .ps1 (nadkarni)
        *** POTENTIAL INCOMPATIBILITY ***

2016-07-08 (bug)[a47641] [file normalize] & Windows junctions (nadkarni)

2016-07-09 [ae61a6] [file] handling of Win hardcoded names (CON) (nadkarni)
        *** POTENTIAL INCOMPATIBILITY ***

2016-07-09 [3613671] [file owned] (more) useful on Win (nadkarni)

2016-07-09 (bug)[1493a4] [namespace upvar] use of resolvers (beric,fellows)
        *** POTENTIAL INCOMPATIBILITY ***

2016-07-10 (bug)[da340d] integer division in clock math (nadkarni)

2016-07-20 tzdata updated to Olson's tzdata2016f (venkat)

--- Released 8.6.6, July 27, 2016 --- https://core.tcl-lang.org/tcl/ for details

2016-09-07 (bug)[c09edf] Bad caching with  custom resolver (neumann,nijtmans)

2016-09-07 (bug)[4dbdd9] Memleak in test var-8.3 (mr_calvin,porter)

2016-10-03 (bug)[2bf561] Allow empty command as alias target (yorick,nijtmans)
        *** POTENTIAL INCOMPATIBILITY ***

2016-10-04 (bug)[4d5ae7] Crash in async connects host no address (gahr,fellows)

2016-10-08 (bug)[838e99] treat application/xml as text (gahr,fellows)
=> http 2.8.10

2016-10-11 (bug)[3cc1d9] Thread finalization crash in zippy (neumann)

2016-10-12 (bug)[be003d] Fix [scan 0x1 %b], [scan 0x1 %o] (porter)

2016-10-14 (bug)[eb6b68] Fix stringComp-14.5 (porter)

2016-10-30 (bug)[b26e38] Fix zlib-7.8 (fellows)

2016-10-30 (bug)[1ae129] Fix memleak in [history] destruction (fellows)

2016-11-04 (feature) Provisional Tcl 9 support in msgcat and tcltest (nijtmans)
=> msgcat 1.6.1
=> tcltest 2.4.1

2016-11-04 (bug)[824752] Crash in Tcl_ListObjReplace() (gahr,porter)

2016-11-11 (bug)[79614f] invalidate VFS mounts on sytem encoding change (yorick)

2016-11-14 OSX: End panic() as legacy support macro; system conflicts (nijtmans)
        *** POTENTIAL INCOMPATIBILITY ***

2016-11-15 (bug) TclOO fix stops crash mixing Itcl and snit (fellows)

2016-11-17 (update) Reconcile libtommath updates; purge unused files (nijtmans)
        *** POTENTIAL INCOMPATIBILITY ***

2017-01-09 (bug)[b87ad7] Repair drifts in timer clock (sebres)

2017-01-17 (update) => zlib 1.2.11 (nijtmans)

2017-01-31 (bug)[39f630] Revise Tcl_LinkVar to tolerate some prefixes (nijtmans)
        *** POTENTIAL INCOMPATIBILITY ***

2017-02-01 (bug)[d0f7ba] Improper NAN optimization. expr-22.1[01] (aspect)

2017-02-26 (bug)[25842c] zlib stream finalization (aspect)

2017-03-07 (deprecate) Remove unmaintained makefile.bc file (nijtmans)
        *** POTENTIAL INCOMPATIBILITY ***

2017-03-14 (enhancement) [clock] and [encoding] are now ensembles (kenny)

2017-03-15 (enhancement) several [clock] subcommands bytecoded (kenny)

2017-03-23 tzdata updated to Olson's tzdata2017b (jima)

2017-03-29 (bug)[900cb0] Fix OO unexport introspection (napier)

2017-04-12 (bug)[42202b] Nesting imbalance in coro injection (nadkarni,sebres)

2017-04-18 (bug)[bc4322] http package support for safe interps (nash,nijtmans)

2017-04-28 (bug)[f34cf8] [file join a //b] => /b (neumann,porter)

2017-05-01 (bug)[8bd13f] Windows threads and pipes (sebres,nijtmans)

2017-05-01 (bug)[f9fe90] [file join //a b] EIAS violation (aspect,porter)

2017-05-04 (bug) Make test filesystem-1.52 pass on Windows (nijtmans)

2017-05-05 (bug)[601522] [binary] field spec overflow -> segfault (porter)

2017-05-08 (bug)[6ca52a] http memleak handling keep-alive (aspect,nijtmans)
=> http 2.8.11

2017-05-29 (bug)[a3fb33] crash in [lsort] on long lists (sebres)

2017-06-05 (bug)[67aa9a] Tcl_UtfToUniChar() revised handling invalid UTF-8 (nijtmans)
        *** POTENTIAL INCOMPATIBILITY ***

2017-06-08 (bug)[2738427] Tcl_NumUtfChars() corner case utf-4.9 (nijtmans)

2017-06-22 (update) Update Unicode data to 10.0 (nijtmans)
        *** POTENTIAL INCOMPATIBILITY ***

2017-06-22 (TIP 473) Let [oo::copy] specify target namespace (fellows)

2017-06-26 (bug)[46f801] Repair autoloader fragility (porter)

2017-07-06 (bug)[adb198] Plug memleak in TclJoinPath (sebres,porter)

2017-07-17 (bug)[fb2208] Repeatable tclIndex generation (wiedemann,nijtmans)

--- Released 8.6.7, August 9, 2017 --- https://core.tcl-lang.org/tcl/ for details

Changes to 8.7a1 include all changes to the 8.6 line through 8.6.7,
plus the following, which focuses on the high-level feature changes
in this changeset (new minor version) rather than bug fixes:

2016-03-17 (bug)[0b8c38] socket accept callbacks always in global ns (porter)
        *** POTENTIAL INCOMPATIBILITY ***

2016-07-01 Hack accommodations for legacy Itcl 3 disabled (porter)

2016-07-12 Make TCL_HASH_TYPE build-time configurable (nijtmans)

2016-07-19 (bug)[0363f0] Partial array search ID reform (porter)

2016-07-19 (feature removed) Tcl_ObjType "array search" unregistered (porter)
	*** POTENTIAL INCOMPATIBILITY for Tcl_GetObjType("array search") ***

2016-10-04 Server socket on port 0 chooses port supporting IPv4 * IPv6 (max)

2016-11-25 [array names -regexp] supports backrefs (goth)

2017-01-04 (TIP 456) New routine Tcl_OpenTcpServerEx() (limeboy)

2017-01-04 (TIP 459) New subcommand [package files] (nijtmans)

2017-01-16 threaded allocator initialization repair (vasiljevic,nijtmans)

2017-01-30 Add to Win shell builtins: assoc ftype move (ashok)

2017-03-31 TCL_MEM_DEBUG facilities better support 64-bit memory (nijtmans)

2017-04-13 \u escaped content in msg files converted to true utf-8 (nijtmans)

2017-05-18 (TIP 458) New epoll or kqueue notifiers are default (alborboz)

2017-05-31 Purge build support for SunOS-4.* (stu)

2017-06-22 (TIP 463) New option [regsub ... -command ...] (fellows)

2017-06-22 (TIP 470) Tcl_GetDefineContextObject();[oo::define [self]] (fellows)
=> TclOO 1.2.0

2017-06-23 (TIP 472) Support 0d as prefix of decimal numbers (iyer,griffin)

2017-08-31 (bug)[2a9465] http state 100 continue handling broken (oehlmann)

2017-09-02 (bug)[0e4d88] replace command, delete trace kills namespace (porter)

--- Released 8.7a1, September 8, 2017 --- http://core.tcl.tk/tcl/ for details

2017-08-10 [array names -regexp] supports backrefs (goth)

2017-08-10 Fix gcc build failures due to #pragma placement (cassoff,fellows)

2017-08-29 (bug)[b50fb2] exec redir append stdout and stderr to file (coulter)

2017-08-31 (bug)[2a9465] http state 100 continue handling broken (oehlmann)
=> http 2.8.12

2017-09-02 (bug)[0e4d88] replace command, delete trace kills namespace (porter)

2017-10-19 (bug)[1a5655] [info * methods] includes mixins (fellows)

2017-10-23 tzdata updated to Olson's tzdata2017c (jima)

2017-10-24 (bug)[fc1409] segfault in method cloning, oo-15.15 (coulter,fellows)

2017-11-03 (bug)[6f2f83] More robust [load] for ReactOS (werner)

2017-11-08 (bug)[3298012] Stop crash when hash tables overflow 32 bits (porter)

2017-11-14 (bug)[5d6de6] Close failing case of [package prefer stable] (kupries)

2017-11-17 (bug)[fab924] Fix misleading [load] message on Windows (oehlmann)

2017-12-05 (bug)[4f6a1e] Crash when ensemble map and list are same (sebres)

2017-12-06 (bug)[ce3a21] file normalize failure when tail is empty (porter)

2017-12-08 (new)[TIP 477] nmake build system reform (nadkarni)

2017-12-19 (bug)[586e71] EvalObjv exception handling at level #0 (sebres,porter)

--- Released 8.6.8, December 22, 2017 --- https://core.tcl-lang.org/tcl/ for details

2018-02-11 (enhance) stop blocking conversion of object to/from class (coulter)

2018-02-12 (enhance) NR-enable [package require] (coulter)

2018-02-14 (bug)[9fd5c6] crash in object deletion, test oo-11.5 (coulter)

2018-02-14 (bug)[3c32a3] crash deleting object with class mixed in (coulter)

2018-02-15 (platform) stop using -lieee, removed from glibc-2.27 (porter)
***POTENTIAL INCOMPATIBILITY for math programs that embed Tcl***

2018-02-23 (bug)[8e6a9a] bad binary [string match], test string-11.55 (porter)

2018-03-05 (bug)[1873ea] repair multi-thread std channel init (sebres)

2018-03-09 (bug)[db36fa] broken bytecode for index values (porter)

2018-03-13 (bug) broken compiled [string replace], test string-14.19 (porter)

2018-03-14 (bug) [string trim*] engine crashed on invalid UTF (sebres)

2018-04-17 (bug) missing trace in compiled [array set], test var-20.11 (porter)

2018-04-22 (bug)[46a241] crash in unset array with search, var-13.[23] (goth)

2018-04-30 (bug)[27b682] race made [file delete] raise "no such file" (sebres)

2018-06-04 (bug)[925643] 32/64 cleanup of filesystem DIR operations (sebres)

2018-06-18 (bug) leaks in TclSetEnv and env cache (coulter)

2018-06-24 (bug)[3592747] [yieldto] dying namespace, tailcall-14.1 (coulter)

2018-07-09 (bug)[270f78] race in [file mkdir] (sebres)

2018-07-12 (bug)[3f7af0] [file delete] raised "permission denied" (sebres)

2018-07-26 (bug)[d051b7] overflow crash in [format] (sebres)

2018-08-29 revised quoting of [exec] args in generated command line (sebres)
***POTENTIAL INCOMPATIBILITY***

2018-09-20 HTTP Keep-Alive with pipelined requests (nash)
=> http 2.9.0

2018-09-27 (new)[TIP 505] [lreplace] accepts all out of range indices (porter)

2018-10-04 (bug) Prevent crash from NULL keyName (nijtmans)
=> registry 1.3.3

2018-10-26 (enhance) advance dde version (nijtmans)
=> dde 1.4.1

2018-10-27 tzdata updated to Olson's tzdata2018g (jima)

2018-10-29 Update tcltest package for Travis support (fellows)
=> tcltest 2.5.0

2018-11-09 (bug)[35a8f1] overlong string length of some lists (owens)

2018-11-16 (bug)[00d04c] Repair [binary encode base64] (sebres)

- Released 8.6.9, November 16, 2018 - details at http://core.tcl-lang.org/tcl/ -

2018-11-22 (bug)[7a9dc5] [file normalize ~/~foo] segfault (sebres)

2018-12-30 (bug)[3cf3a9] variable 'timezone' deprecated in vc2017 (nijtmans)

2019-01-09 (bug)[cc1e91] [list [list {*}[set a " "]]] regression (sebres)

2019-02-01 (bug)[e3f481] tests var-1.2[01] (sebres)

2019-03-01 (new) Update to Unicode 12.0 (nijtmans)

2019-03-05 (new)[TIP 527] New command [timerate] (sebres)

2019-03-08 (bug)[39fed4] [package require] memory validity (hume,porter)

2019-04-23 (new) New command tcl::unsupported::corotype (fellows)

2019-05-04 (bug) memlink when namespace deletion kills linked var (porter)

2019-05-28 (new) README file converted to README.md in Markdown (nijtmans)

2019-06-17 (bug)[8b9854] [info level 0] regression with ensembles (porter)

2019-06-20 (bug)[6bdadf] crash multi-arg write-traced [lappend] (fellows,porter)

2019-06-21 (bug)[f8a33c] crash Tcl_Exit before init (brooks,sebres)

2019-08-27 (bug)[fa6bf3] Bytecode fails epoch recovery at numLevel=0 (sebres)

2019-08-29 (bug)[fec0c1] C stack overflow compiling bytecode (ade,sebres)

2019-09-12 tzdata updated to Olson's tzdata2019c (jima)

2019-09-20 (new) registry/dde no longer need -DUNICODE (nijtmans)
=> registry 1.3.4
=> dde 1.4.2

2019-10-02 (bug)[16768d] Fix [info hostname] on NetBSD (rytaro)

2019-10-23 (new) libtommath updated to release 1.2.0 (nijtmans)

2019-10-25 OSX: system Tcl deprecated. End default use of its packages. (walzer)

2019-10-28 (bug)[bcd100] bad fs cache when system encoding changes (coulter)

2019-11-15 (bug)[135804] segfault in [next] after destroy (coulter,sebres)

- Released 8.6.10, Nov 21, 2019 - details at http://core.tcl-lang.org/tcl/ -

Changes to 8.7a3 include all changes to the 8.6 line through 8.6.10,
plus the following, which focuses on the high-level feature changes
in this changeset (new minor version) rather than bug fixes:

2017-11-01 (bug)[3c32a3] crash deleting class mixed into instance (coulter)

2017-11-03 [TIP 345] eliminate the encoding 'identity' (porter)

2017-11-04 (bug)[0d902e] [string first] on ASCII stored as Unicode (fellows)

2017-11-17 [TIP 422] Mark all Tcl_*VA() routines deprecated. (nijtmans)

2017-11-20 (support) Ended use of the obsolete values.h header (culler)

2017-11-30 (bug)[8e1e31] [lsort] ordering of U+0000 (nijtmans)

2017-12-07 [TIP 487] Terminate support for pre-XP Windows (nijtmans)

2017-12-08 [TIP 477] Reform of nmake build (nadkarni)

2017-12-20 (bug)[ba1419] Crash: complex ensemble delete, namespace-7.8 (coulter)

2018-01-17 [TIP 485] Removal of many deprecated features (nijtmans)

2018-01-27 (bug) Crash in [join $l $l], join-4.1 (porter)

2018-02-06 [TIP 493] Cease Distribution of http 1.0 (porter)

2018-02-06 [TIP 484] internal rep for native ints are all 64-bit (nijtmans)

2018-02-14 [TIP 476] Scan/Printf consistency (nijtmans)

2018-03-05 [TIP 351] [lsearch] striding

2018-03-05 [TIPs 330,336] tighten access to Interp fields (porter)

2018-03-12 [TIP 462] [::tcl::process]

2018-03-12 [TIP 490] add oo support for msgcat => msgcat 1.7.0 (oehlmann)

2018-03-12 [TIP 499] custom locale preference list (oehlmann)
=> msgcat 1.7.0

2018-03-20 [TIP 503] End CONST84 support for Tcl 8.3 (porter)

2018-03-30 Refactored [lrange] (spjuth)

2018-04-20 [TIP 389] Unicode beyond BMP (nijtmans)

2018-04-20 [TIP 421] [array for]

2018-05-11 [TIP 425] Windows panic callback use of UTF-8

2018-05-17 [TIP 491] Phase out --disable-threads support

2018-06-03 [TIP 500] TclOO Private Methods and Variables

2018-07-26 (bug)[ba921a] [string cat] of bytearrays (coulter,porter)

2018-09-02 [TIP 478] Many new features in TclOO (lester,fellows)

2018-09-04 (bug)[540bed] [binary format w] from bignum (nijtmans)

2018-09-12 [TIP 430] zipfs and embedded script library (woods)

2018-09-26 [TIP 508] [array default] (bonnet,fellows)

2018-09-27 [TIP 515] level value reform (nijtmans)

2018-09-27 [TIP 516] More OO slot operations (fellows)

2018-09-27 [TIP 426] [info cmdtype] (fellows)

2018-09-28 [TIP 509] Cross platform reentrant mutex

2018-10-08 [TIP 514] native integers are 64-bit

2018-10-12 [TIP 502] index value reform (porter)

2018-11-06 [TIP 406] http cookies (fellows)

2018-11-06 [TIP 445] Tcl_ObjType utilities (migrate to Tcl 9) (porter)

2018-11-06 [TIP 501] [string is dict]

2018-11-06 [TIP 519] inline export/unexport option for [oo::define]

2018-11-06 [TIP 523] [lpop]

2018-11-06 [TIP 524] TclOO custom dialects

2018-11-06 [TIP 506] Tcl_(Incr|Decr)RefCount macros -> functions (porter)

2018-11-15 [TIP 512] No stub for Tcl_SetExitProc()

2019-04-08 (bug)[45b9fa] crash in [try] (coulter)

2019-04-14 [TIP 160] terminal and serial channel controls

2019-04-14 [TIP 312] more types for Tcl_LinkVar

2019-04-14 [TIP 367] [lremove]

2019-04-14 [TIP 504] [string insert]

2019-04-16 [TIP 342] [dict getwithdefault]

2019-05-25 [TIP 431] [file tempdir]

2019-05-25 [TIP 383] [coroinject], [coroprobe]

2019-05-31 [TIP 544] Tcl_GetIntForIndex()

2019-06-12 Replace TclOffset() with offsetof()

2019-06-15 [TIP 461] string compare operators for [expr]

2019-06-16 [TIP 521] floating point classification functions for [expr]

2019-06-20 (bug)[6bdadf] crash multi-arg traced [lappend] (fellows)

2019-06-28 [TIP 547] New encodings utf-16, ucs-2

2019-09-14 [TIP 414] Tcl_InitSubsystems()

2019-09-14 [TIP 548] wchar_t conversion functions

- Released 8.7a3, Nov 21, 2019 --- http://core.tcl-lang.org/tcl/ for details -

Changes to 9.0a1 include all changes to the 8.7 line through 8.7a3,
plus the following, which focuses on the high-level feature changes
in this changeset (new minor version) rather than bug fixes:

2017-11-03 [TIP 114] Leading zero integer no longer means octal

2017-11-03 [TIP 278] Revise variable name resolution, solve "Creative Writing"

2017-11-03 [TIPs 330,336] Encapsulate struct Tcl_Interp

2017-11-17 [TIP 422] Remove all Tcl_*VA() routines

2017-12-15 [TIP 488] Disable magic $::tcl_precision

2018-10-08 [TIP 494] Increased support for size_t value ranges

2019-05-31 [TIP 537] 64-bit indices in regexp matching

- Released 9.0a1, Nov 25, 2019 --- http://core.tcl-lang.org/tcl/ for details -

Added 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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

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.0.1 arises from the check-in with tag `core-9-0-1`.

## Changes since Tcl 9.0.0
 - [zlib-8.8, zlib-8.16 fail on Fedora 40, gcc 14.1.1](https://core.tcl-lang.org/tcl/tktview/73d5cb)
 - [regression in tzdata, %z instead of offset TZ-name](https://core.tcl-lang.org/tcl/tktview/2c237b)
 - [Tcl will not start properly if there is an init.tcl file in the current dir](https://core.tcl-lang.org/tcl/tktview/43c94f)
 - [clock scan "24:00", ISO-8601 compatibility](https://core.tcl-lang.org/tcl/tktview/aee9f2)
 - [install registry and dde in $INSTALL_DIR\lib always](https://core.tcl-lang.org/tcl/tktview/364bd9)
 - [cannot build .chm help file (Windows)](https://core.tcl-lang.org/tcl/tktview/bb110c)
 - [TIP 701 - Tcl_FSTildeExpand C API](https://core.tcl-lang.org/tips/doc/trunk/tip/701.md)
 - [buffer overwrite for non-BMP characters in utf-16](https://core.tcl-lang.org/tcl/tktview/66da4d)

Release Tcl 9.0.0 arises from the check-in with tag `core-9-0-0`.

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

# Major Features

## 64-bit capacity: Data values larger than 2Gb
 - Strings can be any length (that fits in your available memory)
 - Lists and dictionaries can have very large numbers of elements

## Internationalization of text
 - Full Unicode range of codepoints
 - New encodings: `utf-16`/`utf-32`/`ucs-2`(`le`|`be`), `CESU-8`, etc.
 - `encoding` options `-profile`, `-failindex` manage encoding of I/O.
 - `msgcat` supports custom locale search list
 - `source` defaults to `-encoding utf-8`

## Zip filesystems and attached archives.
 - Packaging of the Tcl script library with the Tcl binary library,
   meaning that the `TCL_LIBRARY` environment variable is usually not required.
 - Packaging of an application into a virtual filesystem is now a supported
   core Tcl feature.

## Unix notifiers available using `epoll()` or `kqueue()`
 - This relieves limits on file descriptors imposed by legacy `select()` and fixes a performance bottleneck.

# Incompatibilities

## Notable incompatibilities
 - Unqualified varnames resolved in current namespace, not global.
   Note that in almost all cases where this causes a change, the change is actually the removal of a latent bug.
 - No `--disable-threads` build option.  Always thread-enabled.
 - I/O malencoding default response: raise error (`-profile strict`)
 - Windows platform needs Windows 7 or Windows Server 2008 R2 or later
 - Ended interpretation of `~` as home directory in pathnames.
   (See `file home` and `file tildeexpand` for replacements when you need them.)
 - Removed the `identity` encoding.
   (There were only ever very few valid use cases for this; almost all uses
   were systematically wrong.)
 - Removed the encoding alias `binary` to `iso8859-1`.
 - `$::tcl_precision` no longer controls string generation of doubles.
   (If you need a particular precision, use `format`.)
 - Removed pre-Tcl 8 legacies: `case`, `puts` and `read` variant syntaxes.
 - Removed subcommands [`trace variable`|`vdelete`|`vinfo`]
 - Removed `-eofchar` option for write channels.
 - On Windows 10+ (Version 1903 or higher), system encoding is always utf-8.
 - `%b`/`%d`/`%o`/`%x` format modifiers (without size modifier) for `format`
   and `scan` always truncate to 32-bits on all platforms.
 - `%L` size modifier for `scan` no longer truncates to 64-bit.
 - Removed command `::tcl::unsupported::inject`.
   (See `coroinject` and `coroprobe` for supported commands with significantly
   more comprehensible semantics.)

## Incompatibilities in C public interface
 - Extensions built against Tcl 8.6 and before will not work with Tcl 9.0;
   ABI compatibility was a non-goal for 9.0.  In _most_ cases, rebuilding
   against Tcl 9.0 should work except when a removed API function is used.
 - Many arguments expanded type from `int` to `Tcl_Size`, a signed integer type
   large enough to support 64-bit sized memory objects.
   The constant `TCL_AUTO_LENGTH` is a value of that type that indicates that
   the length should be obtained using an appropriate function (typically `strlen()` for `char *` values).
 - Ended support for `Tcl_ChannelTypeVersion` less than 5
 - Introduced versioning of the `Tcl_ObjType` struct
 - Removed macros `CONST*`: Tcl 9 support means dropping Tcl 8.3 support.
   (Replaced with standard C `const` keyword going forward.)
 - Removed registration of several `Tcl_ObjType`s.
 - Removed API functions:

     `Tcl_Backslash()`,
     `Tcl_*VA()`,
     `Tcl_*MathFunc*()`,
     `Tcl_MakeSafe()`,
     `Tcl_(Save|Restore|Discard|Free)Result()`,
     `Tcl_EvalTokens()`,
     `Tcl_(Get|Set)DefaultEncodingDir()`,
     `Tcl_UniCharN(case)cmp()`,
     `Tcl_UniCharCaseMatch()`

 - Revised many internals; beware reliance on undocumented behaviors.

# New Features

## New commands
 - `array default` — Specify default values for arrays (note that this alters the behaviour of `append`, `incr`, `lappend`).
 - `array for` — Cheap iteration over an array's contents.
 - `chan isbinary` — Test if a channel is configured to work with binary data.
 - `coroinject`, `coroprobe` — Interact with paused coroutines.
 - `clock add weekdays` — Clock arithmetic with week days.
 - `const`, `info const*` — Commands for defining constants (variables that can't be modified).
 - `dict getwithdefault` — Define a fallback value to use when `dict get` would otherwise fail.
 - `file home` — Get the user home directory.
 - `file tempdir` — Create a temporary directory.
 - `file tildeexpand` — Expand a file path containing a `~`.
 - `info commandtype` — Introspection for the kinds of commands.
 - `ledit` — Equivalent to `lreplace` but on a list in a variable.
 - `lpop` — Remove an item from a list in a variable.
 - `lremove` — Remove a sublist from a list in a variable.
 - `lseq` — Generate a list of numbers in a sequence.
 - `package files` — Describe the contents of a package.
 - `string insert` — Insert a string as a substring of another string.
 - `string is dict` — Test whether a string is a dictionary.
 - `tcl::process` — Commands for working with subprocesses.
 - `*::build-info` — Obtain information about the build of Tcl.
 - `readFile`, `writeFile`, `foreachLine` — Simple procedures for basic working with files.
 - `tcl::idna::*` — Commands for working with encoded DNS names.

## New command options
 - `chan configure ... -inputmode ...` — Support for raw terminal input and reading passwords.
 - `clock scan ... -validate ...`
 - `info loaded ... ?prefix?`
 - `lsearch ... -stride ...` — Search a list by groups of items.
 - `regsub ... -command ...` — Generate the replacement for a regular expression by calling a command.
 - `socket ... -nodelay ... -keepalive ...`
 - `vwait` controlled by several new options
 - `expr` string comparators `lt`, `gt`, `le`, `ge`
 - `expr` supports comments inside expressions

## Numbers
 - <code>0<i>NNN</i></code> format is no longer octal interpretation. Use <code>0o<i>NNN</i></code>.
 - <code>0d<i>NNNN</i></code> format to compel decimal interpretation.
 - <code>NN_NNN_NNN</code>, underscores in numbers for optional readability
 - Functions: `isinf()`, `isnan()`, `isnormal()`, `issubnormal()`, `isunordered()`
 - Command: `fpclassify`
 - Function `int()` no longer truncates to word size

## TclOO facilities
 - private variables and methods
 - class variables and methods
 - abstract and singleton classes
 - configurable properties
 - `method -export`, `method -unexport`

# Known bugs
 - [changed behaviour wrt command names, namespaces and resolution](https://core.tcl-lang.org/tcl/tktview/f14b33)
 - [windows dos device paths inconsistencies and missing functionality](https://core.tcl-lang.org/tcl/tktview/d8f121)
 - [Temporary folder with file "tcl9registry13.dll" remains after "exit"](https://core.tcl-lang.org/tcl/tktview/6ce3c0)

Deleted compat/dirent.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21





















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * dirent.h --
 *
 *	This file is a replacement for <dirent.h> in systems that
 *	support the old BSD-style <sys/dir.h> with a "struct direct".
 *
 * Copyright (c) 1991 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _DIRENT
#define _DIRENT

#include <sys/dir.h>

#define dirent direct

#endif /* _DIRENT */

Deleted compat/dirent2.h.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53





















































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * dirent.h --
 *
 *	Declarations of a library of directory-reading procedures
 *	in the POSIX style ("struct dirent").
 *
 * Copyright (c) 1991 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _DIRENT
#define _DIRENT

/*
 * Dirent structure, which holds information about a single
 * directory entry.
 */

#define MAXNAMLEN 255
#define DIRBLKSIZ 512

struct dirent {
    long d_ino;			/* Inode number of entry */
    short d_reclen;		/* Length of this record */
    short d_namlen;		/* Length of string in d_name */
    char d_name[MAXNAMLEN + 1];	/* Name must be no longer than this */
};

/*
 * State that keeps track of the reading of a directory (clients
 * should never look inside this structure;  the fields should
 * only be accessed by the library procedures).
 */

typedef struct _dirdesc {
    int dd_fd;
    long dd_loc;
    long dd_size;
    char dd_buf[DIRBLKSIZ];
} DIR;

/*
 * Procedures defined for reading directories:
 */

extern void		closedir (DIR *dirp);
extern DIR *		opendir (char *name);
extern struct dirent *	readdir (DIR *dirp);

#endif /* _DIRENT */

Changes to compat/fake-rfc2553.c.

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
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







-
-
-
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
+




-
+







TCL_DECLARE_MUTEX(netdbMutex)

#ifndef HAVE_GETNAMEINFO
#ifndef HAVE_STRLCPY
static size_t
strlcpy(char *dst, const char *src, size_t siz)
{
        char *d = dst;
        const char *s = src;
        size_t n = siz;
	char *d = dst;
	const char *s = src;
	size_t n = siz;

        /* Copy as many bytes as will fit */
        if (n != 0 && --n != 0) {
                do {
                        if ((*d++ = *s++) == 0)
                                break;
                } while (--n != 0);
        }
	/* Copy as many bytes as will fit */
	if (n != 0 && --n != 0) {
		do {
			if ((*d++ = *s++) == 0)
				break;
		} while (--n != 0);
	}

        /* Not enough room in dst, add NUL and traverse rest of src */
        if (n == 0) {
                if (siz != 0)
                        *d = '\0';              /* NUL-terminate dst */
                while (*s++)
                        ;
        }
	/* Not enough room in dst, add NUL and traverse rest of src */
	if (n == 0) {
		if (siz != 0)
			*d = '\0';	      /* NUL-terminate dst */
		while (*s++)
			;
	}

        return(s - src - 1);    /* count does not include NUL */
	return(s - src - 1);    /* count does not include NUL */
}
#endif

int fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
                size_t hostlen, char *serv, size_t servlen, int flags)
	size_t hostlen, char *serv, size_t servlen, int flags)
{
	struct sockaddr_in *sin = (struct sockaddr_in *)sa;
	struct hostent *hp;
	char tmpserv[16];
	(void)salen;

	if (sa->sa_family != AF_UNSPEC && sa->sa_family != AF_INET)

Deleted compat/memcmp.c.

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
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
































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * memcmp.c --
 *
 *	Source code for the "memcmp" library routine.
 *
 * Copyright (c) 1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclPort.h"

/*
 * Here is the prototype just in case it is not included in tclPort.h.
 */

int		memcmp(const void *s1, const void *s2, size_t n);

/*
 *----------------------------------------------------------------------
 *
 * memcmp --
 *
 *	Compares two bytes sequences.
 *
 * Results:
 *	Compares its arguments, looking at the first n bytes (each interpreted
 *	as an unsigned char), and returns an integer less than, equal to, or
 *	greater than 0, according as s1 is less than, equal to, or greater
 *	than s2 when taken to be unsigned 8 bit numbers.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
memcmp(
    const void *s1,		/* First string. */
    const void *s2,		/* Second string. */
    size_t n)			/* Length to compare. */
{
    const unsigned char *ptr1 = (const unsigned char *) s1;
    const unsigned char *ptr2 = (const unsigned char *) s2;

    for ( ; n-- ; ptr1++, ptr2++) {
	unsigned char u1 = *ptr1, u2 = *ptr2;

	if (u1 != u2) {
	    return (u1-u2);
	}
    }
    return 0;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Deleted compat/opendir.c.

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
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














































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * opendir.c --
 *
 *	This file provides dirent-style directory-reading procedures for V7
 *	Unix systems that don't have such procedures. The origin of this code
 *	is unclear, but it seems to have come originally from Larry Wall.
 */

#include "tclInt.h"

#undef DIRSIZ
#define DIRSIZ(dp) \
    ((sizeof(struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))

/*
 * open a directory.
 */

DIR *
opendir(
    char *name)
{
    DIR *dirp;
    int fd;
    const char *myname;

    myname = ((*name == '\0') ? "." : name);
    if ((fd = open(myname, 0, 0)) == -1) {
	return NULL;
    }
    dirp = (DIR *) Tcl_Alloc(sizeof(DIR));
    if (dirp == NULL) {
	/* unreachable? */
	close(fd);
	return NULL;
    }
    dirp->dd_fd = fd;
    dirp->dd_loc = 0;
    return dirp;
}

/*
 * read an old style directory entry and present it as a new one
 */
#ifndef pyr
#define	ODIRSIZ	14

struct olddirect {
    ino_t od_ino;
    char od_name[ODIRSIZ];
};
#else	/* a Pyramid in the ATT universe */
#define	ODIRSIZ	248

struct olddirect {
    long od_ino;
    short od_fill1, od_fill2;
    char od_name[ODIRSIZ];
};
#endif

/*
 * get next entry in a directory.
 */

struct dirent *
readdir(
    DIR *dirp)
{
    struct olddirect *dp;
    static struct dirent dir;

    for (;;) {
	if (dirp->dd_loc == 0) {
	    dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ);
	    if (dirp->dd_size <= 0) {
		return NULL;
	    }
	}
	if (dirp->dd_loc >= dirp->dd_size) {
	    dirp->dd_loc = 0;
	    continue;
	}
	dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc);
	dirp->dd_loc += sizeof(struct olddirect);
	if (dp->od_ino == 0) {
	    continue;
	}
	dir.d_ino = dp->od_ino;
	strncpy(dir.d_name, dp->od_name, ODIRSIZ);
	dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */
	dir.d_namlen = strlen(dir.d_name);
	dir.d_reclen = DIRSIZ(&dir);
	return &dir;
    }
}

/*
 * close a directory.
 */

void
closedir(
    DIR *dirp)
{
    close(dirp->dd_fd);
    dirp->dd_fd = -1;
    dirp->dd_loc = 0;
    Tcl_Free(dirp);
}

Deleted compat/stdint.h.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919























































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*  A portable stdint.h
 ****************************************************************************
 *  BSD License:
 ****************************************************************************
 *
 *  Copyright (c) 2005-2016 Paul Hsieh
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************
 *
 *  Version 0.1.16.0
 *
 *  The ANSI C standard committee, for the C99 standard, specified the
 *  inclusion of a new standard include file called stdint.h.  This is
 *  a very useful and long desired include file which contains several
 *  very precise definitions for integer scalar types that is critically
 *  important for making several classes of applications portable
 *  including cryptography, hashing, variable length integer libraries
 *  and so on.  But for most developers its likely useful just for
 *  programming sanity.
 *
 *  The problem is that some compiler vendors chose to ignore the C99
 *  standard and some older compilers have no opportunity to be updated.
 *  Because of this situation, simply including stdint.h in your code
 *  makes it unportable.
 *
 *  So that's what this file is all about.  It's an attempt to build a
 *  single universal include file that works on as many platforms as
 *  possible to deliver what stdint.h is supposed to.  Even compilers
 *  that already come with stdint.h can use this file instead without
 *  any loss of functionality.  A few things that should be noted about
 *  this file:
 *
 *    1) It is not guaranteed to be portable and/or present an identical
 *       interface on all platforms.  The extreme variability of the
 *       ANSI C standard makes this an impossibility right from the
 *       very get go. Its really only meant to be useful for the vast
 *       majority of platforms that possess the capability of
 *       implementing usefully and precisely defined, standard sized
 *       integer scalars.  Systems which are not intrinsically 2s
 *       complement may produce invalid constants.
 *
 *    2) There is an unavoidable use of non-reserved symbols.
 *
 *    3) Other standard include files are invoked.
 *
 *    4) This file may come in conflict with future platforms that do
 *       include stdint.h.  The hope is that one or the other can be
 *       used with no real difference.
 *
 *    5) In the current version, if your platform can't represent
 *       int32_t, int16_t and int8_t, it just dumps out with a compiler
 *       error.
 *
 *    6) 64 bit integers may or may not be defined.  Test for their
 *       presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX.
 *       Note that this is different from the C99 specification which
 *       requires the existence of 64 bit support in the compiler.  If
 *       this is not defined for your platform, yet it is capable of
 *       dealing with 64 bits then it is because this file has not yet
 *       been extended to cover all of your system's capabilities.
 *
 *    7) (u)intptr_t may or may not be defined.  Test for its presence
 *       with the test: #ifdef PTRDIFF_MAX.  If this is not defined
 *       for your platform, then it is because this file has not yet
 *       been extended to cover all of your system's capabilities, not
 *       because its optional.
 *
 *    8) The following might not been defined even if your platform is
 *       capable of defining it:
 *
 *       WCHAR_MIN
 *       WCHAR_MAX
 *       (u)int64_t
 *       PTRDIFF_MIN
 *       PTRDIFF_MAX
 *       (u)intptr_t
 *
 *    9) The following have not been defined:
 *
 *       WINT_MIN
 *       WINT_MAX
 *
 *   10) The criteria for defining (u)int_least(*)_t isn't clear,
 *       except for systems which don't have a type that precisely
 *       defined 8, 16, or 32 bit types (which this include file does
 *       not support anyways). Default definitions have been given.
 *
 *   11) The criteria for defining (u)int_fast(*)_t isn't something I
 *       would trust to any particular compiler vendor or the ANSI C
 *       committee.  It is well known that "compatible systems" are
 *       commonly created that have very different performance
 *       characteristics from the systems they are compatible with,
 *       especially those whose vendors make both the compiler and the
 *       system.  Default definitions have been given, but its strongly
 *       recommended that users never use these definitions for any
 *       reason (they do *NOT* deliver any serious guarantee of
 *       improved performance -- not in this file, nor any vendor's
 *       stdint.h).
 *
 *   12) The following macros:
 *
 *       PRINTF_INTMAX_MODIFIER
 *       PRINTF_INT64_MODIFIER
 *       PRINTF_INT32_MODIFIER
 *       PRINTF_INT16_MODIFIER
 *       PRINTF_LEAST64_MODIFIER
 *       PRINTF_LEAST32_MODIFIER
 *       PRINTF_LEAST16_MODIFIER
 *       PRINTF_INTPTR_MODIFIER
 *
 *       are strings which have been defined as the modifiers required
 *       for the "d", "u" and "x" printf formats to correctly output
 *       (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t,
 *       (u)least32_t, (u)least16_t and (u)intptr_t types respectively.
 *       PRINTF_INTPTR_MODIFIER is not defined for some systems which
 *       provide their own stdint.h.  PRINTF_INT64_MODIFIER is not
 *       defined if INT64_MAX is not defined.  These are an extension
 *       beyond what C99 specifies must be in stdint.h.
 *
 *       In addition, the following macros are defined:
 *
 *       PRINTF_INTMAX_HEX_WIDTH
 *       PRINTF_INT64_HEX_WIDTH
 *       PRINTF_INT32_HEX_WIDTH
 *       PRINTF_INT16_HEX_WIDTH
 *       PRINTF_INT8_HEX_WIDTH
 *       PRINTF_INTMAX_DEC_WIDTH
 *       PRINTF_INT64_DEC_WIDTH
 *       PRINTF_INT32_DEC_WIDTH
 *       PRINTF_INT16_DEC_WIDTH
 *       PRINTF_UINT8_DEC_WIDTH
 *       PRINTF_UINTMAX_DEC_WIDTH
 *       PRINTF_UINT64_DEC_WIDTH
 *       PRINTF_UINT32_DEC_WIDTH
 *       PRINTF_UINT16_DEC_WIDTH
 *       PRINTF_UINT8_DEC_WIDTH
 *
 *       Which specifies the maximum number of characters required to
 *       print the number of that type in either hexadecimal or decimal.
 *       These are an extension beyond what C99 specifies must be in
 *       stdint.h.
 *
 *  Compilers tested (all with 0 warnings at their highest respective
 *  settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32
 *  bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio
 *  .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3
 *
 *  This file should be considered a work in progress.  Suggestions for
 *  improvements, especially those which increase coverage are strongly
 *  encouraged.
 *
 *  Acknowledgements
 *
 *  The following people have made significant contributions to the
 *  development and testing of this file:
 *
 *  Chris Howie
 *  John Steele Scott
 *  Dave Thorup
 *  John Dill
 *  Florian Wobbe
 *  Christopher Sean Morrison
 *  Mikkel Fahnoe Jorgensen
 *
 */

#include <stddef.h>
#include <limits.h>
#include <signal.h>

/*
 *  For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and
 *  do nothing else.  On the Mac OS X version of gcc this is _STDINT_H_.
 */

#if ((defined(__SUNPRO_C) && __SUNPRO_C >= 0x570) || (defined(_MSC_VER) && _MSC_VER >= 1600) || (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (__GNUC__ > 3 || defined(_STDINT_H) || defined(_STDINT_H_) || defined (__UINT_FAST64_TYPE__)) )) && !defined (_PSTDINT_H_INCLUDED)
#include <stdint.h>
#define _PSTDINT_H_INCLUDED
# if defined(__GNUC__) && (defined(__x86_64__) || defined(__ppc64__)) && !(defined(__APPLE__) && defined(__MACH__))
#  ifndef PRINTF_INT64_MODIFIER
#   define PRINTF_INT64_MODIFIER "l"
#  endif
#  ifndef PRINTF_INT32_MODIFIER
#   define PRINTF_INT32_MODIFIER ""
#  endif
# else
#  ifndef PRINTF_INT64_MODIFIER
#   define PRINTF_INT64_MODIFIER "ll"
#  endif
#  ifndef PRINTF_INT32_MODIFIER
#   if (UINT_MAX == UINT32_MAX)
#    define PRINTF_INT32_MODIFIER ""
#   else
#    define PRINTF_INT32_MODIFIER "l"
#   endif
#  endif
# endif
# ifndef PRINTF_INT16_MODIFIER
#  define PRINTF_INT16_MODIFIER "h"
# endif
# ifndef PRINTF_INTMAX_MODIFIER
#  define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
# endif
# ifndef PRINTF_INT64_HEX_WIDTH
#  define PRINTF_INT64_HEX_WIDTH "16"
# endif
# ifndef PRINTF_UINT64_HEX_WIDTH
#  define PRINTF_UINT64_HEX_WIDTH "16"
# endif
# ifndef PRINTF_INT32_HEX_WIDTH
#  define PRINTF_INT32_HEX_WIDTH "8"
# endif
# ifndef PRINTF_UINT32_HEX_WIDTH
#  define PRINTF_UINT32_HEX_WIDTH "8"
# endif
# ifndef PRINTF_INT16_HEX_WIDTH
#  define PRINTF_INT16_HEX_WIDTH "4"
# endif
# ifndef PRINTF_UINT16_HEX_WIDTH
#  define PRINTF_UINT16_HEX_WIDTH "4"
# endif
# ifndef PRINTF_INT8_HEX_WIDTH
#  define PRINTF_INT8_HEX_WIDTH "2"
# endif
# ifndef PRINTF_UINT8_HEX_WIDTH
#  define PRINTF_UINT8_HEX_WIDTH "2"
# endif
# ifndef PRINTF_INT64_DEC_WIDTH
#  define PRINTF_INT64_DEC_WIDTH "19"
# endif
# ifndef PRINTF_UINT64_DEC_WIDTH
#  define PRINTF_UINT64_DEC_WIDTH "20"
# endif
# ifndef PRINTF_INT32_DEC_WIDTH
#  define PRINTF_INT32_DEC_WIDTH "10"
# endif
# ifndef PRINTF_UINT32_DEC_WIDTH
#  define PRINTF_UINT32_DEC_WIDTH "10"
# endif
# ifndef PRINTF_INT16_DEC_WIDTH
#  define PRINTF_INT16_DEC_WIDTH "5"
# endif
# ifndef PRINTF_UINT16_DEC_WIDTH
#  define PRINTF_UINT16_DEC_WIDTH "5"
# endif
# ifndef PRINTF_INT8_DEC_WIDTH
#  define PRINTF_INT8_DEC_WIDTH "3"
# endif
# ifndef PRINTF_UINT8_DEC_WIDTH
#  define PRINTF_UINT8_DEC_WIDTH "3"
# endif
# ifndef PRINTF_INTMAX_HEX_WIDTH
#  define PRINTF_INTMAX_HEX_WIDTH PRINTF_UINT64_HEX_WIDTH
# endif
# ifndef PRINTF_UINTMAX_HEX_WIDTH
#  define PRINTF_UINTMAX_HEX_WIDTH PRINTF_UINT64_HEX_WIDTH
# endif
# ifndef PRINTF_INTMAX_DEC_WIDTH
#  define PRINTF_INTMAX_DEC_WIDTH PRINTF_UINT64_DEC_WIDTH
# endif
# ifndef PRINTF_UINTMAX_DEC_WIDTH
#  define PRINTF_UINTMAX_DEC_WIDTH PRINTF_UINT64_DEC_WIDTH
# endif

/*
 *  Something really weird is going on with Open Watcom.  Just pull some of
 *  these duplicated definitions from Open Watcom's stdint.h file for now.
 */

# if defined (__WATCOMC__) && __WATCOMC__ >= 1250
#  if !defined (INT64_C)
#   define INT64_C(x)   (x + (INT64_MAX - INT64_MAX))
#  endif
#  if !defined (UINT64_C)
#   define UINT64_C(x)  (x + (UINT64_MAX - UINT64_MAX))
#  endif
#  if !defined (INT32_C)
#   define INT32_C(x)   (x + (INT32_MAX - INT32_MAX))
#  endif
#  if !defined (UINT32_C)
#   define UINT32_C(x)  (x + (UINT32_MAX - UINT32_MAX))
#  endif
#  if !defined (INT16_C)
#   define INT16_C(x)   (x)
#  endif
#  if !defined (UINT16_C)
#   define UINT16_C(x)  (x)
#  endif
#  if !defined (INT8_C)
#   define INT8_C(x)   (x)
#  endif
#  if !defined (UINT8_C)
#   define UINT8_C(x)  (x)
#  endif
#  if !defined (UINT64_MAX)
#   define UINT64_MAX  18446744073709551615ULL
#  endif
#  if !defined (INT64_MAX)
#   define INT64_MAX  9223372036854775807LL
#  endif
#  if !defined (UINT32_MAX)
#   define UINT32_MAX  4294967295UL
#  endif
#  if !defined (INT32_MAX)
#   define INT32_MAX  2147483647L
#  endif
#  if !defined (INTMAX_MAX)
#   define INTMAX_MAX INT64_MAX
#  endif
#  if !defined (INTMAX_MIN)
#   define INTMAX_MIN INT64_MIN
#  endif
# endif
#endif

/*
 *  I have no idea what is the truly correct thing to do on older Solaris.
 *  From some online discussions, this seems to be what is being
 *  recommended.  For people who actually are developing on older Solaris,
 *  what I would like to know is, does this define all of the relevant
 *  macros of a complete stdint.h?  Remember, in pstdint.h 64 bit is
 *  considered optional.
 */

#if (defined(__SUNPRO_C) && __SUNPRO_C >= 0x420) && !defined(_PSTDINT_H_INCLUDED)
#include <sys/inttypes.h>
#define _PSTDINT_H_INCLUDED
#endif

#ifndef _PSTDINT_H_INCLUDED
#define _PSTDINT_H_INCLUDED

#ifndef SIZE_MAX
# define SIZE_MAX ((size_t)-1)
#endif

/*
 *  Deduce the type assignments from limits.h under the assumption that
 *  integer sizes in bits are powers of 2, and follow the ANSI
 *  definitions.
 */

#ifndef UINT8_MAX
# define UINT8_MAX 0xff
#endif
#if !defined(uint8_t) && !defined(_UINT8_T) && !defined(vxWorks)
# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S)
    typedef unsigned char uint8_t;
#   define UINT8_C(v) ((uint8_t) v)
# else
#   error "Platform not supported"
# endif
#endif

#ifndef INT8_MAX
# define INT8_MAX 0x7f
#endif
#ifndef INT8_MIN
# define INT8_MIN INT8_C(0x80)
#endif
#if !defined(int8_t) && !defined(_INT8_T) && !defined(vxWorks)
# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S)
    typedef signed char int8_t;
#   define INT8_C(v) ((int8_t) v)
# else
#   error "Platform not supported"
# endif
#endif

#ifndef UINT16_MAX
# define UINT16_MAX 0xffff
#endif
#if !defined(uint16_t) && !defined(_UINT16_T) && !defined(vxWorks)
#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S)
  typedef unsigned int uint16_t;
# ifndef PRINTF_INT16_MODIFIER
#  define PRINTF_INT16_MODIFIER ""
# endif
# define UINT16_C(v) ((uint16_t) (v))
#elif (USHRT_MAX == UINT16_MAX)
  typedef unsigned short uint16_t;
# define UINT16_C(v) ((uint16_t) (v))
# ifndef PRINTF_INT16_MODIFIER
#  define PRINTF_INT16_MODIFIER "h"
# endif
#else
#error "Platform not supported"
#endif
#endif

#ifndef INT16_MAX
# define INT16_MAX 0x7fff
#endif
#ifndef INT16_MIN
# define INT16_MIN INT16_C(0x8000)
#endif
#if !defined(int16_t) && !defined(_INT16_T) && !defined(vxWorks)
#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S)
  typedef signed int int16_t;
# define INT16_C(v) ((int16_t) (v))
# ifndef PRINTF_INT16_MODIFIER
#  define PRINTF_INT16_MODIFIER ""
# endif
#elif (SHRT_MAX == INT16_MAX)
  typedef signed short int16_t;
# define INT16_C(v) ((int16_t) (v))
# ifndef PRINTF_INT16_MODIFIER
#  define PRINTF_INT16_MODIFIER "h"
# endif
#else
#error "Platform not supported"
#endif
#endif

#ifndef UINT32_MAX
# define UINT32_MAX (0xffffffffUL)
#endif
#if !defined(uint32_t) && !defined(_UINT32_T) && !defined(vxWorks)
#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S)
  typedef unsigned long uint32_t;
# define UINT32_C(v) v ## UL
# ifndef PRINTF_INT32_MODIFIER
#  define PRINTF_INT32_MODIFIER "l"
# endif
#elif (UINT_MAX == UINT32_MAX)
  typedef unsigned int uint32_t;
# ifndef PRINTF_INT32_MODIFIER
#  define PRINTF_INT32_MODIFIER ""
# endif
# define UINT32_C(v) v ## U
#elif (USHRT_MAX == UINT32_MAX)
  typedef unsigned short uint32_t;
# define UINT32_C(v) ((unsigned short) (v))
# ifndef PRINTF_INT32_MODIFIER
#  define PRINTF_INT32_MODIFIER ""
# endif
#else
#error "Platform not supported"
#endif
#endif

#ifndef INT32_MAX
# define INT32_MAX (0x7fffffffL)
#endif
#ifndef INT32_MIN
# define INT32_MIN INT32_C(0x80000000)
#endif
#if !defined(int32_t) && !defined(_INT32_T) && !defined(vxWorks)
#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S)
  typedef signed long int32_t;
# define INT32_C(v) v ## L
# ifndef PRINTF_INT32_MODIFIER
#  define PRINTF_INT32_MODIFIER "l"
# endif
#elif (INT_MAX == INT32_MAX)
  typedef signed int int32_t;
# define INT32_C(v) v
# ifndef PRINTF_INT32_MODIFIER
#  define PRINTF_INT32_MODIFIER ""
# endif
#elif (SHRT_MAX == INT32_MAX)
  typedef signed short int32_t;
# define INT32_C(v) ((short) (v))
# ifndef PRINTF_INT32_MODIFIER
#  define PRINTF_INT32_MODIFIER ""
# endif
#else
#error "Platform not supported"
#endif
#endif

/*
 *  The macro stdint_int64_defined is temporarily used to record
 *  whether or not 64 integer support is available.  It must be
 *  defined for any 64 integer extensions for new platforms that are
 *  added.
 */

#undef stdint_int64_defined
#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S)
# if (__STDC__ && __STDC_VERSION__ >= 199901L) || defined (S_SPLINT_S)
#  define stdint_int64_defined
   typedef long long int64_t;
   typedef unsigned long long uint64_t;
#  define UINT64_C(v) v ## ULL
#  define  INT64_C(v) v ## LL
#  ifndef PRINTF_INT64_MODIFIER
#   define PRINTF_INT64_MODIFIER "ll"
#  endif
# endif
#endif

#if !defined (stdint_int64_defined)
# if defined(__GNUC__) && !defined(vxWorks)
#  define stdint_int64_defined
   __extension__ typedef long long int64_t;
   __extension__ typedef unsigned long long uint64_t;
#  define UINT64_C(v) v ## ULL
#  define  INT64_C(v) v ## LL
#  ifndef PRINTF_INT64_MODIFIER
#   define PRINTF_INT64_MODIFIER "ll"
#  endif
# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S)
#  define stdint_int64_defined
   typedef long long int64_t;
   typedef unsigned long long uint64_t;
#  define UINT64_C(v) v ## ULL
#  define  INT64_C(v) v ## LL
#  ifndef PRINTF_INT64_MODIFIER
#   define PRINTF_INT64_MODIFIER "ll"
#  endif
# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC)
#  define stdint_int64_defined
   typedef __int64 int64_t;
   typedef unsigned __int64 uint64_t;
#  define UINT64_C(v) v ## UI64
#  define  INT64_C(v) v ## I64
#  ifndef PRINTF_INT64_MODIFIER
#   define PRINTF_INT64_MODIFIER "I64"
#  endif
# endif
#endif

#if !defined (LONG_LONG_MAX) && defined (INT64_C)
# define LONG_LONG_MAX INT64_C (9223372036854775807)
#endif
#ifndef ULONG_LONG_MAX
# define ULONG_LONG_MAX UINT64_C (18446744073709551615)
#endif

#if !defined (INT64_MAX) && defined (INT64_C)
# define INT64_MAX INT64_C (9223372036854775807)
#endif
#if !defined (INT64_MIN) && defined (INT64_C)
# define INT64_MIN INT64_C (-9223372036854775808)
#endif
#if !defined (UINT64_MAX) && defined (INT64_C)
# define UINT64_MAX UINT64_C (18446744073709551615)
#endif

/*
 *  Width of hexadecimal for number field.
 */

#ifndef PRINTF_INT64_HEX_WIDTH
# define PRINTF_INT64_HEX_WIDTH "16"
#endif
#ifndef PRINTF_INT32_HEX_WIDTH
# define PRINTF_INT32_HEX_WIDTH "8"
#endif
#ifndef PRINTF_INT16_HEX_WIDTH
# define PRINTF_INT16_HEX_WIDTH "4"
#endif
#ifndef PRINTF_INT8_HEX_WIDTH
# define PRINTF_INT8_HEX_WIDTH "2"
#endif
#ifndef PRINTF_INT64_DEC_WIDTH
# define PRINTF_INT64_DEC_WIDTH "19"
#endif
#ifndef PRINTF_INT32_DEC_WIDTH
# define PRINTF_INT32_DEC_WIDTH "10"
#endif
#ifndef PRINTF_INT16_DEC_WIDTH
# define PRINTF_INT16_DEC_WIDTH "5"
#endif
#ifndef PRINTF_INT8_DEC_WIDTH
# define PRINTF_INT8_DEC_WIDTH "3"
#endif
#ifndef PRINTF_UINT64_DEC_WIDTH
# define PRINTF_UINT64_DEC_WIDTH "20"
#endif
#ifndef PRINTF_UINT32_DEC_WIDTH
# define PRINTF_UINT32_DEC_WIDTH "10"
#endif
#ifndef PRINTF_UINT16_DEC_WIDTH
# define PRINTF_UINT16_DEC_WIDTH "5"
#endif
#ifndef PRINTF_UINT8_DEC_WIDTH
# define PRINTF_UINT8_DEC_WIDTH "3"
#endif

/*
 *  Ok, lets not worry about 128 bit integers for now.  Moore's law says
 *  we don't need to worry about that until about 2040 at which point
 *  we'll have bigger things to worry about.
 */

#ifdef stdint_int64_defined
  typedef int64_t intmax_t;
  typedef uint64_t uintmax_t;
# define  INTMAX_MAX   INT64_MAX
# define  INTMAX_MIN   INT64_MIN
# define UINTMAX_MAX  UINT64_MAX
# define UINTMAX_C(v) UINT64_C(v)
# define  INTMAX_C(v)  INT64_C(v)
# ifndef PRINTF_INTMAX_MODIFIER
#   define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
# endif
# ifndef PRINTF_INTMAX_HEX_WIDTH
#  define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
# endif
# ifndef PRINTF_INTMAX_DEC_WIDTH
#  define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
# endif
#else
  typedef int32_t intmax_t;
  typedef uint32_t uintmax_t;
# define  INTMAX_MAX   INT32_MAX
# define UINTMAX_MAX  UINT32_MAX
# define UINTMAX_C(v) UINT32_C(v)
# define  INTMAX_C(v)  INT32_C(v)
# ifndef PRINTF_INTMAX_MODIFIER
#   define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER
# endif
# ifndef PRINTF_INTMAX_HEX_WIDTH
#  define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH
# endif
# ifndef PRINTF_INTMAX_DEC_WIDTH
#  define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH
# endif
#endif

/*
 *  Because this file currently only supports platforms which have
 *  precise powers of 2 as bit sizes for the default integers, the
 *  least definitions are all trivial.  Its possible that a future
 *  version of this file could have different definitions.
 */

#ifndef stdint_least_defined
  typedef   int8_t   int_least8_t;
  typedef  uint8_t  uint_least8_t;
  typedef  int16_t  int_least16_t;
  typedef uint16_t uint_least16_t;
  typedef  int32_t  int_least32_t;
  typedef uint32_t uint_least32_t;
# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER
# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER
# define  UINT_LEAST8_MAX  UINT8_MAX
# define   INT_LEAST8_MAX   INT8_MAX
# define UINT_LEAST16_MAX UINT16_MAX
# define  INT_LEAST16_MAX  INT16_MAX
# define UINT_LEAST32_MAX UINT32_MAX
# define  INT_LEAST32_MAX  INT32_MAX
# define   INT_LEAST8_MIN   INT8_MIN
# define  INT_LEAST16_MIN  INT16_MIN
# define  INT_LEAST32_MIN  INT32_MIN
# ifdef stdint_int64_defined
    typedef  int64_t  int_least64_t;
    typedef uint64_t uint_least64_t;
#   define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER
#   define UINT_LEAST64_MAX UINT64_MAX
#   define  INT_LEAST64_MAX  INT64_MAX
#   define  INT_LEAST64_MIN  INT64_MIN
# endif
#endif
#undef stdint_least_defined

/*
 *  The ANSI C committee has defined *int*_fast*_t types as well.  This,
 *  of course, defies rationality -- you can't know what will be fast
 *  just from the type itself.  Even for a given architecture, compatible
 *  implementations might have different performance characteristics.
 *  Developers are warned to stay away from these types when using this
 *  or any other stdint.h.
 */

typedef   int_least8_t   int_fast8_t;
typedef  uint_least8_t  uint_fast8_t;
typedef  int_least16_t  int_fast16_t;
typedef uint_least16_t uint_fast16_t;
typedef  int_least32_t  int_fast32_t;
typedef uint_least32_t uint_fast32_t;
#define  UINT_FAST8_MAX  UINT_LEAST8_MAX
#define   INT_FAST8_MAX   INT_LEAST8_MAX
#define UINT_FAST16_MAX UINT_LEAST16_MAX
#define  INT_FAST16_MAX  INT_LEAST16_MAX
#define UINT_FAST32_MAX UINT_LEAST32_MAX
#define  INT_FAST32_MAX  INT_LEAST32_MAX
#define   INT_FAST8_MIN   INT_LEAST8_MIN
#define  INT_FAST16_MIN  INT_LEAST16_MIN
#define  INT_FAST32_MIN  INT_LEAST32_MIN
#ifdef stdint_int64_defined
  typedef  int_least64_t  int_fast64_t;
  typedef uint_least64_t uint_fast64_t;
# define UINT_FAST64_MAX UINT_LEAST64_MAX
# define  INT_FAST64_MAX  INT_LEAST64_MAX
# define  INT_FAST64_MIN  INT_LEAST64_MIN
#endif

#undef stdint_int64_defined

/*
 *  Whatever piecemeal, per compiler thing we can do about the wchar_t
 *  type limits.
 */

#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__) && !defined(vxWorks)
# include <wchar.h>
# ifndef WCHAR_MIN
#  define WCHAR_MIN 0
# endif
# ifndef WCHAR_MAX
#  define WCHAR_MAX ((wchar_t)-1)
# endif
#endif

/*
 *  Whatever piecemeal, per compiler/platform thing we can do about the
 *  (u)intptr_t types and limits.
 */

#if (defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED)) || defined (_UINTPTR_T)
# define STDINT_H_UINTPTR_T_DEFINED
#endif

#ifndef STDINT_H_UINTPTR_T_DEFINED
# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64) || defined (__ppc64__)
#  define stdint_intptr_bits 64
# elif defined (__WATCOMC__) || defined (__TURBOC__)
#  if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)
#    define stdint_intptr_bits 16
#  else
#    define stdint_intptr_bits 32
#  endif
# elif defined (__i386__) || defined (_WIN32) || defined (WIN32) || defined (__ppc64__)
#  define stdint_intptr_bits 32
# elif defined (__INTEL_COMPILER)
/* TODO -- what did Intel do about x86-64? */
# else
/* #error "This platform might not be supported yet" */
# endif

# ifdef stdint_intptr_bits
#  define stdint_intptr_glue3_i(a,b,c)  a##b##c
#  define stdint_intptr_glue3(a,b,c)    stdint_intptr_glue3_i(a,b,c)
#  ifndef PRINTF_INTPTR_MODIFIER
#    define PRINTF_INTPTR_MODIFIER      stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER)
#  endif
#  ifndef PTRDIFF_MAX
#    define PTRDIFF_MAX                 stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
#  endif
#  ifndef PTRDIFF_MIN
#    define PTRDIFF_MIN                 stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
#  endif
#  ifndef UINTPTR_MAX
#    define UINTPTR_MAX                 stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX)
#  endif
#  ifndef INTPTR_MAX
#    define INTPTR_MAX                  stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
#  endif
#  ifndef INTPTR_MIN
#    define INTPTR_MIN                  stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
#  endif
#  ifndef INTPTR_C
#    define INTPTR_C(x)                 stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x)
#  endif
#  ifndef UINTPTR_C
#    define UINTPTR_C(x)                stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x)
#  endif
  typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t;
  typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t)  intptr_t;
# else
/* TODO -- This following is likely wrong for some platforms, and does
   nothing for the definition of uintptr_t. */
  typedef ptrdiff_t intptr_t;
# endif
# define STDINT_H_UINTPTR_T_DEFINED
#endif

/*
 *  Assumes sig_atomic_t is signed and we have a 2s complement machine.
 */

#ifndef SIG_ATOMIC_MAX
# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1)
#endif

#endif

#if defined (__TEST_PSTDINT_FOR_CORRECTNESS)

/*
 *  Please compile with the maximum warning settings to make sure macros are
 *  not defined more than once.
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define glue3_aux(x,y,z) x ## y ## z
#define glue3(x,y,z) glue3_aux(x,y,z)

#define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,) = glue3(UINT,bits,_C) (0);
#define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,) = glue3(INT,bits,_C) (0);

#define DECL(us,bits) glue3(DECL,us,) (bits)

#define TESTUMAX(bits) glue3(u,bits,) = ~glue3(u,bits,); if (glue3(UINT,bits,_MAX) != glue3(u,bits,)) printf ("Something wrong with UINT%d_MAX\n", bits)

#define REPORTERROR(msg) { err_n++; if (err_first <= 0) err_first = __LINE__; printf msg; }

#define X_SIZE_MAX ((size_t)-1)

int main () {
	int err_n = 0;
	int err_first = 0;
	DECL(I,8)
	DECL(U,8)
	DECL(I,16)
	DECL(U,16)
	DECL(I,32)
	DECL(U,32)
#ifdef INT64_MAX
	DECL(I,64)
	DECL(U,64)
#endif
	intmax_t imax = INTMAX_C(0);
	uintmax_t umax = UINTMAX_C(0);
	char str0[256], str1[256];

	sprintf (str0, "%" PRINTF_INT32_MODIFIER "d", INT32_C(2147483647));
	if (0 != strcmp (str0, "2147483647")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str0));
	if (atoi(PRINTF_INT32_DEC_WIDTH) != (int) strlen(str0)) REPORTERROR (("Something wrong with PRINTF_INT32_DEC_WIDTH : %s\n", PRINTF_INT32_DEC_WIDTH));
	sprintf (str0, "%" PRINTF_INT32_MODIFIER "u", UINT32_C(4294967295));
	if (0 != strcmp (str0, "4294967295")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str0));
	if (atoi(PRINTF_UINT32_DEC_WIDTH) != (int) strlen(str0)) REPORTERROR (("Something wrong with PRINTF_UINT32_DEC_WIDTH : %s\n", PRINTF_UINT32_DEC_WIDTH));
#ifdef INT64_MAX
	sprintf (str1, "%" PRINTF_INT64_MODIFIER "d", INT64_C(9223372036854775807));
	if (0 != strcmp (str1, "9223372036854775807")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str1));
	if (atoi(PRINTF_INT64_DEC_WIDTH) != (int) strlen(str1)) REPORTERROR (("Something wrong with PRINTF_INT64_DEC_WIDTH : %s, %d\n", PRINTF_INT64_DEC_WIDTH, (int) strlen(str1)));
	sprintf (str1, "%" PRINTF_INT64_MODIFIER "u", UINT64_C(18446744073709550591));
	if (0 != strcmp (str1, "18446744073709550591")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str1));
	if (atoi(PRINTF_UINT64_DEC_WIDTH) != (int) strlen(str1)) REPORTERROR (("Something wrong with PRINTF_UINT64_DEC_WIDTH : %s, %d\n", PRINTF_UINT64_DEC_WIDTH, (int) strlen(str1)));
#endif

	sprintf (str0, "%d %x\n", 0, ~0);

	sprintf (str1, "%d %x\n",  i8, ~0);
	if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i8 : %s\n", str1));
	sprintf (str1, "%u %x\n",  u8, ~0);
	if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with u8 : %s\n", str1));
	sprintf (str1, "%d %x\n",  i16, ~0);
	if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i16 : %s\n", str1));
	sprintf (str1, "%u %x\n",  u16, ~0);
	if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with u16 : %s\n", str1));
	sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n",  i32, ~0);
	if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i32 : %s\n", str1));
	sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n",  u32, ~0);
	if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with u32 : %s\n", str1));
#ifdef INT64_MAX
	sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n",  i64, ~0);
	if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i64 : %s\n", str1));
#endif
	sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n",  imax, ~0);
	if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with imax : %s\n", str1));
	sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n",  umax, ~0);
	if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with umax : %s\n", str1));

	TESTUMAX(8);
	TESTUMAX(16);
	TESTUMAX(32);
#ifdef INT64_MAX
	TESTUMAX(64);
#endif

#define STR(v) #v
#define Q(v) printf ("sizeof " STR(v) " = %u\n", (unsigned) sizeof (v));
	if (err_n) {
		printf ("pstdint.h is not correct.  Please use sizes below to correct it:\n");
	}

	Q(int)
	Q(unsigned)
	Q(long int)
	Q(short int)
	Q(int8_t)
	Q(int16_t)
	Q(int32_t)
#ifdef INT64_MAX
	Q(int64_t)
#endif

#if UINT_MAX < X_SIZE_MAX
	printf ("UINT_MAX < X_SIZE_MAX\n");
#else
	printf ("UINT_MAX >= X_SIZE_MAX\n");
#endif
	printf ("%" PRINTF_INT64_MODIFIER "u vs %" PRINTF_INT64_MODIFIER "u\n", UINT_MAX, X_SIZE_MAX);

	return EXIT_SUCCESS;
}

#endif

Deleted compat/stdlib.h.

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
30
31
32
33
34
35



































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * stdlib.h --
 *
 *	Declares facilities exported by the "stdlib" portion of the C library.
 *	This file isn't complete in the ANSI-C sense; it only declares things
 *	that are needed by Tcl. This file is needed even on many systems with
 *	their own stdlib.h (e.g. SunOS) because not all stdlib.h files declare
 *	all the procedures needed here (such as strtol/strtoul).
 *
 * Copyright (c) 1991 The Regents of the University of California.
 * Copyright (c) 1994-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _STDLIB
#define _STDLIB

extern void		abort(void);
extern double		atof(const char *string);
extern int		atoi(const char *string);
extern long		atol(const char *string);
extern char *		calloc(unsigned int numElements, unsigned int size);
extern void		exit(int status);
extern int		free(char *blockPtr);
extern char *		getenv(const char *name);
extern char *		malloc(unsigned int numBytes);
extern void		qsort(void *base, int n, int size, int (*compar)(
			    const void *element1, const void *element2));
extern char *		realloc(char *ptr, unsigned int numBytes);
extern long		strtol(const char *string, char **endPtr, int base);
extern unsigned long	strtoul(const char *string, char **endPtr, int base);

#endif /* _STDLIB */

Deleted compat/string.h.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53





















































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * string.h --
 *
 *	Declarations of ANSI C library procedures for string handling.
 *
 * Copyright (c) 1991-1993 The Regents of the University of California.
 * Copyright (c) 1994-1996 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _STRING
#define _STRING

/*
 * The following #include is needed to define size_t. (This used to include
 * sys/stdtypes.h but that doesn't exist on older versions of SunOS, e.g.
 * 4.0.2, so I'm trying sys/types.h now.... hopefully it exists everywhere)
 */

#include <sys/types.h>

extern void *		memchr(const void *s, int c, size_t n);
extern int		memcmp(const void *s1, const void *s2, size_t n);
extern void *		memcpy(void *t, const void *f, size_t n);
#ifdef NO_MEMMOVE
#define memmove(d,s,n)	(bcopy((s), (d), (n)))
#else
extern char *		memmove(void *t, const void *f, size_t n);
#endif
extern void *		memset(void *s, int c, size_t n);

extern int		strcasecmp(const char *s1, const char *s2);
extern char *		strcat(char *dst, const char *src);
extern char *		strchr(const char *string, int c);
extern int		strcmp(const char *s1, const char *s2);
extern char *		strcpy(char *dst, const char *src);
extern size_t		strcspn(const char *string, const char *chars);
extern char *		strdup(const char *string);
extern char *		strerror(int error);
extern size_t		strlen(const char *string);
extern int		strncasecmp(const char *s1, const char *s2, size_t n);
extern char *		strncat(char *dst, const char *src, size_t numChars);
extern int		strncmp(const char *s1, const char *s2, size_t nChars);
extern char *		strncpy(char *dst, const char *src, size_t numChars);
extern char *		strpbrk(const char *string, const char *chars);
extern char *		strrchr(const char *string, int c);
extern size_t		strspn(const char *string, const char *chars);
extern char *		strstr(const char *string, const char *substring);
extern char *		strtok(char *s, const char *delim);

#endif /* _STRING */

Deleted compat/strstr.c.

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
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






































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * strstr.c --
 *
 *	Source code for the "strstr" library routine.
 *
 * Copyright (c) 1988-1993 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tcl.h"
#ifndef NULL
#define NULL 0
#endif

/*
 *----------------------------------------------------------------------
 *
 * strstr --
 *
 *	Locate the first instance of a substring in a string.
 *
 * Results:
 *	If string contains substring, the return value is the location of the
 *	first matching instance of substring in string. If string doesn't
 *	contain substring, the return value is 0. Matching is done on an exact
 *	character-for-character basis with no wildcards or special characters.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

char *
strstr(
    const char *string,		/* String to search. */
    const char *substring)		/* Substring to try to find in string. */
{
    const char *a, *b;

    /*
     * First scan quickly through the two strings looking for a
     * single-character match. When it's found, then compare the rest of the
     * substring.
     */

    b = substring;
    if (*b == 0) {
	return (char *)string;
    }
    for ( ; *string != 0; string += 1) {
	if (*string != *b) {
	    continue;
	}
	a = string;
	while (1) {
	    if (*b == 0) {
		return (char *)string;
	    }
	    if (*a++ != *b++) {
		break;
	    }
	}
	b = substring;
    }
    return NULL;
}

Deleted compat/strtol.c.

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
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













































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * strtol.c --
 *
 *	Source code for the "strtol" library procedure.
 *
 * Copyright (c) 1988 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

/*
 *----------------------------------------------------------------------
 *
 * strtol --
 *
 *	Convert an ASCII string into an integer.
 *
 * Results:
 *	The return value is the integer equivalent of string. If endPtr is
 *	non-NULL, then *endPtr is filled in with the character after the last
 *	one that was part of the integer. If string doesn't contain a valid
 *	integer value, then zero is returned and *endPtr is set to string.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

long int
strtol(
    const char *string,		/* String of ASCII digits, possibly preceded
				 * by white space. For bases greater than 10,
				 * either lower- or upper-case digits may be
				 * used. */
    char **endPtr,		/* Where to store address of terminating
				 * character, or NULL. */
    int base)			/* Base for conversion. Must be less than 37.
				 * If 0, then the base is chosen from the
				 * leading characters of string: "0x" means
				 * hex, "0" means octal, anything else means
				 * decimal. */
{
    const char *p;
    long result;

    /*
     * Skip any leading blanks.
     */

    p = string;
    while (isspace(UCHAR(*p))) {
	p += 1;
    }

    /*
     * Check for a sign.
     */

    if (*p == '-') {
	p += 1;
	result = -(strtoul(p, endPtr, base));
    } else {
	if (*p == '+') {
	    p += 1;
	}
	result = strtoul(p, endPtr, base);
    }
    if ((result == 0) && (endPtr != 0) && (*endPtr == p)) {
	*endPtr = (char *) string;
    }
    return result;
}

Deleted compat/strtoul.c.

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
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






















































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * strtoul.c --
 *
 *	Source code for the "strtoul" library procedure.
 *
 * Copyright (c) 1988 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

/*
 * The table below is used to convert from ASCII digits to a numerical
 * equivalent. It maps from '0' through 'z' to integers (100 for non-digit
 * characters).
 */

static const char cvtIn[] = {
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9,		/* '0' - '9' */
    100, 100, 100, 100, 100, 100, 100,		/* punctuation */
    10, 11, 12, 13, 14, 15, 16, 17, 18, 19,	/* 'A' - 'Z' */
    20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
    30, 31, 32, 33, 34, 35,
    100, 100, 100, 100, 100, 100,		/* punctuation */
    10, 11, 12, 13, 14, 15, 16, 17, 18, 19,	/* 'a' - 'z' */
    20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
    30, 31, 32, 33, 34, 35};

/*
 *----------------------------------------------------------------------
 *
 * strtoul --
 *
 *	Convert an ASCII string into an integer.
 *
 * Results:
 *	The return value is the integer equivalent of string. If endPtr is
 *	non-NULL, then *endPtr is filled in with the character after the last
 *	one that was part of the integer. If string doesn't contain a valid
 *	integer value, then zero is returned and *endPtr is set to string.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

unsigned long int
strtoul(
    const char *string,		/* String of ASCII digits, possibly preceded
				 * by white space. For bases greater than 10,
				 * either lower- or upper-case digits may be
				 * used. */
    char **endPtr,		/* Where to store address of terminating
				 * character, or NULL. */
    int base)			/* Base for conversion.  Must be less than 37.
				 * If 0, then the base is chosen from the
				 * leading characters of string: "0x" means
				 * hex, "0" means octal, anything else means
				 * decimal. */
{
    const char *p;
    unsigned long int result = 0;
    unsigned digit;
    int anyDigits = 0;
    int negative=0;
    int overflow=0;

    /*
     * Skip any leading blanks.
     */

    p = string;
    while (isspace(UCHAR(*p))) {
	p += 1;
    }
    if (*p == '-') {
        negative = 1;
        p += 1;
    } else {
        if (*p == '+') {
            p += 1;
        }
    }

    /*
     * If no base was provided, pick one from the leading characters of the
     * string.
     */

    if (base == 0) {
	if (*p == '0') {
	    p += 1;
	    if ((*p == 'x') || (*p == 'X')) {
		p += 1;
		base = 16;
	    } else {
		/*
		 * Must set anyDigits here, otherwise "0" produces a "no
		 * digits" error.
		 */

		anyDigits = 1;
		base = 8;
	    }
	} else {
	    base = 10;
	}
    } else if (base == 16) {
	/*
	 * Skip a leading "0x" from hex numbers.
	 */

	if ((p[0] == '0') && ((p[1] == 'x') || (p[1] == 'X'))) {
	    p += 2;
	}
    }

    /*
     * Sorry this code is so messy, but speed seems important. Do different
     * things for base 8, 10, 16, and other.
     */

    if (base == 8) {
	unsigned long maxres = ULONG_MAX >> 3;

	for ( ; ; p += 1) {
	    digit = *p - '0';
	    if (digit > 7) {
		break;
	    }
	    if (result > maxres) { overflow = 1; }
	    result = (result << 3);
	    if (digit > (ULONG_MAX - result)) { overflow = 1; }
	    result += digit;
	    anyDigits = 1;
	}
    } else if (base == 10) {
	unsigned long maxres = ULONG_MAX / 10;

	for ( ; ; p += 1) {
	    digit = *p - '0';
	    if (digit > 9) {
		break;
	    }
	    if (result > maxres) { overflow = 1; }
	    result *= 10;
	    if (digit > (ULONG_MAX - result)) { overflow = 1; }
	    result += digit;
	    anyDigits = 1;
	}
    } else if (base == 16) {
	unsigned long maxres = ULONG_MAX >> 4;

	for ( ; ; p += 1) {
	    digit = *p - '0';
	    if (digit > ('z' - '0')) {
		break;
	    }
	    digit = cvtIn[digit];
	    if (digit > 15) {
		break;
	    }
	    if (result > maxres) { overflow = 1; }
	    result = (result << 4);
	    if (digit > (ULONG_MAX - result)) { overflow = 1; }
	    result += digit;
	    anyDigits = 1;
	}
    } else if (base >= 2 && base <= 36) {
	unsigned long maxres = ULONG_MAX / base;

	for ( ; ; p += 1) {
	    digit = *p - '0';
	    if (digit > ('z' - '0')) {
		break;
	    }
	    digit = cvtIn[digit];
	    if (digit >= ( (unsigned) base )) {
		break;
	    }
	    if (result > maxres) { overflow = 1; }
	    result *= base;
	    if (digit > (ULONG_MAX - result)) { overflow = 1; }
	    result += digit;
	    anyDigits = 1;
	}
    }

    /*
     * See if there were any digits at all.
     */

    if (!anyDigits) {
	p = string;
    }

    if (endPtr != 0) {
	/* unsafe, but required by the strtoul prototype */
	*endPtr = (char *) p;
    }

    if (overflow) {
	errno = ERANGE;
	return ULONG_MAX;
    }
    if (negative) {
	return -result;
    }
    return result;
}

Changes to compat/waitpid.c.

152
153
154
155
156
157
158
159





160
161
162
163
164
165
166
152
153
154
155
156
157
158

159
160
161
162
163
164
165
166
167
168
169
170







-
+
+
+
+
+







    saveInfo:
	for (waitPtr = deadList; waitPtr != NULL; waitPtr = waitPtr->nextPtr) {
	    if (waitPtr->pid == result) {
		waitPtr->status = status;
		goto waitAgain;
	    }
	}
	waitPtr = (WaitInfo *) Tcl_Alloc(sizeof(WaitInfo));
	waitPtr = (WaitInfo *) Tcl_AttemptAlloc(sizeof(WaitInfo));
	if (!waitPtr) {
	    errno = ENOMEM;
	    return -1;
	}
	waitPtr->pid = result;
	waitPtr->status = status;
	waitPtr->nextPtr = deadList;
	deadList = waitPtr;

    waitAgain:
	continue;

Changes to compat/zlib/CMakeLists.txt.

1

2
3
4
5
6

7
8

9
10
11
12
13
14
15
16

1
2
3
4
5

6
7

8

9
10
11
12
13
14
15
-
+




-
+

-
+
-







cmake_minimum_required(VERSION 2.4.4)
cmake_minimum_required(VERSION 2.4.4...3.15.0)
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)

project(zlib C)

set(VERSION "1.2.11")
set(VERSION "1.3.1")

option(ASM686 "Enable building i686 assembly implementation")
option(ZLIB_BUILD_EXAMPLES "Enable Zlib Examples" ON)
option(AMD64 "Enable building amd64 assembly implementation")

set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers")
set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages")
set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")

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
124
125
126
127
128
129
130

































131
132
133
134
135
136
137







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








if(NOT MINGW)
    set(ZLIB_DLL_SRCS
        win32/zlib1.rc # If present will override custom build rule below.
    )
endif()

if(CMAKE_COMPILER_IS_GNUCC)
    if(ASM686)
        set(ZLIB_ASMS contrib/asm686/match.S)
    elseif (AMD64)
        set(ZLIB_ASMS contrib/amd64/amd64-match.S)
    endif ()

	if(ZLIB_ASMS)
		add_definitions(-DASMV)
		set_source_files_properties(${ZLIB_ASMS} PROPERTIES LANGUAGE C COMPILE_FLAGS -DNO_UNDERLINE)
	endif()
endif()

if(MSVC)
    if(ASM686)
		ENABLE_LANGUAGE(ASM_MASM)
        set(ZLIB_ASMS
			contrib/masmx86/inffas32.asm
			contrib/masmx86/match686.asm
		)
    elseif (AMD64)
		ENABLE_LANGUAGE(ASM_MASM)
        set(ZLIB_ASMS
			contrib/masmx64/gvmat64.asm
			contrib/masmx64/inffasx64.asm
		)
    endif()

	if(ZLIB_ASMS)
		add_definitions(-DASMV -DASMINF)
	endif()
endif()

# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents)
string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*"
    "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents})

if(MINGW)
    # This gets us DLL resource information when compiling on MinGW.
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
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







-
-
+
+
+
+

















-
+







                            -I ${CMAKE_CURRENT_SOURCE_DIR}
                            -I ${CMAKE_CURRENT_BINARY_DIR}
                            -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
                            -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc)
    set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj)
endif(MINGW)

add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
target_include_directories(zlib PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
target_include_directories(zlibstatic PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
set_target_properties(zlib PROPERTIES SOVERSION 1)

if(NOT CYGWIN)
    # This property causes shared libraries on Linux to have the full version
    # encoded into their final filename.  We disable this on Cygwin because
    # it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll
    # seems to be the default.
    #
    # This has no effect with MSVC, on that platform the version info for
    # the DLL comes from the resource file win32/zlib1.rc
    set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION})
endif()

if(UNIX)
    # On unix-like platforms the library is almost always called libz
   set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z)
   if(NOT APPLE)
   if(NOT APPLE AND NOT(CMAKE_SYSTEM_NAME STREQUAL AIX))
     set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"")
   endif()
elseif(BUILD_SHARED_LIBS AND WIN32)
    # Creates zlib1.dll when building shared library version
    set_target_properties(zlib PROPERTIES SUFFIX "1.dll")
endif()

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





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







-
-
-
-
+
+
+
+

-
-
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
+
+
+
+
+
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
    install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}")
endif()

#============================================================================
# Example binaries
#============================================================================

add_executable(example test/example.c)
target_link_libraries(example zlib)
add_test(example example)
if(ZLIB_BUILD_EXAMPLES)
    add_executable(example test/example.c)
    target_link_libraries(example zlib)
    add_test(example example)

add_executable(minigzip test/minigzip.c)
target_link_libraries(minigzip zlib)
    add_executable(minigzip test/minigzip.c)
    target_link_libraries(minigzip zlib)

if(HAVE_OFF64_T)
    add_executable(example64 test/example.c)
    target_link_libraries(example64 zlib)
    set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
    add_test(example64 example64)
    if(HAVE_OFF64_T)
        add_executable(example64 test/example.c)
        target_link_libraries(example64 zlib)
        set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
        add_test(example64 example64)

    add_executable(minigzip64 test/minigzip.c)
    target_link_libraries(minigzip64 zlib)
    set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
endif()
        add_executable(minigzip64 test/minigzip.c)
        target_link_libraries(minigzip64 zlib)
        set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
    endif()
endif()

Changes to compat/zlib/ChangeLog.

1
2
3







































































































4
5
6
7
8
9
10
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
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



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








                ChangeLog file for zlib

Changes in 1.3.1 (22 Jan 2024)
- Reject overflows of zip header fields in minizip
- Fix bug in inflateSync() for data held in bit buffer
- Add LIT_MEM define to use more memory for a small deflate speedup
- Fix decision on the emission of Zip64 end records in minizip
- Add bounds checking to ERR_MSG() macro, used by zError()
- Neutralize zip file traversal attacks in miniunz
- Fix a bug in ZLIB_DEBUG compiles in check_match()
- Various portability and appearance improvements

Changes in 1.3 (18 Aug 2023)
- Remove K&R function definitions and zlib2ansi
- Fix bug in deflateBound() for level 0 and memLevel 9
- Fix bug when gzungetc() is used immediately after gzopen()
- Fix bug when using gzflush() with a very small buffer
- Fix crash when gzsetparams() attempted for transparent write
- Fix test/example.c to work with FORCE_STORED
- Rewrite of zran in examples (see zran.c version history)
- Fix minizip to allow it to open an empty zip file
- Fix reading disk number start on zip64 files in minizip
- Fix logic error in minizip argument processing
- Add minizip testing to Makefile
- Read multiple bytes instead of byte-by-byte in minizip unzip.c
- Add memory sanitizer to configure (--memory)
- Various portability improvements
- Various documentation improvements
- Various spelling and typo corrections

Changes in 1.2.13 (13 Oct 2022)
- Fix configure issue that discarded provided CC definition
- Correct incorrect inputs provided to the CRC functions
- Repair prototypes and exporting of new CRC functions
- Fix inflateBack to detect invalid input with distances too far
- Have infback() deliver all of the available output up to any error
- Fix a bug when getting a gzip header extra field with inflate()
- Fix bug in block type selection when Z_FIXED used
- Tighten deflateBound bounds
- Remove deleted assembler code references
- Various portability and appearance improvements

Changes in 1.2.12 (27 Mar 2022)
- Cygwin does not have _wopen(), so do not create gzopen_w() there
- Permit a deflateParams() parameter change as soon as possible
- Limit hash table inserts after switch from stored deflate
- Fix bug when window full in deflate_stored()
- Fix CLEAR_HASH macro to be usable as a single statement
- Avoid a conversion error in gzseek when off_t type too small
- Have Makefile return non-zero error code on test failure
- Avoid some conversion warnings in gzread.c and gzwrite.c
- Update use of errno for newer Windows CE versions
- Small speedup to inflate [psumbera]
- Return an error if the gzputs string length can't fit in an int
- Add address checking in clang to -w option of configure
- Don't compute check value for raw inflate if asked to validate
- Handle case where inflateSync used when header never processed
- Avoid the use of ptrdiff_t
- Avoid an undefined behavior of memcpy() in gzappend()
- Avoid undefined behaviors of memcpy() in gz*printf()
- Avoid an undefined behavior of memcpy() in _tr_stored_block()
- Make the names in functions declarations identical to definitions
- Remove old assembler code in which bugs have manifested
- Fix deflateEnd() to not report an error at start of raw deflate
- Add legal disclaimer to README
- Emphasize the need to continue decompressing gzip members
- Correct the initialization requirements for deflateInit2()
- Fix a bug that can crash deflate on some input when using Z_FIXED
- Assure that the number of bits for deflatePrime() is valid
- Use a structure to make globals in enough.c evident
- Use a macro for the printf format of big_t in enough.c
- Clean up code style in enough.c, update version
- Use inline function instead of macro for index in enough.c
- Clarify that prefix codes are counted in enough.c
- Show all the codes for the maximum tables size in enough.c
- Add gznorm.c example, which normalizes gzip files
- Fix the zran.c example to work on a multiple-member gzip file
- Add tables for crc32_combine(), to speed it up by a factor of 200
- Add crc32_combine_gen() and crc32_combine_op() for fast combines
- Speed up software CRC-32 computation by a factor of 1.5 to 3
- Use atomic test and set, if available, for dynamic CRC tables
- Don't bother computing check value after successful inflateSync()
- Correct comment in crc32.c
- Add use of the ARMv8 crc32 instructions when requested
- Use ARM crc32 instructions if the ARM architecture has them
- Explicitly note that the 32-bit check values are 32 bits
- Avoid adding empty gzip member after gzflush with Z_FINISH
- Fix memory leak on error in gzlog.c
- Fix error in comment on the polynomial representation of a byte
- Clarify gz* function interfaces, referring to parameter names
- Change macro name in inflate.c to avoid collision in VxWorks
- Correct typo in blast.c
- Improve portability of contrib/minizip
- Fix indentation in minizip's zip.c
- Replace black/white with allow/block. (theresa-m)
- minizip warning fix if MAXU32 already defined. (gvollant)
- Fix unztell64() in minizip to work past 4GB. (Daniël Hörchner)
- Clean up minizip to reduce warnings for testing
- Add fallthrough comments for gcc
- Eliminate use of ULL constants
- Separate out address sanitizing from warnings in configure
- Remove destructive aspects of make distclean
- Check for cc masquerading as gcc or clang in configure
- Fix crc32.c to compile local functions only if used

Changes in 1.2.11 (15 Jan 2017)
- Fix deflate stored bug when pulling last block from window
- Permit immediate deflateParams changes before any deflate input

Changes in 1.2.10 (2 Jan 2017)
- Avoid warnings on snprintf() return value
- Fix bug in deflate_stored() for zero-length input
92
93
94
95
96
97
98
99

100
101
102
103
104
105
106
195
196
197
198
199
200
201

202
203
204
205
206
207
208
209







-
+







- Add contrib/vstudio/vc10 pre-build step for static only
- Quote --version-script argument in CMakeLists.txt
- Don't specify --version-script on Apple platforms in CMakeLists.txt
- Fix casting error in contrib/testzlib/testzlib.c
- Fix types in contrib/minizip to match result of get_crc_table()
- Simplify contrib/vstudio/vc10 with 'd' suffix
- Add TOP support to win32/Makefile.msc
- Suport i686 and amd64 assembler builds in CMakeLists.txt
- Support i686 and amd64 assembler builds in CMakeLists.txt
- Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h
- Add vc11 and vc12 build files to contrib/vstudio
- Add gzvprintf() as an undocumented function in zlib
- Fix configure for Sun shell
- Remove runtime check in configure for four-byte integer type
- Add casts and consts to ease user conversion to C++
- Add man pages for minizip and miniunzip
292
293
294
295
296
297
298
299

300
301
302
303
304
305
306

307
308
309
310
311
312
313
395
396
397
398
399
400
401

402
403
404
405
406
407
408

409
410
411
412
413
414
415
416







-
+






-
+







- Avoid deflate sensitivity to volatile input data
- Avoid division in adler32_combine for NO_DIVIDE
- Clarify the use of Z_FINISH with deflateBound() amount of space
- Set binary for output file in puff.c
- Use u4 type for crc_table to avoid conversion warnings
- Apply casts in zlib.h to avoid conversion warnings
- Add OF to prototypes for adler32_combine_ and crc32_combine_ [Miller]
- Improve inflateSync() documentation to note indeterminancy
- Improve inflateSync() documentation to note indeterminacy
- Add deflatePending() function to return the amount of pending output
- Correct the spelling of "specification" in FAQ [Randers-Pehrson]
- Add a check in configure for stdarg.h, use for gzprintf()
- Check that pointers fit in ints when gzprint() compiled old style
- Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler]
- Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt]
- Add debug records in assmebler code [Londer]
- Add debug records in assembler code [Londer]
- Update RFC references to use http://tools.ietf.org/html/... [Li]
- Add --archs option, use of libtool to configure for Mac OS X [Borstel]

Changes in 1.2.5 (19 Apr 2010)
- Disable visibility attribute in win32/Makefile.gcc [Bar-Lev]
- Default to libdir as sharedlibdir in configure [Nieder]
- Update copyright dates on modified source files
507
508
509
510
511
512
513
514

515
516
517
518
519
520
521
610
611
612
613
614
615
616

617
618
619
620
621
622
623
624







-
+







- Use zlib header window size if windowBits is 0 in inflateInit2()
- Remove compressBound() call in deflate.c to avoid linking compress.o
- Replace use of errno in gz* with functions, support WinCE [Alves]
- Provide alternative to perror() in minigzip.c for WinCE [Alves]
- Don't use _vsnprintf on later versions of MSVC [Lowman]
- Add CMake build script and input file [Lowman]
- Update contrib/minizip to 1.1 [Svensson, Vollant]
- Moved nintendods directory from contrib to .
- Moved nintendods directory from contrib to root
- Replace gzio.c with a new set of routines with the same functionality
- Add gzbuffer(), gzoffset(), gzclose_r(), gzclose_w() as part of above
- Update contrib/minizip to 1.1b
- Change gzeof() to return 0 on error instead of -1 to agree with zlib.h

Changes in 1.2.3.4 (21 Dec 2009)
- Use old school .SUFFIXES in Makefile.in for FreeBSD compatibility
681
682
683
684
685
686
687
688

689
690
691
692
693
694
695
784
785
786
787
788
789
790

791
792
793
794
795
796
797
798







-
+







- Add cast in trees.c t avoid a warning [Oberhumer]
- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer]
- Update make_vms.com [Zinser]
- Initialize state->write in inflateReset() since copied in inflate_fast()
- Be more strict on incomplete code sets in inflate_table() and increase
  ENOUGH and MAXD -- this repairs a possible security vulnerability for
  invalid inflate input.  Thanks to Tavis Ormandy and Markus Oberhumer for
  discovering the vulnerability and providing test cases.
  discovering the vulnerability and providing test cases
- Add ia64 support to configure for HP-UX [Smith]
- Add error return to gzread() for format or i/o error [Levin]
- Use malloc.h for OS/2 [Necasek]

Changes in 1.2.2.3 (27 May 2005)
- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile
- Typecast fread() return values in gzio.c [Vollant]
717
718
719
720
721
722
723
724

725
726
727
728
729
730
731
820
821
822
823
824
825
826

827
828
829
830
831
832
833
834







-
+







- Increase sprintf() buffer size in gzdopen() to allow for large numbers
- Add INFLATE_STRICT to check distances against zlib header
- Improve WinCE errno handling and comments [Chang]
- Remove comment about no gzip header processing in FAQ
- Add Z_FIXED strategy option to deflateInit2() to force fixed trees
- Add updated make_vms.com [Coghlan], update README
- Create a new "examples" directory, move gzappend.c there, add zpipe.c,
  fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html.
  fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html
- Add FAQ entry and comments in deflate.c on uninitialized memory access
- Add Solaris 9 make options in configure [Gilbert]
- Allow strerror() usage in gzio.c for STDC
- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer]
- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant]
- Use z_off_t for adler32_combine() and crc32_combine() lengths
- Make adler32() much faster for small len
788
789
790
791
792
793
794
795

796
797
798
799
800
801
802
891
892
893
894
895
896
897

898
899
900
901
902
903
904
905







-
+








Changes in 1.2.1.1 (9 January 2004)
- Update email address in README
- Several FAQ updates
- Fix a big fat bug in inftrees.c that prevented decoding valid
  dynamic blocks with only literals and no distance codes --
  Thanks to "Hot Emu" for the bug report and sample file
- Add a note to puff.c on no distance codes case.
- Add a note to puff.c on no distance codes case

Changes in 1.2.1 (17 November 2003)
- Remove a tab in contrib/gzappend/gzappend.c
- Update some interfaces in contrib for new zlib functions
- Update zlib version number in some contrib entries
- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta]
- Support shared libraries on Hurd and KFreeBSD [Brown]
966
967
968
969
970
971
972
973

974
975
976
977
978
979
980
1069
1070
1071
1072
1073
1074
1075

1076
1077
1078
1079
1080
1081
1082
1083







-
+







- Clean up what gets compiled for FASTEST
- Incorporate changes to zconf.in.h [Vollant]
    - Refine detection of Turbo C need for dummy returns
    - Refine ZLIB_DLL compilation
    - Include additional header file on VMS for off_t typedef
- Try to use _vsnprintf where it supplants vsprintf [Vollant]
- Add some casts in inffast.c
- Enchance comments in zlib.h on what happens if gzprintf() tries to
- Enhance comments in zlib.h on what happens if gzprintf() tries to
  write more than 4095 bytes before compression
- Remove unused state from inflateBackEnd()
- Remove exit(0) from minigzip.c, example.c
- Get rid of all those darn tabs
- Add "check" target to Makefile.in that does the same thing as "test"
- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in
- Update contrib/inflate86 [Anderson]
1032
1033
1034
1035
1036
1037
1038
1039

1040
1041
1042
1043
1044

1045
1046

1047
1048
1049
1050
1051
1052
1053
1135
1136
1137
1138
1139
1140
1141

1142
1143
1144
1145
1146

1147
1148

1149
1150
1151
1152
1153
1154
1155
1156







-
+




-
+

-
+







    - Note permitted values of flush parameter of inflate()
- Add some FAQs (and even answers) to the FAQ
- Add contrib/inflate86/ for x86 faster inflate
- Add contrib/blast/ for PKWare Data Compression Library decompression
- Add contrib/puff/ simple inflate for deflate format description

Changes in 1.1.4 (11 March 2002)
- ZFREE was repeated on same allocation on some error conditions.
- ZFREE was repeated on same allocation on some error conditions
  This creates a security problem described in
  http://www.zlib.org/advisory-2002-03-11.txt
- Returned incorrect error (Z_MEM_ERROR) on some invalid data
- Avoid accesses before window for invalid distances with inflate window
  less than 32K.
  less than 32K
- force windowBits > 8 to avoid a bug in the encoder for a window size
  of 256 bytes. (A complete fix will be available in 1.1.5).
  of 256 bytes. (A complete fix will be available in 1.1.5)

Changes in 1.1.3 (9 July 1998)
- fix "an inflate input buffer bug that shows up on rare but persistent
  occasions" (Mark)
- fix gzread and gztell for concatenated .gz files (Didier Le Botlan)
- fix gzseek(..., SEEK_SET) in write mode
- fix crc check after a gzeek (Frank Faubert)
1113
1114
1115
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
1216
1217
1218
1219
1220
1221
1222

1223
1224
1225
1226
1227
1228
1229
1230







-
+







- move Makefile.sas to amiga/Makefile.sas

Changes in 1.1.1 (27 Feb 98)
- fix macros _tr_tally_* in deflate.h for debug mode  (Glenn Randers-Pehrson)
- remove block truncation heuristic which had very marginal effect for zlib
  (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the
  compression ratio on some files. This also allows inlining _tr_tally for
  matches in deflate_slow.
  matches in deflate_slow
- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier)

Changes in 1.1.0 (24 Feb 98)
- do not return STREAM_END prematurely in inflate (John Bowler)
- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler)
- compile with -DFASTEST to get compression code optimized for speed only
- in minigzip, try mmap'ing the input file first (Miguel Albrecht)
1144
1145
1146
1147
1148
1149
1150
1151

1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165

1166
1167
1168
1169
1170
1171
1172
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







-
+













-
+







 . ZALLOC the length list in inflate_trees_fixed() instead of using stack
 . ZALLOC the value area for huft_build() instead of using stack
 . Simplify Z_FINISH check in inflate()

- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8
- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi)
- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with
  the declaration of FAR (Gilles VOllant)
  the declaration of FAR (Gilles Vollant)
- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann)
- read_buf buf parameter of type Bytef* instead of charf*
- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout)
- do not redeclare unlink in minigzip.c for WIN32 (John Bowler)
- fix check for presence of directories in "make install" (Ian Willis)

Changes in 1.0.8 (27 Jan 1998)
- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant)
- fix gzgetc and gzputc for big endian systems (Markus Oberhumer)
- added compress2() to allow setting the compression level
- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong)
- use constant arrays for the static trees in trees.c instead of computing
  them at run time (thanks to Ken Raeburn for this suggestion). To create
  trees.h, compile with GEN_TREES_H and run "make test".
  trees.h, compile with GEN_TREES_H and run "make test"
- check return code of example in "make test" and display result
- pass minigzip command line options to file_compress
- simplifying code of inflateSync to avoid gcc 2.8 bug

- support CC="gcc -Wall" in configure -s (QingLong)
- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn)
- fix test for shared library support to avoid compiler warnings
1197
1198
1199
1200
1201
1202
1203
1204
1205


1206
1207
1208
1209

1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221

1222
1223
1224
1225
1226
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
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
1354

1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393







-
-
+
+



-
+











-
+







-
+








-
-
+
+












-
+









-
+




















-
+







- add inflateSyncPoint in zconf.h
- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def

Changes in 1.0.6 (19 Jan 1998)
- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and
  gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code)
- Fix a deflate bug occurring only with compression level 0 (thanks to
  Andy Buckler for finding this one).
- In minigzip, pass transparently also the first byte for .Z files.
  Andy Buckler for finding this one)
- In minigzip, pass transparently also the first byte for .Z files
- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress()
- check Z_FINISH in inflate (thanks to Marc Schluper)
- Implement deflateCopy (thanks to Adam Costello)
- make static libraries by default in configure, add --shared option.
- make static libraries by default in configure, add --shared option
- move MSDOS or Windows specific files to directory msdos
- suppress the notion of partial flush to simplify the interface
  (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4)
- suppress history buffer provided by application to simplify the interface
  (this feature was not implemented anyway in 1.0.4)
- next_in and avail_in must be initialized before calling inflateInit or
  inflateInit2
- add EXPORT in all exported functions (for Windows DLL)
- added Makefile.nt (thanks to Stephen Williams)
- added the unsupported "contrib" directory:
   contrib/asm386/ by Gilles Vollant <info@winimage.com>
        386 asm code replacing longest_match().
        386 asm code replacing longest_match()
   contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
        A C++ I/O streams interface to the zlib gz* functions
   contrib/iostream2/  by Tyge Løvset <Tyge.Lovset@cmr.no>
        Another C++ I/O streams interface
   contrib/untgz/  by "Pedro A. Aranda Guti\irrez" <paag@tid.es>
        A very simple tar.gz file extractor using zlib
   contrib/visual-basic.txt by Carlos Rios <c_rios@sonda.cl>
        How to use compress(), uncompress() and the gz* functions from VB.
        How to use compress(), uncompress() and the gz* functions from VB
- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression
  level) in minigzip (thanks to Tom Lane)

- use const for rommable constants in deflate
- added test for gzseek and gztell in example.c
- add undocumented function inflateSyncPoint() (hack for Paul Mackerras)
- add undocumented function zError to convert error code to string
  (for Tim Smithers)
- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code.
- Use default memcpy for Symantec MSDOS compiler.
- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code
- Use default memcpy for Symantec MSDOS compiler
- Add EXPORT keyword for check_func (needed for Windows DLL)
- add current directory to LD_LIBRARY_PATH for "make test"
- create also a link for libz.so.1
- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura)
- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX)
- added -soname for Linux in configure (Chun-Chung Chen,
- assign numbers to the exported functions in zlib.def (for Windows DLL)
- add advice in zlib.h for best usage of deflateSetDictionary
- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn)
- allow compilation with ANSI keywords only enabled for TurboC in large model
- avoid "versionString"[0] (Borland bug)
- add NEED_DUMMY_RETURN for Borland
- use variable z_verbose for tracing in debug mode (L. Peter Deutsch).
- use variable z_verbose for tracing in debug mode (L. Peter Deutsch)
- allow compilation with CC
- defined STDC for OS/2 (David Charlap)
- limit external names to 8 chars for MVS (Thomas Lund)
- in minigzip.c, use static buffers only for 16-bit systems
- fix suffix check for "minigzip -d foo.gz"
- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee)
- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau)
- added makelcc.bat for lcc-win32 (Tom St Denis)
- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe)
- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion.
- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion
- check for unistd.h in configure (for off_t)
- remove useless check parameter in inflate_blocks_free
- avoid useless assignment of s->check to itself in inflate_blocks_new
- do not flush twice in gzclose (thanks to Ken Raeburn)
- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h
- use NO_ERRNO_H instead of enumeration of operating systems with errno.h
- work around buggy fclose on pipes for HP/UX
- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson)
- fix configure if CC is already equal to gcc

Changes in 1.0.5 (3 Jan 98)
- Fix inflate to terminate gracefully when fed corrupted or invalid data
- Use const for rommable constants in inflate
- Eliminate memory leaks on error conditions in inflate
- Removed some vestigial code in inflate
- Update web address in README

Changes in 1.0.4 (24 Jul 96)
- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
  bit, so the decompressor could decompress all the correct data but went
  on to attempt decompressing extra garbage data. This affected minigzip too.
  on to attempt decompressing extra garbage data. This affected minigzip too
- zlibVersion and gzerror return const char* (needed for DLL)
- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno)
- use z_error only for DEBUG (avoid problem with DLLs)

Changes in 1.0.3 (2 Jul 96)
- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS
  small and medium models; this makes the library incompatible with previous
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
1409
1410
1411
1412
1413
1414
1415

1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436

1437
1438
1439
1440
1441
1442
1443
1444







-
+




















-
+







- updated Makefile.dj2
- added algorithm.doc

Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion]
- fix array overlay in deflate.c which sometimes caused bad compressed data
- fix inflate bug with empty stored block
- fix MSDOS medium model which was broken in 0.99
- fix deflateParams() which could generate bad compressed data.
- fix deflateParams() which could generate bad compressed data
- Bytef is define'd instead of typedef'ed (work around Borland bug)
- added an INDEX file
- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32),
  Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas)
- speed up adler32 for modern machines without auto-increment
- added -ansi for IRIX in configure
- static_init_done in trees.c is an int
- define unlink as delete for VMS
- fix configure for QNX
- add configure branch for SCO and HPUX
- avoid many warnings (unused variables, dead assignments, etc...)
- no fdopen for BeOS
- fix the Watcom fix for 32 bit mode (define FAR as empty)
- removed redefinition of Byte for MKWERKS
- work around an MWKERKS bug (incorrect merge of all .h files)

Changes in 0.99 (27 Jan 96)
- allow preset dictionary shared between compressor and decompressor
- allow compression level 0 (no compression)
- add deflateParams in zlib.h: allow dynamic change of compression level
  and compression strategy.
  and compression strategy
- test large buffers and deflateParams in example.c
- add optional "configure" to build zlib as a shared library
- suppress Makefile.qnx, use configure instead
- fixed deflate for 64-bit systems (detected on Cray)
- fixed inflate_blocks for 64-bit systems (detected on Alpha)
- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2)
- always return Z_BUF_ERROR when deflate() has nothing to do
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
1393
1394
1395

1396
1397

1398
1399

1400
1401
1402
1403
1404
1405
1406
1407
1408

1409
1410
1411
1412
1413

1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432

1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478

1479
1480
1481
1482
1483

1484
1485

1486
1487
1488
1489
1490
1491

1492
1493

1494
1495
1496
1497



1498
1499
1500

1501
1502

1503
1504
1505

1506
1507

1508
1509

1510
1511
1512
1513

1514
1515
1469
1470
1471
1472
1473
1474
1475

1476
1477
1478

1479
1480
1481
1482
1483
1484

1485
1486
1487

1488
1489
1490

1491
1492
1493
1494
1495
1496
1497

1498
1499

1500
1501

1502
1503
1504
1505
1506
1507
1508
1509
1510

1511
1512
1513
1514
1515

1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534

1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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







-
+


-
+





-
+


-
+


-
+






-
+

-
+

-
+








-
+




-
+


















-
+

















-
+








-
+









-
+


-
+


-
+


-
+




-
+

-
+





-
+

-
+

-
-
-
+
+
+


-
+

-
+


-
+

-
+

-
+



-
+


- clear z->msg in inflateInit2 before any error return
- initialize opaque in example.c, gzio.c, deflate.c and inflate.c
- fixed typo in zconf.h (_GNUC__ => __GNUC__)
- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode)
- fix typo in Make_vms.com (f$trnlnm -> f$getsyi)
- in fcalloc, normalize pointer if size > 65520 bytes
- don't use special fcalloc for 32 bit Borland C++
- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc...
- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc.
- use Z_BINARY instead of BINARY
- document that gzclose after gzdopen will close the file
- allow "a" as mode in gzopen.
- allow "a" as mode in gzopen
- fix error checking in gzread
- allow skipping .gz extra-field on pipes
- added reference to Perl interface in README
- put the crc table in FAR data (I dislike more and more the medium model :)
- added get_crc_table
- added a dimension to all arrays (Borland C can't count).
- added a dimension to all arrays (Borland C can't count)
- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast
- guard against multiple inclusion of *.h (for precompiled header on Mac)
- Watcom C pretends to be Microsoft C small model even in 32 bit mode.
- Watcom C pretends to be Microsoft C small model even in 32 bit mode
- don't use unsized arrays to avoid silly warnings by Visual C++:
     warning C4746: 'inflate_mask' : unsized array treated as  '__far'
     (what's wrong with far data in far model?).
     (what's wrong with far data in far model?)
- define enum out of inflate_blocks_state to allow compilation with C++

Changes in 0.95 (16 Aug 95)
- fix MSDOS small and medium model (now easier to adapt to any compiler)
- inlined send_bits
- fix the final (:-) bug for deflate with flush (output was correct but
  not completely flushed in rare occasions).
  not completely flushed in rare occasions)
- default window size is same for compression and decompression
  (it's now sufficient to set MAX_WBITS in zconf.h).
  (it's now sufficient to set MAX_WBITS in zconf.h)
- voidp -> voidpf and voidnp -> voidp (for consistency with other
  typedefs and because voidnp was not near in large model).
  typedefs and because voidnp was not near in large model)

Changes in 0.94 (13 Aug 95)
- support MSDOS medium model
- fix deflate with flush (could sometimes generate bad output)
- fix deflateReset (zlib header was incorrectly suppressed)
- added support for VMS
- allow a compression level in gzopen()
- gzflush now calls fflush
- For deflate with flush, flush even if no more input is provided.
- For deflate with flush, flush even if no more input is provided
- rename libgz.a as libz.a
- avoid complex expression in infcodes.c triggering Turbo C bug
- work around a problem with gcc on Alpha (in INSERT_STRING)
- don't use inline functions (problem with some gcc versions)
- allow renaming of Byte, uInt, etc... with #define.
- allow renaming of Byte, uInt, etc... with #define
- avoid warning about (unused) pointer before start of array in deflate.c
- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c
- avoid reserved word 'new' in trees.c

Changes in 0.93 (25 June 95)
- temporarily disable inline functions
- make deflate deterministic
- give enough lookahead for PARTIAL_FLUSH
- Set binary mode for stdin/stdout in minigzip.c for OS/2
- don't even use signed char in inflate (not portable enough)
- fix inflate memory leak for segmented architectures

Changes in 0.92 (3 May 95)
- don't assume that char is signed (problem on SGI)
- Clear bit buffer when starting a stored block
- no memcpy on Pyramid
- suppressed inftest.c
- optimized fill_window, put longest_match inline for gcc
- optimized inflate on stored blocks.
- optimized inflate on stored blocks
- untabify all sources to simplify patches

Changes in 0.91 (2 May 95)
- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h
- Document the memory requirements in zconf.h
- added "make install"
- fix sync search logic in inflateSync
- deflate(Z_FULL_FLUSH) now works even if output buffer too short
- after inflateSync, don't scare people with just "lo world"
- added support for DJGPP

Changes in 0.9 (1 May 95)
- don't assume that zalloc clears the allocated memory (the TurboC bug
  was Mark's bug after all :)
- let again gzread copy uncompressed data unchanged (was working in 0.71)
- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented
- added a test of inflateSync in example.c
- moved MAX_WBITS to zconf.h because users might want to change that.
- moved MAX_WBITS to zconf.h because users might want to change that
- document explicitly that zalloc(64K) on MSDOS must return a normalized
  pointer (zero offset)
- added Makefiles for Microsoft C, Turbo C, Borland C++
- faster crc32()

Changes in 0.8 (29 April 95)
- added fast inflate (inffast.c)
- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this
  is incompatible with previous versions of zlib which returned Z_OK.
  is incompatible with previous versions of zlib which returned Z_OK
- work around a TurboC compiler bug (bad code for b << 0, see infutil.h)
  (actually that was not a compiler bug, see 0.81 above)
- gzread no longer reads one extra byte in certain cases
- In gzio destroy(), don't reference a freed structure
- avoid many warnings for MSDOS
- avoid the ERROR symbol which is used by MS Windows

Changes in 0.71 (14 April 95)
- Fixed more MSDOS compilation problems :( There is still a bug with
  TurboC large model.
  TurboC large model

Changes in 0.7 (14 April 95)
- Added full inflate support.
- Added full inflate support
- Simplified the crc32() interface. The pre- and post-conditioning
  (one's complement) is now done inside crc32(). WARNING: this is
  incompatible with previous versions; see zlib.h for the new usage.
  incompatible with previous versions; see zlib.h for the new usage

Changes in 0.61 (12 April 95)
- workaround for a bug in TurboC. example and minigzip now work on MSDOS.
- workaround for a bug in TurboC. example and minigzip now work on MSDOS

Changes in 0.6 (11 April 95)
- added minigzip.c
- added gzdopen to reopen a file descriptor as gzFile
- added transparent reading of non-gziped files in gzread.
- added transparent reading of non-gziped files in gzread
- fixed bug in gzread (don't read crc as data)
- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose).
- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose)
- don't allocate big arrays in the stack (for MSDOS)
- fix some MSDOS compilation problems

Changes in 0.5:
- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but
  not yet Z_FULL_FLUSH.
  not yet Z_FULL_FLUSH
- support decompression but only in a single step (forced Z_FINISH)
- added opaque object for zalloc and zfree.
- added opaque object for zalloc and zfree
- added deflateReset and inflateReset
- added a variable zlib_version for consistency checking.
- renamed the 'filter' parameter of deflateInit2 as 'strategy'.
  Added Z_FILTERED and Z_HUFFMAN_ONLY constants.
- added a variable zlib_version for consistency checking
- renamed the 'filter' parameter of deflateInit2 as 'strategy'
  Added Z_FILTERED and Z_HUFFMAN_ONLY constants

Changes in 0.4:
- avoid "zip" everywhere, use zlib instead of ziplib.
- avoid "zip" everywhere, use zlib instead of ziplib
- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush
  if compression method == 8.
  if compression method == 8
- added adler32 and crc32
- renamed deflateOptions as deflateInit2, call one or the other but not both
- added the method parameter for deflateInit2.
- added the method parameter for deflateInit2
- added inflateInit2
- simplied considerably deflateInit and inflateInit by not supporting
- simplified considerably deflateInit and inflateInit by not supporting
  user-provided history buffer. This is supported only in deflateInit2
  and inflateInit2.
  and inflateInit2

Changes in 0.3:
- prefix all macro names with Z_
- use Z_FINISH instead of deflateEnd to finish compression.
- use Z_FINISH instead of deflateEnd to finish compression
- added Z_HUFFMAN_ONLY
- added gzerror()

Changes to compat/zlib/FAQ.

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
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16

17

18
19
20
21
22
23
24






-
+









-
+
-








                Frequently Asked Questions about zlib


If your question is not there, please check the zlib home page
http://zlib.net/ which may have more recent information.
The lastest zlib FAQ is at http://zlib.net/zlib_faq.html
The latest zlib FAQ is at http://zlib.net/zlib_faq.html


 1. Is zlib Y2K-compliant?

    Yes. zlib doesn't handle dates.

 2. Where can I get a Windows DLL version?

    The zlib sources can be compiled without change to produce a DLL.  See the
    file win32/DLL_FAQ.txt in the zlib distribution.  Pointers to the
    file win32/DLL_FAQ.txt in the zlib distribution.
    precompiled DLL are found in the zlib web site at http://zlib.net/ .

 3. Where can I get a Visual Basic interface to zlib?

    See
        * http://marknelson.us/1997/01/01/zlib-engine/
        * win32/DLL_FAQ.txt in the zlib distribution

Added compat/zlib/LICENSE.























1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Copyright notice:

 (C) 1995-2022 Jean-loup Gailly and Mark Adler

  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
     appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.

  Jean-loup Gailly        Mark Adler
  jloup@gzip.org          madler@alumni.caltech.edu

Changes to compat/zlib/Makefile.in.

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

30
31
32
33
34
35

36
37
38
39
40
41
42
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
30

31
32
33
34
35
36
37
38

-
+







-
-
-
-















-
+





-
+







# Makefile for zlib
# Copyright (C) 1995-2017 Jean-loup Gailly, Mark Adler
# Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
# For conditions of distribution and use, see copyright notice in zlib.h

# To compile and test, type:
#    ./configure; make test
# Normally configure builds both a static and a shared library.
# If you want to build just a static library, use: ./configure --static

# To use the asm code, type:
#    cp contrib/asm?86/match.S ./match.S
#    make LOC=-DASMV OBJA=match.o

# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
#    make install
# To install in $HOME instead of /usr/local, use:
#    make install prefix=$HOME

CC=cc

CFLAGS=-O
#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
#CFLAGS=-g -DZLIB_DEBUG
#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
#           -Wstrict-prototypes -Wmissing-prototypes

SFLAGS=-O
LDFLAGS=
TEST_LDFLAGS=-L. libz.a
TEST_LIBS=-L. libz.a
LDSHARED=$(CC)
CPP=$(CC) -E

STATICLIB=libz.a
SHAREDLIB=libz.so
SHAREDLIBV=libz.so.1.2.11
SHAREDLIBV=libz.so.1.3.1
SHAREDLIBM=libz.so.1
LIBS=$(STATICLIB) $(SHAREDLIBV)

AR=ar
ARFLAGS=rc
RANLIB=ranlib
LDCONFIG=ldconfig
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
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







-
+



-
-
+
+







-
+



-
-
+
+



-
+



-
-
+
+









-
+








check: test

test: all teststatic testshared

teststatic: static
	@TMPST=tmpst_$$; \
	if echo hello world | ./minigzip | ./minigzip -d && ./example $$TMPST ; then \
	if echo hello world | ${QEMU_RUN} ./minigzip | ${QEMU_RUN} ./minigzip -d && ${QEMU_RUN} ./example $$TMPST ; then \
	  echo '		*** zlib test OK ***'; \
	else \
	  echo '		*** zlib test FAILED ***'; false; \
	fi; \
	rm -f $$TMPST
	fi
	@rm -f tmpst_$$

testshared: shared
	@LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
	LD_LIBRARYN32_PATH=`pwd`:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \
	DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \
	SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \
	TMPSH=tmpsh_$$; \
	if echo hello world | ./minigzipsh | ./minigzipsh -d && ./examplesh $$TMPSH; then \
	if echo hello world | ${QEMU_RUN} ./minigzipsh | ${QEMU_RUN} ./minigzipsh -d && ${QEMU_RUN} ./examplesh $$TMPSH; then \
	  echo '		*** zlib shared test OK ***'; \
	else \
	  echo '		*** zlib shared test FAILED ***'; false; \
	fi; \
	rm -f $$TMPSH
	fi
	@rm -f tmpsh_$$

test64: all64
	@TMP64=tmp64_$$; \
	if echo hello world | ./minigzip64 | ./minigzip64 -d && ./example64 $$TMP64; then \
	if echo hello world | ${QEMU_RUN} ./minigzip64 | ${QEMU_RUN} ./minigzip64 -d && ${QEMU_RUN} ./example64 $$TMP64; then \
	  echo '		*** zlib 64-bit test OK ***'; \
	else \
	  echo '		*** zlib 64-bit test FAILED ***'; false; \
	fi; \
	rm -f $$TMP64
	fi
	@rm -f tmp64_$$

infcover.o: $(SRCDIR)test/infcover.c $(SRCDIR)zlib.h zconf.h
	$(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/infcover.c

infcover: infcover.o libz.a
	$(CC) $(CFLAGS) -o $@ infcover.o libz.a

cover: infcover
	rm -f *.gcda
	./infcover
	${QEMU_RUN} ./infcover
	gcov inf*.c

libz.a: $(OBJS)
	$(AR) $(ARFLAGS) $@ $(OBJS)
	-@ ($(RANLIB) $@ || true) >/dev/null 2>&1

match.o: match.S
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
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







-
+


-
+


-
+


-
+


-
+


-
+







	$(LDSHARED) $(SFLAGS) -o $@ $(PIC_OBJS) $(LDSHAREDLIBC) $(LDFLAGS)
	rm -f $(SHAREDLIB) $(SHAREDLIBM)
	ln -s $@ $(SHAREDLIB)
	ln -s $@ $(SHAREDLIBM)
	-@rmdir objs

example$(EXE): example.o $(STATICLIB)
	$(CC) $(CFLAGS) -o $@ example.o $(TEST_LDFLAGS)
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(TEST_LIBS)

minigzip$(EXE): minigzip.o $(STATICLIB)
	$(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS)
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(TEST_LIBS)

examplesh$(EXE): example.o $(SHAREDLIBV)
	$(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIBV)
	$(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) -L. $(SHAREDLIBV)

minigzipsh$(EXE): minigzip.o $(SHAREDLIBV)
	$(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIBV)
	$(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) -L. $(SHAREDLIBV)

example64$(EXE): example64.o $(STATICLIB)
	$(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS)
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ example64.o $(TEST_LIBS)

minigzip64$(EXE): minigzip64.o $(STATICLIB)
	$(CC) $(CFLAGS) -o $@ minigzip64.o $(TEST_LDFLAGS)
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip64.o $(TEST_LIBS)

install-libs: $(LIBS)
	-@if [ ! -d $(DESTDIR)$(exec_prefix)  ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi
	-@if [ ! -d $(DESTDIR)$(libdir)       ]; then mkdir -p $(DESTDIR)$(libdir); fi
	-@if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi
	-@if [ ! -d $(DESTDIR)$(man3dir)      ]; then mkdir -p $(DESTDIR)$(man3dir); fi
	-@if [ ! -d $(DESTDIR)$(pkgconfigdir) ]; then mkdir -p $(DESTDIR)$(pkgconfigdir); fi
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
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







+
+
+
+
+
+

-
+











-
+






-
-







	sed -f $$TEMPFILE $(SRCDIR)zconf.h.in > $@ &&\
	touch -r $(SRCDIR)zconf.h.in $@ &&\
	rm $$TEMPFILE

zconf: $(SRCDIR)zconf.h.in
	cp -p $(SRCDIR)zconf.h.in zconf.h

minizip-test: static
	cd contrib/minizip && { CC="$(CC)" CFLAGS="$(CFLAGS)" $(MAKE) test ; cd ../.. ; }

minizip-clean:
	cd contrib/minizip && { $(MAKE) clean ; cd ../.. ; }

mostlyclean: clean
clean:
clean: minizip-clean
	rm -f *.o *.lo *~ \
	   example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \
	   example64$(EXE) minigzip64$(EXE) \
	   infcover \
	   libz.* foo.gz so_locations \
	   _match.s maketree contrib/infback9/*.o
	rm -rf objs
	rm -f *.gcda *.gcno *.gcov
	rm -f contrib/infback9/*.gcda contrib/infback9/*.gcno contrib/infback9/*.gcov

maintainer-clean: distclean
distclean: clean zconf zconf.h.cmakein docs
distclean: clean zconf zconf.h.cmakein
	rm -f Makefile zlib.pc configure.log
	-@rm -f .DS_Store
	@if [ -f Makefile.in ]; then \
	printf 'all:\n\t-@echo "Please use ./configure first.  Thank you."\n' > Makefile ; \
	printf '\ndistclean:\n\tmake -f Makefile.in distclean\n' >> Makefile ; \
	touch -r $(SRCDIR)Makefile.in Makefile ; fi
	@if [ ! -f zconf.h.in ]; then rm -f zconf.h zconf.h.cmakein ; fi
	@if [ ! -f zlib.3 ]; then rm -f zlib.3.pdf ; fi

tags:
	etags $(SRCDIR)*.[ch]

adler32.o zutil.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h
gzclose.o gzlib.o gzread.o gzwrite.o: $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h
compress.o example.o minigzip.o uncompr.o: $(SRCDIR)zlib.h zconf.h

Changes to compat/zlib/README.

1
2
3

4
5
6
7
8
9
10
1
2

3
4
5
6
7
8
9
10


-
+







ZLIB DATA COMPRESSION LIBRARY

zlib 1.2.11 is a general purpose data compression library.  All the code is
zlib 1.3.1 is a general purpose data compression library.  All the code is
thread safe.  The data format used by the zlib library is described by RFCs
(Request for Comments) 1950 to 1952 in the files
http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
rfc1952 (gzip format).

All functions of the compression library are documented in the file zlib.h
(volunteer to write man pages welcome, contact zlib@gzip.org).  A usage example
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
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







-
+

-
+



-
-
+
+

-
+
-
-
+







verify that you have the latest version of zlib; otherwise get the latest
version and check whether the problem still exists or not.

PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help.

Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan.  1997
issue of Dr.  Dobb's Journal; a copy of the article is available at
http://marknelson.us/1997/01/01/zlib-engine/ .
https://marknelson.us/posts/1997/01/01/zlib-engine.html .

The changes made in version 1.2.11 are documented in the file ChangeLog.
The changes made in version 1.3.1 are documented in the file ChangeLog.

Unsupported third party contributions are provided in directory contrib/ .

zlib is available in Java using the java.util.zip package, documented at
http://java.sun.com/developer/technicalArticles/Programming/compression/ .
zlib is available in Java using the java.util.zip package. Follow the API
Documentation link at: https://docs.oracle.com/search/?q=java.util.zip .

A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is available
A Perl interface to zlib and bzip2 written by Paul Marquess <pmqs@cpan.org>
at CPAN (Comprehensive Perl Archive Network) sites, including
http://search.cpan.org/~pmqs/IO-Compress-Zlib/ .
can be found at https://github.com/pmqs/IO-Compress .

A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is
available in Python 1.5 and later versions, see
http://docs.python.org/library/zlib.html .

zlib is built into tcl: http://wiki.tcl.tk/4610 .

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
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







-
+



















-
+







- For 64-bit Irix, deflate.c must be compiled without any optimization. With
  -O, one libpng test fails. The test works in 32 bit mode (with the -n32
  compiler flag). The compiler bug has been reported to SGI.

- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
  when compiled with cc.

- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is
- On Digital Unix 4.0D (formerly OSF/1) on AlphaServer, the cc option -std1 is
  necessary to get gzprintf working correctly. This is done by configure.

- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
  other compilers. Use "make test" to check your compiler.

- gzdopen is not supported on RISCOS or BEOS.

- For PalmOs, see http://palmzlib.sourceforge.net/


Acknowledgments:

  The deflate format used by zlib was defined by Phil Katz.  The deflate and
  zlib specifications were written by L.  Peter Deutsch.  Thanks to all the
  people who reported problems and suggested various improvements in zlib; they
  are too numerous to cite here.

Copyright notice:

 (C) 1995-2017 Jean-loup Gailly and Mark Adler
 (C) 1995-2024 Jean-loup Gailly and Mark Adler

  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
104
105
106
107
108
109
110
111




112
113
114
115
103
104
105
106
107
108
109

110
111
112
113
114
115
116
117







-
+
+
+
+





  Jean-loup Gailly        Mark Adler
  jloup@gzip.org          madler@alumni.caltech.edu

If you use the zlib library in a product, we would appreciate *not* receiving
lengthy legal documents to sign.  The sources are provided for free but without
warranty of any kind.  The library has been entirely written by Jean-loup
Gailly and Mark Adler; it does not include third-party code.
Gailly and Mark Adler; it does not include third-party code.  We make all
contributions to and distributions of this project solely in our personal
capacity, and are not conveying any rights to any intellectual property of
any third parties.

If you redistribute modified sources, we would appreciate that you include in
the file ChangeLog history information documenting your changes.  Please read
the FAQ for more information on the distribution of modified source versions.

Changes to compat/zlib/adler32.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16









-
-







/* adler32.c -- compute the Adler-32 checksum of a data stream
 * Copyright (C) 1995-2011, 2016 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/* @(#) $Id$ */

#include "zutil.h"

local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));

#define BASE 65521U     /* largest prime smaller than 65536 */
#define NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */

#define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71
72
73
74
54
55
56
57
58
59
60

61




62
63
64
65
66
67
68







-
+
-
-
-
-







#else
#  define MOD(a) a %= BASE
#  define MOD28(a) a %= BASE
#  define MOD63(a) a %= BASE
#endif

/* ========================================================================= */
uLong ZEXPORT adler32_z(adler, buf, len)
uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len) {
    uLong adler;
    const Bytef *buf;
    z_size_t len;
{
    unsigned long sum2;
    unsigned n;

    /* split Adler-32 into component sums */
    sum2 = (adler >> 16) & 0xffff;
    adler &= 0xffff;

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
121
122
123
124
125
126
127

128




129
130
131
132

133




134
135
136
137
138
139
140







-
+
-
-
-
-




-
+
-
-
-
-







    }

    /* return recombined sums */
    return adler | (sum2 << 16);
}

/* ========================================================================= */
uLong ZEXPORT adler32(adler, buf, len)
uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) {
    uLong adler;
    const Bytef *buf;
    uInt len;
{
    return adler32_z(adler, buf, len);
}

/* ========================================================================= */
local uLong adler32_combine_(adler1, adler2, len2)
local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) {
    uLong adler1;
    uLong adler2;
    z_off64_t len2;
{
    unsigned long sum1;
    unsigned long sum2;
    unsigned rem;

    /* for negative len, return invalid adler32 as a clue for debugging */
    if (len2 < 0)
        return 0xffffffffUL;
165
166
167
168
169
170
171
172

173
174
175
176
177
178
179
180

181
182
183
184
185
186
151
152
153
154
155
156
157

158




159
160
161

162




163
164







-
+
-
-
-
-



-
+
-
-
-
-


    if (sum1 >= BASE) sum1 -= BASE;
    if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1);
    if (sum2 >= BASE) sum2 -= BASE;
    return sum1 | (sum2 << 16);
}

/* ========================================================================= */
uLong ZEXPORT adler32_combine(adler1, adler2, len2)
uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) {
    uLong adler1;
    uLong adler2;
    z_off_t len2;
{
    return adler32_combine_(adler1, adler2, len2);
}

uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) {
    uLong adler1;
    uLong adler2;
    z_off64_t len2;
{
    return adler32_combine_(adler1, adler2, len2);
}

Changes to compat/zlib/compress.c.

15
16
17
18
19
20
21
22
23
24
25
26


27
28
29
30
31
32
33
34
35
15
16
17
18
19
20
21





22
23


24
25
26
27
28
29
30







-
-
-
-
-
+
+
-
-







   destination buffer, which must be at least 0.1% larger than sourceLen plus
   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.

     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
   Z_STREAM_ERROR if the level parameter is invalid.
*/
int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
    Bytef *dest;
    uLongf *destLen;
    const Bytef *source;
    uLong sourceLen;
int ZEXPORT compress2(Bytef *dest, uLongf *destLen, const Bytef *source,
                      uLong sourceLen, int level) {
    int level;
{
    z_stream stream;
    int err;
    const uInt max = (uInt)-1;
    uLong left;

    left = *destLen;
    *destLen = 0;
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
56
57
58
59
60
61
62





63
64

65
66
67
68
69
70
71

72


73
74
75







-
-
-
-
-
+
+
-







-
+
-
-



    *destLen = stream.total_out;
    deflateEnd(&stream);
    return err == Z_STREAM_END ? Z_OK : err;
}

/* ===========================================================================
 */
int ZEXPORT compress (dest, destLen, source, sourceLen)
    Bytef *dest;
    uLongf *destLen;
    const Bytef *source;
    uLong sourceLen;
int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source,
                     uLong sourceLen) {
{
    return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
}

/* ===========================================================================
     If the default memLevel or windowBits for deflateInit() is changed, then
   this function needs to be updated.
 */
uLong ZEXPORT compressBound (sourceLen)
uLong ZEXPORT compressBound(uLong sourceLen) {
    uLong sourceLen;
{
    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
           (sourceLen >> 25) + 13;
}

Changes to compat/zlib/configure.

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
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







-
+






-
+
+

+
+







-
+
-
-
+







# get source directory
SRCDIR=`dirname $0`
if test $SRCDIR = "."; then
    ZINC=""
    ZINCOUT="-I."
    SRCDIR=""
else
    ZINC='-include zconf.h'
    ZINC='-I. -include zconf.h'
    ZINCOUT='-I. -I$(SRCDIR)'
    SRCDIR="$SRCDIR/"
fi

# set command prefix for cross-compilation
if [ -n "${CHOST}" ]; then
    uname="`echo "${CHOST}" | sed -e 's/^[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)-.*$/\1/'`"
    uname=${CHOST}
    mname=${CHOST}
    CROSS_PREFIX="${CHOST}-"
else
    mname=`(uname -a || echo unknown) 2>/dev/null`
fi

# destination name for static library
STATICLIB=libz.a

# extract zlib version numbers from zlib.h
VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}zlib.h`
VER3=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\\.[0-9]*\).*/\1/p' < ${SRCDIR}zlib.h`
VER3=`echo ${VER}|sed -n -e 's/\([0-9]\{1,\}\(\\.[0-9]\{1,\}\)\{1,2\}\).*/\1/p'`
VER2=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < ${SRCDIR}zlib.h`
VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < ${SRCDIR}zlib.h`
VER1=`echo ${VER}|sed -n -e 's/\([0-9]\{1,\}\)\\..*/\1/p'`

# establish commands for library building
if "${CROSS_PREFIX}ar" --version >/dev/null 2>/dev/null || test $? -lt 126; then
    AR=${AR-"${CROSS_PREFIX}ar"}
    test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log
else
    AR=${AR-"ar"}
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
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







+
+











-
+







cover=0
zprefix=0
zconst=0
build64=0
gcc=0
warn=0
debug=0
address=0
memory=0
old_cc="$CC"
old_cflags="$CFLAGS"
OBJC='$(OBJZ) $(OBJG)'
PIC_OBJC='$(PIC_OBJZ) $(PIC_OBJG)'

# leave this script, optionally in a bad way
leave()
{
  if test "$*" != "0"; then
    echo "** $0 aborting." | tee -a configure.log
  fi
  rm -f $test.[co] $test $test$shared_ext $test.gcno ./--version
  rm -rf $test.[co] $test $test$shared_ext $test.gcno $test.dSYM ./--version
  echo -------------------- >> configure.log
  echo >> configure.log
  echo >> configure.log
  exit $1
}

# process command line options
133
134
135
136
137
138
139



140
141
142
143
144
145
146
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153







+
+
+







    -6* | --64) build64=1; shift ;;
    -a*=* | --archs=*) ARCHS=`echo $1 | sed 's/.*=//'`; shift ;;
    --sysconfdir=*) echo "ignored option: --sysconfdir" | tee -a configure.log; shift ;;
    --localstatedir=*) echo "ignored option: --localstatedir" | tee -a configure.log; shift ;;
    -c* | --const) zconst=1; shift ;;
    -w* | --warn) warn=1; shift ;;
    -d* | --debug) debug=1; shift ;;
    --sanitize) address=1; shift ;;
    --address) address=1; shift ;;
    --memory) memory=1; shift ;;
    *)
      echo "unknown option: $1" | tee -a configure.log
      echo "$0 --help for help" | tee -a configure.log
      leave 1;;
    esac
done

161
162
163
164
165
166
167

168
169
170
171










172
173
174
175
176
177
178
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







+
-
-
-
-
+
+
+
+
+
+
+
+
+
+








# check for gcc vs. cc and set compile and link flags based on the system identified by uname
cat > $test.c <<EOF
extern int getchar();
int hello() {return getchar();}
EOF

if test -z "$CC"; then
test -z "$CC" && echo Checking for ${CROSS_PREFIX}gcc... | tee -a configure.log
cc=${CC-${CROSS_PREFIX}gcc}
cflags=${CFLAGS-"-O3"}
# to force the asm version use: CFLAGS="-O3 -DASMV" ./configure
  echo Checking for ${CROSS_PREFIX}gcc... | tee -a configure.log
  if ${CROSS_PREFIX}gcc -v >/dev/null 2>&1; then
    cc=${CROSS_PREFIX}gcc
  else
    cc=${CROSS_PREFIX}cc
  fi
else
  cc=${CC}
fi

case "$cc" in
  *gcc*) gcc=1 ;;
  *clang*) gcc=1 ;;
esac
case `$cc -v 2>&1` in
  *gcc*) gcc=1 ;;
  *clang*) gcc=1 ;;
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
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







-
+

-
+


+
+
+
+
+
+








-
+
+
+
+
+




-
+

-
+
-

-
+
-



-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  fi
  if test $build64 -eq 1; then
    CFLAGS="${CFLAGS} -m64"
    SFLAGS="${SFLAGS} -m64"
  fi
  if test "$warn" -eq 1; then
    if test "$zconst" -eq 1; then
      CFLAGS="${CFLAGS} -Wall -Wextra -Wcast-qual -pedantic -DZLIB_CONST"
      CFLAGS="${CFLAGS} -Wall -Wextra -Wcast-qual -DZLIB_CONST"
    else
      CFLAGS="${CFLAGS} -Wall -Wextra -pedantic"
      CFLAGS="${CFLAGS} -Wall -Wextra"
    fi
  fi
  if test $address -eq 1; then
    CFLAGS="${CFLAGS} -g -fsanitize=address -fno-omit-frame-pointer"
  fi
  if test $memory -eq 1; then
    CFLAGS="${CFLAGS} -g -fsanitize=memory -fno-omit-frame-pointer"
  fi
  if test $debug -eq 1; then
    CFLAGS="${CFLAGS} -DZLIB_DEBUG"
    SFLAGS="${SFLAGS} -DZLIB_DEBUG"
  fi
  if test -z "$uname"; then
    uname=`(uname -s || echo unknown) 2>/dev/null`
  fi
  case "$uname" in
  Linux* | linux* | GNU | GNU/* | solaris*)
  Linux* | linux* | *-linux* | GNU | GNU/* | solaris*)
        case "$mname" in
        *sparc*)
            LDFLAGS="${LDFLAGS} -Wl,--no-warn-rwx-segments" ;;
        esac
        LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}zlib.map"} ;;
  *BSD | *bsd* | DragonFly)
        LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}zlib.map"}
        LDCONFIG="ldconfig -m" ;;
  CYGWIN* | Cygwin* | cygwin* | OS/2*)
  CYGWIN* | Cygwin* | cygwin* | *-cygwin* | OS/2*)
        EXE='.exe' ;;
  MINGW* | mingw*)
  MINGW* | mingw* | *-mingw*)
# temporary bypass
        rm -f $test.[co] $test $test$shared_ext
        echo "Please use win32/Makefile.gcc instead." | tee -a configure.log
        echo "If this doesn't work for you, try win32/Makefile.gcc." | tee -a configure.log
        leave 1
        LDSHARED=${LDSHARED-"$cc -shared"}
        LDSHAREDLIBC=""
        EXE='.exe' ;;
  QNX*)  # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4
         # (alain.bonnefoy@icbt.com)
                 LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"} ;;
  QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4
        # (alain.bonnefoy@icbt.com)
        LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"} ;;
  HP-UX*)
         LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"}
         case `(uname -m || echo unknown) 2>/dev/null` in
         ia64)
                 shared_ext='.so'
                 SHAREDLIB='libz.so' ;;
         *)
                 shared_ext='.sl'
                 SHAREDLIB='libz.sl' ;;
         esac ;;
  Darwin* | darwin*)
             shared_ext='.dylib'
             SHAREDLIB=libz$shared_ext
             SHAREDLIBV=libz.$VER$shared_ext
             SHAREDLIBM=libz.$VER1$shared_ext
             LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"}
             if libtool -V 2>&1 | grep Apple > /dev/null; then
                 AR="libtool"
             else
                 AR="/usr/bin/libtool"
             fi
             ARFLAGS="-o" ;;
  *)             LDSHARED=${LDSHARED-"$cc -shared"} ;;
        LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"}
        case `(uname -m || echo unknown) 2>/dev/null` in
        ia64)
            shared_ext='.so'
            SHAREDLIB='libz.so' ;;
        *)
            shared_ext='.sl'
            SHAREDLIB='libz.sl' ;;
        esac ;;
  AIX*)
        LDFLAGS="${LDFLAGS} -Wl,-brtl" ;;
  Darwin* | darwin* | *-darwin*)
        shared_ext='.dylib'
        SHAREDLIB=libz$shared_ext
        SHAREDLIBV=libz.$VER$shared_ext
        SHAREDLIBM=libz.$VER1$shared_ext
        LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"}
        if "${CROSS_PREFIX}libtool" -V 2>&1 | grep Apple > /dev/null; then
            AR="${CROSS_PREFIX}libtool"
        elif libtool -V 2>&1 | grep Apple > /dev/null; then
            AR="libtool"
        else
            AR="/usr/bin/libtool"
        fi
        ARFLAGS="-o" ;;
  *)
        LDSHARED=${LDSHARED-"$cc -shared"} ;;
  esac
else
  # find system name and corresponding cc options
  CC=${CC-cc}
  gcc=0
  echo ... using $CC >> configure.log
  if test -z "$uname"; then
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
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







-
+

+
+
+












+
-
+
+

+







    test "`( $* ) 2>&1 | tee -a configure.log`" = ""
  }
  echo - using any output from compiler to indicate an error >> configure.log
else
  try()
  {
    show $*
    ( $* ) >> configure.log 2>&1
    got=`( $* ) 2>&1`
    ret=$?
    if test "$got" != ""; then
      printf "%s\n" "$got" >> configure.log
    fi
    if test $ret -ne 0; then
      echo "(exit code "$ret")" >> configure.log
    fi
    return $ret
  }
fi

tryboth()
{
  show $*
  got=`( $* ) 2>&1`
  ret=$?
  if test "$got" != ""; then
  printf %s "$got" >> configure.log
    printf "%s\n" "$got" >> configure.log
  fi
  if test $ret -ne 0; then
    echo "(exit code "$ret")" >> configure.log
    return $ret
  fi
  test "$got" = ""
}

cat > $test.c << EOF
int foo() { return 0; }
405
406
407
408
409
410
411
412

413
414
415
416
417
418
419
438
439
440
441
442
443
444

445
446
447
448
449
450
451
452







-
+







cat > $test.c <<EOF
extern int getchar();
int hello() {return getchar();}
EOF
if test $shared -eq 1; then
  echo Checking for shared library support... | tee -a configure.log
  # we must test in two steps (cc then ld), required at least on SunOS 4.x
  if try $CC -w -c $SFLAGS $test.c &&
  if try $CC -c $SFLAGS $test.c &&
     try $LDSHARED $SFLAGS -o $test$shared_ext $test.o; then
    echo Building shared library $SHAREDLIBV with $CC. | tee -a configure.log
  elif test -z "$old_cc" -a -z "$old_cflags"; then
    echo No shared library support. | tee -a configure.log
    shared=0;
  else
    echo 'No shared library support; try without defining CC and CFLAGS' | tee -a configure.log
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
467

468
469
470

471
472
473
474
475
476
477
462
463
464
465
466
467
468














469
470
471
472
473
474
475
476
477
478

479
480



481


482



483
484
485
486
487
488
489
490







-
-
-
-
-
-
-
-
-
-
-
-
-
-










-


-
-
-
+
-
-
+
-
-
-
+







  SHAREDLIBM=""
  echo Building static library $STATICLIB version $VER with $CC. | tee -a configure.log
else
  ALL="static shared"
  TEST="all teststatic testshared"
fi

# check for underscores in external names for use by assembler code
CPP=${CPP-"$CC -E"}
case $CFLAGS in
  *ASMV*)
    echo >> configure.log
    show "$NM $test.o | grep _hello"
    if test "`$NM $test.o | grep _hello | tee -a configure.log`" = ""; then
      CPP="$CPP -DNO_UNDERLINE"
      echo Checking for underline in external names... No. | tee -a configure.log
    else
      echo Checking for underline in external names... Yes. | tee -a configure.log
    fi ;;
esac

echo >> configure.log

# check for size_t
cat > $test.c <<EOF
#include <stdio.h>
#include <stdlib.h>
size_t dummy = 0;
EOF
if try $CC -c $CFLAGS $test.c; then
  echo "Checking for size_t... Yes." | tee -a configure.log
  need_sizet=0
else
  echo "Checking for size_t... No." | tee -a configure.log
  need_sizet=1
fi

  # find a size_t integer type
echo >> configure.log

  # check for long long
# find the size_t integer type, if needed
if test $need_sizet -eq 1; then
  cat > $test.c <<EOF
  cat > $test.c << EOF
long long dummy = 0;
EOF
  if try $CC -c $CFLAGS $test.c; then
    echo "Checking for long long... Yes." | tee -a configure.log
    cat > $test.c <<EOF
#include <stdio.h>
int main(void) {
491
492
493
494
495
496
497


498
499

500
501
502
503
504
505
506
507
508
509
510
511
512
513
504
505
506
507
508
509
510
511
512
513

514

515





516
517
518
519
520
521
522







+
+

-
+
-

-
-
-
-
-







    return 0;
}
EOF
  fi
  if try $CC $CFLAGS -o $test $test.c; then
    sizet=`./$test`
    echo "Checking for a pointer-size integer type..." $sizet"." | tee -a configure.log
    CFLAGS="${CFLAGS} -DNO_SIZE_T=${sizet}"
    SFLAGS="${SFLAGS} -DNO_SIZE_T=${sizet}"
  else
    echo "Failed to find a pointer-size integer type." | tee -a configure.log
    echo "Checking for a pointer-size integer type... not found." | tee -a configure.log
    leave 1
  fi
fi

if test $need_sizet -eq 1; then
  CFLAGS="${CFLAGS} -DNO_SIZE_T=${sizet}"
  SFLAGS="${SFLAGS} -DNO_SIZE_T=${sizet}"
fi

echo >> configure.log

# check for large file support, and if none, check for fseeko()
cat > $test.c <<EOF
#include <sys/types.h>
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862

863
864
865
866
867
868
869
854
855
856
857
858
859
860

861
862
863
864
865
866
867
868
869

870
871
872
873
874
875
876
877







-









-
+







echo SFLAGS = $SFLAGS >> configure.log
echo SHAREDLIB = $SHAREDLIB >> configure.log
echo SHAREDLIBM = $SHAREDLIBM >> configure.log
echo SHAREDLIBV = $SHAREDLIBV >> configure.log
echo STATICLIB = $STATICLIB >> configure.log
echo TEST = $TEST >> configure.log
echo VER = $VER >> configure.log
echo Z_U4 = $Z_U4 >> configure.log
echo SRCDIR = $SRCDIR >> configure.log
echo exec_prefix = $exec_prefix >> configure.log
echo includedir = $includedir >> configure.log
echo libdir = $libdir >> configure.log
echo mandir = $mandir >> configure.log
echo prefix = $prefix >> configure.log
echo sharedlibdir = $sharedlibdir >> configure.log
echo uname = $uname >> configure.log

# udpate Makefile with the configure results
# update Makefile with the configure results
sed < ${SRCDIR}Makefile.in "
/^CC *=/s#=.*#=$CC#
/^CFLAGS *=/s#=.*#=$CFLAGS#
/^SFLAGS *=/s#=.*#=$SFLAGS#
/^LDFLAGS *=/s#=.*#=$LDFLAGS#
/^LDSHARED *=/s#=.*#=$LDSHARED#
/^CPP *=/s#=.*#=$CPP#

Changes to compat/zlib/contrib/README.contrib.

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
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

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
30
31
32
33
34
35
36










37
38
39
40
41
42
43
-
+









-
-
-
-
-
-
-
-
















-
-
-










-
-
-
-
-
-
-
-
-
-







All files under this contrib directory are UNSUPPORTED. There were
All files under this contrib directory are UNSUPPORTED. They were
provided by users of zlib and were not tested by the authors of zlib.
Use at your own risk. Please contact the authors of the contributions
for help about these, not the zlib authors. Thanks.


ada/        by Dmitriy Anisimkov <anisimkov@yahoo.com>
        Support for Ada
        See http://zlib-ada.sourceforge.net/

amd64/      by Mikhail Teterin <mi@ALDAN.algebra.com>
        asm code for AMD64
        See patch at http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/96393

asm686/     by Brian Raiter <breadbox@muppetlabs.com>
        asm code for Pentium and PPro/PII, using the AT&T (GNU as) syntax
        See http://www.muppetlabs.com/~breadbox/software/assembly.html

blast/      by Mark Adler <madler@alumni.caltech.edu>
        Decompressor for output of PKWare Data Compression Library (DCL)

delphi/     by Cosmin Truta <cosmint@cs.ubbcluj.ro>
        Support for Delphi and C++ Builder

dotzlib/    by Henrik Ravn <henrik@ravn.com>
        Support for Microsoft .Net and Visual C++ .Net

gcc_gvmat64/by Gilles Vollant <info@winimage.com>
        GCC Version of x86 64-bit (AMD64 and Intel EM64t) code for x64
        assembler to replace longest_match() and inflate_fast()

infback9/   by Mark Adler <madler@alumni.caltech.edu>
        Unsupported diffs to infback to decode the deflate64 format

inflate86/  by Chris Anderson <christop@charm.net>
        Tuned x86 gcc asm code to replace inflate_fast()

iostream/   by Kevin Ruland <kevin@rodin.wustl.edu>
        A C++ I/O streams interface to the zlib gz* functions

iostream2/  by Tyge Løvset <Tyge.Lovset@cmr.no>
        Another C++ I/O streams interface

iostream3/  by Ludwig Schwardt <schwardt@sun.ac.za>
            and Kevin Ruland <kevin@rodin.wustl.edu>
        Yet another C++ I/O streams interface

masmx64/    by Gilles Vollant <info@winimage.com>
        x86 64-bit (AMD64 and Intel EM64t) code for x64 assembler to
        replace longest_match() and inflate_fast(),  also masm x86
        64-bits translation of Chris Anderson inflate_fast()

masmx86/    by Gilles Vollant <info@winimage.com>
        x86 asm code to replace longest_match() and inflate_fast(),
        for Visual C++ and MASM (32 bits).
        Based on Brian Raiter (asm686) and Chris Anderson (inflate86)

minizip/    by Gilles Vollant <info@winimage.com>
        Mini zip and unzip based on zlib
        Includes Zip64 support by Mathias Svensson <mathias@result42.com>
        See http://www.winimage.com/zLibDll/minizip.html

pascal/     by Bob Dellaca <bobdl@xtra.co.nz> et al.
        Support for Pascal

Changes to compat/zlib/contrib/ada/readme.txt.

1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
18
19










-
-
+
+







                        ZLib for Ada thick binding (ZLib.Ada)
                        Release 1.3

ZLib.Ada is a thick binding interface to the popular ZLib data
compression library, available at http://www.gzip.org/zlib/.
It provides Ada-style access to the ZLib C library.


        Here are the main changes since ZLib.Ada 1.2:

- Attension: ZLib.Read generic routine have a initialization requirement
  for Read_Last parameter now. It is a bit incompartible with previous version,
- Attention: ZLib.Read generic routine have a initialization requirement
  for Read_Last parameter now. It is a bit incompatible with previous version,
  but extends functionality, we could use new parameters Allow_Read_Some and
  Flush now.

- Added Is_Open routines to ZLib and ZLib.Streams packages.

- Add pragma Assert to check Stream_Element is 8 bit.

Changes to compat/zlib/contrib/ada/test.adb.

61
62
63
64
65
66
67
68

69
70
71
72
73

74
75
76
77
78
79
80
61
62
63
64
65
66
67

68
69
70
71
72

73
74
75
76
77
78
79
80







-
+




-
+







   File_Z    : ZLib.Streams.Stream_Type;

   Filter : ZLib.Filter_Type;

   Time_Stamp : Ada.Calendar.Time;

   procedure Generate_File;
   --  Generate file of spetsified size with some random data.
   --  Generate file of specified size with some random data.
   --  The random data is repeatable, for the good compression.

   procedure Compare_Streams
     (Left, Right : in out Root_Stream_Type'Class);
   --  The procedure compearing data in 2 streams.
   --  The procedure comparing data in 2 streams.
   --  It is for compare data before and after compression/decompression.

   procedure Compare_Files (Left, Right : String);
   --  Compare files. Based on the Compare_Streams.

   procedure Copy_Streams
     (Source, Target : in out Root_Stream_Type'Class;

Changes to compat/zlib/contrib/ada/zlib-streams.ads.

58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
58
59
60
61
62
63
64

65
66
67
68
69
70
71
72







-
+







      Level             : in     Compression_Level := Default_Compression;
      Strategy          : in     Strategy_Type     := Default_Strategy;
      Header            : in     Header_Type       := Default;
      Read_Buffer_Size  : in     Ada.Streams.Stream_Element_Offset
                                    := Default_Buffer_Size;
      Write_Buffer_Size : in     Ada.Streams.Stream_Element_Offset
                                    := Default_Buffer_Size);
   --  Create the Comression/Decompression stream.
   --  Create the Compression/Decompression stream.
   --  If mode is In_Stream then Write operation is disabled.
   --  If mode is Out_Stream then Read operation is disabled.

   --  If Back_Compressed is true then
   --  Data written to the Stream is compressing to the Back stream
   --  and data read from the Stream is decompressed data from the Back stream.

Changes to compat/zlib/contrib/ada/zlib.adb.

200
201
202
203
204
205
206
207

208
209
210
211
212
213
214
200
201
202
203
204
205
206

207
208
209
210
211
212
213
214







-
+







      Win_Bits : Thin.Int := Thin.Int (Window_Bits);
   begin
      if Is_Open (Filter) then
         raise Status_Error;
      end if;

      --  We allow ZLib to make header only in case of default header type.
      --  Otherwise we would either do header by ourselfs, or do not do
      --  Otherwise we would either do header by ourselves, or do not do
      --  header at all.

      if Header = None or else Header = GZip then
         Win_Bits := -Win_Bits;
      end if;

      --  For the GZip CRC calculation and make headers.

Changes to compat/zlib/contrib/ada/zlib.ads.

110
111
112
113
114
115
116
117

118
119
120
121
122
123
124
110
111
112
113
114
115
116

117
118
119
120
121
122
123
124







-
+







   Finish        : constant Flush_Mode;
   --  Just for tell the compressor that input data is complete.

   ------------------------------------
   -- Compression strategy constants --
   ------------------------------------

   --  RLE stategy could be used only in version 1.2.0 and later.
   --  RLE strategy could be used only in version 1.2.0 and later.

   Filtered         : constant Strategy_Type;
   Huffman_Only     : constant Strategy_Type;
   RLE              : constant Strategy_Type;
   Default_Strategy : constant Strategy_Type;

   Default_Buffer_Size : constant := 4096;

Deleted compat/zlib/contrib/amd64/amd64-match.S.

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
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
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
442
443
444
445
446
447
448
449
450
451
452




































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * match.S -- optimized version of longest_match()
 * based on the similar work by Gilles Vollant, and Brian Raiter, written 1998
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the BSD License. Use by owners of Che Guevarra
 * parafernalia is prohibited, where possible, and highly discouraged
 * elsewhere.
 */

#ifndef NO_UNDERLINE
#	define	match_init	_match_init
#	define	longest_match	_longest_match
#endif

#define	scanend		ebx
#define	scanendw	bx
#define	chainlenwmask	edx /* high word: current chain len low word: s->wmask */
#define	curmatch	rsi
#define	curmatchd	esi
#define	windowbestlen	r8
#define	scanalign	r9
#define	scanalignd	r9d
#define	window		r10
#define	bestlen		r11
#define	bestlend	r11d
#define	scanstart	r12d
#define	scanstartw	r12w
#define scan		r13
#define nicematch	r14d
#define	limit		r15
#define	limitd		r15d
#define prev		rcx

/*
 * The 258 is a "magic number, not a parameter -- changing it
 * breaks the hell loose
 */
#define	MAX_MATCH	(258)
#define	MIN_MATCH	(3)
#define	MIN_LOOKAHEAD	(MAX_MATCH + MIN_MATCH + 1)
#define	MAX_MATCH_8	((MAX_MATCH + 7) & ~7)

/* stack frame offsets */
#define	LocalVarsSize	(112)
#define _chainlenwmask	( 8-LocalVarsSize)(%rsp)
#define _windowbestlen	(16-LocalVarsSize)(%rsp)
#define save_r14        (24-LocalVarsSize)(%rsp)
#define save_rsi        (32-LocalVarsSize)(%rsp)
#define save_rbx        (40-LocalVarsSize)(%rsp)
#define save_r12        (56-LocalVarsSize)(%rsp)
#define save_r13        (64-LocalVarsSize)(%rsp)
#define save_r15        (80-LocalVarsSize)(%rsp)


.globl	match_init, longest_match

/*
 * On AMD64 the first argument of a function (in our case -- the pointer to
 * deflate_state structure) is passed in %rdi, hence our offsets below are
 * all off of that.
 */

/* you can check the structure offset by running

#include <stdlib.h>
#include <stdio.h>
#include "deflate.h"

void print_depl()
{
deflate_state ds;
deflate_state *s=&ds;
printf("size pointer=%u\n",(int)sizeof(void*));

printf("#define dsWSize         (%3u)(%%rdi)\n",(int)(((char*)&(s->w_size))-((char*)s)));
printf("#define dsWMask         (%3u)(%%rdi)\n",(int)(((char*)&(s->w_mask))-((char*)s)));
printf("#define dsWindow        (%3u)(%%rdi)\n",(int)(((char*)&(s->window))-((char*)s)));
printf("#define dsPrev          (%3u)(%%rdi)\n",(int)(((char*)&(s->prev))-((char*)s)));
printf("#define dsMatchLen      (%3u)(%%rdi)\n",(int)(((char*)&(s->match_length))-((char*)s)));
printf("#define dsPrevMatch     (%3u)(%%rdi)\n",(int)(((char*)&(s->prev_match))-((char*)s)));
printf("#define dsStrStart      (%3u)(%%rdi)\n",(int)(((char*)&(s->strstart))-((char*)s)));
printf("#define dsMatchStart    (%3u)(%%rdi)\n",(int)(((char*)&(s->match_start))-((char*)s)));
printf("#define dsLookahead     (%3u)(%%rdi)\n",(int)(((char*)&(s->lookahead))-((char*)s)));
printf("#define dsPrevLen       (%3u)(%%rdi)\n",(int)(((char*)&(s->prev_length))-((char*)s)));
printf("#define dsMaxChainLen   (%3u)(%%rdi)\n",(int)(((char*)&(s->max_chain_length))-((char*)s)));
printf("#define dsGoodMatch     (%3u)(%%rdi)\n",(int)(((char*)&(s->good_match))-((char*)s)));
printf("#define dsNiceMatch     (%3u)(%%rdi)\n",(int)(((char*)&(s->nice_match))-((char*)s)));
}

*/


/*
  to compile for XCode 3.2 on MacOSX x86_64
  - run "gcc -g -c -DXCODE_MAC_X64_STRUCTURE amd64-match.S"
 */


#ifndef CURRENT_LINX_XCODE_MAC_X64_STRUCTURE
#define dsWSize		( 68)(%rdi)
#define dsWMask		( 76)(%rdi)
#define dsWindow	( 80)(%rdi)
#define dsPrev		( 96)(%rdi)
#define dsMatchLen	(144)(%rdi)
#define dsPrevMatch	(148)(%rdi)
#define dsStrStart	(156)(%rdi)
#define dsMatchStart	(160)(%rdi)
#define dsLookahead	(164)(%rdi)
#define dsPrevLen	(168)(%rdi)
#define dsMaxChainLen	(172)(%rdi)
#define dsGoodMatch	(188)(%rdi)
#define dsNiceMatch	(192)(%rdi)

#else 

#ifndef STRUCT_OFFSET
#	define STRUCT_OFFSET	(0)
#endif


#define dsWSize		( 56 + STRUCT_OFFSET)(%rdi)
#define dsWMask		( 64 + STRUCT_OFFSET)(%rdi)
#define dsWindow	( 72 + STRUCT_OFFSET)(%rdi)
#define dsPrev		( 88 + STRUCT_OFFSET)(%rdi)
#define dsMatchLen	(136 + STRUCT_OFFSET)(%rdi)
#define dsPrevMatch	(140 + STRUCT_OFFSET)(%rdi)
#define dsStrStart	(148 + STRUCT_OFFSET)(%rdi)
#define dsMatchStart	(152 + STRUCT_OFFSET)(%rdi)
#define dsLookahead	(156 + STRUCT_OFFSET)(%rdi)
#define dsPrevLen	(160 + STRUCT_OFFSET)(%rdi)
#define dsMaxChainLen	(164 + STRUCT_OFFSET)(%rdi)
#define dsGoodMatch	(180 + STRUCT_OFFSET)(%rdi)
#define dsNiceMatch	(184 + STRUCT_OFFSET)(%rdi)

#endif




.text

/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */

longest_match:
/*
 * Retrieve the function arguments. %curmatch will hold cur_match
 * throughout the entire function (passed via rsi on amd64).
 * rdi will hold the pointer to the deflate_state (first arg on amd64)
 */
		mov     %rsi, save_rsi
		mov     %rbx, save_rbx
		mov	%r12, save_r12
		mov     %r13, save_r13
		mov     %r14, save_r14
		mov     %r15, save_r15

/* uInt wmask = s->w_mask;						*/
/* unsigned chain_length = s->max_chain_length;				*/
/* if (s->prev_length >= s->good_match) {				*/
/*     chain_length >>= 2;						*/
/* }									*/

		movl	dsPrevLen, %eax
		movl	dsGoodMatch, %ebx
		cmpl	%ebx, %eax
		movl	dsWMask, %eax
		movl	dsMaxChainLen, %chainlenwmask
		jl	LastMatchGood
		shrl	$2, %chainlenwmask
LastMatchGood:

/* chainlen is decremented once beforehand so that the function can	*/
/* use the sign flag instead of the zero flag for the exit test.	*/
/* It is then shifted into the high word, to make room for the wmask	*/
/* value, which it will always accompany.				*/

		decl	%chainlenwmask
		shll	$16, %chainlenwmask
		orl	%eax, %chainlenwmask

/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;	*/

		movl	dsNiceMatch, %eax
		movl	dsLookahead, %ebx
		cmpl	%eax, %ebx
		jl	LookaheadLess
		movl	%eax, %ebx
LookaheadLess:	movl	%ebx, %nicematch

/* register Bytef *scan = s->window + s->strstart;			*/

		mov	dsWindow, %window
		movl	dsStrStart, %limitd
		lea	(%limit, %window), %scan

/* Determine how many bytes the scan ptr is off from being		*/
/* dword-aligned.							*/

		mov	%scan, %scanalign
		negl	%scanalignd
		andl	$3, %scanalignd

/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ?			*/
/*     s->strstart - (IPos)MAX_DIST(s) : NIL;				*/

		movl	dsWSize, %eax
		subl	$MIN_LOOKAHEAD, %eax
		xorl	%ecx, %ecx
		subl	%eax, %limitd
		cmovng	%ecx, %limitd

/* int best_len = s->prev_length;					*/

		movl	dsPrevLen, %bestlend

/* Store the sum of s->window + best_len in %windowbestlen locally, and in memory.	*/

		lea	(%window, %bestlen), %windowbestlen
		mov	%windowbestlen, _windowbestlen

/* register ush scan_start = *(ushf*)scan;				*/
/* register ush scan_end   = *(ushf*)(scan+best_len-1);			*/
/* Posf *prev = s->prev;						*/

		movzwl	(%scan), %scanstart
		movzwl	-1(%scan, %bestlen), %scanend
		mov	dsPrev, %prev

/* Jump into the main loop.						*/

		movl	%chainlenwmask, _chainlenwmask
		jmp	LoopEntry

.balign 16

/* do {
 *     match = s->window + cur_match;
 *     if (*(ushf*)(match+best_len-1) != scan_end ||
 *         *(ushf*)match != scan_start) continue;
 *     [...]
 * } while ((cur_match = prev[cur_match & wmask]) > limit
 *          && --chain_length != 0);
 *
 * Here is the inner loop of the function. The function will spend the
 * majority of its time in this loop, and majority of that time will
 * be spent in the first ten instructions.
 */
LookupLoop:
		andl	%chainlenwmask, %curmatchd
		movzwl	(%prev, %curmatch, 2), %curmatchd
		cmpl	%limitd, %curmatchd
		jbe	LeaveNow
		subl	$0x00010000, %chainlenwmask
		js	LeaveNow
LoopEntry:	cmpw	-1(%windowbestlen, %curmatch), %scanendw
		jne	LookupLoop
		cmpw	%scanstartw, (%window, %curmatch)
		jne	LookupLoop

/* Store the current value of chainlen.					*/
		movl	%chainlenwmask, _chainlenwmask

/* %scan is the string under scrutiny, and %prev to the string we	*/
/* are hoping to match it up with. In actuality, %esi and %edi are	*/
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is	*/
/* initialized to -(MAX_MATCH_8 - scanalign).				*/

		mov	$(-MAX_MATCH_8), %rdx
		lea	(%curmatch, %window), %windowbestlen
		lea	MAX_MATCH_8(%windowbestlen, %scanalign), %windowbestlen
		lea	MAX_MATCH_8(%scan, %scanalign), %prev

/* the prefetching below makes very little difference... */
		prefetcht1	(%windowbestlen, %rdx)
		prefetcht1	(%prev, %rdx)

/*
 * Test the strings for equality, 8 bytes at a time. At the end,
 * adjust %rdx so that it is offset to the exact byte that mismatched.
 *
 * It should be confessed that this loop usually does not represent
 * much of the total running time. Replacing it with a more
 * straightforward "rep cmpsb" would not drastically degrade
 * performance -- unrolling it, for example, makes no difference.
 */

#undef USE_SSE	/* works, but is 6-7% slower, than non-SSE... */

LoopCmps:
#ifdef USE_SSE
		/* Preload the SSE registers */
		movdqu	  (%windowbestlen, %rdx), %xmm1
		movdqu	  (%prev, %rdx), %xmm2
		pcmpeqb	%xmm2, %xmm1
		movdqu	16(%windowbestlen, %rdx), %xmm3
		movdqu	16(%prev, %rdx), %xmm4
		pcmpeqb	%xmm4, %xmm3
		movdqu	32(%windowbestlen, %rdx), %xmm5
		movdqu	32(%prev, %rdx), %xmm6
		pcmpeqb	%xmm6, %xmm5
		movdqu	48(%windowbestlen, %rdx), %xmm7
		movdqu	48(%prev, %rdx), %xmm8
		pcmpeqb	%xmm8, %xmm7

		/* Check the comparisions' results */
		pmovmskb %xmm1, %rax
		notw	%ax
		bsfw	%ax, %ax
		jnz	LeaveLoopCmps
		
		/* this is the only iteration of the loop with a possibility of having
		   incremented rdx by 0x108 (each loop iteration add 16*4 = 0x40 
		   and (0x40*4)+8=0x108 */
		add	$8, %rdx
		jz LenMaximum
		add	$8, %rdx

		
		pmovmskb %xmm3, %rax
		notw	%ax
		bsfw	%ax, %ax
		jnz	LeaveLoopCmps
		
		
		add	$16, %rdx


		pmovmskb %xmm5, %rax
		notw	%ax
		bsfw	%ax, %ax
		jnz	LeaveLoopCmps
		
		add	$16, %rdx


		pmovmskb %xmm7, %rax
		notw	%ax
		bsfw	%ax, %ax
		jnz	LeaveLoopCmps
		
		add	$16, %rdx
		
		jmp	LoopCmps
LeaveLoopCmps:	add	%rax, %rdx
#else
		mov	(%windowbestlen, %rdx), %rax
		xor	(%prev, %rdx), %rax
		jnz	LeaveLoopCmps
		
		mov	8(%windowbestlen, %rdx), %rax
		xor	8(%prev, %rdx), %rax
		jnz	LeaveLoopCmps8

		mov	16(%windowbestlen, %rdx), %rax
		xor	16(%prev, %rdx), %rax
		jnz	LeaveLoopCmps16
				
		add	$24, %rdx
		jnz	LoopCmps
		jmp	LenMaximum
#	if 0
/*
 * This three-liner is tantalizingly simple, but bsf is a slow instruction,
 * and the complicated alternative down below is quite a bit faster. Sad...
 */

LeaveLoopCmps:	bsf	%rax, %rax /* find the first non-zero bit */
		shrl	$3, %eax /* divide by 8 to get the byte */
		add	%rax, %rdx
#	else
LeaveLoopCmps16:
		add	$8, %rdx
LeaveLoopCmps8:
		add	$8, %rdx
LeaveLoopCmps:	testl   $0xFFFFFFFF, %eax /* Check the first 4 bytes */
		jnz     Check16
		add     $4, %rdx
		shr     $32, %rax
Check16:        testw   $0xFFFF, %ax
		jnz     LenLower
		add	$2, %rdx
		shrl	$16, %eax
LenLower:	subb	$1, %al
		adc	$0, %rdx
#	endif
#endif

/* Calculate the length of the match. If it is longer than MAX_MATCH,	*/
/* then automatically accept it as the best possible match and leave.	*/

		lea	(%prev, %rdx), %rax
		sub	%scan, %rax
		cmpl	$MAX_MATCH, %eax
		jge	LenMaximum

/* If the length of the match is not longer than the best match we	*/
/* have so far, then forget it and return to the lookup loop.		*/

		cmpl	%bestlend, %eax
		jg	LongerMatch
		mov	_windowbestlen, %windowbestlen
		mov	dsPrev, %prev
		movl	_chainlenwmask, %edx
		jmp	LookupLoop

/*         s->match_start = cur_match;					*/
/*         best_len = len;						*/
/*         if (len >= nice_match) break;				*/
/*         scan_end = *(ushf*)(scan+best_len-1);			*/

LongerMatch:
		movl	%eax, %bestlend
		movl	%curmatchd, dsMatchStart
		cmpl	%nicematch, %eax
		jge	LeaveNow

		lea	(%window, %bestlen), %windowbestlen
		mov	%windowbestlen, _windowbestlen

		movzwl	-1(%scan, %rax), %scanend
		mov	dsPrev, %prev
		movl	_chainlenwmask, %chainlenwmask
		jmp	LookupLoop

/* Accept the current string, with the maximum possible length.		*/

LenMaximum:
		movl	$MAX_MATCH, %bestlend
		movl	%curmatchd, dsMatchStart

/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len;		*/
/* return s->lookahead;							*/

LeaveNow:
		movl	dsLookahead, %eax
		cmpl	%eax, %bestlend
		cmovngl	%bestlend, %eax
LookaheadRet:

/* Restore the registers and return from whence we came.			*/

	mov	save_rsi, %rsi
	mov	save_rbx, %rbx
	mov	save_r12, %r12
	mov	save_r13, %r13
	mov	save_r14, %r14
	mov	save_r15, %r15

	ret

match_init:	ret

Deleted compat/zlib/contrib/asm686/README.686.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51



















































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
This is a patched version of zlib, modified to use
Pentium-Pro-optimized assembly code in the deflation algorithm. The
files changed/added by this patch are:

README.686
match.S

The speedup that this patch provides varies, depending on whether the
compiler used to build the original version of zlib falls afoul of the
PPro's speed traps. My own tests show a speedup of around 10-20% at
the default compression level, and 20-30% using -9, against a version
compiled using gcc 2.7.2.3. Your mileage may vary.

Note that this code has been tailored for the PPro/PII in particular,
and will not perform particuarly well on a Pentium.

If you are using an assembler other than GNU as, you will have to
translate match.S to use your assembler's syntax. (Have fun.)

Brian Raiter
breadbox@muppetlabs.com
April, 1998


Added for zlib 1.1.3:

The patches come from
http://www.muppetlabs.com/~breadbox/software/assembly.html

To compile zlib with this asm file, copy match.S to the zlib directory
then do:

CFLAGS="-O3 -DASMV" ./configure
make OBJA=match.o


Update:

I've been ignoring these assembly routines for years, believing that
gcc's generated code had caught up with it sometime around gcc 2.95
and the major rearchitecting of the Pentium 4. However, I recently
learned that, despite what I believed, this code still has some life
in it. On the Pentium 4 and AMD64 chips, it continues to run about 8%
faster than the code produced by gcc 4.1.

In acknowledgement of its continuing usefulness, I've altered the
license to match that of the rest of zlib. Share and Enjoy!

Brian Raiter
breadbox@muppetlabs.com
April, 2007

Changes to compat/zlib/contrib/blast/blast.h.

53
54
55
56
57
58
59
60

61
62
63
64
65
66
67
53
54
55
56
57
58
59

60
61
62
63
64
65
66
67







-
+







 * The input function is invoked: len = infun(how, &buf), where buf is set by
 * infun() to point to the input buffer, and infun() returns the number of
 * available bytes there.  If infun() returns zero, then blast() returns with
 * an input error.  (blast() only asks for input if it needs it.)  inhow is for
 * use by the application to pass an input descriptor to infun(), if desired.
 *
 * If left and in are not NULL and *left is not zero when blast() is called,
 * then the *left bytes are *in are consumed for input before infun() is used.
 * then the *left bytes at *in are consumed for input before infun() is used.
 *
 * The output function is invoked: err = outfun(how, buf, len), where the bytes
 * to be written are buf[0..len-1].  If err is not zero, then blast() returns
 * with an output error.  outfun() is always called with len <= 4096.  outhow
 * is for use by the application to pass an output descriptor to outfun(), if
 * desired.
 *

Changes to compat/zlib/contrib/delphi/ZLib.pas.

148
149
150
151
152
153
154
155

156
157
158
159
160
161
162
148
149
150
151
152
153
154

155
156
157
158
159
160
161
162







-
+







       InBytes = number of bytes in InBuf
  Out: OutBuf = ptr to user-allocated buffer to contain decompressed data
       BufSize = number of bytes in OutBuf   }
procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
  const OutBuf: Pointer; BufSize: Integer);

const
  zlib_version = '1.2.11';
  zlib_version = '1.3.1';

type
  EZlibError = class(Exception);
  ECompressionError = class(EZlibError);
  EDecompressionError = class(EZlibError);

implementation

Changes to compat/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







//
// © Copyright Henrik Ravn 2004
// © Copyright Henrik Ravn 2004
//
// Use, modification and distribution are subject to the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

using System;
using System.Runtime.InteropServices;
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
30
31
32
33
34
35
36

37
38
39
40
41
42
43
44







-
+







        /// </summary>
        public ChecksumGeneratorBase()
        {
            _current = 0;
        }

        /// <summary>
        /// Initializes a new instance of the checksum generator basewith a specified value
        /// Initializes a new instance of the checksum generator base with a specified value
        /// </summary>
        /// <param name="initialValue">The value to set the current checksum to</param>
        public ChecksumGeneratorBase(uint initialValue)
        {
            _current = initialValue;
        }

57
58
59
60
61
62
63
64

65
66
67
68
69
70
71
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71







-
+







        /// </summary>
        /// <param name="data">The data to update the checksum with</param>
        /// <param name="offset">Where in <c>data</c> to start updating</param>
        /// <param name="count">The number of bytes from <c>data</c> to use</param>
        /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception>
        /// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception>
        /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception>
        /// <remarks>All the other <c>Update</c> methods are implmeneted in terms of this one.
        /// <remarks>All the other <c>Update</c> methods are implemented in terms of this one.
        /// This is therefore the only method a derived class has to implement</remarks>
        public abstract void Update(byte[] data, int offset, int count);

        /// <summary>
        /// Updates the current checksum with an array of bytes.
        /// </summary>
        /// <param name="data">The data to update the checksum with</param>

Changes to compat/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







//
// © Copyright Henrik Ravn 2004
// © Copyright Henrik Ravn 2004
//
// Use, modification and distribution are subject to the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

using System;
using System.Diagnostics;

Changes to compat/zlib/contrib/dotzlib/DotZLib/CodecBase.cs.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







//
// © Copyright Henrik Ravn 2004
// © Copyright Henrik Ravn 2004
//
// Use, modification and distribution are subject to the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

using System;
using System.Runtime.InteropServices;
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
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







-
+




















-
+








        /// <summary>
        /// Performs any codec specific cleanup
        /// </summary>
        /// <remarks>This must be implemented by a derived class</remarks>
        protected abstract void CleanUp();

        // performs the release of the handles and calls the dereived CleanUp()
        // performs the release of the handles and calls the derived CleanUp()
        private void CleanUp(bool isDisposing)
        {
            if (!_isDisposed)
            {
                CleanUp();
                if (_hInput.IsAllocated)
                    _hInput.Free();
                if (_hOutput.IsAllocated)
                    _hOutput.Free();

                _isDisposed = true;
            }
        }


        #endregion

        #region Helper methods

        /// <summary>
        /// Copies a number of bytes to the internal codec buffer - ready for proccesing
        /// Copies a number of bytes to the internal codec buffer - ready for processing
        /// </summary>
        /// <param name="data">The byte array that contains the data to copy</param>
        /// <param name="startIndex">The index of the first byte to copy</param>
        /// <param name="count">The number of bytes to copy from <c>data</c></param>
        protected void copyInput(byte[] data, int startIndex, int count)
        {
            Array.Copy(data, startIndex, _inBuffer,0, count);

Changes to compat/zlib/contrib/dotzlib/DotZLib/Deflater.cs.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







//
// © Copyright Henrik Ravn 2004
// © Copyright Henrik Ravn 2004
//
// Use, modification and distribution are subject to the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

using System;
using System.Diagnostics;

Changes to compat/zlib/contrib/dotzlib/DotZLib/DotZLib.cs.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







//
// © Copyright Henrik Ravn 2004
// © Copyright Henrik Ravn 2004
//
// Use, modification and distribution are subject to the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

using System;
using System.IO;

Changes to compat/zlib/contrib/dotzlib/DotZLib/GZipStream.cs.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







//
// © Copyright Henrik Ravn 2004
// © Copyright Henrik Ravn 2004
//
// Use, modification and distribution are subject to the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

using System;
using System.IO;
242
243
244
245
246
247
248
249

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

249
250
251
252
253
254
255
256







-
+







        /// <exception cref="NotSupportedException">Always thrown</exception>
        public override void SetLength(long value)
        {
            throw new NotSupportedException();
        }

        /// <summary>
        ///  Not suppported.
        ///  Not supported.
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="origin"></param>
        /// <returns></returns>
        /// <exception cref="NotSupportedException">Always thrown</exception>
        public override long Seek(long offset, SeekOrigin origin)
        {
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
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







-
+
















-
+













        /// flushing may degrade the achievable compression rates.</remarks>
        public override void Flush()
        {
            // left empty on purpose
        }

        /// <summary>
        /// Gets/sets the current position in the <c>GZipStream</c>. Not suppported.
        /// Gets/sets the current position in the <c>GZipStream</c>. Not supported.
        /// </summary>
        /// <remarks>In this implementation this property is not supported</remarks>
        /// <exception cref="NotSupportedException">Always thrown</exception>
        public override long Position
        {
            get
            {
                throw new NotSupportedException();
            }
            set
            {
                throw new NotSupportedException();
            }
        }

        /// <summary>
        /// Gets the size of the stream. Not suppported.
        /// Gets the size of the stream. Not supported.
        /// </summary>
        /// <remarks>In this implementation this property is not supported</remarks>
        /// <exception cref="NotSupportedException">Always thrown</exception>
        public override long Length
        {
            get
            {
                throw new NotSupportedException();
            }
        }
        #endregion
    }
}

Changes to compat/zlib/contrib/dotzlib/DotZLib/Inflater.cs.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







//
// © Copyright Henrik Ravn 2004
// © Copyright Henrik Ravn 2004
//
// Use, modification and distribution are subject to the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

using System;
using System.Diagnostics;

Changes to compat/zlib/contrib/dotzlib/DotZLib/UnitTests.cs.

152
153
154
155
156
157
158
159

160
161
162
163
164
165
166
152
153
154
155
156
157
158

159
160
161
162
163
164
165
166







-
+







    public class InfoTests
    {
        #region Info tests
        [Test]
        public void Info_Version()
        {
            Info info = new Info();
            Assert.AreEqual("1.2.11", Info.Version);
            Assert.AreEqual("1.3.1", Info.Version);
            Assert.AreEqual(32, info.SizeOfUInt);
            Assert.AreEqual(32, info.SizeOfULong);
            Assert.AreEqual(32, info.SizeOfPointer);
            Assert.AreEqual(32, info.SizeOfOffset);
        }
        #endregion
    }

Changes to compat/zlib/contrib/dotzlib/readme.txt.

32
33
34
35
36
37
38
39

40
41
42
43
44
45
46
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46







-
+







   build.

2. Using NAnt:
   Open a command prompt with access to the build environment and run nant
   in the same directory as the DotZLib.build file.
   You can define 2 properties on the nant command-line to control the build:
   debug={true|false} to toggle between release/debug builds (default=true).
   nunit={true|false} to include or esclude unit tests (default=true).
   nunit={true|false} to include or exclude unit tests (default=true).
   Also the target clean will remove binaries.
   Output file (DotZLib.dll) will be found in either ./DotZLib/bin/release
   or ./DotZLib/bin/debug, depending on whether you are building the release
   or debug version of the library.

   Examples:
     nant -D:debug=false -D:nunit=false

Changes to compat/zlib/contrib/infback9/infback9.c.

12
13
14
15
16
17
18
19
20
21
22


23
24
25
26
27
28
29
30
31
12
13
14
15
16
17
18




19
20


21
22
23
24
25
26
27







-
-
-
-
+
+
-
-








/*
   strm provides memory allocation functions in zalloc and zfree, or
   Z_NULL to use the library memory allocation functions.

   window is a user-supplied window and output buffer that is 64K bytes.
 */
int ZEXPORT inflateBack9Init_(strm, window, version, stream_size)
z_stream FAR *strm;
unsigned char FAR *window;
const char *version;
int ZEXPORT inflateBack9Init_(z_stream FAR *strm, unsigned char FAR *window,
                              const char *version, int stream_size) {
int stream_size;
{
    struct inflate_state FAR *state;

    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
        stream_size != (int)(sizeof(z_stream)))
        return Z_VERSION_ERROR;
    if (strm == Z_NULL || window == Z_NULL)
        return Z_STREAM_ERROR;
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62
43
44
45
46
47
48
49

50

51
52
53
54
55
56
57







-
+
-







/*
   Build and output length and distance decoding tables for fixed code
   decoding.
 */
#ifdef MAKEFIXED
#include <stdio.h>

void makefixed9(void)
void makefixed9(void) {
{
    unsigned sym, bits, low, size;
    code *next, *lenfix, *distfix;
    struct inflate_state state;
    code fixed[544];

    /* literal/length table */
    sym = 0;
210
211
212
213
214
215
216
217
218

219
220
221

222
223
224
225
226
227
228
229
230
205
206
207
208
209
210
211


212



213


214
215
216
217
218
219
220







-
-
+
-
-
-
+
-
-







   Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
   was in() or out() that caused in the error.  Otherwise,  inflateBack()
   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
   error, or Z_MEM_ERROR if it could not allocate memory for the state.
   inflateBack() can also return Z_STREAM_ERROR if the input parameters
   are not correct, i.e. strm is Z_NULL or the state was not initialized.
 */
int ZEXPORT inflateBack9(strm, in, in_desc, out, out_desc)
z_stream FAR *strm;
int ZEXPORT inflateBack9(z_stream FAR *strm, in_func in, void FAR *in_desc,
in_func in;
void FAR *in_desc;
out_func out;
                         out_func out, void FAR *out_desc) {
void FAR *out_desc;
{
    struct inflate_state FAR *state;
    z_const unsigned char FAR *next;    /* next input */
    unsigned char FAR *put;     /* next output */
    unsigned have;              /* available input */
    unsigned long left;         /* available output */
    inflate_mode mode;          /* current inflate mode */
    int lastblock;              /* true if processing last block */
599
600
601
602
603
604
605
606

607
608
609
610
611
612
613
614
615
589
590
591
592
593
594
595

596


597
598
599
600
601
602
603







-
+
-
-







    /* Return unused input */
  inf_leave:
    strm->next_in = next;
    strm->avail_in = have;
    return ret;
}

int ZEXPORT inflateBack9End(strm)
int ZEXPORT inflateBack9End(z_stream FAR *strm) {
z_stream FAR *strm;
{
    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
        return Z_STREAM_ERROR;
    ZFREE(strm, strm->state);
    strm->state = Z_NULL;
    Tracev((stderr, "inflate: end\n"));
    return Z_OK;
}

Changes to compat/zlib/contrib/infback9/infback9.h.

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30








31
32
33
34
35
36
37
16
17
18
19
20
21
22








23
24
25
26
27
28
29
30
31
32
33
34
35
36
37







-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+







 * zlib.h must be included before this header file.
 */

#ifdef __cplusplus
extern "C" {
#endif

ZEXTERN int ZEXPORT inflateBack9 OF((z_stream FAR *strm,
                                    in_func in, void FAR *in_desc,
                                    out_func out, void FAR *out_desc));
ZEXTERN int ZEXPORT inflateBack9End OF((z_stream FAR *strm));
ZEXTERN int ZEXPORT inflateBack9Init_ OF((z_stream FAR *strm,
                                         unsigned char FAR *window,
                                         const char *version,
                                         int stream_size));
ZEXTERN int ZEXPORT inflateBack9(z_stream FAR *strm,
                                 in_func in, void FAR *in_desc,
                                 out_func out, void FAR *out_desc);
ZEXTERN int ZEXPORT inflateBack9End(z_stream FAR *strm);
ZEXTERN int ZEXPORT inflateBack9Init_(z_stream FAR *strm,
                                      unsigned char FAR *window,
                                      const char *version,
                                      int stream_size);
#define inflateBack9Init(strm, window) \
        inflateBack9Init_((strm), (window), \
        ZLIB_VERSION, sizeof(z_stream))

#ifdef __cplusplus
}
#endif

Changes to compat/zlib/contrib/infback9/inftree9.c.

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
30
31
32
33
34

35
36

37
38

39
40
41
42
43
44
45
46
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
30
31



32


33


34

35
36
37
38
39
40
41

-
+









-
+



















-
-
-
+
-
-
+
-
-
+
-







/* inftree9.c -- generate Huffman trees for efficient decoding
 * Copyright (C) 1995-2017 Mark Adler
 * Copyright (C) 1995-2024 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#include "zutil.h"
#include "inftree9.h"

#define MAXBITS 15

const char inflate9_copyright[] =
   " inflate9 1.2.11 Copyright 1995-2017 Mark Adler ";
   " inflate9 1.3.1 Copyright 1995-2024 Mark Adler ";
/*
  If you use the zlib library in a product, an acknowledgment is welcome
  in the documentation of your product. If for some reason you cannot
  include such an acknowledgment, I would appreciate that you keep this
  copyright string in the executable of your product.
 */

/*
   Build a set of tables to decode the provided canonical Huffman code.
   The code lengths are lens[0..codes-1].  The result starts at *table,
   whose indices are 0..2^bits-1.  work is a writable array of at least
   lens shorts, which is used as a work area.  type is the type of code
   to be generated, CODES, LENS, or DISTS.  On return, zero is success,
   -1 is an invalid code, and +1 means that ENOUGH isn't enough.  table
   on return points to the next available entry's address.  bits is the
   requested root table index bits, and on return it is the actual root
   table index bits.  It will differ if the request is greater than the
   longest code or if it is less than the shortest code.
 */
int inflate_table9(type, lens, codes, table, bits, work)
codetype type;
unsigned short FAR *lens;
int inflate_table9(codetype type, unsigned short FAR *lens, unsigned codes,
unsigned codes;
code FAR * FAR *table;
                   code FAR * FAR *table, unsigned FAR *bits,
unsigned FAR *bits;
unsigned short FAR *work;
                   unsigned short FAR *work) {
{
    unsigned len;               /* a code's length in bits */
    unsigned sym;               /* index of code symbols */
    unsigned min, max;          /* minimum and maximum code lengths */
    unsigned root;              /* number of index bits for root table */
    unsigned curr;              /* number of index bits for current table */
    unsigned drop;              /* code bits to drop for sub-table */
    int left;                   /* number of prefix codes available */
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
55
56
57
58
59
60
61

62
63
64
65
66
67
68
69







-
+







    static const unsigned short lbase[31] = { /* Length codes 257..285 base */
        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17,
        19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115,
        131, 163, 195, 227, 3, 0, 0};
    static const unsigned short lext[31] = { /* Length codes 257..285 extra */
        128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129,
        130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132,
        133, 133, 133, 133, 144, 77, 202};
        133, 133, 133, 133, 144, 203, 77};
    static const unsigned short dbase[32] = { /* Distance codes 0..31 base */
        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49,
        65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073,
        4097, 6145, 8193, 12289, 16385, 24577, 32769, 49153};
    static const unsigned short dext[32] = { /* Distance codes 0..31 extra */
        128, 128, 128, 128, 129, 129, 130, 130, 131, 131, 132, 132,
        133, 133, 134, 134, 135, 135, 136, 136, 137, 137, 138, 138,

Changes to compat/zlib/contrib/infback9/inftree9.h.

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



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







-
+


-
-
+
+













-
-
-
+
+
+
    01100000 - end of block
    01000000 - invalid code
 */

/* Maximum size of the dynamic table.  The maximum number of code structures is
   1446, which is the sum of 852 for literal/length codes and 594 for distance
   codes.  These values were found by exhaustive searches using the program
   examples/enough.c found in the zlib distribtution.  The arguments to that
   examples/enough.c found in the zlib distribution.  The arguments to that
   program are the number of symbols, the initial root table size, and the
   maximum bit length of a code.  "enough 286 9 15" for literal/length codes
   returns returns 852, and "enough 32 6 15" for distance codes returns 594.
   The initial root table size (9 or 6) is found in the fifth argument of the
   returns 852, and "enough 32 6 15" for distance codes returns 594. The
   initial root table size (9 or 6) is found in the fifth argument of the
   inflate_table() calls in infback9.c.  If the root table size is changed,
   then these maximum sizes would be need to be recalculated and updated. */
#define ENOUGH_LENS 852
#define ENOUGH_DISTS 594
#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)

/* Type of code to build for inflate_table9() */
typedef enum {
    CODES,
    LENS,
    DISTS
} codetype;

extern int inflate_table9 OF((codetype type, unsigned short FAR *lens,
                             unsigned codes, code FAR * FAR *table,
                             unsigned FAR *bits, unsigned short FAR *work));
extern int inflate_table9(codetype type, unsigned short FAR *lens,
                          unsigned codes, code FAR * FAR *table,
                          unsigned FAR *bits, unsigned short FAR *work);

Deleted compat/zlib/contrib/inflate86/inffast.S.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * inffast.S is a hand tuned assembler version of:
 *
 * inffast.c -- fast decoding
 * Copyright (C) 1995-2003 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 *
 * Copyright (C) 2003 Chris Anderson <christop@charm.net>
 * Please use the copyright conditions above.
 *
 * This version (Jan-23-2003) of inflate_fast was coded and tested under
 * GNU/Linux on a pentium 3, using the gcc-3.2 compiler distribution.  On that
 * machine, I found that gzip style archives decompressed about 20% faster than
 * the gcc-3.2 -O3 -fomit-frame-pointer compiled version.  Your results will
 * depend on how large of a buffer is used for z_stream.next_in & next_out
 * (8K-32K worked best for my 256K cpu cache) and how much overhead there is in
 * stream processing I/O and crc32/addler32.  In my case, this routine used
 * 70% of the cpu time and crc32 used 20%.
 *
 * I am confident that this version will work in the general case, but I have
 * not tested a wide variety of datasets or a wide variety of platforms.
 *
 * Jan-24-2003 -- Added -DUSE_MMX define for slightly faster inflating.
 * It should be a runtime flag instead of compile time flag...
 *
 * Jan-26-2003 -- Added runtime check for MMX support with cpuid instruction.
 * With -DUSE_MMX, only MMX code is compiled.  With -DNO_MMX, only non-MMX code
 * is compiled.  Without either option, runtime detection is enabled.  Runtime
 * detection should work on all modern cpus and the recomended algorithm (flip
 * ID bit on eflags and then use the cpuid instruction) is used in many
 * multimedia applications.  Tested under win2k with gcc-2.95 and gas-2.12
 * distributed with cygwin3.  Compiling with gcc-2.95 -c inffast.S -o
 * inffast.obj generates a COFF object which can then be linked with MSVC++
 * compiled code.  Tested under FreeBSD 4.7 with gcc-2.95.
 *
 * Jan-28-2003 -- Tested Athlon XP... MMX mode is slower than no MMX (and
 * slower than compiler generated code).  Adjusted cpuid check to use the MMX
 * code only for Pentiums < P4 until I have more data on the P4.  Speed
 * improvment is only about 15% on the Athlon when compared with code generated
 * with MSVC++.  Not sure yet, but I think the P4 will also be slower using the
 * MMX mode because many of it's x86 ALU instructions execute in .5 cycles and
 * have less latency than MMX ops.  Added code to buffer the last 11 bytes of
 * the input stream since the MMX code grabs bits in chunks of 32, which
 * differs from the inffast.c algorithm.  I don't think there would have been
 * read overruns where a page boundary was crossed (a segfault), but there
 * could have been overruns when next_in ends on unaligned memory (unintialized
 * memory read).
 *
 * Mar-13-2003 -- P4 MMX is slightly slower than P4 NO_MMX.  I created a C
 * version of the non-MMX code so that it doesn't depend on zstrm and zstate
 * structure offsets which are hard coded in this file.  This was last tested
 * with zlib-1.2.0 which is currently in beta testing, newer versions of this
 * and inffas86.c can be found at http://www.eetbeetee.com/zlib/ and
 * http://www.charm.net/~christop/zlib/
 */


/*
 * if you have underscore linking problems (_inflate_fast undefined), try
 * using -DGAS_COFF
 */
#if ! defined( GAS_COFF ) && ! defined( GAS_ELF )

#if defined( WIN32 ) || defined( __CYGWIN__ )
#define GAS_COFF /* windows object format */
#else
#define GAS_ELF
#endif

#endif /* ! GAS_COFF && ! GAS_ELF */


#if defined( GAS_COFF )

/* coff externals have underscores */
#define inflate_fast _inflate_fast
#define inflate_fast_use_mmx _inflate_fast_use_mmx

#endif /* GAS_COFF */


.file "inffast.S"

.globl inflate_fast

.text
.align 4,0
.L_invalid_literal_length_code_msg:
.string "invalid literal/length code"

.align 4,0
.L_invalid_distance_code_msg:
.string "invalid distance code"

.align 4,0
.L_invalid_distance_too_far_msg:
.string "invalid distance too far back"

#if ! defined( NO_MMX )
.align 4,0
.L_mask: /* mask[N] = ( 1 << N ) - 1 */
.long 0
.long 1
.long 3
.long 7
.long 15
.long 31
.long 63
.long 127
.long 255
.long 511
.long 1023
.long 2047
.long 4095
.long 8191
.long 16383
.long 32767
.long 65535
.long 131071
.long 262143
.long 524287
.long 1048575
.long 2097151
.long 4194303
.long 8388607
.long 16777215
.long 33554431
.long 67108863
.long 134217727
.long 268435455
.long 536870911
.long 1073741823
.long 2147483647
.long 4294967295
#endif /* NO_MMX */

.text

/*
 * struct z_stream offsets, in zlib.h
 */
#define next_in_strm   0   /* strm->next_in */
#define avail_in_strm  4   /* strm->avail_in */
#define next_out_strm  12  /* strm->next_out */
#define avail_out_strm 16  /* strm->avail_out */
#define msg_strm       24  /* strm->msg */
#define state_strm     28  /* strm->state */

/*
 * struct inflate_state offsets, in inflate.h
 */
#define mode_state     0   /* state->mode */
#define wsize_state    32  /* state->wsize */
#define write_state    40  /* state->write */
#define window_state   44  /* state->window */
#define hold_state     48  /* state->hold */
#define bits_state     52  /* state->bits */
#define lencode_state  68  /* state->lencode */
#define distcode_state 72  /* state->distcode */
#define lenbits_state  76  /* state->lenbits */
#define distbits_state 80  /* state->distbits */

/*
 * inflate_fast's activation record
 */
#define local_var_size 64 /* how much local space for vars */
#define strm_sp        88 /* first arg: z_stream * (local_var_size + 24) */
#define start_sp       92 /* second arg: unsigned int (local_var_size + 28) */

/*
 * offsets for local vars on stack
 */
#define out            60  /* unsigned char* */
#define window         56  /* unsigned char* */
#define wsize          52  /* unsigned int */
#define write          48  /* unsigned int */
#define in             44  /* unsigned char* */
#define beg            40  /* unsigned char* */
#define buf            28  /* char[ 12 ] */
#define len            24  /* unsigned int */
#define last           20  /* unsigned char* */
#define end            16  /* unsigned char* */
#define dcode          12  /* code* */
#define lcode           8  /* code* */
#define dmask           4  /* unsigned int */
#define lmask           0  /* unsigned int */

/*
 * typedef enum inflate_mode consts, in inflate.h
 */
#define INFLATE_MODE_TYPE 11  /* state->mode flags enum-ed in inflate.h */
#define INFLATE_MODE_BAD  26


#if ! defined( USE_MMX ) && ! defined( NO_MMX )

#define RUN_TIME_MMX

#define CHECK_MMX    1
#define DO_USE_MMX   2
#define DONT_USE_MMX 3

.globl inflate_fast_use_mmx

.data

.align 4,0
inflate_fast_use_mmx: /* integer flag for run time control 1=check,2=mmx,3=no */
.long CHECK_MMX

#if defined( GAS_ELF )
/* elf info */
.type   inflate_fast_use_mmx,@object
.size   inflate_fast_use_mmx,4
#endif

#endif /* RUN_TIME_MMX */

#if defined( GAS_COFF )
/* coff info: scl 2 = extern, type 32 = function */
.def inflate_fast; .scl 2; .type 32; .endef
#endif

.text

.align 32,0x90
inflate_fast:
        pushl   %edi
        pushl   %esi
        pushl   %ebp
        pushl   %ebx
        pushf   /* save eflags (strm_sp, state_sp assumes this is 32 bits) */
        subl    $local_var_size, %esp
        cld

#define strm_r  %esi
#define state_r %edi

        movl    strm_sp(%esp), strm_r
        movl    state_strm(strm_r), state_r

        /* in = strm->next_in;
         * out = strm->next_out;
         * last = in + strm->avail_in - 11;
         * beg = out - (start - strm->avail_out);
         * end = out + (strm->avail_out - 257);
         */
        movl    avail_in_strm(strm_r), %edx
        movl    next_in_strm(strm_r), %eax

        addl    %eax, %edx      /* avail_in += next_in */
        subl    $11, %edx       /* avail_in -= 11 */

        movl    %eax, in(%esp)
        movl    %edx, last(%esp)

        movl    start_sp(%esp), %ebp
        movl    avail_out_strm(strm_r), %ecx
        movl    next_out_strm(strm_r), %ebx

        subl    %ecx, %ebp      /* start -= avail_out */
        negl    %ebp            /* start = -start */
        addl    %ebx, %ebp      /* start += next_out */

        subl    $257, %ecx      /* avail_out -= 257 */
        addl    %ebx, %ecx      /* avail_out += out */

        movl    %ebx, out(%esp)
        movl    %ebp, beg(%esp)
        movl    %ecx, end(%esp)

        /* wsize = state->wsize;
         * write = state->write;
         * window = state->window;
         * hold = state->hold;
         * bits = state->bits;
         * lcode = state->lencode;
         * dcode = state->distcode;
         * lmask = ( 1 << state->lenbits ) - 1;
         * dmask = ( 1 << state->distbits ) - 1;
         */

        movl    lencode_state(state_r), %eax
        movl    distcode_state(state_r), %ecx

        movl    %eax, lcode(%esp)
        movl    %ecx, dcode(%esp)

        movl    $1, %eax
        movl    lenbits_state(state_r), %ecx
        shll    %cl, %eax
        decl    %eax
        movl    %eax, lmask(%esp)

        movl    $1, %eax
        movl    distbits_state(state_r), %ecx
        shll    %cl, %eax
        decl    %eax
        movl    %eax, dmask(%esp)

        movl    wsize_state(state_r), %eax
        movl    write_state(state_r), %ecx
        movl    window_state(state_r), %edx

        movl    %eax, wsize(%esp)
        movl    %ecx, write(%esp)
        movl    %edx, window(%esp)

        movl    hold_state(state_r), %ebp
        movl    bits_state(state_r), %ebx

#undef strm_r
#undef state_r

#define in_r       %esi
#define from_r     %esi
#define out_r      %edi

        movl    in(%esp), in_r
        movl    last(%esp), %ecx
        cmpl    in_r, %ecx
        ja      .L_align_long           /* if in < last */

        addl    $11, %ecx               /* ecx = &in[ avail_in ] */
        subl    in_r, %ecx              /* ecx = avail_in */
        movl    $12, %eax
        subl    %ecx, %eax              /* eax = 12 - avail_in */
        leal    buf(%esp), %edi
        rep     movsb                   /* memcpy( buf, in, avail_in ) */
        movl    %eax, %ecx
        xorl    %eax, %eax
        rep     stosb         /* memset( &buf[ avail_in ], 0, 12 - avail_in ) */
        leal    buf(%esp), in_r         /* in = buf */
        movl    in_r, last(%esp)        /* last = in, do just one iteration */
        jmp     .L_is_aligned

        /* align in_r on long boundary */
.L_align_long:
        testl   $3, in_r
        jz      .L_is_aligned
        xorl    %eax, %eax
        movb    (in_r), %al
        incl    in_r
        movl    %ebx, %ecx
        addl    $8, %ebx
        shll    %cl, %eax
        orl     %eax, %ebp
        jmp     .L_align_long

.L_is_aligned:
        movl    out(%esp), out_r

#if defined( NO_MMX )
        jmp     .L_do_loop
#endif

#if defined( USE_MMX )
        jmp     .L_init_mmx
#endif

/*** Runtime MMX check ***/

#if defined( RUN_TIME_MMX )
.L_check_mmx:
        cmpl    $DO_USE_MMX, inflate_fast_use_mmx
        je      .L_init_mmx
        ja      .L_do_loop /* > 2 */

        pushl   %eax
        pushl   %ebx
        pushl   %ecx
        pushl   %edx
        pushf
        movl    (%esp), %eax      /* copy eflags to eax */
        xorl    $0x200000, (%esp) /* try toggling ID bit of eflags (bit 21)
                                   * to see if cpu supports cpuid...
                                   * ID bit method not supported by NexGen but
                                   * bios may load a cpuid instruction and
                                   * cpuid may be disabled on Cyrix 5-6x86 */
        popf
        pushf
        popl    %edx              /* copy new eflags to edx */
        xorl    %eax, %edx        /* test if ID bit is flipped */
        jz      .L_dont_use_mmx   /* not flipped if zero */
        xorl    %eax, %eax
        cpuid
        cmpl    $0x756e6547, %ebx /* check for GenuineIntel in ebx,ecx,edx */
        jne     .L_dont_use_mmx
        cmpl    $0x6c65746e, %ecx
        jne     .L_dont_use_mmx
        cmpl    $0x49656e69, %edx
        jne     .L_dont_use_mmx
        movl    $1, %eax
        cpuid                     /* get cpu features */
        shrl    $8, %eax
        andl    $15, %eax
        cmpl    $6, %eax          /* check for Pentium family, is 0xf for P4 */
        jne     .L_dont_use_mmx
        testl   $0x800000, %edx   /* test if MMX feature is set (bit 23) */
        jnz     .L_use_mmx
        jmp     .L_dont_use_mmx
.L_use_mmx:
        movl    $DO_USE_MMX, inflate_fast_use_mmx
        jmp     .L_check_mmx_pop
.L_dont_use_mmx:
        movl    $DONT_USE_MMX, inflate_fast_use_mmx
.L_check_mmx_pop:
        popl    %edx
        popl    %ecx
        popl    %ebx
        popl    %eax
        jmp     .L_check_mmx
#endif


/*** Non-MMX code ***/

#if defined ( NO_MMX ) || defined( RUN_TIME_MMX )

#define hold_r     %ebp
#define bits_r     %bl
#define bitslong_r %ebx

.align 32,0x90
.L_while_test:
        /* while (in < last && out < end)
         */
        cmpl    out_r, end(%esp)
        jbe     .L_break_loop           /* if (out >= end) */

        cmpl    in_r, last(%esp)
        jbe     .L_break_loop

.L_do_loop:
        /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out
         *
         * do {
         *   if (bits < 15) {
         *     hold |= *((unsigned short *)in)++ << bits;
         *     bits += 16
         *   }
         *   this = lcode[hold & lmask]
         */
        cmpb    $15, bits_r
        ja      .L_get_length_code      /* if (15 < bits) */

        xorl    %eax, %eax
        lodsw                           /* al = *(ushort *)in++ */
        movb    bits_r, %cl             /* cl = bits, needs it for shifting */
        addb    $16, bits_r             /* bits += 16 */
        shll    %cl, %eax
        orl     %eax, hold_r            /* hold |= *((ushort *)in)++ << bits */

.L_get_length_code:
        movl    lmask(%esp), %edx       /* edx = lmask */
        movl    lcode(%esp), %ecx       /* ecx = lcode */
        andl    hold_r, %edx            /* edx &= hold */
        movl    (%ecx,%edx,4), %eax     /* eax = lcode[hold & lmask] */

.L_dolen:
        /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out
         *
         * dolen:
         *    bits -= this.bits;
         *    hold >>= this.bits
         */
        movb    %ah, %cl                /* cl = this.bits */
        subb    %ah, bits_r             /* bits -= this.bits */
        shrl    %cl, hold_r             /* hold >>= this.bits */

        /* check if op is a literal
         * if (op == 0) {
         *    PUP(out) = this.val;
         *  }
         */
        testb   %al, %al
        jnz     .L_test_for_length_base /* if (op != 0) 45.7% */

        shrl    $16, %eax               /* output this.val char */
        stosb
        jmp     .L_while_test

.L_test_for_length_base:
        /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = len
         *
         * else if (op & 16) {
         *   len = this.val
         *   op &= 15
         *   if (op) {
         *     if (op > bits) {
         *       hold |= *((unsigned short *)in)++ << bits;
         *       bits += 16
         *     }
         *     len += hold & mask[op];
         *     bits -= op;
         *     hold >>= op;
         *   }
         */
#define len_r %edx
        movl    %eax, len_r             /* len = this */
        shrl    $16, len_r              /* len = this.val */
        movb    %al, %cl

        testb   $16, %al
        jz      .L_test_for_second_level_length /* if ((op & 16) == 0) 8% */
        andb    $15, %cl                /* op &= 15 */
        jz      .L_save_len             /* if (!op) */
        cmpb    %cl, bits_r
        jae     .L_add_bits_to_len      /* if (op <= bits) */

        movb    %cl, %ch                /* stash op in ch, freeing cl */
        xorl    %eax, %eax
        lodsw                           /* al = *(ushort *)in++ */
        movb    bits_r, %cl             /* cl = bits, needs it for shifting */
        addb    $16, bits_r             /* bits += 16 */
        shll    %cl, %eax
        orl     %eax, hold_r            /* hold |= *((ushort *)in)++ << bits */
        movb    %ch, %cl                /* move op back to ecx */

.L_add_bits_to_len:
        movl    $1, %eax
        shll    %cl, %eax
        decl    %eax
        subb    %cl, bits_r
        andl    hold_r, %eax            /* eax &= hold */
        shrl    %cl, hold_r
        addl    %eax, len_r             /* len += hold & mask[op] */

.L_save_len:
        movl    len_r, len(%esp)        /* save len */
#undef  len_r

.L_decode_distance:
        /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = dist
         *
         *   if (bits < 15) {
         *     hold |= *((unsigned short *)in)++ << bits;
         *     bits += 16
         *   }
         *   this = dcode[hold & dmask];
         * dodist:
         *   bits -= this.bits;
         *   hold >>= this.bits;
         *   op = this.op;
         */

        cmpb    $15, bits_r
        ja      .L_get_distance_code    /* if (15 < bits) */

        xorl    %eax, %eax
        lodsw                           /* al = *(ushort *)in++ */
        movb    bits_r, %cl             /* cl = bits, needs it for shifting */
        addb    $16, bits_r             /* bits += 16 */
        shll    %cl, %eax
        orl     %eax, hold_r            /* hold |= *((ushort *)in)++ << bits */

.L_get_distance_code:
        movl    dmask(%esp), %edx       /* edx = dmask */
        movl    dcode(%esp), %ecx       /* ecx = dcode */
        andl    hold_r, %edx            /* edx &= hold */
        movl    (%ecx,%edx,4), %eax     /* eax = dcode[hold & dmask] */

#define dist_r %edx
.L_dodist:
        movl    %eax, dist_r            /* dist = this */
        shrl    $16, dist_r             /* dist = this.val */
        movb    %ah, %cl
        subb    %ah, bits_r             /* bits -= this.bits */
        shrl    %cl, hold_r             /* hold >>= this.bits */

        /* if (op & 16) {
         *   dist = this.val
         *   op &= 15
         *   if (op > bits) {
         *     hold |= *((unsigned short *)in)++ << bits;
         *     bits += 16
         *   }
         *   dist += hold & mask[op];
         *   bits -= op;
         *   hold >>= op;
         */
        movb    %al, %cl                /* cl = this.op */

        testb   $16, %al                /* if ((op & 16) == 0) */
        jz      .L_test_for_second_level_dist
        andb    $15, %cl                /* op &= 15 */
        jz      .L_check_dist_one
        cmpb    %cl, bits_r
        jae     .L_add_bits_to_dist     /* if (op <= bits) 97.6% */

        movb    %cl, %ch                /* stash op in ch, freeing cl */
        xorl    %eax, %eax
        lodsw                           /* al = *(ushort *)in++ */
        movb    bits_r, %cl             /* cl = bits, needs it for shifting */
        addb    $16, bits_r             /* bits += 16 */
        shll    %cl, %eax
        orl     %eax, hold_r            /* hold |= *((ushort *)in)++ << bits */
        movb    %ch, %cl                /* move op back to ecx */

.L_add_bits_to_dist:
        movl    $1, %eax
        shll    %cl, %eax
        decl    %eax                    /* (1 << op) - 1 */
        subb    %cl, bits_r
        andl    hold_r, %eax            /* eax &= hold */
        shrl    %cl, hold_r
        addl    %eax, dist_r            /* dist += hold & ((1 << op) - 1) */
        jmp     .L_check_window

.L_check_window:
        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist
         *       %ecx = nbytes
         *
         * nbytes = out - beg;
         * if (dist <= nbytes) {
         *   from = out - dist;
         *   do {
         *     PUP(out) = PUP(from);
         *   } while (--len > 0) {
         * }
         */

        movl    in_r, in(%esp)          /* save in so from can use it's reg */
        movl    out_r, %eax
        subl    beg(%esp), %eax         /* nbytes = out - beg */

        cmpl    dist_r, %eax
        jb      .L_clip_window          /* if (dist > nbytes) 4.2% */

        movl    len(%esp), %ecx
        movl    out_r, from_r
        subl    dist_r, from_r          /* from = out - dist */

        subl    $3, %ecx
        movb    (from_r), %al
        movb    %al, (out_r)
        movb    1(from_r), %al
        movb    2(from_r), %dl
        addl    $3, from_r
        movb    %al, 1(out_r)
        movb    %dl, 2(out_r)
        addl    $3, out_r
        rep     movsb

        movl    in(%esp), in_r          /* move in back to %esi, toss from */
        jmp     .L_while_test

.align 16,0x90
.L_check_dist_one:
        cmpl    $1, dist_r
        jne     .L_check_window
        cmpl    out_r, beg(%esp)
        je      .L_check_window

        decl    out_r
        movl    len(%esp), %ecx
        movb    (out_r), %al
        subl    $3, %ecx

        movb    %al, 1(out_r)
        movb    %al, 2(out_r)
        movb    %al, 3(out_r)
        addl    $4, out_r
        rep     stosb

        jmp     .L_while_test

.align 16,0x90
.L_test_for_second_level_length:
        /* else if ((op & 64) == 0) {
         *   this = lcode[this.val + (hold & mask[op])];
         * }
         */
        testb   $64, %al
        jnz     .L_test_for_end_of_block  /* if ((op & 64) != 0) */

        movl    $1, %eax
        shll    %cl, %eax
        decl    %eax
        andl    hold_r, %eax            /* eax &= hold */
        addl    %edx, %eax              /* eax += this.val */
        movl    lcode(%esp), %edx       /* edx = lcode */
        movl    (%edx,%eax,4), %eax     /* eax = lcode[val + (hold&mask[op])] */
        jmp     .L_dolen

.align 16,0x90
.L_test_for_second_level_dist:
        /* else if ((op & 64) == 0) {
         *   this = dcode[this.val + (hold & mask[op])];
         * }
         */
        testb   $64, %al
        jnz     .L_invalid_distance_code  /* if ((op & 64) != 0) */

        movl    $1, %eax
        shll    %cl, %eax
        decl    %eax
        andl    hold_r, %eax            /* eax &= hold */
        addl    %edx, %eax              /* eax += this.val */
        movl    dcode(%esp), %edx       /* edx = dcode */
        movl    (%edx,%eax,4), %eax     /* eax = dcode[val + (hold&mask[op])] */
        jmp     .L_dodist

.align 16,0x90
.L_clip_window:
        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist
         *       %ecx = nbytes
         *
         * else {
         *   if (dist > wsize) {
         *     invalid distance
         *   }
         *   from = window;
         *   nbytes = dist - nbytes;
         *   if (write == 0) {
         *     from += wsize - nbytes;
         */
#define nbytes_r %ecx
        movl    %eax, nbytes_r
        movl    wsize(%esp), %eax       /* prepare for dist compare */
        negl    nbytes_r                /* nbytes = -nbytes */
        movl    window(%esp), from_r    /* from = window */

        cmpl    dist_r, %eax
        jb      .L_invalid_distance_too_far /* if (dist > wsize) */

        addl    dist_r, nbytes_r        /* nbytes = dist - nbytes */
        cmpl    $0, write(%esp)
        jne     .L_wrap_around_window   /* if (write != 0) */

        subl    nbytes_r, %eax
        addl    %eax, from_r            /* from += wsize - nbytes */

        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist
         *       %ecx = nbytes, %eax = len
         *
         *     if (nbytes < len) {
         *       len -= nbytes;
         *       do {
         *         PUP(out) = PUP(from);
         *       } while (--nbytes);
         *       from = out - dist;
         *     }
         *   }
         */
#define len_r %eax
        movl    len(%esp), len_r
        cmpl    nbytes_r, len_r
        jbe     .L_do_copy1             /* if (nbytes >= len) */

        subl    nbytes_r, len_r         /* len -= nbytes */
        rep     movsb
        movl    out_r, from_r
        subl    dist_r, from_r          /* from = out - dist */
        jmp     .L_do_copy1

        cmpl    nbytes_r, len_r
        jbe     .L_do_copy1             /* if (nbytes >= len) */

        subl    nbytes_r, len_r         /* len -= nbytes */
        rep     movsb
        movl    out_r, from_r
        subl    dist_r, from_r          /* from = out - dist */
        jmp     .L_do_copy1

.L_wrap_around_window:
        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist
         *       %ecx = nbytes, %eax = write, %eax = len
         *
         *   else if (write < nbytes) {
         *     from += wsize + write - nbytes;
         *     nbytes -= write;
         *     if (nbytes < len) {
         *       len -= nbytes;
         *       do {
         *         PUP(out) = PUP(from);
         *       } while (--nbytes);
         *       from = window;
         *       nbytes = write;
         *       if (nbytes < len) {
         *         len -= nbytes;
         *         do {
         *           PUP(out) = PUP(from);
         *         } while(--nbytes);
         *         from = out - dist;
         *       }
         *     }
         *   }
         */
#define write_r %eax
        movl    write(%esp), write_r
        cmpl    write_r, nbytes_r
        jbe     .L_contiguous_in_window /* if (write >= nbytes) */

        addl    wsize(%esp), from_r
        addl    write_r, from_r
        subl    nbytes_r, from_r        /* from += wsize + write - nbytes */
        subl    write_r, nbytes_r       /* nbytes -= write */
#undef write_r

        movl    len(%esp), len_r
        cmpl    nbytes_r, len_r
        jbe     .L_do_copy1             /* if (nbytes >= len) */

        subl    nbytes_r, len_r         /* len -= nbytes */
        rep     movsb
        movl    window(%esp), from_r    /* from = window */
        movl    write(%esp), nbytes_r   /* nbytes = write */
        cmpl    nbytes_r, len_r
        jbe     .L_do_copy1             /* if (nbytes >= len) */

        subl    nbytes_r, len_r         /* len -= nbytes */
        rep     movsb
        movl    out_r, from_r
        subl    dist_r, from_r          /* from = out - dist */
        jmp     .L_do_copy1

.L_contiguous_in_window:
        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist
         *       %ecx = nbytes, %eax = write, %eax = len
         *
         *   else {
         *     from += write - nbytes;
         *     if (nbytes < len) {
         *       len -= nbytes;
         *       do {
         *         PUP(out) = PUP(from);
         *       } while (--nbytes);
         *       from = out - dist;
         *     }
         *   }
         */
#define write_r %eax
        addl    write_r, from_r
        subl    nbytes_r, from_r        /* from += write - nbytes */
#undef write_r

        movl    len(%esp), len_r
        cmpl    nbytes_r, len_r
        jbe     .L_do_copy1             /* if (nbytes >= len) */

        subl    nbytes_r, len_r         /* len -= nbytes */
        rep     movsb
        movl    out_r, from_r
        subl    dist_r, from_r          /* from = out - dist */

.L_do_copy1:
        /* regs: %esi = from, %esi = in, %ebp = hold, %bl = bits, %edi = out
         *       %eax = len
         *
         *     while (len > 0) {
         *       PUP(out) = PUP(from);
         *       len--;
         *     }
         *   }
         * } while (in < last && out < end);
         */
#undef nbytes_r
#define in_r %esi
        movl    len_r, %ecx
        rep     movsb

        movl    in(%esp), in_r          /* move in back to %esi, toss from */
        jmp     .L_while_test

#undef len_r
#undef dist_r

#endif /* NO_MMX || RUN_TIME_MMX */


/*** MMX code ***/

#if defined( USE_MMX ) || defined( RUN_TIME_MMX )

.align 32,0x90
.L_init_mmx:
        emms

#undef  bits_r
#undef  bitslong_r
#define bitslong_r %ebp
#define hold_mm    %mm0
        movd    %ebp, hold_mm
        movl    %ebx, bitslong_r

#define used_mm   %mm1
#define dmask2_mm %mm2
#define lmask2_mm %mm3
#define lmask_mm  %mm4
#define dmask_mm  %mm5
#define tmp_mm    %mm6

        movd    lmask(%esp), lmask_mm
        movq    lmask_mm, lmask2_mm
        movd    dmask(%esp), dmask_mm
        movq    dmask_mm, dmask2_mm
        pxor    used_mm, used_mm
        movl    lcode(%esp), %ebx       /* ebx = lcode */
        jmp     .L_do_loop_mmx

.align 32,0x90
.L_while_test_mmx:
        /* while (in < last && out < end)
         */
        cmpl    out_r, end(%esp)
        jbe     .L_break_loop           /* if (out >= end) */

        cmpl    in_r, last(%esp)
        jbe     .L_break_loop

.L_do_loop_mmx:
        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */

        cmpl    $32, bitslong_r
        ja      .L_get_length_code_mmx  /* if (32 < bits) */

        movd    bitslong_r, tmp_mm
        movd    (in_r), %mm7
        addl    $4, in_r
        psllq   tmp_mm, %mm7
        addl    $32, bitslong_r
        por     %mm7, hold_mm           /* hold_mm |= *((uint *)in)++ << bits */

.L_get_length_code_mmx:
        pand    hold_mm, lmask_mm
        movd    lmask_mm, %eax
        movq    lmask2_mm, lmask_mm
        movl    (%ebx,%eax,4), %eax     /* eax = lcode[hold & lmask] */

.L_dolen_mmx:
        movzbl  %ah, %ecx               /* ecx = this.bits */
        movd    %ecx, used_mm
        subl    %ecx, bitslong_r        /* bits -= this.bits */

        testb   %al, %al
        jnz     .L_test_for_length_base_mmx /* if (op != 0) 45.7% */

        shrl    $16, %eax               /* output this.val char */
        stosb
        jmp     .L_while_test_mmx

.L_test_for_length_base_mmx:
#define len_r  %edx
        movl    %eax, len_r             /* len = this */
        shrl    $16, len_r              /* len = this.val */

        testb   $16, %al
        jz      .L_test_for_second_level_length_mmx /* if ((op & 16) == 0) 8% */
        andl    $15, %eax               /* op &= 15 */
        jz      .L_decode_distance_mmx  /* if (!op) */

        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */
        movd    %eax, used_mm
        movd    hold_mm, %ecx
        subl    %eax, bitslong_r
        andl    .L_mask(,%eax,4), %ecx
        addl    %ecx, len_r             /* len += hold & mask[op] */

.L_decode_distance_mmx:
        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */

        cmpl    $32, bitslong_r
        ja      .L_get_dist_code_mmx    /* if (32 < bits) */

        movd    bitslong_r, tmp_mm
        movd    (in_r), %mm7
        addl    $4, in_r
        psllq   tmp_mm, %mm7
        addl    $32, bitslong_r
        por     %mm7, hold_mm           /* hold_mm |= *((uint *)in)++ << bits */

.L_get_dist_code_mmx:
        movl    dcode(%esp), %ebx       /* ebx = dcode */
        pand    hold_mm, dmask_mm
        movd    dmask_mm, %eax
        movq    dmask2_mm, dmask_mm
        movl    (%ebx,%eax,4), %eax     /* eax = dcode[hold & lmask] */

.L_dodist_mmx:
#define dist_r %ebx
        movzbl  %ah, %ecx               /* ecx = this.bits */
        movl    %eax, dist_r
        shrl    $16, dist_r             /* dist  = this.val */
        subl    %ecx, bitslong_r        /* bits -= this.bits */
        movd    %ecx, used_mm

        testb   $16, %al                /* if ((op & 16) == 0) */
        jz      .L_test_for_second_level_dist_mmx
        andl    $15, %eax               /* op &= 15 */
        jz      .L_check_dist_one_mmx

.L_add_bits_to_dist_mmx:
        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */
        movd    %eax, used_mm           /* save bit length of current op */
        movd    hold_mm, %ecx           /* get the next bits on input stream */
        subl    %eax, bitslong_r        /* bits -= op bits */
        andl    .L_mask(,%eax,4), %ecx  /* ecx   = hold & mask[op] */
        addl    %ecx, dist_r            /* dist += hold & mask[op] */

.L_check_window_mmx:
        movl    in_r, in(%esp)          /* save in so from can use it's reg */
        movl    out_r, %eax
        subl    beg(%esp), %eax         /* nbytes = out - beg */

        cmpl    dist_r, %eax
        jb      .L_clip_window_mmx      /* if (dist > nbytes) 4.2% */

        movl    len_r, %ecx
        movl    out_r, from_r
        subl    dist_r, from_r          /* from = out - dist */

        subl    $3, %ecx
        movb    (from_r), %al
        movb    %al, (out_r)
        movb    1(from_r), %al
        movb    2(from_r), %dl
        addl    $3, from_r
        movb    %al, 1(out_r)
        movb    %dl, 2(out_r)
        addl    $3, out_r
        rep     movsb

        movl    in(%esp), in_r          /* move in back to %esi, toss from */
        movl    lcode(%esp), %ebx       /* move lcode back to %ebx, toss dist */
        jmp     .L_while_test_mmx

.align 16,0x90
.L_check_dist_one_mmx:
        cmpl    $1, dist_r
        jne     .L_check_window_mmx
        cmpl    out_r, beg(%esp)
        je      .L_check_window_mmx

        decl    out_r
        movl    len_r, %ecx
        movb    (out_r), %al
        subl    $3, %ecx

        movb    %al, 1(out_r)
        movb    %al, 2(out_r)
        movb    %al, 3(out_r)
        addl    $4, out_r
        rep     stosb

        movl    lcode(%esp), %ebx       /* move lcode back to %ebx, toss dist */
        jmp     .L_while_test_mmx

.align 16,0x90
.L_test_for_second_level_length_mmx:
        testb   $64, %al
        jnz     .L_test_for_end_of_block  /* if ((op & 64) != 0) */

        andl    $15, %eax
        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */
        movd    hold_mm, %ecx
        andl    .L_mask(,%eax,4), %ecx
        addl    len_r, %ecx
        movl    (%ebx,%ecx,4), %eax     /* eax = lcode[hold & lmask] */
        jmp     .L_dolen_mmx

.align 16,0x90
.L_test_for_second_level_dist_mmx:
        testb   $64, %al
        jnz     .L_invalid_distance_code  /* if ((op & 64) != 0) */

        andl    $15, %eax
        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */
        movd    hold_mm, %ecx
        andl    .L_mask(,%eax,4), %ecx
        movl    dcode(%esp), %eax       /* ecx = dcode */
        addl    dist_r, %ecx
        movl    (%eax,%ecx,4), %eax     /* eax = lcode[hold & lmask] */
        jmp     .L_dodist_mmx

.align 16,0x90
.L_clip_window_mmx:
#define nbytes_r %ecx
        movl    %eax, nbytes_r
        movl    wsize(%esp), %eax       /* prepare for dist compare */
        negl    nbytes_r                /* nbytes = -nbytes */
        movl    window(%esp), from_r    /* from = window */

        cmpl    dist_r, %eax
        jb      .L_invalid_distance_too_far /* if (dist > wsize) */

        addl    dist_r, nbytes_r        /* nbytes = dist - nbytes */
        cmpl    $0, write(%esp)
        jne     .L_wrap_around_window_mmx /* if (write != 0) */

        subl    nbytes_r, %eax
        addl    %eax, from_r            /* from += wsize - nbytes */

        cmpl    nbytes_r, len_r
        jbe     .L_do_copy1_mmx         /* if (nbytes >= len) */

        subl    nbytes_r, len_r         /* len -= nbytes */
        rep     movsb
        movl    out_r, from_r
        subl    dist_r, from_r          /* from = out - dist */
        jmp     .L_do_copy1_mmx

        cmpl    nbytes_r, len_r
        jbe     .L_do_copy1_mmx         /* if (nbytes >= len) */

        subl    nbytes_r, len_r         /* len -= nbytes */
        rep     movsb
        movl    out_r, from_r
        subl    dist_r, from_r          /* from = out - dist */
        jmp     .L_do_copy1_mmx

.L_wrap_around_window_mmx:
#define write_r %eax
        movl    write(%esp), write_r
        cmpl    write_r, nbytes_r
        jbe     .L_contiguous_in_window_mmx /* if (write >= nbytes) */

        addl    wsize(%esp), from_r
        addl    write_r, from_r
        subl    nbytes_r, from_r        /* from += wsize + write - nbytes */
        subl    write_r, nbytes_r       /* nbytes -= write */
#undef write_r

        cmpl    nbytes_r, len_r
        jbe     .L_do_copy1_mmx         /* if (nbytes >= len) */

        subl    nbytes_r, len_r         /* len -= nbytes */
        rep     movsb
        movl    window(%esp), from_r    /* from = window */
        movl    write(%esp), nbytes_r   /* nbytes = write */
        cmpl    nbytes_r, len_r
        jbe     .L_do_copy1_mmx         /* if (nbytes >= len) */

        subl    nbytes_r, len_r         /* len -= nbytes */
        rep     movsb
        movl    out_r, from_r
        subl    dist_r, from_r          /* from = out - dist */
        jmp     .L_do_copy1_mmx

.L_contiguous_in_window_mmx:
#define write_r %eax
        addl    write_r, from_r
        subl    nbytes_r, from_r        /* from += write - nbytes */
#undef write_r

        cmpl    nbytes_r, len_r
        jbe     .L_do_copy1_mmx         /* if (nbytes >= len) */

        subl    nbytes_r, len_r         /* len -= nbytes */
        rep     movsb
        movl    out_r, from_r
        subl    dist_r, from_r          /* from = out - dist */

.L_do_copy1_mmx:
#undef nbytes_r
#define in_r %esi
        movl    len_r, %ecx
        rep     movsb

        movl    in(%esp), in_r          /* move in back to %esi, toss from */
        movl    lcode(%esp), %ebx       /* move lcode back to %ebx, toss dist */
        jmp     .L_while_test_mmx

#undef hold_r
#undef bitslong_r

#endif /* USE_MMX || RUN_TIME_MMX */


/*** USE_MMX, NO_MMX, and RUNTIME_MMX from here on ***/

.L_invalid_distance_code:
        /* else {
         *   strm->msg = "invalid distance code";
         *   state->mode = BAD;
         * }
         */
        movl    $.L_invalid_distance_code_msg, %ecx
        movl    $INFLATE_MODE_BAD, %edx
        jmp     .L_update_stream_state

.L_test_for_end_of_block:
        /* else if (op & 32) {
         *   state->mode = TYPE;
         *   break;
         * }
         */
        testb   $32, %al
        jz      .L_invalid_literal_length_code  /* if ((op & 32) == 0) */

        movl    $0, %ecx
        movl    $INFLATE_MODE_TYPE, %edx
        jmp     .L_update_stream_state

.L_invalid_literal_length_code:
        /* else {
         *   strm->msg = "invalid literal/length code";
         *   state->mode = BAD;
         * }
         */
        movl    $.L_invalid_literal_length_code_msg, %ecx
        movl    $INFLATE_MODE_BAD, %edx
        jmp     .L_update_stream_state

.L_invalid_distance_too_far:
        /* strm->msg = "invalid distance too far back";
         * state->mode = BAD;
         */
        movl    in(%esp), in_r          /* from_r has in's reg, put in back */
        movl    $.L_invalid_distance_too_far_msg, %ecx
        movl    $INFLATE_MODE_BAD, %edx
        jmp     .L_update_stream_state

.L_update_stream_state:
        /* set strm->msg = %ecx, strm->state->mode = %edx */
        movl    strm_sp(%esp), %eax
        testl   %ecx, %ecx              /* if (msg != NULL) */
        jz      .L_skip_msg
        movl    %ecx, msg_strm(%eax)    /* strm->msg = msg */
.L_skip_msg:
        movl    state_strm(%eax), %eax  /* state = strm->state */
        movl    %edx, mode_state(%eax)  /* state->mode = edx (BAD | TYPE) */
        jmp     .L_break_loop

.align 32,0x90
.L_break_loop:

/*
 * Regs:
 *
 * bits = %ebp when mmx, and in %ebx when non-mmx
 * hold = %hold_mm when mmx, and in %ebp when non-mmx
 * in   = %esi
 * out  = %edi
 */

#if defined( USE_MMX ) || defined( RUN_TIME_MMX )

#if defined( RUN_TIME_MMX )

        cmpl    $DO_USE_MMX, inflate_fast_use_mmx
        jne     .L_update_next_in

#endif /* RUN_TIME_MMX */

        movl    %ebp, %ebx

.L_update_next_in:

#endif

#define strm_r  %eax
#define state_r %edx

        /* len = bits >> 3;
         * in -= len;
         * bits -= len << 3;
         * hold &= (1U << bits) - 1;
         * state->hold = hold;
         * state->bits = bits;
         * strm->next_in = in;
         * strm->next_out = out;
         */
        movl    strm_sp(%esp), strm_r
        movl    %ebx, %ecx
        movl    state_strm(strm_r), state_r
        shrl    $3, %ecx
        subl    %ecx, in_r
        shll    $3, %ecx
        subl    %ecx, %ebx
        movl    out_r, next_out_strm(strm_r)
        movl    %ebx, bits_state(state_r)
        movl    %ebx, %ecx

        leal    buf(%esp), %ebx
        cmpl    %ebx, last(%esp)
        jne     .L_buf_not_used         /* if buf != last */

        subl    %ebx, in_r              /* in -= buf */
        movl    next_in_strm(strm_r), %ebx
        movl    %ebx, last(%esp)        /* last = strm->next_in */
        addl    %ebx, in_r              /* in += strm->next_in */
        movl    avail_in_strm(strm_r), %ebx
        subl    $11, %ebx
        addl    %ebx, last(%esp)    /* last = &strm->next_in[ avail_in - 11 ] */

.L_buf_not_used:
        movl    in_r, next_in_strm(strm_r)

        movl    $1, %ebx
        shll    %cl, %ebx
        decl    %ebx

#if defined( USE_MMX ) || defined( RUN_TIME_MMX )

#if defined( RUN_TIME_MMX )

        cmpl    $DO_USE_MMX, inflate_fast_use_mmx
        jne     .L_update_hold

#endif /* RUN_TIME_MMX */

        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */
        movd    hold_mm, %ebp

        emms

.L_update_hold:

#endif /* USE_MMX || RUN_TIME_MMX */

        andl    %ebx, %ebp
        movl    %ebp, hold_state(state_r)

#define last_r %ebx

        /* strm->avail_in = in < last ? 11 + (last - in) : 11 - (in - last) */
        movl    last(%esp), last_r
        cmpl    in_r, last_r
        jbe     .L_last_is_smaller     /* if (in >= last) */

        subl    in_r, last_r           /* last -= in */
        addl    $11, last_r            /* last += 11 */
        movl    last_r, avail_in_strm(strm_r)
        jmp     .L_fixup_out
.L_last_is_smaller:
        subl    last_r, in_r           /* in -= last */
        negl    in_r                   /* in = -in */
        addl    $11, in_r              /* in += 11 */
        movl    in_r, avail_in_strm(strm_r)

#undef last_r
#define end_r %ebx

.L_fixup_out:
        /* strm->avail_out = out < end ? 257 + (end - out) : 257 - (out - end)*/
        movl    end(%esp), end_r
        cmpl    out_r, end_r
        jbe     .L_end_is_smaller      /* if (out >= end) */

        subl    out_r, end_r           /* end -= out */
        addl    $257, end_r            /* end += 257 */
        movl    end_r, avail_out_strm(strm_r)
        jmp     .L_done
.L_end_is_smaller:
        subl    end_r, out_r           /* out -= end */
        negl    out_r                  /* out = -out */
        addl    $257, out_r            /* out += 257 */
        movl    out_r, avail_out_strm(strm_r)

#undef end_r
#undef strm_r
#undef state_r

.L_done:
        addl    $local_var_size, %esp
        popf
        popl    %ebx
        popl    %ebp
        popl    %esi
        popl    %edi
        ret

#if defined( GAS_ELF )
/* elf info */
.type inflate_fast,@function
.size inflate_fast,.-inflate_fast
#endif

Changes to compat/zlib/contrib/iostream3/zfstream.h.

409
410
411
412
413
414
415
416

417
418
419
420
421
422
423
409
410
411
412
413
414
415

416
417
418
419
420
421
422
423







-
+







 *  This class defines a two-argument manipulator for gzofstream. It is used
 *  as base for the setcompression(int,int) manipulator.
*/
template<typename T1, typename T2>
  class gzomanip2
  {
  public:
    // Allows insertor to peek at internals
    // Allows inserter to peek at internals
    template <typename Ta, typename Tb>
      friend gzofstream&
      operator<<(gzofstream&,
                 const gzomanip2<Ta,Tb>&);

    // Constructor
    gzomanip2(gzofstream& (*f)(gzofstream&, T1, T2),
448
449
450
451
452
453
454
455

456
457
458
459
460
461
462
463
464
465
466
448
449
450
451
452
453
454

455
456
457
458
459
460
461
462
463
464
465
466







-
+











  inline
  gzomanip2<T1,T2>::gzomanip2(gzofstream &(*f)(gzofstream &, T1, T2),
                              T1 v1,
                              T2 v2)
  : func(f), val1(v1), val2(v2)
  { }

// Insertor applies underlying manipulator function to stream
// Inserter applies underlying manipulator function to stream
template<typename T1, typename T2>
  inline gzofstream&
  operator<<(gzofstream& s, const gzomanip2<T1,T2>& m)
  { return (*m.func)(s, m.val1, m.val2); }

// Insert this onto stream to simplify setting of compression level
inline gzomanip2<int,int>
setcompression(int l, int s = Z_DEFAULT_STRATEGY)
{ return gzomanip2<int,int>(&setcompression, l, s); }

#endif // ZFSTREAM_H

Deleted compat/zlib/contrib/masmx64/bld_ml64.bat.

1
2


-
-
ml64.exe /Flinffasx64 /c /Zi inffasx64.asm
ml64.exe /Flgvmat64   /c /Zi gvmat64.asm

Deleted compat/zlib/contrib/masmx64/gvmat64.asm.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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









































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
;uInt longest_match_x64(
;    deflate_state *s,
;    IPos cur_match);                             /* current match */

; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86_64
;  (AMD64 on Athlon 64, Opteron, Phenom
;     and Intel EM64T on Pentium 4 with EM64T, Pentium D, Core 2 Duo, Core I5/I7)
; Copyright (C) 1995-2010 Jean-loup Gailly, Brian Raiter and Gilles Vollant.
;
; File written by Gilles Vollant, by converting to assembly the longest_match
;  from Jean-loup Gailly in deflate.c of zLib and infoZip zip.
;
;  and by taking inspiration on asm686 with masm, optimised assembly code
;        from Brian Raiter, written 1998
;
;  This software is provided 'as-is', without any express or implied
;  warranty.  In no event will the authors be held liable for any damages
;  arising from the use of this software.
;
;  Permission is granted to anyone to use this software for any purpose,
;  including commercial applications, and to alter it and redistribute it
;  freely, subject to the following restrictions:
;
;  1. The origin of this software must not be misrepresented; you must not
;     claim that you wrote the original software. If you use this software
;     in a product, an acknowledgment in the product documentation would be
;     appreciated but is not required.
;  2. Altered source versions must be plainly marked as such, and must not be
;     misrepresented as being the original software
;  3. This notice may not be removed or altered from any source distribution.
;
;
;
;         http://www.zlib.net
;         http://www.winimage.com/zLibDll
;         http://www.muppetlabs.com/~breadbox/software/assembly.html
;
; to compile this file for infozip Zip, I use option:
;   ml64.exe /Flgvmat64 /c /Zi /DINFOZIP gvmat64.asm
;
; to compile this file for zLib, I use option:
;   ml64.exe /Flgvmat64 /c /Zi gvmat64.asm
; Be carrefull to adapt zlib1222add below to your version of zLib
;   (if you use a version of zLib before 1.0.4 or after 1.2.2.2, change
;    value of zlib1222add later)
;
; This file compile with Microsoft Macro Assembler (x64) for AMD64
;
;   ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK
;
;   (you can get Windows WDK with ml64 for AMD64 from
;      http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price)
;


;uInt longest_match(s, cur_match)
;    deflate_state *s;
;    IPos cur_match;                             /* current match */
.code
longest_match PROC


;LocalVarsSize   equ 88
 LocalVarsSize   equ 72

; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12
; free register :  r14,r15
; register can be saved : rsp

 chainlenwmask   equ  rsp + 8 - LocalVarsSize    ; high word: current chain len
                                                 ; low word: s->wmask
;window          equ  rsp + xx - LocalVarsSize   ; local copy of s->window ; stored in r10
;windowbestlen   equ  rsp + xx - LocalVarsSize   ; s->window + bestlen , use r10+r11
;scanstart       equ  rsp + xx - LocalVarsSize   ; first two bytes of string ; stored in r12w
;scanend         equ  rsp + xx - LocalVarsSize   ; last two bytes of string use ebx
;scanalign       equ  rsp + xx - LocalVarsSize   ; dword-misalignment of string r13
;bestlen         equ  rsp + xx - LocalVarsSize   ; size of best match so far -> r11d
;scan            equ  rsp + xx - LocalVarsSize   ; ptr to string wanting match -> r9
IFDEF INFOZIP
ELSE
 nicematch       equ  (rsp + 16 - LocalVarsSize) ; a good enough match size
ENDIF

save_rdi        equ  rsp + 24 - LocalVarsSize
save_rsi        equ  rsp + 32 - LocalVarsSize
save_rbx        equ  rsp + 40 - LocalVarsSize
save_rbp        equ  rsp + 48 - LocalVarsSize
save_r12        equ  rsp + 56 - LocalVarsSize
save_r13        equ  rsp + 64 - LocalVarsSize
;save_r14        equ  rsp + 72 - LocalVarsSize
;save_r15        equ  rsp + 80 - LocalVarsSize


; summary of register usage
; scanend     ebx
; scanendw    bx
; chainlenwmask   edx
; curmatch    rsi
; curmatchd   esi
; windowbestlen   r8
; scanalign   r9
; scanalignd  r9d
; window      r10
; bestlen     r11
; bestlend    r11d
; scanstart   r12d
; scanstartw  r12w
; scan        r13
; nicematch   r14d
; limit       r15
; limitd      r15d
; prev        rcx

;  all the +4 offsets are due to the addition of pending_buf_size (in zlib
;  in the deflate_state structure since the asm code was first written
;  (if you compile with zlib 1.0.4 or older, remove the +4).
;  Note : these value are good with a 8 bytes boundary pack structure


    MAX_MATCH           equ     258
    MIN_MATCH           equ     3
    MIN_LOOKAHEAD       equ     (MAX_MATCH+MIN_MATCH+1)


;;; Offsets for fields in the deflate_state structure. These numbers
;;; are calculated from the definition of deflate_state, with the
;;; assumption that the compiler will dword-align the fields. (Thus,
;;; changing the definition of deflate_state could easily cause this
;;; program to crash horribly, without so much as a warning at
;;; compile time. Sigh.)

;  all the +zlib1222add offsets are due to the addition of fields
;  in zlib in the deflate_state structure since the asm code was first written
;  (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
;  (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
;  if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").


IFDEF INFOZIP

_DATA   SEGMENT
COMM    window_size:DWORD
; WMask ; 7fff
COMM    window:BYTE:010040H
COMM    prev:WORD:08000H
; MatchLen : unused
; PrevMatch : unused
COMM    strstart:DWORD
COMM    match_start:DWORD
; Lookahead : ignore
COMM    prev_length:DWORD ; PrevLen
COMM    max_chain_length:DWORD
COMM    good_match:DWORD
COMM    nice_match:DWORD
prev_ad equ OFFSET prev
window_ad equ OFFSET window
nicematch equ nice_match
_DATA ENDS
WMask equ 07fffh

ELSE

  IFNDEF zlib1222add
    zlib1222add equ 8
  ENDIF
dsWSize         equ 56+zlib1222add+(zlib1222add/2)
dsWMask         equ 64+zlib1222add+(zlib1222add/2)
dsWindow        equ 72+zlib1222add
dsPrev          equ 88+zlib1222add
dsMatchLen      equ 128+zlib1222add
dsPrevMatch     equ 132+zlib1222add
dsStrStart      equ 140+zlib1222add
dsMatchStart    equ 144+zlib1222add
dsLookahead     equ 148+zlib1222add
dsPrevLen       equ 152+zlib1222add
dsMaxChainLen   equ 156+zlib1222add
dsGoodMatch     equ 172+zlib1222add
dsNiceMatch     equ 176+zlib1222add

window_size     equ [ rcx + dsWSize]
WMask           equ [ rcx + dsWMask]
window_ad       equ [ rcx + dsWindow]
prev_ad         equ [ rcx + dsPrev]
strstart        equ [ rcx + dsStrStart]
match_start     equ [ rcx + dsMatchStart]
Lookahead       equ [ rcx + dsLookahead] ; 0ffffffffh on infozip
prev_length     equ [ rcx + dsPrevLen]
max_chain_length equ [ rcx + dsMaxChainLen]
good_match      equ [ rcx + dsGoodMatch]
nice_match      equ [ rcx + dsNiceMatch]
ENDIF

; parameter 1 in r8(deflate state s), param 2 in rdx (cur match)

; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and
; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp
;
; All registers must be preserved across the call, except for
;   rax, rcx, rdx, r8, r9, r10, and r11, which are scratch.



;;; Save registers that the compiler may be using, and adjust esp to
;;; make room for our stack frame.


;;; Retrieve the function arguments. r8d will hold cur_match
;;; throughout the entire function. edx will hold the pointer to the
;;; deflate_state structure during the function's setup (before
;;; entering the main loop.

; parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match)

; this clear high 32 bits of r8, which can be garbage in both r8 and rdx

        mov [save_rdi],rdi
        mov [save_rsi],rsi
        mov [save_rbx],rbx
        mov [save_rbp],rbp
IFDEF INFOZIP
        mov r8d,ecx
ELSE
        mov r8d,edx
ENDIF
        mov [save_r12],r12
        mov [save_r13],r13
;        mov [save_r14],r14
;        mov [save_r15],r15


;;; uInt wmask = s->w_mask;
;;; unsigned chain_length = s->max_chain_length;
;;; if (s->prev_length >= s->good_match) {
;;;     chain_length >>= 2;
;;; }

        mov edi, prev_length
        mov esi, good_match
        mov eax, WMask
        mov ebx, max_chain_length
        cmp edi, esi
        jl  LastMatchGood
        shr ebx, 2
LastMatchGood:

;;; chainlen is decremented once beforehand so that the function can
;;; use the sign flag instead of the zero flag for the exit test.
;;; It is then shifted into the high word, to make room for the wmask
;;; value, which it will always accompany.

        dec ebx
        shl ebx, 16
        or  ebx, eax

;;; on zlib only
;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;

IFDEF INFOZIP
        mov [chainlenwmask], ebx
; on infozip nice_match = [nice_match]
ELSE
        mov eax, nice_match
        mov [chainlenwmask], ebx
        mov r10d, Lookahead
        cmp r10d, eax
        cmovnl r10d, eax
        mov [nicematch],r10d
ENDIF

;;; register Bytef *scan = s->window + s->strstart;
        mov r10, window_ad
        mov ebp, strstart
        lea r13, [r10 + rbp]

;;; Determine how many bytes the scan ptr is off from being
;;; dword-aligned.

         mov r9,r13
         neg r13
         and r13,3

;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
;;;     s->strstart - (IPos)MAX_DIST(s) : NIL;
IFDEF INFOZIP
        mov eax,07efah ; MAX_DIST = (WSIZE-MIN_LOOKAHEAD) (0x8000-(3+8+1))
ELSE
        mov eax, window_size
        sub eax, MIN_LOOKAHEAD
ENDIF
        xor edi,edi
        sub ebp, eax

        mov r11d, prev_length

        cmovng ebp,edi

;;; int best_len = s->prev_length;


;;; Store the sum of s->window + best_len in esi locally, and in esi.

       lea  rsi,[r10+r11]

;;; register ush scan_start = *(ushf*)scan;
;;; register ush scan_end   = *(ushf*)(scan+best_len-1);
;;; Posf *prev = s->prev;

        movzx r12d,word ptr [r9]
        movzx ebx, word ptr [r9 + r11 - 1]

        mov rdi, prev_ad

;;; Jump into the main loop.

        mov edx, [chainlenwmask]

        cmp bx,word ptr [rsi + r8 - 1]
        jz  LookupLoopIsZero

LookupLoop1:
        and r8d, edx

        movzx   r8d, word ptr [rdi + r8*2]
        cmp r8d, ebp
        jbe LeaveNow
        sub edx, 00010000h
        js  LeaveNow

LoopEntry1:
        cmp bx,word ptr [rsi + r8 - 1]
        jz  LookupLoopIsZero

LookupLoop2:
        and r8d, edx

        movzx   r8d, word ptr [rdi + r8*2]
        cmp r8d, ebp
        jbe LeaveNow
        sub edx, 00010000h
        js  LeaveNow

LoopEntry2:
        cmp bx,word ptr [rsi + r8 - 1]
        jz  LookupLoopIsZero

LookupLoop4:
        and r8d, edx

        movzx   r8d, word ptr [rdi + r8*2]
        cmp r8d, ebp
        jbe LeaveNow
        sub edx, 00010000h
        js  LeaveNow

LoopEntry4:

        cmp bx,word ptr [rsi + r8 - 1]
        jnz LookupLoop1
        jmp LookupLoopIsZero


;;; do {
;;;     match = s->window + cur_match;
;;;     if (*(ushf*)(match+best_len-1) != scan_end ||
;;;         *(ushf*)match != scan_start) continue;
;;;     [...]
;;; } while ((cur_match = prev[cur_match & wmask]) > limit
;;;          && --chain_length != 0);
;;;
;;; Here is the inner loop of the function. The function will spend the
;;; majority of its time in this loop, and majority of that time will
;;; be spent in the first ten instructions.
;;;
;;; Within this loop:
;;; ebx = scanend
;;; r8d = curmatch
;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
;;; esi = windowbestlen - i.e., (window + bestlen)
;;; edi = prev
;;; ebp = limit

LookupLoop:
        and r8d, edx

        movzx   r8d, word ptr [rdi + r8*2]
        cmp r8d, ebp
        jbe LeaveNow
        sub edx, 00010000h
        js  LeaveNow

LoopEntry:

        cmp bx,word ptr [rsi + r8 - 1]
        jnz LookupLoop1
LookupLoopIsZero:
        cmp     r12w, word ptr [r10 + r8]
        jnz LookupLoop1


;;; Store the current value of chainlen.
        mov [chainlenwmask], edx

;;; Point edi to the string under scrutiny, and esi to the string we
;;; are hoping to match it up with. In actuality, esi and edi are
;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is
;;; initialized to -(MAX_MATCH_8 - scanalign).

        lea rsi,[r8+r10]
        mov rdx, 0fffffffffffffef8h; -(MAX_MATCH_8)
        lea rsi, [rsi + r13 + 0108h] ;MAX_MATCH_8]
        lea rdi, [r9 + r13 + 0108h] ;MAX_MATCH_8]

        prefetcht1 [rsi+rdx]
        prefetcht1 [rdi+rdx]


;;; Test the strings for equality, 8 bytes at a time. At the end,
;;; adjust rdx so that it is offset to the exact byte that mismatched.
;;;
;;; We already know at this point that the first three bytes of the
;;; strings match each other, and they can be safely passed over before
;;; starting the compare loop. So what this code does is skip over 0-3
;;; bytes, as much as necessary in order to dword-align the edi
;;; pointer. (rsi will still be misaligned three times out of four.)
;;;
;;; It should be confessed that this loop usually does not represent
;;; much of the total running time. Replacing it with a more
;;; straightforward "rep cmpsb" would not drastically degrade
;;; performance.


LoopCmps:
        mov rax, [rsi + rdx]
        xor rax, [rdi + rdx]
        jnz LeaveLoopCmps

        mov rax, [rsi + rdx + 8]
        xor rax, [rdi + rdx + 8]
        jnz LeaveLoopCmps8


        mov rax, [rsi + rdx + 8+8]
        xor rax, [rdi + rdx + 8+8]
        jnz LeaveLoopCmps16

        add rdx,8+8+8

        jnz short LoopCmps
        jmp short LenMaximum
LeaveLoopCmps16: add rdx,8
LeaveLoopCmps8: add rdx,8
LeaveLoopCmps:

        test    eax, 0000FFFFh
        jnz LenLower

        test eax,0ffffffffh

        jnz LenLower32

        add rdx,4
        shr rax,32
        or ax,ax
        jnz LenLower

LenLower32:
        shr eax,16
        add rdx,2
LenLower:   sub al, 1
        adc rdx, 0
;;; Calculate the length of the match. If it is longer than MAX_MATCH,
;;; then automatically accept it as the best possible match and leave.

        lea rax, [rdi + rdx]
        sub rax, r9
        cmp eax, MAX_MATCH
        jge LenMaximum

;;; If the length of the match is not longer than the best match we
;;; have so far, then forget it and return to the lookup loop.
;///////////////////////////////////

        cmp eax, r11d
        jg  LongerMatch

        lea rsi,[r10+r11]

        mov rdi, prev_ad
        mov edx, [chainlenwmask]
        jmp LookupLoop

;;;         s->match_start = cur_match;
;;;         best_len = len;
;;;         if (len >= nice_match) break;
;;;         scan_end = *(ushf*)(scan+best_len-1);

LongerMatch:
        mov r11d, eax
        mov match_start, r8d
        cmp eax, [nicematch]
        jge LeaveNow

        lea rsi,[r10+rax]

        movzx   ebx, word ptr [r9 + rax - 1]
        mov rdi, prev_ad
        mov edx, [chainlenwmask]
        jmp LookupLoop

;;; Accept the current string, with the maximum possible length.

LenMaximum:
        mov r11d,MAX_MATCH
        mov match_start, r8d

;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
;;; return s->lookahead;

LeaveNow:
IFDEF INFOZIP
        mov eax,r11d
ELSE
        mov eax, Lookahead
        cmp r11d, eax
        cmovng eax, r11d
ENDIF

;;; Restore the stack and return from whence we came.


        mov rsi,[save_rsi]
        mov rdi,[save_rdi]
        mov rbx,[save_rbx]
        mov rbp,[save_rbp]
        mov r12,[save_r12]
        mov r13,[save_r13]
;        mov r14,[save_r14]
;        mov r15,[save_r15]


        ret 0
; please don't remove this string !
; Your can freely use gvmat64 in any free or commercial app
; but it is far better don't remove the string in the binary!
    db     0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0
longest_match   ENDP

match_init PROC
  ret 0
match_init ENDP


END

Deleted compat/zlib/contrib/masmx64/inffas8664.c.

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
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


























































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/* inffas8664.c is a hand tuned assembler version of inffast.c - fast decoding
 * version for AMD64 on Windows using Microsoft C compiler
 *
 * Copyright (C) 1995-2003 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 *
 * Copyright (C) 2003 Chris Anderson <christop@charm.net>
 * Please use the copyright conditions above.
 *
 * 2005 - Adaptation to Microsoft C Compiler for AMD64 by Gilles Vollant
 *
 * inffas8664.c call function inffas8664fnc in inffasx64.asm
 *  inffasx64.asm is automatically convert from AMD64 portion of inffas86.c
 *
 * Dec-29-2003 -- I added AMD64 inflate asm support.  This version is also
 * slightly quicker on x86 systems because, instead of using rep movsb to copy
 * data, it uses rep movsw, which moves data in 2-byte chunks instead of single
 * bytes.  I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates
 * from http://fedora.linux.duke.edu/fc1_x86_64
 * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with
 * 1GB ram.  The 64-bit version is about 4% faster than the 32-bit version,
 * when decompressing mozilla-source-1.3.tar.gz.
 *
 * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from
 * the gcc -S output of zlib-1.2.0/inffast.c.  Zlib-1.2.0 is in beta release at
 * the moment.  I have successfully compiled and tested this code with gcc2.96,
 * gcc3.2, icc5.0, msvc6.0.  It is very close to the speed of inffast.S
 * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX
 * enabled.  I will attempt to merge the MMX code into this version.  Newer
 * versions of this and inffast.S can be found at
 * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/
 *
 */

#include <stdio.h>
#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"

/* Mark Adler's comments from inffast.c: */

/*
   Decode literal, length, and distance codes and write out the resulting
   literal and match bytes until either not enough input or output is
   available, an end-of-block is encountered, or a data error is encountered.
   When large enough input and output buffers are supplied to inflate(), for
   example, a 16K input buffer and a 64K output buffer, more than 95% of the
   inflate execution time is spent in this routine.

   Entry assumptions:

        state->mode == LEN
        strm->avail_in >= 6
        strm->avail_out >= 258
        start >= strm->avail_out
        state->bits < 8

   On return, state->mode is one of:

        LEN -- ran out of enough output space or enough available input
        TYPE -- reached end of block code, inflate() to interpret next block
        BAD -- error in block data

   Notes:

    - The maximum input bits used by a length/distance pair is 15 bits for the
      length code, 5 bits for the length extra, 15 bits for the distance code,
      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
      Therefore if strm->avail_in >= 6, then there is enough input to avoid
      checking for available input while decoding.

    - The maximum bytes that a single length/distance pair can output is 258
      bytes, which is the maximum length that can be coded.  inflate_fast()
      requires strm->avail_out >= 258 for each loop to avoid checking for
      output space.
 */



    typedef struct inffast_ar {
/* 64   32                               x86  x86_64 */
/* ar offset                              register */
/*  0    0 */ void *esp;                /* esp save */
/*  8    4 */ void *ebp;                /* ebp save */
/* 16    8 */ unsigned char FAR *in;    /* esi rsi  local strm->next_in */
/* 24   12 */ unsigned char FAR *last;  /*     r9   while in < last */
/* 32   16 */ unsigned char FAR *out;   /* edi rdi  local strm->next_out */
/* 40   20 */ unsigned char FAR *beg;   /*          inflate()'s init next_out */
/* 48   24 */ unsigned char FAR *end;   /*     r10  while out < end */
/* 56   28 */ unsigned char FAR *window;/*          size of window, wsize!=0 */
/* 64   32 */ code const FAR *lcode;    /* ebp rbp  local strm->lencode */
/* 72   36 */ code const FAR *dcode;    /*     r11  local strm->distcode */
/* 80   40 */ size_t /*unsigned long */hold;       /* edx rdx  local strm->hold */
/* 88   44 */ unsigned bits;            /* ebx rbx  local strm->bits */
/* 92   48 */ unsigned wsize;           /*          window size */
/* 96   52 */ unsigned write;           /*          window write index */
/*100   56 */ unsigned lmask;           /*     r12  mask for lcode */
/*104   60 */ unsigned dmask;           /*     r13  mask for dcode */
/*108   64 */ unsigned len;             /*     r14  match length */
/*112   68 */ unsigned dist;            /*     r15  match distance */
/*116   72 */ unsigned status;          /*          set when state chng*/
    } type_ar;
#ifdef ASMINF

void inflate_fast(strm, start)
z_streamp strm;
unsigned start;         /* inflate()'s starting value for strm->avail_out */
{
    struct inflate_state FAR *state;
    type_ar ar;
    void inffas8664fnc(struct inffast_ar * par);



#if (defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )) || (defined(_MSC_VER) && defined(_M_AMD64))
#define PAD_AVAIL_IN 6
#define PAD_AVAIL_OUT 258
#else
#define PAD_AVAIL_IN 5
#define PAD_AVAIL_OUT 257
#endif

    /* copy state to local variables */
    state = (struct inflate_state FAR *)strm->state;

    ar.in = strm->next_in;
    ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN);
    ar.out = strm->next_out;
    ar.beg = ar.out - (start - strm->avail_out);
    ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT);
    ar.wsize = state->wsize;
    ar.write = state->wnext;
    ar.window = state->window;
    ar.hold = state->hold;
    ar.bits = state->bits;
    ar.lcode = state->lencode;
    ar.dcode = state->distcode;
    ar.lmask = (1U << state->lenbits) - 1;
    ar.dmask = (1U << state->distbits) - 1;

    /* decode literals and length/distances until end-of-block or not enough
       input data or output space */

    /* align in on 1/2 hold size boundary */
    while (((size_t)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) {
        ar.hold += (unsigned long)*ar.in++ << ar.bits;
        ar.bits += 8;
    }

    inffas8664fnc(&ar);

    if (ar.status > 1) {
        if (ar.status == 2)
            strm->msg = "invalid literal/length code";
        else if (ar.status == 3)
            strm->msg = "invalid distance code";
        else
            strm->msg = "invalid distance too far back";
        state->mode = BAD;
    }
    else if ( ar.status == 1 ) {
        state->mode = TYPE;
    }

    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
    ar.len = ar.bits >> 3;
    ar.in -= ar.len;
    ar.bits -= ar.len << 3;
    ar.hold &= (1U << ar.bits) - 1;

    /* update state and return */
    strm->next_in = ar.in;
    strm->next_out = ar.out;
    strm->avail_in = (unsigned)(ar.in < ar.last ?
                                PAD_AVAIL_IN + (ar.last - ar.in) :
                                PAD_AVAIL_IN - (ar.in - ar.last));
    strm->avail_out = (unsigned)(ar.out < ar.end ?
                                 PAD_AVAIL_OUT + (ar.end - ar.out) :
                                 PAD_AVAIL_OUT - (ar.out - ar.end));
    state->hold = (unsigned long)ar.hold;
    state->bits = ar.bits;
    return;
}

#endif

Deleted compat/zlib/contrib/masmx64/inffasx64.asm.

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
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
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












































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
; inffasx64.asm is a hand tuned assembler version of inffast.c - fast decoding
; version for AMD64 on Windows using Microsoft C compiler
;
; inffasx64.asm is automatically convert from AMD64 portion of inffas86.c
; inffasx64.asm is called by inffas8664.c, which contain more info.


; to compile this file, I use option
;   ml64.exe /Flinffasx64 /c /Zi inffasx64.asm
;   with Microsoft Macro Assembler (x64) for AMD64
;

; This file compile with Microsoft Macro Assembler (x64) for AMD64
;
;   ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK
;
;   (you can get Windows WDK with ml64 for AMD64 from
;      http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price)
;


.code
inffas8664fnc PROC

; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and
; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp
;
; All registers must be preserved across the call, except for
;   rax, rcx, rdx, r8, r-9, r10, and r11, which are scratch.


	mov [rsp-8],rsi
	mov [rsp-16],rdi
	mov [rsp-24],r12
	mov [rsp-32],r13
	mov [rsp-40],r14
	mov [rsp-48],r15
	mov [rsp-56],rbx

	mov rax,rcx

	mov	[rax+8], rbp       ; /* save regs rbp and rsp */
	mov	[rax], rsp

	mov	rsp, rax          ; /* make rsp point to &ar */

	mov	rsi, [rsp+16]      ; /* rsi  = in */
	mov	rdi, [rsp+32]      ; /* rdi  = out */
	mov	r9, [rsp+24]       ; /* r9   = last */
	mov	r10, [rsp+48]      ; /* r10  = end */
	mov	rbp, [rsp+64]      ; /* rbp  = lcode */
	mov	r11, [rsp+72]      ; /* r11  = dcode */
	mov	rdx, [rsp+80]      ; /* rdx  = hold */
	mov	ebx, [rsp+88]      ; /* ebx  = bits */
	mov	r12d, [rsp+100]    ; /* r12d = lmask */
	mov	r13d, [rsp+104]    ; /* r13d = dmask */
                                          ; /* r14d = len */
                                          ; /* r15d = dist */


	cld
	cmp	r10, rdi
	je	L_one_time           ; /* if only one decode left */
	cmp	r9, rsi

    jne L_do_loop


L_one_time:
	mov	r8, r12           ; /* r8 = lmask */
	cmp	bl, 32
	ja	L_get_length_code_one_time

	lodsd                         ; /* eax = *(uint *)in++ */
	mov	cl, bl            ; /* cl = bits, needs it for shifting */
	add	bl, 32             ; /* bits += 32 */
	shl	rax, cl
	or	rdx, rax          ; /* hold |= *((uint *)in)++ << bits */
	jmp	L_get_length_code_one_time

ALIGN 4
L_while_test:
	cmp	r10, rdi
	jbe	L_break_loop
	cmp	r9, rsi
	jbe	L_break_loop

L_do_loop:
	mov	r8, r12           ; /* r8 = lmask */
	cmp	bl, 32
	ja	L_get_length_code    ; /* if (32 < bits) */

	lodsd                         ; /* eax = *(uint *)in++ */
	mov	cl, bl            ; /* cl = bits, needs it for shifting */
	add	bl, 32             ; /* bits += 32 */
	shl	rax, cl
	or	rdx, rax          ; /* hold |= *((uint *)in)++ << bits */

L_get_length_code:
	and	r8, rdx            ; /* r8 &= hold */
	mov	eax, [rbp+r8*4]  ; /* eax = lcode[hold & lmask] */

	mov	cl, ah            ; /* cl = this.bits */
	sub	bl, ah            ; /* bits -= this.bits */
	shr	rdx, cl           ; /* hold >>= this.bits */

	test	al, al
	jnz	L_test_for_length_base ; /* if (op != 0) 45.7% */

	mov	r8, r12            ; /* r8 = lmask */
	shr	eax, 16            ; /* output this.val char */
	stosb

L_get_length_code_one_time:
	and	r8, rdx            ; /* r8 &= hold */
	mov	eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */

L_dolen:
	mov	cl, ah            ; /* cl = this.bits */
	sub	bl, ah            ; /* bits -= this.bits */
	shr	rdx, cl           ; /* hold >>= this.bits */

	test	al, al
	jnz	L_test_for_length_base ; /* if (op != 0) 45.7% */

	shr	eax, 16            ; /* output this.val char */
	stosb
	jmp	L_while_test

ALIGN 4
L_test_for_length_base:
	mov	r14d, eax         ; /* len = this */
	shr	r14d, 16           ; /* len = this.val */
	mov	cl, al

	test	al, 16
	jz	L_test_for_second_level_length ; /* if ((op & 16) == 0) 8% */
	and	cl, 15             ; /* op &= 15 */
	jz	L_decode_distance    ; /* if (!op) */

L_add_bits_to_len:
	sub	bl, cl
	xor	eax, eax
	inc	eax
	shl	eax, cl
	dec	eax
	and	eax, edx          ; /* eax &= hold */
	shr	rdx, cl
	add	r14d, eax         ; /* len += hold & mask[op] */

L_decode_distance:
	mov	r8, r13           ; /* r8 = dmask */
	cmp	bl, 32
	ja	L_get_distance_code  ; /* if (32 < bits) */

	lodsd                         ; /* eax = *(uint *)in++ */
	mov	cl, bl            ; /* cl = bits, needs it for shifting */
	add	bl, 32             ; /* bits += 32 */
	shl	rax, cl
	or	rdx, rax          ; /* hold |= *((uint *)in)++ << bits */

L_get_distance_code:
	and	r8, rdx           ; /* r8 &= hold */
	mov	eax, [r11+r8*4] ; /* eax = dcode[hold & dmask] */

L_dodist:
	mov	r15d, eax         ; /* dist = this */
	shr	r15d, 16           ; /* dist = this.val */
	mov	cl, ah
	sub	bl, ah            ; /* bits -= this.bits */
	shr	rdx, cl           ; /* hold >>= this.bits */
	mov	cl, al            ; /* cl = this.op */

	test	al, 16             ; /* if ((op & 16) == 0) */
	jz	L_test_for_second_level_dist
	and	cl, 15             ; /* op &= 15 */
	jz	L_check_dist_one

L_add_bits_to_dist:
	sub	bl, cl
	xor	eax, eax
	inc	eax
	shl	eax, cl
	dec	eax                 ; /* (1 << op) - 1 */
	and	eax, edx          ; /* eax &= hold */
	shr	rdx, cl
	add	r15d, eax         ; /* dist += hold & ((1 << op) - 1) */

L_check_window:
	mov	r8, rsi           ; /* save in so from can use it's reg */
	mov	rax, rdi
	sub	rax, [rsp+40]      ; /* nbytes = out - beg */

	cmp	eax, r15d
	jb	L_clip_window        ; /* if (dist > nbytes) 4.2% */

	mov	ecx, r14d         ; /* ecx = len */
	mov	rsi, rdi
	sub	rsi, r15          ; /* from = out - dist */

	sar	ecx, 1
	jnc	L_copy_two           ; /* if len % 2 == 0 */

	rep     movsw
	mov	al, [rsi]
	mov	[rdi], al
	inc	rdi

	mov	rsi, r8           ; /* move in back to %rsi, toss from */
	jmp	L_while_test

L_copy_two:
	rep     movsw
	mov	rsi, r8           ; /* move in back to %rsi, toss from */
	jmp	L_while_test

ALIGN 4
L_check_dist_one:
	cmp	r15d, 1            ; /* if dist 1, is a memset */
	jne	L_check_window
	cmp	[rsp+40], rdi      ; /* if out == beg, outside window */
	je	L_check_window

	mov	ecx, r14d         ; /* ecx = len */
	mov	al, [rdi-1]
	mov	ah, al

	sar	ecx, 1
	jnc	L_set_two
	mov	[rdi], al
	inc	rdi

L_set_two:
	rep     stosw
	jmp	L_while_test

ALIGN 4
L_test_for_second_level_length:
	test	al, 64
	jnz	L_test_for_end_of_block ; /* if ((op & 64) != 0) */

	xor	eax, eax
	inc	eax
	shl	eax, cl
	dec	eax
	and	eax, edx         ; /* eax &= hold */
	add	eax, r14d        ; /* eax += len */
	mov	eax, [rbp+rax*4] ; /* eax = lcode[val+(hold&mask[op])]*/
	jmp	L_dolen

ALIGN 4
L_test_for_second_level_dist:
	test	al, 64
	jnz	L_invalid_distance_code ; /* if ((op & 64) != 0) */

	xor	eax, eax
	inc	eax
	shl	eax, cl
	dec	eax
	and	eax, edx         ; /* eax &= hold */
	add	eax, r15d        ; /* eax += dist */
	mov	eax, [r11+rax*4] ; /* eax = dcode[val+(hold&mask[op])]*/
	jmp	L_dodist

ALIGN 4
L_clip_window:
	mov	ecx, eax         ; /* ecx = nbytes */
	mov	eax, [rsp+92]     ; /* eax = wsize, prepare for dist cmp */
	neg	ecx                ; /* nbytes = -nbytes */

	cmp	eax, r15d
	jb	L_invalid_distance_too_far ; /* if (dist > wsize) */

	add	ecx, r15d         ; /* nbytes = dist - nbytes */
	cmp	dword ptr [rsp+96], 0
	jne	L_wrap_around_window ; /* if (write != 0) */

	mov	rsi, [rsp+56]     ; /* from  = window */
	sub	eax, ecx         ; /* eax  -= nbytes */
	add	rsi, rax         ; /* from += wsize - nbytes */

	mov	eax, r14d        ; /* eax = len */
	cmp	r14d, ecx
	jbe	L_do_copy           ; /* if (nbytes >= len) */

	sub	eax, ecx         ; /* eax -= nbytes */
	rep     movsb
	mov	rsi, rdi
	sub	rsi, r15         ; /* from = &out[ -dist ] */
	jmp	L_do_copy

ALIGN 4
L_wrap_around_window:
	mov	eax, [rsp+96]     ; /* eax = write */
	cmp	ecx, eax
	jbe	L_contiguous_in_window ; /* if (write >= nbytes) */

	mov	esi, [rsp+92]     ; /* from  = wsize */
	add	rsi, [rsp+56]     ; /* from += window */
	add	rsi, rax         ; /* from += write */
	sub	rsi, rcx         ; /* from -= nbytes */
	sub	ecx, eax         ; /* nbytes -= write */

	mov	eax, r14d        ; /* eax = len */
	cmp	eax, ecx
	jbe	L_do_copy           ; /* if (nbytes >= len) */

	sub	eax, ecx         ; /* len -= nbytes */
	rep     movsb
	mov	rsi, [rsp+56]     ; /* from = window */
	mov	ecx, [rsp+96]     ; /* nbytes = write */
	cmp	eax, ecx
	jbe	L_do_copy           ; /* if (nbytes >= len) */

	sub	eax, ecx         ; /* len -= nbytes */
	rep     movsb
	mov	rsi, rdi
	sub	rsi, r15         ; /* from = out - dist */
	jmp	L_do_copy

ALIGN 4
L_contiguous_in_window:
	mov	rsi, [rsp+56]     ; /* rsi = window */
	add	rsi, rax
	sub	rsi, rcx         ; /* from += write - nbytes */

	mov	eax, r14d        ; /* eax = len */
	cmp	eax, ecx
	jbe	L_do_copy           ; /* if (nbytes >= len) */

	sub	eax, ecx         ; /* len -= nbytes */
	rep     movsb
	mov	rsi, rdi
	sub	rsi, r15         ; /* from = out - dist */
	jmp	L_do_copy           ; /* if (nbytes >= len) */

ALIGN 4
L_do_copy:
	mov	ecx, eax         ; /* ecx = len */
	rep     movsb

	mov	rsi, r8          ; /* move in back to %esi, toss from */
	jmp	L_while_test

L_test_for_end_of_block:
	test	al, 32
	jz	L_invalid_literal_length_code
	mov	dword ptr [rsp+116], 1
	jmp	L_break_loop_with_status

L_invalid_literal_length_code:
	mov	dword ptr [rsp+116], 2
	jmp	L_break_loop_with_status

L_invalid_distance_code:
	mov	dword ptr [rsp+116], 3
	jmp	L_break_loop_with_status

L_invalid_distance_too_far:
	mov	dword ptr [rsp+116], 4
	jmp	L_break_loop_with_status

L_break_loop:
	mov	dword ptr [rsp+116], 0

L_break_loop_with_status:
; /* put in, out, bits, and hold back into ar and pop esp */
	mov	[rsp+16], rsi     ; /* in */
	mov	[rsp+32], rdi     ; /* out */
	mov	[rsp+88], ebx     ; /* bits */
	mov	[rsp+80], rdx     ; /* hold */

	mov	rax, [rsp]       ; /* restore rbp and rsp */
	mov	rbp, [rsp+8]
	mov	rsp, rax



	mov rsi,[rsp-8]
	mov rdi,[rsp-16]
	mov r12,[rsp-24]
	mov r13,[rsp-32]
	mov r14,[rsp-40]
	mov r15,[rsp-48]
	mov rbx,[rsp-56]

    ret 0
;          :
;          : "m" (ar)
;          : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi",
;            "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
;    );

inffas8664fnc 	ENDP
;_TEXT	ENDS
END

Deleted compat/zlib/contrib/masmx64/readme.txt.

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
30
31































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Summary
-------
This directory contains ASM implementations of the functions
longest_match() and inflate_fast(), for 64 bits x86 (both AMD64 and Intel EM64t),
for use with Microsoft Macro Assembler (x64) for AMD64 and Microsoft C++ 64 bits.

gvmat64.asm is written by Gilles Vollant (2005), by using Brian Raiter 686/32 bits
   assembly optimized version from Jean-loup Gailly original longest_match function

inffasx64.asm and inffas8664.c were written by Chris Anderson, by optimizing
   original function from Mark Adler

Use instructions
----------------
Assemble the .asm files using MASM and put the object files into the zlib source
directory.  You can also get object files here:

     http://www.winimage.com/zLibDll/zlib124_masm_obj.zip

define ASMV and ASMINF in your project. Include inffas8664.c in your source tree,
and inffasx64.obj and gvmat64.obj as object to link.


Build instructions
------------------
run bld_64.bat with Microsoft Macro Assembler (x64) for AMD64 (ml64.exe)

ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK

You can get Windows 2003 server DDK with ml64 and cl for AMD64 from
  http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)

Deleted compat/zlib/contrib/masmx86/bld_ml32.bat.

1
2


-
-
ml /coff /Zi /c /Flmatch686.lst match686.asm
ml /coff /Zi /c /Flinffas32.lst inffas32.asm

Deleted compat/zlib/contrib/masmx86/inffas32.asm.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
;/* inffas32.asm is a hand tuned assembler version of inffast.c -- fast decoding
; *
; * inffas32.asm is derivated from inffas86.c, with translation of assembly code
; *
; * Copyright (C) 1995-2003 Mark Adler
; * For conditions of distribution and use, see copyright notice in zlib.h
; *
; * Copyright (C) 2003 Chris Anderson <christop@charm.net>
; * Please use the copyright conditions above.
; *
; * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from
; * the gcc -S output of zlib-1.2.0/inffast.c.  Zlib-1.2.0 is in beta release at
; * the moment.  I have successfully compiled and tested this code with gcc2.96,
; * gcc3.2, icc5.0, msvc6.0.  It is very close to the speed of inffast.S
; * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX
; * enabled.  I will attempt to merge the MMX code into this version.  Newer
; * versions of this and inffast.S can be found at
; * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/
; *
; * 2005 : modification by Gilles Vollant
; */
; For Visual C++ 4.x and higher and ML 6.x and higher
;   ml.exe is in directory \MASM611C of Win95 DDK
;   ml.exe is also distributed in http://www.masm32.com/masmdl.htm
;    and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/
;
;
;   compile with command line option
;   ml  /coff /Zi /c /Flinffas32.lst inffas32.asm

;   if you define NO_GZIP (see inflate.h), compile with
;   ml  /coff /Zi /c /Flinffas32.lst /DNO_GUNZIP inffas32.asm


; zlib122sup is 0 fort zlib 1.2.2.1 and lower
; zlib122sup is 8 fort zlib 1.2.2.2 and more (with addition of dmax and head
;        in inflate_state in inflate.h)
zlib1222sup      equ    8


IFDEF GUNZIP
  INFLATE_MODE_TYPE    equ 11
  INFLATE_MODE_BAD     equ 26
ELSE
  IFNDEF NO_GUNZIP
    INFLATE_MODE_TYPE    equ 11
    INFLATE_MODE_BAD     equ 26
  ELSE
    INFLATE_MODE_TYPE    equ 3
    INFLATE_MODE_BAD     equ 17
  ENDIF
ENDIF


; 75 "inffast.S"
;FILE "inffast.S"

;;;GLOBAL _inflate_fast

;;;SECTION .text



	.586p
	.mmx

	name	inflate_fast_x86
	.MODEL	FLAT

_DATA			segment
inflate_fast_use_mmx:
	dd	1


_TEXT			segment



ALIGN 4
	db	'Fast decoding Code from Chris Anderson'
	db	0

ALIGN 4
invalid_literal_length_code_msg:
	db	'invalid literal/length code'
	db	0

ALIGN 4
invalid_distance_code_msg:
	db	'invalid distance code'
	db	0

ALIGN 4
invalid_distance_too_far_msg:
	db	'invalid distance too far back'
	db	0


ALIGN 4
inflate_fast_mask:
dd	0
dd	1
dd	3
dd	7
dd	15
dd	31
dd	63
dd	127
dd	255
dd	511
dd	1023
dd	2047
dd	4095
dd	8191
dd	16383
dd	32767
dd	65535
dd	131071
dd	262143
dd	524287
dd	1048575
dd	2097151
dd	4194303
dd	8388607
dd	16777215
dd	33554431
dd	67108863
dd	134217727
dd	268435455
dd	536870911
dd	1073741823
dd	2147483647
dd	4294967295


mode_state	 equ	0	;/* state->mode	*/
wsize_state	 equ	(32+zlib1222sup)	;/* state->wsize */
write_state	 equ	(36+4+zlib1222sup)	;/* state->write */
window_state	 equ	(40+4+zlib1222sup)	;/* state->window */
hold_state	 equ	(44+4+zlib1222sup)	;/* state->hold	*/
bits_state	 equ	(48+4+zlib1222sup)	;/* state->bits	*/
lencode_state	 equ	(64+4+zlib1222sup)	;/* state->lencode */
distcode_state	 equ	(68+4+zlib1222sup)	;/* state->distcode */
lenbits_state	 equ	(72+4+zlib1222sup)	;/* state->lenbits */
distbits_state	 equ	(76+4+zlib1222sup)	;/* state->distbits */


;;SECTION .text
; 205 "inffast.S"
;GLOBAL	inflate_fast_use_mmx

;SECTION .data


; GLOBAL inflate_fast_use_mmx:object
;.size inflate_fast_use_mmx, 4
; 226 "inffast.S"
;SECTION .text

ALIGN 4
_inflate_fast proc near
.FPO (16, 4, 0, 0, 1, 0)
	push  edi
	push  esi
	push  ebp
	push  ebx
	pushfd
	sub  esp,64
	cld




	mov  esi, [esp+88]
	mov  edi, [esi+28]







	mov  edx, [esi+4]
	mov  eax, [esi+0]

	add  edx,eax
	sub  edx,11

	mov  [esp+44],eax
	mov  [esp+20],edx

	mov  ebp, [esp+92]
	mov  ecx, [esi+16]
	mov  ebx, [esi+12]

	sub  ebp,ecx
	neg  ebp
	add  ebp,ebx

	sub  ecx,257
	add  ecx,ebx

	mov  [esp+60],ebx
	mov  [esp+40],ebp
	mov  [esp+16],ecx
; 285 "inffast.S"
	mov  eax, [edi+lencode_state]
	mov  ecx, [edi+distcode_state]

	mov  [esp+8],eax
	mov  [esp+12],ecx

	mov  eax,1
	mov  ecx, [edi+lenbits_state]
	shl  eax,cl
	dec  eax
	mov  [esp+0],eax

	mov  eax,1
	mov  ecx, [edi+distbits_state]
	shl  eax,cl
	dec  eax
	mov  [esp+4],eax

	mov  eax, [edi+wsize_state]
	mov  ecx, [edi+write_state]
	mov  edx, [edi+window_state]

	mov  [esp+52],eax
	mov  [esp+48],ecx
	mov  [esp+56],edx

	mov  ebp, [edi+hold_state]
	mov  ebx, [edi+bits_state]
; 321 "inffast.S"
	mov  esi, [esp+44]
	mov  ecx, [esp+20]
	cmp  ecx,esi
	ja   L_align_long

	add  ecx,11
	sub  ecx,esi
	mov  eax,12
	sub  eax,ecx
	lea  edi, [esp+28]
	rep movsb
	mov  ecx,eax
	xor  eax,eax
	rep stosb
	lea  esi, [esp+28]
	mov  [esp+20],esi
	jmp  L_is_aligned


L_align_long:
	test  esi,3
	jz   L_is_aligned
	xor  eax,eax
	mov  al, [esi]
	inc  esi
	mov  ecx,ebx
	add  ebx,8
	shl  eax,cl
	or  ebp,eax
	jmp L_align_long

L_is_aligned:
	mov  edi, [esp+60]
; 366 "inffast.S"
L_check_mmx:
	cmp  dword ptr [inflate_fast_use_mmx],2
	je   L_init_mmx
	ja   L_do_loop

	push  eax
	push  ebx
	push  ecx
	push  edx
	pushfd
	mov  eax, [esp]
	xor  dword ptr [esp],0200000h




	popfd
	pushfd
	pop  edx
	xor  edx,eax
	jz   L_dont_use_mmx
	xor  eax,eax
	cpuid
	cmp  ebx,0756e6547h
	jne  L_dont_use_mmx
	cmp  ecx,06c65746eh
	jne  L_dont_use_mmx
	cmp  edx,049656e69h
	jne  L_dont_use_mmx
	mov  eax,1
	cpuid
	shr  eax,8
	and  eax,15
	cmp  eax,6
	jne  L_dont_use_mmx
	test  edx,0800000h
	jnz  L_use_mmx
	jmp  L_dont_use_mmx
L_use_mmx:
	mov  dword ptr [inflate_fast_use_mmx],2
	jmp  L_check_mmx_pop
L_dont_use_mmx:
	mov  dword ptr [inflate_fast_use_mmx],3
L_check_mmx_pop:
	pop  edx
	pop  ecx
	pop  ebx
	pop  eax
	jmp  L_check_mmx
; 426 "inffast.S"
ALIGN 4
L_do_loop:
; 437 "inffast.S"
	cmp  bl,15
	ja   L_get_length_code

	xor  eax,eax
	lodsw
	mov  cl,bl
	add  bl,16
	shl  eax,cl
	or  ebp,eax

L_get_length_code:
	mov  edx, [esp+0]
	mov  ecx, [esp+8]
	and  edx,ebp
	mov  eax, [ecx+edx*4]

L_dolen:






	mov  cl,ah
	sub  bl,ah
	shr  ebp,cl






	test  al,al
	jnz   L_test_for_length_base

	shr  eax,16
	stosb

L_while_test:


	cmp  [esp+16],edi
	jbe  L_break_loop

	cmp  [esp+20],esi
	ja   L_do_loop
	jmp  L_break_loop

L_test_for_length_base:
; 502 "inffast.S"
	mov  edx,eax
	shr  edx,16
	mov  cl,al

	test  al,16
	jz   L_test_for_second_level_length
	and  cl,15
	jz   L_save_len
	cmp  bl,cl
	jae  L_add_bits_to_len

	mov  ch,cl
	xor  eax,eax
	lodsw
	mov  cl,bl
	add  bl,16
	shl  eax,cl
	or  ebp,eax
	mov  cl,ch

L_add_bits_to_len:
	mov  eax,1
	shl  eax,cl
	dec  eax
	sub  bl,cl
	and  eax,ebp
	shr  ebp,cl
	add  edx,eax

L_save_len:
	mov  [esp+24],edx


L_decode_distance:
; 549 "inffast.S"
	cmp  bl,15
	ja   L_get_distance_code

	xor  eax,eax
	lodsw
	mov  cl,bl
	add  bl,16
	shl  eax,cl
	or  ebp,eax

L_get_distance_code:
	mov  edx, [esp+4]
	mov  ecx, [esp+12]
	and  edx,ebp
	mov  eax, [ecx+edx*4]


L_dodist:
	mov  edx,eax
	shr  edx,16
	mov  cl,ah
	sub  bl,ah
	shr  ebp,cl
; 584 "inffast.S"
	mov  cl,al

	test  al,16
	jz  L_test_for_second_level_dist
	and  cl,15
	jz  L_check_dist_one
	cmp  bl,cl
	jae  L_add_bits_to_dist

	mov  ch,cl
	xor  eax,eax
	lodsw
	mov  cl,bl
	add  bl,16
	shl  eax,cl
	or  ebp,eax
	mov  cl,ch

L_add_bits_to_dist:
	mov  eax,1
	shl  eax,cl
	dec  eax
	sub  bl,cl
	and  eax,ebp
	shr  ebp,cl
	add  edx,eax
	jmp  L_check_window

L_check_window:
; 625 "inffast.S"
	mov  [esp+44],esi
	mov  eax,edi
	sub  eax, [esp+40]

	cmp  eax,edx
	jb   L_clip_window

	mov  ecx, [esp+24]
	mov  esi,edi
	sub  esi,edx

	sub  ecx,3
	mov  al, [esi]
	mov  [edi],al
	mov  al, [esi+1]
	mov  dl, [esi+2]
	add  esi,3
	mov  [edi+1],al
	mov  [edi+2],dl
	add  edi,3
	rep movsb

	mov  esi, [esp+44]
	jmp  L_while_test

ALIGN 4
L_check_dist_one:
	cmp  edx,1
	jne  L_check_window
	cmp  [esp+40],edi
	je  L_check_window

	dec  edi
	mov  ecx, [esp+24]
	mov  al, [edi]
	sub  ecx,3

	mov  [edi+1],al
	mov  [edi+2],al
	mov  [edi+3],al
	add  edi,4
	rep stosb

	jmp  L_while_test

ALIGN 4
L_test_for_second_level_length:




	test  al,64
	jnz   L_test_for_end_of_block

	mov  eax,1
	shl  eax,cl
	dec  eax
	and  eax,ebp
	add  eax,edx
	mov  edx, [esp+8]
	mov  eax, [edx+eax*4]
	jmp  L_dolen

ALIGN 4
L_test_for_second_level_dist:




	test  al,64
	jnz   L_invalid_distance_code

	mov  eax,1
	shl  eax,cl
	dec  eax
	and  eax,ebp
	add  eax,edx
	mov  edx, [esp+12]
	mov  eax, [edx+eax*4]
	jmp  L_dodist

ALIGN 4
L_clip_window:
; 721 "inffast.S"
	mov  ecx,eax
	mov  eax, [esp+52]
	neg  ecx
	mov  esi, [esp+56]

	cmp  eax,edx
	jb   L_invalid_distance_too_far

	add  ecx,edx
	cmp  dword ptr [esp+48],0
	jne  L_wrap_around_window

	sub  eax,ecx
	add  esi,eax
; 749 "inffast.S"
	mov  eax, [esp+24]
	cmp  eax,ecx
	jbe  L_do_copy1

	sub  eax,ecx
	rep movsb
	mov  esi,edi
	sub  esi,edx
	jmp  L_do_copy1

	cmp  eax,ecx
	jbe  L_do_copy1

	sub  eax,ecx
	rep movsb
	mov  esi,edi
	sub  esi,edx
	jmp  L_do_copy1

L_wrap_around_window:
; 793 "inffast.S"
	mov  eax, [esp+48]
	cmp  ecx,eax
	jbe  L_contiguous_in_window

	add  esi, [esp+52]
	add  esi,eax
	sub  esi,ecx
	sub  ecx,eax


	mov  eax, [esp+24]
	cmp  eax,ecx
	jbe  L_do_copy1

	sub  eax,ecx
	rep movsb
	mov  esi, [esp+56]
	mov  ecx, [esp+48]
	cmp  eax,ecx
	jbe  L_do_copy1

	sub  eax,ecx
	rep movsb
	mov  esi,edi
	sub  esi,edx
	jmp  L_do_copy1

L_contiguous_in_window:
; 836 "inffast.S"
	add  esi,eax
	sub  esi,ecx


	mov  eax, [esp+24]
	cmp  eax,ecx
	jbe  L_do_copy1

	sub  eax,ecx
	rep movsb
	mov  esi,edi
	sub  esi,edx

L_do_copy1:
; 862 "inffast.S"
	mov  ecx,eax
	rep movsb

	mov  esi, [esp+44]
	jmp  L_while_test
; 878 "inffast.S"
ALIGN 4
L_init_mmx:
	emms





	movd mm0,ebp
	mov  ebp,ebx
; 896 "inffast.S"
	movd mm4,dword ptr [esp+0]
	movq mm3,mm4
	movd mm5,dword ptr [esp+4]
	movq mm2,mm5
	pxor mm1,mm1
	mov  ebx, [esp+8]
	jmp  L_do_loop_mmx

ALIGN 4
L_do_loop_mmx:
	psrlq mm0,mm1

	cmp  ebp,32
	ja  L_get_length_code_mmx

	movd mm6,ebp
	movd mm7,dword ptr [esi]
	add  esi,4
	psllq mm7,mm6
	add  ebp,32
	por mm0,mm7

L_get_length_code_mmx:
	pand mm4,mm0
	movd eax,mm4
	movq mm4,mm3
	mov  eax, [ebx+eax*4]

L_dolen_mmx:
	movzx  ecx,ah
	movd mm1,ecx
	sub  ebp,ecx

	test  al,al
	jnz L_test_for_length_base_mmx

	shr  eax,16
	stosb

L_while_test_mmx:


	cmp  [esp+16],edi
	jbe L_break_loop

	cmp  [esp+20],esi
	ja L_do_loop_mmx
	jmp L_break_loop

L_test_for_length_base_mmx:

	mov  edx,eax
	shr  edx,16

	test  al,16
	jz  L_test_for_second_level_length_mmx
	and  eax,15
	jz L_decode_distance_mmx

	psrlq mm0,mm1
	movd mm1,eax
	movd ecx,mm0
	sub  ebp,eax
	and  ecx, [inflate_fast_mask+eax*4]
	add  edx,ecx

L_decode_distance_mmx:
	psrlq mm0,mm1

	cmp  ebp,32
	ja L_get_dist_code_mmx

	movd mm6,ebp
	movd mm7,dword ptr [esi]
	add  esi,4
	psllq mm7,mm6
	add  ebp,32
	por mm0,mm7

L_get_dist_code_mmx:
	mov  ebx, [esp+12]
	pand mm5,mm0
	movd eax,mm5
	movq mm5,mm2
	mov  eax, [ebx+eax*4]

L_dodist_mmx:

	movzx  ecx,ah
	mov  ebx,eax
	shr  ebx,16
	sub  ebp,ecx
	movd mm1,ecx

	test  al,16
	jz L_test_for_second_level_dist_mmx
	and  eax,15
	jz L_check_dist_one_mmx

L_add_bits_to_dist_mmx:
	psrlq mm0,mm1
	movd mm1,eax
	movd ecx,mm0
	sub  ebp,eax
	and  ecx, [inflate_fast_mask+eax*4]
	add  ebx,ecx

L_check_window_mmx:
	mov  [esp+44],esi
	mov  eax,edi
	sub  eax, [esp+40]

	cmp  eax,ebx
	jb L_clip_window_mmx

	mov  ecx,edx
	mov  esi,edi
	sub  esi,ebx

	sub  ecx,3
	mov  al, [esi]
	mov  [edi],al
	mov  al, [esi+1]
	mov  dl, [esi+2]
	add  esi,3
	mov  [edi+1],al
	mov  [edi+2],dl
	add  edi,3
	rep movsb

	mov  esi, [esp+44]
	mov  ebx, [esp+8]
	jmp  L_while_test_mmx

ALIGN 4
L_check_dist_one_mmx:
	cmp  ebx,1
	jne  L_check_window_mmx
	cmp  [esp+40],edi
	je   L_check_window_mmx

	dec  edi
	mov  ecx,edx
	mov  al, [edi]
	sub  ecx,3

	mov  [edi+1],al
	mov  [edi+2],al
	mov  [edi+3],al
	add  edi,4
	rep stosb

	mov  ebx, [esp+8]
	jmp  L_while_test_mmx

ALIGN 4
L_test_for_second_level_length_mmx:
	test  al,64
	jnz L_test_for_end_of_block

	and  eax,15
	psrlq mm0,mm1
	movd ecx,mm0
	and  ecx, [inflate_fast_mask+eax*4]
	add  ecx,edx
	mov  eax, [ebx+ecx*4]
	jmp L_dolen_mmx

ALIGN 4
L_test_for_second_level_dist_mmx:
	test  al,64
	jnz L_invalid_distance_code

	and  eax,15
	psrlq mm0,mm1
	movd ecx,mm0
	and  ecx, [inflate_fast_mask+eax*4]
	mov  eax, [esp+12]
	add  ecx,ebx
	mov  eax, [eax+ecx*4]
	jmp  L_dodist_mmx

ALIGN 4
L_clip_window_mmx:

	mov  ecx,eax
	mov  eax, [esp+52]
	neg  ecx
	mov  esi, [esp+56]

	cmp  eax,ebx
	jb  L_invalid_distance_too_far

	add  ecx,ebx
	cmp  dword ptr [esp+48],0
	jne  L_wrap_around_window_mmx

	sub  eax,ecx
	add  esi,eax

	cmp  edx,ecx
	jbe  L_do_copy1_mmx

	sub  edx,ecx
	rep movsb
	mov  esi,edi
	sub  esi,ebx
	jmp  L_do_copy1_mmx

	cmp  edx,ecx
	jbe  L_do_copy1_mmx

	sub  edx,ecx
	rep movsb
	mov  esi,edi
	sub  esi,ebx
	jmp  L_do_copy1_mmx

L_wrap_around_window_mmx:

	mov  eax, [esp+48]
	cmp  ecx,eax
	jbe  L_contiguous_in_window_mmx

	add  esi, [esp+52]
	add  esi,eax
	sub  esi,ecx
	sub  ecx,eax


	cmp  edx,ecx
	jbe  L_do_copy1_mmx

	sub  edx,ecx
	rep movsb
	mov  esi, [esp+56]
	mov  ecx, [esp+48]
	cmp  edx,ecx
	jbe  L_do_copy1_mmx

	sub  edx,ecx
	rep movsb
	mov  esi,edi
	sub  esi,ebx
	jmp  L_do_copy1_mmx

L_contiguous_in_window_mmx:

	add  esi,eax
	sub  esi,ecx


	cmp  edx,ecx
	jbe  L_do_copy1_mmx

	sub  edx,ecx
	rep movsb
	mov  esi,edi
	sub  esi,ebx

L_do_copy1_mmx:


	mov  ecx,edx
	rep movsb

	mov  esi, [esp+44]
	mov  ebx, [esp+8]
	jmp  L_while_test_mmx
; 1174 "inffast.S"
L_invalid_distance_code:





	mov  ecx, invalid_distance_code_msg
	mov  edx,INFLATE_MODE_BAD
	jmp  L_update_stream_state

L_test_for_end_of_block:





	test  al,32
	jz  L_invalid_literal_length_code

	mov  ecx,0
	mov  edx,INFLATE_MODE_TYPE
	jmp  L_update_stream_state

L_invalid_literal_length_code:





	mov  ecx, invalid_literal_length_code_msg
	mov  edx,INFLATE_MODE_BAD
	jmp  L_update_stream_state

L_invalid_distance_too_far:



	mov  esi, [esp+44]
	mov  ecx, invalid_distance_too_far_msg
	mov  edx,INFLATE_MODE_BAD
	jmp  L_update_stream_state

L_update_stream_state:

	mov  eax, [esp+88]
	test  ecx,ecx
	jz  L_skip_msg
	mov  [eax+24],ecx
L_skip_msg:
	mov  eax, [eax+28]
	mov  [eax+mode_state],edx
	jmp  L_break_loop

ALIGN 4
L_break_loop:
; 1243 "inffast.S"
	cmp  dword ptr [inflate_fast_use_mmx],2
	jne  L_update_next_in



	mov  ebx,ebp

L_update_next_in:
; 1266 "inffast.S"
	mov  eax, [esp+88]
	mov  ecx,ebx
	mov  edx, [eax+28]
	shr  ecx,3
	sub  esi,ecx
	shl  ecx,3
	sub  ebx,ecx
	mov  [eax+12],edi
	mov  [edx+bits_state],ebx
	mov  ecx,ebx

	lea  ebx, [esp+28]
	cmp  [esp+20],ebx
	jne  L_buf_not_used

	sub  esi,ebx
	mov  ebx, [eax+0]
	mov  [esp+20],ebx
	add  esi,ebx
	mov  ebx, [eax+4]
	sub  ebx,11
	add  [esp+20],ebx

L_buf_not_used:
	mov  [eax+0],esi

	mov  ebx,1
	shl  ebx,cl
	dec  ebx





	cmp  dword ptr [inflate_fast_use_mmx],2
	jne  L_update_hold



	psrlq mm0,mm1
	movd ebp,mm0

	emms

L_update_hold:



	and  ebp,ebx
	mov  [edx+hold_state],ebp




	mov  ebx, [esp+20]
	cmp  ebx,esi
	jbe  L_last_is_smaller

	sub  ebx,esi
	add  ebx,11
	mov  [eax+4],ebx
	jmp  L_fixup_out
L_last_is_smaller:
	sub  esi,ebx
	neg  esi
	add  esi,11
	mov  [eax+4],esi




L_fixup_out:

	mov  ebx, [esp+16]
	cmp  ebx,edi
	jbe  L_end_is_smaller

	sub  ebx,edi
	add  ebx,257
	mov  [eax+16],ebx
	jmp  L_done
L_end_is_smaller:
	sub  edi,ebx
	neg  edi
	add  edi,257
	mov  [eax+16],edi





L_done:
	add  esp,64
	popfd
	pop  ebx
	pop  ebp
	pop  esi
	pop  edi
	ret
_inflate_fast endp

_TEXT	ends
end

Deleted compat/zlib/contrib/masmx86/match686.asm.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
479































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
; match686.asm -- Asm portion of the optimized longest_match for 32 bits x86
; Copyright (C) 1995-1996 Jean-loup Gailly, Brian Raiter and Gilles Vollant.
; File written by Gilles Vollant, by converting match686.S from Brian Raiter
; for MASM. This is as assembly version of longest_match
;  from Jean-loup Gailly in deflate.c
;
;         http://www.zlib.net
;         http://www.winimage.com/zLibDll
;         http://www.muppetlabs.com/~breadbox/software/assembly.html
;
; For Visual C++ 4.x and higher and ML 6.x and higher
;   ml.exe is distributed in
;  http://www.microsoft.com/downloads/details.aspx?FamilyID=7a1c9da0-0510-44a2-b042-7ef370530c64
;
; this file contain two implementation of longest_match
;
;  this longest_match was written by Brian raiter (1998), optimized for Pentium Pro
;   (and the faster known version of match_init on modern Core 2 Duo and AMD Phenom)
;
;  for using an assembly version of longest_match, you need define ASMV in project
;
;    compile the asm file running
;           ml /coff /Zi /c /Flmatch686.lst match686.asm
;    and do not include match686.obj in your project
;
; note: contrib of zLib 1.2.3 and earlier contained both a deprecated version for
;  Pentium (prior Pentium Pro) and this version for Pentium Pro and modern processor
;  with autoselect (with cpu detection code)
;  if you want support the old pentium optimization, you can still use these version
;
; this file is not optimized for old pentium, but it compatible with all x86 32 bits
; processor (starting 80386)
;
;
; see below : zlib1222add must be adjuster if you use a zlib version < 1.2.2.2

;uInt longest_match(s, cur_match)
;    deflate_state *s;
;    IPos cur_match;                             /* current match */

    NbStack         equ     76
    cur_match       equ     dword ptr[esp+NbStack-0]
    str_s           equ     dword ptr[esp+NbStack-4]
; 5 dword on top (ret,ebp,esi,edi,ebx)
    adrret          equ     dword ptr[esp+NbStack-8]
    pushebp         equ     dword ptr[esp+NbStack-12]
    pushedi         equ     dword ptr[esp+NbStack-16]
    pushesi         equ     dword ptr[esp+NbStack-20]
    pushebx         equ     dword ptr[esp+NbStack-24]

    chain_length    equ     dword ptr [esp+NbStack-28]
    limit           equ     dword ptr [esp+NbStack-32]
    best_len        equ     dword ptr [esp+NbStack-36]
    window          equ     dword ptr [esp+NbStack-40]
    prev            equ     dword ptr [esp+NbStack-44]
    scan_start      equ      word ptr [esp+NbStack-48]
    wmask           equ     dword ptr [esp+NbStack-52]
    match_start_ptr equ     dword ptr [esp+NbStack-56]
    nice_match      equ     dword ptr [esp+NbStack-60]
    scan            equ     dword ptr [esp+NbStack-64]

    windowlen       equ     dword ptr [esp+NbStack-68]
    match_start     equ     dword ptr [esp+NbStack-72]
    strend          equ     dword ptr [esp+NbStack-76]
    NbStackAdd      equ     (NbStack-24)

    .386p

    name    gvmatch
    .MODEL  FLAT



;  all the +zlib1222add offsets are due to the addition of fields
;  in zlib in the deflate_state structure since the asm code was first written
;  (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
;  (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
;  if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").

    zlib1222add         equ     8

;  Note : these value are good with a 8 bytes boundary pack structure
    dep_chain_length    equ     74h+zlib1222add
    dep_window          equ     30h+zlib1222add
    dep_strstart        equ     64h+zlib1222add
    dep_prev_length     equ     70h+zlib1222add
    dep_nice_match      equ     88h+zlib1222add
    dep_w_size          equ     24h+zlib1222add
    dep_prev            equ     38h+zlib1222add
    dep_w_mask          equ     2ch+zlib1222add
    dep_good_match      equ     84h+zlib1222add
    dep_match_start     equ     68h+zlib1222add
    dep_lookahead       equ     6ch+zlib1222add


_TEXT                   segment

IFDEF NOUNDERLINE
            public  longest_match
            public  match_init
ELSE
            public  _longest_match
            public  _match_init
ENDIF

    MAX_MATCH           equ     258
    MIN_MATCH           equ     3
    MIN_LOOKAHEAD       equ     (MAX_MATCH+MIN_MATCH+1)



MAX_MATCH       equ     258
MIN_MATCH       equ     3
MIN_LOOKAHEAD   equ     (MAX_MATCH + MIN_MATCH + 1)
MAX_MATCH_8_     equ     ((MAX_MATCH + 7) AND 0FFF0h)


;;; stack frame offsets

chainlenwmask   equ  esp + 0    ; high word: current chain len
                    ; low word: s->wmask
window      equ  esp + 4    ; local copy of s->window
windowbestlen   equ  esp + 8    ; s->window + bestlen
scanstart   equ  esp + 16   ; first two bytes of string
scanend     equ  esp + 12   ; last two bytes of string
scanalign   equ  esp + 20   ; dword-misalignment of string
nicematch   equ  esp + 24   ; a good enough match size
bestlen     equ  esp + 28   ; size of best match so far
scan        equ  esp + 32   ; ptr to string wanting match

LocalVarsSize   equ 36
;   saved ebx   byte esp + 36
;   saved edi   byte esp + 40
;   saved esi   byte esp + 44
;   saved ebp   byte esp + 48
;   return address  byte esp + 52
deflatestate    equ  esp + 56   ; the function arguments
curmatch    equ  esp + 60

;;; Offsets for fields in the deflate_state structure. These numbers
;;; are calculated from the definition of deflate_state, with the
;;; assumption that the compiler will dword-align the fields. (Thus,
;;; changing the definition of deflate_state could easily cause this
;;; program to crash horribly, without so much as a warning at
;;; compile time. Sigh.)

dsWSize     equ 36+zlib1222add
dsWMask     equ 44+zlib1222add
dsWindow    equ 48+zlib1222add
dsPrev      equ 56+zlib1222add
dsMatchLen  equ 88+zlib1222add
dsPrevMatch equ 92+zlib1222add
dsStrStart  equ 100+zlib1222add
dsMatchStart    equ 104+zlib1222add
dsLookahead equ 108+zlib1222add
dsPrevLen   equ 112+zlib1222add
dsMaxChainLen   equ 116+zlib1222add
dsGoodMatch equ 132+zlib1222add
dsNiceMatch equ 136+zlib1222add


;;; match686.asm -- Pentium-Pro-optimized version of longest_match()
;;; Written for zlib 1.1.2
;;; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html
;;;
;;
;;  This software is provided 'as-is', without any express or implied
;;  warranty.  In no event will the authors be held liable for any damages
;;  arising from the use of this software.
;;
;;  Permission is granted to anyone to use this software for any purpose,
;;  including commercial applications, and to alter it and redistribute it
;;  freely, subject to the following restrictions:
;;
;;  1. The origin of this software must not be misrepresented; you must not
;;     claim that you wrote the original software. If you use this software
;;     in a product, an acknowledgment in the product documentation would be
;;     appreciated but is not required.
;;  2. Altered source versions must be plainly marked as such, and must not be
;;     misrepresented as being the original software
;;  3. This notice may not be removed or altered from any source distribution.
;;

;GLOBAL _longest_match, _match_init


;SECTION    .text

;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch)

;_longest_match:
    IFDEF NOUNDERLINE
    longest_match       proc near
    ELSE
    _longest_match      proc near
    ENDIF
.FPO (9, 4, 0, 0, 1, 0)

;;; Save registers that the compiler may be using, and adjust esp to
;;; make room for our stack frame.

        push    ebp
        push    edi
        push    esi
        push    ebx
        sub esp, LocalVarsSize

;;; Retrieve the function arguments. ecx will hold cur_match
;;; throughout the entire function. edx will hold the pointer to the
;;; deflate_state structure during the function's setup (before
;;; entering the main loop.

        mov edx, [deflatestate]
        mov ecx, [curmatch]

;;; uInt wmask = s->w_mask;
;;; unsigned chain_length = s->max_chain_length;
;;; if (s->prev_length >= s->good_match) {
;;;     chain_length >>= 2;
;;; }

        mov eax, [edx + dsPrevLen]
        mov ebx, [edx + dsGoodMatch]
        cmp eax, ebx
        mov eax, [edx + dsWMask]
        mov ebx, [edx + dsMaxChainLen]
        jl  LastMatchGood
        shr ebx, 2
LastMatchGood:

;;; chainlen is decremented once beforehand so that the function can
;;; use the sign flag instead of the zero flag for the exit test.
;;; It is then shifted into the high word, to make room for the wmask
;;; value, which it will always accompany.

        dec ebx
        shl ebx, 16
        or  ebx, eax
        mov [chainlenwmask], ebx

;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;

        mov eax, [edx + dsNiceMatch]
        mov ebx, [edx + dsLookahead]
        cmp ebx, eax
        jl  LookaheadLess
        mov ebx, eax
LookaheadLess:  mov [nicematch], ebx

;;; register Bytef *scan = s->window + s->strstart;

        mov esi, [edx + dsWindow]
        mov [window], esi
        mov ebp, [edx + dsStrStart]
        lea edi, [esi + ebp]
        mov [scan], edi

;;; Determine how many bytes the scan ptr is off from being
;;; dword-aligned.

        mov eax, edi
        neg eax
        and eax, 3
        mov [scanalign], eax

;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
;;;     s->strstart - (IPos)MAX_DIST(s) : NIL;

        mov eax, [edx + dsWSize]
        sub eax, MIN_LOOKAHEAD
        sub ebp, eax
        jg  LimitPositive
        xor ebp, ebp
LimitPositive:

;;; int best_len = s->prev_length;

        mov eax, [edx + dsPrevLen]
        mov [bestlen], eax

;;; Store the sum of s->window + best_len in esi locally, and in esi.

        add esi, eax
        mov [windowbestlen], esi

;;; register ush scan_start = *(ushf*)scan;
;;; register ush scan_end   = *(ushf*)(scan+best_len-1);
;;; Posf *prev = s->prev;

        movzx   ebx, word ptr [edi]
        mov [scanstart], ebx
        movzx   ebx, word ptr [edi + eax - 1]
        mov [scanend], ebx
        mov edi, [edx + dsPrev]

;;; Jump into the main loop.

        mov edx, [chainlenwmask]
        jmp short LoopEntry

align 4

;;; do {
;;;     match = s->window + cur_match;
;;;     if (*(ushf*)(match+best_len-1) != scan_end ||
;;;         *(ushf*)match != scan_start) continue;
;;;     [...]
;;; } while ((cur_match = prev[cur_match & wmask]) > limit
;;;          && --chain_length != 0);
;;;
;;; Here is the inner loop of the function. The function will spend the
;;; majority of its time in this loop, and majority of that time will
;;; be spent in the first ten instructions.
;;;
;;; Within this loop:
;;; ebx = scanend
;;; ecx = curmatch
;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
;;; esi = windowbestlen - i.e., (window + bestlen)
;;; edi = prev
;;; ebp = limit

LookupLoop:
        and ecx, edx
        movzx   ecx, word ptr [edi + ecx*2]
        cmp ecx, ebp
        jbe LeaveNow
        sub edx, 00010000h
        js  LeaveNow
LoopEntry:  movzx   eax, word ptr [esi + ecx - 1]
        cmp eax, ebx
        jnz LookupLoop
        mov eax, [window]
        movzx   eax, word ptr [eax + ecx]
        cmp eax, [scanstart]
        jnz LookupLoop

;;; Store the current value of chainlen.

        mov [chainlenwmask], edx

;;; Point edi to the string under scrutiny, and esi to the string we
;;; are hoping to match it up with. In actuality, esi and edi are
;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is
;;; initialized to -(MAX_MATCH_8 - scanalign).

        mov esi, [window]
        mov edi, [scan]
        add esi, ecx
        mov eax, [scanalign]
        mov edx, 0fffffef8h; -(MAX_MATCH_8)
        lea edi, [edi + eax + 0108h] ;MAX_MATCH_8]
        lea esi, [esi + eax + 0108h] ;MAX_MATCH_8]

;;; Test the strings for equality, 8 bytes at a time. At the end,
;;; adjust edx so that it is offset to the exact byte that mismatched.
;;;
;;; We already know at this point that the first three bytes of the
;;; strings match each other, and they can be safely passed over before
;;; starting the compare loop. So what this code does is skip over 0-3
;;; bytes, as much as necessary in order to dword-align the edi
;;; pointer. (esi will still be misaligned three times out of four.)
;;;
;;; It should be confessed that this loop usually does not represent
;;; much of the total running time. Replacing it with a more
;;; straightforward "rep cmpsb" would not drastically degrade
;;; performance.

LoopCmps:
        mov eax, [esi + edx]
        xor eax, [edi + edx]
        jnz LeaveLoopCmps
        mov eax, [esi + edx + 4]
        xor eax, [edi + edx + 4]
        jnz LeaveLoopCmps4
        add edx, 8
        jnz LoopCmps
        jmp short LenMaximum
LeaveLoopCmps4: add edx, 4
LeaveLoopCmps:  test    eax, 0000FFFFh
        jnz LenLower
        add edx,  2
        shr eax, 16
LenLower:   sub al, 1
        adc edx, 0

;;; Calculate the length of the match. If it is longer than MAX_MATCH,
;;; then automatically accept it as the best possible match and leave.

        lea eax, [edi + edx]
        mov edi, [scan]
        sub eax, edi
        cmp eax, MAX_MATCH
        jge LenMaximum

;;; If the length of the match is not longer than the best match we
;;; have so far, then forget it and return to the lookup loop.

        mov edx, [deflatestate]
        mov ebx, [bestlen]
        cmp eax, ebx
        jg  LongerMatch
        mov esi, [windowbestlen]
        mov edi, [edx + dsPrev]
        mov ebx, [scanend]
        mov edx, [chainlenwmask]
        jmp LookupLoop

;;;         s->match_start = cur_match;
;;;         best_len = len;
;;;         if (len >= nice_match) break;
;;;         scan_end = *(ushf*)(scan+best_len-1);

LongerMatch:    mov ebx, [nicematch]
        mov [bestlen], eax
        mov [edx + dsMatchStart], ecx
        cmp eax, ebx
        jge LeaveNow
        mov esi, [window]
        add esi, eax
        mov [windowbestlen], esi
        movzx   ebx, word ptr [edi + eax - 1]
        mov edi, [edx + dsPrev]
        mov [scanend], ebx
        mov edx, [chainlenwmask]
        jmp LookupLoop

;;; Accept the current string, with the maximum possible length.

LenMaximum: mov edx, [deflatestate]
        mov dword ptr [bestlen], MAX_MATCH
        mov [edx + dsMatchStart], ecx

;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
;;; return s->lookahead;

LeaveNow:
        mov edx, [deflatestate]
        mov ebx, [bestlen]
        mov eax, [edx + dsLookahead]
        cmp ebx, eax
        jg  LookaheadRet
        mov eax, ebx
LookaheadRet:

;;; Restore the stack and return from whence we came.

        add esp, LocalVarsSize
        pop ebx
        pop esi
        pop edi
        pop ebp

        ret
; please don't remove this string !
; Your can freely use match686 in any free or commercial app if you don't remove the string in the binary!
    db     0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah


    IFDEF NOUNDERLINE
    longest_match       endp
    ELSE
    _longest_match      endp
    ENDIF

    IFDEF NOUNDERLINE
    match_init      proc near
                    ret
    match_init      endp
    ELSE
    _match_init     proc near
                    ret
    _match_init     endp
    ENDIF


_TEXT   ends
end

Deleted compat/zlib/contrib/masmx86/readme.txt.

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



























-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

Summary
-------
This directory contains ASM implementations of the functions
longest_match() and inflate_fast().


Use instructions
----------------
Assemble using MASM, and copy the object files into the zlib source
directory, then run the appropriate makefile, as suggested below.  You can
donwload MASM from here:

    http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=7a1c9da0-0510-44a2-b042-7ef370530c64

You can also get objects files here:

    http://www.winimage.com/zLibDll/zlib124_masm_obj.zip

Build instructions
------------------
* With Microsoft C and MASM:
nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" OBJA="match686.obj inffas32.obj"

* With Borland C and TASM:
make -f win32/Makefile.bor LOCAL_ZLIB="-DASMV -DASMINF" OBJA="match686.obj inffas32.obj" OBJPA="+match686c.obj+match686.obj+inffas32.obj"

Changes to compat/zlib/contrib/minizip/Makefile.

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



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
-
-
+
+
















+
+
-
+

-
+

+
+


-
+
CC=cc
CFLAGS=-O -I../..
CC?=cc
CFLAGS := $(CFLAGS) -O -I../..

UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a
ZIP_OBJS = minizip.o zip.o   ioapi.o ../../libz.a

.c.o:
	$(CC) -c $(CFLAGS) $*.c

all: miniunz minizip

miniunz:  $(UNZ_OBJS)
	$(CC) $(CFLAGS) -o $@ $(UNZ_OBJS)

minizip:  $(ZIP_OBJS)
	$(CC) $(CFLAGS) -o $@ $(ZIP_OBJS)

test:	miniunz minizip
	@rm -f test.*
	@echo hello hello hello > test.txt
	./minizip test readme.txt
	./minizip test test.txt
	./miniunz -l test.zip
	mv readme.txt readme.old
	@mv test.txt test.old
	./miniunz test.zip
	@cmp test.txt test.old
	@rm -f test.*

clean:
	/bin/rm -f *.o *~ minizip miniunz
	/bin/rm -f *.o *~ minizip miniunz test.*

Changes to compat/zlib/contrib/minizip/MiniZip64_Changes.txt.

1
2

3
4
5
6
1

2
3
4
5
6

-
+





MiniZip 1.1 was derrived from MiniZip at version 1.01f
MiniZip 1.1 was derived from MiniZip at version 1.01f

Change in 1.0 (Okt 2009)
 - **TODO - Add history**

Changes to compat/zlib/contrib/minizip/configure.ac.

1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_INIT([minizip], [1.2.11], [bugzilla.redhat.com])
AC_INIT([minizip], [1.3.1], [bugzilla.redhat.com])
AC_CONFIG_SRCDIR([minizip.c])
AM_INIT_AUTOMAKE([foreign])
LT_INIT

AC_MSG_CHECKING([whether to build example programs])
AC_ARG_ENABLE([demos], AC_HELP_STRING([--enable-demos], [build example programs]))
AM_CONDITIONAL([COND_DEMOS], [test "$enable_demos" = yes])

Changes to compat/zlib/contrib/minizip/crypt.h.

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
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







-
+
-



-

+







-
+
-















-
+
-













-
+






-
+


-
-
-
-
-
-
+
+
+
+
+
+
-
-
+







*/

#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))

/***********************************************************************
 * Return the next byte in the pseudo-random sequence
 */
static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab)
static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) {
{
    unsigned temp;  /* POTENTIAL BUG:  temp*(temp^1) may overflow in an
                     * unpredictable manner on 16-bit systems; not a problem
                     * with any known compiler so far, though */
    (void)pcrc_32_tab;

    (void)pcrc_32_tab;
    temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
    return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
}

/***********************************************************************
 * Update the encryption keys with the next byte of plain text
 */
static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c)
static int update_keys(unsigned long* pkeys, const z_crc_t* pcrc_32_tab, int c) {
{
    (*(pkeys+0)) = CRC32((*(pkeys+0)), c);
    (*(pkeys+1)) += (*(pkeys+0)) & 0xff;
    (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
    {
      int keyshift = (int)((*(pkeys+1)) >> 24);
      (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
    }
    return c;
}


/***********************************************************************
 * Initialize the encryption keys and the random header according to
 * the given password.
 */
static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab)
static void init_keys(const char* passwd, unsigned long* pkeys, const z_crc_t* pcrc_32_tab) {
{
    *(pkeys+0) = 305419896L;
    *(pkeys+1) = 591751049L;
    *(pkeys+2) = 878082192L;
    while (*passwd != '\0') {
        update_keys(pkeys,pcrc_32_tab,(int)*passwd);
        passwd++;
    }
}

#define zdecode(pkeys,pcrc_32_tab,c) \
    (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))

#define zencode(pkeys,pcrc_32_tab,c,t) \
    (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
    (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), (Byte)t^(c))

#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED

#define RAND_HEAD_LEN  12
   /* "last resort" source for second part of crypt seed pattern */
#  ifndef ZCR_SEED2
#    define ZCR_SEED2 3141592654UL     /* use PI as default pattern */
#    define ZCR_SEED2 3141592654UL      /* use PI as default pattern */
#  endif

static int crypthead(const char* passwd,      /* password string */
                     unsigned char* buf,      /* where to write header */
                     int bufSize,
                     unsigned long* pkeys,
                     const z_crc_t* pcrc_32_tab,
                     unsigned long crcForCrypting)
static unsigned crypthead(const char* passwd,       /* password string */
                          unsigned char* buf,       /* where to write header */
                          int bufSize,
                          unsigned long* pkeys,
                          const z_crc_t* pcrc_32_tab,
                          unsigned long crcForCrypting) {
{
    int n;                       /* index in random header */
    unsigned n;                  /* index in random header */
    int t;                       /* temporary */
    int c;                       /* random byte */
    unsigned char header[RAND_HEAD_LEN-2]; /* random header */
    static unsigned calls = 0;   /* ensure different random header each time */

    if (bufSize<RAND_HEAD_LEN)
      return 0;

Changes to compat/zlib/contrib/minizip/ioapi.c.

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
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







-
+













-
+
-








-
+
-












-
+
-




-
+







-
+
-


-













-
-
-
-
-
-
-
-
-
+
-


+














-
+
-


+















-
+
-

+




-
+
-

+




-
+
-

+





-
+
-

+
-
+



-
+
-


+














-
+




-
+
-


+















-
+






-
+
-

+




-
+
-

+




-
-
+
-










-
+
-









        #define _CRT_SECURE_NO_WARNINGS
#endif

#if defined(_WIN32)
#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
#define FTELLO_FUNC(stream) _ftelli64(stream)
#define FSEEKO_FUNC(stream, offset, origin) _fseeki64(stream, offset, origin)
#elif defined(__APPLE__) || defined(IOAPI_NO_64)
#elif defined(__APPLE__) || defined(IOAPI_NO_64) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64)
// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
#define FTELLO_FUNC(stream) ftello(stream)
#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
#else
#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
#define FTELLO_FUNC(stream) ftello64(stream)
#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
#endif


#include "ioapi.h"

voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)
voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc, const void*filename, int mode) {
{
    if (pfilefunc->zfile_func64.zopen64_file != NULL)
        return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode);
    else
    {
        return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode);
    }
}

long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)
long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) {
{
    if (pfilefunc->zfile_func64.zseek64_file != NULL)
        return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin);
    else
    {
        uLong offsetTruncated = (uLong)offset;
        if (offsetTruncated != offset)
            return -1;
        else
            return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin);
    }
}

ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)
ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc, voidpf filestream) {
{
    if (pfilefunc->zfile_func64.zseek64_file != NULL)
        return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream);
    else
    {
        uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream);
        uLong tell_uLong = (uLong)(*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream);
        if ((tell_uLong) == MAXU32)
            return (ZPOS64_T)-1;
        else
            return tell_uLong;
    }
}

void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32)
void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32, const zlib_filefunc_def* p_filefunc32) {
{
    p_filefunc64_32->zfile_func64.zopen64_file = NULL;
    p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file;
    p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
    p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file;
    p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file;
    p_filefunc64_32->zfile_func64.ztell64_file = NULL;
    p_filefunc64_32->zfile_func64.zseek64_file = NULL;
    p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file;
    p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
    p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque;
    p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file;
    p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;
}



static voidpf  ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode));
static uLong   ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size));
static uLong   ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size));
static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream));
static long    ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
static int     ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream));
static int     ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream));

static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode)
static voidpf ZCALLBACK fopen_file_func(voidpf opaque, const char* filename, int mode) {
{
    FILE* file = NULL;
    const char* mode_fopen = NULL;
    (void)opaque;
    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
        mode_fopen = "rb";
    else
    if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
        mode_fopen = "r+b";
    else
    if (mode & ZLIB_FILEFUNC_MODE_CREATE)
        mode_fopen = "wb";

    if ((filename!=NULL) && (mode_fopen != NULL))
        file = fopen(filename, mode_fopen);
    return file;
}

static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode)
static voidpf ZCALLBACK fopen64_file_func(voidpf opaque, const void* filename, int mode) {
{
    FILE* file = NULL;
    const char* mode_fopen = NULL;
    (void)opaque;
    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
        mode_fopen = "rb";
    else
    if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
        mode_fopen = "r+b";
    else
    if (mode & ZLIB_FILEFUNC_MODE_CREATE)
        mode_fopen = "wb";

    if ((filename!=NULL) && (mode_fopen != NULL))
        file = FOPEN_FUNC((const char*)filename, mode_fopen);
    return file;
}


static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size)
static uLong ZCALLBACK fread_file_func(voidpf opaque, voidpf stream, void* buf, uLong size) {
{
    uLong ret;
    (void)opaque;
    ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
    return ret;
}

static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size)
static uLong ZCALLBACK fwrite_file_func(voidpf opaque, voidpf stream, const void* buf, uLong size) {
{
    uLong ret;
    (void)opaque;
    ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
    return ret;
}

static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)
static long ZCALLBACK ftell_file_func(voidpf opaque, voidpf stream) {
{
    long ret;
    (void)opaque;
    ret = ftell((FILE *)stream);
    return ret;
}


static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)
static ZPOS64_T ZCALLBACK ftell64_file_func(voidpf opaque, voidpf stream) {
{
    ZPOS64_T ret;
    (void)opaque;
    ret = FTELLO_FUNC((FILE *)stream);
    ret = (ZPOS64_T)FTELLO_FUNC((FILE *)stream);
    return ret;
}

static long ZCALLBACK fseek_file_func (voidpf  opaque, voidpf stream, uLong offset, int origin)
static long ZCALLBACK fseek_file_func(voidpf opaque, voidpf stream, uLong offset, int origin) {
{
    int fseek_origin=0;
    long ret;
    (void)opaque;
    switch (origin)
    {
    case ZLIB_FILEFUNC_SEEK_CUR :
        fseek_origin = SEEK_CUR;
        break;
    case ZLIB_FILEFUNC_SEEK_END :
        fseek_origin = SEEK_END;
        break;
    case ZLIB_FILEFUNC_SEEK_SET :
        fseek_origin = SEEK_SET;
        break;
    default: return -1;
    }
    ret = 0;
    if (fseek((FILE *)stream, offset, fseek_origin) != 0)
    if (fseek((FILE *)stream, (long)offset, fseek_origin) != 0)
        ret = -1;
    return ret;
}

static long ZCALLBACK fseek64_file_func (voidpf  opaque, voidpf stream, ZPOS64_T offset, int origin)
static long ZCALLBACK fseek64_file_func(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) {
{
    int fseek_origin=0;
    long ret;
    (void)opaque;
    switch (origin)
    {
    case ZLIB_FILEFUNC_SEEK_CUR :
        fseek_origin = SEEK_CUR;
        break;
    case ZLIB_FILEFUNC_SEEK_END :
        fseek_origin = SEEK_END;
        break;
    case ZLIB_FILEFUNC_SEEK_SET :
        fseek_origin = SEEK_SET;
        break;
    default: return -1;
    }
    ret = 0;

    if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0)
    if(FSEEKO_FUNC((FILE *)stream, (z_off64_t)offset, fseek_origin) != 0)
                        ret = -1;

    return ret;
}


static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)
static int ZCALLBACK fclose_file_func(voidpf opaque, voidpf stream) {
{
    int ret;
    (void)opaque;
    ret = fclose((FILE *)stream);
    return ret;
}

static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream)
static int ZCALLBACK ferror_file_func(voidpf opaque, voidpf stream) {
{
    int ret;
    (void)opaque;
    ret = ferror((FILE *)stream);
    return ret;
}

void fill_fopen_filefunc (pzlib_filefunc_def)
  zlib_filefunc_def* pzlib_filefunc_def;
void fill_fopen_filefunc(zlib_filefunc_def* pzlib_filefunc_def) {
{
    pzlib_filefunc_def->zopen_file = fopen_file_func;
    pzlib_filefunc_def->zread_file = fread_file_func;
    pzlib_filefunc_def->zwrite_file = fwrite_file_func;
    pzlib_filefunc_def->ztell_file = ftell_file_func;
    pzlib_filefunc_def->zseek_file = fseek_file_func;
    pzlib_filefunc_def->zclose_file = fclose_file_func;
    pzlib_filefunc_def->zerror_file = ferror_file_func;
    pzlib_filefunc_def->opaque = NULL;
}

void fill_fopen64_filefunc (zlib_filefunc64_def*  pzlib_filefunc_def)
void fill_fopen64_filefunc(zlib_filefunc64_def* pzlib_filefunc_def) {
{
    pzlib_filefunc_def->zopen64_file = fopen64_file_func;
    pzlib_filefunc_def->zread_file = fread_file_func;
    pzlib_filefunc_def->zwrite_file = fwrite_file_func;
    pzlib_filefunc_def->ztell64_file = ftell64_file_func;
    pzlib_filefunc_def->zseek64_file = fseek64_file_func;
    pzlib_filefunc_def->zclose_file = fclose_file_func;
    pzlib_filefunc_def->zerror_file = ferror_file_func;
    pzlib_filefunc_def->opaque = NULL;
}

Changes to compat/zlib/contrib/minizip/ioapi.h.

46
47
48
49
50
51
52
53

54
55
56
57
58
59
60
46
47
48
49
50
51
52

53
54
55
56
57
58
59
60







-
+







#include "zlib.h"

#if defined(USE_FILE32API)
#define fopen64 fopen
#define ftello64 ftell
#define fseeko64 fseek
#else
#ifdef __FreeBSD__
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64)
#define fopen64 fopen
#define ftello64 ftello
#define fseeko64 fseeko
#endif
#ifdef _MSC_VER
 #define fopen64 fopen
 #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
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
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







-
+








-
+
-









-
+
+
+
+







#endif
*/

#ifdef HAVE_MINIZIP64_CONF_H
#include "mz64conf.h"
#endif

/* a type choosen by DEFINE */
/* a type chosen by DEFINE */
#ifdef HAVE_64BIT_INT_CUSTOM
typedef  64BIT_INT_CUSTOM_TYPE ZPOS64_T;
#else
#ifdef HAS_STDINT_H
#include "stdint.h"
typedef uint64_t ZPOS64_T;
#else

/* Maximum unsigned 32-bit value used as placeholder for zip64 */

#define MAXU32 0xffffffff

#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef unsigned __int64 ZPOS64_T;
#else
typedef unsigned long long int ZPOS64_T;
#endif
#endif
#endif


/* Maximum unsigned 32-bit value used as placeholder for zip64 */
#ifndef MAXU32
#define MAXU32 (0xffffffff)
#endif

#ifdef __cplusplus
extern "C" {
#endif


#define ZLIB_FILEFUNC_SEEK_CUR (1)
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
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







-
-
-
-
-
+
+
+
+
+

-
-
+
+


-
+












-
-
-
+
+
+













-
-
+
+


















-
-
-
+
+
+

-
+










   #define ZCALLBACK
 #endif
#endif




typedef voidpf   (ZCALLBACK *open_file_func)      OF((voidpf opaque, const char* filename, int mode));
typedef uLong    (ZCALLBACK *read_file_func)      OF((voidpf opaque, voidpf stream, void* buf, uLong size));
typedef uLong    (ZCALLBACK *write_file_func)     OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
typedef int      (ZCALLBACK *close_file_func)     OF((voidpf opaque, voidpf stream));
typedef int      (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
typedef voidpf   (ZCALLBACK *open_file_func)      (voidpf opaque, const char* filename, int mode);
typedef uLong    (ZCALLBACK *read_file_func)      (voidpf opaque, voidpf stream, void* buf, uLong size);
typedef uLong    (ZCALLBACK *write_file_func)     (voidpf opaque, voidpf stream, const void* buf, uLong size);
typedef int      (ZCALLBACK *close_file_func)     (voidpf opaque, voidpf stream);
typedef int      (ZCALLBACK *testerror_file_func) (voidpf opaque, voidpf stream);

typedef long     (ZCALLBACK *tell_file_func)      OF((voidpf opaque, voidpf stream));
typedef long     (ZCALLBACK *seek_file_func)      OF((voidpf opaque, voidpf stream, uLong offset, int origin));
typedef long     (ZCALLBACK *tell_file_func)      (voidpf opaque, voidpf stream);
typedef long     (ZCALLBACK *seek_file_func)      (voidpf opaque, voidpf stream, uLong offset, int origin);


/* here is the "old" 32 bits structure structure */
/* here is the "old" 32 bits structure */
typedef struct zlib_filefunc_def_s
{
    open_file_func      zopen_file;
    read_file_func      zread_file;
    write_file_func     zwrite_file;
    tell_file_func      ztell_file;
    seek_file_func      zseek_file;
    close_file_func     zclose_file;
    testerror_file_func zerror_file;
    voidpf              opaque;
} zlib_filefunc_def;

typedef ZPOS64_T (ZCALLBACK *tell64_file_func)    OF((voidpf opaque, voidpf stream));
typedef long     (ZCALLBACK *seek64_file_func)    OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
typedef voidpf   (ZCALLBACK *open64_file_func)    OF((voidpf opaque, const void* filename, int mode));
typedef ZPOS64_T (ZCALLBACK *tell64_file_func)    (voidpf opaque, voidpf stream);
typedef long     (ZCALLBACK *seek64_file_func)    (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin);
typedef voidpf   (ZCALLBACK *open64_file_func)    (voidpf opaque, const void* filename, int mode);

typedef struct zlib_filefunc64_def_s
{
    open64_file_func    zopen64_file;
    read_file_func      zread_file;
    write_file_func     zwrite_file;
    tell64_file_func    ztell64_file;
    seek64_file_func    zseek64_file;
    close_file_func     zclose_file;
    testerror_file_func zerror_file;
    voidpf              opaque;
} zlib_filefunc64_def;

void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def));
void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
void fill_fopen64_filefunc(zlib_filefunc64_def* pzlib_filefunc_def);
void fill_fopen_filefunc(zlib_filefunc_def* pzlib_filefunc_def);

/* now internal definition, only for zip.c and unzip.h */
typedef struct zlib_filefunc64_32_def_s
{
    zlib_filefunc64_def zfile_func64;
    open_file_func      zopen32_file;
    tell_file_func      ztell32_file;
    seek_file_func      zseek32_file;
} zlib_filefunc64_32_def;


#define ZREAD64(filefunc,filestream,buf,size)     ((*((filefunc).zfile_func64.zread_file))   ((filefunc).zfile_func64.opaque,filestream,buf,size))
#define ZWRITE64(filefunc,filestream,buf,size)    ((*((filefunc).zfile_func64.zwrite_file))  ((filefunc).zfile_func64.opaque,filestream,buf,size))
//#define ZTELL64(filefunc,filestream)            ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream))
//#define ZSEEK64(filefunc,filestream,pos,mode)   ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode))
#define ZCLOSE64(filefunc,filestream)             ((*((filefunc).zfile_func64.zclose_file))  ((filefunc).zfile_func64.opaque,filestream))
#define ZERROR64(filefunc,filestream)             ((*((filefunc).zfile_func64.zerror_file))  ((filefunc).zfile_func64.opaque,filestream))

voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode));
long    call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin));
ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream));
voidpf call_zopen64(const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode);
long call_zseek64(const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin);
ZPOS64_T call_ztell64(const zlib_filefunc64_32_def* pfilefunc,voidpf filestream);

void    fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32);
void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32);

#define ZOPEN64(filefunc,filename,mode)         (call_zopen64((&(filefunc)),(filename),(mode)))
#define ZTELL64(filefunc,filestream)            (call_ztell64((&(filefunc)),(filestream)))
#define ZSEEK64(filefunc,filestream,pos,mode)   (call_zseek64((&(filefunc)),(filestream),(pos),(mode)))

#ifdef __cplusplus
}
#endif

#endif

Changes to compat/zlib/contrib/minizip/iowin32.c.

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
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







+
+
+
+
+





-
-
-
-
-
-
-
-











-
+
-




















-
+
-

















-
+
-







#ifndef INVALID_SET_FILE_POINTER
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
#endif


// see Include/shared/winapifamily.h in the Windows Kit
#if defined(WINAPI_FAMILY_PARTITION) && (!(defined(IOWIN32_USING_WINRT_API)))

#if !defined(WINAPI_FAMILY_ONE_PARTITION)
#define WINAPI_FAMILY_ONE_PARTITION(PartitionSet, Partition) ((WINAPI_FAMILY & PartitionSet) == Partition)
#endif

#if WINAPI_FAMILY_ONE_PARTITION(WINAPI_FAMILY, WINAPI_PARTITION_APP)
#define IOWIN32_USING_WINRT_API 1
#endif
#endif

voidpf  ZCALLBACK win32_open_file_func  OF((voidpf opaque, const char* filename, int mode));
uLong   ZCALLBACK win32_read_file_func  OF((voidpf opaque, voidpf stream, void* buf, uLong size));
uLong   ZCALLBACK win32_write_file_func OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
ZPOS64_T ZCALLBACK win32_tell64_file_func  OF((voidpf opaque, voidpf stream));
long    ZCALLBACK win32_seek64_file_func  OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
int     ZCALLBACK win32_close_file_func OF((voidpf opaque, voidpf stream));
int     ZCALLBACK win32_error_file_func OF((voidpf opaque, voidpf stream));

typedef struct
{
    HANDLE hf;
    int error;
} WIN32FILE_IOWIN;


static void win32_translate_open_mode(int mode,
                                      DWORD* lpdwDesiredAccess,
                                      DWORD* lpdwCreationDisposition,
                                      DWORD* lpdwShareMode,
                                      DWORD* lpdwFlagsAndAttributes)
                                      DWORD* lpdwFlagsAndAttributes) {
{
    *lpdwDesiredAccess = *lpdwShareMode = *lpdwFlagsAndAttributes = *lpdwCreationDisposition = 0;

    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
    {
        *lpdwDesiredAccess = GENERIC_READ;
        *lpdwCreationDisposition = OPEN_EXISTING;
        *lpdwShareMode = FILE_SHARE_READ;
    }
    else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
    {
        *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
        *lpdwCreationDisposition = OPEN_EXISTING;
    }
    else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
    {
        *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
        *lpdwCreationDisposition = CREATE_ALWAYS;
    }
}

static voidpf win32_build_iowin(HANDLE hFile)
static voidpf win32_build_iowin(HANDLE hFile) {
{
    voidpf ret=NULL;

    if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE))
    {
        WIN32FILE_IOWIN w32fiow;
        w32fiow.hf = hFile;
        w32fiow.error = 0;
        ret = malloc(sizeof(WIN32FILE_IOWIN));

        if (ret==NULL)
            CloseHandle(hFile);
        else
            *((WIN32FILE_IOWIN*)ret) = w32fiow;
    }
    return ret;
}

voidpf ZCALLBACK win32_open64_file_func (voidpf opaque,const void* filename,int mode)
voidpf ZCALLBACK win32_open64_file_func(voidpf opaque, const void* filename, int mode) {
{
    const char* mode_fopen = NULL;
    DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
    HANDLE hFile = NULL;

    win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes);

#ifdef IOWIN32_USING_WINRT_API
118
119
120
121
122
123
124
125

126
127
128
129
130
131
132
133
112
113
114
115
116
117
118

119

120
121
122
123
124
125
126







-
+
-







        hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL);
#endif

    return win32_build_iowin(hFile);
}


voidpf ZCALLBACK win32_open64_file_funcA (voidpf opaque,const void* filename,int mode)
voidpf ZCALLBACK win32_open64_file_funcA(voidpf opaque, const void* filename, int mode) {
{
    const char* mode_fopen = NULL;
    DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
    HANDLE hFile = NULL;

    win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes);

#ifdef IOWIN32_USING_WINRT_API
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
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







-
+
-


















-
+
-







        hFile = CreateFileA((LPCSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL);
#endif

    return win32_build_iowin(hFile);
}


voidpf ZCALLBACK win32_open64_file_funcW (voidpf opaque,const void* filename,int mode)
voidpf ZCALLBACK win32_open64_file_funcW(voidpf opaque, const void* filename, int mode) {
{
    const char* mode_fopen = NULL;
    DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
    HANDLE hFile = NULL;

    win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes);

#ifdef IOWIN32_USING_WINRT_API
    if ((filename!=NULL) && (dwDesiredAccess != 0))
        hFile = CreateFile2((LPCWSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition,NULL);
#else
    if ((filename!=NULL) && (dwDesiredAccess != 0))
        hFile = CreateFileW((LPCWSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL);
#endif

    return win32_build_iowin(hFile);
}


voidpf ZCALLBACK win32_open_file_func (voidpf opaque,const char* filename,int mode)
voidpf ZCALLBACK win32_open_file_func(voidpf opaque, const char* filename, int mode) {
{
    const char* mode_fopen = NULL;
    DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
    HANDLE hFile = NULL;

    win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes);

#ifdef IOWIN32_USING_WINRT_API
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
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







-
+
-




















-
+
-



















-
+
-


















-
+
-







        hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL);
#endif

    return win32_build_iowin(hFile);
}


uLong ZCALLBACK win32_read_file_func (voidpf opaque, voidpf stream, void* buf,uLong size)
uLong ZCALLBACK win32_read_file_func(voidpf opaque, voidpf stream, void* buf,uLong size) {
{
    uLong ret=0;
    HANDLE hFile = NULL;
    if (stream!=NULL)
        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;

    if (hFile != NULL)
    {
        if (!ReadFile(hFile, buf, size, &ret, NULL))
        {
            DWORD dwErr = GetLastError();
            if (dwErr == ERROR_HANDLE_EOF)
                dwErr = 0;
            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
        }
    }

    return ret;
}


uLong ZCALLBACK win32_write_file_func (voidpf opaque,voidpf stream,const void* buf,uLong size)
uLong ZCALLBACK win32_write_file_func(voidpf opaque, voidpf stream, const void* buf, uLong size) {
{
    uLong ret=0;
    HANDLE hFile = NULL;
    if (stream!=NULL)
        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;

    if (hFile != NULL)
    {
        if (!WriteFile(hFile, buf, size, &ret, NULL))
        {
            DWORD dwErr = GetLastError();
            if (dwErr == ERROR_HANDLE_EOF)
                dwErr = 0;
            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
        }
    }

    return ret;
}

static BOOL MySetFilePointerEx(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *newPos,  DWORD dwMoveMethod)
static BOOL MySetFilePointerEx(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *newPos, DWORD dwMoveMethod) {
{
#ifdef IOWIN32_USING_WINRT_API
    return SetFilePointerEx(hFile, pos, newPos, dwMoveMethod);
#else
    LONG lHigh = pos.HighPart;
    DWORD dwNewPos = SetFilePointer(hFile, pos.LowPart, &lHigh, dwMoveMethod);
    BOOL fOk = TRUE;
    if (dwNewPos == 0xFFFFFFFF)
        if (GetLastError() != NO_ERROR)
            fOk = FALSE;
    if ((newPos != NULL) && (fOk))
    {
        newPos->LowPart = dwNewPos;
        newPos->HighPart = lHigh;
    }
    return fOk;
#endif
}

long ZCALLBACK win32_tell_file_func (voidpf opaque,voidpf stream)
long ZCALLBACK win32_tell_file_func(voidpf opaque, voidpf stream) {
{
    long ret=-1;
    HANDLE hFile = NULL;
    if (stream!=NULL)
        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
    if (hFile != NULL)
    {
        LARGE_INTEGER pos;
277
278
279
280
281
282
283
284

285
286
287
288
289
290
291
292
264
265
266
267
268
269
270

271

272
273
274
275
276
277
278







-
+
-







        }
        else
            ret=(long)pos.LowPart;
    }
    return ret;
}

ZPOS64_T ZCALLBACK win32_tell64_file_func (voidpf opaque, voidpf stream)
ZPOS64_T ZCALLBACK win32_tell64_file_func(voidpf opaque, voidpf stream) {
{
    ZPOS64_T ret= (ZPOS64_T)-1;
    HANDLE hFile = NULL;
    if (stream!=NULL)
        hFile = ((WIN32FILE_IOWIN*)stream)->hf;

    if (hFile)
    {
302
303
304
305
306
307
308
309

310
311
312
313
314
315
316
317
288
289
290
291
292
293
294

295

296
297
298
299
300
301
302







-
+
-







        else
            ret=pos.QuadPart;
    }
    return ret;
}


long ZCALLBACK win32_seek_file_func (voidpf opaque,voidpf stream,uLong offset,int origin)
long ZCALLBACK win32_seek_file_func(voidpf opaque, voidpf stream, uLong offset, int origin) {
{
    DWORD dwMoveMethod=0xFFFFFFFF;
    HANDLE hFile = NULL;

    long ret=-1;
    if (stream!=NULL)
        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
    switch (origin)
340
341
342
343
344
345
346
347

348
349
350
351
352
353
354
355
325
326
327
328
329
330
331

332

333
334
335
336
337
338
339







-
+
-







        }
        else
            ret=0;
    }
    return ret;
}

long ZCALLBACK win32_seek64_file_func (voidpf opaque, voidpf stream,ZPOS64_T offset,int origin)
long ZCALLBACK win32_seek64_file_func(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) {
{
    DWORD dwMoveMethod=0xFFFFFFFF;
    HANDLE hFile = NULL;
    long ret=-1;

    if (stream!=NULL)
        hFile = ((WIN32FILE_IOWIN*)stream)->hf;

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
442
443
444
445
446
447
448
449
450
451
452

453
454
455
456
457
458
459
460
461
462
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







-
+
-
















-
+
-








-
+
-










-
+
-











-
+
-











-
+
-









        }
        else
            ret=0;
    }
    return ret;
}

int ZCALLBACK win32_close_file_func (voidpf opaque, voidpf stream)
int ZCALLBACK win32_close_file_func(voidpf opaque, voidpf stream) {
{
    int ret=-1;

    if (stream!=NULL)
    {
        HANDLE hFile;
        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
        if (hFile != NULL)
        {
            CloseHandle(hFile);
            ret=0;
        }
        free(stream);
    }
    return ret;
}

int ZCALLBACK win32_error_file_func (voidpf opaque,voidpf stream)
int ZCALLBACK win32_error_file_func(voidpf opaque, voidpf stream) {
{
    int ret=-1;
    if (stream!=NULL)
    {
        ret = ((WIN32FILE_IOWIN*)stream) -> error;
    }
    return ret;
}

void fill_win32_filefunc (zlib_filefunc_def* pzlib_filefunc_def)
void fill_win32_filefunc(zlib_filefunc_def* pzlib_filefunc_def) {
{
    pzlib_filefunc_def->zopen_file = win32_open_file_func;
    pzlib_filefunc_def->zread_file = win32_read_file_func;
    pzlib_filefunc_def->zwrite_file = win32_write_file_func;
    pzlib_filefunc_def->ztell_file = win32_tell_file_func;
    pzlib_filefunc_def->zseek_file = win32_seek_file_func;
    pzlib_filefunc_def->zclose_file = win32_close_file_func;
    pzlib_filefunc_def->zerror_file = win32_error_file_func;
    pzlib_filefunc_def->opaque = NULL;
}

void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def)
void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def) {
{
    pzlib_filefunc_def->zopen64_file = win32_open64_file_func;
    pzlib_filefunc_def->zread_file = win32_read_file_func;
    pzlib_filefunc_def->zwrite_file = win32_write_file_func;
    pzlib_filefunc_def->ztell64_file = win32_tell64_file_func;
    pzlib_filefunc_def->zseek64_file = win32_seek64_file_func;
    pzlib_filefunc_def->zclose_file = win32_close_file_func;
    pzlib_filefunc_def->zerror_file = win32_error_file_func;
    pzlib_filefunc_def->opaque = NULL;
}


void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def)
void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def) {
{
    pzlib_filefunc_def->zopen64_file = win32_open64_file_funcA;
    pzlib_filefunc_def->zread_file = win32_read_file_func;
    pzlib_filefunc_def->zwrite_file = win32_write_file_func;
    pzlib_filefunc_def->ztell64_file = win32_tell64_file_func;
    pzlib_filefunc_def->zseek64_file = win32_seek64_file_func;
    pzlib_filefunc_def->zclose_file = win32_close_file_func;
    pzlib_filefunc_def->zerror_file = win32_error_file_func;
    pzlib_filefunc_def->opaque = NULL;
}


void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def)
void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def) {
{
    pzlib_filefunc_def->zopen64_file = win32_open64_file_funcW;
    pzlib_filefunc_def->zread_file = win32_read_file_func;
    pzlib_filefunc_def->zwrite_file = win32_write_file_func;
    pzlib_filefunc_def->ztell64_file = win32_tell64_file_func;
    pzlib_filefunc_def->zseek64_file = win32_seek64_file_func;
    pzlib_filefunc_def->zclose_file = win32_close_file_func;
    pzlib_filefunc_def->zerror_file = win32_error_file_func;
    pzlib_filefunc_def->opaque = NULL;
}

Changes to compat/zlib/contrib/minizip/iowin32.h.

14
15
16
17
18
19
20
21
22
23
24




25
26
27
28
14
15
16
17
18
19
20




21
22
23
24
25
26
27
28







-
-
-
-
+
+
+
+




#include <windows.h>


#ifdef __cplusplus
extern "C" {
#endif

void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
void fill_win32_filefunc64 OF((zlib_filefunc64_def* pzlib_filefunc_def));
void fill_win32_filefunc64A OF((zlib_filefunc64_def* pzlib_filefunc_def));
void fill_win32_filefunc64W OF((zlib_filefunc64_def* pzlib_filefunc_def));
void fill_win32_filefunc(zlib_filefunc_def* pzlib_filefunc_def);
void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def);
void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def);
void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def);

#ifdef __cplusplus
}
#endif

Changes to compat/zlib/contrib/minizip/miniunz.c.

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
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







-
+

















+







                #define _LARGEFILE64_SOURCE
        #endif
        #ifndef _FILE_OFFSET_BIT
                #define _FILE_OFFSET_BIT 64
        #endif
#endif

#ifdef __APPLE__
#if defined(__APPLE__) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64)
// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
#define FTELLO_FUNC(stream) ftello(stream)
#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
#else
#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
#define FTELLO_FUNC(stream) ftello64(stream)
#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
#endif


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>

#ifdef _WIN32
# include <direct.h>
# include <io.h>
#else
# include <unistd.h>
# include <utime.h>
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
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







-
+

-
-
+
-
-
-













+















+
+
+
+








-
-
+
-







+
+




-
-
+
-


-
+

-
+







  list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT
    if it exists
*/


/* change_file_date : change the date/time of a file
    filename : the filename of the file where date/time must be modified
    dosdate : the new date at the MSDos format (4 bytes)
    dosdate : the new date at the MSDOS format (4 bytes)
    tmu_date : the SAME new date at the tm_unz format */
void change_file_date(filename,dosdate,tmu_date)
    const char *filename;
static void change_file_date(const char *filename, uLong dosdate, tm_unz tmu_date) {
    uLong dosdate;
    tm_unz tmu_date;
{
#ifdef _WIN32
  HANDLE hFile;
  FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;

  hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE,
                      0,NULL,OPEN_EXISTING,0,NULL);
  GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);
  DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal);
  LocalFileTimeToFileTime(&ftLocal,&ftm);
  SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
  CloseHandle(hFile);
#else
#if defined(unix) || defined(__APPLE__)
  (void)dosdate;
  struct utimbuf ut;
  struct tm newdate;
  newdate.tm_sec = tmu_date.tm_sec;
  newdate.tm_min=tmu_date.tm_min;
  newdate.tm_hour=tmu_date.tm_hour;
  newdate.tm_mday=tmu_date.tm_mday;
  newdate.tm_mon=tmu_date.tm_mon;
  if (tmu_date.tm_year > 1900)
      newdate.tm_year=tmu_date.tm_year - 1900;
  else
      newdate.tm_year=tmu_date.tm_year ;
  newdate.tm_isdst=-1;

  ut.actime=ut.modtime=mktime(&newdate);
  utime(filename,&ut);
#else
  (void)filename;
  (void)dosdate;
  (void)tmu_date;
#endif
#endif
}


/* mymkdir and change_file_date are not 100 % portable
   As I don't know well Unix, I wait feedback for the unix portion */

int mymkdir(dirname)
    const char* dirname;
static int mymkdir(const char* dirname) {
{
    int ret=0;
#ifdef _WIN32
    ret = _mkdir(dirname);
#elif unix
    ret = mkdir (dirname,0775);
#elif __APPLE__
    ret = mkdir (dirname,0775);
#else
    (void)dirname;
#endif
    return ret;
}

int makedir (newdir)
    char *newdir;
static int makedir(const char *newdir) {
{
  char *buffer ;
  char *p;
  int  len = (int)strlen(newdir);
  size_t len = strlen(newdir);

  if (len <= 0)
  if (len == 0)
    return 0;

  buffer = (char*)malloc(len+1);
        if (buffer==NULL)
        {
                printf("Error allocating memory\n");
                return UNZ_INTERNALERROR;
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
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







-
+
-
-
+



-
+
-







-
+


-
+
-







        break;
      *p++ = hold;
    }
  free(buffer);
  return 1;
}

void do_banner()
static void do_banner(void) {
{
    printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n");
    printf("MiniUnz 1.1, demo of zLib + Unz package written by Gilles Vollant\n");
    printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");
}

void do_help()
static void do_help(void) {
{
    printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \
           "  -e  Extract without pathname (junk paths)\n" \
           "  -x  Extract with pathname\n" \
           "  -v  list files\n" \
           "  -l  list files\n" \
           "  -d  directory to extract into\n" \
           "  -o  overwrite files without prompting\n" \
           "  -p  extract crypted file using password\n\n");
           "  -p  extract encrypted file using password\n\n");
}

void Display64BitsSize(ZPOS64_T n, int size_char)
static void Display64BitsSize(ZPOS64_T n, int size_char) {
{
  /* to avoid compatibility problem , we do here the conversion */
  char number[21];
  int offset=19;
  int pos_string = 19;
  number[20]=0;
  for (;;) {
      number[offset]=(char)((n%10)+'0');
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
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







-
+
-
-














-
+










-
+







          printf(" ");
      }
  }

  printf("%s",&number[pos_string]);
}

int do_list(uf)
static int do_list(unzFile uf) {
    unzFile uf;
{
    uLong i;
    unz_global_info64 gi;
    int err;

    err = unzGetGlobalInfo64(uf,&gi);
    if (err!=UNZ_OK)
        printf("error %d with zipfile in unzGetGlobalInfo \n",err);
    printf("  Length  Method     Size Ratio   Date    Time   CRC-32     Name\n");
    printf("  ------  ------     ---- -----   ----    ----   ------     ----\n");
    for (i=0;i<gi.number_entry;i++)
    {
        char filename_inzip[256];
        unz_file_info64 file_info;
        uLong ratio=0;
        const char *string_method;
        const char *string_method = "";
        char charCrypt=' ';
        err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
        if (err!=UNZ_OK)
        {
            printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
            break;
        }
        if (file_info.uncompressed_size>0)
            ratio = (uLong)((file_info.compressed_size*100)/file_info.uncompressed_size);

        /* display a '*' if the file is crypted */
        /* display a '*' if the file is encrypted */
        if ((file_info.flag & 1) != 0)
            charCrypt='*';

        if (file_info.compression_method==0)
            string_method="Stored";
        else
        if (file_info.compression_method==Z_DEFLATED)
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
300
301
302
303
304
305
306



307



308
309
310
311
312
313
314
315
316

317
318
319
320
321
322
323







-
-
-
+
-
-
-









-







        }
    }

    return 0;
}


int do_extract_currentfile(uf,popt_extract_without_path,popt_overwrite,password)
    unzFile uf;
    const int* popt_extract_without_path;
static int do_extract_currentfile(unzFile uf, const int* popt_extract_without_path, int* popt_overwrite, const char* password) {
    int* popt_overwrite;
    const char* password;
{
    char filename_inzip[256];
    char* filename_withoutpath;
    char* p;
    int err=UNZ_OK;
    FILE *fout=NULL;
    void* buf;
    uInt size_buf;

    unz_file_info64 file_info;
    uLong ratio=0;
    err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);

    if (err!=UNZ_OK)
    {
        printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
        return err;
    }
362
363
364
365
366
367
368














369
370
371
372
373
374
375
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+







        const char* write_filename;
        int skip=0;

        if ((*popt_extract_without_path)==0)
            write_filename = filename_inzip;
        else
            write_filename = filename_withoutpath;

        if (write_filename[0]!='\0')
        {
            const char* relative_check = write_filename;
            while (relative_check[1]!='\0')
            {
                if (relative_check[0]=='.' && relative_check[1]=='.')
                    write_filename = relative_check;
                relative_check++;
            }
        }

        while (write_filename[0]=='/' || write_filename[0]=='.')
            write_filename++;

        err = unzOpenCurrentFilePassword(uf,password);
        if (err!=UNZ_OK)
        {
            printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
        }

435
436
437
438
439
440
441
442

443
444
445
446
447
448
449
438
439
440
441
442
443
444

445
446
447
448
449
450
451
452







-
+







                err = unzReadCurrentFile(uf,buf,size_buf);
                if (err<0)
                {
                    printf("error %d with zipfile in unzReadCurrentFile\n",err);
                    break;
                }
                if (err>0)
                    if (fwrite(buf,err,1,fout)!=1)
                    if (fwrite(buf,(unsigned)err,1,fout)!=1)
                    {
                        printf("error in writing extracted file\n");
                        err=UNZ_ERRNO;
                        break;
                    }
            }
            while (err>0);
468
469
470
471
472
473
474
475
476
477

478
479
480
481
482
483
484
485
486
487
488
489
490
491
471
472
473
474
475
476
477



478



479
480
481

482
483
484
485
486
487
488







-
-
-
+
-
-
-



-







    }

    free(buf);
    return err;
}


int do_extract(uf,opt_extract_without_path,opt_overwrite,password)
    unzFile uf;
    int opt_extract_without_path;
static int do_extract(unzFile uf, int opt_extract_without_path, int opt_overwrite, const char* password) {
    int opt_overwrite;
    const char* password;
{
    uLong i;
    unz_global_info64 gi;
    int err;
    FILE* fout=NULL;

    err = unzGetGlobalInfo64(uf,&gi);
    if (err!=UNZ_OK)
        printf("error %d with zipfile in unzGetGlobalInfo \n",err);

    for (i=0;i<gi.number_entry;i++)
    {
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
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







-
-
-
-
+
-
-
-
-















-
-
-
+
-







            }
        }
    }

    return 0;
}

int do_extract_onefile(uf,filename,opt_extract_without_path,opt_overwrite,password)
    unzFile uf;
    const char* filename;
    int opt_extract_without_path;
static int do_extract_onefile(unzFile uf, const char* filename, int opt_extract_without_path, int opt_overwrite, const char* password) {
    int opt_overwrite;
    const char* password;
{
    int err = UNZ_OK;
    if (unzLocateFile(uf,filename,CASESENSITIVITY)!=UNZ_OK)
    {
        printf("file %s not found in the zipfile\n",filename);
        return 2;
    }

    if (do_extract_currentfile(uf,&opt_extract_without_path,
                                      &opt_overwrite,
                                      password) == UNZ_OK)
        return 0;
    else
        return 1;
}


int main(argc,argv)
    int argc;
    char *argv[];
int main(int argc, char *argv[]) {
{
    const char *zipfilename=NULL;
    const char *filename_to_extract=NULL;
    const char *password=NULL;
    char filename_try[MAXFILENAME+16] = "";
    int i;
    int ret_value=0;
    int opt_do_list=0;
561
562
563
564
565
566
567
568

569
570
571
572
573
574
575
548
549
550
551
552
553
554

555
556
557
558
559
560
561
562







-
+







        {
            if ((*argv[i])=='-')
            {
                const char *p=argv[i]+1;

                while ((*p)!='\0')
                {
                    char c=*(p++);;
                    char c=*(p++);
                    if ((c=='l') || (c=='L'))
                        opt_do_list = 1;
                    if ((c=='v') || (c=='V'))
                        opt_do_list = 1;
                    if ((c=='x') || (c=='X'))
                        opt_do_extract = 1;
                    if ((c=='e') || (c=='E'))
603
604
605
606
607
608
609
610

611
612
613
614
615
616
617
590
591
592
593
594
595
596

597
598
599
600
601
602
603
604







-
+







    {

#        ifdef USEWIN32IOAPI
        zlib_filefunc64_def ffunc;
#        endif

        strncpy(filename_try, zipfilename,MAXFILENAME-1);
        /* strncpy doesnt append the trailing NULL, of the string is too long. */
        /* strncpy doesn't append the trailing NULL, of the string is too long. */
        filename_try[ MAXFILENAME ] = '\0';

#        ifdef USEWIN32IOAPI
        fill_win32_filefunc64A(&ffunc);
        uf = unzOpen2_64(zipfilename,&ffunc);
#        else
        uf = unzOpen64(zipfilename);

Changes to compat/zlib/contrib/minizip/minizip.c.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21













+







/*
   minizip.c
   Version 1.1, February 14h, 2010
   sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )

         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )

         Modifications of Unzip for Zip64
         Copyright (C) 2007-2008 Even Rouault

         Modifications for Zip64 support on both zip and unzip
         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
*/


#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
        #ifndef __USE_FILE_OFFSET64
                #define __USE_FILE_OFFSET64
        #endif
        #ifndef __USE_LARGEFILE64
                #define __USE_LARGEFILE64
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
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







+
+
+








-
-
-
-
+
+
+
-



















-
-
-
-
+
+
+
-
+








-
+




-
+







#endif

#include "zip.h"

#ifdef _WIN32
        #define USEWIN32IOAPI
        #include "iowin32.h"
#       if defined(_MSC_VER)
#           define snprintf _snprintf
#       endif
#endif



#define WRITEBUFFERSIZE (16384)
#define MAXFILENAME (256)

#ifdef _WIN32
uLong filetime(f, tmzip, dt)
    const char *f;         /* name of file to get info on */
    tm_zip *tmzip;         /* return value: access, modific. and creation times */
    uLong *dt;             /* dostime */
/* f: name of file to get info on, tmzip: return value: access,
   modification and creation times, dt: dostime */
static int filetime(const char *f, tm_zip *tmzip, uLong *dt) {
{
  int ret = 0;
  {
      FILETIME ftLocal;
      HANDLE hFind;
      WIN32_FIND_DATAA ff32;

      hFind = FindFirstFileA(f,&ff32);
      if (hFind != INVALID_HANDLE_VALUE)
      {
        FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);
        FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);
        FindClose(hFind);
        ret = 1;
      }
  }
  return ret;
}
#else
#if defined(unix) || defined(__APPLE__)
uLong filetime(f, tmzip, dt)
    const char *f;         /* name of file to get info on */
    tm_zip *tmzip;         /* return value: access, modific. and creation times */
    uLong *dt;             /* dostime */
/* f: name of file to get info on, tmzip: return value: access,
   modification and creation times, dt: dostime */
static int filetime(const char *f, tm_zip *tmzip, uLong *dt) {
{
  (void)dt;
  int ret=0;
  struct stat s;        /* results of stat() */
  struct tm* filedate;
  time_t tm_t=0;

  if (strcmp(f,"-")!=0)
  {
    char name[MAXFILENAME+1];
    int len = strlen(f);
    size_t len = strlen(f);
    if (len > MAXFILENAME)
      len = MAXFILENAME;

    strncpy(name, f,MAXFILENAME-1);
    /* strncpy doesnt append the trailing NULL, of the string is too long. */
    /* strncpy doesn't append the trailing NULL, of the string is too long. */
    name[ MAXFILENAME ] = '\0';

    if (name[len - 1] == '/')
      name[len - 1] = '\0';
    /* not all systems allow stat'ing a file with / appended */
    if (stat(name,&s)==0)
    {
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
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







-
-
-
-
+
+
+
-
+
+
+








-
-
+
-










-
+
-




-
+
-












-
+
-





-
+









-
+








-
-
+
+











-
+
-






-
-
+
+

-
+







  tmzip->tm_mday = filedate->tm_mday;
  tmzip->tm_mon  = filedate->tm_mon ;
  tmzip->tm_year = filedate->tm_year;

  return ret;
}
#else
uLong filetime(f, tmzip, dt)
    const char *f;         /* name of file to get info on */
    tm_zip *tmzip;         /* return value: access, modific. and creation times */
    uLong *dt;             /* dostime */
/* f: name of file to get info on, tmzip: return value: access,
   modification and creation times, dt: dostime */
static int filetime(const char *f, tm_zip *tmzip, uLong *dt) {
{
    (void)f;
    (void)tmzip;
    (void)dt;
    return 0;
}
#endif
#endif




int check_exist_file(filename)
    const char* filename;
static int check_exist_file(const char* filename) {
{
    FILE* ftestexist;
    int ret = 1;
    ftestexist = FOPEN_FUNC(filename,"rb");
    if (ftestexist==NULL)
        ret = 0;
    else
        fclose(ftestexist);
    return ret;
}

void do_banner()
static void do_banner(void) {
{
    printf("MiniZip 1.1, demo of zLib + MiniZip64 package, written by Gilles Vollant\n");
    printf("more info on MiniZip at http://www.winimage.com/zLibDll/minizip.html\n\n");
}

void do_help()
static void do_help(void) {
{
    printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] [-j] file.zip [files_to_add]\n\n" \
           "  -r  Scan directories recursively\n" \
           "  -o  Overwrite existing file.zip\n" \
           "  -a  Append to existing file.zip\n" \
           "  -0  Store only\n" \
           "  -1  Compress faster\n" \
           "  -9  Compress better\n\n" \
           "  -j  exclude path. store only the file name.\n\n");
}

/* calculate the CRC32 of a file,
   because to encrypt a file, we need known the CRC32 of the file before */
int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc)
static int getFileCrc(const char* filenameinzip, void* buf, unsigned long size_buf, unsigned long* result_crc) {
{
   unsigned long calculate_crc=0;
   int err=ZIP_OK;
   FILE * fin = FOPEN_FUNC(filenameinzip,"rb");

   unsigned long size_read = 0;
   unsigned long total_read = 0;
   /* unsigned long total_read = 0; */
   if (fin==NULL)
   {
       err = ZIP_ERRNO;
   }

    if (err == ZIP_OK)
        do
        {
            err = ZIP_OK;
            size_read = (int)fread(buf,1,size_buf,fin);
            size_read = fread(buf,1,size_buf,fin);
            if (size_read < size_buf)
                if (feof(fin)==0)
            {
                printf("error in reading %s\n",filenameinzip);
                err = ZIP_ERRNO;
            }

            if (size_read>0)
                calculate_crc = crc32(calculate_crc,buf,size_read);
            total_read += size_read;
                calculate_crc = crc32_z(calculate_crc,buf,size_read);
            /* total_read += size_read; */

        } while ((err == ZIP_OK) && (size_read>0));

    if (fin)
        fclose(fin);

    *result_crc=calculate_crc;
    printf("file %s crc %lx\n", filenameinzip, calculate_crc);
    return err;
}

int isLargeFile(const char* filename)
static int isLargeFile(const char* filename) {
{
  int largeFile = 0;
  ZPOS64_T pos = 0;
  FILE* pFile = FOPEN_FUNC(filename, "rb");

  if(pFile != NULL)
  {
    int n = FSEEKO_FUNC(pFile, 0, SEEK_END);
    pos = FTELLO_FUNC(pFile);
    FSEEKO_FUNC(pFile, 0, SEEK_END);
    pos = (ZPOS64_T)FTELLO_FUNC(pFile);

                printf("File : %s is %lld bytes\n", filename, pos);
                printf("File : %s is %llu bytes\n", filename, pos);

    if(pos >= 0xffffffff)
     largeFile = 1;

                fclose(pFile);
  }

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
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







-
+









-
+












-
-
-
+
-


-
+






-
+




















-
+










+







    }
}


void addPathToZip(zipFile zf, const char *filenameinzip, const char *password, int opt_exclude_path,int opt_compress_level) {
    tinydir_dir dir;
    int i;
    char newname[512];
    char newname[MAXFILENAME+1+MAXFILENAME+1];

    tinydir_open_sorted(&dir, filenameinzip);

    for (i = 0; i < dir.n_files; i++)
    {
        tinydir_file file;
        tinydir_readfile_n(&dir, &file, i);
        if(strcmp(file.name,".")==0) continue;
        if(strcmp(file.name,"..")==0) continue;
        sprintf(newname,"%s/%s",dir.path,file.name);
        snprintf(newname, sizeof(newname), "%.*s/%.*s", MAXFILENAME, dir.path, MAXFILENAME, file.name);
        if (file.is_dir)
        {
            addPathToZip(zf,newname,password,opt_exclude_path,opt_compress_level);
        } else {
            addFileToZip(zf,newname,password,opt_exclude_path,opt_compress_level);
        }
    }

    tinydir_close(&dir);
}


int main(argc,argv)
    int argc;
    char *argv[];
int main(int argc, char *argv[]) {
{
    int i;
    int opt_recursive=0;
    int opt_overwrite=1;
    int opt_overwrite=0;
    int opt_compress_level=Z_DEFAULT_COMPRESSION;
    int opt_exclude_path=0;
    int zipfilenamearg = 0;
    char filename_try[MAXFILENAME+16];
    int zipok;
    int err=0;
    int size_buf=0;
    size_t size_buf=0;
    void* buf=NULL;
    const char* password=NULL;


    do_banner();
    if (argc==1)
    {
        do_help();
        return 0;
    }
    else
    {
        for (i=1;i<argc;i++)
        {
            if ((*argv[i])=='-')
            {
                const char *p=argv[i]+1;

                while ((*p)!='\0')
                {
                    char c=*(p++);;
                    char c=*(p++);
                    if ((c=='o') || (c=='O'))
                        opt_overwrite = 1;
                    if ((c=='a') || (c=='A'))
                        opt_overwrite = 2;
                    if ((c>='0') && (c<='9'))
                        opt_compress_level = c-'0';
                    if ((c=='j') || (c=='J'))
                        opt_exclude_path = 1;
                    if ((c=='r') || (c=='R'))
                        opt_recursive = 1;

                    if (((c=='p') || (c=='P')) && (i+1<argc))
                    {
                        password=argv[i+1];
                        i++;
                    }
                }
            }
463
464
465
466
467
468
469
470

471
472
473
474
475
476
477
457
458
459
460
461
462
463

464
465
466
467
468
469
470
471







-
+







    else
    {
        int i,len;
        int dot_found=0;

        zipok = 1 ;
        strncpy(filename_try, argv[zipfilenamearg],MAXFILENAME-1);
        /* strncpy doesnt append the trailing NULL, of the string is too long. */
        /* strncpy doesn't append the trailing NULL, of the string is too long. */
        filename_try[ MAXFILENAME ] = '\0';

        len=(int)strlen(filename_try);
        for (i=0;i<len;i++)
            if (filename_try[i]=='.')
                dot_found=1;

Changes to compat/zlib/contrib/minizip/mztools.c.

23
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38
39
40
41
42
43
23
24
25
26
27
28
29

30






31
32
33
34
35
36
37







-
+
-
-
-
-
-
-







  WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \
} while(0)
#define WRITE_32(buff, n) do { \
  WRITE_16((unsigned char*)(buff), (n) & 0xffff); \
  WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \
} while(0)

extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered)
extern int ZEXPORT unzRepair(const char* file, const char* fileOut, const char* fileOutTmp, uLong* nRecovered, uLong* bytesRecovered) {
const char* file;
const char* fileOut;
const char* fileOutTmp;
uLong* nRecovered;
uLong* bytesRecovered;
{
  int err = Z_OK;
  FILE* fpZip = fopen(file, "rb");
  FILE* fpOut = fopen(fileOut, "wb");
  FILE* fpOutCD = fopen(fileOutTmp, "wb");
  if (fpZip != NULL &&  fpOut != NULL) {
    int entries = 0;
    uLong totalBytes = 0;

Changes to compat/zlib/contrib/minizip/tinydir.h.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
Copyright (c) 2013-2017, tinydir authors:
Copyright (c) 2013-2021, tinydir authors:
- Cong Xu
- Lautis Sun
- Baudouin Feildel
- Andargor <andargor@yahoo.com>
All rights reserved.

Redistribution and use in source and binary forms, with or without
41
42
43
44
45
46
47

48


49
50
51
52
53
54
55
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56
57







+
-
+
+







#define _UNICODE
#endif

#include <errno.h>
#include <stdlib.h>
#include <string.h>
#ifdef _MSC_VER
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
#  define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# include <tchar.h>
# pragma warning(push)
# pragma warning (disable : 4996)
#else
# include <dirent.h>
# include <libgen.h>
85
86
87
88
89
90
91

92


93
94
95
96

97


98
99
100
101
102
103
104
87
88
89
90
91
92
93
94

95
96
97
98
99
100
101

102
103
104
105
106
107
108
109
110







+
-
+
+




+
-
+
+







#endif

#if (defined _MSC_VER || defined __MINGW32__)
# include <windows.h>
# define _TINYDIR_PATH_MAX MAX_PATH
#elif defined  __linux__
# include <limits.h>
# ifdef PATH_MAX
# define _TINYDIR_PATH_MAX PATH_MAX
#  define _TINYDIR_PATH_MAX PATH_MAX
# endif
#elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
# include <sys/param.h>
# if defined(BSD)
#  include <limits.h>
#  ifdef PATH_MAX
#  define _TINYDIR_PATH_MAX PATH_MAX
#   define _TINYDIR_PATH_MAX PATH_MAX
#  endif
# endif
#endif

#ifndef _TINYDIR_PATH_MAX
#define _TINYDIR_PATH_MAX 4096
#endif

115
116
117
118
119
120
121





122
123

124
125
126
127
128
129
130
121
122
123
124
125
126
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141







+
+
+
+
+

-
+







#define _TINYDIR_DRIVE_MAX 3
#endif

#ifdef _MSC_VER
# define _TINYDIR_FUNC static __inline
#elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
# define _TINYDIR_FUNC static __inline__
#elif defined(__cplusplus)
# define _TINYDIR_FUNC static inline
#elif defined(__GNUC__)
/* Suppress unused function warning */
# define _TINYDIR_FUNC __attribute__((unused)) static
#else
# define _TINYDIR_FUNC static inline
# define _TINYDIR_FUNC static
#endif

/* readdir_r usage; define TINYDIR_USE_READDIR_R to use it (if supported) */
#ifdef TINYDIR_USE_READDIR_R

/* readdir_r is a POSIX-only function, and may not be available under various
 * environments/settings, e.g. MinGW. Use readdir fallback */
361
362
363
364
365
366
367
368

369
370
371
372
373
374
375
372
373
374
375
376
377
378

379
380
381
382
383
384
385
386







-
+







		if (tinydir_next(dir) == -1)
		{
			goto bail;
		}
	}
	tinydir_close(dir);

	if (tinydir_open(dir, path) == -1)
	if (n_files == 0 || tinydir_open(dir, path) == -1)
	{
		return -1;
	}

	dir->n_files = 0;
	dir->_files = (tinydir_file *)_TINYDIR_MALLOC(sizeof *dir->_files * n_files);
	if (dir->_files == NULL)
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
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







+














-
-
+

-
+

-
+

+
-
+






-
+
-
-
-
-
-
-






+
-
-
+
+
-
-
-
-
-
-
-
+








	return 0;
}

_TINYDIR_FUNC
int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
{
	const _tinydir_char_t *filename;
	if (dir == NULL || file == NULL)
	{
		errno = EINVAL;
		return -1;
	}
#ifdef _MSC_VER
	if (dir->_h == INVALID_HANDLE_VALUE)
#else
	if (dir->_e == NULL)
#endif
	{
		errno = ENOENT;
		return -1;
	}
	if (_tinydir_strlen(dir->path) +
		_tinydir_strlen(
	filename =
#ifdef _MSC_VER
			dir->_f.cFileName
		dir->_f.cFileName;
#else
			dir->_e->d_name
		dir->_e->d_name;
#endif
	if (_tinydir_strlen(dir->path) +
		) + 1 + _TINYDIR_PATH_EXTRA >=
		_tinydir_strlen(filename) + 1 + _TINYDIR_PATH_EXTRA >=
		_TINYDIR_PATH_MAX)
	{
		/* the path for the file will be too long */
		errno = ENAMETOOLONG;
		return -1;
	}
	if (_tinydir_strlen(
	if (_tinydir_strlen(filename) >= _TINYDIR_FILENAME_MAX)
#ifdef _MSC_VER
			dir->_f.cFileName
#else
			dir->_e->d_name
#endif
		) >= _TINYDIR_FILENAME_MAX)
	{
		errno = ENAMETOOLONG;
		return -1;
	}

	_tinydir_strcpy(file->path, dir->path);
	if (_tinydir_strcmp(dir->path, TINYDIR_STRING("/")) != 0)
	_tinydir_strcat(file->path, TINYDIR_STRING("/"));
	_tinydir_strcpy(file->name,
		_tinydir_strcat(file->path, TINYDIR_STRING("/"));
	_tinydir_strcpy(file->name, filename);
#ifdef _MSC_VER
		dir->_f.cFileName
#else
		dir->_e->d_name
#endif
	);
	_tinydir_strcat(file->path, file->name);
	_tinydir_strcat(file->path, filename);
#ifndef _MSC_VER
#ifdef __MINGW32__
	if (_tstat(
#else
	if (stat(
#endif
		file->path, &file->_s) == -1)
654
655
656
657
658
659
660
661
662
663
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















707
708
709
710
711
712
713
655
656
657
658
659
660
661






662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729







-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-




-


+
+
+
+
+
+
+
+
+
















-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







		errno = ENAMETOOLONG;
		return -1;
	}

	/* Get the parent path */
#if (defined _MSC_VER || defined __MINGW32__)
#if ((defined _MSC_VER) && (_MSC_VER >= 1400))
		_tsplitpath_s(
			path,
			drive_buf, _TINYDIR_DRIVE_MAX,
			dir_name_buf, _TINYDIR_FILENAME_MAX,
			file_name_buf, _TINYDIR_FILENAME_MAX,
			ext_buf, _TINYDIR_FILENAME_MAX);
	errno = _tsplitpath_s(
		path,
		drive_buf, _TINYDIR_DRIVE_MAX,
		dir_name_buf, _TINYDIR_FILENAME_MAX,
		file_name_buf, _TINYDIR_FILENAME_MAX,
		ext_buf, _TINYDIR_FILENAME_MAX);
#else
		_tsplitpath(
			path,
			drive_buf,
			dir_name_buf,
			file_name_buf,
			ext_buf);
	_tsplitpath(
		path,
		drive_buf,
		dir_name_buf,
		file_name_buf,
		ext_buf);
#endif

/* _splitpath_s not work fine with only filename and widechar support */
#ifdef _UNICODE
		if (drive_buf[0] == L'\xFEFE')
			drive_buf[0] = '\0';
		if (dir_name_buf[0] == L'\xFEFE')
			dir_name_buf[0] = '\0';
#endif

	if (errno)
	{
		errno = EINVAL;
		return -1;
	}

/* _splitpath_s not work fine with only filename and widechar support */
#ifdef _UNICODE
	if (drive_buf[0] == L'\xFEFE')
		drive_buf[0] = '\0';
	if (dir_name_buf[0] == L'\xFEFE')
		dir_name_buf[0] = '\0';
#endif

	/* Emulate the behavior of dirname by returning "." for dir name if it's
	empty */
	if (drive_buf[0] == '\0' && dir_name_buf[0] == '\0')
	{
		_tinydir_strcpy(dir_name_buf, TINYDIR_STRING("."));
	}
	/* Concatenate the drive letter and dir name to form full dir name */
	_tinydir_strcat(drive_buf, dir_name_buf);
	dir_name = drive_buf;
	/* Concatenate the file name and extension to form base name */
	_tinydir_strcat(file_name_buf, ext_buf);
	base_name = file_name_buf;
#else
	_tinydir_strcpy(dir_name_buf, path);
	dir_name = dirname(dir_name_buf);
	_tinydir_strcpy(file_name_buf, path);
	base_name =basename(file_name_buf);
	base_name = basename(file_name_buf);
#endif

	/* Special case: if the path is a root dir, open the parent dir as the file */
#if (defined _MSC_VER || defined __MINGW32__)
	if (_tinydir_strlen(base_name) == 0)
#else
	if ((_tinydir_strcmp(base_name, TINYDIR_STRING("/"))) == 0)
#endif
	{
		memset(file, 0, sizeof * file);
		file->is_dir = 1;
		file->is_reg = 0;
		_tinydir_strcpy(file->path, dir_name);
		file->extension = file->path + _tinydir_strlen(file->path);
		return 0;
	}

	/* Open the parent directory */
	if (tinydir_open(&dir, dir_name) == -1)
	{
		return -1;
	}

Changes to compat/zlib/contrib/minizip/unzip.c.

45
46
47
48
49
50
51
52

53
54
55
56
57


58
59
60
61
62
63
64
45
46
47
48
49
50
51

52
53
54
55


56
57
58
59
60
61
62
63
64







-
+



-
-
+
+







  2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz*
  2007-2008 - Even Rouault - Remove old C style function prototypes
  2007-2008 - Even Rouault - Add unzip support for ZIP64

        Copyright (C) 2007-2008 Even Rouault


        Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again).
  Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again).
  Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G
                                should only read the compressed/uncompressed size from the Zip64 format if
                                the size from normal header was 0xFFFFFFFF
  Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant
        Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required)
  Oct-2009 - Mathias Svensson - Applied some bug fixes from patches received from Gilles Vollant
  Oct-2009 - Mathias Svensson - Applied support to unzip files with compression method BZIP2 (bzip2 lib is required)
                                Patch created by Daniel Borca

  Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer

  Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson

*/
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
73
74
75
76
77
78
79


80
81
82
83
84
85
86







-
-







#endif

#include "zlib.h"
#include "unzip.h"

#ifdef STDC
#  include <stddef.h>
#  include <string.h>
#  include <stdlib.h>
#endif
#ifdef NO_ERRNO_H
    extern int errno;
#else
#   include <errno.h>
#endif

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
105
106
107
108
109
110
111



112
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127







-
-
-








-
+







#ifndef UNZ_MAXFILENAMEINZIP
#define UNZ_MAXFILENAMEINZIP (256)
#endif

#ifndef ALLOC
# define ALLOC(size) (malloc(size))
#endif
#ifndef TRYFREE
# define TRYFREE(p) {if (p) free(p);}
#endif

#define SIZECENTRALDIRITEM (0x2e)
#define SIZEZIPLOCALHEADER (0x1e)


const char unz_copyright[] =
   " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";

/* unz_file_info_interntal contain internal info about a file in zipfile*/
/* unz_file_info64_internal contain internal info about a file in zipfile*/
typedef struct unz_file_info64_internal_s
{
    ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */
} unz_file_info64_internal;


/* file_in_zip_read_info_s contain internal information about a file in zipfile,
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
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







-
+












-
+







    ZPOS64_T total_out_64;

    uLong crc32;                /* crc32 of all data uncompressed */
    uLong crc32_wait;           /* crc32 we must obtain after decompress all */
    ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */
    ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/
    zlib_filefunc64_32_def z_filefunc;
    voidpf filestream;        /* io structore of the zipfile */
    voidpf filestream;        /* io structure of the zipfile */
    uLong compression_method;   /* compression method (0==store) */
    ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
    int   raw;
} file_in_zip64_read_info_s;


/* unz64_s contain internal information about the zipfile
*/
typedef struct
{
    zlib_filefunc64_32_def z_filefunc;
    int is64bitOpenFunction;
    voidpf filestream;        /* io structore of the zipfile */
    voidpf filestream;        /* io structure of the zipfile */
    unz_global_info64 gi;       /* public global information */
    ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
    ZPOS64_T num_file;             /* number of the current file in the zipfile*/
    ZPOS64_T pos_in_central_dir;   /* pos of the current file in the central dir*/
    ZPOS64_T current_file_ok;      /* flag about the usability of the current file*/
    ZPOS64_T central_pos;          /* position of the beginning of the central dir*/

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
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








+

-
+
-
-


+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
+




+







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
+
-







#    endif
} unz64_s;


#ifndef NOUNCRYPT
#include "crypt.h"
#endif


/* ===========================================================================
     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
   Reads a long in LSB order from the given gz_stream. Sets
   for end of file.
   IN assertion: the stream s has been successfully opened for reading.
*/

local int unz64local_getShort(const zlib_filefunc64_32_def* pzlib_filefunc_def,
                              voidpf filestream,
                              uLong *pX) {
    unsigned char c[2];
    int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,c,2);
    if (err==2)

local int unz64local_getByte OF((
    const zlib_filefunc64_32_def* pzlib_filefunc_def,
    voidpf filestream,
    int *pi));

local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)
{
    unsigned char c;
    int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1);
    if (err==1)
    {
        *pX = c[0] | ((uLong)c[1] << 8);
        return UNZ_OK;
    }
    else
    {
        *pX = 0;
        if (ZERROR64(*pzlib_filefunc_def,filestream))
            return UNZ_ERRNO;
        else
            return UNZ_EOF;
    }
}

local int unz64local_getLong(const zlib_filefunc64_32_def* pzlib_filefunc_def,
                             voidpf filestream,
                             uLong *pX) {
    unsigned char c[4];
    int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,c,4);
    if (err==4)
    {
        *pX = c[0] | ((uLong)c[1] << 8) | ((uLong)c[2] << 16) | ((uLong)c[3] << 24);
        return UNZ_OK;
    }
    else
    {
        *pX = 0;
        if (ZERROR64(*pzlib_filefunc_def,filestream))
            return UNZ_ERRNO;
        else
            return UNZ_EOF;
    }
}


local int unz64local_getLong64(const zlib_filefunc64_32_def* pzlib_filefunc_def,
                               voidpf filestream,
                               ZPOS64_T *pX) {
    unsigned char c[8];
    int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,c,8);
    if (err==8)
    {
        *pi = (int)c;
        *pX = c[0] | ((ZPOS64_T)c[1] << 8) | ((ZPOS64_T)c[2] << 16) | ((ZPOS64_T)c[3] << 24)
            | ((ZPOS64_T)c[4] << 32) | ((ZPOS64_T)c[5] << 40) | ((ZPOS64_T)c[6] << 48) | ((ZPOS64_T)c[7] << 56);
        return UNZ_OK;
    }
    else
    {
        *pX = 0;
        if (ZERROR64(*pzlib_filefunc_def,filestream))
            return UNZ_ERRNO;
        else
            return UNZ_EOF;
    }
}


/* ===========================================================================
   Reads a long in LSB order from the given gz_stream. Sets
*/
local int unz64local_getShort OF((
    const zlib_filefunc64_32_def* pzlib_filefunc_def,
    voidpf filestream,
    uLong *pX));

local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def,
                             voidpf filestream,
                             uLong *pX)
{
    uLong x ;
    int i = 0;
    int err;

    err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
    x = (uLong)i;

    if (err==UNZ_OK)
        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
    x |= ((uLong)i)<<8;

    if (err==UNZ_OK)
        *pX = x;
    else
        *pX = 0;
    return err;
}

local int unz64local_getLong OF((
    const zlib_filefunc64_32_def* pzlib_filefunc_def,
    voidpf filestream,
    uLong *pX));

local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def,
                            voidpf filestream,
                            uLong *pX)
{
    uLong x ;
    int i = 0;
    int err;

    err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
    x = (uLong)i;

    if (err==UNZ_OK)
        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
    x |= ((uLong)i)<<8;

    if (err==UNZ_OK)
        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
    x |= ((uLong)i)<<16;

    if (err==UNZ_OK)
        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
    x += ((uLong)i)<<24;

    if (err==UNZ_OK)
        *pX = x;
    else
        *pX = 0;
    return err;
}

local int unz64local_getLong64 OF((
    const zlib_filefunc64_32_def* pzlib_filefunc_def,
    voidpf filestream,
    ZPOS64_T *pX));


local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def,
                            voidpf filestream,
                            ZPOS64_T *pX)
{
    ZPOS64_T x ;
    int i = 0;
    int err;

    err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
    x = (ZPOS64_T)i;

    if (err==UNZ_OK)
        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
    x |= ((ZPOS64_T)i)<<8;

    if (err==UNZ_OK)
        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
    x |= ((ZPOS64_T)i)<<16;

    if (err==UNZ_OK)
        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
    x |= ((ZPOS64_T)i)<<24;

    if (err==UNZ_OK)
        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
    x |= ((ZPOS64_T)i)<<32;

    if (err==UNZ_OK)
        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
    x |= ((ZPOS64_T)i)<<40;

    if (err==UNZ_OK)
        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
    x |= ((ZPOS64_T)i)<<48;

    if (err==UNZ_OK)
        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
    x |= ((ZPOS64_T)i)<<56;

    if (err==UNZ_OK)
        *pX = x;
    else
        *pX = 0;
    return err;
}

/* My own strcmpi / strcasecmp */
local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2)
local int strcmpcasenosensitive_internal(const char* fileName1, const char* fileName2) {
{
    for (;;)
    {
        char c1=*(fileName1++);
        char c2=*(fileName2++);
        if ((c1>='a') && (c1<='z'))
            c1 -= 0x20;
        if ((c2>='a') && (c2<='z'))
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
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







-
-
-
+
+
+

-
+




-
-
+
+
-
-













+
+
+
+




-
-
+
-




-
+


-
+









-
+







#endif

#ifndef STRCMPCASENOSENTIVEFUNCTION
#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
#endif

/*
   Compare two filename (fileName1,fileName2).
   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
   Compare two filenames (fileName1,fileName2).
   If iCaseSensitivity = 1, comparison is case sensitive (like strcmp)
   If iCaseSensitivity = 2, comparison is not case sensitive (like strcmpi
                                                                or strcasecmp)
   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
   If iCaseSensitivity = 0, case sensitivity is default of your operating system
        (like 1 on Unix, 2 on Windows)

*/
extern int ZEXPORT unzStringFileNameCompare (const char*  fileName1,
                                                 const char*  fileName2,
                                                 int iCaseSensitivity)
                                             const char*  fileName2,
                                             int iCaseSensitivity) {

{
    if (iCaseSensitivity==0)
        iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;

    if (iCaseSensitivity==1)
        return strcmp(fileName1,fileName2);

    return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
}

#ifndef BUFREADCOMMENT
#define BUFREADCOMMENT (0x400)
#endif

#ifndef CENTRALDIRINVALID
#define CENTRALDIRINVALID ((ZPOS64_T)(-1))
#endif

/*
  Locate the Central directory of a zipfile (at the end, just before
    the global comment)
*/
local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream));
local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)
local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) {
{
    unsigned char* buf;
    ZPOS64_T uSizeFile;
    ZPOS64_T uBackRead;
    ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
    ZPOS64_T uPosFound=0;
    ZPOS64_T uPosFound=CENTRALDIRINVALID;

    if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
        return 0;
        return CENTRALDIRINVALID;


    uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);

    if (uMaxBack>uSizeFile)
        uMaxBack = uSizeFile;

    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
    if (buf==NULL)
        return 0;
        return CENTRALDIRINVALID;

    uBackRead = 4;
    while (uBackRead<uMaxBack)
    {
        uLong uReadSize;
        ZPOS64_T uReadPos ;
        int i;
451
452
453
454
455
456
457
458

459
460
461
462

463
464
465

466
467
468
469
470
471
472
473
474
475
476
477
478
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
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







-
+



-
+


-
+








-
-
-
-

-
+
-




-
+




-
+









-
+







        if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
            break;

        for (i=(int)uReadSize-3; (i--)>0;)
            if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
                ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
            {
                uPosFound = uReadPos+i;
                uPosFound = uReadPos+(unsigned)i;
                break;
            }

        if (uPosFound!=0)
        if (uPosFound!=CENTRALDIRINVALID)
            break;
    }
    TRYFREE(buf);
    free(buf);
    return uPosFound;
}


/*
  Locate the Central directory 64 of a zipfile (at the end, just before
    the global comment)
*/
local ZPOS64_T unz64local_SearchCentralDir64 OF((
    const zlib_filefunc64_32_def* pzlib_filefunc_def,
    voidpf filestream));

local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def,
                                      voidpf filestream)
                                             voidpf filestream) {
{
    unsigned char* buf;
    ZPOS64_T uSizeFile;
    ZPOS64_T uBackRead;
    ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
    ZPOS64_T uPosFound=0;
    ZPOS64_T uPosFound=CENTRALDIRINVALID;
    uLong uL;
                ZPOS64_T relativeOffset;

    if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
        return 0;
        return CENTRALDIRINVALID;


    uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);

    if (uMaxBack>uSizeFile)
        uMaxBack = uSizeFile;

    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
    if (buf==NULL)
        return 0;
        return CENTRALDIRINVALID;

    uBackRead = 4;
    while (uBackRead<uMaxBack)
    {
        uLong uReadSize;
        ZPOS64_T uReadPos;
        int i;
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

558
559

560
561
562
563

564
565
566
567

568
569
570

571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586



587
588
589
590
591
592
593
594
595
596




597
598
599
600
601
602
603
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

467
468
469
470

471
472
473
474

475
476
477

478
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







-
+



-
+


-
-
-
+
+
+



-
+



-
+

-
+

-
+

-
+



-
+



-
+

-
+



-
+



-
+


-
+













-
-
-
+
+
+
-





-
-
-
-
+
+
+
+







        if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
            break;

        for (i=(int)uReadSize-3; (i--)>0;)
            if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
                ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
            {
                uPosFound = uReadPos+i;
                uPosFound = uReadPos+(unsigned)i;
                break;
            }

        if (uPosFound!=0)
        if (uPosFound!=CENTRALDIRINVALID)
            break;
    }
    TRYFREE(buf);
    if (uPosFound == 0)
        return 0;
    free(buf);
    if (uPosFound == CENTRALDIRINVALID)
        return CENTRALDIRINVALID;

    /* Zip64 end of central directory locator */
    if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)
        return 0;
        return CENTRALDIRINVALID;

    /* the signature, already checked */
    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
        return 0;
        return CENTRALDIRINVALID;

    /* number of the disk with the start of the zip64 end of  central directory */
    /* number of the disk with the start of the zip64 end of central directory */
    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
        return 0;
        return CENTRALDIRINVALID;
    if (uL != 0)
        return 0;
        return CENTRALDIRINVALID;

    /* relative offset of the zip64 end of central directory record */
    if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK)
        return 0;
        return CENTRALDIRINVALID;

    /* total number of disks */
    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
        return 0;
        return CENTRALDIRINVALID;
    if (uL != 1)
        return 0;
        return CENTRALDIRINVALID;

    /* Goto end of central directory record */
    if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
        return 0;
        return CENTRALDIRINVALID;

     /* the signature */
    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
        return 0;
        return CENTRALDIRINVALID;

    if (uL != 0x06064b50)
        return 0;
        return CENTRALDIRINVALID;

    return relativeOffset;
}

/*
  Open a Zip file. path contain the full pathname (by example,
     on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
     "zlib/zlib114.zip".
     If the zipfile cannot be opened (file doesn't exist or in not valid), the
       return value is NULL.
     Else, the return value is a unzFile Handle, usable with other function
       of this unzip package.
*/
local unzFile unzOpenInternal (const void *path,
                               zlib_filefunc64_32_def* pzlib_filefunc64_32_def,
                               int is64bitOpenFunction)
local unzFile unzOpenInternal(const void *path,
                              zlib_filefunc64_32_def* pzlib_filefunc64_32_def,
                              int is64bitOpenFunction) {
{
    unz64_s us;
    unz64_s *s;
    ZPOS64_T central_pos;
    uLong   uL;

    uLong number_disk;          /* number of the current dist, used for
                                   spaning ZIP, unsupported, always 0*/
    uLong number_disk_with_CD;  /* number the the disk with central dir, used
                                   for spaning ZIP, unsupported, always 0*/
    uLong number_disk;          /* number of the current disk, used for
                                   spanning ZIP, unsupported, always 0*/
    uLong number_disk_with_CD;  /* number the disk with central dir, used
                                   for spanning ZIP, unsupported, always 0*/
    ZPOS64_T number_entry_CD;      /* total number of entries in
                                   the central dir
                                   (same than number_entry on nospan) */

    int err=UNZ_OK;

    if (unz_copyright[0]!=' ')
617
618
619
620
621
622
623
624

625
626
627
628
629
630
631
524
525
526
527
528
529
530

531
532
533
534
535
536
537
538







-
+







                                                 path,
                                                 ZLIB_FILEFUNC_MODE_READ |
                                                 ZLIB_FILEFUNC_MODE_EXISTING);
    if (us.filestream==NULL)
        return NULL;

    central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream);
    if (central_pos)
    if (central_pos!=CENTRALDIRINVALID)
    {
        uLong uS;
        ZPOS64_T uL64;

        us.isZip64 = 1;

        if (ZSEEK64(us.z_filefunc, us.filestream,
679
680
681
682
683
684
685
686

687
688
689
690
691
692
693
586
587
588
589
590
591
592

593
594
595
596
597
598
599
600







-
+







            err=UNZ_ERRNO;

        us.gi.size_comment = 0;
    }
    else
    {
        central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream);
        if (central_pos==0)
        if (central_pos==CENTRALDIRINVALID)
            err=UNZ_ERRNO;

        us.isZip64 = 0;

        if (ZSEEK64(us.z_filefunc, us.filestream,
                                        central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
            err=UNZ_ERRNO;
758
759
760
761
762
763
764
765
766


767
768
769
770
771
772
773
774
775
776
777
778
779


780
781
782
783
784
785
786
787
788
789
790
791
792
793

794
795
796
797
798

799
800
801
802
803
804
805
806
807
808

809
810
811
812
813
814
815
816
817
818
819

820
821
822
823
824
825
826
827
828

829
830
831
832
833
834
835
836
837
838

839
840
841
842
843
844
845
846
847
848
849
850

851
852

853
854
855
856
857
858



859
860
861
862



863
864
865
866
867
868
869
870
871
872
873
874
875
876









877
878
879
880
881
882
883
884
885
886
887
888

889
890
891
892
893
894
895
896
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
707
708
709
710

711

712
713
714
715
716
717
718
719
720

721
722
723
724
725
726
727
728
729

730

731
732
733
734
735
736
737
738

739

740
741
742
743
744
745
746
747
748
749

750
751

752

753
754



755
756
757
758



759
760
761
762
763
764
765
766









767
768
769
770
771
772
773
774
775












776

777
778
779
780
781
782
783







-
-
+
+
-










-
-
+
+
-












-
+
-



-
+
-








-
+
-









-
+








-
+
-








-
+
-










-
+

-
+
-


-
-
-
+
+
+

-
-
-
+
+
+





-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-







        *s=us;
        unzGoToFirstFile((unzFile)s);
    }
    return (unzFile)s;
}


extern unzFile ZEXPORT unzOpen2 (const char *path,
                                        zlib_filefunc_def* pzlib_filefunc32_def)
extern unzFile ZEXPORT unzOpen2(const char *path,
                                zlib_filefunc_def* pzlib_filefunc32_def) {
{
    if (pzlib_filefunc32_def != NULL)
    {
        zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
        fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
        return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 0);
    }
    else
        return unzOpenInternal(path, NULL, 0);
}

extern unzFile ZEXPORT unzOpen2_64 (const void *path,
                                     zlib_filefunc64_def* pzlib_filefunc_def)
extern unzFile ZEXPORT unzOpen2_64(const void *path,
                                   zlib_filefunc64_def* pzlib_filefunc_def) {
{
    if (pzlib_filefunc_def != NULL)
    {
        zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
        zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
        zlib_filefunc64_32_def_fill.ztell32_file = NULL;
        zlib_filefunc64_32_def_fill.zseek32_file = NULL;
        return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 1);
    }
    else
        return unzOpenInternal(path, NULL, 1);
}

extern unzFile ZEXPORT unzOpen (const char *path)
extern unzFile ZEXPORT unzOpen(const char *path) {
{
    return unzOpenInternal(path, NULL, 0);
}

extern unzFile ZEXPORT unzOpen64 (const void *path)
extern unzFile ZEXPORT unzOpen64(const void *path) {
{
    return unzOpenInternal(path, NULL, 1);
}

/*
  Close a ZipFile opened with unzOpen.
  If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
    these files MUST be closed with unzCloseCurrentFile before call unzClose.
  return UNZ_OK if there is no problem. */
extern int ZEXPORT unzClose (unzFile file)
extern int ZEXPORT unzClose(unzFile file) {
{
    unz64_s* s;
    if (file==NULL)
        return UNZ_PARAMERROR;
    s=(unz64_s*)file;

    if (s->pfile_in_zip_read!=NULL)
        unzCloseCurrentFile(file);

    ZCLOSE64(s->z_filefunc, s->filestream);
    TRYFREE(s);
    free(s);
    return UNZ_OK;
}


/*
  Write info about the ZipFile in the *pglobal_info structure.
  No preparation of the structure is needed
  return UNZ_OK if there is no problem. */
extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info)
extern int ZEXPORT unzGetGlobalInfo64(unzFile file, unz_global_info64* pglobal_info) {
{
    unz64_s* s;
    if (file==NULL)
        return UNZ_PARAMERROR;
    s=(unz64_s*)file;
    *pglobal_info=s->gi;
    return UNZ_OK;
}

extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32)
extern int ZEXPORT unzGetGlobalInfo(unzFile file, unz_global_info* pglobal_info32) {
{
    unz64_s* s;
    if (file==NULL)
        return UNZ_PARAMERROR;
    s=(unz64_s*)file;
    /* to do : check if number_entry is not truncated */
    pglobal_info32->number_entry = (uLong)s->gi.number_entry;
    pglobal_info32->size_comment = s->gi.size_comment;
    return UNZ_OK;
}
/*
   Translate date/time from Dos format to tm_unz (readable more easilty)
   Translate date/time from Dos format to tm_unz (readable more easily)
*/
local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm)
local void unz64local_DosDateToTmuDate(ZPOS64_T ulDosDate, tm_unz* ptm) {
{
    ZPOS64_T uDate;
    uDate = (ZPOS64_T)(ulDosDate>>16);
    ptm->tm_mday = (uInt)(uDate&0x1f) ;
    ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
    ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
    ptm->tm_mday = (int)(uDate&0x1f) ;
    ptm->tm_mon =  (int)((((uDate)&0x1E0)/0x20)-1) ;
    ptm->tm_year = (int)(((uDate&0x0FE00)/0x0200)+1980) ;

    ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
    ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
    ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
    ptm->tm_hour = (int) ((ulDosDate &0xF800)/0x800);
    ptm->tm_min =  (int) ((ulDosDate&0x7E0)/0x20) ;
    ptm->tm_sec =  (int) (2*(ulDosDate&0x1f)) ;
}

/*
  Get Info about the current file in the zipfile, with internal only info
*/
local int unz64local_GetCurrentFileInfoInternal OF((unzFile file,
                                                  unz_file_info64 *pfile_info,
                                                  unz_file_info64_internal
                                                  *pfile_info_internal,
                                                  char *szFileName,
                                                  uLong fileNameBufferSize,
                                                  void *extraField,
                                                  uLong extraFieldBufferSize,
                                                  char *szComment,
local int unz64local_GetCurrentFileInfoInternal(unzFile file,
                                                unz_file_info64 *pfile_info,
                                                unz_file_info64_internal
                                                *pfile_info_internal,
                                                char *szFileName,
                                                uLong fileNameBufferSize,
                                                void *extraField,
                                                uLong extraFieldBufferSize,
                                                char *szComment,
                                                  uLong commentBufferSize));

local int unz64local_GetCurrentFileInfoInternal (unzFile file,
                                                  unz_file_info64 *pfile_info,
                                                  unz_file_info64_internal
                                                  *pfile_info_internal,
                                                  char *szFileName,
                                                  uLong fileNameBufferSize,
                                                  void *extraField,
                                                  uLong extraFieldBufferSize,
                                                  char *szComment,
                                                  uLong commentBufferSize)
                                                uLong commentBufferSize) {
{
    unz64_s* s;
    unz_file_info64 file_info;
    unz_file_info64_internal file_info_internal;
    int err=UNZ_OK;
    uLong uMagic;
    long lSeek=0;
    uLong uL;
989
990
991
992
993
994
995
996

997
998
999
1000
1001
1002
1003
876
877
878
879
880
881
882

883
884
885
886
887
888
889
890







-
+







        if (file_info.size_file_extra<extraFieldBufferSize)
            uSizeRead = file_info.size_file_extra;
        else
            uSizeRead = extraFieldBufferSize;

        if (lSeek!=0)
        {
            if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
            if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
                lSeek=0;
            else
                err=UNZ_ERRNO;
        }

        if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
            if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead)
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
901
902
903
904
905
906
907

908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927







928
929
930
931
932
933





934
935
936
937
938
939






940
941
942
943
944
945
946






947
948
949
950
951
952
953
954
955
956
957
958
959







-
+



















-
-
-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+







                                uLong acc = 0;

        // since lSeek now points to after the extra field we need to move back
        lSeek -= file_info.size_file_extra;

        if (lSeek!=0)
        {
            if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
            if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
                lSeek=0;
            else
                err=UNZ_ERRNO;
        }

        while(acc < file_info.size_file_extra)
        {
            uLong headerId;
                                                uLong dataSize;

            if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK)
                err=UNZ_ERRNO;

            if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK)
                err=UNZ_ERRNO;

            /* ZIP64 extra fields */
            if (headerId == 0x0001)
            {
                                                        uLong uL;

                                                                if(file_info.uncompressed_size == MAXU32)
                                                                {
                                                                        if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
                                                                                        err=UNZ_ERRNO;
                                                                }
                if(file_info.uncompressed_size == MAXU32)
                {
                    if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
                        err=UNZ_ERRNO;
                }

                                                                if(file_info.compressed_size == MAXU32)
                                                                {
                                                                        if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
                                                                                  err=UNZ_ERRNO;
                                                                }
                if(file_info.compressed_size == MAXU32)
                {
                    if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
                        err=UNZ_ERRNO;
                }

                                                                if(file_info_internal.offset_curfile == MAXU32)
                                                                {
                                                                        /* Relative Header offset */
                                                                        if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
                                                                                err=UNZ_ERRNO;
                                                                }
                if(file_info_internal.offset_curfile == MAXU32)
                {
                    /* Relative Header offset */
                    if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
                        err=UNZ_ERRNO;
                }

                                                                if(file_info.disk_num_start == MAXU32)
                                                                {
                                                                        /* Disk Start Number */
                                                                        if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
                                                                                err=UNZ_ERRNO;
                                                                }
                if(file_info.disk_num_start == 0xffff)
                {
                    /* Disk Start Number */
                    if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
                        err=UNZ_ERRNO;
                }

            }
            else
            {
                if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0)
                    err=UNZ_ERRNO;
            }
1086
1087
1088
1089
1090
1091
1092
1093

1094
1095
1096
1097
1098
1099
1100
971
972
973
974
975
976
977

978
979
980
981
982
983
984
985







-
+







            uSizeRead = file_info.size_file_comment;
        }
        else
            uSizeRead = commentBufferSize;

        if (lSeek!=0)
        {
            if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
            if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
                lSeek=0;
            else
                err=UNZ_ERRNO;
        }

        if ((file_info.size_file_comment>0) && (commentBufferSize>0))
            if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128





1129
1130
1131
1132
1133



1134
1135
1136
1137
1138
1139
1140





1141
1142
1143
1144
1145
1146
1147
1148
1002
1003
1004
1005
1006
1007
1008





1009
1010
1011
1012
1013

1014



1015
1016
1017
1018
1019





1020
1021
1022
1023
1024

1025
1026
1027
1028
1029
1030
1031







-
-
-
-
-
+
+
+
+
+
-

-
-
-
+
+
+


-
-
-
-
-
+
+
+
+
+
-









/*
  Write info about the ZipFile in the *pglobal_info structure.
  No preparation of the structure is needed
  return UNZ_OK if there is no problem.
*/
extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file,
                                          unz_file_info64 * pfile_info,
                                          char * szFileName, uLong fileNameBufferSize,
                                          void *extraField, uLong extraFieldBufferSize,
                                          char* szComment,  uLong commentBufferSize)
extern int ZEXPORT unzGetCurrentFileInfo64(unzFile file,
                                           unz_file_info64 * pfile_info,
                                           char * szFileName, uLong fileNameBufferSize,
                                           void *extraField, uLong extraFieldBufferSize,
                                           char* szComment,  uLong commentBufferSize) {
{
    return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL,
                                                szFileName,fileNameBufferSize,
                                                extraField,extraFieldBufferSize,
                                                szComment,commentBufferSize);
                                                 szFileName,fileNameBufferSize,
                                                 extraField,extraFieldBufferSize,
                                                 szComment,commentBufferSize);
}

extern int ZEXPORT unzGetCurrentFileInfo (unzFile file,
                                          unz_file_info * pfile_info,
                                          char * szFileName, uLong fileNameBufferSize,
                                          void *extraField, uLong extraFieldBufferSize,
                                          char* szComment,  uLong commentBufferSize)
extern int ZEXPORT unzGetCurrentFileInfo(unzFile file,
                                         unz_file_info * pfile_info,
                                         char * szFileName, uLong fileNameBufferSize,
                                         void *extraField, uLong extraFieldBufferSize,
                                         char* szComment,  uLong commentBufferSize) {
{
    int err;
    unz_file_info64 file_info64;
    err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL,
                                                szFileName,fileNameBufferSize,
                                                extraField,extraFieldBufferSize,
                                                szComment,commentBufferSize);
    if ((err==UNZ_OK) && (pfile_info != NULL))
1158
1159
1160
1161
1162
1163
1164
1165

1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178

1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199

1200
1201
1202
1203
1204
1205
1206
1207
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







-
+












-
+
-



















-
+
-







        pfile_info->size_file_extra = file_info64.size_file_extra;
        pfile_info->size_file_comment = file_info64.size_file_comment;

        pfile_info->disk_num_start = file_info64.disk_num_start;
        pfile_info->internal_fa = file_info64.internal_fa;
        pfile_info->external_fa = file_info64.external_fa;

        pfile_info->tmu_date = file_info64.tmu_date,
        pfile_info->tmu_date = file_info64.tmu_date;


        pfile_info->compressed_size = (uLong)file_info64.compressed_size;
        pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size;

    }
    return err;
}
/*
  Set the current file of the zipfile to the first file.
  return UNZ_OK if there is no problem
*/
extern int ZEXPORT unzGoToFirstFile (unzFile file)
extern int ZEXPORT unzGoToFirstFile(unzFile file) {
{
    int err=UNZ_OK;
    unz64_s* s;
    if (file==NULL)
        return UNZ_PARAMERROR;
    s=(unz64_s*)file;
    s->pos_in_central_dir=s->offset_central_dir;
    s->num_file=0;
    err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
                                             &s->cur_file_info_internal,
                                             NULL,0,NULL,0,NULL,0);
    s->current_file_ok = (err == UNZ_OK);
    return err;
}

/*
  Set the current file of the zipfile to the next file.
  return UNZ_OK if there is no problem
  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
*/
extern int ZEXPORT unzGoToNextFile (unzFile  file)
extern int ZEXPORT unzGoToNextFile(unzFile file) {
{
    unz64_s* s;
    int err;

    if (file==NULL)
        return UNZ_PARAMERROR;
    s=(unz64_s*)file;
    if (!s->current_file_ok)
1225
1226
1227
1228
1229
1230
1231
1232

1233
1234
1235
1236
1237
1238
1239
1240
1106
1107
1108
1109
1110
1111
1112

1113

1114
1115
1116
1117
1118
1119
1120







-
+
-







  Try locate the file szFileName in the zipfile.
  For the iCaseSensitivity signification, see unzStringFileNameCompare

  return value :
  UNZ_OK if the file is found. It becomes the current file.
  UNZ_END_OF_LIST_OF_FILE if the file is not found
*/
extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity)
extern int ZEXPORT unzLocateFile(unzFile file, const char *szFileName, int iCaseSensitivity) {
{
    unz64_s* s;
    int err;

    /* We remember the 'current' position in the file so that we can jump
     * back there if we fail.
     */
    unz_file_info64 cur_file_infoSaved;
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
1354
1355
1356
1357
1358
1359
1360

1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1181
1182
1183
1184
1185
1186
1187

1188

1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202

1203



1204
1205
1206
1207
1208
1209
1210
1211
1212
1213

1214

1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234

1235



1236
1237
1238
1239
1240
1241
1242







-
+
-














-
+
-
-
-










-
+
-




















-
+
-
-
-







typedef struct unz_file_pos_s
{
    ZPOS64_T pos_in_zip_directory;   // offset in file
    ZPOS64_T num_of_file;            // # of file
} unz_file_pos;
*/

extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos*  file_pos)
extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) {
{
    unz64_s* s;

    if (file==NULL || file_pos==NULL)
        return UNZ_PARAMERROR;
    s=(unz64_s*)file;
    if (!s->current_file_ok)
        return UNZ_END_OF_LIST_OF_FILE;

    file_pos->pos_in_zip_directory  = s->pos_in_central_dir;
    file_pos->num_of_file           = s->num_file;

    return UNZ_OK;
}

extern int ZEXPORT unzGetFilePos(
extern int ZEXPORT unzGetFilePos(unzFile file, unz_file_pos* file_pos) {
    unzFile file,
    unz_file_pos* file_pos)
{
    unz64_file_pos file_pos64;
    int err = unzGetFilePos64(file,&file_pos64);
    if (err==UNZ_OK)
    {
        file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory;
        file_pos->num_of_file = (uLong)file_pos64.num_of_file;
    }
    return err;
}

extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos)
extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) {
{
    unz64_s* s;
    int err;

    if (file==NULL || file_pos==NULL)
        return UNZ_PARAMERROR;
    s=(unz64_s*)file;

    /* jump to the right spot */
    s->pos_in_central_dir = file_pos->pos_in_zip_directory;
    s->num_file           = file_pos->num_of_file;

    /* set the current file */
    err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
                                               &s->cur_file_info_internal,
                                               NULL,0,NULL,0,NULL,0);
    /* return results */
    s->current_file_ok = (err == UNZ_OK);
    return err;
}

extern int ZEXPORT unzGoToFilePos(
extern int ZEXPORT unzGoToFilePos(unzFile file, unz_file_pos* file_pos) {
    unzFile file,
    unz_file_pos* file_pos)
{
    unz64_file_pos file_pos64;
    if (file_pos == NULL)
        return UNZ_PARAMERROR;

    file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory;
    file_pos64.num_of_file = file_pos->num_of_file;
    return unzGoToFilePos64(file,&file_pos64);
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387



1388
1389
1390
1391
1392
1393
1394
1395
1250
1251
1252
1253
1254
1255
1256



1257
1258
1259

1260
1261
1262
1263
1264
1265
1266







-
-
-
+
+
+
-







/*
  Read the local header of the current zipfile
  Check the coherency of the local header and info in the end of central
        directory about this file
  store in *piSizeVar the size of extra info in local header
        (filename and size of extra field data)
*/
local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar,
                                                    ZPOS64_T * poffset_local_extrafield,
                                                    uInt  * psize_local_extrafield)
local int unz64local_CheckCurrentFileCoherencyHeader(unz64_s* s, uInt* piSizeVar,
                                                     ZPOS64_T * poffset_local_extrafield,
                                                     uInt  * psize_local_extrafield) {
{
    uLong uMagic,uData,uFlags;
    uLong size_filename;
    uLong size_extra_field;
    int err=UNZ_OK;

    *piSizeVar = 0;
    *poffset_local_extrafield = 0;
1465
1466
1467
1468
1469
1470
1471
1472
1473


1474
1475
1476
1477
1478
1479
1480
1481
1336
1337
1338
1339
1340
1341
1342


1343
1344

1345
1346
1347
1348
1349
1350
1351







-
-
+
+
-







    return err;
}

/*
  Open for reading data the current file in the zipfile.
  If there is no error and the file is opened, the return value is UNZ_OK.
*/
extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method,
                                            int* level, int raw, const char* password)
extern int ZEXPORT unzOpenCurrentFile3(unzFile file, int* method,
                                       int* level, int raw, const char* password) {
{
    int err=UNZ_OK;
    uInt iSizeVar;
    unz64_s* s;
    file_in_zip64_read_info_s* pfile_in_zip_read_info;
    ZPOS64_T offset_local_extrafield;  /* offset of the local extra field */
    uInt  size_local_extrafield;    /* size of the local extra field */
#    ifndef NOUNCRYPT
1505
1506
1507
1508
1509
1510
1511
1512

1513
1514
1515
1516
1517
1518
1519
1375
1376
1377
1378
1379
1380
1381

1382
1383
1384
1385
1386
1387
1388
1389







-
+







    pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
    pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
    pfile_in_zip_read_info->pos_local_extrafield=0;
    pfile_in_zip_read_info->raw=raw;

    if (pfile_in_zip_read_info->read_buffer==NULL)
    {
        TRYFREE(pfile_in_zip_read_info);
        free(pfile_in_zip_read_info);
        return UNZ_INTERNALERROR;
    }

    pfile_in_zip_read_info->stream_initialised=0;

    if (method!=NULL)
        *method = (int)s->cur_file_info.compression_method;
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
1432
1433
1434
1435
1436
1437
1438
1439

1440
1441
1442
1443
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







+
-
+



















+
-
+







      pfile_in_zip_read_info->stream.avail_in = 0;

      err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0);
      if (err == Z_OK)
        pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED;
      else
      {
        free(pfile_in_zip_read_info->read_buffer);
        TRYFREE(pfile_in_zip_read_info);
        free(pfile_in_zip_read_info);
        return err;
      }
#else
      pfile_in_zip_read_info->raw=1;
#endif
    }
    else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw))
    {
      pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
      pfile_in_zip_read_info->stream.zfree = (free_func)0;
      pfile_in_zip_read_info->stream.opaque = (voidpf)0;
      pfile_in_zip_read_info->stream.next_in = 0;
      pfile_in_zip_read_info->stream.avail_in = 0;

      err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
      if (err == Z_OK)
        pfile_in_zip_read_info->stream_initialised=Z_DEFLATED;
      else
      {
        free(pfile_in_zip_read_info->read_buffer);
        TRYFREE(pfile_in_zip_read_info);
        free(pfile_in_zip_read_info);
        return err;
      }
        /* windowBits is passed < 0 to tell that there is no zlib header.
         * Note that in this case inflate *requires* an extra "dummy" byte
         * after the compressed stream in order to complete decompression and
         * return Z_STREAM_END.
         * In unzip, i don't wait absolutely Z_STREAM_END because I known the
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
1506
1507
1508
1509
1510
1511
1512

1513

1514
1515
1516

1517

1518
1519
1520

1521

1522
1523
1524
1525
1526

1527

1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546

1547
1548
1549
1550
1551

1552

1553
1554
1555
1556
1557
1558
1559







-
+
-



-
+
-



-
+
-





-
+
-



















-
+




-
+
-







    }
#    endif


    return UNZ_OK;
}

extern int ZEXPORT unzOpenCurrentFile (unzFile file)
extern int ZEXPORT unzOpenCurrentFile(unzFile file) {
{
    return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
}

extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char*  password)
extern int ZEXPORT unzOpenCurrentFilePassword(unzFile file, const char* password) {
{
    return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
}

extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw)
extern int ZEXPORT unzOpenCurrentFile2(unzFile file, int* method, int* level, int raw) {
{
    return unzOpenCurrentFile3(file, method, level, raw, NULL);
}

/** Addition for GDAL : START */

extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file)
extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64(unzFile file) {
{
    unz64_s* s;
    file_in_zip64_read_info_s* pfile_in_zip_read_info;
    s=(unz64_s*)file;
    if (file==NULL)
        return 0; //UNZ_PARAMERROR;
    pfile_in_zip_read_info=s->pfile_in_zip_read;
    if (pfile_in_zip_read_info==NULL)
        return 0; //UNZ_PARAMERROR;
    return pfile_in_zip_read_info->pos_in_zipfile +
                         pfile_in_zip_read_info->byte_before_the_zipfile;
}

/** Addition for GDAL : END */

/*
  Read bytes from the current file.
  buf contain buffer where data must be copied
  len the size of buf.

  return the number of byte copied if somes bytes are copied
  return the number of byte copied if some bytes are copied
  return 0 if the end of file was reached
  return <0 with error code if there is an error
    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
*/
extern int ZEXPORT unzReadCurrentFile  (unzFile file, voidp buf, unsigned len)
extern int ZEXPORT unzReadCurrentFile(unzFile file, voidp buf, unsigned len) {
{
    int err=UNZ_OK;
    uInt iRead = 0;
    unz64_s* s;
    file_in_zip64_read_info_s* pfile_in_zip_read_info;
    if (file==NULL)
        return UNZ_PARAMERROR;
    s=(unz64_s*)file;
1763
1764
1765
1766
1767
1768
1769
1770

1771
1772
1773
1774
1775
1776
1777
1630
1631
1632
1633
1634
1635
1636

1637
1638
1639
1640
1641
1642
1643
1644







-
+








        if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
        {
            uInt uDoCopy,i ;

            if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
                (pfile_in_zip_read_info->rest_read_compressed == 0))
                return (iRead==0) ? UNZ_EOF : iRead;
                return (iRead==0) ? UNZ_EOF : (int)iRead;

            if (pfile_in_zip_read_info->stream.avail_out <
                            pfile_in_zip_read_info->stream.avail_in)
                uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
            else
                uDoCopy = pfile_in_zip_read_info->stream.avail_in ;

1853
1854
1855
1856
1857
1858
1859



1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874

1875
1876
1877
1878
1879
1880
1881

1882
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
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
1749
1750

1751
1752
1753
1754
1755
1756
1757
1758

1759

1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772

1773

1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791

1792

1793
1794
1795
1796
1797
1798
1799







+
+
+














-
+






-
+







-
+
-













-
+
-


















-
+
-







            */
            err=inflate(&pfile_in_zip_read_info->stream,flush);

            if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
              err = Z_DATA_ERROR;

            uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
            /* Detect overflow, because z_stream.total_out is uLong (32 bits) */
            if (uTotalOutAfter<uTotalOutBefore)
                uTotalOutAfter += 1LL << 32; /* Add maximum value of uLong + 1 */
            uOutThis = uTotalOutAfter-uTotalOutBefore;

            pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;

            pfile_in_zip_read_info->crc32 =
                crc32(pfile_in_zip_read_info->crc32,bufBefore,
                        (uInt)(uOutThis));

            pfile_in_zip_read_info->rest_read_uncompressed -=
                uOutThis;

            iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);

            if (err==Z_STREAM_END)
                return (iRead==0) ? UNZ_EOF : iRead;
                return (iRead==0) ? UNZ_EOF : (int)iRead;
            if (err!=Z_OK)
                break;
        }
    }

    if (err==Z_OK)
        return iRead;
        return (int)iRead;
    return err;
}


/*
  Give the current position in uncompressed data
*/
extern z_off_t ZEXPORT unztell (unzFile file)
extern z_off_t ZEXPORT unztell(unzFile file) {
{
    unz64_s* s;
    file_in_zip64_read_info_s* pfile_in_zip_read_info;
    if (file==NULL)
        return UNZ_PARAMERROR;
    s=(unz64_s*)file;
    pfile_in_zip_read_info=s->pfile_in_zip_read;

    if (pfile_in_zip_read_info==NULL)
        return UNZ_PARAMERROR;

    return (z_off_t)pfile_in_zip_read_info->stream.total_out;
}

extern ZPOS64_T ZEXPORT unztell64 (unzFile file)
extern ZPOS64_T ZEXPORT unztell64(unzFile file) {
{

    unz64_s* s;
    file_in_zip64_read_info_s* pfile_in_zip_read_info;
    if (file==NULL)
        return (ZPOS64_T)-1;
    s=(unz64_s*)file;
    pfile_in_zip_read_info=s->pfile_in_zip_read;

    if (pfile_in_zip_read_info==NULL)
        return (ZPOS64_T)-1;

    return pfile_in_zip_read_info->total_out_64;
}


/*
  return 1 if the end of file was reached, 0 elsewhere
*/
extern int ZEXPORT unzeof (unzFile file)
extern int ZEXPORT unzeof(unzFile file) {
{
    unz64_s* s;
    file_in_zip64_read_info_s* pfile_in_zip_read_info;
    if (file==NULL)
        return UNZ_PARAMERROR;
    s=(unz64_s*)file;
    pfile_in_zip_read_info=s->pfile_in_zip_read;

1949
1950
1951
1952
1953
1954
1955
1956

1957
1958
1959
1960
1961
1962
1963
1964
1816
1817
1818
1819
1820
1821
1822

1823

1824
1825
1826
1827
1828
1829
1830







-
+
-







  if buf==NULL, it return the size of the local extra field that can be read

  if buf!=NULL, len is the size of the buffer, the extra header is copied in
    buf.
  the return value is the number of bytes copied in buf, or (if <0)
    the error code
*/
extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len)
extern int ZEXPORT unzGetLocalExtrafield(unzFile file, voidp buf, unsigned len) {
{
    unz64_s* s;
    file_in_zip64_read_info_s* pfile_in_zip_read_info;
    uInt read_now;
    ZPOS64_T size_to_read;

    if (file==NULL)
        return UNZ_PARAMERROR;
1997
1998
1999
2000
2001
2002
2003
2004

2005
2006
2007
2008
2009
2010
2011
2012
1863
1864
1865
1866
1867
1868
1869

1870

1871
1872
1873
1874
1875
1876
1877







-
+
-







    return (int)read_now;
}

/*
  Close the file in zip opened with unzOpenCurrentFile
  Return UNZ_CRCERROR if all the file was read but the CRC is not good
*/
extern int ZEXPORT unzCloseCurrentFile (unzFile file)
extern int ZEXPORT unzCloseCurrentFile(unzFile file) {
{
    int err=UNZ_OK;

    unz64_s* s;
    file_in_zip64_read_info_s* pfile_in_zip_read_info;
    if (file==NULL)
        return UNZ_PARAMERROR;
    s=(unz64_s*)file;
2020
2021
2022
2023
2024
2025
2026
2027

2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038

2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051

2052
2053
2054
2055
2056
2057
2058
2059
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







-
+










-
+












-
+
-







        (!pfile_in_zip_read_info->raw))
    {
        if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
            err=UNZ_CRCERROR;
    }


    TRYFREE(pfile_in_zip_read_info->read_buffer);
    free(pfile_in_zip_read_info->read_buffer);
    pfile_in_zip_read_info->read_buffer = NULL;
    if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED)
        inflateEnd(&pfile_in_zip_read_info->stream);
#ifdef HAVE_BZIP2
    else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED)
        BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream);
#endif


    pfile_in_zip_read_info->stream_initialised = 0;
    TRYFREE(pfile_in_zip_read_info);
    free(pfile_in_zip_read_info);

    s->pfile_in_zip_read=NULL;

    return err;
}


/*
  Get the global comment string of the ZipFile, in the szComment buffer.
  uSizeBuf is the size of the szComment buffer.
  return the number of byte copied or an error code <0
*/
extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf)
extern int ZEXPORT unzGetGlobalComment(unzFile file, char * szComment, uLong uSizeBuf) {
{
    unz64_s* s;
    uLong uReadThis ;
    if (file==NULL)
        return (int)UNZ_PARAMERROR;
    s=(unz64_s*)file;

    uReadThis = uSizeBuf;
2072
2073
2074
2075
2076
2077
2078
2079

2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094

2095
2096
2097
2098
2099
2100
2101
2102
2103
2104

2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122

2123
2124
2125
1936
1937
1938
1939
1940
1941
1942

1943

1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956

1957

1958
1959
1960
1961
1962
1963
1964
1965

1966

1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982

1983

1984
1985







-
+
-













-
+
-








-
+
-
















-
+
-



    if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
        *(szComment+s->gi.size_comment)='\0';
    return (int)uReadThis;
}

/* Additions by RX '2004 */
extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file)
extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) {
{
    unz64_s* s;

    if (file==NULL)
          return 0; //UNZ_PARAMERROR;
    s=(unz64_s*)file;
    if (!s->current_file_ok)
      return 0;
    if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
      if (s->num_file==s->gi.number_entry)
         return 0;
    return s->pos_in_central_dir;
}

extern uLong ZEXPORT unzGetOffset (unzFile file)
extern uLong ZEXPORT unzGetOffset(unzFile file) {
{
    ZPOS64_T offset64;

    if (file==NULL)
          return 0; //UNZ_PARAMERROR;
    offset64 = unzGetOffset64(file);
    return (uLong)offset64;
}

extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos)
extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) {
{
    unz64_s* s;
    int err;

    if (file==NULL)
        return UNZ_PARAMERROR;
    s=(unz64_s*)file;

    s->pos_in_central_dir = pos;
    s->num_file = s->gi.number_entry;      /* hack */
    err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
                                              &s->cur_file_info_internal,
                                              NULL,0,NULL,0,NULL,0);
    s->current_file_ok = (err == UNZ_OK);
    return err;
}

extern int ZEXPORT unzSetOffset (unzFile file, uLong pos)
extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) {
{
    return unzSetOffset64(file,pos);
}

Changes to compat/zlib/contrib/minizip/unzip.h.

79
80
81
82
83
84
85
86
87
88
89
90
91






92
93
94
95
96
97
98
79
80
81
82
83
84
85






86
87
88
89
90
91
92
93
94
95
96
97
98







-
-
-
-
-
-
+
+
+
+
+
+







#define UNZ_BADZIPFILE                  (-103)
#define UNZ_INTERNALERROR               (-104)
#define UNZ_CRCERROR                    (-105)

/* tm_unz contain date/time info */
typedef struct tm_unz_s
{
    uInt tm_sec;            /* seconds after the minute - [0,59] */
    uInt tm_min;            /* minutes after the hour - [0,59] */
    uInt tm_hour;           /* hours since midnight - [0,23] */
    uInt tm_mday;           /* day of the month - [1,31] */
    uInt tm_mon;            /* months since January - [0,11] */
    uInt tm_year;           /* years - [1980..2044] */
    int tm_sec;             /* seconds after the minute - [0,59] */
    int tm_min;             /* minutes after the hour - [0,59] */
    int tm_hour;            /* hours since midnight - [0,23] */
    int tm_mday;            /* day of the month - [1,31] */
    int tm_mon;             /* months since January - [0,11] */
    int tm_year;            /* years - [1980..2044] */
} tm_unz;

/* unz_global_info structure contain global data about the ZIPfile
   These data comes from the end of central dir */
typedef struct unz_global_info64_s
{
    ZPOS64_T number_entry;         /* total number of entries in
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
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







-
-
-
+
+
+

-
-
-
+
+
+

-
+




-
-
+
+
















-
-
+
+





-
-
+
+





-
+






-
-
+
+

-
-
+
+






-
-
-
+
+
+










-
+





-
+






-
-
-
+
+
+







    uLong disk_num_start;       /* disk number start               2 bytes */
    uLong internal_fa;          /* internal file attributes        2 bytes */
    uLong external_fa;          /* external file attributes        4 bytes */

    tm_unz tmu_date;
} unz_file_info;

extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
                                                 const char* fileName2,
                                                 int iCaseSensitivity));
extern int ZEXPORT unzStringFileNameCompare(const char* fileName1,
                                            const char* fileName2,
                                            int iCaseSensitivity);
/*
   Compare two filename (fileName1,fileName2).
   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
   Compare two filenames (fileName1,fileName2).
   If iCaseSensitivity = 1, comparison is case sensitive (like strcmp)
   If iCaseSensitivity = 2, comparison is not case sensitive (like strcmpi
                                or strcasecmp)
   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
   If iCaseSensitivity = 0, case sensitivity is default of your operating system
    (like 1 on Unix, 2 on Windows)
*/


extern unzFile ZEXPORT unzOpen OF((const char *path));
extern unzFile ZEXPORT unzOpen64 OF((const void *path));
extern unzFile ZEXPORT unzOpen(const char *path);
extern unzFile ZEXPORT unzOpen64(const void *path);
/*
  Open a Zip file. path contain the full pathname (by example,
     on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
     "zlib/zlib113.zip".
     If the zipfile cannot be opened (file don't exist or in not valid), the
       return value is NULL.
     Else, the return value is a unzFile Handle, usable with other function
       of this unzip package.
     the "64" function take a const void* pointer, because the path is just the
       value passed to the open64_file_func callback.
     Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path
       is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char*
       does not describe the reality
*/


extern unzFile ZEXPORT unzOpen2 OF((const char *path,
                                    zlib_filefunc_def* pzlib_filefunc_def));
extern unzFile ZEXPORT unzOpen2(const char *path,
                                zlib_filefunc_def* pzlib_filefunc_def);
/*
   Open a Zip file, like unzOpen, but provide a set of file low level API
      for read/write the zip file (see ioapi.h)
*/

extern unzFile ZEXPORT unzOpen2_64 OF((const void *path,
                                    zlib_filefunc64_def* pzlib_filefunc_def));
extern unzFile ZEXPORT unzOpen2_64(const void *path,
                                   zlib_filefunc64_def* pzlib_filefunc_def);
/*
   Open a Zip file, like unz64Open, but provide a set of file low level API
      for read/write the zip file (see ioapi.h)
*/

extern int ZEXPORT unzClose OF((unzFile file));
extern int ZEXPORT unzClose(unzFile file);
/*
  Close a ZipFile opened with unzOpen.
  If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
    these files MUST be closed with unzCloseCurrentFile before call unzClose.
  return UNZ_OK if there is no problem. */

extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
                                        unz_global_info *pglobal_info));
extern int ZEXPORT unzGetGlobalInfo(unzFile file,
                                    unz_global_info *pglobal_info);

extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file,
                                        unz_global_info64 *pglobal_info));
extern int ZEXPORT unzGetGlobalInfo64(unzFile file,
                                      unz_global_info64 *pglobal_info);
/*
  Write info about the ZipFile in the *pglobal_info structure.
  No preparation of the structure is needed
  return UNZ_OK if there is no problem. */


extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
                                           char *szComment,
                                           uLong uSizeBuf));
extern int ZEXPORT unzGetGlobalComment(unzFile file,
                                       char *szComment,
                                       uLong uSizeBuf);
/*
  Get the global comment string of the ZipFile, in the szComment buffer.
  uSizeBuf is the size of the szComment buffer.
  return the number of byte copied or an error code <0
*/


/***************************************************************************/
/* Unzip package allow you browse the directory of the zipfile */

extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
extern int ZEXPORT unzGoToFirstFile(unzFile file);
/*
  Set the current file of the zipfile to the first file.
  return UNZ_OK if there is no problem
*/

extern int ZEXPORT unzGoToNextFile OF((unzFile file));
extern int ZEXPORT unzGoToNextFile(unzFile file);
/*
  Set the current file of the zipfile to the next file.
  return UNZ_OK if there is no problem
  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
*/

extern int ZEXPORT unzLocateFile OF((unzFile file,
                     const char *szFileName,
                     int iCaseSensitivity));
extern int ZEXPORT unzLocateFile(unzFile file,
                                 const char *szFileName,
                                 int iCaseSensitivity);
/*
  Try locate the file szFileName in the zipfile.
  For the iCaseSensitivity signification, see unzStringFileNameCompare

  return value :
  UNZ_OK if the file is found. It becomes the current file.
  UNZ_END_OF_LIST_OF_FILE if the file is not found
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
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
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
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







-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+


-
+

-
+











-
+









-
+





-
-
+
+






-
-
-
-
+
+
+
+









-
-
-
-
-
+
+
+
+
+










-
+





-
-
-
+
+
+





-
+





-
+

-
+




-
+




-
-
-
+
+
+








extern int ZEXPORT unzGoToFilePos64(
    unzFile file,
    const unz64_file_pos* file_pos);

/* ****************************************** */

extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file,
                         unz_file_info64 *pfile_info,
                         char *szFileName,
                         uLong fileNameBufferSize,
                         void *extraField,
                         uLong extraFieldBufferSize,
                         char *szComment,
                         uLong commentBufferSize));
extern int ZEXPORT unzGetCurrentFileInfo64(unzFile file,
                                           unz_file_info64 *pfile_info,
                                           char *szFileName,
                                           uLong fileNameBufferSize,
                                           void *extraField,
                                           uLong extraFieldBufferSize,
                                           char *szComment,
                                           uLong commentBufferSize);

extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
                         unz_file_info *pfile_info,
                         char *szFileName,
                         uLong fileNameBufferSize,
                         void *extraField,
                         uLong extraFieldBufferSize,
                         char *szComment,
                         uLong commentBufferSize));
extern int ZEXPORT unzGetCurrentFileInfo(unzFile file,
                                         unz_file_info *pfile_info,
                                         char *szFileName,
                                         uLong fileNameBufferSize,
                                         void *extraField,
                                         uLong extraFieldBufferSize,
                                         char *szComment,
                                         uLong commentBufferSize);
/*
  Get Info about the current file
  if pfile_info!=NULL, the *pfile_info structure will contain somes info about
  if pfile_info!=NULL, the *pfile_info structure will contain some info about
        the current file
  if szFileName!=NULL, the filemane string will be copied in szFileName
  if szFileName!=NULL, the filename string will be copied in szFileName
            (fileNameBufferSize is the size of the buffer)
  if extraField!=NULL, the extra field information will be copied in extraField
            (extraFieldBufferSize is the size of the buffer).
            This is the Central-header version of the extra field
  if szComment!=NULL, the comment string of the file will be copied in szComment
            (commentBufferSize is the size of the buffer)
*/


/** Addition for GDAL : START */

extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file));
extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64(unzFile file);

/** Addition for GDAL : END */


/***************************************************************************/
/* for reading the content of the current zipfile, you can open it, read data
   from it, and close it (you can close it before reading all the file)
   */

extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
extern int ZEXPORT unzOpenCurrentFile(unzFile file);
/*
  Open for reading data the current file in the zipfile.
  If there is no error, the return value is UNZ_OK.
*/

extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file,
                                                  const char* password));
extern int ZEXPORT unzOpenCurrentFilePassword(unzFile file,
                                              const char* password);
/*
  Open for reading data the current file in the zipfile.
  password is a crypting password
  If there is no error, the return value is UNZ_OK.
*/

extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file,
                                           int* method,
                                           int* level,
                                           int raw));
extern int ZEXPORT unzOpenCurrentFile2(unzFile file,
                                       int* method,
                                       int* level,
                                       int raw);
/*
  Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
    if raw==1
  *method will receive method of compression, *level will receive level of
     compression
  note : you can set level parameter as NULL (if you did not want known level,
         but you CANNOT set method parameter as NULL
*/

extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file,
                                           int* method,
                                           int* level,
                                           int raw,
                                           const char* password));
extern int ZEXPORT unzOpenCurrentFile3(unzFile file,
                                       int* method,
                                       int* level,
                                       int raw,
                                       const char* password);
/*
  Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
    if raw==1
  *method will receive method of compression, *level will receive level of
     compression
  note : you can set level parameter as NULL (if you did not want known level,
         but you CANNOT set method parameter as NULL
*/


extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
extern int ZEXPORT unzCloseCurrentFile(unzFile file);
/*
  Close the file in zip opened with unzOpenCurrentFile
  Return UNZ_CRCERROR if all the file was read but the CRC is not good
*/

extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
                      voidp buf,
                      unsigned len));
extern int ZEXPORT unzReadCurrentFile(unzFile file,
                                      voidp buf,
                                      unsigned len);
/*
  Read bytes from the current file (opened by unzOpenCurrentFile)
  buf contain buffer where data must be copied
  len the size of buf.

  return the number of byte copied if somes bytes are copied
  return the number of byte copied if some bytes are copied
  return 0 if the end of file was reached
  return <0 with error code if there is an error
    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
*/

extern z_off_t ZEXPORT unztell OF((unzFile file));
extern z_off_t ZEXPORT unztell(unzFile file);

extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file));
extern ZPOS64_T ZEXPORT unztell64(unzFile file);
/*
  Give the current position in uncompressed data
*/

extern int ZEXPORT unzeof OF((unzFile file));
extern int ZEXPORT unzeof(unzFile file);
/*
  return 1 if the end of file was reached, 0 elsewhere
*/

extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
                                             voidp buf,
                                             unsigned len));
extern int ZEXPORT unzGetLocalExtrafield(unzFile file,
                                         voidp buf,
                                         unsigned len);
/*
  Read extra field from the current file (opened by unzOpenCurrentFile)
  This is the local-header version of the extra field (sometimes, there is
    more info in the local-header version than in the central-header)

  if buf==NULL, it return the size of the local extra field

Changes to compat/zlib/contrib/minizip/zip.c.

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
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







-
+










+






-
-














-
+













-
-
-







         For more info read MiniZip_info.txt

         Changes
   Oct-2009 - Mathias Svensson - Remove old C style function prototypes
   Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives
   Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions.
   Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data
                                 It is used when recreting zip archive with RAW when deleting items from a zip.
                                 It is used when recreating zip archive with RAW when deleting items from a zip.
                                 ZIP64 data is automatically added to items that needs it, and existing ZIP64 data need to be removed.
   Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required)
   Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer

*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include "zlib.h"
#include "zip.h"

#ifdef STDC
#  include <stddef.h>
#  include <string.h>
#  include <stdlib.h>
#endif
#ifdef NO_ERRNO_H
    extern int errno;
#else
#   include <errno.h>
#endif


#ifndef local
#  define local static
#endif
/* compile with -Dlocal if your debugger can't find static symbols */

#ifndef VERSIONMADEBY
# define VERSIONMADEBY   (0x0) /* platform depedent */
# define VERSIONMADEBY   (0x0) /* platform dependent */
#endif

#ifndef Z_BUFSIZE
#define Z_BUFSIZE (64*1024) //(16384)
#endif

#ifndef Z_MAXFILENAMEINZIP
#define Z_MAXFILENAMEINZIP (256)
#endif

#ifndef ALLOC
# define ALLOC(size) (malloc(size))
#endif
#ifndef TRYFREE
# define TRYFREE(p) {if (p) free(p);}
#endif

/*
#define SIZECENTRALDIRITEM (0x2e)
#define SIZEZIPLOCALHEADER (0x1e)
*/

/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
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
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







-
+






-
+





-
+






-
+






-
+


-
+

















-
+
-












-
+
-



-
+




-
+
-



-
+
-





-
+
-














-
+







    bz_stream bstream;          /* bzLib stream structure for bziped */
#endif

    int  stream_initialised;    /* 1 is stream is initialised */
    uInt pos_in_buffered_data;  /* last written byte in buffered_data */

    ZPOS64_T pos_local_header;     /* offset of the local header of the file
                                     currenty writing */
                                     currently writing */
    char* central_header;       /* central header data for the current file */
    uLong size_centralExtra;
    uLong size_centralheader;   /* size of the central header for cur file */
    uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */
    uLong flag;                 /* flag of the file currently writing */

    int  method;                /* compression method of file currenty wr.*/
    int  method;                /* compression method of file currently wr.*/
    int  raw;                   /* 1 for directly writing raw data */
    Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
    uLong dosDate;
    uLong crc32;
    int  encrypt;
    int  zip64;               /* Add ZIP64 extened information in the extra field */
    int  zip64;               /* Add ZIP64 extended information in the extra field */
    ZPOS64_T pos_zip64extrainfo;
    ZPOS64_T totalCompressedData;
    ZPOS64_T totalUncompressedData;
#ifndef NOCRYPT
    unsigned long keys[3];     /* keys defining the pseudo-random sequence */
    const z_crc_t* pcrc_32_tab;
    int crypt_header_size;
    unsigned crypt_header_size;
#endif
} curfile64_info;

typedef struct
{
    zlib_filefunc64_32_def z_filefunc;
    voidpf filestream;        /* io structore of the zipfile */
    voidpf filestream;        /* io structure of the zipfile */
    linkedlist_data central_dir;/* datablock with central dir in construction*/
    int  in_opened_file_inzip;  /* 1 if a file in the zip is currently writ.*/
    curfile64_info ci;            /* info on the file curretly writing */
    curfile64_info ci;            /* info on the file currently writing */

    ZPOS64_T begin_pos;            /* position of the beginning of the zipfile */
    ZPOS64_T add_position_when_writing_offset;
    ZPOS64_T number_entry;

#ifndef NO_ADDFILEINEXISTINGZIP
    char *globalcomment;
#endif

} zip64_internal;


#ifndef NOCRYPT
#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED
#include "crypt.h"
#endif

local linkedlist_datablock_internal* allocate_new_datablock()
local linkedlist_datablock_internal* allocate_new_datablock(void) {
{
    linkedlist_datablock_internal* ldi;
    ldi = (linkedlist_datablock_internal*)
                 ALLOC(sizeof(linkedlist_datablock_internal));
    if (ldi!=NULL)
    {
        ldi->next_datablock = NULL ;
        ldi->filled_in_this_block = 0 ;
        ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ;
    }
    return ldi;
}

local void free_datablock(linkedlist_datablock_internal* ldi)
local void free_datablock(linkedlist_datablock_internal* ldi) {
{
    while (ldi!=NULL)
    {
        linkedlist_datablock_internal* ldinext = ldi->next_datablock;
        TRYFREE(ldi);
        free(ldi);
        ldi = ldinext;
    }
}

local void init_linkedlist(linkedlist_data* ll)
local void init_linkedlist(linkedlist_data* ll) {
{
    ll->first_block = ll->last_block = NULL;
}

local void free_linkedlist(linkedlist_data* ll)
local void free_linkedlist(linkedlist_data* ll) {
{
    free_datablock(ll->first_block);
    ll->first_block = ll->last_block = NULL;
}


local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len)
local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) {
{
    linkedlist_datablock_internal* ldi;
    const unsigned char* from_copy;

    if (ll==NULL)
        return ZIP_INTERNALERROR;

    if (ll->last_block == NULL)
    {
        ll->first_block = ll->last_block = allocate_new_datablock();
        if (ll->first_block == NULL)
            return ZIP_INTERNALERROR;
    }

    ldi = ll->last_block;
    from_copy = (unsigned char*)buf;
    from_copy = (const unsigned char*)buf;

    while (len>0)
    {
        uInt copy_this;
        uInt i;
        unsigned char* to_copy;

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
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
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
366
367
368
369
370
371
372



373

374
375
376
377
378
379
380







-
-
+
-















-
+





-
-
+
-



















-
+
-






-
-
+
+





-
-
-
+
-




















-
-
-
+
-


















-
-
-
+
-








#ifndef NO_ADDFILEINEXISTINGZIP
/* ===========================================================================
   Inputs a long in LSB order to the given file
   nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T)
*/

local int zip64local_putValue OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte));
local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte)
local int zip64local_putValue(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) {
{
    unsigned char buf[8];
    int n;
    for (n = 0; n < nbByte; n++)
    {
        buf[n] = (unsigned char)(x & 0xff);
        x >>= 8;
    }
    if (x != 0)
      {     /* data overflow - hack for ZIP64 (X Roche) */
      for (n = 0; n < nbByte; n++)
        {
          buf[n] = 0xff;
        }
      }

    if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte)
    if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,(uLong)nbByte)!=(uLong)nbByte)
        return ZIP_ERRNO;
    else
        return ZIP_OK;
}

local void zip64local_putValue_inmemory OF((void* dest, ZPOS64_T x, int nbByte));
local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte)
local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) {
{
    unsigned char* buf=(unsigned char*)dest;
    int n;
    for (n = 0; n < nbByte; n++) {
        buf[n] = (unsigned char)(x & 0xff);
        x >>= 8;
    }

    if (x != 0)
    {     /* data overflow - hack for ZIP64 */
       for (n = 0; n < nbByte; n++)
       {
          buf[n] = 0xff;
       }
    }
}

/****************************************************************************/


local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm)
local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) {
{
    uLong year = (uLong)ptm->tm_year;
    if (year>=1980)
        year-=1980;
    else if (year>=80)
        year-=80;
    return
      (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) |
        ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
      (uLong) (((uLong)(ptm->tm_mday) + (32 * (uLong)(ptm->tm_mon+1)) + (512 * year)) << 16) |
        (((uLong)ptm->tm_sec/2) + (32 * (uLong)ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
}


/****************************************************************************/

local int zip64local_getByte OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi));

local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,voidpf filestream,int* pi)
local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int* pi) {
{
    unsigned char c;
    int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1);
    if (err==1)
    {
        *pi = (int)c;
        return ZIP_OK;
    }
    else
    {
        if (ZERROR64(*pzlib_filefunc_def,filestream))
            return ZIP_ERRNO;
        else
            return ZIP_EOF;
    }
}


/* ===========================================================================
   Reads a long in LSB order from the given gz_stream. Sets
*/
local int zip64local_getShort OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX));

local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX)
local int zip64local_getShort(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) {
{
    uLong x ;
    int i = 0;
    int err;

    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
    x = (uLong)i;

    if (err==ZIP_OK)
        err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
    x += ((uLong)i)<<8;

    if (err==ZIP_OK)
        *pX = x;
    else
        *pX = 0;
    return err;
}

local int zip64local_getLong OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX));

local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX)
local int zip64local_getLong(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) {
{
    uLong x ;
    int i = 0;
    int err;

    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
    x = (uLong)i;

416
417
418
419
420
421
422
423
424
425
426

427
428
429
430
431
432
433
434
393
394
395
396
397
398
399

400


401

402
403
404
405
406
407
408







-

-
-
+
-







    if (err==ZIP_OK)
        *pX = x;
    else
        *pX = 0;
    return err;
}

local int zip64local_getLong64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX));


local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)
local int zip64local_getLong64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) {
{
  ZPOS64_T x;
  int i = 0;
  int err;

  err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
  x = (ZPOS64_T)i;

471
472
473
474
475
476
477
478
479
480

481
482
483
484
485
486
487
488
445
446
447
448
449
450
451



452

453
454
455
456
457
458
459







-
-
-
+
-







#ifndef BUFREADCOMMENT
#define BUFREADCOMMENT (0x400)
#endif
/*
  Locate the Central directory of a zipfile (at the end, just before
    the global comment)
*/
local ZPOS64_T zip64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream));

local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)
local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) {
{
  unsigned char* buf;
  ZPOS64_T uSizeFile;
  ZPOS64_T uBackRead;
  ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
  ZPOS64_T uPosFound=0;

  if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
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
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







-
+



-
-
+
+

-
+







-
-
-
+
-







    if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
      break;

    for (i=(int)uReadSize-3; (i--)>0;)
      if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
        ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
      {
        uPosFound = uReadPos+i;
        uPosFound = uReadPos+(unsigned)i;
        break;
      }

      if (uPosFound!=0)
        break;
    if (uPosFound!=0)
      break;
  }
  TRYFREE(buf);
  free(buf);
  return uPosFound;
}

/*
Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before
the global comment)
*/
local ZPOS64_T zip64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream));

local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)
local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) {
{
  unsigned char* buf;
  ZPOS64_T uSizeFile;
  ZPOS64_T uBackRead;
  ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
  ZPOS64_T uPosFound=0;
  uLong uL;
  ZPOS64_T relativeOffset;
582
583
584
585
586
587
588
589

590
591
592
593
594
595
596
597
598

599
600
601
602
603
604
605
606
607
608
609
610

611
612
613
614
615
616
617
550
551
552
553
554
555
556

557
558
559
560
561
562
563
564
565

566
567
568
569
570
571
572
573
574
575
576
577

578
579
580
581
582
583
584
585







-
+








-
+











-
+







      break;

    for (i=(int)uReadSize-3; (i--)>0;)
    {
      // Signature "0x07064b50" Zip64 end of central directory locater
      if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
      {
        uPosFound = uReadPos+i;
        uPosFound = uReadPos+(unsigned)i;
        break;
      }
    }

      if (uPosFound!=0)
        break;
  }

  TRYFREE(buf);
  free(buf);
  if (uPosFound == 0)
    return 0;

  /* Zip64 end of central directory locator */
  if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)
    return 0;

  /* the signature, already checked */
  if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
    return 0;

  /* number of the disk with the start of the zip64 end of  central directory */
  /* number of the disk with the start of the zip64 end of central directory */
  if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
    return 0;
  if (uL != 0)
    return 0;

  /* relative offset of the zip64 end of central directory record */
  if (zip64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=ZIP_OK)
633
634
635
636
637
638
639
640

641
642
643
644
645
646
647
648
649
650
651
652
653




654
655
656
657
658
659
660
601
602
603
604
605
606
607

608

609
610
611
612
613
614
615
616




617
618
619
620
621
622
623
624
625
626
627







-
+
-








-
-
-
-
+
+
+
+








  if (uL != 0x06064b50) // signature of 'Zip64 end of central directory'
    return 0;

  return relativeOffset;
}

int LoadCentralDirectoryRecord(zip64_internal* pziinit)
local int LoadCentralDirectoryRecord(zip64_internal* pziinit) {
{
  int err=ZIP_OK;
  ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/

  ZPOS64_T size_central_dir;     /* size of the central directory  */
  ZPOS64_T offset_central_dir;   /* offset of start of central directory */
  ZPOS64_T central_pos;
  uLong uL;

  uLong number_disk;          /* number of the current dist, used for
                              spaning ZIP, unsupported, always 0*/
  uLong number_disk_with_CD;  /* number the the disk with central dir, used
                              for spaning ZIP, unsupported, always 0*/
  uLong number_disk;          /* number of the current disk, used for
                              spanning ZIP, unsupported, always 0*/
  uLong number_disk_with_CD;  /* number of the disk with central dir, used
                              for spanning ZIP, unsupported, always 0*/
  ZPOS64_T number_entry;
  ZPOS64_T number_entry_CD;      /* total number of entries in
                                the central dir
                                (same than number_entry on nospan) */
  uLong VersionMadeBy;
  uLong VersionNeeded;
  uLong size_comment;
826
827
828
829
830
831
832
833

834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849

850
851
852
853
854
855
856
857
793
794
795
796
797
798
799

800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815

816

817
818
819
820
821
822
823







-
+















-
+
-







        err=ZIP_ERRNO;

      if (err==ZIP_OK)
        err = add_data_in_datablock(&pziinit->central_dir,buf_read, (uLong)read_this);

      size_central_dir_to_read-=read_this;
    }
    TRYFREE(buf_read);
    free(buf_read);
  }
  pziinit->begin_pos = byte_before_the_zipfile;
  pziinit->number_entry = number_entry_CD;

  if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0)
    err=ZIP_ERRNO;

  return err;
}


#endif /* !NO_ADDFILEINEXISTINGZIP*/


/************************************************************/
extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def)
extern zipFile ZEXPORT zipOpen3(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) {
{
    zip64_internal ziinit;
    zip64_internal* zi;
    int err=ZIP_OK;

    ziinit.z_filefunc.zseek32_file = NULL;
    ziinit.z_filefunc.ztell32_file = NULL;
    if (pzlib_filefunc64_32_def==NULL)
901
902
903
904
905
906
907
908

909
910

911
912
913
914
915
916
917
918
919
920

921
922
923
924
925
926
927
928
929
930
931
932

933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948

949
950
951
952
953

954
955
956
957
958

959
960
961
962
963
964
965
966
867
868
869
870
871
872
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

898
899
900
901
902
903
904
905
906
907
908
909
910
911

912

913
914
915

916

917
918
919

920

921
922
923
924
925
926
927







-
+

-
+









-
+
-










-
+
-














-
+
-



-
+
-



-
+
-







      *globalcomment = ziinit.globalcomment;
    }
#    endif /* !NO_ADDFILEINEXISTINGZIP*/

    if (err != ZIP_OK)
    {
#    ifndef NO_ADDFILEINEXISTINGZIP
        TRYFREE(ziinit.globalcomment);
        free(ziinit.globalcomment);
#    endif /* !NO_ADDFILEINEXISTINGZIP*/
        TRYFREE(zi);
        free(zi);
        return NULL;
    }
    else
    {
        *zi = ziinit;
        return (zipFile)zi;
    }
}

extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def)
extern zipFile ZEXPORT zipOpen2(const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) {
{
    if (pzlib_filefunc32_def != NULL)
    {
        zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
        fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
        return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill);
    }
    else
        return zipOpen3(pathname, append, globalcomment, NULL);
}

extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def)
extern zipFile ZEXPORT zipOpen2_64(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) {
{
    if (pzlib_filefunc_def != NULL)
    {
        zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
        zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
        zlib_filefunc64_32_def_fill.ztell32_file = NULL;
        zlib_filefunc64_32_def_fill.zseek32_file = NULL;
        return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill);
    }
    else
        return zipOpen3(pathname, append, globalcomment, NULL);
}



extern zipFile ZEXPORT zipOpen (const char* pathname, int append)
extern zipFile ZEXPORT zipOpen(const char* pathname, int append) {
{
    return zipOpen3((const void*)pathname,append,NULL,NULL);
}

extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append)
extern zipFile ZEXPORT zipOpen64(const void* pathname, int append) {
{
    return zipOpen3(pathname,append,NULL,NULL);
}

int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local)
local int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) {
{
  /* write the local header */
  int err;
  uInt size_filename = (uInt)strlen(filename);
  uInt size_extrafield = size_extrafield_local;

  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC, 4);

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
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
1024
1025
1026
1027
1028
1029







-
-
+
+
















-
-
-
-
-
-
-
+
+
+
+
+
+
+
-







      short DataSize = 16;
      ZPOS64_T CompressedSize = 0;
      ZPOS64_T UncompressedSize = 0;

      // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file)
      zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream);

      err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)HeaderID,2);
      err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)DataSize,2);
      err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)HeaderID,2);
      err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)DataSize,2);

      err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8);
      err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8);
  }

  return err;
}

/*
 NOTE.
 When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped
 before calling this function it can be done with zipRemoveExtraInfoBlock

 It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize
 unnecessary allocations.
 */
extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi,
                                         const void* extrafield_local, uInt size_extrafield_local,
                                         const void* extrafield_global, uInt size_extrafield_global,
                                         const char* comment, int method, int level, int raw,
                                         int windowBits,int memLevel, int strategy,
                                         const char* password, uLong crcForCrypting,
                                         uLong versionMadeBy, uLong flagBase, int zip64)
extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
                                           const void* extrafield_local, uInt size_extrafield_local,
                                           const void* extrafield_global, uInt size_extrafield_global,
                                           const char* comment, int method, int level, int raw,
                                           int windowBits,int memLevel, int strategy,
                                           const char* password, uLong crcForCrypting,
                                           uLong versionMadeBy, uLong flagBase, int zip64) {
{
    zip64_internal* zi;
    uInt size_filename;
    uInt size_comment;
    uInt i;
    int err = ZIP_OK;

#    ifdef NOCRYPT
1078
1079
1080
1081
1082
1083
1084











1085
1086
1087
1088
1089
1090
1091
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







+
+
+
+
+
+
+
+
+
+
+







#ifdef HAVE_BZIP2
    if ((method!=0) && (method!=Z_DEFLATED) && (method!=Z_BZIP2ED))
      return ZIP_PARAMERROR;
#else
    if ((method!=0) && (method!=Z_DEFLATED))
      return ZIP_PARAMERROR;
#endif

    // The filename and comment length must fit in 16 bits.
    if ((filename!=NULL) && (strlen(filename)>0xffff))
        return ZIP_PARAMERROR;
    if ((comment!=NULL) && (strlen(comment)>0xffff))
        return ZIP_PARAMERROR;
    // The extra field length must fit in 16 bits. If the member also requires
    // a Zip64 extra block, that will also need to fit within that 16-bit
    // length, but that will be checked for later.
    if ((size_extrafield_local>0xffff) || (size_extrafield_global>0xffff))
        return ZIP_PARAMERROR;

    zi = (zip64_internal*)file;

    if (zi->in_opened_file_inzip == 1)
    {
        err = zipCloseFileInZip (file);
        if (err != ZIP_OK)
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




1354
1355
1356
1357
1358
1359
1360






1361
1362
1363

1364
1365
1366
1367
1368
1369
1370
1371
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







-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+


-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+







-
+
-
-
-
-
-
-
-
+
+
+
+
+
+





-
+
-
-
-
-
-
-
-
+
+
+
+
+
+



-
-
-
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+


-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+


-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+


-
+
-







#    endif

    if (err==Z_OK)
        zi->in_opened_file_inzip = 1;
    return err;
}

extern int ZEXPORT zipOpenNewFileInZip4 (zipFile file, const char* filename, const zip_fileinfo* zipfi,
                                         const void* extrafield_local, uInt size_extrafield_local,
                                         const void* extrafield_global, uInt size_extrafield_global,
                                         const char* comment, int method, int level, int raw,
                                         int windowBits,int memLevel, int strategy,
                                         const char* password, uLong crcForCrypting,
                                         uLong versionMadeBy, uLong flagBase)
extern int ZEXPORT zipOpenNewFileInZip4(zipFile file, const char* filename, const zip_fileinfo* zipfi,
                                        const void* extrafield_local, uInt size_extrafield_local,
                                        const void* extrafield_global, uInt size_extrafield_global,
                                        const char* comment, int method, int level, int raw,
                                        int windowBits,int memLevel, int strategy,
                                        const char* password, uLong crcForCrypting,
                                        uLong versionMadeBy, uLong flagBase) {
{
    return zipOpenNewFileInZip4_64 (file, filename, zipfi,
                                 extrafield_local, size_extrafield_local,
                                 extrafield_global, size_extrafield_global,
                                 comment, method, level, raw,
                                 windowBits, memLevel, strategy,
                                 password, crcForCrypting, versionMadeBy, flagBase, 0);
    return zipOpenNewFileInZip4_64(file, filename, zipfi,
                                   extrafield_local, size_extrafield_local,
                                   extrafield_global, size_extrafield_global,
                                   comment, method, level, raw,
                                   windowBits, memLevel, strategy,
                                   password, crcForCrypting, versionMadeBy, flagBase, 0);
}

extern int ZEXPORT zipOpenNewFileInZip3 (zipFile file, const char* filename, const zip_fileinfo* zipfi,
                                         const void* extrafield_local, uInt size_extrafield_local,
                                         const void* extrafield_global, uInt size_extrafield_global,
                                         const char* comment, int method, int level, int raw,
                                         int windowBits,int memLevel, int strategy,
                                         const char* password, uLong crcForCrypting)
extern int ZEXPORT zipOpenNewFileInZip3(zipFile file, const char* filename, const zip_fileinfo* zipfi,
                                        const void* extrafield_local, uInt size_extrafield_local,
                                        const void* extrafield_global, uInt size_extrafield_global,
                                        const char* comment, int method, int level, int raw,
                                        int windowBits,int memLevel, int strategy,
                                        const char* password, uLong crcForCrypting) {
{
    return zipOpenNewFileInZip4_64 (file, filename, zipfi,
                                 extrafield_local, size_extrafield_local,
                                 extrafield_global, size_extrafield_global,
                                 comment, method, level, raw,
                                 windowBits, memLevel, strategy,
                                 password, crcForCrypting, VERSIONMADEBY, 0, 0);
    return zipOpenNewFileInZip4_64(file, filename, zipfi,
                                   extrafield_local, size_extrafield_local,
                                   extrafield_global, size_extrafield_global,
                                   comment, method, level, raw,
                                   windowBits, memLevel, strategy,
                                   password, crcForCrypting, VERSIONMADEBY, 0, 0);
}

extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
                                         const void* extrafield_local, uInt size_extrafield_local,
                                         const void* extrafield_global, uInt size_extrafield_global,
                                         const char* comment, int method, int level, int raw,
                                         int windowBits,int memLevel, int strategy,
                                         const char* password, uLong crcForCrypting, int zip64)
                                         const char* password, uLong crcForCrypting, int zip64) {
{
    return zipOpenNewFileInZip4_64 (file, filename, zipfi,
                                 extrafield_local, size_extrafield_local,
                                 extrafield_global, size_extrafield_global,
                                 comment, method, level, raw,
                                 windowBits, memLevel, strategy,
                                 password, crcForCrypting, VERSIONMADEBY, 0, zip64);
    return zipOpenNewFileInZip4_64(file, filename, zipfi,
                                   extrafield_local, size_extrafield_local,
                                   extrafield_global, size_extrafield_global,
                                   comment, method, level, raw,
                                   windowBits, memLevel, strategy,
                                   password, crcForCrypting, VERSIONMADEBY, 0, zip64);
}

extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi,
                                        const void* extrafield_local, uInt size_extrafield_local,
                                        const void* extrafield_global, uInt size_extrafield_global,
                                        const char* comment, int method, int level, int raw)
                                        const char* comment, int method, int level, int raw) {
{
    return zipOpenNewFileInZip4_64 (file, filename, zipfi,
                                 extrafield_local, size_extrafield_local,
                                 extrafield_global, size_extrafield_global,
                                 comment, method, level, raw,
                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
                                 NULL, 0, VERSIONMADEBY, 0, 0);
    return zipOpenNewFileInZip4_64(file, filename, zipfi,
                                   extrafield_local, size_extrafield_local,
                                   extrafield_global, size_extrafield_global,
                                   comment, method, level, raw,
                                   -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
                                   NULL, 0, VERSIONMADEBY, 0, 0);
}

extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
                                        const void* extrafield_local, uInt size_extrafield_local,
                                        const void* extrafield_global, uInt size_extrafield_global,
                                        const char* comment, int method, int level, int raw, int zip64)
                                           const void* extrafield_local, uInt size_extrafield_local,
                                           const void* extrafield_global, uInt size_extrafield_global,
                                           const char* comment, int method, int level, int raw, int zip64) {
{
    return zipOpenNewFileInZip4_64 (file, filename, zipfi,
                                 extrafield_local, size_extrafield_local,
                                 extrafield_global, size_extrafield_global,
                                 comment, method, level, raw,
                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
                                 NULL, 0, VERSIONMADEBY, 0, zip64);
    return zipOpenNewFileInZip4_64(file, filename, zipfi,
                                   extrafield_local, size_extrafield_local,
                                   extrafield_global, size_extrafield_global,
                                   comment, method, level, raw,
                                   -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
                                   NULL, 0, VERSIONMADEBY, 0, zip64);
}

extern int ZEXPORT zipOpenNewFileInZip64 (zipFile file, const char* filename, const zip_fileinfo* zipfi,
                                        const void* extrafield_local, uInt size_extrafield_local,
                                        const void*extrafield_global, uInt size_extrafield_global,
                                        const char* comment, int method, int level, int zip64)
extern int ZEXPORT zipOpenNewFileInZip64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
                                         const void* extrafield_local, uInt size_extrafield_local,
                                         const void*extrafield_global, uInt size_extrafield_global,
                                         const char* comment, int method, int level, int zip64) {
{
    return zipOpenNewFileInZip4_64 (file, filename, zipfi,
                                 extrafield_local, size_extrafield_local,
                                 extrafield_global, size_extrafield_global,
                                 comment, method, level, 0,
                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
                                 NULL, 0, VERSIONMADEBY, 0, zip64);
    return zipOpenNewFileInZip4_64(file, filename, zipfi,
                                   extrafield_local, size_extrafield_local,
                                   extrafield_global, size_extrafield_global,
                                   comment, method, level, 0,
                                   -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
                                   NULL, 0, VERSIONMADEBY, 0, zip64);
}

extern int ZEXPORT zipOpenNewFileInZip (zipFile file, const char* filename, const zip_fileinfo* zipfi,
                                        const void* extrafield_local, uInt size_extrafield_local,
                                        const void*extrafield_global, uInt size_extrafield_global,
                                        const char* comment, int method, int level)
extern int ZEXPORT zipOpenNewFileInZip(zipFile file, const char* filename, const zip_fileinfo* zipfi,
                                       const void* extrafield_local, uInt size_extrafield_local,
                                       const void*extrafield_global, uInt size_extrafield_global,
                                       const char* comment, int method, int level) {
{
    return zipOpenNewFileInZip4_64 (file, filename, zipfi,
                                 extrafield_local, size_extrafield_local,
                                 extrafield_global, size_extrafield_global,
                                 comment, method, level, 0,
                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
                                 NULL, 0, VERSIONMADEBY, 0, 0);
    return zipOpenNewFileInZip4_64(file, filename, zipfi,
                                   extrafield_local, size_extrafield_local,
                                   extrafield_global, size_extrafield_global,
                                   comment, method, level, 0,
                                   -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
                                   NULL, 0, VERSIONMADEBY, 0, 0);
}

local int zip64FlushWriteBuffer(zip64_internal* zi)
local int zip64FlushWriteBuffer(zip64_internal* zi) {
{
    int err=ZIP_OK;

    if (zi->ci.encrypt != 0)
    {
#ifndef NOCRYPT
        uInt i;
        int t;
1395
1396
1397
1398
1399
1400
1401
1402

1403
1404
1405
1406
1407
1408
1409
1410
1358
1359
1360
1361
1362
1363
1364

1365

1366
1367
1368
1369
1370
1371
1372







-
+
-









    zi->ci.pos_in_buffered_data = 0;

    return err;
}

extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned int len)
extern int ZEXPORT zipWriteInFileInZip(zipFile file, const void* buf, unsigned int len) {
{
    zip64_internal* zi;
    int err=ZIP_OK;

    if (file == NULL)
        return ZIP_PARAMERROR;
    zi = (zip64_internal*)file;

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
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1408
1409
1410
1411
1412
1413
1414

1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435





1436
1437
1438
1439
1440
1441
1442







-
+




















-
-
-
-
-








      if(err == BZ_RUN_OK)
        err = ZIP_OK;
    }
    else
#endif
    {
      zi->ci.stream.next_in = (Bytef*)buf;
      zi->ci.stream.next_in = (Bytef*)(uintptr_t)buf;
      zi->ci.stream.avail_in = len;

      while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
      {
          if (zi->ci.stream.avail_out == 0)
          {
              if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
                  err = ZIP_ERRNO;
              zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
              zi->ci.stream.next_out = zi->ci.buffered_data;
          }


          if(err != ZIP_OK)
              break;

          if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
          {
              uLong uTotalOutBefore = zi->ci.stream.total_out;
              err=deflate(&zi->ci.stream,  Z_NO_FLUSH);
              if(uTotalOutBefore > zi->ci.stream.total_out)
              {
                int bBreak = 0;
                bBreak++;
              }

              zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
          }
          else
          {
              uInt copy_this,i;
              if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
1502
1503
1504
1505
1506
1507
1508
1509

1510
1511
1512
1513
1514

1515
1516
1517
1518
1519

1520
1521
1522
1523
1524
1525
1526
1459
1460
1461
1462
1463
1464
1465

1466

1467
1468
1469

1470

1471
1472
1473

1474
1475
1476
1477
1478
1479
1480
1481







-
+
-



-
+
-



-
+







          }
      }// while(...)
    }

    return err;
}

extern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size, uLong crc32)
extern int ZEXPORT zipCloseFileInZipRaw(zipFile file, uLong uncompressed_size, uLong crc32) {
{
    return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32);
}

extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_size, uLong crc32)
extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_size, uLong crc32) {
{
    zip64_internal* zi;
    ZPOS64_T compressed_size;
    uLong invalidValue = 0xffffffff;
    short datasize = 0;
    unsigned datasize = 0;
    int err=ZIP_OK;

    if (file == NULL)
        return ZIP_PARAMERROR;
    zi = (zip64_internal*)file;

    if (zi->in_opened_file_inzip == 0)
1649
1650
1651
1652
1653
1654
1655
1656

1657
1658
1659
1660
1661
1662
1663
1604
1605
1606
1607
1608
1609
1610

1611
1612
1613
1614
1615
1616
1617
1618







-
+








    if(datasize > 0)
    {
      char* p = NULL;

      if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree)
      {
        // we can not write more data to the buffer that we have room for.
        // we cannot write more data to the buffer that we have room for.
        return ZIP_BADZIPFILE;
      }

      p = zi->ci.central_header + zi->ci.size_centralheader;

      // Add Extra Information Header for 'ZIP64 information'
      zip64local_putValue_inmemory(p, 0x0001, 2); // HeaderID
1743
1744
1745
1746
1747
1748
1749
1750

1751
1752
1753
1754
1755

1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777

1778
1779
1780
1781
1782
1783
1784
1785
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







-
+
-



-
+
-




















-
+
-








    zi->number_entry ++;
    zi->in_opened_file_inzip = 0;

    return err;
}

extern int ZEXPORT zipCloseFileInZip (zipFile file)
extern int ZEXPORT zipCloseFileInZip(zipFile file) {
{
    return zipCloseFileInZipRaw (file,0,0);
}

int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip)
local int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) {
{
  int err = ZIP_OK;
  ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writing_offset;

  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4);

  /*num disks*/
    if (err==ZIP_OK) /* number of the disk with the start of the central directory */
      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);

  /*relative offset*/
    if (err==ZIP_OK) /* Relative offset to the Zip64EndOfCentralDirectory */
      err = zip64local_putValue(&zi->z_filefunc,zi->filestream, pos,8);

  /*total disks*/ /* Do not support spawning of disk so always say 1 here*/
    if (err==ZIP_OK) /* number of the disk with the start of the central directory */
      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)1,4);

    return err;
}

int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip)
local int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) {
{
  int err = ZIP_OK;

  uLong Zip64DataSize = 44;

  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDHEADERMAGIC,4);

  if (err==ZIP_OK) /* size of this 'zip64 end of central directory' */
1809
1810
1811
1812
1813
1814
1815
1816
1817


1818
1819
1820
1821
1822
1823
1824
1761
1762
1763
1764
1765
1766
1767


1768
1769
1770
1771
1772
1773
1774
1775
1776







-
-
+
+







  if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */
  {
    ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
    err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8);
  }
  return err;
}
int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip)
{

local int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) {
  int err = ZIP_OK;

  /*signature*/
  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4);

  if (err==ZIP_OK) /* number of this disk */
    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
1857
1858
1859
1860
1861
1862
1863
1864

1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882

1883
1884
1885
1886
1887
1888
1889
1890
1809
1810
1811
1812
1813
1814
1815

1816

1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832

1833

1834
1835
1836
1837
1838
1839
1840







-
+
-
















-
+
-







    else
      err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writing_offset),4);
  }

   return err;
}

int Write_GlobalComment(zip64_internal* zi, const char* global_comment)
local int Write_GlobalComment(zip64_internal* zi, const char* global_comment) {
{
  int err = ZIP_OK;
  uInt size_global_comment = 0;

  if(global_comment != NULL)
    size_global_comment = (uInt)strlen(global_comment);

  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2);

  if (err == ZIP_OK && size_global_comment > 0)
  {
    if (ZWRITE64(zi->z_filefunc,zi->filestream, global_comment, size_global_comment) != size_global_comment)
      err = ZIP_ERRNO;
  }
  return err;
}

extern int ZEXPORT zipClose (zipFile file, const char* global_comment)
extern int ZEXPORT zipClose(zipFile file, const char* global_comment) {
{
    zip64_internal* zi;
    int err = 0;
    uLong size_centraldir = 0;
    ZPOS64_T centraldir_pos_inzip;
    ZPOS64_T pos;

    if (file == NULL)
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
1958
1959
1960
1961
1962

1963
1964
1965

1966
1967
1968
1969
1970
1971
1972
1868
1869
1870
1871
1872
1873
1874

1875
1876
1877
1878
1879
1880
1881
1882
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







-
+


















-
+

-
+




-
+
-









-
+


-
+







            size_centraldir += ldi->filled_in_this_block;
            ldi = ldi->next_datablock;
        }
    }
    free_linkedlist(&(zi->central_dir));

    pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
    if(pos >= 0xffffffff || zi->number_entry > 0xFFFF)
    if(pos >= 0xffffffff || zi->number_entry >= 0xFFFF)
    {
      ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream);
      Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);

      Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos);
    }

    if (err==ZIP_OK)
      err = Write_EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);

    if(err == ZIP_OK)
      err = Write_GlobalComment(zi, global_comment);

    if (ZCLOSE64(zi->z_filefunc,zi->filestream) != 0)
        if (err == ZIP_OK)
            err = ZIP_ERRNO;

#ifndef NO_ADDFILEINEXISTINGZIP
    TRYFREE(zi->globalcomment);
    free(zi->globalcomment);
#endif
    TRYFREE(zi);
    free(zi);

    return err;
}

extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHeader)
extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader) {
{
  char* p = pData;
  int size = 0;
  char* pNewHeader;
  char* pTmp;
  short header;
  short dataSize;

  int retVal = ZIP_OK;

  if(pData == NULL || *dataLen < 4)
  if(pData == NULL || dataLen == NULL || *dataLen < 4)
    return ZIP_PARAMERROR;

  pNewHeader = (char*)ALLOC(*dataLen);
  pNewHeader = (char*)ALLOC((unsigned)*dataLen);
  pTmp = pNewHeader;

  while(p < (pData + *dataLen))
  {
    header = *(short*)p;
    dataSize = *(((short*)p)+1);

1997
1998
1999
2000
2001
2002
2003
2004

2005
2006
2007
1946
1947
1948
1949
1950
1951
1952

1953
1954
1955
1956







-
+



    *dataLen = size;

    retVal = ZIP_OK;
  }
  else
    retVal = ZIP_ERRNO;

  TRYFREE(pNewHeader);
  free(pNewHeader);

  return retVal;
}

Changes to compat/zlib/contrib/minizip/zip.h.

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
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







-
-
-
-
-
-
+
+
+
+
+
+



















-
-
+
+
















-
+


-
-
-
-
+
+
+
+

-
+


-
+

+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+






-
+

-
+









-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-








-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-







-
-
-
+
+
+




-
+




-
-
-
+
+
+

-
-
-
+
+
+







-
-
+
+





-
+







#  endif
#endif
/* default memLevel */

/* tm_zip contain date/time info */
typedef struct tm_zip_s
{
    uInt tm_sec;            /* seconds after the minute - [0,59] */
    uInt tm_min;            /* minutes after the hour - [0,59] */
    uInt tm_hour;           /* hours since midnight - [0,23] */
    uInt tm_mday;           /* day of the month - [1,31] */
    uInt tm_mon;            /* months since January - [0,11] */
    uInt tm_year;           /* years - [1980..2044] */
    int tm_sec;             /* seconds after the minute - [0,59] */
    int tm_min;             /* minutes after the hour - [0,59] */
    int tm_hour;            /* hours since midnight - [0,23] */
    int tm_mday;            /* day of the month - [1,31] */
    int tm_mon;             /* months since January - [0,11] */
    int tm_year;            /* years - [1980..2044] */
} tm_zip;

typedef struct
{
    tm_zip      tmz_date;       /* date in understandable format           */
    uLong       dosDate;       /* if dos_date == 0, tmu_date is used      */
/*    uLong       flag;        */   /* general purpose bit flag        2 bytes */

    uLong       internal_fa;    /* internal file attributes        2 bytes */
    uLong       external_fa;    /* external file attributes        4 bytes */
} zip_fileinfo;

typedef const char* zipcharpc;


#define APPEND_STATUS_CREATE        (0)
#define APPEND_STATUS_CREATEAFTER   (1)
#define APPEND_STATUS_ADDINZIP      (2)

extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append));
extern zipFile ZEXPORT zipOpen(const char *pathname, int append);
extern zipFile ZEXPORT zipOpen64(const void *pathname, int append);
/*
  Create a zipfile.
     pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on
       an Unix computer "zlib/zlib113.zip".
     if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip
       will be created at the end of the file.
         (useful if the file contain a self extractor code)
     if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will
       add files in existing zip (be sure you don't add file that doesn't exist)
     If the zipfile cannot be opened, the return value is NULL.
     Else, the return value is a zipFile Handle, usable with other function
       of this zip package.
*/

/* Note : there is no delete function into a zipfile.
   If you want delete file into a zipfile, you must open a zipfile, and create another
   Of couse, you can use RAW reading and writing to copy the file you did not want delte
   Of course, you can use RAW reading and writing to copy the file you did not want delete
*/

extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,
                                   int append,
                                   zipcharpc* globalcomment,
                                   zlib_filefunc_def* pzlib_filefunc_def));
extern zipFile ZEXPORT zipOpen2(const char *pathname,
                                int append,
                                zipcharpc* globalcomment,
                                zlib_filefunc_def* pzlib_filefunc_def);

extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname,
extern zipFile ZEXPORT zipOpen2_64(const void *pathname,
                                   int append,
                                   zipcharpc* globalcomment,
                                   zlib_filefunc64_def* pzlib_filefunc_def));
                                   zlib_filefunc64_def* pzlib_filefunc_def);

extern zipFile ZEXPORT zipOpen3(const void *pathname,
                                int append,
                                zipcharpc* globalcomment,
                                zlib_filefunc64_32_def* pzlib_filefunc64_32_def);

extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
                       const char* filename,
                       const zip_fileinfo* zipfi,
                       const void* extrafield_local,
                       uInt size_extrafield_local,
                       const void* extrafield_global,
                       uInt size_extrafield_global,
                       const char* comment,
                       int method,
                       int level));
extern int ZEXPORT zipOpenNewFileInZip(zipFile file,
                                       const char* filename,
                                       const zip_fileinfo* zipfi,
                                       const void* extrafield_local,
                                       uInt size_extrafield_local,
                                       const void* extrafield_global,
                                       uInt size_extrafield_global,
                                       const char* comment,
                                       int method,
                                       int level);

extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file,
                       const char* filename,
                       const zip_fileinfo* zipfi,
                       const void* extrafield_local,
                       uInt size_extrafield_local,
                       const void* extrafield_global,
                       uInt size_extrafield_global,
                       const char* comment,
                       int method,
                       int level,
                       int zip64));
extern int ZEXPORT zipOpenNewFileInZip64(zipFile file,
                                         const char* filename,
                                         const zip_fileinfo* zipfi,
                                         const void* extrafield_local,
                                         uInt size_extrafield_local,
                                         const void* extrafield_global,
                                         uInt size_extrafield_global,
                                         const char* comment,
                                         int method,
                                         int level,
                                         int zip64);

/*
  Open a file in the ZIP for writing.
  filename : the filename in zip (if NULL, '-' without quote will be used
  *zipfi contain supplemental information
  if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
    contains the extrafield data the the local header
    contains the extrafield data for the local header
  if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
    contains the extrafield data the the local header
    contains the extrafield data for the global header
  if comment != NULL, comment contain the comment string
  method contain the compression method (0 for store, Z_DEFLATED for deflate)
  level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
  zip64 is set to 1 if a zip64 extended information block should be added to the local file header.
                    this MUST be '1' if the uncompressed size is >= 0xffffffff.

*/


extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,
                                            const char* filename,
                                            const zip_fileinfo* zipfi,
                                            const void* extrafield_local,
                                            uInt size_extrafield_local,
                                            const void* extrafield_global,
                                            uInt size_extrafield_global,
                                            const char* comment,
                                            int method,
                                            int level,
                                            int raw));
extern int ZEXPORT zipOpenNewFileInZip2(zipFile file,
                                        const char* filename,
                                        const zip_fileinfo* zipfi,
                                        const void* extrafield_local,
                                        uInt size_extrafield_local,
                                        const void* extrafield_global,
                                        uInt size_extrafield_global,
                                        const char* comment,
                                        int method,
                                        int level,
                                        int raw);


extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file,
                                            const char* filename,
                                            const zip_fileinfo* zipfi,
                                            const void* extrafield_local,
                                            uInt size_extrafield_local,
                                            const void* extrafield_global,
                                            uInt size_extrafield_global,
                                            const char* comment,
                                            int method,
                                            int level,
                                            int raw,
                                            int zip64));
extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file,
                                           const char* filename,
                                           const zip_fileinfo* zipfi,
                                           const void* extrafield_local,
                                           uInt size_extrafield_local,
                                           const void* extrafield_global,
                                           uInt size_extrafield_global,
                                           const char* comment,
                                           int method,
                                           int level,
                                           int raw,
                                           int zip64);
/*
  Same than zipOpenNewFileInZip, except if raw=1, we write raw file
 */

extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
                                            const char* filename,
                                            const zip_fileinfo* zipfi,
                                            const void* extrafield_local,
                                            uInt size_extrafield_local,
                                            const void* extrafield_global,
                                            uInt size_extrafield_global,
                                            const char* comment,
                                            int method,
                                            int level,
                                            int raw,
                                            int windowBits,
                                            int memLevel,
                                            int strategy,
                                            const char* password,
                                            uLong crcForCrypting));
extern int ZEXPORT zipOpenNewFileInZip3(zipFile file,
                                        const char* filename,
                                        const zip_fileinfo* zipfi,
                                        const void* extrafield_local,
                                        uInt size_extrafield_local,
                                        const void* extrafield_global,
                                        uInt size_extrafield_global,
                                        const char* comment,
                                        int method,
                                        int level,
                                        int raw,
                                        int windowBits,
                                        int memLevel,
                                        int strategy,
                                        const char* password,
                                        uLong crcForCrypting);

extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file,
                                            const char* filename,
                                            const zip_fileinfo* zipfi,
                                            const void* extrafield_local,
                                            uInt size_extrafield_local,
                                            const void* extrafield_global,
                                            uInt size_extrafield_global,
                                            const char* comment,
                                            int method,
                                            int level,
                                            int raw,
                                            int windowBits,
                                            int memLevel,
                                            int strategy,
                                            const char* password,
                                            uLong crcForCrypting,
                                            int zip64
extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file,
                                           const char* filename,
                                           const zip_fileinfo* zipfi,
                                           const void* extrafield_local,
                                           uInt size_extrafield_local,
                                           const void* extrafield_global,
                                           uInt size_extrafield_global,
                                           const char* comment,
                                           int method,
                                           int level,
                                           int raw,
                                           int windowBits,
                                           int memLevel,
                                           int strategy,
                                           const char* password,
                                           uLong crcForCrypting,
                                           int zip64);
                                            ));

/*
  Same than zipOpenNewFileInZip2, except
    windowBits,memLevel,,strategy : see parameter strategy in deflateInit2
    password : crypting password (NULL for no crypting)
    crcForCrypting : crc of file to compress (needed for crypting)
 */

extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file,
                                            const char* filename,
                                            const zip_fileinfo* zipfi,
                                            const void* extrafield_local,
                                            uInt size_extrafield_local,
                                            const void* extrafield_global,
                                            uInt size_extrafield_global,
                                            const char* comment,
                                            int method,
                                            int level,
                                            int raw,
                                            int windowBits,
                                            int memLevel,
                                            int strategy,
                                            const char* password,
                                            uLong crcForCrypting,
                                            uLong versionMadeBy,
                                            uLong flagBase
extern int ZEXPORT zipOpenNewFileInZip4(zipFile file,
                                        const char* filename,
                                        const zip_fileinfo* zipfi,
                                        const void* extrafield_local,
                                        uInt size_extrafield_local,
                                        const void* extrafield_global,
                                        uInt size_extrafield_global,
                                        const char* comment,
                                        int method,
                                        int level,
                                        int raw,
                                        int windowBits,
                                        int memLevel,
                                        int strategy,
                                        const char* password,
                                        uLong crcForCrypting,
                                        uLong versionMadeBy,
                                        uLong flagBase);
                                            ));


extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file,
                                            const char* filename,
                                            const zip_fileinfo* zipfi,
                                            const void* extrafield_local,
                                            uInt size_extrafield_local,
                                            const void* extrafield_global,
                                            uInt size_extrafield_global,
                                            const char* comment,
                                            int method,
                                            int level,
                                            int raw,
                                            int windowBits,
                                            int memLevel,
                                            int strategy,
                                            const char* password,
                                            uLong crcForCrypting,
                                            uLong versionMadeBy,
                                            uLong flagBase,
                                            int zip64
extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file,
                                           const char* filename,
                                           const zip_fileinfo* zipfi,
                                           const void* extrafield_local,
                                           uInt size_extrafield_local,
                                           const void* extrafield_global,
                                           uInt size_extrafield_global,
                                           const char* comment,
                                           int method,
                                           int level,
                                           int raw,
                                           int windowBits,
                                           int memLevel,
                                           int strategy,
                                           const char* password,
                                           uLong crcForCrypting,
                                           uLong versionMadeBy,
                                           uLong flagBase,
                                           int zip64);
                                            ));
/*
  Same than zipOpenNewFileInZip4, except
    versionMadeBy : value for Version made by field
    flag : value for flag field (compression level info will be added)
 */


extern int ZEXPORT zipWriteInFileInZip OF((zipFile file,
                       const void* buf,
                       unsigned len));
extern int ZEXPORT zipWriteInFileInZip(zipFile file,
                                       const void* buf,
                                       unsigned len);
/*
  Write data in the zipfile
*/

extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
extern int ZEXPORT zipCloseFileInZip(zipFile file);
/*
  Close the current file in the zipfile
*/

extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
                                            uLong uncompressed_size,
                                            uLong crc32));
extern int ZEXPORT zipCloseFileInZipRaw(zipFile file,
                                        uLong uncompressed_size,
                                        uLong crc32);

extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file,
                                            ZPOS64_T uncompressed_size,
                                            uLong crc32));
extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file,
                                          ZPOS64_T uncompressed_size,
                                          uLong crc32);

/*
  Close the current file in the zipfile, for file opened with
    parameter raw=1 in zipOpenNewFileInZip2
  uncompressed_size and crc32 are value for the uncompressed size
*/

extern int ZEXPORT zipClose OF((zipFile file,
                const char* global_comment));
extern int ZEXPORT zipClose(zipFile file,
                            const char* global_comment);
/*
  Close the zipfile
*/


extern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader));
extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader);
/*
  zipRemoveExtraInfoBlock -  Added by Mathias Svensson

  Remove extra information block from a extra information data for the local file header or central directory header

  It is needed to remove ZIP64 extra information blocks when before data is written if using RAW mode.

Added compat/zlib/contrib/nuget/nuget.csproj.












































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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<Project Sdk="Microsoft.Build.NoTargets/3.5.6">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <PackageId>madler.zlib.redist</PackageId>
    <PackageId Condition="$([MSBuild]::IsOSPlatform('Windows'))">$(PackageId).win</PackageId>
    <PackageId Condition="$([MSBuild]::IsOSPlatform('Linux'))">$(PackageId).linux</PackageId>
    <PackageId Condition="$([MSBuild]::IsOSPlatform('OSX'))">$(PackageId).osx</PackageId>
    <Copyright>(C) 1995-2024 Jean-loup Gailly and Mark Adler</Copyright>
    <version>1.3.1</version>
    <PackageDescription>NuGet Package for consuming native builds of zlib into .NET without complexity.</PackageDescription>
    <!--
        Warns about not having any lib or ref assemblies (.NET Assemblies) in those directories.
        Native only packages that is to be consumed in .NET should not require these.
    -->
    <NoWarn>NU5128</NoWarn>
    <PackageOutputPath>$(MSBuildProjectDirectory)</PackageOutputPath>
    <Authors>Jean-loup Gailly and Mark Adler</Authors>
  </PropertyGroup>

  <ItemGroup>
    <None Include="../../LICENSE" Pack="true" PackagePath="" />
    <!-- Package up Windows builds. -->
    <None Condition="$([MSBuild]::IsOSPlatform('Windows'))" Include="../vstudio/vc17/x86/ZlibDll$(Configuration)/zlibwapi.dll" Pack="true" PackagePath="runtimes/win-x86/native" />
    <None Condition="$([MSBuild]::IsOSPlatform('Windows'))" Include="../vstudio/vc17/x64/ZlibDll$(Configuration)/zlibwapi.dll" Pack="true" PackagePath="runtimes/win-x64/native" />
    <None Condition="$([MSBuild]::IsOSPlatform('Windows'))" Include="../vstudio/vc17/arm/ZlibDll$(Configuration)/zlibwapi.dll" Pack="true" PackagePath="runtimes/win-arm/native" />
    <None Condition="$([MSBuild]::IsOSPlatform('Windows'))" Include="../vstudio/vc17/arm64/ZlibDll$(Configuration)/zlibwapi.dll" Pack="true" PackagePath="runtimes/win-arm64/native" />
    <!-- Include debug symbols as well as we never know if they might actually be needed in the future. -->
    <None Condition="$([MSBuild]::IsOSPlatform('Windows'))" Include="../vstudio/vc17/x86/ZlibDll$(Configuration)/zlibwapi.pdb" Pack="true" PackagePath="runtimes/win-x86/native" />
    <None Condition="$([MSBuild]::IsOSPlatform('Windows'))" Include="../vstudio/vc17/x64/ZlibDll$(Configuration)/zlibwapi.pdb" Pack="true" PackagePath="runtimes/win-x64/native" />
    <None Condition="$([MSBuild]::IsOSPlatform('Windows'))" Include="../vstudio/vc17/arm/ZlibDll$(Configuration)/zlibwapi.pdb" Pack="true" PackagePath="runtimes/win-arm/native" />
    <None Condition="$([MSBuild]::IsOSPlatform('Windows'))" Include="../vstudio/vc17/arm64/ZlibDll$(Configuration)/zlibwapi.pdb" Pack="true" PackagePath="runtimes/win-arm64/native" />
    <!-- Package up Linux builds. -->
    <None Condition="$([MSBuild]::IsOSPlatform('Linux'))" Include="./linux-x86/libz.so" Pack="true" PackagePath="runtimes/linux-x86/native" />
    <None Condition="$([MSBuild]::IsOSPlatform('Linux'))" Include="./linux-x64/libz.so" Pack="true" PackagePath="runtimes/linux-x64/native" />
    <None Condition="$([MSBuild]::IsOSPlatform('Linux'))" Include="./linux-arm/libz.so" Pack="true" PackagePath="runtimes/linux-arm/native" />
    <None Condition="$([MSBuild]::IsOSPlatform('Linux'))" Include="./linux-arm64/libz.so" Pack="true" PackagePath="runtimes/linux-arm64/native" />
    <!-- Package up MacOS builds. -->
    <None Condition="$([MSBuild]::IsOSPlatform('OSX'))" Include="./osx-x64/libz.dylib" Pack="true" PackagePath="runtimes/osx-x64/native" />
    <None Condition="$([MSBuild]::IsOSPlatform('OSX'))" Include="./osx-arm64/libz.dylib" Pack="true" PackagePath="runtimes/osx-arm64/native" />
  </ItemGroup>

</Project>

Added compat/zlib/contrib/nuget/nuget.sln.























1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "nuget", "nuget.csproj", "{B1BD3984-EF8F-4E9D-9A94-EB784E5EB1E8}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Release|Any CPU = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{B1BD3984-EF8F-4E9D-9A94-EB784E5EB1E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{B1BD3984-EF8F-4E9D-9A94-EB784E5EB1E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{B1BD3984-EF8F-4E9D-9A94-EB784E5EB1E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{B1BD3984-EF8F-4E9D-9A94-EB784E5EB1E8}.Release|Any CPU.Build.0 = Release|Any CPU
	EndGlobalSection
EndGlobal

Changes to compat/zlib/contrib/pascal/zlibpas.pas.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







(* zlibpas -- Pascal interface to the zlib data compression library
 *
 * Copyright (C) 2003 Cosmin Truta.
 * Derived from original sources by Bob Dellaca.
 * For conditions of distribution and use, see copyright notice in readme.txt
 *)

unit zlibpas;

interface

const
  ZLIB_VERSION = '1.2.11';
  ZLIB_VERSION = '1.3.1';
  ZLIB_VERNUM  = $12a0;

type
  alloc_func = function(opaque: Pointer; items, size: Integer): Pointer;
                 cdecl;
  free_func  = procedure(opaque, address: Pointer);
                 cdecl;

Changes to compat/zlib/contrib/puff/README.

34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48







-
+







         unsigned char *source,         /* pointer to source data pointer */
         unsigned long *sourcelen);     /* amount of input available */

Then you can call puff() to decompress a deflate stream that is in memory in
its entirety at source, to a sufficiently sized block of memory for the
decompressed data at dest.  puff() is the only external symbol in puff.c  The
only C library functions that puff.c needs are setjmp() and longjmp(), which
are used to simplify error checking in the code to improve readabilty.  puff.c
are used to simplify error checking in the code to improve readability.  puff.c
does no memory allocation, and uses less than 2K bytes off of the stack.

If destlen is not enough space for the uncompressed data, then inflate will
return an error without writing more than destlen bytes.  Note that this means
that in order to decompress the deflate data successfully, you need to know
the size of the uncompressed data ahead of time.

Changes to compat/zlib/contrib/puff/puff.c.

39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53







-
+







 *                      - Simplify offs[] index in construct()
 *                      - Add input size and checking, using longjmp() to
 *                        maintain easy readability
 *                      - Use short data type for large arrays
 *                      - Use pointers instead of long to specify source and
 *                        destination sizes to avoid arbitrary 4 GB limits
 * 1.2  17 Mar 2002     - Add faster version of decode(), doubles speed (!),
 *                        but leave simple version for readabilty
 *                        but leave simple version for readability
 *                      - Make sure invalid distances detected if pointers
 *                        are 16 bits
 *                      - Fix fixed codes table error
 *                      - Provide a scanning mode for determining size of
 *                        uncompressed data
 * 1.3  20 Mar 2002     - Go back to lengths for puff() parameters [Gailly]
 *                      - Add a puff.h file for the interface
589
590
591
592
593
594
595
596
597
598
599




600
601
602
603
604
605
606
589
590
591
592
593
594
595




596
597
598
599
600
601
602
603
604
605
606







-
-
-
-
+
+
+
+







 *   from the number of bits in each code.  Therefore the code descriptions
 *   are simply a list of code lengths for each symbol.
 *
 * - The code lengths are stored in order for the symbols, so lengths are
 *   provided for each of the literal/length symbols, and for each of the
 *   distance symbols.
 *
 * - If a symbol is not used in the block, this is represented by a zero as
 *   as the code length.  This does not mean a zero-length code, but rather
 *   that no code should be created for this symbol.  There is no way in the
 *   deflate format to represent a zero-length code.
 * - If a symbol is not used in the block, this is represented by a zero as the
 *   code length.  This does not mean a zero-length code, but rather that no
 *   code should be created for this symbol.  There is no way in the deflate
 *   format to represent a zero-length code.
 *
 * - The maximum number of bits in a code is 15, so the possible lengths for
 *   any code are 1..15.
 *
 * - The fact that a length of zero is not permitted for a code has an
 *   interesting consequence.  Normally if only one symbol is used for a given
 *   code, then in fact that code could be represented with zero bits.  However
620
621
622
623
624
625
626
627

628
629
630
631
632
633
634
620
621
622
623
624
625
626

627
628
629
630
631
632
633
634







-
+







 * - If there are only literal codes and no lengths, then there are no distance
 *   codes.  This is represented by one distance code with zero bits.
 *
 * - The list of up to 286 length/literal lengths and up to 30 distance lengths
 *   are themselves compressed using Huffman codes and run-length encoding.  In
 *   the list of code lengths, a 0 symbol means no code, a 1..15 symbol means
 *   that length, and the symbols 16, 17, and 18 are run-length instructions.
 *   Each of 16, 17, and 18 are follwed by extra bits to define the length of
 *   Each of 16, 17, and 18 are followed by extra bits to define the length of
 *   the run.  16 copies the last length 3 to 6 times.  17 represents 3 to 10
 *   zero lengths, and 18 represents 11 to 138 zero lengths.  Unused symbols
 *   are common, hence the special coding for zero lengths.
 *
 * - The symbols for 0..18 are Huffman coded, and so that code must be
 *   described first.  This is simply a sequence of up to 19 three-bit values
 *   representing no code (0) or the code length for that symbol (1..7).

Changes to compat/zlib/contrib/puff/pufftest.c.

139
140
141
142
143
144
145
146

147
148
149
150
151
152
153
139
140
141
142
143
144
145

146
147
148
149
150
151
152
153







-
+







        fprintf(stderr, "puff() failed with return code %d\n", ret);
    else {
        fprintf(stderr, "puff() succeeded uncompressing %lu bytes\n", destlen);
        if (sourcelen < len) fprintf(stderr, "%lu compressed bytes unused\n",
                                     len - sourcelen);
    }

    /* if requested, inflate again and write decompressd data to stdout */
    /* if requested, inflate again and write decompressed data to stdout */
    if (put && ret == 0) {
        if (fail)
            destlen >>= 1;
        dest = malloc(destlen);
        if (dest == NULL) {
            fprintf(stderr, "memory allocation failure\n");
            free(source);

Changes to compat/zlib/contrib/testzlib/testzlib.c.

165
166
167
168
169
170
171
172

173
174
175
176
177
178
179
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179







-
+







    }

    if (ReadFileMemory(argv[1],&lFileSize,&FilePtr)==0)
    {
        printf("error reading %s\n",argv[1]);
        return 1;
    }
    else printf("file %s read, %u bytes\n",argv[1],lFileSize);
    else printf("file %s read, %ld bytes\n",argv[1],lFileSize);

    if (argc>=3)
        BlockSizeCompress=atol(argv[2]);

    if (argc>=4)
        BlockSizeUncompress=atol(argv[3]);

Changes to compat/zlib/contrib/untgz/untgz.c.

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
30
31
32
33
34
35


36
37
38
39
40
41
42
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
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






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










-
+
-
-


-
-
-
-
+










+
+







/*
 * untgz.c -- Display contents and extract files from a gzip'd TAR file
 *
 * written by Pedro A. Aranda Gutierrez <paag@tid.es>
 * adaptation to Unix by Jean-loup Gailly <jloup@gzip.org>
 * various fixes by Cosmin Truta <cosmint@cs.ubbcluj.ro>
 *
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
 *    appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 *    misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>

#include "zlib.h"

#ifdef unix
#ifdef _WIN32
#  include <unistd.h>
#else
#  include <direct.h>
#  include <io.h>
#endif

#ifdef WIN32
#include <windows.h>
#  include <windows.h>
#  ifndef F_OK
#    define F_OK  0
#  endif
#  define mkdir(dirname,mode)   _mkdir(dirname)
#  ifdef _MSC_VER
#    define access(path,mode)   _access(path,mode)
#    define chmod(path,mode)    _chmod(path,mode)
#    define strdup(str)         _strdup(str)
#  endif
#else
#  include <sys/stat.h>
#  include <unistd.h>
#  include <utime.h>
#endif


/* values used in typeflag field */

#define REGTYPE  '0'            /* regular file */
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
111
112
113
114
115
116
117

118

119






120


121



122



123



124

125
126
127
128
129
130
131







-
+
-

-
-
-
-
-
-
+
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-







  char              *fname;
  int                mode;
  time_t             time;
};

enum { TGZ_EXTRACT, TGZ_LIST, TGZ_INVALID };

char *TGZfname          OF((const char *));
char *prog;
void TGZnotfound        OF((const char *));

int getoct              OF((char *, int));
char *strtime           OF((time_t *));
int setfiletime         OF((char *, time_t));
void push_attr          OF((struct attr_item **, char *, int, time_t));
void restore_attr       OF((struct attr_item **));

void error(const char *msg)
int ExprMatch           OF((char *, char *));

{
int makedir             OF((char *));
int matchname           OF((int, int, char **, char *));

  fprintf(stderr, "%s: %s\n", prog, msg);
void error              OF((const char *));
int tar                 OF((gzFile, int, int, int, char **));

  exit(1);
void help               OF((int));
int main                OF((int, char **));

}
char *prog;

const char *TGZsuffix[] = { "\0", ".tar", ".tar.gz", ".taz", ".tgz", NULL };

/* return the file name of the TGZ archive */
/* or NULL if it does not exist */

char *TGZfname (const char *arcname)
201
202
203
204
205
206
207
208

209
210
211
212
213
214
215
200
201
202
203
204
205
206

207
208
209
210
211
212
213
214







-
+







}


/* set file time */

int setfiletime (char *fname,time_t ftime)
{
#ifdef WIN32
#ifdef _WIN32
  static int isWinNT = -1;
  SYSTEMTIME st;
  FILETIME locft, modft;
  struct tm *loctm;
  HANDLE hFile;
  int result;

586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611

612
613
614
615
616
617
618
585
586
587
588
589
590
591






592
593
594
595
596
597
598
599
600
601
602
603

604
605
606
607
608
609
610
611







-
-
-
-
-
-












-
+







  printf("Usage: untgz file.tgz            extract all files\n"
         "       untgz file.tgz fname ...  extract selected files\n"
         "       untgz -l file.tgz         list archive contents\n"
         "       untgz -h                  display this help\n");
  exit(exitval);
}

void error(const char *msg)
{
  fprintf(stderr, "%s: %s\n", prog, msg);
  exit(1);
}


/* ============================================================ */

#if defined(WIN32) && defined(__GNUC__)
int _CRT_glob = 0;      /* disable argument globbing in MinGW */
#endif

int main(int argc,char **argv)
{
    int         action = TGZ_EXTRACT;
    int         arg = 1;
    char        *TGZfile;
    gzFile      *f;
    gzFile      f;

    prog = strrchr(argv[0],'\\');
    if (prog == NULL)
      {
        prog = strrchr(argv[0],'/');
        if (prog == NULL)
          {

Changes to compat/zlib/contrib/vstudio/readme.txt.

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

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
-
+


















-
-
-







Building instructions for the DLL versions of Zlib 1.2.11
Building instructions for the DLL versions of Zlib 1.3.1
========================================================

This directory contains projects that build zlib and minizip using
Microsoft Visual C++ 9.0/10.0.

You don't need to build these projects yourself. You can download the
binaries from:
  http://www.winimage.com/zLibDll

More information can be found at this site.





Build instructions for Visual Studio 2008 (32 bits or 64 bits)
--------------------------------------------------------------
- Decompress current zlib, including all contrib/* files
- Compile assembly code (with Visual Studio Command Prompt) by running:
   bld_ml64.bat (in contrib\masmx64)
   bld_ml32.bat (in contrib\masmx86)
- Open contrib\vstudio\vc9\zlibvc.sln with Microsoft Visual C++ 2008
- Or run: vcbuild /rebuild contrib\vstudio\vc9\zlibvc.sln "Release|Win32"

Build instructions for Visual Studio 2010 (32 bits or 64 bits)
--------------------------------------------------------------
- Decompress current zlib, including all contrib/* files
- Open contrib\vstudio\vc10\zlibvc.sln with Microsoft Visual C++ 2010
38
39
40
41
42
43
44






45
46
47
48
49
50
51
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54







+
+
+
+
+
+







- Decompress current zlib, including all contrib/* files
- Open contrib\vstudio\vc12\zlibvc.sln with Microsoft Visual C++ 2013

Build instructions for Visual Studio 2015 (32 bits or 64 bits)
--------------------------------------------------------------
- Decompress current zlib, including all contrib/* files
- Open contrib\vstudio\vc14\zlibvc.sln with Microsoft Visual C++ 2015

Build instructions for Visual Studio 2022 (64 bits)
--------------------------------------------------------------
- Decompress current zlib, including all contrib/* files
- Open contrib\vstudio\vc143\zlibvc.sln with Microsoft Visual C++ 2022



Important
---------
- To use zlibwapi.dll in your application, you must define the
  macro ZLIB_WINAPI when compiling your application's source files.

70
71
72
73
74
75
76
77

78
73
74
75
76
77
78
79

80
81







-
+

  has a slightly different effect. To avoid compatibility problems, do
  not define it here.


Gilles Vollant
info@winimage.com

Visual Studio 2013 and 2015 Projects from Sean Hunt
Visual Studio 2013, 2015, and 2022 Projects from Sean Hunt
seandhunt_7@yahoo.com

Changes to compat/zlib/contrib/vstudio/vc10/miniunz.vcxproj.filters.

1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Filter Include="Source Files">
      <UniqueIdentifier>{048af943-022b-4db6-beeb-a54c34774ee2}</UniqueIdentifier>
      <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm</Extensions>
      <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat</Extensions>
    </Filter>
    <Filter Include="Header Files">
      <UniqueIdentifier>{c1d600d2-888f-4aea-b73e-8b0dd9befa0c}</UniqueIdentifier>
      <Extensions>h;hpp;hxx;hm;inl;inc</Extensions>
    </Filter>
    <Filter Include="Resource Files">
      <UniqueIdentifier>{0844199a-966b-4f19-81db-1e0125e141b9}</UniqueIdentifier>

Changes to compat/zlib/contrib/vstudio/vc10/minizip.vcxproj.filters.

1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Filter Include="Source Files">
      <UniqueIdentifier>{c0419b40-bf50-40da-b153-ff74215b79de}</UniqueIdentifier>
      <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm</Extensions>
      <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat</Extensions>
    </Filter>
    <Filter Include="Header Files">
      <UniqueIdentifier>{bb87b070-735b-478e-92ce-7383abb2f36c}</UniqueIdentifier>
      <Extensions>h;hpp;hxx;hm;inl;inc</Extensions>
    </Filter>
    <Filter Include="Resource Files">
      <UniqueIdentifier>{f46ab6a6-548f-43cb-ae96-681abb5bd5db}</UniqueIdentifier>

Changes to compat/zlib/contrib/vstudio/vc10/testzlib.vcxproj.

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
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







-
+












-
+







    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>true</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)testzlib.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)testzlib.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
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
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







-
+












-
+














-
+






-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <OmitFramePointers>true</OmitFramePointers>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)testzlib.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <TargetMachine>MachineX86</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <ClCompile>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
348
349
350
351
352
353
354
355

356
357
358
359
360
361
362

363
364
365
366
367
368
369
348
349
350
351
352
353
354

355
356
357
358
359
360
361

362
363
364
365
366
367
368
369







-
+






-
+







      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <TargetMachine>MachineIA64</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <ClCompile>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
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
394
395
396
397
398
399
400








401
402
403
404
405
406
407
408
409
410
411
412







-
-
-
-
-
-
-
-












  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\..\adler32.c" />
    <ClCompile Include="..\..\..\compress.c" />
    <ClCompile Include="..\..\..\crc32.c" />
    <ClCompile Include="..\..\..\deflate.c" />
    <ClCompile Include="..\..\..\infback.c" />
    <ClCompile Include="..\..\masmx64\inffas8664.c">
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
    </ClCompile>
    <ClCompile Include="..\..\..\inffast.c" />
    <ClCompile Include="..\..\..\inflate.c" />
    <ClCompile Include="..\..\..\inftrees.c" />
    <ClCompile Include="..\..\testzlib\testzlib.c" />
    <ClCompile Include="..\..\..\trees.c" />
    <ClCompile Include="..\..\..\uncompr.c" />
    <ClCompile Include="..\..\..\zutil.c" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>

Changes to compat/zlib/contrib/vstudio/vc10/testzlib.vcxproj.filters.

1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Filter Include="Source Files">
      <UniqueIdentifier>{c1f6a2e3-5da5-4955-8653-310d3efe05a9}</UniqueIdentifier>
      <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm</Extensions>
      <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat</Extensions>
    </Filter>
    <Filter Include="Header Files">
      <UniqueIdentifier>{c2aaffdc-2c95-4d6f-8466-4bec5890af2c}</UniqueIdentifier>
      <Extensions>h;hpp;hxx;hm;inl;inc</Extensions>
    </Filter>
    <Filter Include="Resource Files">
      <UniqueIdentifier>{c274fe07-05f2-461c-964b-f6341e4e7eb5}</UniqueIdentifier>
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
26
27
28
29
30
31
32



33
34
35
36
37
38
39







-
-
-







    </ClCompile>
    <ClCompile Include="..\..\..\deflate.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\..\..\infback.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\..\masmx64\inffas8664.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\..\..\inffast.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\..\..\inflate.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\..\..\inftrees.c">

Changes to compat/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj.filters.

1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Filter Include="Source Files">
      <UniqueIdentifier>{fa61a89f-93fc-4c89-b29e-36224b7592f4}</UniqueIdentifier>
      <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm</Extensions>
      <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat</Extensions>
    </Filter>
    <Filter Include="Header Files">
      <UniqueIdentifier>{d4b85da0-2ba2-4934-b57f-e2584e3848ee}</UniqueIdentifier>
      <Extensions>h;hpp;hxx;hm;inl;inc</Extensions>
    </Filter>
    <Filter Include="Resource Files">
      <UniqueIdentifier>{e573e075-00bd-4a7d-bd67-a8cc9bfc5aca}</UniqueIdentifier>

Changes to compat/zlib/contrib/vstudio/vc10/zlib.rc.

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
30
31
32
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
30
31
32




-
-
+
+













-
+




-
+







#include <windows.h>

#define IDR_VERSION1  1
IDR_VERSION1	VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE
  FILEVERSION	 1, 2, 11, 0
  PRODUCTVERSION 1, 2, 11, 0
  FILEVERSION	 1, 3, 1, 0
  PRODUCTVERSION 1, 3, 1, 0
  FILEFLAGSMASK	VS_FFI_FILEFLAGSMASK
  FILEFLAGS	0
  FILEOS	VOS_DOS_WINDOWS32
  FILETYPE	VFT_DLL
  FILESUBTYPE	0	// not used
BEGIN
  BLOCK "StringFileInfo"
  BEGIN
    BLOCK "040904E4"
    //language ID = U.S. English, char set = Windows, Multilingual

    BEGIN
      VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
      VALUE "FileVersion",	"1.2.11\0"
      VALUE "FileVersion",	"1.3.1\0"
      VALUE "InternalName",	"zlib\0"
      VALUE "OriginalFilename",	"zlibwapi.dll\0"
      VALUE "ProductName",	"ZLib.DLL\0"
      VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
      VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0"
      VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
    END
  END
  BLOCK "VarFileInfo"
  BEGIN
    VALUE "Translation", 0x0409, 1252
  END
END

Changes to compat/zlib/contrib/vstudio/vc10/zlibstat.vcxproj.

156
157
158
159
160
161
162
163

164
165
166
167
168
169
170
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170







-
+







    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
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
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







-
-
-
-




-
-
+
+


















-
+



-
-
-
-




-
+







      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
    <PreBuildEvent>
      <Command>cd ..\..\masmx86
bld_ml32.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
    <PreBuildEvent>
      <Command>cd ..\..\masmx86
bld_ml32.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
248
249
250
251
252
253
254
255

256
257
258
259
260
261
262
240
241
242
243
244
245
246

247
248
249
250
251
252
253
254







-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
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
262
263
264
265
266
267
268




269
270
271
272
273
274
275

276
277
278
279
280
281
282
283







-
-
-
-







-
+







      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
    <PreBuildEvent>
      <Command>cd ..\..\masmx64
bld_ml64.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
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
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







-
-
+
+


















-
+



-
-
-
-







-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
    <PreBuildEvent>
      <Command>cd ..\..\masmx64
bld_ml64.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
375
376
377
378
379
380
381
382

383
384
385
386
387
388
389
359
360
361
362
363
364
365

366
367
368
369
370
371
372
373







-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
405
406
407
408
409
410
411
412

413
414
415
416
417
418
419
389
390
391
392
393
394
395

396
397
398
399
400
401
402
403







-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
423
424
425
426
427
428
429








430
431
432
433
434
435
436







-
-
-
-
-
-
-
-







    <ClCompile Include="..\..\..\crc32.c" />
    <ClCompile Include="..\..\..\deflate.c" />
    <ClCompile Include="..\..\..\gzclose.c" />
    <ClCompile Include="..\..\..\gzlib.c" />
    <ClCompile Include="..\..\..\gzread.c" />
    <ClCompile Include="..\..\..\gzwrite.c" />
    <ClCompile Include="..\..\..\infback.c" />
    <ClCompile Include="..\..\masmx64\inffas8664.c">
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
    </ClCompile>
    <ClCompile Include="..\..\..\inffast.c" />
    <ClCompile Include="..\..\..\inflate.c" />
    <ClCompile Include="..\..\..\inftrees.c" />
    <ClCompile Include="..\..\minizip\ioapi.c" />
    <ClCompile Include="..\..\..\trees.c" />
    <ClCompile Include="..\..\..\uncompr.c" />
    <ClCompile Include="..\..\minizip\unzip.c" />

Changes to compat/zlib/contrib/vstudio/vc10/zlibstat.vcxproj.filters.

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
29
30
31
32
33
34
35



36
37
38
39
40
41
42







-
-
-







    </ClCompile>
    <ClCompile Include="..\..\..\gzwrite.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\..\..\infback.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\..\masmx64\inffas8664.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\..\..\inffast.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\..\..\inflate.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\..\..\inftrees.c">

Changes to compat/zlib/contrib/vstudio/vc10/zlibvc.def.

1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







LIBRARY
; zlib data compression and ZIP file I/O library

VERSION		1.2
VERSION		1.3.1

EXPORTS
        adler32                                  @1
        compress                                 @2
        crc32                                    @3
        deflate                                  @4
        deflateCopy                              @5
147
148
149
150
151
152
153





147
148
149
150
151
152
153
154
155
156
157
158







+
+
+
+
+
        inflateValidate                         @169
        uncompress2                             @170
        gzfread                                 @171
        gzfwrite                                @172
        deflateGetDictionary                    @173
        adler32_z                               @174
        crc32_z                                 @175

; zlib1 v1.2.12 added:
		crc32_combine_gen						@176
		crc32_combine_gen64						@177
		crc32_combine_op						@178

Changes to compat/zlib/contrib/vstudio/vc10/zlibvc.sln.

Changes to compat/zlib/contrib/vstudio/vc10/zlibvc.vcxproj.

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
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







-
-
+
+




















-
+









-
-
-
-











-
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Win32</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <GenerateMapFile>true</GenerateMapFile>
      <SubSystem>Windows</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
    </Link>
    <PreBuildEvent>
      <Command>cd ..\..\masmx86
bld_ml32.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">
    <Midl>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Win32</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
284
285
286
287
288
289
290
291
292


293
294
295
296
297
298
299
280
281
282
283
284
285
286


287
288
289
290
291
292
293
294
295







-
-
+
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Win32</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
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
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
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
366
367
368
369
370
371

372
373
374
375
376
377
378
379







-
+









-
-
-
-











-
-
+
+



















-
+







-
-
-
-











-
+







    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <GenerateMapFile>true</GenerateMapFile>
      <SubSystem>Windows</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
    </Link>
    <PreBuildEvent>
      <Command>cd ..\..\masmx86
bld_ml32.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Midl>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>X64</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <GenerateMapFile>true</GenerateMapFile>
      <SubSystem>Windows</SubSystem>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>
    <PreBuildEvent>
      <Command>cd ..\..\masmx64
bld_ml64.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Itanium</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
420
421
422
423
424
425
426
427

428
429
430
431
432
433
434
408
409
410
411
412
413
414

415
416
417
418
419
420
421
422







-
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>X64</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
461
462
463
464
465
466
467
468

469
470
471
472
473
474
475
449
450
451
452
453
454
455

456
457
458
459
460
461
462
463







-
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Itanium</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
506
507
508
509
510
511
512
513
514


515
516
517
518
519
520
521
494
495
496
497
498
499
500


501
502
503
504
505
506
507
508
509







-
-
+
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>X64</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
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
558
559

560
561
562
563
564
565
566
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







-
+







-
-
-
-











-
+







      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <GenerateMapFile>true</GenerateMapFile>
      <SubSystem>Windows</SubSystem>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>
    <PreBuildEvent>
      <Command>cd ..\..\masmx64
bld_ml64.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">
    <Midl>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Itanium</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
581
582
583
584
585
586
587








588
589
590
591
592
593
594







-
-
-
-
-
-
-
-







    <ClCompile Include="..\..\..\crc32.c" />
    <ClCompile Include="..\..\..\deflate.c" />
    <ClCompile Include="..\..\..\gzclose.c" />
    <ClCompile Include="..\..\..\gzlib.c" />
    <ClCompile Include="..\..\..\gzread.c" />
    <ClCompile Include="..\..\..\gzwrite.c" />
    <ClCompile Include="..\..\..\infback.c" />
    <ClCompile Include="..\..\masmx64\inffas8664.c">
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
    </ClCompile>
    <ClCompile Include="..\..\..\inffast.c" />
    <ClCompile Include="..\..\..\inflate.c" />
    <ClCompile Include="..\..\..\inftrees.c" />
    <ClCompile Include="..\..\minizip\ioapi.c" />
    <ClCompile Include="..\..\minizip\iowin32.c" />
    <ClCompile Include="..\..\..\trees.c" />
    <ClCompile Include="..\..\..\uncompr.c" />

Changes to compat/zlib/contrib/vstudio/vc10/zlibvc.vcxproj.filters.

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
38
39
40
41
42
43
44



45
46
47
48
49
50
51







-
-
-







    </ClCompile>
    <ClCompile Include="..\..\..\gzwrite.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\..\..\infback.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\..\masmx64\inffas8664.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\..\..\inffast.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\..\..\inflate.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="..\..\..\inftrees.c">

Changes to compat/zlib/contrib/vstudio/vc11/testzlib.vcxproj.

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
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







-
+












-
+







    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>true</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)testzlib.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)testzlib.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
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
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







-
+












-
+














-
+






-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <OmitFramePointers>true</OmitFramePointers>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)testzlib.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <TargetMachine>MachineX86</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <ClCompile>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
354
355
356
357
358
359
360
361

362
363
364
365
366
367
368

369
370
371
372
373
374
375
354
355
356
357
358
359
360

361
362
363
364
365
366
367

368
369
370
371
372
373
374
375







-
+






-
+







      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <TargetMachine>MachineIA64</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <ClCompile>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
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
400
401
402
403
404
405
406








407
408
409
410
411
412
413
414
415
416
417
418







-
-
-
-
-
-
-
-












  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\..\adler32.c" />
    <ClCompile Include="..\..\..\compress.c" />
    <ClCompile Include="..\..\..\crc32.c" />
    <ClCompile Include="..\..\..\deflate.c" />
    <ClCompile Include="..\..\..\infback.c" />
    <ClCompile Include="..\..\masmx64\inffas8664.c">
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
    </ClCompile>
    <ClCompile Include="..\..\..\inffast.c" />
    <ClCompile Include="..\..\..\inflate.c" />
    <ClCompile Include="..\..\..\inftrees.c" />
    <ClCompile Include="..\..\testzlib\testzlib.c" />
    <ClCompile Include="..\..\..\trees.c" />
    <ClCompile Include="..\..\..\uncompr.c" />
    <ClCompile Include="..\..\..\zutil.c" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>

Changes to compat/zlib/contrib/vstudio/vc11/zlib.rc.

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
30
31
32
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
30
31
32




-
-
+
+













-
+




-
+







#include <windows.h>

#define IDR_VERSION1  1
IDR_VERSION1	VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE
  FILEVERSION	 1, 2, 11, 0
  PRODUCTVERSION 1, 2, 11, 0
  FILEVERSION	 1, 3, 1, 0
  PRODUCTVERSION 1, 3, 1, 0
  FILEFLAGSMASK	VS_FFI_FILEFLAGSMASK
  FILEFLAGS	0
  FILEOS	VOS_DOS_WINDOWS32
  FILETYPE	VFT_DLL
  FILESUBTYPE	0	// not used
BEGIN
  BLOCK "StringFileInfo"
  BEGIN
    BLOCK "040904E4"
    //language ID = U.S. English, char set = Windows, Multilingual

    BEGIN
      VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
      VALUE "FileVersion",	"1.2.11\0"
      VALUE "FileVersion",	"1.3.1\0"
      VALUE "InternalName",	"zlib\0"
      VALUE "OriginalFilename",	"zlibwapi.dll\0"
      VALUE "ProductName",	"ZLib.DLL\0"
      VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
      VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0"
      VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
    END
  END
  BLOCK "VarFileInfo"
  BEGIN
    VALUE "Translation", 0x0409, 1252
  END
END

Changes to compat/zlib/contrib/vstudio/vc11/zlibstat.vcxproj.

163
164
165
166
167
168
169
170

171
172
173
174
175
176
177
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177







-
+







    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
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
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







-
-
+
+


















-
+







-
+







      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
247
248
249
250
251
252
253
254

255
256
257
258
259
260
261
247
248
249
250
251
252
253

254
255
256
257
258
259
260
261







-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
276
277
278
279
280
281
282
283

284
285
286
287
288
289
290
276
277
278
279
280
281
282

283
284
285
286
287
288
289
290







-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
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
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







-
-
+
+


















-
+










-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
366
367
368
369
370
371
372
373

374
375
376
377
378
379
380
366
367
368
369
370
371
372

373
374
375
376
377
378
379
380







-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
396
397
398
399
400
401
402
403

404
405
406
407
408
409
410
396
397
398
399
400
401
402

403
404
405
406
407
408
409
410







-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
430
431
432
433
434
435
436








437
438
439
440
441
442
443







-
-
-
-
-
-
-
-







    <ClCompile Include="..\..\..\crc32.c" />
    <ClCompile Include="..\..\..\deflate.c" />
    <ClCompile Include="..\..\..\gzclose.c" />
    <ClCompile Include="..\..\..\gzlib.c" />
    <ClCompile Include="..\..\..\gzread.c" />
    <ClCompile Include="..\..\..\gzwrite.c" />
    <ClCompile Include="..\..\..\infback.c" />
    <ClCompile Include="..\..\masmx64\inffas8664.c">
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
    </ClCompile>
    <ClCompile Include="..\..\..\inffast.c" />
    <ClCompile Include="..\..\..\inflate.c" />
    <ClCompile Include="..\..\..\inftrees.c" />
    <ClCompile Include="..\..\minizip\ioapi.c" />
    <ClCompile Include="..\..\..\trees.c" />
    <ClCompile Include="..\..\..\uncompr.c" />
    <ClCompile Include="..\..\minizip\unzip.c" />

Changes to compat/zlib/contrib/vstudio/vc11/zlibvc.def.

1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







LIBRARY
; zlib data compression and ZIP file I/O library

VERSION		1.2
VERSION		1.3.1

EXPORTS
        adler32                                  @1
        compress                                 @2
        crc32                                    @3
        deflate                                  @4
        deflateCopy                              @5
147
148
149
150
151
152
153





147
148
149
150
151
152
153
154
155
156
157
158







+
+
+
+
+
        inflateValidate                         @169
        uncompress2                             @170
        gzfread                                 @171
        gzfwrite                                @172
        deflateGetDictionary                    @173
        adler32_z                               @174
        crc32_z                                 @175

; zlib1 v1.2.12 added:
		crc32_combine_gen						@176
		crc32_combine_gen64						@177
		crc32_combine_op						@178

Changes to compat/zlib/contrib/vstudio/vc11/zlibvc.sln.

Changes to compat/zlib/contrib/vstudio/vc11/zlibvc.vcxproj.

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
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







-
-
+
+




















-
+













-
-
-
-











-
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Win32</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
    </Link>
    <PreBuildEvent>
      <Command>cd ..\..\masmx86
bld_ml32.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">
    <Midl>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Win32</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
299
300
301
302
303
304
305
306
307


308
309
310
311
312
313
314
295
296
297
298
299
300
301


302
303
304
305
306
307
308
309
310







-
-
+
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Win32</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
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
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
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
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







-
+













-
-
-
-











-
-
+
+



















-
+











-
-
-
-











-
+







    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
    </Link>
    <PreBuildEvent>
      <Command>cd ..\..\masmx86
bld_ml32.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Midl>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>X64</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>
    <PreBuildEvent>
      <Command>cd ..\..\contrib\masmx64
bld_ml64.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Itanium</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
443
444
445
446
447
448
449
450

451
452
453
454
455
456
457
431
432
433
434
435
436
437

438
439
440
441
442
443
444
445







-
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>X64</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
488
489
490
491
492
493
494
495

496
497
498
499
500
501
502
476
477
478
479
480
481
482

483
484
485
486
487
488
489
490







-
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Itanium</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
533
534
535
536
537
538
539
540
541


542
543
544
545
546
547
548
521
522
523
524
525
526
527


528
529
530
531
532
533
534
535
536







-
-
+
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>X64</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
556
557
558
559
560
561
562
563

564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590

591
592
593
594
595
596
597
544
545
546
547
548
549
550

551
552
553
554
555
556
557
558
559
560
561
562




563
564
565
566
567
568
569
570
571
572
573

574
575
576
577
578
579
580
581







-
+











-
-
-
-











-
+







      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>
    <PreBuildEvent>
      <Command>cd ..\..\masmx64
bld_ml64.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">
    <Midl>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Itanium</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
612
613
614
615
616
617
618








619
620
621
622
623
624
625







-
-
-
-
-
-
-
-







    <ClCompile Include="..\..\..\crc32.c" />
    <ClCompile Include="..\..\..\deflate.c" />
    <ClCompile Include="..\..\..\gzclose.c" />
    <ClCompile Include="..\..\..\gzlib.c" />
    <ClCompile Include="..\..\..\gzread.c" />
    <ClCompile Include="..\..\..\gzwrite.c" />
    <ClCompile Include="..\..\..\infback.c" />
    <ClCompile Include="..\..\masmx64\inffas8664.c">
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
    </ClCompile>
    <ClCompile Include="..\..\..\inffast.c" />
    <ClCompile Include="..\..\..\inflate.c" />
    <ClCompile Include="..\..\..\inftrees.c" />
    <ClCompile Include="..\..\minizip\ioapi.c" />
    <ClCompile Include="..\..\minizip\iowin32.c" />
    <ClCompile Include="..\..\..\trees.c" />
    <ClCompile Include="..\..\..\uncompr.c" />

Changes to compat/zlib/contrib/vstudio/vc12/testzlib.vcxproj.

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
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







-
+












-
+







    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>true</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)testzlib.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)testzlib.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
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
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







-
+












-
+















-
+






-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <OmitFramePointers>true</OmitFramePointers>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)testzlib.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <TargetMachine>MachineX86</TargetMachine>
      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <ClCompile>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
358
359
360
361
362
363
364
365

366
367
368
369
370
371
372

373
374
375
376
377
378
379
358
359
360
361
362
363
364

365
366
367
368
369
370
371

372
373
374
375
376
377
378
379







-
+






-
+







      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <TargetMachine>MachineIA64</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <ClCompile>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
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
404
405
406
407
408
409
410








411
412
413
414
415
416
417
418
419
420
421
422







-
-
-
-
-
-
-
-












  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\..\adler32.c" />
    <ClCompile Include="..\..\..\compress.c" />
    <ClCompile Include="..\..\..\crc32.c" />
    <ClCompile Include="..\..\..\deflate.c" />
    <ClCompile Include="..\..\..\infback.c" />
    <ClCompile Include="..\..\masmx64\inffas8664.c">
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
    </ClCompile>
    <ClCompile Include="..\..\..\inffast.c" />
    <ClCompile Include="..\..\..\inflate.c" />
    <ClCompile Include="..\..\..\inftrees.c" />
    <ClCompile Include="..\..\testzlib\testzlib.c" />
    <ClCompile Include="..\..\..\trees.c" />
    <ClCompile Include="..\..\..\uncompr.c" />
    <ClCompile Include="..\..\..\zutil.c" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>

Changes to compat/zlib/contrib/vstudio/vc12/zlib.rc.

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
30
31
32
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
30
31
32




-
-
+
+













-
+




-
+







#include <windows.h>

#define IDR_VERSION1  1
IDR_VERSION1	VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE
  FILEVERSION	 1, 2, 11, 0
  PRODUCTVERSION 1, 2, 11, 0
  FILEVERSION	 1, 3, 1, 0
  PRODUCTVERSION 1, 3, 1, 0
  FILEFLAGSMASK	VS_FFI_FILEFLAGSMASK
  FILEFLAGS	0
  FILEOS	VOS_DOS_WINDOWS32
  FILETYPE	VFT_DLL
  FILESUBTYPE	0	// not used
BEGIN
  BLOCK "StringFileInfo"
  BEGIN
    BLOCK "040904E4"
    //language ID = U.S. English, char set = Windows, Multilingual

    BEGIN
      VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
      VALUE "FileVersion",	"1.2.11\0"
      VALUE "FileVersion",	"1.3.1\0"
      VALUE "InternalName",	"zlib\0"
      VALUE "OriginalFilename",	"zlibwapi.dll\0"
      VALUE "ProductName",	"ZLib.DLL\0"
      VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
      VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0"
      VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
    END
  END
  BLOCK "VarFileInfo"
  BEGIN
    VALUE "Translation", 0x0409, 1252
  END
END

Changes to compat/zlib/contrib/vstudio/vc12/zlibstat.vcxproj.

166
167
168
169
170
171
172
173

174
175
176
177
178
179
180
166
167
168
169
170
171
172

173
174
175
176
177
178
179
180







-
+







    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
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
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







-
-
+
+


















-
+







-
+







      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
250
251
252
253
254
255
256
257

258
259
260
261
262
263
264
250
251
252
253
254
255
256

257
258
259
260
261
262
263
264







-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
279
280
281
282
283
284
285
286

287
288
289
290
291
292
293
279
280
281
282
283
284
285

286
287
288
289
290
291
292
293







-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
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
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







-
-
+
+


















-
+










-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
369
370
371
372
373
374
375
376

377
378
379
380
381
382
383
369
370
371
372
373
374
375

376
377
378
379
380
381
382
383







-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
399
400
401
402
403
404
405
406

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

406
407
408
409
410
411
412
413







-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
433
434
435
436
437
438
439








440
441
442
443
444
445
446







-
-
-
-
-
-
-
-







    <ClCompile Include="..\..\..\crc32.c" />
    <ClCompile Include="..\..\..\deflate.c" />
    <ClCompile Include="..\..\..\gzclose.c" />
    <ClCompile Include="..\..\..\gzlib.c" />
    <ClCompile Include="..\..\..\gzread.c" />
    <ClCompile Include="..\..\..\gzwrite.c" />
    <ClCompile Include="..\..\..\infback.c" />
    <ClCompile Include="..\..\masmx64\inffas8664.c">
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
    </ClCompile>
    <ClCompile Include="..\..\..\inffast.c" />
    <ClCompile Include="..\..\..\inflate.c" />
    <ClCompile Include="..\..\..\inftrees.c" />
    <ClCompile Include="..\..\minizip\ioapi.c" />
    <ClCompile Include="..\..\..\trees.c" />
    <ClCompile Include="..\..\..\uncompr.c" />
    <ClCompile Include="..\..\minizip\unzip.c" />

Changes to compat/zlib/contrib/vstudio/vc12/zlibvc.def.

1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







LIBRARY
; zlib data compression and ZIP file I/O library

VERSION		1.2
VERSION		1.3.1

EXPORTS
        adler32                                  @1
        compress                                 @2
        crc32                                    @3
        deflate                                  @4
        deflateCopy                              @5
147
148
149
150
151
152
153





147
148
149
150
151
152
153
154
155
156
157
158







+
+
+
+
+
        inflateValidate                         @169
        uncompress2                             @170
        gzfread                                 @171
        gzfwrite                                @172
        deflateGetDictionary                    @173
        adler32_z                               @174
        crc32_z                                 @175

; zlib1 v1.2.12 added:
		crc32_combine_gen						@176
		crc32_combine_gen64						@177
		crc32_combine_op						@178

Changes to compat/zlib/contrib/vstudio/vc12/zlibvc.sln.

Changes to compat/zlib/contrib/vstudio/vc12/zlibvc.vcxproj.

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
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







-
-
+
+




















-
+













-
-
-
-











-
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Win32</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
    </Link>
    <PreBuildEvent>
      <Command>cd ..\..\masmx86
bld_ml32.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">
    <Midl>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Win32</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
302
303
304
305
306
307
308
309
310


311
312
313
314
315
316
317
298
299
300
301
302
303
304


305
306
307
308
309
310
311
312
313







-
-
+
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Win32</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
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
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
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
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







-
+














-
-
-
-











-
-
+
+



















-
+











-
-
-
-











-
+







    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
    </Link>
    <PreBuildEvent>
      <Command>cd ..\..\masmx86
bld_ml32.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Midl>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>X64</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>
    <PreBuildEvent>
      <Command>cd ..\..\contrib\masmx64
bld_ml64.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Itanium</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
447
448
449
450
451
452
453
454

455
456
457
458
459
460
461
435
436
437
438
439
440
441

442
443
444
445
446
447
448
449







-
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>X64</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
492
493
494
495
496
497
498
499

500
501
502
503
504
505
506
480
481
482
483
484
485
486

487
488
489
490
491
492
493
494







-
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Itanium</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
537
538
539
540
541
542
543
544
545


546
547
548
549
550
551
552
525
526
527
528
529
530
531


532
533
534
535
536
537
538
539
540







-
-
+
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>X64</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594

595
596
597
598
599
600
601
548
549
550
551
552
553
554

555
556
557
558
559
560
561
562
563
564
565
566




567
568
569
570
571
572
573
574
575
576
577

578
579
580
581
582
583
584
585







-
+











-
-
-
-











-
+







      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>
    <PreBuildEvent>
      <Command>cd ..\..\masmx64
bld_ml64.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">
    <Midl>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Itanium</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
616
617
618
619
620
621
622








623
624
625
626
627
628
629







-
-
-
-
-
-
-
-







    <ClCompile Include="..\..\..\crc32.c" />
    <ClCompile Include="..\..\..\deflate.c" />
    <ClCompile Include="..\..\..\gzclose.c" />
    <ClCompile Include="..\..\..\gzlib.c" />
    <ClCompile Include="..\..\..\gzread.c" />
    <ClCompile Include="..\..\..\gzwrite.c" />
    <ClCompile Include="..\..\..\infback.c" />
    <ClCompile Include="..\..\masmx64\inffas8664.c">
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
    </ClCompile>
    <ClCompile Include="..\..\..\inffast.c" />
    <ClCompile Include="..\..\..\inflate.c" />
    <ClCompile Include="..\..\..\inftrees.c" />
    <ClCompile Include="..\..\minizip\ioapi.c" />
    <ClCompile Include="..\..\minizip\iowin32.c" />
    <ClCompile Include="..\..\..\trees.c" />
    <ClCompile Include="..\..\..\uncompr.c" />

Changes to compat/zlib/contrib/vstudio/vc14/testzlib.vcxproj.

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
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







-
+












-
+







    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>true</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)testzlib.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)testzlib.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
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
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







-
+












-
+















-
+






-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <OmitFramePointers>true</OmitFramePointers>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)testzlib.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <TargetMachine>MachineX86</TargetMachine>
      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <ClCompile>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
358
359
360
361
362
363
364
365

366
367
368
369
370
371
372

373
374
375
376
377
378
379
358
359
360
361
362
363
364

365
366
367
368
369
370
371

372
373
374
375
376
377
378
379







-
+






-
+







      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <TargetMachine>MachineIA64</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <ClCompile>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
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
404
405
406
407
408
409
410








411
412
413
414
415
416
417
418
419
420
421
422







-
-
-
-
-
-
-
-












  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\..\adler32.c" />
    <ClCompile Include="..\..\..\compress.c" />
    <ClCompile Include="..\..\..\crc32.c" />
    <ClCompile Include="..\..\..\deflate.c" />
    <ClCompile Include="..\..\..\infback.c" />
    <ClCompile Include="..\..\masmx64\inffas8664.c">
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
    </ClCompile>
    <ClCompile Include="..\..\..\inffast.c" />
    <ClCompile Include="..\..\..\inflate.c" />
    <ClCompile Include="..\..\..\inftrees.c" />
    <ClCompile Include="..\..\testzlib\testzlib.c" />
    <ClCompile Include="..\..\..\trees.c" />
    <ClCompile Include="..\..\..\uncompr.c" />
    <ClCompile Include="..\..\..\zutil.c" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>

Changes to compat/zlib/contrib/vstudio/vc14/zlib.rc.

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
30
31
32
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
30
31
32




-
-
+
+













-
+




-
+







#include <windows.h>

#define IDR_VERSION1  1
IDR_VERSION1	VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE
  FILEVERSION	 1, 2, 11, 0
  PRODUCTVERSION 1, 2, 11, 0
  FILEVERSION	 1, 3, 1, 0
  PRODUCTVERSION 1, 3, 1, 0
  FILEFLAGSMASK	VS_FFI_FILEFLAGSMASK
  FILEFLAGS	0
  FILEOS	VOS_DOS_WINDOWS32
  FILETYPE	VFT_DLL
  FILESUBTYPE	0	// not used
BEGIN
  BLOCK "StringFileInfo"
  BEGIN
    BLOCK "040904E4"
    //language ID = U.S. English, char set = Windows, Multilingual

    BEGIN
      VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
      VALUE "FileVersion",	"1.2.11\0"
      VALUE "FileVersion",	"1.3.1\0"
      VALUE "InternalName",	"zlib\0"
      VALUE "OriginalFilename",	"zlibwapi.dll\0"
      VALUE "ProductName",	"ZLib.DLL\0"
      VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
      VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0"
      VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
    END
  END
  BLOCK "VarFileInfo"
  BEGIN
    VALUE "Translation", 0x0409, 1252
  END
END

Changes to compat/zlib/contrib/vstudio/vc14/zlibstat.vcxproj.

166
167
168
169
170
171
172
173

174
175
176
177
178
179
180
166
167
168
169
170
171
172

173
174
175
176
177
178
179
180







-
+







    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
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
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







-
-
+
+


















-
+







-
+







      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
250
251
252
253
254
255
256
257

258
259
260
261
262
263
264
250
251
252
253
254
255
256

257
258
259
260
261
262
263
264







-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
279
280
281
282
283
284
285
286

287
288
289
290
291
292
293
279
280
281
282
283
284
285

286
287
288
289
290
291
292
293







-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
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
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







-
-
+
+


















-
+










-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
369
370
371
372
373
374
375
376

377
378
379
380
381
382
383
369
370
371
372
373
374
375

376
377
378
379
380
381
382
383







-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
399
400
401
402
403
404
405
406

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

406
407
408
409
410
411
412
413







-
+







  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
433
434
435
436
437
438
439








440
441
442
443
444
445
446







-
-
-
-
-
-
-
-







    <ClCompile Include="..\..\..\crc32.c" />
    <ClCompile Include="..\..\..\deflate.c" />
    <ClCompile Include="..\..\..\gzclose.c" />
    <ClCompile Include="..\..\..\gzlib.c" />
    <ClCompile Include="..\..\..\gzread.c" />
    <ClCompile Include="..\..\..\gzwrite.c" />
    <ClCompile Include="..\..\..\infback.c" />
    <ClCompile Include="..\..\masmx64\inffas8664.c">
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
    </ClCompile>
    <ClCompile Include="..\..\..\inffast.c" />
    <ClCompile Include="..\..\..\inflate.c" />
    <ClCompile Include="..\..\..\inftrees.c" />
    <ClCompile Include="..\..\minizip\ioapi.c" />
    <ClCompile Include="..\..\..\trees.c" />
    <ClCompile Include="..\..\..\uncompr.c" />
    <ClCompile Include="..\..\minizip\unzip.c" />

Changes to compat/zlib/contrib/vstudio/vc14/zlibvc.def.

1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







LIBRARY
; zlib data compression and ZIP file I/O library

VERSION		1.2
VERSION		1.3.1

EXPORTS
        adler32                                  @1
        compress                                 @2
        crc32                                    @3
        deflate                                  @4
        deflateCopy                              @5
147
148
149
150
151
152
153





147
148
149
150
151
152
153
154
155
156
157
158







+
+
+
+
+
        inflateValidate                         @169
        uncompress2                             @170
        gzfread                                 @171
        gzfwrite                                @172
        deflateGetDictionary                    @173
        adler32_z                               @174
        crc32_z                                 @175

; zlib1 v1.2.12 added:
		crc32_combine_gen						@176
		crc32_combine_gen64						@177
		crc32_combine_op						@178

Changes to compat/zlib/contrib/vstudio/vc14/zlibvc.sln.

Changes to compat/zlib/contrib/vstudio/vc14/zlibvc.vcxproj.

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
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







-
-
+
+




















-
+













-
-
-
-











-
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Win32</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
    </Link>
    <PreBuildEvent>
      <Command>cd ..\..\masmx86
bld_ml32.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">
    <Midl>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Win32</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
302
303
304
305
306
307
308
309
310


311
312
313
314
315
316
317
298
299
300
301
302
303
304


305
306
307
308
309
310
311
312
313







-
-
+
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Win32</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
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
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
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
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







-
+














-
-
-
-











-
-
+
+



















-
+











-
-
-
-











-
+







    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
    </Link>
    <PreBuildEvent>
      <Command>cd ..\..\masmx86
bld_ml32.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Midl>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>X64</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>
    <PreBuildEvent>
      <Command>cd ..\..\contrib\masmx64
bld_ml64.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Itanium</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
447
448
449
450
451
452
453
454

455
456
457
458
459
460
461
435
436
437
438
439
440
441

442
443
444
445
446
447
448
449







-
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>X64</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
492
493
494
495
496
497
498
499

500
501
502
503
504
505
506
480
481
482
483
484
485
486

487
488
489
490
491
492
493
494







-
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Itanium</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
537
538
539
540
541
542
543
544
545


546
547
548
549
550
551
552
525
526
527
528
529
530
531


532
533
534
535
536
537
538
539
540







-
-
+
+







      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>X64</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594

595
596
597
598
599
600
601
548
549
550
551
552
553
554

555
556
557
558
559
560
561
562
563
564
565
566




567
568
569
570
571
572
573
574
575
576
577

578
579
580
581
582
583
584
585







-
+











-
-
-
-











-
+







      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>
    <PreBuildEvent>
      <Command>cd ..\..\masmx64
bld_ml64.bat</Command>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">
    <Midl>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Itanium</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
616
617
618
619
620
621
622








623
624
625
626
627
628
629







-
-
-
-
-
-
-
-







    <ClCompile Include="..\..\..\crc32.c" />
    <ClCompile Include="..\..\..\deflate.c" />
    <ClCompile Include="..\..\..\gzclose.c" />
    <ClCompile Include="..\..\..\gzlib.c" />
    <ClCompile Include="..\..\..\gzread.c" />
    <ClCompile Include="..\..\..\gzwrite.c" />
    <ClCompile Include="..\..\..\infback.c" />
    <ClCompile Include="..\..\masmx64\inffas8664.c">
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Itanium'">true</ExcludedFromBuild>
      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
    </ClCompile>
    <ClCompile Include="..\..\..\inffast.c" />
    <ClCompile Include="..\..\..\inflate.c" />
    <ClCompile Include="..\..\..\inftrees.c" />
    <ClCompile Include="..\..\minizip\ioapi.c" />
    <ClCompile Include="..\..\minizip\iowin32.c" />
    <ClCompile Include="..\..\..\trees.c" />
    <ClCompile Include="..\..\..\uncompr.c" />

Added compat/zlib/contrib/vstudio/vc17/miniunz.vcxproj.


























































































































































































































































































































































































































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
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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|ARM">
      <Configuration>Debug</Configuration>
      <Platform>ARM</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|ARM64">
      <Configuration>Debug</Configuration>
      <Platform>ARM64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|x64">
      <Configuration>Debug</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|ARM">
      <Configuration>Release</Configuration>
      <Platform>ARM</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|ARM64">
      <Configuration>Release</Configuration>
      <Platform>ARM64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|x64">
      <Configuration>Release</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{C52F9E7B-498A-42BE-8DB4-85A15694382A}</ProjectGuid>
    <Keyword>Win32Proj</Keyword>
    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>Unicode</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup>
    <_ProjectFileVersion>10.0.30128.1</_ProjectFileVersion>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">x86\MiniUnzip$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">x86\MiniUnzip$(Configuration)\Tmp\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</GenerateManifest>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">x86\MiniUnzip$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">x86\MiniUnzip$(Configuration)\Tmp\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</GenerateManifest>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">x64\MiniUnzip$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">x64\MiniUnzip$(Configuration)\Tmp\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</LinkIncremental>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</LinkIncremental>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">false</GenerateManifest>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">x64\MiniUnzip$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">x64\MiniUnzip$(Configuration)\Tmp\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">false</LinkIncremental>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">false</LinkIncremental>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">false</GenerateManifest>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" />
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
    <OutDir>arm64\MiniUnzip$(Configuration)\</OutDir>
    <IntDir>arm64\MiniUnzip$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
    <OutDir>arm64\MiniUnzip$(Configuration)\</OutDir>
    <IntDir>arm64\MiniUnzip$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
    <OutDir>arm\MiniUnzip$(Configuration)\</OutDir>
    <IntDir>arm\MiniUnzip$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
    <OutDir>arm\MiniUnzip$(Configuration)\</OutDir>
    <IntDir>arm\MiniUnzip$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>true</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)miniunz.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)miniunz.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <TargetMachine>MachineX86</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <OmitFramePointers>true</OmitFramePointers>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)miniunz.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <TargetMachine>MachineX86</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>true</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)miniunz.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)miniunz.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
    <Midl />
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>true</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)miniunz.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)miniunz.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
    <Midl />
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>true</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)miniunz.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)miniunz.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <OmitFramePointers>true</OmitFramePointers>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)miniunz.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
    <Midl />
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <OmitFramePointers>true</OmitFramePointers>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)miniunz.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
    <Midl />
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <OmitFramePointers>true</OmitFramePointers>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)miniunz.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
    </Link>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\minizip\miniunz.c" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="zlibvc.vcxproj">
      <Project>{8fd826f8-3739-44e6-8cc8-997122e53b8d}</Project>
    </ProjectReference>
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>

Added compat/zlib/contrib/vstudio/vc17/minizip.vcxproj.






















































































































































































































































































































































































































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
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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|ARM">
      <Configuration>Debug</Configuration>
      <Platform>ARM</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|ARM64">
      <Configuration>Debug</Configuration>
      <Platform>ARM64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|x64">
      <Configuration>Debug</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|ARM">
      <Configuration>Release</Configuration>
      <Platform>ARM</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|ARM64">
      <Configuration>Release</Configuration>
      <Platform>ARM64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|x64">
      <Configuration>Release</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}</ProjectGuid>
    <Keyword>Win32Proj</Keyword>
    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>Unicode</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup>
    <_ProjectFileVersion>10.0.30128.1</_ProjectFileVersion>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">x86\MiniZip$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">x86\MiniZip$(Configuration)\Tmp\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</GenerateManifest>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">x86\MiniZip$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">x86\MiniZip$(Configuration)\Tmp\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">x64\$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">x64\$(Configuration)\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</LinkIncremental>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</LinkIncremental>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">false</GenerateManifest>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">x64\$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">x64\$(Configuration)\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">false</LinkIncremental>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">false</LinkIncremental>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" />
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
    <OutDir>arm64\MiniZip$(Configuration)\</OutDir>
    <IntDir>arm64\MiniZip$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
    <OutDir>arm64\MiniZip$(Configuration)\</OutDir>
    <IntDir>arm64\MiniZip$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
    <OutDir>arm\MiniZip$(Configuration)\</OutDir>
    <IntDir>arm\MiniZip$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
    <OutDir>arm\MiniZip$(Configuration)\</OutDir>
    <IntDir>arm\MiniZip$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>true</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)minizip.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)minizip.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <TargetMachine>MachineX86</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <OmitFramePointers>true</OmitFramePointers>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)minizip.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <TargetMachine>MachineX86</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>true</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)minizip.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)minizip.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
    <Midl />
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>true</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)minizip.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)minizip.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
    <Midl />
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>true</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)minizip.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)minizip.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <OmitFramePointers>true</OmitFramePointers>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)minizip.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
    <Midl />
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <OmitFramePointers>true</OmitFramePointers>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)minizip.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
    <Midl />
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <OmitFramePointers>true</OmitFramePointers>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)minizip.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
    </Link>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\minizip\minizip.c" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="zlibvc.vcxproj">
      <Project>{8fd826f8-3739-44e6-8cc8-997122e53b8d}</Project>
    </ProjectReference>
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>

Added compat/zlib/contrib/vstudio/vc17/testzlib.vcxproj.


























































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|ARM">
      <Configuration>Debug</Configuration>
      <Platform>ARM</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|ARM64">
      <Configuration>Debug</Configuration>
      <Platform>ARM64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|x64">
      <Configuration>Debug</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="ReleaseWithoutAsm|ARM">
      <Configuration>ReleaseWithoutAsm</Configuration>
      <Platform>ARM</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="ReleaseWithoutAsm|ARM64">
      <Configuration>ReleaseWithoutAsm</Configuration>
      <Platform>ARM64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="ReleaseWithoutAsm|Win32">
      <Configuration>ReleaseWithoutAsm</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="ReleaseWithoutAsm|x64">
      <Configuration>ReleaseWithoutAsm</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|ARM">
      <Configuration>Release</Configuration>
      <Platform>ARM</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|ARM64">
      <Configuration>Release</Configuration>
      <Platform>ARM64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|x64">
      <Configuration>Release</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}</ProjectGuid>
    <RootNamespace>testzlib</RootNamespace>
    <Keyword>Win32Proj</Keyword>
    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>Unicode</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup>
    <_ProjectFileVersion>10.0.30128.1</_ProjectFileVersion>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">x86\TestZlib$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">x86\TestZlib$(Configuration)\Tmp\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</GenerateManifest>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">x86\TestZlib$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">x86\TestZlib$(Configuration)\Tmp\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">false</LinkIncremental>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">false</GenerateManifest>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">x86\TestZlib$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">x86\TestZlib$(Configuration)\Tmp\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</GenerateManifest>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">x64\TestZlib$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">x64\TestZlib$(Configuration)\Tmp\</IntDir>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">false</GenerateManifest>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">x64\TestZlib$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">x64\TestZlib$(Configuration)\Tmp\</IntDir>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'">false</GenerateManifest>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">x64\TestZlib$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">x64\TestZlib$(Configuration)\Tmp\</IntDir>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">false</GenerateManifest>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" />
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
    <OutDir>arm64\TestZlib$(Configuration)\</OutDir>
    <IntDir>arm64\TestZlib$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
    <OutDir>arm64\TestZlib$(Configuration)\</OutDir>
    <IntDir>arm64\TestZlib$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'">
    <OutDir>arm64\TestZlib$(Configuration)\</OutDir>
    <IntDir>arm64\TestZlib$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
    <OutDir>arm\TestZlib$(Configuration)\</OutDir>
    <IntDir>arm\TestZlib$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
    <OutDir>arm\TestZlib$(Configuration)\</OutDir>
    <IntDir>arm\TestZlib$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'">
    <OutDir>arm\TestZlib$(Configuration)\</OutDir>
    <IntDir>arm\TestZlib$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>true</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)testzlib.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)testzlib.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <TargetMachine>MachineX86</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <OmitFramePointers>true</OmitFramePointers>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <OutputFile>$(OutDir)testzlib.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <TargetMachine>MachineX86</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <OmitFramePointers>true</OmitFramePointers>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)testzlib.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <TargetMachine>MachineX86</TargetMachine>
      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <ClCompile>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
    <ClCompile>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
    <ClCompile>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">
    <ClCompile>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'">
    <ClCompile>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'">
    <ClCompile>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <ClCompile>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
    <ClCompile>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
    <ClCompile>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\..\adler32.c" />
    <ClCompile Include="..\..\..\compress.c" />
    <ClCompile Include="..\..\..\crc32.c" />
    <ClCompile Include="..\..\..\deflate.c" />
    <ClCompile Include="..\..\..\infback.c" />
    <ClCompile Include="..\..\..\inffast.c" />
    <ClCompile Include="..\..\..\inflate.c" />
    <ClCompile Include="..\..\..\inftrees.c" />
    <ClCompile Include="..\..\testzlib\testzlib.c" />
    <ClCompile Include="..\..\..\trees.c" />
    <ClCompile Include="..\..\..\uncompr.c" />
    <ClCompile Include="..\..\..\zutil.c" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>

Added compat/zlib/contrib/vstudio/vc17/testzlibdll.vcxproj.


























































































































































































































































































































































































































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
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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|ARM">
      <Configuration>Debug</Configuration>
      <Platform>ARM</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|ARM64">
      <Configuration>Debug</Configuration>
      <Platform>ARM64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|x64">
      <Configuration>Debug</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|ARM">
      <Configuration>Release</Configuration>
      <Platform>ARM</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|ARM64">
      <Configuration>Release</Configuration>
      <Platform>ARM64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|x64">
      <Configuration>Release</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{C52F9E7B-498A-42BE-8DB4-85A15694366A}</ProjectGuid>
    <Keyword>Win32Proj</Keyword>
    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>Unicode</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup>
    <_ProjectFileVersion>10.0.30128.1</_ProjectFileVersion>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">x86\TestZlibDll$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">x86\TestZlibDll$(Configuration)\Tmp\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</GenerateManifest>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">x86\TestZlibDll$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">x86\TestZlibDll$(Configuration)\Tmp\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</GenerateManifest>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">x64\TestZlibDll$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">x64\TestZlibDll$(Configuration)\Tmp\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</LinkIncremental>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</LinkIncremental>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">false</GenerateManifest>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">x64\TestZlibDll$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">x64\TestZlibDll$(Configuration)\Tmp\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">false</LinkIncremental>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">false</LinkIncremental>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">false</GenerateManifest>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" />
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
    <OutDir>arm64\TestZlibDll$(Configuration)\</OutDir>
    <IntDir>arm64\TestZlibDll$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
    <OutDir>arm64\TestZlibDll$(Configuration)\</OutDir>
    <IntDir>arm64\TestZlibDll$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
    <OutDir>arm\TestZlibDll$(Configuration)\</OutDir>
    <IntDir>arm\TestZlibDll$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
    <OutDir>arm\TestZlibDll$(Configuration)\</OutDir>
    <IntDir>arm\TestZlibDll$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>true</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)testzlibdll.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)testzlib.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <TargetMachine>MachineX86</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <OmitFramePointers>true</OmitFramePointers>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)testzlibdll.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <TargetMachine>MachineX86</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>true</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)testzlibdll.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)testzlib.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
    <Midl />
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>true</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)testzlibdll.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)testzlib.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
    <Midl />
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>true</MinimalRebuild>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)testzlibdll.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)testzlib.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <OmitFramePointers>true</OmitFramePointers>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)testzlibdll.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
    <Midl />
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <OmitFramePointers>true</OmitFramePointers>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)testzlibdll.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
    <Midl />
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <OmitFramePointers>true</OmitFramePointers>
      <AdditionalIncludeDirectories>..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalDependencies>x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)testzlibdll.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
    </Link>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\testzlib\testzlib.c" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="zlibvc.vcxproj">
      <Project>{8fd826f8-3739-44e6-8cc8-997122e53b8d}</Project>
    </ProjectReference>
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>

Added compat/zlib/contrib/vstudio/vc17/zlib.rc.

































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
30
31
32
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#include <windows.h>

#define IDR_VERSION1  1
IDR_VERSION1	VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE
  FILEVERSION	 1, 3, 1, 0
  PRODUCTVERSION 1, 3, 1, 0
  FILEFLAGSMASK	VS_FFI_FILEFLAGSMASK
  FILEFLAGS	0
  FILEOS	VOS_DOS_WINDOWS32
  FILETYPE	VFT_DLL
  FILESUBTYPE	0	// not used
BEGIN
  BLOCK "StringFileInfo"
  BEGIN
    BLOCK "040904E4"
    //language ID = U.S. English, char set = Windows, Multilingual

    BEGIN
      VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
      VALUE "FileVersion",	"1.3.1\0"
      VALUE "InternalName",	"zlib\0"
      VALUE "OriginalFilename",	"zlibwapi.dll\0"
      VALUE "ProductName",	"ZLib.DLL\0"
      VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
      VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
    END
  END
  BLOCK "VarFileInfo"
  BEGIN
    VALUE "Translation", 0x0409, 1252
  END
END

Added compat/zlib/contrib/vstudio/vc17/zlibstat.vcxproj.



























































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|ARM">
      <Configuration>Debug</Configuration>
      <Platform>ARM</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|ARM64">
      <Configuration>Debug</Configuration>
      <Platform>ARM64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|x64">
      <Configuration>Debug</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="ReleaseWithoutAsm|ARM">
      <Configuration>ReleaseWithoutAsm</Configuration>
      <Platform>ARM</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="ReleaseWithoutAsm|ARM64">
      <Configuration>ReleaseWithoutAsm</Configuration>
      <Platform>ARM64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="ReleaseWithoutAsm|Win32">
      <Configuration>ReleaseWithoutAsm</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="ReleaseWithoutAsm|x64">
      <Configuration>ReleaseWithoutAsm</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|ARM">
      <Configuration>Release</Configuration>
      <Platform>ARM</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|ARM64">
      <Configuration>Release</Configuration>
      <Platform>ARM64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|x64">
      <Configuration>Release</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}</ProjectGuid>
    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'" Label="Configuration">
    <ConfigurationType>StaticLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>StaticLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>StaticLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <PlatformToolset>v143</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'" Label="Configuration">
    <ConfigurationType>StaticLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'" Label="Configuration">
    <ConfigurationType>StaticLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'" Label="Configuration">
    <ConfigurationType>StaticLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <ConfigurationType>StaticLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
    <ConfigurationType>StaticLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
    <ConfigurationType>StaticLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <ConfigurationType>StaticLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
    <ConfigurationType>StaticLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
    <ConfigurationType>StaticLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup>
    <_ProjectFileVersion>10.0.30128.1</_ProjectFileVersion>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">x86\ZlibStat$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">x86\ZlibStat$(Configuration)\Tmp\</IntDir>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">x86\ZlibStat$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">x86\ZlibStat$(Configuration)\Tmp\</IntDir>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">x86\ZlibStat$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">x86\ZlibStat$(Configuration)\Tmp\</IntDir>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">x64\ZlibStat$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">x64\ZlibStat$(Configuration)\Tmp\</IntDir>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">x64\ZlibStat$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">x64\ZlibStat$(Configuration)\Tmp\</IntDir>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">x64\ZlibStat$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">x64\ZlibStat$(Configuration)\Tmp\</IntDir>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" />
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
    <OutDir>arm64\ZlibStat$(Configuration)\</OutDir>
    <IntDir>arm64\ZlibStat$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
    <OutDir>arm64\ZlibStat$(Configuration)\</OutDir>
    <IntDir>arm64\ZlibStat$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'">
    <OutDir>arm64\ZlibStat$(Configuration)\</OutDir>
    <IntDir>arm64\ZlibStat$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
    <OutDir>arm\ZlibStat$(Configuration)\</OutDir>
    <IntDir>arm\ZlibStat$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
    <OutDir>arm\ZlibStat$(Configuration)\</OutDir>
    <IntDir>arm\ZlibStat$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'">
    <OutDir>arm\ZlibStat$(Configuration)\</OutDir>
    <IntDir>arm\ZlibStat$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <DebugInformationFormat>OldStyle</DebugInformationFormat>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <DebugInformationFormat>OldStyle</DebugInformationFormat>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
    <Midl />
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <DebugInformationFormat>OldStyle</DebugInformationFormat>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:ARM64 /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
    <Midl />
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <DebugInformationFormat>OldStyle</DebugInformationFormat>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:ARM /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
    <Midl />
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:ARM64 /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
    <Midl />
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:ARM /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'">
    <Midl />
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:ARM64 /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'">
    <Midl />
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibstat.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Lib>
      <AdditionalOptions>/MACHINE:ARM /NODEFAULTLIB %(AdditionalOptions)</AdditionalOptions>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\..\adler32.c" />
    <ClCompile Include="..\..\..\compress.c" />
    <ClCompile Include="..\..\..\crc32.c" />
    <ClCompile Include="..\..\..\deflate.c" />
    <ClCompile Include="..\..\..\gzclose.c" />
    <ClCompile Include="..\..\..\gzlib.c" />
    <ClCompile Include="..\..\..\gzread.c" />
    <ClCompile Include="..\..\..\gzwrite.c" />
    <ClCompile Include="..\..\..\infback.c" />
    <ClCompile Include="..\..\..\inffast.c" />
    <ClCompile Include="..\..\..\inflate.c" />
    <ClCompile Include="..\..\..\inftrees.c" />
    <ClCompile Include="..\..\minizip\ioapi.c" />
    <ClCompile Include="..\..\..\trees.c" />
    <ClCompile Include="..\..\..\uncompr.c" />
    <ClCompile Include="..\..\minizip\unzip.c" />
    <ClCompile Include="..\..\minizip\zip.c" />
    <ClCompile Include="..\..\..\zutil.c" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="zlib.rc" />
  </ItemGroup>
  <ItemGroup>
    <None Include="zlibvc.def" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>

Added compat/zlib/contrib/vstudio/vc17/zlibvc.def.































































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
LIBRARY
; zlib data compression and ZIP file I/O library

VERSION		1.3.1

EXPORTS
        adler32                                  @1
        compress                                 @2
        crc32                                    @3
        deflate                                  @4
        deflateCopy                              @5
        deflateEnd                               @6
        deflateInit2_                            @7
        deflateInit_                             @8
        deflateParams                            @9
        deflateReset                             @10
        deflateSetDictionary                     @11
        gzclose                                  @12
        gzdopen                                  @13
        gzerror                                  @14
        gzflush                                  @15
        gzopen                                   @16
        gzread                                   @17
        gzwrite                                  @18
        inflate                                  @19
        inflateEnd                               @20
        inflateInit2_                            @21
        inflateInit_                             @22
        inflateReset                             @23
        inflateSetDictionary                     @24
        inflateSync                              @25
        uncompress                               @26
        zlibVersion                              @27
        gzprintf                                 @28
        gzputc                                   @29
        gzgetc                                   @30
        gzseek                                   @31
        gzrewind                                 @32
        gztell                                   @33
        gzeof                                    @34
        gzsetparams                              @35
        zError                                   @36
        inflateSyncPoint                         @37
        get_crc_table                            @38
        compress2                                @39
        gzputs                                   @40
        gzgets                                   @41
        inflateCopy                              @42
        inflateBackInit_                         @43
        inflateBack                              @44
        inflateBackEnd                           @45
        compressBound                            @46
        deflateBound                             @47
        gzclearerr                               @48
        gzungetc                                 @49
        zlibCompileFlags                         @50
        deflatePrime                             @51
        deflatePending                           @52

        unzOpen                                  @61
        unzClose                                 @62
        unzGetGlobalInfo                         @63
        unzGetCurrentFileInfo                    @64
        unzGoToFirstFile                         @65
        unzGoToNextFile                          @66
        unzOpenCurrentFile                       @67
        unzReadCurrentFile                       @68
        unzOpenCurrentFile3                      @69
        unztell                                  @70
        unzeof                                   @71
        unzCloseCurrentFile                      @72
        unzGetGlobalComment                      @73
        unzStringFileNameCompare                 @74
        unzLocateFile                            @75
        unzGetLocalExtrafield                    @76
        unzOpen2                                 @77
        unzOpenCurrentFile2                      @78
        unzOpenCurrentFilePassword               @79

        zipOpen                                  @80
        zipOpenNewFileInZip                      @81
        zipWriteInFileInZip                      @82
        zipCloseFileInZip                        @83
        zipClose                                 @84
        zipOpenNewFileInZip2                     @86
        zipCloseFileInZipRaw                     @87
        zipOpen2                                 @88
        zipOpenNewFileInZip3                     @89

        unzGetFilePos                            @100
        unzGoToFilePos                           @101

        fill_win32_filefunc                      @110

; zlibwapi v1.2.4 added:
        fill_win32_filefunc64                   @111
        fill_win32_filefunc64A                  @112
        fill_win32_filefunc64W                  @113

        unzOpen64                               @120
        unzOpen2_64                             @121
        unzGetGlobalInfo64                      @122
        unzGetCurrentFileInfo64                 @124
        unzGetCurrentFileZStreamPos64           @125
        unztell64                               @126
        unzGetFilePos64                         @127
        unzGoToFilePos64                        @128

        zipOpen64                               @130
        zipOpen2_64                             @131
        zipOpenNewFileInZip64                   @132
        zipOpenNewFileInZip2_64                 @133
        zipOpenNewFileInZip3_64                 @134
        zipOpenNewFileInZip4_64                 @135
        zipCloseFileInZipRaw64                  @136

; zlib1 v1.2.4 added:
        adler32_combine                         @140
        crc32_combine                           @142
        deflateSetHeader                        @144
        deflateTune                             @145
        gzbuffer                                @146
        gzclose_r                               @147
        gzclose_w                               @148
        gzdirect                                @149
        gzoffset                                @150
        inflateGetHeader                        @156
        inflateMark                             @157
        inflatePrime                            @158
        inflateReset2                           @159
        inflateUndermine                        @160

; zlib1 v1.2.6 added:
        gzgetc_                                 @161
        inflateResetKeep                        @163
        deflateResetKeep                        @164

; zlib1 v1.2.7 added:
        gzopen_w                                @165

; zlib1 v1.2.8 added:
        inflateGetDictionary                    @166
        gzvprintf                               @167

; zlib1 v1.2.9 added:
        inflateCodesUsed                        @168
        inflateValidate                         @169
        uncompress2                             @170
        gzfread                                 @171
        gzfwrite                                @172
        deflateGetDictionary                    @173
        adler32_z                               @174
        crc32_z                                 @175

; zlib1 v1.2.12 added:
		crc32_combine_gen						@176
		crc32_combine_gen64						@177
		crc32_combine_op						@178

Added compat/zlib/contrib/vstudio/vc17/zlibvc.sln.




















































































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33015.44
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcxproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcxproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlibdll", "testzlibdll.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcxproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|ARM = Debug|ARM
		Debug|ARM64 = Debug|ARM64
		Debug|Win32 = Debug|Win32
		Debug|x64 = Debug|x64
		Release|ARM = Release|ARM
		Release|ARM64 = Release|ARM64
		Release|Win32 = Release|Win32
		Release|x64 = Release|x64
		ReleaseWithoutAsm|ARM = ReleaseWithoutAsm|ARM
		ReleaseWithoutAsm|ARM64 = ReleaseWithoutAsm|ARM64
		ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32
		ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|ARM.ActiveCfg = Debug|ARM
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|ARM.Build.0 = Debug|ARM
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|ARM64.ActiveCfg = Debug|ARM64
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|ARM64.Build.0 = Debug|ARM64
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|ARM.ActiveCfg = Release|ARM
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|ARM.Build.0 = Release|ARM
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|ARM64.ActiveCfg = Release|ARM64
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|ARM64.Build.0 = Release|ARM64
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|ARM.ActiveCfg = ReleaseWithoutAsm|ARM
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|ARM.Build.0 = ReleaseWithoutAsm|ARM
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|ARM64.ActiveCfg = ReleaseWithoutAsm|ARM64
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|ARM64.Build.0 = ReleaseWithoutAsm|ARM64
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64
		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|ARM.ActiveCfg = Debug|ARM
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|ARM.Build.0 = Debug|ARM
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|ARM64.ActiveCfg = Debug|ARM64
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|ARM64.Build.0 = Debug|ARM64
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|ARM.ActiveCfg = Release|ARM
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|ARM.Build.0 = Release|ARM
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|ARM64.ActiveCfg = Release|ARM64
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|ARM64.Build.0 = Release|ARM64
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|ARM.ActiveCfg = ReleaseWithoutAsm|ARM
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|ARM.Build.0 = ReleaseWithoutAsm|ARM
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|ARM64.ActiveCfg = ReleaseWithoutAsm|ARM64
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|ARM64.Build.0 = ReleaseWithoutAsm|ARM64
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64
		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|ARM.ActiveCfg = Debug|ARM
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|ARM.Build.0 = Debug|ARM
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|ARM64.ActiveCfg = Debug|ARM64
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|ARM64.Build.0 = Debug|ARM64
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|ARM.ActiveCfg = Release|ARM
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|ARM.Build.0 = Release|ARM
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|ARM64.ActiveCfg = Release|ARM64
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|ARM64.Build.0 = Release|ARM64
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|ARM.ActiveCfg = ReleaseWithoutAsm|ARM
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|ARM.Build.0 = ReleaseWithoutAsm|ARM
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|ARM64.ActiveCfg = ReleaseWithoutAsm|ARM64
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|ARM64.Build.0 = ReleaseWithoutAsm|ARM64
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64
		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|ARM.ActiveCfg = Debug|ARM
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|ARM.Build.0 = Debug|ARM
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|ARM64.ActiveCfg = Debug|ARM64
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|ARM64.Build.0 = Debug|ARM64
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|ARM.ActiveCfg = Release|ARM
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|ARM.Build.0 = Release|ARM
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|ARM64.ActiveCfg = Release|ARM64
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|ARM64.Build.0 = Release|ARM64
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|ARM.ActiveCfg = Release|ARM
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|ARM.Build.0 = Release|ARM
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|ARM64.ActiveCfg = Release|ARM64
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|ARM64.Build.0 = Release|ARM64
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32
		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|ARM.ActiveCfg = Debug|ARM
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|ARM.Build.0 = Debug|ARM
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|ARM64.ActiveCfg = Debug|ARM64
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|ARM64.Build.0 = Debug|ARM64
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|ARM.ActiveCfg = Release|ARM
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|ARM.Build.0 = Release|ARM
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|ARM64.ActiveCfg = Release|ARM64
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|ARM64.Build.0 = Release|ARM64
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|ARM.ActiveCfg = Release|ARM
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|ARM.Build.0 = Release|ARM
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|ARM64.ActiveCfg = Release|ARM64
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|ARM64.Build.0 = Release|ARM64
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32
		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|ARM.ActiveCfg = Debug|ARM
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|ARM.Build.0 = Debug|ARM
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|ARM64.ActiveCfg = Debug|ARM64
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|ARM64.Build.0 = Debug|ARM64
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|ARM.ActiveCfg = Release|ARM
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|ARM.Build.0 = Release|ARM
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|ARM64.ActiveCfg = Release|ARM64
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|ARM64.Build.0 = Release|ARM64
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|ARM.ActiveCfg = Release|ARM
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|ARM.Build.0 = Release|ARM
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|ARM64.ActiveCfg = Release|ARM64
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|ARM64.Build.0 = Release|ARM64
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32
		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
	GlobalSection(ExtensibilityGlobals) = postSolution
		SolutionGuid = {EAA58685-56D9-43F2-8703-FD2CB020745E}
	EndGlobalSection
EndGlobal

Added compat/zlib/contrib/vstudio/vc17/zlibvc.vcxproj.












































































































































































































































































































































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|ARM">
      <Configuration>Debug</Configuration>
      <Platform>ARM</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|ARM64">
      <Configuration>Debug</Configuration>
      <Platform>ARM64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|x64">
      <Configuration>Debug</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="ReleaseWithoutAsm|ARM">
      <Configuration>ReleaseWithoutAsm</Configuration>
      <Platform>ARM</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="ReleaseWithoutAsm|ARM64">
      <Configuration>ReleaseWithoutAsm</Configuration>
      <Platform>ARM64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="ReleaseWithoutAsm|Win32">
      <Configuration>ReleaseWithoutAsm</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="ReleaseWithoutAsm|x64">
      <Configuration>ReleaseWithoutAsm</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|ARM">
      <Configuration>Release</Configuration>
      <Platform>ARM</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|ARM64">
      <Configuration>Release</Configuration>
      <Platform>ARM64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|x64">
      <Configuration>Release</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{8FD826F8-3739-44E6-8CC8-997122E53B8D}</ProjectGuid>
    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <PlatformToolset>v143</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseOfMfc>false</UseOfMfc>
    <PlatformToolset>v143</PlatformToolset>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup>
    <_ProjectFileVersion>10.0.30128.1</_ProjectFileVersion>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">x86\ZlibDll$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">x86\ZlibDll$(Configuration)\Tmp\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</GenerateManifest>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">x86\ZlibDll$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">x86\ZlibDll$(Configuration)\Tmp\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">false</LinkIncremental>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">false</GenerateManifest>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">x86\ZlibDll$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">x86\ZlibDll$(Configuration)\Tmp\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</GenerateManifest>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">x64\ZlibDll$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">x64\ZlibDll$(Configuration)\Tmp\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</LinkIncremental>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</LinkIncremental>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">false</GenerateManifest>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">x64\ZlibDll$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">x64\ZlibDll$(Configuration)\Tmp\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">false</LinkIncremental>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'">false</LinkIncremental>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'">false</LinkIncremental>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'">false</GenerateManifest>
    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">x64\ZlibDll$(Configuration)\</OutDir>
    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">x64\ZlibDll$(Configuration)\Tmp\</IntDir>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">false</LinkIncremental>
    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">false</LinkIncremental>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">false</GenerateManifest>
    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">false</GenerateManifest>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">AllRules.ruleset</CodeAnalysisRuleSet>
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" />
    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" />
    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" />
    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">zlibwapi</TargetName>
    <TargetName Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">zlibwapi</TargetName>
    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">zlibwapi</TargetName>
    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">zlibwapi</TargetName>
    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">zlibwapi</TargetName>
    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">zlibwapi</TargetName>
    <TargetName Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">zlibwapi</TargetName>
    <TargetName Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'">zlibwapi</TargetName>
    <TargetName Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'">zlibwapi</TargetName>
    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">zlibwapi</TargetName>
    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">zlibwapi</TargetName>
    <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">zlibwapi</TargetName>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
    <OutDir>arm64\ZlibDll$(Configuration)\</OutDir>
    <IntDir>arm64\ZlibDll$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
    <OutDir>arm\ZlibDll$(Configuration)\</OutDir>
    <IntDir>arm\ZlibDll$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
    <OutDir>arm64\ZlibDll$(Configuration)\</OutDir>
    <IntDir>arm64\ZlibDll$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'">
    <OutDir>arm64\ZlibDll$(Configuration)\</OutDir>
    <IntDir>arm64\ZlibDll$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
    <OutDir>arm\ZlibDll$(Configuration)\</OutDir>
    <IntDir>arm\ZlibDll$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'">
    <OutDir>arm\ZlibDll$(Configuration)\</OutDir>
    <IntDir>arm\ZlibDll$(Configuration)\Tmp\</IntDir>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <Midl>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Win32</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Win32'">
    <Midl>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Win32</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerOutput>All</AssemblerOutput>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <Midl>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Win32</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerOutput>All</AssemblerOutput>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Midl>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>X64</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
    <Midl>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
    <Midl>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|x64'">
    <Midl>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>X64</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerOutput>All</AssemblerOutput>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM64'">
    <Midl>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerOutput>All</AssemblerOutput>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|ARM'">
    <Midl>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerOutput>All</AssemblerOutput>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <Midl>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>X64</TargetEnvironment>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerOutput>All</AssemblerOutput>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
    <Midl>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerOutput>All</AssemblerOutput>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
    <Midl>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TypeLibraryName>$(OutDir)zlibvc.tlb</TypeLibraryName>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <AdditionalIncludeDirectories>..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>
      <AssemblerOutput>All</AssemblerOutput>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
      <ObjectFileName>$(IntDir)</ObjectFileName>
      <ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
      <BrowseInformation>
      </BrowseInformation>
      <WarningLevel>Level3</WarningLevel>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)zlibwapi.dll</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <ProgramDatabaseFile>$(OutDir)zlibwapi.pdb</ProgramDatabaseFile>
      <GenerateMapFile>true</GenerateMapFile>
      <MapFileName>$(OutDir)zlibwapi.map</MapFileName>
      <SubSystem>Windows</SubSystem>
      <ImportLibrary>$(OutDir)zlibwapi.lib</ImportLibrary>
    </Link>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\..\adler32.c" />
    <ClCompile Include="..\..\..\compress.c" />
    <ClCompile Include="..\..\..\crc32.c" />
    <ClCompile Include="..\..\..\deflate.c" />
    <ClCompile Include="..\..\..\gzclose.c" />
    <ClCompile Include="..\..\..\gzlib.c" />
    <ClCompile Include="..\..\..\gzread.c" />
    <ClCompile Include="..\..\..\gzwrite.c" />
    <ClCompile Include="..\..\..\infback.c" />
    <ClCompile Include="..\..\..\inffast.c" />
    <ClCompile Include="..\..\..\inflate.c" />
    <ClCompile Include="..\..\..\inftrees.c" />
    <ClCompile Include="..\..\minizip\ioapi.c" />
    <ClCompile Include="..\..\minizip\iowin32.c" />
    <ClCompile Include="..\..\..\trees.c" />
    <ClCompile Include="..\..\..\uncompr.c" />
    <ClCompile Include="..\..\minizip\unzip.c">
      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">ZLIB_INTERNAL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">ZLIB_INTERNAL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">ZLIB_INTERNAL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">ZLIB_INTERNAL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ClCompile>
    <ClCompile Include="..\..\minizip\zip.c">
      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">ZLIB_INTERNAL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">ZLIB_INTERNAL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">ZLIB_INTERNAL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">ZLIB_INTERNAL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ClCompile>
    <ClCompile Include="..\..\..\zutil.c" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="zlib.rc" />
  </ItemGroup>
  <ItemGroup>
    <None Include="zlibvc.def" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="..\..\..\deflate.h" />
    <ClInclude Include="..\..\..\infblock.h" />
    <ClInclude Include="..\..\..\infcodes.h" />
    <ClInclude Include="..\..\..\inffast.h" />
    <ClInclude Include="..\..\..\inftrees.h" />
    <ClInclude Include="..\..\..\infutil.h" />
    <ClInclude Include="..\..\..\zconf.h" />
    <ClInclude Include="..\..\..\zlib.h" />
    <ClInclude Include="..\..\..\zutil.h" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>

Changes to compat/zlib/contrib/vstudio/vc9/miniunz.vcproj.

538
539
540
541
542
543
544
545

546
547
548
549
550
551
552
538
539
540
541
542
543
544

545
546
547
548
549
550
551
552







-
+







		</Configuration>
	</Configurations>
	<References>
	</References>
	<Files>
		<Filter
			Name="Source Files"
			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
			Filter="cpp;c;cxx;def;odl;idl;hpj;bat"
			>
			<File
				RelativePath="..\..\minizip\miniunz.c"
				>
			</File>
		</Filter>
		<Filter

Changes to compat/zlib/contrib/vstudio/vc9/minizip.vcproj.

535
536
537
538
539
540
541
542

543
544
545
546
547
548
549
535
536
537
538
539
540
541

542
543
544
545
546
547
548
549







-
+







		</Configuration>
	</Configurations>
	<References>
	</References>
	<Files>
		<Filter
			Name="Source Files"
			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
			Filter="cpp;c;cxx;def;odl;idl;hpj;bat"
			>
			<File
				RelativePath="..\..\minizip\minizip.c"
				>
			</File>
		</Filter>
		<Filter

Changes to compat/zlib/contrib/vstudio/vc9/testzlib.vcproj.

44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58







-
+







			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS"
				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS"
				MinimalRebuild="true"
				BasicRuntimeChecks="0"
				RuntimeLibrary="1"
				BufferSecurityCheck="false"
				UsePrecompiledHeader="0"
				AssemblerOutput="4"
				AssemblerListingLocation="$(IntDir)\"
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
67
68
69
70
71
72
73

74
75
76
77
78
79
80







-







				Name="VCResourceCompilerTool"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				AdditionalDependencies="..\..\masmx86\match686.obj ..\..\masmx86\inffas32.obj"
				OutputFile="$(OutDir)/testzlib.exe"
				LinkIncremental="2"
				GenerateManifest="false"
				GenerateDebugInformation="true"
				ProgramDatabaseFile="$(OutDir)/testzlib.pdb"
				SubSystem="1"
				RandomizedBaseAddress="1"
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
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







-
+
















-







			/>
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS"
				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS"
				BasicRuntimeChecks="0"
				RuntimeLibrary="3"
				BufferSecurityCheck="false"
				AssemblerListingLocation="$(IntDir)\"
			/>
			<Tool
				Name="VCManagedResourceCompilerTool"
			/>
			<Tool
				Name="VCResourceCompilerTool"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				AdditionalDependencies="..\..\masmx64\gvmat64.obj ..\..\masmx64\inffasx64.obj"
				GenerateManifest="false"
			/>
			<Tool
				Name="VCALinkTool"
			/>
			<Tool
				Name="VCManifestTool"
513
514
515
516
517
518
519
520

521
522
523
524
525
526
527
511
512
513
514
515
516
517

518
519
520
521
522
523
524
525







-
+







			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="2"
				InlineFunctionExpansion="1"
				OmitFramePointers="true"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS"
				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS"
				StringPooling="true"
				BasicRuntimeChecks="0"
				RuntimeLibrary="0"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				UsePrecompiledHeader="0"
				AssemblerListingLocation="$(IntDir)\"
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
534
535
536
537
538
539
540

541
542
543
544
545
546
547







-







				Name="VCResourceCompilerTool"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				AdditionalDependencies="..\..\masmx86\match686.obj ..\..\masmx86\inffas32.obj"
				OutputFile="$(OutDir)/testzlib.exe"
				LinkIncremental="1"
				GenerateManifest="false"
				GenerateDebugInformation="true"
				SubSystem="1"
				OptimizeReferences="2"
				EnableCOMDATFolding="2"
596
597
598
599
600
601
602
603

604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616

617
618
619
620
621
622
623







-
+
















-







			/>
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS"
				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS"
				BasicRuntimeChecks="0"
				RuntimeLibrary="0"
				BufferSecurityCheck="false"
				AssemblerListingLocation="$(IntDir)\"
			/>
			<Tool
				Name="VCManagedResourceCompilerTool"
			/>
			<Tool
				Name="VCResourceCompilerTool"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				AdditionalDependencies="..\..\masmx64\gvmat64.obj ..\..\masmx64\inffasx64.obj"
				GenerateManifest="false"
			/>
			<Tool
				Name="VCALinkTool"
			/>
			<Tool
				Name="VCManifestTool"
729
730
731
732
733
734
735
736

737
738
739
740
741
742
743
725
726
727
728
729
730
731

732
733
734
735
736
737
738
739







-
+







		</Configuration>
	</Configurations>
	<References>
	</References>
	<Files>
		<Filter
			Name="Source Files"
			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
			Filter="cpp;c;cxx;def;odl;idl;hpj;bat"
			>
			<File
				RelativePath="..\..\..\adler32.c"
				>
			</File>
			<File
				RelativePath="..\..\..\compress.c"
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
748
749
750
751
752
753
754




















































755
756
757
758
759
760
761







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







				>
			</File>
			<File
				RelativePath="..\..\..\infback.c"
				>
			</File>
			<File
				RelativePath="..\..\masmx64\inffas8664.c"
				>
				<FileConfiguration
					Name="Debug|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Debug|Itanium"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="ReleaseWithoutAsm|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="ReleaseWithoutAsm|Itanium"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Release|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Release|Itanium"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
			</File>
			<File
				RelativePath="..\..\..\inffast.c"
				>
			</File>
			<File
				RelativePath="..\..\..\inflate.c"
				>
			</File>

Changes to compat/zlib/contrib/vstudio/vc9/testzlibdll.vcproj.

538
539
540
541
542
543
544
545

546
547
548
549
550
551
552
538
539
540
541
542
543
544

545
546
547
548
549
550
551
552







-
+







		</Configuration>
	</Configurations>
	<References>
	</References>
	<Files>
		<Filter
			Name="Source Files"
			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
			Filter="cpp;c;cxx;def;odl;idl;hpj;bat"
			>
			<File
				RelativePath="..\..\testzlib\testzlib.c"
				>
			</File>
		</Filter>
		<Filter

Changes to compat/zlib/contrib/vstudio/vc9/zlib.rc.

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
30
31
32
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
30
31
32




-
-
+
+













-
+




-
+







#include <windows.h>

#define IDR_VERSION1  1
IDR_VERSION1	VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE
  FILEVERSION	 1, 2, 11, 0
  PRODUCTVERSION 1, 2, 11, 0
  FILEVERSION	 1, 3, 1, 0
  PRODUCTVERSION 1, 3, 1, 0
  FILEFLAGSMASK	VS_FFI_FILEFLAGSMASK
  FILEFLAGS	0
  FILEOS	VOS_DOS_WINDOWS32
  FILETYPE	VFT_DLL
  FILESUBTYPE	0	// not used
BEGIN
  BLOCK "StringFileInfo"
  BEGIN
    BLOCK "040904E4"
    //language ID = U.S. English, char set = Windows, Multilingual

    BEGIN
      VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
      VALUE "FileVersion",	"1.2.11\0"
      VALUE "FileVersion",	"1.3.1\0"
      VALUE "InternalName",	"zlib\0"
      VALUE "OriginalFilename",	"zlibwapi.dll\0"
      VALUE "ProductName",	"ZLib.DLL\0"
      VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
      VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0"
      VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
    END
  END
  BLOCK "VarFileInfo"
  BEGIN
    VALUE "Translation", 0x0409, 1252
  END
END

Changes to compat/zlib/contrib/vstudio/vc9/zlibstat.vcproj.

43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57







-
+







			/>
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS"
				ExceptionHandling="0"
				RuntimeLibrary="1"
				BufferSecurityCheck="false"
				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
				AssemblerListingLocation="$(IntDir)\"
				ObjectFile="$(IntDir)\"
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
117
118
119
120
121
122
123

124
125
126
127
128
129
130
131







-
+







			<Tool
				Name="VCMIDLTool"
				TargetEnvironment="3"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64"
				ExceptionHandling="0"
				RuntimeLibrary="3"
				BufferSecurityCheck="false"
				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
				AssemblerListingLocation="$(IntDir)\"
				ObjectFile="$(IntDir)\"
191
192
193
194
195
196
197
198

199
200
201
202
203
204
205
191
192
193
194
195
196
197

198
199
200
201
202
203
204
205







-
+







			<Tool
				Name="VCMIDLTool"
				TargetEnvironment="2"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64"
				ExceptionHandling="0"
				RuntimeLibrary="3"
				BufferSecurityCheck="false"
				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
				AssemblerListingLocation="$(IntDir)\"
				ObjectFile="$(IntDir)\"
264
265
266
267
268
269
270
271
272


273
274
275
276
277
278
279
264
265
266
267
268
269
270


271
272
273
274
275
276
277
278
279







-
-
+
+







			/>
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				InlineFunctionExpansion="1"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="0"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
				AssemblerListingLocation="$(IntDir)\"
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
291
292
293
294
295
296
297

298
299
300
301
302
303
304







-







			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLibrarianTool"
				AdditionalOptions="/MACHINE:X86 /NODEFAULTLIB"
				AdditionalDependencies="..\..\masmx86\match686.obj ..\..\masmx86\inffas32.obj "
				OutputFile="$(OutDir)\zlibstat.lib"
				SuppressStartupBanner="true"
			/>
			<Tool
				Name="VCALinkTool"
			/>
			<Tool
339
340
341
342
343
344
345
346
347


348
349
350
351
352
353
354
338
339
340
341
342
343
344


345
346
347
348
349
350
351
352
353







-
-
+
+







			<Tool
				Name="VCMIDLTool"
				TargetEnvironment="3"
			/>
			<Tool
				Name="VCCLCompilerTool"
				InlineFunctionExpansion="1"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				PreprocessorDefinitions="ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
				AssemblerListingLocation="$(IntDir)\"
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
365
366
367
368
369
370
371

372
373
374
375
376
377
378







-







			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLibrarianTool"
				AdditionalOptions="/MACHINE:AMD64 /NODEFAULTLIB"
				AdditionalDependencies="..\..\masmx64\gvmat64.obj ..\..\masmx64\inffasx64.obj "
				OutputFile="$(OutDir)\zlibstat.lib"
				SuppressStartupBanner="true"
			/>
			<Tool
				Name="VCALinkTool"
			/>
			<Tool
414
415
416
417
418
419
420
421

422
423
424
425
426
427
428
412
413
414
415
416
417
418

419
420
421
422
423
424
425
426







-
+







			<Tool
				Name="VCMIDLTool"
				TargetEnvironment="2"
			/>
			<Tool
				Name="VCCLCompilerTool"
				InlineFunctionExpansion="1"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
487
488
489
490
491
492
493
494

495
496
497
498
499
500
501
485
486
487
488
489
490
491

492
493
494
495
496
497
498
499







-
+







			/>
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				InlineFunctionExpansion="1"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="0"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
561
562
563
564
565
566
567
568

569
570
571
572
573
574
575
559
560
561
562
563
564
565

566
567
568
569
570
571
572
573







-
+







			<Tool
				Name="VCMIDLTool"
				TargetEnvironment="3"
			/>
			<Tool
				Name="VCCLCompilerTool"
				InlineFunctionExpansion="1"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
635
636
637
638
639
640
641
642

643
644
645
646
647
648
649
633
634
635
636
637
638
639

640
641
642
643
644
645
646
647







-
+







			<Tool
				Name="VCMIDLTool"
				TargetEnvironment="2"
			/>
			<Tool
				Name="VCCLCompilerTool"
				InlineFunctionExpansion="1"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
727
728
729
730
731
732
733




















































734
735
736
737
738
739
740







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







				>
			</File>
			<File
				RelativePath="..\..\..\infback.c"
				>
			</File>
			<File
				RelativePath="..\..\masmx64\inffas8664.c"
				>
				<FileConfiguration
					Name="Debug|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Debug|Itanium"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Release|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Release|Itanium"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="ReleaseWithoutAsm|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="ReleaseWithoutAsm|Itanium"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
			</File>
			<File
				RelativePath="..\..\..\inffast.c"
				>
			</File>
			<File
				RelativePath="..\..\..\inflate.c"
				>
			</File>

Changes to compat/zlib/contrib/vstudio/vc9/zlibvc.def.

1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







LIBRARY
; zlib data compression and ZIP file I/O library

VERSION		1.2
VERSION		1.3.1

EXPORTS
        adler32                                  @1
        compress                                 @2
        crc32                                    @3
        deflate                                  @4
        deflateCopy                              @5
147
148
149
150
151
152
153





147
148
149
150
151
152
153
154
155
156
157
158







+
+
+
+
+
        inflateValidate                         @169
        uncompress2                             @170
        gzfread                                 @171
        gzfwrite                                @172
        deflateGetDictionary                    @173
        adler32_z                               @174
        crc32_z                                 @175

; zlib1 v1.2.12 added:
		crc32_combine_gen						@176
		crc32_combine_gen64						@177
		crc32_combine_op						@178

Changes to compat/zlib/contrib/vstudio/vc9/zlibvc.sln.

Changes to compat/zlib/contrib/vstudio/vc9/zlibvc.vcproj.

49
50
51
52
53
54
55
56
57


58
59
60
61
62
63
64
49
50
51
52
53
54
55


56
57
58
59
60
61
62
63
64







-
-
+
+







				SuppressStartupBanner="true"
				TargetEnvironment="1"
				TypeLibraryName="$(OutDir)/zlibvc.tlb"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI"
				ExceptionHandling="0"
				RuntimeLibrary="1"
				BufferSecurityCheck="false"
				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
				AssemblerListingLocation="$(IntDir)\"
				ObjectFile="$(IntDir)\"
				ProgramDataBaseFileName="$(OutDir)\"
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
77
78
79
80
81
82
83

84
85
86
87
88
89
90







-







			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				AdditionalOptions="/MACHINE:I386"
				AdditionalDependencies="..\..\masmx86\match686.obj ..\..\masmx86\inffas32.obj"
				OutputFile="$(OutDir)\zlibwapi.dll"
				LinkIncremental="2"
				SuppressStartupBanner="true"
				GenerateManifest="false"
				ModuleDefinitionFile=".\zlibvc.def"
				GenerateDebugInformation="true"
				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
146
147
148
149
150
151
152
153
154


155
156
157
158
159
160
161
145
146
147
148
149
150
151


152
153
154
155
156
157
158
159
160







-
-
+
+







				SuppressStartupBanner="true"
				TargetEnvironment="3"
				TypeLibraryName="$(OutDir)/zlibvc.tlb"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64"
				ExceptionHandling="0"
				RuntimeLibrary="3"
				BufferSecurityCheck="false"
				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
				AssemblerListingLocation="$(IntDir)\"
				ObjectFile="$(IntDir)\"
				ProgramDataBaseFileName="$(OutDir)\"
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
172
173
174
175
176
177
178

179
180
181
182
183
184
185







-







				Culture="1036"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				AdditionalDependencies="..\..\masmx64\gvmat64.obj ..\..\masmx64\inffasx64.obj "
				OutputFile="$(OutDir)\zlibwapi.dll"
				LinkIncremental="2"
				SuppressStartupBanner="true"
				GenerateManifest="false"
				ModuleDefinitionFile=".\zlibvc.def"
				GenerateDebugInformation="true"
				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
241
242
243
244
245
246
247
248

249
250
251
252
253
254
255
239
240
241
242
243
244
245

246
247
248
249
250
251
252
253







-
+







				SuppressStartupBanner="true"
				TargetEnvironment="2"
				TypeLibraryName="$(OutDir)/zlibvc.tlb"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64"
				ExceptionHandling="0"
				RuntimeLibrary="3"
				BufferSecurityCheck="false"
				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
				AssemblerListingLocation="$(IntDir)\"
				ObjectFile="$(IntDir)\"
336
337
338
339
340
341
342
343

344
345
346
347
348
349
350
334
335
336
337
338
339
340

341
342
343
344
345
346
347
348







-
+







				SuppressStartupBanner="true"
				TargetEnvironment="1"
				TypeLibraryName="$(OutDir)/zlibvc.tlb"
			/>
			<Tool
				Name="VCCLCompilerTool"
				InlineFunctionExpansion="1"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
436
437
438
439
440
441
442
443

444
445
446
447
448
449
450
434
435
436
437
438
439
440

441
442
443
444
445
446
447
448







-
+







				SuppressStartupBanner="true"
				TargetEnvironment="3"
				TypeLibraryName="$(OutDir)/zlibvc.tlb"
			/>
			<Tool
				Name="VCCLCompilerTool"
				InlineFunctionExpansion="1"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
534
535
536
537
538
539
540
541

542
543
544
545
546
547
548
532
533
534
535
536
537
538

539
540
541
542
543
544
545
546







-
+







				SuppressStartupBanner="true"
				TargetEnvironment="2"
				TypeLibraryName="$(OutDir)/zlibvc.tlb"
			/>
			<Tool
				Name="VCCLCompilerTool"
				InlineFunctionExpansion="1"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
632
633
634
635
636
637
638
639
640


641
642
643
644
645
646
647
630
631
632
633
634
635
636


637
638
639
640
641
642
643
644
645







-
-
+
+







				SuppressStartupBanner="true"
				TargetEnvironment="1"
				TypeLibraryName="$(OutDir)/zlibvc.tlb"
			/>
			<Tool
				Name="VCCLCompilerTool"
				InlineFunctionExpansion="1"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="0"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
				AssemblerOutput="2"
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
660
661
662
663
664
665
666

667
668
669
670
671
672
673







-







			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				AdditionalOptions="/MACHINE:I386"
				AdditionalDependencies="..\..\masmx86\match686.obj ..\..\masmx86\inffas32.obj "
				OutputFile="$(OutDir)\zlibwapi.dll"
				LinkIncremental="1"
				SuppressStartupBanner="true"
				GenerateManifest="false"
				IgnoreAllDefaultLibraries="false"
				ModuleDefinitionFile=".\zlibvc.def"
				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
733
734
735
736
737
738
739
740
741


742
743
744
745
746
747
748
730
731
732
733
734
735
736


737
738
739
740
741
742
743
744
745







-
-
+
+







				SuppressStartupBanner="true"
				TargetEnvironment="3"
				TypeLibraryName="$(OutDir)/zlibvc.tlb"
			/>
			<Tool
				Name="VCCLCompilerTool"
				InlineFunctionExpansion="1"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
				AssemblerOutput="2"
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
759
760
761
762
763
764
765

766
767
768
769
770
771
772







-







				Culture="1036"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				AdditionalDependencies="..\..\masmx64\gvmat64.obj ..\..\masmx64\inffasx64.obj "
				OutputFile="$(OutDir)\zlibwapi.dll"
				LinkIncremental="1"
				SuppressStartupBanner="true"
				GenerateManifest="false"
				IgnoreAllDefaultLibraries="false"
				ModuleDefinitionFile=".\zlibvc.def"
				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
832
833
834
835
836
837
838
839

840
841
842
843
844
845
846
828
829
830
831
832
833
834

835
836
837
838
839
840
841
842







-
+







				SuppressStartupBanner="true"
				TargetEnvironment="2"
				TypeLibraryName="$(OutDir)/zlibvc.tlb"
			/>
			<Tool
				Name="VCCLCompilerTool"
				InlineFunctionExpansion="1"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				AdditionalIncludeDirectories="..\..\.."
				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
946
947
948
949
950
951
952
953
954
955
956
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
942
943
944
945
946
947
948




















































949
950
951
952
953
954
955







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







				>
			</File>
			<File
				RelativePath="..\..\..\infback.c"
				>
			</File>
			<File
				RelativePath="..\..\masmx64\inffas8664.c"
				>
				<FileConfiguration
					Name="Debug|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Debug|Itanium"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="ReleaseWithoutAsm|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="ReleaseWithoutAsm|Itanium"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Release|Win32"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
				<FileConfiguration
					Name="Release|Itanium"
					ExcludedFromBuild="true"
					>
					<Tool
						Name="VCCLCompilerTool"
					/>
				</FileConfiguration>
			</File>
			<File
				RelativePath="..\..\..\inffast.c"
				>
			</File>
			<File
				RelativePath="..\..\..\inflate.c"
				>
			</File>

Changes to compat/zlib/crc32.c.

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
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
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















442
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

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
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
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
467
468
469
470
471
472
473
474
475
476




477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573







574
575
576
577
578
579
580
581
582
583
584
585









586
587
588



589
590
591
592




593
594


595


596
597
598
599

600





601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619

















620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714



715
716



717
718
719
720


721
722




723
724
725
726
727
728
729
730



731
732
733






734
735
736
737
738
739
740
741
742
743
744
745



746
747
748
749
750
751
752
753
754
755
756
757




758
759
760


761
762
763
764
765
766
767
768
769
770
771











772
773
774
775
776
777
778
779
780
781
782
783
784
785









786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812


813


814






815
816
817
818
819
820
821
822
823
824
825
826
827
828
829






830
831
832
833
834







835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861

862
863
864
865
866
867
868
869
870
871
872
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







898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922








923
924
925
926
927
928
929
930






931
932
933
934
935
936
937
938
939


940



941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956






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
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

-
+


-
-
-
+
+
+
-
-







-
+



-
+
+









-
+

+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
-
-
+
+

+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
+
+
+

+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+

-
+

-
+



-
+

-
-
-
-
+
+
+
+

-
-
-
+
+
+
-
-
-
+
-
-
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
+

-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
+
+
-
-
-
+
+
+
+
-
+
+
+
+


-

+
+
+
+
+
+
+
+
+

+
+
+



+
+
+
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
+
+
+
+

-
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+



-
+
+

-
+
-

-
-
+




-
-
-
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-

+
+
-
-
-
+
+
+
+
-
-
-
-
+
+
-
-
+
-
-
+
+
+

-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+

+
+
+
+
+
-
-
-
+
+
+
+
-
-
-
+
+
+
+
+
+
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
-
-
-
+
+
+

-
-
+
+
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
-
+
-
-
-
-
+
+
+
-
-
-
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
+
+
+
-
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
-
-
+
+

+
+
+
+
+
+
+
-
+
+

-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+


+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

/* crc32.c -- compute the CRC-32 of a data stream
 * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler
 * Copyright (C) 1995-2022 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 *
 * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
 * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
 * tables for updating the shift register in one step with three exclusive-ors
 * This interleaved implementation of a CRC makes use of pipelined multiple
 * arithmetic-logic units, commonly found in modern CPU cores. It is due to
 * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution.
 * instead of four steps with four exclusive-ors.  This results in about a
 * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
 */

/* @(#) $Id$ */

/*
  Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
  protection on the static variables used to control the first-use generation
  of the crc tables.  Therefore, if you #define DYNAMIC_CRC_TABLE, you should
  of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
  first call get_crc_table() to initialize the tables before allowing more than
  one thread to use crc32().

  DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h.
  MAKECRCH can be #defined to write out crc32.h. A main() routine is also
  produced, so that this one source file can be compiled to an executable.
 */

#ifdef MAKECRCH
#  include <stdio.h>
#  ifndef DYNAMIC_CRC_TABLE
#    define DYNAMIC_CRC_TABLE
#  endif /* !DYNAMIC_CRC_TABLE */
#endif /* MAKECRCH */

#include "zutil.h"      /* for STDC and FAR definitions */
#include "zutil.h"      /* for Z_U4, Z_U8, z_crc_t, and FAR definitions */

 /*
  A CRC of a message is computed on N braids of words in the message, where
  each word consists of W bytes (4 or 8). If N is 3, for example, then three
  running sparse CRCs are calculated respectively on each braid, at these
  indices in the array of words: 0, 3, 6, ..., 1, 4, 7, ..., and 2, 5, 8, ...
  This is done starting at a word boundary, and continues until as many blocks
  of N * W bytes as are available have been processed. The results are combined
  into a single CRC at the end. For this code, N must be in the range 1..6 and
  W must be 4 or 8. The upper limit on N can be increased if desired by adding
  more #if blocks, extending the patterns apparent in the code. In addition,
  crc32.h would need to be regenerated, if the maximum N value is increased.
/* Definitions for doing the crc four data bytes at a time. */
#if !defined(NOBYFOUR) && defined(Z_U4)
#  define BYFOUR

  N and W are chosen empirically by benchmarking the execution time on a given
  processor. The choices for N and W below were based on testing on Intel Kaby
  Lake i7, AMD Ryzen 7, ARM Cortex-A57, Sparc64-VII, PowerPC POWER9, and MIPS64
  Octeon II processors. The Intel, AMD, and ARM processors were all fastest
  with N=5, W=8. The Sparc, PowerPC, and MIPS64 were all fastest at N=5, W=4.
  They were all tested with either gcc or clang, all using the -O3 optimization
  level. Your mileage may vary.
 */

/* Define N */
#ifdef Z_TESTN
#  define N Z_TESTN
#else
#  define N 5
#endif
#if N < 1 || N > 6
#  error N must be in 1..6
#endif

/*
  z_crc_t must be at least 32 bits. z_word_t must be at least as long as
  z_crc_t. It is assumed here that z_word_t is either 32 bits or 64 bits, and
  that bytes are eight bits.
 */

/*
  Define W and the associated z_word_t type. If W is not defined, then a
  braided calculation is not used, and the associated tables and code are not
  compiled.
 */
#ifdef Z_TESTW
#  if Z_TESTW-1 != -1
#    define W Z_TESTW
#  endif
#else
#  ifdef MAKECRCH
#    define W 8         /* required for MAKECRCH */
#  else
#    if defined(__x86_64__) || defined(__aarch64__)
#      define W 8
#    else
#      define W 4
#    endif
#  endif
#endif
#ifdef BYFOUR
   local unsigned long crc32_little OF((unsigned long,
                        const unsigned char FAR *, z_size_t));
   local unsigned long crc32_big OF((unsigned long,
#ifdef W
#  if W == 8 && defined(Z_U8)
     typedef Z_U8 z_word_t;
#  elif defined(Z_U4)
#    undef W
#    define W 4
     typedef Z_U4 z_word_t;
#  else
#    undef W
#  endif
#endif

                        const unsigned char FAR *, z_size_t));
#  define TBLS 8
/* If available, use the ARM processor CRC32 instruction. */
#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8
#  define ARMCRC32
#endif

#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE))
/*
  Swap the bytes in a z_word_t to convert between little and big endian. Any
  self-respecting compiler will optimize this to a single machine byte-swap
  instruction, if one is available. This assumes that word_t is either 32 bits
  or 64 bits.
 */
local z_word_t byte_swap(z_word_t word) {
#  if W == 8
    return
        (word & 0xff00000000000000) >> 56 |
        (word & 0xff000000000000) >> 40 |
        (word & 0xff0000000000) >> 24 |
        (word & 0xff00000000) >> 8 |
        (word & 0xff000000) << 8 |
        (word & 0xff0000) << 24 |
        (word & 0xff00) << 40 |
        (word & 0xff) << 56;
#  else   /* W == 4 */
    return
        (word & 0xff000000) >> 24 |
        (word & 0xff0000) >> 8 |
        (word & 0xff00) << 8 |
        (word & 0xff) << 24;
#  endif
}
#endif

#ifdef DYNAMIC_CRC_TABLE
/* =========================================================================
 * Table of powers of x for combining CRC-32s, filled in by make_crc_table()
 * below.
 */
   local z_crc_t FAR x2n_table[32];
#else
/* =========================================================================
 * Tables for byte-wise and braided CRC-32 calculations, and a table of powers
 * of x for combining CRC-32s, all made by make_crc_table().
 */
#  define TBLS 1
#endif /* BYFOUR */
#  include "crc32.h"
#endif

/* CRC polynomial. */
#define POLY 0xedb88320         /* p(x) reflected, with x^32 implied */
/* Local functions for crc concatenation */
local unsigned long gf2_matrix_times OF((unsigned long *mat,
                                         unsigned long vec));
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));



/*
  Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial,
  reflected. For speed, this requires that a not be zero.
 */
local z_crc_t multmodp(z_crc_t a, z_crc_t b) {
    z_crc_t m, p;

    m = (z_crc_t)1 << 31;
    p = 0;
    for (;;) {
        if (a & m) {
            p ^= b;
            if ((a & (m - 1)) == 0)
                break;
        }
        m >>= 1;
        b = b & 1 ? (b >> 1) ^ POLY : b >> 1;
    }
    return p;
}

/*
  Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been
  initialized.
 */
local z_crc_t x2nmodp(z_off64_t n, unsigned k) {
    z_crc_t p;

    p = (z_crc_t)1 << 31;           /* x^0 == 1 */
    while (n) {
        if (n & 1)
            p = multmodp(x2n_table[k & 31], p);
        n >>= 1;
        k++;
    }
    return p;
}

#ifdef DYNAMIC_CRC_TABLE

local volatile int crc_table_empty = 1;
local z_crc_t FAR crc_table[TBLS][256];
local void make_crc_table OF((void));
/* =========================================================================
 * Build the tables for byte-wise and braided CRC-32 calculations, and a table
 * of powers of x for combining CRC-32s.
 */
local z_crc_t FAR crc_table[256];
#ifdef W
   local z_word_t FAR crc_big_table[256];
   local z_crc_t FAR crc_braid_table[W][256];
   local z_word_t FAR crc_braid_big_table[W][256];
   local void braid(z_crc_t [][256], z_word_t [][256], int, int);
#endif
#ifdef MAKECRCH
   local void write_table OF((FILE *, const z_crc_t FAR *));
   local void write_table(FILE *, const z_crc_t FAR *, int);
   local void write_table32hi(FILE *, const z_word_t FAR *, int);
   local void write_table64(FILE *, const z_word_t FAR *, int);
#endif /* MAKECRCH */

/*
  Define a once() function depending on the availability of atomics. If this is
  compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in
  multiple threads, and if atomics are not available, then get_crc_table() must
  be called to initialize the tables and must return before any threads are
  allowed to compute or combine CRCs.
 */

/* Definition of once functionality. */
typedef struct once_s once_t;

/* Check for the availability of atomics. */
#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \
    !defined(__STDC_NO_ATOMICS__)

#include <stdatomic.h>

/* Structure for once(), which must be initialized with ONCE_INIT. */
struct once_s {
    atomic_flag begun;
    atomic_int done;
};
#define ONCE_INIT {ATOMIC_FLAG_INIT, 0}

/*
  Run the provided init() function exactly once, even if multiple threads
  invoke once() at the same time. The state must be a once_t initialized with
  ONCE_INIT.
 */
local void once(once_t *state, void (*init)(void)) {
    if (!atomic_load(&state->done)) {
        if (atomic_flag_test_and_set(&state->begun))
            while (!atomic_load(&state->done))
                ;
        else {
            init();
            atomic_store(&state->done, 1);
        }
    }
}

#else   /* no atomics */

/* Structure for once(), which must be initialized with ONCE_INIT. */
struct once_s {
    volatile int begun;
    volatile int done;
};
#define ONCE_INIT {0, 0}

/* Test and set. Alas, not atomic, but tries to minimize the period of
   vulnerability. */
local int test_and_set(int volatile *flag) {
    int was;

    was = *flag;
    *flag = 1;
    return was;
}

/* Run the provided init() function once. This is not thread-safe. */
local void once(once_t *state, void (*init)(void)) {
    if (!state->done) {
        if (test_and_set(&state->begun))
            while (!state->done)
                ;
        else {
            init();
            state->done = 1;
        }
    }
}

#endif

/* State for once(). */
local once_t made = ONCE_INIT;

/*
  Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.

  Polynomials over GF(2) are represented in binary, one bit per coefficient,
  with the lowest powers in the most significant bit.  Then adding polynomials
  with the lowest powers in the most significant bit. Then adding polynomials
  is just exclusive-or, and multiplying a polynomial by x is a right shift by
  one.  If we call the above polynomial p, and represent a byte as the
  one. If we call the above polynomial p, and represent a byte as the
  polynomial q, also with the lowest power in the most significant bit (so the
  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
  byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p,
  where a mod b means the remainder after dividing a by b.

  This calculation is done using the shift-register method of multiplying and
  taking the remainder.  The register is initialized to zero, and for each
  taking the remainder. The register is initialized to zero, and for each
  incoming bit, x^32 is added mod p to the register if the bit is a one (where
  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
  x (which is shifting right by one and adding x^32 mod p if the bit shifted
  out is a one).  We start with the highest power (least significant bit) of
  q and repeat for all eight bits of q.
  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x
  (which is shifting right by one and adding x^32 mod p if the bit shifted out
  is a one). We start with the highest power (least significant bit) of q and
  repeat for all eight bits of q.

  The first table is simply the CRC of all possible eight bit values.  This is
  all the information needed to generate CRCs on data a byte at a time for all
  combinations of CRC register values and incoming bytes.  The remaining tables
  The table is simply the CRC of all possible eight bit values. This is all the
  information needed to generate CRCs on data a byte at a time for all
  combinations of CRC register values and incoming bytes.
  allow for word-at-a-time CRC calculation for both big-endian and little-
  endian machines, where a word is four bytes.
*/
 */
local void make_crc_table()
{

    z_crc_t c;
    int n, k;
    z_crc_t poly;                       /* polynomial exclusive-or pattern */
    /* terms of polynomial defining this crc (except x^32): */
    static volatile int first = 1;      /* flag to limit concurrent making */
    static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};

local void make_crc_table(void) {
    /* See if another task is already doing this (not thread-safe, but better
       than nothing -- significantly reduces duration of vulnerability in
       case the advice about DYNAMIC_CRC_TABLE is ignored) */
    if (first) {
        first = 0;

    unsigned i, j, n;
        /* make exclusive-or pattern from polynomial (0xedb88320UL) */
        poly = 0;
        for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
            poly |= (z_crc_t)1 << (31 - p[n]);
    z_crc_t p;

        /* generate a crc for every 8-bit value */
        for (n = 0; n < 256; n++) {
            c = (z_crc_t)n;
            for (k = 0; k < 8; k++)
                c = c & 1 ? poly ^ (c >> 1) : c >> 1;
            crc_table[0][n] = c;
    /* initialize the CRC of bytes tables */
    for (i = 0; i < 256; i++) {
        p = i;
        for (j = 0; j < 8; j++)
            p = p & 1 ? (p >> 1) ^ POLY : p >> 1;
        crc_table[i] = p;
        }

#ifdef BYFOUR
#ifdef W
        /* generate crc for each value followed by one, two, and three zeros,
           and then the byte reversal of those as well as the first table */
        for (n = 0; n < 256; n++) {
            c = crc_table[0][n];
        crc_big_table[i] = byte_swap(p);
            crc_table[4][n] = ZSWAP32(c);
            for (k = 1; k < 4; k++) {
                c = crc_table[0][c & 0xff] ^ (c >> 8);
                crc_table[k][n] = c;
                crc_table[k + 4][n] = ZSWAP32(c);
            }
        }
#endif /* BYFOUR */

#endif
    }
        crc_table_empty = 0;
    }
    else {      /* not first */

    /* initialize the x^2^n mod p(x) table */
    p = (z_crc_t)1 << 30;         /* x^1 */
        /* wait for the other guy to finish (not efficient, but rare) */
        while (crc_table_empty)
            ;
    x2n_table[0] = p;
    for (n = 1; n < 32; n++)
        x2n_table[n] = p = multmodp(p, p);

    }
#ifdef W
    /* initialize the braiding tables -- needs x2n_table[] */
    braid(crc_braid_table, crc_braid_big_table, N, W);
#endif

#ifdef MAKECRCH
    /* write out CRC tables to crc32.h */
    {
        /*
          The crc32.h header file contains tables for both 32-bit and 64-bit
          z_word_t's, and so requires a 64-bit type be available. In that case,
          z_word_t must be defined to be 64-bits. This code then also generates
          and writes out the tables for the case that z_word_t is 32 bits.
         */
#if !defined(W) || W != 8
#  error Need a 64-bit integer type in order to generate crc32.h.
#endif
        FILE *out;
        int k, n;
        z_crc_t ltl[8][256];
        z_word_t big[8][256];

        out = fopen("crc32.h", "w");
        if (out == NULL) return;

        /* write out little-endian CRC table to crc32.h */
        fprintf(out,
        fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
        fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
        fprintf(out, "local const z_crc_t FAR ");
            "/* crc32.h -- tables for rapid CRC calculation\n"
            " * Generated automatically by crc32.c\n */\n"
            "\n"
            "local const z_crc_t FAR crc_table[] = {\n"
        fprintf(out, "crc_table[TBLS][256] =\n{\n  {\n");
        write_table(out, crc_table[0]);
#  ifdef BYFOUR
        fprintf(out, "#ifdef BYFOUR\n");
        for (k = 1; k < 8; k++) {
            fprintf(out, "  },\n  {\n");
            write_table(out, crc_table[k]);
        }
        fprintf(out, "#endif\n");
#  endif /* BYFOUR */
        fprintf(out, "  }\n};\n");
            "    ");
        write_table(out, crc_table, 256);
        fprintf(out,
            "};\n");

        /* write out big-endian CRC table for 64-bit z_word_t to crc32.h */
        fprintf(out,
            "\n"
            "#ifdef W\n"
            "\n"
            "#if W == 8\n"
            "\n"
            "local const z_word_t FAR crc_big_table[] = {\n"
            "    ");
        write_table64(out, crc_big_table, 256);
        fprintf(out,
            "};\n");

        /* write out big-endian CRC table for 32-bit z_word_t to crc32.h */
        fprintf(out,
            "\n"
            "#else /* W == 4 */\n"
            "\n"
            "local const z_word_t FAR crc_big_table[] = {\n"
            "    ");
        write_table32hi(out, crc_big_table, 256);
        fprintf(out,
            "};\n"
            "\n"
            "#endif\n");

        /* write out braid tables for each value of N */
        for (n = 1; n <= 6; n++) {
            fprintf(out,
            "\n"
            "#if N == %d\n", n);

            /* compute braid tables for this N and 64-bit word_t */
            braid(ltl, big, n, 8);

            /* write out braid tables for 64-bit z_word_t to crc32.h */
            fprintf(out,
            "\n"
            "#if W == 8\n"
            "\n"
            "local const z_crc_t FAR crc_braid_table[][256] = {\n");
            for (k = 0; k < 8; k++) {
                fprintf(out, "   {");
                write_table(out, ltl[k], 256);
                fprintf(out, "}%s", k < 7 ? ",\n" : "");
            }
            fprintf(out,
            "};\n"
            "\n"
            "local const z_word_t FAR crc_braid_big_table[][256] = {\n");
            for (k = 0; k < 8; k++) {
                fprintf(out, "   {");
                write_table64(out, big[k], 256);
                fprintf(out, "}%s", k < 7 ? ",\n" : "");
            }
            fprintf(out,
            "};\n");

            /* compute braid tables for this N and 32-bit word_t */
            braid(ltl, big, n, 4);

            /* write out braid tables for 32-bit z_word_t to crc32.h */
            fprintf(out,
            "\n"
            "#else /* W == 4 */\n"
            "\n"
            "local const z_crc_t FAR crc_braid_table[][256] = {\n");
            for (k = 0; k < 4; k++) {
                fprintf(out, "   {");
                write_table(out, ltl[k], 256);
                fprintf(out, "}%s", k < 3 ? ",\n" : "");
            }
            fprintf(out,
            "};\n"
            "\n"
            "local const z_word_t FAR crc_braid_big_table[][256] = {\n");
            for (k = 0; k < 4; k++) {
                fprintf(out, "   {");
                write_table32hi(out, big[k], 256);
                fprintf(out, "}%s", k < 3 ? ",\n" : "");
            }
            fprintf(out,
            "};\n"
            "\n"
            "#endif\n"
            "\n"
            "#endif\n");
        }
        fprintf(out,
            "\n"
            "#endif\n");

        /* write out zeros operator table to crc32.h */
        fprintf(out,
            "\n"
            "local const z_crc_t FAR x2n_table[] = {\n"
            "    ");
        write_table(out, x2n_table, 32);
        fprintf(out,
            "};\n");
        fclose(out);
    }
#endif /* MAKECRCH */
}

#ifdef MAKECRCH

/*
   Write the 32-bit values in table[0..k-1] to out, five per line in
   hexadecimal separated by commas.
 */
local void write_table(out, table)
    FILE *out;
    const z_crc_t FAR *table;
{
local void write_table(FILE *out, const z_crc_t FAR *table, int k) {
    int n;

    for (n = 0; n < k; n++)
        fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : "    ",
                (unsigned long)(table[n]),
                n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", "));
}

/*
   Write the high 32-bits of each value in table[0..k-1] to out, five per line
   in hexadecimal separated by commas.
 */
local void write_table32hi(FILE *out, const z_word_t FAR *table, int k) {
    int n;

    for (n = 0; n < 256; n++)
        fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : "    ",
                (unsigned long)(table[n]),
                n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
    for (n = 0; n < k; n++)
        fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : "    ",
                (unsigned long)(table[n] >> 32),
                n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", "));
}
#endif /* MAKECRCH */

/*
  Write the 64-bit values in table[0..k-1] to out, three per line in
  hexadecimal separated by commas. This assumes that if there is a 64-bit
  type, then there is also a long long integer type, and it is at least 64
  bits. If not, then the type cast and format string can be adjusted
  accordingly.
 */
local void write_table64(FILE *out, const z_word_t FAR *table, int k) {
    int n;

    for (n = 0; n < k; n++)
        fprintf(out, "%s0x%016llx%s", n == 0 || n % 3 ? "" : "    ",
                (unsigned long long)(table[n]),
                n == k - 1 ? "" : (n % 3 == 2 ? ",\n" : ", "));
}
#else /* !DYNAMIC_CRC_TABLE */
/* ========================================================================
 * Tables of CRC-32s of all single-byte values, made by make_crc_table().

/* Actually do the deed. */
int main(void) {
    make_crc_table();
    return 0;
}

#endif /* MAKECRCH */

#ifdef W
/*
  Generate the little and big-endian braid tables for the given n and z_word_t
  size w. Each array must have room for w blocks of 256 elements.
 */
local void braid(z_crc_t ltl[][256], z_word_t big[][256], int n, int w) {
    int k;
    z_crc_t i, p, q;
    for (k = 0; k < w; k++) {
        p = x2nmodp((n * w + 3 - k) << 3, 0);
        ltl[k][0] = 0;
        big[w - 1 - k][0] = 0;
        for (i = 1; i < 256; i++) {
            ltl[k][i] = q = multmodp(i << 24, p);
            big[w - 1 - k][i] = byte_swap(q);
        }
    }
}
#endif
#include "crc32.h"

#endif /* DYNAMIC_CRC_TABLE */

/* =========================================================================
 * This function can be used by asm versions of crc32()
 * This function can be used by asm versions of crc32(), and to force the
 * generation of the CRC tables in a threaded application.
 */
const z_crc_t FAR * ZEXPORT get_crc_table()
const z_crc_t FAR * ZEXPORT get_crc_table(void) {
{
#ifdef DYNAMIC_CRC_TABLE
    if (crc_table_empty)
        make_crc_table();
    once(&made, make_crc_table);
#endif /* DYNAMIC_CRC_TABLE */
    return (const z_crc_t FAR *)crc_table;
}

/* ========================================================================= */
#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
/* =========================================================================
 * Use ARM machine instructions if available. This will compute the CRC about
 * ten times faster than the braided calculation. This code does not check for
 * the presence of the CRC instruction at run time. __ARM_FEATURE_CRC32 will
 * only be defined if the compilation specifies an ARM processor architecture
 * that has the instructions. For example, compiling with -march=armv8.1-a or
 * -march=armv8-a+crc, or -march=native if the compile machine has the crc32
 * instructions.
 */
#ifdef ARMCRC32

/*
   Constants empirically determined to maximize speed. These values are from
   measurements on a Cortex-A57. Your mileage may vary.
 */
#define Z_BATCH 3990                /* number of words in a batch */
#define Z_BATCH_ZEROS 0xa10d3d0c    /* computed from Z_BATCH = 3990 */
#define Z_BATCH_MIN 800             /* fewest words in a final batch */
/* ========================================================================= */
unsigned long ZEXPORT crc32_z(crc, buf, len)
    unsigned long crc;
    const unsigned char FAR *buf;
    z_size_t len;
{
    if (buf == Z_NULL) return 0UL;

unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf,
                              z_size_t len) {
    z_crc_t val;
    z_word_t crc1, crc2;
    const z_word_t *word;
    z_word_t val0, val1, val2;
    z_size_t last, last2, i;
    z_size_t num;

    /* Return initial CRC, if requested. */
    if (buf == Z_NULL) return 0;

#ifdef DYNAMIC_CRC_TABLE
    if (crc_table_empty)
        make_crc_table();
#endif /* DYNAMIC_CRC_TABLE */

#ifdef BYFOUR
    if (sizeof(void *) == sizeof(ptrdiff_t)) {
        z_crc_t endian;

#ifdef DYNAMIC_CRC_TABLE
    once(&made, make_crc_table);
        endian = 1;
        if (*((unsigned char *)(&endian)))
            return crc32_little(crc, buf, len);
#endif /* DYNAMIC_CRC_TABLE */

    /* Pre-condition the CRC */
    crc = (~crc) & 0xffffffff;
        else
            return crc32_big(crc, buf, len);
    }
#endif /* BYFOUR */

    /* Compute the CRC up to a word boundary. */
    crc = crc ^ 0xffffffffUL;
    while (len >= 8) {
    while (len && ((z_size_t)buf & 7) != 0) {
        DO8;
        len -= 8;
        len--;
        val = *buf++;
        __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val));
    }
    if (len) do {

        DO1;
    } while (--len);
    return crc ^ 0xffffffffUL;
}

    /* Prepare to compute the CRC on full 64-bit words word[0..num-1]. */
    word = (z_word_t const *)buf;
    num = len >> 3;
    len &= 7;

    /* Do three interleaved CRCs to realize the throughput of one crc32x
       instruction per cycle. Each CRC is calculated on Z_BATCH words. The
       three CRCs are combined into a single CRC after each set of batches. */
    while (num >= 3 * Z_BATCH) {
        crc1 = 0;
        crc2 = 0;
        for (i = 0; i < Z_BATCH; i++) {
            val0 = word[i];
            val1 = word[i + Z_BATCH];
            val2 = word[i + 2 * Z_BATCH];
            __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
            __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1));
            __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2));
        }
/* ========================================================================= */
unsigned long ZEXPORT crc32(crc, buf, len)
    unsigned long crc;
    const unsigned char FAR *buf;
    uInt len;
{
    return crc32_z(crc, buf, len);
}

#ifdef BYFOUR

/*
   This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit
   integer pointer type. This violates the strict aliasing rule, where a
   compiler can assume, for optimization purposes, that two pointers to
   fundamentally different types won't ever point to the same memory. This can
   manifest as a problem only if one of the pointers is written to. This code
        word += 3 * Z_BATCH;
        num -= 3 * Z_BATCH;
        crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc1;
        crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc2;
    }

    /* Do one last smaller batch with the remaining words, if there are enough
       to pay for the combination of CRCs. */
    last = num / 3;
    if (last >= Z_BATCH_MIN) {
        last2 = last << 1;
        crc1 = 0;
        crc2 = 0;
        for (i = 0; i < last; i++) {
            val0 = word[i];
            val1 = word[i + last];
            val2 = word[i + last2];
            __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
            __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1));
            __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2));
        }
        word += 3 * last;
        num -= 3 * last;
        val = x2nmodp(last, 6);
        crc = multmodp(val, crc) ^ crc1;
        crc = multmodp(val, crc) ^ crc2;
    }

    /* Compute the CRC on any remaining words. */
    for (i = 0; i < num; i++) {
        val0 = word[i];
        __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
    }
    word += num;

    /* Complete the CRC on any remaining bytes. */
    buf = (const unsigned char FAR *)word;
    while (len) {
        len--;
        val = *buf++;
        __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val));
    }

    /* Return the CRC, post-conditioned. */
    return crc ^ 0xffffffff;
}

#else

#ifdef W

   only reads from those pointers. So long as this code remains isolated in
   this compilation unit, there won't be a problem. For this reason, this code
   should not be copied and pasted into a compilation unit in which other code
   writes to the buffer that is passed to these routines.
/*
  Return the CRC of the W bytes in the word_t data, taking the
  least-significant byte of the word as the first byte of data, without any pre
  or post conditioning. This is used to combine the CRCs of each braid.
 */
local z_crc_t crc_word(z_word_t data) {
    int k;
    for (k = 0; k < W; k++)
        data = (data >> 8) ^ crc_table[data & 0xff];
    return (z_crc_t)data;

/* ========================================================================= */
#define DOLIT4 c ^= *buf4++; \
}

local z_word_t crc_word_big(z_word_t data) {
    int k;
        c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
            crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
    for (k = 0; k < W; k++)
        data = (data << 8) ^
            crc_big_table[(data >> ((W - 1) << 3)) & 0xff];
    return data;
}

#endif

/* ========================================================================= */
local unsigned long crc32_little(crc, buf, len)
    unsigned long crc;
    const unsigned char FAR *buf;
    z_size_t len;
{
    register z_crc_t c;
    register const z_crc_t FAR *buf4;
unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf,
                              z_size_t len) {
    /* Return initial CRC, if requested. */
    if (buf == Z_NULL) return 0;

#ifdef DYNAMIC_CRC_TABLE
    once(&made, make_crc_table);
#endif /* DYNAMIC_CRC_TABLE */

    /* Pre-condition the CRC */
    crc = (~crc) & 0xffffffff;

#ifdef W

    /* If provided enough bytes, do a braided CRC calculation. */
    if (len >= N * W + W - 1) {
        z_size_t blks;
        z_word_t const *words;
        unsigned endian;
        int k;

    c = (z_crc_t)crc;
    c = ~c;
    while (len && ((ptrdiff_t)buf & 3)) {
        /* Compute the CRC up to a z_word_t boundary. */
        while (len && ((z_size_t)buf & (W - 1)) != 0) {
        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
        len--;
    }
            len--;
            crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
        }

    buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
    while (len >= 32) {
        /* Compute the CRC on as many N z_word_t blocks as are available. */
        blks = len / (N * W);
        DOLIT32;
        len -= 32;
    }
    while (len >= 4) {
        len -= blks * N * W;
        words = (z_word_t const *)buf;

        /* Do endian check at execution time instead of compile time, since ARM
           processors can change the endianness at execution time. If the
           compiler knows what the endianness will be, it can optimize out the
           check and the unused branch. */
        endian = 1;
        DOLIT4;
        len -= 4;
    }
        if (*(unsigned char *)&endian) {
            /* Little endian. */

    buf = (const unsigned char FAR *)buf4;

    if (len) do {
        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
    } while (--len);
    c = ~c;
            z_crc_t crc0;
            z_word_t word0;
#if N > 1
            z_crc_t crc1;
            z_word_t word1;
#if N > 2
            z_crc_t crc2;
            z_word_t word2;
#if N > 3
            z_crc_t crc3;
            z_word_t word3;
#if N > 4
    return (unsigned long)c;
}

            z_crc_t crc4;
            z_word_t word4;
#if N > 5
            z_crc_t crc5;
            z_word_t word5;
#endif
#endif
#endif
#endif
#endif

            /* Initialize the CRC for each braid. */
/* ========================================================================= */
#define DOBIG4 c ^= *buf4++; \
        c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
            crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
            crc0 = crc;
#if N > 1
            crc1 = 0;
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4

#if N > 2
            crc2 = 0;
#if N > 3
            crc3 = 0;
#if N > 4
            crc4 = 0;
#if N > 5
            crc5 = 0;
#endif
#endif
#endif
/* ========================================================================= */
local unsigned long crc32_big(crc, buf, len)
    unsigned long crc;
    const unsigned char FAR *buf;
    z_size_t len;
{
    register z_crc_t c;
    register const z_crc_t FAR *buf4;

    c = ZSWAP32((z_crc_t)crc);
    c = ~c;
#endif
#endif

            /*
              Process the first blks-1 blocks, computing the CRCs on each braid
              independently.
             */
            while (--blks) {
                /* Load the word for each braid into registers. */
                word0 = crc0 ^ words[0];
#if N > 1
                word1 = crc1 ^ words[1];
#if N > 2
                word2 = crc2 ^ words[2];
    while (len && ((ptrdiff_t)buf & 3)) {
        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
        len--;
    }

    buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
    while (len >= 32) {
        DOBIG32;
        len -= 32;
#if N > 3
                word3 = crc3 ^ words[3];
#if N > 4
                word4 = crc4 ^ words[4];
#if N > 5
                word5 = crc5 ^ words[5];
#endif
#endif
#endif
#endif
#endif
                words += N;

                /* Compute and update the CRC for each word. The loop should
                   get unrolled. */
                crc0 = crc_braid_table[0][word0 & 0xff];
#if N > 1
                crc1 = crc_braid_table[0][word1 & 0xff];
#if N > 2
                crc2 = crc_braid_table[0][word2 & 0xff];
#if N > 3
                crc3 = crc_braid_table[0][word3 & 0xff];
#if N > 4
                crc4 = crc_braid_table[0][word4 & 0xff];
#if N > 5
                crc5 = crc_braid_table[0][word5 & 0xff];
#endif
    }
    while (len >= 4) {
#endif
        DOBIG4;
        len -= 4;
#endif
    }
    buf = (const unsigned char FAR *)buf4;

    if (len) do {
        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
    } while (--len);
#endif
#endif
                for (k = 1; k < W; k++) {
                    crc0 ^= crc_braid_table[k][(word0 >> (k << 3)) & 0xff];
#if N > 1
                    crc1 ^= crc_braid_table[k][(word1 >> (k << 3)) & 0xff];
#if N > 2
                    crc2 ^= crc_braid_table[k][(word2 >> (k << 3)) & 0xff];
#if N > 3
                    crc3 ^= crc_braid_table[k][(word3 >> (k << 3)) & 0xff];
#if N > 4
                    crc4 ^= crc_braid_table[k][(word4 >> (k << 3)) & 0xff];
#if N > 5
                    crc5 ^= crc_braid_table[k][(word5 >> (k << 3)) & 0xff];
#endif
    c = ~c;
    return (unsigned long)(ZSWAP32(c));
}

#endif /* BYFOUR */

#endif
#endif
#endif
#endif
                }
#define GF2_DIM 32      /* dimension of GF(2) vectors (length of CRC) */

/* ========================================================================= */
local unsigned long gf2_matrix_times(mat, vec)
    unsigned long *mat;
    unsigned long vec;
{
            }

            /*
              Process the last block, combining the CRCs of the N braids at the
              same time.
             */
            crc = crc_word(crc0 ^ words[0]);
#if N > 1
            crc = crc_word(crc1 ^ words[1] ^ crc);
#if N > 2
            crc = crc_word(crc2 ^ words[2] ^ crc);
#if N > 3
            crc = crc_word(crc3 ^ words[3] ^ crc);
#if N > 4
            crc = crc_word(crc4 ^ words[4] ^ crc);
#if N > 5
            crc = crc_word(crc5 ^ words[5] ^ crc);
#endif
#endif
#endif
#endif
#endif
            words += N;
        }
        else {
            /* Big endian. */

    unsigned long sum;
            z_word_t crc0, word0, comb;
#if N > 1
            z_word_t crc1, word1;
#if N > 2
            z_word_t crc2, word2;
#if N > 3
            z_word_t crc3, word3;
#if N > 4
            z_word_t crc4, word4;
#if N > 5
            z_word_t crc5, word5;
#endif
#endif
#endif
#endif
#endif

            /* Initialize the CRC for each braid. */
            crc0 = byte_swap(crc);
#if N > 1
    sum = 0;
            crc1 = 0;
    while (vec) {
        if (vec & 1)
            sum ^= *mat;
        vec >>= 1;
#if N > 2
            crc2 = 0;
#if N > 3
        mat++;
    }
    return sum;
            crc3 = 0;
#if N > 4
            crc4 = 0;
#if N > 5
            crc5 = 0;
#endif
}

#endif
/* ========================================================================= */
local void gf2_matrix_square(square, mat)
    unsigned long *square;
    unsigned long *mat;
{
    int n;

    for (n = 0; n < GF2_DIM; n++)
#endif
#endif
#endif
        square[n] = gf2_matrix_times(mat, mat[n]);
}


            /*
/* ========================================================================= */
local uLong crc32_combine_(crc1, crc2, len2)
    uLong crc1;
    uLong crc2;
    z_off64_t len2;
{
    int n;
              Process the first blks-1 blocks, computing the CRCs on each braid
              independently.
             */
            while (--blks) {
                /* Load the word for each braid into registers. */
                word0 = crc0 ^ words[0];
#if N > 1
                word1 = crc1 ^ words[1];
#if N > 2
                word2 = crc2 ^ words[2];
#if N > 3
                word3 = crc3 ^ words[3];
#if N > 4
                word4 = crc4 ^ words[4];
#if N > 5
                word5 = crc5 ^ words[5];
#endif
#endif
#endif
#endif
#endif
                words += N;

                /* Compute and update the CRC for each word. The loop should
                   get unrolled. */
    unsigned long row;
    unsigned long even[GF2_DIM];    /* even-power-of-two zeros operator */
    unsigned long odd[GF2_DIM];     /* odd-power-of-two zeros operator */

    /* degenerate case (also disallow negative lengths) */
    if (len2 <= 0)
        return crc1;

                crc0 = crc_braid_big_table[0][word0 & 0xff];
#if N > 1
                crc1 = crc_braid_big_table[0][word1 & 0xff];
#if N > 2
                crc2 = crc_braid_big_table[0][word2 & 0xff];
#if N > 3
                crc3 = crc_braid_big_table[0][word3 & 0xff];
#if N > 4
    /* put operator for one zero bit in odd */
    odd[0] = 0xedb88320UL;          /* CRC-32 polynomial */
    row = 1;
    for (n = 1; n < GF2_DIM; n++) {
        odd[n] = row;
        row <<= 1;
                crc4 = crc_braid_big_table[0][word4 & 0xff];
#if N > 5
                crc5 = crc_braid_big_table[0][word5 & 0xff];
#endif
#endif
#endif
#endif
#endif
                for (k = 1; k < W; k++) {
    }

                    crc0 ^= crc_braid_big_table[k][(word0 >> (k << 3)) & 0xff];
    /* put operator for two zero bits in even */
    gf2_matrix_square(even, odd);

#if N > 1
                    crc1 ^= crc_braid_big_table[k][(word1 >> (k << 3)) & 0xff];
#if N > 2
                    crc2 ^= crc_braid_big_table[k][(word2 >> (k << 3)) & 0xff];
#if N > 3
                    crc3 ^= crc_braid_big_table[k][(word3 >> (k << 3)) & 0xff];
#if N > 4
                    crc4 ^= crc_braid_big_table[k][(word4 >> (k << 3)) & 0xff];
#if N > 5
                    crc5 ^= crc_braid_big_table[k][(word5 >> (k << 3)) & 0xff];
#endif
#endif
#endif
#endif
#endif
                }
    /* put operator for four zero bits in odd */
    gf2_matrix_square(odd, even);

    /* apply len2 zeros to crc1 (first square will put the operator for one
       zero byte, eight zero bits, in even) */
    do {
            }

            /*
              Process the last block, combining the CRCs of the N braids at the
              same time.
             */
            comb = crc_word_big(crc0 ^ words[0]);
#if N > 1
            comb = crc_word_big(crc1 ^ words[1] ^ comb);
#if N > 2
            comb = crc_word_big(crc2 ^ words[2] ^ comb);
#if N > 3
            comb = crc_word_big(crc3 ^ words[3] ^ comb);
#if N > 4
            comb = crc_word_big(crc4 ^ words[4] ^ comb);
#if N > 5
            comb = crc_word_big(crc5 ^ words[5] ^ comb);
#endif
        /* apply zeros operator for this bit of len2 */
        gf2_matrix_square(even, odd);
        if (len2 & 1)
            crc1 = gf2_matrix_times(even, crc1);
        len2 >>= 1;

        /* if no more bits set, then done */
#endif
#endif
#endif
#endif
            words += N;
            crc = byte_swap(comb);
        }

        if (len2 == 0)
            break;

        /* another iteration of the loop with odd and even swapped */
        gf2_matrix_square(odd, even);
        if (len2 & 1)
        /*
          Update the pointer to the remaining bytes to process.
         */
        buf = (unsigned char const *)words;
    }

#endif /* W */

    /* Complete the computation of the CRC on any remaining bytes. */
    while (len >= 8) {
            crc1 = gf2_matrix_times(odd, crc1);
        len2 >>= 1;

        len -= 8;
        crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
        crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
        crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
        crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
        crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
        crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
        crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
        crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
    }
        /* if no more bits set, then done */
    } while (len2 != 0);

    /* return combined crc */
    while (len) {
        len--;
        crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
    }

    crc1 ^= crc2;
    return crc1;
    /* Return the CRC, post-conditioned. */
    return crc ^ 0xffffffff;
}

#endif

/* ========================================================================= */
unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf,
                            uInt len) {
    return crc32_z(crc, buf, len);

}

/* ========================================================================= */
uLong ZEXPORT crc32_combine(crc1, crc2, len2)
    uLong crc1;
    uLong crc2;
uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2) {
#ifdef DYNAMIC_CRC_TABLE
    once(&made, make_crc_table);
#endif /* DYNAMIC_CRC_TABLE */
    return multmodp(x2nmodp(len2, 3), crc1) ^ (crc2 & 0xffffffff);
    z_off_t len2;
{
    return crc32_combine_(crc1, crc2, len2);
}

/* ========================================================================= */
uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2) {
    return crc32_combine64(crc1, crc2, (z_off64_t)len2);
}

/* ========================================================================= */
uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
    uLong crc1;
    uLong crc2;
    z_off64_t len2;
{
    return crc32_combine_(crc1, crc2, len2);
uLong ZEXPORT crc32_combine_gen64(z_off64_t len2) {
#ifdef DYNAMIC_CRC_TABLE
    once(&made, make_crc_table);
#endif /* DYNAMIC_CRC_TABLE */
    return x2nmodp(len2, 3);
}

/* ========================================================================= */
uLong ZEXPORT crc32_combine_gen(z_off_t len2) {
    return crc32_combine_gen64((z_off64_t)len2);
}

/* ========================================================================= */
uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op) {
    return multmodp(op, crc1) ^ (crc2 & 0xffffffff);
}

Changes to compat/zlib/crc32.h.

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
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
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









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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427


2428




















































2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
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
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549














































































































3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
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
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
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
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
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938




















































5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
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
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
7079
7080
7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091
7092
7093
7094
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213


7214






















































7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468
7469
7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499
7500
7501
7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520
7521
7522
7523
7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537
7538
7539
7540
7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647
7648
7649
7650
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692
7693
7694
7695
7696
7697
7698
7699
7700
7701
7702
7703
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952
7953
7954
7955
7956
7957
7958
7959
7960
7961
7962
7963
7964
7965
7966
7967
7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999
8000
8001
8002
8003
8004
8005
8006
8007
8008
8009
8010
8011
8012
8013
8014
8015
8016
8017
8018
8019
8020
8021
8022
8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047
8048
8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
8077
8078
8079
8080
8081
8082
8083
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
8148
8149
8150
8151
8152
8153
8154
8155
8156
8157
8158
8159
8160
8161
8162
8163
8164
8165
8166
8167
8168
8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
8193
8194
8195
8196
8197
8198
8199
8200
8201
8202
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
8233
8234
8235
8236
8237
8238
8239
8240
8241
8242
8243
8244
8245
8246
8247
8248
8249
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260
8261
8262
8263
8264
8265
8266
8267
8268
8269
8270
8271
8272
8273
8274
8275
8276
8277
8278
8279
8280
8281
8282
8283
8284
8285
8286
8287
8288
8289
8290
8291
8292
8293
8294
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316
8317
8318
8319
8320
8321
8322



















































8323
8324
8325
8326
8327
8328
8329
8330
8331
8332
8333
8334
8335
8336
8337
8338
8339
8340
8341
8342
8343
8344
8345
8346
8347
8348
8349
8350
8351
8352
8353
8354
8355
8356
8357
8358
8359
8360
8361
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371
8372
8373
8374
8375
8376
8377
8378
8379
8380
8381
8382
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414
8415
8416
8417
8418
8419
8420
8421
8422
8423
8424
8425
8426
8427
8428
8429
8430
8431
8432
8433
8434
8435
8436
8437
8438
8439
8440
8441
8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452
8453
8454
8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487
8488
8489
8490
8491
8492
8493
8494
8495
8496
8497
8498
8499
8500
8501
8502
8503
8504
8505
8506
8507
8508
8509
8510
8511
8512
8513
8514
8515
8516
8517
8518
8519
8520
8521
8522
8523
8524
8525
8526
8527
8528
8529
8530
8531
8532
8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544
8545
8546
8547
8548
8549
8550
8551
8552
8553
8554
8555
8556
8557
8558
8559
8560
8561
8562
8563
8564
8565
8566
8567
8568
8569
8570
8571
8572
8573
8574
8575
8576
8577
8578
8579
8580
8581
8582
8583
8584
8585
8586
8587
8588
8589
8590
8591
8592
8593
8594
8595
8596
8597
8598
8599
8600
8601
8602
8603
8604
8605
8606
8607
8608
8609
8610
8611
8612
8613
8614
8615
8616
8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628
8629
8630
8631
8632
8633
8634
8635
8636
8637
8638
8639
8640
8641
8642
8643
8644
8645
8646
8647
8648
8649
8650
8651
8652
8653
8654
8655
8656
8657
8658
8659
8660
8661
8662
8663
8664
8665
8666
8667
8668
8669
8670
8671
8672
8673
8674
8675
8676
8677
8678
8679
8680
8681
8682
8683
8684
8685
8686
8687
8688
8689
8690
8691
8692
8693
8694
8695
8696
8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707
8708
8709
8710
8711
8712
8713
8714
8715
8716
8717
8718
8719
8720
8721
8722
8723
8724
8725
8726
8727
8728
8729
8730
8731
8732
8733
8734
8735
8736
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746
8747
8748
8749
8750
8751
8752
8753
8754
8755
8756
8757
8758
8759
8760
8761
8762
8763
8764
8765
8766
8767
8768
8769
8770
8771
8772
8773
8774
8775
8776
8777
8778
8779
8780
8781
8782
8783
8784
8785
8786
8787
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
8798
8799
8800
8801
8802
8803
8804
8805
8806
8807
8808
8809
8810
8811
8812
8813
8814
8815
8816
8817
8818
8819
8820
8821
8822
8823
8824
8825
8826
8827
8828
8829
8830
8831
8832
8833
8834
8835
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847
8848
8849
8850
8851
8852
8853
8854
8855
8856
8857
8858
8859
8860
8861
8862
8863
8864
8865
8866
8867
8868
8869
8870
8871
8872
8873
8874
8875
8876
8877
8878
8879
8880
8881
8882
8883
8884
8885
8886
8887
8888
8889
8890
8891
8892
8893
8894
8895
8896
8897
8898
8899
8900
8901
8902
8903
8904
8905
8906
8907
8908
8909
8910
8911
8912
8913
8914
8915
8916
8917
8918
8919
8920
8921
8922
8923
8924
8925
8926
8927
8928
8929
8930
8931
8932
8933
8934
8935
8936
8937
8938
8939
8940
8941
8942
8943
8944
8945
8946
8947
8948
8949
8950
8951
8952
8953
8954
8955
8956
8957
8958
8959
8960
8961
8962
8963
8964
8965
8966
8967
8968
8969
8970
8971
8972
8973
8974
8975
8976
8977
8978
8979
8980
8981
8982
8983
8984
8985
8986
8987
8988
8989
8990
8991
8992
8993
8994
8995
8996
8997
8998
8999
9000
9001
9002
9003
9004
9005
9006
9007
9008
9009
9010
9011
9012
9013
9014
9015
9016
9017
9018
9019
9020
9021
9022
9023
9024
9025
9026
9027
9028
9029
9030
9031
9032
9033
9034
9035
9036
9037
9038
9039
9040
9041
9042
9043
9044
9045
9046
9047
9048
9049
9050
9051
9052
9053
9054
9055
9056
9057
9058
9059
9060
9061
9062
9063
9064
9065
9066
9067
9068
9069
9070
9071
9072
9073
9074
9075
9076
9077
9078
9079
9080
9081
9082
9083
9084
9085
9086
9087
9088
9089
9090
9091
9092
9093
9094
9095
9096
9097
9098
9099
9100
9101
9102
9103
9104
9105
9106
9107
9108
9109
9110
9111
9112
9113
9114
9115
9116
9117
9118
9119
9120
9121
9122
9123
9124
9125
9126
9127
9128
9129
9130
9131
9132
9133
9134
9135
9136
9137
9138
9139
9140
9141
9142
9143
9144
9145
9146
9147
9148
9149
9150
9151
9152
9153
9154
9155
9156
9157
9158
9159
9160
9161
9162
9163
9164
9165
9166
9167
9168
9169
9170
9171
9172
9173
9174
9175
9176
9177
9178
9179
9180
9181
9182
9183
9184
9185
9186
9187
9188
9189
9190
9191
9192
9193
9194
9195
9196
9197
9198
9199
9200
9201
9202
9203
9204
9205
9206
9207
9208
9209
9210
9211
9212
9213
9214
9215
9216
9217
9218
9219
9220
9221
9222
9223
9224
9225
9226
9227
9228
9229
9230
9231
9232
9233
9234
9235
9236
9237
9238
9239
9240
9241
9242
9243
9244
9245
9246
9247
9248
9249
9250
9251
9252
9253
9254
9255
9256
9257
9258
9259
9260
9261
9262
9263
9264
9265
9266
9267
9268
9269
9270
9271
9272
9273
9274
9275
9276
9277
9278
9279
9280
9281
9282
9283
9284
9285
9286
9287
9288
9289
9290
9291
9292
9293
9294
9295
9296
9297
9298
9299
9300
9301
9302
9303
9304
9305
9306
9307
9308
9309
9310
9311
9312
9313
9314
9315
9316
9317
9318
9319
9320
9321
9322
9323
9324
9325
9326
9327
9328
9329
9330
9331
9332
9333
9334
9335
9336
9337
9338
9339
9340
9341
9342
9343
9344
9345
9346
9347
9348
9349
9350
9351
9352
9353
9354
9355
9356
9357
9358
9359
9360
9361
9362
9363
9364
9365
9366
9367
9368
9369
9370
9371
9372
9373
9374
9375
9376
9377
9378
9379
9380
9381
9382
9383
9384
9385
9386
9387
9388
9389
9390
9391
9392
9393
9394
9395
9396
9397
9398
9399
9400
9401
9402
9403
9404
9405
9406
9407
9408
9409
9410
9411
9412
9413
9414
9415
9416
9417
9418
9419
9420
9421
9422
9423
9424
9425
9426
9427
9428
9429
9430
9431
9432
9433
9434
9435
9436
9437


9438
9439
9440
9441
9442
9443
9444
9445
9446




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+
+
+
+
+
+
+
/* crc32.h -- tables for rapid CRC calculation
 * Generated automatically by crc32.c
 */

local const z_crc_t FAR crc_table[TBLS][256] =
{
  {
    0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
    0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
    0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
    0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
    0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
    0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
    0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
    0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
    0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
    0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
    0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
    0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
    0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
    0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
    0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
    0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
    0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
    0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
    0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
    0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
    0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
    0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
    0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
    0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
    0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
    0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
    0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
    0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
    0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
    0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
    0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
    0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
    0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
    0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
    0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
    0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
    0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
    0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
    0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
    0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
    0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
    0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
    0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
    0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
    0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
    0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
    0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
    0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
    0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
    0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
    0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
    0x2d02ef8dUL
#ifdef BYFOUR
  },
  {
    0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
local const z_crc_t FAR crc_table[] = {
    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
    0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
    0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
    0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
    0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
    0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
    0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
    0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
    0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
    0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
    0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
    0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
    0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
    0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
    0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
    0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
    0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
    0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
    0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
    0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
    0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
    0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
    0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
    0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
    0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
    0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
    0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
    0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
    0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
    0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
    0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
    0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
    0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
    0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
    0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
    0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
    0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
    0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
    0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
    0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
    0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
    0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
    0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
    0x2d02ef8d};

#ifdef W

#if W == 8

local const z_word_t FAR crc_big_table[] = {
    0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000,
    0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000,
    0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000,
    0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000,
    0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000,
    0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000,
    0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000,
    0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000,
    0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000,
    0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000,
    0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000,
    0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000,
    0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000,
    0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000,
    0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000,
    0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000,
    0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000,
    0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000,
    0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000,
    0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000,
    0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000,
    0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000,
    0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000,
    0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000,
    0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000,
    0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000,
    0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000,
    0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000,
    0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000,
    0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000,
    0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000,
    0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000,
    0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000,
    0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000,
    0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000,
    0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000,
    0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000,
    0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000,
    0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000,
    0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000,
    0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000,
    0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000,
    0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000,
    0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000,
    0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000,
    0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000,
    0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000,
    0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000,
    0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000,
    0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000,
    0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000,
    0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000,
    0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000,
    0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000,
    0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000,
    0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000,
    0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000,
    0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000,
    0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000,
    0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000,
    0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000,
    0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000,
    0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000,
    0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000,
    0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000,
    0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000,
    0x8567077200000000, 0x1357000500000000, 0x824abf9500000000,
    0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000,
    0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000,
    0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000,
    0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000,
    0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000,
    0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000,
    0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000,
    0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000,
    0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000,
    0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000,
    0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000,
    0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000,
    0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000,
    0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000,
    0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000,
    0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000,
    0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000,
    0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000,
    0x8def022d00000000};

#else /* W == 4 */

local const z_word_t FAR crc_big_table[] = {
    0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07,
    0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79,
    0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7,
    0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84,
    0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13,
    0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663,
    0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5,
    0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5,
    0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832,
    0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51,
    0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf,
    0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1,
    0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76,
    0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606,
    0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996,
    0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6,
    0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c,
    0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712,
    0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c,
    0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4,
    0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943,
    0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333,
    0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe,
    0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce,
    0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359,
    0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a,
    0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04,
    0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a,
    0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0,
    0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580,
    0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10,
    0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060,
    0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1,
    0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf,
    0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31,
    0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852,
    0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5,
    0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5,
    0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75,
    0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005,
    0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292,
    0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1,
    0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f,
    0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111,
    0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0,
    0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0,
    0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40,
    0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530,
    0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba,
    0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4,
    0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a,
    0x8def022d};

#endif

#if N == 1

#if W == 8

local const z_crc_t FAR crc_braid_table[][256] = {
   {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa,
    0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b,
    0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232,
    0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8,
    0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e,
    0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa,
    0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b,
    0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f,
    0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719,
    0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3,
    0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa,
    0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b,
    0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed,
    0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89,
    0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25,
    0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041,
    0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c,
    0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed,
    0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4,
    0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758,
    0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e,
    0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a,
    0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed,
    0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889,
    0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df,
    0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544,
    0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d,
    0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c,
    0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1,
    0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95,
    0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839,
    0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d,
    0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976,
    0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7,
    0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be,
    0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144,
    0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12,
    0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376,
    0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a,
    0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e,
    0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278,
    0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682,
    0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b,
    0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a,
    0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561,
    0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05,
    0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9,
    0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd,
    0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0,
    0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61,
    0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678,
    0x264b06e6},
   {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413,
    0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3,
    0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d,
    0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653,
    0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9,
    0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e,
    0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5,
    0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712,
    0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8,
    0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6,
    0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068,
    0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8,
    0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579,
    0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade,
    0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37,
    0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590,
    0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4,
    0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64,
    0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea,
    0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678,
    0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282,
    0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25,
    0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102,
    0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5,
    0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f,
    0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146,
    0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8,
    0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08,
    0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c,
    0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b,
    0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972,
    0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5,
    0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d,
    0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd,
    0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833,
    0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d,
    0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7,
    0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60,
    0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2,
    0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105,
    0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff,
    0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1,
    0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f,
    0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf,
    0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617,
    0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0,
    0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959,
    0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe,
    0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca,
    0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a,
    0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184,
    0x92364a30},
   {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216,
    0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8,
    0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170,
    0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035,
    0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6,
    0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145,
    0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d,
    0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e,
    0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d,
    0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408,
    0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0,
    0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e,
    0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c,
    0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf,
    0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a,
    0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9,
    0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1,
    0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f,
    0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987,
    0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4,
    0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37,
    0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84,
    0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca,
    0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79,
    0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba,
    0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d,
    0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5,
    0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b,
    0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643,
    0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0,
    0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525,
    0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496,
    0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8,
    0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026,
    0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e,
    0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db,
    0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118,
    0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab,
    0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf,
    0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c,
    0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf,
    0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a,
    0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32,
    0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec,
    0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82,
    0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31,
    0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4,
    0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957,
    0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f,
    0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1,
    0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869,
    0xe4c4abcc},
   {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0,
    0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271,
    0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61,
    0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52,
    0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43,
    0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333,
    0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64,
    0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314,
    0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205,
    0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136,
    0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26,
    0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997,
    0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849,
    0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739,
    0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8,
    0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98,
    0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b,
    0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba,
    0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa,
    0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d,
    0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c,
    0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc,
    0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af,
    0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf,
    0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce,
    0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922,
    0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532,
    0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183,
    0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710,
    0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860,
    0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1,
    0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1,
    0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956,
    0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7,
    0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7,
    0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4,
    0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5,
    0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5,
    0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb,
    0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb,
    0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da,
    0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9,
    0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9,
    0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48,
    0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df,
    0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af,
    0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e,
    0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e,
    0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d,
    0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c,
    0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c,
    0xca64c78c},
   {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757,
    0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a,
    0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733,
    0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
    0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70,
    0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42,
    0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5,
    0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
    0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086,
    0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4,
    0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d,
    0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
    0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d,
    0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f,
    0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859,
    0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
    0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5,
    0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028,
    0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891,
    0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
    0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec,
    0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde,
    0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817,
    0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
    0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24,
    0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e,
    0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7,
    0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
    0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4,
    0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196,
    0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0,
    0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
    0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52,
    0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f,
    0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36,
    0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
    0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675,
    0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647,
    0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d,
    0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
    0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be,
    0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc,
    0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645,
    0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
    0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138,
    0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a,
    0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c,
    0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
    0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0,
    0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d,
    0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194,
    0xde0506f1},
   {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc,
    0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f,
    0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a,
    0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
    0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8,
    0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023,
    0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e,
    0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
    0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84,
    0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7,
    0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922,
    0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
    0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0,
    0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b,
    0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816,
    0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
    0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c,
    0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f,
    0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba,
    0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
    0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98,
    0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873,
    0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e,
    0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
    0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134,
    0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7,
    0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732,
    0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
    0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0,
    0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b,
    0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26,
    0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
    0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc,
    0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef,
    0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a,
    0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
    0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8,
    0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43,
    0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e,
    0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
    0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24,
    0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07,
    0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982,
    0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
    0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0,
    0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b,
    0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576,
    0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
    0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c,
    0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f,
    0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda,
    0xbe9834ed},
   {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504,
    0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49,
    0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e,
    0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
    0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859,
    0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c,
    0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620,
    0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
    0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae,
    0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2,
    0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175,
    0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
    0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05,
    0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40,
    0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f,
    0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
    0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850,
    0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d,
    0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da,
    0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
    0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af,
    0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea,
    0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74,
    0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
    0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa,
    0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a,
    0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd,
    0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
    0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a,
    0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f,
    0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290,
    0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
    0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed,
    0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0,
    0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167,
    0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
    0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0,
    0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5,
    0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc,
    0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
    0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842,
    0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e,
    0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299,
    0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
    0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec,
    0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9,
    0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66,
    0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
    0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9,
    0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4,
    0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33,
    0x9324fd72},
   {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
    0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
    0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
    0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
    0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
    0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
    0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
    0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
    0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
    0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
    0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
    0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
    0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
    0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
    0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
    0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
    0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
    0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
    0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
    0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
    0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
    0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
    0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
    0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
    0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
    0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
    0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
    0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
    0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
    0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
    0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
    0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
    0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
    0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
    0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
    0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
    0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
    0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
    0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
    0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
    0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
    0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
    0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
    0x2d02ef8d}};

local const z_word_t FAR crc_braid_big_table[][256] = {
   {0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000,
    0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000,
    0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000,
    0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000,
    0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000,
    0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000,
    0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000,
    0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000,
    0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000,
    0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000,
    0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000,
    0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000,
    0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000,
    0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000,
    0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000,
    0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000,
    0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000,
    0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000,
    0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000,
    0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000,
    0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000,
    0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000,
    0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000,
    0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000,
    0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000,
    0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000,
    0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000,
    0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000,
    0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000,
    0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000,
    0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000,
    0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000,
    0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000,
    0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000,
    0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000,
    0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000,
    0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000,
    0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000,
    0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000,
    0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000,
    0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000,
    0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000,
    0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000,
    0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000,
    0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000,
    0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000,
    0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000,
    0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000,
    0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000,
    0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000,
    0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000,
    0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000,
    0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000,
    0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000,
    0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000,
    0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000,
    0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000,
    0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000,
    0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000,
    0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000,
    0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000,
    0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000,
    0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000,
    0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000,
    0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000,
    0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000,
    0x8567077200000000, 0x1357000500000000, 0x824abf9500000000,
    0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000,
    0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000,
    0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000,
    0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000,
    0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000,
    0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000,
    0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000,
    0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000,
    0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000,
    0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000,
    0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000,
    0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000,
    0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000,
    0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000,
    0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000,
    0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000,
    0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000,
    0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000,
    0x8def022d00000000},
   {0x0000000000000000, 0x41311b1900000000, 0x8262363200000000,
    0xc3532d2b00000000, 0x04c56c6400000000, 0x45f4777d00000000,
    0x86a75a5600000000, 0xc796414f00000000, 0x088ad9c800000000,
    0x49bbc2d100000000, 0x8ae8effa00000000, 0xcbd9f4e300000000,
    0x0c4fb5ac00000000, 0x4d7eaeb500000000, 0x8e2d839e00000000,
    0xcf1c988700000000, 0x5112c24a00000000, 0x1023d95300000000,
    0xd370f47800000000, 0x9241ef6100000000, 0x55d7ae2e00000000,
    0x14e6b53700000000, 0xd7b5981c00000000, 0x9684830500000000,
    0x59981b8200000000, 0x18a9009b00000000, 0xdbfa2db000000000,
    0x9acb36a900000000, 0x5d5d77e600000000, 0x1c6c6cff00000000,
    0xdf3f41d400000000, 0x9e0e5acd00000000, 0xa224849500000000,
    0xe3159f8c00000000, 0x2046b2a700000000, 0x6177a9be00000000,
    0xa6e1e8f100000000, 0xe7d0f3e800000000, 0x2483dec300000000,
    0x65b2c5da00000000, 0xaaae5d5d00000000, 0xeb9f464400000000,
    0x28cc6b6f00000000, 0x69fd707600000000, 0xae6b313900000000,
    0xef5a2a2000000000, 0x2c09070b00000000, 0x6d381c1200000000,
    0xf33646df00000000, 0xb2075dc600000000, 0x715470ed00000000,
    0x30656bf400000000, 0xf7f32abb00000000, 0xb6c231a200000000,
    0x75911c8900000000, 0x34a0079000000000, 0xfbbc9f1700000000,
    0xba8d840e00000000, 0x79dea92500000000, 0x38efb23c00000000,
    0xff79f37300000000, 0xbe48e86a00000000, 0x7d1bc54100000000,
    0x3c2ade5800000000, 0x054f79f000000000, 0x447e62e900000000,
    0x872d4fc200000000, 0xc61c54db00000000, 0x018a159400000000,
    0x40bb0e8d00000000, 0x83e823a600000000, 0xc2d938bf00000000,
    0x0dc5a03800000000, 0x4cf4bb2100000000, 0x8fa7960a00000000,
    0xce968d1300000000, 0x0900cc5c00000000, 0x4831d74500000000,
    0x8b62fa6e00000000, 0xca53e17700000000, 0x545dbbba00000000,
    0x156ca0a300000000, 0xd63f8d8800000000, 0x970e969100000000,
    0x5098d7de00000000, 0x11a9ccc700000000, 0xd2fae1ec00000000,
    0x93cbfaf500000000, 0x5cd7627200000000, 0x1de6796b00000000,
    0xdeb5544000000000, 0x9f844f5900000000, 0x58120e1600000000,
    0x1923150f00000000, 0xda70382400000000, 0x9b41233d00000000,
    0xa76bfd6500000000, 0xe65ae67c00000000, 0x2509cb5700000000,
    0x6438d04e00000000, 0xa3ae910100000000, 0xe29f8a1800000000,
    0x21cca73300000000, 0x60fdbc2a00000000, 0xafe124ad00000000,
    0xeed03fb400000000, 0x2d83129f00000000, 0x6cb2098600000000,
    0xab2448c900000000, 0xea1553d000000000, 0x29467efb00000000,
    0x687765e200000000, 0xf6793f2f00000000, 0xb748243600000000,
    0x741b091d00000000, 0x352a120400000000, 0xf2bc534b00000000,
    0xb38d485200000000, 0x70de657900000000, 0x31ef7e6000000000,
    0xfef3e6e700000000, 0xbfc2fdfe00000000, 0x7c91d0d500000000,
    0x3da0cbcc00000000, 0xfa368a8300000000, 0xbb07919a00000000,
    0x7854bcb100000000, 0x3965a7a800000000, 0x4b98833b00000000,
    0x0aa9982200000000, 0xc9fab50900000000, 0x88cbae1000000000,
    0x4f5def5f00000000, 0x0e6cf44600000000, 0xcd3fd96d00000000,
    0x8c0ec27400000000, 0x43125af300000000, 0x022341ea00000000,
    0xc1706cc100000000, 0x804177d800000000, 0x47d7369700000000,
    0x06e62d8e00000000, 0xc5b500a500000000, 0x84841bbc00000000,
    0x1a8a417100000000, 0x5bbb5a6800000000, 0x98e8774300000000,
    0xd9d96c5a00000000, 0x1e4f2d1500000000, 0x5f7e360c00000000,
    0x9c2d1b2700000000, 0xdd1c003e00000000, 0x120098b900000000,
    0x533183a000000000, 0x9062ae8b00000000, 0xd153b59200000000,
    0x16c5f4dd00000000, 0x57f4efc400000000, 0x94a7c2ef00000000,
    0xd596d9f600000000, 0xe9bc07ae00000000, 0xa88d1cb700000000,
    0x6bde319c00000000, 0x2aef2a8500000000, 0xed796bca00000000,
    0xac4870d300000000, 0x6f1b5df800000000, 0x2e2a46e100000000,
    0xe136de6600000000, 0xa007c57f00000000, 0x6354e85400000000,
    0x2265f34d00000000, 0xe5f3b20200000000, 0xa4c2a91b00000000,
    0x6791843000000000, 0x26a09f2900000000, 0xb8aec5e400000000,
    0xf99fdefd00000000, 0x3accf3d600000000, 0x7bfde8cf00000000,
    0xbc6ba98000000000, 0xfd5ab29900000000, 0x3e099fb200000000,
    0x7f3884ab00000000, 0xb0241c2c00000000, 0xf115073500000000,
    0x32462a1e00000000, 0x7377310700000000, 0xb4e1704800000000,
    0xf5d06b5100000000, 0x3683467a00000000, 0x77b25d6300000000,
    0x4ed7facb00000000, 0x0fe6e1d200000000, 0xccb5ccf900000000,
    0x8d84d7e000000000, 0x4a1296af00000000, 0x0b238db600000000,
    0xc870a09d00000000, 0x8941bb8400000000, 0x465d230300000000,
    0x076c381a00000000, 0xc43f153100000000, 0x850e0e2800000000,
    0x42984f6700000000, 0x03a9547e00000000, 0xc0fa795500000000,
    0x81cb624c00000000, 0x1fc5388100000000, 0x5ef4239800000000,
    0x9da70eb300000000, 0xdc9615aa00000000, 0x1b0054e500000000,
    0x5a314ffc00000000, 0x996262d700000000, 0xd85379ce00000000,
    0x174fe14900000000, 0x567efa5000000000, 0x952dd77b00000000,
    0xd41ccc6200000000, 0x138a8d2d00000000, 0x52bb963400000000,
    0x91e8bb1f00000000, 0xd0d9a00600000000, 0xecf37e5e00000000,
    0xadc2654700000000, 0x6e91486c00000000, 0x2fa0537500000000,
    0xe836123a00000000, 0xa907092300000000, 0x6a54240800000000,
    0x2b653f1100000000, 0xe479a79600000000, 0xa548bc8f00000000,
    0x661b91a400000000, 0x272a8abd00000000, 0xe0bccbf200000000,
    0xa18dd0eb00000000, 0x62defdc000000000, 0x23efe6d900000000,
    0xbde1bc1400000000, 0xfcd0a70d00000000, 0x3f838a2600000000,
    0x7eb2913f00000000, 0xb924d07000000000, 0xf815cb6900000000,
    0x3b46e64200000000, 0x7a77fd5b00000000, 0xb56b65dc00000000,
    0xf45a7ec500000000, 0x370953ee00000000, 0x763848f700000000,
    0xb1ae09b800000000, 0xf09f12a100000000, 0x33cc3f8a00000000,
    0x72fd249300000000},
   {0x0000000000000000, 0x376ac20100000000, 0x6ed4840300000000,
    0x59be460200000000, 0xdca8090700000000, 0xebc2cb0600000000,
    0xb27c8d0400000000, 0x85164f0500000000, 0xb851130e00000000,
    0x8f3bd10f00000000, 0xd685970d00000000, 0xe1ef550c00000000,
    0x64f91a0900000000, 0x5393d80800000000, 0x0a2d9e0a00000000,
    0x3d475c0b00000000, 0x70a3261c00000000, 0x47c9e41d00000000,
    0x1e77a21f00000000, 0x291d601e00000000, 0xac0b2f1b00000000,
    0x9b61ed1a00000000, 0xc2dfab1800000000, 0xf5b5691900000000,
    0xc8f2351200000000, 0xff98f71300000000, 0xa626b11100000000,
    0x914c731000000000, 0x145a3c1500000000, 0x2330fe1400000000,
    0x7a8eb81600000000, 0x4de47a1700000000, 0xe0464d3800000000,
    0xd72c8f3900000000, 0x8e92c93b00000000, 0xb9f80b3a00000000,
    0x3cee443f00000000, 0x0b84863e00000000, 0x523ac03c00000000,
    0x6550023d00000000, 0x58175e3600000000, 0x6f7d9c3700000000,
    0x36c3da3500000000, 0x01a9183400000000, 0x84bf573100000000,
    0xb3d5953000000000, 0xea6bd33200000000, 0xdd01113300000000,
    0x90e56b2400000000, 0xa78fa92500000000, 0xfe31ef2700000000,
    0xc95b2d2600000000, 0x4c4d622300000000, 0x7b27a02200000000,
    0x2299e62000000000, 0x15f3242100000000, 0x28b4782a00000000,
    0x1fdeba2b00000000, 0x4660fc2900000000, 0x710a3e2800000000,
    0xf41c712d00000000, 0xc376b32c00000000, 0x9ac8f52e00000000,
    0xada2372f00000000, 0xc08d9a7000000000, 0xf7e7587100000000,
    0xae591e7300000000, 0x9933dc7200000000, 0x1c25937700000000,
    0x2b4f517600000000, 0x72f1177400000000, 0x459bd57500000000,
    0x78dc897e00000000, 0x4fb64b7f00000000, 0x16080d7d00000000,
    0x2162cf7c00000000, 0xa474807900000000, 0x931e427800000000,
    0xcaa0047a00000000, 0xfdcac67b00000000, 0xb02ebc6c00000000,
    0x87447e6d00000000, 0xdefa386f00000000, 0xe990fa6e00000000,
    0x6c86b56b00000000, 0x5bec776a00000000, 0x0252316800000000,
    0x3538f36900000000, 0x087faf6200000000, 0x3f156d6300000000,
    0x66ab2b6100000000, 0x51c1e96000000000, 0xd4d7a66500000000,
    0xe3bd646400000000, 0xba03226600000000, 0x8d69e06700000000,
    0x20cbd74800000000, 0x17a1154900000000, 0x4e1f534b00000000,
    0x7975914a00000000, 0xfc63de4f00000000, 0xcb091c4e00000000,
    0x92b75a4c00000000, 0xa5dd984d00000000, 0x989ac44600000000,
    0xaff0064700000000, 0xf64e404500000000, 0xc124824400000000,
    0x4432cd4100000000, 0x73580f4000000000, 0x2ae6494200000000,
    0x1d8c8b4300000000, 0x5068f15400000000, 0x6702335500000000,
    0x3ebc755700000000, 0x09d6b75600000000, 0x8cc0f85300000000,
    0xbbaa3a5200000000, 0xe2147c5000000000, 0xd57ebe5100000000,
    0xe839e25a00000000, 0xdf53205b00000000, 0x86ed665900000000,
    0xb187a45800000000, 0x3491eb5d00000000, 0x03fb295c00000000,
    0x5a456f5e00000000, 0x6d2fad5f00000000, 0x801b35e100000000,
    0xb771f7e000000000, 0xeecfb1e200000000, 0xd9a573e300000000,
    0x5cb33ce600000000, 0x6bd9fee700000000, 0x3267b8e500000000,
    0x050d7ae400000000, 0x384a26ef00000000, 0x0f20e4ee00000000,
    0x569ea2ec00000000, 0x61f460ed00000000, 0xe4e22fe800000000,
    0xd388ede900000000, 0x8a36abeb00000000, 0xbd5c69ea00000000,
    0xf0b813fd00000000, 0xc7d2d1fc00000000, 0x9e6c97fe00000000,
    0xa90655ff00000000, 0x2c101afa00000000, 0x1b7ad8fb00000000,
    0x42c49ef900000000, 0x75ae5cf800000000, 0x48e900f300000000,
    0x7f83c2f200000000, 0x263d84f000000000, 0x115746f100000000,
    0x944109f400000000, 0xa32bcbf500000000, 0xfa958df700000000,
    0xcdff4ff600000000, 0x605d78d900000000, 0x5737bad800000000,
    0x0e89fcda00000000, 0x39e33edb00000000, 0xbcf571de00000000,
    0x8b9fb3df00000000, 0xd221f5dd00000000, 0xe54b37dc00000000,
    0xd80c6bd700000000, 0xef66a9d600000000, 0xb6d8efd400000000,
    0x81b22dd500000000, 0x04a462d000000000, 0x33cea0d100000000,
    0x6a70e6d300000000, 0x5d1a24d200000000, 0x10fe5ec500000000,
    0x27949cc400000000, 0x7e2adac600000000, 0x494018c700000000,
    0xcc5657c200000000, 0xfb3c95c300000000, 0xa282d3c100000000,
    0x95e811c000000000, 0xa8af4dcb00000000, 0x9fc58fca00000000,
    0xc67bc9c800000000, 0xf1110bc900000000, 0x740744cc00000000,
    0x436d86cd00000000, 0x1ad3c0cf00000000, 0x2db902ce00000000,
    0x4096af9100000000, 0x77fc6d9000000000, 0x2e422b9200000000,
    0x1928e99300000000, 0x9c3ea69600000000, 0xab54649700000000,
    0xf2ea229500000000, 0xc580e09400000000, 0xf8c7bc9f00000000,
    0xcfad7e9e00000000, 0x9613389c00000000, 0xa179fa9d00000000,
    0x246fb59800000000, 0x1305779900000000, 0x4abb319b00000000,
    0x7dd1f39a00000000, 0x3035898d00000000, 0x075f4b8c00000000,
    0x5ee10d8e00000000, 0x698bcf8f00000000, 0xec9d808a00000000,
    0xdbf7428b00000000, 0x8249048900000000, 0xb523c68800000000,
    0x88649a8300000000, 0xbf0e588200000000, 0xe6b01e8000000000,
    0xd1dadc8100000000, 0x54cc938400000000, 0x63a6518500000000,
    0x3a18178700000000, 0x0d72d58600000000, 0xa0d0e2a900000000,
    0x97ba20a800000000, 0xce0466aa00000000, 0xf96ea4ab00000000,
    0x7c78ebae00000000, 0x4b1229af00000000, 0x12ac6fad00000000,
    0x25c6adac00000000, 0x1881f1a700000000, 0x2feb33a600000000,
    0x765575a400000000, 0x413fb7a500000000, 0xc429f8a000000000,
    0xf3433aa100000000, 0xaafd7ca300000000, 0x9d97bea200000000,
    0xd073c4b500000000, 0xe71906b400000000, 0xbea740b600000000,
    0x89cd82b700000000, 0x0cdbcdb200000000, 0x3bb10fb300000000,
    0x620f49b100000000, 0x55658bb000000000, 0x6822d7bb00000000,
    0x5f4815ba00000000, 0x06f653b800000000, 0x319c91b900000000,
    0xb48adebc00000000, 0x83e01cbd00000000, 0xda5e5abf00000000,
    0xed3498be00000000},
   {0x0000000000000000, 0x6567bcb800000000, 0x8bc809aa00000000,
    0xeeafb51200000000, 0x5797628f00000000, 0x32f0de3700000000,
    0xdc5f6b2500000000, 0xb938d79d00000000, 0xef28b4c500000000,
    0x8a4f087d00000000, 0x64e0bd6f00000000, 0x018701d700000000,
    0xb8bfd64a00000000, 0xddd86af200000000, 0x3377dfe000000000,
    0x5610635800000000, 0x9f57195000000000, 0xfa30a5e800000000,
    0x149f10fa00000000, 0x71f8ac4200000000, 0xc8c07bdf00000000,
    0xada7c76700000000, 0x4308727500000000, 0x266fcecd00000000,
    0x707fad9500000000, 0x1518112d00000000, 0xfbb7a43f00000000,
    0x9ed0188700000000, 0x27e8cf1a00000000, 0x428f73a200000000,
    0xac20c6b000000000, 0xc9477a0800000000, 0x3eaf32a000000000,
    0x5bc88e1800000000, 0xb5673b0a00000000, 0xd00087b200000000,
    0x6938502f00000000, 0x0c5fec9700000000, 0xe2f0598500000000,
    0x8797e53d00000000, 0xd187866500000000, 0xb4e03add00000000,
    0x5a4f8fcf00000000, 0x3f28337700000000, 0x8610e4ea00000000,
    0xe377585200000000, 0x0dd8ed4000000000, 0x68bf51f800000000,
    0xa1f82bf000000000, 0xc49f974800000000, 0x2a30225a00000000,
    0x4f579ee200000000, 0xf66f497f00000000, 0x9308f5c700000000,
    0x7da740d500000000, 0x18c0fc6d00000000, 0x4ed09f3500000000,
    0x2bb7238d00000000, 0xc518969f00000000, 0xa07f2a2700000000,
    0x1947fdba00000000, 0x7c20410200000000, 0x928ff41000000000,
    0xf7e848a800000000, 0x3d58149b00000000, 0x583fa82300000000,
    0xb6901d3100000000, 0xd3f7a18900000000, 0x6acf761400000000,
    0x0fa8caac00000000, 0xe1077fbe00000000, 0x8460c30600000000,
    0xd270a05e00000000, 0xb7171ce600000000, 0x59b8a9f400000000,
    0x3cdf154c00000000, 0x85e7c2d100000000, 0xe0807e6900000000,
    0x0e2fcb7b00000000, 0x6b4877c300000000, 0xa20f0dcb00000000,
    0xc768b17300000000, 0x29c7046100000000, 0x4ca0b8d900000000,
    0xf5986f4400000000, 0x90ffd3fc00000000, 0x7e5066ee00000000,
    0x1b37da5600000000, 0x4d27b90e00000000, 0x284005b600000000,
    0xc6efb0a400000000, 0xa3880c1c00000000, 0x1ab0db8100000000,
    0x7fd7673900000000, 0x9178d22b00000000, 0xf41f6e9300000000,
    0x03f7263b00000000, 0x66909a8300000000, 0x883f2f9100000000,
    0xed58932900000000, 0x546044b400000000, 0x3107f80c00000000,
    0xdfa84d1e00000000, 0xbacff1a600000000, 0xecdf92fe00000000,
    0x89b82e4600000000, 0x67179b5400000000, 0x027027ec00000000,
    0xbb48f07100000000, 0xde2f4cc900000000, 0x3080f9db00000000,
    0x55e7456300000000, 0x9ca03f6b00000000, 0xf9c783d300000000,
    0x176836c100000000, 0x720f8a7900000000, 0xcb375de400000000,
    0xae50e15c00000000, 0x40ff544e00000000, 0x2598e8f600000000,
    0x73888bae00000000, 0x16ef371600000000, 0xf840820400000000,
    0x9d273ebc00000000, 0x241fe92100000000, 0x4178559900000000,
    0xafd7e08b00000000, 0xcab05c3300000000, 0x3bb659ed00000000,
    0x5ed1e55500000000, 0xb07e504700000000, 0xd519ecff00000000,
    0x6c213b6200000000, 0x094687da00000000, 0xe7e932c800000000,
    0x828e8e7000000000, 0xd49eed2800000000, 0xb1f9519000000000,
    0x5f56e48200000000, 0x3a31583a00000000, 0x83098fa700000000,
    0xe66e331f00000000, 0x08c1860d00000000, 0x6da63ab500000000,
    0xa4e140bd00000000, 0xc186fc0500000000, 0x2f29491700000000,
    0x4a4ef5af00000000, 0xf376223200000000, 0x96119e8a00000000,
    0x78be2b9800000000, 0x1dd9972000000000, 0x4bc9f47800000000,
    0x2eae48c000000000, 0xc001fdd200000000, 0xa566416a00000000,
    0x1c5e96f700000000, 0x79392a4f00000000, 0x97969f5d00000000,
    0xf2f123e500000000, 0x05196b4d00000000, 0x607ed7f500000000,
    0x8ed162e700000000, 0xebb6de5f00000000, 0x528e09c200000000,
    0x37e9b57a00000000, 0xd946006800000000, 0xbc21bcd000000000,
    0xea31df8800000000, 0x8f56633000000000, 0x61f9d62200000000,
    0x049e6a9a00000000, 0xbda6bd0700000000, 0xd8c101bf00000000,
    0x366eb4ad00000000, 0x5309081500000000, 0x9a4e721d00000000,
    0xff29cea500000000, 0x11867bb700000000, 0x74e1c70f00000000,
    0xcdd9109200000000, 0xa8beac2a00000000, 0x4611193800000000,
    0x2376a58000000000, 0x7566c6d800000000, 0x10017a6000000000,
    0xfeaecf7200000000, 0x9bc973ca00000000, 0x22f1a45700000000,
    0x479618ef00000000, 0xa939adfd00000000, 0xcc5e114500000000,
    0x06ee4d7600000000, 0x6389f1ce00000000, 0x8d2644dc00000000,
    0xe841f86400000000, 0x51792ff900000000, 0x341e934100000000,
    0xdab1265300000000, 0xbfd69aeb00000000, 0xe9c6f9b300000000,
    0x8ca1450b00000000, 0x620ef01900000000, 0x07694ca100000000,
    0xbe519b3c00000000, 0xdb36278400000000, 0x3599929600000000,
    0x50fe2e2e00000000, 0x99b9542600000000, 0xfcdee89e00000000,
    0x12715d8c00000000, 0x7716e13400000000, 0xce2e36a900000000,
    0xab498a1100000000, 0x45e63f0300000000, 0x208183bb00000000,
    0x7691e0e300000000, 0x13f65c5b00000000, 0xfd59e94900000000,
    0x983e55f100000000, 0x2106826c00000000, 0x44613ed400000000,
    0xaace8bc600000000, 0xcfa9377e00000000, 0x38417fd600000000,
    0x5d26c36e00000000, 0xb389767c00000000, 0xd6eecac400000000,
    0x6fd61d5900000000, 0x0ab1a1e100000000, 0xe41e14f300000000,
    0x8179a84b00000000, 0xd769cb1300000000, 0xb20e77ab00000000,
    0x5ca1c2b900000000, 0x39c67e0100000000, 0x80fea99c00000000,
    0xe599152400000000, 0x0b36a03600000000, 0x6e511c8e00000000,
    0xa716668600000000, 0xc271da3e00000000, 0x2cde6f2c00000000,
    0x49b9d39400000000, 0xf081040900000000, 0x95e6b8b100000000,
    0x7b490da300000000, 0x1e2eb11b00000000, 0x483ed24300000000,
    0x2d596efb00000000, 0xc3f6dbe900000000, 0xa691675100000000,
    0x1fa9b0cc00000000, 0x7ace0c7400000000, 0x9461b96600000000,
    0xf10605de00000000},
   {0x0000000000000000, 0xb029603d00000000, 0x6053c07a00000000,
    0xd07aa04700000000, 0xc0a680f500000000, 0x708fe0c800000000,
    0xa0f5408f00000000, 0x10dc20b200000000, 0xc14b703000000000,
    0x7162100d00000000, 0xa118b04a00000000, 0x1131d07700000000,
    0x01edf0c500000000, 0xb1c490f800000000, 0x61be30bf00000000,
    0xd197508200000000, 0x8297e06000000000, 0x32be805d00000000,
    0xe2c4201a00000000, 0x52ed402700000000, 0x4231609500000000,
    0xf21800a800000000, 0x2262a0ef00000000, 0x924bc0d200000000,
    0x43dc905000000000, 0xf3f5f06d00000000, 0x238f502a00000000,
    0x93a6301700000000, 0x837a10a500000000, 0x3353709800000000,
    0xe329d0df00000000, 0x5300b0e200000000, 0x042fc1c100000000,
    0xb406a1fc00000000, 0x647c01bb00000000, 0xd455618600000000,
    0xc489413400000000, 0x74a0210900000000, 0xa4da814e00000000,
    0x14f3e17300000000, 0xc564b1f100000000, 0x754dd1cc00000000,
    0xa537718b00000000, 0x151e11b600000000, 0x05c2310400000000,
    0xb5eb513900000000, 0x6591f17e00000000, 0xd5b8914300000000,
    0x86b821a100000000, 0x3691419c00000000, 0xe6ebe1db00000000,
    0x56c281e600000000, 0x461ea15400000000, 0xf637c16900000000,
    0x264d612e00000000, 0x9664011300000000, 0x47f3519100000000,
    0xf7da31ac00000000, 0x27a091eb00000000, 0x9789f1d600000000,
    0x8755d16400000000, 0x377cb15900000000, 0xe706111e00000000,
    0x572f712300000000, 0x4958f35800000000, 0xf971936500000000,
    0x290b332200000000, 0x9922531f00000000, 0x89fe73ad00000000,
    0x39d7139000000000, 0xe9adb3d700000000, 0x5984d3ea00000000,
    0x8813836800000000, 0x383ae35500000000, 0xe840431200000000,
    0x5869232f00000000, 0x48b5039d00000000, 0xf89c63a000000000,
    0x28e6c3e700000000, 0x98cfa3da00000000, 0xcbcf133800000000,
    0x7be6730500000000, 0xab9cd34200000000, 0x1bb5b37f00000000,
    0x0b6993cd00000000, 0xbb40f3f000000000, 0x6b3a53b700000000,
    0xdb13338a00000000, 0x0a84630800000000, 0xbaad033500000000,
    0x6ad7a37200000000, 0xdafec34f00000000, 0xca22e3fd00000000,
    0x7a0b83c000000000, 0xaa71238700000000, 0x1a5843ba00000000,
    0x4d77329900000000, 0xfd5e52a400000000, 0x2d24f2e300000000,
    0x9d0d92de00000000, 0x8dd1b26c00000000, 0x3df8d25100000000,
    0xed82721600000000, 0x5dab122b00000000, 0x8c3c42a900000000,
    0x3c15229400000000, 0xec6f82d300000000, 0x5c46e2ee00000000,
    0x4c9ac25c00000000, 0xfcb3a26100000000, 0x2cc9022600000000,
    0x9ce0621b00000000, 0xcfe0d2f900000000, 0x7fc9b2c400000000,
    0xafb3128300000000, 0x1f9a72be00000000, 0x0f46520c00000000,
    0xbf6f323100000000, 0x6f15927600000000, 0xdf3cf24b00000000,
    0x0eaba2c900000000, 0xbe82c2f400000000, 0x6ef862b300000000,
    0xded1028e00000000, 0xce0d223c00000000, 0x7e24420100000000,
    0xae5ee24600000000, 0x1e77827b00000000, 0x92b0e6b100000000,
    0x2299868c00000000, 0xf2e326cb00000000, 0x42ca46f600000000,
    0x5216664400000000, 0xe23f067900000000, 0x3245a63e00000000,
    0x826cc60300000000, 0x53fb968100000000, 0xe3d2f6bc00000000,
    0x33a856fb00000000, 0x838136c600000000, 0x935d167400000000,
    0x2374764900000000, 0xf30ed60e00000000, 0x4327b63300000000,
    0x102706d100000000, 0xa00e66ec00000000, 0x7074c6ab00000000,
    0xc05da69600000000, 0xd081862400000000, 0x60a8e61900000000,
    0xb0d2465e00000000, 0x00fb266300000000, 0xd16c76e100000000,
    0x614516dc00000000, 0xb13fb69b00000000, 0x0116d6a600000000,
    0x11caf61400000000, 0xa1e3962900000000, 0x7199366e00000000,
    0xc1b0565300000000, 0x969f277000000000, 0x26b6474d00000000,
    0xf6cce70a00000000, 0x46e5873700000000, 0x5639a78500000000,
    0xe610c7b800000000, 0x366a67ff00000000, 0x864307c200000000,
    0x57d4574000000000, 0xe7fd377d00000000, 0x3787973a00000000,
    0x87aef70700000000, 0x9772d7b500000000, 0x275bb78800000000,
    0xf72117cf00000000, 0x470877f200000000, 0x1408c71000000000,
    0xa421a72d00000000, 0x745b076a00000000, 0xc472675700000000,
    0xd4ae47e500000000, 0x648727d800000000, 0xb4fd879f00000000,
    0x04d4e7a200000000, 0xd543b72000000000, 0x656ad71d00000000,
    0xb510775a00000000, 0x0539176700000000, 0x15e537d500000000,
    0xa5cc57e800000000, 0x75b6f7af00000000, 0xc59f979200000000,
    0xdbe815e900000000, 0x6bc175d400000000, 0xbbbbd59300000000,
    0x0b92b5ae00000000, 0x1b4e951c00000000, 0xab67f52100000000,
    0x7b1d556600000000, 0xcb34355b00000000, 0x1aa365d900000000,
    0xaa8a05e400000000, 0x7af0a5a300000000, 0xcad9c59e00000000,
    0xda05e52c00000000, 0x6a2c851100000000, 0xba56255600000000,
    0x0a7f456b00000000, 0x597ff58900000000, 0xe95695b400000000,
    0x392c35f300000000, 0x890555ce00000000, 0x99d9757c00000000,
    0x29f0154100000000, 0xf98ab50600000000, 0x49a3d53b00000000,
    0x983485b900000000, 0x281de58400000000, 0xf86745c300000000,
    0x484e25fe00000000, 0x5892054c00000000, 0xe8bb657100000000,
    0x38c1c53600000000, 0x88e8a50b00000000, 0xdfc7d42800000000,
    0x6feeb41500000000, 0xbf94145200000000, 0x0fbd746f00000000,
    0x1f6154dd00000000, 0xaf4834e000000000, 0x7f3294a700000000,
    0xcf1bf49a00000000, 0x1e8ca41800000000, 0xaea5c42500000000,
    0x7edf646200000000, 0xcef6045f00000000, 0xde2a24ed00000000,
    0x6e0344d000000000, 0xbe79e49700000000, 0x0e5084aa00000000,
    0x5d50344800000000, 0xed79547500000000, 0x3d03f43200000000,
    0x8d2a940f00000000, 0x9df6b4bd00000000, 0x2ddfd48000000000,
    0xfda574c700000000, 0x4d8c14fa00000000, 0x9c1b447800000000,
    0x2c32244500000000, 0xfc48840200000000, 0x4c61e43f00000000,
    0x5cbdc48d00000000, 0xec94a4b000000000, 0x3cee04f700000000,
    0x8cc764ca00000000},
   {0x0000000000000000, 0xa5d35ccb00000000, 0x0ba1c84d00000000,
    0xae72948600000000, 0x1642919b00000000, 0xb391cd5000000000,
    0x1de359d600000000, 0xb830051d00000000, 0x6d8253ec00000000,
    0xc8510f2700000000, 0x66239ba100000000, 0xc3f0c76a00000000,
    0x7bc0c27700000000, 0xde139ebc00000000, 0x70610a3a00000000,
    0xd5b256f100000000, 0x9b02d60300000000, 0x3ed18ac800000000,
    0x90a31e4e00000000, 0x3570428500000000, 0x8d40479800000000,
    0x28931b5300000000, 0x86e18fd500000000, 0x2332d31e00000000,
    0xf68085ef00000000, 0x5353d92400000000, 0xfd214da200000000,
    0x58f2116900000000, 0xe0c2147400000000, 0x451148bf00000000,
    0xeb63dc3900000000, 0x4eb080f200000000, 0x3605ac0700000000,
    0x93d6f0cc00000000, 0x3da4644a00000000, 0x9877388100000000,
    0x20473d9c00000000, 0x8594615700000000, 0x2be6f5d100000000,
    0x8e35a91a00000000, 0x5b87ffeb00000000, 0xfe54a32000000000,
    0x502637a600000000, 0xf5f56b6d00000000, 0x4dc56e7000000000,
    0xe81632bb00000000, 0x4664a63d00000000, 0xe3b7faf600000000,
    0xad077a0400000000, 0x08d426cf00000000, 0xa6a6b24900000000,
    0x0375ee8200000000, 0xbb45eb9f00000000, 0x1e96b75400000000,
    0xb0e423d200000000, 0x15377f1900000000, 0xc08529e800000000,
    0x6556752300000000, 0xcb24e1a500000000, 0x6ef7bd6e00000000,
    0xd6c7b87300000000, 0x7314e4b800000000, 0xdd66703e00000000,
    0x78b52cf500000000, 0x6c0a580f00000000, 0xc9d904c400000000,
    0x67ab904200000000, 0xc278cc8900000000, 0x7a48c99400000000,
    0xdf9b955f00000000, 0x71e901d900000000, 0xd43a5d1200000000,
    0x01880be300000000, 0xa45b572800000000, 0x0a29c3ae00000000,
    0xaffa9f6500000000, 0x17ca9a7800000000, 0xb219c6b300000000,
    0x1c6b523500000000, 0xb9b80efe00000000, 0xf7088e0c00000000,
    0x52dbd2c700000000, 0xfca9464100000000, 0x597a1a8a00000000,
    0xe14a1f9700000000, 0x4499435c00000000, 0xeaebd7da00000000,
    0x4f388b1100000000, 0x9a8adde000000000, 0x3f59812b00000000,
    0x912b15ad00000000, 0x34f8496600000000, 0x8cc84c7b00000000,
    0x291b10b000000000, 0x8769843600000000, 0x22bad8fd00000000,
    0x5a0ff40800000000, 0xffdca8c300000000, 0x51ae3c4500000000,
    0xf47d608e00000000, 0x4c4d659300000000, 0xe99e395800000000,
    0x47ecadde00000000, 0xe23ff11500000000, 0x378da7e400000000,
    0x925efb2f00000000, 0x3c2c6fa900000000, 0x99ff336200000000,
    0x21cf367f00000000, 0x841c6ab400000000, 0x2a6efe3200000000,
    0x8fbda2f900000000, 0xc10d220b00000000, 0x64de7ec000000000,
    0xcaacea4600000000, 0x6f7fb68d00000000, 0xd74fb39000000000,
    0x729cef5b00000000, 0xdcee7bdd00000000, 0x793d271600000000,
    0xac8f71e700000000, 0x095c2d2c00000000, 0xa72eb9aa00000000,
    0x02fde56100000000, 0xbacde07c00000000, 0x1f1ebcb700000000,
    0xb16c283100000000, 0x14bf74fa00000000, 0xd814b01e00000000,
    0x7dc7ecd500000000, 0xd3b5785300000000, 0x7666249800000000,
    0xce56218500000000, 0x6b857d4e00000000, 0xc5f7e9c800000000,
    0x6024b50300000000, 0xb596e3f200000000, 0x1045bf3900000000,
    0xbe372bbf00000000, 0x1be4777400000000, 0xa3d4726900000000,
    0x06072ea200000000, 0xa875ba2400000000, 0x0da6e6ef00000000,
    0x4316661d00000000, 0xe6c53ad600000000, 0x48b7ae5000000000,
    0xed64f29b00000000, 0x5554f78600000000, 0xf087ab4d00000000,
    0x5ef53fcb00000000, 0xfb26630000000000, 0x2e9435f100000000,
    0x8b47693a00000000, 0x2535fdbc00000000, 0x80e6a17700000000,
    0x38d6a46a00000000, 0x9d05f8a100000000, 0x33776c2700000000,
    0x96a430ec00000000, 0xee111c1900000000, 0x4bc240d200000000,
    0xe5b0d45400000000, 0x4063889f00000000, 0xf8538d8200000000,
    0x5d80d14900000000, 0xf3f245cf00000000, 0x5621190400000000,
    0x83934ff500000000, 0x2640133e00000000, 0x883287b800000000,
    0x2de1db7300000000, 0x95d1de6e00000000, 0x300282a500000000,
    0x9e70162300000000, 0x3ba34ae800000000, 0x7513ca1a00000000,
    0xd0c096d100000000, 0x7eb2025700000000, 0xdb615e9c00000000,
    0x63515b8100000000, 0xc682074a00000000, 0x68f093cc00000000,
    0xcd23cf0700000000, 0x189199f600000000, 0xbd42c53d00000000,
    0x133051bb00000000, 0xb6e30d7000000000, 0x0ed3086d00000000,
    0xab0054a600000000, 0x0572c02000000000, 0xa0a19ceb00000000,
    0xb41ee81100000000, 0x11cdb4da00000000, 0xbfbf205c00000000,
    0x1a6c7c9700000000, 0xa25c798a00000000, 0x078f254100000000,
    0xa9fdb1c700000000, 0x0c2eed0c00000000, 0xd99cbbfd00000000,
    0x7c4fe73600000000, 0xd23d73b000000000, 0x77ee2f7b00000000,
    0xcfde2a6600000000, 0x6a0d76ad00000000, 0xc47fe22b00000000,
    0x61acbee000000000, 0x2f1c3e1200000000, 0x8acf62d900000000,
    0x24bdf65f00000000, 0x816eaa9400000000, 0x395eaf8900000000,
    0x9c8df34200000000, 0x32ff67c400000000, 0x972c3b0f00000000,
    0x429e6dfe00000000, 0xe74d313500000000, 0x493fa5b300000000,
    0xececf97800000000, 0x54dcfc6500000000, 0xf10fa0ae00000000,
    0x5f7d342800000000, 0xfaae68e300000000, 0x821b441600000000,
    0x27c818dd00000000, 0x89ba8c5b00000000, 0x2c69d09000000000,
    0x9459d58d00000000, 0x318a894600000000, 0x9ff81dc000000000,
    0x3a2b410b00000000, 0xef9917fa00000000, 0x4a4a4b3100000000,
    0xe438dfb700000000, 0x41eb837c00000000, 0xf9db866100000000,
    0x5c08daaa00000000, 0xf27a4e2c00000000, 0x57a912e700000000,
    0x1919921500000000, 0xbccacede00000000, 0x12b85a5800000000,
    0xb76b069300000000, 0x0f5b038e00000000, 0xaa885f4500000000,
    0x04facbc300000000, 0xa129970800000000, 0x749bc1f900000000,
    0xd1489d3200000000, 0x7f3a09b400000000, 0xdae9557f00000000,
    0x62d9506200000000, 0xc70a0ca900000000, 0x6978982f00000000,
    0xccabc4e400000000},
   {0x0000000000000000, 0xb40b77a600000000, 0x29119f9700000000,
    0x9d1ae83100000000, 0x13244ff400000000, 0xa72f385200000000,
    0x3a35d06300000000, 0x8e3ea7c500000000, 0x674eef3300000000,
    0xd345989500000000, 0x4e5f70a400000000, 0xfa54070200000000,
    0x746aa0c700000000, 0xc061d76100000000, 0x5d7b3f5000000000,
    0xe97048f600000000, 0xce9cde6700000000, 0x7a97a9c100000000,
    0xe78d41f000000000, 0x5386365600000000, 0xddb8919300000000,
    0x69b3e63500000000, 0xf4a90e0400000000, 0x40a279a200000000,
    0xa9d2315400000000, 0x1dd946f200000000, 0x80c3aec300000000,
    0x34c8d96500000000, 0xbaf67ea000000000, 0x0efd090600000000,
    0x93e7e13700000000, 0x27ec969100000000, 0x9c39bdcf00000000,
    0x2832ca6900000000, 0xb528225800000000, 0x012355fe00000000,
    0x8f1df23b00000000, 0x3b16859d00000000, 0xa60c6dac00000000,
    0x12071a0a00000000, 0xfb7752fc00000000, 0x4f7c255a00000000,
    0xd266cd6b00000000, 0x666dbacd00000000, 0xe8531d0800000000,
    0x5c586aae00000000, 0xc142829f00000000, 0x7549f53900000000,
    0x52a563a800000000, 0xe6ae140e00000000, 0x7bb4fc3f00000000,
    0xcfbf8b9900000000, 0x41812c5c00000000, 0xf58a5bfa00000000,
    0x6890b3cb00000000, 0xdc9bc46d00000000, 0x35eb8c9b00000000,
    0x81e0fb3d00000000, 0x1cfa130c00000000, 0xa8f164aa00000000,
    0x26cfc36f00000000, 0x92c4b4c900000000, 0x0fde5cf800000000,
    0xbbd52b5e00000000, 0x79750b4400000000, 0xcd7e7ce200000000,
    0x506494d300000000, 0xe46fe37500000000, 0x6a5144b000000000,
    0xde5a331600000000, 0x4340db2700000000, 0xf74bac8100000000,
    0x1e3be47700000000, 0xaa3093d100000000, 0x372a7be000000000,
    0x83210c4600000000, 0x0d1fab8300000000, 0xb914dc2500000000,
    0x240e341400000000, 0x900543b200000000, 0xb7e9d52300000000,
    0x03e2a28500000000, 0x9ef84ab400000000, 0x2af33d1200000000,
    0xa4cd9ad700000000, 0x10c6ed7100000000, 0x8ddc054000000000,
    0x39d772e600000000, 0xd0a73a1000000000, 0x64ac4db600000000,
    0xf9b6a58700000000, 0x4dbdd22100000000, 0xc38375e400000000,
    0x7788024200000000, 0xea92ea7300000000, 0x5e999dd500000000,
    0xe54cb68b00000000, 0x5147c12d00000000, 0xcc5d291c00000000,
    0x78565eba00000000, 0xf668f97f00000000, 0x42638ed900000000,
    0xdf7966e800000000, 0x6b72114e00000000, 0x820259b800000000,
    0x36092e1e00000000, 0xab13c62f00000000, 0x1f18b18900000000,
    0x9126164c00000000, 0x252d61ea00000000, 0xb83789db00000000,
    0x0c3cfe7d00000000, 0x2bd068ec00000000, 0x9fdb1f4a00000000,
    0x02c1f77b00000000, 0xb6ca80dd00000000, 0x38f4271800000000,
    0x8cff50be00000000, 0x11e5b88f00000000, 0xa5eecf2900000000,
    0x4c9e87df00000000, 0xf895f07900000000, 0x658f184800000000,
    0xd1846fee00000000, 0x5fbac82b00000000, 0xebb1bf8d00000000,
    0x76ab57bc00000000, 0xc2a0201a00000000, 0xf2ea168800000000,
    0x46e1612e00000000, 0xdbfb891f00000000, 0x6ff0feb900000000,
    0xe1ce597c00000000, 0x55c52eda00000000, 0xc8dfc6eb00000000,
    0x7cd4b14d00000000, 0x95a4f9bb00000000, 0x21af8e1d00000000,
    0xbcb5662c00000000, 0x08be118a00000000, 0x8680b64f00000000,
    0x328bc1e900000000, 0xaf9129d800000000, 0x1b9a5e7e00000000,
    0x3c76c8ef00000000, 0x887dbf4900000000, 0x1567577800000000,
    0xa16c20de00000000, 0x2f52871b00000000, 0x9b59f0bd00000000,
    0x0643188c00000000, 0xb2486f2a00000000, 0x5b3827dc00000000,
    0xef33507a00000000, 0x7229b84b00000000, 0xc622cfed00000000,
    0x481c682800000000, 0xfc171f8e00000000, 0x610df7bf00000000,
    0xd506801900000000, 0x6ed3ab4700000000, 0xdad8dce100000000,
    0x47c234d000000000, 0xf3c9437600000000, 0x7df7e4b300000000,
    0xc9fc931500000000, 0x54e67b2400000000, 0xe0ed0c8200000000,
    0x099d447400000000, 0xbd9633d200000000, 0x208cdbe300000000,
    0x9487ac4500000000, 0x1ab90b8000000000, 0xaeb27c2600000000,
    0x33a8941700000000, 0x87a3e3b100000000, 0xa04f752000000000,
    0x1444028600000000, 0x895eeab700000000, 0x3d559d1100000000,
    0xb36b3ad400000000, 0x07604d7200000000, 0x9a7aa54300000000,
    0x2e71d2e500000000, 0xc7019a1300000000, 0x730aedb500000000,
    0xee10058400000000, 0x5a1b722200000000, 0xd425d5e700000000,
    0x602ea24100000000, 0xfd344a7000000000, 0x493f3dd600000000,
    0x8b9f1dcc00000000, 0x3f946a6a00000000, 0xa28e825b00000000,
    0x1685f5fd00000000, 0x98bb523800000000, 0x2cb0259e00000000,
    0xb1aacdaf00000000, 0x05a1ba0900000000, 0xecd1f2ff00000000,
    0x58da855900000000, 0xc5c06d6800000000, 0x71cb1ace00000000,
    0xfff5bd0b00000000, 0x4bfecaad00000000, 0xd6e4229c00000000,
    0x62ef553a00000000, 0x4503c3ab00000000, 0xf108b40d00000000,
    0x6c125c3c00000000, 0xd8192b9a00000000, 0x56278c5f00000000,
    0xe22cfbf900000000, 0x7f3613c800000000, 0xcb3d646e00000000,
    0x224d2c9800000000, 0x96465b3e00000000, 0x0b5cb30f00000000,
    0xbf57c4a900000000, 0x3169636c00000000, 0x856214ca00000000,
    0x1878fcfb00000000, 0xac738b5d00000000, 0x17a6a00300000000,
    0xa3add7a500000000, 0x3eb73f9400000000, 0x8abc483200000000,
    0x0482eff700000000, 0xb089985100000000, 0x2d93706000000000,
    0x999807c600000000, 0x70e84f3000000000, 0xc4e3389600000000,
    0x59f9d0a700000000, 0xedf2a70100000000, 0x63cc00c400000000,
    0xd7c7776200000000, 0x4add9f5300000000, 0xfed6e8f500000000,
    0xd93a7e6400000000, 0x6d3109c200000000, 0xf02be1f300000000,
    0x4420965500000000, 0xca1e319000000000, 0x7e15463600000000,
    0xe30fae0700000000, 0x5704d9a100000000, 0xbe74915700000000,
    0x0a7fe6f100000000, 0x97650ec000000000, 0x236e796600000000,
    0xad50dea300000000, 0x195ba90500000000, 0x8441413400000000,
    0x304a369200000000},
   {0x0000000000000000, 0x9e00aacc00000000, 0x7d07254200000000,
    0xe3078f8e00000000, 0xfa0e4a8400000000, 0x640ee04800000000,
    0x87096fc600000000, 0x1909c50a00000000, 0xb51be5d300000000,
    0x2b1b4f1f00000000, 0xc81cc09100000000, 0x561c6a5d00000000,
    0x4f15af5700000000, 0xd115059b00000000, 0x32128a1500000000,
    0xac1220d900000000, 0x2b31bb7c00000000, 0xb53111b000000000,
    0x56369e3e00000000, 0xc83634f200000000, 0xd13ff1f800000000,
    0x4f3f5b3400000000, 0xac38d4ba00000000, 0x32387e7600000000,
    0x9e2a5eaf00000000, 0x002af46300000000, 0xe32d7bed00000000,
    0x7d2dd12100000000, 0x6424142b00000000, 0xfa24bee700000000,
    0x1923316900000000, 0x87239ba500000000, 0x566276f900000000,
    0xc862dc3500000000, 0x2b6553bb00000000, 0xb565f97700000000,
    0xac6c3c7d00000000, 0x326c96b100000000, 0xd16b193f00000000,
    0x4f6bb3f300000000, 0xe379932a00000000, 0x7d7939e600000000,
    0x9e7eb66800000000, 0x007e1ca400000000, 0x1977d9ae00000000,
    0x8777736200000000, 0x6470fcec00000000, 0xfa70562000000000,
    0x7d53cd8500000000, 0xe353674900000000, 0x0054e8c700000000,
    0x9e54420b00000000, 0x875d870100000000, 0x195d2dcd00000000,
    0xfa5aa24300000000, 0x645a088f00000000, 0xc848285600000000,
    0x5648829a00000000, 0xb54f0d1400000000, 0x2b4fa7d800000000,
    0x324662d200000000, 0xac46c81e00000000, 0x4f41479000000000,
    0xd141ed5c00000000, 0xedc29d2900000000, 0x73c237e500000000,
    0x90c5b86b00000000, 0x0ec512a700000000, 0x17ccd7ad00000000,
    0x89cc7d6100000000, 0x6acbf2ef00000000, 0xf4cb582300000000,
    0x58d978fa00000000, 0xc6d9d23600000000, 0x25de5db800000000,
    0xbbdef77400000000, 0xa2d7327e00000000, 0x3cd798b200000000,
    0xdfd0173c00000000, 0x41d0bdf000000000, 0xc6f3265500000000,
    0x58f38c9900000000, 0xbbf4031700000000, 0x25f4a9db00000000,
    0x3cfd6cd100000000, 0xa2fdc61d00000000, 0x41fa499300000000,
    0xdffae35f00000000, 0x73e8c38600000000, 0xede8694a00000000,
    0x0eefe6c400000000, 0x90ef4c0800000000, 0x89e6890200000000,
    0x17e623ce00000000, 0xf4e1ac4000000000, 0x6ae1068c00000000,
    0xbba0ebd000000000, 0x25a0411c00000000, 0xc6a7ce9200000000,
    0x58a7645e00000000, 0x41aea15400000000, 0xdfae0b9800000000,
    0x3ca9841600000000, 0xa2a92eda00000000, 0x0ebb0e0300000000,
    0x90bba4cf00000000, 0x73bc2b4100000000, 0xedbc818d00000000,
    0xf4b5448700000000, 0x6ab5ee4b00000000, 0x89b261c500000000,
    0x17b2cb0900000000, 0x909150ac00000000, 0x0e91fa6000000000,
    0xed9675ee00000000, 0x7396df2200000000, 0x6a9f1a2800000000,
    0xf49fb0e400000000, 0x17983f6a00000000, 0x899895a600000000,
    0x258ab57f00000000, 0xbb8a1fb300000000, 0x588d903d00000000,
    0xc68d3af100000000, 0xdf84fffb00000000, 0x4184553700000000,
    0xa283dab900000000, 0x3c83707500000000, 0xda853b5300000000,
    0x4485919f00000000, 0xa7821e1100000000, 0x3982b4dd00000000,
    0x208b71d700000000, 0xbe8bdb1b00000000, 0x5d8c549500000000,
    0xc38cfe5900000000, 0x6f9ede8000000000, 0xf19e744c00000000,
    0x1299fbc200000000, 0x8c99510e00000000, 0x9590940400000000,
    0x0b903ec800000000, 0xe897b14600000000, 0x76971b8a00000000,
    0xf1b4802f00000000, 0x6fb42ae300000000, 0x8cb3a56d00000000,
    0x12b30fa100000000, 0x0bbacaab00000000, 0x95ba606700000000,
    0x76bdefe900000000, 0xe8bd452500000000, 0x44af65fc00000000,
    0xdaafcf3000000000, 0x39a840be00000000, 0xa7a8ea7200000000,
    0xbea12f7800000000, 0x20a185b400000000, 0xc3a60a3a00000000,
    0x5da6a0f600000000, 0x8ce74daa00000000, 0x12e7e76600000000,
    0xf1e068e800000000, 0x6fe0c22400000000, 0x76e9072e00000000,
    0xe8e9ade200000000, 0x0bee226c00000000, 0x95ee88a000000000,
    0x39fca87900000000, 0xa7fc02b500000000, 0x44fb8d3b00000000,
    0xdafb27f700000000, 0xc3f2e2fd00000000, 0x5df2483100000000,
    0xbef5c7bf00000000, 0x20f56d7300000000, 0xa7d6f6d600000000,
    0x39d65c1a00000000, 0xdad1d39400000000, 0x44d1795800000000,
    0x5dd8bc5200000000, 0xc3d8169e00000000, 0x20df991000000000,
    0xbedf33dc00000000, 0x12cd130500000000, 0x8ccdb9c900000000,
    0x6fca364700000000, 0xf1ca9c8b00000000, 0xe8c3598100000000,
    0x76c3f34d00000000, 0x95c47cc300000000, 0x0bc4d60f00000000,
    0x3747a67a00000000, 0xa9470cb600000000, 0x4a40833800000000,
    0xd44029f400000000, 0xcd49ecfe00000000, 0x5349463200000000,
    0xb04ec9bc00000000, 0x2e4e637000000000, 0x825c43a900000000,
    0x1c5ce96500000000, 0xff5b66eb00000000, 0x615bcc2700000000,
    0x7852092d00000000, 0xe652a3e100000000, 0x05552c6f00000000,
    0x9b5586a300000000, 0x1c761d0600000000, 0x8276b7ca00000000,
    0x6171384400000000, 0xff71928800000000, 0xe678578200000000,
    0x7878fd4e00000000, 0x9b7f72c000000000, 0x057fd80c00000000,
    0xa96df8d500000000, 0x376d521900000000, 0xd46add9700000000,
    0x4a6a775b00000000, 0x5363b25100000000, 0xcd63189d00000000,
    0x2e64971300000000, 0xb0643ddf00000000, 0x6125d08300000000,
    0xff257a4f00000000, 0x1c22f5c100000000, 0x82225f0d00000000,
    0x9b2b9a0700000000, 0x052b30cb00000000, 0xe62cbf4500000000,
    0x782c158900000000, 0xd43e355000000000, 0x4a3e9f9c00000000,
    0xa939101200000000, 0x3739bade00000000, 0x2e307fd400000000,
    0xb030d51800000000, 0x53375a9600000000, 0xcd37f05a00000000,
    0x4a146bff00000000, 0xd414c13300000000, 0x37134ebd00000000,
    0xa913e47100000000, 0xb01a217b00000000, 0x2e1a8bb700000000,
    0xcd1d043900000000, 0x531daef500000000, 0xff0f8e2c00000000,
    0x610f24e000000000, 0x8208ab6e00000000, 0x1c0801a200000000,
    0x0501c4a800000000, 0x9b016e6400000000, 0x7806e1ea00000000,
    0xe6064b2600000000}};

#else /* W == 4 */

    0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
    0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
    0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
    0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
    0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
    0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
    0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
    0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
    0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
    0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
    0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
    0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
    0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
    0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
    0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
    0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
    0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
    0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
    0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
    0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
    0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
    0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
    0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
    0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
    0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
    0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
    0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
    0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
    0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
    0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
    0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
    0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
    0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
    0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
    0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
    0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
    0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
    0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
    0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
    0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
    0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
    0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
    0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
    0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
    0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
    0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
    0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
    0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
    0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
    0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
    0x9324fd72UL
  },
local const z_crc_t FAR crc_braid_table[][256] = {
   {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757,
    0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a,
    0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733,
    0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
    0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70,
    0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42,
    0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5,
    0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
    0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086,
    0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4,
    0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d,
    0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
    0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d,
    0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f,
    0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859,
    0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
    0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5,
    0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028,
    0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891,
    0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
    0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec,
    0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde,
    0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817,
    0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
    0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24,
    0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e,
    0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7,
    0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
    0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4,
    0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196,
    0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0,
    0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
    0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52,
    0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f,
    0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36,
    0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
    0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675,
    0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647,
    0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d,
    0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
    0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be,
    0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc,
    0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645,
    0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
    0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138,
    0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a,
    0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c,
    0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
    0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0,
    0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d,
    0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194,
    0xde0506f1},
   {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc,
    0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f,
    0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a,
    0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
    0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8,
    0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023,
    0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e,
    0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
    0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84,
    0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7,
    0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922,
    0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
    0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0,
    0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b,
    0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816,
    0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
    0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c,
    0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f,
    0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba,
    0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
    0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98,
    0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873,
    0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e,
    0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
    0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134,
    0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7,
    0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732,
    0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
    0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0,
    0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b,
    0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26,
    0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
    0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc,
    0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef,
    0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a,
    0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
    0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8,
    0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43,
    0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e,
    0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
    0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24,
    0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07,
    0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982,
    0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
    0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0,
    0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b,
    0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576,
    0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
    0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c,
    0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f,
    0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda,
    0xbe9834ed},
   {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504,
    0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49,
    0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e,
    0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
    0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859,
    0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c,
    0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620,
    0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
    0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae,
    0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2,
    0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175,
    0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
    0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05,
    0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40,
    0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f,
    0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
    0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850,
    0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d,
    0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da,
    0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
    0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af,
    0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea,
    0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74,
    0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
    0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa,
    0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a,
    0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd,
    0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
    0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a,
    0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f,
    0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290,
    0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
    0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed,
    0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0,
    0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167,
    0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
    0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0,
    0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5,
    0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc,
    0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
    0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842,
    0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e,
    0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299,
    0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
    0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec,
    0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9,
    0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66,
    0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
    0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9,
    0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4,
    0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33,
    0x9324fd72},
   {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
    0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
    0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
    0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
    0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
    0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
    0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
    0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
    0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
    0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
    0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
    0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
    0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
    0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
    0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
    0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
    0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
    0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
    0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
    0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
    0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
    0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
    0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
    0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
    0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
    0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
    0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
    0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
    0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
    0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
    0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
    0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
    0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
    0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
    0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
    0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
    0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
    0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
    0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
    0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
    0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
    0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
    0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
    0x2d02ef8d}};

local const z_word_t FAR crc_braid_big_table[][256] = {
   {0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07,
    0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79,
    0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7,
    0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84,
    0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13,
    0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663,
    0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5,
    0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5,
    0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832,
    0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51,
    0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf,
    0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1,
    0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76,
    0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606,
    0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996,
    0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6,
    0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c,
    0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712,
    0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c,
    0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4,
    0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943,
    0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333,
    0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe,
    0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce,
    0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359,
    0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a,
    0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04,
    0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a,
    0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0,
    0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580,
    0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10,
    0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060,
    0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1,
    0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf,
    0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31,
    0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852,
    0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5,
    0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5,
    0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75,
    0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005,
    0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292,
    0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1,
    0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f,
    0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111,
    0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0,
    0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0,
    0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40,
    0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530,
    0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba,
    0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4,
    0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a,
    0x8def022d},
   {0x00000000, 0x41311b19, 0x82623632, 0xc3532d2b, 0x04c56c64,
    0x45f4777d, 0x86a75a56, 0xc796414f, 0x088ad9c8, 0x49bbc2d1,
    0x8ae8effa, 0xcbd9f4e3, 0x0c4fb5ac, 0x4d7eaeb5, 0x8e2d839e,
    0xcf1c9887, 0x5112c24a, 0x1023d953, 0xd370f478, 0x9241ef61,
    0x55d7ae2e, 0x14e6b537, 0xd7b5981c, 0x96848305, 0x59981b82,
    0x18a9009b, 0xdbfa2db0, 0x9acb36a9, 0x5d5d77e6, 0x1c6c6cff,
    0xdf3f41d4, 0x9e0e5acd, 0xa2248495, 0xe3159f8c, 0x2046b2a7,
    0x6177a9be, 0xa6e1e8f1, 0xe7d0f3e8, 0x2483dec3, 0x65b2c5da,
    0xaaae5d5d, 0xeb9f4644, 0x28cc6b6f, 0x69fd7076, 0xae6b3139,
    0xef5a2a20, 0x2c09070b, 0x6d381c12, 0xf33646df, 0xb2075dc6,
    0x715470ed, 0x30656bf4, 0xf7f32abb, 0xb6c231a2, 0x75911c89,
    0x34a00790, 0xfbbc9f17, 0xba8d840e, 0x79dea925, 0x38efb23c,
    0xff79f373, 0xbe48e86a, 0x7d1bc541, 0x3c2ade58, 0x054f79f0,
    0x447e62e9, 0x872d4fc2, 0xc61c54db, 0x018a1594, 0x40bb0e8d,
    0x83e823a6, 0xc2d938bf, 0x0dc5a038, 0x4cf4bb21, 0x8fa7960a,
    0xce968d13, 0x0900cc5c, 0x4831d745, 0x8b62fa6e, 0xca53e177,
    0x545dbbba, 0x156ca0a3, 0xd63f8d88, 0x970e9691, 0x5098d7de,
    0x11a9ccc7, 0xd2fae1ec, 0x93cbfaf5, 0x5cd76272, 0x1de6796b,
    0xdeb55440, 0x9f844f59, 0x58120e16, 0x1923150f, 0xda703824,
    0x9b41233d, 0xa76bfd65, 0xe65ae67c, 0x2509cb57, 0x6438d04e,
    0xa3ae9101, 0xe29f8a18, 0x21cca733, 0x60fdbc2a, 0xafe124ad,
    0xeed03fb4, 0x2d83129f, 0x6cb20986, 0xab2448c9, 0xea1553d0,
    0x29467efb, 0x687765e2, 0xf6793f2f, 0xb7482436, 0x741b091d,
    0x352a1204, 0xf2bc534b, 0xb38d4852, 0x70de6579, 0x31ef7e60,
    0xfef3e6e7, 0xbfc2fdfe, 0x7c91d0d5, 0x3da0cbcc, 0xfa368a83,
    0xbb07919a, 0x7854bcb1, 0x3965a7a8, 0x4b98833b, 0x0aa99822,
    0xc9fab509, 0x88cbae10, 0x4f5def5f, 0x0e6cf446, 0xcd3fd96d,
    0x8c0ec274, 0x43125af3, 0x022341ea, 0xc1706cc1, 0x804177d8,
    0x47d73697, 0x06e62d8e, 0xc5b500a5, 0x84841bbc, 0x1a8a4171,
    0x5bbb5a68, 0x98e87743, 0xd9d96c5a, 0x1e4f2d15, 0x5f7e360c,
    0x9c2d1b27, 0xdd1c003e, 0x120098b9, 0x533183a0, 0x9062ae8b,
    0xd153b592, 0x16c5f4dd, 0x57f4efc4, 0x94a7c2ef, 0xd596d9f6,
    0xe9bc07ae, 0xa88d1cb7, 0x6bde319c, 0x2aef2a85, 0xed796bca,
    0xac4870d3, 0x6f1b5df8, 0x2e2a46e1, 0xe136de66, 0xa007c57f,
    0x6354e854, 0x2265f34d, 0xe5f3b202, 0xa4c2a91b, 0x67918430,
    0x26a09f29, 0xb8aec5e4, 0xf99fdefd, 0x3accf3d6, 0x7bfde8cf,
    0xbc6ba980, 0xfd5ab299, 0x3e099fb2, 0x7f3884ab, 0xb0241c2c,
    0xf1150735, 0x32462a1e, 0x73773107, 0xb4e17048, 0xf5d06b51,
    0x3683467a, 0x77b25d63, 0x4ed7facb, 0x0fe6e1d2, 0xccb5ccf9,
    0x8d84d7e0, 0x4a1296af, 0x0b238db6, 0xc870a09d, 0x8941bb84,
    0x465d2303, 0x076c381a, 0xc43f1531, 0x850e0e28, 0x42984f67,
    0x03a9547e, 0xc0fa7955, 0x81cb624c, 0x1fc53881, 0x5ef42398,
    0x9da70eb3, 0xdc9615aa, 0x1b0054e5, 0x5a314ffc, 0x996262d7,
    0xd85379ce, 0x174fe149, 0x567efa50, 0x952dd77b, 0xd41ccc62,
    0x138a8d2d, 0x52bb9634, 0x91e8bb1f, 0xd0d9a006, 0xecf37e5e,
    0xadc26547, 0x6e91486c, 0x2fa05375, 0xe836123a, 0xa9070923,
    0x6a542408, 0x2b653f11, 0xe479a796, 0xa548bc8f, 0x661b91a4,
    0x272a8abd, 0xe0bccbf2, 0xa18dd0eb, 0x62defdc0, 0x23efe6d9,
    0xbde1bc14, 0xfcd0a70d, 0x3f838a26, 0x7eb2913f, 0xb924d070,
    0xf815cb69, 0x3b46e642, 0x7a77fd5b, 0xb56b65dc, 0xf45a7ec5,
    0x370953ee, 0x763848f7, 0xb1ae09b8, 0xf09f12a1, 0x33cc3f8a,
    0x72fd2493},
   {0x00000000, 0x376ac201, 0x6ed48403, 0x59be4602, 0xdca80907,
    0xebc2cb06, 0xb27c8d04, 0x85164f05, 0xb851130e, 0x8f3bd10f,
    0xd685970d, 0xe1ef550c, 0x64f91a09, 0x5393d808, 0x0a2d9e0a,
    0x3d475c0b, 0x70a3261c, 0x47c9e41d, 0x1e77a21f, 0x291d601e,
    0xac0b2f1b, 0x9b61ed1a, 0xc2dfab18, 0xf5b56919, 0xc8f23512,
    0xff98f713, 0xa626b111, 0x914c7310, 0x145a3c15, 0x2330fe14,
    0x7a8eb816, 0x4de47a17, 0xe0464d38, 0xd72c8f39, 0x8e92c93b,
    0xb9f80b3a, 0x3cee443f, 0x0b84863e, 0x523ac03c, 0x6550023d,
    0x58175e36, 0x6f7d9c37, 0x36c3da35, 0x01a91834, 0x84bf5731,
    0xb3d59530, 0xea6bd332, 0xdd011133, 0x90e56b24, 0xa78fa925,
    0xfe31ef27, 0xc95b2d26, 0x4c4d6223, 0x7b27a022, 0x2299e620,
    0x15f32421, 0x28b4782a, 0x1fdeba2b, 0x4660fc29, 0x710a3e28,
    0xf41c712d, 0xc376b32c, 0x9ac8f52e, 0xada2372f, 0xc08d9a70,
    0xf7e75871, 0xae591e73, 0x9933dc72, 0x1c259377, 0x2b4f5176,
    0x72f11774, 0x459bd575, 0x78dc897e, 0x4fb64b7f, 0x16080d7d,
    0x2162cf7c, 0xa4748079, 0x931e4278, 0xcaa0047a, 0xfdcac67b,
    0xb02ebc6c, 0x87447e6d, 0xdefa386f, 0xe990fa6e, 0x6c86b56b,
    0x5bec776a, 0x02523168, 0x3538f369, 0x087faf62, 0x3f156d63,
    0x66ab2b61, 0x51c1e960, 0xd4d7a665, 0xe3bd6464, 0xba032266,
    0x8d69e067, 0x20cbd748, 0x17a11549, 0x4e1f534b, 0x7975914a,
    0xfc63de4f, 0xcb091c4e, 0x92b75a4c, 0xa5dd984d, 0x989ac446,
    0xaff00647, 0xf64e4045, 0xc1248244, 0x4432cd41, 0x73580f40,
    0x2ae64942, 0x1d8c8b43, 0x5068f154, 0x67023355, 0x3ebc7557,
    0x09d6b756, 0x8cc0f853, 0xbbaa3a52, 0xe2147c50, 0xd57ebe51,
    0xe839e25a, 0xdf53205b, 0x86ed6659, 0xb187a458, 0x3491eb5d,
    0x03fb295c, 0x5a456f5e, 0x6d2fad5f, 0x801b35e1, 0xb771f7e0,
    0xeecfb1e2, 0xd9a573e3, 0x5cb33ce6, 0x6bd9fee7, 0x3267b8e5,
    0x050d7ae4, 0x384a26ef, 0x0f20e4ee, 0x569ea2ec, 0x61f460ed,
    0xe4e22fe8, 0xd388ede9, 0x8a36abeb, 0xbd5c69ea, 0xf0b813fd,
    0xc7d2d1fc, 0x9e6c97fe, 0xa90655ff, 0x2c101afa, 0x1b7ad8fb,
    0x42c49ef9, 0x75ae5cf8, 0x48e900f3, 0x7f83c2f2, 0x263d84f0,
    0x115746f1, 0x944109f4, 0xa32bcbf5, 0xfa958df7, 0xcdff4ff6,
    0x605d78d9, 0x5737bad8, 0x0e89fcda, 0x39e33edb, 0xbcf571de,
    0x8b9fb3df, 0xd221f5dd, 0xe54b37dc, 0xd80c6bd7, 0xef66a9d6,
    0xb6d8efd4, 0x81b22dd5, 0x04a462d0, 0x33cea0d1, 0x6a70e6d3,
    0x5d1a24d2, 0x10fe5ec5, 0x27949cc4, 0x7e2adac6, 0x494018c7,
    0xcc5657c2, 0xfb3c95c3, 0xa282d3c1, 0x95e811c0, 0xa8af4dcb,
    0x9fc58fca, 0xc67bc9c8, 0xf1110bc9, 0x740744cc, 0x436d86cd,
    0x1ad3c0cf, 0x2db902ce, 0x4096af91, 0x77fc6d90, 0x2e422b92,
    0x1928e993, 0x9c3ea696, 0xab546497, 0xf2ea2295, 0xc580e094,
    0xf8c7bc9f, 0xcfad7e9e, 0x9613389c, 0xa179fa9d, 0x246fb598,
    0x13057799, 0x4abb319b, 0x7dd1f39a, 0x3035898d, 0x075f4b8c,
    0x5ee10d8e, 0x698bcf8f, 0xec9d808a, 0xdbf7428b, 0x82490489,
    0xb523c688, 0x88649a83, 0xbf0e5882, 0xe6b01e80, 0xd1dadc81,
    0x54cc9384, 0x63a65185, 0x3a181787, 0x0d72d586, 0xa0d0e2a9,
    0x97ba20a8, 0xce0466aa, 0xf96ea4ab, 0x7c78ebae, 0x4b1229af,
    0x12ac6fad, 0x25c6adac, 0x1881f1a7, 0x2feb33a6, 0x765575a4,
    0x413fb7a5, 0xc429f8a0, 0xf3433aa1, 0xaafd7ca3, 0x9d97bea2,
    0xd073c4b5, 0xe71906b4, 0xbea740b6, 0x89cd82b7, 0x0cdbcdb2,
    0x3bb10fb3, 0x620f49b1, 0x55658bb0, 0x6822d7bb, 0x5f4815ba,
    0x06f653b8, 0x319c91b9, 0xb48adebc, 0x83e01cbd, 0xda5e5abf,
    0xed3498be},
   {0x00000000, 0x6567bcb8, 0x8bc809aa, 0xeeafb512, 0x5797628f,
    0x32f0de37, 0xdc5f6b25, 0xb938d79d, 0xef28b4c5, 0x8a4f087d,
    0x64e0bd6f, 0x018701d7, 0xb8bfd64a, 0xddd86af2, 0x3377dfe0,
    0x56106358, 0x9f571950, 0xfa30a5e8, 0x149f10fa, 0x71f8ac42,
    0xc8c07bdf, 0xada7c767, 0x43087275, 0x266fcecd, 0x707fad95,
    0x1518112d, 0xfbb7a43f, 0x9ed01887, 0x27e8cf1a, 0x428f73a2,
    0xac20c6b0, 0xc9477a08, 0x3eaf32a0, 0x5bc88e18, 0xb5673b0a,
    0xd00087b2, 0x6938502f, 0x0c5fec97, 0xe2f05985, 0x8797e53d,
    0xd1878665, 0xb4e03add, 0x5a4f8fcf, 0x3f283377, 0x8610e4ea,
    0xe3775852, 0x0dd8ed40, 0x68bf51f8, 0xa1f82bf0, 0xc49f9748,
    0x2a30225a, 0x4f579ee2, 0xf66f497f, 0x9308f5c7, 0x7da740d5,
    0x18c0fc6d, 0x4ed09f35, 0x2bb7238d, 0xc518969f, 0xa07f2a27,
    0x1947fdba, 0x7c204102, 0x928ff410, 0xf7e848a8, 0x3d58149b,
    0x583fa823, 0xb6901d31, 0xd3f7a189, 0x6acf7614, 0x0fa8caac,
    0xe1077fbe, 0x8460c306, 0xd270a05e, 0xb7171ce6, 0x59b8a9f4,
    0x3cdf154c, 0x85e7c2d1, 0xe0807e69, 0x0e2fcb7b, 0x6b4877c3,
    0xa20f0dcb, 0xc768b173, 0x29c70461, 0x4ca0b8d9, 0xf5986f44,
    0x90ffd3fc, 0x7e5066ee, 0x1b37da56, 0x4d27b90e, 0x284005b6,
    0xc6efb0a4, 0xa3880c1c, 0x1ab0db81, 0x7fd76739, 0x9178d22b,
    0xf41f6e93, 0x03f7263b, 0x66909a83, 0x883f2f91, 0xed589329,
    0x546044b4, 0x3107f80c, 0xdfa84d1e, 0xbacff1a6, 0xecdf92fe,
    0x89b82e46, 0x67179b54, 0x027027ec, 0xbb48f071, 0xde2f4cc9,
    0x3080f9db, 0x55e74563, 0x9ca03f6b, 0xf9c783d3, 0x176836c1,
    0x720f8a79, 0xcb375de4, 0xae50e15c, 0x40ff544e, 0x2598e8f6,
    0x73888bae, 0x16ef3716, 0xf8408204, 0x9d273ebc, 0x241fe921,
    0x41785599, 0xafd7e08b, 0xcab05c33, 0x3bb659ed, 0x5ed1e555,
    0xb07e5047, 0xd519ecff, 0x6c213b62, 0x094687da, 0xe7e932c8,
    0x828e8e70, 0xd49eed28, 0xb1f95190, 0x5f56e482, 0x3a31583a,
    0x83098fa7, 0xe66e331f, 0x08c1860d, 0x6da63ab5, 0xa4e140bd,
    0xc186fc05, 0x2f294917, 0x4a4ef5af, 0xf3762232, 0x96119e8a,
    0x78be2b98, 0x1dd99720, 0x4bc9f478, 0x2eae48c0, 0xc001fdd2,
    0xa566416a, 0x1c5e96f7, 0x79392a4f, 0x97969f5d, 0xf2f123e5,
    0x05196b4d, 0x607ed7f5, 0x8ed162e7, 0xebb6de5f, 0x528e09c2,
    0x37e9b57a, 0xd9460068, 0xbc21bcd0, 0xea31df88, 0x8f566330,
    0x61f9d622, 0x049e6a9a, 0xbda6bd07, 0xd8c101bf, 0x366eb4ad,
    0x53090815, 0x9a4e721d, 0xff29cea5, 0x11867bb7, 0x74e1c70f,
    0xcdd91092, 0xa8beac2a, 0x46111938, 0x2376a580, 0x7566c6d8,
    0x10017a60, 0xfeaecf72, 0x9bc973ca, 0x22f1a457, 0x479618ef,
    0xa939adfd, 0xcc5e1145, 0x06ee4d76, 0x6389f1ce, 0x8d2644dc,
    0xe841f864, 0x51792ff9, 0x341e9341, 0xdab12653, 0xbfd69aeb,
    0xe9c6f9b3, 0x8ca1450b, 0x620ef019, 0x07694ca1, 0xbe519b3c,
    0xdb362784, 0x35999296, 0x50fe2e2e, 0x99b95426, 0xfcdee89e,
    0x12715d8c, 0x7716e134, 0xce2e36a9, 0xab498a11, 0x45e63f03,
    0x208183bb, 0x7691e0e3, 0x13f65c5b, 0xfd59e949, 0x983e55f1,
    0x2106826c, 0x44613ed4, 0xaace8bc6, 0xcfa9377e, 0x38417fd6,
    0x5d26c36e, 0xb389767c, 0xd6eecac4, 0x6fd61d59, 0x0ab1a1e1,
    0xe41e14f3, 0x8179a84b, 0xd769cb13, 0xb20e77ab, 0x5ca1c2b9,
    0x39c67e01, 0x80fea99c, 0xe5991524, 0x0b36a036, 0x6e511c8e,
    0xa7166686, 0xc271da3e, 0x2cde6f2c, 0x49b9d394, 0xf0810409,
    0x95e6b8b1, 0x7b490da3, 0x1e2eb11b, 0x483ed243, 0x2d596efb,
    0xc3f6dbe9, 0xa6916751, 0x1fa9b0cc, 0x7ace0c74, 0x9461b966,
    0xf10605de}};

#endif

#endif

#if N == 2

#if W == 8

local const z_crc_t FAR crc_braid_table[][256] = {
   {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87,
    0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede,
    0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab,
    0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c,
    0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1,
    0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7,
    0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e,
    0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308,
    0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5,
    0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472,
    0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07,
    0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e,
    0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa,
    0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec,
    0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6,
    0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0,
    0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3,
    0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba,
    0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf,
    0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975,
    0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8,
    0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde,
    0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a,
    0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c,
    0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1,
    0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65,
    0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410,
    0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649,
    0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a,
    0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c,
    0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946,
    0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450,
    0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e,
    0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857,
    0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022,
    0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5,
    0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758,
    0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e,
    0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d,
    0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b,
    0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6,
    0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401,
    0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74,
    0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d,
    0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073,
    0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65,
    0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f,
    0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749,
    0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a,
    0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033,
    0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846,
    0x0d7139d7},
   {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563,
    0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f,
    0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875,
    0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536,
    0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8,
    0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43,
    0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f,
    0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184,
    0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a,
    0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39,
    0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523,
    0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f,
    0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d,
    0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6,
    0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b,
    0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0,
    0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151,
    0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d,
    0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47,
    0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a,
    0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964,
    0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef,
    0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d,
    0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6,
    0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348,
    0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53,
    0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449,
    0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645,
    0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4,
    0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f,
    0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2,
    0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69,
    0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46,
    0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a,
    0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650,
    0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13,
    0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded,
    0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366,
    0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57,
    0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc,
    0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222,
    0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61,
    0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b,
    0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277,
    0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558,
    0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3,
    0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e,
    0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5,
    0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74,
    0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78,
    0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262,
    0x1c53e98a},
   {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b,
    0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40,
    0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580,
    0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7,
    0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a,
    0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37,
    0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75,
    0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218,
    0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5,
    0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2,
    0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02,
    0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59,
    0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1,
    0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c,
    0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a,
    0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307,
    0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486,
    0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd,
    0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d,
    0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2,
    0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f,
    0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72,
    0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8,
    0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985,
    0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268,
    0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94,
    0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454,
    0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f,
    0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e,
    0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3,
    0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915,
    0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778,
    0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821,
    0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a,
    0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba,
    0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d,
    0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560,
    0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d,
    0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe,
    0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3,
    0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e,
    0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509,
    0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9,
    0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92,
    0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb,
    0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6,
    0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50,
    0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d,
    0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc,
    0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7,
    0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927,
    0x3f88e851},
   {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96,
    0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8,
    0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0,
    0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14,
    0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7,
    0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4,
    0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe,
    0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad,
    0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e,
    0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa,
    0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2,
    0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c,
    0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab,
    0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8,
    0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d,
    0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e,
    0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7,
    0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99,
    0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1,
    0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690,
    0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933,
    0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20,
    0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf,
    0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc,
    0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f,
    0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92,
    0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca,
    0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4,
    0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd,
    0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de,
    0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb,
    0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8,
    0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474,
    0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a,
    0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252,
    0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6,
    0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55,
    0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846,
    0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7,
    0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4,
    0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47,
    0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3,
    0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb,
    0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5,
    0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49,
    0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a,
    0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f,
    0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c,
    0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305,
    0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b,
    0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523,
    0x3dee8ca6},
   {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f,
    0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91,
    0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e,
    0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c,
    0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02,
    0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12,
    0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567,
    0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277,
    0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679,
    0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b,
    0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4,
    0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a,
    0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0,
    0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0,
    0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91,
    0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881,
    0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173,
    0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d,
    0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912,
    0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8,
    0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6,
    0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6,
    0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b,
    0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b,
    0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75,
    0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f,
    0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00,
    0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee,
    0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c,
    0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c,
    0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d,
    0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d,
    0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67,
    0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89,
    0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706,
    0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14,
    0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a,
    0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a,
    0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f,
    0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f,
    0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591,
    0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983,
    0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c,
    0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2,
    0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8,
    0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8,
    0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89,
    0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99,
    0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b,
    0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485,
    0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a,
    0x36197165},
   {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382,
    0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85,
    0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06,
    0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca,
    0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e,
    0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc,
    0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616,
    0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54,
    0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10,
    0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc,
    0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f,
    0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58,
    0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef,
    0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad,
    0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b,
    0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29,
    0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6,
    0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1,
    0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622,
    0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039,
    0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d,
    0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f,
    0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32,
    0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770,
    0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034,
    0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f,
    0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc,
    0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db,
    0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154,
    0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16,
    0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0,
    0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592,
    0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca,
    0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd,
    0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e,
    0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882,
    0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6,
    0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384,
    0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1,
    0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3,
    0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7,
    0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b,
    0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8,
    0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff,
    0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7,
    0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5,
    0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23,
    0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761,
    0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee,
    0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9,
    0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a,
    0x1a3b93aa},
   {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a,
    0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca,
    0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3,
    0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb,
    0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c,
    0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58,
    0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed,
    0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9,
    0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e,
    0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906,
    0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f,
    0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf,
    0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0,
    0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4,
    0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769,
    0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d,
    0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632,
    0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82,
    0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb,
    0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73,
    0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484,
    0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0,
    0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5,
    0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1,
    0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516,
    0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f,
    0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946,
    0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6,
    0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9,
    0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad,
    0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820,
    0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364,
    0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab,
    0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b,
    0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62,
    0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a,
    0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd,
    0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089,
    0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c,
    0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8,
    0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f,
    0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477,
    0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e,
    0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be,
    0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71,
    0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635,
    0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8,
    0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc,
    0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3,
    0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753,
    0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a,
    0xe147d714},
   {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c,
    0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b,
    0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92,
    0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4,
    0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069,
    0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526,
    0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25,
    0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a,
    0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7,
    0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491,
    0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958,
    0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f,
    0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307,
    0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648,
    0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999,
    0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6,
    0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a,
    0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d,
    0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4,
    0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61,
    0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc,
    0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3,
    0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53,
    0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c,
    0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1,
    0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c,
    0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5,
    0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92,
    0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e,
    0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771,
    0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0,
    0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def,
    0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0,
    0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7,
    0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e,
    0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58,
    0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285,
    0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca,
    0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce,
    0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81,
    0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c,
    0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a,
    0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3,
    0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4,
    0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb,
    0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4,
    0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75,
    0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a,
    0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296,
    0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1,
    0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808,
    0x494f0c4b}};

local const z_word_t FAR crc_braid_big_table[][256] = {
   {0x0000000000000000, 0x43147b1700000000, 0x8628f62e00000000,
    0xc53c8d3900000000, 0x0c51ec5d00000000, 0x4f45974a00000000,
    0x8a791a7300000000, 0xc96d616400000000, 0x18a2d8bb00000000,
    0x5bb6a3ac00000000, 0x9e8a2e9500000000, 0xdd9e558200000000,
    0x14f334e600000000, 0x57e74ff100000000, 0x92dbc2c800000000,
    0xd1cfb9df00000000, 0x7142c0ac00000000, 0x3256bbbb00000000,
    0xf76a368200000000, 0xb47e4d9500000000, 0x7d132cf100000000,
    0x3e0757e600000000, 0xfb3bdadf00000000, 0xb82fa1c800000000,
    0x69e0181700000000, 0x2af4630000000000, 0xefc8ee3900000000,
    0xacdc952e00000000, 0x65b1f44a00000000, 0x26a58f5d00000000,
    0xe399026400000000, 0xa08d797300000000, 0xa382f18200000000,
    0xe0968a9500000000, 0x25aa07ac00000000, 0x66be7cbb00000000,
    0xafd31ddf00000000, 0xecc766c800000000, 0x29fbebf100000000,
    0x6aef90e600000000, 0xbb20293900000000, 0xf834522e00000000,
    0x3d08df1700000000, 0x7e1ca40000000000, 0xb771c56400000000,
    0xf465be7300000000, 0x3159334a00000000, 0x724d485d00000000,
    0xd2c0312e00000000, 0x91d44a3900000000, 0x54e8c70000000000,
    0x17fcbc1700000000, 0xde91dd7300000000, 0x9d85a66400000000,
    0x58b92b5d00000000, 0x1bad504a00000000, 0xca62e99500000000,
    0x8976928200000000, 0x4c4a1fbb00000000, 0x0f5e64ac00000000,
    0xc63305c800000000, 0x85277edf00000000, 0x401bf3e600000000,
    0x030f88f100000000, 0x070392de00000000, 0x4417e9c900000000,
    0x812b64f000000000, 0xc23f1fe700000000, 0x0b527e8300000000,
    0x4846059400000000, 0x8d7a88ad00000000, 0xce6ef3ba00000000,
    0x1fa14a6500000000, 0x5cb5317200000000, 0x9989bc4b00000000,
    0xda9dc75c00000000, 0x13f0a63800000000, 0x50e4dd2f00000000,
    0x95d8501600000000, 0xd6cc2b0100000000, 0x7641527200000000,
    0x3555296500000000, 0xf069a45c00000000, 0xb37ddf4b00000000,
    0x7a10be2f00000000, 0x3904c53800000000, 0xfc38480100000000,
    0xbf2c331600000000, 0x6ee38ac900000000, 0x2df7f1de00000000,
    0xe8cb7ce700000000, 0xabdf07f000000000, 0x62b2669400000000,
    0x21a61d8300000000, 0xe49a90ba00000000, 0xa78eebad00000000,
    0xa481635c00000000, 0xe795184b00000000, 0x22a9957200000000,
    0x61bdee6500000000, 0xa8d08f0100000000, 0xebc4f41600000000,
    0x2ef8792f00000000, 0x6dec023800000000, 0xbc23bbe700000000,
    0xff37c0f000000000, 0x3a0b4dc900000000, 0x791f36de00000000,
    0xb07257ba00000000, 0xf3662cad00000000, 0x365aa19400000000,
    0x754eda8300000000, 0xd5c3a3f000000000, 0x96d7d8e700000000,
    0x53eb55de00000000, 0x10ff2ec900000000, 0xd9924fad00000000,
    0x9a8634ba00000000, 0x5fbab98300000000, 0x1caec29400000000,
    0xcd617b4b00000000, 0x8e75005c00000000, 0x4b498d6500000000,
    0x085df67200000000, 0xc130971600000000, 0x8224ec0100000000,
    0x4718613800000000, 0x040c1a2f00000000, 0x4f00556600000000,
    0x0c142e7100000000, 0xc928a34800000000, 0x8a3cd85f00000000,
    0x4351b93b00000000, 0x0045c22c00000000, 0xc5794f1500000000,
    0x866d340200000000, 0x57a28ddd00000000, 0x14b6f6ca00000000,
    0xd18a7bf300000000, 0x929e00e400000000, 0x5bf3618000000000,
    0x18e71a9700000000, 0xdddb97ae00000000, 0x9ecfecb900000000,
    0x3e4295ca00000000, 0x7d56eedd00000000, 0xb86a63e400000000,
    0xfb7e18f300000000, 0x3213799700000000, 0x7107028000000000,
    0xb43b8fb900000000, 0xf72ff4ae00000000, 0x26e04d7100000000,
    0x65f4366600000000, 0xa0c8bb5f00000000, 0xe3dcc04800000000,
    0x2ab1a12c00000000, 0x69a5da3b00000000, 0xac99570200000000,
    0xef8d2c1500000000, 0xec82a4e400000000, 0xaf96dff300000000,
    0x6aaa52ca00000000, 0x29be29dd00000000, 0xe0d348b900000000,
    0xa3c733ae00000000, 0x66fbbe9700000000, 0x25efc58000000000,
    0xf4207c5f00000000, 0xb734074800000000, 0x72088a7100000000,
    0x311cf16600000000, 0xf871900200000000, 0xbb65eb1500000000,
    0x7e59662c00000000, 0x3d4d1d3b00000000, 0x9dc0644800000000,
    0xded41f5f00000000, 0x1be8926600000000, 0x58fce97100000000,
    0x9191881500000000, 0xd285f30200000000, 0x17b97e3b00000000,
    0x54ad052c00000000, 0x8562bcf300000000, 0xc676c7e400000000,
    0x034a4add00000000, 0x405e31ca00000000, 0x893350ae00000000,
    0xca272bb900000000, 0x0f1ba68000000000, 0x4c0fdd9700000000,
    0x4803c7b800000000, 0x0b17bcaf00000000, 0xce2b319600000000,
    0x8d3f4a8100000000, 0x44522be500000000, 0x074650f200000000,
    0xc27addcb00000000, 0x816ea6dc00000000, 0x50a11f0300000000,
    0x13b5641400000000, 0xd689e92d00000000, 0x959d923a00000000,
    0x5cf0f35e00000000, 0x1fe4884900000000, 0xdad8057000000000,
    0x99cc7e6700000000, 0x3941071400000000, 0x7a557c0300000000,
    0xbf69f13a00000000, 0xfc7d8a2d00000000, 0x3510eb4900000000,
    0x7604905e00000000, 0xb3381d6700000000, 0xf02c667000000000,
    0x21e3dfaf00000000, 0x62f7a4b800000000, 0xa7cb298100000000,
    0xe4df529600000000, 0x2db233f200000000, 0x6ea648e500000000,
    0xab9ac5dc00000000, 0xe88ebecb00000000, 0xeb81363a00000000,
    0xa8954d2d00000000, 0x6da9c01400000000, 0x2ebdbb0300000000,
    0xe7d0da6700000000, 0xa4c4a17000000000, 0x61f82c4900000000,
    0x22ec575e00000000, 0xf323ee8100000000, 0xb037959600000000,
    0x750b18af00000000, 0x361f63b800000000, 0xff7202dc00000000,
    0xbc6679cb00000000, 0x795af4f200000000, 0x3a4e8fe500000000,
    0x9ac3f69600000000, 0xd9d78d8100000000, 0x1ceb00b800000000,
    0x5fff7baf00000000, 0x96921acb00000000, 0xd58661dc00000000,
    0x10baece500000000, 0x53ae97f200000000, 0x82612e2d00000000,
    0xc175553a00000000, 0x0449d80300000000, 0x475da31400000000,
    0x8e30c27000000000, 0xcd24b96700000000, 0x0818345e00000000,
    0x4b0c4f4900000000},
   {0x0000000000000000, 0x3e6bc2ef00000000, 0x3dd0f50400000000,
    0x03bb37eb00000000, 0x7aa0eb0900000000, 0x44cb29e600000000,
    0x47701e0d00000000, 0x791bdce200000000, 0xf440d71300000000,
    0xca2b15fc00000000, 0xc990221700000000, 0xf7fbe0f800000000,
    0x8ee03c1a00000000, 0xb08bfef500000000, 0xb330c91e00000000,
    0x8d5b0bf100000000, 0xe881ae2700000000, 0xd6ea6cc800000000,
    0xd5515b2300000000, 0xeb3a99cc00000000, 0x9221452e00000000,
    0xac4a87c100000000, 0xaff1b02a00000000, 0x919a72c500000000,
    0x1cc1793400000000, 0x22aabbdb00000000, 0x21118c3000000000,
    0x1f7a4edf00000000, 0x6661923d00000000, 0x580a50d200000000,
    0x5bb1673900000000, 0x65daa5d600000000, 0xd0035d4f00000000,
    0xee689fa000000000, 0xedd3a84b00000000, 0xd3b86aa400000000,
    0xaaa3b64600000000, 0x94c874a900000000, 0x9773434200000000,
    0xa91881ad00000000, 0x24438a5c00000000, 0x1a2848b300000000,
    0x19937f5800000000, 0x27f8bdb700000000, 0x5ee3615500000000,
    0x6088a3ba00000000, 0x6333945100000000, 0x5d5856be00000000,
    0x3882f36800000000, 0x06e9318700000000, 0x0552066c00000000,
    0x3b39c48300000000, 0x4222186100000000, 0x7c49da8e00000000,
    0x7ff2ed6500000000, 0x41992f8a00000000, 0xccc2247b00000000,
    0xf2a9e69400000000, 0xf112d17f00000000, 0xcf79139000000000,
    0xb662cf7200000000, 0x88090d9d00000000, 0x8bb23a7600000000,
    0xb5d9f89900000000, 0xa007ba9e00000000, 0x9e6c787100000000,
    0x9dd74f9a00000000, 0xa3bc8d7500000000, 0xdaa7519700000000,
    0xe4cc937800000000, 0xe777a49300000000, 0xd91c667c00000000,
    0x54476d8d00000000, 0x6a2caf6200000000, 0x6997988900000000,
    0x57fc5a6600000000, 0x2ee7868400000000, 0x108c446b00000000,
    0x1337738000000000, 0x2d5cb16f00000000, 0x488614b900000000,
    0x76edd65600000000, 0x7556e1bd00000000, 0x4b3d235200000000,
    0x3226ffb000000000, 0x0c4d3d5f00000000, 0x0ff60ab400000000,
    0x319dc85b00000000, 0xbcc6c3aa00000000, 0x82ad014500000000,
    0x811636ae00000000, 0xbf7df44100000000, 0xc66628a300000000,
    0xf80dea4c00000000, 0xfbb6dda700000000, 0xc5dd1f4800000000,
    0x7004e7d100000000, 0x4e6f253e00000000, 0x4dd412d500000000,
    0x73bfd03a00000000, 0x0aa40cd800000000, 0x34cfce3700000000,
    0x3774f9dc00000000, 0x091f3b3300000000, 0x844430c200000000,
    0xba2ff22d00000000, 0xb994c5c600000000, 0x87ff072900000000,
    0xfee4dbcb00000000, 0xc08f192400000000, 0xc3342ecf00000000,
    0xfd5fec2000000000, 0x988549f600000000, 0xa6ee8b1900000000,
    0xa555bcf200000000, 0x9b3e7e1d00000000, 0xe225a2ff00000000,
    0xdc4e601000000000, 0xdff557fb00000000, 0xe19e951400000000,
    0x6cc59ee500000000, 0x52ae5c0a00000000, 0x51156be100000000,
    0x6f7ea90e00000000, 0x166575ec00000000, 0x280eb70300000000,
    0x2bb580e800000000, 0x15de420700000000, 0x010905e600000000,
    0x3f62c70900000000, 0x3cd9f0e200000000, 0x02b2320d00000000,
    0x7ba9eeef00000000, 0x45c22c0000000000, 0x46791beb00000000,
    0x7812d90400000000, 0xf549d2f500000000, 0xcb22101a00000000,
    0xc89927f100000000, 0xf6f2e51e00000000, 0x8fe939fc00000000,
    0xb182fb1300000000, 0xb239ccf800000000, 0x8c520e1700000000,
    0xe988abc100000000, 0xd7e3692e00000000, 0xd4585ec500000000,
    0xea339c2a00000000, 0x932840c800000000, 0xad43822700000000,
    0xaef8b5cc00000000, 0x9093772300000000, 0x1dc87cd200000000,
    0x23a3be3d00000000, 0x201889d600000000, 0x1e734b3900000000,
    0x676897db00000000, 0x5903553400000000, 0x5ab862df00000000,
    0x64d3a03000000000, 0xd10a58a900000000, 0xef619a4600000000,
    0xecdaadad00000000, 0xd2b16f4200000000, 0xabaab3a000000000,
    0x95c1714f00000000, 0x967a46a400000000, 0xa811844b00000000,
    0x254a8fba00000000, 0x1b214d5500000000, 0x189a7abe00000000,
    0x26f1b85100000000, 0x5fea64b300000000, 0x6181a65c00000000,
    0x623a91b700000000, 0x5c51535800000000, 0x398bf68e00000000,
    0x07e0346100000000, 0x045b038a00000000, 0x3a30c16500000000,
    0x432b1d8700000000, 0x7d40df6800000000, 0x7efbe88300000000,
    0x40902a6c00000000, 0xcdcb219d00000000, 0xf3a0e37200000000,
    0xf01bd49900000000, 0xce70167600000000, 0xb76bca9400000000,
    0x8900087b00000000, 0x8abb3f9000000000, 0xb4d0fd7f00000000,
    0xa10ebf7800000000, 0x9f657d9700000000, 0x9cde4a7c00000000,
    0xa2b5889300000000, 0xdbae547100000000, 0xe5c5969e00000000,
    0xe67ea17500000000, 0xd815639a00000000, 0x554e686b00000000,
    0x6b25aa8400000000, 0x689e9d6f00000000, 0x56f55f8000000000,
    0x2fee836200000000, 0x1185418d00000000, 0x123e766600000000,
    0x2c55b48900000000, 0x498f115f00000000, 0x77e4d3b000000000,
    0x745fe45b00000000, 0x4a3426b400000000, 0x332ffa5600000000,
    0x0d4438b900000000, 0x0eff0f5200000000, 0x3094cdbd00000000,
    0xbdcfc64c00000000, 0x83a404a300000000, 0x801f334800000000,
    0xbe74f1a700000000, 0xc76f2d4500000000, 0xf904efaa00000000,
    0xfabfd84100000000, 0xc4d41aae00000000, 0x710de23700000000,
    0x4f6620d800000000, 0x4cdd173300000000, 0x72b6d5dc00000000,
    0x0bad093e00000000, 0x35c6cbd100000000, 0x367dfc3a00000000,
    0x08163ed500000000, 0x854d352400000000, 0xbb26f7cb00000000,
    0xb89dc02000000000, 0x86f602cf00000000, 0xffedde2d00000000,
    0xc1861cc200000000, 0xc23d2b2900000000, 0xfc56e9c600000000,
    0x998c4c1000000000, 0xa7e78eff00000000, 0xa45cb91400000000,
    0x9a377bfb00000000, 0xe32ca71900000000, 0xdd4765f600000000,
    0xdefc521d00000000, 0xe09790f200000000, 0x6dcc9b0300000000,
    0x53a759ec00000000, 0x501c6e0700000000, 0x6e77ace800000000,
    0x176c700a00000000, 0x2907b2e500000000, 0x2abc850e00000000,
    0x14d747e100000000},
   {0x0000000000000000, 0xc0df8ec100000000, 0xc1b96c5800000000,
    0x0166e29900000000, 0x8273d9b000000000, 0x42ac577100000000,
    0x43cab5e800000000, 0x83153b2900000000, 0x45e1c3ba00000000,
    0x853e4d7b00000000, 0x8458afe200000000, 0x4487212300000000,
    0xc7921a0a00000000, 0x074d94cb00000000, 0x062b765200000000,
    0xc6f4f89300000000, 0xcbc4f6ae00000000, 0x0b1b786f00000000,
    0x0a7d9af600000000, 0xcaa2143700000000, 0x49b72f1e00000000,
    0x8968a1df00000000, 0x880e434600000000, 0x48d1cd8700000000,
    0x8e25351400000000, 0x4efabbd500000000, 0x4f9c594c00000000,
    0x8f43d78d00000000, 0x0c56eca400000000, 0xcc89626500000000,
    0xcdef80fc00000000, 0x0d300e3d00000000, 0xd78f9c8600000000,
    0x1750124700000000, 0x1636f0de00000000, 0xd6e97e1f00000000,
    0x55fc453600000000, 0x9523cbf700000000, 0x9445296e00000000,
    0x549aa7af00000000, 0x926e5f3c00000000, 0x52b1d1fd00000000,
    0x53d7336400000000, 0x9308bda500000000, 0x101d868c00000000,
    0xd0c2084d00000000, 0xd1a4ead400000000, 0x117b641500000000,
    0x1c4b6a2800000000, 0xdc94e4e900000000, 0xddf2067000000000,
    0x1d2d88b100000000, 0x9e38b39800000000, 0x5ee73d5900000000,
    0x5f81dfc000000000, 0x9f5e510100000000, 0x59aaa99200000000,
    0x9975275300000000, 0x9813c5ca00000000, 0x58cc4b0b00000000,
    0xdbd9702200000000, 0x1b06fee300000000, 0x1a601c7a00000000,
    0xdabf92bb00000000, 0xef1948d600000000, 0x2fc6c61700000000,
    0x2ea0248e00000000, 0xee7faa4f00000000, 0x6d6a916600000000,
    0xadb51fa700000000, 0xacd3fd3e00000000, 0x6c0c73ff00000000,
    0xaaf88b6c00000000, 0x6a2705ad00000000, 0x6b41e73400000000,
    0xab9e69f500000000, 0x288b52dc00000000, 0xe854dc1d00000000,
    0xe9323e8400000000, 0x29edb04500000000, 0x24ddbe7800000000,
    0xe40230b900000000, 0xe564d22000000000, 0x25bb5ce100000000,
    0xa6ae67c800000000, 0x6671e90900000000, 0x67170b9000000000,
    0xa7c8855100000000, 0x613c7dc200000000, 0xa1e3f30300000000,
    0xa085119a00000000, 0x605a9f5b00000000, 0xe34fa47200000000,
    0x23902ab300000000, 0x22f6c82a00000000, 0xe22946eb00000000,
    0x3896d45000000000, 0xf8495a9100000000, 0xf92fb80800000000,
    0x39f036c900000000, 0xbae50de000000000, 0x7a3a832100000000,
    0x7b5c61b800000000, 0xbb83ef7900000000, 0x7d7717ea00000000,
    0xbda8992b00000000, 0xbcce7bb200000000, 0x7c11f57300000000,
    0xff04ce5a00000000, 0x3fdb409b00000000, 0x3ebda20200000000,
    0xfe622cc300000000, 0xf35222fe00000000, 0x338dac3f00000000,
    0x32eb4ea600000000, 0xf234c06700000000, 0x7121fb4e00000000,
    0xb1fe758f00000000, 0xb098971600000000, 0x704719d700000000,
    0xb6b3e14400000000, 0x766c6f8500000000, 0x770a8d1c00000000,
    0xb7d503dd00000000, 0x34c038f400000000, 0xf41fb63500000000,
    0xf57954ac00000000, 0x35a6da6d00000000, 0x9f35e17700000000,
    0x5fea6fb600000000, 0x5e8c8d2f00000000, 0x9e5303ee00000000,
    0x1d4638c700000000, 0xdd99b60600000000, 0xdcff549f00000000,
    0x1c20da5e00000000, 0xdad422cd00000000, 0x1a0bac0c00000000,
    0x1b6d4e9500000000, 0xdbb2c05400000000, 0x58a7fb7d00000000,
    0x987875bc00000000, 0x991e972500000000, 0x59c119e400000000,
    0x54f117d900000000, 0x942e991800000000, 0x95487b8100000000,
    0x5597f54000000000, 0xd682ce6900000000, 0x165d40a800000000,
    0x173ba23100000000, 0xd7e42cf000000000, 0x1110d46300000000,
    0xd1cf5aa200000000, 0xd0a9b83b00000000, 0x107636fa00000000,
    0x93630dd300000000, 0x53bc831200000000, 0x52da618b00000000,
    0x9205ef4a00000000, 0x48ba7df100000000, 0x8865f33000000000,
    0x890311a900000000, 0x49dc9f6800000000, 0xcac9a44100000000,
    0x0a162a8000000000, 0x0b70c81900000000, 0xcbaf46d800000000,
    0x0d5bbe4b00000000, 0xcd84308a00000000, 0xcce2d21300000000,
    0x0c3d5cd200000000, 0x8f2867fb00000000, 0x4ff7e93a00000000,
    0x4e910ba300000000, 0x8e4e856200000000, 0x837e8b5f00000000,
    0x43a1059e00000000, 0x42c7e70700000000, 0x821869c600000000,
    0x010d52ef00000000, 0xc1d2dc2e00000000, 0xc0b43eb700000000,
    0x006bb07600000000, 0xc69f48e500000000, 0x0640c62400000000,
    0x072624bd00000000, 0xc7f9aa7c00000000, 0x44ec915500000000,
    0x84331f9400000000, 0x8555fd0d00000000, 0x458a73cc00000000,
    0x702ca9a100000000, 0xb0f3276000000000, 0xb195c5f900000000,
    0x714a4b3800000000, 0xf25f701100000000, 0x3280fed000000000,
    0x33e61c4900000000, 0xf339928800000000, 0x35cd6a1b00000000,
    0xf512e4da00000000, 0xf474064300000000, 0x34ab888200000000,
    0xb7beb3ab00000000, 0x77613d6a00000000, 0x7607dff300000000,
    0xb6d8513200000000, 0xbbe85f0f00000000, 0x7b37d1ce00000000,
    0x7a51335700000000, 0xba8ebd9600000000, 0x399b86bf00000000,
    0xf944087e00000000, 0xf822eae700000000, 0x38fd642600000000,
    0xfe099cb500000000, 0x3ed6127400000000, 0x3fb0f0ed00000000,
    0xff6f7e2c00000000, 0x7c7a450500000000, 0xbca5cbc400000000,
    0xbdc3295d00000000, 0x7d1ca79c00000000, 0xa7a3352700000000,
    0x677cbbe600000000, 0x661a597f00000000, 0xa6c5d7be00000000,
    0x25d0ec9700000000, 0xe50f625600000000, 0xe46980cf00000000,
    0x24b60e0e00000000, 0xe242f69d00000000, 0x229d785c00000000,
    0x23fb9ac500000000, 0xe324140400000000, 0x60312f2d00000000,
    0xa0eea1ec00000000, 0xa188437500000000, 0x6157cdb400000000,
    0x6c67c38900000000, 0xacb84d4800000000, 0xaddeafd100000000,
    0x6d01211000000000, 0xee141a3900000000, 0x2ecb94f800000000,
    0x2fad766100000000, 0xef72f8a000000000, 0x2986003300000000,
    0xe9598ef200000000, 0xe83f6c6b00000000, 0x28e0e2aa00000000,
    0xabf5d98300000000, 0x6b2a574200000000, 0x6a4cb5db00000000,
    0xaa933b1a00000000},
  {
    0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
   {0x0000000000000000, 0x6f4ca59b00000000, 0x9f9e3bec00000000,
    0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
    0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
    0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
    0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
    0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
    0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
    0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
    0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
    0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
    0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
    0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
    0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
    0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
    0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
    0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
    0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
    0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
    0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
    0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
    0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
    0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
    0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
    0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
    0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
    0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
    0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
    0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
    0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
    0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
    0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
    0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
    0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
    0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
    0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
    0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
    0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
    0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
    0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
    0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
    0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
    0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
    0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
    0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
    0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
    0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
    0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
    0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
    0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
    0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
    0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
    0xbe9834edUL
  },
    0xf0d29e7700000000, 0x7f3b060300000000, 0x1077a39800000000,
    0xe0a53def00000000, 0x8fe9987400000000, 0xfe760c0600000000,
    0x913aa99d00000000, 0x61e837ea00000000, 0x0ea4927100000000,
    0x814d0a0500000000, 0xee01af9e00000000, 0x1ed331e900000000,
    0x719f947200000000, 0xfced180c00000000, 0x93a1bd9700000000,
    0x637323e000000000, 0x0c3f867b00000000, 0x83d61e0f00000000,
    0xec9abb9400000000, 0x1c4825e300000000, 0x7304807800000000,
    0x029b140a00000000, 0x6dd7b19100000000, 0x9d052fe600000000,
    0xf2498a7d00000000, 0x7da0120900000000, 0x12ecb79200000000,
    0xe23e29e500000000, 0x8d728c7e00000000, 0xf8db311800000000,
    0x9797948300000000, 0x67450af400000000, 0x0809af6f00000000,
    0x87e0371b00000000, 0xe8ac928000000000, 0x187e0cf700000000,
    0x7732a96c00000000, 0x06ad3d1e00000000, 0x69e1988500000000,
    0x993306f200000000, 0xf67fa36900000000, 0x79963b1d00000000,
    0x16da9e8600000000, 0xe60800f100000000, 0x8944a56a00000000,
    0x0436291400000000, 0x6b7a8c8f00000000, 0x9ba812f800000000,
    0xf4e4b76300000000, 0x7b0d2f1700000000, 0x14418a8c00000000,
    0xe49314fb00000000, 0x8bdfb16000000000, 0xfa40251200000000,
    0x950c808900000000, 0x65de1efe00000000, 0x0a92bb6500000000,
    0x857b231100000000, 0xea37868a00000000, 0x1ae518fd00000000,
    0x75a9bd6600000000, 0xf0b7633000000000, 0x9ffbc6ab00000000,
    0x6f2958dc00000000, 0x0065fd4700000000, 0x8f8c653300000000,
    0xe0c0c0a800000000, 0x10125edf00000000, 0x7f5efb4400000000,
    0x0ec16f3600000000, 0x618dcaad00000000, 0x915f54da00000000,
    0xfe13f14100000000, 0x71fa693500000000, 0x1eb6ccae00000000,
    0xee6452d900000000, 0x8128f74200000000, 0x0c5a7b3c00000000,
    0x6316dea700000000, 0x93c440d000000000, 0xfc88e54b00000000,
    0x73617d3f00000000, 0x1c2dd8a400000000, 0xecff46d300000000,
    0x83b3e34800000000, 0xf22c773a00000000, 0x9d60d2a100000000,
    0x6db24cd600000000, 0x02fee94d00000000, 0x8d17713900000000,
    0xe25bd4a200000000, 0x12894ad500000000, 0x7dc5ef4e00000000,
    0x086c522800000000, 0x6720f7b300000000, 0x97f269c400000000,
    0xf8becc5f00000000, 0x7757542b00000000, 0x181bf1b000000000,
    0xe8c96fc700000000, 0x8785ca5c00000000, 0xf61a5e2e00000000,
    0x9956fbb500000000, 0x698465c200000000, 0x06c8c05900000000,
    0x8921582d00000000, 0xe66dfdb600000000, 0x16bf63c100000000,
    0x79f3c65a00000000, 0xf4814a2400000000, 0x9bcdefbf00000000,
    0x6b1f71c800000000, 0x0453d45300000000, 0x8bba4c2700000000,
    0xe4f6e9bc00000000, 0x142477cb00000000, 0x7b68d25000000000,
    0x0af7462200000000, 0x65bbe3b900000000, 0x95697dce00000000,
    0xfa25d85500000000, 0x75cc402100000000, 0x1a80e5ba00000000,
    0xea527bcd00000000, 0x851ede5600000000, 0xe06fc76000000000,
    0x8f2362fb00000000, 0x7ff1fc8c00000000, 0x10bd591700000000,
    0x9f54c16300000000, 0xf01864f800000000, 0x00cafa8f00000000,
    0x6f865f1400000000, 0x1e19cb6600000000, 0x71556efd00000000,
    0x8187f08a00000000, 0xeecb551100000000, 0x6122cd6500000000,
    0x0e6e68fe00000000, 0xfebcf68900000000, 0x91f0531200000000,
    0x1c82df6c00000000, 0x73ce7af700000000, 0x831ce48000000000,
    0xec50411b00000000, 0x63b9d96f00000000, 0x0cf57cf400000000,
    0xfc27e28300000000, 0x936b471800000000, 0xe2f4d36a00000000,
    0x8db876f100000000, 0x7d6ae88600000000, 0x12264d1d00000000,
    0x9dcfd56900000000, 0xf28370f200000000, 0x0251ee8500000000,
    0x6d1d4b1e00000000, 0x18b4f67800000000, 0x77f853e300000000,
    0x872acd9400000000, 0xe866680f00000000, 0x678ff07b00000000,
    0x08c355e000000000, 0xf811cb9700000000, 0x975d6e0c00000000,
    0xe6c2fa7e00000000, 0x898e5fe500000000, 0x795cc19200000000,
    0x1610640900000000, 0x99f9fc7d00000000, 0xf6b559e600000000,
    0x0667c79100000000, 0x692b620a00000000, 0xe459ee7400000000,
    0x8b154bef00000000, 0x7bc7d59800000000, 0x148b700300000000,
    0x9b62e87700000000, 0xf42e4dec00000000, 0x04fcd39b00000000,
    0x6bb0760000000000, 0x1a2fe27200000000, 0x756347e900000000,
    0x85b1d99e00000000, 0xeafd7c0500000000, 0x6514e47100000000,
    0x0a5841ea00000000, 0xfa8adf9d00000000, 0x95c67a0600000000,
    0x10d8a45000000000, 0x7f9401cb00000000, 0x8f469fbc00000000,
    0xe00a3a2700000000, 0x6fe3a25300000000, 0x00af07c800000000,
    0xf07d99bf00000000, 0x9f313c2400000000, 0xeeaea85600000000,
    0x81e20dcd00000000, 0x713093ba00000000, 0x1e7c362100000000,
    0x9195ae5500000000, 0xfed90bce00000000, 0x0e0b95b900000000,
    0x6147302200000000, 0xec35bc5c00000000, 0x837919c700000000,
    0x73ab87b000000000, 0x1ce7222b00000000, 0x930eba5f00000000,
    0xfc421fc400000000, 0x0c9081b300000000, 0x63dc242800000000,
    0x1243b05a00000000, 0x7d0f15c100000000, 0x8ddd8bb600000000,
    0xe2912e2d00000000, 0x6d78b65900000000, 0x023413c200000000,
    0xf2e68db500000000, 0x9daa282e00000000, 0xe803954800000000,
    0x874f30d300000000, 0x779daea400000000, 0x18d10b3f00000000,
    0x9738934b00000000, 0xf87436d000000000, 0x08a6a8a700000000,
    0x67ea0d3c00000000, 0x1675994e00000000, 0x79393cd500000000,
    0x89eba2a200000000, 0xe6a7073900000000, 0x694e9f4d00000000,
    0x06023ad600000000, 0xf6d0a4a100000000, 0x999c013a00000000,
    0x14ee8d4400000000, 0x7ba228df00000000, 0x8b70b6a800000000,
    0xe43c133300000000, 0x6bd58b4700000000, 0x04992edc00000000,
    0xf44bb0ab00000000, 0x9b07153000000000, 0xea98814200000000,
    0x85d424d900000000, 0x7506baae00000000, 0x1a4a1f3500000000,
    0x95a3874100000000, 0xfaef22da00000000, 0x0a3dbcad00000000,
    0x6571193600000000},
   {0x0000000000000000, 0x85d996dd00000000, 0x4bb55c6000000000,
    0xce6ccabd00000000, 0x966ab9c000000000, 0x13b32f1d00000000,
    0xdddfe5a000000000, 0x5806737d00000000, 0x6dd3035a00000000,
    0xe80a958700000000, 0x26665f3a00000000, 0xa3bfc9e700000000,
    0xfbb9ba9a00000000, 0x7e602c4700000000, 0xb00ce6fa00000000,
    0x35d5702700000000, 0xdaa607b400000000, 0x5f7f916900000000,
    0x91135bd400000000, 0x14cacd0900000000, 0x4cccbe7400000000,
    0xc91528a900000000, 0x0779e21400000000, 0x82a074c900000000,
    0xb77504ee00000000, 0x32ac923300000000, 0xfcc0588e00000000,
    0x7919ce5300000000, 0x211fbd2e00000000, 0xa4c62bf300000000,
    0x6aaae14e00000000, 0xef73779300000000, 0xf54b7eb300000000,
    0x7092e86e00000000, 0xbefe22d300000000, 0x3b27b40e00000000,
    0x6321c77300000000, 0xe6f851ae00000000, 0x28949b1300000000,
    0xad4d0dce00000000, 0x98987de900000000, 0x1d41eb3400000000,
    0xd32d218900000000, 0x56f4b75400000000, 0x0ef2c42900000000,
    0x8b2b52f400000000, 0x4547984900000000, 0xc09e0e9400000000,
    0x2fed790700000000, 0xaa34efda00000000, 0x6458256700000000,
    0xe181b3ba00000000, 0xb987c0c700000000, 0x3c5e561a00000000,
    0xf2329ca700000000, 0x77eb0a7a00000000, 0x423e7a5d00000000,
    0xc7e7ec8000000000, 0x098b263d00000000, 0x8c52b0e000000000,
    0xd454c39d00000000, 0x518d554000000000, 0x9fe19ffd00000000,
    0x1a38092000000000, 0xab918dbd00000000, 0x2e481b6000000000,
    0xe024d1dd00000000, 0x65fd470000000000, 0x3dfb347d00000000,
    0xb822a2a000000000, 0x764e681d00000000, 0xf397fec000000000,
    0xc6428ee700000000, 0x439b183a00000000, 0x8df7d28700000000,
    0x082e445a00000000, 0x5028372700000000, 0xd5f1a1fa00000000,
    0x1b9d6b4700000000, 0x9e44fd9a00000000, 0x71378a0900000000,
    0xf4ee1cd400000000, 0x3a82d66900000000, 0xbf5b40b400000000,
    0xe75d33c900000000, 0x6284a51400000000, 0xace86fa900000000,
    0x2931f97400000000, 0x1ce4895300000000, 0x993d1f8e00000000,
    0x5751d53300000000, 0xd28843ee00000000, 0x8a8e309300000000,
    0x0f57a64e00000000, 0xc13b6cf300000000, 0x44e2fa2e00000000,
    0x5edaf30e00000000, 0xdb0365d300000000, 0x156faf6e00000000,
    0x90b639b300000000, 0xc8b04ace00000000, 0x4d69dc1300000000,
    0x830516ae00000000, 0x06dc807300000000, 0x3309f05400000000,
    0xb6d0668900000000, 0x78bcac3400000000, 0xfd653ae900000000,
    0xa563499400000000, 0x20badf4900000000, 0xeed615f400000000,
    0x6b0f832900000000, 0x847cf4ba00000000, 0x01a5626700000000,
    0xcfc9a8da00000000, 0x4a103e0700000000, 0x12164d7a00000000,
    0x97cfdba700000000, 0x59a3111a00000000, 0xdc7a87c700000000,
    0xe9aff7e000000000, 0x6c76613d00000000, 0xa21aab8000000000,
    0x27c33d5d00000000, 0x7fc54e2000000000, 0xfa1cd8fd00000000,
    0x3470124000000000, 0xb1a9849d00000000, 0x17256aa000000000,
    0x92fcfc7d00000000, 0x5c9036c000000000, 0xd949a01d00000000,
    0x814fd36000000000, 0x049645bd00000000, 0xcafa8f0000000000,
    0x4f2319dd00000000, 0x7af669fa00000000, 0xff2fff2700000000,
    0x3143359a00000000, 0xb49aa34700000000, 0xec9cd03a00000000,
    0x694546e700000000, 0xa7298c5a00000000, 0x22f01a8700000000,
    0xcd836d1400000000, 0x485afbc900000000, 0x8636317400000000,
    0x03efa7a900000000, 0x5be9d4d400000000, 0xde30420900000000,
    0x105c88b400000000, 0x95851e6900000000, 0xa0506e4e00000000,
    0x2589f89300000000, 0xebe5322e00000000, 0x6e3ca4f300000000,
    0x363ad78e00000000, 0xb3e3415300000000, 0x7d8f8bee00000000,
    0xf8561d3300000000, 0xe26e141300000000, 0x67b782ce00000000,
    0xa9db487300000000, 0x2c02deae00000000, 0x7404add300000000,
    0xf1dd3b0e00000000, 0x3fb1f1b300000000, 0xba68676e00000000,
    0x8fbd174900000000, 0x0a64819400000000, 0xc4084b2900000000,
    0x41d1ddf400000000, 0x19d7ae8900000000, 0x9c0e385400000000,
    0x5262f2e900000000, 0xd7bb643400000000, 0x38c813a700000000,
    0xbd11857a00000000, 0x737d4fc700000000, 0xf6a4d91a00000000,
    0xaea2aa6700000000, 0x2b7b3cba00000000, 0xe517f60700000000,
    0x60ce60da00000000, 0x551b10fd00000000, 0xd0c2862000000000,
    0x1eae4c9d00000000, 0x9b77da4000000000, 0xc371a93d00000000,
    0x46a83fe000000000, 0x88c4f55d00000000, 0x0d1d638000000000,
    0xbcb4e71d00000000, 0x396d71c000000000, 0xf701bb7d00000000,
    0x72d82da000000000, 0x2ade5edd00000000, 0xaf07c80000000000,
    0x616b02bd00000000, 0xe4b2946000000000, 0xd167e44700000000,
    0x54be729a00000000, 0x9ad2b82700000000, 0x1f0b2efa00000000,
    0x470d5d8700000000, 0xc2d4cb5a00000000, 0x0cb801e700000000,
    0x8961973a00000000, 0x6612e0a900000000, 0xe3cb767400000000,
    0x2da7bcc900000000, 0xa87e2a1400000000, 0xf078596900000000,
    0x75a1cfb400000000, 0xbbcd050900000000, 0x3e1493d400000000,
    0x0bc1e3f300000000, 0x8e18752e00000000, 0x4074bf9300000000,
    0xc5ad294e00000000, 0x9dab5a3300000000, 0x1872ccee00000000,
    0xd61e065300000000, 0x53c7908e00000000, 0x49ff99ae00000000,
    0xcc260f7300000000, 0x024ac5ce00000000, 0x8793531300000000,
    0xdf95206e00000000, 0x5a4cb6b300000000, 0x94207c0e00000000,
    0x11f9ead300000000, 0x242c9af400000000, 0xa1f50c2900000000,
    0x6f99c69400000000, 0xea40504900000000, 0xb246233400000000,
    0x379fb5e900000000, 0xf9f37f5400000000, 0x7c2ae98900000000,
    0x93599e1a00000000, 0x168008c700000000, 0xd8ecc27a00000000,
    0x5d3554a700000000, 0x053327da00000000, 0x80eab10700000000,
    0x4e867bba00000000, 0xcb5fed6700000000, 0xfe8a9d4000000000,
    0x7b530b9d00000000, 0xb53fc12000000000, 0x30e657fd00000000,
    0x68e0248000000000, 0xed39b25d00000000, 0x235578e000000000,
    0xa68cee3d00000000},
   {0x0000000000000000, 0x76e10f9d00000000, 0xadc46ee100000000,
    0xdb25617c00000000, 0x1b8fac1900000000, 0x6d6ea38400000000,
    0xb64bc2f800000000, 0xc0aacd6500000000, 0x361e593300000000,
    0x40ff56ae00000000, 0x9bda37d200000000, 0xed3b384f00000000,
    0x2d91f52a00000000, 0x5b70fab700000000, 0x80559bcb00000000,
    0xf6b4945600000000, 0x6c3cb26600000000, 0x1addbdfb00000000,
    0xc1f8dc8700000000, 0xb719d31a00000000, 0x77b31e7f00000000,
    0x015211e200000000, 0xda77709e00000000, 0xac967f0300000000,
    0x5a22eb5500000000, 0x2cc3e4c800000000, 0xf7e685b400000000,
    0x81078a2900000000, 0x41ad474c00000000, 0x374c48d100000000,
    0xec6929ad00000000, 0x9a88263000000000, 0xd87864cd00000000,
    0xae996b5000000000, 0x75bc0a2c00000000, 0x035d05b100000000,
    0xc3f7c8d400000000, 0xb516c74900000000, 0x6e33a63500000000,
    0x18d2a9a800000000, 0xee663dfe00000000, 0x9887326300000000,
    0x43a2531f00000000, 0x35435c8200000000, 0xf5e991e700000000,
    0x83089e7a00000000, 0x582dff0600000000, 0x2eccf09b00000000,
    0xb444d6ab00000000, 0xc2a5d93600000000, 0x1980b84a00000000,
    0x6f61b7d700000000, 0xafcb7ab200000000, 0xd92a752f00000000,
    0x020f145300000000, 0x74ee1bce00000000, 0x825a8f9800000000,
    0xf4bb800500000000, 0x2f9ee17900000000, 0x597feee400000000,
    0x99d5238100000000, 0xef342c1c00000000, 0x34114d6000000000,
    0x42f042fd00000000, 0xf1f7b94100000000, 0x8716b6dc00000000,
    0x5c33d7a000000000, 0x2ad2d83d00000000, 0xea78155800000000,
    0x9c991ac500000000, 0x47bc7bb900000000, 0x315d742400000000,
    0xc7e9e07200000000, 0xb108efef00000000, 0x6a2d8e9300000000,
    0x1ccc810e00000000, 0xdc664c6b00000000, 0xaa8743f600000000,
    0x71a2228a00000000, 0x07432d1700000000, 0x9dcb0b2700000000,
    0xeb2a04ba00000000, 0x300f65c600000000, 0x46ee6a5b00000000,
    0x8644a73e00000000, 0xf0a5a8a300000000, 0x2b80c9df00000000,
    0x5d61c64200000000, 0xabd5521400000000, 0xdd345d8900000000,
    0x06113cf500000000, 0x70f0336800000000, 0xb05afe0d00000000,
    0xc6bbf19000000000, 0x1d9e90ec00000000, 0x6b7f9f7100000000,
    0x298fdd8c00000000, 0x5f6ed21100000000, 0x844bb36d00000000,
    0xf2aabcf000000000, 0x3200719500000000, 0x44e17e0800000000,
    0x9fc41f7400000000, 0xe92510e900000000, 0x1f9184bf00000000,
    0x69708b2200000000, 0xb255ea5e00000000, 0xc4b4e5c300000000,
    0x041e28a600000000, 0x72ff273b00000000, 0xa9da464700000000,
    0xdf3b49da00000000, 0x45b36fea00000000, 0x3352607700000000,
    0xe877010b00000000, 0x9e960e9600000000, 0x5e3cc3f300000000,
    0x28ddcc6e00000000, 0xf3f8ad1200000000, 0x8519a28f00000000,
    0x73ad36d900000000, 0x054c394400000000, 0xde69583800000000,
    0xa88857a500000000, 0x68229ac000000000, 0x1ec3955d00000000,
    0xc5e6f42100000000, 0xb307fbbc00000000, 0xe2ef738300000000,
    0x940e7c1e00000000, 0x4f2b1d6200000000, 0x39ca12ff00000000,
    0xf960df9a00000000, 0x8f81d00700000000, 0x54a4b17b00000000,
    0x2245bee600000000, 0xd4f12ab000000000, 0xa210252d00000000,
    0x7935445100000000, 0x0fd44bcc00000000, 0xcf7e86a900000000,
    0xb99f893400000000, 0x62bae84800000000, 0x145be7d500000000,
    0x8ed3c1e500000000, 0xf832ce7800000000, 0x2317af0400000000,
    0x55f6a09900000000, 0x955c6dfc00000000, 0xe3bd626100000000,
    0x3898031d00000000, 0x4e790c8000000000, 0xb8cd98d600000000,
    0xce2c974b00000000, 0x1509f63700000000, 0x63e8f9aa00000000,
    0xa34234cf00000000, 0xd5a33b5200000000, 0x0e865a2e00000000,
    0x786755b300000000, 0x3a97174e00000000, 0x4c7618d300000000,
    0x975379af00000000, 0xe1b2763200000000, 0x2118bb5700000000,
    0x57f9b4ca00000000, 0x8cdcd5b600000000, 0xfa3dda2b00000000,
    0x0c894e7d00000000, 0x7a6841e000000000, 0xa14d209c00000000,
    0xd7ac2f0100000000, 0x1706e26400000000, 0x61e7edf900000000,
    0xbac28c8500000000, 0xcc23831800000000, 0x56aba52800000000,
    0x204aaab500000000, 0xfb6fcbc900000000, 0x8d8ec45400000000,
    0x4d24093100000000, 0x3bc506ac00000000, 0xe0e067d000000000,
    0x9601684d00000000, 0x60b5fc1b00000000, 0x1654f38600000000,
    0xcd7192fa00000000, 0xbb909d6700000000, 0x7b3a500200000000,
    0x0ddb5f9f00000000, 0xd6fe3ee300000000, 0xa01f317e00000000,
    0x1318cac200000000, 0x65f9c55f00000000, 0xbedca42300000000,
    0xc83dabbe00000000, 0x089766db00000000, 0x7e76694600000000,
    0xa553083a00000000, 0xd3b207a700000000, 0x250693f100000000,
    0x53e79c6c00000000, 0x88c2fd1000000000, 0xfe23f28d00000000,
    0x3e893fe800000000, 0x4868307500000000, 0x934d510900000000,
    0xe5ac5e9400000000, 0x7f2478a400000000, 0x09c5773900000000,
    0xd2e0164500000000, 0xa40119d800000000, 0x64abd4bd00000000,
    0x124adb2000000000, 0xc96fba5c00000000, 0xbf8eb5c100000000,
    0x493a219700000000, 0x3fdb2e0a00000000, 0xe4fe4f7600000000,
    0x921f40eb00000000, 0x52b58d8e00000000, 0x2454821300000000,
    0xff71e36f00000000, 0x8990ecf200000000, 0xcb60ae0f00000000,
    0xbd81a19200000000, 0x66a4c0ee00000000, 0x1045cf7300000000,
    0xd0ef021600000000, 0xa60e0d8b00000000, 0x7d2b6cf700000000,
    0x0bca636a00000000, 0xfd7ef73c00000000, 0x8b9ff8a100000000,
    0x50ba99dd00000000, 0x265b964000000000, 0xe6f15b2500000000,
    0x901054b800000000, 0x4b3535c400000000, 0x3dd43a5900000000,
    0xa75c1c6900000000, 0xd1bd13f400000000, 0x0a98728800000000,
    0x7c797d1500000000, 0xbcd3b07000000000, 0xca32bfed00000000,
    0x1117de9100000000, 0x67f6d10c00000000, 0x9142455a00000000,
    0xe7a34ac700000000, 0x3c862bbb00000000, 0x4a67242600000000,
    0x8acde94300000000, 0xfc2ce6de00000000, 0x270987a200000000,
    0x51e8883f00000000},
   {0x0000000000000000, 0xe8dbfbb900000000, 0x91b186a800000000,
    0x796a7d1100000000, 0x63657c8a00000000, 0x8bbe873300000000,
    0xf2d4fa2200000000, 0x1a0f019b00000000, 0x87cc89cf00000000,
    0x6f17727600000000, 0x167d0f6700000000, 0xfea6f4de00000000,
    0xe4a9f54500000000, 0x0c720efc00000000, 0x751873ed00000000,
    0x9dc3885400000000, 0x4f9f624400000000, 0xa74499fd00000000,
    0xde2ee4ec00000000, 0x36f51f5500000000, 0x2cfa1ece00000000,
    0xc421e57700000000, 0xbd4b986600000000, 0x559063df00000000,
    0xc853eb8b00000000, 0x2088103200000000, 0x59e26d2300000000,
    0xb139969a00000000, 0xab36970100000000, 0x43ed6cb800000000,
    0x3a8711a900000000, 0xd25cea1000000000, 0x9e3ec58800000000,
    0x76e53e3100000000, 0x0f8f432000000000, 0xe754b89900000000,
    0xfd5bb90200000000, 0x158042bb00000000, 0x6cea3faa00000000,
    0x8431c41300000000, 0x19f24c4700000000, 0xf129b7fe00000000,
    0x8843caef00000000, 0x6098315600000000, 0x7a9730cd00000000,
    0x924ccb7400000000, 0xeb26b66500000000, 0x03fd4ddc00000000,
    0xd1a1a7cc00000000, 0x397a5c7500000000, 0x4010216400000000,
    0xa8cbdadd00000000, 0xb2c4db4600000000, 0x5a1f20ff00000000,
    0x23755dee00000000, 0xcbaea65700000000, 0x566d2e0300000000,
    0xbeb6d5ba00000000, 0xc7dca8ab00000000, 0x2f07531200000000,
    0x3508528900000000, 0xddd3a93000000000, 0xa4b9d42100000000,
    0x4c622f9800000000, 0x7d7bfbca00000000, 0x95a0007300000000,
    0xecca7d6200000000, 0x041186db00000000, 0x1e1e874000000000,
    0xf6c57cf900000000, 0x8faf01e800000000, 0x6774fa5100000000,
    0xfab7720500000000, 0x126c89bc00000000, 0x6b06f4ad00000000,
    0x83dd0f1400000000, 0x99d20e8f00000000, 0x7109f53600000000,
    0x0863882700000000, 0xe0b8739e00000000, 0x32e4998e00000000,
    0xda3f623700000000, 0xa3551f2600000000, 0x4b8ee49f00000000,
    0x5181e50400000000, 0xb95a1ebd00000000, 0xc03063ac00000000,
    0x28eb981500000000, 0xb528104100000000, 0x5df3ebf800000000,
    0x249996e900000000, 0xcc426d5000000000, 0xd64d6ccb00000000,
    0x3e96977200000000, 0x47fcea6300000000, 0xaf2711da00000000,
    0xe3453e4200000000, 0x0b9ec5fb00000000, 0x72f4b8ea00000000,
    0x9a2f435300000000, 0x802042c800000000, 0x68fbb97100000000,
    0x1191c46000000000, 0xf94a3fd900000000, 0x6489b78d00000000,
    0x8c524c3400000000, 0xf538312500000000, 0x1de3ca9c00000000,
    0x07eccb0700000000, 0xef3730be00000000, 0x965d4daf00000000,
    0x7e86b61600000000, 0xacda5c0600000000, 0x4401a7bf00000000,
    0x3d6bdaae00000000, 0xd5b0211700000000, 0xcfbf208c00000000,
    0x2764db3500000000, 0x5e0ea62400000000, 0xb6d55d9d00000000,
    0x2b16d5c900000000, 0xc3cd2e7000000000, 0xbaa7536100000000,
    0x527ca8d800000000, 0x4873a94300000000, 0xa0a852fa00000000,
    0xd9c22feb00000000, 0x3119d45200000000, 0xbbf0874e00000000,
    0x532b7cf700000000, 0x2a4101e600000000, 0xc29afa5f00000000,
    0xd895fbc400000000, 0x304e007d00000000, 0x49247d6c00000000,
    0xa1ff86d500000000, 0x3c3c0e8100000000, 0xd4e7f53800000000,
    0xad8d882900000000, 0x4556739000000000, 0x5f59720b00000000,
    0xb78289b200000000, 0xcee8f4a300000000, 0x26330f1a00000000,
    0xf46fe50a00000000, 0x1cb41eb300000000, 0x65de63a200000000,
    0x8d05981b00000000, 0x970a998000000000, 0x7fd1623900000000,
    0x06bb1f2800000000, 0xee60e49100000000, 0x73a36cc500000000,
    0x9b78977c00000000, 0xe212ea6d00000000, 0x0ac911d400000000,
    0x10c6104f00000000, 0xf81debf600000000, 0x817796e700000000,
    0x69ac6d5e00000000, 0x25ce42c600000000, 0xcd15b97f00000000,
    0xb47fc46e00000000, 0x5ca43fd700000000, 0x46ab3e4c00000000,
    0xae70c5f500000000, 0xd71ab8e400000000, 0x3fc1435d00000000,
    0xa202cb0900000000, 0x4ad930b000000000, 0x33b34da100000000,
    0xdb68b61800000000, 0xc167b78300000000, 0x29bc4c3a00000000,
    0x50d6312b00000000, 0xb80dca9200000000, 0x6a51208200000000,
    0x828adb3b00000000, 0xfbe0a62a00000000, 0x133b5d9300000000,
    0x09345c0800000000, 0xe1efa7b100000000, 0x9885daa000000000,
    0x705e211900000000, 0xed9da94d00000000, 0x054652f400000000,
    0x7c2c2fe500000000, 0x94f7d45c00000000, 0x8ef8d5c700000000,
    0x66232e7e00000000, 0x1f49536f00000000, 0xf792a8d600000000,
    0xc68b7c8400000000, 0x2e50873d00000000, 0x573afa2c00000000,
    0xbfe1019500000000, 0xa5ee000e00000000, 0x4d35fbb700000000,
    0x345f86a600000000, 0xdc847d1f00000000, 0x4147f54b00000000,
    0xa99c0ef200000000, 0xd0f673e300000000, 0x382d885a00000000,
    0x222289c100000000, 0xcaf9727800000000, 0xb3930f6900000000,
    0x5b48f4d000000000, 0x89141ec000000000, 0x61cfe57900000000,
    0x18a5986800000000, 0xf07e63d100000000, 0xea71624a00000000,
    0x02aa99f300000000, 0x7bc0e4e200000000, 0x931b1f5b00000000,
    0x0ed8970f00000000, 0xe6036cb600000000, 0x9f6911a700000000,
    0x77b2ea1e00000000, 0x6dbdeb8500000000, 0x8566103c00000000,
    0xfc0c6d2d00000000, 0x14d7969400000000, 0x58b5b90c00000000,
    0xb06e42b500000000, 0xc9043fa400000000, 0x21dfc41d00000000,
    0x3bd0c58600000000, 0xd30b3e3f00000000, 0xaa61432e00000000,
    0x42bab89700000000, 0xdf7930c300000000, 0x37a2cb7a00000000,
    0x4ec8b66b00000000, 0xa6134dd200000000, 0xbc1c4c4900000000,
    0x54c7b7f000000000, 0x2dadcae100000000, 0xc576315800000000,
    0x172adb4800000000, 0xfff120f100000000, 0x869b5de000000000,
    0x6e40a65900000000, 0x744fa7c200000000, 0x9c945c7b00000000,
    0xe5fe216a00000000, 0x0d25dad300000000, 0x90e6528700000000,
    0x783da93e00000000, 0x0157d42f00000000, 0xe98c2f9600000000,
    0xf3832e0d00000000, 0x1b58d5b400000000, 0x6232a8a500000000,
    0x8ae9531c00000000},
   {0x0000000000000000, 0x919168ae00000000, 0x6325a08700000000,
    0xf2b4c82900000000, 0x874c31d400000000, 0x16dd597a00000000,
    0xe469915300000000, 0x75f8f9fd00000000, 0x4f9f137300000000,
    0xde0e7bdd00000000, 0x2cbab3f400000000, 0xbd2bdb5a00000000,
    0xc8d322a700000000, 0x59424a0900000000, 0xabf6822000000000,
    0x3a67ea8e00000000, 0x9e3e27e600000000, 0x0faf4f4800000000,
    0xfd1b876100000000, 0x6c8aefcf00000000, 0x1972163200000000,
    0x88e37e9c00000000, 0x7a57b6b500000000, 0xebc6de1b00000000,
    0xd1a1349500000000, 0x40305c3b00000000, 0xb284941200000000,
    0x2315fcbc00000000, 0x56ed054100000000, 0xc77c6def00000000,
    0x35c8a5c600000000, 0xa459cd6800000000, 0x7d7b3f1700000000,
    0xecea57b900000000, 0x1e5e9f9000000000, 0x8fcff73e00000000,
    0xfa370ec300000000, 0x6ba6666d00000000, 0x9912ae4400000000,
    0x0883c6ea00000000, 0x32e42c6400000000, 0xa37544ca00000000,
    0x51c18ce300000000, 0xc050e44d00000000, 0xb5a81db000000000,
    0x2439751e00000000, 0xd68dbd3700000000, 0x471cd59900000000,
    0xe34518f100000000, 0x72d4705f00000000, 0x8060b87600000000,
    0x11f1d0d800000000, 0x6409292500000000, 0xf598418b00000000,
    0x072c89a200000000, 0x96bde10c00000000, 0xacda0b8200000000,
    0x3d4b632c00000000, 0xcfffab0500000000, 0x5e6ec3ab00000000,
    0x2b963a5600000000, 0xba0752f800000000, 0x48b39ad100000000,
    0xd922f27f00000000, 0xfaf67e2e00000000, 0x6b67168000000000,
    0x99d3dea900000000, 0x0842b60700000000, 0x7dba4ffa00000000,
    0xec2b275400000000, 0x1e9fef7d00000000, 0x8f0e87d300000000,
    0xb5696d5d00000000, 0x24f805f300000000, 0xd64ccdda00000000,
    0x47dda57400000000, 0x32255c8900000000, 0xa3b4342700000000,
    0x5100fc0e00000000, 0xc09194a000000000, 0x64c859c800000000,
    0xf559316600000000, 0x07edf94f00000000, 0x967c91e100000000,
    0xe384681c00000000, 0x721500b200000000, 0x80a1c89b00000000,
    0x1130a03500000000, 0x2b574abb00000000, 0xbac6221500000000,
    0x4872ea3c00000000, 0xd9e3829200000000, 0xac1b7b6f00000000,
    0x3d8a13c100000000, 0xcf3edbe800000000, 0x5eafb34600000000,
    0x878d413900000000, 0x161c299700000000, 0xe4a8e1be00000000,
    0x7539891000000000, 0x00c170ed00000000, 0x9150184300000000,
    0x63e4d06a00000000, 0xf275b8c400000000, 0xc812524a00000000,
    0x59833ae400000000, 0xab37f2cd00000000, 0x3aa69a6300000000,
    0x4f5e639e00000000, 0xdecf0b3000000000, 0x2c7bc31900000000,
    0xbdeaabb700000000, 0x19b366df00000000, 0x88220e7100000000,
    0x7a96c65800000000, 0xeb07aef600000000, 0x9eff570b00000000,
    0x0f6e3fa500000000, 0xfddaf78c00000000, 0x6c4b9f2200000000,
    0x562c75ac00000000, 0xc7bd1d0200000000, 0x3509d52b00000000,
    0xa498bd8500000000, 0xd160447800000000, 0x40f12cd600000000,
    0xb245e4ff00000000, 0x23d48c5100000000, 0xf4edfd5c00000000,
    0x657c95f200000000, 0x97c85ddb00000000, 0x0659357500000000,
    0x73a1cc8800000000, 0xe230a42600000000, 0x10846c0f00000000,
    0x811504a100000000, 0xbb72ee2f00000000, 0x2ae3868100000000,
    0xd8574ea800000000, 0x49c6260600000000, 0x3c3edffb00000000,
    0xadafb75500000000, 0x5f1b7f7c00000000, 0xce8a17d200000000,
    0x6ad3daba00000000, 0xfb42b21400000000, 0x09f67a3d00000000,
    0x9867129300000000, 0xed9feb6e00000000, 0x7c0e83c000000000,
    0x8eba4be900000000, 0x1f2b234700000000, 0x254cc9c900000000,
    0xb4dda16700000000, 0x4669694e00000000, 0xd7f801e000000000,
    0xa200f81d00000000, 0x339190b300000000, 0xc125589a00000000,
    0x50b4303400000000, 0x8996c24b00000000, 0x1807aae500000000,
    0xeab362cc00000000, 0x7b220a6200000000, 0x0edaf39f00000000,
    0x9f4b9b3100000000, 0x6dff531800000000, 0xfc6e3bb600000000,
    0xc609d13800000000, 0x5798b99600000000, 0xa52c71bf00000000,
    0x34bd191100000000, 0x4145e0ec00000000, 0xd0d4884200000000,
    0x2260406b00000000, 0xb3f128c500000000, 0x17a8e5ad00000000,
    0x86398d0300000000, 0x748d452a00000000, 0xe51c2d8400000000,
    0x90e4d47900000000, 0x0175bcd700000000, 0xf3c174fe00000000,
    0x62501c5000000000, 0x5837f6de00000000, 0xc9a69e7000000000,
    0x3b12565900000000, 0xaa833ef700000000, 0xdf7bc70a00000000,
    0x4eeaafa400000000, 0xbc5e678d00000000, 0x2dcf0f2300000000,
    0x0e1b837200000000, 0x9f8aebdc00000000, 0x6d3e23f500000000,
    0xfcaf4b5b00000000, 0x8957b2a600000000, 0x18c6da0800000000,
    0xea72122100000000, 0x7be37a8f00000000, 0x4184900100000000,
    0xd015f8af00000000, 0x22a1308600000000, 0xb330582800000000,
    0xc6c8a1d500000000, 0x5759c97b00000000, 0xa5ed015200000000,
    0x347c69fc00000000, 0x9025a49400000000, 0x01b4cc3a00000000,
    0xf300041300000000, 0x62916cbd00000000, 0x1769954000000000,
    0x86f8fdee00000000, 0x744c35c700000000, 0xe5dd5d6900000000,
    0xdfbab7e700000000, 0x4e2bdf4900000000, 0xbc9f176000000000,
    0x2d0e7fce00000000, 0x58f6863300000000, 0xc967ee9d00000000,
    0x3bd326b400000000, 0xaa424e1a00000000, 0x7360bc6500000000,
    0xe2f1d4cb00000000, 0x10451ce200000000, 0x81d4744c00000000,
    0xf42c8db100000000, 0x65bde51f00000000, 0x97092d3600000000,
    0x0698459800000000, 0x3cffaf1600000000, 0xad6ec7b800000000,
    0x5fda0f9100000000, 0xce4b673f00000000, 0xbbb39ec200000000,
    0x2a22f66c00000000, 0xd8963e4500000000, 0x490756eb00000000,
    0xed5e9b8300000000, 0x7ccff32d00000000, 0x8e7b3b0400000000,
    0x1fea53aa00000000, 0x6a12aa5700000000, 0xfb83c2f900000000,
    0x09370ad000000000, 0x98a6627e00000000, 0xa2c188f000000000,
    0x3350e05e00000000, 0xc1e4287700000000, 0x507540d900000000,
    0x258db92400000000, 0xb41cd18a00000000, 0x46a819a300000000,
    0xd739710d00000000}};

#else /* W == 4 */

local const z_crc_t FAR crc_braid_table[][256] = {
   {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa,
    0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b,
    0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232,
    0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8,
    0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e,
    0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa,
    0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b,
    0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f,
    0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719,
    0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3,
    0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa,
    0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b,
    0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed,
    0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89,
    0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25,
    0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041,
    0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c,
    0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed,
    0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4,
    0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758,
    0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e,
    0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a,
    0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed,
    0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889,
    0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df,
    0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544,
    0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d,
    0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c,
    0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1,
    0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95,
    0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839,
    0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d,
    0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976,
    0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7,
    0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be,
    0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144,
    0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12,
    0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376,
    0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a,
    0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e,
    0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278,
    0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682,
    0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b,
    0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a,
    0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561,
    0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05,
    0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9,
    0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd,
    0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0,
    0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61,
    0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678,
    0x264b06e6},
   {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413,
    0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3,
    0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d,
    0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653,
    0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9,
    0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e,
    0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5,
    0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712,
    0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8,
    0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6,
    0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068,
    0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8,
    0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579,
    0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade,
    0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37,
    0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590,
    0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4,
    0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64,
    0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea,
    0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678,
    0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282,
    0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25,
    0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102,
    0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5,
    0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f,
    0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146,
    0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8,
    0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08,
    0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c,
    0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b,
    0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972,
    0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5,
    0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d,
    0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd,
    0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833,
    0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d,
    0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7,
    0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60,
    0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2,
    0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105,
    0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff,
    0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1,
    0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f,
    0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf,
    0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617,
    0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0,
    0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959,
    0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe,
    0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca,
    0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a,
    0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184,
    0x92364a30},
   {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216,
    0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8,
    0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170,
    0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035,
    0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6,
    0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145,
    0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d,
    0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e,
    0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d,
    0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408,
    0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0,
    0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e,
    0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c,
    0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf,
    0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a,
    0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9,
    0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1,
    0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f,
    0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987,
    0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4,
    0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37,
    0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84,
    0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca,
    0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79,
    0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba,
    0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d,
    0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5,
    0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b,
    0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643,
    0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0,
    0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525,
    0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496,
    0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8,
    0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026,
    0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e,
    0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db,
    0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118,
    0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab,
    0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf,
    0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c,
    0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf,
    0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a,
    0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32,
    0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec,
    0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82,
    0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31,
    0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4,
    0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957,
    0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f,
    0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1,
    0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869,
    0xe4c4abcc},
   {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0,
    0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271,
    0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61,
    0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52,
    0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43,
    0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333,
    0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64,
    0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314,
    0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205,
    0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136,
    0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26,
    0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997,
    0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849,
    0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739,
    0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8,
    0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98,
    0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b,
    0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba,
    0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa,
    0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d,
    0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c,
    0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc,
    0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af,
    0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf,
    0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce,
    0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922,
    0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532,
    0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183,
    0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710,
    0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860,
    0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1,
    0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1,
    0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956,
    0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7,
    0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7,
    0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4,
    0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5,
    0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5,
    0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb,
    0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb,
    0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da,
    0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9,
    0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9,
    0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48,
    0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df,
    0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af,
    0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e,
    0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e,
    0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d,
    0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c,
    0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c,
    0xca64c78c}};

local const z_word_t FAR crc_braid_big_table[][256] = {
   {0x00000000, 0xb029603d, 0x6053c07a, 0xd07aa047, 0xc0a680f5,
    0x708fe0c8, 0xa0f5408f, 0x10dc20b2, 0xc14b7030, 0x7162100d,
    0xa118b04a, 0x1131d077, 0x01edf0c5, 0xb1c490f8, 0x61be30bf,
    0xd1975082, 0x8297e060, 0x32be805d, 0xe2c4201a, 0x52ed4027,
    0x42316095, 0xf21800a8, 0x2262a0ef, 0x924bc0d2, 0x43dc9050,
    0xf3f5f06d, 0x238f502a, 0x93a63017, 0x837a10a5, 0x33537098,
    0xe329d0df, 0x5300b0e2, 0x042fc1c1, 0xb406a1fc, 0x647c01bb,
    0xd4556186, 0xc4894134, 0x74a02109, 0xa4da814e, 0x14f3e173,
    0xc564b1f1, 0x754dd1cc, 0xa537718b, 0x151e11b6, 0x05c23104,
    0xb5eb5139, 0x6591f17e, 0xd5b89143, 0x86b821a1, 0x3691419c,
    0xe6ebe1db, 0x56c281e6, 0x461ea154, 0xf637c169, 0x264d612e,
    0x96640113, 0x47f35191, 0xf7da31ac, 0x27a091eb, 0x9789f1d6,
    0x8755d164, 0x377cb159, 0xe706111e, 0x572f7123, 0x4958f358,
    0xf9719365, 0x290b3322, 0x9922531f, 0x89fe73ad, 0x39d71390,
    0xe9adb3d7, 0x5984d3ea, 0x88138368, 0x383ae355, 0xe8404312,
    0x5869232f, 0x48b5039d, 0xf89c63a0, 0x28e6c3e7, 0x98cfa3da,
    0xcbcf1338, 0x7be67305, 0xab9cd342, 0x1bb5b37f, 0x0b6993cd,
    0xbb40f3f0, 0x6b3a53b7, 0xdb13338a, 0x0a846308, 0xbaad0335,
    0x6ad7a372, 0xdafec34f, 0xca22e3fd, 0x7a0b83c0, 0xaa712387,
    0x1a5843ba, 0x4d773299, 0xfd5e52a4, 0x2d24f2e3, 0x9d0d92de,
    0x8dd1b26c, 0x3df8d251, 0xed827216, 0x5dab122b, 0x8c3c42a9,
    0x3c152294, 0xec6f82d3, 0x5c46e2ee, 0x4c9ac25c, 0xfcb3a261,
    0x2cc90226, 0x9ce0621b, 0xcfe0d2f9, 0x7fc9b2c4, 0xafb31283,
    0x1f9a72be, 0x0f46520c, 0xbf6f3231, 0x6f159276, 0xdf3cf24b,
    0x0eaba2c9, 0xbe82c2f4, 0x6ef862b3, 0xded1028e, 0xce0d223c,
    0x7e244201, 0xae5ee246, 0x1e77827b, 0x92b0e6b1, 0x2299868c,
    0xf2e326cb, 0x42ca46f6, 0x52166644, 0xe23f0679, 0x3245a63e,
    0x826cc603, 0x53fb9681, 0xe3d2f6bc, 0x33a856fb, 0x838136c6,
    0x935d1674, 0x23747649, 0xf30ed60e, 0x4327b633, 0x102706d1,
    0xa00e66ec, 0x7074c6ab, 0xc05da696, 0xd0818624, 0x60a8e619,
    0xb0d2465e, 0x00fb2663, 0xd16c76e1, 0x614516dc, 0xb13fb69b,
    0x0116d6a6, 0x11caf614, 0xa1e39629, 0x7199366e, 0xc1b05653,
    0x969f2770, 0x26b6474d, 0xf6cce70a, 0x46e58737, 0x5639a785,
    0xe610c7b8, 0x366a67ff, 0x864307c2, 0x57d45740, 0xe7fd377d,
    0x3787973a, 0x87aef707, 0x9772d7b5, 0x275bb788, 0xf72117cf,
    0x470877f2, 0x1408c710, 0xa421a72d, 0x745b076a, 0xc4726757,
    0xd4ae47e5, 0x648727d8, 0xb4fd879f, 0x04d4e7a2, 0xd543b720,
    0x656ad71d, 0xb510775a, 0x05391767, 0x15e537d5, 0xa5cc57e8,
    0x75b6f7af, 0xc59f9792, 0xdbe815e9, 0x6bc175d4, 0xbbbbd593,
    0x0b92b5ae, 0x1b4e951c, 0xab67f521, 0x7b1d5566, 0xcb34355b,
    0x1aa365d9, 0xaa8a05e4, 0x7af0a5a3, 0xcad9c59e, 0xda05e52c,
    0x6a2c8511, 0xba562556, 0x0a7f456b, 0x597ff589, 0xe95695b4,
    0x392c35f3, 0x890555ce, 0x99d9757c, 0x29f01541, 0xf98ab506,
    0x49a3d53b, 0x983485b9, 0x281de584, 0xf86745c3, 0x484e25fe,
    0x5892054c, 0xe8bb6571, 0x38c1c536, 0x88e8a50b, 0xdfc7d428,
    0x6feeb415, 0xbf941452, 0x0fbd746f, 0x1f6154dd, 0xaf4834e0,
    0x7f3294a7, 0xcf1bf49a, 0x1e8ca418, 0xaea5c425, 0x7edf6462,
    0xcef6045f, 0xde2a24ed, 0x6e0344d0, 0xbe79e497, 0x0e5084aa,
    0x5d503448, 0xed795475, 0x3d03f432, 0x8d2a940f, 0x9df6b4bd,
    0x2ddfd480, 0xfda574c7, 0x4d8c14fa, 0x9c1b4478, 0x2c322445,
    0xfc488402, 0x4c61e43f, 0x5cbdc48d, 0xec94a4b0, 0x3cee04f7,
    0x8cc764ca},
   {0x00000000, 0xa5d35ccb, 0x0ba1c84d, 0xae729486, 0x1642919b,
    0xb391cd50, 0x1de359d6, 0xb830051d, 0x6d8253ec, 0xc8510f27,
    0x66239ba1, 0xc3f0c76a, 0x7bc0c277, 0xde139ebc, 0x70610a3a,
    0xd5b256f1, 0x9b02d603, 0x3ed18ac8, 0x90a31e4e, 0x35704285,
    0x8d404798, 0x28931b53, 0x86e18fd5, 0x2332d31e, 0xf68085ef,
    0x5353d924, 0xfd214da2, 0x58f21169, 0xe0c21474, 0x451148bf,
    0xeb63dc39, 0x4eb080f2, 0x3605ac07, 0x93d6f0cc, 0x3da4644a,
    0x98773881, 0x20473d9c, 0x85946157, 0x2be6f5d1, 0x8e35a91a,
    0x5b87ffeb, 0xfe54a320, 0x502637a6, 0xf5f56b6d, 0x4dc56e70,
    0xe81632bb, 0x4664a63d, 0xe3b7faf6, 0xad077a04, 0x08d426cf,
    0xa6a6b249, 0x0375ee82, 0xbb45eb9f, 0x1e96b754, 0xb0e423d2,
    0x15377f19, 0xc08529e8, 0x65567523, 0xcb24e1a5, 0x6ef7bd6e,
    0xd6c7b873, 0x7314e4b8, 0xdd66703e, 0x78b52cf5, 0x6c0a580f,
    0xc9d904c4, 0x67ab9042, 0xc278cc89, 0x7a48c994, 0xdf9b955f,
    0x71e901d9, 0xd43a5d12, 0x01880be3, 0xa45b5728, 0x0a29c3ae,
    0xaffa9f65, 0x17ca9a78, 0xb219c6b3, 0x1c6b5235, 0xb9b80efe,
    0xf7088e0c, 0x52dbd2c7, 0xfca94641, 0x597a1a8a, 0xe14a1f97,
    0x4499435c, 0xeaebd7da, 0x4f388b11, 0x9a8adde0, 0x3f59812b,
    0x912b15ad, 0x34f84966, 0x8cc84c7b, 0x291b10b0, 0x87698436,
    0x22bad8fd, 0x5a0ff408, 0xffdca8c3, 0x51ae3c45, 0xf47d608e,
    0x4c4d6593, 0xe99e3958, 0x47ecadde, 0xe23ff115, 0x378da7e4,
    0x925efb2f, 0x3c2c6fa9, 0x99ff3362, 0x21cf367f, 0x841c6ab4,
    0x2a6efe32, 0x8fbda2f9, 0xc10d220b, 0x64de7ec0, 0xcaacea46,
    0x6f7fb68d, 0xd74fb390, 0x729cef5b, 0xdcee7bdd, 0x793d2716,
    0xac8f71e7, 0x095c2d2c, 0xa72eb9aa, 0x02fde561, 0xbacde07c,
    0x1f1ebcb7, 0xb16c2831, 0x14bf74fa, 0xd814b01e, 0x7dc7ecd5,
    0xd3b57853, 0x76662498, 0xce562185, 0x6b857d4e, 0xc5f7e9c8,
    0x6024b503, 0xb596e3f2, 0x1045bf39, 0xbe372bbf, 0x1be47774,
    0xa3d47269, 0x06072ea2, 0xa875ba24, 0x0da6e6ef, 0x4316661d,
    0xe6c53ad6, 0x48b7ae50, 0xed64f29b, 0x5554f786, 0xf087ab4d,
    0x5ef53fcb, 0xfb266300, 0x2e9435f1, 0x8b47693a, 0x2535fdbc,
    0x80e6a177, 0x38d6a46a, 0x9d05f8a1, 0x33776c27, 0x96a430ec,
    0xee111c19, 0x4bc240d2, 0xe5b0d454, 0x4063889f, 0xf8538d82,
    0x5d80d149, 0xf3f245cf, 0x56211904, 0x83934ff5, 0x2640133e,
    0x883287b8, 0x2de1db73, 0x95d1de6e, 0x300282a5, 0x9e701623,
    0x3ba34ae8, 0x7513ca1a, 0xd0c096d1, 0x7eb20257, 0xdb615e9c,
    0x63515b81, 0xc682074a, 0x68f093cc, 0xcd23cf07, 0x189199f6,
    0xbd42c53d, 0x133051bb, 0xb6e30d70, 0x0ed3086d, 0xab0054a6,
    0x0572c020, 0xa0a19ceb, 0xb41ee811, 0x11cdb4da, 0xbfbf205c,
    0x1a6c7c97, 0xa25c798a, 0x078f2541, 0xa9fdb1c7, 0x0c2eed0c,
    0xd99cbbfd, 0x7c4fe736, 0xd23d73b0, 0x77ee2f7b, 0xcfde2a66,
    0x6a0d76ad, 0xc47fe22b, 0x61acbee0, 0x2f1c3e12, 0x8acf62d9,
    0x24bdf65f, 0x816eaa94, 0x395eaf89, 0x9c8df342, 0x32ff67c4,
    0x972c3b0f, 0x429e6dfe, 0xe74d3135, 0x493fa5b3, 0xececf978,
    0x54dcfc65, 0xf10fa0ae, 0x5f7d3428, 0xfaae68e3, 0x821b4416,
    0x27c818dd, 0x89ba8c5b, 0x2c69d090, 0x9459d58d, 0x318a8946,
    0x9ff81dc0, 0x3a2b410b, 0xef9917fa, 0x4a4a4b31, 0xe438dfb7,
    0x41eb837c, 0xf9db8661, 0x5c08daaa, 0xf27a4e2c, 0x57a912e7,
    0x19199215, 0xbccacede, 0x12b85a58, 0xb76b0693, 0x0f5b038e,
    0xaa885f45, 0x04facbc3, 0xa1299708, 0x749bc1f9, 0xd1489d32,
    0x7f3a09b4, 0xdae9557f, 0x62d95062, 0xc70a0ca9, 0x6978982f,
    0xccabc4e4},
   {0x00000000, 0xb40b77a6, 0x29119f97, 0x9d1ae831, 0x13244ff4,
    0xa72f3852, 0x3a35d063, 0x8e3ea7c5, 0x674eef33, 0xd3459895,
    0x4e5f70a4, 0xfa540702, 0x746aa0c7, 0xc061d761, 0x5d7b3f50,
    0xe97048f6, 0xce9cde67, 0x7a97a9c1, 0xe78d41f0, 0x53863656,
    0xddb89193, 0x69b3e635, 0xf4a90e04, 0x40a279a2, 0xa9d23154,
    0x1dd946f2, 0x80c3aec3, 0x34c8d965, 0xbaf67ea0, 0x0efd0906,
    0x93e7e137, 0x27ec9691, 0x9c39bdcf, 0x2832ca69, 0xb5282258,
    0x012355fe, 0x8f1df23b, 0x3b16859d, 0xa60c6dac, 0x12071a0a,
    0xfb7752fc, 0x4f7c255a, 0xd266cd6b, 0x666dbacd, 0xe8531d08,
    0x5c586aae, 0xc142829f, 0x7549f539, 0x52a563a8, 0xe6ae140e,
    0x7bb4fc3f, 0xcfbf8b99, 0x41812c5c, 0xf58a5bfa, 0x6890b3cb,
    0xdc9bc46d, 0x35eb8c9b, 0x81e0fb3d, 0x1cfa130c, 0xa8f164aa,
    0x26cfc36f, 0x92c4b4c9, 0x0fde5cf8, 0xbbd52b5e, 0x79750b44,
    0xcd7e7ce2, 0x506494d3, 0xe46fe375, 0x6a5144b0, 0xde5a3316,
    0x4340db27, 0xf74bac81, 0x1e3be477, 0xaa3093d1, 0x372a7be0,
    0x83210c46, 0x0d1fab83, 0xb914dc25, 0x240e3414, 0x900543b2,
    0xb7e9d523, 0x03e2a285, 0x9ef84ab4, 0x2af33d12, 0xa4cd9ad7,
    0x10c6ed71, 0x8ddc0540, 0x39d772e6, 0xd0a73a10, 0x64ac4db6,
    0xf9b6a587, 0x4dbdd221, 0xc38375e4, 0x77880242, 0xea92ea73,
    0x5e999dd5, 0xe54cb68b, 0x5147c12d, 0xcc5d291c, 0x78565eba,
    0xf668f97f, 0x42638ed9, 0xdf7966e8, 0x6b72114e, 0x820259b8,
    0x36092e1e, 0xab13c62f, 0x1f18b189, 0x9126164c, 0x252d61ea,
    0xb83789db, 0x0c3cfe7d, 0x2bd068ec, 0x9fdb1f4a, 0x02c1f77b,
    0xb6ca80dd, 0x38f42718, 0x8cff50be, 0x11e5b88f, 0xa5eecf29,
    0x4c9e87df, 0xf895f079, 0x658f1848, 0xd1846fee, 0x5fbac82b,
    0xebb1bf8d, 0x76ab57bc, 0xc2a0201a, 0xf2ea1688, 0x46e1612e,
    0xdbfb891f, 0x6ff0feb9, 0xe1ce597c, 0x55c52eda, 0xc8dfc6eb,
    0x7cd4b14d, 0x95a4f9bb, 0x21af8e1d, 0xbcb5662c, 0x08be118a,
    0x8680b64f, 0x328bc1e9, 0xaf9129d8, 0x1b9a5e7e, 0x3c76c8ef,
    0x887dbf49, 0x15675778, 0xa16c20de, 0x2f52871b, 0x9b59f0bd,
    0x0643188c, 0xb2486f2a, 0x5b3827dc, 0xef33507a, 0x7229b84b,
    0xc622cfed, 0x481c6828, 0xfc171f8e, 0x610df7bf, 0xd5068019,
    0x6ed3ab47, 0xdad8dce1, 0x47c234d0, 0xf3c94376, 0x7df7e4b3,
    0xc9fc9315, 0x54e67b24, 0xe0ed0c82, 0x099d4474, 0xbd9633d2,
    0x208cdbe3, 0x9487ac45, 0x1ab90b80, 0xaeb27c26, 0x33a89417,
    0x87a3e3b1, 0xa04f7520, 0x14440286, 0x895eeab7, 0x3d559d11,
    0xb36b3ad4, 0x07604d72, 0x9a7aa543, 0x2e71d2e5, 0xc7019a13,
    0x730aedb5, 0xee100584, 0x5a1b7222, 0xd425d5e7, 0x602ea241,
    0xfd344a70, 0x493f3dd6, 0x8b9f1dcc, 0x3f946a6a, 0xa28e825b,
    0x1685f5fd, 0x98bb5238, 0x2cb0259e, 0xb1aacdaf, 0x05a1ba09,
    0xecd1f2ff, 0x58da8559, 0xc5c06d68, 0x71cb1ace, 0xfff5bd0b,
    0x4bfecaad, 0xd6e4229c, 0x62ef553a, 0x4503c3ab, 0xf108b40d,
    0x6c125c3c, 0xd8192b9a, 0x56278c5f, 0xe22cfbf9, 0x7f3613c8,
    0xcb3d646e, 0x224d2c98, 0x96465b3e, 0x0b5cb30f, 0xbf57c4a9,
    0x3169636c, 0x856214ca, 0x1878fcfb, 0xac738b5d, 0x17a6a003,
    0xa3add7a5, 0x3eb73f94, 0x8abc4832, 0x0482eff7, 0xb0899851,
    0x2d937060, 0x999807c6, 0x70e84f30, 0xc4e33896, 0x59f9d0a7,
    0xedf2a701, 0x63cc00c4, 0xd7c77762, 0x4add9f53, 0xfed6e8f5,
    0xd93a7e64, 0x6d3109c2, 0xf02be1f3, 0x44209655, 0xca1e3190,
    0x7e154636, 0xe30fae07, 0x5704d9a1, 0xbe749157, 0x0a7fe6f1,
    0x97650ec0, 0x236e7966, 0xad50dea3, 0x195ba905, 0x84414134,
    0x304a3692},
   {0x00000000, 0x9e00aacc, 0x7d072542, 0xe3078f8e, 0xfa0e4a84,
    0x640ee048, 0x87096fc6, 0x1909c50a, 0xb51be5d3, 0x2b1b4f1f,
    0xc81cc091, 0x561c6a5d, 0x4f15af57, 0xd115059b, 0x32128a15,
    0xac1220d9, 0x2b31bb7c, 0xb53111b0, 0x56369e3e, 0xc83634f2,
    0xd13ff1f8, 0x4f3f5b34, 0xac38d4ba, 0x32387e76, 0x9e2a5eaf,
    0x002af463, 0xe32d7bed, 0x7d2dd121, 0x6424142b, 0xfa24bee7,
    0x19233169, 0x87239ba5, 0x566276f9, 0xc862dc35, 0x2b6553bb,
    0xb565f977, 0xac6c3c7d, 0x326c96b1, 0xd16b193f, 0x4f6bb3f3,
    0xe379932a, 0x7d7939e6, 0x9e7eb668, 0x007e1ca4, 0x1977d9ae,
    0x87777362, 0x6470fcec, 0xfa705620, 0x7d53cd85, 0xe3536749,
    0x0054e8c7, 0x9e54420b, 0x875d8701, 0x195d2dcd, 0xfa5aa243,
    0x645a088f, 0xc8482856, 0x5648829a, 0xb54f0d14, 0x2b4fa7d8,
    0x324662d2, 0xac46c81e, 0x4f414790, 0xd141ed5c, 0xedc29d29,
    0x73c237e5, 0x90c5b86b, 0x0ec512a7, 0x17ccd7ad, 0x89cc7d61,
    0x6acbf2ef, 0xf4cb5823, 0x58d978fa, 0xc6d9d236, 0x25de5db8,
    0xbbdef774, 0xa2d7327e, 0x3cd798b2, 0xdfd0173c, 0x41d0bdf0,
    0xc6f32655, 0x58f38c99, 0xbbf40317, 0x25f4a9db, 0x3cfd6cd1,
    0xa2fdc61d, 0x41fa4993, 0xdffae35f, 0x73e8c386, 0xede8694a,
    0x0eefe6c4, 0x90ef4c08, 0x89e68902, 0x17e623ce, 0xf4e1ac40,
    0x6ae1068c, 0xbba0ebd0, 0x25a0411c, 0xc6a7ce92, 0x58a7645e,
    0x41aea154, 0xdfae0b98, 0x3ca98416, 0xa2a92eda, 0x0ebb0e03,
    0x90bba4cf, 0x73bc2b41, 0xedbc818d, 0xf4b54487, 0x6ab5ee4b,
    0x89b261c5, 0x17b2cb09, 0x909150ac, 0x0e91fa60, 0xed9675ee,
    0x7396df22, 0x6a9f1a28, 0xf49fb0e4, 0x17983f6a, 0x899895a6,
    0x258ab57f, 0xbb8a1fb3, 0x588d903d, 0xc68d3af1, 0xdf84fffb,
    0x41845537, 0xa283dab9, 0x3c837075, 0xda853b53, 0x4485919f,
    0xa7821e11, 0x3982b4dd, 0x208b71d7, 0xbe8bdb1b, 0x5d8c5495,
    0xc38cfe59, 0x6f9ede80, 0xf19e744c, 0x1299fbc2, 0x8c99510e,
    0x95909404, 0x0b903ec8, 0xe897b146, 0x76971b8a, 0xf1b4802f,
    0x6fb42ae3, 0x8cb3a56d, 0x12b30fa1, 0x0bbacaab, 0x95ba6067,
    0x76bdefe9, 0xe8bd4525, 0x44af65fc, 0xdaafcf30, 0x39a840be,
    0xa7a8ea72, 0xbea12f78, 0x20a185b4, 0xc3a60a3a, 0x5da6a0f6,
    0x8ce74daa, 0x12e7e766, 0xf1e068e8, 0x6fe0c224, 0x76e9072e,
    0xe8e9ade2, 0x0bee226c, 0x95ee88a0, 0x39fca879, 0xa7fc02b5,
    0x44fb8d3b, 0xdafb27f7, 0xc3f2e2fd, 0x5df24831, 0xbef5c7bf,
    0x20f56d73, 0xa7d6f6d6, 0x39d65c1a, 0xdad1d394, 0x44d17958,
    0x5dd8bc52, 0xc3d8169e, 0x20df9910, 0xbedf33dc, 0x12cd1305,
    0x8ccdb9c9, 0x6fca3647, 0xf1ca9c8b, 0xe8c35981, 0x76c3f34d,
    0x95c47cc3, 0x0bc4d60f, 0x3747a67a, 0xa9470cb6, 0x4a408338,
    0xd44029f4, 0xcd49ecfe, 0x53494632, 0xb04ec9bc, 0x2e4e6370,
    0x825c43a9, 0x1c5ce965, 0xff5b66eb, 0x615bcc27, 0x7852092d,
    0xe652a3e1, 0x05552c6f, 0x9b5586a3, 0x1c761d06, 0x8276b7ca,
    0x61713844, 0xff719288, 0xe6785782, 0x7878fd4e, 0x9b7f72c0,
    0x057fd80c, 0xa96df8d5, 0x376d5219, 0xd46add97, 0x4a6a775b,
    0x5363b251, 0xcd63189d, 0x2e649713, 0xb0643ddf, 0x6125d083,
    0xff257a4f, 0x1c22f5c1, 0x82225f0d, 0x9b2b9a07, 0x052b30cb,
    0xe62cbf45, 0x782c1589, 0xd43e3550, 0x4a3e9f9c, 0xa9391012,
    0x3739bade, 0x2e307fd4, 0xb030d518, 0x53375a96, 0xcd37f05a,
    0x4a146bff, 0xd414c133, 0x37134ebd, 0xa913e471, 0xb01a217b,
    0x2e1a8bb7, 0xcd1d0439, 0x531daef5, 0xff0f8e2c, 0x610f24e0,
    0x8208ab6e, 0x1c0801a2, 0x0501c4a8, 0x9b016e64, 0x7806e1ea,
    0xe6064b26}};

#endif

#endif

#if N == 3

#if W == 8

local const z_crc_t FAR crc_braid_table[][256] = {
   {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f,
    0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999,
    0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee,
    0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615,
    0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383,
    0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb,
    0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275,
    0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d,
    0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b,
    0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460,
    0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317,
    0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1,
    0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5,
    0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd,
    0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04,
    0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c,
    0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7,
    0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11,
    0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66,
    0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7,
    0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871,
    0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309,
    0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd,
    0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85,
    0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913,
    0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d,
    0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a,
    0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc,
    0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57,
    0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f,
    0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6,
    0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e,
    0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f,
    0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289,
    0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe,
    0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05,
    0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893,
    0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb,
    0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0,
    0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8,
    0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e,
    0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5,
    0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2,
    0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574,
    0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5,
    0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add,
    0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114,
    0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c,
    0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7,
    0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701,
    0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076,
    0x09cd8551},
   {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193,
    0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2,
    0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c,
    0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71,
    0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a,
    0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d,
    0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71,
    0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436,
    0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d,
    0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000,
    0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae,
    0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf,
    0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930,
    0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277,
    0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff,
    0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8,
    0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef,
    0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e,
    0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20,
    0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95,
    0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e,
    0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9,
    0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d,
    0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a,
    0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151,
    0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4,
    0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a,
    0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b,
    0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c,
    0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b,
    0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3,
    0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4,
    0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b,
    0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a,
    0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4,
    0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189,
    0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92,
    0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5,
    0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9,
    0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe,
    0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5,
    0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8,
    0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66,
    0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707,
    0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8,
    0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f,
    0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707,
    0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40,
    0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017,
    0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876,
    0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8,
    0x7bc97a0c},
   {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300,
    0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0,
    0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80,
    0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701,
    0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41,
    0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81,
    0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43,
    0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83,
    0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3,
    0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42,
    0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202,
    0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2,
    0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7,
    0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407,
    0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47,
    0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87,
    0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86,
    0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46,
    0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506,
    0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44,
    0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704,
    0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4,
    0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5,
    0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505,
    0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45,
    0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f,
    0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f,
    0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f,
    0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e,
    0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e,
    0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e,
    0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce,
    0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c,
    0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc,
    0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c,
    0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d,
    0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d,
    0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d,
    0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88,
    0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48,
    0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708,
    0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89,
    0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9,
    0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309,
    0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb,
    0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b,
    0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b,
    0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b,
    0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a,
    0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a,
    0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a,
    0x7851a2ca},
   {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb,
    0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8,
    0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0,
    0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f,
    0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a,
    0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf,
    0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5,
    0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380,
    0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815,
    0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa,
    0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2,
    0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1,
    0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1,
    0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4,
    0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa,
    0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df,
    0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6,
    0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5,
    0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad,
    0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca,
    0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f,
    0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a,
    0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8,
    0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d,
    0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708,
    0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d,
    0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865,
    0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636,
    0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f,
    0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a,
    0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744,
    0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061,
    0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0,
    0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293,
    0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb,
    0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874,
    0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1,
    0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4,
    0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f,
    0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a,
    0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f,
    0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120,
    0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778,
    0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b,
    0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a,
    0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af,
    0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81,
    0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4,
    0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd,
    0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e,
    0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6,
    0x566b6848},
   {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59,
    0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4,
    0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67,
    0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef,
    0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97,
    0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88,
    0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687,
    0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698,
    0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0,
    0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068,
    0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb,
    0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056,
    0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016,
    0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009,
    0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028,
    0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037,
    0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a,
    0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7,
    0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054,
    0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7,
    0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af,
    0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0,
    0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4,
    0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab,
    0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3,
    0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a,
    0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9,
    0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54,
    0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09,
    0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16,
    0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37,
    0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28,
    0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e,
    0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3,
    0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40,
    0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8,
    0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0,
    0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf,
    0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6,
    0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9,
    0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1,
    0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059,
    0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca,
    0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067,
    0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031,
    0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e,
    0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f,
    0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010,
    0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d,
    0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0,
    0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073,
    0xd8ac6b35},
  {
    0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
    0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
    0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
    0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
    0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
    0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
    0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
    0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
    0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
    0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
    0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
    0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
    0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
    0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
    0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
    0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
    0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
    0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
    0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
    0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
    0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
    0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
    0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
    0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
    0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
    0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
    0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
    0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
    0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
    0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
    0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
    0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
    0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
    0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
    0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
    0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
    0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
    0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
    0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
    0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
    0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
    0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
    0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
    0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
    0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
    0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
    0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
    0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
    0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
    0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
    0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
    0xde0506f1UL
  },
  {
    0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
    0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
    0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
    0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
    0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
    0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
    0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
    0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
    0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
    0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
    0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
    0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
    0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
    0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
    0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
    0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
    0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
    0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
    0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
    0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
    0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
    0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
    0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
    0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
    0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
    0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
    0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
    0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
    0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
    0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
    0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
    0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
    0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
    0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
    0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
    0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
    0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
    0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
    0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
    0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
    0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
    0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
    0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
    0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
    0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
    0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
    0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
    0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
    0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
    0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
    0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
    0x8def022dUL
  },
  {
    0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
   {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2,
    0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd,
    0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696,
    0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3,
    0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f,
    0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35,
    0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5,
    0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f,
    0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673,
    0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46,
    0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d,
    0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632,
    0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28,
    0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192,
    0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c,
    0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6,
    0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0,
    0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff,
    0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4,
    0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95,
    0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9,
    0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03,
    0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7,
    0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d,
    0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151,
    0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808,
    0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343,
    0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c,
    0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a,
    0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0,
    0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e,
    0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594,
    0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6,
    0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399,
    0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2,
    0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7,
    0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb,
    0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571,
    0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289,
    0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33,
    0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f,
    0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a,
    0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461,
    0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e,
    0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c,
    0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6,
    0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918,
    0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2,
    0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484,
    0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb,
    0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0,
    0xa140efa8},
   {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706,
    0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed,
    0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289,
    0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a,
    0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214,
    0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3,
    0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3,
    0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254,
    0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a,
    0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9,
    0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad,
    0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746,
    0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060,
    0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187,
    0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef,
    0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408,
    0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e,
    0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495,
    0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1,
    0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532,
    0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c,
    0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb,
    0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb,
    0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c,
    0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42,
    0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060,
    0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04,
    0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef,
    0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99,
    0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e,
    0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16,
    0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1,
    0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7,
    0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c,
    0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38,
    0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb,
    0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5,
    0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42,
    0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62,
    0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85,
    0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb,
    0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18,
    0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c,
    0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997,
    0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1,
    0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36,
    0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e,
    0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9,
    0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf,
    0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24,
    0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040,
    0x917cd6a1},
   {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf,
    0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd,
    0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896,
    0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9,
    0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3,
    0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f,
    0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d,
    0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1,
    0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab,
    0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4,
    0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f,
    0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d,
    0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4,
    0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978,
    0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad,
    0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621,
    0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46,
    0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854,
    0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f,
    0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a,
    0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890,
    0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c,
    0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4,
    0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238,
    0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622,
    0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab,
    0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0,
    0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2,
    0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295,
    0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19,
    0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc,
    0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140,
    0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd,
    0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf,
    0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184,
    0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb,
    0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1,
    0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d,
    0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb,
    0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257,
    0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d,
    0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22,
    0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069,
    0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b,
    0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6,
    0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a,
    0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf,
    0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33,
    0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254,
    0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146,
    0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d,
    0x18ba364e}};

local const z_word_t FAR crc_braid_big_table[][256] = {
   {0x0000000000000000, 0x43cba68700000000, 0xc7903cd400000000,
    0x845b9a5300000000, 0xcf27087300000000, 0x8cecaef400000000,
    0x08b734a700000000, 0x4b7c922000000000, 0x9e4f10e600000000,
    0xdd84b66100000000, 0x59df2c3200000000, 0x1a148ab500000000,
    0x5168189500000000, 0x12a3be1200000000, 0x96f8244100000000,
    0xd53382c600000000, 0x7d99511700000000, 0x3e52f79000000000,
    0xba096dc300000000, 0xf9c2cb4400000000, 0xb2be596400000000,
    0xf175ffe300000000, 0x752e65b000000000, 0x36e5c33700000000,
    0xe3d641f100000000, 0xa01de77600000000, 0x24467d2500000000,
    0x678ddba200000000, 0x2cf1498200000000, 0x6f3aef0500000000,
    0xeb61755600000000, 0xa8aad3d100000000, 0xfa32a32e00000000,
    0xb9f905a900000000, 0x3da29ffa00000000, 0x7e69397d00000000,
    0x3515ab5d00000000, 0x76de0dda00000000, 0xf285978900000000,
    0xb14e310e00000000, 0x647db3c800000000, 0x27b6154f00000000,
    0xa3ed8f1c00000000, 0xe026299b00000000, 0xab5abbbb00000000,
    0xe8911d3c00000000, 0x6cca876f00000000, 0x2f0121e800000000,
    0x87abf23900000000, 0xc46054be00000000, 0x403bceed00000000,
    0x03f0686a00000000, 0x488cfa4a00000000, 0x0b475ccd00000000,
    0x8f1cc69e00000000, 0xccd7601900000000, 0x19e4e2df00000000,
    0x5a2f445800000000, 0xde74de0b00000000, 0x9dbf788c00000000,
    0xd6c3eaac00000000, 0x95084c2b00000000, 0x1153d67800000000,
    0x529870ff00000000, 0xf465465d00000000, 0xb7aee0da00000000,
    0x33f57a8900000000, 0x703edc0e00000000, 0x3b424e2e00000000,
    0x7889e8a900000000, 0xfcd272fa00000000, 0xbf19d47d00000000,
    0x6a2a56bb00000000, 0x29e1f03c00000000, 0xadba6a6f00000000,
    0xee71cce800000000, 0xa50d5ec800000000, 0xe6c6f84f00000000,
    0x629d621c00000000, 0x2156c49b00000000, 0x89fc174a00000000,
    0xca37b1cd00000000, 0x4e6c2b9e00000000, 0x0da78d1900000000,
    0x46db1f3900000000, 0x0510b9be00000000, 0x814b23ed00000000,
    0xc280856a00000000, 0x17b307ac00000000, 0x5478a12b00000000,
    0xd0233b7800000000, 0x93e89dff00000000, 0xd8940fdf00000000,
    0x9b5fa95800000000, 0x1f04330b00000000, 0x5ccf958c00000000,
    0x0e57e57300000000, 0x4d9c43f400000000, 0xc9c7d9a700000000,
    0x8a0c7f2000000000, 0xc170ed0000000000, 0x82bb4b8700000000,
    0x06e0d1d400000000, 0x452b775300000000, 0x9018f59500000000,
    0xd3d3531200000000, 0x5788c94100000000, 0x14436fc600000000,
    0x5f3ffde600000000, 0x1cf45b6100000000, 0x98afc13200000000,
    0xdb6467b500000000, 0x73ceb46400000000, 0x300512e300000000,
    0xb45e88b000000000, 0xf7952e3700000000, 0xbce9bc1700000000,
    0xff221a9000000000, 0x7b7980c300000000, 0x38b2264400000000,
    0xed81a48200000000, 0xae4a020500000000, 0x2a11985600000000,
    0x69da3ed100000000, 0x22a6acf100000000, 0x616d0a7600000000,
    0xe536902500000000, 0xa6fd36a200000000, 0xe8cb8cba00000000,
    0xab002a3d00000000, 0x2f5bb06e00000000, 0x6c9016e900000000,
    0x27ec84c900000000, 0x6427224e00000000, 0xe07cb81d00000000,
    0xa3b71e9a00000000, 0x76849c5c00000000, 0x354f3adb00000000,
    0xb114a08800000000, 0xf2df060f00000000, 0xb9a3942f00000000,
    0xfa6832a800000000, 0x7e33a8fb00000000, 0x3df80e7c00000000,
    0x9552ddad00000000, 0xd6997b2a00000000, 0x52c2e17900000000,
    0x110947fe00000000, 0x5a75d5de00000000, 0x19be735900000000,
    0x9de5e90a00000000, 0xde2e4f8d00000000, 0x0b1dcd4b00000000,
    0x48d66bcc00000000, 0xcc8df19f00000000, 0x8f46571800000000,
    0xc43ac53800000000, 0x87f163bf00000000, 0x03aaf9ec00000000,
    0x40615f6b00000000, 0x12f92f9400000000, 0x5132891300000000,
    0xd569134000000000, 0x96a2b5c700000000, 0xddde27e700000000,
    0x9e15816000000000, 0x1a4e1b3300000000, 0x5985bdb400000000,
    0x8cb63f7200000000, 0xcf7d99f500000000, 0x4b2603a600000000,
    0x08eda52100000000, 0x4391370100000000, 0x005a918600000000,
    0x84010bd500000000, 0xc7caad5200000000, 0x6f607e8300000000,
    0x2cabd80400000000, 0xa8f0425700000000, 0xeb3be4d000000000,
    0xa04776f000000000, 0xe38cd07700000000, 0x67d74a2400000000,
    0x241ceca300000000, 0xf12f6e6500000000, 0xb2e4c8e200000000,
    0x36bf52b100000000, 0x7574f43600000000, 0x3e08661600000000,
    0x7dc3c09100000000, 0xf9985ac200000000, 0xba53fc4500000000,
    0x1caecae700000000, 0x5f656c6000000000, 0xdb3ef63300000000,
    0x98f550b400000000, 0xd389c29400000000, 0x9042641300000000,
    0x1419fe4000000000, 0x57d258c700000000, 0x82e1da0100000000,
    0xc12a7c8600000000, 0x4571e6d500000000, 0x06ba405200000000,
    0x4dc6d27200000000, 0x0e0d74f500000000, 0x8a56eea600000000,
    0xc99d482100000000, 0x61379bf000000000, 0x22fc3d7700000000,
    0xa6a7a72400000000, 0xe56c01a300000000, 0xae10938300000000,
    0xeddb350400000000, 0x6980af5700000000, 0x2a4b09d000000000,
    0xff788b1600000000, 0xbcb32d9100000000, 0x38e8b7c200000000,
    0x7b23114500000000, 0x305f836500000000, 0x739425e200000000,
    0xf7cfbfb100000000, 0xb404193600000000, 0xe69c69c900000000,
    0xa557cf4e00000000, 0x210c551d00000000, 0x62c7f39a00000000,
    0x29bb61ba00000000, 0x6a70c73d00000000, 0xee2b5d6e00000000,
    0xade0fbe900000000, 0x78d3792f00000000, 0x3b18dfa800000000,
    0xbf4345fb00000000, 0xfc88e37c00000000, 0xb7f4715c00000000,
    0xf43fd7db00000000, 0x70644d8800000000, 0x33afeb0f00000000,
    0x9b0538de00000000, 0xd8ce9e5900000000, 0x5c95040a00000000,
    0x1f5ea28d00000000, 0x542230ad00000000, 0x17e9962a00000000,
    0x93b20c7900000000, 0xd079aafe00000000, 0x054a283800000000,
    0x46818ebf00000000, 0xc2da14ec00000000, 0x8111b26b00000000,
    0xca6d204b00000000, 0x89a686cc00000000, 0x0dfd1c9f00000000,
    0x4e36ba1800000000},
   {0x0000000000000000, 0xe1b652ef00000000, 0x836bd40500000000,
    0x62dd86ea00000000, 0x06d7a80b00000000, 0xe761fae400000000,
    0x85bc7c0e00000000, 0x640a2ee100000000, 0x0cae511700000000,
    0xed1803f800000000, 0x8fc5851200000000, 0x6e73d7fd00000000,
    0x0a79f91c00000000, 0xebcfabf300000000, 0x89122d1900000000,
    0x68a47ff600000000, 0x185ca32e00000000, 0xf9eaf1c100000000,
    0x9b37772b00000000, 0x7a8125c400000000, 0x1e8b0b2500000000,
    0xff3d59ca00000000, 0x9de0df2000000000, 0x7c568dcf00000000,
    0x14f2f23900000000, 0xf544a0d600000000, 0x9799263c00000000,
    0x762f74d300000000, 0x12255a3200000000, 0xf39308dd00000000,
    0x914e8e3700000000, 0x70f8dcd800000000, 0x30b8465d00000000,
    0xd10e14b200000000, 0xb3d3925800000000, 0x5265c0b700000000,
    0x366fee5600000000, 0xd7d9bcb900000000, 0xb5043a5300000000,
    0x54b268bc00000000, 0x3c16174a00000000, 0xdda045a500000000,
    0xbf7dc34f00000000, 0x5ecb91a000000000, 0x3ac1bf4100000000,
    0xdb77edae00000000, 0xb9aa6b4400000000, 0x581c39ab00000000,
    0x28e4e57300000000, 0xc952b79c00000000, 0xab8f317600000000,
    0x4a39639900000000, 0x2e334d7800000000, 0xcf851f9700000000,
    0xad58997d00000000, 0x4ceecb9200000000, 0x244ab46400000000,
    0xc5fce68b00000000, 0xa721606100000000, 0x4697328e00000000,
    0x229d1c6f00000000, 0xc32b4e8000000000, 0xa1f6c86a00000000,
    0x40409a8500000000, 0x60708dba00000000, 0x81c6df5500000000,
    0xe31b59bf00000000, 0x02ad0b5000000000, 0x66a725b100000000,
    0x8711775e00000000, 0xe5ccf1b400000000, 0x047aa35b00000000,
    0x6cdedcad00000000, 0x8d688e4200000000, 0xefb508a800000000,
    0x0e035a4700000000, 0x6a0974a600000000, 0x8bbf264900000000,
    0xe962a0a300000000, 0x08d4f24c00000000, 0x782c2e9400000000,
    0x999a7c7b00000000, 0xfb47fa9100000000, 0x1af1a87e00000000,
    0x7efb869f00000000, 0x9f4dd47000000000, 0xfd90529a00000000,
    0x1c26007500000000, 0x74827f8300000000, 0x95342d6c00000000,
    0xf7e9ab8600000000, 0x165ff96900000000, 0x7255d78800000000,
    0x93e3856700000000, 0xf13e038d00000000, 0x1088516200000000,
    0x50c8cbe700000000, 0xb17e990800000000, 0xd3a31fe200000000,
    0x32154d0d00000000, 0x561f63ec00000000, 0xb7a9310300000000,
    0xd574b7e900000000, 0x34c2e50600000000, 0x5c669af000000000,
    0xbdd0c81f00000000, 0xdf0d4ef500000000, 0x3ebb1c1a00000000,
    0x5ab132fb00000000, 0xbb07601400000000, 0xd9dae6fe00000000,
    0x386cb41100000000, 0x489468c900000000, 0xa9223a2600000000,
    0xcbffbccc00000000, 0x2a49ee2300000000, 0x4e43c0c200000000,
    0xaff5922d00000000, 0xcd2814c700000000, 0x2c9e462800000000,
    0x443a39de00000000, 0xa58c6b3100000000, 0xc751eddb00000000,
    0x26e7bf3400000000, 0x42ed91d500000000, 0xa35bc33a00000000,
    0xc18645d000000000, 0x2030173f00000000, 0x81e66bae00000000,
    0x6050394100000000, 0x028dbfab00000000, 0xe33bed4400000000,
    0x8731c3a500000000, 0x6687914a00000000, 0x045a17a000000000,
    0xe5ec454f00000000, 0x8d483ab900000000, 0x6cfe685600000000,
    0x0e23eebc00000000, 0xef95bc5300000000, 0x8b9f92b200000000,
    0x6a29c05d00000000, 0x08f446b700000000, 0xe942145800000000,
    0x99bac88000000000, 0x780c9a6f00000000, 0x1ad11c8500000000,
    0xfb674e6a00000000, 0x9f6d608b00000000, 0x7edb326400000000,
    0x1c06b48e00000000, 0xfdb0e66100000000, 0x9514999700000000,
    0x74a2cb7800000000, 0x167f4d9200000000, 0xf7c91f7d00000000,
    0x93c3319c00000000, 0x7275637300000000, 0x10a8e59900000000,
    0xf11eb77600000000, 0xb15e2df300000000, 0x50e87f1c00000000,
    0x3235f9f600000000, 0xd383ab1900000000, 0xb78985f800000000,
    0x563fd71700000000, 0x34e251fd00000000, 0xd554031200000000,
    0xbdf07ce400000000, 0x5c462e0b00000000, 0x3e9ba8e100000000,
    0xdf2dfa0e00000000, 0xbb27d4ef00000000, 0x5a91860000000000,
    0x384c00ea00000000, 0xd9fa520500000000, 0xa9028edd00000000,
    0x48b4dc3200000000, 0x2a695ad800000000, 0xcbdf083700000000,
    0xafd526d600000000, 0x4e63743900000000, 0x2cbef2d300000000,
    0xcd08a03c00000000, 0xa5acdfca00000000, 0x441a8d2500000000,
    0x26c70bcf00000000, 0xc771592000000000, 0xa37b77c100000000,
    0x42cd252e00000000, 0x2010a3c400000000, 0xc1a6f12b00000000,
    0xe196e61400000000, 0x0020b4fb00000000, 0x62fd321100000000,
    0x834b60fe00000000, 0xe7414e1f00000000, 0x06f71cf000000000,
    0x642a9a1a00000000, 0x859cc8f500000000, 0xed38b70300000000,
    0x0c8ee5ec00000000, 0x6e53630600000000, 0x8fe531e900000000,
    0xebef1f0800000000, 0x0a594de700000000, 0x6884cb0d00000000,
    0x893299e200000000, 0xf9ca453a00000000, 0x187c17d500000000,
    0x7aa1913f00000000, 0x9b17c3d000000000, 0xff1ded3100000000,
    0x1eabbfde00000000, 0x7c76393400000000, 0x9dc06bdb00000000,
    0xf564142d00000000, 0x14d246c200000000, 0x760fc02800000000,
    0x97b992c700000000, 0xf3b3bc2600000000, 0x1205eec900000000,
    0x70d8682300000000, 0x916e3acc00000000, 0xd12ea04900000000,
    0x3098f2a600000000, 0x5245744c00000000, 0xb3f326a300000000,
    0xd7f9084200000000, 0x364f5aad00000000, 0x5492dc4700000000,
    0xb5248ea800000000, 0xdd80f15e00000000, 0x3c36a3b100000000,
    0x5eeb255b00000000, 0xbf5d77b400000000, 0xdb57595500000000,
    0x3ae10bba00000000, 0x583c8d5000000000, 0xb98adfbf00000000,
    0xc972036700000000, 0x28c4518800000000, 0x4a19d76200000000,
    0xabaf858d00000000, 0xcfa5ab6c00000000, 0x2e13f98300000000,
    0x4cce7f6900000000, 0xad782d8600000000, 0xc5dc527000000000,
    0x246a009f00000000, 0x46b7867500000000, 0xa701d49a00000000,
    0xc30bfa7b00000000, 0x22bda89400000000, 0x40602e7e00000000,
    0xa1d67c9100000000},
   {0x0000000000000000, 0x5880e2d700000000, 0xf106b47400000000,
    0xa98656a300000000, 0xe20d68e900000000, 0xba8d8a3e00000000,
    0x130bdc9d00000000, 0x4b8b3e4a00000000, 0x851da10900000000,
    0xdd9d43de00000000, 0x741b157d00000000, 0x2c9bf7aa00000000,
    0x6710c9e000000000, 0x3f902b3700000000, 0x96167d9400000000,
    0xce969f4300000000, 0x0a3b421300000000, 0x52bba0c400000000,
    0xfb3df66700000000, 0xa3bd14b000000000, 0xe8362afa00000000,
    0xb0b6c82d00000000, 0x19309e8e00000000, 0x41b07c5900000000,
    0x8f26e31a00000000, 0xd7a601cd00000000, 0x7e20576e00000000,
    0x26a0b5b900000000, 0x6d2b8bf300000000, 0x35ab692400000000,
    0x9c2d3f8700000000, 0xc4addd5000000000, 0x1476842600000000,
    0x4cf666f100000000, 0xe570305200000000, 0xbdf0d28500000000,
    0xf67beccf00000000, 0xaefb0e1800000000, 0x077d58bb00000000,
    0x5ffdba6c00000000, 0x916b252f00000000, 0xc9ebc7f800000000,
    0x606d915b00000000, 0x38ed738c00000000, 0x73664dc600000000,
    0x2be6af1100000000, 0x8260f9b200000000, 0xdae01b6500000000,
    0x1e4dc63500000000, 0x46cd24e200000000, 0xef4b724100000000,
    0xb7cb909600000000, 0xfc40aedc00000000, 0xa4c04c0b00000000,
    0x0d461aa800000000, 0x55c6f87f00000000, 0x9b50673c00000000,
    0xc3d085eb00000000, 0x6a56d34800000000, 0x32d6319f00000000,
    0x795d0fd500000000, 0x21dded0200000000, 0x885bbba100000000,
    0xd0db597600000000, 0x28ec084d00000000, 0x706cea9a00000000,
    0xd9eabc3900000000, 0x816a5eee00000000, 0xcae160a400000000,
    0x9261827300000000, 0x3be7d4d000000000, 0x6367360700000000,
    0xadf1a94400000000, 0xf5714b9300000000, 0x5cf71d3000000000,
    0x0477ffe700000000, 0x4ffcc1ad00000000, 0x177c237a00000000,
    0xbefa75d900000000, 0xe67a970e00000000, 0x22d74a5e00000000,
    0x7a57a88900000000, 0xd3d1fe2a00000000, 0x8b511cfd00000000,
    0xc0da22b700000000, 0x985ac06000000000, 0x31dc96c300000000,
    0x695c741400000000, 0xa7caeb5700000000, 0xff4a098000000000,
    0x56cc5f2300000000, 0x0e4cbdf400000000, 0x45c783be00000000,
    0x1d47616900000000, 0xb4c137ca00000000, 0xec41d51d00000000,
    0x3c9a8c6b00000000, 0x641a6ebc00000000, 0xcd9c381f00000000,
    0x951cdac800000000, 0xde97e48200000000, 0x8617065500000000,
    0x2f9150f600000000, 0x7711b22100000000, 0xb9872d6200000000,
    0xe107cfb500000000, 0x4881991600000000, 0x10017bc100000000,
    0x5b8a458b00000000, 0x030aa75c00000000, 0xaa8cf1ff00000000,
    0xf20c132800000000, 0x36a1ce7800000000, 0x6e212caf00000000,
    0xc7a77a0c00000000, 0x9f2798db00000000, 0xd4aca69100000000,
    0x8c2c444600000000, 0x25aa12e500000000, 0x7d2af03200000000,
    0xb3bc6f7100000000, 0xeb3c8da600000000, 0x42badb0500000000,
    0x1a3a39d200000000, 0x51b1079800000000, 0x0931e54f00000000,
    0xa0b7b3ec00000000, 0xf837513b00000000, 0x50d8119a00000000,
    0x0858f34d00000000, 0xa1dea5ee00000000, 0xf95e473900000000,
    0xb2d5797300000000, 0xea559ba400000000, 0x43d3cd0700000000,
    0x1b532fd000000000, 0xd5c5b09300000000, 0x8d45524400000000,
    0x24c304e700000000, 0x7c43e63000000000, 0x37c8d87a00000000,
    0x6f483aad00000000, 0xc6ce6c0e00000000, 0x9e4e8ed900000000,
    0x5ae3538900000000, 0x0263b15e00000000, 0xabe5e7fd00000000,
    0xf365052a00000000, 0xb8ee3b6000000000, 0xe06ed9b700000000,
    0x49e88f1400000000, 0x11686dc300000000, 0xdffef28000000000,
    0x877e105700000000, 0x2ef846f400000000, 0x7678a42300000000,
    0x3df39a6900000000, 0x657378be00000000, 0xccf52e1d00000000,
    0x9475ccca00000000, 0x44ae95bc00000000, 0x1c2e776b00000000,
    0xb5a821c800000000, 0xed28c31f00000000, 0xa6a3fd5500000000,
    0xfe231f8200000000, 0x57a5492100000000, 0x0f25abf600000000,
    0xc1b334b500000000, 0x9933d66200000000, 0x30b580c100000000,
    0x6835621600000000, 0x23be5c5c00000000, 0x7b3ebe8b00000000,
    0xd2b8e82800000000, 0x8a380aff00000000, 0x4e95d7af00000000,
    0x1615357800000000, 0xbf9363db00000000, 0xe713810c00000000,
    0xac98bf4600000000, 0xf4185d9100000000, 0x5d9e0b3200000000,
    0x051ee9e500000000, 0xcb8876a600000000, 0x9308947100000000,
    0x3a8ec2d200000000, 0x620e200500000000, 0x29851e4f00000000,
    0x7105fc9800000000, 0xd883aa3b00000000, 0x800348ec00000000,
    0x783419d700000000, 0x20b4fb0000000000, 0x8932ada300000000,
    0xd1b24f7400000000, 0x9a39713e00000000, 0xc2b993e900000000,
    0x6b3fc54a00000000, 0x33bf279d00000000, 0xfd29b8de00000000,
    0xa5a95a0900000000, 0x0c2f0caa00000000, 0x54afee7d00000000,
    0x1f24d03700000000, 0x47a432e000000000, 0xee22644300000000,
    0xb6a2869400000000, 0x720f5bc400000000, 0x2a8fb91300000000,
    0x8309efb000000000, 0xdb890d6700000000, 0x9002332d00000000,
    0xc882d1fa00000000, 0x6104875900000000, 0x3984658e00000000,
    0xf712facd00000000, 0xaf92181a00000000, 0x06144eb900000000,
    0x5e94ac6e00000000, 0x151f922400000000, 0x4d9f70f300000000,
    0xe419265000000000, 0xbc99c48700000000, 0x6c429df100000000,
    0x34c27f2600000000, 0x9d44298500000000, 0xc5c4cb5200000000,
    0x8e4ff51800000000, 0xd6cf17cf00000000, 0x7f49416c00000000,
    0x27c9a3bb00000000, 0xe95f3cf800000000, 0xb1dfde2f00000000,
    0x1859888c00000000, 0x40d96a5b00000000, 0x0b52541100000000,
    0x53d2b6c600000000, 0xfa54e06500000000, 0xa2d402b200000000,
    0x6679dfe200000000, 0x3ef93d3500000000, 0x977f6b9600000000,
    0xcfff894100000000, 0x8474b70b00000000, 0xdcf455dc00000000,
    0x7572037f00000000, 0x2df2e1a800000000, 0xe3647eeb00000000,
    0xbbe49c3c00000000, 0x1262ca9f00000000, 0x4ae2284800000000,
    0x0169160200000000, 0x59e9f4d500000000, 0xf06fa27600000000,
    0xa8ef40a100000000},
   {0x0000000000000000, 0x463b676500000000, 0x8c76ceca00000000,
    0xca4da9af00000000, 0x59ebed4e00000000, 0x1fd08a2b00000000,
    0xd59d238400000000, 0x93a644e100000000, 0xb2d6db9d00000000,
    0xf4edbcf800000000, 0x3ea0155700000000, 0x789b723200000000,
    0xeb3d36d300000000, 0xad0651b600000000, 0x674bf81900000000,
    0x21709f7c00000000, 0x25abc6e000000000, 0x6390a18500000000,
    0xa9dd082a00000000, 0xefe66f4f00000000, 0x7c402bae00000000,
    0x3a7b4ccb00000000, 0xf036e56400000000, 0xb60d820100000000,
    0x977d1d7d00000000, 0xd1467a1800000000, 0x1b0bd3b700000000,
    0x5d30b4d200000000, 0xce96f03300000000, 0x88ad975600000000,
    0x42e03ef900000000, 0x04db599c00000000, 0x0b50fc1a00000000,
    0x4d6b9b7f00000000, 0x872632d000000000, 0xc11d55b500000000,
    0x52bb115400000000, 0x1480763100000000, 0xdecddf9e00000000,
    0x98f6b8fb00000000, 0xb986278700000000, 0xffbd40e200000000,
    0x35f0e94d00000000, 0x73cb8e2800000000, 0xe06dcac900000000,
    0xa656adac00000000, 0x6c1b040300000000, 0x2a20636600000000,
    0x2efb3afa00000000, 0x68c05d9f00000000, 0xa28df43000000000,
    0xe4b6935500000000, 0x7710d7b400000000, 0x312bb0d100000000,
    0xfb66197e00000000, 0xbd5d7e1b00000000, 0x9c2de16700000000,
    0xda16860200000000, 0x105b2fad00000000, 0x566048c800000000,
    0xc5c60c2900000000, 0x83fd6b4c00000000, 0x49b0c2e300000000,
    0x0f8ba58600000000, 0x16a0f83500000000, 0x509b9f5000000000,
    0x9ad636ff00000000, 0xdced519a00000000, 0x4f4b157b00000000,
    0x0970721e00000000, 0xc33ddbb100000000, 0x8506bcd400000000,
    0xa47623a800000000, 0xe24d44cd00000000, 0x2800ed6200000000,
    0x6e3b8a0700000000, 0xfd9dcee600000000, 0xbba6a98300000000,
    0x71eb002c00000000, 0x37d0674900000000, 0x330b3ed500000000,
    0x753059b000000000, 0xbf7df01f00000000, 0xf946977a00000000,
    0x6ae0d39b00000000, 0x2cdbb4fe00000000, 0xe6961d5100000000,
    0xa0ad7a3400000000, 0x81dde54800000000, 0xc7e6822d00000000,
    0x0dab2b8200000000, 0x4b904ce700000000, 0xd836080600000000,
    0x9e0d6f6300000000, 0x5440c6cc00000000, 0x127ba1a900000000,
    0x1df0042f00000000, 0x5bcb634a00000000, 0x9186cae500000000,
    0xd7bdad8000000000, 0x441be96100000000, 0x02208e0400000000,
    0xc86d27ab00000000, 0x8e5640ce00000000, 0xaf26dfb200000000,
    0xe91db8d700000000, 0x2350117800000000, 0x656b761d00000000,
    0xf6cd32fc00000000, 0xb0f6559900000000, 0x7abbfc3600000000,
    0x3c809b5300000000, 0x385bc2cf00000000, 0x7e60a5aa00000000,
    0xb42d0c0500000000, 0xf2166b6000000000, 0x61b02f8100000000,
    0x278b48e400000000, 0xedc6e14b00000000, 0xabfd862e00000000,
    0x8a8d195200000000, 0xccb67e3700000000, 0x06fbd79800000000,
    0x40c0b0fd00000000, 0xd366f41c00000000, 0x955d937900000000,
    0x5f103ad600000000, 0x192b5db300000000, 0x2c40f16b00000000,
    0x6a7b960e00000000, 0xa0363fa100000000, 0xe60d58c400000000,
    0x75ab1c2500000000, 0x33907b4000000000, 0xf9ddd2ef00000000,
    0xbfe6b58a00000000, 0x9e962af600000000, 0xd8ad4d9300000000,
    0x12e0e43c00000000, 0x54db835900000000, 0xc77dc7b800000000,
    0x8146a0dd00000000, 0x4b0b097200000000, 0x0d306e1700000000,
    0x09eb378b00000000, 0x4fd050ee00000000, 0x859df94100000000,
    0xc3a69e2400000000, 0x5000dac500000000, 0x163bbda000000000,
    0xdc76140f00000000, 0x9a4d736a00000000, 0xbb3dec1600000000,
    0xfd068b7300000000, 0x374b22dc00000000, 0x717045b900000000,
    0xe2d6015800000000, 0xa4ed663d00000000, 0x6ea0cf9200000000,
    0x289ba8f700000000, 0x27100d7100000000, 0x612b6a1400000000,
    0xab66c3bb00000000, 0xed5da4de00000000, 0x7efbe03f00000000,
    0x38c0875a00000000, 0xf28d2ef500000000, 0xb4b6499000000000,
    0x95c6d6ec00000000, 0xd3fdb18900000000, 0x19b0182600000000,
    0x5f8b7f4300000000, 0xcc2d3ba200000000, 0x8a165cc700000000,
    0x405bf56800000000, 0x0660920d00000000, 0x02bbcb9100000000,
    0x4480acf400000000, 0x8ecd055b00000000, 0xc8f6623e00000000,
    0x5b5026df00000000, 0x1d6b41ba00000000, 0xd726e81500000000,
    0x911d8f7000000000, 0xb06d100c00000000, 0xf656776900000000,
    0x3c1bdec600000000, 0x7a20b9a300000000, 0xe986fd4200000000,
    0xafbd9a2700000000, 0x65f0338800000000, 0x23cb54ed00000000,
    0x3ae0095e00000000, 0x7cdb6e3b00000000, 0xb696c79400000000,
    0xf0ada0f100000000, 0x630be41000000000, 0x2530837500000000,
    0xef7d2ada00000000, 0xa9464dbf00000000, 0x8836d2c300000000,
    0xce0db5a600000000, 0x04401c0900000000, 0x427b7b6c00000000,
    0xd1dd3f8d00000000, 0x97e658e800000000, 0x5dabf14700000000,
    0x1b90962200000000, 0x1f4bcfbe00000000, 0x5970a8db00000000,
    0x933d017400000000, 0xd506661100000000, 0x46a022f000000000,
    0x009b459500000000, 0xcad6ec3a00000000, 0x8ced8b5f00000000,
    0xad9d142300000000, 0xeba6734600000000, 0x21ebdae900000000,
    0x67d0bd8c00000000, 0xf476f96d00000000, 0xb24d9e0800000000,
    0x780037a700000000, 0x3e3b50c200000000, 0x31b0f54400000000,
    0x778b922100000000, 0xbdc63b8e00000000, 0xfbfd5ceb00000000,
    0x685b180a00000000, 0x2e607f6f00000000, 0xe42dd6c000000000,
    0xa216b1a500000000, 0x83662ed900000000, 0xc55d49bc00000000,
    0x0f10e01300000000, 0x492b877600000000, 0xda8dc39700000000,
    0x9cb6a4f200000000, 0x56fb0d5d00000000, 0x10c06a3800000000,
    0x141b33a400000000, 0x522054c100000000, 0x986dfd6e00000000,
    0xde569a0b00000000, 0x4df0deea00000000, 0x0bcbb98f00000000,
    0xc186102000000000, 0x87bd774500000000, 0xa6cde83900000000,
    0xe0f68f5c00000000, 0x2abb26f300000000, 0x6c80419600000000,
    0xff26057700000000, 0xb91d621200000000, 0x7350cbbd00000000,
    0x356bacd800000000},
   {0x0000000000000000, 0x9e83da9f00000000, 0x7d01c4e400000000,
    0xe3821e7b00000000, 0xbb04f91200000000, 0x2587238d00000000,
    0xc6053df600000000, 0x5886e76900000000, 0x7609f22500000000,
    0xe88a28ba00000000, 0x0b0836c100000000, 0x958bec5e00000000,
    0xcd0d0b3700000000, 0x538ed1a800000000, 0xb00ccfd300000000,
    0x2e8f154c00000000, 0xec12e44b00000000, 0x72913ed400000000,
    0x911320af00000000, 0x0f90fa3000000000, 0x57161d5900000000,
    0xc995c7c600000000, 0x2a17d9bd00000000, 0xb494032200000000,
    0x9a1b166e00000000, 0x0498ccf100000000, 0xe71ad28a00000000,
    0x7999081500000000, 0x211fef7c00000000, 0xbf9c35e300000000,
    0x5c1e2b9800000000, 0xc29df10700000000, 0xd825c89700000000,
    0x46a6120800000000, 0xa5240c7300000000, 0x3ba7d6ec00000000,
    0x6321318500000000, 0xfda2eb1a00000000, 0x1e20f56100000000,
    0x80a32ffe00000000, 0xae2c3ab200000000, 0x30afe02d00000000,
    0xd32dfe5600000000, 0x4dae24c900000000, 0x1528c3a000000000,
    0x8bab193f00000000, 0x6829074400000000, 0xf6aadddb00000000,
    0x34372cdc00000000, 0xaab4f64300000000, 0x4936e83800000000,
    0xd7b532a700000000, 0x8f33d5ce00000000, 0x11b00f5100000000,
    0xf232112a00000000, 0x6cb1cbb500000000, 0x423edef900000000,
    0xdcbd046600000000, 0x3f3f1a1d00000000, 0xa1bcc08200000000,
    0xf93a27eb00000000, 0x67b9fd7400000000, 0x843be30f00000000,
    0x1ab8399000000000, 0xf14de1f400000000, 0x6fce3b6b00000000,
    0x8c4c251000000000, 0x12cfff8f00000000, 0x4a4918e600000000,
    0xd4cac27900000000, 0x3748dc0200000000, 0xa9cb069d00000000,
    0x874413d100000000, 0x19c7c94e00000000, 0xfa45d73500000000,
    0x64c60daa00000000, 0x3c40eac300000000, 0xa2c3305c00000000,
    0x41412e2700000000, 0xdfc2f4b800000000, 0x1d5f05bf00000000,
    0x83dcdf2000000000, 0x605ec15b00000000, 0xfedd1bc400000000,
    0xa65bfcad00000000, 0x38d8263200000000, 0xdb5a384900000000,
    0x45d9e2d600000000, 0x6b56f79a00000000, 0xf5d52d0500000000,
    0x1657337e00000000, 0x88d4e9e100000000, 0xd0520e8800000000,
    0x4ed1d41700000000, 0xad53ca6c00000000, 0x33d010f300000000,
    0x2968296300000000, 0xb7ebf3fc00000000, 0x5469ed8700000000,
    0xcaea371800000000, 0x926cd07100000000, 0x0cef0aee00000000,
    0xef6d149500000000, 0x71eece0a00000000, 0x5f61db4600000000,
    0xc1e201d900000000, 0x22601fa200000000, 0xbce3c53d00000000,
    0xe465225400000000, 0x7ae6f8cb00000000, 0x9964e6b000000000,
    0x07e73c2f00000000, 0xc57acd2800000000, 0x5bf917b700000000,
    0xb87b09cc00000000, 0x26f8d35300000000, 0x7e7e343a00000000,
    0xe0fdeea500000000, 0x037ff0de00000000, 0x9dfc2a4100000000,
    0xb3733f0d00000000, 0x2df0e59200000000, 0xce72fbe900000000,
    0x50f1217600000000, 0x0877c61f00000000, 0x96f41c8000000000,
    0x757602fb00000000, 0xebf5d86400000000, 0xa39db33200000000,
    0x3d1e69ad00000000, 0xde9c77d600000000, 0x401fad4900000000,
    0x18994a2000000000, 0x861a90bf00000000, 0x65988ec400000000,
    0xfb1b545b00000000, 0xd594411700000000, 0x4b179b8800000000,
    0xa89585f300000000, 0x36165f6c00000000, 0x6e90b80500000000,
    0xf013629a00000000, 0x13917ce100000000, 0x8d12a67e00000000,
    0x4f8f577900000000, 0xd10c8de600000000, 0x328e939d00000000,
    0xac0d490200000000, 0xf48bae6b00000000, 0x6a0874f400000000,
    0x898a6a8f00000000, 0x1709b01000000000, 0x3986a55c00000000,
    0xa7057fc300000000, 0x448761b800000000, 0xda04bb2700000000,
    0x82825c4e00000000, 0x1c0186d100000000, 0xff8398aa00000000,
    0x6100423500000000, 0x7bb87ba500000000, 0xe53ba13a00000000,
    0x06b9bf4100000000, 0x983a65de00000000, 0xc0bc82b700000000,
    0x5e3f582800000000, 0xbdbd465300000000, 0x233e9ccc00000000,
    0x0db1898000000000, 0x9332531f00000000, 0x70b04d6400000000,
    0xee3397fb00000000, 0xb6b5709200000000, 0x2836aa0d00000000,
    0xcbb4b47600000000, 0x55376ee900000000, 0x97aa9fee00000000,
    0x0929457100000000, 0xeaab5b0a00000000, 0x7428819500000000,
    0x2cae66fc00000000, 0xb22dbc6300000000, 0x51afa21800000000,
    0xcf2c788700000000, 0xe1a36dcb00000000, 0x7f20b75400000000,
    0x9ca2a92f00000000, 0x022173b000000000, 0x5aa794d900000000,
    0xc4244e4600000000, 0x27a6503d00000000, 0xb9258aa200000000,
    0x52d052c600000000, 0xcc53885900000000, 0x2fd1962200000000,
    0xb1524cbd00000000, 0xe9d4abd400000000, 0x7757714b00000000,
    0x94d56f3000000000, 0x0a56b5af00000000, 0x24d9a0e300000000,
    0xba5a7a7c00000000, 0x59d8640700000000, 0xc75bbe9800000000,
    0x9fdd59f100000000, 0x015e836e00000000, 0xe2dc9d1500000000,
    0x7c5f478a00000000, 0xbec2b68d00000000, 0x20416c1200000000,
    0xc3c3726900000000, 0x5d40a8f600000000, 0x05c64f9f00000000,
    0x9b45950000000000, 0x78c78b7b00000000, 0xe64451e400000000,
    0xc8cb44a800000000, 0x56489e3700000000, 0xb5ca804c00000000,
    0x2b495ad300000000, 0x73cfbdba00000000, 0xed4c672500000000,
    0x0ece795e00000000, 0x904da3c100000000, 0x8af59a5100000000,
    0x147640ce00000000, 0xf7f45eb500000000, 0x6977842a00000000,
    0x31f1634300000000, 0xaf72b9dc00000000, 0x4cf0a7a700000000,
    0xd2737d3800000000, 0xfcfc687400000000, 0x627fb2eb00000000,
    0x81fdac9000000000, 0x1f7e760f00000000, 0x47f8916600000000,
    0xd97b4bf900000000, 0x3af9558200000000, 0xa47a8f1d00000000,
    0x66e77e1a00000000, 0xf864a48500000000, 0x1be6bafe00000000,
    0x8565606100000000, 0xdde3870800000000, 0x43605d9700000000,
    0xa0e243ec00000000, 0x3e61997300000000, 0x10ee8c3f00000000,
    0x8e6d56a000000000, 0x6def48db00000000, 0xf36c924400000000,
    0xabea752d00000000, 0x3569afb200000000, 0xd6ebb1c900000000,
    0x48686b5600000000},
   {0x0000000000000000, 0xc064281700000000, 0x80c9502e00000000,
    0x40ad783900000000, 0x0093a15c00000000, 0xc0f7894b00000000,
    0x805af17200000000, 0x403ed96500000000, 0x002643b900000000,
    0xc0426bae00000000, 0x80ef139700000000, 0x408b3b8000000000,
    0x00b5e2e500000000, 0xc0d1caf200000000, 0x807cb2cb00000000,
    0x40189adc00000000, 0x414af7a900000000, 0x812edfbe00000000,
    0xc183a78700000000, 0x01e78f9000000000, 0x41d956f500000000,
    0x81bd7ee200000000, 0xc11006db00000000, 0x01742ecc00000000,
    0x416cb41000000000, 0x81089c0700000000, 0xc1a5e43e00000000,
    0x01c1cc2900000000, 0x41ff154c00000000, 0x819b3d5b00000000,
    0xc136456200000000, 0x01526d7500000000, 0xc3929f8800000000,
    0x03f6b79f00000000, 0x435bcfa600000000, 0x833fe7b100000000,
    0xc3013ed400000000, 0x036516c300000000, 0x43c86efa00000000,
    0x83ac46ed00000000, 0xc3b4dc3100000000, 0x03d0f42600000000,
    0x437d8c1f00000000, 0x8319a40800000000, 0xc3277d6d00000000,
    0x0343557a00000000, 0x43ee2d4300000000, 0x838a055400000000,
    0x82d8682100000000, 0x42bc403600000000, 0x0211380f00000000,
    0xc275101800000000, 0x824bc97d00000000, 0x422fe16a00000000,
    0x0282995300000000, 0xc2e6b14400000000, 0x82fe2b9800000000,
    0x429a038f00000000, 0x02377bb600000000, 0xc25353a100000000,
    0x826d8ac400000000, 0x4209a2d300000000, 0x02a4daea00000000,
    0xc2c0f2fd00000000, 0xc7234eca00000000, 0x074766dd00000000,
    0x47ea1ee400000000, 0x878e36f300000000, 0xc7b0ef9600000000,
    0x07d4c78100000000, 0x4779bfb800000000, 0x871d97af00000000,
    0xc7050d7300000000, 0x0761256400000000, 0x47cc5d5d00000000,
    0x87a8754a00000000, 0xc796ac2f00000000, 0x07f2843800000000,
    0x475ffc0100000000, 0x873bd41600000000, 0x8669b96300000000,
    0x460d917400000000, 0x06a0e94d00000000, 0xc6c4c15a00000000,
    0x86fa183f00000000, 0x469e302800000000, 0x0633481100000000,
    0xc657600600000000, 0x864ffada00000000, 0x462bd2cd00000000,
    0x0686aaf400000000, 0xc6e282e300000000, 0x86dc5b8600000000,
    0x46b8739100000000, 0x06150ba800000000, 0xc67123bf00000000,
    0x04b1d14200000000, 0xc4d5f95500000000, 0x8478816c00000000,
    0x441ca97b00000000, 0x0422701e00000000, 0xc446580900000000,
    0x84eb203000000000, 0x448f082700000000, 0x049792fb00000000,
    0xc4f3baec00000000, 0x845ec2d500000000, 0x443aeac200000000,
    0x040433a700000000, 0xc4601bb000000000, 0x84cd638900000000,
    0x44a94b9e00000000, 0x45fb26eb00000000, 0x859f0efc00000000,
    0xc53276c500000000, 0x05565ed200000000, 0x456887b700000000,
    0x850cafa000000000, 0xc5a1d79900000000, 0x05c5ff8e00000000,
    0x45dd655200000000, 0x85b94d4500000000, 0xc514357c00000000,
    0x05701d6b00000000, 0x454ec40e00000000, 0x852aec1900000000,
    0xc587942000000000, 0x05e3bc3700000000, 0xcf41ed4f00000000,
    0x0f25c55800000000, 0x4f88bd6100000000, 0x8fec957600000000,
    0xcfd24c1300000000, 0x0fb6640400000000, 0x4f1b1c3d00000000,
    0x8f7f342a00000000, 0xcf67aef600000000, 0x0f0386e100000000,
    0x4faefed800000000, 0x8fcad6cf00000000, 0xcff40faa00000000,
    0x0f9027bd00000000, 0x4f3d5f8400000000, 0x8f59779300000000,
    0x8e0b1ae600000000, 0x4e6f32f100000000, 0x0ec24ac800000000,
    0xcea662df00000000, 0x8e98bbba00000000, 0x4efc93ad00000000,
    0x0e51eb9400000000, 0xce35c38300000000, 0x8e2d595f00000000,
    0x4e49714800000000, 0x0ee4097100000000, 0xce80216600000000,
    0x8ebef80300000000, 0x4edad01400000000, 0x0e77a82d00000000,
    0xce13803a00000000, 0x0cd372c700000000, 0xccb75ad000000000,
    0x8c1a22e900000000, 0x4c7e0afe00000000, 0x0c40d39b00000000,
    0xcc24fb8c00000000, 0x8c8983b500000000, 0x4cedaba200000000,
    0x0cf5317e00000000, 0xcc91196900000000, 0x8c3c615000000000,
    0x4c58494700000000, 0x0c66902200000000, 0xcc02b83500000000,
    0x8cafc00c00000000, 0x4ccbe81b00000000, 0x4d99856e00000000,
    0x8dfdad7900000000, 0xcd50d54000000000, 0x0d34fd5700000000,
    0x4d0a243200000000, 0x8d6e0c2500000000, 0xcdc3741c00000000,
    0x0da75c0b00000000, 0x4dbfc6d700000000, 0x8ddbeec000000000,
    0xcd7696f900000000, 0x0d12beee00000000, 0x4d2c678b00000000,
    0x8d484f9c00000000, 0xcde537a500000000, 0x0d811fb200000000,
    0x0862a38500000000, 0xc8068b9200000000, 0x88abf3ab00000000,
    0x48cfdbbc00000000, 0x08f102d900000000, 0xc8952ace00000000,
    0x883852f700000000, 0x485c7ae000000000, 0x0844e03c00000000,
    0xc820c82b00000000, 0x888db01200000000, 0x48e9980500000000,
    0x08d7416000000000, 0xc8b3697700000000, 0x881e114e00000000,
    0x487a395900000000, 0x4928542c00000000, 0x894c7c3b00000000,
    0xc9e1040200000000, 0x09852c1500000000, 0x49bbf57000000000,
    0x89dfdd6700000000, 0xc972a55e00000000, 0x09168d4900000000,
    0x490e179500000000, 0x896a3f8200000000, 0xc9c747bb00000000,
    0x09a36fac00000000, 0x499db6c900000000, 0x89f99ede00000000,
    0xc954e6e700000000, 0x0930cef000000000, 0xcbf03c0d00000000,
    0x0b94141a00000000, 0x4b396c2300000000, 0x8b5d443400000000,
    0xcb639d5100000000, 0x0b07b54600000000, 0x4baacd7f00000000,
    0x8bcee56800000000, 0xcbd67fb400000000, 0x0bb257a300000000,
    0x4b1f2f9a00000000, 0x8b7b078d00000000, 0xcb45dee800000000,
    0x0b21f6ff00000000, 0x4b8c8ec600000000, 0x8be8a6d100000000,
    0x8abacba400000000, 0x4adee3b300000000, 0x0a739b8a00000000,
    0xca17b39d00000000, 0x8a296af800000000, 0x4a4d42ef00000000,
    0x0ae03ad600000000, 0xca8412c100000000, 0x8a9c881d00000000,
    0x4af8a00a00000000, 0x0a55d83300000000, 0xca31f02400000000,
    0x8a0f294100000000, 0x4a6b015600000000, 0x0ac6796f00000000,
    0xcaa2517800000000},
   {0x0000000000000000, 0xd4ea739b00000000, 0xe9d396ed00000000,
    0x3d39e57600000000, 0x93a15c0000000000, 0x474b2f9b00000000,
    0x7a72caed00000000, 0xae98b97600000000, 0x2643b90000000000,
    0xf2a9ca9b00000000, 0xcf902fed00000000, 0x1b7a5c7600000000,
    0xb5e2e50000000000, 0x6108969b00000000, 0x5c3173ed00000000,
    0x88db007600000000, 0x4c86720100000000, 0x986c019a00000000,
    0xa555e4ec00000000, 0x71bf977700000000, 0xdf272e0100000000,
    0x0bcd5d9a00000000, 0x36f4b8ec00000000, 0xe21ecb7700000000,
    0x6ac5cb0100000000, 0xbe2fb89a00000000, 0x83165dec00000000,
    0x57fc2e7700000000, 0xf964970100000000, 0x2d8ee49a00000000,
    0x10b701ec00000000, 0xc45d727700000000, 0x980ce50200000000,
    0x4ce6969900000000, 0x71df73ef00000000, 0xa535007400000000,
    0x0badb90200000000, 0xdf47ca9900000000, 0xe27e2fef00000000,
    0x36945c7400000000, 0xbe4f5c0200000000, 0x6aa52f9900000000,
    0x579ccaef00000000, 0x8376b97400000000, 0x2dee000200000000,
    0xf904739900000000, 0xc43d96ef00000000, 0x10d7e57400000000,
    0xd48a970300000000, 0x0060e49800000000, 0x3d5901ee00000000,
    0xe9b3727500000000, 0x472bcb0300000000, 0x93c1b89800000000,
    0xaef85dee00000000, 0x7a122e7500000000, 0xf2c92e0300000000,
    0x26235d9800000000, 0x1b1ab8ee00000000, 0xcff0cb7500000000,
    0x6168720300000000, 0xb582019800000000, 0x88bbe4ee00000000,
    0x5c51977500000000, 0x3019ca0500000000, 0xe4f3b99e00000000,
    0xd9ca5ce800000000, 0x0d202f7300000000, 0xa3b8960500000000,
    0x7752e59e00000000, 0x4a6b00e800000000, 0x9e81737300000000,
    0x165a730500000000, 0xc2b0009e00000000, 0xff89e5e800000000,
    0x2b63967300000000, 0x85fb2f0500000000, 0x51115c9e00000000,
    0x6c28b9e800000000, 0xb8c2ca7300000000, 0x7c9fb80400000000,
    0xa875cb9f00000000, 0x954c2ee900000000, 0x41a65d7200000000,
    0xef3ee40400000000, 0x3bd4979f00000000, 0x06ed72e900000000,
    0xd207017200000000, 0x5adc010400000000, 0x8e36729f00000000,
    0xb30f97e900000000, 0x67e5e47200000000, 0xc97d5d0400000000,
    0x1d972e9f00000000, 0x20aecbe900000000, 0xf444b87200000000,
    0xa8152f0700000000, 0x7cff5c9c00000000, 0x41c6b9ea00000000,
    0x952cca7100000000, 0x3bb4730700000000, 0xef5e009c00000000,
    0xd267e5ea00000000, 0x068d967100000000, 0x8e56960700000000,
    0x5abce59c00000000, 0x678500ea00000000, 0xb36f737100000000,
    0x1df7ca0700000000, 0xc91db99c00000000, 0xf4245cea00000000,
    0x20ce2f7100000000, 0xe4935d0600000000, 0x30792e9d00000000,
    0x0d40cbeb00000000, 0xd9aab87000000000, 0x7732010600000000,
    0xa3d8729d00000000, 0x9ee197eb00000000, 0x4a0be47000000000,
    0xc2d0e40600000000, 0x163a979d00000000, 0x2b0372eb00000000,
    0xffe9017000000000, 0x5171b80600000000, 0x859bcb9d00000000,
    0xb8a22eeb00000000, 0x6c485d7000000000, 0x6032940b00000000,
    0xb4d8e79000000000, 0x89e102e600000000, 0x5d0b717d00000000,
    0xf393c80b00000000, 0x2779bb9000000000, 0x1a405ee600000000,
    0xceaa2d7d00000000, 0x46712d0b00000000, 0x929b5e9000000000,
    0xafa2bbe600000000, 0x7b48c87d00000000, 0xd5d0710b00000000,
    0x013a029000000000, 0x3c03e7e600000000, 0xe8e9947d00000000,
    0x2cb4e60a00000000, 0xf85e959100000000, 0xc56770e700000000,
    0x118d037c00000000, 0xbf15ba0a00000000, 0x6bffc99100000000,
    0x56c62ce700000000, 0x822c5f7c00000000, 0x0af75f0a00000000,
    0xde1d2c9100000000, 0xe324c9e700000000, 0x37ceba7c00000000,
    0x9956030a00000000, 0x4dbc709100000000, 0x708595e700000000,
    0xa46fe67c00000000, 0xf83e710900000000, 0x2cd4029200000000,
    0x11ede7e400000000, 0xc507947f00000000, 0x6b9f2d0900000000,
    0xbf755e9200000000, 0x824cbbe400000000, 0x56a6c87f00000000,
    0xde7dc80900000000, 0x0a97bb9200000000, 0x37ae5ee400000000,
    0xe3442d7f00000000, 0x4ddc940900000000, 0x9936e79200000000,
    0xa40f02e400000000, 0x70e5717f00000000, 0xb4b8030800000000,
    0x6052709300000000, 0x5d6b95e500000000, 0x8981e67e00000000,
    0x27195f0800000000, 0xf3f32c9300000000, 0xcecac9e500000000,
    0x1a20ba7e00000000, 0x92fbba0800000000, 0x4611c99300000000,
    0x7b282ce500000000, 0xafc25f7e00000000, 0x015ae60800000000,
    0xd5b0959300000000, 0xe88970e500000000, 0x3c63037e00000000,
    0x502b5e0e00000000, 0x84c12d9500000000, 0xb9f8c8e300000000,
    0x6d12bb7800000000, 0xc38a020e00000000, 0x1760719500000000,
    0x2a5994e300000000, 0xfeb3e77800000000, 0x7668e70e00000000,
    0xa282949500000000, 0x9fbb71e300000000, 0x4b51027800000000,
    0xe5c9bb0e00000000, 0x3123c89500000000, 0x0c1a2de300000000,
    0xd8f05e7800000000, 0x1cad2c0f00000000, 0xc8475f9400000000,
    0xf57ebae200000000, 0x2194c97900000000, 0x8f0c700f00000000,
    0x5be6039400000000, 0x66dfe6e200000000, 0xb235957900000000,
    0x3aee950f00000000, 0xee04e69400000000, 0xd33d03e200000000,
    0x07d7707900000000, 0xa94fc90f00000000, 0x7da5ba9400000000,
    0x409c5fe200000000, 0x94762c7900000000, 0xc827bb0c00000000,
    0x1ccdc89700000000, 0x21f42de100000000, 0xf51e5e7a00000000,
    0x5b86e70c00000000, 0x8f6c949700000000, 0xb25571e100000000,
    0x66bf027a00000000, 0xee64020c00000000, 0x3a8e719700000000,
    0x07b794e100000000, 0xd35de77a00000000, 0x7dc55e0c00000000,
    0xa92f2d9700000000, 0x9416c8e100000000, 0x40fcbb7a00000000,
    0x84a1c90d00000000, 0x504bba9600000000, 0x6d725fe000000000,
    0xb9982c7b00000000, 0x1700950d00000000, 0xc3eae69600000000,
    0xfed303e000000000, 0x2a39707b00000000, 0xa2e2700d00000000,
    0x7608039600000000, 0x4b31e6e000000000, 0x9fdb957b00000000,
    0x31432c0d00000000, 0xe5a95f9600000000, 0xd890bae000000000,
    0x0c7ac97b00000000},
   {0x0000000000000000, 0x2765258100000000, 0x0fcc3bd900000000,
    0x28a91e5800000000, 0x5f9e066900000000, 0x78fb23e800000000,
    0x50523db000000000, 0x7737183100000000, 0xbe3c0dd200000000,
    0x9959285300000000, 0xb1f0360b00000000, 0x9695138a00000000,
    0xe1a20bbb00000000, 0xc6c72e3a00000000, 0xee6e306200000000,
    0xc90b15e300000000, 0x3d7f6b7f00000000, 0x1a1a4efe00000000,
    0x32b350a600000000, 0x15d6752700000000, 0x62e16d1600000000,
    0x4584489700000000, 0x6d2d56cf00000000, 0x4a48734e00000000,
    0x834366ad00000000, 0xa426432c00000000, 0x8c8f5d7400000000,
    0xabea78f500000000, 0xdcdd60c400000000, 0xfbb8454500000000,
    0xd3115b1d00000000, 0xf4747e9c00000000, 0x7afed6fe00000000,
    0x5d9bf37f00000000, 0x7532ed2700000000, 0x5257c8a600000000,
    0x2560d09700000000, 0x0205f51600000000, 0x2aaceb4e00000000,
    0x0dc9cecf00000000, 0xc4c2db2c00000000, 0xe3a7fead00000000,
    0xcb0ee0f500000000, 0xec6bc57400000000, 0x9b5cdd4500000000,
    0xbc39f8c400000000, 0x9490e69c00000000, 0xb3f5c31d00000000,
    0x4781bd8100000000, 0x60e4980000000000, 0x484d865800000000,
    0x6f28a3d900000000, 0x181fbbe800000000, 0x3f7a9e6900000000,
    0x17d3803100000000, 0x30b6a5b000000000, 0xf9bdb05300000000,
    0xded895d200000000, 0xf6718b8a00000000, 0xd114ae0b00000000,
    0xa623b63a00000000, 0x814693bb00000000, 0xa9ef8de300000000,
    0x8e8aa86200000000, 0xb5fadc2600000000, 0x929ff9a700000000,
    0xba36e7ff00000000, 0x9d53c27e00000000, 0xea64da4f00000000,
    0xcd01ffce00000000, 0xe5a8e19600000000, 0xc2cdc41700000000,
    0x0bc6d1f400000000, 0x2ca3f47500000000, 0x040aea2d00000000,
    0x236fcfac00000000, 0x5458d79d00000000, 0x733df21c00000000,
    0x5b94ec4400000000, 0x7cf1c9c500000000, 0x8885b75900000000,
    0xafe092d800000000, 0x87498c8000000000, 0xa02ca90100000000,
    0xd71bb13000000000, 0xf07e94b100000000, 0xd8d78ae900000000,
    0xffb2af6800000000, 0x36b9ba8b00000000, 0x11dc9f0a00000000,
    0x3975815200000000, 0x1e10a4d300000000, 0x6927bce200000000,
    0x4e42996300000000, 0x66eb873b00000000, 0x418ea2ba00000000,
    0xcf040ad800000000, 0xe8612f5900000000, 0xc0c8310100000000,
    0xe7ad148000000000, 0x909a0cb100000000, 0xb7ff293000000000,
    0x9f56376800000000, 0xb83312e900000000, 0x7138070a00000000,
    0x565d228b00000000, 0x7ef43cd300000000, 0x5991195200000000,
    0x2ea6016300000000, 0x09c324e200000000, 0x216a3aba00000000,
    0x060f1f3b00000000, 0xf27b61a700000000, 0xd51e442600000000,
    0xfdb75a7e00000000, 0xdad27fff00000000, 0xade567ce00000000,
    0x8a80424f00000000, 0xa2295c1700000000, 0x854c799600000000,
    0x4c476c7500000000, 0x6b2249f400000000, 0x438b57ac00000000,
    0x64ee722d00000000, 0x13d96a1c00000000, 0x34bc4f9d00000000,
    0x1c1551c500000000, 0x3b70744400000000, 0x6af5b94d00000000,
    0x4d909ccc00000000, 0x6539829400000000, 0x425ca71500000000,
    0x356bbf2400000000, 0x120e9aa500000000, 0x3aa784fd00000000,
    0x1dc2a17c00000000, 0xd4c9b49f00000000, 0xf3ac911e00000000,
    0xdb058f4600000000, 0xfc60aac700000000, 0x8b57b2f600000000,
    0xac32977700000000, 0x849b892f00000000, 0xa3feacae00000000,
    0x578ad23200000000, 0x70eff7b300000000, 0x5846e9eb00000000,
    0x7f23cc6a00000000, 0x0814d45b00000000, 0x2f71f1da00000000,
    0x07d8ef8200000000, 0x20bdca0300000000, 0xe9b6dfe000000000,
    0xced3fa6100000000, 0xe67ae43900000000, 0xc11fc1b800000000,
    0xb628d98900000000, 0x914dfc0800000000, 0xb9e4e25000000000,
    0x9e81c7d100000000, 0x100b6fb300000000, 0x376e4a3200000000,
    0x1fc7546a00000000, 0x38a271eb00000000, 0x4f9569da00000000,
    0x68f04c5b00000000, 0x4059520300000000, 0x673c778200000000,
    0xae37626100000000, 0x895247e000000000, 0xa1fb59b800000000,
    0x869e7c3900000000, 0xf1a9640800000000, 0xd6cc418900000000,
    0xfe655fd100000000, 0xd9007a5000000000, 0x2d7404cc00000000,
    0x0a11214d00000000, 0x22b83f1500000000, 0x05dd1a9400000000,
    0x72ea02a500000000, 0x558f272400000000, 0x7d26397c00000000,
    0x5a431cfd00000000, 0x9348091e00000000, 0xb42d2c9f00000000,
    0x9c8432c700000000, 0xbbe1174600000000, 0xccd60f7700000000,
    0xebb32af600000000, 0xc31a34ae00000000, 0xe47f112f00000000,
    0xdf0f656b00000000, 0xf86a40ea00000000, 0xd0c35eb200000000,
    0xf7a67b3300000000, 0x8091630200000000, 0xa7f4468300000000,
    0x8f5d58db00000000, 0xa8387d5a00000000, 0x613368b900000000,
    0x46564d3800000000, 0x6eff536000000000, 0x499a76e100000000,
    0x3ead6ed000000000, 0x19c84b5100000000, 0x3161550900000000,
    0x1604708800000000, 0xe2700e1400000000, 0xc5152b9500000000,
    0xedbc35cd00000000, 0xcad9104c00000000, 0xbdee087d00000000,
    0x9a8b2dfc00000000, 0xb22233a400000000, 0x9547162500000000,
    0x5c4c03c600000000, 0x7b29264700000000, 0x5380381f00000000,
    0x74e51d9e00000000, 0x03d205af00000000, 0x24b7202e00000000,
    0x0c1e3e7600000000, 0x2b7b1bf700000000, 0xa5f1b39500000000,
    0x8294961400000000, 0xaa3d884c00000000, 0x8d58adcd00000000,
    0xfa6fb5fc00000000, 0xdd0a907d00000000, 0xf5a38e2500000000,
    0xd2c6aba400000000, 0x1bcdbe4700000000, 0x3ca89bc600000000,
    0x1401859e00000000, 0x3364a01f00000000, 0x4453b82e00000000,
    0x63369daf00000000, 0x4b9f83f700000000, 0x6cfaa67600000000,
    0x988ed8ea00000000, 0xbfebfd6b00000000, 0x9742e33300000000,
    0xb027c6b200000000, 0xc710de8300000000, 0xe075fb0200000000,
    0xc8dce55a00000000, 0xefb9c0db00000000, 0x26b2d53800000000,
    0x01d7f0b900000000, 0x297eeee100000000, 0x0e1bcb6000000000,
    0x792cd35100000000, 0x5e49f6d000000000, 0x76e0e88800000000,
    0x5185cd0900000000}};

#else /* W == 4 */

local const z_crc_t FAR crc_braid_table[][256] = {
   {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f,
    0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91,
    0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e,
    0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c,
    0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02,
    0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12,
    0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567,
    0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277,
    0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679,
    0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b,
    0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4,
    0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a,
    0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0,
    0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0,
    0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91,
    0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881,
    0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173,
    0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d,
    0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912,
    0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8,
    0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6,
    0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6,
    0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b,
    0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b,
    0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75,
    0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f,
    0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00,
    0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee,
    0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c,
    0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c,
    0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d,
    0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d,
    0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67,
    0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89,
    0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706,
    0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14,
    0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a,
    0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a,
    0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f,
    0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f,
    0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591,
    0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983,
    0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c,
    0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2,
    0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8,
    0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8,
    0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89,
    0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99,
    0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b,
    0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485,
    0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a,
    0x36197165},
   {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382,
    0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85,
    0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06,
    0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca,
    0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e,
    0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc,
    0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616,
    0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54,
    0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10,
    0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc,
    0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f,
    0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58,
    0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef,
    0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad,
    0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b,
    0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29,
    0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6,
    0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1,
    0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622,
    0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039,
    0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d,
    0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f,
    0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32,
    0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770,
    0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034,
    0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f,
    0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc,
    0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db,
    0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154,
    0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16,
    0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0,
    0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592,
    0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca,
    0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd,
    0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e,
    0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882,
    0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6,
    0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384,
    0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1,
    0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3,
    0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7,
    0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b,
    0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8,
    0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff,
    0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7,
    0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5,
    0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23,
    0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761,
    0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee,
    0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9,
    0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a,
    0x1a3b93aa},
   {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a,
    0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca,
    0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3,
    0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb,
    0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c,
    0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58,
    0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed,
    0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9,
    0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e,
    0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906,
    0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f,
    0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf,
    0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0,
    0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4,
    0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769,
    0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d,
    0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632,
    0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82,
    0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb,
    0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73,
    0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484,
    0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0,
    0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5,
    0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1,
    0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516,
    0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f,
    0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946,
    0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6,
    0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9,
    0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad,
    0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820,
    0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364,
    0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab,
    0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b,
    0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62,
    0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a,
    0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd,
    0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089,
    0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c,
    0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8,
    0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f,
    0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477,
    0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e,
    0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be,
    0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71,
    0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635,
    0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8,
    0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc,
    0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3,
    0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753,
    0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a,
    0xe147d714},
   {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c,
    0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b,
    0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92,
    0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4,
    0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069,
    0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526,
    0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25,
    0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a,
    0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7,
    0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491,
    0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958,
    0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f,
    0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307,
    0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648,
    0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999,
    0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6,
    0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a,
    0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d,
    0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4,
    0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61,
    0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc,
    0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3,
    0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53,
    0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c,
    0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1,
    0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c,
    0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5,
    0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92,
    0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e,
    0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771,
    0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0,
    0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def,
    0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0,
    0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7,
    0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e,
    0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58,
    0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285,
    0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca,
    0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce,
    0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81,
    0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c,
    0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a,
    0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3,
    0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4,
    0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb,
    0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4,
    0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75,
    0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a,
    0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296,
    0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1,
    0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808,
    0x494f0c4b}};

local const z_word_t FAR crc_braid_big_table[][256] = {
   {0x00000000, 0x43147b17, 0x8628f62e, 0xc53c8d39, 0x0c51ec5d,
    0x4f45974a, 0x8a791a73, 0xc96d6164, 0x18a2d8bb, 0x5bb6a3ac,
    0x9e8a2e95, 0xdd9e5582, 0x14f334e6, 0x57e74ff1, 0x92dbc2c8,
    0xd1cfb9df, 0x7142c0ac, 0x3256bbbb, 0xf76a3682, 0xb47e4d95,
    0x7d132cf1, 0x3e0757e6, 0xfb3bdadf, 0xb82fa1c8, 0x69e01817,
    0x2af46300, 0xefc8ee39, 0xacdc952e, 0x65b1f44a, 0x26a58f5d,
    0xe3990264, 0xa08d7973, 0xa382f182, 0xe0968a95, 0x25aa07ac,
    0x66be7cbb, 0xafd31ddf, 0xecc766c8, 0x29fbebf1, 0x6aef90e6,
    0xbb202939, 0xf834522e, 0x3d08df17, 0x7e1ca400, 0xb771c564,
    0xf465be73, 0x3159334a, 0x724d485d, 0xd2c0312e, 0x91d44a39,
    0x54e8c700, 0x17fcbc17, 0xde91dd73, 0x9d85a664, 0x58b92b5d,
    0x1bad504a, 0xca62e995, 0x89769282, 0x4c4a1fbb, 0x0f5e64ac,
    0xc63305c8, 0x85277edf, 0x401bf3e6, 0x030f88f1, 0x070392de,
    0x4417e9c9, 0x812b64f0, 0xc23f1fe7, 0x0b527e83, 0x48460594,
    0x8d7a88ad, 0xce6ef3ba, 0x1fa14a65, 0x5cb53172, 0x9989bc4b,
    0xda9dc75c, 0x13f0a638, 0x50e4dd2f, 0x95d85016, 0xd6cc2b01,
    0x76415272, 0x35552965, 0xf069a45c, 0xb37ddf4b, 0x7a10be2f,
    0x3904c538, 0xfc384801, 0xbf2c3316, 0x6ee38ac9, 0x2df7f1de,
    0xe8cb7ce7, 0xabdf07f0, 0x62b26694, 0x21a61d83, 0xe49a90ba,
    0xa78eebad, 0xa481635c, 0xe795184b, 0x22a99572, 0x61bdee65,
    0xa8d08f01, 0xebc4f416, 0x2ef8792f, 0x6dec0238, 0xbc23bbe7,
    0xff37c0f0, 0x3a0b4dc9, 0x791f36de, 0xb07257ba, 0xf3662cad,
    0x365aa194, 0x754eda83, 0xd5c3a3f0, 0x96d7d8e7, 0x53eb55de,
    0x10ff2ec9, 0xd9924fad, 0x9a8634ba, 0x5fbab983, 0x1caec294,
    0xcd617b4b, 0x8e75005c, 0x4b498d65, 0x085df672, 0xc1309716,
    0x8224ec01, 0x47186138, 0x040c1a2f, 0x4f005566, 0x0c142e71,
    0xc928a348, 0x8a3cd85f, 0x4351b93b, 0x0045c22c, 0xc5794f15,
    0x866d3402, 0x57a28ddd, 0x14b6f6ca, 0xd18a7bf3, 0x929e00e4,
    0x5bf36180, 0x18e71a97, 0xdddb97ae, 0x9ecfecb9, 0x3e4295ca,
    0x7d56eedd, 0xb86a63e4, 0xfb7e18f3, 0x32137997, 0x71070280,
    0xb43b8fb9, 0xf72ff4ae, 0x26e04d71, 0x65f43666, 0xa0c8bb5f,
    0xe3dcc048, 0x2ab1a12c, 0x69a5da3b, 0xac995702, 0xef8d2c15,
    0xec82a4e4, 0xaf96dff3, 0x6aaa52ca, 0x29be29dd, 0xe0d348b9,
    0xa3c733ae, 0x66fbbe97, 0x25efc580, 0xf4207c5f, 0xb7340748,
    0x72088a71, 0x311cf166, 0xf8719002, 0xbb65eb15, 0x7e59662c,
    0x3d4d1d3b, 0x9dc06448, 0xded41f5f, 0x1be89266, 0x58fce971,
    0x91918815, 0xd285f302, 0x17b97e3b, 0x54ad052c, 0x8562bcf3,
    0xc676c7e4, 0x034a4add, 0x405e31ca, 0x893350ae, 0xca272bb9,
    0x0f1ba680, 0x4c0fdd97, 0x4803c7b8, 0x0b17bcaf, 0xce2b3196,
    0x8d3f4a81, 0x44522be5, 0x074650f2, 0xc27addcb, 0x816ea6dc,
    0x50a11f03, 0x13b56414, 0xd689e92d, 0x959d923a, 0x5cf0f35e,
    0x1fe48849, 0xdad80570, 0x99cc7e67, 0x39410714, 0x7a557c03,
    0xbf69f13a, 0xfc7d8a2d, 0x3510eb49, 0x7604905e, 0xb3381d67,
    0xf02c6670, 0x21e3dfaf, 0x62f7a4b8, 0xa7cb2981, 0xe4df5296,
    0x2db233f2, 0x6ea648e5, 0xab9ac5dc, 0xe88ebecb, 0xeb81363a,
    0xa8954d2d, 0x6da9c014, 0x2ebdbb03, 0xe7d0da67, 0xa4c4a170,
    0x61f82c49, 0x22ec575e, 0xf323ee81, 0xb0379596, 0x750b18af,
    0x361f63b8, 0xff7202dc, 0xbc6679cb, 0x795af4f2, 0x3a4e8fe5,
    0x9ac3f696, 0xd9d78d81, 0x1ceb00b8, 0x5fff7baf, 0x96921acb,
    0xd58661dc, 0x10baece5, 0x53ae97f2, 0x82612e2d, 0xc175553a,
    0x0449d803, 0x475da314, 0x8e30c270, 0xcd24b967, 0x0818345e,
    0x4b0c4f49},
   {0x00000000, 0x3e6bc2ef, 0x3dd0f504, 0x03bb37eb, 0x7aa0eb09,
    0x44cb29e6, 0x47701e0d, 0x791bdce2, 0xf440d713, 0xca2b15fc,
    0xc9902217, 0xf7fbe0f8, 0x8ee03c1a, 0xb08bfef5, 0xb330c91e,
    0x8d5b0bf1, 0xe881ae27, 0xd6ea6cc8, 0xd5515b23, 0xeb3a99cc,
    0x9221452e, 0xac4a87c1, 0xaff1b02a, 0x919a72c5, 0x1cc17934,
    0x22aabbdb, 0x21118c30, 0x1f7a4edf, 0x6661923d, 0x580a50d2,
    0x5bb16739, 0x65daa5d6, 0xd0035d4f, 0xee689fa0, 0xedd3a84b,
    0xd3b86aa4, 0xaaa3b646, 0x94c874a9, 0x97734342, 0xa91881ad,
    0x24438a5c, 0x1a2848b3, 0x19937f58, 0x27f8bdb7, 0x5ee36155,
    0x6088a3ba, 0x63339451, 0x5d5856be, 0x3882f368, 0x06e93187,
    0x0552066c, 0x3b39c483, 0x42221861, 0x7c49da8e, 0x7ff2ed65,
    0x41992f8a, 0xccc2247b, 0xf2a9e694, 0xf112d17f, 0xcf791390,
    0xb662cf72, 0x88090d9d, 0x8bb23a76, 0xb5d9f899, 0xa007ba9e,
    0x9e6c7871, 0x9dd74f9a, 0xa3bc8d75, 0xdaa75197, 0xe4cc9378,
    0xe777a493, 0xd91c667c, 0x54476d8d, 0x6a2caf62, 0x69979889,
    0x57fc5a66, 0x2ee78684, 0x108c446b, 0x13377380, 0x2d5cb16f,
    0x488614b9, 0x76edd656, 0x7556e1bd, 0x4b3d2352, 0x3226ffb0,
    0x0c4d3d5f, 0x0ff60ab4, 0x319dc85b, 0xbcc6c3aa, 0x82ad0145,
    0x811636ae, 0xbf7df441, 0xc66628a3, 0xf80dea4c, 0xfbb6dda7,
    0xc5dd1f48, 0x7004e7d1, 0x4e6f253e, 0x4dd412d5, 0x73bfd03a,
    0x0aa40cd8, 0x34cfce37, 0x3774f9dc, 0x091f3b33, 0x844430c2,
    0xba2ff22d, 0xb994c5c6, 0x87ff0729, 0xfee4dbcb, 0xc08f1924,
    0xc3342ecf, 0xfd5fec20, 0x988549f6, 0xa6ee8b19, 0xa555bcf2,
    0x9b3e7e1d, 0xe225a2ff, 0xdc4e6010, 0xdff557fb, 0xe19e9514,
    0x6cc59ee5, 0x52ae5c0a, 0x51156be1, 0x6f7ea90e, 0x166575ec,
    0x280eb703, 0x2bb580e8, 0x15de4207, 0x010905e6, 0x3f62c709,
    0x3cd9f0e2, 0x02b2320d, 0x7ba9eeef, 0x45c22c00, 0x46791beb,
    0x7812d904, 0xf549d2f5, 0xcb22101a, 0xc89927f1, 0xf6f2e51e,
    0x8fe939fc, 0xb182fb13, 0xb239ccf8, 0x8c520e17, 0xe988abc1,
    0xd7e3692e, 0xd4585ec5, 0xea339c2a, 0x932840c8, 0xad438227,
    0xaef8b5cc, 0x90937723, 0x1dc87cd2, 0x23a3be3d, 0x201889d6,
    0x1e734b39, 0x676897db, 0x59035534, 0x5ab862df, 0x64d3a030,
    0xd10a58a9, 0xef619a46, 0xecdaadad, 0xd2b16f42, 0xabaab3a0,
    0x95c1714f, 0x967a46a4, 0xa811844b, 0x254a8fba, 0x1b214d55,
    0x189a7abe, 0x26f1b851, 0x5fea64b3, 0x6181a65c, 0x623a91b7,
    0x5c515358, 0x398bf68e, 0x07e03461, 0x045b038a, 0x3a30c165,
    0x432b1d87, 0x7d40df68, 0x7efbe883, 0x40902a6c, 0xcdcb219d,
    0xf3a0e372, 0xf01bd499, 0xce701676, 0xb76bca94, 0x8900087b,
    0x8abb3f90, 0xb4d0fd7f, 0xa10ebf78, 0x9f657d97, 0x9cde4a7c,
    0xa2b58893, 0xdbae5471, 0xe5c5969e, 0xe67ea175, 0xd815639a,
    0x554e686b, 0x6b25aa84, 0x689e9d6f, 0x56f55f80, 0x2fee8362,
    0x1185418d, 0x123e7666, 0x2c55b489, 0x498f115f, 0x77e4d3b0,
    0x745fe45b, 0x4a3426b4, 0x332ffa56, 0x0d4438b9, 0x0eff0f52,
    0x3094cdbd, 0xbdcfc64c, 0x83a404a3, 0x801f3348, 0xbe74f1a7,
    0xc76f2d45, 0xf904efaa, 0xfabfd841, 0xc4d41aae, 0x710de237,
    0x4f6620d8, 0x4cdd1733, 0x72b6d5dc, 0x0bad093e, 0x35c6cbd1,
    0x367dfc3a, 0x08163ed5, 0x854d3524, 0xbb26f7cb, 0xb89dc020,
    0x86f602cf, 0xffedde2d, 0xc1861cc2, 0xc23d2b29, 0xfc56e9c6,
    0x998c4c10, 0xa7e78eff, 0xa45cb914, 0x9a377bfb, 0xe32ca719,
    0xdd4765f6, 0xdefc521d, 0xe09790f2, 0x6dcc9b03, 0x53a759ec,
    0x501c6e07, 0x6e77ace8, 0x176c700a, 0x2907b2e5, 0x2abc850e,
    0x14d747e1},
   {0x00000000, 0xc0df8ec1, 0xc1b96c58, 0x0166e299, 0x8273d9b0,
    0x42ac5771, 0x43cab5e8, 0x83153b29, 0x45e1c3ba, 0x853e4d7b,
    0x8458afe2, 0x44872123, 0xc7921a0a, 0x074d94cb, 0x062b7652,
    0xc6f4f893, 0xcbc4f6ae, 0x0b1b786f, 0x0a7d9af6, 0xcaa21437,
    0x49b72f1e, 0x8968a1df, 0x880e4346, 0x48d1cd87, 0x8e253514,
    0x4efabbd5, 0x4f9c594c, 0x8f43d78d, 0x0c56eca4, 0xcc896265,
    0xcdef80fc, 0x0d300e3d, 0xd78f9c86, 0x17501247, 0x1636f0de,
    0xd6e97e1f, 0x55fc4536, 0x9523cbf7, 0x9445296e, 0x549aa7af,
    0x926e5f3c, 0x52b1d1fd, 0x53d73364, 0x9308bda5, 0x101d868c,
    0xd0c2084d, 0xd1a4ead4, 0x117b6415, 0x1c4b6a28, 0xdc94e4e9,
    0xddf20670, 0x1d2d88b1, 0x9e38b398, 0x5ee73d59, 0x5f81dfc0,
    0x9f5e5101, 0x59aaa992, 0x99752753, 0x9813c5ca, 0x58cc4b0b,
    0xdbd97022, 0x1b06fee3, 0x1a601c7a, 0xdabf92bb, 0xef1948d6,
    0x2fc6c617, 0x2ea0248e, 0xee7faa4f, 0x6d6a9166, 0xadb51fa7,
    0xacd3fd3e, 0x6c0c73ff, 0xaaf88b6c, 0x6a2705ad, 0x6b41e734,
    0xab9e69f5, 0x288b52dc, 0xe854dc1d, 0xe9323e84, 0x29edb045,
    0x24ddbe78, 0xe40230b9, 0xe564d220, 0x25bb5ce1, 0xa6ae67c8,
    0x6671e909, 0x67170b90, 0xa7c88551, 0x613c7dc2, 0xa1e3f303,
    0xa085119a, 0x605a9f5b, 0xe34fa472, 0x23902ab3, 0x22f6c82a,
    0xe22946eb, 0x3896d450, 0xf8495a91, 0xf92fb808, 0x39f036c9,
    0xbae50de0, 0x7a3a8321, 0x7b5c61b8, 0xbb83ef79, 0x7d7717ea,
    0xbda8992b, 0xbcce7bb2, 0x7c11f573, 0xff04ce5a, 0x3fdb409b,
    0x3ebda202, 0xfe622cc3, 0xf35222fe, 0x338dac3f, 0x32eb4ea6,
    0xf234c067, 0x7121fb4e, 0xb1fe758f, 0xb0989716, 0x704719d7,
    0xb6b3e144, 0x766c6f85, 0x770a8d1c, 0xb7d503dd, 0x34c038f4,
    0xf41fb635, 0xf57954ac, 0x35a6da6d, 0x9f35e177, 0x5fea6fb6,
    0x5e8c8d2f, 0x9e5303ee, 0x1d4638c7, 0xdd99b606, 0xdcff549f,
    0x1c20da5e, 0xdad422cd, 0x1a0bac0c, 0x1b6d4e95, 0xdbb2c054,
    0x58a7fb7d, 0x987875bc, 0x991e9725, 0x59c119e4, 0x54f117d9,
    0x942e9918, 0x95487b81, 0x5597f540, 0xd682ce69, 0x165d40a8,
    0x173ba231, 0xd7e42cf0, 0x1110d463, 0xd1cf5aa2, 0xd0a9b83b,
    0x107636fa, 0x93630dd3, 0x53bc8312, 0x52da618b, 0x9205ef4a,
    0x48ba7df1, 0x8865f330, 0x890311a9, 0x49dc9f68, 0xcac9a441,
    0x0a162a80, 0x0b70c819, 0xcbaf46d8, 0x0d5bbe4b, 0xcd84308a,
    0xcce2d213, 0x0c3d5cd2, 0x8f2867fb, 0x4ff7e93a, 0x4e910ba3,
    0x8e4e8562, 0x837e8b5f, 0x43a1059e, 0x42c7e707, 0x821869c6,
    0x010d52ef, 0xc1d2dc2e, 0xc0b43eb7, 0x006bb076, 0xc69f48e5,
    0x0640c624, 0x072624bd, 0xc7f9aa7c, 0x44ec9155, 0x84331f94,
    0x8555fd0d, 0x458a73cc, 0x702ca9a1, 0xb0f32760, 0xb195c5f9,
    0x714a4b38, 0xf25f7011, 0x3280fed0, 0x33e61c49, 0xf3399288,
    0x35cd6a1b, 0xf512e4da, 0xf4740643, 0x34ab8882, 0xb7beb3ab,
    0x77613d6a, 0x7607dff3, 0xb6d85132, 0xbbe85f0f, 0x7b37d1ce,
    0x7a513357, 0xba8ebd96, 0x399b86bf, 0xf944087e, 0xf822eae7,
    0x38fd6426, 0xfe099cb5, 0x3ed61274, 0x3fb0f0ed, 0xff6f7e2c,
    0x7c7a4505, 0xbca5cbc4, 0xbdc3295d, 0x7d1ca79c, 0xa7a33527,
    0x677cbbe6, 0x661a597f, 0xa6c5d7be, 0x25d0ec97, 0xe50f6256,
    0xe46980cf, 0x24b60e0e, 0xe242f69d, 0x229d785c, 0x23fb9ac5,
    0xe3241404, 0x60312f2d, 0xa0eea1ec, 0xa1884375, 0x6157cdb4,
    0x6c67c389, 0xacb84d48, 0xaddeafd1, 0x6d012110, 0xee141a39,
    0x2ecb94f8, 0x2fad7661, 0xef72f8a0, 0x29860033, 0xe9598ef2,
    0xe83f6c6b, 0x28e0e2aa, 0xabf5d983, 0x6b2a5742, 0x6a4cb5db,
    0xaa933b1a},
   {0x00000000, 0x6f4ca59b, 0x9f9e3bec, 0xf0d29e77, 0x7f3b0603,
    0x1077a398, 0xe0a53def, 0x8fe99874, 0xfe760c06, 0x913aa99d,
    0x61e837ea, 0x0ea49271, 0x814d0a05, 0xee01af9e, 0x1ed331e9,
    0x719f9472, 0xfced180c, 0x93a1bd97, 0x637323e0, 0x0c3f867b,
    0x83d61e0f, 0xec9abb94, 0x1c4825e3, 0x73048078, 0x029b140a,
    0x6dd7b191, 0x9d052fe6, 0xf2498a7d, 0x7da01209, 0x12ecb792,
    0xe23e29e5, 0x8d728c7e, 0xf8db3118, 0x97979483, 0x67450af4,
    0x0809af6f, 0x87e0371b, 0xe8ac9280, 0x187e0cf7, 0x7732a96c,
    0x06ad3d1e, 0x69e19885, 0x993306f2, 0xf67fa369, 0x79963b1d,
    0x16da9e86, 0xe60800f1, 0x8944a56a, 0x04362914, 0x6b7a8c8f,
    0x9ba812f8, 0xf4e4b763, 0x7b0d2f17, 0x14418a8c, 0xe49314fb,
    0x8bdfb160, 0xfa402512, 0x950c8089, 0x65de1efe, 0x0a92bb65,
    0x857b2311, 0xea37868a, 0x1ae518fd, 0x75a9bd66, 0xf0b76330,
    0x9ffbc6ab, 0x6f2958dc, 0x0065fd47, 0x8f8c6533, 0xe0c0c0a8,
    0x10125edf, 0x7f5efb44, 0x0ec16f36, 0x618dcaad, 0x915f54da,
    0xfe13f141, 0x71fa6935, 0x1eb6ccae, 0xee6452d9, 0x8128f742,
    0x0c5a7b3c, 0x6316dea7, 0x93c440d0, 0xfc88e54b, 0x73617d3f,
    0x1c2dd8a4, 0xecff46d3, 0x83b3e348, 0xf22c773a, 0x9d60d2a1,
    0x6db24cd6, 0x02fee94d, 0x8d177139, 0xe25bd4a2, 0x12894ad5,
    0x7dc5ef4e, 0x086c5228, 0x6720f7b3, 0x97f269c4, 0xf8becc5f,
    0x7757542b, 0x181bf1b0, 0xe8c96fc7, 0x8785ca5c, 0xf61a5e2e,
    0x9956fbb5, 0x698465c2, 0x06c8c059, 0x8921582d, 0xe66dfdb6,
    0x16bf63c1, 0x79f3c65a, 0xf4814a24, 0x9bcdefbf, 0x6b1f71c8,
    0x0453d453, 0x8bba4c27, 0xe4f6e9bc, 0x142477cb, 0x7b68d250,
    0x0af74622, 0x65bbe3b9, 0x95697dce, 0xfa25d855, 0x75cc4021,
    0x1a80e5ba, 0xea527bcd, 0x851ede56, 0xe06fc760, 0x8f2362fb,
    0x7ff1fc8c, 0x10bd5917, 0x9f54c163, 0xf01864f8, 0x00cafa8f,
    0x6f865f14, 0x1e19cb66, 0x71556efd, 0x8187f08a, 0xeecb5511,
    0x6122cd65, 0x0e6e68fe, 0xfebcf689, 0x91f05312, 0x1c82df6c,
    0x73ce7af7, 0x831ce480, 0xec50411b, 0x63b9d96f, 0x0cf57cf4,
    0xfc27e283, 0x936b4718, 0xe2f4d36a, 0x8db876f1, 0x7d6ae886,
    0x12264d1d, 0x9dcfd569, 0xf28370f2, 0x0251ee85, 0x6d1d4b1e,
    0x18b4f678, 0x77f853e3, 0x872acd94, 0xe866680f, 0x678ff07b,
    0x08c355e0, 0xf811cb97, 0x975d6e0c, 0xe6c2fa7e, 0x898e5fe5,
    0x795cc192, 0x16106409, 0x99f9fc7d, 0xf6b559e6, 0x0667c791,
    0x692b620a, 0xe459ee74, 0x8b154bef, 0x7bc7d598, 0x148b7003,
    0x9b62e877, 0xf42e4dec, 0x04fcd39b, 0x6bb07600, 0x1a2fe272,
    0x756347e9, 0x85b1d99e, 0xeafd7c05, 0x6514e471, 0x0a5841ea,
    0xfa8adf9d, 0x95c67a06, 0x10d8a450, 0x7f9401cb, 0x8f469fbc,
    0xe00a3a27, 0x6fe3a253, 0x00af07c8, 0xf07d99bf, 0x9f313c24,
    0xeeaea856, 0x81e20dcd, 0x713093ba, 0x1e7c3621, 0x9195ae55,
    0xfed90bce, 0x0e0b95b9, 0x61473022, 0xec35bc5c, 0x837919c7,
    0x73ab87b0, 0x1ce7222b, 0x930eba5f, 0xfc421fc4, 0x0c9081b3,
    0x63dc2428, 0x1243b05a, 0x7d0f15c1, 0x8ddd8bb6, 0xe2912e2d,
    0x6d78b659, 0x023413c2, 0xf2e68db5, 0x9daa282e, 0xe8039548,
    0x874f30d3, 0x779daea4, 0x18d10b3f, 0x9738934b, 0xf87436d0,
    0x08a6a8a7, 0x67ea0d3c, 0x1675994e, 0x79393cd5, 0x89eba2a2,
    0xe6a70739, 0x694e9f4d, 0x06023ad6, 0xf6d0a4a1, 0x999c013a,
    0x14ee8d44, 0x7ba228df, 0x8b70b6a8, 0xe43c1333, 0x6bd58b47,
    0x04992edc, 0xf44bb0ab, 0x9b071530, 0xea988142, 0x85d424d9,
    0x7506baae, 0x1a4a1f35, 0x95a38741, 0xfaef22da, 0x0a3dbcad,
    0x65711936}};

#endif

#endif

#if N == 4

#if W == 8

local const z_crc_t FAR crc_braid_table[][256] = {
   {0x00000000, 0xf1da05aa, 0x38c50d15, 0xc91f08bf, 0x718a1a2a,
    0x80501f80, 0x494f173f, 0xb8951295, 0xe3143454, 0x12ce31fe,
    0xdbd13941, 0x2a0b3ceb, 0x929e2e7e, 0x63442bd4, 0xaa5b236b,
    0x5b8126c1, 0x1d596ee9, 0xec836b43, 0x259c63fc, 0xd4466656,
    0x6cd374c3, 0x9d097169, 0x541679d6, 0xa5cc7c7c, 0xfe4d5abd,
    0x0f975f17, 0xc68857a8, 0x37525202, 0x8fc74097, 0x7e1d453d,
    0xb7024d82, 0x46d84828, 0x3ab2ddd2, 0xcb68d878, 0x0277d0c7,
    0xf3add56d, 0x4b38c7f8, 0xbae2c252, 0x73fdcaed, 0x8227cf47,
    0xd9a6e986, 0x287cec2c, 0xe163e493, 0x10b9e139, 0xa82cf3ac,
    0x59f6f606, 0x90e9feb9, 0x6133fb13, 0x27ebb33b, 0xd631b691,
    0x1f2ebe2e, 0xeef4bb84, 0x5661a911, 0xa7bbacbb, 0x6ea4a404,
    0x9f7ea1ae, 0xc4ff876f, 0x352582c5, 0xfc3a8a7a, 0x0de08fd0,
    0xb5759d45, 0x44af98ef, 0x8db09050, 0x7c6a95fa, 0x7565bba4,
    0x84bfbe0e, 0x4da0b6b1, 0xbc7ab31b, 0x04efa18e, 0xf535a424,
    0x3c2aac9b, 0xcdf0a931, 0x96718ff0, 0x67ab8a5a, 0xaeb482e5,
    0x5f6e874f, 0xe7fb95da, 0x16219070, 0xdf3e98cf, 0x2ee49d65,
    0x683cd54d, 0x99e6d0e7, 0x50f9d858, 0xa123ddf2, 0x19b6cf67,
    0xe86ccacd, 0x2173c272, 0xd0a9c7d8, 0x8b28e119, 0x7af2e4b3,
    0xb3edec0c, 0x4237e9a6, 0xfaa2fb33, 0x0b78fe99, 0xc267f626,
    0x33bdf38c, 0x4fd76676, 0xbe0d63dc, 0x77126b63, 0x86c86ec9,
    0x3e5d7c5c, 0xcf8779f6, 0x06987149, 0xf74274e3, 0xacc35222,
    0x5d195788, 0x94065f37, 0x65dc5a9d, 0xdd494808, 0x2c934da2,
    0xe58c451d, 0x145640b7, 0x528e089f, 0xa3540d35, 0x6a4b058a,
    0x9b910020, 0x230412b5, 0xd2de171f, 0x1bc11fa0, 0xea1b1a0a,
    0xb19a3ccb, 0x40403961, 0x895f31de, 0x78853474, 0xc01026e1,
    0x31ca234b, 0xf8d52bf4, 0x090f2e5e, 0xeacb7748, 0x1b1172e2,
    0xd20e7a5d, 0x23d47ff7, 0x9b416d62, 0x6a9b68c8, 0xa3846077,
    0x525e65dd, 0x09df431c, 0xf80546b6, 0x311a4e09, 0xc0c04ba3,
    0x78555936, 0x898f5c9c, 0x40905423, 0xb14a5189, 0xf79219a1,
    0x06481c0b, 0xcf5714b4, 0x3e8d111e, 0x8618038b, 0x77c20621,
    0xbedd0e9e, 0x4f070b34, 0x14862df5, 0xe55c285f, 0x2c4320e0,
    0xdd99254a, 0x650c37df, 0x94d63275, 0x5dc93aca, 0xac133f60,
    0xd079aa9a, 0x21a3af30, 0xe8bca78f, 0x1966a225, 0xa1f3b0b0,
    0x5029b51a, 0x9936bda5, 0x68ecb80f, 0x336d9ece, 0xc2b79b64,
    0x0ba893db, 0xfa729671, 0x42e784e4, 0xb33d814e, 0x7a2289f1,
    0x8bf88c5b, 0xcd20c473, 0x3cfac1d9, 0xf5e5c966, 0x043fcccc,
    0xbcaade59, 0x4d70dbf3, 0x846fd34c, 0x75b5d6e6, 0x2e34f027,
    0xdfeef58d, 0x16f1fd32, 0xe72bf898, 0x5fbeea0d, 0xae64efa7,
    0x677be718, 0x96a1e2b2, 0x9faeccec, 0x6e74c946, 0xa76bc1f9,
    0x56b1c453, 0xee24d6c6, 0x1ffed36c, 0xd6e1dbd3, 0x273bde79,
    0x7cbaf8b8, 0x8d60fd12, 0x447ff5ad, 0xb5a5f007, 0x0d30e292,
    0xfceae738, 0x35f5ef87, 0xc42fea2d, 0x82f7a205, 0x732da7af,
    0xba32af10, 0x4be8aaba, 0xf37db82f, 0x02a7bd85, 0xcbb8b53a,
    0x3a62b090, 0x61e39651, 0x903993fb, 0x59269b44, 0xa8fc9eee,
    0x10698c7b, 0xe1b389d1, 0x28ac816e, 0xd97684c4, 0xa51c113e,
    0x54c61494, 0x9dd91c2b, 0x6c031981, 0xd4960b14, 0x254c0ebe,
    0xec530601, 0x1d8903ab, 0x4608256a, 0xb7d220c0, 0x7ecd287f,
    0x8f172dd5, 0x37823f40, 0xc6583aea, 0x0f473255, 0xfe9d37ff,
    0xb8457fd7, 0x499f7a7d, 0x808072c2, 0x715a7768, 0xc9cf65fd,
    0x38156057, 0xf10a68e8, 0x00d06d42, 0x5b514b83, 0xaa8b4e29,
    0x63944696, 0x924e433c, 0x2adb51a9, 0xdb015403, 0x121e5cbc,
    0xe3c45916},
   {0x00000000, 0x0ee7e8d1, 0x1dcfd1a2, 0x13283973, 0x3b9fa344,
    0x35784b95, 0x265072e6, 0x28b79a37, 0x773f4688, 0x79d8ae59,
    0x6af0972a, 0x64177ffb, 0x4ca0e5cc, 0x42470d1d, 0x516f346e,
    0x5f88dcbf, 0xee7e8d10, 0xe09965c1, 0xf3b15cb2, 0xfd56b463,
    0xd5e12e54, 0xdb06c685, 0xc82efff6, 0xc6c91727, 0x9941cb98,
    0x97a62349, 0x848e1a3a, 0x8a69f2eb, 0xa2de68dc, 0xac39800d,
    0xbf11b97e, 0xb1f651af, 0x078c1c61, 0x096bf4b0, 0x1a43cdc3,
    0x14a42512, 0x3c13bf25, 0x32f457f4, 0x21dc6e87, 0x2f3b8656,
    0x70b35ae9, 0x7e54b238, 0x6d7c8b4b, 0x639b639a, 0x4b2cf9ad,
    0x45cb117c, 0x56e3280f, 0x5804c0de, 0xe9f29171, 0xe71579a0,
    0xf43d40d3, 0xfadaa802, 0xd26d3235, 0xdc8adae4, 0xcfa2e397,
    0xc1450b46, 0x9ecdd7f9, 0x902a3f28, 0x8302065b, 0x8de5ee8a,
    0xa55274bd, 0xabb59c6c, 0xb89da51f, 0xb67a4dce, 0x0f1838c2,
    0x01ffd013, 0x12d7e960, 0x1c3001b1, 0x34879b86, 0x3a607357,
    0x29484a24, 0x27afa2f5, 0x78277e4a, 0x76c0969b, 0x65e8afe8,
    0x6b0f4739, 0x43b8dd0e, 0x4d5f35df, 0x5e770cac, 0x5090e47d,
    0xe166b5d2, 0xef815d03, 0xfca96470, 0xf24e8ca1, 0xdaf91696,
    0xd41efe47, 0xc736c734, 0xc9d12fe5, 0x9659f35a, 0x98be1b8b,
    0x8b9622f8, 0x8571ca29, 0xadc6501e, 0xa321b8cf, 0xb00981bc,
    0xbeee696d, 0x089424a3, 0x0673cc72, 0x155bf501, 0x1bbc1dd0,
    0x330b87e7, 0x3dec6f36, 0x2ec45645, 0x2023be94, 0x7fab622b,
    0x714c8afa, 0x6264b389, 0x6c835b58, 0x4434c16f, 0x4ad329be,
    0x59fb10cd, 0x571cf81c, 0xe6eaa9b3, 0xe80d4162, 0xfb257811,
    0xf5c290c0, 0xdd750af7, 0xd392e226, 0xc0badb55, 0xce5d3384,
    0x91d5ef3b, 0x9f3207ea, 0x8c1a3e99, 0x82fdd648, 0xaa4a4c7f,
    0xa4ada4ae, 0xb7859ddd, 0xb962750c, 0x1e307184, 0x10d79955,
    0x03ffa026, 0x0d1848f7, 0x25afd2c0, 0x2b483a11, 0x38600362,
    0x3687ebb3, 0x690f370c, 0x67e8dfdd, 0x74c0e6ae, 0x7a270e7f,
    0x52909448, 0x5c777c99, 0x4f5f45ea, 0x41b8ad3b, 0xf04efc94,
    0xfea91445, 0xed812d36, 0xe366c5e7, 0xcbd15fd0, 0xc536b701,
    0xd61e8e72, 0xd8f966a3, 0x8771ba1c, 0x899652cd, 0x9abe6bbe,
    0x9459836f, 0xbcee1958, 0xb209f189, 0xa121c8fa, 0xafc6202b,
    0x19bc6de5, 0x175b8534, 0x0473bc47, 0x0a945496, 0x2223cea1,
    0x2cc42670, 0x3fec1f03, 0x310bf7d2, 0x6e832b6d, 0x6064c3bc,
    0x734cfacf, 0x7dab121e, 0x551c8829, 0x5bfb60f8, 0x48d3598b,
    0x4634b15a, 0xf7c2e0f5, 0xf9250824, 0xea0d3157, 0xe4ead986,
    0xcc5d43b1, 0xc2baab60, 0xd1929213, 0xdf757ac2, 0x80fda67d,
    0x8e1a4eac, 0x9d3277df, 0x93d59f0e, 0xbb620539, 0xb585ede8,
    0xa6add49b, 0xa84a3c4a, 0x11284946, 0x1fcfa197, 0x0ce798e4,
    0x02007035, 0x2ab7ea02, 0x245002d3, 0x37783ba0, 0x399fd371,
    0x66170fce, 0x68f0e71f, 0x7bd8de6c, 0x753f36bd, 0x5d88ac8a,
    0x536f445b, 0x40477d28, 0x4ea095f9, 0xff56c456, 0xf1b12c87,
    0xe29915f4, 0xec7efd25, 0xc4c96712, 0xca2e8fc3, 0xd906b6b0,
    0xd7e15e61, 0x886982de, 0x868e6a0f, 0x95a6537c, 0x9b41bbad,
    0xb3f6219a, 0xbd11c94b, 0xae39f038, 0xa0de18e9, 0x16a45527,
    0x1843bdf6, 0x0b6b8485, 0x058c6c54, 0x2d3bf663, 0x23dc1eb2,
    0x30f427c1, 0x3e13cf10, 0x619b13af, 0x6f7cfb7e, 0x7c54c20d,
    0x72b32adc, 0x5a04b0eb, 0x54e3583a, 0x47cb6149, 0x492c8998,
    0xf8dad837, 0xf63d30e6, 0xe5150995, 0xebf2e144, 0xc3457b73,
    0xcda293a2, 0xde8aaad1, 0xd06d4200, 0x8fe59ebf, 0x8102766e,
    0x922a4f1d, 0x9ccda7cc, 0xb47a3dfb, 0xba9dd52a, 0xa9b5ec59,
    0xa7520488},
   {0x00000000, 0x3c60e308, 0x78c1c610, 0x44a12518, 0xf1838c20,
    0xcde36f28, 0x89424a30, 0xb522a938, 0x38761e01, 0x0416fd09,
    0x40b7d811, 0x7cd73b19, 0xc9f59221, 0xf5957129, 0xb1345431,
    0x8d54b739, 0x70ec3c02, 0x4c8cdf0a, 0x082dfa12, 0x344d191a,
    0x816fb022, 0xbd0f532a, 0xf9ae7632, 0xc5ce953a, 0x489a2203,
    0x74fac10b, 0x305be413, 0x0c3b071b, 0xb919ae23, 0x85794d2b,
    0xc1d86833, 0xfdb88b3b, 0xe1d87804, 0xddb89b0c, 0x9919be14,
    0xa5795d1c, 0x105bf424, 0x2c3b172c, 0x689a3234, 0x54fad13c,
    0xd9ae6605, 0xe5ce850d, 0xa16fa015, 0x9d0f431d, 0x282dea25,
    0x144d092d, 0x50ec2c35, 0x6c8ccf3d, 0x91344406, 0xad54a70e,
    0xe9f58216, 0xd595611e, 0x60b7c826, 0x5cd72b2e, 0x18760e36,
    0x2416ed3e, 0xa9425a07, 0x9522b90f, 0xd1839c17, 0xede37f1f,
    0x58c1d627, 0x64a1352f, 0x20001037, 0x1c60f33f, 0x18c1f649,
    0x24a11541, 0x60003059, 0x5c60d351, 0xe9427a69, 0xd5229961,
    0x9183bc79, 0xade35f71, 0x20b7e848, 0x1cd70b40, 0x58762e58,
    0x6416cd50, 0xd1346468, 0xed548760, 0xa9f5a278, 0x95954170,
    0x682dca4b, 0x544d2943, 0x10ec0c5b, 0x2c8cef53, 0x99ae466b,
    0xa5cea563, 0xe16f807b, 0xdd0f6373, 0x505bd44a, 0x6c3b3742,
    0x289a125a, 0x14faf152, 0xa1d8586a, 0x9db8bb62, 0xd9199e7a,
    0xe5797d72, 0xf9198e4d, 0xc5796d45, 0x81d8485d, 0xbdb8ab55,
    0x089a026d, 0x34fae165, 0x705bc47d, 0x4c3b2775, 0xc16f904c,
    0xfd0f7344, 0xb9ae565c, 0x85ceb554, 0x30ec1c6c, 0x0c8cff64,
    0x482dda7c, 0x744d3974, 0x89f5b24f, 0xb5955147, 0xf134745f,
    0xcd549757, 0x78763e6f, 0x4416dd67, 0x00b7f87f, 0x3cd71b77,
    0xb183ac4e, 0x8de34f46, 0xc9426a5e, 0xf5228956, 0x4000206e,
    0x7c60c366, 0x38c1e67e, 0x04a10576, 0x3183ec92, 0x0de30f9a,
    0x49422a82, 0x7522c98a, 0xc00060b2, 0xfc6083ba, 0xb8c1a6a2,
    0x84a145aa, 0x09f5f293, 0x3595119b, 0x71343483, 0x4d54d78b,
    0xf8767eb3, 0xc4169dbb, 0x80b7b8a3, 0xbcd75bab, 0x416fd090,
    0x7d0f3398, 0x39ae1680, 0x05cef588, 0xb0ec5cb0, 0x8c8cbfb8,
    0xc82d9aa0, 0xf44d79a8, 0x7919ce91, 0x45792d99, 0x01d80881,
    0x3db8eb89, 0x889a42b1, 0xb4faa1b9, 0xf05b84a1, 0xcc3b67a9,
    0xd05b9496, 0xec3b779e, 0xa89a5286, 0x94fab18e, 0x21d818b6,
    0x1db8fbbe, 0x5919dea6, 0x65793dae, 0xe82d8a97, 0xd44d699f,
    0x90ec4c87, 0xac8caf8f, 0x19ae06b7, 0x25cee5bf, 0x616fc0a7,
    0x5d0f23af, 0xa0b7a894, 0x9cd74b9c, 0xd8766e84, 0xe4168d8c,
    0x513424b4, 0x6d54c7bc, 0x29f5e2a4, 0x159501ac, 0x98c1b695,
    0xa4a1559d, 0xe0007085, 0xdc60938d, 0x69423ab5, 0x5522d9bd,
    0x1183fca5, 0x2de31fad, 0x29421adb, 0x1522f9d3, 0x5183dccb,
    0x6de33fc3, 0xd8c196fb, 0xe4a175f3, 0xa00050eb, 0x9c60b3e3,
    0x113404da, 0x2d54e7d2, 0x69f5c2ca, 0x559521c2, 0xe0b788fa,
    0xdcd76bf2, 0x98764eea, 0xa416ade2, 0x59ae26d9, 0x65cec5d1,
    0x216fe0c9, 0x1d0f03c1, 0xa82daaf9, 0x944d49f1, 0xd0ec6ce9,
    0xec8c8fe1, 0x61d838d8, 0x5db8dbd0, 0x1919fec8, 0x25791dc0,
    0x905bb4f8, 0xac3b57f0, 0xe89a72e8, 0xd4fa91e0, 0xc89a62df,
    0xf4fa81d7, 0xb05ba4cf, 0x8c3b47c7, 0x3919eeff, 0x05790df7,
    0x41d828ef, 0x7db8cbe7, 0xf0ec7cde, 0xcc8c9fd6, 0x882dbace,
    0xb44d59c6, 0x016ff0fe, 0x3d0f13f6, 0x79ae36ee, 0x45ced5e6,
    0xb8765edd, 0x8416bdd5, 0xc0b798cd, 0xfcd77bc5, 0x49f5d2fd,
    0x759531f5, 0x313414ed, 0x0d54f7e5, 0x800040dc, 0xbc60a3d4,
    0xf8c186cc, 0xc4a165c4, 0x7183ccfc, 0x4de32ff4, 0x09420aec,
    0x3522e9e4},
   {0x00000000, 0x6307d924, 0xc60fb248, 0xa5086b6c, 0x576e62d1,
    0x3469bbf5, 0x9161d099, 0xf26609bd, 0xaedcc5a2, 0xcddb1c86,
    0x68d377ea, 0x0bd4aece, 0xf9b2a773, 0x9ab57e57, 0x3fbd153b,
    0x5cbacc1f, 0x86c88d05, 0xe5cf5421, 0x40c73f4d, 0x23c0e669,
    0xd1a6efd4, 0xb2a136f0, 0x17a95d9c, 0x74ae84b8, 0x281448a7,
    0x4b139183, 0xee1bfaef, 0x8d1c23cb, 0x7f7a2a76, 0x1c7df352,
    0xb975983e, 0xda72411a, 0xd6e01c4b, 0xb5e7c56f, 0x10efae03,
    0x73e87727, 0x818e7e9a, 0xe289a7be, 0x4781ccd2, 0x248615f6,
    0x783cd9e9, 0x1b3b00cd, 0xbe336ba1, 0xdd34b285, 0x2f52bb38,
    0x4c55621c, 0xe95d0970, 0x8a5ad054, 0x5028914e, 0x332f486a,
    0x96272306, 0xf520fa22, 0x0746f39f, 0x64412abb, 0xc14941d7,
    0xa24e98f3, 0xfef454ec, 0x9df38dc8, 0x38fbe6a4, 0x5bfc3f80,
    0xa99a363d, 0xca9def19, 0x6f958475, 0x0c925d51, 0x76b13ed7,
    0x15b6e7f3, 0xb0be8c9f, 0xd3b955bb, 0x21df5c06, 0x42d88522,
    0xe7d0ee4e, 0x84d7376a, 0xd86dfb75, 0xbb6a2251, 0x1e62493d,
    0x7d659019, 0x8f0399a4, 0xec044080, 0x490c2bec, 0x2a0bf2c8,
    0xf079b3d2, 0x937e6af6, 0x3676019a, 0x5571d8be, 0xa717d103,
    0xc4100827, 0x6118634b, 0x021fba6f, 0x5ea57670, 0x3da2af54,
    0x98aac438, 0xfbad1d1c, 0x09cb14a1, 0x6acccd85, 0xcfc4a6e9,
    0xacc37fcd, 0xa051229c, 0xc356fbb8, 0x665e90d4, 0x055949f0,
    0xf73f404d, 0x94389969, 0x3130f205, 0x52372b21, 0x0e8de73e,
    0x6d8a3e1a, 0xc8825576, 0xab858c52, 0x59e385ef, 0x3ae45ccb,
    0x9fec37a7, 0xfcebee83, 0x2699af99, 0x459e76bd, 0xe0961dd1,
    0x8391c4f5, 0x71f7cd48, 0x12f0146c, 0xb7f87f00, 0xd4ffa624,
    0x88456a3b, 0xeb42b31f, 0x4e4ad873, 0x2d4d0157, 0xdf2b08ea,
    0xbc2cd1ce, 0x1924baa2, 0x7a236386, 0xed627dae, 0x8e65a48a,
    0x2b6dcfe6, 0x486a16c2, 0xba0c1f7f, 0xd90bc65b, 0x7c03ad37,
    0x1f047413, 0x43beb80c, 0x20b96128, 0x85b10a44, 0xe6b6d360,
    0x14d0dadd, 0x77d703f9, 0xd2df6895, 0xb1d8b1b1, 0x6baaf0ab,
    0x08ad298f, 0xada542e3, 0xcea29bc7, 0x3cc4927a, 0x5fc34b5e,
    0xfacb2032, 0x99ccf916, 0xc5763509, 0xa671ec2d, 0x03798741,
    0x607e5e65, 0x921857d8, 0xf11f8efc, 0x5417e590, 0x37103cb4,
    0x3b8261e5, 0x5885b8c1, 0xfd8dd3ad, 0x9e8a0a89, 0x6cec0334,
    0x0febda10, 0xaae3b17c, 0xc9e46858, 0x955ea447, 0xf6597d63,
    0x5351160f, 0x3056cf2b, 0xc230c696, 0xa1371fb2, 0x043f74de,
    0x6738adfa, 0xbd4aece0, 0xde4d35c4, 0x7b455ea8, 0x1842878c,
    0xea248e31, 0x89235715, 0x2c2b3c79, 0x4f2ce55d, 0x13962942,
    0x7091f066, 0xd5999b0a, 0xb69e422e, 0x44f84b93, 0x27ff92b7,
    0x82f7f9db, 0xe1f020ff, 0x9bd34379, 0xf8d49a5d, 0x5ddcf131,
    0x3edb2815, 0xccbd21a8, 0xafbaf88c, 0x0ab293e0, 0x69b54ac4,
    0x350f86db, 0x56085fff, 0xf3003493, 0x9007edb7, 0x6261e40a,
    0x01663d2e, 0xa46e5642, 0xc7698f66, 0x1d1bce7c, 0x7e1c1758,
    0xdb147c34, 0xb813a510, 0x4a75acad, 0x29727589, 0x8c7a1ee5,
    0xef7dc7c1, 0xb3c70bde, 0xd0c0d2fa, 0x75c8b996, 0x16cf60b2,
    0xe4a9690f, 0x87aeb02b, 0x22a6db47, 0x41a10263, 0x4d335f32,
    0x2e348616, 0x8b3ced7a, 0xe83b345e, 0x1a5d3de3, 0x795ae4c7,
    0xdc528fab, 0xbf55568f, 0xe3ef9a90, 0x80e843b4, 0x25e028d8,
    0x46e7f1fc, 0xb481f841, 0xd7862165, 0x728e4a09, 0x1189932d,
    0xcbfbd237, 0xa8fc0b13, 0x0df4607f, 0x6ef3b95b, 0x9c95b0e6,
    0xff9269c2, 0x5a9a02ae, 0x399ddb8a, 0x65271795, 0x0620ceb1,
    0xa328a5dd, 0xc02f7cf9, 0x32497544, 0x514eac60, 0xf446c70c,
    0x97411e28},
   {0x00000000, 0x01b5fd1d, 0x036bfa3a, 0x02de0727, 0x06d7f474,
    0x07620969, 0x05bc0e4e, 0x0409f353, 0x0dafe8e8, 0x0c1a15f5,
    0x0ec412d2, 0x0f71efcf, 0x0b781c9c, 0x0acde181, 0x0813e6a6,
    0x09a61bbb, 0x1b5fd1d0, 0x1aea2ccd, 0x18342bea, 0x1981d6f7,
    0x1d8825a4, 0x1c3dd8b9, 0x1ee3df9e, 0x1f562283, 0x16f03938,
    0x1745c425, 0x159bc302, 0x142e3e1f, 0x1027cd4c, 0x11923051,
    0x134c3776, 0x12f9ca6b, 0x36bfa3a0, 0x370a5ebd, 0x35d4599a,
    0x3461a487, 0x306857d4, 0x31ddaac9, 0x3303adee, 0x32b650f3,
    0x3b104b48, 0x3aa5b655, 0x387bb172, 0x39ce4c6f, 0x3dc7bf3c,
    0x3c724221, 0x3eac4506, 0x3f19b81b, 0x2de07270, 0x2c558f6d,
    0x2e8b884a, 0x2f3e7557, 0x2b378604, 0x2a827b19, 0x285c7c3e,
    0x29e98123, 0x204f9a98, 0x21fa6785, 0x232460a2, 0x22919dbf,
    0x26986eec, 0x272d93f1, 0x25f394d6, 0x244669cb, 0x6d7f4740,
    0x6ccaba5d, 0x6e14bd7a, 0x6fa14067, 0x6ba8b334, 0x6a1d4e29,
    0x68c3490e, 0x6976b413, 0x60d0afa8, 0x616552b5, 0x63bb5592,
    0x620ea88f, 0x66075bdc, 0x67b2a6c1, 0x656ca1e6, 0x64d95cfb,
    0x76209690, 0x77956b8d, 0x754b6caa, 0x74fe91b7, 0x70f762e4,
    0x71429ff9, 0x739c98de, 0x722965c3, 0x7b8f7e78, 0x7a3a8365,
    0x78e48442, 0x7951795f, 0x7d588a0c, 0x7ced7711, 0x7e337036,
    0x7f868d2b, 0x5bc0e4e0, 0x5a7519fd, 0x58ab1eda, 0x591ee3c7,
    0x5d171094, 0x5ca2ed89, 0x5e7ceaae, 0x5fc917b3, 0x566f0c08,
    0x57daf115, 0x5504f632, 0x54b10b2f, 0x50b8f87c, 0x510d0561,
    0x53d30246, 0x5266ff5b, 0x409f3530, 0x412ac82d, 0x43f4cf0a,
    0x42413217, 0x4648c144, 0x47fd3c59, 0x45233b7e, 0x4496c663,
    0x4d30ddd8, 0x4c8520c5, 0x4e5b27e2, 0x4feedaff, 0x4be729ac,
    0x4a52d4b1, 0x488cd396, 0x49392e8b, 0xdafe8e80, 0xdb4b739d,
    0xd99574ba, 0xd82089a7, 0xdc297af4, 0xdd9c87e9, 0xdf4280ce,
    0xdef77dd3, 0xd7516668, 0xd6e49b75, 0xd43a9c52, 0xd58f614f,
    0xd186921c, 0xd0336f01, 0xd2ed6826, 0xd358953b, 0xc1a15f50,
    0xc014a24d, 0xc2caa56a, 0xc37f5877, 0xc776ab24, 0xc6c35639,
    0xc41d511e, 0xc5a8ac03, 0xcc0eb7b8, 0xcdbb4aa5, 0xcf654d82,
    0xced0b09f, 0xcad943cc, 0xcb6cbed1, 0xc9b2b9f6, 0xc80744eb,
    0xec412d20, 0xedf4d03d, 0xef2ad71a, 0xee9f2a07, 0xea96d954,
    0xeb232449, 0xe9fd236e, 0xe848de73, 0xe1eec5c8, 0xe05b38d5,
    0xe2853ff2, 0xe330c2ef, 0xe73931bc, 0xe68ccca1, 0xe452cb86,
    0xe5e7369b, 0xf71efcf0, 0xf6ab01ed, 0xf47506ca, 0xf5c0fbd7,
    0xf1c90884, 0xf07cf599, 0xf2a2f2be, 0xf3170fa3, 0xfab11418,
    0xfb04e905, 0xf9daee22, 0xf86f133f, 0xfc66e06c, 0xfdd31d71,
    0xff0d1a56, 0xfeb8e74b, 0xb781c9c0, 0xb63434dd, 0xb4ea33fa,
    0xb55fcee7, 0xb1563db4, 0xb0e3c0a9, 0xb23dc78e, 0xb3883a93,
    0xba2e2128, 0xbb9bdc35, 0xb945db12, 0xb8f0260f, 0xbcf9d55c,
    0xbd4c2841, 0xbf922f66, 0xbe27d27b, 0xacde1810, 0xad6be50d,
    0xafb5e22a, 0xae001f37, 0xaa09ec64, 0xabbc1179, 0xa962165e,
    0xa8d7eb43, 0xa171f0f8, 0xa0c40de5, 0xa21a0ac2, 0xa3aff7df,
    0xa7a6048c, 0xa613f991, 0xa4cdfeb6, 0xa57803ab, 0x813e6a60,
    0x808b977d, 0x8255905a, 0x83e06d47, 0x87e99e14, 0x865c6309,
    0x8482642e, 0x85379933, 0x8c918288, 0x8d247f95, 0x8ffa78b2,
    0x8e4f85af, 0x8a4676fc, 0x8bf38be1, 0x892d8cc6, 0x889871db,
    0x9a61bbb0, 0x9bd446ad, 0x990a418a, 0x98bfbc97, 0x9cb64fc4,
    0x9d03b2d9, 0x9fddb5fe, 0x9e6848e3, 0x97ce5358, 0x967bae45,
    0x94a5a962, 0x9510547f, 0x9119a72c, 0x90ac5a31, 0x92725d16,
    0x93c7a00b},
   {0x00000000, 0x6e8c1b41, 0xdd183682, 0xb3942dc3, 0x61416b45,
    0x0fcd7004, 0xbc595dc7, 0xd2d54686, 0xc282d68a, 0xac0ecdcb,
    0x1f9ae008, 0x7116fb49, 0xa3c3bdcf, 0xcd4fa68e, 0x7edb8b4d,
    0x1057900c, 0x5e74ab55, 0x30f8b014, 0x836c9dd7, 0xede08696,
    0x3f35c010, 0x51b9db51, 0xe22df692, 0x8ca1edd3, 0x9cf67ddf,
    0xf27a669e, 0x41ee4b5d, 0x2f62501c, 0xfdb7169a, 0x933b0ddb,
    0x20af2018, 0x4e233b59, 0xbce956aa, 0xd2654deb, 0x61f16028,
    0x0f7d7b69, 0xdda83def, 0xb32426ae, 0x00b00b6d, 0x6e3c102c,
    0x7e6b8020, 0x10e79b61, 0xa373b6a2, 0xcdffade3, 0x1f2aeb65,
    0x71a6f024, 0xc232dde7, 0xacbec6a6, 0xe29dfdff, 0x8c11e6be,
    0x3f85cb7d, 0x5109d03c, 0x83dc96ba, 0xed508dfb, 0x5ec4a038,
    0x3048bb79, 0x201f2b75, 0x4e933034, 0xfd071df7, 0x938b06b6,
    0x415e4030, 0x2fd25b71, 0x9c4676b2, 0xf2ca6df3, 0xa2a3ab15,
    0xcc2fb054, 0x7fbb9d97, 0x113786d6, 0xc3e2c050, 0xad6edb11,
    0x1efaf6d2, 0x7076ed93, 0x60217d9f, 0x0ead66de, 0xbd394b1d,
    0xd3b5505c, 0x016016da, 0x6fec0d9b, 0xdc782058, 0xb2f43b19,
    0xfcd70040, 0x925b1b01, 0x21cf36c2, 0x4f432d83, 0x9d966b05,
    0xf31a7044, 0x408e5d87, 0x2e0246c6, 0x3e55d6ca, 0x50d9cd8b,
    0xe34de048, 0x8dc1fb09, 0x5f14bd8f, 0x3198a6ce, 0x820c8b0d,
    0xec80904c, 0x1e4afdbf, 0x70c6e6fe, 0xc352cb3d, 0xadded07c,
    0x7f0b96fa, 0x11878dbb, 0xa213a078, 0xcc9fbb39, 0xdcc82b35,
    0xb2443074, 0x01d01db7, 0x6f5c06f6, 0xbd894070, 0xd3055b31,
    0x609176f2, 0x0e1d6db3, 0x403e56ea, 0x2eb24dab, 0x9d266068,
    0xf3aa7b29, 0x217f3daf, 0x4ff326ee, 0xfc670b2d, 0x92eb106c,
    0x82bc8060, 0xec309b21, 0x5fa4b6e2, 0x3128ada3, 0xe3fdeb25,
    0x8d71f064, 0x3ee5dda7, 0x5069c6e6, 0x9e36506b, 0xf0ba4b2a,
    0x432e66e9, 0x2da27da8, 0xff773b2e, 0x91fb206f, 0x226f0dac,
    0x4ce316ed, 0x5cb486e1, 0x32389da0, 0x81acb063, 0xef20ab22,
    0x3df5eda4, 0x5379f6e5, 0xe0eddb26, 0x8e61c067, 0xc042fb3e,
    0xaecee07f, 0x1d5acdbc, 0x73d6d6fd, 0xa103907b, 0xcf8f8b3a,
    0x7c1ba6f9, 0x1297bdb8, 0x02c02db4, 0x6c4c36f5, 0xdfd81b36,
    0xb1540077, 0x638146f1, 0x0d0d5db0, 0xbe997073, 0xd0156b32,
    0x22df06c1, 0x4c531d80, 0xffc73043, 0x914b2b02, 0x439e6d84,
    0x2d1276c5, 0x9e865b06, 0xf00a4047, 0xe05dd04b, 0x8ed1cb0a,
    0x3d45e6c9, 0x53c9fd88, 0x811cbb0e, 0xef90a04f, 0x5c048d8c,
    0x328896cd, 0x7cabad94, 0x1227b6d5, 0xa1b39b16, 0xcf3f8057,
    0x1deac6d1, 0x7366dd90, 0xc0f2f053, 0xae7eeb12, 0xbe297b1e,
    0xd0a5605f, 0x63314d9c, 0x0dbd56dd, 0xdf68105b, 0xb1e40b1a,
    0x027026d9, 0x6cfc3d98, 0x3c95fb7e, 0x5219e03f, 0xe18dcdfc,
    0x8f01d6bd, 0x5dd4903b, 0x33588b7a, 0x80cca6b9, 0xee40bdf8,
    0xfe172df4, 0x909b36b5, 0x230f1b76, 0x4d830037, 0x9f5646b1,
    0xf1da5df0, 0x424e7033, 0x2cc26b72, 0x62e1502b, 0x0c6d4b6a,
    0xbff966a9, 0xd1757de8, 0x03a03b6e, 0x6d2c202f, 0xdeb80dec,
    0xb03416ad, 0xa06386a1, 0xceef9de0, 0x7d7bb023, 0x13f7ab62,
    0xc122ede4, 0xafaef6a5, 0x1c3adb66, 0x72b6c027, 0x807cadd4,
    0xeef0b695, 0x5d649b56, 0x33e88017, 0xe13dc691, 0x8fb1ddd0,
    0x3c25f013, 0x52a9eb52, 0x42fe7b5e, 0x2c72601f, 0x9fe64ddc,
    0xf16a569d, 0x23bf101b, 0x4d330b5a, 0xfea72699, 0x902b3dd8,
    0xde080681, 0xb0841dc0, 0x03103003, 0x6d9c2b42, 0xbf496dc4,
    0xd1c57685, 0x62515b46, 0x0cdd4007, 0x1c8ad00b, 0x7206cb4a,
    0xc192e689, 0xaf1efdc8, 0x7dcbbb4e, 0x1347a00f, 0xa0d38dcc,
    0xce5f968d},
   {0x00000000, 0xe71da697, 0x154a4b6f, 0xf257edf8, 0x2a9496de,
    0xcd893049, 0x3fdeddb1, 0xd8c37b26, 0x55292dbc, 0xb2348b2b,
    0x406366d3, 0xa77ec044, 0x7fbdbb62, 0x98a01df5, 0x6af7f00d,
    0x8dea569a, 0xaa525b78, 0x4d4ffdef, 0xbf181017, 0x5805b680,
    0x80c6cda6, 0x67db6b31, 0x958c86c9, 0x7291205e, 0xff7b76c4,
    0x1866d053, 0xea313dab, 0x0d2c9b3c, 0xd5efe01a, 0x32f2468d,
    0xc0a5ab75, 0x27b80de2, 0x8fd5b0b1, 0x68c81626, 0x9a9ffbde,
    0x7d825d49, 0xa541266f, 0x425c80f8, 0xb00b6d00, 0x5716cb97,
    0xdafc9d0d, 0x3de13b9a, 0xcfb6d662, 0x28ab70f5, 0xf0680bd3,
    0x1775ad44, 0xe52240bc, 0x023fe62b, 0x2587ebc9, 0xc29a4d5e,
    0x30cda0a6, 0xd7d00631, 0x0f137d17, 0xe80edb80, 0x1a593678,
    0xfd4490ef, 0x70aec675, 0x97b360e2, 0x65e48d1a, 0x82f92b8d,
    0x5a3a50ab, 0xbd27f63c, 0x4f701bc4, 0xa86dbd53, 0xc4da6723,
    0x23c7c1b4, 0xd1902c4c, 0x368d8adb, 0xee4ef1fd, 0x0953576a,
    0xfb04ba92, 0x1c191c05, 0x91f34a9f, 0x76eeec08, 0x84b901f0,
    0x63a4a767, 0xbb67dc41, 0x5c7a7ad6, 0xae2d972e, 0x493031b9,
    0x6e883c5b, 0x89959acc, 0x7bc27734, 0x9cdfd1a3, 0x441caa85,
    0xa3010c12, 0x5156e1ea, 0xb64b477d, 0x3ba111e7, 0xdcbcb770,
    0x2eeb5a88, 0xc9f6fc1f, 0x11358739, 0xf62821ae, 0x047fcc56,
    0xe3626ac1, 0x4b0fd792, 0xac127105, 0x5e459cfd, 0xb9583a6a,
    0x619b414c, 0x8686e7db, 0x74d10a23, 0x93ccacb4, 0x1e26fa2e,
    0xf93b5cb9, 0x0b6cb141, 0xec7117d6, 0x34b26cf0, 0xd3afca67,
    0x21f8279f, 0xc6e58108, 0xe15d8cea, 0x06402a7d, 0xf417c785,
    0x130a6112, 0xcbc91a34, 0x2cd4bca3, 0xde83515b, 0x399ef7cc,
    0xb474a156, 0x536907c1, 0xa13eea39, 0x46234cae, 0x9ee03788,
    0x79fd911f, 0x8baa7ce7, 0x6cb7da70, 0x52c5c807, 0xb5d86e90,
    0x478f8368, 0xa09225ff, 0x78515ed9, 0x9f4cf84e, 0x6d1b15b6,
    0x8a06b321, 0x07ece5bb, 0xe0f1432c, 0x12a6aed4, 0xf5bb0843,
    0x2d787365, 0xca65d5f2, 0x3832380a, 0xdf2f9e9d, 0xf897937f,
    0x1f8a35e8, 0xedddd810, 0x0ac07e87, 0xd20305a1, 0x351ea336,
    0xc7494ece, 0x2054e859, 0xadbebec3, 0x4aa31854, 0xb8f4f5ac,
    0x5fe9533b, 0x872a281d, 0x60378e8a, 0x92606372, 0x757dc5e5,
    0xdd1078b6, 0x3a0dde21, 0xc85a33d9, 0x2f47954e, 0xf784ee68,
    0x109948ff, 0xe2cea507, 0x05d30390, 0x8839550a, 0x6f24f39d,
    0x9d731e65, 0x7a6eb8f2, 0xa2adc3d4, 0x45b06543, 0xb7e788bb,
    0x50fa2e2c, 0x774223ce, 0x905f8559, 0x620868a1, 0x8515ce36,
    0x5dd6b510, 0xbacb1387, 0x489cfe7f, 0xaf8158e8, 0x226b0e72,
    0xc576a8e5, 0x3721451d, 0xd03ce38a, 0x08ff98ac, 0xefe23e3b,
    0x1db5d3c3, 0xfaa87554, 0x961faf24, 0x710209b3, 0x8355e44b,
    0x644842dc, 0xbc8b39fa, 0x5b969f6d, 0xa9c17295, 0x4edcd402,
    0xc3368298, 0x242b240f, 0xd67cc9f7, 0x31616f60, 0xe9a21446,
    0x0ebfb2d1, 0xfce85f29, 0x1bf5f9be, 0x3c4df45c, 0xdb5052cb,
    0x2907bf33, 0xce1a19a4, 0x16d96282, 0xf1c4c415, 0x039329ed,
    0xe48e8f7a, 0x6964d9e0, 0x8e797f77, 0x7c2e928f, 0x9b333418,
    0x43f04f3e, 0xa4ede9a9, 0x56ba0451, 0xb1a7a2c6, 0x19ca1f95,
    0xfed7b902, 0x0c8054fa, 0xeb9df26d, 0x335e894b, 0xd4432fdc,
    0x2614c224, 0xc10964b3, 0x4ce33229, 0xabfe94be, 0x59a97946,
    0xbeb4dfd1, 0x6677a4f7, 0x816a0260, 0x733def98, 0x9420490f,
    0xb39844ed, 0x5485e27a, 0xa6d20f82, 0x41cfa915, 0x990cd233,
    0x7e1174a4, 0x8c46995c, 0x6b5b3fcb, 0xe6b16951, 0x01accfc6,
    0xf3fb223e, 0x14e684a9, 0xcc25ff8f, 0x2b385918, 0xd96fb4e0,
    0x3e721277},
   {0x00000000, 0xa58b900e, 0x9066265d, 0x35edb653, 0xfbbd4afb,
    0x5e36daf5, 0x6bdb6ca6, 0xce50fca8, 0x2c0b93b7, 0x898003b9,
    0xbc6db5ea, 0x19e625e4, 0xd7b6d94c, 0x723d4942, 0x47d0ff11,
    0xe25b6f1f, 0x5817276e, 0xfd9cb760, 0xc8710133, 0x6dfa913d,
    0xa3aa6d95, 0x0621fd9b, 0x33cc4bc8, 0x9647dbc6, 0x741cb4d9,
    0xd19724d7, 0xe47a9284, 0x41f1028a, 0x8fa1fe22, 0x2a2a6e2c,
    0x1fc7d87f, 0xba4c4871, 0xb02e4edc, 0x15a5ded2, 0x20486881,
    0x85c3f88f, 0x4b930427, 0xee189429, 0xdbf5227a, 0x7e7eb274,
    0x9c25dd6b, 0x39ae4d65, 0x0c43fb36, 0xa9c86b38, 0x67989790,
    0xc213079e, 0xf7feb1cd, 0x527521c3, 0xe83969b2, 0x4db2f9bc,
    0x785f4fef, 0xddd4dfe1, 0x13842349, 0xb60fb347, 0x83e20514,
    0x2669951a, 0xc432fa05, 0x61b96a0b, 0x5454dc58, 0xf1df4c56,
    0x3f8fb0fe, 0x9a0420f0, 0xafe996a3, 0x0a6206ad, 0xbb2d9bf9,
    0x1ea60bf7, 0x2b4bbda4, 0x8ec02daa, 0x4090d102, 0xe51b410c,
    0xd0f6f75f, 0x757d6751, 0x9726084e, 0x32ad9840, 0x07402e13,
    0xa2cbbe1d, 0x6c9b42b5, 0xc910d2bb, 0xfcfd64e8, 0x5976f4e6,
    0xe33abc97, 0x46b12c99, 0x735c9aca, 0xd6d70ac4, 0x1887f66c,
    0xbd0c6662, 0x88e1d031, 0x2d6a403f, 0xcf312f20, 0x6ababf2e,
    0x5f57097d, 0xfadc9973, 0x348c65db, 0x9107f5d5, 0xa4ea4386,
    0x0161d388, 0x0b03d525, 0xae88452b, 0x9b65f378, 0x3eee6376,
    0xf0be9fde, 0x55350fd0, 0x60d8b983, 0xc553298d, 0x27084692,
    0x8283d69c, 0xb76e60cf, 0x12e5f0c1, 0xdcb50c69, 0x793e9c67,
    0x4cd32a34, 0xe958ba3a, 0x5314f24b, 0xf69f6245, 0xc372d416,
    0x66f94418, 0xa8a9b8b0, 0x0d2228be, 0x38cf9eed, 0x9d440ee3,
    0x7f1f61fc, 0xda94f1f2, 0xef7947a1, 0x4af2d7af, 0x84a22b07,
    0x2129bb09, 0x14c40d5a, 0xb14f9d54, 0xad2a31b3, 0x08a1a1bd,
    0x3d4c17ee, 0x98c787e0, 0x56977b48, 0xf31ceb46, 0xc6f15d15,
    0x637acd1b, 0x8121a204, 0x24aa320a, 0x11478459, 0xb4cc1457,
    0x7a9ce8ff, 0xdf1778f1, 0xeafacea2, 0x4f715eac, 0xf53d16dd,
    0x50b686d3, 0x655b3080, 0xc0d0a08e, 0x0e805c26, 0xab0bcc28,
    0x9ee67a7b, 0x3b6dea75, 0xd936856a, 0x7cbd1564, 0x4950a337,
    0xecdb3339, 0x228bcf91, 0x87005f9f, 0xb2ede9cc, 0x176679c2,
    0x1d047f6f, 0xb88fef61, 0x8d625932, 0x28e9c93c, 0xe6b93594,
    0x4332a59a, 0x76df13c9, 0xd35483c7, 0x310fecd8, 0x94847cd6,
    0xa169ca85, 0x04e25a8b, 0xcab2a623, 0x6f39362d, 0x5ad4807e,
    0xff5f1070, 0x45135801, 0xe098c80f, 0xd5757e5c, 0x70feee52,
    0xbeae12fa, 0x1b2582f4, 0x2ec834a7, 0x8b43a4a9, 0x6918cbb6,
    0xcc935bb8, 0xf97eedeb, 0x5cf57de5, 0x92a5814d, 0x372e1143,
    0x02c3a710, 0xa748371e, 0x1607aa4a, 0xb38c3a44, 0x86618c17,
    0x23ea1c19, 0xedbae0b1, 0x483170bf, 0x7ddcc6ec, 0xd85756e2,
    0x3a0c39fd, 0x9f87a9f3, 0xaa6a1fa0, 0x0fe18fae, 0xc1b17306,
    0x643ae308, 0x51d7555b, 0xf45cc555, 0x4e108d24, 0xeb9b1d2a,
    0xde76ab79, 0x7bfd3b77, 0xb5adc7df, 0x102657d1, 0x25cbe182,
    0x8040718c, 0x621b1e93, 0xc7908e9d, 0xf27d38ce, 0x57f6a8c0,
    0x99a65468, 0x3c2dc466, 0x09c07235, 0xac4be23b, 0xa629e496,
    0x03a27498, 0x364fc2cb, 0x93c452c5, 0x5d94ae6d, 0xf81f3e63,
    0xcdf28830, 0x6879183e, 0x8a227721, 0x2fa9e72f, 0x1a44517c,
    0xbfcfc172, 0x719f3dda, 0xd414add4, 0xe1f91b87, 0x44728b89,
    0xfe3ec3f8, 0x5bb553f6, 0x6e58e5a5, 0xcbd375ab, 0x05838903,
    0xa008190d, 0x95e5af5e, 0x306e3f50, 0xd235504f, 0x77bec041,
    0x42537612, 0xe7d8e61c, 0x29881ab4, 0x8c038aba, 0xb9ee3ce9,
    0x1c65ace7}};

local const z_word_t FAR crc_braid_big_table[][256] = {
   {0x0000000000000000, 0x0e908ba500000000, 0x5d26669000000000,
    0x53b6ed3500000000, 0xfb4abdfb00000000, 0xf5da365e00000000,
    0xa66cdb6b00000000, 0xa8fc50ce00000000, 0xb7930b2c00000000,
    0xb903808900000000, 0xeab56dbc00000000, 0xe425e61900000000,
    0x4cd9b6d700000000, 0x42493d7200000000, 0x11ffd04700000000,
    0x1f6f5be200000000, 0x6e27175800000000, 0x60b79cfd00000000,
    0x330171c800000000, 0x3d91fa6d00000000, 0x956daaa300000000,
    0x9bfd210600000000, 0xc84bcc3300000000, 0xc6db479600000000,
    0xd9b41c7400000000, 0xd72497d100000000, 0x84927ae400000000,
    0x8a02f14100000000, 0x22fea18f00000000, 0x2c6e2a2a00000000,
    0x7fd8c71f00000000, 0x71484cba00000000, 0xdc4e2eb000000000,
    0xd2dea51500000000, 0x8168482000000000, 0x8ff8c38500000000,
    0x2704934b00000000, 0x299418ee00000000, 0x7a22f5db00000000,
    0x74b27e7e00000000, 0x6bdd259c00000000, 0x654dae3900000000,
    0x36fb430c00000000, 0x386bc8a900000000, 0x9097986700000000,
    0x9e0713c200000000, 0xcdb1fef700000000, 0xc321755200000000,
    0xb26939e800000000, 0xbcf9b24d00000000, 0xef4f5f7800000000,
    0xe1dfd4dd00000000, 0x4923841300000000, 0x47b30fb600000000,
    0x1405e28300000000, 0x1a95692600000000, 0x05fa32c400000000,
    0x0b6ab96100000000, 0x58dc545400000000, 0x564cdff100000000,
    0xfeb08f3f00000000, 0xf020049a00000000, 0xa396e9af00000000,
    0xad06620a00000000, 0xf99b2dbb00000000, 0xf70ba61e00000000,
    0xa4bd4b2b00000000, 0xaa2dc08e00000000, 0x02d1904000000000,
    0x0c411be500000000, 0x5ff7f6d000000000, 0x51677d7500000000,
    0x4e08269700000000, 0x4098ad3200000000, 0x132e400700000000,
    0x1dbecba200000000, 0xb5429b6c00000000, 0xbbd210c900000000,
    0xe864fdfc00000000, 0xe6f4765900000000, 0x97bc3ae300000000,
    0x992cb14600000000, 0xca9a5c7300000000, 0xc40ad7d600000000,
    0x6cf6871800000000, 0x62660cbd00000000, 0x31d0e18800000000,
    0x3f406a2d00000000, 0x202f31cf00000000, 0x2ebfba6a00000000,
    0x7d09575f00000000, 0x7399dcfa00000000, 0xdb658c3400000000,
    0xd5f5079100000000, 0x8643eaa400000000, 0x88d3610100000000,
    0x25d5030b00000000, 0x2b4588ae00000000, 0x78f3659b00000000,
    0x7663ee3e00000000, 0xde9fbef000000000, 0xd00f355500000000,
    0x83b9d86000000000, 0x8d2953c500000000, 0x9246082700000000,
    0x9cd6838200000000, 0xcf606eb700000000, 0xc1f0e51200000000,
    0x690cb5dc00000000, 0x679c3e7900000000, 0x342ad34c00000000,
    0x3aba58e900000000, 0x4bf2145300000000, 0x45629ff600000000,
    0x16d472c300000000, 0x1844f96600000000, 0xb0b8a9a800000000,
    0xbe28220d00000000, 0xed9ecf3800000000, 0xe30e449d00000000,
    0xfc611f7f00000000, 0xf2f194da00000000, 0xa14779ef00000000,
    0xafd7f24a00000000, 0x072ba28400000000, 0x09bb292100000000,
    0x5a0dc41400000000, 0x549d4fb100000000, 0xb3312aad00000000,
    0xbda1a10800000000, 0xee174c3d00000000, 0xe087c79800000000,
    0x487b975600000000, 0x46eb1cf300000000, 0x155df1c600000000,
    0x1bcd7a6300000000, 0x04a2218100000000, 0x0a32aa2400000000,
    0x5984471100000000, 0x5714ccb400000000, 0xffe89c7a00000000,
    0xf17817df00000000, 0xa2cefaea00000000, 0xac5e714f00000000,
    0xdd163df500000000, 0xd386b65000000000, 0x80305b6500000000,
    0x8ea0d0c000000000, 0x265c800e00000000, 0x28cc0bab00000000,
    0x7b7ae69e00000000, 0x75ea6d3b00000000, 0x6a8536d900000000,
    0x6415bd7c00000000, 0x37a3504900000000, 0x3933dbec00000000,
    0x91cf8b2200000000, 0x9f5f008700000000, 0xcce9edb200000000,
    0xc279661700000000, 0x6f7f041d00000000, 0x61ef8fb800000000,
    0x3259628d00000000, 0x3cc9e92800000000, 0x9435b9e600000000,
    0x9aa5324300000000, 0xc913df7600000000, 0xc78354d300000000,
    0xd8ec0f3100000000, 0xd67c849400000000, 0x85ca69a100000000,
    0x8b5ae20400000000, 0x23a6b2ca00000000, 0x2d36396f00000000,
    0x7e80d45a00000000, 0x70105fff00000000, 0x0158134500000000,
    0x0fc898e000000000, 0x5c7e75d500000000, 0x52eefe7000000000,
    0xfa12aebe00000000, 0xf482251b00000000, 0xa734c82e00000000,
    0xa9a4438b00000000, 0xb6cb186900000000, 0xb85b93cc00000000,
    0xebed7ef900000000, 0xe57df55c00000000, 0x4d81a59200000000,
    0x43112e3700000000, 0x10a7c30200000000, 0x1e3748a700000000,
    0x4aaa071600000000, 0x443a8cb300000000, 0x178c618600000000,
    0x191cea2300000000, 0xb1e0baed00000000, 0xbf70314800000000,
    0xecc6dc7d00000000, 0xe25657d800000000, 0xfd390c3a00000000,
    0xf3a9879f00000000, 0xa01f6aaa00000000, 0xae8fe10f00000000,
    0x0673b1c100000000, 0x08e33a6400000000, 0x5b55d75100000000,
    0x55c55cf400000000, 0x248d104e00000000, 0x2a1d9beb00000000,
    0x79ab76de00000000, 0x773bfd7b00000000, 0xdfc7adb500000000,
    0xd157261000000000, 0x82e1cb2500000000, 0x8c71408000000000,
    0x931e1b6200000000, 0x9d8e90c700000000, 0xce387df200000000,
    0xc0a8f65700000000, 0x6854a69900000000, 0x66c42d3c00000000,
    0x3572c00900000000, 0x3be24bac00000000, 0x96e429a600000000,
    0x9874a20300000000, 0xcbc24f3600000000, 0xc552c49300000000,
    0x6dae945d00000000, 0x633e1ff800000000, 0x3088f2cd00000000,
    0x3e18796800000000, 0x2177228a00000000, 0x2fe7a92f00000000,
    0x7c51441a00000000, 0x72c1cfbf00000000, 0xda3d9f7100000000,
    0xd4ad14d400000000, 0x871bf9e100000000, 0x898b724400000000,
    0xf8c33efe00000000, 0xf653b55b00000000, 0xa5e5586e00000000,
    0xab75d3cb00000000, 0x0389830500000000, 0x0d1908a000000000,
    0x5eafe59500000000, 0x503f6e3000000000, 0x4f5035d200000000,
    0x41c0be7700000000, 0x1276534200000000, 0x1ce6d8e700000000,
    0xb41a882900000000, 0xba8a038c00000000, 0xe93ceeb900000000,
    0xe7ac651c00000000},
   {0x0000000000000000, 0x97a61de700000000, 0x6f4b4a1500000000,
    0xf8ed57f200000000, 0xde96942a00000000, 0x493089cd00000000,
    0xb1ddde3f00000000, 0x267bc3d800000000, 0xbc2d295500000000,
    0x2b8b34b200000000, 0xd366634000000000, 0x44c07ea700000000,
    0x62bbbd7f00000000, 0xf51da09800000000, 0x0df0f76a00000000,
    0x9a56ea8d00000000, 0x785b52aa00000000, 0xeffd4f4d00000000,
    0x171018bf00000000, 0x80b6055800000000, 0xa6cdc68000000000,
    0x316bdb6700000000, 0xc9868c9500000000, 0x5e20917200000000,
    0xc4767bff00000000, 0x53d0661800000000, 0xab3d31ea00000000,
    0x3c9b2c0d00000000, 0x1ae0efd500000000, 0x8d46f23200000000,
    0x75aba5c000000000, 0xe20db82700000000, 0xb1b0d58f00000000,
    0x2616c86800000000, 0xdefb9f9a00000000, 0x495d827d00000000,
    0x6f2641a500000000, 0xf8805c4200000000, 0x006d0bb000000000,
    0x97cb165700000000, 0x0d9dfcda00000000, 0x9a3be13d00000000,
    0x62d6b6cf00000000, 0xf570ab2800000000, 0xd30b68f000000000,
    0x44ad751700000000, 0xbc4022e500000000, 0x2be63f0200000000,
    0xc9eb872500000000, 0x5e4d9ac200000000, 0xa6a0cd3000000000,
    0x3106d0d700000000, 0x177d130f00000000, 0x80db0ee800000000,
    0x7836591a00000000, 0xef9044fd00000000, 0x75c6ae7000000000,
    0xe260b39700000000, 0x1a8de46500000000, 0x8d2bf98200000000,
    0xab503a5a00000000, 0x3cf627bd00000000, 0xc41b704f00000000,
    0x53bd6da800000000, 0x2367dac400000000, 0xb4c1c72300000000,
    0x4c2c90d100000000, 0xdb8a8d3600000000, 0xfdf14eee00000000,
    0x6a57530900000000, 0x92ba04fb00000000, 0x051c191c00000000,
    0x9f4af39100000000, 0x08ecee7600000000, 0xf001b98400000000,
    0x67a7a46300000000, 0x41dc67bb00000000, 0xd67a7a5c00000000,
    0x2e972dae00000000, 0xb931304900000000, 0x5b3c886e00000000,
    0xcc9a958900000000, 0x3477c27b00000000, 0xa3d1df9c00000000,
    0x85aa1c4400000000, 0x120c01a300000000, 0xeae1565100000000,
    0x7d474bb600000000, 0xe711a13b00000000, 0x70b7bcdc00000000,
    0x885aeb2e00000000, 0x1ffcf6c900000000, 0x3987351100000000,
    0xae2128f600000000, 0x56cc7f0400000000, 0xc16a62e300000000,
    0x92d70f4b00000000, 0x057112ac00000000, 0xfd9c455e00000000,
    0x6a3a58b900000000, 0x4c419b6100000000, 0xdbe7868600000000,
    0x230ad17400000000, 0xb4accc9300000000, 0x2efa261e00000000,
    0xb95c3bf900000000, 0x41b16c0b00000000, 0xd61771ec00000000,
    0xf06cb23400000000, 0x67caafd300000000, 0x9f27f82100000000,
    0x0881e5c600000000, 0xea8c5de100000000, 0x7d2a400600000000,
    0x85c717f400000000, 0x12610a1300000000, 0x341ac9cb00000000,
    0xa3bcd42c00000000, 0x5b5183de00000000, 0xccf79e3900000000,
    0x56a174b400000000, 0xc107695300000000, 0x39ea3ea100000000,
    0xae4c234600000000, 0x8837e09e00000000, 0x1f91fd7900000000,
    0xe77caa8b00000000, 0x70dab76c00000000, 0x07c8c55200000000,
    0x906ed8b500000000, 0x68838f4700000000, 0xff2592a000000000,
    0xd95e517800000000, 0x4ef84c9f00000000, 0xb6151b6d00000000,
    0x21b3068a00000000, 0xbbe5ec0700000000, 0x2c43f1e000000000,
    0xd4aea61200000000, 0x4308bbf500000000, 0x6573782d00000000,
    0xf2d565ca00000000, 0x0a38323800000000, 0x9d9e2fdf00000000,
    0x7f9397f800000000, 0xe8358a1f00000000, 0x10d8dded00000000,
    0x877ec00a00000000, 0xa10503d200000000, 0x36a31e3500000000,
    0xce4e49c700000000, 0x59e8542000000000, 0xc3bebead00000000,
    0x5418a34a00000000, 0xacf5f4b800000000, 0x3b53e95f00000000,
    0x1d282a8700000000, 0x8a8e376000000000, 0x7263609200000000,
    0xe5c57d7500000000, 0xb67810dd00000000, 0x21de0d3a00000000,
    0xd9335ac800000000, 0x4e95472f00000000, 0x68ee84f700000000,
    0xff48991000000000, 0x07a5cee200000000, 0x9003d30500000000,
    0x0a55398800000000, 0x9df3246f00000000, 0x651e739d00000000,
    0xf2b86e7a00000000, 0xd4c3ada200000000, 0x4365b04500000000,
    0xbb88e7b700000000, 0x2c2efa5000000000, 0xce23427700000000,
    0x59855f9000000000, 0xa168086200000000, 0x36ce158500000000,
    0x10b5d65d00000000, 0x8713cbba00000000, 0x7ffe9c4800000000,
    0xe85881af00000000, 0x720e6b2200000000, 0xe5a876c500000000,
    0x1d45213700000000, 0x8ae33cd000000000, 0xac98ff0800000000,
    0x3b3ee2ef00000000, 0xc3d3b51d00000000, 0x5475a8fa00000000,
    0x24af1f9600000000, 0xb309027100000000, 0x4be4558300000000,
    0xdc42486400000000, 0xfa398bbc00000000, 0x6d9f965b00000000,
    0x9572c1a900000000, 0x02d4dc4e00000000, 0x988236c300000000,
    0x0f242b2400000000, 0xf7c97cd600000000, 0x606f613100000000,
    0x4614a2e900000000, 0xd1b2bf0e00000000, 0x295fe8fc00000000,
    0xbef9f51b00000000, 0x5cf44d3c00000000, 0xcb5250db00000000,
    0x33bf072900000000, 0xa4191ace00000000, 0x8262d91600000000,
    0x15c4c4f100000000, 0xed29930300000000, 0x7a8f8ee400000000,
    0xe0d9646900000000, 0x777f798e00000000, 0x8f922e7c00000000,
    0x1834339b00000000, 0x3e4ff04300000000, 0xa9e9eda400000000,
    0x5104ba5600000000, 0xc6a2a7b100000000, 0x951fca1900000000,
    0x02b9d7fe00000000, 0xfa54800c00000000, 0x6df29deb00000000,
    0x4b895e3300000000, 0xdc2f43d400000000, 0x24c2142600000000,
    0xb36409c100000000, 0x2932e34c00000000, 0xbe94feab00000000,
    0x4679a95900000000, 0xd1dfb4be00000000, 0xf7a4776600000000,
    0x60026a8100000000, 0x98ef3d7300000000, 0x0f49209400000000,
    0xed4498b300000000, 0x7ae2855400000000, 0x820fd2a600000000,
    0x15a9cf4100000000, 0x33d20c9900000000, 0xa474117e00000000,
    0x5c99468c00000000, 0xcb3f5b6b00000000, 0x5169b1e600000000,
    0xc6cfac0100000000, 0x3e22fbf300000000, 0xa984e61400000000,
    0x8fff25cc00000000, 0x1859382b00000000, 0xe0b46fd900000000,
    0x7712723e00000000},
   {0x0000000000000000, 0x411b8c6e00000000, 0x823618dd00000000,
    0xc32d94b300000000, 0x456b416100000000, 0x0470cd0f00000000,
    0xc75d59bc00000000, 0x8646d5d200000000, 0x8ad682c200000000,
    0xcbcd0eac00000000, 0x08e09a1f00000000, 0x49fb167100000000,
    0xcfbdc3a300000000, 0x8ea64fcd00000000, 0x4d8bdb7e00000000,
    0x0c90571000000000, 0x55ab745e00000000, 0x14b0f83000000000,
    0xd79d6c8300000000, 0x9686e0ed00000000, 0x10c0353f00000000,
    0x51dbb95100000000, 0x92f62de200000000, 0xd3eda18c00000000,
    0xdf7df69c00000000, 0x9e667af200000000, 0x5d4bee4100000000,
    0x1c50622f00000000, 0x9a16b7fd00000000, 0xdb0d3b9300000000,
    0x1820af2000000000, 0x593b234e00000000, 0xaa56e9bc00000000,
    0xeb4d65d200000000, 0x2860f16100000000, 0x697b7d0f00000000,
    0xef3da8dd00000000, 0xae2624b300000000, 0x6d0bb00000000000,
    0x2c103c6e00000000, 0x20806b7e00000000, 0x619be71000000000,
    0xa2b673a300000000, 0xe3adffcd00000000, 0x65eb2a1f00000000,
    0x24f0a67100000000, 0xe7dd32c200000000, 0xa6c6beac00000000,
    0xfffd9de200000000, 0xbee6118c00000000, 0x7dcb853f00000000,
    0x3cd0095100000000, 0xba96dc8300000000, 0xfb8d50ed00000000,
    0x38a0c45e00000000, 0x79bb483000000000, 0x752b1f2000000000,
    0x3430934e00000000, 0xf71d07fd00000000, 0xb6068b9300000000,
    0x30405e4100000000, 0x715bd22f00000000, 0xb276469c00000000,
    0xf36dcaf200000000, 0x15aba3a200000000, 0x54b02fcc00000000,
    0x979dbb7f00000000, 0xd686371100000000, 0x50c0e2c300000000,
    0x11db6ead00000000, 0xd2f6fa1e00000000, 0x93ed767000000000,
    0x9f7d216000000000, 0xde66ad0e00000000, 0x1d4b39bd00000000,
    0x5c50b5d300000000, 0xda16600100000000, 0x9b0dec6f00000000,
    0x582078dc00000000, 0x193bf4b200000000, 0x4000d7fc00000000,
    0x011b5b9200000000, 0xc236cf2100000000, 0x832d434f00000000,
    0x056b969d00000000, 0x44701af300000000, 0x875d8e4000000000,
    0xc646022e00000000, 0xcad6553e00000000, 0x8bcdd95000000000,
    0x48e04de300000000, 0x09fbc18d00000000, 0x8fbd145f00000000,
    0xcea6983100000000, 0x0d8b0c8200000000, 0x4c9080ec00000000,
    0xbffd4a1e00000000, 0xfee6c67000000000, 0x3dcb52c300000000,
    0x7cd0dead00000000, 0xfa960b7f00000000, 0xbb8d871100000000,
    0x78a013a200000000, 0x39bb9fcc00000000, 0x352bc8dc00000000,
    0x743044b200000000, 0xb71dd00100000000, 0xf6065c6f00000000,
    0x704089bd00000000, 0x315b05d300000000, 0xf276916000000000,
    0xb36d1d0e00000000, 0xea563e4000000000, 0xab4db22e00000000,
    0x6860269d00000000, 0x297baaf300000000, 0xaf3d7f2100000000,
    0xee26f34f00000000, 0x2d0b67fc00000000, 0x6c10eb9200000000,
    0x6080bc8200000000, 0x219b30ec00000000, 0xe2b6a45f00000000,
    0xa3ad283100000000, 0x25ebfde300000000, 0x64f0718d00000000,
    0xa7dde53e00000000, 0xe6c6695000000000, 0x6b50369e00000000,
    0x2a4bbaf000000000, 0xe9662e4300000000, 0xa87da22d00000000,
    0x2e3b77ff00000000, 0x6f20fb9100000000, 0xac0d6f2200000000,
    0xed16e34c00000000, 0xe186b45c00000000, 0xa09d383200000000,
    0x63b0ac8100000000, 0x22ab20ef00000000, 0xa4edf53d00000000,
    0xe5f6795300000000, 0x26dbede000000000, 0x67c0618e00000000,
    0x3efb42c000000000, 0x7fe0ceae00000000, 0xbccd5a1d00000000,
    0xfdd6d67300000000, 0x7b9003a100000000, 0x3a8b8fcf00000000,
    0xf9a61b7c00000000, 0xb8bd971200000000, 0xb42dc00200000000,
    0xf5364c6c00000000, 0x361bd8df00000000, 0x770054b100000000,
    0xf146816300000000, 0xb05d0d0d00000000, 0x737099be00000000,
    0x326b15d000000000, 0xc106df2200000000, 0x801d534c00000000,
    0x4330c7ff00000000, 0x022b4b9100000000, 0x846d9e4300000000,
    0xc576122d00000000, 0x065b869e00000000, 0x47400af000000000,
    0x4bd05de000000000, 0x0acbd18e00000000, 0xc9e6453d00000000,
    0x88fdc95300000000, 0x0ebb1c8100000000, 0x4fa090ef00000000,
    0x8c8d045c00000000, 0xcd96883200000000, 0x94adab7c00000000,
    0xd5b6271200000000, 0x169bb3a100000000, 0x57803fcf00000000,
    0xd1c6ea1d00000000, 0x90dd667300000000, 0x53f0f2c000000000,
    0x12eb7eae00000000, 0x1e7b29be00000000, 0x5f60a5d000000000,
    0x9c4d316300000000, 0xdd56bd0d00000000, 0x5b1068df00000000,
    0x1a0be4b100000000, 0xd926700200000000, 0x983dfc6c00000000,
    0x7efb953c00000000, 0x3fe0195200000000, 0xfccd8de100000000,
    0xbdd6018f00000000, 0x3b90d45d00000000, 0x7a8b583300000000,
    0xb9a6cc8000000000, 0xf8bd40ee00000000, 0xf42d17fe00000000,
    0xb5369b9000000000, 0x761b0f2300000000, 0x3700834d00000000,
    0xb146569f00000000, 0xf05ddaf100000000, 0x33704e4200000000,
    0x726bc22c00000000, 0x2b50e16200000000, 0x6a4b6d0c00000000,
    0xa966f9bf00000000, 0xe87d75d100000000, 0x6e3ba00300000000,
    0x2f202c6d00000000, 0xec0db8de00000000, 0xad1634b000000000,
    0xa18663a000000000, 0xe09defce00000000, 0x23b07b7d00000000,
    0x62abf71300000000, 0xe4ed22c100000000, 0xa5f6aeaf00000000,
    0x66db3a1c00000000, 0x27c0b67200000000, 0xd4ad7c8000000000,
    0x95b6f0ee00000000, 0x569b645d00000000, 0x1780e83300000000,
    0x91c63de100000000, 0xd0ddb18f00000000, 0x13f0253c00000000,
    0x52eba95200000000, 0x5e7bfe4200000000, 0x1f60722c00000000,
    0xdc4de69f00000000, 0x9d566af100000000, 0x1b10bf2300000000,
    0x5a0b334d00000000, 0x9926a7fe00000000, 0xd83d2b9000000000,
    0x810608de00000000, 0xc01d84b000000000, 0x0330100300000000,
    0x422b9c6d00000000, 0xc46d49bf00000000, 0x8576c5d100000000,
    0x465b516200000000, 0x0740dd0c00000000, 0x0bd08a1c00000000,
    0x4acb067200000000, 0x89e692c100000000, 0xc8fd1eaf00000000,
    0x4ebbcb7d00000000, 0x0fa0471300000000, 0xcc8dd3a000000000,
    0x8d965fce00000000},
   {0x0000000000000000, 0x1dfdb50100000000, 0x3afa6b0300000000,
    0x2707de0200000000, 0x74f4d70600000000, 0x6909620700000000,
    0x4e0ebc0500000000, 0x53f3090400000000, 0xe8e8af0d00000000,
    0xf5151a0c00000000, 0xd212c40e00000000, 0xcfef710f00000000,
    0x9c1c780b00000000, 0x81e1cd0a00000000, 0xa6e6130800000000,
    0xbb1ba60900000000, 0xd0d15f1b00000000, 0xcd2cea1a00000000,
    0xea2b341800000000, 0xf7d6811900000000, 0xa425881d00000000,
    0xb9d83d1c00000000, 0x9edfe31e00000000, 0x8322561f00000000,
    0x3839f01600000000, 0x25c4451700000000, 0x02c39b1500000000,
    0x1f3e2e1400000000, 0x4ccd271000000000, 0x5130921100000000,
    0x76374c1300000000, 0x6bcaf91200000000, 0xa0a3bf3600000000,
    0xbd5e0a3700000000, 0x9a59d43500000000, 0x87a4613400000000,
    0xd457683000000000, 0xc9aadd3100000000, 0xeead033300000000,
    0xf350b63200000000, 0x484b103b00000000, 0x55b6a53a00000000,
    0x72b17b3800000000, 0x6f4cce3900000000, 0x3cbfc73d00000000,
    0x2142723c00000000, 0x0645ac3e00000000, 0x1bb8193f00000000,
    0x7072e02d00000000, 0x6d8f552c00000000, 0x4a888b2e00000000,
    0x57753e2f00000000, 0x0486372b00000000, 0x197b822a00000000,
    0x3e7c5c2800000000, 0x2381e92900000000, 0x989a4f2000000000,
    0x8567fa2100000000, 0xa260242300000000, 0xbf9d912200000000,
    0xec6e982600000000, 0xf1932d2700000000, 0xd694f32500000000,
    0xcb69462400000000, 0x40477f6d00000000, 0x5dbaca6c00000000,
    0x7abd146e00000000, 0x6740a16f00000000, 0x34b3a86b00000000,
    0x294e1d6a00000000, 0x0e49c36800000000, 0x13b4766900000000,
    0xa8afd06000000000, 0xb552656100000000, 0x9255bb6300000000,
    0x8fa80e6200000000, 0xdc5b076600000000, 0xc1a6b26700000000,
    0xe6a16c6500000000, 0xfb5cd96400000000, 0x9096207600000000,
    0x8d6b957700000000, 0xaa6c4b7500000000, 0xb791fe7400000000,
    0xe462f77000000000, 0xf99f427100000000, 0xde989c7300000000,
    0xc365297200000000, 0x787e8f7b00000000, 0x65833a7a00000000,
    0x4284e47800000000, 0x5f79517900000000, 0x0c8a587d00000000,
    0x1177ed7c00000000, 0x3670337e00000000, 0x2b8d867f00000000,
    0xe0e4c05b00000000, 0xfd19755a00000000, 0xda1eab5800000000,
    0xc7e31e5900000000, 0x9410175d00000000, 0x89eda25c00000000,
    0xaeea7c5e00000000, 0xb317c95f00000000, 0x080c6f5600000000,
    0x15f1da5700000000, 0x32f6045500000000, 0x2f0bb15400000000,
    0x7cf8b85000000000, 0x61050d5100000000, 0x4602d35300000000,
    0x5bff665200000000, 0x30359f4000000000, 0x2dc82a4100000000,
    0x0acff44300000000, 0x1732414200000000, 0x44c1484600000000,
    0x593cfd4700000000, 0x7e3b234500000000, 0x63c6964400000000,
    0xd8dd304d00000000, 0xc520854c00000000, 0xe2275b4e00000000,
    0xffdaee4f00000000, 0xac29e74b00000000, 0xb1d4524a00000000,
    0x96d38c4800000000, 0x8b2e394900000000, 0x808efeda00000000,
    0x9d734bdb00000000, 0xba7495d900000000, 0xa78920d800000000,
    0xf47a29dc00000000, 0xe9879cdd00000000, 0xce8042df00000000,
    0xd37df7de00000000, 0x686651d700000000, 0x759be4d600000000,
    0x529c3ad400000000, 0x4f618fd500000000, 0x1c9286d100000000,
    0x016f33d000000000, 0x2668edd200000000, 0x3b9558d300000000,
    0x505fa1c100000000, 0x4da214c000000000, 0x6aa5cac200000000,
    0x77587fc300000000, 0x24ab76c700000000, 0x3956c3c600000000,
    0x1e511dc400000000, 0x03aca8c500000000, 0xb8b70ecc00000000,
    0xa54abbcd00000000, 0x824d65cf00000000, 0x9fb0d0ce00000000,
    0xcc43d9ca00000000, 0xd1be6ccb00000000, 0xf6b9b2c900000000,
    0xeb4407c800000000, 0x202d41ec00000000, 0x3dd0f4ed00000000,
    0x1ad72aef00000000, 0x072a9fee00000000, 0x54d996ea00000000,
    0x492423eb00000000, 0x6e23fde900000000, 0x73de48e800000000,
    0xc8c5eee100000000, 0xd5385be000000000, 0xf23f85e200000000,
    0xefc230e300000000, 0xbc3139e700000000, 0xa1cc8ce600000000,
    0x86cb52e400000000, 0x9b36e7e500000000, 0xf0fc1ef700000000,
    0xed01abf600000000, 0xca0675f400000000, 0xd7fbc0f500000000,
    0x8408c9f100000000, 0x99f57cf000000000, 0xbef2a2f200000000,
    0xa30f17f300000000, 0x1814b1fa00000000, 0x05e904fb00000000,
    0x22eedaf900000000, 0x3f136ff800000000, 0x6ce066fc00000000,
    0x711dd3fd00000000, 0x561a0dff00000000, 0x4be7b8fe00000000,
    0xc0c981b700000000, 0xdd3434b600000000, 0xfa33eab400000000,
    0xe7ce5fb500000000, 0xb43d56b100000000, 0xa9c0e3b000000000,
    0x8ec73db200000000, 0x933a88b300000000, 0x28212eba00000000,
    0x35dc9bbb00000000, 0x12db45b900000000, 0x0f26f0b800000000,
    0x5cd5f9bc00000000, 0x41284cbd00000000, 0x662f92bf00000000,
    0x7bd227be00000000, 0x1018deac00000000, 0x0de56bad00000000,
    0x2ae2b5af00000000, 0x371f00ae00000000, 0x64ec09aa00000000,
    0x7911bcab00000000, 0x5e1662a900000000, 0x43ebd7a800000000,
    0xf8f071a100000000, 0xe50dc4a000000000, 0xc20a1aa200000000,
    0xdff7afa300000000, 0x8c04a6a700000000, 0x91f913a600000000,
    0xb6fecda400000000, 0xab0378a500000000, 0x606a3e8100000000,
    0x7d978b8000000000, 0x5a90558200000000, 0x476de08300000000,
    0x149ee98700000000, 0x09635c8600000000, 0x2e64828400000000,
    0x3399378500000000, 0x8882918c00000000, 0x957f248d00000000,
    0xb278fa8f00000000, 0xaf854f8e00000000, 0xfc76468a00000000,
    0xe18bf38b00000000, 0xc68c2d8900000000, 0xdb71988800000000,
    0xb0bb619a00000000, 0xad46d49b00000000, 0x8a410a9900000000,
    0x97bcbf9800000000, 0xc44fb69c00000000, 0xd9b2039d00000000,
    0xfeb5dd9f00000000, 0xe348689e00000000, 0x5853ce9700000000,
    0x45ae7b9600000000, 0x62a9a59400000000, 0x7f54109500000000,
    0x2ca7199100000000, 0x315aac9000000000, 0x165d729200000000,
    0x0ba0c79300000000},
   {0x0000000000000000, 0x24d9076300000000, 0x48b20fc600000000,
    0x6c6b08a500000000, 0xd1626e5700000000, 0xf5bb693400000000,
    0x99d0619100000000, 0xbd0966f200000000, 0xa2c5dcae00000000,
    0x861cdbcd00000000, 0xea77d36800000000, 0xceaed40b00000000,
    0x73a7b2f900000000, 0x577eb59a00000000, 0x3b15bd3f00000000,
    0x1fccba5c00000000, 0x058dc88600000000, 0x2154cfe500000000,
    0x4d3fc74000000000, 0x69e6c02300000000, 0xd4efa6d100000000,
    0xf036a1b200000000, 0x9c5da91700000000, 0xb884ae7400000000,
    0xa748142800000000, 0x8391134b00000000, 0xeffa1bee00000000,
    0xcb231c8d00000000, 0x762a7a7f00000000, 0x52f37d1c00000000,
    0x3e9875b900000000, 0x1a4172da00000000, 0x4b1ce0d600000000,
    0x6fc5e7b500000000, 0x03aeef1000000000, 0x2777e87300000000,
    0x9a7e8e8100000000, 0xbea789e200000000, 0xd2cc814700000000,
    0xf615862400000000, 0xe9d93c7800000000, 0xcd003b1b00000000,
    0xa16b33be00000000, 0x85b234dd00000000, 0x38bb522f00000000,
    0x1c62554c00000000, 0x70095de900000000, 0x54d05a8a00000000,
    0x4e91285000000000, 0x6a482f3300000000, 0x0623279600000000,
    0x22fa20f500000000, 0x9ff3460700000000, 0xbb2a416400000000,
    0xd74149c100000000, 0xf3984ea200000000, 0xec54f4fe00000000,
    0xc88df39d00000000, 0xa4e6fb3800000000, 0x803ffc5b00000000,
    0x3d369aa900000000, 0x19ef9dca00000000, 0x7584956f00000000,
    0x515d920c00000000, 0xd73eb17600000000, 0xf3e7b61500000000,
    0x9f8cbeb000000000, 0xbb55b9d300000000, 0x065cdf2100000000,
    0x2285d84200000000, 0x4eeed0e700000000, 0x6a37d78400000000,
    0x75fb6dd800000000, 0x51226abb00000000, 0x3d49621e00000000,
    0x1990657d00000000, 0xa499038f00000000, 0x804004ec00000000,
    0xec2b0c4900000000, 0xc8f20b2a00000000, 0xd2b379f000000000,
    0xf66a7e9300000000, 0x9a01763600000000, 0xbed8715500000000,
    0x03d117a700000000, 0x270810c400000000, 0x4b63186100000000,
    0x6fba1f0200000000, 0x7076a55e00000000, 0x54afa23d00000000,
    0x38c4aa9800000000, 0x1c1dadfb00000000, 0xa114cb0900000000,
    0x85cdcc6a00000000, 0xe9a6c4cf00000000, 0xcd7fc3ac00000000,
    0x9c2251a000000000, 0xb8fb56c300000000, 0xd4905e6600000000,
    0xf049590500000000, 0x4d403ff700000000, 0x6999389400000000,
    0x05f2303100000000, 0x212b375200000000, 0x3ee78d0e00000000,
    0x1a3e8a6d00000000, 0x765582c800000000, 0x528c85ab00000000,
    0xef85e35900000000, 0xcb5ce43a00000000, 0xa737ec9f00000000,
    0x83eeebfc00000000, 0x99af992600000000, 0xbd769e4500000000,
    0xd11d96e000000000, 0xf5c4918300000000, 0x48cdf77100000000,
    0x6c14f01200000000, 0x007ff8b700000000, 0x24a6ffd400000000,
    0x3b6a458800000000, 0x1fb342eb00000000, 0x73d84a4e00000000,
    0x57014d2d00000000, 0xea082bdf00000000, 0xced12cbc00000000,
    0xa2ba241900000000, 0x8663237a00000000, 0xae7d62ed00000000,
    0x8aa4658e00000000, 0xe6cf6d2b00000000, 0xc2166a4800000000,
    0x7f1f0cba00000000, 0x5bc60bd900000000, 0x37ad037c00000000,
    0x1374041f00000000, 0x0cb8be4300000000, 0x2861b92000000000,
    0x440ab18500000000, 0x60d3b6e600000000, 0xdddad01400000000,
    0xf903d77700000000, 0x9568dfd200000000, 0xb1b1d8b100000000,
    0xabf0aa6b00000000, 0x8f29ad0800000000, 0xe342a5ad00000000,
    0xc79ba2ce00000000, 0x7a92c43c00000000, 0x5e4bc35f00000000,
    0x3220cbfa00000000, 0x16f9cc9900000000, 0x093576c500000000,
    0x2dec71a600000000, 0x4187790300000000, 0x655e7e6000000000,
    0xd857189200000000, 0xfc8e1ff100000000, 0x90e5175400000000,
    0xb43c103700000000, 0xe561823b00000000, 0xc1b8855800000000,
    0xadd38dfd00000000, 0x890a8a9e00000000, 0x3403ec6c00000000,
    0x10daeb0f00000000, 0x7cb1e3aa00000000, 0x5868e4c900000000,
    0x47a45e9500000000, 0x637d59f600000000, 0x0f16515300000000,
    0x2bcf563000000000, 0x96c630c200000000, 0xb21f37a100000000,
    0xde743f0400000000, 0xfaad386700000000, 0xe0ec4abd00000000,
    0xc4354dde00000000, 0xa85e457b00000000, 0x8c87421800000000,
    0x318e24ea00000000, 0x1557238900000000, 0x793c2b2c00000000,
    0x5de52c4f00000000, 0x4229961300000000, 0x66f0917000000000,
    0x0a9b99d500000000, 0x2e429eb600000000, 0x934bf84400000000,
    0xb792ff2700000000, 0xdbf9f78200000000, 0xff20f0e100000000,
    0x7943d39b00000000, 0x5d9ad4f800000000, 0x31f1dc5d00000000,
    0x1528db3e00000000, 0xa821bdcc00000000, 0x8cf8baaf00000000,
    0xe093b20a00000000, 0xc44ab56900000000, 0xdb860f3500000000,
    0xff5f085600000000, 0x933400f300000000, 0xb7ed079000000000,
    0x0ae4616200000000, 0x2e3d660100000000, 0x42566ea400000000,
    0x668f69c700000000, 0x7cce1b1d00000000, 0x58171c7e00000000,
    0x347c14db00000000, 0x10a513b800000000, 0xadac754a00000000,
    0x8975722900000000, 0xe51e7a8c00000000, 0xc1c77def00000000,
    0xde0bc7b300000000, 0xfad2c0d000000000, 0x96b9c87500000000,
    0xb260cf1600000000, 0x0f69a9e400000000, 0x2bb0ae8700000000,
    0x47dba62200000000, 0x6302a14100000000, 0x325f334d00000000,
    0x1686342e00000000, 0x7aed3c8b00000000, 0x5e343be800000000,
    0xe33d5d1a00000000, 0xc7e45a7900000000, 0xab8f52dc00000000,
    0x8f5655bf00000000, 0x909aefe300000000, 0xb443e88000000000,
    0xd828e02500000000, 0xfcf1e74600000000, 0x41f881b400000000,
    0x652186d700000000, 0x094a8e7200000000, 0x2d93891100000000,
    0x37d2fbcb00000000, 0x130bfca800000000, 0x7f60f40d00000000,
    0x5bb9f36e00000000, 0xe6b0959c00000000, 0xc26992ff00000000,
    0xae029a5a00000000, 0x8adb9d3900000000, 0x9517276500000000,
    0xb1ce200600000000, 0xdda528a300000000, 0xf97c2fc000000000,
    0x4475493200000000, 0x60ac4e5100000000, 0x0cc746f400000000,
    0x281e419700000000},
   {0x0000000000000000, 0x08e3603c00000000, 0x10c6c17800000000,
    0x1825a14400000000, 0x208c83f100000000, 0x286fe3cd00000000,
    0x304a428900000000, 0x38a922b500000000, 0x011e763800000000,
    0x09fd160400000000, 0x11d8b74000000000, 0x193bd77c00000000,
    0x2192f5c900000000, 0x297195f500000000, 0x315434b100000000,
    0x39b7548d00000000, 0x023cec7000000000, 0x0adf8c4c00000000,
    0x12fa2d0800000000, 0x1a194d3400000000, 0x22b06f8100000000,
    0x2a530fbd00000000, 0x3276aef900000000, 0x3a95cec500000000,
    0x03229a4800000000, 0x0bc1fa7400000000, 0x13e45b3000000000,
    0x1b073b0c00000000, 0x23ae19b900000000, 0x2b4d798500000000,
    0x3368d8c100000000, 0x3b8bb8fd00000000, 0x0478d8e100000000,
    0x0c9bb8dd00000000, 0x14be199900000000, 0x1c5d79a500000000,
    0x24f45b1000000000, 0x2c173b2c00000000, 0x34329a6800000000,
    0x3cd1fa5400000000, 0x0566aed900000000, 0x0d85cee500000000,
    0x15a06fa100000000, 0x1d430f9d00000000, 0x25ea2d2800000000,
    0x2d094d1400000000, 0x352cec5000000000, 0x3dcf8c6c00000000,
    0x0644349100000000, 0x0ea754ad00000000, 0x1682f5e900000000,
    0x1e6195d500000000, 0x26c8b76000000000, 0x2e2bd75c00000000,
    0x360e761800000000, 0x3eed162400000000, 0x075a42a900000000,
    0x0fb9229500000000, 0x179c83d100000000, 0x1f7fe3ed00000000,
    0x27d6c15800000000, 0x2f35a16400000000, 0x3710002000000000,
    0x3ff3601c00000000, 0x49f6c11800000000, 0x4115a12400000000,
    0x5930006000000000, 0x51d3605c00000000, 0x697a42e900000000,
    0x619922d500000000, 0x79bc839100000000, 0x715fe3ad00000000,
    0x48e8b72000000000, 0x400bd71c00000000, 0x582e765800000000,
    0x50cd166400000000, 0x686434d100000000, 0x608754ed00000000,
    0x78a2f5a900000000, 0x7041959500000000, 0x4bca2d6800000000,
    0x43294d5400000000, 0x5b0cec1000000000, 0x53ef8c2c00000000,
    0x6b46ae9900000000, 0x63a5cea500000000, 0x7b806fe100000000,
    0x73630fdd00000000, 0x4ad45b5000000000, 0x42373b6c00000000,
    0x5a129a2800000000, 0x52f1fa1400000000, 0x6a58d8a100000000,
    0x62bbb89d00000000, 0x7a9e19d900000000, 0x727d79e500000000,
    0x4d8e19f900000000, 0x456d79c500000000, 0x5d48d88100000000,
    0x55abb8bd00000000, 0x6d029a0800000000, 0x65e1fa3400000000,
    0x7dc45b7000000000, 0x75273b4c00000000, 0x4c906fc100000000,
    0x44730ffd00000000, 0x5c56aeb900000000, 0x54b5ce8500000000,
    0x6c1cec3000000000, 0x64ff8c0c00000000, 0x7cda2d4800000000,
    0x74394d7400000000, 0x4fb2f58900000000, 0x475195b500000000,
    0x5f7434f100000000, 0x579754cd00000000, 0x6f3e767800000000,
    0x67dd164400000000, 0x7ff8b70000000000, 0x771bd73c00000000,
    0x4eac83b100000000, 0x464fe38d00000000, 0x5e6a42c900000000,
    0x568922f500000000, 0x6e20004000000000, 0x66c3607c00000000,
    0x7ee6c13800000000, 0x7605a10400000000, 0x92ec833100000000,
    0x9a0fe30d00000000, 0x822a424900000000, 0x8ac9227500000000,
    0xb26000c000000000, 0xba8360fc00000000, 0xa2a6c1b800000000,
    0xaa45a18400000000, 0x93f2f50900000000, 0x9b11953500000000,
    0x8334347100000000, 0x8bd7544d00000000, 0xb37e76f800000000,
    0xbb9d16c400000000, 0xa3b8b78000000000, 0xab5bd7bc00000000,
    0x90d06f4100000000, 0x98330f7d00000000, 0x8016ae3900000000,
    0x88f5ce0500000000, 0xb05cecb000000000, 0xb8bf8c8c00000000,
    0xa09a2dc800000000, 0xa8794df400000000, 0x91ce197900000000,
    0x992d794500000000, 0x8108d80100000000, 0x89ebb83d00000000,
    0xb1429a8800000000, 0xb9a1fab400000000, 0xa1845bf000000000,
    0xa9673bcc00000000, 0x96945bd000000000, 0x9e773bec00000000,
    0x86529aa800000000, 0x8eb1fa9400000000, 0xb618d82100000000,
    0xbefbb81d00000000, 0xa6de195900000000, 0xae3d796500000000,
    0x978a2de800000000, 0x9f694dd400000000, 0x874cec9000000000,
    0x8faf8cac00000000, 0xb706ae1900000000, 0xbfe5ce2500000000,
    0xa7c06f6100000000, 0xaf230f5d00000000, 0x94a8b7a000000000,
    0x9c4bd79c00000000, 0x846e76d800000000, 0x8c8d16e400000000,
    0xb424345100000000, 0xbcc7546d00000000, 0xa4e2f52900000000,
    0xac01951500000000, 0x95b6c19800000000, 0x9d55a1a400000000,
    0x857000e000000000, 0x8d9360dc00000000, 0xb53a426900000000,
    0xbdd9225500000000, 0xa5fc831100000000, 0xad1fe32d00000000,
    0xdb1a422900000000, 0xd3f9221500000000, 0xcbdc835100000000,
    0xc33fe36d00000000, 0xfb96c1d800000000, 0xf375a1e400000000,
    0xeb5000a000000000, 0xe3b3609c00000000, 0xda04341100000000,
    0xd2e7542d00000000, 0xcac2f56900000000, 0xc221955500000000,
    0xfa88b7e000000000, 0xf26bd7dc00000000, 0xea4e769800000000,
    0xe2ad16a400000000, 0xd926ae5900000000, 0xd1c5ce6500000000,
    0xc9e06f2100000000, 0xc1030f1d00000000, 0xf9aa2da800000000,
    0xf1494d9400000000, 0xe96cecd000000000, 0xe18f8cec00000000,
    0xd838d86100000000, 0xd0dbb85d00000000, 0xc8fe191900000000,
    0xc01d792500000000, 0xf8b45b9000000000, 0xf0573bac00000000,
    0xe8729ae800000000, 0xe091fad400000000, 0xdf629ac800000000,
    0xd781faf400000000, 0xcfa45bb000000000, 0xc7473b8c00000000,
    0xffee193900000000, 0xf70d790500000000, 0xef28d84100000000,
    0xe7cbb87d00000000, 0xde7cecf000000000, 0xd69f8ccc00000000,
    0xceba2d8800000000, 0xc6594db400000000, 0xfef06f0100000000,
    0xf6130f3d00000000, 0xee36ae7900000000, 0xe6d5ce4500000000,
    0xdd5e76b800000000, 0xd5bd168400000000, 0xcd98b7c000000000,
    0xc57bd7fc00000000, 0xfdd2f54900000000, 0xf531957500000000,
    0xed14343100000000, 0xe5f7540d00000000, 0xdc40008000000000,
    0xd4a360bc00000000, 0xcc86c1f800000000, 0xc465a1c400000000,
    0xfccc837100000000, 0xf42fe34d00000000, 0xec0a420900000000,
    0xe4e9223500000000},
   {0x0000000000000000, 0xd1e8e70e00000000, 0xa2d1cf1d00000000,
    0x7339281300000000, 0x44a39f3b00000000, 0x954b783500000000,
    0xe672502600000000, 0x379ab72800000000, 0x88463f7700000000,
    0x59aed87900000000, 0x2a97f06a00000000, 0xfb7f176400000000,
    0xcce5a04c00000000, 0x1d0d474200000000, 0x6e346f5100000000,
    0xbfdc885f00000000, 0x108d7eee00000000, 0xc16599e000000000,
    0xb25cb1f300000000, 0x63b456fd00000000, 0x542ee1d500000000,
    0x85c606db00000000, 0xf6ff2ec800000000, 0x2717c9c600000000,
    0x98cb419900000000, 0x4923a69700000000, 0x3a1a8e8400000000,
    0xebf2698a00000000, 0xdc68dea200000000, 0x0d8039ac00000000,
    0x7eb911bf00000000, 0xaf51f6b100000000, 0x611c8c0700000000,
    0xb0f46b0900000000, 0xc3cd431a00000000, 0x1225a41400000000,
    0x25bf133c00000000, 0xf457f43200000000, 0x876edc2100000000,
    0x56863b2f00000000, 0xe95ab37000000000, 0x38b2547e00000000,
    0x4b8b7c6d00000000, 0x9a639b6300000000, 0xadf92c4b00000000,
    0x7c11cb4500000000, 0x0f28e35600000000, 0xdec0045800000000,
    0x7191f2e900000000, 0xa07915e700000000, 0xd3403df400000000,
    0x02a8dafa00000000, 0x35326dd200000000, 0xe4da8adc00000000,
    0x97e3a2cf00000000, 0x460b45c100000000, 0xf9d7cd9e00000000,
    0x283f2a9000000000, 0x5b06028300000000, 0x8aeee58d00000000,
    0xbd7452a500000000, 0x6c9cb5ab00000000, 0x1fa59db800000000,
    0xce4d7ab600000000, 0xc238180f00000000, 0x13d0ff0100000000,
    0x60e9d71200000000, 0xb101301c00000000, 0x869b873400000000,
    0x5773603a00000000, 0x244a482900000000, 0xf5a2af2700000000,
    0x4a7e277800000000, 0x9b96c07600000000, 0xe8afe86500000000,
    0x39470f6b00000000, 0x0eddb84300000000, 0xdf355f4d00000000,
    0xac0c775e00000000, 0x7de4905000000000, 0xd2b566e100000000,
    0x035d81ef00000000, 0x7064a9fc00000000, 0xa18c4ef200000000,
    0x9616f9da00000000, 0x47fe1ed400000000, 0x34c736c700000000,
    0xe52fd1c900000000, 0x5af3599600000000, 0x8b1bbe9800000000,
    0xf822968b00000000, 0x29ca718500000000, 0x1e50c6ad00000000,
    0xcfb821a300000000, 0xbc8109b000000000, 0x6d69eebe00000000,
    0xa324940800000000, 0x72cc730600000000, 0x01f55b1500000000,
    0xd01dbc1b00000000, 0xe7870b3300000000, 0x366fec3d00000000,
    0x4556c42e00000000, 0x94be232000000000, 0x2b62ab7f00000000,
    0xfa8a4c7100000000, 0x89b3646200000000, 0x585b836c00000000,
    0x6fc1344400000000, 0xbe29d34a00000000, 0xcd10fb5900000000,
    0x1cf81c5700000000, 0xb3a9eae600000000, 0x62410de800000000,
    0x117825fb00000000, 0xc090c2f500000000, 0xf70a75dd00000000,
    0x26e292d300000000, 0x55dbbac000000000, 0x84335dce00000000,
    0x3befd59100000000, 0xea07329f00000000, 0x993e1a8c00000000,
    0x48d6fd8200000000, 0x7f4c4aaa00000000, 0xaea4ada400000000,
    0xdd9d85b700000000, 0x0c7562b900000000, 0x8471301e00000000,
    0x5599d71000000000, 0x26a0ff0300000000, 0xf748180d00000000,
    0xc0d2af2500000000, 0x113a482b00000000, 0x6203603800000000,
    0xb3eb873600000000, 0x0c370f6900000000, 0xdddfe86700000000,
    0xaee6c07400000000, 0x7f0e277a00000000, 0x4894905200000000,
    0x997c775c00000000, 0xea455f4f00000000, 0x3badb84100000000,
    0x94fc4ef000000000, 0x4514a9fe00000000, 0x362d81ed00000000,
    0xe7c566e300000000, 0xd05fd1cb00000000, 0x01b736c500000000,
    0x728e1ed600000000, 0xa366f9d800000000, 0x1cba718700000000,
    0xcd52968900000000, 0xbe6bbe9a00000000, 0x6f83599400000000,
    0x5819eebc00000000, 0x89f109b200000000, 0xfac821a100000000,
    0x2b20c6af00000000, 0xe56dbc1900000000, 0x34855b1700000000,
    0x47bc730400000000, 0x9654940a00000000, 0xa1ce232200000000,
    0x7026c42c00000000, 0x031fec3f00000000, 0xd2f70b3100000000,
    0x6d2b836e00000000, 0xbcc3646000000000, 0xcffa4c7300000000,
    0x1e12ab7d00000000, 0x29881c5500000000, 0xf860fb5b00000000,
    0x8b59d34800000000, 0x5ab1344600000000, 0xf5e0c2f700000000,
    0x240825f900000000, 0x57310dea00000000, 0x86d9eae400000000,
    0xb1435dcc00000000, 0x60abbac200000000, 0x139292d100000000,
    0xc27a75df00000000, 0x7da6fd8000000000, 0xac4e1a8e00000000,
    0xdf77329d00000000, 0x0e9fd59300000000, 0x390562bb00000000,
    0xe8ed85b500000000, 0x9bd4ada600000000, 0x4a3c4aa800000000,
    0x4649281100000000, 0x97a1cf1f00000000, 0xe498e70c00000000,
    0x3570000200000000, 0x02eab72a00000000, 0xd302502400000000,
    0xa03b783700000000, 0x71d39f3900000000, 0xce0f176600000000,
    0x1fe7f06800000000, 0x6cded87b00000000, 0xbd363f7500000000,
    0x8aac885d00000000, 0x5b446f5300000000, 0x287d474000000000,
    0xf995a04e00000000, 0x56c456ff00000000, 0x872cb1f100000000,
    0xf41599e200000000, 0x25fd7eec00000000, 0x1267c9c400000000,
    0xc38f2eca00000000, 0xb0b606d900000000, 0x615ee1d700000000,
    0xde82698800000000, 0x0f6a8e8600000000, 0x7c53a69500000000,
    0xadbb419b00000000, 0x9a21f6b300000000, 0x4bc911bd00000000,
    0x38f039ae00000000, 0xe918dea000000000, 0x2755a41600000000,
    0xf6bd431800000000, 0x85846b0b00000000, 0x546c8c0500000000,
    0x63f63b2d00000000, 0xb21edc2300000000, 0xc127f43000000000,
    0x10cf133e00000000, 0xaf139b6100000000, 0x7efb7c6f00000000,
    0x0dc2547c00000000, 0xdc2ab37200000000, 0xebb0045a00000000,
    0x3a58e35400000000, 0x4961cb4700000000, 0x98892c4900000000,
    0x37d8daf800000000, 0xe6303df600000000, 0x950915e500000000,
    0x44e1f2eb00000000, 0x737b45c300000000, 0xa293a2cd00000000,
    0xd1aa8ade00000000, 0x00426dd000000000, 0xbf9ee58f00000000,
    0x6e76028100000000, 0x1d4f2a9200000000, 0xcca7cd9c00000000,
    0xfb3d7ab400000000, 0x2ad59dba00000000, 0x59ecb5a900000000,
    0x880452a700000000},
   {0x0000000000000000, 0xaa05daf100000000, 0x150dc53800000000,
    0xbf081fc900000000, 0x2a1a8a7100000000, 0x801f508000000000,
    0x3f174f4900000000, 0x951295b800000000, 0x543414e300000000,
    0xfe31ce1200000000, 0x4139d1db00000000, 0xeb3c0b2a00000000,
    0x7e2e9e9200000000, 0xd42b446300000000, 0x6b235baa00000000,
    0xc126815b00000000, 0xe96e591d00000000, 0x436b83ec00000000,
    0xfc639c2500000000, 0x566646d400000000, 0xc374d36c00000000,
    0x6971099d00000000, 0xd679165400000000, 0x7c7ccca500000000,
    0xbd5a4dfe00000000, 0x175f970f00000000, 0xa85788c600000000,
    0x0252523700000000, 0x9740c78f00000000, 0x3d451d7e00000000,
    0x824d02b700000000, 0x2848d84600000000, 0xd2ddb23a00000000,
    0x78d868cb00000000, 0xc7d0770200000000, 0x6dd5adf300000000,
    0xf8c7384b00000000, 0x52c2e2ba00000000, 0xedcafd7300000000,
    0x47cf278200000000, 0x86e9a6d900000000, 0x2cec7c2800000000,
    0x93e463e100000000, 0x39e1b91000000000, 0xacf32ca800000000,
    0x06f6f65900000000, 0xb9fee99000000000, 0x13fb336100000000,
    0x3bb3eb2700000000, 0x91b631d600000000, 0x2ebe2e1f00000000,
    0x84bbf4ee00000000, 0x11a9615600000000, 0xbbacbba700000000,
    0x04a4a46e00000000, 0xaea17e9f00000000, 0x6f87ffc400000000,
    0xc582253500000000, 0x7a8a3afc00000000, 0xd08fe00d00000000,
    0x459d75b500000000, 0xef98af4400000000, 0x5090b08d00000000,
    0xfa956a7c00000000, 0xa4bb657500000000, 0x0ebebf8400000000,
    0xb1b6a04d00000000, 0x1bb37abc00000000, 0x8ea1ef0400000000,
    0x24a435f500000000, 0x9bac2a3c00000000, 0x31a9f0cd00000000,
    0xf08f719600000000, 0x5a8aab6700000000, 0xe582b4ae00000000,
    0x4f876e5f00000000, 0xda95fbe700000000, 0x7090211600000000,
    0xcf983edf00000000, 0x659de42e00000000, 0x4dd53c6800000000,
    0xe7d0e69900000000, 0x58d8f95000000000, 0xf2dd23a100000000,
    0x67cfb61900000000, 0xcdca6ce800000000, 0x72c2732100000000,
    0xd8c7a9d000000000, 0x19e1288b00000000, 0xb3e4f27a00000000,
    0x0cecedb300000000, 0xa6e9374200000000, 0x33fba2fa00000000,
    0x99fe780b00000000, 0x26f667c200000000, 0x8cf3bd3300000000,
    0x7666d74f00000000, 0xdc630dbe00000000, 0x636b127700000000,
    0xc96ec88600000000, 0x5c7c5d3e00000000, 0xf67987cf00000000,
    0x4971980600000000, 0xe37442f700000000, 0x2252c3ac00000000,
    0x8857195d00000000, 0x375f069400000000, 0x9d5adc6500000000,
    0x084849dd00000000, 0xa24d932c00000000, 0x1d458ce500000000,
    0xb740561400000000, 0x9f088e5200000000, 0x350d54a300000000,
    0x8a054b6a00000000, 0x2000919b00000000, 0xb512042300000000,
    0x1f17ded200000000, 0xa01fc11b00000000, 0x0a1a1bea00000000,
    0xcb3c9ab100000000, 0x6139404000000000, 0xde315f8900000000,
    0x7434857800000000, 0xe12610c000000000, 0x4b23ca3100000000,
    0xf42bd5f800000000, 0x5e2e0f0900000000, 0x4877cbea00000000,
    0xe272111b00000000, 0x5d7a0ed200000000, 0xf77fd42300000000,
    0x626d419b00000000, 0xc8689b6a00000000, 0x776084a300000000,
    0xdd655e5200000000, 0x1c43df0900000000, 0xb64605f800000000,
    0x094e1a3100000000, 0xa34bc0c000000000, 0x3659557800000000,
    0x9c5c8f8900000000, 0x2354904000000000, 0x89514ab100000000,
    0xa11992f700000000, 0x0b1c480600000000, 0xb41457cf00000000,
    0x1e118d3e00000000, 0x8b03188600000000, 0x2106c27700000000,
    0x9e0eddbe00000000, 0x340b074f00000000, 0xf52d861400000000,
    0x5f285ce500000000, 0xe020432c00000000, 0x4a2599dd00000000,
    0xdf370c6500000000, 0x7532d69400000000, 0xca3ac95d00000000,
    0x603f13ac00000000, 0x9aaa79d000000000, 0x30afa32100000000,
    0x8fa7bce800000000, 0x25a2661900000000, 0xb0b0f3a100000000,
    0x1ab5295000000000, 0xa5bd369900000000, 0x0fb8ec6800000000,
    0xce9e6d3300000000, 0x649bb7c200000000, 0xdb93a80b00000000,
    0x719672fa00000000, 0xe484e74200000000, 0x4e813db300000000,
    0xf189227a00000000, 0x5b8cf88b00000000, 0x73c420cd00000000,
    0xd9c1fa3c00000000, 0x66c9e5f500000000, 0xcccc3f0400000000,
    0x59deaabc00000000, 0xf3db704d00000000, 0x4cd36f8400000000,
    0xe6d6b57500000000, 0x27f0342e00000000, 0x8df5eedf00000000,
    0x32fdf11600000000, 0x98f82be700000000, 0x0deabe5f00000000,
    0xa7ef64ae00000000, 0x18e77b6700000000, 0xb2e2a19600000000,
    0xecccae9f00000000, 0x46c9746e00000000, 0xf9c16ba700000000,
    0x53c4b15600000000, 0xc6d624ee00000000, 0x6cd3fe1f00000000,
    0xd3dbe1d600000000, 0x79de3b2700000000, 0xb8f8ba7c00000000,
    0x12fd608d00000000, 0xadf57f4400000000, 0x07f0a5b500000000,
    0x92e2300d00000000, 0x38e7eafc00000000, 0x87eff53500000000,
    0x2dea2fc400000000, 0x05a2f78200000000, 0xafa72d7300000000,
    0x10af32ba00000000, 0xbaaae84b00000000, 0x2fb87df300000000,
    0x85bda70200000000, 0x3ab5b8cb00000000, 0x90b0623a00000000,
    0x5196e36100000000, 0xfb93399000000000, 0x449b265900000000,
    0xee9efca800000000, 0x7b8c691000000000, 0xd189b3e100000000,
    0x6e81ac2800000000, 0xc48476d900000000, 0x3e111ca500000000,
    0x9414c65400000000, 0x2b1cd99d00000000, 0x8119036c00000000,
    0x140b96d400000000, 0xbe0e4c2500000000, 0x010653ec00000000,
    0xab03891d00000000, 0x6a25084600000000, 0xc020d2b700000000,
    0x7f28cd7e00000000, 0xd52d178f00000000, 0x403f823700000000,
    0xea3a58c600000000, 0x5532470f00000000, 0xff379dfe00000000,
    0xd77f45b800000000, 0x7d7a9f4900000000, 0xc272808000000000,
    0x68775a7100000000, 0xfd65cfc900000000, 0x5760153800000000,
    0xe8680af100000000, 0x426dd00000000000, 0x834b515b00000000,
    0x294e8baa00000000, 0x9646946300000000, 0x3c434e9200000000,
    0xa951db2a00000000, 0x035401db00000000, 0xbc5c1e1200000000,
    0x1659c4e300000000}};

#else /* W == 4 */

local const z_crc_t FAR crc_braid_table[][256] = {
   {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87,
    0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
    0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
    0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
    0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
    0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
    0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
    0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
    0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
    0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
    0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
    0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
    0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
    0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
    0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
    0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
    0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
    0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
    0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
    0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
    0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
    0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
    0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
    0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
    0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
    0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
    0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
    0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
    0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
    0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
    0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
    0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
    0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
    0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
    0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
    0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
    0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
    0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
    0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
    0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
    0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
    0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
    0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
    0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
    0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
    0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
    0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
    0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
    0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
    0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
    0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
    0x72fd2493UL
  },
    0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede,
    0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab,
    0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c,
    0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1,
    0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7,
    0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e,
    0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308,
    0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5,
    0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472,
    0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07,
    0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e,
    0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa,
    0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec,
    0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6,
    0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0,
    0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3,
    0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba,
    0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf,
    0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975,
    0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8,
    0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde,
    0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a,
    0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c,
    0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1,
    0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65,
    0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410,
    0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649,
    0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a,
    0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c,
    0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946,
    0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450,
    0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e,
    0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857,
    0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022,
    0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5,
    0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758,
    0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e,
    0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d,
    0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b,
    0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6,
    0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401,
    0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74,
    0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d,
    0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073,
    0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65,
    0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f,
    0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749,
    0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a,
    0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033,
    0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846,
    0x0d7139d7},
   {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563,
    0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f,
    0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875,
    0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536,
    0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8,
    0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43,
    0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f,
    0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184,
    0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a,
    0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39,
    0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523,
    0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f,
    0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d,
    0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6,
    0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b,
    0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0,
    0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151,
    0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d,
    0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47,
    0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a,
    0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964,
    0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef,
    0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d,
    0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6,
    0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348,
    0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53,
    0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449,
    0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645,
    0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4,
    0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f,
    0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2,
    0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69,
    0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46,
    0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a,
    0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650,
    0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13,
    0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded,
    0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366,
    0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57,
    0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc,
    0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222,
    0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61,
    0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b,
    0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277,
    0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558,
    0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3,
    0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e,
    0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5,
    0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74,
    0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78,
    0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262,
    0x1c53e98a},
   {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b,
    0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40,
    0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580,
    0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7,
    0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a,
    0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37,
    0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75,
    0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218,
    0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5,
    0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2,
    0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02,
    0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59,
    0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1,
    0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c,
    0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a,
    0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307,
    0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486,
    0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd,
    0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d,
    0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2,
    0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f,
    0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72,
    0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8,
    0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985,
    0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268,
    0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94,
    0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454,
    0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f,
    0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e,
    0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3,
    0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915,
    0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778,
    0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821,
    0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a,
    0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba,
    0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d,
    0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560,
    0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d,
    0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe,
    0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3,
    0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e,
    0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509,
    0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9,
    0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92,
    0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb,
    0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6,
    0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50,
    0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d,
    0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc,
    0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7,
    0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927,
    0x3f88e851},
   {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96,
    0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8,
    0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0,
    0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14,
    0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7,
    0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4,
    0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe,
    0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad,
    0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e,
    0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa,
    0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2,
    0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c,
    0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab,
    0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8,
    0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d,
    0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e,
    0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7,
    0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99,
    0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1,
    0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690,
    0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933,
    0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20,
    0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf,
    0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc,
    0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f,
    0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92,
    0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca,
    0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4,
    0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd,
    0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de,
    0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb,
    0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8,
    0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474,
    0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a,
    0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252,
    0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6,
    0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55,
    0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846,
    0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7,
    0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4,
    0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47,
    0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3,
    0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb,
    0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5,
    0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49,
    0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a,
    0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f,
    0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c,
    0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305,
    0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b,
    0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523,
    0x3dee8ca6}};

local const z_word_t FAR crc_braid_big_table[][256] = {
   {0x00000000, 0x85d996dd, 0x4bb55c60, 0xce6ccabd, 0x966ab9c0,
    0x13b32f1d, 0xdddfe5a0, 0x5806737d, 0x6dd3035a, 0xe80a9587,
    0x26665f3a, 0xa3bfc9e7, 0xfbb9ba9a, 0x7e602c47, 0xb00ce6fa,
    0x35d57027, 0xdaa607b4, 0x5f7f9169, 0x91135bd4, 0x14cacd09,
    0x4cccbe74, 0xc91528a9, 0x0779e214, 0x82a074c9, 0xb77504ee,
    0x32ac9233, 0xfcc0588e, 0x7919ce53, 0x211fbd2e, 0xa4c62bf3,
    0x6aaae14e, 0xef737793, 0xf54b7eb3, 0x7092e86e, 0xbefe22d3,
    0x3b27b40e, 0x6321c773, 0xe6f851ae, 0x28949b13, 0xad4d0dce,
    0x98987de9, 0x1d41eb34, 0xd32d2189, 0x56f4b754, 0x0ef2c429,
    0x8b2b52f4, 0x45479849, 0xc09e0e94, 0x2fed7907, 0xaa34efda,
    0x64582567, 0xe181b3ba, 0xb987c0c7, 0x3c5e561a, 0xf2329ca7,
    0x77eb0a7a, 0x423e7a5d, 0xc7e7ec80, 0x098b263d, 0x8c52b0e0,
    0xd454c39d, 0x518d5540, 0x9fe19ffd, 0x1a380920, 0xab918dbd,
    0x2e481b60, 0xe024d1dd, 0x65fd4700, 0x3dfb347d, 0xb822a2a0,
    0x764e681d, 0xf397fec0, 0xc6428ee7, 0x439b183a, 0x8df7d287,
    0x082e445a, 0x50283727, 0xd5f1a1fa, 0x1b9d6b47, 0x9e44fd9a,
    0x71378a09, 0xf4ee1cd4, 0x3a82d669, 0xbf5b40b4, 0xe75d33c9,
    0x6284a514, 0xace86fa9, 0x2931f974, 0x1ce48953, 0x993d1f8e,
    0x5751d533, 0xd28843ee, 0x8a8e3093, 0x0f57a64e, 0xc13b6cf3,
    0x44e2fa2e, 0x5edaf30e, 0xdb0365d3, 0x156faf6e, 0x90b639b3,
    0xc8b04ace, 0x4d69dc13, 0x830516ae, 0x06dc8073, 0x3309f054,
    0xb6d06689, 0x78bcac34, 0xfd653ae9, 0xa5634994, 0x20badf49,
    0xeed615f4, 0x6b0f8329, 0x847cf4ba, 0x01a56267, 0xcfc9a8da,
    0x4a103e07, 0x12164d7a, 0x97cfdba7, 0x59a3111a, 0xdc7a87c7,
    0xe9aff7e0, 0x6c76613d, 0xa21aab80, 0x27c33d5d, 0x7fc54e20,
    0xfa1cd8fd, 0x34701240, 0xb1a9849d, 0x17256aa0, 0x92fcfc7d,
    0x5c9036c0, 0xd949a01d, 0x814fd360, 0x049645bd, 0xcafa8f00,
    0x4f2319dd, 0x7af669fa, 0xff2fff27, 0x3143359a, 0xb49aa347,
    0xec9cd03a, 0x694546e7, 0xa7298c5a, 0x22f01a87, 0xcd836d14,
    0x485afbc9, 0x86363174, 0x03efa7a9, 0x5be9d4d4, 0xde304209,
    0x105c88b4, 0x95851e69, 0xa0506e4e, 0x2589f893, 0xebe5322e,
    0x6e3ca4f3, 0x363ad78e, 0xb3e34153, 0x7d8f8bee, 0xf8561d33,
    0xe26e1413, 0x67b782ce, 0xa9db4873, 0x2c02deae, 0x7404add3,
    0xf1dd3b0e, 0x3fb1f1b3, 0xba68676e, 0x8fbd1749, 0x0a648194,
    0xc4084b29, 0x41d1ddf4, 0x19d7ae89, 0x9c0e3854, 0x5262f2e9,
    0xd7bb6434, 0x38c813a7, 0xbd11857a, 0x737d4fc7, 0xf6a4d91a,
    0xaea2aa67, 0x2b7b3cba, 0xe517f607, 0x60ce60da, 0x551b10fd,
    0xd0c28620, 0x1eae4c9d, 0x9b77da40, 0xc371a93d, 0x46a83fe0,
    0x88c4f55d, 0x0d1d6380, 0xbcb4e71d, 0x396d71c0, 0xf701bb7d,
    0x72d82da0, 0x2ade5edd, 0xaf07c800, 0x616b02bd, 0xe4b29460,
    0xd167e447, 0x54be729a, 0x9ad2b827, 0x1f0b2efa, 0x470d5d87,
    0xc2d4cb5a, 0x0cb801e7, 0x8961973a, 0x6612e0a9, 0xe3cb7674,
    0x2da7bcc9, 0xa87e2a14, 0xf0785969, 0x75a1cfb4, 0xbbcd0509,
    0x3e1493d4, 0x0bc1e3f3, 0x8e18752e, 0x4074bf93, 0xc5ad294e,
    0x9dab5a33, 0x1872ccee, 0xd61e0653, 0x53c7908e, 0x49ff99ae,
    0xcc260f73, 0x024ac5ce, 0x87935313, 0xdf95206e, 0x5a4cb6b3,
    0x94207c0e, 0x11f9ead3, 0x242c9af4, 0xa1f50c29, 0x6f99c694,
    0xea405049, 0xb2462334, 0x379fb5e9, 0xf9f37f54, 0x7c2ae989,
    0x93599e1a, 0x168008c7, 0xd8ecc27a, 0x5d3554a7, 0x053327da,
    0x80eab107, 0x4e867bba, 0xcb5fed67, 0xfe8a9d40, 0x7b530b9d,
    0xb53fc120, 0x30e657fd, 0x68e02480, 0xed39b25d, 0x235578e0,
    0xa68cee3d},
   {0x00000000, 0x76e10f9d, 0xadc46ee1, 0xdb25617c, 0x1b8fac19,
    0x6d6ea384, 0xb64bc2f8, 0xc0aacd65, 0x361e5933, 0x40ff56ae,
    0x9bda37d2, 0xed3b384f, 0x2d91f52a, 0x5b70fab7, 0x80559bcb,
    0xf6b49456, 0x6c3cb266, 0x1addbdfb, 0xc1f8dc87, 0xb719d31a,
    0x77b31e7f, 0x015211e2, 0xda77709e, 0xac967f03, 0x5a22eb55,
    0x2cc3e4c8, 0xf7e685b4, 0x81078a29, 0x41ad474c, 0x374c48d1,
    0xec6929ad, 0x9a882630, 0xd87864cd, 0xae996b50, 0x75bc0a2c,
    0x035d05b1, 0xc3f7c8d4, 0xb516c749, 0x6e33a635, 0x18d2a9a8,
    0xee663dfe, 0x98873263, 0x43a2531f, 0x35435c82, 0xf5e991e7,
    0x83089e7a, 0x582dff06, 0x2eccf09b, 0xb444d6ab, 0xc2a5d936,
    0x1980b84a, 0x6f61b7d7, 0xafcb7ab2, 0xd92a752f, 0x020f1453,
    0x74ee1bce, 0x825a8f98, 0xf4bb8005, 0x2f9ee179, 0x597feee4,
    0x99d52381, 0xef342c1c, 0x34114d60, 0x42f042fd, 0xf1f7b941,
    0x8716b6dc, 0x5c33d7a0, 0x2ad2d83d, 0xea781558, 0x9c991ac5,
    0x47bc7bb9, 0x315d7424, 0xc7e9e072, 0xb108efef, 0x6a2d8e93,
    0x1ccc810e, 0xdc664c6b, 0xaa8743f6, 0x71a2228a, 0x07432d17,
    0x9dcb0b27, 0xeb2a04ba, 0x300f65c6, 0x46ee6a5b, 0x8644a73e,
    0xf0a5a8a3, 0x2b80c9df, 0x5d61c642, 0xabd55214, 0xdd345d89,
    0x06113cf5, 0x70f03368, 0xb05afe0d, 0xc6bbf190, 0x1d9e90ec,
    0x6b7f9f71, 0x298fdd8c, 0x5f6ed211, 0x844bb36d, 0xf2aabcf0,
    0x32007195, 0x44e17e08, 0x9fc41f74, 0xe92510e9, 0x1f9184bf,
    0x69708b22, 0xb255ea5e, 0xc4b4e5c3, 0x041e28a6, 0x72ff273b,
    0xa9da4647, 0xdf3b49da, 0x45b36fea, 0x33526077, 0xe877010b,
    0x9e960e96, 0x5e3cc3f3, 0x28ddcc6e, 0xf3f8ad12, 0x8519a28f,
    0x73ad36d9, 0x054c3944, 0xde695838, 0xa88857a5, 0x68229ac0,
    0x1ec3955d, 0xc5e6f421, 0xb307fbbc, 0xe2ef7383, 0x940e7c1e,
    0x4f2b1d62, 0x39ca12ff, 0xf960df9a, 0x8f81d007, 0x54a4b17b,
    0x2245bee6, 0xd4f12ab0, 0xa210252d, 0x79354451, 0x0fd44bcc,
    0xcf7e86a9, 0xb99f8934, 0x62bae848, 0x145be7d5, 0x8ed3c1e5,
    0xf832ce78, 0x2317af04, 0x55f6a099, 0x955c6dfc, 0xe3bd6261,
    0x3898031d, 0x4e790c80, 0xb8cd98d6, 0xce2c974b, 0x1509f637,
    0x63e8f9aa, 0xa34234cf, 0xd5a33b52, 0x0e865a2e, 0x786755b3,
    0x3a97174e, 0x4c7618d3, 0x975379af, 0xe1b27632, 0x2118bb57,
    0x57f9b4ca, 0x8cdcd5b6, 0xfa3dda2b, 0x0c894e7d, 0x7a6841e0,
    0xa14d209c, 0xd7ac2f01, 0x1706e264, 0x61e7edf9, 0xbac28c85,
    0xcc238318, 0x56aba528, 0x204aaab5, 0xfb6fcbc9, 0x8d8ec454,
    0x4d240931, 0x3bc506ac, 0xe0e067d0, 0x9601684d, 0x60b5fc1b,
    0x1654f386, 0xcd7192fa, 0xbb909d67, 0x7b3a5002, 0x0ddb5f9f,
    0xd6fe3ee3, 0xa01f317e, 0x1318cac2, 0x65f9c55f, 0xbedca423,
    0xc83dabbe, 0x089766db, 0x7e766946, 0xa553083a, 0xd3b207a7,
    0x250693f1, 0x53e79c6c, 0x88c2fd10, 0xfe23f28d, 0x3e893fe8,
    0x48683075, 0x934d5109, 0xe5ac5e94, 0x7f2478a4, 0x09c57739,
    0xd2e01645, 0xa40119d8, 0x64abd4bd, 0x124adb20, 0xc96fba5c,
    0xbf8eb5c1, 0x493a2197, 0x3fdb2e0a, 0xe4fe4f76, 0x921f40eb,
    0x52b58d8e, 0x24548213, 0xff71e36f, 0x8990ecf2, 0xcb60ae0f,
    0xbd81a192, 0x66a4c0ee, 0x1045cf73, 0xd0ef0216, 0xa60e0d8b,
    0x7d2b6cf7, 0x0bca636a, 0xfd7ef73c, 0x8b9ff8a1, 0x50ba99dd,
    0x265b9640, 0xe6f15b25, 0x901054b8, 0x4b3535c4, 0x3dd43a59,
    0xa75c1c69, 0xd1bd13f4, 0x0a987288, 0x7c797d15, 0xbcd3b070,
    0xca32bfed, 0x1117de91, 0x67f6d10c, 0x9142455a, 0xe7a34ac7,
    0x3c862bbb, 0x4a672426, 0x8acde943, 0xfc2ce6de, 0x270987a2,
    0x51e8883f},
   {0x00000000, 0xe8dbfbb9, 0x91b186a8, 0x796a7d11, 0x63657c8a,
    0x8bbe8733, 0xf2d4fa22, 0x1a0f019b, 0x87cc89cf, 0x6f177276,
    0x167d0f67, 0xfea6f4de, 0xe4a9f545, 0x0c720efc, 0x751873ed,
    0x9dc38854, 0x4f9f6244, 0xa74499fd, 0xde2ee4ec, 0x36f51f55,
    0x2cfa1ece, 0xc421e577, 0xbd4b9866, 0x559063df, 0xc853eb8b,
    0x20881032, 0x59e26d23, 0xb139969a, 0xab369701, 0x43ed6cb8,
    0x3a8711a9, 0xd25cea10, 0x9e3ec588, 0x76e53e31, 0x0f8f4320,
    0xe754b899, 0xfd5bb902, 0x158042bb, 0x6cea3faa, 0x8431c413,
    0x19f24c47, 0xf129b7fe, 0x8843caef, 0x60983156, 0x7a9730cd,
    0x924ccb74, 0xeb26b665, 0x03fd4ddc, 0xd1a1a7cc, 0x397a5c75,
    0x40102164, 0xa8cbdadd, 0xb2c4db46, 0x5a1f20ff, 0x23755dee,
    0xcbaea657, 0x566d2e03, 0xbeb6d5ba, 0xc7dca8ab, 0x2f075312,
    0x35085289, 0xddd3a930, 0xa4b9d421, 0x4c622f98, 0x7d7bfbca,
    0x95a00073, 0xecca7d62, 0x041186db, 0x1e1e8740, 0xf6c57cf9,
    0x8faf01e8, 0x6774fa51, 0xfab77205, 0x126c89bc, 0x6b06f4ad,
    0x83dd0f14, 0x99d20e8f, 0x7109f536, 0x08638827, 0xe0b8739e,
    0x32e4998e, 0xda3f6237, 0xa3551f26, 0x4b8ee49f, 0x5181e504,
    0xb95a1ebd, 0xc03063ac, 0x28eb9815, 0xb5281041, 0x5df3ebf8,
    0x249996e9, 0xcc426d50, 0xd64d6ccb, 0x3e969772, 0x47fcea63,
    0xaf2711da, 0xe3453e42, 0x0b9ec5fb, 0x72f4b8ea, 0x9a2f4353,
    0x802042c8, 0x68fbb971, 0x1191c460, 0xf94a3fd9, 0x6489b78d,
    0x8c524c34, 0xf5383125, 0x1de3ca9c, 0x07eccb07, 0xef3730be,
    0x965d4daf, 0x7e86b616, 0xacda5c06, 0x4401a7bf, 0x3d6bdaae,
    0xd5b02117, 0xcfbf208c, 0x2764db35, 0x5e0ea624, 0xb6d55d9d,
    0x2b16d5c9, 0xc3cd2e70, 0xbaa75361, 0x527ca8d8, 0x4873a943,
    0xa0a852fa, 0xd9c22feb, 0x3119d452, 0xbbf0874e, 0x532b7cf7,
    0x2a4101e6, 0xc29afa5f, 0xd895fbc4, 0x304e007d, 0x49247d6c,
    0xa1ff86d5, 0x3c3c0e81, 0xd4e7f538, 0xad8d8829, 0x45567390,
    0x5f59720b, 0xb78289b2, 0xcee8f4a3, 0x26330f1a, 0xf46fe50a,
    0x1cb41eb3, 0x65de63a2, 0x8d05981b, 0x970a9980, 0x7fd16239,
    0x06bb1f28, 0xee60e491, 0x73a36cc5, 0x9b78977c, 0xe212ea6d,
    0x0ac911d4, 0x10c6104f, 0xf81debf6, 0x817796e7, 0x69ac6d5e,
    0x25ce42c6, 0xcd15b97f, 0xb47fc46e, 0x5ca43fd7, 0x46ab3e4c,
    0xae70c5f5, 0xd71ab8e4, 0x3fc1435d, 0xa202cb09, 0x4ad930b0,
    0x33b34da1, 0xdb68b618, 0xc167b783, 0x29bc4c3a, 0x50d6312b,
    0xb80dca92, 0x6a512082, 0x828adb3b, 0xfbe0a62a, 0x133b5d93,
    0x09345c08, 0xe1efa7b1, 0x9885daa0, 0x705e2119, 0xed9da94d,
    0x054652f4, 0x7c2c2fe5, 0x94f7d45c, 0x8ef8d5c7, 0x66232e7e,
    0x1f49536f, 0xf792a8d6, 0xc68b7c84, 0x2e50873d, 0x573afa2c,
    0xbfe10195, 0xa5ee000e, 0x4d35fbb7, 0x345f86a6, 0xdc847d1f,
    0x4147f54b, 0xa99c0ef2, 0xd0f673e3, 0x382d885a, 0x222289c1,
    0xcaf97278, 0xb3930f69, 0x5b48f4d0, 0x89141ec0, 0x61cfe579,
    0x18a59868, 0xf07e63d1, 0xea71624a, 0x02aa99f3, 0x7bc0e4e2,
    0x931b1f5b, 0x0ed8970f, 0xe6036cb6, 0x9f6911a7, 0x77b2ea1e,
    0x6dbdeb85, 0x8566103c, 0xfc0c6d2d, 0x14d79694, 0x58b5b90c,
    0xb06e42b5, 0xc9043fa4, 0x21dfc41d, 0x3bd0c586, 0xd30b3e3f,
    0xaa61432e, 0x42bab897, 0xdf7930c3, 0x37a2cb7a, 0x4ec8b66b,
    0xa6134dd2, 0xbc1c4c49, 0x54c7b7f0, 0x2dadcae1, 0xc5763158,
    0x172adb48, 0xfff120f1, 0x869b5de0, 0x6e40a659, 0x744fa7c2,
    0x9c945c7b, 0xe5fe216a, 0x0d25dad3, 0x90e65287, 0x783da93e,
    0x0157d42f, 0xe98c2f96, 0xf3832e0d, 0x1b58d5b4, 0x6232a8a5,
    0x8ae9531c},
   {0x00000000, 0x919168ae, 0x6325a087, 0xf2b4c829, 0x874c31d4,
    0x16dd597a, 0xe4699153, 0x75f8f9fd, 0x4f9f1373, 0xde0e7bdd,
    0x2cbab3f4, 0xbd2bdb5a, 0xc8d322a7, 0x59424a09, 0xabf68220,
    0x3a67ea8e, 0x9e3e27e6, 0x0faf4f48, 0xfd1b8761, 0x6c8aefcf,
    0x19721632, 0x88e37e9c, 0x7a57b6b5, 0xebc6de1b, 0xd1a13495,
    0x40305c3b, 0xb2849412, 0x2315fcbc, 0x56ed0541, 0xc77c6def,
    0x35c8a5c6, 0xa459cd68, 0x7d7b3f17, 0xecea57b9, 0x1e5e9f90,
    0x8fcff73e, 0xfa370ec3, 0x6ba6666d, 0x9912ae44, 0x0883c6ea,
    0x32e42c64, 0xa37544ca, 0x51c18ce3, 0xc050e44d, 0xb5a81db0,
    0x2439751e, 0xd68dbd37, 0x471cd599, 0xe34518f1, 0x72d4705f,
    0x8060b876, 0x11f1d0d8, 0x64092925, 0xf598418b, 0x072c89a2,
    0x96bde10c, 0xacda0b82, 0x3d4b632c, 0xcfffab05, 0x5e6ec3ab,
    0x2b963a56, 0xba0752f8, 0x48b39ad1, 0xd922f27f, 0xfaf67e2e,
    0x6b671680, 0x99d3dea9, 0x0842b607, 0x7dba4ffa, 0xec2b2754,
    0x1e9fef7d, 0x8f0e87d3, 0xb5696d5d, 0x24f805f3, 0xd64ccdda,
    0x47dda574, 0x32255c89, 0xa3b43427, 0x5100fc0e, 0xc09194a0,
    0x64c859c8, 0xf5593166, 0x07edf94f, 0x967c91e1, 0xe384681c,
    0x721500b2, 0x80a1c89b, 0x1130a035, 0x2b574abb, 0xbac62215,
    0x4872ea3c, 0xd9e38292, 0xac1b7b6f, 0x3d8a13c1, 0xcf3edbe8,
    0x5eafb346, 0x878d4139, 0x161c2997, 0xe4a8e1be, 0x75398910,
    0x00c170ed, 0x91501843, 0x63e4d06a, 0xf275b8c4, 0xc812524a,
    0x59833ae4, 0xab37f2cd, 0x3aa69a63, 0x4f5e639e, 0xdecf0b30,
    0x2c7bc319, 0xbdeaabb7, 0x19b366df, 0x88220e71, 0x7a96c658,
    0xeb07aef6, 0x9eff570b, 0x0f6e3fa5, 0xfddaf78c, 0x6c4b9f22,
    0x562c75ac, 0xc7bd1d02, 0x3509d52b, 0xa498bd85, 0xd1604478,
    0x40f12cd6, 0xb245e4ff, 0x23d48c51, 0xf4edfd5c, 0x657c95f2,
    0x97c85ddb, 0x06593575, 0x73a1cc88, 0xe230a426, 0x10846c0f,
    0x811504a1, 0xbb72ee2f, 0x2ae38681, 0xd8574ea8, 0x49c62606,
    0x3c3edffb, 0xadafb755, 0x5f1b7f7c, 0xce8a17d2, 0x6ad3daba,
    0xfb42b214, 0x09f67a3d, 0x98671293, 0xed9feb6e, 0x7c0e83c0,
    0x8eba4be9, 0x1f2b2347, 0x254cc9c9, 0xb4dda167, 0x4669694e,
    0xd7f801e0, 0xa200f81d, 0x339190b3, 0xc125589a, 0x50b43034,
    0x8996c24b, 0x1807aae5, 0xeab362cc, 0x7b220a62, 0x0edaf39f,
    0x9f4b9b31, 0x6dff5318, 0xfc6e3bb6, 0xc609d138, 0x5798b996,
    0xa52c71bf, 0x34bd1911, 0x4145e0ec, 0xd0d48842, 0x2260406b,
    0xb3f128c5, 0x17a8e5ad, 0x86398d03, 0x748d452a, 0xe51c2d84,
    0x90e4d479, 0x0175bcd7, 0xf3c174fe, 0x62501c50, 0x5837f6de,
    0xc9a69e70, 0x3b125659, 0xaa833ef7, 0xdf7bc70a, 0x4eeaafa4,
    0xbc5e678d, 0x2dcf0f23, 0x0e1b8372, 0x9f8aebdc, 0x6d3e23f5,
    0xfcaf4b5b, 0x8957b2a6, 0x18c6da08, 0xea721221, 0x7be37a8f,
    0x41849001, 0xd015f8af, 0x22a13086, 0xb3305828, 0xc6c8a1d5,
    0x5759c97b, 0xa5ed0152, 0x347c69fc, 0x9025a494, 0x01b4cc3a,
    0xf3000413, 0x62916cbd, 0x17699540, 0x86f8fdee, 0x744c35c7,
    0xe5dd5d69, 0xdfbab7e7, 0x4e2bdf49, 0xbc9f1760, 0x2d0e7fce,
    0x58f68633, 0xc967ee9d, 0x3bd326b4, 0xaa424e1a, 0x7360bc65,
    0xe2f1d4cb, 0x10451ce2, 0x81d4744c, 0xf42c8db1, 0x65bde51f,
    0x97092d36, 0x06984598, 0x3cffaf16, 0xad6ec7b8, 0x5fda0f91,
    0xce4b673f, 0xbbb39ec2, 0x2a22f66c, 0xd8963e45, 0x490756eb,
    0xed5e9b83, 0x7ccff32d, 0x8e7b3b04, 0x1fea53aa, 0x6a12aa57,
    0xfb83c2f9, 0x09370ad0, 0x98a6627e, 0xa2c188f0, 0x3350e05e,
    0xc1e42877, 0x507540d9, 0x258db924, 0xb41cd18a, 0x46a819a3,
    0xd739710d}};

#endif

#endif

#if N == 5

#if W == 8

local const z_crc_t FAR crc_braid_table[][256] = {
   {0x00000000, 0xaf449247, 0x85f822cf, 0x2abcb088, 0xd08143df,
    0x7fc5d198, 0x55796110, 0xfa3df357, 0x7a7381ff, 0xd53713b8,
    0xff8ba330, 0x50cf3177, 0xaaf2c220, 0x05b65067, 0x2f0ae0ef,
    0x804e72a8, 0xf4e703fe, 0x5ba391b9, 0x711f2131, 0xde5bb376,
    0x24664021, 0x8b22d266, 0xa19e62ee, 0x0edaf0a9, 0x8e948201,
    0x21d01046, 0x0b6ca0ce, 0xa4283289, 0x5e15c1de, 0xf1515399,
    0xdbede311, 0x74a97156, 0x32bf01bd, 0x9dfb93fa, 0xb7472372,
    0x1803b135, 0xe23e4262, 0x4d7ad025, 0x67c660ad, 0xc882f2ea,
    0x48cc8042, 0xe7881205, 0xcd34a28d, 0x627030ca, 0x984dc39d,
    0x370951da, 0x1db5e152, 0xb2f17315, 0xc6580243, 0x691c9004,
    0x43a0208c, 0xece4b2cb, 0x16d9419c, 0xb99dd3db, 0x93216353,
    0x3c65f114, 0xbc2b83bc, 0x136f11fb, 0x39d3a173, 0x96973334,
    0x6caac063, 0xc3ee5224, 0xe952e2ac, 0x461670eb, 0x657e037a,
    0xca3a913d, 0xe08621b5, 0x4fc2b3f2, 0xb5ff40a5, 0x1abbd2e2,
    0x3007626a, 0x9f43f02d, 0x1f0d8285, 0xb04910c2, 0x9af5a04a,
    0x35b1320d, 0xcf8cc15a, 0x60c8531d, 0x4a74e395, 0xe53071d2,
    0x91990084, 0x3edd92c3, 0x1461224b, 0xbb25b00c, 0x4118435b,
    0xee5cd11c, 0xc4e06194, 0x6ba4f3d3, 0xebea817b, 0x44ae133c,
    0x6e12a3b4, 0xc15631f3, 0x3b6bc2a4, 0x942f50e3, 0xbe93e06b,
    0x11d7722c, 0x57c102c7, 0xf8859080, 0xd2392008, 0x7d7db24f,
    0x87404118, 0x2804d35f, 0x02b863d7, 0xadfcf190, 0x2db28338,
    0x82f6117f, 0xa84aa1f7, 0x070e33b0, 0xfd33c0e7, 0x527752a0,
    0x78cbe228, 0xd78f706f, 0xa3260139, 0x0c62937e, 0x26de23f6,
    0x899ab1b1, 0x73a742e6, 0xdce3d0a1, 0xf65f6029, 0x591bf26e,
    0xd95580c6, 0x76111281, 0x5cada209, 0xf3e9304e, 0x09d4c319,
    0xa690515e, 0x8c2ce1d6, 0x23687391, 0xcafc06f4, 0x65b894b3,
    0x4f04243b, 0xe040b67c, 0x1a7d452b, 0xb539d76c, 0x9f8567e4,
    0x30c1f5a3, 0xb08f870b, 0x1fcb154c, 0x3577a5c4, 0x9a333783,
    0x600ec4d4, 0xcf4a5693, 0xe5f6e61b, 0x4ab2745c, 0x3e1b050a,
    0x915f974d, 0xbbe327c5, 0x14a7b582, 0xee9a46d5, 0x41ded492,
    0x6b62641a, 0xc426f65d, 0x446884f5, 0xeb2c16b2, 0xc190a63a,
    0x6ed4347d, 0x94e9c72a, 0x3bad556d, 0x1111e5e5, 0xbe5577a2,
    0xf8430749, 0x5707950e, 0x7dbb2586, 0xd2ffb7c1, 0x28c24496,
    0x8786d6d1, 0xad3a6659, 0x027ef41e, 0x823086b6, 0x2d7414f1,
    0x07c8a479, 0xa88c363e, 0x52b1c569, 0xfdf5572e, 0xd749e7a6,
    0x780d75e1, 0x0ca404b7, 0xa3e096f0, 0x895c2678, 0x2618b43f,
    0xdc254768, 0x7361d52f, 0x59dd65a7, 0xf699f7e0, 0x76d78548,
    0xd993170f, 0xf32fa787, 0x5c6b35c0, 0xa656c697, 0x091254d0,
    0x23aee458, 0x8cea761f, 0xaf82058e, 0x00c697c9, 0x2a7a2741,
    0x853eb506, 0x7f034651, 0xd047d416, 0xfafb649e, 0x55bff6d9,
    0xd5f18471, 0x7ab51636, 0x5009a6be, 0xff4d34f9, 0x0570c7ae,
    0xaa3455e9, 0x8088e561, 0x2fcc7726, 0x5b650670, 0xf4219437,
    0xde9d24bf, 0x71d9b6f8, 0x8be445af, 0x24a0d7e8, 0x0e1c6760,
    0xa158f527, 0x2116878f, 0x8e5215c8, 0xa4eea540, 0x0baa3707,
    0xf197c450, 0x5ed35617, 0x746fe69f, 0xdb2b74d8, 0x9d3d0433,
    0x32799674, 0x18c526fc, 0xb781b4bb, 0x4dbc47ec, 0xe2f8d5ab,
    0xc8446523, 0x6700f764, 0xe74e85cc, 0x480a178b, 0x62b6a703,
    0xcdf23544, 0x37cfc613, 0x988b5454, 0xb237e4dc, 0x1d73769b,
    0x69da07cd, 0xc69e958a, 0xec222502, 0x4366b745, 0xb95b4412,
    0x161fd655, 0x3ca366dd, 0x93e7f49a, 0x13a98632, 0xbced1475,
    0x9651a4fd, 0x391536ba, 0xc328c5ed, 0x6c6c57aa, 0x46d0e722,
    0xe9947565},
   {0x00000000, 0x4e890ba9, 0x9d121752, 0xd39b1cfb, 0xe15528e5,
    0xafdc234c, 0x7c473fb7, 0x32ce341e, 0x19db578b, 0x57525c22,
    0x84c940d9, 0xca404b70, 0xf88e7f6e, 0xb60774c7, 0x659c683c,
    0x2b156395, 0x33b6af16, 0x7d3fa4bf, 0xaea4b844, 0xe02db3ed,
    0xd2e387f3, 0x9c6a8c5a, 0x4ff190a1, 0x01789b08, 0x2a6df89d,
    0x64e4f334, 0xb77fefcf, 0xf9f6e466, 0xcb38d078, 0x85b1dbd1,
    0x562ac72a, 0x18a3cc83, 0x676d5e2c, 0x29e45585, 0xfa7f497e,
    0xb4f642d7, 0x863876c9, 0xc8b17d60, 0x1b2a619b, 0x55a36a32,
    0x7eb609a7, 0x303f020e, 0xe3a41ef5, 0xad2d155c, 0x9fe32142,
    0xd16a2aeb, 0x02f13610, 0x4c783db9, 0x54dbf13a, 0x1a52fa93,
    0xc9c9e668, 0x8740edc1, 0xb58ed9df, 0xfb07d276, 0x289cce8d,
    0x6615c524, 0x4d00a6b1, 0x0389ad18, 0xd012b1e3, 0x9e9bba4a,
    0xac558e54, 0xe2dc85fd, 0x31479906, 0x7fce92af, 0xcedabc58,
    0x8053b7f1, 0x53c8ab0a, 0x1d41a0a3, 0x2f8f94bd, 0x61069f14,
    0xb29d83ef, 0xfc148846, 0xd701ebd3, 0x9988e07a, 0x4a13fc81,
    0x049af728, 0x3654c336, 0x78ddc89f, 0xab46d464, 0xe5cfdfcd,
    0xfd6c134e, 0xb3e518e7, 0x607e041c, 0x2ef70fb5, 0x1c393bab,
    0x52b03002, 0x812b2cf9, 0xcfa22750, 0xe4b744c5, 0xaa3e4f6c,
    0x79a55397, 0x372c583e, 0x05e26c20, 0x4b6b6789, 0x98f07b72,
    0xd67970db, 0xa9b7e274, 0xe73ee9dd, 0x34a5f526, 0x7a2cfe8f,
    0x48e2ca91, 0x066bc138, 0xd5f0ddc3, 0x9b79d66a, 0xb06cb5ff,
    0xfee5be56, 0x2d7ea2ad, 0x63f7a904, 0x51399d1a, 0x1fb096b3,
    0xcc2b8a48, 0x82a281e1, 0x9a014d62, 0xd48846cb, 0x07135a30,
    0x499a5199, 0x7b546587, 0x35dd6e2e, 0xe64672d5, 0xa8cf797c,
    0x83da1ae9, 0xcd531140, 0x1ec80dbb, 0x50410612, 0x628f320c,
    0x2c0639a5, 0xff9d255e, 0xb1142ef7, 0x46c47ef1, 0x084d7558,
    0xdbd669a3, 0x955f620a, 0xa7915614, 0xe9185dbd, 0x3a834146,
    0x740a4aef, 0x5f1f297a, 0x119622d3, 0xc20d3e28, 0x8c843581,
    0xbe4a019f, 0xf0c30a36, 0x235816cd, 0x6dd11d64, 0x7572d1e7,
    0x3bfbda4e, 0xe860c6b5, 0xa6e9cd1c, 0x9427f902, 0xdaaef2ab,
    0x0935ee50, 0x47bce5f9, 0x6ca9866c, 0x22208dc5, 0xf1bb913e,
    0xbf329a97, 0x8dfcae89, 0xc375a520, 0x10eeb9db, 0x5e67b272,
    0x21a920dd, 0x6f202b74, 0xbcbb378f, 0xf2323c26, 0xc0fc0838,
    0x8e750391, 0x5dee1f6a, 0x136714c3, 0x38727756, 0x76fb7cff,
    0xa5606004, 0xebe96bad, 0xd9275fb3, 0x97ae541a, 0x443548e1,
    0x0abc4348, 0x121f8fcb, 0x5c968462, 0x8f0d9899, 0xc1849330,
    0xf34aa72e, 0xbdc3ac87, 0x6e58b07c, 0x20d1bbd5, 0x0bc4d840,
    0x454dd3e9, 0x96d6cf12, 0xd85fc4bb, 0xea91f0a5, 0xa418fb0c,
    0x7783e7f7, 0x390aec5e, 0x881ec2a9, 0xc697c900, 0x150cd5fb,
    0x5b85de52, 0x694bea4c, 0x27c2e1e5, 0xf459fd1e, 0xbad0f6b7,
    0x91c59522, 0xdf4c9e8b, 0x0cd78270, 0x425e89d9, 0x7090bdc7,
    0x3e19b66e, 0xed82aa95, 0xa30ba13c, 0xbba86dbf, 0xf5216616,
    0x26ba7aed, 0x68337144, 0x5afd455a, 0x14744ef3, 0xc7ef5208,
    0x896659a1, 0xa2733a34, 0xecfa319d, 0x3f612d66, 0x71e826cf,
    0x432612d1, 0x0daf1978, 0xde340583, 0x90bd0e2a, 0xef739c85,
    0xa1fa972c, 0x72618bd7, 0x3ce8807e, 0x0e26b460, 0x40afbfc9,
    0x9334a332, 0xddbda89b, 0xf6a8cb0e, 0xb821c0a7, 0x6bbadc5c,
    0x2533d7f5, 0x17fde3eb, 0x5974e842, 0x8aeff4b9, 0xc466ff10,
    0xdcc53393, 0x924c383a, 0x41d724c1, 0x0f5e2f68, 0x3d901b76,
    0x731910df, 0xa0820c24, 0xee0b078d, 0xc51e6418, 0x8b976fb1,
    0x580c734a, 0x168578e3, 0x244b4cfd, 0x6ac24754, 0xb9595baf,
    0xf7d05006},
   {0x00000000, 0x8d88fde2, 0xc060fd85, 0x4de80067, 0x5bb0fd4b,
    0xd63800a9, 0x9bd000ce, 0x1658fd2c, 0xb761fa96, 0x3ae90774,
    0x77010713, 0xfa89faf1, 0xecd107dd, 0x6159fa3f, 0x2cb1fa58,
    0xa13907ba, 0xb5b2f36d, 0x383a0e8f, 0x75d20ee8, 0xf85af30a,
    0xee020e26, 0x638af3c4, 0x2e62f3a3, 0xa3ea0e41, 0x02d309fb,
    0x8f5bf419, 0xc2b3f47e, 0x4f3b099c, 0x5963f4b0, 0xd4eb0952,
    0x99030935, 0x148bf4d7, 0xb014e09b, 0x3d9c1d79, 0x70741d1e,
    0xfdfce0fc, 0xeba41dd0, 0x662ce032, 0x2bc4e055, 0xa64c1db7,
    0x07751a0d, 0x8afde7ef, 0xc715e788, 0x4a9d1a6a, 0x5cc5e746,
    0xd14d1aa4, 0x9ca51ac3, 0x112de721, 0x05a613f6, 0x882eee14,
    0xc5c6ee73, 0x484e1391, 0x5e16eebd, 0xd39e135f, 0x9e761338,
    0x13feeeda, 0xb2c7e960, 0x3f4f1482, 0x72a714e5, 0xff2fe907,
    0xe977142b, 0x64ffe9c9, 0x2917e9ae, 0xa49f144c, 0xbb58c777,
    0x36d03a95, 0x7b383af2, 0xf6b0c710, 0xe0e83a3c, 0x6d60c7de,
    0x2088c7b9, 0xad003a5b, 0x0c393de1, 0x81b1c003, 0xcc59c064,
    0x41d13d86, 0x5789c0aa, 0xda013d48, 0x97e93d2f, 0x1a61c0cd,
    0x0eea341a, 0x8362c9f8, 0xce8ac99f, 0x4302347d, 0x555ac951,
    0xd8d234b3, 0x953a34d4, 0x18b2c936, 0xb98bce8c, 0x3403336e,
    0x79eb3309, 0xf463ceeb, 0xe23b33c7, 0x6fb3ce25, 0x225bce42,
    0xafd333a0, 0x0b4c27ec, 0x86c4da0e, 0xcb2cda69, 0x46a4278b,
    0x50fcdaa7, 0xdd742745, 0x909c2722, 0x1d14dac0, 0xbc2ddd7a,
    0x31a52098, 0x7c4d20ff, 0xf1c5dd1d, 0xe79d2031, 0x6a15ddd3,
    0x27fdddb4, 0xaa752056, 0xbefed481, 0x33762963, 0x7e9e2904,
    0xf316d4e6, 0xe54e29ca, 0x68c6d428, 0x252ed44f, 0xa8a629ad,
    0x099f2e17, 0x8417d3f5, 0xc9ffd392, 0x44772e70, 0x522fd35c,
    0xdfa72ebe, 0x924f2ed9, 0x1fc7d33b, 0xadc088af, 0x2048754d,
    0x6da0752a, 0xe02888c8, 0xf67075e4, 0x7bf88806, 0x36108861,
    0xbb987583, 0x1aa17239, 0x97298fdb, 0xdac18fbc, 0x5749725e,
    0x41118f72, 0xcc997290, 0x817172f7, 0x0cf98f15, 0x18727bc2,
    0x95fa8620, 0xd8128647, 0x559a7ba5, 0x43c28689, 0xce4a7b6b,
    0x83a27b0c, 0x0e2a86ee, 0xaf138154, 0x229b7cb6, 0x6f737cd1,
    0xe2fb8133, 0xf4a37c1f, 0x792b81fd, 0x34c3819a, 0xb94b7c78,
    0x1dd46834, 0x905c95d6, 0xddb495b1, 0x503c6853, 0x4664957f,
    0xcbec689d, 0x860468fa, 0x0b8c9518, 0xaab592a2, 0x273d6f40,
    0x6ad56f27, 0xe75d92c5, 0xf1056fe9, 0x7c8d920b, 0x3165926c,
    0xbced6f8e, 0xa8669b59, 0x25ee66bb, 0x680666dc, 0xe58e9b3e,
    0xf3d66612, 0x7e5e9bf0, 0x33b69b97, 0xbe3e6675, 0x1f0761cf,
    0x928f9c2d, 0xdf679c4a, 0x52ef61a8, 0x44b79c84, 0xc93f6166,
    0x84d76101, 0x095f9ce3, 0x16984fd8, 0x9b10b23a, 0xd6f8b25d,
    0x5b704fbf, 0x4d28b293, 0xc0a04f71, 0x8d484f16, 0x00c0b2f4,
    0xa1f9b54e, 0x2c7148ac, 0x619948cb, 0xec11b529, 0xfa494805,
    0x77c1b5e7, 0x3a29b580, 0xb7a14862, 0xa32abcb5, 0x2ea24157,
    0x634a4130, 0xeec2bcd2, 0xf89a41fe, 0x7512bc1c, 0x38fabc7b,
    0xb5724199, 0x144b4623, 0x99c3bbc1, 0xd42bbba6, 0x59a34644,
    0x4ffbbb68, 0xc273468a, 0x8f9b46ed, 0x0213bb0f, 0xa68caf43,
    0x2b0452a1, 0x66ec52c6, 0xeb64af24, 0xfd3c5208, 0x70b4afea,
    0x3d5caf8d, 0xb0d4526f, 0x11ed55d5, 0x9c65a837, 0xd18da850,
    0x5c0555b2, 0x4a5da89e, 0xc7d5557c, 0x8a3d551b, 0x07b5a8f9,
    0x133e5c2e, 0x9eb6a1cc, 0xd35ea1ab, 0x5ed65c49, 0x488ea165,
    0xc5065c87, 0x88ee5ce0, 0x0566a102, 0xa45fa6b8, 0x29d75b5a,
    0x643f5b3d, 0xe9b7a6df, 0xffef5bf3, 0x7267a611, 0x3f8fa676,
    0xb2075b94},
   {0x00000000, 0x80f0171f, 0xda91287f, 0x5a613f60, 0x6e5356bf,
    0xeea341a0, 0xb4c27ec0, 0x343269df, 0xdca6ad7e, 0x5c56ba61,
    0x06378501, 0x86c7921e, 0xb2f5fbc1, 0x3205ecde, 0x6864d3be,
    0xe894c4a1, 0x623c5cbd, 0xe2cc4ba2, 0xb8ad74c2, 0x385d63dd,
    0x0c6f0a02, 0x8c9f1d1d, 0xd6fe227d, 0x560e3562, 0xbe9af1c3,
    0x3e6ae6dc, 0x640bd9bc, 0xe4fbcea3, 0xd0c9a77c, 0x5039b063,
    0x0a588f03, 0x8aa8981c, 0xc478b97a, 0x4488ae65, 0x1ee99105,
    0x9e19861a, 0xaa2befc5, 0x2adbf8da, 0x70bac7ba, 0xf04ad0a5,
    0x18de1404, 0x982e031b, 0xc24f3c7b, 0x42bf2b64, 0x768d42bb,
    0xf67d55a4, 0xac1c6ac4, 0x2cec7ddb, 0xa644e5c7, 0x26b4f2d8,
    0x7cd5cdb8, 0xfc25daa7, 0xc817b378, 0x48e7a467, 0x12869b07,
    0x92768c18, 0x7ae248b9, 0xfa125fa6, 0xa07360c6, 0x208377d9,
    0x14b11e06, 0x94410919, 0xce203679, 0x4ed02166, 0x538074b5,
    0xd37063aa, 0x89115cca, 0x09e14bd5, 0x3dd3220a, 0xbd233515,
    0xe7420a75, 0x67b21d6a, 0x8f26d9cb, 0x0fd6ced4, 0x55b7f1b4,
    0xd547e6ab, 0xe1758f74, 0x6185986b, 0x3be4a70b, 0xbb14b014,
    0x31bc2808, 0xb14c3f17, 0xeb2d0077, 0x6bdd1768, 0x5fef7eb7,
    0xdf1f69a8, 0x857e56c8, 0x058e41d7, 0xed1a8576, 0x6dea9269,
    0x378bad09, 0xb77bba16, 0x8349d3c9, 0x03b9c4d6, 0x59d8fbb6,
    0xd928eca9, 0x97f8cdcf, 0x1708dad0, 0x4d69e5b0, 0xcd99f2af,
    0xf9ab9b70, 0x795b8c6f, 0x233ab30f, 0xa3caa410, 0x4b5e60b1,
    0xcbae77ae, 0x91cf48ce, 0x113f5fd1, 0x250d360e, 0xa5fd2111,
    0xff9c1e71, 0x7f6c096e, 0xf5c49172, 0x7534866d, 0x2f55b90d,
    0xafa5ae12, 0x9b97c7cd, 0x1b67d0d2, 0x4106efb2, 0xc1f6f8ad,
    0x29623c0c, 0xa9922b13, 0xf3f31473, 0x7303036c, 0x47316ab3,
    0xc7c17dac, 0x9da042cc, 0x1d5055d3, 0xa700e96a, 0x27f0fe75,
    0x7d91c115, 0xfd61d60a, 0xc953bfd5, 0x49a3a8ca, 0x13c297aa,
    0x933280b5, 0x7ba64414, 0xfb56530b, 0xa1376c6b, 0x21c77b74,
    0x15f512ab, 0x950505b4, 0xcf643ad4, 0x4f942dcb, 0xc53cb5d7,
    0x45cca2c8, 0x1fad9da8, 0x9f5d8ab7, 0xab6fe368, 0x2b9ff477,
    0x71fecb17, 0xf10edc08, 0x199a18a9, 0x996a0fb6, 0xc30b30d6,
    0x43fb27c9, 0x77c94e16, 0xf7395909, 0xad586669, 0x2da87176,
    0x63785010, 0xe388470f, 0xb9e9786f, 0x39196f70, 0x0d2b06af,
    0x8ddb11b0, 0xd7ba2ed0, 0x574a39cf, 0xbfdefd6e, 0x3f2eea71,
    0x654fd511, 0xe5bfc20e, 0xd18dabd1, 0x517dbcce, 0x0b1c83ae,
    0x8bec94b1, 0x01440cad, 0x81b41bb2, 0xdbd524d2, 0x5b2533cd,
    0x6f175a12, 0xefe74d0d, 0xb586726d, 0x35766572, 0xdde2a1d3,
    0x5d12b6cc, 0x077389ac, 0x87839eb3, 0xb3b1f76c, 0x3341e073,
    0x6920df13, 0xe9d0c80c, 0xf4809ddf, 0x74708ac0, 0x2e11b5a0,
    0xaee1a2bf, 0x9ad3cb60, 0x1a23dc7f, 0x4042e31f, 0xc0b2f400,
    0x282630a1, 0xa8d627be, 0xf2b718de, 0x72470fc1, 0x4675661e,
    0xc6857101, 0x9ce44e61, 0x1c14597e, 0x96bcc162, 0x164cd67d,
    0x4c2de91d, 0xccddfe02, 0xf8ef97dd, 0x781f80c2, 0x227ebfa2,
    0xa28ea8bd, 0x4a1a6c1c, 0xcaea7b03, 0x908b4463, 0x107b537c,
    0x24493aa3, 0xa4b92dbc, 0xfed812dc, 0x7e2805c3, 0x30f824a5,
    0xb00833ba, 0xea690cda, 0x6a991bc5, 0x5eab721a, 0xde5b6505,
    0x843a5a65, 0x04ca4d7a, 0xec5e89db, 0x6cae9ec4, 0x36cfa1a4,
    0xb63fb6bb, 0x820ddf64, 0x02fdc87b, 0x589cf71b, 0xd86ce004,
    0x52c47818, 0xd2346f07, 0x88555067, 0x08a54778, 0x3c972ea7,
    0xbc6739b8, 0xe60606d8, 0x66f611c7, 0x8e62d566, 0x0e92c279,
    0x54f3fd19, 0xd403ea06, 0xe03183d9, 0x60c194c6, 0x3aa0aba6,
    0xba50bcb9},
   {0x00000000, 0x9570d495, 0xf190af6b, 0x64e07bfe, 0x38505897,
    0xad208c02, 0xc9c0f7fc, 0x5cb02369, 0x70a0b12e, 0xe5d065bb,
    0x81301e45, 0x1440cad0, 0x48f0e9b9, 0xdd803d2c, 0xb96046d2,
    0x2c109247, 0xe141625c, 0x7431b6c9, 0x10d1cd37, 0x85a119a2,
    0xd9113acb, 0x4c61ee5e, 0x288195a0, 0xbdf14135, 0x91e1d372,
    0x049107e7, 0x60717c19, 0xf501a88c, 0xa9b18be5, 0x3cc15f70,
    0x5821248e, 0xcd51f01b, 0x19f3c2f9, 0x8c83166c, 0xe8636d92,
    0x7d13b907, 0x21a39a6e, 0xb4d34efb, 0xd0333505, 0x4543e190,
    0x695373d7, 0xfc23a742, 0x98c3dcbc, 0x0db30829, 0x51032b40,
    0xc473ffd5, 0xa093842b, 0x35e350be, 0xf8b2a0a5, 0x6dc27430,
    0x09220fce, 0x9c52db5b, 0xc0e2f832, 0x55922ca7, 0x31725759,
    0xa40283cc, 0x8812118b, 0x1d62c51e, 0x7982bee0, 0xecf26a75,
    0xb042491c, 0x25329d89, 0x41d2e677, 0xd4a232e2, 0x33e785f2,
    0xa6975167, 0xc2772a99, 0x5707fe0c, 0x0bb7dd65, 0x9ec709f0,
    0xfa27720e, 0x6f57a69b, 0x434734dc, 0xd637e049, 0xb2d79bb7,
    0x27a74f22, 0x7b176c4b, 0xee67b8de, 0x8a87c320, 0x1ff717b5,
    0xd2a6e7ae, 0x47d6333b, 0x233648c5, 0xb6469c50, 0xeaf6bf39,
    0x7f866bac, 0x1b661052, 0x8e16c4c7, 0xa2065680, 0x37768215,
    0x5396f9eb, 0xc6e62d7e, 0x9a560e17, 0x0f26da82, 0x6bc6a17c,
    0xfeb675e9, 0x2a14470b, 0xbf64939e, 0xdb84e860, 0x4ef43cf5,
    0x12441f9c, 0x8734cb09, 0xe3d4b0f7, 0x76a46462, 0x5ab4f625,
    0xcfc422b0, 0xab24594e, 0x3e548ddb, 0x62e4aeb2, 0xf7947a27,
    0x937401d9, 0x0604d54c, 0xcb552557, 0x5e25f1c2, 0x3ac58a3c,
    0xafb55ea9, 0xf3057dc0, 0x6675a955, 0x0295d2ab, 0x97e5063e,
    0xbbf59479, 0x2e8540ec, 0x4a653b12, 0xdf15ef87, 0x83a5ccee,
    0x16d5187b, 0x72356385, 0xe745b710, 0x67cf0be4, 0xf2bfdf71,
    0x965fa48f, 0x032f701a, 0x5f9f5373, 0xcaef87e6, 0xae0ffc18,
    0x3b7f288d, 0x176fbaca, 0x821f6e5f, 0xe6ff15a1, 0x738fc134,
    0x2f3fe25d, 0xba4f36c8, 0xdeaf4d36, 0x4bdf99a3, 0x868e69b8,
    0x13febd2d, 0x771ec6d3, 0xe26e1246, 0xbede312f, 0x2baee5ba,
    0x4f4e9e44, 0xda3e4ad1, 0xf62ed896, 0x635e0c03, 0x07be77fd,
    0x92cea368, 0xce7e8001, 0x5b0e5494, 0x3fee2f6a, 0xaa9efbff,
    0x7e3cc91d, 0xeb4c1d88, 0x8fac6676, 0x1adcb2e3, 0x466c918a,
    0xd31c451f, 0xb7fc3ee1, 0x228cea74, 0x0e9c7833, 0x9becaca6,
    0xff0cd758, 0x6a7c03cd, 0x36cc20a4, 0xa3bcf431, 0xc75c8fcf,
    0x522c5b5a, 0x9f7dab41, 0x0a0d7fd4, 0x6eed042a, 0xfb9dd0bf,
    0xa72df3d6, 0x325d2743, 0x56bd5cbd, 0xc3cd8828, 0xefdd1a6f,
    0x7aadcefa, 0x1e4db504, 0x8b3d6191, 0xd78d42f8, 0x42fd966d,
    0x261ded93, 0xb36d3906, 0x54288e16, 0xc1585a83, 0xa5b8217d,
    0x30c8f5e8, 0x6c78d681, 0xf9080214, 0x9de879ea, 0x0898ad7f,
    0x24883f38, 0xb1f8ebad, 0xd5189053, 0x406844c6, 0x1cd867af,
    0x89a8b33a, 0xed48c8c4, 0x78381c51, 0xb569ec4a, 0x201938df,
    0x44f94321, 0xd18997b4, 0x8d39b4dd, 0x18496048, 0x7ca91bb6,
    0xe9d9cf23, 0xc5c95d64, 0x50b989f1, 0x3459f20f, 0xa129269a,
    0xfd9905f3, 0x68e9d166, 0x0c09aa98, 0x99797e0d, 0x4ddb4cef,
    0xd8ab987a, 0xbc4be384, 0x293b3711, 0x758b1478, 0xe0fbc0ed,
    0x841bbb13, 0x116b6f86, 0x3d7bfdc1, 0xa80b2954, 0xcceb52aa,
    0x599b863f, 0x052ba556, 0x905b71c3, 0xf4bb0a3d, 0x61cbdea8,
    0xac9a2eb3, 0x39eafa26, 0x5d0a81d8, 0xc87a554d, 0x94ca7624,
    0x01baa2b1, 0x655ad94f, 0xf02a0dda, 0xdc3a9f9d, 0x494a4b08,
    0x2daa30f6, 0xb8dae463, 0xe46ac70a, 0x711a139f, 0x15fa6861,
    0x808abcf4},
   {0x00000000, 0xcf9e17c8, 0x444d29d1, 0x8bd33e19, 0x889a53a2,
    0x4704446a, 0xccd77a73, 0x03496dbb, 0xca45a105, 0x05dbb6cd,
    0x8e0888d4, 0x41969f1c, 0x42dff2a7, 0x8d41e56f, 0x0692db76,
    0xc90cccbe, 0x4ffa444b, 0x80645383, 0x0bb76d9a, 0xc4297a52,
    0xc76017e9, 0x08fe0021, 0x832d3e38, 0x4cb329f0, 0x85bfe54e,
    0x4a21f286, 0xc1f2cc9f, 0x0e6cdb57, 0x0d25b6ec, 0xc2bba124,
    0x49689f3d, 0x86f688f5, 0x9ff48896, 0x506a9f5e, 0xdbb9a147,
    0x1427b68f, 0x176edb34, 0xd8f0ccfc, 0x5323f2e5, 0x9cbde52d,
    0x55b12993, 0x9a2f3e5b, 0x11fc0042, 0xde62178a, 0xdd2b7a31,
    0x12b56df9, 0x996653e0, 0x56f84428, 0xd00eccdd, 0x1f90db15,
    0x9443e50c, 0x5bddf2c4, 0x58949f7f, 0x970a88b7, 0x1cd9b6ae,
    0xd347a166, 0x1a4b6dd8, 0xd5d57a10, 0x5e064409, 0x919853c1,
    0x92d13e7a, 0x5d4f29b2, 0xd69c17ab, 0x19020063, 0xe498176d,
    0x2b0600a5, 0xa0d53ebc, 0x6f4b2974, 0x6c0244cf, 0xa39c5307,
    0x284f6d1e, 0xe7d17ad6, 0x2eddb668, 0xe143a1a0, 0x6a909fb9,
    0xa50e8871, 0xa647e5ca, 0x69d9f202, 0xe20acc1b, 0x2d94dbd3,
    0xab625326, 0x64fc44ee, 0xef2f7af7, 0x20b16d3f, 0x23f80084,
    0xec66174c, 0x67b52955, 0xa82b3e9d, 0x6127f223, 0xaeb9e5eb,
    0x256adbf2, 0xeaf4cc3a, 0xe9bda181, 0x2623b649, 0xadf08850,
    0x626e9f98, 0x7b6c9ffb, 0xb4f28833, 0x3f21b62a, 0xf0bfa1e2,
    0xf3f6cc59, 0x3c68db91, 0xb7bbe588, 0x7825f240, 0xb1293efe,
    0x7eb72936, 0xf564172f, 0x3afa00e7, 0x39b36d5c, 0xf62d7a94,
    0x7dfe448d, 0xb2605345, 0x3496dbb0, 0xfb08cc78, 0x70dbf261,
    0xbf45e5a9, 0xbc0c8812, 0x73929fda, 0xf841a1c3, 0x37dfb60b,
    0xfed37ab5, 0x314d6d7d, 0xba9e5364, 0x750044ac, 0x76492917,
    0xb9d73edf, 0x320400c6, 0xfd9a170e, 0x1241289b, 0xdddf3f53,
    0x560c014a, 0x99921682, 0x9adb7b39, 0x55456cf1, 0xde9652e8,
    0x11084520, 0xd804899e, 0x179a9e56, 0x9c49a04f, 0x53d7b787,
    0x509eda3c, 0x9f00cdf4, 0x14d3f3ed, 0xdb4de425, 0x5dbb6cd0,
    0x92257b18, 0x19f64501, 0xd66852c9, 0xd5213f72, 0x1abf28ba,
    0x916c16a3, 0x5ef2016b, 0x97fecdd5, 0x5860da1d, 0xd3b3e404,
    0x1c2df3cc, 0x1f649e77, 0xd0fa89bf, 0x5b29b7a6, 0x94b7a06e,
    0x8db5a00d, 0x422bb7c5, 0xc9f889dc, 0x06669e14, 0x052ff3af,
    0xcab1e467, 0x4162da7e, 0x8efccdb6, 0x47f00108, 0x886e16c0,
    0x03bd28d9, 0xcc233f11, 0xcf6a52aa, 0x00f44562, 0x8b277b7b,
    0x44b96cb3, 0xc24fe446, 0x0dd1f38e, 0x8602cd97, 0x499cda5f,
    0x4ad5b7e4, 0x854ba02c, 0x0e989e35, 0xc10689fd, 0x080a4543,
    0xc794528b, 0x4c476c92, 0x83d97b5a, 0x809016e1, 0x4f0e0129,
    0xc4dd3f30, 0x0b4328f8, 0xf6d93ff6, 0x3947283e, 0xb2941627,
    0x7d0a01ef, 0x7e436c54, 0xb1dd7b9c, 0x3a0e4585, 0xf590524d,
    0x3c9c9ef3, 0xf302893b, 0x78d1b722, 0xb74fa0ea, 0xb406cd51,
    0x7b98da99, 0xf04be480, 0x3fd5f348, 0xb9237bbd, 0x76bd6c75,
    0xfd6e526c, 0x32f045a4, 0x31b9281f, 0xfe273fd7, 0x75f401ce,
    0xba6a1606, 0x7366dab8, 0xbcf8cd70, 0x372bf369, 0xf8b5e4a1,
    0xfbfc891a, 0x34629ed2, 0xbfb1a0cb, 0x702fb703, 0x692db760,
    0xa6b3a0a8, 0x2d609eb1, 0xe2fe8979, 0xe1b7e4c2, 0x2e29f30a,
    0xa5facd13, 0x6a64dadb, 0xa3681665, 0x6cf601ad, 0xe7253fb4,
    0x28bb287c, 0x2bf245c7, 0xe46c520f, 0x6fbf6c16, 0xa0217bde,
    0x26d7f32b, 0xe949e4e3, 0x629adafa, 0xad04cd32, 0xae4da089,
    0x61d3b741, 0xea008958, 0x259e9e90, 0xec92522e, 0x230c45e6,
    0xa8df7bff, 0x67416c37, 0x6408018c, 0xab961644, 0x2045285d,
    0xefdb3f95},
   {0x00000000, 0x24825136, 0x4904a26c, 0x6d86f35a, 0x920944d8,
    0xb68b15ee, 0xdb0de6b4, 0xff8fb782, 0xff638ff1, 0xdbe1dec7,
    0xb6672d9d, 0x92e57cab, 0x6d6acb29, 0x49e89a1f, 0x246e6945,
    0x00ec3873, 0x25b619a3, 0x01344895, 0x6cb2bbcf, 0x4830eaf9,
    0xb7bf5d7b, 0x933d0c4d, 0xfebbff17, 0xda39ae21, 0xdad59652,
    0xfe57c764, 0x93d1343e, 0xb7536508, 0x48dcd28a, 0x6c5e83bc,
    0x01d870e6, 0x255a21d0, 0x4b6c3346, 0x6fee6270, 0x0268912a,
    0x26eac01c, 0xd965779e, 0xfde726a8, 0x9061d5f2, 0xb4e384c4,
    0xb40fbcb7, 0x908ded81, 0xfd0b1edb, 0xd9894fed, 0x2606f86f,
    0x0284a959, 0x6f025a03, 0x4b800b35, 0x6eda2ae5, 0x4a587bd3,
    0x27de8889, 0x035cd9bf, 0xfcd36e3d, 0xd8513f0b, 0xb5d7cc51,
    0x91559d67, 0x91b9a514, 0xb53bf422, 0xd8bd0778, 0xfc3f564e,
    0x03b0e1cc, 0x2732b0fa, 0x4ab443a0, 0x6e361296, 0x96d8668c,
    0xb25a37ba, 0xdfdcc4e0, 0xfb5e95d6, 0x04d12254, 0x20537362,
    0x4dd58038, 0x6957d10e, 0x69bbe97d, 0x4d39b84b, 0x20bf4b11,
    0x043d1a27, 0xfbb2ada5, 0xdf30fc93, 0xb2b60fc9, 0x96345eff,
    0xb36e7f2f, 0x97ec2e19, 0xfa6add43, 0xdee88c75, 0x21673bf7,
    0x05e56ac1, 0x6863999b, 0x4ce1c8ad, 0x4c0df0de, 0x688fa1e8,
    0x050952b2, 0x218b0384, 0xde04b406, 0xfa86e530, 0x9700166a,
    0xb382475c, 0xddb455ca, 0xf93604fc, 0x94b0f7a6, 0xb032a690,
    0x4fbd1112, 0x6b3f4024, 0x06b9b37e, 0x223be248, 0x22d7da3b,
    0x06558b0d, 0x6bd37857, 0x4f512961, 0xb0de9ee3, 0x945ccfd5,
    0xf9da3c8f, 0xdd586db9, 0xf8024c69, 0xdc801d5f, 0xb106ee05,
    0x9584bf33, 0x6a0b08b1, 0x4e895987, 0x230faadd, 0x078dfbeb,
    0x0761c398, 0x23e392ae, 0x4e6561f4, 0x6ae730c2, 0x95688740,
    0xb1ead676, 0xdc6c252c, 0xf8ee741a, 0xf6c1cb59, 0xd2439a6f,
    0xbfc56935, 0x9b473803, 0x64c88f81, 0x404adeb7, 0x2dcc2ded,
    0x094e7cdb, 0x09a244a8, 0x2d20159e, 0x40a6e6c4, 0x6424b7f2,
    0x9bab0070, 0xbf295146, 0xd2afa21c, 0xf62df32a, 0xd377d2fa,
    0xf7f583cc, 0x9a737096, 0xbef121a0, 0x417e9622, 0x65fcc714,
    0x087a344e, 0x2cf86578, 0x2c145d0b, 0x08960c3d, 0x6510ff67,
    0x4192ae51, 0xbe1d19d3, 0x9a9f48e5, 0xf719bbbf, 0xd39bea89,
    0xbdadf81f, 0x992fa929, 0xf4a95a73, 0xd02b0b45, 0x2fa4bcc7,
    0x0b26edf1, 0x66a01eab, 0x42224f9d, 0x42ce77ee, 0x664c26d8,
    0x0bcad582, 0x2f4884b4, 0xd0c73336, 0xf4456200, 0x99c3915a,
    0xbd41c06c, 0x981be1bc, 0xbc99b08a, 0xd11f43d0, 0xf59d12e6,
    0x0a12a564, 0x2e90f452, 0x43160708, 0x6794563e, 0x67786e4d,
    0x43fa3f7b, 0x2e7ccc21, 0x0afe9d17, 0xf5712a95, 0xd1f37ba3,
    0xbc7588f9, 0x98f7d9cf, 0x6019add5, 0x449bfce3, 0x291d0fb9,
    0x0d9f5e8f, 0xf210e90d, 0xd692b83b, 0xbb144b61, 0x9f961a57,
    0x9f7a2224, 0xbbf87312, 0xd67e8048, 0xf2fcd17e, 0x0d7366fc,
    0x29f137ca, 0x4477c490, 0x60f595a6, 0x45afb476, 0x612de540,
    0x0cab161a, 0x2829472c, 0xd7a6f0ae, 0xf324a198, 0x9ea252c2,
    0xba2003f4, 0xbacc3b87, 0x9e4e6ab1, 0xf3c899eb, 0xd74ac8dd,
    0x28c57f5f, 0x0c472e69, 0x61c1dd33, 0x45438c05, 0x2b759e93,
    0x0ff7cfa5, 0x62713cff, 0x46f36dc9, 0xb97cda4b, 0x9dfe8b7d,
    0xf0787827, 0xd4fa2911, 0xd4161162, 0xf0944054, 0x9d12b30e,
    0xb990e238, 0x461f55ba, 0x629d048c, 0x0f1bf7d6, 0x2b99a6e0,
    0x0ec38730, 0x2a41d606, 0x47c7255c, 0x6345746a, 0x9ccac3e8,
    0xb84892de, 0xd5ce6184, 0xf14c30b2, 0xf1a008c1, 0xd52259f7,
    0xb8a4aaad, 0x9c26fb9b, 0x63a94c19, 0x472b1d2f, 0x2aadee75,
    0x0e2fbf43},
   {0x00000000, 0x36f290f3, 0x6de521e6, 0x5b17b115, 0xdbca43cc,
    0xed38d33f, 0xb62f622a, 0x80ddf2d9, 0x6ce581d9, 0x5a17112a,
    0x0100a03f, 0x37f230cc, 0xb72fc215, 0x81dd52e6, 0xdacae3f3,
    0xec387300, 0xd9cb03b2, 0xef399341, 0xb42e2254, 0x82dcb2a7,
    0x0201407e, 0x34f3d08d, 0x6fe46198, 0x5916f16b, 0xb52e826b,
    0x83dc1298, 0xd8cba38d, 0xee39337e, 0x6ee4c1a7, 0x58165154,
    0x0301e041, 0x35f370b2, 0x68e70125, 0x5e1591d6, 0x050220c3,
    0x33f0b030, 0xb32d42e9, 0x85dfd21a, 0xdec8630f, 0xe83af3fc,
    0x040280fc, 0x32f0100f, 0x69e7a11a, 0x5f1531e9, 0xdfc8c330,
    0xe93a53c3, 0xb22de2d6, 0x84df7225, 0xb12c0297, 0x87de9264,
    0xdcc92371, 0xea3bb382, 0x6ae6415b, 0x5c14d1a8, 0x070360bd,
    0x31f1f04e, 0xddc9834e, 0xeb3b13bd, 0xb02ca2a8, 0x86de325b,
    0x0603c082, 0x30f15071, 0x6be6e164, 0x5d147197, 0xd1ce024a,
    0xe73c92b9, 0xbc2b23ac, 0x8ad9b35f, 0x0a044186, 0x3cf6d175,
    0x67e16060, 0x5113f093, 0xbd2b8393, 0x8bd91360, 0xd0cea275,
    0xe63c3286, 0x66e1c05f, 0x501350ac, 0x0b04e1b9, 0x3df6714a,
    0x080501f8, 0x3ef7910b, 0x65e0201e, 0x5312b0ed, 0xd3cf4234,
    0xe53dd2c7, 0xbe2a63d2, 0x88d8f321, 0x64e08021, 0x521210d2,
    0x0905a1c7, 0x3ff73134, 0xbf2ac3ed, 0x89d8531e, 0xd2cfe20b,
    0xe43d72f8, 0xb929036f, 0x8fdb939c, 0xd4cc2289, 0xe23eb27a,
    0x62e340a3, 0x5411d050, 0x0f066145, 0x39f4f1b6, 0xd5cc82b6,
    0xe33e1245, 0xb829a350, 0x8edb33a3, 0x0e06c17a, 0x38f45189,
    0x63e3e09c, 0x5511706f, 0x60e200dd, 0x5610902e, 0x0d07213b,
    0x3bf5b1c8, 0xbb284311, 0x8ddad3e2, 0xd6cd62f7, 0xe03ff204,
    0x0c078104, 0x3af511f7, 0x61e2a0e2, 0x57103011, 0xd7cdc2c8,
    0xe13f523b, 0xba28e32e, 0x8cda73dd, 0x78ed02d5, 0x4e1f9226,
    0x15082333, 0x23fab3c0, 0xa3274119, 0x95d5d1ea, 0xcec260ff,
    0xf830f00c, 0x1408830c, 0x22fa13ff, 0x79eda2ea, 0x4f1f3219,
    0xcfc2c0c0, 0xf9305033, 0xa227e126, 0x94d571d5, 0xa1260167,
    0x97d49194, 0xccc32081, 0xfa31b072, 0x7aec42ab, 0x4c1ed258,
    0x1709634d, 0x21fbf3be, 0xcdc380be, 0xfb31104d, 0xa026a158,
    0x96d431ab, 0x1609c372, 0x20fb5381, 0x7bece294, 0x4d1e7267,
    0x100a03f0, 0x26f89303, 0x7def2216, 0x4b1db2e5, 0xcbc0403c,
    0xfd32d0cf, 0xa62561da, 0x90d7f129, 0x7cef8229, 0x4a1d12da,
    0x110aa3cf, 0x27f8333c, 0xa725c1e5, 0x91d75116, 0xcac0e003,
    0xfc3270f0, 0xc9c10042, 0xff3390b1, 0xa42421a4, 0x92d6b157,
    0x120b438e, 0x24f9d37d, 0x7fee6268, 0x491cf29b, 0xa524819b,
    0x93d61168, 0xc8c1a07d, 0xfe33308e, 0x7eeec257, 0x481c52a4,
    0x130be3b1, 0x25f97342, 0xa923009f, 0x9fd1906c, 0xc4c62179,
    0xf234b18a, 0x72e94353, 0x441bd3a0, 0x1f0c62b5, 0x29fef246,
    0xc5c68146, 0xf33411b5, 0xa823a0a0, 0x9ed13053, 0x1e0cc28a,
    0x28fe5279, 0x73e9e36c, 0x451b739f, 0x70e8032d, 0x461a93de,
    0x1d0d22cb, 0x2bffb238, 0xab2240e1, 0x9dd0d012, 0xc6c76107,
    0xf035f1f4, 0x1c0d82f4, 0x2aff1207, 0x71e8a312, 0x471a33e1,
    0xc7c7c138, 0xf13551cb, 0xaa22e0de, 0x9cd0702d, 0xc1c401ba,
    0xf7369149, 0xac21205c, 0x9ad3b0af, 0x1a0e4276, 0x2cfcd285,
    0x77eb6390, 0x4119f363, 0xad218063, 0x9bd31090, 0xc0c4a185,
    0xf6363176, 0x76ebc3af, 0x4019535c, 0x1b0ee249, 0x2dfc72ba,
    0x180f0208, 0x2efd92fb, 0x75ea23ee, 0x4318b31d, 0xc3c541c4,
    0xf537d137, 0xae206022, 0x98d2f0d1, 0x74ea83d1, 0x42181322,
    0x190fa237, 0x2ffd32c4, 0xaf20c01d, 0x99d250ee, 0xc2c5e1fb,
    0xf4377108}};

local const z_word_t FAR crc_braid_big_table[][256] = {
   {0x0000000000000000, 0xf390f23600000000, 0xe621e56d00000000,
    0x15b1175b00000000, 0xcc43cadb00000000, 0x3fd338ed00000000,
    0x2a622fb600000000, 0xd9f2dd8000000000, 0xd981e56c00000000,
    0x2a11175a00000000, 0x3fa0000100000000, 0xcc30f23700000000,
    0x15c22fb700000000, 0xe652dd8100000000, 0xf3e3cada00000000,
    0x007338ec00000000, 0xb203cbd900000000, 0x419339ef00000000,
    0x54222eb400000000, 0xa7b2dc8200000000, 0x7e40010200000000,
    0x8dd0f33400000000, 0x9861e46f00000000, 0x6bf1165900000000,
    0x6b822eb500000000, 0x9812dc8300000000, 0x8da3cbd800000000,
    0x7e3339ee00000000, 0xa7c1e46e00000000, 0x5451165800000000,
    0x41e0010300000000, 0xb270f33500000000, 0x2501e76800000000,
    0xd691155e00000000, 0xc320020500000000, 0x30b0f03300000000,
    0xe9422db300000000, 0x1ad2df8500000000, 0x0f63c8de00000000,
    0xfcf33ae800000000, 0xfc80020400000000, 0x0f10f03200000000,
    0x1aa1e76900000000, 0xe931155f00000000, 0x30c3c8df00000000,
    0xc3533ae900000000, 0xd6e22db200000000, 0x2572df8400000000,
    0x97022cb100000000, 0x6492de8700000000, 0x7123c9dc00000000,
    0x82b33bea00000000, 0x5b41e66a00000000, 0xa8d1145c00000000,
    0xbd60030700000000, 0x4ef0f13100000000, 0x4e83c9dd00000000,
    0xbd133beb00000000, 0xa8a22cb000000000, 0x5b32de8600000000,
    0x82c0030600000000, 0x7150f13000000000, 0x64e1e66b00000000,
    0x9771145d00000000, 0x4a02ced100000000, 0xb9923ce700000000,
    0xac232bbc00000000, 0x5fb3d98a00000000, 0x8641040a00000000,
    0x75d1f63c00000000, 0x6060e16700000000, 0x93f0135100000000,
    0x93832bbd00000000, 0x6013d98b00000000, 0x75a2ced000000000,
    0x86323ce600000000, 0x5fc0e16600000000, 0xac50135000000000,
    0xb9e1040b00000000, 0x4a71f63d00000000, 0xf801050800000000,
    0x0b91f73e00000000, 0x1e20e06500000000, 0xedb0125300000000,
    0x3442cfd300000000, 0xc7d23de500000000, 0xd2632abe00000000,
    0x21f3d88800000000, 0x2180e06400000000, 0xd210125200000000,
    0xc7a1050900000000, 0x3431f73f00000000, 0xedc32abf00000000,
    0x1e53d88900000000, 0x0be2cfd200000000, 0xf8723de400000000,
    0x6f0329b900000000, 0x9c93db8f00000000, 0x8922ccd400000000,
    0x7ab23ee200000000, 0xa340e36200000000, 0x50d0115400000000,
    0x4561060f00000000, 0xb6f1f43900000000, 0xb682ccd500000000,
    0x45123ee300000000, 0x50a329b800000000, 0xa333db8e00000000,
    0x7ac1060e00000000, 0x8951f43800000000, 0x9ce0e36300000000,
    0x6f70115500000000, 0xdd00e26000000000, 0x2e90105600000000,
    0x3b21070d00000000, 0xc8b1f53b00000000, 0x114328bb00000000,
    0xe2d3da8d00000000, 0xf762cdd600000000, 0x04f23fe000000000,
    0x0481070c00000000, 0xf711f53a00000000, 0xe2a0e26100000000,
    0x1130105700000000, 0xc8c2cdd700000000, 0x3b523fe100000000,
    0x2ee328ba00000000, 0xdd73da8c00000000, 0xd502ed7800000000,
    0x26921f4e00000000, 0x3323081500000000, 0xc0b3fa2300000000,
    0x194127a300000000, 0xead1d59500000000, 0xff60c2ce00000000,
    0x0cf030f800000000, 0x0c83081400000000, 0xff13fa2200000000,
    0xeaa2ed7900000000, 0x19321f4f00000000, 0xc0c0c2cf00000000,
    0x335030f900000000, 0x26e127a200000000, 0xd571d59400000000,
    0x670126a100000000, 0x9491d49700000000, 0x8120c3cc00000000,
    0x72b031fa00000000, 0xab42ec7a00000000, 0x58d21e4c00000000,
    0x4d63091700000000, 0xbef3fb2100000000, 0xbe80c3cd00000000,
    0x4d1031fb00000000, 0x58a126a000000000, 0xab31d49600000000,
    0x72c3091600000000, 0x8153fb2000000000, 0x94e2ec7b00000000,
    0x67721e4d00000000, 0xf0030a1000000000, 0x0393f82600000000,
    0x1622ef7d00000000, 0xe5b21d4b00000000, 0x3c40c0cb00000000,
    0xcfd032fd00000000, 0xda6125a600000000, 0x29f1d79000000000,
    0x2982ef7c00000000, 0xda121d4a00000000, 0xcfa30a1100000000,
    0x3c33f82700000000, 0xe5c125a700000000, 0x1651d79100000000,
    0x03e0c0ca00000000, 0xf07032fc00000000, 0x4200c1c900000000,
    0xb19033ff00000000, 0xa42124a400000000, 0x57b1d69200000000,
    0x8e430b1200000000, 0x7dd3f92400000000, 0x6862ee7f00000000,
    0x9bf21c4900000000, 0x9b8124a500000000, 0x6811d69300000000,
    0x7da0c1c800000000, 0x8e3033fe00000000, 0x57c2ee7e00000000,
    0xa4521c4800000000, 0xb1e30b1300000000, 0x4273f92500000000,
    0x9f0023a900000000, 0x6c90d19f00000000, 0x7921c6c400000000,
    0x8ab134f200000000, 0x5343e97200000000, 0xa0d31b4400000000,
    0xb5620c1f00000000, 0x46f2fe2900000000, 0x4681c6c500000000,
    0xb51134f300000000, 0xa0a023a800000000, 0x5330d19e00000000,
    0x8ac20c1e00000000, 0x7952fe2800000000, 0x6ce3e97300000000,
    0x9f731b4500000000, 0x2d03e87000000000, 0xde931a4600000000,
    0xcb220d1d00000000, 0x38b2ff2b00000000, 0xe14022ab00000000,
    0x12d0d09d00000000, 0x0761c7c600000000, 0xf4f135f000000000,
    0xf4820d1c00000000, 0x0712ff2a00000000, 0x12a3e87100000000,
    0xe1331a4700000000, 0x38c1c7c700000000, 0xcb5135f100000000,
    0xdee022aa00000000, 0x2d70d09c00000000, 0xba01c4c100000000,
    0x499136f700000000, 0x5c2021ac00000000, 0xafb0d39a00000000,
    0x76420e1a00000000, 0x85d2fc2c00000000, 0x9063eb7700000000,
    0x63f3194100000000, 0x638021ad00000000, 0x9010d39b00000000,
    0x85a1c4c000000000, 0x763136f600000000, 0xafc3eb7600000000,
    0x5c53194000000000, 0x49e20e1b00000000, 0xba72fc2d00000000,
    0x08020f1800000000, 0xfb92fd2e00000000, 0xee23ea7500000000,
    0x1db3184300000000, 0xc441c5c300000000, 0x37d137f500000000,
    0x226020ae00000000, 0xd1f0d29800000000, 0xd183ea7400000000,
    0x2213184200000000, 0x37a20f1900000000, 0xc432fd2f00000000,
    0x1dc020af00000000, 0xee50d29900000000, 0xfbe1c5c200000000,
    0x087137f400000000},
   {0x0000000000000000, 0x3651822400000000, 0x6ca2044900000000,
    0x5af3866d00000000, 0xd844099200000000, 0xee158bb600000000,
    0xb4e60ddb00000000, 0x82b78fff00000000, 0xf18f63ff00000000,
    0xc7dee1db00000000, 0x9d2d67b600000000, 0xab7ce59200000000,
    0x29cb6a6d00000000, 0x1f9ae84900000000, 0x45696e2400000000,
    0x7338ec0000000000, 0xa319b62500000000, 0x9548340100000000,
    0xcfbbb26c00000000, 0xf9ea304800000000, 0x7b5dbfb700000000,
    0x4d0c3d9300000000, 0x17ffbbfe00000000, 0x21ae39da00000000,
    0x5296d5da00000000, 0x64c757fe00000000, 0x3e34d19300000000,
    0x086553b700000000, 0x8ad2dc4800000000, 0xbc835e6c00000000,
    0xe670d80100000000, 0xd0215a2500000000, 0x46336c4b00000000,
    0x7062ee6f00000000, 0x2a91680200000000, 0x1cc0ea2600000000,
    0x9e7765d900000000, 0xa826e7fd00000000, 0xf2d5619000000000,
    0xc484e3b400000000, 0xb7bc0fb400000000, 0x81ed8d9000000000,
    0xdb1e0bfd00000000, 0xed4f89d900000000, 0x6ff8062600000000,
    0x59a9840200000000, 0x035a026f00000000, 0x350b804b00000000,
    0xe52ada6e00000000, 0xd37b584a00000000, 0x8988de2700000000,
    0xbfd95c0300000000, 0x3d6ed3fc00000000, 0x0b3f51d800000000,
    0x51ccd7b500000000, 0x679d559100000000, 0x14a5b99100000000,
    0x22f43bb500000000, 0x7807bdd800000000, 0x4e563ffc00000000,
    0xcce1b00300000000, 0xfab0322700000000, 0xa043b44a00000000,
    0x9612366e00000000, 0x8c66d89600000000, 0xba375ab200000000,
    0xe0c4dcdf00000000, 0xd6955efb00000000, 0x5422d10400000000,
    0x6273532000000000, 0x3880d54d00000000, 0x0ed1576900000000,
    0x7de9bb6900000000, 0x4bb8394d00000000, 0x114bbf2000000000,
    0x271a3d0400000000, 0xa5adb2fb00000000, 0x93fc30df00000000,
    0xc90fb6b200000000, 0xff5e349600000000, 0x2f7f6eb300000000,
    0x192eec9700000000, 0x43dd6afa00000000, 0x758ce8de00000000,
    0xf73b672100000000, 0xc16ae50500000000, 0x9b99636800000000,
    0xadc8e14c00000000, 0xdef00d4c00000000, 0xe8a18f6800000000,
    0xb252090500000000, 0x84038b2100000000, 0x06b404de00000000,
    0x30e586fa00000000, 0x6a16009700000000, 0x5c4782b300000000,
    0xca55b4dd00000000, 0xfc0436f900000000, 0xa6f7b09400000000,
    0x90a632b000000000, 0x1211bd4f00000000, 0x24403f6b00000000,
    0x7eb3b90600000000, 0x48e23b2200000000, 0x3bdad72200000000,
    0x0d8b550600000000, 0x5778d36b00000000, 0x6129514f00000000,
    0xe39edeb000000000, 0xd5cf5c9400000000, 0x8f3cdaf900000000,
    0xb96d58dd00000000, 0x694c02f800000000, 0x5f1d80dc00000000,
    0x05ee06b100000000, 0x33bf849500000000, 0xb1080b6a00000000,
    0x8759894e00000000, 0xddaa0f2300000000, 0xebfb8d0700000000,
    0x98c3610700000000, 0xae92e32300000000, 0xf461654e00000000,
    0xc230e76a00000000, 0x4087689500000000, 0x76d6eab100000000,
    0x2c256cdc00000000, 0x1a74eef800000000, 0x59cbc1f600000000,
    0x6f9a43d200000000, 0x3569c5bf00000000, 0x0338479b00000000,
    0x818fc86400000000, 0xb7de4a4000000000, 0xed2dcc2d00000000,
    0xdb7c4e0900000000, 0xa844a20900000000, 0x9e15202d00000000,
    0xc4e6a64000000000, 0xf2b7246400000000, 0x7000ab9b00000000,
    0x465129bf00000000, 0x1ca2afd200000000, 0x2af32df600000000,
    0xfad277d300000000, 0xcc83f5f700000000, 0x9670739a00000000,
    0xa021f1be00000000, 0x22967e4100000000, 0x14c7fc6500000000,
    0x4e347a0800000000, 0x7865f82c00000000, 0x0b5d142c00000000,
    0x3d0c960800000000, 0x67ff106500000000, 0x51ae924100000000,
    0xd3191dbe00000000, 0xe5489f9a00000000, 0xbfbb19f700000000,
    0x89ea9bd300000000, 0x1ff8adbd00000000, 0x29a92f9900000000,
    0x735aa9f400000000, 0x450b2bd000000000, 0xc7bca42f00000000,
    0xf1ed260b00000000, 0xab1ea06600000000, 0x9d4f224200000000,
    0xee77ce4200000000, 0xd8264c6600000000, 0x82d5ca0b00000000,
    0xb484482f00000000, 0x3633c7d000000000, 0x006245f400000000,
    0x5a91c39900000000, 0x6cc041bd00000000, 0xbce11b9800000000,
    0x8ab099bc00000000, 0xd0431fd100000000, 0xe6129df500000000,
    0x64a5120a00000000, 0x52f4902e00000000, 0x0807164300000000,
    0x3e56946700000000, 0x4d6e786700000000, 0x7b3ffa4300000000,
    0x21cc7c2e00000000, 0x179dfe0a00000000, 0x952a71f500000000,
    0xa37bf3d100000000, 0xf98875bc00000000, 0xcfd9f79800000000,
    0xd5ad196000000000, 0xe3fc9b4400000000, 0xb90f1d2900000000,
    0x8f5e9f0d00000000, 0x0de910f200000000, 0x3bb892d600000000,
    0x614b14bb00000000, 0x571a969f00000000, 0x24227a9f00000000,
    0x1273f8bb00000000, 0x48807ed600000000, 0x7ed1fcf200000000,
    0xfc66730d00000000, 0xca37f12900000000, 0x90c4774400000000,
    0xa695f56000000000, 0x76b4af4500000000, 0x40e52d6100000000,
    0x1a16ab0c00000000, 0x2c47292800000000, 0xaef0a6d700000000,
    0x98a124f300000000, 0xc252a29e00000000, 0xf40320ba00000000,
    0x873bccba00000000, 0xb16a4e9e00000000, 0xeb99c8f300000000,
    0xddc84ad700000000, 0x5f7fc52800000000, 0x692e470c00000000,
    0x33ddc16100000000, 0x058c434500000000, 0x939e752b00000000,
    0xa5cff70f00000000, 0xff3c716200000000, 0xc96df34600000000,
    0x4bda7cb900000000, 0x7d8bfe9d00000000, 0x277878f000000000,
    0x1129fad400000000, 0x621116d400000000, 0x544094f000000000,
    0x0eb3129d00000000, 0x38e290b900000000, 0xba551f4600000000,
    0x8c049d6200000000, 0xd6f71b0f00000000, 0xe0a6992b00000000,
    0x3087c30e00000000, 0x06d6412a00000000, 0x5c25c74700000000,
    0x6a74456300000000, 0xe8c3ca9c00000000, 0xde9248b800000000,
    0x8461ced500000000, 0xb2304cf100000000, 0xc108a0f100000000,
    0xf75922d500000000, 0xadaaa4b800000000, 0x9bfb269c00000000,
    0x194ca96300000000, 0x2f1d2b4700000000, 0x75eead2a00000000,
    0x43bf2f0e00000000},
   {0x0000000000000000, 0xc8179ecf00000000, 0xd1294d4400000000,
    0x193ed38b00000000, 0xa2539a8800000000, 0x6a44044700000000,
    0x737ad7cc00000000, 0xbb6d490300000000, 0x05a145ca00000000,
    0xcdb6db0500000000, 0xd488088e00000000, 0x1c9f964100000000,
    0xa7f2df4200000000, 0x6fe5418d00000000, 0x76db920600000000,
    0xbecc0cc900000000, 0x4b44fa4f00000000, 0x8353648000000000,
    0x9a6db70b00000000, 0x527a29c400000000, 0xe91760c700000000,
    0x2100fe0800000000, 0x383e2d8300000000, 0xf029b34c00000000,
    0x4ee5bf8500000000, 0x86f2214a00000000, 0x9fccf2c100000000,
    0x57db6c0e00000000, 0xecb6250d00000000, 0x24a1bbc200000000,
    0x3d9f684900000000, 0xf588f68600000000, 0x9688f49f00000000,
    0x5e9f6a5000000000, 0x47a1b9db00000000, 0x8fb6271400000000,
    0x34db6e1700000000, 0xfcccf0d800000000, 0xe5f2235300000000,
    0x2de5bd9c00000000, 0x9329b15500000000, 0x5b3e2f9a00000000,
    0x4200fc1100000000, 0x8a1762de00000000, 0x317a2bdd00000000,
    0xf96db51200000000, 0xe053669900000000, 0x2844f85600000000,
    0xddcc0ed000000000, 0x15db901f00000000, 0x0ce5439400000000,
    0xc4f2dd5b00000000, 0x7f9f945800000000, 0xb7880a9700000000,
    0xaeb6d91c00000000, 0x66a147d300000000, 0xd86d4b1a00000000,
    0x107ad5d500000000, 0x0944065e00000000, 0xc153989100000000,
    0x7a3ed19200000000, 0xb2294f5d00000000, 0xab179cd600000000,
    0x6300021900000000, 0x6d1798e400000000, 0xa500062b00000000,
    0xbc3ed5a000000000, 0x74294b6f00000000, 0xcf44026c00000000,
    0x07539ca300000000, 0x1e6d4f2800000000, 0xd67ad1e700000000,
    0x68b6dd2e00000000, 0xa0a143e100000000, 0xb99f906a00000000,
    0x71880ea500000000, 0xcae547a600000000, 0x02f2d96900000000,
    0x1bcc0ae200000000, 0xd3db942d00000000, 0x265362ab00000000,
    0xee44fc6400000000, 0xf77a2fef00000000, 0x3f6db12000000000,
    0x8400f82300000000, 0x4c1766ec00000000, 0x5529b56700000000,
    0x9d3e2ba800000000, 0x23f2276100000000, 0xebe5b9ae00000000,
    0xf2db6a2500000000, 0x3accf4ea00000000, 0x81a1bde900000000,
    0x49b6232600000000, 0x5088f0ad00000000, 0x989f6e6200000000,
    0xfb9f6c7b00000000, 0x3388f2b400000000, 0x2ab6213f00000000,
    0xe2a1bff000000000, 0x59ccf6f300000000, 0x91db683c00000000,
    0x88e5bbb700000000, 0x40f2257800000000, 0xfe3e29b100000000,
    0x3629b77e00000000, 0x2f1764f500000000, 0xe700fa3a00000000,
    0x5c6db33900000000, 0x947a2df600000000, 0x8d44fe7d00000000,
    0x455360b200000000, 0xb0db963400000000, 0x78cc08fb00000000,
    0x61f2db7000000000, 0xa9e545bf00000000, 0x12880cbc00000000,
    0xda9f927300000000, 0xc3a141f800000000, 0x0bb6df3700000000,
    0xb57ad3fe00000000, 0x7d6d4d3100000000, 0x64539eba00000000,
    0xac44007500000000, 0x1729497600000000, 0xdf3ed7b900000000,
    0xc600043200000000, 0x0e179afd00000000, 0x9b28411200000000,
    0x533fdfdd00000000, 0x4a010c5600000000, 0x8216929900000000,
    0x397bdb9a00000000, 0xf16c455500000000, 0xe85296de00000000,
    0x2045081100000000, 0x9e8904d800000000, 0x569e9a1700000000,
    0x4fa0499c00000000, 0x87b7d75300000000, 0x3cda9e5000000000,
    0xf4cd009f00000000, 0xedf3d31400000000, 0x25e44ddb00000000,
    0xd06cbb5d00000000, 0x187b259200000000, 0x0145f61900000000,
    0xc95268d600000000, 0x723f21d500000000, 0xba28bf1a00000000,
    0xa3166c9100000000, 0x6b01f25e00000000, 0xd5cdfe9700000000,
    0x1dda605800000000, 0x04e4b3d300000000, 0xccf32d1c00000000,
    0x779e641f00000000, 0xbf89fad000000000, 0xa6b7295b00000000,
    0x6ea0b79400000000, 0x0da0b58d00000000, 0xc5b72b4200000000,
    0xdc89f8c900000000, 0x149e660600000000, 0xaff32f0500000000,
    0x67e4b1ca00000000, 0x7eda624100000000, 0xb6cdfc8e00000000,
    0x0801f04700000000, 0xc0166e8800000000, 0xd928bd0300000000,
    0x113f23cc00000000, 0xaa526acf00000000, 0x6245f40000000000,
    0x7b7b278b00000000, 0xb36cb94400000000, 0x46e44fc200000000,
    0x8ef3d10d00000000, 0x97cd028600000000, 0x5fda9c4900000000,
    0xe4b7d54a00000000, 0x2ca04b8500000000, 0x359e980e00000000,
    0xfd8906c100000000, 0x43450a0800000000, 0x8b5294c700000000,
    0x926c474c00000000, 0x5a7bd98300000000, 0xe116908000000000,
    0x29010e4f00000000, 0x303fddc400000000, 0xf828430b00000000,
    0xf63fd9f600000000, 0x3e28473900000000, 0x271694b200000000,
    0xef010a7d00000000, 0x546c437e00000000, 0x9c7bddb100000000,
    0x85450e3a00000000, 0x4d5290f500000000, 0xf39e9c3c00000000,
    0x3b8902f300000000, 0x22b7d17800000000, 0xeaa04fb700000000,
    0x51cd06b400000000, 0x99da987b00000000, 0x80e44bf000000000,
    0x48f3d53f00000000, 0xbd7b23b900000000, 0x756cbd7600000000,
    0x6c526efd00000000, 0xa445f03200000000, 0x1f28b93100000000,
    0xd73f27fe00000000, 0xce01f47500000000, 0x06166aba00000000,
    0xb8da667300000000, 0x70cdf8bc00000000, 0x69f32b3700000000,
    0xa1e4b5f800000000, 0x1a89fcfb00000000, 0xd29e623400000000,
    0xcba0b1bf00000000, 0x03b72f7000000000, 0x60b72d6900000000,
    0xa8a0b3a600000000, 0xb19e602d00000000, 0x7989fee200000000,
    0xc2e4b7e100000000, 0x0af3292e00000000, 0x13cdfaa500000000,
    0xdbda646a00000000, 0x651668a300000000, 0xad01f66c00000000,
    0xb43f25e700000000, 0x7c28bb2800000000, 0xc745f22b00000000,
    0x0f526ce400000000, 0x166cbf6f00000000, 0xde7b21a000000000,
    0x2bf3d72600000000, 0xe3e449e900000000, 0xfada9a6200000000,
    0x32cd04ad00000000, 0x89a04dae00000000, 0x41b7d36100000000,
    0x588900ea00000000, 0x909e9e2500000000, 0x2e5292ec00000000,
    0xe6450c2300000000, 0xff7bdfa800000000, 0x376c416700000000,
    0x8c01086400000000, 0x441696ab00000000, 0x5d28452000000000,
    0x953fdbef00000000},
   {0x0000000000000000, 0x95d4709500000000, 0x6baf90f100000000,
    0xfe7be06400000000, 0x9758503800000000, 0x028c20ad00000000,
    0xfcf7c0c900000000, 0x6923b05c00000000, 0x2eb1a07000000000,
    0xbb65d0e500000000, 0x451e308100000000, 0xd0ca401400000000,
    0xb9e9f04800000000, 0x2c3d80dd00000000, 0xd24660b900000000,
    0x4792102c00000000, 0x5c6241e100000000, 0xc9b6317400000000,
    0x37cdd11000000000, 0xa219a18500000000, 0xcb3a11d900000000,
    0x5eee614c00000000, 0xa095812800000000, 0x3541f1bd00000000,
    0x72d3e19100000000, 0xe707910400000000, 0x197c716000000000,
    0x8ca801f500000000, 0xe58bb1a900000000, 0x705fc13c00000000,
    0x8e24215800000000, 0x1bf051cd00000000, 0xf9c2f31900000000,
    0x6c16838c00000000, 0x926d63e800000000, 0x07b9137d00000000,
    0x6e9aa32100000000, 0xfb4ed3b400000000, 0x053533d000000000,
    0x90e1434500000000, 0xd773536900000000, 0x42a723fc00000000,
    0xbcdcc39800000000, 0x2908b30d00000000, 0x402b035100000000,
    0xd5ff73c400000000, 0x2b8493a000000000, 0xbe50e33500000000,
    0xa5a0b2f800000000, 0x3074c26d00000000, 0xce0f220900000000,
    0x5bdb529c00000000, 0x32f8e2c000000000, 0xa72c925500000000,
    0x5957723100000000, 0xcc8302a400000000, 0x8b11128800000000,
    0x1ec5621d00000000, 0xe0be827900000000, 0x756af2ec00000000,
    0x1c4942b000000000, 0x899d322500000000, 0x77e6d24100000000,
    0xe232a2d400000000, 0xf285e73300000000, 0x675197a600000000,
    0x992a77c200000000, 0x0cfe075700000000, 0x65ddb70b00000000,
    0xf009c79e00000000, 0x0e7227fa00000000, 0x9ba6576f00000000,
    0xdc34474300000000, 0x49e037d600000000, 0xb79bd7b200000000,
    0x224fa72700000000, 0x4b6c177b00000000, 0xdeb867ee00000000,
    0x20c3878a00000000, 0xb517f71f00000000, 0xaee7a6d200000000,
    0x3b33d64700000000, 0xc548362300000000, 0x509c46b600000000,
    0x39bff6ea00000000, 0xac6b867f00000000, 0x5210661b00000000,
    0xc7c4168e00000000, 0x805606a200000000, 0x1582763700000000,
    0xebf9965300000000, 0x7e2de6c600000000, 0x170e569a00000000,
    0x82da260f00000000, 0x7ca1c66b00000000, 0xe975b6fe00000000,
    0x0b47142a00000000, 0x9e9364bf00000000, 0x60e884db00000000,
    0xf53cf44e00000000, 0x9c1f441200000000, 0x09cb348700000000,
    0xf7b0d4e300000000, 0x6264a47600000000, 0x25f6b45a00000000,
    0xb022c4cf00000000, 0x4e5924ab00000000, 0xdb8d543e00000000,
    0xb2aee46200000000, 0x277a94f700000000, 0xd901749300000000,
    0x4cd5040600000000, 0x572555cb00000000, 0xc2f1255e00000000,
    0x3c8ac53a00000000, 0xa95eb5af00000000, 0xc07d05f300000000,
    0x55a9756600000000, 0xabd2950200000000, 0x3e06e59700000000,
    0x7994f5bb00000000, 0xec40852e00000000, 0x123b654a00000000,
    0x87ef15df00000000, 0xeecca58300000000, 0x7b18d51600000000,
    0x8563357200000000, 0x10b745e700000000, 0xe40bcf6700000000,
    0x71dfbff200000000, 0x8fa45f9600000000, 0x1a702f0300000000,
    0x73539f5f00000000, 0xe687efca00000000, 0x18fc0fae00000000,
    0x8d287f3b00000000, 0xcaba6f1700000000, 0x5f6e1f8200000000,
    0xa115ffe600000000, 0x34c18f7300000000, 0x5de23f2f00000000,
    0xc8364fba00000000, 0x364dafde00000000, 0xa399df4b00000000,
    0xb8698e8600000000, 0x2dbdfe1300000000, 0xd3c61e7700000000,
    0x46126ee200000000, 0x2f31debe00000000, 0xbae5ae2b00000000,
    0x449e4e4f00000000, 0xd14a3eda00000000, 0x96d82ef600000000,
    0x030c5e6300000000, 0xfd77be0700000000, 0x68a3ce9200000000,
    0x01807ece00000000, 0x94540e5b00000000, 0x6a2fee3f00000000,
    0xfffb9eaa00000000, 0x1dc93c7e00000000, 0x881d4ceb00000000,
    0x7666ac8f00000000, 0xe3b2dc1a00000000, 0x8a916c4600000000,
    0x1f451cd300000000, 0xe13efcb700000000, 0x74ea8c2200000000,
    0x33789c0e00000000, 0xa6acec9b00000000, 0x58d70cff00000000,
    0xcd037c6a00000000, 0xa420cc3600000000, 0x31f4bca300000000,
    0xcf8f5cc700000000, 0x5a5b2c5200000000, 0x41ab7d9f00000000,
    0xd47f0d0a00000000, 0x2a04ed6e00000000, 0xbfd09dfb00000000,
    0xd6f32da700000000, 0x43275d3200000000, 0xbd5cbd5600000000,
    0x2888cdc300000000, 0x6f1addef00000000, 0xfacead7a00000000,
    0x04b54d1e00000000, 0x91613d8b00000000, 0xf8428dd700000000,
    0x6d96fd4200000000, 0x93ed1d2600000000, 0x06396db300000000,
    0x168e285400000000, 0x835a58c100000000, 0x7d21b8a500000000,
    0xe8f5c83000000000, 0x81d6786c00000000, 0x140208f900000000,
    0xea79e89d00000000, 0x7fad980800000000, 0x383f882400000000,
    0xadebf8b100000000, 0x539018d500000000, 0xc644684000000000,
    0xaf67d81c00000000, 0x3ab3a88900000000, 0xc4c848ed00000000,
    0x511c387800000000, 0x4aec69b500000000, 0xdf38192000000000,
    0x2143f94400000000, 0xb49789d100000000, 0xddb4398d00000000,
    0x4860491800000000, 0xb61ba97c00000000, 0x23cfd9e900000000,
    0x645dc9c500000000, 0xf189b95000000000, 0x0ff2593400000000,
    0x9a2629a100000000, 0xf30599fd00000000, 0x66d1e96800000000,
    0x98aa090c00000000, 0x0d7e799900000000, 0xef4cdb4d00000000,
    0x7a98abd800000000, 0x84e34bbc00000000, 0x11373b2900000000,
    0x78148b7500000000, 0xedc0fbe000000000, 0x13bb1b8400000000,
    0x866f6b1100000000, 0xc1fd7b3d00000000, 0x54290ba800000000,
    0xaa52ebcc00000000, 0x3f869b5900000000, 0x56a52b0500000000,
    0xc3715b9000000000, 0x3d0abbf400000000, 0xa8decb6100000000,
    0xb32e9aac00000000, 0x26faea3900000000, 0xd8810a5d00000000,
    0x4d557ac800000000, 0x2476ca9400000000, 0xb1a2ba0100000000,
    0x4fd95a6500000000, 0xda0d2af000000000, 0x9d9f3adc00000000,
    0x084b4a4900000000, 0xf630aa2d00000000, 0x63e4dab800000000,
    0x0ac76ae400000000, 0x9f131a7100000000, 0x6168fa1500000000,
    0xf4bc8a8000000000},
   {0x0000000000000000, 0x1f17f08000000000, 0x7f2891da00000000,
    0x603f615a00000000, 0xbf56536e00000000, 0xa041a3ee00000000,
    0xc07ec2b400000000, 0xdf69323400000000, 0x7eada6dc00000000,
    0x61ba565c00000000, 0x0185370600000000, 0x1e92c78600000000,
    0xc1fbf5b200000000, 0xdeec053200000000, 0xbed3646800000000,
    0xa1c494e800000000, 0xbd5c3c6200000000, 0xa24bcce200000000,
    0xc274adb800000000, 0xdd635d3800000000, 0x020a6f0c00000000,
    0x1d1d9f8c00000000, 0x7d22fed600000000, 0x62350e5600000000,
    0xc3f19abe00000000, 0xdce66a3e00000000, 0xbcd90b6400000000,
    0xa3cefbe400000000, 0x7ca7c9d000000000, 0x63b0395000000000,
    0x038f580a00000000, 0x1c98a88a00000000, 0x7ab978c400000000,
    0x65ae884400000000, 0x0591e91e00000000, 0x1a86199e00000000,
    0xc5ef2baa00000000, 0xdaf8db2a00000000, 0xbac7ba7000000000,
    0xa5d04af000000000, 0x0414de1800000000, 0x1b032e9800000000,
    0x7b3c4fc200000000, 0x642bbf4200000000, 0xbb428d7600000000,
    0xa4557df600000000, 0xc46a1cac00000000, 0xdb7dec2c00000000,
    0xc7e544a600000000, 0xd8f2b42600000000, 0xb8cdd57c00000000,
    0xa7da25fc00000000, 0x78b317c800000000, 0x67a4e74800000000,
    0x079b861200000000, 0x188c769200000000, 0xb948e27a00000000,
    0xa65f12fa00000000, 0xc66073a000000000, 0xd977832000000000,
    0x061eb11400000000, 0x1909419400000000, 0x793620ce00000000,
    0x6621d04e00000000, 0xb574805300000000, 0xaa6370d300000000,
    0xca5c118900000000, 0xd54be10900000000, 0x0a22d33d00000000,
    0x153523bd00000000, 0x750a42e700000000, 0x6a1db26700000000,
    0xcbd9268f00000000, 0xd4ced60f00000000, 0xb4f1b75500000000,
    0xabe647d500000000, 0x748f75e100000000, 0x6b98856100000000,
    0x0ba7e43b00000000, 0x14b014bb00000000, 0x0828bc3100000000,
    0x173f4cb100000000, 0x77002deb00000000, 0x6817dd6b00000000,
    0xb77eef5f00000000, 0xa8691fdf00000000, 0xc8567e8500000000,
    0xd7418e0500000000, 0x76851aed00000000, 0x6992ea6d00000000,
    0x09ad8b3700000000, 0x16ba7bb700000000, 0xc9d3498300000000,
    0xd6c4b90300000000, 0xb6fbd85900000000, 0xa9ec28d900000000,
    0xcfcdf89700000000, 0xd0da081700000000, 0xb0e5694d00000000,
    0xaff299cd00000000, 0x709babf900000000, 0x6f8c5b7900000000,
    0x0fb33a2300000000, 0x10a4caa300000000, 0xb1605e4b00000000,
    0xae77aecb00000000, 0xce48cf9100000000, 0xd15f3f1100000000,
    0x0e360d2500000000, 0x1121fda500000000, 0x711e9cff00000000,
    0x6e096c7f00000000, 0x7291c4f500000000, 0x6d86347500000000,
    0x0db9552f00000000, 0x12aea5af00000000, 0xcdc7979b00000000,
    0xd2d0671b00000000, 0xb2ef064100000000, 0xadf8f6c100000000,
    0x0c3c622900000000, 0x132b92a900000000, 0x7314f3f300000000,
    0x6c03037300000000, 0xb36a314700000000, 0xac7dc1c700000000,
    0xcc42a09d00000000, 0xd355501d00000000, 0x6ae900a700000000,
    0x75fef02700000000, 0x15c1917d00000000, 0x0ad661fd00000000,
    0xd5bf53c900000000, 0xcaa8a34900000000, 0xaa97c21300000000,
    0xb580329300000000, 0x1444a67b00000000, 0x0b5356fb00000000,
    0x6b6c37a100000000, 0x747bc72100000000, 0xab12f51500000000,
    0xb405059500000000, 0xd43a64cf00000000, 0xcb2d944f00000000,
    0xd7b53cc500000000, 0xc8a2cc4500000000, 0xa89dad1f00000000,
    0xb78a5d9f00000000, 0x68e36fab00000000, 0x77f49f2b00000000,
    0x17cbfe7100000000, 0x08dc0ef100000000, 0xa9189a1900000000,
    0xb60f6a9900000000, 0xd6300bc300000000, 0xc927fb4300000000,
    0x164ec97700000000, 0x095939f700000000, 0x696658ad00000000,
    0x7671a82d00000000, 0x1050786300000000, 0x0f4788e300000000,
    0x6f78e9b900000000, 0x706f193900000000, 0xaf062b0d00000000,
    0xb011db8d00000000, 0xd02ebad700000000, 0xcf394a5700000000,
    0x6efddebf00000000, 0x71ea2e3f00000000, 0x11d54f6500000000,
    0x0ec2bfe500000000, 0xd1ab8dd100000000, 0xcebc7d5100000000,
    0xae831c0b00000000, 0xb194ec8b00000000, 0xad0c440100000000,
    0xb21bb48100000000, 0xd224d5db00000000, 0xcd33255b00000000,
    0x125a176f00000000, 0x0d4de7ef00000000, 0x6d7286b500000000,
    0x7265763500000000, 0xd3a1e2dd00000000, 0xccb6125d00000000,
    0xac89730700000000, 0xb39e838700000000, 0x6cf7b1b300000000,
    0x73e0413300000000, 0x13df206900000000, 0x0cc8d0e900000000,
    0xdf9d80f400000000, 0xc08a707400000000, 0xa0b5112e00000000,
    0xbfa2e1ae00000000, 0x60cbd39a00000000, 0x7fdc231a00000000,
    0x1fe3424000000000, 0x00f4b2c000000000, 0xa130262800000000,
    0xbe27d6a800000000, 0xde18b7f200000000, 0xc10f477200000000,
    0x1e66754600000000, 0x017185c600000000, 0x614ee49c00000000,
    0x7e59141c00000000, 0x62c1bc9600000000, 0x7dd64c1600000000,
    0x1de92d4c00000000, 0x02feddcc00000000, 0xdd97eff800000000,
    0xc2801f7800000000, 0xa2bf7e2200000000, 0xbda88ea200000000,
    0x1c6c1a4a00000000, 0x037beaca00000000, 0x63448b9000000000,
    0x7c537b1000000000, 0xa33a492400000000, 0xbc2db9a400000000,
    0xdc12d8fe00000000, 0xc305287e00000000, 0xa524f83000000000,
    0xba3308b000000000, 0xda0c69ea00000000, 0xc51b996a00000000,
    0x1a72ab5e00000000, 0x05655bde00000000, 0x655a3a8400000000,
    0x7a4dca0400000000, 0xdb895eec00000000, 0xc49eae6c00000000,
    0xa4a1cf3600000000, 0xbbb63fb600000000, 0x64df0d8200000000,
    0x7bc8fd0200000000, 0x1bf79c5800000000, 0x04e06cd800000000,
    0x1878c45200000000, 0x076f34d200000000, 0x6750558800000000,
    0x7847a50800000000, 0xa72e973c00000000, 0xb83967bc00000000,
    0xd80606e600000000, 0xc711f66600000000, 0x66d5628e00000000,
    0x79c2920e00000000, 0x19fdf35400000000, 0x06ea03d400000000,
    0xd98331e000000000, 0xc694c16000000000, 0xa6aba03a00000000,
    0xb9bc50ba00000000},
  {
    0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
   {0x0000000000000000, 0xe2fd888d00000000, 0x85fd60c000000000,
    0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
    0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
    0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
    0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
    0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
    0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
    0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
    0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
    0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
    0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
    0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
    0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
    0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
    0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
    0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
    0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
    0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
    0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
    0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
    0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
    0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
    0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
    0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
    0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
    0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
    0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
    0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
    0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
    0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
    0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
    0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
    0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
    0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
    0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
    0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
    0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
    0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
    0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
    0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
    0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
    0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
    0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
    0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
    0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
    0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
    0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
    0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
    0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
    0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
    0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
    0xed3498beUL
  },
  {
    0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
    0x6700e84d00000000, 0x4bfdb05b00000000, 0xa90038d600000000,
    0xce00d09b00000000, 0x2cfd581600000000, 0x96fa61b700000000,
    0x7407e93a00000000, 0x1307017700000000, 0xf1fa89fa00000000,
    0xdd07d1ec00000000, 0x3ffa596100000000, 0x58fab12c00000000,
    0xba0739a100000000, 0x6df3b2b500000000, 0x8f0e3a3800000000,
    0xe80ed27500000000, 0x0af35af800000000, 0x260e02ee00000000,
    0xc4f38a6300000000, 0xa3f3622e00000000, 0x410eeaa300000000,
    0xfb09d30200000000, 0x19f45b8f00000000, 0x7ef4b3c200000000,
    0x9c093b4f00000000, 0xb0f4635900000000, 0x5209ebd400000000,
    0x3509039900000000, 0xd7f48b1400000000, 0x9be014b000000000,
    0x791d9c3d00000000, 0x1e1d747000000000, 0xfce0fcfd00000000,
    0xd01da4eb00000000, 0x32e02c6600000000, 0x55e0c42b00000000,
    0xb71d4ca600000000, 0x0d1a750700000000, 0xefe7fd8a00000000,
    0x88e715c700000000, 0x6a1a9d4a00000000, 0x46e7c55c00000000,
    0xa41a4dd100000000, 0xc31aa59c00000000, 0x21e72d1100000000,
    0xf613a60500000000, 0x14ee2e8800000000, 0x73eec6c500000000,
    0x91134e4800000000, 0xbdee165e00000000, 0x5f139ed300000000,
    0x3813769e00000000, 0xdaeefe1300000000, 0x60e9c7b200000000,
    0x82144f3f00000000, 0xe514a77200000000, 0x07e92fff00000000,
    0x2b1477e900000000, 0xc9e9ff6400000000, 0xaee9172900000000,
    0x4c149fa400000000, 0x77c758bb00000000, 0x953ad03600000000,
    0xf23a387b00000000, 0x10c7b0f600000000, 0x3c3ae8e000000000,
    0xdec7606d00000000, 0xb9c7882000000000, 0x5b3a00ad00000000,
    0xe13d390c00000000, 0x03c0b18100000000, 0x64c059cc00000000,
    0x863dd14100000000, 0xaac0895700000000, 0x483d01da00000000,
    0x2f3de99700000000, 0xcdc0611a00000000, 0x1a34ea0e00000000,
    0xf8c9628300000000, 0x9fc98ace00000000, 0x7d34024300000000,
    0x51c95a5500000000, 0xb334d2d800000000, 0xd4343a9500000000,
    0x36c9b21800000000, 0x8cce8bb900000000, 0x6e33033400000000,
    0x0933eb7900000000, 0xebce63f400000000, 0xc7333be200000000,
    0x25ceb36f00000000, 0x42ce5b2200000000, 0xa033d3af00000000,
    0xec274c0b00000000, 0x0edac48600000000, 0x69da2ccb00000000,
    0x8b27a44600000000, 0xa7dafc5000000000, 0x452774dd00000000,
    0x22279c9000000000, 0xc0da141d00000000, 0x7add2dbc00000000,
    0x9820a53100000000, 0xff204d7c00000000, 0x1dddc5f100000000,
    0x31209de700000000, 0xd3dd156a00000000, 0xb4ddfd2700000000,
    0x562075aa00000000, 0x81d4febe00000000, 0x6329763300000000,
    0x04299e7e00000000, 0xe6d416f300000000, 0xca294ee500000000,
    0x28d4c66800000000, 0x4fd42e2500000000, 0xad29a6a800000000,
    0x172e9f0900000000, 0xf5d3178400000000, 0x92d3ffc900000000,
    0x702e774400000000, 0x5cd32f5200000000, 0xbe2ea7df00000000,
    0xd92e4f9200000000, 0x3bd3c71f00000000, 0xaf88c0ad00000000,
    0x4d75482000000000, 0x2a75a06d00000000, 0xc88828e000000000,
    0xe47570f600000000, 0x0688f87b00000000, 0x6188103600000000,
    0x837598bb00000000, 0x3972a11a00000000, 0xdb8f299700000000,
    0xbc8fc1da00000000, 0x5e72495700000000, 0x728f114100000000,
    0x907299cc00000000, 0xf772718100000000, 0x158ff90c00000000,
    0xc27b721800000000, 0x2086fa9500000000, 0x478612d800000000,
    0xa57b9a5500000000, 0x8986c24300000000, 0x6b7b4ace00000000,
    0x0c7ba28300000000, 0xee862a0e00000000, 0x548113af00000000,
    0xb67c9b2200000000, 0xd17c736f00000000, 0x3381fbe200000000,
    0x1f7ca3f400000000, 0xfd812b7900000000, 0x9a81c33400000000,
    0x787c4bb900000000, 0x3468d41d00000000, 0xd6955c9000000000,
    0xb195b4dd00000000, 0x53683c5000000000, 0x7f95644600000000,
    0x9d68eccb00000000, 0xfa68048600000000, 0x18958c0b00000000,
    0xa292b5aa00000000, 0x406f3d2700000000, 0x276fd56a00000000,
    0xc5925de700000000, 0xe96f05f100000000, 0x0b928d7c00000000,
    0x6c92653100000000, 0x8e6fedbc00000000, 0x599b66a800000000,
    0xbb66ee2500000000, 0xdc66066800000000, 0x3e9b8ee500000000,
    0x1266d6f300000000, 0xf09b5e7e00000000, 0x979bb63300000000,
    0x75663ebe00000000, 0xcf61071f00000000, 0x2d9c8f9200000000,
    0x4a9c67df00000000, 0xa861ef5200000000, 0x849cb74400000000,
    0x66613fc900000000, 0x0161d78400000000, 0xe39c5f0900000000,
    0xd84f981600000000, 0x3ab2109b00000000, 0x5db2f8d600000000,
    0xbf4f705b00000000, 0x93b2284d00000000, 0x714fa0c000000000,
    0x164f488d00000000, 0xf4b2c00000000000, 0x4eb5f9a100000000,
    0xac48712c00000000, 0xcb48996100000000, 0x29b511ec00000000,
    0x054849fa00000000, 0xe7b5c17700000000, 0x80b5293a00000000,
    0x6248a1b700000000, 0xb5bc2aa300000000, 0x5741a22e00000000,
    0x30414a6300000000, 0xd2bcc2ee00000000, 0xfe419af800000000,
    0x1cbc127500000000, 0x7bbcfa3800000000, 0x994172b500000000,
    0x23464b1400000000, 0xc1bbc39900000000, 0xa6bb2bd400000000,
    0x4446a35900000000, 0x68bbfb4f00000000, 0x8a4673c200000000,
    0xed469b8f00000000, 0x0fbb130200000000, 0x43af8ca600000000,
    0xa152042b00000000, 0xc652ec6600000000, 0x24af64eb00000000,
    0x08523cfd00000000, 0xeaafb47000000000, 0x8daf5c3d00000000,
    0x6f52d4b000000000, 0xd555ed1100000000, 0x37a8659c00000000,
    0x50a88dd100000000, 0xb255055c00000000, 0x9ea85d4a00000000,
    0x7c55d5c700000000, 0x1b553d8a00000000, 0xf9a8b50700000000,
    0x2e5c3e1300000000, 0xcca1b69e00000000, 0xaba15ed300000000,
    0x495cd65e00000000, 0x65a18e4800000000, 0x875c06c500000000,
    0xe05cee8800000000, 0x02a1660500000000, 0xb8a65fa400000000,
    0x5a5bd72900000000, 0x3d5b3f6400000000, 0xdfa6b7e900000000,
    0xf35befff00000000, 0x11a6677200000000, 0x76a68f3f00000000,
    0x945b07b200000000},
   {0x0000000000000000, 0xa90b894e00000000, 0x5217129d00000000,
    0xfb1c9bd300000000, 0xe52855e100000000, 0x4c23dcaf00000000,
    0xb73f477c00000000, 0x1e34ce3200000000, 0x8b57db1900000000,
    0x225c525700000000, 0xd940c98400000000, 0x704b40ca00000000,
    0x6e7f8ef800000000, 0xc77407b600000000, 0x3c689c6500000000,
    0x9563152b00000000, 0x16afb63300000000, 0xbfa43f7d00000000,
    0x44b8a4ae00000000, 0xedb32de000000000, 0xf387e3d200000000,
    0x5a8c6a9c00000000, 0xa190f14f00000000, 0x089b780100000000,
    0x9df86d2a00000000, 0x34f3e46400000000, 0xcfef7fb700000000,
    0x66e4f6f900000000, 0x78d038cb00000000, 0xd1dbb18500000000,
    0x2ac72a5600000000, 0x83cca31800000000, 0x2c5e6d6700000000,
    0x8555e42900000000, 0x7e497ffa00000000, 0xd742f6b400000000,
    0xc976388600000000, 0x607db1c800000000, 0x9b612a1b00000000,
    0x326aa35500000000, 0xa709b67e00000000, 0x0e023f3000000000,
    0xf51ea4e300000000, 0x5c152dad00000000, 0x4221e39f00000000,
    0xeb2a6ad100000000, 0x1036f10200000000, 0xb93d784c00000000,
    0x3af1db5400000000, 0x93fa521a00000000, 0x68e6c9c900000000,
    0xc1ed408700000000, 0xdfd98eb500000000, 0x76d207fb00000000,
    0x8dce9c2800000000, 0x24c5156600000000, 0xb1a6004d00000000,
    0x18ad890300000000, 0xe3b112d000000000, 0x4aba9b9e00000000,
    0x548e55ac00000000, 0xfd85dce200000000, 0x0699473100000000,
    0xaf92ce7f00000000, 0x58bcdace00000000, 0xf1b7538000000000,
    0x0aabc85300000000, 0xa3a0411d00000000, 0xbd948f2f00000000,
    0x149f066100000000, 0xef839db200000000, 0x468814fc00000000,
    0xd3eb01d700000000, 0x7ae0889900000000, 0x81fc134a00000000,
    0x28f79a0400000000, 0x36c3543600000000, 0x9fc8dd7800000000,
    0x64d446ab00000000, 0xcddfcfe500000000, 0x4e136cfd00000000,
    0xe718e5b300000000, 0x1c047e6000000000, 0xb50ff72e00000000,
    0xab3b391c00000000, 0x0230b05200000000, 0xf92c2b8100000000,
    0x5027a2cf00000000, 0xc544b7e400000000, 0x6c4f3eaa00000000,
    0x9753a57900000000, 0x3e582c3700000000, 0x206ce20500000000,
    0x89676b4b00000000, 0x727bf09800000000, 0xdb7079d600000000,
    0x74e2b7a900000000, 0xdde93ee700000000, 0x26f5a53400000000,
    0x8ffe2c7a00000000, 0x91cae24800000000, 0x38c16b0600000000,
    0xc3ddf0d500000000, 0x6ad6799b00000000, 0xffb56cb000000000,
    0x56bee5fe00000000, 0xada27e2d00000000, 0x04a9f76300000000,
    0x1a9d395100000000, 0xb396b01f00000000, 0x488a2bcc00000000,
    0xe181a28200000000, 0x624d019a00000000, 0xcb4688d400000000,
    0x305a130700000000, 0x99519a4900000000, 0x8765547b00000000,
    0x2e6edd3500000000, 0xd57246e600000000, 0x7c79cfa800000000,
    0xe91ada8300000000, 0x401153cd00000000, 0xbb0dc81e00000000,
    0x1206415000000000, 0x0c328f6200000000, 0xa539062c00000000,
    0x5e259dff00000000, 0xf72e14b100000000, 0xf17ec44600000000,
    0x58754d0800000000, 0xa369d6db00000000, 0x0a625f9500000000,
    0x145691a700000000, 0xbd5d18e900000000, 0x4641833a00000000,
    0xef4a0a7400000000, 0x7a291f5f00000000, 0xd322961100000000,
    0x283e0dc200000000, 0x8135848c00000000, 0x9f014abe00000000,
    0x360ac3f000000000, 0xcd16582300000000, 0x641dd16d00000000,
    0xe7d1727500000000, 0x4edafb3b00000000, 0xb5c660e800000000,
    0x1ccde9a600000000, 0x02f9279400000000, 0xabf2aeda00000000,
    0x50ee350900000000, 0xf9e5bc4700000000, 0x6c86a96c00000000,
    0xc58d202200000000, 0x3e91bbf100000000, 0x979a32bf00000000,
    0x89aefc8d00000000, 0x20a575c300000000, 0xdbb9ee1000000000,
    0x72b2675e00000000, 0xdd20a92100000000, 0x742b206f00000000,
    0x8f37bbbc00000000, 0x263c32f200000000, 0x3808fcc000000000,
    0x9103758e00000000, 0x6a1fee5d00000000, 0xc314671300000000,
    0x5677723800000000, 0xff7cfb7600000000, 0x046060a500000000,
    0xad6be9eb00000000, 0xb35f27d900000000, 0x1a54ae9700000000,
    0xe148354400000000, 0x4843bc0a00000000, 0xcb8f1f1200000000,
    0x6284965c00000000, 0x99980d8f00000000, 0x309384c100000000,
    0x2ea74af300000000, 0x87acc3bd00000000, 0x7cb0586e00000000,
    0xd5bbd12000000000, 0x40d8c40b00000000, 0xe9d34d4500000000,
    0x12cfd69600000000, 0xbbc45fd800000000, 0xa5f091ea00000000,
    0x0cfb18a400000000, 0xf7e7837700000000, 0x5eec0a3900000000,
    0xa9c21e8800000000, 0x00c997c600000000, 0xfbd50c1500000000,
    0x52de855b00000000, 0x4cea4b6900000000, 0xe5e1c22700000000,
    0x1efd59f400000000, 0xb7f6d0ba00000000, 0x2295c59100000000,
    0x8b9e4cdf00000000, 0x7082d70c00000000, 0xd9895e4200000000,
    0xc7bd907000000000, 0x6eb6193e00000000, 0x95aa82ed00000000,
    0x3ca10ba300000000, 0xbf6da8bb00000000, 0x166621f500000000,
    0xed7aba2600000000, 0x4471336800000000, 0x5a45fd5a00000000,
    0xf34e741400000000, 0x0852efc700000000, 0xa159668900000000,
    0x343a73a200000000, 0x9d31faec00000000, 0x662d613f00000000,
    0xcf26e87100000000, 0xd112264300000000, 0x7819af0d00000000,
    0x830534de00000000, 0x2a0ebd9000000000, 0x859c73ef00000000,
    0x2c97faa100000000, 0xd78b617200000000, 0x7e80e83c00000000,
    0x60b4260e00000000, 0xc9bfaf4000000000, 0x32a3349300000000,
    0x9ba8bddd00000000, 0x0ecba8f600000000, 0xa7c021b800000000,
    0x5cdcba6b00000000, 0xf5d7332500000000, 0xebe3fd1700000000,
    0x42e8745900000000, 0xb9f4ef8a00000000, 0x10ff66c400000000,
    0x9333c5dc00000000, 0x3a384c9200000000, 0xc124d74100000000,
    0x682f5e0f00000000, 0x761b903d00000000, 0xdf10197300000000,
    0x240c82a000000000, 0x8d070bee00000000, 0x18641ec500000000,
    0xb16f978b00000000, 0x4a730c5800000000, 0xe378851600000000,
    0xfd4c4b2400000000, 0x5447c26a00000000, 0xaf5b59b900000000,
    0x0650d0f700000000},
   {0x0000000000000000, 0x479244af00000000, 0xcf22f88500000000,
    0x88b0bc2a00000000, 0xdf4381d000000000, 0x98d1c57f00000000,
    0x1061795500000000, 0x57f33dfa00000000, 0xff81737a00000000,
    0xb81337d500000000, 0x30a38bff00000000, 0x7731cf5000000000,
    0x20c2f2aa00000000, 0x6750b60500000000, 0xefe00a2f00000000,
    0xa8724e8000000000, 0xfe03e7f400000000, 0xb991a35b00000000,
    0x31211f7100000000, 0x76b35bde00000000, 0x2140662400000000,
    0x66d2228b00000000, 0xee629ea100000000, 0xa9f0da0e00000000,
    0x0182948e00000000, 0x4610d02100000000, 0xcea06c0b00000000,
    0x893228a400000000, 0xdec1155e00000000, 0x995351f100000000,
    0x11e3eddb00000000, 0x5671a97400000000, 0xbd01bf3200000000,
    0xfa93fb9d00000000, 0x722347b700000000, 0x35b1031800000000,
    0x62423ee200000000, 0x25d07a4d00000000, 0xad60c66700000000,
    0xeaf282c800000000, 0x4280cc4800000000, 0x051288e700000000,
    0x8da234cd00000000, 0xca30706200000000, 0x9dc34d9800000000,
    0xda51093700000000, 0x52e1b51d00000000, 0x1573f1b200000000,
    0x430258c600000000, 0x04901c6900000000, 0x8c20a04300000000,
    0xcbb2e4ec00000000, 0x9c41d91600000000, 0xdbd39db900000000,
    0x5363219300000000, 0x14f1653c00000000, 0xbc832bbc00000000,
    0xfb116f1300000000, 0x73a1d33900000000, 0x3433979600000000,
    0x63c0aa6c00000000, 0x2452eec300000000, 0xace252e900000000,
    0xeb70164600000000, 0x7a037e6500000000, 0x3d913aca00000000,
    0xb52186e000000000, 0xf2b3c24f00000000, 0xa540ffb500000000,
    0xe2d2bb1a00000000, 0x6a62073000000000, 0x2df0439f00000000,
    0x85820d1f00000000, 0xc21049b000000000, 0x4aa0f59a00000000,
    0x0d32b13500000000, 0x5ac18ccf00000000, 0x1d53c86000000000,
    0x95e3744a00000000, 0xd27130e500000000, 0x8400999100000000,
    0xc392dd3e00000000, 0x4b22611400000000, 0x0cb025bb00000000,
    0x5b43184100000000, 0x1cd15cee00000000, 0x9461e0c400000000,
    0xd3f3a46b00000000, 0x7b81eaeb00000000, 0x3c13ae4400000000,
    0xb4a3126e00000000, 0xf33156c100000000, 0xa4c26b3b00000000,
    0xe3502f9400000000, 0x6be093be00000000, 0x2c72d71100000000,
    0xc702c15700000000, 0x809085f800000000, 0x082039d200000000,
    0x4fb27d7d00000000, 0x1841408700000000, 0x5fd3042800000000,
    0xd763b80200000000, 0x90f1fcad00000000, 0x3883b22d00000000,
    0x7f11f68200000000, 0xf7a14aa800000000, 0xb0330e0700000000,
    0xe7c033fd00000000, 0xa052775200000000, 0x28e2cb7800000000,
    0x6f708fd700000000, 0x390126a300000000, 0x7e93620c00000000,
    0xf623de2600000000, 0xb1b19a8900000000, 0xe642a77300000000,
    0xa1d0e3dc00000000, 0x29605ff600000000, 0x6ef21b5900000000,
    0xc68055d900000000, 0x8112117600000000, 0x09a2ad5c00000000,
    0x4e30e9f300000000, 0x19c3d40900000000, 0x5e5190a600000000,
    0xd6e12c8c00000000, 0x9173682300000000, 0xf406fcca00000000,
    0xb394b86500000000, 0x3b24044f00000000, 0x7cb640e000000000,
    0x2b457d1a00000000, 0x6cd739b500000000, 0xe467859f00000000,
    0xa3f5c13000000000, 0x0b878fb000000000, 0x4c15cb1f00000000,
    0xc4a5773500000000, 0x8337339a00000000, 0xd4c40e6000000000,
    0x93564acf00000000, 0x1be6f6e500000000, 0x5c74b24a00000000,
    0x0a051b3e00000000, 0x4d975f9100000000, 0xc527e3bb00000000,
    0x82b5a71400000000, 0xd5469aee00000000, 0x92d4de4100000000,
    0x1a64626b00000000, 0x5df626c400000000, 0xf584684400000000,
    0xb2162ceb00000000, 0x3aa690c100000000, 0x7d34d46e00000000,
    0x2ac7e99400000000, 0x6d55ad3b00000000, 0xe5e5111100000000,
    0xa27755be00000000, 0x490743f800000000, 0x0e95075700000000,
    0x8625bb7d00000000, 0xc1b7ffd200000000, 0x9644c22800000000,
    0xd1d6868700000000, 0x59663aad00000000, 0x1ef47e0200000000,
    0xb686308200000000, 0xf114742d00000000, 0x79a4c80700000000,
    0x3e368ca800000000, 0x69c5b15200000000, 0x2e57f5fd00000000,
    0xa6e749d700000000, 0xe1750d7800000000, 0xb704a40c00000000,
    0xf096e0a300000000, 0x78265c8900000000, 0x3fb4182600000000,
    0x684725dc00000000, 0x2fd5617300000000, 0xa765dd5900000000,
    0xe0f799f600000000, 0x4885d77600000000, 0x0f1793d900000000,
    0x87a72ff300000000, 0xc0356b5c00000000, 0x97c656a600000000,
    0xd054120900000000, 0x58e4ae2300000000, 0x1f76ea8c00000000,
    0x8e0582af00000000, 0xc997c60000000000, 0x41277a2a00000000,
    0x06b53e8500000000, 0x5146037f00000000, 0x16d447d000000000,
    0x9e64fbfa00000000, 0xd9f6bf5500000000, 0x7184f1d500000000,
    0x3616b57a00000000, 0xbea6095000000000, 0xf9344dff00000000,
    0xaec7700500000000, 0xe95534aa00000000, 0x61e5888000000000,
    0x2677cc2f00000000, 0x7006655b00000000, 0x379421f400000000,
    0xbf249dde00000000, 0xf8b6d97100000000, 0xaf45e48b00000000,
    0xe8d7a02400000000, 0x60671c0e00000000, 0x27f558a100000000,
    0x8f87162100000000, 0xc815528e00000000, 0x40a5eea400000000,
    0x0737aa0b00000000, 0x50c497f100000000, 0x1756d35e00000000,
    0x9fe66f7400000000, 0xd8742bdb00000000, 0x33043d9d00000000,
    0x7496793200000000, 0xfc26c51800000000, 0xbbb481b700000000,
    0xec47bc4d00000000, 0xabd5f8e200000000, 0x236544c800000000,
    0x64f7006700000000, 0xcc854ee700000000, 0x8b170a4800000000,
    0x03a7b66200000000, 0x4435f2cd00000000, 0x13c6cf3700000000,
    0x54548b9800000000, 0xdce437b200000000, 0x9b76731d00000000,
    0xcd07da6900000000, 0x8a959ec600000000, 0x022522ec00000000,
    0x45b7664300000000, 0x12445bb900000000, 0x55d61f1600000000,
    0xdd66a33c00000000, 0x9af4e79300000000, 0x3286a91300000000,
    0x7514edbc00000000, 0xfda4519600000000, 0xba36153900000000,
    0xedc528c300000000, 0xaa576c6c00000000, 0x22e7d04600000000,
    0x657594e900000000}};

#else /* W == 4 */

local const z_crc_t FAR crc_braid_table[][256] = {
   {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59,
    0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4,
    0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67,
    0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef,
    0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97,
    0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88,
    0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687,
    0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698,
    0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0,
    0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068,
    0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb,
    0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056,
    0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016,
    0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009,
    0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028,
    0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037,
    0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a,
    0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7,
    0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054,
    0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7,
    0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af,
    0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0,
    0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4,
    0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab,
    0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3,
    0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a,
    0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9,
    0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54,
    0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09,
    0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16,
    0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37,
    0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28,
    0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e,
    0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3,
    0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40,
    0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8,
    0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0,
    0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf,
    0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6,
    0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9,
    0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1,
    0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059,
    0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca,
    0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067,
    0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031,
    0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e,
    0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f,
    0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010,
    0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d,
    0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0,
    0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073,
    0xd8ac6b35},
   {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2,
    0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd,
    0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696,
    0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3,
    0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f,
    0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35,
    0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5,
    0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f,
    0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673,
    0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46,
    0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d,
    0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632,
    0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28,
    0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192,
    0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c,
    0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6,
    0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0,
    0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff,
    0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4,
    0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95,
    0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9,
    0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03,
    0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7,
    0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d,
    0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151,
    0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808,
    0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343,
    0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c,
    0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a,
    0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0,
    0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e,
    0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594,
    0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6,
    0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399,
    0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2,
    0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7,
    0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb,
    0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571,
    0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289,
    0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33,
    0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f,
    0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a,
    0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461,
    0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e,
    0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c,
    0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6,
    0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918,
    0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2,
    0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484,
    0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb,
    0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0,
    0xa140efa8},
   {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706,
    0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed,
    0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289,
    0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a,
    0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214,
    0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3,
    0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3,
    0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254,
    0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a,
    0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9,
    0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad,
    0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746,
    0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060,
    0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187,
    0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef,
    0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408,
    0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e,
    0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495,
    0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1,
    0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532,
    0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c,
    0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb,
    0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb,
    0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c,
    0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42,
    0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060,
    0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04,
    0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef,
    0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99,
    0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e,
    0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16,
    0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1,
    0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7,
    0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c,
    0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38,
    0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb,
    0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5,
    0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42,
    0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62,
    0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85,
    0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb,
    0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18,
    0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c,
    0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997,
    0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1,
    0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36,
    0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e,
    0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9,
    0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf,
    0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24,
    0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040,
    0x917cd6a1},
   {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf,
    0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd,
    0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896,
    0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9,
    0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3,
    0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f,
    0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d,
    0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1,
    0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab,
    0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4,
    0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f,
    0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d,
    0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4,
    0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978,
    0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad,
    0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621,
    0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46,
    0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854,
    0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f,
    0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a,
    0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890,
    0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c,
    0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4,
    0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238,
    0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622,
    0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab,
    0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0,
    0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2,
    0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295,
    0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19,
    0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc,
    0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140,
    0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd,
    0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf,
    0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184,
    0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb,
    0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1,
    0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d,
    0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb,
    0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257,
    0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d,
    0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22,
    0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069,
    0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b,
    0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6,
    0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a,
    0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf,
    0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33,
    0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254,
    0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146,
    0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d,
    0x18ba364e}};

local const z_word_t FAR crc_braid_big_table[][256] = {
   {0x00000000, 0x43cba687, 0xc7903cd4, 0x845b9a53, 0xcf270873,
    0x8cecaef4, 0x08b734a7, 0x4b7c9220, 0x9e4f10e6, 0xdd84b661,
    0x59df2c32, 0x1a148ab5, 0x51681895, 0x12a3be12, 0x96f82441,
    0xd53382c6, 0x7d995117, 0x3e52f790, 0xba096dc3, 0xf9c2cb44,
    0xb2be5964, 0xf175ffe3, 0x752e65b0, 0x36e5c337, 0xe3d641f1,
    0xa01de776, 0x24467d25, 0x678ddba2, 0x2cf14982, 0x6f3aef05,
    0xeb617556, 0xa8aad3d1, 0xfa32a32e, 0xb9f905a9, 0x3da29ffa,
    0x7e69397d, 0x3515ab5d, 0x76de0dda, 0xf2859789, 0xb14e310e,
    0x647db3c8, 0x27b6154f, 0xa3ed8f1c, 0xe026299b, 0xab5abbbb,
    0xe8911d3c, 0x6cca876f, 0x2f0121e8, 0x87abf239, 0xc46054be,
    0x403bceed, 0x03f0686a, 0x488cfa4a, 0x0b475ccd, 0x8f1cc69e,
    0xccd76019, 0x19e4e2df, 0x5a2f4458, 0xde74de0b, 0x9dbf788c,
    0xd6c3eaac, 0x95084c2b, 0x1153d678, 0x529870ff, 0xf465465d,
    0xb7aee0da, 0x33f57a89, 0x703edc0e, 0x3b424e2e, 0x7889e8a9,
    0xfcd272fa, 0xbf19d47d, 0x6a2a56bb, 0x29e1f03c, 0xadba6a6f,
    0xee71cce8, 0xa50d5ec8, 0xe6c6f84f, 0x629d621c, 0x2156c49b,
    0x89fc174a, 0xca37b1cd, 0x4e6c2b9e, 0x0da78d19, 0x46db1f39,
    0x0510b9be, 0x814b23ed, 0xc280856a, 0x17b307ac, 0x5478a12b,
    0xd0233b78, 0x93e89dff, 0xd8940fdf, 0x9b5fa958, 0x1f04330b,
    0x5ccf958c, 0x0e57e573, 0x4d9c43f4, 0xc9c7d9a7, 0x8a0c7f20,
    0xc170ed00, 0x82bb4b87, 0x06e0d1d4, 0x452b7753, 0x9018f595,
    0xd3d35312, 0x5788c941, 0x14436fc6, 0x5f3ffde6, 0x1cf45b61,
    0x98afc132, 0xdb6467b5, 0x73ceb464, 0x300512e3, 0xb45e88b0,
    0xf7952e37, 0xbce9bc17, 0xff221a90, 0x7b7980c3, 0x38b22644,
    0xed81a482, 0xae4a0205, 0x2a119856, 0x69da3ed1, 0x22a6acf1,
    0x616d0a76, 0xe5369025, 0xa6fd36a2, 0xe8cb8cba, 0xab002a3d,
    0x2f5bb06e, 0x6c9016e9, 0x27ec84c9, 0x6427224e, 0xe07cb81d,
    0xa3b71e9a, 0x76849c5c, 0x354f3adb, 0xb114a088, 0xf2df060f,
    0xb9a3942f, 0xfa6832a8, 0x7e33a8fb, 0x3df80e7c, 0x9552ddad,
    0xd6997b2a, 0x52c2e179, 0x110947fe, 0x5a75d5de, 0x19be7359,
    0x9de5e90a, 0xde2e4f8d, 0x0b1dcd4b, 0x48d66bcc, 0xcc8df19f,
    0x8f465718, 0xc43ac538, 0x87f163bf, 0x03aaf9ec, 0x40615f6b,
    0x12f92f94, 0x51328913, 0xd5691340, 0x96a2b5c7, 0xddde27e7,
    0x9e158160, 0x1a4e1b33, 0x5985bdb4, 0x8cb63f72, 0xcf7d99f5,
    0x4b2603a6, 0x08eda521, 0x43913701, 0x005a9186, 0x84010bd5,
    0xc7caad52, 0x6f607e83, 0x2cabd804, 0xa8f04257, 0xeb3be4d0,
    0xa04776f0, 0xe38cd077, 0x67d74a24, 0x241ceca3, 0xf12f6e65,
    0xb2e4c8e2, 0x36bf52b1, 0x7574f436, 0x3e086616, 0x7dc3c091,
    0xf9985ac2, 0xba53fc45, 0x1caecae7, 0x5f656c60, 0xdb3ef633,
    0x98f550b4, 0xd389c294, 0x90426413, 0x1419fe40, 0x57d258c7,
    0x82e1da01, 0xc12a7c86, 0x4571e6d5, 0x06ba4052, 0x4dc6d272,
    0x0e0d74f5, 0x8a56eea6, 0xc99d4821, 0x61379bf0, 0x22fc3d77,
    0xa6a7a724, 0xe56c01a3, 0xae109383, 0xeddb3504, 0x6980af57,
    0x2a4b09d0, 0xff788b16, 0xbcb32d91, 0x38e8b7c2, 0x7b231145,
    0x305f8365, 0x739425e2, 0xf7cfbfb1, 0xb4041936, 0xe69c69c9,
    0xa557cf4e, 0x210c551d, 0x62c7f39a, 0x29bb61ba, 0x6a70c73d,
    0xee2b5d6e, 0xade0fbe9, 0x78d3792f, 0x3b18dfa8, 0xbf4345fb,
    0xfc88e37c, 0xb7f4715c, 0xf43fd7db, 0x70644d88, 0x33afeb0f,
    0x9b0538de, 0xd8ce9e59, 0x5c95040a, 0x1f5ea28d, 0x542230ad,
    0x17e9962a, 0x93b20c79, 0xd079aafe, 0x054a2838, 0x46818ebf,
    0xc2da14ec, 0x8111b26b, 0xca6d204b, 0x89a686cc, 0x0dfd1c9f,
    0x4e36ba18},
   {0x00000000, 0xe1b652ef, 0x836bd405, 0x62dd86ea, 0x06d7a80b,
    0xe761fae4, 0x85bc7c0e, 0x640a2ee1, 0x0cae5117, 0xed1803f8,
    0x8fc58512, 0x6e73d7fd, 0x0a79f91c, 0xebcfabf3, 0x89122d19,
    0x68a47ff6, 0x185ca32e, 0xf9eaf1c1, 0x9b37772b, 0x7a8125c4,
    0x1e8b0b25, 0xff3d59ca, 0x9de0df20, 0x7c568dcf, 0x14f2f239,
    0xf544a0d6, 0x9799263c, 0x762f74d3, 0x12255a32, 0xf39308dd,
    0x914e8e37, 0x70f8dcd8, 0x30b8465d, 0xd10e14b2, 0xb3d39258,
    0x5265c0b7, 0x366fee56, 0xd7d9bcb9, 0xb5043a53, 0x54b268bc,
    0x3c16174a, 0xdda045a5, 0xbf7dc34f, 0x5ecb91a0, 0x3ac1bf41,
    0xdb77edae, 0xb9aa6b44, 0x581c39ab, 0x28e4e573, 0xc952b79c,
    0xab8f3176, 0x4a396399, 0x2e334d78, 0xcf851f97, 0xad58997d,
    0x4ceecb92, 0x244ab464, 0xc5fce68b, 0xa7216061, 0x4697328e,
    0x229d1c6f, 0xc32b4e80, 0xa1f6c86a, 0x40409a85, 0x60708dba,
    0x81c6df55, 0xe31b59bf, 0x02ad0b50, 0x66a725b1, 0x8711775e,
    0xe5ccf1b4, 0x047aa35b, 0x6cdedcad, 0x8d688e42, 0xefb508a8,
    0x0e035a47, 0x6a0974a6, 0x8bbf2649, 0xe962a0a3, 0x08d4f24c,
    0x782c2e94, 0x999a7c7b, 0xfb47fa91, 0x1af1a87e, 0x7efb869f,
    0x9f4dd470, 0xfd90529a, 0x1c260075, 0x74827f83, 0x95342d6c,
    0xf7e9ab86, 0x165ff969, 0x7255d788, 0x93e38567, 0xf13e038d,
    0x10885162, 0x50c8cbe7, 0xb17e9908, 0xd3a31fe2, 0x32154d0d,
    0x561f63ec, 0xb7a93103, 0xd574b7e9, 0x34c2e506, 0x5c669af0,
    0xbdd0c81f, 0xdf0d4ef5, 0x3ebb1c1a, 0x5ab132fb, 0xbb076014,
    0xd9dae6fe, 0x386cb411, 0x489468c9, 0xa9223a26, 0xcbffbccc,
    0x2a49ee23, 0x4e43c0c2, 0xaff5922d, 0xcd2814c7, 0x2c9e4628,
    0x443a39de, 0xa58c6b31, 0xc751eddb, 0x26e7bf34, 0x42ed91d5,
    0xa35bc33a, 0xc18645d0, 0x2030173f, 0x81e66bae, 0x60503941,
    0x028dbfab, 0xe33bed44, 0x8731c3a5, 0x6687914a, 0x045a17a0,
    0xe5ec454f, 0x8d483ab9, 0x6cfe6856, 0x0e23eebc, 0xef95bc53,
    0x8b9f92b2, 0x6a29c05d, 0x08f446b7, 0xe9421458, 0x99bac880,
    0x780c9a6f, 0x1ad11c85, 0xfb674e6a, 0x9f6d608b, 0x7edb3264,
    0x1c06b48e, 0xfdb0e661, 0x95149997, 0x74a2cb78, 0x167f4d92,
    0xf7c91f7d, 0x93c3319c, 0x72756373, 0x10a8e599, 0xf11eb776,
    0xb15e2df3, 0x50e87f1c, 0x3235f9f6, 0xd383ab19, 0xb78985f8,
    0x563fd717, 0x34e251fd, 0xd5540312, 0xbdf07ce4, 0x5c462e0b,
    0x3e9ba8e1, 0xdf2dfa0e, 0xbb27d4ef, 0x5a918600, 0x384c00ea,
    0xd9fa5205, 0xa9028edd, 0x48b4dc32, 0x2a695ad8, 0xcbdf0837,
    0xafd526d6, 0x4e637439, 0x2cbef2d3, 0xcd08a03c, 0xa5acdfca,
    0x441a8d25, 0x26c70bcf, 0xc7715920, 0xa37b77c1, 0x42cd252e,
    0x2010a3c4, 0xc1a6f12b, 0xe196e614, 0x0020b4fb, 0x62fd3211,
    0x834b60fe, 0xe7414e1f, 0x06f71cf0, 0x642a9a1a, 0x859cc8f5,
    0xed38b703, 0x0c8ee5ec, 0x6e536306, 0x8fe531e9, 0xebef1f08,
    0x0a594de7, 0x6884cb0d, 0x893299e2, 0xf9ca453a, 0x187c17d5,
    0x7aa1913f, 0x9b17c3d0, 0xff1ded31, 0x1eabbfde, 0x7c763934,
    0x9dc06bdb, 0xf564142d, 0x14d246c2, 0x760fc028, 0x97b992c7,
    0xf3b3bc26, 0x1205eec9, 0x70d86823, 0x916e3acc, 0xd12ea049,
    0x3098f2a6, 0x5245744c, 0xb3f326a3, 0xd7f90842, 0x364f5aad,
    0x5492dc47, 0xb5248ea8, 0xdd80f15e, 0x3c36a3b1, 0x5eeb255b,
    0xbf5d77b4, 0xdb575955, 0x3ae10bba, 0x583c8d50, 0xb98adfbf,
    0xc9720367, 0x28c45188, 0x4a19d762, 0xabaf858d, 0xcfa5ab6c,
    0x2e13f983, 0x4cce7f69, 0xad782d86, 0xc5dc5270, 0x246a009f,
    0x46b78675, 0xa701d49a, 0xc30bfa7b, 0x22bda894, 0x40602e7e,
    0xa1d67c91},
   {0x00000000, 0x5880e2d7, 0xf106b474, 0xa98656a3, 0xe20d68e9,
    0xba8d8a3e, 0x130bdc9d, 0x4b8b3e4a, 0x851da109, 0xdd9d43de,
    0x741b157d, 0x2c9bf7aa, 0x6710c9e0, 0x3f902b37, 0x96167d94,
    0xce969f43, 0x0a3b4213, 0x52bba0c4, 0xfb3df667, 0xa3bd14b0,
    0xe8362afa, 0xb0b6c82d, 0x19309e8e, 0x41b07c59, 0x8f26e31a,
    0xd7a601cd, 0x7e20576e, 0x26a0b5b9, 0x6d2b8bf3, 0x35ab6924,
    0x9c2d3f87, 0xc4addd50, 0x14768426, 0x4cf666f1, 0xe5703052,
    0xbdf0d285, 0xf67beccf, 0xaefb0e18, 0x077d58bb, 0x5ffdba6c,
    0x916b252f, 0xc9ebc7f8, 0x606d915b, 0x38ed738c, 0x73664dc6,
    0x2be6af11, 0x8260f9b2, 0xdae01b65, 0x1e4dc635, 0x46cd24e2,
    0xef4b7241, 0xb7cb9096, 0xfc40aedc, 0xa4c04c0b, 0x0d461aa8,
    0x55c6f87f, 0x9b50673c, 0xc3d085eb, 0x6a56d348, 0x32d6319f,
    0x795d0fd5, 0x21dded02, 0x885bbba1, 0xd0db5976, 0x28ec084d,
    0x706cea9a, 0xd9eabc39, 0x816a5eee, 0xcae160a4, 0x92618273,
    0x3be7d4d0, 0x63673607, 0xadf1a944, 0xf5714b93, 0x5cf71d30,
    0x0477ffe7, 0x4ffcc1ad, 0x177c237a, 0xbefa75d9, 0xe67a970e,
    0x22d74a5e, 0x7a57a889, 0xd3d1fe2a, 0x8b511cfd, 0xc0da22b7,
    0x985ac060, 0x31dc96c3, 0x695c7414, 0xa7caeb57, 0xff4a0980,
    0x56cc5f23, 0x0e4cbdf4, 0x45c783be, 0x1d476169, 0xb4c137ca,
    0xec41d51d, 0x3c9a8c6b, 0x641a6ebc, 0xcd9c381f, 0x951cdac8,
    0xde97e482, 0x86170655, 0x2f9150f6, 0x7711b221, 0xb9872d62,
    0xe107cfb5, 0x48819916, 0x10017bc1, 0x5b8a458b, 0x030aa75c,
    0xaa8cf1ff, 0xf20c1328, 0x36a1ce78, 0x6e212caf, 0xc7a77a0c,
    0x9f2798db, 0xd4aca691, 0x8c2c4446, 0x25aa12e5, 0x7d2af032,
    0xb3bc6f71, 0xeb3c8da6, 0x42badb05, 0x1a3a39d2, 0x51b10798,
    0x0931e54f, 0xa0b7b3ec, 0xf837513b, 0x50d8119a, 0x0858f34d,
    0xa1dea5ee, 0xf95e4739, 0xb2d57973, 0xea559ba4, 0x43d3cd07,
    0x1b532fd0, 0xd5c5b093, 0x8d455244, 0x24c304e7, 0x7c43e630,
    0x37c8d87a, 0x6f483aad, 0xc6ce6c0e, 0x9e4e8ed9, 0x5ae35389,
    0x0263b15e, 0xabe5e7fd, 0xf365052a, 0xb8ee3b60, 0xe06ed9b7,
    0x49e88f14, 0x11686dc3, 0xdffef280, 0x877e1057, 0x2ef846f4,
    0x7678a423, 0x3df39a69, 0x657378be, 0xccf52e1d, 0x9475ccca,
    0x44ae95bc, 0x1c2e776b, 0xb5a821c8, 0xed28c31f, 0xa6a3fd55,
    0xfe231f82, 0x57a54921, 0x0f25abf6, 0xc1b334b5, 0x9933d662,
    0x30b580c1, 0x68356216, 0x23be5c5c, 0x7b3ebe8b, 0xd2b8e828,
    0x8a380aff, 0x4e95d7af, 0x16153578, 0xbf9363db, 0xe713810c,
    0xac98bf46, 0xf4185d91, 0x5d9e0b32, 0x051ee9e5, 0xcb8876a6,
    0x93089471, 0x3a8ec2d2, 0x620e2005, 0x29851e4f, 0x7105fc98,
    0xd883aa3b, 0x800348ec, 0x783419d7, 0x20b4fb00, 0x8932ada3,
    0xd1b24f74, 0x9a39713e, 0xc2b993e9, 0x6b3fc54a, 0x33bf279d,
    0xfd29b8de, 0xa5a95a09, 0x0c2f0caa, 0x54afee7d, 0x1f24d037,
    0x47a432e0, 0xee226443, 0xb6a28694, 0x720f5bc4, 0x2a8fb913,
    0x8309efb0, 0xdb890d67, 0x9002332d, 0xc882d1fa, 0x61048759,
    0x3984658e, 0xf712facd, 0xaf92181a, 0x06144eb9, 0x5e94ac6e,
    0x151f9224, 0x4d9f70f3, 0xe4192650, 0xbc99c487, 0x6c429df1,
    0x34c27f26, 0x9d442985, 0xc5c4cb52, 0x8e4ff518, 0xd6cf17cf,
    0x7f49416c, 0x27c9a3bb, 0xe95f3cf8, 0xb1dfde2f, 0x1859888c,
    0x40d96a5b, 0x0b525411, 0x53d2b6c6, 0xfa54e065, 0xa2d402b2,
    0x6679dfe2, 0x3ef93d35, 0x977f6b96, 0xcfff8941, 0x8474b70b,
    0xdcf455dc, 0x7572037f, 0x2df2e1a8, 0xe3647eeb, 0xbbe49c3c,
    0x1262ca9f, 0x4ae22848, 0x01691602, 0x59e9f4d5, 0xf06fa276,
    0xa8ef40a1},
   {0x00000000, 0x463b6765, 0x8c76ceca, 0xca4da9af, 0x59ebed4e,
    0x1fd08a2b, 0xd59d2384, 0x93a644e1, 0xb2d6db9d, 0xf4edbcf8,
    0x3ea01557, 0x789b7232, 0xeb3d36d3, 0xad0651b6, 0x674bf819,
    0x21709f7c, 0x25abc6e0, 0x6390a185, 0xa9dd082a, 0xefe66f4f,
    0x7c402bae, 0x3a7b4ccb, 0xf036e564, 0xb60d8201, 0x977d1d7d,
    0xd1467a18, 0x1b0bd3b7, 0x5d30b4d2, 0xce96f033, 0x88ad9756,
    0x42e03ef9, 0x04db599c, 0x0b50fc1a, 0x4d6b9b7f, 0x872632d0,
    0xc11d55b5, 0x52bb1154, 0x14807631, 0xdecddf9e, 0x98f6b8fb,
    0xb9862787, 0xffbd40e2, 0x35f0e94d, 0x73cb8e28, 0xe06dcac9,
    0xa656adac, 0x6c1b0403, 0x2a206366, 0x2efb3afa, 0x68c05d9f,
    0xa28df430, 0xe4b69355, 0x7710d7b4, 0x312bb0d1, 0xfb66197e,
    0xbd5d7e1b, 0x9c2de167, 0xda168602, 0x105b2fad, 0x566048c8,
    0xc5c60c29, 0x83fd6b4c, 0x49b0c2e3, 0x0f8ba586, 0x16a0f835,
    0x509b9f50, 0x9ad636ff, 0xdced519a, 0x4f4b157b, 0x0970721e,
    0xc33ddbb1, 0x8506bcd4, 0xa47623a8, 0xe24d44cd, 0x2800ed62,
    0x6e3b8a07, 0xfd9dcee6, 0xbba6a983, 0x71eb002c, 0x37d06749,
    0x330b3ed5, 0x753059b0, 0xbf7df01f, 0xf946977a, 0x6ae0d39b,
    0x2cdbb4fe, 0xe6961d51, 0xa0ad7a34, 0x81dde548, 0xc7e6822d,
    0x0dab2b82, 0x4b904ce7, 0xd8360806, 0x9e0d6f63, 0x5440c6cc,
    0x127ba1a9, 0x1df0042f, 0x5bcb634a, 0x9186cae5, 0xd7bdad80,
    0x441be961, 0x02208e04, 0xc86d27ab, 0x8e5640ce, 0xaf26dfb2,
    0xe91db8d7, 0x23501178, 0x656b761d, 0xf6cd32fc, 0xb0f65599,
    0x7abbfc36, 0x3c809b53, 0x385bc2cf, 0x7e60a5aa, 0xb42d0c05,
    0xf2166b60, 0x61b02f81, 0x278b48e4, 0xedc6e14b, 0xabfd862e,
    0x8a8d1952, 0xccb67e37, 0x06fbd798, 0x40c0b0fd, 0xd366f41c,
    0x955d9379, 0x5f103ad6, 0x192b5db3, 0x2c40f16b, 0x6a7b960e,
    0xa0363fa1, 0xe60d58c4, 0x75ab1c25, 0x33907b40, 0xf9ddd2ef,
    0xbfe6b58a, 0x9e962af6, 0xd8ad4d93, 0x12e0e43c, 0x54db8359,
    0xc77dc7b8, 0x8146a0dd, 0x4b0b0972, 0x0d306e17, 0x09eb378b,
    0x4fd050ee, 0x859df941, 0xc3a69e24, 0x5000dac5, 0x163bbda0,
    0xdc76140f, 0x9a4d736a, 0xbb3dec16, 0xfd068b73, 0x374b22dc,
    0x717045b9, 0xe2d60158, 0xa4ed663d, 0x6ea0cf92, 0x289ba8f7,
    0x27100d71, 0x612b6a14, 0xab66c3bb, 0xed5da4de, 0x7efbe03f,
    0x38c0875a, 0xf28d2ef5, 0xb4b64990, 0x95c6d6ec, 0xd3fdb189,
    0x19b01826, 0x5f8b7f43, 0xcc2d3ba2, 0x8a165cc7, 0x405bf568,
    0x0660920d, 0x02bbcb91, 0x4480acf4, 0x8ecd055b, 0xc8f6623e,
    0x5b5026df, 0x1d6b41ba, 0xd726e815, 0x911d8f70, 0xb06d100c,
    0xf6567769, 0x3c1bdec6, 0x7a20b9a3, 0xe986fd42, 0xafbd9a27,
    0x65f03388, 0x23cb54ed, 0x3ae0095e, 0x7cdb6e3b, 0xb696c794,
    0xf0ada0f1, 0x630be410, 0x25308375, 0xef7d2ada, 0xa9464dbf,
    0x8836d2c3, 0xce0db5a6, 0x04401c09, 0x427b7b6c, 0xd1dd3f8d,
    0x97e658e8, 0x5dabf147, 0x1b909622, 0x1f4bcfbe, 0x5970a8db,
    0x933d0174, 0xd5066611, 0x46a022f0, 0x009b4595, 0xcad6ec3a,
    0x8ced8b5f, 0xad9d1423, 0xeba67346, 0x21ebdae9, 0x67d0bd8c,
    0xf476f96d, 0xb24d9e08, 0x780037a7, 0x3e3b50c2, 0x31b0f544,
    0x778b9221, 0xbdc63b8e, 0xfbfd5ceb, 0x685b180a, 0x2e607f6f,
    0xe42dd6c0, 0xa216b1a5, 0x83662ed9, 0xc55d49bc, 0x0f10e013,
    0x492b8776, 0xda8dc397, 0x9cb6a4f2, 0x56fb0d5d, 0x10c06a38,
    0x141b33a4, 0x522054c1, 0x986dfd6e, 0xde569a0b, 0x4df0deea,
    0x0bcbb98f, 0xc1861020, 0x87bd7745, 0xa6cde839, 0xe0f68f5c,
    0x2abb26f3, 0x6c804196, 0xff260577, 0xb91d6212, 0x7350cbbd,
    0x356bacd8}};

#endif

#endif

#if N == 6

#if W == 8

local const z_crc_t FAR crc_braid_table[][256] = {
   {0x00000000, 0x3db1ecdc, 0x7b63d9b8, 0x46d23564, 0xf6c7b370,
    0xcb765fac, 0x8da46ac8, 0xb0158614, 0x36fe60a1, 0x0b4f8c7d,
    0x4d9db919, 0x702c55c5, 0xc039d3d1, 0xfd883f0d, 0xbb5a0a69,
    0x86ebe6b5, 0x6dfcc142, 0x504d2d9e, 0x169f18fa, 0x2b2ef426,
    0x9b3b7232, 0xa68a9eee, 0xe058ab8a, 0xdde94756, 0x5b02a1e3,
    0x66b34d3f, 0x2061785b, 0x1dd09487, 0xadc51293, 0x9074fe4f,
    0xd6a6cb2b, 0xeb1727f7, 0xdbf98284, 0xe6486e58, 0xa09a5b3c,
    0x9d2bb7e0, 0x2d3e31f4, 0x108fdd28, 0x565de84c, 0x6bec0490,
    0xed07e225, 0xd0b60ef9, 0x96643b9d, 0xabd5d741, 0x1bc05155,
    0x2671bd89, 0x60a388ed, 0x5d126431, 0xb60543c6, 0x8bb4af1a,
    0xcd669a7e, 0xf0d776a2, 0x40c2f0b6, 0x7d731c6a, 0x3ba1290e,
    0x0610c5d2, 0x80fb2367, 0xbd4acfbb, 0xfb98fadf, 0xc6291603,
    0x763c9017, 0x4b8d7ccb, 0x0d5f49af, 0x30eea573, 0x6c820349,
    0x5133ef95, 0x17e1daf1, 0x2a50362d, 0x9a45b039, 0xa7f45ce5,
    0xe1266981, 0xdc97855d, 0x5a7c63e8, 0x67cd8f34, 0x211fba50,
    0x1cae568c, 0xacbbd098, 0x910a3c44, 0xd7d80920, 0xea69e5fc,
    0x017ec20b, 0x3ccf2ed7, 0x7a1d1bb3, 0x47acf76f, 0xf7b9717b,
    0xca089da7, 0x8cdaa8c3, 0xb16b441f, 0x3780a2aa, 0x0a314e76,
    0x4ce37b12, 0x715297ce, 0xc14711da, 0xfcf6fd06, 0xba24c862,
    0x879524be, 0xb77b81cd, 0x8aca6d11, 0xcc185875, 0xf1a9b4a9,
    0x41bc32bd, 0x7c0dde61, 0x3adfeb05, 0x076e07d9, 0x8185e16c,
    0xbc340db0, 0xfae638d4, 0xc757d408, 0x7742521c, 0x4af3bec0,
    0x0c218ba4, 0x31906778, 0xda87408f, 0xe736ac53, 0xa1e49937,
    0x9c5575eb, 0x2c40f3ff, 0x11f11f23, 0x57232a47, 0x6a92c69b,
    0xec79202e, 0xd1c8ccf2, 0x971af996, 0xaaab154a, 0x1abe935e,
    0x270f7f82, 0x61dd4ae6, 0x5c6ca63a, 0xd9040692, 0xe4b5ea4e,
    0xa267df2a, 0x9fd633f6, 0x2fc3b5e2, 0x1272593e, 0x54a06c5a,
    0x69118086, 0xeffa6633, 0xd24b8aef, 0x9499bf8b, 0xa9285357,
    0x193dd543, 0x248c399f, 0x625e0cfb, 0x5fefe027, 0xb4f8c7d0,
    0x89492b0c, 0xcf9b1e68, 0xf22af2b4, 0x423f74a0, 0x7f8e987c,
    0x395cad18, 0x04ed41c4, 0x8206a771, 0xbfb74bad, 0xf9657ec9,
    0xc4d49215, 0x74c11401, 0x4970f8dd, 0x0fa2cdb9, 0x32132165,
    0x02fd8416, 0x3f4c68ca, 0x799e5dae, 0x442fb172, 0xf43a3766,
    0xc98bdbba, 0x8f59eede, 0xb2e80202, 0x3403e4b7, 0x09b2086b,
    0x4f603d0f, 0x72d1d1d3, 0xc2c457c7, 0xff75bb1b, 0xb9a78e7f,
    0x841662a3, 0x6f014554, 0x52b0a988, 0x14629cec, 0x29d37030,
    0x99c6f624, 0xa4771af8, 0xe2a52f9c, 0xdf14c340, 0x59ff25f5,
    0x644ec929, 0x229cfc4d, 0x1f2d1091, 0xaf389685, 0x92897a59,
    0xd45b4f3d, 0xe9eaa3e1, 0xb58605db, 0x8837e907, 0xcee5dc63,
    0xf35430bf, 0x4341b6ab, 0x7ef05a77, 0x38226f13, 0x059383cf,
    0x8378657a, 0xbec989a6, 0xf81bbcc2, 0xc5aa501e, 0x75bfd60a,
    0x480e3ad6, 0x0edc0fb2, 0x336de36e, 0xd87ac499, 0xe5cb2845,
    0xa3191d21, 0x9ea8f1fd, 0x2ebd77e9, 0x130c9b35, 0x55deae51,
    0x686f428d, 0xee84a438, 0xd33548e4, 0x95e77d80, 0xa856915c,
    0x18431748, 0x25f2fb94, 0x6320cef0, 0x5e91222c, 0x6e7f875f,
    0x53ce6b83, 0x151c5ee7, 0x28adb23b, 0x98b8342f, 0xa509d8f3,
    0xe3dbed97, 0xde6a014b, 0x5881e7fe, 0x65300b22, 0x23e23e46,
    0x1e53d29a, 0xae46548e, 0x93f7b852, 0xd5258d36, 0xe89461ea,
    0x0383461d, 0x3e32aac1, 0x78e09fa5, 0x45517379, 0xf544f56d,
    0xc8f519b1, 0x8e272cd5, 0xb396c009, 0x357d26bc, 0x08ccca60,
    0x4e1eff04, 0x73af13d8, 0xc3ba95cc, 0xfe0b7910, 0xb8d94c74,
    0x8568a0a8},
   {0x00000000, 0x69790b65, 0xd2f216ca, 0xbb8b1daf, 0x7e952bd5,
    0x17ec20b0, 0xac673d1f, 0xc51e367a, 0xfd2a57aa, 0x94535ccf,
    0x2fd84160, 0x46a14a05, 0x83bf7c7f, 0xeac6771a, 0x514d6ab5,
    0x383461d0, 0x2125a915, 0x485ca270, 0xf3d7bfdf, 0x9aaeb4ba,
    0x5fb082c0, 0x36c989a5, 0x8d42940a, 0xe43b9f6f, 0xdc0ffebf,
    0xb576f5da, 0x0efde875, 0x6784e310, 0xa29ad56a, 0xcbe3de0f,
    0x7068c3a0, 0x1911c8c5, 0x424b522a, 0x2b32594f, 0x90b944e0,
    0xf9c04f85, 0x3cde79ff, 0x55a7729a, 0xee2c6f35, 0x87556450,
    0xbf610580, 0xd6180ee5, 0x6d93134a, 0x04ea182f, 0xc1f42e55,
    0xa88d2530, 0x1306389f, 0x7a7f33fa, 0x636efb3f, 0x0a17f05a,
    0xb19cedf5, 0xd8e5e690, 0x1dfbd0ea, 0x7482db8f, 0xcf09c620,
    0xa670cd45, 0x9e44ac95, 0xf73da7f0, 0x4cb6ba5f, 0x25cfb13a,
    0xe0d18740, 0x89a88c25, 0x3223918a, 0x5b5a9aef, 0x8496a454,
    0xedefaf31, 0x5664b29e, 0x3f1db9fb, 0xfa038f81, 0x937a84e4,
    0x28f1994b, 0x4188922e, 0x79bcf3fe, 0x10c5f89b, 0xab4ee534,
    0xc237ee51, 0x0729d82b, 0x6e50d34e, 0xd5dbcee1, 0xbca2c584,
    0xa5b30d41, 0xccca0624, 0x77411b8b, 0x1e3810ee, 0xdb262694,
    0xb25f2df1, 0x09d4305e, 0x60ad3b3b, 0x58995aeb, 0x31e0518e,
    0x8a6b4c21, 0xe3124744, 0x260c713e, 0x4f757a5b, 0xf4fe67f4,
    0x9d876c91, 0xc6ddf67e, 0xafa4fd1b, 0x142fe0b4, 0x7d56ebd1,
    0xb848ddab, 0xd131d6ce, 0x6abacb61, 0x03c3c004, 0x3bf7a1d4,
    0x528eaab1, 0xe905b71e, 0x807cbc7b, 0x45628a01, 0x2c1b8164,
    0x97909ccb, 0xfee997ae, 0xe7f85f6b, 0x8e81540e, 0x350a49a1,
    0x5c7342c4, 0x996d74be, 0xf0147fdb, 0x4b9f6274, 0x22e66911,
    0x1ad208c1, 0x73ab03a4, 0xc8201e0b, 0xa159156e, 0x64472314,
    0x0d3e2871, 0xb6b535de, 0xdfcc3ebb, 0xd25c4ee9, 0xbb25458c,
    0x00ae5823, 0x69d75346, 0xacc9653c, 0xc5b06e59, 0x7e3b73f6,
    0x17427893, 0x2f761943, 0x460f1226, 0xfd840f89, 0x94fd04ec,
    0x51e33296, 0x389a39f3, 0x8311245c, 0xea682f39, 0xf379e7fc,
    0x9a00ec99, 0x218bf136, 0x48f2fa53, 0x8deccc29, 0xe495c74c,
    0x5f1edae3, 0x3667d186, 0x0e53b056, 0x672abb33, 0xdca1a69c,
    0xb5d8adf9, 0x70c69b83, 0x19bf90e6, 0xa2348d49, 0xcb4d862c,
    0x90171cc3, 0xf96e17a6, 0x42e50a09, 0x2b9c016c, 0xee823716,
    0x87fb3c73, 0x3c7021dc, 0x55092ab9, 0x6d3d4b69, 0x0444400c,
    0xbfcf5da3, 0xd6b656c6, 0x13a860bc, 0x7ad16bd9, 0xc15a7676,
    0xa8237d13, 0xb132b5d6, 0xd84bbeb3, 0x63c0a31c, 0x0ab9a879,
    0xcfa79e03, 0xa6de9566, 0x1d5588c9, 0x742c83ac, 0x4c18e27c,
    0x2561e919, 0x9eeaf4b6, 0xf793ffd3, 0x328dc9a9, 0x5bf4c2cc,
    0xe07fdf63, 0x8906d406, 0x56caeabd, 0x3fb3e1d8, 0x8438fc77,
    0xed41f712, 0x285fc168, 0x4126ca0d, 0xfaadd7a2, 0x93d4dcc7,
    0xabe0bd17, 0xc299b672, 0x7912abdd, 0x106ba0b8, 0xd57596c2,
    0xbc0c9da7, 0x07878008, 0x6efe8b6d, 0x77ef43a8, 0x1e9648cd,
    0xa51d5562, 0xcc645e07, 0x097a687d, 0x60036318, 0xdb887eb7,
    0xb2f175d2, 0x8ac51402, 0xe3bc1f67, 0x583702c8, 0x314e09ad,
    0xf4503fd7, 0x9d2934b2, 0x26a2291d, 0x4fdb2278, 0x1481b897,
    0x7df8b3f2, 0xc673ae5d, 0xaf0aa538, 0x6a149342, 0x036d9827,
    0xb8e68588, 0xd19f8eed, 0xe9abef3d, 0x80d2e458, 0x3b59f9f7,
    0x5220f292, 0x973ec4e8, 0xfe47cf8d, 0x45ccd222, 0x2cb5d947,
    0x35a41182, 0x5cdd1ae7, 0xe7560748, 0x8e2f0c2d, 0x4b313a57,
    0x22483132, 0x99c32c9d, 0xf0ba27f8, 0xc88e4628, 0xa1f74d4d,
    0x1a7c50e2, 0x73055b87, 0xb61b6dfd, 0xdf626698, 0x64e97b37,
    0x0d907052},
   {0x00000000, 0x7fc99b93, 0xff933726, 0x805aacb5, 0x2457680d,
    0x5b9ef39e, 0xdbc45f2b, 0xa40dc4b8, 0x48aed01a, 0x37674b89,
    0xb73de73c, 0xc8f47caf, 0x6cf9b817, 0x13302384, 0x936a8f31,
    0xeca314a2, 0x915da034, 0xee943ba7, 0x6ece9712, 0x11070c81,
    0xb50ac839, 0xcac353aa, 0x4a99ff1f, 0x3550648c, 0xd9f3702e,
    0xa63aebbd, 0x26604708, 0x59a9dc9b, 0xfda41823, 0x826d83b0,
    0x02372f05, 0x7dfeb496, 0xf9ca4629, 0x8603ddba, 0x0659710f,
    0x7990ea9c, 0xdd9d2e24, 0xa254b5b7, 0x220e1902, 0x5dc78291,
    0xb1649633, 0xcead0da0, 0x4ef7a115, 0x313e3a86, 0x9533fe3e,
    0xeafa65ad, 0x6aa0c918, 0x1569528b, 0x6897e61d, 0x175e7d8e,
    0x9704d13b, 0xe8cd4aa8, 0x4cc08e10, 0x33091583, 0xb353b936,
    0xcc9a22a5, 0x20393607, 0x5ff0ad94, 0xdfaa0121, 0xa0639ab2,
    0x046e5e0a, 0x7ba7c599, 0xfbfd692c, 0x8434f2bf, 0x28e58a13,
    0x572c1180, 0xd776bd35, 0xa8bf26a6, 0x0cb2e21e, 0x737b798d,
    0xf321d538, 0x8ce84eab, 0x604b5a09, 0x1f82c19a, 0x9fd86d2f,
    0xe011f6bc, 0x441c3204, 0x3bd5a997, 0xbb8f0522, 0xc4469eb1,
    0xb9b82a27, 0xc671b1b4, 0x462b1d01, 0x39e28692, 0x9def422a,
    0xe226d9b9, 0x627c750c, 0x1db5ee9f, 0xf116fa3d, 0x8edf61ae,
    0x0e85cd1b, 0x714c5688, 0xd5419230, 0xaa8809a3, 0x2ad2a516,
    0x551b3e85, 0xd12fcc3a, 0xaee657a9, 0x2ebcfb1c, 0x5175608f,
    0xf578a437, 0x8ab13fa4, 0x0aeb9311, 0x75220882, 0x99811c20,
    0xe64887b3, 0x66122b06, 0x19dbb095, 0xbdd6742d, 0xc21fefbe,
    0x4245430b, 0x3d8cd898, 0x40726c0e, 0x3fbbf79d, 0xbfe15b28,
    0xc028c0bb, 0x64250403, 0x1bec9f90, 0x9bb63325, 0xe47fa8b6,
    0x08dcbc14, 0x77152787, 0xf74f8b32, 0x888610a1, 0x2c8bd419,
    0x53424f8a, 0xd318e33f, 0xacd178ac, 0x51cb1426, 0x2e028fb5,
    0xae582300, 0xd191b893, 0x759c7c2b, 0x0a55e7b8, 0x8a0f4b0d,
    0xf5c6d09e, 0x1965c43c, 0x66ac5faf, 0xe6f6f31a, 0x993f6889,
    0x3d32ac31, 0x42fb37a2, 0xc2a19b17, 0xbd680084, 0xc096b412,
    0xbf5f2f81, 0x3f058334, 0x40cc18a7, 0xe4c1dc1f, 0x9b08478c,
    0x1b52eb39, 0x649b70aa, 0x88386408, 0xf7f1ff9b, 0x77ab532e,
    0x0862c8bd, 0xac6f0c05, 0xd3a69796, 0x53fc3b23, 0x2c35a0b0,
    0xa801520f, 0xd7c8c99c, 0x57926529, 0x285bfeba, 0x8c563a02,
    0xf39fa191, 0x73c50d24, 0x0c0c96b7, 0xe0af8215, 0x9f661986,
    0x1f3cb533, 0x60f52ea0, 0xc4f8ea18, 0xbb31718b, 0x3b6bdd3e,
    0x44a246ad, 0x395cf23b, 0x469569a8, 0xc6cfc51d, 0xb9065e8e,
    0x1d0b9a36, 0x62c201a5, 0xe298ad10, 0x9d513683, 0x71f22221,
    0x0e3bb9b2, 0x8e611507, 0xf1a88e94, 0x55a54a2c, 0x2a6cd1bf,
    0xaa367d0a, 0xd5ffe699, 0x792e9e35, 0x06e705a6, 0x86bda913,
    0xf9743280, 0x5d79f638, 0x22b06dab, 0xa2eac11e, 0xdd235a8d,
    0x31804e2f, 0x4e49d5bc, 0xce137909, 0xb1dae29a, 0x15d72622,
    0x6a1ebdb1, 0xea441104, 0x958d8a97, 0xe8733e01, 0x97baa592,
    0x17e00927, 0x682992b4, 0xcc24560c, 0xb3edcd9f, 0x33b7612a,
    0x4c7efab9, 0xa0ddee1b, 0xdf147588, 0x5f4ed93d, 0x208742ae,
    0x848a8616, 0xfb431d85, 0x7b19b130, 0x04d02aa3, 0x80e4d81c,
    0xff2d438f, 0x7f77ef3a, 0x00be74a9, 0xa4b3b011, 0xdb7a2b82,
    0x5b208737, 0x24e91ca4, 0xc84a0806, 0xb7839395, 0x37d93f20,
    0x4810a4b3, 0xec1d600b, 0x93d4fb98, 0x138e572d, 0x6c47ccbe,
    0x11b97828, 0x6e70e3bb, 0xee2a4f0e, 0x91e3d49d, 0x35ee1025,
    0x4a278bb6, 0xca7d2703, 0xb5b4bc90, 0x5917a832, 0x26de33a1,
    0xa6849f14, 0xd94d0487, 0x7d40c03f, 0x02895bac, 0x82d3f719,
    0xfd1a6c8a},
   {0x00000000, 0xa396284c, 0x9c5d56d9, 0x3fcb7e95, 0xe3cbabf3,
    0x405d83bf, 0x7f96fd2a, 0xdc00d566, 0x1ce651a7, 0xbf7079eb,
    0x80bb077e, 0x232d2f32, 0xff2dfa54, 0x5cbbd218, 0x6370ac8d,
    0xc0e684c1, 0x39cca34e, 0x9a5a8b02, 0xa591f597, 0x0607dddb,
    0xda0708bd, 0x799120f1, 0x465a5e64, 0xe5cc7628, 0x252af2e9,
    0x86bcdaa5, 0xb977a430, 0x1ae18c7c, 0xc6e1591a, 0x65777156,
    0x5abc0fc3, 0xf92a278f, 0x7399469c, 0xd00f6ed0, 0xefc41045,
    0x4c523809, 0x9052ed6f, 0x33c4c523, 0x0c0fbbb6, 0xaf9993fa,
    0x6f7f173b, 0xcce93f77, 0xf32241e2, 0x50b469ae, 0x8cb4bcc8,
    0x2f229484, 0x10e9ea11, 0xb37fc25d, 0x4a55e5d2, 0xe9c3cd9e,
    0xd608b30b, 0x759e9b47, 0xa99e4e21, 0x0a08666d, 0x35c318f8,
    0x965530b4, 0x56b3b475, 0xf5259c39, 0xcaeee2ac, 0x6978cae0,
    0xb5781f86, 0x16ee37ca, 0x2925495f, 0x8ab36113, 0xe7328d38,
    0x44a4a574, 0x7b6fdbe1, 0xd8f9f3ad, 0x04f926cb, 0xa76f0e87,
    0x98a47012, 0x3b32585e, 0xfbd4dc9f, 0x5842f4d3, 0x67898a46,
    0xc41fa20a, 0x181f776c, 0xbb895f20, 0x844221b5, 0x27d409f9,
    0xdefe2e76, 0x7d68063a, 0x42a378af, 0xe13550e3, 0x3d358585,
    0x9ea3adc9, 0xa168d35c, 0x02fefb10, 0xc2187fd1, 0x618e579d,
    0x5e452908, 0xfdd30144, 0x21d3d422, 0x8245fc6e, 0xbd8e82fb,
    0x1e18aab7, 0x94abcba4, 0x373de3e8, 0x08f69d7d, 0xab60b531,
    0x77606057, 0xd4f6481b, 0xeb3d368e, 0x48ab1ec2, 0x884d9a03,
    0x2bdbb24f, 0x1410ccda, 0xb786e496, 0x6b8631f0, 0xc81019bc,
    0xf7db6729, 0x544d4f65, 0xad6768ea, 0x0ef140a6, 0x313a3e33,
    0x92ac167f, 0x4eacc319, 0xed3aeb55, 0xd2f195c0, 0x7167bd8c,
    0xb181394d, 0x12171101, 0x2ddc6f94, 0x8e4a47d8, 0x524a92be,
    0xf1dcbaf2, 0xce17c467, 0x6d81ec2b, 0x15141c31, 0xb682347d,
    0x89494ae8, 0x2adf62a4, 0xf6dfb7c2, 0x55499f8e, 0x6a82e11b,
    0xc914c957, 0x09f24d96, 0xaa6465da, 0x95af1b4f, 0x36393303,
    0xea39e665, 0x49afce29, 0x7664b0bc, 0xd5f298f0, 0x2cd8bf7f,
    0x8f4e9733, 0xb085e9a6, 0x1313c1ea, 0xcf13148c, 0x6c853cc0,
    0x534e4255, 0xf0d86a19, 0x303eeed8, 0x93a8c694, 0xac63b801,
    0x0ff5904d, 0xd3f5452b, 0x70636d67, 0x4fa813f2, 0xec3e3bbe,
    0x668d5aad, 0xc51b72e1, 0xfad00c74, 0x59462438, 0x8546f15e,
    0x26d0d912, 0x191ba787, 0xba8d8fcb, 0x7a6b0b0a, 0xd9fd2346,
    0xe6365dd3, 0x45a0759f, 0x99a0a0f9, 0x3a3688b5, 0x05fdf620,
    0xa66bde6c, 0x5f41f9e3, 0xfcd7d1af, 0xc31caf3a, 0x608a8776,
    0xbc8a5210, 0x1f1c7a5c, 0x20d704c9, 0x83412c85, 0x43a7a844,
    0xe0318008, 0xdffafe9d, 0x7c6cd6d1, 0xa06c03b7, 0x03fa2bfb,
    0x3c31556e, 0x9fa77d22, 0xf2269109, 0x51b0b945, 0x6e7bc7d0,
    0xcdedef9c, 0x11ed3afa, 0xb27b12b6, 0x8db06c23, 0x2e26446f,
    0xeec0c0ae, 0x4d56e8e2, 0x729d9677, 0xd10bbe3b, 0x0d0b6b5d,
    0xae9d4311, 0x91563d84, 0x32c015c8, 0xcbea3247, 0x687c1a0b,
    0x57b7649e, 0xf4214cd2, 0x282199b4, 0x8bb7b1f8, 0xb47ccf6d,
    0x17eae721, 0xd70c63e0, 0x749a4bac, 0x4b513539, 0xe8c71d75,
    0x34c7c813, 0x9751e05f, 0xa89a9eca, 0x0b0cb686, 0x81bfd795,
    0x2229ffd9, 0x1de2814c, 0xbe74a900, 0x62747c66, 0xc1e2542a,
    0xfe292abf, 0x5dbf02f3, 0x9d598632, 0x3ecfae7e, 0x0104d0eb,
    0xa292f8a7, 0x7e922dc1, 0xdd04058d, 0xe2cf7b18, 0x41595354,
    0xb87374db, 0x1be55c97, 0x242e2202, 0x87b80a4e, 0x5bb8df28,
    0xf82ef764, 0xc7e589f1, 0x6473a1bd, 0xa495257c, 0x07030d30,
    0x38c873a5, 0x9b5e5be9, 0x475e8e8f, 0xe4c8a6c3, 0xdb03d856,
    0x7895f01a},
   {0x00000000, 0x2a283862, 0x545070c4, 0x7e7848a6, 0xa8a0e188,
    0x8288d9ea, 0xfcf0914c, 0xd6d8a92e, 0x8a30c551, 0xa018fd33,
    0xde60b595, 0xf4488df7, 0x229024d9, 0x08b81cbb, 0x76c0541d,
    0x5ce86c7f, 0xcf108ce3, 0xe538b481, 0x9b40fc27, 0xb168c445,
    0x67b06d6b, 0x4d985509, 0x33e01daf, 0x19c825cd, 0x452049b2,
    0x6f0871d0, 0x11703976, 0x3b580114, 0xed80a83a, 0xc7a89058,
    0xb9d0d8fe, 0x93f8e09c, 0x45501f87, 0x6f7827e5, 0x11006f43,
    0x3b285721, 0xedf0fe0f, 0xc7d8c66d, 0xb9a08ecb, 0x9388b6a9,
    0xcf60dad6, 0xe548e2b4, 0x9b30aa12, 0xb1189270, 0x67c03b5e,
    0x4de8033c, 0x33904b9a, 0x19b873f8, 0x8a409364, 0xa068ab06,
    0xde10e3a0, 0xf438dbc2, 0x22e072ec, 0x08c84a8e, 0x76b00228,
    0x5c983a4a, 0x00705635, 0x2a586e57, 0x542026f1, 0x7e081e93,
    0xa8d0b7bd, 0x82f88fdf, 0xfc80c779, 0xd6a8ff1b, 0x8aa03f0e,
    0xa088076c, 0xdef04fca, 0xf4d877a8, 0x2200de86, 0x0828e6e4,
    0x7650ae42, 0x5c789620, 0x0090fa5f, 0x2ab8c23d, 0x54c08a9b,
    0x7ee8b2f9, 0xa8301bd7, 0x821823b5, 0xfc606b13, 0xd6485371,
    0x45b0b3ed, 0x6f988b8f, 0x11e0c329, 0x3bc8fb4b, 0xed105265,
    0xc7386a07, 0xb94022a1, 0x93681ac3, 0xcf8076bc, 0xe5a84ede,
    0x9bd00678, 0xb1f83e1a, 0x67209734, 0x4d08af56, 0x3370e7f0,
    0x1958df92, 0xcff02089, 0xe5d818eb, 0x9ba0504d, 0xb188682f,
    0x6750c101, 0x4d78f963, 0x3300b1c5, 0x192889a7, 0x45c0e5d8,
    0x6fe8ddba, 0x1190951c, 0x3bb8ad7e, 0xed600450, 0xc7483c32,
    0xb9307494, 0x93184cf6, 0x00e0ac6a, 0x2ac89408, 0x54b0dcae,
    0x7e98e4cc, 0xa8404de2, 0x82687580, 0xfc103d26, 0xd6380544,
    0x8ad0693b, 0xa0f85159, 0xde8019ff, 0xf4a8219d, 0x227088b3,
    0x0858b0d1, 0x7620f877, 0x5c08c015, 0xce31785d, 0xe419403f,
    0x9a610899, 0xb04930fb, 0x669199d5, 0x4cb9a1b7, 0x32c1e911,
    0x18e9d173, 0x4401bd0c, 0x6e29856e, 0x1051cdc8, 0x3a79f5aa,
    0xeca15c84, 0xc68964e6, 0xb8f12c40, 0x92d91422, 0x0121f4be,
    0x2b09ccdc, 0x5571847a, 0x7f59bc18, 0xa9811536, 0x83a92d54,
    0xfdd165f2, 0xd7f95d90, 0x8b1131ef, 0xa139098d, 0xdf41412b,
    0xf5697949, 0x23b1d067, 0x0999e805, 0x77e1a0a3, 0x5dc998c1,
    0x8b6167da, 0xa1495fb8, 0xdf31171e, 0xf5192f7c, 0x23c18652,
    0x09e9be30, 0x7791f696, 0x5db9cef4, 0x0151a28b, 0x2b799ae9,
    0x5501d24f, 0x7f29ea2d, 0xa9f14303, 0x83d97b61, 0xfda133c7,
    0xd7890ba5, 0x4471eb39, 0x6e59d35b, 0x10219bfd, 0x3a09a39f,
    0xecd10ab1, 0xc6f932d3, 0xb8817a75, 0x92a94217, 0xce412e68,
    0xe469160a, 0x9a115eac, 0xb03966ce, 0x66e1cfe0, 0x4cc9f782,
    0x32b1bf24, 0x18998746, 0x44914753, 0x6eb97f31, 0x10c13797,
    0x3ae90ff5, 0xec31a6db, 0xc6199eb9, 0xb861d61f, 0x9249ee7d,
    0xcea18202, 0xe489ba60, 0x9af1f2c6, 0xb0d9caa4, 0x6601638a,
    0x4c295be8, 0x3251134e, 0x18792b2c, 0x8b81cbb0, 0xa1a9f3d2,
    0xdfd1bb74, 0xf5f98316, 0x23212a38, 0x0909125a, 0x77715afc,
    0x5d59629e, 0x01b10ee1, 0x2b993683, 0x55e17e25, 0x7fc94647,
    0xa911ef69, 0x8339d70b, 0xfd419fad, 0xd769a7cf, 0x01c158d4,
    0x2be960b6, 0x55912810, 0x7fb91072, 0xa961b95c, 0x8349813e,
    0xfd31c998, 0xd719f1fa, 0x8bf19d85, 0xa1d9a5e7, 0xdfa1ed41,
    0xf589d523, 0x23517c0d, 0x0979446f, 0x77010cc9, 0x5d2934ab,
    0xced1d437, 0xe4f9ec55, 0x9a81a4f3, 0xb0a99c91, 0x667135bf,
    0x4c590ddd, 0x3221457b, 0x18097d19, 0x44e11166, 0x6ec92904,
    0x10b161a2, 0x3a9959c0, 0xec41f0ee, 0xc669c88c, 0xb811802a,
    0x9239b848},
   {0x00000000, 0x4713f6fb, 0x8e27edf6, 0xc9341b0d, 0xc73eddad,
    0x802d2b56, 0x4919305b, 0x0e0ac6a0, 0x550cbd1b, 0x121f4be0,
    0xdb2b50ed, 0x9c38a616, 0x923260b6, 0xd521964d, 0x1c158d40,
    0x5b067bbb, 0xaa197a36, 0xed0a8ccd, 0x243e97c0, 0x632d613b,
    0x6d27a79b, 0x2a345160, 0xe3004a6d, 0xa413bc96, 0xff15c72d,
    0xb80631d6, 0x71322adb, 0x3621dc20, 0x382b1a80, 0x7f38ec7b,
    0xb60cf776, 0xf11f018d, 0x8f43f22d, 0xc85004d6, 0x01641fdb,
    0x4677e920, 0x487d2f80, 0x0f6ed97b, 0xc65ac276, 0x8149348d,
    0xda4f4f36, 0x9d5cb9cd, 0x5468a2c0, 0x137b543b, 0x1d71929b,
    0x5a626460, 0x93567f6d, 0xd4458996, 0x255a881b, 0x62497ee0,
    0xab7d65ed, 0xec6e9316, 0xe26455b6, 0xa577a34d, 0x6c43b840,
    0x2b504ebb, 0x70563500, 0x3745c3fb, 0xfe71d8f6, 0xb9622e0d,
    0xb768e8ad, 0xf07b1e56, 0x394f055b, 0x7e5cf3a0, 0xc5f6e21b,
    0x82e514e0, 0x4bd10fed, 0x0cc2f916, 0x02c83fb6, 0x45dbc94d,
    0x8cefd240, 0xcbfc24bb, 0x90fa5f00, 0xd7e9a9fb, 0x1eddb2f6,
    0x59ce440d, 0x57c482ad, 0x10d77456, 0xd9e36f5b, 0x9ef099a0,
    0x6fef982d, 0x28fc6ed6, 0xe1c875db, 0xa6db8320, 0xa8d14580,
    0xefc2b37b, 0x26f6a876, 0x61e55e8d, 0x3ae32536, 0x7df0d3cd,
    0xb4c4c8c0, 0xf3d73e3b, 0xfdddf89b, 0xbace0e60, 0x73fa156d,
    0x34e9e396, 0x4ab51036, 0x0da6e6cd, 0xc492fdc0, 0x83810b3b,
    0x8d8bcd9b, 0xca983b60, 0x03ac206d, 0x44bfd696, 0x1fb9ad2d,
    0x58aa5bd6, 0x919e40db, 0xd68db620, 0xd8877080, 0x9f94867b,
    0x56a09d76, 0x11b36b8d, 0xe0ac6a00, 0xa7bf9cfb, 0x6e8b87f6,
    0x2998710d, 0x2792b7ad, 0x60814156, 0xa9b55a5b, 0xeea6aca0,
    0xb5a0d71b, 0xf2b321e0, 0x3b873aed, 0x7c94cc16, 0x729e0ab6,
    0x358dfc4d, 0xfcb9e740, 0xbbaa11bb, 0x509cc277, 0x178f348c,
    0xdebb2f81, 0x99a8d97a, 0x97a21fda, 0xd0b1e921, 0x1985f22c,
    0x5e9604d7, 0x05907f6c, 0x42838997, 0x8bb7929a, 0xcca46461,
    0xc2aea2c1, 0x85bd543a, 0x4c894f37, 0x0b9ab9cc, 0xfa85b841,
    0xbd964eba, 0x74a255b7, 0x33b1a34c, 0x3dbb65ec, 0x7aa89317,
    0xb39c881a, 0xf48f7ee1, 0xaf89055a, 0xe89af3a1, 0x21aee8ac,
    0x66bd1e57, 0x68b7d8f7, 0x2fa42e0c, 0xe6903501, 0xa183c3fa,
    0xdfdf305a, 0x98ccc6a1, 0x51f8ddac, 0x16eb2b57, 0x18e1edf7,
    0x5ff21b0c, 0x96c60001, 0xd1d5f6fa, 0x8ad38d41, 0xcdc07bba,
    0x04f460b7, 0x43e7964c, 0x4ded50ec, 0x0afea617, 0xc3cabd1a,
    0x84d94be1, 0x75c64a6c, 0x32d5bc97, 0xfbe1a79a, 0xbcf25161,
    0xb2f897c1, 0xf5eb613a, 0x3cdf7a37, 0x7bcc8ccc, 0x20caf777,
    0x67d9018c, 0xaeed1a81, 0xe9feec7a, 0xe7f42ada, 0xa0e7dc21,
    0x69d3c72c, 0x2ec031d7, 0x956a206c, 0xd279d697, 0x1b4dcd9a,
    0x5c5e3b61, 0x5254fdc1, 0x15470b3a, 0xdc731037, 0x9b60e6cc,
    0xc0669d77, 0x87756b8c, 0x4e417081, 0x0952867a, 0x075840da,
    0x404bb621, 0x897fad2c, 0xce6c5bd7, 0x3f735a5a, 0x7860aca1,
    0xb154b7ac, 0xf6474157, 0xf84d87f7, 0xbf5e710c, 0x766a6a01,
    0x31799cfa, 0x6a7fe741, 0x2d6c11ba, 0xe4580ab7, 0xa34bfc4c,
    0xad413aec, 0xea52cc17, 0x2366d71a, 0x647521e1, 0x1a29d241,
    0x5d3a24ba, 0x940e3fb7, 0xd31dc94c, 0xdd170fec, 0x9a04f917,
    0x5330e21a, 0x142314e1, 0x4f256f5a, 0x083699a1, 0xc10282ac,
    0x86117457, 0x881bb2f7, 0xcf08440c, 0x063c5f01, 0x412fa9fa,
    0xb030a877, 0xf7235e8c, 0x3e174581, 0x7904b37a, 0x770e75da,
    0x301d8321, 0xf929982c, 0xbe3a6ed7, 0xe53c156c, 0xa22fe397,
    0x6b1bf89a, 0x2c080e61, 0x2202c8c1, 0x65113e3a, 0xac252537,
    0xeb36d3cc},
   {0x00000000, 0xa13984ee, 0x99020f9d, 0x383b8b73, 0xe975197b,
    0x484c9d95, 0x707716e6, 0xd14e9208, 0x099b34b7, 0xa8a2b059,
    0x90993b2a, 0x31a0bfc4, 0xe0ee2dcc, 0x41d7a922, 0x79ec2251,
    0xd8d5a6bf, 0x1336696e, 0xb20fed80, 0x8a3466f3, 0x2b0de21d,
    0xfa437015, 0x5b7af4fb, 0x63417f88, 0xc278fb66, 0x1aad5dd9,
    0xbb94d937, 0x83af5244, 0x2296d6aa, 0xf3d844a2, 0x52e1c04c,
    0x6ada4b3f, 0xcbe3cfd1, 0x266cd2dc, 0x87555632, 0xbf6edd41,
    0x1e5759af, 0xcf19cba7, 0x6e204f49, 0x561bc43a, 0xf72240d4,
    0x2ff7e66b, 0x8ece6285, 0xb6f5e9f6, 0x17cc6d18, 0xc682ff10,
    0x67bb7bfe, 0x5f80f08d, 0xfeb97463, 0x355abbb2, 0x94633f5c,
    0xac58b42f, 0x0d6130c1, 0xdc2fa2c9, 0x7d162627, 0x452dad54,
    0xe41429ba, 0x3cc18f05, 0x9df80beb, 0xa5c38098, 0x04fa0476,
    0xd5b4967e, 0x748d1290, 0x4cb699e3, 0xed8f1d0d, 0x4cd9a5b8,
    0xede02156, 0xd5dbaa25, 0x74e22ecb, 0xa5acbcc3, 0x0495382d,
    0x3caeb35e, 0x9d9737b0, 0x4542910f, 0xe47b15e1, 0xdc409e92,
    0x7d791a7c, 0xac378874, 0x0d0e0c9a, 0x353587e9, 0x940c0307,
    0x5fefccd6, 0xfed64838, 0xc6edc34b, 0x67d447a5, 0xb69ad5ad,
    0x17a35143, 0x2f98da30, 0x8ea15ede, 0x5674f861, 0xf74d7c8f,
    0xcf76f7fc, 0x6e4f7312, 0xbf01e11a, 0x1e3865f4, 0x2603ee87,
    0x873a6a69, 0x6ab57764, 0xcb8cf38a, 0xf3b778f9, 0x528efc17,
    0x83c06e1f, 0x22f9eaf1, 0x1ac26182, 0xbbfbe56c, 0x632e43d3,
    0xc217c73d, 0xfa2c4c4e, 0x5b15c8a0, 0x8a5b5aa8, 0x2b62de46,
    0x13595535, 0xb260d1db, 0x79831e0a, 0xd8ba9ae4, 0xe0811197,
    0x41b89579, 0x90f60771, 0x31cf839f, 0x09f408ec, 0xa8cd8c02,
    0x70182abd, 0xd121ae53, 0xe91a2520, 0x4823a1ce, 0x996d33c6,
    0x3854b728, 0x006f3c5b, 0xa156b8b5, 0x99b34b70, 0x388acf9e,
    0x00b144ed, 0xa188c003, 0x70c6520b, 0xd1ffd6e5, 0xe9c45d96,
    0x48fdd978, 0x90287fc7, 0x3111fb29, 0x092a705a, 0xa813f4b4,
    0x795d66bc, 0xd864e252, 0xe05f6921, 0x4166edcf, 0x8a85221e,
    0x2bbca6f0, 0x13872d83, 0xb2bea96d, 0x63f03b65, 0xc2c9bf8b,
    0xfaf234f8, 0x5bcbb016, 0x831e16a9, 0x22279247, 0x1a1c1934,
    0xbb259dda, 0x6a6b0fd2, 0xcb528b3c, 0xf369004f, 0x525084a1,
    0xbfdf99ac, 0x1ee61d42, 0x26dd9631, 0x87e412df, 0x56aa80d7,
    0xf7930439, 0xcfa88f4a, 0x6e910ba4, 0xb644ad1b, 0x177d29f5,
    0x2f46a286, 0x8e7f2668, 0x5f31b460, 0xfe08308e, 0xc633bbfd,
    0x670a3f13, 0xace9f0c2, 0x0dd0742c, 0x35ebff5f, 0x94d27bb1,
    0x459ce9b9, 0xe4a56d57, 0xdc9ee624, 0x7da762ca, 0xa572c475,
    0x044b409b, 0x3c70cbe8, 0x9d494f06, 0x4c07dd0e, 0xed3e59e0,
    0xd505d293, 0x743c567d, 0xd56aeec8, 0x74536a26, 0x4c68e155,
    0xed5165bb, 0x3c1ff7b3, 0x9d26735d, 0xa51df82e, 0x04247cc0,
    0xdcf1da7f, 0x7dc85e91, 0x45f3d5e2, 0xe4ca510c, 0x3584c304,
    0x94bd47ea, 0xac86cc99, 0x0dbf4877, 0xc65c87a6, 0x67650348,
    0x5f5e883b, 0xfe670cd5, 0x2f299edd, 0x8e101a33, 0xb62b9140,
    0x171215ae, 0xcfc7b311, 0x6efe37ff, 0x56c5bc8c, 0xf7fc3862,
    0x26b2aa6a, 0x878b2e84, 0xbfb0a5f7, 0x1e892119, 0xf3063c14,
    0x523fb8fa, 0x6a043389, 0xcb3db767, 0x1a73256f, 0xbb4aa181,
    0x83712af2, 0x2248ae1c, 0xfa9d08a3, 0x5ba48c4d, 0x639f073e,
    0xc2a683d0, 0x13e811d8, 0xb2d19536, 0x8aea1e45, 0x2bd39aab,
    0xe030557a, 0x4109d194, 0x79325ae7, 0xd80bde09, 0x09454c01,
    0xa87cc8ef, 0x9047439c, 0x317ec772, 0xe9ab61cd, 0x4892e523,
    0x70a96e50, 0xd190eabe, 0x00de78b6, 0xa1e7fc58, 0x99dc772b,
    0x38e5f3c5},
   {0x00000000, 0xe81790a1, 0x0b5e2703, 0xe349b7a2, 0x16bc4e06,
    0xfeabdea7, 0x1de26905, 0xf5f5f9a4, 0x2d789c0c, 0xc56f0cad,
    0x2626bb0f, 0xce312bae, 0x3bc4d20a, 0xd3d342ab, 0x309af509,
    0xd88d65a8, 0x5af13818, 0xb2e6a8b9, 0x51af1f1b, 0xb9b88fba,
    0x4c4d761e, 0xa45ae6bf, 0x4713511d, 0xaf04c1bc, 0x7789a414,
    0x9f9e34b5, 0x7cd78317, 0x94c013b6, 0x6135ea12, 0x89227ab3,
    0x6a6bcd11, 0x827c5db0, 0xb5e27030, 0x5df5e091, 0xbebc5733,
    0x56abc792, 0xa35e3e36, 0x4b49ae97, 0xa8001935, 0x40178994,
    0x989aec3c, 0x708d7c9d, 0x93c4cb3f, 0x7bd35b9e, 0x8e26a23a,
    0x6631329b, 0x85788539, 0x6d6f1598, 0xef134828, 0x0704d889,
    0xe44d6f2b, 0x0c5aff8a, 0xf9af062e, 0x11b8968f, 0xf2f1212d,
    0x1ae6b18c, 0xc26bd424, 0x2a7c4485, 0xc935f327, 0x21226386,
    0xd4d79a22, 0x3cc00a83, 0xdf89bd21, 0x379e2d80, 0xb0b5e621,
    0x58a27680, 0xbbebc122, 0x53fc5183, 0xa609a827, 0x4e1e3886,
    0xad578f24, 0x45401f85, 0x9dcd7a2d, 0x75daea8c, 0x96935d2e,
    0x7e84cd8f, 0x8b71342b, 0x6366a48a, 0x802f1328, 0x68388389,
    0xea44de39, 0x02534e98, 0xe11af93a, 0x090d699b, 0xfcf8903f,
    0x14ef009e, 0xf7a6b73c, 0x1fb1279d, 0xc73c4235, 0x2f2bd294,
    0xcc626536, 0x2475f597, 0xd1800c33, 0x39979c92, 0xdade2b30,
    0x32c9bb91, 0x05579611, 0xed4006b0, 0x0e09b112, 0xe61e21b3,
    0x13ebd817, 0xfbfc48b6, 0x18b5ff14, 0xf0a26fb5, 0x282f0a1d,
    0xc0389abc, 0x23712d1e, 0xcb66bdbf, 0x3e93441b, 0xd684d4ba,
    0x35cd6318, 0xdddaf3b9, 0x5fa6ae09, 0xb7b13ea8, 0x54f8890a,
    0xbcef19ab, 0x491ae00f, 0xa10d70ae, 0x4244c70c, 0xaa5357ad,
    0x72de3205, 0x9ac9a2a4, 0x79801506, 0x919785a7, 0x64627c03,
    0x8c75eca2, 0x6f3c5b00, 0x872bcba1, 0xba1aca03, 0x520d5aa2,
    0xb144ed00, 0x59537da1, 0xaca68405, 0x44b114a4, 0xa7f8a306,
    0x4fef33a7, 0x9762560f, 0x7f75c6ae, 0x9c3c710c, 0x742be1ad,
    0x81de1809, 0x69c988a8, 0x8a803f0a, 0x6297afab, 0xe0ebf21b,
    0x08fc62ba, 0xebb5d518, 0x03a245b9, 0xf657bc1d, 0x1e402cbc,
    0xfd099b1e, 0x151e0bbf, 0xcd936e17, 0x2584feb6, 0xc6cd4914,
    0x2edad9b5, 0xdb2f2011, 0x3338b0b0, 0xd0710712, 0x386697b3,
    0x0ff8ba33, 0xe7ef2a92, 0x04a69d30, 0xecb10d91, 0x1944f435,
    0xf1536494, 0x121ad336, 0xfa0d4397, 0x2280263f, 0xca97b69e,
    0x29de013c, 0xc1c9919d, 0x343c6839, 0xdc2bf898, 0x3f624f3a,
    0xd775df9b, 0x5509822b, 0xbd1e128a, 0x5e57a528, 0xb6403589,
    0x43b5cc2d, 0xaba25c8c, 0x48ebeb2e, 0xa0fc7b8f, 0x78711e27,
    0x90668e86, 0x732f3924, 0x9b38a985, 0x6ecd5021, 0x86dac080,
    0x65937722, 0x8d84e783, 0x0aaf2c22, 0xe2b8bc83, 0x01f10b21,
    0xe9e69b80, 0x1c136224, 0xf404f285, 0x174d4527, 0xff5ad586,
    0x27d7b02e, 0xcfc0208f, 0x2c89972d, 0xc49e078c, 0x316bfe28,
    0xd97c6e89, 0x3a35d92b, 0xd222498a, 0x505e143a, 0xb849849b,
    0x5b003339, 0xb317a398, 0x46e25a3c, 0xaef5ca9d, 0x4dbc7d3f,
    0xa5abed9e, 0x7d268836, 0x95311897, 0x7678af35, 0x9e6f3f94,
    0x6b9ac630, 0x838d5691, 0x60c4e133, 0x88d37192, 0xbf4d5c12,
    0x575accb3, 0xb4137b11, 0x5c04ebb0, 0xa9f11214, 0x41e682b5,
    0xa2af3517, 0x4ab8a5b6, 0x9235c01e, 0x7a2250bf, 0x996be71d,
    0x717c77bc, 0x84898e18, 0x6c9e1eb9, 0x8fd7a91b, 0x67c039ba,
    0xe5bc640a, 0x0dabf4ab, 0xeee24309, 0x06f5d3a8, 0xf3002a0c,
    0x1b17baad, 0xf85e0d0f, 0x10499dae, 0xc8c4f806, 0x20d368a7,
    0xc39adf05, 0x2b8d4fa4, 0xde78b600, 0x366f26a1, 0xd5269103,
    0x3d3101a2}};

local const z_word_t FAR crc_braid_big_table[][256] = {
   {0x0000000000000000, 0xa19017e800000000, 0x03275e0b00000000,
    0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
    0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
    0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
    0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
    0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
    0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
    0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
    0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
    0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
    0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
    0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
    0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
    0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
    0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
    0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
    0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
    0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
    0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
    0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
    0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
    0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
    0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
    0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
    0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
    0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
    0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
    0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
    0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
    0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
    0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
    0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
    0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
    0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
    0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
    0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
    0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
    0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
    0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
    0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
    0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
    0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
    0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
    0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
    0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
    0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
    0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
    0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
    0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
    0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
    0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
    0xf10605deUL
    0xa2b749e300000000, 0x064ebc1600000000, 0xa7deabfe00000000,
    0x0569e21d00000000, 0xa4f9f5f500000000, 0x0c9c782d00000000,
    0xad0c6fc500000000, 0x0fbb262600000000, 0xae2b31ce00000000,
    0x0ad2c43b00000000, 0xab42d3d300000000, 0x09f59a3000000000,
    0xa8658dd800000000, 0x1838f15a00000000, 0xb9a8e6b200000000,
    0x1b1faf5100000000, 0xba8fb8b900000000, 0x1e764d4c00000000,
    0xbfe65aa400000000, 0x1d51134700000000, 0xbcc104af00000000,
    0x14a4897700000000, 0xb5349e9f00000000, 0x1783d77c00000000,
    0xb613c09400000000, 0x12ea356100000000, 0xb37a228900000000,
    0x11cd6b6a00000000, 0xb05d7c8200000000, 0x3070e2b500000000,
    0x91e0f55d00000000, 0x3357bcbe00000000, 0x92c7ab5600000000,
    0x363e5ea300000000, 0x97ae494b00000000, 0x351900a800000000,
    0x9489174000000000, 0x3cec9a9800000000, 0x9d7c8d7000000000,
    0x3fcbc49300000000, 0x9e5bd37b00000000, 0x3aa2268e00000000,
    0x9b32316600000000, 0x3985788500000000, 0x98156f6d00000000,
    0x284813ef00000000, 0x89d8040700000000, 0x2b6f4de400000000,
    0x8aff5a0c00000000, 0x2e06aff900000000, 0x8f96b81100000000,
    0x2d21f1f200000000, 0x8cb1e61a00000000, 0x24d46bc200000000,
    0x85447c2a00000000, 0x27f335c900000000, 0x8663222100000000,
    0x229ad7d400000000, 0x830ac03c00000000, 0x21bd89df00000000,
    0x802d9e3700000000, 0x21e6b5b000000000, 0x8076a25800000000,
    0x22c1ebbb00000000, 0x8351fc5300000000, 0x27a809a600000000,
    0x86381e4e00000000, 0x248f57ad00000000, 0x851f404500000000,
    0x2d7acd9d00000000, 0x8ceada7500000000, 0x2e5d939600000000,
    0x8fcd847e00000000, 0x2b34718b00000000, 0x8aa4666300000000,
    0x28132f8000000000, 0x8983386800000000, 0x39de44ea00000000,
    0x984e530200000000, 0x3af91ae100000000, 0x9b690d0900000000,
    0x3f90f8fc00000000, 0x9e00ef1400000000, 0x3cb7a6f700000000,
    0x9d27b11f00000000, 0x35423cc700000000, 0x94d22b2f00000000,
    0x366562cc00000000, 0x97f5752400000000, 0x330c80d100000000,
    0x929c973900000000, 0x302bdeda00000000, 0x91bbc93200000000,
    0x1196570500000000, 0xb00640ed00000000, 0x12b1090e00000000,
    0xb3211ee600000000, 0x17d8eb1300000000, 0xb648fcfb00000000,
    0x14ffb51800000000, 0xb56fa2f000000000, 0x1d0a2f2800000000,
    0xbc9a38c000000000, 0x1e2d712300000000, 0xbfbd66cb00000000,
    0x1b44933e00000000, 0xbad484d600000000, 0x1863cd3500000000,
    0xb9f3dadd00000000, 0x09aea65f00000000, 0xa83eb1b700000000,
    0x0a89f85400000000, 0xab19efbc00000000, 0x0fe01a4900000000,
    0xae700da100000000, 0x0cc7444200000000, 0xad5753aa00000000,
    0x0532de7200000000, 0xa4a2c99a00000000, 0x0615807900000000,
    0xa785979100000000, 0x037c626400000000, 0xa2ec758c00000000,
    0x005b3c6f00000000, 0xa1cb2b8700000000, 0x03ca1aba00000000,
    0xa25a0d5200000000, 0x00ed44b100000000, 0xa17d535900000000,
    0x0584a6ac00000000, 0xa414b14400000000, 0x06a3f8a700000000,
    0xa733ef4f00000000, 0x0f56629700000000, 0xaec6757f00000000,
    0x0c713c9c00000000, 0xade12b7400000000, 0x0918de8100000000,
    0xa888c96900000000, 0x0a3f808a00000000, 0xabaf976200000000,
    0x1bf2ebe000000000, 0xba62fc0800000000, 0x18d5b5eb00000000,
    0xb945a20300000000, 0x1dbc57f600000000, 0xbc2c401e00000000,
    0x1e9b09fd00000000, 0xbf0b1e1500000000, 0x176e93cd00000000,
    0xb6fe842500000000, 0x1449cdc600000000, 0xb5d9da2e00000000,
    0x11202fdb00000000, 0xb0b0383300000000, 0x120771d000000000,
    0xb397663800000000, 0x33baf80f00000000, 0x922aefe700000000,
    0x309da60400000000, 0x910db1ec00000000, 0x35f4441900000000,
    0x946453f100000000, 0x36d31a1200000000, 0x97430dfa00000000,
    0x3f26802200000000, 0x9eb697ca00000000, 0x3c01de2900000000,
    0x9d91c9c100000000, 0x39683c3400000000, 0x98f82bdc00000000,
    0x3a4f623f00000000, 0x9bdf75d700000000, 0x2b82095500000000,
    0x8a121ebd00000000, 0x28a5575e00000000, 0x893540b600000000,
    0x2dccb54300000000, 0x8c5ca2ab00000000, 0x2eebeb4800000000,
    0x8f7bfca000000000, 0x271e717800000000, 0x868e669000000000,
    0x24392f7300000000, 0x85a9389b00000000, 0x2150cd6e00000000,
    0x80c0da8600000000, 0x2277936500000000, 0x83e7848d00000000,
    0x222caf0a00000000, 0x83bcb8e200000000, 0x210bf10100000000,
    0x809be6e900000000, 0x2462131c00000000, 0x85f204f400000000,
    0x27454d1700000000, 0x86d55aff00000000, 0x2eb0d72700000000,
    0x8f20c0cf00000000, 0x2d97892c00000000, 0x8c079ec400000000,
    0x28fe6b3100000000, 0x896e7cd900000000, 0x2bd9353a00000000,
    0x8a4922d200000000, 0x3a145e5000000000, 0x9b8449b800000000,
    0x3933005b00000000, 0x98a317b300000000, 0x3c5ae24600000000,
    0x9dcaf5ae00000000, 0x3f7dbc4d00000000, 0x9eedaba500000000,
    0x3688267d00000000, 0x9718319500000000, 0x35af787600000000,
    0x943f6f9e00000000, 0x30c69a6b00000000, 0x91568d8300000000,
    0x33e1c46000000000, 0x9271d38800000000, 0x125c4dbf00000000,
    0xb3cc5a5700000000, 0x117b13b400000000, 0xb0eb045c00000000,
    0x1412f1a900000000, 0xb582e64100000000, 0x1735afa200000000,
    0xb6a5b84a00000000, 0x1ec0359200000000, 0xbf50227a00000000,
    0x1de76b9900000000, 0xbc777c7100000000, 0x188e898400000000,
    0xb91e9e6c00000000, 0x1ba9d78f00000000, 0xba39c06700000000,
    0x0a64bce500000000, 0xabf4ab0d00000000, 0x0943e2ee00000000,
    0xa8d3f50600000000, 0x0c2a00f300000000, 0xadba171b00000000,
    0x0f0d5ef800000000, 0xae9d491000000000, 0x06f8c4c800000000,
    0xa768d32000000000, 0x05df9ac300000000, 0xa44f8d2b00000000,
    0x00b678de00000000, 0xa1266f3600000000, 0x039126d500000000,
    0xa201313d00000000},
   {0x0000000000000000, 0xee8439a100000000, 0x9d0f029900000000,
    0x738b3b3800000000, 0x7b1975e900000000, 0x959d4c4800000000,
    0xe616777000000000, 0x08924ed100000000, 0xb7349b0900000000,
    0x59b0a2a800000000, 0x2a3b999000000000, 0xc4bfa03100000000,
    0xcc2deee000000000, 0x22a9d74100000000, 0x5122ec7900000000,
    0xbfa6d5d800000000, 0x6e69361300000000, 0x80ed0fb200000000,
    0xf366348a00000000, 0x1de20d2b00000000, 0x157043fa00000000,
    0xfbf47a5b00000000, 0x887f416300000000, 0x66fb78c200000000,
    0xd95dad1a00000000, 0x37d994bb00000000, 0x4452af8300000000,
    0xaad6962200000000, 0xa244d8f300000000, 0x4cc0e15200000000,
    0x3f4bda6a00000000, 0xd1cfe3cb00000000, 0xdcd26c2600000000,
    0x3256558700000000, 0x41dd6ebf00000000, 0xaf59571e00000000,
    0xa7cb19cf00000000, 0x494f206e00000000, 0x3ac41b5600000000,
    0xd44022f700000000, 0x6be6f72f00000000, 0x8562ce8e00000000,
    0xf6e9f5b600000000, 0x186dcc1700000000, 0x10ff82c600000000,
    0xfe7bbb6700000000, 0x8df0805f00000000, 0x6374b9fe00000000,
    0xb2bb5a3500000000, 0x5c3f639400000000, 0x2fb458ac00000000,
    0xc130610d00000000, 0xc9a22fdc00000000, 0x2726167d00000000,
    0x54ad2d4500000000, 0xba2914e400000000, 0x058fc13c00000000,
    0xeb0bf89d00000000, 0x9880c3a500000000, 0x7604fa0400000000,
    0x7e96b4d500000000, 0x90128d7400000000, 0xe399b64c00000000,
    0x0d1d8fed00000000, 0xb8a5d94c00000000, 0x5621e0ed00000000,
    0x25aadbd500000000, 0xcb2ee27400000000, 0xc3bcaca500000000,
    0x2d38950400000000, 0x5eb3ae3c00000000, 0xb037979d00000000,
    0x0f91424500000000, 0xe1157be400000000, 0x929e40dc00000000,
    0x7c1a797d00000000, 0x748837ac00000000, 0x9a0c0e0d00000000,
    0xe987353500000000, 0x07030c9400000000, 0xd6ccef5f00000000,
    0x3848d6fe00000000, 0x4bc3edc600000000, 0xa547d46700000000,
    0xadd59ab600000000, 0x4351a31700000000, 0x30da982f00000000,
    0xde5ea18e00000000, 0x61f8745600000000, 0x8f7c4df700000000,
    0xfcf776cf00000000, 0x12734f6e00000000, 0x1ae101bf00000000,
    0xf465381e00000000, 0x87ee032600000000, 0x696a3a8700000000,
    0x6477b56a00000000, 0x8af38ccb00000000, 0xf978b7f300000000,
    0x17fc8e5200000000, 0x1f6ec08300000000, 0xf1eaf92200000000,
    0x8261c21a00000000, 0x6ce5fbbb00000000, 0xd3432e6300000000,
    0x3dc717c200000000, 0x4e4c2cfa00000000, 0xa0c8155b00000000,
    0xa85a5b8a00000000, 0x46de622b00000000, 0x3555591300000000,
    0xdbd160b200000000, 0x0a1e837900000000, 0xe49abad800000000,
    0x971181e000000000, 0x7995b84100000000, 0x7107f69000000000,
    0x9f83cf3100000000, 0xec08f40900000000, 0x028ccda800000000,
    0xbd2a187000000000, 0x53ae21d100000000, 0x20251ae900000000,
    0xcea1234800000000, 0xc6336d9900000000, 0x28b7543800000000,
    0x5b3c6f0000000000, 0xb5b856a100000000, 0x704bb39900000000,
    0x9ecf8a3800000000, 0xed44b10000000000, 0x03c088a100000000,
    0x0b52c67000000000, 0xe5d6ffd100000000, 0x965dc4e900000000,
    0x78d9fd4800000000, 0xc77f289000000000, 0x29fb113100000000,
    0x5a702a0900000000, 0xb4f413a800000000, 0xbc665d7900000000,
    0x52e264d800000000, 0x21695fe000000000, 0xcfed664100000000,
    0x1e22858a00000000, 0xf0a6bc2b00000000, 0x832d871300000000,
    0x6da9beb200000000, 0x653bf06300000000, 0x8bbfc9c200000000,
    0xf834f2fa00000000, 0x16b0cb5b00000000, 0xa9161e8300000000,
    0x4792272200000000, 0x34191c1a00000000, 0xda9d25bb00000000,
    0xd20f6b6a00000000, 0x3c8b52cb00000000, 0x4f0069f300000000,
    0xa184505200000000, 0xac99dfbf00000000, 0x421de61e00000000,
    0x3196dd2600000000, 0xdf12e48700000000, 0xd780aa5600000000,
    0x390493f700000000, 0x4a8fa8cf00000000, 0xa40b916e00000000,
    0x1bad44b600000000, 0xf5297d1700000000, 0x86a2462f00000000,
    0x68267f8e00000000, 0x60b4315f00000000, 0x8e3008fe00000000,
    0xfdbb33c600000000, 0x133f0a6700000000, 0xc2f0e9ac00000000,
    0x2c74d00d00000000, 0x5fffeb3500000000, 0xb17bd29400000000,
    0xb9e99c4500000000, 0x576da5e400000000, 0x24e69edc00000000,
    0xca62a77d00000000, 0x75c472a500000000, 0x9b404b0400000000,
    0xe8cb703c00000000, 0x064f499d00000000, 0x0edd074c00000000,
    0xe0593eed00000000, 0x93d205d500000000, 0x7d563c7400000000,
    0xc8ee6ad500000000, 0x266a537400000000, 0x55e1684c00000000,
    0xbb6551ed00000000, 0xb3f71f3c00000000, 0x5d73269d00000000,
    0x2ef81da500000000, 0xc07c240400000000, 0x7fdaf1dc00000000,
    0x915ec87d00000000, 0xe2d5f34500000000, 0x0c51cae400000000,
    0x04c3843500000000, 0xea47bd9400000000, 0x99cc86ac00000000,
    0x7748bf0d00000000, 0xa6875cc600000000, 0x4803656700000000,
    0x3b885e5f00000000, 0xd50c67fe00000000, 0xdd9e292f00000000,
    0x331a108e00000000, 0x40912bb600000000, 0xae15121700000000,
    0x11b3c7cf00000000, 0xff37fe6e00000000, 0x8cbcc55600000000,
    0x6238fcf700000000, 0x6aaab22600000000, 0x842e8b8700000000,
    0xf7a5b0bf00000000, 0x1921891e00000000, 0x143c06f300000000,
    0xfab83f5200000000, 0x8933046a00000000, 0x67b73dcb00000000,
    0x6f25731a00000000, 0x81a14abb00000000, 0xf22a718300000000,
    0x1cae482200000000, 0xa3089dfa00000000, 0x4d8ca45b00000000,
    0x3e079f6300000000, 0xd083a6c200000000, 0xd811e81300000000,
    0x3695d1b200000000, 0x451eea8a00000000, 0xab9ad32b00000000,
    0x7a5530e000000000, 0x94d1094100000000, 0xe75a327900000000,
    0x09de0bd800000000, 0x014c450900000000, 0xefc87ca800000000,
    0x9c43479000000000, 0x72c77e3100000000, 0xcd61abe900000000,
    0x23e5924800000000, 0x506ea97000000000, 0xbeea90d100000000,
    0xb678de0000000000, 0x58fce7a100000000, 0x2b77dc9900000000,
    0xc5f3e53800000000},
   {0x0000000000000000, 0xfbf6134700000000, 0xf6ed278e00000000,
    0x0d1b34c900000000, 0xaddd3ec700000000, 0x562b2d8000000000,
    0x5b30194900000000, 0xa0c60a0e00000000, 0x1bbd0c5500000000,
    0xe04b1f1200000000, 0xed502bdb00000000, 0x16a6389c00000000,
    0xb660329200000000, 0x4d9621d500000000, 0x408d151c00000000,
    0xbb7b065b00000000, 0x367a19aa00000000, 0xcd8c0aed00000000,
    0xc0973e2400000000, 0x3b612d6300000000, 0x9ba7276d00000000,
    0x6051342a00000000, 0x6d4a00e300000000, 0x96bc13a400000000,
    0x2dc715ff00000000, 0xd63106b800000000, 0xdb2a327100000000,
    0x20dc213600000000, 0x801a2b3800000000, 0x7bec387f00000000,
    0x76f70cb600000000, 0x8d011ff100000000, 0x2df2438f00000000,
    0xd60450c800000000, 0xdb1f640100000000, 0x20e9774600000000,
    0x802f7d4800000000, 0x7bd96e0f00000000, 0x76c25ac600000000,
    0x8d34498100000000, 0x364f4fda00000000, 0xcdb95c9d00000000,
    0xc0a2685400000000, 0x3b547b1300000000, 0x9b92711d00000000,
    0x6064625a00000000, 0x6d7f569300000000, 0x968945d400000000,
    0x1b885a2500000000, 0xe07e496200000000, 0xed657dab00000000,
    0x16936eec00000000, 0xb65564e200000000, 0x4da377a500000000,
    0x40b8436c00000000, 0xbb4e502b00000000, 0x0035567000000000,
    0xfbc3453700000000, 0xf6d871fe00000000, 0x0d2e62b900000000,
    0xade868b700000000, 0x561e7bf000000000, 0x5b054f3900000000,
    0xa0f35c7e00000000, 0x1be2f6c500000000, 0xe014e58200000000,
    0xed0fd14b00000000, 0x16f9c20c00000000, 0xb63fc80200000000,
    0x4dc9db4500000000, 0x40d2ef8c00000000, 0xbb24fccb00000000,
    0x005ffa9000000000, 0xfba9e9d700000000, 0xf6b2dd1e00000000,
    0x0d44ce5900000000, 0xad82c45700000000, 0x5674d71000000000,
    0x5b6fe3d900000000, 0xa099f09e00000000, 0x2d98ef6f00000000,
    0xd66efc2800000000, 0xdb75c8e100000000, 0x2083dba600000000,
    0x8045d1a800000000, 0x7bb3c2ef00000000, 0x76a8f62600000000,
    0x8d5ee56100000000, 0x3625e33a00000000, 0xcdd3f07d00000000,
    0xc0c8c4b400000000, 0x3b3ed7f300000000, 0x9bf8ddfd00000000,
    0x600eceba00000000, 0x6d15fa7300000000, 0x96e3e93400000000,
    0x3610b54a00000000, 0xcde6a60d00000000, 0xc0fd92c400000000,
    0x3b0b818300000000, 0x9bcd8b8d00000000, 0x603b98ca00000000,
    0x6d20ac0300000000, 0x96d6bf4400000000, 0x2dadb91f00000000,
    0xd65baa5800000000, 0xdb409e9100000000, 0x20b68dd600000000,
    0x807087d800000000, 0x7b86949f00000000, 0x769da05600000000,
    0x8d6bb31100000000, 0x006aace000000000, 0xfb9cbfa700000000,
    0xf6878b6e00000000, 0x0d71982900000000, 0xadb7922700000000,
    0x5641816000000000, 0x5b5ab5a900000000, 0xa0aca6ee00000000,
    0x1bd7a0b500000000, 0xe021b3f200000000, 0xed3a873b00000000,
    0x16cc947c00000000, 0xb60a9e7200000000, 0x4dfc8d3500000000,
    0x40e7b9fc00000000, 0xbb11aabb00000000, 0x77c29c5000000000,
    0x8c348f1700000000, 0x812fbbde00000000, 0x7ad9a89900000000,
    0xda1fa29700000000, 0x21e9b1d000000000, 0x2cf2851900000000,
    0xd704965e00000000, 0x6c7f900500000000, 0x9789834200000000,
    0x9a92b78b00000000, 0x6164a4cc00000000, 0xc1a2aec200000000,
    0x3a54bd8500000000, 0x374f894c00000000, 0xccb99a0b00000000,
    0x41b885fa00000000, 0xba4e96bd00000000, 0xb755a27400000000,
    0x4ca3b13300000000, 0xec65bb3d00000000, 0x1793a87a00000000,
    0x1a889cb300000000, 0xe17e8ff400000000, 0x5a0589af00000000,
    0xa1f39ae800000000, 0xace8ae2100000000, 0x571ebd6600000000,
    0xf7d8b76800000000, 0x0c2ea42f00000000, 0x013590e600000000,
    0xfac383a100000000, 0x5a30dfdf00000000, 0xa1c6cc9800000000,
    0xacddf85100000000, 0x572beb1600000000, 0xf7ede11800000000,
    0x0c1bf25f00000000, 0x0100c69600000000, 0xfaf6d5d100000000,
    0x418dd38a00000000, 0xba7bc0cd00000000, 0xb760f40400000000,
    0x4c96e74300000000, 0xec50ed4d00000000, 0x17a6fe0a00000000,
    0x1abdcac300000000, 0xe14bd98400000000, 0x6c4ac67500000000,
    0x97bcd53200000000, 0x9aa7e1fb00000000, 0x6151f2bc00000000,
    0xc197f8b200000000, 0x3a61ebf500000000, 0x377adf3c00000000,
    0xcc8ccc7b00000000, 0x77f7ca2000000000, 0x8c01d96700000000,
    0x811aedae00000000, 0x7aecfee900000000, 0xda2af4e700000000,
    0x21dce7a000000000, 0x2cc7d36900000000, 0xd731c02e00000000,
    0x6c206a9500000000, 0x97d679d200000000, 0x9acd4d1b00000000,
    0x613b5e5c00000000, 0xc1fd545200000000, 0x3a0b471500000000,
    0x371073dc00000000, 0xcce6609b00000000, 0x779d66c000000000,
    0x8c6b758700000000, 0x8170414e00000000, 0x7a86520900000000,
    0xda40580700000000, 0x21b64b4000000000, 0x2cad7f8900000000,
    0xd75b6cce00000000, 0x5a5a733f00000000, 0xa1ac607800000000,
    0xacb754b100000000, 0x574147f600000000, 0xf7874df800000000,
    0x0c715ebf00000000, 0x016a6a7600000000, 0xfa9c793100000000,
    0x41e77f6a00000000, 0xba116c2d00000000, 0xb70a58e400000000,
    0x4cfc4ba300000000, 0xec3a41ad00000000, 0x17cc52ea00000000,
    0x1ad7662300000000, 0xe121756400000000, 0x41d2291a00000000,
    0xba243a5d00000000, 0xb73f0e9400000000, 0x4cc91dd300000000,
    0xec0f17dd00000000, 0x17f9049a00000000, 0x1ae2305300000000,
    0xe114231400000000, 0x5a6f254f00000000, 0xa199360800000000,
    0xac8202c100000000, 0x5774118600000000, 0xf7b21b8800000000,
    0x0c4408cf00000000, 0x015f3c0600000000, 0xfaa92f4100000000,
    0x77a830b000000000, 0x8c5e23f700000000, 0x8145173e00000000,
    0x7ab3047900000000, 0xda750e7700000000, 0x21831d3000000000,
    0x2c9829f900000000, 0xd76e3abe00000000, 0x6c153ce500000000,
    0x97e32fa200000000, 0x9af81b6b00000000, 0x610e082c00000000,
    0xc1c8022200000000, 0x3a3e116500000000, 0x372525ac00000000,
    0xccd336eb00000000},
   {0x0000000000000000, 0x6238282a00000000, 0xc470505400000000,
    0xa648787e00000000, 0x88e1a0a800000000, 0xead9888200000000,
    0x4c91f0fc00000000, 0x2ea9d8d600000000, 0x51c5308a00000000,
    0x33fd18a000000000, 0x95b560de00000000, 0xf78d48f400000000,
    0xd924902200000000, 0xbb1cb80800000000, 0x1d54c07600000000,
    0x7f6ce85c00000000, 0xe38c10cf00000000, 0x81b438e500000000,
    0x27fc409b00000000, 0x45c468b100000000, 0x6b6db06700000000,
    0x0955984d00000000, 0xaf1de03300000000, 0xcd25c81900000000,
    0xb249204500000000, 0xd071086f00000000, 0x7639701100000000,
    0x1401583b00000000, 0x3aa880ed00000000, 0x5890a8c700000000,
    0xfed8d0b900000000, 0x9ce0f89300000000, 0x871f504500000000,
    0xe527786f00000000, 0x436f001100000000, 0x2157283b00000000,
    0x0ffef0ed00000000, 0x6dc6d8c700000000, 0xcb8ea0b900000000,
    0xa9b6889300000000, 0xd6da60cf00000000, 0xb4e248e500000000,
    0x12aa309b00000000, 0x709218b100000000, 0x5e3bc06700000000,
    0x3c03e84d00000000, 0x9a4b903300000000, 0xf873b81900000000,
    0x6493408a00000000, 0x06ab68a000000000, 0xa0e310de00000000,
    0xc2db38f400000000, 0xec72e02200000000, 0x8e4ac80800000000,
    0x2802b07600000000, 0x4a3a985c00000000, 0x3556700000000000,
    0x576e582a00000000, 0xf126205400000000, 0x931e087e00000000,
    0xbdb7d0a800000000, 0xdf8ff88200000000, 0x79c780fc00000000,
    0x1bffa8d600000000, 0x0e3fa08a00000000, 0x6c0788a000000000,
    0xca4ff0de00000000, 0xa877d8f400000000, 0x86de002200000000,
    0xe4e6280800000000, 0x42ae507600000000, 0x2096785c00000000,
    0x5ffa900000000000, 0x3dc2b82a00000000, 0x9b8ac05400000000,
    0xf9b2e87e00000000, 0xd71b30a800000000, 0xb523188200000000,
    0x136b60fc00000000, 0x715348d600000000, 0xedb3b04500000000,
    0x8f8b986f00000000, 0x29c3e01100000000, 0x4bfbc83b00000000,
    0x655210ed00000000, 0x076a38c700000000, 0xa12240b900000000,
    0xc31a689300000000, 0xbc7680cf00000000, 0xde4ea8e500000000,
    0x7806d09b00000000, 0x1a3ef8b100000000, 0x3497206700000000,
    0x56af084d00000000, 0xf0e7703300000000, 0x92df581900000000,
    0x8920f0cf00000000, 0xeb18d8e500000000, 0x4d50a09b00000000,
    0x2f6888b100000000, 0x01c1506700000000, 0x63f9784d00000000,
    0xc5b1003300000000, 0xa789281900000000, 0xd8e5c04500000000,
    0xbadde86f00000000, 0x1c95901100000000, 0x7eadb83b00000000,
    0x500460ed00000000, 0x323c48c700000000, 0x947430b900000000,
    0xf64c189300000000, 0x6aace00000000000, 0x0894c82a00000000,
    0xaedcb05400000000, 0xcce4987e00000000, 0xe24d40a800000000,
    0x8075688200000000, 0x263d10fc00000000, 0x440538d600000000,
    0x3b69d08a00000000, 0x5951f8a000000000, 0xff1980de00000000,
    0x9d21a8f400000000, 0xb388702200000000, 0xd1b0580800000000,
    0x77f8207600000000, 0x15c0085c00000000, 0x5d7831ce00000000,
    0x3f4019e400000000, 0x9908619a00000000, 0xfb3049b000000000,
    0xd599916600000000, 0xb7a1b94c00000000, 0x11e9c13200000000,
    0x73d1e91800000000, 0x0cbd014400000000, 0x6e85296e00000000,
    0xc8cd511000000000, 0xaaf5793a00000000, 0x845ca1ec00000000,
    0xe66489c600000000, 0x402cf1b800000000, 0x2214d99200000000,
    0xbef4210100000000, 0xdccc092b00000000, 0x7a84715500000000,
    0x18bc597f00000000, 0x361581a900000000, 0x542da98300000000,
    0xf265d1fd00000000, 0x905df9d700000000, 0xef31118b00000000,
    0x8d0939a100000000, 0x2b4141df00000000, 0x497969f500000000,
    0x67d0b12300000000, 0x05e8990900000000, 0xa3a0e17700000000,
    0xc198c95d00000000, 0xda67618b00000000, 0xb85f49a100000000,
    0x1e1731df00000000, 0x7c2f19f500000000, 0x5286c12300000000,
    0x30bee90900000000, 0x96f6917700000000, 0xf4ceb95d00000000,
    0x8ba2510100000000, 0xe99a792b00000000, 0x4fd2015500000000,
    0x2dea297f00000000, 0x0343f1a900000000, 0x617bd98300000000,
    0xc733a1fd00000000, 0xa50b89d700000000, 0x39eb714400000000,
    0x5bd3596e00000000, 0xfd9b211000000000, 0x9fa3093a00000000,
    0xb10ad1ec00000000, 0xd332f9c600000000, 0x757a81b800000000,
    0x1742a99200000000, 0x682e41ce00000000, 0x0a1669e400000000,
    0xac5e119a00000000, 0xce6639b000000000, 0xe0cfe16600000000,
    0x82f7c94c00000000, 0x24bfb13200000000, 0x4687991800000000,
    0x5347914400000000, 0x317fb96e00000000, 0x9737c11000000000,
    0xf50fe93a00000000, 0xdba631ec00000000, 0xb99e19c600000000,
    0x1fd661b800000000, 0x7dee499200000000, 0x0282a1ce00000000,
    0x60ba89e400000000, 0xc6f2f19a00000000, 0xa4cad9b000000000,
    0x8a63016600000000, 0xe85b294c00000000, 0x4e13513200000000,
    0x2c2b791800000000, 0xb0cb818b00000000, 0xd2f3a9a100000000,
    0x74bbd1df00000000, 0x1683f9f500000000, 0x382a212300000000,
    0x5a12090900000000, 0xfc5a717700000000, 0x9e62595d00000000,
    0xe10eb10100000000, 0x8336992b00000000, 0x257ee15500000000,
    0x4746c97f00000000, 0x69ef11a900000000, 0x0bd7398300000000,
    0xad9f41fd00000000, 0xcfa769d700000000, 0xd458c10100000000,
    0xb660e92b00000000, 0x1028915500000000, 0x7210b97f00000000,
    0x5cb961a900000000, 0x3e81498300000000, 0x98c931fd00000000,
    0xfaf119d700000000, 0x859df18b00000000, 0xe7a5d9a100000000,
    0x41eda1df00000000, 0x23d589f500000000, 0x0d7c512300000000,
    0x6f44790900000000, 0xc90c017700000000, 0xab34295d00000000,
    0x37d4d1ce00000000, 0x55ecf9e400000000, 0xf3a4819a00000000,
    0x919ca9b000000000, 0xbf35716600000000, 0xdd0d594c00000000,
    0x7b45213200000000, 0x197d091800000000, 0x6611e14400000000,
    0x0429c96e00000000, 0xa261b11000000000, 0xc059993a00000000,
    0xeef041ec00000000, 0x8cc869c600000000, 0x2a8011b800000000,
    0x48b8399200000000},
   {0x0000000000000000, 0x4c2896a300000000, 0xd9565d9c00000000,
    0x957ecb3f00000000, 0xf3abcbe300000000, 0xbf835d4000000000,
    0x2afd967f00000000, 0x66d500dc00000000, 0xa751e61c00000000,
    0xeb7970bf00000000, 0x7e07bb8000000000, 0x322f2d2300000000,
    0x54fa2dff00000000, 0x18d2bb5c00000000, 0x8dac706300000000,
    0xc184e6c000000000, 0x4ea3cc3900000000, 0x028b5a9a00000000,
    0x97f591a500000000, 0xdbdd070600000000, 0xbd0807da00000000,
    0xf120917900000000, 0x645e5a4600000000, 0x2876cce500000000,
    0xe9f22a2500000000, 0xa5dabc8600000000, 0x30a477b900000000,
    0x7c8ce11a00000000, 0x1a59e1c600000000, 0x5671776500000000,
    0xc30fbc5a00000000, 0x8f272af900000000, 0x9c46997300000000,
    0xd06e0fd000000000, 0x4510c4ef00000000, 0x0938524c00000000,
    0x6fed529000000000, 0x23c5c43300000000, 0xb6bb0f0c00000000,
    0xfa9399af00000000, 0x3b177f6f00000000, 0x773fe9cc00000000,
    0xe24122f300000000, 0xae69b45000000000, 0xc8bcb48c00000000,
    0x8494222f00000000, 0x11eae91000000000, 0x5dc27fb300000000,
    0xd2e5554a00000000, 0x9ecdc3e900000000, 0x0bb308d600000000,
    0x479b9e7500000000, 0x214e9ea900000000, 0x6d66080a00000000,
    0xf818c33500000000, 0xb430559600000000, 0x75b4b35600000000,
    0x399c25f500000000, 0xace2eeca00000000, 0xe0ca786900000000,
    0x861f78b500000000, 0xca37ee1600000000, 0x5f49252900000000,
    0x1361b38a00000000, 0x388d32e700000000, 0x74a5a44400000000,
    0xe1db6f7b00000000, 0xadf3f9d800000000, 0xcb26f90400000000,
    0x870e6fa700000000, 0x1270a49800000000, 0x5e58323b00000000,
    0x9fdcd4fb00000000, 0xd3f4425800000000, 0x468a896700000000,
    0x0aa21fc400000000, 0x6c771f1800000000, 0x205f89bb00000000,
    0xb521428400000000, 0xf909d42700000000, 0x762efede00000000,
    0x3a06687d00000000, 0xaf78a34200000000, 0xe35035e100000000,
    0x8585353d00000000, 0xc9ada39e00000000, 0x5cd368a100000000,
    0x10fbfe0200000000, 0xd17f18c200000000, 0x9d578e6100000000,
    0x0829455e00000000, 0x4401d3fd00000000, 0x22d4d32100000000,
    0x6efc458200000000, 0xfb828ebd00000000, 0xb7aa181e00000000,
    0xa4cbab9400000000, 0xe8e33d3700000000, 0x7d9df60800000000,
    0x31b560ab00000000, 0x5760607700000000, 0x1b48f6d400000000,
    0x8e363deb00000000, 0xc21eab4800000000, 0x039a4d8800000000,
    0x4fb2db2b00000000, 0xdacc101400000000, 0x96e486b700000000,
    0xf031866b00000000, 0xbc1910c800000000, 0x2967dbf700000000,
    0x654f4d5400000000, 0xea6867ad00000000, 0xa640f10e00000000,
    0x333e3a3100000000, 0x7f16ac9200000000, 0x19c3ac4e00000000,
    0x55eb3aed00000000, 0xc095f1d200000000, 0x8cbd677100000000,
    0x4d3981b100000000, 0x0111171200000000, 0x946fdc2d00000000,
    0xd8474a8e00000000, 0xbe924a5200000000, 0xf2badcf100000000,
    0x67c417ce00000000, 0x2bec816d00000000, 0x311c141500000000,
    0x7d3482b600000000, 0xe84a498900000000, 0xa462df2a00000000,
    0xc2b7dff600000000, 0x8e9f495500000000, 0x1be1826a00000000,
    0x57c914c900000000, 0x964df20900000000, 0xda6564aa00000000,
    0x4f1baf9500000000, 0x0333393600000000, 0x65e639ea00000000,
    0x29ceaf4900000000, 0xbcb0647600000000, 0xf098f2d500000000,
    0x7fbfd82c00000000, 0x33974e8f00000000, 0xa6e985b000000000,
    0xeac1131300000000, 0x8c1413cf00000000, 0xc03c856c00000000,
    0x55424e5300000000, 0x196ad8f000000000, 0xd8ee3e3000000000,
    0x94c6a89300000000, 0x01b863ac00000000, 0x4d90f50f00000000,
    0x2b45f5d300000000, 0x676d637000000000, 0xf213a84f00000000,
    0xbe3b3eec00000000, 0xad5a8d6600000000, 0xe1721bc500000000,
    0x740cd0fa00000000, 0x3824465900000000, 0x5ef1468500000000,
    0x12d9d02600000000, 0x87a71b1900000000, 0xcb8f8dba00000000,
    0x0a0b6b7a00000000, 0x4623fdd900000000, 0xd35d36e600000000,
    0x9f75a04500000000, 0xf9a0a09900000000, 0xb588363a00000000,
    0x20f6fd0500000000, 0x6cde6ba600000000, 0xe3f9415f00000000,
    0xafd1d7fc00000000, 0x3aaf1cc300000000, 0x76878a6000000000,
    0x10528abc00000000, 0x5c7a1c1f00000000, 0xc904d72000000000,
    0x852c418300000000, 0x44a8a74300000000, 0x088031e000000000,
    0x9dfefadf00000000, 0xd1d66c7c00000000, 0xb7036ca000000000,
    0xfb2bfa0300000000, 0x6e55313c00000000, 0x227da79f00000000,
    0x099126f200000000, 0x45b9b05100000000, 0xd0c77b6e00000000,
    0x9cefedcd00000000, 0xfa3aed1100000000, 0xb6127bb200000000,
    0x236cb08d00000000, 0x6f44262e00000000, 0xaec0c0ee00000000,
    0xe2e8564d00000000, 0x77969d7200000000, 0x3bbe0bd100000000,
    0x5d6b0b0d00000000, 0x11439dae00000000, 0x843d569100000000,
    0xc815c03200000000, 0x4732eacb00000000, 0x0b1a7c6800000000,
    0x9e64b75700000000, 0xd24c21f400000000, 0xb499212800000000,
    0xf8b1b78b00000000, 0x6dcf7cb400000000, 0x21e7ea1700000000,
    0xe0630cd700000000, 0xac4b9a7400000000, 0x3935514b00000000,
    0x751dc7e800000000, 0x13c8c73400000000, 0x5fe0519700000000,
    0xca9e9aa800000000, 0x86b60c0b00000000, 0x95d7bf8100000000,
    0xd9ff292200000000, 0x4c81e21d00000000, 0x00a974be00000000,
    0x667c746200000000, 0x2a54e2c100000000, 0xbf2a29fe00000000,
    0xf302bf5d00000000, 0x3286599d00000000, 0x7eaecf3e00000000,
    0xebd0040100000000, 0xa7f892a200000000, 0xc12d927e00000000,
    0x8d0504dd00000000, 0x187bcfe200000000, 0x5453594100000000,
    0xdb7473b800000000, 0x975ce51b00000000, 0x02222e2400000000,
    0x4e0ab88700000000, 0x28dfb85b00000000, 0x64f72ef800000000,
    0xf189e5c700000000, 0xbda1736400000000, 0x7c2595a400000000,
    0x300d030700000000, 0xa573c83800000000, 0xe95b5e9b00000000,
    0x8f8e5e4700000000, 0xc3a6c8e400000000, 0x56d803db00000000,
    0x1af0957800000000},
   {0x0000000000000000, 0x939bc97f00000000, 0x263793ff00000000,
    0xb5ac5a8000000000, 0x0d68572400000000, 0x9ef39e5b00000000,
    0x2b5fc4db00000000, 0xb8c40da400000000, 0x1ad0ae4800000000,
    0x894b673700000000, 0x3ce73db700000000, 0xaf7cf4c800000000,
    0x17b8f96c00000000, 0x8423301300000000, 0x318f6a9300000000,
    0xa214a3ec00000000, 0x34a05d9100000000, 0xa73b94ee00000000,
    0x1297ce6e00000000, 0x810c071100000000, 0x39c80ab500000000,
    0xaa53c3ca00000000, 0x1fff994a00000000, 0x8c64503500000000,
    0x2e70f3d900000000, 0xbdeb3aa600000000, 0x0847602600000000,
    0x9bdca95900000000, 0x2318a4fd00000000, 0xb0836d8200000000,
    0x052f370200000000, 0x96b4fe7d00000000, 0x2946caf900000000,
    0xbadd038600000000, 0x0f71590600000000, 0x9cea907900000000,
    0x242e9ddd00000000, 0xb7b554a200000000, 0x02190e2200000000,
    0x9182c75d00000000, 0x339664b100000000, 0xa00dadce00000000,
    0x15a1f74e00000000, 0x863a3e3100000000, 0x3efe339500000000,
    0xad65faea00000000, 0x18c9a06a00000000, 0x8b52691500000000,
    0x1de6976800000000, 0x8e7d5e1700000000, 0x3bd1049700000000,
    0xa84acde800000000, 0x108ec04c00000000, 0x8315093300000000,
    0x36b953b300000000, 0xa5229acc00000000, 0x0736392000000000,
    0x94adf05f00000000, 0x2101aadf00000000, 0xb29a63a000000000,
    0x0a5e6e0400000000, 0x99c5a77b00000000, 0x2c69fdfb00000000,
    0xbff2348400000000, 0x138ae52800000000, 0x80112c5700000000,
    0x35bd76d700000000, 0xa626bfa800000000, 0x1ee2b20c00000000,
    0x8d797b7300000000, 0x38d521f300000000, 0xab4ee88c00000000,
    0x095a4b6000000000, 0x9ac1821f00000000, 0x2f6dd89f00000000,
    0xbcf611e000000000, 0x04321c4400000000, 0x97a9d53b00000000,
    0x22058fbb00000000, 0xb19e46c400000000, 0x272ab8b900000000,
    0xb4b171c600000000, 0x011d2b4600000000, 0x9286e23900000000,
    0x2a42ef9d00000000, 0xb9d926e200000000, 0x0c757c6200000000,
    0x9feeb51d00000000, 0x3dfa16f100000000, 0xae61df8e00000000,
    0x1bcd850e00000000, 0x88564c7100000000, 0x309241d500000000,
    0xa30988aa00000000, 0x16a5d22a00000000, 0x853e1b5500000000,
    0x3acc2fd100000000, 0xa957e6ae00000000, 0x1cfbbc2e00000000,
    0x8f60755100000000, 0x37a478f500000000, 0xa43fb18a00000000,
    0x1193eb0a00000000, 0x8208227500000000, 0x201c819900000000,
    0xb38748e600000000, 0x062b126600000000, 0x95b0db1900000000,
    0x2d74d6bd00000000, 0xbeef1fc200000000, 0x0b43454200000000,
    0x98d88c3d00000000, 0x0e6c724000000000, 0x9df7bb3f00000000,
    0x285be1bf00000000, 0xbbc028c000000000, 0x0304256400000000,
    0x909fec1b00000000, 0x2533b69b00000000, 0xb6a87fe400000000,
    0x14bcdc0800000000, 0x8727157700000000, 0x328b4ff700000000,
    0xa110868800000000, 0x19d48b2c00000000, 0x8a4f425300000000,
    0x3fe318d300000000, 0xac78d1ac00000000, 0x2614cb5100000000,
    0xb58f022e00000000, 0x002358ae00000000, 0x93b891d100000000,
    0x2b7c9c7500000000, 0xb8e7550a00000000, 0x0d4b0f8a00000000,
    0x9ed0c6f500000000, 0x3cc4651900000000, 0xaf5fac6600000000,
    0x1af3f6e600000000, 0x89683f9900000000, 0x31ac323d00000000,
    0xa237fb4200000000, 0x179ba1c200000000, 0x840068bd00000000,
    0x12b496c000000000, 0x812f5fbf00000000, 0x3483053f00000000,
    0xa718cc4000000000, 0x1fdcc1e400000000, 0x8c47089b00000000,
    0x39eb521b00000000, 0xaa709b6400000000, 0x0864388800000000,
    0x9bfff1f700000000, 0x2e53ab7700000000, 0xbdc8620800000000,
    0x050c6fac00000000, 0x9697a6d300000000, 0x233bfc5300000000,
    0xb0a0352c00000000, 0x0f5201a800000000, 0x9cc9c8d700000000,
    0x2965925700000000, 0xbafe5b2800000000, 0x023a568c00000000,
    0x91a19ff300000000, 0x240dc57300000000, 0xb7960c0c00000000,
    0x1582afe000000000, 0x8619669f00000000, 0x33b53c1f00000000,
    0xa02ef56000000000, 0x18eaf8c400000000, 0x8b7131bb00000000,
    0x3edd6b3b00000000, 0xad46a24400000000, 0x3bf25c3900000000,
    0xa869954600000000, 0x1dc5cfc600000000, 0x8e5e06b900000000,
    0x369a0b1d00000000, 0xa501c26200000000, 0x10ad98e200000000,
    0x8336519d00000000, 0x2122f27100000000, 0xb2b93b0e00000000,
    0x0715618e00000000, 0x948ea8f100000000, 0x2c4aa55500000000,
    0xbfd16c2a00000000, 0x0a7d36aa00000000, 0x99e6ffd500000000,
    0x359e2e7900000000, 0xa605e70600000000, 0x13a9bd8600000000,
    0x803274f900000000, 0x38f6795d00000000, 0xab6db02200000000,
    0x1ec1eaa200000000, 0x8d5a23dd00000000, 0x2f4e803100000000,
    0xbcd5494e00000000, 0x097913ce00000000, 0x9ae2dab100000000,
    0x2226d71500000000, 0xb1bd1e6a00000000, 0x041144ea00000000,
    0x978a8d9500000000, 0x013e73e800000000, 0x92a5ba9700000000,
    0x2709e01700000000, 0xb492296800000000, 0x0c5624cc00000000,
    0x9fcdedb300000000, 0x2a61b73300000000, 0xb9fa7e4c00000000,
    0x1beedda000000000, 0x887514df00000000, 0x3dd94e5f00000000,
    0xae42872000000000, 0x16868a8400000000, 0x851d43fb00000000,
    0x30b1197b00000000, 0xa32ad00400000000, 0x1cd8e48000000000,
    0x8f432dff00000000, 0x3aef777f00000000, 0xa974be0000000000,
    0x11b0b3a400000000, 0x822b7adb00000000, 0x3787205b00000000,
    0xa41ce92400000000, 0x06084ac800000000, 0x959383b700000000,
    0x203fd93700000000, 0xb3a4104800000000, 0x0b601dec00000000,
    0x98fbd49300000000, 0x2d578e1300000000, 0xbecc476c00000000,
    0x2878b91100000000, 0xbbe3706e00000000, 0x0e4f2aee00000000,
    0x9dd4e39100000000, 0x2510ee3500000000, 0xb68b274a00000000,
    0x03277dca00000000, 0x90bcb4b500000000, 0x32a8175900000000,
    0xa133de2600000000, 0x149f84a600000000, 0x87044dd900000000,
    0x3fc0407d00000000, 0xac5b890200000000, 0x19f7d38200000000,
    0x8a6c1afd00000000},
   {0x0000000000000000, 0x650b796900000000, 0xca16f2d200000000,
    0xaf1d8bbb00000000, 0xd52b957e00000000, 0xb020ec1700000000,
    0x1f3d67ac00000000, 0x7a361ec500000000, 0xaa572afd00000000,
    0xcf5c539400000000, 0x6041d82f00000000, 0x054aa14600000000,
    0x7f7cbf8300000000, 0x1a77c6ea00000000, 0xb56a4d5100000000,
    0xd061343800000000, 0x15a9252100000000, 0x70a25c4800000000,
    0xdfbfd7f300000000, 0xbab4ae9a00000000, 0xc082b05f00000000,
    0xa589c93600000000, 0x0a94428d00000000, 0x6f9f3be400000000,
    0xbffe0fdc00000000, 0xdaf576b500000000, 0x75e8fd0e00000000,
    0x10e3846700000000, 0x6ad59aa200000000, 0x0fdee3cb00000000,
    0xa0c3687000000000, 0xc5c8111900000000, 0x2a524b4200000000,
    0x4f59322b00000000, 0xe044b99000000000, 0x854fc0f900000000,
    0xff79de3c00000000, 0x9a72a75500000000, 0x356f2cee00000000,
    0x5064558700000000, 0x800561bf00000000, 0xe50e18d600000000,
    0x4a13936d00000000, 0x2f18ea0400000000, 0x552ef4c100000000,
    0x30258da800000000, 0x9f38061300000000, 0xfa337f7a00000000,
    0x3ffb6e6300000000, 0x5af0170a00000000, 0xf5ed9cb100000000,
    0x90e6e5d800000000, 0xead0fb1d00000000, 0x8fdb827400000000,
    0x20c609cf00000000, 0x45cd70a600000000, 0x95ac449e00000000,
    0xf0a73df700000000, 0x5fbab64c00000000, 0x3ab1cf2500000000,
    0x4087d1e000000000, 0x258ca88900000000, 0x8a91233200000000,
    0xef9a5a5b00000000, 0x54a4968400000000, 0x31afefed00000000,
    0x9eb2645600000000, 0xfbb91d3f00000000, 0x818f03fa00000000,
    0xe4847a9300000000, 0x4b99f12800000000, 0x2e92884100000000,
    0xfef3bc7900000000, 0x9bf8c51000000000, 0x34e54eab00000000,
    0x51ee37c200000000, 0x2bd8290700000000, 0x4ed3506e00000000,
    0xe1cedbd500000000, 0x84c5a2bc00000000, 0x410db3a500000000,
    0x2406cacc00000000, 0x8b1b417700000000, 0xee10381e00000000,
    0x942626db00000000, 0xf12d5fb200000000, 0x5e30d40900000000,
    0x3b3bad6000000000, 0xeb5a995800000000, 0x8e51e03100000000,
    0x214c6b8a00000000, 0x444712e300000000, 0x3e710c2600000000,
    0x5b7a754f00000000, 0xf467fef400000000, 0x916c879d00000000,
    0x7ef6ddc600000000, 0x1bfda4af00000000, 0xb4e02f1400000000,
    0xd1eb567d00000000, 0xabdd48b800000000, 0xced631d100000000,
    0x61cbba6a00000000, 0x04c0c30300000000, 0xd4a1f73b00000000,
    0xb1aa8e5200000000, 0x1eb705e900000000, 0x7bbc7c8000000000,
    0x018a624500000000, 0x64811b2c00000000, 0xcb9c909700000000,
    0xae97e9fe00000000, 0x6b5ff8e700000000, 0x0e54818e00000000,
    0xa1490a3500000000, 0xc442735c00000000, 0xbe746d9900000000,
    0xdb7f14f000000000, 0x74629f4b00000000, 0x1169e62200000000,
    0xc108d21a00000000, 0xa403ab7300000000, 0x0b1e20c800000000,
    0x6e1559a100000000, 0x1423476400000000, 0x71283e0d00000000,
    0xde35b5b600000000, 0xbb3eccdf00000000, 0xe94e5cd200000000,
    0x8c4525bb00000000, 0x2358ae0000000000, 0x4653d76900000000,
    0x3c65c9ac00000000, 0x596eb0c500000000, 0xf6733b7e00000000,
    0x9378421700000000, 0x4319762f00000000, 0x26120f4600000000,
    0x890f84fd00000000, 0xec04fd9400000000, 0x9632e35100000000,
    0xf3399a3800000000, 0x5c24118300000000, 0x392f68ea00000000,
    0xfce779f300000000, 0x99ec009a00000000, 0x36f18b2100000000,
    0x53faf24800000000, 0x29ccec8d00000000, 0x4cc795e400000000,
    0xe3da1e5f00000000, 0x86d1673600000000, 0x56b0530e00000000,
    0x33bb2a6700000000, 0x9ca6a1dc00000000, 0xf9add8b500000000,
    0x839bc67000000000, 0xe690bf1900000000, 0x498d34a200000000,
    0x2c864dcb00000000, 0xc31c179000000000, 0xa6176ef900000000,
    0x090ae54200000000, 0x6c019c2b00000000, 0x163782ee00000000,
    0x733cfb8700000000, 0xdc21703c00000000, 0xb92a095500000000,
    0x694b3d6d00000000, 0x0c40440400000000, 0xa35dcfbf00000000,
    0xc656b6d600000000, 0xbc60a81300000000, 0xd96bd17a00000000,
    0x76765ac100000000, 0x137d23a800000000, 0xd6b532b100000000,
    0xb3be4bd800000000, 0x1ca3c06300000000, 0x79a8b90a00000000,
    0x039ea7cf00000000, 0x6695dea600000000, 0xc988551d00000000,
    0xac832c7400000000, 0x7ce2184c00000000, 0x19e9612500000000,
    0xb6f4ea9e00000000, 0xd3ff93f700000000, 0xa9c98d3200000000,
    0xccc2f45b00000000, 0x63df7fe000000000, 0x06d4068900000000,
    0xbdeaca5600000000, 0xd8e1b33f00000000, 0x77fc388400000000,
    0x12f741ed00000000, 0x68c15f2800000000, 0x0dca264100000000,
    0xa2d7adfa00000000, 0xc7dcd49300000000, 0x17bde0ab00000000,
    0x72b699c200000000, 0xddab127900000000, 0xb8a06b1000000000,
    0xc29675d500000000, 0xa79d0cbc00000000, 0x0880870700000000,
    0x6d8bfe6e00000000, 0xa843ef7700000000, 0xcd48961e00000000,
    0x62551da500000000, 0x075e64cc00000000, 0x7d687a0900000000,
    0x1863036000000000, 0xb77e88db00000000, 0xd275f1b200000000,
    0x0214c58a00000000, 0x671fbce300000000, 0xc802375800000000,
    0xad094e3100000000, 0xd73f50f400000000, 0xb234299d00000000,
    0x1d29a22600000000, 0x7822db4f00000000, 0x97b8811400000000,
    0xf2b3f87d00000000, 0x5dae73c600000000, 0x38a50aaf00000000,
    0x4293146a00000000, 0x27986d0300000000, 0x8885e6b800000000,
    0xed8e9fd100000000, 0x3defabe900000000, 0x58e4d28000000000,
    0xf7f9593b00000000, 0x92f2205200000000, 0xe8c43e9700000000,
    0x8dcf47fe00000000, 0x22d2cc4500000000, 0x47d9b52c00000000,
    0x8211a43500000000, 0xe71add5c00000000, 0x480756e700000000,
    0x2d0c2f8e00000000, 0x573a314b00000000, 0x3231482200000000,
    0x9d2cc39900000000, 0xf827baf000000000, 0x28468ec800000000,
    0x4d4df7a100000000, 0xe2507c1a00000000, 0x875b057300000000,
    0xfd6d1bb600000000, 0x986662df00000000, 0x377be96400000000,
    0x5270900d00000000},
   {0x0000000000000000, 0xdcecb13d00000000, 0xb8d9637b00000000,
    0x6435d24600000000, 0x70b3c7f600000000, 0xac5f76cb00000000,
    0xc86aa48d00000000, 0x148615b000000000, 0xa160fe3600000000,
    0x7d8c4f0b00000000, 0x19b99d4d00000000, 0xc5552c7000000000,
    0xd1d339c000000000, 0x0d3f88fd00000000, 0x690a5abb00000000,
    0xb5e6eb8600000000, 0x42c1fc6d00000000, 0x9e2d4d5000000000,
    0xfa189f1600000000, 0x26f42e2b00000000, 0x32723b9b00000000,
    0xee9e8aa600000000, 0x8aab58e000000000, 0x5647e9dd00000000,
    0xe3a1025b00000000, 0x3f4db36600000000, 0x5b78612000000000,
    0x8794d01d00000000, 0x9312c5ad00000000, 0x4ffe749000000000,
    0x2bcba6d600000000, 0xf72717eb00000000, 0x8482f9db00000000,
    0x586e48e600000000, 0x3c5b9aa000000000, 0xe0b72b9d00000000,
    0xf4313e2d00000000, 0x28dd8f1000000000, 0x4ce85d5600000000,
    0x9004ec6b00000000, 0x25e207ed00000000, 0xf90eb6d000000000,
    0x9d3b649600000000, 0x41d7d5ab00000000, 0x5551c01b00000000,
    0x89bd712600000000, 0xed88a36000000000, 0x3164125d00000000,
    0xc64305b600000000, 0x1aafb48b00000000, 0x7e9a66cd00000000,
    0xa276d7f000000000, 0xb6f0c24000000000, 0x6a1c737d00000000,
    0x0e29a13b00000000, 0xd2c5100600000000, 0x6723fb8000000000,
    0xbbcf4abd00000000, 0xdffa98fb00000000, 0x031629c600000000,
    0x17903c7600000000, 0xcb7c8d4b00000000, 0xaf495f0d00000000,
    0x73a5ee3000000000, 0x4903826c00000000, 0x95ef335100000000,
    0xf1dae11700000000, 0x2d36502a00000000, 0x39b0459a00000000,
    0xe55cf4a700000000, 0x816926e100000000, 0x5d8597dc00000000,
    0xe8637c5a00000000, 0x348fcd6700000000, 0x50ba1f2100000000,
    0x8c56ae1c00000000, 0x98d0bbac00000000, 0x443c0a9100000000,
    0x2009d8d700000000, 0xfce569ea00000000, 0x0bc27e0100000000,
    0xd72ecf3c00000000, 0xb31b1d7a00000000, 0x6ff7ac4700000000,
    0x7b71b9f700000000, 0xa79d08ca00000000, 0xc3a8da8c00000000,
    0x1f446bb100000000, 0xaaa2803700000000, 0x764e310a00000000,
    0x127be34c00000000, 0xce97527100000000, 0xda1147c100000000,
    0x06fdf6fc00000000, 0x62c824ba00000000, 0xbe24958700000000,
    0xcd817bb700000000, 0x116dca8a00000000, 0x755818cc00000000,
    0xa9b4a9f100000000, 0xbd32bc4100000000, 0x61de0d7c00000000,
    0x05ebdf3a00000000, 0xd9076e0700000000, 0x6ce1858100000000,
    0xb00d34bc00000000, 0xd438e6fa00000000, 0x08d457c700000000,
    0x1c52427700000000, 0xc0bef34a00000000, 0xa48b210c00000000,
    0x7867903100000000, 0x8f4087da00000000, 0x53ac36e700000000,
    0x3799e4a100000000, 0xeb75559c00000000, 0xfff3402c00000000,
    0x231ff11100000000, 0x472a235700000000, 0x9bc6926a00000000,
    0x2e2079ec00000000, 0xf2ccc8d100000000, 0x96f91a9700000000,
    0x4a15abaa00000000, 0x5e93be1a00000000, 0x827f0f2700000000,
    0xe64add6100000000, 0x3aa66c5c00000000, 0x920604d900000000,
    0x4eeab5e400000000, 0x2adf67a200000000, 0xf633d69f00000000,
    0xe2b5c32f00000000, 0x3e59721200000000, 0x5a6ca05400000000,
    0x8680116900000000, 0x3366faef00000000, 0xef8a4bd200000000,
    0x8bbf999400000000, 0x575328a900000000, 0x43d53d1900000000,
    0x9f398c2400000000, 0xfb0c5e6200000000, 0x27e0ef5f00000000,
    0xd0c7f8b400000000, 0x0c2b498900000000, 0x681e9bcf00000000,
    0xb4f22af200000000, 0xa0743f4200000000, 0x7c988e7f00000000,
    0x18ad5c3900000000, 0xc441ed0400000000, 0x71a7068200000000,
    0xad4bb7bf00000000, 0xc97e65f900000000, 0x1592d4c400000000,
    0x0114c17400000000, 0xddf8704900000000, 0xb9cda20f00000000,
    0x6521133200000000, 0x1684fd0200000000, 0xca684c3f00000000,
    0xae5d9e7900000000, 0x72b12f4400000000, 0x66373af400000000,
    0xbadb8bc900000000, 0xdeee598f00000000, 0x0202e8b200000000,
    0xb7e4033400000000, 0x6b08b20900000000, 0x0f3d604f00000000,
    0xd3d1d17200000000, 0xc757c4c200000000, 0x1bbb75ff00000000,
    0x7f8ea7b900000000, 0xa362168400000000, 0x5445016f00000000,
    0x88a9b05200000000, 0xec9c621400000000, 0x3070d32900000000,
    0x24f6c69900000000, 0xf81a77a400000000, 0x9c2fa5e200000000,
    0x40c314df00000000, 0xf525ff5900000000, 0x29c94e6400000000,
    0x4dfc9c2200000000, 0x91102d1f00000000, 0x859638af00000000,
    0x597a899200000000, 0x3d4f5bd400000000, 0xe1a3eae900000000,
    0xdb0586b500000000, 0x07e9378800000000, 0x63dce5ce00000000,
    0xbf3054f300000000, 0xabb6414300000000, 0x775af07e00000000,
    0x136f223800000000, 0xcf83930500000000, 0x7a65788300000000,
    0xa689c9be00000000, 0xc2bc1bf800000000, 0x1e50aac500000000,
    0x0ad6bf7500000000, 0xd63a0e4800000000, 0xb20fdc0e00000000,
    0x6ee36d3300000000, 0x99c47ad800000000, 0x4528cbe500000000,
    0x211d19a300000000, 0xfdf1a89e00000000, 0xe977bd2e00000000,
    0x359b0c1300000000, 0x51aede5500000000, 0x8d426f6800000000,
    0x38a484ee00000000, 0xe44835d300000000, 0x807de79500000000,
    0x5c9156a800000000, 0x4817431800000000, 0x94fbf22500000000,
    0xf0ce206300000000, 0x2c22915e00000000, 0x5f877f6e00000000,
    0x836bce5300000000, 0xe75e1c1500000000, 0x3bb2ad2800000000,
    0x2f34b89800000000, 0xf3d809a500000000, 0x97eddbe300000000,
    0x4b016ade00000000, 0xfee7815800000000, 0x220b306500000000,
    0x463ee22300000000, 0x9ad2531e00000000, 0x8e5446ae00000000,
    0x52b8f79300000000, 0x368d25d500000000, 0xea6194e800000000,
    0x1d46830300000000, 0xc1aa323e00000000, 0xa59fe07800000000,
    0x7973514500000000, 0x6df544f500000000, 0xb119f5c800000000,
    0xd52c278e00000000, 0x09c096b300000000, 0xbc267d3500000000,
    0x60cacc0800000000, 0x04ff1e4e00000000, 0xd813af7300000000,
    0xcc95bac300000000, 0x10790bfe00000000, 0x744cd9b800000000,
    0xa8a0688500000000}};

#else /* W == 4 */

local const z_crc_t FAR crc_braid_table[][256] = {
   {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f,
    0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999,
    0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee,
    0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615,
    0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383,
    0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb,
    0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275,
    0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d,
    0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b,
    0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460,
    0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317,
    0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1,
    0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5,
    0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd,
    0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04,
    0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c,
    0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7,
    0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11,
    0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66,
    0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7,
    0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871,
    0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309,
    0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd,
    0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85,
    0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913,
    0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d,
    0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a,
    0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc,
    0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57,
    0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f,
    0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6,
    0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e,
    0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f,
    0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289,
    0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe,
    0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05,
    0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893,
    0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb,
    0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0,
    0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8,
    0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e,
    0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5,
    0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2,
    0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574,
    0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5,
    0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add,
    0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114,
    0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c,
    0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7,
    0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701,
    0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076,
    0x09cd8551},
   {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193,
    0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2,
    0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c,
    0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71,
    0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a,
    0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d,
    0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71,
    0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436,
    0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d,
    0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000,
    0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae,
    0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf,
    0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930,
    0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277,
    0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff,
    0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8,
    0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef,
    0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e,
    0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20,
    0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95,
    0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e,
    0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9,
    0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d,
    0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a,
    0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151,
    0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4,
    0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a,
    0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b,
    0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c,
    0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b,
    0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3,
    0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4,
    0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b,
    0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a,
    0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4,
    0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189,
    0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92,
    0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5,
    0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9,
    0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe,
    0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5,
    0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8,
    0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66,
    0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707,
    0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8,
    0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f,
    0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707,
    0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40,
    0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017,
    0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876,
    0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8,
    0x7bc97a0c},
   {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300,
    0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0,
    0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80,
    0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701,
    0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41,
    0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81,
    0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43,
    0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83,
    0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3,
    0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42,
    0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202,
    0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2,
    0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7,
    0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407,
    0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47,
    0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87,
    0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86,
    0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46,
    0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506,
    0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44,
    0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704,
    0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4,
    0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5,
    0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505,
    0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45,
    0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f,
    0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f,
    0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f,
    0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e,
    0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e,
    0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e,
    0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce,
    0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c,
    0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc,
    0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c,
    0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d,
    0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d,
    0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d,
    0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88,
    0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48,
    0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708,
    0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89,
    0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9,
    0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309,
    0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb,
    0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b,
    0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b,
    0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b,
    0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a,
    0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a,
    0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a,
    0x7851a2ca},
   {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb,
    0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8,
    0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0,
    0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f,
    0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a,
    0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf,
    0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5,
    0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380,
    0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815,
    0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa,
    0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2,
    0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1,
    0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1,
    0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4,
    0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa,
    0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df,
    0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6,
    0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5,
    0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad,
    0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca,
    0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f,
    0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a,
    0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8,
    0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d,
    0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708,
    0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d,
    0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865,
    0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636,
    0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f,
    0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a,
    0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744,
    0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061,
    0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0,
    0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293,
    0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb,
    0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874,
    0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1,
    0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4,
    0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f,
    0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a,
    0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f,
    0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120,
    0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778,
    0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b,
    0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a,
    0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af,
    0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81,
    0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4,
    0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd,
    0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e,
    0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6,
    0x566b6848}};

local const z_word_t FAR crc_braid_big_table[][256] = {
   {0x00000000, 0x9e83da9f, 0x7d01c4e4, 0xe3821e7b, 0xbb04f912,
    0x2587238d, 0xc6053df6, 0x5886e769, 0x7609f225, 0xe88a28ba,
    0x0b0836c1, 0x958bec5e, 0xcd0d0b37, 0x538ed1a8, 0xb00ccfd3,
    0x2e8f154c, 0xec12e44b, 0x72913ed4, 0x911320af, 0x0f90fa30,
    0x57161d59, 0xc995c7c6, 0x2a17d9bd, 0xb4940322, 0x9a1b166e,
    0x0498ccf1, 0xe71ad28a, 0x79990815, 0x211fef7c, 0xbf9c35e3,
    0x5c1e2b98, 0xc29df107, 0xd825c897, 0x46a61208, 0xa5240c73,
    0x3ba7d6ec, 0x63213185, 0xfda2eb1a, 0x1e20f561, 0x80a32ffe,
    0xae2c3ab2, 0x30afe02d, 0xd32dfe56, 0x4dae24c9, 0x1528c3a0,
    0x8bab193f, 0x68290744, 0xf6aadddb, 0x34372cdc, 0xaab4f643,
    0x4936e838, 0xd7b532a7, 0x8f33d5ce, 0x11b00f51, 0xf232112a,
    0x6cb1cbb5, 0x423edef9, 0xdcbd0466, 0x3f3f1a1d, 0xa1bcc082,
    0xf93a27eb, 0x67b9fd74, 0x843be30f, 0x1ab83990, 0xf14de1f4,
    0x6fce3b6b, 0x8c4c2510, 0x12cfff8f, 0x4a4918e6, 0xd4cac279,
    0x3748dc02, 0xa9cb069d, 0x874413d1, 0x19c7c94e, 0xfa45d735,
    0x64c60daa, 0x3c40eac3, 0xa2c3305c, 0x41412e27, 0xdfc2f4b8,
    0x1d5f05bf, 0x83dcdf20, 0x605ec15b, 0xfedd1bc4, 0xa65bfcad,
    0x38d82632, 0xdb5a3849, 0x45d9e2d6, 0x6b56f79a, 0xf5d52d05,
    0x1657337e, 0x88d4e9e1, 0xd0520e88, 0x4ed1d417, 0xad53ca6c,
    0x33d010f3, 0x29682963, 0xb7ebf3fc, 0x5469ed87, 0xcaea3718,
    0x926cd071, 0x0cef0aee, 0xef6d1495, 0x71eece0a, 0x5f61db46,
    0xc1e201d9, 0x22601fa2, 0xbce3c53d, 0xe4652254, 0x7ae6f8cb,
    0x9964e6b0, 0x07e73c2f, 0xc57acd28, 0x5bf917b7, 0xb87b09cc,
    0x26f8d353, 0x7e7e343a, 0xe0fdeea5, 0x037ff0de, 0x9dfc2a41,
    0xb3733f0d, 0x2df0e592, 0xce72fbe9, 0x50f12176, 0x0877c61f,
    0x96f41c80, 0x757602fb, 0xebf5d864, 0xa39db332, 0x3d1e69ad,
    0xde9c77d6, 0x401fad49, 0x18994a20, 0x861a90bf, 0x65988ec4,
    0xfb1b545b, 0xd5944117, 0x4b179b88, 0xa89585f3, 0x36165f6c,
    0x6e90b805, 0xf013629a, 0x13917ce1, 0x8d12a67e, 0x4f8f5779,
    0xd10c8de6, 0x328e939d, 0xac0d4902, 0xf48bae6b, 0x6a0874f4,
    0x898a6a8f, 0x1709b010, 0x3986a55c, 0xa7057fc3, 0x448761b8,
    0xda04bb27, 0x82825c4e, 0x1c0186d1, 0xff8398aa, 0x61004235,
    0x7bb87ba5, 0xe53ba13a, 0x06b9bf41, 0x983a65de, 0xc0bc82b7,
    0x5e3f5828, 0xbdbd4653, 0x233e9ccc, 0x0db18980, 0x9332531f,
    0x70b04d64, 0xee3397fb, 0xb6b57092, 0x2836aa0d, 0xcbb4b476,
    0x55376ee9, 0x97aa9fee, 0x09294571, 0xeaab5b0a, 0x74288195,
    0x2cae66fc, 0xb22dbc63, 0x51afa218, 0xcf2c7887, 0xe1a36dcb,
    0x7f20b754, 0x9ca2a92f, 0x022173b0, 0x5aa794d9, 0xc4244e46,
    0x27a6503d, 0xb9258aa2, 0x52d052c6, 0xcc538859, 0x2fd19622,
    0xb1524cbd, 0xe9d4abd4, 0x7757714b, 0x94d56f30, 0x0a56b5af,
    0x24d9a0e3, 0xba5a7a7c, 0x59d86407, 0xc75bbe98, 0x9fdd59f1,
    0x015e836e, 0xe2dc9d15, 0x7c5f478a, 0xbec2b68d, 0x20416c12,
    0xc3c37269, 0x5d40a8f6, 0x05c64f9f, 0x9b459500, 0x78c78b7b,
    0xe64451e4, 0xc8cb44a8, 0x56489e37, 0xb5ca804c, 0x2b495ad3,
    0x73cfbdba, 0xed4c6725, 0x0ece795e, 0x904da3c1, 0x8af59a51,
    0x147640ce, 0xf7f45eb5, 0x6977842a, 0x31f16343, 0xaf72b9dc,
    0x4cf0a7a7, 0xd2737d38, 0xfcfc6874, 0x627fb2eb, 0x81fdac90,
    0x1f7e760f, 0x47f89166, 0xd97b4bf9, 0x3af95582, 0xa47a8f1d,
    0x66e77e1a, 0xf864a485, 0x1be6bafe, 0x85656061, 0xdde38708,
    0x43605d97, 0xa0e243ec, 0x3e619973, 0x10ee8c3f, 0x8e6d56a0,
    0x6def48db, 0xf36c9244, 0xabea752d, 0x3569afb2, 0xd6ebb1c9,
    0x48686b56},
   {0x00000000, 0xc0642817, 0x80c9502e, 0x40ad7839, 0x0093a15c,
    0xc0f7894b, 0x805af172, 0x403ed965, 0x002643b9, 0xc0426bae,
    0x80ef1397, 0x408b3b80, 0x00b5e2e5, 0xc0d1caf2, 0x807cb2cb,
    0x40189adc, 0x414af7a9, 0x812edfbe, 0xc183a787, 0x01e78f90,
    0x41d956f5, 0x81bd7ee2, 0xc11006db, 0x01742ecc, 0x416cb410,
    0x81089c07, 0xc1a5e43e, 0x01c1cc29, 0x41ff154c, 0x819b3d5b,
    0xc1364562, 0x01526d75, 0xc3929f88, 0x03f6b79f, 0x435bcfa6,
    0x833fe7b1, 0xc3013ed4, 0x036516c3, 0x43c86efa, 0x83ac46ed,
    0xc3b4dc31, 0x03d0f426, 0x437d8c1f, 0x8319a408, 0xc3277d6d,
    0x0343557a, 0x43ee2d43, 0x838a0554, 0x82d86821, 0x42bc4036,
    0x0211380f, 0xc2751018, 0x824bc97d, 0x422fe16a, 0x02829953,
    0xc2e6b144, 0x82fe2b98, 0x429a038f, 0x02377bb6, 0xc25353a1,
    0x826d8ac4, 0x4209a2d3, 0x02a4daea, 0xc2c0f2fd, 0xc7234eca,
    0x074766dd, 0x47ea1ee4, 0x878e36f3, 0xc7b0ef96, 0x07d4c781,
    0x4779bfb8, 0x871d97af, 0xc7050d73, 0x07612564, 0x47cc5d5d,
    0x87a8754a, 0xc796ac2f, 0x07f28438, 0x475ffc01, 0x873bd416,
    0x8669b963, 0x460d9174, 0x06a0e94d, 0xc6c4c15a, 0x86fa183f,
    0x469e3028, 0x06334811, 0xc6576006, 0x864ffada, 0x462bd2cd,
    0x0686aaf4, 0xc6e282e3, 0x86dc5b86, 0x46b87391, 0x06150ba8,
    0xc67123bf, 0x04b1d142, 0xc4d5f955, 0x8478816c, 0x441ca97b,
    0x0422701e, 0xc4465809, 0x84eb2030, 0x448f0827, 0x049792fb,
    0xc4f3baec, 0x845ec2d5, 0x443aeac2, 0x040433a7, 0xc4601bb0,
    0x84cd6389, 0x44a94b9e, 0x45fb26eb, 0x859f0efc, 0xc53276c5,
    0x05565ed2, 0x456887b7, 0x850cafa0, 0xc5a1d799, 0x05c5ff8e,
    0x45dd6552, 0x85b94d45, 0xc514357c, 0x05701d6b, 0x454ec40e,
    0x852aec19, 0xc5879420, 0x05e3bc37, 0xcf41ed4f, 0x0f25c558,
    0x4f88bd61, 0x8fec9576, 0xcfd24c13, 0x0fb66404, 0x4f1b1c3d,
    0x8f7f342a, 0xcf67aef6, 0x0f0386e1, 0x4faefed8, 0x8fcad6cf,
    0xcff40faa, 0x0f9027bd, 0x4f3d5f84, 0x8f597793, 0x8e0b1ae6,
    0x4e6f32f1, 0x0ec24ac8, 0xcea662df, 0x8e98bbba, 0x4efc93ad,
    0x0e51eb94, 0xce35c383, 0x8e2d595f, 0x4e497148, 0x0ee40971,
    0xce802166, 0x8ebef803, 0x4edad014, 0x0e77a82d, 0xce13803a,
    0x0cd372c7, 0xccb75ad0, 0x8c1a22e9, 0x4c7e0afe, 0x0c40d39b,
    0xcc24fb8c, 0x8c8983b5, 0x4cedaba2, 0x0cf5317e, 0xcc911969,
    0x8c3c6150, 0x4c584947, 0x0c669022, 0xcc02b835, 0x8cafc00c,
    0x4ccbe81b, 0x4d99856e, 0x8dfdad79, 0xcd50d540, 0x0d34fd57,
    0x4d0a2432, 0x8d6e0c25, 0xcdc3741c, 0x0da75c0b, 0x4dbfc6d7,
    0x8ddbeec0, 0xcd7696f9, 0x0d12beee, 0x4d2c678b, 0x8d484f9c,
    0xcde537a5, 0x0d811fb2, 0x0862a385, 0xc8068b92, 0x88abf3ab,
    0x48cfdbbc, 0x08f102d9, 0xc8952ace, 0x883852f7, 0x485c7ae0,
    0x0844e03c, 0xc820c82b, 0x888db012, 0x48e99805, 0x08d74160,
    0xc8b36977, 0x881e114e, 0x487a3959, 0x4928542c, 0x894c7c3b,
    0xc9e10402, 0x09852c15, 0x49bbf570, 0x89dfdd67, 0xc972a55e,
    0x09168d49, 0x490e1795, 0x896a3f82, 0xc9c747bb, 0x09a36fac,
    0x499db6c9, 0x89f99ede, 0xc954e6e7, 0x0930cef0, 0xcbf03c0d,
    0x0b94141a, 0x4b396c23, 0x8b5d4434, 0xcb639d51, 0x0b07b546,
    0x4baacd7f, 0x8bcee568, 0xcbd67fb4, 0x0bb257a3, 0x4b1f2f9a,
    0x8b7b078d, 0xcb45dee8, 0x0b21f6ff, 0x4b8c8ec6, 0x8be8a6d1,
    0x8abacba4, 0x4adee3b3, 0x0a739b8a, 0xca17b39d, 0x8a296af8,
    0x4a4d42ef, 0x0ae03ad6, 0xca8412c1, 0x8a9c881d, 0x4af8a00a,
    0x0a55d833, 0xca31f024, 0x8a0f2941, 0x4a6b0156, 0x0ac6796f,
    0xcaa25178},
   {0x00000000, 0xd4ea739b, 0xe9d396ed, 0x3d39e576, 0x93a15c00,
    0x474b2f9b, 0x7a72caed, 0xae98b976, 0x2643b900, 0xf2a9ca9b,
    0xcf902fed, 0x1b7a5c76, 0xb5e2e500, 0x6108969b, 0x5c3173ed,
    0x88db0076, 0x4c867201, 0x986c019a, 0xa555e4ec, 0x71bf9777,
    0xdf272e01, 0x0bcd5d9a, 0x36f4b8ec, 0xe21ecb77, 0x6ac5cb01,
    0xbe2fb89a, 0x83165dec, 0x57fc2e77, 0xf9649701, 0x2d8ee49a,
    0x10b701ec, 0xc45d7277, 0x980ce502, 0x4ce69699, 0x71df73ef,
    0xa5350074, 0x0badb902, 0xdf47ca99, 0xe27e2fef, 0x36945c74,
    0xbe4f5c02, 0x6aa52f99, 0x579ccaef, 0x8376b974, 0x2dee0002,
    0xf9047399, 0xc43d96ef, 0x10d7e574, 0xd48a9703, 0x0060e498,
    0x3d5901ee, 0xe9b37275, 0x472bcb03, 0x93c1b898, 0xaef85dee,
    0x7a122e75, 0xf2c92e03, 0x26235d98, 0x1b1ab8ee, 0xcff0cb75,
    0x61687203, 0xb5820198, 0x88bbe4ee, 0x5c519775, 0x3019ca05,
    0xe4f3b99e, 0xd9ca5ce8, 0x0d202f73, 0xa3b89605, 0x7752e59e,
    0x4a6b00e8, 0x9e817373, 0x165a7305, 0xc2b0009e, 0xff89e5e8,
    0x2b639673, 0x85fb2f05, 0x51115c9e, 0x6c28b9e8, 0xb8c2ca73,
    0x7c9fb804, 0xa875cb9f, 0x954c2ee9, 0x41a65d72, 0xef3ee404,
    0x3bd4979f, 0x06ed72e9, 0xd2070172, 0x5adc0104, 0x8e36729f,
    0xb30f97e9, 0x67e5e472, 0xc97d5d04, 0x1d972e9f, 0x20aecbe9,
    0xf444b872, 0xa8152f07, 0x7cff5c9c, 0x41c6b9ea, 0x952cca71,
    0x3bb47307, 0xef5e009c, 0xd267e5ea, 0x068d9671, 0x8e569607,
    0x5abce59c, 0x678500ea, 0xb36f7371, 0x1df7ca07, 0xc91db99c,
    0xf4245cea, 0x20ce2f71, 0xe4935d06, 0x30792e9d, 0x0d40cbeb,
    0xd9aab870, 0x77320106, 0xa3d8729d, 0x9ee197eb, 0x4a0be470,
    0xc2d0e406, 0x163a979d, 0x2b0372eb, 0xffe90170, 0x5171b806,
    0x859bcb9d, 0xb8a22eeb, 0x6c485d70, 0x6032940b, 0xb4d8e790,
    0x89e102e6, 0x5d0b717d, 0xf393c80b, 0x2779bb90, 0x1a405ee6,
    0xceaa2d7d, 0x46712d0b, 0x929b5e90, 0xafa2bbe6, 0x7b48c87d,
    0xd5d0710b, 0x013a0290, 0x3c03e7e6, 0xe8e9947d, 0x2cb4e60a,
    0xf85e9591, 0xc56770e7, 0x118d037c, 0xbf15ba0a, 0x6bffc991,
    0x56c62ce7, 0x822c5f7c, 0x0af75f0a, 0xde1d2c91, 0xe324c9e7,
    0x37ceba7c, 0x9956030a, 0x4dbc7091, 0x708595e7, 0xa46fe67c,
    0xf83e7109, 0x2cd40292, 0x11ede7e4, 0xc507947f, 0x6b9f2d09,
    0xbf755e92, 0x824cbbe4, 0x56a6c87f, 0xde7dc809, 0x0a97bb92,
    0x37ae5ee4, 0xe3442d7f, 0x4ddc9409, 0x9936e792, 0xa40f02e4,
    0x70e5717f, 0xb4b80308, 0x60527093, 0x5d6b95e5, 0x8981e67e,
    0x27195f08, 0xf3f32c93, 0xcecac9e5, 0x1a20ba7e, 0x92fbba08,
    0x4611c993, 0x7b282ce5, 0xafc25f7e, 0x015ae608, 0xd5b09593,
    0xe88970e5, 0x3c63037e, 0x502b5e0e, 0x84c12d95, 0xb9f8c8e3,
    0x6d12bb78, 0xc38a020e, 0x17607195, 0x2a5994e3, 0xfeb3e778,
    0x7668e70e, 0xa2829495, 0x9fbb71e3, 0x4b510278, 0xe5c9bb0e,
    0x3123c895, 0x0c1a2de3, 0xd8f05e78, 0x1cad2c0f, 0xc8475f94,
    0xf57ebae2, 0x2194c979, 0x8f0c700f, 0x5be60394, 0x66dfe6e2,
    0xb2359579, 0x3aee950f, 0xee04e694, 0xd33d03e2, 0x07d77079,
    0xa94fc90f, 0x7da5ba94, 0x409c5fe2, 0x94762c79, 0xc827bb0c,
    0x1ccdc897, 0x21f42de1, 0xf51e5e7a, 0x5b86e70c, 0x8f6c9497,
    0xb25571e1, 0x66bf027a, 0xee64020c, 0x3a8e7197, 0x07b794e1,
    0xd35de77a, 0x7dc55e0c, 0xa92f2d97, 0x9416c8e1, 0x40fcbb7a,
    0x84a1c90d, 0x504bba96, 0x6d725fe0, 0xb9982c7b, 0x1700950d,
    0xc3eae696, 0xfed303e0, 0x2a39707b, 0xa2e2700d, 0x76080396,
    0x4b31e6e0, 0x9fdb957b, 0x31432c0d, 0xe5a95f96, 0xd890bae0,
    0x0c7ac97b},
   {0x00000000, 0x27652581, 0x0fcc3bd9, 0x28a91e58, 0x5f9e0669,
    0x78fb23e8, 0x50523db0, 0x77371831, 0xbe3c0dd2, 0x99592853,
    0xb1f0360b, 0x9695138a, 0xe1a20bbb, 0xc6c72e3a, 0xee6e3062,
    0xc90b15e3, 0x3d7f6b7f, 0x1a1a4efe, 0x32b350a6, 0x15d67527,
    0x62e16d16, 0x45844897, 0x6d2d56cf, 0x4a48734e, 0x834366ad,
    0xa426432c, 0x8c8f5d74, 0xabea78f5, 0xdcdd60c4, 0xfbb84545,
    0xd3115b1d, 0xf4747e9c, 0x7afed6fe, 0x5d9bf37f, 0x7532ed27,
    0x5257c8a6, 0x2560d097, 0x0205f516, 0x2aaceb4e, 0x0dc9cecf,
    0xc4c2db2c, 0xe3a7fead, 0xcb0ee0f5, 0xec6bc574, 0x9b5cdd45,
    0xbc39f8c4, 0x9490e69c, 0xb3f5c31d, 0x4781bd81, 0x60e49800,
    0x484d8658, 0x6f28a3d9, 0x181fbbe8, 0x3f7a9e69, 0x17d38031,
    0x30b6a5b0, 0xf9bdb053, 0xded895d2, 0xf6718b8a, 0xd114ae0b,
    0xa623b63a, 0x814693bb, 0xa9ef8de3, 0x8e8aa862, 0xb5fadc26,
    0x929ff9a7, 0xba36e7ff, 0x9d53c27e, 0xea64da4f, 0xcd01ffce,
    0xe5a8e196, 0xc2cdc417, 0x0bc6d1f4, 0x2ca3f475, 0x040aea2d,
    0x236fcfac, 0x5458d79d, 0x733df21c, 0x5b94ec44, 0x7cf1c9c5,
    0x8885b759, 0xafe092d8, 0x87498c80, 0xa02ca901, 0xd71bb130,
    0xf07e94b1, 0xd8d78ae9, 0xffb2af68, 0x36b9ba8b, 0x11dc9f0a,
    0x39758152, 0x1e10a4d3, 0x6927bce2, 0x4e429963, 0x66eb873b,
    0x418ea2ba, 0xcf040ad8, 0xe8612f59, 0xc0c83101, 0xe7ad1480,
    0x909a0cb1, 0xb7ff2930, 0x9f563768, 0xb83312e9, 0x7138070a,
    0x565d228b, 0x7ef43cd3, 0x59911952, 0x2ea60163, 0x09c324e2,
    0x216a3aba, 0x060f1f3b, 0xf27b61a7, 0xd51e4426, 0xfdb75a7e,
    0xdad27fff, 0xade567ce, 0x8a80424f, 0xa2295c17, 0x854c7996,
    0x4c476c75, 0x6b2249f4, 0x438b57ac, 0x64ee722d, 0x13d96a1c,
    0x34bc4f9d, 0x1c1551c5, 0x3b707444, 0x6af5b94d, 0x4d909ccc,
    0x65398294, 0x425ca715, 0x356bbf24, 0x120e9aa5, 0x3aa784fd,
    0x1dc2a17c, 0xd4c9b49f, 0xf3ac911e, 0xdb058f46, 0xfc60aac7,
    0x8b57b2f6, 0xac329777, 0x849b892f, 0xa3feacae, 0x578ad232,
    0x70eff7b3, 0x5846e9eb, 0x7f23cc6a, 0x0814d45b, 0x2f71f1da,
    0x07d8ef82, 0x20bdca03, 0xe9b6dfe0, 0xced3fa61, 0xe67ae439,
    0xc11fc1b8, 0xb628d989, 0x914dfc08, 0xb9e4e250, 0x9e81c7d1,
    0x100b6fb3, 0x376e4a32, 0x1fc7546a, 0x38a271eb, 0x4f9569da,
    0x68f04c5b, 0x40595203, 0x673c7782, 0xae376261, 0x895247e0,
    0xa1fb59b8, 0x869e7c39, 0xf1a96408, 0xd6cc4189, 0xfe655fd1,
    0xd9007a50, 0x2d7404cc, 0x0a11214d, 0x22b83f15, 0x05dd1a94,
    0x72ea02a5, 0x558f2724, 0x7d26397c, 0x5a431cfd, 0x9348091e,
    0xb42d2c9f, 0x9c8432c7, 0xbbe11746, 0xccd60f77, 0xebb32af6,
    0xc31a34ae, 0xe47f112f, 0xdf0f656b, 0xf86a40ea, 0xd0c35eb2,
    0xf7a67b33, 0x80916302, 0xa7f44683, 0x8f5d58db, 0xa8387d5a,
    0x613368b9, 0x46564d38, 0x6eff5360, 0x499a76e1, 0x3ead6ed0,
    0x19c84b51, 0x31615509, 0x16047088, 0xe2700e14, 0xc5152b95,
    0xedbc35cd, 0xcad9104c, 0xbdee087d, 0x9a8b2dfc, 0xb22233a4,
    0x95471625, 0x5c4c03c6, 0x7b292647, 0x5380381f, 0x74e51d9e,
    0x03d205af, 0x24b7202e, 0x0c1e3e76, 0x2b7b1bf7, 0xa5f1b395,
    0x82949614, 0xaa3d884c, 0x8d58adcd, 0xfa6fb5fc, 0xdd0a907d,
    0xf5a38e25, 0xd2c6aba4, 0x1bcdbe47, 0x3ca89bc6, 0x1401859e,
    0x3364a01f, 0x4453b82e, 0x63369daf, 0x4b9f83f7, 0x6cfaa676,
    0x988ed8ea, 0xbfebfd6b, 0x9742e333, 0xb027c6b2, 0xc710de83,
    0xe075fb02, 0xc8dce55a, 0xefb9c0db, 0x26b2d538, 0x01d7f0b9,
    0x297eeee1, 0x0e1bcb60, 0x792cd351, 0x5e49f6d0, 0x76e0e888,
    0x5185cd09}};

#endif

#endif

#endif
  }
};

local const z_crc_t FAR x2n_table[] = {
    0x40000000, 0x20000000, 0x08000000, 0x00800000, 0x00008000,
    0xedb88320, 0xb1e6b092, 0xa06a2517, 0xed627dae, 0x88d14467,
    0xd7bbfe6a, 0xec447f11, 0x8e7ea170, 0x6427800e, 0x4d47bae0,
    0x09fe548f, 0x83852d0f, 0x30362f1a, 0x7b5a9cc3, 0x31fec169,
    0x9fec022a, 0x6c8dedc4, 0x15d6874d, 0x5fde7a4e, 0xbad90e37,
    0x2e4e5eef, 0x4eaba214, 0xa8a472c0, 0x429a969e, 0x148d302a,
    0xc40ba6d0, 0xc4e22c3c};

Changes to compat/zlib/deflate.c.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/* deflate.c -- compress data using the deflation algorithm
 * Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
 * Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/*
 *  ALGORITHM
 *
 *      The "deflation" process depends on being able to identify portions
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
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







-
+







-
-
-







-
+


-
-
-
-
-
+
+

-
+

-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







 */

/* @(#) $Id$ */

#include "deflate.h"

const char deflate_copyright[] =
   " deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler ";
   " deflate 1.3.1 Copyright 1995-2024 Jean-loup Gailly and Mark Adler ";
/*
  If you use the zlib library in a product, an acknowledgment is welcome
  in the documentation of your product. If for some reason you cannot
  include such an acknowledgment, I would appreciate that you keep this
  copyright string in the executable of your product.
 */

/* ===========================================================================
 *  Function prototypes.
 */
typedef enum {
    need_more,      /* block not completed, need more input or more output */
    block_done,     /* block flush performed */
    finish_started, /* finish started, need only more output at next deflate */
    finish_done     /* finish done, accept no more input or output */
} block_state;

typedef block_state (*compress_func) OF((deflate_state *s, int flush));
typedef block_state (*compress_func)(deflate_state *s, int flush);
/* Compression function. Returns the block state after the call. */

local int deflateStateCheck      OF((z_streamp strm));
local void slide_hash     OF((deflate_state *s));
local void fill_window    OF((deflate_state *s));
local block_state deflate_stored OF((deflate_state *s, int flush));
local block_state deflate_fast   OF((deflate_state *s, int flush));
local block_state deflate_stored(deflate_state *s, int flush);
local block_state deflate_fast(deflate_state *s, int flush);
#ifndef FASTEST
local block_state deflate_slow   OF((deflate_state *s, int flush));
local block_state deflate_slow(deflate_state *s, int flush);
#endif
local block_state deflate_rle    OF((deflate_state *s, int flush));
local block_state deflate_huff   OF((deflate_state *s, int flush));
local block_state deflate_rle(deflate_state *s, int flush);
local block_state deflate_huff(deflate_state *s, int flush);
local void lm_init        OF((deflate_state *s));
local void putShortMSB    OF((deflate_state *s, uInt b));
local void flush_pending  OF((z_streamp strm));
local unsigned read_buf   OF((z_streamp strm, Bytef *buf, unsigned size));
#ifdef ASMV
#  pragma message("Assembler code may have bugs -- use at your own risk")
      void match_init OF((void)); /* asm code initialization */
      uInt longest_match  OF((deflate_state *s, IPos cur_match));
#else
local uInt longest_match  OF((deflate_state *s, IPos cur_match));
#endif

#ifdef ZLIB_DEBUG
local  void check_match OF((deflate_state *s, IPos start, IPos match,
                            int length));
#endif

/* ===========================================================================
 * Local data
 */

#define NIL 0
/* Tail of hash chains */
156
157
158
159
160
161
162
163

164
165
166
167
168
169
170
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148







-
+








/* ===========================================================================
 * Update a hash value with the given input byte
 * IN  assertion: all calls to UPDATE_HASH are made with consecutive input
 *    characters, so that a running hash key can be computed from the previous
 *    key instead of complete recalculation each time.
 */
#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
#define UPDATE_HASH(s,h,c) (h = (((h) << s->hash_shift) ^ (c)) & s->hash_mask)


/* ===========================================================================
 * Insert string str in the dictionary and set match_head to the previous head
 * of the hash chain (the most recent string with same hash key). Return
 * the previous length of the hash chain.
 * If this file is compiled with -DFASTEST, the compression level is forced
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
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







+
-
-
+
+
+
+






+
+
+
+
+
-
+
-
-







#endif

/* ===========================================================================
 * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
 * prev[] will be initialized on the fly.
 */
#define CLEAR_HASH(s) \
    do { \
    s->head[s->hash_size-1] = NIL; \
    zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
        s->head[s->hash_size - 1] = NIL; \
        zmemzero((Bytef *)s->head, \
                 (unsigned)(s->hash_size - 1)*sizeof(*s->head)); \
    } while (0)

/* ===========================================================================
 * Slide the hash table when sliding the window down (could be avoided with 32
 * bit values at the expense of memory usage). We slide even when level == 0 to
 * keep the hash table consistent if we switch back to level > 0 later.
 */
#if defined(__has_feature)
#  if __has_feature(memory_sanitizer)
     __attribute__((no_sanitize("memory")))
#  endif
#endif
local void slide_hash(s)
local void slide_hash(deflate_state *s) {
    deflate_state *s;
{
    unsigned n, m;
    Posf *p;
    uInt wsize = s->w_size;

    n = s->hash_size;
    p = &s->head[n];
    do {
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
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
-
+
+
-






-
+
-
-
-
-
-
+
-
-
-
+
-
-




-
-
-
-
-







        *p = (Pos)(m >= wsize ? m - wsize : NIL);
        /* If n is not on any hash chain, prev[n] is garbage but
         * its value will never be used.
         */
    } while (--n);
#endif
}

/* ===========================================================================
 * Read a new buffer from the current input stream, update the adler32
 * and total number of bytes read.  All deflate() input goes through
 * this function so some applications may wish to modify it to avoid
 * allocating a large strm->next_in buffer and copying from it.
 * (See also flush_pending()).
 */
local unsigned read_buf(z_streamp strm, Bytef *buf, unsigned size) {
    unsigned len = strm->avail_in;

    if (len > size) len = size;
    if (len == 0) return 0;

    strm->avail_in  -= len;

    zmemcpy(buf, strm->next_in, len);
    if (strm->state->wrap == 1) {
        strm->adler = adler32(strm->adler, buf, len);
    }
#ifdef GZIP
    else if (strm->state->wrap == 2) {
        strm->adler = crc32(strm->adler, buf, len);
    }
#endif
    strm->next_in  += len;
    strm->total_in += len;

    return len;
}

/* ===========================================================================
 * Fill the window when the lookahead becomes insufficient.
 * Updates strstart and lookahead.
 *
 * IN assertion: lookahead < MIN_LOOKAHEAD
 * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
 *    At least one byte has been read, or avail_in == 0; reads are
 *    performed for at least two bytes (required for the zip translate_eol
 *    option -- not supported here).
 */
local void fill_window(deflate_state *s) {
    unsigned n;
    unsigned more;    /* Amount of free space at the end of the window. */
    uInt wsize = s->w_size;

    Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");

    do {
        more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);

        /* Deal with !@#$% 64K limit: */
        if (sizeof(int) <= 2) {
            if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
                more = wsize;

            } else if (more == (unsigned)(-1)) {
                /* Very unlikely, but possible on 16 bit machine if
                 * strstart == 0 && lookahead == 1 (input done a byte at time)
                 */
                more--;
            }
        }

        /* If the window is almost full and there is insufficient lookahead,
         * move the upper half to the lower one to make room in the upper half.
         */
        if (s->strstart >= wsize + MAX_DIST(s)) {

            zmemcpy(s->window, s->window + wsize, (unsigned)wsize - more);
            s->match_start -= wsize;
            s->strstart    -= wsize; /* we now have strstart >= MAX_DIST */
            s->block_start -= (long) wsize;
            if (s->insert > s->strstart)
                s->insert = s->strstart;
            slide_hash(s);
            more += wsize;
        }
        if (s->strm->avail_in == 0) break;

        /* If there was no sliding:
         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
         *    more == window_size - lookahead - strstart
         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
         * => more >= window_size - 2*WSIZE + 2
         * In the BIG_MEM or MMAP case (not yet supported),
         *   window_size == input_size + MIN_LOOKAHEAD  &&
         *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
         * Otherwise, window_size == 2*WSIZE so more >= 2.
         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
         */
        Assert(more >= 2, "more < 2");

        n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
        s->lookahead += n;

        /* Initialize the hash value now that we have some input: */
        if (s->lookahead + s->insert >= MIN_MATCH) {
            uInt str = s->strstart - s->insert;
            s->ins_h = s->window[str];
            UPDATE_HASH(s, s->ins_h, s->window[str + 1]);
#if MIN_MATCH != 3
            Call UPDATE_HASH() MIN_MATCH-3 more times
#endif
            while (s->insert) {
                UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
#ifndef FASTEST
                s->prev[str & s->w_mask] = s->head[s->ins_h];
#endif
                s->head[s->ins_h] = (Pos)str;
                str++;
                s->insert--;
                if (s->lookahead + s->insert < MIN_MATCH)
                    break;
            }
        }
        /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
         * but this is not important since only literal bytes will be emitted.
         */

    } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);

    /* If the WIN_INIT bytes after the end of the current data have never been
     * written, then zero those bytes in order to avoid memory check reports of
     * the use of uninitialized (or uninitialised as Julian writes) bytes by
     * the longest match routines.  Update the high water mark for the next
     * time through here.  WIN_INIT is set to MAX_MATCH since the longest match
     * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
     */
    if (s->high_water < s->window_size) {
        ulg curr = s->strstart + (ulg)(s->lookahead);
        ulg init;

        if (s->high_water < curr) {
            /* Previous high water mark below current data -- zero WIN_INIT
             * bytes or up to end of window, whichever is less.
             */
            init = s->window_size - curr;
            if (init > WIN_INIT)
                init = WIN_INIT;
            zmemzero(s->window + curr, (unsigned)init);
            s->high_water = curr + init;
        }
        else if (s->high_water < (ulg)curr + WIN_INIT) {
            /* High water mark at or above current data, but below current data
             * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
             * to end of window, whichever is less.
             */
            init = (ulg)curr + WIN_INIT - s->high_water;
            if (init > s->window_size - s->high_water)
                init = s->window_size - s->high_water;
            zmemzero(s->window + s->high_water, (unsigned)init);
            s->high_water += init;
        }
    }

    Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
           "not enough room for search");
}

/* ========================================================================= */
int ZEXPORT deflateInit_(strm, level, version, stream_size)
    z_streamp strm;
    int level;
    const char *version;
    int stream_size;
int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version,
                         int stream_size) {
{
    return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
                         Z_DEFAULT_STRATEGY, version, stream_size);
    /* To do: ignore strm->next_in if we use it as window */
}

/* ========================================================================= */
int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
int ZEXPORT deflateInit2_(z_streamp strm, int level, int method,
                  version, stream_size)
    z_streamp strm;
    int  level;
    int  method;
    int  windowBits;
                          int windowBits, int memLevel, int strategy,
    int  memLevel;
    int  strategy;
    const char *version;
                          const char *version, int stream_size) {
    int stream_size;
{
    deflate_state *s;
    int wrap = 1;
    static const char my_version[] = ZLIB_VERSION;

    ushf *overlay;
    /* We overlay pending_buf and d_buf+l_buf. This works since the average
     * output size for (length,distance) codes is <= 24 bits.
     */

    if (version == Z_NULL || version[0] != my_version[0] ||
        stream_size != sizeof(z_stream)) {
        return Z_VERSION_ERROR;
    }
    if (strm == Z_NULL) return Z_STREAM_ERROR;

    strm->msg = Z_NULL;
283
284
285
286
287
288
289


290
291
292
293
294
295
296
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424







+
+







    if (level != 0) level = 1;
#else
    if (level == Z_DEFAULT_COMPRESSION) level = 6;
#endif

    if (windowBits < 0) { /* suppress zlib wrapper */
        wrap = 0;
        if (windowBits < -15)
            return Z_STREAM_ERROR;
        windowBits = -windowBits;
    }
#ifdef GZIP
    else if (windowBits > 15) {
        wrap = 2;       /* write gzip wrapper instead */
        windowBits -= 16;
    }
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
366
367
368
369
370
371
372
373
374
375
376

377
378
379

380
381
382
383
384
385
386
387
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558







-
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+








+
-
-
+
+
+
+
+
+
+
+
+
+
+











-
+
-
-




















-
+
-
-
-
+
-







    s->w_bits = (uInt)windowBits;
    s->w_size = 1 << s->w_bits;
    s->w_mask = s->w_size - 1;

    s->hash_bits = (uInt)memLevel + 7;
    s->hash_size = 1 << s->hash_bits;
    s->hash_mask = s->hash_size - 1;
    s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
    s->hash_shift =  ((s->hash_bits + MIN_MATCH-1) / MIN_MATCH);

    s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
    s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
    s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));

    s->high_water = 0;      /* nothing written to s->window yet */

    s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */

    /* We overlay pending_buf and sym_buf. This works since the average size
     * for length/distance pairs over any compressed block is assured to be 31
     * bits or less.
     *
     * Analysis: The longest fixed codes are a length code of 8 bits plus 5
     * extra bits, for lengths 131 to 257. The longest fixed distance codes are
     * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest
     * possible fixed-codes length/distance pair is then 31 bits total.
     *
     * sym_buf starts one-fourth of the way into pending_buf. So there are
     * three bytes in sym_buf for every four bytes in pending_buf. Each symbol
     * in sym_buf is three bytes -- two for the distance and one for the
     * literal/length. As each symbol is consumed, the pointer to the next
     * sym_buf value to read moves forward three bytes. From that symbol, up to
     * 31 bits are written to pending_buf. The closest the written pending_buf
     * bits gets to the next sym_buf symbol to read is just before the last
     * code is written. At that time, 31*(n - 2) bits have been written, just
     * after 24*(n - 2) bits have been consumed from sym_buf. sym_buf starts at
     * 8*n bits into pending_buf. (Note that the symbol buffer fills when n - 1
     * symbols are written.) The closest the writing gets to what is unread is
     * then n + 14 bits. Here n is lit_bufsize, which is 16384 by default, and
     * can range from 128 to 32768.
     *
     * Therefore, at a minimum, there are 142 bits of space between what is
     * written and what is read in the overlain buffers, so the symbols cannot
     * be overwritten by the compressed data. That space is actually 139 bits,
     * due to the three-bit fixed-code block header.
     *
     * That covers the case where either Z_FIXED is specified, forcing fixed
     * codes, or when the use of fixed codes is chosen, because that choice
     * results in a smaller compressed block than dynamic codes. That latter
     * condition then assures that the above analysis also covers all dynamic
     * blocks. A dynamic-code block will only be chosen to be emitted if it has
     * fewer bits than a fixed-code block would for the same set of symbols.
     * Therefore its average symbol length is assured to be less than 31. So
     * the compressed data for a dynamic block also cannot overwrite the
     * symbols from which it is being constructed.
     */
    overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
    s->pending_buf = (uchf *) overlay;
    s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);

    s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, LIT_BUFS);
    s->pending_buf_size = (ulg)s->lit_bufsize * 4;

    if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
        s->pending_buf == Z_NULL) {
        s->status = FINISH_STATE;
        strm->msg = ERR_MSG(Z_MEM_ERROR);
        deflateEnd (strm);
        return Z_MEM_ERROR;
    }
#ifdef LIT_MEM
    s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
    s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
    s->d_buf = (ushf *)(s->pending_buf + (s->lit_bufsize << 1));
    s->l_buf = s->pending_buf + (s->lit_bufsize << 2);
    s->sym_end = s->lit_bufsize - 1;
#else
    s->sym_buf = s->pending_buf + s->lit_bufsize;
    s->sym_end = (s->lit_bufsize - 1) * 3;
#endif
    /* We avoid equality with lit_bufsize*3 because of wraparound at 64K
     * on 16 bit machines and because stored blocks are restricted to
     * 64K-1 bytes.
     */

    s->level = level;
    s->strategy = strategy;
    s->method = (Byte)method;

    return deflateReset(strm);
}

/* =========================================================================
 * Check for a valid deflate stream state. Return 0 if ok, 1 if not.
 */
local int deflateStateCheck (strm)
local int deflateStateCheck(z_streamp strm) {
    z_streamp strm;
{
    deflate_state *s;
    if (strm == Z_NULL ||
        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
        return 1;
    s = strm->state;
    if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE &&
#ifdef GZIP
                                           s->status != GZIP_STATE &&
#endif
                                           s->status != EXTRA_STATE &&
                                           s->status != NAME_STATE &&
                                           s->status != COMMENT_STATE &&
                                           s->status != HCRC_STATE &&
                                           s->status != BUSY_STATE &&
                                           s->status != FINISH_STATE))
        return 1;
    return 0;
}

/* ========================================================================= */
int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
int ZEXPORT deflateSetDictionary(z_streamp strm, const Bytef *dictionary,
    z_streamp strm;
    const Bytef *dictionary;
    uInt  dictLength;
                                 uInt  dictLength) {
{
    deflate_state *s;
    uInt str, n;
    int wrap;
    unsigned avail;
    z_const unsigned char *next;

    if (deflateStateCheck(strm) || dictionary == Z_NULL)
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
467

468
469
470
471
472
473
474
475
476
609
610
611
612
613
614
615

616



617

618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634

635


636
637
638
639
640
641
642







-
+
-
-
-
+
-

















-
+
-
-







    strm->next_in = next;
    strm->avail_in = avail;
    s->wrap = wrap;
    return Z_OK;
}

/* ========================================================================= */
int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength)
int ZEXPORT deflateGetDictionary(z_streamp strm, Bytef *dictionary,
    z_streamp strm;
    Bytef *dictionary;
    uInt  *dictLength;
                                 uInt *dictLength) {
{
    deflate_state *s;
    uInt len;

    if (deflateStateCheck(strm))
        return Z_STREAM_ERROR;
    s = strm->state;
    len = s->strstart + s->lookahead;
    if (len > s->w_size)
        len = s->w_size;
    if (dictionary != Z_NULL && len)
        zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len);
    if (dictLength != Z_NULL)
        *dictLength = len;
    return Z_OK;
}

/* ========================================================================= */
int ZEXPORT deflateResetKeep (strm)
int ZEXPORT deflateResetKeep(z_streamp strm) {
    z_streamp strm;
{
    deflate_state *s;

    if (deflateStateCheck(strm)) {
        return Z_STREAM_ERROR;
    }

    strm->total_in = strm->total_out = 0;
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
558
559
560
561
562
563
564
565
566
567
568

569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590

591
592
593
594
595

596
597
598
599
600
601
602
650
651
652
653
654
655
656

657
658
659
660
661
662

663
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
707
708
709
710
711
712

713




714
715
716
717
718
719
720
721
722

723




724
725
726
727
728
729
730
731
732
733
734

735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751

752




753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769

770
771
772
773
774

775
776
777
778
779
780
781
782







-
+





-
+






-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+
-
-
-







-
+
-
-
-
-









-
+
-
-
-
-





+
+
+
+
+
+
-
+

+














-
+
-
-
-
-

















-
+




-
+







    if (s->wrap < 0) {
        s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
    }
    s->status =
#ifdef GZIP
        s->wrap == 2 ? GZIP_STATE :
#endif
        s->wrap ? INIT_STATE : BUSY_STATE;
        INIT_STATE;
    strm->adler =
#ifdef GZIP
        s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
#endif
        adler32(0L, Z_NULL, 0);
    s->last_flush = Z_NO_FLUSH;
    s->last_flush = -2;

    _tr_init(s);

    return Z_OK;
}

/* ========================================================================= */
int ZEXPORT deflateReset (strm)
    z_streamp strm;
{
/* ===========================================================================
 * Initialize the "longest match" routines for a new zlib stream
 */
local void lm_init(deflate_state *s) {
    s->window_size = (ulg)2L*s->w_size;

    CLEAR_HASH(s);

    /* Set the default configuration parameters:
     */
    s->max_lazy_match   = configuration_table[s->level].max_lazy;
    s->good_match       = configuration_table[s->level].good_length;
    s->nice_match       = configuration_table[s->level].nice_length;
    s->max_chain_length = configuration_table[s->level].max_chain;

    s->strstart = 0;
    s->block_start = 0L;
    s->lookahead = 0;
    s->insert = 0;
    s->match_length = s->prev_length = MIN_MATCH-1;
    s->match_available = 0;
    s->ins_h = 0;
}

/* ========================================================================= */
int ZEXPORT deflateReset(z_streamp strm) {
    int ret;

    ret = deflateResetKeep(strm);
    if (ret == Z_OK)
        lm_init(strm->state);
    return ret;
}

/* ========================================================================= */
int ZEXPORT deflateSetHeader (strm, head)
int ZEXPORT deflateSetHeader(z_streamp strm, gz_headerp head) {
    z_streamp strm;
    gz_headerp head;
{
    if (deflateStateCheck(strm) || strm->state->wrap != 2)
        return Z_STREAM_ERROR;
    strm->state->gzhead = head;
    return Z_OK;
}

/* ========================================================================= */
int ZEXPORT deflatePending (strm, pending, bits)
int ZEXPORT deflatePending(z_streamp strm, unsigned *pending, int *bits) {
    unsigned *pending;
    int *bits;
    z_streamp strm;
{
    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
    if (pending != Z_NULL)
        *pending = strm->state->pending;
    if (bits != Z_NULL)
        *bits = strm->state->bi_valid;
    return Z_OK;
}

/* ========================================================================= */
int ZEXPORT deflatePrime (strm, bits, value)
int ZEXPORT deflatePrime(z_streamp strm, int bits, int value) {
    z_streamp strm;
    int bits;
    int value;
{
    deflate_state *s;
    int put;

    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
    s = strm->state;
#ifdef LIT_MEM
    if (bits < 0 || bits > 16 ||
        (uchf *)s->d_buf < s->pending_out + ((Buf_size + 7) >> 3))
        return Z_BUF_ERROR;
#else
    if (bits < 0 || bits > 16 ||
    if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3))
        s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3))
        return Z_BUF_ERROR;
#endif
    do {
        put = Buf_size - s->bi_valid;
        if (put > bits)
            put = bits;
        s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid);
        s->bi_valid += put;
        _tr_flush_bits(s);
        value >>= put;
        bits -= put;
    } while (bits);
    return Z_OK;
}

/* ========================================================================= */
int ZEXPORT deflateParams(strm, level, strategy)
int ZEXPORT deflateParams(z_streamp strm, int level, int strategy) {
    z_streamp strm;
    int level;
    int strategy;
{
    deflate_state *s;
    compress_func func;

    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
    s = strm->state;

#ifdef FASTEST
    if (level != 0) level = 1;
#else
    if (level == Z_DEFAULT_COMPRESSION) level = 6;
#endif
    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
        return Z_STREAM_ERROR;
    }
    func = configuration_table[s->level].func;

    if ((strategy != s->strategy || func != configuration_table[level].func) &&
        s->high_water) {
        s->last_flush != -2) {
        /* Flush the last buffer: */
        int err = deflate(strm, Z_BLOCK);
        if (err == Z_STREAM_ERROR)
            return err;
        if (strm->avail_out == 0)
        if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead)
            return Z_BUF_ERROR;
    }
    if (s->level != level) {
        if (s->level == 0 && s->matches != 0) {
            if (s->matches == 1)
                slide_hash(s);
            else
610
611
612
613
614
615
616
617
618
619

620
621

622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638



639
640
641
642
643
644
645








646
647
648
649





650




651
652
653
654
655
656







657


658
659
660
661




662
663

664
665

666
667
668
669
670
671
672
790
791
792
793
794
795
796



797


798


799
800
801
802
803
804
805
806
807
808
809
810



811
812
813


814




815
816
817
818
819
820
821
822
823



824
825
826
827
828

829
830
831
832
833





834
835
836
837
838
839
840

841
842
843



844
845
846
847
848

849
850

851
852
853
854
855
856
857
858







-
-
-
+
-
-
+
-
-












-
-
-
+
+
+
-
-

-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
+
+
+
+
+
-
+
+
+
+

-
-
-
-
-
+
+
+
+
+
+
+
-
+
+

-
-
-
+
+
+
+

-
+

-
+







        s->max_chain_length = configuration_table[level].max_chain;
    }
    s->strategy = strategy;
    return Z_OK;
}

/* ========================================================================= */
int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
    z_streamp strm;
    int good_length;
int ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy,
    int max_lazy;
    int nice_length;
                        int nice_length, int max_chain) {
    int max_chain;
{
    deflate_state *s;

    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
    s = strm->state;
    s->good_match = (uInt)good_length;
    s->max_lazy_match = (uInt)max_lazy;
    s->nice_match = nice_length;
    s->max_chain_length = (uInt)max_chain;
    return Z_OK;
}

/* =========================================================================
 * For the default windowBits of 15 and memLevel of 8, this function returns
 * a close to exact, as well as small, upper bound on the compressed size.
 * They are coded as constants here for a reason--if the #define's are
 * For the default windowBits of 15 and memLevel of 8, this function returns a
 * close to exact, as well as small, upper bound on the compressed size. This
 * is an expansion of ~0.03%, plus a small constant.
 * changed, then this function needs to be changed as well.  The return
 * value for 15 and 8 only works for those exact settings.
 *
 * For any setting other than those defaults for windowBits and memLevel,
 * the value returned is a conservative worst case for the maximum expansion
 * resulting from using fixed blocks instead of stored blocks, which deflate
 * can emit on compressed data for some combinations of the parameters.
 * For any setting other than those defaults for windowBits and memLevel, one
 * of two worst case bounds is returned. This is at most an expansion of ~4% or
 * ~13%, plus a small constant.
 *
 * Both the 0.03% and 4% derive from the overhead of stored blocks. The first
 * one is for stored blocks of 16383 bytes (memLevel == 8), whereas the second
 * is for stored blocks of 127 bytes (the worst case memLevel == 1). The
 * expansion results from five bytes of header for each stored block.
 *
 * This function could be more sophisticated to provide closer upper bounds for
 * every combination of windowBits and memLevel.  But even the conservative
 * upper bound of about 14% expansion does not seem onerous for output buffer
 * The larger expansion of 13% results from a window size less than or equal to
 * the symbols buffer size (windowBits <= memLevel + 7). In that case some of
 * the data being compressed may have slid out of the sliding window, impeding
 * a stored block from being emitted. Then the only choice is a fixed or
 * dynamic block, where a fixed block limits the maximum expansion to 9 bits
 * allocation.
 * per 8-bit byte, plus 10 bits for every block. The smallest block size for
 * which this can occur is 255 (memLevel == 2).
 *
 * Shifts are used to approximate divisions, for speed.
 */
uLong ZEXPORT deflateBound(strm, sourceLen)
    z_streamp strm;
    uLong sourceLen;
{
    deflate_state *s;
uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) {
    deflate_state *s;
    uLong fixedlen, storelen, wraplen;

    /* upper bound for fixed blocks with 9-bit literals and length 255
       (memLevel == 2, which is the lowest that may not use stored blocks) --
       ~13% overhead plus a small constant */
    uLong complen, wraplen;
    fixedlen = sourceLen + (sourceLen >> 3) + (sourceLen >> 8) +
               (sourceLen >> 9) + 4;

    /* conservative upper bound for compressed data */
    complen = sourceLen +
              ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5;
    /* upper bound for stored blocks with length 127 (memLevel == 1) --
       ~4% overhead plus a small constant */
    storelen = sourceLen + (sourceLen >> 5) + (sourceLen >> 7) +
               (sourceLen >> 11) + 7;

    /* if can't get parameters, return conservative bound plus zlib wrapper */
    /* if can't get parameters, return larger bound plus a zlib wrapper */
    if (deflateStateCheck(strm))
        return complen + 6;
        return (fixedlen > storelen ? fixedlen : storelen) + 6;

    /* compute wrapper length */
    s = strm->state;
    switch (s->wrap) {
    case 0:                                 /* raw deflate */
        wraplen = 0;
        break;
695
696
697
698
699
700
701
702

703

704

705
706


707
708
709
710
711
712
713
714
715
716

717
718
719
720
721
722
723
724
725
726
727
728
729
730

731
732
733
734
735
736
737
738
739
881
882
883
884
885
886
887

888
889
890

891
892

893
894
895
896
897
898
899
900
901
902
903

904



905
906
907
908
909
910
911
912
913
914

915


916
917
918
919
920
921
922







-
+

+
-
+

-
+
+









-
+
-
-
-










-
+
-
-







        }
        break;
#endif
    default:                                /* for compiler happiness */
        wraplen = 6;
    }

    /* if not default parameters, return conservative bound */
    /* if not default parameters, return one of the conservative bounds */
    if (s->w_bits != 15 || s->hash_bits != 8 + 7)
        return (s->w_bits <= s->hash_bits && s->level ? fixedlen : storelen) +
        return complen + wraplen;
               wraplen;

    /* default settings: return tight bound for that case */
    /* default settings: return tight bound for that case -- ~0.03% overhead
       plus a small constant */
    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
           (sourceLen >> 25) + 13 - 6 + wraplen;
}

/* =========================================================================
 * Put a short in the pending buffer. The 16-bit value is put in MSB order.
 * IN assertion: the stream state is correct and there is enough room in
 * pending_buf.
 */
local void putShortMSB (s, b)
local void putShortMSB(deflate_state *s, uInt b) {
    deflate_state *s;
    uInt b;
{
    put_byte(s, (Byte)(b >> 8));
    put_byte(s, (Byte)(b & 0xff));
}

/* =========================================================================
 * Flush as much pending output as possible. All deflate() output, except for
 * some deflate_stored() output, goes through this function so some
 * applications may wish to modify it to avoid allocating a large
 * strm->next_out buffer and copying into it. (See also read_buf()).
 */
local void flush_pending(strm)
local void flush_pending(z_streamp strm) {
    z_streamp strm;
{
    unsigned len;
    deflate_state *s = strm->state;

    _tr_flush_bits(s);
    len = s->pending;
    if (len > strm->avail_out) len = strm->avail_out;
    if (len == 0) return;
756
757
758
759
760
761
762
763

764
765
766
767
768
769
770
771
772
773
939
940
941
942
943
944
945

946



947
948
949
950
951
952
953







-
+
-
-
-







    do { \
        if (s->gzhead->hcrc && s->pending > (beg)) \
            strm->adler = crc32(strm->adler, s->pending_buf + (beg), \
                                s->pending - (beg)); \
    } while (0)

/* ========================================================================= */
int ZEXPORT deflate (strm, flush)
int ZEXPORT deflate(z_streamp strm, int flush) {
    z_streamp strm;
    int flush;
{
    int old_flush; /* value of flush param for previous deflate call */
    deflate_state *s;

    if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) {
        return Z_STREAM_ERROR;
    }
    s = strm->state;
807
808
809
810
811
812
813


814
815
816

817
818
819
820
821
822
823
987
988
989
990
991
992
993
994
995
996
997

998
999
1000
1001
1002
1003
1004
1005







+
+


-
+








    /* User must not provide more input after the first FINISH: */
    if (s->status == FINISH_STATE && strm->avail_in != 0) {
        ERR_RETURN(strm, Z_BUF_ERROR);
    }

    /* Write the header */
    if (s->status == INIT_STATE && s->wrap == 0)
        s->status = BUSY_STATE;
    if (s->status == INIT_STATE) {
        /* zlib header */
        uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
        uInt header = (Z_DEFLATED + ((s->w_bits - 8) << 4)) << 8;
        uInt level_flags;

        if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
            level_flags = 0;
        else if (s->level < 6)
            level_flags = 1;
        else if (s->level == 6)
1069
1070
1071
1072
1073
1074
1075
1076

1077
1078
1079
1080
1081
1082
1083
1084
1085
1251
1252
1253
1254
1255
1256
1257

1258


1259
1260
1261
1262
1263
1264
1265







-
+
-
-







     * to flush the rest.
     */
    if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
    return s->pending != 0 ? Z_OK : Z_STREAM_END;
}

/* ========================================================================= */
int ZEXPORT deflateEnd (strm)
int ZEXPORT deflateEnd(z_streamp strm) {
    z_streamp strm;
{
    int status;

    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;

    status = strm->state->status;

    /* Deallocate in reverse order of allocations: */
1095
1096
1097
1098
1099
1100
1101
1102

1103
1104
1105
1106


1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132

1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143

1144
1145

1146
1147





1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354


1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399


1400
1401
1402
1403
1404
1405
1406
1407
1408
1409

1410
1411
1412
1413
1414
1415
1416
1417
1418
1419

1420
1421
1422
1423
1424
1425
1426
1427
1428

1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389

1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408

1409
1410
1411
1412
1413
1414

1415
1416

1417
1418
1419
1420
1421
1422
1423




1424
1425
1426
1427
1428
1429
1430


1431
1432
1433
1434
1435

1436
1437
1438
1439
1440




1441
1442
1443
1444
1445

1446
1447
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

1478
1479

1480
1481
1482
1483
1484
1485
1486
1487
1488
1489

1490
1491
1492
1493
1494
1495

1496



1497
1498
1499
1500
1501
1502
1503
1504
1505
1506

1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517

1518
1519
1520
1521
1522
1523
1524
1525
1526
1527

1528
1529
1530
1531
1532
1533
1534
1535
1536

1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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







-
+
-
-
-

+
+




-



















-
-
+










-
+


+
-
-
+
+
+
+
+









-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-










-
-
-
-
-
+
-
-
-




















-
+


-
+

















-
+
+

















-
+





-
+

-
+






-
-
-
-
+
+
+
+



-
-
+
+
+


-
+




-
-
-
-
+
+
+
+

-
+









-
+








-
+
+











-
+

-
+









-






-
+
-
-
-










-
+
+









-
+









-
+








-
+



















-
+
-
-
-
-

-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+



-
+







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







}

/* =========================================================================
 * Copy the source state to the destination state.
 * To simplify the source, this is not supported for 16-bit MSDOS (which
 * doesn't have enough memory anyway to duplicate compression states).
 */
int ZEXPORT deflateCopy (dest, source)
int ZEXPORT deflateCopy(z_streamp dest, z_streamp source) {
    z_streamp dest;
    z_streamp source;
{
#ifdef MAXSEG_64K
    (void)dest;
    (void)source;
    return Z_STREAM_ERROR;
#else
    deflate_state *ds;
    deflate_state *ss;
    ushf *overlay;


    if (deflateStateCheck(source) || dest == Z_NULL) {
        return Z_STREAM_ERROR;
    }

    ss = source->state;

    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));

    ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
    if (ds == Z_NULL) return Z_MEM_ERROR;
    dest->state = (struct internal_state FAR *) ds;
    zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state));
    ds->strm = dest;

    ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
    ds->prev   = (Posf *)  ZALLOC(dest, ds->w_size, sizeof(Pos));
    ds->head   = (Posf *)  ZALLOC(dest, ds->hash_size, sizeof(Pos));
    overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
    ds->pending_buf = (uchf *) overlay;
    ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, LIT_BUFS);

    if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
        ds->pending_buf == Z_NULL) {
        deflateEnd (dest);
        return Z_MEM_ERROR;
    }
    /* following zmemcpy do not work for 16-bit MSDOS */
    zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
    zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
    zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
    zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
    zmemcpy(ds->pending_buf, ss->pending_buf, ds->lit_bufsize * LIT_BUFS);

    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
#ifdef LIT_MEM
    ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
    ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
    ds->d_buf = (ushf *)(ds->pending_buf + (ds->lit_bufsize << 1));
    ds->l_buf = ds->pending_buf + (ds->lit_bufsize << 2);
#else
    ds->sym_buf = ds->pending_buf + ds->lit_bufsize;
#endif

    ds->l_desc.dyn_tree = ds->dyn_ltree;
    ds->d_desc.dyn_tree = ds->dyn_dtree;
    ds->bl_desc.dyn_tree = ds->bl_tree;

    return Z_OK;
#endif /* MAXSEG_64K */
}

/* ===========================================================================
 * Read a new buffer from the current input stream, update the adler32
 * and total number of bytes read.  All deflate() input goes through
 * this function so some applications may wish to modify it to avoid
 * allocating a large strm->next_in buffer and copying from it.
 * (See also flush_pending()).
 */
local unsigned read_buf(strm, buf, size)
    z_streamp strm;
    Bytef *buf;
    unsigned size;
{
    unsigned len = strm->avail_in;

    if (len > size) len = size;
    if (len == 0) return 0;

    strm->avail_in  -= len;

    zmemcpy(buf, strm->next_in, len);
    if (strm->state->wrap == 1) {
        strm->adler = adler32(strm->adler, buf, len);
    }
#ifdef GZIP
    else if (strm->state->wrap == 2) {
        strm->adler = crc32(strm->adler, buf, len);
    }
#endif
    strm->next_in  += len;
    strm->total_in += len;

    return len;
}

/* ===========================================================================
 * Initialize the "longest match" routines for a new zlib stream
 */
local void lm_init (s)
    deflate_state *s;
{
    s->window_size = (ulg)2L*s->w_size;

    CLEAR_HASH(s);

    /* Set the default configuration parameters:
     */
    s->max_lazy_match   = configuration_table[s->level].max_lazy;
    s->good_match       = configuration_table[s->level].good_length;
    s->nice_match       = configuration_table[s->level].nice_length;
    s->max_chain_length = configuration_table[s->level].max_chain;

    s->strstart = 0;
    s->block_start = 0L;
    s->lookahead = 0;
    s->insert = 0;
    s->match_length = s->prev_length = MIN_MATCH-1;
    s->match_available = 0;
    s->ins_h = 0;
#ifndef FASTEST
#ifdef ASMV
    match_init(); /* initialize the asm code */
#endif
#endif
}

#ifndef FASTEST
/* ===========================================================================
 * Set match_start to the longest match starting at the given string and
 * return its length. Matches shorter or equal to prev_length are discarded,
 * in which case the result is equal to prev_length and match_start is
 * garbage.
 * IN assertions: cur_match is the head of the hash chain for the current
 *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
 * OUT assertion: the match length is not greater than s->lookahead.
 */
#ifndef ASMV
/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
 * match.S. The code will be functionally equivalent.
 */
local uInt longest_match(s, cur_match)
local uInt longest_match(deflate_state *s, IPos cur_match) {
    deflate_state *s;
    IPos cur_match;                             /* current match */
{
    unsigned chain_length = s->max_chain_length;/* max hash chain length */
    register Bytef *scan = s->window + s->strstart; /* current string */
    register Bytef *match;                      /* matched string */
    register int len;                           /* length of current match */
    int best_len = (int)s->prev_length;         /* best match length so far */
    int nice_match = s->nice_match;             /* stop if match long enough */
    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
        s->strstart - (IPos)MAX_DIST(s) : NIL;
    /* Stop when cur_match becomes <= limit. To simplify the code,
     * we prevent matches with the string of window index 0.
     */
    Posf *prev = s->prev;
    uInt wmask = s->w_mask;

#ifdef UNALIGNED_OK
    /* Compare two bytes at a time. Note: this is not always beneficial.
     * Try with and without -DUNALIGNED_OK to check.
     */
    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
    register ush scan_start = *(ushf*)scan;
    register ush scan_end   = *(ushf*)(scan+best_len-1);
    register ush scan_end   = *(ushf*)(scan + best_len - 1);
#else
    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
    register Byte scan_end1  = scan[best_len-1];
    register Byte scan_end1  = scan[best_len - 1];
    register Byte scan_end   = scan[best_len];
#endif

    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
     * It is easy to get rid of this optimization if necessary.
     */
    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");

    /* Do not waste too much time if we already have a good match: */
    if (s->prev_length >= s->good_match) {
        chain_length >>= 2;
    }
    /* Do not look for matches beyond the end of the input. This is necessary
     * to make deflate deterministic.
     */
    if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead;

    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
    Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
           "need lookahead");

    do {
        Assert(cur_match < s->strstart, "no future");
        match = s->window + cur_match;

        /* Skip to next match if the match length cannot increase
         * or if the match length is less than 2.  Note that the checks below
         * for insufficient lookahead only occur occasionally for performance
         * reasons.  Therefore uninitialized memory will be accessed, and
         * conditional jumps will be made that depend on those values.
         * However the length of the match is limited to the lookahead, so
         * the output of deflate is not affected by the uninitialized values.
         */
#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
        /* This code assumes sizeof(unsigned short) == 2. Do not use
         * UNALIGNED_OK if your compiler uses a different size.
         */
        if (*(ushf*)(match+best_len-1) != scan_end ||
        if (*(ushf*)(match + best_len - 1) != scan_end ||
            *(ushf*)match != scan_start) continue;

        /* It is not necessary to compare scan[2] and match[2] since they are
         * always equal when the other bytes match, given that the hash keys
         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
         * strstart+3, +5, ... up to strstart+257. We check for insufficient
         * strstart + 3, + 5, up to strstart + 257. We check for insufficient
         * lookahead only every 4th comparison; the 128th check will be made
         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
         * at strstart + 257. If MAX_MATCH-2 is not a multiple of 8, it is
         * necessary to put more guard bytes at the end of the window, or
         * to check more often for insufficient lookahead.
         */
        Assert(scan[2] == match[2], "scan[2]?");
        scan++, match++;
        do {
        } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
        } while (*(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
                 *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
                 *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
                 *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
                 scan < strend);
        /* The funny "do {}" generates better code on most compilers */

        /* Here, scan <= window+strstart+257 */
        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
        /* Here, scan <= window + strstart + 257 */
        Assert(scan <= s->window + (unsigned)(s->window_size - 1),
               "wild scan");
        if (*scan == *match) scan++;

        len = (MAX_MATCH - 1) - (int)(strend-scan);
        len = (MAX_MATCH - 1) - (int)(strend - scan);
        scan = strend - (MAX_MATCH-1);

#else /* UNALIGNED_OK */

        if (match[best_len]   != scan_end  ||
            match[best_len-1] != scan_end1 ||
            *match            != *scan     ||
            *++match          != scan[1])      continue;
        if (match[best_len]     != scan_end  ||
            match[best_len - 1] != scan_end1 ||
            *match              != *scan     ||
            *++match            != scan[1])      continue;

        /* The check at best_len-1 can be removed because it will be made
        /* The check at best_len - 1 can be removed because it will be made
         * again later. (This heuristic is not always a win.)
         * It is not necessary to compare scan[2] and match[2] since they
         * are always equal when the other bytes match, given that
         * the hash keys are equal and that HASH_BITS >= 8.
         */
        scan += 2, match++;
        Assert(*scan == *match, "match[2]?");

        /* We check for insufficient lookahead only every 8th comparison;
         * the 256th check will be made at strstart+258.
         * the 256th check will be made at strstart + 258.
         */
        do {
        } while (*++scan == *++match && *++scan == *++match &&
                 *++scan == *++match && *++scan == *++match &&
                 *++scan == *++match && *++scan == *++match &&
                 *++scan == *++match && *++scan == *++match &&
                 scan < strend);

        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
        Assert(scan <= s->window + (unsigned)(s->window_size - 1),
               "wild scan");

        len = MAX_MATCH - (int)(strend - scan);
        scan = strend - MAX_MATCH;

#endif /* UNALIGNED_OK */

        if (len > best_len) {
            s->match_start = cur_match;
            best_len = len;
            if (len >= nice_match) break;
#ifdef UNALIGNED_OK
            scan_end = *(ushf*)(scan+best_len-1);
            scan_end = *(ushf*)(scan + best_len - 1);
#else
            scan_end1  = scan[best_len-1];
            scan_end1  = scan[best_len - 1];
            scan_end   = scan[best_len];
#endif
        }
    } while ((cur_match = prev[cur_match & wmask]) > limit
             && --chain_length != 0);

    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
    return s->lookahead;
}
#endif /* ASMV */

#else /* FASTEST */

/* ---------------------------------------------------------------------------
 * Optimized version for FASTEST only
 */
local uInt longest_match(s, cur_match)
local uInt longest_match(deflate_state *s, IPos cur_match) {
    deflate_state *s;
    IPos cur_match;                             /* current match */
{
    register Bytef *scan = s->window + s->strstart; /* current string */
    register Bytef *match;                       /* matched string */
    register int len;                           /* length of current match */
    register Bytef *strend = s->window + s->strstart + MAX_MATCH;

    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
     * It is easy to get rid of this optimization if necessary.
     */
    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");

    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
    Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
           "need lookahead");

    Assert(cur_match < s->strstart, "no future");

    match = s->window + cur_match;

    /* Return failure if the match length is less than 2:
     */
    if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;

    /* The check at best_len-1 can be removed because it will be made
    /* The check at best_len - 1 can be removed because it will be made
     * again later. (This heuristic is not always a win.)
     * It is not necessary to compare scan[2] and match[2] since they
     * are always equal when the other bytes match, given that
     * the hash keys are equal and that HASH_BITS >= 8.
     */
    scan += 2, match += 2;
    Assert(*scan == *match, "match[2]?");

    /* We check for insufficient lookahead only every 8th comparison;
     * the 256th check will be made at strstart+258.
     * the 256th check will be made at strstart + 258.
     */
    do {
    } while (*++scan == *++match && *++scan == *++match &&
             *++scan == *++match && *++scan == *++match &&
             *++scan == *++match && *++scan == *++match &&
             *++scan == *++match && *++scan == *++match &&
             scan < strend);

    Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
    Assert(scan <= s->window + (unsigned)(s->window_size - 1), "wild scan");

    len = MAX_MATCH - (int)(strend - scan);

    if (len < MIN_MATCH) return MIN_MATCH - 1;

    s->match_start = cur_match;
    return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
}

#endif /* FASTEST */

#ifdef ZLIB_DEBUG

#define EQUAL 0
/* result of memcmp for equal strings */

/* ===========================================================================
 * Check that the match at match_start is indeed a match.
 */
local void check_match(s, start, match, length)
local void check_match(deflate_state *s, IPos start, IPos match, int length) {
    deflate_state *s;
    IPos start, match;
    int length;
{
    /* check that the match is indeed a match */
    if (zmemcmp(s->window + match,
                s->window + start, length) != EQUAL) {
        fprintf(stderr, " start %u, match %u, length %d\n",
                start, match, length);
    Bytef *back = s->window + (int)match, *here = s->window + start;
    IPos len = length;
    if (match == (IPos)-1) {
        /* match starts one byte before the current window -- just compare the
           subsequent length-1 bytes */
        back++;
        here++;
        len--;
    }
    if (zmemcmp(back, here, len) != EQUAL) {
        fprintf(stderr, " start %u, match %d, length %d\n",
                start, (int)match, length);
        do {
            fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
        } while (--length != 0);
            fprintf(stderr, "(%02x %02x)", *back++, *here++);
        } while (--len != 0);
        z_error("invalid match");
    }
    if (z_verbose > 1) {
        fprintf(stderr,"\\[%d,%d]", start-match, length);
        fprintf(stderr,"\\[%d,%d]", start - match, length);
        do { putc(s->window[start++], stderr); } while (--length != 0);
    }
}
#else
#  define check_match(s, start, match, length)
#endif /* ZLIB_DEBUG */

/* ===========================================================================
 * Fill the window when the lookahead becomes insufficient.
 * Updates strstart and lookahead.
 *
 * IN assertion: lookahead < MIN_LOOKAHEAD
 * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
 *    At least one byte has been read, or avail_in == 0; reads are
 *    performed for at least two bytes (required for the zip translate_eol
 *    option -- not supported here).
 */
local void fill_window(s)
    deflate_state *s;
{
    unsigned n;
    unsigned more;    /* Amount of free space at the end of the window. */
    uInt wsize = s->w_size;

    Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");

    do {
        more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);

        /* Deal with !@#$% 64K limit: */
        if (sizeof(int) <= 2) {
            if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
                more = wsize;

            } else if (more == (unsigned)(-1)) {
                /* Very unlikely, but possible on 16 bit machine if
                 * strstart == 0 && lookahead == 1 (input done a byte at time)
                 */
                more--;
            }
        }

        /* If the window is almost full and there is insufficient lookahead,
         * move the upper half to the lower one to make room in the upper half.
         */
        if (s->strstart >= wsize+MAX_DIST(s)) {

            zmemcpy(s->window, s->window+wsize, (unsigned)wsize - more);
            s->match_start -= wsize;
            s->strstart    -= wsize; /* we now have strstart >= MAX_DIST */
            s->block_start -= (long) wsize;
            slide_hash(s);
            more += wsize;
        }
        if (s->strm->avail_in == 0) break;

        /* If there was no sliding:
         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
         *    more == window_size - lookahead - strstart
         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
         * => more >= window_size - 2*WSIZE + 2
         * In the BIG_MEM or MMAP case (not yet supported),
         *   window_size == input_size + MIN_LOOKAHEAD  &&
         *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
         * Otherwise, window_size == 2*WSIZE so more >= 2.
         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
         */
        Assert(more >= 2, "more < 2");

        n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
        s->lookahead += n;

        /* Initialize the hash value now that we have some input: */
        if (s->lookahead + s->insert >= MIN_MATCH) {
            uInt str = s->strstart - s->insert;
            s->ins_h = s->window[str];
            UPDATE_HASH(s, s->ins_h, s->window[str + 1]);
#if MIN_MATCH != 3
            Call UPDATE_HASH() MIN_MATCH-3 more times
#endif
            while (s->insert) {
                UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
#ifndef FASTEST
                s->prev[str & s->w_mask] = s->head[s->ins_h];
#endif
                s->head[s->ins_h] = (Pos)str;
                str++;
                s->insert--;
                if (s->lookahead + s->insert < MIN_MATCH)
                    break;
            }
        }
        /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
         * but this is not important since only literal bytes will be emitted.
         */

    } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);

    /* If the WIN_INIT bytes after the end of the current data have never been
     * written, then zero those bytes in order to avoid memory check reports of
     * the use of uninitialized (or uninitialised as Julian writes) bytes by
     * the longest match routines.  Update the high water mark for the next
     * time through here.  WIN_INIT is set to MAX_MATCH since the longest match
     * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
     */
    if (s->high_water < s->window_size) {
        ulg curr = s->strstart + (ulg)(s->lookahead);
        ulg init;

        if (s->high_water < curr) {
            /* Previous high water mark below current data -- zero WIN_INIT
             * bytes or up to end of window, whichever is less.
             */
            init = s->window_size - curr;
            if (init > WIN_INIT)
                init = WIN_INIT;
            zmemzero(s->window + curr, (unsigned)init);
            s->high_water = curr + init;
        }
        else if (s->high_water < (ulg)curr + WIN_INIT) {
            /* High water mark at or above current data, but below current data
             * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
             * to end of window, whichever is less.
             */
            init = (ulg)curr + WIN_INIT - s->high_water;
            if (init > s->window_size - s->high_water)
                init = s->window_size - s->high_water;
            zmemzero(s->window + s->high_water, (unsigned)init);
            s->high_water += init;
        }
    }

    Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
           "not enough room for search");
}

/* ===========================================================================
 * Flush the current block, with given end-of-file flag.
 * IN assertion: strstart is set to the end of the current match.
 */
#define FLUSH_BLOCK_ONLY(s, last) { \
   _tr_flush_block(s, (s->block_start >= 0L ? \
                   (charf *)&s->window[(unsigned)s->block_start] : \
1634
1635
1636
1637
1638
1639
1640
1641

1642
1643

1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1618
1619
1620
1621
1622
1623
1624

1625
1626

1627



1628
1629
1630
1631
1632
1633
1634







-
+

-
+
-
-
-







 * of hash table slides to perform. If s->matches is 1, then one hash table
 * slide will be done when switching. If s->matches is 2, the maximum value
 * allowed here, then the hash table will be cleared, since two or more slides
 * is the same as a clear.
 *
 * deflate_stored() is written to minimize the number of times an input byte is
 * copied. It is most efficient with large input and output buffers, which
 * maximizes the opportunites to have a single copy from next_in to next_out.
 * maximizes the opportunities to have a single copy from next_in to next_out.
 */
local block_state deflate_stored(s, flush)
local block_state deflate_stored(deflate_state *s, int flush) {
    deflate_state *s;
    int flush;
{
    /* Smallest worthy block size when not flushing or finishing. By default
     * this is 32K. This can be as small as 507 bytes for memLevel == 1. For
     * large input and output buffers, the stored block size will be larger.
     */
    unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size);

    /* Copy as many min_block or larger stored blocks directly to next_out as
1738
1739
1740
1741
1742
1743
1744

1745
1746
1747
1748
1749
1750
1751
1752


1753
1754
1755

1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773

1774
1775
1776
1777
1778
1779
1780
1781


1782
1783
1784
1785
1786
1787

1788
1789
1790
1791
1792
1793
1794
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
1749
1750
1751
1752
1753
1754
1755
1756

1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781







+








+
+



+


-














-
+








+
+






+







        /* If any input was used, then no unused input remains in the window,
         * therefore s->block_start == s->strstart.
         */
        if (used >= s->w_size) {    /* supplant the previous history */
            s->matches = 2;         /* clear hash */
            zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size);
            s->strstart = s->w_size;
            s->insert = s->strstart;
        }
        else {
            if (s->window_size - s->strstart <= used) {
                /* Slide the window down. */
                s->strstart -= s->w_size;
                zmemcpy(s->window, s->window + s->w_size, s->strstart);
                if (s->matches < 2)
                    s->matches++;   /* add a pending slide_hash() */
                if (s->insert > s->strstart)
                    s->insert = s->strstart;
            }
            zmemcpy(s->window + s->strstart, s->strm->next_in - used, used);
            s->strstart += used;
            s->insert += MIN(used, s->w_size - s->insert);
        }
        s->block_start = s->strstart;
        s->insert += MIN(used, s->w_size - s->insert);
    }
    if (s->high_water < s->strstart)
        s->high_water = s->strstart;

    /* If the last block was written to next_out, then done. */
    if (last)
        return finish_done;

    /* If flushing and all input has been consumed, then done. */
    if (flush != Z_NO_FLUSH && flush != Z_FINISH &&
        s->strm->avail_in == 0 && (long)s->strstart == s->block_start)
        return block_done;

    /* Fill the window with any remaining input. */
    have = s->window_size - s->strstart - 1;
    have = s->window_size - s->strstart;
    if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) {
        /* Slide the window down. */
        s->block_start -= s->w_size;
        s->strstart -= s->w_size;
        zmemcpy(s->window, s->window + s->w_size, s->strstart);
        if (s->matches < 2)
            s->matches++;           /* add a pending slide_hash() */
        have += s->w_size;          /* more space now */
        if (s->insert > s->strstart)
            s->insert = s->strstart;
    }
    if (have > s->strm->avail_in)
        have = s->strm->avail_in;
    if (have) {
        read_buf(s->strm, s->window + s->strstart, have);
        s->strstart += have;
        s->insert += MIN(have, s->w_size - s->insert);
    }
    if (s->high_water < s->strstart)
        s->high_water = s->strstart;

    /* There was not enough avail_out to write a complete worthy or flushed
     * stored block to next_out. Write a stored block to pending instead, if we
     * have enough input for a worthy block, or if flushing and there is enough
1817
1818
1819
1820
1821
1822
1823
1824

1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845

1846
1847
1848
1849
1850
1851
1852
1804
1805
1806
1807
1808
1809
1810

1811



1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828

1829
1830
1831
1832
1833
1834
1835
1836







-
+
-
-
-

















-
+







/* ===========================================================================
 * Compress as much as possible from the input stream, return the current
 * block state.
 * This function does not perform lazy evaluation of matches and inserts
 * new strings in the dictionary only for unmatched strings or for short
 * matches. It is used only for the fast compression options.
 */
local block_state deflate_fast(s, flush)
local block_state deflate_fast(deflate_state *s, int flush) {
    deflate_state *s;
    int flush;
{
    IPos hash_head;       /* head of the hash chain */
    int bflush;           /* set if current block must be flushed */

    for (;;) {
        /* Make sure that we always have enough lookahead, except
         * at the end of the input file. We need MAX_MATCH bytes
         * for the next match, plus MIN_MATCH bytes to insert the
         * string following the next match.
         */
        if (s->lookahead < MIN_LOOKAHEAD) {
            fill_window(s);
            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
                return need_more;
            }
            if (s->lookahead == 0) break; /* flush the current block */
        }

        /* Insert the string window[strstart .. strstart+2] in the
        /* Insert the string window[strstart .. strstart + 2] in the
         * dictionary, and set hash_head to the head of the hash chain:
         */
        hash_head = NIL;
        if (s->lookahead >= MIN_MATCH) {
            INSERT_STRING(s, s->strstart, hash_head);
        }

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
1870
1871
1872
1873
1874
1875
1876

1877
1878
1879
1880
1881
1882
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







-
+










-
+










-
+










-
+
-
-
-


















-
+







                s->strstart++;
            } else
#endif
            {
                s->strstart += s->match_length;
                s->match_length = 0;
                s->ins_h = s->window[s->strstart];
                UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
                UPDATE_HASH(s, s->ins_h, s->window[s->strstart + 1]);
#if MIN_MATCH != 3
                Call UPDATE_HASH() MIN_MATCH-3 more times
#endif
                /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
                 * matter since it will be recomputed at next deflate call.
                 */
            }
        } else {
            /* No match, output a literal byte */
            Tracevv((stderr,"%c", s->window[s->strstart]));
            _tr_tally_lit (s, s->window[s->strstart], bflush);
            _tr_tally_lit(s, s->window[s->strstart], bflush);
            s->lookahead--;
            s->strstart++;
        }
        if (bflush) FLUSH_BLOCK(s, 0);
    }
    s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
    if (flush == Z_FINISH) {
        FLUSH_BLOCK(s, 1);
        return finish_done;
    }
    if (s->last_lit)
    if (s->sym_next)
        FLUSH_BLOCK(s, 0);
    return block_done;
}

#ifndef FASTEST
/* ===========================================================================
 * Same as above, but achieves better compression. We use a lazy
 * evaluation for matches: a match is finally adopted only if there is
 * no better match at the next window position.
 */
local block_state deflate_slow(s, flush)
local block_state deflate_slow(deflate_state *s, int flush) {
    deflate_state *s;
    int flush;
{
    IPos hash_head;          /* head of hash chain */
    int bflush;              /* set if current block must be flushed */

    /* Process the input block. */
    for (;;) {
        /* Make sure that we always have enough lookahead, except
         * at the end of the input file. We need MAX_MATCH bytes
         * for the next match, plus MIN_MATCH bytes to insert the
         * string following the next match.
         */
        if (s->lookahead < MIN_LOOKAHEAD) {
            fill_window(s);
            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
                return need_more;
            }
            if (s->lookahead == 0) break; /* flush the current block */
        }

        /* Insert the string window[strstart .. strstart+2] in the
        /* Insert the string window[strstart .. strstart + 2] in the
         * dictionary, and set hash_head to the head of the hash chain:
         */
        hash_head = NIL;
        if (s->lookahead >= MIN_MATCH) {
            INSERT_STRING(s, s->strstart, hash_head);
        }

1983
1984
1985
1986
1987
1988
1989
1990

1991
1992

1993
1994
1995
1996

1997
1998
1999
2000

2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019


2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038


2039
2040
2041
2042
2043
2044
2045
2046

2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057

2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
1964
1965
1966
1967
1968
1969
1970

1971
1972

1973
1974
1975
1976

1977
1978
1979
1980

1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998


1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017


2018
2019
2020
2021
2022
2023
2024
2025
2026

2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037

2038



2039
2040
2041
2042
2043
2044
2045







-
+

-
+



-
+



-
+

















-
-
+
+

















-
-
+
+







-
+










-
+
-
-
-







        /* If there was a match at the previous step and the current
         * match is not better, output the previous match:
         */
        if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
            uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
            /* Do not insert strings in hash table beyond this. */

            check_match(s, s->strstart-1, s->prev_match, s->prev_length);
            check_match(s, s->strstart - 1, s->prev_match, s->prev_length);

            _tr_tally_dist(s, s->strstart -1 - s->prev_match,
            _tr_tally_dist(s, s->strstart - 1 - s->prev_match,
                           s->prev_length - MIN_MATCH, bflush);

            /* Insert in hash table all strings up to the end of the match.
             * strstart-1 and strstart are already inserted. If there is not
             * strstart - 1 and strstart are already inserted. If there is not
             * enough lookahead, the last two strings are not inserted in
             * the hash table.
             */
            s->lookahead -= s->prev_length-1;
            s->lookahead -= s->prev_length - 1;
            s->prev_length -= 2;
            do {
                if (++s->strstart <= max_insert) {
                    INSERT_STRING(s, s->strstart, hash_head);
                }
            } while (--s->prev_length != 0);
            s->match_available = 0;
            s->match_length = MIN_MATCH-1;
            s->strstart++;

            if (bflush) FLUSH_BLOCK(s, 0);

        } else if (s->match_available) {
            /* If there was no match at the previous position, output a
             * single literal. If there was a match but the current match
             * is longer, truncate the previous match to a single literal.
             */
            Tracevv((stderr,"%c", s->window[s->strstart-1]));
            _tr_tally_lit(s, s->window[s->strstart-1], bflush);
            Tracevv((stderr,"%c", s->window[s->strstart - 1]));
            _tr_tally_lit(s, s->window[s->strstart - 1], bflush);
            if (bflush) {
                FLUSH_BLOCK_ONLY(s, 0);
            }
            s->strstart++;
            s->lookahead--;
            if (s->strm->avail_out == 0) return need_more;
        } else {
            /* There is no previous match to compare with, wait for
             * the next step to decide.
             */
            s->match_available = 1;
            s->strstart++;
            s->lookahead--;
        }
    }
    Assert (flush != Z_NO_FLUSH, "no flush?");
    if (s->match_available) {
        Tracevv((stderr,"%c", s->window[s->strstart-1]));
        _tr_tally_lit(s, s->window[s->strstart-1], bflush);
        Tracevv((stderr,"%c", s->window[s->strstart - 1]));
        _tr_tally_lit(s, s->window[s->strstart - 1], bflush);
        s->match_available = 0;
    }
    s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
    if (flush == Z_FINISH) {
        FLUSH_BLOCK(s, 1);
        return finish_done;
    }
    if (s->last_lit)
    if (s->sym_next)
        FLUSH_BLOCK(s, 0);
    return block_done;
}
#endif /* FASTEST */

/* ===========================================================================
 * For Z_RLE, simply look for runs of bytes, generate matches only of distance
 * one.  Do not maintain a hash table.  (It will be regenerated if this run of
 * deflate switches away from Z_RLE.)
 */
local block_state deflate_rle(s, flush)
local block_state deflate_rle(deflate_state *s, int flush) {
    deflate_state *s;
    int flush;
{
    int bflush;             /* set if current block must be flushed */
    uInt prev;              /* byte at distance one to match */
    Bytef *scan, *strend;   /* scan goes up to strend for length of run */

    for (;;) {
        /* Make sure that we always have enough lookahead, except
         * at the end of the input file. We need MAX_MATCH bytes
2088
2089
2090
2091
2092
2093
2094
2095


2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110

2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121

2122
2123
2124
2125
2126
2127
2128
2129
2130

2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150

2151
2152
2153
2154
2155
2156
2157
2158
2159
2160

2161
2162
2163
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
2095
2096
2097
2098
2099

2100
2101
2102
2103
2104
2105
2106
2107
2108

2109



2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125

2126
2127
2128
2129
2130
2131
2132
2133
2134
2135

2136
2137
2138
2139







-
+
+














-
+










-
+








-
+
-
-
-
















-
+









-
+



                         prev == *++scan && prev == *++scan &&
                         prev == *++scan && prev == *++scan &&
                         scan < strend);
                s->match_length = MAX_MATCH - (uInt)(strend - scan);
                if (s->match_length > s->lookahead)
                    s->match_length = s->lookahead;
            }
            Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan");
            Assert(scan <= s->window + (uInt)(s->window_size - 1),
                   "wild scan");
        }

        /* Emit match if have run of MIN_MATCH or longer, else emit literal */
        if (s->match_length >= MIN_MATCH) {
            check_match(s, s->strstart, s->strstart - 1, s->match_length);

            _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush);

            s->lookahead -= s->match_length;
            s->strstart += s->match_length;
            s->match_length = 0;
        } else {
            /* No match, output a literal byte */
            Tracevv((stderr,"%c", s->window[s->strstart]));
            _tr_tally_lit (s, s->window[s->strstart], bflush);
            _tr_tally_lit(s, s->window[s->strstart], bflush);
            s->lookahead--;
            s->strstart++;
        }
        if (bflush) FLUSH_BLOCK(s, 0);
    }
    s->insert = 0;
    if (flush == Z_FINISH) {
        FLUSH_BLOCK(s, 1);
        return finish_done;
    }
    if (s->last_lit)
    if (s->sym_next)
        FLUSH_BLOCK(s, 0);
    return block_done;
}

/* ===========================================================================
 * For Z_HUFFMAN_ONLY, do not look for matches.  Do not maintain a hash table.
 * (It will be regenerated if this run of deflate switches away from Huffman.)
 */
local block_state deflate_huff(s, flush)
local block_state deflate_huff(deflate_state *s, int flush) {
    deflate_state *s;
    int flush;
{
    int bflush;             /* set if current block must be flushed */

    for (;;) {
        /* Make sure that we have a literal to write. */
        if (s->lookahead == 0) {
            fill_window(s);
            if (s->lookahead == 0) {
                if (flush == Z_NO_FLUSH)
                    return need_more;
                break;      /* flush the current block */
            }
        }

        /* Output a literal byte */
        s->match_length = 0;
        Tracevv((stderr,"%c", s->window[s->strstart]));
        _tr_tally_lit (s, s->window[s->strstart], bflush);
        _tr_tally_lit(s, s->window[s->strstart], bflush);
        s->lookahead--;
        s->strstart++;
        if (bflush) FLUSH_BLOCK(s, 0);
    }
    s->insert = 0;
    if (flush == Z_FINISH) {
        FLUSH_BLOCK(s, 1);
        return finish_done;
    }
    if (s->last_lit)
    if (s->sym_next)
        FLUSH_BLOCK(s, 0);
    return block_done;
}

Changes to compat/zlib/deflate.h.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/* deflate.h -- internal compression state
 * Copyright (C) 1995-2016 Jean-loup Gailly
 * Copyright (C) 1995-2024 Jean-loup Gailly
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/* WARNING: this file should *not* be used by applications. It is
   part of the implementation of the compression library and is
   subject to change. Applications should only use zlib.h.
 */
18
19
20
21
22
23
24




25
26
27
28
29
30
31
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35







+
+
+
+







/* define NO_GZIP when compiling if you want to disable gzip header and
   trailer creation by deflate().  NO_GZIP would be used to avoid linking in
   the crc code when it is not needed.  For shared libraries, gzip encoding
   should be left enabled. */
#ifndef NO_GZIP
#  define GZIP
#endif

/* define LIT_MEM to slightly increase the speed of deflate (order 1% to 2%) at
   the cost of a larger memory footprint */
/* #define LIT_MEM */

/* ===========================================================================
 * Internal compression state.
 */

#define LENGTH_CODES 29
/* number of length codes, not counting the special END_BLOCK code */
213
214
215
216
217
218
219



220





221
222
223
224
225
226
227
217
218
219
220
221
222
223
224
225
226

227
228
229
230
231
232
233
234
235
236
237
238







+
+
+
-
+
+
+
+
+







     * The same heap array is used to build all trees.
     */

    uch depth[2*L_CODES+1];
    /* Depth of each subtree used as tie breaker for trees of equal frequency
     */

#ifdef LIT_MEM
#   define LIT_BUFS 5
    ushf *d_buf;          /* buffer for distances */
    uchf *l_buf;          /* buffer for literals or lengths */
    uchf *l_buf;          /* buffer for literals/lengths */
#else
#   define LIT_BUFS 4
    uchf *sym_buf;        /* buffer for distances and literals/lengths */
#endif

    uInt  lit_bufsize;
    /* Size of match buffer for literals/lengths.  There are 4 reasons for
     * limiting lit_bufsize to 64K:
     *   - frequencies can be kept in 16 bit counters
     *   - if compression is not successful for the first block, all input
     *     data is still in the window so we can still emit a stored block even
235
236
237
238
239
240
241
242
243


244
245
246
247
248
249
250
251
252
253
254
255
246
247
248
249
250
251
252


253
254





255
256
257
258
259
260
261







-
-
+
+
-
-
-
-
-







     *     example a binary file with poorly compressible code followed by
     *     a highly compressible string table.) Smaller buffer sizes give
     *     fast adaptation but have of course the overhead of transmitting
     *     trees more frequently.
     *   - I can't count above 4
     */

    uInt last_lit;      /* running index in l_buf */

    uInt sym_next;      /* running index in symbol buffer */
    uInt sym_end;       /* symbol table full when sym_next reaches this */
    ushf *d_buf;
    /* Buffer for distances. To simplify the code, d_buf and l_buf have
     * the same number of elements. To use different lengths, an extra flag
     * array would be necessary.
     */

    ulg opt_len;        /* bit length of current block with optimal trees */
    ulg static_len;     /* bit length of current block with static trees */
    uInt matches;       /* number of string matches in current block */
    uInt insert;        /* bytes at end of window left to insert */

#ifdef ZLIB_DEBUG
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
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
366
367

368
369
370
371
372
373
374
375
376
377







-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+



















+


-
-
+
+

-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
+
+
+



-
+

+







 */

#define WIN_INIT MAX_MATCH
/* Number of bytes after end of data in window to initialize in order to avoid
   memory checker errors from longest match routines */

        /* in trees.c */
void ZLIB_INTERNAL _tr_init OF((deflate_state *s));
int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,
                        ulg stored_len, int last));
void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s));
void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
                        ulg stored_len, int last));
void ZLIB_INTERNAL _tr_init(deflate_state *s);
int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc);
void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf,
                                   ulg stored_len, int last);
void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s);
void ZLIB_INTERNAL _tr_align(deflate_state *s);
void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf,
                                    ulg stored_len, int last);

#define d_code(dist) \
   ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
/* Mapping from a distance to a distance code. dist is the distance - 1 and
 * must not have side effects. _dist_code[256] and _dist_code[257] are never
 * used.
 */

#ifndef ZLIB_DEBUG
/* Inline versions of _tr_tally for speed: */

#if defined(GEN_TREES_H) || !defined(STDC)
  extern uch ZLIB_INTERNAL _length_code[];
  extern uch ZLIB_INTERNAL _dist_code[];
#else
  extern const uch ZLIB_INTERNAL _length_code[];
  extern const uch ZLIB_INTERNAL _dist_code[];
#endif

#ifdef LIT_MEM
# define _tr_tally_lit(s, c, flush) \
  { uch cc = (c); \
    s->d_buf[s->last_lit] = 0; \
    s->l_buf[s->last_lit++] = cc; \
    s->d_buf[s->sym_next] = 0; \
    s->l_buf[s->sym_next++] = cc; \
    s->dyn_ltree[cc].Freq++; \
    flush = (s->last_lit == s->lit_bufsize-1); \
    flush = (s->sym_next == s->sym_end); \
   }
# define _tr_tally_dist(s, distance, length, flush) \
  { uch len = (uch)(length); \
    ush dist = (ush)(distance); \
    s->d_buf[s->sym_next] = dist; \
    s->l_buf[s->sym_next++] = len; \
    dist--; \
    s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
    s->dyn_dtree[d_code(dist)].Freq++; \
    flush = (s->sym_next == s->sym_end); \
  }
#else
# define _tr_tally_lit(s, c, flush) \
  { uch cc = (c); \
    s->sym_buf[s->sym_next++] = 0; \
    s->sym_buf[s->sym_next++] = 0; \
    s->sym_buf[s->sym_next++] = cc; \
    s->dyn_ltree[cc].Freq++; \
    flush = (s->sym_next == s->sym_end); \
   }
# define _tr_tally_dist(s, distance, length, flush) \
  { uch len = (uch)(length); \
    ush dist = (ush)(distance); \
    s->d_buf[s->last_lit] = dist; \
    s->l_buf[s->last_lit++] = len; \
    s->sym_buf[s->sym_next++] = (uch)dist; \
    s->sym_buf[s->sym_next++] = (uch)(dist >> 8); \
    s->sym_buf[s->sym_next++] = len; \
    dist--; \
    s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
    s->dyn_dtree[d_code(dist)].Freq++; \
    flush = (s->last_lit == s->lit_bufsize-1); \
    flush = (s->sym_next == s->sym_end); \
  }
#endif
#else
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
# define _tr_tally_dist(s, distance, length, flush) \
              flush = _tr_tally(s, distance, length)
#endif

#endif /* DEFLATE_H */

Added compat/zlib/doc/algorithm.txt.


















































































































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
1. Compression algorithm (deflate)

The deflation algorithm used by gzip (also zip and zlib) is a variation of
LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in
the input data.  The second occurrence of a string is replaced by a
pointer to the previous string, in the form of a pair (distance,
length).  Distances are limited to 32K bytes, and lengths are limited
to 258 bytes. When a string does not occur anywhere in the previous
32K bytes, it is emitted as a sequence of literal bytes.  (In this
description, `string' must be taken as an arbitrary sequence of bytes,
and is not restricted to printable characters.)

Literals or match lengths are compressed with one Huffman tree, and
match distances are compressed with another tree. The trees are stored
in a compact form at the start of each block. The blocks can have any
size (except that the compressed data for one block must fit in
available memory). A block is terminated when deflate() determines that
it would be useful to start another block with fresh trees. (This is
somewhat similar to the behavior of LZW-based _compress_.)

Duplicated strings are found using a hash table. All input strings of
length 3 are inserted in the hash table. A hash index is computed for
the next 3 bytes. If the hash chain for this index is not empty, all
strings in the chain are compared with the current input string, and
the longest match is selected.

The hash chains are searched starting with the most recent strings, to
favor small distances and thus take advantage of the Huffman encoding.
The hash chains are singly linked. There are no deletions from the
hash chains, the algorithm simply discards matches that are too old.

To avoid a worst-case situation, very long hash chains are arbitrarily
truncated at a certain length, determined by a runtime option (level
parameter of deflateInit). So deflate() does not always find the longest
possible match but generally finds a match which is long enough.

deflate() also defers the selection of matches with a lazy evaluation
mechanism. After a match of length N has been found, deflate() searches for
a longer match at the next input byte. If a longer match is found, the
previous match is truncated to a length of one (thus producing a single
literal byte) and the process of lazy evaluation begins again. Otherwise,
the original match is kept, and the next match search is attempted only N
steps later.

The lazy match evaluation is also subject to a runtime parameter. If
the current match is long enough, deflate() reduces the search for a longer
match, thus speeding up the whole process. If compression ratio is more
important than speed, deflate() attempts a complete second search even if
the first match is already long enough.

The lazy match evaluation is not performed for the fastest compression
modes (level parameter 1 to 3). For these fast modes, new strings
are inserted in the hash table only when no match was found, or
when the match is not too long. This degrades the compression ratio
but saves time since there are both fewer insertions and fewer searches.


2. Decompression algorithm (inflate)

2.1 Introduction

The key question is how to represent a Huffman code (or any prefix code) so
that you can decode fast.  The most important characteristic is that shorter
codes are much more common than longer codes, so pay attention to decoding the
short codes fast, and let the long codes take longer to decode.

inflate() sets up a first level table that covers some number of bits of
input less than the length of longest code.  It gets that many bits from the
stream, and looks it up in the table.  The table will tell if the next
code is that many bits or less and how many, and if it is, it will tell
the value, else it will point to the next level table for which inflate()
grabs more bits and tries to decode a longer code.

How many bits to make the first lookup is a tradeoff between the time it
takes to decode and the time it takes to build the table.  If building the
table took no time (and if you had infinite memory), then there would only
be a first level table to cover all the way to the longest code.  However,
building the table ends up taking a lot longer for more bits since short
codes are replicated many times in such a table.  What inflate() does is
simply to make the number of bits in the first table a variable, and then
to set that variable for the maximum speed.

For inflate, which has 286 possible codes for the literal/length tree, the size
of the first table is nine bits.  Also the distance trees have 30 possible
values, and the size of the first table is six bits.  Note that for each of
those cases, the table ended up one bit longer than the ``average'' code
length, i.e. the code length of an approximately flat code which would be a
little more than eight bits for 286 symbols and a little less than five bits
for 30 symbols.


2.2 More details on the inflate table lookup

Ok, you want to know what this cleverly obfuscated inflate tree actually
looks like.  You are correct that it's not a Huffman tree.  It is simply a
lookup table for the first, let's say, nine bits of a Huffman symbol.  The
symbol could be as short as one bit or as long as 15 bits.  If a particular
symbol is shorter than nine bits, then that symbol's translation is duplicated
in all those entries that start with that symbol's bits.  For example, if the
symbol is four bits, then it's duplicated 32 times in a nine-bit table.  If a
symbol is nine bits long, it appears in the table once.

If the symbol is longer than nine bits, then that entry in the table points
to another similar table for the remaining bits.  Again, there are duplicated
entries as needed.  The idea is that most of the time the symbol will be short
and there will only be one table look up.  (That's whole idea behind data
compression in the first place.)  For the less frequent long symbols, there
will be two lookups.  If you had a compression method with really long
symbols, you could have as many levels of lookups as is efficient.  For
inflate, two is enough.

So a table entry either points to another table (in which case nine bits in
the above example are gobbled), or it contains the translation for the symbol
and the number of bits to gobble.  Then you start again with the next
ungobbled bit.

You may wonder: why not just have one lookup table for how ever many bits the
longest symbol is?  The reason is that if you do that, you end up spending
more time filling in duplicate symbol entries than you do actually decoding.
At least for deflate's output that generates new trees every several 10's of
kbytes.  You can imagine that filling in a 2^15 entry table for a 15-bit code
would take too long if you're only decoding several thousand symbols.  At the
other extreme, you could make a new table for every bit in the code.  In fact,
that's essentially a Huffman tree.  But then you spend too much time
traversing the tree while decoding, even for short symbols.

So the number of bits for the first lookup table is a trade of the time to
fill out the table vs. the time spent looking at the second level and above of
the table.

Here is an example, scaled down:

The code being decoded, with 10 symbols, from 1 to 6 bits long:

A: 0
B: 10
C: 1100
D: 11010
E: 11011
F: 11100
G: 11101
H: 11110
I: 111110
J: 111111

Let's make the first table three bits long (eight entries):

000: A,1
001: A,1
010: A,1
011: A,1
100: B,2
101: B,2
110: -> table X (gobble 3 bits)
111: -> table Y (gobble 3 bits)

Each entry is what the bits decode as and how many bits that is, i.e. how
many bits to gobble.  Or the entry points to another table, with the number of
bits to gobble implicit in the size of the table.

Table X is two bits long since the longest code starting with 110 is five bits
long:

00: C,1
01: C,1
10: D,2
11: E,2

Table Y is three bits long since the longest code starting with 111 is six
bits long:

000: F,2
001: F,2
010: G,2
011: G,2
100: H,2
101: H,2
110: I,3
111: J,3

So what we have here are three tables with a total of 20 entries that had to
be constructed.  That's compared to 64 entries for a single table.  Or
compared to 16 entries for a Huffman tree (six two entry tables and one four
entry table).  Assuming that the code ideally represents the probability of
the symbols, it takes on the average 1.25 lookups per symbol.  That's compared
to one lookup for the single table, or 1.66 lookups per symbol for the
Huffman tree.

There, I think that gives you a picture of what's going on.  For inflate, the
meaning of a particular symbol is often more than just a letter.  It can be a
byte (a "literal"), or it can be either a length or a distance which
indicates a base value and a number of bits to fetch after the code that is
added to the base value.  Or it might be the special end-of-block code.  The
data structures created in inftrees.c try to encode all that information
compactly in the tables.


Jean-loup Gailly        Mark Adler
jloup@gzip.org          madler@alumni.caltech.edu


References:

[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data
Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3,
pp. 337-343.

``DEFLATE Compressed Data Format Specification'' available in
http://tools.ietf.org/html/rfc1951

Added compat/zlib/doc/crc-doc.1.0.pdf.

cannot compute difference between binary files

Added compat/zlib/doc/rfc1950.txt.












































































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






Network Working Group                                         P. Deutsch
Request for Comments: 1950                           Aladdin Enterprises
Category: Informational                                      J-L. Gailly
                                                                Info-ZIP
                                                                May 1996


         ZLIB Compressed Data Format Specification version 3.3

Status of This Memo

   This memo provides information for the Internet community.  This memo
   does not specify an Internet standard of any kind.  Distribution of
   this memo is unlimited.

IESG Note:

   The IESG takes no position on the validity of any Intellectual
   Property Rights statements contained in this document.

Notices

   Copyright (c) 1996 L. Peter Deutsch and Jean-Loup Gailly

   Permission is granted to copy and distribute this document for any
   purpose and without charge, including translations into other
   languages and incorporation into compilations, provided that the
   copyright notice and this notice are preserved, and that any
   substantive changes or deletions from the original are clearly
   marked.

   A pointer to the latest version of this and related documentation in
   HTML format can be found at the URL
   <ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>.

Abstract

   This specification defines a lossless compressed data format.  The
   data can be produced or consumed, even for an arbitrarily long
   sequentially presented input data stream, using only an a priori
   bounded amount of intermediate storage.  The format presently uses
   the DEFLATE compression method but can be easily extended to use
   other compression methods.  It can be implemented readily in a manner
   not covered by patents.  This specification also defines the ADLER-32
   checksum (an extension and improvement of the Fletcher checksum),
   used for detection of data corruption, and provides an algorithm for
   computing it.




Deutsch & Gailly             Informational                      [Page 1]

RFC 1950       ZLIB Compressed Data Format Specification        May 1996


Table of Contents

   1. Introduction ................................................... 2
      1.1. Purpose ................................................... 2
      1.2. Intended audience ......................................... 3
      1.3. Scope ..................................................... 3
      1.4. Compliance ................................................ 3
      1.5.  Definitions of terms and conventions used ................ 3
      1.6. Changes from previous versions ............................ 3
   2. Detailed specification ......................................... 3
      2.1. Overall conventions ....................................... 3
      2.2. Data format ............................................... 4
      2.3. Compliance ................................................ 7
   3. References ..................................................... 7
   4. Source code .................................................... 8
   5. Security Considerations ........................................ 8
   6. Acknowledgements ............................................... 8
   7. Authors' Addresses ............................................. 8
   8. Appendix: Rationale ............................................ 9
   9. Appendix: Sample code ..........................................10

1. Introduction

   1.1. Purpose

      The purpose of this specification is to define a lossless
      compressed data format that:

          * Is independent of CPU type, operating system, file system,
            and character set, and hence can be used for interchange;

          * Can be produced or consumed, even for an arbitrarily long
            sequentially presented input data stream, using only an a
            priori bounded amount of intermediate storage, and hence can
            be used in data communications or similar structures such as
            Unix filters;

          * Can use a number of different compression methods;

          * Can be implemented readily in a manner not covered by
            patents, and hence can be practiced freely.

      The data format defined by this specification does not attempt to
      allow random access to compressed data.







Deutsch & Gailly             Informational                      [Page 2]

RFC 1950       ZLIB Compressed Data Format Specification        May 1996


   1.2. Intended audience

      This specification is intended for use by implementors of software
      to compress data into zlib format and/or decompress data from zlib
      format.

      The text of the specification assumes a basic background in
      programming at the level of bits and other primitive data
      representations.

   1.3. Scope

      The specification specifies a compressed data format that can be
      used for in-memory compression of a sequence of arbitrary bytes.

   1.4. Compliance

      Unless otherwise indicated below, a compliant decompressor must be
      able to accept and decompress any data set that conforms to all
      the specifications presented here; a compliant compressor must
      produce data sets that conform to all the specifications presented
      here.

   1.5.  Definitions of terms and conventions used

      byte: 8 bits stored or transmitted as a unit (same as an octet).
      (For this specification, a byte is exactly 8 bits, even on
      machines which store a character on a number of bits different
      from 8.) See below, for the numbering of bits within a byte.

   1.6. Changes from previous versions

      Version 3.1 was the first public release of this specification.
      In version 3.2, some terminology was changed and the Adler-32
      sample code was rewritten for clarity.  In version 3.3, the
      support for a preset dictionary was introduced, and the
      specification was converted to RFC style.

2. Detailed specification

   2.1. Overall conventions

      In the diagrams below, a box like this:

         +---+
         |   | <-- the vertical bars might be missing
         +---+




Deutsch & Gailly             Informational                      [Page 3]

RFC 1950       ZLIB Compressed Data Format Specification        May 1996


      represents one byte; a box like this:

         +==============+
         |              |
         +==============+

      represents a variable number of bytes.

      Bytes stored within a computer do not have a "bit order", since
      they are always treated as a unit.  However, a byte considered as
      an integer between 0 and 255 does have a most- and least-
      significant bit, and since we write numbers with the most-
      significant digit on the left, we also write bytes with the most-
      significant bit on the left.  In the diagrams below, we number the
      bits of a byte so that bit 0 is the least-significant bit, i.e.,
      the bits are numbered:

         +--------+
         |76543210|
         +--------+

      Within a computer, a number may occupy multiple bytes.  All
      multi-byte numbers in the format described here are stored with
      the MOST-significant byte first (at the lower memory address).
      For example, the decimal number 520 is stored as:

             0     1
         +--------+--------+
         |00000010|00001000|
         +--------+--------+
          ^        ^
          |        |
          |        + less significant byte = 8
          + more significant byte = 2 x 256

   2.2. Data format

      A zlib stream has the following structure:

           0   1
         +---+---+
         |CMF|FLG|   (more-->)
         +---+---+








Deutsch & Gailly             Informational                      [Page 4]

RFC 1950       ZLIB Compressed Data Format Specification        May 1996


      (if FLG.FDICT set)

           0   1   2   3
         +---+---+---+---+
         |     DICTID    |   (more-->)
         +---+---+---+---+

         +=====================+---+---+---+---+
         |...compressed data...|    ADLER32    |
         +=====================+---+---+---+---+

      Any data which may appear after ADLER32 are not part of the zlib
      stream.

      CMF (Compression Method and flags)
         This byte is divided into a 4-bit compression method and a 4-
         bit information field depending on the compression method.

            bits 0 to 3  CM     Compression method
            bits 4 to 7  CINFO  Compression info

      CM (Compression method)
         This identifies the compression method used in the file. CM = 8
         denotes the "deflate" compression method with a window size up
         to 32K.  This is the method used by gzip and PNG (see
         references [1] and [2] in Chapter 3, below, for the reference
         documents).  CM = 15 is reserved.  It might be used in a future
         version of this specification to indicate the presence of an
         extra field before the compressed data.

      CINFO (Compression info)
         For CM = 8, CINFO is the base-2 logarithm of the LZ77 window
         size, minus eight (CINFO=7 indicates a 32K window size). Values
         of CINFO above 7 are not allowed in this version of the
         specification.  CINFO is not defined in this specification for
         CM not equal to 8.

      FLG (FLaGs)
         This flag byte is divided as follows:

            bits 0 to 4  FCHECK  (check bits for CMF and FLG)
            bit  5       FDICT   (preset dictionary)
            bits 6 to 7  FLEVEL  (compression level)

         The FCHECK value must be such that CMF and FLG, when viewed as
         a 16-bit unsigned integer stored in MSB order (CMF*256 + FLG),
         is a multiple of 31.




Deutsch & Gailly             Informational                      [Page 5]

RFC 1950       ZLIB Compressed Data Format Specification        May 1996


      FDICT (Preset dictionary)
         If FDICT is set, a DICT dictionary identifier is present
         immediately after the FLG byte. The dictionary is a sequence of
         bytes which are initially fed to the compressor without
         producing any compressed output. DICT is the Adler-32 checksum
         of this sequence of bytes (see the definition of ADLER32
         below).  The decompressor can use this identifier to determine
         which dictionary has been used by the compressor.

      FLEVEL (Compression level)
         These flags are available for use by specific compression
         methods.  The "deflate" method (CM = 8) sets these flags as
         follows:

            0 - compressor used fastest algorithm
            1 - compressor used fast algorithm
            2 - compressor used default algorithm
            3 - compressor used maximum compression, slowest algorithm

         The information in FLEVEL is not needed for decompression; it
         is there to indicate if recompression might be worthwhile.

      compressed data
         For compression method 8, the compressed data is stored in the
         deflate compressed data format as described in the document
         "DEFLATE Compressed Data Format Specification" by L. Peter
         Deutsch. (See reference [3] in Chapter 3, below)

         Other compressed data formats are not specified in this version
         of the zlib specification.

      ADLER32 (Adler-32 checksum)
         This contains a checksum value of the uncompressed data
         (excluding any dictionary data) computed according to Adler-32
         algorithm. This algorithm is a 32-bit extension and improvement
         of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073
         standard. See references [4] and [5] in Chapter 3, below)

         Adler-32 is composed of two sums accumulated per byte: s1 is
         the sum of all bytes, s2 is the sum of all s1 values. Both sums
         are done modulo 65521. s1 is initialized to 1, s2 to zero.  The
         Adler-32 checksum is stored as s2*65536 + s1 in most-
         significant-byte first (network) order.








Deutsch & Gailly             Informational                      [Page 6]

RFC 1950       ZLIB Compressed Data Format Specification        May 1996


   2.3. Compliance

      A compliant compressor must produce streams with correct CMF, FLG
      and ADLER32, but need not support preset dictionaries.  When the
      zlib data format is used as part of another standard data format,
      the compressor may use only preset dictionaries that are specified
      by this other data format.  If this other format does not use the
      preset dictionary feature, the compressor must not set the FDICT
      flag.

      A compliant decompressor must check CMF, FLG, and ADLER32, and
      provide an error indication if any of these have incorrect values.
      A compliant decompressor must give an error indication if CM is
      not one of the values defined in this specification (only the
      value 8 is permitted in this version), since another value could
      indicate the presence of new features that would cause subsequent
      data to be interpreted incorrectly.  A compliant decompressor must
      give an error indication if FDICT is set and DICTID is not the
      identifier of a known preset dictionary.  A decompressor may
      ignore FLEVEL and still be compliant.  When the zlib data format
      is being used as a part of another standard format, a compliant
      decompressor must support all the preset dictionaries specified by
      the other format. When the other format does not use the preset
      dictionary feature, a compliant decompressor must reject any
      stream in which the FDICT flag is set.

3. References

   [1] Deutsch, L.P.,"GZIP Compressed Data Format Specification",
       available in ftp://ftp.uu.net/pub/archiving/zip/doc/

   [2] Thomas Boutell, "PNG (Portable Network Graphics) specification",
       available in ftp://ftp.uu.net/graphics/png/documents/

   [3] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification",
       available in ftp://ftp.uu.net/pub/archiving/zip/doc/

   [4] Fletcher, J. G., "An Arithmetic Checksum for Serial
       Transmissions," IEEE Transactions on Communications, Vol. COM-30,
       No. 1, January 1982, pp. 247-252.

   [5] ITU-T Recommendation X.224, Annex D, "Checksum Algorithms,"
       November, 1993, pp. 144, 145. (Available from
       gopher://info.itu.ch). ITU-T X.244 is also the same as ISO 8073.







Deutsch & Gailly             Informational                      [Page 7]

RFC 1950       ZLIB Compressed Data Format Specification        May 1996


4. Source code

   Source code for a C language implementation of a "zlib" compliant
   library is available at ftp://ftp.uu.net/pub/archiving/zip/zlib/.

5. Security Considerations

   A decoder that fails to check the ADLER32 checksum value may be
   subject to undetected data corruption.

6. Acknowledgements

   Trademarks cited in this document are the property of their
   respective owners.

   Jean-Loup Gailly and Mark Adler designed the zlib format and wrote
   the related software described in this specification.  Glenn
   Randers-Pehrson converted this document to RFC and HTML format.

7. Authors' Addresses

   L. Peter Deutsch
   Aladdin Enterprises
   203 Santa Margarita Ave.
   Menlo Park, CA 94025

   Phone: (415) 322-0103 (AM only)
   FAX:   (415) 322-1734
   EMail: <ghost@aladdin.com>


   Jean-Loup Gailly

   EMail: <gzip@prep.ai.mit.edu>

   Questions about the technical content of this specification can be
   sent by email to

   Jean-Loup Gailly <gzip@prep.ai.mit.edu> and
   Mark Adler <madler@alumni.caltech.edu>

   Editorial comments on this specification can be sent by email to

   L. Peter Deutsch <ghost@aladdin.com> and
   Glenn Randers-Pehrson <randeg@alumni.rpi.edu>






Deutsch & Gailly             Informational                      [Page 8]

RFC 1950       ZLIB Compressed Data Format Specification        May 1996


8. Appendix: Rationale

   8.1. Preset dictionaries

      A preset dictionary is specially useful to compress short input
      sequences. The compressor can take advantage of the dictionary
      context to encode the input in a more compact manner. The
      decompressor can be initialized with the appropriate context by
      virtually decompressing a compressed version of the dictionary
      without producing any output. However for certain compression
      algorithms such as the deflate algorithm this operation can be
      achieved without actually performing any decompression.

      The compressor and the decompressor must use exactly the same
      dictionary. The dictionary may be fixed or may be chosen among a
      certain number of predefined dictionaries, according to the kind
      of input data. The decompressor can determine which dictionary has
      been chosen by the compressor by checking the dictionary
      identifier. This document does not specify the contents of
      predefined dictionaries, since the optimal dictionaries are
      application specific. Standard data formats using this feature of
      the zlib specification must precisely define the allowed
      dictionaries.

   8.2. The Adler-32 algorithm

      The Adler-32 algorithm is much faster than the CRC32 algorithm yet
      still provides an extremely low probability of undetected errors.

      The modulo on unsigned long accumulators can be delayed for 5552
      bytes, so the modulo operation time is negligible.  If the bytes
      are a, b, c, the second sum is 3a + 2b + c + 3, and so is position
      and order sensitive, unlike the first sum, which is just a
      checksum.  That 65521 is prime is important to avoid a possible
      large class of two-byte errors that leave the check unchanged.
      (The Fletcher checksum uses 255, which is not prime and which also
      makes the Fletcher check insensitive to single byte changes 0 <->
      255.)

      The sum s1 is initialized to 1 instead of zero to make the length
      of the sequence part of s2, so that the length does not have to be
      checked separately. (Any sequence of zeroes has a Fletcher
      checksum of zero.)








Deutsch & Gailly             Informational                      [Page 9]

RFC 1950       ZLIB Compressed Data Format Specification        May 1996


9. Appendix: Sample code

   The following C code computes the Adler-32 checksum of a data buffer.
   It is written for clarity, not for speed.  The sample code is in the
   ANSI C programming language. Non C users may find it easier to read
   with these hints:

      &      Bitwise AND operator.
      >>     Bitwise right shift operator. When applied to an
             unsigned quantity, as here, right shift inserts zero bit(s)
             at the left.
      <<     Bitwise left shift operator. Left shift inserts zero
             bit(s) at the right.
      ++     "n++" increments the variable n.
      %      modulo operator: a % b is the remainder of a divided by b.

      #define BASE 65521 /* largest prime smaller than 65536 */

      /*
         Update a running Adler-32 checksum with the bytes buf[0..len-1]
       and return the updated checksum. The Adler-32 checksum should be
       initialized to 1.

       Usage example:

         unsigned long adler = 1L;

         while (read_buffer(buffer, length) != EOF) {
           adler = update_adler32(adler, buffer, length);
         }
         if (adler != original_adler) error();
      */
      unsigned long update_adler32(unsigned long adler,
         unsigned char *buf, int len)
      {
        unsigned long s1 = adler & 0xffff;
        unsigned long s2 = (adler >> 16) & 0xffff;
        int n;

        for (n = 0; n < len; n++) {
          s1 = (s1 + buf[n]) % BASE;
          s2 = (s2 + s1)     % BASE;
        }
        return (s2 << 16) + s1;
      }

      /* Return the adler32 of the bytes buf[0..len-1] */




Deutsch & Gailly             Informational                     [Page 10]

RFC 1950       ZLIB Compressed Data Format Specification        May 1996


      unsigned long adler32(unsigned char *buf, int len)
      {
        return update_adler32(1L, buf, len);
      }















































Deutsch & Gailly             Informational                     [Page 11]


Added compat/zlib/doc/rfc1951.txt.




























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






Network Working Group                                         P. Deutsch
Request for Comments: 1951                           Aladdin Enterprises
Category: Informational                                         May 1996


        DEFLATE Compressed Data Format Specification version 1.3

Status of This Memo

   This memo provides information for the Internet community.  This memo
   does not specify an Internet standard of any kind.  Distribution of
   this memo is unlimited.

IESG Note:

   The IESG takes no position on the validity of any Intellectual
   Property Rights statements contained in this document.

Notices

   Copyright (c) 1996 L. Peter Deutsch

   Permission is granted to copy and distribute this document for any
   purpose and without charge, including translations into other
   languages and incorporation into compilations, provided that the
   copyright notice and this notice are preserved, and that any
   substantive changes or deletions from the original are clearly
   marked.

   A pointer to the latest version of this and related documentation in
   HTML format can be found at the URL
   <ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>.

Abstract

   This specification defines a lossless compressed data format that
   compresses data using a combination of the LZ77 algorithm and Huffman
   coding, with efficiency comparable to the best currently available
   general-purpose compression methods.  The data can be produced or
   consumed, even for an arbitrarily long sequentially presented input
   data stream, using only an a priori bounded amount of intermediate
   storage.  The format can be implemented readily in a manner not
   covered by patents.








Deutsch                      Informational                      [Page 1]

RFC 1951      DEFLATE Compressed Data Format Specification      May 1996


Table of Contents

   1. Introduction ................................................... 2
      1.1. Purpose ................................................... 2
      1.2. Intended audience ......................................... 3
      1.3. Scope ..................................................... 3
      1.4. Compliance ................................................ 3
      1.5.  Definitions of terms and conventions used ................ 3
      1.6. Changes from previous versions ............................ 4
   2. Compressed representation overview ............................. 4
   3. Detailed specification ......................................... 5
      3.1. Overall conventions ....................................... 5
          3.1.1. Packing into bytes .................................. 5
      3.2. Compressed block format ................................... 6
          3.2.1. Synopsis of prefix and Huffman coding ............... 6
          3.2.2. Use of Huffman coding in the "deflate" format ....... 7
          3.2.3. Details of block format ............................. 9
          3.2.4. Non-compressed blocks (BTYPE=00) ................... 11
          3.2.5. Compressed blocks (length and distance codes) ...... 11
          3.2.6. Compression with fixed Huffman codes (BTYPE=01) .... 12
          3.2.7. Compression with dynamic Huffman codes (BTYPE=10) .. 13
      3.3. Compliance ............................................... 14
   4. Compression algorithm details ................................. 14
   5. References .................................................... 16
   6. Security Considerations ....................................... 16
   7. Source code ................................................... 16
   8. Acknowledgements .............................................. 16
   9. Author's Address .............................................. 17

1. Introduction

   1.1. Purpose

      The purpose of this specification is to define a lossless
      compressed data format that:
          * Is independent of CPU type, operating system, file system,
            and character set, and hence can be used for interchange;
          * Can be produced or consumed, even for an arbitrarily long
            sequentially presented input data stream, using only an a
            priori bounded amount of intermediate storage, and hence
            can be used in data communications or similar structures
            such as Unix filters;
          * Compresses data with efficiency comparable to the best
            currently available general-purpose compression methods,
            and in particular considerably better than the "compress"
            program;
          * Can be implemented readily in a manner not covered by
            patents, and hence can be practiced freely;



Deutsch                      Informational                      [Page 2]

RFC 1951      DEFLATE Compressed Data Format Specification      May 1996


          * Is compatible with the file format produced by the current
            widely used gzip utility, in that conforming decompressors
            will be able to read data produced by the existing gzip
            compressor.

      The data format defined by this specification does not attempt to:

          * Allow random access to compressed data;
          * Compress specialized data (e.g., raster graphics) as well
            as the best currently available specialized algorithms.

      A simple counting argument shows that no lossless compression
      algorithm can compress every possible input data set.  For the
      format defined here, the worst case expansion is 5 bytes per 32K-
      byte block, i.e., a size increase of 0.015% for large data sets.
      English text usually compresses by a factor of 2.5 to 3;
      executable files usually compress somewhat less; graphical data
      such as raster images may compress much more.

   1.2. Intended audience

      This specification is intended for use by implementors of software
      to compress data into "deflate" format and/or decompress data from
      "deflate" format.

      The text of the specification assumes a basic background in
      programming at the level of bits and other primitive data
      representations.  Familiarity with the technique of Huffman coding
      is helpful but not required.

   1.3. Scope

      The specification specifies a method for representing a sequence
      of bytes as a (usually shorter) sequence of bits, and a method for
      packing the latter bit sequence into bytes.

   1.4. Compliance

      Unless otherwise indicated below, a compliant decompressor must be
      able to accept and decompress any data set that conforms to all
      the specifications presented here; a compliant compressor must
      produce data sets that conform to all the specifications presented
      here.

   1.5.  Definitions of terms and conventions used

      Byte: 8 bits stored or transmitted as a unit (same as an octet).
      For this specification, a byte is exactly 8 bits, even on machines



Deutsch                      Informational                      [Page 3]

RFC 1951      DEFLATE Compressed Data Format Specification      May 1996


      which store a character on a number of bits different from eight.
      See below, for the numbering of bits within a byte.

      String: a sequence of arbitrary bytes.

   1.6. Changes from previous versions

      There have been no technical changes to the deflate format since
      version 1.1 of this specification.  In version 1.2, some
      terminology was changed.  Version 1.3 is a conversion of the
      specification to RFC style.

2. Compressed representation overview

   A compressed data set consists of a series of blocks, corresponding
   to successive blocks of input data.  The block sizes are arbitrary,
   except that non-compressible blocks are limited to 65,535 bytes.

   Each block is compressed using a combination of the LZ77 algorithm
   and Huffman coding. The Huffman trees for each block are independent
   of those for previous or subsequent blocks; the LZ77 algorithm may
   use a reference to a duplicated string occurring in a previous block,
   up to 32K input bytes before.

   Each block consists of two parts: a pair of Huffman code trees that
   describe the representation of the compressed data part, and a
   compressed data part.  (The Huffman trees themselves are compressed
   using Huffman encoding.)  The compressed data consists of a series of
   elements of two types: literal bytes (of strings that have not been
   detected as duplicated within the previous 32K input bytes), and
   pointers to duplicated strings, where a pointer is represented as a
   pair <length, backward distance>.  The representation used in the
   "deflate" format limits distances to 32K bytes and lengths to 258
   bytes, but does not limit the size of a block, except for
   uncompressible blocks, which are limited as noted above.

   Each type of value (literals, distances, and lengths) in the
   compressed data is represented using a Huffman code, using one code
   tree for literals and lengths and a separate code tree for distances.
   The code trees for each block appear in a compact form just before
   the compressed data for that block.










Deutsch                      Informational                      [Page 4]

RFC 1951      DEFLATE Compressed Data Format Specification      May 1996


3. Detailed specification

   3.1. Overall conventions In the diagrams below, a box like this:

         +---+
         |   | <-- the vertical bars might be missing
         +---+

      represents one byte; a box like this:

         +==============+
         |              |
         +==============+

      represents a variable number of bytes.

      Bytes stored within a computer do not have a "bit order", since
      they are always treated as a unit.  However, a byte considered as
      an integer between 0 and 255 does have a most- and least-
      significant bit, and since we write numbers with the most-
      significant digit on the left, we also write bytes with the most-
      significant bit on the left.  In the diagrams below, we number the
      bits of a byte so that bit 0 is the least-significant bit, i.e.,
      the bits are numbered:

         +--------+
         |76543210|
         +--------+

      Within a computer, a number may occupy multiple bytes.  All
      multi-byte numbers in the format described here are stored with
      the least-significant byte first (at the lower memory address).
      For example, the decimal number 520 is stored as:

             0        1
         +--------+--------+
         |00001000|00000010|
         +--------+--------+
          ^        ^
          |        |
          |        + more significant byte = 2 x 256
          + less significant byte = 8

      3.1.1. Packing into bytes

         This document does not address the issue of the order in which
         bits of a byte are transmitted on a bit-sequential medium,
         since the final data format described here is byte- rather than



Deutsch                      Informational                      [Page 5]

RFC 1951      DEFLATE Compressed Data Format Specification      May 1996


         bit-oriented.  However, we describe the compressed block format
         in below, as a sequence of data elements of various bit
         lengths, not a sequence of bytes.  We must therefore specify
         how to pack these data elements into bytes to form the final
         compressed byte sequence:

             * Data elements are packed into bytes in order of
               increasing bit number within the byte, i.e., starting
               with the least-significant bit of the byte.
             * Data elements other than Huffman codes are packed
               starting with the least-significant bit of the data
               element.
             * Huffman codes are packed starting with the most-
               significant bit of the code.

         In other words, if one were to print out the compressed data as
         a sequence of bytes, starting with the first byte at the
         *right* margin and proceeding to the *left*, with the most-
         significant bit of each byte on the left as usual, one would be
         able to parse the result from right to left, with fixed-width
         elements in the correct MSB-to-LSB order and Huffman codes in
         bit-reversed order (i.e., with the first bit of the code in the
         relative LSB position).

   3.2. Compressed block format

      3.2.1. Synopsis of prefix and Huffman coding

         Prefix coding represents symbols from an a priori known
         alphabet by bit sequences (codes), one code for each symbol, in
         a manner such that different symbols may be represented by bit
         sequences of different lengths, but a parser can always parse
         an encoded string unambiguously symbol-by-symbol.

         We define a prefix code in terms of a binary tree in which the
         two edges descending from each non-leaf node are labeled 0 and
         1 and in which the leaf nodes correspond one-for-one with (are
         labeled with) the symbols of the alphabet; then the code for a
         symbol is the sequence of 0's and 1's on the edges leading from
         the root to the leaf labeled with that symbol.  For example:











Deutsch                      Informational                      [Page 6]

RFC 1951      DEFLATE Compressed Data Format Specification      May 1996


                          /\              Symbol    Code
                         0  1             ------    ----
                        /    \                A      00
                       /\     B               B       1
                      0  1                    C     011
                     /    \                   D     010
                    A     /\
                         0  1
                        /    \
                       D      C

         A parser can decode the next symbol from an encoded input
         stream by walking down the tree from the root, at each step
         choosing the edge corresponding to the next input bit.

         Given an alphabet with known symbol frequencies, the Huffman
         algorithm allows the construction of an optimal prefix code
         (one which represents strings with those symbol frequencies
         using the fewest bits of any possible prefix codes for that
         alphabet).  Such a code is called a Huffman code.  (See
         reference [1] in Chapter 5, references for additional
         information on Huffman codes.)

         Note that in the "deflate" format, the Huffman codes for the
         various alphabets must not exceed certain maximum code lengths.
         This constraint complicates the algorithm for computing code
         lengths from symbol frequencies.  Again, see Chapter 5,
         references for details.

      3.2.2. Use of Huffman coding in the "deflate" format

         The Huffman codes used for each alphabet in the "deflate"
         format have two additional rules:

             * All codes of a given bit length have lexicographically
               consecutive values, in the same order as the symbols
               they represent;

             * Shorter codes lexicographically precede longer codes.












Deutsch                      Informational                      [Page 7]

RFC 1951      DEFLATE Compressed Data Format Specification      May 1996


         We could recode the example above to follow this rule as
         follows, assuming that the order of the alphabet is ABCD:

            Symbol  Code
            ------  ----
            A       10
            B       0
            C       110
            D       111

         I.e., 0 precedes 10 which precedes 11x, and 110 and 111 are
         lexicographically consecutive.

         Given this rule, we can define the Huffman code for an alphabet
         just by giving the bit lengths of the codes for each symbol of
         the alphabet in order; this is sufficient to determine the
         actual codes.  In our example, the code is completely defined
         by the sequence of bit lengths (2, 1, 3, 3).  The following
         algorithm generates the codes as integers, intended to be read
         from most- to least-significant bit.  The code lengths are
         initially in tree[I].Len; the codes are produced in
         tree[I].Code.

         1)  Count the number of codes for each code length.  Let
             bl_count[N] be the number of codes of length N, N >= 1.

         2)  Find the numerical value of the smallest code for each
             code length:

                code = 0;
                bl_count[0] = 0;
                for (bits = 1; bits <= MAX_BITS; bits++) {
                    code = (code + bl_count[bits-1]) << 1;
                    next_code[bits] = code;
                }

         3)  Assign numerical values to all codes, using consecutive
             values for all codes of the same length with the base
             values determined at step 2. Codes that are never used
             (which have a bit length of zero) must not be assigned a
             value.

                for (n = 0;  n <= max_code; n++) {
                    len = tree[n].Len;
                    if (len != 0) {
                        tree[n].Code = next_code[len];
                        next_code[len]++;
                    }



Deutsch                      Informational                      [Page 8]

RFC 1951      DEFLATE Compressed Data Format Specification      May 1996


                }

         Example:

         Consider the alphabet ABCDEFGH, with bit lengths (3, 3, 3, 3,
         3, 2, 4, 4).  After step 1, we have:

            N      bl_count[N]
            -      -----------
            2      1
            3      5
            4      2

         Step 2 computes the following next_code values:

            N      next_code[N]
            -      ------------
            1      0
            2      0
            3      2
            4      14

         Step 3 produces the following code values:

            Symbol Length   Code
            ------ ------   ----
            A       3        010
            B       3        011
            C       3        100
            D       3        101
            E       3        110
            F       2         00
            G       4       1110
            H       4       1111

      3.2.3. Details of block format

         Each block of compressed data begins with 3 header bits
         containing the following data:

            first bit       BFINAL
            next 2 bits     BTYPE

         Note that the header bits do not necessarily begin on a byte
         boundary, since a block does not necessarily occupy an integral
         number of bytes.





Deutsch                      Informational                      [Page 9]

RFC 1951      DEFLATE Compressed Data Format Specification      May 1996


         BFINAL is set if and only if this is the last block of the data
         set.

         BTYPE specifies how the data are compressed, as follows:

            00 - no compression
            01 - compressed with fixed Huffman codes
            10 - compressed with dynamic Huffman codes
            11 - reserved (error)

         The only difference between the two compressed cases is how the
         Huffman codes for the literal/length and distance alphabets are
         defined.

         In all cases, the decoding algorithm for the actual data is as
         follows:

            do
               read block header from input stream.
               if stored with no compression
                  skip any remaining bits in current partially
                     processed byte
                  read LEN and NLEN (see next section)
                  copy LEN bytes of data to output
               otherwise
                  if compressed with dynamic Huffman codes
                     read representation of code trees (see
                        subsection below)
                  loop (until end of block code recognized)
                     decode literal/length value from input stream
                     if value < 256
                        copy value (literal byte) to output stream
                     otherwise
                        if value = end of block (256)
                           break from loop
                        otherwise (value = 257..285)
                           decode distance from input stream

                           move backwards distance bytes in the output
                           stream, and copy length bytes from this
                           position to the output stream.
                  end loop
            while not last block

         Note that a duplicated string reference may refer to a string
         in a previous block; i.e., the backward distance may cross one
         or more block boundaries.  However a distance cannot refer past
         the beginning of the output stream.  (An application using a



Deutsch                      Informational                     [Page 10]

RFC 1951      DEFLATE Compressed Data Format Specification      May 1996


         preset dictionary might discard part of the output stream; a
         distance can refer to that part of the output stream anyway)
         Note also that the referenced string may overlap the current
         position; for example, if the last 2 bytes decoded have values
         X and Y, a string reference with <length = 5, distance = 2>
         adds X,Y,X,Y,X to the output stream.

         We now specify each compression method in turn.

      3.2.4. Non-compressed blocks (BTYPE=00)

         Any bits of input up to the next byte boundary are ignored.
         The rest of the block consists of the following information:

              0   1   2   3   4...
            +---+---+---+---+================================+
            |  LEN  | NLEN  |... LEN bytes of literal data...|
            +---+---+---+---+================================+

         LEN is the number of data bytes in the block.  NLEN is the
         one's complement of LEN.

      3.2.5. Compressed blocks (length and distance codes)

         As noted above, encoded data blocks in the "deflate" format
         consist of sequences of symbols drawn from three conceptually
         distinct alphabets: either literal bytes, from the alphabet of
         byte values (0..255), or <length, backward distance> pairs,
         where the length is drawn from (3..258) and the distance is
         drawn from (1..32,768).  In fact, the literal and length
         alphabets are merged into a single alphabet (0..285), where
         values 0..255 represent literal bytes, the value 256 indicates
         end-of-block, and values 257..285 represent length codes
         (possibly in conjunction with extra bits following the symbol
         code) as follows:
















Deutsch                      Informational                     [Page 11]

RFC 1951      DEFLATE Compressed Data Format Specification      May 1996


                 Extra               Extra               Extra
            Code Bits Length(s) Code Bits Lengths   Code Bits Length(s)
            ---- ---- ------     ---- ---- -------   ---- ---- -------
             257   0     3       267   1   15,16     277   4   67-82
             258   0     4       268   1   17,18     278   4   83-98
             259   0     5       269   2   19-22     279   4   99-114
             260   0     6       270   2   23-26     280   4  115-130
             261   0     7       271   2   27-30     281   5  131-162
             262   0     8       272   2   31-34     282   5  163-194
             263   0     9       273   3   35-42     283   5  195-226
             264   0    10       274   3   43-50     284   5  227-257
             265   1  11,12      275   3   51-58     285   0    258
             266   1  13,14      276   3   59-66

         The extra bits should be interpreted as a machine integer
         stored with the most-significant bit first, e.g., bits 1110
         represent the value 14.

                  Extra           Extra               Extra
             Code Bits Dist  Code Bits   Dist     Code Bits Distance
             ---- ---- ----  ---- ----  ------    ---- ---- --------
               0   0    1     10   4     33-48    20    9   1025-1536
               1   0    2     11   4     49-64    21    9   1537-2048
               2   0    3     12   5     65-96    22   10   2049-3072
               3   0    4     13   5     97-128   23   10   3073-4096
               4   1   5,6    14   6    129-192   24   11   4097-6144
               5   1   7,8    15   6    193-256   25   11   6145-8192
               6   2   9-12   16   7    257-384   26   12  8193-12288
               7   2  13-16   17   7    385-512   27   12 12289-16384
               8   3  17-24   18   8    513-768   28   13 16385-24576
               9   3  25-32   19   8   769-1024   29   13 24577-32768

      3.2.6. Compression with fixed Huffman codes (BTYPE=01)

         The Huffman codes for the two alphabets are fixed, and are not
         represented explicitly in the data.  The Huffman code lengths
         for the literal/length alphabet are:

                   Lit Value    Bits        Codes
                   ---------    ----        -----
                     0 - 143     8          00110000 through
                                            10111111
                   144 - 255     9          110010000 through
                                            111111111
                   256 - 279     7          0000000 through
                                            0010111
                   280 - 287     8          11000000 through
                                            11000111



Deutsch                      Informational                     [Page 12]

RFC 1951      DEFLATE Compressed Data Format Specification      May 1996


         The code lengths are sufficient to generate the actual codes,
         as described above; we show the codes in the table for added
         clarity.  Literal/length values 286-287 will never actually
         occur in the compressed data, but participate in the code
         construction.

         Distance codes 0-31 are represented by (fixed-length) 5-bit
         codes, with possible additional bits as shown in the table
         shown in Paragraph 3.2.5, above.  Note that distance codes 30-
         31 will never actually occur in the compressed data.

      3.2.7. Compression with dynamic Huffman codes (BTYPE=10)

         The Huffman codes for the two alphabets appear in the block
         immediately after the header bits and before the actual
         compressed data, first the literal/length code and then the
         distance code.  Each code is defined by a sequence of code
         lengths, as discussed in Paragraph 3.2.2, above.  For even
         greater compactness, the code length sequences themselves are
         compressed using a Huffman code.  The alphabet for code lengths
         is as follows:

               0 - 15: Represent code lengths of 0 - 15
                   16: Copy the previous code length 3 - 6 times.
                       The next 2 bits indicate repeat length
                             (0 = 3, ... , 3 = 6)
                          Example:  Codes 8, 16 (+2 bits 11),
                                    16 (+2 bits 10) will expand to
                                    12 code lengths of 8 (1 + 6 + 5)
                   17: Repeat a code length of 0 for 3 - 10 times.
                       (3 bits of length)
                   18: Repeat a code length of 0 for 11 - 138 times
                       (7 bits of length)

         A code length of 0 indicates that the corresponding symbol in
         the literal/length or distance alphabet will not occur in the
         block, and should not participate in the Huffman code
         construction algorithm given earlier.  If only one distance
         code is used, it is encoded using one bit, not zero bits; in
         this case there is a single code length of one, with one unused
         code.  One distance code of zero bits means that there are no
         distance codes used at all (the data is all literals).

         We can now define the format of the block:

               5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286)
               5 Bits: HDIST, # of Distance codes - 1        (1 - 32)
               4 Bits: HCLEN, # of Code Length codes - 4     (4 - 19)



Deutsch                      Informational                     [Page 13]

RFC 1951      DEFLATE Compressed Data Format Specification      May 1996


               (HCLEN + 4) x 3 bits: code lengths for the code length
                  alphabet given just above, in the order: 16, 17, 18,
                  0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15

                  These code lengths are interpreted as 3-bit integers
                  (0-7); as above, a code length of 0 means the
                  corresponding symbol (literal/length or distance code
                  length) is not used.

               HLIT + 257 code lengths for the literal/length alphabet,
                  encoded using the code length Huffman code

               HDIST + 1 code lengths for the distance alphabet,
                  encoded using the code length Huffman code

               The actual compressed data of the block,
                  encoded using the literal/length and distance Huffman
                  codes

               The literal/length symbol 256 (end of data),
                  encoded using the literal/length Huffman code

         The code length repeat codes can cross from HLIT + 257 to the
         HDIST + 1 code lengths.  In other words, all code lengths form
         a single sequence of HLIT + HDIST + 258 values.

   3.3. Compliance

      A compressor may limit further the ranges of values specified in
      the previous section and still be compliant; for example, it may
      limit the range of backward pointers to some value smaller than
      32K.  Similarly, a compressor may limit the size of blocks so that
      a compressible block fits in memory.

      A compliant decompressor must accept the full range of possible
      values defined in the previous section, and must accept blocks of
      arbitrary size.

4. Compression algorithm details

   While it is the intent of this document to define the "deflate"
   compressed data format without reference to any particular
   compression algorithm, the format is related to the compressed
   formats produced by LZ77 (Lempel-Ziv 1977, see reference [2] below);
   since many variations of LZ77 are patented, it is strongly
   recommended that the implementor of a compressor follow the general
   algorithm presented here, which is known not to be patented per se.
   The material in this section is not part of the definition of the



Deutsch                      Informational                     [Page 14]

RFC 1951      DEFLATE Compressed Data Format Specification      May 1996


   specification per se, and a compressor need not follow it in order to
   be compliant.

   The compressor terminates a block when it determines that starting a
   new block with fresh trees would be useful, or when the block size
   fills up the compressor's block buffer.

   The compressor uses a chained hash table to find duplicated strings,
   using a hash function that operates on 3-byte sequences.  At any
   given point during compression, let XYZ be the next 3 input bytes to
   be examined (not necessarily all different, of course).  First, the
   compressor examines the hash chain for XYZ.  If the chain is empty,
   the compressor simply writes out X as a literal byte and advances one
   byte in the input.  If the hash chain is not empty, indicating that
   the sequence XYZ (or, if we are unlucky, some other 3 bytes with the
   same hash function value) has occurred recently, the compressor
   compares all strings on the XYZ hash chain with the actual input data
   sequence starting at the current point, and selects the longest
   match.

   The compressor searches the hash chains starting with the most recent
   strings, to favor small distances and thus take advantage of the
   Huffman encoding.  The hash chains are singly linked. There are no
   deletions from the hash chains; the algorithm simply discards matches
   that are too old.  To avoid a worst-case situation, very long hash
   chains are arbitrarily truncated at a certain length, determined by a
   run-time parameter.

   To improve overall compression, the compressor optionally defers the
   selection of matches ("lazy matching"): after a match of length N has
   been found, the compressor searches for a longer match starting at
   the next input byte.  If it finds a longer match, it truncates the
   previous match to a length of one (thus producing a single literal
   byte) and then emits the longer match.  Otherwise, it emits the
   original match, and, as described above, advances N bytes before
   continuing.

   Run-time parameters also control this "lazy match" procedure.  If
   compression ratio is most important, the compressor attempts a
   complete second search regardless of the length of the first match.
   In the normal case, if the current match is "long enough", the
   compressor reduces the search for a longer match, thus speeding up
   the process.  If speed is most important, the compressor inserts new
   strings in the hash table only when no match was found, or when the
   match is not "too long".  This degrades the compression ratio but
   saves time since there are both fewer insertions and fewer searches.





Deutsch                      Informational                     [Page 15]

RFC 1951      DEFLATE Compressed Data Format Specification      May 1996


5. References

   [1] Huffman, D. A., "A Method for the Construction of Minimum
       Redundancy Codes", Proceedings of the Institute of Radio
       Engineers, September 1952, Volume 40, Number 9, pp. 1098-1101.

   [2] Ziv J., Lempel A., "A Universal Algorithm for Sequential Data
       Compression", IEEE Transactions on Information Theory, Vol. 23,
       No. 3, pp. 337-343.

   [3] Gailly, J.-L., and Adler, M., ZLIB documentation and sources,
       available in ftp://ftp.uu.net/pub/archiving/zip/doc/

   [4] Gailly, J.-L., and Adler, M., GZIP documentation and sources,
       available as gzip-*.tar in ftp://prep.ai.mit.edu/pub/gnu/

   [5] Schwartz, E. S., and Kallick, B. "Generating a canonical prefix
       encoding." Comm. ACM, 7,3 (Mar. 1964), pp. 166-169.

   [6] Hirschberg and Lelewer, "Efficient decoding of prefix codes,"
       Comm. ACM, 33,4, April 1990, pp. 449-459.

6. Security Considerations

   Any data compression method involves the reduction of redundancy in
   the data.  Consequently, any corruption of the data is likely to have
   severe effects and be difficult to correct.  Uncompressed text, on
   the other hand, will probably still be readable despite the presence
   of some corrupted bytes.

   It is recommended that systems using this data format provide some
   means of validating the integrity of the compressed data.  See
   reference [3], for example.

7. Source code

   Source code for a C language implementation of a "deflate" compliant
   compressor and decompressor is available within the zlib package at
   ftp://ftp.uu.net/pub/archiving/zip/zlib/.

8. Acknowledgements

   Trademarks cited in this document are the property of their
   respective owners.

   Phil Katz designed the deflate format.  Jean-Loup Gailly and Mark
   Adler wrote the related software described in this specification.
   Glenn Randers-Pehrson converted this document to RFC and HTML format.



Deutsch                      Informational                     [Page 16]

RFC 1951      DEFLATE Compressed Data Format Specification      May 1996


9. Author's Address

   L. Peter Deutsch
   Aladdin Enterprises
   203 Santa Margarita Ave.
   Menlo Park, CA 94025

   Phone: (415) 322-0103 (AM only)
   FAX:   (415) 322-1734
   EMail: <ghost@aladdin.com>

   Questions about the technical content of this specification can be
   sent by email to:

   Jean-Loup Gailly <gzip@prep.ai.mit.edu> and
   Mark Adler <madler@alumni.caltech.edu>

   Editorial comments on this specification can be sent by email to:

   L. Peter Deutsch <ghost@aladdin.com> and
   Glenn Randers-Pehrson <randeg@alumni.rpi.edu>






























Deutsch                      Informational                     [Page 17]


Added compat/zlib/doc/rfc1952.txt.




































































































































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






Network Working Group                                         P. Deutsch
Request for Comments: 1952                           Aladdin Enterprises
Category: Informational                                         May 1996


               GZIP file format specification version 4.3

Status of This Memo

   This memo provides information for the Internet community.  This memo
   does not specify an Internet standard of any kind.  Distribution of
   this memo is unlimited.

IESG Note:

   The IESG takes no position on the validity of any Intellectual
   Property Rights statements contained in this document.

Notices

   Copyright (c) 1996 L. Peter Deutsch

   Permission is granted to copy and distribute this document for any
   purpose and without charge, including translations into other
   languages and incorporation into compilations, provided that the
   copyright notice and this notice are preserved, and that any
   substantive changes or deletions from the original are clearly
   marked.

   A pointer to the latest version of this and related documentation in
   HTML format can be found at the URL
   <ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>.

Abstract

   This specification defines a lossless compressed data format that is
   compatible with the widely used GZIP utility.  The format includes a
   cyclic redundancy check value for detecting data corruption.  The
   format presently uses the DEFLATE method of compression but can be
   easily extended to use other compression methods.  The format can be
   implemented readily in a manner not covered by patents.










Deutsch                      Informational                      [Page 1]

RFC 1952             GZIP File Format Specification             May 1996


Table of Contents

   1. Introduction ................................................... 2
      1.1. Purpose ................................................... 2
      1.2. Intended audience ......................................... 3
      1.3. Scope ..................................................... 3
      1.4. Compliance ................................................ 3
      1.5. Definitions of terms and conventions used ................. 3
      1.6. Changes from previous versions ............................ 3
   2. Detailed specification ......................................... 4
      2.1. Overall conventions ....................................... 4
      2.2. File format ............................................... 5
      2.3. Member format ............................................. 5
          2.3.1. Member header and trailer ........................... 6
              2.3.1.1. Extra field ................................... 8
              2.3.1.2. Compliance .................................... 9
      3. References .................................................. 9
      4. Security Considerations .................................... 10
      5. Acknowledgements ........................................... 10
      6. Author's Address ........................................... 10
      7. Appendix: Jean-Loup Gailly's gzip utility .................. 11
      8. Appendix: Sample CRC Code .................................. 11

1. Introduction

   1.1. Purpose

      The purpose of this specification is to define a lossless
      compressed data format that:

          * Is independent of CPU type, operating system, file system,
            and character set, and hence can be used for interchange;
          * Can compress or decompress a data stream (as opposed to a
            randomly accessible file) to produce another data stream,
            using only an a priori bounded amount of intermediate
            storage, and hence can be used in data communications or
            similar structures such as Unix filters;
          * Compresses data with efficiency comparable to the best
            currently available general-purpose compression methods,
            and in particular considerably better than the "compress"
            program;
          * Can be implemented readily in a manner not covered by
            patents, and hence can be practiced freely;
          * Is compatible with the file format produced by the current
            widely used gzip utility, in that conforming decompressors
            will be able to read data produced by the existing gzip
            compressor.




Deutsch                      Informational                      [Page 2]

RFC 1952             GZIP File Format Specification             May 1996


      The data format defined by this specification does not attempt to:

          * Provide random access to compressed data;
          * Compress specialized data (e.g., raster graphics) as well as
            the best currently available specialized algorithms.

   1.2. Intended audience

      This specification is intended for use by implementors of software
      to compress data into gzip format and/or decompress data from gzip
      format.

      The text of the specification assumes a basic background in
      programming at the level of bits and other primitive data
      representations.

   1.3. Scope

      The specification specifies a compression method and a file format
      (the latter assuming only that a file can store a sequence of
      arbitrary bytes).  It does not specify any particular interface to
      a file system or anything about character sets or encodings
      (except for file names and comments, which are optional).

   1.4. Compliance

      Unless otherwise indicated below, a compliant decompressor must be
      able to accept and decompress any file that conforms to all the
      specifications presented here; a compliant compressor must produce
      files that conform to all the specifications presented here.  The
      material in the appendices is not part of the specification per se
      and is not relevant to compliance.

   1.5. Definitions of terms and conventions used

      byte: 8 bits stored or transmitted as a unit (same as an octet).
      (For this specification, a byte is exactly 8 bits, even on
      machines which store a character on a number of bits different
      from 8.)  See below for the numbering of bits within a byte.

   1.6. Changes from previous versions

      There have been no technical changes to the gzip format since
      version 4.1 of this specification.  In version 4.2, some
      terminology was changed, and the sample CRC code was rewritten for
      clarity and to eliminate the requirement for the caller to do pre-
      and post-conditioning.  Version 4.3 is a conversion of the
      specification to RFC style.



Deutsch                      Informational                      [Page 3]

RFC 1952             GZIP File Format Specification             May 1996


2. Detailed specification

   2.1. Overall conventions

      In the diagrams below, a box like this:

         +---+
         |   | <-- the vertical bars might be missing
         +---+

      represents one byte; a box like this:

         +==============+
         |              |
         +==============+

      represents a variable number of bytes.

      Bytes stored within a computer do not have a "bit order", since
      they are always treated as a unit.  However, a byte considered as
      an integer between 0 and 255 does have a most- and least-
      significant bit, and since we write numbers with the most-
      significant digit on the left, we also write bytes with the most-
      significant bit on the left.  In the diagrams below, we number the
      bits of a byte so that bit 0 is the least-significant bit, i.e.,
      the bits are numbered:

         +--------+
         |76543210|
         +--------+

      This document does not address the issue of the order in which
      bits of a byte are transmitted on a bit-sequential medium, since
      the data format described here is byte- rather than bit-oriented.

      Within a computer, a number may occupy multiple bytes.  All
      multi-byte numbers in the format described here are stored with
      the least-significant byte first (at the lower memory address).
      For example, the decimal number 520 is stored as:

             0        1
         +--------+--------+
         |00001000|00000010|
         +--------+--------+
          ^        ^
          |        |
          |        + more significant byte = 2 x 256
          + less significant byte = 8



Deutsch                      Informational                      [Page 4]

RFC 1952             GZIP File Format Specification             May 1996


   2.2. File format

      A gzip file consists of a series of "members" (compressed data
      sets).  The format of each member is specified in the following
      section.  The members simply appear one after another in the file,
      with no additional information before, between, or after them.

   2.3. Member format

      Each member has the following structure:

         +---+---+---+---+---+---+---+---+---+---+
         |ID1|ID2|CM |FLG|     MTIME     |XFL|OS | (more-->)
         +---+---+---+---+---+---+---+---+---+---+

      (if FLG.FEXTRA set)

         +---+---+=================================+
         | XLEN  |...XLEN bytes of "extra field"...| (more-->)
         +---+---+=================================+

      (if FLG.FNAME set)

         +=========================================+
         |...original file name, zero-terminated...| (more-->)
         +=========================================+

      (if FLG.FCOMMENT set)

         +===================================+
         |...file comment, zero-terminated...| (more-->)
         +===================================+

      (if FLG.FHCRC set)

         +---+---+
         | CRC16 |
         +---+---+

         +=======================+
         |...compressed blocks...| (more-->)
         +=======================+

           0   1   2   3   4   5   6   7
         +---+---+---+---+---+---+---+---+
         |     CRC32     |     ISIZE     |
         +---+---+---+---+---+---+---+---+




Deutsch                      Informational                      [Page 5]

RFC 1952             GZIP File Format Specification             May 1996


      2.3.1. Member header and trailer

         ID1 (IDentification 1)
         ID2 (IDentification 2)
            These have the fixed values ID1 = 31 (0x1f, \037), ID2 = 139
            (0x8b, \213), to identify the file as being in gzip format.

         CM (Compression Method)
            This identifies the compression method used in the file.  CM
            = 0-7 are reserved.  CM = 8 denotes the "deflate"
            compression method, which is the one customarily used by
            gzip and which is documented elsewhere.

         FLG (FLaGs)
            This flag byte is divided into individual bits as follows:

               bit 0   FTEXT
               bit 1   FHCRC
               bit 2   FEXTRA
               bit 3   FNAME
               bit 4   FCOMMENT
               bit 5   reserved
               bit 6   reserved
               bit 7   reserved

            If FTEXT is set, the file is probably ASCII text.  This is
            an optional indication, which the compressor may set by
            checking a small amount of the input data to see whether any
            non-ASCII characters are present.  In case of doubt, FTEXT
            is cleared, indicating binary data. For systems which have
            different file formats for ascii text and binary data, the
            decompressor can use FTEXT to choose the appropriate format.
            We deliberately do not specify the algorithm used to set
            this bit, since a compressor always has the option of
            leaving it cleared and a decompressor always has the option
            of ignoring it and letting some other program handle issues
            of data conversion.

            If FHCRC is set, a CRC16 for the gzip header is present,
            immediately before the compressed data. The CRC16 consists
            of the two least significant bytes of the CRC32 for all
            bytes of the gzip header up to and not including the CRC16.
            [The FHCRC bit was never set by versions of gzip up to
            1.2.4, even though it was documented with a different
            meaning in gzip 1.2.4.]

            If FEXTRA is set, optional extra fields are present, as
            described in a following section.



Deutsch                      Informational                      [Page 6]

RFC 1952             GZIP File Format Specification             May 1996


            If FNAME is set, an original file name is present,
            terminated by a zero byte.  The name must consist of ISO
            8859-1 (LATIN-1) characters; on operating systems using
            EBCDIC or any other character set for file names, the name
            must be translated to the ISO LATIN-1 character set.  This
            is the original name of the file being compressed, with any
            directory components removed, and, if the file being
            compressed is on a file system with case insensitive names,
            forced to lower case. There is no original file name if the
            data was compressed from a source other than a named file;
            for example, if the source was stdin on a Unix system, there
            is no file name.

            If FCOMMENT is set, a zero-terminated file comment is
            present.  This comment is not interpreted; it is only
            intended for human consumption.  The comment must consist of
            ISO 8859-1 (LATIN-1) characters.  Line breaks should be
            denoted by a single line feed character (10 decimal).

            Reserved FLG bits must be zero.

         MTIME (Modification TIME)
            This gives the most recent modification time of the original
            file being compressed.  The time is in Unix format, i.e.,
            seconds since 00:00:00 GMT, Jan.  1, 1970.  (Note that this
            may cause problems for MS-DOS and other systems that use
            local rather than Universal time.)  If the compressed data
            did not come from a file, MTIME is set to the time at which
            compression started.  MTIME = 0 means no time stamp is
            available.

         XFL (eXtra FLags)
            These flags are available for use by specific compression
            methods.  The "deflate" method (CM = 8) sets these flags as
            follows:

               XFL = 2 - compressor used maximum compression,
                         slowest algorithm
               XFL = 4 - compressor used fastest algorithm

         OS (Operating System)
            This identifies the type of file system on which compression
            took place.  This may be useful in determining end-of-line
            convention for text files.  The currently defined values are
            as follows:






Deutsch                      Informational                      [Page 7]

RFC 1952             GZIP File Format Specification             May 1996


                 0 - FAT filesystem (MS-DOS, OS/2, NT/Win32)
                 1 - Amiga
                 2 - VMS (or OpenVMS)
                 3 - Unix
                 4 - VM/CMS
                 5 - Atari TOS
                 6 - HPFS filesystem (OS/2, NT)
                 7 - Macintosh
                 8 - Z-System
                 9 - CP/M
                10 - TOPS-20
                11 - NTFS filesystem (NT)
                12 - QDOS
                13 - Acorn RISCOS
               255 - unknown

         XLEN (eXtra LENgth)
            If FLG.FEXTRA is set, this gives the length of the optional
            extra field.  See below for details.

         CRC32 (CRC-32)
            This contains a Cyclic Redundancy Check value of the
            uncompressed data computed according to CRC-32 algorithm
            used in the ISO 3309 standard and in section 8.1.1.6.2 of
            ITU-T recommendation V.42.  (See http://www.iso.ch for
            ordering ISO documents. See gopher://info.itu.ch for an
            online version of ITU-T V.42.)

         ISIZE (Input SIZE)
            This contains the size of the original (uncompressed) input
            data modulo 2^32.

      2.3.1.1. Extra field

         If the FLG.FEXTRA bit is set, an "extra field" is present in
         the header, with total length XLEN bytes.  It consists of a
         series of subfields, each of the form:

            +---+---+---+---+==================================+
            |SI1|SI2|  LEN  |... LEN bytes of subfield data ...|
            +---+---+---+---+==================================+

         SI1 and SI2 provide a subfield ID, typically two ASCII letters
         with some mnemonic value.  Jean-Loup Gailly
         <gzip@prep.ai.mit.edu> is maintaining a registry of subfield
         IDs; please send him any subfield ID you wish to use.  Subfield
         IDs with SI2 = 0 are reserved for future use.  The following
         IDs are currently defined:



Deutsch                      Informational                      [Page 8]

RFC 1952             GZIP File Format Specification             May 1996


            SI1         SI2         Data
            ----------  ----------  ----
            0x41 ('A')  0x70 ('P')  Apollo file type information

         LEN gives the length of the subfield data, excluding the 4
         initial bytes.

      2.3.1.2. Compliance

         A compliant compressor must produce files with correct ID1,
         ID2, CM, CRC32, and ISIZE, but may set all the other fields in
         the fixed-length part of the header to default values (255 for
         OS, 0 for all others).  The compressor must set all reserved
         bits to zero.

         A compliant decompressor must check ID1, ID2, and CM, and
         provide an error indication if any of these have incorrect
         values.  It must examine FEXTRA/XLEN, FNAME, FCOMMENT and FHCRC
         at least so it can skip over the optional fields if they are
         present.  It need not examine any other part of the header or
         trailer; in particular, a decompressor may ignore FTEXT and OS
         and always produce binary output, and still be compliant.  A
         compliant decompressor must give an error indication if any
         reserved bit is non-zero, since such a bit could indicate the
         presence of a new field that would cause subsequent data to be
         interpreted incorrectly.

3. References

   [1] "Information Processing - 8-bit single-byte coded graphic
       character sets - Part 1: Latin alphabet No.1" (ISO 8859-1:1987).
       The ISO 8859-1 (Latin-1) character set is a superset of 7-bit
       ASCII. Files defining this character set are available as
       iso_8859-1.* in ftp://ftp.uu.net/graphics/png/documents/

   [2] ISO 3309

   [3] ITU-T recommendation V.42

   [4] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification",
       available in ftp://ftp.uu.net/pub/archiving/zip/doc/

   [5] Gailly, J.-L., GZIP documentation, available as gzip-*.tar in
       ftp://prep.ai.mit.edu/pub/gnu/

   [6] Sarwate, D.V., "Computation of Cyclic Redundancy Checks via Table
       Look-Up", Communications of the ACM, 31(8), pp.1008-1013.




Deutsch                      Informational                      [Page 9]

RFC 1952             GZIP File Format Specification             May 1996


   [7] Schwaderer, W.D., "CRC Calculation", April 85 PC Tech Journal,
       pp.118-133.

   [8] ftp://ftp.adelaide.edu.au/pub/rocksoft/papers/crc_v3.txt,
       describing the CRC concept.

4. Security Considerations

   Any data compression method involves the reduction of redundancy in
   the data.  Consequently, any corruption of the data is likely to have
   severe effects and be difficult to correct.  Uncompressed text, on
   the other hand, will probably still be readable despite the presence
   of some corrupted bytes.

   It is recommended that systems using this data format provide some
   means of validating the integrity of the compressed data, such as by
   setting and checking the CRC-32 check value.

5. Acknowledgements

   Trademarks cited in this document are the property of their
   respective owners.

   Jean-Loup Gailly designed the gzip format and wrote, with Mark Adler,
   the related software described in this specification.  Glenn
   Randers-Pehrson converted this document to RFC and HTML format.

6. Author's Address

   L. Peter Deutsch
   Aladdin Enterprises
   203 Santa Margarita Ave.
   Menlo Park, CA 94025

   Phone: (415) 322-0103 (AM only)
   FAX:   (415) 322-1734
   EMail: <ghost@aladdin.com>

   Questions about the technical content of this specification can be
   sent by email to:

   Jean-Loup Gailly <gzip@prep.ai.mit.edu> and
   Mark Adler <madler@alumni.caltech.edu>

   Editorial comments on this specification can be sent by email to:

   L. Peter Deutsch <ghost@aladdin.com> and
   Glenn Randers-Pehrson <randeg@alumni.rpi.edu>



Deutsch                      Informational                     [Page 10]

RFC 1952             GZIP File Format Specification             May 1996


7. Appendix: Jean-Loup Gailly's gzip utility

   The most widely used implementation of gzip compression, and the
   original documentation on which this specification is based, were
   created by Jean-Loup Gailly <gzip@prep.ai.mit.edu>.  Since this
   implementation is a de facto standard, we mention some more of its
   features here.  Again, the material in this section is not part of
   the specification per se, and implementations need not follow it to
   be compliant.

   When compressing or decompressing a file, gzip preserves the
   protection, ownership, and modification time attributes on the local
   file system, since there is no provision for representing protection
   attributes in the gzip file format itself.  Since the file format
   includes a modification time, the gzip decompressor provides a
   command line switch that assigns the modification time from the file,
   rather than the local modification time of the compressed input, to
   the decompressed output.

8. Appendix: Sample CRC Code

   The following sample code represents a practical implementation of
   the CRC (Cyclic Redundancy Check). (See also ISO 3309 and ITU-T V.42
   for a formal specification.)

   The sample code is in the ANSI C programming language. Non C users
   may find it easier to read with these hints:

      &      Bitwise AND operator.
      ^      Bitwise exclusive-OR operator.
      >>     Bitwise right shift operator. When applied to an
             unsigned quantity, as here, right shift inserts zero
             bit(s) at the left.
      !      Logical NOT operator.
      ++     "n++" increments the variable n.
      0xNNN  0x introduces a hexadecimal (base 16) constant.
             Suffix L indicates a long value (at least 32 bits).

      /* Table of CRCs of all 8-bit messages. */
      unsigned long crc_table[256];

      /* Flag: has the table been computed? Initially false. */
      int crc_table_computed = 0;

      /* Make the table for a fast CRC. */
      void make_crc_table(void)
      {
        unsigned long c;



Deutsch                      Informational                     [Page 11]

RFC 1952             GZIP File Format Specification             May 1996


        int n, k;
        for (n = 0; n < 256; n++) {
          c = (unsigned long) n;
          for (k = 0; k < 8; k++) {
            if (c & 1) {
              c = 0xedb88320L ^ (c >> 1);
            } else {
              c = c >> 1;
            }
          }
          crc_table[n] = c;
        }
        crc_table_computed = 1;
      }

      /*
         Update a running crc with the bytes buf[0..len-1] and return
       the updated crc. The crc should be initialized to zero. Pre- and
       post-conditioning (one's complement) is performed within this
       function so it shouldn't be done by the caller. Usage example:

         unsigned long crc = 0L;

         while (read_buffer(buffer, length) != EOF) {
           crc = update_crc(crc, buffer, length);
         }
         if (crc != original_crc) error();
      */
      unsigned long update_crc(unsigned long crc,
                      unsigned char *buf, int len)
      {
        unsigned long c = crc ^ 0xffffffffL;
        int n;

        if (!crc_table_computed)
          make_crc_table();
        for (n = 0; n < len; n++) {
          c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
        }
        return c ^ 0xffffffffL;
      }

      /* Return the CRC of the bytes buf[0..len-1]. */
      unsigned long crc(unsigned char *buf, int len)
      {
        return update_crc(0L, buf, len);
      }




Deutsch                      Informational                     [Page 12]


Added compat/zlib/doc/txtvsbin.txt.












































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
A Fast Method for Identifying Plain Text Files
==============================================


Introduction
------------

Given a file coming from an unknown source, it is sometimes desirable
to find out whether the format of that file is plain text.  Although
this may appear like a simple task, a fully accurate detection of the
file type requires heavy-duty semantic analysis on the file contents.
It is, however, possible to obtain satisfactory results by employing
various heuristics.

Previous versions of PKZip and other zip-compatible compression tools
were using a crude detection scheme: if more than 80% (4/5) of the bytes
found in a certain buffer are within the range [7..127], the file is
labeled as plain text, otherwise it is labeled as binary.  A prominent
limitation of this scheme is the restriction to Latin-based alphabets.
Other alphabets, like Greek, Cyrillic or Asian, make extensive use of
the bytes within the range [128..255], and texts using these alphabets
are most often misidentified by this scheme; in other words, the rate
of false negatives is sometimes too high, which means that the recall
is low.  Another weakness of this scheme is a reduced precision, due to
the false positives that may occur when binary files containing large
amounts of textual characters are misidentified as plain text.

In this article we propose a new, simple detection scheme that features
a much increased precision and a near-100% recall.  This scheme is
designed to work on ASCII, Unicode and other ASCII-derived alphabets,
and it handles single-byte encodings (ISO-8859, MacRoman, KOI8, etc.)
and variable-sized encodings (ISO-2022, UTF-8, etc.).  Wider encodings
(UCS-2/UTF-16 and UCS-4/UTF-32) are not handled, however.


The Algorithm
-------------

The algorithm works by dividing the set of bytecodes [0..255] into three
categories:
- The allow list of textual bytecodes:
  9 (TAB), 10 (LF), 13 (CR), 32 (SPACE) to 255.
- The gray list of tolerated bytecodes:
  7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB), 27 (ESC).
- The block list of undesired, non-textual bytecodes:
  0 (NUL) to 6, 14 to 31.

If a file contains at least one byte that belongs to the allow list and
no byte that belongs to the block list, then the file is categorized as
plain text; otherwise, it is categorized as binary.  (The boundary case,
when the file is empty, automatically falls into the latter category.)


Rationale
---------

The idea behind this algorithm relies on two observations.

The first observation is that, although the full range of 7-bit codes
[0..127] is properly specified by the ASCII standard, most control
characters in the range [0..31] are not used in practice.  The only
widely-used, almost universally-portable control codes are 9 (TAB),
10 (LF) and 13 (CR).  There are a few more control codes that are
recognized on a reduced range of platforms and text viewers/editors:
7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB) and 27 (ESC); but these
codes are rarely (if ever) used alone, without being accompanied by
some printable text.  Even the newer, portable text formats such as
XML avoid using control characters outside the list mentioned here.

The second observation is that most of the binary files tend to contain
control characters, especially 0 (NUL).  Even though the older text
detection schemes observe the presence of non-ASCII codes from the range
[128..255], the precision rarely has to suffer if this upper range is
labeled as textual, because the files that are genuinely binary tend to
contain both control characters and codes from the upper range.  On the
other hand, the upper range needs to be labeled as textual, because it
is used by virtually all ASCII extensions.  In particular, this range is
used for encoding non-Latin scripts.

Since there is no counting involved, other than simply observing the
presence or the absence of some byte values, the algorithm produces
consistent results, regardless what alphabet encoding is being used.
(If counting were involved, it could be possible to obtain different
results on a text encoded, say, using ISO-8859-16 versus UTF-8.)

There is an extra category of plain text files that are "polluted" with
one or more block-listed codes, either by mistake or by peculiar design
considerations.  In such cases, a scheme that tolerates a small fraction
of block-listed codes would provide an increased recall (i.e. more true
positives).  This, however, incurs a reduced precision overall, since
false positives are more likely to appear in binary files that contain
large chunks of textual data.  Furthermore, "polluted" plain text should
be regarded as binary by general-purpose text detection schemes, because
general-purpose text processing algorithms might not be applicable.
Under this premise, it is safe to say that our detection method provides
a near-100% recall.

Experiments have been run on many files coming from various platforms
and applications.  We tried plain text files, system logs, source code,
formatted office documents, compiled object code, etc.  The results
confirm the optimistic assumptions about the capabilities of this
algorithm.


--
Cosmin Truta
Last updated: 2006-May-28

Changes to compat/zlib/examples/README.examples.

30
31
32
33
34
35
36




37
38
39
40
41
42
43
44
45
46

47
48
49
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







+
+
+
+










+



gzlog.c
gzlog.h
    efficiently and robustly maintain a message log file in gzip format
    - illustrates use of raw deflate, Z_PARTIAL_FLUSH, deflatePrime(),
      and deflateSetDictionary()
    - illustrates use of a gzip header extra field

gznorm.c
    normalize a gzip file by combining members into a single member
    - demonstrates how to concatenate deflate streams using Z_BLOCK

zlib_how.html
    painfully comprehensive description of zpipe.c (see below)
    - describes in excruciating detail the use of deflate() and inflate()

zpipe.c
    reads and writes zlib streams from stdin to stdout
    - illustrates the proper use of deflate() and inflate()
    - deeply commented in zlib_how.html (see above)

zran.c
zran.h
    index a zlib or gzip stream and randomly access it
    - illustrates the use of Z_BLOCK, inflatePrime(), and
      inflateSetDictionary() to provide random access

Changes to compat/zlib/examples/enough.c.

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
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
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
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
467
468
469



















470
471
472
473
474




475
476
477
478

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
558
559
560
561
562
563
564




565
566
567

568
569

570
571
572
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

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
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
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
467
468
469
470





471
472
473
474
475
476





477
478











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
558
559
560
561





562
563
564





565
566
567
568
569

570




571





572
573
574
575
576
577

578
579




580
581
582
583


584
585




586
587
588
589
590
591

592
593

594
595
596
597

-
-
-
+
+
+















+
+



-
-
-
+
+
+


-
+




-
+


-
+

-
+

-
-
+
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
-
+
+
+



-
+

-
+


-
+



-
+





-
-
-
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+





+
+




-
-
-
-
-
-
+
+
+
+
+
+
+














-
+

-
-
+
+



-
-
-
-
-
-
+
+
+
+
+
+
-


-
-
-
+
+
+






-
+

-
+

-
-
+
+

-
-
+
+


-
+
-


-
-
-
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
+



-
-
+
+

-
-
-
+
+
+

-
+

-
-
-
+
+
+



-
-
-
-
-
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
+
+


-
+


-
-
+
+



-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
+

-
-
-
-
+
+
+
+

-
+

-
+

-
+
+




-
-
-
+
+
+


-
+

-
+


-
+
-
-
+
-
-
-
-
-


-
-
-
+
+
+


-
-
+
+



-
-
-
-
+
+
+
+
-
-
+
-
-
-
-
-
-
+

-
-
+
+

-
+


-
+




+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
+
+



-
-
+
+


-
-
-
+
+
+



-
-
-
-
-
+
+
+
+
+

-
-
+
+


-
+




-
+

-
-
-
+
+
+

-
+





-
-
+
+


-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+

-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+



-
+

-
+


-
+





-
-
-
+
+
+

-
-
-
+
+
+
+
+
-
-
-
+
+




-
-
+
+

-
+



-
-
-
+
+
+
-
-
-
+
-
-
-
-
-
+
+
+
+

-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+

-
+
-
-
-
-
+
-
-
-
-
-
+
+
+



-
+

-
-
-
-
+
+
+
+
-
-


-
-
-
-
+
+
+
+


-
+

-
+



/* enough.c -- determine the maximum size of inflate's Huffman code tables over
 * all possible valid and complete Huffman codes, subject to a length limit.
 * Copyright (C) 2007, 2008, 2012 Mark Adler
 * Version 1.4  18 August 2012  Mark Adler
 * all possible valid and complete prefix codes, subject to a length limit.
 * Copyright (C) 2007, 2008, 2012, 2018 Mark Adler
 * Version 1.5  5 August 2018  Mark Adler
 */

/* Version history:
   1.0   3 Jan 2007  First version (derived from codecount.c version 1.4)
   1.1   4 Jan 2007  Use faster incremental table usage computation
                     Prune examine() search on previously visited states
   1.2   5 Jan 2007  Comments clean up
                     As inflate does, decrease root for short codes
                     Refuse cases where inflate would increase root
   1.3  17 Feb 2008  Add argument for initial root table size
                     Fix bug for initial root table size == max - 1
                     Use a macro to compute the history index
   1.4  18 Aug 2012  Avoid shifts more than bits in type (caused endless loop!)
                     Clean up comparisons of different types
                     Clean up code indentation
   1.5   5 Aug 2018  Clean up code style, formatting, and comments
                     Show all the codes for the maximum, and only the maximum
 */

/*
   Examine all possible Huffman codes for a given number of symbols and a
   maximum code length in bits to determine the maximum table size for zilb's
   inflate.  Only complete Huffman codes are counted.
   Examine all possible prefix codes for a given number of symbols and a
   maximum code length in bits to determine the maximum table size for zlib's
   inflate. Only complete prefix codes are counted.

   Two codes are considered distinct if the vectors of the number of codes per
   length are not identical.  So permutations of the symbol assignments result
   length are not identical. So permutations of the symbol assignments result
   in the same code for the counting, as do permutations of the assignments of
   the bit values to the codes (i.e. only canonical codes are counted).

   We build a code from shorter to longer lengths, determining how many symbols
   are coded at each length.  At each step, we have how many symbols remain to
   are coded at each length. At each step, we have how many symbols remain to
   be coded, what the last code length used was, and how many bit patterns of
   that length remain unused. Then we add one to the code length and double the
   number of unused patterns to graduate to the next code length.  We then
   number of unused patterns to graduate to the next code length. We then
   assign all portions of the remaining symbols to that code length that
   preserve the properties of a correct and eventually complete code.  Those
   preserve the properties of a correct and eventually complete code. Those
   properties are: we cannot use more bit patterns than are available; and when
   all the symbols are used, there are exactly zero possible bit patterns
   remaining.
   all the symbols are used, there are exactly zero possible bit patterns left
   unused.

   The inflate Huffman decoding algorithm uses two-level lookup tables for
   speed.  There is a single first-level table to decode codes up to root bits
   in length (root == 9 in the current inflate implementation).  The table
   has 1 << root entries and is indexed by the next root bits of input.  Codes
   shorter than root bits have replicated table entries, so that the correct
   entry is pointed to regardless of the bits that follow the short code.  If
   the code is longer than root bits, then the table entry points to a second-
   level table.  The size of that table is determined by the longest code with
   that root-bit prefix.  If that longest code has length len, then the table
   has size 1 << (len - root), to index the remaining bits in that set of
   codes.  Each subsequent root-bit prefix then has its own sub-table.  The
   total number of table entries required by the code is calculated
   incrementally as the number of codes at each bit length is populated.  When
   all of the codes are shorter than root bits, then root is reduced to the
   longest code length, resulting in a single, smaller, one-level table.
   speed. There is a single first-level table to decode codes up to root bits
   in length (root == 9 for literal/length codes and root == 6 for distance
   codes, in the current inflate implementation). The base table has 1 << root
   entries and is indexed by the next root bits of input. Codes shorter than
   root bits have replicated table entries, so that the correct entry is
   pointed to regardless of the bits that follow the short code. If the code is
   longer than root bits, then the table entry points to a second-level table.
   The size of that table is determined by the longest code with that root-bit
   prefix. If that longest code has length len, then the table has size 1 <<
   (len - root), to index the remaining bits in that set of codes. Each
   subsequent root-bit prefix then has its own sub-table. The total number of
   table entries required by the code is calculated incrementally as the number
   of codes at each bit length is populated. When all of the codes are shorter
   than root bits, then root is reduced to the longest code length, resulting
   in a single, smaller, one-level table.

   The inflate algorithm also provides for small values of root (relative to
   the log2 of the number of symbols), where the shortest code has more bits
   than root.  In that case, root is increased to the length of the shortest
   code.  This program, by design, does not handle that case, so it is verified
   that the number of symbols is less than 2^(root + 1).
   than root. In that case, root is increased to the length of the shortest
   code. This program, by design, does not handle that case, so it is verified
   that the number of symbols is less than 1 << (root + 1).

   In order to speed up the examination (by about ten orders of magnitude for
   the default arguments), the intermediate states in the build-up of a code
   are remembered and previously visited branches are pruned.  The memory
   are remembered and previously visited branches are pruned. The memory
   required for this will increase rapidly with the total number of symbols and
   the maximum code length in bits.  However this is a very small price to pay
   the maximum code length in bits. However this is a very small price to pay
   for the vast speedup.

   First, all of the possible Huffman codes are counted, and reachable
   First, all of the possible prefix codes are counted, and reachable
   intermediate states are noted by a non-zero count in a saved-results array.
   Second, the intermediate states that lead to (root + 1) bit or longer codes
   are used to look at all sub-codes from those junctures for their inflate
   memory usage.  (The amount of memory used is not affected by the number of
   memory usage. (The amount of memory used is not affected by the number of
   codes of root bits or less in length.)  Third, the visited states in the
   construction of those sub-codes and the associated calculation of the table
   size is recalled in order to avoid recalculating from the same juncture.
   Beginning the code examination at (root + 1) bit codes, which is enabled by
   identifying the reachable nodes, accounts for about six of the orders of
   magnitude of improvement for the default arguments.  About another four
   orders of magnitude come from not revisiting previous states.  Out of
   approximately 2x10^16 possible Huffman codes, only about 2x10^6 sub-codes
   magnitude of improvement for the default arguments. About another four
   orders of magnitude come from not revisiting previous states. Out of
   approximately 2x10^16 possible prefix codes, only about 2x10^6 sub-codes
   need to be examined to cover all of the possible table memory usage cases
   for the default arguments of 286 symbols limited to 15-bit codes.

   Note that an unsigned long long type is used for counting.  It is quite easy
   to exceed the capacity of an eight-byte integer with a large number of
   symbols and a large maximum code length, so multiple-precision arithmetic
   would need to replace the unsigned long long arithmetic in that case.  This
   program will abort if an overflow occurs.  The big_t type identifies where
   the counting takes place.
   Note that the uintmax_t type is used for counting. It is quite easy to
   exceed the capacity of an eight-byte integer with a large number of symbols
   and a large maximum code length, so multiple-precision arithmetic would need
   to replace the integer arithmetic in that case. This program will abort if
   an overflow occurs. The big_t type identifies where the counting takes
   place.

   An unsigned long long type is also used for calculating the number of
   possible codes remaining at the maximum length.  This limits the maximum
   code length to the number of bits in a long long minus the number of bits
   needed to represent the symbols in a flat code.  The code_t type identifies
   where the bit pattern counting takes place.
   The uintmax_t type is also used for calculating the number of possible codes
   remaining at the maximum length. This limits the maximum code length to the
   number of bits in a long long minus the number of bits needed to represent
   the symbols in a flat code. The code_t type identifies where the bit-pattern
   counting takes place.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdint.h>
#include <assert.h>

#define local static

/* special data types */
typedef unsigned long long big_t;   /* type for code counting */
typedef unsigned long long code_t;  /* type for bit pattern counting */
struct tab {                        /* type for been here check */
    size_t len;         /* length of bit vector in char's */
    char *vec;          /* allocated bit vector */
// Special data types.
typedef uintmax_t big_t;    // type for code counting
#define PRIbig "ju"         // printf format for big_t
typedef uintmax_t code_t;   // type for bit pattern counting
struct tab {                // type for been-here check
    size_t len;             // allocated length of bit vector in octets
    char *vec;              // allocated bit vector
};

/* The array for saving results, num[], is indexed with this triplet:

      syms: number of symbols remaining to code
      left: number of available bit patterns at length len
      len: number of bits in the codes currently being assigned

   Those indices are constrained thusly when saving results:

      syms: 3..totsym (totsym == total symbols to code)
      left: 2..syms - 1, but only the evens (so syms == 8 -> 2, 4, 6)
      len: 1..max - 1 (max == maximum code length in bits)

   syms == 2 is not saved since that immediately leads to a single code.  left
   syms == 2 is not saved since that immediately leads to a single code. left
   must be even, since it represents the number of available bit patterns at
   the current length, which is double the number at the previous length.
   left ends at syms-1 since left == syms immediately results in a single code.
   the current length, which is double the number at the previous length. left
   ends at syms-1 since left == syms immediately results in a single code.
   (left > sym is not allowed since that would result in an incomplete code.)
   len is less than max, since the code completes immediately when len == max.

   The offset into the array is calculated for the three indices with the
   first one (syms) being outermost, and the last one (len) being innermost.
   We build the array with length max-1 lists for the len index, with syms-3
   of those for each symbol.  There are totsym-2 of those, with each one
   varying in length as a function of sym.  See the calculation of index in
   count() for the index, and the calculation of size in main() for the size
   The offset into the array is calculated for the three indices with the first
   one (syms) being outermost, and the last one (len) being innermost. We build
   the array with length max-1 lists for the len index, with syms-3 of those
   for each symbol. There are totsym-2 of those, with each one varying in
   length as a function of sym. See the calculation of index in map() for the
   index, and the calculation of size in main() for the size of the array.
   of the array.

   For the deflate example of 286 symbols limited to 15-bit codes, the array
   has 284,284 entries, taking up 2.17 MB for an 8-byte big_t.  More than
   half of the space allocated for saved results is actually used -- not all
   possible triplets are reached in the generation of valid Huffman codes.
   has 284,284 entries, taking up 2.17 MB for an 8-byte big_t. More than half
   of the space allocated for saved results is actually used -- not all
   possible triplets are reached in the generation of valid prefix codes.
 */

/* The array for tracking visited states, done[], is itself indexed identically
   to the num[] array as described above for the (syms, left, len) triplet.
   Each element in the array is further indexed by the (mem, rem) doublet,
   where mem is the amount of inflate table space used so far, and rem is the
   remaining unused entries in the current inflate sub-table.  Each indexed
   remaining unused entries in the current inflate sub-table. Each indexed
   element is simply one bit indicating whether the state has been visited or
   not.  Since the ranges for mem and rem are not known a priori, each bit
   not. Since the ranges for mem and rem are not known a priori, each bit
   vector is of a variable size, and grows as needed to accommodate the visited
   states.  mem and rem are used to calculate a single index in a triangular
   array.  Since the range of mem is expected in the default case to be about
   states. mem and rem are used to calculate a single index in a triangular
   array. Since the range of mem is expected in the default case to be about
   ten times larger than the range of rem, the array is skewed to reduce the
   memory usage, with eight times the range for mem than for rem.  See the
   calculations for offset and bit in beenhere() for the details.
   memory usage, with eight times the range for mem than for rem. See the
   calculations for offset and bit in been_here() for the details.

   For the deflate example of 286 symbols limited to 15-bit codes, the bit
   vectors grow to total approximately 21 MB, in addition to the 4.3 MB done[]
   vectors grow to total 5.5 MB, in addition to the 4.3 MB done array itself.
   array itself.
 */

/* Globals to avoid propagating constants or constant pointers recursively */
local int max;          /* maximum allowed bit length for the codes */
local int root;         /* size of base code table in bits */
// Type for a variable-length, allocated string.
typedef struct {
    char *str;          // pointer to allocated string
local int large;        /* largest code table so far */
local size_t size;      /* number of elements in num and done */
local int *code;        /* number of symbols assigned to each bit length */
local big_t *num;       /* saved results array for code counting */
local struct tab *done; /* states already evaluated array */

/* Index function for num[] and done[] */
    size_t size;        // size of allocation
    size_t len;         // length of string, not including terminating zero
} string_t;

// Clear a string_t.
local void string_clear(string_t *s) {
    s->str[0] = 0;
    s->len = 0;
}

#define INDEX(i,j,k) (((size_t)((i-1)>>1)*((i-2)>>1)+(j>>1)-1)*(max-1)+k-1)

/* Free allocated space.  Uses globals code, num, and done. */
local void cleanup(void)
{
    size_t n;

// Initialize a string_t.
local void string_init(string_t *s) {
    s->size = 16;
    s->str = malloc(s->size);
    assert(s->str != NULL && "out of memory");
    string_clear(s);
}

// Release the allocation of a string_t.
local void string_free(string_t *s) {
    free(s->str);
    s->str = NULL;
    s->size = 0;
    s->len = 0;
}

// Save the results of printf with fmt and the subsequent argument list to s.
// Each call appends to s. The allocated space for s is increased as needed.
local void string_printf(string_t *s, char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    size_t len = s->len;
    int ret = vsnprintf(s->str + len, s->size - len, fmt, ap);
    assert(ret >= 0 && "out of memory");
    s->len += ret;
    if (s->size < s->len + 1) {
        do {
            s->size <<= 1;
            assert(s->size != 0 && "overflow");
        } while (s->size < s->len + 1);
        s->str = realloc(s->str, s->size);
        assert(s->str != NULL && "out of memory");
        vsnprintf(s->str + len, s->size - len, fmt, ap);
    }
    if (done != NULL) {
        for (n = 0; n < size; n++)
            if (done[n].len)
    va_end(ap);
                free(done[n].vec);
        free(done);
    }
    if (num != NULL)
        free(num);
    if (code != NULL)
        free(code);
}

/* Return the number of possible Huffman codes using bit patterns of lengths
   len through max inclusive, coding syms symbols, with left bit patterns of
   length len unused -- return -1 if there is an overflow in the counting.
   Keep a record of previous results in num to prevent repeating the same
}

// Globals to avoid propagating constants or constant pointers recursively.
struct {
    int max;            // maximum allowed bit length for the codes
    int root;           // size of base code table in bits
    int large;          // largest code table so far
    size_t size;        // number of elements in num and done
    big_t tot;          // total number of codes with maximum tables size
    string_t out;       // display of subcodes for maximum tables size
    int *code;          // number of symbols assigned to each bit length
    big_t *num;         // saved results array for code counting
    struct tab *done;   // states already evaluated array
} g;

// Index function for num[] and done[].
local inline size_t map(int syms, int left, int len) {
    return ((size_t)((syms - 1) >> 1) * ((syms - 2) >> 1) +
            (left >> 1) - 1) * (g.max - 1) +
           len - 1;
}

// Free allocated space in globals.
local void cleanup(void) {
    if (g.done != NULL) {
        for (size_t n = 0; n < g.size; n++)
            if (g.done[n].len)
                free(g.done[n].vec);
        g.size = 0;
        free(g.done);   g.done = NULL;
    }
    free(g.num);    g.num = NULL;
    free(g.code);   g.code = NULL;
    string_free(&g.out);
}

// Return the number of possible prefix codes using bit patterns of lengths len
// through max inclusive, coding syms symbols, with left bit patterns of length
// len unused -- return -1 if there is an overflow in the counting. Keep a
// record of previous results in num to prevent repeating the same calculation.
   calculation.  Uses the globals max and num. */
local big_t count(int syms, int len, int left)
local big_t count(int syms, int left, int len) {
{
    big_t sum;          /* number of possible codes from this juncture */
    big_t got;          /* value returned from count() */
    int least;          /* least number of syms to use at this juncture */
    int most;           /* most number of syms to use at this juncture */
    int use;            /* number of bit patterns to use in next call */
    size_t index;       /* index of this case in *num */

    /* see if only one possible code */
    // see if only one possible code
    if (syms == left)
        return 1;

    /* note and verify the expected state */
    assert(syms > left && left > 0 && len < max);
    // note and verify the expected state
    assert(syms > left && left > 0 && len < g.max);

    /* see if we've done this one already */
    index = INDEX(syms, left, len);
    got = num[index];
    // see if we've done this one already
    size_t index = map(syms, left, len);
    big_t got = g.num[index];
    if (got)
        return got;         /* we have -- return the saved result */
        return got;         // we have -- return the saved result

    /* we need to use at least this many bit patterns so that the code won't be
       incomplete at the next length (more bit patterns than symbols) */
    least = (left << 1) - syms;
    // we need to use at least this many bit patterns so that the code won't be
    // incomplete at the next length (more bit patterns than symbols)
    int least = (left << 1) - syms;
    if (least < 0)
        least = 0;

    /* we can use at most this many bit patterns, lest there not be enough
       available for the remaining symbols at the maximum length (if there were
       no limit to the code length, this would become: most = left - 1) */
    most = (((code_t)left << (max - len)) - syms) /
            (((code_t)1 << (max - len)) - 1);
    // we can use at most this many bit patterns, lest there not be enough
    // available for the remaining symbols at the maximum length (if there were
    // no limit to the code length, this would become: most = left - 1)
    int most = (((code_t)left << (g.max - len)) - syms) /
               (((code_t)1 << (g.max - len)) - 1);

    /* count all possible codes from this juncture and add them up */
    sum = 0;
    for (use = least; use <= most; use++) {
        got = count(syms - use, len + 1, (left - use) << 1);
    // count all possible codes from this juncture and add them up
    big_t sum = 0;
    for (int use = least; use <= most; use++) {
        got = count(syms - use, (left - use) << 1, len + 1);
        sum += got;
        if (got == (big_t)0 - 1 || sum < got)   /* overflow */
            return (big_t)0 - 1;
        if (got == (big_t)-1 || sum < got)      // overflow
            return (big_t)-1;
    }

    /* verify that all recursive calls are productive */
    // verify that all recursive calls are productive
    assert(sum != 0);

    /* save the result and return it */
    num[index] = sum;
    // save the result and return it
    g.num[index] = sum;
    return sum;
}

/* Return true if we've been here before, set to true if not.  Set a bit in a
   bit vector to indicate visiting this state.  Each (syms,len,left) state
   has a variable size bit vector indexed by (mem,rem).  The bit vector is
   lengthened if needed to allow setting the (mem,rem) bit. */
// Return true if we've been here before, set to true if not. Set a bit in a
// bit vector to indicate visiting this state. Each (syms,len,left) state has a
// variable size bit vector indexed by (mem,rem). The bit vector is lengthened
// as needed to allow setting the (mem,rem) bit.
local int beenhere(int syms, int len, int left, int mem, int rem)
{
    size_t index;       /* index for this state's bit vector */
    size_t offset;      /* offset in this state's bit vector */
    int bit;            /* mask for this state's bit */
    size_t length;      /* length of the bit vector in bytes */
    char *vector;       /* new or enlarged bit vector */

    /* point to vector for (syms,left,len), bit in vector for (mem,rem) */
    index = INDEX(syms, left, len);
    mem -= 1 << root;
    offset = (mem >> 3) + rem;
local int been_here(int syms, int left, int len, int mem, int rem) {
    // point to vector for (syms,left,len), bit in vector for (mem,rem)
    size_t index = map(syms, left, len);
    mem -= 1 << g.root;             // mem always includes the root table
    mem >>= 1;                      // mem and rem are always even
    rem >>= 1;
    size_t offset = (mem >> 3) + rem;
    offset = ((offset * (offset + 1)) >> 1) + rem;
    bit = 1 << (mem & 7);
    int bit = 1 << (mem & 7);

    /* see if we've been here */
    length = done[index].len;
    if (offset < length && (done[index].vec[offset] & bit) != 0)
        return 1;       /* done this! */
    // see if we've been here
    size_t length = g.done[index].len;
    if (offset < length && (g.done[index].vec[offset] & bit) != 0)
        return 1;       // done this!

    /* we haven't been here before -- set the bit to show we have now */
    // we haven't been here before -- set the bit to show we have now

    /* see if we need to lengthen the vector in order to set the bit */
    // see if we need to lengthen the vector in order to set the bit
    if (length <= offset) {
        /* if we have one already, enlarge it, zero out the appended space */
        // if we have one already, enlarge it, zero out the appended space
        char *vector;
        if (length) {
            do {
                length <<= 1;
            } while (length <= offset);
            vector = realloc(done[index].vec, length);
            if (vector != NULL)
                memset(vector + done[index].len, 0, length - done[index].len);
            vector = realloc(g.done[index].vec, length);
            assert(vector != NULL && "out of memory");
            memset(vector + g.done[index].len, 0, length - g.done[index].len);
        }

        /* otherwise we need to make a new vector and zero it out */
        // otherwise we need to make a new vector and zero it out
        else {
            length = 1 << (len - root);
            length = 16;
            while (length <= offset)
                length <<= 1;
            vector = calloc(length, sizeof(char));
            vector = calloc(length, 1);
        }

            assert(vector != NULL && "out of memory");
        /* in either case, bail if we can't get the memory */
        if (vector == NULL) {
            fputs("abort: unable to allocate enough memory\n", stderr);
            cleanup();
            exit(1);
        }

        /* install the new vector */
        done[index].len = length;
        done[index].vec = vector;
        // install the new vector
        g.done[index].len = length;
        g.done[index].vec = vector;
    }

    /* set the bit */
    done[index].vec[offset] |= bit;
    // set the bit
    g.done[index].vec[offset] |= bit;
    return 0;
}

/* Examine all possible codes from the given node (syms, len, left).  Compute
   the amount of memory required to build inflate's decoding tables, where the
   number of code structures used so far is mem, and the number remaining in
   the current sub-table is rem.  Uses the globals max, code, root, large, and
// Examine all possible codes from the given node (syms, len, left). Compute
// the amount of memory required to build inflate's decoding tables, where the
// number of code structures used so far is mem, and the number remaining in
// the current sub-table is rem.
   done. */
local void examine(int syms, int len, int left, int mem, int rem)
local void examine(int syms, int left, int len, int mem, int rem) {
{
    int least;          /* least number of syms to use at this juncture */
    int most;           /* most number of syms to use at this juncture */
    int use;            /* number of bit patterns to use in next call */

    /* see if we have a complete code */
    // see if we have a complete code
    if (syms == left) {
        /* set the last code entry */
        code[len] = left;
        // set the last code entry
        g.code[len] = left;

        /* complete computation of memory used by this code */
        // complete computation of memory used by this code
        while (rem < left) {
            left -= rem;
            rem = 1 << (len - root);
            rem = 1 << (len - g.root);
            mem += rem;
        }
        assert(rem == left);

        // if this is at the maximum, show the sub-code
        if (mem >= g.large) {
        /* if this is a new maximum, show the entries used and the sub-code */
        if (mem > large) {
            large = mem;
            printf("max %d: ", mem);
            for (use = root + 1; use <= max; use++)
                if (code[use])
                    printf("%d[%d] ", code[use], use);
            putchar('\n');
            fflush(stdout);
            // if this is a new maximum, update the maximum and clear out the
            // printed sub-codes from the previous maximum
            if (mem > g.large) {
                g.large = mem;
                string_clear(&g.out);
            }

            // compute the starting state for this sub-code
            syms = 0;
            left = 1 << g.max;
            for (int bits = g.max; bits > g.root; bits--) {
                syms += g.code[bits];
                left -= g.code[bits];
                assert((left & 1) == 0);
                left >>= 1;
            }

            // print the starting state and the resulting sub-code to g.out
            string_printf(&g.out, "<%u, %u, %u>:",
                          syms, g.root + 1, ((1 << g.root) - left) << 1);
            for (int bits = g.root + 1; bits <= g.max; bits++)
                if (g.code[bits])
                    string_printf(&g.out, " %d[%d]", g.code[bits], bits);
            string_printf(&g.out, "\n");
        }

        /* remove entries as we drop back down in the recursion */
        code[len] = 0;
        // remove entries as we drop back down in the recursion
        g.code[len] = 0;
        return;
    }

    /* prune the tree if we can */
    if (beenhere(syms, len, left, mem, rem))
    // prune the tree if we can
    if (been_here(syms, left, len, mem, rem))
        return;

    /* we need to use at least this many bit patterns so that the code won't be
       incomplete at the next length (more bit patterns than symbols) */
    least = (left << 1) - syms;
    // we need to use at least this many bit patterns so that the code won't be
    // incomplete at the next length (more bit patterns than symbols)
    int least = (left << 1) - syms;
    if (least < 0)
        least = 0;

    /* we can use at most this many bit patterns, lest there not be enough
       available for the remaining symbols at the maximum length (if there were
       no limit to the code length, this would become: most = left - 1) */
    most = (((code_t)left << (max - len)) - syms) /
            (((code_t)1 << (max - len)) - 1);
    // we can use at most this many bit patterns, lest there not be enough
    // available for the remaining symbols at the maximum length (if there were
    // no limit to the code length, this would become: most = left - 1)
    int most = (((code_t)left << (g.max - len)) - syms) /
               (((code_t)1 << (g.max - len)) - 1);

    /* occupy least table spaces, creating new sub-tables as needed */
    use = least;
    // occupy least table spaces, creating new sub-tables as needed
    int use = least;
    while (rem < use) {
        use -= rem;
        rem = 1 << (len - root);
        rem = 1 << (len - g.root);
        mem += rem;
    }
    rem -= use;

    /* examine codes from here, updating table space as we go */
    // examine codes from here, updating table space as we go
    for (use = least; use <= most; use++) {
        code[len] = use;
        examine(syms - use, len + 1, (left - use) << 1,
                mem + (rem ? 1 << (len - root) : 0), rem << 1);
        g.code[len] = use;
        examine(syms - use, (left - use) << 1, len + 1,
                mem + (rem ? 1 << (len - g.root) : 0), rem << 1);
        if (rem == 0) {
            rem = 1 << (len - root);
            rem = 1 << (len - g.root);
            mem += rem;
        }
        rem--;
    }

    /* remove entries as we drop back down in the recursion */
    code[len] = 0;
    // remove entries as we drop back down in the recursion
    g.code[len] = 0;
}

/* Look at all sub-codes starting with root + 1 bits.  Look at only the valid
   intermediate code states (syms, left, len).  For each completed code,
   calculate the amount of memory required by inflate to build the decoding
   tables. Find the maximum amount of memory required and show the code that
   requires that maximum.  Uses the globals max, root, and num. */
local void enough(int syms)
// Look at all sub-codes starting with root + 1 bits. Look at only the valid
// intermediate code states (syms, left, len). For each completed code,
// calculate the amount of memory required by inflate to build the decoding
// tables. Find the maximum amount of memory required and show the codes that
// require that maximum.
local void enough(int syms) {
{
    int n;              /* number of remaing symbols for this node */
    int left;           /* number of unused bit patterns at this length */
    size_t index;       /* index of this case in *num */

    /* clear code */
    for (n = 0; n <= max; n++)
        code[n] = 0;
    // clear code
    for (int n = 0; n <= g.max; n++)
        g.code[n] = 0;

    /* look at all (root + 1) bit and longer codes */
    large = 1 << root;              /* base table */
    if (root < max)                 /* otherwise, there's only a base table */
        for (n = 3; n <= syms; n++)
            for (left = 2; left < n; left += 2)
    // look at all (root + 1) bit and longer codes
    string_clear(&g.out);           // empty saved results
    g.large = 1 << g.root;          // base table
    if (g.root < g.max)             // otherwise, there's only a base table
        for (int n = 3; n <= syms; n++)
            for (int left = 2; left < n; left += 2) {
            {
                /* look at all reachable (root + 1) bit nodes, and the
                   resulting codes (complete at root + 2 or more) */
                index = INDEX(n, left, root + 1);
                if (root + 1 < max && num[index])       /* reachable node */
                    examine(n, root + 1, left, 1 << root, 0);
                // look at all reachable (root + 1) bit nodes, and the
                // resulting codes (complete at root + 2 or more)
                size_t index = map(n, left, g.root + 1);
                if (g.root + 1 < g.max && g.num[index]) // reachable node
                    examine(n, left, g.root + 1, 1 << g.root, 0);

                /* also look at root bit codes with completions at root + 1
                   bits (not saved in num, since complete), just in case */
                if (num[index - 1] && n <= left << 1)
                    examine((n - left) << 1, root + 1, (n - left) << 1,
                            1 << root, 0);
                // also look at root bit codes with completions at root + 1
                // bits (not saved in num, since complete), just in case
                if (g.num[index - 1] && n <= left << 1)
                    examine((n - left) << 1, (n - left) << 1, g.root + 1,
                            1 << g.root, 0);
            }

    /* done */
    printf("done: maximum of %d table entries\n", large);
}


    // done
/*
   Examine and show the total number of possible Huffman codes for a given
   maximum number of symbols, initial root table size, and maximum code length
   in bits -- those are the command arguments in that order.  The default
   values are 286, 9, and 15 respectively, for the deflate literal/length code.
   The possible codes are counted for each number of coded symbols from two to
   the maximum.  The counts for each of those and the total number of codes are
   shown.  The maximum number of inflate table entires is then calculated
   across all possible codes.  Each new maximum number of table entries and the
   associated sub-code (starting at root + 1 == 10 bits) is shown.

    printf("maximum of %d table entries for root = %d\n", g.large, g.root);
   To count and examine Huffman codes that are not length-limited, provide a
   maximum length equal to the number of symbols minus one.

    fputs(g.out.str, stdout);
   For the deflate literal/length code, use "enough".  For the deflate distance
   code, use "enough 30 6".

}
   This uses the %llu printf format to print big_t numbers, which assumes that
   big_t is an unsigned long long.  If the big_t type is changed (for example
   to a multiple precision type), the method of printing will also need to be
   updated.
 */
int main(int argc, char **argv)
{
    int syms;           /* total number of symbols to code */
    int n;              /* number of symbols to code for this run */

// Examine and show the total number of possible prefix codes for a given
// maximum number of symbols, initial root table size, and maximum code length
    big_t got;          /* return value of count() */
    big_t sum;          /* accumulated number of codes over n */
    code_t word;        /* for counting bits in code_t */

    /* set up globals for cleanup() */
    code = NULL;
    num = NULL;
    done = NULL;
// in bits -- those are the command arguments in that order. The default values
// are 286, 9, and 15 respectively, for the deflate literal/length code. The
// possible codes are counted for each number of coded symbols from two to the
// maximum. The counts for each of those and the total number of codes are
// shown. The maximum number of inflate table entries is then calculated across
// all possible codes. Each new maximum number of table entries and the
// associated sub-code (starting at root + 1 == 10 bits) is shown.
//
// To count and examine prefix codes that are not length-limited, provide a
// maximum length equal to the number of symbols minus one.
//
// For the deflate literal/length code, use "enough". For the deflate distance
// code, use "enough 30 6".
int main(int argc, char **argv) {
    // set up globals for cleanup()
    g.code = NULL;
    g.num = NULL;
    g.done = NULL;
    string_init(&g.out);

    /* get arguments -- default to the deflate literal/length code */
    syms = 286;
    root = 9;
    max = 15;
    // get arguments -- default to the deflate literal/length code
    int syms = 286;
    g.root = 9;
    g.max = 15;
    if (argc > 1) {
        syms = atoi(argv[1]);
        if (argc > 2) {
            root = atoi(argv[2]);
            g.root = atoi(argv[2]);
            if (argc > 3)
                max = atoi(argv[3]);
                g.max = atoi(argv[3]);
        }
    }
    if (argc > 4 || syms < 2 || root < 1 || max < 1) {
    if (argc > 4 || syms < 2 || g.root < 1 || g.max < 1) {
        fputs("invalid arguments, need: [sym >= 2 [root >= 1 [max >= 1]]]\n",
              stderr);
        return 1;
    }

    /* if not restricting the code length, the longest is syms - 1 */
    if (max > syms - 1)
        max = syms - 1;
    // if not restricting the code length, the longest is syms - 1
    if (g.max > syms - 1)
        g.max = syms - 1;

    /* determine the number of bits in a code_t */
    for (n = 0, word = 1; word; n++, word <<= 1)
        ;
    // determine the number of bits in a code_t
    int bits = 0;
    for (code_t word = 1; word; word <<= 1)
        bits++;


    /* make sure that the calculation of most will not overflow */
    if (max > n || (code_t)(syms - 2) >= (((code_t)0 - 1) >> (max - 1))) {
    // make sure that the calculation of most will not overflow
    if (g.max > bits || (code_t)(syms - 2) >= ((code_t)-1 >> (g.max - 1))) {
        fputs("abort: code length too long for internal types\n", stderr);
        return 1;
    }

    /* reject impossible code requests */
    if ((code_t)(syms - 1) > ((code_t)1 << max) - 1) {
    // reject impossible code requests
    if ((code_t)(syms - 1) > ((code_t)1 << g.max) - 1) {
        fprintf(stderr, "%d symbols cannot be coded in %d bits\n",
                syms, max);
                syms, g.max);
        return 1;
    }

    /* allocate code vector */
    code = calloc(max + 1, sizeof(int));
    if (code == NULL) {
    // allocate code vector
    g.code = calloc(g.max + 1, sizeof(int));
    assert(g.code != NULL && "out of memory");
        fputs("abort: unable to allocate enough memory\n", stderr);
        return 1;
    }


    /* determine size of saved results array, checking for overflows,
       allocate and clear the array (set all to zero with calloc()) */
    if (syms == 2)              /* iff max == 1 */
        num = NULL;             /* won't be saving any results */
    // determine size of saved results array, checking for overflows,
    // allocate and clear the array (set all to zero with calloc())
    if (syms == 2)              // iff max == 1
        g.num = NULL;           // won't be saving any results
    else {
        size = syms >> 1;
        if (size > ((size_t)0 - 1) / (n = (syms - 1) >> 1) ||
                (size *= n, size > ((size_t)0 - 1) / (n = max - 1)) ||
                (size *= n, size > ((size_t)0 - 1) / sizeof(big_t)) ||
                (num = calloc(size, sizeof(big_t))) == NULL) {
        g.size = syms >> 1;
        int n = (syms - 1) >> 1;
        assert(g.size <= (size_t)-1 / n && "overflow");
        g.size *= n;
        n = g.max - 1;
        assert(g.size <= (size_t)-1 / n && "overflow");
        g.size *= n;
        g.num = calloc(g.size, sizeof(big_t));
            fputs("abort: unable to allocate enough memory\n", stderr);
            cleanup();
            return 1;
        }
    }
        assert(g.num != NULL && "out of memory");
    }


    /* count possible codes for all numbers of symbols, add up counts */
    sum = 0;
    for (n = 2; n <= syms; n++) {
        got = count(n, 1, 2);
    // count possible codes for all numbers of symbols, add up counts
    big_t sum = 0;
    for (int n = 2; n <= syms; n++) {
        big_t got = count(n, 2, 1);
        sum += got;
        if (got == (big_t)0 - 1 || sum < got) {     /* overflow */
        assert(got != (big_t)-1 && sum >= got && "overflow");
            fputs("abort: can't count that high!\n", stderr);
            cleanup();
            return 1;
        }
    }
        printf("%llu %d-codes\n", got, n);
    }
    printf("%llu total codes for 2 to %d symbols", sum, syms);
    if (max < syms - 1)
        printf(" (%d-bit length limit)\n", max);
    printf("%"PRIbig" total codes for 2 to %d symbols", sum, syms);
    if (g.max < syms - 1)
        printf(" (%d-bit length limit)\n", g.max);
    else
        puts(" (no length limit)");

    /* allocate and clear done array for beenhere() */
    // allocate and clear done array for been_here()
    if (syms == 2)
        done = NULL;
    else if (size > ((size_t)0 - 1) / sizeof(struct tab) ||
             (done = calloc(size, sizeof(struct tab))) == NULL) {
        fputs("abort: unable to allocate enough memory\n", stderr);
        g.done = NULL;
    else {
        g.done = calloc(g.size, sizeof(struct tab));
        assert(g.done != NULL && "out of memory");
        cleanup();
        return 1;
    }

    /* find and show maximum inflate table usage */
    if (root > max)                 /* reduce root to max length */
        root = max;
    if ((code_t)syms < ((code_t)1 << (root + 1)))
    // find and show maximum inflate table usage
    if (g.root > g.max)             // reduce root to max length
        g.root = g.max;
    if ((code_t)syms < ((code_t)1 << (g.root + 1)))
        enough(syms);
    else
        puts("cannot handle minimum code lengths > root");
        fputs("cannot handle minimum code lengths > root", stderr);

    /* done */
    // done
    cleanup();
    return 0;
}

Changes to compat/zlib/examples/fitblk.c.

13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27







-
+








/* Approach to just fitting a requested compressed size:

   fitblk performs three compression passes on a portion of the input
   data in order to determine how much of that input will compress to
   nearly the requested output block size.  The first pass generates
   enough deflate blocks to produce output to fill the requested
   output size plus a specfied excess amount (see the EXCESS define
   output size plus a specified excess amount (see the EXCESS define
   below).  The last deflate block may go quite a bit past that, but
   is discarded.  The second pass decompresses and recompresses just
   the compressed data that fit in the requested plus excess sized
   buffer.  The deflate process is terminated after that amount of
   input, which is less than the amount consumed on the first pass.
   The last deflate block of the result will be of a comparable size
   to the final product, so that the header for that deflate block and
105
106
107
108
109
110
111
112

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

112
113
114
115
116
117
118
119







-
+







        inf->next_out = raw;
        ret = inflate(inf, Z_NO_FLUSH);
        assert(ret != Z_STREAM_ERROR && ret != Z_DATA_ERROR &&
               ret != Z_NEED_DICT);
        if (ret == Z_MEM_ERROR)
            return ret;

        /* compress what was decompresed until done or no room */
        /* compress what was decompressed until done or no room */
        def->avail_in = RAWLEN - inf->avail_out;
        def->next_in = raw;
        if (inf->avail_out != 0)
            flush = Z_FINISH;
        ret = deflate(def, flush);
        assert(ret != Z_STREAM_ERROR);
    } while (ret != Z_STREAM_END && def->avail_out != 0);
194
195
196
197
198
199
200
201

202
203
204
205
206
207
208
194
195
196
197
198
199
200

201
202
203
204
205
206
207
208







-
+







    inf.next_in = blk;
    def.avail_out = size + EXCESS;
    def.next_out = tmp;
    ret = recompress(&inf, &def);
    if (ret == Z_MEM_ERROR)
        quit("out of memory");

    /* set up for next reocmpression */
    /* set up for next recompression */
    ret = inflateReset(&inf);
    assert(ret != Z_STREAM_ERROR);
    ret = deflateReset(&def);
    assert(ret != Z_STREAM_ERROR);

    /* do second and final recompression (third compression) */
    inf.avail_in = size - MARGIN;   /* assure stream will complete */

Changes to compat/zlib/examples/gun.c.

39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53







-
+







   writing all of the uncompressed data to the output.  Unlike gzip, gun allows
   an empty file on input, and will produce no error writing an empty output
   file.

   gun will also decompress files made by Unix compress, which uses LZW
   compression.  These files are automatically detected by virtue of their
   magic header bytes.  Since the end of Unix compress stream is marked by the
   end-of-file, they cannot be concantenated.  If a Unix compress stream is
   end-of-file, they cannot be concatenated.  If a Unix compress stream is
   encountered in an input file, it is the last stream in that file.

   Like gunzip and uncompress, the file attributes of the original compressed
   file are maintained in the final uncompressed file, to the extent that the
   user permissions allow it.

   On my Mac OS X PowerPC G4, gun is almost twice as fast as gunzip (version

Changes to compat/zlib/examples/gzappend.c.

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
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







-
+




















-
+







 * 1.1   4 Nov 2003     - Expand and clarify some comments and notes
 *                      - Add version and copyright to help
 *                      - Send help to stdout instead of stderr
 *                      - Add some preemptive typecasts
 *                      - Add L to constants in lseek() calls
 *                      - Remove some debugging information in error messages
 *                      - Use new data_type definition for zlib 1.2.1
 *                      - Simplfy and unify file operations
 *                      - Simplify and unify file operations
 *                      - Finish off gzip file in gztack()
 *                      - Use deflatePrime() instead of adding empty blocks
 *                      - Keep gzip file clean on appended file read errors
 *                      - Use in-place rotate instead of auxiliary buffer
 *                        (Why you ask?  Because it was fun to write!)
 * 1.2  11 Oct 2012     - Fix for proper z_const usage
 *                      - Check for input buffer malloc failure
 */

/*
   gzappend takes a gzip file and appends to it, compressing files from the
   command line or data from stdin.  The gzip file is written to directly, to
   avoid copying that file, in case it's large.  Note that this results in the
   unfriendly behavior that if gzappend fails, the gzip file is corrupted.

   This program was written to illustrate the use of the new Z_BLOCK option of
   zlib 1.2.x's inflate() function.  This option returns from inflate() at each
   block boundary to facilitate locating and modifying the last block bit at
   the start of the final deflate block.  Also whether using Z_BLOCK or not,
   another required feature of zlib 1.2.x is that inflate() now provides the
   number of unusued bits in the last input byte used.  gzappend will not work
   number of unused bits in the last input byte used.  gzappend will not work
   with versions of zlib earlier than 1.2.1.

   gzappend first decompresses the gzip file internally, discarding all but
   the last 32K of uncompressed data, and noting the location of the last block
   bit and the number of unused bits in the last byte of the compressed data.
   The gzip trailer containing the CRC-32 and length of the uncompressed data
   is verified.  This trailer will be later overwritten.
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
133
134
135
136
137
138
139

140
141
142
143
144
145
146
147







-
+








    /* pointer to last entry in list */
    last = list + (len - 1);

    /* do simple left shift by one */
    if (rot == 1) {
        tmp = *list;
        memcpy(list, list + 1, len - 1);
        memmove(list, list + 1, len - 1);
        *last = tmp;
        return;
    }

    /* do simple right shift by one */
    if (rot == len - 1) {
        tmp = *last;

Changes to compat/zlib/examples/gzlog.c.

1
2
3

4
5

6
7
8
9
10
11
12
1
2

3
4

5
6
7
8
9
10
11
12


-
+

-
+







/*
 * gzlog.c
 * Copyright (C) 2004, 2008, 2012, 2016 Mark Adler, all rights reserved
 * Copyright (C) 2004, 2008, 2012, 2016, 2019 Mark Adler, all rights reserved
 * For conditions of distribution and use, see copyright notice in gzlog.h
 * version 2.2, 14 Aug 2012
 * version 2.3, 25 May 2019
 */

/*
   gzlog provides a mechanism for frequently appending short strings to a gzip
   file that is efficient both in execution time and compression ratio.  The
   strategy is to write the short strings in an uncompressed form to the end of
   the gzip file, only compressing when the amount of uncompressed data has
208
209
210
211
212
213
214
215
216


217
218
219
220
221
222
223
208
209
210
211
212
213
214


215
216
217
218
219
220
221
222
223







-
-
+
+







   - Write over the extra field, marking foo.gz as complete.

   Recovery procedure:
   - If not a replace recovery, read in the foo.add file, and provide that data
     to the appropriate recovery below.  If there is no foo.add file, provide
     a zero data length to the recovery.  In that case, the append recovery
     restores the foo.gz to the previous compressed + uncompressed data state.
     For the the compress recovery, a missing foo.add file results in foo.gz
     being restored to the previous compressed-only data state.
     For the compress recovery, a missing foo.add file results in foo.gz being
     restored to the previous compressed-only data state.
   - Append recovery:
     - Pick up append at + step above
   - Compress recovery:
     - Pick up compress at * step above
   - Replace recovery:
     - Pick up compress at @ step above
   - Log the repair with a date stamp in foo.repairs
752
753
754
755
756
757
758

759
760
761
762
763
764

765
766
767
768
769
770
771
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773







+






+







            len = (size_t)(st.st_size);
            if ((off_t)len != st.st_size ||
                    (data = malloc(st.st_size)) == NULL) {
                log_log(log, op, "allocation failure");
                return -2;
            }
            if ((fd = open(log->path, O_RDONLY, 0)) < 0) {
                free(data);
                log_log(log, op, ".add file read failure");
                return -1;
            }
            ret = (size_t)read(fd, data, len) != len;
            close(fd);
            if (ret) {
                free(data);
                log_log(log, op, ".add file read failure");
                return -1;
            }
            log_log(log, op, "loaded .add file");
        }
        else
            log_log(log, op, "missing .add file!");

Changes to compat/zlib/examples/gzlog.h.

36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
36
37
38
39
40
41
42

43
44
45
46
47
48
49
50







-
+







   opening the log file locked for small bursts, and then closing it.  The log
   object works by appending stored (uncompressed) data to the gzip file until
   1 MB has been accumulated.  At that time, the stored data is compressed, and
   replaces the uncompressed data in the file.  The log file is truncated to
   its new size at that time.  After each write operation, the log file is a
   valid gzip file that can decompressed to recover what was written.

   The gzlog operations can be interupted at any point due to an application or
   The gzlog operations can be interrupted at any point due to an application or
   system crash, and the log file will be recovered the next time the log is
   opened with gzlog_open().
 */

#ifndef GZLOG_H
#define GZLOG_H

Added compat/zlib/examples/gznorm.c.























































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/* gznorm.c -- normalize a gzip stream
 * Copyright (C) 2018 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 * Version 1.0  7 Oct 2018  Mark Adler */

// gznorm takes a gzip stream, potentially containing multiple members, and
// converts it to a gzip stream with a single member. In addition the gzip
// header is normalized, removing the file name and time stamp, and setting the
// other header contents (XFL, OS) to fixed values. gznorm does not recompress
// the data, so it is fast, but no advantage is gained from the history that
// could be available across member boundaries.

#include <stdio.h>      // fread, fwrite, putc, fflush, ferror, fprintf,
                        // vsnprintf, stdout, stderr, NULL, FILE
#include <stdlib.h>     // malloc, free
#include <string.h>     // strerror
#include <errno.h>      // errno
#include <stdarg.h>     // va_list, va_start, va_end
#include "zlib.h"       // inflateInit2, inflate, inflateReset, inflateEnd,
                        // z_stream, z_off_t, crc32_combine, Z_NULL, Z_BLOCK,
                        // Z_OK, Z_STREAM_END, Z_BUF_ERROR, Z_DATA_ERROR,
                        // Z_MEM_ERROR

#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
#  include <fcntl.h>
#  include <io.h>
#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
#else
#  define SET_BINARY_MODE(file)
#endif

#define local static

// printf to an allocated string. Return the string, or NULL if the printf or
// allocation fails.
local char *aprintf(char *fmt, ...) {
    // Get the length of the result of the printf.
    va_list args;
    va_start(args, fmt);
    int len = vsnprintf(NULL, 0, fmt, args);
    va_end(args);
    if (len < 0)
        return NULL;

    // Allocate the required space and printf to it.
    char *str = malloc(len + 1);
    if (str == NULL)
        return NULL;
    va_start(args, fmt);
    vsnprintf(str, len + 1, fmt, args);
    va_end(args);
    return str;
}

// Return with an error, putting an allocated error message in *err. Doing an
// inflateEnd() on an already ended state, or one with state set to Z_NULL, is
// permitted.
#define BYE(...) \
    do { \
        inflateEnd(&strm); \
        *err = aprintf(__VA_ARGS__); \
        return 1; \
    } while (0)

// Chunk size for buffered reads and for decompression. Twice this many bytes
// will be allocated on the stack by gzip_normalize(). Must fit in an unsigned.
#define CHUNK 16384

// Read a gzip stream from in and write an equivalent normalized gzip stream to
// out. If given no input, an empty gzip stream will be written. If successful,
// 0 is returned, and *err is set to NULL. On error, 1 is returned, where the
// details of the error are returned in *err, a pointer to an allocated string.
//
// The input may be a stream with multiple gzip members, which is converted to
// a single gzip member on the output. Each gzip member is decompressed at the
// level of deflate blocks. This enables clearing the last-block bit, shifting
// the compressed data to concatenate to the previous member's compressed data,
// which can end at an arbitrary bit boundary, and identifying stored blocks in
// order to resynchronize those to byte boundaries. The deflate compressed data
// is terminated with a 10-bit empty fixed block. If any members on the input
// end with a 10-bit empty fixed block, then that block is excised from the
// stream. This avoids appending empty fixed blocks for every normalization,
// and assures that gzip_normalize applied a second time will not change the
// input. The pad bits after stored block headers and after the final deflate
// block are all forced to zeros.
local int gzip_normalize(FILE *in, FILE *out, char **err) {
    // initialize the inflate engine to process a gzip member
    z_stream strm;
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    strm.avail_in = 0;
    strm.next_in = Z_NULL;
    if (inflateInit2(&strm, 15 + 16) != Z_OK)
        BYE("out of memory");

    // State while processing the input gzip stream.
    enum {              // BETWEEN -> HEAD -> BLOCK -> TAIL -> BETWEEN -> ...
        BETWEEN,        // between gzip members (must end in this state)
        HEAD,           // reading a gzip header
        BLOCK,          // reading deflate blocks
        TAIL            // reading a gzip trailer
    } state = BETWEEN;              // current component being processed
    unsigned long crc = 0;          // accumulated CRC of uncompressed data
    unsigned long len = 0;          // accumulated length of uncompressed data
    unsigned long buf = 0;          // deflate stream bit buffer of num bits
    int num = 0;                    // number of bits in buf (at bottom)

    // Write a canonical gzip header (no mod time, file name, comment, extra
    // block, or extra flags, and OS is marked as unknown).
    fwrite("\x1f\x8b\x08\0\0\0\0\0\0\xff", 1, 10, out);

    // Process the gzip stream from in until reaching the end of the input,
    // encountering invalid input, or experiencing an i/o error.
    int more;                       // true if not at the end of the input
    do {
        // State inside this loop.
        unsigned char *put;         // next input buffer location to process
        int prev;                   // number of bits from previous block in
                                    // the bit buffer, or -1 if not at the
                                    // start of a block
        unsigned long long memb;    // uncompressed length of member
        size_t tail;                // number of trailer bytes read (0..8)
        unsigned long part;         // accumulated trailer component

        // Get the next chunk of input from in.
        unsigned char dat[CHUNK];
        strm.avail_in = fread(dat, 1, CHUNK, in);
        if (strm.avail_in == 0)
            break;
        more = strm.avail_in == CHUNK;
        strm.next_in = put = dat;

        // Run that chunk of input through the inflate engine to exhaustion.
        do {
            // At this point it is assured that strm.avail_in > 0.

            // Inflate until the end of a gzip component (header, deflate
            // block, trailer) is reached, or until all of the chunk is
            // consumed. The resulting decompressed data is discarded, though
            // the total size of the decompressed data in each member is
            // tracked, for the calculation of the total CRC.
            do {
                // inflate and handle any errors
                unsigned char scrap[CHUNK];
                strm.avail_out = CHUNK;
                strm.next_out = scrap;
                int ret = inflate(&strm, Z_BLOCK);
                if (ret == Z_MEM_ERROR)
                    BYE("out of memory");
                if (ret == Z_DATA_ERROR)
                    BYE("input invalid: %s", strm.msg);
                if (ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_STREAM_END)
                    BYE("internal error");

                // Update the number of uncompressed bytes generated in this
                // member. The actual count (not modulo 2^32) is required to
                // correctly compute the total CRC.
                unsigned got = CHUNK - strm.avail_out;
                memb += got;
                if (memb < got)
                    BYE("overflow error");

                // Continue to process this chunk until it is consumed, or
                // until the end of a component (header, deflate block, or
                // trailer) is reached.
            } while (strm.avail_out == 0 && (strm.data_type & 0x80) == 0);

            // Since strm.avail_in was > 0 for the inflate call, some input was
            // just consumed. It is therefore assured that put < strm.next_in.

            // Disposition the consumed component or part of a component.
            switch (state) {
                case BETWEEN:
                    state = HEAD;
                    // Fall through to HEAD when some or all of the header is
                    // processed.

                case HEAD:
                    // Discard the header.
                    if (strm.data_type & 0x80) {
                        // End of header reached -- deflate blocks follow.
                        put = strm.next_in;
                        prev = num;
                        memb = 0;
                        state = BLOCK;
                    }
                    break;

                case BLOCK:
                    // Copy the deflate stream to the output, but with the
                    // last-block-bit cleared. Re-synchronize stored block
                    // headers to the output byte boundaries. The bytes at
                    // put..strm.next_in-1 is the compressed data that has been
                    // processed and is ready to be copied to the output.

                    // At this point, it is assured that new compressed data is
                    // available, i.e., put < strm.next_in. If prev is -1, then
                    // that compressed data starts in the middle of a deflate
                    // block. If prev is not -1, then the bits in the bit
                    // buffer, possibly combined with the bits in *put, contain
                    // the three-bit header of the new deflate block. In that
                    // case, prev is the number of bits from the previous block
                    // that remain in the bit buffer. Since num is the number
                    // of bits in the bit buffer, we have that num - prev is
                    // the number of bits from the new block currently in the
                    // bit buffer.

                    // If strm.data_type & 0xc0 is 0x80, then the last byte of
                    // the available compressed data includes the last bits of
                    // the end of a deflate block. In that case, that last byte
                    // also has strm.data_type & 0x1f bits of the next deflate
                    // block, in the range 0..7. If strm.data_type & 0xc0 is
                    // 0xc0, then the last byte of the compressed data is the
                    // end of the deflate stream, followed by strm.data_type &
                    // 0x1f pad bits, also in the range 0..7.

                    // Set bits to the number of bits not yet consumed from the
                    // last byte. If we are at the end of the block, bits is
                    // either the number of bits in the last byte belonging to
                    // the next block, or the number of pad bits after the
                    // final block. In either of those cases, bits is in the
                    // range 0..7.
                    ;                   // (required due to C syntax oddity)
                    int bits = strm.data_type & 0x1f;

                    if (prev != -1) {
                        // We are at the start of a new block. Clear the last
                        // block bit, and check for special cases. If it is a
                        // stored block, then emit the header and pad to the
                        // next byte boundary. If it is a final, empty fixed
                        // block, then excise it.

                        // Some or all of the three header bits for this block
                        // may already be in the bit buffer. Load any remaining
                        // header bits into the bit buffer.
                        if (num - prev < 3) {
                            buf += (unsigned long)*put++ << num;
                            num += 8;
                        }

                        // Set last to have a 1 in the position of the last
                        // block bit in the bit buffer.
                        unsigned long last = (unsigned long)1 << prev;

                        if (((buf >> prev) & 7) == 3) {
                            // This is a final fixed block. Load at least ten
                            // bits from this block, including the header, into
                            // the bit buffer. We already have at least three,
                            // so at most one more byte needs to be loaded.
                            if (num - prev < 10) {
                                if (put == strm.next_in)
                                    // Need to go get and process more input.
                                    // We'll end up back here to finish this.
                                    break;
                                buf += (unsigned long)*put++ << num;
                                num += 8;
                            }
                            if (((buf >> prev) & 0x3ff) == 3) {
                                // That final fixed block is empty. Delete it
                                // to avoid adding an empty block every time a
                                // gzip stream is normalized.
                                num = prev;
                                buf &= last - 1;    // zero the pad bits
                            }
                        }
                        else if (((buf >> prev) & 6) == 0) {
                            // This is a stored block. Flush to the next
                            // byte boundary after the three-bit header.
                            num = (prev + 10) & ~7;
                            buf &= last - 1;        // zero the pad bits
                        }

                        // Clear the last block bit.
                        buf &= ~last;

                        // Write out complete bytes in the bit buffer.
                        while (num >= 8) {
                            putc(buf, out);
                            buf >>= 8;
                            num -= 8;
                        }

                        // If no more bytes left to process, then we have
                        // consumed the byte that had bits from the next block.
                        if (put == strm.next_in)
                            bits = 0;
                    }

                    // We are done handling the deflate block header. Now copy
                    // all or almost all of the remaining compressed data that
                    // has been processed so far. Don't copy one byte at the
                    // end if it contains bits from the next deflate block or
                    // pad bits at the end of a deflate block.

                    // mix is 1 if we are at the end of a deflate block, and if
                    // some of the bits in the last byte follow this block. mix
                    // is 0 if we are in the middle of a deflate block, if the
                    // deflate block ended on a byte boundary, or if all of the
                    // compressed data processed so far has been consumed.
                    int mix = (strm.data_type & 0x80) && bits;

                    // Copy all of the processed compressed data to the output,
                    // except for the last byte if it contains bits from the
                    // next deflate block or pad bits at the end of the deflate
                    // stream. Copy the data after shifting in num bits from
                    // buf in front of it, leaving num bits from the end of the
                    // compressed data in buf when done.
                    unsigned char *end = strm.next_in - mix;
                    if (put < end) {
                        if (num)
                            // Insert num bits from buf before the data being
                            // copied.
                            do {
                                buf += (unsigned)(*put++) << num;
                                putc(buf, out);
                                buf >>= 8;
                            } while (put < end);
                        else {
                            // No shifting needed -- write directly.
                            fwrite(put, 1, end - put, out);
                            put = end;
                        }
                    }

                    // Process the last processed byte if it wasn't written.
                    if (mix) {
                        // Load the last byte into the bit buffer.
                        buf += (unsigned)(*put++) << num;
                        num += 8;

                        if (strm.data_type & 0x40) {
                            // We are at the end of the deflate stream and
                            // there are bits pad bits. Discard the pad bits
                            // and write a byte to the output, if available.
                            // Leave the num bits left over in buf to prepend
                            // to the next deflate stream.
                            num -= bits;
                            if (num >= 8) {
                                putc(buf, out);
                                num -= 8;
                                buf >>= 8;
                            }

                            // Force the pad bits in the bit buffer to zeros.
                            buf &= ((unsigned long)1 << num) - 1;

                            // Don't need to set prev here since going to TAIL.
                        }
                        else
                            // At the end of an internal deflate block. Leave
                            // the last byte in the bit buffer to examine on
                            // the next entry to BLOCK, when more bits from the
                            // next block will be available.
                            prev = num - bits;      // number of bits in buffer
                                                    // from current block
                    }

                    // Don't have a byte left over, so we are in the middle of
                    // a deflate block, or the deflate block ended on a byte
                    // boundary. Set prev appropriately for the next entry into
                    // BLOCK.
                    else if (strm.data_type & 0x80)
                        // The block ended on a byte boundary, so no header
                        // bits are in the bit buffer.
                        prev = num;
                    else
                        // In the middle of a deflate block, so no header here.
                        prev = -1;

                    // Check for the end of the deflate stream.
                    if ((strm.data_type & 0xc0) == 0xc0) {
                        // That ends the deflate stream on the input side, the
                        // pad bits were discarded, and any remaining bits from
                        // the last block in the stream are saved in the bit
                        // buffer to prepend to the next stream. Process the
                        // gzip trailer next.
                        tail = 0;
                        part = 0;
                        state = TAIL;
                    }
                    break;

                case TAIL:
                    // Accumulate available trailer bytes to update the total
                    // CRC and the total uncompressed length.
                    do {
                        part = (part >> 8) + ((unsigned long)(*put++) << 24);
                        tail++;
                        if (tail == 4) {
                            // Update the total CRC.
                            z_off_t len2 = memb;
                            if (len2 < 0 || (unsigned long long)len2 != memb)
                                BYE("overflow error");
                            crc = crc ? crc32_combine(crc, part, len2) : part;
                            part = 0;
                        }
                        else if (tail == 8) {
                            // Update the total uncompressed length. (It's ok
                            // if this sum is done modulo 2^32.)
                            len += part;

                            // At the end of a member. Set up to inflate an
                            // immediately following gzip member. (If we made
                            // it this far, then the trailer was valid.)
                            if (inflateReset(&strm) != Z_OK)
                                BYE("internal error");
                            state = BETWEEN;
                            break;
                        }
                    } while (put < strm.next_in);
                    break;
            }

            // Process the input buffer until completely consumed.
        } while (strm.avail_in > 0);

        // Process input until end of file, invalid input, or i/o error.
    } while (more);

    // Done with the inflate engine.
    inflateEnd(&strm);

    // Verify the validity of the input.
    if (state != BETWEEN)
        BYE("input invalid: incomplete gzip stream");

    // Write the remaining deflate stream bits, followed by a terminating
    // deflate fixed block.
    buf += (unsigned long)3 << num;
    putc(buf, out);
    putc(buf >> 8, out);
    if (num > 6)
        putc(0, out);

    // Write the gzip trailer, which is the CRC and the uncompressed length
    // modulo 2^32, both in little-endian order.
    putc(crc, out);
    putc(crc >> 8, out);
    putc(crc >> 16, out);
    putc(crc >> 24, out);
    putc(len, out);
    putc(len >> 8, out);
    putc(len >> 16, out);
    putc(len >> 24, out);
    fflush(out);

    // Check for any i/o errors.
    if (ferror(in) || ferror(out))
        BYE("i/o error: %s", strerror(errno));

    // All good!
    *err = NULL;
    return 0;
}

// Normalize the gzip stream on stdin, writing the result to stdout.
int main(void) {
    // Avoid end-of-line conversions on evil operating systems.
    SET_BINARY_MODE(stdin);
    SET_BINARY_MODE(stdout);

    // Normalize from stdin to stdout, returning 1 on error, 0 if ok.
    char *err;
    int ret = gzip_normalize(stdin, stdout, &err);
    if (ret)
        fprintf(stderr, "gznorm error: %s\n", err);
    free(err);
    return ret;
}

Changes to compat/zlib/examples/zlib_how.html.

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


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
-
-
+
+




-
+












-
+







<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
  "http://www.w3.org/TR/REC-html40/loose.dtd">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>zlib Usage Example</title>
<!--  Copyright (c) 2004, 2005 Mark Adler.  -->
<!--  Copyright (c) 2004-2023 Mark Adler.  -->
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#00A000">
<h2 align="center"> zlib Usage Example </h2>
We often get questions about how the <tt>deflate()</tt> and <tt>inflate()</tt> functions should be used.
Users wonder when they should provide more input, when they should use more output,
what to do with a <tt>Z_BUF_ERROR</tt>, how to make sure the process terminates properly, and
so on.  So for those who have read <tt>zlib.h</tt> (a few times), and
would like further edification, below is an annotated example in C of simple routines to compress and decompress
from an input file to an output file using <tt>deflate()</tt> and <tt>inflate()</tt> respectively.  The
annotations are interspersed between lines of the code.  So please read between the lines.
We hope this helps explain some of the intricacies of <em>zlib</em>.
<p>
Without further adieu, here is the program <a href="zpipe.c"><tt>zpipe.c</tt></a>:
Without further ado, here is the program <a href="zpipe.c"><tt>zpipe.c</tt></a>:
<pre><b>
/* zpipe.c: example of proper use of zlib's inflate() and deflate()
   Not copyrighted -- provided to the public domain
   Version 1.4  11 December 2005  Mark Adler */

/* Version history:
   1.0  30 Oct 2004  First version
151
152
153
154
155
156
157
158


159
160

161
162
163
164

165
166
167
168
169
170
171
151
152
153
154
155
156
157

158
159
160

161




162
163
164
165
166
167
168
169







-
+
+

-
+
-
-
-
-
+







before we fall out of the loop at the bottom.
<pre><b>
    /* compress until end of file */
    do {
</b></pre>
We start off by reading data from the input file.  The number of bytes read is put directly
into <tt>avail_in</tt>, and a pointer to those bytes is put into <tt>next_in</tt>.  We also
check to see if end-of-file on the input has been reached.  If we are at the end of file, then <tt>flush</tt> is set to the
check to see if end-of-file on the input has been reached using feof().
If we are at the end of file, then <tt>flush</tt> is set to the
<em>zlib</em> constant <tt>Z_FINISH</tt>, which is later passed to <tt>deflate()</tt> to
indicate that this is the last chunk of input data to compress.  We need to use <tt>feof()</tt>
indicate that this is the last chunk of input data to compress.
to check for end-of-file as opposed to seeing if fewer than <tt>CHUNK</tt> bytes have been read.  The
reason is that if the input file length is an exact multiple of <tt>CHUNK</tt>, we will miss
the fact that we got to the end-of-file, and not know to tell <tt>deflate()</tt> to finish
up the compressed stream.  If we are not yet at the end of the input, then the <em>zlib</em>
If we are not yet at the end of the input, then the <em>zlib</em>
constant <tt>Z_NO_FLUSH</tt> will be passed to <tt>deflate</tt> to indicate that we are still
in the middle of the uncompressed data.
<p>
If there is an error in reading from the input file, the process is aborted with
<tt>deflateEnd()</tt> being called to free the allocated <em>zlib</em> state before returning
the error.  We wouldn't want a memory leak, now would we?  <tt>deflateEnd()</tt> can be called
at any time after the state has been initialized.  Once that's done, <tt>deflateInit()</tt> (or
536
537
538
539
540
541
542
543







544
545
534
535
536
537
538
539
540

541
542
543
544
545
546
547
548
549







-
+
+
+
+
+
+
+


    else {
        fputs("zpipe usage: zpipe [-d] &lt; source &gt; dest\n", stderr);
        return 1;
    }
}
</b></pre>
<hr>
<i>Copyright (c) 2004, 2005 by Mark Adler<br>Last modified 11 December 2005</i>
<i>Last modified 24 January 2023<br>
Copyright &#169; 2004-2023 Mark Adler</i><br>
<a rel="license" href="http://creativecommons.org/licenses/by-nd/4.0/">
<img alt="Creative Commons License" style="border-width:0"
src="https://i.creativecommons.org/l/by-nd/4.0/88x31.png"></a>
<a rel="license" href="http://creativecommons.org/licenses/by-nd/4.0/">
Creative Commons Attribution-NoDerivatives 4.0 International License</a>.
</body>
</html>

Changes to compat/zlib/examples/zran.c.

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
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
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




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
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
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
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










467
468
469
470
471

472
473
474
475
476
477
478
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
-
-
+
+

-
+




+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-




+

-
+
-

-
-
-
+
+

-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
-
-
-






-
-
-
-
+
+
+
+
+
+
-
-
-
+
-

+
-
-
-
+
+
+
+
+
+




-
-


-
-
-
-
+
+
+
+

-
+





-
-
-
+
+
+
+
+
+
+
+

-
+




-

-
+



-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+

+
+
+
+
+
+
+
+
+
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
-
-
-
+
+
+
+
+
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
-
+
+
+

-
-
+
+


-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+


-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+

-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
-

-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
+
+
+
+
+
-
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+


+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+


-
+





+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+






+
+
+













-
-
-
-
+
+
+
+
+
+

-
+

-
-
+
+


-
-
+
+



+
+
/* zran.c -- example of zlib/gzip stream indexing and random access
 * Copyright (C) 2005, 2012 Mark Adler
/* zran.c -- example of deflate stream indexing and random access
 * Copyright (C) 2005, 2012, 2018, 2023 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
   Version 1.1  29 Sep 2012  Mark Adler */
 * Version 1.4  13 Apr 2023  Mark Adler */

/* Version History:
 1.0  29 May 2005  First version
 1.1  29 Sep 2012  Fix memory reallocation error
 1.2  14 Oct 2018  Handle gzip streams with multiple members
                   Add a header file to facilitate usage in applications
 1.3  18 Feb 2023  Permit raw deflate streams as well as zlib and gzip
                   Permit crossing gzip member boundaries when extracting
                   Support a size_t size when extracting (was an int)
                   Do a binary search over the index for an access point
                   Expose the access point type to enable save and load
 1.4  13 Apr 2023  Add a NOPRIME define to not use inflatePrime()
 */

/* Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary()
   for random access of a compressed file.  A file containing a zlib or gzip
   stream is provided on the command line.  The compressed stream is decoded in
   its entirety, and an index built with access points about every SPAN bytes
   in the uncompressed output.  The compressed file is left open, and can then
   be read randomly, having to decompress on the average SPAN/2 uncompressed
   bytes before getting to the desired block of data.

   An access point can be created at the start of any deflate block, by saving
   the starting file offset and bit of that block, and the 32K bytes of
   uncompressed data that precede that block.  Also the uncompressed offset of
   that block is saved to provide a referece for locating a desired starting
   point in the uncompressed stream.  build_index() works by decompressing the
   input zlib or gzip stream a block at a time, and at the end of each block
   deciding if enough uncompressed data has gone by to justify the creation of
   a new access point.  If so, that point is saved in a data structure that
   grows as needed to accommodate the points.

   To use the index, an offset in the uncompressed data is provided, for which
   the latest access point at or preceding that offset is located in the index.
   The input file is positioned to the specified location in the index, and if
   necessary the first few bits of the compressed data is read from the file.
   inflate is initialized with those bits and the 32K of uncompressed data, and
   the decompression then proceeds until the desired offset in the file is
   reached.  Then the decompression continues to read the desired uncompressed
   data from the file.

// Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary()
// for random access of a compressed file. A file containing a raw deflate
// stream is provided on the command line. The compressed stream is decoded in
// its entirety, and an index built with access points about every SPAN bytes
// in the uncompressed output. The compressed file is left open, and can then
// be read randomly, having to decompress on the average SPAN/2 uncompressed
// bytes before getting to the desired block of data.
//
// An access point can be created at the start of any deflate block, by saving
// the starting file offset and bit of that block, and the 32K bytes of
// uncompressed data that precede that block. Also the uncompressed offset of
// that block is saved to provide a reference for locating a desired starting
// point in the uncompressed stream. deflate_index_build() decompresses the
// input raw deflate stream a block at a time, and at the end of each block
// decides if enough uncompressed data has gone by to justify the creation of a
// new access point. If so, that point is saved in a data structure that grows
// as needed to accommodate the points.
//
// To use the index, an offset in the uncompressed data is provided, for which
// the latest access point at or preceding that offset is located in the index.
// The input file is positioned to the specified location in the index, and if
// necessary the first few bits of the compressed data is read from the file.
// inflate is initialized with those bits and the 32K of uncompressed data, and
// decompression then proceeds until the desired offset in the file is reached.
// Then decompression continues to read the requested uncompressed data from
// the file.
//
   Another approach would be to generate the index on demand.  In that case,
   requests for random access reads from the compressed data would try to use
   the index, but if a read far enough past the end of the index is required,
   then further index entries would be generated and added.

   There is some fair bit of overhead to starting inflation for the random
   access, mainly copying the 32K byte dictionary.  So if small pieces of the
   file are being accessed, it would make sense to implement a cache to hold
   some lookahead and avoid many calls to extract() for small lengths.

   Another way to build an index would be to use inflateCopy().  That would
   not be constrained to have access points at block boundaries, but requires
   more memory per access point, and also cannot be saved to file due to the
   use of pointers in the state.  The approach here allows for storage of the
   index in a file.
// There is some fair bit of overhead to starting inflation for the random
// access, mainly copying the 32K byte dictionary. If small pieces of the file
// are being accessed, it would make sense to implement a cache to hold some
// lookahead to avoid many calls to deflate_index_extract() for small lengths.
//
// Another way to build an index would be to use inflateCopy(). That would not
// be constrained to have access points at block boundaries, but would require
// more memory per access point, and could not be saved to a file due to the
// use of pointers in the state. The approach here allows for storage of the
// index in a file.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "zlib.h"

#include "zran.h"
#define local static

#define SPAN 1048576L       /* desired distance between access points */
#define WINSIZE 32768U      /* sliding window size */
#define CHUNK 16384         /* file input buffer size */
#define WINSIZE 32768U      // sliding window size
#define CHUNK 16384         // file input buffer size

/* access point entry */
struct point {
    off_t out;          /* corresponding offset in uncompressed data */
    off_t in;           /* offset in input file of first full byte */
    int bits;           /* number of bits (1-7) from byte at in - 1, or 0 */
    unsigned char window[WINSIZE];  /* preceding 32K of uncompressed data */
};

// See comments in zran.h.
/* access point list */
struct access {
    int have;           /* number of list entries filled in */
    int size;           /* number of list entries allocated */
    struct point *list; /* allocated list */
};

void deflate_index_free(struct deflate_index *index) {
/* Deallocate an index built by build_index() */
local void free_index(struct access *index)
{
    if (index != NULL) {
        free(index->list);
        free(index);
    }
}

/* Add an entry to the access point list.  If out of memory, deallocate the
   existing list and return NULL. */
local struct access *addpoint(struct access *index, int bits,
    off_t in, off_t out, unsigned left, unsigned char *window)
// Add an access point to the list. If out of memory, deallocate the existing
// list and return NULL. index->mode is temporarily the allocated number of
// access points, until it is time for deflate_index_build() to return. Then
// index->mode is set to the mode of inflation.
static struct deflate_index *add_point(struct deflate_index *index, int bits,
                                       off_t in, off_t out, unsigned left,
{
    struct point *next;

                                       unsigned char *window) {
    /* if list is empty, create it (start with eight points) */
    if (index == NULL) {
        // The list is empty. Create it, starting with eight access points.
        index = malloc(sizeof(struct access));
        if (index == NULL) return NULL;
        index->list = malloc(sizeof(struct point) << 3);
        index = malloc(sizeof(struct deflate_index));
        if (index == NULL)
            return NULL;
        index->have = 0;
        index->mode = 8;
        index->list = malloc(sizeof(point_t) * index->mode);
        if (index->list == NULL) {
            free(index);
            return NULL;
        }
        index->size = 8;
        index->have = 0;
    }

    /* if list is full, make it bigger */
    else if (index->have == index->size) {
        index->size <<= 1;
        next = realloc(index->list, sizeof(struct point) * index->size);
    else if (index->have == index->mode) {
        // The list is full. Make it bigger.
        index->mode <<= 1;
        point_t *next = realloc(index->list, sizeof(point_t) * index->mode);
        if (next == NULL) {
            free_index(index);
            deflate_index_free(index);
            return NULL;
        }
        index->list = next;
    }

    /* fill in entry and increment how many we have */
    next = index->list + index->have;
    next->bits = bits;
    // Fill in the access point and increment how many we have.
    point_t *next = (point_t *)(index->list) + index->have++;
    if (index->have < 0) {
        // Overflowed the int!
        deflate_index_free(index);
        return NULL;
    }
    next->out = out;
    next->in = in;
    next->out = out;
    next->bits = bits;
    if (left)
        memcpy(next->window, window + WINSIZE - left, left);
    if (left < WINSIZE)
        memcpy(next->window + left, window, WINSIZE - left);
    index->have++;

    /* return list, possibly reallocated */
    // Return the index, which may have been newly allocated or destroyed.
    return index;
}

/* Make one entire pass through the compressed stream and build an index, with
   access points about every span bytes of uncompressed output -- span is
   chosen to balance the speed of random access against the memory requirements
   of the list, about 32K bytes per access point.  Note that data after the end
   of the first zlib or gzip stream in the file is ignored.  build_index()
   returns the number of access points on success (>= 1), Z_MEM_ERROR for out
// Decompression modes. These are the inflateInit2() windowBits parameter.
#define RAW -15
#define ZLIB 15
#define GZIP 31

// See comments in zran.h.
   of memory, Z_DATA_ERROR for an error in the input file, or Z_ERRNO for a
   file read error.  On success, *built points to the resulting index. */
local int build_index(FILE *in, off_t span, struct access **built)
{
    int ret;
int deflate_index_build(FILE *in, off_t span, struct deflate_index **built) {
    // Set up inflation state.
    z_stream strm = {0};        // inflate engine (gets fired up later)
    unsigned char buf[CHUNK];   // input buffer
    unsigned char win[WINSIZE] = {0};   // output sliding window
    off_t totin = 0;            // total bytes read from input
    off_t totout = 0;           // total bytes uncompressed
    int mode = 0;               // mode: RAW, ZLIB, or GZIP (0 => not set yet)

    // Decompress from in, generating access points along the way.
    int ret;                    // the return value from zlib, or Z_ERRNO
    off_t totin, totout;        /* our own total counters to avoid 4GB limit */
    off_t last;                 /* totout value of last access point */
    struct access *index;       /* access points being generated */
    z_stream strm;
    off_t last;                 // last access point uncompressed offset
    struct deflate_index *index = NULL;     // list of access points
    do {
        // Assure available input, at least until reaching EOF.
        if (strm.avail_in == 0) {
            strm.avail_in = fread(buf, 1, sizeof(buf), in);
            totin += strm.avail_in;
            strm.next_in = buf;
    unsigned char input[CHUNK];
    unsigned char window[WINSIZE];

    /* initialize inflate */
            if (strm.avail_in < sizeof(buf) && ferror(in)) {
                ret = Z_ERRNO;
                break;
            }

    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
            if (mode == 0) {
    strm.opaque = Z_NULL;
    strm.avail_in = 0;
    strm.next_in = Z_NULL;
    ret = inflateInit2(&strm, 47);      /* automatic zlib or gzip decoding */
    if (ret != Z_OK)
        return ret;

    /* inflate the input, maintain a sliding window, and build an index -- this
       also validates the integrity of the compressed data using the check
       information at the end of the gzip or zlib stream */
                // At the start of the input -- determine the type. Assume raw
                // if it is neither zlib nor gzip. This could in theory result
                // in a false positive for zlib, but in practice the fill bits
                // after a stored block are always zeros, so a raw stream won't
                // start with an 8 in the low nybble.
                mode = strm.avail_in == 0 ? RAW :       // empty -- will fail
                       (strm.next_in[0] & 0xf) == 8 ? ZLIB :
                       strm.next_in[0] == 0x1f ? GZIP :
                       /* else */ RAW;
                ret = inflateInit2(&strm, mode);
                if (ret != Z_OK)
                    break;
            }
        }

        // Assure available output. This rotates the output through, for use as
        // a sliding window on the uncompressed data.
        if (strm.avail_out == 0) {
            strm.avail_out = sizeof(win);
            strm.next_out = win;
        }

        if (mode == RAW && index == NULL)
            // We skip the inflate() call at the start of raw deflate data in
            // order generate an access point there. Set data_type to imitate
            // the end of a header.
    totin = totout = last = 0;
    index = NULL;               /* will be allocated by first addpoint() */
    strm.avail_out = 0;
    do {
        /* get some compressed data from input file */
        strm.avail_in = fread(input, 1, CHUNK, in);
            strm.data_type = 0x80;
        else {
            // Inflate and update the number of uncompressed bytes.
            unsigned before = strm.avail_out;
        if (ferror(in)) {
            ret = Z_ERRNO;
            goto build_index_error;
            ret = inflate(&strm, Z_BLOCK);
            totout += before - strm.avail_out;
        }

        if ((strm.data_type & 0xc0) == 0x80 &&
            (index == NULL || totout - last >= span)) {
            // We are at the end of a header or a non-last deflate block, so we
            // can add an access point here. Furthermore, we are either at the
            // very start for the first access point, or there has been span or
            // more uncompressed bytes since the last access point, so we want
            // to add an access point here.
            index = add_point(index, strm.data_type & 7, totin - strm.avail_in,
        if (strm.avail_in == 0) {
            ret = Z_DATA_ERROR;
                              totout, strm.avail_out, win);
            if (index == NULL) {
                ret = Z_MEM_ERROR;
            goto build_index_error;
        }
        strm.next_in = input;

        /* process all of that, or until end of stream */
                break;
            }
            last = totout;
        }

        do {
            /* reset sliding window if necessary */
            if (strm.avail_out == 0) {
                strm.avail_out = WINSIZE;
                strm.next_out = window;
            }
        if (ret == Z_STREAM_END && mode == GZIP &&
            (strm.avail_in || ungetc(getc(in), in) != EOF))
            // There is more input after the end of a gzip member. Reset the
            // inflate state to read another gzip member. On success, this will
            // set ret to Z_OK to continue decompressing.
            ret = inflateReset2(&strm, GZIP);

        // Keep going until Z_STREAM_END or error. If the compressed data ends
        // prematurely without a file read error, Z_BUF_ERROR is returned.
    } while (ret == Z_OK);
    inflateEnd(&strm);

            /* inflate until out of input, output, or at end of block --
               update the total input and output counters */
            totin += strm.avail_in;
    if (ret != Z_STREAM_END) {
        // An error was encountered. Discard the index and return a negative
        // error code.
        deflate_index_free(index);
            totout += strm.avail_out;
            ret = inflate(&strm, Z_BLOCK);      /* return at end of block */
            totin -= strm.avail_in;
            totout -= strm.avail_out;
            if (ret == Z_NEED_DICT)
                ret = Z_DATA_ERROR;
        return ret == Z_NEED_DICT ? Z_DATA_ERROR : ret;
    }

            if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
                goto build_index_error;
            if (ret == Z_STREAM_END)
    // Shrink the index to only the occupied access points and return it.
    index->mode = mode;
    index->length = totout;
    point_t *list = realloc(index->list, sizeof(point_t) * index->have);
    if (list == NULL) {
                break;

        // Seems like a realloc() to make something smaller should always work,
        // but just in case.
        deflate_index_free(index);
        return Z_MEM_ERROR;
    }
            /* if at end of block, consider adding an index entry (note that if
               data_type indicates an end-of-block, then all of the
               uncompressed data from that block has been delivered, and none
               of the compressed data after that block has been consumed,
               except for up to seven bits) -- the totout == 0 provides an
               entry point after the zlib or gzip header, and assures that the
               index always has at least one access point; we avoid creating an
               access point after the last block by checking bit 6 of data_type
             */
            if ((strm.data_type & 128) && !(strm.data_type & 64) &&
                (totout == 0 || totout - last > span)) {
                index = addpoint(index, strm.data_type & 7, totin,
                                 totout, strm.avail_out, window);
                if (index == NULL) {
                    ret = Z_MEM_ERROR;
                    goto build_index_error;
                }
                last = totout;
            }
        } while (strm.avail_in != 0);
    } while (ret != Z_STREAM_END);

    /* clean up and return index (release unused entries in list) */
    (void)inflateEnd(&strm);
    index->list = list;
    *built = index;
    return index->have;
}

#ifdef NOPRIME
// Support zlib versions before 1.2.3 (July 2005), or incomplete zlib clones
// that do not have inflatePrime().

#  define INFLATEPRIME inflatePreface

// Append the low bits bits of value to in[] at bit position *have, updating
// *have. value must be zero above its low bits bits. bits must be positive.
// This assumes that any bits above the *have bits in the last byte are zeros.
// That assumption is preserved on return, as any bits above *have + bits in
// the last byte written will be set to zeros.
static inline void append_bits(unsigned value, int bits,
                               unsigned char *in, int *have) {
    in += *have >> 3;           // where the first bits from value will go
    int k = *have & 7;          // the number of bits already there
    *have += bits;
    if (k)
        *in |= value << k;      // write value above the low k bits
    else
        *in = value;
    k = 8 - k;                  // the number of bits just appended
    while (bits > k) {
        value >>= k;            // drop the bits appended
        bits -= k;
        k = 8;                  // now at a byte boundary
        *++in = value;
    }
}

// Insert enough bits in the form of empty deflate blocks in front of the
// low bits bits of value, in order to bring the sequence to a byte boundary.
// Then feed that to inflate(). This does what inflatePrime() does, except that
// a negative value of bits is not supported. bits must be in 0..16. If the
// arguments are invalid, Z_STREAM_ERROR is returned. Otherwise the return
// value from inflate() is returned.
    index->list = realloc(index->list, sizeof(struct point) * index->have);
    index->size = index->have;
    *built = index;
    return index->size;
static int inflatePreface(z_stream *strm, int bits, int value) {
    // Check input.
    if (strm == Z_NULL || bits < 0 || bits > 16)
        return Z_STREAM_ERROR;
    if (bits == 0)
        return Z_OK;
    value &= (2 << (bits - 1)) - 1;

    // An empty dynamic block with an odd number of bits (95). The high bit of
    // the last byte is unused.
    static const unsigned char dyn[] = {
        4, 0xe0, 0x81, 8, 0, 0, 0, 0, 0x20, 0xa8, 0xab, 0x1f
    };
    const int dynlen = 95;          // number of bits in the block

    /* return error */
  build_index_error:
    (void)inflateEnd(&strm);
    if (index != NULL)
        free_index(index);
    return ret;
}

/* Use the index to read len bytes from offset into buf, return bytes read or
    // Build an input buffer for inflate that is a multiple of eight bits in
    // length, and that ends with the low bits bits of value.
    unsigned char in[(dynlen + 3 * 10 + 16 + 7) / 8];
    int have = 0;
    if (bits & 1) {
        // Insert an empty dynamic block to get to an odd number of bits, so
        // when bits bits from value are appended, we are at an even number of
        // bits.
        memcpy(in, dyn, sizeof(dyn));
        have = dynlen;
    }
    while ((have + bits) & 7)
        // Insert empty fixed blocks until appending bits bits would put us on
        // a byte boundary. This will insert at most three fixed blocks.
        append_bits(2, 10, in, &have);

    // Append the bits bits from value, which takes us to a byte boundary.
    append_bits(value, bits, in, &have);

    // Deliver the input to inflate(). There is no output space provided, but
    // inflate() can't get stuck waiting on output not ingesting all of the
    // provided input. The reason is that there will be at most 16 bits of
    // input from value after the empty deflate blocks (which themselves
    // generate no output). At least ten bits are needed to generate the first
    // output byte from a fixed block. The last two bytes of the buffer have to
    // be ingested in order to get ten bits, which is the most that value can
    // occupy.
    strm->avail_in = have >> 3;
    strm->next_in = in;
    strm->avail_out = 0;
    strm->next_out = in;                // not used, but can't be NULL
    return inflate(strm, Z_NO_FLUSH);
}

   negative for error (Z_DATA_ERROR or Z_MEM_ERROR).  If data is requested past
   the end of the uncompressed data, then extract() will return a value less
   than len, indicating how much as actually read into buf.  This function
   should not return a data error unless the file was modified since the index
   was generated.  extract() may also return Z_ERRNO if there is an error on
   reading or seeking the input file. */
local int extract(FILE *in, struct access *index, off_t offset,
                  unsigned char *buf, int len)
{
    int ret, skip;
#else
#  define INFLATEPRIME inflatePrime
#endif

// See comments in zran.h.
    z_stream strm;
    struct point *here;
    unsigned char input[CHUNK];
ptrdiff_t deflate_index_extract(FILE *in, struct deflate_index *index,
                                off_t offset, unsigned char *buf, size_t len) {
    unsigned char discard[WINSIZE];
    // Do a quick sanity check on the index.
    if (index == NULL || index->have < 1 || index->list[0].out != 0)
        return Z_STREAM_ERROR;

    /* proceed only if something reasonable to do */
    if (len < 0)
    // If nothing to extract, return zero bytes extracted.
    if (len == 0 || offset < 0 || offset >= index->length)
        return 0;

    /* find where in stream to start */
    here = index->list;
    ret = index->have;
    while (--ret && here[1].out <= offset)
        here++;

    /* initialize file and inflate state to start there */
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    // Find the access point closest to but not after offset.
    int lo = -1, hi = index->have;
    point_t *point = index->list;
    while (hi - lo > 1) {
        int mid = (lo + hi) >> 1;
        if (offset < point[mid].out)
            hi = mid;
        else
            lo = mid;
    }
    point += lo;

    // Initialize the input file and prime the inflate engine to start there.
    int ret = fseeko(in, point->in - (point->bits ? 1 : 0), SEEK_SET);
    if (ret == -1)
        return Z_ERRNO;
    strm.opaque = Z_NULL;
    strm.avail_in = 0;
    strm.next_in = Z_NULL;
    ret = inflateInit2(&strm, -15);         /* raw inflate */
    int ch = 0;
    if (point->bits && (ch = getc(in)) == EOF)
        return ferror(in) ? Z_ERRNO : Z_BUF_ERROR;
    z_stream strm = {0};
    ret = inflateInit2(&strm, RAW);
    if (ret != Z_OK)
        return ret;
    ret = fseeko(in, here->in - (here->bits ? 1 : 0), SEEK_SET);
    if (ret == -1)
        goto extract_ret;
    if (here->bits) {
        ret = getc(in);
        if (ret == -1) {
    if (point->bits)
        INFLATEPRIME(&strm, point->bits, ch >> (8 - point->bits));
    inflateSetDictionary(&strm, point->window, WINSIZE);

    // Skip uncompressed bytes until offset reached, then satisfy request.
    unsigned char input[CHUNK];
    unsigned char discard[WINSIZE];
    offset -= point->out;       // number of bytes to skip to get to offset
    size_t left = len;          // number of bytes left to read after offset
    do {
        if (offset) {
            ret = ferror(in) ? Z_ERRNO : Z_DATA_ERROR;
            goto extract_ret;
            // Discard up to offset uncompressed bytes.
            strm.avail_out = offset < WINSIZE ? (unsigned)offset : WINSIZE;
            strm.next_out = discard;
        }
        (void)inflatePrime(&strm, here->bits, ret >> (8 - here->bits));
    }
    (void)inflateSetDictionary(&strm, here->window, WINSIZE);

        else {
            // Uncompress up to left bytes into buf.
            strm.avail_out = left < UINT_MAX ? (unsigned)left : UINT_MAX;
            strm.next_out = buf + len - left;
        }

        // Uncompress, setting got to the number of bytes uncompressed.
        if (strm.avail_in == 0) {
            // Assure available input.
            strm.avail_in = fread(input, 1, CHUNK, in);
            if (strm.avail_in < CHUNK && ferror(in)) {
                ret = Z_ERRNO;
                break;
            }
    /* skip uncompressed bytes until offset reached, then satisfy request */
    offset -= here->out;
    strm.avail_in = 0;
    skip = 1;                               /* while skipping to offset */
    do {
        /* define where to put uncompressed data, and how much */
        if (offset == 0 && skip) {          /* at offset now */
            strm.avail_out = len;
            strm.next_out = buf;
            strm.next_in = input;
            skip = 0;                       /* only do this once */
        }
        if (offset > WINSIZE) {             /* skip WINSIZE bytes */
            strm.avail_out = WINSIZE;
            strm.next_out = discard;
            offset -= WINSIZE;
        }
        else if (offset != 0) {             /* last skip */
        unsigned got = strm.avail_out;
        ret = inflate(&strm, Z_NO_FLUSH);
        got -= strm.avail_out;

        // Update the appropriate count.
        if (offset)
            strm.avail_out = (unsigned)offset;
            strm.next_out = discard;
            offset = 0;
        }

            offset -= got;
        else
            left -= got;

        // If we're at the end of a gzip member and there's more to read,
        /* uncompress until avail_out filled, or end of stream */
        do {
            if (strm.avail_in == 0) {
                strm.avail_in = fread(input, 1, CHUNK, in);
        // continue to the next gzip member.
        if (ret == Z_STREAM_END && index->mode == GZIP) {
            // Discard the gzip trailer.
            unsigned drop = 8;              // length of gzip trailer
            if (strm.avail_in >= drop) {
                strm.avail_in -= drop;
                if (ferror(in)) {
                    ret = Z_ERRNO;
                    goto extract_ret;
                }
                if (strm.avail_in == 0) {
                    ret = Z_DATA_ERROR;
                    goto extract_ret;
                }
                strm.next_in = input;
            }
                strm.next_in += drop;
            }
            else {
                // Read and discard the remainder of the gzip trailer.
                drop -= strm.avail_in;
                strm.avail_in = 0;
                do {
                    if (getc(in) == EOF)
                        // The input does not have a complete trailer.
                        return ferror(in) ? Z_ERRNO : Z_BUF_ERROR;
                } while (--drop);
            }

            if (strm.avail_in || ungetc(getc(in), in) != EOF) {
                // There's more after the gzip trailer. Use inflate to skip the
                // gzip header and resume the raw inflate there.
                inflateReset2(&strm, GZIP);
                do {
                    if (strm.avail_in == 0) {
                        strm.avail_in = fread(input, 1, CHUNK, in);
                        if (strm.avail_in < CHUNK && ferror(in)) {
                            ret = Z_ERRNO;
                            break;
                        }
                        strm.next_in = input;
                    }
            ret = inflate(&strm, Z_NO_FLUSH);       /* normal inflate */
            if (ret == Z_NEED_DICT)
                ret = Z_DATA_ERROR;
            if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
                goto extract_ret;
            if (ret == Z_STREAM_END)
                break;
        } while (strm.avail_out != 0);

                    strm.avail_out = WINSIZE;
                    strm.next_out = discard;
        /* if reach end of stream, then don't keep trying to get more */
        if (ret == Z_STREAM_END)
            break;

                    ret = inflate(&strm, Z_BLOCK);  // stop at end of header
                } while (ret == Z_OK && (strm.data_type & 0x80) == 0);
                if (ret != Z_OK)
                    break;
                inflateReset2(&strm, RAW);
        /* do until offset reached and requested data read, or stream ends */
    } while (skip);

            }
    /* compute number of uncompressed bytes read after offset */
    ret = skip ? 0 : len - strm.avail_out;

    /* clean up and return bytes read or error */
  extract_ret:
    (void)inflateEnd(&strm);
    return ret;
        }

        // Continue until we have the requested data, the deflate data has
        // ended, or an error is encountered.
    } while (ret == Z_OK && left);
    inflateEnd(&strm);

    // Return the number of uncompressed bytes read into buf, or the error.
    return ret == Z_OK || ret == Z_STREAM_END ? len - left : ret;
}

#ifdef TEST
/* Demonstrate the use of build_index() and extract() by processing the file
   provided on the command line, and the extracting 16K from about 2/3rds of
   the way through the uncompressed output, and writing that to stdout. */
int main(int argc, char **argv)

#define SPAN 1048576L       // desired distance between access points
#define LEN 16384           // number of bytes to extract

// Demonstrate the use of deflate_index_build() and deflate_index_extract() by
// processing the file provided on the command line, and extracting LEN bytes
// from 2/3rds of the way through the uncompressed output, writing that to
// stdout. An offset can be provided as the second argument, in which case the
// data is extracted from there instead.
int main(int argc, char **argv) {
{
    int len;
    off_t offset;
    FILE *in;
    struct access *index = NULL;
    unsigned char buf[CHUNK];

    /* open input file */
    if (argc != 2) {
        fprintf(stderr, "usage: zran file.gz\n");
    // Open the input file.
    if (argc < 2 || argc > 3) {
        fprintf(stderr, "usage: zran file.raw [offset]\n");
        return 1;
    }
    in = fopen(argv[1], "rb");
    FILE *in = fopen(argv[1], "rb");
    if (in == NULL) {
        fprintf(stderr, "zran: could not open %s for reading\n", argv[1]);
        return 1;
    }

    // Get optional offset.
    off_t offset = -1;
    if (argc == 3) {
        char *end;
        offset = strtoll(argv[2], &end, 10);
        if (*end || offset < 0) {
            fprintf(stderr, "zran: %s is not a valid offset\n", argv[2]);
            return 1;
        }
    }

    /* build index */
    len = build_index(in, SPAN, &index);
    // Build index.
    struct deflate_index *index = NULL;
    int len = deflate_index_build(in, SPAN, &index);
    if (len < 0) {
        fclose(in);
        switch (len) {
        case Z_MEM_ERROR:
            fprintf(stderr, "zran: out of memory\n");
            break;
        case Z_BUF_ERROR:
            fprintf(stderr, "zran: %s ended prematurely\n", argv[1]);
            break;
        case Z_DATA_ERROR:
            fprintf(stderr, "zran: compressed data error in %s\n", argv[1]);
            break;
        case Z_ERRNO:
            fprintf(stderr, "zran: read error on %s\n", argv[1]);
            break;
        default:
            fprintf(stderr, "zran: error %d while building index\n", len);
        }
        return 1;
    }
    fprintf(stderr, "zran: built index with %d access points\n", len);

    /* use index by reading some bytes from an arbitrary offset */
    offset = (index->list[index->have - 1].out << 1) / 3;
    len = extract(in, index, offset, buf, CHUNK);
    if (len < 0)
    // Use index by reading some bytes from an arbitrary offset.
    unsigned char buf[LEN];
    if (offset == -1)
        offset = ((index->length + 1) << 1) / 3;
    ptrdiff_t got = deflate_index_extract(in, index, offset, buf, LEN);
    if (got < 0)
        fprintf(stderr, "zran: extraction failed: %s error\n",
                len == Z_MEM_ERROR ? "out of memory" : "input corrupted");
                got == Z_MEM_ERROR ? "out of memory" : "input corrupted");
    else {
        fwrite(buf, 1, len, stdout);
        fprintf(stderr, "zran: extracted %d bytes at %llu\n", len, offset);
        fwrite(buf, 1, got, stdout);
        fprintf(stderr, "zran: extracted %ld bytes at %lld\n", got, offset);
    }

    /* clean up and exit */
    free_index(index);
    // Clean up and exit.
    deflate_index_free(index);
    fclose(in);
    return 0;
}

#endif

Added compat/zlib/examples/zran.h.




















































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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/* zran.h -- example of deflated stream indexing and random access
 * Copyright (C) 2005, 2012, 2018, 2023 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 * Version 1.3  18 Feb 2023  Mark Adler */

#include <stdio.h>
#include "zlib.h"

// Access point.
typedef struct point {
    off_t out;          // offset in uncompressed data
    off_t in;           // offset in compressed file of first full byte
    int bits;           // 0, or number of bits (1-7) from byte at in-1
    unsigned char window[32768];    // preceding 32K of uncompressed data
} point_t;

// Access point list.
struct deflate_index {
    int have;           // number of access points in list
    int mode;           // -15 for raw, 15 for zlib, or 31 for gzip
    off_t length;       // total length of uncompressed data
    point_t *list;      // allocated list of access points
};

// Make one pass through a zlib, gzip, or raw deflate compressed stream and
// build an index, with access points about every span bytes of uncompressed
// output. gzip files with multiple members are fully indexed. span should be
// chosen to balance the speed of random access against the memory requirements
// of the list, which is about 32K bytes per access point. The return value is
// the number of access points on success (>= 1), Z_MEM_ERROR for out of
// memory, Z_BUF_ERROR for a premature end of input, Z_DATA_ERROR for a format
// or verification error in the input file, or Z_ERRNO for a file read error.
// On success, *built points to the resulting index.
int deflate_index_build(FILE *in, off_t span, struct deflate_index **built);

// Use the index to read len bytes from offset into buf. Return the number of
// bytes read or a negative error code. If data is requested past the end of
// the uncompressed data, then deflate_index_extract() will return a value less
// than len, indicating how much was actually read into buf. If given a valid
// index, this function should not return an error unless the file was modified
// somehow since the index was generated, given that deflate_index_build() had
// validated all of the input. If nevertheless there is a failure, Z_BUF_ERROR
// is returned if the compressed data ends prematurely, Z_DATA_ERROR if the
// deflate compressed data is not valid, Z_MEM_ERROR if out of memory,
// Z_STREAM_ERROR if the index is not valid, or Z_ERRNO if there is an error
// reading or seeking on the input file.
ptrdiff_t deflate_index_extract(FILE *in, struct deflate_index *index,
                                off_t offset, unsigned char *buf, size_t len);

// Deallocate an index built by deflate_index_build().
void deflate_index_free(struct deflate_index *index);

Changes to compat/zlib/gzclose.c.

1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10

11


12
13
14
15
16
17
18










-
+
-
-







/* gzclose.c -- zlib gzclose() function
 * Copyright (C) 2004, 2010 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#include "gzguts.h"

/* gzclose() is in a separate file so that it is linked in only if it is used.
   That way the other gzclose functions can be used instead to avoid linking in
   unneeded compression or decompression routines. */
int ZEXPORT gzclose(file)
int ZEXPORT gzclose(gzFile file) {
    gzFile file;
{
#ifndef NO_GZCOMPRESS
    gz_statep state;

    if (file == NULL)
        return Z_STREAM_ERROR;
    state = (gz_statep)file;

Changes to compat/zlib/gzguts.h.

1
2

3
4
5
6
7
8
9
10
11


12
13
14
15
16
17
18
19
1

2
3
4
5
6
7
8
9


10
11

12
13
14
15
16
17
18

-
+







-
-
+
+
-







/* gzguts.h -- zlib internal header definitions for gz* operations
 * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
 * Copyright (C) 2004-2024 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#ifdef _LARGEFILE64_SOURCE
#  ifndef _LARGEFILE_SOURCE
#    define _LARGEFILE_SOURCE 1
#  endif
#  ifdef _FILE_OFFSET_BITS
#    undef _FILE_OFFSET_BITS
#  undef _FILE_OFFSET_BITS
#  undef _TIME_BITS
#  endif
#endif

#ifdef HAVE_HIDDEN
#  define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
#else
#  define ZLIB_INTERNAL
#endif
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48







-
+







#  include <stddef.h>
#endif

#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
#  include <io.h>
#endif

#if defined(_WIN32) || defined(__CYGWIN__)
#if defined(_WIN32)
#  define WIDECHAR
#endif

#ifdef WINAPI_FAMILY
#  define open _open
#  define read _read
#  define write _write
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
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







-
-
+
+

















-
-
-
-
+
+
+
+







#endif
/* since "static" is used to mean two completely different things in C, we
   define "local" for the non-static meaning of "static", for readability
   (compile with -Dlocal if your debugger can't find static symbols) */

/* gz* functions always use library allocation functions */
#ifndef STDC
  extern voidp  malloc OF((uInt size));
  extern void   free   OF((voidpf ptr));
  extern voidp  malloc(uInt size);
  extern void   free(voidpf ptr);
#endif

/* get errno and strerror definition */
#if defined UNDER_CE
#  include <windows.h>
#  define zstrerror() gz_strwinerror((DWORD)GetLastError())
#else
#  ifndef NO_STRERROR
#    include <errno.h>
#    define zstrerror() strerror(errno)
#  else
#    define zstrerror() "stdio error (consult errno)"
#  endif
#endif

/* provide prototypes for these when building zlib without LFS */
#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
    ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
    ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
    ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
    ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
    ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *);
    ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int);
    ZEXTERN z_off64_t ZEXPORT gztell64(gzFile);
    ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile);
#endif

/* default memLevel */
#if MAX_MEM_LEVEL >= 8
#  define DEF_MEM_LEVEL 8
#else
#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
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
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








+












-
+

-
+





-
-
-
-
-
+
+
-
    int how;                /* 0: get header, 1: copy, 2: decompress */
    z_off64_t start;        /* where the gzip data started, for rewinding */
    int eof;                /* true if end of input file reached */
    int past;               /* true if read requested past end */
        /* just for writing */
    int level;              /* compression level */
    int strategy;           /* compression strategy */
    int reset;              /* true if a reset is pending after a Z_FINISH */
        /* seek request */
    z_off64_t skip;         /* amount to skip (already rewound if backwards) */
    int seek;               /* true if seek request pending */
        /* error information */
    int err;                /* error code */
    char *msg;              /* error message */
        /* zlib inflate or deflate stream */
    z_stream strm;          /* stream structure in-place (not a pointer) */
} gz_state;
typedef gz_state FAR *gz_statep;

/* shared functions */
void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *));
void ZLIB_INTERNAL gz_error(gz_statep, int, const char *);
#if defined UNDER_CE
char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));
char ZLIB_INTERNAL *gz_strwinerror(DWORD error);
#endif

/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
   value -- needed when comparing unsigned to z_off64_t, which is signed
   (possible z_off64_t types off_t, off64_t, and long are all signed) */
#ifdef INT_MAX
#  define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
#else
unsigned ZLIB_INTERNAL gz_intmax OF((void));
#  define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
unsigned ZLIB_INTERNAL gz_intmax(void);
#define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
#endif

Changes to compat/zlib/gzlib.c.

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
30
31
32
33

34
35
36
37
38
39
40
41
42
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


30
31
32
33
34
35
36

-
+





-
+









-
-
-
-











-
+
-
-







/* gzlib.c -- zlib functions common to reading and writing gzip files
 * Copyright (C) 2004-2017 Mark Adler
 * Copyright (C) 2004-2024 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#include "gzguts.h"

#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__)
#if defined(_WIN32) && !defined(__BORLANDC__)
#  define LSEEK _lseeki64
#else
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
#  define LSEEK lseek64
#else
#  define LSEEK lseek
#endif
#endif

/* Local functions */
local void gz_reset OF((gz_statep));
local gzFile gz_open OF((const void *, int, const char *));

#if defined UNDER_CE

/* Map the Windows error number in ERROR to a locale-dependent error message
   string and return a pointer to it.  Typically, the values for ERROR come
   from GetLastError.

   The string pointed to shall not be modified by the application, but may be
   overwritten by a subsequent call to gz_strwinerror

   The gz_strwinerror function does not change the current setting of
   GetLastError. */
char ZLIB_INTERNAL *gz_strwinerror (error)
char ZLIB_INTERNAL *gz_strwinerror(DWORD error) {
     DWORD error;
{
    static char buf[1024];

    wchar_t *msgbuf;
    DWORD lasterr = GetLastError();
    DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
        | FORMAT_MESSAGE_ALLOCATE_BUFFER,
        NULL,
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
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







-
+
-
-






+
+







-
+
-
-
-
-







    SetLastError(lasterr);
    return buf;
}

#endif /* UNDER_CE */

/* Reset gzip file state */
local void gz_reset(state)
local void gz_reset(gz_statep state) {
    gz_statep state;
{
    state->x.have = 0;              /* no output data available */
    if (state->mode == GZ_READ) {   /* for reading ... */
        state->eof = 0;             /* not at end of file */
        state->past = 0;            /* have not read past end yet */
        state->how = LOOK;          /* look for gzip header */
    }
    else                            /* for writing ... */
        state->reset = 0;           /* no deflateReset pending */
    state->seek = 0;                /* no seek request pending */
    gz_error(state, Z_OK, NULL);    /* clear error */
    state->x.pos = 0;               /* no uncompressed data yet */
    state->strm.avail_in = 0;       /* no input data yet */
}

/* Open a gzip file either by name or file descriptor. */
local gzFile gz_open(path, fd, mode)
local gzFile gz_open(const void *path, int fd, const char *mode) {
    const void *path;
    int fd;
    const char *mode;
{
    gz_statep state;
    z_size_t len;
    int oflag;
#ifdef O_CLOEXEC
    int cloexec = 0;
#endif
#ifdef O_EXCL
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
366

367
368
369
370
371
372
373
374
375
376
377
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







-
-
+
+
-
-
+
+
+
+




-
-
-
-
-
-
-
-
-
+
-
-
-

















-
+
-
-
-





-
+
-
-
-
















-
-
+
+





-
+
-
-




















-
+
-
-
-
-







    gz_reset(state);

    /* return stream */
    return (gzFile)state;
}

/* -- see zlib.h -- */
gzFile ZEXPORT gzopen(path, mode)
    const char *path;
gzFile ZEXPORT gzopen(const char *path, const char *mode) {
    return gz_open(path, -1, mode);
    const char *mode;
{
}

/* -- see zlib.h -- */
gzFile ZEXPORT gzopen64(const char *path, const char *mode) {
    return gz_open(path, -1, mode);
}

/* -- see zlib.h -- */
gzFile ZEXPORT gzopen64(path, mode)
    const char *path;
    const char *mode;
{
    return gz_open(path, -1, mode);
}

/* -- see zlib.h -- */
gzFile ZEXPORT gzdopen(fd, mode)
gzFile ZEXPORT gzdopen(int fd, const char *mode) {
    int fd;
    const char *mode;
{
    char *path;         /* identifier for error messages */
    gzFile gz;

    if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
        return NULL;
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
    (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
#else
    sprintf(path, "<fd:%d>", fd);   /* for debugging */
#endif
    gz = gz_open(path, fd, mode);
    free(path);
    return gz;
}

/* -- see zlib.h -- */
#ifdef WIDECHAR
gzFile ZEXPORT gzopen_w(path, mode)
gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) {
    const wchar_t *path;
    const char *mode;
{
    return gz_open(path, -2, mode);
}
#endif

/* -- see zlib.h -- */
int ZEXPORT gzbuffer(file, size)
int ZEXPORT gzbuffer(gzFile file, unsigned size) {
    gzFile file;
    unsigned size;
{
    gz_statep state;

    /* get internal structure and check integrity */
    if (file == NULL)
        return -1;
    state = (gz_statep)file;
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
        return -1;

    /* make sure we haven't already allocated memory */
    if (state->size != 0)
        return -1;

    /* check and set requested size */
    if ((size << 1) < size)
        return -1;              /* need to be able to double it */
    if (size < 2)
        size = 2;               /* need two bytes to check magic header */
    if (size < 8)
        size = 8;               /* needed to behave well with flushing */
    state->want = size;
    return 0;
}

/* -- see zlib.h -- */
int ZEXPORT gzrewind(file)
int ZEXPORT gzrewind(gzFile file) {
    gzFile file;
{
    gz_statep state;

    /* get internal structure */
    if (file == NULL)
        return -1;
    state = (gz_statep)file;

    /* check that we're reading and that there's no error */
    if (state->mode != GZ_READ ||
            (state->err != Z_OK && state->err != Z_BUF_ERROR))
        return -1;

    /* back up and start over */
    if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
        return -1;
    gz_reset(state);
    return 0;
}

/* -- see zlib.h -- */
z_off64_t ZEXPORT gzseek64(file, offset, whence)
z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) {
    gzFile file;
    z_off64_t offset;
    int whence;
{
    unsigned n;
    z_off64_t ret;
    gz_statep state;

    /* get internal structure and check integrity */
    if (file == NULL)
        return -1;
393
394
395
396
397
398
399
400

401
402
403
404
405
406
407
362
363
364
365
366
367
368

369
370
371
372
373
374
375
376







-
+







    else if (state->seek)
        offset += state->skip;
    state->seek = 0;

    /* if within raw area while reading, just go there */
    if (state->mode == GZ_READ && state->how == COPY &&
            state->x.pos + offset >= 0) {
        ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
        ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR);
        if (ret == -1)
            return -1;
        state->x.have = 0;
        state->eof = 0;
        state->past = 0;
        state->seek = 0;
        gz_error(state, Z_OK, NULL);
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
467
468
469
470
471
472

473
474
475
476
477
478
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
558
559
560
561
562
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
467
468
469
470
471

472


473
474
475
476
477
478
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







-
+
-
-
-
-







-
+
-
-














-
+
-
-







-
+
-
-




















-
+
-
-







-
+
-
-














-
+
-
-
-

















-
+
-
-







        state->seek = 1;
        state->skip = offset;
    }
    return state->x.pos + offset;
}

/* -- see zlib.h -- */
z_off_t ZEXPORT gzseek(file, offset, whence)
z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) {
    gzFile file;
    z_off_t offset;
    int whence;
{
    z_off64_t ret;

    ret = gzseek64(file, (z_off64_t)offset, whence);
    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
}

/* -- see zlib.h -- */
z_off64_t ZEXPORT gztell64(file)
z_off64_t ZEXPORT gztell64(gzFile file) {
    gzFile file;
{
    gz_statep state;

    /* get internal structure and check integrity */
    if (file == NULL)
        return -1;
    state = (gz_statep)file;
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
        return -1;

    /* return position */
    return state->x.pos + (state->seek ? state->skip : 0);
}

/* -- see zlib.h -- */
z_off_t ZEXPORT gztell(file)
z_off_t ZEXPORT gztell(gzFile file) {
    gzFile file;
{
    z_off64_t ret;

    ret = gztell64(file);
    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
}

/* -- see zlib.h -- */
z_off64_t ZEXPORT gzoffset64(file)
z_off64_t ZEXPORT gzoffset64(gzFile file) {
    gzFile file;
{
    z_off64_t offset;
    gz_statep state;

    /* get internal structure and check integrity */
    if (file == NULL)
        return -1;
    state = (gz_statep)file;
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
        return -1;

    /* compute and return effective offset in file */
    offset = LSEEK(state->fd, 0, SEEK_CUR);
    if (offset == -1)
        return -1;
    if (state->mode == GZ_READ)             /* reading */
        offset -= state->strm.avail_in;     /* don't count buffered input */
    return offset;
}

/* -- see zlib.h -- */
z_off_t ZEXPORT gzoffset(file)
z_off_t ZEXPORT gzoffset(gzFile file) {
    gzFile file;
{
    z_off64_t ret;

    ret = gzoffset64(file);
    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
}

/* -- see zlib.h -- */
int ZEXPORT gzeof(file)
int ZEXPORT gzeof(gzFile file) {
    gzFile file;
{
    gz_statep state;

    /* get internal structure and check integrity */
    if (file == NULL)
        return 0;
    state = (gz_statep)file;
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
        return 0;

    /* return end-of-file state */
    return state->mode == GZ_READ ? state->past : 0;
}

/* -- see zlib.h -- */
const char * ZEXPORT gzerror(file, errnum)
const char * ZEXPORT gzerror(gzFile file, int *errnum) {
    gzFile file;
    int *errnum;
{
    gz_statep state;

    /* get internal structure and check integrity */
    if (file == NULL)
        return NULL;
    state = (gz_statep)file;
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
        return NULL;

    /* return error information */
    if (errnum != NULL)
        *errnum = state->err;
    return state->err == Z_MEM_ERROR ? "out of memory" :
                                       (state->msg == NULL ? "" : state->msg);
}

/* -- see zlib.h -- */
void ZEXPORT gzclearerr(file)
void ZEXPORT gzclearerr(gzFile file) {
    gzFile file;
{
    gz_statep state;

    /* get internal structure and check integrity */
    if (file == NULL)
        return;
    state = (gz_statep)file;
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
572
573
574
575
576
577
578
579

580
581
582
583
584
585
586
587
588
589
590
522
523
524
525
526
527
528

529




530
531
532
533
534
535
536







-
+
-
-
-
-








/* Create an error message in allocated memory and set state->err and
   state->msg accordingly.  Free any previous error message already there.  Do
   not try to free or allocate space if the error is Z_MEM_ERROR (out of
   memory).  Simply save the error message as a static string.  If there is an
   allocation failure constructing the error message, then convert the error to
   out of memory. */
void ZLIB_INTERNAL gz_error(state, err, msg)
void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) {
    gz_statep state;
    int err;
    const char *msg;
{
    /* free previously allocated message and clear */
    if (state->msg != NULL) {
        if (state->err != Z_MEM_ERROR)
            free(state->msg);
        state->msg = NULL;
    }

613
614
615
616
617
618
619
620
621
622
623
624
625

626
627




628
629
630
631
632
633
634
635
636
637

559
560
561
562
563
564
565

566
567
568
569

570


571
572
573
574


575
576
577
578
579
580

581
582







-




-
+
-
-
+
+
+
+
-
-






-

+
#else
    strcpy(state->msg, state->path);
    strcat(state->msg, ": ");
    strcat(state->msg, msg);
#endif
}

#ifndef INT_MAX
/* portably return maximum value for an int (when limits.h presumed not
   available) -- we need to do this to cover cases where 2's complement not
   used, since C standard permits 1's complement and sign-bit representations,
   otherwise we could just use ((unsigned)-1) >> 1 */
unsigned ZLIB_INTERNAL gz_intmax()
unsigned ZLIB_INTERNAL gz_intmax(void) {
{
    unsigned p, q;
#ifdef INT_MAX
    return INT_MAX;
#else
    unsigned p = 1, q;

    p = 1;
    do {
        q = p;
        p <<= 1;
        p++;
    } while (p > q);
    return q >> 1;
}
#endif
}

Changes to compat/zlib/gzread.c.

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
30
31
32
33
1

2
3
4
5
6
7









8
9
10
11



12


13

14
15
16
17
18
19
20

-
+





-
-
-
-
-
-
-
-
-




-
-
-
+
-
-
+
-







/* gzread.c -- zlib functions for reading gzip files
 * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
 * Copyright (C) 2004-2017 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#include "gzguts.h"

/* Local functions */
local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
local int gz_avail OF((gz_statep));
local int gz_look OF((gz_statep));
local int gz_decomp OF((gz_statep));
local int gz_fetch OF((gz_statep));
local int gz_skip OF((gz_statep, z_off64_t));
local z_size_t gz_read OF((gz_statep, voidp, z_size_t));

/* Use read() to load a buffer -- return -1 on error, otherwise 0.  Read from
   state->fd, and update state->eof, state->err, and state->msg as appropriate.
   This function needs to loop on read(), since read() is not guaranteed to
   read the number of bytes requested, depending on the type of descriptor. */
local int gz_load(state, buf, len, have)
    gz_statep state;
    unsigned char *buf;
local int gz_load(gz_statep state, unsigned char *buf, unsigned len,
    unsigned len;
    unsigned *have;
                  unsigned *have) {
{
    int ret;
    unsigned get, max = ((unsigned)-1 >> 2) + 1;

    *have = 0;
    do {
        get = len - *have;
        if (get > max)
49
50
51
52
53
54
55
56

57
58
59
60
61
62
63
64
65
36
37
38
39
40
41
42

43


44
45
46
47
48
49
50







-
+
-
-







/* Load up input buffer and set eof flag if last data loaded -- return -1 on
   error, 0 otherwise.  Note that the eof flag is set when the end of the input
   file is reached, even though there may be unused data in the buffer.  Once
   that data has been used, no more attempts will be made to read the file.
   If strm->avail_in != 0, then the current data is moved to the beginning of
   the input buffer, and then the remainder of the buffer is loaded with the
   available data from the input file. */
local int gz_avail(state)
local int gz_avail(gz_statep state) {
    gz_statep state;
{
    unsigned got;
    z_streamp strm = &(state->strm);

    if (state->err != Z_OK && state->err != Z_BUF_ERROR)
        return -1;
    if (state->eof == 0) {
        if (strm->avail_in) {       /* copy what's there to the start */
84
85
86
87
88
89
90
91

92
93
94
95
96
97
98
99
100
69
70
71
72
73
74
75

76


77
78
79
80
81
82
83







-
+
-
-







   left unchanged if there is no more input data available, will be set to COPY
   if there is no gzip header and direct copying will be performed, or it will
   be set to GZIP for decompression.  If direct copying, then leftover input
   data from the input buffer will be copied to the output buffer.  In that
   case, all further file reads will be directly to either the output buffer or
   a user buffer.  If decompressing, the inflate state will be initialized.
   gz_look() will return 0 on success or -1 on failure. */
local int gz_look(state)
local int gz_look(gz_statep state) {
    gz_statep state;
{
    z_streamp strm = &(state->strm);

    /* allocate read buffers and inflate memory */
    if (state->size == 0) {
        /* allocate buffers */
        state->in = (unsigned char *)malloc(state->want);
        state->out = (unsigned char *)malloc(state->want << 1);
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
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







-
-
-
-
+
+
+
-










-
+
-
-







        return 0;
    }

    /* doing raw i/o, copy any leftover input to output -- this assumes that
       the output buffer is larger than the input buffer, which also assures
       space for gzungetc() */
    state->x.next = state->out;
    if (strm->avail_in) {
        memcpy(state->x.next, strm->next_in, strm->avail_in);
        state->x.have = strm->avail_in;
        strm->avail_in = 0;
    memcpy(state->x.next, strm->next_in, strm->avail_in);
    state->x.have = strm->avail_in;
    strm->avail_in = 0;
    }
    state->how = COPY;
    state->direct = 1;
    return 0;
}

/* Decompress from input to the provided next_out and avail_out in the state.
   On return, state->x.have and state->x.next point to the just decompressed
   data.  If the gzip stream completes, state->how is reset to LOOK to look for
   the next gzip stream or raw data, once state->x.have is depleted.  Returns 0
   on success, -1 on failure. */
local int gz_decomp(state)
local int gz_decomp(gz_statep state) {
    gz_statep state;
{
    int ret = Z_OK;
    unsigned had;
    z_streamp strm = &(state->strm);

    /* fill output buffer up to end of deflate stream */
    had = strm->avail_out;
    do {
222
223
224
225
226
227
228
229

230
231
232
233
234
235
236
237
238
201
202
203
204
205
206
207

208


209
210
211
212
213
214
215







-
+
-
-








/* Fetch data and put it in the output buffer.  Assumes state->x.have is 0.
   Data is either copied from the input file or decompressed from the input
   file depending on state->how.  If state->how is LOOK, then a gzip header is
   looked for to determine whether to copy or decompress.  Returns -1 on error,
   otherwise 0.  gz_fetch() will leave state->how as COPY or GZIP unless the
   end of the input file has been reached and all data has been processed.  */
local int gz_fetch(state)
local int gz_fetch(gz_statep state) {
    gz_statep state;
{
    z_streamp strm = &(state->strm);

    do {
        switch(state->how) {
        case LOOK:      /* -> LOOK, COPY (only if never GZIP), or GZIP */
            if (gz_look(state) == -1)
                return -1;
252
253
254
255
256
257
258
259

260
261
262
263
264
265
266
267
268
269
229
230
231
232
233
234
235

236



237
238
239
240
241
242
243







-
+
-
-
-







                return -1;
        }
    } while (state->x.have == 0 && (!state->eof || strm->avail_in));
    return 0;
}

/* Skip len uncompressed bytes of output.  Return -1 on error, 0 on success. */
local int gz_skip(state, len)
local int gz_skip(gz_statep state, z_off64_t len) {
    gz_statep state;
    z_off64_t len;
{
    unsigned n;

    /* skip over len bytes or reach end-of-file, whichever comes first */
    while (len)
        /* skip over whatever is in output buffer */
        if (state->x.have) {
            n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
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
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







-
+
-
-
-
-


















-
+

-
+







    return 0;
}

/* Read len bytes into buf from file, or less than len up to the end of the
   input.  Return the number of bytes read.  If zero is returned, either the
   end of file was reached, or there was an error.  state->err must be
   consulted in that case to determine which. */
local z_size_t gz_read(state, buf, len)
local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) {
    gz_statep state;
    voidp buf;
    z_size_t len;
{
    z_size_t got;
    unsigned n;

    /* if len is zero, avoid unnecessary operations */
    if (len == 0)
        return 0;

    /* process a skip request */
    if (state->seek) {
        state->seek = 0;
        if (gz_skip(state, state->skip) == -1)
            return 0;
    }

    /* get len bytes to buf, or less than len if at the end */
    got = 0;
    do {
        /* set n to the maximum amount of len that fits in an unsigned int */
        n = -1;
        n = (unsigned)-1;
        if (n > len)
            n = len;
            n = (unsigned)len;

        /* first just try copying data from the output buffer */
        if (state->x.have) {
            if (state->x.have < n)
                n = state->x.have;
            memcpy(buf, state->x.next, n);
            state->x.next += n;
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
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







-
+
-
-
-
-




















-
+










-
+
-
-
-
-
-







    } while (len);

    /* return number of bytes read into user buffer */
    return got;
}

/* -- see zlib.h -- */
int ZEXPORT gzread(file, buf, len)
int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) {
    gzFile file;
    voidp buf;
    unsigned len;
{
    gz_statep state;

    /* get internal structure */
    if (file == NULL)
        return -1;
    state = (gz_statep)file;

    /* check that we're reading and that there's no (serious) error */
    if (state->mode != GZ_READ ||
            (state->err != Z_OK && state->err != Z_BUF_ERROR))
        return -1;

    /* since an int is returned, make sure len fits in one, otherwise return
       with an error (this avoids a flaw in the interface) */
    if ((int)len < 0) {
        gz_error(state, Z_STREAM_ERROR, "request does not fit in an int");
        return -1;
    }

    /* read len or fewer bytes to buf */
    len = gz_read(state, buf, len);
    len = (unsigned)gz_read(state, buf, len);

    /* check for an error */
    if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)
        return -1;

    /* return the number of bytes read (this is assured to fit in an int) */
    return (int)len;
}

/* -- see zlib.h -- */
z_size_t ZEXPORT gzfread(buf, size, nitems, file)
z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, gzFile file) {
    voidp buf;
    z_size_t size;
    z_size_t nitems;
    gzFile file;
{
    z_size_t len;
    gz_statep state;

    /* get internal structure */
    if (file == NULL)
        return 0;
    state = (gz_statep)file;
440
441
442
443
444
445
446
447

448
449
450
451
452
453
454
455
456
457
401
402
403
404
405
406
407

408



409
410
411
412
413
414
415







-
+
-
-
-








/* -- see zlib.h -- */
#ifdef Z_PREFIX_SET
#  undef z_gzgetc
#else
#  undef gzgetc
#endif
int ZEXPORT gzgetc(file)
int ZEXPORT gzgetc(gzFile file) {
    gzFile file;
{
    int ret;
    unsigned char buf[1];
    gz_statep state;

    /* get internal structure */
    if (file == NULL)
        return -1;
    state = (gz_statep)file;
465
466
467
468
469
470
471
472

473
474
475
476

477
478
479
480
481
482
483

484
485
486
487
488
489
490
491
492




493
494
495
496
497
498
499
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







-
+
-


-
+
-
-




-
+
-
-
-






+
+
+
+







    if (state->x.have) {
        state->x.have--;
        state->x.pos++;
        return *(state->x.next)++;
    }

    /* nothing there -- try gz_read() */
    ret = gz_read(state, buf, 1);
    return gz_read(state, buf, 1) < 1 ? -1 : buf[0];
    return ret < 1 ? -1 : buf[0];
}

int ZEXPORT gzgetc_(file)
int ZEXPORT gzgetc_(gzFile file) {
gzFile file;
{
    return gzgetc(file);
}

/* -- see zlib.h -- */
int ZEXPORT gzungetc(c, file)
int ZEXPORT gzungetc(int c, gzFile file) {
    int c;
    gzFile file;
{
    gz_statep state;

    /* get internal structure */
    if (file == NULL)
        return -1;
    state = (gz_statep)file;

    /* in case this was just opened, set up the input buffer */
    if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
        (void)gz_look(state);

    /* check that we're reading and that there's no (serious) error */
    if (state->mode != GZ_READ ||
        (state->err != Z_OK && state->err != Z_BUF_ERROR))
        return -1;

    /* process a skip request */
536
537
538
539
540
541
542
543

544
545
546
547
548
549
550
551
552
553
554
492
493
494
495
496
497
498

499




500
501
502
503
504
505
506







-
+
-
-
-
-







    state->x.next[0] = (unsigned char)c;
    state->x.pos--;
    state->past = 0;
    return c;
}

/* -- see zlib.h -- */
char * ZEXPORT gzgets(file, buf, len)
char * ZEXPORT gzgets(gzFile file, char *buf, int len) {
    gzFile file;
    char *buf;
    int len;
{
    unsigned left, n;
    char *str;
    unsigned char *eol;
    gz_statep state;

    /* check parameters and get internal structure */
    if (file == NULL || buf == NULL || len < 1)
600
601
602
603
604
605
606
607

608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627

628
629
630
631
632
633
634
635
636
552
553
554
555
556
557
558

559


560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576

577


578
579
580
581
582
583
584







-
+
-
-

















-
+
-
-







    if (buf == str)
        return NULL;
    buf[0] = 0;
    return str;
}

/* -- see zlib.h -- */
int ZEXPORT gzdirect(file)
int ZEXPORT gzdirect(gzFile file) {
    gzFile file;
{
    gz_statep state;

    /* get internal structure */
    if (file == NULL)
        return 0;
    state = (gz_statep)file;

    /* if the state is not known, but we can find out, then do so (this is
       mainly for right after a gzopen() or gzdopen()) */
    if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
        (void)gz_look(state);

    /* return 1 if transparent, 0 if processing a gzip stream */
    return state->direct;
}

/* -- see zlib.h -- */
int ZEXPORT gzclose_r(file)
int ZEXPORT gzclose_r(gzFile file) {
    gzFile file;
{
    int ret, err;
    gz_statep state;

    /* get internal structure */
    if (file == NULL)
        return Z_STREAM_ERROR;
    state = (gz_statep)file;

Changes to compat/zlib/gzwrite.c.

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
1

2
3
4
5
6
7






8
9
10

11


12
13
14
15
16
17
18

-
+





-
-
-
-
-
-



-
+
-
-







/* gzwrite.c -- zlib functions for writing gzip files
 * Copyright (C) 2004-2017 Mark Adler
 * Copyright (C) 2004-2019 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#include "gzguts.h"

/* Local functions */
local int gz_init OF((gz_statep));
local int gz_comp OF((gz_statep, int));
local int gz_zero OF((gz_statep, z_off64_t));
local z_size_t gz_write OF((gz_statep, voidpc, z_size_t));

/* Initialize state for writing a gzip file.  Mark initialization by setting
   state->size to non-zero.  Return -1 on a memory allocation failure, or 0 on
   success. */
local int gz_init(state)
local int gz_init(gz_statep state) {
    gz_statep state;
{
    int ret;
    z_streamp strm = &(state->strm);

    /* allocate input buffer (double size for gzprintf) */
    state->in = (unsigned char *)malloc(state->want << 1);
    if (state->in == NULL) {
        gz_error(state, Z_MEM_ERROR, "out of memory");
66
67
68
69
70
71
72
73

74
75
76
77
78
79
80
81
82
83
58
59
60
61
62
63
64

65



66
67
68
69
70
71
72







-
+
-
-
-








/* Compress whatever is at avail_in and next_in and write to the output file.
   Return -1 if there is an error writing to the output file or if gz_init()
   fails to allocate memory, otherwise 0.  flush is assumed to be a valid
   deflate() flush value.  If flush is Z_FINISH, then the deflate() state is
   reset to start a new gzip stream.  If gz->direct is true, then simply write
   to the output file without compressing, and ignore flush. */
local int gz_comp(state, flush)
local int gz_comp(gz_statep state, int flush) {
    gz_statep state;
    int flush;
{
    int ret, writ;
    unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
    z_streamp strm = &(state->strm);

    /* allocate memory if this is the first time through */
    if (state->size == 0 && gz_init(state) == -1)
        return -1;
92
93
94
95
96
97
98









99
100
101
102
103
104
105
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103







+
+
+
+
+
+
+
+
+







                return -1;
            }
            strm->avail_in -= (unsigned)writ;
            strm->next_in += writ;
        }
        return 0;
    }

    /* check for a pending reset */
    if (state->reset) {
        /* don't start a new gzip member unless there is data to write */
        if (strm->avail_in == 0)
            return 0;
        deflateReset(strm);
        state->reset = 0;
    }

    /* run deflate() on provided input until it produces no more output */
    ret = Z_OK;
    do {
        /* write out current buffer contents if full, or if flushing, but if
           doing Z_FINISH then don't write until we get to Z_STREAM_END */
        if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
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
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142

143



144
145
146
147
148
149
150







-
+







-
+
-
-
-







            return -1;
        }
        have -= strm->avail_out;
    } while (have);

    /* if that completed a deflate stream, allow another to start */
    if (flush == Z_FINISH)
        deflateReset(strm);
        state->reset = 1;

    /* all done, no errors */
    return 0;
}

/* Compress len zeros to output.  Return -1 on a write error or memory
   allocation failure by gz_comp(), or 0 on success. */
local int gz_zero(state, len)
local int gz_zero(gz_statep state, z_off64_t len) {
    gz_statep state;
    z_off64_t len;
{
    int first;
    unsigned n;
    z_streamp strm = &(state->strm);

    /* consume whatever's left in the input buffer */
    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
        return -1;
171
172
173
174
175
176
177
178

179
180
181
182
183
184
185
186
187
188
189
166
167
168
169
170
171
172

173




174
175
176
177
178
179
180







-
+
-
-
-
-







        len -= n;
    }
    return 0;
}

/* Write len bytes from buf to file.  Return the number of bytes written.  If
   the returned value is less than len, then there was an error. */
local z_size_t gz_write(state, buf, len)
local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {
    gz_statep state;
    voidpc buf;
    z_size_t len;
{
    z_size_t put = len;

    /* if len is zero, avoid unnecessary operations */
    if (len == 0)
        return 0;

    /* allocate memory if this is the first time through */
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
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







-
+



















-
+













-
+
-
-
-
-








            if (state->strm.avail_in == 0)
                state->strm.next_in = state->in;
            have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
                              state->in);
            copy = state->size - have;
            if (copy > len)
                copy = len;
                copy = (unsigned)len;
            memcpy(state->in + have, buf, copy);
            state->strm.avail_in += copy;
            state->x.pos += copy;
            buf = (const char *)buf + copy;
            len -= copy;
            if (len && gz_comp(state, Z_NO_FLUSH) == -1)
                return 0;
        } while (len);
    }
    else {
        /* consume whatever's left in the input buffer */
        if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
            return 0;

        /* directly compress user buffer to file */
        state->strm.next_in = (z_const Bytef *)buf;
        do {
            unsigned n = (unsigned)-1;
            if (n > len)
                n = len;
                n = (unsigned)len;
            state->strm.avail_in = n;
            state->x.pos += n;
            if (gz_comp(state, Z_NO_FLUSH) == -1)
                return 0;
            len -= n;
        } while (len);
    }

    /* input was all buffered or compressed */
    return put;
}

/* -- see zlib.h -- */
int ZEXPORT gzwrite(file, buf, len)
int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) {
    gzFile file;
    voidpc buf;
    unsigned len;
{
    gz_statep state;

    /* get internal structure */
    if (file == NULL)
        return 0;
    state = (gz_statep)file;

267
268
269
270
271
272
273
274

275
276
277
278

279
280
281
282
283
284
285
286
254
255
256
257
258
259
260

261




262

263
264
265
266
267
268
269







-
+
-
-
-
-
+
-







    }

    /* write len bytes from buf (the return value will fit in an int) */
    return (int)gz_write(state, buf, len);
}

/* -- see zlib.h -- */
z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems,
    voidpc buf;
    z_size_t size;
    z_size_t nitems;
    gzFile file;
                          gzFile file) {
{
    z_size_t len;
    gz_statep state;

    /* get internal structure */
    if (file == NULL)
        return 0;
    state = (gz_statep)file;
297
298
299
300
301
302
303
304

305
306
307
308
309
310
311
312
313
314
280
281
282
283
284
285
286

287



288
289
290
291
292
293
294







-
+
-
-
-







    }

    /* write len bytes to buf, return the number of full items written */
    return len ? gz_write(state, buf, len) / size : 0;
}

/* -- see zlib.h -- */
int ZEXPORT gzputc(file, c)
int ZEXPORT gzputc(gzFile file, int c) {
    gzFile file;
    int c;
{
    unsigned have;
    unsigned char buf[1];
    gz_statep state;
    z_streamp strm;

    /* get internal structure */
    if (file == NULL)
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
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
366







-
+
-
-
-
-
-
+












-
-
-
+
+
+
+
+
+
+






-
+
-







    buf[0] = (unsigned char)c;
    if (gz_write(state, buf, 1) != 1)
        return -1;
    return c & 0xff;
}

/* -- see zlib.h -- */
int ZEXPORT gzputs(file, str)
int ZEXPORT gzputs(gzFile file, const char *s) {
    gzFile file;
    const char *str;
{
    int ret;
    z_size_t len;
    z_size_t len, put;
    gz_statep state;

    /* get internal structure */
    if (file == NULL)
        return -1;
    state = (gz_statep)file;

    /* check that we're writing and that there's no error */
    if (state->mode != GZ_WRITE || state->err != Z_OK)
        return -1;

    /* write string */
    len = strlen(str);
    ret = gz_write(state, str, len);
    return ret == 0 && len != 0 ? -1 : ret;
    len = strlen(s);
    if ((int)len < 0 || (unsigned)len != len) {
        gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
        return -1;
    }
    put = gz_write(state, s, len);
    return put < len ? -1 : (int)len;
}

#if defined(STDC) || defined(Z_HAVE_STDARG_H)
#include <stdarg.h>

/* -- see zlib.h -- */
int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {
{
    int len;
    unsigned left;
    char *next;
    gz_statep state;
    z_streamp strm;

    /* get internal structure */
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
467
468
469
470




471
472
473
474
475
476
477
478
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







-
+






-
+
-












-
-
-
-
-
-
+
+
+
+
-







    strm->avail_in += (unsigned)len;
    state->x.pos += len;
    if (strm->avail_in >= state->size) {
        left = strm->avail_in - state->size;
        strm->avail_in = state->size;
        if (gz_comp(state, Z_NO_FLUSH) == -1)
            return state->err;
        memcpy(state->in, state->in + state->size, left);
        memmove(state->in, state->in + state->size, left);
        strm->next_in = state->in;
        strm->avail_in = left;
    }
    return len;
}

int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
{
    va_list va;
    int ret;

    va_start(va, format);
    ret = gzvprintf(file, format, va);
    va_end(va);
    return ret;
}

#else /* !STDC && !Z_HAVE_STDARG_H */

/* -- see zlib.h -- */
int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
                       a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
    gzFile file;
    const char *format;
    int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
        a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3,
                       int a4, int a5, int a6, int a7, int a8, int a9, int a10,
                       int a11, int a12, int a13, int a14, int a15, int a16,
                       int a17, int a18, int a19, int a20) {
{
    unsigned len, left;
    char *next;
    gz_statep state;
    z_streamp strm;

    /* get internal structure */
    if (file == NULL)
536
537
538
539
540
541
542
543

544
545
546
547
548
549
550
551
552
553

554
555
556
557
558
559
560
561
562
563
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







-
+









-
+
-
-
-







    strm->avail_in += len;
    state->x.pos += len;
    if (strm->avail_in >= state->size) {
        left = strm->avail_in - state->size;
        strm->avail_in = state->size;
        if (gz_comp(state, Z_NO_FLUSH) == -1)
            return state->err;
        memcpy(state->in, state->in + state->size, left);
        memmove(state->in, state->in + state->size, left);
        strm->next_in = state->in;
        strm->avail_in = left;
    }
    return (int)len;
}

#endif

/* -- see zlib.h -- */
int ZEXPORT gzflush(file, flush)
int ZEXPORT gzflush(gzFile file, int flush) {
    gzFile file;
    int flush;
{
    gz_statep state;

    /* get internal structure */
    if (file == NULL)
        return Z_STREAM_ERROR;
    state = (gz_statep)file;

578
579
580
581
582
583
584
585

586
587
588
589
590
591
592
593
594
595
596
597
598
599
600

601
602
603
604
605
606
607
550
551
552
553
554
555
556

557




558
559
560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
575







-
+
-
-
-
-










-
+








    /* compress remaining data with requested flush */
    (void)gz_comp(state, flush);
    return state->err;
}

/* -- see zlib.h -- */
int ZEXPORT gzsetparams(file, level, strategy)
int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
    gzFile file;
    int level;
    int strategy;
{
    gz_statep state;
    z_streamp strm;

    /* get internal structure */
    if (file == NULL)
        return Z_STREAM_ERROR;
    state = (gz_statep)file;
    strm = &(state->strm);

    /* check that we're writing and that there's no error */
    if (state->mode != GZ_WRITE || state->err != Z_OK)
    if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct)
        return Z_STREAM_ERROR;

    /* if no change is requested, then do nothing */
    if (level == state->level && strategy == state->strategy)
        return Z_OK;

    /* check for seek request */
620
621
622
623
624
625
626
627

628
629
630
631
632
633
634
635
636
588
589
590
591
592
593
594

595


596
597
598
599
600
601
602







-
+
-
-







    }
    state->level = level;
    state->strategy = strategy;
    return Z_OK;
}

/* -- see zlib.h -- */
int ZEXPORT gzclose_w(file)
int ZEXPORT gzclose_w(gzFile file) {
    gzFile file;
{
    int ret = Z_OK;
    gz_statep state;

    /* get internal structure */
    if (file == NULL)
        return Z_STREAM_ERROR;
    state = (gz_statep)file;

Changes to compat/zlib/infback.c.

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
30
31

32
33

34
35
36
37
38
39
40
41
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
30
31
32
33
34

-
+















-
-
-







-
+
-
-
-
+
-
-
+
-







/* infback.c -- inflate using a call-back interface
 * Copyright (C) 1995-2016 Mark Adler
 * Copyright (C) 1995-2022 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/*
   This code is largely copied from inflate.c.  Normally either infback.o or
   inflate.o would be linked into an application--not both.  The interface
   with inffast.c is retained so that optimized assembler-coded versions of
   inflate_fast() can be used with either inflate.c or infback.c.
 */

#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"

/* function prototypes */
local void fixedtables OF((struct inflate_state FAR *state));

/*
   strm provides memory allocation functions in zalloc and zfree, or
   Z_NULL to use the library memory allocation functions.

   windowBits is in the range 8..15, and window is a user-supplied
   window and output buffer that is 2**windowBits bytes.
 */
int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits,
z_streamp strm;
int windowBits;
unsigned char FAR *window;
                             unsigned char FAR *window, const char *version,
const char *version;
int stream_size;
                             int stream_size) {
{
    struct inflate_state FAR *state;

    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
        stream_size != (int)(sizeof(z_stream)))
        return Z_VERSION_ERROR;
    if (strm == Z_NULL || window == Z_NULL ||
        windowBits < 8 || windowBits > 15)
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
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







+













-
+
-
-







    strm->state = (struct internal_state FAR *)state;
    state->dmax = 32768U;
    state->wbits = (uInt)windowBits;
    state->wsize = 1U << windowBits;
    state->window = window;
    state->wnext = 0;
    state->whave = 0;
    state->sane = 1;
    return Z_OK;
}

/*
   Return state with length and distance decoding tables and index sizes set to
   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
   If BUILDFIXED is defined, then instead this routine builds the tables the
   first time it's called, and returns those tables the first time and
   thereafter.  This reduces the size of the code by about 2K bytes, in
   exchange for a little execution time.  However, BUILDFIXED should not be
   used for threaded applications, since the rewriting of the tables and virgin
   may not be thread-safe.
 */
local void fixedtables(state)
local void fixedtables(struct inflate_state FAR *state) {
struct inflate_state FAR *state;
{
#ifdef BUILDFIXED
    static int virgin = 1;
    static code *lenfix, *distfix;
    static code fixed[544];

    /* build fixed huffman tables if first call (may not be thread safe) */
    if (virgin) {
243
244
245
246
247
248
249
250

251
252
253
254

255
256
257
258
259
260
261
262
263
235
236
237
238
239
240
241

242




243


244
245
246
247
248
249
250







-
+
-
-
-
-
+
-
-







   Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
   was in() or out() that caused in the error.  Otherwise,  inflateBack()
   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
   error, or Z_MEM_ERROR if it could not allocate memory for the state.
   inflateBack() can also return Z_STREAM_ERROR if the input parameters
   are not correct, i.e. strm is Z_NULL or the state was not initialized.
 */
int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc,
z_streamp strm;
in_func in;
void FAR *in_desc;
out_func out;
                        out_func out, void FAR *out_desc) {
void FAR *out_desc;
{
    struct inflate_state FAR *state;
    z_const unsigned char FAR *next;    /* next input */
    unsigned char FAR *put;     /* next output */
    unsigned have, left;        /* available input and output */
    unsigned long hold;         /* bit buffer */
    unsigned bits;              /* bits in bit buffer */
    unsigned copy;              /* number of stored or match bytes to copy */
473
474
475
476
477
478
479

480
481
482
483
484
485
486
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474







+







            if (ret) {
                strm->msg = (char *)"invalid distances set";
                state->mode = BAD;
                break;
            }
            Tracev((stderr, "inflate:       codes ok\n"));
            state->mode = LEN;
                /* fallthrough */

        case LEN:
            /* use inflate_fast() if we have enough input and output */
            if (have >= 6 && left >= 258) {
                RESTORE();
                if (state->whave < state->wsize)
                    state->whave = state->wsize - left;
600
601
602
603
604
605
606
607

608
609
610
611
612
613
614
615
616
617
618

619

620
621
622
623
624

625





626
627
628
629
630
631

632
633
634
635
636
637
638
639
640
588
589
590
591
592
593
594

595
596




597
598
599
600
601
602
603

604
605
606
607
608

609
610
611
612
613
614
615
616
617
618
619
620

621


622
623
624
625
626
627
628







-
+

-
-
-
-






+
-
+




-
+

+
+
+
+
+





-
+
-
-







                do {
                    *put++ = *from++;
                } while (--copy);
            } while (state->length != 0);
            break;

        case DONE:
            /* inflate stream terminated properly -- write leftover output */
            /* inflate stream terminated properly */
            ret = Z_STREAM_END;
            if (left < state->wsize) {
                if (out(out_desc, state->window, state->wsize - left))
                    ret = Z_BUF_ERROR;
            }
            goto inf_leave;

        case BAD:
            ret = Z_DATA_ERROR;
            goto inf_leave;

        default:
        default:                /* can't happen, but makes compilers happy */
            /* can't happen, but makes compilers happy */
            ret = Z_STREAM_ERROR;
            goto inf_leave;
        }

    /* Return unused input */
    /* Write leftover output and return unused input */
  inf_leave:
    if (left < state->wsize) {
        if (out(out_desc, state->window, state->wsize - left) &&
            ret == Z_STREAM_END)
            ret = Z_BUF_ERROR;
    }
    strm->next_in = next;
    strm->avail_in = have;
    return ret;
}

int ZEXPORT inflateBackEnd(strm)
int ZEXPORT inflateBackEnd(z_streamp strm) {
z_streamp strm;
{
    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
        return Z_STREAM_ERROR;
    ZFREE(strm, strm->state);
    strm->state = Z_NULL;
    Tracev((stderr, "inflate: end\n"));
    return Z_OK;
}

Changes to compat/zlib/inffast.c.

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
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







-
+
-
-
-



















-
+







      checking for available input while decoding.

    - The maximum bytes that a single length/distance pair can output is 258
      bytes, which is the maximum length that can be coded.  inflate_fast()
      requires strm->avail_out >= 258 for each loop to avoid checking for
      output space.
 */
void ZLIB_INTERNAL inflate_fast(strm, start)
void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
z_streamp strm;
unsigned start;         /* inflate()'s starting value for strm->avail_out */
{
    struct inflate_state FAR *state;
    z_const unsigned char FAR *in;      /* local strm->next_in */
    z_const unsigned char FAR *last;    /* have enough input while in < last */
    unsigned char FAR *out;     /* local strm->next_out */
    unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
    unsigned char FAR *end;     /* while out < end, enough space available */
#ifdef INFLATE_STRICT
    unsigned dmax;              /* maximum distance from zlib header */
#endif
    unsigned wsize;             /* window size or zero if not using window */
    unsigned whave;             /* valid bytes in the window */
    unsigned wnext;             /* window write index */
    unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
    unsigned long hold;         /* local strm->hold */
    unsigned bits;              /* local strm->bits */
    code const FAR *lcode;      /* local strm->lencode */
    code const FAR *dcode;      /* local strm->distcode */
    unsigned lmask;             /* mask for first level of length codes */
    unsigned dmask;             /* mask for first level of distance codes */
    code here;                  /* retrieved table entry */
    code const *here;           /* retrieved table entry */
    unsigned op;                /* code bits, operation, extra bits, or */
                                /*  window position, window bytes to copy */
    unsigned len;               /* match length, unused bytes */
    unsigned dist;              /* match distance */
    unsigned char FAR *from;    /* where to copy match from */

    /* copy state to local variables */
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
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







-
+

-
+


-
+

-
+

-
-
+
+


-
+

















-
+

-
+


-
+

-
+







    do {
        if (bits < 15) {
            hold += (unsigned long)(*in++) << bits;
            bits += 8;
            hold += (unsigned long)(*in++) << bits;
            bits += 8;
        }
        here = lcode[hold & lmask];
        here = lcode + (hold & lmask);
      dolen:
        op = (unsigned)(here.bits);
        op = (unsigned)(here->bits);
        hold >>= op;
        bits -= op;
        op = (unsigned)(here.op);
        op = (unsigned)(here->op);
        if (op == 0) {                          /* literal */
            Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
            Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
                    "inflate:         literal '%c'\n" :
                    "inflate:         literal 0x%02x\n", here.val));
            *out++ = (unsigned char)(here.val);
                    "inflate:         literal 0x%02x\n", here->val));
            *out++ = (unsigned char)(here->val);
        }
        else if (op & 16) {                     /* length base */
            len = (unsigned)(here.val);
            len = (unsigned)(here->val);
            op &= 15;                           /* number of extra bits */
            if (op) {
                if (bits < op) {
                    hold += (unsigned long)(*in++) << bits;
                    bits += 8;
                }
                len += (unsigned)hold & ((1U << op) - 1);
                hold >>= op;
                bits -= op;
            }
            Tracevv((stderr, "inflate:         length %u\n", len));
            if (bits < 15) {
                hold += (unsigned long)(*in++) << bits;
                bits += 8;
                hold += (unsigned long)(*in++) << bits;
                bits += 8;
            }
            here = dcode[hold & dmask];
            here = dcode + (hold & dmask);
          dodist:
            op = (unsigned)(here.bits);
            op = (unsigned)(here->bits);
            hold >>= op;
            bits -= op;
            op = (unsigned)(here.op);
            op = (unsigned)(here->op);
            if (op & 16) {                      /* distance base */
                dist = (unsigned)(here.val);
                dist = (unsigned)(here->val);
                op &= 15;                       /* number of extra bits */
                if (bits < op) {
                    hold += (unsigned long)(*in++) << bits;
                    bits += 8;
                    if (bits < op) {
                        hold += (unsigned long)(*in++) << bits;
                        bits += 8;
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
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







-
+









-
+







                        *out++ = *from++;
                        if (len > 1)
                            *out++ = *from++;
                    }
                }
            }
            else if ((op & 64) == 0) {          /* 2nd level distance code */
                here = dcode[here.val + (hold & ((1U << op) - 1))];
                here = dcode + here->val + (hold & ((1U << op) - 1));
                goto dodist;
            }
            else {
                strm->msg = (char *)"invalid distance code";
                state->mode = BAD;
                break;
            }
        }
        else if ((op & 64) == 0) {              /* 2nd level length code */
            here = lcode[here.val + (hold & ((1U << op) - 1))];
            here = lcode + here->val + (hold & ((1U << op) - 1));
            goto dolen;
        }
        else if (op & 32) {                     /* end-of-block */
            Tracevv((stderr, "inflate:         end of block\n"));
            state->mode = TYPE;
            break;
        }

Changes to compat/zlib/inffast.h.

1
2
3
4
5
6
7
8
9
10
11

1
2
3
4
5
6
7
8
9
10

11










-
+
/* inffast.h -- header to use inffast.c
 * Copyright (C) 1995-2003, 2010 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/* WARNING: this file should *not* be used by applications. It is
   part of the implementation of the compression library and is
   subject to change. Applications should only use zlib.h.
 */

void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));
void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start);

Changes to compat/zlib/inflate.c.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/* inflate.c -- zlib decompression
 * Copyright (C) 1995-2016 Mark Adler
 * Copyright (C) 1995-2022 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/*
 * Change history:
 *
 * 1.2.beta0    24 Nov 2002
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
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







-
-
-
-
-
-
-
-
-
-
-
-
+
-
-











-
+
-
-











+











-
+
-
-










-
+
-
-
-









+
+








#ifdef MAKEFIXED
#  ifndef BUILDFIXED
#    define BUILDFIXED
#  endif
#endif

/* function prototypes */
local int inflateStateCheck OF((z_streamp strm));
local void fixedtables OF((struct inflate_state FAR *state));
local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
                           unsigned copy));
#ifdef BUILDFIXED
   void makefixed OF((void));
#endif
local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
                              unsigned len));

local int inflateStateCheck(strm)
local int inflateStateCheck(z_streamp strm) {
z_streamp strm;
{
    struct inflate_state FAR *state;
    if (strm == Z_NULL ||
        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
        return 1;
    state = (struct inflate_state FAR *)strm->state;
    if (state == Z_NULL || state->strm != strm ||
        state->mode < HEAD || state->mode > SYNC)
        return 1;
    return 0;
}

int ZEXPORT inflateResetKeep(strm)
int ZEXPORT inflateResetKeep(z_streamp strm) {
z_streamp strm;
{
    struct inflate_state FAR *state;

    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;
    strm->total_in = strm->total_out = state->total = 0;
    strm->msg = Z_NULL;
    if (state->wrap)        /* to support ill-conceived Java test suite */
        strm->adler = state->wrap & 1;
    state->mode = HEAD;
    state->last = 0;
    state->havedict = 0;
    state->flags = -1;
    state->dmax = 32768U;
    state->head = Z_NULL;
    state->hold = 0;
    state->bits = 0;
    state->lencode = state->distcode = state->next = state->codes;
    state->sane = 1;
    state->back = -1;
    Tracev((stderr, "inflate: reset\n"));
    return Z_OK;
}

int ZEXPORT inflateReset(strm)
int ZEXPORT inflateReset(z_streamp strm) {
z_streamp strm;
{
    struct inflate_state FAR *state;

    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;
    state->wsize = 0;
    state->whave = 0;
    state->wnext = 0;
    return inflateResetKeep(strm);
}

int ZEXPORT inflateReset2(strm, windowBits)
int ZEXPORT inflateReset2(z_streamp strm, int windowBits) {
z_streamp strm;
int windowBits;
{
    int wrap;
    struct inflate_state FAR *state;

    /* get the state */
    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;

    /* extract wrap request from windowBits parameter */
    if (windowBits < 0) {
        if (windowBits < -15)
            return Z_STREAM_ERROR;
        wrap = 0;
        windowBits = -windowBits;
    }
    else {
        wrap = (windowBits >> 4) + 5;
#ifdef GUNZIP
        if (windowBits < 48)
188
189
190
191
192
193
194
195

196
197
198

199
200
201
202
203
204
205
206
207
171
172
173
174
175
176
177

178



179


180
181
182
183
184
185
186







-
+
-
-
-
+
-
-








    /* update state and reset the rest of it */
    state->wrap = wrap;
    state->wbits = (unsigned)windowBits;
    return inflateReset(strm);
}

int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
int ZEXPORT inflateInit2_(z_streamp strm, int windowBits,
z_streamp strm;
int windowBits;
const char *version;
                          const char *version, int stream_size) {
int stream_size;
{
    int ret;
    struct inflate_state FAR *state;

    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
        stream_size != (int)(sizeof(z_stream)))
        return Z_VERSION_ERROR;
    if (strm == Z_NULL) return Z_STREAM_ERROR;
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
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







-
-
-
-
+
+
-



-
+
-
-
-
-



+
+







    if (ret != Z_OK) {
        ZFREE(strm, state);
        strm->state = Z_NULL;
    }
    return ret;
}

int ZEXPORT inflateInit_(strm, version, stream_size)
z_streamp strm;
const char *version;
int stream_size;
int ZEXPORT inflateInit_(z_streamp strm, const char *version,
                         int stream_size) {
{
    return inflateInit2_(strm, DEF_WBITS, version, stream_size);
}

int ZEXPORT inflatePrime(strm, bits, value)
int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) {
z_streamp strm;
int bits;
int value;
{
    struct inflate_state FAR *state;

    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
    if (bits == 0)
        return Z_OK;
    state = (struct inflate_state FAR *)strm->state;
    if (bits < 0) {
        state->hold = 0;
        state->bits = 0;
        return Z_OK;
    }
    if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR;
271
272
273
274
275
276
277
278

279
280
281
282
283
284
285
286
287
245
246
247
248
249
250
251

252


253
254
255
256
257
258
259







-
+
-
-







   If BUILDFIXED is defined, then instead this routine builds the tables the
   first time it's called, and returns those tables the first time and
   thereafter.  This reduces the size of the code by about 2K bytes, in
   exchange for a little execution time.  However, BUILDFIXED should not be
   used for threaded applications, since the rewriting of the tables and virgin
   may not be thread-safe.
 */
local void fixedtables(state)
local void fixedtables(struct inflate_state FAR *state) {
struct inflate_state FAR *state;
{
#ifdef BUILDFIXED
    static int virgin = 1;
    static code *lenfix, *distfix;
    static code fixed[544];

    /* build fixed huffman tables if first call (may not be thread safe) */
    if (virgin) {
335
336
337
338
339
340
341
342

343
344
345
346
347
348
349
307
308
309
310
311
312
313

314
315
316
317
318
319
320
321







-
+







        return 0;
    }

   Then that can be linked with zlib built with MAKEFIXED defined and run:

    a.out > inffixed.h
 */
void makefixed()
void makefixed(void)
{
    unsigned low, size;
    struct inflate_state state;

    fixedtables(&state);
    puts("    /* inffixed.h -- table for decoding fixed codes");
    puts("     * Generated automatically by makefixed().");
389
390
391
392
393
394
395
396

397
398
399
400
401
402
403
404
405
406
407
361
362
363
364
365
366
367

368




369
370
371
372
373
374
375







-
+
-
-
-
-








   Providing output buffers larger than 32K to inflate() should provide a speed
   advantage, since only the last 32K of output is copied to the sliding window
   upon return from inflate(), and since all distances after the first 32K of
   output will fall in the output data, making match copies simpler and faster.
   The advantage may be dependent on the size of the processor's data caches.
 */
local int updatewindow(strm, end, copy)
local int updatewindow(z_streamp strm, const Bytef *end, unsigned copy) {
z_streamp strm;
const Bytef *end;
unsigned copy;
{
    struct inflate_state FAR *state;
    unsigned dist;

    state = (struct inflate_state FAR *)strm->state;

    /* if it hasn't been done already, allocate space for the window */
    if (state->window == Z_NULL) {
443
444
445
446
447
448
449
450

451
452
453

454
455
456
457
458
459
460
411
412
413
414
415
416
417

418
419
420

421
422
423
424
425
426
427
428







-
+


-
+







    return 0;
}

/* Macros for inflate(): */

/* check function to use adler32() for zlib or crc32() for gzip */
#ifdef GUNZIP
#  define UPDATE(check, buf, len) \
#  define UPDATE_CHECK(check, buf, len) \
    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
#else
#  define UPDATE(check, buf, len) adler32(check, buf, len)
#  define UPDATE_CHECK(check, buf, len) adler32(check, buf, len)
#endif

/* check macros for header crc */
#ifdef GUNZIP
#  define CRC2(check, word) \
    do { \
        hbuf[0] = (unsigned char)(word); \
615
616
617
618
619
620
621
622

623
624
625
626
627
628
629
630
631
632
583
584
585
586
587
588
589

590



591
592
593
594
595
596
597







-
+
-
-
-







   the allocation of and copying into a sliding window until necessary, which
   provides the effect documented in zlib.h for Z_FINISH when the entire input
   stream available.  So the only thing the flush parameter actually does is:
   when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
   will return Z_BUF_ERROR if it has not reached the end of the stream.
 */

int ZEXPORT inflate(strm, flush)
int ZEXPORT inflate(z_streamp strm, int flush) {
z_streamp strm;
int flush;
{
    struct inflate_state FAR *state;
    z_const unsigned char FAR *next;    /* next input */
    unsigned char FAR *put;     /* next output */
    unsigned have, left;        /* available input and output */
    unsigned long hold;         /* bit buffer */
    unsigned bits;              /* bits in bit buffer */
    unsigned in, out;           /* save starting available input and output */
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
631
632
633
634
635
636
637

638
639
640
641
642
643
644







-







                    state->wbits = 15;
                state->check = crc32(0L, Z_NULL, 0);
                CRC2(state->check, hold);
                INITBITS();
                state->mode = FLAGS;
                break;
            }
            state->flags = 0;           /* expect zlib header */
            if (state->head != Z_NULL)
                state->head->done = -1;
            if (!(state->wrap & 1) ||   /* check if zlib header allowed */
#else
            if (
#endif
                ((BITS(8) << 8) + (hold >> 8)) % 31) {
693
694
695
696
697
698
699

700
701
702
703
704
705
706
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671







+







                state->wbits = len;
            if (len > 15 || len > state->wbits) {
                strm->msg = (char *)"invalid window size";
                state->mode = BAD;
                break;
            }
            state->dmax = 1U << len;
            state->flags = 0;               /* indicate zlib header */
            Tracev((stderr, "inflate:   zlib header ok\n"));
            strm->adler = state->check = adler32(0L, Z_NULL, 0);
            state->mode = hold & 0x200 ? DICTID : TYPE;
            INITBITS();
            break;
#ifdef GUNZIP
        case FLAGS:
718
719
720
721
722
723
724

725
726
727
728
729
730
731
732

733
734
735
736
737
738
739
740
741
742

743
744
745
746
747
748
749
750
751
752
753
754
755

756
757
758
759
760
761
762
763



764
765
766
767
768
769
770
771
772
773
774
775
776
777

778
779
780
781
782
783
784
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730


731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755







+








+










+













+






-
-
+
+
+














+







            }
            if (state->head != Z_NULL)
                state->head->text = (int)((hold >> 8) & 1);
            if ((state->flags & 0x0200) && (state->wrap & 4))
                CRC2(state->check, hold);
            INITBITS();
            state->mode = TIME;
                /* fallthrough */
        case TIME:
            NEEDBITS(32);
            if (state->head != Z_NULL)
                state->head->time = hold;
            if ((state->flags & 0x0200) && (state->wrap & 4))
                CRC4(state->check, hold);
            INITBITS();
            state->mode = OS;
                /* fallthrough */
        case OS:
            NEEDBITS(16);
            if (state->head != Z_NULL) {
                state->head->xflags = (int)(hold & 0xff);
                state->head->os = (int)(hold >> 8);
            }
            if ((state->flags & 0x0200) && (state->wrap & 4))
                CRC2(state->check, hold);
            INITBITS();
            state->mode = EXLEN;
                /* fallthrough */
        case EXLEN:
            if (state->flags & 0x0400) {
                NEEDBITS(16);
                state->length = (unsigned)(hold);
                if (state->head != Z_NULL)
                    state->head->extra_len = (unsigned)hold;
                if ((state->flags & 0x0200) && (state->wrap & 4))
                    CRC2(state->check, hold);
                INITBITS();
            }
            else if (state->head != Z_NULL)
                state->head->extra = Z_NULL;
            state->mode = EXTRA;
                /* fallthrough */
        case EXTRA:
            if (state->flags & 0x0400) {
                copy = state->length;
                if (copy > have) copy = have;
                if (copy) {
                    if (state->head != Z_NULL &&
                        state->head->extra != Z_NULL) {
                        len = state->head->extra_len - state->length;
                        state->head->extra != Z_NULL &&
                        (len = state->head->extra_len - state->length) <
                            state->head->extra_max) {
                        zmemcpy(state->head->extra + len, next,
                                len + copy > state->head->extra_max ?
                                state->head->extra_max - len : copy);
                    }
                    if ((state->flags & 0x0200) && (state->wrap & 4))
                        state->check = crc32(state->check, next, copy);
                    have -= copy;
                    next += copy;
                    state->length -= copy;
                }
                if (state->length) goto inf_leave;
            }
            state->length = 0;
            state->mode = NAME;
                /* fallthrough */
        case NAME:
            if (state->flags & 0x0800) {
                if (have == 0) goto inf_leave;
                copy = 0;
                do {
                    len = (unsigned)(next[copy++]);
                    if (state->head != Z_NULL &&
792
793
794
795
796
797
798

799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818

819
820
821
822
823
824
825
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798







+




















+







                next += copy;
                if (len) goto inf_leave;
            }
            else if (state->head != Z_NULL)
                state->head->name = Z_NULL;
            state->length = 0;
            state->mode = COMMENT;
                /* fallthrough */
        case COMMENT:
            if (state->flags & 0x1000) {
                if (have == 0) goto inf_leave;
                copy = 0;
                do {
                    len = (unsigned)(next[copy++]);
                    if (state->head != Z_NULL &&
                            state->head->comment != Z_NULL &&
                            state->length < state->head->comm_max)
                        state->head->comment[state->length++] = (Bytef)len;
                } while (len && copy < have);
                if ((state->flags & 0x0200) && (state->wrap & 4))
                    state->check = crc32(state->check, next, copy);
                have -= copy;
                next += copy;
                if (len) goto inf_leave;
            }
            else if (state->head != Z_NULL)
                state->head->comment = Z_NULL;
            state->mode = HCRC;
                /* fallthrough */
        case HCRC:
            if (state->flags & 0x0200) {
                NEEDBITS(16);
                if ((state->wrap & 4) && hold != (state->check & 0xffff)) {
                    strm->msg = (char *)"header crc mismatch";
                    state->mode = BAD;
                    break;
835
836
837
838
839
840
841

842
843
844
845
846
847
848

849
850

851
852
853
854
855
856
857
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833







+







+


+







            break;
#endif
        case DICTID:
            NEEDBITS(32);
            strm->adler = state->check = ZSWAP32(hold);
            INITBITS();
            state->mode = DICT;
                /* fallthrough */
        case DICT:
            if (state->havedict == 0) {
                RESTORE();
                return Z_NEED_DICT;
            }
            strm->adler = state->check = adler32(0L, Z_NULL, 0);
            state->mode = TYPE;
                /* fallthrough */
        case TYPE:
            if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
                /* fallthrough */
        case TYPEDO:
            if (state->last) {
                BYTEBITS();
                state->mode = CHECK;
                break;
            }
            NEEDBITS(3);
894
895
896
897
898
899
900

901
902

903
904
905
906
907
908
909
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887







+


+







            }
            state->length = (unsigned)hold & 0xffff;
            Tracev((stderr, "inflate:       stored length %u\n",
                    state->length));
            INITBITS();
            state->mode = COPY_;
            if (flush == Z_TREES) goto inf_leave;
                /* fallthrough */
        case COPY_:
            state->mode = COPY;
                /* fallthrough */
        case COPY:
            copy = state->length;
            if (copy) {
                if (copy > have) copy = have;
                if (copy > left) copy = left;
                if (copy == 0) goto inf_leave;
                zmemcpy(put, next, copy);
931
932
933
934
935
936
937

938
939
940
941
942
943
944
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923







+







                state->mode = BAD;
                break;
            }
#endif
            Tracev((stderr, "inflate:       table sizes ok\n"));
            state->have = 0;
            state->mode = LENLENS;
                /* fallthrough */
        case LENLENS:
            while (state->have < state->ncode) {
                NEEDBITS(3);
                state->lens[order[state->have++]] = (unsigned short)BITS(3);
                DROPBITS(3);
            }
            while (state->have < 19)
952
953
954
955
956
957
958

959
960
961
962
963
964
965
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945







+







                strm->msg = (char *)"invalid code lengths set";
                state->mode = BAD;
                break;
            }
            Tracev((stderr, "inflate:       code lengths ok\n"));
            state->have = 0;
            state->mode = CODELENS;
                /* fallthrough */
        case CODELENS:
            while (state->have < state->nlen + state->ndist) {
                for (;;) {
                    here = state->lencode[BITS(state->lenbits)];
                    if ((unsigned)(here.bits) <= bits) break;
                    PULLBYTE();
                }
1035
1036
1037
1038
1039
1040
1041

1042
1043

1044
1045
1046
1047
1048
1049
1050
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032







+


+







                strm->msg = (char *)"invalid distances set";
                state->mode = BAD;
                break;
            }
            Tracev((stderr, "inflate:       codes ok\n"));
            state->mode = LEN_;
            if (flush == Z_TREES) goto inf_leave;
                /* fallthrough */
        case LEN_:
            state->mode = LEN;
                /* fallthrough */
        case LEN:
            if (have >= 6 && left >= 258) {
                RESTORE();
                inflate_fast(strm, out);
                LOAD();
                if (state->mode == TYPE)
                    state->back = -1;
1086
1087
1088
1089
1090
1091
1092

1093
1094
1095
1096
1097
1098
1099
1100
1101
1102

1103
1104
1105
1106
1107
1108
1109
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







+










+







            if (here.op & 64) {
                strm->msg = (char *)"invalid literal/length code";
                state->mode = BAD;
                break;
            }
            state->extra = (unsigned)(here.op) & 15;
            state->mode = LENEXT;
                /* fallthrough */
        case LENEXT:
            if (state->extra) {
                NEEDBITS(state->extra);
                state->length += BITS(state->extra);
                DROPBITS(state->extra);
                state->back += state->extra;
            }
            Tracevv((stderr, "inflate:         length %u\n", state->length));
            state->was = state->length;
            state->mode = DIST;
                /* fallthrough */
        case DIST:
            for (;;) {
                here = state->distcode[BITS(state->distbits)];
                if ((unsigned)(here.bits) <= bits) break;
                PULLBYTE();
            }
            if ((here.op & 0xf0) == 0) {
1123
1124
1125
1126
1127
1128
1129

1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145

1146
1147
1148
1149
1150
1151
1152
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138







+
















+







                strm->msg = (char *)"invalid distance code";
                state->mode = BAD;
                break;
            }
            state->offset = (unsigned)here.val;
            state->extra = (unsigned)(here.op) & 15;
            state->mode = DISTEXT;
                /* fallthrough */
        case DISTEXT:
            if (state->extra) {
                NEEDBITS(state->extra);
                state->offset += BITS(state->extra);
                DROPBITS(state->extra);
                state->back += state->extra;
            }
#ifdef INFLATE_STRICT
            if (state->offset > state->dmax) {
                strm->msg = (char *)"invalid distance too far back";
                state->mode = BAD;
                break;
            }
#endif
            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
            state->mode = MATCH;
                /* fallthrough */
        case MATCH:
            if (left == 0) goto inf_leave;
            copy = out - left;
            if (state->offset > copy) {         /* copy from window */
                copy = state->offset - copy;
                if (copy > state->whave) {
                    if (state->sane) {
1198
1199
1200
1201
1202
1203
1204
1205

1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220

1221
1222
1223
1224

1225
1226
1227
1228
1229
1230
1231
1232
1233

1234
1235
1236
1237
1238
1239
1240
1241
1242

1243
1244
1245
1246
1247
1248
1249
1184
1185
1186
1187
1188
1189
1190

1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210

1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238







-
+















+



-
+









+









+







            if (state->wrap) {
                NEEDBITS(32);
                out -= left;
                strm->total_out += out;
                state->total += out;
                if ((state->wrap & 4) && out)
                    strm->adler = state->check =
                        UPDATE(state->check, put - out, out);
                        UPDATE_CHECK(state->check, put - out, out);
                out = left;
                if ((state->wrap & 4) && (
#ifdef GUNZIP
                     state->flags ? hold :
#endif
                     ZSWAP32(hold)) != state->check) {
                    strm->msg = (char *)"incorrect data check";
                    state->mode = BAD;
                    break;
                }
                INITBITS();
                Tracev((stderr, "inflate:   check matches trailer\n"));
            }
#ifdef GUNZIP
            state->mode = LENGTH;
                /* fallthrough */
        case LENGTH:
            if (state->wrap && state->flags) {
                NEEDBITS(32);
                if (hold != (state->total & 0xffffffffUL)) {
                if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) {
                    strm->msg = (char *)"incorrect length check";
                    state->mode = BAD;
                    break;
                }
                INITBITS();
                Tracev((stderr, "inflate:   length matches trailer\n"));
            }
#endif
            state->mode = DONE;
                /* fallthrough */
        case DONE:
            ret = Z_STREAM_END;
            goto inf_leave;
        case BAD:
            ret = Z_DATA_ERROR;
            goto inf_leave;
        case MEM:
            return Z_MEM_ERROR;
        case SYNC:
                /* fallthrough */
        default:
            return Z_STREAM_ERROR;
        }

    /*
       Return from inflate(), updating the total counts and the check value.
       If there was no progress during the inflate() call, return a buffer
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
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







-
+








-
+
-
-











-
+
-
-
-
+
-


















-
+
-
-
-
+
-







    in -= strm->avail_in;
    out -= strm->avail_out;
    strm->total_in += in;
    strm->total_out += out;
    state->total += out;
    if ((state->wrap & 4) && out)
        strm->adler = state->check =
            UPDATE(state->check, strm->next_out - out, out);
            UPDATE_CHECK(state->check, strm->next_out - out, out);
    strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
                      (state->mode == TYPE ? 128 : 0) +
                      (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
        ret = Z_BUF_ERROR;
    return ret;
}

int ZEXPORT inflateEnd(strm)
int ZEXPORT inflateEnd(z_streamp strm) {
z_streamp strm;
{
    struct inflate_state FAR *state;
    if (inflateStateCheck(strm))
        return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;
    if (state->window != Z_NULL) ZFREE(strm, state->window);
    ZFREE(strm, strm->state);
    strm->state = Z_NULL;
    Tracev((stderr, "inflate: end\n"));
    return Z_OK;
}

int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength)
int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary,
z_streamp strm;
Bytef *dictionary;
uInt *dictLength;
                                 uInt *dictLength) {
{
    struct inflate_state FAR *state;

    /* check state */
    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;

    /* copy dictionary */
    if (state->whave && dictionary != Z_NULL) {
        zmemcpy(dictionary, state->window + state->wnext,
                state->whave - state->wnext);
        zmemcpy(dictionary + state->whave - state->wnext,
                state->window, state->wnext);
    }
    if (dictLength != Z_NULL)
        *dictLength = state->whave;
    return Z_OK;
}

int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary,
z_streamp strm;
const Bytef *dictionary;
uInt dictLength;
                                 uInt dictLength) {
{
    struct inflate_state FAR *state;
    unsigned long dictid;
    int ret;

    /* check state */
    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;
1342
1343
1344
1345
1346
1347
1348
1349

1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1323
1324
1325
1326
1327
1328
1329

1330



1331
1332
1333
1334
1335
1336
1337







-
+
-
-
-







        return Z_MEM_ERROR;
    }
    state->havedict = 1;
    Tracev((stderr, "inflate:   dictionary set\n"));
    return Z_OK;
}

int ZEXPORT inflateGetHeader(strm, head)
int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) {
z_streamp strm;
gz_headerp head;
{
    struct inflate_state FAR *state;

    /* check state */
    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;
    if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;

1370
1371
1372
1373
1374
1375
1376
1377

1378
1379
1380

1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400

1401
1402
1403

1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416

1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435





1436
1437
1438

1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451

1452
1453
1454
1455
1456
1457
1458
1459
1460
1461

1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1348
1349
1350
1351
1352
1353
1354

1355



1356

1357
1358
1359
1360
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
1387
1388
1389

1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430

1431


1432
1433
1434
1435
1436
1437
1438

1439



1440
1441
1442
1443
1444
1445
1446







-
+
-
-
-
+
-


















-
+
-
-

+












-
+



















+
+
+
+
+



+












-
+
-
-







-
+
-
-
-







   state.  If on return *have equals four, then the pattern was found and the
   return value is how many bytes were read including the last byte of the
   pattern.  If *have is less than four, then the pattern has not been found
   yet and the return value is len.  In the latter case, syncsearch() can be
   called again with more data and the *have state.  *have is initialized to
   zero for the first call.
 */
local unsigned syncsearch(have, buf, len)
local unsigned syncsearch(unsigned FAR *have, const unsigned char FAR *buf,
unsigned FAR *have;
const unsigned char FAR *buf;
unsigned len;
                          unsigned len) {
{
    unsigned got;
    unsigned next;

    got = *have;
    next = 0;
    while (next < len && got < 4) {
        if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
            got++;
        else if (buf[next])
            got = 0;
        else
            got = 4 - got;
        next++;
    }
    *have = got;
    return next;
}

int ZEXPORT inflateSync(strm)
int ZEXPORT inflateSync(z_streamp strm) {
z_streamp strm;
{
    unsigned len;               /* number of bytes to look at or looked at */
    int flags;                  /* temporary to save header status */
    unsigned long in, out;      /* temporary to save total_in and total_out */
    unsigned char buf[4];       /* to restore bit buffer to byte string */
    struct inflate_state FAR *state;

    /* check parameters */
    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;
    if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;

    /* if first time, start search in bit buffer */
    if (state->mode != SYNC) {
        state->mode = SYNC;
        state->hold <<= state->bits & 7;
        state->hold >>= state->bits & 7;
        state->bits -= state->bits & 7;
        len = 0;
        while (state->bits >= 8) {
            buf[len++] = (unsigned char)(state->hold);
            state->hold >>= 8;
            state->bits -= 8;
        }
        state->have = 0;
        syncsearch(&(state->have), buf, len);
    }

    /* search available input */
    len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
    strm->avail_in -= len;
    strm->next_in += len;
    strm->total_in += len;

    /* return no joy or set up to restart inflate() on a new block */
    if (state->have != 4) return Z_DATA_ERROR;
    if (state->flags == -1)
        state->wrap = 0;    /* if no header yet, treat as raw */
    else
        state->wrap &= ~4;  /* no point in computing a check value now */
    flags = state->flags;
    in = strm->total_in;  out = strm->total_out;
    inflateReset(strm);
    strm->total_in = in;  strm->total_out = out;
    state->flags = flags;
    state->mode = TYPE;
    return Z_OK;
}

/*
   Returns true if inflate is currently at the end of a block generated by
   Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
   implementation to provide an additional safety check. PPP uses
   Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
   block. When decompressing, PPP checks that at the end of input packet,
   inflate is waiting for these length bytes.
 */
int ZEXPORT inflateSyncPoint(strm)
int ZEXPORT inflateSyncPoint(z_streamp strm) {
z_streamp strm;
{
    struct inflate_state FAR *state;

    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;
    return state->mode == STORED && state->bits == 0;
}

int ZEXPORT inflateCopy(dest, source)
int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) {
z_streamp dest;
z_streamp source;
{
    struct inflate_state FAR *state;
    struct inflate_state FAR *copy;
    unsigned char FAR *window;
    unsigned wsize;

    /* check input */
    if (inflateStateCheck(source) || dest == Z_NULL)
1501
1502
1503
1504
1505
1506
1507
1508

1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526

1527
1528
1529
1530
1531
1532
1533
1534

1535
1536
1537
1538
1539
1540
1541

1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554

1555
1556
1557
1558
1559
1560
1561
1476
1477
1478
1479
1480
1481
1482

1483



1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497

1498



1499
1500
1501
1502

1503
1504
1505
1506
1507
1508
1509

1510


1511
1512
1513
1514
1515
1516
1517
1518
1519
1520

1521


1522
1523
1524
1525
1526







-
+
-
-
-














-
+
-
-
-




-
+






-
+
-
-










-
+
-
-





        zmemcpy(window, state->window, wsize);
    }
    copy->window = window;
    dest->state = (struct internal_state FAR *)copy;
    return Z_OK;
}

int ZEXPORT inflateUndermine(strm, subvert)
int ZEXPORT inflateUndermine(z_streamp strm, int subvert) {
z_streamp strm;
int subvert;
{
    struct inflate_state FAR *state;

    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
    state->sane = !subvert;
    return Z_OK;
#else
    (void)subvert;
    state->sane = 1;
    return Z_DATA_ERROR;
#endif
}

int ZEXPORT inflateValidate(strm, check)
int ZEXPORT inflateValidate(z_streamp strm, int check) {
z_streamp strm;
int check;
{
    struct inflate_state FAR *state;

    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;
    if (check)
    if (check && state->wrap)
        state->wrap |= 4;
    else
        state->wrap &= ~4;
    return Z_OK;
}

long ZEXPORT inflateMark(strm)
long ZEXPORT inflateMark(z_streamp strm) {
z_streamp strm;
{
    struct inflate_state FAR *state;

    if (inflateStateCheck(strm))
        return -(1L << 16);
    state = (struct inflate_state FAR *)strm->state;
    return (long)(((unsigned long)((long)state->back)) << 16) +
        (state->mode == COPY ? state->length :
            (state->mode == MATCH ? state->was - state->length : 0));
}

unsigned long ZEXPORT inflateCodesUsed(strm)
unsigned long ZEXPORT inflateCodesUsed(z_streamp strm) {
z_streamp strm;
{
    struct inflate_state FAR *state;
    if (inflateStateCheck(strm)) return (unsigned long)-1;
    state = (struct inflate_state FAR *)strm->state;
    return (unsigned long)(state->next - state->codes);
}

Changes to compat/zlib/inflate.h.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/* inflate.h -- internal inflate state definition
 * Copyright (C) 1995-2016 Mark Adler
 * Copyright (C) 1995-2019 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/* WARNING: this file should *not* be used by applications. It is
   part of the implementation of the compression library and is
   subject to change. Applications should only use zlib.h.
 */
82
83
84
85
86
87
88
89


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

89
90
91
92
93
94
95
96
97







-
+
+







struct inflate_state {
    z_streamp strm;             /* pointer back to this zlib stream */
    inflate_mode mode;          /* current inflate mode */
    int last;                   /* true if processing last block */
    int wrap;                   /* bit 0 true for zlib, bit 1 true for gzip,
                                   bit 2 true to validate check value */
    int havedict;               /* true if dictionary provided */
    int flags;                  /* gzip header method and flags (0 if zlib) */
    int flags;                  /* gzip header method and flags, 0 if zlib, or
                                   -1 if raw or no header yet */
    unsigned dmax;              /* zlib header max distance (INFLATE_STRICT) */
    unsigned long check;        /* protected copy of check value */
    unsigned long total;        /* protected copy of output count */
    gz_headerp head;            /* where to save gzip header information */
        /* sliding window */
    unsigned wbits;             /* log base 2 of requested window size */
    unsigned wsize;             /* window size or zero if not using window */

Changes to compat/zlib/inftrees.c.

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
30
31
32
33
34
35


36
37

38
39
40
41
42
43
44
45
46
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
30
31




32
33


34


35
36
37
38
39
40
41

-
+









-
+



















-
-
-
-
+
+
-
-
+
-
-







/* inftrees.c -- generate Huffman trees for efficient decoding
 * Copyright (C) 1995-2017 Mark Adler
 * Copyright (C) 1995-2024 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#include "zutil.h"
#include "inftrees.h"

#define MAXBITS 15

const char inflate_copyright[] =
   " inflate 1.2.11 Copyright 1995-2017 Mark Adler ";
   " inflate 1.3.1 Copyright 1995-2024 Mark Adler ";
/*
  If you use the zlib library in a product, an acknowledgment is welcome
  in the documentation of your product. If for some reason you cannot
  include such an acknowledgment, I would appreciate that you keep this
  copyright string in the executable of your product.
 */

/*
   Build a set of tables to decode the provided canonical Huffman code.
   The code lengths are lens[0..codes-1].  The result starts at *table,
   whose indices are 0..2^bits-1.  work is a writable array of at least
   lens shorts, which is used as a work area.  type is the type of code
   to be generated, CODES, LENS, or DISTS.  On return, zero is success,
   -1 is an invalid code, and +1 means that ENOUGH isn't enough.  table
   on return points to the next available entry's address.  bits is the
   requested root table index bits, and on return it is the actual root
   table index bits.  It will differ if the request is greater than the
   longest code or if it is less than the shortest code.
 */
int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
codetype type;
unsigned short FAR *lens;
unsigned codes;
int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
                                unsigned codes, code FAR * FAR *table,
code FAR * FAR *table;
unsigned FAR *bits;
                                unsigned FAR *bits, unsigned short FAR *work) {
unsigned short FAR *work;
{
    unsigned len;               /* a code's length in bits */
    unsigned sym;               /* index of code symbols */
    unsigned min, max;          /* minimum and maximum code lengths */
    unsigned root;              /* number of index bits for root table */
    unsigned curr;              /* number of index bits for current table */
    unsigned drop;              /* code bits to drop for sub-table */
    int left;                   /* number of prefix codes available */
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
53
54
55
56
57
58
59

60
61
62
63
64
65
66
67







-
+







    unsigned short count[MAXBITS+1];    /* number of codes of each length */
    unsigned short offs[MAXBITS+1];     /* offsets in table for each length */
    static const unsigned short lbase[31] = { /* Length codes 257..285 base */
        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
    static const unsigned short lext[31] = { /* Length codes 257..285 extra */
        16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202};
        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 203, 77};
    static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
        8193, 12289, 16385, 24577, 0, 0};
    static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
        16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
        23, 23, 24, 24, 25, 25, 26, 26, 27, 27,

Changes to compat/zlib/inftrees.h.

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



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







-
+


-
-
+
+














-
-
-
+
+
+
    01100000 - end of block
    01000000 - invalid code
 */

/* Maximum size of the dynamic table.  The maximum number of code structures is
   1444, which is the sum of 852 for literal/length codes and 592 for distance
   codes.  These values were found by exhaustive searches using the program
   examples/enough.c found in the zlib distribtution.  The arguments to that
   examples/enough.c found in the zlib distribution.  The arguments to that
   program are the number of symbols, the initial root table size, and the
   maximum bit length of a code.  "enough 286 9 15" for literal/length codes
   returns returns 852, and "enough 30 6 15" for distance codes returns 592.
   The initial root table size (9 or 6) is found in the fifth argument of the
   returns 852, and "enough 30 6 15" for distance codes returns 592. The
   initial root table size (9 or 6) is found in the fifth argument of the
   inflate_table() calls in inflate.c and infback.c.  If the root table size is
   changed, then these maximum sizes would be need to be recalculated and
   updated. */
#define ENOUGH_LENS 852
#define ENOUGH_DISTS 592
#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)

/* Type of code to build for inflate_table() */
typedef enum {
    CODES,
    LENS,
    DISTS
} codetype;

int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
                             unsigned codes, code FAR * FAR *table,
                             unsigned FAR *bits, unsigned short FAR *work));
int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
                                unsigned codes, code FAR * FAR *table,
                                unsigned FAR *bits, unsigned short FAR *work);

Changes to compat/zlib/make_vms.com.

10
11
12
13
14
15
16
17

18
19

20
21
22
23
24
25
26
10
11
12
13
14
15
16

17
18

19
20
21
22
23
24
25
26







-
+

-
+







$!------------------------------------------------------------------------------
$! Version history
$! 0.01 20060120 First version to receive a number
$! 0.02 20061008 Adapt to new Makefile.in
$! 0.03 20091224 Add support for large file check
$! 0.04 20100110 Add new gzclose, gzlib, gzread, gzwrite
$! 0.05 20100221 Exchange zlibdefs.h by zconf.h.in
$! 0.06 20120111 Fix missing amiss_err, update zconf_h.in, fix new exmples
$! 0.06 20120111 Fix missing amiss_err, update zconf_h.in, fix new examples
$!               subdir path, update module search in makefile.in
$! 0.07 20120115 Triggered by work done by Alexey Chupahin completly redesigned
$! 0.07 20120115 Triggered by work done by Alexey Chupahin completely redesigned
$!               shared image creation
$! 0.08 20120219 Make it work on VAX again, pre-load missing symbols to shared
$!               image
$! 0.09 20120305 SMS.  P1 sets builder ("MMK", "MMS", " " (built-in)).
$!               "" -> automatic, preference: MMK, MMS, built-in.
$!
$ on error then goto err_exit

Changes to compat/zlib/old/visual-basic.txt.

111
112
113
114
115
116
117
118

119
120
121
122
123
124
125
111
112
113
114
115
116
117

118
119
120
121
122
123
124
125







-
+







    ReDim bytaryCpr(lngCprSiz - 1)
    If lngfncCpr(bytaryCpr(0), lngCprSiz, bytaryOri(0), lngOriSiz, intLvl) =
SUCCESS Then
        lngpvtPcnSml = (1# - (lngCprSiz / lngOriSiz)) * 100
        ReDim Preserve bytaryCpr(lngCprSiz - 1)
        Open strCprPth For Binary Access Write As #1
            Put #1, , bytaryCpr()
            Put #1, , lngOriSiz 'Add the the original size value to the end
            Put #1, , lngOriSiz 'Add the original size value to the end
(last 4 bytes)
        Close #1
    Else
        MsgBox "Compression error"
    End If
    Erase bytaryCpr
    Erase bytaryOri

Changes to compat/zlib/os400/README400.

1

2
3
4
5
6

7
8
9
10
11
12
13

1
2
3
4
5

6
7
8
9
10
11
12
13
-
+




-
+







        ZLIB version 1.2.11 for OS/400 installation instructions
        ZLIB version 1.3.1 for OS/400 installation instructions

1) Download and unpack the zlib tarball to some IFS directory.
   (i.e.: /path/to/the/zlib/ifs/source/directory)

   If the installed IFS command suppors gzip format, this is straightforward,
   If the installed IFS command supports gzip format, this is straightforward,
else you have to unpack first to some directory on a system supporting it,
then move the whole directory to the IFS via the network (via SMB or FTP).

2) Edit the configuration parameters in the compilation script.

        EDTF STMF('/path/to/the/zlib/ifs/source/directory/os400/make.sh')

39
40
41
42
43
44
45
46

47
48
39
40
41
42
43
44
45

46
47
48







-
+


                In the ILE environment, the same definitions are available from
                file zlib.inc located in the same IFS include directory as the
                C/C++ header files.
                Please read comments in this member for more information.

        Remember that most foreign textual data are ASCII coded: this
                implementation does not handle conversion from/to ASCII, so
                text data code conversions must be done explicitely.
                text data code conversions must be done explicitly.

        Mainly for the reason above, always open zipped files in binary mode.

Changes to compat/zlib/os400/bndsrc.

111
112
113
114
115
116
117








118
119
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127







+
+
+
+
+
+
+
+


  EXPORT SYMBOL("crc32_z")
  EXPORT SYMBOL("deflateGetDictionary")
  EXPORT SYMBOL("gzfread")
  EXPORT SYMBOL("gzfwrite")
  EXPORT SYMBOL("inflateCodesUsed")
  EXPORT SYMBOL("inflateValidate")
  EXPORT SYMBOL("uncompress2")

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
/*   Version 1.2.12 additional entry points.                        */
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

  EXPORT SYMBOL("crc32_combine_gen64")
  EXPORT SYMBOL("crc32_combine_gen")
  EXPORT SYMBOL("crc32_combine_op")

ENDPGMEXP

Changes to compat/zlib/os400/zlib.inc.

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
30

31
32
33
34
35
36
37
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

30
31
32
33
34
35
36
37



-
+




















-
+


-
+

-
+







      *  ZLIB.INC - Interface to the general purpose compression library
      *
      *  ILE RPG400 version by Patrick Monnerat, DATASPHERE.
      *  Version 1.2.11
      *  Version 1.3.1
      *
      *
      *  WARNING:
      *     Procedures inflateInit(), inflateInit2(), deflateInit(),
      *         deflateInit2() and inflateBackInit() need to be called with
      *         two additional arguments:
      *         the package version string and the stream control structure.
      *         size. This is needed because RPG lacks some macro feature.
      *         Call these procedures as:
      *             inflateInit(...: ZLIB_VERSION: %size(z_stream))
      *
      /if not defined(ZLIB_H_)
      /define ZLIB_H_
      *
      **************************************************************************
      *                               Constants
      **************************************************************************
      *
      *  Versioning information.
      *
     D ZLIB_VERSION    C                   '1.2.11'
     D ZLIB_VERSION    C                   '1.3.1'
     D ZLIB_VERNUM     C                   X'12a0'
     D ZLIB_VER_MAJOR  C                   1
     D ZLIB_VER_MINOR  C                   2
     D ZLIB_VER_MINOR  C                   3
     D ZLIB_VER_REVISION...
     D                 C                   11
     D                 C                   1
     D ZLIB_VER_SUBREVISION...
     D                 C                   0
      *
      *  Other equates.
      *
     D Z_NO_FLUSH      C                   0
     D Z_PARTIAL_FLUSH...

Changes to compat/zlib/qnx/package.qpg.

21
22
23
24
25
26
27
28
29
30
31




32
33
34
35
36
37
38
21
22
23
24
25
26
27




28
29
30
31
32
33
34
35
36
37
38







-
-
-
-
+
+
+
+







      <QPG:EmailAddress></QPG:EmailAddress>
   </QPG:Responsible>

   <QPG:Values>
      <QPG:Files>
         <QPG:Add file="../zconf.h" install="/opt/include/" user="root:sys" permission="644"/>
         <QPG:Add file="../zlib.h" install="/opt/include/" user="root:sys" permission="644"/>
         <QPG:Add file="../libz.so.1.2.11" install="/opt/lib/" user="root:bin" permission="644"/>
         <QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.2.11"/>
         <QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.11"/>
         <QPG:Add file="../libz.so.1.2.11" install="/opt/lib/" component="slib"/>
         <QPG:Add file="../libz.so.1.3.1" install="/opt/lib/" user="root:bin" permission="644"/>
         <QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.3.1"/>
         <QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.3.1"/>
         <QPG:Add file="../libz.so.1.3.1" install="/opt/lib/" component="slib"/>
      </QPG:Files>

      <QPG:PackageFilter>
         <QPM:PackageManifest>
            <QPM:PackageDescription>
               <QPM:PackageType>Library</QPM:PackageType>
               <QPM:PackageReleaseNotes></QPM:PackageReleaseNotes>
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73







-
+







               <QPM:ProductDescriptionShort>A massively spiffy yet delicately unobtrusive compression library.</QPM:ProductDescriptionShort>
               <QPM:ProductDescriptionLong>zlib is designed to be a free, general-purpose, legally unencumbered, lossless data compression library for use on virtually any computer hardware and operating system.</QPM:ProductDescriptionLong>
               <QPM:ProductDescriptionURL>http://www.gzip.org/zlib</QPM:ProductDescriptionURL>
               <QPM:ProductDescriptionEmbedURL></QPM:ProductDescriptionEmbedURL>
            </QPM:ProductDescription>

            <QPM:ReleaseDescription>
               <QPM:ReleaseVersion>1.2.11</QPM:ReleaseVersion>
               <QPM:ReleaseVersion>1.3.1</QPM:ReleaseVersion>
               <QPM:ReleaseUrgency>Medium</QPM:ReleaseUrgency>
               <QPM:ReleaseStability>Stable</QPM:ReleaseStability>
               <QPM:ReleaseNoteMinor></QPM:ReleaseNoteMinor>
               <QPM:ReleaseNoteMajor></QPM:ReleaseNoteMajor>
               <QPM:ExcludeCountries>
                  <QPM:Country></QPM:Country>
               </QPM:ExcludeCountries>

Changes to compat/zlib/test/example.c.

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
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








-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


-
-
-
-
+
-
-
-




-
+
-












-
-
-
-
-



-
+
-
-
+
-







static z_const char hello[] = "hello, hello!";
/* "hello world" would be more standard, but the repeated "hello"
 * stresses the compression code better, sorry...
 */

static const char dictionary[] = "hello";
static uLong dictId;    /* Adler32 value of the dictionary */

void test_deflate       OF((Byte *compr, uLong comprLen));
void test_inflate       OF((Byte *compr, uLong comprLen,
                            Byte *uncompr, uLong uncomprLen));
void test_large_deflate OF((Byte *compr, uLong comprLen,
                            Byte *uncompr, uLong uncomprLen));
void test_large_inflate OF((Byte *compr, uLong comprLen,
                            Byte *uncompr, uLong uncomprLen));
void test_flush         OF((Byte *compr, uLong *comprLen));
void test_sync          OF((Byte *compr, uLong comprLen,
                            Byte *uncompr, uLong uncomprLen));
void test_dict_deflate  OF((Byte *compr, uLong comprLen));
void test_dict_inflate  OF((Byte *compr, uLong comprLen,
                            Byte *uncompr, uLong uncomprLen));
int  main               OF((int argc, char *argv[]));


#ifdef Z_SOLO

void *myalloc OF((void *, unsigned, unsigned));
void myfree OF((void *, void *));

void *myalloc(q, n, m)
static void *myalloc(void *q, unsigned n, unsigned m) {
    void *q;
    unsigned n, m;
{
    (void)q;
    return calloc(n, m);
}

void myfree(void *q, void *p)
static void myfree(void *q, void *p) {
{
    (void)q;
    free(p);
}

static alloc_func zalloc = myalloc;
static free_func zfree = myfree;

#else /* !Z_SOLO */

static alloc_func zalloc = (alloc_func)0;
static free_func zfree = (free_func)0;

void test_compress      OF((Byte *compr, uLong comprLen,
                            Byte *uncompr, uLong uncomprLen));
void test_gzio          OF((const char *fname,
                            Byte *uncompr, uLong uncomprLen));

/* ===========================================================================
 * Test compress() and uncompress()
 */
void test_compress(compr, comprLen, uncompr, uncomprLen)
static void test_compress(Byte *compr, uLong comprLen, Byte *uncompr,
    Byte *compr, *uncompr;
    uLong comprLen, uncomprLen;
                   uLong uncomprLen) {
{
    int err;
    uLong len = (uLong)strlen(hello)+1;

    err = compress(compr, &comprLen, (const Bytef*)hello, len);
    CHECK_ERR(err, "compress");

    strcpy((char*)uncompr, "garbage");
107
108
109
110
111
112
113
114
115
116
117

118
119
120
121
122
123
124
125
77
78
79
80
81
82
83




84

85
86
87
88
89
90
91







-
-
-
-
+
-







        printf("uncompress(): %s\n", (char *)uncompr);
    }
}

/* ===========================================================================
 * Test read/write of .gz files
 */
void test_gzio(fname, uncompr, uncomprLen)
    const char *fname; /* compressed file name */
    Byte *uncompr;
    uLong uncomprLen;
static void test_gzio(const char *fname, Byte *uncompr, uLong uncomprLen) {
{
#ifdef NO_GZCOMPRESS
    fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
#else
    int err;
    int len = (int)strlen(hello)+1;
    gzFile file;
    z_off_t pos;
193
194
195
196
197
198
199
200

201
202
203
204
205
206
207
208
209
210
159
160
161
162
163
164
165

166



167
168
169
170
171
172
173







-
+
-
-
-







}

#endif /* Z_SOLO */

/* ===========================================================================
 * Test deflate() with small buffers
 */
void test_deflate(compr, comprLen)
static void test_deflate(Byte *compr, uLong comprLen) {
    Byte *compr;
    uLong comprLen;
{
    z_stream c_stream; /* compression stream */
    int err;
    uLong len = (uLong)strlen(hello)+1;

    c_stream.zalloc = zalloc;
    c_stream.zfree = zfree;
    c_stream.opaque = (voidpf)0;
231
232
233
234
235
236
237
238

239
240

241
242
243
244
245
246
247
248
194
195
196
197
198
199
200

201


202

203
204
205
206
207
208
209







-
+
-
-
+
-







    err = deflateEnd(&c_stream);
    CHECK_ERR(err, "deflateEnd");
}

/* ===========================================================================
 * Test inflate() with small buffers
 */
void test_inflate(compr, comprLen, uncompr, uncomprLen)
static void test_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
    Byte *compr, *uncompr;
    uLong comprLen, uncomprLen;
                  uLong uncomprLen) {
{
    int err;
    z_stream d_stream; /* decompression stream */

    strcpy((char*)uncompr, "garbage");

    d_stream.zalloc = zalloc;
    d_stream.zfree = zfree;
272
273
274
275
276
277
278
279

280
281

282
283
284
285
286
287
288
289
233
234
235
236
237
238
239

240


241

242
243
244
245
246
247
248







-
+
-
-
+
-







        printf("inflate(): %s\n", (char *)uncompr);
    }
}

/* ===========================================================================
 * Test deflate() with large buffers and dynamic change of compression level
 */
void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
static void test_large_deflate(Byte *compr, uLong comprLen, Byte *uncompr,
    Byte *compr, *uncompr;
    uLong comprLen, uncomprLen;
                        uLong uncomprLen) {
{
    z_stream c_stream; /* compression stream */
    int err;

    c_stream.zalloc = zalloc;
    c_stream.zfree = zfree;
    c_stream.opaque = (voidpf)0;

304
305
306
307
308
309
310
311

312
313
314
315
316
317
318
263
264
265
266
267
268
269

270
271
272
273
274
275
276
277







-
+







        fprintf(stderr, "deflate not greedy\n");
        exit(1);
    }

    /* Feed in already compressed data and switch to no compression: */
    deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
    c_stream.next_in = compr;
    c_stream.avail_in = (uInt)comprLen/2;
    c_stream.avail_in = (uInt)uncomprLen/2;
    err = deflate(&c_stream, Z_NO_FLUSH);
    CHECK_ERR(err, "deflate");

    /* Switch back to compressing mode: */
    deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
    c_stream.next_in = uncompr;
    c_stream.avail_in = (uInt)uncomprLen;
327
328
329
330
331
332
333
334

335
336

337
338
339
340
341
342
343
344
286
287
288
289
290
291
292

293


294

295
296
297
298
299
300
301







-
+
-
-
+
-







    err = deflateEnd(&c_stream);
    CHECK_ERR(err, "deflateEnd");
}

/* ===========================================================================
 * Test inflate() with large buffers
 */
void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
static void test_large_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
    Byte *compr, *uncompr;
    uLong comprLen, uncomprLen;
                        uLong uncomprLen) {
{
    int err;
    z_stream d_stream; /* decompression stream */

    strcpy((char*)uncompr, "garbage");

    d_stream.zalloc = zalloc;
    d_stream.zfree = zfree;
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
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







-
+










-
-
-
+
-







        if (err == Z_STREAM_END) break;
        CHECK_ERR(err, "large inflate");
    }

    err = inflateEnd(&d_stream);
    CHECK_ERR(err, "inflateEnd");

    if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
    if (d_stream.total_out != 2*uncomprLen + uncomprLen/2) {
        fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
        exit(1);
    } else {
        printf("large_inflate(): OK\n");
    }
}

/* ===========================================================================
 * Test deflate() with full flush
 */
void test_flush(compr, comprLen)
    Byte *compr;
    uLong *comprLen;
static void test_flush(Byte *compr, uLong *comprLen) {
{
    z_stream c_stream; /* compression stream */
    int err;
    uInt len = (uInt)strlen(hello)+1;

    c_stream.zalloc = zalloc;
    c_stream.zfree = zfree;
    c_stream.opaque = (voidpf)0;
406
407
408
409
410
411
412
413
414
415


416
417
418
419
420
421
422
423
360
361
362
363
364
365
366



367
368

369
370
371
372
373
374
375







-
-
-
+
+
-








    *comprLen = c_stream.total_out;
}

/* ===========================================================================
 * Test inflateSync()
 */
void test_sync(compr, comprLen, uncompr, uncomprLen)
    Byte *compr, *uncompr;
    uLong comprLen, uncomprLen;
static void test_sync(Byte *compr, uLong comprLen, Byte *uncompr,
                      uLong uncomprLen) {
{
    int err;
    z_stream d_stream; /* decompression stream */

    strcpy((char*)uncompr, "garbage");

    d_stream.zalloc = zalloc;
    d_stream.zfree = zfree;
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
467
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







-
-
+
+
-











-
+
-
-
-







    CHECK_ERR(err, "inflate");

    d_stream.avail_in = (uInt)comprLen-2;   /* read all compressed data */
    err = inflateSync(&d_stream);           /* but skip the damaged part */
    CHECK_ERR(err, "inflateSync");

    err = inflate(&d_stream, Z_FINISH);
    if (err != Z_DATA_ERROR) {
        fprintf(stderr, "inflate should report DATA_ERROR\n");
    if (err != Z_STREAM_END) {
        fprintf(stderr, "inflate should report Z_STREAM_END\n");
        /* Because of incorrect adler32 */
        exit(1);
    }
    err = inflateEnd(&d_stream);
    CHECK_ERR(err, "inflateEnd");

    printf("after inflateSync(): hel%s\n", (char *)uncompr);
}

/* ===========================================================================
 * Test deflate() with preset dictionary
 */
void test_dict_deflate(compr, comprLen)
static void test_dict_deflate(Byte *compr, uLong comprLen) {
    Byte *compr;
    uLong comprLen;
{
    z_stream c_stream; /* compression stream */
    int err;

    c_stream.zalloc = zalloc;
    c_stream.zfree = zfree;
    c_stream.opaque = (voidpf)0;

487
488
489
490
491
492
493
494

495
496

497
498
499
500
501
502
503
504
435
436
437
438
439
440
441

442


443

444
445
446
447
448
449
450







-
+
-
-
+
-







    err = deflateEnd(&c_stream);
    CHECK_ERR(err, "deflateEnd");
}

/* ===========================================================================
 * Test inflate() with a preset dictionary
 */
void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
static void test_dict_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
    Byte *compr, *uncompr;
    uLong comprLen, uncomprLen;
                       uLong uncomprLen) {
{
    int err;
    z_stream d_stream; /* decompression stream */

    strcpy((char*)uncompr, "garbage");

    d_stream.zalloc = zalloc;
    d_stream.zfree = zfree;
538
539
540
541
542
543
544
545
546
547

548
549
550
551


552
553
554
555
556
557
558
559


560
561
562
563
564
565
566
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







-
-
-
+
-

-
-
+
+







-
+
+







    }
}

/* ===========================================================================
 * Usage:  example [output.gz  [input.gz]]
 */

int main(argc, argv)
    int argc;
    char *argv[];
int main(int argc, char *argv[]) {
{
    Byte *compr, *uncompr;
    uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
    uLong uncomprLen = comprLen;
    uLong uncomprLen = 20000;
    uLong comprLen = 3 * uncomprLen;
    static const char* myVersion = ZLIB_VERSION;

    if (zlibVersion()[0] != myVersion[0]) {
        fprintf(stderr, "incompatible zlib version\n");
        exit(1);

    } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
        fprintf(stderr, "warning: different zlib version\n");
        fprintf(stderr, "warning: different zlib version linked: %s\n",
                zlibVersion());
    }

    printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",
            ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags());

    compr    = (Byte*)calloc((uInt)comprLen, 1);
    uncompr  = (Byte*)calloc((uInt)uncomprLen, 1);
586
587
588
589
590
591
592
593

594
595
596
597
598
599
600
601
602
530
531
532
533
534
535
536

537
538
539
540
541
542
543
544
545
546







-
+









    test_inflate(compr, comprLen, uncompr, uncomprLen);

    test_large_deflate(compr, comprLen, uncompr, uncomprLen);
    test_large_inflate(compr, comprLen, uncompr, uncomprLen);

    test_flush(compr, &comprLen);
    test_sync(compr, comprLen, uncompr, uncomprLen);
    comprLen = uncomprLen;
    comprLen = 3 * uncomprLen;

    test_dict_deflate(compr, comprLen);
    test_dict_inflate(compr, comprLen, uncompr, uncomprLen);

    free(compr);
    free(uncompr);

    return 0;
}

Changes to compat/zlib/test/infcover.c.

369
370
371
372
373
374
375
376

377
378
379
380
381
382
383
369
370
371
372
373
374
375

376
377
378
379
380
381
382
383







-
+







    inf("63 18 68 30 d0 0 0", "force split window update", 4, -8, 259, Z_OK);
    inf("3 0", "use fixed blocks", 0, -15, 1, Z_STREAM_END);
    inf("", "bad window size", 0, 1, 0, Z_STREAM_ERROR);

    mem_setup(&strm);
    strm.avail_in = 0;
    strm.next_in = Z_NULL;
    ret = inflateInit_(&strm, ZLIB_VERSION - 1, (int)sizeof(z_stream));
    ret = inflateInit_(&strm, "!", (int)sizeof(z_stream));
                                                assert(ret == Z_VERSION_ERROR);
    mem_done(&strm, "wrong version");

    strm.avail_in = 0;
    strm.next_in = Z_NULL;
    ret = inflateInit(&strm);                   assert(ret == Z_OK);
    ret = inflateEnd(&strm);                    assert(ret == Z_OK);
458
459
460
461
462
463
464

465

466
467
468
469
470
471
472
458
459
460
461
462
463
464
465

466
467
468
469
470
471
472
473







+
-
+







    if (state != Z_NULL)
        state->mode = SYNC;     /* force an otherwise impossible situation */
    return next < sizeof(dat) ? (*buf = dat + next++, 1) : 0;
}

local int push(void *desc, unsigned char *buf, unsigned len)
{
    (void)buf;
    buf += len;
    (void)len;
    return desc != Z_NULL;      /* force error if desc not null */
}

/* cover inflateBack() up to common deflate data cases and after those */
local void cover_back(void)
{
    int ret;

Changes to compat/zlib/test/minigzip.c.

55
56
57
58
59
60
61
62

63
64
65
66
67
68
69
55
56
57
58
59
60
61

62
63
64
65
66
67
68
69







-
+







#endif
#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
#  include <unix.h> /* for fileno */
#endif

#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)
#ifndef WIN32 /* unlink already in stdio.h for WIN32 */
  extern int unlink OF((const char *));
  extern int unlink(const char *);
#endif
#endif

#if defined(UNDER_CE)
#  include <windows.h>
#  define perror(s) pwinerror(s)

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
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







-
-
-
-
+
-
-
-




-
+
-
-












-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







#ifdef Z_SOLO
/* for Z_SOLO, create simplified gz* functions using deflate and inflate */

#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)
#  include <unistd.h>       /* for unlink() */
#endif

void *myalloc OF((void *, unsigned, unsigned));
void myfree OF((void *, void *));

void *myalloc(q, n, m)
static void *myalloc(void *q, unsigned n, unsigned m) {
    void *q;
    unsigned n, m;
{
    (void)q;
    return calloc(n, m);
}

void myfree(q, p)
static void myfree(void *q, void *p) {
    void *q, *p;
{
    (void)q;
    free(p);
}

typedef struct gzFile_s {
    FILE *file;
    int write;
    int err;
    char *msg;
    z_stream strm;
} *gzFile;

gzFile gzopen OF((const char *, const char *));
gzFile gzdopen OF((int, const char *));
gzFile gz_open OF((const char *, int, const char *));

gzFile gzopen(path, mode)
const char *path;
static gzFile gz_open(const char *path, int fd, const char *mode) {
const char *mode;
{
    return gz_open(path, -1, mode);
}

gzFile gzdopen(fd, mode)
int fd;
const char *mode;
{
    return gz_open(NULL, fd, mode);
}

gzFile gz_open(path, fd, mode)
    const char *path;
    int fd;
    const char *mode;
{
    gzFile gz;
    int ret;

    gz = malloc(sizeof(struct gzFile_s));
    if (gz == NULL)
        return NULL;
    gz->write = strchr(mode, 'w') != NULL;
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
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







-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+

















-
-
-
-
-
-
+
-







        return NULL;
    }
    gz->err = 0;
    gz->msg = "";
    return gz;
}

int gzwrite OF((gzFile, const void *, unsigned));

int gzwrite(gz, buf, len)
    gzFile gz;
static gzFile gzopen(const char *path, const char *mode) {
    return gz_open(path, -1, mode);
}

static gzFile gzdopen(int fd, const char *mode) {
    const void *buf;
    unsigned len;
{
    return gz_open(NULL, fd, mode);
}

static int gzwrite(gzFile gz, const void *buf, unsigned len) {
    z_stream *strm;
    unsigned char out[BUFLEN];

    if (gz == NULL || !gz->write)
        return 0;
    strm = &(gz->strm);
    strm->next_in = (void *)buf;
    strm->avail_in = len;
    do {
        strm->next_out = out;
        strm->avail_out = BUFLEN;
        (void)deflate(strm, Z_NO_FLUSH);
        fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
    } while (strm->avail_out == 0);
    return len;
}

int gzread OF((gzFile, void *, unsigned));

int gzread(gz, buf, len)
    gzFile gz;
    void *buf;
    unsigned len;
static int gzread(gzFile gz, void *buf, unsigned len) {
{
    int ret;
    unsigned got;
    unsigned char in[1];
    z_stream *strm;

    if (gz == NULL || gz->write)
        return 0;
288
289
290
291
292
293
294
295
296
297

298
299
300
301
302
303
304
305
306
254
255
256
257
258
259
260



261


262
263
264
265
266
267
268







-
-
-
+
-
-







        }
        if (ret == Z_STREAM_END)
            inflateReset(strm);
    } while (strm->avail_out);
    return len - strm->avail_out;
}

int gzclose OF((gzFile));

int gzclose(gz)
static int gzclose(gzFile gz) {
    gzFile gz;
{
    z_stream *strm;
    unsigned char out[BUFLEN];

    if (gz == NULL)
        return Z_STREAM_ERROR;
    strm = &(gz->strm);
    if (gz->write) {
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
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
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







-
-
-
+
-
-
-








-
-
-
-
-
-
-
-
-
-



-
-
+
-




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-



-
+

-
+
-
-
-







    else
        inflateEnd(strm);
    fclose(gz->file);
    free(gz);
    return Z_OK;
}

const char *gzerror OF((gzFile, int *));

const char *gzerror(gz, err)
static const char *gzerror(gzFile gz, int *err) {
    gzFile gz;
    int *err;
{
    *err = gz->err;
    return gz->msg;
}

#endif

static char *prog;

void error            OF((const char *msg));
void gz_compress      OF((FILE   *in, gzFile out));
#ifdef USE_MMAP
int  gz_compress_mmap OF((FILE   *in, gzFile out));
#endif
void gz_uncompress    OF((gzFile in, FILE   *out));
void file_compress    OF((char  *file, char *mode));
void file_uncompress  OF((char  *file));
int  main             OF((int argc, char *argv[]));

/* ===========================================================================
 * Display error message and exit
 */
void error(msg)
    const char *msg;
static void error(const char *msg) {
{
    fprintf(stderr, "%s: %s\n", prog, msg);
    exit(1);
}

/* ===========================================================================
 * Compress input to output then close both files.
 */

void gz_compress(in, out)
    FILE   *in;
    gzFile out;
{
    local char buf[BUFLEN];
    int len;
    int err;

#ifdef USE_MMAP
    /* Try first compressing with mmap. If mmap fails (minigzip used in a
     * pipe), use the normal fread loop.
     */
    if (gz_compress_mmap(in, out) == Z_OK) return;
#endif
    for (;;) {
        len = (int)fread(buf, 1, sizeof(buf), in);
        if (ferror(in)) {
            perror("fread");
            exit(1);
        }
        if (len == 0) break;

        if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
    }
    fclose(in);
    if (gzclose(out) != Z_OK) error("failed gzclose");
}

#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */

/* Try compressing the input file at once using mmap. Return Z_OK if
 * if success, Z_ERRNO otherwise.
 * success, Z_ERRNO otherwise.
 */
int gz_compress_mmap(in, out)
static int gz_compress_mmap(FILE *in, gzFile out) {
    FILE   *in;
    gzFile out;
{
    int len;
    int err;
    int ifd = fileno(in);
    caddr_t buf;    /* mmap'ed buffer for the entire input file */
    off_t buf_len;  /* length of the input file */
    struct stat sb;

419
420
421
422
423
424
425
426
427
428

429
430
431
432
433






























434
435
436
437
438
439
440
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
366
367
368
369
370
371
372
373
374
375
376









-
+

-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








    munmap(buf, buf_len);
    fclose(in);
    if (gzclose(out) != Z_OK) error("failed gzclose");
    return Z_OK;
}
#endif /* USE_MMAP */

/* ===========================================================================
 * Uncompress input to output then close both files.
 * Compress input to output then close both files.
 */
void gz_uncompress(in, out)
    gzFile in;
    FILE   *out;
{

static void gz_compress(FILE *in, gzFile out) {
    local char buf[BUFLEN];
    int len;
    int err;

#ifdef USE_MMAP
    /* Try first compressing with mmap. If mmap fails (minigzip used in a
     * pipe), use the normal fread loop.
     */
    if (gz_compress_mmap(in, out) == Z_OK) return;
#endif
    for (;;) {
        len = (int)fread(buf, 1, sizeof(buf), in);
        if (ferror(in)) {
            perror("fread");
            exit(1);
        }
        if (len == 0) break;

        if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
    }
    fclose(in);
    if (gzclose(out) != Z_OK) error("failed gzclose");
}

/* ===========================================================================
 * Uncompress input to output then close both files.
 */
static void gz_uncompress(gzFile in, FILE *out) {
    local char buf[BUFLEN];
    int len;
    int err;

    for (;;) {
        len = gzread(in, buf, sizeof(buf));
        if (len < 0) error (gzerror(in, &err));
450
451
452
453
454
455
456
457

458
459
460
461
462
463
464
465
466
467
386
387
388
389
390
391
392

393



394
395
396
397
398
399
400







-
+
-
-
-







}


/* ===========================================================================
 * Compress the given file: create a corresponding .gz file and remove the
 * original.
 */
void file_compress(file, mode)
static void file_compress(char *file, char *mode) {
    char  *file;
    char  *mode;
{
    local char outfile[MAX_NAME_LEN];
    FILE  *in;
    gzFile out;

    if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
        fprintf(stderr, "%s: filename too long\n", prog);
        exit(1);
489
490
491
492
493
494
495
496

497
498
499
500
501
502
503

504
505
506
507
508
509
510
422
423
424
425
426
427
428

429


430
431
432
433

434
435
436
437
438
439
440
441







-
+
-
-




-
+







    unlink(file);
}


/* ===========================================================================
 * Uncompress the given file and remove the original.
 */
void file_uncompress(file)
static void file_uncompress(char *file) {
    char  *file;
{
    local char buf[MAX_NAME_LEN];
    char *infile, *outfile;
    FILE  *out;
    gzFile in;
    unsigned len = strlen(file);
    z_size_t len = strlen(file);

    if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {
        fprintf(stderr, "%s: filename too long\n", prog);
        exit(1);
    }

#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
549
550
551
552
553
554
555
556
557
558

559
560
561
562
563
564
565
566
480
481
482
483
484
485
486



487

488
489
490
491
492
493
494







-
-
-
+
-







 *   -d : decompress
 *   -f : compress with Z_FILTERED
 *   -h : compress with Z_HUFFMAN_ONLY
 *   -r : compress with Z_RLE
 *   -1 to -9 : compression level
 */

int main(argc, argv)
    int argc;
    char *argv[];
int main(int argc, char *argv[]) {
{
    int copyout = 0;
    int uncompr = 0;
    gzFile file;
    char *bname, outmode[20];

#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
    snprintf(outmode, sizeof(outmode), "%s", "wb6 ");

Changes to compat/zlib/treebuild.xml.

1
2
3


4
5
6
7
8
9
10
1


2
3
4
5
6
7
8
9
10

-
-
+
+







<?xml version="1.0" ?>
<package name="zlib" version="1.2.11">
    <library name="zlib" dlversion="1.2.11" dlname="z">
<package name="zlib" version="1.3.1">
    <library name="zlib" dlversion="1.3.1" dlname="z">
	<property name="description"> zip compression library </property>
	<property name="include-target-dir" value="$(@PACKAGE/install-includedir)" />

	<!-- fixme: not implemented yet -->
	<property name="compiler/c/inline" value="yes" />

	<include-file name="zlib.h" scope="public" mode="644" />

Changes to compat/zlib/trees.c.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/* trees.c -- output deflated data using Huffman coding
 * Copyright (C) 1995-2017 Jean-loup Gailly
 * Copyright (C) 1995-2024 Jean-loup Gailly
 * detect_data_type() function provided freely by Cosmin Truta, 2006
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/*
 *  ALGORITHM
 *
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
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







+
+
+
+
+
+
-
+


-
+


-
+



+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+

+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
-
+
-
-
-
+
+
+
-
-
+
+
+
+
+

-
+












-
-
-
-
-
-
-
-
-





-
+
-
-
-
-
-
-





-
+







    const ct_data *static_tree;  /* static tree or NULL */
    const intf *extra_bits;      /* extra bits for each code or NULL */
    int     extra_base;          /* base index for extra_bits */
    int     elems;               /* max number of elements in the tree */
    int     max_length;          /* max bit length for the codes */
};

#ifdef NO_INIT_GLOBAL_POINTERS
#  define TCONST
#else
#  define TCONST const
#endif

local const static_tree_desc  static_l_desc =
local TCONST static_tree_desc static_l_desc =
{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};

local const static_tree_desc  static_d_desc =
local TCONST static_tree_desc static_d_desc =
{static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS};

local const static_tree_desc  static_bl_desc =
local TCONST static_tree_desc static_bl_desc =
{(const ct_data *)0, extra_blbits, 0,   BL_CODES, MAX_BL_BITS};

/* ===========================================================================
 * Output a short LSB first on the stream.
 * IN assertion: there is enough room in pendingBuf.
 */
#define put_short(s, w) { \
    put_byte(s, (uch)((w) & 0xff)); \
    put_byte(s, (uch)((ush)(w) >> 8)); \
}
 * Local (static) routines in this file.

/* ===========================================================================
 * Reverse the first len bits of a code, using straightforward code (a faster
 * method would use a table)
 * IN assertion: 1 <= len <= 15
 */
local unsigned bi_reverse(unsigned code, int len) {
    register unsigned res = 0;
    do {
        res |= code & 1;
        code >>= 1, res <<= 1;
    } while (--len > 0);
    return res >> 1;
}

/* ===========================================================================
 * Flush the bit buffer, keeping at most 7 bits in it.
 */
local void bi_flush(deflate_state *s) {
    if (s->bi_valid == 16) {
        put_short(s, s->bi_buf);
        s->bi_buf = 0;
        s->bi_valid = 0;
    } else if (s->bi_valid >= 8) {
        put_byte(s, (Byte)s->bi_buf);
        s->bi_buf >>= 8;
        s->bi_valid -= 8;
    }
}

/* ===========================================================================
 * Flush the bit buffer and align the output on a byte boundary
 */
local void bi_windup(deflate_state *s) {
    if (s->bi_valid > 8) {
        put_short(s, s->bi_buf);
    } else if (s->bi_valid > 0) {
        put_byte(s, (Byte)s->bi_buf);
    }
    s->bi_buf = 0;
    s->bi_valid = 0;
#ifdef ZLIB_DEBUG
    s->bits_sent = (s->bits_sent + 7) & ~7;
#endif
}

/* ===========================================================================
 * Generate the codes for a given tree and bit counts (which need not be
 * optimal).
 * IN assertion: the array bl_count contains the bit length statistics for
 * the given tree and the field len is set for all tree elements.
 * OUT assertion: the field code is set for all tree elements of non
 *     zero code length.
 */
local void gen_codes(ct_data *tree, int max_code, ushf *bl_count) {
    ush next_code[MAX_BITS+1]; /* next code value for each bit length */
    unsigned code = 0;         /* running code value */
    int bits;                  /* bit index */
    int n;                     /* code index */

    /* The distribution counts are first used to generate the code values
local void tr_static_init OF((void));
     * without bit reversal.
local void init_block     OF((deflate_state *s));
local void pqdownheap     OF((deflate_state *s, ct_data *tree, int k));
local void gen_bitlen     OF((deflate_state *s, tree_desc *desc));
local void gen_codes      OF((ct_data *tree, int max_code, ushf *bl_count));
local void build_tree     OF((deflate_state *s, tree_desc *desc));
local void scan_tree      OF((deflate_state *s, ct_data *tree, int max_code));
     */
    for (bits = 1; bits <= MAX_BITS; bits++) {
        code = (code + bl_count[bits - 1]) << 1;
        next_code[bits] = (ush)code;
    }
    /* Check that the bit counts in bl_count are consistent. The last code
     * must be all ones.
     */
    Assert (code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1,
            "inconsistent bit counts");
    Tracev((stderr,"\ngen_codes: max_code %d ", max_code));

    for (n = 0;  n <= max_code; n++) {
local void send_tree      OF((deflate_state *s, ct_data *tree, int max_code));
local int  build_bl_tree  OF((deflate_state *s));
local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
                              int blcodes));
        int len = tree[n].Len;
local void compress_block OF((deflate_state *s, const ct_data *ltree,
                              const ct_data *dtree));
        if (len == 0) continue;
local int  detect_data_type OF((deflate_state *s));
local unsigned bi_reverse OF((unsigned value, int length));
local void bi_windup      OF((deflate_state *s));
        /* Now reverse the bits */
        tree[n].Code = (ush)bi_reverse(next_code[len]++, len);

local void bi_flush       OF((deflate_state *s));

        Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
            n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len] - 1));
    }
}

#ifdef GEN_TREES_H
local void gen_trees_header OF((void));
local void gen_trees_header(void);
#endif

#ifndef ZLIB_DEBUG
#  define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
   /* Send a code of the given tree. c and tree must not have side effects */

#else /* !ZLIB_DEBUG */
#  define send_code(s, c, tree) \
     { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
       send_bits(s, tree[c].Code, tree[c].Len); }
#endif

/* ===========================================================================
 * Output a short LSB first on the stream.
 * IN assertion: there is enough room in pendingBuf.
 */
#define put_short(s, w) { \
    put_byte(s, (uch)((w) & 0xff)); \
    put_byte(s, (uch)((ush)(w) >> 8)); \
}

/* ===========================================================================
 * Send a value on a given number of bits.
 * IN assertion: length <= 16 and value fits in length bits.
 */
#ifdef ZLIB_DEBUG
local void send_bits      OF((deflate_state *s, int value, int length));
local void send_bits(deflate_state *s, int value, int length) {

local void send_bits(s, value, length)
    deflate_state *s;
    int value;  /* value to send */
    int length; /* number of bits */
{
    Tracevv((stderr," l %2d v %4x ", length, value));
    Assert(length > 0 && length <= 15, "invalid length");
    s->bits_sent += (ulg)length;

    /* If not enough room in bi_buf, use (valid) bits from bi_buf and
     * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
     * (16 - bi_valid) bits from value, leaving (width - (16 - bi_valid))
     * unused bits in value.
     */
    if (s->bi_valid > (int)Buf_size - length) {
        s->bi_buf |= (ush)value << s->bi_valid;
        put_short(s, s->bi_buf);
        s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
        s->bi_valid += length - Buf_size;
225
226
227
228
229
230
231
232

233
234
235
236
237
238
239
240
287
288
289
290
291
292
293

294

295
296
297
298
299
300
301







-
+
-









/* the arguments must not have side effects */

/* ===========================================================================
 * Initialize the various 'constant' tables.
 */
local void tr_static_init()
local void tr_static_init(void) {
{
#if defined(GEN_TREES_H) || !defined(STDC)
    static int static_init_done = 0;
    int n;        /* iterates over tree elements */
    int bits;     /* bit counter */
    int length;   /* length value */
    int code;     /* code value */
    int dist;     /* distance index */
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
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







-
+








-
+





-
+







-
+



-
+







    static_bl_desc.extra_bits = extra_blbits;
#endif

    /* Initialize the mapping length (0..255) -> length code (0..28) */
    length = 0;
    for (code = 0; code < LENGTH_CODES-1; code++) {
        base_length[code] = length;
        for (n = 0; n < (1<<extra_lbits[code]); n++) {
        for (n = 0; n < (1 << extra_lbits[code]); n++) {
            _length_code[length++] = (uch)code;
        }
    }
    Assert (length == 256, "tr_static_init: length != 256");
    /* Note that the length 255 (match length 258) can be represented
     * in two different ways: code 284 + 5 bits or code 285, so we
     * overwrite length_code[255] to use the best encoding:
     */
    _length_code[length-1] = (uch)code;
    _length_code[length - 1] = (uch)code;

    /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
    dist = 0;
    for (code = 0 ; code < 16; code++) {
        base_dist[code] = dist;
        for (n = 0; n < (1<<extra_dbits[code]); n++) {
        for (n = 0; n < (1 << extra_dbits[code]); n++) {
            _dist_code[dist++] = (uch)code;
        }
    }
    Assert (dist == 256, "tr_static_init: dist != 256");
    dist >>= 7; /* from now on, all distances are divided by 128 */
    for ( ; code < D_CODES; code++) {
        base_dist[code] = dist << 7;
        for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
        for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {
            _dist_code[256 + dist++] = (uch)code;
        }
    }
    Assert (dist == 256, "tr_static_init: 256+dist != 512");
    Assert (dist == 256, "tr_static_init: 256 + dist != 512");

    /* Construct the codes of the static literal tree */
    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
    n = 0;
    while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
    while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
    while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
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
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







-
+








-
+

-
+
-







#  ifdef GEN_TREES_H
    gen_trees_header();
#  endif
#endif /* defined(GEN_TREES_H) || !defined(STDC) */
}

/* ===========================================================================
 * Genererate the file trees.h describing the static trees.
 * Generate the file trees.h describing the static trees.
 */
#ifdef GEN_TREES_H
#  ifndef ZLIB_DEBUG
#    include <stdio.h>
#  endif

#  define SEPARATOR(i, last, width) \
      ((i) == (last)? "\n};\n\n" :    \
       ((i) % (width) == (width)-1 ? ",\n" : ", "))
       ((i) % (width) == (width) - 1 ? ",\n" : ", "))

void gen_trees_header()
void gen_trees_header(void) {
{
    FILE *header = fopen("trees.h", "w");
    int i;

    Assert (header != NULL, "Can't open trees.h");
    fprintf(header,
            "/* header created automatically with -DGEN_TREES_H */\n\n");

368
369
370
371
372
373
374
















375
376
377
378
379

380
381
382
383
384
385
386
387
388
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+
-
-







        fprintf(header, "%5u%s", base_dist[i],
                SEPARATOR(i, D_CODES-1, 10));
    }

    fclose(header);
}
#endif /* GEN_TREES_H */

/* ===========================================================================
 * Initialize a new block.
 */
local void init_block(deflate_state *s) {
    int n; /* iterates over tree elements */

    /* Initialize the trees. */
    for (n = 0; n < L_CODES;  n++) s->dyn_ltree[n].Freq = 0;
    for (n = 0; n < D_CODES;  n++) s->dyn_dtree[n].Freq = 0;
    for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;

    s->dyn_ltree[END_BLOCK].Freq = 1;
    s->opt_len = s->static_len = 0L;
    s->sym_next = s->matches = 0;
}

/* ===========================================================================
 * Initialize the tree data structures for a new zlib stream.
 */
void ZLIB_INTERNAL _tr_init(s)
void ZLIB_INTERNAL _tr_init(deflate_state *s) {
    deflate_state *s;
{
    tr_static_init();

    s->l_desc.dyn_tree = s->dyn_ltree;
    s->l_desc.stat_desc = &static_l_desc;

    s->d_desc.dyn_tree = s->dyn_dtree;
    s->d_desc.stat_desc = &static_d_desc;
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
471
472
473
474
475
476
477


















478
479
480
481
482
483
484







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    s->bits_sent = 0L;
#endif

    /* Initialize the first block of the first file: */
    init_block(s);
}

/* ===========================================================================
 * Initialize a new block.
 */
local void init_block(s)
    deflate_state *s;
{
    int n; /* iterates over tree elements */

    /* Initialize the trees. */
    for (n = 0; n < L_CODES;  n++) s->dyn_ltree[n].Freq = 0;
    for (n = 0; n < D_CODES;  n++) s->dyn_dtree[n].Freq = 0;
    for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;

    s->dyn_ltree[END_BLOCK].Freq = 1;
    s->opt_len = s->static_len = 0L;
    s->last_lit = s->matches = 0;
}

#define SMALLEST 1
/* Index within the heap array of least frequent node in the Huffman tree */


/* ===========================================================================
 * Remove the smallest element from the heap and recreate the heap with
 * one less element. Updates heap and heap_len.
444
445
446
447
448
449
450
451

452
453
454
455
456
457
458
459
460
461

462
463
464
465
466
467
468
500
501
502
503
504
505
506

507




508
509
510
511
512

513
514
515
516
517
518
519
520







-
+
-
-
-
-





-
+








/* ===========================================================================
 * Restore the heap property by moving down the tree starting at node k,
 * exchanging a node with the smallest of its two sons if necessary, stopping
 * when the heap property is re-established (each father smaller than its
 * two sons).
 */
local void pqdownheap(s, tree, k)
local void pqdownheap(deflate_state *s, ct_data *tree, int k) {
    deflate_state *s;
    ct_data *tree;  /* the tree to restore */
    int k;               /* node to move down */
{
    int v = s->heap[k];
    int j = k << 1;  /* left son of k */
    while (j <= s->heap_len) {
        /* Set j to the smallest of the two sons: */
        if (j < s->heap_len &&
            smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
            smaller(tree, s->heap[j + 1], s->heap[j], s->depth)) {
            j++;
        }
        /* Exit if v is smaller than both sons */
        if (smaller(tree, v, s->heap[j], s->depth)) break;

        /* Exchange v with the smallest son */
        s->heap[k] = s->heap[j];  k = j;
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
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
558

559
560
561
562
563
564
565
566
567
568
569

570
571
572
573
574
575
576
577
578
579
580
581

582
583


584
585
586
587
588
589
590
591
592







-
+
-
-
-




















-
+










-
+











-
+

-
-
+
+







 * IN assertion: the fields freq and dad are set, heap[heap_max] and
 *    above are the tree nodes sorted by increasing frequency.
 * OUT assertions: the field len is set to the optimal bit length, the
 *     array bl_count contains the frequencies for each bit length.
 *     The length opt_len is updated; static_len is also updated if stree is
 *     not null.
 */
local void gen_bitlen(s, desc)
local void gen_bitlen(deflate_state *s, tree_desc *desc) {
    deflate_state *s;
    tree_desc *desc;    /* the tree descriptor */
{
    ct_data *tree        = desc->dyn_tree;
    int max_code         = desc->max_code;
    const ct_data *stree = desc->stat_desc->static_tree;
    const intf *extra    = desc->stat_desc->extra_bits;
    int base             = desc->stat_desc->extra_base;
    int max_length       = desc->stat_desc->max_length;
    int h;              /* heap index */
    int n, m;           /* iterate over the tree elements */
    int bits;           /* bit length */
    int xbits;          /* extra bits */
    ush f;              /* frequency */
    int overflow = 0;   /* number of elements with bit length too large */

    for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;

    /* In a first pass, compute the optimal bit lengths (which may
     * overflow in the case of the bit length tree).
     */
    tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */

    for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
    for (h = s->heap_max + 1; h < HEAP_SIZE; h++) {
        n = s->heap[h];
        bits = tree[tree[n].Dad].Len + 1;
        if (bits > max_length) bits = max_length, overflow++;
        tree[n].Len = (ush)bits;
        /* We overwrite tree[n].Dad which is no longer needed */

        if (n > max_code) continue; /* not a leaf node */

        s->bl_count[bits]++;
        xbits = 0;
        if (n >= base) xbits = extra[n-base];
        if (n >= base) xbits = extra[n - base];
        f = tree[n].Freq;
        s->opt_len += (ulg)f * (unsigned)(bits + xbits);
        if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits);
    }
    if (overflow == 0) return;

    Tracev((stderr,"\nbit length overflow\n"));
    /* This happens for example on obj2 and pic of the Calgary corpus */

    /* Find the first bit length which could increase: */
    do {
        bits = max_length-1;
        bits = max_length - 1;
        while (s->bl_count[bits] == 0) bits--;
        s->bl_count[bits]--;      /* move one leaf down the tree */
        s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
        s->bl_count[bits]--;        /* move one leaf down the tree */
        s->bl_count[bits + 1] += 2; /* move one overflow item as its brother */
        s->bl_count[max_length]--;
        /* The brother of the overflow item also moves one step up,
         * but this does not affect bl_count[max_length]
         */
        overflow -= 2;
    } while (overflow > 0);

557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581

582
583
584
585
586
587
588
589
590
591
592
593
594
595

596
597
598
599
600
601

602
603
604
605
606
607
608
609
610
611
612
613
614
615

616
617
618
619
620
621
622
623
624
625
626
627

628
629
630
631
632
633
634
606
607
608
609
610
611
612


















613














614






615




616
617
618
619
620
621
622
623
624

625



626
627
628
629
630
631
632
633

634
635
636
637
638
639
640
641







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-









-
+
-
-
-








-
+







                tree[m].Len = (ush)bits;
            }
            n--;
        }
    }
}

/* ===========================================================================
 * Generate the codes for a given tree and bit counts (which need not be
 * optimal).
 * IN assertion: the array bl_count contains the bit length statistics for
 * the given tree and the field len is set for all tree elements.
 * OUT assertion: the field code is set for all tree elements of non
 *     zero code length.
 */
local void gen_codes (tree, max_code, bl_count)
    ct_data *tree;             /* the tree to decorate */
    int max_code;              /* largest code with non zero frequency */
    ushf *bl_count;            /* number of codes at each bit length */
{
    ush next_code[MAX_BITS+1]; /* next code value for each bit length */
    unsigned code = 0;         /* running code value */
    int bits;                  /* bit index */
    int n;                     /* code index */

#ifdef DUMP_BL_TREE
    /* The distribution counts are first used to generate the code values
     * without bit reversal.
     */
    for (bits = 1; bits <= MAX_BITS; bits++) {
        code = (code + bl_count[bits-1]) << 1;
        next_code[bits] = (ush)code;
    }
    /* Check that the bit counts in bl_count are consistent. The last code
     * must be all ones.
     */
    Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
            "inconsistent bit counts");
    Tracev((stderr,"\ngen_codes: max_code %d ", max_code));

#  include <stdio.h>
    for (n = 0;  n <= max_code; n++) {
        int len = tree[n].Len;
        if (len == 0) continue;
        /* Now reverse the bits */
        tree[n].Code = (ush)bi_reverse(next_code[len]++, len);

#endif
        Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
             n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
    }
}

/* ===========================================================================
 * Construct one Huffman tree and assigns the code bit strings and lengths.
 * Update the total bit length for the current block.
 * IN assertion: the field freq is set for all tree elements.
 * OUT assertions: the fields len and code are set to the optimal bit length
 *     and corresponding code. The length opt_len is updated; static_len is
 *     also updated if stree is not null. The field max_code is set.
 */
local void build_tree(s, desc)
local void build_tree(deflate_state *s, tree_desc *desc) {
    deflate_state *s;
    tree_desc *desc; /* the tree descriptor */
{
    ct_data *tree         = desc->dyn_tree;
    const ct_data *stree  = desc->stat_desc->static_tree;
    int elems             = desc->stat_desc->elems;
    int n, m;          /* iterate over heap elements */
    int max_code = -1; /* largest code with non zero frequency */
    int node;          /* new node being created */

    /* Construct the initial heap, with least frequent element in
     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n + 1].
     * heap[0] is not used.
     */
    s->heap_len = 0, s->heap_max = HEAP_SIZE;

    for (n = 0; n < elems; n++) {
        if (tree[n].Freq != 0) {
            s->heap[++(s->heap_len)] = max_code = n;
648
649
650
651
652
653
654
655

656
657
658
659
660
661
662
655
656
657
658
659
660
661

662
663
664
665
666
667
668
669







-
+







        tree[node].Freq = 1;
        s->depth[node] = 0;
        s->opt_len--; if (stree) s->static_len -= stree[node].Len;
        /* node is 0 or 1 so it does not have extra bits */
    }
    desc->max_code = max_code;

    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
    /* The elements heap[heap_len/2 + 1 .. heap_len] are leaves of the tree,
     * establish sub-heaps of increasing lengths:
     */
    for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);

    /* Construct the Huffman tree by repeatedly combining the least two
     * frequent nodes.
     */
696
697
698
699
700
701
702
703

704
705
706
707
708
709
710
711
712
713
714
715
716
717

718
719
720

721
722
723
724
725
726
727
703
704
705
706
707
708
709

710




711
712
713
714
715
716
717
718
719

720
721
722

723
724
725
726
727
728
729
730







-
+
-
-
-
-









-
+


-
+







    gen_codes ((ct_data *)tree, max_code, s->bl_count);
}

/* ===========================================================================
 * Scan a literal or distance tree to determine the frequencies of the codes
 * in the bit length tree.
 */
local void scan_tree (s, tree, max_code)
local void scan_tree(deflate_state *s, ct_data *tree, int max_code) {
    deflate_state *s;
    ct_data *tree;   /* the tree to be scanned */
    int max_code;    /* and its largest code of non zero frequency */
{
    int n;                     /* iterates over all tree elements */
    int prevlen = -1;          /* last emitted length */
    int curlen;                /* length of current code */
    int nextlen = tree[0].Len; /* length of next code */
    int count = 0;             /* repeat count of the current code */
    int max_count = 7;         /* max repeat count */
    int min_count = 4;         /* min repeat count */

    if (nextlen == 0) max_count = 138, min_count = 3;
    tree[max_code+1].Len = (ush)0xffff; /* guard */
    tree[max_code + 1].Len = (ush)0xffff; /* guard */

    for (n = 0; n <= max_code; n++) {
        curlen = nextlen; nextlen = tree[n+1].Len;
        curlen = nextlen; nextlen = tree[n + 1].Len;
        if (++count < max_count && curlen == nextlen) {
            continue;
        } else if (count < min_count) {
            s->bl_tree[curlen].Freq += count;
        } else if (curlen != 0) {
            if (curlen != prevlen) s->bl_tree[curlen].Freq++;
            s->bl_tree[REP_3_6].Freq++;
741
742
743
744
745
746
747
748

749
750
751
752
753
754
755
756
757
758
759
760
761

762
763
764
765

766
767
768
769
770
771
772
773
774
775
776

777
778
779

780
781
782

783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799

800
801
802
803
804
805
806
807
808
809
810
811


812
813
814
815
816
817
818
819
820
821
822

823
824
825
826
827
828
829
830
831
832
833
834

835
836

837
838
839
840
841
842
843
844
845
846



847
848
849
850
851
852
853

854
855
856

857
858
859
860
861
862
863

864
865
866

867
868
869

870
871
872

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
898
899
900
901
902
903
904
905
































































































906
907
908
909
910
911

912
913
914

915
916
917
918
919
920
921
922
923
744
745
746
747
748
749
750

751




752
753
754
755
756
757
758
759

760
761
762
763

764
765
766
767
768
769
770
771
772
773
774

775
776
777

778
779
780

781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797

798


799
800
801
802
803
804
805
806


807
808
809
810
811
812
813
814
815
816
817
818

819
820
821
822
823
824
825
826
827
828
829
830

831


832

833
834
835
836
837
838



839
840
841
842
843
844
845
846
847

848
849
850

851
852
853
854
855
856
857

858



859



860
861
862
863
864

865
866
867
868
869
870

871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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







-
+
-
-
-
-








-
+



-
+










-
+


-
+


-
+
















-
+
-
-








-
-
+
+










-
+











-
+
-
-
+
-






-
-
-
+
+
+






-
+


-
+






-
+
-
-
-
+
-
-
-
+



+
-
+





-
+






-
+
-
-







-
+
-
-







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+
-
-
-
+
-
-







    }
}

/* ===========================================================================
 * Send a literal or distance tree in compressed form, using the codes in
 * bl_tree.
 */
local void send_tree (s, tree, max_code)
local void send_tree(deflate_state *s, ct_data *tree, int max_code) {
    deflate_state *s;
    ct_data *tree; /* the tree to be scanned */
    int max_code;       /* and its largest code of non zero frequency */
{
    int n;                     /* iterates over all tree elements */
    int prevlen = -1;          /* last emitted length */
    int curlen;                /* length of current code */
    int nextlen = tree[0].Len; /* length of next code */
    int count = 0;             /* repeat count of the current code */
    int max_count = 7;         /* max repeat count */
    int min_count = 4;         /* min repeat count */

    /* tree[max_code+1].Len = -1; */  /* guard already set */
    /* tree[max_code + 1].Len = -1; */  /* guard already set */
    if (nextlen == 0) max_count = 138, min_count = 3;

    for (n = 0; n <= max_code; n++) {
        curlen = nextlen; nextlen = tree[n+1].Len;
        curlen = nextlen; nextlen = tree[n + 1].Len;
        if (++count < max_count && curlen == nextlen) {
            continue;
        } else if (count < min_count) {
            do { send_code(s, curlen, s->bl_tree); } while (--count != 0);

        } else if (curlen != 0) {
            if (curlen != prevlen) {
                send_code(s, curlen, s->bl_tree); count--;
            }
            Assert(count >= 3 && count <= 6, " 3_6?");
            send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
            send_code(s, REP_3_6, s->bl_tree); send_bits(s, count - 3, 2);

        } else if (count <= 10) {
            send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
            send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count - 3, 3);

        } else {
            send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
            send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count - 11, 7);
        }
        count = 0; prevlen = curlen;
        if (nextlen == 0) {
            max_count = 138, min_count = 3;
        } else if (curlen == nextlen) {
            max_count = 6, min_count = 3;
        } else {
            max_count = 7, min_count = 4;
        }
    }
}

/* ===========================================================================
 * Construct the Huffman tree for the bit lengths and return the index in
 * bl_order of the last bit length code to send.
 */
local int build_bl_tree(s)
local int build_bl_tree(deflate_state *s) {
    deflate_state *s;
{
    int max_blindex;  /* index of last bit length code of non zero freq */

    /* Determine the bit length frequencies for literal and distance trees */
    scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
    scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);

    /* Build the bit length tree: */
    build_tree(s, (tree_desc *)(&(s->bl_desc)));
    /* opt_len now includes the length of the tree representations, except
     * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
    /* opt_len now includes the length of the tree representations, except the
     * lengths of the bit lengths codes and the 5 + 5 + 4 bits for the counts.
     */

    /* Determine the number of bit length codes to send. The pkzip format
     * requires that at least 4 bit length codes be sent. (appnote.txt says
     * 3 but the actual value used is 4.)
     */
    for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
        if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
    }
    /* Update opt_len to include the bit length tree and counts */
    s->opt_len += 3*((ulg)max_blindex+1) + 5+5+4;
    s->opt_len += 3*((ulg)max_blindex + 1) + 5 + 5 + 4;
    Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
            s->opt_len, s->static_len));

    return max_blindex;
}

/* ===========================================================================
 * Send the header for a block using dynamic Huffman trees: the counts, the
 * lengths of the bit length codes, the literal tree and the distance tree.
 * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
 */
local void send_all_trees(s, lcodes, dcodes, blcodes)
local void send_all_trees(deflate_state *s, int lcodes, int dcodes,
    deflate_state *s;
    int lcodes, dcodes, blcodes; /* number of codes for each tree */
                          int blcodes) {
{
    int rank;                    /* index in bl_order */

    Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
    Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
            "too many codes");
    Tracev((stderr, "\nbl counts: "));
    send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
    send_bits(s, dcodes-1,   5);
    send_bits(s, blcodes-4,  4); /* not -3 as stated in appnote.txt */
    send_bits(s, lcodes - 257, 5);  /* not +255 as stated in appnote.txt */
    send_bits(s, dcodes - 1,   5);
    send_bits(s, blcodes - 4,  4);  /* not -3 as stated in appnote.txt */
    for (rank = 0; rank < blcodes; rank++) {
        Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
        send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
    }
    Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));

    send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
    send_tree(s, (ct_data *)s->dyn_ltree, lcodes - 1);  /* literal tree */
    Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));

    send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
    send_tree(s, (ct_data *)s->dyn_dtree, dcodes - 1);  /* distance tree */
    Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
}

/* ===========================================================================
 * Send a stored block
 */
void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)
void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf,
    deflate_state *s;
    charf *buf;       /* input block */
    ulg stored_len;   /* length of input block */
                                    ulg stored_len, int last) {
    int last;         /* one if this is the last block for a file */
{
    send_bits(s, (STORED_BLOCK<<1)+last, 3);    /* send block type */
    send_bits(s, (STORED_BLOCK<<1) + last, 3);  /* send block type */
    bi_windup(s);        /* align on byte boundary */
    put_short(s, (ush)stored_len);
    put_short(s, (ush)~stored_len);
    if (stored_len)
    zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);
        zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);
    s->pending += stored_len;
#ifdef ZLIB_DEBUG
    s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
    s->compressed_len += (stored_len + 4) << 3;
    s->bits_sent += 2*16;
    s->bits_sent += stored_len<<3;
    s->bits_sent += stored_len << 3;
#endif
}

/* ===========================================================================
 * Flush the bits in the bit buffer to pending output (leaves at most 7 bits)
 */
void ZLIB_INTERNAL _tr_flush_bits(s)
void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s) {
    deflate_state *s;
{
    bi_flush(s);
}

/* ===========================================================================
 * Send one empty static block to give enough lookahead for inflate.
 * This takes 10 bits, of which 7 may remain in the bit buffer.
 */
void ZLIB_INTERNAL _tr_align(s)
void ZLIB_INTERNAL _tr_align(deflate_state *s) {
    deflate_state *s;
{
    send_bits(s, STATIC_TREES<<1, 3);
    send_code(s, END_BLOCK, static_ltree);
#ifdef ZLIB_DEBUG
    s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
#endif
    bi_flush(s);
}

/* ===========================================================================
 * Send the block data compressed using the given Huffman trees
 */
local void compress_block(deflate_state *s, const ct_data *ltree,
                          const ct_data *dtree) {
    unsigned dist;      /* distance of matched string */
    int lc;             /* match length or unmatched char (if dist == 0) */
    unsigned sx = 0;    /* running index in symbol buffers */
    unsigned code;      /* the code to send */
    int extra;          /* number of extra bits to send */

    if (s->sym_next != 0) do {
#ifdef LIT_MEM
        dist = s->d_buf[sx];
        lc = s->l_buf[sx++];
#else
        dist = s->sym_buf[sx++] & 0xff;
        dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;
        lc = s->sym_buf[sx++];
#endif
        if (dist == 0) {
            send_code(s, lc, ltree); /* send a literal byte */
            Tracecv(isgraph(lc), (stderr," '%c' ", lc));
        } else {
            /* Here, lc is the match length - MIN_MATCH */
            code = _length_code[lc];
            send_code(s, code + LITERALS + 1, ltree);   /* send length code */
            extra = extra_lbits[code];
            if (extra != 0) {
                lc -= base_length[code];
                send_bits(s, lc, extra);       /* send the extra length bits */
            }
            dist--; /* dist is now the match distance - 1 */
            code = d_code(dist);
            Assert (code < D_CODES, "bad d_code");

            send_code(s, code, dtree);       /* send the distance code */
            extra = extra_dbits[code];
            if (extra != 0) {
                dist -= (unsigned)base_dist[code];
                send_bits(s, dist, extra);   /* send the extra distance bits */
            }
        } /* literal or match pair ? */

        /* Check for no overlay of pending_buf on needed symbols */
#ifdef LIT_MEM
        Assert(s->pending < 2 * (s->lit_bufsize + sx), "pendingBuf overflow");
#else
        Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
#endif

    } while (sx < s->sym_next);

    send_code(s, END_BLOCK, ltree);
}

/* ===========================================================================
 * Check if the data type is TEXT or BINARY, using the following algorithm:
 * - TEXT if the two conditions below are satisfied:
 *    a) There are no non-portable control characters belonging to the
 *       "block list" (0..6, 14..25, 28..31).
 *    b) There is at least one printable character belonging to the
 *       "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
 * - BINARY otherwise.
 * - The following partially-portable control characters form a
 *   "gray list" that is ignored in this detection algorithm:
 *   (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
 * IN assertion: the fields Freq of dyn_ltree are set.
 */
local int detect_data_type(deflate_state *s) {
    /* block_mask is the bit mask of block-listed bytes
     * set bits 0..6, 14..25, and 28..31
     * 0xf3ffc07f = binary 11110011111111111100000001111111
     */
    unsigned long block_mask = 0xf3ffc07fUL;
    int n;

    /* Check for non-textual ("block-listed") bytes. */
    for (n = 0; n <= 31; n++, block_mask >>= 1)
        if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0))
            return Z_BINARY;

    /* Check for textual ("allow-listed") bytes. */
    if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
            || s->dyn_ltree[13].Freq != 0)
        return Z_TEXT;
    for (n = 32; n < LITERALS; n++)
        if (s->dyn_ltree[n].Freq != 0)
            return Z_TEXT;

    /* There are no "block-listed" or "allow-listed" bytes:
     * this stream either is empty or has tolerated ("gray-listed") bytes only.
     */
    return Z_BINARY;
}

/* ===========================================================================
 * Determine the best encoding for the current block: dynamic trees, static
 * trees or store, and write out the encoded block.
 */
void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf,
    deflate_state *s;
    charf *buf;       /* input block, or NULL if too old */
    ulg stored_len;   /* length of input block */
                                   ulg stored_len, int last) {
    int last;         /* one if this is the last block for a file */
{
    ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
    int max_blindex = 0;  /* index of last bit length code of non zero freq */

    /* Build the Huffman trees unless a stored block is forced */
    if (s->level > 0) {

        /* Check if the file is binary or text */
938
939
940
941
942
943
944
945
946


947
948
949
950

951

952



953
954
955
956
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


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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
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

1116











1117




































































































































































-
-
+
+



-
+

+
-
+
+
+









-
+










-
-
+
-
-
-
-
+






-
-
-
+
+
+


















-
-
+
+






-
-
+
+
-
-
-
-
-
+
+
+
+
+
+
+











-
+


-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

        /* Build the bit length tree for the above two trees, and get the index
         * in bl_order of the last bit length code to send.
         */
        max_blindex = build_bl_tree(s);

        /* Determine the best encoding. Compute the block lengths in bytes. */
        opt_lenb = (s->opt_len+3+7)>>3;
        static_lenb = (s->static_len+3+7)>>3;
        opt_lenb = (s->opt_len + 3 + 7) >> 3;
        static_lenb = (s->static_len + 3 + 7) >> 3;

        Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
                opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
                s->last_lit));
                s->sym_next / 3));

#ifndef FORCE_STATIC
        if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
        if (static_lenb <= opt_lenb || s->strategy == Z_FIXED)
#endif
            opt_lenb = static_lenb;

    } else {
        Assert(buf != (char*)0, "lost buf");
        opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
    }

#ifdef FORCE_STORED
    if (buf != (char*)0) { /* force stored block */
#else
    if (stored_len+4 <= opt_lenb && buf != (char*)0) {
    if (stored_len + 4 <= opt_lenb && buf != (char*)0) {
                       /* 4: two words for the lengths */
#endif
        /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
         * Otherwise we can't have processed more than WSIZE input bytes since
         * the last block flush, because compression would have been
         * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
         * transform a block into a stored block.
         */
        _tr_stored_block(s, buf, stored_len, last);

#ifdef FORCE_STATIC
    } else if (static_lenb >= 0) { /* force static trees */
    } else if (static_lenb == opt_lenb) {
#else
    } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
#endif
        send_bits(s, (STATIC_TREES<<1)+last, 3);
        send_bits(s, (STATIC_TREES<<1) + last, 3);
        compress_block(s, (const ct_data *)static_ltree,
                       (const ct_data *)static_dtree);
#ifdef ZLIB_DEBUG
        s->compressed_len += 3 + s->static_len;
#endif
    } else {
        send_bits(s, (DYN_TREES<<1)+last, 3);
        send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
                       max_blindex+1);
        send_bits(s, (DYN_TREES<<1) + last, 3);
        send_all_trees(s, s->l_desc.max_code + 1, s->d_desc.max_code + 1,
                       max_blindex + 1);
        compress_block(s, (const ct_data *)s->dyn_ltree,
                       (const ct_data *)s->dyn_dtree);
#ifdef ZLIB_DEBUG
        s->compressed_len += 3 + s->opt_len;
#endif
    }
    Assert (s->compressed_len == s->bits_sent, "bad compressed size");
    /* The above check is made mod 2^32, for files larger than 512 MB
     * and uLong implemented on 32 bits.
     */
    init_block(s);

    if (last) {
        bi_windup(s);
#ifdef ZLIB_DEBUG
        s->compressed_len += 7;  /* align on byte boundary */
#endif
    }
    Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
           s->compressed_len-7*last));
    Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len >> 3,
           s->compressed_len - 7*last));
}

/* ===========================================================================
 * Save the match info and tally the frequency counts. Return true if
 * the current block must be flushed.
 */
int ZLIB_INTERNAL _tr_tally (s, dist, lc)
    deflate_state *s;
int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc) {
#ifdef LIT_MEM
    unsigned dist;  /* distance of matched string */
    unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */
{
    s->d_buf[s->last_lit] = (ush)dist;
    s->l_buf[s->last_lit++] = (uch)lc;
    s->d_buf[s->sym_next] = (ush)dist;
    s->l_buf[s->sym_next++] = (uch)lc;
#else
    s->sym_buf[s->sym_next++] = (uch)dist;
    s->sym_buf[s->sym_next++] = (uch)(dist >> 8);
    s->sym_buf[s->sym_next++] = (uch)lc;
#endif
    if (dist == 0) {
        /* lc is the unmatched char */
        s->dyn_ltree[lc].Freq++;
    } else {
        s->matches++;
        /* Here, lc is the match length - MIN_MATCH */
        dist--;             /* dist = match distance - 1 */
        Assert((ush)dist < (ush)MAX_DIST(s) &&
               (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
               (ush)d_code(dist) < (ush)D_CODES,  "_tr_tally: bad match");

        s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
        s->dyn_ltree[_length_code[lc] + LITERALS + 1].Freq++;
        s->dyn_dtree[d_code(dist)].Freq++;
    }

    return (s->sym_next == s->sym_end);
#ifdef TRUNCATE_BLOCK
    /* Try to guess if it is profitable to stop the current block here */
    if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
        /* Compute an upper bound for the compressed length */
        ulg out_length = (ulg)s->last_lit*8L;
        ulg in_length = (ulg)((long)s->strstart - s->block_start);
        int dcode;
        for (dcode = 0; dcode < D_CODES; dcode++) {
            out_length += (ulg)s->dyn_dtree[dcode].Freq *
                (5L+extra_dbits[dcode]);
        }
}
        out_length >>= 3;
        Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
               s->last_lit, in_length, out_length,
               100L - out_length*100L/in_length));
        if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
    }
#endif
    return (s->last_lit == s->lit_bufsize-1);
    /* We avoid equality with lit_bufsize because of wraparound at 64K
     * on 16 bit machines and because stored blocks are restricted to
     * 64K-1 bytes.
     */
}

/* ===========================================================================
 * Send the block data compressed using the given Huffman trees
 */
local void compress_block(s, ltree, dtree)
    deflate_state *s;
    const ct_data *ltree; /* literal tree */
    const ct_data *dtree; /* distance tree */
{
    unsigned dist;      /* distance of matched string */
    int lc;             /* match length or unmatched char (if dist == 0) */
    unsigned lx = 0;    /* running index in l_buf */
    unsigned code;      /* the code to send */
    int extra;          /* number of extra bits to send */

    if (s->last_lit != 0) do {
        dist = s->d_buf[lx];
        lc = s->l_buf[lx++];
        if (dist == 0) {
            send_code(s, lc, ltree); /* send a literal byte */
            Tracecv(isgraph(lc), (stderr," '%c' ", lc));
        } else {
            /* Here, lc is the match length - MIN_MATCH */
            code = _length_code[lc];
            send_code(s, code+LITERALS+1, ltree); /* send the length code */
            extra = extra_lbits[code];
            if (extra != 0) {
                lc -= base_length[code];
                send_bits(s, lc, extra);       /* send the extra length bits */
            }
            dist--; /* dist is now the match distance - 1 */
            code = d_code(dist);
            Assert (code < D_CODES, "bad d_code");

            send_code(s, code, dtree);       /* send the distance code */
            extra = extra_dbits[code];
            if (extra != 0) {
                dist -= (unsigned)base_dist[code];
                send_bits(s, dist, extra);   /* send the extra distance bits */
            }
        } /* literal or match pair ? */

        /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
        Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
               "pendingBuf overflow");

    } while (lx < s->last_lit);

    send_code(s, END_BLOCK, ltree);
}

/* ===========================================================================
 * Check if the data type is TEXT or BINARY, using the following algorithm:
 * - TEXT if the two conditions below are satisfied:
 *    a) There are no non-portable control characters belonging to the
 *       "black list" (0..6, 14..25, 28..31).
 *    b) There is at least one printable character belonging to the
 *       "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
 * - BINARY otherwise.
 * - The following partially-portable control characters form a
 *   "gray list" that is ignored in this detection algorithm:
 *   (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
 * IN assertion: the fields Freq of dyn_ltree are set.
 */
local int detect_data_type(s)
    deflate_state *s;
{
    /* black_mask is the bit mask of black-listed bytes
     * set bits 0..6, 14..25, and 28..31
     * 0xf3ffc07f = binary 11110011111111111100000001111111
     */
    unsigned long black_mask = 0xf3ffc07fUL;
    int n;

    /* Check for non-textual ("black-listed") bytes. */
    for (n = 0; n <= 31; n++, black_mask >>= 1)
        if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0))
            return Z_BINARY;

    /* Check for textual ("white-listed") bytes. */
    if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
            || s->dyn_ltree[13].Freq != 0)
        return Z_TEXT;
    for (n = 32; n < LITERALS; n++)
        if (s->dyn_ltree[n].Freq != 0)
            return Z_TEXT;

    /* There are no "black-listed" or "white-listed" bytes:
     * this stream either is empty or has tolerated ("gray-listed") bytes only.
     */
    return Z_BINARY;
}

/* ===========================================================================
 * Reverse the first len bits of a code, using straightforward code (a faster
 * method would use a table)
 * IN assertion: 1 <= len <= 15
 */
local unsigned bi_reverse(code, len)
    unsigned code; /* the value to invert */
    int len;       /* its bit length */
{
    register unsigned res = 0;
    do {
        res |= code & 1;
        code >>= 1, res <<= 1;
    } while (--len > 0);
    return res >> 1;
}

/* ===========================================================================
 * Flush the bit buffer, keeping at most 7 bits in it.
 */
local void bi_flush(s)
    deflate_state *s;
{
    if (s->bi_valid == 16) {
        put_short(s, s->bi_buf);
        s->bi_buf = 0;
        s->bi_valid = 0;
    } else if (s->bi_valid >= 8) {
        put_byte(s, (Byte)s->bi_buf);
        s->bi_buf >>= 8;
        s->bi_valid -= 8;
    }
}

/* ===========================================================================
 * Flush the bit buffer and align the output on a byte boundary
 */
local void bi_windup(s)
    deflate_state *s;
{
    if (s->bi_valid > 8) {
        put_short(s, s->bi_buf);
    } else if (s->bi_valid > 0) {
        put_byte(s, (Byte)s->bi_buf);
    }
    s->bi_buf = 0;
    s->bi_valid = 0;
#ifdef ZLIB_DEBUG
    s->bits_sent = (s->bits_sent+7) & ~7;
#endif
}

Changes to compat/zlib/uncompr.c.

20
21
22
23
24
25
26
27
28
29
30
31


32
33
34
35
36
37
38
39
20
21
22
23
24
25
26





27
28

29
30
31
32
33
34
35







-
-
-
-
-
+
+
-







   first unused input byte.

     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough
   memory, Z_BUF_ERROR if there was not enough room in the output buffer, or
   Z_DATA_ERROR if the input data was corrupted, including if the input data is
   an incomplete zlib stream.
*/
int ZEXPORT uncompress2 (dest, destLen, source, sourceLen)
    Bytef *dest;
    uLongf *destLen;
    const Bytef *source;
    uLong *sourceLen;
int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, const Bytef *source,
                        uLong *sourceLen) {
{
    z_stream stream;
    int err;
    const uInt max = (uInt)-1;
    uLong len, left;
    Byte buf[1];    /* for detection of incomplete stream when *destLen == 0 */

    len = *sourceLen;
79
80
81
82
83
84
85
86
87
88
89
90


91
92
93
75
76
77
78
79
80
81





82
83

84
85







-
-
-
-
-
+
+
-


    inflateEnd(&stream);
    return err == Z_STREAM_END ? Z_OK :
           err == Z_NEED_DICT ? Z_DATA_ERROR  :
           err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR :
           err;
}

int ZEXPORT uncompress (dest, destLen, source, sourceLen)
    Bytef *dest;
    uLongf *destLen;
    const Bytef *source;
    uLong sourceLen;
int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, const Bytef *source,
                       uLong sourceLen) {
{
    return uncompress2(dest, destLen, source, &sourceLen);
}

Changes to compat/zlib/win32/DLL_FAQ.txt.

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
1
2
3
4
5

6
7
8
9
10
11
12
13

14
15
16




17
18
19
20
21
22
23





-
+







-
+


-
-
-
-








            Frequently Asked Questions about ZLIB1.DLL


This document describes the design, the rationale, and the usage
of the official DLL build of zlib, named ZLIB1.DLL.  If you have
of the common DLL build of zlib, named ZLIB1.DLL.  If you have
general questions about zlib, you should see the file "FAQ" found
in the zlib distribution, or at the following location:
  http://www.gzip.org/zlib/zlib_faq.html


 1. What is ZLIB1.DLL, and how can I get it?

  - ZLIB1.DLL is the official build of zlib as a DLL.
  - ZLIB1.DLL is the common build of zlib as a DLL.
    (Please remark the character '1' in the name.)

    Pointers to a precompiled ZLIB1.DLL can be found in the zlib
    web site at:
      http://www.zlib.net/

    Applications that link to ZLIB1.DLL can rely on the following
    specification:

    * The exported symbols are exclusively defined in the source
      files "zlib.h" and "zlib.def", found in an official zlib
      source distribution.
    * The symbols are exported by name, not by ordinal.
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
371
372
373
374
375
376
377












378
379
380
381







-
-
-
-
-
-
-
-
-
-
-
-




    macros like NO_GZCOMPRESS or NO_GZIP at compile time?

  - No.  A legitimate build of ZLIB1.DLL must provide the complete
    zlib functionality, as implemented in the official zlib source
    code.  But you can make your own private DLL build, under a
    different file name, as suggested in the previous answer.


17. I made my own ZLIB1.DLL build.  Can I test it for compliance?

  - We prefer that you download the official DLL from the zlib
    web site.  If you need something peculiar from this DLL, you
    can send your suggestion to the zlib mailing list.

    However, in case you do rebuild the DLL yourself, you can run
    it with the test programs found in the DLL distribution.
    Running these test programs is not a guarantee of compliance,
    but a failure can imply a detected problem.

**

This document is written and maintained by
Cosmin Truta <cosmint@cs.ubbcluj.ro>

Changes to compat/zlib/win32/Makefile.bor.

1
2
3
4
5
6
7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12





-







# Makefile for zlib
# Borland C++ for Win32
#
# Usage:
#  make -f win32/Makefile.bor
#  make -f win32/Makefile.bor LOCAL_ZLIB=-DASMV OBJA=match.obj OBJPA=+match.obj

# ------------ Borland C++ ------------

# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7)
# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or
# added to the declaration of LOC here:
LOC = $(LOCAL_ZLIB)

Changes to compat/zlib/win32/Makefile.gcc.

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




14
15
16
17
18
19
20













-
-
-
-







# Makefile for zlib, derived from Makefile.dj2.
# Modified for mingw32 by C. Spieler, 6/16/98.
# Updated for zlib 1.2.x by Christian Spieler and Cosmin Truta, Mar-2003.
# Last updated: Mar 2012.
# Tested under Cygwin and MinGW.

# Copyright (C) 1995-2003 Jean-loup Gailly.
# For conditions of distribution and use, see copyright notice in zlib.h

# To compile, or to compile and test, type from the top level zlib directory:
#
#   make -fwin32/Makefile.gcc;  make test testdll -fwin32/Makefile.gcc
#
# To use the asm code, type:
#   cp contrib/asm?86/match.S ./match.S
#   make LOC=-DASMV OBJA=match.o -fwin32/Makefile.gcc
#
# To install libz.a, zconf.h and zlib.h in the system directories, type:
#
#   make install -fwin32/Makefile.gcc
#
# BINARY_PATH, INCLUDE_PATH and LIBRARY_PATH must be set.
#
# To install the shared lib, append SHARED_MODE=1 to the make command :
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
30
31
32
33
34
35
36

37
38
39
40
41
42
43







-







IMPLIB    = libz.dll.a

#
# Set to 1 if shared object needs to be installed
#
SHARED_MODE=0

#LOC = -DASMV
#LOC = -DZLIB_DEBUG -g

PREFIX =
CC = $(PREFIX)gcc
CFLAGS = $(LOC) -O3 -Wall

AS = $(CC)

Changes to compat/zlib/win32/Makefile.msc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1
2
3
4
5
6




7
8
9
10
11
12
13






-
-
-
-







# Makefile for zlib using Microsoft (Visual) C
# zlib is copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
#
# Usage:
#   nmake -f win32/Makefile.msc                          (standard build)
#   nmake -f win32/Makefile.msc LOC=-DFOO                (nonstandard build)
#   nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" \
#         OBJA="inffas32.obj match686.obj"               (use ASM code, x86)
#   nmake -f win32/Makefile.msc AS=ml64 LOC="-DASMV -DASMINF -I." \
#         OBJA="inffasx64.obj gvmat64.obj inffas8664.obj"  (use ASM code, x64)

# The toplevel directory of the source tree.
#
TOP = .

# optional build flags
LOC =

Changes to compat/zlib/win32/README-WIN32.txt.

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
30
31
32
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
30
31
32


-
+















-
-
+
+




-
+







ZLIB DATA COMPRESSION LIBRARY

zlib 1.2.11 is a general purpose data compression library.  All the code is
zlib 1.3.1 is a general purpose data compression library.  All the code is
thread safe.  The data format used by the zlib library is described by RFCs
(Request for Comments) 1950 to 1952 in the files
http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
and rfc1952.txt (gzip format).

All functions of the compression library are documented in the file zlib.h
(volunteer to write man pages welcome, contact zlib@gzip.org).  Two compiled
examples are distributed in this package, example and minigzip.  The example_d
and minigzip_d flavors validate that the zlib1.dll file is working correctly.

Questions about zlib should be sent to <zlib@gzip.org>.  The zlib home page
is http://zlib.net/ .  Before reporting a problem, please check this site to
verify that you have the latest version of zlib; otherwise get the latest
version and check whether the problem still exists or not.

PLEASE read DLL_FAQ.txt, and the the zlib FAQ http://zlib.net/zlib_faq.html
before asking for help.
PLEASE read DLL_FAQ.txt, and the zlib FAQ http://zlib.net/zlib_faq.html before
asking for help.


Manifest:

The package zlib-1.2.11-win32-x86.zip will contain the following files:
The package zlib-1.3.1-win32-x86.zip will contain the following files:

  README-WIN32.txt This document
  ChangeLog        Changes since previous zlib packages
  DLL_FAQ.txt      Frequently asked questions about zlib1.dll
  zlib.3.pdf       Documentation of this library in Adobe Acrobat format

  example.exe      A statically-bound example (using zlib.lib, not the dll)

Changes to compat/zlib/win32/README.txt.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+








What's here
===========
  The official ZLIB1.DLL


Source
======
  zlib version 1.2.11
  zlib version 1.3.1
  available at http://www.gzip.org/zlib/


Specification and rationale
===========================
  See the accompanying DLL_FAQ.txt

Changes to compat/zlib/win32/zdll.lib.

cannot compute difference between binary files

Changes to compat/zlib/win32/zlib.def.

65
66
67
68
69
70
71

72
73
74
75
76
77
78


79
80
81
82
83
84
85
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88







+







+
+







; large file functions
    gzopen64
    gzseek64
    gztell64
    gzoffset64
    adler32_combine64
    crc32_combine64
    crc32_combine_gen64
; checksum functions
    adler32
    adler32_z
    crc32
    crc32_z
    adler32_combine
    crc32_combine
    crc32_combine_gen
    crc32_combine_op
; various hacks, don't look :)
    deflateInit_
    deflateInit2_
    inflateInit_
    inflateInit2_
    inflateBackInit_
    gzgetc_

Changes to compat/zlib/win32/zlib1.dll.

cannot compute difference between binary files

Changes to compat/zlib/win32/zlib1.rc.

22
23
24
25
26
27
28
29

30
31
32
33
34
35
36
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36







-
+







  BEGIN
    BLOCK "040904E4"
    //language ID = U.S. English, char set = Windows, Multilingual
    BEGIN
      VALUE "FileDescription",	"zlib data compression library\0"
      VALUE "FileVersion",	ZLIB_VERSION "\0"
      VALUE "InternalName",	"zlib1.dll\0"
      VALUE "LegalCopyright",	"(C) 1995-2017 Jean-loup Gailly & Mark Adler\0"
      VALUE "LegalCopyright",	"(C) 1995-2022 Jean-loup Gailly & Mark Adler\0"
      VALUE "OriginalFilename",	"zlib1.dll\0"
      VALUE "ProductName",	"zlib\0"
      VALUE "ProductVersion",	ZLIB_VERSION "\0"
      VALUE "Comments",		"For more information visit http://www.zlib.net/\0"
    END
  END
  BLOCK "VarFileInfo"

Added compat/zlib/win64-arm/libz.dll.a.

cannot compute difference between binary files

Added compat/zlib/win64-arm/zdll.lib.

cannot compute difference between binary files

Added compat/zlib/win64-arm/zlib1.dll.

cannot compute difference between binary files

Changes to compat/zlib/win64/libz.dll.a.

cannot compute difference between binary files

Changes to compat/zlib/win64/zdll.lib.

cannot compute difference between binary files

Changes to compat/zlib/win64/zlib1.dll.

cannot compute difference between binary files

Changes to compat/zlib/zconf.h.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/* zconf.h -- configuration of the zlib compression library
 * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
 * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/* @(#) $Id$ */

#ifndef ZCONF_H
#define ZCONF_H
34
35
36
37
38
39
40



41
42
43
44
45
46
47
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50







+
+
+







#    define compress              z_compress
#    define compress2             z_compress2
#    define compressBound         z_compressBound
#  endif
#  define crc32                 z_crc32
#  define crc32_combine         z_crc32_combine
#  define crc32_combine64       z_crc32_combine64
#  define crc32_combine_gen     z_crc32_combine_gen
#  define crc32_combine_gen64   z_crc32_combine_gen64
#  define crc32_combine_op      z_crc32_combine_op
#  define crc32_z               z_crc32_z
#  define deflate               z_deflate
#  define deflateBound          z_deflateBound
#  define deflateCopy           z_deflateCopy
#  define deflateEnd            z_deflateEnd
#  define deflateGetDictionary  z_deflateGetDictionary
#  define deflateInit           z_deflateInit
234
235
236
237
238
239
240



241


242
243
244
245
246
247
248
237
238
239
240
241
242
243
244
245
246

247
248
249
250
251
252
253
254
255







+
+
+
-
+
+







#if defined(ZLIB_CONST) && !defined(z_const)
#  define z_const const
#else
#  define z_const
#endif

#ifdef Z_SOLO
#  ifdef _WIN64
     typedef unsigned long long z_size_t;
#  else
   typedef unsigned long z_size_t;
     typedef unsigned long z_size_t;
#  endif
#else
#  define z_longlong long long
#  if defined(NO_SIZE_T)
     typedef unsigned NO_SIZE_T z_size_t;
#  elif defined(STDC)
#    include <stddef.h>
     typedef size_t z_size_t;
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
296
297
298
299
300
301
302








303
304
305
306
307
308
309







-
-
-
-
-
-
-
-







#  ifdef STDC
#    define OF(args)  args
#  else
#    define OF(args)  ()
#  endif
#endif

#ifndef Z_ARG /* function prototypes for stdarg */
#  if defined(STDC) || defined(Z_HAVE_STDARG_H)
#    define Z_ARG(args)  args
#  else
#    define Z_ARG(args)  ()
#  endif
#endif

/* The following definitions for FAR are needed only for MSDOS mixed
 * model programming (small or medium model with some far allocations).
 * This was tested only with MSC; for other MSDOS compilers you may have
 * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
 * just define FAR to be empty.
 */
#ifdef SYS16BIT
345
346
347
348
349
350
351



352
353
354
355
356
357
358
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360







+
+
+







    * define ZLIB_WINAPI.
    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
    */
#  ifdef ZLIB_WINAPI
#    ifdef FAR
#      undef FAR
#    endif
#    ifndef WIN32_LEAN_AND_MEAN
#      define WIN32_LEAN_AND_MEAN
#    endif
#    include <windows.h>
     /* No need for _export, use ZLIB.DEF instead. */
     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
#    define ZEXPORT WINAPI
#    ifdef WIN32
#      define ZEXPORTVA WINAPIV
#    else
463
464
465
466
467
468
469
470
471




472





473
474

475
476
477
478
479
480
481
465
466
467
468
469
470
471


472
473
474
475
476
477
478
479
480
481
482

483
484
485
486
487
488
489
490







-
-
+
+
+
+

+
+
+
+
+

-
+







 * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
 * equivalently requesting no 64-bit operations
 */
#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
#  undef _LARGEFILE64_SOURCE
#endif

#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
#  define Z_HAVE_UNISTD_H
#ifndef Z_HAVE_UNISTD_H
#  ifdef __WATCOMC__
#    define Z_HAVE_UNISTD_H
#  endif
#endif
#ifndef Z_HAVE_UNISTD_H
#  if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)
#    define Z_HAVE_UNISTD_H
#  endif
#endif
#ifndef Z_SOLO
#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
#  if defined(Z_HAVE_UNISTD_H)
#    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
#    ifdef VMS
#      include <unixio.h>       /* for off_t */
#    endif
#    ifndef z_off_t
#      define z_off_t off_t
#    endif
503
504
505
506
507
508
509
510

511
512
513
514
515
516
517
512
513
514
515
516
517
518

519
520
521
522
523
524
525
526







-
+







#ifndef z_off_t
#  define z_off_t long
#endif

#if !defined(_WIN32) && defined(Z_LARGE64)
#  define z_off64_t off64_t
#else
#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
#  if defined(_WIN32) && !defined(__GNUC__)
#    define z_off64_t __int64
#  else
#    define z_off64_t z_off_t
#  endif
#endif

/* MVS linker does not support external names larger than 8 bytes */

Changes to compat/zlib/zconf.h.cmakein.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/* zconf.h -- configuration of the zlib compression library
 * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
 * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/* @(#) $Id$ */

#ifndef ZCONF_H
#define ZCONF_H
36
37
38
39
40
41
42



43
44
45
46
47
48
49
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52







+
+
+







#    define compress              z_compress
#    define compress2             z_compress2
#    define compressBound         z_compressBound
#  endif
#  define crc32                 z_crc32
#  define crc32_combine         z_crc32_combine
#  define crc32_combine64       z_crc32_combine64
#  define crc32_combine_gen     z_crc32_combine_gen
#  define crc32_combine_gen64   z_crc32_combine_gen64
#  define crc32_combine_op      z_crc32_combine_op
#  define crc32_z               z_crc32_z
#  define deflate               z_deflate
#  define deflateBound          z_deflateBound
#  define deflateCopy           z_deflateCopy
#  define deflateEnd            z_deflateEnd
#  define deflateGetDictionary  z_deflateGetDictionary
#  define deflateInit           z_deflateInit
236
237
238
239
240
241
242



243


244
245
246
247
248
249
250
239
240
241
242
243
244
245
246
247
248

249
250
251
252
253
254
255
256
257







+
+
+
-
+
+







#if defined(ZLIB_CONST) && !defined(z_const)
#  define z_const const
#else
#  define z_const
#endif

#ifdef Z_SOLO
#  ifdef _WIN64
     typedef unsigned long long z_size_t;
#  else
   typedef unsigned long z_size_t;
     typedef unsigned long z_size_t;
#  endif
#else
#  define z_longlong long long
#  if defined(NO_SIZE_T)
     typedef unsigned NO_SIZE_T z_size_t;
#  elif defined(STDC)
#    include <stddef.h>
     typedef size_t z_size_t;
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
298
299
300
301
302
303
304








305
306
307
308
309
310
311







-
-
-
-
-
-
-
-







#  ifdef STDC
#    define OF(args)  args
#  else
#    define OF(args)  ()
#  endif
#endif

#ifndef Z_ARG /* function prototypes for stdarg */
#  if defined(STDC) || defined(Z_HAVE_STDARG_H)
#    define Z_ARG(args)  args
#  else
#    define Z_ARG(args)  ()
#  endif
#endif

/* The following definitions for FAR are needed only for MSDOS mixed
 * model programming (small or medium model with some far allocations).
 * This was tested only with MSC; for other MSDOS compilers you may have
 * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
 * just define FAR to be empty.
 */
#ifdef SYS16BIT
347
348
349
350
351
352
353



354
355
356
357
358
359
360
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362







+
+
+







    * define ZLIB_WINAPI.
    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
    */
#  ifdef ZLIB_WINAPI
#    ifdef FAR
#      undef FAR
#    endif
#    ifndef WIN32_LEAN_AND_MEAN
#      define WIN32_LEAN_AND_MEAN
#    endif
#    include <windows.h>
     /* No need for _export, use ZLIB.DEF instead. */
     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
#    define ZEXPORT WINAPI
#    ifdef WIN32
#      define ZEXPORTVA WINAPIV
#    else
465
466
467
468
469
470
471
472
473




474





475
476

477
478
479
480
481
482
483
467
468
469
470
471
472
473


474
475
476
477
478
479
480
481
482
483
484

485
486
487
488
489
490
491
492







-
-
+
+
+
+

+
+
+
+
+

-
+







 * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
 * equivalently requesting no 64-bit operations
 */
#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
#  undef _LARGEFILE64_SOURCE
#endif

#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
#  define Z_HAVE_UNISTD_H
#ifndef Z_HAVE_UNISTD_H
#  ifdef __WATCOMC__
#    define Z_HAVE_UNISTD_H
#  endif
#endif
#ifndef Z_HAVE_UNISTD_H
#  if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)
#    define Z_HAVE_UNISTD_H
#  endif
#endif
#ifndef Z_SOLO
#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
#  if defined(Z_HAVE_UNISTD_H)
#    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
#    ifdef VMS
#      include <unixio.h>       /* for off_t */
#    endif
#    ifndef z_off_t
#      define z_off_t off_t
#    endif
505
506
507
508
509
510
511
512

513
514
515
516
517
518
519
514
515
516
517
518
519
520

521
522
523
524
525
526
527
528







-
+







#ifndef z_off_t
#  define z_off_t long
#endif

#if !defined(_WIN32) && defined(Z_LARGE64)
#  define z_off64_t off64_t
#else
#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
#  if defined(_WIN32) && !defined(__GNUC__)
#    define z_off64_t __int64
#  else
#    define z_off64_t z_off_t
#  endif
#endif

/* MVS linker does not support external names larger than 8 bytes */

Changes to compat/zlib/zconf.h.in.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/* zconf.h -- configuration of the zlib compression library
 * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
 * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/* @(#) $Id$ */

#ifndef ZCONF_H
#define ZCONF_H
34
35
36
37
38
39
40



41
42
43
44
45
46
47
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50







+
+
+







#    define compress              z_compress
#    define compress2             z_compress2
#    define compressBound         z_compressBound
#  endif
#  define crc32                 z_crc32
#  define crc32_combine         z_crc32_combine
#  define crc32_combine64       z_crc32_combine64
#  define crc32_combine_gen     z_crc32_combine_gen
#  define crc32_combine_gen64   z_crc32_combine_gen64
#  define crc32_combine_op      z_crc32_combine_op
#  define crc32_z               z_crc32_z
#  define deflate               z_deflate
#  define deflateBound          z_deflateBound
#  define deflateCopy           z_deflateCopy
#  define deflateEnd            z_deflateEnd
#  define deflateGetDictionary  z_deflateGetDictionary
#  define deflateInit           z_deflateInit
234
235
236
237
238
239
240



241


242
243
244
245
246
247
248
237
238
239
240
241
242
243
244
245
246

247
248
249
250
251
252
253
254
255







+
+
+
-
+
+







#if defined(ZLIB_CONST) && !defined(z_const)
#  define z_const const
#else
#  define z_const
#endif

#ifdef Z_SOLO
#  ifdef _WIN64
     typedef unsigned long long z_size_t;
#  else
   typedef unsigned long z_size_t;
     typedef unsigned long z_size_t;
#  endif
#else
#  define z_longlong long long
#  if defined(NO_SIZE_T)
     typedef unsigned NO_SIZE_T z_size_t;
#  elif defined(STDC)
#    include <stddef.h>
     typedef size_t z_size_t;
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
296
297
298
299
300
301
302








303
304
305
306
307
308
309







-
-
-
-
-
-
-
-







#  ifdef STDC
#    define OF(args)  args
#  else
#    define OF(args)  ()
#  endif
#endif

#ifndef Z_ARG /* function prototypes for stdarg */
#  if defined(STDC) || defined(Z_HAVE_STDARG_H)
#    define Z_ARG(args)  args
#  else
#    define Z_ARG(args)  ()
#  endif
#endif

/* The following definitions for FAR are needed only for MSDOS mixed
 * model programming (small or medium model with some far allocations).
 * This was tested only with MSC; for other MSDOS compilers you may have
 * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
 * just define FAR to be empty.
 */
#ifdef SYS16BIT
345
346
347
348
349
350
351



352
353
354
355
356
357
358
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360







+
+
+







    * define ZLIB_WINAPI.
    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
    */
#  ifdef ZLIB_WINAPI
#    ifdef FAR
#      undef FAR
#    endif
#    ifndef WIN32_LEAN_AND_MEAN
#      define WIN32_LEAN_AND_MEAN
#    endif
#    include <windows.h>
     /* No need for _export, use ZLIB.DEF instead. */
     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
#    define ZEXPORT WINAPI
#    ifdef WIN32
#      define ZEXPORTVA WINAPIV
#    else
463
464
465
466
467
468
469
470
471




472





473
474

475
476
477
478
479
480
481
465
466
467
468
469
470
471


472
473
474
475
476
477
478
479
480
481
482

483
484
485
486
487
488
489
490







-
-
+
+
+
+

+
+
+
+
+

-
+







 * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
 * equivalently requesting no 64-bit operations
 */
#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
#  undef _LARGEFILE64_SOURCE
#endif

#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
#  define Z_HAVE_UNISTD_H
#ifndef Z_HAVE_UNISTD_H
#  ifdef __WATCOMC__
#    define Z_HAVE_UNISTD_H
#  endif
#endif
#ifndef Z_HAVE_UNISTD_H
#  if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)
#    define Z_HAVE_UNISTD_H
#  endif
#endif
#ifndef Z_SOLO
#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
#  if defined(Z_HAVE_UNISTD_H)
#    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
#    ifdef VMS
#      include <unixio.h>       /* for off_t */
#    endif
#    ifndef z_off_t
#      define z_off_t off_t
#    endif
503
504
505
506
507
508
509
510

511
512
513
514
515
516
517
512
513
514
515
516
517
518

519
520
521
522
523
524
525
526







-
+







#ifndef z_off_t
#  define z_off_t long
#endif

#if !defined(_WIN32) && defined(Z_LARGE64)
#  define z_off64_t off64_t
#else
#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
#  if defined(_WIN32) && !defined(__GNUC__)
#    define z_off64_t __int64
#  else
#    define z_off64_t z_off_t
#  endif
#endif

/* MVS linker does not support external names larger than 8 bytes */

Changes to compat/zlib/zlib.3.

1

2
3
4
5
6
7
8

1
2
3
4
5
6
7
8
-
+







.TH ZLIB 3 "15 Jan 2017"
.TH ZLIB 3 "22 Jan 2024"
.SH NAME
zlib \- compression/decompression library
.SH SYNOPSIS
[see
.I zlib.h
for full description]
.SH DESCRIPTION
101
102
103
104
105
106
107
108

109
110

111
112
113
114
115
116
117
101
102
103
104
105
106
107

108
109

110
111
112
113
114
115
116
117







-
+

-
+







.IP
http://zlib.net/zlib_faq.html
.LP
before asking for help.
Send questions and/or comments to zlib@gzip.org,
or (for the Windows DLL version) to Gilles Vollant (info@winimage.com).
.SH AUTHORS AND LICENSE
Version 1.2.11
Version 1.3.1
.LP
Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
.LP
This software is provided 'as-is', without any express or implied
warranty.  In no event will the authors be held liable for any damages
arising from the use of this software.
.LP
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it

Changes to compat/zlib/zlib.3.pdf.

cannot compute difference between binary files

Changes to compat/zlib/zlib.h.

1
2

3
4

5
6
7
8
9
10
11
1

2
3

4
5
6
7
8
9
10
11

-
+

-
+







/* zlib.h -- interface of the 'zlib' general purpose compression library
  version 1.2.11, January 15th, 2017
  version 1.3.1, January 22nd, 2024

  Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
  Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler

  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
33
34
35
36
37
38
39
40
41


42
43
44


45
46
47
48
49
50
51
33
34
35
36
37
38
39


40
41
42


43
44
45
46
47
48
49
50
51







-
-
+
+

-
-
+
+








#include "zconf.h"

#ifdef __cplusplus
extern "C" {
#endif

#define ZLIB_VERSION "1.2.11"
#define ZLIB_VERNUM 0x12b0
#define ZLIB_VERSION "1.3.1"
#define ZLIB_VERNUM 0x1310
#define ZLIB_VER_MAJOR 1
#define ZLIB_VER_MINOR 2
#define ZLIB_VER_REVISION 11
#define ZLIB_VER_MINOR 3
#define ZLIB_VER_REVISION 1
#define ZLIB_VER_SUBREVISION 0

/*
    The 'zlib' compression library provides in-memory compression and
  decompression functions, including integrity checks of the uncompressed data.
  This version of the library supports only one compression method (deflation)
  but other algorithms will be added later and will have the same stream
74
75
76
77
78
79
80
81
82


83
84
85
86
87
88
89
74
75
76
77
78
79
80


81
82
83
84
85
86
87
88
89







-
-
+
+







  directory information, and uses a different, slower check method than zlib.

    The library does not install any signal handler.  The decoder checks
  the consistency of the compressed data, so the library should never crash
  even in the case of corrupted input.
*/

typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
typedef voidpf (*alloc_func)(voidpf opaque, uInt items, uInt size);
typedef void   (*free_func)(voidpf opaque, voidpf address);

struct internal_state;

typedef struct z_stream_s {
    z_const Bytef *next_in;     /* next input byte */
    uInt     avail_in;  /* number of bytes available at next_in */
    uLong    total_in;  /* total number of input bytes read so far */
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
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







-
+







-
+




-
+
















-
+








#define zlib_version zlibVersion()
/* for compatibility with versions < 1.0.2 */


                        /* basic functions */

ZEXTERN const char * ZEXPORT zlibVersion OF((void));
ZEXTERN const char * ZEXPORT zlibVersion(void);
/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
   If the first character differs, the library code actually used is not
   compatible with the zlib.h header file used by the application.  This check
   is automatically made by deflateInit and inflateInit.
 */

/*
ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
ZEXTERN int ZEXPORT deflateInit(z_streamp strm, int level);

     Initializes the internal stream state for compression.  The fields
   zalloc, zfree and opaque must be initialized before by the caller.  If
   zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
   allocation functions.
   allocation functions.  total_in, total_out, adler, and msg are initialized.

     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
   1 gives best speed, 9 gives best compression, 0 gives no compression at all
   (the input data is simply copied a block at a time).  Z_DEFAULT_COMPRESSION
   requests a default compromise between speed and compression (currently
   equivalent to level 6).

     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
   memory, Z_STREAM_ERROR if level is not a valid compression level, or
   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
   with the version assumed by the caller (ZLIB_VERSION).  msg is set to null
   if there is no error message.  deflateInit does not perform any compression:
   this will be done by deflate().
*/


ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
ZEXTERN int ZEXPORT deflate(z_streamp strm, int flush);
/*
    deflate compresses as much data as possible, and stops when the input
  buffer becomes empty or the output buffer becomes full.  It may introduce
  some output latency (reading input without producing any output) except when
  forced to flush.

    The detailed semantics are as follows.  deflate performs one or both of the
272
273
274
275
276
277
278
279

280
281
282
283
284
285
286
272
273
274
275
276
277
278

279
280
281
282
283
284
285
286







-
+







  one of the actions is possible, by providing more input and/or consuming more
  output, and updating avail_in or avail_out accordingly; avail_out should
  never be zero before the call.  The application can consume the compressed
  output when it wants, for example when the output buffer is full (avail_out
  == 0), or after each call of deflate().  If deflate returns Z_OK and with
  zero avail_out, it must be called again after making room in the output
  buffer because there might be more output pending. See deflatePending(),
  which can be used if desired to determine whether or not there is more ouput
  which can be used if desired to determine whether or not there is more output
  in that case.

    Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
  decide how much data to accumulate before producing output, in order to
  maximize compression.

    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
316
317
318
319
320
321
322
323
324


325
326
327
328
329
330
331
316
317
318
319
320
321
322


323
324
325
326
327
328
329
330
331







-
-
+
+







  random access is desired.  Using Z_FULL_FLUSH too often can seriously degrade
  compression.

    If deflate returns with avail_out == 0, this function must be called again
  with the same value of the flush parameter and more output space (updated
  avail_out), until the flush is complete (deflate returns with non-zero
  avail_out).  In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
  avail_out is greater than six to avoid repeated flush markers due to
  avail_out == 0 on return.
  avail_out is greater than six when the flush marker begins, in order to avoid
  repeated flush markers upon calling deflate() again when avail_out == 0.

    If the parameter flush is set to Z_FINISH, pending input is processed,
  pending output is flushed and deflate returns with Z_STREAM_END if there was
  enough output space.  If deflate returns with Z_OK or Z_BUF_ERROR, this
  function must be called again with Z_FINISH and more output space (updated
  avail_out) but no more input data, until it returns with Z_STREAM_END or an
  error.  After deflate has returned Z_STREAM_END, the only possible operations
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
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







-
+














-
+







-
+
+













-
+







  by the application), or Z_BUF_ERROR if no progress is possible (for example
  avail_in or avail_out was zero).  Note that Z_BUF_ERROR is not fatal, and
  deflate() can be called again with more input and more output space to
  continue compressing.
*/


ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
ZEXTERN int ZEXPORT deflateEnd(z_streamp strm);
/*
     All dynamically allocated data structures for this stream are freed.
   This function discards any unprocessed input and does not flush any pending
   output.

     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
   prematurely (some input or output was discarded).  In the error case, msg
   may be set but then points to a static string (which must not be
   deallocated).
*/


/*
ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
ZEXTERN int ZEXPORT inflateInit(z_streamp strm);

     Initializes the internal stream state for decompression.  The fields
   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
   the caller.  In the current version of inflate, the provided input is not
   read or consumed.  The allocation of a sliding window will be deferred to
   the first call of inflate (if the decompression does not complete on the
   first call).  If zalloc and zfree are set to Z_NULL, inflateInit updates
   them to use default allocation functions.
   them to use default allocation functions.  total_in, total_out, adler, and
   msg are initialized.

     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
   invalid, such as a null pointer to the structure.  msg is set to null if
   there is no error message.  inflateInit does not perform any decompression.
   Actual decompression will be done by inflate().  So next_in, and avail_in,
   next_out, and avail_out are unused and unchanged.  The current
   implementation of inflateInit() does not process any header information --
   that is deferred until inflate() is called.
*/


ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
ZEXTERN int ZEXPORT inflate(z_streamp strm, int flush);
/*
    inflate decompresses as much data as possible, and stops when the input
  buffer becomes empty or the output buffer becomes full.  It may introduce
  some output latency (reading input without producing any output) except when
  forced to flush.

  The detailed semantics are as follows.  inflate performs one or both of the
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
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







-
+

















-
-
-
-
-
-
+
+
+
+
+
+


-
+
-







  inflate() can be called again with more input and more output space to
  continue decompressing.  If Z_DATA_ERROR is returned, the application may
  then call inflateSync() to look for a good compression block if a partial
  recovery of the data is to be attempted.
*/


ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
ZEXTERN int ZEXPORT inflateEnd(z_streamp strm);
/*
     All dynamically allocated data structures for this stream are freed.
   This function discards any unprocessed input and does not flush any pending
   output.

     inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state
   was inconsistent.
*/


                        /* Advanced functions */

/*
    The following functions are needed only in some special applications.
*/

/*
ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
                                     int  level,
                                     int  method,
                                     int  windowBits,
                                     int  memLevel,
                                     int  strategy));
ZEXTERN int ZEXPORT deflateInit2(z_streamp strm,
                                 int level,
                                 int method,
                                 int windowBits,
                                 int memLevel,
                                 int strategy);

     This is another version of deflateInit with more compression options.  The
   fields next_in, zalloc, zfree and opaque must be initialized before by the
   fields zalloc, zfree and opaque must be initialized before by the caller.
   caller.

     The method parameter is the compression method.  It must be Z_DEFLATED in
   this version of the library.

     The windowBits parameter is the base two logarithm of the window size
   (the size of the history buffer).  It should be in the range 8..15 for this
   version of the library.  Larger values of this parameter result in better
604
605
606
607
608
609
610
611
612
613



614
615
616
617
618
619
620
604
605
606
607
608
609
610



611
612
613
614
615
616
617
618
619
620







-
-
-
+
+
+







   memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid
   method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is
   incompatible with the version assumed by the caller (ZLIB_VERSION).  msg is
   set to null if there is no error message.  deflateInit2 does not perform any
   compression: this will be done by deflate().
*/

ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
                                             const Bytef *dictionary,
                                             uInt  dictLength));
ZEXTERN int ZEXPORT deflateSetDictionary(z_streamp strm,
                                         const Bytef *dictionary,
                                         uInt  dictLength);
/*
     Initializes the compression dictionary from the given byte sequence
   without producing any compressed output.  When using the zlib format, this
   function must be called immediately after deflateInit, deflateInit2 or
   deflateReset, and before any call of deflate.  When doing raw deflate, this
   function must be called either before any call of deflate, or immediately
   after the completion of a deflate block, i.e. after all input has been
648
649
650
651
652
653
654
655
656
657



658
659
660
661
662
663
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
707
708



709
710
711
712
713
714
715
716
717
718
719






720
721
722
723
724
725
726
727
728
729
730
731
732

733
734
735
736
737
738
739
740
741
742
743
744
745
746
747





748
749
750
751
752
753
754
755
756
757
758
759
760
761


762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777



778
779
780
781
782
783
784
785
786
787
788
789
790
791
792



793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808


809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825



826
827
828
829
830
831
832
833


834
835
836
837
838
839
840
648
649
650
651
652
653
654



655
656
657
658
659
660
661
662
663

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
707
708
709
710
711
712
713
714





715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732

733
734
735
736
737
738
739
740
741
742
743





744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760


761
762
763
764
765
766
767
768
769
770
771
772
773
774
775



776
777
778
779
780
781
782
783
784
785
786
787
788
789
790



791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807


808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824


825
826
827
828
829
830
831
832
833


834
835
836
837
838
839
840
841
842







-
-
-
+
+
+






-
+












-
-
+
+
















-
+




-
+





-
-
-
+
+
+






-
-
-
-
-
+
+
+
+
+
+












-
+










-
-
-
-
-
+
+
+
+
+












-
-
+
+













-
-
-
+
+
+












-
-
-
+
+
+














-
-
+
+















-
-
+
+
+






-
-
+
+







     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
   inconsistent (for example if deflate has already been called for this stream
   or if not at a block boundary for raw deflate).  deflateSetDictionary does
   not perform any compression: this will be done by deflate().
*/

ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm,
                                             Bytef *dictionary,
                                             uInt  *dictLength));
ZEXTERN int ZEXPORT deflateGetDictionary(z_streamp strm,
                                         Bytef *dictionary,
                                         uInt  *dictLength);
/*
     Returns the sliding dictionary being maintained by deflate.  dictLength is
   set to the number of bytes in the dictionary, and that many bytes are copied
   to dictionary.  dictionary must have enough space, where 32768 bytes is
   always enough.  If deflateGetDictionary() is called with dictionary equal to
   Z_NULL, then only the dictionary length is returned, and nothing is copied.
   Similary, if dictLength is Z_NULL, then it is not set.
   Similarly, if dictLength is Z_NULL, then it is not set.

     deflateGetDictionary() may return a length less than the window size, even
   when more than the window size in input has been provided. It may return up
   to 258 bytes less in that case, due to how zlib's implementation of deflate
   manages the sliding window and lookahead for matches, where matches can be
   up to 258 bytes long. If the application needs the last window-size bytes of
   input, then that would need to be saved by the application outside of zlib.

     deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
   stream state is inconsistent.
*/

ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
                                    z_streamp source));
ZEXTERN int ZEXPORT deflateCopy(z_streamp dest,
                                z_streamp source);
/*
     Sets the destination stream as a complete copy of the source stream.

     This function can be useful when several compression strategies will be
   tried, for example when there are several ways of pre-processing the input
   data with a filter.  The streams that will be discarded should then be freed
   by calling deflateEnd.  Note that deflateCopy duplicates the internal
   compression state which can be quite large, so this strategy is slow and can
   consume lots of memory.

     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
   destination.
*/

ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
ZEXTERN int ZEXPORT deflateReset(z_streamp strm);
/*
     This function is equivalent to deflateEnd followed by deflateInit, but
   does not free and reallocate the internal compression state.  The stream
   will leave the compression level and any other attributes that may have been
   set unchanged.
   set unchanged.  total_in, total_out, adler, and msg are initialized.

     deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
   stream state was inconsistent (such as zalloc or state being Z_NULL).
*/

ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
                                      int level,
                                      int strategy));
ZEXTERN int ZEXPORT deflateParams(z_streamp strm,
                                  int level,
                                  int strategy);
/*
     Dynamically update the compression level and compression strategy.  The
   interpretation of level and strategy is as in deflateInit2().  This can be
   used to switch between compression and straight copy of the input data, or
   to switch to a different kind of input data requiring a different strategy.
   If the compression approach (which is a function of the level) or the
   strategy is changed, and if any input has been consumed in a previous
   deflate() call, then the input available so far is compressed with the old
   level and strategy using deflate(strm, Z_BLOCK).  There are three approaches
   for the compression levels 0, 1..3, and 4..9 respectively.  The new level
   and strategy will take effect at the next call of deflate().
   strategy is changed, and if there have been any deflate() calls since the
   state was initialized or reset, then the input available so far is
   compressed with the old level and strategy using deflate(strm, Z_BLOCK).
   There are three approaches for the compression levels 0, 1..3, and 4..9
   respectively.  The new level and strategy will take effect at the next call
   of deflate().

     If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does
   not have enough output space to complete, then the parameter change will not
   take effect.  In this case, deflateParams() can be called again with the
   same parameters and more output space to try again.

     In order to assure a change in the parameters on the first try, the
   deflate stream should be flushed using deflate() with Z_BLOCK or other flush
   request until strm.avail_out is not zero, before calling deflateParams().
   Then no more input data should be provided before the deflateParams() call.
   If this is done, the old level and strategy will be applied to the data
   compressed before deflateParams(), and the new level and strategy will be
   applied to the the data compressed after deflateParams().
   applied to the data compressed after deflateParams().

     deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream
   state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if
   there was not enough output space to complete the compression of the
   available input data before a change in the strategy or approach.  Note that
   in the case of a Z_BUF_ERROR, the parameters are not changed.  A return
   value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be
   retried with more output space.
*/

ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
                                    int good_length,
                                    int max_lazy,
                                    int nice_length,
                                    int max_chain));
ZEXTERN int ZEXPORT deflateTune(z_streamp strm,
                                int good_length,
                                int max_lazy,
                                int nice_length,
                                int max_chain);
/*
     Fine tune deflate's internal compression parameters.  This should only be
   used by someone who understands the algorithm used by zlib's deflate for
   searching for the best matching string, and even then only by the most
   fanatic optimizer trying to squeeze out the last compressed bit for their
   specific input data.  Read the deflate.c source code for the meaning of the
   max_lazy, good_length, nice_length, and max_chain parameters.

     deflateTune() can be called after deflateInit() or deflateInit2(), and
   returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
 */

ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
                                       uLong sourceLen));
ZEXTERN uLong ZEXPORT deflateBound(z_streamp strm,
                                   uLong sourceLen);
/*
     deflateBound() returns an upper bound on the compressed size after
   deflation of sourceLen bytes.  It must be called after deflateInit() or
   deflateInit2(), and after deflateSetHeader(), if used.  This would be used
   to allocate an output buffer for deflation in a single pass, and so would be
   called before deflate().  If that first deflate() call is provided the
   sourceLen input bytes, an output buffer allocated to the size returned by
   deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed
   to return Z_STREAM_END.  Note that it is possible for the compressed size to
   be larger than the value returned by deflateBound() if flush options other
   than Z_FINISH or Z_NO_FLUSH are used.
*/

ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
                                       unsigned *pending,
                                       int *bits));
ZEXTERN int ZEXPORT deflatePending(z_streamp strm,
                                   unsigned *pending,
                                   int *bits);
/*
     deflatePending() returns the number of bytes and bits of output that have
   been generated, but not yet provided in the available output.  The bytes not
   provided would be due to the available output space having being consumed.
   The number of bits of output not provided are between 0 and 7, where they
   await more bits to join them in order to fill out a full byte.  If pending
   or bits are Z_NULL, then those values are not set.

     deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
   stream state was inconsistent.
 */

ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
                                     int bits,
                                     int value));
ZEXTERN int ZEXPORT deflatePrime(z_streamp strm,
                                 int bits,
                                 int value);
/*
     deflatePrime() inserts bits in the deflate output stream.  The intent
   is that this function is used to start off the deflate output with the bits
   leftover from a previous deflate stream when appending to it.  As such, this
   function can only be used for raw deflate, and must be used before the first
   deflate() call after a deflateInit2() or deflateReset().  bits must be less
   than or equal to 16, and that many of the least significant bits of value
   will be inserted in the output.

     deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough
   room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the
   source stream state was inconsistent.
*/

ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
                                         gz_headerp head));
ZEXTERN int ZEXPORT deflateSetHeader(z_streamp strm,
                                     gz_headerp head);
/*
     deflateSetHeader() provides gzip header information for when a gzip
   stream is requested by deflateInit2().  deflateSetHeader() may be called
   after deflateInit2() or deflateReset() and before the first call of
   deflate().  The text, time, os, extra field, name, and comment information
   in the provided gz_header structure are written to the gzip header (xflag is
   ignored -- the extra flags are set according to the compression level).  The
   caller must assure that, if not Z_NULL, name and comment are terminated with
   a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
   available there.  If hcrc is true, a gzip header crc is included.  Note that
   the current versions of the command-line version of gzip (up through version
   1.3.x) do not support header crc's, and will report that it is a "multi-part
   gzip file" and give up.

     If deflateSetHeader is not used, the default gzip header has text false,
   the time set to zero, and os set to 255, with no extra, name, or comment
   fields.  The gzip header is returned to the default state by deflateReset().
   the time set to zero, and os set to the current operating system, with no
   extra, name, or comment fields.  The gzip header is returned to the default
   state by deflateReset().

     deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
   stream state was inconsistent.
*/

/*
ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
                                     int  windowBits));
ZEXTERN int ZEXPORT inflateInit2(z_streamp strm,
                                 int windowBits);

     This is another version of inflateInit with an extra parameter.  The
   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
   before by the caller.

     The windowBits parameter is the base two logarithm of the maximum window
   size (the size of the history buffer).  It should be in the range 8..15 for
861
862
863
864
865
866
867
868
869
870





871
872
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
898
899
900
901
902
903
904
905
906
907
908
909



910
911
912
913
914
915
916

917
918
919
920
921
922

923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938




939
940
941
942


943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
863
864
865
866
867
868
869



870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910



911
912
913
914
915
916
917
918
919

920
921
922
923
924
925

926
927
928
929
930
931
932
933
934
935
936
937
938




939
940
941
942
943
944


945
946
947
948
949
950
951
952
953
954
955
956
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







-
-
-
+
+
+
+
+













-
-
-
+
+
+




















-
-
-
+
+
+






-
+





-
+












-
-
-
-
+
+
+
+


-
-
+
+














-
+




+





-
-
+
+












-
-
-
+
+
+


















-
+







   above on the use in deflateInit2() applies to the magnitude of windowBits.

     windowBits can also be greater than 15 for optional gzip decoding.  Add
   32 to windowBits to enable zlib and gzip decoding with automatic header
   detection, or add 16 to decode only the gzip format (the zlib format will
   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is a
   CRC-32 instead of an Adler-32.  Unlike the gunzip utility and gzread() (see
   below), inflate() will not automatically decode concatenated gzip streams.
   inflate() will return Z_STREAM_END at the end of the gzip stream.  The state
   would need to be reset to continue decoding a subsequent gzip stream.
   below), inflate() will *not* automatically decode concatenated gzip members.
   inflate() will return Z_STREAM_END at the end of the gzip member.  The state
   would need to be reset to continue decoding a subsequent gzip member.  This
   *must* be done if there is more data after a gzip member, in order for the
   decompression to be compliant with the gzip standard (RFC 1952).

     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
   invalid, such as a null pointer to the structure.  msg is set to null if
   there is no error message.  inflateInit2 does not perform any decompression
   apart from possibly reading the zlib header if present: actual decompression
   will be done by inflate().  (So next_in and avail_in may be modified, but
   next_out and avail_out are unused and unchanged.) The current implementation
   of inflateInit2() does not process any header information -- that is
   deferred until inflate() is called.
*/

ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
                                             const Bytef *dictionary,
                                             uInt  dictLength));
ZEXTERN int ZEXPORT inflateSetDictionary(z_streamp strm,
                                         const Bytef *dictionary,
                                         uInt  dictLength);
/*
     Initializes the decompression dictionary from the given uncompressed byte
   sequence.  This function must be called immediately after a call of inflate,
   if that call returned Z_NEED_DICT.  The dictionary chosen by the compressor
   can be determined from the Adler-32 value returned by that call of inflate.
   The compressor and decompressor must use exactly the same dictionary (see
   deflateSetDictionary).  For raw inflate, this function can be called at any
   time to set the dictionary.  If the provided dictionary is smaller than the
   window and there is already data in the window, then the provided dictionary
   will amend what's there.  The application must insure that the dictionary
   that was used for compression is provided.

     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
   expected one (incorrect Adler-32 value).  inflateSetDictionary does not
   perform any decompression: this will be done by subsequent calls of
   inflate().
*/

ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,
                                             Bytef *dictionary,
                                             uInt  *dictLength));
ZEXTERN int ZEXPORT inflateGetDictionary(z_streamp strm,
                                         Bytef *dictionary,
                                         uInt  *dictLength);
/*
     Returns the sliding dictionary being maintained by inflate.  dictLength is
   set to the number of bytes in the dictionary, and that many bytes are copied
   to dictionary.  dictionary must have enough space, where 32768 bytes is
   always enough.  If inflateGetDictionary() is called with dictionary equal to
   Z_NULL, then only the dictionary length is returned, and nothing is copied.
   Similary, if dictLength is Z_NULL, then it is not set.
   Similarly, if dictLength is Z_NULL, then it is not set.

     inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
   stream state is inconsistent.
*/

ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
ZEXTERN int ZEXPORT inflateSync(z_streamp strm);
/*
     Skips invalid compressed data until a possible full flush point (see above
   for the description of deflate with Z_FULL_FLUSH) can be found, or until all
   available input is skipped.  No output is provided.

     inflateSync searches for a 00 00 FF FF pattern in the compressed data.
   All full flush points have this pattern, but not all occurrences of this
   pattern are full flush points.

     inflateSync returns Z_OK if a possible full flush point has been found,
   Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
   has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
   In the success case, the application may save the current current value of
   total_in which indicates where valid compressed data was found.  In the
   error case, the application may repeatedly call inflateSync, providing more
   input each time, until success or end of the input data.
   In the success case, the application may save the current value of total_in
   which indicates where valid compressed data was found.  In the error case,
   the application may repeatedly call inflateSync, providing more input each
   time, until success or end of the input data.
*/

ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
                                    z_streamp source));
ZEXTERN int ZEXPORT inflateCopy(z_streamp dest,
                                z_streamp source);
/*
     Sets the destination stream as a complete copy of the source stream.

     This function can be useful when randomly accessing a large stream.  The
   first pass through the stream can periodically record the inflate state,
   allowing restarting inflate at those points when randomly accessing the
   stream.

     inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
   destination.
*/

ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
ZEXTERN int ZEXPORT inflateReset(z_streamp strm);
/*
     This function is equivalent to inflateEnd followed by inflateInit,
   but does not free and reallocate the internal decompression state.  The
   stream will keep attributes that may have been set by inflateInit2.
   total_in, total_out, adler, and msg are initialized.

     inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
   stream state was inconsistent (such as zalloc or state being Z_NULL).
*/

ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
                                      int windowBits));
ZEXTERN int ZEXPORT inflateReset2(z_streamp strm,
                                  int windowBits);
/*
     This function is the same as inflateReset, but it also permits changing
   the wrap and window size requests.  The windowBits parameter is interpreted
   the same as it is for inflateInit2.  If the window size is changed, then the
   memory allocated for the window is freed, and the window will be reallocated
   by inflate() if needed.

     inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
   stream state was inconsistent (such as zalloc or state being Z_NULL), or if
   the windowBits parameter is invalid.
*/

ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
                                     int bits,
                                     int value));
ZEXTERN int ZEXPORT inflatePrime(z_streamp strm,
                                 int bits,
                                 int value);
/*
     This function inserts bits in the inflate input stream.  The intent is
   that this function is used to start inflating at a bit position in the
   middle of a byte.  The provided bits will be used before any bytes are used
   from next_in.  This function should only be used with raw inflate, and
   should be used before the first inflate() call after inflateInit2() or
   inflateReset().  bits must be less than or equal to 16, and that many of the
   least significant bits of value will be inserted in the input.

     If bits is negative, then the input stream bit buffer is emptied.  Then
   inflatePrime() can be called again to put bits in the buffer.  This is used
   to clear out bits leftover after feeding inflate a block description prior
   to feeding inflate codes.

     inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
   stream state was inconsistent.
*/

ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
ZEXTERN long ZEXPORT inflateMark(z_streamp strm);
/*
     This function returns two values, one in the lower 16 bits of the return
   value, and the other in the remaining upper bits, obtained by shifting the
   return value down 16 bits.  If the upper value is -1 and the lower value is
   zero, then inflate() is currently decoding information outside of a block.
   If the upper value is -1 and the lower value is non-zero, then inflate is in
   the middle of a stored block, with the lower value equaling the number of
1023
1024
1025
1026
1027
1028
1029
1030
1031


1032
1033
1034
1035
1036
1037
1038
1028
1029
1030
1031
1032
1033
1034


1035
1036
1037
1038
1039
1040
1041
1042
1043







-
-
+
+







   location in the input stream can be determined from avail_in and data_type
   as noted in the description for the Z_BLOCK flush parameter for inflate.

     inflateMark returns the value noted above, or -65536 if the provided
   source stream state was inconsistent.
*/

ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
                                         gz_headerp head));
ZEXTERN int ZEXPORT inflateGetHeader(z_streamp strm,
                                     gz_headerp head);
/*
     inflateGetHeader() requests that gzip header information be stored in the
   provided gz_header structure.  inflateGetHeader() may be called after
   inflateInit2() or inflateReset(), and before the first call of inflate().
   As inflate() processes the gzip stream, head->done is zero until the header
   is completed, at which time head->done is set to one.  If a zlib stream is
   being decoded, then head->done is set to -1 to indicate that there will be
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
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







-
-
+
+



















-
-
-
+
+
+

-
-
-
+
+
+







   retrieve the header from the next gzip stream.

     inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
   stream state was inconsistent.
*/

/*
ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
                                        unsigned char FAR *window));
ZEXTERN int ZEXPORT inflateBackInit(z_streamp strm, int windowBits,
                                    unsigned char FAR *window);

     Initialize the internal stream state for decompression using inflateBack()
   calls.  The fields zalloc, zfree and opaque in strm must be initialized
   before the call.  If zalloc and zfree are Z_NULL, then the default library-
   derived memory allocation routines are used.  windowBits is the base two
   logarithm of the window size, in the range 8..15.  window is a caller
   supplied buffer of that size.  Except for special applications where it is
   assured that deflate was used with small window sizes, windowBits must be 15
   and a 32K byte window must be supplied to be able to decompress general
   deflate streams.

     See inflateBack() for the usage of these routines.

     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
   the parameters are invalid, Z_MEM_ERROR if the internal state could not be
   allocated, or Z_VERSION_ERROR if the version of the library does not match
   the version of the header file.
*/

typedef unsigned (*in_func) OF((void FAR *,
                                z_const unsigned char FAR * FAR *));
typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
typedef unsigned (*in_func)(void FAR *,
                            z_const unsigned char FAR * FAR *);
typedef int (*out_func)(void FAR *, unsigned char FAR *, unsigned);

ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
                                    in_func in, void FAR *in_desc,
                                    out_func out, void FAR *out_desc));
ZEXTERN int ZEXPORT inflateBack(z_streamp strm,
                                in_func in, void FAR *in_desc,
                                out_func out, void FAR *out_desc);
/*
     inflateBack() does a raw inflate with a single call using a call-back
   interface for input and output.  This is potentially more efficient than
   inflate() for file i/o applications, in that it avoids copying between the
   output and the sliding window by simply making the window itself the output
   buffer.  inflate() can be faster on modern CPUs when used with large
   buffers.  inflateBack() trusts the application to not change the output
1159
1160
1161
1162
1163
1164
1165
1166

1167
1168
1169
1170
1171
1172
1173
1174

1175
1176
1177
1178
1179
1180
1181
1164
1165
1166
1167
1168
1169
1170

1171
1172
1173
1174
1175
1176
1177
1178

1179
1180
1181
1182
1183
1184
1185
1186







-
+







-
+







   using strm->next_in which will be Z_NULL only if in() returned an error.  If
   strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning
   non-zero.  (in() will always be called before out(), so strm->next_in is
   assured to be defined if out() returns non-zero.)  Note that inflateBack()
   cannot return Z_OK.
*/

ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
ZEXTERN int ZEXPORT inflateBackEnd(z_streamp strm);
/*
     All memory allocated by inflateBackInit() is freed.

     inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
   state was inconsistent.
*/

ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
ZEXTERN uLong ZEXPORT zlibCompileFlags(void);
/* Return flags indicating compile-time options.

    Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
     1.0: size of uInt
     3.2: size of uLong
     5.4: size of voidpf (pointer)
     7.6: size of z_off_t
1220
1221
1222
1223
1224
1225
1226
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
1225
1226
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







-
-
+
+













-
-
-
+
+
+













-
+






-
-
+
+
















-
-
+
+


















-
+

+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-







     The following utility functions are implemented on top of the basic
   stream-oriented functions.  To simplify the interface, some default options
   are assumed (compression level and memory usage, standard memory allocation
   functions).  The source code of these utility functions can be modified if
   you need special options.
*/

ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
                                 const Bytef *source, uLong sourceLen));
ZEXTERN int ZEXPORT compress(Bytef *dest,   uLongf *destLen,
                             const Bytef *source, uLong sourceLen);
/*
     Compresses the source buffer into the destination buffer.  sourceLen is
   the byte length of the source buffer.  Upon entry, destLen is the total size
   of the destination buffer, which must be at least the value returned by
   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
   compressed data.  compress() is equivalent to compress2() with a level
   parameter of Z_DEFAULT_COMPRESSION.

     compress returns Z_OK if success, Z_MEM_ERROR if there was not
   enough memory, Z_BUF_ERROR if there was not enough room in the output
   buffer.
*/

ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
                                  const Bytef *source, uLong sourceLen,
                                  int level));
ZEXTERN int ZEXPORT compress2(Bytef *dest,   uLongf *destLen,
                              const Bytef *source, uLong sourceLen,
                              int level);
/*
     Compresses the source buffer into the destination buffer.  The level
   parameter has the same meaning as in deflateInit.  sourceLen is the byte
   length of the source buffer.  Upon entry, destLen is the total size of the
   destination buffer, which must be at least the value returned by
   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
   compressed data.

     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
   Z_STREAM_ERROR if the level parameter is invalid.
*/

ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
ZEXTERN uLong ZEXPORT compressBound(uLong sourceLen);
/*
     compressBound() returns an upper bound on the compressed size after
   compress() or compress2() on sourceLen bytes.  It would be used before a
   compress() or compress2() call to allocate the destination buffer.
*/

ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
                                   const Bytef *source, uLong sourceLen));
ZEXTERN int ZEXPORT uncompress(Bytef *dest,   uLongf *destLen,
                               const Bytef *source, uLong sourceLen);
/*
     Decompresses the source buffer into the destination buffer.  sourceLen is
   the byte length of the source buffer.  Upon entry, destLen is the total size
   of the destination buffer, which must be large enough to hold the entire
   uncompressed data.  (The size of the uncompressed data must have been saved
   previously by the compressor and transmitted to the decompressor by some
   mechanism outside the scope of this compression library.) Upon exit, destLen
   is the actual size of the uncompressed data.

     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
   enough memory, Z_BUF_ERROR if there was not enough room in the output
   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.  In
   the case where there is not enough room, uncompress() will fill the output
   buffer with the uncompressed data up to that point.
*/

ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest,   uLongf *destLen,
                                    const Bytef *source, uLong *sourceLen));
ZEXTERN int ZEXPORT uncompress2(Bytef *dest,   uLongf *destLen,
                                const Bytef *source, uLong *sourceLen);
/*
     Same as uncompress, except that sourceLen is a pointer, where the
   length of the source is *sourceLen.  On return, *sourceLen is the number of
   source bytes consumed.
*/

                        /* gzip file access functions */

/*
     This library supports reading and writing files in gzip (.gz) format with
   an interface similar to that of stdio, using the functions that start with
   "gz".  The gzip format is different from the zlib format.  gzip is a gzip
   wrapper, documented in RFC 1952, wrapped around a deflate stream.
*/

typedef struct gzFile_s *gzFile;    /* semi-opaque gzip file descriptor */

/*
ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
ZEXTERN gzFile ZEXPORT gzopen(const char *path, const char *mode);

     Open the gzip (.gz) file at path for reading and decompressing, or
     Opens a gzip (.gz) file for reading or writing.  The mode parameter is as
   in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
   a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
   compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
   for fixed code compression as in "wb9F".  (See the description of
   deflateInit2 for more information about the strategy parameter.)  'T' will
   request transparent writing or appending with no compression and not using
   compressing and writing.  The mode parameter is as in fopen ("rb" or "wb")
   but can also include a compression level ("wb9") or a strategy: 'f' for
   filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h",
   'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression
   as in "wb9F".  (See the description of deflateInit2 for more information
   about the strategy parameter.)  'T' will request transparent writing or
   appending with no compression and not using the gzip format.
   the gzip format.

     "a" can be used instead of "w" to request that the gzip stream that will
   be written be appended to the file.  "+" will result in an error, since
   reading and writing to the same gzip file is not supported.  The addition of
   "x" when writing will create the file exclusively, which fails if the file
   already exists.  On systems that support it, the addition of "e" when
   reading or writing will set the flag to close the file on an execve() call.
1333
1334
1335
1336
1337
1338
1339
1340

1341
1342
1343
1344



1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390

1391
1392

1393
1394
1395
1396
1397
1398
1399
1338
1339
1340
1341
1342
1343
1344

1345
1346



1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394

1395
1396

1397
1398
1399
1400
1401
1402
1403
1404







-
+

-
-
-
+
+
+


















-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+







-
+

-
-
-
+
+
+






-
+

-
+







     gzopen returns NULL if the file could not be opened, if there was
   insufficient memory to allocate the gzFile state, or if an invalid mode was
   specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
   errno can be checked to determine if the reason gzopen failed was that the
   file could not be opened.
*/

ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
ZEXTERN gzFile ZEXPORT gzdopen(int fd, const char *mode);
/*
     gzdopen associates a gzFile with the file descriptor fd.  File descriptors
   are obtained from calls like open, dup, creat, pipe or fileno (if the file
   has been previously opened with fopen).  The mode parameter is as in gzopen.
     Associate a gzFile with the file descriptor fd.  File descriptors are
   obtained from calls like open, dup, creat, pipe or fileno (if the file has
   been previously opened with fopen).  The mode parameter is as in gzopen.

     The next call of gzclose on the returned gzFile will also close the file
   descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
   fd.  If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
   mode);.  The duplicated descriptor should be saved to avoid a leak, since
   gzdopen does not close fd if it fails.  If you are using fileno() to get the
   file descriptor from a FILE *, then you will have to use dup() to avoid
   double-close()ing the file descriptor.  Both gzclose() and fclose() will
   close the associated file descriptor, so they need to have different file
   descriptors.

     gzdopen returns NULL if there was insufficient memory to allocate the
   gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
   provided, or '+' was provided), or if fd is -1.  The file descriptor is not
   used until the next gz* read, write, seek, or close operation, so gzdopen
   will not detect if fd is invalid (unless fd is -1).
*/

ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
ZEXTERN int ZEXPORT gzbuffer(gzFile file, unsigned size);
/*
     Set the internal buffer size used by this library's functions.  The
   default buffer size is 8192 bytes.  This function must be called after
   gzopen() or gzdopen(), and before any other calls that read or write the
   file.  The buffer memory allocation is always deferred to the first read or
   write.  Three times that size in buffer space is allocated.  A larger buffer
   size of, for example, 64K or 128K bytes will noticeably increase the speed
   of decompression (reading).
     Set the internal buffer size used by this library's functions for file to
   size.  The default buffer size is 8192 bytes.  This function must be called
   after gzopen() or gzdopen(), and before any other calls that read or write
   the file.  The buffer memory allocation is always deferred to the first read
   or write.  Three times that size in buffer space is allocated.  A larger
   buffer size of, for example, 64K or 128K bytes will noticeably increase the
   speed of decompression (reading).

     The new buffer size also affects the maximum length for gzprintf().

     gzbuffer() returns 0 on success, or -1 on failure, such as being called
   too late.
*/

ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
ZEXTERN int ZEXPORT gzsetparams(gzFile file, int level, int strategy);
/*
     Dynamically update the compression level or strategy.  See the description
   of deflateInit2 for the meaning of these parameters.  Previously provided
   data is flushed before the parameter change.
     Dynamically update the compression level and strategy for file.  See the
   description of deflateInit2 for the meaning of these parameters. Previously
   provided data is flushed before applying the parameter changes.

     gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not
   opened for writing, Z_ERRNO if there is an error writing the flushed data,
   or Z_MEM_ERROR if there is a memory allocation error.
*/

ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
ZEXTERN int ZEXPORT gzread(gzFile file, voidp buf, unsigned len);
/*
     Reads the given number of uncompressed bytes from the compressed file.  If
     Read and decompress up to len uncompressed bytes from file into buf.  If
   the input file is not in gzip format, gzread copies the given number of
   bytes into the buffer directly from the file.

     After reaching the end of a gzip stream in the input, gzread will continue
   to read, looking for another gzip stream.  Any number of gzip streams may be
   concatenated in the input file, and will all be decompressed by gzread().
   If something other than a gzip stream is encountered after a gzip stream,
1413
1414
1415
1416
1417
1418
1419
1420
1421


1422
1423
1424
1425
1426
1427





1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438

1439
1440
1441
1442
1443

1444
1445
1446

1447
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
1478

1479
1480
1481
1482
1483

1484
1485

1486
1487
1488
1489
1490
1491

1492
1493
1494
1495
1496
1497






1498
1499
1500
1501
1502
1503
1504

1505
1506

1507
1508
1509
1510

1511
1512

1513
1514
1515
1516
1517
1518
1519

1520
1521
1522


1523
1524
1525
1526
1527
1528
1529
1530
1531

1532
1533
1534
1535



1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548


1549
1550
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
1749

1750
1751
1752
1753
1754


1755













1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777














1778
1779
1780
1781
1782
1783
1784
1418
1419
1420
1421
1422
1423
1424


1425
1426
1427





1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442

1443
1444
1445
1446
1447

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
1478
1479
1480

1481
1482
1483
1484
1485

1486
1487

1488
1489
1490
1491
1492
1493

1494
1495





1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507

1508
1509

1510
1511
1512
1513

1514
1515

1516
1517
1518
1519
1520
1521
1522

1523
1524


1525
1526
1527
1528
1529
1530
1531
1532
1533
1534

1535
1536



1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550


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
1749
1750
1751
1752
1753
1754

1755
1756
1757
1758
1759
1760
1761
1762

1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783














1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804







-
-
+
+

-
-
-
-
-
+
+
+
+
+










-
+




-
+


-
+
-

-
-
+
+
-


-
-
+
+

-
+










-
+

-
-
+
+






-
+




-
+

-
+





-
+

-
-
-
-
-
+
+
+
+
+
+






-
+

-
+



-
+

-
+






-
+

-
-
+
+








-
+

-
-
-
+
+
+











-
-
+
+

-
-
+
+














-
+

-
+

-
+



-
+

-
-
-
-
+
+
+
+





-
+

-
-
-
-
-
+
+
+
+
+


-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+






-
+

-
+


















-
+

-
-
+
+









-
-
+
+










-
+

-
-
-
-
+
+
+
+










-
+

-
+














-
+


+
-
-
+
+














-
-
+
+





-
-
+
+









-
+


+
-
-
-
+
+
+











-
-
+
+





-
+





+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+








-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+








     gzread returns the number of uncompressed bytes actually read, less than
   len for end of file, or -1 for error.  If len is too large to fit in an int,
   then nothing is read, -1 is returned, and the error state is set to
   Z_STREAM_ERROR.
*/

ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,
                                     gzFile file));
ZEXTERN z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems,
                                 gzFile file);
/*
     Read up to nitems items of size size from file to buf, otherwise operating
   as gzread() does.  This duplicates the interface of stdio's fread(), with
   size_t request and return types.  If the library defines size_t, then
   z_size_t is identical to size_t.  If not, then z_size_t is an unsigned
   integer type that can contain a pointer.
     Read and decompress up to nitems items of size size from file into buf,
   otherwise operating as gzread() does.  This duplicates the interface of
   stdio's fread(), with size_t request and return types.  If the library
   defines size_t, then z_size_t is identical to size_t.  If not, then z_size_t
   is an unsigned integer type that can contain a pointer.

     gzfread() returns the number of full items read of size size, or zero if
   the end of the file was reached and a full item could not be read, or if
   there was an error.  gzerror() must be consulted if zero is returned in
   order to determine if there was an error.  If the multiplication of size and
   nitems overflows, i.e. the product does not fit in a z_size_t, then nothing
   is read, zero is returned, and the error state is set to Z_STREAM_ERROR.

     In the event that the end of file is reached and only a partial item is
   available at the end, i.e. the remaining uncompressed data length is not a
   multiple of size, then the final partial item is nevetheless read into buf
   multiple of size, then the final partial item is nevertheless read into buf
   and the end-of-file flag is set.  The length of the partial item read is not
   provided, but could be inferred from the result of gztell().  This behavior
   is the same as the behavior of fread() implementations in common libraries,
   but it prevents the direct use of gzfread() to read a concurrently written
   file, reseting and retrying on end-of-file, when size is not 1.
   file, resetting and retrying on end-of-file, when size is not 1.
*/

ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
ZEXTERN int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len);
                                voidpc buf, unsigned len));
/*
     Writes the given number of uncompressed bytes into the compressed file.
   gzwrite returns the number of uncompressed bytes written or 0 in case of
     Compress and write the len uncompressed bytes at buf to file. gzwrite
   returns the number of uncompressed bytes written or 0 in case of error.
   error.
*/

ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,
                                      z_size_t nitems, gzFile file));
ZEXTERN z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size,
                                  z_size_t nitems, gzFile file);
/*
     gzfwrite() writes nitems items of size size from buf to file, duplicating
     Compress and write nitems items of size size from buf to file, duplicating
   the interface of stdio's fwrite(), with size_t request and return types.  If
   the library defines size_t, then z_size_t is identical to size_t.  If not,
   then z_size_t is an unsigned integer type that can contain a pointer.

     gzfwrite() returns the number of full items written of size size, or zero
   if there was an error.  If the multiplication of size and nitems overflows,
   i.e. the product does not fit in a z_size_t, then nothing is written, zero
   is returned, and the error state is set to Z_STREAM_ERROR.
*/

ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
ZEXTERN int ZEXPORTVA gzprintf(gzFile file, const char *format, ...);
/*
     Converts, formats, and writes the arguments to the compressed file under
   control of the format string, as in fprintf.  gzprintf returns the number of
     Convert, format, compress, and write the arguments (...) to file under
   control of the string format, as in fprintf.  gzprintf returns the number of
   uncompressed bytes actually written, or a negative zlib error code in case
   of error.  The number of uncompressed bytes written is limited to 8191, or
   one less than the buffer size given to gzbuffer().  The caller should assure
   that this limit is not exceeded.  If it is exceeded, then gzprintf() will
   return an error (0) with nothing written.  In this case, there may also be a
   buffer overflow with unpredictable consequences, which is possible only if
   zlib was compiled with the insecure functions sprintf() or vsprintf()
   zlib was compiled with the insecure functions sprintf() or vsprintf(),
   because the secure snprintf() or vsnprintf() functions were not available.
   This can be determined using zlibCompileFlags().
*/

ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
ZEXTERN int ZEXPORT gzputs(gzFile file, const char *s);
/*
     Writes the given null-terminated string to the compressed file, excluding
     Compress and write the given null-terminated string s to file, excluding
   the terminating null character.

     gzputs returns the number of characters written, or -1 in case of error.
*/

ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
ZEXTERN char * ZEXPORT gzgets(gzFile file, char *buf, int len);
/*
     Reads bytes from the compressed file until len-1 characters are read, or a
   newline character is read and transferred to buf, or an end-of-file
   condition is encountered.  If any characters are read or if len == 1, the
   string is terminated with a null character.  If no characters are read due
   to an end-of-file or len < 1, then the buffer is left untouched.
     Read and decompress bytes from file into buf, until len-1 characters are
   read, or until a newline character is read and transferred to buf, or an
   end-of-file condition is encountered.  If any characters are read or if len
   is one, the string is terminated with a null character.  If no characters
   are read due to an end-of-file or len is less than one, then the buffer is
   left untouched.

     gzgets returns buf which is a null-terminated string, or it returns NULL
   for end-of-file or in case of error.  If there was an error, the contents at
   buf are indeterminate.
*/

ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
ZEXTERN int ZEXPORT gzputc(gzFile file, int c);
/*
     Writes c, converted to an unsigned char, into the compressed file.  gzputc
     Compress and write c, converted to an unsigned char, into file.  gzputc
   returns the value that was written, or -1 in case of error.
*/

ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
ZEXTERN int ZEXPORT gzgetc(gzFile file);
/*
     Reads one byte from the compressed file.  gzgetc returns this byte or -1
     Read and decompress one byte from file.  gzgetc returns this byte or -1
   in case of end of file or error.  This is implemented as a macro for speed.
   As such, it does not do all of the checking the other functions do.  I.e.
   it does not check to see if file is NULL, nor whether the structure file
   points to has been clobbered or not.
*/

ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
ZEXTERN int ZEXPORT gzungetc(int c, gzFile file);
/*
     Push one character back onto the stream to be read as the first character
   on the next read.  At least one character of push-back is allowed.
     Push c back onto the stream for file to be read as the first character on
   the next read.  At least one character of push-back is always allowed.
   gzungetc() returns the character pushed, or -1 on failure.  gzungetc() will
   fail if c is -1, and may fail if a character has been pushed but not read
   yet.  If gzungetc is used immediately after gzopen or gzdopen, at least the
   output buffer size of pushed characters is allowed.  (See gzbuffer above.)
   The pushed character will be discarded if the stream is repositioned with
   gzseek() or gzrewind().
*/

ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
ZEXTERN int ZEXPORT gzflush(gzFile file, int flush);
/*
     Flushes all pending output into the compressed file.  The parameter flush
   is as in the deflate() function.  The return value is the zlib error number
   (see function gzerror below).  gzflush is only permitted when writing.
     Flush all pending output to file.  The parameter flush is as in the
   deflate() function.  The return value is the zlib error number (see function
   gzerror below).  gzflush is only permitted when writing.

     If the flush parameter is Z_FINISH, the remaining data is written and the
   gzip stream is completed in the output.  If gzwrite() is called again, a new
   gzip stream will be started in the output.  gzread() is able to read such
   concatenated gzip streams.

     gzflush should be called only when strictly necessary because it will
   degrade compression if called too often.
*/

/*
ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
                                   z_off_t offset, int whence));
ZEXTERN z_off_t ZEXPORT gzseek(gzFile file,
                               z_off_t offset, int whence);

     Sets the starting position for the next gzread or gzwrite on the given
   compressed file.  The offset represents a number of bytes in the
     Set the starting position to offset relative to whence for the next gzread
   or gzwrite on file.  The offset represents a number of bytes in the
   uncompressed data stream.  The whence parameter is defined as in lseek(2);
   the value SEEK_END is not supported.

     If the file is opened for reading, this function is emulated but can be
   extremely slow.  If the file is opened for writing, only forward seeks are
   supported; gzseek then compresses a sequence of zeroes up to the new
   starting position.

     gzseek returns the resulting offset location as measured in bytes from
   the beginning of the uncompressed stream, or -1 in case of error, in
   particular if the file is opened for writing and the new starting position
   would be before the current position.
*/

ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
ZEXTERN int ZEXPORT    gzrewind(gzFile file);
/*
     Rewinds the given file. This function is supported only for reading.
     Rewind file. This function is supported only for reading.

     gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
     gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET).
*/

/*
ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
ZEXTERN z_off_t ZEXPORT    gztell(gzFile file);

     Returns the starting position for the next gzread or gzwrite on the given
   compressed file.  This position represents a number of bytes in the
   uncompressed data stream, and is zero when starting, even if appending or
   reading a gzip stream from the middle of a file using gzdopen().
     Return the starting position for the next gzread or gzwrite on file.
   This position represents a number of bytes in the uncompressed data stream,
   and is zero when starting, even if appending or reading a gzip stream from
   the middle of a file using gzdopen().

     gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
*/

/*
ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
ZEXTERN z_off_t ZEXPORT gzoffset(gzFile file);

     Returns the current offset in the file being read or written.  This offset
   includes the count of bytes that precede the gzip stream, for example when
   appending or when using gzdopen() for reading.  When reading, the offset
   does not include as yet unused buffered input.  This information can be used
   for a progress indicator.  On error, gzoffset() returns -1.
     Return the current compressed (actual) read or write offset of file.  This
   offset includes the count of bytes that precede the gzip stream, for example
   when appending or when using gzdopen() for reading.  When reading, the
   offset does not include as yet unused buffered input.  This information can
   be used for a progress indicator.  On error, gzoffset() returns -1.
*/

ZEXTERN int ZEXPORT gzeof OF((gzFile file));
ZEXTERN int ZEXPORT gzeof(gzFile file);
/*
     Returns true (1) if the end-of-file indicator has been set while reading,
   false (0) otherwise.  Note that the end-of-file indicator is set only if the
   read tried to go past the end of the input, but came up short.  Therefore,
   just like feof(), gzeof() may return false even if there is no more data to
   read, in the event that the last read request was for the exact number of
   bytes remaining in the input file.  This will happen if the input file size
   is an exact multiple of the buffer size.
     Return true (1) if the end-of-file indicator for file has been set while
   reading, false (0) otherwise.  Note that the end-of-file indicator is set
   only if the read tried to go past the end of the input, but came up short.
   Therefore, just like feof(), gzeof() may return false even if there is no
   more data to read, in the event that the last read request was for the exact
   number of bytes remaining in the input file.  This will happen if the input
   file size is an exact multiple of the buffer size.

     If gzeof() returns true, then the read functions will return no more data,
   unless the end-of-file indicator is reset by gzclearerr() and the input file
   has grown since the previous end of file was detected.
*/

ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
ZEXTERN int ZEXPORT gzdirect(gzFile file);
/*
     Returns true (1) if file is being copied directly while reading, or false
     Return true (1) if file is being copied directly while reading, or false
   (0) if file is a gzip stream being decompressed.

     If the input file is empty, gzdirect() will return true, since the input
   does not contain a gzip stream.

     If gzdirect() is used immediately after gzopen() or gzdopen() it will
   cause buffers to be allocated to allow reading the file to determine if it
   is a gzip file.  Therefore if gzbuffer() is used, it should be called before
   gzdirect().

     When writing, gzdirect() returns true (1) if transparent writing was
   requested ("wT" for the gzopen() mode), or false (0) otherwise.  (Note:
   gzdirect() is not needed when writing.  Transparent writing must be
   explicitly requested, so the application already knows the answer.  When
   linking statically, using gzdirect() will include all of the zlib code for
   gzip file reading and decompression, which may not be desired.)
*/

ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
ZEXTERN int ZEXPORT    gzclose(gzFile file);
/*
     Flushes all pending output if necessary, closes the compressed file and
   deallocates the (de)compression state.  Note that once file is closed, you
     Flush all pending output for file, if necessary, close file and
   deallocate the (de)compression state.  Note that once file is closed, you
   cannot call gzerror with file, since its structures have been deallocated.
   gzclose must not be called more than once on the same file, just as free
   must not be called more than once on the same allocation.

     gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
   file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the
   last read ended in the middle of a gzip stream, or Z_OK on success.
*/

ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
ZEXTERN int ZEXPORT gzclose_r(gzFile file);
ZEXTERN int ZEXPORT gzclose_w(gzFile file);
/*
     Same as gzclose(), but gzclose_r() is only for use when reading, and
   gzclose_w() is only for use when writing or appending.  The advantage to
   using these instead of gzclose() is that they avoid linking in zlib
   compression or decompression code that is not used when only reading or only
   writing respectively.  If gzclose() is used, then both compression and
   decompression code will be included the application when linking to a static
   zlib library.
*/

ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
ZEXTERN const char * ZEXPORT gzerror(gzFile file, int *errnum);
/*
     Returns the error message for the last error which occurred on the given
   compressed file.  errnum is set to zlib error number.  If an error occurred
   in the file system and not in the compression library, errnum is set to
   Z_ERRNO and the application may consult errno to get the exact error code.
     Return the error message for the last error which occurred on file.
   errnum is set to zlib error number.  If an error occurred in the file system
   and not in the compression library, errnum is set to Z_ERRNO and the
   application may consult errno to get the exact error code.

     The application must not modify the returned string.  Future calls to
   this function may invalidate the previously returned string.  If file is
   closed, then the string previously returned by gzerror will no longer be
   available.

     gzerror() should be used to distinguish errors from end-of-file for those
   functions above that do not distinguish those cases in their return values.
*/

ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
ZEXTERN void ZEXPORT gzclearerr(gzFile file);
/*
     Clears the error and end-of-file flags for file.  This is analogous to the
     Clear the error and end-of-file flags for file.  This is analogous to the
   clearerr() function in stdio.  This is useful for continuing to read a gzip
   file that is being written concurrently.
*/

#endif /* !Z_SOLO */

                        /* checksum functions */

/*
     These functions are not related to compression but are exported
   anyway because they might be useful in applications using the compression
   library.
*/

ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
ZEXTERN uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len);
/*
     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
   return the updated checksum. An Adler-32 value is in the range of a 32-bit
   return the updated checksum.  If buf is Z_NULL, this function returns the
   required initial value for the checksum.
   unsigned integer. If buf is Z_NULL, this function returns the required
   initial value for the checksum.

     An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed
   much faster.

   Usage example:

     uLong adler = adler32(0L, Z_NULL, 0);

     while (read_buffer(buffer, length) != EOF) {
       adler = adler32(adler, buffer, length);
     }
     if (adler != original_adler) error();
*/

ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf,
                                    z_size_t len));
ZEXTERN uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf,
                                z_size_t len);
/*
     Same as adler32(), but with a size_t length.
*/

/*
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
                                          z_off_t len2));
ZEXTERN uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2,
                                      z_off_t len2);

     Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1
   and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
   each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of
   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.  Note
   that the z_off_t type (like off_t) is a signed integer.  If len2 is
   negative, the result has no meaning or utility.
*/

ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
ZEXTERN uLong ZEXPORT crc32(uLong crc, const Bytef *buf, uInt len);
/*
     Update a running CRC-32 with the bytes buf[0..len-1] and return the
   updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer.
   updated CRC-32.  If buf is Z_NULL, this function returns the required
   initial value for the crc.  Pre- and post-conditioning (one's complement) is
   performed within this function so it shouldn't be done by the application.
   If buf is Z_NULL, this function returns the required initial value for the
   crc. Pre- and post-conditioning (one's complement) is performed within this
   function so it shouldn't be done by the application.

   Usage example:

     uLong crc = crc32(0L, Z_NULL, 0);

     while (read_buffer(buffer, length) != EOF) {
       crc = crc32(crc, buffer, length);
     }
     if (crc != original_crc) error();
*/

ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf,
                                  z_size_t len));
ZEXTERN uLong ZEXPORT crc32_z(uLong crc, const Bytef *buf,
                              z_size_t len);
/*
     Same as crc32(), but with a size_t length.
*/

/*
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2);

     Combine two CRC-32 check values into one.  For two sequences of bytes,
   seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
   calculated for each, crc1 and crc2.  crc32_combine() returns the CRC-32
   check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
   len2. len2 must be non-negative.
*/
   len2.

/*
ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2);

     Return the operator corresponding to length len2, to be used with
   crc32_combine_op(). len2 must be non-negative.
*/

ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op);
/*
     Give the same result as crc32_combine(), using op in place of len2. op is
   is generated from len2 by crc32_combine_gen(). This will be faster than
   crc32_combine() if the generated op is used more than once.
*/


                        /* various hacks, don't look :) */

/* deflateInit and inflateInit are macros to allow checking the zlib version
 * and the compiler's view of z_stream:
 */
ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
                                     const char *version, int stream_size));
ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
                                     const char *version, int stream_size));
ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
                                      int windowBits, int memLevel,
                                      int strategy, const char *version,
                                      int stream_size));
ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
                                      const char *version, int stream_size));
ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
                                         unsigned char FAR *window,
                                         const char *version,
                                         int stream_size));
ZEXTERN int ZEXPORT deflateInit_(z_streamp strm, int level,
                                 const char *version, int stream_size);
ZEXTERN int ZEXPORT inflateInit_(z_streamp strm,
                                 const char *version, int stream_size);
ZEXTERN int ZEXPORT deflateInit2_(z_streamp strm, int  level, int  method,
                                  int windowBits, int memLevel,
                                  int strategy, const char *version,
                                  int stream_size);
ZEXTERN int ZEXPORT inflateInit2_(z_streamp strm, int  windowBits,
                                  const char *version, int stream_size);
ZEXTERN int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits,
                                     unsigned char FAR *window,
                                     const char *version,
                                     int stream_size);
#ifdef Z_PREFIX_SET
#  define z_deflateInit(strm, level) \
          deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
#  define z_inflateInit(strm) \
          inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
#  define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
          deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
1815
1816
1817
1818
1819
1820
1821
1822

1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844







1845
1846
1847
1848
1849
1850
1851
1852
1853
1854

1855
1856
1857
1858
1859
1860
1861

1862
1863
1864
1865
1866
1867
1868
1869







1870
1871
1872
1873
1874
1875
1876
1877







1878
1879
1880
1881
1882
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
1835
1836
1837
1838
1839
1840
1841

1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858






1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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







-
+
















-
-
-
-
-
-
+
+
+
+
+
+
+










+







+


-
-
-
-
-
-
+
+
+
+
+
+
+


-
-
-
-
-
-
+
+
+
+
+
+
+




-
-
+
+
+




-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+



-
-
-
+
+
+








 * only be used by the gzgetc() macro.  You have been warned.
 */
struct gzFile_s {
    unsigned have;
    unsigned char *next;
    z_off64_t pos;
};
ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */
ZEXTERN int ZEXPORT gzgetc_(gzFile file);       /* backward compatibility */
#ifdef Z_PREFIX_SET
#  undef z_gzgetc
#  define z_gzgetc(g) \
          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))
#else
#  define gzgetc(g) \
          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))
#endif

/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
 * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
 * both are true, the application gets the *64 functions, and the regular
 * functions are changed to 64 bits) -- in case these are set on systems
 * without large file support, _LFS64_LARGEFILE must also be true
 */
#ifdef Z_LARGE64
   ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
   ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
   ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
   ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
   ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
   ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
   ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *);
   ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int);
   ZEXTERN z_off64_t ZEXPORT gztell64(gzFile);
   ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile);
   ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t);
   ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t);
   ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t);
#endif

#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
#  ifdef Z_PREFIX_SET
#    define z_gzopen z_gzopen64
#    define z_gzseek z_gzseek64
#    define z_gztell z_gztell64
#    define z_gzoffset z_gzoffset64
#    define z_adler32_combine z_adler32_combine64
#    define z_crc32_combine z_crc32_combine64
#    define z_crc32_combine_gen z_crc32_combine_gen64
#  else
#    define gzopen gzopen64
#    define gzseek gzseek64
#    define gztell gztell64
#    define gzoffset gzoffset64
#    define adler32_combine adler32_combine64
#    define crc32_combine crc32_combine64
#    define crc32_combine_gen crc32_combine_gen64
#  endif
#  ifndef Z_LARGE64
     ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
     ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
     ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
     ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
     ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *);
     ZEXTERN z_off_t ZEXPORT gzseek64(gzFile, z_off_t, int);
     ZEXTERN z_off_t ZEXPORT gztell64(gzFile);
     ZEXTERN z_off_t ZEXPORT gzoffset64(gzFile);
     ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t);
     ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t);
     ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t);
#  endif
#else
   ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
   ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));
   ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));
   ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
   ZEXTERN gzFile ZEXPORT gzopen(const char *, const char *);
   ZEXTERN z_off_t ZEXPORT gzseek(gzFile, z_off_t, int);
   ZEXTERN z_off_t ZEXPORT gztell(gzFile);
   ZEXTERN z_off_t ZEXPORT gzoffset(gzFile);
   ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t);
   ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t);
   ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t);
#endif

#else /* Z_SOLO */

   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
   ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t);
   ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t);
   ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t);

#endif /* !Z_SOLO */

/* undocumented functions */
ZEXTERN const char   * ZEXPORT zError           OF((int));
ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp));
ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table    OF((void));
ZEXTERN int            ZEXPORT inflateUndermine OF((z_streamp, int));
ZEXTERN int            ZEXPORT inflateValidate OF((z_streamp, int));
ZEXTERN unsigned long  ZEXPORT inflateCodesUsed OF ((z_streamp));
ZEXTERN int            ZEXPORT inflateResetKeep OF((z_streamp));
ZEXTERN int            ZEXPORT deflateResetKeep OF((z_streamp));
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO)
ZEXTERN gzFile         ZEXPORT gzopen_w OF((const wchar_t *path,
                                            const char *mode));
ZEXTERN const char   * ZEXPORT zError(int);
ZEXTERN int            ZEXPORT inflateSyncPoint(z_streamp);
ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table(void);
ZEXTERN int            ZEXPORT inflateUndermine(z_streamp, int);
ZEXTERN int            ZEXPORT inflateValidate(z_streamp, int);
ZEXTERN unsigned long  ZEXPORT inflateCodesUsed(z_streamp);
ZEXTERN int            ZEXPORT inflateResetKeep(z_streamp);
ZEXTERN int            ZEXPORT deflateResetKeep(z_streamp);
#if defined(_WIN32) && !defined(Z_SOLO)
ZEXTERN gzFile         ZEXPORT gzopen_w(const wchar_t *path,
                                        const char *mode);
#endif
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
#  ifndef Z_SOLO
ZEXTERN int            ZEXPORTVA gzvprintf Z_ARG((gzFile file,
                                                  const char *format,
                                                  va_list va));
ZEXTERN int            ZEXPORTVA gzvprintf(gzFile file,
                                           const char *format,
                                           va_list va);
#  endif
#endif

#ifdef __cplusplus
}
#endif

#endif /* ZLIB_H */

Changes to compat/zlib/zlib.map.

88
89
90
91
92
93
94






88
89
90
91
92
93
94
95
96
97
98
99
100







+
+
+
+
+
+
    uncompress2;
    gzfread;
    gzfwrite;
    deflateGetDictionary;
    adler32_z;
    crc32_z;
} ZLIB_1.2.7.1;

ZLIB_1.2.12 {
	crc32_combine_gen;
	crc32_combine_gen64;
	crc32_combine_op;
} ZLIB_1.2.9;

Deleted compat/zlib/zlib2ansi.

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
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
























































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#!/usr/bin/perl

# Transform K&R C function definitions into ANSI equivalent.
#
# Author: Paul Marquess
# Version: 1.0
# Date: 3 October 2006

# TODO
#
# Asumes no function pointer parameters. unless they are typedefed.
# Assumes no literal strings that look like function definitions
# Assumes functions start at the beginning of a line

use strict;
use warnings;

local $/;
$_ = <>;

my $sp = qr{ \s* (?: /\* .*? \*/ )? \s* }x; # assume no nested comments

my $d1    = qr{ $sp (?: [\w\*\s]+ $sp)* $sp \w+ $sp [\[\]\s]* $sp }x ;
my $decl  = qr{ $sp (?: \w+ $sp )+ $d1 }xo ;
my $dList = qr{ $sp $decl (?: $sp , $d1 )* $sp ; $sp }xo ;


while (s/^
            (                  # Start $1
                (              #   Start $2
                    .*?        #     Minimal eat content
                    ( ^ \w [\w\s\*]+ )    #     $3 -- function name
                    \s*        #     optional whitespace
                )              # $2 - Matched up to before parameter list

                \( \s*         # Literal "(" + optional whitespace
                ( [^\)]+ )     # $4 - one or more anythings except ")"
                \s* \)         # optional whitespace surrounding a Literal ")"

                ( (?: $dList )+ ) # $5

                $sp ^ {        # literal "{" at start of line
            )                  # Remember to $1
        //xsom
      )
{
    my $all = $1 ;
    my $prefix = $2;
    my $param_list = $4 ;
    my $params = $5;

    StripComments($params);
    StripComments($param_list);
    $param_list =~ s/^\s+//;
    $param_list =~ s/\s+$//;

    my $i = 0 ;
    my %pList = map { $_ => $i++ }
                split /\s*,\s*/, $param_list;
    my $pMatch = '(\b' . join('|', keys %pList) . '\b)\W*$' ;

    my @params = split /\s*;\s*/, $params;
    my @outParams = ();
    foreach my $p (@params)
    {
        if ($p =~ /,/)
        {
            my @bits = split /\s*,\s*/, $p;
            my $first = shift @bits;
            $first =~ s/^\s*//;
            push @outParams, $first;
            $first =~ /^(\w+\s*)/;
            my $type = $1 ;
            push @outParams, map { $type . $_ } @bits;
        }
        else
        {
            $p =~ s/^\s+//;
            push @outParams, $p;
        }
    }


    my %tmp = map { /$pMatch/;  $_ => $pList{$1}  }
              @outParams ;

    @outParams = map  { "    $_" }
                 sort { $tmp{$a} <=> $tmp{$b} }
                 @outParams ;

    print $prefix ;
    print "(\n" . join(",\n", @outParams) . ")\n";
    print "{" ;

}

# Output any trailing code.
print ;
exit 0;


sub StripComments
{

  no warnings;

  # Strip C & C++ coments
  # From the perlfaq
  $_[0] =~

    s{
       /\*         ##  Start of /* ... */ comment
       [^*]*\*+    ##  Non-* followed by 1-or-more *'s
       (
         [^/*][^*]*\*+
       )*          ##  0-or-more things which don't start with /
                   ##    but do end with '*'
       /           ##  End of /* ... */ comment

     |         ##     OR  C++ Comment
       //          ## Start of C++ comment //
       [^\n]*      ## followed by 0-or-more non end of line characters

     |         ##     OR  various things which aren't comments:

       (
         "           ##  Start of " ... " string
         (
           \\.           ##  Escaped char
         |               ##    OR
           [^"\\]        ##  Non "\
         )*
         "           ##  End of " ... " string

       |         ##     OR

         '           ##  Start of ' ... ' string
         (
           \\.           ##  Escaped char
         |               ##    OR
           [^'\\]        ##  Non '\
         )*
         '           ##  End of ' ... ' string

       |         ##     OR

         .           ##  Anything other char
         [^/"'\\]*   ##  Chars which doesn't start a comment, string or escape
       )
     }{$2}gxs;

}

Changes to compat/zlib/zutil.c.

20
21
22
23
24
25
26
27

28
29
30
31
32

33
34
35
36
37
38
39
40
20
21
22
23
24
25
26

27

28
29
30

31

32
33
34
35
36
37
38







-
+
-



-
+
-







    (z_const char *)"insufficient memory", /* Z_MEM_ERROR     (-4) */
    (z_const char *)"buffer error",        /* Z_BUF_ERROR     (-5) */
    (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */
    (z_const char *)""
};


const char * ZEXPORT zlibVersion()
const char * ZEXPORT zlibVersion(void) {
{
    return ZLIB_VERSION;
}

uLong ZEXPORT zlibCompileFlags()
uLong ZEXPORT zlibCompileFlags(void) {
{
    uLong flags;

    flags = 0;
    switch ((int)(sizeof(uInt))) {
    case 2:     break;
    case 4:     flags += 1;     break;
    case 8:     flags += 2;     break;
57
58
59
60
61
62
63

64
65
66

67
68
69
70
71
72
73
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73







+



+







    case 4:     flags += 1 << 6;        break;
    case 8:     flags += 2 << 6;        break;
    default:    flags += 3 << 6;
    }
#ifdef ZLIB_DEBUG
    flags += 1 << 8;
#endif
    /*
#if defined(ASMV) || defined(ASMINF)
    flags += 1 << 9;
#endif
     */
#ifdef ZLIB_WINAPI
    flags += 1 << 10;
#endif
#ifdef BUILDFIXED
    flags += 1 << 12;
#endif
#ifdef DYNAMIC_CRC_TABLE
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
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







-
+
-
-








-
+
-
-



-
-
+
+








-
+
-
-
-
-






-
+
-
-
-
-








-
+
-
-
-







#ifdef ZLIB_DEBUG
#include <stdlib.h>
#  ifndef verbose
#    define verbose 0
#  endif
int ZLIB_INTERNAL z_verbose = verbose;

void ZLIB_INTERNAL z_error (m)
void ZLIB_INTERNAL z_error(char *m) {
    char *m;
{
    fprintf(stderr, "%s\n", m);
    exit(1);
}
#endif

/* exported to allow conversion of error code to string for compress() and
 * uncompress()
 */
const char * ZEXPORT zError(err)
const char * ZEXPORT zError(int err) {
    int err;
{
    return ERR_MSG(err);
}

#if defined(_WIN32_WCE)
    /* The Microsoft C Run-Time Library for Windows CE doesn't have
#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
    /* The older Microsoft C Run-Time Library for Windows CE doesn't have
     * errno.  We define it as a global variable to simplify porting.
     * Its value is always 0 and should not be used.
     */
    int errno = 0;
#endif

#ifndef HAVE_MEMCPY

void ZLIB_INTERNAL zmemcpy(dest, source, len)
void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len) {
    Bytef* dest;
    const Bytef* source;
    uInt  len;
{
    if (len == 0) return;
    do {
        *dest++ = *source++; /* ??? to be unrolled */
    } while (--len != 0);
}

int ZLIB_INTERNAL zmemcmp(s1, s2, len)
int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len) {
    const Bytef* s1;
    const Bytef* s2;
    uInt  len;
{
    uInt j;

    for (j = 0; j < len; j++) {
        if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
    }
    return 0;
}

void ZLIB_INTERNAL zmemzero(dest, len)
void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len) {
    Bytef* dest;
    uInt  len;
{
    if (len == 0) return;
    do {
        *dest++ = 0;  /* ??? to be unrolled */
    } while (--len != 0);
}
#endif

210
211
212
213
214
215
216
217

218
219
220
221
222
223
224
225
195
196
197
198
199
200
201

202

203
204
205
206
207
208
209







-
+
-







/* This table is used to remember the original form of pointers
 * to large buffers (64K). Such pointers are normalized with a zero offset.
 * Since MSDOS is not a preemptive multitasking OS, this table is not
 * protected from concurrent access. This hack doesn't work anyway on
 * a protected system like OS/2. Use Microsoft C instead.
 */

voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) {
{
    voidpf buf;
    ulg bsize = (ulg)items*size;

    (void)opaque;

    /* If we allocate less than 65520 bytes, we assume that farmalloc
     * will return a usable pointer which doesn't have to be normalized.
236
237
238
239
240
241
242
243

244
245
246
247
248
249
250
251
220
221
222
223
224
225
226

227

228
229
230
231
232
233
234







-
+
-







    /* Normalize the pointer to seg:0 */
    *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
    *(ush*)&buf = 0;
    table[next_ptr++].new_ptr = buf;
    return buf;
}

void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
{
    int n;

    (void)opaque;

    if (*(ush*)&ptr != 0) { /* object < 64K */
        farfree(ptr);
        return;
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
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







-
+
-




-
+
-












-
-
-
+
+
+


-
+
-
-
-
-





-
+
-
-
-







#  define MY_ZCALLOC

#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
#  define _halloc  halloc
#  define _hfree   hfree
#endif

voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size)
voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size) {
{
    (void)opaque;
    return _halloc((long)items, size);
}

void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
{
    (void)opaque;
    _hfree(ptr);
}

#endif /* M_I86 */

#endif /* SYS16BIT */


#ifndef MY_ZCALLOC /* Any system without a special alloc function */

#ifndef STDC
extern voidp  malloc OF((uInt size));
extern voidp  calloc OF((uInt items, uInt size));
extern void   free   OF((voidpf ptr));
extern voidp malloc(uInt size);
extern voidp calloc(uInt items, uInt size);
extern void free(voidpf ptr);
#endif

voidpf ZLIB_INTERNAL zcalloc (opaque, items, size)
voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) {
    voidpf opaque;
    unsigned items;
    unsigned size;
{
    (void)opaque;
    return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
                              (voidpf)calloc(items, size);
}

void ZLIB_INTERNAL zcfree (opaque, ptr)
void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
    voidpf opaque;
    voidpf ptr;
{
    (void)opaque;
    free(ptr);
}

#endif /* MY_ZCALLOC */

#endif /* !Z_SOLO */

Changes to compat/zlib/zutil.h.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/* zutil.h -- internal interface and configuration of the compression library
 * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
 * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/* WARNING: this file should *not* be used by applications. It is
   part of the implementation of the compression library and is
   subject to change. Applications should only use zlib.h.
 */
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
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







-
-
-
-












+
+
+
+
+
+
+
+
+
+
+




-
+







#  if !(defined(_WIN32_WCE) && defined(_MSC_VER))
#    include <stddef.h>
#  endif
#  include <string.h>
#  include <stdlib.h>
#endif

#ifdef Z_SOLO
   typedef long ptrdiff_t;  /* guess -- will be caught if guess is wrong */
#endif

#ifndef local
#  define local static
#endif
/* since "static" is used to mean two completely different things in C, we
   define "local" for the non-static meaning of "static", for readability
   (compile with -Dlocal if your debugger can't find static symbols) */

typedef unsigned char  uch;
typedef uch FAR uchf;
typedef unsigned short ush;
typedef ush FAR ushf;
typedef unsigned long  ulg;

#if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC)
#  include <limits.h>
#  if (ULONG_MAX == 0xffffffffffffffff)
#    define Z_U8 unsigned long
#  elif (ULLONG_MAX == 0xffffffffffffffff)
#    define Z_U8 unsigned long long
#  elif (UINT_MAX == 0xffffffffffffffff)
#    define Z_U8 unsigned
#  endif
#endif

extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
/* (size given to avoid silly warnings with Visual C++) */

#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
#define ERR_MSG(err) z_errmsg[(err) < -6 || (err) > 2 ? 9 : 2 - (err)]

#define ERR_RETURN(strm,err) \
  return (strm->msg = ERR_MSG(err), (err))
/* To be used only when the state is known to be valid */

        /* common constants */

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
133
134
135
136
137
138
139

140
141









142
143
144
145
146
147
148







-
+

-
-
-
-
-
-
-
-
-







#ifdef OS2
#  define OS_CODE  6
#  if defined(M_I86) && !defined(Z_SOLO)
#    include <malloc.h>
#  endif
#endif

#if defined(MACOS) || defined(TARGET_OS_MAC)
#if defined(MACOS)
#  define OS_CODE  7
#  ifndef Z_SOLO
#    if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
#      include <unix.h> /* for fdopen */
#    else
#      ifndef fdopen
#        define fdopen(fd,mode) NULL /* No fdopen() */
#      endif
#    endif
#  endif
#endif

#ifdef __acorn
#  define OS_CODE 13
#endif

#if defined(WIN32) && !defined(__CYGWIN__)
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-









-
-
+
+
+







#  define OS_CODE 18
#endif

#ifdef __APPLE__
#  define OS_CODE 19
#endif

#if defined(_BEOS_) || defined(RISCOS)
#  define fdopen(fd,mode) NULL /* No fdopen() */
#endif

#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
#  if defined(_WIN32_WCE)
#    define fdopen(fd,mode) NULL /* No fdopen() */
#    ifndef _PTRDIFF_T_DEFINED
       typedef int ptrdiff_t;
#      define _PTRDIFF_T_DEFINED
#    endif
#  else
#    define fdopen(fd,type)  _fdopen(fd,type)
#  endif
#endif

#if defined(__BORLANDC__) && !defined(MSDOS)
  #pragma warn -8004
  #pragma warn -8008
  #pragma warn -8066
#endif

/* provide prototypes for these when building zlib without LFS */
#if !defined(_WIN32) && \
    (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
    ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
    ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
    ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t);
    ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t);
    ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t);
#endif

        /* common defaults */

#ifndef OS_CODE
#  define OS_CODE  3     /* assume Unix */
#endif
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
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







-
-
-
+
+
+






-
+
















-
-
-
+
+
+












#    define zmemzero(dest, len) _fmemset(dest, 0, len)
#  else
#    define zmemcpy memcpy
#    define zmemcmp memcmp
#    define zmemzero(dest, len) memset(dest, 0, len)
#  endif
#else
   void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
   int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
   void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len));
   void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len);
   int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len);
   void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len);
#endif

/* Diagnostic functions */
#ifdef ZLIB_DEBUG
#  include <stdio.h>
   extern int ZLIB_INTERNAL z_verbose;
   extern void ZLIB_INTERNAL z_error OF((char *m));
   extern void ZLIB_INTERNAL z_error(char *m);
#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
#  define Trace(x) {if (z_verbose>=0) fprintf x ;}
#  define Tracev(x) {if (z_verbose>0) fprintf x ;}
#  define Tracevv(x) {if (z_verbose>1) fprintf x ;}
#  define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
#  define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
#else
#  define Assert(cond,msg)
#  define Trace(x)
#  define Tracev(x)
#  define Tracevv(x)
#  define Tracec(c,x)
#  define Tracecv(c,x)
#endif

#ifndef Z_SOLO
   voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
                                    unsigned size));
   void ZLIB_INTERNAL zcfree  OF((voidpf opaque, voidpf ptr));
   voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items,
                                unsigned size);
   void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr);
#endif

#define ZALLOC(strm, items, size) \
           (*((strm)->zalloc))((strm)->opaque, (items), (size))
#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}

/* Reverse the bytes in a 32-bit value */
#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
                    (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))

#endif /* ZUTIL_H */

Changes to doc/Access.3.

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
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







+


-
+











-
+







\fB#include <tcl.h>\fR
.sp
int
\fBTcl_Access\fR(\fIpath\fR, \fImode\fR)
.sp
int
\fBTcl_Stat\fR(\fIpath\fR, \fIstatPtr\fR)
.fi
.SH ARGUMENTS
.AS "struct stat" *statPtr out
.AP char *path in
.AP "const char" *path in
Native name of the file to check the attributes of.
.AP int mode in
Mask consisting of one or more of \fBR_OK\fR, \fBW_OK\fR, \fBX_OK\fR and
\fBF_OK\fR. \fBR_OK\fR, \fBW_OK\fR and \fBX_OK\fR request checking whether the
file exists and has read, write and execute permissions, respectively.
\fBF_OK\fR just requests a check for the existence of the file.
.AP "struct stat" *statPtr out
The structure that contains the result.
.BE
.SH DESCRIPTION
.PP
As of Tcl 8.4, the object-based APIs \fBTcl_FSAccess\fR and \fBTcl_FSStat\fR
The object-based APIs \fBTcl_FSAccess\fR and \fBTcl_FSStat\fR
should be used in preference to \fBTcl_Access\fR and \fBTcl_Stat\fR, wherever
possible. Those functions also support Tcl's virtual filesystem layer, which
these do not.
.SS "OBSOLETE FUNCTIONS"
.PP
There are two reasons for calling \fBTcl_Access\fR and \fBTcl_Stat\fR rather
than calling system level functions \fBaccess\fR and \fBstat\fR directly.

Changes to doc/AddErrInfo.3.

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
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







-
+














-
+

+







-

+








-
+










-
+


-
+


-
+

-
+
-
-
-



-
+
+

-
-
-
+
+
+
+
+







.so man.macros
.BS
.SH NAME
Tcl_GetReturnOptions, Tcl_SetReturnOptions, Tcl_AddErrorInfo, Tcl_AppendObjToErrorInfo, Tcl_AddObjErrorInfo, Tcl_SetObjErrorCode, Tcl_SetErrorCode, Tcl_SetErrorLine, Tcl_GetErrorLine, Tcl_PosixError, Tcl_LogCommandInfo \- retrieve or record information about errors and other return options
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp

Tcl_Obj *
\fBTcl_GetReturnOptions\fR(\fIinterp, code\fR)
.sp
int
\fBTcl_SetReturnOptions\fR(\fIinterp, options\fR)
.sp
\fBTcl_AddErrorInfo\fR(\fIinterp, message\fR)
.sp
\fBTcl_AppendObjToErrorInfo\fR(\fIinterp, objPtr\fR)
.sp
\fBTcl_AddObjErrorInfo\fR(\fIinterp, message, length\fR)
.sp
\fBTcl_SetObjErrorCode\fR(\fIinterp, errorObjPtr\fR)
.sp
\fBTcl_SetErrorCode\fR(\fIinterp, element, element, ... \fB(char *) NULL\fR)
\fBTcl_SetErrorCode\fR(\fIinterp, element, element, ... \fB(char *)NULL\fR)
.sp
int
\fBTcl_GetErrorLine\fR(\fIinterp\fR)
.sp
\fBTcl_SetErrorLine\fR(\fIinterp, lineNum\fR)
.sp
const char *
\fBTcl_PosixError\fR(\fIinterp\fR)
.sp
void
\fBTcl_LogCommandInfo\fR(\fIinterp, script, command, commandLength\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp commandLength
.AP Tcl_Interp *interp in
Interpreter in which to record information.
.AP int code
The code returned from script evaluation.
.AP Tcl_Obj *options
A dictionary of return options.
.AP char *message in
.AP "const char" *message in
For \fBTcl_AddErrorInfo\fR,
this is a conventional C string to append to the \fB\-errorinfo\fR return option.
For \fBTcl_AddObjErrorInfo\fR,
this points to the first byte of an array of \fIlength\fR bytes
containing a string to append to the \fB\-errorinfo\fR return option.
This byte array may contain embedded null bytes
unless \fIlength\fR is negative.
.AP Tcl_Obj *objPtr in
A message to be appended to the \fB\-errorinfo\fR return option
in the form of a Tcl_Obj value.
.AP size_t length in
.AP Tcl_Size length in
The number of bytes to copy from \fImessage\fR when
appending to the \fB\-errorinfo\fR return option.
If TCL_INDEX_NONE, all bytes up to the first null byte are used.
If negative, all bytes up to the first null byte are used.
.AP Tcl_Obj *errorObjPtr in
The \fB\-errorcode\fR return option will be set to this value.
.AP char *element in
.AP "const char" *element in
String to record as one element of the \fB\-errorcode\fR return option.
Last \fIelement\fR argument must be NULL.
Last \fIelement\fR argument must be (char *)NULL.
.AP va_list argList in
An argument list which must have been initialized using
\fBva_start\fR, and cleared using \fBva_end\fR.
.AP int lineNum
The line number of a script where an error occurred.
.AP "const char" *script in
Pointer to first character in script containing command (must be <= command)
Pointer to first character in script containing command
(must be <= \fIcommand\fR).
.AP "const char" *command in
Pointer to first character in command that generated the error
.AP int commandLength in
Number of bytes in command; -1 means use all bytes up to first null byte
Pointer to first character in the command that generated the error; must
point within the string given by \fIscript\fR.
.AP Tcl_Size commandLength in
Number of bytes in command; a negative value means use all bytes up to the
first null byte.
.BE
.SH DESCRIPTION
.PP
The \fBTcl_SetReturnOptions\fR and \fBTcl_GetReturnOptions\fR
routines expose the same capabilities as the \fBreturn\fR and
\fBcatch\fR commands, respectively, in the form of a C interface.
.PP
296
297
298
299
300
301
302
















303
304
305
306
307
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





If an error had occurred, the \fBTcl_ResetResult\fR call will
clear the error state to make it appear as if no error had
occurred after all.
The global variables \fBerrorInfo\fR and
\fBerrorCode\fR are not modified by \fBTcl_ResetResult\fR
so they continue to hold a record of information about the
most recent error seen in an interpreter.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
The result of \fBTcl_GetReturnOptions\fR will have at least one
reference to it from the Tcl interpreter. If not using it immediately,
you should use \fBTcl_IncrRefCount\fR to add your own reference.
.PP
The \fIoptions\fR argument to \fBTcl_SetReturnOptions\fR will have a
reference added by the Tcl interpreter; it may safely be called with a
zero-reference value.
.PP
\fBTcl_AppendObjToErrorInfo\fR only reads its \fIobjPtr\fR argument;
it does not modify its reference count at all.
.PP
The \fIerrorObjPtr\fR argument to \fBTcl_SetObjErrorCode\fR will have a
reference added by the Tcl interpreter; it may safely be called with a
zero-reference value.
.SH "SEE ALSO"
Tcl_DecrRefCount(3), Tcl_IncrRefCount(3), Tcl_Interp(3), Tcl_ResetResult(3),
Tcl_SetErrno(3), errorCode(n), errorInfo(n)
.SH KEYWORDS
error, value, value result, stack, trace, variable

Changes to doc/Alloc.3.

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



30
31
32

33
34

35


36
37
38
39
40
41
42
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
30
31
32
33

34
35

36
37
38
39
40
41
42
43
44
45
46






-
+



-
+




-
+


-










+
+
+


-
+

-
+

+
+







'\"
'\" Copyright (c) 1995-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_Alloc 3 7.5 Tcl "Tcl Library Procedures"
.TH Tcl_Alloc 3 9.0 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_Alloc, Tcl_Free, Tcl_Realloc, Tcl_AttemptAlloc, Tcl_AttemptRealloc \- allocate or free heap memory
Tcl_Alloc, Tcl_Free, Tcl_Realloc, Tcl_AttemptAlloc, Tcl_AttemptRealloc, Tcl_GetMemoryInfo \- allocate or free heap memory
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
char *
void *
\fBTcl_Alloc\fR(\fIsize\fR)
.sp
void
\fBTcl_Free\fR(\fIptr\fR)
.sp
void *
\fBTcl_Realloc\fR(\fIptr, size\fR)
.sp
void *
\fBTcl_AttemptAlloc\fR(\fIsize\fR)
.sp
void *
\fBTcl_AttemptRealloc\fR(\fIptr, size\fR)
.sp
\fBTcl_GetMemoryInfo\fR(\fIdsPtr\fR)
.fi
.SH ARGUMENTS
.AS char *size
.AP "unsigned int" size in
.AP "size_t" size in
Size in bytes of the memory block to allocate.
.AP char *ptr in
.AP void *ptr in
Pointer to memory block to free or realloc.
.AP Tcl_DString *dsPtr in
Initialized DString pointer.
.BE

.SH DESCRIPTION
.PP
These procedures provide a platform and compiler independent interface
for memory allocation.  Programs that need to transfer ownership of
memory blocks between Tcl and other modules should use these routines
64
65
66
67
68
69
70







71
72
73
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84







+
+
+
+
+
+
+



platforms, but not all, attempting to allocate a zero-sized block of
memory will also cause these functions to return NULL.
.PP
When a module or Tcl itself is compiled with \fBTCL_MEM_DEBUG\fR defined,
the procedures \fBTcl_Alloc\fR, \fBTcl_Free\fR, \fBTcl_Realloc\fR,
\fBTcl_AttemptAlloc\fR, and \fBTcl_AttempRealloc\fR are implemented
as macros, redefined to be special debugging versions of these procedures.
.PP
\fBTcl_GetMemoryInfo\fR appends a list-of-lists of memory stats to the
provided DString. This function cannot be used in stub-enabled extensions,
and it is only available if Tcl is compiled with the threaded memory allocator
When used in stub-enabled embedders, the stubs table must be first initialized
using one of \fBTcl_InitSubsystems\fR, \fBTcl_SetPanicProc\fR,
\fBTcl_FindExecutable\fR or \fBTclZipfs_AppHook\fR.

.SH KEYWORDS
alloc, allocation, free, malloc, memory, realloc, TCL_MEM_DEBUG

Changes to doc/AllowExc.3.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25







+







.SH NAME
Tcl_AllowExceptions \- allow all exceptions in next script evaluation
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_AllowExceptions\fR(\fIinterp\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Interpreter in which script will be evaluated.
.BE

.SH DESCRIPTION

Changes to doc/AppInit.3.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26







+







Tcl_AppInit \- perform application-specific initialization
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_AppInit\fR(\fIinterp\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Interpreter for the application.
.BE

.SH DESCRIPTION

Changes to doc/AssocData.3.

15
16
17
18
19
20
21

22
23
24
25
26
27
28
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29







+







.sp
void *
\fBTcl_GetAssocData\fR(\fIinterp, key, delProcPtr\fR)
.sp
\fBTcl_SetAssocData\fR(\fIinterp, key, delProc, clientData\fR)
.sp
\fBTcl_DeleteAssocData\fR(\fIinterp, key\fR)
.fi
.SH ARGUMENTS
.AS Tcl_InterpDeleteProc **delProcPtr
.AP Tcl_Interp *interp in
Interpreter in which to execute the specified command.
.AP "const char" *key in
Key for association with which to store data or from which to delete or
retrieve data.  Typically the module prefix for a package.

Changes to doc/Async.3.

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
30
31
32
33
34
35
36


37
38
39
40
41
42
43
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51











-
+







+


+
+
+



+




+








+
+







'\"
'\" Copyright (c) 1989-1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_AsyncCreate 3 7.0 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_AsyncCreate, Tcl_AsyncMark, Tcl_AsyncInvoke, Tcl_AsyncDelete, Tcl_AsyncReady \- handle asynchronous events
Tcl_AsyncCreate, Tcl_AsyncMark, Tcl_AsyncMarkFromSignal, Tcl_AsyncInvoke, Tcl_AsyncDelete, Tcl_AsyncReady \- handle asynchronous events
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_AsyncHandler
\fBTcl_AsyncCreate\fR(\fIproc, clientData\fR)
.sp
void
\fBTcl_AsyncMark\fR(\fIasync\fR)
.sp
int
\fBTcl_AsyncMarkFromSignal\fR(\fIasync\fR, \fIsigNumber\fR)
.sp
int
\fBTcl_AsyncInvoke\fR(\fIinterp, code\fR)
.sp
void
\fBTcl_AsyncDelete\fR(\fIasync\fR)
.sp
int
\fBTcl_AsyncReady\fR()
.fi
.SH ARGUMENTS
.AS Tcl_AsyncHandler clientData
.AP Tcl_AsyncProc *proc in
Procedure to invoke to handle an asynchronous event.
.AP void *clientData in
One-word value to pass to \fIproc\fR.
.AP Tcl_AsyncHandler async in
Token for asynchronous event handler.
.AP int sigNumber in
POSIX signal number, when used in a signal context.
.AP Tcl_Interp *interp in
Tcl interpreter in which command was being evaluated when handler was
invoked, or NULL if handler was invoked when there was no interpreter
active.
.AP int code in
Completion code from command that just completed in \fIinterp\fR,
or 0 if \fIinterp\fR is NULL.
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
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







-
-
-
-
+
+
+
+
+








-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+







allocation could have been in progress when the event occurred.
The only safe approach is to set a flag indicating that the event
occurred, then handle the event later when the world has returned
to a clean state, such as after the current Tcl command completes.
.PP
\fBTcl_AsyncCreate\fR, \fBTcl_AsyncDelete\fR, and \fBTcl_AsyncReady\fR
are thread sensitive.  They access and/or set a thread-specific data
structure in the event of a core built with \fI\-\-enable\-threads\fR.  The token
created by \fBTcl_AsyncCreate\fR contains the needed thread information it
was called from so that calling \fBTcl_AsyncMark\fR(\fItoken\fR) will only yield
the origin thread into the asynchronous handler.
structure in the event of a core built with \fI\-\-enable\-threads\fR.
The token created by \fBTcl_AsyncCreate\fR contains the needed thread
information it was called from so that calling \fBTcl_AsyncMarkFromSignal\fR
or \fBTcl_AsyncMark\fR with this token will only yield the origin
thread into the asynchronous handler.
.PP
\fBTcl_AsyncCreate\fR creates an asynchronous handler and returns
a token for it.
The asynchronous handler must be created before
any occurrences of the asynchronous event that it is intended
to handle (it is not safe to create a handler at the time of
an event).
When an asynchronous event occurs the code that detects the event
(such as a signal handler) should call \fBTcl_AsyncMark\fR with the
token for the handler.
\fBTcl_AsyncMark\fR will mark the handler as ready to execute, but it
will not invoke the handler immediately.
Tcl will call the \fIproc\fR associated with the handler later, when
the world is in a safe state, and \fIproc\fR can then carry out
the actions associated with the asynchronous event.
(such as a POSIX signal handler) should call \fBTcl_AsyncMarkFromSignal\fR
with the token for the handler and the POSIX signal number. The
return value of this function is true, when the handler will be
marked, false otherwise.
For non-signal contexts, \fBTcl_AsyncMark\fR serves the same purpose.
\fBTcl_AsyncMarkFromSignal\fR and \fBTcl_AsyncMark\fR will mark
the handler as ready to execute, but will not invoke the handler
immediately. Tcl will call the \fIproc\fR associated with the
handler later, when the world is in a safe state, and \fIproc\fR
can then carry out the actions associated with the asynchronous event.
\fIProc\fR should have arguments and result that match the
type \fBTcl_AsyncProc\fR:
.PP
.CS
typedef int \fBTcl_AsyncProc\fR(
        void *\fIclientData\fR,
        Tcl_Interp *\fIinterp\fR,

Changes to doc/BackgdErr.3.

13
14
15
16
17
18
19

20
21
22
23
24
25
26
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27







+







.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_BackgroundException\fR(\fIinterp, code\fR)
.sp
\fBTcl_BackgroundError\fR(\fIinterp\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Interpreter in which the exception occurred.
.AP int code in
The exceptional return code to be reported.
.BE

Changes to doc/BoolObj.3.

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
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
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
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











-
+





-
+

-
+



+
+
+
+

-
-
+
+








-
+


+
+
+
+
+
+
+






-
+




-
+




-
+


-
+




















+
+
+
+
+













+
+
+
+
+
+
+
+
+
+
+
+





'\"
'\" Copyright (c) 1996-1997 Sun Microsystems, Inc.
'\" Contributions from Don Porter, NIST, 2005.  (not subject to US copyright)
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_BooleanObj 3 8.5 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_NewBooleanObj, Tcl_SetBooleanObj, Tcl_GetBooleanFromObj \- store/retrieve boolean value in a Tcl_Obj
Tcl_NewBooleanObj, Tcl_SetBooleanObj, Tcl_GetBooleanFromObj, Tcl_GetBoolFromObj \- store/retrieve boolean value in a Tcl_Obj
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Obj *
\fBTcl_NewBooleanObj\fR(\fIboolValue\fR)
\fBTcl_NewBooleanObj\fR(\fIintValue\fR)
.sp
\fBTcl_SetBooleanObj\fR(\fIobjPtr, boolValue\fR)
\fBTcl_SetBooleanObj\fR(\fIobjPtr, intValue\fR)
.sp
int
\fBTcl_GetBooleanFromObj\fR(\fIinterp, objPtr, boolPtr\fR)
.sp
int
\fBTcl_GetBoolFromObj\fR(\fIinterp, objPtr, flags. charPtr\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp boolValue in/out
.AP int boolValue in
.AS Tcl_Interp intValue in/out
.AP int intValue in
Integer value to be stored as a boolean value in a Tcl_Obj.
.AP Tcl_Obj *objPtr in/out
Points to the Tcl_Obj in which to store, or from which to
retrieve a boolean value.
.AP Tcl_Interp *interp in/out
If a boolean value cannot be retrieved,
an error message is left in the interpreter's result value
unless \fIinterp\fR is NULL.
.AP int *boolPtr out
.AP "bool \&| int" *boolPtr out
Points to place where \fBTcl_GetBooleanFromObj\fR
stores the boolean value (0 or 1) obtained from \fIobjPtr\fR.
.AP char *charPtr out
Points to place where \fBTcl_GetBoolFromObj\fR
stores the boolean value (0 or 1) obtained from \fIobjPtr\fR.
.AP int flags in
0 or TCL_NULL_OK. If TCL_NULL_OK
is used, then the empty string or NULL will result in \fBTcl_GetBoolFromObj\fR
return TCL_OK, the *charPtr filled with the value \fB'\exFF'\fR;
.BE

.SH DESCRIPTION
.PP
These procedures are used to pass boolean values to and from
Tcl as Tcl_Obj's.  When storing a boolean value into a Tcl_Obj,
any non-zero integer value in \fIboolValue\fR is taken to be
any non-zero integer value in \fIintValue\fR is taken to be
the boolean value \fB1\fR, and the integer value \fB0\fR is
taken to be the boolean value \fB0\fR.
.PP
\fBTcl_NewBooleanObj\fR creates a new Tcl_Obj, stores the boolean
value \fIboolValue\fR in it, and returns a pointer to the new Tcl_Obj.
value \fIintValue\fR in it, and returns a pointer to the new Tcl_Obj.
The new Tcl_Obj has reference count of zero.
.PP
\fBTcl_SetBooleanObj\fR accepts \fIobjPtr\fR, a pointer to
an existing Tcl_Obj, and stores in the Tcl_Obj \fI*objPtr\fR
the boolean value \fIboolValue\fR.  This is a write operation
the boolean value \fIintValue\fR.  This is a write operation
on \fI*objPtr\fR, so \fIobjPtr\fR must be unshared.  Attempts to
write to a shared Tcl_Obj will panic.  A successful write
of \fIboolValue\fR into \fI*objPtr\fR implies the freeing of
of \fIintValue\fR into \fI*objPtr\fR implies the freeing of
any former value stored in \fI*objPtr\fR.
.PP
\fBTcl_GetBooleanFromObj\fR attempts to retrieve a boolean value
from the value stored in \fI*objPtr\fR.
If \fIobjPtr\fR holds a string value recognized by \fBTcl_GetBoolean\fR,
then the recognized boolean value is written at the address given
by \fIboolPtr\fR.
If \fIobjPtr\fR holds any value recognized as
a number by Tcl, then if that value is zero a 0 is written at
the address given by \fIboolPtr\fR and if that
value is non-zero a 1 is written at the address given by \fIboolPtr\fR.
In all cases where a value is written at the address given
by \fIboolPtr\fR, \fBTcl_GetBooleanFromObj\fR returns \fBTCL_OK\fR.
If the value of \fIobjPtr\fR does not meet any of the conditions
above, then \fBTCL_ERROR\fR is returned and an error message is
left in the interpreter's result unless \fIinterp\fR is NULL.
\fBTcl_GetBooleanFromObj\fR may also make changes to the internal
fields of \fI*objPtr\fR so that future calls to
\fBTcl_GetBooleanFromObj\fR on the same \fIobjPtr\fR can be
performed more efficiently.
.PP
\fBTcl_GetBoolFromObj\fR functions almost the same as
\fBTcl_GetBooleanFromObj\fR, but it has an additional parameter
\fBflags\fR, which can be used to specify whether the empty
string or NULL is accepted as valid.
.PP
Note that the routines \fBTcl_GetBooleanFromObj\fR and
\fBTcl_GetBoolean\fR are not functional equivalents.
The set of values for which \fBTcl_GetBooleanFromObj\fR
will return \fBTCL_OK\fR is strictly larger than
the set of values for which \fBTcl_GetBoolean\fR will do the same.
For example, the value
.QW 5
passed to \fBTcl_GetBooleanFromObj\fR
will lead to a \fBTCL_OK\fR return (and the boolean value 1),
while the same value passed to \fBTcl_GetBoolean\fR will lead to
a \fBTCL_ERROR\fR return.

.SH "REFERENCE COUNT MANAGEMENT"
.PP
\fBTcl_NewBooleanObj\fR always returns a zero-reference object, much
like \fBTcl_NewObj\fR.
.PP
\fBTcl_SetBooleanObj\fR does not modify the reference count of its
\fIobjPtr\fR argument, but does require that the object be unshared.
.PP
\fBTcl_GetBooleanFromObj\fR does not modify the reference count of its
\fIobjPtr\fR argument; it only reads. Note however that this function
may set the interpreter result; if that is the only place that
is holding a reference to the object, it will be deleted.
.SH "SEE ALSO"
Tcl_NewObj, Tcl_IsShared, Tcl_GetBoolean

.SH KEYWORDS
boolean, value

Changes to doc/ByteArrObj.3.

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
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

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

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






-
+



-
+





-
+

-
-
+

+

+
+
+
+
-
+


-
+
+

-
+


-
-
-
+
+
+

-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+

-


-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
-
-
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
-
-
+

+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+
'\"
'\" Copyright (c) 1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_ByteArrayObj 3 8.1 Tcl "Tcl Library Procedures"
.TH Tcl_ByteArrayObj 3 9.0 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_NewByteArrayObj, Tcl_SetByteArrayObj, Tcl_GetByteArrayFromObj, Tcl_SetByteArrayLength \- manipulate Tcl values as a arrays of bytes
Tcl_NewByteArrayObj, Tcl_SetByteArrayObj, Tcl_GetBytesFromObj, Tcl_GetByteArrayFromObj, Tcl_SetByteArrayLength \- manipulate a Tcl value as an array of bytes
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Obj *
\fBTcl_NewByteArrayObj\fR(\fIbytes, length\fR)
\fBTcl_NewByteArrayObj\fR(\fIbytes, numBytes\fR)
.sp
void
\fBTcl_SetByteArrayObj\fR(\fIobjPtr, bytes, length\fR)
\fBTcl_SetByteArrayObj\fR(\fIobjPtr, bytes, numBytes\fR)
.sp
.VS TIP568
unsigned char *
\fBTcl_GetBytesFromObj\fR(\fIinterp, objPtr, numBytesPtr\fR)
.VE TIP568
.sp
unsigned char *
\fBTcl_GetByteArrayFromObj\fR(\fIobjPtr, lengthPtr\fR)
\fBTcl_GetByteArrayFromObj\fR(\fIobjPtr, numBytesPtr\fR)
.sp
unsigned char *
\fBTcl_SetByteArrayLength\fR(\fIobjPtr, length\fR)
\fBTcl_SetByteArrayLength\fR(\fIobjPtr, numBytes\fR)
.fi
.SH ARGUMENTS
.AS "const unsigned char" *lengthPtr in/out
.AS "const unsigned char" *numBytesPtr in/out
.AP "const unsigned char" *bytes in
The array of bytes used to initialize or set a byte-array value. May be NULL
even if \fIlength\fR is non-zero.
.AP size_t length in
The length of the array of bytes.
even if \fInumBytes\fR is non-zero.
.AP Tcl_Size numBytes in
The number of bytes in the array.
.AP Tcl_Obj *objPtr in/out
For \fBTcl_SetByteArrayObj\fR, this points to the value to be converted to
byte-array type.  For \fBTcl_GetByteArrayFromObj\fR and
\fBTcl_SetByteArrayLength\fR, this points to the value from which to get
For \fBTcl_SetByteArrayObj\fR, this points to an unshared value to be
overwritten by a byte-array value.  For \fBTcl_GetBytesFromObj\fR,
\fBTcl_GetByteArrayFromObj\fR and \fBTcl_SetByteArrayLength\fR, this points
to the value from which to extract an array of bytes.
the byte-array value; if \fIobjPtr\fR does not already point to a byte-array
value, it will be converted to one.
.AP int *lengthPtr out
If non-NULL, filled with the length of the array of bytes in the value.
.AP Tcl_Interp *interp in
Interpreter to use for error reporting.
.AP "Tcl_Size \&| int" *numBytesPtr out
Points to space where the number of bytes in the array may be written.
May be (Tcl_Size *)NULL when not used. If it points to a variable which
type is not \fBTcl_Size\fR, a compiler warning will be generated.
If your extensions is compiled with -DTCL_8_API, this function will return
NULL for byte arrays larger than INT_MAX (which should
trigger proper error-handling), otherwise expect it to crash.
.BE

.SH DESCRIPTION
.PP
These procedures are used to create, modify, and read Tcl byte-array values
from C code.  Byte-array values are typically used to hold the
results of binary IO operations or data structures created with the
\fBbinary\fR command.  In Tcl, an array of bytes is not equivalent to a
string.  Conceptually, a string is an array of Unicode characters, while a
byte-array is an array of 8-bit quantities with no implicit meaning.
Accessor functions are provided to get the string representation of a
byte-array or to convert an arbitrary value to a byte-array.  Obtaining the
These routines are used to create, modify, store, transfer, and retrieve
arbitrary binary data in Tcl values.  Specifically, data that can be
represented as a sequence of arbitrary byte values is supported.
This includes data read from binary channels, values created by the
\fBbinary\fR command, encrypted data, or other information representable as
a finite byte sequence.
.PP
A byte is an 8-bit quantity with no inherent meaning.  When the 8 bits are
interpreted as an integer value, the range of possible values is (0-255).
The C type best suited to store a byte is the \fBunsigned char\fR.
An \fBunsigned char\fR array of size \fIN\fR stores an arbitrary binary
value of size \fIN\fR bytes.  We call this representation a byte-array.
Here we document the routines that allow us to operate on Tcl values as
byte-arrays.
.PP
All Tcl values must correspond to a string representation.
When a byte-array value must be processed as a string, the sequence
of \fIN\fR bytes is transformed into the corresponding sequence
of \fIN\fR characters, where each byte value transforms to the same
character codepoint value in the range (U+0000 - U+00FF).  Obtaining the
string representation of a byte-array value (by calling
\fBTcl_GetStringFromObj\fR) produces a properly formed UTF-8 sequence with a
\fBTcl_GetStringFromObj\fR) produces this string in Tcl's usual
one-to-one mapping between the bytes in the internal representation and the
UTF-8 characters in the string representation.
Modified UTF-8 encoding.
.PP
\fBTcl_NewByteArrayObj\fR and \fBTcl_SetByteArrayObj\fR will
create a new value of byte-array type or modify an existing value to have a
byte-array type.  Both of these procedures set the value's type to be
byte-array and set the value's internal representation to a copy of the
array of bytes given by \fIbytes\fR. \fBTcl_NewByteArrayObj\fR returns a
pointer to a newly allocated value with a reference count of zero.
\fBTcl_SetByteArrayObj\fR invalidates any old string representation and, if
the value is not already a byte-array value, frees any old internal
representation. If \fIbytes\fR is NULL then the new byte array contains
arbitrary values.
\fBTcl_NewByteArrayObj\fR and \fBTcl_SetByteArrayObj\fR
create a new value or overwrite an existing unshared value, respectively,
to hold a byte-array value of \fInumBytes\fR bytes.  When a caller
passes a non-NULL value of \fIbytes\fR, it must point to memory from
which \fInumBytes\fR bytes can be read.  These routines
allocate \fInumBytes\fR bytes of memory, copy \fInumBytes\fR
bytes from \fIbytes\fR into it, and keep the result in the internal
representation of the new or overwritten value.
When the caller passes a NULL value of \fIbytes\fR, the data copying
step is skipped, and the bytes stored in the value are undefined.
A \fIbytes\fR value of NULL is useful only when the caller will arrange
to write known contents into the byte-array through a pointer retrieved
by a call to one of the routines explained below.  \fBTcl_NewByteArrayObj\fR
returns a pointer to the created value with a reference count of zero.
\fBTcl_SetByteArrayObj\fR overwrites and invalidates any old contents
of the unshared \fIobjPtr\fR as appropriate, and keeps its reference
count (0 or 1) unchanged.  The value produced by these routines has no
string representation.  Any memory allocation failure may cause a panic.
.PP
\fBTcl_GetBytesFromObj\fR performs the opposite function of
\fBTcl_SetByteArrayObj\fR, providing access to read a byte-array from
a Tcl value that was previously written into it.  When \fIobjPtr\fR
is a value previously produced by \fBTcl_NewByteArrayObj\fR or
\fBTcl_SetByteArrayObj\fR, then \fBTcl_GetBytesFromObj\fR returns
a pointer to the byte-array kept in the value's internal representation.
If the caller provides a non-NULL value for \fInumBytesPtr\fR, it must
point to memory where \fBTcl_GetBytesFromObj\fR can write the number
of bytes in the value's internal byte-array.  With both pieces of
information, the caller is able to retrieve any information about the
contents of that byte-array that it seeks.  When \fIobjPtr\fR does
not already contain an internal byte-array, \fBTcl_GetBytesFromObj\fR
will try to create one from the value's string representation.  Any
string value that does not include any character codepoints outside
the range (U+0000 - U+00FF) will successfully translate to a unique
byte-array value.  With the created byte-array, the routine returns
as before.  For any string representation which does contain
a forbidden character codepoint, the conversion fails, and
\fBTcl_GetBytesFromObj\fR returns NULL to signal that failure.  On
failure, nothing will be written to \fInumBytesPtr\fR, and if
the \fIinterp\fR argument is non-NULL, then error messages and
codes are left in it recording the error.
.PP
\fBTcl_GetByteArrayFromObj\fR performs exactly the same function as
\fBTcl_GetBytesFromObj\fR does when called with the \fIinterp\fR
argument passed the value NULL.  This is incompatible with the
\fBTcl_GetByteArrayFromObj\fR converts a Tcl value to byte-array type and
returns a pointer to the value's new internal representation as an array of
bytes.  The length of this array is stored in \fIlengthPtr\fR if
way \fBTcl_GetByteArrayFromObj\fR functioned in Tcl 8.
\fBTcl_GetBytesFromObj\fR is the more capable interface and should
usually be favored for use over \fBTcl_GetByteArrayFromObj\fR.
.PP
On success, both \fBTcl_GetBytesFromObj\fR and \fBTcl_GetByteArrayFromObj\fR
return a pointer into the internal representation of a \fBTcl_Obj\fR.
That pointer must not be freed by the caller, and should not be retained
for use beyond the known time the internal representation of the value
has not been disturbed.  The pointer may be used to overwrite the byte
\fIlengthPtr\fR is non-NULL.  The storage for the array of bytes is owned by
the value and should not be freed.  The contents of the array may be
contents of the internal representation, so long as the value is unshared
modified by the caller only if the value is not shared and the caller
invalidates the string representation.
and any string representation is invalidated.
.PP
On success, both \fBTcl_GetBytesFromObj\fR and \fBTcl_GetByteArrayFromObj\fR
write the number of bytes in the byte-array value of \fIobjPtr\fR
to the space pointed to by \fInumBytesPtr\fR.  This space may be of type
\fBTcl_Size\fR or of type \fBint\fR.  It is recommended that callers provide
a \fBTcl_Size\fR space for this purpose.  If the caller provides only
an \fBint\fR space and the number of bytes in the byte-array value of
\fIobjPtr\fR is greater than \fBINT_MAX\fR, the routine will fail due
to being unable to correctly report the byte-array size to the caller.
The ability to provide an \fBint\fR space is best considered a migration
aid for codebases constrained to continue operating with Tcl releases
older than 9.0.
.PP
\fBTcl_SetByteArrayLength\fR converts the Tcl value to byte-array type
and changes the length of the value's internal representation as an
array of bytes.  If \fIlength\fR is greater than the space currently
\fBTcl_SetByteArrayLength\fR enables a caller to change the size of a
byte-array in the internal representation of an unshared \fIobjPtr\fR to
become \fInumBytes\fR bytes.  This is most often useful after the
allocated for the array, the array is reallocated to the new length; the
newly allocated bytes at the end of the array have arbitrary values.  If
\fIlength\fR is less than the space currently allocated for the array,
bytes of the internal byte-array have been directly overwritten and it
has been discovered that the required size differs from the first
estimate used in the allocation. \fBTcl_SetByteArrayLength\fR returns
the length of array is reduced to the new length.  The return value is a
pointer to the value's new array of bytes.
a pointer to the resized byte-array.  Because resizing the byte-array
changes the internal representation, \fBTcl_SetByteArrayLength\fR
also invalidates any string representation in \fIobjPtr\fR.  If resizing
grows the byte-array, the new byte values are undefined.  If \fIobjPtr\fR
does not already possess an internal byte-array, one is produced in the
same way that \fBTcl_GetBytesFromObj\fR does, also returning NULL
when any characters of the value in \fIobjPtr\fR (up to
\fInumBytes\fR of them) are not valid bytes.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
\fBTcl_NewByteArrayObj\fR always returns a zero-reference object, much
like \fBTcl_NewObj\fR.
.PP
\fBTcl_SetByteArrayObj\fR and \fBTcl_SetByteArrayLength\fR do not modify the
reference count of their \fIobjPtr\fR arguments, but do require that the
object be unshared.
.PP
\fBTcl_GetBytesFromObj\fR and \fBTcl_GetByteArrayFromObj\fR do not modify
the reference count of \fIobjPtr\fR; they only read.

.SH "SEE ALSO"
Tcl_GetStringFromObj, Tcl_NewObj, Tcl_IncrRefCount, Tcl_DecrRefCount

.SH KEYWORDS
value, binary data, byte array, utf, unicode, internationalization
value, binary data, byte array, utf, unicode

Changes to doc/CallDel.3.

13
14
15
16
17
18
19

20
21
22
23
24
25
26
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27







+







.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_CallWhenDeleted\fR(\fIinterp\fR, \fIproc\fR, \fIclientData\fR)
.sp
\fBTcl_DontCallWhenDeleted\fR(\fIinterp\fR, \fIproc\fR, \fIclientData\fR)
.fi
.SH ARGUMENTS
.AS Tcl_InterpDeleteProc clientData
.AP Tcl_Interp *interp in
Interpreter with which to associated callback.
.AP Tcl_InterpDeleteProc *proc in
Procedure to call when \fIinterp\fR is deleted.
.AP void *clientData in
56
57
58
59
60
61
62
63


64
65
66
67
57
58
59
60
61
62
63

64
65
66
67
68
69







-
+
+




deleted.
If there is no deletion callback that matches \fIinterp\fR,
\fIproc\fR, and \fIclientData\fR then the call to
\fBTcl_DontCallWhenDeleted\fR has no effect.
.PP
Note that if the callback is being used to delete a resource that \fImust\fR
be released on exit, \fBTcl_CreateExitHandler\fR should be used to ensure that
a callback is received even if the application terminates without deleting the interpreter.
a callback is received even if the application terminates without deleting the
interpreter.
.SH "SEE ALSO"
Tcl_CreateExitHandler(3), Tcl_CreateThreadExitHandler(3)
.SH KEYWORDS
callback, cleanup, delete, interpreter

Changes to doc/Cancel.3.

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
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







+









-
+




















-
+



















+
+
+
+
+
+
+
+





.nf
\fB#include <tcl.h>\fR
int
\fBTcl_CancelEval\fR(\fIinterp, resultObjPtr, clientData, flags\fR)
.sp
int
\fBTcl_Canceled\fR(\fIinterp, flags\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Interpreter in which to cancel the script.
.AP Tcl_Obj *resultObjPtr in
Error message to use in the cancellation, or NULL to use a default message. If
not NULL, this object will have its reference count decremented before
\fBTcl_CancelEval\fR returns.
.AP int flags in
ORed combination of flag bits that specify additional options.
OR'ed combination of flag bits that specify additional options.
For \fBTcl_CancelEval\fR, only \fBTCL_CANCEL_UNWIND\fR is currently
supported.  For \fBTcl_Canceled\fR, only \fBTCL_LEAVE_ERR_MSG\fR and
\fBTCL_CANCEL_UNWIND\fR are currently supported.
.AP void *clientData in
Currently reserved for future use.
It should be set to NULL.
.BE
.SH DESCRIPTION
.PP
\fBTcl_CancelEval\fR cancels or unwinds the script in progress soon after
the next invocation of asynchronous handlers, causing \fBTCL_ERROR\fR to be
the return code for that script.  This function is thread-safe and may be
called from any thread in the process.
.PP
\fBTcl_Canceled\fR checks if the script in progress has been canceled and
returns \fBTCL_ERROR\fR if it has.  Otherwise, \fBTCL_OK\fR is returned.
Extensions can use this function to check to see if they should abort a long
running command.  This function is thread sensitive and may only be called
from the thread the interpreter was created in.
.SS "FLAG BITS"
Any ORed combination of the following values may be used for the
Any OR'ed combination of the following values may be used for the
\fIflags\fR argument to procedures such as \fBTcl_CancelEval\fR:
.TP 20
\fBTCL_CANCEL_UNWIND\fR
.
This flag is used by \fBTcl_CancelEval\fR and \fBTcl_Canceled\fR.
For \fBTcl_CancelEval\fR, if this flag is set, the script in progress
is canceled and the evaluation stack for the interpreter is unwound.
For \fBTcl_Canceled\fR, if this flag is set, the script in progress
is considered to be canceled only if the evaluation stack for the
interpreter is being unwound.
.TP 20
\fBTCL_LEAVE_ERR_MSG\fR
.
This flag is only used by \fBTcl_Canceled\fR; it is ignored by
other procedures.  If an error is returned and this bit is set in
\fIflags\fR, then an error message will be left in the interpreter's
result, where it can be retrieved with \fBTcl_GetObjResult\fR or
\fBTcl_GetStringResult\fR.  If this flag bit is not set then no error
message is left and the interpreter's result will not be modified.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
\fBTcl_CancelEval\fR always decrements the reference count of its
\fIresultObjPtr\fR argument (if that is non-NULL). It is expected to
be usually called with an object with zero reference count. If the
object is shared with some other location (including the Tcl
evaluation stack) it should have its reference count incremented
before calling this function.
.SH "SEE ALSO"
interp(n), Tcl_Eval(3),
TIP 285
.SH KEYWORDS
cancel, unwind

Changes to doc/ChnlStack.3.

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
30
31
32
33
34
35
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
30
31
32
33
34













-













-
+







'\"
'\" Copyright (c) 1999-2000 Ajuba Solutions.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
.TH Tcl_StackChannel 3 8.3 Tcl "Tcl Library Procedures"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
Tcl_StackChannel, Tcl_UnstackChannel, Tcl_GetStackedChannel, Tcl_GetTopChannel \- manipulate stacked I/O channels
.SH SYNOPSIS
.nf
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Channel
\fBTcl_StackChannel\fR(\fIinterp, typePtr, clientData, mask, channel\fR)
.sp
int
\fBTcl_UnstackChannel\fR(\fIinterp, channel\fR)
.sp
Tcl_Channel
\fBTcl_GetStackedChannel\fR(\fIchannel\fR)
.sp
Tcl_Channel
\fBTcl_GetTopChannel\fR(\fIchannel\fR)
.sp
.fi
.SH ARGUMENTS
.AS Tcl_ChannelType clientData
.AP Tcl_Interp *interp in
Interpreter for error reporting.
.AP "const Tcl_ChannelType" *typePtr in
The new channel I/O procedures to use for \fIchannel\fR.
.AP void *clientData in
84
85
86
87
88
89
90
91

92
93
94
83
84
85
86
87
88
89

90
91
92
93







-
+



\fBTcl_GetTopChannel\fR returns the top channel in the stack of
channels the supplied channel is part of.
.PP
\fBTcl_GetStackedChannel\fR returns the channel in the stack of
channels which is just below the supplied channel.

.SH "SEE ALSO"
Notifier(3), Tcl_CreateChannel(3), Tcl_OpenFileChannel(3), vwait(n).
Notifier(3), Tcl_CreateChannel(3), Tcl_OpenFileChannel(3), vwait(n)

.SH KEYWORDS
channel, compression

Changes to doc/Class.3.

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
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







+
+
+
+
+
+
+
+
+


















-
+



-
+







.sp
\fBTcl_ClassSetMetadata\fR(\fIclass, metaTypePtr, metadata\fR)
.sp
Tcl_ObjectMapMethodNameProc
\fBTcl_ObjectGetMethodNameMapper\fR(\fIobject\fR)
.sp
\fBTcl_ObjectSetMethodNameMapper\fR(\fIobject\fR, \fImethodNameMapper\fR)
.sp
.VS "TIP 605"
Tcl_Class
\fBTcl_GetClassOfObject\fR(\fIobject\fR)
.sp
Tcl_Obj *
\fBTcl_GetObjectClassName\fR(\fIinterp\fR, \fIobject\fR)
.VE "TIP 605"
.fi
.SH ARGUMENTS
.AS void *metadata in/out
.AP Tcl_Interp *interp in/out
Interpreter providing the context for looking up or creating an object, and
into whose result error messages will be written on failure.
.AP Tcl_Obj *objPtr in
The name of the object to look up.
.AP Tcl_Object object in
Reference to the object to operate upon.
.AP Tcl_Class class in
Reference to the class to operate upon.
.AP "const char" *name in
The name of the object to create, or NULL if a new unused name is to be
automatically selected.
.AP "const char" *nsName in
The name of the namespace to create for the object's private use, or NULL if a
new unused name is to be automatically selected. The namespace must not
already exist.
.AP int objc in
.AP Tcl_Size objc in
The number of elements in the \fIobjv\fR array.
.AP "Tcl_Obj *const" *objv in
The arguments to the command to create the instance of the class.
.AP int skip in
.AP Tcl_Size skip in
The number of arguments at the start of the argument array, \fIobjv\fR, that
are not arguments to any constructors. This allows the generation of correct
error messages even when complicated calling patterns are used (e.g., via the
\fBnext\fR command).
.AP Tcl_ObjectMetadataType *metaTypePtr in
The type of \fImetadata\fR being set with \fBTcl_ClassSetMetadata\fR or
retrieved with \fBTcl_ClassGetMetadata\fR.
110
111
112
113
114
115
116







117
118
119
120
121
122
123
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139







+
+
+
+
+
+
+







may be retrieved using the \fBTcl_GetObjectCommand\fR function, the name of
the object (and hence the name of the command) with \fBTcl_GetObjectName\fR,
and the namespace may be retrieved using the \fBTcl_GetObjectNamespace\fR
function. Note that the Tcl_Obj reference returned by \fBTcl_GetObjectName\fR
is a shared reference. You can also get whether the object has been marked for
deletion with \fBTcl_ObjectDeleted\fR (it returns true if deletion of the
object has begun); this can be useful during the processing of methods.
.VS "TIP 605"
The class of an object can be retrieved with \fBTcl_GetClassOfObject\fR, and
the name of the class of an object with \fBTcl_GetObjectClassName\fR; note
that these two \fImay\fR return NULL during deletion of an object (this is
transient, and only occurs when the object is a long way through being
deleted).
.VE "TIP 605"
.PP
Instances of classes are created using \fBTcl_NewObjectInstance\fR, which
creates an object from any class (and which is internally called by both
the \fBcreate\fR and \fBnew\fR methods of the \fBoo::class\fR class). It takes
parameters that optionally give the name of the object and namespace to
create, and which describe the arguments to pass to the class's constructor
(if any). The result of the function will be either a reference to the newly
237
238
239
240
241
242
243























244
245
246
247
248
249
250
251
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








currently undefined. The \fIobject\fR parameter says which object is being
processed. The \fIstartClsPtr\fR parameter points to a variable that contains
the first class to provide a definition in the method chain to process, or
NULL if the whole chain is to be processed (the argument itself is never
NULL); this variable may be updated by the callback. The \fImethodNameObj\fR
parameter gives an unshared object containing the name of the method being
invoked, as provided by the user; this object may be updated by the callback.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
The \fIobjPtr\fR argument to \fBTcl_GetObjectFromObj\fR will not have its
reference count manipulated, but this function may modify the interpreter
result (to report any error) so interpreter results should not be fed into
this without an additional reference being used.
.PP
The result of \fBTcl_GetObjectName\fR is a value that is owned by the object
that is regenerated when this function is first called after the object is
renamed.  If the value is to be retained at all, the caller should increment
the reference count.
.PP
The first \fIobjc\fR values in the \fIobjv\fR argument to
\fBTcl_NewObjectInstance\fR are the arguments to pass to the constructor. They
must have a reference count of at least 1, and may have their reference counts
changed during the running of the constructor. Constructors may modify the
interpreter result, which consequently means that interpreter results should
not be used as arguments without an additional reference being taken.
.PP
The \fImethodNameObj\fR argument to a Tcl_ObjectMapMethodNameProc
implementation will be a value with a reference count of at least 1 where at
least one reference is not held by the interpreter result. It is expected that
method name mappers will only read their \fImethodNameObj\fR arguments.
.SH "SEE ALSO"
Method(3), oo::class(n), oo::copy(n), oo::define(n), oo::object(n)
.SH KEYWORDS
class, constructor, object
.\" Local variables:
.\" mode: nroff
.\" fill-column: 78
.\" End:

Changes to doc/CmdCmplt.3.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26







+







Tcl_CommandComplete \- Check for unmatched braces in a Tcl command
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_CommandComplete\fR(\fIcmd\fR)
.fi
.SH ARGUMENTS
.AS "const char" *cmd
.AP "const char" *cmd in
Command string to test for completeness.
.BE

.SH DESCRIPTION

Changes to doc/Concat.3.

12
13
14
15
16
17
18

19
20
21

22
23
24
25
26
27
28
12
13
14
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29







+


-
+







Tcl_Concat \- concatenate a collection of strings
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
const char *
\fBTcl_Concat\fR(\fIargc, argv\fR)
.fi
.SH ARGUMENTS
.AS "const char *const" argv[]
.AP int argc in
.AP Tcl_Size argc in
Number of strings.
.AP "const char *const" argv[] in
Array of strings to concatenate.  Must have \fIargc\fR entries.
.BE

.SH DESCRIPTION
.PP

Changes to doc/CrtAlias.3.

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
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
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
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










-
+







-
-
-




















-
-
-
-









+




















-
+




-
+











-
-
-
-
-
+
+
+
+
+
-
-
+
-
-
+
-







'\"
'\" Copyright (c) 1995-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_CreateAlias 3 7.6 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_IsSafe, Tcl_MakeSafe, Tcl_CreateChild, Tcl_GetChild, Tcl_GetParent, Tcl_GetInterpPath, Tcl_CreateAlias, Tcl_CreateAliasObj, Tcl_GetAlias, Tcl_GetAliasObj, Tcl_ExposeCommand, Tcl_HideCommand \- manage multiple Tcl interpreters, aliases and hidden commands
Tcl_IsSafe, Tcl_CreateChild, Tcl_GetChild, Tcl_GetParent, Tcl_GetInterpPath, Tcl_CreateAlias, Tcl_CreateAliasObj, Tcl_GetAliasObj, Tcl_ExposeCommand, Tcl_HideCommand \- manage multiple Tcl interpreters, aliases and hidden commands
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_IsSafe\fR(\fIinterp\fR)
.sp
int
\fBTcl_MakeSafe\fR(\fIinterp\fR)
.sp
Tcl_Interp *
\fBTcl_CreateChild\fR(\fIinterp, name, isSafe\fR)
.sp
Tcl_Interp *
\fBTcl_GetChild\fR(\fIinterp, name\fR)
.sp
Tcl_Interp *
\fBTcl_GetParent\fR(\fIinterp\fR)
.sp
int
\fBTcl_GetInterpPath\fR(\fIinterp, childInterp\fR)
.sp
int
\fBTcl_CreateAlias\fR(\fIchildInterp, childCmd, targetInterp, targetCmd,
                argc, argv\fR)
.sp
int
\fBTcl_CreateAliasObj\fR(\fIchildInterp, childCmd, targetInterp, targetCmd,
                   objc, objv\fR)
.sp
int
\fBTcl_GetAlias\fR(\fIinterp, childCmd, targetInterpPtr, targetCmdPtr,
             argcPtr, argvPtr\fR)
.sp
int
\fBTcl_GetAliasObj\fR(\fIinterp, childCmd, targetInterpPtr, targetCmdPtr,
                objcPtr, objvPtr\fR)
.sp
int
\fBTcl_ExposeCommand\fR(\fIinterp, hiddenCmdName, cmdName\fR)
.sp
int
\fBTcl_HideCommand\fR(\fIinterp, cmdName, hiddenCmdName\fR)
.fi
.SH ARGUMENTS
.AS "const char *const" **targetInterpPtr out
.AP Tcl_Interp *interp in
Interpreter in which to execute the specified command.
.AP "const char" *name in
Name of child interpreter to create or manipulate.
.AP int isSafe in
If non-zero, a
.QW safe
child that is suitable for running untrusted code
is created, otherwise a trusted child is created.
.AP Tcl_Interp *childInterp in
Interpreter to use for creating the source command for an alias (see
below).
.AP "const char" *childCmd in
Name of source command for alias.
.AP Tcl_Interp *targetInterp in
Interpreter that contains the target command for an alias.
.AP "const char" *targetCmd in
Name of target command for alias in \fItargetInterp\fR.
.AP int argc in
.AP Tcl_Size argc in
Count of additional arguments to pass to the alias command.
.AP "const char *const" *argv in
Vector of strings, the additional arguments to pass to the alias command.
This storage is owned by the caller.
.AP int objc in
.AP Tcl_Size objc in
Count of additional value arguments to pass to the aliased command.
.AP Tcl_Obj **objv in
Vector of Tcl_Obj structures, the additional value arguments to pass to
the aliased command.
This storage is owned by the caller.
.AP Tcl_Interp **targetInterpPtr in
Pointer to location to store the address of the interpreter where a target
command is defined for an alias.
.AP "const char" **targetCmdPtr out
Pointer to location to store the address of the name of the target command
for an alias.
.AP int *argcPtr out
Pointer to location to store count of additional arguments to be passed to
the alias. The location is in storage owned by the caller.
.AP "const char" ***argvPtr out
Pointer to location to store a vector of strings, the additional arguments
.AP "Tcl_Size \&| int" *objcPtr out
Pointer to location to store count of additional value arguments to be
passed to the alias. The location is in storage owned by the caller.
If it points to a variable which type is not \fBTcl_Size\fR, a compiler
warning will be generated. If your extensions is compiled with -DTCL_8_API,
to pass to an alias. The location is in storage owned by the caller, the
vector of strings is owned by the called function.
this function will return TCL_ERROR for aliases with more than INT_MAX
.AP int *objcPtr out
Pointer to location to store count of additional value arguments to be
value arguments, otherwise expect it to crash
passed to the alias. The location is in storage owned by the caller.
.AP Tcl_Obj ***objvPtr out
Pointer to location to store a vector of Tcl_Obj structures, the additional
arguments to pass to an alias command. The location is in storage
owned by the caller, the vector of Tcl_Obj structures is owned by the
called function.
.AP "const char" *cmdName in
Name of an exposed command to hide or create.
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
125
126
127
128
129
130
131












132
133
134
135
136
137
138







-
-
-
-
-
-
-
-
-
-
-
-







If the creation of the new child interpreter failed, \fBNULL\fR is returned.
.PP
\fBTcl_IsSafe\fR returns \fB1\fR if \fIinterp\fR is
.QW safe
(was created with the \fBTCL_SAFE_INTERPRETER\fR flag specified),
\fB0\fR otherwise.
.PP
\fBTcl_MakeSafe\fR marks \fIinterp\fR as
.QW safe ,
so that future
calls to \fBTcl_IsSafe\fR will return 1.  It also removes all known
potentially-unsafe core functionality (both commands and variables)
from \fIinterp\fR.  However, it cannot know what parts of an extension
or application are safe and does not make any attempt to remove those
parts, so safety is not guaranteed after calling \fBTcl_MakeSafe\fR.
Callers will want to take care with their use of \fBTcl_MakeSafe\fR
to avoid false claims of safety.  For many situations, \fBTcl_CreateChild\fR
may be a better choice, since it creates interpreters in a known-safe state.
.PP
\fBTcl_GetChild\fR returns a pointer to a child interpreter of
\fIinterp\fR. The child interpreter is identified by \fIname\fR.
If no such child interpreter exists, \fBNULL\fR is returned.
.PP
\fBTcl_GetParent\fR returns a pointer to the parent interpreter of
\fIinterp\fR. If \fIinterp\fR has no parent (it is a
top-level interpreter) then \fBNULL\fR is returned.
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
157
158
159
160
161
162
163
164

165
166
167
168

169
170
171




172
173
174
175
176
177
178







+
-
+



-
+


-
-
-
-







\fItargetInterp\fR. Any two interpreters can be used, without any
restrictions on how they are related.
.PP
\fBTcl_CreateAliasObj\fR is similar to \fBTcl_CreateAlias\fR except
that it takes a vector of values to pass as additional arguments instead
of a vector of strings.
.PP
\fBTcl_GetAliasObj\fR returns information in the form of a pointer to
\fBTcl_GetAlias\fR returns information about an alias \fIaliasName\fR
a vector of Tcl_Obj structures about an alias \fIaliasName\fR
in \fIinterp\fR. Any of the result fields can be \fBNULL\fR, in
which case the corresponding datum is not returned. If a result field is
non\-\fBNULL\fR, the address indicated is set to the corresponding datum.
For example, if \fItargetNamePtr\fR is non\-\fBNULL\fR it is set to a
For example, if \fItargetCmdPtr\fR is non\-\fBNULL\fR it is set to a
pointer to the string containing the name of the target command.
.PP
\fBTcl_GetAliasObj\fR is similar to \fBTcl_GetAlias\fR except that it
returns a pointer to a vector of Tcl_Obj structures instead of a vector of
strings.
.PP
\fBTcl_ExposeCommand\fR moves the command named \fIhiddenCmdName\fR from
the set of hidden commands to the set of exposed commands, putting
it under the name
\fIcmdName\fR.
\fIHiddenCmdName\fR must be the name of an existing hidden
command, or the operation will return \fBTCL_ERROR\fR and
leave an error message as the result of \fIinterp\fR.
224
225
226
227
228
229
230








231
232

233
234
235
236
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215

216
217
218
219
220







+
+
+
+
+
+
+
+

-
+




message is left as the result of \fIinterp\fR.
If the operation succeeds, it returns \fBTCL_OK\fR.
After executing this command, attempts to use \fIcmdName\fR in
any script evaluation mechanism will fail.
.PP
For a description of the Tcl interface to multiple interpreters, see
\fIinterp(n)\fR.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
\fBTcl_CreateAliasObj\fR increments the reference counts of the values
in its \fIobjv\fR argument. (That reference lasts the same length of
time as the owning alias.)
.PP
\fBTcl_GetAliasObj\fR returns (via its \fIobjvPtr\fR argument) a
pointer to values that it holds a reference to.
.SH "SEE ALSO"
interp
interp(n)

.SH KEYWORDS
alias, command, exposed commands, hidden commands, interpreter, invoke,
parent, child

Changes to doc/CrtChannel.3.

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
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







+
+
+
+
+



















-


-


-







.sp
Tcl_ThreadId
\fBTcl_GetChannelThread\fR(\fIchannel\fR)
.sp
int
\fBTcl_GetChannelMode\fR(\fIchannel\fR)
.sp
.VS 8.7
int
\fBTcl_RemoveChannelMode\fR(\fIinterp, channel, mode\fR)
.VE 8.7
.sp
int
\fBTcl_GetChannelBufferSize\fR(\fIchannel\fR)
.sp
\fBTcl_SetChannelBufferSize\fR(\fIchannel, size\fR)
.sp
\fBTcl_NotifyChannel\fR(\fIchannel, mask\fR)
.sp
int
\fBTcl_BadChannelOption\fR(\fIinterp, optionName, optionList\fR)
.sp
int
\fBTcl_IsChannelShared\fR(\fIchannel\fR)
.sp
int
\fBTcl_IsChannelRegistered\fR(\fIinterp, channel\fR)
.sp
int
\fBTcl_IsChannelExisting\fR(\fIchannelName\fR)
.sp
void
\fBTcl_CutChannel\fR(\fIchannel\fR)
.sp
void
\fBTcl_SpliceChannel\fR(\fIchannel\fR)
.sp
void
\fBTcl_ClearChannelHandlers\fR(\fIchannel\fR)
.sp
int
\fBTcl_ChannelBuffered\fR(\fIchannel\fR)
.sp
const char *
\fBTcl_ChannelName\fR(\fItypePtr\fR)
106
107
108
109
110
111
112
113

114
115
116
117
118
119
120
108
109
110
111
112
113
114

115
116
117
118
119
120
121
122







-
+







\fBTcl_ChannelGetHandleProc\fR(\fItypePtr\fR)
.sp
Tcl_DriverFlushProc *
\fBTcl_ChannelFlushProc\fR(\fItypePtr\fR)
.sp
Tcl_DriverHandlerProc *
\fBTcl_ChannelHandlerProc\fR(\fItypePtr\fR)
.sp
.fi
.SH ARGUMENTS
.AS "const Tcl_ChannelType" *channelName
.AP "const Tcl_ChannelType" *typePtr in
Points to a structure containing the addresses of procedures that
can be called to perform I/O and other functions on the channel.
.AP "const char" *channelName in
The name of this channel, such as \fBfile3\fR; must not be in use
132
133
134
135
136
137
138
139

140
141
142
143
144
145
146
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148







-
+







The channel to operate on.
.AP int direction in
\fBTCL_READABLE\fR means the input handle is wanted; \fBTCL_WRITABLE\fR
means the output handle is wanted.
.AP void **handlePtr out
Points to the location where the desired OS-specific handle should be
stored.
.AP int size in
.AP Tcl_Size size in
The size, in bytes, of buffers to allocate in this channel.
.AP int mask in
An OR-ed combination of \fBTCL_READABLE\fR, \fBTCL_WRITABLE\fR
and \fBTCL_EXCEPTION\fR that indicates events that have occurred on
this channel.
.AP Tcl_Interp *interp in
Current interpreter. (can be NULL)
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
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







+
+
+
+
+
+
+
+
+
+

















+
-
+







\fBTcl_GetChannelThread\fR returns the id of the thread currently managing
the specified \fIchannel\fR. This allows channel drivers to send their file
events to the correct event queue even for a multi-threaded core.
.PP
\fBTcl_GetChannelMode\fR returns an OR-ed combination of \fBTCL_READABLE\fR
and \fBTCL_WRITABLE\fR, indicating whether the channel is open for input
and output.
.PP
.VS 8.7
.PP
\fBTcl_RemoveChannelMode\fR removes an access privilege from the
channel, either \fBTCL_READABLE\fR or \fBTCL_WRITABLE\fR, and returns
a regular Tcl result code, \fBTCL_OK\fR, or \fBTCL_ERROR\fR. The
function throws an error if either an invalid mode is specified or the
result of the removal would be an inaccessible channel. In that case
an error message is left in the interp argument, if not NULL.
.VE 8.7
.PP
\fBTcl_GetChannelBufferSize\fR returns the size, in bytes, of buffers
allocated to store input or output in \fIchannel\fR. If the value was not set
by a previous call to \fBTcl_SetChannelBufferSize\fR, described below, then
the default value of 4096 is returned.
.PP
\fBTcl_SetChannelBufferSize\fR sets the size, in bytes, of buffers that
will be allocated in subsequent operations on the channel to store input or
output. The \fIsize\fR argument should be between one and one million,
allowing buffers of one byte to one million bytes. If \fIsize\fR is
outside this range, \fBTcl_SetChannelBufferSize\fR sets the buffer size to
4096.
.PP
\fBTcl_NotifyChannel\fR is called by a channel driver to indicate to
the generic layer that the events specified by \fImask\fR have
occurred on the channel.  Channel drivers are responsible for invoking
this function whenever the channel handlers need to be called for the
channel (or other pending tasks like a write flush should be performed).
channel.  See \fBWATCHPROC\fR below for more details.
See \fBWATCHPROC\fR below for more details.
.PP
\fBTcl_BadChannelOption\fR is called from driver specific
\fIsetOptionProc\fR or \fIgetOptionProc\fR to generate a complete
error message.
.PP
\fBTcl_ChannelBuffered\fR returns the number of bytes of input
currently buffered in the internal buffer (push back area) of the
299
300
301
302
303
304
305
306

307
308
309
310
311
312
313
312
313
314
315
316
317
318

319
320
321
322
323
324
325
326







-
+







was versioned starting in Tcl 8.3.2/8.4 to correct a problem with stacked
channel drivers.  See the \fBOLD CHANNEL TYPES\fR section below for
details about the old structure.
.PP
The \fBTcl_ChannelType\fR structure contains the following fields:
.PP
.CS
typedef struct Tcl_ChannelType {
typedef struct {
        const char *\fItypeName\fR;
        Tcl_ChannelTypeVersion \fIversion\fR;
        void *\fIcloseProc\fR; /* Not used any more*/
        Tcl_DriverInputProc *\fIinputProc\fR;
        Tcl_DriverOutputProc *\fIoutputProc\fR;
        void *\fIseekProc\fR; /* Not used any more */
        Tcl_DriverSetOptionProc *\fIsetOptionProc\fR;
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
369
370
371
372
373
374
375

376
377
378
379
380
381
382







-







identifies the type of the device implemented by this driver, e.g.
\fBfile\fR or \fBsocket\fR.
.PP
This value can be retrieved with \fBTcl_ChannelName\fR, which returns
a pointer to the string.
.SS VERSION
.PP

The \fIversion\fR field should be set to the version of the structure
that you require. \fBTCL_CHANNEL_VERSION_5\fR is the minimum supported.
.PP
This value can be retrieved with \fBTcl_ChannelVersion\fR.
.SS BLOCKMODEPROC
.PP
The \fIblockModeProc\fR field contains the address of a function called by
525
526
527
528
529
530
531
532

533
534

535
536
537
538
539
540
541
537
538
539
540
541
542
543

544
545

546
547
548
549
550
551
552
553







-
+

-
+







.PP
The \fIwideSeekProc\fR field contains the address of a function called by the
generic layer to move the access point at which subsequent input or output
operations will be applied. \fIWideSeekProc\fR must match the following
prototype:
.PP
.CS
typedef Tcl_WideInt \fBTcl_DriverWideSeekProc\fR(
typedef long long \fBTcl_DriverWideSeekProc\fR(
        void *\fIinstanceData\fR,
        Tcl_WideInt \fIoffset\fR,
        long long \fIoffset\fR,
        int \fIseekMode\fR,
        int *\fIerrorCodePtr\fR);
.CE
.PP
The \fIinstanceData\fR argument is the same as the value given to
\fBTcl_CreateChannel\fR when this channel was created.  \fIOffset\fR and
\fIseekMode\fR have the same meaning as for the \fBTcl_Seek\fR
757
758
759
760
761
762
763
764

765
766
767
768
769
770
771
769
770
771
772
773
774
775

776
777
778
779
780
781
782
783







-
+







The \fItruncateProc\fR field contains the address of the function
called by the generic layer when a channel is truncated to some
length. It can be NULL.
.PP
.CS
typedef int \fBTcl_DriverTruncateProc\fR(
        void *\fIinstanceData\fR,
        Tcl_WideInt \fIlength\fR);
        long long \fIlength\fR);
.CE
.PP
\fIInstanceData\fR is the same as the value passed to
\fBTcl_CreateChannel\fR when this channel was created, and
\fIlength\fR is the new length of the underlying file, which should
not be negative. The result should be 0 on success or an errno code
(suitable for use with \fBTcl_SetErrno\fR) on failure.

Changes to doc/CrtChnlHdlr.3.

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
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







-


-


-

-
+








-
+







.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
Tcl_CreateChannelHandler, Tcl_DeleteChannelHandler \- call a procedure when a channel becomes readable or writable
.SH SYNOPSIS
.nf
.nf
\fB#include <tcl.h>\fR
.sp
void
\fBTcl_CreateChannelHandler\fR(\fIchannel, mask, proc, clientData\fR)
.sp
void
\fBTcl_DeleteChannelHandler\fR(\fIchannel, proc, clientData\fR)
.sp
.fi
.SH ARGUMENTS
.AS Tcl_ChannelProc clientData
.AP Tcl_Channel channel in
Tcl channel such as returned by \fBTcl_CreateChannel\fR.
.AP int mask in
Conditions under which \fIproc\fR should be called: OR-ed combination of
\fBTCL_READABLE\fR, \fBTCL_WRITABLE\fR and \fBTCL_EXCEPTION\fR. Specify
a zero value to temporarily disable an existing handler.
.AP Tcl_FileProc *proc in
.AP Tcl_ChannelProc *proc in
Procedure to invoke whenever the channel indicated by \fIchannel\fR meets
the conditions specified by \fImask\fR.
.AP void *clientData in
Arbitrary one-word value to pass to \fIproc\fR.
.BE
.SH DESCRIPTION
.PP
80
81
82
83
84
85
86
87

88
89

77
78
79
80
81
82
83

84
85

86







-
+

-
+
example, if there are two handlers for \fBTCL_READABLE\fR on the same
channel, the first handler could consume all of the available input
so that the channel is no longer readable when the second handler
is invoked.
For this reason it may be useful to use nonblocking I/O on channels
for which there are event handlers.
.SH "SEE ALSO"
Notifier(3), Tcl_CreateChannel(3), Tcl_OpenFileChannel(3), vwait(n).
Notifier(3), Tcl_CreateChannel(3), Tcl_OpenFileChannel(3), vwait(n)
.SH KEYWORDS
blocking, callback, channel, events, handler, nonblocking.
blocking, callback, channel, events, handler, nonblocking

Changes to doc/CrtCloseHdlr.3.

10
11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
10
11
12
13
14
15
16

17
18

19

20
21
22
23
24
25
26
27







-


-

-
+







'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
Tcl_CreateCloseHandler, Tcl_DeleteCloseHandler \- arrange for callbacks when channels are closed
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
void
\fBTcl_CreateCloseHandler\fR(\fIchannel, proc, clientData\fR)
.sp
void
\fBTcl_DeleteCloseHandler\fR(\fIchannel, proc, clientData\fR)
.sp
.fi
.SH ARGUMENTS
.AS Tcl_CloseProc clientData
.AP Tcl_Channel channel in
The channel for which to create or delete a close callback.
.AP Tcl_CloseProc *proc in
The procedure to call as the callback.
.AP void *clientData in

Changes to doc/CrtCommand.3.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
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







+









-
+







Tcl_CreateCommand \- implement new commands in C
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Command
\fBTcl_CreateCommand\fR(\fIinterp, cmdName, proc, clientData, deleteProc\fR)
.fi
.SH ARGUMENTS
.AS Tcl_CmdDeleteProc *deleteProc
.AP Tcl_Interp *interp in
Interpreter in which to create new command.
.AP "const char" *cmdName in
Name of command.
.AP Tcl_CmdProc *proc in
Implementation of new command:  \fIproc\fR will be called whenever
\fIcmdName\fR is invoked as a command.
.AP voie *clientData in
.AP void *clientData in
Arbitrary one-word value to pass to \fIproc\fR and \fIdeleteProc\fR.
.AP Tcl_CmdDeleteProc *deleteProc in
Procedure to call before \fIcmdName\fR is deleted from the interpreter;
allows for command-specific cleanup.  If NULL, then no procedure is
called before the command is deleted.
.BE
.SH DESCRIPTION
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
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







+



-
-
+




-
-
-
+
+
+
+
+
+







data structure that describes what to do when the command procedure
is invoked.  \fIArgc\fR and \fIargv\fR describe the arguments to
the command, \fIargc\fR giving the number of arguments (including
the command name) and \fIargv\fR giving the values of the arguments
as strings.  The \fIargv\fR array will contain \fIargc\fR+1 values;
the first \fIargc\fR values point to the argument strings, and the
last value is NULL.
.PP
Note that the argument strings should not be modified as they may
point to constant strings or may be shared with other parts of the
interpreter.
.PP
Note that the argument strings are encoded in normalized UTF-8 since
Note also that the argument strings are encoded in normalized UTF-8 since
version 8.1 of Tcl.
.PP
\fIProc\fR must return an integer code that is expected to be one of
\fBTCL_OK\fR, \fBTCL_ERROR\fR, \fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or
\fBTCL_CONTINUE\fR.  See the Tcl overview man page
for details on what these codes mean.  Most normal commands will only
return \fBTCL_OK\fR or \fBTCL_ERROR\fR.  In addition, \fIproc\fR must set
\fBTCL_CONTINUE\fR. See the \fBreturn\fR man page for details on
what these codes mean and the use of extended values for an extension's
private use. Most normal commands will only return \fBTCL_OK\fR
or \fBTCL_ERROR\fR.
.PP
In addition, \fIproc\fR must set
the interpreter result;
in the case of a \fBTCL_OK\fR return code this gives the result
of the command, and in the case of \fBTCL_ERROR\fR it gives an error message.
The \fBTcl_SetResult\fR procedure provides an easy interface for setting
the return value;  for complete details on how the interpreter result
field is managed, see the \fBTcl_Interp\fR man page.
Before invoking a command procedure,

Changes to doc/CrtFileHdlr.3.

13
14
15
16
17
18
19

20
21
22
23
24
25
26
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27







+







.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_CreateFileHandler\fR(\fIfd, mask, proc, clientData\fR)
.sp
\fBTcl_DeleteFileHandler\fR(\fIfd\fR)
.fi
.SH ARGUMENTS
.AS Tcl_FileProc clientData
.AP int fd in
Unix file descriptor for an open file or device.
.AP int mask in
Conditions under which \fIproc\fR should be called:
OR-ed combination of \fBTCL_READABLE\fR, \fBTCL_WRITABLE\fR,

Changes to doc/CrtInterp.3.

20
21
22
23
24
25
26

27
28
29
30
31
32
33
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34







+







\fBTcl_DeleteInterp\fR(\fIinterp\fR)
.sp
int
\fBTcl_InterpDeleted\fR(\fIinterp\fR)
.sp
int
\fBTcl_InterpActive\fR(\fIinterp\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Token for interpreter to be destroyed or queried.
.BE
.SH DESCRIPTION
.PP

Changes to doc/CrtObjCmd.3.

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
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










-
+







+
+
+







'\"
'\" Copyright (c) 1996-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_CreateObjCommand 3 8.0 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_CreateObjCommand, Tcl_DeleteCommand, Tcl_DeleteCommandFromToken, Tcl_GetCommandInfo, Tcl_GetCommandInfoFromToken, Tcl_SetCommandInfo, Tcl_SetCommandInfoFromToken, Tcl_GetCommandName, Tcl_GetCommandFullName, Tcl_GetCommandFromObj, Tcl_RegisterCommandTypeName, Tcl_GetCommandTypeName \- implement new commands in C
Tcl_CreateObjCommand, Tcl_CreateObjCommand2, Tcl_DeleteCommand, Tcl_DeleteCommandFromToken, Tcl_GetCommandInfo, Tcl_GetCommandInfoFromToken, Tcl_SetCommandInfo, Tcl_SetCommandInfoFromToken, Tcl_GetCommandName, Tcl_GetCommandFullName, Tcl_GetCommandFromObj \- implement new commands in C
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Command
\fBTcl_CreateObjCommand\fR(\fIinterp, cmdName, proc, clientData, deleteProc\fR)
.sp
Tcl_Command
\fBTcl_CreateObjCommand2\fR(\fIinterp, cmdName, proc2, clientData, deleteProc\fR)
.sp
int
\fBTcl_DeleteCommand\fR(\fIinterp, cmdName\fR)
.sp
int
\fBTcl_DeleteCommandFromToken\fR(\fIinterp, token\fR)
.sp
int
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
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







-




-
+
-
-
-
-
-
-
-




-
+




+
+
+







.sp
int
\fBTcl_SetCommandInfoFromToken\fR(\fItoken, infoPtr\fR)
.sp
const char *
\fBTcl_GetCommandName\fR(\fIinterp, token\fR)
.sp
void
\fBTcl_GetCommandFullName\fR(\fIinterp, token, objPtr\fR)
.sp
Tcl_Command
\fBTcl_GetCommandFromObj\fR(\fIinterp, objPtr\fR)
.sp
.fi
.VS "info cmdtype feature"
void
\fBTcl_RegisterCommandTypeName\fR(\fIproc, typeName\fR)
.sp
const char *
\fBTcl_GetCommandTypeName\fR(\fItoken\fR)
.VE "info cmdtype feature"
.SH ARGUMENTS
.AS Tcl_CmdDeleteProc *deleteProc in/out
.AP Tcl_Interp *interp in
Interpreter in which to create a new command or that contains a command.
.AP char *cmdName in
.AP "const char" *cmdName in
Name of command.
.AP Tcl_ObjCmdProc *proc in
Implementation of the new command: \fIproc\fR will be called whenever
\fIcmdName\fR is invoked as a command.
.AP Tcl_ObjCmdProc2 *proc2 in
Implementation of the new command: \fIproc2\fR will be called whenever
\fIcmdName\fR is invoked as a command.
.AP void *clientData in
Arbitrary one-word value to pass to \fIproc\fR and \fIdeleteProc\fR.
.AP Tcl_CmdDeleteProc *deleteProc in
Procedure to call before \fIcmdName\fR is deleted from the interpreter;
allows for command-specific cleanup. If NULL, then no procedure is
called before the command is deleted.
.AP Tcl_Command token in
130
131
132
133
134
135
136
137
138
139




140
141
142
143
144
145
146
128
129
130
131
132
133
134



135
136
137
138
139
140
141
142
143
144
145







-
-
-
+
+
+
+







\fBTcl_GetIntFromObj\fR on \fIobjv\fR[\fB2\fR] to obtain the integer
representation of that value; that call may change the type of the value
that \fIobjv\fR[\fB2\fR] points at, but will not change where
\fIobjv\fR[\fB2\fR] points.
.PP
\fIproc\fR must return an integer code that is either \fBTCL_OK\fR,
\fBTCL_ERROR\fR, \fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or \fBTCL_CONTINUE\fR.
See the Tcl overview man page
for details on what these codes mean.  Most normal commands will only
return \fBTCL_OK\fR or \fBTCL_ERROR\fR.
See the \fBreturn\fR man page for details on what these codes mean and the
use of extended values for an extension's private use. Most normal commands
will only return \fBTCL_OK\fR or \fBTCL_ERROR\fR.
.PP
In addition, if \fIproc\fR needs to return a non-empty result,
it can call \fBTcl_SetObjResult\fR to set the interpreter's result.
In the case of a \fBTCL_OK\fR return code this gives the result
of the command,
and in the case of \fBTCL_ERROR\fR this gives an error message.
Before invoking a command procedure,
\fBTcl_EvalObjEx\fR sets interpreter's result to
176
177
178
179
180
181
182











183
184
185
186
187
188
189
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







+
+
+
+
+
+
+
+
+
+
+







.CS
typedef void \fBTcl_CmdDeleteProc\fR(
        void *\fIclientData\fR);
.CE
.PP
The \fIclientData\fR argument will be the same as the \fIclientData\fR
argument passed to \fBTcl_CreateObjCommand\fR.
.PP
\fBTcl_CreateObjCommand2\fR does the same as \fBTcl_CreateObjCommand\fR,
except its \fIproc2\fR argument is of type \fBTcl_ObjCmdProc2\fR.
.PP
.CS
typedef int \fBTcl_ObjCmdProc2\fR(
        void *\fIclientData\fR,
        Tcl_Interp *\fIinterp\fR,
        Tcl_Size \fIobjc\fR,
        Tcl_Obj *const \fIobjv\fR[]);
.CE
.PP
\fBTcl_DeleteCommand\fR deletes a command from a command interpreter.
Once the call completes, attempts to invoke \fIcmdName\fR in
\fIinterp\fR will result in errors.
If \fIcmdName\fR is not bound as a command in \fIinterp\fR then
\fBTcl_DeleteCommand\fR does nothing and returns -1;  otherwise
it returns 0.
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
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







-
+








+
+



-
-
-
+
+
+
+

-
-
+
+
+
+







If the command is not found, then it returns 0.
Otherwise it places information about the command
in the \fBTcl_CmdInfo\fR structure
pointed to by \fIinfoPtr\fR and returns 1.
A \fBTcl_CmdInfo\fR structure has the following fields:
.PP
.CS
typedef struct Tcl_CmdInfo {
typedef struct {
    int \fIisNativeObjectProc\fR;
    Tcl_ObjCmdProc *\fIobjProc\fR;
    void *\fIobjClientData\fR;
    Tcl_CmdProc *\fIproc\fR;
    void *\fIclientData\fR;
    Tcl_CmdDeleteProc *\fIdeleteProc\fR;
    void *\fIdeleteData\fR;
    Tcl_Namespace *\fInamespacePtr\fR;
    Tcl_ObjCmdProc2 *\fIobjProc2\fR;
    void *\fIobjClientData2\fR;
} \fBTcl_CmdInfo\fR;
.CE
.PP
The \fIisNativeObjectProc\fR field has the value 1
if \fBTcl_CreateObjCommand\fR was called to register the command;
it is 0 if only \fBTcl_CreateCommand\fR was called.
The \fIisNativeObjectProc\fR field has the value 2 if
\fBTcl_CreateObjCommand2\fR was called to register the command;
it has the value 1 if \fBTcl_CreateObjCommand\fR was called to
register the command; it is 0 if only \fBTcl_CreateCommand\fR was called.
It allows a program to determine whether it is faster to
call \fIobjProc\fR or \fIproc\fR:
\fIobjProc\fR is normally faster
call \fIobjProc2\fR, \fIobjProc\fR or \fIproc\fR:
\fIobjProc2\fR/\fIobjProc\fR is normally faster
if \fIisNativeObjectProc\fR has the value 2;
\fIobjProc\fR/\fIobjProc\fR is normally faster
if \fIisNativeObjectProc\fR has the value 1.
The fields \fIobjProc\fR and \fIobjClientData\fR
have the same meaning as the \fIproc\fR and \fIclientData\fR
arguments to \fBTcl_CreateObjCommand\fR;
they hold information about the value-based command procedure
that the Tcl interpreter calls to implement the command.
The fields \fIproc\fR and \fIclientData\fR
276
277
278
279
280
281
282
283
284

285
286
287
288
289
290
291
291
292
293
294
295
296
297


298
299
300
301
302
303
304
305







-
-
+







copies the information from \fI*infoPtr\fR to Tcl's internal structure
for the command and returns 1.
.PP
Note that \fBTcl_SetCommandInfo\fR and
\fBTcl_SetCommandInfoFromToken\fR both allow the clientData for a
command's deletion procedure to be given a different value than the
clientData for its command procedure.
.PP
Note that neither \fBTcl_SetCommandInfo\fR nor
Note also that neither \fBTcl_SetCommandInfo\fR nor
\fBTcl_SetCommandInfoFromToken\fR will change a command's namespace.
Use \fBTcl_Eval\fR to call the \fBrename\fR command to do that.
.PP
\fBTcl_GetCommandName\fR provides a mechanism for tracking commands
that have been renamed.
Given a token returned by \fBTcl_CreateObjCommand\fR
when the command was created, \fBTcl_GetCommandName\fR returns the
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
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







-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+
-




is appended to the value specified by \fIobjPtr\fR.
.PP
\fBTcl_GetCommandFromObj\fR returns a token for the command
specified by the name in a \fBTcl_Obj\fR.
The command name is resolved relative to the current namespace.
Returns NULL if the command is not found.
.PP
.VS "info cmdtype feature"
\fBTcl_RegisterCommandTypeName\fR is used to associate a name (the
\fItypeName\fR argument) with a particular implementation function so that it
.SH "REFERENCE COUNT MANAGEMENT"
.PP
When the \fIproc\fR passed to \fBTcl_CreateObjCommand\fR is called,
the values in its \fIobjv\fR argument will have a reference count of
can then be looked up with \fBTcl_GetCommandTypeName\fR, which in turn is
called with a command token that information is wanted for and which returns
the name of the type that was registered for the implementation function used
for that command. (The lookup functionality is surfaced virtually directly in Tcl via
\fBinfo cmdtype\fR.) If there is no function registered for a particular
function, the result will be the string literal
.QW \fBnative\fR .
The registration of a name can be undone by registering a mapping to NULL
instead. The result from \fBTcl_GetCommandTypeName\fR will be exactly that
at least 1, with that guaranteed reference being from the Tcl
evaluation stack. You should not call \fBTcl_DecrRefCount\fR on any of
those values unless you call \fBTcl_IncrRefCount\fR on them first.
Also, when the \fIproc\fR is called, the interpreter result is
guaranteed to be an empty string value with a reference count of 1.
.PP
\fBTcl_GetCommandFullName\fR does not modify the reference count of its
\fIobjPtr\fR argument, but does require that the object be unshared.
.PP
\fBTcl_GetCommandFromObj\fR does not modify the reference count of its
string which was registered, and not a copy; use of a compile-time constant
string is \fIstrongly recommended\fR.
\fIobjPtr\fR argument; it only reads.
.VE "info cmdtype feature"
.SH "SEE ALSO"
Tcl_CreateCommand(3), Tcl_ResetResult(3), Tcl_SetObjResult(3)
.SH KEYWORDS
bind, command, create, delete, namespace, value

Changes to doc/CrtTimerHdlr.3.

14
15
16
17
18
19
20

21
22
23
24
25
26
27
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28







+







.nf
\fB#include <tcl.h>\fR
.sp
Tcl_TimerToken
\fBTcl_CreateTimerHandler\fR(\fImilliseconds, proc, clientData\fR)
.sp
\fBTcl_DeleteTimerHandler\fR(\fItoken\fR)
.fi
.SH ARGUMENTS
.AS Tcl_TimerToken milliseconds
.AP int milliseconds  in
How many milliseconds to wait before invoking \fIproc\fR.
.AP Tcl_TimerProc *proc in
Procedure to invoke after \fImilliseconds\fR have elapsed.
.AP void *clientData in

Changes to doc/CrtTrace.3.

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

30
31
32
33
34
35
36
37
38
39
40



41
42
43
44
45

46
47
48
49
50
51
52
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
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



-
+








-
+










+
+
+

+




-
+











+
+
+




-
+







'\"
'\" Copyright (c) 1989-1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 2002 by Kevin B. Kenny <kennykb@acm.org>.  All rights reserved.
'\" Copyright (c) 2002 Kevin B. Kenny <kennykb@acm.org>.  All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_CreateTrace 3 "" Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_CreateTrace, Tcl_CreateObjTrace, Tcl_DeleteTrace \- arrange for command execution to be traced
Tcl_CreateTrace, Tcl_CreateObjTrace, Tcl_CreateObjTrace2, Tcl_DeleteTrace \- arrange for command execution to be traced
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Trace
\fBTcl_CreateTrace\fR(\fIinterp, level, proc, clientData\fR)
.sp
Tcl_Trace
\fBTcl_CreateObjTrace\fR(\fIinterp, level, flags, objProc, clientData, deleteProc\fR)
.sp
Tcl_Trace
\fBTcl_CreateObjTrace2\fR(\fIinterp, level, flags, objProc2, clientData, deleteProc\fR)
.sp
\fBTcl_DeleteTrace\fR(\fIinterp, trace\fR)
.fi
.SH ARGUMENTS
.AS Tcl_CmdObjTraceDeleteProc *deleteProc
.AP Tcl_Interp *interp in
Interpreter containing command to be traced or untraced.
.AP int level in
.AP Tcl_Size level in
Only commands at or below this nesting level will be traced unless
0 is specified.  1 means
top-level commands only, 2 means top-level commands or those that are
invoked as immediate consequences of executing top-level commands
(procedure bodies, bracketed commands, etc.) and so on.
A value of 0 means that commands at any level are traced.
.AP int flags in
Flags governing the trace execution.  See below for details.
.AP Tcl_CmdObjTraceProc *objProc in
Procedure to call for each command that is executed.  See below for
details of the calling sequence.
.AP Tcl_CmdObjTraceProc2 *objProc2 in
Procedure to call for each command that is executed.  See below for
details of the calling sequence.
.AP Tcl_CmdTraceProc *proc in
Procedure to call for each command that is executed.  See below for
details on the calling sequence.
.AP void *clientData in
Arbitrary one-word value to pass to \fIobjProc\fR or \fIproc\fR.
Arbitrary one-word value to pass to \fIobjProc\fR, \fIobjProc2\fR or \fIproc\fR.
.AP Tcl_CmdObjTraceDeleteProc *deleteProc in
Procedure to call when the trace is deleted.  See below for details of
the calling sequence.  A NULL pointer is permissible and results in no
callback when the trace is deleted.
.AP Tcl_Trace trace in
Token for trace to be removed (return value from previous call
to \fBTcl_CreateTrace\fR).
70
71
72
73
74
75
76














77
78
79
80
81
82
83
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+







        \fBTcl_Interp\fR* \fIinterp\fR,
        int \fIlevel\fR,
        const char *\fIcommand\fR,
        \fBTcl_Command\fR \fIcommandToken\fR,
        int \fIobjc\fR,
        \fBTcl_Obj\fR *const \fIobjv\fR[]);
.CE
.PP
\fIobjProc2\fR should have arguments and result that match the type,
\fBTcl_CmdObjTraceProc2\fR:
.PP
.CS
typedef int \fBTcl_CmdObjTraceProc2\fR(
        \fBvoid *\fR \fIclientData\fR,
        \fBTcl_Interp\fR* \fIinterp\fR,
        Tcl_Size \fIlevel\fR,
        const char *\fIcommand\fR,
        \fBTcl_Command\fR \fIcommandToken\fR,
        Tcl_Size \fIobjc\fR,
        \fBTcl_Obj\fR *const \fIobjv\fR[]);
.CE
.PP
The \fIclientData\fR and \fIinterp\fR parameters are copies of the
corresponding arguments given to \fBTcl_CreateTrace\fR.
\fIclientData\fR typically points to an application-specific data
structure that describes what to do when \fIobjProc\fR is invoked.  The
\fIlevel\fR parameter gives the nesting level of the command (1 for
top-level commands passed to \fBTcl_Eval\fR by the application, 2 for
95
96
97
98
99
100
101
102

103
104
105
106
107
108
109
110
111
112
113
116
117
118
119
120
121
122

123




124
125
126
127
128
129
130







-
+
-
-
-
-







.PP
The \fIobjProc\fR callback is expected to return a standard Tcl status
return code.  If this code is \fBTCL_OK\fR (the normal case), then
the Tcl interpreter will invoke the command.  Any other return code
is treated as if the command returned that status, and the command is
\fInot\fR invoked.
.PP
The \fIobjProc\fR callback must not modify \fIobjv\fR in any way.  It
The \fIobjProc\fR callback must not modify \fIobjv\fR in any way.
is, however, permissible to change the command by calling
\fBTcl_SetCommandTokenInfo\fR prior to returning.  Any such change
takes effect immediately, and the command is invoked with the new
information.
.PP
Tracing will only occur for commands at nesting level less than
or equal to the \fIlevel\fR parameter (i.e. the \fIlevel\fR
parameter to \fIobjProc\fR will always be less than or equal to the
\fIlevel\fR parameter to \fBTcl_CreateTrace\fR).
.PP
Tracing has a significant effect on runtime performance because it
183
184
185
186
187
188
189









190
191
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217







+
+
+
+
+
+
+
+
+


compilation of Tcl commands such as \fBif\fR and \fBwhile\fR is always
disabled.  There is no notification when a trace created with
\fBTcl_CreateTrace\fR is deleted.
There is no way to be notified when the trace created by
\fBTcl_CreateTrace\fR is deleted.  There is no way for the \fIproc\fR
associated with a call to \fBTcl_CreateTrace\fR to abort execution of
\fIcommand\fR.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
When the \fIproc\fR passed to \fBTcl_CreateObjTrace\fR is called,
the values in its \fIobjv\fR argument will have a reference count of
at least 1, with that guaranteed reference being from the Tcl
evaluation stack. You should not call \fBTcl_DecrRefCount\fR on any of
those values unless you call \fBTcl_IncrRefCount\fR on them first.
.SH "SEE ALSO"
trace(n)
.SH KEYWORDS
command, create, delete, interpreter, trace

Changes to doc/DString.3.

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

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
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
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











-
+
















-
+












+
+
+
+
+








-
-
+
+

-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_DString 3 7.4 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_DStringInit, Tcl_DStringAppend, Tcl_DStringAppendElement, Tcl_DStringStartSublist, Tcl_DStringEndSublist, Tcl_DStringLength, Tcl_DStringValue, Tcl_DStringSetLength, Tcl_DStringFree, Tcl_DStringResult, Tcl_DStringGetResult \- manipulate dynamic strings
Tcl_DStringInit, Tcl_DStringAppend, Tcl_DStringAppendElement, Tcl_DStringStartSublist, Tcl_DStringEndSublist, Tcl_DStringLength, Tcl_DStringValue, Tcl_DStringSetLength, Tcl_DStringFree, Tcl_DStringResult, Tcl_DStringGetResult, Tcl_DStringToObj \- manipulate dynamic strings
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_DStringInit\fR(\fIdsPtr\fR)
.sp
char *
\fBTcl_DStringAppend\fR(\fIdsPtr, bytes, length\fR)
.sp
char *
\fBTcl_DStringAppendElement\fR(\fIdsPtr, element\fR)
.sp
\fBTcl_DStringStartSublist\fR(\fIdsPtr\fR)
.sp
\fBTcl_DStringEndSublist\fR(\fIdsPtr\fR)
.sp
size_t
Tcl_Size
\fBTcl_DStringLength\fR(\fIdsPtr\fR)
.sp
char *
\fBTcl_DStringValue\fR(\fIdsPtr\fR)
.sp
\fBTcl_DStringSetLength\fR(\fIdsPtr, newLength\fR)
.sp
\fBTcl_DStringFree\fR(\fIdsPtr\fR)
.sp
\fBTcl_DStringResult\fR(\fIinterp, dsPtr\fR)
.sp
\fBTcl_DStringGetResult\fR(\fIinterp, dsPtr\fR)
.sp
Tcl_Obj *
\fBTcl_DStringToObj\fR(\fIdsPtr\fR)
.fi
.sp
.SH ARGUMENTS
.AS Tcl_DString newLength in/out
.AP Tcl_DString *dsPtr in/out
Pointer to structure that is used to manage a dynamic string.
.AP "const char" *bytes in
Pointer to characters to append to dynamic string.
.AP "const char" *element in
Pointer to characters to append as list element to dynamic string.
.AP size_t length in
Number of bytes from \fIbytes\fR to add to dynamic string.  If TCL_INDEX_NONE,
.AP Tcl_Size length in
Number of bytes from \fIbytes\fR to add to dynamic string.  If negative,
add all characters up to null terminating character.
.AP size_t newLength in
.AP Tcl_Size newLength in
New length for dynamic string, not including null terminating
character.
.AP Tcl_Interp *interp in/out
Interpreter whose result is to be set from or moved to the
dynamic string.
.BE

132
133
134
135
136
137
138




139
140
141
142
143
144










145
146
147
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







+
+
+
+






+
+
+
+
+
+
+
+
+
+



.PP
\fBTcl_DStringResult\fR sets the result of \fIinterp\fR to the value of
the dynamic string given by \fIdsPtr\fR.  It does this by moving
a pointer from \fIdsPtr\fR to the interpreter's result.
This saves the cost of allocating new memory and copying the string.
\fBTcl_DStringResult\fR also reinitializes the dynamic string to
an empty string.
Since the dynamic string is reinitialized, there is no need to
further call \fBTcl_DStringFree\fR on it and it can be reused without
calling \fBTcl_DStringInit\fR. The caller must ensure that the dynamic
string stored in \fIdsPtr\fR is encoded in Tcl's internal UTF-8 format.
.PP
\fBTcl_DStringGetResult\fR does the opposite of \fBTcl_DStringResult\fR.
It sets the value of \fIdsPtr\fR to the result of \fIinterp\fR and
it clears \fIinterp\fR's result.
If possible it does this by moving a pointer rather than by copying
the string.
.PP
\fBTcl_DStringToObj\fR returns a \fBTcl_Obj\fR containing the value of the
dynamic string given by \fIdsPtr\fR. It does this by moving a pointer from
\fIdsPtr\fR to a newly allocated \fBTcl_Obj\fR and reinitializing to dynamic
string to an empty string. This saves the cost of allocating new memory and
copying the string. Since the dynamic string is reinitialized, there is no need
to further call \fBTcl_DStringFree\fR on it and it can be reused without calling
\fBTcl_DStringInit\fR. The returned \fBTcl_Obj\fR has a reference count of 0.
The caller must ensure that the dynamic string stored in \fIdsPtr\fR is encoded
in Tcl's internal UTF-8 format.

.SH KEYWORDS
append, dynamic string, free, result

Changes to doc/DetachPids.3.

16
17
18
19
20
21
22

23
24
25

26
27
28
29
30
31
32
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33







+


-
+







.sp
\fBTcl_DetachPids\fR(\fInumPids, pidPtr\fR)
.sp
\fBTcl_ReapDetachedProcs\fR()
.sp
Tcl_Pid
\fBTcl_WaitPid\fR(\fIpid, statusPtr, options\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Pid *statusPtr out
.AP int numPids in
.AP Tcl_Size numPids in
Number of process ids contained in the array pointed to by \fIpidPtr\fR.
.AP int *pidPtr in
Address of array containing \fInumPids\fR process ids.
.AP Tcl_Pid pid in
The id of the process (pipe) to wait for.
.AP int *statusPtr out
The result of waiting on a process (pipe). Either 0 or ECHILD.

Changes to doc/DictObj.3.

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
29
30
31
32
33
34
35

36
37

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52







-


-







+







int
\fBTcl_DictObjSize\fR(\fIinterp, dictPtr, sizePtr\fR)
.sp
int
\fBTcl_DictObjFirst\fR(\fIinterp, dictPtr, searchPtr,
                 keyPtrPtr, valuePtrPtr, donePtr\fR)
.sp
void
\fBTcl_DictObjNext\fR(\fIsearchPtr, keyPtrPtr, valuePtrPtr, donePtr\fR)
.sp
void
\fBTcl_DictObjDone\fR(\fIsearchPtr\fR)
.sp
int
\fBTcl_DictObjPutKeyList\fR(\fIinterp, dictPtr, keyc, keyv, valuePtr\fR)
.sp
int
\fBTcl_DictObjRemoveKeyList\fR(\fIinterp, dictPtr, keyc, keyv\fR)
.fi
.SH ARGUMENTS
.AS Tcl_DictSearch "**valuePtrPtr" in/out
.AP Tcl_Interp *interp in
If an error occurs while converting a value to be a dictionary value,
an error message is left in the interpreter's result value
unless \fIinterp\fR is NULL.
.AP Tcl_Obj *dictPtr in/out
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
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







-
+


+
+
+
+
+











-
+







dictionary value (or sub-value, in the case of
\fBTcl_DictObjPutKeyList\fR.)
.AP Tcl_Obj **valuePtrPtr out
Points to a variable that will have the value from a key/value pair
placed within it.  For \fBTcl_DictObjFirst\fR and
\fBTcl_DictObjNext\fR, this may be NULL to indicate that the caller is
not interested in the value.
.AP int *sizePtr out
.AP "Tcl_Size \&| int" *sizePtr out
Points to a variable that will have the number of key/value pairs
contained within the dictionary placed within it.
May be (Tcl_Size *)NULL when not used. If it points to a variable which
type is not \fBTcl_Size\fR, a compiler warning will be generated.
If your extensions is compiled with -DTCL_8_API, this function will return
NULL for dictionaries larger than INT_MAX (which should
trigger proper error-handling), otherwise expect it to crash.
.AP Tcl_DictSearch *searchPtr in/out
Pointer to record to use to keep track of progress in enumerating all
key/value pairs in a dictionary.  The contents of the record will be
initialized by the call to \fBTcl_DictObjFirst\fR.  If the enumerating
is to be terminated before all values in the dictionary have been
returned, the search record \fImust\fR be passed to
\fBTcl_DictObjDone\fR to enable the internal locks to be released.
.AP int *donePtr out
Points to a variable that will have a non-zero value written into it
when the enumeration of the key/value pairs in a dictionary has
completed, and a zero otherwise.
.AP int keyc in
.AP Tcl_Size keyc in
Indicates the number of keys that will be supplied in the \fIkeyv\fR
array.
.AP "Tcl_Obj *const" *keyv in
Array of \fIkeyc\fR pointers to values that
\fBTcl_DictObjPutKeyList\fR and \fBTcl_DictObjRemoveKeyList\fR will
use to locate the key/value pair to manipulate within the
sub-dictionaries of the main dictionary value passed to them.
134
135
136
137
138
139
140
141


142
143
144
145
146
147
148
138
139
140
141
142
143
144

145
146
147
148
149
150
151
152
153







-
+
+







error if the key did not previously exist.  The result of this
procedure is \fBTCL_OK\fR, or \fBTCL_ERROR\fR if the \fIdictPtr\fR cannot be
converted to a dictionary.
.PP
\fBTcl_DictObjSize\fR updates the given variable with the number of
key/value pairs currently in the given dictionary. The result of this
procedure is \fBTCL_OK\fR, or \fBTCL_ERROR\fR if the \fIdictPtr\fR cannot be
converted to a dictionary.
converted to a dictionary or if \fIsizePtr\fR points to a variable of type
\fBint\fR and the dict contains more than 2**31 key/value pairs.
.PP
\fBTcl_DictObjFirst\fR commences an iteration across all the key/value
pairs in the given dictionary, placing the key and value in the
variables pointed to by the \fIkeyPtrPtr\fR and \fIvaluePtrPtr\fR
arguments (which may be NULL to indicate that the caller is
uninterested in they key or variable respectively.)  The next
key/value pair in the dictionary may be retrieved with
186
187
188
189
190
191
192



































































193
194
195
196
197
198
199
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







first) that acts as a path to the key/value pair to be affected.  Note
that there is no corresponding operation for reading a value for a
path as this is easy to construct from repeated use of
\fBTcl_DictObjGet\fR. With \fBTcl_DictObjPutKeyList\fR, nested
dictionaries are created for non-terminal keys where they do not
already exist. With \fBTcl_DictObjRemoveKeyList\fR, all non-terminal
keys must exist and have dictionaries as their values.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
\fBTcl_NewDictObj\fR always returns a zero-reference object, much like
\fBTcl_NewObj\fR.
.PP
\fBTcl_DictObjPut\fR does not modify the reference count of its \fIdictPtr\fR
argument, but does require that the object be unshared.  If
\fBTcl_DictObjPut\fR returns \fBTCL_ERROR\fR it does not manipulate any
reference counts; but if it returns \fBTCL_OK\fR then it definitely increments
the reference count of \fIvaluePtr\fR and may increment the reference count of
\fIkeyPtr\fR; the latter case happens exactly when the key did not previously
exist in the dictionary.  Note however that this function may set the
interpreter result; if that is the only place that is holding a reference to
an object, it will be deleted.
.PP
\fBTcl_DictObjGet\fR only reads from its \fIdictPtr\fR and \fIkeyPtr\fR
arguments, and does not manipulate their reference counts at all.  If the
\fIvaluePtrPtr\fR argument is not set to NULL (and the function doesn't return
\fBTCL_ERROR\fR), it will be set to a value with a reference count of at least
1, with a reference owned by the dictionary.  Note however that this function
may set the interpreter result; if that is the only place that is holding a
reference to an object, it will be deleted.
.PP
\fBTcl_DictObjRemove\fR does not modify the reference count of its
\fIdictPtr\fR argument, but does require that the object be unshared. It does
not manipulate the reference count of its \fIkeyPtr\fR argument at all.  Note
however that this function may set the interpreter result; if that is the only
place that is holding a reference to an object, it will be deleted.
.PP
\fBTcl_DictObjSize\fR does not modify the reference count of its \fIdictPtr\fR
argument; it only reads.  Note however that this function may set the
interpreter result; if that is the only place that is holding a reference to
the dictionary object, it will be deleted.
.PP
\fBTcl_DictObjFirst\fR does not modify the reference count of its
\fIdictPtr\fR argument; it only reads. The variables given by the
\fIkeyPtrPtr\fR and \fIvaluePtrPtr\fR arguments (if not NULL) will be updated
to contain references to the relevant values in the dictionary; their
reference counts will be at least 1 (due to the dictionary holding a reference
to them). It may also manipulate internal references; these are not exposed to
user code, but require a matching \fBTcl_DictObjDone\fR call.  Note however
that this function may set the interpreter result; if that is the only place
that is holding a reference to the dictionary object, it will be deleted.
.PP
Similarly for \fBTcl_DictObjNext\fR; the variables given by the
\fIkeyPtrPtr\fR and \fIvaluePtrPtr\fR arguments (if not NULL) will be updated
to contain references to the relevant values in the dictionary; their
reference counts will be at least 1 (due to the dictionary holding a reference
to them).
.PP
\fBTcl_DictObjDone\fR does not manipulate (user-visible) reference counts.
.PP
\fBTcl_DictObjPutKeyList\fR is similar to \fBTcl_DictObjPut\fR; it does not
modify the reference count of its \fIdictPtr\fR argument, but does require
that the object be unshared. It may increment the reference count of any value
passed in the \fIkeyv\fR argument, and will increment the reference count of
the \fIvaluePtr\fR argument on success. It is recommended that values passed
via \fIkeyv\fR and \fIvaluePtr\fR do not have zero reference counts.  Note
however that this function may set the interpreter result; if that is the only
place that is holding a reference to an object, it will be deleted.
.PP
\fBTcl_DictObjRemoveKeyList\fR is similar to \fBTcl_DictObjRemove\fR; it does
not modify the reference count of its \fIdictPtr\fR argument, but does require
that the object be unshared, and does not modify the reference counts of any
of the values passed in the \fIkeyv\fR argument.  Note however that this
function may set the interpreter result; if that is the only place that is
holding a reference to an object, it will be deleted.
.SH EXAMPLE
Using the dictionary iteration interface to search determine if there
is a key that maps to itself:
.PP
.CS
Tcl_DictSearch search;
Tcl_Obj *key, *value;

Changes to doc/DoOneEvent.3.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26







+







Tcl_DoOneEvent \- wait for events and invoke event handlers
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_DoOneEvent\fR(\fIflags\fR)
.fi
.SH ARGUMENTS
.AS int flags
.AP int flags in
This parameter is normally zero.  It may be an OR-ed combination
of any of the following flag bits:
\fBTCL_WINDOW_EVENTS\fR, \fBTCL_FILE_EVENTS\fR,
\fBTCL_TIMER_EVENTS\fR, \fBTCL_IDLE_EVENTS\fR, \fBTCL_ALL_EVENTS\fR,
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
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







-
-
+

-
-
+

-
-
+

-
-
+

-
-
+


-
-
+







The normal return value is 1 to signify that some event
was processed (see below for other alternatives).
.PP
If the \fIflags\fR argument to \fBTcl_DoOneEvent\fR is non-zero,
it restricts the kinds of events that will be processed by
\fBTcl_DoOneEvent\fR.
\fIFlags\fR may be an OR-ed combination of any of the following bits:
.TP 27
\fBTCL_WINDOW_EVENTS\fR \-
.IP \fBTCL_WINDOW_EVENTS\fR
Process window system events.
.TP 27
\fBTCL_FILE_EVENTS\fR \-
.IP \fBTCL_FILE_EVENTS\fR
Process file events.
.TP 27
\fBTCL_TIMER_EVENTS\fR \-
.IP \fBTCL_TIMER_EVENTS\fR
Process timer events.
.TP 27
\fBTCL_IDLE_EVENTS\fR \-
.IP \fBTCL_IDLE_EVENTS\fR
Process idle callbacks.
.TP 27
\fBTCL_ALL_EVENTS\fR \-
.IP \fBTCL_ALL_EVENTS\fR
Process all kinds of events:  equivalent to OR-ing together all of the
above flags or specifying none of them.
.TP 27
\fBTCL_DONT_WAIT\fR \-
.IP \fBTCL_DONT_WAIT\fR
Do not sleep:  process only events that are ready at the time of the
call.
.LP
If any of the flags \fBTCL_WINDOW_EVENTS\fR, \fBTCL_FILE_EVENTS\fR,
\fBTCL_TIMER_EVENTS\fR, or \fBTCL_IDLE_EVENTS\fR is set, then the only
events that will be considered are those for which flags are set.
Setting none of these flags is equivalent to the value

Changes to doc/DoWhenIdle.3.

13
14
15
16
17
18
19

20
21
22
23
24

25
26
27
28
29
30
31
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32







+




-
+







.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_DoWhenIdle\fR(\fIproc, clientData\fR)
.sp
\fBTcl_CancelIdleCall\fR(\fIproc, clientData\fR)
.fi
.SH ARGUMENTS
.AS Tcl_IdleProc clientData
.AP Tcl_IdleProc *proc in
Procedure to invoke.
.AP coid *clientData in
.AP void *clientData in
Arbitrary one-word value to pass to \fIproc\fR.
.BE
.SH DESCRIPTION
.PP
\fBTcl_DoWhenIdle\fR arranges for \fIproc\fR to be invoked
when the application becomes idle.  The application is
considered to be idle when \fBTcl_DoOneEvent\fR has been

Changes to doc/DoubleObj.3.

16
17
18
19
20
21
22

23
24
25
26
27
28
29
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30







+







Tcl_Obj *
\fBTcl_NewDoubleObj\fR(\fIdoubleValue\fR)
.sp
\fBTcl_SetDoubleObj\fR(\fIobjPtr, doubleValue\fR)
.sp
int
\fBTcl_GetDoubleFromObj\fR(\fIinterp, objPtr, doublePtr\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp doubleValue in/out
.AP double doubleValue in
A double-precision floating-point value used to initialize or set a Tcl value.
.AP Tcl_Obj *objPtr in/out
For \fBTcl_SetDoubleObj\fR, this points to the value in which to store a
double value.
54
55
56
57
58
59
60












61
62
63
64


55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

77
78







+
+
+
+
+
+
+
+
+
+
+
+



-
+
+
Tcl value \fIobjPtr\fR.  If the attempt succeeds, then \fBTCL_OK\fR is
returned, and the double value is written to the storage pointed to by
\fIdoublePtr\fR.  If the attempt fails, then \fBTCL_ERROR\fR is returned,
and if \fIinterp\fR is non-NULL, an error message is left in \fIinterp\fR.
The \fBTcl_ObjType\fR of \fIobjPtr\fR may be changed to make subsequent
calls to \fBTcl_GetDoubleFromObj\fR more efficient.
'\" TODO: add discussion of treatment of NaN value
.SH "REFERENCE COUNT MANAGEMENT"
.PP
\fBTcl_NewDoubleObj\fR always returns a zero-reference object, much
like \fBTcl_NewObj\fR.
.PP
\fBTcl_SetDoubleObj\fR does not modify the reference count of its
\fIobjPtr\fR argument, but does require that the object be unshared.
.PP
\fBTcl_GetDoubleFromObj\fR does not modify the reference count of its
\fIobjPtr\fR argument; it only reads. Note however that this function
may set the interpreter result; if that is the only place that
is holding a reference to the object, it will be deleted.
.SH "SEE ALSO"
Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_GetObjResult
.SH KEYWORDS
double, double value, double type, internal representation, value, value type, string representation
double, double value, double type, internal representation, value, value type,
string representation

Changes to doc/DumpActiveMemory.3.

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
30
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

-
-
+
+














-


-

-
+







'\"
'\" Copyright (c) 1992-1999 Karl Lehenbauer and Mark Diekhans.
'\" Copyright (c) 2000 by Scriptics Corporation.
'\" Copyright (c) 1992-1999 Karl Lehenbauer & Mark Diekhans.
'\" Copyright (c) 2000 Scriptics Corporation.
'\" All rights reserved.
'\"
.TH "Tcl_DumpActiveMemory" 3 8.1 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_DumpActiveMemory, Tcl_InitMemory, Tcl_ValidateAllMemory \- Validated memory allocation interface
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_DumpActiveMemory\fR(\fIfileName\fR)
.sp
void
\fBTcl_InitMemory\fR(\fIinterp\fR)
.sp
void
\fBTcl_ValidateAllMemory\fR(\fIfileName, line\fR)

.fi
.SH ARGUMENTS
.AS Tcl_Interp *fileName
.AP Tcl_Interp *interp in
Tcl interpreter in which to add commands.
.AP "const char" *fileName in
For \fBTcl_DumpActiveMemory\fR, name of the file to which memory
information will be written.  For \fBTcl_ValidateAllMemory\fR, name of

Changes to doc/Encoding.3.

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
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
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
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










-
+







-








+
+
+



+
+
+











+
+
+






-










+







'\"
'\" Copyright (c) 1997-1998 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_GetEncoding 3 "8.1" Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_GetEncoding, Tcl_FreeEncoding, Tcl_GetEncodingFromObj, Tcl_ExternalToUtfDString, Tcl_ExternalToUtf, Tcl_UtfToExternalDString, Tcl_UtfToExternal, Tcl_GetEncodingName, Tcl_SetSystemEncoding, Tcl_GetEncodingNameFromEnvironment, Tcl_GetEncodingNames, Tcl_CreateEncoding, Tcl_GetEncodingSearchPath, Tcl_SetEncodingSearchPath \- procedures for creating and using encodings
Tcl_GetEncoding, Tcl_FreeEncoding, Tcl_GetEncodingFromObj, Tcl_ExternalToUtfDString, Tcl_ExternalToUtfDStringEx, Tcl_ExternalToUtf, Tcl_UtfToExternalDString, Tcl_UtfToExternalDStringEx, Tcl_UtfToExternal, Tcl_GetEncodingName, Tcl_SetSystemEncoding, Tcl_GetEncodingNameFromEnvironment, Tcl_GetEncodingNames, Tcl_CreateEncoding, Tcl_GetEncodingSearchPath, Tcl_SetEncodingSearchPath \- procedures for creating and using encodings
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Encoding
\fBTcl_GetEncoding\fR(\fIinterp, name\fR)
.sp
void
\fBTcl_FreeEncoding\fR(\fIencoding\fR)
.sp
int
\fBTcl_GetEncodingFromObj\fR(\fIinterp, objPtr, encodingPtr\fR)
.sp
char *
\fBTcl_ExternalToUtfDString\fR(\fIencoding, src, srcLen, dstPtr\fR)
.sp
int
\fBTcl_ExternalToUtfDStringEx\fR(\fIinterp, encoding, src, srcLen, flags, dstPtr, errorIdxPtr\fR)
.sp
char *
\fBTcl_UtfToExternalDString\fR(\fIencoding, src, srcLen, dstPtr\fR)
.sp
int
\fBTcl_UtfToExternalDStringEx\fR(\fIinterp, encoding, src, srcLen, flags, dstPtr, errorIdxPtr\fR)
.sp
int
\fBTcl_ExternalToUtf\fR(\fIinterp, encoding, src, srcLen, flags, statePtr,
                  dst, dstLen, srcReadPtr, dstWrotePtr, dstCharsPtr\fR)
.sp
int
\fBTcl_UtfToExternal\fR(\fIinterp, encoding, src, srcLen, flags, statePtr,
                  dst, dstLen, srcReadPtr, dstWrotePtr, dstCharsPtr\fR)
.sp
const char *
\fBTcl_GetEncodingName\fR(\fIencoding\fR)
.sp
Tcl_Size
\fBTcl_GetEncodingNulLength\fR(\fIencoding\fR)
.sp
int
\fBTcl_SetSystemEncoding\fR(\fIinterp, name\fR)
.sp
const char *
\fBTcl_GetEncodingNameFromEnvironment\fR(\fIbufPtr\fR)
.sp
void
\fBTcl_GetEncodingNames\fR(\fIinterp\fR)
.sp
Tcl_Encoding
\fBTcl_CreateEncoding\fR(\fItypePtr\fR)
.sp
Tcl_Obj *
\fBTcl_GetEncodingSearchPath\fR()
.sp
int
\fBTcl_SetEncodingSearchPath\fR(\fIsearchPath\fR)
.fi
.SH ARGUMENTS
.AS "const Tcl_EncodingType" *dstWrotePtr in/out
.AP Tcl_Interp *interp in
Interpreter to use for error reporting, or NULL if no error reporting is
desired.
.AP "const char" *name in
Name of encoding to load.
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
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







-
+






-
+







-
-
+
+
+
+
+
-
-
-
+
+
+
+







.AP "const char" *src in
For the \fBTcl_ExternalToUtf\fR functions, an array of bytes in the
specified encoding that are to be converted to UTF-8.  For the
\fBTcl_UtfToExternal\fR function, an array of
UTF-8 characters to be converted to the specified encoding.
.AP "const TCHAR" *tsrc in
An array of Windows TCHAR characters to convert to UTF-8.
.AP size_t srcLen in
.AP Tcl_Size srcLen in
Length of \fIsrc\fR or \fItsrc\fR in bytes.  If the length is negative, the
encoding-specific length of the string is used.
.AP Tcl_DString *dstPtr out
Pointer to an uninitialized or free \fBTcl_DString\fR in which the converted
result will be stored.
.AP int flags in
Various flag bits OR-ed together.
This is a bit mask passed in to control the operation of the encoding functions.
\fBTCL_ENCODING_START\fR signifies that the
source buffer is the first block in a (potentially multi-block) input
stream, telling the conversion routine to reset to an initial state and
perform any initialization that needs to occur before the first byte is
converted. \fBTCL_ENCODING_END\fR signifies that the source buffer is the last
block in a (potentially multi-block) input stream, telling the conversion
routine to perform any finalization that needs to occur after the last
byte is converted and then to reset to an initial state.
\fBTCL_ENCODING_STOPONERROR\fR signifies that the conversion routine should
byte is converted and then to reset to an initial state. The
\fBTCL_PROFILE_*\fR bits defined in the \fBPROFILES\fR section below
control the encoding profile to be used for dealing with invalid data or
other errors in the encoding transform.
The flag \fBTCL_ENCODING_STOPONERROR\fR has no effect,
return immediately upon reading a source character that does not exist in
the target encoding; otherwise a default fallback character will
automatically be substituted.
it only has meaning in Tcl 8.x.
.PP
Some flags bits may not be usable with some functions as noted in the
function descriptions below.
.AP Tcl_EncodingState *statePtr in/out
Used when converting a (generally long or indefinite length) byte stream
in a piece-by-piece fashion.  The conversion routine stores its current
state in \fI*statePtr\fR after \fIsrc\fR (the buffer containing the
current piece) has been converted; that state information must be passed
back when converting the next piece of the stream so the conversion
routine knows what state it was in when it left off at the end of the
118
119
120
121
122
123
124



125
126
127
128
129
130
131
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146







+
+
+







a problem converting some source characters.  May be NULL.
.AP int *dstWrotePtr out
Filled with the number of bytes that were actually stored in the output
buffer as a result of the conversion.  May be NULL.
.AP int *dstCharsPtr out
Filled with the number of characters that correspond to the number of bytes
stored in the output buffer.  May be NULL.
.AP Tcl_Size *errorIdxPtr out
Filled with the index of the byte or character that caused the encoding transform
to fail. May be NULL.
.AP Tcl_DString *bufPtr out
Storage for the prescribed system encoding name.
.AP "const Tcl_EncodingType" *typePtr in
Structure that defines a new type of encoding.
.AP Tcl_Obj *searchPath in
List of filesystem directories in which to search for encoding data files.
.AP "const char" *path in
191
192
193
194
195
196
197





















198
199
200
201
202
203
204
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







\fBTcl_ExternalToUtfDString\fR converts a source buffer \fIsrc\fR from the
specified \fIencoding\fR into UTF-8.  The converted bytes are stored in
\fIdstPtr\fR, which is then null-terminated.  The caller should eventually
call \fBTcl_DStringFree\fR to free any information stored in \fIdstPtr\fR.
When converting, if any of the characters in the source buffer cannot be
represented in the target encoding, a default fallback character will be
used.  The return value is a pointer to the value stored in the DString.
.PP
\fBTcl_ExternalToUtfDStringEx\fR is a more flexible version of older
\fBTcl_ExternalToUtfDString\fR function. It takes three additional parameters,
\fBinterp\fR, \fBflags\fR and \fBerrorIdxPtr\fR. The \fBflags\fR parameter may
be used to specify the profile to be used for the transform. The
\fBTCL_ENCODING_START\fR and \fBTCL_ENCODING_END\fR bits in \fBflags\fR are
ignored as the function assumes the entire source string to be decoded is passed
into the function. On success, the function returns \fBTCL_OK\fR with the
converted string stored in \fB*dstPtr\fR. For errors \fIother than conversion
errors\fR, such as invalid flags, the function returns \fBTCL_ERROR\fR with an
error message in \fBinterp\fR if it is not NULL.
For conversion errors, \fBTcl_ExternalToUtfDStringEx\fR returns one
of the \fBTCL_CONVERT_*\fR errors listed below for \fBTcl_ExternalToUtf\fR.
When one of these conversion errors is returned, an error message is stored
in \fBinterp\fR only if \fBerrorIdxPtr\fR is NULL. Otherwise, no error message
is stored as the function expects the caller is interested the decoded data
up to that point and not treating this as an immediate error condition.
The index of the error location is stored in \fB*errorIdxPtr\fR.
.PP
The caller must call \fBTcl_DStringFree\fR to free up the \fB*dstPtr\fR resources
irrespective of the return value from the function.
.PP
\fBTcl_ExternalToUtf\fR converts a source buffer \fIsrc\fR from the specified
\fIencoding\fR into UTF-8.  Up to \fIsrcLen\fR bytes are converted from the
source buffer and up to \fIdstLen\fR converted bytes are stored in \fIdst\fR.
In all cases, \fI*srcReadPtr\fR is filled with the number of bytes that were
successfully converted from \fIsrc\fR and \fI*dstWrotePtr\fR is filled with
the corresponding number of bytes that were stored in \fIdst\fR.  The return
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
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







-
-
+
+



-
+











+
+
+
+
+
+
+
+
+
+














+
+
+







The last few bytes in the source buffer were the beginning of a multibyte
sequence, but more bytes were needed to complete this sequence.  A
subsequent call to the conversion routine should pass a buffer containing
the unconverted bytes that remained in \fIsrc\fR plus some further bytes
from the source stream to properly convert the formerly split-up multibyte
sequence.
.IP \fBTCL_CONVERT_SYNTAX\fR 29
The source buffer contained an invalid character sequence.  This may occur
if the input stream has been damaged or if the input encoding method was
The source buffer contained an invalid byte or character sequence.  This may
occur if the input stream has been damaged or if the input encoding method was
misidentified.
.IP \fBTCL_CONVERT_UNKNOWN\fR 29
The source buffer contained a character that could not be represented in
the target encoding and \fBTCL_ENCODING_STOPONERROR\fR was specified.
the target encoding.
.RE
.LP
\fBTcl_UtfToExternalDString\fR converts a source buffer \fIsrc\fR from UTF-8
into the specified \fIencoding\fR.  The converted bytes are stored in
\fIdstPtr\fR, which is then terminated with the appropriate encoding-specific
null.  The caller should eventually call \fBTcl_DStringFree\fR to free any
information stored in \fIdstPtr\fR.  When converting, if any of the
characters in the source buffer cannot be represented in the target
encoding, a default fallback character will be used.  The return value is
a pointer to the value stored in the DString.
.PP
\fBTcl_UtfToExternalDStringEx\fR is an enhanced version of
\fBTcl_UtfToExternalDString\fR that transforms UTF-8 encoded source data to a
specified \fIencoding\fR. Except for the direction of the transform, the
parameters and return values are identical to those of
\fBTcl_ExternalToUtfDStringEx\fR. See
that function above for details about the same.
.PP
Irrespective of the return code from the function, the caller must free
resources associated with \fB*dstPtr\fR when the function returns.
.PP
\fBTcl_UtfToExternal\fR converts a source buffer \fIsrc\fR from UTF-8 into
the specified \fIencoding\fR.  Up to \fIsrcLen\fR bytes are converted from
the source buffer and up to \fIdstLen\fR converted bytes are stored in
\fIdst\fR.  In all cases, \fI*srcReadPtr\fR is filled with the number of
bytes that were successfully converted from \fIsrc\fR and \fI*dstWrotePtr\fR
is filled with the corresponding number of bytes that were stored in
\fIdst\fR.  The return values are the same as the return values for
\fBTcl_ExternalToUtf\fR.
.PP
\fBTcl_GetEncodingName\fR is roughly the inverse of \fBTcl_GetEncoding\fR.
Given an \fIencoding\fR, the return value is the \fIname\fR argument that
was used to create the encoding.  The string returned by
\fBTcl_GetEncodingName\fR is only guaranteed to persist until the
\fIencoding\fR is deleted.  The caller must not modify this string.
.PP
\fBTcl_GetEncodingNulLength\fR returns the length of the terminating
nul byte sequence for strings in the specified encoding.
.PP
\fBTcl_SetSystemEncoding\fR sets the default encoding that should be used
whenever the user passes a NULL value for the \fIencoding\fR argument to
any of the other encoding functions.  If \fIname\fR is NULL, the system
encoding is reset to the default system encoding, \fBbinary\fR.  If the
name did not refer to any known or loadable encoding, \fBTCL_ERROR\fR is
returned and an error message is left in \fIinterp\fR.  Otherwise, this
287
288
289
290
291
292
293
294

295
296
297
298
299
300

301
302
303
304
305
306
307
336
337
338
339
340
341
342

343
344
345
346
347
348

349
350
351
352
353
354
355
356







-
+





-
+







encoding procedures.
.PP
The \fItypePtr\fR argument to \fBTcl_CreateEncoding\fR contains information
about the name of the encoding and the procedures that will be called to
convert between this encoding and UTF-8.  It is defined as follows:
.PP
.CS
typedef struct Tcl_EncodingType {
typedef struct {
    const char *\fIencodingName\fR;
    Tcl_EncodingConvertProc *\fItoUtfProc\fR;
    Tcl_EncodingConvertProc *\fIfromUtfProc\fR;
    Tcl_EncodingFreeProc *\fIfreeProc\fR;
    void *\fIclientData\fR;
    int \fInullSize\fR;
    Tcl_Size \fInullSize\fR;
} \fBTcl_EncodingType\fR;
.CE
.PP
The \fIencodingName\fR provides a string name for the encoding, by
which it can be referred in other procedures such as
\fBTcl_GetEncoding\fR.  The \fItoUtfProc\fR refers to a callback
procedure to invoke to convert text from this encoding into UTF-8.
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
542
543
544
545
546
547
548







549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566

567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599







-
-
-
-
-
-
-
+
+
+
+
+
+
+











-
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


.PP
.CS
.ta 1.5i
# Encoding file: iso2022-jp, escape-driven
E
init		{}
final		{}
iso8859-1	\ex1b(B
jis0201		\ex1b(J
jis0208		\ex1b$@
jis0208		\ex1b$B
jis0212		\ex1b$(D
gb2312		\ex1b$A
ksc5601		\ex1b$(C
iso8859-1	\ex1B(B
jis0201		\ex1B(J
jis0208		\ex1B$@
jis0208		\ex1B$B
jis0212		\ex1B$(D
gb2312		\ex1B$A
ksc5601		\ex1B$(C
.CE
.PP
In the file, the first column represents an option and the second column
is the associated value.  \fBinit\fR is a string to emit or expect before
the first character is converted, while \fBfinal\fR is a string to emit
or expect after the last character.  All other options are names of
table-based encodings; the associated value is the escape-sequence that
marks that encoding.  Tcl syntax is used for the values; in the above
example, for instance,
.QW \fB{}\fR
represents the empty string and
.QW \fB\ex1b\fR
.QW \fB\ex1B\fR
represents character 27.
.PP
When \fBTcl_GetEncoding\fR encounters an encoding \fIname\fR that has not
been loaded, it attempts to load an encoding file called \fIname\fB.enc\fR
from the \fBencoding\fR subdirectory of each directory that Tcl searches
for its script library.  If the encoding file exists, but is
malformed, an error message will be left in \fIinterp\fR.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
\fBTcl_GetEncodingFromObj\fR does not modify the reference count of its
\fIobjPtr\fR argument; it only reads. Note however that this function may set
the interpreter result; if that is the only place that is holding a reference
to the object, it will be deleted.
.PP
\fBTcl_GetEncodingSearchPath\fR returns an object with a reference count of at
least 1.
.SH "PROFILES"
Encoding profiles define the manner in which errors in the encoding transforms
are handled by the encoding functions. An application can specify the profile
to be used by OR-ing the \fBflags\fR parameter passed to the function
with at most one of \fBTCL_ENCODING_PROFILE_TCL8\fR,
\fBTCL_ENCODING_PROFILE_STRICT\fR or \fBTCL_ENCODING_PROFILE_REPLACE\fR.
These correspond to the \fBtcl8\fR, \fBstrict\fR and \fBreplace\fR profiles
respectively. If none are specified, a version-dependent default profile is used.
For Tcl 9.0, the default profile is \fBstrict\fR.
.PP
For details about profiles, see the \fBPROFILES\fR section in
the documentation of the \fBencoding\fR command.
.SH "SEE ALSO"
encoding(n)
.SH KEYWORDS
utf, encoding, convert

Changes to doc/Ensemble.3.

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
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







+













-
+






-
+







\fBTcl_GetEnsembleUnknownHandler\fR(\fIinterp, token, listObjPtr\fR)
.sp
int
\fBTcl_SetEnsembleUnknownHandler\fR(\fIinterp, token, listObj\fR)
.sp
int
\fBTcl_GetEnsembleNamespace\fR(\fIinterp, token, namespacePtrPtr\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Namespace **namespacePtrPtr in/out
.AP Tcl_Interp *interp in/out
The interpreter in which the ensemble is to be created or found. Also
where error result messages are written. The functions whose names
start with \fBTcl_GetEnsemble\fR may have a NULL for the \fIinterp\fR,
but all other functions must not.
.AP "const char" *name in
The name of the ensemble command to be created.
.AP Tcl_Namespace *namespacePtr in
The namespace to which the ensemble command is to be bound, or NULL
for the current namespace.
.AP int ensFlags in
An ORed set of flag bits describing the basic configuration of the
An OR'ed set of flag bits describing the basic configuration of the
ensemble. Currently only one bit has meaning, \fBTCL_ENSEMBLE_PREFIX\fR,
which is present when the ensemble command should also match
unambiguous prefixes of subcommands.
.AP Tcl_Obj *cmdNameObj in
A value holding the name of the ensemble command to look up.
.AP int flags in
An ORed set of flag bits controlling the behavior of
An OR'ed set of flag bits controlling the behavior of
\fBTcl_FindEnsemble\fR. Currently only \fBTCL_LEAVE_ERR_MSG\fR is supported.
.AP Tcl_Command token in
A normal command token that refers to an ensemble command, or which
you wish to use for testing as an ensemble command in \fBTcl_IsEnsemble\fR.
.AP int *ensFlagsPtr out
Pointer to a variable into which to write the current ensemble flag
bits; currently only the bit \fBTCL_ENSEMBLE_PREFIX\fR is defined.
157
158
159
160
161
162
163

164
165
166
167
168
169
170
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172







+







ensemble) and the dictionary obtained from
\fBTcl_GetEnsembleMappingDict\fR should always be treated as immutable
even if it is unshared.
All command names in prefixes set via \fBTcl_SetEnsembleMappingDict\fR
must be fully qualified.
.TP
\fBformal pre-subcommand parameter list\fR (read-write)
.
A list of formal parameter names (the names only being used when generating
error messages) that come at invocation of the ensemble between the name of
the ensemble and the subcommand argument. NULL (the default) is equivalent to
the empty list. May be read and written using
\fBTcl_GetEnsembleParameterList\fR and \fBTcl_SetEnsembleParameterList\fR
respectively. The result of both of those functions is a Tcl result code
(\fBTCL_OK\fR, or \fBTCL_ERROR\fR if the token does not refer to an
205
206
207
208
209
210
211





















212
213
214
215
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




.
The namespace to which the ensemble is bound; when the namespace is
deleted, so too will the ensemble, and this namespace is also the
namespace whose list of exported commands is used if both the mapping
dictionary and the subcommand list properties are NULL. May be read
using \fBTcl_GetEnsembleNamespace\fR which returns a Tcl result code
(\fBTCL_OK\fR, or \fBTCL_ERROR\fR if the token does not refer to an ensemble).
.SH "REFERENCE COUNT MANAGEMENT"
.PP
\fBTcl_FindEnsemble\fR does not modify the reference count of its
\fIcmdNameObj\fR argument; it only reads. Note however that this function may
set the interpreter result; if that is the only place that is holding a
reference to the object, it will be deleted.
.PP
The ensemble property getters (\fBTcl_GetEnsembleMappingDict\fR,
\fBTcl_GetEnsembleParameterList\fR, \fBTcl_GetEnsembleSubcommandList\fR, and
\fBTcl_GetEnsembleUnknownHandler\fR) do not manipulate the reference count of
the values they provide out; if those are non-NULL, they will have a reference
count of at least 1.  Note that these functions may set the interpreter
result.
.PP
The ensemble property setters (\fBTcl_SetEnsembleMappingDict\fR,
\fBTcl_SetEnsembleParameterList\fR, \fBTcl_SetEnsembleSubcommandList\fR, and
\fBTcl_SetEnsembleUnknownHandler\fR) will increment the reference count of the
new value of the property they are given if they succeed (and decrement the
reference count of the old value of the property, if relevant). If the
property setters return \fBTCL_ERROR\fR, the reference count of the Tcl_Obj
argument is left unchanged.
.SH "SEE ALSO"
namespace(n), Tcl_DeleteCommandFromToken(3)
.SH KEYWORDS
command, ensemble

Changes to doc/Environment.3.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25







+







Tcl_PutEnv \- procedures to manipulate the environment
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_PutEnv\fR(\fIassignment\fR)
.fi
.SH ARGUMENTS
.AS "const char" *assignment
.AP "const char" *assignment in
Info about environment variable in the format
.QW \fINAME\fB=\fIvalue\fR .
The \fIassignment\fR argument is in the system encoding.
.BE

Changes to doc/Eval.3.

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
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







-
+
+








-
+



-
-
+
+










-
+







int
\fBTcl_GlobalEval\fR(\fIinterp, script\fR)
.sp
int
\fBTcl_GlobalEvalObj\fR(\fIinterp, objPtr\fR)
.sp
int
\fBTcl_VarEval\fR(\fIinterp, part, part, ... \fB(char *) NULL\fR)
\fBTcl_VarEval\fR(\fIinterp, part, part, ... \fB(char *)NULL\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp **termPtr
.AP Tcl_Interp *interp in
Interpreter in which to execute the script.  The interpreter's result is
modified to hold the result or error message from the script.
.AP Tcl_Obj *objPtr in
A Tcl value containing the script to execute.
.AP int flags in
ORed combination of flag bits that specify additional options.
OR'ed combination of flag bits that specify additional options.
\fBTCL_EVAL_GLOBAL\fR and \fBTCL_EVAL_DIRECT\fR are currently supported.
.AP "const char" *fileName in
Name of a file containing a Tcl script.
.AP int objc in
The number of values in the array pointed to by \fIobjPtr\fR;
.AP Tcl_Size objc in
The number of values in the array pointed to by \fIobjv\fR;
this is also the number of words in the command.
.AP Tcl_Obj **objv in
Points to an array of pointers to values; each value holds the
value of a single word in the command to execute.
.AP int numBytes in
The number of bytes in \fIscript\fR, not including any
null terminating character.  If \-1, then all characters up to the
first null byte are used.
.AP "const char" *script in
Points to first byte of script to execute (null-terminated and UTF-8).
.AP char *part in
.AP "const char" *part in
String forming part of a Tcl script.
.BE

.SH DESCRIPTION
.PP
The procedures described here are invoked to execute Tcl scripts in
various forms.
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
90
91
92
93
94
95
96

97
98
99
100

101


102
103
104

105
106
107
108
109
110
111
112







-
+



-
+
-
-



-
+







.PP
\fBTcl_EvalFile\fR reads the file given by \fIfileName\fR and evaluates
its contents as a Tcl script.  It returns the same information as
\fBTcl_EvalObjEx\fR.
If the file could not be read then a Tcl error is returned to describe
why the file could not be read.
The eofchar for files is
.QW \e32
.QW \ex1A
(^Z) for all platforms. If you require a
.QW ^Z
in code for string comparison, you can use
.QW \e032
.QW \ex1A ,
or
.QW \eu001a ,
which will be safely substituted by the Tcl interpreter into
.QW ^Z .
.PP
\fBTcl_EvalObjv\fR executes a single pre-parsed command instead of a
\fBTcl_EvalObjv\fR executes a single preparsed command instead of a
script.  The \fIobjc\fR and \fIobjv\fR arguments contain the values
of the words for the Tcl command, one word in each value in
\fIobjv\fR.  \fBTcl_EvalObjv\fR evaluates the command and returns
a completion code and result just like \fBTcl_EvalObjEx\fR.
The caller of \fBTcl_EvalObjv\fR has to manage the reference count of the
elements of \fIobjv\fR, insuring that the values are valid until
\fBTcl_EvalObjv\fR returns.
135
136
137
138
139
140
141
142
143


144
145
146
147

148
149
150
151
152
153
154
134
135
136
137
138
139
140


141
142
143
144
145

146
147
148
149
150
151
152
153







-
-
+
+



-
+







equivalent to using the \fBTCL_EVAL_GLOBAL\fR flag (see below).
.PP
\fBTcl_VarEval\fR takes any number of string arguments
of any length, concatenates them into a single string,
then calls \fBTcl_Eval\fR to execute that string as a Tcl command.
It returns the result of the command and also modifies
the interpreter result in the same way as \fBTcl_Eval\fR.
The last argument to \fBTcl_VarEval\fR must be NULL to indicate the end
of arguments.  \fBTcl_VarEval\fR is now deprecated.
The last argument to \fBTcl_VarEval\fR must be (char *)NULL to indicate the end
of arguments.

.SH "FLAG BITS"
.PP
Any ORed combination of the following values may be used for the
Any OR'ed combination of the following values may be used for the
\fIflags\fR argument to procedures such as \fBTcl_EvalObjEx\fR:
.TP 23
\fBTCL_EVAL_DIRECT\fR
.
This flag is only used by \fBTcl_EvalObjEx\fR; it is ignored by
other procedures.  If this flag bit is set, the script is not
compiled to bytecodes; instead it is executed directly
186
187
188
189
190
191
192














193
194
195
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208







+
+
+
+
+
+
+
+
+
+
+
+
+
+



invocation for \fIinterp\fR,
it converts the return code to \fBTCL_ERROR\fR
and sets \fIinterp\fR's result to an error message indicating that
the \fBreturn\fR, \fBbreak\fR, or \fBcontinue\fR command was
invoked in an inappropriate place.
This means that top-level applications should never see a return code
from \fBTcl_EvalObjEx\fR other than \fBTCL_OK\fR or \fBTCL_ERROR\fR.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
\fBTcl_EvalObjEx\fR and \fBTcl_GlobalEvalObj\fR both increment and
decrement the reference count of their \fIobjPtr\fR argument; you must
not pass them any value with a reference count of zero. They also
manipulate the interpreter result; you must not count on the
interpreter result to hold the reference count of any value over
these calls.
.PP
\fBTcl_EvalObjv\fR may increment and decrement the reference count of
any value passed via its \fIobjv\fR argument; you must not pass any
value with a reference count of zero. This function also manipulates
the interpreter result; you must not count on the interpreter result
to hold the reference count of any value over this call.

.SH KEYWORDS
execute, file, global, result, script, value

Changes to doc/Exit.3.

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
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







+




-
-
+
+
















-
+

-
+

-
+


-
+







.sp
\fBTcl_CreateThreadExitHandler\fR(\fIproc, clientData\fR)
.sp
\fBTcl_DeleteThreadExitHandler\fR(\fIproc, clientData\fR)
.sp
Tcl_ExitProc *
\fBTcl_SetExitProc\fR(\fIproc\fR)
.fi
.SH ARGUMENTS
.AS Tcl_ExitProc clientData
.AP int status  in
Provides information about why the application or thread exited.
Exact meaning may
be platform-specific.  0 usually means a normal exit, any nonzero value
Exact meaning may be platform-specific.
0 usually means a normal exit, any nonzero value
usually means that an error occurred.
.AP Tcl_ExitProc *proc in
Procedure to invoke before exiting application, or (for
\fBTcl_SetExitProc\fR) NULL to uninstall the current application exit
procedure.
.AP void *clientData in
Arbitrary one-word value to pass to \fIproc\fR.
.BE

.SH DESCRIPTION
.PP
The procedures described here provide a graceful mechanism to end the
execution of a \fBTcl\fR application. Exit handlers are invoked to cleanup the
application's state before ending the execution of \fBTcl\fR code.
.PP
Invoke \fBTcl_Exit\fR to end a \fBTcl\fR application and to exit from this
process. This procedure is invoked by the \fBexit\fR command, and can be
process. This procedure is invoked by the \fBexit\fR Tcl command, and can be
invoked anyplace else to terminate the application.
No-one should ever invoke the \fBexit\fR system procedure directly;  always
No-one should ever invoke the \fBexit()\fR system call directly;  always
invoke \fBTcl_Exit\fR instead, so that it can invoke exit handlers.
Note that if other code invokes \fBexit\fR system procedure directly, or
Note that if other code invokes \fBexit()\fR system call directly, or
otherwise causes the application to terminate without calling
\fBTcl_Exit\fR, the exit handlers will not be run.
\fBTcl_Exit\fR internally invokes the \fBexit\fR system call, thus it never
\fBTcl_Exit\fR internally invokes the \fBexit()\fR system call, thus it never
returns control to its caller.
If an application exit handler has been installed (see
\fBTcl_SetExitProc\fR), that handler is invoked with an argument
consisting of the exit status (cast to void *); the application
exit handler should not return control to Tcl.
.PP
\fBTcl_Finalize\fR is similar to \fBTcl_Exit\fR except that it does not
135
136
137
138
139
140
141
142


136
137
138
139
140
141
142

143
144







-
+
+
invoked will be the exit status code (as passed to \fBTcl_Exit\fR)
cast to a void *value.
.PP
\fBTcl_SetExitProc\fR can not be used in stub-enabled extensions.
.SH "SEE ALSO"
exit(n)
.SH KEYWORDS
abort, callback, cleanup, dynamic loading, end application, exit, unloading, thread
abort, callback, cleanup, dynamic loading, end application, exit, unloading,
thread

Changes to doc/ExprLong.3.

21
22
23
24
25
26
27

28
29
30
31
32
33
34
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35







+







\fBTcl_ExprDouble\fR(\fIinterp, expr, doublePtr\fR)
.sp
int
\fBTcl_ExprBoolean\fR(\fIinterp, expr, booleanPtr\fR)
.sp
int
\fBTcl_ExprString\fR(\fIinterp, expr\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp *booleanPtr out
.AP Tcl_Interp *interp in
Interpreter in whose context to evaluate \fIexpr\fR.
.AP "const char" *expr in
Expression to be evaluated.
.AP long *longPtr out

Changes to doc/ExprLongObj.3.

20
21
22
23
24
25
26

27
28
29
30
31
32
33
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34







+







\fBTcl_ExprDoubleObj\fR(\fIinterp, objPtr, doublePtr\fR)
.sp
int
\fBTcl_ExprBooleanObj\fR(\fIinterp, objPtr, booleanPtr\fR)
.sp
int
\fBTcl_ExprObj\fR(\fIinterp, objPtr, resultPtrPtr\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp **resultPtrPtr out
.AP Tcl_Interp *interp in
Interpreter in whose context to evaluate \fIobjPtr\fR.
.AP Tcl_Obj *objPtr in
Pointer to a value containing the expression to evaluate.
.AP long *longPtr out
94
95
96
97
98
99
100









101
102
103
104
105
106
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116







+
+
+
+
+
+
+
+
+






.PP
If \fBTcl_ExprObj\fR successfully evaluates the expression,
it stores a pointer to the Tcl value
containing the expression's value at \fI*resultPtrPtr\fR.
In this case, the caller is responsible for calling
\fBTcl_DecrRefCount\fR to decrement the value's reference count
when it is finished with the value.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
\fBTcl_ExprLongObj\fR, \fBTcl_ExprDoubleObj\fR,
\fBTcl_ExprBooleanObj\fR, and \fBTcl_ExprObj\fR all increment and
decrement the reference count of their \fIobjPtr\fR arguments; you
must not pass them any value with a reference count of zero. They also
manipulate the interpreter result; you must not count on the
interpreter result to hold the reference count of any value over these
calls.

.SH "SEE ALSO"
Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean, Tcl_ExprString, Tcl_GetObjResult

.SH KEYWORDS
boolean, double, evaluate, expression, integer, value, string

Changes to doc/FileSystem.3.

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
30
31
32
33
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
30
31
32











-
+













-







'\"
'\" Copyright (c) 2001 Vincent Darley
'\" Copyright (c) 2008-2010 Donal K. Fellows
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Filesystem 3 8.4 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_FSRegister, Tcl_FSUnregister, Tcl_FSData, Tcl_FSMountsChanged, Tcl_FSGetFileSystemForPath, Tcl_FSGetPathType, Tcl_FSCopyFile, Tcl_FSCopyDirectory, Tcl_FSCreateDirectory, Tcl_FSDeleteFile, Tcl_FSRemoveDirectory, Tcl_FSRenameFile, Tcl_FSListVolumes, Tcl_FSEvalFile, Tcl_FSEvalFileEx, Tcl_FSLoadFile, Tcl_FSUnloadFile, Tcl_FSMatchInDirectory, Tcl_FSLink, Tcl_FSLstat, Tcl_FSUtime, Tcl_FSFileAttrsGet, Tcl_FSFileAttrsSet, Tcl_FSFileAttrStrings, Tcl_FSStat, Tcl_FSAccess, Tcl_FSOpenFileChannel, Tcl_FSGetCwd, Tcl_FSChdir, Tcl_FSPathSeparator, Tcl_FSJoinPath, Tcl_FSSplitPath, Tcl_FSEqualPaths, Tcl_FSGetNormalizedPath, Tcl_FSJoinToPath, Tcl_FSConvertToPathType, Tcl_FSGetInternalRep, Tcl_FSGetTranslatedPath, Tcl_FSGetTranslatedStringPath, Tcl_FSNewNativePath, Tcl_FSGetNativePath, Tcl_FSFileSystemInfo, Tcl_GetAccessTimeFromStat, Tcl_GetBlockSizeFromStat, Tcl_GetBlocksFromStat, Tcl_GetChangeTimeFromStat, Tcl_GetDeviceTypeFromStat, Tcl_GetFSDeviceFromStat, Tcl_GetFSInodeFromStat, Tcl_GetGroupIdFromStat, Tcl_GetLinkCountFromStat, Tcl_GetModeFromStat, Tcl_GetModificationTimeFromStat, Tcl_GetSizeFromStat, Tcl_GetUserIdFromStat, Tcl_AllocStatBuf \- procedures to interact with any filesystem
Tcl_FSRegister, Tcl_FSUnregister, Tcl_FSData, Tcl_FSMountsChanged, Tcl_FSGetFileSystemForPath, Tcl_FSGetPathType, Tcl_FSCopyFile, Tcl_FSCopyDirectory, Tcl_FSCreateDirectory, Tcl_FSDeleteFile, Tcl_FSRemoveDirectory, Tcl_FSRenameFile, Tcl_FSListVolumes, Tcl_FSEvalFile, Tcl_FSEvalFileEx, Tcl_FSLoadFile, Tcl_FSUnloadFile, Tcl_FSMatchInDirectory, Tcl_FSLink, Tcl_FSLstat, Tcl_FSUtime, Tcl_FSFileAttrsGet, Tcl_FSFileAttrsSet, Tcl_FSFileAttrStrings, Tcl_FSStat, Tcl_FSAccess, Tcl_FSOpenFileChannel, Tcl_FSGetCwd, Tcl_FSChdir, Tcl_FSPathSeparator, Tcl_FSJoinPath, Tcl_FSSplitPath, Tcl_FSEqualPaths, Tcl_FSGetNormalizedPath, Tcl_FSJoinToPath, Tcl_FSConvertToPathType, Tcl_FSGetInternalRep, Tcl_FSGetTranslatedPath, Tcl_FSGetTranslatedStringPath, Tcl_FSNewNativePath, Tcl_FSGetNativePath, Tcl_FSFileSystemInfo, Tcl_GetAccessTimeFromStat, Tcl_GetBlockSizeFromStat, Tcl_GetBlocksFromStat, Tcl_GetChangeTimeFromStat, Tcl_GetDeviceTypeFromStat, Tcl_GetFSDeviceFromStat, Tcl_GetFSInodeFromStat, Tcl_GetGroupIdFromStat, Tcl_GetLinkCountFromStat, Tcl_GetModeFromStat, Tcl_GetModificationTimeFromStat, Tcl_GetSizeFromStat, Tcl_GetUserIdFromStat, Tcl_AllocStatBuf, Tcl_FSTildeExpand \- procedures to interact with any filesystem
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_FSRegister\fR(\fIclientData, fsPtr\fR)
.sp
int
\fBTcl_FSUnregister\fR(\fIfsPtr\fR)
.sp
void *
\fBTcl_FSData\fR(\fIfsPtr\fR)
.sp
void
\fBTcl_FSMountsChanged\fR(\fIfsPtr\fR)
.sp
const Tcl_Filesystem *
\fBTcl_FSGetFileSystemForPath\fR(\fIpathPtr\fR)
.sp
Tcl_PathType
\fBTcl_FSGetPathType\fR(\fIpathPtr\fR)
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54







-
+







int
\fBTcl_FSCreateDirectory\fR(\fIpathPtr\fR)
.sp
int
\fBTcl_FSDeleteFile\fR(\fIpathPtr\fR)
.sp
int
\fBTcl_FSRemoveDirectory\fR(\fIpathPtr, int recursive, errorPtr\fR)
\fBTcl_FSRemoveDirectory\fR(\fIpathPtr, recursive, errorPtr\fR)
.sp
int
\fBTcl_FSRenameFile\fR(\fIsrcPathPtr, destPathPtr\fR)
.sp
Tcl_Obj *
\fBTcl_FSListVolumes\fR(\fIvoid\fR)
.sp
75
76
77
78
79
80
81
82

83
84
85

86
87
88
89
90
91
92
74
75
76
77
78
79
80

81
82
83

84
85
86
87
88
89
90
91







-
+


-
+







int
\fBTcl_FSLstat\fR(\fIpathPtr, statPtr\fR)
.sp
int
\fBTcl_FSUtime\fR(\fIpathPtr, tval\fR)
.sp
int
\fBTcl_FSFileAttrsGet\fR(\fIinterp, int index, pathPtr, objPtrRef\fR)
\fBTcl_FSFileAttrsGet\fR(\fIinterp, index, pathPtr, objPtrRef\fR)
.sp
int
\fBTcl_FSFileAttrsSet\fR(\fIinterp, int index, pathPtr, Tcl_Obj *objPtr\fR)
\fBTcl_FSFileAttrsSet\fR(\fIinterp, index, pathPtr, objPtr\fR)
.sp
const char *const *
\fBTcl_FSFileAttrStrings\fR(\fIpathPtr, objPtrRef\fR)
.sp
int
\fBTcl_FSStat\fR(\fIpathPtr, statPtr\fR)
.sp
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
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







+
+
+



-
+





-
+


-
+




















-
+


-
+




+





+
+










+
+







.sp
const void *
\fBTcl_FSGetNativePath\fR(\fIpathPtr\fR)
.sp
Tcl_Obj *
\fBTcl_FSFileSystemInfo\fR(\fIpathPtr\fR)
.sp
int
\fBTcl_FSTildeExpand\fR(\fIinterp, pathStr, dsPtr\fR)
.sp
Tcl_StatBuf *
\fBTcl_AllocStatBuf\fR()
.sp
Tcl_WideInt
long long
\fBTcl_GetAccessTimeFromStat\fR(\fIstatPtr\fR)
.sp
unsigned
\fBTcl_GetBlockSizeFromStat\fR(\fIstatPtr\fR)
.sp
Tcl_WideUInt
unsigned long long
\fBTcl_GetBlocksFromStat\fR(\fIstatPtr\fR)
.sp
Tcl_WideInt
long long
\fBTcl_GetChangeTimeFromStat\fR(\fIstatPtr\fR)
.sp
int
\fBTcl_GetDeviceTypeFromStat\fR(\fIstatPtr\fR)
.sp
unsigned
\fBTcl_GetFSDeviceFromStat\fR(\fIstatPtr\fR)
.sp
unsigned
\fBTcl_GetFSInodeFromStat\fR(\fIstatPtr\fR)
.sp
int
\fBTcl_GetGroupIdFromStat\fR(\fIstatPtr\fR)
.sp
int
\fBTcl_GetLinkCountFromStat\fR(\fIstatPtr\fR)
.sp
unsigned
\fBTcl_GetModeFromStat\fR(\fIstatPtr\fR)
.sp
Tcl_WideInt
long long
\fBTcl_GetModificationTimeFromStat\fR(\fIstatPtr\fR)
.sp
Tcl_WideUInt
unsigned long long
\fBTcl_GetSizeFromStat\fR(\fIstatPtr\fR)
.sp
int
\fBTcl_GetUserIdFromStat\fR(\fIstatPtr\fR)
.fi
.SH ARGUMENTS
.AS Tcl_GlobTypeData **srcPathPtr out
.AP "const Tcl_Filesystem" *fsPtr in
Points to a structure containing the addresses of procedures that
can be called to perform the various filesystem operations.
.AP "const char" *pathStr in
Pointer to a NUL terminated string representing a file system path.
.AP Tcl_Obj *pathPtr in
The path represented by this value is used for the operation in
question. If the value does not already have an internal \fBpath\fR
representation, it will be converted to have one.
.AP Tcl_Obj *srcPathPtr in
As for \fIpathPtr\fR, but used for the source file for a copy or
rename operation.
.AP Tcl_Obj *destPathPtr in
As for \fIpathPtr\fR, but used for the destination filename for a copy or
rename operation.
.AP int recursive in
Whether to remove subdirectories and their contents as well.
.AP "const char" *encodingName in
The encoding of the data stored in the
file identified by \fIpathPtr\fR and to be evaluated.
.AP "const char" *pattern in
Only files or directories matching this pattern will be returned.
.AP Tcl_GlobTypeData *types in
Only files or directories matching the type descriptions contained in
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
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







-
-
+
+




+
+
+
+



-
+













-
+

-
+



















-
-
+
+
+
+
+
+
+


-
+














+
+







The first of two path values to compare. The value may be converted
to \fBpath\fR type.
.AP Tcl_Obj *secondPtr in
The second of two path values to compare. The value may be converted
to \fBpath\fR type.
.AP Tcl_Obj *listObj in
The list of path elements to operate on with a \fBjoin\fR operation.
.AP int elements in
If non-negative, the number of elements in the \fIlistObj\fR which should
.AP Tcl_Size elements in
The number of elements in the \fIlistObj\fR which should
be joined together. If negative, then all elements are joined.
.AP Tcl_Obj **errorPtr out
In the case of an error, filled with a value containing the name of
the file which caused an error in the various copy/rename operations.
.AP int index in
The index of the attribute in question.
.AP Tcl_Obj *objPtr in
The value to set in the operation.
.AP Tcl_Obj **objPtrRef out
Filled with a value containing the result of the operation.
.AP Tcl_Obj *resultPtr out
Pre-allocated value in which to store (using
Preallocated value in which to store (using
\fBTcl_ListObjAppendElement\fR) the list of
files or directories which are successfully matched.
.AP int mode in
Mask consisting of one or more of R_OK, W_OK, X_OK and F_OK. R_OK,
W_OK and X_OK request checking whether the file exists and  has  read,
write and  execute  permissions, respectively. F_OK just requests
checking for the existence of the file.
.AP Tcl_StatBuf *statPtr out
The structure that contains the result of a stat or lstat operation.
.AP "const char" *sym1 in
Name of a procedure to look up in the file's symbol table
.AP "const char" *sym2 in
Name of a procedure to look up in the file's symbol table
.AP Tcl_PackageInitProc **proc1Ptr out
.AP Tcl_LibraryInitProc **proc1Ptr out
Filled with the init function for this code.
.AP Tcl_PackageInitProc **proc2Ptr out
.AP Tcl_LibraryInitProc **proc2Ptr out
Filled with the safe-init function for this code.
.AP void **clientDataPtr out
Filled with the clientData value to pass to this code's unload
function when it is called.
.AP Tcl_LoadHandle *loadHandlePtr out
Filled with an abstract token representing the loaded file.
.AP Tcl_FSUnloadFileProc **unloadProcPtr out
Filled with the function to use to unload this piece of code.
.AP Tcl_LoadHandle loadHandle in
Handle to the loaded library to be unloaded.
.AP utimbuf *tval in
The access and modification times in this structure are read and
used to set those values for a given file.
.AP "const char" *modeString in
Specifies how the file is to be accessed. May have any of the values
allowed for the \fImode\fR argument to the Tcl \fBopen\fR command.
.AP int permissions in
POSIX-style permission flags such as 0644. If a new file is created, these
permissions will be set on the created file.
.AP int *lenPtr out
If non-NULL, filled with the number of elements in the split path.
.AP "Tcl_Size \&| int" *lenPtr out
Filled with the number of elements in the split path.
May be (Tcl_Size *)NULL when not used. If it points to a variable which
type is not \fBTcl_Size\fR, a compiler warning will be generated.
If your extensions is compiled with -DTCL_8_API, this function will return
NULL for paths having more than INT_MAX elements (which should
trigger proper error-handling), otherwise expect it to crash.
.AP Tcl_Obj *basePtr in
The base path on to which to join the given elements. May be NULL.
.AP int objc in
.AP Tcl_Size objc in
The number of elements in \fIobjv\fR.
.AP "Tcl_Obj *const" objv[] in
The elements to join to the given base path.
.AP Tcl_Obj *linkNamePtr in
The name of the link to be created or read.
.AP Tcl_Obj *toPtr in
What the link called \fIlinkNamePtr\fR should be linked to, or NULL if
the symbolic link specified by \fIlinkNamePtr\fR is to be read.
.AP int linkAction in
OR-ed combination of flags indicating what kind of link should be
created (will be ignored if \fItoPtr\fR is NULL). Valid bits to set
are \fBTCL_CREATE_SYMBOLIC_LINK\fR and \fBTCL_CREATE_HARD_LINK\fR.
When both flags are set and the underlying filesystem can do either,
symbolic links are preferred.
.AP Tcl_DString *dsPtr out
Pointer to a \fBTcl_DString\fR to hold an output string result.
.BE
.SH DESCRIPTION
.PP
There are several reasons for calling the \fBTcl_FS\fR API functions
(e.g.\ \fBTcl_FSAccess\fR and \fBTcl_FSStat\fR)
rather than calling system level functions like \fBaccess\fR and
\fBstat\fR directly. First, they will work cross-platform, so an
362
363
364
365
366
367
368
369


370
371
372
373
374
375
376
380
381
382
383
384
385
386

387
388
389
390
391
392
393
394
395







-
+
+







function is called (if it is non-NULL).
Otherwise the function returns -1 and sets the \fBerrno\fR global C
variable to the
.QW EXDEV
POSIX error code (which signifies a
.QW "cross-domain link" ).
.PP
\fBTcl_FSCopyDirectory\fR attempts to copy the directory given by \fIsrcPathPtr\fR to the
\fBTcl_FSCopyDirectory\fR attempts to copy the directory given by
\fIsrcPathPtr\fR to the
path name given by \fIdestPathPtr\fR. If the two paths given lie in the same
filesystem (according to \fBTcl_FSGetFileSystemForPath\fR) then that
filesystem's
.QW "copy file"
function is called (if it is non-NULL).
Otherwise the function returns -1 and sets the \fBerrno\fR global C
variable to the
415
416
417
418
419
420
421
422

423
424
425
426
427

428
429
430
431
432
433
434
435
436
434
435
436
437
438
439
440

441
442
443
444
445

446


447
448
449
450
451
452
453







-
+




-
+
-
-







its contents as a Tcl script. It returns the same information as
\fBTcl_EvalObjEx\fR.
If \fIencodingName\fR is NULL, the utf-8 encoding is used for
reading the file contents.
If the file could not be read then a Tcl error is returned to describe
why the file could not be read.
The eofchar for files is
.QW \e32
.QW \ex1A
(^Z) for all platforms.
If you require a
.QW ^Z
in code for string comparison, you can use
.QW \e032
.QW \ex1A ,
or
.QW \eu001a ,
which will be safely substituted by the Tcl interpreter into
.QW ^Z .
\fBTcl_FSEvalFile\fR is a simpler version of
\fBTcl_FSEvalFileEx\fR that always uses the utf-8 encoding
when reading the file.
.PP
\fBTcl_FSLoadFile\fR dynamically loads a binary code file into memory and
474
475
476
477
478
479
480
481
482



483
484
485
486
487
488
489
491
492
493
494
495
496
497


498
499
500
501
502
503
504
505
506
507







-
-
+
+
+







If the \fItoPtr\fR is NULL, a
.QW "read link"
action is performed. The result
is a Tcl_Obj specifying the contents of the symbolic link given by
\fIlinkNamePtr\fR, or NULL if the link could not be read. The result is owned
by the caller, which should call \fBTcl_DecrRefCount\fR when the result is no
longer needed. If the \fItoPtr\fR is not NULL, Tcl should create a link
of one of the types passed in in the \fIlinkAction\fR flag. This flag is
an ORed combination of \fBTCL_CREATE_SYMBOLIC_LINK\fR and \fBTCL_CREATE_HARD_LINK\fR.
of one of the types passed in in the \fIlinkAction\fR flag.
This flag is an OR'ed combination of \fBTCL_CREATE_SYMBOLIC_LINK\fR
and \fBTCL_CREATE_HARD_LINK\fR.
Where a choice exists (i.e.\ more than one flag is passed in), the Tcl
convention is to prefer symbolic links. When a link is successfully
created, the return value should be \fItoPtr\fR (which is therefore
already owned by the caller). If unsuccessful, NULL is returned.
.PP
\fBTcl_FSLstat\fR fills the \fITcl_StatBuf\fR structure \fIstatPtr\fR with
information about the specified file. You do not need any access rights to the
641
642
643
644
645
646
647
648

649
650
651
652
653
654
655
659
660
661
662
663
664
665

666
667
668
669
670
671
672
673







-
+







updated to contain the number of elements in the returned list.
.PP
\fBTcl_FSEqualPaths\fR tests whether the two paths given represent the same
filesystem object.
It returns 1 if the paths are equal, and 0 if they are different. If
either path is NULL, 0 is always returned.
.PP
\fBTcl_FSGetNormalizedPath\fR this important function attempts to extract
\fBTcl_FSGetNormalizedPath\fR attempts to extract
from the given Tcl_Obj a unique normalized path representation, whose
string value can be used as a unique identifier for the file.
.PP
It returns the normalized path value, owned by Tcl, or NULL if the path
was invalid or could otherwise not be successfully converted.
Extraction of absolute, normalized paths is very efficient (because the
filesystem operates on these representations internally), although the
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
688
689
690
691
692
693
694





695
696
697
698
699
700
701







-
-
-
-
-







passed into this function (\fIpathPtr\fR or \fIpath\fR elements) have
a reference count
of zero, they will be freed when this function returns.
.PP
\fBTcl_FSConvertToPathType\fR tries to convert the given Tcl_Obj to a valid
Tcl path type, taking account of the fact that the cwd may have changed
even if this value is already supposedly of the correct type.
The filename may begin with
.QW ~
(to indicate current user's home directory) or
.QW ~<user>
(to indicate any user's home directory).
.PP
If the conversion succeeds (i.e.\ the value is a valid path in one of
the current filesystems), then \fBTCL_OK\fR is returned. Otherwise
\fBTCL_ERROR\fR is returned, and an error message may
be left in the interpreter.
.PP
\fBTcl_FSGetInternalRep\fR extracts the internal representation of a given
696
697
698
699
700
701
702
703

704
705
706
707
708
709
710
711
712
713
714
715
716
717
709
710
711
712
713
714
715

716







717
718
719
720
721
722
723







-
+
-
-
-
-
-
-
-







not require additional conversions.
.PP
\fBTcl_FSGetTranslatedPath\fR attempts to extract the translated path
from the given Tcl_Obj.
.PP
If the translation succeeds (i.e.\ the value is a valid path), then it is
returned. Otherwise NULL will be returned, and an error message may be
left in the interpreter. A
left in the interpreter. The value returned is owned by the
.QW translated
path is one which contains no
.QW ~
or
.QW ~user
sequences (these have been expanded to their current
representation in the filesystem). The value returned is owned by the
caller, which must store it or call \fBTcl_DecrRefCount\fR to ensure memory is
freed. This function is of little practical use, and
\fBTcl_FSGetNormalizedPath\fR or \fBTcl_FSGetNativePath\fR are usually
better functions to use for most purposes.
.PP
\fBTcl_FSGetTranslatedStringPath\fR does the same as
\fBTcl_FSGetTranslatedPath\fR, but returns a character string or NULL.
732
733
734
735
736
737
738
739

740
741
742
743
744
745
746
738
739
740
741
742
743
744

745
746
747
748
749
750
751
752







-
+







a UTF-8 string representation if that is required by some Tcl code.
.PP
\fBTcl_FSGetNativePath\fR is for use by the Win/Unix native
filesystems, so that they can easily retrieve the native (char* or
TCHAR*) representation of a path. This function is a convenience
wrapper around \fBTcl_FSGetInternalRep\fR. It may be desirable in the
future to have non-string-based native representations (for example,
on MacOSX, a representation using a fileSpec of FSRef structure would
on macOS, a representation using a fileSpec of FSRef structure would
probably be more efficient). On Windows a full Unicode representation
would allow for paths of unlimited length. Currently the representation
is simply a character string which may contain either the relative path
or a complete, absolute normalized path in the native encoding (complex
conditions dictate which of these will be provided, so neither can be
relied upon, unless the path is known to be absolute). If you need a
native path which must be absolute, then you should ask for the native
776
777
778
779
780
781
782











783
784
785
786
787
788
789
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806







+
+
+
+
+
+
+
+
+
+
+







.PP
\fBTcl_FSGetPathType\fR determines whether the given path is relative
to the current directory, relative to the current volume, or
absolute.
.PP
It returns one of \fBTCL_PATH_ABSOLUTE\fR, \fBTCL_PATH_RELATIVE\fR, or
\fBTCL_PATH_VOLUME_RELATIVE\fR
.PP
\fBTcl_FSTildeExpand\fR performs tilde substitution on the input path passed via
\fBpathStr\fR as described in the documentation for the \fBfile tildeexpand\fR
Tcl command. On success, the function returns \fBTCL_OK\fR with the result of
the substitution in \fBdsPtr\fR which must be subsequently freed by the caller.
The \fBdsPtr\fR structure is initialized by the function. No guarantees are made
about the form of the returned path such as the path separators used. The
returned result should be passed to other Tcl C API functions such as
\fBTcl_FSGetNormalizedPath\fR or \fBTcl_FSGetNativePath\fR if necessary. On
error, the function returns \fBTCL_ERROR\fR with an error message in
\fBinterp\fR which may be passed as NULL if error messages are not of interest.
.SS "PORTABLE STAT RESULT API"
.PP
\fBTcl_AllocStatBuf\fR allocates a \fITcl_StatBuf\fR on the system heap (which
may be deallocated by being passed to \fBTcl_Free\fR). This allows extensions to
invoke \fBTcl_FSStat\fR and \fBTcl_FSLstat\fR without being dependent on the
size of the buffer. That in turn depends on the flags used to build Tcl.
.PP
840
841
842
843
844
845
846
847

848
849

850
851
852
853
854
855
856
857
858
859
860
861
862
863

864
865

866
867
868
869
870
871
872
873







-
+

-
+







have changed, and that cached file representations may therefore no
longer be correct.
.SS "THE TCL_FILESYSTEM STRUCTURE"
.PP
The \fBTcl_Filesystem\fR structure contains the following fields:
.PP
.CS
typedef struct Tcl_Filesystem {
typedef struct {
    const char *\fItypeName\fR;
    int \fIstructureLength\fR;
    Tcl_Size \fIstructureLength\fR;
    Tcl_FSVersion \fIversion\fR;
    Tcl_FSPathInFilesystemProc *\fIpathInFilesystemProc\fR;
    Tcl_FSDupInternalRepProc *\fIdupInternalRepProc\fR;
    Tcl_FSFreeInternalRepProc *\fIfreeInternalRepProc\fR;
    Tcl_FSInternalToNormalizedProc *\fIinternalToNormalizedProc\fR;
    Tcl_FSCreateInternalRepProc *\fIcreateInternalRepProc\fR;
    Tcl_FSNormalizePathProc *\fInormalizePathProc\fR;
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







-
+
-
-







path value. In Tcl, every
.QW path
must have a single unique
.QW normalized
string representation. Depending on the filesystem,
there may be more than one unnormalized string representation which
refers to that path (e.g.\ a relative path, a path with different
character case if the filesystem is case insensitive, a path contain a
character case if the filesystem is case insensitive,
reference to a home directory such as
.QW ~ ,
a path containing symbolic
links, etc). If the very last component in the path is a symbolic
link, it should not be converted into the value it points to (but
its case or other aspects should be made unique). All other path
components should be converted from symbolic links. This one
exception is required to agree with Tcl's semantics with \fBfile
delete\fR, \fBfile rename\fR, \fBfile copy\fR operating on symbolic links.
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







-
+







result; errors are only signaled for actual file or filesystem
problems which may occur during the matching process.
.PP
The \fBTcl_GlobTypeData\fR structure passed in the \fItypes\fR
parameter contains the following fields:
.PP
.CS
typedef struct Tcl_GlobTypeData {
typedef struct {
    /* Corresponds to bcdpfls as in 'find -t' */
    int \fItype\fR;
    /* Corresponds to file permissions */
    int \fIperm\fR;
    /* Acceptable mac type */
    Tcl_Obj *\fImacType\fR;
    /* Acceptable mac creator */
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393




1394
1395
1396
1397
1398
1399
1400
1398
1399
1400
1401
1402
1403
1404




1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415







-
-
-
-
+
+
+
+







        int \fIindex\fR,
        Tcl_Obj *\fIpathPtr\fR,
        Tcl_Obj **\fIobjPtrRef\fR);
.CE
.PP
Returns a standard Tcl return code. The attribute value retrieved,
which corresponds to the \fIindex\fR'th element in the list returned by
the \fBTcl_FSFileAttrStringsProc\fR, is a Tcl_Obj placed in \fIobjPtrRef\fR (if
\fBTCL_OK\fR was returned) and is likely to have a reference count of zero. Either
way we must either store it somewhere (e.g.\ the Tcl result), or
Incr/Decr its reference count to ensure it is properly freed.
the \fBTcl_FSFileAttrStringsProc\fR, is a Tcl_Obj placed in \fIobjPtrRef\fR
(if \fBTCL_OK\fR was returned) and is likely to have a reference count of
zero. Either way we must either store it somewhere (e.g.\ the Tcl result),
or Incr/Decr its reference count to ensure it is properly freed.
.SS FILEATTRSSETPROC
.PP
Function to process a \fBTcl_FSFileAttrsSet\fR call, used by \fBfile
attributes\fR. If the filesystem is read-only, there is no need
to implement this.
.PP
.CS
1624
1625
1626
1627
1628
1629
1630
























































































































































1631
1632
1633
1634
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




typedef int \fBTcl_FSChdirProc\fR(
        Tcl_Obj *\fIpathPtr\fR);
.CE
.PP
The \fBTcl_FSChdirProc\fR changes the applications current working
directory to the value specified in \fIpathPtr\fR. The function returns
-1 on error or 0 on success.
.SH "REFERENCE COUNT MANAGEMENT"
.SS "PUBLIC API CALLS"
.PP
For all of these functions, \fIpathPtr\fR (including the \fIsrcPathPtr\fR and
\fIdestPathPtr\fR arguments to \fBTcl_FSCopyFile\fR,
\fBTcl_FSCopyDirectory\fR, and \fBTcl_FSRenameFile\fR, the \fIfirstPtr\fR and
\fIsecondPtr\fR arguments to \fBTcl_FSEqualPaths\fR, and the \fIlinkNamePtr\fR
and \fItoPtr\fR arguments to \fBTcl_FSLink\fR) must not be a zero reference
count value; references may be retained in internal caches even for
theoretically read-only operations.  These functions may also manipulate the
interpreter result (if they take and are given a non-NULL \fIinterp\fR
argument); you must not count on the interpreter result to hold the reference
count of any argument value over these calls and should manage your own
references there. However, references held by the arguments to a Tcl command
\fIare\fR suitable for reference count management purposes for the duration of
the implementation of that command.
.PP
The \fIerrorPtr\fR argument to \fBTcl_FSCopyDirectory\fR and
\fBTcl_FSRemoveDirectory\fR is, when an object is set into it at all, set to
an object with a non-zero reference count that should be passed to
\fBTcl_DecrRefCount\fR when no longer needed.
.PP
\fBTcl_FSListVolumes\fR always returns a zero-reference object, much
like \fBTcl_NewObj\fR.
.PP
\fBTcl_FSLink\fR always returns a non-zero-reference object when it is
asked to read; you must call \fBTcl_DecrRefCount\fR on the object
once you no longer need it.
.PP
\fBTcl_FSGetCwd\fR always returns a non-zero-reference object; you
must call \fBTcl_DecrRefCount\fR on the object once you no longer need
it.
.PP
\fBTcl_FSPathSeparator\fR always returns a zero-reference object, much
like \fBTcl_NewObj\fR.
.PP
\fBTcl_FSJoinPath\fR always returns a zero-reference object, much
like \fBTcl_NewObj\fR. Its \fIlistObj\fR argument can have any reference
count; it is only read by this function.
.PP
\fBTcl_FSSplitPath\fR always returns a zero-reference object, much
like \fBTcl_NewObj\fR.
.PP
\fBTcl_FSGetNormalizedPath\fR returns an object with a non-zero
reference count where Tcl is the owner. You should increment its
reference count if you want to retain it, but do not need to if you
are just using the value immediately.
.PP
\fBTcl_FSJoinToPath\fR always returns a zero-reference object, much like
\fBTcl_NewObj\fR. Its \fIbasePtr\fR argument follows the rules above for
\fIpathPtr\fR, as do the values in the \fIobjv\fR argument.
.PP
\fBTcl_FSGetTranslatedPath\fR returns a non-zero-reference object (or
NULL in the error case); you must call \fBTcl_DecrRefCount\fR on the
object once you no longer need it.
.PP
\fBTcl_FSNewNativePath\fR always returns a zero-reference object (or
NULL), much like \fBTcl_NewObj\fR.
.PP
\fBTcl_FSFileSystemInfo\fR always returns a zero-reference object (or
NULL), much like \fBTcl_NewObj\fR.
.PP
The \fIobjPtr\fR and \fIobjPtrRef\fR arguments to \fBTcl_FSFileAttrsGet\fR,
\fBTcl_FSFileAttrsSet\fR and \fBTcl_FSFileAttrStrings\fR are conventional Tcl
values; the \fIobjPtr\fR argument will be read but not retained, and the
\fIobjPtrRef\fR argument will have (on success) a zero-reference value written
into it (as with \fBTcl_NewObj\fR). \fBTcl_FSFileAttrsGet\fR and
\fBTcl_FSFileAttrsSet\fR may also manipulate the interpreter result.
.PP
The \fIresultPtr\fR argument to \fBTcl_FSMatchInDirectory\fR will not have its
reference count manipulated, but it should have a reference count of no more
than 1, and should not be the current interpreter result (as the function may
overwrite that on error).
.SS "VIRTUAL FILESYSTEM INTERFACE"
.PP
For all virtual filesystem implementation functions, any \fIpathPtr\fR
arguments should not have their reference counts manipulated. If they take an
\fIinterp\fR argument, they may set an error message in that, but must not
manipulate the \fIpathPtr\fR afterwards. Aside from that:
.TP
\fIinternalToNormalizedProc\fR
.
This should return a zero-reference count value, as if allocated with
\fBTcl_NewObj\fR.
.TP
\fInormalizePathProc\fR
.
Unlike with other API implementation functions, the \fIpathPtr\fR argument
here is guaranteed to be an unshared object that should be updated. Its
reference count should not be modified.
.TP
\fIfilesystemPathTypeProc\fR
.
The return value (if non-NULL) either has a reference count of zero or needs
to be maintained (on a per-thread basis) by the filesystem. Tcl will increment
the reference count of the value if it wishes to retain it.
.TP
\fIfilesystemSeparatorProc\fR
.
The return value should be a value with reference count of zero.
.TP
\fImatchInDirectoryProc\fR
.
The \fIresultPtr\fR argument should be assumed to hold a list that can be
appended to (i.e., that has a reference count no greater than 1). No reference
to it should be retained.
.TP
\fIlinkProc\fR
.
If \fItoPtr\fR is NULL, this should return a value with reference count 1 that
has just been allocated and passed to \fBTcl_IncrRefCount\fR. If \fItoPtr\fR
is not NULL, it should be returned on success.
.TP
\fIlistVolumesProc\fR
.
The result value should be a list (if non-NULL); it will have its reference
count decremented once (with \fBTcl_DecrRefCount\fR) by Tcl once done.
.TP
\fIfileAttrStringsProc\fR
.
If the result is NULL, the \fIobjPtrRef\fR should have a list value written to
it; that list will have its reference count both incremented (with
\fBTcl_IncrRefCount\fR) and decremented (with \fBTcl_DecrRefCount\fR).
.TP
\fIfileAttrsGetProc\fR
.
The \fIobjPtrRef\fR argument should have (on non-error return) a zero
reference count value written to it (allocated as if with \fBTcl_NewObj\fR).
.TP
\fIfileAttrsSetProc\fR
.
The \fIobjPtr\fR argument should either just be read or its reference count
incremented to retain it.
.TP
\fIremoveDirectoryProc\fR
.
If an error is being reported, the problem filename reported via
\fIerrorPtr\fR should be newly allocated (as if with \fBTcl_NewObj\fR) and
have a reference count of 1 (i.e., have been passed to
\fBTcl_IncrRefCount\fR).
.TP
\fIcopyDirectoryProc\fR
.
If an error is being reported, the problem filename reported via
\fIerrorPtr\fR should be newly allocated (as if with \fBTcl_NewObj\fR) and
have a reference count of 1 (i.e., have been passed to
\fBTcl_IncrRefCount\fR).
.TP
\fIgetCwdProc\fR
.
The result will be passed to \fBTcl_DecrRefCount\fR by the implementation of
\fBTcl_FSGetCwd\fR after it has been normalized.
.SH "SEE ALSO"
cd(n), file(n), filename(n), load(n), open(n), pwd(n), source(n), unload(n)
.SH KEYWORDS
stat, access, filesystem, vfs, virtual filesystem

Changes to doc/FindExec.3.

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
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







-
+




+
















+
+
+







.BS
.SH NAME
Tcl_FindExecutable, Tcl_GetNameOfExecutable \- identify or return the name of the binary file containing the application
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
void
const char *
\fBTcl_FindExecutable\fR(\fIargv0\fR)
.sp
const char *
\fBTcl_GetNameOfExecutable\fR()
.fi
.SH ARGUMENTS
.AS char *argv0
.AP char *argv0 in
The first command-line argument to the program, which gives the
application's name.
.BE

.SH DESCRIPTION
.PP
The \fBTcl_FindExecutable\fR procedure computes the full path name of
the executable file from which the application was invoked and saves
it for Tcl's internal use.
The executable's path name is needed for several purposes in
Tcl.  For example, it is needed on some platforms in the
implementation of the \fBload\fR command.
It is also returned by the \fBinfo nameofexecutable\fR command.
.PP
The result of \fBTcl_FindExecutable\fR is the full Tcl version with
build information (e.g., \fB9.0.0+abcdef...abcdef.gcc-1002\fR).
.PP
On UNIX platforms this procedure is typically invoked as the very
first thing in the application's main program;  it must be passed
\fIargv[0]\fR as its argument.  It is important not to change the
working directory before the invocation.
\fBTcl_FindExecutable\fR uses \fIargv0\fR
along with the \fBPATH\fR environment variable to find the

Changes to doc/GetCwd.3.

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
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







-
+
+









-
+

















-
-
+
+



.nf
\fB#include <tcl.h>\fR
.sp
char *
\fBTcl_GetCwd\fR(\fIinterp\fR, \fIbufferPtr\fR)
.sp
int
\fBTcl_Chdir\fR(\fIpath\fR)
\fBTcl_Chdir\fR(\fIdirName\fR)
.fi
.SH ARGUMENTS
.AS Tcl_DString *bufferPtr in/out
.AP Tcl_Interp *interp in
Interpreter in which to report an error, if any.
.AP Tcl_DString *bufferPtr in/out
This dynamic string is used to store the current working directory.
At the time of the call it should be uninitialized or free.  The
caller must eventually call \fBTcl_DStringFree\fR to free up
anything stored here.
.AP char *path in
.AP "const char" *dirName in
File path in UTF\-8 format.
.BE

.SH DESCRIPTION
.PP
These procedures may be used to manipulate the current working
directory for the application.  They provide C\-level access to
the same functionality as the Tcl \fBpwd\fR command.
.PP
\fBTcl_GetCwd\fR returns a pointer to a string specifying the current
directory, or NULL if the current directory could not be determined.
If NULL is returned, an error message is left in the \fIinterp\fR's result.
Storage for the result string is allocated in bufferPtr; the caller
must call \fBTcl_DStringFree()\fR when the result is no longer needed.
The format of the path is UTF\-8.
.PP
\fBTcl_Chdir\fR changes the applications current working directory to
the value specified in \fIpath\fR.  The format of the passed in string
must be UTF\-8.  The function returns -1 on error or 0 on success.
the value specified in \fIdirName\fR.  The format of the passed in string
must be UTF\-8.  The function returns \-1 on error or 0 on success.

.SH KEYWORDS
pwd

Changes to doc/GetHostName.3.

1
2

3
4
5
6
7
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

-
+













+







'\"
'\" Copyright (c) 1998-2000 by Scriptics Corporation.
'\" Copyright (c) 1998-2000 Scriptics Corporation.
'\" All rights reserved.
'\"
.TH Tcl_GetHostName 3 8.3 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_GetHostName \- get the name of the local host
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
const char *
\fBTcl_GetHostName\fR()
.fi
.BE

.SH DESCRIPTION
.PP
\fBTcl_GetHostName\fR is a utility procedure used by some of the
Tcl commands.  It returns a pointer to a string containing the name
for the current machine, or an empty string if the name cannot be

Changes to doc/GetIndex.3.

16
17
18
19
20
21
22

23
24
25
26
27
28
29
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30







+







int
\fBTcl_GetIndexFromObj\fR(\fIinterp, objPtr, tablePtr, msg, flags,
indexPtr\fR)
.sp
int
\fBTcl_GetIndexFromObjStruct\fR(\fIinterp, objPtr, structTablePtr, offset,
                          msg, flags, indexPtr\fR)
.fi
.SH ARGUMENTS
.AS "const char" *structTablePtr in/out
.AP Tcl_Interp *interp in
Interpreter to use for error reporting; if NULL, then no message is
provided on errors.
.AP Tcl_Obj *objPtr in/out
The string value of this value is used to search through \fItablePtr\fR.
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
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







-
-
-
-
+
+
+
+
+
+












+
-
+
-















-
+



+
+
-
+













+
+
+
+
+
+




The end of the array is marked by a NULL string pointer.
.AP "const char" *msg in
Null-terminated string describing what is being looked up, such as
\fBoption\fR.  This string is included in error messages.
.AP int flags in
OR-ed combination of bits providing additional information for
operation.  The only bits that are currently defined are \fBTCL_EXACT\fR
and \fBTCL_INDEX_TEMP_TABLE\fR.
.AP int *indexPtr out
The index of the string in \fItablePtr\fR that matches the value of
\fIobjPtr\fR is returned here.
, \fBTCL_INDEX_TEMP_TABLE\fR, and \fBTCL_NULL_OK\fR.
.AP enum|char|short|int|long *indexPtr out
If not (int *)NULL, the index of the string in \fItablePtr\fR that
matches the value of \fIobjPtr\fR is returned here. The variable can
be any integer type, signed or unsigned, char, short, long or
long long. It can also be an enum.
.BE
.SH DESCRIPTION
.PP
These procedures provide an efficient way for looking up keywords,
switch names, option names, and similar things where the literal value of
a Tcl value must be chosen from a predefined set.
\fBTcl_GetIndexFromObj\fR compares \fIobjPtr\fR against each of
the strings in \fItablePtr\fR to find a match.  A match occurs if
\fIobjPtr\fR's string value is identical to one of the strings in
\fItablePtr\fR, or if it is a non-empty unique abbreviation
for exactly one of the strings in \fItablePtr\fR and the
\fBTCL_EXACT\fR flag was not specified; in either case
\fBTCL_OK\fR is returned. If \fIindexPtr\fR is not NULL the index
the index of the matching entry is stored at \fI*indexPtr\fR
of the matching entry is stored at \fI*indexPtr\fR.
and \fBTCL_OK\fR is returned.
.PP
If there is no matching entry,
\fBTCL_ERROR\fR is returned and an error message is left in \fIinterp\fR's
result if \fIinterp\fR is not NULL.  \fIMsg\fR is included in the
error message to indicate what was being looked up.  For example,
if \fImsg\fR is \fBoption\fR the error message will have a form like
.QW "\fBbad option \N'34'firt\N'34': must be first, second, or third\fR" .
.PP
If the \fBTCL_INDEX_TEMP_TABLE\fR was not specified, when
\fBTcl_GetIndexFromObj\fR completes successfully it modifies the
internal representation of \fIobjPtr\fR to hold the address of
the table and the index of the matching entry.  If \fBTcl_GetIndexFromObj\fR
is invoked again with the same \fIobjPtr\fR and \fItablePtr\fR
arguments (e.g. during a reinvocation of a Tcl command), it returns
the matching index immediately without having to redo the lookup
operation.  Note: \fBTcl_GetIndexFromObj\fR assumes that the entries
operation.  Note that \fBTcl_GetIndexFromObj\fR assumes that the entries
in \fItablePtr\fR are static: they must not change between
invocations.  This caching mechanism can be disallowed by specifying
the \fBTCL_INDEX_TEMP_TABLE\fR flag.
If the \fBTCL_NULL_OK\fR flag was specified, objPtr is allowed
to be NULL or the empty string. The resulting index is -1.
If the value of \fIobjPtr\fR is the empty string,
Otherwise, if the value of \fIobjPtr\fR is the empty string,
\fBTcl_GetIndexFromObj\fR will treat it as a non-matching value
and return \fBTCL_ERROR\fR.
.PP
\fBTcl_GetIndexFromObjStruct\fR works just like
\fBTcl_GetIndexFromObj\fR, except that instead of treating
\fItablePtr\fR as an array of string pointers, it treats it as a
pointer to the first string in a series of strings that have
\fIoffset\fR bytes between them (i.e. that there is a pointer to the
first array of characters at \fItablePtr\fR, a pointer to the second
array of characters at \fItablePtr\fR+\fIoffset\fR bytes, etc.)
This is particularly useful when processing things like
\fBTk_ConfigurationSpec\fR, whose string keys are in the same place in
each of several array elements.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
\fBTcl_GetIndexFromObj\fR and \fBTcl_GetIndexFromObjStruct\fR do not modify
the reference count of their \fIobjPtr\fR arguments; they only read. Note
however that these functions may set the interpreter result; if that is the
only place that is holding a reference to the object, it will be deleted.
.SH "SEE ALSO"
prefix(n), Tcl_WrongNumArgs(3)
.SH KEYWORDS
index, option, value, table lookup

Changes to doc/GetInt.3.

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
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







-
+
+
+
+
+











-
-
+
+
+
+
+
+













-
+







int
\fBTcl_GetInt\fR(\fIinterp, src, intPtr\fR)
.sp
int
\fBTcl_GetDouble\fR(\fIinterp, src, doublePtr\fR)
.sp
int
\fBTcl_GetBoolean\fR(\fIinterp, src, boolPtr\fR)
\fBTcl_GetBoolean\fR(\fIinterp, src, intPtr\fR)
.sp
int
\fBTcl_GetBool\fR(\fIinterp, src, flags, charPtr\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp *doublePtr out
.AP Tcl_Interp *interp in
Interpreter to use for error reporting.
.AP "const char" *src in
Textual value to be converted.
.AP int *intPtr out
Points to place to store integer value converted from \fIsrc\fR.
.AP double *doublePtr out
Points to place to store double-precision floating-point
value converted from \fIsrc\fR.
.AP int *boolPtr out
Points to place to store boolean value (0 or 1) converted from \fIsrc\fR.
.AP char *charPtr out
Points to place to store boolean value (0 or 1) value converted from \fIsrc\fR.
.AP int flags in
0 or TCL_NULL_OK. If TCL_NULL_OK
is used, then the empty string or NULL will result in \fBTcl_GetBool\fR
return TCL_OK, the *charPtr filled with the value \fB'\exFF'\fR;
.BE

.SH DESCRIPTION
.PP
These procedures convert from strings to integers or double-precision
floating-point values or booleans (represented as 0- or 1-valued
integers).  Each of the procedures takes a \fIsrc\fR argument,
converts it to an internal form of a particular type, and stores
the converted value at the location indicated by the procedure's
third argument.  If all goes well, each of the procedures returns
\fBTCL_OK\fR.  If \fIsrc\fR does not have the proper syntax for the
desired type then \fBTCL_ERROR\fR is returned, an error message is left
in the interpreter's result, and nothing is stored at *\fIintPtr\fR
or *\fIdoublePtr\fR or *\fIboolPtr\fR.
or *\fIdoublePtr\fR.
.PP
\fBTcl_GetInt\fR expects \fIsrc\fR to consist of a collection
of integer digits, optionally signed and optionally preceded and
followed by white space.  If the first two characters of \fIsrc\fR
after the optional white space and sign are
.QW \fB0x\fR
then \fIsrc\fR is expected to be in hexadecimal form;  otherwise,
87
88
89
90
91
92
93
94

95
96

97
98




99
100
101
95
96
97
98
99
100
101

102
103

104
105
106
107
108
109
110
111
112
113







-
+

-
+


+
+
+
+



.QW \fB,\fR
as a decimal point is not supported nor should any other sort of
inter-digit separator be present.
.PP
\fBTcl_GetBoolean\fR expects \fIsrc\fR to specify a boolean
value.  If \fIsrc\fR is any of \fB0\fR, \fBfalse\fR,
\fBno\fR, or \fBoff\fR, then \fBTcl_GetBoolean\fR stores a zero
value at \fI*boolPtr\fR.
value at \fI*intPtr\fR.
If \fIsrc\fR is any of \fB1\fR, \fBtrue\fR, \fByes\fR, or \fBon\fR,
then 1 is stored at \fI*boolPtr\fR.
then 1 is stored at \fI*intPtr\fR.
Any of these values may be abbreviated, and upper-case spellings
are also acceptable.
.PP
\fBTcl_GetBool\fR functions almost the same as \fBTcl_GetBoolean\fR,
but it has an additional parameter \fBflags\fR, which can be used
to specify whether the empty string or NULL is accepted as valid.

.SH KEYWORDS
boolean, conversion, double, floating-point, integer

Changes to doc/GetOpnFl.3.

11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25







-
+







Tcl_GetOpenFile \- Return a FILE* for a channel registered in the given interpreter (Unix only)
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_GetOpenFile\fR(\fIinterp, chanID, write, checkUsage, filePtr\fR)
.sp
.fi
.SH ARGUMENTS
.AS Tcl_Interp checkUsage out
.AP Tcl_Interp *interp in
Tcl interpreter from which file handle is to be obtained.
.AP "const char" *chanID in
String identifying channel, such as \fBstdin\fR or \fBfile4\fR.
.AP int write in

Changes to doc/GetStdChan.3.

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
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

-
+


















-
+







'\"
'\" Copyright (c) 1996 by Sun Microsystems, Inc.
'\" Copyright (c) 1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_GetStdChannel 3 7.5 Tcl "Tcl Library Procedures"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
Tcl_GetStdChannel, Tcl_SetStdChannel \- procedures for retrieving and replacing the standard channels
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Channel
\fBTcl_GetStdChannel\fR(\fItype\fR)
.sp
\fBTcl_SetStdChannel\fR(\fIchannel, type\fR)
.sp
.fi
.SH ARGUMENTS
.AS Tcl_Channel channel
.AP int type in
The identifier for the standard channel to retrieve or modify.  Must be one of
\fBTCL_STDIN\fR, \fBTCL_STDOUT\fR, or \fBTCL_STDERR\fR.
.AP Tcl_Channel channel in
The channel to use as the new value for the specified standard channel.

Changes to doc/GetTime.3.

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
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

-
+


















+







'\"
'\" Copyright (c) 2001 by Kevin B. Kenny <kennykb@acm.org>.
'\" Copyright (c) 2001 Kevin B. Kenny <kennykb@acm.org>.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_GetTime 3 8.4 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_GetTime, Tcl_SetTimeProc, Tcl_QueryTimeProc \- get date and time
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_GetTime\fR(\fItimePtr\fR)
.sp
\fBTcl_SetTimeProc\fR(\fIgetProc, scaleProc, clientData\fR)
.sp
\fBTcl_QueryTimeProc\fR(\fIgetProcPtr, scaleProcPtr, clientDataPtr\fR)
.fi
.SH ARGUMENTS
.AS Tcl_GetTimeProc *getProc in
.AP Tcl_Time *timePtr out
Points to memory in which to store the date and time information.
.AP Tcl_GetTimeProc getProc in
Pointer to handler function replacing \fBTcl_GetTime\fR's access to the OS.
.AP Tcl_ScaleTimeProc scaleProc in
39
40
41
42
43
44
45
46
47


48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
40
41
42
43
44
45
46


47
48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
63







-
-
+
+







-
+







.SH DESCRIPTION
.PP
The \fBTcl_GetTime\fR function retrieves the current time as a
\fITcl_Time\fR structure in memory the caller provides.  This
structure has the following definition:
.PP
.CS
typedef struct Tcl_Time {
    long \fIsec\fR;
typedef struct {
    long long \fIsec\fR;
    long \fIusec\fR;
} \fBTcl_Time\fR;
.CE
.PP
On return, the \fIsec\fR member of the structure is filled in with the
number of seconds that have elapsed since the \fIepoch:\fR the epoch
is the point in time of 00:00 UTC, 1 January 1970.  This number does
\fInot\fR count leap seconds \- an interval of one day advances it by
\fInot\fR count leap seconds; an interval of one day advances it by
86400 seconds regardless of whether a leap second has been inserted.
.PP
The \fIusec\fR member of the structure is filled in with the number of
microseconds that have elapsed since the start of the second
designated by \fIsec\fR.  The Tcl library makes every effort to keep
this number as precise as possible, subject to the limitations of the
computer system.  On multiprocessor variants of Windows, this number

Changes to doc/GetVersion.3.

10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
10
11
12
13
14
15
16
17
18

19
20
21
22
23
24

25
26
27
28
29
30
31
32







+

-






-
+







.SH NAME
Tcl_GetVersion \- get the version of the library at runtime
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_GetVersion\fR(\fImajor, minor, patchLevel, type\fR)
.fi
.SH ARGUMENTS
.AS Tcl_ReleaseType *patchLevel out
.AP int *major out
Major version number of the Tcl library.
.AP int *minor out
Minor version number of the Tcl library.
.AP int *patchLevel out
The patch level of the Tcl library (or alpha or beta number).
.AP Tcl_ReleaseType *type out
.AP int *type out
The type of release, also indicates the type of patch level. Can be
one of \fBTCL_ALPHA_RELEASE\fR, \fBTCL_BETA_RELEASE\fR, or
\fBTCL_FINAL_RELEASE\fR.
.BE

.SH DESCRIPTION
.PP

Changes to doc/Hash.3.

42
43
44
45
46
47
48

49
50
51
52
53
54
55
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56







+







\fBTcl_FirstHashEntry\fR(\fItablePtr, searchPtr\fR)
.sp
Tcl_HashEntry *
\fBTcl_NextHashEntry\fR(\fIsearchPtr\fR)
.sp
char *
\fBTcl_HashStats\fR(\fItablePtr\fR)
.fi
.SH ARGUMENTS
.AS "const Tcl_HashKeyType" *searchPtr out
.AP Tcl_HashTable *tablePtr in
Address of hash table structure (for all procedures but
\fBTcl_InitHashTable\fR, this must have been initialized by
previous call to \fBTcl_InitHashTable\fR).
.AP int keyType in
237
238
239
240
241
242
243
244

245
246
247
248
249
250
251
238
239
240
241
242
243
244

245
246
247
248
249
250
251
252







-
+







.PP
Extension writers can define new hash key types by defining four procedures,
initializing a \fBTcl_HashKeyType\fR structure to describe the type, and
calling \fBTcl_InitCustomHashTable\fR. The \fBTcl_HashKeyType\fR structure is
defined as follows:
.PP
.CS
typedef struct Tcl_HashKeyType {
typedef struct {
    int \fIversion\fR;
    int \fIflags\fR;
    Tcl_HashKeyProc *\fIhashKeyProc\fR;
    Tcl_CompareHashKeysProc *\fIcompareKeysProc\fR;
    Tcl_AllocHashEntryProc *\fIallocEntryProc\fR;
    Tcl_FreeHashEntryProc *\fIfreeEntryProc\fR;
} \fBTcl_HashKeyType\fR;
320
321
322
323
324
325
326














327
328
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343







+
+
+
+
+
+
+
+
+
+
+
+
+
+


typedef void \fBTcl_FreeHashEntryProc\fR(
        Tcl_HashEntry *\fIhPtr\fR);
.CE
.PP
If this is NULL then \fBTcl_Free\fR is used to free the space for the entry.
Tcl_Obj* keys use this function to decrement the reference count on the
value.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
When a hash table is created with \fBTcl_InitCustomHashTable\fR, the
\fBTcl_CreateHashEntry\fR function will increment the reference count of its
\fIkey\fR argument when it creates a key (but not if there is an existing
matching key). The reference count of the key will be decremented when the
corresponding hash entry is deleted, whether with \fBTcl_DeleteHashEntry\fR or
with \fBTcl_DeleteHashTable\fR. The \fBTcl_GetHashKey\fR function will return
the key without further modifying its reference count.
.PP
Custom hash tables that use a Tcl_Obj* as key will generally need to do
something similar in their \fIallocEntryProc\fR.
.SH "SEE ALSO"
Dict(3)
.SH KEYWORDS
hash table, key, lookup, search, value

Changes to doc/Init.3.

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












30
31
32
33
34
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
30
31
32
33
34

35
36
37
38
39
40
41
42
43
44
45
46
47
48

49
50

-
+


-
+










+
+
+
+




+
+









-
+
+
+
+
+
+
+
+
+
+
+
+


-


'\"
'\" Copyright (c) 1998-2000 by Scriptics Corporation.
'\" Copyright (c) 1998-2000 Scriptics Corporation.
'\" All rights reserved.
'\"
.TH Tcl_Init 3 8.0 Tcl "Tcl Library Procedures"
.TH Tcl_Init 3 9.0 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_Init \- find and source initialization script
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_Init\fR(\fIinterp\fR)
.sp
const char *
\fBTcl_SetPreInitScript\fR(\fIscriptPtr\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Interpreter to initialize.
.AP "const char" *scriptPtr in
Address of the initialization script.
.BE

.SH DESCRIPTION
.PP
\fBTcl_Init\fR is a helper procedure that finds and \fBsource\fRs the
\fBinit.tcl\fR script, which should exist somewhere on the Tcl library
path.
.PP
\fBTcl_Init\fR is typically called from \fBTcl_AppInit\fR procedures.

.PP
\fBTcl_SetPreInitScript\fR registers the pre-initialization script and
returns the former (now replaced) script pointer.
A value of \fINULL\fR may be passed to not register any script.
The pre-initialization script is executed by \fBTcl_Init\fR before accessing
the file system. The purpose is to typically prepare a custom file system
(like an embedded zip-file) to be activated before the search.
.PP
When used in stub-enabled embedders, the stubs table must be first initialized
using one of \fBTcl_InitSubsystems\fR, \fBTcl_SetPanicProc\fR,
\fBTcl_FindExecutable\fR
or \fBTclZipfs_AppHook\fR before \fBTcl_SetPreInitScript\fR may be called.
.SH "SEE ALSO"
Tcl_AppInit, Tcl_Main

.SH KEYWORDS
application, initialization, interpreter

Changes to doc/InitStubs.3.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25







+







Tcl_InitStubs \- initialize the Tcl stubs mechanism
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
const char *
\fBTcl_InitStubs\fR(\fIinterp, version, exact\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Tcl interpreter handle.
.AP "const char" *version in
A version string consisting of one or more decimal numbers
separated by dots.
60
61
62
63
64
65
66
67
68


69
70
71
72
73
74
75
61
62
63
64
65
66
67


68
69
70
71
72
73
74
75
76







-
-
+
+







Tcl functions.
.IP 2) 5
Define the \fBUSE_TCL_STUBS\fR symbol.  Typically, you would include the
\fB\-DUSE_TCL_STUBS\fR flag when compiling the extension.
.IP 3) 5
Link the extension with the Tcl stubs library instead of the standard
Tcl library.  For example, to use the Tcl 9.0 ABI on Unix platforms,
the library name is \fIlibtclstub9.0.a\fR; on Windows platforms, the
library name is \fItclstub90.lib\fR.
the library name is \fIlibtclstub.a\fR; on Windows platforms, the
library name is \fItclstub.lib\fR.
.PP
If the extension also requires the Tk API, it must also call
\fBTk_InitStubs\fR to initialize the Tk stubs interface and link
with the Tk stubs libraries.  See the \fBTk_InitStubs\fR page for
more information.
.SH DESCRIPTION
\fBTcl_InitStubs\fR attempts to initialize the stub table pointers

Changes to doc/InitSubSyst.3.

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
30
31
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
30
31

32
33
34
35
36







-
+







-
-
+
+
+
+






+
+
+



-
+




'\"
'\" Copyright (c) 2018 Tcl Core Team
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
.TH Tcl_InitSubsystems 3 8.7 Tcl "Tcl Library Procedures"
.TH Tcl_InitSubsystems 3 9.0 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_InitSubsystems \- initialize the Tcl library.
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
void
\fBTcl_InitSubsystems\fR(\fIvoid\fR)
const char *
\fBTcl_InitSubsystems\fR()
.fi
.BE
.SH DESCRIPTION
.PP
The \fBTcl_InitSubsystems\fR procedure initializes the Tcl
library. This procedure is typically invoked as the very
first thing in the application's main program.
.PP
The result of \fBTcl_InitSubsystems\fR is the full Tcl version with
build information (e.g., \fB9.0.0+abcdef...abcdef.gcc-1002\fR).
.PP
\fBTcl_InitSubsystems\fR is very similar in use to
\fBTcl_FindExecutable\fR. It can be used when Tcl is
used as utility library, no other encodings than utf-8,
iso8859-1 or unicode are used, and no interest exists in the
iso8859-1 or utf-16 are used, and no interest exists in the
value of \fBinfo nameofexecutable\fR. The system encoding will not
be extracted from the environment, but falls back to utf-8.
.SH KEYWORDS
binary, executable file

Changes to doc/IntObj.3.

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
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
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
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










-
+













+
+
+






+
+




-
+







+
+
+
+
+
+
















+


-
+







+
+


+












+
+


+
+
+
+




















-
+




-
-
-
+
+
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+












-
+
+







'\"
'\" Copyright (c) 1996-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_IntObj 3 8.5 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_NewIntObj, Tcl_NewLongObj, Tcl_NewWideIntObj, Tcl_SetIntObj, Tcl_SetLongObj, Tcl_SetWideIntObj, Tcl_GetIntFromObj, Tcl_GetIntForIndex, Tcl_GetLongFromObj, Tcl_GetWideIntFromObj, Tcl_NewBignumObj, Tcl_SetBignumObj, Tcl_GetBignumFromObj, Tcl_TakeBignumFromObj \- manipulate Tcl values as integers
Tcl_NewIntObj, Tcl_NewLongObj, Tcl_NewWideIntObj, Tcl_NewWideUIntObj, Tcl_SetIntObj, Tcl_SetLongObj, Tcl_SetWideIntObj, Tcl_SetWideUIntObj, Tcl_GetIntFromObj, Tcl_GetIntForIndex, Tcl_GetLongFromObj, Tcl_GetWideIntFromObj, Tcl_GetWideUIntFromObj, Tcl_NewBignumObj, Tcl_SetBignumObj, Tcl_GetBignumFromObj, Tcl_TakeBignumFromObj \- manipulate Tcl values as integers
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Obj *
\fBTcl_NewIntObj\fR(\fIintValue\fR)
.sp
Tcl_Obj *
\fBTcl_NewLongObj\fR(\fIlongValue\fR)
.sp
Tcl_Obj *
\fBTcl_NewWideIntObj\fR(\fIwideValue\fR)
.sp
Tcl_Obj *
\fBTcl_NewWideUIntObj\fR(\fIuwideValue\fR)
.sp
\fBTcl_SetIntObj\fR(\fIobjPtr, intValue\fR)
.sp
\fBTcl_SetLongObj\fR(\fIobjPtr, longValue\fR)
.sp
\fBTcl_SetWideIntObj\fR(\fIobjPtr, wideValue\fR)
.sp
\fBTcl_SetWideUIntObj\fR(\fIobjPtr, uwideValue\fR)
.sp
int
\fBTcl_GetIntFromObj\fR(\fIinterp, objPtr, intPtr\fR)
.sp
int
\fBTcl_GetIntForIndex\fR(\fIinterp, objPtr, endValue, intPtr\fR)
\fBTcl_GetIntForIndex\fR(\fIinterp, objPtr, endValue, indexPtr\fR)
.sp
int
\fBTcl_GetLongFromObj\fR(\fIinterp, objPtr, longPtr\fR)
.sp
int
\fBTcl_GetWideIntFromObj\fR(\fIinterp, objPtr, widePtr\fR)
.sp
int
\fBTcl_GetWideUIntFromObj\fR(\fIinterp, objPtr, uwidePtr\fR)
.sp
int
\fBTcl_GetSizeIntFromObj\fR(\fIinterp, objPtr, sizePtr\fR)
.sp
.sp
\fB#include <tclTomMath.h>\fR
.sp
Tcl_Obj *
\fBTcl_NewBignumObj\fR(\fIbigValue\fR)
.sp
\fBTcl_SetBignumObj\fR(\fIobjPtr, bigValue\fR)
.sp
int
\fBTcl_GetBignumFromObj\fR(\fIinterp, objPtr, bigValue\fR)
.sp
int
\fBTcl_TakeBignumFromObj\fR(\fIinterp, objPtr, bigValue\fR)
.sp
int
\fBTcl_InitBignumFromDouble\fR(\fIinterp, doubleValue, bigValue\fR)
.fi
.SH ARGUMENTS
.AS Tcl_WideInt doubleValue in/out
.AP int endValue in
.AP Tcl_Size endValue in
\fBTcl_GetIntForIndex\fR will return this when the input value is "end".
.AP int intValue in
Integer value used to initialize or set a Tcl value.
.AP long longValue in
Long integer value used to initialize or set a Tcl value.
.AP Tcl_WideInt wideValue in
Wide integer value used to initialize or set a Tcl value.
.AP Tcl_WideUInt uwideValue in
Unsigned wide integer value used to initialize or set a Tcl value.
.AP Tcl_Obj *objPtr in/out
For \fBTcl_SetIntObj\fR, \fBTcl_SetLongObj\fR, \fBTcl_SetWideIntObj\fR,
\fBTcl_SetWideUIntObj\fR,
and \fBTcl_SetBignumObj\fR, this points to the value in which to store an
integral value.  For \fBTcl_GetIntFromObj\fR, \fBTcl_GetLongFromObj\fR,
\fBTcl_GetWideIntFromObj\fR, \fBTcl_GetBignumFromObj\fR, and
\fBTcl_TakeBignumFromObj\fR, this refers to the value from which
to retrieve an integral value.
.AP Tcl_Interp *interp in/out
When non-NULL, an error message is left here when integral value
retrieval fails.
.AP int *intPtr out
Points to place to store the integer value retrieved from \fIobjPtr\fR.
.AP long *longPtr out
Points to place to store the long integer value retrieved from \fIobjPtr\fR.
.AP Tcl_Size *indexPtr out
Points to place to store the Tcl_Size value retrieved from \fIobjPtr\fR.
.AP Tcl_WideInt *widePtr out
Points to place to store the wide integer value retrieved from \fIobjPtr\fR.
.AP Tcl_WideUInt *uwidePtr out
Points to place to store the unsigned wide integer value retrieved from \fIobjPtr\fR.
.AP Tcl_Size *sizePtr out
Points to place to store the \fBTcl_Size\fR integer value retrieved from \fIobjPtr\fR.
.AP mp_int *bigValue in/out
Points to a multi-precision integer structure declared by the LibTomMath
library.
.AP double doubleValue in
Double value from which the integer part is determined and
used to initialize a multi-precision integer value.
.BE
.SH DESCRIPTION
.PP
These procedures are used to create, modify, and read Tcl values
that hold integral values.
.PP
The different routines exist to accommodate different integral types in C
with which values might be exchanged.  The C integral types for which Tcl
provides value exchange routines are \fBint\fR, \fBlong int\fR,
\fBTcl_WideInt\fR, and \fBmp_int\fR.  The \fBint\fR and \fBlong int\fR types
are provided by the C language standard.  The \fBTcl_WideInt\fR type is a
typedef defined to be whatever signed integral type covers at least the
64-bit integer range (-9223372036854775808 to 9223372036854775807).  Depending
on the platform and the C compiler, the actual type might be
\fBlong long int\fR, \fB__int64\fR, or something else.
\fBlong long int\fR, or something else.
The \fBmp_int\fR type is a multiple-precision integer type defined
by the LibTomMath multiple-precision integer library.
.PP
The \fBTcl_NewIntObj\fR, \fBTcl_NewLongObj\fR, \fBTcl_NewWideIntObj\fR,
and \fBTcl_NewBignumObj\fR routines each create and return a new
Tcl value initialized to the integral value of the argument.  The
returned Tcl value is unshared.
\fBTcl_NewWideUIntObj\fR, and \fBTcl_NewBignumObj\fR
routines each create and return a new Tcl value initialized to the
integral value of the argument.  The returned Tcl value is unshared.
.PP
The \fBTcl_SetIntObj\fR, \fBTcl_SetLongObj\fR, \fBTcl_SetWideIntObj\fR,
and \fBTcl_SetBignumObj\fR routines each set the value of an existing
Tcl value pointed to by \fIobjPtr\fR to the integral value provided
by the other argument.  The \fIobjPtr\fR argument must point to an
unshared Tcl value.  Any attempt to set the value of a shared Tcl value
violates Tcl's copy-on-write policy.  Any existing string representation
or internal representation in the unshared Tcl value will be freed
as a consequence of setting the new value.
\fBTcl_SetWideUIntObj\fR, and \fBTcl_SetBignumObj\fR
routines each set the value of an existing Tcl value pointed to by \fIobjPtr\fR
to the integral value provided by the other argument.  The \fIobjPtr\fR
argument must point to an unshared Tcl value.  Any attempt to set the
value of a shared Tcl value violates Tcl's copy-on-write policy.  Any
existing string representation or internal representation in the unshared
Tcl value will be freed as a consequence of setting the new value.
.PP
The \fBTcl_GetIntForIndex\fR routine attempts to retrieve an index
value from the Tcl value \fIobjPtr\fR.  If the attempt succeeds,
then \fBTCL_OK\fR is returned, and the value is written to the
storage provided by the caller.  The attempt might fail if
\fIobjPtr\fR does not hold an index value.  If the attempt fails,
then \fBTCL_ERROR\fR is returned, and if \fIinterp\fR is non-NULL,
an error message is left in \fIinterp\fR.  The \fBTcl_ObjType\fR
of \fIobjPtr\fR may be changed to make subsequent calls to the
same routine more efficient.
.PP
The \fBTcl_GetIntFromObj\fR, \fBTcl_GetLongFromObj\fR,
\fBTcl_GetWideIntFromObj\fR, \fBTcl_GetBignumFromObj\fR, and
\fBTcl_GetWideIntFromObj\fR, \fBTcl_GetSizeIntFromObj\fR,
\fBTcl_GetBignumFromObj\fR, and
\fBTcl_TakeBignumFromObj\fR routines attempt to retrieve an integral
value of the appropriate type from the Tcl value \fIobjPtr\fR.  If the
attempt succeeds, then \fBTCL_OK\fR is returned, and the value is
written to the storage provided by the caller.  The attempt might
fail if \fIobjPtr\fR does not hold an integral value, or if the
value exceeds the range of the target type.  If the attempt fails,
then \fBTCL_ERROR\fR is returned, and if \fIinterp\fR is non-NULL,
156
157
158
159
160
161
162





















163
164
165
166
167
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





If anything later in the caller requires
\fIobjPtr\fR to continue to hold the same value, then
\fBTcl_GetBignumFromObj\fR must be chosen.
.PP
The \fBTcl_InitBignumFromDouble\fR routine is a utility procedure
that extracts the integer part of \fIdoubleValue\fR and stores that
integer value in the \fBmp_int\fR value \fIbigValue\fR.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
\fBTcl_NewIntObj\fR, \fBTcl_NewLongObj\fR, \fBTcl_NewWideIntObj\fR, and
\fBTcl_NewBignumObj\fR always return a zero-reference object, much like
\fBTcl_NewObj\fR.
.PP
\fBTcl_SetIntObj\fR, \fBTcl_SetLongObj\fR, \fBTcl_SetWideIntObj\fR, and
\fBTcl_SetBignumObj\fR do not modify the reference count of their \fIobjPtr\fR
arguments, but do require that the object be unshared.
.PP
\fBTcl_GetIntFromObj\fR, \fBTcl_GetIntForIndex\fR, \fBTcl_GetLongFromObj\fR,
\fBTcl_GetWideIntFromObj\fR, \fBTcl_GetBignumFromObj\fR, and
\fBTcl_TakeBignumFromObj\fR do not modify the reference count of their
\fIobjPtr\fR arguments; they only read. Note however that this function may
set the interpreter result; if that is the only place that is holding a
reference to the object, it will be deleted. Also note that if
\fBTcl_TakeBignumFromObj\fR is given an unshared value, the value of that
object may be modified; it is intended to be used when the value is
.QW consumed
by the operation at this point.

.SH "SEE ALSO"
Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_GetObjResult
.SH KEYWORDS
integer, integer value, integer type, internal representation, value,
value type, string representation

Changes to doc/Limit.3.

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
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







-


-





-


-


-





-


-


-

+








-
+







.sp
int
\fBTcl_LimitTypeExceeded\fR(\fIinterp, type\fR)
.sp
int
\fBTcl_LimitTypeEnabled\fR(\fIinterp, type\fR)
.sp
void
\fBTcl_LimitTypeSet\fR(\fIinterp, type\fR)
.sp
void
\fBTcl_LimitTypeReset\fR(\fIinterp, type\fR)
.sp
int
\fBTcl_LimitGetCommands\fR(\fIinterp\fR)
.sp
void
\fBTcl_LimitSetCommands\fR(\fIinterp, commandLimit\fR)
.sp
void
\fBTcl_LimitGetTime\fR(\fIinterp, timeLimitPtr\fR)
.sp
void
\fBTcl_LimitSetTime\fR(\fIinterp, timeLimitPtr\fR)
.sp
int
\fBTcl_LimitGetGranularity\fR(\fIinterp, type\fR)
.sp
void
\fBTcl_LimitSetGranularity\fR(\fIinterp, type, granularity\fR)
.sp
void
\fBTcl_LimitAddHandler\fR(\fIinterp, type, handlerProc, clientData, deleteProc\fR)
.sp
void
\fBTcl_LimitRemoveHandler\fR(\fIinterp, type, handlerProc, clientData\fR)
.fi
.SH ARGUMENTS
.AS Tcl_LimitHandlerDeleteProc commandLimit in/out
.AP Tcl_Interp *interp in
Interpreter that the limit being managed applies to or that will have
its limits checked.
.AP int type in
The type of limit that the operation refers to.  This must be either
\fBTCL_LIMIT_COMMANDS\fR or \fBTCL_LIMIT_TIME\fR.
.AP int commandLimit in
.AP Tcl_Size commandLimit in
The maximum number of commands (as reported by \fBinfo cmdcount\fR)
that may be executed in the interpreter.
.AP Tcl_Time *timeLimitPtr in/out
A pointer to a structure that will either have the new time limit read
from (\fBTcl_LimitSetTime\fR) or the current time limit written to
(\fBTcl_LimitGetTime\fR).
.AP int granularity in

Changes to doc/LinkVar.3.

21
22
23
24
25
26
27

28
29
30
31
32
33
34
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35







+







int
\fBTcl_LinkArray\fR(\fIinterp, varName, addr, type, size\fR)
.VE "TIP 312"
.sp
\fBTcl_UnlinkVar\fR(\fIinterp, varName\fR)
.sp
\fBTcl_UpdateLinkedVar\fR(\fIinterp, varName\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp varName in
.AP Tcl_Interp *interp in
Interpreter that contains \fIvarName\fR.
Also used by \fBTcl_LinkVar\fR to return error messages.
.AP "const char" *varName in
Name of global variable.
49
50
51
52
53
54
55
56

57
58
59
60
61
62

63
64
65
66
67
68
69
50
51
52
53
54
55
56

57
58
59
60
61
62

63
64
65
66
67
68
69
70







-
+





-
+







\fBTCL_LINK_BOOLEAN\fR, or one of the extra ones listed below.
.sp
In \fBTcl_LinkVar\fR, the additional linked type \fBTCL_LINK_STRING\fR may be
used.
.sp
.VS "TIP 312"
In \fBTcl_LinkArray\fR, the additional linked types \fBTCL_LINK_CHARS\fR and
\fBTCL_LINK_BYTES\fR may be used.
\fBTCL_LINK_BINARY\fR may be used.
.VE "TIP 312"
.sp
All the above for both functions may be
optionally OR'ed with \fBTCL_LINK_READ_ONLY\fR to make the Tcl
variable read-only.
.AP size_t size in
.AP Tcl_Size size in
.VS "TIP 312"
The number of elements in the C array. Must be greater than zero.
.VE "TIP 312"
.BE
.SH DESCRIPTION
.PP
\fBTcl_LinkVar\fR uses variable traces to keep the Tcl variable
142
143
144
145
146
147
148
149

150
151
152
153

154
155
156
157
158
159
160
143
144
145
146
147
148
149

150
151
152
153

154
155
156
157
158
159
160
161







-
+



-
+







write non-integer values (or values outside the range) into
\fIvarName\fR will be rejected with Tcl errors. Incomplete integer
representations (like the empty string, '+', '-' or the hex/octal/decimal/binary
prefix) are accepted as if they are valid too.
.RS
.PP
.VS "TIP 312"
If using an array of these, consider using \fBTCL_LINK_BYTES\fR instead.
If using an array of these, consider using \fBTCL_LINK_BINARY\fR instead.
.VE "TIP 312"
.RE
.TP
\fBTCL_LINK_BYTES\fR
\fBTCL_LINK_BINARY\fR
.VS "TIP 312"
The C array is of type \fBunsigned char *\fR and is mapped into Tcl
as a bytearray.
Any value written into the Tcl variable must have the same length as
the underlying storage. Only supported with \fBTcl_LinkArray\fR.
.VE "TIP 312"
.TP
235
236
237
238
239
240
241
242

243
244
245
246
247
248
249
250
251
236
237
238
239
240
241
242

243


244
245
246
247
248
249
250







-
+
-
-







.TP
\fBTCL_LINK_WIDE_UINT\fR
.
The C variable, or each element of the C array, is of type \fBTcl_WideUInt\fR
(which is an unsigned integer type at least 64-bits wide on all platforms that
can support it.)
Any value written into the Tcl variable must have a proper unsigned
integer form acceptable to \fBTcl_GetWideIntFromObj\fR (it will be
wideinteger form acceptable to \fBTcl_GetWideUIntFromObj\fR;
cast to unsigned);
.\" FIXME! Use bignums instead.
attempts to write non-integer values into \fIvarName\fR will be
rejected with Tcl errors. Incomplete integer representations (like
the empty string, '+', '-' or the hex/octal/decimal/binary prefix) are accepted
as if they are valid too.
.TP
\fBTCL_LINK_BOOLEAN\fR
.

Changes to doc/ListObj.3.

24
25
26
27
28
29
30
31

32
33
34
35
36
37

38
39
40
41
42
43
44
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45







-
+






+







.sp
\fBTcl_SetListObj\fR(\fIobjPtr, objc, objv\fR)
.sp
int
\fBTcl_ListObjGetElements\fR(\fIinterp, listPtr, objcPtr, objvPtr\fR)
.sp
int
\fBTcl_ListObjLength\fR(\fIinterp, listPtr, intPtr\fR)
\fBTcl_ListObjLength\fR(\fIinterp, listPtr, lengthPtr\fR)
.sp
int
\fBTcl_ListObjIndex\fR(\fIinterp, listPtr, index, objPtrPtr\fR)
.sp
int
\fBTcl_ListObjReplace\fR(\fIinterp, listPtr, first, count, objc, objv\fR)
.fi
.SH ARGUMENTS
.AS "Tcl_Obj *const" *elemListPtr in/out
.AP Tcl_Interp *interp in
If an error occurs while converting a value to be a list value,
an error message is left in the interpreter's result value
unless \fIinterp\fR is NULL.
.AP Tcl_Obj *listPtr in/out
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
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







-
+


+
+
+
+
+



-
+










-
+


+
+
+
+
+
-
+






-
+



-
+







an attempt will be made to convert it to one.
.AP Tcl_Obj *objPtr in
For \fBTcl_ListObjAppendElement\fR,
points to the Tcl value that will be appended to \fIlistPtr\fR.
For \fBTcl_SetListObj\fR,
this points to the Tcl value that will be converted to a list value
containing the \fIobjc\fR elements of the array referenced by \fIobjv\fR.
.AP int *objcPtr in
.AP "Tcl_Size \&| int" *objcPtr in
Points to location where \fBTcl_ListObjGetElements\fR
stores the number of element values in \fIlistPtr\fR.
May be (Tcl_Size *)NULL when not used. If it points to a variable which
type is not \fBTcl_Size\fR, a compiler warning will be generated.
If your extensions is compiled with -DTCL_8_API, this function will return
NULL for lists with more than INT_MAX elements (which should
trigger proper error-handling), otherwise expect it to crash.
.AP Tcl_Obj ***objvPtr out
A location where \fBTcl_ListObjGetElements\fR stores a pointer to an array
of pointers to the element values of \fIlistPtr\fR.
.AP int objc in
.AP Tcl_Size objc in
The number of Tcl values that \fBTcl_NewListObj\fR
will insert into a new list value,
and \fBTcl_ListObjReplace\fR will insert into \fIlistPtr\fR.
For \fBTcl_SetListObj\fR,
the number of Tcl values to insert into \fIobjPtr\fR.
.AP "Tcl_Obj *const" objv[] in
An array of pointers to values.
\fBTcl_NewListObj\fR will insert these values into a new list value
and \fBTcl_ListObjReplace\fR will insert them into an existing \fIlistPtr\fR.
Each value will become a separate list element.
.AP int *intPtr out
.AP "Tcl_Size \&| int" *lengthPtr out
Points to location where \fBTcl_ListObjLength\fR
stores the length of the list.
May be (Tcl_Size *)NULL when not used. If it points to a variable which
type is not \fBTcl_Size\fR, a compiler warning will be generated.
If your extensions is compiled with -DTCL_8_API, this function will return
TCL_ERROR for lists with more than INT_MAX elements (which should
trigger proper error-handling), otherwise expect it to crash.
.AP int index in
.AP Tcl_Size index in
Index of the list element that \fBTcl_ListObjIndex\fR
is to return.
The first element has index 0.
.AP Tcl_Obj **objPtrPtr out
Points to place where \fBTcl_ListObjIndex\fR is to store
a pointer to the resulting list element value.
.AP int first in
.AP Tcl_Size first in
Index of the starting list element that \fBTcl_ListObjReplace\fR
is to replace.
The list's first element has index 0.
.AP int count in
.AP Tcl_Size count in
The number of elements that \fBTcl_ListObjReplace\fR
is to replace.
.BE

.SH DESCRIPTION
.PP
Tcl list values have an internal representation that supports
149
150
151
152
153
154
155
156



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
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







-
+
+
+








-







.PP
\fBTcl_ListObjGetElements\fR returns a count and a pointer to an array of
the elements in a list value.  It returns the count by storing it in the
address \fIobjcPtr\fR.  Similarly, it returns the array pointer by storing
it in the address \fIobjvPtr\fR.
The memory pointed to is managed by Tcl and should not be freed or written
to by the caller. If the list is empty, 0 is stored at \fIobjcPtr\fR
and NULL at \fIobjvPtr\fR.
and NULL at \fIobjvPtr\fR. If \fIobjcPtr\fR points to a variable
of type \fBint\fR and the list contains more than 2**31 elements, the
function returns \fBTCL_ERROR\fR.
If \fIlistPtr\fR is not already a list value, \fBTcl_ListObjGetElements\fR
will attempt to convert it to one; if the conversion fails, it returns
\fBTCL_ERROR\fR and leaves an error message in the interpreter's result
value if \fIinterp\fR is not NULL.
Otherwise it returns \fBTCL_OK\fR after storing the count and array pointer.
.PP
\fBTcl_ListObjLength\fR returns the number of elements in the list value
referenced by \fIlistPtr\fR.
It returns this count by storing an integer in the address \fIintPtr\fR.
If the value is not already a list value,
\fBTcl_ListObjLength\fR will attempt to convert it to one;
if the conversion fails, it returns \fBTCL_ERROR\fR
and leaves an error message in the interpreter's result value
if \fIinterp\fR is not NULL.
Otherwise it returns \fBTCL_OK\fR after storing the list's length.
.PP
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





by simply calling \fBTcl_ListObjReplace\fR
with a NULL \fIobjvPtr\fR:
.PP
.CS
result = \fBTcl_ListObjReplace\fR(interp, listPtr, first, count,
        0, NULL);
.CE
.SH "REFERENCE COUNT MANAGEMENT"
.PP
\fBTcl_NewListObj\fR always returns a zero-reference object, much like
\fBTcl_NewObj\fR. If a non-NULL \fIobjv\fR argument is given, the reference
counts of the first \fIobjc\fR values in that array are incremented.
.PP
\fBTcl_SetListObj\fR does not modify the reference count of its \fIobjPtr\fR
argument, but does require that the object be unshared. The reference counts
of the first \fIobjc\fR values in the \fIobjv\fR array are incremented.
.PP
\fBTcl_ListObjGetElements\fR, \fBTcl_ListObjIndex\fR, and
\fBTcl_ListObjLength\fR do not modify the reference count of their
\fIlistPtr\fR arguments; they only read. Note however that these three
functions may set the interpreter result; if that is the only place that is
holding a reference to the object, it will be deleted.
.PP
\fBTcl_ListObjAppendList\fR, \fBTcl_ListObjAppendElement\fR, and
\fBTcl_ListObjReplace\fR require an unshared \fIlistPtr\fR argument.
\fBTcl_ListObjAppendList\fR only reads its \fIelemListPtr\fR argument.
\fBTcl_ListObjAppendElement\fR increments the reference count of its
\fIobjPtr\fR on success. \fBTcl_ListObjReplace\fR increments the reference
count of the first \fIobjc\fR values in the \fIobjv\fR array on success.  Note
however that all these three functions may set the interpreter result on
failure; if that is the only place that is holding a reference to the object,
it will be deleted.
.SH "SEE ALSO"
Tcl_NewObj(3), Tcl_DecrRefCount(3), Tcl_IncrRefCount(3), Tcl_GetObjResult(3)
.SH KEYWORDS
append, index, insert, internal representation, length, list, list value,
list type, value, value type, replace, string representation

Changes to doc/Load.3.

15
16
17
18
19
20
21

22
23
24
25
26
27
28
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29







+







\fB#include <tcl.h>\fR
.sp
int
\fBTcl_LoadFile\fR(\fIinterp, pathPtr, symbols, flags, procPtrs, loadHandlePtr\fR)
.sp
void *
\fBTcl_FindSymbol\fR(\fIinterp, loadHandle, symbol\fR)
.fi
.SH ARGUMENTS
.AS Tcl_LoadHandle loadHandle in
.AP Tcl_Interp *interp in
Interpreter to use for reporting error messages.
.AP Tcl_Obj *pathPtr in
The name of the file to load. If it is a single name, the library search path
of the current environment will be used to resolve it.
56
57
58
59
60
61
62




63
64
65
66
67
68
69
70
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75







+
+
+
+








The result of \fBTcl_LoadFile\fR is a standard Tcl error code. The library may
be unloaded with \fBTcl_FSUnloadFile\fR.
.PP
\fBTcl_FindSymbol\fR locates a symbol in a loaded library and returns it. If
the symbol cannot be found, it returns NULL and sets an error message in the
given \fIinterp\fR (if that is non-NULL). Note that it is unsafe to use this
operation on a handle that has been passed to \fBTcl_FSUnloadFile\fR.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
The reference count of the \fIpathPtr\fR argument to \fBTcl_LoadFile\fR may be
incremented. As such, it should not be given a zero reference count value.
.SH "SEE ALSO"
Tcl_FSLoadFile(3), Tcl_FSUnloadFile(3), load(n), unload(n)
.SH KEYWORDS
binary code, loading, shared library
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/Method.3.

54
55
56
57
58
59
60
61

62

63
64
65
66
67
68
69
54
55
56
57
58
59
60

61
62
63
64
65
66
67
68
69
70







-
+

+







.sp
Tcl_Method
\fBTcl_ObjectContextMethod\fR(\fIcontext\fR)
.sp
Tcl_Object
\fBTcl_ObjectContextObject\fR(\fIcontext\fR)
.sp
int
Tcl_Size
\fBTcl_ObjectContextSkippedArgs\fR(\fIcontext\fR)
.fi
.SH ARGUMENTS
.AS void *clientData in
.AP Tcl_Interp *interp in/out
The interpreter holding the object or class to create or update a method in.
.AP Tcl_Object object in
The object to create the method in.
.AP Tcl_Class class in
91
92
93
94
95
96
97
98

99
100
101
102

103
104
105
106
107
108
109
92
93
94
95
96
97
98

99
100
101
102

103
104
105
106
107
108
109
110







-
+



-
+







when the method was created. If NULL, the \fIclientData\fR value will not be
retrieved.
.AP Tcl_Method method in
A reference to a method to query.
.AP Tcl_ObjectContext context in
A reference to a method-call context. Note that client code \fImust not\fR
retain a reference to a context.
.AP int objc in
.AP Tcl_Size objc in
The number of arguments to pass to the method implementation.
.AP "Tcl_Obj *const" *objv in
An array of arguments to pass to the method implementation.
.AP int skip in
.AP Tcl_Size skip in
The number of arguments passed to the method implementation that do not
represent "real" arguments.
.BE
.SH DESCRIPTION
.PP
A method is an operation carried out on an object that is associated with the
object. Every method must be attached to either an object or a class; methods
254
255
256
257
258
259
260
























261
262

263
264
265
266
267
268
269
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+







.PP
The \fIinterp\fR argument gives a place to write an error message when the
attempt to clone the object is to fail, in which case the clone procedure must
also return TCL_ERROR; it should return TCL_OK otherwise.
The \fIoldClientData\fR field to a Tcl_CloneProc gives the value from the
method being copied from, and the \fInewClientDataPtr\fR field will point to
a variable in which to write the value for the method being copied to.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
The \fInameObj\fR argument to \fBTcl_NewMethod\fR and
\fBTcl_NewInstanceMethod\fR (when non-NULL) will have its reference count
incremented if there is no existing method with that name in that
class/object.
.PP
The result of \fBTcl_MethodName\fR is a value with a reference count of at
least one. It should not be modified without first duplicating it (with
\fBTcl_DuplicateObj\fR).
.PP
The values in the first \fIobjc\fR values of the \fIobjv\fR argument to
\fBTcl_ObjectContextInvokeNext\fR are assumed to have a reference count of at
least 1; the containing array is assumed to endure until the next method
implementation (see \fBnext\fR) returns. Be aware that methods may
\fByield\fR; if any post-call actions are desired (e.g., decrementing the
reference count of values passed in here), they must be scheduled with
\fBTcl_NRAddCallback\fR.
.PP
The \fIcallProc\fR of the \fBTcl_MethodType\fR structure takes values of at
least reference count 1 in its \fIobjv\fR argument. It may add its own
references, but must not decrement the reference count below that level; the
caller of the method will decrement the reference count once the method
returns properly (and the reference will be held if the method \fByield\fRs).
.SH "SEE ALSO"
Class(3), oo::class(n), oo::define(n), oo::object(n)
Class(3), NRE(3), oo::class(n), oo::define(n), oo::object(n)
.SH KEYWORDS
constructor, method, object

.\" Local variables:
.\" mode: nroff
.\" fill-column: 78
.\" End:

Changes to doc/NRE.3.

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
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
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
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

-
-
+
+








-
+








+
+
+
+



+
+
+












-






-
+






+
+
+
+
+


+
+






-
+







.\"
.\" Copyright (c) 2008 by Kevin B. Kenny.
.\" Copyright (c) 2018 by Nathan Coulter.
.\" Copyright (c) 2008 Kevin B. Kenny.
.\" Copyright (c) 2018 Nathan Coulter.
.\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH NRE 3 8.6 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_NRCreateCommand, Tcl_NRCallObjProc, Tcl_NREvalObj, Tcl_NREvalObjv, Tcl_NRCmdSwap, Tcl_NRExprObj, Tcl_NRAddCallback \- Non-Recursive (stackless) evaluation of Tcl scripts.
Tcl_NRCreateCommand, Tcl_NRCreateCommand2, Tcl_NRCallObjProc, Tcl_NRCallObjProc2, Tcl_NREvalObj, Tcl_NREvalObjv, Tcl_NRCmdSwap, Tcl_NRExprObj, Tcl_NRAddCallback \- Non-Recursive (stackless) evaluation of Tcl scripts.
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Command
\fBTcl_NRCreateCommand\fR(\fIinterp, cmdName, proc, nreProc, clientData,
                    deleteProc\fR)
.sp
Tcl_Command
\fBTcl_NRCreateCommand2\fR(\fIinterp, cmdName, proc2, nreProc2, clientData,
                    deleteProc\fR)
.sp
int
\fBTcl_NRCallObjProc\fR(\fIinterp, nreProc, clientData, objc, objv\fR)
.sp
int
\fBTcl_NRCallObjProc2\fR(\fIinterp, nreProc2, clientData, objc, objv\fR)
.sp
int
\fBTcl_NREvalObj\fR(\fIinterp, objPtr, flags\fR)
.sp
int
\fBTcl_NREvalObjv\fR(\fIinterp, objc, objv, flags\fR)
.sp
int
\fBTcl_NRCmdSwap\fR(\fIinterp, cmd, objc, objv, flags\fR)
.sp
int
\fBTcl_NRExprObj\fR(\fIinterp, objPtr, resultPtr\fR)
.sp
void
\fBTcl_NRAddCallback\fR(\fIinterp, postProcPtr, data0, data1, data2, data3\fR)
.fi
.SH ARGUMENTS
.AS Tcl_CmdDeleteProc *interp in
.AP Tcl_Interp *interp in
The relevant Interpreter.
.AP char *cmdName in
.AP "const char" *cmdName in
Name of the command to create.
.AP Tcl_ObjCmdProc *proc in
Called in order to evaluate a command.  Is often just a small wrapper that uses
\fBTcl_NRCallObjProc\fR to call \fInreProc\fR using a new trampoline.  Behaves
in the same way as the \fIproc\fR argument to \fBTcl_CreateObjCommand\fR(3)
(\fIq.v.\fR).
.AP Tcl_ObjCmdProc2 *proc2 in
Called in order to evaluate a command.  Is often just a small wrapper that uses
\fBTcl_NRCallObjProc2\fR to call \fInreProc2\fR using a new trampoline.  Behaves
in the same way as the \fIproc2\fR argument to \fBTcl_CreateObjCommand2\fR(3)
(\fIq.v.\fR).
.AP Tcl_ObjCmdProc *nreProc in
Called instead of \fIproc\fR when a trampoline is already in use.
.AP Tcl_ObjCmdProc2 *nreProc2 in
Called instead of \fIproc2\fR when a trampoline is already in use.
.AP void *clientData in
Arbitrary one-word value passed to \fIproc\fR, \fInreProc\fR, \fIdeleteProc\fR
and \fIobjProc\fR.
.AP Tcl_CmdDeleteProc *deleteProc in/out
Called before \fIcmdName\fR is deleted from the interpreter, allowing for
command-specific cleanup. May be NULL.
.AP int objc in
.AP Tcl_Size objc in
Number of items in \fIobjv\fR.
.AP Tcl_Obj **objv in
Words in the command.
.AP Tcl_Obj *objPtr in
A script or expression to evaluate.
.AP int flags in
As described for \fITcl_EvalObjv\fR.
99
100
101
102
103
104
105



106
107
108
109
110
111
112
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128







+
+
+







resolves \fIcmdName\fR, which may contain namespace qualifiers, relative to the
current namespace, creates a command by that name, and returns a token for the
command which may be used in subsequent calls to \fBTcl_GetCommandName\fR.
Except for a few cases noted below any existing command by the same name is
first deleted.  If \fIinterp\fR is in the process of being deleted
\fBTcl_NRCreateCommand\fR does not create any command, does not delete any
command, and returns NULL.
.PP
\fBTcl_NRCreateCommand2\fR, is an alternative to \fBTcl_NRCreateCommand\fR
in the same way as \fBTcl_CreateObjCommand2\fR.
.PP
\fBTcl_NREvalObj\fR pushes a function that is like \fBTcl_EvalObjEx\fR but
consumes no space on the C stack.
.PP
\fBTcl_NREvalObjv\fR pushes a function that is like \fBTcl_EvalObjv\fR but
consumes no space on the C stack.
.PP
137
138
139
140
141
142
143
144

145
146
147
148
149
150
151
153
154
155
156
157
158
159

160
161
162
163
164
165
166
167







-
+







.PP
\fIdata\fR is a pointer to an array containing \fIdata0\fR through \fIdata3\fR.
\fIresult\fR is the value returned by the previous function implementing part
the routine.
.SH EXAMPLE
.PP
The following command uses \fBTcl_EvalObjEx\fR, which consumes space on the C
stack, to evalute a script:
stack, to evaluate a script:
.PP
.CS
int
\fITheCmdOldObjProc\fR(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
223
224
225
226
227
228
229



















230
231
232
233
234
235
236


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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
-
+
+
    return result;
}
.CE
.PP
Any function comprising a routine can push other functions, making it possible
implement looping and sequencing constructs using the function stack.
.PP
.SH "REFERENCE COUNT MANAGEMENT"
.PP
The first \fIobjc\fR values in the \fIobjv\fR array passed to the functions
\fBTcl_NRCallObjProc\fR, \fBTcl_NREvalObjv\fR, and \fBTcl_NRCmdSwap\fR should
have a reference count of at least 1; they may have additional references
taken during the execution.
.PP
The \fIobjPtr\fR argument to \fBTcl_NREvalObj\fR and \fBTcl_NRExprObj\fR
should have a reference count of at least 1, and may have additional
references taken to it during execution.
.PP
The \fIresultObj\fR argument to \fBTcl_NRExprObj\fR should be an unshared
object.
.PP
Use \fBTcl_NRAddCallback\fR to schedule any required final decrementing of the
reference counts of arguments to any of the other functions on this page, as
with any other post-processing step in the non-recursive execution engine.
.PP
The
.SH "SEE ALSO"
Tcl_CreateCommand(3), Tcl_CreateObjCommand(3), Tcl_EvalObjEx(3), Tcl_GetCommandFromObj(3), Tcl_ExprObj(3)
.SH KEYWORDS
stackless, nonrecursive, execute, command, global, value, result, script
.SH COPYRIGHT
Copyright (c) 2008 by Kevin B. Kenny.
Copyright (c) 2018 by Nathan Coulter.
Copyright \(co 2008 Kevin B. Kenny.
Copyright \(co 2018 Nathan Coulter.

Changes to doc/Namespace.3.

42
43
44
45
46
47
48
49

50
51
52


53
54
55
56
57
58
59
42
43
44
45
46
47
48

49
50
51

52
53
54
55
56
57
58
59
60







-
+


-
+
+







Tcl_Namespace *
\fBTcl_FindNamespace\fR(\fIinterp, name, contextNsPtr, flags\fR)
.sp
Tcl_Command
\fBTcl_FindCommand\fR(\fIinterp, name, contextNsPtr, flags\fR)
.sp
Tcl_Obj *
\fBTcl_GetNamespaceUnknownHandler(\fIinterp, nsPtr\fR)
\fBTcl_GetNamespaceUnknownHandler\fR(\fIinterp, nsPtr\fR)
.sp
int
\fBTcl_SetNamespaceUnknownHandler(\fIinterp, nsPtr, handlerPtr\fR)
\fBTcl_SetNamespaceUnknownHandler\fR(\fIinterp, nsPtr, handlerPtr\fR)
.fi
.SH ARGUMENTS
.AS Tcl_NamespaceDeleteProc allowOverwrite in/out
.AP Tcl_Interp *interp in/out
The interpreter in which the namespace exists and where name lookups
are performed. Also where error result messages are written.
.AP "const char" *name in
The name of the namespace or command to be created or accessed.
129
130
131
132
133
134
135
136

137
138
139
140
141
142
143
130
131
132
133
134
135
136

137
138
139
140
141
142
143
144







-
+







.PP
\fBTcl_Export\fR sets and appends to the export patterns for a
namespace.  Patterns are appended unless the \fIresetListFirst\fR flag
is true.
.PP
\fBTcl_Import\fR imports commands matching a pattern into a
namespace.  Note that the pattern must include the name of the
namespace to import from.  This function returns an error if
namespace to import from.  This function returns TCL_ERROR if
an attempt to import a command over an existing command is made,
unless the \fIallowOverwrite\fR flag has been set.
.PP
\fBTcl_ForgetImport\fR removes imports matching a pattern.
.PP
\fBTcl_GetCurrentNamespace\fR returns the current namespace for an
interpreter.
155
156
157
158
159
160
161












162
163
164
165
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178







+
+
+
+
+
+
+
+
+
+
+
+




.PP
\fBTcl_GetNamespaceUnknownHandler\fR returns the unknown command handler
for the namespace, or NULL if none is set.
.PP
\fBTcl_SetNamespaceUnknownHandler\fR sets the unknown command handler for
the namespace. If \fIhandlerPtr\fR is NULL, then the handler is reset to
its default.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
The \fIobjPtr\fR argument to \fBTcl_AppendExportList\fR should be an
unshared object, as it will be modified by this function. The
reference count of \fIobjPtr\fR will not be altered.
.PP
\fBTcl_GetNamespaceUnknownHandler\fR returns a possibly shared value.
Its reference count should be incremented if the value is to be
retained.
.PP
The \fIhandlerPtr\fR argument to \fBTcl_SetNamespaceUnknownHandler\fR
will have its reference count incremented if it is a non-empty list.
.SH "SEE ALSO"
Tcl_CreateCommand(3), Tcl_ListObjAppendList(3), Tcl_SetVar(3)
.SH KEYWORDS
namespace, command

Changes to doc/Notifier.3.

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
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







-


-


-


-


-


-





-





-





-


-














-


-

+




















-
+

-
+
+










-
+







.BS
.SH NAME
Tcl_CreateEventSource, Tcl_DeleteEventSource, Tcl_SetMaxBlockTime, Tcl_QueueEvent, Tcl_ThreadQueueEvent, Tcl_ThreadAlert, Tcl_GetCurrentThread, Tcl_DeleteEvents, Tcl_InitNotifier, Tcl_FinalizeNotifier, Tcl_WaitForEvent, Tcl_AlertNotifier, Tcl_SetTimer, Tcl_ServiceAll, Tcl_ServiceEvent, Tcl_GetServiceMode, Tcl_SetServiceMode, Tcl_ServiceModeHook, Tcl_SetNotifier \- the event queue and notifier interfaces
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
void
\fBTcl_CreateEventSource\fR(\fIsetupProc, checkProc, clientData\fR)
.sp
void
\fBTcl_DeleteEventSource\fR(\fIsetupProc, checkProc, clientData\fR)
.sp
void
\fBTcl_SetMaxBlockTime\fR(\fItimePtr\fR)
.sp
void
\fBTcl_QueueEvent\fR(\fIevPtr, position\fR)
.sp
void
\fBTcl_ThreadQueueEvent\fR(\fIthreadId, evPtr, position\fR)
.sp
void
\fBTcl_ThreadAlert\fR(\fIthreadId\fR)
.sp
Tcl_ThreadId
\fBTcl_GetCurrentThread\fR()
.sp
void
\fBTcl_DeleteEvents\fR(\fIdeleteProc, clientData\fR)
.sp
void *
\fBTcl_InitNotifier\fR()
.sp
void
\fBTcl_FinalizeNotifier\fR(\fIclientData\fR)
.sp
int
\fBTcl_WaitForEvent\fR(\fItimePtr\fR)
.sp
void
\fBTcl_AlertNotifier\fR(\fIclientData\fR)
.sp
void
\fBTcl_SetTimer\fR(\fItimePtr\fR)
.sp
int
\fBTcl_ServiceAll\fR()
.sp
int
\fBTcl_ServiceEvent\fR(\fIflags\fR)
.sp
int
\fBTcl_GetServiceMode\fR()
.sp
int
\fBTcl_SetServiceMode\fR(\fImode\fR)
.sp
void
\fBTcl_ServiceModeHook\fR(\fImode\fR)
.sp
void
\fBTcl_SetNotifier\fR(\fInotifierProcPtr\fR)
.fi
.SH ARGUMENTS
.AS Tcl_EventDeleteProc *notifierProcPtr
.AP Tcl_EventSetupProc *setupProc in
Procedure to invoke to prepare for event wait in \fBTcl_DoOneEvent\fR.
.AP Tcl_EventCheckProc *checkProc in
Procedure for \fBTcl_DoOneEvent\fR to invoke after waiting for
events.  Checks to see if any events have occurred and, if so,
queues them.
.AP void *clientData in
Arbitrary one-word value to pass to \fIsetupProc\fR, \fIcheckProc\fR, or
\fIdeleteProc\fR.
.AP "const Tcl_Time" *timePtr in
Indicates the maximum amount of time to wait for an event.  This
is specified as an interval (how long to wait), not an absolute
time (when to wakeup).  If the pointer passed to \fBTcl_WaitForEvent\fR
is NULL, it means there is no maximum wait time:  wait forever if
necessary.
.AP Tcl_Event *evPtr in
An event to add to the event queue.  The storage for the event must
have been allocated by the caller using \fBTcl_Alloc\fR.
.AP Tcl_QueuePosition position in
.AP int position in
Where to add the new event in the queue:  \fBTCL_QUEUE_TAIL\fR,
\fBTCL_QUEUE_HEAD\fR, or \fBTCL_QUEUE_MARK\fR.
\fBTCL_QUEUE_HEAD\fR, \fBTCL_QUEUE_MARK\fR, and whether to do
an alert if the queue is empty: \fBTCL_QUEUE_ALERT_IF_EMPTY\fR.
.AP Tcl_ThreadId threadId in
A unique identifier for a thread.
.AP Tcl_EventDeleteProc *deleteProc in
Procedure to invoke for each queued event in \fBTcl_DeleteEvents\fR.
.AP int flags in
What types of events to service.  These flags are the same as those
passed to \fBTcl_DoOneEvent\fR.
.AP int mode in
Indicates whether events should be serviced by \fBTcl_ServiceAll\fR.
Must be one of \fBTCL_SERVICE_NONE\fR or \fBTCL_SERVICE_ALL\fR.
.AP Tcl_NotifierProcs* notifierProcPtr in
.AP const Tcl_NotifierProcs* notifierProcPtr in
Structure of function pointers describing notifier procedures that are
to replace the ones installed in the executable.  See
\fBREPLACING THE NOTIFIER\fR for details.
.BE
.SH INTRODUCTION
.PP
The interfaces described here are used to customize the Tcl event
261
262
263
264
265
266
267
268
269


270
271
272
273
274
275
276
251
252
253
254
255
256
257


258
259
260
261
262
263
264
265
266







-
-
+
+







\fBTcl_WaitForEvent\fR does not block if there is no new data on the X
connection.
The \fItimePtr\fR argument to \fBTcl_WaitForEvent\fR points to
a structure that describes a time interval in seconds and
microseconds:
.PP
.CS
typedef struct Tcl_Time {
    long \fIsec\fR;
typedef struct {
    long long \fIsec\fR;
    long \fIusec\fR;
} \fBTcl_Time\fR;
.CE
.PP
The \fIusec\fR field should be less than 1000000.
.PP
Information provided to \fBTcl_SetMaxBlockTime\fR
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
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







-
+












-
+



-
+


-
+







+
+
+
+







define its own event structure with whatever information is relevant
to that event source.  However, the first element of the structure
must be a structure of type \fBTcl_Event\fR, and the address of this
structure is used when communicating between the event source and the
rest of the notifier.  A \fBTcl_Event\fR has the following definition:
.PP
.CS
typedef struct {
typedef struct Tcl_Event {
    Tcl_EventProc *\fIproc\fR;
    struct Tcl_Event *\fInextPtr\fR;
} \fBTcl_Event\fR;
.CE
.PP
The event source must fill in the \fIproc\fR field of
the event before calling \fBTcl_QueueEvent\fR.
The \fInextPtr\fR is used to link together the events in the queue
and should not be modified by the event source.
.PP
An event may be added to the queue at any of three positions, depending
on the \fIposition\fR argument to \fBTcl_QueueEvent\fR:
.IP \fBTCL_QUEUE_TAIL\fR 24
.IP \fBTCL_QUEUE_TAIL\fR 32
Add the event at the back of the queue, so that all other pending
events will be serviced first.  This is almost always the right
place for new events.
.IP \fBTCL_QUEUE_HEAD\fR 24
.IP \fBTCL_QUEUE_HEAD\fR 32
Add the event at the front of the queue, so that it will be serviced
before all other queued events.
.IP \fBTCL_QUEUE_MARK\fR 24
.IP \fBTCL_QUEUE_MARK\fR 32
Add the event at the front of the queue, unless there are other
events at the front whose position is \fBTCL_QUEUE_MARK\fR;  if so,
add the new event just after all other \fBTCL_QUEUE_MARK\fR events.
This value of \fIposition\fR is used to insert an ordered sequence of
events at the front of the queue, such as a series of
Enter and Leave events synthesized during a grab or ungrab operation
in Tk.
.IP \fBTCL_QUEUE_ALERT_IF_EMPTY\fR 32
When used in \fBTcl_ThreadQueueEvent\fR
arranges for an automatic call of \fBTcl_ThreadAlert\fR when the queue was
empty.
.PP
When it is time to handle an event from the queue (steps 1 and 4
above) \fBTcl_ServiceEvent\fR will invoke the \fIproc\fR specified
in the first queued \fBTcl_Event\fR structure.
\fIProc\fR must match the following prototype:
.PP
.CS
535
536
537
538
539
540
541
542

543
544
545
546
547
548
549
529
530
531
532
533
534
535

536
537
538
539
540
541
542
543







-
+







to another program, such as a Web browser plugin.
.PP
To do this, the extension makes a call to \fBTcl_SetNotifier\fR
passing a pointer to a \fBTcl_NotifierProcs\fR data structure.  The
structure has the following layout:
.PP
.CS
typedef struct Tcl_NotifierProcs {
typedef struct {
    Tcl_SetTimerProc *\fIsetTimerProc\fR;
    Tcl_WaitForEventProc *\fIwaitForEventProc\fR;
    Tcl_CreateFileHandlerProc *\fIcreateFileHandlerProc\fR;
    Tcl_DeleteFileHandlerProc *\fIdeleteFileHandlerProc\fR;
    Tcl_InitNotifierProc *\fIinitNotifierProc\fR;
    Tcl_FinalizeNotifierProc *\fIfinalizeNotifierProc\fR;
    Tcl_AlertNotifierProc *\fIalertNotifierProc\fR;
618
619
620
621
622
623
624
625


612
613
614
615
616
617
618

619
620







-
+
+
mode, which should be restored when the recursive loop exits.
\fBTcl_GetServiceMode\fR returns the current value of the service
mode.
.SH "SEE ALSO"
Tcl_CreateFileHandler(3), Tcl_DeleteFileHandler(3), Tcl_Sleep(3),
Tcl_DoOneEvent(3), Thread(3)
.SH KEYWORDS
event, notifier, event queue, event sources, file events, timer, idle, service mode, threads
event, notifier, event queue, event sources, file events, timer, idle,
service mode, threads

Added doc/Number.3.





























































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
'\"
'\" Contribution from Don Porter, NIST, 2022. (not subject to US copyright)
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_GetNumber 3 9.0 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_GetNumber, Tcl_GetNumberFromObj \- get numeric value from Tcl value
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fB#include <tclTomMath.h>\fR
.sp
int
\fBTcl_GetNumber\fR(\fIinterp, bytes, numBytes, clientDataPtr, typePtr\fR)
.sp
int
\fBTcl_GetNumberFromObj\fR(\fIinterp, objPtr, clientDataPtr, typePtr\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp clientDataPtr out
.AP Tcl_Interp *interp out
When non-NULL, error information is recorded here when the value is not
in any of the numeric formats recognized by Tcl.
.AP "const char" *bytes in
Points to first byte of the string value to be examined.
.AP Tcl_Size numBytes in
The number of bytes, starting at \fIbytes\fR, that should be examined.
If \fBnumBytes\fR is negative, then all bytes should
be examined until the first \fBNUL\fR byte terminates examination.
.AP "void *" *clientDataPtr out
Points to space where a pointer value may be written through which a numeric
value is available to read.
.AP int *typePtr out
Points to space where a value may be written reporting what type of
numeric storage is available to read.
.AP Tcl_Obj *objPtr in
A Tcl value to be examined.
.BE
.SH DESCRIPTION
.PP
These procedures enable callers to retrieve a numeric value from a
Tcl value in a numeric format recognized by Tcl.
.PP
Tcl recognizes many values as numbers.  Several examples include:
\fB"0"\fR, \fB" +1"\fR, \fB"-2 "\fR, \fB" 3 "\fR, \fB"0xdad1"\fR, \fB"0d09"\fR,
\fB"1_000_000"\fR, \fB"4.0"\fR, \fB"1e-7"\fR, \fB"NaN"\fR, or \fB"Inf"\fR.
When built-in Tcl commands act on these values as numbers, they are converted
to a numeric representation for efficient handling in C code.  Tcl makes
use of three C types to store these representations: \fBdouble\fR,
\fBTcl_WideInt\fR, and \fBmp_int\fR.  The \fBdouble\fR type is provided by the
C language standard.  The \fBTcl_WideInt\fR type is declared in the Tcl
header file, \fBtcl.h\fR, and is equivalent to the C standard type
\fBlong long\fR on most platforms. The \fBmp_int\fR type is declared in the
header file \fBtclTomMath.h\fR, and implemented by the LibTomMath
multiple-precision integer library, included with Tcl.
.PP
The routines \fBTcl_GetNumber\fR and \fBTcl_GetNumberFromObj\fR perform
the same function.  They differ only in how the arguments present the Tcl
value to be examined.  \fBTcl_GetNumber\fR accepts a counted string
value in the arguments \fIbytes\fR and \fInumBytes\fR (or a
\fBNUL\fR-terminated string value when \fInumBytes\fR is
negative).  \fBTcl_GetNumberFromObj\fR accepts the Tcl value
in \fIobjPtr\fR.
.PP
Both routines examine the Tcl value and determine whether Tcl recognizes
it as a number.  If not, both routines return \fBTCL_ERROR\fR and (when
\fIinterp\fR is not NULL) record an error message and error code
in \fIinterp\fR.
.PP
If Tcl does recognize the examined value as a number, both routines return
\fBTCL_OK\fR, and use the pointer arguments \fIclientDataPtr\fR
and \fItypePtr\fR (which may not be NULL) to report information the
caller can use to retrieve the numeric representation.  Both routines
write to *\fIclientDataPtr\fR a pointer to the internal storage location
where Tcl holds the converted numeric value.
.PP
When the converted numeric value is stored as a \fBdouble\fR,
a call to math library routine \fBisnan\fR determines whether that
value is not a number (NaN).  If so, both \fBTcl_GetNumber\fR and
\fBTcl_GetNumberFromObj\fR write the value \fBTCL_NUMBER_NAN\fR
to *\fItypePtr\fR. If not, both routines write the value
\fBTCL_NUMBER_DOUBLE\fR to *\fItypePtr\fR.  These routines report
different type values in these cases because \fBTcl_GetDoubleFromObj\fR
raises an error on NaN values.  For both reported type values,
the storage pointer may be cast to type \fBconst double *\fR and
the \fBdouble\fR numeric value may be read through it.
.PP
When the converted numeric value is stored as a \fBTcl_WideInt\fR,
both \fBTcl_GetNumber\fR and \fBTcl_GetNumberFromObj\fR write the
value \fBTCL_NUMBER_INT\fR to *\fItypePtr\fR.
The storage pointer may be cast to type \fBconst Tcl_WideInt *\fR and
the \fBTcl_WideInt\fR numeric value may be read through it.
.PP
When the converted numeric value is stored as an \fBmp_int\fR,
both \fBTcl_GetNumber\fR and \fBTcl_GetNumberFromObj\fR write the
value \fBTCL_NUMBER_BIG\fR to *\fItypePtr\fR.
The storage pointer may be cast to type \fBconst mp_int *\fR and
the \fBmp_int\fR numeric value may be read through it.
.PP
Future releases of Tcl might expand or revise the recognition of
values as numbers.  If additional storage representations are
adopted, these routines will add new values to be written to
*\fItypePtr\fR to identify them.  Callers should consider how
they should react to unknown values written to *\fItypePtr\fR.
.PP
When callers of these routines read numeric values through the
reported storage pointer, they are accessing memory that belongs
to the Tcl library.  The Tcl library has the power to overwrite
or free this memory.  The storage pointer reported by a call to
\fBTcl_GetNumber\fR or \fBTcl_GetNumberFromObj\fR should not be
used after the same thread has possibly returned control to the
Tcl library.  If longer term access to the numeric value is needed,
it should be copied into memory controlled by the caller.  Callers
must not attempt to write through or free the storage pointer.
.SH "SEE ALSO"
Tcl_GetDouble, Tcl_GetDoubleFromObj, Tcl_GetWideIntFromObj
.SH KEYWORDS
double, double value, double type, integer, integer value, integer type,
internal representation, value, value type, string representation

Changes to doc/Object.3.

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


30
31
32
33
34
35
36
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
30

31
32
33
34
35
36
37
38
39










-
+














+
+



-
+
+







'\"
'\" Copyright (c) 1996-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_Obj 3 8.5 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_NewObj, Tcl_DuplicateObj, Tcl_IncrRefCount, Tcl_DecrRefCount, Tcl_IsShared, Tcl_InvalidateStringRep \- manipulate Tcl values
Tcl_NewObj, Tcl_DuplicateObj, Tcl_IncrRefCount, Tcl_DecrRefCount, Tcl_BounceRefCount, Tcl_IsShared, Tcl_InvalidateStringRep \- manipulate Tcl values
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Obj *
\fBTcl_NewObj\fR()
.sp
Tcl_Obj *
\fBTcl_DuplicateObj\fR(\fIobjPtr\fR)
.sp
\fBTcl_IncrRefCount\fR(\fIobjPtr\fR)
.sp
\fBTcl_DecrRefCount\fR(\fIobjPtr\fR)
.sp
\fBTcl_BounceRefCount\fR(\fIobjPtr\fR)
.sp
int
\fBTcl_IsShared\fR(\fIobjPtr\fR)
.sp
\fBTcl_InvalidateStringRep\fR(\fIobjPtr\fR)
\fBTcl_InvalidateStringRep\fR(\fIobjPtr\fR)3
.fi
.SH ARGUMENTS
.AS Tcl_Obj *objPtr
.AP Tcl_Obj *objPtr in
Points to a value;
must have been the result of a previous call to \fBTcl_NewObj\fR.
.BE
.SH INTRODUCTION
106
107
108
109
110
111
112
113
114


115
116

117
118
119
120
121
122
123
109
110
111
112
113
114
115


116
117
118

119
120
121
122
123
124
125
126







-
-
+
+

-
+







by defining their own \fBTcl_ObjType\fR structs.
.SH "THE TCL_OBJ STRUCTURE"
.PP
Each Tcl value is represented by a \fBTcl_Obj\fR structure
which is defined as follows.
.PP
.CS
typedef struct Tcl_Obj {
    size_t \fIrefCount\fR;
typedef struct {
    Tcl_Size \fIrefCount\fR;
    char *\fIbytes\fR;
    size_t \fIlength\fR;
    Tcl_Size \fIlength\fR;
    const Tcl_ObjType *\fItypePtr\fR;
    union {
        long \fIlongValue\fR;
        double \fIdoubleValue\fR;
        void *\fIotherValuePtr\fR;
        Tcl_WideInt \fIwideValue\fR;
        struct {
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
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







-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+

-
+
-
-
+
+













+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







.PP
The string representation of \fIx\fR's value is needed
and is recomputed.
The string representation is now \fB124\fR
and both representations are again valid.
.SH "STORAGE MANAGEMENT OF VALUES"
.PP
Tcl values are allocated on the heap and are shared as much as possible
to reduce storage requirements.
Tcl values are allocated on the heap and are shared as much as
possible to reduce storage requirements.  Reference counting is used
Reference counting is used to determine when a value is
no longer needed and can safely be freed.
A value just created by \fBTcl_NewObj\fR or \fBTcl_NewStringObj\fR
has \fIrefCount\fR 0.
The macro \fBTcl_IncrRefCount\fR increments the reference count
when a new reference to the value is created.
The macro \fBTcl_DecrRefCount\fR decrements the count
to determine when a value is no longer needed and can safely be freed.
A value just created by \fBTcl_NewObj\fR, \fBTcl_NewStringObj\fR, or
any Abstract List command or function, has \fIrefCount\fR 0, meaning
that the object can often be given to a function like
\fBTcl_SetObjResult\fR, \fBTcl_ListObjAppendElement\fR, or
\fBTcl_DictObjPut\fR (as a value) without explicit reference
management, all of which are common use cases. (The latter two require
that the target list or dictionary be well-formed, but that is
often easy to arrange when the value is being initially constructed.)
The macro \fBTcl_IncrRefCount\fR increments the reference count when a
new reference to the value is created.
The macro \fBTcl_DecrRefCount\fR decrements the count when a reference
when a reference is no longer needed and,
if the value's reference count drops to zero, frees its storage.
is no longer needed. If the value's reference count drops to zero, frees
its storage.
The macro \fBTcl_BounceRefCount\fR will check if the value has no
references (i.e. in a "new" state) and free the value.
A value shared by different code or data structures has
\fIrefCount\fR greater than 1.
\fIrefCount\fR greater than 1.  Incrementing a value's reference count
Incrementing a value's reference count ensures that
it will not be freed too early or have its value change accidentally.
ensures that it will not be freed too early or have its value change
accidentally.
.PP
As an example, the bytecode interpreter shares argument values
between calling and called Tcl procedures to avoid having to copy values.
It assigns the call's argument values to the procedure's
formal parameter variables.
In doing so, it calls \fBTcl_IncrRefCount\fR to increment
the reference count of each argument since there is now a new
reference to it from the formal parameter.
When the called procedure returns,
the interpreter calls \fBTcl_DecrRefCount\fR to decrement
each argument's reference count.
When a value's reference count drops less than or equal to zero,
\fBTcl_DecrRefCount\fR reclaims its storage.

.PP
Most command procedures do not have to be concerned about
reference counting since they use a value's value immediately
and do not retain a pointer to the value after they return.
However, if they do retain a pointer to a value in a data structure,
they must be careful to increment its reference count
since the retained pointer is a new reference.
Most command procedures have not been concerned about reference
counting since they use a value immediately and do not retain
a pointer to the value after they return.  However, there are some
procedures that may return a new value, with a refCount of 0. In this
situation, it is the caller's responsibility to free the value before
the procedure returns.  One way to cover this is to always call
\fBTcl_IncrRefCount\fR before using the value, then call
\fBTcl_DecrRefCount\fR before returning. The other way is to use
\fBTcl_BounceRefCount\fR after the value is no longer needed or
referenced. This macro will free the value if there are no other
references to the value. When retaining a pointer to a value in a data
structure the procedure must be careful to increment its reference
count since the retained pointer is a new reference. Examples of
procedures that return new values are \fBTcl_NewIntObj\fR, and
commands like \fBlseq\fR, which creates an Abstract List, and an
lindex on this list may return a new Obj with a refCount of 0.

.PP
Command procedures that directly modify values
such as those for \fBlappend\fR and \fBlinsert\fR must be careful to
copy a shared value before changing it.
They must first check whether the value is shared
by calling \fBTcl_IsShared\fR.
If the value is shared they must copy the value
341
342
343
344
345
346
347





348
349
350
351
352
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380







+
+
+
+
+





.CE
.PP
As another example, \fBincr\fR's command procedure
must check whether the variable's value is shared before
incrementing the integer in its internal representation.
If it is shared, it needs to duplicate the value
in order to avoid accidentally changing values in other data structures.
.PP
In cases where a value is obtained, used, and not retained, the value
can be freed using \fBTcl_BounceRefCount\fR. This
is functionally equivalent to calling \fBTcl_IncrRefCount\fR followed
\fBTcl_DecrRefCount\fR.
.SH "SEE ALSO"
Tcl_ConvertToType(3), Tcl_GetIntFromObj(3), Tcl_ListObjAppendElement(3), Tcl_ListObjIndex(3), Tcl_ListObjReplace(3), Tcl_RegisterObjType(3)
.SH KEYWORDS
internal representation, value, value creation, value type,
reference counting, string representation, type conversion

Changes to doc/ObjectType.3.

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
30
31
32
33
34
35
36
37
38
39
40








41
42
43
44
45
46
47
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
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






-
+



-
+














+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+















+
+
+
+
+
+
+
+







'\"
'\" Copyright (c) 1996-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_ObjType 3 8.0 Tcl "Tcl Library Procedures"
.TH Tcl_ObjType 3 9.0 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_RegisterObjType, Tcl_GetObjType, Tcl_AppendAllObjTypes, Tcl_ConvertToType  \- manipulate Tcl value types
Tcl_RegisterObjType, Tcl_GetObjType, Tcl_AppendAllObjTypes, Tcl_ConvertToType, Tcl_FreeInternalRep, Tcl_InitStringRep, Tcl_HasStringRep, Tcl_StoreInternalRep, Tcl_FetchInternalRep  \- manipulate Tcl value types
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_RegisterObjType\fR(\fItypePtr\fR)
.sp
const Tcl_ObjType *
\fBTcl_GetObjType\fR(\fItypeName\fR)
.sp
int
\fBTcl_AppendAllObjTypes\fR(\fIinterp, objPtr\fR)
.sp
int
\fBTcl_ConvertToType\fR(\fIinterp, objPtr, typePtr\fR)
.sp
void
\fBTcl_FreeInternalRep\fR(\fIobjPtr\fR)
.sp
char *
\fBTcl_InitStringRep\fR(\fIobjPtr, bytes, numBytes\fR)
.sp
int
\fBTcl_HasStringRep\fR(\fIobjPtr\fR)
.sp
void
\fBTcl_StoreInternalRep\fR(\fIobjPtr, typePtr, irPtr\fR)
.sp
Tcl_ObjInternalRep *
\fBTcl_FetchInternalRep\fR(\fIobjPtr, typePtr\fR)
.fi
.SH ARGUMENTS
.AS "const char" *typeName
.AP "const Tcl_ObjType" *typePtr in
Points to the structure containing information about the Tcl value type.
This storage must live forever,
typically by being statically allocated.
.AP "const char" *typeName in
The name of a Tcl value type that \fBTcl_GetObjType\fR should look up.
.AP Tcl_Interp *interp in
Interpreter to use for error reporting.
.AP Tcl_Obj *objPtr in
For \fBTcl_AppendAllObjTypes\fR, this points to the value onto which
it appends the name of each value type as a list element.
For \fBTcl_ConvertToType\fR, this points to a value that
must have been the result of a previous call to \fBTcl_NewObj\fR.
.AP "const char*" bytes in
String representation.
.AP "unsigned int" numBytes in
Length of the string representation in bytes.
.AP "const Tcl_ObjInternalRep*" irPtr in
Internal object representation.
.AP "const Tcl_ObjType*" typePtr in
Requested internal representation type.
.BE

.SH DESCRIPTION
.PP
The procedures in this man page manage Tcl value types (sometimes
referred to as object types or \fBTcl_ObjType\fRs for historical reasons).
They are used to register new value types, look up types,
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+
-
-
-
-
-
-
-
+
+
+
+
+
+


-
+





+
+
+
+
+
+
+
+
+
+
+







as a test whether the conversion can be done (and in fact was done).
.PP
In many cases, the \fItypePtr->setFromAnyProc\fR routine will
set \fIobjPtr->typePtr\fR to the argument value \fItypePtr\fR,
but that is no longer guaranteed.  The \fIsetFromAnyProc\fR is
free to set the internal representation for \fIobjPtr\fR to make
use of another related Tcl_ObjType, if it sees fit.
.PP
\fBTcl_FreeInternalRep\fR performs the function of the existing internal
macro \fBTclInitStringRep\fR, but is extended to return a pointer to the
string rep, and to accept \fINULL\fR as a value for bytes.
When bytes is \fINULL\fR and \fIobjPtr\fR has no string rep, an uninitialzed
buffer of \fInumBytes\fR bytes is created for filling by the caller.
When \fIbytes\fR is \fINULL\fR and \fIobjPtr\fR has a string rep,
the string rep will be truncated to a length of \fInumBytes\fR bytes.
When \fInumBytes\fR is greater than zero, and the returned pointer is
\fINULL\fR, that indicates a failure to allocate memory for the string
representation.
The caller may then choose whether to raise an error or panic.
.PP
\fBTcl_HasStringRep\fR returns a boolean indicating whether or not a string
rep is currently stored in \fIobjPtr\fR.
This is used when the caller wants to act on \fIobjPtr\fR differently
depending on whether or not it is a pure value.
Typically this only makes sense in an extension if it is already known that
\fIobjPtr\fR possesses an internal type that is managed by the extension.
.PP
\fBTcl_StoreInternalRep\fR stores in \fIobjPtr\fR a copy of the internal
representation pointed to by \fIirPtr\fR and sets its type to \fItypePtr\fR.
When \fIirPtr\fR is \fINULL\fR, this leaves \fIobjPtr\fR without a
representation for type \fItypePtr\fR.
.PP
\fBTcl_FetchInternalRep\fR returns a pointer to the internal representation
stored in \fIobjPtr\fR that matches the requested type \fItypePtr\fR.
If no such internal representation is in \fIobjPtr\fR, return \fINULL\fR.
.PP
This returns a public type
.CS
typedef union Tcl_ObjInternalRep {...} Tcl_ObjInternalRep
.CE
where the contents are exactly the existing contents of the union in the
\fIinternalRep\fR field of the \fITcl_Obj\fR struct.
This definition permits us to pass internal representations and pointers to
them as arguments and results in public routines.
.SH "THE TCL_OBJTYPE STRUCTURE"
.PP
Extension writers can define new value types by defining four
Extension writers can define new value types by defining four to twelve
procedures and
initializing a Tcl_ObjType structure to describe the type.
Extension writers may also pass a pointer to their Tcl_ObjType
structure to \fBTcl_RegisterObjType\fR if they wish to permit
other extensions to look up their Tcl_ObjType by name with
the \fBTcl_GetObjType\fR routine.
The \fBTcl_ObjType\fR structure is defined as follows:
procedures and initializing a Tcl_ObjType structure to describe the
type.  Extension writers may also pass a pointer to their Tcl_ObjType
structure to \fBTcl_RegisterObjType\fR if they wish to permit other
extensions to look up their Tcl_ObjType by name with the
\fBTcl_GetObjType\fR routine.  The \fBTcl_ObjType\fR structure is
defined as follows:
.PP
.CS
typedef struct Tcl_ObjType {
typedef struct {
    const char *\fIname\fR;
    Tcl_FreeInternalRepProc *\fIfreeIntRepProc\fR;
    Tcl_DupInternalRepProc *\fIdupIntRepProc\fR;
    Tcl_UpdateStringProc *\fIupdateStringProc\fR;
    Tcl_SetFromAnyProc *\fIsetFromAnyProc\fR;
    size_t \fIversion\fR;
    /* List emulation functions - ObjType Version 1 & 2 */
    Tcl_ObjTypeLengthProc *lengthProc;
    /* List emulation functions - ObjType Version 2 */
    Tcl_ObjTypeIndexProc *\fIindexProc\fR;
    Tcl_ObjTypeSliceProc *\fIsliceProc\fR;
    Tcl_ObjTypeReverseProc *\fIreverseProc\fR;
    Tcl_ObjTypeGetElements *\fIgetElementsProc\fR;
    Tcl_ObjTypeSetElement *\fIsetElementProc\fR;
    Tcl_ObjTypeReplaceProc *\fIreplaceProc\fR;
    Tcl_ObjTypeInOperatorProc *\fIinOperProc\fR;
} \fBTcl_ObjType\fR;
.CE
.SS "THE NAME FIELD"
.PP
The \fIname\fR member describes the name of the type, e.g. \fBint\fR.
When a type is registered, this is the name used by callers
of \fBTcl_GetObjType\fR to lookup the type.  For unregistered
244
245
246
247
248
249
250























































































































































251
252

253
254


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
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
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
467
468
469
470
471
472
473

474
475

476
477







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
+
+
The \fIfreeIntRepProc\fR member can be set to NULL
to indicate that the internal representation does not require freeing.
The \fIfreeIntRepProc\fR implementation must not access the
\fIbytes\fR member of the value, since Tcl makes its own internal
uses of that field during value deletion.  The defined tasks for
the \fIfreeIntRepProc\fR have no need to consult the \fIbytes\fR
member.
.PP
Note that if a subsidiary value has its reference count reduced to zero
during the running of a \fIfreeIntRepProc\fR, that value may be not freed
immediately, in order to limit stack usage. However, the value will be freed
before the outermost current \fBTcl_DecrRefCount\fR returns.
.SS "THE VERSION FIELD"
.PP
The \fIversion\fR member provides for future extensibility of the
structure and should be set to \fBTCL_OBJTYPE_V0\fR for compatibility
of ObjType definitions prior to version 9.0. Specifics about versions
will be described further in the sections below.
.SH "ABSTRACT LIST TYPES"
.PP
Additional fields in the Tcl_ObjType descriptor allow for control over
how custom data values can be manipulated using Tcl's List commands
without converting the value to a List type. This requires the custom
type to provide functions that will perform the given operation on the
custom data representation.  Not all functions are required. In the
absence of a particular function (set to NULL), the fallback is to
allow the internal List operation to perform the operation, most
likely causing the value type to be converted to a traditional list.
.SS "SCALAR VALUE TYPES"
.PP
For a custom value type that is scalar or atomic in nature, i.e., not
a divisible collection, version \fBTCL_OBJTYPE_V1\fR is
recommended. In this case, List commands will treat the scalar value
as if it where a list of length 1, and not convert the value to a List
type.
.SS "VERSION 2: ABSTRACT LISTS"
.PP
Version 2, \fBTCL_OBJTYPE_V2\fR, allows full List support when the
functions described below are provided.  This allows for script level
use of the List commands without causing the type of the Tcl_Obj value
to be converted to a list.
.SS "THE LENGTHPROC FIELD"
.PP
The \fBLengthProc\fR function correlates with the \fBTcl_ListObjLength\fR
C API. The function returns the number of elements in the list. It
is used in every List operation and is required for all Abstract List
implementations.
.CS
typedef Tcl_Size
(Tcl_ObjTypeLengthProc) (Tcl_Obj *listPtr);
.CE
.PP
.SS "THE INDEXPROC FIELD"
.PP
The \fBIndexProc\fR function correlates with with the
\fBTcl_ListObjIndex\fR C API. The function returns a Tcl_Obj value for
the element at the specified index.
.CS
typedef int (\fBTcl_ObjTypeIndexProc\fR) (
    Tcl_Interp *interp,
    Tcl_Obj *listPtr,
    Tcl_Size index,
    Tcl_Obj** elemObj);
.CE
.SS "THE SLICEPROC FIELD"
.PP
The \fBSliceProc\fR correlates with the \fBlrange\fR command,
returning a new List or Abstract List for the portion of the original
list specified.
.CS
typedef int (\fBTcl_ObjTypeSliceProc\fR) (
    Tcl_Interp *interp,
    Tcl_Obj *listPtr,
    Tcl_Size fromIdx,
    Tcl_Size toIdx,
    Tcl_Obj **newObjPtr);
.CE
.SS "THE REVERSEPROC FIELD"
.PP
The \fBReverseProc\fR correlates with the \fBlreverse\fR command,
returning a List or Abstract List that has the same elements as the
input Abstract List, with the elements in the reverse order.
.CS
typedef int (\fBTcl_ObjTypeReverseProc\fR) (
    Tcl_Interp *interp,
    Tcl_Obj *listPtr,
    Tcl_Obj **newObjPtr);
.CE
.SS "THE GETELEMENTS FIELD"
.PP
The \fBGetElements\fR function returns a count and a pointer to an
array of Tcl_Obj values for the entire Abstract List. This
correlates to the \fBTcl_ListObjGetElements\fR C API call.
.CS
typedef int (\fBTcl_ObjTypeGetElements\fR) (
    Tcl_Interp *interp,
    Tcl_Obj *listPtr,
    Tcl_Size *objcptr,
    Tcl_Obj ***objvptr);
.CE
.SS "THE SETELEMENT FIELD"
.PP
The \fBSetElement\fR function replaces the element within the
specified list at the give index. This function correlates to the
\fBlset\fR command.
.CS
typedef Tcl_Obj *(\fBTcl_ObjTypeSetElement\fR) (
    Tcl_Interp *interp,
    Tcl_Obj *listPtr,
    Tcl_Size indexCount,
    Tcl_Obj *const indexArray[],
    Tcl_Obj *valueObj);
.CE
.SS "REPLACEPROC FIELD"
.PP
The \fBReplaceProc\fR returns a new list after modifying the list
replacing the elements to be deleted, and adding the elements to be
inserted. This function correlates to the \fBTcl_ListObjReplace\fR C API.
.CS
typedef int (\fBTcl_ObjTypeReplaceProc\fR) (
    Tcl_Interp *interp,
    Tcl_Obj *listObj,
    Tcl_Size first,
    Tcl_Size numToDelete,
    Tcl_Size numToInsert,
    Tcl_Obj *const insertObjs[]);
.CE
.SS "THE INOPERPROC FIELD"
.PP
The \fBInOperProc\fR function determines whether the value is present in the
given list, according to equivalent string comparison of elements. The
\fBboolResult\fR is set to 1 (true) if the value is present, and 0
(false) if it is not present. This function implements the "in" and
"ni" math operators for an abstract list.
.CS
typedef int (\fBTcl_ObjTypeInOperatorProc\fR) (
    Tcl_Interp *interp,
    Tcl_Obj *valueObj,
    Tcl_Obj *listObj,
    int *boolResult);
.CE
.SH "REFERENCE COUNT MANAGEMENT"
.PP
The \fIobjPtr\fR argument to \fBTcl_AppendAllObjTypes\fR should be an unshared
value; this function will not modify the reference count of that value, but
will modify its contents. If \fIobjPtr\fR is not (interpretable as) a list,
this function will set the interpreter result and produce an error; using an
unshared empty value is strongly recommended.
.PP
The \fIobjPtr\fR argument to \fBTcl_ConvertToType\fR can have any non-zero
reference count; this function will not modify the reference count, but may
write to the interpreter result on error so values that originate from there
should have an additional reference made before calling this.
.PP
None of the callback functions in the \fBTcl_ObjType\fR structure should
modify the reference count of their arguments, but if the values contain
subsidiary values (e.g., the elements of a list or the keys of a dictionary)
then those subsidiary values may have their reference counts modified.
.SH "SEE ALSO"
Tcl_NewObj(3), Tcl_DecrRefCount(3), Tcl_IncrRefCount(3)
Tcl_NewObj(3), Tcl_DecrRefCount(3), Tcl_IncrRefCount(3), Tcl_BounceRefCount(3)
.SH KEYWORDS
internal representation, value, value type, string representation, type conversion
internal representation, value, value type, string representation,
type conversion

Changes to doc/OpenFileChnl.3.

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
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







-














-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+

















-
+


-
+










-
+












-
+







.sp
int
\fBTcl_GetChannelNames\fR(\fIinterp\fR)
.sp
int
\fBTcl_GetChannelNamesEx\fR(\fIinterp, pattern\fR)
.sp
void
\fBTcl_RegisterChannel\fR(\fIinterp, channel\fR)
.sp
int
\fBTcl_UnregisterChannel\fR(\fIinterp, channel\fR)
.sp
int
\fBTcl_DetachChannel\fR(\fIinterp, channel\fR)
.sp
int
\fBTcl_IsStandardChannel\fR(\fIchannel\fR)
.sp
int
\fBTcl_Close\fR(\fIinterp, channel\fR)
.sp
int
Tcl_Size
\fBTcl_ReadChars\fR(\fIchannel, readObjPtr, charsToRead, appendFlag\fR)
.sp
int
Tcl_Size
\fBTcl_Read\fR(\fIchannel, readBuf, bytesToRead\fR)
.sp
size_t
Tcl_Size
\fBTcl_GetsObj\fR(\fIchannel, lineObjPtr\fR)
.sp
size_t
Tcl_Size
\fBTcl_Gets\fR(\fIchannel, lineRead\fR)
.sp
size_t
Tcl_Size
\fBTcl_Ungets\fR(\fIchannel, input, inputLen, addAtEnd\fR)
.sp
size_t
Tcl_Size
\fBTcl_WriteObj\fR(\fIchannel, writeObjPtr\fR)
.sp
size_t
Tcl_Size
\fBTcl_WriteChars\fR(\fIchannel, charBuf, bytesToWrite\fR)
.sp
size_t
Tcl_Size
\fBTcl_Write\fR(\fIchannel, byteBuf, bytesToWrite\fR)
.sp
size_t
Tcl_Size
\fBTcl_ReadRaw\fR(\fIchannel, readBuf, bytesToRead\fR)
.sp
size_t
Tcl_Size
\fBTcl_WriteRaw\fR(\fIchannel, byteBuf, bytesToWrite\fR)
.sp
int
\fBTcl_Eof\fR(\fIchannel\fR)
.sp
int
\fBTcl_Flush\fR(\fIchannel\fR)
.sp
int
\fBTcl_InputBlocked\fR(\fIchannel\fR)
.sp
int
\fBTcl_InputBuffered\fR(\fIchannel\fR)
.sp
int
\fBTcl_OutputBuffered\fR(\fIchannel\fR)
.sp
Tcl_WideInt
long long
\fBTcl_Seek\fR(\fIchannel, offset, seekMode\fR)
.sp
Tcl_WideInt
long long
\fBTcl_Tell\fR(\fIchannel\fR)
.sp
int
\fBTcl_TruncateChannel\fR(\fIchannel, length\fR)
.sp
int
\fBTcl_GetChannelOption\fR(\fIinterp, channel, optionName, optionValue\fR)
.sp
int
\fBTcl_SetChannelOption\fR(\fIinterp, channel, optionName, newValue\fR)
.sp
.fi
.SH ARGUMENTS
.AS Tcl_DString *channelName in/out
.AP Tcl_Interp *interp in
Used for error reporting and to look up a channel registered in it.
.AP "const char" *fileName in
The name of a local or network file.
.AP "const char" *mode in
Specifies how the file is to be accessed.  May have any of the values
allowed for the \fImode\fR argument to the Tcl \fBopen\fR command.
.AP int permissions in
POSIX-style permission flags such as 0644.  If a new file is created, these
permissions will be set on the created file.
.AP int argc in
.AP Tcl_Size argc in
The number of elements in \fIargv\fR.
.AP "const char" **argv in
Arguments for constructing a command pipeline.  These values have the same
meaning as the non-switch arguments to the Tcl \fBexec\fR command.
.AP int flags in
Specifies the disposition of the stdio handles in pipeline: OR-ed
combination of \fBTCL_STDIN\fR, \fBTCL_STDOUT\fR, \fBTCL_STDERR\fR, and
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
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







-
+








-
+












-
+










-
+


-
+







-
+







The pattern to match on, passed to Tcl_StringMatch, or NULL.
.AP Tcl_Channel channel in
A Tcl channel for input or output.  Must have been the return value
from a procedure such as \fBTcl_OpenFileChannel\fR.
.AP Tcl_Obj *readObjPtr in/out
A pointer to a Tcl value in which to store the characters read from the
channel.
.AP size_t charsToRead in
.AP Tcl_Size charsToRead in
The number of characters to read from the channel.  If the channel's encoding
is \fBbinary\fR, this is equivalent to the number of bytes to read from the
channel.
.AP int appendFlag in
If non-zero, data read from the channel will be appended to the value.
Otherwise, the data will replace the existing contents of the value.
.AP char *readBuf out
A buffer in which to store the bytes read from the channel.
.AP size_t bytesToRead in
.AP Tcl_Size bytesToRead in
The number of bytes to read from the channel.  The buffer \fIreadBuf\fR must
be large enough to hold this many bytes.
.AP Tcl_Obj *lineObjPtr in/out
A pointer to a Tcl value in which to store the line read from the
channel.  The line read will be appended to the current value of the
value.
.AP Tcl_DString *lineRead in/out
A pointer to a Tcl dynamic string in which to store the line read from the
channel.  Must have been initialized by the caller.  The line read will be
appended to any data already in the dynamic string.
.AP "const char" *input in
The input to add to a channel buffer.
.AP size_t inputLen in
.AP Tcl_Size inputLen in
Length of the input
.AP int addAtEnd in
Flag indicating whether the input should be added to the end or
beginning of the channel buffer.
.AP Tcl_Obj *writeObjPtr in
A pointer to a Tcl value whose contents will be output to the channel.
.AP "const char" *charBuf in
A buffer containing the characters to output to the channel.
.AP "const char" *byteBuf in
A buffer containing the bytes to output to the channel.
.AP size_t bytesToWrite in
.AP Tcl_Size bytesToWrite in
The number of bytes to consume from \fIcharBuf\fR or \fIbyteBuf\fR and
output to the channel.
.AP Tcl_WideInt offset in
.AP "long long" offset in
How far to move the access point in the channel at which the next input or
output operation will be applied, measured in bytes from the position
given by \fIseekMode\fR.  May be either positive or negative.
.AP int seekMode in
Relative to which point to seek; used with \fIoffset\fR to calculate the new
access point for the channel. Legal values are \fBSEEK_SET\fR,
\fBSEEK_CUR\fR, and \fBSEEK_END\fR.
.AP Tcl_WideInt length in
.AP "long long" length in
The (non-negative) length to truncate the channel the channel to.
.AP "const char" *optionName in
The name of an option applicable to this channel, such as \fB\-blocking\fR.
May have any of the values accepted by the \fBfconfigure\fR command.
.AP Tcl_DString *optionValue in
Where to store the value of an option or a list of all options and their
values. Must have been initialized by the caller.
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
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







-
+














-
-
+
+
+
+

-
+






+
-
-
+
+
-







If the channel was closed successfully, \fBTcl_Close\fR returns \fBTCL_OK\fR.
If an error occurs, \fBTcl_Close\fR returns \fBTCL_ERROR\fR and records a
POSIX error code that can be retrieved with \fBTcl_GetErrno\fR.
If the channel is being closed synchronously and an error occurs during
closing of the channel and \fIinterp\fR is not NULL, an error message is
left in the interpreter's result.
.PP
Note: it is not safe to call \fBTcl_Close\fR on a channel that has been
Note that it is not safe to call \fBTcl_Close\fR on a channel that has been
registered using \fBTcl_RegisterChannel\fR; see the documentation for
\fBTcl_RegisterChannel\fR, above, for details. If the channel has ever
been given as the \fBchan\fR argument in a call to
\fBTcl_RegisterChannel\fR, you should instead use
\fBTcl_UnregisterChannel\fR, which will internally call \fBTcl_Close\fR
when all calls to \fBTcl_RegisterChannel\fR have been matched by
corresponding calls to \fBTcl_UnregisterChannel\fR.
.SH "TCL_READCHARS AND TCL_READ"
.PP
\fBTcl_ReadChars\fR consumes bytes from \fIchannel\fR, converting the bytes
to UTF-8 based on the channel's encoding and storing the produced data in
\fIreadObjPtr\fR's string representation.  The return value of
\fBTcl_ReadChars\fR is the number of characters, up to \fIcharsToRead\fR,
that were stored in \fIreadObjPtr\fR.  If an error occurs while reading, the
return value is \-1 and \fBTcl_ReadChars\fR records a POSIX error code that
can be retrieved with \fBTcl_GetErrno\fR.
return value is -1 and \fBTcl_ReadChars\fR records a POSIX error
code that can be retrieved with \fBTcl_GetErrno\fR. If an encoding error happens
while the channel is in blocking mode with -profile strict, the characters
retrieved until the encoding error happened will be stored in \fIreadObjPtr\fR.
.PP
Setting \fIcharsToRead\fR to \fB\-1\fR will cause the command to read
Setting \fIcharsToRead\fR to -1 will cause the command to read
all characters currently available (non-blocking) or everything until
eof (blocking mode).
.PP
The return value may be smaller than the value to read, indicating that less
data than requested was available.  This is called a \fIshort read\fR.  In
blocking mode, this can only happen on an end-of-file.  In nonblocking mode,
a short read can also occur if an encoding error is encountered (with -profile
a short read can also occur if there is not enough input currently
available:  \fBTcl_ReadChars\fR returns a short count rather than waiting
strict) or if there is not enough input currently available:
\fBTcl_ReadChars\fR returns a short count rather than waiting for more data.
for more data.
.PP
If the channel is in blocking mode, a return value of zero indicates an
end-of-file condition.  If the channel is in nonblocking mode, a return
value of zero indicates either that no input is currently available or an
end-of-file condition.  Use \fBTcl_Eof\fR and \fBTcl_InputBlocked\fR to tell
which of these conditions actually occurred.
.PP
467
468
469
470
471
472
473
474

475
476

477
478
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
468
469
470
471
472
473
474

475
476

477
478
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







-
+

-
+


-
-
-
+
+
+

















-
+
















-
-
-
-
+
+
+
+







channel is treated as an individual Unicode character.  All of the
characters of the line except for the terminating end-of-line character(s)
are appended to \fIlineObjPtr\fR's string representation.  The end-of-line
character(s) are read and discarded.
.PP
If a line was successfully read, the return value is greater than or equal
to zero and indicates the number of bytes stored in \fIlineObjPtr\fR.  If an
error occurs, \fBTcl_GetsObj\fR returns \-1 and records a POSIX error code
error occurs, \fBTcl_GetsObj\fR returns -1 and records a POSIX error code
that can be retrieved with \fBTcl_GetErrno\fR.  \fBTcl_GetsObj\fR also
returns \-1 if the end of the file is reached; the \fBTcl_Eof\fR procedure
returns -1 if the end of the file is reached; the \fBTcl_Eof\fR procedure
can be used to distinguish an error from an end-of-file condition.
.PP
If the channel is in nonblocking mode, the return value can also be \-1 if
no data was available or the data that was available did not contain an
end-of-line character.  When \-1 is returned, the \fBTcl_InputBlocked\fR
If the channel is in nonblocking mode, the return value can also be -1
if no data was available or the data that was available did not contain an
end-of-line character.  When -1 is returned, the \fBTcl_InputBlocked\fR
procedure may be invoked to determine if the channel is blocked because
of input unavailability.
.PP
\fBTcl_Gets\fR is the same as \fBTcl_GetsObj\fR except the resulting
characters are appended to the dynamic string given by
\fIlineRead\fR rather than a Tcl value.
.SH "TCL_UNGETS"
.PP
\fBTcl_Ungets\fR is used to add data to the input queue of a channel,
at either the head or tail of the queue.  The pointer \fIinput\fR points
to the data that is to be added.  The length of the input to add is given
by \fIinputLen\fR.  A non-zero value of \fIaddAtEnd\fR indicates that the
data is to be added at the end of queue; otherwise it will be added at the
head of the queue.  If \fIchannel\fR has a
.QW sticky
EOF set, no data will be
added to the input queue.  \fBTcl_Ungets\fR returns \fIinputLen\fR or
\-1 if an error occurs.
-1 if an error occurs.
.SH "TCL_WRITECHARS, TCL_WRITEOBJ, AND TCL_WRITE"
.PP
\fBTcl_WriteChars\fR accepts \fIbytesToWrite\fR bytes of character data at
\fIcharBuf\fR.  The UTF-8 characters in the buffer are converted to the
channel's encoding and queued for output to \fIchannel\fR.  If
\fIbytesToWrite\fR is negative, \fBTcl_WriteChars\fR expects \fIcharBuf\fR
to be null-terminated and it outputs everything up to the null.
.PP
Data queued for output may not appear on the output device immediately, due
to internal buffering.  If the data should appear immediately, call
\fBTcl_Flush\fR after the call to \fBTcl_WriteChars\fR, or set the
\fB\-buffering\fR option on the channel to \fBnone\fR.  If you wish the data
to appear as soon as a complete line is accepted for output, set the
\fB\-buffering\fR option on the channel to \fBline\fR mode.
.PP
The return value of \fBTcl_WriteChars\fR is a count of how many bytes were
accepted for output to the channel.  This is either greater than zero to
indicate success or \-1 to indicate that an error occurred.  If an error
occurs, \fBTcl_WriteChars\fR records a POSIX error code that may be
retrieved with \fBTcl_GetErrno\fR.
accepted for output to the channel.  This is either -1 to
indicate that an error occurred or another number greater than
zero to indicate success.  If an error occurs, \fBTcl_WriteChars\fR records
a POSIX error code that may be retrieved with \fBTcl_GetErrno\fR.
.PP
Newline characters in the output data are translated to platform-specific
end-of-line sequences according to the \fB\-translation\fR option for the
channel.  This is done even if the channel has no encoding.
.PP
\fBTcl_WriteObj\fR is similar to \fBTcl_WriteChars\fR except it
accepts a Tcl value whose contents will be output to the channel.  The
595
596
597
598
599
600
601
602

603
604
605
606
607
608
609
596
597
598
599
600
601
602

603
604
605
606
607
608
609
610







-
+







\fIoptionName\fR is NULL, the function stores an alternating list of option
names and their values in \fIoptionValue\fR, using a series of calls to
\fBTcl_DStringAppendElement\fR. The various preexisting options and
their possible values are described in the manual entry for the Tcl
\fBfconfigure\fR command. Other options can be added by each channel type.
These channel type specific options are described in the manual entry for
the Tcl command that creates a channel of that type; for example, the
additional options for TCP based channels are described in the manual entry
additional options for TCP-based channels are described in the manual entry
for the Tcl \fBsocket\fR command.
The procedure normally returns \fBTCL_OK\fR. If an error occurs, it returns
\fBTCL_ERROR\fR and calls \fBTcl_SetErrno\fR to store an appropriate POSIX
error code.
.SH TCL_SETCHANNELOPTION
.PP
\fBTcl_SetChannelOption\fR sets a new value \fInewValue\fR
637
638
639
640
641
642
643


















644
645
646
647
648
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





platform and the channel type.  On Unix platforms, the handle is
always a Unix file descriptor as returned from the \fBopen\fR system
call.  On Windows platforms, the handle is a file \fBHANDLE\fR when
the channel was created with \fBTcl_OpenFileChannel\fR,
\fBTcl_OpenCommandChannel\fR, or \fBTcl_MakeFileChannel\fR.  Other
channel types may return a different type of handle on Windows
platforms.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
The \fIreadObjPtr\fR argument to \fBTcl_ReadChars\fR must be an unshared
value; it will be modified by this function.  Using the interpreter result for
this purpose is \fIstrongly\fR not recommended; the preferred pattern is to
use a new value from \fBTcl_NewObj\fR to receive the data and only to pass it
to \fBTcl_SetObjResult\fR if this function succeeds.
.PP
The \fIlineObjPtr\fR argument to \fBTcl_GetsObj\fR must be an unshared value;
it will be modified by this function.  Using the interpreter result for this
purpose is \fIstrongly\fR not recommended; the preferred pattern is to use a
new value from \fBTcl_NewObj\fR to receive the data and only to pass it to
\fBTcl_SetObjResult\fR if this function succeeds.
.PP
The \fIwriteObjPtr\fR argument to \fBTcl_WriteObj\fR should be a value with
any reference count. This function will not modify the reference count. Using
the interpreter result without adding an additional reference to it is not
recommended.
.SH "SEE ALSO"
DString(3), fconfigure(n), filename(n), fopen(3), Tcl_CreateChannel(3)
.SH KEYWORDS
access point, blocking, buffered I/O, channel, channel driver, end of file,
flush, input, nonblocking, output, read, seek, write

Changes to doc/OpenTcp.3.

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
30
31
32
33
34
35
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
30
31
32
33
34
35






-
+



















-
-
+
+







'\"
'\" Copyright (c) 1996-7 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_OpenTcpClient 3 8.7 Tcl "Tcl Library Procedures"
.TH Tcl_OpenTcpClient 3 9.0 Tcl "Tcl Library Procedures"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
Tcl_OpenTcpClient, Tcl_MakeTcpClientChannel, Tcl_OpenTcpServer, Tcl_OpenTcpServerEx \- procedures to open channels using TCP sockets
.SH SYNOPSIS
.nf
\fB#include <tcl.h> \fR
.sp
Tcl_Channel
\fBTcl_OpenTcpClient\fR(\fIinterp, port, host, myaddr, myport, async\fR)
.sp
Tcl_Channel
\fBTcl_MakeTcpClientChannel\fR(\fIsock\fR)
.sp
Tcl_Channel
\fBTcl_OpenTcpServer\fR(\fIinterp, port, myaddr, proc, clientData\fR)
.sp
Tcl_Channel
\fBTcl_OpenTcpServerEx\fR(\fIinterp, service, myaddr, flags, proc, clientData\fR)
.sp
\fBTcl_OpenTcpServerEx\fR(\fIinterp, service, myaddr, flags, backlog, proc, clientData\fR)
.fi
.SH ARGUMENTS
.AS Tcl_TcpAcceptProc clientData
.AP Tcl_Interp *interp in
Tcl interpreter to use for error reporting.  If non-NULL and an
error occurs, an error message is left in the interpreter's result.
.AP int port in
A port number to connect to as a client or to listen on as a server.
43
44
45
46
47
48
49


50
51
52


53
54
55
56
57
58
59
43
44
45
46
47
48
49
50
51
52


53
54
55
56
57
58
59
60
61







+
+

-
-
+
+







is allocated at random.
.AP "const char" *myaddr in
A string specifying the host name or address for network interface to use
for the local end of the connection.  If NULL, a default interface is
chosen.
.AP int async in
If nonzero, the client socket is connected asynchronously to the server.
.AP int backlog in
Length of OS listen backlog queue. Use -1 for default value.
.AP "unsigned int" flags in
ORed combination of \fBTCL_TCPSERVER\fR flags that specify additional
informations about the socket being created.
ORed combination of \fBTCL_TCPSERVER_*\fR flags that specify additional
information about the socket being created.
.AP void *sock in
Platform-specific handle for client TCP socket.
.AP Tcl_TcpAcceptProc *proc in
Pointer to a procedure to invoke each time a new connection is
accepted via the socket.
.AP void *clientData in
Arbitrary one-word value to pass to \fIproc\fR.
167
168
169
170
171
172
173
174




175
176
177
178
179
180
181
182
183
169
170
171
172
173
174
175

176
177
178
179
180
181
182
183
184
185
186
187
188







-
+
+
+
+









If one of the standard channels, \fBstdin\fR, \fBstdout\fR or \fBstderr\fR was
previously closed, the act of creating the new channel also assigns it as a
replacement for the standard channel.
.SS TCL_OPENTCPSERVEREX
.PP
\fBTcl_OpenTcpServerEx\fR behaviour is identical to \fBTcl_OpenTcpServer\fR but
gives more flexibility to the user by providing a mean to further customize some
aspects of the socket via the \fIflags\fR parameter.
aspects of the socket via the \fIflags\fR parameter. Available
flags (dependent on platform) are
\fITCL_TCPSERVER_REUSEADDR\fR
\fITCL_TCPSERVER_REUSEPORT\fR
.SH "PLATFORM ISSUES"
.PP
On Unix platforms, the socket handle is a Unix file descriptor as
returned by the \fBsocket\fR system call.  On the Windows platform, the
socket handle is a \fBSOCKET\fR as defined in the WinSock API.
.SH "SEE ALSO"
Tcl_OpenFileChannel(3), Tcl_RegisterChannel(3), vwait(n)
.SH KEYWORDS
channel, client, server, socket, TCP

Changes to doc/Panic.3.

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
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







-


-
+


-

-
+






-
-
-
-







'\"  Note:  do not modify the .SH NAME line immediately below!
.SH NAME
Tcl_Panic, Tcl_SetPanicProc, Tcl_ConsolePanic \- report fatal error and abort
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
void
\fBTcl_Panic\fR(\fIformat\fR, \fIarg\fR, \fIarg\fR, \fI...\fR)
.sp
void
const char *
\fBTcl_SetPanicProc\fR(\fIpanicProc\fR)
.sp
void
\fBTcl_ConsolePanic\fR(\fIformat\fR, \fIarg\fR, \fIarg\fR, \fI...\fR)
.sp
.fi
.SH ARGUMENTS
.AS Tcl_PanicProc *panicProc
.AP "const char*" format in
A printf-style format string.
.AP "" arg in
Arguments matching the format string.
.AP va_list argList in
An argument list of arguments matching the format string.
Must have been initialized using \fBva_start\fR,
and cleared using \fBva_end\fR.
.AP Tcl_PanicProc *panicProc in
Procedure to report fatal error message and abort.
.BE
.SH DESCRIPTION
.PP
When the Tcl library detects that its internal data structures are in an
inconsistent state, or that its C procedures have been called in a
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
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







+
+
+





-
+
-











.PP
After \fBTcl_SetPanicProc\fR returns, any future calls to
\fBTcl_Panic\fR will call \fIpanicProc\fR, passing along the
\fIformat\fR and \fIarg\fR arguments. \fIpanicProc\fR should avoid
making calls into the Tcl library, or into other libraries that may
call the Tcl library, since the original call to \fBTcl_Panic\fR
indicates the Tcl library is not in a state of reliable operation.
.PP
The result of \fBTcl_SetPanicProc\fR is the full Tcl version with build
information (e.g., \fB9.0.0+abcdef...abcdef.gcc-1002\fR).
.PP
The typical use of \fBTcl_SetPanicProc\fR arranges for the error message
to be displayed or reported in a manner more suitable for the
application or the platform.
.PP
\fBTcl_SetPanicProc\fR can not be used safely by stub-enabled extensions, so its
\fBTcl_SetPanicProc\fR can not be used in stub-enabled extensions.
symbol is not included in the stub table.
.PP
Although the primary callers of \fBTcl_Panic\fR are the procedures of
the Tcl library, \fBTcl_Panic\fR is a public function and may be called
by any extension or application that wishes to abort the process and
have a panic message displayed the same way that panic messages from Tcl
will be displayed.
.PP
.SH "SEE ALSO"
abort(3), printf(3), exec(n), format(n)
.SH KEYWORDS
abort, fatal, error

Changes to doc/ParseArgs.3.

11
12
13
14
15
16
17

18
19
20
21
22
23
24

25
26
27





28
29
30
31
32
33
34
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







+






-
+



+
+
+
+
+







Tcl_ParseArgsObjv \- parse arguments according to a tabular description
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_ParseArgsObjv\fR(\fIinterp, argTable, objcPtr, objv, remObjv\fR)
.fi
.SH ARGUMENTS
.AS "const Tcl_ArgvInfo" ***remObjv in/out
.AP Tcl_Interp *interp out
Where to store error messages.
.AP "const Tcl_ArgvInfo" *argTable in
Pointer to array of option descriptors.
.AP int *objcPtr in/out
.AP "Tcl_Size \&| int" *objcPtr in/out
A pointer to variable holding number of arguments in \fIobjv\fR. Will be
modified to hold number of arguments left in the unprocessed argument list
stored in \fIremObjv\fR.
May be (Tcl_Size *)NULL when not used. If it points to a variable which
type is not \fBTcl_Size\fR, a compiler warning will be generated.
If your extensions is compiled with -DTCL_8_API, this function will return
NULL for argument lists with more than INT_MAX elements (which should
trigger proper error-handling), otherwise expect it to crash.
.AP "Tcl_Obj *const" *objv in
The array of arguments to be parsed.
.AP Tcl_Obj ***remObjv out
Pointer to a variable that will hold the array of unprocessed arguments.
Should be NULL if no return of unprocessed arguments is required. If
\fIobjcPtr\fR is updated to a non-zero value, the array returned through this
must be deallocated using \fBTcl_Free\fR.
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
59
60
61
62
63
64
65


66

67
68


69

70
71
72


73

74
75
76
77
78
79
80







-
-
+
-


-
-
+
-



-
-
+
-







TCL_ERROR is returned. Otherwise, the interpreter result is left unchanged and
TCL_OK is returned.
.PP
The collection of arguments to be parsed is described by the \fIargTable\fR
parameter. This points to a table of descriptor structures that is terminated
by an entry with the \fItype\fR field set to TCL_ARGV_END. As convenience, the
following prototypical entries are provided:
.TP
\fBTCL_ARGV_AUTO_HELP\fR
.IP \fBTCL_ARGV_AUTO_HELP\fR
.
Enables the argument processor to provide help when passed the argument
.QW \fB\-help\fR .
.TP
\fBTCL_ARGV_AUTO_REST\fR
.IP \fBTCL_ARGV_AUTO_REST\fR
.
Instructs the argument processor that arguments after
.QW \fB\-\-\fR
are to be unprocessed.
.TP
\fBTCL_ARGV_TABLE_END\fR
.IP \fBTCL_ARGV_TABLE_END\fR
.
Marks the end of the table of argument descriptors.
.SS "ARGUMENT DESCRIPTOR ENTRIES"
.PP
Each entry of the argument descriptor table must be a structure of type
\fBTcl_ArgvInfo\fR. The structure is defined as this:
.PP
.CS
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
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







-
-
+
-



-
-
+
-


-
-
+
-




-
-
+
-


















-
-
+
-







-
+


-
+




-
-
-
-
-
+
+
+
+
+

-
-
+
-




-
-
+
-



-
-
+
-



-
-
+
-





+
+
+
+
+
+







fields describe the interpretation of the value of the argument, as described
below. The \fIhelpStr\fR field gives some text that is used to provide help to
users when they request it.
.PP
As noted above, the \fItype\fR field is used to describe the interpretation of
the argument's value. The following values are acceptable values for
\fItype\fR:
.TP
\fBTCL_ARGV_CONSTANT\fR
.IP \fBTCL_ARGV_CONSTANT\fR
.
The argument does not take any following value argument. If this argument is
present, the (integer) value of the \fIsrcPtr\fR field is copied to the variable
pointed to by the \fIdstPtr\fR field. The \fIclientData\fR field is ignored.
.TP
\fBTCL_ARGV_END\fR
.IP \fBTCL_ARGV_END\fR
.
This value marks the end of all option descriptors in the table. All other
fields are ignored.
.TP
\fBTCL_ARGV_FLOAT\fR
.IP \fBTCL_ARGV_FLOAT\fR
.
This argument takes a following floating point value argument. The value (once
parsed by \fBTcl_GetDoubleFromObj\fR) will be stored as a double-precision
value in the variable pointed to by the \fIdstPtr\fR field. The \fIsrcPtr\fR
and \fIclientData\fR fields are ignored.
.TP
\fBTCL_ARGV_FUNC\fR
.IP \fBTCL_ARGV_FUNC\fR
.
This argument optionally takes a following value argument; it is up to the
handler callback function passed in \fIsrcPtr\fR to decide. That function will
have the following signature:
.RS
.PP
.CS
typedef int (\fBTcl_ArgvFuncProc\fR)(
        void *\fIclientData\fR,
        Tcl_Obj *\fIobjPtr\fR,
        void *\fIdstPtr\fR);
.CE
.PP
The result is a boolean value indicating whether to consume the following
argument. The \fIclientData\fR is the value from the table entry, the
\fIobjPtr\fR is the value that represents the following argument or NULL if
there are no following arguments at all, and the \fIdstPtr\fR argument to the
\fBTcl_ArgvFuncProc\fR is the location to write the parsed value to.
.RE
.TP
\fBTCL_ARGV_GENFUNC\fR
.IP \fBTCL_ARGV_GENFUNC\fR
.
This argument takes zero or more following arguments; the handler callback
function passed in \fIsrcPtr\fR returns how many (or a negative number to
signal an error, in which case it should also set the interpreter result). The
function will have the following signature:
.RS
.PP
.CS
typedef int (\fBTcl_ArgvGenFuncProc\fR)(
typedef Tcl_Size (\fBTcl_ArgvGenFuncProc\fR)(
        void *\fIclientData\fR,
        Tcl_Interp *\fIinterp\fR,
        int \fIobjc\fR,
        Tcl_Size \fIobjc\fR,
        Tcl_Obj *const *\fIobjv\fR,
        void *\fIdstPtr\fR);
.CE
.PP
The \fIclientData\fR is the value from the table entry, the \fIinterp\fR is
where to store any error messages, the \fIkeyStr\fR is the name of the
argument, \fIobjc\fR and \fIobjv\fR describe an array of all the remaining
arguments, and \fIdstPtr\fR argument to the \fBTcl_ArgvGenFuncProc\fR is the
location to write the parsed value (or values) to.
The \fIclientData\fR is the value from the table entry, the \fIinterp\fR
is where to store any error messages, \fIobjc\fR and \fIobjv\fR describe
an array of all the remaining arguments, and \fIdstPtr\fR argument to the
\fBTcl_ArgvGenFuncProc\fR is the location to write the parsed value
(or values) to.
.RE
.TP
\fBTCL_ARGV_HELP\fR
.IP \fBTCL_ARGV_HELP\fR
.
This special argument does not take any following value argument, but instead
causes \fBTcl_ParseArgsObjv\fR to generate an error message describing the
arguments supported. All other fields except the \fIhelpStr\fR field are
ignored.
.TP
\fBTCL_ARGV_INT\fR
.IP \fBTCL_ARGV_INT\fR
.
This argument takes a following integer value argument. The value (once parsed
by \fBTcl_GetIntFromObj\fR) will be stored as an int in the variable pointed
to by the \fIdstPtr\fR field. The \fIsrcPtr\fR field is ignored.
.TP
\fBTCL_ARGV_REST\fR
.IP \fBTCL_ARGV_REST\fR
.
This special argument does not take any following value argument, but instead
marks all following arguments to be left unprocessed. The \fIsrcPtr\fR,
\fIdstPtr\fR and \fIclientData\fR fields are ignored.
.TP
\fBTCL_ARGV_STRING\fR
.IP \fBTCL_ARGV_STRING\fR
.
This argument takes a following string value argument. A pointer to the string
will be stored at \fIdstPtr\fR; the string inside will have a lifetime linked
to the lifetime of the string representation of the argument value that it
came from, and so should be copied if it needs to be retained. The
\fIsrcPtr\fR and \fIclientData\fR fields are ignored.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
The values in the \fIobjv\fR argument to \fBTcl_ParseArgsObjv\fR will not have
their reference counts modified by this function. The interpreter result may
be modified on error; the values passed should not be the interpreter result
with no further reference added.
.SH "SEE ALSO"
Tcl_GetIndexFromObj(3), Tcl_Main(3), Tcl_CreateObjCommand(3)
.SH KEYWORDS
argument, parse
'\" Local Variables:
'\" fill-column: 78
'\" End:

Changes to doc/ParseCmd.3.

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
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







+










-
+







const char *
\fBTcl_ParseVar\fR(\fIinterp, start, termPtr\fR)
.sp
\fBTcl_FreeParse\fR(\fIusedParsePtr\fR)
.sp
int
\fBTcl_EvalTokensStandard\fR(\fIinterp, tokenPtr, numTokens\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp *usedParsePtr out
.AP Tcl_Interp *interp out
For procedures other than \fBTcl_FreeParse\fR and
\fBTcl_EvalTokensStandard\fR, used only for error reporting;
if NULL, then no error messages are left after errors.
For \fBTcl_EvalTokensStandard\fR, determines the context for evaluating
the script and also is used for error reporting; must not be NULL.
.AP "const char" *start in
Pointer to first character in string to parse.
.AP int numBytes in
.AP Tcl_Size numBytes in
Number of bytes in string to parse, not including any terminating null
character.  If less than 0 then the script consists of all characters
following \fIstart\fR up to the first null character.
.AP int nested in
Non-zero means that the script is part of a command substitution so an
unquoted close bracket should be treated as a command terminator.  If zero,
close brackets have no special meaning.
151
152
153
154
155
156
157
158

159
160
161
162
163
164
165
152
153
154
155
156
157
158

159
160
161
162
163
164
165
166







-
+







returns \fBTCL_OK\fR and fills in the structure pointed to by
\fIparsePtr\fR with information about the structure of the variable name
(see below for details).  If an error
occurs while parsing the command then \fBTCL_ERROR\fR is returned, an
error message is left in \fIinterp\fR's result (if \fIinterp\fR is not
NULL), and no information is left at \fI*parsePtr\fR.
.PP
\fBTcl_ParseVar\fR parse a Tcl variable reference such as \fB$abc\fR
\fBTcl_ParseVar\fR parses a Tcl variable reference such as \fB$abc\fR
or \fB$x([expr {$index + 1}])\fR from the beginning of its \fIstart\fR
argument.  The first character of \fIstart\fR must be \fB$\fR.  If
the variable name is parsed successfully, \fBTcl_ParseVar\fR returns a
pointer to the string value of the variable.  If an error occurs while
parsing, then NULL is returned and an error message is left in
\fIinterp\fR's result.
.PP
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
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







-
+

-
+

-
-
+
+

-
+



-
+


-
-
+
+









-
+
-







.SH "TCL_PARSE STRUCTURE"
.PP
\fBTcl_ParseCommand\fR, \fBTcl_ParseExpr\fR, \fBTcl_ParseBraces\fR,
\fBTcl_ParseQuotedString\fR, and \fBTcl_ParseVarName\fR
return parse information in two data structures, Tcl_Parse and Tcl_Token:
.PP
.CS
typedef struct Tcl_Parse {
typedef struct {
    const char *\fIcommentStart\fR;
    int \fIcommentSize\fR;
    Tcl_Size \fIcommentSize\fR;
    const char *\fIcommandStart\fR;
    int \fIcommandSize\fR;
    int \fInumWords\fR;
    Tcl_Size \fIcommandSize\fR;
    Tcl_Size \fInumWords\fR;
    Tcl_Token *\fItokenPtr\fR;
    int \fInumTokens\fR;
    Tcl_Size \fInumTokens\fR;
    ...
} \fBTcl_Parse\fR;

typedef struct Tcl_Token {
typedef struct {
    int \fItype\fR;
    const char *\fIstart\fR;
    size_t \fIsize\fR;
    size_t \fInumComponents\fR;
    Tcl_Size \fIsize\fR;
    Tcl_Size \fInumComponents\fR;
} \fBTcl_Token\fR;
.CE
.PP
The first five fields of a Tcl_Parse structure
are filled in only by \fBTcl_ParseCommand\fR.
These fields are not used by the other parsing procedures.
.PP
\fBTcl_ParseCommand\fR fills in a Tcl_Parse structure
with information that describes one Tcl command and any comments that
precede the command.
precede the command. If there are comments,
If there are comments,
the \fIcommentStart\fR field points to the \fB#\fR character that begins
the first comment and \fIcommentSize\fR indicates the number of bytes
in all of the comments preceding the command, including the newline
character that terminates the last comment.
If the command is not preceded by any comments, \fIcommentSize\fR is 0.
\fBTcl_ParseCommand\fR also sets the \fIcommandStart\fR field
to point to the first character of the first
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
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







-
-
+
-












-
-
+
-



-
-
+
-






-
-
+
-


-
-
+
-


-
-
+
-





-
-
+
-













-
-
+
-







that are described below.  The \fIstart\fR field
points to the first character in the token and the \fIsize\fR field
gives the total number of characters in the token.  Some token types,
such as \fBTCL_TOKEN_WORD\fR and \fBTCL_TOKEN_VARIABLE\fR, consist of
several component tokens, which immediately follow the parent token;
the \fInumComponents\fR field describes how many of these there are.
The \fItype\fR field has one of the following values:
.TP 20
\fBTCL_TOKEN_WORD\fR
.IP \fBTCL_TOKEN_WORD\fR
.
This token ordinarily describes one word of a command
but it may also describe a quoted or braced string in an expression.
The token describes a component of the script that is
the result of concatenating together a sequence of subcomponents,
each described by a separate subtoken.
The token starts with the first non-blank
character of the component (which may be a double-quote or open brace)
and includes all characters in the component up to but not including the
space, semicolon, close bracket, close quote, or close brace that
terminates the component.  The \fInumComponents\fR field counts the total
number of sub-tokens that make up the word, including sub-tokens
of \fBTCL_TOKEN_VARIABLE\fR and \fBTCL_TOKEN_BS\fR tokens.
.TP
\fBTCL_TOKEN_SIMPLE_WORD\fR
.IP \fBTCL_TOKEN_SIMPLE_WORD\fR
.
This token has the same meaning as \fBTCL_TOKEN_WORD\fR, except that
the word is guaranteed to consist of a single \fBTCL_TOKEN_TEXT\fR
sub-token.  The \fInumComponents\fR field is always 1.
.TP
\fBTCL_TOKEN_EXPAND_WORD\fR
.IP \fBTCL_TOKEN_EXPAND_WORD\fR
.
This token has the same meaning as \fBTCL_TOKEN_WORD\fR, except that
the command parser notes this word began with the expansion
prefix \fB{*}\fR, indicating that after substitution,
the list value of this word should be expanded to form multiple
arguments in command evaluation.  This
token type can only be created by Tcl_ParseCommand.
.TP
\fBTCL_TOKEN_TEXT\fR
.IP \fBTCL_TOKEN_TEXT\fR
.
The token describes a range of literal text that is part of a word.
The \fInumComponents\fR field is always 0.
.TP
\fBTCL_TOKEN_BS\fR
.IP \fBTCL_TOKEN_BS\fR
.
The token describes a backslash sequence such as \fB\en\fR or \fB\e0xA3\fR.
The \fInumComponents\fR field is always 0.
.TP
\fBTCL_TOKEN_COMMAND\fR
.IP \fBTCL_TOKEN_COMMAND\fR
.
The token describes a command whose result must be substituted into
the word.  The token includes the square brackets that surround the
command.  The \fInumComponents\fR field is always 0 (the nested command
is not parsed; call \fBTcl_ParseCommand\fR recursively if you want to
see its tokens).
.TP
\fBTCL_TOKEN_VARIABLE\fR
.IP \fBTCL_TOKEN_VARIABLE\fR
.
The token describes a variable substitution, including the
\fB$\fR, variable name, and array index (if there is one) up through the
close parenthesis that terminates the index.  This token is followed
by one or more additional tokens that describe the variable name and
array index.  If \fInumComponents\fR  is 1 then the variable is a
scalar and the next token is a \fBTCL_TOKEN_TEXT\fR token that gives the
variable name.  If \fInumComponents\fR is greater than 1 then the
variable is an array: the first sub-token is a \fBTCL_TOKEN_TEXT\fR
token giving the array name and the remaining sub-tokens are
\fBTCL_TOKEN_TEXT\fR, \fBTCL_TOKEN_BS\fR, \fBTCL_TOKEN_COMMAND\fR, and
\fBTCL_TOKEN_VARIABLE\fR tokens that must be concatenated to produce the
array index. The \fInumComponents\fR field includes nested sub-tokens
that are part of \fBTCL_TOKEN_VARIABLE\fR tokens in the array index.
.TP
\fBTCL_TOKEN_SUB_EXPR\fR
.IP \fBTCL_TOKEN_SUB_EXPR\fR
.
The token describes one subexpression of an expression
(or an entire expression).
A subexpression may consist of a value
such as an integer literal, variable substitution,
or parenthesized subexpression;
it may also consist of an operator and its operands.
The token starts with the first non-blank character of the subexpression
337
338
339
340
341
342
343
344
345

346
347
348
349
350
351
352
353
321
322
323
324
325
326
327


328

329
330
331
332
333
334
335







-
-
+
-







Otherwise, the subexpression is a value described by
one of the token types \fBTCL_TOKEN_WORD\fR, \fBTCL_TOKEN_TEXT\fR,
\fBTCL_TOKEN_BS\fR, \fBTCL_TOKEN_COMMAND\fR,
\fBTCL_TOKEN_VARIABLE\fR, and \fBTCL_TOKEN_SUB_EXPR\fR.
The \fInumComponents\fR field
counts the total number of sub-tokens that make up the subexpression;
this includes the sub-tokens for any nested \fBTCL_TOKEN_SUB_EXPR\fR tokens.
.TP
\fBTCL_TOKEN_OPERATOR\fR
.IP \fBTCL_TOKEN_OPERATOR\fR
.
The token describes one operator of an expression
such as \fB&&\fR or \fBhypot\fR.
A \fBTCL_TOKEN_OPERATOR\fR token is always preceded by a
\fBTCL_TOKEN_SUB_EXPR\fR token
that describes the operator and its operands;
the \fBTCL_TOKEN_SUB_EXPR\fR token's \fInumComponents\fR field
can be used to determine the number of operands.
446
447
448
449
450
451
452
453


428
429
430
431
432
433
434

435
436







-
+
+
.PP
There are additional fields in the Tcl_Parse structure after the
\fInumTokens\fR field, but these are for the private use of
\fBTcl_ParseCommand\fR, \fBTcl_ParseExpr\fR, \fBTcl_ParseBraces\fR,
\fBTcl_ParseQuotedString\fR, and \fBTcl_ParseVarName\fR; they should not be
referenced by code outside of these procedures.
.SH KEYWORDS
backslash substitution, braces, command, expression, parse, token, variable substitution
backslash substitution, braces, command, expression, parse, token,
variable substitution

Changes to doc/PkgRequire.3.

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
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







+







-
+
-













-
+







\fBTcl_PkgPresentEx\fR(\fIinterp, name, version, exact, clientDataPtr\fR)
.sp
int
\fBTcl_PkgProvide\fR(\fIinterp, name, version\fR)
.sp
int
\fBTcl_PkgProvideEx\fR(\fIinterp, name, version, clientData\fR)
.fi
.SH ARGUMENTS
.AS void *clientDataPtr out
.AP Tcl_Interp *interp in
Interpreter where package is needed or available.
.AP "const char" *name in
Name of package.
.AP "const char" *version in
A version string consisting of one or more decimal numbers
A version specification string as described for \fBpackage require\fR.
separated by dots.
.AP int exact in
Non-zero means that only the particular version specified by
\fIversion\fR is acceptable.
Zero means that newer versions than \fIversion\fR are also
acceptable as long as they have the same major version number
as \fIversion\fR.
.AP "const void" *clientData in
Arbitrary value to be associated with the package.
.AP void *clientDataPtr out
Pointer to place to store the value associated with the matching
package. It is only changed if the pointer is not NULL and the
function completed successfully. The storage can be any pointer
type with the same size as a void pointer.
.AP int objc in
.AP Tcl_Size objc in
Number of requirements.
.AP Tcl_Obj* objv[] in
Array of requirements.
.BE
.SH DESCRIPTION
.PP
These procedures provide C-level interfaces to Tcl's package and
87
88
89
90
91
92
93




94
95
96
97

87
88
89
90
91
92
93
94
95
96
97
98
99
100

101







+
+
+
+



-
+
allow the setting and retrieving of the client data associated with
the package. In all other respects they are equivalent to the matching
functions.
.PP
\fBTcl_PkgRequireProc\fR is the form of \fBpackage require\fR handling
multiple requirements. The other forms are present for backward
compatibility and translate their invocations to this form.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
The requirements values given (in the \fIobjv\fR argument) to
\fBTcl_PkgRequireProc\fR must have non-zero reference counts.
.SH KEYWORDS
package, present, provide, require, version
.SH "SEE ALSO"
package(n), Tcl_StaticPackage(3)
package(n), Tcl_StaticLibrary(3)

Changes to doc/Preserve.3.

15
16
17
18
19
20
21

22
23
24
25
26
27
28
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29







+







\fB#include <tcl.h>\fR
.sp
\fBTcl_Preserve\fR(\fIclientData\fR)
.sp
\fBTcl_Release\fR(\fIclientData\fR)
.sp
\fBTcl_EventuallyFree\fR(\fIclientData, freeProc\fR)
.fi
.SH ARGUMENTS
.AS Tcl_FreeProc clientData
.AP void *clientData in
Token describing structure to be freed or reallocated.  Usually a pointer
to memory for structure.
.AP Tcl_FreeProc *freeProc in
Procedure to invoke to free \fIclientData\fR.
76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
91
92
93
94
95
96
97
77
78
79
80
81
82
83

84
85
86
87
88



89
90
91
92
93
94
95







-
+




-
-
-







.PP
All the work of freeing the object is carried out by \fIfreeProc\fR.
\fIFreeProc\fR must have arguments and result that match the
type \fBTcl_FreeProc\fR:
.PP
.CS
typedef void \fBTcl_FreeProc\fR(
        char *\fIblockPtr\fR);
        void *\fIblockPtr\fR);
.CE
.PP
The \fIblockPtr\fR argument to \fIfreeProc\fR will be the
same as the \fIclientData\fR argument to \fBTcl_EventuallyFree\fR.
The type of \fIblockPtr\fR (\fBchar *\fR) is different than the type of the
\fIclientData\fR argument to \fBTcl_EventuallyFree\fR for historical
reasons, but the value is the same.
.PP
When the \fIclientData\fR argument to \fBTcl_EventuallyFree\fR
refers to storage allocated and returned by a prior call to
\fBTcl_Alloc\fR or another function of the Tcl library,
then the \fIfreeProc\fR argument should be given the special value of
\fBTCL_DYNAMIC\fR.
.PP

Changes to doc/PrintDbl.3.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25







+







.SH NAME
Tcl_PrintDouble \- Convert floating value to string
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_PrintDouble\fR(\fIinterp, value, dst\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp *interp out
.AP Tcl_Interp *interp in
This argument is ignored.
.AP double value in
Floating-point value to be converted.
.AP char *dst out

Changes to doc/RecEvalObj.3.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25







+







Tcl_RecordAndEvalObj \- save command on history list before evaluating
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_RecordAndEvalObj\fR(\fIinterp, cmdPtr, flags\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Tcl interpreter in which to evaluate command.
.AP Tcl_Obj *cmdPtr in
Points to a Tcl value containing a command (or sequence of commands)
to execute.
40
41
42
43
44
45
46






47
48
49
50
51
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58







+
+
+
+
+
+





you should invoke \fBTcl_EvalObjEx\fR instead of \fBTcl_RecordAndEvalObj\fR.
Normally \fBTcl_RecordAndEvalObj\fR is only called with top-level
commands typed by the user, since the purpose of history is to
allow the user to re-issue recently invoked commands.
If the \fIflags\fR argument contains the \fBTCL_NO_EVAL\fR bit then
the command is recorded without being evaluated.

.SH "REFERENCE COUNT MANAGEMENT"
.PP
The reference count of the \fIcmdPtr\fR argument to \fBTcl_RecordAndEvalObj\fR
must be at least 1. This function will modify the interpreter result; do not
use an existing result as \fIcmdPtr\fR directly without incrementing its
reference count.
.SH "SEE ALSO"
Tcl_EvalObjEx, Tcl_GetObjResult

.SH KEYWORDS
command, event, execute, history, interpreter, value, record

Changes to doc/RecordEval.3.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26







+







Tcl_RecordAndEval \- save command on history list before evaluating
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_RecordAndEval\fR(\fIinterp, cmd, flags\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Tcl interpreter in which to evaluate command.
.AP "const char" *cmd in
Command (or sequence of commands) to execute.
.AP int flags in

Changes to doc/RegConfig.3.

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
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







-

-
+











-
+











-
+


-
+







'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
Tcl_RegisterConfig \- procedures to register embedded configuration information
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
void
\fBTcl_RegisterConfig\fR(\fIinterp, pkgName, configuration, valEncoding\fR)
.sp
.fi
.SH ARGUMENTS
.AS Tcl_Interp *configuration
.AP Tcl_Interp *interp in
Refers to the interpreter the embedded configuration information is
registered for. Must not be NULL.
.AP "const char" *pkgName in
Contains the name of the package registering the embedded
configuration as ASCII string. This means that this information is in
UTF-8 too. Must not be NULL.
.AP "const Tcl_Config" *configuration in
Refers to an array of Tcl_Config entries containing the information
embedded in the binary library. Must not be NULL. The end of the array
embedded in the library. Must not be NULL. The end of the array
is signaled by either a key identical to NULL, or a key referring to
the empty string.
.AP "const char" *valEncoding in
Contains the name of the encoding used to store the configuration
values as ASCII string. This means that this information is in UTF-8
too. Must not be NULL.
.BE
.SH DESCRIPTION
.PP
The function described here has its base in TIP 59 and provides
extensions with support for the embedding of configuration
information into their binary library and the generation of a
information into their library and the generation of a
Tcl-level interface for querying this information.
.PP
To embed configuration information into their binary library an
To embed configuration information into their library an
extension has to define a non-volatile array of Tcl_Config entries in
one if its source files and then call \fBTcl_RegisterConfig\fR to
register that information.
.PP
\fBTcl_RegisterConfig\fR takes four arguments; first, a reference to
the interpreter we are registering the information with, second, the
name of the package registering its configuration information, third,
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

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







+


+

+


+
-
+
-






-
+







-
+
the provided information so that the keys from \fIconfiguration\fR and
their associated values can be retrieved through calls to
\fBpkgconfig\fR.
.PP
The command \fBpkgconfig\fR will provide two subcommands, \fBlist\fR
and \fBget\fR:
.RS
.\" METHOD: list
.TP
::\fIpkgName\fR::\fBpkgconfig\fR list
.
Returns a list containing the names of all defined keys.
.\" METHOD: get
.TP
::\fIpkgName\fR::\fBpkgconfig\fR get \fIkey\fR
.
Returns the configuration value associated with the specified
Returns the configuration value associated with the specified \fIkey\fR.
\fIkey\fR.
.RE
.SH TCL_CONFIG
.PP
The \fBTcl_Config\fR structure contains the following fields:
.PP
.CS
typedef struct Tcl_Config {
typedef struct {
    const char *\fIkey\fR;
    const char *\fIvalue\fR;
} \fBTcl_Config\fR;
.CE
.\" No cross references yet.
.\" .SH "SEE ALSO"
.SH KEYWORDS
embedding, configuration, binary library
embedding, configuration, library

Changes to doc/RegExp.3.

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
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







-








-














-
+






-
+





-
+















-
+



-
+


-
+







.sp
Tcl_RegExp
\fBTcl_RegExpCompile\fR(\fIinterp\fR, \fIpattern\fR)
.sp
int
\fBTcl_RegExpExec\fR(\fIinterp\fR, \fIregexp\fR, \fItext\fR, \fIstart\fR)
.sp
void
\fBTcl_RegExpRange\fR(\fIregexp\fR, \fIindex\fR, \fIstartPtr\fR, \fIendPtr\fR)
.sp
Tcl_RegExp
\fBTcl_GetRegExpFromObj\fR(\fIinterp\fR, \fIpatObj\fR, \fIcflags\fR)
.sp
int
\fBTcl_RegExpExecObj\fR(\fIinterp\fR, \fIregexp\fR, \fItextObj\fR, \fIoffset\fR, \fInmatches\fR, \fIeflags\fR)
.sp
void
\fBTcl_RegExpGetInfo\fR(\fIregexp\fR, \fIinfoPtr\fR)
.fi
.SH ARGUMENTS
.AS Tcl_RegExpInfo *interp in/out
.AP Tcl_Interp *interp in
Tcl interpreter to use for error reporting.  The interpreter may be
NULL if no error reporting is desired.
.AP Tcl_Obj *textObj in/out
Refers to the value from which to get the text to search.  The
internal representation of the value may be converted to a form that
can be efficiently searched.
.AP Tcl_Obj *patObj in/out
Refers to the value from which to get a regular expression. The
compiled regular expression is cached in the value.
.AP char *text in
.AP "const char" *text in
Text to search for a match with a regular expression.
.AP "const char" *pattern in
String in the form of a regular expression pattern.
.AP Tcl_RegExp regexp in
Compiled regular expression.  Must have been returned previously
by \fBTcl_GetRegExpFromObj\fR or \fBTcl_RegExpCompile\fR.
.AP char *start in
.AP "const char" *start in
If \fItext\fR is just a portion of some other string, this argument
identifies the beginning of the larger string.
If it is not the same as \fItext\fR, then no
.QW \fB^\fR
matches will be allowed.
.AP size_t index in
.AP Tcl_Size index in
Specifies which range is desired:  0 means the range of the entire
match, 1 or greater means the range that matched a parenthesized
sub-expression.
.AP "const char" **startPtr out
The address of the first character in the range is stored here, or
NULL if there is no such range.
.AP "const char" **endPtr out
The address of the character just after the last one in the range
is stored here, or NULL if there is no such range.
.AP int cflags in
OR-ed combination of the compilation flags \fBTCL_REG_ADVANCED\fR,
\fBTCL_REG_EXTENDED\fR, \fBTCL_REG_BASIC\fR, \fBTCL_REG_EXPANDED\fR,
\fBTCL_REG_QUOTE\fR, \fBTCL_REG_NOCASE\fR, \fBTCL_REG_NEWLINE\fR,
\fBTCL_REG_NLSTOP\fR, \fBTCL_REG_NLANCH\fR, \fBTCL_REG_NOSUB\fR, and
\fBTCL_REG_CANMATCH\fR. See below for more information.
.AP size_t offset in
.AP Tcl_Size offset in
The character offset into the text where matching should begin.
The value of the offset has no impact on \fB^\fR matches.  This
behavior is controlled by \fIeflags\fR.
.AP size_t nmatches in
.AP Tcl_Size nmatches in
The number of matching subexpressions that should be remembered for
later use.  If this value is 0, then no subexpression match
information will be computed.  If the value is TCL_INDEX_NONE, then
information will be computed.  If the value is negative, then
all of the matching subexpressions will be remembered.  Any other
value will be taken as the maximum number of subexpressions to
remember.
.AP int eflags in
OR-ed combination of the execution flags \fBTCL_REG_NOTBOL\fR and
\fBTCL_REG_NOTEOL\fR. See below for more information.
.AP Tcl_RegExpInfo *infoPtr out
120
121
122
123
124
125
126
127

128
129
130
131
132
133
134
118
119
120
121
122
123
124

125
126
127
128
129
130
131
132







-
+







\fBTcl_RegExpCompile\fR compiles a regular expression string into
the internal form used for efficient pattern matching.
The return value is a token for this compiled form, which can be
used in subsequent calls to \fBTcl_RegExpExec\fR or \fBTcl_RegExpRange\fR.
If an error occurs while compiling the regular expression then
\fBTcl_RegExpCompile\fR returns NULL and leaves an error message
in the interpreter result.
Note:  the return value from \fBTcl_RegExpCompile\fR is only valid
Note that the return value from \fBTcl_RegExpCompile\fR is only valid
up to the next call to \fBTcl_RegExpCompile\fR;  it is not safe to
retain these values for long periods of time.
.PP
\fBTcl_RegExpExec\fR executes the regular expression pattern matcher.
It returns 1 if \fItext\fR contains a range of characters that
match \fIregexp\fR, 0 if no match is found, and
\-1 if an error occurs.
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
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







+







+







+








+






+



+



+

















+
















+




















+






+







long as the internal representation of \fIpatObj\fR refers to the
compiled form.  The \fIcflags\fR argument is a bit-wise OR of
zero or more of the following flags that control the compilation of
\fIpatObj\fR:
.RS 2
.TP
\fBTCL_REG_ADVANCED\fR
.
Compile advanced regular expressions
.PQ ARE s .
This mode corresponds to
the normal regular expression syntax accepted by the Tcl \fBregexp\fR and
\fBregsub\fR commands.
.TP
\fBTCL_REG_EXTENDED\fR
.
Compile extended regular expressions
.PQ ERE s .
This mode corresponds
to the regular expression syntax recognized by Tcl 8.0 and earlier
versions.
.TP
\fBTCL_REG_BASIC\fR
.
Compile basic regular expressions
.PQ BRE s .
This mode corresponds
to the regular expression syntax recognized by common Unix utilities
like \fBsed\fR and \fBgrep\fR.  This is the default if no flags are
specified.
.TP
\fBTCL_REG_EXPANDED\fR
.
Compile the regular expression (basic, extended, or advanced) using an
expanded syntax that allows comments and whitespace.  This mode causes
non-backslashed non-bracket-expression white
space and #-to-end-of-line comments to be ignored.
.TP
\fBTCL_REG_QUOTE\fR
.
Compile a literal string, with all characters treated as ordinary characters.
.TP
\fBTCL_REG_NOCASE\fR
.
Compile for matching that ignores upper/lower case distinctions.
.TP
\fBTCL_REG_NEWLINE\fR
.
Compile for newline-sensitive matching.  By default, newline is a
completely ordinary character with no special meaning in either
regular expressions or strings.  With this flag,
.QW [^
bracket expressions and
.QW .
never match newline,
.QW ^
matches an empty string
after any newline in addition to its normal function, and
.QW $
matches
an empty string before any newline in addition to its normal function.
\fBREG_NEWLINE\fR is the bit-wise OR of \fBREG_NLSTOP\fR and
\fBREG_NLANCH\fR.
.TP
\fBTCL_REG_NLSTOP\fR
.
Compile for partial newline-sensitive matching,
with the behavior of
.QW [^
bracket expressions and
.QW .
affected, but not the behavior of
.QW ^
and
.QW $ .
In this mode,
.QW [^
bracket expressions and
.QW .
never match newline.
.TP
\fBTCL_REG_NLANCH\fR
.
Compile for inverse partial newline-sensitive matching,
with the behavior of
.QW ^
and
.QW $
(the
.QW anchors )
affected, but not the behavior of
.QW [^
bracket expressions and
.QW . .
In this mode
.QW ^
matches an empty string
after any newline in addition to its normal function, and
.QW $
matches
an empty string before any newline in addition to its normal function.
.TP
\fBTCL_REG_NOSUB\fR
.
Compile for matching that reports only success or failure,
not what was matched.  This reduces compile overhead and may improve
performance.  Subsequent calls to \fBTcl_RegExpGetInfo\fR or
\fBTcl_RegExpRange\fR will not report any match information.
.TP
\fBTCL_REG_CANMATCH\fR
.
Compile for matching that reports the potential to complete a partial
match given more text (see below).
.RE
.PP
Only one of
\fBTCL_REG_EXTENDED\fR,
\fBTCL_REG_ADVANCED\fR,
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
366
367
368
369
370
371
372
373
374
375
376
377
378
379
















380
381
382
383


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
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







+









+















-
-
+
+

-
+














-
-
-
+
+
+




















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+
+
\fBTcl_RegExpExec\fR, the behavior of anchors is not affected by the
offset value.  Instead the behavior of the anchors is explicitly
controlled by the \fIeflags\fR argument, which is a bit-wise OR of
zero or more of the following flags:
.RS 2
.TP
\fBTCL_REG_NOTBOL\fR
.
The starting character will not be treated as the beginning of a
line or the beginning of the string, so
.QW ^
will not match there.
Note that this flag has no effect on how
.QW \fB\eA\fR
matches.
.TP
\fBTCL_REG_NOTEOL\fR
.
The last character in the string will not be treated as the end of a
line or the end of the string, so
.QW $
will not match there.
Note that this flag has no effect on how
.QW \fB\eZ\fR
matches.
.RE
.PP
\fBTcl_RegExpGetInfo\fR retrieves information about the last match
performed with a given regular expression \fIregexp\fR.  The
\fIinfoPtr\fR argument contains a pointer to a structure that is
defined as follows:
.PP
.CS
typedef struct Tcl_RegExpInfo {
    size_t \fInsubs\fR;
typedef struct {
    Tcl_Size \fInsubs\fR;
    Tcl_RegExpIndices *\fImatches\fR;
    size_t \fIextendStart\fR;
    Tcl_Size \fIextendStart\fR;
} \fBTcl_RegExpInfo\fR;
.CE
.PP
The \fInsubs\fR field contains a count of the number of parenthesized
subexpressions within the regular expression.  If the \fBTCL_REG_NOSUB\fR
was used, then this value will be zero.  The \fImatches\fR field
points to an array of \fInsubs\fR+1 values that indicate the bounds of each
subexpression matched.  The first element in the array refers to the
range matched by the entire regular expression, and subsequent elements
refer to the parenthesized subexpressions in the order that they
appear in the pattern.  Each element is a structure that is defined as
follows:
.PP
.CS
typedef struct Tcl_RegExpIndices {
    size_t \fIstart\fR;
    size_t \fIend\fR;
typedef struct {
    Tcl_Size \fIstart\fR;
    Tcl_Size \fIend\fR;
} \fBTcl_RegExpIndices\fR;
.CE
.PP
The \fIstart\fR and \fIend\fR values are Unicode character indices
relative to the offset location within \fIobjPtr\fR where matching began.
The \fIstart\fR index identifies the first character of the matched
subexpression.  The \fIend\fR index identifies the first character
after the matched subexpression.  If the subexpression matched the
empty string, then \fIstart\fR and \fIend\fR will be equal.  If the
subexpression did not participate in the match, then \fIstart\fR and
\fIend\fR will be set to \-1.
.PP
The \fIextendStart\fR field in \fBTcl_RegExpInfo\fR is only set if the
\fBTCL_REG_CANMATCH\fR flag was used.  It indicates the first
character in the string where a match could occur.  If a match was
found, this will be the same as the beginning of the current match.
If no match was found, then it indicates the earliest point at which a
match might occur if additional text is appended to the string.  If it
is no match is possible even with further text, this field will be set
to \-1.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
The \fItextObj\fR and \fIpatObj\fR arguments to \fBTcl_RegExpMatchObj\fR must
have reference counts of at least 1.  Note however that this function may set
the interpreter result; neither argument should be the direct interpreter
result without an additional reference being taken.
.PP
The \fIpatObj\fR argument to \fBTcl_GetRegExpFromObj\fR must have a reference
count of at least 1.  Note however that this function may set the interpreter
result; the argument should not be the direct interpreter result without an
additional reference being taken.
.PP
The \fItextObj\fR argument to \fBTcl_RegExpExecObj\fR must have a reference
count of at least 1.  Note however that this function may set the interpreter
result; the argument should not be the direct interpreter result without an
additional reference being taken.
.SH "SEE ALSO"
re_syntax(n)
.SH KEYWORDS
match, pattern, regular expression, string, subexpression, Tcl_RegExpIndices, Tcl_RegExpInfo
match, pattern, regular expression, string, subexpression,
Tcl_RegExpIndices, Tcl_RegExpInfo

Added doc/SaveInterpState.3.











































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
'\"
'\" Copyright (c) 1997 Sun Microsystems, Inc.
'\" Contributions from Don Porter, NIST, 2004. (not subject to US copyright)
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_SaveInterpState 3 8.1 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_SaveInterpState, Tcl_RestoreInterpState, Tcl_DiscardInterpState \- save and restore an interpreter's state
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_InterpState
\fBTcl_SaveInterpState\fR(\fIinterp, status\fR)
.sp
int
\fBTcl_RestoreInterpState\fR(\fIinterp, state\fR)
.sp
\fBTcl_DiscardInterpState\fR(\fIstate\fR)
.fi
.SH ARGUMENTS
.AS Tcl_InterpState savedPtr
.AP Tcl_Interp *interp in
Interpreter for which state should be saved.
.AP int status in
Return code value to save as part of interpreter state.
.AP Tcl_InterpState state in
Saved state token to be restored or discarded.
.BE
.SH DESCRIPTION
.PP
These routines allows a C procedure to take a snapshot of the current
state of an interpreter so that it can be restored after a call
to \fBTcl_Eval\fR or some other routine that modifies the interpreter
state.
.PP
\fBTcl_SaveInterpState\fR stores a snapshot of the interpreter state in
an opaque token returned by \fBTcl_SaveInterpState\fR.  That token
value may then be passed back to one of \fBTcl_RestoreInterpState\fR
or \fBTcl_DiscardInterpState\fR, depending on whether the interp
state is to be restored.  So long as one of the latter two routines
is called, Tcl will take care of memory management.
.PP
\fBTcl_SaveInterpState\fR takes a snapshot of those portions of
interpreter state that make up the full result of script evaluation.
This include the interpreter result, the return code (passed in
as the \fIstatus\fR argument, and any return options, including
\fB\-errorinfo\fR and \fB\-errorcode\fR when an error is in progress.
This snapshot is returned as an opaque token of type \fBTcl_InterpState\fR.
The call to \fBTcl_SaveInterpState\fR does not itself change the
state of the interpreter.
.PP
\fBTcl_RestoreInterpState\fR accepts a \fBTcl_InterpState\fR token
previously returned by \fBTcl_SaveInterpState\fR and restores the
state of the interp to the state held in that snapshot.  The return
value of \fBTcl_RestoreInterpState\fR is the status value originally
passed to \fBTcl_SaveInterpState\fR when the snapshot token was
created.
.PP
\fBTcl_DiscardInterpState\fR is called to release a \fBTcl_InterpState\fR
token previously returned by \fBTcl_SaveInterpState\fR when that
snapshot is not to be restored to an interp.
.PP
The \fBTcl_InterpState\fR token returned by \fBTcl_SaveInterpState\fR
must eventually be passed to either \fBTcl_RestoreInterpState\fR
or \fBTcl_DiscardInterpState\fR to avoid a memory leak.  Once
the \fBTcl_InterpState\fR token is passed to one of them, the
token is no longer valid and should not be used anymore.
.SH KEYWORDS
result, state, interp

Deleted doc/SaveResult.3.

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
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





















































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
'\"
'\" Copyright (c) 1997 by Sun Microsystems, Inc.
'\" Contributions from Don Porter, NIST, 2004. (not subject to US copyright)
'\" Copyright (c) 2018 Nathan Coulter.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_SaveResult 3 8.1 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_SaveInterpState, Tcl_RestoreInterpState, Tcl_DiscardInterpState,
Tcl_SaveResult, Tcl_RestoreResult, Tcl_DiscardResult \- Save and restore the
state of an an interpreter.
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_InterpState
\fBTcl_SaveInterpState\fR(\fIinterp, status\fR)
.sp
int
\fBTcl_RestoreInterpState\fR(\fIinterp, state\fR)
.sp
\fBTcl_DiscardInterpState\fR(\fIstate\fR)
.sp
\fBTcl_SaveResult\fR(\fIinterp, savedPtr\fR)
.sp
\fBTcl_RestoreResult\fR(\fIinterp, savedPtr\fR)
.sp
\fBTcl_DiscardResult\fR(\fIsavedPtr\fR)
.SH ARGUMENTS
.AS Tcl_InterpState savedPtr
.AP Tcl_Interp *interp in
The interpreter for the operation.
.AP int status in
The return code for the state.
.AP Tcl_InterpState state in
A token for saved state.
.AP Tcl_SavedResult *savedPtr in
A pointer to storage for saved state.
.BE
.SH DESCRIPTION
.PP
These routines save the state of an interpreter before a call to a routine such
as \fBTcl_Eval\fR, and restore the state afterwards.
.PP
\fBTcl_SaveInterpState\fR saves the parts of \fIinterp\fR that comprise the
result of a script, including the resulting value, the return code passed as
\fIstatus\fR, and any options such as \fB\-errorinfo\fR and \fB\-errorcode\fR.
It returns a token for the saved state.  The interpreter result is not reset
and no interpreter state is changed.
.PP
\fBTcl_RestoreInterpState\fR restores the state indicated by \fIstate\fR and
returns the \fIstatus\fR originally passed in the corresponding call to
\fBTcl_SaveInterpState\fR.
.PP
If a saved state is not restored, \fBTcl_DiscardInterpState\fR must be called
to release it.  A token used to discard or restore state must not be used
again.
.PP
\fBTcl_SaveResult\fR, \fBTcl_RestoreResult\fR, and \fBTcl_DiscardResult\fR are
deprecated.  Instead use \fBTcl_SaveInterpState\fR,
\fBTcl_RestoreInterpState\fR, and \fBTcl_DiscardInterpState\fR, which are more
capable.
.PP
\fBTcl_SaveResult\fR moves the result of \fIinterp\fR to the location
\fIstatePtr\fR points to and returns the interpreter result to its initial
state.  It does not save options such as \fB\-errorcode\fR or
\fB\-errorinfo\fR.
.PP
\fBTcl_RestoreResult\fR clears any existing result or error in \fIinterp\fR and
moves the result from \fIstatePtr\fR back to \fIinterp\fR.  \fIstatePtr\fR is
then in an undefined state and must not be used until passed again to
\fBTcl_SaveResult\fR.
.PP
\fBTcl_DiscardResult\fR releases the state stored at \fBstatePtr\fR, which is
then in an undefined state and must not be used until passed again to
\fBTcl_SaveResult\fR.
.PP
If a saved result is not restored, \fBTcl_DiscardResult\fR must be called to
release it.
.SH KEYWORDS
result, state, interp

Changes to doc/SetChanErr.3.

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
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







-


-


-


-

-
+









-
+






-
+





-
+







'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
Tcl_SetChannelError, Tcl_SetChannelErrorInterp, Tcl_GetChannelError, Tcl_GetChannelErrorInterp \- functions to create/intercept Tcl errors by channel drivers.
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
void
\fBTcl_SetChannelError\fR(\fIchan, msg\fR)
.sp
void
\fBTcl_SetChannelErrorInterp\fR(\fIinterp, msg\fR)
.sp
void
\fBTcl_GetChannelError\fR(\fIchan, msgPtr\fR)
.sp
void
\fBTcl_GetChannelErrorInterp\fR(\fIinterp, msgPtr\fR)
.sp
.fi
.SH ARGUMENTS
.AS Tcl_Channel chan
.AP Tcl_Channel chan in
Refers to the Tcl channel whose bypass area is accessed.
.AP Tcl_Interp* interp in
Refers to the Tcl interpreter whose bypass area is accessed.
.AP Tcl_Obj* msg in
Error message put into a bypass area. A list of return options and values,
followed by a string message. Both message and the option/value information
are optional.
are optional. This \fImust\fR be a well-formed list.
.AP Tcl_Obj** msgPtr out
Reference to a place where the message stored in the accessed bypass area can
be stored in.
.BE
.SH DESCRIPTION
.PP
The current definition of a Tcl channel driver does not permit the direct
The standard definition of a Tcl channel driver does not permit the direct
return of arbitrary error messages, except for the setting and retrieval of
channel options. All other functions are restricted to POSIX error codes.
.PP
The functions described here overcome this limitation. Channel drivers are
allowed to use \fBTcl_SetChannelError\fR and \fBTcl_SetChannelErrorInterp\fR
to place arbitrary error messages in \fBbypass areas\fR defined for channels
to place arbitrary error messages in \fIbypass areas\fR defined for channels
and interpreters. And the generic I/O layer uses \fBTcl_GetChannelError\fR and
\fBTcl_GetChannelErrorInterp\fR to look for messages in the bypass areas and
arrange for their return as errors. The POSIX error codes set by a driver are
used now if and only if no messages are present.
.PP
\fBTcl_SetChannelError\fR stores error information in the bypass area of the
specified channel. The number of references to the \fBmsg\fR value goes up by
126
127
128
129
130
131
132









133
134
135
136
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141







+
+
+
+
+
+
+
+
+




.PP
All other API functions are unchanged. In particular, the functions below
leave all their error information in the interpreter result.
.DS
.ta 1.9i 4i
\fBTcl_Close\fR	\fBTcl_UnstackChannel\fR	\fBTcl_UnregisterChannel\fR
.DE
.SH "REFERENCE COUNT MANAGEMENT"
.PP
The \fImsg\fR argument to \fBTcl_SetChannelError\fR and
\fBTcl_SetChannelErrorInterp\fR, if not NULL, may have any reference count;
these functions will copy.
.PP
\fBTcl_GetChannelError\fR and \fBTcl_GetChannelErrorInterp\fR write a value
reference into their \fImsgPtr\fR, but do not manipulate its reference count.
The reference count will be at least 1 (unless the reference is NULL).
.SH "SEE ALSO"
Tcl_Close(3), Tcl_OpenFileChannel(3), Tcl_SetErrno(3)
.SH KEYWORDS
channel driver, error messages, channel type

Changes to doc/SetErrno.3.

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
30
31



32
33
34
35
36
37
38
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44










-
+
















+
+
+




+
+
+







'\"
'\" Copyright (c) 1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_SetErrno 3 8.3 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_SetErrno, Tcl_GetErrno, Tcl_ErrnoId, Tcl_ErrnoMsg \- manipulate errno to store and retrieve error codes
Tcl_SetErrno, Tcl_GetErrno, Tcl_ErrnoId, Tcl_ErrnoMsg, Tcl_WinConvertError \- manipulate errno to store and retrieve error codes
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
void
\fBTcl_SetErrno\fR(\fIerrorCode\fR)
.sp
int
\fBTcl_GetErrno\fR()
.sp
const char *
\fBTcl_ErrnoId\fR()
.sp
const char *
\fBTcl_ErrnoMsg\fR(\fIerrorCode\fR)
.sp
void
\fBTcl_WinConvertError\fR(\fIwinErrorCode\fR)
.fi
.SH ARGUMENTS
.AS int errorCode
.AP int errorCode in
A POSIX error code such as \fBENOENT\fR.
.AS unsigned int winErrorCode in
.AP DWORD winErrorCode in
A Windows or Winsock error code such as \fBERROR_FILE_NOT_FOUND\fR.
.BE

.SH DESCRIPTION
.PP
\fBTcl_SetErrno\fR and \fBTcl_GetErrno\fR provide portable access
to the \fBerrno\fR variable, which is used to record a POSIX error
code after system calls and other operations such as \fBTcl_Gets\fR.
57
58
59
60
61
62
63



64
65
66
63
64
65
66
67
68
69
70
71
72
73
74
75







+
+
+



\fBTcl_ErrnoMsg\fR returns a human-readable string such as
.QW "permission denied"
that corresponds to the value of its
\fIerrorCode\fR argument.  The \fIerrorCode\fR argument is
typically the value returned by \fBTcl_GetErrno\fR.
The strings returned by these functions are
statically allocated and the caller must not free or modify them.
.PP
\fBTcl_WinConvertError\fR (Windows only) maps the passed Windows or Winsock
error code to a POSIX error and stores it in \fBerrno\fR.

.SH KEYWORDS
errno, error code, global variables

Changes to doc/SetRecLmt.3.

10
11
12
13
14
15
16
17

18

19
20
21
22
23
24

25
26
27
28
29
30
31
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32







-
+

+





-
+







.BS
.SH NAME
Tcl_SetRecursionLimit \- set maximum allowable nesting depth in interpreter
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
Tcl_Size
\fBTcl_SetRecursionLimit\fR(\fIinterp, depth\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Interpreter whose recursion limit is to be set.
Must be greater than zero.
.AP int depth in
.AP Tcl_Size depth in
New limit for nested calls to \fBTcl_Eval\fR for \fIinterp\fR.
.BE

.SH DESCRIPTION
.PP
At any given time Tcl enforces a limit on the number of recursive
calls that may be active for \fBTcl_Eval\fR and related procedures

Changes to doc/SetResult.3.

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
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
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
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







-
+


















-
+






+
















-
-
-







'\"
'\" Copyright (c) 1989-1993 The Regents of the University of California.
'\" Copyright (c) 1994-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_SetResult 3 8.7 Tcl "Tcl Library Procedures"
.TH Tcl_SetResult 3 9.0 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_SetObjResult, Tcl_GetObjResult, Tcl_SetResult, Tcl_GetStringResult, Tcl_AppendResult, Tcl_AppendElement, Tcl_ResetResult, Tcl_TransferResult \- manipulate Tcl result
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_SetObjResult\fR(\fIinterp, objPtr\fR)
.sp
Tcl_Obj *
\fBTcl_GetObjResult\fR(\fIinterp\fR)
.sp
\fBTcl_SetResult\fR(\fIinterp, result, freeProc\fR)
.sp
const char *
\fBTcl_GetStringResult\fR(\fIinterp\fR)
.sp
\fBTcl_AppendResult\fR(\fIinterp, result, result, ... , \fB(char *) NULL\fR)
\fBTcl_AppendResult\fR(\fIinterp, result, result, ... , \fB(char *)NULL\fR)
.sp
\fBTcl_ResetResult\fR(\fIinterp\fR)
.sp
\fBTcl_TransferResult\fR(\fIsourceInterp, code, targetInterp\fR)
.sp
\fBTcl_AppendElement\fR(\fIinterp, element\fR)
.fi
.SH ARGUMENTS
.AS Tcl_FreeProc sourceInterp out
.AP Tcl_Interp *interp out
Interpreter whose result is to be modified or read.
.AP Tcl_Obj *objPtr in
Tcl value to become result for \fIinterp\fR.
.AP char *result in
String value to become result for \fIinterp\fR or to be
appended to the existing result.
.AP "const char" *element in
String value to append as a list element
to the existing result of \fIinterp\fR.
.AP Tcl_FreeProc *freeProc in
Address of procedure to call to release storage at
\fIresult\fR, or \fBTCL_STATIC\fR, \fBTCL_DYNAMIC\fR, or
\fBTCL_VOLATILE\fR.
.AP va_list argList in
An argument list which must have been initialized using
\fBva_start\fR, and cleared using \fBva_end\fR.
.AP Tcl_Interp *sourceInterp in
Interpreter that the result and return options should be transferred from.
.AP Tcl_Interp *targetInterp in
Interpreter that the result and return options should be transferred to.
.AP int code in
Return code value that controls transfer of return options.
.BE
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
131
132
133
134
135
136
137

138
139
140
141
142
143
144
145







-
+







\fBTcl_AppendResult\fR takes care of all the
storage management issues associated with managing \fIinterp\fR's
result, such as allocating a larger result area if necessary.
It also manages conversion to and from the \fIresult\fR field of the
\fIinterp\fR so as to handle backward-compatibility with old-style
extensions.
Any number of \fIresult\fR arguments may be passed in a single
call; the last argument in the list must be a NULL pointer.
call; the last argument in the list must be (char *)NULL.
.PP
\fBTcl_TransferResult\fR transfers interpreter state from \fIsourceInterp\fR
to \fItargetInterp\fR. The two interpreters must have been created in the
same thread.  If \fIsourceInterp\fR and \fItargetInterp\fR are the same,
nothing is done. Otherwise, \fBTcl_TransferResult\fR moves the result
from \fIsourceInterp\fR to \fItargetInterp\fR, and resets the result
in \fIsourceInterp\fR. It also moves the return options dictionary as
205
206
207
208
209
210
211
212

213
214
215
216



























217
218
219
220
221
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







-
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





This allows applications to use non-standard storage allocators.
When Tcl no longer needs the storage for the string, it will
call \fIfreeProc\fR. \fIFreeProc\fR should have arguments and
result that match the type \fBTcl_FreeProc\fR:
.PP
.CS
typedef void \fBTcl_FreeProc\fR(
        char *\fIblockPtr\fR);
        void *\fIblockPtr\fR);
.CE
.PP
When \fIfreeProc\fR is called, its \fIblockPtr\fR will be set to
the value of \fIresult\fR passed to \fBTcl_SetResult\fR.

.SH "REFERENCE COUNT MANAGEMENT"
.PP
The interpreter result is one of the main places that owns references to
values, along with the bytecode execution stack, argument lists, variables,
and the list and dictionary collection values.
.PP
\fBTcl_SetObjResult\fR takes a value with an arbitrary reference count
\fI(specifically including zero)\fR and guarantees to increment the reference
count. If code wishes to continue using the value after setting it as the
result, it should add its own reference to it with \fBTcl_IncrRefCount\fR.
.PP
\fBTcl_GetObjResult\fR returns the current interpreter result value. This will
have a reference count of at least 1. If the caller wishes to keep the
interpreter result value, it should increment its reference count.
.PP
\fBTcl_GetStringResult\fR does not manipulate reference counts, but the string
it returns is owned by (and has a lifetime controlled by) the current
interpreter result value; it should be copied instead of being relied upon to
persist after the next Tcl API call, as most Tcl operations can modify the
interpreter result.
.PP
\fBTcl_SetResult\fR, \fBTcl_AppendResult\fR,
\fBTcl_AppendElement\fR, and \fBTcl_ResetResult\fR all modify the interpreter
result. They may cause the old interpreter result to have its reference count
decremented and a new interpreter result to be allocated. After they have been
called, the reference count of the interpreter result is guaranteed to be 1.
.SH "SEE ALSO"
Tcl_AddErrorInfo, Tcl_CreateObjCommand, Tcl_SetErrorCode, Tcl_Interp,
Tcl_GetReturnOptions
.SH KEYWORDS
append, command, element, list, value, result, return value, interpreter

Changes to doc/SetVar.3.

39
40
41
42
43
44
45

46
47
48
49
50
51
52
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53







+







\fBTcl_ObjGetVar2\fR(\fIinterp, part1Ptr, part2Ptr, flags\fR)
.sp
int
\fBTcl_UnsetVar\fR(\fIinterp, varName, flags\fR)
.sp
int
\fBTcl_UnsetVar2\fR(\fIinterp, name1, name2, flags\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp *newValuePtr
.AP Tcl_Interp *interp in
Interpreter containing variable.
.AP "const char" *name1 in
Contains the name of an array variable (if \fIname2\fR is non-NULL)
or (if \fIname2\fR is NULL) either the name of a scalar variable
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
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







+












+






+








+






+







element variable name).
.PP
The \fIflags\fR argument may be used to specify any of several
options to the procedures.
It consists of an OR-ed combination of the following bits.
.TP
\fBTCL_GLOBAL_ONLY\fR
.
Under normal circumstances the procedures look up variables as follows.
If a procedure call is active in \fIinterp\fR,
the variable is looked up at the current level of procedure call.
Otherwise, the variable is looked up first in the current namespace,
then in the global namespace.
However, if this bit is set in \fIflags\fR then the variable
is looked up only in the global namespace
even if there is a procedure call active.
If both \fBTCL_GLOBAL_ONLY\fR and \fBTCL_NAMESPACE_ONLY\fR are given,
\fBTCL_GLOBAL_ONLY\fR is ignored.
.TP
\fBTCL_NAMESPACE_ONLY\fR
.
If this bit is set in \fIflags\fR then the variable
is looked up only in the current namespace; if a procedure is active
its variables are ignored, and the global namespace is also ignored unless
it is the current namespace.
.TP
\fBTCL_LEAVE_ERR_MSG\fR
.
If an error is returned and this bit is set in \fIflags\fR, then
an error message will be left in the interpreter's result,
where it can be retrieved with \fBTcl_GetObjResult\fR
or \fBTcl_GetStringResult\fR.
If this flag bit is not set then no error message is left
and the interpreter's result will not be modified.
.TP
\fBTCL_APPEND_VALUE\fR
.
If this bit is set then \fInewValuePtr\fR or \fInewValue\fR is
appended to the current value instead of replacing it.
If the variable is currently undefined, then the bit is ignored.
This bit is only used by the \fBTcl_Set*\fR procedures.
.TP
\fBTCL_LIST_ELEMENT\fR
.
If this bit is set, then \fInewValue\fR is converted to a valid
Tcl list element before setting (or appending to) the variable.
A separator space is appended before the new list element unless
the list element is going to be the first element in a list or
sublist (i.e. the variable's current value is empty, or contains
the single character
.QW { ,
238
239
240
241
242
243
244





















245
246
247
248
249
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





If the variable cannot be removed because it does not exist then
\fBTCL_ERROR\fR is returned.
If an array element is specified, the given element is removed
but the array remains.
If an array name is specified without an index, then the entire
array is removed.

.SH "REFERENCE COUNT MANAGEMENT"
.PP
The result of \fBTcl_SetVar2Ex\fR, \fBTcl_ObjSetVar2\fR, \fBTcl_GetVar2Ex\fR,
and \fBTcl_ObjGetVar2\fR is (if non-NULL) a value with a reference of at least
1, where that reference is held by the variable that the function has just
operated upon.
.PP
The \fInewValuePtr\fR argument to \fBTcl_SetVar2Ex\fR and \fBTcl_ObjSetVar2\fR
may be an arbitrary reference count value.  Its reference count is
incremented on success.  On failure, if its reference count is zero, it is
decremented and freed so the caller need do nothing with it.
.PP
The \fIpart1Ptr\fR argument to \fBTcl_ObjSetVar2\fR and \fBTcl_ObjGetVar2\fR can
have any reference count.  These functions never modify it.
.PP
The \fIpart2Ptr\fR argument to \fBTcl_ObjSetVar2\fR and \fBTcl_ObjGetVar2\fR, if
non-NULL, should not have a zero reference count as these functions may
retain a reference to it, particularly when it is used to create an array
element that did not previously exist, and decrementing the reference count
later would leave them pointing to a freed Tcl_Obj.

.SH "SEE ALSO"
Tcl_GetObjResult, Tcl_GetStringResult, Tcl_TraceVar

.SH KEYWORDS
array, get variable, interpreter, scalar, set, unset, value, variable

Changes to doc/Signal.3.

14
15
16
17
18
19
20
21

22
23
24
25
26
27
28
14
15
16
17
18
19
20

21
22
23
24
25
26
27
28







-
+







\fB#include <tcl.h>\fR
.sp
const char *
\fBTcl_SignalId\fR(\fIsig\fR)
.sp
const char *
\fBTcl_SignalMsg\fR(\fIsig\fR)
.sp
.fi
.SH ARGUMENTS
.AS int sig
.AP int sig in
A POSIX signal number such as \fBSIGPIPE\fR.
.BE

.SH DESCRIPTION

Changes to doc/Sleep.3.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25







+







.SH NAME
Tcl_Sleep \- delay execution for a given number of milliseconds
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_Sleep\fR(\fIms\fR)
.fi
.SH ARGUMENTS
.AS int ms
.AP int ms in
Number of milliseconds to sleep.
.BE
.SH DESCRIPTION
.PP

Changes to doc/SourceRCFile.3.

1
2

3
4
5
6
7
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
1

2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22

-
+











-

+







'\"
'\" Copyright (c) 1998-2000 by Scriptics Corporation.
'\" Copyright (c) 1998-2000 Scriptics Corporation.
'\" All rights reserved.
'\"
.TH Tcl_SourceRCFile 3 8.3 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_SourceRCFile \- source the Tcl rc file
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
void
\fBTcl_SourceRCFile\fR(\fIinterp\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Tcl interpreter to source rc file into.
.BE

.SH DESCRIPTION

Changes to doc/SplitList.3.

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
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







-
+


-
+


-
+


-
+

+





-
+

-
+

+
+
+
+
+





-
+









-
+







.sp
int
\fBTcl_SplitList\fR(\fIinterp, list, argcPtr, argvPtr\fR)
.sp
char *
\fBTcl_Merge\fR(\fIargc, argv\fR)
.sp
size_t
Tcl_Size
\fBTcl_ScanElement\fR(\fIsrc, flagsPtr\fR)
.sp
size_t
Tcl_Size
\fBTcl_ScanCountedElement\fR(\fIsrc, length, flagsPtr\fR)
.sp
size_t
Tcl_Size
\fBTcl_ConvertElement\fR(\fIsrc, dst, flags\fR)
.sp
size_t
Tcl_Size
\fBTcl_ConvertCountedElement\fR(\fIsrc, length, dst, flags\fR)
.fi
.SH ARGUMENTS
.AS "const char *const" ***argvPtr out
.AP Tcl_Interp *interp out
Interpreter to use for error reporting.  If NULL, then no error message
is left.
.AP char *list in
.AP "const char" *list in
Pointer to a string with proper list structure.
.AP int *argcPtr out
.AP "Tcl_Size \&| int" *argcPtr out
Filled in with number of elements in \fIlist\fR.
May be (Tcl_Size *)NULL when not used. If it points to a variable which
type is not \fBTcl_Size\fR, a compiler warning will be generated.
If your extensions is compiled with -DTCL_8_API, this function will return
TCL_ERROR for lists with more than INT_MAX elements (which should
trigger proper error-handling), otherwise expect it to crash.
.AP "const char" ***argvPtr out
\fI*argvPtr\fR will be filled in with the address of an array of
pointers to the strings that are the extracted elements of \fIlist\fR.
There will be \fI*argcPtr\fR valid entries in the array, followed by
a NULL entry.
.AP int argc in
.AP Tcl_Size argc in
Number of elements in \fIargv\fR.
.AP "const char *const" *argv in
Array of strings to merge together into a single list.
Each string will become a separate element of the list.
.AP "const char" *src in
String that is to become an element of a list.
.AP int *flagsPtr in
Pointer to word to fill in with information about \fIsrc\fR.
The value of *\fIflagsPtr\fR must be passed to \fBTcl_ConvertElement\fR.
.AP size_t length in
.AP Tcl_Size length in
Number of bytes in string \fIsrc\fR.
.AP char *dst in
Place to copy converted list element.  Must contain enough characters
to hold converted string.
.AP int flags in
Information about \fIsrc\fR. Must be value returned by previous
call to \fBTcl_ScanElement\fR, possibly OR-ed
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
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







+
-
+










-
+



-
-
+
+
+







addition to the array of pointers, it
also holds copies of all the list elements.  It is the caller's
responsibility to free up all of this storage.
For example, suppose that you have called \fBTcl_SplitList\fR with
the following code:
.PP
.CS
Tcl_Size argc;
int argc, code;
int code;
char *string;
char **argv;
\&...
code = \fBTcl_SplitList\fR(interp, string, &argc, &argv);
.CE
.PP
Then you should eventually free the storage with a call like the
following:
.PP
.CS
Tcl_Free((char *) argv);
Tcl_Free(argv);
.CE
.PP
\fBTcl_SplitList\fR normally returns \fBTCL_OK\fR, which means the list was
successfully parsed.
If there was a syntax error in \fIlist\fR, then \fBTCL_ERROR\fR is returned
successfully parsed. If \fIsizePtr\fR points to a variable of type
\fBint\fR and the list contains more than 2**31 key/value pairs, or there was
a syntax error in \fIlist\fR, then \fBTCL_ERROR\fR is returned
and the interpreter's result will point to an error message describing the
problem (if \fIinterp\fR was not NULL).
If \fBTCL_ERROR\fR is returned then no memory is allocated and \fI*argvPtr\fR
is not modified.
.PP
\fBTcl_Merge\fR is the inverse of \fBTcl_SplitList\fR:  it
takes a collection of strings given by \fIargc\fR

Changes to doc/SplitPath.3.

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
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







+





-
+

+
+
+
+
+





-
+







\fBTcl_SplitPath\fR(\fIpath, argcPtr, argvPtr\fR)
.sp
char *
\fBTcl_JoinPath\fR(\fIargc, argv, resultPtr\fR)
.sp
Tcl_PathType
\fBTcl_GetPathType\fR(\fIpath\fR)
.fi
.SH ARGUMENTS
.AS "const char *const" ***argvPtr in/out
.AP "const char" *path in
File path in a form appropriate for the current platform (see the
\fBfilename\fR manual entry for acceptable forms for path names).
.AP int *argcPtr out
.AP "Tcl_Size \&| int" *argcPtr out
Filled in with number of path elements in \fIpath\fR.
May be (Tcl_Size *)NULL when not used. If it points to a variable which
type is not \fBTcl_Size\fR, a compiler warning will be generated.
If your extensions is compiled with -DTCL_8_API, argcPtr will be filled
with -1 for paths with more than INT_MAX elements (which should
trigger proper error-handling), otherwise expect it to crash.
.AP "const char" ***argvPtr out
\fI*argvPtr\fR will be filled in with the address of an array of
pointers to the strings that are the extracted elements of \fIpath\fR.
There will be \fI*argcPtr\fR valid entries in the array, followed by
a NULL entry.
.AP int argc in
.AP Tcl_Size argc in
Number of elements in \fIargv\fR.
.AP "const char *const" *argv in
Array of path elements to merge together into a single path.
.AP Tcl_DString *resultPtr in/out
A pointer to an initialized \fBTcl_DString\fR to which the result of
\fBTcl_JoinPath\fR will be appended.
.BE
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
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







-
+










-
+







dynamically allocated; in addition to the array of pointers, it also
holds copies of all the path elements.  It is the caller's
responsibility to free all of this storage.
For example, suppose that you have called \fBTcl_SplitPath\fR with the
following code:
.PP
.CS
int argc;
Tcl_Size argc;
char *path;
char **argv;
\&...
Tcl_SplitPath(string, &argc, &argv);
.CE
.PP
Then you should eventually free the storage with a call like the
following:
.PP
.CS
Tcl_Free((char *) argv);
Tcl_Free(argv);
.CE
.PP
\fBTcl_JoinPath\fR is the inverse of \fBTcl_SplitPath\fR: it takes a
collection of path elements given by \fIargc\fR and \fIargv\fR and
generates a result string that is a properly constructed path. The
result string is appended to \fIresultPtr\fR.  \fIResultPtr\fR must
refer to an initialized \fBTcl_DString\fR.

Added doc/StaticLibrary.3.















































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
'\"
'\" Copyright (c) 1995-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_StaticLibrary 3 7.5 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_StaticLibrary, Tcl_StaticPackage \- make a statically linked library available via the 'load' command
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_StaticLibrary\fR(\fIinterp, prefix, initProc, safeInitProc\fR)
.sp
\fBTcl_StaticPackage\fR(\fIinterp, prefix, initProc, safeInitProc\fR)
.fi
.SH ARGUMENTS
.AS Tcl_LibraryInitProc *safeInitProc
.AP Tcl_Interp *interp in
If not NULL, points to an interpreter into which the library has
already been incorporated (i.e., the caller has already invoked the
appropriate initialization procedure).  NULL means the library
has not yet been incorporated into any interpreter.
.AP "const char" *prefix in
Prefix for library initialization function. Normally in titlecase (first
letter upper-case, all others lower-case), but this is no longer required.
.AP Tcl_LibraryInitProc *initProc in
Procedure to invoke to incorporate this library into a trusted
interpreter.
.AP Tcl_LibraryInitProc *safeInitProc in
Procedure to call to incorporate this library into a safe interpreter
(one that will execute untrusted scripts).  NULL means the library
cannot be used in safe interpreters.
.BE
.SH DESCRIPTION
.PP
This procedure may be invoked to announce that a library has been
linked statically with a Tcl application and, optionally, that it
has already been incorporated into an interpreter.
Once \fBTcl_StaticLibrary\fR has been invoked for a library, it
may be incorporated into interpreters using the \fBload\fR command.
\fBTcl_StaticLibrary\fR is normally invoked only by the \fBTcl_AppInit\fR
procedure for the application, not by libraries for themselves
(\fBTcl_StaticLibrary\fR should only be invoked for statically
linked libraries, and code in the library itself should not need
to know whether the library is dynamically loaded or statically linked).
.PP
When the \fBload\fR command is used later to incorporate the library into
an interpreter, one of \fIinitProc\fR and \fIsafeInitProc\fR will
be invoked, depending on whether the target interpreter is safe
or not.
\fIinitProc\fR and \fIsafeInitProc\fR must both match the
following prototype:
.PP
.CS
typedef int \fBTcl_LibraryInitProc\fR(
        Tcl_Interp *\fIinterp\fR);
.CE
.PP
The \fIinterp\fR argument identifies the interpreter in which the library
is to be incorporated.  The initialization procedure must return \fBTCL_OK\fR or
\fBTCL_ERROR\fR to indicate whether or not it completed successfully; in
the event of an error it should set the interpreter's result to point to an
error message.  The result or error from the initialization procedure will
be returned as the result of the \fBload\fR command that caused the
initialization procedure to be invoked.
.PP
\fBTcl_StaticLibrary\fR was named \fBTcl_StaticPackage\fR in Tcl 8.6 and
earlier, but the old name is deprecated now.
.PP
\fBTcl_StaticLibrary\fR can not be used in stub-enabled extensions.
.SH KEYWORDS
initialization procedure, package, static linking
.SH "SEE ALSO"
load(n), package(n), Tcl_PkgRequire(3)

Deleted doc/StaticPkg.3.

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
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









































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
'\"
'\" Copyright (c) 1995-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_StaticPackage 3 7.5 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_StaticPackage \- make a statically linked package available via the 'load' command
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_StaticPackage\fR(\fIinterp, pkgName, initProc, safeInitProc\fR)
.SH ARGUMENTS
.AS Tcl_PackageInitProc *safeInitProc
.AP Tcl_Interp *interp in
If not NULL, points to an interpreter into which the package has
already been loaded (i.e., the caller has already invoked the
appropriate initialization procedure).  NULL means the package
has not yet been incorporated into any interpreter.
.AP "const char" *pkgName in
Name of the package;  should be properly capitalized (first letter
upper-case, all others lower-case).
.AP Tcl_PackageInitProc *initProc in
Procedure to invoke to incorporate this package into a trusted
interpreter.
.AP Tcl_PackageInitProc *safeInitProc in
Procedure to call to incorporate this package into a safe interpreter
(one that will execute untrusted scripts).  NULL means the package
cannot be used in safe interpreters.
.BE
.SH DESCRIPTION
.PP
This procedure may be invoked to announce that a package has been
linked statically with a Tcl application and, optionally, that it
has already been loaded into an interpreter.
Once \fBTcl_StaticPackage\fR has been invoked for a package, it
may be loaded into interpreters using the \fBload\fR command.
\fBTcl_StaticPackage\fR is normally invoked only by the \fBTcl_AppInit\fR
procedure for the application, not by packages for themselves
(\fBTcl_StaticPackage\fR should only be invoked for statically
loaded packages, and code in the package itself should not need
to know whether the package is dynamically or statically loaded).
.PP
When the \fBload\fR command is used later to load the package into
an interpreter, one of \fIinitProc\fR and \fIsafeInitProc\fR will
be invoked, depending on whether the target interpreter is safe
or not.
\fIinitProc\fR and \fIsafeInitProc\fR must both match the
following prototype:
.PP
.CS
typedef int \fBTcl_PackageInitProc\fR(
        Tcl_Interp *\fIinterp\fR);
.CE
.PP
The \fIinterp\fR argument identifies the interpreter in which the package
is to be loaded.  The initialization procedure must return \fBTCL_OK\fR or
\fBTCL_ERROR\fR to indicate whether or not it completed successfully; in
the event of an error it should set the interpreter's result to point to an
error message.  The result or error from the initialization procedure will
be returned as the result of the \fBload\fR command that caused the
initialization procedure to be invoked.
.PP
\fBTcl_StaticPackage\fR can not be safely used by stub-enabled extensions,
so its symbol is not included in the stub table.
.SH KEYWORDS
initialization procedure, package, static linking
.SH "SEE ALSO"
load(n), package(n), Tcl_PkgRequire(3)

Changes to doc/StdChannels.3.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







'\"
'\" Copyright (c) 2001 by ActiveState Corporation
'\" Copyright (c) 2001 ActiveState Corporation
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH "Standard Channels" 3 7.5 Tcl "Tcl Library Procedures"
.so man.macros
.BS
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
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







-
-
+








-
-
+



-
-
+


-
-
+










-
-
+







.PP
These cases differ in how they handle unavailable platform- specific
standard channels.  (A channel is not
.QW available
if it could not be
successfully opened; for example, in a Tcl application run as a
Windows NT service.)
.TP
1)
.IP 1)
A single standard channel is initialized when it is explicitly
specified in a call to \fBTcl_SetStdChannel\fR.  The states of the
other standard channels are unaffected.
.RS
.PP
Missing platform-specific standard channels do not matter here. This
approach is not available at the script level.
.RE
.TP
2)
.IP 2)
All uninitialized standard channels are initialized to
platform-specific default values:
.RS
.TP
(a)
.IP (a)
when open channels are listed with \fBTcl_GetChannelNames\fR (or the
\fBfile channels\fR script command), or
.TP
(b)
.IP (b)
when information about any standard channel is requested with a call
to \fBTcl_GetStdChannel\fR, or with a call to \fBTcl_GetChannel\fR
which specifies one of the standard names (\fBstdin\fR, \fBstdout\fR
and \fBstderr\fR).
.PP
In case of missing platform-specific standard channels, the Tcl
standard channels are considered as initialized and then immediately
closed. This means that the first three Tcl channels then opened by
the application are designated as the Tcl standard channels.
.RE
.TP
3)
.IP 3)
All uninitialized standard channels are initialized to
platform-specific default values when a user-requested channel is
registered with \fBTcl_RegisterChannel\fR.
.PP
In case of unavailable platform-specific standard channels the channel
whose creation caused the initialization of the Tcl standard channels
is made a normal channel.  The next three Tcl channels opened by the

Changes to doc/StrMatch.3.

15
16
17
18
19
20
21

22
23
24
25
26
27
28
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29







+







\fB#include <tcl.h>\fR
.sp
int
\fBTcl_StringMatch\fR(\fIstr\fR, \fIpattern\fR)
.sp
int
\fBTcl_StringCaseMatch\fR(\fIstr\fR, \fIpattern\fR, \fIflags\fR)
.fi
.SH ARGUMENTS
.AS "const char" *pattern
.AP "const char" *str in
String to test.
.AP "const char" *pattern in
Pattern to match against string.  May contain special
characters from the set *?\e[].

Changes to doc/StringObj.3.

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
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







-
+















-
+







.sp
Tcl_UniChar *
\fBTcl_GetUnicode\fR(\fIobjPtr\fR)
.sp
int
\fBTcl_GetUniChar\fR(\fIobjPtr, index\fR)
.sp
int
Tcl_Size
\fBTcl_GetCharLength\fR(\fIobjPtr\fR)
.sp
Tcl_Obj *
\fBTcl_GetRange\fR(\fIobjPtr, first, last\fR)
.sp
void
\fBTcl_AppendToObj\fR(\fIobjPtr, bytes, length\fR)
.sp
void
\fBTcl_AppendUnicodeToObj\fR(\fIobjPtr, unicode, numChars\fR)
.sp
void
\fBTcl_AppendObjToObj\fR(\fIobjPtr, appendObjPtr\fR)
.sp
void
\fBTcl_AppendStringsToObj\fR(\fIobjPtr, string, string, ... \fB(char *) NULL\fR)
\fBTcl_AppendStringsToObj\fR(\fIobjPtr, string, string, ... \fB(char *)NULL\fR)
.sp
void
\fBTcl_AppendLimitedToObj\fR(\fIobjPtr, bytes, length, limit, ellipsis\fR)
.sp
Tcl_Obj *
\fBTcl_Format\fR(\fIinterp, format, objc, objv\fR)
.sp
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
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







+






-
+



-
+


-
+





-
+


-
-
+
+

-
+

-
-
+
+
+

-
+
+

-
+


-
-
-
+
+
+
+
+
+
+
+


-
-
-
-
+








-
+



-
+







\fBTcl_SetObjLength\fR(\fIobjPtr, newLength\fR)
.sp
int
\fBTcl_AttemptSetObjLength\fR(\fIobjPtr, newLength\fR)
.sp
Tcl_Obj *
\fBTcl_ConcatObj\fR(\fIobjc, objv\fR)
.fi
.SH ARGUMENTS
.AS "const Tcl_UniChar" *appendObjPtr in/out
.AP "const char" *bytes in
Points to the first byte of an array of UTF-8-encoded bytes
used to set or append to a string value.
This byte array may contain embedded null characters
unless \fInumChars\fR is TCL_INDEX_NONE.  (Applications needing null bytes
unless \fInumChars\fR is negative.  (Applications needing null bytes
should represent them as the two-byte sequence \fI\e300\e200\fR, use
\fBTcl_ExternalToUtf\fR to convert, or \fBTcl_NewByteArrayObj\fR if
the string is a collection of uninterpreted bytes.)
.AP size_t length in
.AP Tcl_Size length in
The number of bytes to copy from \fIbytes\fR when
initializing, setting, or appending to a string value.
If TCL_INDEX_NONE, all bytes up to the first null are used.
If negative, all bytes up to the first null are used.
.AP "const Tcl_UniChar" *unicode in
Points to the first byte of an array of Unicode characters
used to set or append to a string value.
This byte array may contain embedded null characters
unless \fInumChars\fR is negative.
.AP size_t numChars in
.AP Tcl_Size numChars in
The number of Unicode characters to copy from \fIunicode\fR when
initializing, setting, or appending to a string value.
If TCL_INDEX_NONE, all characters up to the first null character are used.
.AP size_t index in
If negative, all characters up to the first null character are used.
.AP Tcl_Size index in
The index of the Unicode character to return.
.AP size_t first in
.AP Tcl_Size first in
The index of the first Unicode character in the Unicode range to be
returned as a new value.
.AP size_t last in
returned as a new value. If negative, behave the same as if the
value was 0.
.AP Tcl_Size last in
The index of the last Unicode character in the Unicode range to be
returned as a new value.
returned as a new value. If negative, take all characters up to
the last one available.
.AP Tcl_Obj *objPtr in/out
Points to a value to manipulate.
A pointer to a value to read, or to an unshared value to modify.
.AP Tcl_Obj *appendObjPtr in
The value to append to \fIobjPtr\fR in \fBTcl_AppendObjToObj\fR.
.AP int *lengthPtr out
If non-NULL, the location where \fBTcl_GetStringFromObj\fR will store
the length of a value's string representation.
.AP "Tcl_Size \&| int" *lengthPtr out
The location where \fBTcl_GetStringFromObj\fR will store the length
of a value's string representation.
May be (Tcl_Size *)NULL when not used. If it points to a variable which
type is not \fBTcl_Size\fR, a compiler warning will be generated.
If your extensions is compiled with -DTCL_8_API, this function will
panic for strings with more than INT_MAX bytes/characters, otherwise
expect it to crash.
.AP "const char" *string in
Null-terminated string value to append to \fIobjPtr\fR.
.AP va_list argList in
An argument list which must have been initialized using
\fBva_start\fR, and cleared using \fBva_end\fR.
.AP size_t limit in
.AP Tcl_Size limit in
Maximum number of bytes to be appended.
.AP "const char" *ellipsis in
Suffix to append when the limit leads to string truncation.
If NULL is passed then the suffix
.QW "..."
is used.
.AP "const char" *format in
Format control string including % conversion specifiers.
.AP int objc in
.AP Tcl_Size objc in
The number of elements to format or concatenate.
.AP Tcl_Obj *objv[] in
The array of values to format or concatenate.
.AP size_t newLength in
.AP Tcl_Size newLength in
New length for the string value of \fIobjPtr\fR, not including the
final null character.
.BE
.SH DESCRIPTION
.PP
The procedures described in this manual entry allow Tcl values to
be manipulated as string values.  They use the internal representation
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
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







-
-
+
+


-
-
-
-
+
+
+
+
+
+







-
+





+
+




















-
+













-
+







\fIlengthPtr\fR if it is non-NULL.  The storage referenced by the returned
byte pointer is owned by the value manager and should not be modified by
the caller.  The procedure \fBTcl_GetUnicode\fR is used in the common case
where the caller does not need the length of the unicode string
representation.
.PP
\fBTcl_GetUniChar\fR returns the \fIindex\fR'th character in the
value's Unicode representation. If the index is out of range or
it references a low surrogate preceded by a high surrogate, it returns -1;
value's Unicode representation. If the index is out of range
it returns -1;
.PP
\fBTcl_GetRange\fR returns a newly created value comprised of the
characters between \fIfirst\fR and \fIlast\fR (inclusive) in the
value's Unicode representation.  If the value's Unicode
representation is invalid, the Unicode representation is regenerated
from the value's string representation.
characters between \fIfirst\fR and \fIlast\fR (inclusive) in the value's
Unicode representation.  If the value's Unicode representation
is invalid, the Unicode representation is regenerated from the value's
string representation.  If \fIfirst\fR is negative, then the returned
string starts at the beginning of the value. If \fIlast\fR negative,
then the returned string ends at the end of the value.
.PP
\fBTcl_GetCharLength\fR returns the number of characters (as opposed
to bytes) in the string value.
.PP
\fBTcl_AppendToObj\fR appends the data given by \fIbytes\fR and
\fIlength\fR to the string representation of the value specified by
\fIobjPtr\fR.  If the value has an invalid string representation,
then an attempt is made to convert \fIbytes\fR is to the Unicode
then an attempt is made to convert \fIbytes\fR to the Unicode
format.  If the conversion is successful, then the converted form of
\fIbytes\fR is appended to the value's Unicode representation.
Otherwise, the value's Unicode representation is invalidated and
converted to the UTF format, and \fIbytes\fR is appended to the
value's new string representation.
Eventually buffer growth is done by large allocations to optimize
multiple calls.
.PP
\fBTcl_AppendUnicodeToObj\fR appends the Unicode string given by
\fIunicode\fR and \fInumChars\fR to the value specified by
\fIobjPtr\fR.  If the value has an invalid Unicode representation,
then \fIunicode\fR is converted to the UTF format and appended to the
value's string representation.  Appends are optimized to handle
repeated appends relatively efficiently (it over-allocates the string
or Unicode space to avoid repeated reallocations and copies of
value's string value).
.PP
\fBTcl_AppendObjToObj\fR is similar to \fBTcl_AppendToObj\fR, but it
appends the string or Unicode value (whichever exists and is best
suited to be appended to \fIobjPtr\fR) of \fIappendObjPtr\fR to
\fIobjPtr\fR.
.PP
\fBTcl_AppendStringsToObj\fR is similar to \fBTcl_AppendToObj\fR
except that it can be passed more than one value to append and
each value must be a null-terminated string (i.e. none of the
values may contain internal null characters).  Any number of
\fIstring\fR arguments may be provided, but the last argument
must be a NULL pointer to indicate the end of the list.
must be (char *)NULL to indicate the end of the list.
.PP
\fBTcl_AppendLimitedToObj\fR is similar to \fBTcl_AppendToObj\fR
except that it imposes a limit on how many bytes are appended.
This can be handy when the string to be appended might be
very large, but the value being constructed should not be allowed to grow
without bound. A common usage is when constructing an error message, where the
end result should be kept short enough to be read.
Bytes from \fIbytes\fR are appended to \fIobjPtr\fR, but no more
than \fIlimit\fR bytes total are to be appended. If the limit prevents
all \fIlength\fR bytes that are available from being appended, then the
appending is done so that the last bytes appended are from the
string \fIellipsis\fR. This allows for an indication of the truncation
to be left in the string.
When \fIlength\fR is \fB-1\fR, all bytes up to the first zero byte are appended,
When \fIlength\fR is negative, all bytes up to the first zero byte are appended,
subject to the limit. When \fIellipsis\fR is NULL, the default
string \fB...\fR is used. When \fIellipsis\fR is non-NULL, it must point
to a zero-byte-terminated string in Tcl's internal UTF encoding.
The number of bytes appended can be less than the lesser
of \fIlength\fR and \fIlimit\fR when appending fewer
bytes is necessary to append only whole multi-byte characters.
.PP
301
302
303
304
305
306
307
308
309





310
311
312
313
314
315
316
310
311
312
313
314
315
316


317
318
319
320
321
322
323
324
325
326
327
328







-
-
+
+
+
+
+







sprintf(buf, format, ...);
\fBTcl_NewStringObj\fR(buf, -1);
.CE
.PP
but with greater convenience and no need to
determine \fBSOME_SUITABLE_LENGTH\fR. The formatting is done with the same
core formatting engine used by \fBTcl_Format\fR.  This means the set of
supported conversion specifiers is that of the \fBformat\fR command and
not that of the \fBsprintf\fR routine where the two sets differ. When a
supported conversion specifiers is that of the \fBformat\fR command but
the behavior is as similar as possible to \fBsprintf\fR. The "hh" and
(Microsoft-specific) "w" format specifiers are not supported. The "L"
format specifier means that an "mp_int *" argument is expected (or a
"long double" in combination with \fB[aAeEgGaA]\fR). When a
conversion specifier passed to \fBTcl_ObjPrintf\fR includes a precision,
the value is taken as a number of bytes, as \fBsprintf\fR does, and not
as a number of characters, as \fBformat\fR does.  This is done on the
assumption that C code is more likely to know how many bytes it is
passing around than the number of encoded characters those bytes happen
to represent.  The variable number of arguments passed in should be of
the types that would be suitable for passing to \fBsprintf\fR.  Note in
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





array. \fBTcl_ConcatObj\fR eliminates leading and trailing white space
as it copies the string representations of the \fIobjv\fR array to the
result. If an element of the \fIobjv\fR array consists of nothing but
white space, then that value is ignored entirely. This white-space
removal was added to make the output of the \fBconcat\fR command
cleaner-looking. \fBTcl_ConcatObj\fR returns a pointer to a
newly-created value whose ref count is zero.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
\fBTcl_NewStringObj\fR, \fBTcl_NewUnicodeObj\fR, \fBTcl_Format\fR,
\fBTcl_ObjPrintf\fR, and \fBTcl_ConcatObj\fR always return a zero-reference
object, much like \fBTcl_NewObj\fR.
.PP
\fBTcl_GetStringFromObj\fR, \fBTcl_GetString\fR, \fBTcl_GetUnicodeFromObj\fR,
\fBTcl_GetUnicode\fR, \fBTcl_GetUniChar\fR, \fBTcl_GetCharLength\fR, and
\fBTcl_GetRange\fR all only work with an existing value; they do not
manipulate its reference count in any way.
.PP
\fBTcl_SetStringObj\fR, \fBTcl_SetUnicodeObj\fR, \fBTcl_AppendToObj\fR,
\fBTcl_AppendUnicodeToObj\fR, \fBTcl_AppendObjToObj\fR,
\fBTcl_AppendStringsToObj\fR, \fBTcl_AppendStringsToObjVA\fR,
\fBTcl_AppendLimitedToObj\fR, \fBTcl_AppendFormatToObj\fR,
\fBTcl_AppendPrintfToObj\fR, \fBTcl_SetObjLength\fR, and
\fBTcl_AttemptSetObjLength\fR and require their \fIobjPtr\fR to be an unshared
value (i.e, a reference count no more than 1) as they will modify it.
.PP
Additional arguments to the above functions (the \fIappendObjPtr\fR argument
to \fBTcl_AppendObjToObj\fR, values in the \fIobjv\fR argument to
\fBTcl_Format\fR, \fBTcl_AppendFormatToObj\fR, and \fBTcl_ConcatObj\fR) can
have any reference count, but reference counts of zero are not recommended.
.PP
\fBTcl_Format\fR and \fBTcl_AppendFormatToObj\fR may modify the interpreter
result, which involves changing the reference count of a value.

.SH "SEE ALSO"
Tcl_NewObj(3), Tcl_IncrRefCount(3), Tcl_DecrRefCount(3), format(n), sprintf(3)
.SH KEYWORDS
append, internal representation, value, value type, string value,
string type, string representation, concat, concatenate, unicode

Changes to doc/SubstObj.3.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
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







+









-
+







Tcl_SubstObj \- perform substitutions on Tcl values
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Obj *
\fBTcl_SubstObj\fR(\fIinterp, objPtr, flags\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp **termPtr
.AP Tcl_Interp *interp in
Interpreter in which to execute Tcl scripts and lookup variables.  If
an error occurs, the interpreter's result is modified to hold an error
message.
.AP Tcl_Obj *objPtr in
A Tcl value containing the string to perform substitutions on.
.AP int flags in
ORed combination of flag bits that specify which substitutions to
OR'ed combination of flag bits that specify which substitutions to
perform.  The flags \fBTCL_SUBST_COMMANDS\fR,
\fBTCL_SUBST_VARIABLES\fR and \fBTCL_SUBST_BACKSLASHES\fR are
currently supported, and \fBTCL_SUBST_ALL\fR is provided as a
convenience for the common case where all substitutions are desired.
.BE
.SH DESCRIPTION
.PP
58
59
60
61
62
63
64







65
66
67
68
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76







+
+
+
+
+
+
+




empty string is substituted for the command.  Where an uncaught
.QW "break exception"
occurs during the evaluation of a command substitution, the
result of the whole substitution on \fIobjPtr\fR will be truncated at
the point immediately before the start of the command substitution,
and no characters will be added to the result or substitutions
performed after that point.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
The \fIobjPtr\fR argument to \fBTcl_SubstObj\fR must not have a reference
count of zero. This function modifies the interpreter result, both on success
and on failure; the result of this function on success is exactly the current
interpreter result. Successful results should have their reference count
incremented if they are to be retained.
.SH "SEE ALSO"
subst(n)
.SH KEYWORDS
backslash substitution, command substitution, variable substitution

Changes to doc/TCL_MEM_DEBUG.3.

1
2
3


4
5
6
7
8
9
10
1


2
3
4
5
6
7
8
9
10

-
-
+
+







'\"
'\" Copyright (c) 1992-1999 Karl Lehenbauer and Mark Diekhans.
'\" Copyright (c) 2000 by Scriptics Corporation.
'\" Copyright (c) 1992-1999 Karl Lehenbauer & Mark Diekhans.
'\" Copyright (c) 2000 Scriptics Corporation.
'\" All rights reserved.
'\"
.TH TCL_MEM_DEBUG 3 8.1 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
TCL_MEM_DEBUG \- Compile-time flag to enable Tcl memory debugging

Changes to doc/Tcl.n.

151
152
153
154
155
156
157


158
159
160
161
162
163
164
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166







+
+







the following character is treated as an ordinary
character and included in the word.
This allows characters such as double quotes, close brackets,
and dollar signs to be included in words without triggering
special processing.
The following table lists the backslash sequences that are
handled specially, along with the value that replaces each sequence.
.RS
.RS
.RS
.TP 7
\e\fBa\fR
Audible alert (bell) (Unicode U+000007).
.TP 7
\e\fBb\fR
Backspace (Unicode U+000008).
217
218
219
220
221
222
223
224

225
226
227
228
229
230
231
232
233
234
235
236
219
220
221
222
223
224
225

226





227
228
229
230
231
232
233







-
+
-
-
-
-
-







\e\fBU\fIhhhhhhhh\fR
.
The hexadecimal digits \fIhhhhhhhh\fR (one up to eight of them) give a
twenty-one-bit hexadecimal value for the Unicode character that will be
inserted, in the range U+000000\(enU+10FFFF.  The parser will stop just
before this range overflows, or when the maximum of eight digits
is reached.  The upper bits of the Unicode character will be 0.
.RS
.RE
.PP
The range U+00D800\(enU+00DFFF is reserved for surrogates, which
are illegal on its own. Therefore, such sequences will result in
the replacement character U+FFFD. Surrogate pairs should be
encoded as single \e\fBU\fIhhhhhhhh\fR character.
.RE
.PP
Backslash substitution is not performed on words enclosed in braces,
except for backslash-newline as described above.
.RE
.IP "[10] \fBComments.\fR"
If a hash character

Changes to doc/TclZlib.3.

14
15
16
17
18
19
20
21

22
23
24
25
26
27
28
14
15
16
17
18
19
20

21
22
23
24
25
26
27
28







-
+







.nf
#include <tcl.h>
.sp
int
\fBTcl_ZlibDeflate\fR(\fIinterp, format, dataObj, level, dictObj\fR)
.sp
int
\fBTcl_ZlibInflate\fR(\fIinterp, format, dataObj, dictObj\fR)
\fBTcl_ZlibInflate\fR(\fIinterp, format, dataObj, bufferSize, dictObj\fR)
.sp
unsigned int
\fBTcl_ZlibCRC32\fR(\fIinitValue, bytes, length\fR)
.sp
unsigned int
\fBTcl_ZlibAdler32\fR(\fIinitValue, bytes, length\fR)
.sp
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
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







+
+
+



-
+


















-
-
+
+







\fIformat\fR is \fBTCL_ZLIB_FORMAT_GZIP\fR or \fBTCL_ZLIB_FORMAT_AUTO\fR. If
a NULL is passed, a default header will be used on compression and the header
will be ignored (apart from integrity checks) on decompression. See the
section \fBGZIP OPTIONS DICTIONARY\fR for details about the contents of this
dictionary.
.AP "unsigned int" initValue in
The initial value for the checksum algorithm.
.AP "Tcl_Size" bufferSize in
A hint as to what size of buffer is to be used to receive the data.
Use 0 to use a geric guess based on the input data.
.AP "unsigned char" *bytes in
An array of bytes to run the checksum algorithm over, or NULL to get the
recommended initial value for the checksum algorithm.
.AP size_t length in
.AP Tcl_Size length in
The number of bytes in the array.
.AP int mode in
What mode to operate the stream in. Should be either
\fBTCL_ZLIB_STREAM_DEFLATE\fR for a compressing stream or
\fBTCL_ZLIB_STREAM_INFLATE\fR for a decompressing stream.
.AP Tcl_ZlibStream *zshandlePtr out
A pointer to a variable in which to write the abstract token for the stream
upon successful creation.
.AP Tcl_ZlibStream zshandle in
The abstract token for the stream to operate on.
.AP int flush in
Whether and how to flush the stream after writing the data to it. Must be one
of: \fBTCL_ZLIB_NO_FLUSH\fR if no flushing is to be done, \fBTCL_ZLIB_FLUSH\fR
if the currently compressed data must be made available for access using
\fBTcl_ZlibStreamGet\fR, \fBTCL_ZLIB_FULLFLUSH\fR if the stream must be put
into a state where the decompressor can recover from on corruption, or
\fBTCL_ZLIB_FINALIZE\fR to ensure that the stream is finished and that any
trailer demanded by the format is written.
.AP size_t count in
The maximum number of bytes to get from the stream, or TCL_INDEX_NONE to get
.AP Tcl_Size count in
The maximum number of bytes to get from the stream, or -1 to get
all remaining bytes from the stream's buffers.
.AP Tcl_Obj *compDict in
A byte array value that is the compression dictionary to use with the stream.
Note that this is \fInot a Tcl dictionary\fR, and it is recommended that this
only ever be used with streams that were created with their \fIformat\fR set
to \fBTCL_ZLIB_FORMAT_ZLIB\fR because the other formats have no mechanism to
indicate whether a compression dictionary was present other than to fail on
184
185
186
187
188
189
190
191

192
193
194
195
196
197
198
187
188
189
190
191
192
193

194
195
196
197
198
199
200
201







-
+







\fBTcl_ZlibStreamSetCompressionDictionary\fR is used to control the
compression dictionary used with the stream, a compression dictionary being an
array of bytes (such as might be created with \fBTcl_NewByteArrayObj\fR) that
is used to initialize the compression engine rather than leaving it to create
it on the fly from the data being compressed. Setting a compression dictionary
allows for more efficient compression in the case where the start of the data
is highly regular, but it does require both the compressor and the
decompressor to agreee on the value to use. Compression dictionaries are only
decompressor to agree on the value to use. Compression dictionaries are only
fully supported for zlib-format data; on compression, they must be set before
any data is sent in with \fBTcl_ZlibStreamPut\fR, and on decompression they
should be set when \fBTcl_ZlibStreamGet\fR produces an \fBerror\fR with its
\fB\-errorcode\fR set to
.QW "\fBZLIB NEED_DICT\fI code\fR" ;
the \fIcode\fR will be the Adler-32 checksum (see \fBTcl_ZlibAdler32\fR) of
the compression dictionary sought. (Note that this is only true for
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
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







-
-
+
-


-
-
+
-


-
-
+
-



-
-
+
-






-
-
+
-



-
-
+
-




-
-
+
-


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












that is used to describe the gzip header in the compressed data. When creating
compressed data, the dictionary is read and when unpacking compressed data the
dictionary is written (in which case the \fIdictObj\fR parameter must refer to
an unshared dictionary value).
.PP
The following fields in the dictionary value are understood. All other fields
are ignored. No field is required when creating a gzip-format stream.
.TP
\fBcomment\fR
.IP \fBcomment\fR
.
This holds the comment field of the header, if present. If absent, no comment
was supplied (on decompression) or will be created (on compression).
.TP
\fBcrc\fR
.IP \fBcrc\fR
.
A boolean value describing whether a CRC of the header is computed. Note that
the \fBgzip\fR program does \fInot\fR use or allow a CRC on the header.
.TP
\fBfilename\fR
.IP \fBfilename\fR
.
The name of the file that held the uncompressed data. This should not contain
any directory separators, and should be sanitized before use on decompression
with \fBfile tail\fR.
.TP
\fBos\fR
.IP \fBos\fR
.
The operating system type code field from the header (if not the
.QW unknown
value). See RFC 1952 for the meaning of these codes. On compression, if this
is absent then the field will be set to the
.QW unknown
value.
.TP
\fBsize\fR
.IP \fBsize\fR
.
The size of the uncompressed data. This is ignored on compression; the size
of the data compressed depends on how much data is supplied to the
compression engine.
.TP
\fBtime\fR
.IP \fBtime\fR
.
The time field from the header if non-zero, expected to be the time that the
file named by the \fBfilename\fR field was modified. Suitable for use with
\fBclock format\fR. On creation, the right value to use is that from
\fBclock seconds\fR or \fBfile mtime\fR.
.TP
\fBtype\fR
.IP \fBtype\fR
.
The type of the uncompressed data (either \fBbinary\fR or \fBtext\fR) if
known.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
\fBTcl_ZlibDeflate\fR and \fBTcl_ZlibInflate\fR take a value with arbitrary
reference count for their \fIdataObj\fR and \fIdictObj\fR arguments (the
latter often being NULL instead), and set the interpreter result with their
output value (or an error).  The existing interpreter result should not be
passed as any argument value unless an additional reference is held.
.PP
\fBTcl_ZlibStreamInit\fR takes a value with arbitrary reference count for its
\fIdictObj\fR argument; it only reads from it. The existing interpreter result
should not be passed unless an additional reference is held.
.PP
\fBTcl_ZlibStreamGetCommandName\fR returns a zero reference count value, much
like \fBTcl_NewObj\fR.
.PP
The \fIdataObj\fR argument to \fBTcl_ZlibStreamPut\fR is a value with
arbitrary reference count; it is only ever read from.
.PP
The \fIdataObj\fR argument to \fBTcl_ZlibStreamGet\fR is an unshared value
(see \fBTcl_IsShared\fR) that will be updated by the function.
.PP
The \fIcompDict\fR argument to \fBTcl_ZlibStreamSetCompressionDictionary\fR,
if non-NULL, may be duplicated or may have its reference count incremented.
Using a zero reference count value is not recommended.

.SH "PORTABILITY NOTES"
These functions will fail gracefully if Tcl is not linked with the zlib
library.
.SH "SEE ALSO"
Tcl_NewByteArrayObj(3), zlib(n)
'\"Tcl_StackChannel(3)
.SH "KEYWORDS"
compress, decompress, deflate, gzip, inflate
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/Tcl_Main.3.

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
30
31
32




33
34
35
36
37
38
39
40
41
42
43
44


45
46
47
48
49
50
51
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
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








-
+



-
+






+
+
+
+






+


-
+




+
+
+
+












+
+







'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 2000 Ajuba Solutions.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_Main 3 8.4 Tcl "Tcl Library Procedures"
.TH Tcl_Main 3 9.0 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_Main, Tcl_SetStartupScript, Tcl_GetStartupScript, Tcl_SetMainLoop \- main program, startup script, and event loop definition for Tcl-based applications
Tcl_Main, Tcl_MainEx, Tcl_MainExW, Tcl_SetStartupScript, Tcl_GetStartupScript, Tcl_SetMainLoop \- main program, startup script, and event loop definition for Tcl-based applications
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_Main\fR(\fIargc, argv, appInitProc\fR)
.sp
\fBTcl_MainEx\fR(\fIargc, charargv, appInitProc, interp\fR)
.sp
\fBTcl_MainExW\fR(\fIargc, wideargv, appInitProc, interp\fR)
.sp
\fBTcl_SetStartupScript\fR(\fIpath, encoding\fR)
.sp
Tcl_Obj *
\fBTcl_GetStartupScript\fR(\fIencodingPtr\fR)
.sp
\fBTcl_SetMainLoop\fR(\fImainLoopProc\fR)
.fi
.SH ARGUMENTS
.AS Tcl_MainLoopProc *mainLoopProc
.AP int argc in
.AP Tcl_Size argc in
Number of elements in \fIargv\fR.
.AP char *argv[] in
Array of strings containing command-line arguments. On Windows, when
using -DUNICODE, the parameter type changes to wchar_t *.
.AP char *charargv[] in
As argv, but does not change type to wchar_t.
.AP char *wideargv[] in
As argv, but type is always wchar_t.
.AP Tcl_AppInitProc *appInitProc in
Address of an application-specific initialization procedure.
The value for this argument is usually \fBTcl_AppInit\fR.
.AP Tcl_Obj *path in
Name of file to use as startup script, or NULL.
.AP "const char" *encoding in
Encoding of file to use as startup script, or NULL.
.AP "const char" **encodingPtr out
If non-NULL, location to write a copy of the (const char *)
pointing to the encoding name.
.AP Tcl_MainLoopProc *mainLoopProc in
Address of an application-specific event loop procedure.
.AP Tcl_Interp *interp in
Already created Tcl Interpreter.
.BE
.SH DESCRIPTION
.PP
\fBTcl_Main\fR can serve as the main program for Tcl-based shell
applications.  A
.QW "shell application"
is a program
71
72
73
74
75
76
77
78
79




80
81
82
83
84
85
86
82
83
84
85
86
87
88


89
90
91
92
93
94
95
96
97
98
99







-
-
+
+
+
+







Normally each shell application contains a small \fBmain\fR function
that does nothing but invoke \fBTcl_Main\fR.
\fBTcl_Main\fR then does all the work of creating and running a
\fBtclsh\fR-like application.
.PP
\fBTcl_Main\fR is not provided by the public interface of Tcl's
stub library.  Programs that call \fBTcl_Main\fR must be linked
against the standard Tcl library.  Extensions (stub-enabled or
not) are not intended to call \fBTcl_Main\fR.
against the standard Tcl library.  If the standard Tcl library is
a dll (so, not a static .lib/.a) , then the program must be linked
against the stub library as well. Extensions
(stub-enabled or not) are not intended to call \fBTcl_Main\fR.
.PP
\fBTcl_Main\fR is not thread-safe.  It should only be called by
a single main thread of a multi-threaded application.  This
restriction is not a problem with normal use described above.
.PP
\fBTcl_Main\fR and therefore all applications based upon it, like
\fBtclsh\fR, use \fBTcl_GetStdChannel\fR to initialize the standard
187
188
189
190
191
192
193














194
195
196
197
198
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+





itself will evaluate the \fBexit\fR command after the main loop
procedure (if any) returns.  In non-interactive mode, after
\fBTcl_Main\fR evaluates the startup script, and the main loop
procedure (if any) returns, \fBTcl_Main\fR will also evaluate
the \fBexit\fR command.
.PP
\fBTcl_Main\fR can not be used in stub-enabled extensions.
.PP
The difference between Tcl_MainEx and Tcl_MainExW is that the arguments
are passed as characters or wide characters. When used in stub-enabled
embedders, the stubs table must be first initialized using one of
\fBTcl_InitSubsystems\fR, \fBTcl_SetPanicProc\fR, \fBTcl_FindExecutable\fR or \fBTclZipfs_AppHook\fR.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
\fBTcl_SetStartupScript\fR takes a value (or NULL) for its \fIpath\fR
argument, and will increment the reference count of it.
.PP
\fBTcl_GetStartupScript\fR returns a value with reference count at least 1, or
NULL. It's \fIencodingPtr\fR is also used (if non-NULL) to return a value with
a reference count at least 1, or NULL. In both cases, the owner of the values
is the current thread.
.SH "SEE ALSO"
tclsh(1), Tcl_GetStdChannel(3), Tcl_StandardChannels(3), Tcl_AppInit(3),
exit(n), encoding(n)
.SH KEYWORDS
application-specific initialization, command-line arguments, main program

Changes to doc/Thread.3.

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
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







-


-


-


-
+


-


-


-







+







.BS
.SH NAME
Tcl_ConditionNotify, Tcl_ConditionWait, Tcl_ConditionFinalize, Tcl_GetThreadData, Tcl_MutexLock, Tcl_MutexUnlock, Tcl_MutexFinalize, Tcl_CreateThread, Tcl_JoinThread \- Tcl thread support
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
void
\fBTcl_ConditionNotify\fR(\fIcondPtr\fR)
.sp
void
\fBTcl_ConditionWait\fR(\fIcondPtr, mutexPtr, timePtr\fR)
.sp
void
\fBTcl_ConditionFinalize\fR(\fIcondPtr\fR)
.sp
Void *
void *
\fBTcl_GetThreadData\fR(\fIkeyPtr, size\fR)
.sp
void
\fBTcl_MutexLock\fR(\fImutexPtr\fR)
.sp
void
\fBTcl_MutexUnlock\fR(\fImutexPtr\fR)
.sp
void
\fBTcl_MutexFinalize\fR(\fImutexPtr\fR)
.sp
int
\fBTcl_CreateThread\fR(\fIidPtr, proc, clientData, stackSize, flags\fR)
.sp
int
\fBTcl_JoinThread\fR(\fIid, result\fR)
.fi
.SH ARGUMENTS
.AS Tcl_CreateThreadProc proc out
.AP Tcl_Condition *condPtr in
A condition variable, which must be associated with a mutex lock.
.AP Tcl_Mutex *mutexPtr in
.VS TIP509
A recursive mutex lock.
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
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







-
+











-
+
-
-
-







.AP Tcl_ThreadId id in
Id of the thread waited upon.
.AP Tcl_ThreadCreateProc *proc in
This procedure will act as the \fBmain()\fR of the newly created
thread. The specified \fIclientData\fR will be its sole argument.
.AP void *clientData in
Arbitrary information. Passed as sole argument to the \fIproc\fR.
.AP int stackSize in
.AP size_t stackSize in
The size of the stack given to the new thread.
.AP int flags in
Bitmask containing flags allowing the caller to modify behavior of
the new thread.
.AP int *result out
The referred storage is used to place the exit code of the thread
waited upon into it.
.BE
.SH INTRODUCTION
Beginning with the 8.1 release, the Tcl core is thread safe, which
allows you to incorporate Tcl into multithreaded applications without
customizing the Tcl core.  Starting with the 8.6 release, Tcl
customizing the Tcl core.
multithreading support is on by default. To disable Tcl multithreading
support, you must include the \fB\-\|\-disable-threads\fR option to
\fBconfigure\fR when you configure and compile your Tcl core.
.PP
An important constraint of the Tcl threads implementation is that
\fIonly the thread that created a Tcl interpreter can use that
interpreter\fR.  In other words, multiple threads can not access
the same Tcl interpreter.  (However, a single thread can safely create
and use multiple interpreters.)
.SH DESCRIPTION

Changes to doc/ToUpper.3.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







'\"
'\" Copyright (c) 1997 by Sun Microsystems, Inc.
'\" Copyright (c) 1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_UtfToUpper 3 "8.1" Tcl "Tcl Library Procedures"
.so man.macros
.BS
18
19
20
21
22
23
24
25

26
27
28

29
30
31

32

33
34
35
36
37
38
39
18
19
20
21
22
23
24

25
26
27

28
29
30

31
32
33
34
35
36
37
38
39
40







-
+


-
+


-
+

+







.sp
int
\fBTcl_UniCharToLower\fR(\fIch\fR)
.sp
int
\fBTcl_UniCharToTitle\fR(\fIch\fR)
.sp
int
Tcl_Size
\fBTcl_UtfToUpper\fR(\fIstr\fR)
.sp
int
Tcl_Size
\fBTcl_UtfToLower\fR(\fIstr\fR)
.sp
int
Tcl_Size
\fBTcl_UtfToTitle\fR(\fIstr\fR)
.fi
.SH ARGUMENTS
.AS char *str in/out
.AP int ch in
The Unicode character to be converted.
.AP char *str in/out
Pointer to UTF-8 string to be converted in place.
.BE

Changes to doc/TraceCmd.3.

10
11
12
13
14
15
16
17

18
19
20

21
22
23


24
25
26
27
28
29
30
10
11
12
13
14
15
16

17
18
19

20
21


22
23
24
25
26
27
28
29
30







-
+


-
+

-
-
+
+







.SH NAME
Tcl_CommandTraceInfo, Tcl_TraceCommand, Tcl_UntraceCommand \- monitor renames and deletes of a command
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
void *
\fBTcl_CommandTraceInfo(\fIinterp, cmdName, flags, proc, prevClientData\fB)\fR
\fBTcl_CommandTraceInfo\fR(\fIinterp, cmdName, flags, proc, prevClientData\fR)
.sp
int
\fBTcl_TraceCommand(\fIinterp, cmdName, flags, proc, clientData\fB)\fR
\fBTcl_TraceCommand\fR(\fIinterp, cmdName, flags, proc, clientData\fR)
.sp
void
\fBTcl_UntraceCommand(\fIinterp, cmdName, flags, proc, clientData\fB)\fR
\fBTcl_UntraceCommand\fR(\fIinterp, cmdName, flags, proc, clientData\fR)
.fi
.SH ARGUMENTS
.AS Tcl_CommandTraceProc prevClientData
.AP Tcl_Interp *interp in
Interpreter containing the command.
.AP "const char" *cmdName in
Name of command.
.AP int flags in
50
51
52
53
54
55
56

57
58
59

60
61
62
63
64
65
66
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68







+



+







interpreter's result.
.PP
The \fIflags\fR argument to \fBTcl_TraceCommand\fR indicates when the
trace procedure is to be invoked.  It consists of an OR'ed combination
of any of the following values:
.TP
\fBTCL_TRACE_RENAME\fR
.
Invoke \fIproc\fR whenever the command is renamed.
.TP
\fBTCL_TRACE_DELETE\fR
.
Invoke \fIproc\fR when the command is deleted.
.PP
Whenever one of the specified operations occurs to the command,
\fIproc\fR will be invoked.  It should have arguments and result that
match the type \fBTcl_CommandTraceProc\fR:
.PP
.CS

Changes to doc/TraceVar.3.

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
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







-
+


-
+

-
+

-
+


-
+


-
+
+







.SH NAME
Tcl_TraceVar, Tcl_TraceVar2, Tcl_UntraceVar, Tcl_UntraceVar2, Tcl_VarTraceInfo, Tcl_VarTraceInfo2 \- monitor accesses to a variable
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_TraceVar(\fIinterp, varName, flags, proc, clientData\fB)\fR
\fBTcl_TraceVar\fR(\fIinterp, varName, flags, proc, clientData\fR)
.sp
int
\fBTcl_TraceVar2(\fIinterp, name1, name2, flags, proc, clientData\fB)\fR
\fBTcl_TraceVar2\fR(\fIinterp, name1, name2, flags, proc, clientData\fR)
.sp
\fBTcl_UntraceVar(\fIinterp, varName, flags, proc, clientData\fB)\fR
\fBTcl_UntraceVar\fR(\fIinterp, varName, flags, proc, clientData\fR)
.sp
\fBTcl_UntraceVar2(\fIinterp, name1, name2, flags, proc, clientData\fB)\fR
\fBTcl_UntraceVar2\fR(\fIinterp, name1, name2, flags, proc, clientData\fR)
.sp
void *
\fBTcl_VarTraceInfo(\fIinterp, varName, flags, proc, prevClientData\fB)\fR
\fBTcl_VarTraceInfo\fR(\fIinterp, varName, flags, proc, prevClientData\fR)
.sp
void *
\fBTcl_VarTraceInfo2(\fIinterp, name1, name2, flags, proc, prevClientData\fB)\fR
\fBTcl_VarTraceInfo2\fR(\fIinterp, name1, name2, flags, proc, prevClientData\fR)
.fi
.SH ARGUMENTS
.AS void *prevClientData
.AP Tcl_Interp *interp in
Interpreter containing variable.
.AP "const char" *varName in
Name of variable.  May refer to a scalar variable, to
an array variable with no index, or to an array variable
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
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







+





+





+



+



+







+






+






+















-
-
+
+









-
-
-
+
+
+
+
+







.PP
The \fIflags\fR argument to \fBTcl_TraceVar\fR indicates when the
trace procedure is to be invoked and provides information
for setting up the trace.  It consists of an OR-ed combination
of any of the following values:
.TP
\fBTCL_GLOBAL_ONLY\fR
.
Normally, the variable will be looked up at the current level of
procedure call;  if this bit is set then the variable will be looked
up at global level, ignoring any active procedures.
.TP
\fBTCL_NAMESPACE_ONLY\fR
.
Normally, the variable will be looked up at the current level of
procedure call;  if this bit is set then the variable will be looked
up in the current namespace, ignoring any active procedures.
.TP
\fBTCL_TRACE_READS\fR
.
Invoke \fIproc\fR whenever an attempt is made to read the variable.
.TP
\fBTCL_TRACE_WRITES\fR
.
Invoke \fIproc\fR whenever an attempt is made to modify the variable.
.TP
\fBTCL_TRACE_UNSETS\fR
.
Invoke \fIproc\fR whenever the variable is unset.
A variable may be unset either explicitly by an \fBunset\fR command,
or implicitly when a procedure returns (its local variables are
automatically unset) or when the interpreter or namespace is deleted (all
variables are automatically unset).
.TP
\fBTCL_TRACE_ARRAY\fR
.
Invoke \fIproc\fR whenever the array command is invoked.
This gives the trace procedure a chance to update the array before
array names or array get is called.  Note that this is called
before an array set, but that will trigger write traces.
.TP
\fBTCL_TRACE_RESULT_DYNAMIC\fR
.
The result of invoking the \fIproc\fR is a dynamically allocated
string that will be released by the Tcl library via a call to
\fBTcl_Free\fR.  Must not be specified at the same time as
\fBTCL_TRACE_RESULT_OBJECT\fR.
.TP
\fBTCL_TRACE_RESULT_OBJECT\fR
.
The result of invoking the \fIproc\fR is a Tcl_Obj* (cast to a char*)
with a reference count of at least one.  The ownership of that
reference will be transferred to the Tcl core for release (when the
core has finished with it) via a call to \fBTcl_DecrRefCount\fR.  Must
not be specified at the same time as \fBTCL_TRACE_RESULT_DYNAMIC\fR.
.PP
Whenever one of the specified operations occurs on the variable,
\fIproc\fR will be invoked.
It should have arguments and result that match the type
\fBTcl_VarTraceProc\fR:
.PP
.CS
typedef char *\fBTcl_VarTraceProc\fR(
        void *\fIclientData\fR,
        Tcl_Interp *\fIinterp\fR,
        char *\fIname1\fR,
        char *\fIname2\fR,
        const char *\fIname1\fR,
        const char *\fIname2\fR,
        int \fIflags\fR);
.CE
.PP
The \fIclientData\fR and \fIinterp\fR parameters will
have the same values as those passed to \fBTcl_TraceVar\fR when the
trace was created.
\fIclientData\fR typically points to an application-specific
data structure that describes what to do when \fIproc\fR
is invoked.
\fIName1\fR and \fIname2\fR give the name of the traced variable
in the normal two-part form (see the description of \fBTcl_TraceVar2\fR
below for details).
\fIName1\fR and \fIname2\fR give the name of the variable that
triggered the callback in the normal two-part form (see the description
of \fBTcl_TraceVar2\fR below for details).  In case \fIname1\fR is an
alias to an array element (created through facilities such as \fBupvar\fR),
\fIname2\fR holds the index of the array element, rather than NULL.
\fIFlags\fR is an OR-ed combination of bits providing several
pieces of information.
One of the bits \fBTCL_TRACE_READS\fR, \fBTCL_TRACE_WRITES\fR,
\fBTCL_TRACE_ARRAY\fR, or \fBTCL_TRACE_UNSETS\fR
will be set in \fIflags\fR to indicate which operation is being performed
on the variable.
The bit \fBTCL_GLOBAL_ONLY\fR will be set whenever the variable being
356
357
358
359
360
361
362








363
364
365
366
367
368
369
370
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389







+
+
+
+
+
+
+
+








In an unset callback to \fIproc\fR, the \fBTCL_TRACE_DESTROYED\fR bit
is set in \fIflags\fR if the trace is being removed as part
of the deletion.
Traces on a variable are always removed whenever the variable
is deleted;  the only time \fBTCL_TRACE_DESTROYED\fR is not set is for
a whole-array trace invoked when only a single element of an
array is unset.
.SH "REFERENCE COUNT MANAGEMENT"
.PP
When a \fIproc\fR callback is invoked, and that callback was installed with
the \fBTCL_TRACE_RESULT_OBJECT\fR flag, the result of the callback is a
Tcl_Obj reference when there is an error. The result will have its reference
count decremented once when no longer needed, or may have additional
references made to it (e.g., by setting it as the interpreter result with
\fBTcl_SetObjResult\fR).
.SH BUGS
.PP
Array traces are not yet integrated with the Tcl \fBinfo exists\fR command,
nor is there Tcl-level access to array traces.
.SH "SEE ALSO"
trace(n)
.SH KEYWORDS
clientData, trace, variable

Changes to doc/Translate.3.

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
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
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
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











-
+






+





-
+
-











-
+










-
+







'\"
'\" Copyright (c) 1989-1993 The Regents of the University of California.
'\" Copyright (c) 1994-1998 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tcl_TranslateFileName 3 8.1 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_TranslateFileName \- convert file name to native form and replace tilde with home directory
Tcl_TranslateFileName \- convert file name to native form
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
char *
\fBTcl_TranslateFileName\fR(\fIinterp\fR, \fIname\fR, \fIbufferPtr\fR)
.fi
.SH ARGUMENTS
.AS Tcl_DString *bufferPtr in/out
.AP Tcl_Interp *interp in
Interpreter in which to report an error, if any.
.AP "const char" *name in
File name, which may start with a
File name
.QW ~ .
.AP Tcl_DString *bufferPtr in/out
If needed, this dynamic string is used to store the new file name.
At the time of the call it should be uninitialized or free.  The
caller must eventually call \fBTcl_DStringFree\fR to free up
anything stored here.
.BE
.SH DESCRIPTION
.PP
This utility procedure translates a file name to a platform-specific form
which, after being converted to the appropriate encoding, is suitable for
passing to the local operating system.  In particular, it converts
network names into native form and does tilde substitution.
network names into native form.
.PP
However, with the advent of the newer \fBTcl_FSGetNormalizedPath\fR and
\fBTcl_FSGetNativePath\fR, there is no longer any need to use this
procedure.  In particular, \fBTcl_FSGetNativePath\fR performs all the
necessary translation and encoding conversion, is virtual-filesystem
aware, and caches the native result for faster repeated calls.
Finally \fBTcl_FSGetNativePath\fR does not require you to free anything
afterwards.
.PP
If
\fBTcl_TranslateFileName\fR has to do tilde substitution or translate
\fBTcl_TranslateFileName\fR has to translate
the name then it uses
the dynamic string at \fI*bufferPtr\fR to hold the new string it
generates.
After \fBTcl_TranslateFileName\fR returns a non-NULL result, the caller must
eventually invoke \fBTcl_DStringFree\fR to free any information
placed in \fI*bufferPtr\fR.  The caller need not know whether or
not \fBTcl_TranslateFileName\fR actually used the string;  \fBTcl_TranslateFileName\fR
64
65
66
67
68
69
70
71

64
65
66
67
68
69
70

71







-
+
\fBTcl_DStringFree\fR.
.PP
The caller is responsible for making sure that the interpreter's result
has its default empty value when \fBTcl_TranslateFileName\fR is invoked.
.SH "SEE ALSO"
filename(n)
.SH KEYWORDS
file name, home directory, tilde, translate, user
file name, home directory, translate, user

Changes to doc/UniCharIsAlpha.3.

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
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







+
















-
+
+

-
+
+





-
+
+







\fBTcl_UniCharIsSpace\fR(\fIch\fR)
.sp
int
\fBTcl_UniCharIsUpper\fR(\fIch\fR)
.sp
int
\fBTcl_UniCharIsWordChar\fR(\fIch\fR)
.fi
.SH ARGUMENTS
.AS int ch
.AP int ch in
The Unicode character to be examined.
.BE

.SH DESCRIPTION
.PP
All of the routines described examine Unicode characters and return a
boolean value. A non-zero return value means that the character does
belong to the character class associated with the called routine. The
rest of this document just describes the character classes associated
with the various routines.

.SH "CHARACTER CLASSES"
.PP
\fBTcl_UniCharIsAlnum\fR tests if the character is an alphanumeric Unicode character.
\fBTcl_UniCharIsAlnum\fR tests if the character is an alphanumeric Unicode
character.
.PP
\fBTcl_UniCharIsAlpha\fR tests if the character is an alphabetic Unicode character.
\fBTcl_UniCharIsAlpha\fR tests if the character is an alphabetic Unicode
character.
.PP
\fBTcl_UniCharIsControl\fR tests if the character is a Unicode control character.
.PP
\fBTcl_UniCharIsDigit\fR tests if the character is a numeric Unicode character.
.PP
\fBTcl_UniCharIsGraph\fR tests if the character is any Unicode print character except space.
\fBTcl_UniCharIsGraph\fR tests if the character is any Unicode print character
except space.
.PP
\fBTcl_UniCharIsLower\fR tests if the character is a lowercase Unicode character.
.PP
\fBTcl_UniCharIsPrint\fR tests if the character is a Unicode print character.
.PP
\fBTcl_UniCharIsPunct\fR tests if the character is a Unicode punctuation character.
.PP

Changes to doc/UpVar.3.

11
12
13
14
15
16
17
18

19
20
21


22
23
24
25
26
27
28
11
12
13
14
15
16
17

18
19
20

21
22
23
24
25
26
27
28
29







-
+


-
+
+







.SH NAME
Tcl_UpVar, Tcl_UpVar2 \- link one variable to another
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_UpVar(\fIinterp, frameName, sourceName, destName, flags\fB)\fR
\fBTcl_UpVar\fR(\fIinterp, frameName, sourceName, destName, flags\fR)
.sp
int
\fBTcl_UpVar2(\fIinterp, frameName, name1, name2, destName, flags\fB)\fR
\fBTcl_UpVar2\fR(\fIinterp, frameName, name1, name2, destName, flags\fR)
.fi
.SH ARGUMENTS
.AS "const char" *sourceName
.AP Tcl_Interp *interp in
Interpreter containing variables;  also used for error reporting.
.AP "const char" *frameName in
Identifies the stack frame containing source variable.
May have any of the forms accepted by

Changes to doc/Utf.3.

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
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
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
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










-
+






-
+


-
+


-
+


-
+



-
+


-
+


-
+


-
+


-
+


-
+
+
+
+
+
+
+




















-
+


-
+



















-
+

+




















-
+
+

-
+

-
+

-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+







'\"
'\" Copyright (c) 1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Utf 3 "8.1" Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_UniChar, Tcl_UniCharToUtf, Tcl_UtfToUniChar, Tcl_UtfToChar16, Tcl_UtfToWChar, Tcl_UniCharToUtfDString, Tcl_UtfToUniCharDString, Tcl_Char16ToUtfDString, Tcl_UtfToWCharDString, Tcl_UtfToChar16DString, Tcl_UniCharLen, Tcl_UniCharNcmp, Tcl_UniCharNcasecmp, Tcl_UniCharCaseMatch, Tcl_UtfNcmp, Tcl_UtfNcasecmp, Tcl_UtfCharComplete, Tcl_NumUtfChars, Tcl_UtfFindFirst, Tcl_UtfFindLast, Tcl_UtfNext, Tcl_UtfPrev, Tcl_UniCharAtIndex, Tcl_UtfAtIndex, Tcl_UtfBackslash \- routines for manipulating UTF-8 strings
Tcl_UniChar, Tcl_UniCharToUtf, Tcl_UtfToUniChar, Tcl_UtfToChar16, Tcl_UtfToWChar, Tcl_UniCharToUtfDString, Tcl_UtfToUniCharDString, Tcl_Char16ToUtfDString, Tcl_UtfToWCharDString, Tcl_UtfToChar16DString, Tcl_WCharToUtfDString, Tcl_WCharLen, Tcl_Char16Len, Tcl_UniCharLen, Tcl_UniCharNcmp, Tcl_UniCharNcasecmp, Tcl_UniCharCaseMatch, Tcl_UtfNcmp, Tcl_UtfNcasecmp, Tcl_UtfCharComplete, Tcl_NumUtfChars, Tcl_UtfFindFirst, Tcl_UtfFindLast, Tcl_UtfNext, Tcl_UtfPrev, Tcl_UniCharAtIndex, Tcl_UtfAtIndex, Tcl_UtfBackslash \- routines for manipulating UTF-8 strings
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
typedef ... \fBTcl_UniChar\fR;
.sp
int
Tcl_Size
\fBTcl_UniCharToUtf\fR(\fIch, buf\fR)
.sp
int
Tcl_Size
\fBTcl_UtfToUniChar\fR(\fIsrc, chPtr\fR)
.sp
int
Tcl_Size
\fBTcl_UtfToChar16\fR(\fIsrc, uPtr\fR)
.sp
int
Tcl_Size
\fBTcl_UtfToWChar\fR(\fIsrc, wPtr\fR)
.sp
char *
\fBTcl_UniCharToUtfDString\fR(\fIuniStr, uniLength, dsPtr\fR)
\fBTcl_UniCharToUtfDString\fR(\fIuniStr, numUniChars, dsPtr\fR)
.sp
char *
\fBTcl_Char16ToUtfDString\fR(\fIuStr, uniLength, dsPtr\fR)
\fBTcl_Char16ToUtfDString\fR(\fIutf16, numUtf16, dsPtr\fR)
.sp
char *
\fBTcl_WCharToUtfDString\fR(\fIwStr, uniLength, dsPtr\fR)
\fBTcl_WCharToUtfDString\fR(\fIwcharStr, numWChars, dsPtr\fR)
.sp
Tcl_UniChar *
\fBTcl_UtfToUniCharDString\fR(\fIsrc, length, dsPtr\fR)
\fBTcl_UtfToUniCharDString\fR(\fIsrc, numBytes, dsPtr\fR)
.sp
unsigned short *
\fBTcl_UtfToChar16DString\fR(\fIsrc, length, dsPtr\fR)
\fBTcl_UtfToChar16DString\fR(\fIsrc, numBytes, dsPtr\fR)
.sp
wchar_t *
\fBTcl_UtfToWCharDString\fR(\fIsrc, length, dsPtr\fR)
\fBTcl_UtfToWCharDString\fR(\fIsrc, numBytes, dsPtr\fR)
.sp
int
\fBTcl_Char16Len\fR(\fIutf16\fR)
.sp
int
\fBTcl_WCharLen\fR(\fIwcharStr\fR)
.sp
int
\fBTcl_UniCharLen\fR(\fIuniStr\fR)
.sp
int
\fBTcl_UniCharNcmp\fR(\fIucs, uct, uniLength\fR)
.sp
int
\fBTcl_UniCharNcasecmp\fR(\fIucs, uct, uniLength\fR)
.sp
int
\fBTcl_UniCharCaseMatch\fR(\fIuniStr, uniPattern, nocase\fR)
.sp
int
\fBTcl_UtfNcmp\fR(\fIcs, ct, length\fR)
.sp
int
\fBTcl_UtfNcasecmp\fR(\fIcs, ct, length\fR)
.sp
int
\fBTcl_UtfCharComplete\fR(\fIsrc, length\fR)
\fBTcl_UtfCharComplete\fR(\fIsrc, numBytes\fR)
.sp
int
\fBTcl_NumUtfChars\fR(\fIsrc, length\fR)
\fBTcl_NumUtfChars\fR(\fIsrc, numBytes\fR)
.sp
const char *
\fBTcl_UtfFindFirst\fR(\fIsrc, ch\fR)
.sp
const char *
\fBTcl_UtfFindLast\fR(\fIsrc, ch\fR)
.sp
const char *
\fBTcl_UtfNext\fR(\fIsrc\fR)
.sp
const char *
\fBTcl_UtfPrev\fR(\fIsrc, start\fR)
.sp
int
\fBTcl_UniCharAtIndex\fR(\fIsrc, index\fR)
.sp
const char *
\fBTcl_UtfAtIndex\fR(\fIsrc, index\fR)
.sp
size_t
Tcl_Size
\fBTcl_UtfBackslash\fR(\fIsrc, readPtr, dst\fR)
.fi
.SH ARGUMENTS
.AS "const Tcl_UniChar" *uniPattern in/out
.AP char *buf out
Buffer in which the UTF-8 representation of the Tcl_UniChar is stored.  At most
4 bytes are stored in the buffer.
.AP int ch in
The Unicode character to be converted or examined.
.AP Tcl_UniChar *chPtr out
Filled with the Tcl_UniChar represented by the head of the UTF-8 string.
.AP unsigned short *uPtr out
Filled with the utf-16 represented by the head of the UTF-8 string.
.AP wchar_t *wPtr out
Filled with the wchar_t represented by the head of the UTF-8 string.
.AP "const char" *src in
Pointer to a UTF-8 string.
.AP "const char" *cs in
Pointer to a UTF-8 string.
.AP "const char" *ct in
Pointer to a UTF-8 string.
.AP "const Tcl_UniChar" *uniStr in
A null-terminated Unicode string.
A sequence of \fBTcl_UniChar\fR units with null-termination optional
depending on function.
.AP "const Tcl_UniChar" *ucs in
A null-terminated Unicode string.
A null-terminated sequence of \fBTcl_UniChar\fR.
.AP "const Tcl_UniChar" *uct in
A null-terminated Unicode string.
A null-terminated sequence of \fBTcl_UniChar\fR.
.AP "const Tcl_UniChar" *uniPattern in
A null-terminated Unicode string.
.AP "const unsigned short" *uStr in
A null-terminated UTF-16 string.
.AP "const wchar_t" *wStr in
A null-terminated wchar_t string.
A null-terminated sequence of \fBTcl_UniChar\fR.
.AP "const unsigned short" *utf16 in
A sequence of UTF-16 units with null-termination optional
depending on function.
.AP "const wchar_t" *wcharStr in
A sequence of \fBwchar_t\fR units with null-termination optional
.AP "const unsigned short" *utf16s in
A null-terminated utf-16 string.
.AP "const unsigned short" *utf16t in
A null-terminated utf-16 string.
.AP "const unsigned short" *utf16Pattern in
A null-terminated utf-16 string.
.AP size_t length in
The length of the UTF-8 string in bytes (not UTF-8 characters).  If
negative, all bytes up to the first null byte are used.
.AP size_t uniLength in
The length of the Unicode string in characters.
depending on function.
.AP int numBytes in
The length of the UTF-8 input in bytes.  If
negative, the length includes all bytes until the first null byte.
.AP int numUtf16 in
The length of the input in UTF-16 units.
If negative, the length includes all bytes until the first null.
.AP int numUniChars in
The length of the input in Tcl_UniChar units.
If negative, the length includes all bytes until the first null.
.AP int numWChars in
The length of the input in wchar_t units.
If negative, the length includes all bytes until the first null.
.AP "Tcl_DString" *dsPtr in/out
A pointer to a previously initialized \fBTcl_DString\fR.
.AP "const char" *start in
Pointer to the beginning of a UTF-8 string.
.AP size_t index in
.AP Tcl_Size index in
The index of a character (not byte) in the UTF-8 string.
.AP int *readPtr out
If non-NULL, filled with the number of bytes in the backslash sequence,
including the backslash character.
.AP char *dst out
Buffer in which the bytes represented by the backslash sequence are stored.
At most 4 bytes are stored in the buffer.
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
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







-
-
-
+
+
+
+
-
-
+
+














-
-
-
+
+
+
+
-
-

-
-
+
+
+
-
-
-
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







consists of a lead byte followed by some number of trail bytes.
.PP
\fBTCL_UTF_MAX\fR is the maximum number of bytes that \fBTcl_UtfToUniChar\fR
can consume in a single call.
.PP
\fBTcl_UniCharToUtf\fR stores the character \fIch\fR as a UTF-8 string
in starting at \fIbuf\fR.  The return value is the number of bytes stored
in \fIbuf\fR. If ch is a high surrogate (range U+D800 - U+DBFF), then
the return value will be 1 and a single byte in the range 0xF0 - 0xF4
will be stored. If you still want to produce UTF-8 output for it (even
in \fIbuf\fR. The character \fIch\fR can be or'ed with the value TCL_COMBINE
to enable special behavior, compatible with Tcl 8.x. Then, if ch is a high
surrogate (range U+D800 - U+DBFF), the return value will be 1 and a single
byte in the range 0xF0 - 0xF4 will be stored. If \fIch\fR is a low surrogate
though knowing it's an illegal code-point on its own), just call
\fBTcl_UniCharToUtf\fR again specifying ch = -1.
(range U+DC00 - U+DFFF), an attempt is made to combine the result with
the earlier produced bytes, resulting in a 4-byte UTF-8 byte sequence.
.PP
\fBTcl_UtfToUniChar\fR reads one UTF-8 character starting at \fIsrc\fR
and stores it as a Tcl_UniChar in \fI*chPtr\fR.  The return value is the
number of bytes read from \fIsrc\fR.  The caller must ensure that the
source buffer is long enough such that this routine does not run off the
end and dereference non-existent or random memory; if the source buffer
is known to be null-terminated, this will not happen.  If the input is
a byte in the range 0x80 - 0x9F, \fBTcl_UtfToUniChar\fR assumes the
cp1252 encoding, stores the corresponding Tcl_UniChar in \fI*chPtr\fR
and returns 1. If the input is otherwise
not in proper UTF-8 format, \fBTcl_UtfToUniChar\fR will store the first
byte of \fIsrc\fR in \fI*chPtr\fR as a Tcl_UniChar between 0x00A0 and
0x00FF and return 1.
.PP
\fBTcl_UniCharToUtfDString\fR converts the given Unicode string
to UTF-8, storing the result in a previously initialized \fBTcl_DString\fR.
The return value is a pointer to the UTF-8 representation of the
\fBTcl_UniCharToUtfDString\fR converts the input in the form of a
sequence of \fBTcl_UniChar\fR code points to UTF-8, appending the result to the
previously initialized output \fBTcl_DString\fR. The return value is a pointer
to the UTF-8 representation of the \fBappended\fR string.
Unicode string.  Storage for the return value is appended to the
end of the \fBTcl_DString\fR.
.PP
\fBTcl_UtfToUniCharDString\fR converts the given UTF-8 string to Unicode,
storing the result in the previously initialized \fBTcl_DString\fR.
\fBTcl_UtfToUniCharDString\fR converts the input in the form of
a UTF-8 encoded string to a \fBTcl_UniChar\fR sequence
appending the result in the previously initialized \fBTcl_DString\fR.
In the argument \fIlength\fR, you may either specify the length of
the given UTF-8 string in bytes or
.QW \-1 ,
in which case \fBTcl_UtfToUniCharDString\fR uses \fBstrlen\fR to
calculate the length.  The return value is a pointer to the Unicode
The return value is a pointer to the appended result which is also
representation of the UTF-8 string.  Storage for the return value
is appended to the end of the \fBTcl_DString\fR.  The Unicode string
is terminated with a Unicode null character.
terminated with a \fBTcl_UniChar\fR null character.
.PP
\fBTcl_WCharToUtfDString\fR and \fBTcl_UtfToWCharDString\fR are similar to
\fBTcl_UniCharToUtfDString\fR and \fBTcl_UtfToUniCharDString\fR except they
operate on sequences of \fBwchar_t\fR instead of \fBTcl_UniChar\fR.
.PP
\fBTcl_Char16ToUtfDString\fR and \fBTcl_UtfToChar16DString\fR are similar to
\fBTcl_UniCharToUtfDString\fR and \fBTcl_UtfToUniCharDString\fR except they
operate on sequences of \fBUTF-16\fR units instead of \fBTcl_UniChar\fR.
.PP
\fBTcl_Char16Len\fR corresponds to \fBstrlen\fR for UTF-16
characters.  It accepts a null-terminated UTF-16 sequence and returns
the number of UTF-16 units until the null.
.PP
\fBTcl_WCharLen\fR corresponds to \fBstrlen\fR for wchar_t
characters.  It accepts a null-terminated \fBwchar_t\fR sequence and returns
the number of \fBwchar_t\fR units until the null.
.PP
\fBTcl_UniCharLen\fR corresponds to \fBstrlen\fR for Unicode
characters.  It accepts a null-terminated Unicode string and returns
the number of Unicode characters (not bytes) in that string.
.PP
\fBTcl_UniCharNcmp\fR and \fBTcl_UniCharNcasecmp\fR correspond to
\fBstrncmp\fR and \fBstrncasecmp\fR, respectively, for Unicode characters.
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
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







-
-
-
-
-
+
+
+
+
+




















-
+
+
















-
+




-
+





-
+
-




-
+







.PP
\fBTcl_UtfNcasecmp\fR corresponds to \fBstrncasecmp\fR for UTF-8
strings.  It is similar to \fBTcl_UtfNcmp\fR except comparisons ignore
differences in case when comparing upper, lower or title case
characters.
.PP
\fBTcl_UtfCharComplete\fR returns 1 if the source UTF-8 string \fIsrc\fR
of \fIlength\fR bytes is long enough to be decoded by
\fBTcl_UtfToUniChar\fR, or 0 otherwise.  This function does not guarantee
that the UTF-8 string is properly formed.  This routine is used by
procedures that are operating on a byte at a time and need to know if a
full Unicode character has been seen.
of \fInumBytes\fR bytes is long enough to be decoded by
\fBTcl_UtfToUniChar\fR/\fBTcl_UtfNext\fR, or 0 otherwise.  This function
does not guarantee that the UTF-8 string is properly formed.  This routine
is used by procedures that are operating on a byte at a time and need to
know if a full Unicode character has been seen.
.PP
\fBTcl_NumUtfChars\fR corresponds to \fBstrlen\fR for UTF-8 strings.  It
returns the number of Tcl_UniChars that are represented by the UTF-8 string
\fIsrc\fR.  The length of the source string is \fIlength\fR bytes.  If the
length is negative, all bytes up to the first null byte are used.
.PP
\fBTcl_UtfFindFirst\fR corresponds to \fBstrchr\fR for UTF-8 strings.  It
returns a pointer to the first occurrence of the Unicode character \fIch\fR
in the null-terminated UTF-8 string \fIsrc\fR.  The null terminator is
considered part of the UTF-8 string.
.PP
\fBTcl_UtfFindLast\fR corresponds to \fBstrrchr\fR for UTF-8 strings.  It
returns a pointer to the last occurrence of the Unicode character \fIch\fR
in the null-terminated UTF-8 string \fIsrc\fR.  The null terminator is
considered part of the UTF-8 string.
.PP
Given \fIsrc\fR, a pointer to some location in a UTF-8 string,
\fBTcl_UtfNext\fR returns a pointer to the next UTF-8 character in the
string.  The caller must not ask for the next character after the last
character in the string if the string is not terminated by a null
character.
character. \fBTcl_UtfCharComplete\fR can be used in that case to
make sure enough bytes are available before calling \fBTcl_UtfNext\fR.
.PP
\fBTcl_UtfPrev\fR is used to step backward through but not beyond the
UTF-8 string that begins at \fIstart\fR.  If the UTF-8 string is made
up entirely of complete and well-formed characters, and \fIsrc\fR points
to the lead byte of one of those characters (or to the location one byte
past the end of the string), then repeated calls of \fBTcl_UtfPrev\fR will
return pointers to the lead bytes of each character in the string, one
character at a time, terminating when it returns \fIstart\fR.
.PP
When the conditions of completeness and well-formedness may not be satisfied,
a more precise description of the function of \fBTcl_UtfPrev\fR is necessary.
It always returns a pointer greater than or equal to \fIstart\fR; that is,
always a pointer to a location in the string. It always returns a pointer to
a byte that begins a character when scanning for characters beginning
from \fIstart\fR. When \fIsrc\fR is greater than \fIstart\fR, it
always returns a pointer less than \fIsrc\fR and greater than or
equal to (\fIsrc\fR - \fBTCL_UTF_MAX\fR).  The character that begins
equal to (\fIsrc\fR - 4).  The character that begins
at the returned pointer is the first one that either includes the
byte \fIsrc[-1]\fR, or might include it if the right trail bytes are
present at \fIsrc\fR and greater. \fBTcl_UtfPrev\fR never reads the
byte \fIsrc[0]\fR nor the byte \fIstart[-1]\fR nor the byte
\fIsrc[-\fBTCL_UTF_MAX\fI-1]\fR.
\fIsrc[-5]\fR.
.PP
\fBTcl_UniCharAtIndex\fR corresponds to a C string array dereference or the
Pascal Ord() function.  It returns the Unicode character represented at the
specified character (not byte) \fIindex\fR in the UTF-8 string
\fIsrc\fR.  The source string must contain at least \fIindex\fR
characters.  If \fIindex\fR is TCL_INDEX_NONE or \fIindex\fR points
characters.  If \fIindex\fR is negative it returns -1.
to the second half of a surrogate pair, it returns -1.
.PP
\fBTcl_UtfAtIndex\fR returns a pointer to the specified character (not
byte) \fIindex\fR in the UTF-8 string \fIsrc\fR.  The source string must
contain at least \fIindex\fR characters.  This is equivalent to calling
\fBTcl_UtfToUniChar\fR \fIindex\fR times.  If \fIindex\fR is TCL_INDEX_NONE,
\fBTcl_UtfToUniChar\fR \fIindex\fR times.  If \fIindex\fR is negative,
the return pointer points to the first character in the source string.
.PP
\fBTcl_UtfBackslash\fR is a utility procedure used by several of the Tcl
commands.  It parses a backslash sequence and stores the properly formed
UTF-8 character represented by the backslash sequence in the output
buffer \fIdst\fR.  At most 4 bytes are stored in the buffer.
\fBTcl_UtfBackslash\fR modifies \fI*readPtr\fR to contain the number

Changes to doc/WrongNumArgs.3.

10
11
12
13
14
15
16

17
18
19
20
21
22

23
24
25
26
27
28
29
10
11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30







+





-
+







.SH NAME
Tcl_WrongNumArgs \- generate standard error message for wrong number of arguments
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_WrongNumArgs\fR(\fIinterp, objc, objv, message\fR)
.fi
.SH ARGUMENTS
.AS "Tcl_Obj *const" *message
.AP Tcl_Interp interp in
Interpreter in which error will be reported: error message gets stored
in its result value.
.AP int objc in
.AP Tcl_Size objc in
Number of leading arguments from \fIobjv\fR to include in error
message.
.AP "Tcl_Obj *const" objv[] in
Arguments to command that had the wrong number of arguments.
.AP "const char" *message in
Additional error information to print after leading arguments
from \fIobjv\fR.  This typically gives the acceptable syntax
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
75






76
77
78
79
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







-
+









+
+
+
+
+
+




.PP
Some of the values in the \fIobjv\fR array may be abbreviations for
a subcommand.  The command
\fBTcl_GetIndexFromObj\fR will convert the abbreviated string value
into an \fIindexObject\fR.  If an error occurs in the parsing of the
subcommand we would like to use the full subcommand name rather than
the abbreviation.  If the \fBTcl_WrongNumArgs\fR command finds any
\fIindexObjects\fR in the \fIobjv\fR array it will use the full subcommand
\fIindexObject\fRs in the \fIobjv\fR array, it will use the full subcommand
name in the error message instead of the abbreviated name that was
originally passed in.  Using the above example, let us assume that
\fIbar\fR is actually an abbreviation for \fIbarfly\fR and the value
is now an \fIindexObject\fR because it was passed to
\fBTcl_GetIndexFromObj\fR.  In this case the error message would be:
.PP
.CS
wrong # args: should be "foo barfly fileName count"
.CE
.SH "REFERENCE COUNT MANAGEMENT"
.PP
The \fIobjv\fR argument to \fBTcl_WrongNumArgs\fR should be the exact
arguments passed to the command or method implementation function that is
calling \fBTcl_WrongNumArgs\fR. As such, all values referenced in it should
have reference counts greater than zero; this is usually a non-issue.
.SH "SEE ALSO"
Tcl_GetIndexFromObj(3)
.SH KEYWORDS
command, error message, wrong number of arguments

Changes to doc/abstract.n.

8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
oo::abstract \- a class that does not allow direct instances of itself
.SH SYNOPSIS
.nf
package require TclOO
package require tcl::oo

\fBoo::abstract\fI method \fR?\fIarg ...\fR?
.fi
.SH "CLASS HIERARCHY"
.nf
\fBoo::object\fR
   \(-> \fBoo::class\fR

Changes to doc/after.n.

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
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







+

-

-

-

-

-

+






+




+



+
















+
+
+
+


















+













+







.TH after n 7.5 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
after \- Execute a command after a time delay
.SH SYNOPSIS
.nf
\fBafter \fIms\fR
.sp
\fBafter \fIms \fR?\fIscript script script ...\fR?
.sp
\fBafter cancel \fIid\fR
.sp
\fBafter cancel \fIscript script script ...\fR
.sp
\fBafter idle \fR?\fIscript script script ...\fR?
.sp
\fBafter info \fR?\fIid\fR?
.fi
.BE
.SH DESCRIPTION
.PP
This command is used to delay execution of the program or to execute
a command in background sometime in the future.  It has several forms,
depending on the first argument to the command:
.\" METHOD: <none>
.TP
\fBafter \fIms\fR
.
\fIMs\fR must be an integer giving a time in milliseconds.
A negative number is treated as 0.
The command sleeps for \fIms\fR milliseconds and then returns.
While the command is sleeping the application does not respond to
events.
.\" METHOD: <timedelay>
.TP
\fBafter \fIms \fR?\fIscript script script ...\fR?
.
In this form the command returns immediately, but it arranges
for a Tcl command to be executed \fIms\fR milliseconds later as an
event handler.
The command will be executed exactly once, at the given time.
The delayed command is formed by concatenating all the \fIscript\fR
arguments in the same fashion as the \fBconcat\fR command.
The command will be executed at global level (outside the context
of any Tcl procedure).
If an error occurs while executing the delayed command then
the background error will be reported by the command
registered with \fBinterp bgerror\fR.
The \fBafter\fR command returns an identifier that can be used
to cancel the delayed command using \fBafter cancel\fR.
A \fIms\fR value of 0 (or negative) queues the event immediately with
priority over other event types (if not installed with an event proc,
which will wait for next round of events).
.\" METHOD: cancel
.TP
\fBafter cancel \fIid\fR
.
Cancels the execution of a delayed command that
was previously scheduled.
\fIId\fR indicates which command should be canceled;  it must have
been the return value from a previous \fBafter\fR command.
If the command given by \fIid\fR has already been executed then
the \fBafter cancel\fR command has no effect.
.TP
\fBafter cancel \fIscript script ...\fR
.
This command also cancels the execution of a delayed command.
The \fIscript\fR arguments are concatenated together with space
separators (just as in the \fBconcat\fR command).
If there is a pending command that matches the string, it is
canceled and will never be executed;  if no such command is
currently pending then the \fBafter cancel\fR command has no effect.
.\" METHOD: idle
.TP
\fBafter idle \fIscript \fR?\fIscript script ...\fR?
.
Concatenates the \fIscript\fR arguments together with space
separators (just as in the \fBconcat\fR command), and arranges
for the resulting script to be evaluated later as an idle callback.
The script will be run exactly once, the next time the event
loop is entered and there are no events to process.
The command returns an identifier that can be used
to cancel the delayed command using \fBafter cancel\fR.
If an error occurs while executing the script then the
background error will be reported by the command
registered with \fBinterp bgerror\fR.
.\" METHOD: info
.TP
\fBafter info \fR?\fIid\fR?
.
This command returns information about existing event handlers.
If no \fIid\fR argument is supplied, the command returns
a list of the identifiers for all existing
event handlers created by the \fBafter\fR command for this

Changes to doc/apply.n.

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
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







-
+





-
+




-
+







(the stack of frames accessed via \fBuplevel\fR). The execution of \fIbody\fR
proceeds in this call frame, in the namespace given by \fInamespace\fR or
in the global namespace if none was specified. If given, \fInamespace\fR is
interpreted relative to the global namespace even if its name does not start
with
.QW :: .
.PP
The semantics of \fBapply\fR can also be described by:
The semantics of \fBapply\fR can also be described by approximately this:
.PP
.CS
proc apply {fun args} {
    set len [llength $fun]
    if {($len < 2) || ($len > 3)} {
         error "can't interpret \e"$fun\e" as anonymous function"
        error "can't interpret \e"$fun\e" as anonymous function"
    }
    lassign $fun argList body ns
    set name ::$ns::[getGloballyUniqueName]
    set body0 {
         rename [lindex [info level 0] 0] {}
        rename [lindex [info level 0] 0] {}
    }
    proc $name $argList ${body0}$body
    set code [catch {uplevel 1 $name $args} res opt]
    return -options $opt $res
}
.CE
.SH EXAMPLES
92
93
94
95
96
97
98
99

100
101
102
92
93
94
95
96
97
98

99
100
101
102







-
+



}}}
set vbl 123
set vbl abc
.CE
.SH "SEE ALSO"
proc(n), uplevel(n)
.SH KEYWORDS
anonymous function, argument, lambda, procedure,
anonymous function, argument, lambda, procedure
'\" Local Variables:
'\" mode: nroff
'\" End:

Changes to doc/array.n.

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
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47







-
+

















+


+










+







'\"
'\" Copyright (c) 1993-1994 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH array n 8.7 Tcl "Tcl Built-In Commands"
.TH array n 9.0 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
array \- Manipulate array variables
.SH SYNOPSIS
\fBarray \fIoption arrayName\fR ?\fIarg arg ...\fR?
.BE
.SH DESCRIPTION
.PP
This command performs one of several operations on the
variable given by \fIarrayName\fR.
Unless otherwise specified for individual commands below,
\fIarrayName\fR must be the name of an existing array variable.
The \fIoption\fR argument determines what action is carried
out by the command.
The legal \fIoptions\fR (which may be abbreviated) are:
.\" METHOD: anymore
.TP
\fBarray anymore \fIarrayName searchId\fR
.
Returns 1 if there are any more elements left to be processed
in an array search, 0 if all elements have already been
returned.
\fISearchId\fR indicates which search on \fIarrayName\fR to
check, and must have been the return value from a previous
invocation of \fBarray startsearch\fR.
This option is particularly useful if an array has an element
with an empty name, since the return value from
\fBarray nextelement\fR will not indicate whether the search
has been completed.
.\" METHOD: default
.TP
\fBarray default \fIsubcommand arrayName args...\fR
.VS TIP508
Manages the default value of the array. Arrays initially have no default
value, but this command allows you to set one; the default value will be
returned when reading from an element of the array \fIarrayName\fR if the read
would otherwise result in an error. Note that this may cause the \fBappend\fR,
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
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







+


+





+


+


+

-
+
+






-
+
+


+














+


+












+


+









+


+









+


+



+


+














+


+




+


+







.VS TIP508
This removes the default value for the array \fIarrayName\fR and returns the
empty string. Does nothing if \fIarrayName\fR does not have a default
value. Raises an error if \fIarrayName\fR is an existing variable that is not
an array.
.VE TIP508
.RE
.\" METHOD: donesearch
.TP
\fBarray donesearch \fIarrayName searchId\fR
.
This command terminates an array search and destroys all the
state associated with that search.  \fISearchId\fR indicates
which search on \fIarrayName\fR to destroy, and must have
been the return value from a previous invocation of
\fBarray startsearch\fR.  Returns an empty string.
.\" METHOD: exists
.TP
\fBarray exists \fIarrayName\fR
.
Returns 1 if \fIarrayName\fR is an array variable, 0 if there
is no variable by that name or if it is a scalar variable.
.\" METHOD: for
.TP
\fBarray for {\fIkeyVariable valueVariable\fB} \fIarrayName body\fP
\fBarray for {\fIkeyVariable valueVariable\fB} \fIarrayName body\fR
.
The first argument is a two element list of variable names for the
key and value of each entry in the array.  The second argument is the
array name to iterate over.  The third argument is the body to execute
for each key and value returned.
The ordering of the returned keys is undefined.
If an array element is deleted or a new array element is inserted during
the \fIarray for\fP process, the command will terminate with an error.
the \fIarray for\fR process, the command will terminate with an error.
.\" METHOD: get
.TP
\fBarray get \fIarrayName\fR ?\fIpattern\fR?
.
Returns a list containing pairs of elements.  The first
element in each pair is the name of an element in \fIarrayName\fR
and the second element of each pair is the value of the
array element.  The order of the pairs is undefined.
If \fIpattern\fR is not specified, then all of the elements of the
array are included in the result.
If \fIpattern\fR is specified, then only those elements whose names
match \fIpattern\fR (using the matching rules of
\fBstring match\fR) are included.
If \fIarrayName\fR is not the name of an array variable, or if
the array contains no elements, then an empty list is returned.
If traces on the array modify the list of elements, the elements
returned are those that exist both before and after the call to
\fBarray get\fR.
.\" METHOD: names
.TP
\fBarray names \fIarrayName\fR ?\fImode\fR? ?\fIpattern\fR?
.
Returns a list containing the names of all of the elements in
the array that match \fIpattern\fR.  \fIMode\fR may be one of
\fB\-exact\fR, \fB\-glob\fR, or \fB\-regexp\fR.  If specified, \fImode\fR
designates which matching rules to use to match \fIpattern\fR against
the names of the elements in the array.  If not specified, \fImode\fR
defaults to \fB\-glob\fR.  See the documentation for \fBstring match\fR
for information on glob style matching, and the documentation for
\fBregexp\fR for information on regexp matching.
If \fIpattern\fR is omitted then the command returns all of
the element names in the array.  If there are no (matching) elements
in the array, or if \fIarrayName\fR is not the name of an array
variable, then an empty string is returned.
.\" METHOD: nextelement
.TP
\fBarray nextelement \fIarrayName searchId\fR
.
Returns the name of the next element in \fIarrayName\fR, or
an empty string if all elements of \fIarrayName\fR have
already been returned in this search.  The \fIsearchId\fR
argument identifies the search, and must have
been the return value of an \fBarray startsearch\fR command.
Warning:  if elements are added to or deleted from the array,
then all searches are automatically terminated just as if
\fBarray donesearch\fR had been invoked; this will cause
\fBarray nextelement\fR operations to fail for those searches.
.\" METHOD: set
.TP
\fBarray set \fIarrayName list\fR
.
Sets the values of one or more elements in \fIarrayName\fR.
\fIlist\fR must have a form like that returned by \fBarray get\fR,
consisting of an even number of elements.
Each odd-numbered element in \fIlist\fR is treated as an element
name within \fIarrayName\fR, and the following element in \fIlist\fR
is used as a new value for that array element.
If the variable \fIarrayName\fR does not already exist
and \fIlist\fR is empty,
\fIarrayName\fR is created with an empty array value.
.\" METHOD: size
.TP
\fBarray size \fIarrayName\fR
.
Returns a decimal string giving the number of elements in the
array.
If \fIarrayName\fR is not the name of an array then 0 is returned.
.\" METHOD: startsearch
.TP
\fBarray startsearch \fIarrayName\fR
.
This command initializes an element-by-element search through the
array given by \fIarrayName\fR, such that invocations of the
\fBarray nextelement\fR command will return the names of the
individual elements in the array.
When the search has been completed, the \fBarray donesearch\fR
command should be invoked.
The return value is a
search identifier that must be used in \fBarray nextelement\fR
and \fBarray donesearch\fR commands; it allows multiple
searches to be underway simultaneously for the same array.
It is currently more efficient and easier to use either the \fBarray
get\fR or \fBarray names\fR, together with \fBforeach\fR, to iterate
over all but very large arrays.  See the examples below for how to do
this.
.\" METHOD: statistics
.TP
\fBarray statistics \fIarrayName\fR
.
Returns statistics about the distribution of data within the hashtable
that represents the array.  This information includes the number of
entries in the table, the number of buckets, and the utilization of
the buckets.
.\" METHOD: unset
.TP
\fBarray unset \fIarrayName\fR ?\fIpattern\fR?
.
Unsets all of the elements in the array that match \fIpattern\fR (using the
matching rules of \fBstring match\fR).  If \fIarrayName\fR is not the name
of an array variable or there are no matching elements in the array, no
error will be raised.  If \fIpattern\fR is omitted and \fIarrayName\fR is
an array variable, then the command unsets the entire array.
The command always returns an empty string.
.SH EXAMPLES

Changes to doc/binary.n.

1
2
3


4
5
6
7
8
9
10
1


2
3
4
5
6
7
8
9
10

-
-
+
+







'\"
'\" Copyright (c) 1997 by Sun Microsystems, Inc.
'\" Copyright (c) 2008 by Donal K. Fellows
'\" Copyright (c) 1997 Sun Microsystems, Inc.
'\" Copyright (c) 2008 Donal K. Fellows
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH binary n 8.0 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
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
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







+
+




-
-
+
+
+










+





+









+











-
+
+
+




+
















+






+











+












+







Note that other operations on binary data, such as taking a subsequence of it,
getting its length, or reinterpreting it as a string in some encoding, are
done by other Tcl commands (respectively \fBstring range\fR,
\fBstring length\fR and \fBencoding convertfrom\fR in the example cases).  A
binary string in Tcl is merely one where all the characters it contains are in
the range \eu0000\-\eu00FF.
.SH "BINARY ENCODE AND DECODE"
.\" METHOD: decode
.\" METHOD: encode
.PP
When encoding binary data as a readable string, the starting binary data is
passed to the \fBbinary encode\fR command, together with the name of the
encoding to use and any encoding-specific options desired. Data which has been
encoded can be converted back to binary form using \fBbinary decode\fR. The
following formats and options are supported.
encoded can be converted back to binary form using \fBbinary decode\fR.
The \fBbinary encode\fR command raises an error if the \fIdata\fR argument
is not binary data. The following formats and options are supported.
.TP
\fBbase64\fR
.
The \fBbase64\fR binary encoding is commonly used in mail messages and XML
documents, and uses mostly upper and lower case letters and digits. It has the
distinction of being able to be rewrapped arbitrarily without losing
information.
.RS
.PP
During encoding, the following options are supported:
.\" OPTION: -maxlen
.TP
\fB\-maxlen \fIlength\fR
.
Indicates that the output should be split into lines of no more than
\fIlength\fR characters. By default, lines are not split.
.\" OPTION: -wrapchar
.TP
\fB\-wrapchar \fIcharacter\fR
.
Indicates that, when lines are split because of the \fB\-maxlen\fR option,
\fIcharacter\fR should be used to separate lines. By default, this is a
newline character,
.QW \en .
.PP
During decoding, the following options are supported:
.\" OPTION: -strict
.TP
\fB\-strict\fR
.
Instructs the decoder to throw an error if it encounters any characters
that are not strictly part of the encoding itself. Otherwise it ignores them.
RFC 2045 calls for base64 decoders to be non-strict.
.RE
.TP
\fBhex\fR
.
The \fBhex\fR binary encoding converts each byte to a pair of hexadecimal
digits in big-endian form.
digits that represent the byte value as a hexadecimal integer.
When encoding, lower characters are used.
When decoding, upper and lower characters are accepted.
.RS
.PP
No options are supported during encoding. During decoding, the following
options are supported:
.\" OPTION: -strict
.TP
\fB\-strict\fR
.
Instructs the decoder to throw an error if it encounters whitespace characters.
Otherwise it ignores them.
.RE
.TP
\fBuuencode\fR
.
The \fBuuencode\fR binary encoding used to be common for transfer of data
between Unix systems and on USENET, but is less common these days, having been
largely superseded by the \fBbase64\fR binary encoding.
.RS
.PP
During encoding, the following options are supported (though changing them may
produce files that other implementations of decoders cannot process):
.\" OPTION: -maxlen
.TP
\fB\-maxlen \fIlength\fR
.
Indicates the maximum number of characters to produce for each encoded line.
The valid range is 5 to 85. Line lengths outside that range cannot be
accommodated by the encoding format. The default value is 61.
.\" OPTION: -wrapchar
.TP
\fB\-wrapchar \fIcharacter\fR
.
Indicates the character(s) to use to mark the end of each encoded line.
Acceptable values are a sequence of zero or more characters from the
set { \\x09 (TAB), \\x0B (VT), \\x0C (FF), \\x0D (CR) } followed
by zero or one newline \\x0A (LF).  Any other values are rejected because
they would generate encoded text that could not be decoded. The default value
is a single newline.
.PP
During decoding, the following options are supported:
.\" OPTION: -strict
.TP
\fB\-strict\fR
.
Instructs the decoder to throw an error if it encounters anything
outside of the standard encoding format. Without this option, the
decoder tolerates some deviations, mostly to forgive reflows of lines
between the encoder and decoder.
.PP
Note that neither the encoder nor the decoder handle the header and footer of
the uuencode format.
.RE
.SH "BINARY FORMAT"
.\" METHOD: format
.PP
The \fBbinary format\fR command generates a binary string whose layout
is specified by the \fIformatString\fR and whose contents come from
the additional arguments.  The resulting binary value is returned.
.PP
The \fIformatString\fR consists of a sequence of zero or more field
specifiers separated by zero or more spaces.  Each field specifier is
234
235
236
237
238
239
240
241

242
243
244
245
246
247
248
247
248
249
250
251
252
253

254
255
256
257
258
259
260
261







-
+







.PP
which returns a binary string equivalent to:
.PP
.CS
\fB\e254\fR
.CE
.PP
(i.e. \fB\exac\fR) by
(i.e. \fB\exAC\fR) by
truncating the high-bits of the character, and which is probably not
what is desired.
.RE
.IP \fBA\fR 5
This form is the same as \fBa\fR except that spaces are used for
padding instead of nulls.  For example,
.RS
292
293
294
295
296
297
298
299

300
301
302
303
304
305
306
305
306
307
308
309
310
311

312
313
314
315
316
317
318
319







-
+







.CS
\fBbinary format\fR B5B* 11100 111000011010
.CE
.PP
will return a binary string equivalent to:
.PP
.CS
\fB\exe0\exe1\exa0\fR
\fB\exE0\exE1\exA0\fR
.CE
.RE
.IP \fBH\fR 5
Stores a string of \fIcount\fR hexadecimal digits in high-to-low
within each byte in the output binary string.  \fIArg\fR must contain a
sequence of characters in the set
.QW 0123456789abcdefABCDEF .
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
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







-
+














-
+







.CS
\fBbinary format\fR H3H*H2 ab DEF 987
.CE
.PP
will return a binary string equivalent to:
.PP
.CS
\fB\exab\ex00\exde\exf0\ex98\fR
\fB\exAB\ex00\exDE\exF0\ex98\fR
.CE
.RE
.IP \fBh\fR 5
This form is the same as \fBH\fR except that the digits are stored in
low-to-high order within each byte. This is seldom required. For example,
.RS
.PP
.CS
\fBbinary format\fR h3h*h2 AB def 987
.CE
.PP
will return a binary string equivalent to:
.PP
.CS
\fB\exba\ex00\exed\ex0f\ex89\fR
\fB\exBA\ex00\exED\ex0F\ex89\fR
.CE
.RE
.IP \fBc\fR 5
Stores one or more 8-bit integer values in the output string.  If no
\fIcount\fR is specified, then \fIarg\fR must consist of an integer
value. If \fIcount\fR is specified, \fIarg\fR must consist of a list
containing at least that many integers. The low-order 8 bits of each integer
356
357
358
359
360
361
362
363

364
365
366
367
368
369
370
369
370
371
372
373
374
375

376
377
378
379
380
381
382
383







-
+







.CS
\fBbinary format\fR c3cc* {3 -3 128 1} 260 {2 5}
.CE
.PP
will return a binary string equivalent to:
.PP
.CS
\fB\ex03\exfd\ex80\ex04\ex02\ex05\fR
\fB\ex03\exFD\ex80\ex04\ex02\ex05\fR
.CE
.PP
whereas:
.PP
.CS
\fBbinary format\fR c {2 5}
.CE
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
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







-
+















-
+







.CS
\fBbinary format\fR s3 {3 -3 258 1}
.CE
.PP
will return a binary string equivalent to:
.PP
.CS
\fB\ex03\ex00\exfd\exff\ex02\ex01\fR
\fB\ex03\ex00\exFD\exFF\ex02\ex01\fR
.CE
.RE
.IP \fBS\fR 5
This form is the same as \fBs\fR except that it stores one or more
16-bit integers in big-endian byte order in the output string.  For
example,
.RS
.PP
.CS
\fBbinary format\fR S3 {3 -3 258 1}
.CE
.PP
will return a binary string equivalent to:
.PP
.CS
\fB\ex00\ex03\exff\exfd\ex01\ex02\fR
\fB\ex00\ex03\exFF\exFD\ex01\ex02\fR
.CE
.RE
.IP \fBt\fR 5
This form (mnemonically \fItiny\fR) is the same as \fBs\fR and \fBS\fR
except that it stores the 16-bit integers in the output string in the
native byte order of the machine where the Tcl script is running.
To determine what the native byte order of the machine is, refer to
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
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







-
+















-
+







.CS
\fBbinary format\fR i3 {3 -3 65536 1}
.CE
.PP
will return a binary string equivalent to:
.PP
.CS
\fB\ex03\ex00\ex00\ex00\exfd\exff\exff\exff\ex00\ex00\ex01\ex00\fR
\fB\ex03\ex00\ex00\ex00\exFD\exFF\exFF\exFF\ex00\ex00\ex01\ex00\fR
.CE
.RE
.IP \fBI\fR 5
This form is the same as \fBi\fR except that it stores one or more one
or more 32-bit integers in big-endian byte order in the output string.
For example,
.RS
.PP
.CS
\fBbinary format\fR I3 {3 -3 65536 1}
.CE
.PP
will return a binary string equivalent to:
.PP
.CS
\fB\ex00\ex00\ex00\ex03\exff\exff\exff\exfd\ex00\ex01\ex00\ex00\fR
\fB\ex00\ex00\ex00\ex03\exFF\exFF\exFF\exFD\ex00\ex01\ex00\ex00\fR
.CE
.RE
.IP \fBn\fR 5
This form (mnemonically \fInumber\fR or \fInormal\fR) is the same as
\fBi\fR and \fBI\fR except that it stores the 32-bit integers in the
output string in the native byte order of the machine where the Tcl
script is running.
503
504
505
506
507
508
509
510

511
512
513
514
515
516
517
516
517
518
519
520
521
522

523
524
525
526
527
528
529
530







-
+







.CS
\fBbinary format\fR f2 {1.6 3.4}
.CE
.PP
will return a binary string equivalent to:
.PP
.CS
\fB\excd\excc\excc\ex3f\ex9a\ex99\ex59\ex40\fR
\fB\exCD\exCC\exCC\ex3F\ex9A\ex99\ex59\ex40\fR
.CE
.RE
.IP \fBr\fR 5
This form (mnemonically \fIreal\fR) is the same as \fBf\fR except that
it stores the single-precision floating point numbers in little-endian
order.  This conversion only produces meaningful output when used on
machines which use the IEEE floating point representation (very
529
530
531
532
533
534
535
536

537
538
539
540
541
542
543
542
543
544
545
546
547
548

549
550
551
552
553
554
555
556







-
+







.CS
\fBbinary format\fR d1 {1.6}
.CE
.PP
will return a binary string equivalent to:
.PP
.CS
\fB\ex9a\ex99\ex99\ex99\ex99\ex99\exf9\ex3f\fR
\fB\ex9A\ex99\ex99\ex99\ex99\ex99\exF9\ex3F\fR
.CE
.RE
.IP \fBq\fR 5
This form (mnemonically the mirror of \fBd\fR) is the same as \fBd\fR
except that it stores the double-precision floating point numbers in
little-endian order.  This conversion only produces meaningful output
when used on machines which use the IEEE floating point representation
600
601
602
603
604
605
606

607
608
609
610
611
612



613
614
615
616
617
618
619
613
614
615
616
617
618
619
620
621
622
623



624
625
626
627
628
629
630
631
632
633







+



-
-
-
+
+
+







will return
.PP
.CS
\fBabfdeghi\e000\e000j\fR
.CE
.RE
.SH "BINARY SCAN"
.\" METHOD: scan
.PP
The \fBbinary scan\fR command parses fields from a binary string,
returning the number of conversions performed.  \fIString\fR gives the
input bytes to be parsed (one byte per character, and characters not
representable as a byte have their high bits chopped)
and \fIformatString\fR indicates how to parse it.
input bytes to be parsed and \fIformatString\fR indicates how to parse it.
An error is raised if \fIstring\fR is anything other than a valid binary
data value.
Each \fIvarName\fR gives the name of a variable; when a field is
scanned from \fIstring\fR the result is assigned to the corresponding
variable.
.PP
As with \fBbinary format\fR, the \fIformatString\fR consists of a
sequence of zero or more field specifiers separated by zero or more
spaces.  Each field specifier is a single type character followed by
758
759
760
761
762
763
764









765
766
767
768
769
770
771
772
773
774
775
776
777
778
779

780
781
782
783
784
785
786
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801

802
803
804
805
806
807
808
809







+
+
+
+
+
+
+
+
+














-
+







.CS
\fBbinary scan\fR \ex70\ex87\ex05 B5B* var1 var2
.CE
.PP
will return \fB2\fR with \fB01110\fR stored in \fIvar1\fR and
\fB1000011100000101\fR stored in \fIvar2\fR.
.RE
.IP \fBC\fR 5
This form is similar to \fBA\fR, except that it scans the data from start
and terminates at the first null (C string semantics). For example,
.RS
.CS
\fBbinary scan\fR "abc\e000efghi" C* var1
.CE
will return \fB1\fR with \fBabc\fR stored in \fIvar1\fR.
.RE
.IP \fBH\fR 5
The data is turned into a string of \fIcount\fR hexadecimal digits in
high-to-low order represented as a sequence of characters in the set
.QW 0123456789abcdef .
The data bytes are scanned in first to last
order with the hex digits being taken in high-to-low order within each
byte. Any extra bits in the last byte are ignored. If \fIcount\fR is
.QW \fB*\fR ,
then all of the remaining hex digits in \fIstring\fR will be
scanned. If \fIcount\fR is omitted, then one hex digit will be
scanned. For example,
.RS
.PP
.CS
\fBbinary scan\fR \ex07\exC6\ex05\ex1f\ex34 H3H* var1 var2
\fBbinary scan\fR \ex07\exC6\ex05\ex1F\ex34 H3H* var1 var2
.CE
.PP
will return \fB2\fR with \fB07c\fR stored in \fIvar1\fR and
\fB051f34\fR stored in \fIvar2\fR.
.RE
.IP \fBh\fR 5
This form is the same as \fBH\fR, except the digits are taken in
823
824
825
826
827
828
829
830

831
832
833
834
835
836
837
838
839
840
841
842
843
844

845
846
847
848
849
850
851
846
847
848
849
850
851
852

853
854
855
856
857
858
859
860
861
862
863
864
865
866

867
868
869
870
871
872
873
874







-
+













-
+







.QW \fB*\fR ,
then all of the remaining bytes in \fIstring\fR will be scanned.  If
\fIcount\fR is omitted, then one 16-bit integer will be scanned.  For
example,
.RS
.PP
.CS
\fBbinary scan\fR \ex05\ex00\ex07\ex00\exf0\exff s2s* var1 var2
\fBbinary scan\fR \ex05\ex00\ex07\ex00\exF0\exFF s2s* var1 var2
.CE
.PP
will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR
stored in \fIvar2\fR.  Note that the integers returned are signed unless
\fBsu\fR is used in place of \fBs\fR.
.RE
.IP \fBS\fR 5
This form is the same as \fBs\fR except that the data is interpreted
as \fIcount\fR 16-bit integers represented in big-endian byte
order.  For example,
.RS
.PP
.CS
\fBbinary scan\fR \ex00\ex05\ex00\ex07\exff\exf0 S2S* var1 var2
\fBbinary scan\fR \ex00\ex05\ex00\ex07\exFF\exF0 S2S* var1 var2
.CE
.PP
will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR
stored in \fIvar2\fR.
.RE
.IP \fBt\fR 5
The data is interpreted as \fIcount\fR 16-bit signed integers
862
863
864
865
866
867
868
869

870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885

886
887
888
889
890
891
892
885
886
887
888
889
890
891

892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907

908
909
910
911
912
913
914
915







-
+















-
+







.QW \fB*\fR ,
then all of the remaining bytes in \fIstring\fR will be scanned.  If
\fIcount\fR is omitted, then one 32-bit integer will be scanned.  For
example,
.RS
.PP
.CS
set str \ex05\ex00\ex00\ex00\ex07\ex00\ex00\ex00\exf0\exff\exff\exff
set str \ex05\ex00\ex00\ex00\ex07\ex00\ex00\ex00\exF0\exFF\exFF\exFF
\fBbinary scan\fR $str i2i* var1 var2
.CE
.PP
will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR
stored in \fIvar2\fR.  Note that the integers returned are signed unless
\fBiu\fR is used in place of \fBi\fR.
.RE
.IP \fBI\fR 5
This form is the same as \fBI\fR except that the data is interpreted
as \fIcount\fR 32-bit signed integers represented in big-endian byte
order, or as unsigned if \fBu\fR is placed
immediately after the \fBI\fR.  For example,
.RS
.PP
.CS
set str \ex00\ex00\ex00\ex05\ex00\ex00\ex00\ex07\exff\exff\exff\exf0
set str \ex00\ex00\ex00\ex05\ex00\ex00\ex00\ex07\exFF\exFF\exFF\exF0
\fBbinary scan\fR $str I2I* var1 var2
.CE
.PP
will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR
stored in \fIvar2\fR.
.RE
.IP \fBn\fR 5
904
905
906
907
908
909
910
911

912
913
914
915
916
917
918
919
920
921
922
923
924
925
926

927
928
929
930
931
932
933
927
928
929
930
931
932
933

934
935
936
937
938
939
940
941
942
943
944
945
946
947
948

949
950
951
952
953
954
955
956







-
+














-
+







.QW \fB*\fR ,
then all of the remaining bytes in \fIstring\fR will be scanned.  If
\fIcount\fR is omitted, then one 64-bit integer will be scanned.  For
example,
.RS
.PP
.CS
set str \ex05\ex00\ex00\ex00\ex07\ex00\ex00\ex00\exf0\exff\exff\exff
set str \ex05\ex00\ex00\ex00\ex07\ex00\ex00\ex00\exF0\exFF\exFF\exFF
\fBbinary scan\fR $str wi* var1 var2
.CE
.PP
will return \fB2\fR with \fB30064771077\fR stored in \fIvar1\fR and
\fB\-16\fR stored in \fIvar2\fR.
.RE
.IP \fBW\fR 5
This form is the same as \fBw\fR except that the data is interpreted
as \fIcount\fR 64-bit signed integers represented in big-endian byte
order, or as unsigned if \fBu\fR is placed
immediately after the \fBW\fR.  For example,
.RS
.PP
.CS
set str \ex00\ex00\ex00\ex05\ex00\ex00\ex00\ex07\exff\exff\exff\exf0
set str \ex00\ex00\ex00\ex05\ex00\ex00\ex00\ex07\exFF\exFF\exFF\exF0
\fBbinary scan\fR $str WI* var1 var2
.CE
.PP
will return \fB2\fR with \fB21474836487\fR stored in \fIvar1\fR and \fB\-16\fR
stored in \fIvar2\fR.
.RE
.IP \fBm\fR 5
950
951
952
953
954
955
956
957

958
959
960
961
962
963
964
973
974
975
976
977
978
979

980
981
982
983
984
985
986
987







-
+







bytes that are scanned may vary.  If the data does not represent a
valid floating point number, the resulting value is undefined and
compiler dependent.  For example, on a Windows system running on an
Intel Pentium processor,
.RS
.PP
.CS
\fBbinary scan\fR \ex3f\excc\excc\excd f var1
\fBbinary scan\fR \ex3F\exCC\exCC\exCD f var1
.CE
.PP
will return \fB1\fR with \fB1.6000000238418579\fR stored in
\fIvar1\fR.
.RE
.IP \fBr\fR 5
This form is the same as \fBf\fR except that the data is interpreted
974
975
976
977
978
979
980
981

982
983
984
985
986
987
988
997
998
999
1000
1001
1002
1003

1004
1005
1006
1007
1008
1009
1010
1011







-
+







This form is the same as \fBf\fR except that the data is interpreted
as \fIcount\fR double-precision floating point numbers in the
machine's native representation. For example, on a Windows system
running on an Intel Pentium processor,
.RS
.PP
.CS
\fBbinary scan\fR \ex9a\ex99\ex99\ex99\ex99\ex99\exf9\ex3f d var1
\fBbinary scan\fR \ex9A\ex99\ex99\ex99\ex99\ex99\exF9\ex3F d var1
.CE
.PP
will return \fB1\fR with \fB1.6000000000000001\fR
stored in \fIvar1\fR.
.RE
.IP \fBq\fR 5
This form is the same as \fBd\fR except that the data is interpreted
1081
1082
1083
1084
1085
1086
1087
1088

1089
1090
1091
1092
1093
1094
1095
1096
1097
1104
1105
1106
1107
1108
1109
1110

1111
1112
1113
1114
1115
1116
1117
1118
1119
1120







-
+









This converts the contents of a file (named in the variable \fIfilename\fR) to
base64 and prints them:
.PP
.CS
set f [open $filename rb]
set data [read $f]
close $f
puts [\fBbinary encode\fR base64 \-maxlen 64 $data]
puts [\fBbinary encode\fR base64 -maxlen 64 $data]
.CE
.SH "SEE ALSO"
encoding(n), format(n), scan(n), string(n), tcl_platform(n)
.SH KEYWORDS
binary, format, scan
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/callback.n.

8
9
10
11
12
13
14
15

16
17
18


19
20
21
22
23
24
25
8
9
10
11
12
13
14

15
16


17
18
19
20
21
22
23
24
25







-
+

-
-
+
+







.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
callback, mymethod \- generate callbacks to methods
.SH SYNOPSIS
.nf
package require TclOO
package require tcl::oo

\fBcallback\fR \fImethodName\fR ?\fIarg ...\fR?
\fBmymethod\fR \fImethodName\fR ?\fIarg ...\fR?
\fBcallback\fI methodName\fR ?\fIarg ...\fR?
\fBmymethod\fI methodName\fR ?\fIarg ...\fR?
.fi
.BE
.SH DESCRIPTION
The \fBcallback\fR command,
'\" Based on notes in the tcllib docs, we know the provenance of mymethod
also called \fBmymethod\fR for compatibility with the ooutil and snit packages
of Tcllib,

Changes to doc/catch.n.

26
27
28
29
30
31
32
33
34
35
36






37
38
39
40
41
42
43
26
27
28
29
30
31
32




33
34
35
36
37
38
39
40
41
42
43
44
45







-
-
-
-
+
+
+
+
+
+







value corresponding to the exceptional return code returned by evaluation
of \fIscript\fR.  Tcl defines the normal return code from script
evaluation to be zero (0), or \fBTCL_OK\fR.  Tcl also defines four exceptional
return codes: 1 (\fBTCL_ERROR\fR), 2 (\fBTCL_RETURN\fR), 3 (\fBTCL_BREAK\fR),
and 4 (\fBTCL_CONTINUE\fR).  Errors during evaluation of a script are indicated
by a return code of \fBTCL_ERROR\fR.  The other exceptional return codes are
returned by the \fBreturn\fR, \fBbreak\fR, and \fBcontinue\fR commands
and in other special situations as documented.  Tcl packages can define
new commands that return other integer values as return codes as well,
and scripts that make use of the \fBreturn \-code\fR command can also
have return codes other than the five defined by Tcl.
and in other special situations as documented.
New commands defined by Tcl packages as well as scripts that make
use of the \fBreturn \-code\fR  command can return other integer
values as the return code. These must however lie outside the range
reserved for Tcl as documented for the \fBreturn\fR command.

.PP
If the \fIresultVarName\fR argument is given, then the variable it names is
set to the result of the script evaluation.  When the return code from the
script is 1 (\fBTCL_ERROR\fR), the value stored in \fIresultVarName\fR is an
error message.  When the return code from the script is 0 (\fBTCL_OK\fR), the
value stored in \fIresultVarName\fR is the value returned from \fIscript\fR.
.PP

Changes to doc/cd.n.

16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39







+








-
+







.BE
.SH DESCRIPTION
.PP
Change the current working directory to \fIdirName\fR, or to the
home directory (as specified in the HOME environment variable) if
\fIdirName\fR is not given.
Returns an empty string.
.PP
Note that the current working directory is a per-process resource; the
\fBcd\fR command changes the working directory for all interpreters
and all threads.
.SH EXAMPLES
.PP
Change to the home directory of the user \fBfred\fR:
.PP
.CS
\fBcd\fR ~fred
\fBcd\fR [file home fred]
.CE
.PP
Change to the directory \fBlib\fR that is a sibling directory of the
current one:
.PP
.CS
\fBcd\fR ../lib

Changes to doc/chan.n.

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
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







+

-
+


-
+




+

-
+

-
+















-
+









-
+



-
+







This command provides several operations for reading from, writing to
and otherwise manipulating open channels (such as have been created
with the \fBopen\fR and \fBsocket\fR commands, or the default named
channels \fBstdin\fR, \fBstdout\fR or \fBstderr\fR which correspond to
the process's standard input, output and error streams respectively).
\fIOption\fR indicates what to do with the channel; any unique
abbreviation for \fIoption\fR is acceptable. Valid options are:
.\" METHOD: blocked
.TP
\fBchan blocked \fIchannelId\fR
\fBchan blocked \fIchannel\fR
.
This tests whether the last input operation on the channel called
\fIchannelId\fR failed because it would have otherwise caused the
\fIchannel\fR failed because it would have otherwise caused the
process to block, and returns 1 if that was the case. It returns 0
otherwise. Note that this only ever returns 1 when the channel has
been configured to be non-blocking; all Tcl channels have blocking
turned on by default.
.\" METHOD: close
.TP
\fBchan close \fIchannelId\fR ?\fIdirection\fR?
\fBchan close \fIchannel\fR ?\fIdirection\fR?
.
Close and destroy the channel called \fIchannelId\fR. Note that this
Close and destroy the channel called \fIchannel\fR. Note that this
deletes all existing file-events registered on the channel.
If the \fIdirection\fR argument (which must be \fBread\fR or \fBwrite\fR or
any unique abbreviation of them) is present, the channel will only be
half-closed, so that it can go from being read-write to write-only or
read-only respectively. If a read-only channel is closed for reading, it is
the same as if the channel is fully closed, and respectively similar for
write-only channels. Without the \fIdirection\fR argument, the channel is
closed for both reading and writing (but only if those directions are
currently open). It is an error to close a read-only channel for writing, or a
write-only channel for reading.
.RS
.PP
As part of closing the channel, all buffered output is flushed to the
channel's output device (only if the channel is ceasing to be writable), any
buffered input is discarded (only if the channel is ceasing to be readable),
the underlying operating system resource is closed and \fIchannelId\fR becomes
the underlying operating system resource is closed and \fIchannel\fR becomes
unavailable for future use (both only if the channel is being completely
closed).
.PP
If the channel is blocking and the channel is ceasing to be writable, the
command does not return until all output is flushed.  If the channel is
non-blocking and there is unflushed output, the channel remains open and the
command returns immediately; output will be flushed in the background and the
channel will be closed when all the flushing is complete.
.PP
If \fIchannelId\fR is a blocking channel for a command pipeline then
If \fIchannel\fR is a blocking channel for a command pipeline then
\fBchan close\fR waits for the child processes to complete.
.PP
If the channel is shared between interpreters, then \fBchan close\fR
makes \fIchannelId\fR unavailable in the invoking interpreter but has
makes \fIchannel\fR unavailable in the invoking interpreter but has
no other effect until all of the sharing interpreters have closed the
channel. When the last interpreter in which the channel is registered
invokes \fBchan close\fR (or \fBclose\fR), the cleanup actions
described above occur. With half-closing, the half-close of the channel only
applies to the current interpreter's view of the channel until all channels
have closed it in that direction (or completely).
See the \fBinterp\fR command for a description of channel sharing.
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
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







+
+
+
+
+
+
+
+
+
+
+

+

-
+


-
+

















+
+

-
+











+

-
+












+

-
+

-
+

-
+

+




-
-
+
+










-
+











-
-
+

-
+

-
+


-
-
-
+
-
-
-
-
-
-
-
-
-



+
+

+
+
+
+
+
+
+
+
+
+
-
+

-
+







pipeline created with \fBopen\fR returns an error, \fBchan close\fR
generates an error (similar to the \fBexec\fR command.)
.PP
Note that half-closes of sockets and command pipelines can have important side
effects because they result in a shutdown() or close() of the underlying
system resource, which can change how other processes or systems respond to
the Tcl program.
.PP
Channels are automatically closed when an interpreter is destroyed and
when the process exits.
From 8.6 on (TIP#398), nonblocking channels are no longer switched to
blocking mode when exiting; this guarantees a timely exit even when the
peer or a communication channel is stalled. To ensure proper flushing of
stalled nonblocking channels on exit, one must now either (a) actively
switch them back to blocking or (b) use the environment variable
\fBTCL_FLUSH_NONBLOCKING_ON_EXIT\fR, which when set and not equal to
.QW \fB0\fR
restores the previous behavior.
.RE
.\" METHOD: configure
.TP
\fBchan configure \fIchannelId\fR ?\fIoptionName\fR? ?\fIvalue\fR? ?\fIoptionName value\fR?...
\fBchan configure \fIchannel\fR ?\fIoptionName\fR? ?\fIvalue\fR? ?\fIoptionName value\fR?...
.
Query or set the configuration options of the channel named
\fIchannelId\fR.
\fIchannel\fR.
.RS
.PP
If no \fIoptionName\fR or \fIvalue\fR arguments are supplied, the
command returns a list containing alternating option names and values
for the channel.  If \fIoptionName\fR is supplied but no \fIvalue\fR
then the command returns the current value of the given option.  If
one or more pairs of \fIoptionName\fR and \fIvalue\fR are supplied,
the command sets each of the named options to the corresponding
\fIvalue\fR; in this case the return value is an empty string.
.PP
The options described below are supported for all channels. In
addition, each channel type may add options that only it supports. See
the manual entry for the command that creates each type of channel
for the options supported by that specific type of channel. For
example, see the manual entry for the \fBsocket\fR command for additional
options for sockets, and the \fBopen\fR command for additional options for
serial devices.
.RE
.\" OPTION: -blocking
.TP
\fB\-blocking\fR \fIboolean\fR
\fB\-blocking\fI boolean\fR
.
The \fB\-blocking\fR option determines whether I/O operations on the
channel can cause the process to block indefinitely.  The value of the
option must be a proper boolean value.  Channels are normally in
blocking mode; if a channel is placed into non-blocking mode it will
affect the operation of the \fBchan gets\fR, \fBchan read\fR, \fBchan
puts\fR, \fBchan flush\fR, and \fBchan close\fR commands; see the
documentation for those commands for details.  For non-blocking mode to
work correctly, the application must be using the Tcl event loop
(e.g. by calling \fBTcl_DoOneEvent\fR or invoking the \fBvwait\fR
command).
.\" OPTION: -buffering
.TP
\fB\-buffering\fR \fInewValue\fR
\fB\-buffering\fI newValue\fR
.
If \fInewValue\fR is \fBfull\fR then the I/O system will buffer output
until its internal buffer is full or until the \fBchan flush\fR
command is invoked. If \fInewValue\fR is \fBline\fR, then the I/O
system will automatically flush output for the channel whenever a
newline character is output. If \fInewValue\fR is \fBnone\fR, the I/O
system will flush automatically after every output operation.  The
default is for \fB\-buffering\fR to be set to \fBfull\fR except for
channels that connect to terminal-like devices; for these channels the
initial setting is \fBline\fR.  Additionally, \fBstdin\fR and
\fBstdout\fR are initially set to \fBline\fR, and \fBstderr\fR is set
to \fBnone\fR.
.\" OPTION: -buffersize
.TP
\fB\-buffersize\fR \fInewSize\fR
\fB\-buffersize\fI newSize\fR
.
\fINewvalue\fR must be an integer; its value is used to set the size
\fInewSize\fR must be an integer; its value is used to set the size
of buffers, in bytes, subsequently allocated for this channel to store
input or output. \fINewvalue\fR must be a number of no more than one
input or output. \fInewSize\fR must be a number of no more than one
million, allowing buffers of up to one million bytes in size.
.\" OPTION: -encoding
.TP
\fB\-encoding\fR \fIname\fR
.
This option is used to specify the encoding of the channel as one of
the named encodings returned by \fBencoding names\fR or the special
value \fBbinary\fR, so that the data can be converted to and from
the named encodings returned by \fBencoding names\fR, so that the
data can be converted to and from
Unicode for use in Tcl.  For instance, in order for Tcl to read
characters from a Japanese file in \fBshiftjis\fR and properly process
and display the contents, the encoding would be set to \fBshiftjis\fR.
Thereafter, when reading from the channel, the bytes in the Japanese
file would be converted to Unicode as they are read.  Writing is also
supported \- as Tcl strings are written to the channel they will
automatically be converted to the specified encoding on output.
.RS
.PP
If a file contains pure binary data (for instance, a JPEG image), the
encoding for the channel should be configured to be \fBbinary\fR.  Tcl
encoding for the channel should be configured to be \fBiso8859-1\fR.  Tcl
will then assign no interpretation to the data in the file and simply
read or write raw bytes.  The Tcl \fBbinary\fR command can be used to
manipulate this byte-oriented data.  It is usually better to set the
\fB\-translation\fR option to \fBbinary\fR when you want to transfer
binary data, as this turns off the other automatic interpretations of
the bytes in the stream as well.
.PP
The default encoding for newly opened channels is the same platform-
and locale-dependent system encoding used for interfacing with the
operating system, as returned by \fBencoding system\fR.
.RE
.TP
\fB\-eofchar\fR \fIchar\fR
.\" OPTION: -eofchar
.TP
\fB\-eofchar\fR \fB{\fIinChar outChar\fB}\fR
\fB\-eofchar\fI char\fR
.
This option supports DOS file systems that use Control-z (\ex1a) as an
This option supports DOS file systems that use Control-z (\ex1A) as an
end of file marker.  If \fIchar\fR is not an empty string, then this
character signals end-of-file when it is encountered during input.
For output, the end-of-file character is output when the channel is
closed.  If \fIchar\fR is the empty string, then there is no special
end of file character marker.  For read-write channels, a two-element
Otherwise (the default) there is no special end of file character marker.
list specifies the end of file marker for input and output,
respectively.  As a convenience, when setting the end-of-file
character for a read-write channel you can specify a single value that
will apply to both reading and writing.  When querying the end-of-file
character of a read-write channel, a two-element list will always be
returned.  The default value for \fB\-eofchar\fR is the empty string
in all cases except for files under Windows.  In that case the
\fB\-eofchar\fR is Control-z (\ex1a) for reading and the empty string
for writing.
The acceptable range for \fB\-eofchar\fR values is \ex01 - \ex7f;
attempting to set \fB\-eofchar\fR to a value outside of this range will
generate an error.
.VS "TCL8.7 TIP656"
.\" OPTION: -profile
.TP
\fB\-profile\fI profile\fR
.
Specifies the encoding profile to be used on the channel. The encoding
transforms in use for the channel's input and output will then be subject to the
rules of that profile. Any failures will result in a channel error. See
\fBPROFILES\fR in the \fBencoding(n)\fR documentation for details about encoding
profiles.
.VE "TCL8.7 TIP656"
.\" OPTION: -translation
.TP
\fB\-translation\fR \fImode\fR
\fB\-translation\fI translation\fR
.TP
\fB\-translation\fR \fB{\fIinMode outMode\fB}\fR
\fB\-translation\fR \fB{\fIinTranslation outTranslation\fB}\fR
.
In Tcl scripts the end of a line is always represented using a single
newline character (\en).  However, in actual files and devices the end
of a line may be represented differently on different platforms, or
even for different devices on the same platform.  For example, under
UNIX newlines are used in files, whereas carriage-return-linefeed
sequences are normally used in network connections.  On input (i.e.,
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
366
367
368
369
370
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







-
-
+
-










-
-
+
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-





-
-
+
-







-
-
+
-





-
+



-
-
-
+
+
+
-
-
-
+
+


-
-
-
-
+
-
-
-
-
-

-
-
-
+
+
-
-
-
+
+
-
-
-
+
+
-
-
+

+
-
-
-
+
+
+
+
+
+
-
-
-
+
+

-
+
-
-
-
-
+
+
+
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

+


















-
+







read-write channels; the read translation mode is the first element of
the list, and the write translation mode is the second element.  As a
convenience, when setting the translation mode for a read-write channel
you can specify a single value that will apply to both reading and
writing.  When querying the translation mode of a read-write channel, a
two-element list will always be returned.  The following values are
currently supported:
.TP
\fBauto\fR
.IP \fBauto\fR
.
As the input translation mode, \fBauto\fR treats any of newline
(\fBlf\fR), carriage return (\fBcr\fR), or carriage return followed by
a newline (\fBcrlf\fR) as the end of line representation.  The end of
line representation can even change from line-to-line, and all cases
are translated to a newline.  As the output translation mode,
\fBauto\fR chooses a platform specific representation; for sockets on
all platforms Tcl chooses \fBcrlf\fR, for all Unix flavors, it chooses
\fBlf\fR, and for the various flavors of Windows it chooses
\fBcrlf\fR.  The default setting for \fB\-translation\fR is \fBauto\fR
for both input and output.
.TP
\fBbinary\fR
.IP \fBbinary\fR
.
No end-of-line translations are performed.  This is nearly identical
Like \fBlf\fR, no end-of-line translation is performed, but in addition, sets
to \fBlf\fR mode, except that in addition \fBbinary\fR mode also sets
the end-of-file character to the empty string (which disables it) and
sets the encoding to \fBbinary\fR (which disables encoding filtering).
See the description of \fB\-eofchar\fR and \fB\-encoding\fR for more
information.
.TP
\fBcr\fR
\fB\-eofchar\fR to the empty string to disable it, and sets \fB\-encoding\fR
to \fBiso8859-1\fR.  With this one setting, a channel is fully configured
for binary input and output:  Each byte read from the channel
becomes the Unicode character having the same value as that byte, and each
character written to the channel becomes a single byte in the output.  This
makes it possible to work seamlessly with binary data as long as each character
in the data remains in the range of 0 to 255 so that there is no distinction
between binary data and text.  For example, A JPEG image can be read from a
such a channel, manipulated, and then written back to such a channel.
.IP \fBcr\fR
.
The end of a line in the underlying file or device is represented by a
single carriage return character.  As the input translation mode,
\fBcr\fR mode converts carriage returns to newline characters.  As the
output translation mode, \fBcr\fR mode translates newline characters
to carriage returns.
.TP
\fBcrlf\fR
.IP \fBcrlf\fR
.
The end of a line in the underlying file or device is represented by a
carriage return character followed by a linefeed character.  As the
input translation mode, \fBcrlf\fR mode converts
carriage-return-linefeed sequences to newline characters.  As the
output translation mode, \fBcrlf\fR mode translates newline characters
to carriage-return-linefeed sequences.  This mode is typically used on
Windows platforms and for network connections.
.TP
\fBlf\fR
.IP \fBlf\fR
.
The end of a line in the underlying file or device is represented by a
single newline (linefeed) character.  In this mode no translations
occur during either input or output.  This mode is typically used on
UNIX platforms.
.RE
.RE
.\" METHOD: copy
.TP
\fBchan copy \fIinputChan outputChan\fR ?\fB\-size \fIsize\fR? ?\fB\-command \fIcallback\fR?
.
Copy data from the channel \fIinputChan\fR, which must have been
opened for reading, to the channel \fIoutputChan\fR, which must have
been opened for writing. The \fBchan copy\fR command leverages the
Reads characters from \fIinputChan\fR and writes them to \fIoutputChan\fR until
all characters are copied, blocking until the copy is complete and returning
the number of characters copied.  Leverages internal buffers to avoid extra
buffering in the Tcl I/O system to avoid extra copies and to avoid
buffering too much data in main memory when copying large files to
slow destinations like network sockets.
copies and to avoid buffering too much data in main memory when copying large
files to slow destinations like network sockets.
.RS
.PP
The \fBchan copy\fR command transfers data from \fIinputChan\fR until
end of file or \fIsize\fR bytes or characters have been transferred;
\fIsize\fR is in bytes if the two channels are using the same encoding,
and is in characters otherwise.  If no \fB\-size\fR argument is given,
\fB\-size\fR limits the number of characters copied.
then the copy goes until end of file. All the data read from
\fIinputChan\fR is copied to \fIoutputChan\fR.  Without the
\fB\-command\fR option, \fBchan copy\fR blocks until the copy is
complete and returns the number of bytes or characters (using the same
rules as for the \fB\-size\fR option) written to \fIoutputChan\fR.
.PP
The \fB\-command\fR argument makes \fBchan copy\fR work in the
background.  In this case it returns immediately and the
\fIcallback\fR is invoked later when the copy completes.  The
If \fB\-command\fR is given, \fBchan copy\fR returns immediately, works in the
background, and calls \fIcallback\fR when the copy completes, providing as an
\fIcallback\fR is called with one or two additional arguments that
indicates how many bytes were written to \fIoutputChan\fR.  If an
error occurred during the background copy, the second argument is the
additional argument the number of characters written to \fIoutputChan\fR.  If
an error occurs during the background copy, another argument provides message
error string associated with the error.  With a background copy, it is
not necessary to put \fIinputChan\fR or \fIoutputChan\fR into
non-blocking mode; the \fBchan copy\fR command takes care of that
for the error.  \fIinputChan\fR and \fIoutputChan\fR are automatically
configured for non-blocking mode if needed.  Background copying only works
automatically.  However, it is necessary to enter the event loop by
using the \fBvwait\fR command or by using Tk.
correctly if events are being processed, e.g. via \fBvwait\fR or Tk.
.PP
During a background copy no other read operation may be performed on
You are not allowed to do other I/O operations with \fIinputChan\fR or
\fIoutputChan\fR during a background \fBchan copy\fR.  If either
\fIinputChan\fR or \fIoutputChan\fR get closed while the copy is in
\fIinputChan\fR, and no write operation may be performed on
\fIoutputChan\fR.  However, write operations may by performed on
\fIinputChan\fR and read operations may be performed on \fIoutputChan\fR, as
exhibited by the bidirectional copy example below.
.PP
If either \fIinputChan\fR or \fIoutputChan\fR is closed while the copy is in
progress, the current copy is stopped and the command callback is
\fInot\fR made.  If \fIinputChan\fR is closed, then all data already
queued for \fIoutputChan\fR is written out.
progress, copying ceases and \fBno\fR callback is made.  If \fIinputChan\fR is
closed all data already queued is written to \fIoutputChan\fR.
.PP
Note that \fIinputChan\fR can become readable during a background
There should be no event handler established for \fIinputChan\fR  because it
copy.  You should turn off any \fBchan event\fR or \fBfileevent\fR
handlers during a background copy so those handlers do not interfere
with the copy.  Any I/O attempted by a \fBchan event\fR or
\fBfileevent\fR handler will get a
may become readable during a background copy.  An attempt to read or write from
within an event handler results result in the error,  "channel busy".  Any
wrong-sided I/O attempted (by a \fBchan event\fR handler or otherwise) results
in a
.QW "channel busy"
error.
.PP
\fBChan copy\fR translates end-of-line sequences in \fIinputChan\fR
and \fIoutputChan\fR according to the \fB\-translation\fR option for
these channels (see \fBchan configure\fR above).  The translations
mean that the number of bytes read from \fIinputChan\fR can be
different than the number of bytes written to \fIoutputChan\fR.  Only
the number of bytes written to \fIoutputChan\fR is reported, either as
the return value of a synchronous \fBchan copy\fR or as the argument
to the callback for an asynchronous \fBchan copy\fR.
.PP
\fBChan copy\fR obeys the encodings and character translations
configured for the channels. This means that the incoming characters
are converted internally first UTF-8 and then into the encoding of the
channel \fBchan copy\fR writes to (see \fBchan configure\fR above for
details on the \fB\-encoding\fR and \fB\-translation\fR options). No
conversion is done if both channels are set to encoding \fBbinary\fR
and have matching translations. If only the output channel is set to
encoding \fBbinary\fR the system will write the internal UTF-8
representation of the incoming characters. If only the input channel
is set to encoding \fBbinary\fR the system will assume that the
incoming bytes are valid UTF-8 characters and convert them according
to the output encoding. The behaviour of the system for bytes which
are not valid UTF-8 characters is undefined in this case.
.RE
.\" METHOD: create
.TP
\fBchan create \fImode cmdPrefix\fR
.
This subcommand creates a new script level channel using the command
prefix \fIcmdPrefix\fR as its handler. Any such channel is called a
\fBreflected\fR channel. The specified command prefix, \fBcmdPrefix\fR,
must be a non-empty list, and should provide the API described in the
\fBrefchan\fR manual page. The handle of the new channel is
returned as the result of the \fBchan create\fR command, and the
channel is open. Use either \fBclose\fR or \fBchan close\fR to remove
the channel.
.RS
.PP
The argument \fImode\fR specifies if the new channel is opened for
reading, writing, or both. It has to be a list containing any of the
strings
.QW \fBread\fR
or
.QW \fBwrite\fR .
.QW \fBwrite\fR ,
The list must have at least one
element, as a channel you can neither write to nor read from makes no
sense. The handler command for the new channel must support the chosen
mode, or an error is thrown.
.PP
The command prefix is executed in the global namespace, at the top of
call stack, following the appending of arguments as described in the
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
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







+

-
+


-
+

+

-
+



-
+




















-
+
+







handles.
.PP
This subcommand is \fBsafe\fR and made accessible to safe
interpreters.  While it arranges for the execution of arbitrary Tcl
code the system also makes sure that the code is always executed
within the safe interpreter.
.RE
.\" METHOD: eof
.TP
\fBchan eof \fIchannelId\fR
\fBchan eof \fIchannel\fR
.
Test whether the last input operation on the channel called
\fIchannelId\fR failed because the end of the data stream was reached,
\fIchannel\fR failed because the end of the data stream was reached,
returning 1 if end-of-file was reached, and 0 otherwise.
.\" METHOD: event
.TP
\fBchan event \fIchannelId event\fR ?\fIscript\fR?
\fBchan event \fIchannel event\fR ?\fIscript\fR?
.
Arrange for the Tcl script \fIscript\fR to be installed as a \fIfile
event handler\fR to be called whenever the channel called
\fIchannelId\fR enters the state described by \fIevent\fR (which must
\fIchannel\fR enters the state described by \fIevent\fR (which must
be either \fBreadable\fR or \fBwritable\fR); only one such handler may
be installed per event per channel at a time.  If \fIscript\fR is the
empty string, the current handler is deleted (this also happens if the
channel is closed or the interpreter deleted).  If \fIscript\fR is
omitted, the currently installed script is returned (or an empty
string if no such handler is installed).  The callback is only
performed if the event loop is being serviced (e.g. via \fBvwait\fR or
\fBupdate\fR).
.RS
.PP
A file event handler is a binding between a channel and a script, such
that the script is evaluated whenever the channel becomes readable or
writable.  File event handlers are most commonly used to allow data to
be received from another process on an event-driven basis, so that the
receiver can continue to interact with the user or with other channels
while waiting for the data to arrive.  If an application invokes
\fBchan gets\fR or \fBchan read\fR on a blocking channel when there is
no input data available, the process will block; until the input data
arrives, it will not be able to service other events, so it will
appear to the user to
.QW "freeze up" .
.QW "freeze up"
\&.
With \fBchan event\fR, the
process can tell when data is present and only invoke \fBchan gets\fR
or \fBchan read\fR when they will not block.
.PP
A channel is considered to be readable if there is unread data
available on the underlying device.  A channel is also considered to
be readable if there is unread data in an input buffer, except in the
478
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
558

559
560
561
562




563
564
565

566
567

568
569
570
571

572
573
574
575
576
577
578
462
463
464
465
466
467
468
469
470

471
472

473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582



583
584
585
586
587
588
589
590
591

592
593
594
595

596
597
598
599
600
601
602
603







+

-
+

-
+










+

-
+

-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+






+

-
+




-
+




+


+




















+

-
-
-
+
+
+
+



+

-
+



-
+







context of any Tcl procedure) in the interpreter in which the \fBchan
event\fR command was invoked.  If an error occurs while executing the
script then the command registered with \fBinterp bgerror\fR is used
to report the error.  In addition, the file event handler is deleted
if it ever returns an error; this is done in order to prevent infinite
loops due to buggy handlers.
.RE
.\" METHOD: flush
.TP
\fBchan flush \fIchannelId\fR
\fBchan flush \fIchannel\fR
.
Ensures that all pending output for the channel called \fIchannelId\fR
Ensures that all pending output for the channel called \fIchannel\fR
is written.
.RS
.PP
If the channel is in blocking mode the command does not return until
all the buffered output has been flushed to the channel. If the
channel is in non-blocking mode, the command may return before all
buffered output has been flushed; the remainder will be flushed in the
background as fast as the underlying file or device is able to absorb
it.
.RE
.\" METHOD: gets
.TP
\fBchan gets \fIchannelId\fR ?\fIvarName\fR?
\fBchan gets \fIchannel\fR ?\fIvarName\fR?
.
Reads the next line from the channel called \fIchannelId\fR. If
Reads a line from the channel consisting of all characters up to the next
\fIvarName\fR is not specified, the result of the command will be the
line that has been read (without a trailing newline character) or an
empty string upon end-of-file or, in non-blocking mode, if the data
available is exhausted. If \fIvarName\fR is specified, the line that
has been read will be written to the variable called \fIvarName\fR and
result will be the number of characters that have been read or -1 if
end-of-file was reached or, in non-blocking mode, if the data
available is exhausted.
end-of-line sequence or until end of file is seen. The line feed character
corresponding to end-of-line sequence is not included as part of the line.
If the \fIvarName\fR argument is specified, the line is stored in the variable
of that name and the command returns the length of the line. If \fIvarName\fR
is not specified, the command returns the line itself as the result of the command.
.RS
.PP
If a complete line is not available and the channel is not at EOF, the command
will block in the case of a blocking channel. For non-blocking channels, the
command will return the empty string as the result in the case of \fIvarName\fR
not specified and -1 if it is.
.RE
.RS
.PP
If an end-of-file occurs while part way through reading a line, the
partial line will be returned (or written into \fIvarName\fR). When
\fIvarName\fR is not specified, the end-of-file case can be
distinguished from an empty line using the \fBchan eof\fR command, and
the partial-line-but-non-blocking case can be distinguished with the
\fBchan blocked\fR command.
If a blocking channel is already at EOF, the command returns an empty string if
\fIvarName\fR is not specified. Note an empty string result can also be returned
when a blank line (no characters before the next end of line sequence). The two
cases can be distinguished by calling the \fBchan eof\fR command to check for
end of file. If \fIvarName\fR is specified, the command returns -1 on end of file.
There is no ambiguity in this case because blank lines result in 0 being returned.
.RE
.RS
.PP
If a non-blocking channel is already at EOF, the command returns an empty line
if \fIvarName\fR is not specified. This can be distinguished from an empty line
being returned by either a blank line being read or a full line not being available
through the use of the \fBchan eof\fR and \fBchan blocked\fR commands. If
\fBchan eof\fR returns true, the channel is at EOF. If \fBchan blocked\fR returns
true, a full line was not available. If both commands return false, an empty
line was read. If \fIvarName\fR was specified for a non-bocking channel at EOF,
the command returns -1. This can be distinguished from full line not being
available either by \fBchan eof\fR or \fBchan blocked\fR as above. Note that
when \fIvarName\fR is specified, there is no need to distinguish between eof
and blank lines as the latter will result in the command returning 0.
.PP
If the encoding profile \fBstrict\fR is in effect for the channel, the command
will raise an exception with the POSIX error code \fBEILSEQ\fR if any encoding
errors are encountered in the channel input data. The file pointer remains
unchanged and it is possible to introspect, and in some cases recover, by
changing the encoding in use. See \fBENCODING ERROR EXAMPLES\fR later.
.RE
.\" METHOD: isbinary
.TP
\fBchan isbinary \fIchannel\fR
.
Test whether the channel called \fIchannel\fR is a binary channel,
returning 1 if it is and, and 0 otherwise. A binary channel is
a channel with iso8859-1 encoding, -eofchar set to {} and
-translation set to lf.
.\" METHOD: names
.TP
\fBchan names\fR ?\fIpattern\fR?
.
Produces a list of all channel names. If \fIpattern\fR is specified,
only those channel names that match it (according to the rules of
\fBstring match\fR) will be returned.
.\" METHOD: pending
.TP
\fBchan pending \fImode channelId\fR
\fBchan pending \fImode channel\fR
.
Depending on whether \fImode\fR is \fBinput\fR or \fBoutput\fR,
returns the number of
bytes of input or output (respectively) currently buffered
internally for \fIchannelId\fR (especially useful in a readable event
internally for \fIchannel\fR (especially useful in a readable event
callback to impose application-specific limits on input line lengths to avoid
a potential denial-of-service attack where a hostile user crafts
an extremely long line that exceeds the available memory to buffer it).
Returns -1 if the channel was not opened for the mode in question.
.\" METHOD: pipe
.TP
\fBchan pipe\fR
.
Creates a standalone pipe whose read- and write-side channels are
returned as a 2-element list, the first element being the read side and
the second the write side. Can be useful e.g. to redirect
separately \fBstderr\fR and \fBstdout\fR from a subprocess. To do
this, spawn with "2>@" or
">@" redirection operators onto the write side of a pipe, and then
immediately close it in the parent. This is necessary to get an EOF on
the read side once the child has exited or otherwise closed its output.
.RS
.PP
Note that the pipe buffering semantics can vary at the operating system level
substantially; it is not safe to assume that a write performed on the output
side of the pipe will appear instantly to the input side. This is a
fundamental difference and Tcl cannot conceal it. The overall stream semantics
\fIare\fR compatible, so blocking reads and writes will not see most of the
differences, but the details of what exactly gets written when are not. This
is most likely to show up when using pipelines for testing; care should be
taken to ensure that deadlocks do not occur and that potential short reads are
allowed for.
.RE
.\" METHOD: pop
.TP
\fBchan pop \fIchannelId\fR
Removes the topmost transformation from the channel \fIchannelId\fR, if there
is any. If there are no transformations added to \fIchannelId\fR, this is
\fBchan pop \fIchannel\fR
.
Removes the topmost transformation from the channel \fIchannel\fR, if there
is any. If there are no transformations added to \fIchannel\fR, this is
equivalent to \fBchan close\fR of that channel. The result is normally the
empty string, but can be an error in some situations (i.e. where the
underlying system stream is closed and that results in an error).
.\" METHOD: postevent
.TP
\fBchan postevent \fIchannelId eventSpec\fR
\fBchan postevent \fIchannel eventSpec\fR
.
This subcommand is used by command handlers specified with \fBchan
create\fR. It notifies the channel represented by the handle
\fIchannelId\fR that the event(s) listed in the \fIeventSpec\fR have
\fIchannel\fR that the event(s) listed in the \fIeventSpec\fR have
occurred. The argument has to be a list containing any of the strings
\fBread\fR and \fBwrite\fR. The list must contain at least one
element as it does not make sense to invoke the command if there are
no events to post.
.RS
.PP
Note that this subcommand can only be used with channel handles that
595
596
597
598
599
600
601

602
603
604



605
606
607
608
609
610
611

612
613

614
615

616
617

618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637

638
639
640
641
642
643
644
645
646
647
648
649





650

651
652

653
654

655
656
657

658
659
660
661
662
663
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

707
708
709

710
711
712
713
714

715
716
717
718
719

720
721
722
723
724
725

726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743

744
745

746
747
748

749
750
751
752

753
754

755
756
757

758
759
760
761

762







763
764
765



766
767
768
769
770
771
772
620
621
622
623
624
625
626
627
628


629
630
631
632
633
634
635
636
637
638
639
640

641
642

643
644

645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718

719
720
721
722
723
724
725
726

727
728
729
730
731

732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755

756
757
758

759
760
761
762


763

764
765


766

767
768
769


770

771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789

790
791
792

793
794
795
796
797
798
799

800
801
802

803
804
805
806
807
808
809
810
811
812
813
814
815
816



817
818
819
820
821
822
823
824
825
826







+

-
-
+
+
+







+

-
+

-
+

-
+



















-
+












+
+
+
+
+

+

-
+

-
+


-
+








-
+


















-
+







-
+




-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+

-
+


-
+



-
-
+
-


-
-
+
-



-
-
+
-

















+

-
+


-
+




+

-
+


-
+




+

+
+
+
+
+
+
+
-
-
-
+
+
+







This command is \fBsafe\fR and made accessible to safe interpreters.
It can trigger the execution of \fBchan event\fR handlers, whether in the
current interpreter or in other interpreters or other threads, even
where the event is posted from a safe interpreter and listened for by
a trusted interpreter. \fBChan event\fR handlers are \fIalways\fR
executed in the interpreter that set them up.
.RE
.\" METHOD: push
.TP
\fBchan push \fIchannelId cmdPrefix\fR
Adds a new transformation on top of the channel \fIchannelId\fR. The
\fBchan push \fIchannel cmdPrefix\fR
.
Adds a new transformation on top of the channel \fIchannel\fR. The
\fIcmdPrefix\fR argument describes a list of one or more words which represent
a handler that will be used to implement the transformation. The command
prefix must provide the API described in the \fBtranschan\fR manual page.
The result of this subcommand is a handle to the transformation. Note that it
is important to make sure that the transformation is capable of supporting the
channel mode that it is used with or this can make the channel neither
readable nor writable.
.\" METHOD: puts
.TP
\fBchan puts\fR ?\fB\-nonewline\fR? ?\fIchannelId\fR? \fIstring\fR
\fBchan puts\fR ?\fB\-nonewline\fR? ?\fIchannel\fR? \fIstring\fR
.
Writes \fIstring\fR to the channel named \fIchannelId\fR followed by a
Writes \fIstring\fR to the channel named \fIchannel\fR followed by a
newline character. A trailing newline character is written unless the
optional flag \fB\-nonewline\fR is given. If \fIchannelId\fR is
optional flag \fB\-nonewline\fR is given. If \fIchannel\fR is
omitted, the string is written to the standard output channel,
\fBstdout\fR.
.RS
.PP
Newline characters in the output are translated by \fBchan puts\fR to
platform-specific end-of-line sequences according to the currently
configured value of the \fB\-translation\fR option for the channel
(for example, on PCs newlines are normally replaced with
carriage-return-linefeed sequences; see \fBchan configure\fR above for
details).
.PP
Tcl buffers output internally, so characters written with \fBchan
puts\fR may not appear immediately on the output file or device; Tcl
will normally delay output until the buffer is full or the channel is
closed.  You can force output to appear immediately with the \fBchan
flush\fR command.
.PP
When the output buffer fills up, the \fBchan puts\fR command will
normally block until all the buffered data has been accepted for
output by the operating system.  If \fIchannelId\fR is in non-blocking
output by the operating system.  If \fIchannel\fR is in non-blocking
mode then the \fBchan puts\fR command will not block even if the
operating system cannot accept the data.  Instead, Tcl continues to
buffer the data and writes it in the background as fast as the
underlying file or device can accept it.  The application must use the
Tcl event loop for non-blocking output to work; otherwise Tcl never
finds out that the file or device is ready for more output data.  It
is possible for an arbitrarily large amount of data to be buffered for
a channel in non-blocking mode, which could consume a large amount of
memory.  To avoid wasting memory, non-blocking I/O should normally be
used in an event-driven fashion with the \fBchan event\fR command
(do not invoke \fBchan puts\fR unless you have recently been notified
via a file event that the channel is ready for more output data).
.PP
The command will raise an error exception with POSIX error code \fBEILSEQ\fR if
the encoding profile \fBstrict\fR is in effect for the channel and the output
data cannot be encoded in the encoding configured for the channel. Data
may be partially written to the channel in this case.
.RE
.\" METHOD: read
.TP
\fBchan read \fIchannelId\fR ?\fInumChars\fR?
\fBchan read \fIchannel\fR ?\fInumChars\fR?
.TP
\fBchan read \fR?\fB\-nonewline\fR? \fIchannelId\fR
\fBchan read \fR?\fB\-nonewline\fR? \fIchannel\fR
.
In the first form, the result will be the next \fInumChars\fR
characters read from the channel named \fIchannelId\fR; if
characters read from the channel named \fIchannel\fR; if
\fInumChars\fR is omitted, all characters up to the point when the
channel would signal a failure (whether an end-of-file, blocked or
other error condition) are read. In the second form (i.e. when
\fInumChars\fR has been omitted) the flag \fB\-nonewline\fR may be
given to indicate that any trailing newline in the string that has
been read should be trimmed.
.RS
.PP
If \fIchannelId\fR is in non-blocking mode, \fBchan read\fR may not
If \fIchannel\fR is in non-blocking mode, \fBchan read\fR may not
read as many characters as requested: once all available input has
been read, the command will return the data that is available rather
than blocking for more input.  If the channel is configured to use a
multi-byte encoding, then there may actually be some bytes remaining
in the internal buffers that do not form a complete character.  These
bytes will not be returned until a complete character is available or
end-of-file is reached.  The \fB\-nonewline\fR switch is ignored if
the command returns before reaching the end of the file.
.PP
\fBChan read\fR translates end-of-line sequences in the input into
newline characters according to the \fB\-translation\fR option for the
channel (see \fBchan configure\fR above for a discussion on the ways
in which \fBchan configure\fR will alter input).
.PP
When reading from a serial port, most applications should configure
the serial port channel to be non-blocking, like this:
.PP
.CS
\fBchan configure \fIchannelId \fB\-blocking \fI0\fR.
\fBchan configure \fIchannel \fB\-blocking \fI0\fR.
.CE
.PP
Then \fBchan read\fR behaves much like described above.  Note that
most serial ports are comparatively slow; it is entirely possible to
get a \fBreadable\fR event for each character read from them. Care
must be taken when using \fBchan read\fR on blocking serial ports:
.TP
\fBchan read \fIchannelId numChars\fR
\fBchan read \fIchannel numChars\fR
.
In this form \fBchan read\fR blocks until \fInumChars\fR have been
received from the serial port.
.TP
\fBchan read \fIchannelId\fR
\fBchan read \fIchannel\fR
.
In this form \fBchan read\fR blocks until the reception of the
end-of-file character, see \fBchan configure -eofchar\fR. If there no
end-of-file character has been configured for the channel, then
\fBchan read\fR will block forever.
.PP
If the encoding profile \fBstrict\fR is in effect for the channel, the command
will raise an exception with the POSIX error code \fBEILSEQ\fR if any encoding
errors are encountered in the channel input data. If the channel is in blocking
mode, the error is thrown after advancing the file pointer to the beginning of
the invalid data. The successfully decoded leading portion of the data prior to
the error location is returned as the value of the \fB\-data\fR key of the error
option dictionary. If the channel is in non-blocking mode, the successfully
decoded portion of data is returned by the command without an error
exception being raised. A subsequent read will start at the invalid data
and immediately raise a \fBEILSEQ\fR POSIX error exception. Unlike the
blocking channel case, the \fB\-data\fR key is not present in the
error option dictionary. In the case of exception thrown due to encoding
errors, it is possible to introspect, and in some cases recover, by
changing the encoding in use. See \fBENCODING ERROR EXAMPLES\fR later.
.RE
.\" METHOD: seek
.TP
\fBchan seek \fIchannelId offset\fR ?\fIorigin\fR?
\fBchan seek \fIchannel offset\fR ?\fIorigin\fR?
.
Sets the current access position within the underlying data stream for
the channel named \fIchannelId\fR to be \fIoffset\fR bytes relative to
the channel named \fIchannel\fR to be \fIoffset\fR bytes relative to
\fIorigin\fR. \fIOffset\fR must be an integer (which may be negative)
and \fIorigin\fR must be one of the following:
.RS
.TP 10
\fBstart\fR
.IP \fBstart\fR
.
The new access position will be \fIoffset\fR bytes from the start
of the underlying file or device.
.TP 10
\fBcurrent\fR
.IP \fBcurrent\fR
.
The new access position will be \fIoffset\fR bytes from the current
access position; a negative \fIoffset\fR moves the access position
backwards in the underlying file or device.
.TP 10
\fBend\fR
.IP \fBend\fR
.
The new access position will be \fIoffset\fR bytes from the end of the
file or device.  A negative \fIoffset\fR places the access position
before the end of file, and a positive \fIoffset\fR places the access
position after the end of file.
.PP
The \fIorigin\fR argument defaults to \fBstart\fR.
.PP
\fBChan seek\fR flushes all buffered output for the channel before the
command returns, even if the channel is in non-blocking mode.  It also
discards any buffered and unread input.  This command returns an empty
string.  An error occurs if this command is applied to channels whose
underlying file or device does not support seeking.
.PP
Note that \fIoffset\fR values are byte offsets, not character offsets.
Both \fBchan seek\fR and \fBchan tell\fR operate in terms of bytes,
not characters, unlike \fBchan read\fR.
.RE
.\" METHOD: tell
.TP
\fBchan tell \fIchannelId\fR
\fBchan tell \fIchannel\fR
.
Returns a number giving the current access position within the
underlying data stream for the channel named \fIchannelId\fR. This
underlying data stream for the channel named \fIchannel\fR. This
value returned is a byte offset that can be passed to \fBchan seek\fR
in order to set the channel to a particular position.  Note that this
value is in terms of bytes, not characters like \fBchan read\fR.  The
value returned is -1 for channels that do not support seeking.
.\" METHOD: truncate
.TP
\fBchan truncate \fIchannelId\fR ?\fIlength\fR?
\fBchan truncate \fIchannel\fR ?\fIlength\fR?
.
Sets the byte length of the underlying data stream for the channel
named \fIchannelId\fR to be \fIlength\fR (or to the current byte
named \fIchannel\fR to be \fIlength\fR (or to the current byte
offset within the underlying data stream if \fIlength\fR is
omitted). The channel is flushed before truncation.
.
.SH EXAMPLES
.SS "SIMPLE CHANNEL OPERATION EXAMPLES"
.PP
Instruct Tcl to always send output to \fBstdout\fR immediately,
whether or not it is to a terminal:
.PP
.CS
\fBfconfigure\fR stdout -buffering none
.CE
.PP
This opens a file using a known encoding (CP1252, a very common encoding
on Windows), searches for a string, rewrites that part, and truncates the
file after a further two lines.
In the following example a file is opened using the encoding CP1252, which is
common on Windows, searches for a string, rewrites that part, and truncates the
file two lines later.
.PP
.CS
set f [open somefile.txt r+]
\fBchan configure\fR $f -encoding cp1252
set offset 0

\fI# Search for string "FOOBAR" in the file\fR
789
790
791
792
793
794
795





























































796
797


798
799
800
801
802
803
804
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910


911
912
913
914
915
916
917
918
919







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+








    \fI# Save offset of start of next line for later\fR
    set offset [\fBchan tell\fR $f]
}
\fBchan close\fR $f
.CE
.PP
This example illustrates flushing of a channel. The user is
prompted for some information. Because the standard input channel
is line buffered, it must be flushed for the user to see the prompt.
.PP
.CS
chan puts -nonewline "Please type your name: "
\fBchan flush\fR stdout
chan gets stdin name
chan puts "Hello there, $name!"
.CE
.PP
This example reads a file one line at a time and prints it out with
the current line number attached to the start of each line.
.PP
.CS
set chan [open "some.file.txt"]
set lineNumber 0
while {[\fBchan gets\fR $chan line] >= 0} {
    chan puts "[incr lineNumber]: $line"
}
chan close $chan
.CE
.PP
In this example illustrating event driven reads,
\fBGetData\fR will be called with the channel as an
argument whenever $chan becomes readable. The \fBread\fR call will
read whatever binary data is currently available without blocking.
Here the channel has the fileevent removed when an end of file
occurs to avoid being continually called (see above). Alternatively
the channel may be closed on this condition.
.PP
.CS
proc GetData {chan} {
    set data [chan read $chan]
    chan puts "[string length $data] $data"
    if {[chan eof $chan]} {
        chan event $chan readable {}
    }
}

chan configure $chan -blocking 0 -translation binary
\fBchan event\fR $chan readable [list GetData $chan]
.CE
.PP
The next example is similar but uses \fBchan gets\fR to read
line-oriented data.
.PP
.CS
proc GetData {chan} {
    if {[chan gets $chan line] >= 0} {
        chan puts $line
    }
    if {[chan eof $chan]} {
        chan close $chan
    }
}

chan configure $chan -blocking 0 -buffering line -translation crlf
\fBchan event\fR $chan readable [list GetData $chan]
.CE
.PP
A network server that does echoing of its input line-by-line without
preventing servicing of other connections at the same time.
A network server that echoes its input line-by-line without
preventing servicing of other connections at the same time:
.PP
.CS
# This is a very simple logger...
proc log {message} {
    \fBchan puts\fR stdout $message
}

825
826
827
828
829
830
831











































































































































































































































832
833
834
835


836

837

838
839
840
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184

1185
1186
1187
1188

1189
1190
1191
1192







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+
+

+
-
+



}

# Create the server socket and enter the event-loop to wait
# for incoming connections...
socket -server connect 12345
vwait forever
.CE
.PP
The following example reads a PPM-format image from a file
combining ASCII and binary content.
.PP
.CS
# Open the file and put it into Unix ASCII mode
set f [open teapot.ppm]
\fBchan configure\fR $f -encoding ascii -translation lf

# Get the header
if {[chan gets $f] ne "P6"} {
    error "not a raw\-bits PPM"
}

# Read lines until we have got non-comment lines
# that supply us with three decimal values.
set words {}
while {[llength $words] < 3} {
    chan gets $f line
    if {[string match "#*" $line]} continue
    lappend words {*}[join [scan $line %d%d%d]]
}

# Those words supply the size of the image and its
# overall depth per channel. Assign to variables.
lassign $words xSize ySize depth

# Now switch to binary mode to pull in the data,
# one byte per channel (red,green,blue) per pixel.
\fBchan configure\fR $f -translation binary
set numDataBytes [expr {3 * $xSize * $ySize}]
set data [chan read $f $numDataBytes]

close $f
.CE
.SS "FILE SEEK EXAMPLES"
.PP
Read a file twice:
.PP
.CS
set f [open file.txt]
set data1 [chan read $f]
\fBchan seek\fR $f 0
set data2 [chan read $f]
chan close $f
# $data1 eq $data2 if the file wasn't updated
.CE
.PP
Read the last 10 bytes from a file:
.PP
.CS
set f [open file.data]
# This is guaranteed to work with binary data but
# may fail with other encodings...
chan configure $f -translation binary
\fBchan seek\fR $f -10 end
set data [chan read $f 10]
chan close $f
.CE
.PP
Read a line from a file channel only if it starts with \fBfoobar\fR:
.PP
.CS
# Save the offset in case we need to undo the read...
set offset [\fBtell\fR $chan]
if {[read $chan 6] eq "foobar"} {
    gets $chan line
} else {
    set line {}
    # Undo the read...
    seek $chan $offset
}
.CE
.SS "ENCODING ERROR EXAMPLES"
.PP
The example below illustrates handling of an encoding error encountered
during channel input. First, creation of a test file containing
the invalid UTF-8 sequence (\fBA \\xC3 B\fR):
.PP
.CS
% set f [open test_A_195_B.txt wb]; chan puts -nonewline $f A\\xC3B; chan close $f
.CE
.PP
An attempt to read the file will result in an encoding error which is
then introspected by switching the channel to binary mode. Note in the
example that when the error is reported the file position remains
unchanged so that the \fBchan gets\fR during recovery returns the
full line.
.PP
.CS
% set f [open test_A_195_B.txt r]
file384b6a8
% chan configure $f -encoding utf-8
% catch {chan gets $f} e d
1
% set d
-code 1 -level 0
-errorstack {INNER {invokeStk1 gets file384b6a8}}
-errorcode {POSIX EILSEQ {invalid or incomplete multibyte or wide character}}
-errorinfo {...} -errorline 1
% chan tell $f
0
% chan configure $f -translation binary
% chan gets $f
AÃB
.CE
.PP
The following example is similar to the above but demonstrates recovery after a
blocking read. The successfully decoded data "A" is returned in the error options
dictionary key \fB\-data\fR. The file position is advanced on the encoding error
position 1. The data at the error position is thus recovered by the next
\fBchan read\fR command.
.PP
.CS
% set f [open test_A_195_B.txt r]
file35a65a0
% chan configure $f -encoding utf-8 -blocking 1
% catch {chan read $f} e d
1
% set d
-data A -code 1 -level 0
-errorstack {INNER {invokeStk1 read file35a65a0}}
-errorcode {POSIX EILSEQ {invalid or incomplete multibyte or wide character}}
-errorinfo {...} -errorline 1
% chan tell $f
1
% chan configure $f -translation binary
% chan read $f
ÃB
% chan close $f
.CE
.PP
Finally the same example, but this time with a non-blocking channel.
.PP
.CS
% set f [open test_A_195_B.txt r]
file35a65a0
% chan configure $f -encoding utf-8 -blocking 0
% chan read $f
A
% chan tell $f
1
% catch {chan read $f} e d
1
% set d
-code 1 -level 0
-errorstack {INNER {invokeStk1 read file384b228}}
-errorcode {POSIX EILSEQ {invalid or incomplete multibyte or wide character}}
-errorinfo {...} -errorline 1
.CE

.SS "CHANNEL COPY EXAMPLES"
.PP
The first example transfers the contents of one channel exactly to
another. Note that when copying one file to another, it is better to
use \fBfile copy\fR which also copies file metadata (e.g. the file
access permissions) where possible.
.PP
.CS
\fBchan configure\fR $in -translation binary
\fBchan configure\fR $out -translation binary
\fBchan copy\fR $in $out
.CE
.PP
This second example shows how the callback gets
passed the number of bytes transferred.
It also uses vwait to put the application into the event loop.
Of course, this simplified example could be done without the command
callback.
.PP
.CS
proc Cleanup {in out bytes {error {}}} {
    global total
    set total $bytes
    \fBchan close\fR $in
    \fBchan close\fR $out
    if {$error ne ""} {
        # error occurred during the copy
    }
}

set in [open $file1]
set out [socket $server $port]
\fBchan copy\fR $in $out -command [list Cleanup $in $out]
vwait total
.CE
.PP
The third example copies in chunks and tests for end of file
in the command callback.
.PP
.CS
proc CopyMore {in out chunk bytes {error {}}} {
    global total done
    incr total $bytes
    if {($error ne "") || [\fBchan eof\fR $in]} {
        set done $total
        \fBchan close\fR $in
        \fBchan close\fR $out
    } else {
        \fBchan copy\fR $in $out -size $chunk \e
            -command [list CopyMore $in $out $chunk]
    }
}

set in [open $file1]
set out [socket $server $port]
set chunk 1024
set total 0
\fBchan copy\fR $in $out -size $chunk \e
    -command [list CopyMore $in $out $chunk]
vwait done
.CE
.PP
The fourth example starts an asynchronous, bidirectional copy between
two sockets. Those could also be pipes from two bidirectional pipelines
(e.g., \fI[open "|hal 9000" r+]\fR); the conversation will remain
essentially secret to the script, since all four \fBchan event\fR slots
are busy, though any transforms that are \fBchan push\fRed on the
channels will be able to observe the passing traffic.
.PP
.CS
proc Done {dir args} {
    global flows done
    \fBchan puts\fR "$dir is over."
    incr flows -1
    if {$flows <= 0} {
        set done 1
    }
}

set flows 2
\fBchan copy\fR $sok1 $sok2 -command [list Done UP]
\fBchan copy\fR $sok2 $sok1 -command [list Done DOWN]
vwait done
.CE
.SH "SEE ALSO"
close(n), eof(n), fblocked(n), fconfigure(n), fcopy(n), file(n),
fileevent(n), flush(n), gets(n), open(n), puts(n), read(n), seek(n),
socket(n), tell(n), refchan(n), transchan(n)
socket(n), tell(n), refchan(n), transchan(n),
Tcl_StandardChannels(3)
.SH KEYWORDS
blocking, channel, end of file, events, input, non-blocking,
channel, input, output, events, offset
offset, output, readable, seek, stdio, tell, writable
'\" Local Variables:
'\" mode: nroff
'\" End:

Changes to doc/class.n.

8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
oo::class \- class of all classes
.SH SYNOPSIS
.nf
package require TclOO
package require tcl::oo

\fBoo::class\fI method \fR?\fIarg ...\fR?
.fi
.SH "CLASS HIERARCHY"
.nf
\fBoo::object\fR
   \(-> \fBoo::class\fR
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
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







+










+

















+








-
-
+
+
+
+
+







the newly-created class) to allow the class to be conveniently configured at
creation time.
.SS DESTRUCTOR
The \fBoo::class\fR class does not define an explicit destructor. However,
when a class is destroyed, all its subclasses and instances are also
destroyed, along with all objects that it has been mixed into.
.SS "EXPORTED METHODS"
.\" METHOD: create
.TP
\fIcls \fBcreate \fIname \fR?\fIarg ...\fR?
.
This creates a new instance of the class \fIcls\fR called \fIname\fR (which is
resolved within the calling context's namespace if not fully qualified),
passing the arguments, \fIarg ...\fR, to the constructor, and (if that returns
a successful result) returning the fully qualified name of the created object
(the result of the constructor is ignored). If the constructor fails (i.e.
returns a non-OK result) then the object is destroyed and the error message is
the result of this method call.
.\" METHOD: new
.TP
\fIcls \fBnew \fR?\fIarg ...\fR?
.
This creates a new instance of the class \fIcls\fR with a new unique name,
passing the arguments, \fIarg ...\fR, to the constructor, and (if that returns
a successful result) returning the fully qualified name of the created object
(the result of the constructor is ignored). If the constructor fails (i.e.,
returns a non-OK result) then the object is destroyed and the error message is
the result of this method call.
.RS
.PP
Note that this method is not exported by the \fBoo::class\fR object itself, so
classes should not be created using this method.
.RE
.SS "NON-EXPORTED METHODS"
.PP
The \fBoo::class\fR class supports the following non-exported methods:
.\" METHOD: createWithNamespace
.TP
\fIcls \fBcreateWithNamespace\fI name nsName\fR ?\fIarg ...\fR?
.
This creates a new instance of the class \fIcls\fR called \fIname\fR (which is
resolved within the calling context's namespace if not fully qualified),
passing the arguments, \fIarg ...\fR, to the constructor, and (if that returns
a successful result) returning the fully qualified name of the created object
(the result of the constructor is ignored). The name of the instance's
internal namespace will be \fInsName\fR unless that namespace already exists
(when an arbitrary name will be chosen instead). If the constructor fails
internal namespace will be \fInsName\fR;
.VS
it is an error if that namespace cannot be created.
.VE
If the constructor fails
(i.e., returns a non-OK result) then the object is destroyed and the error
message is the result of this method call.
.SH EXAMPLES
.PP
This example defines a simple class hierarchy and creates a new instance of
it. It then invokes a method of the object before destroying the hierarchy and
showing that the destruction is transitive.

Changes to doc/classvariable.n.

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
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







-
+

-
+










-
-
+
+







.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
classvariable \- create link from local variable to variable in class
.SH SYNOPSIS
.nf
package require TclOO
package require tcl::oo

\fBclassvariable\fR \fIvariableName\fR ?\fI...\fR?
\fBclassvariable\fI variableName\fR ?\fI...\fR?
.fi
.BE
.SH DESCRIPTION
The \fBclassvariable\fR command is available within methods. It takes a series
of one or more variable names and makes them available in the method's scope;
those variable names must not be qualified and must not refer to array
elements. The originating scope for the variables is the namespace of the
class that the method was defined by. In other words, the referenced variables
are shared between all instances of that class.
.PP
Note: This command is equivalent to the command \fBtypevariable\fR provided by
the snit package in tcllib for approximately the same purpose. If used in a
Note that this command is equivalent to the command \fBtypevariable\fR provided
by the snit package in tcllib for approximately the same purpose. If used in a
method defined directly on a class instance (e.g., through the
\fBoo::objdefine\fR \fBmethod\fR definition) this is very much like just
using:
.PP
.CS
namespace upvar [namespace current] $var $var
.CE

Changes to doc/clock.n.

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
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
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

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










+
-
-
-
+
+
+
-

-
-
+
-

-

-
-
+
-

-
+






+

-
+
+


+


+



-
+
+












+

-
+
+



+


+
-
+
+
+


+
-
+
+
+

-
+
+



+


+




+




+









+
+
+
+
+
+
+
+
+

+





+


+



+


+




-
+














+


+





-
+

+


+













+


+















+
+
+
+
+
+
+
+
+







'\"
'\" Generated from file './doc/clock.dt' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2004 Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
'\"
.TH "clock" n 8.5 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
.SH NAME
clock \- Obtain and manipulate dates and times
.SH "SYNOPSIS"
.nf
package require \fBTcl 8.5\fR
.sp
\fBclock add\fR \fItimeVal\fR ?\fIcount unit...\fR? ?\fI\-option value\fR?
package require \fBTcl 8.5-\fR

\fBclock add\fI timeVal\fR ?\fIcount unit...\fR? ?\fI\-option value\fR?
.sp
\fBclock clicks\fR ?\fI\-option\fR?
.sp
\fBclock format\fR \fItimeVal\fR ?\fI\-option value\fR...?
\fBclock format\fI timeVal\fR ?\fI\-option value\fR...?
.sp
\fBclock microseconds\fR
.sp
\fBclock milliseconds\fR
.sp
\fBclock scan\fR \fIinputString\fR ?\fI\-option value\fR...?
\fBclock scan\fI inputString\fR ?\fI\-option value\fR...?
.sp
\fBclock seconds\fR
.sp
.fi
.BE
.SH "DESCRIPTION"
.PP
The \fBclock\fR command performs several operations that obtain and
manipulate values that represent times.  The command supports several
subcommands that determine what action is carried out by the command.
.\" METHOD: add
.TP
\fBclock add\fR \fItimeVal\fR ?\fIcount unit...\fR? ?\fI\-option value\fR?
\fBclock add\fI timeVal\fR ?\fIcount unit...\fR? ?\fI\-option value\fR?
.
Adds a (possibly negative) offset to a time that is expressed as an
integer number of seconds.  See \fBCLOCK ARITHMETIC\fR for a full description.
.\" METHOD: clicks
.TP
\fBclock clicks\fR ?\fI\-option\fR?
.
If no \fI\-option\fR argument is supplied, returns a high-resolution
time value as a system-dependent integer value.  The unit of the value
is system-dependent but should be the highest resolution clock available
on the system such as a CPU cycle counter.  See \fBHIGH RESOLUTION TIMERS\fR for a full description.
on the system such as a CPU cycle counter.
See \fBHIGH RESOLUTION TIMERS\fR for a full description.
.RS
.PP
If the \fI\-option\fR argument is \fB\-milliseconds\fR, then the command
is synonymous with \fBclock milliseconds\fR (see below).  This
usage is obsolete, and \fBclock milliseconds\fR is to be
considered the preferred way of obtaining a count of milliseconds.
.PP
If the \fI\-option\fR argument is \fB\-microseconds\fR, then the command
is synonymous with \fBclock microseconds\fR (see below).  This
usage is obsolete, and \fBclock microseconds\fR is to be
considered the preferred way of obtaining a count of microseconds.
.RE
.\" METHOD: format
.TP
\fBclock format\fR \fItimeVal\fR ?\fI\-option value\fR...?
\fBclock format\fI timeVal\fR ?\fI\-option value\fR...?
.
Formats a time that is expressed as an integer number of seconds into a format
intended for consumption by users or external programs.
See \fBFORMATTING TIMES\fR for a full description.
.\" METHOD: microseconds
.TP
\fBclock microseconds\fR
.
Returns the current time as an integer number of microseconds.  See \fBHIGH RESOLUTION TIMERS\fR for a full description.
Returns the current time as an integer number of microseconds.
See \fBHIGH RESOLUTION TIMERS\fR for a full description.
.\" METHOD: milliseconds
.TP
\fBclock milliseconds\fR
.
Returns the current time as an integer number of milliseconds.  See \fBHIGH RESOLUTION TIMERS\fR for a full description.
Returns the current time as an integer number of milliseconds.
See \fBHIGH RESOLUTION TIMERS\fR for a full description.
.\" METHOD: scan
.TP
\fBclock scan\fR \fIinputString\fR ?\fI\-option value\fR...?
\fBclock scan\fI inputString\fR ?\fI\-option value\fR...?
.
Scans a time that is expressed as a character string and produces an
integer number of seconds.
See \fBSCANNING TIMES\fR for a full description.
.\" METHOD: seconds
.TP
\fBclock seconds\fR
.
Returns the current time as an integer number of seconds.
.SS "PARAMETERS"
.TP
\fIcount\fR
.
An integer representing a count of some unit of time.  See
\fBCLOCK ARITHMETIC\fR for the details.
.TP
\fItimeVal\fR
.
An integer value passed to the \fBclock\fR command that represents an
absolute time as a number of seconds from the \fIepoch time\fR of
1 January 1970, 00:00 UTC.  Note that the count of seconds does not
include any leap seconds; seconds are counted as if each UTC day has
exactly 86400 seconds.  Tcl responds to leap seconds by speeding or
slowing its clock by a tiny fraction for some minutes until it is
back in sync with UTC; its data model does not represent minutes that
have 59 or 61 seconds.
.TP
\fInow\fR
Instead of \fItimeVal\fR a non-integer value \fBnow\fR can be used as
replacement for today, which is simply interpolated to the run-time as value
of \fBclock seconds\fR. For example:
.sp
\fBclock format now -f %a; # current day of the week\fR
.sp
\fBclock add now 1 month; # next month\fR
.TP
\fIunit\fR
.
One of the words, \fBseconds\fR, \fBminutes\fR, \fBhours\fR,
\fBdays\fR, \fBweekdays\fR, \fBweeks\fR, \fBmonths\fR, or \fByears\fR.
Used in conjunction with \fIcount\fR to identify an interval of time,
for example, \fI3 seconds\fR or \fI1 year\fR.
.SS "OPTIONS"
.\" OPTION: -base
.TP
\fB\-base\fR time
.
Specifies that any relative times present in a \fBclock scan\fR command
are to be given relative to \fItime\fR.  \fItime\fR must be expressed as
a count of nominal seconds from the epoch time of 1 January 1970, 00:00 UTC.
.\" OPTION: -format
.TP
\fB\-format\fR format
.
Specifies the desired output format for \fBclock format\fR or the
expected input format for \fBclock scan\fR.  The \fIformat\fR string consists
of any number of characters other than the per-cent sign
.PQ \fB%\fR
interspersed with any number of \fIformat groups\fR, which are two-character
interspersed with any number of \fIformat groups\fR, which are two- or three-character
sequences beginning with the per-cent sign.  The permissible format groups,
and their interpretation, are described under \fBFORMAT GROUPS\fR.
.RS
.PP
On \fBclock format\fR, the default format is
.PP
.CS
%a %b %d %H:%M:%S %Z %Y
.CE
.PP
On \fBclock scan\fR, the lack of a \fB\-format\fR option indicates that a
.QW "free format scan"
is requested; see \fBFREE FORM SCAN\fR for a description of what happens.
.RE
.\" OPTION: -gmt
.TP
\fB\-gmt\fR boolean
.
If \fIboolean\fR is true, specifies that a time specified to \fBclock add\fR,
\fBclock format\fR or \fBclock scan\fR should be processed in
UTC.  If \fIboolean\fR is false, the processing defaults to the local time
zone.  This usage is obsolete; the correct current usage is to
specify the UTC time zone with
.QW "\fB\-timezone\fR \fI:UTC\fR"
.QW "\fB\-timezone\fI :UTC\fR"
or any of the equivalent ways to specify it.
.\" OPTION: -locale
.TP
\fB\-locale\fR localeName
.
Specifies that locale-dependent scanning and formatting (and date arithmetic
for dates preceding the adoption of the Gregorian calendar) is to be done in
the locale identified by \fIlocaleName\fR.  The locale name may be any of
the locales acceptable to the \fBmsgcat\fR package, or it may be the special
name \fIsystem\fR, which represents the current locale of the process, or
the null string, which represents Tcl's default locale.
.RS
.PP
The effect of locale on scanning and formatting is discussed in the
descriptions of the individual format groups under \fBFORMAT GROUPS\fR.
The effect of locale on clock arithmetic is discussed under
\fBCLOCK ARITHMETIC\fR.
.RE
.\" OPTION: -timezone
.TP
\fB\-timezone\fR zoneName
.
Specifies that clock arithmetic, formatting, and scanning are to be done
according to the rules for the time zone specified by \fIzoneName\fR.
The permissible values, and their interpretation, are discussed under
\fBTIME ZONES\fR.
On subcommands that expect a \fB\-timezone\fR argument, the default
is to use the \fIcurrent time zone\fR.  The current time zone is
determined, in order of preference, by:
.RS
.IP [1]
the environment variable \fBTCL_TZ\fR.
.IP [2]
the environment variable \fBTZ\fR.
.IP [3]
on Windows systems, the time zone settings from the Control Panel.
.RE
.\" OPTION: -validate
.TP
\fB\-validate\fR boolean
.
If \fIboolean\fR is true (default), \fBclock scan\fR will raise an error
if the input contains invalid values, e.g. day of month greater than
number of days in the month. If specified as false, the command makes
an adjustment to bring values within acceptable range. See
\fBSCANNING TIMES\fR for details.
.PP
If none of these is present, the C \fBlocaltime\fR and \fBmktime\fR
functions are used to attempt to convert times between local and
Greenwich.  On 32-bit systems, this approach is likely to have bugs,
particularly for times that lie outside the window (approximately the
years 1902 to 2037) that can be represented in a 32-bit integer.
.SH "CLOCK ARITHMETIC"
182
183
184
185
186
187
188
189

190
191

192
193
194
195
196
197
198
225
226
227
228
229
230
231

232
233

234
235
236
237
238
239
240
241







-
+

-
+







to the \fBclock add\fR command.  The result is interpreted as
a nominal number of seconds from the Epoch.
.PP
Surprising results
may be obtained when crossing a point at which a leap second is
inserted or removed; the \fBclock add\fR command simply ignores
leap seconds and therefore assumes that times come in sequence,
23:59:58, 23:59:59, 00:00:00.  (This assumption is handled by
23:59:58, 23:59:59, 00:00:00.  This assumption is handled by
the fact that Tcl's model of time reacts to leap seconds by speeding
or slowing the clock by a minuscule amount until Tcl's time
or slowing the clock by a miniscule amount until Tcl's time
is back in step with the world.
.PP
The fact that adding and subtracting hours is defined in terms of
absolute time means that it will add fixed amounts of time in time zones
that observe summer time (Daylight Saving Time).  For example,
the following code sets the value of \fBx\fR to \fB04:00:00\fR because
the clock has changed in the interval in question.
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


366
367
368
369
370
371
372
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







-
+

-
+








-
+





-
-
+
+

















-
-
+
+







-
+





-
-
+
+







interspersed with any number of \fIformat groups\fR, which are two-character
sequences beginning with the per-cent sign.  The permissible format groups,
and their interpretation, are described under \fBFORMAT GROUPS\fR.
.PP
If a \fB\-timezone\fR option is present, the following
argument is a string that specifies the time zone in which the date and time
are to be formatted.  As an alternative to
.QW "\fB\-timezone\fR \fI:UTC\fR" ,
.QW "\fB\-timezone\fI :UTC\fR" ,
the obsolete usage
.QW "\fB\-gmt\fR \fItrue\fR"
.QW "\fB\-gmt\fI true\fR"
may be used.  See
\fBTIME ZONES\fR for the permissible variants for the time zone.
.PP
If a \fB\-locale\fR option is present, the following argument is
a string that specifies the locale in which the time is to be formatted,
in the same format that is used for the \fBmsgcat\fR package.  Note
that the default, if \fB\-locale\fR is not specified, is the root locale
\fB{}\fR rather than the current locale.  The current locale may
be obtained by using \fB\-locale\fR \fBcurrent\fR.
be obtained by using \fB\-locale current\fR.
In addition, some platforms support a \fBsystem\fR locale that
reflects the user's current choices.  For instance, on Windows, the
format that the user has selected from dates and times in the Control
Panel can be obtained by using the \fBsystem\fR locale.  On
platforms that do not define a user selection of date and time formats
separate from \fBLC_TIME\fR, \fB\-locale\fR \fBsystem\fR is
synonymous with \fB\-locale\fR \fBcurrent\fR.
separate from \fBLC_TIME\fR, \fB\-locale system\fR is
synonymous with \fB\-locale current\fR.
.SH "SCANNING TIMES"
.PP
The \fBclock scan\fR command accepts times that are formatted as
strings and converts them to counts of seconds from the epoch time
of 1 January 1970, 00:00 UTC.  It normally takes a \fB\-format\fR
option that is followed by a string describing
the expected format of the input.  (See
\fBFREE FORM SCAN\fR for the effect of \fBclock scan\fR
without such an argument.)  The string consists of any number of
characters other than the per-cent sign
.PQ \fB%\fR "" ,
interspersed with any number of \fIformat groups\fR, which are two-character
sequences beginning with the per-cent sign.  The permissible format groups,
and their interpretation, are described under \fBFORMAT GROUPS\fR.
.PP
If a \fB\-timezone\fR option is present, the following
argument is a string that specifies the time zone in which the date and time
are to be interpreted.  As an alternative to \fB\-timezone\fR \fI:UTC\fR,
the obsolete usage \fB\-gmt\fR \fItrue\fR may be used.  See
are to be interpreted.  As an alternative to \fB\-timezone\fI :UTC\fR,
the obsolete usage \fB\-gmt\fI true\fR may be used.  See
\fBTIME ZONES\fR for the permissible variants for the time zone.
.PP
If a \fB\-locale\fR option is present, the following argument is
a string that specifies the locale in which the time is to be interpreted,
in the same format that is used for the \fBmsgcat\fR package.  Note
that the default, if \fB\-locale\fR is not specified, is the root locale
\fB{}\fR rather than the current locale.  The current locale may
be obtained by using \fB\-locale\fR \fBcurrent\fR.
be obtained by using \fB\-locale current\fR.
In addition, some platforms support a \fBsystem\fR locale that
reflects the user's current choices.  For instance, on Windows, the
format that the user has selected from dates and times in the Control
Panel can be obtained by using the \fBsystem\fR locale.  On
platforms that do not define a user selection of date and time formats
separate from \fBLC_TIME\fR, \fB\-locale\fR \fBsystem\fR is
synonymous with \fB\-locale\fR \fBcurrent\fR.
separate from \fBLC_TIME\fR, \fB\-locale system\fR is
synonymous with \fB\-locale current\fR.
.PP
If a \fB\-base\fR option is present, the following argument is
a time (expressed in seconds from the epoch time) that is used as
a \fIbase time\fR for interpreting relative times.  If no
\fB\-base\fR option is present, the base time is the current time.
.PP
Scanning of times in fixed format works by determining three things:
384
385
386
387
388
389
390
391
392






393
394
395
396
397
398
399
427
428
429
430
431
432
433


434
435
436
437
438
439
440
441
442
443
444
445
446







-
-
+
+
+
+
+
+







.PP
The date is determined according to the fields that are present in the
preprocessed format string.  In order of preference:
.IP [1]
If the string contains a \fB%s\fR format group, representing
seconds from the epoch, that group is used to determine the date.
.IP [2]
If the string contains a \fB%J\fR format group, representing
the Julian Day Number, that group is used to determine the date.
If the string contains a \fB%J\fR, \fB%EJ\fR or \fB%Ej\fR format groups,
representing the Calendar or Astronomical Julian Day Number, that groups
are used to determine the date.
Note, that in case of \fB%EJ\fR or \fB%Ej\fR format groups, representing
the Julian Date with time fraction, this groups may be used to determine
the date and time.
.IP [3]
If the string contains a complete set of format groups specifying
century, year, month, and day of month; century, year, and day of year;
or ISO8601 fiscal year, week of year, and day of week; those groups are
combined and used to determine the date.  If more than one complete
set is present, the one at the rightmost position in the string is
used.
450
451
452
453
454
455
456


457

458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474


475
476
477
478
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
558
559

560
561
562
563
564

565
566
567
568
569
570

571
572
573
574
575
576

577
578
579

580
581
582
583

584
585
586
587

588
589
590
591

592
593
594
595
596
597
598
599

600
601
602
603

604
605
606
607

608
609
610
611
612

613
614
615
616
617

618
619
620
621
622
623

624
625
626
627
628
629
630

631
632
633
634
635
636
637

638
639
640
641
642
643
644

645
646
647


648
649
650
651

652
653
654
655
656

657
658
659
660
661
662
663

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
707
708
709
710

711
712
713
714
715

716
717
718
719
720

721
722
723
724
725
726
727

728
729
730
731
732
733

734
735
736
737

738
739


740
741
742

743

744
745
746
747
748
749

750
751
752
753
754
755
756

757
758
759
760
761
762
763
764
765
766
767
768
769

770
771
772
773
774
775
776
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
558
559
560
561


562
563
564
565
566


567
568
569
570


571
572
573
574
575
576
577
578


579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610


611
612
613
614


615
616
617
618


619
620
621
622


623
624
625
626
627


628
629
630
631
632


633
634


635
636
637


638
639
640


641
642
643


644
645
646
647
648
649
650


651
652
653


654
655
656


657
658
659
660


661
662
663
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
707


708
709


710
711


712
713
714
715
716


717
718
719
720
721
722
723


724
725
726
727
728
729
730


731
732
733
734
735
736


737
738
739
740
741
742


743
744
745
746


747
748
749
750


751
752
753
754
755
756


757
758
759
760
761


762
763
764
765

766


767
768
769
770
771
772

773
774
775
776
777


778
779
780
781
782
783


784
785
786
787
788
789
790
791
792
793
794
795
796

797
798
799
800
801
802
803
804







+
+
-
+














-
-
-
+
+



-
-
-
+
+



-
-
-
+
+



-
-
-
+
+



-
-
+



-
-
+



-
-
+



-
-
+



-
-
+




-
-
+




-
-
+



-
-
+







-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
+



-
-
+



-
-
+



-
-
+




-
-
+




-
-
+

-
-
+


-
-
+


-
-
+


-
-
+






-
-
+


-
-
+


-
-
+



-
-
+



-
-
+




-
-
+





-
-
+





-
-
+





-
-
+

-
-
+
+


-
-
+



-
-
+





-
-
+



-
-
+

-
-
+

-
-
+




-
-
+






-
-
+






-
-
+





-
-
+





-
-
+



-
-
+



-
-
+





-
-
+




-
-
+



-
+
-
-
+
+



+
-
+




-
-
+





-
-
+












-
+







in the same day, once without and once with Daylight Saving Time.
If this situation occurs, the first occurrence of the time is chosen.
(For this reason, it is wise to have the input string contain the
time zone when converting local times.  This caveat does not apply to
UTC times.)
.PP
If the interpretation of the groups yields an impossible time because
a field is out of range, an exception is raised if the \fB-validate\fR
option is not present or passed as true. If passed as false,
a field is out of range, enough of that field's unit will be added to
enough of that field's unit will be added to
or subtracted from the time to bring it in range. Thus, if attempting to
scan or format day 0 of the month, one day will be subtracted from day
1 of the month, yielding the last day of the previous month.
.PP
If the interpretation of the groups yields an impossible time because
a Daylight Saving Time change skips over that time, or an ambiguous
time because a Daylight Saving Time change skips back so that the clock
observes the given time twice, and no time zone specifier (\fB%z\fR
or \fB%Z\fR) is present in the format, the time is interpreted as
if the clock had not changed.
.SH "FORMAT GROUPS"
.PP
The following format groups are recognized by the \fBclock scan\fR and
\fBclock format\fR commands.
.TP
\fB%a\fR
On output, produces an abbreviation (\fIe.g.,\fR \fBMon\fR) for the day
.IP \fB%a\fR
On output, produces an abbreviation (\fIe.g., \fBMon\fR) for the day
of the week in the given locale.  On input, matches the name of the day
of the week in the given locale (in either abbreviated or full form, or
any unique prefix of either form).
.TP
\fB%A\fR
On output, produces the full name (\fIe.g.,\fR \fBMonday\fR) of the day
.IP \fB%A\fR
On output, produces the full name (\fIe.g., \fBMonday\fR) of the day
of the week in the given locale.  On input, matches the name of the day
of the week in the given locale (in either abbreviated or full form, or
any unique prefix of either form).
.TP
\fB%b\fR
On output, produces an abbreviation (\fIe.g.,\fR \fBJan\fR) for the name
.IP \fB%b\fR
On output, produces an abbreviation (\fIe.g., \fBJan\fR) for the name
of the month in the given locale.  On input, matches the name of the month
in the given locale (in either abbreviated or full form, or
any unique prefix of either form).
.TP
\fB%B\fR
On output, produces the full name (\fIe.g.,\fR \fBJanuary\fR)
.IP \fB%B\fR
On output, produces the full name (\fIe.g., \fBJanuary\fR)
of the month in the given locale.  On input, matches the name of the month
in the given locale (in either abbreviated or full form, or
any unique prefix of either form).
.TP
\fB%c\fR
.IP \fB%c\fR
On output, produces a localized representation of date and time of day;
the localized representation is expected to use the Gregorian calendar.
On input, matches whatever \fB%c\fR produces.
.TP
\fB%C\fR
.IP \fB%C\fR
On output, produces the number of the century in Indo-Arabic numerals.
On input, matches one or two digits, possibly with leading whitespace,
that are expected to be the number of the century.
.TP
\fB%d\fR
.IP \fB%d\fR
On output, produces the number of the day of the month, as two decimal
digits.  On input, matches one or two digits, possibly with leading
whitespace, that are expected to be the number of the day of the month.
.TP
\fB%D\fR
.IP \fB%D\fR
This format group is synonymous with \fB%m/%d/%Y\fR.  It should be
used only in exchanging data within the \fBen_US\fR locale, since
other locales typically do not use this order for the fields of the date.
.TP
\fB%e\fR
.IP \fB%e\fR
On output, produces the number of the day of the month, as one or
two decimal digits (with a leading blank for one-digit dates).
On input, matches one or two digits, possibly with leading
whitespace, that are expected to be the number of the day of the month.
.TP
\fB%Ec\fR
.IP \fB%Ec\fR
On output, produces a locale-dependent representation of the date and
time of day in the locale's alternative calendar.  On input, matches
whatever \fB%Ec\fR produces.  The locale's alternative calendar need not
be the Gregorian calendar.
.TP
\fB%EC\fR
.IP \fB%EC\fR
On output, produces a locale-dependent name of an era in the locale's
alternative calendar.  On input, matches the name of the era or any
unique prefix.
.TP
\fB%EE\fR
.IP \fB%EE\fR
On output, produces the string \fBB.C.E.\fR or \fBC.E.\fR, or a
string of the same meaning in the locale, to indicate whether \fB%Y\fR refers
to years before or after Year 1 of the Common Era.  On input, accepts
the string \fBB.C.E.\fR, \fBB.C.\fR, \fBC.E.\fR, \fBA.D.\fR, or the
abbreviation appropriate to the current locale, and uses it to fix
whether \fB%Y\fR refers to years before or after Year 1 of the
Common Era.
.TP
\fB%Ex\fR
.IP \fB%Ej\fR
On output, produces a string of digits giving the Astronomical Julian Date or
Astronomical Julian Day Number (JDN/JD). In opposite to calendar julian day
\fB%J\fR, it starts the day at noon.
On input, accepts a string of digits (or floating point with the time fraction)
and interprets it as an Astronomical Julian Day Number (JDN/JD).
The Astronomical Julian Date is a count of the number of calendar days
that have elapsed since 1 January, 4713 BCE of the proleptic
Julian calendar, which contains also the time fraction (after floating point).
The epoch time of 1 January 1970 corresponds to Astronomical JDN 2440587.5.
This value corresponds the julian day used in sqlite-database, and is the same
as result of \fBselect julianday(:seconds, 'unixepoch')\fR.
.IP \fB%EJ\fR
On output, produces a string of digits giving the Calendar Julian Date.
In opposite to julian day \fB%J\fR format group, it produces float number.
In opposite to astronomical julian day \fB%Ej\fR group, it starts at midnight.
On input, accepts a string of digits (or floating point with the time fraction)
and interprets it as a Calendar Julian Day Number.
The Calendar Julian Date is a count of the number of calendar days
that have elapsed since 1 January, 4713 BCE of the proleptic
Julian calendar, which contains also the time fraction (after floating point).
The epoch time of 1 January 1970 corresponds to Astronomical JDN 2440588.
.IP \fB%Es\fR
This affects similar to \fB%s\fR, but in opposition to \fB%s\fR it parses
or formats local seconds (not the posix seconds).
Because \fB%s\fR has the same precedence as \fB%s\fR (uniquely determines
a point in time), it overrides all other input formats.
.IP \fB%Ex\fR
On output, produces a locale-dependent representation of the date
in the locale's alternative calendar.  On input, matches
whatever \fB%Ex\fR produces.  The locale's alternative calendar need not
be the Gregorian calendar.
.TP
\fB%EX\fR
.IP \fB%EX\fR
On output, produces a locale-dependent representation of the
time of day in the locale's alternative numerals.  On input, matches
whatever \fB%EX\fR produces.
.TP
\fB%Ey\fR
.IP \fB%Ey\fR
On output, produces a locale-dependent number of the year of the era
in the locale's alternative calendar and numerals.  On input, matches
such a number.
.TP
\fB%EY\fR
.IP \fB%EY\fR
On output, produces a representation of the year in the locale's
alternative calendar and numerals.  On input, matches what \fB%EY\fR
produces.  Often synonymous with \fB%EC%Ey\fR.
.TP
\fB%g\fR
.IP \fB%g\fR
On output, produces a two-digit year number suitable for use with
the week-based ISO8601 calendar; that is, the year number corresponds
to the week number produced by \fB%V\fR.  On input, accepts such
a two-digit year number, possibly with leading whitespace.
.TP
\fB%G\fR
.IP \fB%G\fR
On output, produces a four-digit year number suitable for use with
the week-based ISO8601 calendar; that is, the year number corresponds
to the week number produced by \fB%V\fR.  On input, accepts such
a four-digit year number, possibly with leading whitespace.
.TP
\fB%h\fR
.IP \fB%h\fR
This format group is synonymous with \fB%b\fR.
.TP
\fB%H\fR
.IP \fB%H\fR
On output, produces a two-digit number giving the hour of the day
(00-23) on a 24-hour clock.  On input, accepts such a number.
.TP
\fB%I\fR
.IP \fB%I\fR
On output, produces a two-digit number giving the hour of the day
(12-11) on a 12-hour clock.  On input, accepts such a number.
.TP
\fB%j\fR
.IP \fB%j\fR
On output, produces a three-digit number giving the day of the year
(001-366).  On input, accepts such a number.
.TP
\fB%J\fR
.IP \fB%J\fR
On output, produces a string of digits giving the Julian Day Number.
On input, accepts a string of digits and interprets it as a Julian Day Number.
The Julian Day Number is a count of the number of calendar days
that have elapsed since 1 January, 4713 BCE of the proleptic
Julian calendar.  The epoch time of 1 January 1970 corresponds
to Julian Day Number 2440588.
.TP
\fB%k\fR
.IP \fB%k\fR
On output, produces a one- or two-digit number giving the hour of the day
(0-23) on a 24-hour clock.  On input, accepts such a number.
.TP
\fB%l\fR
.IP \fB%l\fR
On output, produces a one- or two-digit number giving the hour of the day
(12-11) on a 12-hour clock.  On input, accepts such a number.
.TP
\fB%m\fR
.IP \fB%m\fR
On output, produces the number of the month (01-12) with exactly two
digits.  On input, accepts two digits and interprets them as the number
of the month.
.TP
\fB%M\fR
.IP \fB%M\fR
On output, produces the number of the minute of the hour (00-59)
with exactly two digits.  On input, accepts two digits and interprets them
as the number of the minute of the hour.
.TP
\fB%N\fR
.IP \fB%N\fR
On output, produces the number of the month (1-12) with one or two digits,
and a leading blank for one-digit dates.
On input, accepts one or two digits, possibly with leading whitespace,
and interprets them as the number of the month.
.TP
\fB%Od\fR, \fB%Oe\fR, \fB%OH\fR, \fB%OI\fR, \fB%Ok\fR, \fB%Ol\fR, \fB%Om\fR, \fB%OM\fR, \fB%OS\fR, \fB%Ou\fR, \fB%Ow\fR, \fB%Oy\fR
.IP "\fB%Od\fR, \fB%Oe\fR, \fB%OH\fR, \fB%OI\fR, \fB%Ok\fR, \fB%Ol\fR, \fB%Om\fR, \fB%OM\fR, \fB%OS\fR, \fB%Ou\fR, \fB%Ow\fR, \fB%Oy\fR"
All of these format groups are synonymous with their counterparts
without the
.QW \fBO\fR ,
except that the string is produced and parsed in the
locale-dependent alternative numerals.
.TP
\fB%p\fR
.IP \fB%p\fR
On output, produces an indicator for the part of the day, \fBAM\fR
or \fBPM\fR, appropriate to the given locale.  If the script of the
given locale supports multiple letterforms, lowercase is preferred.
On input, matches the representation \fBAM\fR or \fBPM\fR in
the given locale, in either case.
.TP
\fB%P\fR
.IP \fB%P\fR
On output, produces an indicator for the part of the day, \fBam\fR
or \fBpm\fR, appropriate to the given locale.  If the script of the
given locale supports multiple letterforms, uppercase is preferred.
On input, matches the representation \fBAM\fR or \fBPM\fR in
the given locale, in either case.
.TP
\fB%Q\fR
.IP \fB%Q\fR
This format group is reserved for internal use within the Tcl library.
.TP
\fB%r\fR
.\" It's the STARDATE! We're so Enterprise-ready...
.IP \fB%r\fR
On output, produces a locale-dependent time of day representation on a
12-hour clock. On input, accepts whatever \fB%r\fR produces.
.TP
\fB%R\fR
.IP \fB%R\fR
On output, the time in 24-hour notation (%H:%M). For a version
including the seconds, see \fB%T\fR below. On input, accepts whatever
\fB%R\fR produces.
.TP
\fB%s\fR
.IP \fB%s\fR
On output, simply formats the \fItimeVal\fR argument as a decimal
integer and inserts it into the output string.  On input, accepts
a decimal integer and uses is as the time value without any further
processing. Since \fB%s\fR uniquely determines a point in time, it
overrides all other input formats.
.TP
\fB%S\fR
.IP \fB%S\fR
On output, produces a two-digit number of the second of the minute
(00-59). On input, accepts two digits and uses them as the second of the
minute.
.TP
\fB%t\fR
.IP \fB%t\fR
On output, produces a TAB character. On input, matches a TAB character.
.TP
\fB%T\fR
.IP \fB%T\fR
Synonymous with \fB%H:%M:%S\fR.
.TP
\fB%u\fR
.IP \fB%u\fR
On output, produces the number of the day of the week
(\fB1\fR\(->Monday, \fB7\fR\(->Sunday). On input, accepts a single digit and
interprets it as the day of the week. Sunday may be either \fB0\fR or
\fB7\fR.
.TP
\fB%U\fR
.IP \fB%U\fR
On output, produces the ordinal number of the week of the year
(00-53). The first Sunday of the year is the first day of week 01. On
input accepts two digits which are otherwise ignored. This format
group is never used in determining an input date.  This interpretation
of the week of the year was once common in US banking but is now
largely obsolete.  See \fB%V\fR for the ISO8601 week number.
.TP
\fB%V\fR
.IP \fB%V\fR
On output, produces the number of the ISO8601 week as a two digit
number (01-53). Week 01 is the week containing January 4; or the first
week of the year containing at least 4 days; or the week containing
the first Thursday of the year (the three statements are
equivalent). Each week begins on a Monday. On input, accepts the
ISO8601 week number.
.TP
\fB%w\fR
.IP \fB%w\fR
On output, produces the ordinal number of the day of the week
(Sunday==0; Saturday==6).  On input, accepts a single digit and
interprets it as the day of the week; Sunday may be represented as
either 0 or 7.  Note that \fB%w\fR is not the ISO8601 weekday number,
which is produced and accepted by \fB%u\fR.
.TP
\fB%W\fR
.IP \fB%W\fR
On output, produces a week number (00-53) within the year; week 01
begins on the first Monday of the year. On input, accepts two digits,
which are otherwise ignored. This format group is never used in
determining an input date.  It is not the ISO8601 week number; that
week is produced and accepted by \fB%V\fR.
.TP
\fB%x\fR
.IP \fB%x\fR
On output, produces the date in a locale-dependent representation. On
input, accepts whatever \fB%x\fR produces and is used to determine
calendar date.
.TP
\fB%X\fR
.IP \fB%X\fR
On output, produces the time of day in a locale-dependent
representation. On input, accepts whatever \fB%X\fR produces and is used
to determine time of day.
.TP
\fB%y\fR
.IP \fB%y\fR
On output, produces the two-digit year of the century. On input,
accepts two digits, and is used to determine calendar date. The
date is presumed to lie between 1938 and 2037 inclusive. Note
that \fB%y\fR does not yield a year appropriate for use with the ISO8601
week number \fB%V\fR; programs should use \fB%g\fR for that purpose.
.TP
\fB%Y\fR
.IP \fB%Y\fR
On output, produces the four-digit calendar year. On input,
accepts four digits and may be used to determine calendar date. Note
that \fB%Y\fR does not yield a year appropriate for use with the ISO8601
week number \fB%V\fR; programs should use \fB%G\fR for that purpose.
.TP
\fB%z\fR
.IP \fB%z\fR
On output, produces the current time zone, expressed in hours and
minutes east (+hhmm) or west (\-hhmm) of Greenwich. On input, accepts a
time zone specifier (see \fBTIME ZONES\fR below) that will be used to
determine the time zone.
determine the time zone (this token is optionally applicable on input,
.TP
\fB%Z\fR
so the value is not mandatory and can be missing in input).
.IP \fB%Z\fR
On output, produces the current time zone's name, possibly
translated to the given locale. On input, accepts a time zone
specifier (see \fBTIME ZONES\fR below) that will be used to determine the
time zone (token is also like \fB%z\fR optionally applicable on input).
time zone. This option should, in general, be used on input only when
This option should, in general, be used on input only when
parsing RFC822 dates. Other uses are fraught with ambiguity; for
instance, the string \fBBST\fR may represent British Summer Time or
Brazilian Standard Time. It is recommended that date/time strings for
use by computers use numeric time zones instead.
.TP
\fB%%\fR
.IP \fB%%\fR
On output, produces a literal
.QW \fB%\fR
character. On input, matches a literal
.QW \fB%\fR
character.
.TP
\fB%+\fR
.IP \fB%+\fR
Synonymous with
.QW "\fB%a %b %e %H:%M:%S %Z %Y\fR" .
.SH "TIME ZONES"
.PP
When the \fBclock\fR command is processing a local time, it has several
possible sources for the time zone to use.  In order of preference, they
are:
.IP [1]
A time zone specified inside a string being parsed and matched by a \fB%z\fR
or \fB%Z\fR format group.
.IP [2]
A time zone specified with the \fB\-timezone\fR option to the \fBclock\fR
command (or, equivalently, by \fB\-gmt\fR \fB1\fR).
command (or, equivalently, by \fB\-gmt 1\fR).
.IP [3]
A time zone specified in an environment variable \fBTCL_TZ\fR.
.IP [4]
A time zone specified in an environment variable \fBTZ\fR.
.IP [5]
The local time zone from the Control Panel on Windows systems.
.IP [6]
800
801
802
803
804
805
806
807

808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826

827
828
829
830
831
832
833
828
829
830
831
832
833
834

835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853

854
855
856
857
858
859
860
861







-
+


















-
+







.PP
If the time zone begins with a colon, it is one of a
standardized list of names like \fB:America/New_York\fR
that give the rules for various locales.  A complete list
of the location names is too lengthy to be listed here.
On most Tcl installations, the definitions of the locations
are to be found in named files in the directory
.QW "\fI/no_backup/tools/lib/tcl8.5/clock/tzdata\fR" .
.QW "\fI/no_backup/tools/lib/tcl9.0/clock/tzdata\fR" .
On some Unix systems, these files are omitted, and the definitions are
instead obtained from system files in
.QW "\fI/usr/share/zoneinfo\fR" ,
.QW "\fI/usr/share/lib/zoneinfo\fR"
or
.QW "\fI/usr/local/etc/zoneinfo\fR" .
As a special case, the name \fB:localtime\fR refers to
the local time zone as defined by the C library.
.PP
A time zone string consisting of a plus or minus sign followed by
four or six decimal digits is interpreted as an offset in
hours, minutes, and seconds (if six digits are present) from
UTC.  The plus sign denotes a sign east of Greenwich;
the minus sign one west of Greenwich.
.PP
A time zone string conforming to the Posix specification of the \fBTZ\fR
environment variable will be recognized.  The specification
may be found at
\fIhttp://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html\fR.
\fIhttps://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html\fR.
.PP
If the Posix time zone string contains a DST (Daylight Savings Time)
part, but doesn't contain a rule stating when DST starts or ends,
then default rules are used. For Timezones with an offset between 0
and +12, the current European/Russian rules are used, otherwise the
current US rules are used. In Europe (offset +0 to +2) the switch
to summertime is done each last Sunday in March at 1:00 GMT, and
843
844
845
846
847
848
849
850

851
852
853
854
855
856



857
858
859
860
861
862
863
871
872
873
874
875
876
877

878
879
880
881
882


883
884
885
886
887
888
889
890
891
892







-
+




-
-
+
+
+







rules change again.
.PP
Any other time zone string is processed by prefixing a colon and attempting
to use it as a location name, as above.
.SH "LOCALIZATION"
.PP
Developers wishing to localize the date and time formatting and parsing
are referred to \fIhttp://tip.tcl.tk/173\fR for a
are referred to \fIhttps://tip.tcl-lang.org/173\fR for a
specification.
.SH "FREE FORM SCAN"
.PP
If the \fBclock scan\fR command is invoked without a \fB\-format\fR
option, then it requests a \fIfree-form scan.\fR  \fI
This form of scan is deprecated.\fR  The reason for the deprecation
option, then it requests a \fIfree-form scan\fR.
\fIThis form of scan is deprecated.\fR
The reason for the deprecation
is that there are too many ambiguities. (Does the string
.QW 2000
represent a year, a time of day, or a quantity?)  No set of rules
for interpreting free-form dates and times has been found to
give unsurprising results in all cases.
.PP
If free-form scan is used, only the \fB\-base\fR and \fB\-gmt\fR
888
889
890
891
892
893
894
895


896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916

917
918
919
920
921
922

923
924
925



926
927
928
929
930
931
932
917
918
919
920
921
922
923

924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945

946
947
948
949
950
951

952
953
954

955
956
957
958
959
960
961
962
963
964







-
+
+




















-
+





-
+


-
+
+
+







\fItime\fR
.
A time of day, which is of the form:
.QW "\fIhh\fR?\fB:\fImm\fR?\fB:\fIss\fR?? ?\fImeridian\fR? ?\fIzone\fR?"
or
.QW "\fBhhmm \fR?\fBmeridian\fR? ?\fBzone\fR?" .
If no \fImeridian\fR is specified, \fIhh\fR is interpreted on
a 24-hour clock.
a 24-hour clock. The "24:00" and "24:00:00" formats (with or without
colon) are supported only if no \fImeridian\fR is specified.
.TP
\fIdate\fR
.
A specific month and day with optional year.  The
acceptable formats are
.QW "\fImm\fB/\fIdd\fR?\fB/\fIyy\fR?" ,
.QW "\fImonthname dd\fR?\fB, \fIyy\fR?" ,
.QW "\fIday\fB, \fIdd monthname \fR?\fIyy\fR?" ,
.QW "\fIdd monthname yy\fR" ,
.QW "?\fICC\fR?\fIyymmdd\fR" ,
and
.QW "\fIdd\fB-\fImonthname\fB-\fR?\fICC\fR?\fIyy\fR" .
The default year is the current year.  If the year is less
than 100, we treat the years 00-68 as 2000-2068 and the years 69-99
as 1969-1999.  Not all platforms can represent the years 38-70, so
an error may result if these years are used.
.TP
\fIISO 8601 point-in-time\fR
.
An ISO 8601 point-in-time specification, such as
.QW "\fICCyymmdd\fBT\fIhhmmss\fR",
.QW "\fICCyymmdd\fBT\fIhhmmss\fR" ,
where \fBT\fR is the literal
.QW T ,
.QW "\fICCyymmdd hhmmss\fR" ,
.QW "\fICCyymmdd\fBT\fIhh:mm:ss\fR" ,
or
.QW "\fICCyy-mm-dd\fBT\fIhh\fB:\fImm\fB:\fIss\fR".
.QW "\fICCyy-mm-dd\fBT\fIhh:mm:ss\fR" .
Note that only these four formats are accepted.
The command does \fInot\fR accept the full range of point-in-time
specifications specified in ISO8601.  Other formats can be recognized by
specifications specified in ISO8601.  For example, leap seconds are
not supported. The "24:00" and "24:00:00" formats (with or without
colon) are supported.  Other formats can be recognized by
giving an explicit \fB\-format\fR option to the \fBclock scan\fR command.
.TP
\fIrelative time\fR
.
A specification relative to the current time.  The format is \fBnumber
unit\fR. Acceptable units are \fByear\fR, \fBfortnight\fR,
\fBmonth\fR, \fBweek\fR, \fBday\fR,
942
943
944
945
946
947
948


















949
950
951
952
953
954

955
956
957
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+



Using that time as the base, day-of-week specifications are added.
Next, relative specifications are used.  If a date or day is
specified, and no absolute or relative time is given, midnight is
used.  Finally, a correction is applied so that the correct hour of
the day is produced after allowing for daylight savings time
differences and the correct date is given when going from the end
of a long month to a short month.
.PP
The precedence of the applying of single tokens resp. which sequence will be
used by calculating of the time is complex, e. g. heavily dependent on the
precision of type of the token.
.sp
In example below the second date-string contains "next January", therefore
it results in next year but in January. And third date-string besides "January"
contains also additionally "Fri", so it results in the nearest Friday.
Thus both win before "385 days" resp. make it more precise, because of higher
precision of this token types.
.CS
% clock format [clock scan "5 years 18 months 385 days" -base 0 -gmt 1] -gmt 1
Thu Jul 21 00:00:00 GMT 1977
% clock format [clock scan "5 years 18 months 385 days next January" -base 0 -gmt 1] -gmt 1
Sat Jan 21 00:00:00 GMT 1978
% clock format [clock scan "5 years 18 months 385 days next January Fri" -base 0 -gmt 1] -gmt 1
Fri Jan 27 00:00:00 GMT 1978
.CE
.SH "SEE ALSO"
msgcat(n)
.SH KEYWORDS
clock, date, time
.SH "COPYRIGHT"
Copyright (c) 2004 Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
Copyright \(co 2004 Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
'\" Local Variables:
'\" mode: nroff
'\" End:

Changes to doc/close.n.

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
8
9
10
11
12
13
14

15
16
17
18












































































19
20


21



22
23
24
25
26







-
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-

-
-
-
+




.TH close n 7.5 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
close \- Close an open channel
.SH SYNOPSIS
\fBclose \fIchannelId\fR ?r(ead)|w(rite)?
\fBclose \fIchannel\fR ?\fBr\fR(\fBead\fR)|\fBw\fR(\fBrite\fR)?
.BE
.SH DESCRIPTION
.PP
Closes or half-closes the channel given by \fIchannelId\fR.
.PP
\fIChannelId\fR must be an identifier for an open channel such as a
Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR),
the return value from an invocation of \fBopen\fR or \fBsocket\fR, or
the result of a channel creation command provided by a Tcl extension.
.PP
The single-argument form is a simple
.QW "full-close" :
all buffered output is flushed to the channel's output device,
any buffered input is discarded, the underlying file or device is closed,
and \fIchannelId\fR becomes unavailable for use.
.PP
If the channel is blocking, the command does not return until all output
is flushed.
If the channel is nonblocking and there is unflushed output, the
channel remains open and the command
returns immediately; output will be flushed in the background and the
channel will be closed when all the flushing is complete.
.PP
If \fIchannelId\fR is a blocking channel for a command pipeline then
\fBclose\fR waits for the child processes to complete.
.PP
If the channel is shared between interpreters, then \fBclose\fR
makes \fIchannelId\fR unavailable in the invoking interpreter but has no
other effect until all of the sharing interpreters have closed the
channel.
When the last interpreter in which the channel is registered invokes
\fBclose\fR, the cleanup actions described above occur. See the
\fBinterp\fR command for a description of channel sharing.
.PP
Channels are automatically closed when an interpreter is destroyed and
when the process exits.
From 8.6 on (TIP#398), nonblocking channels are no longer switched to blocking mode when exiting; this guarantees a timely exit even when the peer or a communication channel is stalled. To ensure proper flushing of stalled nonblocking channels on exit, one must now either (a) actively switch them back to blocking or (b) use the environment variable TCL_FLUSH_NONBLOCKING_ON_EXIT,  which when set and not equal to "0" restores the previous behavior.
.PP
The command returns an empty string, and may generate an error if
an error occurs while flushing output.  If a command in a command
pipeline created with \fBopen\fR returns an error, \fBclose\fR
generates an error (similar to the \fBexec\fR command.)
.PP
The two-argument form is a
.QW "half-close" :
given a bidirectional channel like a
socket or command pipeline and a (possibly abbreviated) direction, it closes
only the sub-stream going in that direction. This means a shutdown() on a
socket, and a close() of one end of a pipe for a command pipeline. Then, the
Tcl-level channel data structure is either kept or freed depending on whether
the other direction is still open.
.PP
A single-argument close on an already half-closed bidirectional channel is
defined to just
.QW "finish the job" .
A half-close on an already closed half, or on a wrong-sided unidirectional
channel, raises an error.
.PP
In the case of a command pipeline, the child-reaping duty falls upon the
shoulders of the last close or half-close, which is thus allowed to report an
abnormal exit error.
.PP
Currently only sockets and command pipelines support half-close. A future
extension will allow reflected and stacked channels to do so.
.SH EXAMPLE
.PP
This illustrates how you can use Tcl to ensure that files get closed
even when errors happen by combining \fBcatch\fR, \fBclose\fR and
\fBreturn\fR:
.PP
.CS
proc withOpenFile {filename channelVar script} {
    upvar 1 $channelVar chan
    set chan [open $filename]
    catch {
        uplevel 1 $script
    } result options
    \fBclose\fR $chan
    return -options $options $result
The \fBclose\fR command has been superceded by the \fBchan close\fR
command which supports the same syntax and options.
}
.CE
.SH "SEE ALSO"
file(n), open(n), socket(n), eof(n), Tcl_StandardChannels(3)
.SH KEYWORDS
blocking, channel, close, nonblocking, half-close
chan(n)
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/concat.n.

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
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







-
+















-
+







-
+







-
+





+
+
+
+
+
+
+
+

-
+





.TH concat n 8.3 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
concat \- Join lists together
.SH SYNOPSIS
\fBconcat\fI \fR?\fIarg arg ...\fR?
\fBconcat\fR ?\fIarg arg ...\fR?
.BE
.SH DESCRIPTION
.PP
This command joins each of its arguments together with spaces after
trimming leading and trailing white-space from each of them.  If all of the
arguments are lists, this has the same effect as concatenating them
into a single list.
Arguments that are empty (after trimming) are ignored entirely.
It permits any number of arguments;
if no \fIarg\fRs are supplied, the result is an empty string.
.SH EXAMPLES
Although \fBconcat\fR will concatenate lists, flattening them in the process
(so giving the following interactive session):
.PP
.CS
\fI%\fR \fBconcat\fR a b {c d e} {f {g h}}
\fI% \fBconcat\fR a b {c d e} {f {g h}}
\fIa b c d e f {g h}\fR
.CE
.PP
it will also concatenate things that are not lists, as can be seen from this
session:
.PP
.CS
\fI%\fR \fBconcat\fR " a b {c   " d "  e} f"
\fI% \fBconcat\fR " a b {c   " d "  e} f"
\fIa b {c d e} f\fR
.CE
.PP
Note also that the concatenation does not remove spaces from the middle of
values, as can be seen here:
.PP
.CS
\fI%\fR \fBconcat\fR "a   b   c" { d e f }
\fI% \fBconcat\fR "a   b   c" { d e f }
\fIa   b   c d e f\fR
.CE
.PP
(i.e., there are three spaces between each of the \fBa\fR, the \fBb\fR and the
\fBc\fR).
.PP
For \fItrue\fR list concatenation, the \fBlist\fR command should be used with
expansion of each input list:
.PP
.CS
\fI% \fRlist {*}"a   b   c" {*}{ d e f }
\fIa b c d e f\fR
.CE
.SH "SEE ALSO"
append(n), eval(n), join(n)
append(n), eval(n), join(n), list(n)
.SH KEYWORDS
concatenate, join, list
'\" Local Variables:
'\" mode: nroff
'\" End:

Added doc/configurable.n.


























































































































































































































































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
'\"
'\" Copyright (c) 2019 Donal K. Fellows
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH configurable n 0.4 TclOO "TclOO Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
oo::configurable, configure, property \- class that makes configurable classes and objects, and supports making configurable properties
.SH SYNOPSIS
.nf
package require TclOO

\fBoo::configurable create \fIclass\fR ?\fIdefinitionScript\fR?

\fBoo::define \fIclass\fB {\fR
    \fBproperty \fIpropName\fR ?\fIoptions...\fR? ?\fIpropName\fR ?\fIoptions...\fR?...?
\fB}\fR

\fBoo::objdefine \fIobject\fB {\fR
    \fBproperty \fIpropName\fR ?\fIoptions...\fR? ?\fIpropName\fR ?\fIoptions...\fR?...?
\fB}\fR

\fIobjectName \fBconfigure\fR
\fIobjectName \fBconfigure\fI \-prop\fR
\fIobjectName \fBconfigure\fI \-prop value\fR ?\fI\-prop value\fR...
.fi
.SH "CLASS HIERARCHY"
.nf
\fBoo::object\fR
   \(-> \fBoo::class\fR
       \(-> \fBoo::configurable\fR

\fBoo::object\fR
   \(-> \fBoo::class\fR
       \(-> \fBoo::configurablesupport::configurable\fR
.fi
.BE
.SH DESCRIPTION
.PP
Configurable objects are objects that support being configured with a
\fBconfigure\fR method. Each of the configurable entities of the object is
known as a property of the object. Properties may be defined on classes or
instances; when configuring an object, any of the properties defined by its
classes (direct or indirect) or by the instance itself may be configured.
.PP
The \fBoo::configurable\fR metaclass installs basic support for making
configurable objects into a class. This consists of making a \fBproperty\fR
definition command available in definition scripts for the class and instances
(e.g., from the class's constructor, within \fBoo::define\fR and within
\fBoo::objdefine\fR) and making a \fBconfigure\fR method available within the
instances.
.SS "CONFIGURE METHOD"
.\" METHOD: configure
.PP
The behavior of the \fBconfigure\fR method is modelled after the
\fBfconfigure\fR/\fBchan configure\fR command.
.PP
If passed no additional arguments, the \fBconfigure\fR method returns an
alphabetically sorted dictionary of all \fIreadable\fR and \fIread-write\fR
properties and their current values.
.PP
If passed a single additional argument, that argument to the \fBconfigure\fR
method must be the name of a property to read (or an unambiguous prefix
thereof); its value is returned.
.PP
Otherwise, if passed an even number of arguments then each pair of arguments
specifies a property name (or an unambiguous prefix thereof) and the value to
set it to. The properties will be set in the order specified, including
duplicates. If the setting of any property fails, the overall \fBconfigure\fR
method fails, the preceding pairs (if any) will continue to have been applied,
and the succeeding pairs (if any) will be not applied. On success, the result
of the \fBconfigure\fR method in this mode operation will be an empty string.
.SS "PROPERTY DEFINITIONS"
.\" COMMAND: property
.PP
When a class has been manufactured by the \fBoo::configurable\fR metaclass (or
one of its subclasses), it gains an extra definition, \fBproperty\fR. The
\fBproperty\fR definition defines one or more properties that will be exposed
by the class's instances.
.PP
The \fBproperty\fR command takes the name of a property to define first,
\fIwithout a leading hyphen\fR, followed by a number of option-value pairs
that modify the basic behavior of the property. This can then be followed by
an arbitrary number of other property definitions. The supported options are:
.\" OPTION: -get
.TP
\fB\-get \fIgetterScript\fR
.
This defines the implementation of how to read from the property; the
\fIgetterScript\fR will become the body of a method (taking no arguments)
defined on the class, if the kind of the property is such that the property
can be read from. The method will be named
\fB<ReadProp-\fIpropertyName\fB>\fR, and will default to being a simple read
of the instance variable with the same name as the property (e.g.,
.QW "\fBproperty\fR xyz"
will result in a method
.QW <ReadProp-xyz>
being created).
.\" OPTION: -kind
.TP
\fB\-kind \fIpropertyKind\fR
.
This defines what sort of property is being created. The \fIpropertyKind\fR
must be exactly one of \fBreadable\fR, \fBwritable\fR, or \fBreadwrite\fR
(which is the default) which will make the property read-only, write-only or
read-write, respectively.  Read-only properties can only ever be read from,
write-only properties can only ever be written to, and read-write properties
can be both read and written.
.RS
.PP
Note that write-only properties are not particularly discoverable as they are
never reported by the \fBconfigure\fR method other than by error messages when
attempting to write to a property that does not exist.
.RE
.\" OPTION: -set
.TP
\fB\-set \fIsetterScript\fR
.
This defines the implementation of how to write to the property; the
\fIsetterScript\fR will become the body of a method taking a single argument,
\fIvalue\fR, defined on the class, if the kind of the property is such that
the property can be written to. The method will be named
\fB<WriteProp-\fIpropertyName\fB>\fR, and will default to being a simple write
of the instance variable with the same name as the property (e.g.,
.QW "\fBproperty\fR xyz"
will result in a method
.QW <WriteProp-xyz>
being created).
.PP
Instances of the class that was created by \fBoo::configurable\fR will also
support \fBproperty\fR definitions; the semantics will be exactly as above
except that the properties will be defined on the instance alone.
.PP
Note that the property implementation methods that \fBproperty\fR defines
should not be private, as this makes them inaccessible from the implementation
of \fBconfigure\fR (by design; the property configuration mechanism is
intended for use mainly from outside a class, whereas a class may access
variables directly). The variables accessed by the default implementations of
the properties \fImay\fR be private, if so declared.
.SH "ADVANCED USAGE"
.PP
The configurable class system is comprised of several pieces. The
\fBoo::configurable\fR metaclass works by mixing in a class and setting
definition namespaces during object creation that provide the other bits and
pieces of machinery. The key pieces of the implementation are enumerated here
so that they can be used by other code:
.\" COMMAND: configurable
.TP
\fBoo::configuresupport::configurable\fR
.
This is a class that provides the implementation of the \fBconfigure\fR method
(described above in \fBCONFIGURE METHOD\fR).
.\" NAMESPACE: configurableclass
.TP
\fBoo::configuresupport::configurableclass\fR
.
This is a namespace that contains the definition dialect that provides the
\fBproperty\fR declaration for use in classes (i.e., via \fBoo::define\fR, and
class constructors under normal circumstances), as described above in
\fBPROPERTY DEFINITIONS\fR. It \fBnamespace export\fRs its \fBproperty\fR
command so that it may be used easily in user definition dialects.
.\" NAMESPACE: configurableobject
.TP
\fBoo::configuresupport::configurableobject\fR
.
This is a namespace that contains the definition dialect that provides the
\fBproperty\fR declaration for use in instance objects (i.e., via
\fBoo::objdefine\fR, and the \fBself\fR declaration in \fBoo::define\fR), as
described above in \fBPROPERTY DEFINITIONS\fR. It \fBnamespace export\fRs its
\fBproperty\fR command so that it may be used easily in user definition
dialects.
.PP
The underlying property discovery mechanism relies on four slots (see
\fBoo::define\fR for what that implies) that list the properties that can be
configured. These slots do not themselves impose any semantics on what the
slots mean other than that they have unique names, no important order, can be
inherited and discovered on classes and instances.
.PP
These slots, and their intended semantics, are:
.\" METHOD: readableproperties
.TP
\fBoo::configuresupport::readableproperties\fR
.
The set of properties of a class (not including those from its superclasses)
that may be read from when configuring an instance of the class. This slot can
also be read with the \fBinfo class properties\fR command.
.\" METHOD: writableproperties
.TP
\fBoo::configuresupport::writableproperties\fR
.
The set of properties of a class (not including those from its superclasses)
that may be written to when configuring an instance of the class. This slot
can also be read with the \fBinfo class properties\fR command.
.\" METHOD: objreadableproperties
.TP
\fBoo::configuresupport::objreadableproperties\fR
.
The set of properties of an object instance (not including those from its
classes) that may be read from when configuring the object. This slot can
also be read with the \fBinfo object properties\fR command.
.\" METHOD: objwritableproperties
.TP
\fBoo::configuresupport::objwritableproperties\fR
.
The set of properties of an object instance (not including those from its
classes) that may be written to when configuring the object. This slot can
also be read with the \fBinfo object properties\fR command.
.PP
Note that though these are slots, they are \fInot\fR in the standard
\fBoo::define\fR or \fBoo::objdefine\fR namespaces; in order to use them
inside a definition script, they need to be referred to by full name. This is
because they are intended to be building bricks of configurable property
system, and not directly used by normal user code.
.SS "IMPLEMENTATION NOTE"
.PP
The implementation of the \fBconfigure\fR method uses
\fBinfo object properties\fR with the \fB\-all\fR option to discover what
properties it may manipulate.
.SH EXAMPLES
.PP
Here we create a simple configurable class and demonstrate how it can be
configured:
.PP
.CS
\fBoo::configurable\fR create Point {
    \fBproperty\fR x y
    constructor args {
        my \fBconfigure\fR -x 0 -y 0 {*}$args
    }
    variable x y
    method print {} {
        puts "x=$x, y=$y"
    }
}

set pt [Point new -x 27]
$pt print;   \fI# x=27, y=0\fR
$pt \fBconfigure\fR -y 42
$pt print;   \fI# x=27, y=42\fR
puts "distance from origin: [expr {
    hypot([$pt \fBconfigure\fR -x], [$pt \fBconfigure\fR -y])
}]";         \fI# distance from origin: 49.92995093127971\fR
puts [$pt \fBconfigure\fR]
             \fI# -x 27 -y 42\fR
.CE
.PP
Such a configurable class can be extended by subclassing, though the subclass
needs to also be created by \fBoo::configurable\fR if it will use the
\fBproperty\fR definition:
.PP
.CS
\fBoo::configurable\fR create Point3D {
    superclass Point
    \fBproperty\fR z
    constructor args {
        next -z 0 {*}$args
    }
}

set pt2 [Point3D new -x 2 -y 3 -z 4]
puts [$pt2 \fBconfigure\fR]
             \fI# -x 2 -y 3 -z 4\fR
.CE
.PP
Once you have a configurable class, you can also add instance properties to
it. (The backing variables for all properties start unset.) Note below that we
are using an unambiguous prefix of a property name when setting it; this is
supported for all properties though full names are normally recommended
because subclasses will not make an unambiguous prefix become ambiguous in
that case.
.PP
.CS
oo::objdefine $pt {
    \fBproperty\fR color
}
$pt \fBconfigure\fR -c bisque
puts [$pt \fBconfigure\fR]
             \fI# -color bisque -x 27 -y 42\fR
.CE
.PP
You can also do derived properties by making them read-only and supplying a
script that computes them.
.PP
.CS
\fBoo::configurable\fR create PointMk2 {
    \fBproperty\fR x y
    \fBproperty\fR distance -kind readable -get {
        return [expr {hypot($x, $y)}]
    }
    variable x y
    constructor args {
        my \fBconfigure\fR -x 0 -y 0 {*}$args
    }
}

set pt3 [PointMk2 new -x 3 -y 4]
puts [$pt3 \fBconfigure\fR -distance]
             \fI# 5.0\fR
$pt3 \fBconfigure\fR -distance 10
             \fI# ERROR: bad property "-distance": must be -x or -y\fR
.CE
.PP
Setters are used to validate the type of a property:
.PP
.CS
\fBoo::configurable\fR create PointMk3 {
    \fBproperty\fR x -set {
        if {![string is double -strict $value]} {
            error "-x property must be a number"
        }
        set x $value
    }
    \fBproperty\fR y -set {
        if {![string is double -strict $value]} {
            error "-y property must be a number"
        }
        set y $value
    }
    variable x y
    constructor args {
        my \fBconfigure\fR -x 0 -y 0 {*}$args
    }
}

set pt4 [PointMk3 new]
puts [$pt4 \fBconfigure\fR]
             \fI# -x 0 -y 0\fR
$pt4 \fBconfigure\fR -x 3 -y 4
puts [$pt4 \fBconfigure\fR]
             \fI# -x 3 -y 4\fR
$pt4 \fBconfigure\fR -x "obviously not a number"
             \fI# ERROR: -x property must be a number\fR
.CE
.SH "SEE ALSO"
info(n), oo::class(n), oo::define(n)
.SH KEYWORDS
class, object, properties, configuration
.\" Local variables:
.\" mode: nroff
.\" fill-column: 78
.\" End:

Added doc/const.n.






















































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
'\"
'\" Copyright (c) 2023 Donal K. Fellows
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH const n 9.0 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
const \- create and initialize a constant
.SH SYNOPSIS
\fBconst \fIvarName value\fR
.BE
.SH DESCRIPTION
.PP
This command is normally used within a procedure body (or method body,
or lambda term) to create a constant within that procedure, or within a
\fBnamespace eval\fR body to create a constant within that namespace.
The constant is an unmodifiable variable, called \fIvarName\fR, that is
initialized with \fIvalue\fR.
The result of \fBconst\fR is always the empty string on success.
.PP
If a variable \fIvarName\fR does not exist, it is created with its value set
to \fIvalue\fR and marked as a constant; this means that no other command
(e.g., \fBset\fR, \fBappend\fR, \fBincr\fR, \fBunset\fR)
may modify or remove the variable; variables are checked for whether they
are constants before any traces are called.
If a variable \fIvarName\fR already exists, it is an error unless that
variable is marked as a constant (in which case \fBconst\fR is a no-op).
.PP
The \fIvarName\fR may not be a qualified name or reference an element of an
array by any means. If the variable exists and is an array, that is an error.
.PP
Constants are normally only removed by their containing procedure exiting or
their namespace being deleted.
.SH EXAMPLES
.PP
Create a constant in a procedure:
.PP
.CS
proc foo {a b} {
    \fBconst\fR BAR 12345
    return [expr {$a + $b + $BAR}]
}
.CE
.PP
Create a constant in a namespace to factor out a regular expression:
.PP
.CS
namespace eval someNS {
    \fBconst\fR FOO_MATCHER {(?i)}\emfoo\eM}

    proc findFoos str {
        variable FOO_MATCHER
        regexp -all $FOO_MATCHER $str
    }

    proc findFooIndices str {
        variable FOO_MATCHER
        regexp -all -indices $FOO_MATCHER $str
    }
}
.CE
.PP
Making a constant in a loop doesn't error:
.PP
.CS
proc foo {n} {
    set result {}
    for {set i 0} {$i < $n} {incr i} {
        \fBconst\fR X 123
	lappend result [expr {$X + $i**2}]
    }
}
.CE
.SH "SEE ALSO"
proc(n), namespace(n), set(n), unset(n)
.SH KEYWORDS
namespace, procedure, variable, constant
.\" Local variables:
.\" mode: nroff
.\" fill-column: 78
.\" End:

Changes to doc/cookiejar.n.

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
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







-
+




-
-
+
+











+











+









+








+



-
+

+






+



-
+



+





+




+









+





-
-
+
+




+

-
+





+

-
+





+

-
+



+

-
+








-
-
+
-

-
-
+
-

-
-
+
-






+

-
+




+

-
+
















-
+



-
+


















-
+



-
+









.SH NAME
cookiejar \- Implementation of the Tcl http package cookie jar protocol
.SH SYNOPSIS
.nf
\fBpackage require\fR \fBcookiejar\fR ?\fB0.1\fR?

\fB::http::cookiejar configure\fR ?\fIoptionName\fR? ?\fIoptionValue\fR?
\fB::http::cookiejar create\fR \fIname\fR ?\fIfilename\fR?
\fB::http::cookiejar create\fI name\fR ?\fIfilename\fR?
\fB::http::cookiejar new\fR ?\fIfilename\fR?

\fIcookiejar\fR \fBdestroy\fR
\fIcookiejar\fR \fBforceLoadDomainData\fR
\fIcookiejar\fR \fBgetCookies\fR \fIprotocol host path\fR
\fIcookiejar\fR \fBstoreCookie\fR \fIoptions\fR
\fIcookiejar\fR \fBgetCookies\fI protocol host path\fR
\fIcookiejar\fR \fBstoreCookie\fI options\fR
\fIcookiejar\fR \fBlookup\fR ?\fIhost\fR? ?\fIkey\fR?
.fi
.SH DESCRIPTION
.PP
The cookiejar package provides an implementation of the http package's cookie
jar protocol using an SQLite database. It provides one main command,
\fB::http::cookiejar\fR, which is a TclOO class that should be instantiated to
create a cookie jar that manages a particular HTTP session.
.PP
The database management policy can be controlled at the package level by the
\fBconfigure\fR method on the \fB::http::cookiejar\fR class object:
.\" METHOD: configure
.TP
\fB::http::cookiejar configure\fR ?\fIoptionName\fR? ?\fIoptionValue\fR?
.
If neither \fIoptionName\fR nor \fIoptionValue\fR are supplied, this returns a
copy of the configuration as a Tcl dictionary. If just \fIoptionName\fR is
supplied, just the value of the named option is returned. If both
\fIoptionName\fR and \fIoptionValue\fR are given, the named option is changed
to be the given value.
.RS
.PP
Supported options are:
.\" OPTION: -domainfile
.TP
\fB\-domainfile \fIfilename\fR
.
A file (defaulting to within the cookiejar package) with a description of the
list of top-level domains (e.g., \fB.com\fR or \fB.co.jp\fR). Such domains
\fImust not\fR accept cookies set upon them. Note that the list of such
domains is both security-sensitive and \fInot\fR constant and should be
periodically refetched. Cookie jars maintain their own cache of the domain
list.
.\" OPTION: -domainlist
.TP
\fB\-domainlist \fIurl\fR
.
A URL to fetch the list of top-level domains (e.g., \fB.com\fR or
\fB.co.jp\fR) from.  Such domains \fImust not\fR accept cookies set upon
them. Note that the list of such domains is both security-sensitive and
\fInot\fR constant and should be periodically refetched. Cookie jars maintain
their own cache of the domain list.
.\" OPTION: -domainrefresh
.TP
\fB\-domainrefresh \fIintervalMilliseconds\fR
.
The number of milliseconds between checks of the \fI\-domainlist\fR for new
The number of milliseconds between checks of the \fB\-domainlist\fR for new
domains.
.\" OPTION: -loglevel
.TP
\fB\-loglevel \fIlevel\fR
.
The logging level of this package. The logging level must be (in order of
decreasing verbosity) one of \fBdebug\fR, \fBinfo\fR, \fBwarn\fR, or
\fBerror\fR.
.\" OPTION: -offline
.TP
\fB\-offline \fIflag\fR
.
Allows the cookie managment engine to be placed into offline mode. In offline
Allows the cookie management engine to be placed into offline mode. In offline
mode, the list of domains is read immediately from the file configured in the
\fB\-domainfile\fR option, and the \fB\-domainlist\fR option is not used; it
also makes the \fB\-domainrefresh\fR option be effectively ignored.
.\" OPTION: -purgeold
.TP
\fB\-purgeold \fIintervalMilliseconds\fR
.
The number of milliseconds between checks of the database for expired
cookies; expired cookies are deleted.
.\" OPTION: -retain
.TP
\fB\-retain \fIcookieCount\fR
.
The maximum number of cookies to retain in the database.
.\" OPTION: -vacuumtrigger
.TP
\fB\-vacuumtrigger \fIdeletionCount\fR
.
A count of the number of persistent cookie deletions to go between vacuuming
the database.
.RE
.PP
Cookie jar instances may be made with any of the standard TclOO instance
creation methods (\fBcreate\fR or \fBnew\fR).
.\" METHOD: new
.TP
\fB::http::cookiejar new\fR ?\fIfilename\fR?
.
If a \fIfilename\fR argument is provided, it is the name of a file containing
an SQLite database that will contain the persistent cookies maintained by the
cookie jar; the database will be created if the file does not already
exist. If \fIfilename\fR is not supplied, the database will be held entirely within
cookie jar; the database will be created if the file does not already exist.
If \fIfilename\fR is not supplied, the database will be held entirely within
memory, which effectively forces all cookies within it to be session cookies.
.SS "INSTANCE METHODS"
.PP
The following methods are supported on the instances:
.\" METHOD: destroy
.TP
\fIcookiejar\fR \fBdestroy\fR
\fIcookiejar \fBdestroy\fR
.
This is the standard TclOO destruction method. It does \fInot\fR delete the
SQLite database if it is written to disk. Callers are responsible for ensuring
that the cookie jar is not in use by the http package at the time of
destruction.
.\" METHOD: forceLoadDomainData
.TP
\fIcookiejar\fR \fBforceLoadDomainData\fR
\fIcookiejar \fBforceLoadDomainData\fR
.
This method causes the cookie jar to immediately load (and cache) the domain
list data. The domain list will be loaded from the \fB\-domainlist\fR
configured a the package level if that is enabled, and otherwise will be
obtained from the \fB\-domainfile\fR configured at the package level.
.\" METHOD: getCookies
.TP
\fIcookiejar\fR \fBgetCookies\fR \fIprotocol host path\fR
\fIcookiejar \fBgetCookies\fI protocol host path\fR
.
This method obtains the cookies for a particular HTTP request. \fIThis
implements the http cookie jar protocol.\fR
.\" METHOD: policyAllow
.TP
\fIcookiejar\fR \fBpolicyAllow\fR \fIoperation domain path\fR
\fIcookiejar \fBpolicyAllow\fI operation domain path\fR
.
This method is called by the \fBstoreCookie\fR method to get a decision on
whether to allow \fIoperation\fR to be performed for the \fIdomain\fR and
\fIpath\fR. This is checked immediately before the database is updated but
after the built-in security checks are done, and should return a boolean
value; if the value is false, the operation is rejected and the database is
not modified. The supported \fIoperation\fRs are:
.RS
.TP
\fBdelete\fR
.IP \fBdelete\fR
.
The \fIdomain\fR is seeking to delete a cookie.
.TP
\fBsession\fR
.IP \fBsession\fR
.
The \fIdomain\fR is seeking to create or update a session cookie.
.TP
\fBset\fR
.IP \fBset\fR
.
The \fIdomain\fR is seeking to create or update a persistent cookie (with a
defined lifetime).
.PP
The default implementation of this method just returns true, but subclasses of
this class may impose their own rules.
.RE
.\" METHOD: storeCookie
.TP
\fIcookiejar\fR \fBstoreCookie\fR \fIoptions\fR
\fIcookiejar \fBstoreCookie\fI options\fR
.
This method stores a single cookie from a particular HTTP response. Cookies
that fail security checks are ignored. \fIThis implements the http cookie jar
protocol.\fR
.\" METHOD: lookup
.TP
\fIcookiejar\fR \fBlookup\fR ?\fIhost\fR? ?\fIkey\fR?
\fIcookiejar \fBlookup\fR ?\fIhost\fR? ?\fIkey\fR?
.
This method looks a cookie by exact host (or domain) matching. If neither
\fIhost\fR nor \fIkey\fR are supplied, the list of hosts for which a cookie is
stored is returned. If just \fIhost\fR (which may be a hostname or a domain
name) is supplied, the list of cookie keys stored for that host is returned.
If both \fIhost\fR and \fIkey\fR are supplied, the value for that key is
returned; it is an error if no such host or key match exactly.
.SH "EXAMPLES"
.PP
The simplest way of using a cookie jar is to just permanently configure it at
the start of the application.
.PP
.CS
package require http
\fBpackage require cookiejar\fR

set cookiedb ~/.tclcookies.db
set cookiedb [file join [file home] cookiejar]
http::configure -cookiejar [\fBhttp::cookiejar new\fR $cookiedb]

# No further explicit steps are required to use cookies
set tok [http::geturl http://core.tcl.tk/]
set tok [http::geturl http://core.tcl-lang.org/]
.CE
.PP
To only allow a particular domain to use cookies, perhaps because you only
want to enable a particular host to create and manipulate sessions, create a
subclass that imposes that policy.
.PP
.CS
package require http
\fBpackage require cookiejar\fR

oo::class create MyCookieJar {
    superclass \fBhttp::cookiejar\fR

    method \fBpolicyAllow\fR {operation domain path} {
        return [expr {$domain eq "my.example.com"}]
    }
}

set cookiedb ~/.tclcookies.db
set cookiedb [file join [file home] cookiejar]
http::configure -cookiejar [MyCookieJar new $cookiedb]

# No further explicit steps are required to use cookies
set tok [http::geturl http://core.tcl.tk/]
set tok [http::geturl http://core.tcl-lang.org/]
.CE
.SH "SEE ALSO"
http(n), oo::class(n), sqlite3(n)
.SH KEYWORDS
cookie, internet, security policy, www
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/copy.n.

8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
oo::copy \- create copies of objects and classes
.SH SYNOPSIS
.nf
package require TclOO
package require tcl::oo

\fBoo::copy\fI sourceObject \fR?\fItargetObject\fR? ?\fItargetNamespace\fR?
.fi
.BE
.SH DESCRIPTION
.PP
The \fBoo::copy\fR command creates a copy of an object or class. It takes the

Changes to doc/coroutine.n.

9
10
11
12
13
14
15

16
17

18
19

20
21
22
23
24
25
26
9
10
11
12
13
14
15
16
17

18
19

20
21
22
23
24
25
26
27







+

-
+

-
+







.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
coroutine, yield, yieldto, coroinject, coroprobe \- Create and produce values from coroutines
.SH SYNOPSIS
.nf
\fBcoroutine \fIname command\fR ?\fIarg...\fR?

\fByield\fR ?\fIvalue\fR?
\fByieldto\fR \fIcommand\fR ?\fIarg...\fR?
\fByieldto\fI command\fR ?\fIarg...\fR?
\fIname\fR ?\fIvalue...\fR?
.sp

.VS "8.7, TIP383"
\fBcoroinject \fIcoroName command\fR ?\fIarg...\fR?
\fBcoroprobe \fIcoroName command\fR ?\fIarg...\fR?
.VE "8.7, TIP383"
.fi
.BE
.SH DESCRIPTION
93
94
95
96
97
98
99
100

101
102
103
104
105
106
107
94
95
96
97
98
99
100

101
102
103
104
105
106
107
108







-
+







with quite a bit of similarity to \fBcoroprobe\fR. However, with
\fBcoroinject\fR there are several key differences:
.VE "8.7, TIP383"
.IP \(bu
.VS "8.7, TIP383"
The coroutine is not immediately resumed after the injection has been done.  A
consequence of this is that multiple injections may be done before the
coroutine is resumed. There injected commands are performed in \fIreverse
coroutine is resumed. The injected commands are performed in \fIreverse
order of definition\fR (that is, they are internally stored on a stack).
.VE "8.7, TIP383"
.IP \(bu
.VS "8.7, TIP383"
An additional two arguments are appended to the list of arguments to be run
(that is, the \fIcommand\fR and its \fIargs\fR are extended by two elements).
The first is the name of the command that suspended the coroutine (\fByield\fR
115
116
117
118
119
120
121
122




123
124
125
126
127
128
129
116
117
118
119
120
121
122

123
124
125
126
127
128
129
130
131
132
133







-
+
+
+
+







multiple injected commands, the result of one becomes the resumption value
processed by the next.
.PP
The injection is a one-off. It is not retained once it has been executed. It
may \fByield\fR or \fByieldto\fR as part of its execution.
.PP
Note that running coroutines may be neither probed nor injected; the
operations may only be applied to
operations may only be applied to coroutines that are suspended. (If a
coroutine is running then any introspection code would be merely inspecting
the state of where it is currently running; \fBcoroinject\fR/\fBcoroprobe\fR
are unnecessary in that case.)
.VE "8.7, TIP383"
.SH EXAMPLES
.PP
This example shows a coroutine that will produce an infinite sequence of
even values, and a loop that consumes the first ten of them.
.PP
.CS
191
192
193
194
195
196
197
198

199
200
201
202
203
204
205
195
196
197
198
199
200
201

202
203
204
205
206
207
208
209







-
+







proc juggler {name target {value ""}} {
    if {$value eq ""} {
        set value [\fByield\fR [info coroutine]]
    }
    while {$value ne ""} {
        puts "$name : $value"
        set value [string range $value 0 end-1]
        lassign [\fByieldto\fR \fI$target\fR $value] value
        lassign [\fByieldto\fI $target\fR $value] value
    }
}
\fBcoroutine\fR j1 juggler Larry [
    \fBcoroutine\fR j2 juggler Curly [
        \fBcoroutine\fR j3 juggler Moe j1]] "Nyuck!Nyuck!Nyuck!"
.CE
.PP
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
241
242
243
244
245
246
247




248
249
250
251
252
253
254







-
-
-
-







\fIcollect\fR rst
# ==> Received 'rst' at a yield in ::collect
\fIcollect\fR xyz

puts [\fIcollect\fR]
# ==> 123 {abc def} 456 pqr RST xyz
.CE
.PP
This example shows a simple coroutine that collects non-empty values and
returns a list of them when not given an argument. It also shows how we can
look inside the coroutine to find out what it is doing.
.VE "8.7, TIP383"
.SS "DETAILED SEMANTICS"
.PP
This example demonstrates that coroutines start from the global namespace, and
that \fIcommand\fR resolution happens before the coroutine stack is created.
.PP
.CS

Changes to doc/dde.n.

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
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







-
+

-
+

-

-

-

-

-

+

-
















+







.TH dde n 1.4 dde "Tcl Bundled Packages"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
dde \- Execute a Dynamic Data Exchange command
.SH SYNOPSIS
.sp
.nf
\fBpackage require dde 1.4\fR
.sp

\fBdde servername\fR ?\fB\-force\fR? ?\fB\-handler \fIproc\fR? ?\fB\-\|\-\fR? ?\fItopic\fR?
.sp
\fBdde execute\fR ?\fB\-async\fR? ?\fB\-binary\fR? \fIservice topic data\fR
.sp
\fBdde poke\fR ?\fB\-binary\fR? \fIservice topic item data\fR
.sp
\fBdde request\fR ?\fB\-binary\fR? \fIservice topic item\fR
.sp
\fBdde services \fIservice topic\fR
.sp
\fBdde eval\fR ?\fB\-async\fR? \fItopic cmd \fR?\fIarg arg ...\fR?
.fi
.BE

.SH DESCRIPTION
.PP
This command allows an application to send Dynamic Data Exchange (DDE)
command when running under Microsoft Windows. Dynamic Data Exchange is
a mechanism where applications can exchange raw data. Each DDE
transaction needs a \fIservice name\fR and a \fItopic\fR. Both the
\fIservice name\fR and \fItopic\fR are application defined; Tcl uses
the service name \fBTclEval\fR, while the topic name is the name of the
interpreter given by \fBdde servername\fR. Other applications have their
own \fIservice names\fR and \fItopics\fR. For instance, Microsoft Excel
has the service name \fBExcel\fR.
.PP
.SH "DDE COMMANDS"
.PP
The following commands are a subset of the full Dynamic Data Exchange
set of commands.
.\" METHOD: servername
.TP
\fBdde servername \fR?\fB\-force\fR? ?\fB\-handler \fIproc\fR? ?\fB\-\|\-\fR? ?\fItopic\fR?
.
\fBdde servername\fR registers the interpreter as a DDE server with
the service name \fBTclEval\fR and the topic name specified by \fItopic\fR.
If no \fItopic\fR is given, \fBdde servername\fR returns the name
of the current topic or the empty string if it is not registered as a
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
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







+












+
+





+
+










+
+





+
+











+












+







.PP
The \fB\-handler\fR option specifies a Tcl procedure that will be called to
process calls to the dde server. If the package has been loaded into a
safe interpreter then a \fB\-handler\fR procedure must be defined. The
procedure is called with all the arguments provided by the remote
call.
.RE
.\" METHOD: execute
.TP
\fBdde execute\fR ?\fB\-async\fR? ?\fB\-binary\fR? \fIservice topic data\fR
.
\fBdde execute\fR takes the \fIdata\fR and sends it to the server indicated
by \fIservice\fR with the topic indicated by \fItopic\fR. Typically,
\fIservice\fR is the name of an application, and \fItopic\fR is a file to
work on.  The \fIdata\fR field is given to the remote application.
Typically, the application treats the \fIdata\fR field as a script, and the
script is run in the application.  The \fB\-async\fR option requests
asynchronous invocation.  The command returns an error message if the
script did not run, unless the \fB\-async\fR flag was used, in which case
the command returns immediately with no error.
.RS
.PP
Without the \fB\-binary\fR option all data will be sent in unicode. For
dde clients which don't implement the CF_UNICODE clipboard format, this
will automatically be translated to the system encoding. You can use
the \fB\-binary\fR option in combination with the result of
\fBencoding convertto\fR to send data in any other encoding.
.RE
.\" METHOD: poke
.TP
\fBdde poke\fR ?\fB\-binary\fR? \fIservice topic item data\fR
.
\fBdde poke\fR passes the \fIdata\fR to the server indicated by
\fIservice\fR using the \fItopic\fR and \fIitem\fR specified.  Typically,
\fIservice\fR is the name of an application.  \fItopic\fR is application
specific but can be a command to the server or the name of a file to work
on.  The \fIitem\fR is also application specific and is often not used, but
it must always be non-null.  The \fIdata\fR field is given to the remote
application.
.RS
.PP
Without the \fB\-binary\fR option all data will be sent in unicode. For
dde clients which don't implement the CF_UNICODE clipboard format, this
will automatically be translated to the system encoding. You can use
the \fB\-binary\fR option in combination with the result of
\fBencoding convertto\fR to send data in any other encoding.
.RE
.\" METHOD: request
.TP
\fBdde request\fR ?\fB\-binary\fR? \fIservice topic item\fR
.
\fBdde request\fR is typically used to get the value of something; the
value of a cell in Microsoft Excel or the text of a selection in
Microsoft Word. \fIservice\fR is typically the name of an application,
\fItopic\fR is typically the name of the file, and \fIitem\fR is
application-specific. The command returns the value of \fIitem\fR as
defined in the application.  Normally this is interpreted to be a
string with terminating null.  If \fB\-binary\fR is specified, the
result is returned as a byte array.
.\" METHOD: services
.TP
\fBdde services \fIservice topic\fR
.
\fBdde services\fR returns a list of service-topic pairs that
currently exist on the machine. If \fIservice\fR and \fItopic\fR are
both empty strings ({}), then all service-topic pairs currently
available on the system are returned. If \fIservice\fR is empty and
\fItopic\fR is not, then all services with the specified topic are
returned. If \fIservice\fR is non-empty and \fItopic\fR is, all topics
for a given service are returned. If both are non-empty, if that
service-topic pair currently exists, it is returned; otherwise, an
empty string is returned.
.\" METHOD: eval
.TP
\fBdde eval\fR ?\fB\-async\fR? \fItopic cmd \fR?\fIarg arg ...\fR?
.
\fBdde eval\fR evaluates a command and its arguments using the interpreter
specified by \fItopic\fR. The DDE service must be the \fBTclEval\fR
service.  The \fB\-async\fR option requests asynchronous invocation.  The
command returns an error message if the script did not run, unless the
168
169
170
171
172
173
174
175

176
177
178
179
180
181
182
183
175
176
177
178
179
180
181

182
183
184
185
186
187
188
189
190







-
+








.SH EXAMPLE
.PP
This asks Internet Explorer (which must already be running) to go to a
particularly important website:
.PP
.CS
package require dde
\fBdde execute\fR -async iexplore WWW_OpenURL http://www.tcl.tk/
\fBdde execute\fR -async iexplore WWW_OpenURL http://www.tcl-lang.org/
.CE
.SH "SEE ALSO"
tk(n), winfo(n), send(n)
.SH KEYWORDS
application, dde, name, remote execution
'\"Local Variables:
'\"mode: nroff
'\"End:

Changes to doc/define.n.

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
30
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

30
31
32
33
34
35
36











-
+


-
+





+
+

+
+
+
+
+

-







'\"
'\" Copyright (c) 2007-2018 Donal K. Fellows
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH define n 0.3 TclOO "TclOO Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
oo::define, oo::objdefine \- define and configure classes and objects
oo::define, oo::objdefine, oo::Slot \- define and configure classes and objects
.SH SYNOPSIS
.nf
package require TclOO
package require tcl::oo

\fBoo::define\fI class defScript\fR
\fBoo::define\fI class subcommand arg\fR ?\fIarg ...\fR?
\fBoo::objdefine\fI object defScript\fR
\fBoo::objdefine\fI object subcommand arg\fR ?\fIarg ...\fR?

\fBoo::Slot\fR \fIarg...\fR
.fi
.SH "CLASS HIERARCHY"
.nf
\fBoo::object\fR
   \(-> \fBoo::Slot\fR
.fi
.BE

.SH DESCRIPTION
The \fBoo::define\fR command is used to control the configuration of classes,
and the \fBoo::objdefine\fR command is used to control the configuration of
objects (including classes as instance objects), with the configuration being
applied to the entity named in the \fIclass\fR or the \fIobject\fR argument.
Configuring a class also updates the
configuration of all subclasses of the class and all objects that are
38
39
40
41
42
43
44

45
46
47
48
49
50
51
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58







+







Note that the constructor for \fBoo::class\fR will call \fBoo::define\fR on
the script argument that it is provided. This is a convenient way to create
and define a class in one step.
.SH "CONFIGURING CLASSES"
.PP
The following commands are supported in the \fIdefScript\fR for
\fBoo::define\fR, each of which may also be used in the \fIsubcommand\fR form:
.\" METHOD: classmethod
.TP
\fBclassmethod\fI name\fR ?\fIargList bodyScrip\fR?
.VS TIP478
This creates a class method, or (if \fIargList\fR and \fIbodyScript\fR are
omitted) promotes an existing method on the class object to be a class
method. The \fIname\fR, \fIargList\fR and \fIbodyScript\fR arguments are as in
the \fBmethod\fR definition, below.
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
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







+
















+
















+








+



















+









+







instance of the subclass, the current object is the subclass.
.PP
In a private definition context, the methods as invoked on classes are
\fInot\fR private, but the methods as invoked on instances of classes are
private.
.RE
.VE TIP478
.\" METHOD: constructor
.TP
\fBconstructor\fI argList bodyScript\fR
.
This creates or updates the constructor for a class. The formal arguments to
the constructor (defined using the same format as for the Tcl \fBproc\fR
command) will be \fIargList\fR, and the body of the constructor will be
\fIbodyScript\fR. When the body of the constructor is evaluated, the current
namespace of the constructor will be a namespace that is unique to the object
being constructed. Within the constructor, the \fBnext\fR command should be
used to call the superclasses' constructors. If \fIbodyScript\fR is the empty
string, the constructor will be deleted.
.RS
.PP
Classes do not need to have a constructor defined. If none is specified, the
superclass's constructor will be used instead.
.RE
.\" METHOD: destructor
.TP
\fBdestructor\fI bodyScript\fR
.
This creates or updates the destructor for a class. Destructors take no
arguments, and the body of the destructor will be \fIbodyScript\fR. The
destructor is called when objects of the class are deleted, and when called
will have the object's unique namespace as the current namespace. Destructors
should use the \fBnext\fR command to call the superclasses' destructors. Note
that destructors are not called in all situations (e.g. if the interpreter is
destroyed). If \fIbodyScript\fR is the empty string, the destructor will be
deleted.
.RS
Note that errors during the evaluation of a destructor \fIare not returned\fR
to the code that causes the destruction of an object. Instead, they are passed
to the currently-defined \fBbgerror\fR handler.
.RE
.\" METHOD: export
.TP
\fBexport\fI name \fR?\fIname ...\fR?
.
This arranges for each of the named methods, \fIname\fR, to be exported
(i.e. usable outside an instance through the instance object's command) by the
class being defined. Note that the methods themselves may be actually defined
by a superclass; subclass exports override superclass visibility, and may in
turn be overridden by instances.
.\" METHOD: forward
.TP
\fBforward\fI name cmdName \fR?\fIarg ...\fR?
.
This creates or updates a forwarded method called \fIname\fR. The method is
defined be forwarded to the command called \fIcmdName\fR, with additional
arguments, \fIarg\fR etc., added before those arguments specified by the
caller of the method. The \fIcmdName\fR will always be resolved using the
rules of the invoking objects' namespaces, i.e., when \fIcmdName\fR is not
fully-qualified, the command will be searched for in each object's namespace,
using the instances' namespace's path, or by looking in the global namespace.
The method will be exported if \fIname\fR starts with a lower-case letter, and
non-exported otherwise.
.RS
.PP
.VS TIP500
If in a private definition context (see the \fBprivate\fR definition command,
below), this command creates private forwarded methods.
.VE TIP500
.RE
.\" METHOD: initialise
.TP
\fBinitialise\fI script\fR
.TP
\fBinitialize\fI script\fR
.VS TIP478
This evaluates \fIscript\fR in a context which supports local variables and
where the current namespace is the instance namespace of the class object
itself. This is useful for setting up, e.g., class-scoped variables.
.VE TIP478
.\" METHOD: method
.TP
\fBmethod\fI name \fR?\fIoption\fR? \fIargList bodyScript\fR
.
This creates or updates a method that is implemented as a procedure-like
script. The name of the method is \fIname\fR, the formal arguments to the
method (defined using the same format as for the Tcl \fBproc\fR command) will
be \fIargList\fR, and the body of the method will be \fIbodyScript\fR. When
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
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







+



















+







.PP
.VS TIP500
If in a private definition context (see the \fBprivate\fR definition command,
below) or if the \fB\-private\fR flag is given for \fIoption\fR, this command
creates private procedure-like methods.
.VE TIP500
.RE
.\" METHOD: private
.TP
\fBprivate \fIcmd arg...\fR
.TP
\fBprivate \fIscript\fR
.
.VS TIP500
This evaluates the \fIscript\fR (or the list of command and arguments given by
\fIcmd\fR and \fIarg\fRs) in a context where the definitions made on the
current class will be private definitions.
.RS
.PP
The following class definition commands are affected by \fBprivate\fR:
\fBforward\fR, \fBmethod\fR, \fBself\fR, and \fBvariable\fR. Nesting
\fBprivate\fR inside \fBprivate\fR has no cumulative effect; the innermost
definition context is just a private definition context. All other definition
commands have no difference in behavior when used in a private definition
context.
.RE
.VE TIP500
.\" METHOD: self
.TP
\fBself\fI subcommand arg ...\fR
.TP
\fBself\fI script\fR
.TP
\fBself\fR
.
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
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







+











+









+







.VE TIP470
.VS TIP500
If in a private definition context (see the \fBprivate\fR definition command,
below), the definitions on the class object will also be made in a private
definition context.
.VE TIP500
.RE
.\" METHOD: superclass
.TP
\fBsuperclass\fR ?\fI\-slotOperation\fR? ?\fIclassName ...\fR?
.
This slot (see \fBSLOTTED DEFINITIONS\fR below)
allows the alteration of the superclasses of the class being defined.
Each \fIclassName\fR argument names one class that is to be a superclass of
the defined class. Note that objects must not be changed from being classes to
being non-classes or vice-versa, that an empty parent class is equivalent to
\fBoo::object\fR, and that the parent classes of \fBoo::object\fR and
\fBoo::class\fR may not be modified.
By default, this slot works by replacement.
.\" METHOD: unexport
.TP
\fBunexport\fI name \fR?\fIname ...\fR?
.
This arranges for each of the named methods, \fIname\fR, to be not exported
(i.e. not usable outside the instance through the instance object's command,
but instead just through the \fBmy\fR command visible in each object's
context) by the class being defined. Note that the methods themselves may be
actually defined by a superclass; subclass unexports override superclass
visibility, and may be overridden by instance unexports.
.\" METHOD: variable
.TP
\fBvariable\fR ?\fI\-slotOperation\fR? ?\fIname ...\fR?
.
This slot (see \fBSLOTTED DEFINITIONS\fR below) arranges for each of the named
variables to be automatically made
available in the methods, constructor and destructor declared by the class
being defined. Each variable name must not have any namespace
248
249
250
251
252
253
254

255
256
257
258
259
260
261
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280







+







extremely unlikely.
.VE TIP500
.RE
.SS "ADVANCED CLASS CONFIGURATION OPTIONS"
.PP
The following definitions are also supported, but are not required in simple
programs:
.\" METHOD: definitionnamespace
.TP
\fBdefinitionnamespace\fR ?\fIkind\fR? \fInamespaceName\fR
.VS TIP524
This allows control over what namespace will be used by the \fBoo::define\fR
and \fBoo::objdefine\fR commands to look up the definition commands they
use. When any object has a definition operation applied to it, \fIthe class that
it is an instance of\fR (and its superclasses and mixins) is consulted for
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
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
366
367
368
369
370
371
372
373
374
375
376
377
378







+








+










+








+
















+







+
















+







.PP
The class \fBoo::object\fR has its instance namespace locked to
\fB::oo::objdefine\fR, and the class \fBoo::class\fR has its class namespace
locked to \fB::oo::define\fR. A consequence of this is that effective use of
this feature for classes requires the definition of a metaclass.
.RE
.VE TIP524
.\" METHOD: deletemethod
.TP
\fBdeletemethod\fI name\fR ?\fIname ...\fR?
.
This deletes each of the methods called \fIname\fR from a class. The methods
must have previously existed in that class. Does not affect the superclasses
of the class, nor does it affect the subclasses or instances of the class
(except when they have a call chain through the class being modified) or the
class object itself.
.\" METHOD: filter
.TP
\fBfilter\fR ?\fI\-slotOperation\fR? ?\fImethodName ...\fR?
.
This slot (see \fBSLOTTED DEFINITIONS\fR below)
sets or updates the list of method names that are used to guard whether
method call to instances of the class may be called and what the method's
results are. Each \fImethodName\fR names a single filtering method (which may
be exposed or not exposed); it is not an error for a non-existent method to be
named since they may be defined by subclasses.
By default, this slot works by appending.
.\" METHOD: mixin
.TP
\fBmixin\fR ?\fI\-slotOperation\fR? ?\fIclassName ...\fR?
.
This slot (see \fBSLOTTED DEFINITIONS\fR below)
sets or updates the list of additional classes that are to be mixed into
all the instances of the class being defined. Each \fIclassName\fR argument
names a single class that is to be mixed in.
By default, this slot works by replacement.
.\" METHOD: renamemethod
.TP
\fBrenamemethod\fI fromName toName\fR
.
This renames the method called \fIfromName\fR in a class to \fItoName\fR. The
method must have previously existed in the class, and \fItoName\fR must not
previously refer to a method in that class. Does not affect the superclasses
of the class, nor does it affect the subclasses or instances of the class
(except when they have a call chain through the class being modified), or the
class object itself. Does
not change the export status of the method; if it was exported before, it will
be afterwards.
.SH "CONFIGURING OBJECTS"
.PP
The following commands are supported in the \fIdefScript\fR for
\fBoo::objdefine\fR, each of which may also be used in the \fIsubcommand\fR
form:
.\" METHOD: export
.TP
\fBexport\fI name \fR?\fIname ...\fR?
.
This arranges for each of the named methods, \fIname\fR, to be exported
(i.e. usable outside the object through the object's command) by the object
being defined. Note that the methods themselves may be actually defined by a
class or superclass; object exports override class visibility.
.\" METHOD: forward
.TP
\fBforward\fI name cmdName \fR?\fIarg ...\fR?
.
This creates or updates a forwarded object method called \fIname\fR. The
method is defined be forwarded to the command called \fIcmdName\fR, with
additional arguments, \fIarg\fR etc., added before those arguments specified
by the caller of the method. Forwarded methods should be deleted using the
\fBmethod\fR subcommand. The method will be exported if \fIname\fR starts with
a lower-case letter, and non-exported otherwise.
.RS
.PP
.VS TIP500
If in a private definition context (see the \fBprivate\fR definition command,
below), this command creates private forwarded methods.
.VE TIP500
.RE
.\" METHOD: method
.TP
\fBmethod\fI name \fR?\fIoption\fR? \fIargList bodyScript\fR
.
This creates, updates or deletes an object method. The name of the method is
\fIname\fR, the formal arguments to the method (defined using the same format
as for the Tcl \fBproc\fR command) will be \fIargList\fR, and the body of the
method will be \fIbodyScript\fR. When the body of the method is evaluated, the
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
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







+








+

















+








+







.PP
.VS TIP500
If in a private definition context (see the \fBprivate\fR definition command,
below) or if the \fB\-private\fR flag is given for \fIoption\fR, this command
creates private procedure-like methods.
.VE TIP500
.RE
.\" METHOD: mixin
.TP
\fBmixin\fR ?\fI\-slotOperation\fR? ?\fIclassName ...\fR?
.
This slot (see \fBSLOTTED DEFINITIONS\fR below)
sets or updates a per-object list of additional classes that are to be
mixed into the object. Each argument, \fIclassName\fR, names a single class
that is to be mixed in.
By default, this slot works by replacement.
.\" METHOD: private
.TP
\fBprivate \fIcmd arg...\fR
.TP
\fBprivate \fIscript\fR
.VS TIP500
This evaluates the \fIscript\fR (or the list of command and arguments given by
\fIcmd\fR and \fIarg\fRs) in a context where the definitions made on the
current object will be private definitions.
.RS
.PP
The following class definition commands are affected by \fBprivate\fR:
\fBforward\fR, \fBmethod\fR, and \fBvariable\fR. Nesting \fBprivate\fR inside
\fBprivate\fR has no cumulative effect; the innermost definition context is
just a private definition context. All other definition commands have no
difference in behavior when used in a private definition context.
.RE
.VE TIP500
.\" METHOD: unexport
.TP
\fBunexport\fI name \fR?\fIname ...\fR?
.
This arranges for each of the named methods, \fIname\fR, to be not exported
(i.e. not usable outside the object through the object's command, but instead
just through the \fBmy\fR command visible in the object's context) by the
object being defined. Note that the methods themselves may be actually defined
by a class; instance unexports override class visibility.
.\" METHOD: variable
.TP
\fBvariable\fR ?\fI\-slotOperation\fR? ?\fIname ...\fR?
.
This slot (see \fBSLOTTED DEFINITIONS\fR below) arranges for each of the named
variables to be automatically made available in the methods declared by the
object being defined.  Each variable name must not have any namespace
separators and must not look like an array access. All variables will be
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
467
468
469
470
471
472
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
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







+






+








+











+










+







superclass methods extremely unlikely.
.VE TIP500
.RE
.SS "ADVANCED OBJECT CONFIGURATION OPTIONS"
.PP
The following definitions are also supported, but are not required in simple
programs:
.\" METHOD: class
.TP
\fBclass\fI className\fR
.
This allows the class of an object to be changed after creation. Note that the
class's constructors are not called when this is done, and so the object may
well be in an inconsistent state unless additional configuration work is done.
.\" METHOD: deletemethod
.TP
\fBdeletemethod\fI name\fR ?\fIname ...\fR
.
This deletes each of the methods called \fIname\fR from an object. The methods
must have previously existed in that object (e.g., because it was created
through \fBoo::objdefine method\fR). Does not affect the classes that the
object is an instance of, or remove the exposure of those class-provided
methods in the instance of that class.
.\" METHOD: filter
.TP
\fBfilter\fR ?\fI\-slotOperation\fR? ?\fImethodName ...\fR?
.
This slot (see \fBSLOTTED DEFINITIONS\fR below)
sets or updates the list of method names that are used to guard whether a
method call to the object may be called and what the method's results are.
Each \fImethodName\fR names a single filtering method (which may be exposed or
not exposed); it is not an error for a non-existent method to be named. Note
that the actual list of filters also depends on the filters set upon any
classes that the object is an instance of.
By default, this slot works by appending.
.\" METHOD: renamemethod
.TP
\fBrenamemethod\fI fromName toName\fR
.
This renames the method called \fIfromName\fR in an object to \fItoName\fR.
The method must have previously existed in the object, and \fItoName\fR must
not previously refer to a method in that object. Does not affect the classes
that the object is an instance of and cannot rename in an instance object the
methods provided by those classes (though a \fBoo::objdefine forward\fRed
method may provide an equivalent capability). Does not change the export
status of the method; if it was exported before, it will be afterwards.
.\" METHOD: self
.TP
\fBself \fR
.VS TIP470
This gives the name of the object currently being configured.
.VE TIP470
.SH "PRIVATE METHODS"
.VS TIP500
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
558
559
560
561
562
563
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595

596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630







+
+
-
-
+
+
+




+
+
+
+
+
+
+
+




+





+





+








+
+
+
+

+






+















+

-
+
















+
+
+
+
+
+
+
+
+
+
+







\fBself call\fR).
.VE TIP500
.SH "SLOTTED DEFINITIONS"
Some of the configurable definitions of a class or object are \fIslotted
definitions\fR. This means that the configuration is implemented by a slot
object, that is an instance of the class \fBoo::Slot\fR, which manages a list
of values (class names, variable names, etc.) that comprises the contents of
the slot.
.PP
the slot. The class defines five operations (as methods) that may be done on
the slot:
The \fBoo::Slot\fR class defines six operations (as methods) that may be done
on the slot:
.\" METHOD: -append
.TP
\fIslot\fR \fB\-append\fR ?\fImember ...\fR?
.
This appends the given \fImember\fR elements to the slot definition.
.\" METHOD: -appendifnew
.TP
\fIslot\fR \fB\-appendifnew\fR ?\fImember ...\fR?
.VS TIP558
This appends the given \fImember\fR elements to the slot definition if they
do not already exist.
.VE TIP558
.\" METHOD: -clear
.TP
\fIslot\fR \fB\-clear\fR
.
This sets the slot definition to the empty list.
.\" METHOD: -prepend
.TP
\fIslot\fR \fB\-prepend\fR ?\fImember ...\fR?
.VS TIP516
This prepends the given \fImember\fR elements to the slot definition.
.VE TIP516
.\" METHOD: -remove
.TP
\fIslot\fR \fB\-remove\fR ?\fImember ...\fR?
.VS TIP516
This removes the given \fImember\fR elements from the slot definition.
.VE TIP516
.\" METHOD: -set
.TP
\fIslot\fR \fB\-set\fR ?\fImember ...\fR?
.
This replaces the slot definition with the given \fImember\fR elements.
.PP
A consequence of this is that any use of a slot's default operation where the
first member argument begins with a hyphen will be an error. One of the above
operations should be used explicitly in those circumstances.
.PP
You only need to make an instance of \fBoo::Slot\fR if you are definining your
own slot that behaves like a standard slot.
.PP
.SS "SLOT IMPLEMENTATION"
.\" METHOD: --default-operation
Internally, slot objects also define a method \fB\-\-default\-operation\fR
which is forwarded to the default operation of the slot (thus, for the class
.QW \fBvariable\fR
slot, this is forwarded to
.QW "\fBmy \-append\fR" ),
and these methods which provide the implementation interface:
.\" METHOD: Get
.TP
\fIslot\fR \fBGet\fR
.
Returns a list that is the current contents of the slot, but does not modify
the slot. This method must always be called from a stack frame created by a
call to \fBoo::define\fR or \fBoo::objdefine\fR. This method \fIshould not\fR
return an error unless it is called from outside a definition context or with
the wrong number of arguments.
.RS
.PP
.VS TIP516
The elements of the list should be fully resolved, if that is a meaningful
concept to the slot.
.VE TIP516
.RE
.\" METHOD: Resolve
.TP
\fIslot\fR \fBResolve\fR \fIslotElement\fR
\fIslot\fR \fBResolve\fI slotElement\fR
.VS TIP516
Returns \fIslotElement\fR with a resolution operation applied to it, but does
not modify the slot. For slots of simple strings, this is an operation that
does nothing, whereas for slots of classes, this maps a class name to its
fully-qualified class name.  This method must always be called from a stack
frame created by a call to \fBoo::define\fR or \fBoo::objdefine\fR.  This
method \fIshould not\fR return an error unless it is called from outside a
definition context or with the wrong number of arguments; unresolvable
arguments should be returned as is (as not all slot operations strictly
require that values are resolvable to work).
.RS
.PP
Implementations \fIshould not\fR enforce uniqueness and ordering constraints
in this method; that is the responsibility of the \fBSet\fR method.
.RE
.VE TIP516
.\" METHOD: Resolve
.TP
\fIslot\fR \fBResolve \fIelement\fR
.VS
This converts an element of the slotted collection into its resolved form; for
a simple value, it could just return the value, but for a slot that contains
references to commands or classes it should convert those into their
fully-qualified forms (so they can be compared with \fBstring equals\fR): that
could be done by forwarding to \fBnamespace which\fR or similar.
.VE
.\" METHOD: Set
.TP
\fIslot\fR \fBSet \fIelementList\fR
.
Sets the contents of the slot to the list \fIelementList\fR and returns the
empty string. This method must always be called from a stack frame created by
a call to \fBoo::define\fR or \fBoo::objdefine\fR. This method may return an
error if it rejects the change to the slot contents (e.g., because of invalid
571
572
573
574
575
576
577
578
579








580
581
582
583
584
585
586
638
639
640
641
642
643
644


645
646
647
648
649
650
651
652
653
654
655
656
657
658
659







-
-
+
+
+
+
+
+
+
+







earliest location in the slot that it can.)
.RE
.PP
The implementation of these methods is slot-dependent (and responsible for
accessing the correct part of the class or object definition). Slots also have
an unknown method handler to tie all these pieces together, and they hide
their \fBdestroy\fR method so that it is not invoked inadvertently. It is
\fIrecommended\fR that any user changes to the slot mechanism be restricted to
defining new operations whose names start with a hyphen.
\fIrecommended\fR that any user changes to the slot mechanism itself be
restricted to defining new operations whose names start with a hyphen.
.PP
Note that slot instances are not expected to contain the storage for the slot
they manage; that will be in or attached to the class or object that they
manage. Those instances should provide their own implementations of the
\fBGet\fR and \fBSet\fR methods (and optionally \fBResolve\fR; that defaults
to a do-nothing pass-through).
.PP
.VS TIP516
Most slot operations will initially \fBResolve\fR their argument list, combine
it with the results of the \fBGet\fR method, and then \fBSet\fR the result.
Some operations omit one or both of the first two steps; omitting the third
would result in an idempotent read-only operation (but the standard mechanism
for reading from slots is via \fBinfo class\fR and \fBinfo object\fR).

Changes to doc/dict.n.

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
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







+













+






+







+









+







-
+










+



+















+







.BE
.SH DESCRIPTION
.PP
Performs one of several operations on dictionary values or variables
containing dictionary values (see the \fBDICTIONARY VALUES\fR section
below for a description), depending on \fIoption\fR.  The legal
\fIoption\fRs (which may be abbreviated) are:
.\" METHOD: append
.TP
\fBdict append \fIdictionaryVariable key \fR?\fIstring ...\fR?
.
This appends the given string (or strings) to the value that the given
key maps to in the dictionary value contained in the given variable,
writing the resulting dictionary value back to that variable.
Non-existent keys are treated as if they map to an empty string. The
updated dictionary value is returned.
.VS TIP508
If \fIdictionaryVariable\fR indicates an element that does not exist of an
array that has a default value set, the default value and will be used as the
value of the dictionary prior to the appending operation.
.VE TIP508
.\" METHOD: create
.TP
\fBdict create \fR?\fIkey value ...\fR?
.
Return a new dictionary that contains each of the key/value mappings
listed as arguments (keys and values alternating, with each key being
followed by its associated value.)
.\" METHOD: exists
.TP
\fBdict exists \fIdictionaryValue key \fR?\fIkey ...\fR?
.
This returns a boolean value indicating whether the given key (or path
of keys through a set of nested dictionaries) exists in the given
dictionary value. This returns a true value exactly when \fBdict
get\fR on that path will succeed.
.\" METHOD: filter
.TP
\fBdict filter \fIdictionaryValue filterType arg \fR?\fIarg ...\fR?
.
This takes a dictionary value and returns a new dictionary that
contains just those key/value pairs that match the specified filter
type (which may be abbreviated.)  Supported filter types are:
.RS
.TP
\fBdict filter \fIdictionaryValue \fBkey\fR ?\fIglobPattern ...\fR?
.
The key rule only matches those key/value pairs whose keys match any
of the given patterns (in the style of \fBstring match\fR.)
.TP
\fBdict filter \fIdictionaryValue \fBscript {\fIkeyVariable valueVariable\fB} \fIscript\fR
.
The script rule tests for matching by assigning the key to the
\fIkeyVariable\fR and the value to the \fIvalueVariable\fR, and then evaluating
the given script which should return a boolean value (with the
the given script which should result in a boolean value (with the
key/value pair only being included in the result of the \fBdict
filter\fR when a true value is returned.)  Note that the first
argument after the rule selection word is a two-element list.  If the
\fIscript\fR returns with a condition of \fBTCL_BREAK\fR, no further
key/value pairs are considered for inclusion in the resulting
dictionary, and a condition of \fBTCL_CONTINUE\fR is equivalent to a false
result. The key/value pairs are tested in the order in which the keys
were inserted into the dictionary.
.TP
\fBdict filter \fIdictionaryValue \fBvalue \fR?\fIglobPattern ...\fR?
.
The value rule only matches those key/value pairs whose values match any
of the given patterns (in the style of \fBstring match\fR.)
.RE
.\" METHOD: for
.TP
\fBdict for {\fIkeyVariable valueVariable\fB} \fIdictionaryValue body\fR
.
This command takes three arguments, the first a two-element list of
variable names (for the key and value respectively of each mapping in
the dictionary), the second the dictionary value to iterate across,
and the third a script to be evaluated for each mapping with the key
and value variables set appropriately (in the manner of \fBforeach\fR.)
The result of the command is an empty string. If any evaluation of the
body generates a \fBTCL_BREAK\fR result, no further pairs from the
dictionary will be iterated over and the \fBdict for\fR command will
terminate successfully immediately. If any evaluation of the body
generates a \fBTCL_CONTINUE\fR result, this shall be treated exactly like a
normal \fBTCL_OK\fR result. The order of iteration is the order in
which the keys were inserted into the dictionary.
.\" METHOD: get
.TP
\fBdict get \fIdictionaryValue \fR?\fIkey ...\fR?
.
Given a dictionary value (first argument) and a key (second argument),
this will retrieve the value for that key. Where several keys are
supplied, the behaviour of the command shall be as if the result of
\fBdict get $dictVal $key\fR was passed as the first argument to
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
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







+
+
















+















+








+







+















+







elements in a manner similar to \fBarray get\fR. That is, the first
element of each pair would be the key and the second element would be
the value for that key.
.PP
It is an error to attempt to retrieve a value for a key that is not
present in the dictionary.
.RE
.\" METHOD: getdef
.\" METHOD: getwithdefault
.TP
\fBdict getdef \fIdictionaryValue \fR?\fIkey ...\fR? \fIkey default\fR
.TP
\fBdict getwithdefault \fIdictionaryValue \fR?\fIkey ...\fR? \fIkey default\fR
.VS "8.7, TIP342"
This behaves the same as \fBdict get\fR (with at least one \fIkey\fR
argument), returning the value that the key path maps to in the
dictionary \fIdictionaryValue\fR, except that instead of producing an
error because the \fIkey\fR (or one of the \fIkey\fRs on the key path)
is absent, it returns the \fIdefault\fR argument instead.
.RS
.PP
Note that there must always be at least one \fIkey\fR provided, and that
\fBdict getdef\fR and \fBdict getwithdefault\fR are aliases for each other.
.RE
.VE "8.7, TIP342"
.\" METHOD: incr
.TP
\fBdict incr \fIdictionaryVariable key \fR?\fIincrement\fR?
.
This adds the given increment value (an integer that defaults to 1 if
not specified) to the value that the given key maps to in the
dictionary value contained in the given variable, writing the
resulting dictionary value back to that variable. Non-existent keys
are treated as if they map to 0. It is an error to increment a value
for an existing key if that value is not an integer. The updated
dictionary value is returned.
.VS TIP508
If \fIdictionaryVariable\fR indicates an element that does not exist of an
array that has a default value set, the default value and will be used as the
value of the dictionary prior to the incrementing operation.
.VE TIP508
.\" METHOD: info
.TP
\fBdict info \fIdictionaryValue\fR
.
This returns information (intended for display to people) about the
given dictionary though the format of this data is dependent on the
implementation of the dictionary. For dictionaries that are
implemented by hash tables, it is expected that this will return the
string produced by \fBTcl_HashStats\fR, similar to \fBarray statistics\fR.
.\" METHOD: keys
.TP
\fBdict keys \fIdictionaryValue \fR?\fIglobPattern\fR?
.
Return a list of all keys in the given dictionary value. If a pattern
is supplied, only those keys that match it (according to the rules of
\fBstring match\fR) will be returned. The returned keys will be in the
order that they were inserted into the dictionary.
.\" METHOD: lappend
.TP
\fBdict lappend \fIdictionaryVariable key \fR?\fIvalue ...\fR?
.
This appends the given items to the list value that the given key maps
to in the dictionary value contained in the given variable, writing
the resulting dictionary value back to that variable. Non-existent
keys are treated as if they map to an empty list, and it is legal for
there to be no items to append to the list. It is an error for the
value that the key maps to to not be representable as a list. The
updated dictionary value is returned.
.VS TIP508
If \fIdictionaryVariable\fR indicates an element that does not exist of an
array that has a default value set, the default value and will be used as the
value of the dictionary prior to the list-appending operation.
.VE TIP508
.\" METHOD: map
.TP
\fBdict map \fR{\fIkeyVariable valueVariable\fR} \fIdictionaryValue body\fR
.
This command applies a transformation to each element of a dictionary,
returning a new dictionary. It takes three arguments: the first is a
two-element list of variable names (for the key and value respectively of each
mapping in the dictionary), the second the dictionary value to iterate across,
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
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







+








+








+








+













+




+
















+







map\fR command will terminate successfully immediately. If the evaluation of
the body for a particular step generates a \fBcontinue\fR result, the current
iteration is aborted and the accumulator dictionary is not modified. The order
of iteration is the natural order of the dictionary (typically the order in
which the keys were added to the dictionary; the order is the same as that
used in \fBdict for\fR).
.RE
.\" METHOD: merge
.TP
\fBdict merge \fR?\fIdictionaryValue ...\fR?
.
Return a dictionary that contains the contents of each of the
\fIdictionaryValue\fR arguments.  Where two (or more) dictionaries
contain a mapping for the same key, the resulting dictionary maps that
key to the value according to the last dictionary on the command line
containing a mapping for that key.
.\" METHOD: remove
.TP
\fBdict remove \fIdictionaryValue \fR?\fIkey ...\fR?
.
Return a new dictionary that is a copy of an old one passed in as
first argument except without mappings for each of the keys listed.
It is legal for there to be no keys to remove, and it also legal for
any of the keys to be removed to not be present in the input
dictionary in the first place.
.\" METHOD: replace
.TP
\fBdict replace \fIdictionaryValue \fR?\fIkey value ...\fR?
.
Return a new dictionary that is a copy of an old one passed in as
first argument except with some values different or some extra
key/value pairs added. It is legal for this command to be called with
no key/value pairs, but illegal for this command to be called with a
key but no value.
.\" METHOD: set
.TP
\fBdict set \fIdictionaryVariable key \fR?\fIkey ...\fR? \fIvalue\fR
.
This operation takes the name of a variable containing a dictionary
value and places an updated dictionary value in that variable
containing a mapping from the given key to the given value. When
multiple keys are present, this operation creates or updates a chain
of nested dictionaries. The updated dictionary value is returned.
.VS TIP508
If \fIdictionaryVariable\fR indicates an element that does not exist of an
array that has a default value set, the default value and will be used as the
value of the dictionary prior to the value insert/update operation.
.VE TIP508
.\" METHOD: size
.TP
\fBdict size \fIdictionaryValue\fR
.
Return the number of key/value mappings in the given dictionary value.
.\" METHOD: unset
.TP
\fBdict unset \fIdictionaryVariable key \fR?\fIkey ...\fR?
.
This operation (the companion to \fBdict set\fR) takes the name of a
variable containing a dictionary value and places an updated
dictionary value in that variable that does not contain a mapping for
the given key. Where multiple keys are present, this describes a path
through nested dictionaries to the mapping to remove. At least one key
must be specified, but the last key on the key-path need not exist.
All other components on the path must exist. The updated dictionary
value is returned.
.VS TIP508
If \fIdictionaryVariable\fR indicates an element that does not exist of an
array that has a default value set, the default value and will be used as the
value of the dictionary prior to the value remove operation.
.VE TIP508
.\" METHOD: update
.TP
\fBdict update \fIdictionaryVariable key varName \fR?\fIkey varName ...\fR? \fIbody\fR
.
Execute the Tcl script in \fIbody\fR with the value for each \fIkey\fR
(as found by reading the dictionary value in \fIdictionaryVariable\fR)
mapped to the variable \fIvarName\fR. There may be multiple
\fIkey\fR/\fIvarName\fR pairs. If a \fIkey\fR does not have a mapping,
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
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







+




+








+







.RS
.PP
Each \fIvarName\fR is mapped in the scope enclosing the \fBdict update\fR;
it is recommended that this command only be used in a local scope
(\fBproc\fRedure, lambda term for \fBapply\fR, or method). Because of
this, the variables set by \fBdict update\fR will continue to
exist after the command finishes (unless explicitly \fBunset\fR).
.PP
Note that the mapping of values to variables
does not use traces; changes to the \fIdictionaryVariable\fR's
contents only happen when \fIbody\fR terminates.
.RE
.\" METHOD: values
.TP
\fBdict values \fIdictionaryValue \fR?\fIglobPattern\fR?
.
Return a list of all values in the given dictionary value. If a
pattern is supplied, only those values that match it (according to the
rules of \fBstring match\fR) will be returned. The returned values
will be in the order of that the keys associated with those values
were inserted into the dictionary.
.\" METHOD: with
.TP
\fBdict with \fIdictionaryVariable \fR?\fIkey ...\fR? \fIbody\fR
.
Execute the Tcl script in \fIbody\fR with the value for each key in
\fIdictionaryVariable\fR mapped (in a manner similarly to \fBdict
update\fR) to a variable with the same name. Where one or more
\fIkey\fRs are available, these indicate a chain of nested
320
321
322
323
324
325
326

327
328
329
330
331
332
333
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359







+







.RS
.PP
The variables are mapped in the scope enclosing the \fBdict with\fR;
it is recommended that this command only be used in a local scope
(\fBproc\fRedure, lambda term for \fBapply\fR, or method). Because of
this, the variables set by \fBdict with\fR will continue to
exist after the command finishes (unless explicitly \fBunset\fR).
.PP
Note that the mapping of values to variables does not use
traces; changes to the \fIdictionaryVariable\fR's contents only happen
when \fIbody\fR terminates.
.PP
If the \fIdictionaryVariable\fR contains a value that is not a dictionary at
the point when the \fIbody\fR terminates (which can easily happen if the name
is the same as any of the keys in dictionary) then an error occurs at that

Changes to doc/encoding.n.

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
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
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
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

-
+














-
+

-
-
+
+
-
-
-
-
-
-









+


+
+
+
+

-
+
-
-
-
-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
+
+

-
-
+
+
-
-
-
-
+
+
+
+
+
+
+
+












+










+

+
+
+
+
+
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+

-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


-
+
+


-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+





'\"
'\" Copyright (c) 1998 by Scriptics Corporation.
'\" Copyright (c) 1998 Scriptics Corporation.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH encoding n "8.1" Tcl "Tcl Built-In Commands"
.so man.macros
.BS
.SH NAME
encoding \- Manipulate encodings
.SH SYNOPSIS
\fBencoding \fIoption\fR ?\fIarg arg ...\fR?
.BE
.SH INTRODUCTION
.PP
Strings in Tcl are logically a sequence of 16-bit Unicode characters.
Strings in Tcl are logically a sequence of Unicode characters.
These strings are represented in memory as a sequence of bytes that
may be in one of several encodings: modified UTF\-8 (which uses 1 to 3
bytes per character), 16-bit
may be in one of several encodings: modified UTF\-8 (which uses 1 to 4
bytes per character), or a custom encoding start as 8 bit binary data.
.QW Unicode
(which uses 2 bytes per character, with an endianness that is
dependent on the host architecture), and binary (which uses a single
byte per character but only handles a restricted range of characters).
Tcl does not guarantee to always use the same encoding for the same
string.
.PP
Different operating system interfaces or applications may generate
strings in other encodings such as Shift\-JIS.  The \fBencoding\fR
command helps to bridge the gap between Unicode and these other
formats.
.SH DESCRIPTION
.PP
Performs one of several encoding related operations, depending on
\fIoption\fR.  The legal \fIoption\fRs are:
.\" METHOD: convertfrom
.TP
\fBencoding convertfrom\fR ?\fIencoding\fR? \fIdata\fR
.VS "TCL8.7 TIP607, TIP656"
.TP
\fBencoding convertfrom\fR ?\fB-profile \fIprofile\fR? ?\fB-failindex var\fR? \fIencoding data\fR
.VE "TCL8.7 TIP607, TIP656"
.
Convert \fIdata\fR to Unicode from the specified \fIencoding\fR.  The
Converts \fIdata\fR, which should be in binary string encoded as per
characters in \fIdata\fR are treated as binary data where the lower
8-bits of each character is taken as a single byte.  The resulting
sequence of bytes is treated as a string in the specified
\fIencoding\fR.  If \fIencoding\fR is not specified, the current
\fIencoding\fR, to a Tcl string. If \fIencoding\fR is not specified, the current
system encoding is used.
.PP
.VS "TCL8.7 TIP607, TIP656"
The \fB-profile\fR option determines the command behavior in the presence
of conversion errors. See the \fBPROFILES\fR section below for details. Any premature
termination of processing due to errors is reported through an exception if
the \fB-failindex\fR option is not specified.
.PP
If the \fB-failindex\fR is specified, instead of an exception being raised
on premature termination, the result of the conversion up to the point of the
error is returned as the result of the command. In addition, the index
of the source byte triggering the error is stored in \fBvar\fR. If no
errors are encountered, the entire result of the conversion is returned and
the value \fB-1\fR is stored in \fBvar\fR.
.VE "TCL8.7 TIP607, TIP656"
.\" METHOD: convertto
.TP
\fBencoding convertto\fR ?\fIencoding\fR? \fIstring\fR
\fBencoding convertto\fR ?\fIencoding\fR? \fIdata\fR
.TP
\fBencoding convertto\fR ?\fB-profile \fIprofile\fR? ?\fB-failindex var\fR? \fIencoding data\fR
.
Convert \fIstring\fR from Unicode to the specified \fIencoding\fR.
The result is a sequence of bytes that represents the converted
Convert \fIstring\fR to the specified \fIencoding\fR. The result is a Tcl binary
string that contains the sequence of bytes representing the converted string in
string.  Each byte is stored in the lower 8-bits of a Unicode
character (indeed, the resulting string is a binary string as far as
Tcl is concerned, at least initially).  If \fIencoding\fR is not
specified, the current system encoding is used.
the specified encoding. If \fIencoding\fR is not specified, the current system
encoding is used.
.PP
.VS "TCL8.7 TIP607, TIP656"
The \fB-profile\fR and \fB-failindex\fR options have the same effect as
described for the \fBencoding convertfrom\fR command.
.VE "TCL8.7 TIP607, TIP656"
.\" METHOD: dirs
.TP
\fBencoding dirs\fR ?\fIdirectoryList\fR?
.
Tcl can load encoding data files from the file system that describe
additional encodings for it to work with. This command sets the search
path for \fB*.enc\fR encoding data files to the list of directories
\fIdirectoryList\fR. If \fIdirectoryList\fR is omitted then the
command returns the current list of directories that make up the
search path. It is an error for \fIdirectoryList\fR to not be a valid
list. If, when a search for an encoding data file is happening, an
element in \fIdirectoryList\fR does not refer to a readable,
searchable directory, that element is ignored.
.\" METHOD: names
.TP
\fBencoding names\fR
.
Returns a list containing the names of all of the encodings that are
currently available.
The encodings
.QW utf-8
and
.QW iso8859-1
are guaranteed to be present in the list.
.\" METHOD: profiles
.TP
\fBencoding profiles\fR
.VS "TCL8.7 TIP656"
Returns a list of the names of encoding profiles. See \fBPROFILES\fR below.
.VE "TCL8.7 TIP656"
.\" METHOD: system
.TP
\fBencoding system\fR ?\fIencoding\fR?
.
Set the system encoding to \fIencoding\fR. If \fIencoding\fR is
omitted then the command returns the current system encoding.  The
system encoding is used whenever Tcl passes strings to system calls.
.\" Do not put .VS on whole section as that messes up the bullet list alignment
.SH PROFILES
.PP
.VS "TCL8.7 TIP656"
Operations involving encoding transforms may encounter several types of
errors such as invalid sequences in the source data, characters that
cannot be encoded in the target encoding and so on.
A \fIprofile\fR prescribes the strategy for dealing with such errors
in one of two ways:
.VE "TCL8.7 TIP656"
.
.IP \(bu
.VS "TCL8.7 TIP656"
Terminating further processing of the source data. The profile does not
determine how this premature termination is conveyed to the caller. By default,
this is signalled by raising an exception. If the \fB-failindex\fR option
is specified, errors are reported through that mechanism.
.VE "TCL8.7 TIP656"
.IP \(bu
.VS "TCL8.7 TIP656"
Continue further processing of the source data using a fallback strategy such
as replacing or discarding the offending bytes in a profile-defined manner.
.VE "TCL8.7 TIP656"
.PP
The following profiles are currently implemented with \fBstrict\fR being
the default if the \fB-profile\fR is not specified.
.VS "TCL8.7 TIP656"
.TP
\fBstrict\fR
.
The \fBstrict\fR profile always stops processing when an conversion error is
encountered. The error is signalled via an exception or the \fB-failindex\fR
option mechanism. The \fBstrict\fR profile implements a Unicode standard
conformant behavior.
.TP
\fBtcl8\fR
.
The \fBtcl8\fR profile always follows the first strategy above and corresponds
to the behavior of encoding transforms in Tcl 8.6. When converting from an
external encoding \fBother than utf-8\fR to Tcl strings with the \fBencoding
convertfrom\fR command, invalid bytes are mapped to their numerically equivalent
code points. For example, the byte 0x80 which is invalid in ASCII would be
mapped to code point U+0080. When converting from \fButf-8\fR, invalid bytes
that are defined in CP1252 are mapped to their Unicode equivalents while those
that are not fall back to the numerical equivalents. For example, byte 0x80 is
defined by CP1252 and is therefore mapped to its Unicode equivalent U+20AC while
byte 0x81 which is not defined by CP1252 is mapped to U+0081. As an additional
special case, the sequence 0xC0 0x80 is mapped to U+0000.

When converting from Tcl strings to an external encoding format using
\fBencoding convertto\fR, characters that cannot be represented in the
target encoding are replaced by an encoding-dependent character, usually
the question mark \fB?\fR.
.TP
\fBreplace\fR
.
Like the \fBtcl8\fR profile, the \fBreplace\fR profile always continues
processing on conversion errors but follows a Unicode standard conformant
method for substitution of invalid source data.

When converting an encoded byte sequence to a Tcl string using
\fBencoding convertfrom\fR, invalid bytes
are replaced by the U+FFFD REPLACEMENT CHARACTER code point.

When encoding a Tcl string with \fBencoding convertto\fR,
code points that cannot be represented in the
target encoding are transformed to an encoding-specific fallback character,
U+FFFD REPLACEMENT CHARACTER for UTF targets and generally `?` for other
encodings.
.VE "TCL8.7 TIP656"
.SH EXAMPLE
.SH EXAMPLES
.PP
These examples use the utility proc below that prints the Unicode code points
comprising a Tcl string.
.PP
.CS
proc codepoints s {join [lmap c [split $s {}] {
    string cat U+ [format %.6X [scan $c %c]]}]
}
.CE
.PP
It is common practice to write script files using a text editor that
produces output in the euc-jp encoding, which represents the ASCII
Example 1: convert a byte sequence in Japanese euc-jp encoding to a TCL string:
characters as singe bytes and Japanese characters as two bytes.  This
makes it easy to embed literal strings that correspond to non-ASCII
characters by simply typing the strings in place in the script.
However, because the \fBsource\fR command always reads files using the
current system encoding, Tcl will only source such files correctly
when the encoding used to write the file is the same.  This tends not
to be true in an internationalized setting.  For example, if such a
file was sourced in North America (where the ISO8859\-1 is normally
used), each byte in the file would be treated as a separate character
that maps to the 00 page in Unicode.  The resulting Tcl strings will
not contain the expected Japanese characters.  Instead, they will
contain a sequence of Latin-1 characters that correspond to the bytes
of the original string.  The \fBencoding\fR command can be used to
convert this string to the expected Japanese Unicode characters.  For
example,
.PP
.CS
set s [\fBencoding convertfrom\fR euc-jp "\exA4\exCF"]
% codepoints [\fBencoding convertfrom\fR euc-jp "\exA4\exCF"]
U+00306F
.CE
.PP
would return the Unicode string
The result is the unicode codepoint
.QW "\eu306F" ,
which is the Hiragana letter HA.
.VS "TCL8.7 TIP607, TIP656"
.PP
Example 2: Error handling based on profiles:
.PP
The letter \fBA\fR is Unicode character U+0041 and the byte "\ex80" is invalid
in ASCII encoding.
.PP
.CS
% codepoints [\fBencoding convertfrom\fR -profile tcl8 ascii A\ex80]
U+000041 U+000080
% codepoints [\fBencoding convertfrom\fR -profile replace ascii A\ex80]
U+000041 U+00FFFD
% codepoints [\fBencoding convertfrom\fR -profile strict ascii A\ex80]
unexpected byte sequence starting at index 1: '\ex80'
.CE
.PP
Example 3: Get partial data and the error location:
.PP
.CS
% codepoints [\fBencoding convertfrom\fR -profile strict -failindex idx ascii AB\ex80]
U+000041 U+000042
% set idx
2
.CE
.PP
Example 4: Encode a character that is not representable in ISO8859-1:
.PP
.CS
% \fBencoding convertto\fR iso8859-1 A\eu0141
A?
% \fBencoding convertto\fR -profile strict iso8859-1 A\eu0141
unexpected character at index 1: 'U+000141'
% \fBencoding convertto\fR -profile strict -failindex idx iso8859-1 A\eu0141
A
% set idx
1
.CE
.VE "TCL8.7 TIP607, TIP656"
.PP
.SH "SEE ALSO"
Tcl_GetEncoding(3)
Tcl_GetEncoding(3), fconfigure(n)
.SH KEYWORDS
encoding, unicode
.\" Local Variables:
.\" mode: nroff
.\" End:

Changes to doc/eof.n.

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
8
9
10
11
12
13
14

15
16
17
18

















19














20








21



22
23
24
25
26







-
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-

-
-
-
+




.TH eof n 7.5 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
eof \- Check for end of file condition on channel
.SH SYNOPSIS
\fBeof \fIchannelId\fR
\fBeof \fIchannel\fR
.BE
.SH DESCRIPTION
.PP
Returns 1 if an end of file condition occurred during the most
recent input operation on \fIchannelId\fR (such as \fBgets\fR),
0 otherwise.
.PP
\fIChannelId\fR must be an identifier for an open channel such as a
Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR),
the return value from an invocation of \fBopen\fR or \fBsocket\fR, or
the result of a channel creation command provided by a Tcl extension.
.SH EXAMPLES
.PP
Read and print out the contents of a file line-by-line:
.PP
.CS
set f [open somefile.txt]
while {1} {
    set line [gets $f]
    if {[\fBeof\fR $f]} {
The \fBeof\fR command has been superceded by the \fBchan eof\fR
        close $f
        break
    }
    puts "Read line: $line"
}
.CE
.PP
Read and print out the contents of a file by fixed-size records:
.PP
.CS
set f [open somefile.dat]
fconfigure $f -translation binary
set recordSize 40
while {1} {
command which supports the same syntax and options.
    set record [read $f $recordSize]
    if {[\fBeof\fR $f]} {
        close $f
        break
    }
    puts "Read record: $record"
}
.CE
.SH "SEE ALSO"
file(n), open(n), close(n), fblocked(n), Tcl_StandardChannels(3)
.SH KEYWORDS
channel, end of file
chan(n)
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/error.n.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
10
11
12
13
14
15
16

17
18
19
20
21
22
23







-







.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
error \- Generate an error
.SH SYNOPSIS
\fBerror \fImessage\fR ?\fIinfo\fR? ?\fIcode\fR?
.BE

.SH DESCRIPTION
.PP
Returns a \fBTCL_ERROR\fR code, which causes command interpretation to be
unwound.  \fIMessage\fR is a string that is returned to the application
to indicate what went wrong.
.PP
The \fB\-errorinfo\fR return option of an interpreter is used

Changes to doc/eval.n.

18
19
20
21
22
23
24

25
26








27
28
29
30
31
32
33
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41







+

-
+
+
+
+
+
+
+
+







.PP
\fBEval\fR takes one or more arguments, which together comprise a Tcl
script containing one or more commands.
\fBEval\fR concatenates all its arguments in the same
fashion as the \fBconcat\fR command, passes the concatenated string to the
Tcl interpreter recursively, and returns the result of that
evaluation (or any error generated by it).
.PP
Note that the \fBlist\fR command quotes sequences of words in such a
way that they are not further expanded by the \fBeval\fR command.
way that they are not further expanded by the \fBeval\fR command;
for \fIany\fR values, $a, $b, and $c, these two lines are effectively
equivalent:
.PP
.CS
\fBeval\fR [list $a $b $c]
$a $b $c
.CE
.SH EXAMPLES
.PP
Often, it is useful to store a fragment of a script in a variable and
execute it later on with extra values appended. This technique is used
in a number of places throughout the Tcl core (e.g. in \fBfcopy\fR,
\fBlsort\fR and \fBtrace\fR command callbacks). This example shows how
to do this using core Tcl commands:
70
71
72
73
74
75
76






77
78
79
80
81
82
83
84
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98







+
+
+
+
+
+








.PP
However, the last line would now normally be written without
\fBeval\fR, like this:
.PP
.CS
set var [linsert $var 0 {*}$args]
.CE
.PP
or indeed like this:
.PP
.CS
set var [list {*}$args {*}$var]
.CE
.SH "SEE ALSO"
catch(n), concat(n), error(n), errorCode(n), errorInfo(n), interp(n), list(n),
namespace(n), subst(n), uplevel(n)
.SH KEYWORDS
concatenate, evaluate, script
'\" Local Variables:
'\" mode: nroff
'\" End:

Changes to doc/exec.n.

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
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







+
+
+
+





+





+





+











-
+







.SH DESCRIPTION
.PP
This command treats its arguments as the specification
of one or more subprocesses to execute.
The arguments take the form of a standard shell pipeline
where each \fIarg\fR becomes one word of a command, and
each distinct command becomes a subprocess.
The result of the command is the standard output of the final subprocess in
the pipeline, interpreted using the system \fBencoding\fR; to use any other
encoding (especially including binary data), the pipeline must be
\fBopen\fRed, configured and read explicitly.
.PP
If the initial arguments to \fBexec\fR start with \fB\-\fR then
they are treated as command-line switches and are not part
of the pipeline specification.  The following switches are
currently supported:
.\" OPTION: -ignorestderr
.TP 13
\fB\-ignorestderr\fR
.
Stops the \fBexec\fR command from treating the output of messages to the
pipeline's standard error channel as an error case.
.\" OPTION: -keepnewline
.TP 13
\fB\-keepnewline\fR
.
Retains a trailing newline in the pipeline's output.
Normally a trailing newline will be deleted.
.\" OPTION: --
.TP 13
\fB\-\|\-\fR
.
Marks the end of switches.  The argument following this one will
be treated as the first \fIarg\fR even if it starts with a \fB\-\fR.
.PP
If an \fIarg\fR (or pair of \fIarg\fRs) has one of the forms
described below then it is used by \fBexec\fR to control the
flow of input and output among the subprocess(es).
Such arguments will not be passed to the subprocess(es).  In forms
such as
.QW "\fB<\fR \fIfileName\fR" ,
.QW "\fB<\fI fileName\fR" ,
\fIfileName\fR may either be in a separate argument from
.QW \fB<\fR
or in the same argument with no intervening space (i.e.
.QW \fB<\fIfileName\fR ).
.TP 15
\fB|\fR
.
190
191
192
193
194
195
196
197

198
199
200
201
202
203
204
197
198
199
200
201
202
203

204
205
206
207
208
209
210
211







-
+







The standard output from the last command in the pipeline will
go to the application's standard output if it has not been
redirected, and error output from all of
the commands in the pipeline will go to the application's
standard error file unless redirected.
.PP
The first word in each command is taken as the command name;
tilde-substitution is performed on it, and if the result contains
if the result contains
no slashes then the directories
in the PATH environment variable are searched for
an executable by the given name.
If the name contains a slash then it must refer to an executable
reachable from the current directory.
No
.QW glob
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

















-
-
-
-
-
-
-
-
-







is decisive.
.PP
Unfortunately, there is currently no way to supply newline character within
an argument to the batch files (\fB.cmd\fR or \fB.bat\fR) or to the command
processor (\fBcmd.exe /c\fR), because this causes truncation of command-line
(also the argument chain) on the first newline character.
But it works properly with an executable (using CommandLineToArgv, etc).
.PP
\fBArgument quoting\fR
.RS
The arguments of the \fBexec\fR command are mapped to the arguments of the called
program. Additional quote characters (\fB"\fR) are automatically  added around
arguments if expected. Special characters are escaped by inserting backslash
characters.
.PP
The MS-Windows environment does execute programs mentioned in the arguments and
called batch files (conspec) replace environment variables, which may have side
effects (vulnerabilities) or break any already existing quoting (for example,
if the environment variable contains a special character like a \fB"\fR).
Examples are:
.CS
% exec my-echo.cmd {test&whoami}
  test
  mylogin
% exec my-echo.cmd "ENV X:%X%"
  ENV X: CONTENT OF X
.CE
The following formatting is automatically performed on any
argument item to avoid subprogram execution:
Any special character argument containing a special character (\fB&\fR, \fB|\fR,
\fB^\fR, \fB<\fR, \fB>\fR, \fB!\fR, \fB(\fR, \fB)\fR, \fB(\fR, \fB%\fR)
is automatically enclosed in quotes (\fB"\fR). Any data quote is escaped by
insertion of backslash characters.
.PP
The automatic resolving of environment variables using "\fB%var%\fR" is critical,
but has more use than danger and is not escaped.
.RE
.PP
The Tk console text widget does not provide real standard IO capabilities.
Under Tk, when redirecting from standard input, all applications will see an
immediate end-of-file; information redirected to standard output or standard
error will be discarded.
.PP
Either forward or backward slashes are accepted as path separators for
arguments to Tcl commands.  When executing an application, the path name
specified for the application may also contain forward or backward slashes
as path separators.  Bear in mind, however, that most Windows applications
accept arguments with forward slashes only as option delimiters and
backslashes only in paths.  Any arguments to an application that specify a
path name with forward slashes will not automatically be converted to use
the backslash character.  If an argument contains forward slashes as the
path separator, it may or may not be recognized as a path name, depending on
the program.
.PP
Additionally, when calling a 16-bit DOS or Windows 3.X application, all path
names must use the short, cryptic, path format (e.g., using
.QW applba~1.def
instead of
.QW applbakery.default ),
which can be obtained with the
.QW "\fBfile attributes\fI fileName \fB\-shortname\fR"
command.
.PP
Two or more forward or backward slashes in a row in a path refer to a
network path.  For example, a simple concatenation of the root directory
\fBc:/\fR with a subdirectory \fB/windows/system\fR will yield
\fBc://windows/system\fR (two slashes together), which refers to the mount
point called \fBsystem\fR on the machine called \fBwindows\fR (and the
\fBc:/\fR is ignored), and is not equivalent to \fBc:/windows/system\fR,
which describes a directory on the current computer.  The \fBfile join\fR
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
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







-
+

-
-
-
+









-
+







application name, the following directories are automatically searched in
order when attempting to locate the application:
.IP \(bu 3
The directory from which the Tcl executable was loaded.
.IP \(bu 3
The current directory.
.IP \(bu 3
The Windows NT 32-bit system directory.
The Windows 32-bit system directory.
.IP \(bu 3
The Windows NT 16-bit system directory.
.IP \(bu 3
The Windows NT home directory.
The Windows home directory.
.IP \(bu 3
The directories listed in the path.
.PP
In order to execute shell built-in commands like \fBdir\fR and \fBcopy\fR,
the caller must prepend the desired command with
.QW "\fBcmd.exe /c\0\fR"
because built-in commands are not implemented using executables.
.RE
.TP
\fBUnix\fR (including Mac OS X)
\fBUnix\fR (including macOS)
.
The \fBexec\fR command is fully functional and works as described.
.SH "UNIX EXAMPLES"
.PP
Here are some examples of the use of the \fBexec\fR command on Unix.
To execute a simple program and get its result:
.PP
418
419
420
421
422
423
424

425

426
427
428
429
430
431
432
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460







+

+







.CE
.PP
With the file \fIcmp.bat\fR looking something like:
.PP
.CS
@gcc %*
.CE
.PP
or like another variant using single parameters:
.PP
.CS
@gcc %1 %2 %3 %4 %5 %6 %7 %8 %9
.CE
.SS "WORKING WITH COMMAND BUILT-INS"
.PP
Sometimes you need to be careful, as different programs may have the
same name and be in the path. It can then happen that typing a command
450
451
452
453
454
455
456
457

458
459
460
461
462
463
464
465
466
467
478
479
480
481
482
483
484

485
486
487
488
489
490
491
492
493
494
495







-
+










Many programs on Windows require filename arguments to be passed in with
backslashes as pathname separators. This is done with the help of the
\fBfile nativename\fR command. For example, to make a directory (on NTFS)
encrypted so that only the current user can access it requires use of
the \fICIPHER\fR command, like this:
.PP
.CS
set secureDir "~/Desktop/Secure Directory"
set secureDir [file join [file home] Desktop/SecureDirectory]
file mkdir $secureDir
\fBexec\fR CIPHER /e /s:[file nativename $secureDir]
.CE
.SH "SEE ALSO"
error(n), file(n), open(n)
.SH KEYWORDS
execute, pipeline, redirection, subprocess
'\" Local Variables:
'\" mode: nroff
'\" End:

Changes to doc/exit.n.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
10
11
12
13
14
15
16

17
18
19
20
21
22
23







-







.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
exit \- End the application
.SH SYNOPSIS
\fBexit \fR?\fIreturnCode\fR?
.BE

.SH DESCRIPTION
.PP
Terminate the process, returning \fIreturnCode\fR to the
system as the exit status.
If \fIreturnCode\fR is not specified then it defaults
to 0.
.SH EXAMPLE

Changes to doc/expr.n.

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
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
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
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



-
+















-
+



















-
-
-
-
+
+
+
+
+
+
+
+
+




-
+

-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+












-
-
-
+
+
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-






-
-
+
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-2000 Sun Microsystems, Inc.
'\" Copyright (c) 2005 by Kevin B. Kenny <kennykb@acm.org>. All rights reserved
'\" Copyright (c) 2005 Kevin B. Kenny <kennykb@acm.org>. All rights reserved
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH expr n 8.5 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
expr \- Evaluate an expression
.SH SYNOPSIS
\fBexpr \fIarg \fR?\fIarg arg ...\fR?
.BE
.SH DESCRIPTION
.PP
The \fIexpr\fR command concatenates \fIarg\fRs, separated by a space, into an expression, and evaluates
Concatenates \fIarg\fRs, separated by a space, into an expression, and evaluates
that expression, returning its value.
The operators permitted in an expression include a subset of
the operators permitted in C expressions.  For those operators
common to both Tcl and C, Tcl applies the same meaning and precedence
as the corresponding C operators.
The value of an expression is often a numeric result, either an integer or a
floating-point value, but may also be a non-numeric value.
For example, the expression
.PP
.CS
\fBexpr\fR 8.2 + 6
.CE
.PP
evaluates to 14.2.
Expressions differ from C expressions in the way that
operands are specified.  Expressions also support
non-numeric operands, string comparisons, and some
additional operators not found in C.
.PP
When an expression evaluates to an integer, the value is the decimal form of
the integer, and when an expression evaluates to a floating-point number, the
value is the form produced by the \fB%g\fR format specifier of Tcl's
\fBformat\fR command.
When the result of expression is an integer, it is in decimal form, and when
the result is a floating-point number, it is in the form produced by the
\fB%g\fR format specifier of \fBformat\fR.
.PP
.VS "TIP 582"
At any point in the expression except within double quotes or braces, \fB#\fR
is the beginning of a comment, which lasts to the end of the line or
the end of the expression, whichever comes first.
.VE "TIP 582"
.SS OPERANDS
.PP
An expression consists of a combination of operands, operators, parentheses and
commas, possibly with whitespace between any of these elements, which is
ignored.
ignored.  Each operand is interpreted as a numeric value if at all possible.
.PP
An operand may be specified in any of the following ways:
.IP [1]
As a numeric value, either integer or floating-point.
.IP [2]
As a boolean value, using any form understood by \fBstring is\fR
Each operand has one of the following forms:
.RS
.TP
A \fBnumeric value\fR
.PP
.RS
Either integer or floating-point.  The first two characters of an integer may
also be \fB0d\fR for decimal, \fB0b\fR for binary, \fB0o\fR for octal or
\fB0x\fR for hexadecimal.
.PP
A floating-point number may be take any of several
common decimal formats, and may use the decimal point \fB.\fR,
\fBe\fR or \fBE\fR for scientific notation, and
the sign characters \fB+\fR and \fB\-\fR.  The
following are all valid floating-point numbers:  2.1, 3., 6e4, 7.91e+16.
The strings \fBInf\fR
and \fBNaN\fR, in any combination of case, are also recognized as floating point
values.  An operand that doesn't have a numeric interpretation must be quoted
with either braces or with double quotes.
.PP
Digits in any numeric value may be separated with one or more underscore
characters, "\fB_\fR".  A separator may only
appear between digits, not appear at the start of a
numeric value, between the leading 0 and radix specifier, or at the
end of a numeric value.  Here are some examples:
.PP
.CS
.ta 9c
\fBexpr\fR 100_000_000		\fI100000000\fR
\fBexpr\fR 0xffff_ffff		\fI4294967295\fR
\fBformat\fR 0x%x 0b1111_1110_1101_1011		\fI0xfedb\fR
\fBexpr\fR 3_141_592_653_589e-1_2		\fI3.141592653589\fR
.CE
.RE
.TP
A \fBboolean value\fR
.
Using any form understood by \fBstring is\fR
\fBboolean\fR.
.IP [3]
As a variable, using standard \fB$\fR notation.
The value of the variable is then the value of the operand.
.IP [4]
As a string enclosed in double-quotes.
Backslash, variable, and command substitution are performed as described in
\fBTcl\fR.
.IP [5]
As a string enclosed in braces.
The operand is treated as a braced value as described in \fBTcl\fR.
.IP [6]
As a Tcl command enclosed in brackets.
Command substitution is performed as described in \fBTcl\fR.
.IP [7]
As a mathematical function such as \fBsin($x)\fR, whose arguments have any of the above
forms for operands.  See \fBMATH FUNCTIONS\fR below for
.TP
A \fBvariable\fR
.
Using standard \fB$\fR notation.
The value of the variable is the value of the operand.
.TP
A string enclosed in \fBdouble-quotes\fR
.
Backslash, variable, and command substitution are performed according to the
rules for \fBTcl\fR.
.TP
A string enclosed in \fBbraces\fR.
.
The operand is treated as a braced value according to the rule for braces in
\fBTcl\fR.
.TP
A Tcl command enclosed in \fBbrackets\fR
.
Command substitution is performed as according to the command substitution rule
for \fBTcl\fR.
.TP
A function call.
.
This is mathematical function such as \fBsin($x)\fR, whose arguments have any of
the above forms for operands.  See \fBMATH FUNCTIONS\fR below for
a discussion of how mathematical functions are handled.
.RE
.PP
Because \fBexpr\fR parses and performs substitutions on values that have
already been parsed and substituted by \fBTcl\fR, it is usually best to enclose
expressions in braces to avoid the first round of substitutions by
\fBTcl\fR.
.PP
Below are some examples of simple expressions where the value of \fBa\fR is 3
and the value of \fBb\fR is 6.  The command on the left side of each line
produces the value on the right side.
.PP
.CS
.ta 9c
\fBexpr\fR 3.1 + $a	\fI6.1\fR
\fBexpr\fR 2 + "$a.$b"	\fI5.6\fR
\fBexpr\fR 4*[llength "6 2"]	\fI8\fR
\fBexpr\fR {3.1 + $a}	\fI6.1\fR
\fBexpr\fR {2 + "$a.$b"}	\fI5.6\fR
\fBexpr\fR {4*[llength {6 2}]}	\fI8\fR
\fBexpr\fR {{word one} < "word $a"}	\fI0\fR
.CE
.PP
\fBInteger value\fR
.PP
An integer operand may be specified in decimal (the normal case, the optional
first two characters are \fB0d\fR), binary
(the first two characters are \fB0b\fR), octal
(the first two characters are \fB0o\fR), or hexadecimal
(the first two characters are \fB0x\fR) form.  For
.PP
\fBFloating-point value\fR
.PP
A floating-point number may be specified in any of several
common decimal formats, and may use the decimal point \fB.\fR,
\fBe\fR or \fBE\fR for scientific notation, and
the sign characters \fB+\fR and \fB\-\fR.  The
following are all valid floating-point numbers:  2.1, 3., 6e4, 7.91e+16.
The strings \fBInf\fR
and \fBNaN\fR, in any combination of case, are also recognized as floating point
values.  An operand that doesn't have a numeric interpretation must be quoted
with either braces or with double quotes.
.PP
\fBBoolean value\fR
.PP
A boolean value may be represented by any of the values \fB0\fR, \fBfalse\fR, \fBno\fR,
or \fBoff\fR and any of the values \fB1\fR, \fBtrue\fR, \fByes\fR, or \fBon\fR.
.PP
\fBDigit Separator\fR
.PP
Digits in any numeric value may be separated with one or more underscore
characters, "\fB_\fR", to improve readability.  These separators may only
appear between digits.  The separator may not appear at the start of a
numeric value, between the leading 0 and radix specifier, or at the
end of a numeric value.  Here are some examples:
.PP
.CS
.ta 9c
\fBexpr\fR 100_000_000		\fI100000000\fR
\fBexpr\fR 0xffff_ffff		\fI4294967295\fR
\fBformat\fR 0x%x 0b1111_1110_1101_1011		\fI0xfedb\fR
.CE
.PP
.SS OPERATORS
.PP
For operators having both a numeric mode and a string mode, the numeric mode is
chosen when all operands have a numeric interpretation.  The integer
interpretation of an operand is preferred over the floating-point
interpretation.  To ensure string operations on arbitrary values it is generally a
good idea to use \fBeq\fR, \fBne\fR, or the \fBstring\fR command instead of
interpretation.  To ensure string operations on arbitrary values it is generally
a good idea to use \fBeq\fR, \fBne\fR, or the \fBstring\fR command instead of
more versatile operators such as \fB==\fR.
.PP
Unless otherwise specified, operators accept non-numeric operands.  The value
of a boolean operation is 1 if true, 0 otherwise.  See also \fBstring is\fR
\fBboolean\fR.  The valid operators, most of which are also available as
commands in the \fBtcl::mathop\fR namespace (see \fBmathop\fR(n)), are listed
below, grouped in decreasing order of precedence:
190
191
192
193
194
195
196
197

198
199
200
201
202
203
204
198
199
200
201
202
203
204

205
206
207
208
209
210
211
212







-
+







comparison operators below, which have the same precedence.
.TP 20
\fBlt\0\0gt\0\0le\0\0ge\fR
.VS "8.7, TIP461"
Boolean string comparisons: less than, greater than, less than or equal, and
greater than or equal. These always compare values using their UNICODE strings
(also see \fBstring compare\fR), unlike with the numeric-preferring
comparisons abov, which have the same precedence.
comparisons above, which have the same precedence.
.VE "8.7, TIP461"
.TP 20
\fB==\0\0!=\fR
.
Boolean equal and not equal.
.TP 20
\fBeq\0\0ne\fR
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
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







-
+













-
-
+
+



















-
+




-
+
+















-
-
-
-
-
-
-
-







.PP
As in C, \fB&&\fR, \fB||\fR, and \fB?:\fR feature
.QW "lazy evaluation" ,
which means that operands are not evaluated if they are
not needed to determine the outcome.  For example, in
.PP
.CS
\fBexpr\fR {$v ? [a] : [b]}
\fBexpr\fR {$v?[a]:[b]}
.CE
.PP
only one of \fB[a]\fR or \fB[b]\fR is evaluated,
depending on the value of \fB$v\fR.  This is not true of the normal Tcl parser,
so it is normally recommended to enclose the arguments to \fBexpr\fR in braces.
Without braces, as in
\fBexpr\fR $v ? [a] : [b]
both \fB[a]\fR and \fB[b]\fR are evaluated before \fBexpr\fR is even called.
.PP
For more details on the results
produced by each operator, see the documentation for C.
.SS "MATH FUNCTIONS"
.PP
A mathematical function such as \fBsin($x)\fR is replaced with a call to an ordinary
Tcl command in the \fBtcl::mathfunc\fR namespace.  The evaluation
A mathematical function such as \fBsin($x)\fR is replaced with a call to an
ordinary Tcl command in the \fBtcl::mathfunc\fR namespace.  The evaluation
of an expression such as
.PP
.CS
\fBexpr\fR {sin($x+$y)}
.CE
.PP
is the same in every way as the evaluation of
.PP
.CS
\fBexpr\fR {[tcl::mathfunc::sin [\fBexpr\fR {$x+$y}]]}
.CE
.PP
which in turn is the same as the evaluation of
.PP
.CS
tcl::mathfunc::sin [\fBexpr\fR {$x+$y}]
.CE
.PP
\fBtcl::mathfunc::sin\fR is resolved as described in
\fBNAMESPACE RESOLUTION\fR in the \fBnamespace\fR(n) documentation.   Given the
\fBNAMESPACE RESOLUTION\fR in the \fBnamespace\fR(n) documentation.  Given the
default value of \fBnamespace path\fR, \fB[namespace
current]::tcl::mathfunc::sin\fR or \fB::tcl::mathfunc::sin\fR are the typical
resolutions.
.PP
As in C, a mathematical function may accept multiple arguments separated by commas. Thus,
As in C, a mathematical function may accept multiple arguments separated by
commas. Thus,
.PP
.CS
\fBexpr\fR {hypot($x,$y)}
.CE
.PP
becomes
.PP
.CS
tcl::mathfunc::hypot $x $y
.CE
.PP
See the \fBmathfunc\fR(n) documentation for the math functions that are
available by default.
.SS "TYPES, OVERFLOW, AND PRECISION"
.PP
When needed to guarantee exact performance, internal computations involving
integers use the LibTomMath multiple precision integer library.  In Tcl releases
prior to 8.5, integer calculations were performed using one of the C types
\fIlong int\fR or \fITcl_WideInt\fR, causing implicit range truncation
in those calculations where values overflowed the range of those types.
Any code that relied on these implicit truncations should instead call
\fBint()\fR or \fBwide()\fR, which do truncate.
.PP
Internal floating-point computations are
performed using the \fIdouble\fR C type.
When converting a string to floating-point value, exponent overflow is
detected and results in the \fIdouble\fR value of \fBInf\fR or
\fB\-Inf\fR as appropriate.  Floating-point overflow and underflow
are detected to the degree supported by the hardware, which is generally
fairly reliable.
375
376
377
378
379
380
381
382
383
384



385
386
387
388


389
390
391
392
393
394
395
376
377
378
379
380
381
382



383
384
385
386



387
388
389
390
391
392
393
394
395







-
-
-
+
+
+

-
-
-
+
+







Where an expression contains syntax that Tcl would otherwise perform
substitutions on, enclosing an expression in braces or otherwise quoting it
so that it's a static value allows the Tcl compiler to generate bytecode for
the expression, resulting in better speed and smaller storage requirements.
This also avoids issues that can arise if Tcl is allowed to perform
substitution on the value before \fBexpr\fR is called.
.PP
In the following example, the value of the expression is 11 because the Tcl parser first
substitutes \fB$b\fR and \fBexpr\fR then substitutes \fB$a\fR as part
of evaluating the expression
In the following example, the value of the expression is 11 because the Tcl
parser first substitutes \fB$b\fR and \fBexpr\fR then substitutes \fB$a\fR as
part of evaluating the expression
.QW "$a + 2*4" .
Enclosing the
expression in braces would result in a syntax error as \fB$b\fR does
not evaluate to a numeric value.
Enclosing the expression in braces would result in a syntax error as \fB$b\fR
does not evaluate to a numeric value.
.PP
.CS
set a 3
set b {$a + 2}
\fBexpr\fR $b*4
.CE
.PP
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
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







+

+


















-
+



+

.CE
.PP
Set a variable indicating whether an environment variable is defined and has
value of true:
.PP
.CS
set isTrue [\fBexpr\fR {
    # Does the environment variable exist, and...
    [info exists ::env(SOME_ENV_VAR)] &&
    # ...does it contain a proper true value?
    [string is true -strict $::env(SOME_ENV_VAR)]
}]
.CE
.PP
Generate a random integer in the range 0..99 inclusive:
.PP
.CS
set randNum [\fBexpr\fR { int(100 * rand()) }]
.CE
.SH "SEE ALSO"
array(n), for(n), if(n), mathfunc(n), mathop(n), namespace(n), proc(n),
string(n), Tcl(n), while(n)
.SH KEYWORDS
arithmetic, boolean, compare, expression, fuzzy comparison, integer value
.SH COPYRIGHT
.nf
Copyright \(co 1993 The Regents of the University of California.
Copyright \(co 1994-2000 Sun Microsystems Incorporated.
Copyright \(co 2005 by Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
Copyright \(co 2005 Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
.fi
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/fblocked.n.

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
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
1
2
3
4
5
6
7
8
9
10
11
12

13
14

15
16

17


























18



















19



20
21
22
23
24












-
+

-


-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
+




'\"
'\" Copyright (c) 1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH fblocked n 7.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
fblocked \- Test whether the last input operation exhausted all available input
.SH SYNOPSIS
\fBfblocked \fIchannelId\fR
\fBfblocked \fIchannel\fR
.BE

.SH DESCRIPTION
.PP
The \fBfblocked\fR command returns 1 if the most recent input operation
The \fBfblocked\fR command has been superceded by the \fBchan blocked\fR
on \fIchannelId\fR returned less information than requested because all
available input was exhausted.
For example, if \fBgets\fR is invoked when there are only three
characters available for input and no end-of-line sequence, \fBgets\fR
returns an empty string and a subsequent call to \fBfblocked\fR will
return 1.
.PP
\fIChannelId\fR must be an identifier for an open channel such as a
Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR),
the return value from an invocation of \fBopen\fR or \fBsocket\fR, or
the result of a channel creation command provided by a Tcl extension.
.SH EXAMPLE
The \fBfblocked\fR command is particularly useful when writing network
servers, as it allows you to write your code in a line-by-line style
without preventing the servicing of other connections.  This can be
seen in this simple echo-service:
.PP
.CS
# This is called whenever a new client connects to the server
proc connect {chan host port} {
    set clientName [format <%s:%d> $host $port]
    puts "connection from $clientName"
    fconfigure $chan -blocking 0 -buffering line
    fileevent $chan readable [list echoLine $chan $clientName]
}

command which supports the same syntax and options.
# This is called whenever either at least one byte of input
# data is available, or the channel was closed by the client.
proc echoLine {chan clientName} {
    gets $chan line
    if {[eof $chan]} {
        puts "finishing connection from $clientName"
        close $chan
    } elseif {![\fBfblocked\fR $chan]} {
        # Didn't block waiting for end-of-line
        puts "$clientName - $line"
        puts $chan $line
    }
}

# Create the server socket and enter the event-loop to wait
# for incoming connections...
socket -server connect 12345
vwait forever
.CE
.SH "SEE ALSO"
gets(n), open(n), read(n), socket(n), Tcl_StandardChannels(3)
.SH KEYWORDS
blocking, nonblocking
chan(n)
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/fconfigure.n.

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
8
9
10
11
12
13
14



15
16
17
18
19
20
21

22







































































































































































































































23


























24


25




26
27
28







-
-
-
+
+
+




-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
+
-
-
-
-



.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
fconfigure \- Set and get options on a channel
.SH SYNOPSIS
.nf
\fBfconfigure \fIchannelId\fR
\fBfconfigure \fIchannelId\fR \fIname\fR
\fBfconfigure \fIchannelId\fR \fIname value \fR?\fIname value ...\fR?
\fBfconfigure \fIchannel\fR
\fBfconfigure \fIchannel name\fR
\fBfconfigure \fIchannel name value \fR?\fIname value ...\fR?
.fi
.BE
.SH DESCRIPTION
.PP
The \fBfconfigure\fR command sets and retrieves options for channels.
The \fBfconfigure\fR command has been superceded by the \fBchan configure\fR
.PP
\fIChannelId\fR identifies the channel for which to set or query an
option and must refer to an open channel such as a Tcl standard
channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR), the return
value from an invocation of \fBopen\fR or \fBsocket\fR, or the result
of a channel creation command provided by a Tcl extension.
.PP
If no \fIname\fR or \fIvalue\fR arguments are supplied, the command
returns a list containing alternating option names and values for the channel.
If \fIname\fR is supplied but no \fIvalue\fR then the command returns
the current value of the given option.
If one or more pairs of \fIname\fR and \fIvalue\fR are supplied, the
command sets each of the named options to the corresponding \fIvalue\fR;
in this case the return value is an empty string.
.PP
The options described below are supported for all channels. In addition,
each channel type may add options that only it supports. See the manual
entry for the command that creates each type of channels for the options
that that specific type of channel supports. For example, see the manual
entry for the \fBsocket\fR command for additional options for sockets, and
the \fBopen\fR command for additional options for serial devices.
.TP
\fB\-blocking\fR \fIboolean\fR
The \fB\-blocking\fR option determines whether I/O operations on the
channel can cause the process to block indefinitely.
The value of the option must be a proper boolean value.
Channels are normally in blocking mode;  if a channel is placed into
nonblocking mode it will affect the operation of the \fBgets\fR,
\fBread\fR, \fBputs\fR, \fBflush\fR, and \fBclose\fR commands by
allowing them to operate asynchronously;
see the documentation for those commands for details.
For nonblocking mode to work correctly, the application must be
using the Tcl event loop (e.g. by calling \fBTcl_DoOneEvent\fR or
invoking the \fBvwait\fR command).
.TP
\fB\-buffering\fR \fInewValue\fR
.
If \fInewValue\fR is \fBfull\fR then the I/O system will buffer output
until its internal buffer is full or until the \fBflush\fR command is
invoked. If \fInewValue\fR is \fBline\fR, then the I/O system will
automatically flush output for the channel whenever a newline character
is output. If \fInewValue\fR is \fBnone\fR, the I/O system will flush
automatically after every output operation.  The default is for
\fB\-buffering\fR to be set to \fBfull\fR except for channels that
connect to terminal-like devices; for these channels the initial setting
is \fBline\fR.  Additionally, \fBstdin\fR and \fBstdout\fR are
initially set to \fBline\fR, and \fBstderr\fR is set to \fBnone\fR.
.TP
\fB\-buffersize\fR \fInewSize\fR
.
\fINewvalue\fR must be an integer; its value is used to set the size of
buffers, in bytes, subsequently allocated for this channel to store input
or output. \fINewvalue\fR must be between one and one million, allowing
buffers of one to one million bytes in size.
.TP
\fB\-encoding\fR \fIname\fR
.
This option is used to specify the encoding of the channel, so that the data
can be converted to and from Unicode for use in Tcl.  For instance, in
order for Tcl to read characters from a Japanese file in \fBshiftjis\fR
and properly process and display the contents, the encoding would be set
to \fBshiftjis\fR.  Thereafter, when reading from the channel, the bytes in
the Japanese file would be converted to Unicode as they are read.
Writing is also supported \- as Tcl strings are written to the channel they
will automatically be converted to the specified encoding on output.
.RS
.PP
If a file contains pure binary data (for instance, a JPEG image), the
encoding for the channel should be configured to be \fBbinary\fR.  Tcl
will then assign no interpretation to the data in the file and simply read or
write raw bytes.  The Tcl \fBbinary\fR command can be used to manipulate this
byte-oriented data.  It is usually better to set the
\fB\-translation\fR option to \fBbinary\fR when you want to transfer
binary data, as this turns off the other automatic interpretations of
the bytes in the stream as well.
.PP
The default encoding for newly opened channels is the same platform- and
locale-dependent system encoding used for interfacing with the operating
system, as returned by \fBencoding system\fR.
.RE
.TP
\fB\-eofchar\fR \fIchar\fR
.TP
\fB\-eofchar\fR \fB{\fIinChar outChar\fB}\fR
.
This option supports DOS file systems that use Control-z (\ex1a) as an
end of file marker.  If \fIchar\fR is not an empty string, then this
character signals end-of-file when it is encountered during input.  For
output, the end-of-file character is output when the channel is closed.
If \fIchar\fR is the empty string, then there is no special end of file
character marker.  For read-write channels, a two-element list specifies
the end of file marker for input and output, respectively.  As a
convenience, when setting the end-of-file character for a read-write
channel you can specify a single value that will apply to both reading
and writing.  When querying the end-of-file character of a read-write
channel, a two-element list will always be returned.  The default value
for \fB\-eofchar\fR is the empty string in all cases except for files
under Windows.  In that case the \fB\-eofchar\fR is Control-z (\ex1a) for
reading and the empty string for writing.
The acceptable range for \fB\-eofchar\fR values is \ex01 - \ex7f;
attempting to set \fB\-eofchar\fR to a value outside of this range will
generate an error.
.TP
\fB\-translation\fR \fImode\fR
.TP
\fB\-translation\fR \fB{\fIinMode outMode\fB}\fR
.
In Tcl scripts the end of a line is always represented using a single
newline character (\en).  However, in actual files and devices the end of
a line may be represented differently on different platforms, or even for
different devices on the same platform.  For example, under UNIX newlines
are used in files, whereas carriage-return-linefeed sequences are
normally used in network connections.  On input (i.e., with \fBgets\fR
and \fBread\fR) the Tcl I/O system automatically translates the external
end-of-line representation into newline characters.  Upon output (i.e.,
with \fBputs\fR), the I/O system translates newlines to the external
end-of-line representation.  The default translation mode, \fBauto\fR,
handles all the common cases automatically, but the \fB\-translation\fR
option provides explicit control over the end of line translations.
.RS
.PP
The value associated with \fB\-translation\fR is a single item for
read-only and write-only channels.  The value is a two-element list for
read-write channels; the read translation mode is the first element of
the list, and the write translation mode is the second element.  As a
convenience, when setting the translation mode for a read-write channel
you can specify a single value that will apply to both reading and
writing.  When querying the translation mode of a read-write channel, a
two-element list will always be returned.  The following values are
currently supported:
.TP
\fBauto\fR
.
As the input translation mode, \fBauto\fR treats any of newline
(\fBlf\fR), carriage return (\fBcr\fR), or carriage return followed by a
newline (\fBcrlf\fR) as the end of line representation.  The end of line
representation can even change from line-to-line, and all cases are
translated to a newline.  As the output translation mode, \fBauto\fR
chooses a platform specific representation; for sockets on all platforms
Tcl chooses \fBcrlf\fR, for all Unix flavors, it chooses \fBlf\fR, and
for the various flavors of Windows it chooses \fBcrlf\fR.  The default
setting for \fB\-translation\fR is \fBauto\fR for both input and output.
.TP
\fBbinary\fR
.
No end-of-line translations are performed.  This is nearly identical to
\fBlf\fR mode, except that in addition \fBbinary\fR mode also sets the
end-of-file character to the empty string (which disables it) and sets the
encoding to \fBbinary\fR (which disables encoding filtering).  See the
description of \fB\-eofchar\fR and \fB\-encoding\fR for more information.
.RS
.PP
Internally, i.e. when it comes to the actual behaviour of the
translator this value \fBis\fR identical to \fBlf\fR and is therefore
reported as such when queried. Even if \fBbinary\fR was used to set
the translation.
.RE
.TP
\fBcr\fR
.
The end of a line in the underlying file or device is represented by a
single carriage return character.  As the input translation mode,
\fBcr\fR mode converts carriage returns to newline characters.  As the
output translation mode, \fBcr\fR mode translates newline characters to
carriage returns.
.TP
\fBcrlf\fR
.
The end of a line in the underlying file or device is represented by a
carriage return character followed by a linefeed character.  As the input
translation mode, \fBcrlf\fR mode converts carriage-return-linefeed
sequences to newline characters.  As the output translation mode,
\fBcrlf\fR mode translates newline characters to carriage-return-linefeed
sequences.  This mode is typically used on Windows platforms and for
network connections.
.TP
\fBlf\fR
.
The end of a line in the underlying file or device is represented by a
single newline (linefeed) character.  In this mode no translations occur
during either input or output.  This mode is typically used on UNIX
platforms.
.RE
.PP
.SH "STANDARD CHANNELS"
.PP
The Tcl standard channels (\fBstdin\fR, \fBstdout\fR, and \fBstderr\fR)
can be configured through this command like every other channel opened
by the Tcl library. Beyond the standard options described above they
will also support any special option according to their current type.
If, for example, a Tcl application is started by the \fBinet\fR
super-server common on Unix system its Tcl standard channels will be
sockets and thus support the socket options.
.SH EXAMPLES
.PP
Instruct Tcl to always send output to \fBstdout\fR immediately,
whether or not it is to a terminal:
.PP
.CS
\fBfconfigure\fR stdout -buffering none
.CE
.PP
Open a socket and read lines from it without ever blocking the
processing of other events:
.PP
.CS
set s [socket some.where.com 12345]
\fBfconfigure\fR $s -blocking 0
fileevent $s readable "readMe $s"
proc readMe chan {
    if {[gets $chan line] < 0} {
        if {[eof $chan]} {
            close $chan
            return
        }
        # Could not read a complete line this time; Tcl's
        # internal buffering will hold the partial line for us
        # until some more data is available over the socket.
    } else {
        puts stdout $line
    }
}
.CE
.PP
Read a PPM-format image from a file:
.PP
.CS
# Open the file and put it into Unix ASCII mode
set f [open teapot.ppm]
\fBfconfigure\fR $f \-encoding ascii \-translation lf

command which supports the same syntax and options.
# Get the header
if {[gets $f] ne "P6"} {
    error "not a raw\-bits PPM"
}

# Read lines until we have got non-comment lines
# that supply us with three decimal values.
set words {}
while {[llength $words] < 3} {
    gets $f line
    if {[string match "#*" $line]} continue
    lappend words {*}[join [scan $line %d%d%d]]
}

# Those words supply the size of the image and its
# overall depth per channel. Assign to variables.
lassign $words xSize ySize depth

# Now switch to binary mode to pull in the data,
# one byte per channel (red,green,blue) per pixel.
\fBfconfigure\fR $f \-translation binary
set numDataBytes [expr {3 * $xSize * $ySize}]
set data [read $f $numDataBytes]

close $f
.CE
.SH "SEE ALSO"
close(n), flush(n), gets(n), open(n), puts(n), read(n), socket(n),
Tcl_StandardChannels(3)
chan(n)
.SH KEYWORDS
blocking, buffering, carriage return, end of line, flushing, linemode,
newline, nonblocking, platform, translation, encoding, filter, byte array,
binary
'\" Local Variables:
'\" mode: nroff
'\" End:

Changes to doc/fcopy.n.

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
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







-
+

-


-
+
+


-
+

+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+



-
+
+







.TH fcopy n 8.0 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
fcopy \- Copy data from one channel to another
.SH SYNOPSIS
\fBfcopy \fIinchan\fR \fIoutchan\fR ?\fB\-size \fIsize\fR? ?\fB\-command \fIcallback\fR?
\fBfcopy \fIinputChan outputChan\fR ?\fB\-size \fIsize\fR? ?\fB\-command \fIcallback\fR?
.BE

.SH DESCRIPTION
.PP
The \fBfcopy\fR command copies data from one I/O channel, \fIinchan\fR to another I/O channel, \fIoutchan\fR.
The \fBfcopy\fR command copies data from one I/O channel, \fIinchan\fR, to
another I/O channel, \fIoutchan\fR.
The \fBfcopy\fR command leverages the buffering in the Tcl I/O system to
avoid extra copies and to avoid buffering too much data in
main memory when copying large files to slow destinations like
main memory when copying large files to destinations like
network sockets.
.SS "DATA QUANTITY"
All data until \fIEOF\fR is copied.
In addition, the quantity of copied data may be specified by the option
\fB\-size\fR. The given size is in bytes, if the input channel is in binary
mode. Otherwise, it is in characters.
.PP
The \fBfcopy\fR
command transfers data from \fIinchan\fR until end of file
or \fIsize\fR bytes or characters have been
transferred; \fIsize\fR is in bytes if the two channels are using the
same encoding, and is in characters otherwise.
If no \fB\-size\fR argument is given,
Depreciated feature: the transfer is treated as a binary transfer, if the
encoding profile is set to
.QW tcl8
and the input encoding matches the output encoding.
In this case, eventual encoding errors are not handled.
An eventually given size is in bytes in this case.
then the copy goes until end of file.
All the data read from \fIinchan\fR is copied to \fIoutchan\fR.
.
.SS "BLOCKING OPERATION MODE"
Without the \fB\-command\fR option, \fBfcopy\fR blocks until the copy is complete
and returns the number of bytes or characters (using the same rules as
for the \fB\-size\fR option) written to \fIoutchan\fR.
.PP
.
.SS "BACKGROUND OPERATION MODE"
The \fB\-command\fR argument makes \fBfcopy\fR work in the background.
In this case it returns immediately and the \fIcallback\fR is invoked
later when the copy completes.
The \fIcallback\fR is called with
one or two additional
arguments that indicates how many bytes were written to \fIoutchan\fR.
If an error occurred during the background copy, the second argument is the
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
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







-
+
+


-
+
+










-
-
+
+




-
+












+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







and the command callback is \fInot\fR made.
If \fIinchan\fR is closed,
then all data already queued for \fIoutchan\fR is written out.
.PP
Note that \fIinchan\fR can become readable during a background copy.
You should turn off any \fBfileevent\fR handlers during a background
copy so those handlers do not interfere with the copy.
Any wrong-sided I/O attempted (by a \fBfileevent\fR handler or otherwise) will get a
Any wrong-sided I/O attempted (by a \fBfileevent\fR handler or otherwise) will
get a
.QW "channel busy"
error.
.PP
.
.SS "CHANNEL TRANSLATION OPTIONS"
\fBFcopy\fR translates end-of-line sequences in \fIinchan\fR and \fIoutchan\fR
according to the \fB\-translation\fR option
for these channels.
See the manual entry for \fBfconfigure\fR for details on the
\fB\-translation\fR option.
The translations mean that the number of bytes read from \fIinchan\fR
can be different than the number of bytes written to \fIoutchan\fR.
Only the number of bytes written to \fIoutchan\fR is reported,
either as the return value of a synchronous \fBfcopy\fR or
as the argument to the callback for an asynchronous \fBfcopy\fR.
.PP
\fBFcopy\fR obeys the encodings and character translations configured
.SS "CHANNEL ENCODING OPTIONS"
\fBFcopy\fR obeys the encodings, profiles and character translations configured
for the channels. This
means that the incoming characters are converted internally first
UTF-8 and then into the encoding of the channel \fBfcopy\fR writes
to. See the manual entry for \fBfconfigure\fR for details on the
\fB\-encoding\fR and \fB\-translation\fR options. No conversion is
\fB\-encoding\fR and \fB\-profile\fR options. No conversion is
done if both channels are
set to encoding
.QW binary
and have matching translations. If only the output channel is set to encoding
.QW binary
the system will write the internal UTF-8 representation of the incoming
characters. If only the input channel is set to encoding
.QW binary
the system will assume that the incoming
bytes are valid UTF-8 characters and convert them according to the
output encoding. The behaviour of the system for bytes which are not
valid UTF-8 characters is undefined in this case.
.PP
\fBFcopy\fR may throw encoding errors (error code \fBEILSEQ\fR), if input or output
channel is configured to the
.QW strict
encoding profile.
.PP
If an encoding error arises on the input channel, any data before the error
byte is written to the output channel. The input file pointer is located just
before the values causing the encoding error.
Error inspection or recovery is possible by changing the encoding parameters and
invoking a file command (\fBread\fR, \fBfcopy\fR).
.PP
If an encoding error arises on the output channel, the erroneous data is lost.
To make the difference between the input error case and the output error case,
only the error message may be inspected (read or write), as both throw the
error code \fIEILSEQ\fR.
.SH EXAMPLES
.PP
The first example transfers the contents of one channel exactly to
another. Note that when copying one file to another, it is better to
use \fBfile copy\fR which also copies file metadata (e.g. the file
access permissions) where possible.
.PP

Changes to doc/file.n.

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
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







-
+



-
-
+
+
-
-
-
-
+
+
+









+
+
+







-
-
-
-
-
+
+
+
+
+


-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+








+
+
-
-
+
+

-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+







+

-
+




















+



















+


+













-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

+







+





+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+




+




















+







.TH file n 8.3 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
file \- Manipulate file names and attributes
.SH SYNOPSIS
\fBfile \fIoption\fR \fIname\fR ?\fIarg arg ...\fR?
\fBfile \fIoption name\fR ?\fIarg arg ...\fR?
.BE
.SH DESCRIPTION
.PP
This command provides several operations on a file's name or attributes.
\fIName\fR is the name of a file; if it starts with a tilde, then tilde
This command provides several operations on a file's name or attributes.  The
\fIname\fR argument is the name of a file in most cases. The \fIoption\fR
substitution is done before executing the command (see the manual entry for
\fBfilename\fR for details).  \fIOption\fR indicates what to do with the
file name.  Any unique abbreviation for \fIoption\fR is acceptable.  The
valid options are:
argument indicates what to do with the file name.  Any unique abbreviation for
\fIoption\fR is acceptable.  The valid options are:
.\" METHOD: atime
.TP
\fBfile atime \fIname\fR ?\fItime\fR?
.
Returns a decimal string giving the time at which file \fIname\fR was last
accessed.  If \fItime\fR is specified, it is an access time to set
for the file.  The time is measured in the standard POSIX fashion as
seconds from a fixed starting time (often January 1, 1970).  If the file
does not exist or its access time cannot be queried or set then an error is
generated.  On Windows, FAT file systems do not support access time.
On \fBzipfs\fR file systems, access time is mapped to the modification
time.
.\" METHOD: attributes
.TP
\fBfile attributes \fIname\fR
.TP
\fBfile attributes \fIname\fR ?\fIoption\fR?
.TP
\fBfile attributes \fIname\fR ?\fIoption value option value...\fR?
.
This subcommand returns or sets platform specific values associated
with a file. The first form returns a list of the platform specific
flags and their values. The second form returns the value for the
specific option. The third form sets one or more of the values. The
values are as follows:
This subcommand returns or sets platform-specific values associated
with a file. The first form returns a list of the platform-specific
options and their values. The second form returns the value for the
given option. The third form sets one or more of the values. The values
are as follows:
.RS
.PP
On Unix, \fB\-group\fR gets or sets the group name for the file. A group id
can be given to the command, but it returns a group name. \fB\-owner\fR gets
or sets the user name of the owner of the file. The command returns the
owner name, but the numerical id can be passed when setting the
owner. \fB\-permissions\fR sets or retrieves the octal code that chmod(1)
uses.  This command does also has limited support for setting using the
On Unix, \fB\-group\fR gets or sets the group name for the file. A
group id can be given to the command, but it returns a group name.
\fB\-owner\fR gets or sets the user name of the owner of the file. The
command returns the owner name, but the numerical id can be passed when
setting the owner. \fB\-permissions\fR retrieves or sets a file's
access permissions, using octal notation by default. This option also
provides limited support for setting permissions using the symbolic
symbolic attributes for chmod(1), of the form [ugo]?[[+\-=][rwxst],[...]],
where multiple symbolic attributes can be separated by commas (example:
\fBu+s,go\-rw\fR add sticky bit for user, remove read and write
permissions for group and other).  A simplified \fBls\fR style string,
of the form rwxrwxrwx (must be 9 characters), is also supported
(example: \fBrwxr\-xr\-t\fR is equivalent to 01755).
On versions of Unix supporting file flags, \fB\-readonly\fR gives the
value or sets or clears the readonly attribute of the file,
i.e. the user immutable flag \fBuchg\fR to chflags(1).
notation accepted by the \fBchmod\fR command, following the form
[\fBugo\fR]?[[\fB+-=\fR][\fBrwxst\fR]\fB,\fR[...]]. Multiple permission
specifications may be given, separated by commas. E.g., \fBu+s,go-rw\fR
would set the setuid bit for a file's owner as well as remove read and
write permission for the file's group and other users. An
\fBls\fR-style string of the form \fBrwxrwxrwx\fR is also accepted but
must always be 9 characters long. E.g., \fBrwxr-xr-t\fR is equivalent
to \fB01755\fR. On versions of Unix supporting file flags,
\fB\-readonly\fR returns the value of, or sets, or clears the readonly
attribute of a file, i.e., the user immutable flag (\fBuchg\fR) to the
\fBchflags\fR command.
.PP
On Windows, \fB\-archive\fR gives the value or sets or clears the
archive attribute of the file. \fB\-hidden\fR gives the value or sets
or clears the hidden attribute of the file. \fB\-longname\fR will
expand each path element to its long version. This attribute cannot be
set. \fB\-readonly\fR gives the value or sets or clears the readonly
attribute of the file. \fB\-shortname\fR gives a string where every
path element is replaced with its short (8.3) version of the
name if possible. For path elements that cannot be mapped to short
names, the long name is retained. This attribute cannot be set.
name. This attribute cannot be set. \fB\-system\fR gives or sets or
clears the value of the system attribute of the file.
\fB\-system\fR gives or sets or clears the value of the system
attribute of the file.
.PP
On Mac OS X and Darwin, \fB\-creator\fR gives or sets the
On macOS and Darwin, \fB\-creator\fR gives or sets the
Finder creator type of the file. \fB\-hidden\fR gives or sets or clears
the hidden attribute of the file. \fB\-readonly\fR gives or sets or
clears the readonly attribute of the file. \fB\-rsrclength\fR gives
the length of the resource fork of the file, this attribute can only be
set to the value 0, which results in the resource fork being stripped
off the file.
.PP
On all platforms, files in \fBzipfs\fR mounted archives return the following
attributes. These are all read-only and cannot be directly set.
.RS
.\" OPTION: -archive
.TP
\fB\-archive\fR
.
The path of the mounted ZIP archive containing the file.
.\" OPTION: -compsize
.TP
\fB\-compsize\fR
.
The compressed size of the file within the archive.
This is \fB0\fR for directories.
.\" OPTION: -crc
.TP
\fB\-crc\fR
.
The CRC of the file if present, else \fB0\fR.
.\" OPTION: -mount
.TP
\fB\-mount\fR
.
The path where the containing archive is mounted.
.\" OPTION: -offset
.TP
\fB\-offset\fR
.
The offset of the file within the archive.
.\" OPTION: -uncompsize
.TP
\fB\-uncompsize\fR
.
The uncompressed size of the file. This is \fB0\fR for directories.
.RE
.PP
Other attributes may be present in the returned list. These should
be ignored.
.RE
.\" METHOD: channels
.TP
\fBfile channels\fR ?\fIpattern\fR?
.
If \fIpattern\fR is not specified, returns a list of names of all
registered open channels in this interpreter.  If \fIpattern\fR is
specified, only those names matching \fIpattern\fR are returned.  Matching
is determined using the same rules as for \fBstring match\fR.
.\" METHOD: copy
.TP
\fBfile copy \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR \fItarget\fR
\fBfile copy \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource target\fR
.TP
\fBfile copy \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR ?\fIsource\fR ...? \fItargetDir\fR
.
The first form makes a copy of the file or directory \fIsource\fR under
the pathname \fItarget\fR. If \fItarget\fR is an existing directory,
then the second form is used.  The second form makes a copy inside
\fItargetDir\fR of each \fIsource\fR file listed.  If a directory is
specified as a \fIsource\fR, then the contents of the directory will be
recursively copied into \fItargetDir\fR. Existing files will not be
overwritten unless the \fB\-force\fR option is specified (when Tcl will
also attempt to adjust permissions on the destination file or directory
if that is necessary to allow the copy to proceed).  When copying
within a single filesystem, \fIfile copy\fR will copy soft links (i.e.
the links themselves are copied, not the things they point to).  Trying
to overwrite a non-empty directory, overwrite a directory with a file,
or overwrite a file with a directory will all result in errors even if
\fB\-force\fR was specified.  Arguments are processed in the order
specified, halting at the first error, if any.  A \fB\-\|\-\fR marks
the end of switches; the argument following the \fB\-\|\-\fR will be
treated as a \fIsource\fR even if it starts with a \fB\-\fR.
.\" METHOD: delete
.TP
\fBfile delete \fR?\fB\-force\fR? ?\fB\-\|\-\fR? ?\fIpathname\fR ... ?
.
Removes the file or directory specified by each \fIpathname\fR
argument.  Non-empty directories will be removed only if the
\fB\-force\fR option is specified.  When operating on symbolic links,
the links themselves will be deleted, not the objects they point to.
Trying to delete a non-existent file is not considered an error.
Trying to delete a read-only file will cause the file to be deleted,
even if the \fB\-force\fR flags is not specified.  If the \fB\-force\fR
option is specified on a directory, Tcl will attempt both to change
permissions and move the current directory
.QW pwd
out of the given path if that is necessary to allow the deletion to
proceed.  Arguments are processed in the order specified, halting at
the first error, if any.
A \fB\-\|\-\fR marks the end of switches; the argument following the
\fB\-\|\-\fR will be treated as a \fIpathname\fR even if it starts with
a \fB\-\fR.
.\" METHOD: dirname
.TP
\fBfile dirname \fIname\fR
.
Returns a name comprised of all of the path components in \fIname\fR
excluding the last element.  If \fIname\fR is a relative file name and
only contains one path element, then returns
.QW \fB.\fR .
If \fIname\fR refers to a root directory, then the root directory is
returned.  For example,
.RS
.PP
.CS
\fBfile dirname\fR c:/
.CE
.PP
returns \fBc:/\fR.
.PP
Note that tilde substitution will only be
performed if it is necessary to complete the command. For example,
.PP
.CS
\fBfile dirname\fR ~/src/foo.c
.CE
.PP
returns \fB~/src\fR, whereas
.PP
.CS
\fBfile dirname\fR ~
.CE
.PP
returns \fB/home\fR (or something similar).
.RE
.\" METHOD: executable
.TP
\fBfile executable \fIname\fR
.
Returns \fB1\fR if file \fIname\fR is executable by the current user,
\fB0\fR otherwise. On Windows, which does not have an executable attribute,
the command treats all directories and any files with extensions
\fBexe\fR, \fBcom\fR, \fBcmd\fR or \fBbat\fR as executable.
.\" METHOD: exists
.TP
\fBfile exists \fIname\fR
.
Returns \fB1\fR if file \fIname\fR exists and the current user has
search privileges for the directories leading to it, \fB0\fR otherwise.
.\" METHOD: extension
.TP
\fBfile extension \fIname\fR
.
Returns all of the characters in \fIname\fR after and including the last
dot in the last element of \fIname\fR.  If there is no dot in the last
element of \fIname\fR then returns the empty string.
.\" METHOD: home
.TP
\fBfile home ?\fIusername\fR?
.VS "8.7, TIP 602"
If no argument is specified, the command returns the home directory
of the current user. This is generally the value of the \fB$HOME\fR
environment variable except that on Windows platforms backslashes
in the path are replaced by forward slashes. An error is raised if
the \fB$HOME\fR environment variable is not set.
.RS
.PP
If \fIusername\fR is specified, the command returns the home directory
configured in the system for the specified user. Note this may be
different than the value of the \fB$HOME\fR environment variable
even when \fIusername\fR corresponds to the current user. An error is
raised if the \fIusername\fR does not correspond to a user account
on the system.
.RE
.VE "8.7, TIP 602"
.\" METHOD: isdirectory
.TP
\fBfile isdirectory \fIname\fR
.
Returns \fB1\fR if file \fIname\fR is a directory, \fB0\fR otherwise.
.\" METHOD: isfile
.TP
\fBfile isfile \fIname\fR
.
Returns \fB1\fR if file \fIname\fR is a regular file, \fB0\fR otherwise.
.\" METHOD: join
.TP
\fBfile join \fIname\fR ?\fIname ...\fR?
.
Takes one or more file names and combines them, using the correct path
separator for the current platform.  If a particular \fIname\fR is
relative, then it will be joined to the previous file name argument.
Otherwise, any earlier arguments will be discarded, and joining will
proceed from the current argument.  For example,
.RS
.PP
.CS
\fBfile join\fR a b /foo bar
.CE
.PP
returns \fB/foo/bar\fR.
.PP
Note that any of the names can contain separators, and that the result
is always canonical for the current platform: \fB/\fR for Unix and
Windows.
.RE
.\" METHOD: link
.TP
\fBfile link\fR ?\fI\-linktype\fR? \fIlinkName\fR ?\fItarget\fR?
.
If only one argument is given, that argument is assumed to be
\fIlinkName\fR, and this command returns the value of the link given by
\fIlinkName\fR (i.e. the name of the file it points to).  If
\fIlinkName\fR is not a link or its value cannot be read (as, for example,
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
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







-
-
-
-
+





+

-
+



-
-
-
-
+
+
+
+
+









+









+
+






+







.QW \fB\-hard\fR .
.PP
On Unix, symbolic links can be made to relative paths, and those paths
must be relative to the actual \fIlinkName\fR's location (not to the
cwd), but on all other platforms where relative links are not supported,
target paths will always be converted to absolute, normalized form
before the link is created (and therefore relative paths are interpreted
as relative to the cwd).  Furthermore,
.QW ~user
paths are always expanded
to absolute form.  When creating links on filesystems that either do not
as relative to the cwd). When creating links on filesystems that either do not
support any links, or do not support the specific type requested, an
error message will be returned.  Most Unix platforms support both
symbolic and hard links (the latter for files only). Windows
supports symbolic directory links and hard file links on NTFS drives.
.RE
.\" METHOD: lstat
.TP
\fBfile lstat \fIname varName\fR
\fBfile lstat \fIname\fR ?\fIvarName\fR?
.
Same as \fBstat\fR option (see below) except uses the \fIlstat\fR
kernel call instead of \fIstat\fR.  This means that if \fIname\fR
refers to a symbolic link the information returned in \fIvarName\fR
is for the link rather than the file it refers to.  On systems that
do not support symbolic links this option behaves exactly the same
as the \fBstat\fR option.
refers to a symbolic link the information returned is for the link
rather than the file it refers to.  On systems that do not support
symbolic links this option behaves exactly the same as the
\fBstat\fR option.
.\" METHOD: mkdir
.TP
\fBfile mkdir\fR ?\fIdir\fR ...?
.
Creates each directory specified.  For each pathname \fIdir\fR specified,
this command will create all non-existing parent directories as
well as \fIdir\fR itself.  If an existing directory is specified, then
no action is taken and no error is returned.  Trying to overwrite an existing
file with a directory will result in an error.  Arguments are processed in
the order specified, halting at the first error, if any.
.\" METHOD: mtime
.TP
\fBfile mtime \fIname\fR ?\fItime\fR?
.
Returns a decimal string giving the time at which file \fIname\fR was last
modified.  If \fItime\fR is specified, it is a modification time to set for
the file (equivalent to Unix \fBtouch\fR).  The time is measured in the
standard POSIX fashion as seconds from a fixed starting time (often January
1, 1970).  If the file does not exist or its modified time cannot be queried
or set then an error is generated.
On \fBzipfs\fR file systems, modification time cannot be explicitly set.
.\" METHOD: nativename
.TP
\fBfile nativename \fIname\fR
.
Returns the platform-specific name of the file. This is useful if the
filename is needed to pass to a platform-specific call, such as to a
subprocess via \fBexec\fR under Windows (see \fBEXAMPLES\fR below).
.\" METHOD: normalize
.TP
\fBfile normalize \fIname\fR
.
Returns a unique normalized path representation for the file-system
object (file, directory, link, etc), whose string value can be used as a
unique identifier for it.  A normalized path is an absolute path which has
all
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

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
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
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
467
468
469
470
471
472
473
474
475
476







+





+










+





+







+

-
+

















+








+








+






+







-
-
-
-
-
-
-
-
-
-
-
-
+
-

-
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+







very last path component may be a symbolic link), and on Windows it also
means we want the long form with that form's case-dependence (which
gives us a unique, case-dependent path).  The one exception concerning the
last link in the path is necessary, because Tcl or the user may wish to
operate on the actual symbolic link itself (for example \fBfile delete\fR,
\fBfile rename\fR, \fBfile copy\fR are defined to operate on symbolic
links, not on the things that they point to).
.\" METHOD: owned
.TP
\fBfile owned \fIname\fR
.
Returns \fB1\fR if file \fIname\fR is owned by the current user, \fB0\fR
otherwise.
.\" METHOD: pathtype
.TP
\fBfile pathtype \fIname\fR
.
Returns one of \fBabsolute\fR, \fBrelative\fR, \fBvolumerelative\fR. If
\fIname\fR refers to a specific file on a specific volume, the path type will
be \fBabsolute\fR. If \fIname\fR refers to a file relative to the current
working directory, then the path type will be \fBrelative\fR. If \fIname\fR
refers to a file relative to the current working directory on a specified
volume, or to a specific file on the current working volume, then the path
type is \fBvolumerelative\fR.
.\" METHOD: readable
.TP
\fBfile readable \fIname\fR
.
Returns \fB1\fR if file \fIname\fR is readable by the current user,
\fB0\fR otherwise.
.\" METHOD: readlink
.TP
\fBfile readlink \fIname\fR
.
Returns the value of the symbolic link given by \fIname\fR (i.e. the name
of the file it points to).  If \fIname\fR is not a symbolic link or its
value cannot be read, then an error is returned.  On systems that do not
support symbolic links this option is undefined.
.\" METHOD: rename
.TP
\fBfile rename \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR \fItarget\fR
\fBfile rename \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource target\fR
.TP
\fBfile rename \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR ?\fIsource\fR ...? \fItargetDir\fR
.
The first form takes the file or directory specified by pathname
\fIsource\fR and renames it to \fItarget\fR, moving the file if the
pathname \fItarget\fR specifies a name in a different directory.  If
\fItarget\fR is an existing directory, then the second form is used.
The second form moves each \fIsource\fR file or directory into the
directory \fItargetDir\fR. Existing files will not be overwritten
unless the \fB\-force\fR option is specified.  When operating inside a
single filesystem, Tcl will rename symbolic links rather than the
things that they point to.  Trying to overwrite a non-empty directory,
overwrite a directory with a file, or a file with a directory will all
result in errors.  Arguments are processed in the order specified,
halting at the first error, if any.  A \fB\-\|\-\fR marks the end of
switches; the argument following the \fB\-\|\-\fR will be treated as a
\fIsource\fR even if it starts with a \fB\-\fR.
.\" METHOD: rootname
.TP
\fBfile rootname \fIname\fR
.
Returns all of the characters in \fIname\fR up to but not including the
last
.QW .
character in the last component of name.  If the last
component of \fIname\fR does not contain a dot, then returns \fIname\fR.
.\" METHOD: separator
.TP
\fBfile separator\fR ?\fIname\fR?
.
If no argument is given, returns the character which is used to separate
path segments for native files on this platform.  If a path is given,
the filesystem responsible for that path is asked to return its
separator character.  If no file system accepts \fIname\fR, an error
is generated.
.\" METHOD: size
.TP
\fBfile size \fIname\fR
.
Returns a decimal string giving the size of file \fIname\fR in bytes.  If
the file does not exist or its size cannot be queried then an error is
generated.
.\" METHOD: split
.TP
\fBfile split \fIname\fR
.
Returns a list whose elements are the path components in \fIname\fR.  The
first element of the list will have the same path type as \fIname\fR.
All other elements will be relative.  Path separators will be discarded
unless they are needed to ensure that an element is unambiguously relative.
For example, under Unix
.RS
.PP
.CS
\fBfile split\fR /foo/~bar/baz
.CE
.PP
returns
.QW \fB/\0\0foo\0\0./~bar\0\0baz\fR
to ensure that later commands
that use the third component do not attempt to perform tilde
substitution.
.\" METHOD: stat
.RE
.TP
\fBfile stat \fIname varName\fR
\fBfile stat \fIname\fR ?\fIvarName\fR?
.
Invokes the \fBstat\fR kernel call on \fIname\fR, and uses the variable
given by \fIvarName\fR to hold information returned from the kernel call.
\fIVarName\fR is treated as an array variable, and the following elements
of that variable are set: \fBatime\fR, \fBctime\fR, \fBdev\fR, \fBgid\fR,
\fBino\fR, \fBmode\fR, \fBmtime\fR, \fBnlink\fR, \fBsize\fR, \fBtype\fR,
\fBuid\fR.  Each element except \fBtype\fR is a decimal string with the
value of the corresponding field from the \fBstat\fR return structure;
see the manual entry for \fBstat\fR for details on the meanings of the
values.  The \fBtype\fR element gives the type of the file in the same
form returned by the command \fBfile type\fR.  This command returns an
empty string.
Invokes the \fBstat\fR kernel call on \fIname\fR, and returns a
dictionary with the information returned from the kernel call. If
\fIvarName\fR is given, it uses the variable to hold the information.
\fIVarName\fR is treated as an array variable, and in such case the
command returns the empty string. The following elements are set:
\fBatime\fR, \fBctime\fR, \fBdev\fR, \fBgid\fR, \fBino\fR, \fBmode\fR,
\fBmtime\fR, \fBnlink\fR, \fBsize\fR, \fBtype\fR, \fBuid\fR.  Each element
except \fBtype\fR is a decimal string with the value of the corresponding
field from the \fBstat\fR return structure; see the manual entry for
\fBstat\fR for details on the meanings of the values.  The \fBtype\fR
element gives the type of the file in the same form returned by the
command \fBfile type\fR.
.\" METHOD: system
.TP
\fBfile system \fIname\fR
.
Returns a list of one or two elements, the first of which is the name of
the filesystem to use for the file, and the second, if given, an
arbitrary string representing the filesystem-specific nature or type of
the location within that filesystem.  If a filesystem only supports one
420
421
422
423
424
425
426

427
428
429
430
431
432
433
434

435
436
437
438
439
440
441
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507







+








+







on Windows).  A generic virtual file system might return
the list
.QW "vfs ftp"
to represent a file on a remote ftp site mounted as a
virtual filesystem through an extension called
.QW vfs .
If the file does not belong to any filesystem, an error is generated.
.\" METHOD: tail
.TP
\fBfile tail \fIname\fR
.
Returns all of the characters in the last filesystem component of
\fIname\fR.  Any trailing directory separator in \fIname\fR is ignored.
If \fIname\fR contains no separators then returns \fIname\fR.  So,
\fBfile tail a/b\fR, \fBfile tail a/b/\fR and \fBfile tail b\fR all
return \fBb\fR.
.\" METHOD: tempdir
.TP
\fBfile tempdir\fR ?\fItemplate\fR?
.VS "8.7, TIP 431"
Creates a temporary directory (guaranteed to be newly created and writable by
the current script) and returns its name. If \fItemplate\fR is given, it
specifies one of or both of the existing directory (on a filesystem controlled
by the operating system) to contain the temporary directory, and the base part
458
459
460
461
462
463
464

465
466
467

468
469
470
471
472
473
474
475
476
477
478
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
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594

595
596
597
598
599

600
601
602
603
604
605
606
607







+


-
+














+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






+













+







-
+




-
+







% \fBfile tempdir\fR /tmp/
/tmp/tcl_1mOJHD
% \fBfile tempdir\fR myapp
/var/tmp/myapp_0ihS0n
.CE
.RE
.VE "8.7, TIP 431"
.\" METHOD: tempfile
.TP
\fBfile tempfile\fR ?\fInameVar\fR? ?\fItemplate\fR?
'\" TIP #210
.\" TIP #210
Creates a temporary file and returns a read-write channel opened on that file.
If the \fInameVar\fR is given, it specifies a variable that the name of the
temporary file will be written into; if absent, Tcl will attempt to arrange
for the temporary file to be deleted once it is no longer required. If the
\fItemplate\fR is present, it specifies parts of the template of the filename
to use when creating it (such as the directory, base-name or extension) though
some platforms may ignore some or all of these parts and use a built-in
default instead.
.RS
.PP
Note that temporary files are \fIonly\fR ever created on the native
filesystem. As such, they can be relied upon to be used with operating-system
native APIs and external programs that require a filename.
.RE
.\" METHOD: tildeexpand
.TP
\fBfile tildeexpand \fIname\fR
.VS "8.7, TIP 602"
Returns the result of performing tilde substitution on \fIname\fR. If the name
begins with a tilde, then the file name will be interpreted as if the first
element is replaced with the location of the home directory for the given user.
If the tilde is followed immediately by a path separator, the \fB$HOME\fR
environment variable is substituted.  Otherwise the characters between the
tilde and the next separator are taken as a user name, which is used to
retrieve the user's home directory for substitution.  An error is raised if the
\fB$HOME\fR environment variable or user does not exist.
.RS
.PP
If the file name does not begin with a tilde, it is returned unmodified.
.RE
.VE "8.7, TIP 602"
.\" METHOD: type
.TP
\fBfile type \fIname\fR
.
Returns a string giving the type of file \fIname\fR, which will be one of
\fBfile\fR, \fBdirectory\fR, \fBcharacterSpecial\fR, \fBblockSpecial\fR,
\fBfifo\fR, \fBlink\fR, or \fBsocket\fR.
.\" METHOD: volumes
.TP
\fBfile volumes\fR
.
Returns the absolute paths to the volumes mounted on the system, as a
proper Tcl list.  Without any virtual filesystems mounted as root
volumes, on UNIX, the command will always return
.QW / ,
since all filesystems are locally mounted.
On Windows, it will return a list of the available local drives
(e.g.
.QW "a:/ c:/" ).
If any virtual filesystem has mounted additional
volumes, they will be in the returned list.
.\" METHOD: writable
.TP
\fBfile writable \fIname\fR
.
Returns \fB1\fR if file \fIname\fR is writable by the current user,
\fB0\fR otherwise.
.SH "PORTABILITY ISSUES"
.TP
\fBUnix\fR\0\0\0\0\0\0\0
\fBUnix\fR
.
These commands always operate using the real user and group identifiers,
not the effective ones.
.TP
\fBWindows\fR\0\0\0\0
\fBWindows\fR
.
The \fBfile owned\fR subcommand uses the user identifier (SID) of
the process token, not the thread token which may be impersonating
some other user.
.SH EXAMPLES
.PP
This procedure shows how to search for C files in a given directory
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
558
559
560
561
562
563
564
565
566

567
568
569
570
571
572
573
574
575
576
577
615
616
617
618
619
620
621

622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642

643
644
645
646
647
648
649
650
651
652

653
654
655
656
657
658
659
660
661
662
663
664







-
+




















-
+









-
+











        windows {
            set ext .obj
        }
        unix {
           set ext .o
        }
    }
    foreach file [glob \-nocomplain \-directory $dir *.c] {
    foreach file [glob -nocomplain -directory $dir *.c] {
        set objectFile [\fBfile tail\fR [\fBfile rootname\fR $file]]$ext
        if {[\fBfile exists\fR $objectFile]} {
            lappend files $file
        }
    }
    return $files
}
.CE
.PP
Rename a file and leave a symbolic link pointing from the old location
to the new place:
.PP
.CS
set oldName foobar.txt
set newName foo/bar.txt
# Make sure that where we're going to move to exists...
if {![\fBfile isdirectory\fR [\fBfile dirname\fR $newName]]} {
    \fBfile mkdir\fR [\fBfile dirname\fR $newName]
}
\fBfile rename\fR $oldName $newName
\fBfile link\fR \-symbolic $oldName $newName
\fBfile link\fR -symbolic $oldName $newName
.CE
.PP
On Windows, a file can be
.QW started
easily enough (equivalent to double-clicking on it in the Explorer
interface) but the name passed to the operating system must be in
native format:
.PP
.CS
exec {*}[auto_execok start] {} [\fBfile nativename\fR ~/example.txt]
exec {*}[auto_execok start] {} [\fBfile nativename\fR C:/Users/fred/example.txt]
.CE
.SH "SEE ALSO"
filename(n), open(n), close(n), eof(n), gets(n), tell(n), seek(n),
fblocked(n), flush(n)
.SH KEYWORDS
attributes, copy files, delete files, directory, file, move files, name,
rename files, stat, user
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/fileevent.n.

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
9
10
11
12
13
14
15

16
17

18
19

20
21


















































































22























23
























24



25

26
27
28
29







-
+

-
+

-


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
+
-




.TH fileevent n 7.5 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
fileevent \- Execute a script when a channel becomes readable or writable
.SH SYNOPSIS
\fBfileevent \fIchannelId \fBreadable \fR?\fIscript\fR?
\fBfileevent \fIchannel \fBreadable \fR?\fIscript\fR?
.sp
\fBfileevent \fIchannelId \fBwritable \fR?\fIscript\fR?
\fBfileevent \fIchannel \fBwritable \fR?\fIscript\fR?
.BE

.SH DESCRIPTION
.PP
This command is used to create \fIfile event handlers\fR.  A file event
handler is a binding between a channel and a script, such that the script
is evaluated whenever the channel becomes readable or writable.  File event
handlers are most commonly used to allow data to be received from another
process on an event-driven basis, so that the receiver can continue to
interact with the user while waiting for the data to arrive.  If an
application invokes \fBgets\fR or \fBread\fR on a blocking channel when
there is no input data available, the process will block; until the input
data arrives, it will not be able to service other events, so it will
appear to the user to
.QW "freeze up" .
With \fBfileevent\fR, the process can
tell when data is present and only invoke \fBgets\fR or \fBread\fR when
they will not block.
.PP
The \fIchannelId\fR argument to \fBfileevent\fR refers to an open
channel such as a Tcl standard channel (\fBstdin\fR, \fBstdout\fR,
or \fBstderr\fR), the return value from an invocation of \fBopen\fR
or \fBsocket\fR, or the result of a channel creation command provided
by a Tcl extension.
.PP
If the \fIscript\fR argument is specified, then \fBfileevent\fR
creates a new event handler:  \fIscript\fR will be evaluated
whenever the channel becomes readable or writable (depending on the
second argument to \fBfileevent\fR).
In this case \fBfileevent\fR returns an empty string.
The \fBreadable\fR and \fBwritable\fR event handlers for a file
are independent, and may be created and deleted separately.
However, there may be at most one \fBreadable\fR and one \fBwritable\fR
handler for a file at a given time in a given interpreter.
If \fBfileevent\fR is called when the specified handler already
exists in the invoking interpreter, the new script replaces the old one.
.PP
If the \fIscript\fR argument is not specified, \fBfileevent\fR
returns the current script for \fIchannelId\fR, or an empty string
if there is none.
If the \fIscript\fR argument is specified as an empty string
then the event handler is deleted, so that no script will be invoked.
A file event handler is also deleted automatically whenever
its channel is closed or its interpreter is deleted.
.PP
A channel is considered to be readable if there is unread data
available on the underlying device.
A channel is also considered to be readable if there is unread
data in an input buffer, except in the special case where the
most recent attempt to read from the channel was a \fBgets\fR
call that could not find a complete line in the input buffer.
This feature allows a file to be read a line at a time in nonblocking mode
using events.
A channel is also considered to be readable if an end of file or
error condition is present on the underlying file or device.
It is important for \fIscript\fR to check for these conditions
and handle them appropriately;  for example, if there is no special
check for end of file, an infinite loop may occur where \fIscript\fR
reads no data, returns, and is immediately invoked again.
.PP
A channel is considered to be writable if at least one byte of data
can be written to the underlying file or device without blocking,
or if an error condition is present on the underlying file or device.
.PP
Event-driven I/O works best for channels that have been placed into
nonblocking mode with the \fBfconfigure\fR command.  In blocking mode,
a \fBputs\fR command may block if you give it more data than the
underlying file or device can accept, and a \fBgets\fR or \fBread\fR
command will block if you attempt to read more data than is ready; a
readable underlying file or device may not even guarantee that a
blocking [read 1] will succeed (counter-examples being multi-byte
encodings, compression or encryption transforms ). In all such cases,
no events will be processed while the commands block.
.PP
In nonblocking mode \fBputs\fR, \fBread\fR, and \fBgets\fR never block.
See the documentation for the individual commands for information
on how they handle blocking and nonblocking channels.
.PP
Testing for the end of file condition should be done after any attempts
read the channel data. The eof flag is set once an attempt to read the
end of data has occurred and testing before this read will require an
additional event to be fired.
.PP
The script for a file event is executed at global level (outside the
context of any Tcl procedure) in the interpreter in which the
\fBfileevent\fR command was invoked.
The \fBfileevent\fR command has been superceded by the \fBchan event\fR
If an error occurs while executing the script then the
command registered with \fBinterp bgerror\fR is used to report the error.
In addition, the file event handler is deleted if it ever returns
an error;  this is done in order to prevent infinite loops due to
buggy handlers.
.SH EXAMPLE
.PP
In this setup \fBGetData\fR will be called with the channel as an
argument whenever $chan becomes readable. The \fBread\fR call will
read whatever binary data is currently available without blocking.
Here the channel has the fileevent removed when an end of file
occurs to avoid being continually called (see above). Alternatively
the channel may be closed on this condition.
.PP
.CS
proc GetData {chan} {
    set data [read $chan]
    puts "[string length $data] $data"
    if {[eof $chan]} {
        fileevent $chan readable {}
    }
}

command which supports the same syntax and options.
fconfigure $chan -blocking 0 -encoding binary
\fBfileevent\fR $chan readable [list GetData $chan]
.CE
.PP
The next example demonstrates use of \fBgets\fR to read line-oriented
data.
.PP
.CS
proc GetData {chan} {
    if {[gets $chan line] >= 0} {
        puts $line
    }
    if {[eof $chan]} {
        close $chan
    }
}

fconfigure $chan -blocking 0 -buffering line -translation crlf
\fBfileevent\fR $chan readable [list GetData $chan]
.CE
.SH CREDITS
.PP
\fBfileevent\fR is based on the \fBaddinput\fR command created
by Mark Diekhans.
.SH "SEE ALSO"
fconfigure(n), gets(n), interp(n), puts(n), read(n), Tcl_StandardChannels(3)
.SH KEYWORDS
asynchronous I/O, blocking, channel, event handler, nonblocking, readable,
chan(n)
script, writable.
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/filename.n.

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
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







+
-
+





+
-
+









+



+




+



+



+




+





+













+






+




+




+




+




+




+
+
+
+
+
+
+


+
+
+
+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
-
-
-
-
-
-
-












-
+
-
-



















-
+







type of a given path.
.SH "PATH SYNTAX"
.PP
The rules for native names depend on the value reported in the Tcl
\fBplatform\fR element of the \fBtcl_platform\fR array:
.TP 10
\fBUnix\fR
.
On Unix and Apple MacOS X platforms, Tcl uses path names where the
On Unix and Apple macOS platforms, Tcl uses path names where the
components are separated by slashes.  Path names may be relative or
absolute, and file names may contain any character other than slash.
The file names \fB\&.\fR and \fB\&..\fR are special and refer to the
current directory and the parent of the current directory respectively.
Multiple adjacent slash characters are interpreted as a single
separator, except for the first double slash \fB//\fR in absolute paths.
separator.  Any number of trailing slash characters at the end of a
Any number of trailing slash characters at the end of a
path are simply ignored, so the paths \fBfoo\fR, \fBfoo/\fR and
\fBfoo//\fR are all identical, and in particular \fBfoo/\fR does not
necessarily mean a directory is being referred.
.RS
.PP
The following examples illustrate various forms of path
names:
.TP 15
\fB/\fR
.
Absolute path to the root directory.
.TP 15
\fB/etc/passwd\fR
.
Absolute path to the file named \fBpasswd\fR in the directory
\fBetc\fR in the root directory.
.TP 15
\fB\&.\fR
.
Relative path to the current directory.
.TP 15
\fBfoo\fR
.
Relative path to the file \fBfoo\fR in the current directory.
.TP 15
\fBfoo/bar\fR
.
Relative path to the file \fBbar\fR in the directory \fBfoo\fR in the
current directory.
.TP 15
\fB\&../foo\fR
.
Relative path to the file \fBfoo\fR in the directory above the current
directory.
.RE
.TP
\fBWindows\fR
.
On Microsoft Windows platforms, Tcl supports both drive-relative and UNC
style names.  Both \fB/\fR and \fB\e\fR may be used as directory separators
in either type of name.  Drive-relative names consist of an optional drive
specifier followed by an absolute or relative path.  UNC paths follow the
general form \fB\e\eservername\esharename\epath\efile\fR, but must at
the very least contain the server and share components, i.e.
\fB\e\eservername\esharename\fR.  In both forms,
the file names \fB.\fR and \fB..\fR are special and refer to the current
directory and the parent of the current directory respectively.  The
following examples illustrate various forms of path names:
.RS
.TP 15
\fB\&\e\eHost\eshare/file\fR
.
Absolute UNC path to a file called \fBfile\fR in the root directory of
the export point \fBshare\fR on the host \fBHost\fR.  Note that
repeated use of \fBfile dirname\fR on this path will give
\fB//Host/share\fR, and will never give just \fB//Host\fR.
.TP 15
\fBc:foo\fR
.
Volume-relative path to a file \fBfoo\fR in the current directory on drive
\fBc\fR.
.TP 15
\fBc:/foo\fR
.
Absolute path to a file \fBfoo\fR in the root directory of drive
\fBc\fR.
.TP 15
\fBfoo\ebar\fR
.
Relative path to a file \fBbar\fR in the \fBfoo\fR directory in the current
directory on the current volume.
.TP 15
\fB\&\efoo\fR
.
Volume-relative path to a file \fBfoo\fR in the root directory of the current
volume.
.TP 15
\fB\&\e\efoo\fR
.
Volume-relative path to a file \fBfoo\fR in the root directory of the current
volume.  This is not a valid UNC path, so the assumption is that the
extra backslashes are superfluous.
.RE
.TP
\fBZipfs\fR
.RS
On all platforms where \fBzipfs\fR support is enabled, paths within mounted
ZIP archives begin with the string returned by the \fBzipfs root\fR command.
Zipfs paths are case-sensitive on all platforms.
.RE
.SH "TILDE SUBSTITUTION"
.PP
Unlike earlier versions of Tcl, Tcl 9 does not do implicit tilde substitution
on file paths with the exception noted below. The commands \fBfile home\fR and
\fBfile tildeexpand\fR may be used to explicitly accomplish the same.
.PP
In addition to the file name rules described above, Tcl also supports
The exception to the above is initialization of the \fBauto_path\fR variable
\fIcsh\fR-style tilde substitution.  If a file name starts with a tilde,
then the file name will be interpreted as if the first element is
replaced with the location of the home directory for the given user.  If
the tilde is followed immediately by a separator, then the \fB$HOME\fR
environment variable is substituted.  Otherwise the characters between
the tilde and the next separator are taken as a user name, which is used
to retrieve the user's home directory for substitution.  This works on
and the Tcl module search paths as documented in the manpages for
\fBtclvars\fR and \fBtm\fR. When any path in an environment variable used to
initialize these starts with a tilde, it will be interpreted as if the first
element is replaced with the location of the home directory for the given
user. If the tilde is followed immediately by a separator, the
\fB$HOME\fR environment variable is substituted. Otherwise the characters
between the tilde and the next separator are taken as a user name, which is
used to retrieve the user's home directory for substitution. This works on
Unix, MacOS X and Windows (except very old releases).
.PP
Old Windows platforms do not support tilde substitution when a user name
POSIX, macOS and Windows platforms.
follows the tilde.  On these platforms, attempts to use a tilde followed
by a user name will generate an error that the user does not exist when
Tcl attempts to interpret that part of the path or otherwise access the
file.  The behaviour of these paths when not trying to interpret them is
the same as on Unix.  File names that have a tilde without a user name
will be correctly substituted using the \fB$HOME\fR environment
variable, just like for Unix.
.SH "PORTABILITY ISSUES"
.PP
Not all file systems are case sensitive, so scripts should avoid code
that depends on the case of characters in a file name.  In addition,
the character sets allowed on different devices may differ, so scripts
should choose file names that do not contain special characters like:
\fB<>:?"/\e|\fR.
'\""\" reset emacs highlighting
The safest approach is to use names consisting of
alphanumeric characters only.  Care should be taken with filenames
which contain spaces (common on Windows systems) and
filenames where the backslash is the directory separator (Windows
native path names).  Also Windows 3.1 only supports file
native path names).
names with a root of no more than 8 characters and an extension of no
more than 3 characters.
.PP
On Windows platforms there are file and path length restrictions.
Complete paths or filenames longer than about 260 characters will lead
to errors in most file operations.
.PP
Another Windows peculiarity is that any number of trailing dots
.QW .
in filenames are totally ignored, so, for example, attempts to create a
file or directory with a name
.QW foo.
will result in the creation of a file/directory with name
.QW foo .
This fact is reflected in the results of \fBfile normalize\fR.
Furthermore, a file name consisting only of dots
.QW .........
or dots with trailing characters
.QW .....abc
is illegal.
.SH "SEE ALSO"
file(n), glob(n)
file(n), glob(n), zipfs(n)
.SH KEYWORDS
current directory, absolute file name, relative file name,
volume-relative file name, portability
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/flush.n.

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
8
9
10
11
12
13
14

15
16
17
18




















19



20
21



22
23
24
25
26







-
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+

-
-
-
+




.TH flush n 7.5 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
flush \- Flush buffered output for a channel
.SH SYNOPSIS
\fBflush \fIchannelId\fR
\fBflush \fIchannel\fR
.BE
.SH DESCRIPTION
.PP
Flushes any output that has been buffered for \fIchannelId\fR.
.PP
\fIChannelId\fR must be an identifier for an open channel such as a
Tcl standard channel (\fBstdout\fR or \fBstderr\fR), the return
value from an invocation of \fBopen\fR or \fBsocket\fR, or the result
of a channel creation command provided by a Tcl extension.  The
channel must have been opened for writing.
.PP
If the channel is in blocking mode the command does not return until all the
buffered output has been flushed to the channel. If the channel is in
nonblocking mode, the command may return before all buffered output has been
flushed; the remainder will be flushed in the background as fast as the
underlying file or device is able to absorb it.
.SH EXAMPLE
.PP
Prompt for the user to type some information in on the console:
.PP
.CS
puts -nonewline "Please type your name: "
\fBflush\fR stdout
The \fBflush\fR command has been superceded by the \fBchan flush\fR
gets stdin name
puts "Hello there, $name!"
.CE
command which supports the same syntax and options.
.SH "SEE ALSO"
file(n), open(n), socket(n), Tcl_StandardChannels(3)
.SH KEYWORDS
blocking, buffer, channel, flush, nonblocking, output
chan(n)
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/for.n.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
10
11
12
13
14
15
16

17
18
19
20
21
22
23







-







.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
for \- 'For' loop
.SH SYNOPSIS
\fBfor \fIstart test next body\fR
.BE

.SH DESCRIPTION
.PP
\fBFor\fR is a looping command, similar in structure to the C
\fBfor\fR statement.  The \fIstart\fR, \fInext\fR, and
\fIbody\fR arguments must be Tcl command strings, and \fItest\fR
is an expression string.
The \fBfor\fR command first invokes the Tcl interpreter to
34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47







-
+







or \fInext\fR,
then the \fBfor\fR command will
return immediately.
The operation of \fBbreak\fR and \fBcontinue\fR are similar to the
corresponding statements in C.
\fBFor\fR returns an empty string.
.PP
Note: \fItest\fR should almost always be enclosed in braces.  If not,
Note that \fItest\fR should almost always be enclosed in braces.  If not,
variable substitutions will be made before the \fBfor\fR
command starts executing, which means that variable changes
made by the loop body will not be considered in the expression.
This is likely to result in an infinite loop.  If \fItest\fR is
enclosed in braces, variable substitutions are delayed until the
expression is evaluated (before
each loop iteration), so changes in the variables will be visible.

Changes to doc/foreach.n.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
12
13
14
15
16
17
18

19
20
21
22
23
24
25







-







.SH NAME
foreach \- Iterate over all elements in one or more lists
.SH SYNOPSIS
\fBforeach \fIvarname list body\fR
.br
\fBforeach \fIvarlist1 list1\fR ?\fIvarlist2 list2 ...\fR? \fIbody\fR
.BE

.SH DESCRIPTION
.PP
The \fBforeach\fR command implements a loop where the loop
variable(s) take on values from one or more lists.
In the simplest case there is one loop variable, \fIvarname\fR,
and one list, \fIlist\fR, that is a list of values to assign to \fIvarname\fR.
The \fIbody\fR argument is a Tcl script.
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
91
92
93
94
95
96
97

98
99

100
101
102
103
104
105







-


-






set x {}
\fBforeach\fR i {a b c} {j k} {d e f g} {
    lappend x $i $j $k
}
# The value of x is "a d e b f g c {} {}"
# There are 3 iterations of the loop.
.CE

.SH "SEE ALSO"
for(n), while(n), break(n), continue(n)

.SH KEYWORDS
foreach, iteration, list, loop
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/format.n.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
10
11
12
13
14
15
16

17
18
19
20
21
22
23







-







.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
format \- Format a string in the style of sprintf
.SH SYNOPSIS
\fBformat \fIformatString \fR?\fIarg arg ...\fR?
.BE

.SH INTRODUCTION
.PP
This command generates a formatted string in a fashion similar to the
ANSI C \fBsprintf\fR procedure.
\fIFormatString\fR indicates how to format the result, using
\fB%\fR conversion specifiers as in \fBsprintf\fR, and the additional
arguments, if any, provide values to be substituted into the result.
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
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







-
-
+



-
-
+


-
-
+


-
-
+


-
-
+







This follows the XPG3 conventions for positional specifiers.
If there are any positional specifiers in \fIformatString\fR
then all of the specifiers must be positional.
.SS "OPTIONAL FLAGS"
.PP
The second portion of a conversion specifier may contain any of the
following flag characters, in any order:
.TP 10
\fB\-\fR
.IP \fB\-\fR 10
Specifies that the converted argument should be left-justified
in its field (numbers are normally right-justified with leading
spaces if needed).
.TP 10
\fB+\fR
.IP \fB+\fR 10
Specifies that a number should always be printed with a sign,
even if positive.
.TP 10
\fIspace\fR
.IP \fIspace\fR 10
Specifies that a space should be added to the beginning of the
number if the first character is not a sign.
.TP 10
\fB0\fR
.IP \fB0\fR 10
Specifies that the number should be padded on the left with
zeroes instead of spaces.
.TP 10
\fB#\fR
.IP \fB#\fR 10
Requests an alternate output form. For \fBo\fR conversions,
\fB0o\fR will be added to the beginning of the result unless
it is zero. For \fBx\fR or \fBX\fR conversions, \fB0x\fR
will be added to the beginning of the result unless it is zero.
For \fBb\fR conversions, \fB0b\fR
will be added to the beginning of the result unless it is zero.
For \fBd\fR conversions, \fB0d\fR there is no effect unless
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
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







-
-
+
+





-
+




-
-
+
+

+
+
+


-
-
+
+
-
-
-





-
-
+

-
-
+

-
-
+

-
-
+

-
-
+





-
-
+

-
-
+

-
-
+

-
-
+




-
-
+






-
-
+





-
-
+





-
-
+

-
-
+







For \fBg\fR and \fBG\fR conversions it specifies the total number
of digits to appear, including those on both sides of the decimal
point (however, trailing zeroes after the decimal point will still
be omitted unless the \fB#\fR flag has been specified).
For integer conversions, it specifies a minimum number of digits
to print (leading zeroes will be added if necessary).
For \fBs\fR conversions it specifies the maximum number of characters to be
printed; if the string is longer than this then the trailing characters will be dropped.
If the precision is specified with \fB*\fR rather than a number
printed; if the string is longer than this then the trailing characters will
be dropped. If the precision is specified with \fB*\fR rather than a number
then the next argument to the \fBformat\fR command determines the precision;
it must be a numeric string.
.SS "OPTIONAL SIZE MODIFIER"
.PP
The fifth part of a conversion specifier is a size modifier,
which must be \fBll\fR, \fBh\fR, \fBl\fR, or \fBL\fR.
which must be \fBll\fR, \fBh\fR, \fBl\fR, \fBz\fR, \fBt\fR, or \fBL\fR.
If it is \fBll\fR it specifies that an integer value is taken
without truncation for conversion to a formatted substring.
If it is \fBh\fR it specifies that an integer value is
truncated to a 16-bit range before converting.  This option is rarely useful.
If it is \fBl\fR it specifies that the integer value is
truncated to the same range as that produced by the \fBwide()\fR
If it is \fBl\fR (or \fBj\fR or \fBq\fR) it specifies that the integer value
is truncated to the same range as that produced by the \fBwide()\fR
function of the \fBexpr\fR command (at least a 64-bit range).
If it is \fBz\fR or \fBt\fR it specifies that the integer value is
truncated to the range determined by the value of the \fBpointerSize\fR
element of the \fBtcl_platform\fR array.
If it is \fBL\fR it specifies that an integer or double value is taken
without truncation for conversion to a formatted substring.
If neither \fBh\fR nor \fBl\fR nor \fBL\fR are present, the integer value is
truncated to the same range as that produced by the \fBint()\fR
If neither of those are present, the integer value is
truncated to a 32-bit range.
function of the \fBexpr\fR command (at least a 32-bit range, but
determined by the value of the \fBwordSize\fR element of the
\fBtcl_platform\fR array).
.SS "MANDATORY CONVERSION TYPE"
.PP
The last thing in a conversion specifier is an alphabetic character
that determines what kind of conversion to perform.
The following conversion characters are currently supported:
.TP 10
\fBd\fR
.IP \fBd\fR 10
Convert integer to signed decimal string.
.TP 10
\fBu\fR
.IP \fBu\fR 10
Convert integer to unsigned decimal string.
.TP 10
\fBi\fR
.IP \fBi\fR 10
Convert integer to signed decimal string (equivalent to \fBd\fR).
.TP 10
\fBo\fR
.IP \fBo\fR 10
Convert integer to unsigned octal string.
.TP 10
\fBx\fR or \fBX\fR
.IP "\fBx\fR or \fBX\fR" 10
Convert integer to unsigned hexadecimal string, using digits
.QW 0123456789abcdef
for \fBx\fR and
.QW 0123456789ABCDEF
for \fBX\fR).
.TP 10
\fBb\fR
.IP \fBb\fR 10
Convert integer to unsigned binary string, using digits 0 and 1.
.TP 10
\fBc\fR
.IP \fBc\fR 10
Convert integer to the Unicode character it represents.
.TP 10
\fBs\fR
.IP \fBs\fR 10
No conversion; just insert string.
.TP 10
\fBf\fR
.IP \fBf\fR 10
Convert number to signed decimal string of
the form \fIxx.yyy\fR, where the number of \fIy\fR's is determined by
the precision (default: 6).
If the precision is 0 then no decimal point is output.
.TP 10
\fBe\fR or \fBE\fR
.IP "\fBe\fR or \fBE\fR" 10
Convert number to scientific notation in the
form \fIx.yyy\fBe\(+-\fIzz\fR, where the number of \fIy\fR's is determined
by the precision (default: 6).
If the precision is 0 then no decimal point is output.
If the \fBE\fR form is used then \fBE\fR is
printed instead of \fBe\fR.
.TP 10
\fBg\fR or \fBG\fR
.IP "\fBg\fR or \fBG\fR" 10
If the exponent is less than \-4 or greater than or equal to the
precision, then convert number as for \fB%e\fR or
\fB%E\fR.
Otherwise convert as for \fB%f\fR.
Trailing zeroes and a trailing decimal point are omitted.
.TP 10
\fBa\fR or \fBA\fR
.IP "\fBa\fR or \fBA\fR" 10
Convert double to hexadecimal notation in the form
\fI0x1.yyy\fBp\(+-\fIzz\fR, where the number of \fIy\fR's is
determined by the precision (default: 13).
If the \fBA\fR form is used then the hex characters
are printed in uppercase.
.TP 10
\fB%\fR
.IP \fB%\fR 10
No conversion: just insert \fB%\fR.
.TP 10
\fBp\fR
.IP \fBp\fR 10
Shorthand form for \fB0x%zx\fR, so it outputs the integer in
hexadecimal form with \fB0x\fR prefix.
.SH "DIFFERENCES FROM ANSI SPRINTF"
.PP
The behavior of the format command is the same as the
ANSI C \fBsprintf\fR procedure except for the following
differences:

Changes to doc/fpclassify.n.

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
30
31

32
33
34
35
36

37
38
39
40

41
42
43
44
45
46
47
48
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

30


31

32
33
34
35
36
37
38

-
-
+
+




-
+






-
+






-
-
+
-

-
-
+
-

-
-
+
-


-
-
+
-

-
-
+
-







'\"
'\" Copyright (c) 2018 by Kevin B. Kenny <kennykb@acm.org>. All rights reserved
'\" Copyright (c) 2019 by Donal Fellows
'\" Copyright (c) 2018 Kevin B. Kenny <kennykb@acm.org>. All rights reserved
'\" Copyright (c) 2019 Donal Fellows
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH fpclassify n 8.7 Tcl "Tcl Float Classifier"
.TH fpclassify n 9.0 Tcl "Tcl Float Classifier"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
fpclassify \- Floating point number classification of Tcl values
.SH SYNOPSIS
package require \fBTcl 8.7\fR
package require \fBtcl 9.0\fR
.sp
\fBfpclassify \fIvalue\fR
.BE
.SH DESCRIPTION
The \fBfpclassify\fR command takes a floating point number, \fIvalue\fR, and
returns one of the following strings that describe it:
.TP
\fBzero\fR
.IP \fBzero\fR
.
\fIvalue\fR is a floating point zero.
.TP
\fBsubnormal\fR
.IP \fBsubnormal\fR
.
\fIvalue\fR is the result of a gradual underflow.
.TP
\fBnormal\fR
.IP \fBnormal\fR
.
\fIvalue\fR is an ordinary floating-point number (not zero, subnormal,
infinite, nor NaN).
.TP
\fBinfinite\fR
.IP \fBinfinite\fR
.
\fIvalue\fR is a floating-point infinity.
.TP
\fBnan\fR
.IP \fBnan\fR
.
\fIvalue\fR is Not-a-Number.
.PP
The \fBfpclassify\fR command throws an error if value is not a floating-point
value and cannot be converted to one.
.SH EXAMPLE
.PP
This shows how to check whether the result of a computation is numerically
72
73
74
75
76
77
78
79

80
81
82
83
62
63
64
65
66
67
68

69
70
71
72
73







-
+




floating point
.SH STANDARDS
This command depends on the \fBfpclassify\fR() C macro conforming to
.QW "ISO C99"
(i.e., to ISO/IEC 9899:1999).
.SH COPYRIGHT
.nf
Copyright \(co 2018 by Kevin B. Kenny <kennykb@acm.org>. All rights reserved
Copyright \(co 2018 Kevin B. Kenny <kennykb@acm.org>. All rights reserved
.fi
'\" Local Variables:
'\" mode: nroff
'\" End:

Changes to doc/gets.n.

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
8
9
10
11
12
13
14

15
16

17
18






































19





20
21


22


23
24
25
26







-
+

-


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+

-
-
+
-
-




.TH gets n 7.5 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
gets \- Read a line from a channel
.SH SYNOPSIS
\fBgets \fIchannelId\fR ?\fIvarName\fR?
\fBgets \fIchannel\fR ?\fIvarName\fR?
.BE

.SH DESCRIPTION
.PP
This command reads the next line from \fIchannelId\fR, returns everything
in the line up to (but not including) the end-of-line character(s), and
discards the end-of-line character(s).
.PP
\fIChannelId\fR must be an identifier for an open channel such as the
Tcl standard input channel (\fBstdin\fR), the return value from an
invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel
creation command provided by a Tcl extension. The channel must have
been opened for input.
.PP
If \fIvarName\fR is omitted the line is returned as the result of the
command.
If \fIvarName\fR is specified then the line is placed in the variable by
that name and the return value is a count of the number of characters
returned.
.PP
If end of file occurs while scanning for an end of
line, the command returns whatever input is available up to the end of file.
If \fIchannelId\fR is in non-blocking mode and there is not a full
line of input available, the command returns an empty string and
does not consume any input.
If \fIvarName\fR is specified and an empty string is returned in
\fIvarName\fR because of end-of-file or because of insufficient
data in non-blocking mode, then the return count is -1.
Note that if \fIvarName\fR is not specified then the end-of-file
and no-full-line-available cases can
produce the same results as if there were an input line consisting
only of the end-of-line character(s).
The \fBeof\fR and \fBfblocked\fR commands can be used to distinguish
these three cases.
.SH "EXAMPLE"
This example reads a file one line at a time and prints it out with
the current line number attached to the start of each line.
.PP
.CS
set chan [open "some.file.txt"]
set lineNumber 0
while {[\fBgets\fR $chan line] >= 0} {
The \fBgets\fR command has been superceded by the \fBchan gets\fR
    puts "[incr lineNumber]: $line"
}
close $chan
.CE

command which supports the same syntax and options.
.SH "SEE ALSO"
file(n), eof(n), fblocked(n), Tcl_StandardChannels(3)

chan(n)
.SH KEYWORDS
blocking, channel, end of file, end of line, line, non-blocking, read
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/glob.n.

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
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







+

-
+







+






+



-
-
+
+
+

-
+











+











-
+

+

-
+




















-
-
+
+


-
+















+










-
-
+
-

-
-
+
-

-
-
+
-



-
-
+
-

-
-
+
-







in the list, so if a sorted list is required the caller should use
\fBlsort\fR.
.SS OPTIONS
.PP
If the initial arguments to \fBglob\fR start with \fB\-\fR then
they are treated as switches. The following switches are
currently supported:
.\" OPTION: -directory
.TP
\fB\-directory\fR \fIdirectory\fR
\fB\-directory\fI directory\fR
.
Search for files which match the given patterns starting in the given
\fIdirectory\fR. This allows searching of directories whose name
contains glob-sensitive characters without the need to quote such
characters explicitly. This option may not be used in conjunction with
\fB\-path\fR, which is used to allow searching for complete file paths
whose names may contain glob-sensitive characters.
.\" OPTION: -join
.TP
\fB\-join\fR
.
The remaining pattern arguments, after option processing, are treated
as a single pattern obtained by joining the arguments with directory
separators.
.\" OPTION: -nocomplain
.TP
\fB\-nocomplain\fR
.
Allows an empty list to be returned without error; without this
switch an error is returned if the result list would be empty.
Allows an empty list to be returned without error; This is the
default behavior in Tcl 9.0, so this switch has no effect any more.
.\" OPTION: -path
.TP
\fB\-path\fR \fIpathPrefix\fR
\fB\-path\fI pathPrefix\fR
.
Search for files with the given \fIpathPrefix\fR where the rest of the name
matches the given patterns. This allows searching for files with names
similar to a given file (as opposed to a directory) even when the names
contain glob-sensitive
characters. This option may not be used in conjunction with
\fB\-directory\fR. For example, to find all files with the same root name
as $path, but differing extensions, you should use
.QW "\fBglob \-path [file rootname $path] .*\fR"
which will work even if \fB$path\fR contains
numerous glob-sensitive characters.
.\" OPTION: -tails
.TP
\fB\-tails\fR
.
Only return the part of each file found which follows the last directory
named in any \fB\-directory\fR or \fB\-path\fR path specification.
Thus
.QW "\fBglob \-tails \-directory $dir *\fR"
is equivalent to
.QW "\fBset pwd [pwd]; cd $dir; glob *; cd $pwd\fR" .
For \fB\-path\fR specifications, the returned names will include the last
path segment, so
.QW "\fBglob \-tails \-path [file rootname ~/foo.tex] .*\fR"
.QW "\fBglob \-tails \-path [file rootname /home/fred/foo.tex] .*\fR"
will return paths like \fBfoo.aux foo.bib foo.tex\fR etc.
.\" OPTION: -types
.TP
\fB\-types\fR \fItypeList\fR
\fB\-types\fI typeList\fR
.
Only list files or directories which match \fItypeList\fR, where the items
in the list have two forms. The first form is like the \-type option of
the Unix find command:
\fIb\fR (block special file),
\fIc\fR (character special file),
\fId\fR (directory),
\fIf\fR (plain file),
\fIl\fR (symbolic link),
\fIp\fR (named pipe),
or \fIs\fR (socket), where multiple types may be specified in the list.
\fBGlob\fR will return all files which match at least one of the types given.
Note that symbolic links will be returned both if \fB\-types l\fR is given,
or if the target of a link matches the requested type. So, a link to
a directory will be returned if \fB\-types d\fR was specified.
.RS
.PP
The second form specifies types where all the types given must match.
These are \fIr\fR, \fIw\fR, \fIx\fR as file permissions, and
\fIreadonly\fR, \fIhidden\fR as special permission cases. On the
Macintosh, MacOS types and creators are also supported, where any item
which is four characters long is assumed to be a MacOS type
Macintosh, macOS types and creators are also supported, where any item
which is four characters long is assumed to be a macOS type
(e.g. \fBTEXT\fR). Items which are of the form \fI{macintosh type XXXX}\fR
or \fI{macintosh creator XXXX}\fR will match types or creators
respectively. Unrecognized types, or specifications of multiple MacOS
respectively. Unrecognized types, or specifications of multiple macOS
types/creators will signal an error.
.PP
The two forms may be mixed, so \fB\-types {d f r w}\fR will find all
regular files OR directories that have both read AND write permissions.
The following are equivalent:
.PP
.CS
\fBglob \-type d *\fR
\fBglob */\fR
.CE
.PP
except that the first case doesn't return the trailing
.QW /
and is more platform independent.
.RE
.\" OPTION: --
.TP
\fB\-\|\-\fR
.
Marks the end of switches. The argument following this one will
be treated as a \fIpattern\fR even if it starts with a \fB\-\fR.
.SS "GLOBBING PATTERNS"
.PP
The \fIpattern\fR arguments may contain any of the following
special characters, which are a superset of those supported by
\fBstring match\fR:
.TP 10
\fB?\fR
.IP \fB?\fR 10
.
Matches any single character.
.TP 10
\fB*\fR
.IP \fB*\fR 10
.
Matches any sequence of zero or more characters.
.TP 10
\fB[\fIchars\fB]\fR
.IP \fB[\fIchars\fB]\fR 10
.
Matches any single character in \fIchars\fR. If \fIchars\fR
contains a sequence of the form \fIa\fB\-\fIb\fR then any
character between \fIa\fR and \fIb\fR (inclusive) will match.
.TP 10
\fB\e\fIx\fR
.IP \fB\e\fIx\fR 10
.
Matches the character \fIx\fR.
.TP 10
\fB{\fIa\fB,\fIb\fB,\fI...\fR}
.IP \fB{\fIa\fB,\fIb\fB,\fI...\fB}\fR 10
.
Matches any of the sub-patterns \fIa\fR, \fIb\fR, etc.
.PP
On Unix, as with csh, a
.QW . \|
at the beginning of a file's name or just after a
.QW /
must be matched explicitly or with a {} construct, unless the
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
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







-
-
-
-
-
-
-
-
-
-







-
-
-
-
-
-
-
-
-
-



-
+
-
-
-
-
-
-







and
.QW .. \|
which must be matched explicitly (this is to avoid a recursive pattern like
.QW "glob \-join * * * *"
from recursing up the directory hierarchy as well as down). In addition, all
.QW /
characters must be matched explicitly.
.LP
If the first character in a \fIpattern\fR is
.QW ~
then it refers to the home directory for the user whose name follows the
.QW ~ .
If the
.QW ~
is followed immediately by
.QW /
then the value of the HOME environment variable is used.
.PP
The \fBglob\fR command differs from csh globbing in two ways.
First, it does not sort its result list (use the \fBlsort\fR
command if you want the list sorted).
Second, \fBglob\fR only returns the names of files that actually
exist; in csh no check for existence is made unless a pattern
contains a ?, *, or [] construct.
.LP
When the \fBglob\fR command returns relative paths whose filenames
start with a tilde
.QW ~
(for example through \fBglob *\fR or \fBglob \-tails\fR, the returned
list will not quote the tilde with
.QW ./ .
This means care must be taken if those names are later to
be used with \fBfile join\fR, to avoid them being interpreted as
absolute paths pointing to a given user's home directory.
.SH "WINDOWS PORTABILITY ISSUES"
.PP
For Windows UNC names, the servername and sharename components of the path
may not contain ?, *, or [] constructs. On Windows NT, if \fIpattern\fR is
may not contain ?, *, or [] constructs.
of the form
.QW \fB~\fIusername\fB@\fIdomain\fR ,
it refers to the home
directory of the user whose account information resides on the specified NT
domain server. Otherwise, user account information is obtained from
the local computer.
.PP
Since the backslash character has a special meaning to the glob
command, glob patterns containing Windows style path separators need
special care. The pattern
.QW \fIC:\e\efoo\e\e*\fR
is interpreted as
.QW \fIC:\efoo\e*\fR
235
236
237
238
239
240
241
242

243
244
245
246
247
248
249
206
207
208
209
210
211
212

213
214
215
216
217
218
219
220







-
+







\fBglob\fR *.tcl
.CE
.PP
Find all the Tcl files in the user's home directory, irrespective of
what the current directory is:
.PP
.CS
\fBglob\fR \-directory ~ *.tcl
\fBglob\fR \-directory [file home] *.tcl
.CE
.PP
Find all subdirectories of the current directory:
.PP
.CS
\fBglob\fR \-type d *
.CE

Changes to doc/history.n.

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
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







-
-
+
+
+


+




+


+







+


+


+


+


+


+




+


+



+


+



+


+













-
-
+
+







An event is considered to match the string either if the string is
the same as the first characters of the event, or if the string
matches the event in the sense of the \fBstring match\fR command.
.PP
The \fBhistory\fR command can take any of the following forms:
.TP
\fBhistory\fR
Same
as \fBhistory info\fR, described below.
.
Same as \fBhistory info\fR, described below.
.\" METHOD: add
.TP
\fBhistory add\fI command \fR?\fBexec\fR?
.
Adds the \fIcommand\fR argument to the history list as a new event.  If
\fBexec\fR is specified (or abbreviated) then the command is also
executed and its result is returned.  If \fBexec\fR is not specified
then an empty string is returned as result.
.\" METHOD: change
.TP
\fBhistory change\fI newValue\fR ?\fIevent\fR?
.
Replaces the value recorded for an event with \fInewValue\fR.  \fIEvent\fR
specifies the event to replace, and
defaults to the \fIcurrent\fR event (not event \fB\-1\fR).  This command
is intended for use in commands that implement new forms of history
substitution and wish to replace the current event (which invokes the
substitution) with the command created through substitution.  The return
value is an empty string.
.\" METHOD: clear
.TP
\fBhistory clear\fR
.
Erase the history list.  The current keep limit is retained.
The history event numbers are reset.
.\" METHOD: event
.TP
\fBhistory event\fR ?\fIevent\fR?
.
Returns the value of the event given by \fIevent\fR.  \fIEvent\fR
defaults to \fB\-1\fR.
.\" METHOD: info
.TP
\fBhistory info \fR?\fIcount\fR?
.
Returns a formatted string (intended for humans to read) giving
the event number and contents for each of the events in the history
list except the current event.  If \fIcount\fR is specified
then only the most recent \fIcount\fR events are returned.
.\" METHOD: keep
.TP
\fBhistory keep \fR?\fIcount\fR?
.
This command may be used to change the size of the history list to
\fIcount\fR events.  Initially, 20 events are retained in the history
list.  If \fIcount\fR is not specified, the current keep limit is returned.
.\" METHOD: nextid
.TP
\fBhistory nextid\fR
.
Returns the number of the next event to be recorded
in the history list.  It is useful for things like printing the
event number in command-line prompts.
.\" METHOD: redo
.TP
\fBhistory redo \fR?\fIevent\fR?
.
Re-executes the command indicated by \fIevent\fR and returns its result.
\fIEvent\fR defaults to \fB\-1\fR.  This command results in history
revision:  see below for details.
.SH "HISTORY REVISION"
.PP
Pre-8.0 Tcl had a complex history revision mechanism.
The current mechanism is more limited, and the old
history operations \fBsubstitute\fR and \fBwords\fR have been removed.
(As a consolation, the \fBclear\fR operation was added.)
.PP
The history option \fBredo\fR results in much simpler
.QW "history revision" .
When this option is invoked then the most recent event
is modified to eliminate the history command and replace it with
the result of the history command.
is modified to eliminate the \fBhistory\fR command and replace it with
the result of the \fBhistory\fR command.
If you want to redo an event without modifying history, then use
the \fBevent\fR operation to retrieve some event,
and the \fBadd\fR operation to add it to history and execute it.
.SH KEYWORDS
event, history, record
'\" Local Variables:
'\" mode: nroff

Changes to doc/http.n.

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
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
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
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
467




























468
469
470
471
472
473
474

475
476
477
478


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


558
559
560





561
562
563
564
565
566
567










568
569
570

571
572
573
574
575

576

577
578
579
580
581
582
583
584
585
586
587
588
589
590
591

592
593
594
595
596
597


598
599
600
601
602
603
604












605
606
607

608
609

610
611
612
613
614


615
616
617

618
619
620
621
622
623




624
625
626

627
628


629
630
631
632
633





634
635
636
637



638
639
640

641
642
643
644
645
646

647
648
649
650


651
652



653
654
655

656
657



658
659
660
661
662

663
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

707
708
709
710
711
712
713
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


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
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
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
467
468
469
470
471
472

473
474
475
476
477
478
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
558
559
560
561
562
563

564
565
566




567
568
569
570
571
572
573
574

575
576
577
578
579
580
581
582
583

584
585
586
587
588
589

590
591
592
593
594
595
596

597
598

599
600
601
602
603
604
605
606
607

608
609





610
611
612
613
614
615





616
617
618
619


620
621

622
623


624
625
626
627

628
629


630
631
632
633
634

635
636



637


638
639



640
641
642
643
644

645
646

647
648
649
650

651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822

823
824
825
826

827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860

861
862
863
864
865
866
867
868

869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909

910


911
912


913

914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929

930

931
932
933
934
935
936
937
938
939
940

941
942
943
944
945
946
947
948

949
950
951
952


953

954



955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195

1196


1197
1198



1199
1200
1201
1202
1203



1204



1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216

1217
1218
1219
1220
1221
1222
1223

1224















1225






1226
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


-
+





-
+






+
-
+

-
+

-

-
-
+
-
-
+
-
-
+
-

-

-

-
-
+
-
-
+
-
-
+
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
-
-
+
-

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+
+












-
-
+
+
-




-
+




+
+
+
+
+
+
+
+
+
+
+
+
+

+











+

-
+






+

-
+







+

-
+




+

-
+


-
-
-
+
+
+
+

-
+

+
+
-
-
+
+
-
-
+
-
-
+
+
+

-
+






-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+










+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+



-
-
+
+
-
-
-
-

-
+




-
+



+

-
+


-
-
+
+
+

-
-
+
+

+

-
+


-
+


-
-
+
+






+

-
+



-
+

+

-
+




+

-
+


-
+
+

-
+

-
-
-
+
+
+
+







-
-
+
+
+
+


+
+
+
+
+

+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+

+
+
+
+
-
-
-
+
+
+
+








-
-
+
+









+
+
-
+
+
+
+

+
-
+
+
+
+
+
+
+
+

+

-
+















+

-
+



+

-
+


-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+



+

-
+

+
-
-
+
+
+
+

-
-
+
+
+
+






-
+
+
+
+



+

-
+




+

-
+

+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+







+

-
+





-
-
+
+


+

-
+

+
-
-
-
+
+
+
+
+

-
+

+
+
-
+
+

-
+





-
+
+

+

-
+




+

-
+


-
-
-
-
+
+
+
+
+

+

-
+






+

-
+



+

-
+




+

-
+

-
+






+

-
+

-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
-
-
+

-
+

-
-
+
+
+

-
+

-
-
+
+
+
+

-
+

-
-
-
+
-
-
+
+
-
-
-
+
+
+
+
+
-
+

-
+



-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+



-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+




+
+

-
+









+

-
+


-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+
-
-


-
-

-
+
+
+
+
+











-
+
-




+
+
+
+
+
+
-
+
+
+





-
+
+
+

-
-
+
-

-
-
-
+
+
+


-
-
+
-


+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
-
+
-
-
+
+
-
-
-
+
+
+
+
+
-
-
-

-
-
-
+
+
+
+
+
+
+
+
+
+


-
+





+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
-
-
+
-
-
-
-
-
+
+
-
-
-
+
-
-
-
-
-
-
+
+
+
+
-
-
-
+
-
-
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
+
+
-
-
+
+
+
-
-
-
+
-
-
+
+
+
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
+
+
-
-
+
+
-
-
+
+
-
-
-
-
+
+
+
+
-
-
+



















-
+

-
+







'\"
'\" Copyright (c) 1995-1997 Sun Microsystems, Inc.
'\" Copyright (c) 1998-2000 by Ajuba Solutions.
'\" Copyright (c) 1998-2000 Ajuba Solutions.
'\" Copyright (c) 2004 ActiveState Corporation.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH "http" n 2.9 http "Tcl Bundled Packages"
.TH "http" n 2.10 http "Tcl Bundled Packages"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
http \- Client-side implementation of the HTTP/1.1 protocol
.SH SYNOPSIS
.nf
\fBpackage require http\fI ?\fB2.9\fR?
\fBpackage require http\fR ?\fB2.10\fR?
.\" See Also -useragent option documentation in body!
.sp

\fB::http::config\fR ?\fI\-option value\fR ...?
.sp
\fB::http::geturl \fIurl\fR ?\fI\-option value\fR ...?
.sp
\fB::http::formatQuery\fR \fIkey value\fR ?\fIkey value\fR ...?
\fB::http::formatQuery\fI key value\fR ?\fIkey value\fR ...?
.sp
\fB::http::quoteString\fR \fIvalue\fR
\fB::http::quoteString\fI value\fR
.sp
\fB::http::reset\fR \fItoken\fR ?\fIwhy\fR?
\fB::http::reset\fI token\fR ?\fIwhy\fR?
.sp
\fB::http::wait \fItoken\fR
.sp
\fB::http::status \fItoken\fR
.sp
\fB::http::size \fItoken\fR
.sp
\fB::http::code \fItoken\fR
\fB::http::error \fItoken\fR
.sp
\fB::http::ncode \fItoken\fR
\fB::http::postError \fItoken\fR
.sp
\fB::http::meta \fItoken\fR
\fB::http::cleanup \fItoken\fR
.sp
\fB::http::data \fItoken\fR
.sp
\fB::http::error \fItoken\fR
\fB::http::requestLine\fI token\fR
\fB::http::requestHeaders\fI token\fR ?\fIheaderName\fR?
\fB::http::requestHeaderValue\fI token headerName\fR
\fB::http::responseLine\fI token\fR
\fB::http::responseCode\fI token\fR
.sp
\fB::http::cleanup \fItoken\fR
.sp
\fB::http::register \fIproto port command\fR
\fB::http::reasonPhrase\fI code\fR
\fB::http::responseHeaders\fI token\fR ?\fIheaderName\fR?
\fB::http::responseHeaderValue\fI token headerName\fR
\fB::http::responseInfo\fI token\fR
\fB::http::responseBody\fI token\fR
\fB::http::register \fIproto port command\fR ?\fIsocketCmdVarName\fR? ?\fIuseSockThread\fR? ?\fIendToEndProxy\fR?
.sp
\fB::http::registerError \fIport\fR ?\fImessage\fR?
\fB::http::registerError \fIsock\fR ?\fImessage\fR?
.sp
\fB::http::unregister \fIproto\fR
\fB::http::code \fItoken\fR
\fB::http::data \fItoken\fR
\fB::http::meta \fItoken\fR ?\fIheaderName\fR?
\fB::http::metaValue\fI token headerName\fR
\fB::http::ncode \fItoken\fR
.fi
.SH "EXPORTED COMMANDS"
.PP
Namespace \fBhttp\fR exports the commands \fBconfig\fR, \fBformatQuery\fR,
\fBgeturl\fR, \fBpostError\fR, \fBquoteString\fR, \fBreasonPhrase\fR,
\fBregister\fR,
\fBregisterError\fR, \fBrequestHeaders\fR, \fBrequestHeaderValue\fR,
\fBrequestLine\fR, \fBresponseBody\fR, \fBresponseCode\fR,
\fBresponseHeaders\fR, \fBresponseHeaderValue\fR, \fBresponseInfo\fR,
\fBresponseLine\fR,
\fBreset\fR, \fBunregister\fR, and \fBwait\fR.
.PP
It does not export the commands \fBcleanup\fR, \fBcode\fR, \fBdata\fR,
\fBerror\fR, \fBmeta\fR, \fBmetaValue\fR, \fBncode\fR,
\fBsize\fR, or \fBstatus\fR.
.BE
.SH DESCRIPTION
.PP
The \fBhttp\fR package provides the client side of the HTTP/1.1
protocol, as defined in RFC 7230 to RFC 7235, which supersede RFC 2616.
protocol, as defined in RFC 9110 to 9112, which supersede RFC 7230
to RFC 7235, which in turn supersede RFC 2616.
The package implements the GET, POST, and HEAD operations
of HTTP/1.1.  It allows configuration of a proxy host to get through
firewalls.  The package is compatible with the \fBSafesock\fR security
policy, so it can be used by untrusted applets to do URL fetching from
a restricted set of hosts. This package can be extended to support
additional HTTP transport protocols, such as HTTPS, by providing
a custom \fBsocket\fR command, via \fB::http::register\fR.
.PP
The \fB::http::geturl\fR procedure does a HTTP transaction.
Its \fIoptions \fR determine whether a GET, POST, or HEAD transaction
is performed.
The return value of \fB::http::geturl\fR is a token for the transaction.
The value is also the name of an array in the ::http namespace
that contains state information about the transaction.  The elements
The token can be supplied as an argument to other commands, to manage the
transaction and examine its results.
of this array are described in the \fBSTATE ARRAY\fR section.
.PP
If the \fB\-command\fR option is specified, then
the HTTP operation is done in the background.
\fB::http::geturl\fR returns immediately after generating the
HTTP request and the callback is invoked
HTTP request and the \fB\-command\fR callback is invoked
when the transaction completes.  For this to work, the Tcl event loop
must be active.  In Tk applications this is always true.  For pure-Tcl
applications, the caller can use \fB::http::wait\fR after calling
\fB::http::geturl\fR to start the event loop.
.PP
\fBNote:\fR The event queue is even used without the \fB\-command\fR option.
As a side effect, arbitrary commands may be processed while \fBhttp::geturl\fR
is running.
.PP
When the HTTP server has replied to the request, call the command
\fB::http::responseInfo\fR, which
returns a \fBdict\fR of metadata that is essential for identifying a
successful transaction and making use of the response.  See
section \fBMETADATA\fR for details of the information returned.
The response itself is returned by command \fB::http::responseBody\fR,
unless it has been redirected to a file by the \fI\-channel\fR option
of \fB::http::geturl\fR.
.SH COMMANDS
.\" COMMAND: config
.TP
\fB::http::config\fR ?\fIoptions\fR?
.
The \fB::http::config\fR command is used to set and query the name of the
proxy server and port, and the User-Agent name used in the HTTP
requests.  If no options are specified, then the current configuration
is returned.  If a single argument is specified, then it should be one
of the flags described below.  In this case the current value of
that setting is returned.  Otherwise, the options should be a set of
flags and values that define the configuration:
.RS
.\" OPTION: -accept
.TP
\fB\-accept\fR \fImimetypes\fR
\fB\-accept\fI mimetypes\fR
.
The Accept header of the request.  The default is */*, which means that
all types of documents are accepted.  Otherwise you can supply a
comma-separated list of mime type patterns that you are
willing to receive.  For example,
.QW "image/gif, image/jpeg, text/*" .
.\" OPTION: -cookiejar
.TP
\fB\-cookiejar\fR \fIcommand\fR
\fB\-cookiejar\fI command\fR
.VS TIP406
The cookie store for the package to use to manage HTTP cookies.
\fIcommand\fR is a command prefix list; if the empty list (the
default value) is used, no cookies will be sent by requests or stored
from responses. The command indicated by \fIcommand\fR, if supplied,
must obey the \fBCOOKIE JAR PROTOCOL\fR described below.
.VE TIP406
.\" OPTION: -pipeline
.TP
\fB\-pipeline\fR \fIboolean\fR
\fB\-pipeline\fI boolean\fR
.
Specifies whether HTTP/1.1 transactions on a persistent socket will be
pipelined.  See the \fBPERSISTENT SOCKETS\fR section for details. The default
is 1.
.\" OPTION: -postfresh
.TP
\fB\-postfresh\fR \fIboolean\fR
\fB\-postfresh\fI boolean\fR
.
Specifies whether requests that use the \fBPOST\fR method will always use a
fresh socket, overriding the \fB-keepalive\fR option of
command \fBhttp::geturl\fR.  See the \fBPERSISTENT SOCKETS\fR section for details.
The default is 0.
fresh socket, overriding the \fB\-keepalive\fR option of
command \fBhttp::geturl\fR.  See the \fBPERSISTENT SOCKETS\fR section for
details. The default is 0.
.\" OPTION: -proxyauth
.TP
\fB\-proxyhost\fR \fIhostname\fR
\fB\-proxyauth\fI string\fR
.
If non-empty, the string is supplied to the proxy server as the value of the
request header Proxy-Authorization.  This option can be used for HTTP Basic
The name of the proxy host, if any.  If this value is the
empty string, the URL host is contacted directly.
Authentication.  If the proxy server requires authentication by another
technique, e.g. Digest Authentication, the \fB\-proxyauth\fR option is not
.TP
\fB\-proxyport\fR \fInumber\fR
useful.  In that case the caller must expect a 407 response from the proxy,
.
The proxy port number.
compute the authentication value to be supplied, and use the \fB\-headers\fR
option to supply it as the value of the Proxy-Authorization header.
.\" OPTION: -proxyfilter
.TP
\fB\-proxyfilter\fR \fIcommand\fR
\fB\-proxyfilter\fI command\fR
.
The command is a callback that is made during
\fB::http::geturl\fR
to determine if a proxy is required for a given host.  One argument, a
host name, is added to \fIcommand\fR when it is invoked.  If a proxy
is required, the callback should return a two-element list containing
the proxy server and proxy port.  Otherwise the filter should return
an empty list.  The default filter returns the values of the
\fB\-proxyhost\fR and \fB\-proxyport\fR settings if they are
non-empty.
the proxy server and proxy port.  Otherwise the filter command should return
an empty list.
.RS
.PP
The default value of \fB\-proxyfilter\fR is \fBhttp::ProxyRequired\fR, and
this command returns the values of the \fB\-proxyhost\fR and
\fB\-proxyport\fR settings if they are non-empty.  The options
\fB\-proxyhost\fR, \fB\-proxyport\fR, and \fB\-proxynot\fR are used only
by \fBhttp::ProxyRequired\fR, and nowhere else in \fB::http::geturl\fR.
A user-supplied \fB\-proxyfilter\fR command may use these options, or
alternatively it may obtain values from elsewhere in the calling script.
In the latter case, any values provided for \fB\-proxyhost\fR,
\fB\-proxyport\fR, and \fB\-proxynot\fR are unused.
.PP
The \fB::http::geturl\fR command runs the \fB\-proxyfilter\fR callback inside
a \fBcatch\fR command.  Therefore an error in the callback command does
not call the \fBbgerror\fR handler.  See the \fBERRORS\fR section for
details.
.RE
.\" OPTION: -proxyhost
.TP
\fB\-proxyhost\fI hostname\fR
.
The host name or IP address of the proxy server, if any.  If this value is
the empty string, the URL host is contacted directly.  See
\fB\-proxyfilter\fR for how the value is used.
.\" OPTION: -proxynot
.TP
\fB\-proxynot\fI list\fR
.
A Tcl list of domain names and IP addresses that should be accessed directly,
not through the proxy server.  The target hostname is compared with each list
element using a case-insensitive \fBstring match\fR.  It is often convenient
to use the wildcard "*" at the start of a domain name (e.g. *.example.com) or
at the end of an IP address (e.g. 192.168.0.*).  See \fB\-proxyfilter\fR for
how the value is used.
.\" OPTION: -proxyport
.TP
\fB\-proxyport\fI number\fR
.
The port number of the proxy server.  See \fB\-proxyfilter\fR for how the
value is used.
.\" OPTION: -repost
.TP
\fB\-repost\fR \fIboolean\fR
\fB\-repost\fI boolean\fR
.
Specifies what to do if a POST request over a persistent connection fails
because the server has half-closed the connection.  If boolean \fBtrue\fR, the
request
will be automatically retried; if boolean \fBfalse\fR it will not, and the
application
that uses \fBhttp::geturl\fR is expected to seek user confirmation before
retrying the POST.  The value \fBtrue\fR should be used only under certain
conditions. See the \fBPERSISTENT SOCKETS\fR section for details. The
default is 0.
.\" OPTION: -threadlevel
.TP
\fB\-threadlevel\fI level\fR
.
Specifies whether and how to use the \fBThread\fR package.  Possible values
of \fIlevel\fR are 0, 1 or 2.
.RS
.IP \fB0\fR
(the default) do not use Thread
.IP \fB1\fR
use Thread if it is available, do not use it if it is unavailable
.IP \fB2\fR
use Thread if it is available, raise an error if it is unavailable
.PP
The Tcl \fBsocket -async\fR command can block in adverse cases (e.g. a slow
DNS lookup).  Using the Thread package works around this problem, for both
HTTP and HTTPS transactions.  Values of \fIlevel\fR other than 0 are
available only to the main interpreter in each thread.  See
section \fBTHREADS\fR for more information.
.RE
.\" OPTION: -urlencoding
.TP
\fB\-urlencoding\fR \fIencoding\fR
\fB\-urlencoding\fI encoding\fR
.
The \fIencoding\fR used for creating the x-url-encoded URLs with
\fB::http::formatQuery\fR and \fB::http::quoteString\fR.
The default is \fButf-8\fR, as specified by RFC
2718.  Prior to http 2.5 this was unspecified, and that behavior can be
The default is \fButf-8\fR, as specified by RFC 2718.
.\" OPTION: -useragent
returned by specifying the empty string (\fB{}\fR), although
\fIiso8859-1\fR is recommended to restore similar behavior but without the
\fB::http::formatQuery\fR or \fB::http::quoteString\fR
throwing an error processing non-latin-1 characters.
.TP
\fB\-useragent\fR \fIstring\fR
\fB\-useragent\fI string\fR
.
The value of the User-Agent header in the HTTP request.  In an unsafe
interpreter, the default value depends upon the operating system, and
the version numbers of \fBhttp\fR and \fBTcl\fR, and is (for example)
.QW "\fBMozilla/5.0 (Windows; U; Windows NT 10.0) http/2.9.0 Tcl/8.6.9\fR" .
.QW "\fBMozilla/5.0 (Windows; U; Windows NT 10.0) http/2.10.0 Tcl/9.0.0\fR" .
A safe interpreter cannot determine its operating system, and so the default
in a safe interpreter is to use a Windows 10 value with the current version
numbers of \fBhttp\fR and \fBTcl\fR.
.\" OPTION: -zip
.TP
\fB\-zip\fR \fIboolean\fR
\fB\-zip\fI boolean\fR
.
If the value is boolean \fBtrue\fR, then by default requests will send a header
.QW "\fBAccept-Encoding: gzip,deflate,compress\fR" .
If the value is boolean \fBfalse\fR, then by default this header will not be sent.
.QW "\fBAccept-Encoding: gzip,deflate\fR" .
If the value is boolean \fBfalse\fR, then by default requests will send a header
.QW "\fBAccept-Encoding: identity\fR" .
In either case the default can be overridden for an individual request by
supplying a custom \fBAccept-Encoding\fR header in the \fB-headers\fR option
of \fBhttp::geturl\fR. The default is 1.
supplying a custom \fBAccept-Encoding\fR header in the \fB\-headers\fR option
of \fBhttp::geturl\fR. The default value is 1.
.RE
.\" COMMAND: geturl
.TP
\fB::http::geturl\fR \fIurl\fR ?\fIoptions\fR?
\fB::http::geturl\fI url\fR ?\fIoptions\fR?
.
The \fB::http::geturl\fR command is the main procedure in the package.
The \fB\-query\fR option causes a POST operation and
The \fB\-query\fR or \fB\-querychannel\fR option causes a POST operation and
the \fB\-validate\fR option causes a HEAD operation;
otherwise, a GET operation is performed.  The \fB::http::geturl\fR command
returns a \fItoken\fR value that can be used to get
information about the transaction.  See the \fBSTATE ARRAY\fR and
returns a \fItoken\fR value that can be passed as an argument to other commands
to get information about the transaction.  See the \fBMETADATA\fR and
\fBERRORS\fR section for
details.  The \fB::http::geturl\fR command blocks until the operation
completes, unless the \fB\-command\fR option specifies a callback
that is invoked when the HTTP transaction completes.
\fB::http::geturl\fR takes several options:
.RS
.\" OPTION: -binary
.TP
\fB\-binary\fR \fIboolean\fR
\fB\-binary\fI boolean\fR
.
Specifies whether to force interpreting the URL data as binary.  Normally
this is auto-detected (anything not beginning with a \fBtext\fR content
type or whose content encoding is \fBgzip\fR or \fBcompress\fR is
type or whose content encoding is \fBgzip\fR or \fBdeflate\fR is
considered binary data).
.\" OPTION: -blocksize
.TP
\fB\-blocksize\fR \fIsize\fR
\fB\-blocksize\fI size\fR
.
The block size used when reading the URL.
At most \fIsize\fR bytes are read at once.  After each block, a call to the
\fB\-progress\fR callback is made (if that option is specified).
.\" OPTION: -channel
.TP
\fB\-channel\fR \fIname\fR
\fB\-channel\fI name\fR
.
Copy the URL contents to channel \fIname\fR instead of saving it in
\fBstate(body)\fR.
a Tcl variable for retrieval by \fB::http::responseBody\fR.
.\" OPTION: -command
.TP
\fB\-command\fR \fIcallback\fR
\fB\-command\fI callback\fR
.
Invoke \fIcallback\fR after the HTTP transaction completes.
This option causes \fB::http::geturl\fR to return immediately.
The \fIcallback\fR gets an additional argument that is the \fItoken\fR returned
The presence of this option causes \fB::http::geturl\fR to return immediately.
After the HTTP transaction completes, the value of \fIcallback\fR is expanded,
an additional argument is added, and the resulting command is evaluated.
The additional argument is the \fItoken\fR returned
from \fB::http::geturl\fR. This token is the name of an array that is
described in the \fBSTATE ARRAY\fR section.  Here is a template for the
callback:
.RS
.PP
.CS
proc httpCallback {token} {
    upvar #0 $token state
    # Access state as a Tcl array
    upvar 0 $token state
    # Access state as a Tcl array defined in this proc
    ...
    return
}
.CE
.PP
The \fB::http::geturl\fR command runs the \fB\-command\fR callback inside
a \fBcatch\fR command.  Therefore an error in the callback command does
not call the \fBbgerror\fR handler.  See the \fBERRORS\fR section for
details.
.RE
.\" OPTION: -guesstype
.TP
\fB\-guesstype\fI boolean\fR
.
Attempt to guess the \fBContent-Type\fR and character set when a misconfigured
server provides no information.  The default value is \fIfalse\fR (do
nothing).  If boolean \fItrue\fR then, if the server does not send a
\fBContent-Type\fR header, or if it sends the value "application/octet-stream",
\fBhttp::geturl\fR will attempt to guess appropriate values.  This is not
intended to become a general-purpose tool, and currently it is limited to
detecting XML documents that begin with an XML declaration.  In this case
the \fBContent-Type\fR is changed to "application/xml", the binary flag
state(binary) is changed to 0, and the character set is changed to
the one specified by the "encoding" tag of the XML line, or to utf-8 if no
encoding is specified.  Not used if a \fB\-channel\fR is specified.
.\" OPTION: -handler
.TP
\fB\-handler\fR \fIcallback\fR
\fB\-handler\fI callback\fR
.
If this option is absent, \fBhttp::geturl\fR processes incoming data itself,
either appending it to the state(body) variable or writing it to the -channel.
But if the \fB\-handler\fR option is present, \fBhttp::geturl\fR does not do
this processing and instead calls \fIcallback\fR.
Invoke \fIcallback\fR whenever HTTP data is available; if present, nothing
else will be done with the HTTP data.  This procedure gets two additional
arguments: the socket for the HTTP data and the \fItoken\fR returned from
Whenever HTTP data is available, the value of \fIcallback\fR is expanded, an
additional two arguments are added, and the resulting command is evaluated.
The two additional
arguments are: the socket for the HTTP data and the \fItoken\fR returned from
\fB::http::geturl\fR.  The token is the name of a global array that is
described in the \fBSTATE ARRAY\fR section.  The procedure is expected
to return the number of bytes read from the socket.  Here is a
template for the callback:
.RS
.PP
.CS
proc httpHandlerCallback {socket token} {
    upvar #0 $token state
    # Access socket, and state as a Tcl array
    upvar 0 $token state
    # Access socket, and state as a Tcl array defined in this proc
    # For example...
    ...
    set data [read $socket 1000]
    set nbytes [string length $data]
    ...
    return $nbytes
}
.CE
.PP
The \fBhttp::geturl\fR code for the \fB\-handler\fR option is not compatible
with either compression or chunked transfer-encoding.  If \fB\-handler\fR is
The \fBhttp::geturl\fR code for the \fB-handler\fR option is not compatible with either compression or chunked transfer-encoding.  If \fB-handler\fR is specified, then to work around these issues \fBhttp::geturl\fR will reduce the HTTP protocol to 1.0, and override the \fB-zip\fR option (i.e. it will not send the header "\fBAccept-Encoding: gzip,deflate,compress\fR").
specified, then to work around these issues \fBhttp::geturl\fR will reduce the
HTTP protocol to 1.0, and override the \fB\-zip\fR option (i.e. it will
send the header \fBAccept-Encoding: identity\fR instead
of \fBAccept-Encoding: gzip,deflate\fR).
.PP
If options \fB\-handler\fR and \fB\-channel\fR are used together, the handler
If options \fB-handler\fR and \fB-channel\fR are used together, the handler is responsible for copying the data from the HTTP socket to the specified channel.  The name of the channel is available to the handler as element \fB-channel\fR of the token array.
is responsible for copying the data from the HTTP socket to the specified
channel.  The name of the channel is available to the handler as element
\fB\-channel\fR of the token array.
.PP
The \fB::http::geturl\fR command runs the \fB\-handler\fR callback inside
a \fBcatch\fR command.  Therefore an error in the callback command does
not call the \fBbgerror\fR handler.  See the \fBERRORS\fR section for
details.
.RE
.\" OPTION: -headers
.TP
\fB\-headers\fR \fIkeyvaluelist\fR
\fB\-headers\fI keyvaluelist\fR
.
This option is used to add headers not already specified
by \fB::http::config\fR to the HTTP request.  The
\fIkeyvaluelist\fR argument must be a list with an even number of
elements that alternate between keys and values.  The keys become
header field names.  Newlines are stripped from the values so the
header cannot be corrupted.  For example, if \fIkeyvaluelist\fR is
\fBPragma no-cache\fR then the following header is included in the
HTTP request:
.RS
.PP
.CS
Pragma: no-cache
.CE
.RE
.\" OPTION: -keepalive
.TP
\fB\-keepalive\fR \fIboolean\fR
\fB\-keepalive\fI boolean\fR
.
If boolean \fBtrue\fR, attempt to keep the connection open for servicing
multiple requests.  Default is 0.
.\" OPTION: -method
.TP
\fB\-method\fR \fItype\fR
\fB\-method\fI type\fR
.
Force the HTTP request method to \fItype\fR. \fB::http::geturl\fR will
auto-select GET, POST or HEAD based on other options, but this option
enables choices like PUT and DELETE for webdav support.
auto-select GET, POST or HEAD based on other options, but this option overrides
that selection and enables choices like PUT and DELETE for WebDAV support.
.RS
.PP
It is the caller's responsibility to ensure that the headers and request body
(if any) conform to the requirements of the request method.  For example, if
using \fB\-method\fI POST\fR to send a POST with an empty request body, the
caller must also supply the option
.PP
.CS
\-headers {Content-Length 0}
.CE
.RE
.\" OPTION: -myaddr
.TP
\fB\-myaddr\fR \fIaddress\fR
\fB\-myaddr\fI address\fR
.
Pass an specific local address to the underlying \fBsocket\fR call in case
multiple interfaces are available.
.\" OPTION: -progress
.TP
\fB\-progress\fR \fIcallback\fR
\fB\-progress\fI callback\fR
.
If the \fB\-progress\fR option is present,
The \fIcallback\fR is made after each transfer of data from the URL.
The callback gets three additional arguments: the \fItoken\fR from
then the \fIcallback\fR is made after each transfer of data from the URL.
The value of \fIcallback\fR is expanded, an additional three arguments are
added, and the resulting command is evaluated.
The three additional arguments are: the \fItoken\fR returned from
\fB::http::geturl\fR, the expected total size of the contents from the
\fBContent-Length\fR meta-data, and the current number of bytes
transferred so far.  The expected total size may be unknown, in which
\fBContent-Length\fR response header, and the current number of bytes
transferred so far.  The token is the name of a global array that is
described in the \fBSTATE ARRAY\fR section.  The expected total size may
be unknown, in which
case zero is passed to the callback.  Here is a template for the
progress callback:
.RS
.PP
.CS
proc httpProgress {token total current} {
    upvar #0 $token state
    upvar 0 $token state
    # Access state as a Tcl array defined in this proc
    ...
    return
}
.CE
.RE
.\" OPTION: -protocol
.TP
\fB\-protocol\fR \fIversion\fR
\fB\-protocol\fI version\fR
.
Select the HTTP protocol version to use. This should be 1.0 or 1.1 (the
default). Should only be necessary for servers that do not understand or
otherwise complain about HTTP/1.1.
.\" OPTION: -query
.TP
\fB\-query\fR \fIquery\fR
\fB\-query\fI query\fR
.
This flag (if the value is non-empty) causes \fB::http::geturl\fR to do a
This flag causes \fB::http::geturl\fR to do a POST request that passes the
\fIquery\fR to the server. The \fIquery\fR must be an x-url-encoding
formatted query.  The \fB::http::formatQuery\fR procedure can be used to
do the formatting.
POST request that passes the string
\fIquery\fR verbatim to the server as the request payload.
The content format (and encoding) of \fIquery\fR is announced by the request
header \fBContent-Type\fR which is set by the option \fB\-type\fR.  Any value
of \fB\-type\fR is permitted, and it is the responsibility of the caller to
supply \fIquery\fR in the correct format.
.RS
.PP
If \fB\-type\fR is not specified, it defaults to
\fIapplication/x-www-form-urlencoded\fR, which requires \fIquery\fR to be an
x-url-encoding formatted query-string (this \fB\-type\fR and query format are
used in a POST submitted from an html form).  The \fB::http::formatQuery\fR
procedure can be used to do the formatting.
.RE
.\" OPTION: -queryblocksize
.TP
\fB\-queryblocksize\fR \fIsize\fR
\fB\-queryblocksize\fI size\fR
.
The block size used when posting query data to the URL.
At most
\fIsize\fR
bytes are written at once.  After each block, a call to the
\fB\-queryprogress\fR
callback is made (if that option is specified).
.\" OPTION: -querychannel
.TP
\fB\-querychannel\fR \fIchannelID\fR
\fB\-querychannel\fI channelID\fR
.
This flag causes \fB::http::geturl\fR to do a POST request that passes the
data contained in \fIchannelID\fR to the server. The data contained in
\fIchannelID\fR must be an x-url-encoding
formatted query unless the \fB\-type\fR option below is used.
If a Content-Length header is not specified via the \fB\-headers\fR options,
\fB::http::geturl\fR attempts to determine the size of the post data
If a \fBContent-Length\fR header is not specified via the \fB\-headers\fR
options, \fB::http::geturl\fR attempts to determine the size of the post data
in order to create that header.  If it is
unable to determine the size, it returns an error.
.\" OPTION: -queryprogress
.TP
\fB\-queryprogress\fR \fIcallback\fR
\fB\-queryprogress\fI callback\fR
.
If the \fB\-queryprogress\fR option is present,
The \fIcallback\fR is made after each transfer of data to the URL
(i.e. POST) and acts exactly like the \fB\-progress\fR option (the
callback format is the same).
then the \fIcallback\fR is made after each transfer of data to the URL
in a POST request (i.e. a call to \fB::http::geturl\fR with
option \fB\-query\fR or \fB\-querychannel\fR) and acts exactly like
the \fB\-progress\fR option (the callback format is the same).
.\" OPTION: -strict
.TP
\fB\-strict\fR \fIboolean\fR
\fB\-strict\fI boolean\fR
.
If true then the command will test that the URL complies with RFC 3986, i.e.
that it has no characters that should be "x-url-encoded" (e.g. a space should
Whether to enforce RFC 3986 URL validation on the request.  Default is 1.
be encoded to "%20").  Default value is 1.
.\" OPTION: -timeout
.TP
\fB\-timeout\fR \fImilliseconds\fR
\fB\-timeout\fI milliseconds\fR
.
If \fImilliseconds\fR is non-zero, then \fB::http::geturl\fR sets up a timeout
to occur after the specified number of milliseconds.
A timeout results in a call to \fB::http::reset\fR and to
the \fB\-command\fR callback, if specified.
The return value of \fB::http::status\fR is \fBtimeout\fR
The return value of \fB::http::status\fR (and the value of the \fIstatus\fR key
in the dictionary returned by \fB::http::responseInfo\fR) is \fBtimeout\fR
after a timeout has occurred.
.\" OPTION: -type
.TP
\fB\-type\fR \fImime-type\fR
\fB\-type\fI mime-type\fR
.
Use \fImime-type\fR as the \fBContent-Type\fR value, instead of the
default value (\fBapplication/x-www-form-urlencoded\fR) during a
POST operation.
.\" OPTION: -validate
.TP
\fB\-validate\fR \fIboolean\fR
\fB\-validate\fI boolean\fR
.
If \fIboolean\fR is non-zero, then \fB::http::geturl\fR does an HTTP HEAD
request.  This request returns meta information about the URL, but the
contents are not returned.  The meta information is available in the
\fBstate(meta) \fR variable after the transaction.  See the
\fBSTATE ARRAY\fR section for details.
request.  This server returns the same status line and response headers as it
would for a HTTP GET request, but omits the response entity
(the URL "contents").  The response headers are available after the
transaction using command \fB::http::responseHeaders\fR or, for selected
information, \fB::http::responseInfo\fR.
.RE
.\" COMMAND: formatQuery
.TP
\fB::http::formatQuery\fR \fIkey value\fR ?\fIkey value\fR ...?
\fB::http::formatQuery\fI key value\fR ?\fIkey value\fR ...?
.
This procedure does x-url-encoding of query data.  It takes an even
number of arguments that are the keys and values of the query.  It
encodes the keys and values, and generates one string that has the
proper & and = separators.  The result is suitable for the
\fB\-query\fR value passed to \fB::http::geturl\fR.
.\" COMMAND: quoteString
.TP
\fB::http::quoteString\fR \fIvalue\fR
\fB::http::quoteString\fI value\fR
.
This procedure does x-url-encoding of string.  It takes a single argument and
encodes it.
.\" COMMAND: reset
.TP
\fB::http::reset\fR \fItoken\fR ?\fIwhy\fR?
\fB::http::reset\fI token\fR ?\fIwhy\fR?
.
This command resets the HTTP transaction identified by \fItoken\fR, if any.
This sets the \fBstate(status)\fR value to \fIwhy\fR, which defaults to
\fBreset\fR, and then calls the registered \fB\-command\fR callback.
.\" COMMAND: wait
.TP
\fB::http::wait\fR \fItoken\fR
\fB::http::wait\fI token\fR
.
This is a convenience procedure that blocks and waits for the
This command blocks and waits for the
transaction to complete.  This only works in trusted code because it
uses \fBvwait\fR.  Also, it is not useful for the case where
\fB::http::geturl\fR is called \fIwithout\fR the \fB\-command\fR option
because in this case the \fB::http::geturl\fR call does not return
until the HTTP transaction is complete, and thus there is nothing to
wait for.
.\" COMMAND: status
.TP
\fB::http::data\fR \fItoken\fR
\fB::http::status\fI token\fR
.
This is a convenience procedure that returns the \fBbody\fR element
(i.e., the URL data) of the state array.
.TP
\fB::http::error\fR \fItoken\fR
.
This command returns a description of the status of the HTTP transaction.
The return value is the empty string until the HTTP transaction is
completed; after completion it has one of the values ok, eof, error,
timeout, and reset.  The meaning of these values is described in the
section \fBERRORS\fR (below).
.PP
This is a convenience procedure that returns the \fBerror\fR element
of the state array.
.TP
\fB::http::status\fR \fItoken\fR
.
.RS
The name "status" is not related to the terms "status line" and
"status code" that are defined for a HTTP response.
.RE
This is a convenience procedure that returns the \fBstatus\fR element of
the state array.
.\" COMMAND: size
.TP
\fB::http::code\fR \fItoken\fR
\fB::http::size\fI token\fR
.
This is a convenience procedure that returns the \fBhttp\fR element of the
state array.
This command returns the number of bytes
received so far from the URL in the \fB::http::geturl\fR call.
.\" COMMAND: error
.TP
\fB::http::ncode\fR \fItoken\fR
\fB::http::error\fI token\fR
.
This is a convenience procedure that returns just the numeric return
code (200, 404, etc.) from the \fBhttp\fR element of the state array.
This command returns the error information if the HTTP transaction failed,
or the empty string if there was no error.  The information is a Tcl list of
the error message, stack trace, and error code.
.\" COMMAND: postError
.TP
\fB::http::size\fR \fItoken\fR
\fB::http::postError\fI token\fR
.
This is a convenience procedure that returns the \fBcurrentsize\fR
element of the state array, which represents the number of bytes
received from the URL in the \fB::http::geturl\fR call.
A POST request is a call to \fB::http::geturl\fR with either
.TP
\fB::http::meta\fR \fItoken\fR
the \fB\-query\fR or \fB\-querychannel\fR option.
The \fB::http::postError\fR command returns the error information generated
.
This is a convenience procedure that returns the \fBmeta\fR
element of the state array which contains the HTTP response
when a HTTP POST request sends its request-body to the server; or the empty
string if there was no error.  The information is a Tcl list of the error
message, stack trace, and error code.  When this type of error occurs,
the \fB::http::geturl\fR command continues the transaction and attempts to
receive a response from the server.
headers. See below for an explanation of this element.
.\" COMMAND: cleanup
.TP
\fB::http::cleanup\fR \fItoken\fR
\fB::http::cleanup\fI token\fR
.
This procedure cleans up the state associated with the connection
identified by \fItoken\fR.  After this call, the procedures
like \fB::http::data\fR cannot be used to get information
like \fB::http::responseBody\fR cannot be used to get information
about the operation.  It is \fIstrongly\fR recommended that you call
this function after you are done with a given HTTP request.  Not doing
so will result in memory not being freed, and if your app calls
\fB::http::geturl\fR enough times, the memory leak could cause a
performance hit...or worse.
.\" COMMAND: requestLine
.TP
\fB::http::requestLine\fI token\fR
.
This command returns the "request line" sent to the server.
The "request line" is the first line of a HTTP client request, and has three
elements separated by spaces: the HTTP method, the URL relative to the server,
and the HTTP version. Examples:
.PP
.RS
GET / HTTP/1.1
GET /introduction.html?subject=plumbing HTTP/1.1
POST /forms/order.html HTTP/1.1
.RE
.\" COMMAND: requestHeaders
.TP
\fB::http::requestHeaders\fI token\fR ?\fIheaderName\fR?
.
This command returns the HTTP request header names and values, in the
order that they were sent to the server, as a Tcl list of the form
?name value ...?  Header names are case-insensitive and are converted to lower
case.  The return value is not a \fBdict\fR because some header names may occur
more than once.  If one argument is supplied, all request headers
are returned.  If two arguments are supplied, the
second provides the value of a header name.  Only headers with the requested
name (converted to lower case) are returned.  If no such headers are found,
an empty list is returned.
.\" COMMAND: requestHeaderValue
.TP
\fB::http::requestHeaderValue\fI token headerName\fR
.
This command returns the value of the HTTP request header named
\fIheaderName\fR.  Header names are case-insensitive and are converted to
lower case.  If no such header exists, the return value is the empty string.
If there are multiple headers named \fIheaderName\fR, the result is obtained
by joining the individual values with the string ", " (comma and space),
preserving their order.
.\" COMMAND: responseLine
.TP
\fB::http::responseLine\fI token\fR
.
This command returns the first line of the server response: the
HTTP "status line".  The "status line" has three
elements separated by spaces: the HTTP version, a three-digit numerical
"status code", and a "reason phrase".  Only the reason phrase may contain
spaces.  Examples:
.PP
.RS
HTTP/1.1 200 OK
HTTP/1.0 404 Not Found
.RE
.RS
The "status code" is a three-digit number in the range 100 to 599.
A value of 200 is the normal return from a GET request, and its matching
"reason phrase" is "OK".  Codes beginning with 4 or 5 indicate errors.
Codes beginning with 3 are redirection errors.  In this case the
\fBLocation\fR response header specifies a new URL that contains the
requested information.
.PP
The "reason phrase" is a textual description of the "status code": it may
vary from server to server,
and can be changed without affecting the HTTP protocol.  The recommended
values (RFC 7231 and IANA assignments) for each code are provided by the
command \fB::http::reasonPhrase\fR.
.RE
.\" COMMAND: responseCode
.TP
\fB::http::responseCode\fI token\fR
.
This command returns the "status code" (200, 404, etc.) of the server
"status line".  If a three-digit code cannot be found, the full status
line is returned.  See command \fB::http::responseLine\fR for more information
on the "status line".
.\" COMMAND: reasonPhrase
.TP
\fB::http::reasonPhrase\fI code\fR
.
This command returns the IANA recommended "reason phrase" for a particular
"status code" returned by a HTTP server.  The argument \fIcode\fR is a valid
status code, and therefore is an integer in the range 100 to 599 inclusive.
For numbers in this range with no assigned meaning, the command returns the
value "Unassigned".  Several status codes are used only in response to the
methods defined by HTTP extensions such as WebDAV, and not in response to a
HEAD, GET, or POST request method.
.PP
.RS
The "reason phrase" returned by a HTTP server may differ from the recommended
value, without affecting the HTTP protocol.  The value returned by
\fB::http::geturl\fR can be obtained by calling either command
\fB::http::responseLine\fR (which returns the full status line) or command
\fB::http::responseInfo\fR (which returns a dictionary, with
the "reason phrase" stored in key \fIreasonPhrase\fR).
.PP
A registry of valid status codes is maintained at
https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
.RE
.\" COMMAND: responseHeaders
.TP
\fB::http::responseHeaders\fI token\fR ?\fIheaderName\fR?
.
The response from a HTTP server includes metadata headers that describe the
response body and the transaction itself.
This command returns the HTTP response header names and values, in the
order that they were received from the server, as a Tcl list of the form
?name value ...?  Header names are case-insensitive and are converted to lower
case.  The return value is not a \fBdict\fR because some header names may occur
more than once, notably \fBSet-Cookie\fR.  If the second argument is not
supplied, all response headers are returned.  If the second argument is
supplied, it provides the value of a header name.  Only headers with the
requested name (converted to lower case) are returned.  If no such headers
are found, an empty list is returned.  See section \fBMETADATA\fR for more
information.
.\" COMMAND: responseHeaderValue
.TP
\fB::http::responseHeaderValue\fI token headerName\fR
.
This command returns the value of the HTTP response header named
\fIheaderName\fR.  Header names are case-insensitive and are converted to
lower case.  If no such header exists, the return value is the empty string.
If there are multiple headers named \fIheaderName\fR, the result is obtained
by joining the individual values with the string ", " (comma and space),
preserving their order.  Multiple headers with the same name may be processed
in this manner, except \fBSet-Cookie\fR which does not conform to the
comma-separated-list syntax and cannot be combined into a single value.
Each \fBSet-Cookie\fR header must be treated individually, e.g. by processing
the return value of \fB::http::responseHeaders\fI token\fR \fBSet-Cookie\fR.
.\" COMMAND: responseInfo
.TP
\fB::http::responseInfo\fI token\fR
.
This command returns a \fBdict\fR of selected response metadata that are
essential for identifying a successful transaction and making use of the
response, along with other metadata that are informational.  The keys of
the \fBdict\fR are \fIstage\fR, \fIstatus\fR, \fIresponseCode\fR,
\fIreasonPhrase\fR, \fIcontentType\fR, \fIbinary\fR, \fIredirection\fR,
\fIupgrade\fR, \fIerror\fR, \fIpostError\fR, \fImethod\fR, \fIcharset\fR,
\fIcompression\fR, \fIhttpRequest\fR, \fIhttpResponse\fR, \fIurl\fR,
\fIconnectionRequest\fR, \fIconnectionResponse\fR, \fIconnectionActual\fR,
\fItransferEncoding\fR, \fItotalPost\fR, \fIcurrentPost\fR, \fItotalSize\fR,
and \fIcurrentSize\fR.  The meaning of these keys is described in the
section \fBMETADATA\fR below.
.RS
.PP
It is always worth checking the value of \fIbinary\fR after a HTTP transaction,
to determine whether a misconfigured server has caused http to interpret a
text resource as a binary, or vice versa.
.PP
After a POST transaction, check the value of \fIpostError\fR to verify that
the request body was uploaded without error.
.RE
.\" COMMAND: responseBody
.TP
\fB::http::responseBody\fI token\fR
.
This command returns the entity sent by the HTTP server (unless
\fI-channel\fR was used, in which case the entity was delivered to the
channel, and the command returns the empty string).
.RS
.PP
Other terms for
"entity", with varying precision, include "representation of resource",
"resource", "response body after decoding", "payload",
"message body after decoding", "content(s)", and "file".
.RE
.\" COMMAND: register
.TP
\fB::http::register\fR \fIproto port command\fR
\fB::http::register\fI proto port command\fR ?\fIsocketCmdVarName\fR? ?\fIuseSockThread\fR? ?\fIendToEndProxy\fR?
.
This procedure allows one to provide custom HTTP transport types
such as HTTPS, by registering a prefix, the default port, and the
command to execute to create the Tcl \fBchannel\fR. E.g.:
command to execute to create the Tcl \fBchannel\fR. The optional
arguments configure how \fBhttp\fR uses the custom transport, and have
default values that are compatible with older versions of \fBhttp\fR
in which \fB::http::register\fR has no optional arguments.
.RS
.PP
Argument \fIsocketCmdVarName\fR is the name of a variable provided by
the transport, whose value is the command used by the transport to open
a socket.  Its default value is set by the transport and is "::socket",
but if the name of the variable is supplied to \fB::http::register\fR,
then \fBhttp\fR will set a new value in order to make optional
facilities available.  These facilities are enabled by the optional
arguments \fIuseSockThread\fR, \fIendToEndProxy\fR, which take boolean
values with default value \fIfalse\fR.
.PP
Iff argument \fIuseSockThread\fR is supplied and is boolean \fItrue\fR,
then iff permitted by the value [\fBhttp::config\fI \-threadlevel\fR]
and by the availability of package \fBThread\fR, sockets created for
the transport will be opened in a different thread so that a slow DNS
lookup will not cause the script to block.
.PP
Iff argument \fIendToEndProxy\fR is supplied and is boolean \fItrue\fR,
then when \fBhttp::geturl\fR accesses a server via a proxy, it will
open a channel by sending a CONNECT request to the proxy, and it will
then make its request over this channel.  This allows end-to-end
encryption for HTTPS requests made through a proxy.
.PP
For example,
.RS
.PP
.CS
package require http
package require tls

::http::register https 443 ::tls::socket
::http::register https 443 ::tls::socket ::tls::socketCmd 1 1

set token [::http::geturl https://my.secure.site/]
.CE
.RE
.RE
.\" COMMAND: registerError
.TP
\fB::http::registerError\fR \fIport\fR ?\fImessage\fR?
\fB::http::registerError\fI sock\fR ?\fImessage\fR?
.
This procedure allows a registered protocol handler to deliver an error
message for use by \fBhttp\fR.  Calling this command does not raise an
error. The command is useful when a registered protocol detects an problem
(for example, an invalid TLS certificate) that will cause an error to
propagate to \fBhttp\fR.  The command allows \fBhttp\fR to provide a
precise error message rather than a general one.  The command returns the
value provided by the last call with argument \fImessage\fR, or the empty
string if no such call has been made.
.\" COMMAND: unregister
.TP
\fB::http::unregister\fR \fIproto\fR
\fB::http::unregister\fI proto\fR
.
This procedure unregisters a protocol handler that was previously
registered via \fB::http::register\fR, returning a two-item list of
registered via \fB::http::register\fR, returning a six-item list of
the default port and handler command that was previously installed
(via \fB::http::register\fR) if there was such a handler, and an error if
there was no such handler.
the values that were previously supplied to \fB::http::register\fR
if there was such a handler, and an error if there was no such handler.
.\" COMMAND: code
.TP
\fB::http::code\fI token\fR
.
An alternative name for the command \fB::http::responseLine\fR
.\" COMMAND: data
.TP
\fB::http::data\fI token\fR
.
An alternative name for the command \fB::http::responseBody\fR.
.\" COMMAND: meta
.TP
\fB::http::meta\fI token\fR ?\fIheaderName\fR?
.
An alternative name for the command \fB::http::responseHeaders\fR
.\" COMMAND: ncode
.TP
\fB::http::ncode\fI token\fR
.
An alternative name for the command \fB::http::responseCode\fR
.SH ERRORS
The \fB::http::geturl\fR procedure will raise errors in the following cases:
invalid command line options,
an invalid URL,
or an invalid URL.
a URL on a non-existent host,
or a URL at a bad port on an existing host.
These errors mean that it
cannot even start the network transaction.
It will also raise an error if it gets an I/O error while
writing out the HTTP request header.
For synchronous \fB::http::geturl\fR calls (where \fB\-command\fR is
not specified), it will raise an error if it gets an I/O error while
not specified), it will raise an error if
the URL is on a non-existent host
or at a bad port on an existing host.
It will also raise an error for any I/O errors while
writing out the HTTP request line and headers, or
reading the HTTP reply headers or data.  Because \fB::http::geturl\fR
does not return a token in these cases, it does all the required
cleanup and there is no issue of your app having to call
\fB::http::cleanup\fR.
.PP
For asynchronous \fB::http::geturl\fR calls, all of the above error
situations apply, except that if there is any error while reading the
HTTP reply headers or data, no exception is thrown.  This is because
after writing the HTTP headers, \fB::http::geturl\fR returns, and the
rest of the HTTP transaction occurs in the background.  The command
callback can check if any error occurred during the read by calling
\fB::http::status\fR to check the status and if its \fIerror\fR,
\fB::http::responseInfo\fR to check the transaction status.
calling \fB::http::error\fR to get the error message.
.PP
Alternatively, if the main program flow reaches a point where it needs
to know the result of the asynchronous HTTP request, it can call
\fB::http::wait\fR and then check status and error, just as the
synchronous call does.
.PP
The \fB::http::geturl\fR command runs the \fB\-command\fR, \fB\-handler\fR,
and \fB\-proxyfilter\fR callbacks inside a \fBcatch\fR command.  Therefore
an error in the callback command does not call the \fBbgerror\fR handler.
When debugging one of these
callback does.
callbacks, it may be convenient to report errors by using a
\fBcatch\fR command within the callback command itself, e.g. to write
an error message to stdout.
.PP
In any case, you must still call
\fB::http::cleanup\fR to delete the state array when you are done.
.PP
There are other possible results of the HTTP transaction
determined by examining the status from \fB::http::status\fR.
determined by examining the status from \fB::http::status\fR (or the value
of the \fIstatus\fR key in the dictionary returned
by \fB::http::responseInfo\fR).
These are described below.
.TP
\fBok\fR
.IP \fBok\fR
.
If the HTTP transaction completes entirely, then status will be \fBok\fR.
However, you should still check the \fB::http::code\fR value to get
the HTTP status.  The \fB::http::ncode\fR procedure provides just
the numeric error (e.g., 200, 404 or 500) while the \fB::http::code\fR
However, you should still check the \fB::http::responseLine\fR value to get
the HTTP status.  The \fB::http::responseCode\fR procedure provides just
the numeric error (e.g., 200, 404 or 500) while the \fB::http::responseLine\fR
procedure returns a value like
.QW "HTTP 404 File not found" .
.TP
\fBeof\fR
.IP \fBeof\fR
.
If the server closes the socket without replying, then no error
is raised, but the status of the transaction will be \fBeof\fR.
.IP \fBerror\fR
The error message, stack trace, and error code are accessible
via \fB::http::error\fR.  The error message is also provided by the value of
the \fIerror\fR key in the dictionary returned by \fB::http::responseInfo\fR.
.IP \fBtimeout\fR
A timeout occurred before the transaction could complete.
.IP \fBreset\fR
The user has called \fB::http::reset\fR.
.IP \fB""\fR
(empty string) The transaction has not yet finished.
.TP
\fBerror\fR
.
The error message will also be stored in the \fBerror\fR status
array element, accessible via \fB::http::error\fR.
.PP
Another error possibility is that \fB::http::geturl\fR failed to
write the whole of the POST request body (\fB\-query\fR or \fB\-querychannel\fR
data) to the server.  \fB::http::geturl\fR stores the error message for later
retrieval by the \fB::http::postError\fR or \fB::http::responseInfo\fR
commands, and then attempts to complete the transaction.
If it can read the server's response the status will be \fBok\fR, but it is
important to call \fB::http::postError\fR or \fB::http::responseInfo\fR after
every POST to check that the data was sent in full.
If the server has closed the connection the status will be \fBeof\fR.
.SH "METADATA"
.PP
.SS "MOST USEFUL METADATA"
When a HTTP server responds to a request, it supplies not only the entity
requested, but also metadata.  This is provided by the first line (the
"status line") of the response, and by a number of HTTP headers.  Further
metadata relates to how \fB::http::geturl\fR has processed the response
from the server.
.PP
The most important metadata can be accessed with the command
\fB::http::responseInfo\fR.
This command returns a \fBdict\fR of metadata that are essential for
identifying a successful transaction and making use of the response,
along with other metadata that are informational.  The keys of
the \fBdict\fR are:
.PP
.RS
.RS
.\" TODO: Find a better way to mark this up!
\fB===== Essential Values =====\fR
.RE
.RE
.IP \fBstage\fR
This value, set by \fB::http::geturl\fR, describes the stage that the
transaction has reached. Values, in order of the transaction lifecycle,
are: "created", "connecting", "header", "body", and "complete".  The
other \fBdict\fR keys will not be available until the value of \fBstage\fR
is "body" or "complete".  The key \fBcurrentSize\fR has its final value only
when \fBstage\fR is "complete".
.IP \fBstatus\fR
This value, set by \fB::http::geturl\fR, is "ok" for a successful transaction;
"eof", "error", "timeout", or "reset" for an unsuccessful transaction; or ""
if the transaction is still in progress.  The value is the same as that
returned by command \fB::http::status\fR. The meaning of these values is
described in the section \fBERRORS\fR (above).
.IP \fBresponseCode\fR
The "HTTP status code" sent by the server in the first line (the "status line")
of the response.  If the value cannot be extracted from the status line, the
full status line is returned.
.IP \fBreasonPhrase\fR
The "reason phrase" sent by the server as a description of the HTTP status code.
If the value cannot be extracted from the status line, the full status
line is returned.
.IP \fBcontentType\fR
The value of the \fBContent-Type\fR response header or, if the header was not
supplied, the default value "application/octet-stream".
.IP \fBbinary\fR
This boolean value, set by \fB::http::geturl\fR, describes how the command
has interpreted the entity returned by the server (after decoding any
compression specified by the \fBContent-Encoding\fR response header).
This decoded entity is accessible as the return value of the
command \fB::http::responseBody\fR.
.PP
.RS
The value is \fBtrue\fR if http has interpreted the decoded entity as binary.
The value returned by \fB::http::responseBody\fR is a Tcl binary string.
This is a suitable format for image data, zip files, etc.
\fB::http::geturl\fR chooses this value if the user has requested a binary
interpretation by passing the option \fB\-binary\fR to the command, or if the
server has supplied a binary content type in a \fBContent-Type\fR response
header, or if the server has not supplied any \fBContent-Type\fR header.
.PP
The value is \fBfalse\fR in other cases, and this means that http has
interpreted the decoded entity as text. The text has been converted, from the
character set notified by the server, into Tcl's internal Unicode format;
the value returned by \fB::http::responseBody\fR is an ordinary Tcl string.
.PP
It is always worth checking the value of "binary" after a HTTP transaction,
to determine whether a misconfigured server has caused http to interpret a
text resource as a binary, or vice versa.
.RE
.IP \fBredirection\fR
The URL that is the redirection target. The value is that of the \fBLocation\fR
response header.  This header is sent when a response has status code
3XX (redirection).
.IP \fBupgrade\fR
If not empty, the value indicates the protocol(s) to which the server will
switch after completion of this transaction, while continuing to use the
same connection.  When the server intends to switch protocols, it will also
send the value "101" as the status code (the \fBresponseCode\fR key), and the
word "upgrade" as an element of the \fBConnection\fR response header (the
\fBconnectionResponse\fR key), and it will not send a response body.
See the section \fBPROTOCOL UPGRADES\fR for more information.
.IP \fBerror\fR
The error message, if there is one.  Further information, including a stack
trace and error code, are available from command \fB::http::error\fR.
.IP \fBpostError\fR
The error message (if any) generated when a HTTP POST request sends its
request-body to the server.  Further information, including a stack trace
and error code, are available from command \fB::http::postError\fR.  A POST
transaction may appear complete, according to the
keys \fBstage\fR, \fBstatus\fR, and \fBresponseCode\fR, but it is important
to check this \fBpostError\fR key in case an error occurred when uploading
the request-body.
.PP
.RS
.RS
\fB===== Informational Values =====\fR
.RE
.RE
.IP \fBmethod\fR
The HTTP method used in the request.
.IP \fBcharset\fR
The value of the charset attribute of the \fBContent-Type\fR response header.
The charset value is used only for a text resource.  If the server did not
specify a charset, the value defaults to that of the
variable \fB::http::defaultCharset\fR, which unless it has been deliberately
modified by the caller is \fBiso8859-1\fR.  Incoming text data is automatically
converted from the character set defined by \fBcharset\fR to Tcl's internal
Unicode representation, i.e. to a Tcl string.
.IP \fBcompression\fR
A copy of the \fBContent-Encoding\fR response-header value.
.IP \fBhttpRequest\fR
The version of HTTP specified in the request (i.e. sent in the request line).
The value is that of the option \fB\-protocol\fR supplied
to \fB::http::geturl\fR (default value "1.1"), unless the command reduced the
value to "1.0" because it was passed the \fB\-handler\fR option.
.IP \fBhttpResponse\fR
The version of HTTP used by the server (obtained from the response
"status line").  The server uses this version of HTTP in its response, but
ensures that this response is compatible with the HTTP version specified in the
client's request.  If the value cannot be extracted from the status line, the
full status line is returned.
.IP \fBurl\fR
The requested URL, typically the URL supplied as an argument
to \fB::http::geturl\fR but without its "fragment" (the final part of the URL
beginning with "#").
.IP \fBconnectionRequest\fR
The value, if any, sent to the server in \fBConnection\fR request header(s).
.IP \fBconnectionResponse\fR
The value, if any, received from the server in \fBConnection\fR response
header(s).
.IP \fBconnectionActual\fR
This value, set by \fB::http::geturl\fR, reports whether the connection was
closed after the transaction (value "close"), or left open (value "keep-alive").
.IP \fBtransferEncoding\fR
The value of the Transfer-Encoding response header, if it is present.
The value is either "chunked" (indicating HTTP/1.1 "chunked encoding") or
the empty string.
.IP \fBtotalPost\fR
The total length of the request body in a POST request.
.IP \fBcurrentPost\fR
The number of bytes of the POST request body sent to the server so far.
The value is the same as that returned by command \fB::http::size\fR.
.IP \fBtotalSize\fR
A copy of the \fBContent-Length\fR response-header value.
The number of bytes specified in a \fBContent-Length\fR header, if one
was sent.  If none was sent, the value is 0.  A correctly configured server
omits this header if the transfer-encoding is "chunked", or (for older
servers) if the server closes the connection when it reaches the end of
the resource.
.IP \fBcurrentSize\fR
The number of bytes fetched from the server so far.
.PP
.SS "MORE METADATA"
The dictionary returned by \fB::http::responseInfo\fR is the most useful
subset of the available metadata.  Other metadata include:
.PP
1. The full "status line" of the response, available as the return value
of command \fB::http::responseLine\fR.
.PP
2. The full response headers, available as the return value of
command \fB::http::responseHeaders\fR.  This return value is a list of the
response-header names and values, in the order that they were received from
the server.
.PP
The return value is not a \fBdict\fR because some header names may
occur more than once, notably \fBSet-Cookie\fR. If the value is read
into a \fBdict\fR or into an array (using array set), only the last header
with each name will be preserved.
.PP
.RS
Some of the header names (metadata keys) are listed below, but the HTTP
standard defines several more, and servers are free to add their own.
When a dictionary key is mentioned below, this refers to the \fBdict\fR
value returned by command \fB::http::responseInfo\fR.
.IP \fBContent-Type\fR
The content type of the URL contents.  Examples include \fBtext/html\fR,
\fBimage/gif,\fR \fBapplication/postscript\fR and
\fBapplication/x-tcl\fR.  Text values typically specify a character set, e.g.
\fBtext/html; charset=UTF-8\fR.  Dictionary key \fIcontentType\fR.
.IP \fBContent-Length\fR
The advertised size in bytes of the contents, available as dictionary
key \fItotalSize\fR.  The actual number of bytes read by \fB::http::geturl\fR
so far is available as dictionary key \fBcurrentSize\fR.
.IP \fBContent-Encoding\fR
The compression algorithm used for the contents.
Examples include \fBgzip\fR, \fBdeflate\fR.
Dictionary key \fIcontent\fR.
.IP \fBLocation\fR
This header is sent when a response has status code 3XX (redirection).
It provides the URL that is the redirection target.
Dictionary key \fIredirection\fR.
.IP \fBSet-Cookie\fR
This header is sent to offer a cookie to the client.  Cookie management is
done by the \fB::http::config\fR option \fB\-cookiejar\fR, and so
the \fBSet-Cookie\fR headers need not be parsed by user scripts.
See section \fBCOOKIE JAR PROTOCOL\fR.
.IP \fBConnection\fR
The value can be supplied as a comma-separated list, or by multiple headers.
The list often has only one element, either "close" or "keep-alive".
The value "upgrade" indicates a successful upgrade request and is typically
combined with the status code 101, an \fBUpgrade\fR response header, and no
response body.  Dictionary key \fIconnectionResponse\fR.
.IP \fBUpgrade\fR
The value indicates the protocol(s) to which the server will switch
immediately after the empty line that terminates the 101 response headers.
Dictionary key \fIupgrade\fR.
.RE
.PP
.SS "EVEN MORE METADATA"
.IP 1.
Details of the HTTP request.  The request is determined by the options
Another error possibility is that \fB::http::geturl\fR is unable to
supplied to \fB::http::geturl\fR and \fB::http::config\fR.  However, it is
write all the post query data to the server before the server
responds and closes the socket.
sometimes helpful to examine what \fB::http::geturl\fR actually sent to the
server, and this information is available through
The error message is saved in the \fBposterror\fR status array
element and then  \fB::http::geturl\fR attempts to complete the
transaction.
commands \fB::http::requestHeaders\fR and \fB::http::requestLine\fR.
.IP 2.
The state array: the internal variables of \fB::http::geturl\fR.
It may sometimes be helpful to examine this array.
Details are given in the next section.
If it can read the server's response
it will end up with an \fBok\fR status, otherwise it will have
an \fBeof\fR status.
.SH "STATE ARRAY"
The \fB::http::geturl\fR procedure returns a \fItoken\fR that can be used to
get to the state of the HTTP transaction in the form of a Tcl array.
Use this construct to create an easy-to-use array variable:
The \fB::http::geturl\fR procedure returns a \fItoken\fR that can be used
as an argument to other \fB::http::*\fR commands, which examine and manage
the state of the HTTP transaction.  For most purposes these commands are
sufficient.  The \fItoken\fR can also be used to access
the internal state of the transaction, which is stored in a Tcl array.
This facility is most useful when writing callback commands for the
options \fB\-command\fR, \fB\-handler\fR, \fB\-progress\fR,
or \fB\-queryprogress\fR.
Use the following command inside the proc to define an easy-to-use
array \fIstate\fR as a local variable within the proc
.PP
.CS
upvar #0 $token state
upvar 0 $token state
.CE
.PP
Once the data associated with the URL is no longer needed, the state
array should be unset to free up storage.
The \fB::http::cleanup\fR procedure is provided for that purpose.
.PP
The following elements of
The following elements of the array are supported, and are the origin of the
the array are supported:
.RS
.TP
\fBbinary\fR
.
This is boolean \fBtrue\fR if (after decoding any compression specified
by the
.QW "Content-Encoding"
response header) the HTTP response is binary.  It is boolean \fBfalse\fR
if the HTTP response is text.
.TP
\fBbody\fR
.
The contents of the URL.  This will be empty if the \fB\-channel\fR
option has been specified.  This value is returned by the \fB::http::data\fR command.
values returned by commands as described below.  When a dictionary key is
.TP
\fBcharset\fR
.
The value of the charset attribute from the \fBContent-Type\fR meta-data
value.  If none was specified, this defaults to the RFC standard
\fBiso8859-1\fR, or the value of \fB$::http::defaultCharset\fR.  Incoming
mentioned below, this refers to the \fBdict\fR value returned by
command \fB::http::responseInfo\fR.
text data will be automatically converted from this charset to utf-8.
.TP
\fBcoding\fR
.
A copy of the \fBContent-Encoding\fR meta-data value.
.TP
\fBcurrentsize\fR
.RS
.IP \fBbinary\fR
For dictionary key \fIbinary\fR.
.IP \fBbody\fR
For command \fB::http::responseBody\fR.
.IP \fBcharset\fR
For dictionary key \fIcharset\fR.
.IP \fBcoding\fR
For dictionary key \fIcompression\fR.
.IP \fBconnection\fR
For dictionary key \fIconnectionActual\fR.
.IP \fBcurrentsize\fR
.
The current number of bytes fetched from the URL.
This value is returned by the \fB::http::size\fR command.
For command \fB::http::size\fR; and for dictionary key \fIcurrentSize\fR.
.TP
\fBerror\fR
.IP \fBerror\fR
.
If defined, this is the error string seen when the HTTP transaction
was aborted.
.TP
\fBhttp\fR
For command \fB::http::error\fR; part is used in dictionary key \fIerror\fR.
.IP \fBhttp\fR
.
The HTTP status reply from the server.  This value
is returned by the \fB::http::code\fR command.  The format of this value is:
For command \fB::http::responseLine\fR.
.RS
.PP
.CS
\fIHTTP/1.1 code string\fR
.CE
.PP
.IP \fBhttpResponse\fR
For dictionary key \fIhttpResponse\fR.
.IP \fBmeta\fR
For command \fB::http::responseHeaders\fR. Further discussion above in the
The \fIcode\fR is a three-digit number defined in the HTTP standard.
A code of 200 is OK.  Codes beginning with 4 or 5 indicate errors.
Codes beginning with 3 are redirection errors.  In this case the
section \fBMORE METADATA\fR.
\fBLocation\fR meta-data specifies a new URL that contains the
requested information.
.IP \fBmethod\fR
For dictionary key \fImethod\fR.
.RE
.TP
\fBmeta\fR
.
The HTTP protocol returns meta-data that describes the URL contents.
.IP \fBposterror\fR
For dictionary key \fIpostError\fR.
.IP \fBpostErrorFull\fR
For command \fB::http::postError\fR.
.IP \fB\-protocol\fR
The \fBmeta\fR element of the state array is a list of the keys and
values of the meta-data.  This is in a format useful for initializing
an array that just contains the meta-data:
.RS
For dictionary key \fIhttpRequest\fR.
.IP \fBquerylength\fR
For dictionary key \fItotalPost\fR.
.PP
.CS
array set meta $state(meta)
.IP \fBqueryoffset\fR
.CE
.PP
Some of the meta-data keys are listed below, but the HTTP standard defines
more, and servers are free to add their own.
.TP
\fBContent-Type\fR
For dictionary key \fIcurrentPost\fR.
.
The type of the URL contents.  Examples include \fBtext/html\fR,
\fBimage/gif,\fR \fBapplication/postscript\fR and
\fBapplication/x-tcl\fR.
.IP \fBreasonPhrase\fR
For dictionary key \fIreasonPhrase\fR.
.TP
\fBContent-Length\fR
.IP \fBrequestHeaders\fR
For command \fB::http::requestHeaders\fR.
.IP \fBrequestLine\fR
.
The advertised size of the contents.  The actual size obtained by
\fB::http::geturl\fR is available as \fBstate(currentsize)\fR.
For command \fB::http::requestLine\fR.
.TP
\fBLocation\fR
.IP \fBresponseCode\fR
For dictionary key \fIresponseCode\fR.
.IP \fBstate\fR
.
An alternate URL that contains the requested data.
.RE
.TP
\fBposterror\fR
For dictionary key \fIstage\fR.
.
The error, if any, that occurred while writing
the post query data to the server.
.TP
\fBstatus\fR
.IP \fBstatus\fR
.
Either \fBok\fR, for successful completion, \fBreset\fR for
user-reset, \fBtimeout\fR if a timeout occurred before the transaction
could complete, or \fBerror\fR for an error condition.  During the
transaction this value is the empty string.
.TP
\fBtotalsize\fR
For command \fB::http::status\fR; and for dictionary key \fIstatus\fR.
.IP \fBtotalsize\fR
.
A copy of the \fBContent-Length\fR meta-data value.
For dictionary key \fItotalSize\fR.
.IP \fBtransfer\fR
.TP
\fBtype\fR
For dictionary key \fItransferEncoding\fR.
.IP \fBtype\fR
.
A copy of the \fBContent-Type\fR meta-data value.
.TP
\fBurl\fR
For dictionary key \fIcontentType\fR.
.IP \fBupgrade\fR
For dictionary key \fIupgrade\fR.
.IP \fBurl\fR
.
The requested URL.
For dictionary key \fIurl\fR.
.RE
.SH "PERSISTENT CONNECTIONS"
.PP
.SS "BASICS"
.PP
See RFC 7230 Sec 6, which supersedes RFC 2616 Sec 8.1.
.PP
A persistent connection allows multiple HTTP/1.1 transactions to be
carried over the same TCP connection.  Pipelining allows a
client to make multiple requests over a persistent connection without
waiting for each response.  The server sends responses in the same order
that the requests were received.
.PP
If a POST request fails to complete, typically user confirmation is
needed before sending the request again.  The user may wish to verify
whether the server was modified by the failed POST request, before
sending the same request again.
.PP
A HTTP request will use a persistent socket if the call to
\fBhttp::geturl\fR has the option \fB-keepalive true\fR. It will use
\fBhttp::geturl\fR has the option \fB\-keepalive true\fR. It will use
pipelining where permitted if the \fBhttp::config\fR option
\fB-pipeline\fR is boolean \fBtrue\fR (its default value).
\fB\-pipeline\fR is boolean \fBtrue\fR (its default value).
.PP
The http package maintains no more than one persistent connection to each
server (i.e. each value of
.QW "domain:port" ).
If \fBhttp::geturl\fR is called to make a request over a persistent
connection while the connection is busy with another request, the new
request will be held in a queue until the connection is free.
721
722
723
724
725
726
727
728
729


730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749

750
751
752
753
754
755
756
757

758
759
760
761
762
763
764


765
766

767
768


769
770
771
772
773
774
775



776
777

778
779
780
781
782

783
784
785


786
787
788
789
790
791
792
793

794
795
796
797
798
799
800
801
802
803
804

805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820

821
822
823
824
825
826
827
828
829
830

831
832
833
834
835
836
837
838

839
840
841
842
843
844
845
846
847

848
849
850
851
852

853
854
855
856
857

858
859
860
861
862
863

864
865
866
867
868
869

870
871
872
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
898
899
900
901
902
903

904
905
906
907
908
909
910
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
1354
1355

1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392

1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430


1431

1432
1433
1434
1435
1436


1437

1438
1439
1440
1441
1442
1443


1444

1445
1446


1447

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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554

1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566

1567
1568
1569
1570
1571
1572
1573
1574







-
-
+
+



















-
+







-
+





-
-
+
+

-
+
-
-
+
+





-
-
+
+
+

-
+




-
+

-
-
+
+







-
+











+
















+








-
-
+
-





-
-
+
-






-
-
+
-


-
-
+
-


-
-
+
-



-
-
+
-



-
-
+
-


-
-
+
-


-
-
+
-







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+











-
+







the special treatment necessary for POST requests, and the options for
dealing with these cases.
.PP
In accordance with RFC 7230, \fBhttp::geturl\fR does not pipeline
requests that use the POST method.  If a POST uses a persistent
connection and is not the first request on that connection,
\fBhttp::geturl\fR waits until it has received the response for the previous
request; or (if \fBhttp::config\fR option \fB-postfresh\fR is boolean \fBtrue\fR) it
uses a new connection for each POST.
request; or (if \fBhttp::config\fR option \fB\-postfresh\fR is boolean
\fBtrue\fR) it uses a new connection for each POST.
.PP
If the server is processing a number of pipelined requests, and sends a
response header
.QW "\fBConnection: close\fR"
with one of the responses (other than the last), then subsequent responses
are unfulfilled. \fBhttp::geturl\fR will send the unfulfilled requests again
over a new connection.
.PP
A difficulty arises when a HTTP client sends a request over a persistent
connection that has been idle for a while.  The HTTP server may
half-close an apparently idle connection while the client is sending a
request, but before the request arrives at the server: in this case (an
.QW "asynchronous close event" )
the request will fail.  The difficulty arises because the client cannot
be certain whether the POST modified the state of the server.  For HEAD or
GET requests, \fBhttp::geturl\fR opens another connection and retransmits
the failed request. However, if the request was a POST, RFC 7230 forbids
automatic retry by default, suggesting either user confirmation, or
confirmation by user-agent software that has semantic understanding of
the application.  The \fBhttp::config\fR option \fB-repost\fR allows for
the application.  The \fBhttp::config\fR option \fB\-repost\fR allows for
either possibility.
.PP
Asynchronous close events can occur only in a short interval of time.  The
\fBhttp\fR package monitors each persistent connection for closure by the
server.  Upon detection, the connection is also closed at the client end,
and subsequent requests will use a fresh connection.
.PP
If the \fBhttp::geturl\fR command is called with option \fB-keepalive true\fR,
If the \fBhttp::geturl\fR command is called with option \fB\-keepalive true\fR,
then it will both try to use an existing persistent connection
(if one is available), and it will send the server a
.QW "\fBConnection: keep-alive\fR"
request header asking to keep the connection open for future requests.
.PP
The \fBhttp::config\fR options \fB-pipeline\fR, \fB-postfresh\fR, and
\fB-repost\fR relate to persistent connections.
The \fBhttp::config\fR options \fB\-pipeline\fR, \fB\-postfresh\fR, and
\fB\-repost\fR relate to persistent connections.
.PP
Option \fB-pipeline\fR, if boolean \fBtrue\fR, will pipeline GET and HEAD requests
Option \fB\-pipeline\fR, if boolean \fBtrue\fR, will pipeline GET and HEAD
made
over a persistent connection.  POST requests will not be pipelined - if the
requests made over a persistent connection.  POST requests will not be
pipelined - if the
POST is not the first transaction on the connection, its request will not
be sent until the previous response has finished.  GET and HEAD requests
made after a POST will not be sent until the POST response has been
delivered, and will not be sent if the POST fails.
.PP
Option \fB-postfresh\fR, if boolean \fBtrue\fR, will override the \fBhttp::geturl\fR option
\fB-keepalive\fR, and always open a fresh connection for a POST request.
Option \fB\-postfresh\fR, if boolean \fBtrue\fR, will override the
\fBhttp::geturl\fR option \fB\-keepalive\fR, and always open a fresh connection
for a POST request.
.PP
Option \fB-repost\fR, if \fBtrue\fR, permits automatic retry of a POST request
Option \fB\-repost\fR, if \fBtrue\fR, permits automatic retry of a POST request
that fails because it uses a persistent connection that the server has
half-closed (an
.QW "asynchronous close event" ).
Subsequent GET and HEAD requests in a failed pipeline will also be retried.
\fIThe -repost option should be used only if the application understands
\fIThe \fB\-repost\fI option should be used only if the application understands
that the retry is appropriate\fR - specifically, the application must know
that if the failed POST successfully modified the state of the server, a repeat POST
would have no adverse effect.
that if the failed POST successfully modified the state of the server, a repeat
POST would have no adverse effect.
.VS TIP406
.SH "COOKIE JAR PROTOCOL"
.PP
Cookies are short key-value pairs used to implement sessions within the
otherwise-stateless HTTP protocol. (See RFC 6265 for details; Tcl does not
implement the Cookie2 protocol as that is rarely seen in the wild.)
.PP
Cookie storage managment commands \(em
Cookie storage management commands \(em
.QW "cookie jars"
\(em must support these subcommands which form the HTTP cookie storage
management protocol. Note that \fIcookieJar\fR below does not have to be a
command name; it is properly a command prefix (a Tcl list of words that will
be expanded in place) and admits many possible implementations.
.PP
Though not formally part of the protocol, it is expected that particular
values of \fIcookieJar\fR will correspond to sessions; it is up to the caller
of \fB::http::config\fR to decide what session applies and to manage the
deletion of said sessions when they are no longer desired (which should be
when they not configured as the current cookie jar).
.\" METHOD: getCookies
.TP
\fIcookieJar \fBgetCookies \fIprotocol host requestPath\fR
.
This command asks the cookie jar what cookies should be supplied for a
particular request. It should take the \fIprotocol\fR (typically \fBhttp\fR or
\fBhttps\fR), \fIhost\fR name and \fIrequestPath\fR (parsed from the \fIurl\fR
argument to \fB::http::geturl\fR) and return a list of cookie keys and values
that describe the cookies to supply to the remote host. The list must have an
even number of elements.
.RS
.PP
There should only ever be at most one cookie with a particular key for any
request (typically the one with the most specific \fIhost\fR/domain match and
most specific \fIrequestPath\fR/path match), but there may be many cookies
with different names in any request.
.RE
.\" METHOD: storeCookie
.TP
\fIcookieJar \fBstoreCookie \fIcookieDictionary\fR
.
This command asks the cookie jar to store a particular cookie that was
returned by a request; the result of this command is ignored. The cookie
(which will have been parsed by the http package) is described by a
dictionary, \fIcookieDictionary\fR, that may have the following keys:
.RS
.TP
\fBdomain\fR
.IP \fBdomain\fR
.
This is always present. Its value describes the domain hostname \fIor
prefix\fR that the cookie should be returned for.  The checking of the domain
against the origin (below) should be careful since sites that issue cookies
should only do so for domains related to themselves. Cookies that do not obey
a relevant origin matching rule should be ignored.
.TP
\fBexpires\fR
.IP \fBexpires\fR
.
This is optional. If present, the cookie is intended to be a persistent cookie
and the value of the option is the Tcl timestamp (in seconds from the same
base as \fBclock seconds\fR) of when the cookie expires (which may be in the
past, which should result in the cookie being deleted immediately). If absent,
the cookie is intended to be a session cookie that should be not persisted
beyond the lifetime of the cookie jar.
.TP
\fBhostonly\fR
.IP \fBhostonly\fR
.
This is always present. Its value is a boolean that describes whether the
cookie is a single host cookie (true) or a domain-level cookie (false).
.TP
\fBhttponly\fR
.IP \fBhttponly\fR
.
This is always present. Its value is a boolean that is true when the site
wishes the cookie to only ever be used with HTTP (or HTTPS) traffic.
.TP
\fBkey\fR
.IP \fBkey\fR
.
This is always present. Its value is the \fIkey\fR of the cookie, which is
part of the information that must be return when sending this cookie back in a
future request.
.TP
\fBorigin\fR
.IP \fBorigin\fR
.
This is always present. Its value describes where the http package believes it
received the cookie from, which may be useful for checking whether the
cookie's domain is valid.
.TP
\fBpath\fR
.IP \fBpath\fR
.
This is always present. Its value describes the path prefix of requests to the
cookie domain where the cookie should be returned.
.TP
\fBsecure\fR
.IP \fBsecure\fR
.
This is always present. Its value is a boolean that is true when the cookie
should only used on requests sent over secure channels (typically HTTPS).
.TP
\fBvalue\fR
.IP \fBvalue\fR
.
This is always present. Its value is the value of the cookie, which is part of
the information that must be return when sending this cookie back in a future
request.
.PP
Other keys may always be ignored; they have no meaning in this protocol.
.RE
.VE TIP406
.SH "PROTOCOL UPGRADES"
.PP
The HTTP/1.1 \fBConnection\fR and \fBUpgrade\fR request headers inform the
server that the client wishes to change the protocol used over the existing
connection (RFC 7230).
This mechanism can be used to request a WebSocket (RFC 6455), a
higher version of the HTTP protocol (HTTP 2), or TLS encryption.  If the
server accepts the upgrade request, its response code will be 101.
.PP
To request a protocol upgrade when calling \fBhttp::geturl\fR,
the \fB\-headers\fR option must supply appropriate values for \fBConnection\fR
and \fBUpgrade\fR, and
the \fB\-command\fR option must supply a command that implements the requested
protocol and can also handle the server response if the server refuses the
protocol upgrade.  For upgrade requests \fBhttp::geturl\fR ignores the value of
option \fB\-keepalive\fR, and always uses the value \fB0\fR so that the upgrade
request is not made over a connection that is intended for multiple HTTP
requests.
.PP
The Tcllib library \fBwebsocket\fR implements WebSockets, and makes the
necessary calls to commands in the \fBhttp\fR package.
.PP
There is currently no native Tcl client library for HTTP/2.
.PP
The \fBUpgrade\fR mechanism is not used to request TLS in web browsers, because
\fBhttp\fR and \fBhttps\fR are served over different ports.  It is used by
protocols such as Internet Printing Protocol (IPP) that are built on top of
\fBhttp(s)\fR and use the same TCP port number for both secure and insecure
traffic.
.PP
In browsers, opportunistic encryption is instead implemented by the
\fBUpgrade-Insecure-Requests\fR client header.  If a secure service is
available, the server response code is a 307 redirect, and the response header
\fBLocation\fR specifies the target URL.  The browser must
call \fBhttp::geturl\fR again in order to fetch this URL.
See https://w3c.github.io/webappsec-upgrade-insecure-requests/
.PP
.SH THREADS
.PP
.SS "PURPOSE"
.PP
Command \fB::http::geturl\fR uses the Tcl \fB::socket\fR command with
the \fB\-async\fR option to connect to a remote server, but the return from
this command can be delayed in adverse cases (e.g. a slow DNS lookup),
preventing the event loop from processing other events.
This delay is avoided if the \fB::socket\fR command is evaluated in another
thread.  The Thread package is not part of Tcl but is provided in
"Batteries Included" distributions.  Instead of the \fB::socket\fR command,
the http package uses \fB::http::socket\fR which makes connections in the
manner specified by the value of \fB\-threadlevel\fR and the availability
of package Thread.
.PP
.SS "WITH TLS (HTTPS)"
.PP
The same \fB\-threadlevel\fR configuration applies to both HTTP and HTTPS
connections.
HTTPS is enabled by using the \fBhttp::register\fR command, typically by
specifying the \fB::tls::socket\fR command of the tls package to handle TLS
cryptography.  The \fB::tls::socket\fR command connects to the remote server by
using the command specified by the value of variable \fB::tls::socketCmd\fR, and
this value defaults to "::socket".  If http::geturl finds
that \fB::tls::socketCmd\fR has this value, it replaces it with the value
"::http::socket".  If \fB::tls::socketCmd\fR has a value other than "::socket",
i.e. if the script or the Tcl installation has replaced the value "::socket"
with the name of a different command, then http does not change the value.
The script or installation that modified \fB::tls::socketCmd\fR is responsible
for integrating \fB::http::socket\fR into its own replacement command.
.PP
.SS "WITH A CHILD INTERPRETER"
.PP
The peer thread can transfer the socket only to the main interpreter of the
script's thread.  Therefore the thread-based \fB::http::socket\fR works with
non-zero \fB\-threadlevel\fR values only if the script runs in the main
interpreter.  A child interpreter must use \fB\-threadlevel 0\fR unless the
parent interpreter has provided alternative facilities.  The main parent
interpreter may grant full \fB\-threadlevel\fR facilities to a child
interpreter, for example by aliasing, to \fB::http::socket\fR in the child,
a command that runs \fBhttp::socket\fR in the parent, and then transfers
the socket to the child.
.PP
.SH EXAMPLE
.PP
This example creates a procedure to copy a URL to a file while printing a
progress meter, and prints the meta-data associated with the URL.
progress meter, and prints the response headers associated with the URL.
.PP
.CS
proc httpcopy { url file {chunk 4096} } {
    set out [open $file w]
    set token [\fB::http::geturl\fR $url -channel $out \e
            -progress httpCopyProgress -blocksize $chunk]
    close $out

    # This ends the line started by httpCopyProgress
    puts stderr ""

    upvar #0 $token state
    upvar 0 $token state
    set max 0
    foreach {name value} $state(meta) {
        if {[string length $name] > $max} {
            set max [string length $name]
        }
        if {[regexp -nocase ^location$ $name]} {
            # Handle URL redirects

Changes to doc/idna.n.

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
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







-
-
-
-
+
+
+
+


+




+

-
+






+

-
+




+

-
+





-
+







-
+







+







'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
tcl::idna \- Support for normalization of Internationalized Domain Names
.SH SYNOPSIS
.nf
package require tcl::idna 1.0

\fBtcl::idna decode\fR \fIhostname\fR
\fBtcl::idna encode\fR \fIhostname\fR
\fBtcl::idna puny decode\fR \fIstring\fR ?\fIcase\fR?
\fBtcl::idna puny encode\fR \fIstring\fR ?\fIcase\fR?
\fBtcl::idna decode\fI hostname\fR
\fBtcl::idna encode\fI hostname\fR
\fBtcl::idna puny decode\fI string\fR ?\fIcase\fR?
\fBtcl::idna puny encode\fI string\fR ?\fIcase\fR?
\fBtcl::idna version\fR
.fi
.BE
.SH DESCRIPTION
This package provides an implementation of the punycode scheme used in
Internationalised Domain Names, and some access commands. (See RFC 3492 for a
description of punycode.)
.\" METHOD: decode
.TP
\fBtcl::idna decode\fR \fIhostname\fR
\fBtcl::idna decode\fI hostname\fR
.
This command takes the name of a host that potentially contains
punycode-encoded character sequences, \fIhostname\fR, and returns the hostname
as might be displayed to the user. Note that there are often UNICODE
characters that have extremely similar glyphs, so care should be taken with
displaying hostnames to users.
.\" METHOD: encode
.TP
\fBtcl::idna encode\fR \fIhostname\fR
\fBtcl::idna encode\fI hostname\fR
.
This command takes the name of a host as might be displayed to the user,
\fIhostname\fR, and returns the version of the hostname with characters not
permitted in basic hostnames encoded with punycode.
.\" METHOD: puny
.TP
\fBtcl::idna puny\fR \fIsubcommand ...\fR
\fBtcl::idna puny\fI subcommand ...\fR
.
This command provides direct access to the basic punycode encoder and
decoder. It supports two \fIsubcommand\fRs:
.RS
.TP
\fBtcl::idna puny decode\fR \fIstring\fR ?\fIcase\fR?
\fBtcl::idna puny decode\fI string\fR ?\fIcase\fR?
.
This command decodes the punycode-encoded string, \fIstring\fR, and returns
the result. If \fIcase\fR is provided, it is a boolean to make the case be
folded to upper case (if \fIcase\fR is true) or lower case (if \fIcase\fR is
false) during the decoding process; if omitted, no case transformation is
applied.
.TP
\fBtcl::idna puny encode\fR \fIstring\fR ?\fIcase\fR?
\fBtcl::idna puny encode\fI string\fR ?\fIcase\fR?
.
This command encodes the string, \fIstring\fR, and returns the
punycode-encoded version of the string. If \fIcase\fR is provided, it is a
boolean to make the case be folded to upper case (if \fIcase\fR is true) or
lower case (if \fIcase\fR is false) during the encoding process; if omitted,
no case transformation is applied.
.RE
.\" METHOD: version
.TP
\fBtcl::idna version\fR
.
This returns the version of the \fBtcl::idna\fR package.
.SH "EXAMPLE"
.PP
This is an example of how punycoding of a string works:

Changes to doc/if.n.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
10
11
12
13
14
15
16

17
18
19
20
21
22
23







-







.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
if \- Execute scripts conditionally
.SH SYNOPSIS
\fBif \fIexpr1 \fR?\fBthen\fR? \fIbody1 \fBelseif \fIexpr2 \fR?\fBthen\fR? \fIbody2\fR \fBelseif\fR ... ?\fBelse\fR? ?\fIbodyN\fR?
.BE

.SH DESCRIPTION
.PP
The \fIif\fR command evaluates \fIexpr1\fR as an expression (in the
same way that \fBexpr\fR evaluates its argument).  The value of the
expression must be a boolean
(a numeric value, where 0 is false and
anything is true, or a string value such as \fBtrue\fR or \fByes\fR

Changes to doc/info.n.

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
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







+




+




+





+




+

















-
+













-
-


+








+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






+






+







info \- Information about the state of the Tcl interpreter
.SH SYNOPSIS
\fBinfo \fIoption \fR?\fIarg arg ...\fR?
.BE
.SH DESCRIPTION
.PP
Available commands:
.\" METHOD: args
.TP
\fBinfo args \fIprocname\fR
.
Returns the names of the parameters to the procedure named \fIprocname\fR.
.\" METHOD: body
.TP
\fBinfo body \fIprocname\fR
.
Returns the body of the procedure named \fIprocname\fR.
.\" METHOD: class
.TP
\fBinfo class\fI subcommand class\fR ?\fIarg ...\fR
.
Returns information about the class named \fIclass\fR.
See \fBCLASS INTROSPECTION\fR below.
.\" METHOD: cmdcount
.TP
\fBinfo cmdcount\fR
.
Returns the total number of commands evaluated in this interpreter.
.\" METHOD: cmdtype
.TP
\fBinfo cmdtype \fIcommandName\fR
.VS TIP426
Returns a the type of the command named \fIcommandName\fR.
Built-in types are:
.RS
.IP \fBalias\fR
\fIcommandName\fR was created by \fBinterp alias\fR.
In a safe interpreter an alias is only visible if both the alias and the
target are visible.
.IP \fBcoroutine\fR
\fIcommandName\fR was created by \fBcoroutine\fR.
.IP \fBensemble\fR
\fIcommandName\fR was created by \fBnamespace ensemble\fR.
.IP \fBimport\fR
\fIcommandName\fR was created by \fBnamespace import\fR.
.IP \fBnative\fR
\fIcommandName\fR was created by the \fBTcl_CreateObjProc\fR
\fIcommandName\fR was created by the \fBTcl_CreateObjCommand\fR
interface directly without further registration of the type of command.
.IP \fBobject\fR
\fIcommandName\fR is the public command that represents an
instance of \fBoo::object\fR or one of its subclasses.
.IP \fBprivateObject\fR
\fIcommandName\fR is the private command, \fBmy\fR by default,
that represents an instance of \fBoo::object\fR or one of its subclasses.
.IP \fBproc\fR
\fIcommandName\fR was created by \fBproc\fR.
.IP \fBinterp\fR
\fIcommandName\fR was created by \fBinterp create\fR.
.IP \fBzlibStream\fR
\fIcommandName\fR was created by \fBzlib stream\fR.
.PP
Other types may be also registered as well.  See \fBTcl_RegisterCommandTypeName\fR.
.RE
.VE TIP426
.\" METHOD: commands
.TP
\fBinfo commands \fR?\fIpattern\fR?
.
Returns the names of all commands visible in the current namespace.  If
\fIpattern\fR is given, returns only those names that match according to
\fBstring match\fR.  Only the last component of \fIpattern\fR is a pattern.
Other components identify a namespace.  See \fBNAMESPACE RESOLUTION\fR in the
\fBnamespace\fR(n) documentation.
.\" METHOD: complete
.TP
\fBinfo complete \fIcommand\fR
.
Returns 1 if \fIcommand\fR is a complete command, and \fB0\fR otherwise.
Typically used in line-oriented input environments
to allow users to type in commands that span multiple lines.
.\" METHOD: constant
.TP
\fBinfo constant \fIvarName\fR
.VS "TIP 677"
Returns 1 if \fIvarName\fR is a constant variable (see \fBconst\fR) and 0
otherwise.
.VE "TIP 677"
.\" METHOD: consts
.TP
\fBinfo consts\fR ?\fIpattern\fR?
.VS "TIP 677"
Returns the list of constant variables (see \fBconst\fR) in the current scope,
or the list of constant variables matching \fIpattern\fR (if that is provided)
in a manner similar to \fBinfo vars\fR.
.VE "TIP 677"
.\" METHOD: coroutine
.TP
\fBinfo coroutine\fR
.
Returns the name of the current \fBcoroutine\fR, or the empty
string if there is no current coroutine or the current coroutine
has been deleted.
.\" METHOD: default
.TP
\fBinfo default \fIprocname parameter varname\fR
.
If the parameter \fIparameter\fR for the procedure named \fIprocname\fR has a
default value, stores that value in \fIvarname\fR and returns \fB1\fR.
Otherwise, returns \fB0\fR.
.\" METHOD: errorstack
.TP
\fBinfo errorstack \fR?\fIinterp\fR?
.
Returns a description of the active command at each level for the
last error in the current interpreter, or in the interpreter named
\fIinterp\fR if given.
.RS
121
122
123
124
125
126
127

128
129
130
131
132

133
134
135
136
137
138
139
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164







+





+







granularity.
.PP
This information is also present in the \fB\-errorstack\fR entry of the
options dictionary returned by 3-argument \fBcatch\fR; \fBinfo errorstack\fR
is a convenient way of retrieving it for uncaught errors at top-level in an
interactive \fBinterpreter\fR.
.RE
.\" METHOD: exists
.TP
\fBinfo exists \fIvarName\fR
.
Returns \fB1\fR if a variable named \fIvarName\fR is visible and has been
defined, and \fB0\fR otherwise.
.\" METHOD: frame
.TP
\fBinfo frame\fR ?\fIdepth\fR?
.
Returns the depth of the call to \fBinfo frame\fR itself.  Otherwise, returns a
dictionary describing the active command at the \fIdepth\fR, which counts all
commands visible to \fBinfo level\fR, plus commands that don't create a new
level, such as \fBeval\fR, \fBsource\fR, or \fIuplevel\fR. The frame depth is
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
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







-
-
+
-



-
-
+
-
-
+
-
-
-
+
-


-
-
+
-

-
-
+
-
-
+


-
-
+
-




-
-
+
-


-
-
+
-

-
-
+
-

-
-
+
-


-
-
+
-







.QW "foo [bar [x]]" ,
only
.QW x
is seen by \fBinfo frame\fR invoked within
.QW x .
.PP
The dictionary may contain the following keys:
.TP
\fBtype\fR
.IP \fBtype\fR
.
Always present.  Possible values are \fBsource\fR, \fBproc\fR,
\fBeval\fR, and \fBprecompiled\fR.
.RS
.TP
\fBsource\fR\0\0\0\0\0\0\0\0
.IP \fBsource\fR
.
A script loaded via the \fBsource\fR
A script loaded via the \fBsource\fR command.
command.
.TP
\fBproc\fR\0\0\0\0\0\0\0\0
.IP \fBproc\fR
.
The body of a procedure that could not be traced back to a
line in a particular script.
.TP
\fBeval\fR\0\0\0\0\0\0\0\0
.IP \fBeval\fR
.
The body of a script provided to \fBeval\fR or \fBuplevel\fR.
.TP
\fBprecompiled\fR\0\0\0\0\0\0\0\0
.IP \fBprecompiled\fR
.
A pre-compiled script (loadable by the package
A precompiled script (loadable by the package
\fBtbcload\fR), and no further information is available.
.RE
.TP
\fBline\fR
.IP \fBline\fR
.
The line number of of the command inside its script.  Not available for
\fBprecompiled\fR commands.  When the type is \fBsource\fR, the line number is
relative to the beginning of the file, whereas for the last two types it is
relative to the start of the script.
.TP
\fBfile\fR
.IP \fBfile\fR
.
For type \fBsource\fR, provides the normalized path of the file that contains
the command.
.TP
\fBcmd\fR
.IP \fBcmd\fR
.
The command before substitutions were performed.
.TP
\fBproc\fR
.IP \fBproc\fR
.
For type \fBprod\fR, the name of the procedure containing the command.
.TP
\fBlambda\fR
.IP \fBlambda\fR
.
For a command in a script evaluated as the body of an unnamed routine via the
\fBapply\fR command, the definition of that routine.
.TP
\fBlevel\fR
.IP \fBlevel\fR
.
For a frame that corresponds to a level, (to be determined).
.PP
When a command can be traced to its literal definition in some script, e.g.
procedures nested in statically defined procedures, and literal eval scripts in
files or statically defined procedures, its type is \fBsource\fR and its
location is the absolute line number in the script.  Otherwise, its type is
\fBproc\fR and its location is its line number within the body of the
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
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
366
367
368
369
370
371
372
373
374







+







+









+




-
+
+





+
+







-
+

+





+

-
+

-
-
-
+
+
+


+







-
+





+





+





+








+








+






+





+









-
-
+
+
+
+
+



+







than any dynamic outer scope.
.PP
The syntactic form \fB{*}\fR is handled like \fBeval\fR. I.e. if it
is given a literal list argument the system tracks the line number
within the list words as well, and otherwise all line numbers are
counted relative to the start of each word (smallest scope)
.RE
.\" METHOD: functions
.TP
\fBinfo functions \fR?\fIpattern\fR?
.
If \fIpattern\fR is not given, returns a list of all the math
functions currently defined.
If \fIpattern\fR is given, returns only those names that match
\fIpattern\fR according to \fBstring match\fR.
.\" METHOD: globals
.TP
\fBinfo globals \fR?\fIpattern\fR?
.
If \fIpattern\fR is not given, returns a list of all the names
of currently-defined global variables.
Global variables are variables in the global namespace.
If \fIpattern\fR is given, only those names matching \fIpattern\fR
are returned.  Matching is determined using the same rules as for
\fBstring match\fR.
.\" METHOD: hostname
.TP
\fBinfo hostname\fR
.
Returns the name of the current host.

.RS
.PP
This name is not guaranteed to be the fully-qualified domain
name of the host.  Where machines have several different names, as is
common on systems with both TCP/IP (DNS) and NetBIOS-based networking
installed, it is the name that is suitable for TCP/IP networking that
is returned.
.RE
.\" METHOD: level
.TP
\fBinfo level\fR ?\fIlevel\fR?
.
If \fInumber\fR is not given, the level this routine was called from.
Otherwise returns the complete command active at the given level.  If
\fInumber\fR is greater than \fB0\fR, it is the desired level.  Otherwise, it
is \fInumber\fR levels up from the current level.  A complete command is the
words in the command, with all subsitutions performed, meaning that it is a
words in the command, with all substitutions performed, meaning that it is a
list.  See \fBuplevel\fR for more information on levels.
.\" METHOD: library
.TP
\fBinfo library\fR
.
Returns the value of \fBtcl_library\fR, which is the name of the library
directory in which the scripts distributed with Tcl scripts are stored.
.\" METHOD: loaded
.TP
\fBinfo loaded \fR?\fIinterp\fR? ?\fIpackage\fR?
\fBinfo loaded \fR?\fIinterp\fR? ?\fIprefix\fR?
.
Returns the name of each file loaded in \fIinterp\fR va \fBload\fR as part of
\fIpackage\fR .  If \fIpackage\fR is not given, returns a list where each item
is the name of the loaded file and the name of the package for which the file
Returns the name of each file loaded in \fIinterp\fR by the \fBload\fR command
with prefix \fIprefix\fR .  If \fIprefix\fR is not given, returns a list where
each item is the name of the loaded file and the prefix for which the file
was loaded.  For a statically-loaded package the name of the file is the empty
string.  For \fIinterp\fR, the empty string is the current interpreter.
.\" METHOD: locals
.TP
\fBinfo locals \fR?\fIpattern\fR?
.
If \fIpattern\fR is given, returns the name of each local variable matching
\fIpattern\fR according to \fBstring match\fR.  Otherwise, returns the name of
each local variable.  A variables defined with the \fBglobal\fR, \fBupvar\fR or
\fBvariable\fR is not local.

.\" METHOD: nameofexecutable
.TP
\fBinfo nameofexecutable\fR
.
Returns the absolute pathname of the program for the current interpreter.  If
such a file can not be identified an empty string is returned.
.\" METHOD: object
.TP
\fBinfo object\fI subcommand object\fR ?\fIarg ...\fR
.
Returns information about the object named \fIobject\fR. \fIsubcommand\fR is
described \fBOBJECT INTROSPECTION\fR below.
.\" METHOD: patchlevel
.TP
\fBinfo patchlevel\fR
.
Returns the value of the global variable \fBtcl_patchLevel\fR, in which the
exact version of the Tcl library initially stored.
.\" METHOD: procs
.TP
\fBinfo procs \fR?\fIpattern\fR?
.
Returns the names of all visible procedures. If \fIpattern\fR is given, returns
only those names that match according to \fBstring match\fR.  Only the final
component in \fIpattern\fR is actually considered a pattern.  Any qualifying
components simply select a namespace.  See \fBNAMESPACE RESOLUTION\fR in the
\fBnamespace\fR(n) documentation.
.\" METHOD: script
.TP
\fBinfo script\fR ?\fIfilename\fR?
.
Returns the pathname of the innermost script currently being evaluated, or the
empty string if no pathname can be determined.  If \fIfilename\fR is given,
sets the return value of any future calls to \fBinfo script\fR for the duration
of the innermost active script.  This is useful in virtual file system
applications.
.\" METHOD: sharedlibextension
.TP
\fBinfo sharedlibextension\fR
.
Returns the extension used on this platform for names of shared libraries, e.g.
\fB.so\fR under Solaris.  Returns the empty string if shared libraries are not
supported on this platform.
.\" METHOD: tclversion
.TP
\fBinfo tclversion\fR
.
Returns the value of the global variable \fBtcl_version\fR, in which the
major and minor version of the Tcl library are stored.
.\" METHOD: vars
.TP
\fBinfo vars\fR ?\fIpattern\fR?
.
If \fIpattern\fR is not given, returns the names of all visible variables.  If
\fIpattern\fR is given, returns only those names that match according to
\fBstring match\fR.  Only the last component of \fIpattern\fR is a pattern.
Other components identify a namespace.  See \fBNAMESPACE RESOLUTION\fR in the
\fBnamespace\fR(n) documentation.  When \fIpattern\fR is a qualified name,
results are fully qualified.

A variable that has declared but not yet defined is included in the results.
.RS
.PP
A variable that has been declared but not yet given a value will be included in
the results.
.RE
.SS "CLASS INTROSPECTION"
.PP
The following \fIsubcommand\fR values are supported by \fBinfo class\fR:
.\" METHOD: call
.TP
\fBinfo class call\fI class method\fR
.
Returns a description of the method implementations that are used to provide a
stereotypical instance of \fIclass\fR's implementation of \fImethod\fR
(stereotypical instances being objects instantiated by a class without having
any object-specific definitions added). This consists of a list of lists of
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
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
467
468
469
470
471


472
473
474


475
476
477


478
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591







+









+








+


















+





+




+





+






+







+










+














+








-
-
+
+

-
-
+
+

-
-
+
+



+








+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







+





+













+







Note that there is no inspection of whether the method implementations
actually use \fBnext\fR to transfer control along the call chain,
.VS TIP500
and the call chains that this command files do not actually contain private
methods.
.VE TIP500
.RE
.\" METHOD: constructor
.TP
\fBinfo class constructor\fI class\fR
.
This subcommand returns a description of the definition of the constructor of
class \fIclass\fR. The definition is described as a two element list; the first
element is the list of arguments to the constructor in a form suitable for
passing to another call to \fBproc\fR or a method definition, and the second
element is the body of the constructor. If no constructor is present, this
returns the empty list.
.\" METHOD: definition
.TP
\fBinfo class definition\fI class method\fR
.
This subcommand returns a description of the definition of the method named
\fImethod\fR of class \fIclass\fR. The definition is described as a two element
list; the first element is the list of arguments to the method in a form
suitable for passing to another call to \fBproc\fR or a method definition, and
the second element is the body of the method.
.\" METHOD: definitionnamespace
.TP
\fBinfo class definitionnamespace\fI class\fR ?\fIkind\fR?
.VS TIP524
This subcommand returns the definition namespace for \fIkind\fR definitions of
the class \fIclass\fR; the definition namespace only affects the instances of
\fIclass\fR, not \fIclass\fR itself. The \fIkind\fR can be either
\fB\-class\fR to return the definition namespace used for \fBoo::define\fR, or
\fB\-instance\fR to return the definition namespace used for
\fBoo::objdefine\fR; the \fB\-class\fR kind is default (though this is only
actually useful on classes that are subclasses of \fBoo::class\fR).
.RS
.PP
If \fIclass\fR does not provide a definition namespace of the given kind,
this command returns the empty string. In those circumstances, the
\fBoo::define\fR and \fBoo::objdefine\fR commands look up which definition
namespace to use using the class inheritance hierarchy.
.RE
.VE TIP524
.\" METHOD: destructor
.TP
\fBinfo class destructor\fI class\fR
.
This subcommand returns the body of the destructor of class \fIclass\fR. If no
destructor is present, this returns the empty string.
.\" METHOD: filters
.TP
\fBinfo class filters\fI class\fR
.
This subcommand returns the list of filter methods set on the class.
.\" METHOD: forward
.TP
\fBinfo class forward\fI class method\fR
.
This subcommand returns the argument list for the method forwarding called
\fImethod\fR that is set on the class called \fIclass\fR.
.\" METHOD: instances
.TP
\fBinfo class instances\fI class\fR ?\fIpattern\fR?
.
This subcommand returns a list of instances of class \fIclass\fR. If the
optional \fIpattern\fR argument is present, it constrains the list of returned
instances to those that match it according to the rules of \fBstring match\fR.
.\" METHOD: methods
.TP
\fBinfo class methods\fI class\fR ?\fIoptions...\fR?
.
This subcommand returns a list of all public (i.e. exported) methods of the
class called \fIclass\fR. Any of the following \fIoption\fRs may be
given, controlling exactly which method names are returned:
.RS
.\" OPTION: -all
.TP
\fB\-all\fR
.
If the \fB\-all\fR flag is given,
.VS TIP500
and the \fB\-scope\fR flag is not given,
.VE TIP500
the list of methods will include those
methods defined not just by the class, but also by the class's superclasses
and mixins.
.\" OPTION: -private
.TP
\fB\-private\fR
.
If the \fB\-private\fR flag is given,
.VS TIP500
and the \fB\-scope\fR flag is not given,
.VE TIP500
the list of methods will also include
the non-exported methods of the class (and superclasses and
mixins, if \fB\-all\fR is also given).
.VS TIP500
Note that this naming is an unfortunate clash with true private methods; this
option name is retained for backward compatibility.
.VE TIP500
.\" OPTION: -scope
.TP
\fB\-scope\fI scope\fR
.VS TIP500
Returns a list of all methods on \fIclass\fR that have the given visibility
\fIscope\fR.  When this option is supplied, both the \fB\-all\fR and
\fB\-private\fR options are ignored. The valid values for \fIscope\fR are:
.RS
.IP \fBpublic\fR 3
Only methods with \fIpublic\fR scope (i.e., callable from anywhere by any instance
of this class) are to be returned.
Only methods with \fIpublic\fR scope (i.e., callable from anywhere by any
instance of this class) are to be returned.
.IP \fBunexported\fR 3
Only methods with \fIunexported\fR scope (i.e., only callable via \fBmy\fR) are to
be returned.
Only methods with \fIunexported\fR scope (i.e., only callable via \fBmy\fR)
are to be returned.
.IP \fBprivate\fR 3
Only methods with \fIprivate\fR scope (i.e., only callable from within this class's
methods) are to be returned.
Only methods with \fIprivate\fR scope (i.e., only callable from within this
class's methods) are to be returned.
.RE
.VE TIP500
.RE
.\" METHOD: methodtype
.TP
\fBinfo class methodtype\fI class method\fR
.
This subcommand returns a description of the type of implementation used for
the method named \fImethod\fR of class \fIclass\fR. When the result is
\fBmethod\fR, further information can be discovered with \fBinfo class
definition\fR, and when the result is \fBforward\fR, further information can
be discovered with \fBinfo class forward\fR.
.\" METHOD: mixins
.TP
\fBinfo class mixins\fI class\fR
.
This subcommand returns a list of all classes that have been mixed into the
class named \fIclass\fR.
.\" METHOD: properties
.TP
\fBinfo class properties\fI class\fR ?\fIoptions...\fR
.VS "TIP 558"
This subcommand returns a sorted list of properties defined on the class named
\fIclass\fR. The \fIoptions\fR define exactly which properties are returned:
.RS
.\" OPTION: -all
.TP
\fB\-all\fR
.
With this option, the properties from the superclasses and mixins of the class
are also returned.
.\" OPTION: -readable
.TP
\fB\-readable\fR
.
This option (the default behavior) asks for the readable properties to be
returned. Only readable or writable properties are returned, not both.
.\" OPTION: -writable
.TP
\fB\-writable\fR
.
This option asks for the writable properties to be returned.  Only readable or
writable properties are returned, not both.
.RE
.VE "TIP 558"
.\" METHOD: subclasses
.TP
\fBinfo class subclasses\fI class\fR ?\fIpattern\fR?
.
This subcommand returns a list of direct subclasses of class \fIclass\fR. If
the optional \fIpattern\fR argument is present, it constrains the list of
returned classes to those that match it according to the rules of
\fBstring match\fR.
.\" METHOD: superclasses
.TP
\fBinfo class superclasses\fI class\fR
.
This subcommand returns a list of direct superclasses of class \fIclass\fR in
inheritance precedence order.
.\" METHOD: variables
.TP
\fBinfo class variables\fI class\fR ?\fB\-private\fR?
.
This subcommand returns a list of all variables that have been declared for
the class named \fIclass\fR (i.e. that are automatically present in the
class's methods, constructor and destructor).
.VS TIP500
If the \fB\-private\fR option is given, this lists the private variables
declared instead.
.VE TIP500
.SS "OBJECT INTROSPECTION"
.PP
The following \fIsubcommand\fR values are supported by \fBinfo object\fR:
.\" METHOD: call
.TP
\fBinfo object call\fI object method\fR
.
Returns a description of the method implementations that are used to provide
\fIobject\fR's implementation of \fImethod\fR.  This consists of a list of
lists of four elements, where each sublist consists of a word that describes
the general type of method implementation (being one of \fBmethod\fR for an
541
542
543
544
545
546
547

548
549
550
551
552
553

554
555
556
557
558
559
560
561
562
563
564
565

566
567
568
569
570
571
572
573

574
575
576
577

578
579
580
581
582

583
584
585
586
587
588
589
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661







+






+












+








+




+





+







Note that there is no inspection of whether the method implementations
actually use \fBnext\fR to transfer control along the call chain,
.VS TIP500
and the call chains that this command files do not actually contain private
methods.
.VE TIP500
.RE
.\" METHOD: class
.TP
\fBinfo object class\fI object\fR ?\fIclassName\fR?
.
If \fIclassName\fR is not given, this subcommand returns class of the
\fIobject\fR object. If \fIclassName\fR is present, this subcommand returns a
boolean value indicating whether the \fIobject\fR is of that class.
.\" METHOD: creationid
.TP
\fBinfo object creationid\fI object\fR
.VS TIP500
Returns the unique creation identifier for the \fIobject\fR object. This
creation identifier is unique to the object (within a Tcl interpreter) and
cannot be controlled at object creation time or altered afterwards.
.RS
.PP
\fIImplementation note:\fR the creation identifier is used to generate unique
identifiers associated with the object, especially for private variables.
.RE
.VE TIP500
.\" METHOD: definition
.TP
\fBinfo object definition\fI object method\fR
.
This subcommand returns a description of the definition of the method named
\fImethod\fR of object \fIobject\fR. The definition is described as a two
element list; the first element is the list of arguments to the method in a
form suitable for passing to another call to \fBproc\fR or a method definition,
and the second element is the body of the method.
.\" METHOD: filters
.TP
\fBinfo object filters\fI object\fR
.
This subcommand returns the list of filter methods set on the object.
.\" METHOD: forward
.TP
\fBinfo object forward\fI object method\fR
.
This subcommand returns the argument list for the method forwarding called
\fImethod\fR that is set on the object called \fIobject\fR.
.\" METHOD: isa
.TP
\fBinfo object isa\fI category object\fR ?\fIarg\fR?
.
This subcommand tests whether an object belongs to a particular category,
returning a boolean value that indicates whether the \fIobject\fR argument
meets the criteria for the category. The supported categories are:
.RS
608
609
610
611
612
613
614

615
616
617
618
619
620
621

622
623
624
625
626
627
628
629
630
631

632
633
634
635
636
637
638
639
640
641
642
643
644
645

646
647
648
649
650
651
652
653
654
655
656
657
658


659
660
661


662
663
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
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732


733
734
735


736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791

792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808







+







+










+














+











-
-
+
+

-
-
+
+



+








+





+





+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+








+







.TP
\fBinfo object isa typeof\fI object class\fR
.
This returns whether \fIclass\fR is the type of \fIobject\fR (i.e. whether
\fIobject\fR is an instance of \fIclass\fR or one of its subclasses, whether
direct or indirect).
.RE
.\" METHOD: methods
.TP
\fBinfo object methods\fI object\fR ?\fIoption...\fR?
.
This subcommand returns a list of all public (i.e. exported) methods of the
object called \fIobject\fR. Any of the following \fIoption\fRs may be
given, controlling exactly which method names are returned:
.RS
.\" OPTION: -all
.TP
\fB\-all\fR
.
If the \fB\-all\fR flag is given,
.VS TIP500
and the \fB\-scope\fR flag is not given,
.VE TIP500
the list of methods will include those
methods defined not just by the object, but also by the object's class and
mixins, plus the superclasses of those classes.
.\" OPTION: -private
.TP
\fB\-private\fR
.
If the \fB\-private\fR flag is given,
.VS TIP500
and the \fB\-scope\fR flag is not given,
.VE TIP500
the list of methods will also include
the non-exported methods of the object (and classes, if
\fB\-all\fR is also given).
.VS TIP500
Note that this naming is an unfortunate clash with true private methods; this
option name is retained for backward compatibility.
.VE TIP500
.\" OPTION: -scope
.TP
\fB\-scope\fI scope\fR
.VS TIP500
Returns a list of all methods on \fIobject\fR that have the given visibility
\fIscope\fR.  When this option is supplied, both the \fB\-all\fR and
\fB\-private\fR options are ignored. The valid values for \fIscope\fR are:
.RS
.IP \fBpublic\fR 3
Only methods with \fIpublic\fR scope (i.e., callable from anywhere) are to be
returned.
.IP \fBunexported\fR 3
Only methods with \fIunexported\fR scope (i.e., only callable via \fBmy\fR) are to
be returned.
Only methods with \fIunexported\fR scope (i.e., only callable via \fBmy\fR)
are to be returned.
.IP \fBprivate\fR 3
Only methods with \fIprivate\fR scope (i.e., only callable from within this object's
instance methods) are to be returned.
Only methods with \fIprivate\fR scope (i.e., only callable from within this
object's instance methods) are to be returned.
.RE
.VE TIP500
.RE
.\" METHOD: methodtype
.TP
\fBinfo object methodtype\fI object method\fR
.
This subcommand returns a description of the type of implementation used for
the method named \fImethod\fR of object \fIobject\fR. When the result is
\fBmethod\fR, further information can be discovered with \fBinfo object
definition\fR, and when the result is \fBforward\fR, further information can
be discovered with \fBinfo object forward\fR.
.\" METHOD: mixins
.TP
\fBinfo object mixins\fI object\fR
.
This subcommand returns a list of all classes that have been mixed into the
object named \fIobject\fR.
.\" METHOD: namespace
.TP
\fBinfo object namespace\fI object\fR
.
This subcommand returns the name of the internal namespace of the object named
\fIobject\fR.
.\" METHOD: properties
.TP
\fBinfo object properties\fI object\fR ?\fIoptions...\fR
.VS "TIP 558"
This subcommand returns a sorted list of properties defined on the object
named \fIobject\fR. The \fIoptions\fR define exactly which properties are
returned:
.RS
.\" OPTION: -all
.TP
\fB\-all\fR
.
With this option, the properties from the class, superclasses and mixins of
the object are also returned.
.\" OPTION: -readable
.TP
\fB\-readable\fR
.
This option (the default behavior) asks for the readable properties to be
returned. Only readable or writable properties are returned, not both.
.\" OPTION: -writable
.TP
\fB\-writable\fR
.
This option asks for the writable properties to be returned. Only readable or
writable properties are returned, not both.
.RE
.VE "TIP 558"
.\" METHOD: variables
.TP
\fBinfo object variables\fI object\fRR ?\fB\-private\fR?
\fBinfo object variables\fI object\fR ?\fB\-private\fR?
.
This subcommand returns a list of all variables that have been declared for
the object named \fIobject\fR (i.e. that are automatically present in the
object's methods).
.VS TIP500
If the \fB\-private\fR option is given, this lists the private variables
declared instead.
.VE TIP500
.\" METHOD: vars
.TP
\fBinfo object vars\fI object\fR ?\fIpattern\fR?
.
This subcommand returns a list of all variables in the private namespace of
the object named \fIobject\fR. If the optional \fIpattern\fR argument is
given, it is a filter (in the syntax of a \fBstring match\fR glob pattern)
that constrains the list of variables returned. Note that this is different

Changes to doc/interp.n.

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
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







+

-
+







-
+







-
+







Both restrictions are motivated by safety concerns.
.SH "THE INTERP COMMAND"
.PP
The \fBinterp\fR command is used to create, delete, and manipulate
child interpreters, and to share or transfer
channels between interpreters.  It can have any of several forms, depending
on the \fIsubcommand\fR argument:
.\" METHOD: alias
.TP
\fBinterp\fR \fBalias\fR \fIsrcPath\fR \fIsrcToken\fR
\fBinterp alias\fI srcPath srcToken\fR
.
Returns a Tcl list whose elements are the \fItargetCmd\fR and
\fIarg\fRs associated with the alias represented by \fIsrcToken\fR
(this is the value returned when the alias was
created; it is possible that the name of the source command in the
child is different from \fIsrcToken\fR).
.TP
\fBinterp\fR \fBalias\fR \fIsrcPath\fR \fIsrcToken\fR \fB{}\fR
\fBinterp alias\fI srcPath srcToken\fR \fB{}\fR
.
Deletes the alias for \fIsrcToken\fR in the child interpreter identified by
\fIsrcPath\fR.
\fIsrcToken\fR refers to the value returned when the alias
was created;  if the source command has been renamed, the renamed
command will be deleted.
.TP
\fBinterp\fR \fBalias\fR \fIsrcPath\fR \fIsrcCmd\fR \fItargetPath\fR \fItargetCmd \fR?\fIarg arg ...\fR?
\fBinterp alias\fI srcPath srcCmd targetPath targetCmd \fR?\fIarg arg ...\fR?
.
This command creates an alias between one child and another (see the
\fBalias\fR child command below for creating aliases between a child
and its parent).  In this command, either of the child interpreters
may be anywhere in the hierarchy of interpreters under the interpreter
invoking the command.
\fISrcPath\fR and \fIsrcCmd\fR identify the source of the alias.
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
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







+

-
+






+









+

-
+
+












+

+
+
+
+
+
+
+
-
+







The alias arranges for the given target command to be invoked
in the target interpreter whenever the given source command is
invoked in the source interpreter.  See \fBALIAS INVOCATION\fR below for
more details.
The command returns a token that uniquely identifies the command created
\fIsrcCmd\fR, even if the command is renamed afterwards. The token may but
does not have to be equal to \fIsrcCmd\fR.
.\" METHOD: aliases
.TP
\fBinterp\fR \fBaliases \fR?\fIpath\fR?
\fBinterp aliases \fR?\fIpath\fR?
.
This command returns a Tcl list of the tokens of all the source commands for
aliases defined in the interpreter identified by \fIpath\fR. The tokens
correspond to the values returned when
the aliases were created (which may not be the same
as the current names of the commands).
.\" METHOD: bgerror
.TP
\fBinterp bgerror \fIpath\fR ?\fIcmdPrefix\fR?
.
This command either gets or sets the current background exception handler
for the interpreter identified by \fIpath\fR. If \fIcmdPrefix\fR is
absent, the current background exception handler is returned, and if it is
present, it is a list of words (of minimum length one) that describes
what to set the interpreter's background exception handler to. See the
\fBBACKGROUND EXCEPTION HANDLING\fR section for more details.
.\" METHOD: cancel
.TP
\fBinterp\fR \fBcancel \fR?\fB\-unwind\fR? ?\fB\-\|\-\fR? ?\fIpath\fR? ?\fIresult\fR?
\fBinterp cancel \fR?\fB\-unwind\fR? ?\fB\-\|\-\fR? ?\fIpath\fR? ?\fIresult\fR?
.
Cancels the script being evaluated in the interpreter identified by
\fIpath\fR. Without the \fB\-unwind\fR switch the evaluation stack for
the interpreter is unwound until an enclosing catch command is found or
there are no further invocations of the interpreter left on the call
stack. With the \fB\-unwind\fR switch the evaluation stack for the
interpreter is unwound without regard to any intervening catch command
until there are no further invocations of the interpreter left on the
call stack. The \fB\-\|\-\fR switch can be used to mark the end of
switches; it may be needed if \fIpath\fR is an unusual value such
as \fB\-safe\fR. If \fIresult\fR is present, it will be used as the
error message string; otherwise, a default error message string will be
used.
.\" METHOD: children
.TP
\fBinterp children\fR ?\fIpath\fR?
.
Returns a Tcl list of the names of all the child interpreters associated
with the interpreter identified by \fIpath\fR. If \fIpath\fR is omitted,
the invoking interpreter is used.
.\" METHOD: create
.TP
\fBinterp\fR \fBcreate \fR?\fB\-safe\fR? ?\fB\-\|\-\fR? ?\fIpath\fR?
\fBinterp create \fR?\fB\-safe\fR? ?\fB\-\|\-\fR? ?\fIpath\fR?
.
Creates a child interpreter identified by \fIpath\fR and a new command,
called a \fIchild command\fR. The name of the child command is the last
component of \fIpath\fR. The new child interpreter and the child command
are created in the interpreter identified by the path obtained by removing
the last component from \fIpath\fR. For example, if \fIpath\fR is \fBa b
c\fR then a new child interpreter and child command named \fBc\fR are
187
188
189
190
191
192
193

194
195

196
197
198
199
200
201
202
200
201
202
203
204
205
206
207
208

209
210
211
212
213
214
215
216







+

-
+







mark the end of switches;  it may be needed if \fIpath\fR is an unusual
value such as \fB\-safe\fR. The result of the command is the name of the
new interpreter. The name of a child interpreter must be unique among all
the children for its parent;  an error occurs if a child interpreter by the
given name already exists in this parent.
The initial recursion limit of the child interpreter is set to the
current recursion limit of its parent interpreter.
.\" METHOD: debug
.TP
\fBinterp\fR \fBdebug \fIpath\fR ?\fB\-frame\fR ?\fIbool\fR??
\fBinterp debug \fIpath\fR ?\fB\-frame\fR ?\fIbool\fR??
.
Controls whether frame-level stack information is captured in the
child interpreter identified by \fIpath\fR.  If no arguments are
given, option and current setting are returned.  If \fB\-frame\fR
is given, the debug setting is set to the given boolean if provided
and the current setting is returned.
This only affects the output of \fBinfo frame\fR, in that exact
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
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
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
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
442
443
444
445
446
447
448
449
450
451
452
453







+

-
+






+

-
+







+
+





+
+






+

-
+









+

-
+














+

-
+



+

-
+

















+
+


+

+
+





+

-
+








+

-
+






+

-
+


















+

-
+

-
+






-
-
-
+
-
-
-

-
+









+

-
+

-
+

















+







+







\fBsource\fR. This more exact information is paid for with slower
execution of all commands.
.PP
Note that once it is on, this flag cannot be switched back off: such
attempts are silently ignored. This is needed to maintain the
consistency of the underlying interpreter's state.
.RE
.\" METHOD: delete
.TP
\fBinterp\fR \fBdelete \fR?\fIpath ...\fR?
\fBinterp delete \fR?\fIpath ...\fR?
.
Deletes zero or more interpreters given by the optional \fIpath\fR
arguments, and for each interpreter, it also deletes its children. The
command also deletes the child command for each interpreter deleted.
For each \fIpath\fR argument, if no interpreter by that name
exists, the command raises an error.
.\" METHOD: eval
.TP
\fBinterp\fR \fBeval\fR \fIpath arg \fR?\fIarg ...\fR?
\fBinterp eval\fI path arg \fR?\fIarg ...\fR?
.
This command concatenates all of the \fIarg\fR arguments in the same
fashion as the \fBconcat\fR command, then evaluates the resulting string as
a Tcl script in the child interpreter identified by \fIpath\fR. The result
of this evaluation (including all \fBreturn\fR options,
such as \fB\-errorinfo\fR and \fB\-errorcode\fR information, if an
error occurs) is returned to the invoking interpreter.
.RS
.PP
Note that the script will be executed in the current context stack frame of the
\fIpath\fR interpreter; this is so that the implementations (in a parent
interpreter) of aliases in a child interpreter can execute scripts in
the child that find out information about the child's current state
and stack frame.
.RE
.\" METHOD: exists
.TP
\fBinterp exists \fIpath\fR
.
Returns \fB1\fR if a child interpreter by the specified \fIpath\fR
exists in this parent, \fB0\fR otherwise. If \fIpath\fR is omitted, the
invoking interpreter is used.
.\" METHOD: expose
.TP
\fBinterp expose \fIpath\fR \fIhiddenName\fR ?\fIexposedCmdName\fR?
\fBinterp expose \fIpath hiddenName\fR ?\fIexposedCmdName\fR?
.
Makes the hidden command \fIhiddenName\fR exposed, eventually bringing
it back under a new \fIexposedCmdName\fR name (this name is currently
accepted only if it is a valid global name space name without any ::),
in the interpreter
denoted by \fIpath\fR.
If an exposed command with the targeted name already exists, this command
fails.
Hidden commands are explained in more detail in \fBHIDDEN COMMANDS\fR, below.
.\" METHOD: hide
.TP
\fBinterp\fR \fBhide\fR \fIpath\fR \fIexposedCmdName\fR ?\fIhiddenCmdName\fR?
\fBinterp hide\fI path exposedCmdName\fR ?\fIhiddenCmdName\fR?
.
Makes the exposed command \fIexposedCmdName\fR hidden, renaming
it to the hidden command \fIhiddenCmdName\fR, or keeping the same name if
\fIhiddenCmdName\fR is not given, in the interpreter denoted
by \fIpath\fR.
If a hidden command with the targeted name already exists, this command
fails.
Currently both \fIexposedCmdName\fR and \fIhiddenCmdName\fR can
not contain namespace qualifiers, or an error is raised.
Commands to be hidden by \fBinterp hide\fR are looked up in the global
namespace even if the current namespace is not the global one. This
prevents children from fooling a parent interpreter into hiding the wrong
command, by making the current namespace be different from the global one.
Hidden commands are explained in more detail in \fBHIDDEN COMMANDS\fR, below.
.\" METHOD: hidden
.TP
\fBinterp\fR \fBhidden\fR \fIpath\fR
\fBinterp hidden\fI path\fR
.
Returns a list of the names of all hidden commands in the interpreter
identified by \fIpath\fR.
.\" METHOD: invokehidden
.TP
\fBinterp\fR \fBinvokehidden\fR \fIpath\fR ?\fI\-option ...\fR? \fIhiddenCmdName\fR ?\fIarg ...\fR?
\fBinterp invokehidden\fI path\fR ?\fI\-option ...\fR? \fIhiddenCmdName\fR ?\fIarg ...\fR?
.
Invokes the hidden command \fIhiddenCmdName\fR with the arguments supplied
in the interpreter denoted by \fIpath\fR. No substitutions or evaluation
are applied to the arguments. Three \fI\-option\fRs are supported, all
of which start with \fB\-\fR: \fB\-namespace\fR (which takes a single
argument afterwards, \fInsName\fR), \fB\-global\fR, and \fB\-\|\-\fR.
If the \fB\-namespace\fR flag is present, the hidden command is invoked in
the namespace called \fInsName\fR in the target interpreter.
If the \fB\-global\fR flag is present, the hidden command is invoked at the
global level in the target interpreter; otherwise it is invoked at the
current call frame and can access local variables in that and outer call
frames.
The \fB\-\|\-\fR flag allows the \fIhiddenCmdName\fR argument to start with a
.QW \-
character, and is otherwise unnecessary.
If both the \fB\-namespace\fR and \fB\-global\fR flags are present, the
\fB\-namespace\fR flag is ignored.
.RS
.PP
Note that the hidden command will be executed (by default) in the
current context stack frame of the \fIpath\fR interpreter.
.PP
Hidden commands are explained in more detail in \fBHIDDEN COMMANDS\fR, below.
.RE
.\" METHOD: issafe
.TP
\fBinterp issafe\fR ?\fIpath\fR?
.
Returns \fB1\fR if the interpreter identified by the specified \fIpath\fR
is safe, \fB0\fR otherwise.
.\" METHOD: limit
.TP
\fBinterp\fR \fBlimit\fR \fIpath\fR \fIlimitType\fR ?\fI\-option\fR? ?\fIvalue\fR \fI...\fR?
\fBinterp limit\fI path limitType\fR ?\fI\-option\fR? ?\fIvalue ...\fR?
.
Sets up, manipulates and queries the configuration of the resource
limit \fIlimitType\fR for the interpreter denoted by \fIpath\fR.  If
no \fI\-option\fR is specified, return the current configuration of the
limit.  If \fI\-option\fR is the sole argument, return the value of that
option.  Otherwise, a list of \fI\-option\fR/\fIvalue\fR argument pairs
must supplied. See \fBRESOURCE LIMITS\fR below for a more detailed
explanation of what limits and options are supported.
.\" METHOD: marktrusted
.TP
\fBinterp marktrusted\fR \fIpath\fR
\fBinterp marktrusted\fI path\fR
.
Marks the interpreter identified by \fIpath\fR as trusted. Does
not expose the hidden commands. This command can only be invoked from a
trusted interpreter.
The command has no effect if the interpreter identified by \fIpath\fR is
already trusted.
.\" METHOD: recursionlimit
.TP
\fBinterp\fR \fBrecursionlimit\fR \fIpath\fR ?\fInewlimit\fR?
\fBinterp recursionlimit\fI path\fR ?\fInewlimit\fR?
.
Returns the maximum allowable nesting depth for the interpreter
specified by \fIpath\fR.  If \fInewlimit\fR is specified,
the interpreter recursion limit will be set so that nesting
of more than \fInewlimit\fR calls to \fBTcl_Eval\fR
and related procedures in that interpreter will return an error.
The \fInewlimit\fR value is also returned.
The \fInewlimit\fR value must be a positive integer between 1 and the
maximum value of a non-long integer on the platform.
.RS
.PP
The command sets the maximum size of the Tcl call stack only. It cannot
by itself prevent stack overflows on the C stack being used by the
application. If your machine has a limit on the size of the C stack, you
may get stack overflows before reaching the limit set by the command. If
this happens, see if there is a mechanism in your system for increasing
the maximum size of the C stack.
.RE
.\" METHOD: share
.TP
\fBinterp\fR \fBshare\fR \fIsrcPath channelId destPath\fR
\fBinterp share\fI srcPath channel destPath\fR
.
Causes the IO channel identified by \fIchannelId\fR to become shared
Causes the IO channel identified by \fIchannel\fR to become shared
between the interpreter identified by \fIsrcPath\fR and the interpreter
identified by \fIdestPath\fR. Both interpreters have the same permissions
on the IO channel.
Both interpreters must close it to close the underlying IO channel; IO
channels accessible in an interpreter are automatically closed when an
interpreter is destroyed.
.TP
\fBinterp\fR \fBchildren\fR ?\fIpath\fR?
.
.\" METHOD: target
Returns a Tcl list of the names of all the child interpreters associated
with the interpreter identified by \fIpath\fR. If \fIpath\fR is omitted,
the invoking interpreter is used.
.TP
\fBinterp\fR \fBtarget\fR \fIpath alias\fR
\fBinterp target\fI path alias\fR
.
Returns a Tcl list describing the target interpreter for an alias. The
alias is specified with an interpreter path and source command name, just
as in \fBinterp alias\fR above. The name of the target interpreter is
returned as an interpreter path, relative to the invoking interpreter.
If the target interpreter for the alias is the invoking interpreter then an
empty list is returned. If the target interpreter for the alias is not the
invoking interpreter or one of its descendants then an error is generated.
The target command does not have to be defined at the time of this invocation.
.\" METHOD: transfer
.TP
\fBinterp\fR \fBtransfer\fR \fIsrcPath channelId destPath\fR
\fBinterp transfer\fI srcPath channel destPath\fR
.
Causes the IO channel identified by \fIchannelId\fR to become available in
Causes the IO channel identified by \fIchannel\fR to become available in
the interpreter identified by \fIdestPath\fR and unavailable in the
interpreter identified by \fIsrcPath\fR.
.SH "CHILD COMMAND"
.PP
For each child interpreter created with the \fBinterp\fR command, a
new Tcl command is created in the parent interpreter with the same
name as the new interpreter. This command may be used to invoke
various operations on the interpreter.  It has the following
general form:
.PP
.CS
\fIchild command \fR?\fIarg arg ...\fR?
.CE
.PP
\fIChild\fR is the name of the interpreter, and \fIcommand\fR
and the \fIarg\fRs determine the exact behavior of the command.
The valid forms of this command are:
.\" METHOD: aliases
.TP
\fIchild \fBaliases\fR
.
Returns a Tcl list whose elements are the tokens of all the
aliases in \fIchild\fR.  The tokens correspond to the values returned when
the aliases were created (which may not be the same
as the current names of the commands).
.\" METHOD: alias
.TP
\fIchild \fBalias \fIsrcToken\fR
.
Returns a Tcl list whose elements are the \fItargetCmd\fR and
\fIarg\fRs associated with the alias represented by \fIsrcToken\fR
(this is the value returned when the alias was
created; it is possible that the actual source command in the
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
467
468
469
470
471
472
473
474
475

476
477
478
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
467
468
469
470
471
472
473
474
475
476
477
478
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

558

559
560
561
562
563

564
565
566

567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585

586
587
588
589
590
591
592
593







+









+









+
+





+
+










+















+




+


















+
+


+
-
+
-
+
+



-
+
+

-
+








+







+

-
+







The \fIarg\fR arguments will be passed to \fItargetCmd\fR as additional
arguments, prepended before any arguments passed in the invocation of
\fIsrcCmd\fR.
See \fBALIAS INVOCATION\fR below for details.
The command returns a token that uniquely identifies the command created
\fIsrcCmd\fR, even if the command is renamed afterwards. The token may but
does not have to be equal to \fIsrcCmd\fR.
.\" METHOD: bgerror
.TP
\fIchild \fBbgerror\fR ?\fIcmdPrefix\fR?
.
This command either gets or sets the current background exception handler
for the \fIchild\fR interpreter. If \fIcmdPrefix\fR is
absent, the current background exception handler is returned, and if it is
present, it is a list of words (of minimum length one) that describes
what to set the interpreter's background exception handler to. See the
\fBBACKGROUND EXCEPTION HANDLING\fR section for more details.
.\" METHOD: eval
.TP
\fIchild \fBeval \fIarg \fR?\fIarg ..\fR?
.
This command concatenates all of the \fIarg\fR arguments in
the same fashion as the \fBconcat\fR command, then evaluates
the resulting string as a Tcl script in \fIchild\fR.
The result of this evaluation (including all \fBreturn\fR options,
such as \fB\-errorinfo\fR and \fB\-errorcode\fR information, if an
error occurs) is returned to the invoking interpreter.
.RS
.PP
Note that the script will be executed in the current context stack frame
of \fIchild\fR; this is so that the implementations (in a parent
interpreter) of aliases in a child interpreter can execute scripts in
the child that find out information about the child's current state
and stack frame.
.RE
.\" METHOD: expose
.TP
\fIchild \fBexpose \fIhiddenName \fR?\fIexposedCmdName\fR?
.
This command exposes the hidden command \fIhiddenName\fR, eventually bringing
it back under a new \fIexposedCmdName\fR name (this name is currently
accepted only if it is a valid global name space name without any ::),
in \fIchild\fR.
If an exposed command with the targeted name already exists, this command
fails.
For more details on hidden commands, see \fBHIDDEN COMMANDS\fR, below.
.\" METHOD: hide
.TP
\fIchild \fBhide \fIexposedCmdName\fR ?\fIhiddenCmdName\fR?
.
This command hides the exposed command \fIexposedCmdName\fR, renaming it to
the hidden command \fIhiddenCmdName\fR, or keeping the same name if the
argument is not given, in the \fIchild\fR interpreter.
If a hidden command with the targeted name already exists, this command
fails.
Currently both \fIexposedCmdName\fR and \fIhiddenCmdName\fR can
not contain namespace qualifiers, or an error is raised.
Commands to be hidden are looked up in the global
namespace even if the current namespace is not the global one. This
prevents children from fooling a parent interpreter into hiding the wrong
command, by making the current namespace be different from the global one.
For more details on hidden commands, see \fBHIDDEN COMMANDS\fR, below.
.\" METHOD: hidden
.TP
\fIchild \fBhidden\fR
.
Returns a list of the names of all hidden commands in \fIchild\fR.
.\" METHOD: invokehidden
.TP
\fIchild \fBinvokehidden\fR ?\fI\-option ...\fR? \fIhiddenName \fR?\fIarg ..\fR?
.
This command invokes the hidden command \fIhiddenName\fR with the
supplied arguments, in \fIchild\fR. No substitutions or evaluations are
applied to the arguments. Three \fI\-option\fRs are supported, all
of which start with \fB\-\fR: \fB\-namespace\fR (which takes a single
argument afterwards, \fInsName\fR), \fB\-global\fR, and \fB\-\|\-\fR.
If the \fB\-namespace\fR flag is given, the hidden command is invoked in
the specified namespace in the child.
If the \fB\-global\fR flag is given, the command is invoked at the global
level in the child; otherwise it is invoked at the current call frame and
can access local variables in that or outer call frames.
The \fB\-\|\-\fR flag allows the \fIhiddenCmdName\fR argument to start with a
.QW \-
character, and is otherwise unnecessary.
If both the \fB\-namespace\fR and \fB\-global\fR flags are given, the
\fB\-namespace\fR flag is ignored.
.RS
.PP
Note that the hidden command will be executed (by default) in the
current context stack frame of \fIchild\fR.
.PP
For more details on hidden commands,
For more details on hidden commands, see \fBHIDDEN COMMANDS\fR, below.
see \fBHIDDEN COMMANDS\fR, below.
.RE
.\" METHOD: issafe
.TP
\fIchild \fBissafe\fR
.
Returns  \fB1\fR if the child interpreter is safe, \fB0\fR otherwise.
Returns \fB1\fR if the child interpreter is safe, \fB0\fR otherwise.
.\" METHOD: limit
.TP
\fIchild \fBlimit\fR \fIlimitType\fR ?\fI\-option\fR? ?\fIvalue\fR \fI...\fR?
\fIchild \fBlimit\fI limitType\fR ?\fI\-option\fR? ?\fIvalue ...\fR?
.
Sets up, manipulates and queries the configuration of the resource
limit \fIlimitType\fR for the child interpreter.  If no \fI\-option\fR
is specified, return the current configuration of the limit.  If
\fI\-option\fR is the sole argument, return the value of that option.
Otherwise, a list of \fI\-option\fR/\fIvalue\fR argument pairs must
supplied. See \fBRESOURCE LIMITS\fR below for a more detailed explanation of
what limits and options are supported.
.\" METHOD: marktrusted
.TP
\fIchild \fBmarktrusted\fR
.
Marks the child interpreter as trusted. Can only be invoked by a
trusted interpreter. This command does not expose any hidden
commands in the child interpreter. The command has no effect if the child
is already trusted.
.\" METHOD: recursionlimit
.TP
\fIchild\fR \fBrecursionlimit\fR ?\fInewlimit\fR?
\fIchild \fBrecursionlimit\fR ?\fInewlimit\fR?
.
Returns the maximum allowable nesting depth for the \fIchild\fR interpreter.
If \fInewlimit\fR is specified, the recursion limit in \fIchild\fR will be
set so that nesting of more than \fInewlimit\fR calls to \fBTcl_Eval()\fR
and related procedures in \fIchild\fR will return an error.
The \fInewlimit\fR value is also returned.
The \fInewlimit\fR value must be a positive integer between 1 and the
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599











600
601
602
603
604
605
606
607
608

609
610
611
612
613
614
615
630
631
632
633
634
635
636










637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655

656
657
658
659
660
661
662
663







-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+








-
+







\fBbinary\fR	\fBbreak\fR	\fBcatch\fR	\fBchan\fR
\fBclock\fR	\fBclose\fR	\fBconcat\fR	\fBcontinue\fR
\fBdict\fR	\fBeof\fR	\fBerror\fR	\fBeval\fR
\fBexpr\fR	\fBfblocked\fR	\fBfcopy\fR	\fBfileevent\fR
\fBflush\fR	\fBfor\fR	\fBforeach\fR	\fBformat\fR
\fBgets\fR	\fBglobal\fR	\fBif\fR	\fBincr\fR
\fBinfo\fR	\fBinterp\fR	\fBjoin\fR	\fBlappend\fR
\fBlassign\fR	\fBlindex\fR	\fBlinsert\fR	\fBlist\fR
\fBllength\fR	\fBlrange\fR	\fBlrepeat\fR	\fBlreplace\fR
\fBlsearch\fR	\fBlset\fR	\fBlsort\fR	\fBnamespace\fR
\fBpackage\fR	\fBpid\fR	\fBproc\fR	\fBputs\fR
\fBread\fR	\fBregexp\fR	\fBregsub\fR	\fBrename\fR
\fBreturn\fR	\fBscan\fR	\fBseek\fR	\fBset\fR
\fBsplit\fR	\fBstring\fR	\fBsubst\fR	\fBswitch\fR
\fBtell\fR	\fBtime\fR	\fBtrace\fR	\fBunset\fR
\fBupdate\fR	\fBuplevel\fR	\fBupvar\fR	\fBvariable\fR
\fBvwait\fR	\fBwhile\fR
\fBlassign\fR	\fBledit\fR	\fBlindex\fR	\fBlinsert\fR
\fBlist\fR	\fBllength\fR	\fBlrange\fR	\fBlrepeat\fR
\fBlreplace\fR	\fBlsearch\fR	\fBlseq\fR      \fBlset\fR
\fBlsort\fR     \fBnamespace\fR	\fBpackage\fR	\fBpid\fR
\fBproc\fR      \fBputs\fR	\fBread\fR	\fBregexp\fR
\fBregsub\fR	\fBrename\fR	\fBreturn\fR	\fBscan\fR
\fBseek\fR	\fBset\fR	\fBsplit\fR	\fBstring\fR
\fBsubst\fR	\fBswitch\fR	\fBtell\fR	\fBtime\fR
\fBtrace\fR	\fBunset\fR	\fBupdate\fR	\fBuplevel\fR
\fBupvar\fR	\fBvariable\fR	\fBvwait\fR	\fBwhile\fR
\fBzlib\fR
.DE
The following commands are hidden by \fBinterp create\fR when it
creates a safe interpreter:
.DS
.ta 1.2i 2.4i 3.6i
\fBcd\fR	\fBencoding\fR	\fBexec\fR	\fBexit\fR
\fBfconfigure\fR	\fBfile\fR	\fBglob\fR	\fBload\fR
\fBopen\fR	\fBpwd\fR	\fBsocket\fR	\fBsource\fR
\fBunload\fR
\fBunload\fR	\fBzipfs\fR
.DE
These commands can be recreated later as Tcl procedures or aliases, or
re-exposed by \fBinterp expose\fR.
.PP
The following commands from Tcl's library of support procedures are
not present in a safe interpreter:
.DS
785
786
787
788
789
790
791

792
793
794
795
796
797
798
799
800
801


802
803
804


805
806
807
808
809
810
811
812

813
814
815
816
817
818
819

820
821
822
823
824
825
826
827
828

829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849



850
851
852
853
854
855


856
857
858
859
860
861
862
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903


904
905
906
907
908
909
910


911
912
913
914
915
916
917
918
919







+










+
+



+
+








+







+









+



















-
-
+
+
+




-
-
+
+







\fBinterp eval\fR) where it becomes the responsibility of the calling code to
catch and handle.
.SS "LIMIT OPTIONS"
.PP
Every limit has a number of options associated with it, some of which are
common across all kinds of limits, and others of which are particular to the
kind of limit.
.\" OPTION: -command
.TP
\fB\-command\fR
.
This option (common for all limit types) specifies (if non-empty) a Tcl script
to be executed in the global namespace of the interpreter reading and writing
the option when the particular limit in the limited interpreter is exceeded.
The callback may modify the limit on the interpreter if it wishes the limited
interpreter to continue executing. If the callback generates an exception, it
is reported through the background exception mechanism (see
\fBBACKGROUND EXCEPTION HANDLING\fR).
.RS
.PP
Note that the callbacks defined by one interpreter are
completely isolated from the callbacks defined by another, and that the order
in which those callbacks are called is undefined.
.RE
.\" OPTION: -granularity
.TP
\fB\-granularity\fR
.
This option (common for all limit types) specifies how frequently (out of the
points when the Tcl interpreter is in a consistent state where limit checking
is possible) that the limit is actually checked. This allows the tuning of how
frequently a limit is checked, and hence how often the limit-checking overhead
(which may be substantial in the case of time limits) is incurred.
.\" OPTION: -milliseconds
.TP
\fB\-milliseconds\fR
.
This option specifies the number of milliseconds after the moment defined in
the \fB\-seconds\fR option that the time limit will fire. It should only ever
be specified in conjunction with the \fB\-seconds\fR option (whether it was
set previously or is being set this invocation.)
.\" OPTION: -seconds
.TP
\fB\-seconds\fR
.
This option specifies the number of seconds after the epoch (see \fBclock
seconds\fR) that the time limit for the interpreter will be triggered. The
limit will be triggered at the start of the second unless specified at a
sub-second level using the \fB\-milliseconds\fR option. This option may be the
empty string, which indicates that a time limit is not set for the
interpreter.
.\" OPTION: -value
.TP
\fB\-value\fR
.
This option specifies the number of commands that the interpreter may execute
before triggering the command limit. This option may be the empty string,
which indicates that a command limit is not set for the interpreter.
.PP
Where an interpreter with a resource limit set on it creates a child
interpreter, that child interpreter will have resource limits imposed on it
that are at least as restrictive as the limits on the creating parent
interpreter. If the parent interpreter of the limited parent wishes to relax
these conditions, it should hide the \fBinterp\fR command in the child and
then use aliases and the \fBinterp invokehidden\fR subcommand to provide such
access as it chooses to the \fBinterp\fR command to the limited parent as
necessary.
.SH "BACKGROUND EXCEPTION HANDLING"
.PP
When an exception happens in a situation where it cannot be reported directly up
the stack (e.g. when processing events in an \fBupdate\fR or \fBvwait\fR call)
the exception is instead reported through the background exception handling mechanism.
Every interpreter has a background exception handler registered; the default exception
the exception is instead reported through the background exception handling
mechanism. Every interpreter has a background exception handler registered;
the default exception
handler arranges for the \fBbgerror\fR command in the interpreter's global
namespace to be called, but other exception handlers may be installed and process
background exceptions in substantially different ways.
.PP
A background exception handler consists of a non-empty list of words to which will
be appended two further words at invocation time. The first word will be the
A background exception handler consists of a non-empty list of words to which
will be appended two further words at invocation time. The first word will be the
interpreter result at time of the exception, typically an error message,
and the second will be the dictionary of return options at the time of
the exception.  These are the same values that \fBcatch\fR can capture
when it controls script evaluation in a non-background situation.
The resulting list will then be executed
in the interpreter's global namespace without further substitutions being
performed.
896
897
898
899
900
901
902

903

904
905
906
907
908
953
954
955
956
957
958
959
960

961
962
963
964
965
966







+
-
+





    set x 0
    while {1} {
        puts "Counting up... [incr x]"
    }
}
.CE
.SH "SEE ALSO"
bgerror(n), load(n), safe(n),
bgerror(n), load(n), safe(n), Tcl_CreateChild(3), Tcl_Eval(3), Tcl_BackgroundException(3)
Tcl_CreateChild(3), Tcl_Eval(3), Tcl_BackgroundException(3)
.SH KEYWORDS
alias, parent interpreter, safe interpreter, child interpreter
'\"Local Variables:
'\"mode: nroff
'\"End:

Changes to doc/lappend.n.

45
46
47
48
49
50
51
52

53
54

55
56
57
58
59
60
45
46
47
48
49
50
51

52
53

54
55
56
57
58
59
60







-
+

-
+






1
% \fBlappend\fR var 2
1 2
% \fBlappend\fR var 3 4 5
1 2 3 4 5
.CE
.SH "SEE ALSO"
list(n), lassign(n), lindex(n), linsert(n), llength(n),
list(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n)
lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n)
.SH KEYWORDS
append, element, list, variable
.\" Local variables:
.\" mode: nroff
.\" fill-column: 78
.\" End:

Changes to doc/lassign.n.

48
49
50
51
52
53
54
55

56
57

58
59
60
61
62
48
49
50
51
52
53
54

55
56

57
58
59
60
61
62







-
+

-
+





.QW shift
command in many shell languages like this:
.PP
.CS
set ::argv [\fBlassign\fR $::argv argumentToReadOff]
.CE
.SH "SEE ALSO"
list(n), lappend(n), lindex(n), linsert(n), llength(n),
list(n), lappend(n), ledit(n), lindex(n), linsert(n), llength(n),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n)
lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n)
.SH KEYWORDS
assign, element, list, multiple, set, variable
'\"Local Variables:
'\"mode: nroff
'\"End:

Added doc/ledit.n.






























































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
'\"
'\" Copyright (c) 2022 Ashok P. Nadkarni <apnmbx-public@yahoo.com>.  All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH ledit n 9.0 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
ledit \- Replace elements of a list stored in variable
.SH SYNOPSIS
\fBledit \fIlistVar first last \fR?\fIvalue value ...\fR?
.BE
.SH DESCRIPTION
.PP
The command fetches the list value in variable \fIlistVar\fR and replaces the
elements in the range given by indices \fIfirst\fR to \fIlast\fR (inclusive)
with the \fIvalue\fR arguments. The resulting list is then stored back in
\fIlistVar\fR and returned as the result of the command.
.PP
Arguments \fIfirst\fR and \fIlast\fR are index values specifying the first and
last elements of the range to replace. They are interpreted
the same as index values for the command \fBstring index\fR,
supporting simple index arithmetic and indices relative to the
end of the list. The index \fB0\fR refers to the first element of the
list, and \fBend\fR refers to the last element of the list.
(Unlike with \fBlpop\fR, \fBlset\fR, and \fBlindex\fR, indices into sublists
are not supported.)
.PP
If either \fIfirst\fR or \fIlast\fR is less than zero, it is considered to
refer to the position before the first element of the list. This allows
elements to be prepended.
.PP
If either \fIfirst\fR or \fIlast\fR indicates a position greater than the
index of the last element of the list, it is treated as if it is an
index one greater than the last element. This allows elements to be appended.
.PP
If \fIlast\fR is less than \fIfirst\fR, then any specified elements
will be inserted into the list before the element specified by \fIfirst\fR
with no elements being deleted.
.PP
The \fIvalue\fR arguments specify zero or more new elements to
be added to the list in place of those that were deleted.
Each \fIvalue\fR argument will become a separate element of
the list.  If no \fIvalue\fR arguments are specified, the elements
between \fIfirst\fR and \fIlast\fR are simply deleted.
.SH EXAMPLES
.PP
Prepend to a list.
.PP
.CS
set lst {c d e f g}
      \fI\(-> c d e f g\fR
\fBledit\fR lst -1 -1 a b
      \fI\(-> a b c d e f g\fR
.CE
.PP
Append to the list.
.PP
.CS
\fBledit\fR lst end+1 end+1 h i
      \fI\(-> a b c d e f g h i\fR
.CE
.PP
Delete third and fourth elements.
.PP
.CS
\fBledit\fR lst 2 3
      \fI\(-> a b e f g h i\fR
.CE
.PP
Replace two elements with three.
.PP
.CS
\fBledit\fR lst 2 3 x y z
      \fI\(-> a b x y z g h i\fR
set lst
      \fI\(-> a b x y z g h i\fR
.CE
.PP
.SH "SEE ALSO"
list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n),
string(n)
.SH KEYWORDS
element, list, replace
.\" Local variables:
.\" mode: nroff
.\" fill-column: 78
.\" End:

Changes to doc/library.n.

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
30
31
32
33
34
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
30
31
32
33
34
35
36
37
38
39
40











-
+















+
+
+
+
+
+







'\"
'\" Copyright (c) 1991-1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH library n "8.0" Tcl "Tcl Built-In Commands"
.so man.macros
.BS
.SH NAME
auto_execok, auto_import, auto_load, auto_mkindex, auto_qualify, auto_reset, tcl_findLibrary, parray, tcl_endOfWord, tcl_startOfNextWord, tcl_startOfPreviousWord, tcl_wordBreakAfter, tcl_wordBreakBefore \- standard library of Tcl procedures
auto_execok, auto_import, auto_load, auto_mkindex, auto_qualify, auto_reset, foreachLine, parray, readFile, tcl_findLibrary, tcl_endOfWord, tcl_startOfNextWord, tcl_startOfPreviousWord, tcl_wordBreakAfter, tcl_wordBreakBefore, writeFile \- standard library of Tcl procedures
.SH SYNOPSIS
.nf
\fBauto_execok \fIcmd\fR
\fBauto_import \fIpattern\fR
\fBauto_load \fIcmd\fR
\fBauto_mkindex \fIdir pattern pattern ...\fR
\fBauto_qualify \fIcommand namespace\fR
\fBauto_reset\fR
\fBtcl_findLibrary \fIbasename version patch initScript enVarName varName\fR
\fBparray \fIarrayName\fR ?\fIpattern\fR?
\fBtcl_endOfWord \fIstr start\fR
\fBtcl_startOfNextWord \fIstr start\fR
\fBtcl_startOfPreviousWord \fIstr start\fR
\fBtcl_wordBreakAfter \fIstr start\fR
\fBtcl_wordBreakBefore \fIstr start\fR
.VS "Tcl 8.7, TIP 670"
\fBforeachLine \fIfilename varName body\fR
\fBreadFile \fIfilename\fR ?\fBtext\fR|\fBbinary\fR?
\fBwriteFile \fIfilename\fR ?\fBtext\fR|\fBbinary\fR? \fIcontents\fR
.VE "Tcl 8.7, TIP 670"
.fi
.BE
.SH INTRODUCTION
.PP
Tcl includes a library of Tcl procedures for commonly-needed functions.
The procedures defined in the Tcl library are generic ones suitable
for use by many different applications.
The location of the Tcl library is returned by the \fBinfo library\fR
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
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







+


+












+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+







+
+
+
+
+


+




-
+


















+
+
+
+
+
+







\fBTcl_AppInit\fR procedure, this happens automatically.
The code in \fBinit.tcl\fR will define the \fBunknown\fR procedure
and arrange for the other procedures to be loaded on-demand using
the auto-load mechanism defined below.
.SH "COMMAND PROCEDURES"
.PP
The following procedures are provided in the Tcl library:
.\" COMMAND: auto_execok
.TP
\fBauto_execok \fIcmd\fR
.
Determines whether there is an executable file or shell builtin
by the name \fIcmd\fR.  If so, it returns a list of arguments to be
passed to \fBexec\fR to execute the executable file or shell builtin
named by \fIcmd\fR.  If not, it returns an empty string.  This command
examines the directories in the current search path (given by the PATH
environment variable) in its search for an executable file named
\fIcmd\fR.  On Windows platforms, the search is expanded with the same
directories and file extensions as used by \fBexec\fR. \fBAuto_execok\fR
remembers information about previous searches in an array named
\fBauto_execs\fR;  this avoids the path search in future calls for the
same \fIcmd\fR.  The command \fBauto_reset\fR may be used to force
\fBauto_execok\fR to forget its cached information.
.RS
.PP
For example, to run the \fIumask\fR shell builtin on Linux, you would do:
.PP
.CS
exec {*}[\fBauto_execok\fR umask]
.CE
.PP
To run the \fIDIR\fR shell builtin on Windows, you would do:
.PP
.CS
exec {*}[\fBauto_execok\fR dir]
.CE
.PP
To discover if there is a \fIfrobnicate\fR binary on the user's PATH,
you would do:
.PP
.CS
set mayFrob [expr {[llength [\fBauto_execok\fR frobnicate]] > 0}]
.CE
.RE
.\" COMMAND: auto_import
.TP
\fBauto_import \fIpattern\fR
.
\fBAuto_import\fR is invoked during \fBnamespace import\fR to see if
the imported commands specified by \fIpattern\fR reside in an
autoloaded library.  If so, the commands are loaded so that they will
be available to the interpreter for creating the import links.  If the
commands do not reside in an autoloaded library, \fBauto_import\fR
does nothing.  The pattern matching is performed according to the
matching rules of \fBnamespace import\fR.
.RS
.PP
It is not normally necessary to call this command directly.
.RE
.\" COMMAND: auto_load
.TP
\fBauto_load \fIcmd\fR
.
This command attempts to load the definition for a Tcl command named
\fIcmd\fR.  To do this, it searches an \fIauto-load path\fR, which is
a list of one or more directories.  The auto-load path is given by the
global variable \fBauto_path\fR if it exists.  If there is no
\fBauto_path\fR variable, then the TCLLIBPATH environment variable is
\fBauto_path\fR variable, then the \fBTCLLIBPATH\fR environment variable is
used, if it exists.  Otherwise the auto-load path consists of just the
Tcl library directory.  Within each directory in the auto-load path
there must be a file \fBtclIndex\fR that describes one or more
commands defined in that directory and a script to evaluate to load
each of the commands.  The \fBtclIndex\fR file should be generated
with the \fBauto_mkindex\fR command.  If \fIcmd\fR is found in an
index file, then the appropriate script is evaluated to create the
command.  The \fBauto_load\fR command returns 1 if \fIcmd\fR was
successfully created.  The command returns 0 if there was no index
entry for \fIcmd\fR or if the script did not actually define \fIcmd\fR
(e.g. because index information is out of date).  If an error occurs
while processing the script, then that error is returned.
\fBAuto_load\fR only reads the index information once and saves it in
the array \fBauto_index\fR;  future calls to \fBauto_load\fR check for
\fIcmd\fR in the array rather than re-reading the index files.  The
cached index information may be deleted with the command
\fBauto_reset\fR.  This will force the next \fBauto_load\fR command to
reload the index database from disk.
.RS
.PP
It is not normally necessary to call this command directly; the
default \fBunknown\fR handler will do so.
.RE
.\" COMMAND: auto_mkindex
.TP
\fBauto_mkindex \fIdir pattern pattern ...\fR
.
Generates an index suitable for use by \fBauto_load\fR.  The command
searches \fIdir\fR for all files whose names match any of the
\fIpattern\fR arguments (matching is done with the \fBglob\fR
command), generates an index of all the Tcl command procedures defined
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
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
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
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
467
468
469
470
471
472
473
474
475

476
477
478
479
480
481
482
483
484

485
486
487
488
489
490
491
492
493







+








+


+

















+


+




















+


+






+
+
+
+
+
+
+
+
+
+
+
+
+


+








+


+





+
+
+
+
+
+
+
+
+
+
+
+
+
+


+




+


+





+


+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






+


+


+
+
+
+
+


+


+
+
+
+
+


+


+


+


+













+
+
+
+
+
+
+
+
+
+
+
+
+


+





+
+
+
+
+
+
+


+






+
+
+
+
+
+
+
+
+




+


+



-
+
+
+


+



-
+
+







have spaces before the \fBproc\fR) will not be indexed.  If your
script contains
.QW dangerous
code, such as global initialization
code or procedure names with special characters like \fB$\fR,
\fB*\fR, \fB[\fR or \fB]\fR, you are safer using \fBauto_mkindex_old\fR.
.RE
.\" COMMAND: auto_reset
.TP
\fBauto_reset\fR
.
Destroys all the information cached by \fBauto_execok\fR and
\fBauto_load\fR.  This information will be re-read from disk the next
time it is needed.  \fBAuto_reset\fR also deletes any procedures
listed in the auto-load index, so that fresh copies of them will be
loaded the next time that they are used.
.\" COMMAND: auto_qualify
.TP
\fBauto_qualify \fIcommand namespace\fR
.
Computes a list of fully qualified names for \fIcommand\fR.  This list
mirrors the path a standard Tcl interpreter follows for command
lookups:  first it looks for the command in the current namespace, and
then in the global namespace.  Accordingly, if \fIcommand\fR is
relative and \fInamespace\fR is not \fB::\fR, the list returned has
two elements:  \fIcommand\fR scoped by \fInamespace\fR, as if it were
a command in the \fInamespace\fR namespace; and \fIcommand\fR as if it
were a command in the global namespace.  Otherwise, if either
\fIcommand\fR is absolute (it begins with \fB::\fR), or
\fInamespace\fR is \fB::\fR, the list contains only \fIcommand\fR as
if it were a command in the global namespace.
.RS
.PP
\fBAuto_qualify\fR is used by the auto-loading facilities in Tcl, both
for producing auto-loading indexes such as \fIpkgIndex.tcl\fR, and for
performing the actual auto-loading of functions at runtime.
.RE
.\" COMMAND: auto_findLibrary
.TP
\fBtcl_findLibrary \fIbasename version patch initScript enVarName varName\fR
.
This is a standard search procedure for use by extensions during
their initialization.  They call this procedure to look for their
script library in several standard directories.
The last component of the name of the library directory is
normally \fIbasenameversion\fR
(e.g., tk8.0), but it might be
.QW library
when in the build hierarchies.
The \fIinitScript\fR file will be sourced into the interpreter
once it is found.  The directory in which this file is found is
stored into the global variable \fIvarName\fR.
If this variable is already defined (e.g., by C code during
application initialization) then no searching is done.
Otherwise the search looks in these directories:
the directory named by the environment variable \fIenVarName\fR;
relative to the Tcl library directory;
relative to the executable file in the standard installation
bin or bin/\fIarch\fR directory;
relative to the executable file in the current build tree;
relative to the executable file in a parallel build tree.
.\" COMMAND: parray
.TP
\fBparray \fIarrayName\fR ?\fIpattern\fR?
.
Prints on standard output the names and values of all the elements in the
array \fIarrayName\fR, or just the names that match \fIpattern\fR (using the
matching rules of \fBstring match\fR) and their values if \fIpattern\fR is
given.
\fIArrayName\fR must be an array accessible to the caller of \fBparray\fR.
It may be either local or global.
The result of this command is the empty string.
.RS
.PP
For example, to print the contents of the \fBtcl_platform\fR array, do:
.PP
.CS
\fBparray\fR tcl_platform
.CE
.RE
.SS "WORD BOUNDARY HELPERS"
.PP
These procedures are mainly used internally by Tk.
.\" COMMAND: tcl_endOfWord
.TP
\fBtcl_endOfWord \fIstr start\fR
.
Returns the index of the first end-of-word location that occurs after
a starting index \fIstart\fR in the string \fIstr\fR.  An end-of-word
location is defined to be the first non-word character following the
first word character after the starting point.  Returns -1 if there
are no more end-of-word locations after the starting point.  See the
description of \fBtcl_wordchars\fR and \fBtcl_nonwordchars\fR below
for more details on how Tcl determines which characters are word
characters.
.\" COMMAND: tcl_startOfNextWord
.TP
\fBtcl_startOfNextWord \fIstr start\fR
.
Returns the index of the first start-of-word location that occurs
after a starting index \fIstart\fR in the string \fIstr\fR.  A
start-of-word location is defined to be the first word character
following a non-word character.  Returns \-1 if there are no more
start-of-word locations after the starting point.
.RS
.PP
For example, to print the indices of the starts of each word in a
string according to platform rules:
.PP
.CS
set theString "The quick brown fox"
for {set idx 0} {$idx >= 0} {
        set idx [\fBtcl_startOfNextWord\fR $theString $idx]} {
    puts "Word start index: $idx"
}
.CE
.RE
.\" COMMAND: tcl_startOfPreviousWord
.TP
\fBtcl_startOfPreviousWord \fIstr start\fR
.
Returns the index of the first start-of-word location that occurs
before a starting index \fIstart\fR in the string \fIstr\fR.  Returns
\-1 if there are no more start-of-word locations before the starting
point.
.\" COMMAND: tcl_wordBreakAfter
.TP
\fBtcl_wordBreakAfter \fIstr start\fR
.
Returns the index of the first word boundary after the starting index
\fIstart\fR in the string \fIstr\fR.  Returns \-1 if there are no more
boundaries after the starting point in the given string.  The index
returned refers to the second character of the pair that comprises a
boundary.
.\" COMMAND: tcl_wordBreakBefore
.TP
\fBtcl_wordBreakBefore \fIstr start\fR
.
Returns the index of the first word boundary before the starting index
\fIstart\fR in the string \fIstr\fR.  Returns \-1 if there are no more
boundaries before the starting point in the given string.  The index
returned refers to the second character of the pair that comprises a
boundary.
.SS "FILE ACCESS HELPERS"
.\" COMMAND: foreachLine
.TP
\fBforeachLine \fIvarName filename body\fR
.VS "Tcl 8.7, TIP 670"
This reads in the text file named \fIfilename\fR one line at a time
(using system defaults for reading text files). It writes that line to the
variable named by \fIvarName\fR and then executes \fIbody\fR for that line.
The result value of \fIbody\fR is ignored, but \fBerror\fR, \fBreturn\fR,
\fBbreak\fR and \fBcontinue\fR may be used within it to produce an error,
return from the calling context, stop the loop, or go to the next line
respectively.
The overall result of \fBforeachLine\fR is the empty string (assuming no
errors from I/O or from evaluating the body of the loop); the file will be
closed prior to the procedure returning.
.VE "Tcl 8.7, TIP 670"
.\" COMMAND: readFile
.TP
\fBreadFile \fIfilename\fR ?\fBtext\fR|\fBbinary\fR?
.VS "Tcl 8.7, TIP 670"
Reads in the file named in \fIfilename\fR and returns its contents.
The second argument says how to read in the file, either as \fBtext\fR
(using the system defaults for reading text files) or as \fBbinary\fR
(as uninterpreted bytes). The default is \fBtext\fR. When read as text, this
will include any trailing newline.
The file will be closed prior to the procedure returning.
.VE "Tcl 8.7, TIP 670"
.\" COMMAND: writeFile
.TP
\fBwriteFile \fIfilename\fR ?\fBtext\fR|\fBbinary\fR? \fIcontents\fR
.VS "Tcl 8.7, TIP 670"
Writes the \fIcontents\fR to the file named in \fIfilename\fR.
The optional second argument says how to write to the file, either as
\fBtext\fR (using the system defaults for writing text files) or as
\fBbinary\fR (as uninterpreted bytes). The default is \fBtext\fR.
If a trailing newline is required, it will need to be provided in
\fIcontents\fR. The result of this command is the empty string; the file will
be closed prior to the procedure returning.
.VE "Tcl 8.7, TIP 670"
.SH "VARIABLES"
.PP
The following global variables are defined or used by the procedures in
the Tcl library. They fall into two broad classes, handling unknown
commands and packages, and determining what are words.
.SS "AUTOLOADING AND PACKAGE MANAGEMENT VARIABLES"
.\" VARIABLE: auto_execs
.TP
\fBauto_execs\fR
.
Used by \fBauto_execok\fR to record information about whether
particular commands exist as executable files.
.RS
.PP
Not normally usefully accessed directly by user code.
.RE
.\" VARIABLE: auto_index
.TP
\fBauto_index\fR
.
Used by \fBauto_load\fR to save the index information read from
disk.
.RS
.PP
Not normally usefully accessed directly by user code.
.RE
.\" VARIABLE: auto_noexec
.TP
\fBauto_noexec\fR
.
If set to any value, then \fBunknown\fR will not attempt to auto-exec
any commands.
.\" VARIABLE: auto_noload
.TP
\fBauto_noload\fR
.
If set to any value, then \fBunknown\fR will not attempt to auto-load
any commands.
.\" VARIABLE: auto_path
.TP
\fBauto_path\fR
.
If set, then it must contain a valid Tcl list giving directories to
search during auto-load operations (including for package index
files when using the default \fBpackage unknown\fR handler).
This variable is initialized during startup to contain, in order:
the directories listed in the \fBTCLLIBPATH\fR environment variable,
the directory named by the \fBtcl_library\fR global variable,
the parent directory of \fBtcl_library\fR,
the directories listed in the \fBtcl_pkgPath\fR variable.
Additional locations to look for files and package indices should
normally be added to this variable using \fBlappend\fR.
.RS
.PP
For example, to add the \fIlib\fR directory next to the running
script, you would do:
.PP
.CS
lappend \fBauto_path\fR [file dirname [info script]]/lib
.CE
.PP
Note that if the script uses \fBcd\fR, it is advisable to ensure that
entries on the \fBauto_path\fR are \fBfile normalize\fRd.
.RE
.\" VARIABLE: env(TCL_LIBRARY)
.TP
\fBenv(TCL_LIBRARY)\fR
.
If set, then it specifies the location of the directory containing
library scripts (the value of this variable will be
assigned to the \fBtcl_library\fR variable and therefore returned by
the command \fBinfo library\fR).  If this variable is not set then
a default value is used.
.RS
.PP
Use of this environment variable is not recommended outside of testing.
Tcl installations should already know where to find their own script
files, as the value is baked in during the build or installation.
.RE
.\" VARIABLE: env(TCLLIBPATH)
.TP
\fBenv(TCLLIBPATH)\fR
.
If set, then it must contain a valid Tcl list giving directories to
search during auto-load operations.  Directories must be specified in
Tcl format, using
.QW /
as the path separator, regardless of platform.
This variable is only used when initializing the \fBauto_path\fR variable.
.RS
.PP
A key consequence of this variable is that it gives a way to let the user
of a script specify the list of places where that script may use
\fBpackage require\fR to read packages from. It is not normally usefully
settable within a Tcl script itself \fIexcept\fR to influence where other
interpreters load from (whether made with \fBinterp create\fR or launched
as their own threads or subprocesses).
.RE
.SS "WORD BOUNDARY DETERMINATION VARIABLES"
These variables are only used in the \fBtcl_endOfWord\fR,
\fBtcl_startOfNextWord\fR, \fBtcl_startOfPreviousWord\fR,
\fBtcl_wordBreakAfter\fR, and \fBtcl_wordBreakBefore\fR commands.
.\" VARIABLE: tcl_nonwordchars
.TP
\fBtcl_nonwordchars\fR
.
This variable contains a regular expression that is used by routines
like \fBtcl_endOfWord\fR to identify whether a character is part of a
word or not.  If the pattern matches a character, the character is
considered to be a non-word character. The default is "\\W".
considered to be a non-word character. The default value is
.QW "\\W" .
.\" VARIABLE: tcl_wordchars
.TP
\fBtcl_wordchars\fR
.
This variable contains a regular expression that is used by routines
like \fBtcl_endOfWord\fR to identify whether a character is part of a
word or not.  If the pattern matches a character, the character is
considered to be a word character. The default is "\\w".
considered to be a word character. The default value is
.QW "\\w" .
.SH "SEE ALSO"
env(n), info(n), re_syntax(n)
.SH KEYWORDS
auto-exec, auto-load, library, unknown, word, whitespace
'\"Local Variables:
'\"mode: nroff
'\"End:

Changes to doc/lindex.n.

1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 2001 by Kevin B. Kenny <kennykb@acm.org>.  All rights reserved.
'\" Copyright (c) 2001 Kevin B. Kenny <kennykb@acm.org>.  All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH lindex n 8.4 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
111
112
113
114
115
116
117
118

119
120

121
122
123
124
125
126
111
112
113
114
115
116
117

118
119

120
121
122
123
124
125
126







-
+

-
+






\fBlindex\fR {a b c d e f} $idx+2
      \fI\(-> d\fR
set idx 3
\fBlindex\fR {a b c d e f} $idx+2
      \fI\(-> f\fR
.CE
.SH "SEE ALSO"
list(n), lappend(n), lassign(n), linsert(n), llength(n),
list(n), lappend(n), lassign(n), ledit(n), linsert(n), llength(n),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n),
lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n),
string(n)
.SH KEYWORDS
element, index, list
'\"Local Variables:
'\"mode: nroff
'\"End:

Changes to doc/link.n.

9
10
11
12
13
14
15
16

17
18

19
20
21
22
23
24
25
9
10
11
12
13
14
15

16
17

18
19
20
21
22
23
24
25







-
+

-
+







.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
link \- create link from command to method of object
.SH SYNOPSIS
.nf
package require TclOO
package require tcl::oo

\fBlink\fR \fImethodName\fR ?\fI...\fR?
\fBlink\fI methodName\fR ?\fI...\fR?
\fBlink\fR \fB{\fIcommandName methodName\fB}\fR ?\fI...\fR?
.fi
.BE
.SH DESCRIPTION
The \fBlink\fR command is available within methods. It takes a series of one
or more method names (\fImethodName ...\fR) and/or pairs of command- and
method-name (\fB{\fIcommandName methodName\fB}\fR) and makes the named methods
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
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







-
+

-
+

-
+














-
+

-
+



-
+










-
+







oo::class create ABC {
    method Foo {} {
        puts "This is Foo in [self]"
    }

    constructor {} {
        \fBlink\fR Foo
        # The method foo is now directly accessible as foo here
        # The method Foo is now directly accessible as Foo here
        \fBlink\fR {bar Foo}
        # The method foo is now directly accessible as bar
        # The method Foo is now directly accessible as bar
        \fBlink\fR {::ExternalCall Foo}
        # The method foo is now directly accessible in the global
        # The method Foo is now directly accessible in the global
        # namespace as ExternalCall
    }

    method grill {} {
        puts "Step 1:"
        Foo
        puts "Step 2:"
        bar
    }
}

ABC create abc
abc grill
        \fI\(-> Step 1:\fR
        \fI\(-> This is foo in ::abc\fR
        \fI\(-> This is Foo in ::abc\fR
        \fI\(-> Step 2:\fR
        \fI\(-> This is foo in ::abc\fR
        \fI\(-> This is Foo in ::abc\fR
# Direct access via the linked command
puts "Step 3:"; ExternalCall
        \fI\(-> Step 3:\fR
        \fI\(-> This is foo in ::abc\fR
        \fI\(-> This is Foo in ::abc\fR
.CE
.PP
This example shows that multiple linked commands can be made in a call to
\fBlink\fR, and that they can handle arguments.
.PP
.CS
oo::class create Ex {
    constructor {} {
        \fBlink\fR a b c
        # The methods a, b, and c (defined below) are all now
        # directly acessible within methods under their own names.
        # directly accessible within methods under their own names.
    }

    method a {} {
        puts "This is a"
    }
    method b {x} {
        puts "This is b($x)"

Changes to doc/linsert.n.

41
42
43
44
45
46
47
48

49
50

51
52
53
54
55
56
41
42
43
44
45
46
47

48
49

50
51
52
53
54
55
56







-
+

-
+






set oldList {the fox jumps over the dog}
set midList [\fBlinsert\fR $oldList 1 quick]
set newList [\fBlinsert\fR $midList end-1 lazy]
# The old lists still exist though...
set newerList [\fBlinsert\fR [\fBlinsert\fR $oldList end-1 quick] 1 lazy]
.CE
.SH "SEE ALSO"
list(n), lappend(n), lassign(n), lindex(n), llength(n),
list(n), lappend(n), lassign(n), ledit(n), lindex(n), llength(n),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n),
lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n),
string(n)
.SH KEYWORDS
element, insert, list
'\" Local Variables:
'\" mode: nroff
'\" End:

Changes to doc/list.n.

42
43
44
45
46
47
48
49

50
51

52
53
54
55
56
42
43
44
45
46
47
48

49
50

51
52
53
54
55
56







-
+

-
+





.PP
while \fBconcat\fR with the same arguments will return
.PP
.CS
\fBa b c d e f {g h}\fR
.CE
.SH "SEE ALSO"
lappend(n), lassign(n), lindex(n), linsert(n), llength(n),
lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n)
lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n)
.SH KEYWORDS
element, list, quoting
'\"Local Variables:
'\"mode: nroff
'\"End:

Changes to doc/llength.n.

45
46
47
48
49
50
51
52

53
54

55
56
57
58
59
60
45
46
47
48
49
50
51

52
53

54
55
56
57
58
59
60







-
+

-
+






An empty list is not necessarily an empty string:
.PP
.CS
% set var { }; puts "[string length $var],[\fBllength\fR $var]"
1,0
.CE
.SH "SEE ALSO"
list(n), lappend(n), lassign(n), lindex(n), linsert(n),
list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n)
lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n)
.SH KEYWORDS
element, list, length
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/lmap.n.

74
75
76
77
78
79
80
81

82
83

84
85
86
87
88
74
75
76
77
78
79
80

81
82

83
84
85
86
87
88







-
+

-
+





set prefix [\fBlmap\fR x $values {expr {
    [isGood $x] ? $x : [break]
}}]
# The value of prefix is "8 7 6 5 4"
.CE
.SH "SEE ALSO"
break(n), continue(n), for(n), foreach(n), while(n),
list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n),
list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n),
lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n)
lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n)
.SH KEYWORDS
foreach, iteration, list, loop, map
'\" Local Variables:
'\" mode: nroff
'\" End:

Changes to doc/load.n.

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
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







-
+

-
+





-
+



-
-
+

-
+








-
+

-
+
-
-
-
-
+



-
-
-
+
+
+

-
+





-
+




-
+











-
+



-
-
-
-
+
+
+
+


-
-
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
+

-
-
+
+


-
+

-
+







-
+










-
+







.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
load \- Load machine code and initialize new commands
.SH SYNOPSIS
\fBload\fR ?\fB\-global\fR? ?\fB\-lazy\fR? ?\fB\-\-\fR? \fIfileName\fR
.br
\fBload\fR ?\fB\-global\fR? ?\fB\-lazy\fR? ?\fB\-\-\fR? \fIfileName packageName\fR
\fBload\fR ?\fB\-global\fR? ?\fB\-lazy\fR? ?\fB\-\-\fR? \fIfileName prefix\fR
.br
\fBload\fR ?\fB\-global\fR? ?\fB\-lazy\fR? ?\fB\-\-\fR? \fIfileName packageName interp\fR
\fBload\fR ?\fB\-global\fR? ?\fB\-lazy\fR? ?\fB\-\-\fR? \fIfileName prefix interp\fR
.BE
.SH DESCRIPTION
.PP
This command loads binary code from a file into the
application's address space and calls an initialization procedure
in the package to incorporate it into an interpreter.  \fIfileName\fR
in the library to incorporate it into an interpreter.  \fIfileName\fR
is the name of the file containing the code;  its exact form varies
from system to system but on most systems it is a shared library,
such as a \fB.so\fR file under Solaris or a DLL under Windows.
\fIpackageName\fR is the name of the package, and is used to
compute the name of an initialization procedure.
\fIprefix\fR is used to compute the name of an initialization procedure.
\fIinterp\fR is the path name of the interpreter into which to load
the package (see the \fBinterp\fR manual entry for details);
the library (see the \fBinterp\fR manual entry for details);
if \fIinterp\fR is omitted, it defaults to the
interpreter in which the \fBload\fR command was invoked.
.PP
Once the file has been loaded into the application's address space,
one of two initialization procedures will be invoked in the new code.
Typically the initialization procedure will add new commands to a
Tcl interpreter.
The name of the initialization procedure is determined by
\fIpackageName\fR and whether or not the target interpreter
\fIprefix\fR and whether or not the target interpreter
is a safe one.  For normal interpreters the name of the initialization
procedure will have the form \fIpkg\fB_Init\fR, where \fIpkg\fR
procedure will have the form \fIprefix\fB_Init\fR.  For example, if
is the same as \fIpackageName\fR except that the first letter is
converted to upper case and all other letters
are converted to lower case.  For example, if \fIpackageName\fR is
\fBfoo\fR or \fBFOo\fR, the initialization procedure's name will
\fIprefix\fR is \fBFoo\fR, the initialization procedure's name will
be \fBFoo_Init\fR.
.PP
If the target interpreter is a safe interpreter, then the name
of the initialization procedure will be \fIpkg\fB_SafeInit\fR
instead of \fIpkg\fB_Init\fR.
The \fIpkg\fB_SafeInit\fR function should be written carefully, so that it
of the initialization procedure will be \fIprefix\fB_SafeInit\fR
instead of \fIprefix\fB_Init\fR.
The \fIprefix\fB_SafeInit\fR function should be written carefully, so that it
initializes the safe interpreter only with partial functionality provided
by the package that is safe for use by untrusted code. For more information
by the library that is safe for use by untrusted code. For more information
on Safe\-Tcl, see the \fBsafe\fR manual entry.
.PP
The initialization procedure must match the following prototype:
.PP
.CS
typedef int \fBTcl_PackageInitProc\fR(
typedef int \fBTcl_LibraryInitProc\fR(
        Tcl_Interp *\fIinterp\fR);
.CE
.PP
The \fIinterp\fR argument identifies the interpreter in which the
package is to be loaded.  The initialization procedure must return
library is to be loaded.  The initialization procedure must return
\fBTCL_OK\fR or \fBTCL_ERROR\fR to indicate whether or not it completed
successfully;  in the event of an error it should set the interpreter's result
to point to an error message.  The result of the \fBload\fR command
will be the result returned by the initialization procedure.
.PP
The actual loading of a file will only be done once for each \fIfileName\fR
in an application.  If a given \fIfileName\fR is loaded into multiple
interpreters, then the first \fBload\fR will load the code and
call the initialization procedure;  subsequent \fBload\fRs will
call the initialization procedure without loading the code again.
For Tcl versions lower than 8.5, it is not possible to unload or reload a
package. From version 8.5 however, the \fBunload\fR command allows the unloading
library. From version 8.5 however, the \fBunload\fR command allows the unloading
of libraries loaded with \fBload\fR, for libraries that are aware of the
Tcl's unloading mechanism.
.PP
The \fBload\fR command also supports packages that are statically
linked with the application, if those packages have been registered
by calling the \fBTcl_StaticPackage\fR procedure.
If \fIfileName\fR is an empty string, then \fIpackageName\fR must
The \fBload\fR command also supports libraries that are statically
linked with the application, if those libraries have been registered
by calling the \fBTcl_StaticLibrary\fR procedure.
If \fIfileName\fR is an empty string, then \fIprefix\fR must
be specified.
.PP
If \fIpackageName\fR is omitted or specified as an empty string,
Tcl tries to guess the name of the package.
If \fIprefix\fR is omitted or specified as an empty string,
Tcl tries to guess the prefix by taking the last element of
This may be done differently on different platforms.
The default guess, which is used on most UNIX platforms, is to
take the last element of \fIfileName\fR, strip off the first
three characters if they are \fBlib\fR, and use any following
alphabetic and underline characters as the module name.
For example, the command \fBload libxyz4.2.so\fR uses the module
name \fBxyz\fR and the command \fBload bin/last.so {}\fR uses the
module name \fBlast\fR.
\fIfileName\fR, strip off the first three characters if they
are \fBlib\fR, then strip off the next four characters if
they are \fBtcl9\fR, and use any following wordchars
but not digits, converted to titlecase as the prefix.
For example, the command \fBload libxyz4.2.so\fR uses the prefix
\fBXyz\fR and the command \fBload bin/last.so {}\fR uses the
prefix \fBLast\fR.
.PP
If \fIfileName\fR is an empty string, then \fIpackageName\fR must
If \fIfileName\fR is an empty string, then \fIprefix\fR must
be specified.
The \fBload\fR command first searches for a statically loaded package
(one that has been registered by calling the \fBTcl_StaticPackage\fR
The \fBload\fR command first searches for a statically loaded library
(one that has been registered by calling the \fBTcl_StaticLibrary\fR
procedure) by that name; if one is found, it is used.
Otherwise, the \fBload\fR command searches for a dynamically loaded
package by that name, and uses it if it is found.  If several
library by that name, and uses it if it is found.  If several
different files have been \fBload\fRed with different versions of
the package, Tcl picks the file that was loaded first.
the library, Tcl picks the file that was loaded first.
.PP
If \fB\-global\fR is specified preceding the filename, all symbols
found in the shared library are exported for global use by other
libraries. The option \fB\-lazy\fR delays the actual loading of
symbols until their first actual use. The options may be abbreviated.
The option \fB\-\-\fR indicates the end of the options, and should
be used if you wish to use a filename which starts with \fB\-\fR
and you provide a packageName to the \fBload\fR command.
and you provide a prefix to the \fBload\fR command.
.PP
On platforms which do not support the \fB\-global\fR or \fB\-lazy\fR
options, the options still exist but have no effect. Note that use
of the \fB\-global\fR or \fB\-lazy\fR option may lead to crashes
in your application later (in case of symbol conflicts resp. missing
symbols), which cannot be detected during the \fBload\fR. So, only
use this when you know what you are doing, you will not get a nice
error message when something is wrong with the loaded library.
.SH "PORTABILITY ISSUES"
.TP
\fBWindows\fR\0\0\0\0\0
\fBWindows\fR
.
When a load fails with
.QW "library not found"
error, it is also possible
that a dependent library was not found.  To see the dependent libraries,
type
.QW "dumpbin -imports <dllname>"
184
185
186
187
188
189
190
191

192
193
194
195
196
179
180
181
182
183
184
185

186
187
188
189
190
191







-
+





    }
}

# Now execute the command defined by the extension
foo
.CE
.SH "SEE ALSO"
info sharedlibextension, package(n), Tcl_StaticPackage(3), safe(n)
info sharedlibextension, package(n), Tcl_StaticLibrary(3), safe(n)
.SH KEYWORDS
binary code, dynamic library, load, safe interpreter, shared library
'\"Local Variables:
'\"mode: nroff
'\"End:

Changes to doc/lpop.n.

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
30
31
32
33
34
35
36
37


38
39
40
41
42
43
44
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
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
45
46

-
+




-
+













-
+






+
-
+








-
+
+







'\"
'\" Copyright (c) 2018 by Peter Spjuth.  All rights reserved.
'\" Copyright (c) 2018 Peter Spjuth.  All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH lpop n 8.7 Tcl "Tcl Built-In Commands"
.TH lpop n 9.0 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
lpop \- Get and remove an element in a list
.SH SYNOPSIS
\fBlpop \fIvarName ?index ...?\fR
.BE
.SH DESCRIPTION
.PP
The \fBlpop\fR command accepts a parameter, \fIvarName\fR, which
it interprets as the name of a variable containing a Tcl list.
It also accepts one or more \fIindices\fR into
the list. If no indices are presented, it defaults to "end".
the list. If no indices are presented, it defaults to "\fBend\fR".
.PP
When presented with a single index, the \fBlpop\fR command
addresses the \fIindex\fR'th element in it, removes if from the list
and returns the element.
.PP
If \fIindex\fR is negative or greater or equal than the number
of elements in the list in the variable called \fIvarName\fR, an
of elements in \fI$varName\fR, then an error occurs.
error occurs.
.PP
The interpretation of each simple \fIindex\fR value is the same as
for the command \fBstring index\fR, supporting simple index
arithmetic and indices relative to the end of the list.
.PP
If additional \fIindex\fR arguments are supplied, then each argument is
used in turn to address an element within a sublist designated
by the previous indexing operation,
allowing the script to remove elements in sublists.
allowing the script to remove elements in sublists, similar to
\fBlindex\fR and \fBlset\fR.
The command,
.PP
.CS
\fBlpop\fR a 1 2
.CE
.PP
gets and removes element 2 of sublist 1.
82
83
84
85
86
87
88
89

90
91

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

91
92

93
94
95
96
97
98
99







-
+

-
+






The indicated value becomes the new value of \fIx\fR.
.PP
.CS
\fBlpop\fR x 1 1 0
      \fI\(-> {{a b} {c d}} {{e f} h}\fR
.CE
.SH "SEE ALSO"
list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n),
list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n),
lmap(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n),
lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n),
string(n)
.SH KEYWORDS
element, index, list, remove, pop, stack, queue
'\"Local Variables:
'\"mode: nroff
'\"End:

Changes to doc/lrange.n.

25
26
27
28
29
30
31

32

33
34
35
36
37
38
39
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40







+
-
+







supporting simple index arithmetic and indices relative to the
end of the list.
If \fIfirst\fR is less than zero, it is treated as if it were zero.
If \fIlast\fR is greater than or equal to the number of elements
in the list, then it is treated as if it were \fBend\fR.
If \fIfirst\fR is greater than \fIlast\fR then an empty string
is returned.
.PP
Note:
Note that
.QW "\fBlrange \fIlist first first\fR"
does not always produce the same result as
.QW "\fBlindex \fIlist first\fR"
(although it often does for simple fields that are not enclosed in
braces); it does, however, produce exactly the same results as
.QW "\fBlist [lindex \fIlist first\fB]\fR"
.SH EXAMPLES
67
68
69
70
71
72
73
74

75
76

77
78
79
80
81
82
83
68
69
70
71
72
73
74

75
76

77
78
79
80
81
82
83
84







-
+

-
+







some {elements to} select
% lindex $var 1
elements to
% \fBlrange\fR $var 1 1
{elements to}
.CE
.SH "SEE ALSO"
list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n),
list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n),
lmap(n), lpop(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n),
lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n),
string(n)
.SH KEYWORDS
element, list, range, sublist
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/lremove.n.

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
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






-
+











-
+







'\"
'\" Copyright (c) 2019 Donal K. Fellows.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH lremove n 8.7 Tcl "Tcl Built-In Commands"
.TH lremove n 9.0 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
lremove \- Remove elements from a list by index
.SH SYNOPSIS
\fBlremove \fIlist\fR ?\fIindex ...\fR?
.BE
.SH DESCRIPTION
.PP
\fBlremove\fR returns a new list formed by simultaneously removing zero or
more elements of \fIlist\fR at each of the indices given by an arbirary number
more elements of \fIlist\fR at each of the indices given by an arbitrary number
of \fIindex\fR arguments. The indices may be in any order and may be repeated;
the element at index will only be removed once.  The index values are
interpreted the same as index values for the command \fBstring index\fR,
supporting simple index arithmetic and indices relative to the end of the
list.  0 refers to the first element of the list, and \fBend\fR refers to the
last element of the list.
.SH EXAMPLES
42
43
44
45
46
47
48
49

50
51

52
53
54
55
56
57
42
43
44
45
46
47
48

49
50

51
52
53
54
55
56
57







-
+

-
+






Removing the same element indicated in two different ways:
.PP
.CS
% \fBlremove\fR {a b c d e} 2 end-2
a b d e
.CE
.SH "SEE ALSO"
list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n),
list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n),
lmap(n), lpop(n), lrange(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n)
lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n)
.SH KEYWORDS
element, list, remove
.\" Local variables:
.\" mode: nroff
.\" fill-column: 78
.\" End:

Changes to doc/lrepeat.n.

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
30
31
32
33
34
35

36
37

38
39
40
41
42
43
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
30
31
32
33
34
35
36

37
38

39
40
41
42
43
44
45

-
+


















-
+
+
+













-
+

-
+






'\"
'\" Copyright (c) 2003 by Simon Geard.  All rights reserved.
'\" Copyright (c) 2003 Simon Geard.  All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH lrepeat n 8.5 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
lrepeat \- Build a list by repeating elements
.SH SYNOPSIS
\fBlrepeat \fIcount \fR?\fIelement ...\fR?
.BE
.SH DESCRIPTION
.PP
The \fBlrepeat\fR command creates a list of size \fIcount * number of
elements\fR by repeating \fIcount\fR times the sequence of elements
\fIelement ...\fR.  \fIcount\fR must be a non-negative integer,
\fIelement\fR can be any Tcl value.  Note that \fBlrepeat 1 element ...\fR
\fIelement\fR can be any Tcl value.
.PP
Note that \fBlrepeat 1 element ...\fR
is identical to \fBlist element ...\fR.
.SH EXAMPLES
.CS
\fBlrepeat\fR 3 a
      \fI\(-> a a a\fR
\fBlrepeat\fR 3 [\fBlrepeat\fR 3 0]
      \fI\(-> {0 0 0} {0 0 0} {0 0 0}\fR
\fBlrepeat\fR 3 a b c
      \fI\(-> a b c a b c a b c\fR
\fBlrepeat\fR 3 [\fBlrepeat\fR 2 a] b c
      \fI\(-> {a a} b c {a a} b c {a a} b c\fR
.CE
.SH "SEE ALSO"
list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n),
list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n),
lmap(n), lpop(n), lrange(n), lremove(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n)
lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n)
.SH KEYWORDS
element, index, list
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/lreplace.n.

91
92
93
94
95
96
97
98

99
100

101
102
103
104
105
106
107
91
92
93
94
95
96
97

98
99

100
101
102
103
104
105
106
107







-
+

-
+







% set var {a b c d e}
a b c d e
% set var [\fBlreplace\fR $var 12345 end+2 f g h i]
a b c d e f g h i
.CE
.VE TIP505
.SH "SEE ALSO"
list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n),
list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n),
lreverse(n), lsearch(n), lset(n), lsort(n),
lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n),
string(n)
.SH KEYWORDS
element, list, replace
.\" Local variables:
.\" mode: nroff
.\" fill-column: 78
.\" End:

Changes to doc/lreverse.n.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







'\"
'\" Copyright (c) 2006 by Donal K. Fellows.  All rights reserved.
'\" Copyright (c) 2006 Donal K. Fellows.  All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH lreverse n 8.5 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
21
22
23
24
25
26
27
28

29
30

31
32
33
34
35
21
22
23
24
25
26
27

28
29

30
31
32
33
34
35







-
+

-
+





.CS
\fBlreverse\fR {a a b c}
      \fI\(-> c b a a\fR
\fBlreverse\fR {a b {c d} e f}
      \fI\(-> f e {c d} b a\fR
.CE
.SH "SEE ALSO"
list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n),
list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lsearch(n), lset(n), lsort(n)
lsearch(n), lseq(n), lset(n), lsort(n)
.SH KEYWORDS
element, list, reverse
'\" Local Variables:
'\" mode: nroff
'\" End:

Changes to doc/lsearch.n.

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
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







+





+





+






+













+







+






+





+













+





+








+




+






+









+





+





+


+











+













+







+







indicates how the elements of the list are to be matched against
\fIpattern\fR and must have one of the values below:
.SS "MATCHING STYLE OPTIONS"
.PP
If all matching style options are omitted, the default matching style
is \fB\-glob\fR.  If more than one matching style is specified, the
last matching style given takes precedence.
.\" OPTION: -exact
.TP
\fB\-exact\fR
.
\fIPattern\fR is a literal string that is compared for exact equality
against each list element.
.\" OPTION: -glob
.TP
\fB\-glob\fR
.
\fIPattern\fR is a glob-style pattern which is matched against each list
element using the same rules as the \fBstring match\fR command.
.\" OPTION: -regexp
.TP
\fB\-regexp\fR
.
\fIPattern\fR is treated as a regular expression and matched against
each list element using the rules described in the \fBre_syntax\fR
reference page.
.\" OPTION: -sorted
.TP
\fB\-sorted\fR
.
The list elements are in sorted order.  If this option is specified,
\fBlsearch\fR will use a more efficient searching algorithm to search
\fIlist\fR.  If no other options are specified, \fIlist\fR is assumed
to be sorted in increasing order, and to contain ASCII strings.  This
option is mutually exclusive with \fB\-glob\fR and \fB\-regexp\fR, and
is treated exactly like \fB\-exact\fR when either \fB\-all\fR or
\fB\-not\fR are specified.
.SS "GENERAL MODIFIER OPTIONS"
.PP
These options may be given with all matching styles.
.\" OPTION: -all
.TP
\fB\-all\fR
.
Changes the result to be the list of all matching indices (or all matching
values if \fB\-inline\fR is specified as well.) If indices are returned, the
indices will be in ascending numeric order. If values are returned, the order
of the values will be the order of those values within the input \fIlist\fR.
.\" OPTION: -inline
.TP
\fB\-inline\fR
.
The matching value is returned instead of its index (or an empty
string if no value matches.)  If \fB\-all\fR is also specified, then
the result of the command is the list of all values that matched.
.\" OPTION: -not
.TP
\fB\-not\fR
.
This negates the sense of the match, returning the index of the first
non-matching value in the list.
.\" OPTION: -start
.TP
\fB\-start\fR\0\fIindex\fR
.
The list is searched starting at position \fIindex\fR.
The interpretation of the \fIindex\fR value is the same as
for the command \fBstring index\fR, supporting simple index
arithmetic and indices relative to the end of the list.
.SS "CONTENTS DESCRIPTION OPTIONS"
.PP
These options describe how to interpret the items in the list being
searched.  They are only meaningful when used with the \fB\-exact\fR
and \fB\-sorted\fR options.  If more than one is specified, the last
one takes precedence.  The default is \fB\-ascii\fR.
.\" OPTION: -ascii
.TP
\fB\-ascii\fR
.
The list elements are to be examined as Unicode strings (the name is
for backward-compatibility reasons.)
.\" OPTION: -dictionary
.TP
\fB\-dictionary\fR
.
The list elements are to be compared using dictionary-style
comparisons (see \fBlsort\fR for a fuller description). Note that this
only makes a meaningful difference from the \fB\-ascii\fR option when
the \fB\-sorted\fR option is given, because values are only
dictionary-equal when exactly equal.
.\" OPTION: -integer
.TP
\fB\-integer\fR
.
The list elements are to be compared as integers.
.\" OPTION: -nocase
.TP
\fB\-nocase\fR
.
Causes comparisons to be handled in a case-insensitive manner.  Has no
effect if combined with the \fB\-dictionary\fR, \fB\-integer\fR, or
\fB\-real\fR options.
.\" OPTION: -real
.TP
\fB\-real\fR
.
The list elements are to be compared as floating-point values.
.SS "SORTED LIST OPTIONS"
.PP
These options (only meaningful with the \fB\-sorted\fR option) specify
how the list is sorted.  If more than one is given, the last one takes
precedence.  The default option is \fB\-increasing\fR.
.\" OPTION: -decreasing
.TP
\fB\-decreasing\fR
.
The list elements are sorted in decreasing order.  This option is only
meaningful when used with \fB\-sorted\fR.
.\" OPTION: -increasing
.TP
\fB\-increasing\fR
.
The list elements are sorted in increasing order.  This option is only
meaningful when used with \fB\-sorted\fR.
.\" OPTION: -bisect
.TP
\fB\-bisect\fR
.
Inexact search when the list elements are in sorted order. For an increasing
list the last index where the element is less than or equal to the pattern
is returned. For a decreasing list the last index where the element is greater
than or equal to the pattern is returned. If the pattern is before the first
element or the list is empty, -1 is returned.
This option implies \fB\-sorted\fR and cannot be used with either \fB\-all\fR
or \fB\-not\fR.
.SS "NESTED LIST OPTIONS"
.PP
These options are used to search lists of lists.  They may be used
with any other options.
.\" OPTION: -stride
.TP
\fB\-stride\0\fIstrideLength\fR
.
If this option is specified, the list is treated as consisting of
groups of \fIstrideLength\fR elements and the groups are searched by
either their first element or, if the \fB\-index\fR option is used,
by the element within each group given by the first index passed to
\fB\-index\fR (which is then ignored by \fB\-index\fR). The resulting
index always points to the first element in a group.
.PP
The list length must be an integer multiple of \fIstrideLength\fR, which
in turn must be at least 1. A \fIstrideLength\fR of 1 is the default and
indicates no grouping.
.\" OPTION: -index
.TP
\fB\-index\fR\0\fIindexList\fR
.
This option is designed for use when searching within nested lists.
The \fIindexList\fR argument gives a path of indices (much as might be
used with the \fBlindex\fR or \fBlset\fR commands) within each element
to allow the location of the term being matched against.
.\" OPTION: -subindices
.TP
\fB\-subindices\fR
.
If this option is given, the index result from this command (or every
index result when \fB\-all\fR is also specified) will be a complete
path (suitable for use with \fBlindex\fR or \fBlset\fR) within the
overall list to the term found.  This option has no effect unless the
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
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







-
-
+
+





-
-
+
+



-
+

-
+







\fBlsearch\fR -start 3 {a b c a b c} c
      \fI\(-> 5\fR
.CE
.PP
It is also possible to search inside elements:
.PP
.CS
\fBlsearch\fR -index 1 -all -inline {{a abc} {b bcd} {c cde}} *bc*
      \fI\(-> {a abc} {b bcd}\fR
\fBlsearch\fR -index 1 -all -inline {{abc abc} {abc bcd} {abc cde}} *bc*
      \fI\(-> {abc abc} {abc bcd}\fR
.CE
.PP
The same thing for a flattened list:
.PP
.CS
\fBlsearch\fR -stride 2 -index 1 -all -inline {a abc b bcd c cde} *bc*
      \fI\(-> {a abc b bcd}\fR
\fBlsearch\fR -stride 2 -index 1 -all -inline {abc abc abc bcd abc cde} *bc*
      \fI\(-> abc abc abc bcd\fR
.CE
.SH "SEE ALSO"
foreach(n),
list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n),
list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lset(n), lsort(n),
lreverse(n), lseq(n), lset(n), lsort(n),
string(n)
.SH KEYWORDS
binary search, linear search,
list, match, pattern, regular expression, search, string
'\" Local Variables:
'\" mode: nroff
'\" End:

Added doc/lseq.n.




























































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
'\"
'\" Copyright (c) 2022 Eric Taylor.  All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH lseq n 9.0 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
lseq \- Build a numeric sequence returned as a list
.SH SYNOPSIS
.nf
\fBlseq \fIstart \fR?(\fB..\fR|\fBto\fR)? \fIend\fR ??\fBby\fR? \fIstep\fR?
\fBlseq \fIstart \fBcount\fI count\fR ??\fBby\fR? \fIstep\fR?
\fBlseq \fIcount\fR ?\fBby \fIstep\fR?
.fi
.BE
.SH DESCRIPTION
.PP
The \fBlseq\fR command creates a sequence of numeric values using the given
parameters \fIstart\fR, \fIend\fR, and \fIstep\fR. The \fIoperation\fR
argument "\fB..\fR" or "\fBto\fR" defines the range. The "\fBcount\fR" option
is used to define a count of the number of elements in the list. A short form
use of the command, with a single count value, will create a range from 0 to
\fIcount\fR-1.
.PP
The \fBlseq\fR command can produce both increasing and decreasing
sequences. When both \fIstart\fR and \fIend\fR are provided without a
\fIstep\fR value, then if \fIstart\fR <= \fIend\fR, the sequence will be
increasing and if \fIstart\fR > \fIend\fR it will be decreasing. If a
\fIstep\fR vale is included, it's sign should agree with the direction of the
sequence (descending \(-> negative and ascending \(-> positive), otherwise an
empty list is returned.  For example:
.RS
.PP
.CS \"
% \fBlseq\fR 1 to 5    ;# increasing
\fI\(-> 1 2 3 4 5

% \fBlseq\fR 5 to 1    ;# decreasing
\fI\(-> 5 4 3 2 1

% \fBlseq\fR 6 to 1 by 2   ;# decreasing, step wrong sign, empty list

% \fBlseq\fR 1 to 5 by 0   ;# all step sizes of 0 produce an empty list
.\"
.CE
.RE
.PP
The numeric arguments, \fIstart\fR, \fIend\fR, \fIstep\fR, and \fIcount\fR,
may also be a valid expression. The expression will be evaluated and the
numeric result will be used.  An expression that does not evaluate to a number
will produce an invalid argument error.
.PP
\fIStart\fR defines the initial value and \fIend\fR defines the limit, not
necessarily the last value. \fBlseq\fR produces a list with \fIcount\fR
elements, and if \fIcount\fR is not supplied, it is computed as:
.RS
.PP
.CS
\fIcount\fR = int( (\fIend\fR - \fIstart\fR + \fIstep\fR) / \fIstep\fR )
.CE
.RE
.SH EXAMPLES
.CS
.\"
\fBlseq\fR 3
\fI\(-> 0 1 2\fR

\fBlseq\fR 3 0
\fI\(-> 3 2 1 0\fR

\fBlseq\fR 10 .. 1 by -2
\fI\(-> 10 8 6 4 2\fR

set l [\fBlseq\fR 0 -5]
\fI\(-> 0 -1 -2 -3 -4 -5\fR

foreach i [\fBlseq\fR [llength $l]] {
    puts l($i)=[lindex $l $i]
}
\fI\(-> l(0)=0\fR
\fI\(-> l(1)=-1\fR
\fI\(-> l(2)=-2\fR
\fI\(-> l(3)=-3\fR
\fI\(-> l(4)=-4\fR
\fI\(-> l(5)=-5\fR

foreach i [\fBlseq\fR {[llength $l]-1} 0] {
    puts l($i)=[lindex $l $i]
}
\fI\(-> l(5)=-5\fR
\fI\(-> l(4)=-4\fR
\fI\(-> l(3)=-3\fR
\fI\(-> l(2)=-2\fR
\fI\(-> l(1)=-1\fR
\fI\(-> l(0)=0\fR

set i 17
         \fI\(-> 17\fR
if {$i in [\fBlseq\fR 0 50]} { # equivalent to: (0 <= $i && $i <= 50)
    puts "Ok"
} else {
    puts "outside :("
}
\fI\(-> Ok\fR

set sqrs [lmap i [\fBlseq\fR 1 10] { expr {$i*$i} }]
\fI\(-> 1 4 9 16 25 36 49 64 81 100\fR
.\"
.CE
.SH "SEE ALSO"
foreach(n), list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n),
lmap(n), lpop(n), lrange(n), lremove(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n)
.SH KEYWORDS
element, index, list
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/lset.n.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







'\"
'\" Copyright (c) 2001 by Kevin B. Kenny <kennykb@acm.org>.  All rights reserved.
'\" Copyright (c) 2001 Kevin B. Kenny <kennykb@acm.org>.  All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH lset n 8.4 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
134
135
136
137
138
139
140
141

142
143

144
145
146
147
148
149
134
135
136
137
138
139
140

141
142

143
144
145
146
147
148
149







-
+

-
+






.CS
\fBlset\fR x 1 1 0 j
      \fI\(-> {{a b} {c d}} {{e f} {j h}}\fR
\fBlset\fR x {1 1 0} j
      \fI\(-> {{a b} {c d}} {{e f} {j h}}\fR
.CE
.SH "SEE ALSO"
list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n),
list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lsort(n)
lreverse(n), lsearch(n), lseq(n), lsort(n)
string(n)
.SH KEYWORDS
element, index, list, replace, set
'\"Local Variables:
'\"mode: nroff
'\"End:

Changes to doc/lsort.n.

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
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







-
+






+





+










+




+




+










+






+





+





+







.SH SYNOPSIS
\fBlsort \fR?\fIoptions\fR? \fIlist\fR
.BE
.SH DESCRIPTION
.PP
This command sorts the elements of \fIlist\fR, returning a new
list in sorted order.  The implementation of the \fBlsort\fR command
uses the merge\-sort algorithm which is a stable sort that has O(n log
uses the merge-sort algorithm which is a stable sort that has O(n log
n) performance characteristics.
.PP
By default ASCII sorting is used with the result returned in
increasing order.  However, any of the following options may be
specified before \fIlist\fR to control the sorting process (unique
abbreviations are accepted):
.\" OPTION: -ascii
.TP
\fB\-ascii\fR
.
Use string comparison with Unicode code-point collation order (the
name is for backward-compatibility reasons.)  This is the default.
.\" OPTION: -dictionary
.TP
\fB\-dictionary\fR
.
Use dictionary-style comparison.  This is the same as \fB\-ascii\fR
except (a) case is ignored except as a tie-breaker and (b) if two
strings contain embedded numbers, the numbers compare as integers,
not characters.  For example, in \fB\-dictionary\fR mode, \fBbigBoy\fR
sorts between \fBbigbang\fR and \fBbigboy\fR, and \fBx10y\fR
sorts between \fBx9y\fR and \fBx11y\fR. Overrides the \fB\-nocase\fR
option.
.\" OPTION: -integer
.TP
\fB\-integer\fR
.
Convert list elements to integers and use integer comparison.
.\" OPTION: -real
.TP
\fB\-real\fR
.
Convert list elements to floating-point values and use floating comparison.
.\" OPTION: -command
.TP
\fB\-command\0\fIcommand\fR
.
Use \fIcommand\fR as a comparison command.
To compare two elements, evaluate a Tcl script consisting of
\fIcommand\fR with the two elements appended as additional
arguments.  The script should return an integer less than,
equal to, or greater than zero if the first element is to
be considered less than, equal to, or greater than the second,
respectively.
.\" OPTION: -increasing
.TP
\fB\-increasing\fR
.
Sort the list in increasing order
.PQ smallest "items first" .
This is the default.
.\" OPTION: -decreasing
.TP
\fB\-decreasing\fR
.
Sort the list in decreasing order
.PQ largest "items first" .
.\" OPTION: -indices
.TP
\fB\-indices\fR
.
Return a list of indices into \fIlist\fR in sorted order instead of
the values themselves.
.\" OPTION: -index
.TP
\fB\-index\0\fIindexList\fR
.
If this option is specified, each of the elements of \fIlist\fR must
itself be a proper Tcl sublist (unless \fB\-stride\fR is used).
Instead of sorting based on whole sublists, \fBlsort\fR will extract
the \fIindexList\fR'th element from each sublist (as if the overall
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
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







+

















-
+







-
+





+






+







.CE
.PP
returns \fB{{d e m o} 34512} {{b i g} 12345} {{c o d e} 54321}\fR
(because \fBe\fR sorts before \fBi\fR which sorts before \fBo\fR.)
This option is much more efficient than using \fB\-command\fR
to achieve the same effect.
.RE
.\" OPTION: -stride
.TP
\fB\-stride\0\fIstrideLength\fR
.
If this option is specified, the list is treated as consisting of
groups of \fIstrideLength\fR elements and the groups are sorted by
either their first element or, if the \fB\-index\fR option is used,
by the element within each group given by the first index passed to
\fB\-index\fR (which is then ignored by \fB\-index\fR). Elements
always remain in the same position within their group.
.RS
.PP
The list length must be an integer multiple of \fIstrideLength\fR, which
in turn must be at least 2.
.PP
For example,
.PP
.CS
\fBlsort\fR \-stride 2 {carrot 10 apple 50 banana 25}
\fBlsort\fR -stride 2 {carrot 10 apple 50 banana 25}
.CE
.PP
returns
.QW "apple 50 banana 25 carrot 10" ,
and
.PP
.CS
\fBlsort\fR \-stride 2 \-index 1 \-integer {carrot 10 apple 50 banana 25}
\fBlsort\fR -stride 2 -index 1 -integer {carrot 10 apple 50 banana 25}
.CE
.PP
returns
.QW "carrot 10 banana 25 apple 50" .
.RE
.\" OPTION: -nocase
.TP
\fB\-nocase\fR
.
Causes comparisons to be handled in a case-insensitive manner.  Has no
effect if combined with the \fB\-dictionary\fR, \fB\-integer\fR, or
\fB\-real\fR options.
.\" OPTION: -unique
.TP
\fB\-unique\fR
.
If this option is specified, then only the last set of duplicate
elements found in the list will be retained.  Note that duplicates are
determined relative to the comparison used in the sort.  Thus if
\fB\-index 0\fR is used, \fB{1 a}\fR and \fB{1 b}\fR would be
230
231
232
233
234
235
236
237

238
239
240
241
242
243
244
242
243
244
245
246
247
248

249
250
251
252
253
254
255
256







-
+







a b c e f g h i
.CE
.PP
Sorting using striding and multiple indices:
.PP
.CS
\fI%\fR # Note the first index value is relative to the group
\fI%\fR \fBlsort\fR \-stride 3 \-index {0 1} \e
\fI%\fR \fBlsort\fR -stride 3 -index {0 1} \e
     {{Bob Smith} 25 Audi {Jane Doe} 40 Ford}
{{Jane Doe} 40 Ford {Bob Smith} 25 Audi}
.CE
.PP
Stripping duplicate values using sorting:
.PP
.CS
260
261
262
263
264
265
266
267

268
269

270
271
272
273
274
272
273
274
275
276
277
278

279
280

281
282
283
284
285
286







-
+

-
+





    return [string compare [lindex $a 1] [lindex $b 1]]
}
\fI%\fR \fBlsort\fR -command compare \e
        {{3 apple} {0x2 carrot} {1 dingo} {2 banana}}
{1 dingo} {2 banana} {0x2 carrot} {3 apple}
.CE
.SH "SEE ALSO"
list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n),
list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n)
lreverse(n), lsearch(n), lseq(n), lset(n)
.SH KEYWORDS
element, list, order, sort
'\" Local Variables:
'\" mode: nroff
'\" End:

Changes to doc/mathfunc.n.

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
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
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


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



-
+











+
-
-
-
+
+
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
+
-
-
-

-
+
-
-
+
-
-
+
-
-
+

-
-
+
-

-
+
-
-
+

-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-

-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
-
+
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-2000 Sun Microsystems, Inc.
'\" Copyright (c) 2005 by Kevin B. Kenny <kennykb@acm.org>. All rights reserved
'\" Copyright (c) 2005 Kevin B. Kenny <kennykb@acm.org>. All rights reserved
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH mathfunc n 8.5 Tcl "Tcl Mathematical Functions"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
mathfunc \- Mathematical functions for Tcl expressions
.SH SYNOPSIS
.nf
package require \fBTcl 8.5\fR
.sp
\fB::tcl::mathfunc::abs\fR \fIarg\fR
package require \fBTcl 8.5-\fR

\fB::tcl::mathfunc::abs\fI arg\fR
.br
\fB::tcl::mathfunc::acos\fR \fIarg\fR
\fB::tcl::mathfunc::acos\fI arg\fR
.br
\fB::tcl::mathfunc::asin\fR \fIarg\fR
\fB::tcl::mathfunc::asin\fI arg\fR
.br
\fB::tcl::mathfunc::atan\fR \fIarg\fR
\fB::tcl::mathfunc::atan\fI arg\fR
.br
\fB::tcl::mathfunc::atan2\fR \fIy\fR \fIx\fR
\fB::tcl::mathfunc::atan2\fI y x\fR
.br
\fB::tcl::mathfunc::bool\fR \fIarg\fR
\fB::tcl::mathfunc::bool\fI arg\fR
.br
\fB::tcl::mathfunc::ceil\fR \fIarg\fR
\fB::tcl::mathfunc::ceil\fI arg\fR
.br
\fB::tcl::mathfunc::cos\fR \fIarg\fR
\fB::tcl::mathfunc::cos\fI arg\fR
.br
\fB::tcl::mathfunc::cosh\fR \fIarg\fR
\fB::tcl::mathfunc::cosh\fI arg\fR
.br
\fB::tcl::mathfunc::double\fR \fIarg\fR
\fB::tcl::mathfunc::double\fI arg\fR
.br
\fB::tcl::mathfunc::entier\fR \fIarg\fR
\fB::tcl::mathfunc::entier\fI arg\fR
.br
\fB::tcl::mathfunc::exp\fR \fIarg\fR
\fB::tcl::mathfunc::exp\fI arg\fR
.br
\fB::tcl::mathfunc::floor\fR \fIarg\fR
\fB::tcl::mathfunc::floor\fI arg\fR
.br
\fB::tcl::mathfunc::fmod\fR \fIx\fR \fIy\fR
\fB::tcl::mathfunc::fmod\fI x y\fR
.br
\fB::tcl::mathfunc::hypot\fR \fIx\fR \fIy\fR
\fB::tcl::mathfunc::hypot\fI x y\fR
\fB::tcl::mathfunc::int\fI arg\fR
.br
\fB::tcl::mathfunc::int\fR \fIarg\fR
.br
.VS "8.7, TIP 521"
\fB::tcl::mathfunc::isfinite\fR \fIarg\fR
\fB::tcl::mathfunc::isfinite\fI arg\fR
.br
\fB::tcl::mathfunc::isinf\fR \fIarg\fR
\fB::tcl::mathfunc::isinf\fI arg\fR
.br
\fB::tcl::mathfunc::isnan\fR \fIarg\fR
\fB::tcl::mathfunc::isnan\fI arg\fR
.br
\fB::tcl::mathfunc::isnormal\fR \fIarg\fR
\fB::tcl::mathfunc::isnormal\fI arg\fR
.VE "8.7, TIP 521"
.br
\fB::tcl::mathfunc::isqrt\fR \fIarg\fR
\fB::tcl::mathfunc::isqrt\fI arg\fR
.br
.VS "8.7, TIP 521"
\fB::tcl::mathfunc::issubnormal\fR \fIarg\fR
\fB::tcl::mathfunc::issubnormal\fI arg\fR
.br
\fB::tcl::mathfunc::isunordered\fR \fIx y\fR
\fB::tcl::mathfunc::isunordered\fI x y\fR
.VE "8.7, TIP 521"
.br
\fB::tcl::mathfunc::log\fR \fIarg\fR
\fB::tcl::mathfunc::log\fI arg\fR
.br
\fB::tcl::mathfunc::log10\fR \fIarg\fR
\fB::tcl::mathfunc::log10\fI arg\fR
.br
\fB::tcl::mathfunc::max\fR \fIarg\fR ?\fIarg\fR ...?
\fB::tcl::mathfunc::max\fI arg\fR ?\fIarg\fR ...?
.br
\fB::tcl::mathfunc::min\fR \fIarg\fR ?\fIarg\fR ...?
\fB::tcl::mathfunc::min\fI arg\fR ?\fIarg\fR ...?
.br
\fB::tcl::mathfunc::pow\fR \fIx\fR \fIy\fR
\fB::tcl::mathfunc::pow\fI x y\fR
.br
\fB::tcl::mathfunc::rand\fR
.br
\fB::tcl::mathfunc::round\fR \fIarg\fR
\fB::tcl::mathfunc::round\fI arg\fR
.br
\fB::tcl::mathfunc::sin\fR \fIarg\fR
\fB::tcl::mathfunc::sin\fI arg\fR
.br
\fB::tcl::mathfunc::sinh\fR \fIarg\fR
\fB::tcl::mathfunc::sinh\fI arg\fR
.br
\fB::tcl::mathfunc::sqrt\fR \fIarg\fR
\fB::tcl::mathfunc::sqrt\fI arg\fR
.br
\fB::tcl::mathfunc::srand\fR \fIarg\fR
\fB::tcl::mathfunc::srand\fI arg\fR
.br
\fB::tcl::mathfunc::tan\fR \fIarg\fR
\fB::tcl::mathfunc::tan\fI arg\fR
.br
\fB::tcl::mathfunc::tanh\fR \fIarg\fR
\fB::tcl::mathfunc::tanh\fI arg\fR
.br
\fB::tcl::mathfunc::wide\fR \fIarg\fR
.sp
\fB::tcl::mathfunc::wide\fI arg\fR
.fi
.BE
.SH "DESCRIPTION"
.PP
The \fBexpr\fR command handles mathematical functions of the form
\fBsin($x)\fR or \fBatan2($y,$x)\fR by converting them to calls of the
form \fB[tcl::mathfunc::sin [expr {$x}]]\fR or
\fB[tcl::mathfunc::atan2 [expr {$y}] [expr {$x}]]\fR.
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
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
366
367







+





+





+





+





+







+








+






+




+





+








+







+





+






+





+








+








+







+







+







+







+







+








+









+





+





+





+





+





+










+





+




+





+







+






+




+




+












-
+





.DE
.PP
In addition to these predefined functions, applications may
define additional functions by using \fBproc\fR (or any other method,
such as \fBinterp alias\fR or \fBTcl_CreateObjCommand\fR) to define
new commands in the \fBtcl::mathfunc\fR namespace.
.SS "DETAILED DEFINITIONS"
.\" COMMAND: abs
.TP
\fBabs \fIarg\fR
.
Returns the absolute value of \fIarg\fR.  \fIArg\fR may be either
integer or floating-point, and the result is returned in the same form.
.\" COMMAND: acos
.TP
\fBacos \fIarg\fR
.
Returns the arc cosine of \fIarg\fR, in the range [\fI0\fR,\fIpi\fR]
radians. \fIArg\fR should be in the range [\fI\-1\fR,\fI1\fR].
.\" COMMAND: asin
.TP
\fBasin \fIarg\fR
.
Returns the arc sine of \fIarg\fR, in the range [\fI\-pi/2\fR,\fIpi/2\fR]
radians.  \fIArg\fR should be in the range [\fI\-1\fR,\fI1\fR].
.\" COMMAND: atan
.TP
\fBatan \fIarg\fR
.
Returns the arc tangent of \fIarg\fR, in the range [\fI\-pi/2\fR,\fIpi/2\fR]
radians.
.\" COMMAND: atan2
.TP
\fBatan2 \fIy x\fR
.
Returns the arc tangent of \fIy\fR/\fIx\fR, in the range [\fI\-pi\fR,\fIpi\fR]
radians.  \fIx\fR and \fIy\fR cannot both be 0.  If \fIx\fR is greater
than \fI0\fR, this is equivalent to
.QW "\fBatan \fR[\fBexpr\fR {\fIy\fB/\fIx\fR}]" .
.\" COMMAND: bool
.TP
\fBbool \fIarg\fR
.
Accepts any numeric value, or any string acceptable to
\fBstring is boolean\fR, and returns the corresponding
boolean value \fB0\fR or \fB1\fR.  Non-zero numbers are true.
Other numbers are false.  Non-numeric strings produce boolean value in
agreement with \fBstring is true\fR and \fBstring is false\fR.
.\" COMMAND: ceil
.TP
\fBceil \fIarg\fR
.
Returns the smallest integral floating-point value (i.e. with a zero
fractional part) not less than \fIarg\fR.  The argument may be any
numeric value.
.\" COMMAND: cos
.TP
\fBcos \fIarg\fR
.
Returns the cosine of \fIarg\fR, measured in radians.
.\" COMMAND: cosh
.TP
\fBcosh \fIarg\fR
.
Returns the hyperbolic cosine of \fIarg\fR.  If the result would cause
an overflow, an error is returned.
.\" COMMAND: double
.TP
\fBdouble \fIarg\fR
.
The argument may be any numeric value,
If \fIarg\fR is a floating-point value, returns \fIarg\fR, otherwise converts
\fIarg\fR to floating-point and returns the converted value.  May return
\fBInf\fR or \fB\-Inf\fR when the argument is a numeric value that exceeds
the floating-point range.
.\" COMMAND: entier
.TP
\fBentier \fIarg\fR
.
The argument may be any numeric value.  The integer part of \fIarg\fR
is determined and returned.  The integer range returned by this function
is unlimited, unlike \fBint\fR and \fBwide\fR which
truncate their range to fit in particular storage widths.
.\" COMMAND: exp
.TP
\fBexp \fIarg\fR
.
Returns the exponential of \fIarg\fR, defined as \fIe\fR**\fIarg\fR.
If the result would cause an overflow, an error is returned.
.\" COMMAND: floor
.TP
\fBfloor \fIarg\fR
.
Returns the largest integral floating-point value (i.e. with a zero
fractional part) not greater than \fIarg\fR.  The argument may be
any numeric value.
.\" COMMAND: fmod
.TP
\fBfmod \fIx y\fR
.
Returns the floating-point remainder of the division of \fIx\fR by
\fIy\fR.  If \fIy\fR is 0, an error is returned.
.\" COMMAND: hypot
.TP
\fBhypot \fIx y\fR
.
Computes the length of the hypotenuse of a right-angled triangle,
approximately
.QW "\fBsqrt\fR [\fBexpr\fR {\fIx\fB*\fIx\fB+\fIy\fB*\fIy\fR}]"
except for being more numerically stable when the two arguments have
substantially different magnitudes.
.\" COMMAND: int
.TP
\fBint \fIarg\fR
.
The argument may be any numeric value.  The integer part of \fIarg\fR
is determined, and then the low order bits of that integer value up
to the machine word size are returned as an integer value.  For reference,
the number of bytes in the machine word are stored in the \fBwordSize\fR
element of the \fBtcl_platform\fR array.
.\" COMMAND: isfinite
.TP
\fBisfinite \fIarg\fR
.VS "8.7, TIP 521"
Returns 1 if the floating-point number \fIarg\fR is finite. That is, if it is
zero, subnormal, or normal. Returns 0 if the number is infinite or NaN. Throws
an error if \fIarg\fR cannot be promoted to a floating-point value.
.VE "8.7, TIP 521"
.\" COMMAND: isinf
.TP
\fBisinf \fIarg\fR
.VS "8.7, TIP 521"
Returns 1 if the floating-point number \fIarg\fR is infinite. Returns 0 if the
number is finite or NaN. Throws an error if \fIarg\fR cannot be promoted to a
floating-point value.
.VE "8.7, TIP 521"
.\" COMMAND: isnan
.TP
\fBisnan \fIarg\fR
.VS "8.7, TIP 521"
Returns 1 if the floating-point number \fIarg\fR is Not-a-Number. Returns 0 if
the number is finite or infinite. Throws an error if \fIarg\fR cannot be
promoted to a floating-point value.
.VE "8.7, TIP 521"
.\" COMMAND: isnormal
.TP
\fBisnormal \fIarg\fR
.VS "8.7, TIP 521"
Returns 1 if the floating-point number \fIarg\fR is normal. Returns 0 if the
number is zero, subnormal, infinite or NaN. Throws an error if \fIarg\fR
cannot be promoted to a floating-point value.
.VE "8.7, TIP 521"
.\" COMMAND: isqrt
.TP
\fBisqrt \fIarg\fR
.
Computes the integer part of the square root of \fIarg\fR.  \fIArg\fR must be
a positive value, either an integer or a floating point number.
Unlike \fBsqrt\fR, which is limited to the precision of a floating point
number, \fIisqrt\fR will return a result of arbitrary precision.
.\" COMMAND: issubnormal
.TP
\fBissubnormal \fIarg\fR
.VS "8.7, TIP 521"
Returns 1 if the floating-point number \fIarg\fR is subnormal, i.e., the
result of gradual underflow. Returns 0 if the number is zero, normal, infinite
or NaN. Throws an error if \fIarg\fR cannot be promoted to a floating-point
value.
.VE "8.7, TIP 521"
.\" COMMAND: isunordered
.TP
\fBisunordered \fIx y\fR
.VS "8.7, TIP 521"
Returns 1 if \fIx\fR and \fIy\fR cannot be compared for ordering, that is, if
either one is NaN. Returns 0 if both values can be ordered, that is, if they
are both chosen from among the set of zero, subnormal, normal and infinite
values. Throws an error if either \fIx\fR or \fIy\fR cannot be promoted to a
floating-point value.
.VE "8.7, TIP 521"
.\" COMMAND: log
.TP
\fBlog \fIarg\fR
.
Returns the natural logarithm of \fIarg\fR.  \fIArg\fR must be a
positive value.
.\" COMMAND: log10
.TP
\fBlog10 \fIarg\fR
.
Returns the base 10 logarithm of \fIarg\fR.  \fIArg\fR must be a
positive value.
.\" COMMAND: max
.TP
\fBmax \fIarg\fB \fI...\fR
.
Accepts one or more numeric arguments.  Returns the one argument
with the greatest value.
.\" COMMAND: min
.TP
\fBmin \fIarg\fB \fI...\fR
.
Accepts one or more numeric arguments.  Returns the one argument
with the least value.
.\" COMMAND: pow
.TP
\fBpow \fIx y\fR
.
Computes the value of \fIx\fR raised to the power \fIy\fR.  If \fIx\fR
is negative, \fIy\fR must be an integer value.
.\" COMMAND: rand
.TP
\fBrand\fR
.
Returns a pseudo-random floating-point value in the range (\fI0\fR,\fI1\fR).
The generator algorithm is a simple linear congruential generator that
is not cryptographically secure.  Each result from \fBrand\fR completely
determines all future results from subsequent calls to \fBrand\fR, so
\fBrand\fR should not be used to generate a sequence of secrets, such as
one-time passwords.  The seed of the generator is initialized from the
internal clock of the machine or may be set with the \fBsrand\fR function.
.\" COMMAND: round
.TP
\fBround \fIarg\fR
.
If \fIarg\fR is an integer value, returns \fIarg\fR, otherwise converts
\fIarg\fR to integer by rounding and returns the converted value.
.\" COMMAND: sin
.TP
\fBsin \fIarg\fR
.
Returns the sine of \fIarg\fR, measured in radians.
.\" COMMAND: sinh
.TP
\fBsinh \fIarg\fR
.
Returns the hyperbolic sine of \fIarg\fR.  If the result would cause
an overflow, an error is returned.
.\" COMMAND: sqrt
.TP
\fBsqrt \fIarg\fR
.
The argument may be any non-negative numeric value.  Returns a floating-point
value that is the square root of \fIarg\fR.  May return \fBInf\fR when the
argument is a numeric value that exceeds the square of the maximum value of
the floating-point range.
.\" COMMAND: srand
.TP
\fBsrand \fIarg\fR
.
The \fIarg\fR, which must be an integer, is used to reset the seed for
the random number generator of \fBrand\fR.  Returns the first random
number (see \fBrand\fR) from that seed.  Each interpreter has its own seed.
.\" COMMAND: tan
.TP
\fBtan \fIarg\fR
.
Returns the tangent of \fIarg\fR, measured in radians.
.\" COMMAND: tanh
.TP
\fBtanh \fIarg\fR
.
Returns the hyperbolic tangent of \fIarg\fR.
.\" COMMAND: wide
.TP
\fBwide \fIarg\fR
.
The argument may be any numeric value.  The integer part of \fIarg\fR
is determined, and then the low order 64 bits of that integer value
are returned as an integer value.
.SH "SEE ALSO"
expr(n), fpclassify(n), mathop(n), namespace(n)
.SH "COPYRIGHT"
.nf
Copyright \(co 1993 The Regents of the University of California.
Copyright \(co 1994-2000 Sun Microsystems Incorporated.
Copyright \(co 2005, 2006 by Kevin B. Kenny <kennykb@acm.org>.
Copyright \(co 2005-2006 Kevin B. Kenny <kennykb@acm.org>.
.fi
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/mathop.n.

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
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
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

30


31

32

33

34

35

36


37

38
39

40

41

42
43


44



45
46
47
48
49
50
51
52
53













+
-
-
-
+
+
+
-
-
+
-

-
-
+
-

-
-
+
-
-
+
-

-

-

-

-
-
+
-
-
+
-

-
-
+
-

-

-

-

-

-
-
+
-


-

-

-


-
-
+
-
-
-
+
+







.\"
.\" Copyright (c) 2006-2007 Donal K. Fellows.
.\"
.\" See the file "license.terms" for information on usage and redistribution
.\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
.\"
.TH mathop n 8.5 Tcl "Tcl Mathematical Operator Commands"
.so man.macros
.BS
.\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
mathop \- Mathematical operators as Tcl commands
.SH SYNOPSIS
.nf
package require \fBTcl 8.5\fR
.sp
\fB::tcl::mathop::!\fR \fInumber\fR
package require \fBTcl 8.5-\fR

\fB::tcl::mathop::!\fI number\fR
.br
\fB::tcl::mathop::~\fR \fInumber\fR
\fB::tcl::mathop::~\fI number\fR
.br
\fB::tcl::mathop::+\fR ?\fInumber\fR ...?
.br
\fB::tcl::mathop::\-\fR \fInumber\fR ?\fInumber\fR ...?
\fB::tcl::mathop::\-\fI number\fR ?\fInumber\fR ...?
.br
\fB::tcl::mathop::*\fR ?\fInumber\fR ...?
.br
\fB::tcl::mathop::/\fR \fInumber\fR ?\fInumber\fR ...?
\fB::tcl::mathop::/\fI number\fR ?\fInumber\fR ...?
.br
\fB::tcl::mathop::%\fR \fInumber number\fR
\fB::tcl::mathop::%\fI number number\fR
.br
\fB::tcl::mathop::**\fR ?\fInumber\fR ...?
.br
\fB::tcl::mathop::&\fR ?\fInumber\fR ...?
.br
\fB::tcl::mathop::|\fR ?\fInumber\fR ...?
.br
\fB::tcl::mathop::^\fR ?\fInumber\fR ...?
.br
\fB::tcl::mathop::<<\fR \fInumber number\fR
\fB::tcl::mathop::<<\fI number number\fR
.br
\fB::tcl::mathop::>>\fR \fInumber number\fR
\fB::tcl::mathop::>>\fI number number\fR
.br
\fB::tcl::mathop::==\fR ?\fIarg\fR ...?
.br
\fB::tcl::mathop::!=\fR \fIarg arg\fR
\fB::tcl::mathop::!=\fI arg arg\fR
.br
\fB::tcl::mathop::<\fR ?\fIarg\fR ...?
.br
\fB::tcl::mathop::<=\fR ?\fIarg\fR ...?
.br
\fB::tcl::mathop::>=\fR ?\fIarg\fR ...?
.br
\fB::tcl::mathop::>\fR ?\fIarg\fR ...?
.br
\fB::tcl::mathop::eq\fR ?\fIarg\fR ...?
.br
\fB::tcl::mathop::ne\fR \fIarg arg\fR
\fB::tcl::mathop::ne\fI arg arg\fR
.br
.VS "8.7, TIP461"
\fB::tcl::mathop::lt\fR ?\fIarg\fR ...?
.br
\fB::tcl::mathop::le\fR ?\fIarg\fR ...?
.br
\fB::tcl::mathop::gt\fR ?\fIarg\fR ...?
.br
\fB::tcl::mathop::ge\fR ?\fIarg\fR ...?
.VE "8.7, TIP461"
.br
\fB::tcl::mathop::in\fR \fIarg list\fR
\fB::tcl::mathop::in\fI arg list\fR
.br
\fB::tcl::mathop::ni\fR \fIarg list\fR
.sp
\fB::tcl::mathop::ni\fI arg list\fR
.fi
.BE
.SH DESCRIPTION
.PP
The commands in the \fB::tcl::mathop\fR namespace implement the same set of
operations as supported by the \fBexpr\fR command. All are exported from the
namespace, but are not imported into any other namespace by default. Note that
renaming, reimplementing or deleting any of the commands in the namespace does
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
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







+

-
+





+






+

-
+





+






+

-
+














+

-
+
















+



















+







+






+

-
+




+

-
+



+










+










+










+










+








+








+








+












+

-
+




+






+






+






+

-
+




+

-
+







+

-
+



+

-
+







\fB!=\fR	\fBne\fR	\fB<\fR	\fB<=\fR	\fB>\fR
\fB>=\fR	\fBin\fR	\fBni\fR	\fBlt\fR	\fBle\fR
\fBgt\fR	\fBge\fR
.DE
.SS "MATHEMATICAL OPERATORS"
.PP
The behaviors of the mathematical operator commands are as follows:
.\" COMMAND: !
.TP
\fB!\fR \fIboolean\fR
\fB!\fI boolean\fR
.
Returns the boolean negation of \fIboolean\fR, where \fIboolean\fR may be any
numeric value or any other form of boolean value (i.e. it returns truth if the
argument is falsity or zero, and falsity if the argument is truth or
non-zero).
.\" COMMAND: +
.TP
\fB+\fR ?\fInumber\fR ...?
.
Returns the sum of arbitrarily many arguments. Each \fInumber\fR argument may
be any numeric value. If no arguments are given, the result will be zero (the
summation identity).
.\" COMMAND: -
.TP
\fB\-\fR \fInumber\fR ?\fInumber\fR ...?
\fB\-\fI number\fR ?\fInumber\fR ...?
.
If only a single \fInumber\fR argument is given, returns the negation of that
numeric value. Otherwise returns the number that results when all subsequent
numeric values are subtracted from the first one. All \fInumber\fR arguments
must be numeric values. At least one argument must be given.
.\" COMMAND: *
.TP
\fB*\fR ?\fInumber\fR ...?
.
Returns the product of arbitrarily many arguments. Each \fInumber\fR may be
any numeric value. If no arguments are given, the result will be one (the
multiplicative identity).
.\" COMMAND: /
.TP
\fB/\fR \fInumber\fR ?\fInumber\fR ...?
\fB/\fI number\fR ?\fInumber\fR ...?
.
If only a single \fInumber\fR argument is given, returns the reciprocal of that
numeric value (i.e. the value obtained by dividing 1.0 by that value).
Otherwise returns the number that results when the first numeric argument is
divided by all subsequent numeric arguments. All \fInumber\fR arguments must
be numeric values. At least one argument must be given.
.RS
.PP
Note that when the leading values in the list of arguments are integers,
integer division will be used for those initial steps (i.e. the intermediate
results will be as if the functions \fIfloor\fR and \fIint\fR are applied to
them, in that order). If all values in the operation are integers, the result
will be an integer.
.RE
.\" COMMAND: %
.TP
\fB%\fR \fInumber number\fR
\fB%\fI number number\fR
.
Returns the integral modulus (i.e., remainder) of the first argument
with respect to the second.
Each \fInumber\fR must have an integral value.
Also, the sign of the result will be the same as the sign of the second
\fInumber\fR, which must not be zero.
.RS
.PP
Note that Tcl defines this operation exactly even for negative numbers, so
that the following command returns a true value (omitting the namespace for
clarity):
.PP
.CS
\fB==\fR [\fB*\fR [\fB/\fI x y\fR] \fIy\fR] [\fB\-\fI x\fR [\fB%\fI x y\fR]]
.CE
.RE
.\" COMMAND: **
.TP
\fB**\fR ?\fInumber\fR ...?
.
Returns the result of raising each value to the power of the result of
recursively operating on the result of processing the following arguments, so
.QW "\fB** 2 3 4\fR"
is the same as
.QW "\fB** 2 [** 3 4]\fR" .
Each \fInumber\fR may be
any numeric value, though the second number must not be fractional if the
first is negative.  The maximum exponent value that Tcl can handle if the
first number is an integer > 1 is 268435455. If no arguments are given,
the result will be one, and if only one argument is given, the result will
be that argument. The result will have an integral value only when all
arguments are integral values.
.SS "COMPARISON OPERATORS"
.PP
The behaviors of the comparison operator commands (most of which operate
preferentially on numeric arguments) are as follows:
.\" COMMAND: ==
.TP
\fB==\fR ?\fIarg\fR ...?
.
Returns whether each argument is equal to the arguments on each side of it in
the sense of the \fBexpr\fR == operator (\fIi.e.\fR, numeric comparison if
possible, exact string comparison otherwise). If fewer than two arguments
are given, this operation always returns a true value.
.\" COMMAND: eq
.TP
\fBeq\fR ?\fIarg\fR ...?
.
Returns whether each argument is equal to the arguments on each side of it
using exact string comparison. If fewer than two arguments are given, this
operation always returns a true value.
.\" COMMAND: !=
.TP
\fB!=\fR \fIarg arg\fR
\fB!=\fI arg arg\fR
.
Returns whether the two arguments are not equal to each other, in the sense of
the \fBexpr\fR != operator (\fIi.e.\fR, numeric comparison if possible, exact
string comparison otherwise).
.\" COMMAND: ne
.TP
\fBne\fR \fIarg arg\fR
\fBne\fI arg arg\fR
.
Returns whether the two arguments are not equal to each other using exact
string comparison.
.\" COMMAND: <
.TP
\fB<\fR ?\fIarg\fR ...?
.
Returns whether the arbitrarily-many arguments are ordered, with each argument
after the first having to be strictly more than the one preceding it.
Comparisons are performed preferentially on the numeric values, and are
otherwise performed using UNICODE string comparison. If fewer than two
arguments are present, this operation always returns a true value. When the
arguments are numeric but should be compared as strings, the \fBlt\fR
operator or the \fBstring compare\fR command should be used instead.
.\" COMMAND: <=
.TP
\fB<=\fR ?\fIarg\fR ...?
.
Returns whether the arbitrarily-many arguments are ordered, with each argument
after the first having to be equal to or more than the one preceding it.
Comparisons are performed preferentially on the numeric values, and are
otherwise performed using UNICODE string comparison. If fewer than two
arguments are present, this operation always returns a true value. When the
arguments are numeric but should be compared as strings,  the \fBle\fR
operator or the \fBstring compare\fR command should be used instead.
.\" COMMAND: >
.TP
\fB>\fR ?\fIarg\fR ...?
.
Returns whether the arbitrarily-many arguments are ordered, with each argument
after the first having to be strictly less than the one preceding it.
Comparisons are performed preferentially on the numeric values, and are
otherwise performed using UNICODE string comparison. If fewer than two
arguments are present, this operation always returns a true value. When the
arguments are numeric but should be compared as strings, the \fBgt\fR
operator or the \fBstring compare\fR command should be used instead.
.\" COMMAND: >=
.TP
\fB>=\fR ?\fIarg\fR ...?
.
Returns whether the arbitrarily-many arguments are ordered, with each argument
after the first having to be equal to or less than the one preceding it.
Comparisons are performed preferentially on the numeric values, and are
otherwise performed using UNICODE string comparison. If fewer than two
arguments are present, this operation always returns a true value. When the
arguments are numeric but should be compared as strings, the \fBge\fR
operator or the \fBstring compare\fR command should be used instead.
.\" COMMAND: lt
.TP
\fBlt\fR ?\fIarg\fR ...?
.VS "8.7, TIP461"
Returns whether the arbitrarily-many arguments are ordered, with each argument
after the first having to be strictly more than the one preceding it.
Comparisons are performed using UNICODE string comparison. If fewer than two
arguments are present, this operation always returns a true value.
.VE "8.7, TIP461"
.\" COMMAND: le
.TP
\fBle\fR ?\fIarg\fR ...?
.VS "8.7, TIP461"
Returns whether the arbitrarily-many arguments are ordered, with each argument
after the first having to be equal to or strictly more than the one preceding it.
Comparisons are performed using UNICODE string comparison. If fewer than two
arguments are present, this operation always returns a true value.
.VE "8.7, TIP461"
.\" COMMAND: gt
.TP
\fBgt\fR ?\fIarg\fR ...?
.VS "8.7, TIP461"
Returns whether the arbitrarily-many arguments are ordered, with each argument
after the first having to be strictly less than the one preceding it.
Comparisons are performed using UNICODE string comparison. If fewer than two
arguments are present, this operation always returns a true value.
.VE "8.7, TIP461"
.\" COMMAND: ge
.TP
\fBge\fR ?\fIarg\fR ...?
.VS "8.7, TIP461"
Returns whether the arbitrarily-many arguments are ordered, with each argument
after the first having to be equal to or strictly less than the one preceding it.
Comparisons are performed using UNICODE string comparison. If fewer than two
arguments are present, this operation always returns a true value.
.VE "8.7, TIP461"
.SS "BIT-WISE OPERATORS"
.PP
The behaviors of the bit-wise operator commands (all of which only operate on
integral arguments) are as follows:
.\" COMMAND: ~
.TP
\fB~\fR \fInumber\fR
\fB~\fI number\fR
.
Returns the bit-wise negation of \fInumber\fR. \fINumber\fR may be an integer
of any size. Note that the result of this operation will always have the
opposite sign to the input \fInumber\fR.
.\" COMMAND: &
.TP
\fB&\fR ?\fInumber\fR ...?
.
Returns the bit-wise AND of each of the arbitrarily many arguments. Each
\fInumber\fR must have an integral value. If no arguments are given, the
result will be minus one.
.\" COMMAND: |
.TP
\fB|\fR ?\fInumber\fR ...?
.
Returns the bit-wise OR of each of the arbitrarily many arguments. Each
\fInumber\fR must have an integral value. If no arguments are given, the
result will be zero.
.\" COMMAND: ^
.TP
\fB^\fR ?\fInumber\fR ...?
.
Returns the bit-wise XOR of each of the arbitrarily many arguments. Each
\fInumber\fR must have an integral value. If no arguments are given, the
result will be zero.
.\" COMMAND: <<
.TP
\fB<<\fR \fInumber number\fR
\fB<<\fI number number\fR
.
Returns the result of bit-wise shifting the first argument left by the
number of bits specified in the second argument. Each \fInumber\fR
must have an integral value.
.\" COMMAND: >>
.TP
\fB>>\fR \fInumber number\fR
\fB>>\fI number number\fR
.
Returns the result of bit-wise shifting the first argument right by
the number of bits specified in the second argument. Each \fInumber\fR
must have an integral value.
.SS "LIST OPERATORS"
.PP
The behaviors of the list-oriented operator commands are as follows:
.\" COMMAND: in
.TP
\fBin\fR \fIarg list\fR
\fBin\fI arg list\fR
.
Returns whether the value \fIarg\fR is present in the list \fIlist\fR
(according to exact string comparison of elements).
.\" COMMAND: ni
.TP
\fBni\fR \fIarg list\fR
\fBni\fI arg list\fR
.
Returns whether the value \fIarg\fR is not present in the list \fIlist\fR
(according to exact string comparison of elements).
.SH EXAMPLES
.PP
The simplest way to use the operators is often by using \fBnamespace path\fR
to make the commands available. This has the advantage of not affecting the

Changes to doc/memory.n.

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
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
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
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

-
-
+
+

















+

-
+


+

-
+






+








+



-
+


+






+

-
+




+

-
+







+
















+

-
+










+







'\"
'\" Copyright (c) 1992-1999 by Karl Lehenbauer and Mark Diekhans
'\" Copyright (c) 2000 by Scriptics Corporation.
'\" Copyright (c) 1992-1999 Karl Lehenbauer & Mark Diekhans
'\" Copyright (c) 2000 Scriptics Corporation.
'\" All rights reserved.
'\"
.TH memory n 8.1 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
.SH NAME
memory \- Control Tcl memory debugging capabilities
.SH SYNOPSIS
\fBmemory \fIoption \fR?\fIarg arg ...\fR?
.BE
.SH DESCRIPTION
.PP
The \fBmemory\fR command gives the Tcl developer control of Tcl's memory
debugging capabilities.  The memory command has several suboptions, which are
described below.  It is only available when Tcl has been compiled with
memory debugging enabled (when \fBTCL_MEM_DEBUG\fR is defined at
compile time), and after \fBTcl_InitMemory\fR has been called.
.\" METHOD: active
.TP
\fBmemory active\fR \fIfile\fR
\fBmemory active\fI file\fR
.
Write a list of all currently allocated memory to the specified \fIfile\fR.
.\" METHOD: break_on_malloc
.TP
\fBmemory break_on_malloc\fR \fIcount\fR
\fBmemory break_on_malloc\fI count\fR
.
After the \fIcount\fR allocations have been performed, \fBTcl_Alloc\fR
outputs a message to this effect and that it is now attempting to enter
the C debugger.  Tcl will then issue a \fISIGINT\fR signal against itself.
If you are running Tcl under a C debugger, it should then enter the debugger
command mode.
.\" METHOD: info
.TP
\fBmemory info\fR
.
Returns a report containing the total allocations and frees since
Tcl began, the current packets allocated (the current
number of calls to \fBTcl_Alloc\fR not met by a corresponding call
to \fBTcl_Free\fR), the current bytes allocated, and the maximum number
of packets and bytes allocated.
.\" METHOD: init
.TP
\fBmemory init \fR[\fBon\fR|\fBoff\fR]
.
Turn on or off the pre-initialization of all allocated memory
Turn on or off the preinitialization of all allocated memory
with bogus bytes.  Useful for detecting the use of uninitialized
values.
.\" METHOD: objs
.TP
\fBmemory objs \fIfile\fR
.
Causes a list of all allocated Tcl_Obj values to be written to the specified
\fIfile\fR immediately, together with where they were allocated.  Useful for
checking for leaks of values.
.\" METHOD: onexit
.TP
\fBmemory onexit\fR \fIfile\fR
\fBmemory onexit\fI file\fR
.
Causes a list of all allocated memory to be written to the specified \fIfile\fR
during the finalization of Tcl's memory subsystem.  Useful for checking
that memory is properly cleaned up during process exit.
.\" METHOD: tag
.TP
\fBmemory tag\fR \fIstring\fR
\fBmemory tag\fI string\fR
.
Each packet of memory allocated by \fBTcl_Alloc\fR can have associated
with it a string-valued tag.  In the lists of allocated memory generated
by \fBmemory active\fR and \fBmemory onexit\fR, the tag for each packet
is printed along with other information about the packet.  The
\fBmemory tag\fR command sets the tag value for subsequent calls
to \fBTcl_Alloc\fR to be \fIstring\fR.
.\" METHOD: trace
.TP
\fBmemory trace \fR[\fBon\fR|\fBoff\fR]
.
Turns memory tracing on or off.  When memory tracing is on, every call
to \fBTcl_Alloc\fR causes a line of trace information to be written to
\fIstderr\fR, consisting of the word \fITcl_Alloc\fR, followed by the
address returned, the amount of memory allocated, and the C filename
and line number of the code performing the allocation.  For example:
.RS
.PP
.CS
Tcl_Alloc 40e478 98 tclProc.c 1406
.CE
.PP
Calls to \fBTcl_Free\fR are traced in the same manner.
.RE
.\" METHOD: trace_on_at_malloc
.TP
\fBmemory trace_on_at_malloc\fR \fIcount\fR
\fBmemory trace_on_at_malloc\fI count\fR
.
Enable memory tracing after \fIcount\fR \fBTcl_Alloc\fRs have been performed.
For example, if you enter \fBmemory trace_on_at_malloc 100\fR,
after the 100th call to \fBTcl_Alloc\fR, memory trace information will begin
being displayed for all allocations and frees.  Since there can be a lot
of memory activity before a problem occurs, judicious use of this option
can reduce the slowdown caused by tracing (and the amount of trace information
produced), if you can identify a number of allocations that occur before
the problem sets in.  The current number of memory allocations that have
occurred since Tcl started is printed on a guard zone failure.
.\" METHOD: validate
.TP
\fBmemory validate \fR[\fBon\fR|\fBoff\fR]
.
Turns memory validation on or off. When memory validation is enabled,
on every call to \fBTcl_Alloc\fR or \fBTcl_Free\fR, the guard zones are
checked for every piece of memory currently in existence that was
allocated by \fBTcl_Alloc\fR.  This has a large performance impact and

Changes to doc/msgcat.n.

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
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
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

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













+
-
+
-

-
+

-

-

-
+

-



-

-



-

-
+

-

-

-

-

-

-

-


-
-
+
-


-



+













-
-
+
+

-
-
-
+
+
+
+

-
+
+






+







'\"
'\" Copyright (c) 1998 Mark Harrison.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH "msgcat" n 1.5 msgcat "Tcl Bundled Packages"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
msgcat \- Tcl message catalog
.SH SYNOPSIS
.nf
\fBpackage require Tcl 8.7\fR
\fBpackage require tcl 9.0\fR
.sp
\fBpackage require msgcat 1.7\fR
.sp

\fB::msgcat::mc \fIsrc-string\fR ?\fIarg arg ...\fR?
.sp
\fB::msgcat::mcmax ?\fIsrc-string src-string ...\fR?
.sp
.VS "TIP 412"
\fB::msgcat::mcexists\fR ?\fB-exactnamespace\fR? ?\fB-exactlocale\fR? \fIsrc-string\fR
\fB::msgcat::mcexists\fR ?\fB\-exactnamespace\fR? ?\fB\-exactlocale\fR? \fIsrc-string\fR
.VE "TIP 412"
.sp
.VS "TIP 490"
\fB::msgcat::mcpackagenamespaceget\fR
.VE "TIP 490"
.sp
\fB::msgcat::mclocale \fR?\fInewLocale\fR?
.sp
.VS "TIP 499"
\fB::msgcat::mcpreferences\fR ?\fIlocale preference\fR? ...
.VE "TIP 499"
.sp
.VS "TIP 412"
\fB::msgcat::mcloadedlocales subcommand\fR ?\fIlocale\fR?
\fB::msgcat::mcloadedlocales subcommand\fR
.VE "TIP 412"
.sp
\fB::msgcat::mcload \fIdirname\fR
.sp
\fB::msgcat::mcset \fIlocale src-string \fR?\fItranslate-string\fR?
.sp
\fB::msgcat::mcmset \fIlocale src-trans-list\fR
.sp
\fB::msgcat::mcflset \fIsrc-string \fR?\fItranslate-string\fR?
.sp
\fB::msgcat::mcflmset \fIsrc-trans-list\fR
.sp
\fB::msgcat::mcunknown \fIlocale src-string\fR ?\fIarg arg ...\fR?
.sp
.VS "TIP 412"
\fB::msgcat::mcpackagelocale subcommand\fR ?\fIlocale\fR?
.sp
\fB::msgcat::mcpackageconfig subcommand\fR \fIoption\fR ?\fIvalue\fR?
\fB::msgcat::mcpackageconfig subcommand\fI option\fR ?\fIvalue\fR?
.sp
\fB::msgcat::mcforgetpackage\fR
.VE "TIP 412"
.sp
.VS "TIP 499"
\fB::msgcat::mcutil subcommand\fR ?\fIlocale\fR?
.VS "TIP 499"
.fi
.BE
.SH DESCRIPTION
.PP
The \fBmsgcat\fR package provides a set of functions
that can be used to manage multi-lingual user interfaces.
Text strings are defined in a
.QW "message catalog"
which is independent from the application, and
which can be edited or localized without modifying
the application source code.  New languages
or locales may be provided by adding a new file to
the message catalog.
.PP
\fBmsgcat\fR distinguises packages by its namespace.
Each package has its own message catalog and configuration settings in \fBmsgcat\fR.
\fBmsgcat\fR distinguishes packages by its namespace. Each package has
its own message catalog and configuration settings in \fBmsgcat\fR.
.PP
A \fIlocale\fR is a specification string describing a user language like \fBde_ch\fR for Swiss German.
In \fBmsgcat\fR, there is a global locale initialized by the system locale of the current system.
Each package may decide to use the global locale or to use a package specific locale.
A \fIlocale\fR is a specification string describing a user language like
\fBde_ch\fR for Swiss German. In \fBmsgcat\fR, there is a global locale
initialized by the system locale of the current system. Each package may
decide to use the global locale or to use a package specific locale.
.PP
The global locale may be changed on demand, for example by a user initiated language change or within a multi user application like a web server.
The global locale may be changed on demand, for example by a user initiated
language change or within a multi user application like a web server.
.PP
.VS tip490
Object oriented programming is supported by the use of a package namespace.
.VE tip490
.PP
.SH COMMANDS
.\" COMMAND: mc
.TP
\fB::msgcat::mc \fIsrc-string\fR ?\fIarg arg ...\fR?
.
Returns a translation of \fIsrc-string\fR according to the
current locale.  If additional arguments past \fIsrc-string\fR
are given, the \fBformat\fR command is used to substitute the
additional arguments in the translation of \fIsrc-string\fR.
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
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







-
+

-
-
-
+
+
+
+


-
-
+
+
+

-
+
+







-
+

-
-
+
+



-
+
+

-
+
+
+



-
+




-
+


-
-
-
+
+
+


-
+
+

















+



-
-
+
+


-
-
+
+
+
+

+
-
+

-
+
+












+










-
+
+



-
+
+





-
+

-
-
-
+
+
+
+


-
+

-
-
-
+
+

+
+


-


-
-
+
+
+










-
+
+
+


+







+











+


+





+


+







+
















-
+
+

+



-
+
+


+
+


-
+

-
-
+
+
+
+




+



-
+
+







\fB::msgcat::mc\fR is the main function used to localize an
application.  Instead of using an English string directly, an
application can pass the English string through \fB::msgcat::mc\fR and
use the result.  If an application is written for a single language in
this fashion, then it is easy to add support for additional languages
later simply by defining new message catalog entries.
.RE
.VS "TIP 490"
.\" COMMAND: mcn
.TP
\fB::msgcat::mcn \fInamespace\fR \fIsrc-string\fR ?\fIarg arg ...\fR?
.
Like \fB::msgcat::mc\fR, but with the message namespace specified as first argument.
\fB::msgcat::mcn \fInamespace src-string\fR ?\fIarg arg ...\fR?
.VS "TIP 490"
Like \fB::msgcat::mc\fR, but with the message namespace specified as first
argument.
.PP
.RS
\fBmcn\fR may be used for cases where the package namespace is not the namespace of the caller.
An example is shown within the description of the command \fB::msgcat::mcpackagenamespaceget\fR below.
\fBmcn\fR may be used for cases where the package namespace is not the
namespace of the caller. An example is shown within the description of the
command \fB::msgcat::mcpackagenamespaceget\fR below.
.RE
.PP
.VE
.\" COMMAND: mcmax
.TP
\fB::msgcat::mcmax ?\fIsrc-string src-string ...\fR?
.
Given several source strings, \fB::msgcat::mcmax\fR returns the length
of the longest translated string.  This is useful when designing
localized GUIs, which may require that all buttons, for example, be a
fixed width (which will be the width of the widest button).
.VS "TIP 412"
.\" COMMAND: mcexists
.TP
\fB::msgcat::mcexists\fR ?\fB-exactnamespace\fR? ?\fB-exactlocale\fR? ?\fB-namespace\fR \fInamespace\fR? \fIsrc-string\fR
.
\fB::msgcat::mcexists\fR ?\fB\-exactnamespace\fR? ?\fB\-exactlocale\fR? ?\fB\-namespace\fI namespace\fR? \fIsrc-string\fR
.VS "TIP 412"
Return true, if there is a translation for the given \fIsrc-string\fR.
.PP
.RS
The search may be limited by the option \fB\-exactnamespace\fR to only check the current namespace and not any parent namespaces.
The search may be limited by the option \fB\-exactnamespace\fR to only check
the current namespace and not any parent namespaces.
.PP
It may also be limited by the option \fB\-exactlocale\fR to only check the first prefered locale (e.g. first element returned by \fB::msgcat::mcpreferences\fR if global locale is used).
It may also be limited by the option \fB\-exactlocale\fR to only check the
first prefered locale (e.g. first element returned by
\fB::msgcat::mcpreferences\fR if global locale is used).
.PP
.VE "TIP 412"
.VS "TIP 490"
An explicit package namespace may be specified by the option \fB-namespace\fR.
An explicit package namespace may be specified by the option \fB\-namespace\fR.
The namespace of the caller is used if not explicitly specified.
.RE
.PP
.VE "TIP 490"
.VS "TIP 490"
.\" COMMAND: mcpackagenamespaceget
.TP
\fB::msgcat::mcpackagenamespaceget\fR
.
Return the package namespace of the caller.
This command handles all cases described in section \fBOBJECT ORIENTED PROGRAMMING\fR.
.VS "TIP 490"
Return the package namespace of the caller. This command handles all cases
described in section \fBOBJECT ORIENTED PROGRAMMING\fR.
.PP
.RS
Example usage is a tooltip package, which saves the caller package namespace to update the translation each time the tooltip is shown:
Example usage is a tooltip package, which saves the caller package namespace
to update the translation each time the tooltip is shown:
.CS
proc ::tooltip::tooltip {widget message} {
    ...
    set messagenamespace [uplevel 1 {::msgcat::mcpackagenamespaceget}]
    ...
    bind $widget  [list ::tooltip::show $widget $messagenamespace $message]
}

proc ::tooltip::show {widget messagenamespace message} {
    ...
    set message [::msgcat::mcn $messagenamespace $message]
    ...
}
.CE
.RE
.PP
.VE "TIP 490"
.\" COMMAND: mclocale
.TP
\fB::msgcat::mclocale \fR?\fInewLocale\fR?
.
If \fInewLocale\fR is omitted, the current locale is returned, otherwise the current locale
is set to \fInewLocale\fR.
If \fInewLocale\fR is omitted, the current locale is returned, otherwise the
current locale is set to \fInewLocale\fR.
.PP
.RS
If the new locale is set to \fInewLocale\fR, the corresponding preferences are calculated and set.
For example, if the current locale is en_US_funky, then \fB::msgcat::mcpreferences\fR returns \fB{en_us_funky en_us en {}}\fR.
If the new locale is set to \fInewLocale\fR, the corresponding preferences
are calculated and set.
For example, if the current locale is en_US_funky, then
\fB::msgcat::mcpreferences\fR returns \fB{en_us_funky en_us en {}}\fR.
.PP
The same result may be achieved by \fB::msgcat::mcpreferences\fR
The same result may be acheved by \fB::msgcat::mcpreferences\fR {*}[\fB::msgcat::mcutil getpreferences\fR \fInewLocale\fR].
{*}[\fB::msgcat::mcutil getpreferences\fI newLocale\fR].
.PP
The current locale is always the first element of the list returned by \fBmcpreferences\fR.
The current locale is always the first element of the list returned by
\fBmcpreferences\fR.
.PP
msgcat stores and compares the locale in a
case-insensitive manner, and returns locales in lowercase.
The initial locale is determined by the locale specified in
the user's environment.  See \fBLOCALE SPECIFICATION\fR
below for a description of the locale string format.
.PP
.VS "TIP 412"
If the locale is set, the preference list of locales is evaluated.
Locales in this list are loaded now, if not jet loaded.
.VE "TIP 412"
.RE
.\" COMMAND: mcpreferences
.TP
\fB::msgcat::mcpreferences\fR ?\fIlocale preference\fR? ...
.
Without arguments, returns an ordered list of the locales preferred by
the user.
The list is ordered from most specific to least preference.
.PP
.VS "TIP 499"
.RS
A set of locale preferences may be given to set the list of locale preferences.
The current locale is also set, which is the first element of the locale preferences list.
The current locale is also set, which is the first element of the locale
preferences list.
.PP
Locale preferences are loaded now, if not jet loaded.
.PP
As an example, the user may prefer French or English text. This may be configured by:
As an example, the user may prefer French or English text. This may be
configured by:
.CS
::msgcat::mcpreferences fr en {}
.CE
.RE
.PP
.VS "TIP 499"
.\" COMMAND: mcloadedlocales
.TP
\fB::msgcat:mcloadedlocales subcommand\fR ?\fIlocale\fR?
.
This group of commands manage the list of loaded locales for packages not setting a package locale.
\fB::msgcat::mcloadedlocales subcommand\fR
.VS "TIP 499"
This group of commands manage the list of loaded locales for packages not
setting a package locale.
.PP
.RS
The subcommand \fBget\fR returns the list of currently loaded locales.
The subcommand \fBloaded\fR returns the list of currently loaded locales.
.PP
The subcommand \fBpresent\fR requires the argument \fIlocale\fR and returns true, if this locale is loaded.
.PP
The subcommand \fBclear\fR removes all locales and their data, which are not in the current preference list.
The subcommand \fBclear\fR removes all locales and their data, which are not in
the current preference list.
.RE
.VE
.\" COMMAND: mcload
.TP
\fB::msgcat::mcload \fIdirname\fR
.
.VS "TIP 412"
Searches the specified directory for files that match
the language specifications returned by \fB::msgcat::mcloadedlocales get\fR
(or \fBmsgcat::mcpackagelocale preferences\fR if a package locale is set) (note that these are all lowercase), extended by the file extension
the language specifications returned by \fB::msgcat::mcloadedlocales loaded\fR
(or \fBmsgcat::mcpackagelocale preferences\fR if a package locale is set)
(note that these are all lowercase), extended by the file extension
.QW .msg .
Each matching file is
read in order, assuming a UTF-8 encoding.  The file contents are
then evaluated as a Tcl script.  This means that Unicode characters
may be present in the message file either directly in their UTF-8
encoded form, or by use of the backslash-u quoting recognized by Tcl
evaluation.  The number of message files which matched the specification
and were loaded is returned.
.RS
.PP
In addition, the given folder is stored in the \fBmsgcat\fR package configuration option \fImcfolder\fR to eventually load message catalog files required by a locale change.
In addition, the given folder is stored in the \fBmsgcat\fR package
configuration option \fImcfolder\fR to eventually load message catalog
files required by a locale change.
.VE "TIP 412"
.RE
.\" COMMAND: mcset
.TP
\fB::msgcat::mcset \fIlocale src-string \fR?\fItranslate-string\fR?
.
Sets the translation for \fIsrc-string\fR to \fItranslate-string\fR
in the specified \fIlocale\fR and the current namespace.  If
\fItranslate-string\fR is not specified, \fIsrc-string\fR is used
for both.  The function returns \fItranslate-string\fR.
.\" COMMAND: mcmset
.TP
\fB::msgcat::mcmset \fIlocale src-trans-list\fR
.
Sets the translation for multiple source strings in
\fIsrc-trans-list\fR in the specified \fIlocale\fR and the current
namespace.
\fIsrc-trans-list\fR must have an even number of elements and is in
the form {\fIsrc-string translate-string\fR ?\fIsrc-string
translate-string ...\fR?} \fB::msgcat::mcmset\fR can be significantly
faster than multiple invocations of \fB::msgcat::mcset\fR. The function
returns the number of translations set.
.\" COMMAND: mcflset
.TP
\fB::msgcat::mcflset \fIsrc-string \fR?\fItranslate-string\fR?
.
Sets the translation for \fIsrc-string\fR to \fItranslate-string\fR in the
current namespace for the locale implied by the name of the message catalog
being loaded via \fB::msgcat::mcload\fR.  If \fItranslate-string\fR is not
specified, \fIsrc-string\fR is used for both.  The function returns
\fItranslate-string\fR.
.\" COMMAND: mcflmset
.TP
\fB::msgcat::mcflmset \fIsrc-trans-list\fR
.
Sets the translation for multiple source strings in \fIsrc-trans-list\fR in
the current namespace for the locale implied by the name of the message
catalog being loaded via \fB::msgcat::mcload\fR. \fIsrc-trans-list\fR must
have an even number of elements and is in the form {\fIsrc-string
translate-string\fR ?\fIsrc-string translate-string ...\fR?}
\fB::msgcat::mcflmset\fR can be significantly faster than multiple invocations
of \fB::msgcat::mcflset\fR. The function returns the number of translations set.
.\" COMMAND: mcunknown
.TP
\fB::msgcat::mcunknown \fIlocale src-string\fR ?\fIarg arg ...\fR?
.
This routine is called by \fB::msgcat::mc\fR in the case when
a translation for \fIsrc-string\fR is not defined in the
current locale.  The default action is to return
\fIsrc-string\fR passed by format if there are any arguments.  This
procedure can be redefined by the
application, for example to log error messages for each unknown
string.  The \fB::msgcat::mcunknown\fR procedure is invoked at the
same stack context as the call to \fB::msgcat::mc\fR.  The return value
of \fB::msgcat::mcunknown\fR is used as the return value for the call
to \fB::msgcat::mc\fR.
.VS "TIP 412"
.RS
.PP
Note that this routine is only called if the concerned package did not set a package locale unknown command name.
Note that this routine is only called if the concerned package did not set a
package locale unknown command name.
.RE
.\" COMMAND: mcforgetpackage
.TP
\fB::msgcat::mcforgetpackage\fR
.
The calling package clears all its state within the \fBmsgcat\fR package including all settings and translations.
The calling package clears all its state within the \fBmsgcat\fR package
including all settings and translations.
.VE "TIP 412"
.PP
.\" COMMAND: mcutil
.\" METHOD: getpreferences
.VS "TIP 499"
.TP
\fB::msgcat::mcutil getpreferences\fR \fIlocale\fR
\fB::msgcat::mcutil getpreferences\fI locale\fR
.
Return the preferences list of the given locale as described in section \fBLOCALE SPECIFICATION\fR.
An example is the composition of a preference list for the bilingual region "Biel/Bienne" as a concatenation of swiss german and swiss french:
Return the preferences list of the given locale as described in the section
\fBLOCALE SPECIFICATION\fR.
An example is the composition of a preference list for the bilingual region
"Biel/Bienne" as a concatenation of swiss german and swiss french:
.CS
% concat [lrange [msgcat::mcutil getpreferences fr_CH] 0 end-1] [msgcat::mcutil getpreferences de_CH]
fr_ch fr de_ch de {}
.CE
.\" METHOD: getsystemlocale
.TP
\fB::msgcat::mcutil getsystemlocale\fR
.
The system locale is returned as described by the section \fBLOCALE SPECIFICATION\fR.
The system locale is returned as described by the section
\fBLOCALE SPECIFICATION\fR.
.VE "TIP 499"
.PP
.SH "LOCALE SPECIFICATION"
.PP
The locale is specified to \fBmsgcat\fR by a locale string
passed to \fB::msgcat::mclocale\fR.
The locale string consists of
355
356
357
358
359
360
361
362

363
364

365
366
367
368
369
370
371
372
378
379
380
381
382
383
384

385
386

387

388
389
390
391
392
393
394







-
+

-
+
-







.PP
.CS
language[_country][_modifier]
.CE
.PP
On Windows and Cygwin, if none of those environment variables is set,
msgcat will attempt to extract locale information from the registry.
From Windows Vista on, the RFC4747 locale name "lang-script-country-options"
The RFC4747 locale name "lang-script-country-options"
is transformed to the locale as "lang_country_script" (Example:
sr-Latn-CS -> sr_cs_latin). For Windows XP, the language id is
sr-Latn-CS -> sr_cs_latin).
transformed analoguously (Example: 0c1a -> sr_yu_cyrillic).
If all these attempts to discover an initial locale from the user's
environment fail, msgcat defaults to an initial locale of
.QW C .
.PP
When a locale is specified by the user, a
.QW "best match"
search is performed during string translation.  For example, if a user
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
558
559
560




561
562
563
564
565


566
567
568

569
570
571

572
573
574
575

576
577
578
579

580
581
582
583

584
585

586
587

588
589

590
591
592
593
594
595
596
597
598
599




600
601

602
603
604

605
606

607
608

609
610

611
612
613
614



615
616

617
618
619
620
621
622
623
624
625
626
627



628
629
630



631
632
633
634
635
636
637


638
639
640



641
642
643
644
645


646
647
648
649
650



651
652
653
654
655
656
657
658
659
660


661
662
663


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
707
708
709
710
711
712
553
554
555
556
557
558
559

560
561
562
563
564
565
566
567
568
569
570


571
572
573
574
575
576
577
578
579
580
581
582

583
584
585
586
587
588



589
590
591
592
593
594
595


596
597
598
599

600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617

618
619
620
621
622

623
624
625
626
627
628
629
630
631
632
633
634
635

636
637
638
639
640

641
642
643
644
645
646

647
648
649
650
651

652
653
654
655

656
657
658
659

660
661
662
663
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
707
708
709
710
711
712
713

714
715
716
717

718
719
720

721
722
723
724
725

726
727
728
729
730
731
732
733
734
735
736
737
738


739
740
741
742
743
744
745
746
747
748

749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767

768
769
770
771
772
773
774
775
776







-
+
+
+


+
+




-
-
+
+
+
+




+



-
+
+
+



-
-
-
+
+
+
+



-
-
+
+


-
+



+




+




+



-
+


+

-
+


+









-
+
+
+
+

-
+



+

-
+


+

-
+



-
+
+
+

-
+










-
+
+
+


-
+
+
+






-
+
+


-
+
+
+




-
+
+




-
+
+
+









-
+
+


-
+
+

-
+
+
+


-
+












-
-
+
+
+
+






-
+
+
+
+















-
+
+







.VS "TIP 412"
.SH "PACKAGE PRIVATE LOCALE"
.PP
A package using \fBmsgcat\fR may choose to use its own package private
locale and its own set of loaded locales, independent to the global
locale set by \fB::msgcat::mclocale\fR.
.PP
This allows a package to change its locale without causing any locales load or removal in other packages and not to invoke the global locale change callback (see below).
This allows a package to change its locale without causing any locales load or
removal in other packages and not to invoke the global locale change callback
(see below).
.PP
This action is controled by the following ensemble:
.\" COMMAND: mcpackagelocale
.\" METHOD: set
.TP
\fB::msgcat::mcpackagelocale set\fR ?\fIlocale\fR?
.
Set or change a package private locale.
The package private locale is set to the given \fIlocale\fR if the \fIlocale\fR is given.
If the option \fIlocale\fR is not given, the package is set to package private locale mode, but no locale is changed (e.g. if the global locale was valid for the package before, it is copied to the package private locale).
The package private locale is set to the given \fIlocale\fR if the \fIlocale\fR
is given. If the option \fIlocale\fR is not given, the package is set to package
private locale mode, but no locale is changed (e.g. if the global locale was
valid for the package before, it is copied to the package private locale).
.PP
.RS
This command may cause the load of locales.
.RE
.\" METHOD: get
.TP
\fB::msgcat::mcpackagelocale get\fR
.
Return the package private locale or the global locale, if no package private locale is set.
Return the package private locale or the global locale, if no package private
locale is set.
.\" METHOD: preferences
.TP
\fB::msgcat::mcpackagelocale preferences\fR ?\fIlocale preference\fR? ...
.
With no parameters, return the package private preferences or the global preferences,
if no package private locale is set.
The package locale state (set or not) is not changed (in contrast to the command \fB::msgcat::mcpackagelocale set\fR).
With no parameters, return the package private preferences or the global
preferences, if no package private locale is set.
The package locale state (set or not) is not changed (in contrast to the
command \fB::msgcat::mcpackagelocale set\fR).
.PP
.RS
.VS "TIP 499"
If a set of locale preferences is given, it is set as package locale preference list.
The package locale is set to the first element of the preference list.
If a set of locale preferences is given, it is set as package locale preference
list. The package locale is set to the first element of the preference list.
A package locale is activated, if it was not set so far.
.PP
Locale preferences are loaded now for the package, if not jet loaded.
Locale preferences are loaded now for the package, if not yet loaded.
.VE "TIP 499"
.RE
.PP
.\" METHOD: loaded
.TP
\fB::msgcat::mcpackagelocale loaded\fR
.
Return the list of locales loaded for this package.
.\" METHOD: isset
.TP
\fB::msgcat::mcpackagelocale isset\fR
.
Returns true, if a package private locale is set.
.\" METHOD: unset
.TP
\fB::msgcat::mcpackagelocale unset\fR
.
Unset the package private locale and use the globale locale.
Unset the package private locale and use the global locale.
Load and remove locales to adjust the list of loaded locales for the
package to the global loaded locales list.
.\" METHOD: present
.TP
\fB::msgcat::mcpackagelocale present\fR \fIlocale\fR
\fB::msgcat::mcpackagelocale present\fI locale\fR
.
Returns true, if the given locale is loaded for the package.
.\" METHOD: clear
.TP
\fB::msgcat::mcpackagelocale clear\fR
.
Clear any loaded locales of the package not present in the package preferences.
.PP
.SH "CHANGING PACKAGE OPTIONS"
.PP
Each package using msgcat has a set of options within \fBmsgcat\fR.
The package options are described in the next sectionPackage options.
Each package option may be set or unset individually using the following ensemble:
Each package option may be set or unset individually using the following
ensemble:
.\" COMMAND: mcpackageconfig
.\" METHOD: get
.TP
\fB::msgcat::mcpackageconfig get\fR \fIoption\fR
\fB::msgcat::mcpackageconfig get\fI option\fR
.
Return the current value of the given \fIoption\fR.
This call returns an error if the option is not set for the package.
.\" METHOD: isset
.TP
\fB::msgcat::mcpackageconfig isset\fR \fIoption\fR
\fB::msgcat::mcpackageconfig isset\fI option\fR
.
Returns 1, if the given \fIoption\fR is set for the package, 0 otherwise.
.\" METHOD: set
.TP
\fB::msgcat::mcpackageconfig set\fR \fIoption\fR \fIvalue\fR
\fB::msgcat::mcpackageconfig set\fI option value\fR
.
Set the given \fIoption\fR to the given \fIvalue\fR.
This may invoke additional actions in dependency of the \fIoption\fR.
The return value is 0 or the number of loaded packages for the option \fBmcfolder\fR.
The return value is 0 or the number of loaded packages for the option
\fBmcfolder\fR.
.\" METHOD: unset
.TP
\fB::msgcat::mcpackageconfig unset\fR \fIoption\fR
\fB::msgcat::mcpackageconfig unset\fI option\fR
.
Unsets the given \fIoption\fR for the package.
No action is taken if the \fIoption\fR is not set for the package.
The empty string is returned.
.SS Package options
.PP
The following package options are available for each package:
.TP
\fBmcfolder\fR
.
This is the message folder of the package. This option is set by mcload and by the subcommand set. Both are identical and both return the number of loaded message catalog files.
This is the message folder of the package. This option is set by mcload and by
the subcommand set. Both are identical and both return the number of loaded
message catalog files.
.RS
.PP
Setting or changing this value will load all locales contained in the preferences valid for the package. This implies also to invoke any set loadcmd (see below).
Setting or changing this value will load all locales contained in the
preferences valid for the package. This implies also to invoke any set
loadcmd (see below).
.PP
Unsetting this value will disable message file load for the package.
.RE
.TP
\fBloadcmd\fR
.
This callback is invoked before a set of message catalog files are loaded for the package which has this property set.
This callback is invoked before a set of message catalog files are loaded for
the package which has this property set.
.PP
.RS
This callback may be used to do any preparation work for message file load or to get the message data from another source like a data base. In this case, no message files are used (mcfolder is unset).
This callback may be used to do any preparation work for message file load or
to get the message data from another source like a data base. In this case, no
message files are used (mcfolder is unset).
.PP
See section \fBcallback invocation\fR below.
The parameter list appended to this callback is the list of locales to load.
.PP
If this callback is changed, it is called with the preferences valid for the package.
If this callback is changed, it is called with the preferences valid for the
package.
.RE
.TP
\fBchangecmd\fR
.
This callback is invoked when a default local change was performed. Its purpose is to allow a package to update any dependency on the default locale like showing the GUI in another language.
This callback is invoked when a default local change was performed. Its
purpose is to allow a package to update any dependency on the default locale
like showing the GUI in another language.
.PP
.RS
See the callback invocation section below.
The parameter list appended to this callback is \fBmcpreferences\fR.
The registered callbacks are invoked in no particular order.
.RE
.TP
\fBunknowncmd\fR
.
Use a package locale mcunknown procedure instead of the standard version supplied by the msgcat package (msgcat::mcunknown).
Use a package locale mcunknown procedure instead of the standard version
supplied by the msgcat package (\fBmsgcat::mcunknown\fR).
.PP
.RS
The called procedure must return the formatted message which will finally be returned by msgcat::mc.
The called procedure must return the formatted message which will finally be
returned by \fBmsgcat::mc\fR.
.PP
A generic unknown handler is used if set to the empty string. This consists in returning the key if no arguments are given. With given arguments, format is used to process the arguments.
A generic unknown handler is used if set to the empty string. This consists of
returning the key if no arguments are given. With given arguments, the
\fBformat\fR command is used to process the arguments.
.PP
See section \fBcallback invocation\fR below.
The appended arguments are identical to \fB::msgcat::mcunknown\fR.
The appended arguments are identical to \fBmsgcat::mcunknown\fR.
.RE
.SH "Callback invocation"
A package may decide to register one or multiple callbacks, as described above.
.PP
Callbacks are invoked, if:
.PP
1. the callback command is set,
.PP
2. the command is not the empty string,
.PP
3. the registering namespace exists.
.PP
If a called routine fails with an error, the \fBbgerror\fR routine for the interpreter is invoked after command completion.
Only exception is the callback \fBunknowncmd\fR, where an error causes the invoking \fBmc\fR-command to fail with that error.
If a called routine fails with an error, the \fBbgerror\fR routine for the
interpreter is invoked after command completion.
Only exception is the callback \fBunknowncmd\fR, where an error causes the
invoking \fBmc\fR-command to fail with that error.
.PP
.VS tip490
.SH "OBJECT ORIENTED PROGRAMMING"
\fBmsgcat\fR supports packages implemented by object oriented programming.
Objects and classes should be defined within a package namespace.
.PP
There are 3 supported cases where package namespace sensitive commands of msgcat (\fBmc\fR, \fBmcexists\fR, \fBmcpackagelocale\fR, \fBmcforgetpackage\fR, \fBmcpackagenamespaceget\fR, \fBmcpackageconfig\fR, \fBmcset\fR and \fBmcmset\fR) may be called:
There are 3 supported cases where package namespace sensitive commands of msgcat
(\fBmc\fR, \fBmcexists\fR, \fBmcpackagelocale\fR, \fBmcforgetpackage\fR,
\fBmcpackagenamespaceget\fR, \fBmcpackageconfig\fR, \fBmcset\fR and \fBmcmset\fR)
may be called:
.PP
.TP
\fB1) In class definition script\fR
.
\fBmsgcat\fR command is called within a class definition script.
.CS
namespace eval ::N2 {
    mcload $dir/msgs
    oo::class create C1 {puts [mc Hi!]}
}
.CE
.PP
.TP
\fB2) method defined in a class\fR
.
\fBmsgcat\fR command is called from a method in an object and the method is defined in a class.
\fBmsgcat\fR command is called from a method in an object and the method is
defined in a class.
.CS
namespace eval ::N3Class {
    mcload $dir/msgs
    oo::class create C1
    oo::define C1 method m1 {
        puts [mc Hi!]
    }
725
726
727
728
729
730
731
732
733


734
735
736
737
738

739
740
741
742
743
744
745
746
747


748
749
750
751
752
753
754
755
756
757
758
759
760
761
762


763
764
765


766
767
768
769
770
771
772

773
774


775
776
777
778
779
780


781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799


800
801
802
789
790
791
792
793
794
795


796
797
798
799
800
801

802
803
804
805
806
807
808
809
810

811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826

827
828
829
830

831
832
833
834
835
836
837
838

839
840

841
842
843
844
845
846
847

848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867

868
869
870
871
872







-
-
+
+




-
+








-
+
+














-
+
+


-
+
+






-
+

-
+
+





-
+
+


















-
+
+



        puts [mc Hi!]
    }
}
.CE
.PP
.VE tip490
.SH EXAMPLES
Packages which display a GUI may update their widgets when the global locale changes.
To register to a callback, use:
Packages which display a GUI may update their widgets when the global locale
changes. To register to a callback, use:
.CS
namespace eval gui {
    msgcat::mcpackageconfig changecmd updateGUI

    proc updateGui args {
    proc updateGUI args {
        puts "New locale is '[lindex $args 0]'."
    }
}
% msgcat::mclocale fr
fr
% New locale is 'fr'.
.CE
.PP
If locales (or additional locales) are contained in another source like a data base, a package may use the load callback and not mcload:
If locales (or additional locales) are contained in another source like a
database, a package may use the load callback and not \fBmcload\fR:
.CS
namespace eval db {
    msgcat::mcpackageconfig loadcmd loadMessages

    proc loadMessages args {
        foreach locale $args {
            if {[LocaleInDB $locale]} {
                msgcat::mcmset $locale [GetLocaleList $locale]
            }
        }
    }
}
.CE
.PP
The \fBclock\fR command implementation uses \fBmsgcat\fR with a package locale to implement the command line parameter \fB-locale\fR.
The \fBclock\fR command implementation uses \fBmsgcat\fR with a package
locale to implement the command line parameter \fB\-locale\fR.
Here are some sketches of the implementation:
.PP
First, a package locale is initialized and the generic unknown function is desactivated:
First, a package locale is initialized and the generic unknown function is
deactivated:
.CS
msgcat::mcpackagelocale set
msgcat::mcpackageconfig unknowncmd ""
.CE
As an example, the user requires the week day in a certain locale as follows:
.CS
clock format clock seconds -format %A -locale fr
clock format [clock seconds] -format %A -locale fr
.CE
\fBclock\fR sets the package locale to \fBfr\fR and looks for the day name as follows:
\fBclock\fR sets the package locale to \fBfr\fR and looks for the day name as
follows:
.CS
msgcat::mcpackagelocale set $locale
return [lindex [msgcat::mc DAYS_OF_WEEK_FULL] $day]
### Returns "mercredi"
.CE
Within \fBclock\fR, some message-catalog items are heavy in computation and thus are dynamically cached using:
Within \fBclock\fR, some message-catalog items are heavy in computation and
thus are dynamically cached using:
.CS
proc ::tcl::clock::LocalizeFormat { locale format } {
    set key FORMAT_$format
    if { [::msgcat::mcexists -exactlocale -exactnamespace $key] } {
        return [mc $key]
    }
    #...expensive computation of format clipped...
    mcset $locale $key $format
    return $format
}
.CE
.VE "TIP 412"
.SH CREDITS
.PP
The message catalog code was developed by Mark Harrison.
.SH "SEE ALSO"
format(n), scan(n), namespace(n), package(n), oo::class(n), oo::object
.SH KEYWORDS
internationalization, i18n, localization, l10n, message, text, translation, class, object
internationalization, i18n, localization, l10n, message, text, translation,
class, object
.\" Local Variables:
.\" mode: nroff
.\" End:

Changes to doc/my.n.

8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
my, myclass \- invoke any method of current object or its class
.SH SYNOPSIS
.nf
package require TclOO
package require tcl::oo

\fBmy\fI methodName\fR ?\fIarg ...\fR?
\fBmyclass\fI methodName\fR ?\fIarg ...\fR?
.fi
.BE
.SH DESCRIPTION
.PP
31
32
33
34
35
36
37
38
39
40



41
42
43
44
45
46
47
31
32
33
34
35
36
37



38
39
40
41
42
43
44
45
46
47







-
-
-
+
+
+







superclasses, including those that are not exported
.VS TIP500
and private methods of the object or class when used within another method
defined by that object or class.
.VE TIP500
.PP
The object upon which the method is invoked via \fBmy\fR is the one that owns
the namespace that the \fBmy\fR command is contained in initially (\fBNB:\fR the link
remains if the command is renamed), which is the currently invoked object by
default.
the namespace that the \fBmy\fR command is contained in initially (\fBNB:\fR the
link remains if the command is renamed), which is the currently invoked object
by default.
.VS TIP478
Similarly, the object on which the method is invoked via \fBmyclass\fR is the
object that is the current class of the object that owns the namespace that
the \fBmyclass\fR command is contained in initially. As with \fBmy\fR, the
link remains even if the command is renamed into another namespace, and
defaults to being the manufacturing class of the current object.
.VE TIP478

Changes to doc/namespace.n.

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
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







-
+









+
















+







.TH namespace n 8.5 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
namespace \- create and manipulate contexts for commands and variables
.SH SYNOPSIS
\fBnamespace \fR?\fIsubcommand\fR? ?\fIarg ...\fR?
\fBnamespace \fR\fIsubcommand\fR ?\fIarg ...\fR?
.BE
.SH DESCRIPTION
.PP
The \fBnamespace\fR command lets you create, access, and destroy
separate contexts for commands and variables.
See the section \fBWHAT IS A NAMESPACE?\fR below
for a brief overview of namespaces.
The legal values of \fIsubcommand\fR are listed below.
Note that you can abbreviate the \fIsubcommand\fRs.
.\" METHOD: children
.TP
\fBnamespace children \fR?\fInamespace\fR? ?\fIpattern\fR?
.
Returns a list of all child namespaces that belong to the
namespace \fInamespace\fR.
If \fInamespace\fR is not specified,
then the children are returned for the current namespace.
This command returns fully-qualified names,
which start with a double colon (\fB::\fR).
If the optional \fIpattern\fR is given,
then this command returns only the names that match the glob-style pattern.
The actual pattern used is determined as follows:
a pattern that starts with double colon (\fB::\fR) is used directly,
otherwise the namespace \fInamespace\fR
(or the fully-qualified name of the current namespace)
is prepended onto the pattern.
.\" METHOD: code
.TP
\fBnamespace code \fIscript\fR
.
Captures the current namespace context for later execution
of the script \fIscript\fR.
It returns a new script in which \fIscript\fR has been wrapped
in a \fBnamespace inscope\fR command.
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
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







+









+












+

-
+




+

-
+














+

-
+



+







This command is needed because
extensions like Tk normally execute callback scripts
in the global namespace.
A scoped command captures a command together with its namespace context
in a way that allows it to be executed properly later.
See the section \fBSCOPED SCRIPTS\fR for some examples
of how this is used to create callback scripts.
.\" METHOD: current
.TP
\fBnamespace current\fR
.
Returns the fully-qualified name for the current namespace.
The actual name of the global namespace is
.MT
(i.e., an empty string),
but this command returns \fB::\fR for the global namespace
as a convenience to programmers.
.\" METHOD: delete
.TP
\fBnamespace delete \fR?\fInamespace namespace ...\fR?
.
Each namespace \fInamespace\fR is deleted
and all variables, procedures, and child namespaces
contained in the namespace are deleted.
If a procedure is currently executing inside the namespace,
the namespace will be kept alive until the procedure returns;
however, the namespace is marked to prevent other code from
looking it up by name.
If a namespace does not exist, this command returns an error.
If no namespace names are given, this command does nothing.
.\" METHOD: ensemble
.TP
\fBnamespace ensemble\fR \fIsubcommand\fR ?\fIarg ...\fR?
\fBnamespace ensemble \fIsubcommand\fR ?\fIarg ...\fR?
.
Creates and manipulates a command that is formed out of an ensemble of
subcommands.  See the section \fBENSEMBLES\fR below for further
details.
.\" METHOD: eval
.TP
\fBnamespace eval\fR \fInamespace arg\fR ?\fIarg ...\fR?
\fBnamespace eval \fInamespace arg\fR ?\fIarg ...\fR?
.
Activates a namespace called \fInamespace\fR and evaluates some code
in that context.
If the namespace does not already exist, it is created.
If more than one \fIarg\fR argument is specified,
the arguments are concatenated together with a space between each one
in the same fashion as the \fBeval\fR command,
and the result is evaluated.
.RS
.PP
If \fInamespace\fR has leading namespace qualifiers
and any leading namespaces do not exist,
they are automatically created.
.RE
.\" METHOD: exists
.TP
\fBnamespace exists\fR \fInamespace\fR
\fBnamespace exists \fInamespace\fR
.
Returns \fB1\fR if \fInamespace\fR is a valid namespace in the current
context, returns \fB0\fR otherwise.
.\" METHOD: export
.TP
\fBnamespace export \fR?\fB\-clear\fR? ?\fIpattern pattern ...\fR?
.
Specifies which commands are exported from a namespace.
The exported commands are those that can be later imported
into another namespace using a \fBnamespace import\fR command.
Both commands defined in a namespace and
133
134
135
136
137
138
139

140
141
142
143
144
145
146
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155







+







in the current (exporting) namespace.
Each \fIpattern\fR is appended onto the namespace's list of export patterns.
If the \fB\-clear\fR flag is given,
the namespace's export pattern list is reset to empty before any
\fIpattern\fR arguments are appended.
If no \fIpattern\fRs are given and the \fB\-clear\fR flag is not given,
this command returns the namespace's current export list.
.\" METHOD: forget
.TP
\fBnamespace forget \fR?\fIpattern pattern ...\fR?
.
Removes previously imported commands from a namespace.
Each \fIpattern\fR is a simple or qualified name such as
\fBx\fR, \fBfoo::x\fR or \fBa::b::p*\fR.
Qualified names contain double colons (\fB::\fR) and qualify a name
157
158
159
160
161
162
163
164


165
166

167
168
169
170
171
172
173
166
167
168
169
170
171
172

173
174
175

176
177
178
179
180
181
182
183







-
+
+

-
+







current namespace that were imported from a different namespace.
For
.QW "qualified patterns" ,
this command first finds the matching exported commands.
It then checks whether any of those commands
were previously imported by the current namespace.
If so, this command deletes the corresponding imported commands.
In effect, this un-does the action of a \fBnamespace import\fR command.
In effect, this undoes the action of a \fBnamespace import\fR command.
.\" METHOD: import
.TP
\fBnamespace import \fR?\fB\-force\fR? ?\fIpattern\fR \fIpattern ...\fR?
\fBnamespace import \fR?\fB\-force\fR? ?\fIpattern pattern ...\fR?
.
Imports commands into a namespace, or queries the set of imported
commands in a namespace.  When no arguments are present,
\fBnamespace import\fR returns the list of commands in
the current namespace that have been imported from other
namespaces.  The commands in the returned list are in
the format of simple names, with no namespace qualifiers at all.
201
202
203
204
205
206
207

208
209

210
211
212
213
214
215
216
211
212
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227







+

-
+







that is, only requested commands that are currently defined
in the exporting namespace are imported.
In other words, you can import only the commands that are in a namespace
at the time when the \fBnamespace import\fR command is executed.
If another command is defined and exported in this namespace later on,
it will not be imported.
.RE
.\" METHOD: inscope
.TP
\fBnamespace inscope\fR \fInamespace\fR \fIscript\fR ?\fIarg ...\fR?
\fBnamespace inscope \fInamespace script\fR ?\fIarg ...\fR?
.
Executes a script in the context of the specified \fInamespace\fR.
This command is not expected to be used directly by programmers;
calls to it are generated implicitly when applications
use \fBnamespace code\fR commands to create callback scripts
that the applications then register with, e.g., Tk widgets.
The \fBnamespace inscope\fR command is much like the \fBnamespace eval\fR
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
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







+















+







+









+

-
+







-
-
+

+

-
+









+

-
+









+













+







.CS
\fBnamespace eval ::foo [concat $script [list $x $y $z]]\fR
.CE
.PP
thus additional arguments will not undergo a second round of substitution,
as is the case with \fBnamespace eval\fR.
.RE
.\" METHOD: origin
.TP
\fBnamespace origin \fIcommand\fR
.
Returns the fully-qualified name of the original command
to which the imported command \fIcommand\fR refers.
When a command is imported into a namespace,
a new command is created in that namespace
that points to the actual command in the exporting namespace.
If a command is imported into a sequence of namespaces
\fIa, b,...,n\fR where each successive namespace
just imports the command from the previous namespace,
this command returns the fully-qualified name of the original command
in the first namespace, \fIa\fR.
If \fIcommand\fR does not refer to an imported command,
the command's own fully-qualified name is returned.
.\" METHOD: parent
.TP
\fBnamespace parent\fR ?\fInamespace\fR?
.
Returns the fully-qualified name of the parent namespace
for namespace \fInamespace\fR.
If \fInamespace\fR is not specified,
the fully-qualified name of the current namespace's parent is returned.
.\" METHOD: path
.TP
\fBnamespace path\fR ?\fInamespaceList\fR?
.
Returns the command resolution path of the current namespace. If
\fInamespaceList\fR is specified as a list of named namespaces, the
current namespace's command resolution path is set to those namespaces
and returns the empty list. The default command resolution path is
always empty. See the section \fBNAME RESOLUTION\fR below for an
explanation of the rules regarding name resolution.
.\" METHOD: qualifiers
.TP
\fBnamespace qualifiers\fR \fIstring\fR
\fBnamespace qualifiers\fI string\fR
.
Returns any leading namespace qualifiers for \fIstring\fR.
Qualifiers are namespace names separated by double colons (\fB::\fR).
For the \fIstring\fR \fB::foo::bar::x\fR,
this command returns \fB::foo::bar\fR,
and for \fB::\fR it returns an empty string.
This command is the complement of the \fBnamespace tail\fR command.
Note that it does not check whether the
namespace names are, in fact,
It does not check whether the namespace names are, in fact,
the names of currently defined namespaces.
.\" METHOD: tail
.TP
\fBnamespace tail\fR \fIstring\fR
\fBnamespace tail\fI string\fR
.
Returns the simple name at the end of a qualified string.
Qualifiers are namespace names separated by double colons (\fB::\fR).
For the \fIstring\fR \fB::foo::bar::x\fR,
this command returns \fBx\fR,
and for \fB::\fR it returns an empty string.
This command is the complement of the \fBnamespace qualifiers\fR command.
It does not check whether the namespace names are, in fact,
the names of currently defined namespaces.
.\" METHOD: upvar
.TP
\fBnamespace upvar\fR \fInamespace\fR ?\fIotherVar myVar \fR...?
\fBnamespace upvar\fI namespace\fR ?\fIotherVar myVar \fR...?
.
This command arranges for zero or more local variables in the current
procedure to refer to variables in \fInamespace\fR. The namespace name is
resolved as described in section \fBNAME RESOLUTION\fR.
The command
\fBnamespace upvar $ns a b\fR has the same behaviour as
\fBupvar 0 ${ns}::a b\fR, with the sole exception of the resolution rules
used for qualified namespace or variable names.
\fBnamespace upvar\fR returns an empty string.
.\" METHOD: unknown
.TP
\fBnamespace unknown\fR ?\fIscript\fR?
.
Sets or returns the unknown command handler for the current namespace.
The handler is invoked when a command called from within the namespace
cannot be found in the current namespace, the namespace's path nor in
the global namespace.
The \fIscript\fR argument, if given, should be a well
formed list representing a command name and optional arguments. When
the handler is invoked, the full invocation line will be appended to the
script and the result evaluated in the context of the namespace. The
default handler for all namespaces is \fB::unknown\fR. If no argument
is given, it returns the handler for the current namespace.
.\" METHOD: which
.TP
\fBnamespace which\fR ?\fB\-command\fR? ?\fB\-variable\fR? \fIname\fR
.
Looks up \fIname\fR as either a command or variable
and returns its fully-qualified name.
For example, if \fIname\fR does not exist in the current namespace
but does exist in the global namespace,
473
474
475
476
477
478
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
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
558
559



560
561
562
563
564
565
566
567
568
569







-
-
+
+
+
+



















-
+
-

-
+














-
+
-
-
-
-
+
+






-
+


-
-
+
+


-
+


-
+


-
-
-
+
+
+







If you provide a fully-qualified name that starts with a \fB::\fR,
there is no question about what command, variable, or namespace
you mean.
However, if the name does not start with a \fB::\fR
(i.e., is \fIrelative\fR),
Tcl follows basic rules for looking it up:
.IP \(bu
\fBVariable names\fR are always resolved by looking first in the current
namespace, and then in the global namespace.
\fBVariable names\fR are always resolved starting in the current
namespace. In the absence of special resolvers, foo::bar::baz refers to
a variable named "baz" in a namespace named "bar" that is a child of a
namespace named "foo" that is a child of the current namespace of the interpreter.
.IP \(bu
\fBCommand names\fR are always resolved by looking in the current namespace
first. If not found there, they are searched for in every namespace on the
current namespace's command path (which is empty by default). If not found
there, command names are looked up in the global namespace (or, failing that,
are processed by the appropriate \fBnamespace unknown\fR handler.)
.IP \(bu
\fBNamespace names\fR are always resolved by looking in only the current
namespace.
.PP
In the following example,
.PP
.CS
set traceLevel 0
\fBnamespace eval\fR Debug {
    printTrace $traceLevel
}
.CE
.PP
Tcl looks for \fBtraceLevel\fR in the namespace \fBDebug\fR
Tcl looks for \fBtraceLevel\fR in the namespace \fBDebug\fR.
and then in the global namespace.
It looks up the command \fBprintTrace\fR in the same way.
If a variable or command name is not found in either context,
If a variable or command name is not found,
the name is undefined.
To make this point absolutely clear, consider the following example:
.PP
.CS
set traceLevel 0
\fBnamespace eval\fR Foo {
    variable traceLevel 3

    \fBnamespace eval\fR Debug {
        printTrace $traceLevel
    }
}
.CE
.PP
Here Tcl looks for \fBtraceLevel\fR first in the namespace \fBFoo::Debug\fR.
Here Tcl looks for \fBtraceLevel\fR in the namespace \fBFoo::Debug\fR.
Since it is not found there, Tcl then looks for it
in the global namespace.
The variable \fBFoo::traceLevel\fR is completely ignored
during the name resolution process.
The variables \fBFoo::traceLevel\fR and \fBFoo::Debug::traceLevel\fR
are completely ignored during the name resolution process.
.PP
You can use the \fBnamespace which\fR command to clear up any question
about name resolution.
For example, the command:
.PP
.CS
\fBnamespace eval\fR Foo::Debug {\fBnamespace which\fR \-variable traceLevel}
\fBnamespace eval\fR Foo::Debug {\fBnamespace which\fR -variable traceLevel}
.CE
.PP
returns \fB::traceLevel\fR.
On the other hand, the command,
returns the empty string.
The command,
.PP
.CS
\fBnamespace eval\fR Foo {\fBnamespace which\fR \-variable traceLevel}
\fBnamespace eval\fR Foo {\fBnamespace which\fR -variable traceLevel}
.CE
.PP
returns \fB::Foo::traceLevel\fR.
returns the empty string as well.
.PP
As mentioned above,
namespace names are looked up differently
than the names of variables and commands.
Namespace names are always resolved in the current namespace.
namespace names and variables are looked up differently
than the names of commands.
Namespace names and variables are always resolved in the current namespace.
This means, for example,
that a \fBnamespace eval\fR command that creates a new namespace
always creates a child of the current namespace
unless the new namespace name begins with \fB::\fR.
.PP
Tcl has no access control to limit what variables, commands,
or namespaces you can reference.
572
573
574
575
576
577
578
579

580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596

597
598
599
600
601
602
603
589
590
591
592
593
594
595

596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612

613
614
615
616
617
618
619
620







-
+
















-
+







Some library commands are used so frequently
that it is a nuisance to type their qualified names.
For example, suppose that all of the commands in a package
like BLT are contained in a namespace called \fBBlt\fR.
Then you might access these commands like this:
.PP
.CS
Blt::graph .g \-background red
Blt::graph .g -background red
Blt::table . .g 0,0
.CE
.PP
If you use the \fBgraph\fR and \fBtable\fR commands frequently,
you may want to access them without the \fBBlt::\fR prefix.
You can do this by importing the commands into the current namespace,
like this:
.PP
.CS
\fBnamespace import\fR Blt::*
.CE
.PP
This adds all exported commands from the \fBBlt\fR namespace
into the current namespace context, so you can write code like this:
.PP
.CS
graph .g \-background red
graph .g -background red
table . .g 0,0
.CE
.PP
The \fBnamespace import\fR command only imports commands
from a namespace that that namespace exported
with a \fBnamespace export\fR command.
.PP
618
619
620
621
622
623
624
625

626
627
628
629
630
631
632
635
636
637
638
639
640
641

642
643
644
645
646
647
648
649







-
+







different packages.  But from time to time (perhaps when debugging),
you may want to get around this restriction.  You may want to
reissue the \fBnamespace import\fR command to pick up new commands
that have appeared in a namespace.  In that case, you can use the
\fB\-force\fR option, and existing commands will be silently overwritten:
.PP
.CS
\fBnamespace import\fR \-force Blt::graph Blt::table
\fBnamespace import\fR -force Blt::graph Blt::table
.CE
.PP
If for some reason, you want to stop using the imported commands,
you can remove them with a \fBnamespace forget\fR command, like this:
.PP
.CS
\fBnamespace forget\fR Blt::*
726
727
728
729
730
731
732

733
734
735
736
737
738
739
740
741
742
743

744
745
746
747
748
749
750

751
752

753
754
755
756
757
758
759
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771

772
773
774
775
776
777
778
779







+











+







+

-
+







may be any number of ensembles associated with any namespace
(including none, which is true of all namespaces by default), though
all the ensembles associated with a namespace are deleted when that
namespace is deleted.  The link between an ensemble command and its
namespace is maintained however the ensemble is renamed.
.PP
Three subcommands of the \fBnamespace ensemble\fR command are defined:
.\" METHOD: create
.TP
\fBnamespace ensemble create\fR ?\fIoption value ...\fR?
.
Creates a new ensemble command linked to the current namespace,
returning the fully qualified name of the command created.  The
arguments to \fBnamespace ensemble create\fR allow the configuration
of the command as if with the \fBnamespace ensemble configure\fR
command.  If not overridden with the \fB\-command\fR option, this
command creates an ensemble with exactly the same name as the linked
namespace.  See the section \fBENSEMBLE OPTIONS\fR below for a full
list of options supported and their effects.
.\" METHOD: configure
.TP
\fBnamespace ensemble configure \fIcommand\fR ?\fIoption\fR? ?\fIvalue ...\fR?
.
Retrieves the value of an option associated with the ensemble command
named \fIcommand\fR, or updates some options associated with that
ensemble command.  See the section \fBENSEMBLE OPTIONS\fR below for a
full list of options supported and their effects.
.\" METHOD: exists
.TP
\fBnamespace ensemble exists\fR \fIcommand\fR
\fBnamespace ensemble exists\fI command\fR
.
Returns a boolean value that describes whether the command
\fIcommand\fR exists and is an ensemble command.  This command only
ever returns an error if the number of arguments to the command is
wrong.
.PP
When called, an ensemble command takes its first argument and looks it
767
768
769
770
771
772
773

774
775
776
777
778
779
780
781
782
783
784
785
786
787
788

789
790

791
792
793
794

795
796
797
798
799
800
801

802
803
804
805
806
807
808
809
810
811
812

813
814
815
816
817
818
819
820
821
822
823
824
825
826

827
828
829
830
831
832
833
834
835
836
837

838
839
840
841
842
843
844
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872







+















+


+




+







+











+














+











+







command.  The ensemble command will not be visible through the use of
the \fBuplevel\fR or \fBinfo level\fR commands.
.SS "ENSEMBLE OPTIONS"
.PP
The following options, supported by the \fBnamespace ensemble
create\fR and \fBnamespace ensemble configure\fR commands, control how
an ensemble command behaves:
.\" OPTION: -map
.TP
\fB\-map\fR
.
When non-empty, this option supplies a dictionary that provides a
mapping from subcommand names to a list of prefix words to substitute
in place of the ensemble command and subcommand words (in a manner
similar to an alias created with \fBinterp alias\fR; the words are not
reparsed after substitution); if the first word of any target is not
fully qualified when set, it is assumed to be relative to the
\fIcurrent\fR namespace and changed to be exactly that (that is, it is
always fully qualified when read). When this option is empty, the mapping
will be from the local name of the subcommand to its fully-qualified
name.  Note that when this option is non-empty and the
\fB\-subcommands\fR option is empty, the ensemble subcommand names
will be exactly those words that have mappings in the dictionary.
.\" OPTION: -parameters
.TP
\fB\-parameters\fR
.
This option gives a list of named arguments (the names being used during
generation of error messages) that are passed by the caller of the ensemble
between the name of the ensemble and the subcommand argument. By default, it
is the empty list.
.\" OPTION: -prefixes
.TP
\fB\-prefixes\fR
.
This option (which is enabled by default) controls whether the
ensemble command recognizes unambiguous prefixes of its subcommands.
When turned off, the ensemble command requires exact matching of
subcommand names.
.\" OPTION: -subcommands
.TP
\fB\-subcommands\fR
.
When non-empty, this option lists exactly what subcommands are in the
ensemble.  The mapping for each of those commands will be either whatever
is defined in the \fB\-map\fR option, or to the command with the same
name in the namespace linked to the ensemble.  If this option is
empty, the subcommands of the namespace will either be the keys of the
dictionary listed in the \fB\-map\fR option or the exported commands
of the linked namespace at the time of the invocation of the ensemble
command.
.\" OPTION: -unknown
.TP
\fB\-unknown\fR
.
When non-empty, this option provides a partial command (to which all
the words that are arguments to the ensemble command, including the
fully-qualified name of the ensemble, are appended) to handle the case
where an ensemble subcommand is not recognized and would otherwise
generate an error.  When empty (the default) an error (in the style of
\fBTcl_GetIndexFromObj\fR) is generated whenever the ensemble is
unable to determine how to implement a particular subcommand.  See
\fBUNKNOWN HANDLER BEHAVIOUR\fR for more details.
.PP
The following extra option is allowed by \fBnamespace ensemble
create\fR:
.\" OPTION: -command
.TP
\fB\-command\fR
.
This write-only option allows the name of the ensemble created by
\fBnamespace ensemble create\fR to be anything in any existing
namespace.  The default value for this option is the fully-qualified
name of the namespace in which the \fBnamespace ensemble create\fR
command is invoked.
.PP
The following extra option is allowed by \fBnamespace ensemble
configure\fR:
.\" OPTION: -namespace
.TP
\fB\-namespace\fR
.
This read-only option allows the retrieval of the fully-qualified name
of the namespace which the ensemble was created within.
.SS "UNKNOWN HANDLER BEHAVIOUR"
.PP

Changes to doc/next.n.

8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
next, nextto \- invoke superclass method implementations
.SH SYNOPSIS
.nf
package require TclOO
package require tcl::oo

\fBnext\fR ?\fIarg ...\fR?
\fBnextto\fI class\fR ?\fIarg ...\fR?
.fi
.BE

.SH DESCRIPTION
30
31
32
33
34
35
36
37
38
39
40




41
42
43
44
45
46
47
30
31
32
33
34
35
36




37
38
39
40
41
42
43
44
45
46
47







-
-
-
-
+
+
+
+







of the next method in the method chain; if there are no further methods in the
method chain, the result of \fBnext\fR will be an error. The arguments,
\fIarg\fR, to \fBnext\fR are the arguments to pass to the next method in the
chain.
.PP
The \fBnextto\fR command is the same as the \fBnext\fR command, except that it
takes an additional \fIclass\fR argument that identifies a class whose
implementation of the current method chain (see \fBinfo object\fR \fBcall\fR) should
be used; the method implementation selected will be the one provided by the
given class, and it must refer to an existing non-filter invocation that lies
further along the chain than the current implementation.
implementation of the current method chain (see \fBinfo object\fR \fBcall\fR)
should be used; the method implementation selected will be the one provided by
the given class, and it must refer to an existing non-filter invocation that
lies further along the chain than the current implementation.
.SH "THE METHOD CHAIN"
.PP
When a method of an object is invoked, things happen in several stages:
.IP [1]
The structure of the object, its class, superclasses, filters, and mixins, are
examined to build a \fImethod chain\fR, which contains a list of method
implementations to invoke.
92
93
94
95
96
97
98
99

100
101
102
103
104
105
106
92
93
94
95
96
97
98

99
100
101
102
103
104
105
106







-
+







a filter and once as a normal method.
.PP
Each filter should decide for itself whether to permit the execution to go
forward to the proper implementation of the method (which it does by invoking
the \fBnext\fR command as filters are inserted into the front of the method
call chain) and is responsible for returning the result of \fBnext\fR.
.PP
Filters are invoked when processing an invokation of the \fBunknown\fR
Filters are invoked when processing an invocation of the \fBunknown\fR
method because of a failure to locate a method implementation, but \fInot\fR
when invoking either constructors or destructors. (Note however that the
\fBdestroy\fR method is a conventional method, and filters are invoked as
normal when it is called.)
.SH EXAMPLES
.PP
This example demonstrates how to use the \fBnext\fR command to call the

Changes to doc/object.n.

8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
oo::object \- root class of the class hierarchy
.SH SYNOPSIS
.nf
package require TclOO
package require tcl::oo

\fBoo::object\fI method \fR?\fIarg ...\fR?
.fi
.SH "CLASS HIERARCHY"
.nf
\fBoo::object\fR
.fi
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
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







+










+






+
+
+
+
+
+














+








+





+







across renamings of the object.
.SS CONSTRUCTOR
The \fBoo::object\fR class does not define an explicit constructor.
.SS DESTRUCTOR
The \fBoo::object\fR class does not define an explicit destructor.
.SS "EXPORTED METHODS"
The \fBoo::object\fR class supports the following exported methods:
.\" METHOD: destroy
.TP
\fIobj \fBdestroy\fR
.
This method destroys the object, \fIobj\fR, that it is invoked upon, invoking
any destructors on the object's class in the process. It is equivalent to
using \fBrename\fR to delete the object command. The result of this method is
always the empty string.
.SS "NON-EXPORTED METHODS"
.PP
The \fBoo::object\fR class supports the following non-exported methods:
.\" METHOD: eval
.TP
\fIobj \fBeval\fR ?\fIarg ...\fR?
.
This method concatenates the arguments, \fIarg\fR, as if with \fBconcat\fR,
and then evaluates the resulting script in the namespace that is uniquely
associated with \fIobj\fR, returning the result of the evaluation.
.RS
.PP
Note that object-internal commands such as \fBmy\fR and \fBself\fR can be
invoked in this context.
.RE
.\" METHOD: unknown
.TP
\fIobj \fBunknown ?\fImethodName\fR? ?\fIarg ...\fR?
.
This method is called when an attempt to invoke the method \fImethodName\fR on
object \fIobj\fR fails. The arguments that the user supplied to the method are
given as \fIarg\fR arguments.
.VS
If \fImethodName\fR is absent, the object was invoked with no method name at
all (or any other arguments).
.VE
The default implementation (i.e., the one defined by the \fBoo::object\fR
class) generates a suitable error, detailing what methods the object supports
given whether the object was invoked by its public name or through the
\fBmy\fR command.
.\" METHOD: variable
.TP
\fIobj \fBvariable \fR?\fIvarName ...\fR?
.
This method arranges for each variable called \fIvarName\fR to be linked from
the object \fIobj\fR's unique namespace into the caller's context. Thus, if it
is invoked from inside a procedure then the namespace variable in the object
is linked to the local variable in the procedure. Each \fIvarName\fR argument
must not have any namespace separators in it. The result is the empty string.
.\" METHOD: varname
.TP
\fIobj \fBvarname \fIvarName\fR
.
This method returns the globally qualified name of the variable \fIvarName\fR
in the unique namespace for the object \fIobj\fR.
.\" METHOD: <cloned>
.TP
\fIobj \fB<cloned> \fIsourceObjectName\fR
.VS
This method is used by the \fBoo::object\fR command to copy the state of one
object to another. It is responsible for copying the procedures and variables
of the namespace of the source object (\fIsourceObjectName\fR) to the current
object. It does not copy any other types of commands or any traces on the

Changes to doc/open.n.

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
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







-
+

-

-

+














-
-
+
-


-
-
+
-


-
-
+
-


-
-
+
-


-
-
+
-



-
-
+
-











-
+

-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-


-
-
+
-


-
-
+
-


-
-
+
-







-
-
+
-






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







.TH open n 8.3 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
open \- Open a file-based or command pipeline channel
.SH SYNOPSIS
.sp
.nf
\fBopen \fIfileName\fR
.br
\fBopen \fIfileName access\fR
.br
\fBopen \fIfileName access permissions\fR
.fi
.BE
.SH DESCRIPTION
.PP
This command opens a file, serial port, or command pipeline and returns a
channel identifier that may be used in future invocations of commands like
\fBread\fR, \fBputs\fR, and \fBclose\fR.
If the first character of \fIfileName\fR is not \fB|\fR then
the command opens a file:
\fIfileName\fR gives the name of the file to open, and it must conform to the
conventions described in the \fBfilename\fR manual entry.
.PP
The \fIaccess\fR argument, if present, indicates the way in which the file
(or command pipeline) is to be accessed.
In the first form \fIaccess\fR may have any of the following values:
.TP 15
\fBr\fR
.IP \fBr\fR
.
Open the file for reading only; the file must already exist. This is the
default value if \fIaccess\fR is not specified.
.TP 15
\fBr+\fR
.IP \fBr+\fR
.
Open the file for both reading and writing; the file must
already exist.
.TP 15
\fBw\fR
.IP \fBw\fR
.
Open the file for writing only.  Truncate it if it exists.  If it does not
exist, create a new file.
.TP 15
\fBw+\fR
.IP \fBw+\fR
.
Open the file for reading and writing.  Truncate it if it exists.
If it does not exist, create a new file.
.TP 15
\fBa\fR
.IP \fBa\fR
.
Open the file for writing only.  If the file does not exist,
create a new empty file.
Set the file pointer to the end of the file prior to each write.
.TP 15
\fBa+\fR
.IP \fBa+\fR
.
Open the file for reading and writing.  If the file does not exist,
create a new empty file.
Set the initial access position  to the end of the file.
.PP
All of the legal \fIaccess\fR values above may have the character
\fBb\fR added as the second or third character in the value to
indicate that the opened channel should be configured as if with the
\fBfconfigure\fR \fB\-translation binary\fR option, making the channel suitable for
reading or writing of binary data.
.PP
In the second form, \fIaccess\fR consists of a list of any of the
following flags, all of which have the standard POSIX meanings.
following flags, most of which have the standard POSIX meanings.
One of the flags must be either \fBRDONLY\fR, \fBWRONLY\fR or \fBRDWR\fR.
.TP 15
\fBRDONLY\fR
.IP \fBRDONLY\fR
.
Open the file for reading only.
.TP 15
\fBWRONLY\fR
.IP \fBWRONLY\fR
.
Open the file for writing only.
.TP 15
\fBRDWR\fR
.IP \fBRDWR\fR
.
Open the file for both reading and writing.
.TP 15
\fBAPPEND\fR
.IP \fBAPPEND\fR
.
Set the file pointer to the end of the file prior to each write.
.TP 15
\fBBINARY\fR
.IP \fBBINARY\fR
.
Configure the opened channel with the \fB\-translation binary\fR option.
.TP 15
\fBCREAT\fR
.IP \fBCREAT\fR
.
Create the file if it does not already exist (without this flag it
is an error for the file not to exist).
.TP 15
\fBEXCL\fR
.IP \fBEXCL\fR
.
If \fBCREAT\fR is also specified, an error is returned if the
file already exists.
.TP 15
\fBNOCTTY\fR
.IP \fBNOCTTY\fR
.
If the file is a terminal device, this flag prevents the file from
becoming the controlling terminal of the process.
.TP 15
\fBNONBLOCK\fR
.IP \fBNONBLOCK\fR
.
Prevents the process from blocking while opening the file, and
possibly in subsequent I/O operations.  The exact behavior of
this flag is system- and device-dependent;  its use is discouraged
(it is better to use the \fBfconfigure\fR command to put a file
in nonblocking mode).
For details refer to your system documentation on the \fBopen\fR system
call's \fBO_NONBLOCK\fR flag.
.TP 15
\fBTRUNC\fR
.IP \fBTRUNC\fR
.
If the file exists it is truncated to zero length.
.PP
If a new file is created as part of opening it, \fIpermissions\fR
(an integer) is used to set the permissions for the new file in
conjunction with the process's file mode creation mask.
\fIPermissions\fR defaults to 0666.
.PP
.VS "8.7, TIP 603"
When the file opened is an ordinary disk file, the \fBchan configure\fR and
\fBfconfigure\fR commands can be used to query this additional configuration
option:
.\" OPTION: -stat
.TP
\fB\-stat\fR
.
This option, when read, returns a dictionary of values much as is obtained
from the \fBfile stat\fR command, where that stat information relates to the
real opened file. Keys in the dictionary may include \fBatime\fR, \fBctime\fR,
\fBdev\fR, \fBgid\fR, \fBino\fR, \fBmode\fR, \fBmtime\fR, \fBnlink\fR,
\fBsize\fR, \fBtype\fR, and \fBuid\fR among others; the \fBmtime\fR,
\fBsize\fR and \fBtype\fR fields are guaranteed to be present and meaningful
on all platforms; other keys may be present too.
.RS
.PP
\fIImplementation note:\fR This option maps to a call to \fBfstat()\fR on
POSIX platforms, and to a call to \fBGetFileInformationByHandle()\fR on
Windows; the information reported is what those system calls produce.
.RE
.VE "8.7, TIP 603"
.SH "COMMAND PIPELINES"
.PP
If the first character of \fIfileName\fR is
.QW \fB|\fR
then the
remaining characters of \fIfileName\fR are treated as a list of arguments
that describe a command pipeline to invoke, in the same style as the
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
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
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
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







+

-
+















+

-
+
















+






+

-
+








+

-
+











+









+

-
+





+

-
+






-
-
+
-


-
-
+
-



-
-
+
-




+

-
+







-
-
+
-


-
-
+
-



-
-
+
-



-
-
+
-







+







+

-
+







+

-
+

-
+






+


















-
+

-
+

-
+



-
+


-
+



-
+


-
+



-
+

















-
-
+
-

-
-
+
+
-
-
+
-


-
-
+
-




-
-
+
-

-
-
+
+
-
-
+
-

-
-
+
+
-
-
+
-







is opened and initialized in a platform-dependent manner.  Acceptable
values for the \fIfileName\fR to use to open a serial port are described in
the PORTABILITY ISSUES section.
.PP
The \fBchan configure\fR and \fBfconfigure\fR commands can be used to query
and set additional configuration options specific to serial ports (where
supported):
.\" OPTION: -mode
.TP
\fB\-mode\fR \fIbaud\fB,\fIparity\fB,\fIdata\fB,\fIstop\fR
\fB\-mode\fI baud\fB,\fIparity\fB,\fIdata\fB,\fIstop\fR
.
This option is a set of 4 comma-separated values: the baud rate, parity,
number of data bits, and number of stop bits for this serial port.  The
\fIbaud\fR rate is a simple integer that specifies the connection speed.
\fIParity\fR is one of the following letters: \fBn\fR, \fBo\fR, \fBe\fR,
\fBm\fR, \fBs\fR; respectively signifying the parity options of
.QW none ,
.QW odd ,
.QW even ,
.QW mark ,
or
.QW space .
\fIData\fR is the number of
data bits and should be an integer from 5 to 8, while \fIstop\fR is the
number of stop bits and should be the integer 1 or 2.
.\" OPTION: -handshake
.TP
\fB\-handshake\fR \fItype\fR
\fB\-handshake\fI type\fR
.
(Windows and Unix). This option is used to setup automatic handshake
control. Note that not all handshake types maybe supported by your operating
system. The \fItype\fR parameter is case-independent.
.RS
.PP
If \fItype\fR is \fBnone\fR then any handshake is switched off.
\fBrtscts\fR activates hardware handshake. Hardware handshake signals
are described below.
For software handshake \fBxonxoff\fR the handshake characters can be redefined
with \fB\-xchar\fR.
An additional hardware handshake \fBdtrdsr\fR is available only under Windows.
There is no default handshake configuration, the initial value depends
on your operating system settings.
The \fB\-handshake\fR option cannot be queried.
.RE
.\" OPTION: -queue
.TP
\fB\-queue\fR
.
(Windows and Unix). The \fB\-queue\fR option can only be queried.
It returns a list of two integers representing the current number
of bytes in the input and output queue respectively.
.\" OPTION: -timeout
.TP
\fB\-timeout\fR \fImsec\fR
\fB\-timeout\fI msec\fR
.
(Windows and Unix). This option is used to set the timeout for blocking
read operations. It specifies the maximum interval between the
reception of two bytes in milliseconds.
For Unix systems the granularity is 100 milliseconds.
The \fB\-timeout\fR option does not affect write operations or
nonblocking reads.
This option cannot be queried.
.\" OPTION: -ttycontrol
.TP
\fB\-ttycontrol\fR \fI{signal boolean signal boolean ...}\fR
\fB\-ttycontrol\fI {signal boolean signal boolean ...}\fR
.
(Windows and Unix). This option is used to setup the handshake
output lines (see below) permanently or to send a BREAK over the serial line.
The \fIsignal\fR names are case-independent.
\fB{RTS 1 DTR 0}\fR sets the RTS output to high and the DTR output to low.
The BREAK condition (see below) is enabled and disabled with \fB{BREAK 1}\fR and
\fB{BREAK 0}\fR respectively.
It is not a good idea to change the \fBRTS\fR (or \fBDTR\fR) signal
with active hardware handshake \fBrtscts\fR (or \fBdtrdsr\fR).
The result is unpredictable.
The \fB\-ttycontrol\fR option cannot be queried.
.\" OPTION: -ttystatus
.TP
\fB\-ttystatus\fR
.
(Windows and Unix). The \fB\-ttystatus\fR option can only be
queried.  It returns the current modem status and handshake input signals
(see below).
The result is a list of signal,value pairs with a fixed order,
e.g. \fB{CTS 1 DSR 0 RING 1 DCD 0}\fR.
The \fIsignal\fR names are returned upper case.
.\" OPTION: -xchar
.TP
\fB\-xchar\fR \fI{xonChar xoffChar}\fR
\fB\-xchar\fI {xonChar xoffChar}\fR
.
(Windows and Unix). This option is used to query or change the software
handshake characters. Normally the operating system default should be
DC1 (0x11) and DC3 (0x13) representing the ASCII standard
XON and XOFF characters.
.\" OPTION: -closemode
.TP
\fB\-closemode\fR \fIcloseMode\fR
\fB\-closemode\fI closeMode\fR
.VS "8.7, TIP 160"
(Windows and Unix). This option is used to query or change the close mode of
the serial channel, which defines how pending output in operating system
buffers is handled when the channel is closed. The following values for
\fIcloseMode\fR are supported:
.RS
.TP
\fBdefault\fR
.IP \fBdefault\fR
.
indicates that a system default operation should be used; all serial channels
default to this.
.TP
\fBdiscard\fR
.IP \fBdiscard\fR
.
indicates that the contents of the OS buffers should be discarded.  Note that
this is \fInot recommended\fR when writing to a POSIX terminal, as it can
interact unexpectedly with handling of \fBstderr\fR.
.TP
\fBdrain\fR
.IP \fBdrain\fR
.
indicates that Tcl should wait when closing the channel until all output has
been consumed. This may slow down \fBclose\fR noticeably.
.RE
.VE "8.7, TIP 160"
.\" OPTION: -inputmode
.TP
\fB\-inputmode\fR \fIinputMode\fR
\fB\-inputmode\fI inputMode\fR
.VS "8.7, TIP 160"
(Unix only; Windows has the equivalent option on console channels). This
option is used to query or change the input mode of the serial channel under
the assumption that it is talking to a terminal, which controls how interactive
input from users is handled. The following values for \fIinputMode\fR are
supported:
.RS
.TP
\fBnormal\fR
.IP \fBnormal\fR
.
indicates that normal line-oriented input should be used, with standard
terminal editing capabilities enabled.
.TP
\fBpassword\fR
.IP \fBpassword\fR
.
indicates that non-echoing input should be used, with standard terminal
editing capabilities enabled but no writing of typed characters to the
terminal (except for newlines). Some terminals may indicate this specially.
.TP
\fBraw\fR
.IP \fBraw\fR
.
indicates that all keyboard input should be given directly to Tcl with the
terminal doing no processing at all. It does not echo the keys, leaving it up
to the Tcl script to interpret what to do.
.TP
\fBreset\fR (set only)
.IP "\fBreset\fR (set only)"
.
indicates that the terminal should be reset to what state it was in when the
terminal was opened.
.PP
Note that setting this option (technically, anything that changes the terminal
state from its initial value \fIvia this option\fR) will cause the channel to
turn on an automatic reset of the terminal when the channel is closed.
.RE
.\" OPTION: -winsize
.TP
\fB\-winsize\fR
.
(Unix only; Windows has the equivalent option on console channels). This
option is query only. It retrieves a two-element list with the the current
width and height of the terminal.
.VE "8.7, TIP 160"
.\" OPTION: -pollinterval
.TP
\fB\-pollinterval\fR \fImsec\fR
\fB\-pollinterval\fI msec\fR
.
(Windows only). This option is used to set the maximum time between
polling for fileevents.
This affects the time interval between checking for events throughout the Tcl
interpreter (the smallest value always wins).  Use this option only if
you want to poll the serial port more or less often than 10 msec
(the default).
.\" OPTION: -sysbuffer
.TP
\fB\-sysbuffer\fR \fIinSize\fR
\fB\-sysbuffer\fI inSize\fR
.TP
\fB\-sysbuffer\fR \fI{inSize outSize}\fR
\fB\-sysbuffer\fI {inSize outSize}\fR
.
(Windows only). This option is used to change the size of Windows
system buffers for a serial channel. Especially at higher communication
rates the default input buffer size of 4096 bytes can overrun
for latent systems. The first form specifies the input buffer size,
in the second form both input and output buffers are defined.
.\" OPTION: -lasterror
.TP
\fB\-lasterror\fR
.
(Windows only). This option is query only.
In case of a serial communication error, \fBread\fR or \fBputs\fR
returns a general Tcl file I/O error.
\fBfconfigure\fR \fB\-lasterror\fR can be called to get a list of error details.
See below for an explanation of the various error codes.
.SS "SERIAL PORT SIGNALS"
.PP
RS-232 is the most commonly used standard electrical interface for serial
communications. A negative voltage (-3V..-12V) define a mark (on=1) bit and
a positive voltage (+3..+12V) define a space (off=0) bit (RS-232C).  The
following signals are specified for incoming and outgoing data, status
lines and handshaking. Here we are using the terms \fIworkstation\fR for
your computer and \fImodem\fR for the external device, because some signal
names (DCD, RI) come from modems. Of course your external device may use
these signal lines for other purposes.
.IP \fBTXD\fR(output)
.IP "\fBTXD\fR (output)"
\fBTransmitted Data:\fR Outgoing serial data.
.IP \fBRXD\fR(input)
.IP "\fBRXD\fR (input)"
\fBReceived Data:\fRIncoming serial data.
.IP \fBRTS\fR(output)
.IP "\fBRTS\fR (output)"
\fBRequest To Send:\fR This hardware handshake line informs the modem that
your workstation is ready to receive data. Your workstation may
automatically reset this signal to indicate that the input buffer is full.
.IP \fBCTS\fR(input)
.IP "\fBCTS\fR (input)"
\fBClear To Send:\fR The complement to RTS. Indicates that the modem is
ready to receive data.
.IP \fBDTR\fR(output)
.IP "\fBDTR\fR (output)"
\fBData Terminal Ready:\fR This signal tells the modem that the workstation
is ready to establish a link. DTR is often enabled automatically whenever a
serial port is opened.
.IP \fBDSR\fR(input)
.IP "\fBDSR\fR (input)"
\fBData Set Ready:\fR The complement to DTR. Tells the workstation that the
modem is ready to establish a link.
.IP \fBDCD\fR(input)
.IP "\fBDCD\fR (input)"
\fBData Carrier Detect:\fR This line becomes active when a modem detects a
.QW Carrier
signal.
.IP \fBRI\fR(input)
.IP "\fBRI\fR (input)"
\fBRing Indicator:\fR Goes active when the modem detects an incoming call.
.IP \fBBREAK\fR
A BREAK condition is not a hardware signal line, but a logical zero on the
TXD or RXD lines for a long period of time, usually 250 to 500
milliseconds.  Normally a receive or transmit data signal stays at the mark
(on=1) voltage until the next character is transferred. A BREAK is sometimes
used to reset the communications line or change the operating mode of
communications hardware.
.SS "ERROR CODES (Windows only)"
.PP
A lot of different errors may occur during serial read operations or during
event polling in background. The external device may have been switched
off, the data lines may be noisy, system buffers may overrun or your mode
settings may be wrong.  That is why a reliable software should always
\fBcatch\fR serial read operations.  In cases of an error Tcl returns a
general file I/O error.  Then \fBfconfigure\fR \fB\-lasterror\fR may help to
locate the problem.  The following error codes may be returned.
.TP 10
\fBRXOVER\fR
.IP \fBRXOVER\fR
.
Windows input buffer overrun. The data comes faster than your scripts reads
it or your system is overloaded. Use \fBfconfigure\fR \fB\-sysbuffer\fR to avoid a
temporary bottleneck and/or make your script faster.
it or your system is overloaded. Use \fBfconfigure\fR \fB\-sysbuffer\fR to
avoid a temporary bottleneck and/or make your script faster.
.TP 10
\fBTXFULL\fR
.IP \fBTXFULL\fR
.
Windows output buffer overrun. Complement to RXOVER. This error should
practically not happen, because Tcl cares about the output buffer status.
.TP 10
\fBOVERRUN\fR
.IP \fBOVERRUN\fR
.
UART buffer overrun (hardware) with data lost.
The data comes faster than the system driver receives it.
Check your advanced serial port settings to enable the FIFO (16550) buffer
and/or setup a lower(1) interrupt threshold value.
.TP 10
\fBRXPARITY\fR
.IP \fBRXPARITY\fR
.
A parity error has been detected by your UART.
Wrong parity settings with \fBfconfigure\fR \fB\-mode\fR or a noisy data line (RXD)
may cause this error.
Wrong parity settings with \fBfconfigure\fR \fB\-mode\fR or a noisy data line
(RXD) may cause this error.
.TP 10
\fBFRAME\fR
.IP \fBFRAME\fR
.
A stop-bit error has been detected by your UART.
Wrong mode settings with \fBfconfigure\fR \fB\-mode\fR or a noisy data line (RXD)
may cause this error.
Wrong mode settings with \fBfconfigure\fR \fB\-mode\fR or a noisy data line
(RXD) may cause this error.
.TP 10
\fBBREAK\fR
.IP \fBBREAK\fR
.
A BREAK condition has been detected by your UART (see above).
.SS "PORTABILITY ISSUES"
.TP
\fBWindows \fR
.
Valid values for \fIfileName\fR to open a serial port are of the form
\fBcom\fIX\fB\fR, where \fIX\fR is a number, generally from 1 to 9.
449
450
451
452
453
454
455






456
457
458

459
460
461
462
463
464
465
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440

441
442
443
444
445
446
447
448







+
+
+
+
+
+


-
+







some will be sent to the Tcl evaluator.  If a command pipeline is opened for
writing, keystrokes entered into the console are not visible until the
pipe is closed.  These problems only occur because both Tcl and the child
application are competing for the console at the same time.  If the command
pipeline is started from a script, so that Tcl is not accessing the console,
or if the command pipeline does not use standard input or output, but is
redirected from or to a file, then the above problems do not occur.
.PP
Files opened in the
.QW \fBa\fR
mode or with the \fBAPPEND\fR flag set are implemented by seeking immediately
before each write, which is not an atomic operation and does not carry the
guarantee of strict appending that is present on POSIX platforms.
.RE
.TP
\fBUnix\fR\0\0\0\0\0\0\0
\fBUnix \fR
.
Valid values for \fIfileName\fR to open a serial port are generally of the
form \fB/dev/tty\fIX\fR, where \fIX\fR is \fBa\fR or \fBb\fR, but the name
of any pseudo-file that maps to a serial port may be used.
Advanced configuration options are only supported for serial ports
when Tcl is built to use the POSIX serial interface.
.RS
478
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
461
462
463
464
465
466
467
468
469

470
471
472
473
474
475


476

477
478


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







+

-
+





-
-
+
-


-
-
+
-

-
+

-
-
+
-













+




-
+






+
+
+
+
+
+
+
+
+
+
+
+
+










+
+
+
+
+
+
+
+
+
+
+
+







See the \fBPORTABILITY ISSUES\fR section of the \fBexec\fR command for
additional information not specific to command pipelines about executing
applications on the various platforms
.SH "CONSOLE CHANNELS"
.VS "8.7, TIP 160"
On Windows only, console channels (usually \fBstdin\fR or \fBstdout\fR)
support the following options:
.\" OPTION: -inputmode
.TP
\fB\-inputmode\fR \fIinputMode\fR
\fB\-inputmode\fI inputMode\fR
.
This option is used to query or change the input mode of the console channel,
which controls how interactive input from users is handled. The following
values for \fIinputMode\fR are supported:
.RS
.TP
\fBnormal\fR
.IP \fBnormal\fR
.
indicates that normal line-oriented input should be used, with standard
console editing capabilities enabled.
.TP
\fBpassword\fR
.IP \fBpassword\fR
.
indicates that non-echoing input should be used, with standard console
editing capabilitied enabled but no writing of typed characters to the
editing capabilities enabled but no writing of typed characters to the
terminal (except for newlines).
.TP
\fBraw\fR
.IP \fBraw\fR
.
indicates that all keyboard input should be given directly to Tcl with the
console doing no processing at all. It does not echo the keys, leaving it up
to the Tcl script to interpret what to do.
.TP
\fBreset\fR (set only)
.
indicates that the console should be reset to what state it was in when the
console channel was opened.
.PP
Note that setting this option (technically, anything that changes the console
state from its default \fIvia this option\fR) will cause the channel to turn
on an automatic reset of the console when the channel is closed.
.RE
.\" OPTION: -winsize
.TP
\fB\-winsize\fR
.
This option is query only.
It retrieves a two-element list with the the current width and height of the
It retrieves a two-element list with the current width and height of the
console that this channel is talking to.
.PP
Note that the equivalent options exist on Unix, but are on the serial channel
type.
.VE "8.7, TIP 160"
.SH "EXAMPLES"
Open a file for writing, forcing it to be created and raising an error if it
already exists.
.PP
.CS
set myNewFile [\fBopen\fR filename.txt {WRONLY CREAT EXCL}]
.CE
.PP
Open a file for writing as a log file.
.PP
.CS
set myLogFile [\fBopen\fR filename.log "a"]
fconfigure $myLogFile -buffering line
.CE
.PP
Open a command pipeline and catch any errors:
.PP
.CS
set fl [\fBopen\fR "| ls this_file_does_not_exist"]
set data [read $fl]
if {[catch {close $fl} err]} {
    puts "ls command failed: $err"
}
.CE
.PP
Open a command pipeline and read binary data from it. Note the unusual form
with
.QW |[list
that handles non-trivial edge cases with arguments that potentially have
spaces in.
.PP
.CS
set fl [\fBopen\fR |[list create_image_data $input] "rb"]
set binData [read $fl]
close $fl
.CE
.PP
.VS "8.7, TIP 160"
Read a password securely from the user (assuming that the script is being run
interactively):
.PP
.CS
chan configure stdin \fB-inputmode password\fR

Changes to doc/package.n.

8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
package \- Facilities for package loading and version control
.SH SYNOPSIS
.nf
\fBpackage files\fR \fIpackage\fR
\fBpackage files\fI package\fR
\fBpackage forget\fR ?\fIpackage package ...\fR?
\fBpackage ifneeded \fIpackage version\fR ?\fIscript\fR?
\fBpackage names\fR
\fBpackage present \fIpackage \fR?\fIrequirement...\fR?
\fBpackage present \-exact \fIpackage version\fR
\fBpackage provide \fIpackage \fR?\fIversion\fR?
\fBpackage require \fIpackage \fR?\fIrequirement...\fR?
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
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







+

-
+





+






+







This command also detects and reports version clashes.
Typically, only the \fBpackage require\fR and \fBpackage provide\fR
commands are invoked in normal Tcl scripts;  the other commands are used
primarily by system scripts that maintain the package database.
.PP
The behavior of the \fBpackage\fR command is determined by its first argument.
The following forms are permitted:
.\" METHOD: files
.TP
\fBpackage files\fR \fIpackage\fR
\fBpackage files \fIpackage\fR
.
Lists all files forming part of \fIpackage\fR. Auto-loaded files are not
included in this list, only files which were directly sourced during package
initialization. The list order corresponds with the order in which the
files were sourced.
.\" METHOD: forget
.TP
\fBpackage forget\fR ?\fIpackage package ...\fR?
.
Removes all information about each specified package from this interpreter,
including information provided by both \fBpackage ifneeded\fR and
\fBpackage provide\fR.
.\" METHOD: ifneeded
.TP
\fBpackage ifneeded \fIpackage version\fR ?\fIscript\fR?
.
This command typically appears only in system configuration
scripts to set up the package database.
It indicates that a particular version of
a particular package is available if needed, and that the package
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
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







+








+





+













+







If the database already contains information for \fIpackage\fR
and \fIversion\fR, the new \fIscript\fR replaces the existing
one.
If the \fIscript\fR argument is omitted, the current script for
version \fIversion\fR of package \fIpackage\fR is returned,
or an empty string if no \fBpackage ifneeded\fR command has
been invoked for this \fIpackage\fR and \fIversion\fR.
.\" METHOD: names
.TP
\fBpackage names\fR
.
Returns a list of the names of all packages in the
interpreter for which a version has been provided (via
\fBpackage provide\fR) or for which a \fBpackage ifneeded\fR
script is available.
The order of elements in the list is arbitrary.
.\" METHOD: present
.TP
\fBpackage present\fR ?\fB\-exact\fR? \fIpackage\fR ?\fIrequirement...\fR?
.
This command is equivalent to \fBpackage require\fR except that it
does not try and load the package if it is not already loaded.
.\" METHOD: provide
.TP
\fBpackage provide \fIpackage \fR?\fIversion\fR?
.
This command is invoked to indicate that version \fIversion\fR
of package \fIpackage\fR is now present in the interpreter.
It is typically invoked once as part of an \fBifneeded\fR script,
and again by the package itself when it is finally loaded.
An error occurs if a different version of \fIpackage\fR has been
provided by a previous \fBpackage provide\fR command.
If the \fIversion\fR argument is omitted, then the command
returns the version number that is currently provided, or an
empty string if no \fBpackage provide\fR command has been
invoked for \fIpackage\fR in this interpreter.
.\" METHOD: require
.TP
\fBpackage require \fR\fIpackage \fR?\fIrequirement...\fR?
.
This command is typically invoked by Tcl code that wishes to use
a particular version of a particular package.  The arguments
indicate which package is wanted, and the command ensures that
a suitable version of the package is loaded into the interpreter.
152
153
154
155
156
157
158

159
160
161
162
163
164
165
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173







+







.RE
.TP
\fBpackage require \-exact \fIpackage version\fR
.
This form of the command is used when only the given \fIversion\fR
of \fIpackage\fR is acceptable to the caller.  This command is
equivalent to \fBpackage require \fIpackage version\fR-\fIversion\fR.
.\" METHOD: unknown
.TP
\fBpackage unknown \fR?\fIcommand\fR?
.
This command supplies a
.QW "last resort"
command to invoke during
\fBpackage require\fR if no suitable version of a package can be found
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
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







+






+






+







-
-
+
-


-
-
+
-


-
-
+
-


-
-


-
+

-
+



-
-







If no requirements are supplied to the \fBpackage require\fR command,
then only the name will be added to invoked command.
If the \fBpackage unknown\fR command is invoked without a \fIcommand\fR
argument, then the current \fBpackage unknown\fR script is returned,
or an empty string if there is none.
If \fIcommand\fR is specified as an empty string, then the current
\fBpackage unknown\fR script is removed, if there is one.
.\" METHOD: vcompare
.TP
\fBpackage vcompare \fIversion1 version2\fR
.
Compares the two version numbers given by \fIversion1\fR and \fIversion2\fR.
Returns -1 if \fIversion1\fR is an earlier version than \fIversion2\fR,
0 if they are equal, and 1 if \fIversion1\fR is later than \fIversion2\fR.
.\" METHOD: versions
.TP
\fBpackage versions \fIpackage\fR
.
Returns a list of all the version numbers of \fIpackage\fR
for which information has been provided by \fBpackage ifneeded\fR
commands.
.\" METHOD: vsatisfies
.TP
\fBpackage vsatisfies \fIversion requirement...\fR
.
Returns 1 if the \fIversion\fR satisfies at least one of the given
requirements, and 0 otherwise. Each \fIrequirement\fR is allowed to
have any of the forms:
.RS
.TP
min
.IP \fImin\fR
.
This form is called
.QW min-bounded .
.TP
min-
.IP \fImin\fB\-\fR
.
This form is called
.QW min-unbound .
.TP
min-max
.IP \fImin\fB\-\fImax\fR
.
This form is called
.QW bounded .
.RE
.RS
.PP
where
.QW min
.QW \fImin\fR
and
.QW max
.QW \fImax\fR
are valid version numbers. The legacy syntax is
a special case of the extended syntax, keeping backward
compatibility. Regarding satisfaction the rules are:
.RE
.RS
.IP [1]
The \fIversion\fR has to pass at least one of the listed
\fIrequirement\fRs to be satisfactory.
.IP [2]
A version satisfies a
.QW bounded
requirement when
256
257
258
259
260
261
262

263
264

265
266
267
268
269
270
271
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274







+


+







A \fIversion\fR satisfies a
.QW min-unbound
requirement if, and only if it is greater than or equal to the
\fImin\fR, where the \fImin\fR has been padded internally with
.QW a0 .
There is no constraint to a maximum.
.RE
.\" METHOD: prefer
.TP
\fBpackage prefer \fR?\fBlatest\fR|\fBstable\fR?
.
With no arguments, the commands returns either
.QW latest
or
.QW stable ,
whichever describes the current mode of selection logic used by
\fBpackage require\fR.
.RS

Changes to doc/packagens.n.

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

30
31

32

33
34
35
36
37
38

39
40

41
42
43
44
45
46
47
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
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

-
+











-






-


+


+

+


+

+


+
-
+






+


+







'\"
'\" Copyright (c) 1998-2000 by Scriptics Corporation.
'\" Copyright (c) 1998-2000 Scriptics Corporation.
'\" All rights reserved.
'\"
.TH pkg::create n 8.3 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
pkg::create \- Construct an appropriate 'package ifneeded' command for a given package specification
.SH SYNOPSIS
\fB::pkg::create\fR \fB\-name \fIpackageName \fB\-version \fIpackageVersion\fR ?\fB\-load \fIfilespec\fR? ... ?\fB\-source \fIfilespec\fR? ...
.BE

.SH DESCRIPTION
.PP
\fB::pkg::create\fR is a utility procedure that is part of the standard Tcl
library.  It is used to create an appropriate \fBpackage ifneeded\fR
command for a given package specification.  It can be used to construct a
\fBpkgIndex.tcl\fR file for use with the \fBpackage\fR mechanism.

.SH OPTIONS
The parameters supported are:
.\" OPTION: -name
.TP
\fB\-name \fIpackageName\fR
.
This parameter specifies the name of the package.  It is required.
.\" OPTION: -version
.TP
\fB\-version \fIpackageVersion\fR
.
This parameter specifies the version of the package.  It is required.
.\" OPTION: -load
.TP
\fB\-load \fIfilespec\fR
.
This parameter specifies a binary library that must be loaded with the
This parameter specifies a library that must be loaded with the
\fBload\fR command.  \fIfilespec\fR is a list with two elements.  The
first element is the name of the file to load.  The second, optional
element is a list of commands supplied by loading that file.  If the
list of procedures is empty or omitted, \fB::pkg::create\fR will
set up the library for direct loading (see \fBpkg_mkIndex\fR).  Any
number of \fB\-load\fR parameters may be specified.
.\" OPTION: -source
.TP
\fB\-source \fIfilespec\fR
.
This parameter is similar to the \fB\-load\fR parameter, except that it
specifies a Tcl library that must be loaded with the
\fBsource\fR command.  Any number of \fB\-source\fR parameters may be
specified.
.PP
At least one \fB\-load\fR or \fB\-source\fR parameter must be given.
.SH "SEE ALSO"

Changes to doc/pid.n.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
10
11
12
13
14
15
16

17
18
19
20
21
22
23







-







.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
pid \- Retrieve process identifiers
.SH SYNOPSIS
\fBpid \fR?\fIfileId\fR?
.BE

.SH DESCRIPTION
.PP
If the \fIfileId\fR argument is given then it should normally
refer to a process pipeline created with the \fBopen\fR command.
In this case the \fBpid\fR command will return a list whose elements
are the process identifiers of all the processes in the pipeline,
in order.
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49







-








# Print process information
exec ps -fp [\fBpid\fR $pipeline] >@stdout
# Print a separator and then the output of the pipeline
puts [string repeat - 70]
puts [read $pipeline]
close $pipeline
.CE

.SH "SEE ALSO"
exec(n), open(n)
.SH KEYWORDS
file, pipeline, process identifier
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/pkgMkIndex.n.

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
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







+


+


+


+




+


+
-
+




+


+


+


+







There may be many versions of a package in the various index files
in \fBauto_path\fR, but only one will actually be loaded in a given
interpreter, based on the first call to \fBpackage require\fR.
Different versions of a package may be loaded in different
interpreters.
.SH OPTIONS
The optional switches are:
.\" OPTION: -direct
.TP 15
\fB\-direct\fR
.
The generated index will implement direct loading of the package
upon \fBpackage require\fR.  This is the default.
.\" OPTION: -lazy
.TP 15
\fB\-lazy\fR
.
The generated index will manage to delay loading the package until the
use of one of the commands provided by the package, instead of loading
it immediately upon \fBpackage require\fR.  This is not compatible with
the use of \fIauto_reset\fR, and therefore its use is discouraged.
.\" OPTION: -load
.TP 15
\fB\-load \fIpkgPat\fR
.
The index process will pre-load any packages that exist in the
The index process will preload any packages that exist in the
current interpreter and match \fIpkgPat\fR into the child interpreter used to
generate the index.  The pattern match uses string match rules, but without
making case distinctions.
See \fBCOMPLEX CASES\fR below.
.\" OPTION: -verbose
.TP 15
\fB\-verbose\fR
.
Generate output during the indexing process.  Output is via
the \fBtclLog\fR procedure, which by default prints to stderr.
.\" OPTION: --
.TP 15
\fB\-\-\fR
.
End of the flags, in case \fIdir\fR begins with a dash.
.SH "PACKAGES AND THE AUTO-LOADER"
.PP
The package management facilities overlap somewhat with the auto-loader,
in that both arrange for files to be loaded on-demand.
However, package management is a higher-level mechanism that uses
the auto-loader for the last step in the loading process.

Changes to doc/platform.n.

9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23







-
+







.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
platform \- System identification support code and utilities
.SH SYNOPSIS
.nf
\fBpackage require platform\fR ?\fB1.0.10\fR?
.sp

\fBplatform::generic\fR
\fBplatform::identify\fR
\fBplatform::patterns \fIidentifier\fR
.fi
.BE
.SH DESCRIPTION
.PP
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
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







+









+







+







naming conventions.
.PP
The \fBplatform\fR package prevents such fragmentation - i.e., it
establishes a standard naming convention for architectures running Tcl
and makes it more convenient for developers to identify the current
architecture a Tcl program is running on.
.SH COMMANDS
.\" COMMAND: identify
.TP
\fBplatform::identify\fR
.
This command returns an identifier describing the platform the Tcl
core is running on. The returned identifier has the general format
\fIOS\fR-\fICPU\fR. The \fIOS\fR part of the identifier may contain
details like kernel version, libc version, etc., and this information
may contain dashes as well.  The \fICPU\fR part will not contain
dashes, making the preceding dash the last dash in the result.
.\" COMMAND: generic
.TP
\fBplatform::generic\fR
.
This command returns a simplified identifier describing the platform
the Tcl core is running on. In contrast to \fBplatform::identify\fR it
leaves out details like kernel version, libc version, etc. The
returned identifier has the general format \fIOS\fR-\fICPU\fR.
.\" COMMAND: patterns
.TP
\fBplatform::patterns \fIidentifier\fR
.
This command takes an identifier as returned by
\fBplatform::identify\fR and returns a list of identifiers describing
compatible architectures.
.SH EXAMPLE

Changes to doc/platform_shell.n.

9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23







-
+







.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
platform::shell \- System identification support code and utilities
.SH SYNOPSIS
.nf
\fBpackage require platform::shell\fR ?\fB1.1.4\fR?
.sp

\fBplatform::shell::generic \fIshell\fR
\fBplatform::shell::identify \fIshell\fR
\fBplatform::shell::platform \fIshell\fR
.fi
.BE
.SH DESCRIPTION
.PP
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
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







+


+


+


+


+


+








different 32/64 bit settings and thus different identifiers.
.PP
For applications like a code repository it is important to identify
the architecture of the shell which will actually run the installed
packages, versus the architecture of the shell running the repository
software.
.SH COMMANDS
.\" COMMAND: identify
.TP
\fBplatform::shell::identify \fIshell\fR
.
This command does the same identification as \fBplatform::identify\fR,
for the specified Tcl shell, in contrast to the running shell.
.\" COMMAND: generic
.TP
\fBplatform::shell::generic \fIshell\fR
.
This command does the same identification as \fBplatform::generic\fR,
for the specified Tcl shell, in contrast to the running shell.
.\" COMMAND: platform
.TP
\fBplatform::shell::platform \fIshell\fR
.
This command returns the contents of \fBtcl_platform(platform)\fR for
the specified Tcl shell.
.SH KEYWORDS
operating system, cpu architecture, platform, architecture
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/prefix.n.

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
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







-
-
+
+







+

-
+



+

-
+



+

-
+






-
+

+

-
+


+





+














-
+














-
+

-
+










-
+

-
+







.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
tcl::prefix \- facilities for prefix matching
.SH SYNOPSIS
.nf
\fB::tcl::prefix all\fR \fItable string\fR
\fB::tcl::prefix longest\fR \fItable string\fR
\fB::tcl::prefix all\fI table string\fR
\fB::tcl::prefix longest\fI table string\fR
\fB::tcl::prefix match\fR ?\fIoption ...\fR? \fItable string\fR
.fi
.BE
.SH DESCRIPTION
.PP
This document describes commands looking up a prefix in a list of strings.
The following commands are supported:
.\" METHOD: all
.TP
\fB::tcl::prefix all\fR \fItable string\fR
\fB::tcl::prefix all\fI table string\fR
.
Returns a list of all elements in \fItable\fR that begin with the prefix
\fIstring\fR.
.\" METHOD: longest
.TP
\fB::tcl::prefix longest\fR \fItable string\fR
\fB::tcl::prefix longest\fI table string\fR
.
Returns the longest common prefix of all elements in \fItable\fR that
begin with the prefix \fIstring\fR.
.\" METHOD: match
.TP
\fB::tcl::prefix match\fR ?\fIoptions\fR? \fItable string\fR
\fB::tcl::prefix match\fR ?\fIoption ...\fR? \fItable string\fR
.
If \fIstring\fR equals one element in \fItable\fR or is a prefix to exactly
one element, the matched element is returned. If not, the result depends
on the \fB\-error\fR option. (It is recommended that the \fItable\fR be sorted
before use with this subcommand, so that the list of matches presented in the
error message also becomes sorted, though this is not strictly necessary for
the operation of this subcommand itself.)
the operation of this subcommand itself.) The following options are supported:
.RS
.\" OPTION: -exact
.TP
\fB\-exact\fR\0
\fB\-exact\fR
.
Accept only exact matches.
.\" OPTION: -message
.TP
\fB\-message\0\fIstring\fR
.
Use \fIstring\fR in the error message at a mismatch. Default is
.QW option .
.\" OPTION: -error
.TP
\fB\-error\0\fIoptions\fR
.
The \fIoptions\fR are used when no match is found. If \fIoptions\fR is empty,
no error is generated and an empty string is returned. Otherwise the
\fIoptions\fR are used as \fBreturn\fR options when generating the error
message. The default corresponds to setting
.QW "\-level 0" .
Example: If
.QW "\fB\-error\fR {\-errorcode MyError \-level 1}"
is used, an error would be generated as:
.RS
.PP
.CS
return \-errorcode MyError \-level 1 \-code error \e
return -errorcode MyError -level 1 -code error \e
       "ambiguous option ..."
.CE
.RE
.RE
.SH "EXAMPLES"
.PP
Basic use:
.PP
.CS
namespace import ::tcl::prefix
\fBprefix match\fR {apa bepa cepa} apa
     \fI\(-> apa\fR
\fBprefix match\fR {apa bepa cepa} a
     \fI\(-> apa\fR
\fBprefix match\fR \-exact {apa bepa cepa} a
\fBprefix match\fR -exact {apa bepa cepa} a
     \fI\(-> bad option "a": must be apa, bepa, or cepa\fR
\fBprefix match\fR \-message "switch" {apa ada bepa cepa} a
\fBprefix match\fR -message "switch" {apa ada bepa cepa} a
     \fI\(-> ambiguous switch "a": must be apa, ada, bepa, or cepa\fR
\fBprefix longest\fR {fblocked fconfigure fcopy file fileevent flush} fc
     \fI\(-> fco\fR
\fBprefix all\fR {fblocked fconfigure fcopy file fileevent flush} fc
     \fI\(-> fconfigure fcopy\fR
.CE
.PP
Simplifying option matching:
.PP
.CS
array set opts {\-apa 1 \-bepa "" \-cepa 0}
array set opts {-apa 1 -bepa "" -cepa 0}
foreach {arg val} $args {
    set opts([\fBprefix match\fR {\-apa \-bepa \-cepa} $arg]) $val
    set opts([\fBprefix match\fR {-apa -bepa -cepa} $arg]) $val
}
.CE
.PP
Creating a \fBswitch\fR that supports prefixes:
.PP
.CS
switch [\fBprefix match\fR {apa bepa cepa} $arg] {

Changes to doc/proc.n.

53
54
55
56
57
58
59
60
61
62
63




64
65
66
67
68
69
70
53
54
55
56
57
58
59




60
61
62
63
64
65
66
67
68
69
70







-
-
-
-
+
+
+
+







in a future version of Tcl; portable code should ensure that all
optional arguments come after all required arguments.
.PP
There is one special case to permit procedures with
variable numbers of arguments.  If the last formal argument has the name
.QW \fBargs\fR ,
then a call to the procedure may contain more actual arguments
than the procedure has formal arguments.  In this case, all of the actual arguments
starting at the one that would be assigned to \fBargs\fR are combined into
a list (as if the \fBlist\fR command had been used); this combined value
is assigned to the local variable \fBargs\fR.
than the procedure has formal arguments.  In this case, all of the actual
arguments starting at the one that would be assigned to \fBargs\fR are
combined into a list (as if the \fBlist\fR command had been used); this
combined value is assigned to the local variable \fBargs\fR.
.PP
When \fIbody\fR is being executed, variable names normally refer to
local variables, which are created automatically when referenced and
deleted when the procedure returns.  One local variable is automatically
created for each of the procedure's arguments.
Other variables can only be accessed by invoking one of the \fBglobal\fR,
\fBvariable\fR, \fBupvar\fR or \fBnamespace upvar\fR commands.

Changes to doc/process.n.

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
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
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
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






-
+













+










+






+







+












-
+




-
+



-
+









+

-
+






+







'\"
'\" Copyright (c) 2017 Frederic Bonnet.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH process n 8.7 Tcl "Tcl Built-In Commands"
.TH process n 9.0 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
tcl::process \- Subprocess management
.SH SYNOPSIS
\fB::tcl::process \fIoption \fR?\fIarg arg ...\fR?
.BE
.SH DESCRIPTION
.PP
This command provides a way to manage subprocesses created by the \fBopen\fR
and \fBexec\fR commands, as identified by the process identifiers (PIDs) of
those subprocesses. The legal \fIoptions\fR (which may be abbreviated) are:
.\" METHOD: autopurge
.TP
\fB::tcl::process autopurge\fR ?\fIflag\fR?
.
Automatic purge facility. If \fIflag\fR is specified as a boolean value then
it activates or deactivate autopurge. In all cases it returns the current
status as a boolean value. When autopurge is active,
\fBTcl_ReapDetachedProcs\fR is called each time the \fBexec\fR command is
executed or a pipe channel created by \fBopen\fR is closed. When autopurge is
inactive, \fB::tcl::process\fR purge must be called explicitly. By default
autopurge is active.
.\" METHOD: list
.TP
\fB::tcl::process list\fR
.
Returns the list of subprocess PIDs. This includes all currently executing
subprocesses and all terminated subprocesses that have not yet had their
corresponding process table entries purged.
.\" METHOD: purge
.TP
\fB::tcl::process purge\fR ?\fIpids\fR?
.
Cleans up all data associated with terminated subprocesses. If \fIpids\fR is
specified as a list of PIDs then the command only cleanup data for the matching
subprocesses if they exist, and raises an error otherwise. If a process listed is
still active, this command does nothing to that process.
.\" METHOD: status
.TP
\fB::tcl::process status\fR ?\fIswitches\fR? ?\fIpids\fR?
.
Returns a dictionary mapping subprocess PIDs to their respective status. If
\fIpids\fR is specified as a list of PIDs then the command only returns the
status of the matching subprocesses if they exist, and raises an error
otherwise. For active processes, the status is an empty value. For terminated
processes, the status is a list with the following format:
.QW "\fB{\fIcode\fR ?\fImsg errorCode\fR?\fB}\fR" ,
where:
.RS
.TP
\fIcode\fR\0
\fIcode\fR
.
is a standard Tcl return code, i.e., \fB0\fR for TCL_OK and \fB1\fR
for TCL_ERROR,
.TP
\fImsg\fR\0
\fImsg\fR
.
is the human-readable error message,
.TP
\fIerrorCode\fR\0
\fIerrorCode\fR
.
uses the same format as the \fBerrorCode\fR global variable
.PP
Note that \fBmsg\fR and \fBerrorCode\fR are only present for abnormally
terminated processes (i.e. those where the \fIcode\fR is nonzero). Under the
hood this command calls \fBTcl_WaitPid\fR with the \fBWNOHANG\fR flag set for
non-blocking behavior, unless the \fB\-wait\fR switch is set (see below).
.PP
Additionally, \fB::tcl::process status\fR accepts the following switches:
.\" OPTION: -wait
.TP
\fB\-wait\fR\0
\fB\-wait\fR
.
By default the command returns immediately (the underlying \fBTcl_WaitPid\fR is
called with the \fBWNOHANG\fR flag set) unless this switch is set. If \fIpids\fR
is specified as a list of PIDs then the command waits until the status of the
matching subprocesses are available. If \fIpids\fR was not specified, this
command will wait for all known subprocesses.
.\" OPTION: --
.TP
\fB\-\|\-\fR
.
Marks the end of switches.  The argument following this one will
be treated as the first \fIarg\fR even if it starts with a \fB\-\fR.
.RE
.SH "EXAMPLES"

Changes to doc/puts.n.

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
8
9
10
11
12
13
14

15
16
17
18















19













20
















































21



22
23
24
25
26







-
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
+




.TH puts n 7.5 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
puts \- Write to a channel
.SH SYNOPSIS
\fBputs \fR?\fB\-nonewline\fR? ?\fIchannelId\fR? \fIstring\fR
\fBputs \fR?\fB\-nonewline\fR? ?\fIchannel\fR? \fIstring\fR
.BE
.SH DESCRIPTION
.PP
Writes the characters given by \fIstring\fR to the channel given
by \fIchannelId\fR.
.PP
\fIChannelId\fR must be an identifier for an open channel such as a
Tcl standard channel (\fBstdout\fR or \fBstderr\fR), the return
value from an invocation of \fBopen\fR or \fBsocket\fR, or the result
of a channel creation command provided by a Tcl extension. The channel
must have been opened for output.
.PP
If no \fIchannelId\fR is specified then it defaults to
\fBstdout\fR. \fBPuts\fR normally outputs a newline character after
\fIstring\fR, but this feature may be suppressed by specifying the
\fB\-nonewline\fR switch.
.PP
Newline characters in the output are translated by \fBputs\fR to
The \fBputs\fR command has been superceded by the \fBchan puts\fR
platform-specific end-of-line sequences according to the current
value of the \fB\-translation\fR option for the channel (for example,
on PCs newlines are normally replaced with carriage-return-linefeed
sequences.
See the \fBfconfigure\fR manual entry for a discussion on ways in
which \fBfconfigure\fR will alter output.
.PP
Tcl buffers output internally, so characters written with \fBputs\fR
may not appear immediately on the output file or device;  Tcl will
normally delay output until the buffer is full or the channel is
closed.
You can force output to appear immediately with the \fBflush\fR
command.
command which supports the same syntax and options.
.PP
When the output buffer fills up, the \fBputs\fR command will normally
block until all the buffered data has been accepted for output by the
operating system.
If \fIchannelId\fR is in nonblocking mode then the \fBputs\fR command
will not block even if the operating system cannot accept the data.
Instead, Tcl continues to buffer the data and writes it in the
background as fast as the underlying file or device can accept it.
The application must use the Tcl event loop for nonblocking output
to work;  otherwise Tcl never finds out that the file or device is
ready for more output data.
It is possible for an arbitrarily large amount of data to be
buffered for a channel in nonblocking mode, which could consume a
large amount of memory.
To avoid wasting memory, nonblocking I/O should normally
be used in an event-driven fashion with the \fBfileevent\fR command
(do not invoke \fBputs\fR unless you have recently been notified
via a file event that the channel is ready for more output data).
.SH EXAMPLES
.PP
Write a short message to the console (or wherever \fBstdout\fR is
directed):
.PP
.CS
\fBputs\fR "Hello, World!"
.CE
.PP
Print a message in several parts:
.PP
.CS
\fBputs\fR -nonewline "Hello, "
\fBputs\fR "World!"
.CE
.PP
Print a message to the standard error channel:
.PP
.CS
\fBputs\fR stderr "Hello, World!"
.CE
.PP
Append a log message to a file:
.PP
.CS
set chan [open my.log a]
set timestamp [clock format [clock seconds]]
\fBputs\fR $chan "$timestamp - Hello, World!"
close $chan
.CE
.SH "SEE ALSO"
file(n), fileevent(n), Tcl_StandardChannels(3)
.SH KEYWORDS
channel, newline, output, write
chan(n)
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/re_syntax.n.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15








-
-







'\"
'\" Copyright (c) 1998 Sun Microsystems, Inc.
'\" Copyright (c) 1999 Scriptics Corporation
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
.ie '\w'o''\w'\C'^o''' .ds qo \C'^o'
.el .ds qo u
.TH re_syntax n "8.1" Tcl "Tcl Built-In Commands"
.BS
.SH NAME
re_syntax \- Syntax of Tcl regular expressions
.BE
.SH DESCRIPTION
.PP
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
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







-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-



















-
+



-
+

-
+

-
+


-
+

-
+



-
+


-
+




-
+












-
+
+
+



-
+
+
+
+
+
+
+
+
+
+
+
+
+
+







.SS QUANTIFIERS
A quantified atom is an \fIatom\fR possibly followed
by a single \fIquantifier\fR.
Without a quantifier, it matches a single match for the atom.
The quantifiers,
and what a so-quantified atom matches, are:
.RS 2
.TP 6
\fB*\fR
.IP \fB*\fR 6
.
a sequence of 0 or more matches of the atom
.TP
\fB+\fR
.IP \fB+\fR 6
.
a sequence of 1 or more matches of the atom
.TP
\fB?\fR
.IP \fB?\fR 6
.
a sequence of 0 or 1 matches of the atom
.TP
\fB{\fIm\fB}\fR
.IP \fB{\fIm\fB}\fR 6
.
a sequence of exactly \fIm\fR matches of the atom
.TP
\fB{\fIm\fB,}\fR
.IP \fB{\fIm\fB,}\fR 6
.
a sequence of \fIm\fR or more matches of the atom
.TP
\fB{\fIm\fB,\fIn\fB}\fR
.IP \fB{\fIm\fB,\fIn\fB}\fR 6
.
a sequence of \fIm\fR through \fIn\fR (inclusive) matches of the atom;
\fIm\fR may not exceed \fIn\fR
.TP
\fB*?  +?  ??  {\fIm\fB}?  {\fIm\fB,}?  {\fIm\fB,\fIn\fB}?\fR
.
\fInon-greedy\fR quantifiers, which match the same possibilities,
but prefer the smallest number rather than the largest number
of matches (see \fBMATCHING\fR)
.RE
.PP
The forms using \fB{\fR and \fB}\fR are known as \fIbound\fRs. The
numbers \fIm\fR and \fIn\fR are unsigned decimal integers with
permissible values from 0 to 255 inclusive.
.SS ATOMS
An atom is one of:
.RS 2
.IP \fB(\fIre\fB)\fR 6
matches a match for \fIre\fR (\fIre\fR is any regular expression) with
the match noted for possible reporting
.IP \fB(?:\fIre\fB)\fR
.IP \fB(?:\fIre\fB)\fR 6
as previous, but does no reporting (a
.QW non-capturing
set of parentheses)
.IP \fB()\fR
.IP \fB()\fR 6
matches an empty string, noted for possible reporting
.IP \fB(?:)\fR
.IP \fB(?:)\fR 6
matches an empty string, without reporting
.IP \fB[\fIchars\fB]\fR
.IP \fB[\fIchars\fB]\fR 6
a \fIbracket expression\fR, matching any one of the \fIchars\fR (see
\fBBRACKET EXPRESSIONS\fR for more detail)
.IP \fB.\fR
.IP \fB.\fR 6
matches any single character
.IP \fB\e\fIk\fR
.IP \fB\e\fIk\fR 6
matches the non-alphanumeric character \fIk\fR
taken as an ordinary character, e.g. \fB\e\e\fR matches a backslash
character
.IP \fB\e\fIc\fR
.IP \fB\e\fIc\fR 6
where \fIc\fR is alphanumeric (possibly followed by other characters),
an \fIescape\fR (AREs only), see \fBESCAPES\fR below
.IP \fB{\fR
.IP \fB{\fR 6
when followed by a character other than a digit, matches the
left-brace character
.QW \fB{\fR ;
when followed by a digit, it is the beginning of a \fIbound\fR (see above)
.IP \fIx\fR
.IP \fIx\fR 6
where \fIx\fR is a single character with no other significance,
matches that character.
.RE
.SS CONSTRAINTS
A \fIconstraint\fR matches an empty string when specific conditions
are met. A constraint may not be followed by a quantifier. The
simple constraints are as follows; some more constraints are described
later, under \fBESCAPES\fR.
.RS 2
.TP 8
\fB^\fR
.
matches at the beginning of a line
matches at the beginning of the string or a line (according to whether
matching is newline-sensitive or not, as described in \fBMATCHING\fR,
below).
.TP
\fB$\fR
.
matches at the end of a line
matches at the end of the string or a line (according to whether
matching is newline-sensitive or not, as described in \fBMATCHING\fR,
below).
.RS
.PP
The difference between string and line matching modes is immaterial
when the string does not contain a newline character.  The \fB\eA\fR
and \fB\eZ\fR constraint escapes have a similar purpose but are
always constraints for the overall string.
.PP
The default newline-sensitivity depends on the command that uses the
regular expression, and can be overridden as described in
\fBMETASYNTAX\fR, below.
.RE
.TP
\fB(?=\fIre\fB)\fR
.
\fIpositive lookahead\fR (AREs only), matches at any point where a
substring matching \fIre\fR begins
.TP
\fB(?!\fIre\fB)\fR
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
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
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


366

367
368
369
370
371
372
373







-
+


-
+

-
+




















-
-
+
-

-
-
+
-

-
-
+
-


-
-
+
-


-
-
+
-



-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-


-
-
+
-


-
+


-
-
+
-

-
-
+
-


-
-
+
-

-
-
+
-




-
-
+
-







and \fB=]\fR is an equivalence class, standing for the sequences of
characters of all collating elements equivalent to that one, including
itself. (If there are no other equivalent collating elements, the
treatment is as if the enclosing delimiters were
.QW \fB[.\fR \&
and
.QW \fB.]\fR .)
For example, if \fBo\fR and \fB\[^o]\fR are the members of an
For example, if \fBo\fR and \fB\(^o\fR are the members of an
equivalence class, then
.QW \fB[[=o=]]\fR ,
.QW \fB[[=\[^o]=]]\fR ,
.QW \fB[[=\(^o=]]\fR ,
and
.QW \fB[o\[^o]]\fR \&
.QW \fB[o\(^o]\fR \&
are all synonymous. An equivalence class may not be an endpoint of a range.
.RS
.PP
(\fINote:\fR Tcl implements only the Unicode locale. It does not define any
equivalence classes. The examples above are just illustrations.)
.RE
.SH ESCAPES
Escapes (AREs only), which begin with a \fB\e\fR followed by an
alphanumeric character, come in several varieties: character entry,
class shorthands, constraint escapes, and back references. A \fB\e\fR
followed by an alphanumeric character but not constituting a valid
escape is illegal in AREs. In EREs, there are no escapes: outside a
bracket expression, a \fB\e\fR followed by an alphanumeric character
merely stands for that character as an ordinary character, and inside
a bracket expression, \fB\e\fR is an ordinary character. (The latter
is the one actual incompatibility between EREs and AREs.)
.SS "CHARACTER-ENTRY ESCAPES"
Character-entry escapes (AREs only) exist to make it easier to specify
non-printing and otherwise inconvenient characters in REs:
.RS 2
.TP 5
\fB\ea\fR
.IP \fB\ea\fR 5
.
alert (bell) character, as in C
.TP
\fB\eb\fR
.IP \fB\eb\fR 5
.
backspace, as in C
.TP
\fB\eB\fR
.IP \fB\eB\fR 5
.
synonym for \fB\e\fR to help reduce backslash doubling in some
applications where there are multiple levels of backslash processing
.TP
\fB\ec\fIX\fR
.IP \fB\ec\fIX\fR 5
.
(where \fIX\fR is any character) the character whose low-order 5 bits
are the same as those of \fIX\fR, and whose other bits are all zero
.TP
\fB\ee\fR
.IP \fB\ee\fR 5
.
the character whose collating-sequence name is
.QW \fBESC\fR ,
or failing that, the character with octal value 033
.TP
\fB\ef\fR
.IP \fB\ef\fR 5
.
formfeed, as in C
.TP
\fB\en\fR
.IP \fB\en\fR 5
.
newline, as in C
.TP
\fB\er\fR
.IP \fB\er\fR 5
.
carriage return, as in C
.TP
\fB\et\fR
.IP \fB\et\fR 5
.
horizontal tab, as in C
.TP
\fB\eu\fIwxyz\fR
.IP \fB\eu\fIwxyz\fR 5
.
(where \fIwxyz\fR is one up to four hexadecimal digits) the Unicode
character \fBU+\fIwxyz\fR in the local byte ordering
.TP
\fB\eU\fIstuvwxyz\fR
.IP \fB\eU\fIstuvwxyz\fR 5
.
(where \fIstuvwxyz\fR is one up to eight hexadecimal digits) reserved
for a Unicode extension up to 21 bits. The digits are parsed until the
first non-hexadecimal character is encountered, the maximun of eight
first non-hexadecimal character is encountered, the maximum of eight
hexadecimal digits are reached, or an overflow would occur in the maximum
value of \fBU+\fI10ffff\fR.
.TP
\fB\ev\fR
.IP \fB\ev\fR 5
.
vertical tab, as in C
.TP
\fB\ex\fIhh\fR
.IP \fB\ex\fIhh\fR 5
.
(where \fIhh\fR is one or two hexadecimal digits) the character
whose hexadecimal value is \fB0x\fIhh\fR.
.TP
\fB\e0\fR
.IP \fB\e0\fR 5
.
the character whose value is \fB0\fR
.TP
\fB\e\fIxyz\fR
.IP \fB\e\fIxyz\fR 5
.
(where \fIxyz\fR is exactly three octal digits, and is not a \fIback
reference\fR (see below)) the character whose octal value is
\fB0\fIxyz\fR. The first digit must be in the range 0-3, otherwise
the two-digit form is assumed.
.TP
\fB\e\fIxy\fR
.IP \fB\e\fIxy\fR 5
.
(where \fIxy\fR is exactly two octal digits, and is not a \fIback
reference\fR (see below)) the character whose octal value is
\fB0\fIxy\fR
.RE
.PP
Hexadecimal digits are
.QR \fB0\fR \fB9\fR ,
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
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







-
+
+











-
+
+







.TP
\fB\es\fR
.
\fB[[:space:]]\fR
.TP
\fB\ew\fR
.
\fB[[:alnum:]_]\fR (note underscore)
\fB[[:alnum:]_\eu203F\eu2040\eu2054\euFE33\euFE34\euFE4D\euFE4E\euFE4F\euFF3F]\fR
(including punctuation connector characters)
.TP
\fB\eD\fR
.
\fB[^[:digit:]]\fR
.TP
\fB\eS\fR
.
\fB[^[:space:]]\fR
.TP
\fB\eW\fR
.
\fB[^[:alnum:]_]\fR (note underscore)
\fB[^[:alnum:]_\eu203F\eu2040\eu2054\euFE33\euFE34\euFE4D\euFE4E\euFE4F\euFF3F]\fR
(including punctuation connector characters)
.RE
.PP
Within bracket expressions,
.QW \fB\ed\fR ,
.QW \fB\es\fR ,
and
.QW \fB\ew\fR \&
465
466
467
468
469
470
471
472
473

474
475
476
477
478
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
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
467
468







-
-
+
-



-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-



-
-
+
-

-
-
+
-







which is equivalent to
.QW \fB[a-c^[:digit:]]\fR ,
is illegal.)
.SS "CONSTRAINT ESCAPES"
A constraint escape (AREs only) is a constraint, matching the empty
string if specific conditions are met, written as an escape:
.RS 2
.TP 6
\fB\eA\fR
.IP \fB\eA\fR 6
.
matches only at the beginning of the string (see \fBMATCHING\fR,
below, for how this differs from
.QW \fB^\fR )
.TP
\fB\em\fR
.IP \fB\em\fR 6
.
matches only at the beginning of a word
.TP
\fB\eM\fR
.IP \fB\eM\fR 6
.
matches only at the end of a word
.TP
\fB\ey\fR
.IP \fB\ey\fR 6
.
matches only at the beginning or end of a word
.TP
\fB\eY\fR
.IP \fB\eY\fR 6
.
matches only at a point that is not the beginning or end of a word
.TP
\fB\eZ\fR
.IP \fB\eZ\fR 6
.
matches only at the end of the string (see \fBMATCHING\fR, below, for
how this differs from
.QW \fB$\fR )
.TP
\fB\e\fIm\fR
.IP \fB\e\fIm\fR 6
.
(where \fIm\fR is a nonzero digit) a \fIback reference\fR, see below
.TP
\fB\e\fImnn\fR
.IP \fB\e\fImnn\fR 6
.
(where \fIm\fR is a nonzero digit, and \fInn\fR is some more digits,
and the decimal value \fImnn\fR is not greater than the number of
closing capturing parentheses seen so far) a \fIback reference\fR, see
below
.RE
.PP
A word is defined as in the specification of

Changes to doc/read.n.

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
8
9
10
11
12
13
14

15
16

17
18
19
20

21



















22










































23



24
25
26
27







-
+

-
+



-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
+



.TH read n 8.1 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
read \- Read from a channel
.SH SYNOPSIS
\fBread \fR?\fB\-nonewline\fR? \fIchannelId\fR
\fBread \fR?\fB\-nonewline\fR? \fIchannel\fR
.sp
\fBread \fIchannelId numChars\fR
\fBread \fIchannel numChars\fR
.BE
.SH DESCRIPTION
.PP
In the first form, the \fBread\fR command reads all of the data from
The \fBread\fR command has been superceded by the \fBchan read\fR
\fIchannelId\fR up to the end of the file.  If the \fB\-nonewline\fR
switch is specified then the last character of the file is discarded
if it is a newline.  In the second form, the extra argument specifies
how many characters to read.  Exactly that many characters will be
read and returned, unless there are fewer than \fInumChars\fR left in
the file; in this case all the remaining characters are returned.  If
the channel is configured to use a multi-byte encoding, then the
number of characters read may not be the same as the number of bytes
read.
.PP
\fIChannelId\fR must be an identifier for an open channel such as the
Tcl standard input channel (\fBstdin\fR), the return value from an
invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel
creation command provided by a Tcl extension. The channel must have
been opened for input.
.PP
If \fIchannelId\fR is in nonblocking mode, the command may not read as
many characters as requested: once all available input has been read,
the command will return the data that is available rather than
command which supports the same syntax and options.
blocking for more input.  If the channel is configured to use a
multi-byte encoding, then there may actually be some bytes remaining
in the internal buffers that do not form a complete character.  These
bytes will not be returned until a complete character is available or
end-of-file is reached.  The \fB\-nonewline\fR switch is ignored if
the command returns before reaching the end of the file.
.PP
\fBRead\fR translates end-of-line sequences in the input into
newline characters according to the \fB\-translation\fR option
for the channel.
See the \fBfconfigure\fR manual entry for a discussion on ways in
which \fBfconfigure\fR will alter input.
.SH "USE WITH SERIAL PORTS"
'\" Note:  this advice actually applies to many versions of Tcl
.PP
For most applications a channel connected to a serial port should be
configured to be nonblocking: \fBfconfigure\fI channelId \fB\-blocking
\fI0\fR.  Then \fBread\fR behaves much like described above.  Care
must be taken when using \fBread\fR on blocking serial ports:
.TP
\fBread \fIchannelId numChars\fR
.
In this form \fBread\fR blocks until \fInumChars\fR have been received
from the serial port.
.TP
\fBread \fIchannelId\fR
.
In this form \fBread\fR blocks until the reception of the end-of-file
character, see \fBfconfigure\fR \fB\-eofchar\fR. If there no end-of-file
character has been configured for the channel, then \fBread\fR will
block forever.
.SH "EXAMPLE"
.PP
This example code reads a file all at once, and splits it into a list,
with each line in the file corresponding to an element in the list:
.PP
.CS
set fl [open /proc/meminfo]
set data [\fBread\fR $fl]
close $fl
set lines [split $data \en]
.CE
.SH "SEE ALSO"
file(n), eof(n), fblocked(n), fconfigure(n), Tcl_StandardChannels(3)
.SH KEYWORDS
blocking, channel, end of line, end of file, nonblocking, read, translation, encoding
chan(n)
'\"Local Variables:
'\"mode: nroff
'\"End:

Changes to doc/refchan.n.

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
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
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
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













+
+
-
+
+
+
+
+
+
+
+
+
+
+
+

















+

-
+


-
+



















-
-
+
+




+

-
+


-
+


-
+














+

-
+


-
+















+

-
+


-
+







'\"
'\" Copyright (c) 2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH refchan n 8.5 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
.\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
refchan \- command handler API of reflected channels
.SH SYNOPSIS
.nf
\fBchan create \fImode cmdPrefix\fR
\fBcmdPrefix \fIoption\fR ?\fIarg arg ...\fR?

\fIcmdPrefix \fBblocking\fI channel mode\fR
\fIcmdPrefix \fBcget\fI channel option\fR
\fIcmdPrefix \fBcgetall\fI channel\fR
\fIcmdPrefix \fBconfigure\fI channel option value\fR
\fIcmdPrefix \fBfinalize\fI channel\fR
\fIcmdPrefix \fBinitialize\fI channel mode\fR
\fIcmdPrefix \fBread\fI channel count\fR
\fIcmdPrefix \fBseek\fI channel offset base\fR
\fIcmdPrefix \fBwatch\fI channel eventspec\fR
\fIcmdPrefix \fBwrite\fI channel data\fR
.fi
.BE
.SH DESCRIPTION
.PP
The Tcl-level handler for a reflected channel has to be a command with
subcommands (termed an \fIensemble\fR, as it is a command such as that
created by \fBnamespace ensemble\fR \fBcreate\fR, though the implementation
of handlers for reflected channel \fIis not\fR tied to \fBnamespace
ensemble\fRs in any way; see \fBEXAMPLE\fR below for how to build an
\fBoo::class\fR that supports the API). Note that \fIcmdPrefix\fR is whatever was
specified in the call to \fBchan create\fR, and may consist of
multiple arguments; this will be expanded to multiple words in place
of the prefix.
.PP
Of all the possible subcommands, the handler \fImust\fR support
\fBinitialize\fR, \fBfinalize\fR, and \fBwatch\fR. Support for the
other subcommands is optional.
.SS "MANDATORY SUBCOMMANDS"
.\" METHOD: initialize
.TP
\fIcmdPrefix \fBinitialize \fIchannelId mode\fR
\fIcmdPrefix \fBinitialize \fIchannel mode\fR
.
An invocation of this subcommand will be the first call the
\fIcmdPrefix\fR will receive for the specified new \fIchannelId\fR. It
\fIcmdPrefix\fR will receive for the specified new \fIchannel\fR. It
is the responsibility of this subcommand to set up any internal data
structures required to keep track of the channel and its state.
.RS
.PP
The return value of the method has to be a list containing the names
of all subcommands supported by the \fIcmdPrefix\fR. This also tells
the Tcl core which version of the API for reflected channels is used by
this command handler.
.PP
Any error thrown by the method will abort the creation of the channel
and no channel will be created. The thrown error will appear as error
thrown by \fBchan create\fR. Any exception other than an \fBerror\fR
(e.g.,\ \fBbreak\fR, etc.) is treated as (and converted to) an error.
.PP
\fBNote:\fR If the creation of the channel was aborted due to failures
here, then the \fBfinalize\fR subcommand will not be called.
.PP
The \fImode\fR argument tells the handler whether the channel was
opened for reading, writing, or both. It is a list containing any of
the strings \fBread\fR or \fBwrite\fR. The list will always
contain at least one element.
the strings \fBread\fR or \fBwrite\fR. The list may be empty, but
will usually contain at least one element.
.PP
The subcommand must throw an error if the chosen mode is not
supported by the \fIcmdPrefix\fR.
.RE
.\" METHOD: finalize
.TP
\fIcmdPrefix \fBfinalize \fIchannelId\fR
\fIcmdPrefix \fBfinalize \fIchannel\fR
.
An invocation of this subcommand will be the last call the
\fIcmdPrefix\fR will receive for the specified \fIchannelId\fR. It will
\fIcmdPrefix\fR will receive for the specified \fIchannel\fR. It will
be generated just before the destruction of the data structures of the
channel held by the Tcl core. The command handler \fImust not\fR
access the \fIchannelId\fR anymore in no way. Upon this subcommand being
access the \fIchannel\fR anymore in no way. Upon this subcommand being
called, any internal resources allocated to this channel must be
cleaned up.
.RS
.PP
The return value of this subcommand is ignored.
.PP
If the subcommand throws an error the command which caused its
invocation (usually \fBchan close\fR) will appear to have thrown this
error. Any exception beyond \fBerror\fR (e.g.,\ \fBbreak\fR, etc.) is
treated as (and converted to) an error.
.PP
This subcommand is not invoked if the creation of the channel was
aborted during \fBinitialize\fR (See above).
.RE
.\" METHOD: watch
.TP
\fIcmdPrefix \fBwatch \fIchannelId eventspec\fR
\fIcmdPrefix \fBwatch \fIchannel eventspec\fR
.
This subcommand notifies the \fIcmdPrefix\fR that the specified
\fIchannelId\fR is interested in the events listed in the
\fIchannel\fR is interested in the events listed in the
\fIeventspec\fR. This argument is a list containing any of \fBread\fR
and \fBwrite\fR. The list may be empty, which signals that the
channel does not wish to be notified of any events. In that situation,
the handler should disable event generation completely.
.RS
.PP
\fBWarning:\fR Any return value of the subcommand is ignored. This
includes all errors thrown by the subcommand, \fBbreak\fR, \fBcontinue\fR, and
custom return codes.
.PP
This subcommand interacts with \fBchan postevent\fR. Trying to post an
event which was not listed in the last call to \fBwatch\fR will cause
\fBchan postevent\fR to throw an error.
.RE
.SS "OPTIONAL SUBCOMMANDS"
.\" METHOD: read
.TP
\fIcmdPrefix \fBread \fIchannelId count\fR
\fIcmdPrefix \fBread \fIchannel count\fR
.
This \fIoptional\fR subcommand is called when the user requests data from the
channel \fIchannelId\fR. \fIcount\fR specifies how many \fIbytes\fR have been
channel \fIchannel\fR. \fIcount\fR specifies how many \fIbytes\fR have been
requested. If the subcommand is not supported then it is not possible to read
from the channel handled by the command.
.RS
.PP
The return value of this subcommand is taken as the requested data
\fIbytes\fR. If the returned data contains more bytes than requested,
an error will be signaled and later thrown by the command which
153
154
155
156
157
158
159

160
161

162
163
164

165
166
167
168
169
170
171
170
171
172
173
174
175
176
177
178

179
180
181

182
183
184
185
186
187
188
189







+

-
+


-
+







to a symbolic string.
.PP
If the subcommand throws any other error, the command which caused its
invocation (usually \fBgets\fR, or \fBread\fR) will appear to have
thrown this error. Any exception beyond \fBerror\fR, (e.g.,\ \fBbreak\fR,
etc.) is treated as and converted to an error.
.RE
.\" METHOD: write
.TP
\fIcmdPrefix \fBwrite \fIchannelId data\fR
\fIcmdPrefix \fBwrite \fIchannel data\fR
.
This \fIoptional\fR subcommand is called when the user writes data to
the channel \fIchannelId\fR. The \fIdata\fR argument contains \fIbytes\fR, not
the channel \fIchannel\fR. The \fIdata\fR argument contains \fIbytes\fR, not
characters. Any type of transformation (EOL, encoding) configured for
the channel has already been applied at this point. If this subcommand
is not supported then it is not possible to write to the channel
handled by the command.
.RS
.PP
The return value of the subcommand is taken as the number of bytes
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
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







+

-
+



-
+





-
-
+
-

-
-
+
-

-
-
+
-




















+

-
+


-
+














+

-
+


-
+










+

-
+


-
+











+

-
+


-
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+







to a symbolic string.
.PP
If the subcommand throws any other error the command which caused its
invocation (usually \fBputs\fR) will appear to have thrown this error.
Any exception beyond \fBerror\fR (e.g.,\ \fBbreak\fR, etc.) is treated
as and converted to an error.
.RE
.\" METHOD: seek
.TP
\fIcmdPrefix \fBseek \fIchannelId offset base\fR
\fIcmdPrefix \fBseek \fIchannel offset base\fR
.
This \fIoptional\fR subcommand is responsible for the handling of
\fBchan seek\fR and \fBchan tell\fR requests on the channel
\fIchannelId\fR. If it is not supported then seeking will not be possible for
\fIchannel\fR. If it is not supported then seeking will not be possible for
the channel.
.RS
.PP
The \fIbase\fR argument is the same as the equivalent argument of the
builtin \fBchan seek\fR, namely:
.TP 10
\fBstart\fR
.IP \fBstart\fR 10
.
Seeking is relative to the beginning of the channel.
.TP 10
\fBcurrent\fR
.IP \fBcurrent\fR 10
.
Seeking is relative to the current seek position.
.TP 10
\fBend\fR
.IP \fBend\fR 10
.
Seeking is relative to the end of the channel.
.PP
The \fIoffset\fR is an integer number specifying the amount of
\fBbytes\fR to seek forward or backward. A positive number should seek
forward, and a negative number should seek backward.
A channel may provide only limited seeking. For example sockets can
seek forward, but not backward.
.PP
The return value of the subcommand is taken as the (new) location of
the channel, counted from the start. This has to be an integer number
greater than or equal to zero.
If the subcommand throws an error the command which caused its
invocation (usually \fBchan seek\fR, or \fBchan tell\fR) will appear to have
thrown this error. Any exception beyond \fBerror\fR (e.g.,\ \fBbreak\fR,
etc.) is treated as and converted to an error.
.PP
The offset/base combination of 0/\fBcurrent\fR signals a \fBchan tell\fR
request, i.e.,\ seek nothing relative to the current location, making
the new location identical to the current one, which is then returned.
.RE
.\" METHOD: configure
.TP
\fIcmdPrefix \fBconfigure \fIchannelId option value\fR
\fIcmdPrefix \fBconfigure \fIchannel option value\fR
.
This \fIoptional\fR subcommand is for setting the type-specific options of
channel \fIchannelId\fR. The \fIoption\fR argument indicates the option to be
channel \fIchannel\fR. The \fIoption\fR argument indicates the option to be
written, and the \fIvalue\fR argument indicates the value to set the option to.
.RS
.PP
This subcommand will never try to update more than one option at a
time; that is behavior implemented in the Tcl channel core.
.PP
The return value of the subcommand is ignored.
.PP
If the subcommand throws an error the command which performed the
(re)configuration or query (usually \fBfconfigure\fR or
\fBchan configure\fR) will appear to have thrown this error. Any exception
beyond \fBerror\fR (e.g.,\ \fBbreak\fR, etc.) is treated as and
converted to an error.
.RE
.\" METHOD: cget
.TP
\fIcmdPrefix \fBcget \fIchannelId option\fR
\fIcmdPrefix \fBcget \fIchannel option\fR
.
This \fIoptional\fR subcommand is used when reading a single type-specific
option of channel \fIchannelId\fR. If this subcommand is supported then the
option of channel \fIchannel\fR. If this subcommand is supported then the
subcommand \fBcgetall\fR must be supported as well.
.RS
.PP
The subcommand should return the value of the specified \fIoption\fR.
.PP
If the subcommand throws an error, the command which performed the
(re)configuration or query (usually \fBfconfigure\fR or \fBchan configure\fR)
will appear to have thrown this error. Any exception beyond \fIerror\fR
(e.g.,\ \fBbreak\fR, etc.) is treated as and converted to an error.
.RE
.\" METHOD: cgetall
.TP
\fIcmdPrefix \fBcgetall \fIchannelId\fR
\fIcmdPrefix \fBcgetall \fIchannel\fR
.
This \fIoptional\fR subcommand is used for reading all type-specific options
of channel \fIchannelId\fR. If this subcommand is supported then the
of channel \fIchannel\fR. If this subcommand is supported then the
subcommand \fBcget\fR has to be supported as well.
.RS
.PP
The subcommand should return a list of all options and their values.
This list must have an even number of elements.
.PP
If the subcommand throws an error the command which performed the
(re)configuration or query (usually \fBfconfigure\fR or \fBchan configure\fR)
will appear to have thrown this error. Any exception beyond \fBerror\fR
(e.g.,\ \fBbreak\fR, etc.) is treated as and converted to an error.
.RE
.\" METHOD: blocking
.TP
\fIcmdPrefix \fBblocking \fIchannelId mode\fR
\fIcmdPrefix \fBblocking \fIchannel mode\fR
.
This \fIoptional\fR subcommand handles changes to the blocking mode of the
channel \fIchannelId\fR. The \fImode\fR is a boolean flag. A true value means
channel \fIchannel\fR. The \fImode\fR is a boolean flag. A true value means
that the channel has to be set to blocking, and a false value means that the
channel should be non-blocking.
.RS
.PP
The return value of the subcommand is ignored.
.PP
If the subcommand throws an error the command which caused its
invocation (usually \fBfconfigure\fR or \fBchan configure\fR) will appear to
have thrown this error. Any exception beyond \fBerror\fR (e.g.,\ \fBbreak\fR,
etc.) is treated as and converted to an error.
.RE
.\" METHOD: truncate
.TP
\fIcmdPrefix \fBtruncate\fI channel length\fR
.
This \fIoptional\fR subcommand handles changing the length of the
underlying data stream for the channel \fIchannel\fR. Its length
gets set to \fIlength\fR.
.RS
.PP
If the subcommand throws an error the command which caused its
invocation (usually \fBchan truncate\fR) will appear to have thrown
this error. Any exception beyond \fBerror\fR (e.g.,\ \fBbreak\fR,
etc.) is treated as and converted to an error.
.RE
.SH NOTES
Some of the functions supported in channels defined in Tcl's C
interface are not available to channels reflected to the Tcl level.
.PP
The function \fBTcl_DriverGetHandleProc\fR is not supported;
i.e.,\ reflected channels do not have OS specific handles.
.PP

Changes to doc/regexp.n.

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
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







+








+






+









+


















+










+













+





+







+



















+

-
+












+







subexpression within \fIexp\fR, the next \fIsubMatchVar\fR will
contain the characters that matched the next parenthesized
subexpression to the right in \fIexp\fR, and so on.
.PP
If the initial arguments to \fBregexp\fR start with \fB\-\fR then
they are treated as switches.  The following switches are
currently supported:
.\" OPTION: -about
.TP 15
\fB\-about\fR
.
Instead of attempting to match the regular expression, returns a list
containing information about the regular expression.  The first
element of the list is a subexpression count.  The second element is a
list of property names that describe various attributes of the regular
expression. This switch is primarily intended for debugging purposes.
.\" OPTION: -expanded
.TP 15
\fB\-expanded\fR
.
Enables use of the expanded regular expression syntax where
whitespace and comments are ignored.  This is the same as specifying
the \fB(?x)\fR embedded option (see the \fBre_syntax\fR manual page).
.\" OPTION: -indices
.TP 15
\fB\-indices\fR
.
Changes what is stored in the \fImatchVar\fR and \fIsubMatchVar\fRs.
Instead of storing the matching characters from \fIstring\fR,
each variable
will contain a list of two decimal strings giving the indices
in \fIstring\fR of the first and last characters in the matching
range of characters.
.\" OPTION: -line
.TP 15
\fB\-line\fR
.
Enables newline-sensitive matching.  By default, newline is a
completely ordinary character with no special meaning.  With this
flag,
.QW [^
bracket expressions and
.QW .
never match newline,
.QW ^
matches an empty string after any newline in addition to its normal
function, and
.QW $
matches an empty string before any newline in
addition to its normal function.  This flag is equivalent to
specifying both \fB\-linestop\fR and \fB\-lineanchor\fR, or the
\fB(?n)\fR embedded option (see the \fBre_syntax\fR manual page).
.\" OPTION: -linestop
.TP 15
\fB\-linestop\fR
.
Changes the behavior of
.QW [^
bracket expressions and
.QW .
so that they
stop at newlines.  This is the same as specifying the \fB(?p)\fR
embedded option (see the \fBre_syntax\fR manual page).
.\" OPTION: -lineanchor
.TP 15
\fB\-lineanchor\fR
.
Changes the behavior of
.QW ^
and
.QW $
(the
.QW anchors )
so they match the
beginning and end of a line respectively.  This is the same as
specifying the \fB(?w)\fR embedded option (see the \fBre_syntax\fR
manual page).
.\" OPTION: -nocase
.TP 15
\fB\-nocase\fR
.
Causes upper-case characters in \fIstring\fR to be treated as
lower case during the matching process.
.\" OPTION: -all
.TP 15
\fB\-all\fR
.
Causes the regular expression to be matched as many times as possible
in the string, returning the total number of matches found.  If this
is specified with match variables, they will contain information for
the last match only.
.\" OPTION: -inline
.TP 15
\fB\-inline\fR
.
Causes the command to return, as a list, the data that would otherwise
be placed in match variables.  When using \fB\-inline\fR,
match variables may not be specified.  If used with \fB\-all\fR, the
list will be concatenated at each iteration, such that a flat list is
always returned.  For each match iteration, the command will append the
overall match data, plus one element for each subexpression in the
regular expression.  Examples are:
.RS
.PP
.CS
\fBregexp\fR -inline -- {\ew(\ew)} " inlined "
      \fI\(-> in n\fR
\fBregexp\fR -all -inline -- {\ew(\ew)} " inlined "
      \fI\(-> in n li i ne e\fR
.CE
.RE
.\" OPTION: -start
.TP 15
\fB\-start\fR \fIindex\fR
\fB\-start\fI index\fR
.
Specifies a character index offset into the string to start
matching the regular expression at.
The \fIindex\fR value is interpreted in the same manner
as the \fIindex\fR argument to \fBstring index\fR.
When using this switch,
.QW ^
will not match the beginning of the line, and \eA will still
match the start of the string at \fIindex\fR.  If \fB\-indices\fR
is specified, the indices will be indexed starting from the
absolute beginning of the input string.
\fIindex\fR will be constrained to the bounds of the input string.
.\" OPTION: --
.TP 15
\fB\-\|\-\fR
.
Marks the end of switches.  The argument following this one will
be treated as \fIexp\fR even if it starts with a \fB\-\fR.
.PP
If there are more \fIsubMatchVar\fRs than parenthesized
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
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







-
+







-
+





-
+







-
+








which is a name chosen to look nice given that we are not
actually interested in its contents.
.PP
Find the index of the word \fBbadger\fR (in any case) within a string
and store that in the variable \fBlocation\fR:
.PP
.CS
\fBregexp\fR \-indices {(?i)\embadger\eM} $string location
\fBregexp\fR -indices {(?i)\embadger\eM} $string location
.CE
.PP
This could also be written as a \fIbasic\fR regular expression (as opposed
to using the default syntax of \fIadvanced\fR regular expressions) match by
prefixing the expression with a suitable flag:
.PP
.CS
\fBregexp\fR \-indices {(?ib)\e<badger\e>} $string location
\fBregexp\fR -indices {(?ib)\e<badger\e>} $string location
.CE
.PP
This counts the number of octal digits in a string:
.PP
.CS
\fBregexp\fR \-all {[0\-7]} $string
\fBregexp\fR -all {[0-7]} $string
.CE
.PP
This lists all words (consisting of all sequences of non-whitespace
characters) in a string, and is useful as a more powerful version of the
\fBsplit\fR command:
.PP
.CS
\fBregexp\fR \-all \-inline {\eS+} $string
\fBregexp\fR -all -inline {\eS+} $string
.CE
.SH "SEE ALSO"
re_syntax(n), regsub(n), string(n)
.SH KEYWORDS
match, parsing, pattern, regular expression, splitting, string
'\" Local Variables:
'\" mode: nroff
'\" End:

Changes to doc/registry.n.

8
9
10
11
12
13
14
15

16
17
18



19
20
21
22
23
24
25
8
9
10
11
12
13
14

15
16


17
18
19
20
21
22
23
24
25
26







-
+

-
-
+
+
+







.TH registry n 1.1 registry "Tcl Bundled Packages"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
registry \- Manipulate the Windows registry
.SH SYNOPSIS
.sp
.nf
\fBpackage require registry 1.3\fR
.sp
\fBregistry \fR?\fI\-mode\fR? \fIoption\fR \fIkeyName\fR ?\fIarg arg ...\fR?

\fBregistry \fR?\fI\-mode\fR? \fIoption keyName\fR ?\fIarg arg ...\fR?
.fi
.BE
.SH DESCRIPTION
.PP
The \fBregistry\fR package provides a general set of operations for
manipulating the Windows registry.  The package implements the
\fBregistry\fR Tcl command.  This command is only supported on the
Windows platform.  Warning: this command should be used with caution
49
50
51
52
53
54
55

56
57
58
59
60
61
62
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64







+







when it is \fB\-64bit\fR the 64-bit registry will be used. If this
argument is omitted, the system's default registry will be the subject
of the requested operation.
.PP
\fIOption\fR indicates what to do with the registry key name.  Any
unique abbreviation for \fIoption\fR is acceptable.  The valid options
are:
.\" METHOD: broadcast
.TP
\fBregistry broadcast \fIkeyName\fR ?\fB\-timeout \fImilliseconds\fR?
.
Sends a broadcast message to the system and running programs to notify them
of certain updates.  This is necessary to propagate changes to key registry
keys like Environment.  The timeout specifies the amount of time, in
milliseconds, to wait for applications to respond to the broadcast message.
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
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







+









+







+








+










+






+

















-
-
+
-


-
-
+
-



-
-
+
-


-
-
+
-





-
-
+
-


-
-
+
-


-
-
+
-


-
-
+
-


-
-
+
-







    Environment
} "\e\e"]
set curPath [\fBregistry get\fR $regPath "Path"]
\fBregistry set\fR $regPath "Path" "$curPath;$addPath"
\fBregistry broadcast\fR "Environment"
.CE
.RE
.\" METHOD: delete
.TP
\fBregistry delete \fIkeyName\fR ?\fIvalueName\fR?
.
If the optional \fIvalueName\fR argument is present, the specified
value under \fIkeyName\fR will be deleted from the registry.  If the
optional \fIvalueName\fR is omitted, the specified key and any subkeys
or values beneath it in the registry hierarchy will be deleted.  If
the key could not be deleted then an error is generated.  If the key
did not exist, the command has no effect.
.\" METHOD: get
.TP
\fBregistry get \fIkeyName valueName\fR
.
Returns the data associated with the value \fIvalueName\fR under the key
\fIkeyName\fR.  If either the key or the value does not exist, then an
error is generated.  For more details on the format of the returned
data, see \fBSUPPORTED TYPES\fR, below.
.\" METHOD: keys
.TP
\fBregistry keys \fIkeyName\fR ?\fIpattern\fR?
.
If \fIpattern\fR is not specified, returns a list of names of all the
subkeys of \fIkeyName\fR.  If \fIpattern\fR is specified, only those
names matching \fIpattern\fR are returned.  Matching is determined
using the same rules as for \fBstring match\fR.  If the
specified \fIkeyName\fR does not exist, then an error is generated.
.\" METHOD: set
.TP
\fBregistry set \fIkeyName\fR ?\fIvalueName data \fR?\fItype\fR??
.
If \fIvalueName\fR is not specified, creates the key \fIkeyName\fR if
it does not already exist.  If \fIvalueName\fR is specified, creates
the key \fIkeyName\fR and value \fIvalueName\fR if necessary.  The
contents of \fIvalueName\fR are set to \fIdata\fR with the type
indicated by \fItype\fR.  If \fItype\fR is not specified, the type
\fBsz\fR is assumed.  For more details on the data and type arguments,
see \fBSUPPORTED TYPES\fR below.
.\" METHOD: type
.TP
\fBregistry type \fIkeyName valueName\fR
.
Returns the type of the value \fIvalueName\fR in the key
\fIkeyName\fR.  For more information on the possible types, see
\fBSUPPORTED TYPES\fR, below.
.\" METHOD: values
.TP
\fBregistry values \fIkeyName\fR ?\fIpattern\fR?
.
If \fIpattern\fR is not specified, returns a list of names of all the
values of \fIkeyName\fR.  If \fIpattern\fR is specified, only those
names matching \fIpattern\fR are returned.  Matching is determined
using the same rules as for \fBstring match\fR.
.SH "SUPPORTED TYPES"
Each value under a key in the registry contains some data of a
particular type in a type-specific representation.  The \fBregistry\fR
command converts between this internal representation and one that can
be manipulated by Tcl scripts.  In most cases, the data is simply
returned as a Tcl string.  The type indicates the intended use for the
data, but does not actually change the representation.  For some
types, the \fBregistry\fR command returns the data in a different form to
make it easier to manipulate.  The following types are recognized by the
registry command:
.TP 17
\fBbinary\fR
.IP \fBbinary\fR
.
The registry value contains arbitrary binary data.  The data is represented
exactly in Tcl, including any embedded nulls.
.TP
\fBnone\fR
.IP \fBnone\fR
.
The registry value contains arbitrary binary data with no defined
type.  The data is represented exactly in Tcl, including any embedded
nulls.
.TP
\fBsz\fR
.IP \fBsz\fR
.
The registry value contains a null-terminated string.  The data is
represented in Tcl as a string.
.TP
\fBexpand_sz\fR
.IP \fBexpand_sz\fR
.
The registry value contains a null-terminated string that contains
unexpanded references to environment variables in the normal Windows
style (for example,
.QW %PATH% ).
The data is represented in Tcl as a string.
.TP
\fBdword\fR
.IP \fBdword\fR
.
The registry value contains a little-endian 32-bit number.  The data is
represented in Tcl as a decimal string.
.TP
\fBdword_big_endian\fR
.IP \fBdword_big_endian\fR
.
The registry value contains a big-endian 32-bit number.  The data is
represented in Tcl as a decimal string.
.TP
\fBlink\fR
.IP \fBlink\fR
.
The registry value contains a symbolic link.  The data is represented
exactly in Tcl, including any embedded nulls.
.TP
\fBmulti_sz\fR
.IP \fBmulti_sz\fR
.
The registry value contains an array of null-terminated strings.  The
data is represented in Tcl as a list of strings.
.TP
\fBresource_list\fR
.IP \fBresource_list\fR
.
The registry value contains a device-driver resource list.  The data
is represented exactly in Tcl, including any embedded nulls.
.PP
In addition to the symbolically named types listed above, unknown
types are identified using a 32-bit integer that corresponds to the
type code returned by the system interfaces.  In this case, the data
is represented exactly in Tcl, including any embedded nulls.

Changes to doc/regsub.n.

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
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







+













+













-
+













+






+

















+










+













+






+

-
+










+







with the Tcl parser's use of backslashes, so it is generally
safest to enclose \fIsubSpec\fR in braces if it includes
backslashes.
.LP
If the initial arguments to \fBregsub\fR start with \fB\-\fR then
they are treated as switches.  The following switches are
currently supported:
.\" OPTION: -all
.TP
\fB\-all\fR
.
All ranges in \fIstring\fR that match \fIexp\fR are found and
substitution is performed for each of these ranges.
Without this switch only the first
matching range is found and substituted.
If \fB\-all\fR is specified, then
.QW &
and
.QW \e\fIn\fR
sequences are handled for each substitution using the information
from the corresponding match.
.\" OPTION: -command
.TP
\fB\-command\fR
.VS 8.7
Changes the handling of \fIsubSpec\fR so that it is not treated
as a template for a substitution string and the substrings
.QW &
and
.QW \e\fIn\fR
no longer have special meaning. Instead \fIsubSpec\fR must be a
command prefix, that is, a non-empty list.  The substring of \fIstring\fR
that matches \fIexp\fR, and then each substring that matches each
capturing sub-RE within \fIexp\fR are appended as additional elements
to that list. (The items appended to the list are much like what
\fBregexp\fR \fB-inline\fR would return).  The completed list is then
\fBregexp\fR \fB\-inline\fR would return).  The completed list is then
evaluated as a Tcl command, and the result of that command is the
substitution string.  Any error or exception from command evaluation
becomes an error or exception from the \fBregsub\fR command.
.RS
.PP
If \fB\-all\fR is not also given, the command callback will be invoked at most
once (exactly when the regular expression matches). If \fB\-all\fR is given,
the command callback will be invoked for each matched location, in sequence.
The exact location indices that matched are not made available to the script.
.PP
See \fBEXAMPLES\fR below for illustrative cases.
.RE
.VE 8.7
.\" OPTION: -expanded
.TP
\fB\-expanded\fR
.
Enables use of the expanded regular expression syntax where
whitespace and comments are ignored.  This is the same as specifying
the \fB(?x)\fR embedded option (see the \fBre_syntax\fR manual page).
.\" OPTION: -line
.TP
\fB\-line\fR
.
Enables newline-sensitive matching.  By default, newline is a
completely ordinary character with no special meaning.  With this flag,
.QW [^
bracket expressions and
.QW .
never match newline,
.QW ^
matches an empty string after any newline in addition to its normal
function, and
.QW $
matches an empty string before any newline in
addition to its normal function.  This flag is equivalent to
specifying both \fB\-linestop\fR and \fB\-lineanchor\fR, or the
\fB(?n)\fR embedded option (see the \fBre_syntax\fR manual page).
.\" OPTION: -linestop
.TP
\fB\-linestop\fR
.
Changes the behavior of
.QW [^
bracket expressions and
.QW .
so that they
stop at newlines.  This is the same as specifying the \fB(?p)\fR
embedded option (see the \fBre_syntax\fR manual page).
.\" OPTION: -lineanchor
.TP
\fB\-lineanchor\fR
.
Changes the behavior of
.QW ^
and
.QW $
(the
.QW anchors )
so they match the
beginning and end of a line respectively.  This is the same as
specifying the \fB(?w)\fR embedded option (see the \fBre_syntax\fR
manual page).
.\" OPTION: -nocase
.TP
\fB\-nocase\fR
.
Upper-case characters in \fIstring\fR will be converted to lower-case
before matching against \fIexp\fR;  however, substitutions specified
by \fIsubSpec\fR use the original unconverted form of \fIstring\fR.
.\" OPTION: -start
.TP
\fB\-start\fR \fIindex\fR
\fB\-start\fI index\fR
.
Specifies a character index offset into the string to start
matching the regular expression at.
The \fIindex\fR value is interpreted in the same manner
as the \fIindex\fR argument to \fBstring index\fR.
When using this switch,
.QW ^
will not match the beginning of the line, and \eA will still
match the start of the string at \fIindex\fR.
\fIindex\fR will be constrained to the bounds of the input string.
.\" OPTION: --
.TP
\fB\-\|\-\fR
.
Marks the end of switches.  The argument following this one will
be treated as \fIexp\fR even if it starts with a \fB\-\fR.
.PP
If \fIvarName\fR is supplied, the command returns a count of the
252
253
254
255
256
257
258









259
260
261
262
263
264
265
266
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284







+
+
+
+
+
+
+
+
+








        return " "
    }
    # convert hex to a char
    scan $h %x charNumber
    format %c $charNumber
}}}]
.CE
.PP
The \fB\-command\fR option can also be useful for restricting the range of
commands such as \fBstring totitle\fR:
.PP
.CS
set message "the quIck broWn fOX JUmped oVer the laZy dogS..."
puts [\fBregsub\fR -all -command {\ew+} $message {string totitle}]
# \(-> \fIThe Quick Brown Fox Jumped Over The Lazy Dogs..\fR
.CE
.VE 8.7
.SH "SEE ALSO"
regexp(n), re_syntax(n), subst(n), string(n)
.SH KEYWORDS
match, pattern, quoting, regular expression, substitution
'\" Local Variables:
'\" mode: nroff
'\" End:

Changes to doc/return.n.

9
10
11
12
13
14
15

16
17
18
19
20

21
22
23
24
25
26
27
9
10
11
12
13
14
15
16
17

18

19
20
21
22
23
24
25
26
27







+

-

-

+







.TH return n 8.5 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
return \- Return from a procedure, or set return code of a script
.SH SYNOPSIS
.nf
\fBreturn \fR?\fIresult\fR?
.sp
\fBreturn \fR?\fB\-code \fIcode\fR? ?\fIresult\fR?
.sp
\fBreturn \fR?\fIoption value \fR...? ?\fIresult\fR?
.fi
.BE
.SH DESCRIPTION
.PP
In its simplest usage, the \fBreturn\fR command is used without options
in the body of a procedure to immediately return control to the caller
of the procedure.  If a \fIresult\fR argument is provided, its value
becomes the result of the procedure passed back to the caller.
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
50
51
52
53
54
55
56

57
58
59
60
61
62
63
64







-
+







Normal return:  same as if the option is omitted.  The return code
of the procedure is 0 (\fBTCL_OK\fR).
.TP 13
\fBerror\fR (or \fB1\fR)
.
Error return: the return code of the procedure is 1 (\fBTCL_ERROR\fR).
The procedure command behaves in its calling context as if it
were the command \fBerror\fR \fIresult\fR.  See below for additional
were the command \fBerror\fI result\fR.  See below for additional
options.
.TP 13
\fBreturn\fR (or \fB2\fR)
.
The return code of the procedure is 2 (\fBTCL_RETURN\fR).  The
procedure command behaves in its calling context as if it
were the command \fBreturn\fR (with no arguments).
74
75
76
77
78
79
80
81




82
83
84
85
86
87
88
74
75
76
77
78
79
80

81
82
83
84
85
86
87
88
89
90
91







-
+
+
+
+







The return code of the procedure is 4 (\fBTCL_CONTINUE\fR).  The
procedure command behaves in its calling context as if it
were the command \fBcontinue\fR.
.TP 13
\fIvalue\fR
.
\fIValue\fR must be an integer;  it will be returned as the
return code for the current procedure.
return code for the current procedure. Applications
and packages should use values in the range 5 to 1073741823 (0x3fffffff)
for their own purposes. Values outside this range are reserved
for use by Tcl.
.LP
When a procedure wants to signal that it has received invalid
arguments from its caller, it may use \fBreturn -code error\fR
with \fIresult\fR set to a suitable error message.  Otherwise
usage of the \fBreturn -code\fR option is mostly limited to
procedures that implement a new control structure.
.PP
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
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







+












+


















+


+


-
+
+











+












+







used to capture all of this information \(em the return code, the result,
and the return options dictionary \(em that arise from evaluation of a
script.
.PP
As documented above, the \fB\-code\fR entry in the return options dictionary
receives special treatment by Tcl.  There are other return options also
recognized and treated specially by Tcl.  They are:
.\" OPTION: -errorcode
.TP
\fB\-errorcode \fIlist\fR
.
The \fB\-errorcode\fR option receives special treatment only when the value
of the \fB\-code\fR option is \fBTCL_ERROR\fR.  Then the \fIlist\fR value
is meant to be additional information about the error,
presented as a Tcl list for further processing by programs.
If no \fB\-errorcode\fR option is provided to \fBreturn\fR when
the \fB\-code error\fR option is provided, Tcl will set the value
of the \fB\-errorcode\fR entry in the return options dictionary
to the default value of \fBNONE\fR.  The \fB\-errorcode\fR return
option will also be stored in the global variable \fBerrorCode\fR.
.\" OPTION: -errorinfo
.TP
\fB\-errorinfo \fIinfo\fR
.
The \fB\-errorinfo\fR option receives special treatment only when the value
of the \fB\-code\fR option is \fBTCL_ERROR\fR.  Then \fIinfo\fR is the initial
stack trace, meant to provide to a human reader additional information
about the context in which the error occurred.  The stack trace will
also be stored in the global variable \fBerrorInfo\fR.
If no \fB\-errorinfo\fR option is provided to \fBreturn\fR when
the \fB\-code error\fR option is provided, Tcl will provide its own
initial stack trace value in the entry for \fB\-errorinfo\fR.  Tcl's
initial stack trace will include only the call to the procedure, and
stack unwinding will append information about higher stack levels, but
there will be no information about the context of the error within
the procedure.  Typically the \fIinfo\fR value is supplied from
the value of \fB\-errorinfo\fR in a return options dictionary captured
by the \fBcatch\fR command (or from the copy of that information
stored in the global variable \fBerrorInfo\fR).
.\" OPTION: -errorstack
.TP
\fB\-errorstack \fIlist\fR
.
The \fB\-errorstack\fR option receives special treatment only when the value
of the \fB\-code\fR option is \fBTCL_ERROR\fR.  Then \fIlist\fR is the initial
error stack, recording actual argument values passed to each proc level.  The error stack will
error stack, recording actual argument values passed to each proc level.
The error stack will
also be reachable through \fBinfo errorstack\fR.
If no \fB\-errorstack\fR option is provided to \fBreturn\fR when
the \fB\-code error\fR option is provided, Tcl will provide its own
initial error stack in the entry for \fB\-errorstack\fR.  Tcl's
initial error stack will include only the call to the procedure, and
stack unwinding will append information about higher stack levels, but
there will be no information about the context of the error within
the procedure.  Typically the \fIlist\fR value is supplied from
the value of \fB\-errorstack\fR in a return options dictionary captured
by the \fBcatch\fR command (or from the copy of that information from
\fBinfo errorstack\fR).
.\" OPTION: -level
.TP
\fB\-level \fIlevel\fR
.
The \fB\-level\fR and \fB\-code\fR options work together to set the return
code to be returned by one of the commands currently being evaluated.
The \fIlevel\fR value must be a non-negative integer representing a number
of levels on the call stack.  It defines the number of levels up the stack
at which the return code of a command currently being evaluated should
be \fIcode\fR.  If no \fB\-level\fR option is provided, the default value
of \fIlevel\fR is 1, so that \fBreturn\fR sets the return code that the
current procedure returns to its caller, 1 level up the call stack.  The
mechanism by which these options work is described in more detail below.
.\" OPTION: -options
.TP
\fB\-options \fIoptions\fR
.
The value \fIoptions\fR must be a valid dictionary.  The entries of that
dictionary are treated as additional \fIoption value\fR pairs for the
\fBreturn\fR command.
.SH "RETURN CODE HANDLING MECHANISMS"

Changes to doc/safe.n.

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
30
31
32









33
34
35
36
37
38
39
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
30
31
32
33
34
35
36
37
38
39
40













+

-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
+

+

-
-
-
-
-
+
+
+
+
+
+
+
+
+







'\"
'\" Copyright (c) 1995-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH "Safe Tcl" n 8.0 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
safe \- Creating and manipulating safe interpreters
.SH SYNOPSIS
.nf
\fB::safe::interpCreate\fR ?\fIchild\fR? ?\fIoptions...\fR?
.sp
\fB::safe::interpInit\fR \fIchild\fR ?\fIoptions...\fR?
\fB::safe::interpInit\fI child\fR ?\fIoptions...\fR?
.sp
\fB::safe::interpConfigure\fR \fIchild\fR ?\fIoptions...\fR?
\fB::safe::interpConfigure\fI child\fR ?\fIoptions...\fR?
.sp
\fB::safe::interpDelete\fR \fIchild\fR
\fB::safe::interpDelete\fI child\fR
.sp
\fB::safe::interpAddToAccessPath\fR \fIchild\fR \fIdirectory\fR
\fB::safe::interpAddToAccessPath\fI child directory\fR
.sp
\fB::safe::interpFindInAccessPath\fR \fIchild\fR \fIdirectory\fR
\fB::safe::interpFindInAccessPath\fI child directory\fR
.sp
\fB::safe::setSyncMode\fR ?\fInewValue\fR?
\fB::safe::setLogCmd\fR ?\fIcmd arg...\fR?
.fi
.SS OPTIONS
.PP
?\fB\-accessPath\fR \fIpathList\fR?
?\fB\-statics\fR \fIboolean\fR? ?\fB\-noStatics\fR?
?\fB\-nested\fR \fIboolean\fR? ?\fB\-nestedLoadOk\fR?
?\fB\-deleteHook\fR \fIscript\fR?
.nf
?\fB\-accessPath\fI pathList\fR?
?\fB\-autoPath\fI pathList\fR?
?\fB\-statics\fI boolean\fR?
?\fB\-noStatics\fR?
?\fB\-nested\fI boolean\fR?
?\fB\-nestedLoadOk\fR?
?\fB\-deleteHook\fI script\fR?
.fi
.BE
.SH DESCRIPTION
Safe Tcl is a mechanism for executing untrusted Tcl scripts
safely and for providing mediated access by such scripts to
potentially dangerous functionality.
.PP
Safe Tcl ensures that untrusted Tcl scripts cannot harm the
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
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







+


+







-
+
+





+
+

-
+
+





+

-
+
+


















-
+



-
+


+

-
+
+





+

-
+
+











+

-
+
+













+

+
+
+
+
+
+
+
+
+
+
+

+







Different levels of security can be selected by using the optional flags
of the commands described below.
.PP
All commands provided in the parent interpreter by Safe Tcl reside in
the \fBsafe\fR namespace.
.SH COMMANDS
The following commands are provided in the parent interpreter:
.\" COMMAND: interpCreate
.TP
\fB::safe::interpCreate\fR ?\fIchild\fR? ?\fIoptions...\fR?
.
Creates a safe interpreter, installs the aliases described in the section
\fBALIASES\fR and initializes the auto-loading and package mechanism as
specified by the supplied \fIoptions\fR.
See the \fBOPTIONS\fR section below for a description of the
optional arguments.
If the \fIchild\fR argument is omitted, a name will be generated.
\fB::safe::interpCreate\fR always returns the interpreter name.
.sp
.RS
.PP
The interpreter name \fIchild\fR may include namespace separators,
but may not have leading or trailing namespace separators, or excess
colon characters in namespace separators.  The interpreter name is
qualified relative to the global namespace ::, not the namespace in which
the \fB::safe::interpCreate\fR command is evaluated.
.RE
.\" COMMAND: interpInit
.TP
\fB::safe::interpInit\fR \fIchild\fR ?\fIoptions...\fR?
\fB::safe::interpInit\fI child\fR ?\fIoptions...\fR?
.
This command is similar to \fBinterpCreate\fR except it that does not
create the safe interpreter. \fIchild\fR must have been created by some
other means, like \fBinterp create\fR \fB\-safe\fR.  The interpreter
name \fIchild\fR may include namespace separators, subject to the same
restrictions as for \fBinterpCreate\fR.
.\" COMMAND: interpConfigure
.TP
\fB::safe::interpConfigure\fR \fIchild\fR ?\fIoptions...\fR?
\fB::safe::interpConfigure\fI child\fR ?\fIoptions...\fR?
.
If no \fIoptions\fR are given, returns the settings for all options for the
named safe interpreter as a list of options and their current values
for that \fIchild\fR.
If a single additional argument is provided,
it will return a list of 2 elements \fIname\fR and \fIvalue\fR where
\fIname\fR is the full name of that option and \fIvalue\fR the current value
for that option and the \fIchild\fR.
If more than two additional arguments are provided, it will reconfigure the
safe interpreter and change each and only the provided options.
See the section on \fBOPTIONS\fR below for options description.
Example of use:
.RS
.PP
.CS
# Create new interp with the same configuration as "$i0":
set i1 [safe::interpCreate {*}[safe::interpConfigure $i0]]

# Get the current deleteHook
set dh [safe::interpConfigure $i0  \-del]
set dh [safe::interpConfigure $i0  -del]

# Change (only) the statics loading ok attribute of an
# interp and its deleteHook (leaving the rest unchanged):
safe::interpConfigure $i0  \-delete {foo bar} \-statics 0
safe::interpConfigure $i0  -delete {foo bar} -statics 0
.CE
.RE
.\" COMMAND: interpDelete
.TP
\fB::safe::interpDelete\fR \fIchild\fR
\fB::safe::interpDelete\fI child\fR
.
Deletes the safe interpreter and cleans up the corresponding
parent interpreter data structures.
If a \fIdeleteHook\fR script was specified for this interpreter it is
evaluated before the interpreter is deleted, with the name of the
interpreter as an additional argument.
.\" COMMAND: interpFindInAccessPath
.TP
\fB::safe::interpFindInAccessPath\fR \fIchild\fR \fIdirectory\fR
\fB::safe::interpFindInAccessPath\fI child directory\fR
.
This command finds and returns the token for the real directory
\fIdirectory\fR in the safe interpreter's current virtual access path.
It generates an error if the directory is not found.
Example of use:
.RS
.PP
.CS
$child eval [list set tk_library \e
      [::safe::interpFindInAccessPath $name $tk_library]]
.CE
.RE
.\" COMMAND: interpAddToAccessPath
.TP
\fB::safe::interpAddToAccessPath\fR \fIchild\fR \fIdirectory\fR
\fB::safe::interpAddToAccessPath\fI child directory\fR
.
This command adds \fIdirectory\fR to the virtual path maintained for the
safe interpreter in the parent, and returns the token that can be used in
the safe interpreter to obtain access to files in that directory.
If the directory is already in the virtual path, it only returns the token
without adding the directory to the virtual path again.
Example of use:
.RS
.PP
.CS
$child eval [list set tk_library \e
      [::safe::interpAddToAccessPath $name $tk_library]]
.CE
.RE
.\" COMMAND: setSyncMode
.TP
\fB::safe::setSyncMode\fR ?\fInewValue\fR?
.
This command is used to get or set the "Sync Mode" of the Safe Base.
When an argument is supplied, the command returns an error if the argument
is not a boolean value, or if any Safe Base interpreters exist.  Typically
the value will be set as part of initialization - boolean true for
"Sync Mode" on (the default), false for "Sync Mode" off.  With "Sync Mode"
on, the Safe Base keeps each child interpreter's ::auto_path synchronized
with its access path.  See the section \fBSYNC MODE\fR below for details.
.\" COMMAND: setLogCmd
.TP
\fB::safe::setLogCmd\fR ?\fIcmd arg...\fR?
.
This command installs a script that will be called when interesting
life cycle events occur for a safe interpreter.
When called with no arguments, it returns the currently installed script.
When called with one argument, an empty string, the currently installed
script is removed and logging is turned off.
The script will be invoked with one additional argument, a string
describing the event of interest.
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
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







+

-
+
+







+

+
+
+
+
+
+
+
+
+
-
+
+




+


+



+

-
+
+





+


+



+

-
+
+










-
+
+










-
+
+







-
+
+


-
+



-
+
+






+







.SS OPTIONS
The following options are common to
\fB::safe::interpCreate\fR, \fB::safe::interpInit\fR,
and \fB::safe::interpConfigure\fR.
Any option name can be abbreviated to its minimal
non-ambiguous name.
Option names are not case sensitive.
.\" OPTION: -accessPath
.TP
\fB\-accessPath\fR \fIdirectoryList\fR
\fB\-accessPath\fI directoryList\fR
.
This option sets the list of directories from which the safe interpreter
can \fBsource\fR and \fBload\fR files.
If this option is not specified, or if it is given as the
empty list, the safe interpreter will use the same directories as its
parent for auto-loading.
See the section \fBSECURITY\fR below for more detail about virtual paths,
tokens and access control.
.\" OPTION: -autoPath
.TP
\fB\-autoPath\fI directoryList\fR
.
This option sets the list of directories in the safe interpreter's
::auto_path.  The option is undefined if the Safe Base has "Sync Mode" on
- in that case the safe interpreter's ::auto_path is managed by the Safe
Base and is a tokenized form of its access path.
See the section \fBSYNC MODE\fR below for details.
.\" OPTION: -statics
.TP
\fB\-statics\fR \fIboolean\fR
\fB\-statics\fI boolean\fR
.
This option specifies if the safe interpreter will be allowed
to load statically linked packages (like \fBload {} Tk\fR).
The default value is \fBtrue\fR :
safe interpreters are allowed to load statically linked packages.
.\" OPTION: -noStatics
.TP
\fB\-noStatics\fR
.
This option is a convenience shortcut for \fB\-statics false\fR and
thus specifies that the safe interpreter will not be allowed
to load statically linked packages.
.\" OPTION: -nested
.TP
\fB\-nested\fR \fIboolean\fR
\fB\-nested\fI boolean\fR
.
This option specifies if the safe interpreter will be allowed
to load packages into its own sub-interpreters.
The default value is \fBfalse\fR :
safe interpreters are not allowed to load packages into
their own sub-interpreters.
.\" OPTION: -nestedLoadOk
.TP
\fB\-nestedLoadOk\fR
.
This option is a convenience shortcut for \fB\-nested true\fR and
thus specifies the safe interpreter will be allowed
to load packages into its own sub-interpreters.
.\" OPTION: -deleteHook
.TP
\fB\-deleteHook\fR \fIscript\fR
\fB\-deleteHook\fI script\fR
.
When this option is given a non-empty \fIscript\fR, it will be
evaluated in the parent with the name of
the safe interpreter as an additional argument
just before actually deleting the safe interpreter.
Giving an empty value removes any currently installed deletion hook
script for that safe interpreter.
The default value (\fB{}\fR) is not to have any deletion call back.
.SH ALIASES
The following aliases are provided in a safe interpreter:
.TP
\fBsource\fR \fIfileName\fR
\fBsource\fI fileName\fR
.
The requested file, a Tcl source file, is sourced into the safe interpreter
if it is found.
The \fBsource\fR alias can only source files from directories in
the virtual path for the safe interpreter. The \fBsource\fR alias requires
the safe interpreter to
use one of the token names in its virtual path to denote the directory in
which the file to be sourced can be found.
See the section on \fBSECURITY\fR for more discussion of restrictions on
valid filenames.
.TP
\fBload\fR \fIfileName\fR
\fBload\fI fileName\fR
.
The requested file, a shared object file, is dynamically loaded into the
safe interpreter if it is found.
The filename must contain a token name mentioned in the virtual path for
the safe interpreter for it to be found successfully.
Additionally, the shared object file must contain a safe entry point; see
the manual page for the \fBload\fR command for more details.
.TP
\fBfile\fR ?\fIsubCmd args...\fR?
\fBfile\fR ?\fIsubcommand args...\fR?
.
The \fBfile\fR alias provides access to a safe subset of the subcommands of
the \fBfile\fR command; it allows only \fBdirname\fR, \fBjoin\fR,
\fBextension\fR, \fBroot\fR, \fBtail\fR, \fBpathname\fR and \fBsplit\fR
\fBextension\fR, \fBroot\fR, \fBtail\fR, \fBpathtype\fR and \fBsplit\fR
subcommands. For more details on what these subcommands do see the manual
page for the \fBfile\fR command.
.TP
\fBencoding\fR ?\fIsubCmd args...\fR?
\fBencoding\fR ?\fIsubcommand args...\fR?
.
The \fBencoding\fR alias provides access to a safe subset of the
subcommands of the \fBencoding\fR command;  it disallows setting of
the system encoding, but allows all other subcommands including
\fBsystem\fR to check the current encoding.
.TP
\fBexit\fR
.
The calling interpreter is deleted and its computation is stopped, but the
Tcl process in which this interpreter exists is not terminated.
.SH SECURITY
Safe Tcl does not attempt to completely prevent annoyance and
denial of service attacks. These forms of attack prevent the
application or user from temporarily using the computer to perform
useful work, for example by consuming all available CPU time or
327
328
329
330
331
332
333
334


335
336
337
338
339
340
341
381
382
383
384
385
386
387

388
389
390
391
392
393
394
395
396







-
+
+







.PQ \fBtclIndex\fR .
.PP
Each element of the initial access path
list will be assigned a token that will be set in
the child \fBauto_path\fR and the first element of that list will be set as
the \fBtcl_library\fR for that child.
.PP
If the access path argument is not given or is the empty list,
If the access path argument is not given to \fB::safe::interpCreate\fR or
\fB::safe::interpInit\fR or is the empty list,
the default behavior is to let the child access the same packages
as the parent has access to (Or to be more precise:
only packages written in Tcl (which by definition cannot be dangerous
as they run in the child interpreter) and C extensions that
provides a _SafeInit entry point). For that purpose, the parent's
\fBauto_path\fR will be used to construct the child access path.
In order that the child successfully loads the Tcl library files
353
354
355
356
357
358
359















































































































































360
361


362
363

364
365
366
367
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558

559
560
561

562
563
564
565
566







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
+

-
+




explicitly specifying your directory list with the \fB\-accessPath\fR flag
instead of relying on this default mechanism.
.PP
When the \fIaccessPath\fR is changed after the first creation or
initialization (i.e. through \fBinterpConfigure -accessPath \fR\fIlist\fR),
an \fBauto_reset\fR is automatically evaluated in the safe interpreter
to synchronize its \fBauto_index\fR with the new token list.
.SH TYPICAL USE
In many cases, the properties of a Safe Base interpreter can be specified
when the interpreter is created, and then left unchanged for the lifetime
of the interpreter.
.PP
If you wish to use Safe Base interpreters with "Sync Mode" off, evaluate
the command
.RS
.PP
.CS
 safe::setSyncMode 0
.CE
.RE
.PP
Use \fB::safe::interpCreate\fR or \fB::safe::interpInit\fR to create an
interpreter with the properties that you require.  The simplest way is not
to specify \fB\-accessPath\fR or \fB\-autoPath\fR, which means the safe
interpreter will use the same paths as the parent interpreter.  However,
if \fB\-accessPath\fR is specified, then \fB\-autoPath\fR must also be
specified, or else it will be set to {}.
.PP
The value of \fB\-autoPath\fR will be that required to access tclIndex
and pkgIndex.tcl files according to the same rules as an unsafe
interpreter (see pkg_mkIndex(n) and library(n)).
.PP
With "Sync Mode" on, the option \fB\-autoPath\fR is undefined, and
the Safe Base sets the child's ::auto_path to a tokenized form of the
access path. In addition to the directories present if "Safe Mode" is off,
the ::auto_path includes the numerous subdirectories and module paths
that belong to the access path.
.SH SYNC MODE
Before Tcl version 9.0, the Safe Base kept each safe interpreter's
::auto_path synchronized with a tokenized form of its access path.
Limitations of Tcl 8.4 and earlier made this feature necessary.  This
definition of ::auto_path did not conform its specification in library(n)
and pkg_mkIndex(n), but nevertheless worked perfectly well for the discovery
and loading of packages.  The introduction of Tcl modules in Tcl 8.5 added a
large number of directories to the access path, and it is inconvenient to
have these additional directories unnecessarily appended to the ::auto_path.
.PP
In order to preserve compatibility with existing code, this synchronization
of the ::auto_path and access path ("Sync Mode" on) is still the default.
However, the Safe Base offers the option of limiting the safe interpreter's
::auto_path to the much shorter list of directories that is necessary for
it to perform its function ("Sync Mode" off).  Use the command
\fB::safe::setSyncMode\fR to choose the mode before creating any Safe
Base interpreters.
.PP
In either mode, the most convenient way to initialize a safe interpreter is
to call \fB::safe::interpCreate\fR or \fB::safe::interpInit\fR without the
\fB\-accessPath\fR or \fB\-autoPath\fR options (or with the \fB\-accessPath\fR
option set to the
empty list), which will give the safe interpreter the same access as the
parent interpreter to packages, modules, and autoloader files.  With
"Sync Mode" off, the Safe Base will set the value of \fB\-autoPath\fR to the
parent's ::auto_path, and will set the child's ::auto_path to a tokenized form
of the parent's ::auto_path.
.PP
With "Sync Mode" off, if a value is specified for \fB\-autoPath\fR, even the
empty list, in a call to \fB::safe::interpCreate\fR, \fB::safe::interpInit\fR,
or \fB::safe::interpConfigure\fR, it will be tokenized and used as the safe
interpreter's ::auto_path.  Any directories that do not also belong to the
access path cannot be tokenized and will be silently ignored.  However, the
value of \fB\-autoPath\fR will remain as specified, and will be used to
re-tokenize the child's ::auto_path if \fB::safe::interpConfigure\fR is called
to change the value of \fB\-accessPath\fR.
.PP
With "Sync Mode" off, if the access path is reset to the values in the
parent interpreter by calling \fB::safe::interpConfigure\fR with arguments
\fB\-accessPath\fR {}, then the ::auto_path will also be reset unless the
argument \fB\-autoPath\fR is supplied to specify a different value.
.PP
With "Sync Mode" off, if a non-empty value of \fB\-accessPath\fR is supplied, the
safe interpreter's ::auto_path will be set to {} (by
\fB::safe::interpCreate\fR, \fB::safe::interpInit\fR) or left unchanged
(by \fB::safe::interpConfigure\fR).  If the same command specifies a new
value for \fB\-autoPath\fR, it will be applied after the \fB\-accessPath\fR
argument has been processed.
.PP
Examples of use with "Sync Mode" off: any of these commands will set the
::auto_path to a tokenized form of its value in the parent interpreter:
.RS
.PP
.CS
safe::interpCreate foo
safe::interpCreate foo -accessPath {}
safe::interpInit bar
safe::interpInit bar -accessPath {}
safe::interpConfigure foo -accessPath {}
.CE
.RE
.PP
Example of use with "Sync Mode" off: when initializing a safe interpreter
with a non-empty access path, the ::auto_path will be set to {} unless its
own value is also specified:
.RS
.PP
.CS
safe::interpCreate foo -accessPath {
    /usr/local/TclHome/lib/tcl9.0
    /usr/local/TclHome/lib/tcl9.0/http1.0
    /usr/local/TclHome/lib/tcl9.0/opt0.4
    /usr/local/TclHome/lib/tcl9.0/msgs
    /usr/local/TclHome/lib/tcl9.0/encoding
    /usr/local/TclHome/lib
}

# The child's ::auto_path must be given a suitable value:

safe::interpConfigure foo -autoPath {
    /usr/local/TclHome/lib/tcl9.0
    /usr/local/TclHome/lib
}

# The two commands can be combined:

safe::interpCreate foo -accessPath {
    /usr/local/TclHome/lib/tcl9.0
    /usr/local/TclHome/lib/tcl9.0/http1.0
    /usr/local/TclHome/lib/tcl9.0/opt0.4
    /usr/local/TclHome/lib/tcl9.0/msgs
    /usr/local/TclHome/lib/tcl9.0/encoding
    /usr/local/TclHome/lib
} -autoPath {
    /usr/local/TclHome/lib/tcl9.0
    /usr/local/TclHome/lib
}
.CE
.RE
.PP
Example of use with "Sync Mode" off: the command
\fBsafe::interpAddToAccessPath\fR does not change the safe interpreter's
::auto_path, and so any necessary change must be made by the script:
.RS
.PP
.CS
safe::interpAddToAccessPath foo /usr/local/TclHome/lib/extras/Img1.4.11

lassign [safe::interpConfigure foo -autoPath] DUM childAutoPath
lappend childAutoPath /usr/local/TclHome/lib/extras/Img1.4.11
safe::interpConfigure foo -autoPath $childAutoPath
.CE
.RE
.SH "SEE ALSO"
interp(n), library(n), load(n), package(n), source(n), unknown(n)
interp(n), library(n), load(n), package(n), pkg_mkIndex(n), source(n),
tm(n), unknown(n)
.SH KEYWORDS
alias, auto\-loading, auto_mkindex, load, parent interpreter, safe
alias, auto-loading, auto_mkindex, load, parent interpreter, safe
interpreter, child interpreter, source
'\" Local Variables:
'\" mode: nroff
'\" End:

Changes to doc/scan.n.

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
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







-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+



-
-
+
-



-
-
+
-



-
-
+
-



-
-
+
-



-
-
+
-




-
-
-
-
-
+
-
-
-
+
+
+
+
-
-
+
+
-




-
-
+
-


-
-
+
-






-
-
+
-










-
-
+
-











-
-
+
-







at most once and the empty positions will be filled in with empty strings.
.SS "OPTIONAL SIZE MODIFIER"
.PP
The size modifier field is used only when scanning a substring into
one of Tcl's integer values.  The size modifier field dictates the
integer range acceptable to be stored in a variable, or, for the inline
case, in a position in the result list.
The syntactically valid values for the size modifier are \fBh\fR, \fBL\fR,
\fBl\fR, and \fBll\fR.  The \fBh\fR size modifier value is equivalent
to the absence of a size modifier in the the conversion specifier.
Either one indicates the integer range to be stored is limited to
The syntactically valid values for the size modifier are \fBh\fR,
\fBl\fR, \fBz\fR, \fBt\fR, \fBq\fR, \fBj\fR, \fBll\fR, and \fBL\fR.
The \fBh\fR size modifier value is equivalent to the absence of a size
modifier in the the conversion specifier.  Either one indicates the
integer range to be stored is limited to the 32-bit range.  The \fBL\fR
the same range produced by the \fBint()\fR function of the \fBexpr\fR
command.  The \fBL\fR size modifier is equivalent to the \fBl\fR size
modifier. Either one indicates the integer range to be stored is
limited to the same range produced by the \fBwide()\fR function of
the \fBexpr\fR command.  The \fBll\fR size modifier indicates that
the integer range to be stored is unlimited.
size modifier is equivalent to the \fBll\fR size modifier.  Either one
indicates the integer range to be stored is unlimited.  The \fBl\fR (or
\fBq\fR or \fBj\fR) size modifier indicates that the integer range to be
stored is limited to the same range produced by the \fBwide()\fR function
of the \fBexpr\fR command. The \fBz\fR and \fBt\fR modifiers indicate the
integer range to be the same as for either \fBh\fR or \fBl\fR, depending
on the value of the \fBpointerSize\fR element of the \fBtcl_platform\fR array.
.SS "MANDATORY CONVERSION CHARACTER"
.PP
The following conversion characters are supported:
.TP
\fBd\fR
.IP \fBd\fR
.
The input substring must be a decimal integer.
It is read in and the integer value is stored in the variable,
truncated as required by the size modifier value.
.TP
\fBo\fR
.IP \fBo\fR
.
The input substring must be an octal integer. It is read in and the
integer value is stored in the variable,
truncated as required by the size modifier value.
.TP
\fBx\fR or \fBX\fR
.IP "\fBx\fR or \fBX\fR"
.
The input substring must be a hexadecimal integer.
It is read in and the integer value is stored in the variable,
truncated as required by the size modifier value.
.TP
\fBb\fR
.IP \fBb\fR
.
The input substring must be a binary integer.
It is read in and the integer value is stored in the variable,
truncated as required by the size modifier value.
.TP
\fBu\fR
.IP \fBu\fR
.
The input substring must be a decimal integer.
The integer value is truncated as required by the size modifier
value, and the corresponding unsigned value for that truncated
range is computed and stored in the variable as a decimal string.
The conversion makes no sense without reference to a truncation range,
so the size modifier \fBll\fR is not permitted in combination
with conversion character \fBu\fR.
.TP
\fBi\fR
.IP \fBi\fR
.
The input substring must be an integer.  The base (i.e. decimal, octal, or hexadecimal) is determined by the C convention (leading 0 for octal; prefix 0x for hexadecimal).  The integer value is stored in the variable,
truncated as required by the size modifier value.
The input substring must be an integer.  The base (i.e. decimal,
octal, or hexadecimal) is determined by the C convention (leading
0 for octal; prefix 0x for hexadecimal).  The integer value is
stored in the variable, truncated as required by the size modifier
.TP
\fBc\fR
value.
.IP \fBc\fR
.
A single character is read in and its Unicode value is stored in
the variable as an integer value.
Initial white space is not skipped in this case, so the input
substring may be a white-space character.
.TP
\fBs\fR
.IP \fBs\fR
.
The input substring consists of all the characters up to the next
white-space character; the characters are copied to the variable.
.TP
\fBe\fR or \fBf\fR or \fBg\fR or \fBE\fR or \fBG\fR
.IP "\fBe\fR or \fBf\fR or \fBg\fR or \fBE\fR or \fBG\fR"
.
The input substring must be a floating-point number consisting
of an optional sign, a string of decimal digits possibly
containing a decimal point, and an optional exponent consisting
of an \fBe\fR or \fBE\fR followed by an optional sign and a string of
decimal digits.
It is read in and stored in the variable as a floating-point value.
.TP
\fB[\fIchars\fB]\fR
.IP \fB[\fIchars\fB]\fR
.
The input substring consists of one or more characters in \fIchars\fR.
The matching string is stored in the variable.
If the first character between the brackets is a \fB]\fR then
it is treated as part of \fIchars\fR rather than the closing
bracket for the set.
If \fIchars\fR
contains a sequence of the form \fIa\fB\-\fIb\fR then any
character between \fIa\fR and \fIb\fR (inclusive) will match.
If the first or last character between the brackets is a \fB\-\fR, then
it is treated as part of \fIchars\fR rather than indicating a range.
.TP
\fB[^\fIchars\fB]\fR
.IP \fB[^\fIchars\fB]\fR
.
The input substring consists of one or more characters not in \fIchars\fR.
The matching string is stored in the variable.
If the character immediately following the \fB^\fR is a \fB]\fR then it is
treated as part of the set rather than the closing bracket for
the set.
If \fIchars\fR
contains a sequence of the form \fIa\fB\-\fIb\fR then any
character between \fIa\fR and \fIb\fR (inclusive) will be excluded
from the set.
If the first or last character between the brackets is a \fB\-\fR, then
it is treated as part of \fIchars\fR rather than indicating a range value.
.TP
\fBn\fR
.IP \fBn\fR
.
No input is consumed from the input string.  Instead, the total number
of characters scanned from the input string so far is stored in the variable.
.PP
The number of characters read from the input for a conversion is the
largest number that makes sense for that particular conversion (e.g.
as many decimal digits as possible for \fB%d\fR, as
many octal digits as possible for \fB%o\fR, and so on).
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
245
246
247
248
249
250
251


252
253
254
255
256
257
258







-
-







puts "X=$x, Y=$y"
.CE
.PP
An interactive session demonstrating the truncation of integer
values determined by size modifiers:
.PP
.CS
\fI%\fR set tcl_platform(wordSize)
4
\fI%\fR scan 20000000000000000000 %d
2147483647
\fI%\fR scan 20000000000000000000 %ld
9223372036854775807
\fI%\fR scan 20000000000000000000 %lld
20000000000000000000
.CE

Changes to doc/seek.n.

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
8
9
10
11
12
13
14

15
16
17
18






19






























20






























21



22
23
24
25
26







-
+



-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
+




.TH seek n 8.1 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
seek \- Change the access position for an open channel
.SH SYNOPSIS
\fBseek \fIchannelId offset \fR?\fIorigin\fR?
\fBseek \fIchannel offset \fR?\fIorigin\fR?
.BE
.SH DESCRIPTION
.PP
Changes the current access position for \fIchannelId\fR.
.PP
\fIChannelId\fR must be an identifier for an open channel such as a
Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR),
the return value from an invocation of \fBopen\fR or \fBsocket\fR, or
the result of a channel creation command provided by a Tcl extension.
The \fBseek\fR command has been superceded by the \fBchan seek\fR
.PP
The \fIoffset\fR and \fIorigin\fR
arguments specify the position at which the next read or write will occur
for \fIchannelId\fR. \fIOffset\fR must be an integer (which may be
negative) and \fIorigin\fR must be one of the following:
.TP 10
\fBstart\fR
.
The new access position will be \fIoffset\fR bytes from the start
of the underlying file or device.
.TP 10
\fBcurrent\fR
.
The new access position will be \fIoffset\fR bytes from the current
access position; a negative \fIoffset\fR moves the access position
backwards in the underlying file or device.
.TP 10
\fBend\fR
.
The new access position will be \fIoffset\fR bytes from the end of
the file or device.  A negative \fIoffset\fR places the access position
before the end of file, and a positive \fIoffset\fR places the access
position after the end of file.
.PP
The \fIorigin\fR argument defaults to \fBstart\fR.
.PP
The command flushes all buffered output for the channel before the command
returns, even if the channel is in non-blocking mode.
It also discards any buffered and unread input.
This command returns an empty string.
command which supports the same syntax and options.
An error occurs if this command is applied to channels whose underlying
file or device does not support seeking.
.PP
Note that \fIoffset\fR values are byte offsets, not character
offsets.  Both \fBseek\fR and \fBtell\fR operate in terms of bytes,
not characters, unlike \fBread\fR.
.SH EXAMPLES
.PP
Read a file twice:
.PP
.CS
set f [open file.txt]
set data1 [read $f]
\fBseek\fR $f 0
set data2 [read $f]
close $f
# $data1 eq $data2 if the file wasn't updated
.CE
.PP
Read the last 10 bytes from a file:
.PP
.CS
set f [open file.data]
# This is guaranteed to work with binary data but
# may fail with other encodings...
fconfigure $f -translation binary
\fBseek\fR $f -10 end
set data [read $f 10]
close $f
.CE
.SH "SEE ALSO"
file(n), open(n), close(n), gets(n), tell(n), Tcl_StandardChannels(3)
.SH KEYWORDS
access position, file, seek
chan(n)
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/self.n.

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
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







-
+











+
















+










+
















+









+






+





+












+




+







.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
self \- method call internal introspection
.SH SYNOPSIS
.nf
package require TclOO
package require tcl::oo

\fBself\fR ?\fIsubcommand\fR?
.fi
.BE
.SH DESCRIPTION
The \fBself\fR command, which should only be used from within the context of a
call to a method (i.e. inside a method, constructor or destructor body) is
used to allow the method to discover information about how it was called. It
takes an argument, \fIsubcommand\fR, that tells it what sort of information is
actually desired; if omitted the result will be the same as if \fBself
object\fR was invoked. The supported subcommands are:
.\" METHOD: call
.TP
\fBself call\fR
.
This returns a two-element list describing the method implementations used to
implement the current call chain. The first element is the same as would be
reported by \fBinfo object\fR \fBcall\fR for the current method (except that this
also reports useful values from within constructors and destructors, whose
names are reported as \fB<constructor>\fR and \fB<destructor>\fR
respectively,
.VS TIP500
and for private methods, which are described as being \fBprivate\fR instead of
being a \fBmethod\fR),
.VE TIP500
and the second element is an index into the first element's
list that indicates which actual implementation is currently executing (the
first implementation to execute is always at index 0).
.\" METHOD: caller
.TP
\fBself caller\fR
.
When the method was invoked from inside another object method, this subcommand
returns a three element list describing the containing object and method. The
first element describes the declaring object or class of the method, the
second element is the name of the object on which the containing method was
invoked, and the third element is the name of the method (with the strings
\fB<constructor>\fR and \fB<destructor>\fR indicating constructors and
destructors respectively).
.\" METHOD: class
.TP
\fBself class\fR
.
This returns the name of the class that the current method was defined within.
Note that this will change as the chain of method implementations is traversed
with \fBnext\fR, and that if the method was defined on an object then this
will fail.
.RS
.PP
If you want the class of the current object, you need to use this other
construct:
.PP
.CS
info object class [\fBself object\fR]
.CE
.RE
.\" METHOD: filter
.TP
\fBself filter\fR
.
When invoked inside a filter, this subcommand returns a three element list
describing the filter. The first element gives the name of the object or class
that declared the filter (note that this may be different from the object or
class that provided the implementation of the filter), the second element is
either \fBobject\fR or \fBclass\fR depending on whether the declaring entity
was an object or class, and the third element is the name of the filter.
.\" METHOD: method
.TP
\fBself method\fR
.
This returns the name of the current method (with the strings
\fB<constructor>\fR and \fB<destructor>\fR indicating constructors and
destructors respectively).
.\" METHOD: namespace
.TP
\fBself namespace\fR
.
This returns the name of the unique namespace of the object that the method
was invoked upon.
.\" METHOD: next
.TP
\fBself next\fR
.
When invoked from a method that is not at the end of a call chain (i.e. where
the \fBnext\fR command will invoke an actual method implementation), this
subcommand returns a two element list describing the next element in the
method call chain; the first element is the name of the class or object that
declares the next part of the call chain, and the second element is the name
of the method (with the strings \fB<constructor>\fR and \fB<destructor>\fR
indicating constructors and destructors respectively). If invoked from a
method that is at the end of a call chain, this subcommand returns the empty
string.
.\" METHOD: object
.TP
\fBself object\fR
.
This returns the name of the object that the method was invoked upon.
.\" METHOD: target
.TP
\fBself target\fR
.
When invoked inside a filter implementation, this subcommand returns a two
element list describing the method being filtered. The first element will be
the name of the declarer of the method, and the second element will be the
actual name of the method.

Changes to doc/set.n.

66
67
68
69
70
71
72
73


74
75
76
77
78
79
66
67
68
69
70
71
72

73
74
75
76
77
78
79
80







-
+
+






.CS
\fBset\fR in0 "small random"
\fBset\fR in1 "large random"
\fBset\fR vbl in[expr {rand() >= 0.5}]
\fBset\fR out [\fBset\fR $vbl]
.CE
.SH "SEE ALSO"
expr(n), global(n), namespace(n), proc(n), trace(n), unset(n), upvar(n), variable(n)
expr(n), global(n), namespace(n), proc(n), trace(n), unset(n), upvar(n),
variable(n)
.SH KEYWORDS
read, write, variable
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/singleton.n.

8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
oo::singleton \- a class that does only allows one instance of itself
.SH SYNOPSIS
.nf
package require TclOO
package require tcl::oo

\fBoo::singleton\fI method \fR?\fIarg ...\fR?
.fi
.SH "CLASS HIERARCHY"
.nf
\fBoo::object\fR
   \(-> \fBoo::class\fR
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
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







+
















-
+
+







means that it is effectively the same as the constructor of the
\fBoo::class\fR class.
.SS DESTRUCTOR
The \fBoo::singleton\fR class does not define an explicit destructor;
destroying an instance of it is just like destroying an ordinary class (and
will destroy the singleton object).
.SS "EXPORTED METHODS"
.\" METHOD: new
.TP
\fIcls \fBnew \fR?\fIarg ...\fR?
.
This returns the current instance of the singleton class, if one exists, and
creates a new instance only if there is no existing instance. The additional
arguments, \fIarg ...\fR, are only used if a new instance is actually
manufactured; that construction is via the \fBoo::class\fR class's \fBnew\fR
method.
.RS
.PP
This is an override of the behaviour of a superclass's method with an
identical call signature to the superclass's implementation.
.RE
.SS "NON-EXPORTED METHODS"
The \fBoo::singleton\fR class explicitly states that \fBcreate\fR and
\fBcreateWithNamespace\fR are unexported; callers should not assume that they
have control over either the name or the namespace name of the singleton instance.
have control over either the name or the namespace name of the singleton
instance.
.SH EXAMPLE
.PP
This example demonstrates that there is only one instance even though the
\fBnew\fR method is called three times.
.PP
.CS
\fBoo::singleton\fR create Highlander {

Changes to doc/socket.n.

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
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


-
+











-
+

-

+







'\"
'\" Copyright (c) 1996 Sun Microsystems, Inc.
'\" Copyright (c) 1998-1999 by Scriptics Corporation.
'\" Copyright (c) 1998-1999 Scriptics Corporation.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH socket n 8.6 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
socket \- Open a TCP network connection
.SH SYNOPSIS
.sp
.nf
\fBsocket \fR?\fIoptions\fR? \fIhost port\fR
.sp
\fBsocket\fR \fB\-server \fIcommand\fR ?\fIoptions\fR? \fIport\fR
.fi
.BE
.SH DESCRIPTION
.PP
This command opens a network socket and returns a channel identifier
that may be used in future invocations of commands like \fBread\fR,
\fBputs\fR and \fBflush\fR.  At present only the TCP network protocol
is supported over IPv4 and IPv6; future releases may include support
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
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







+








+








+







system) and \fIhost\fR
is either a domain-style name such as \fBwww.tcl.tk\fR or
a numerical IPv4 or IPv6 address such as \fB127.0.0.1\fR or \fB2001:DB8::1\fR.
Use \fIlocalhost\fR to refer to the host on which the command is invoked.
.PP
The following options may also be present before \fIhost\fR
to specify additional information about the connection:
.\" OPTION: -myaddr
.TP
\fB\-myaddr\fI addr\fR
.
\fIAddr\fR gives the domain-style name or numerical IP address of
the client-side network interface to use for the connection.
This option may be useful if the client machine has multiple network
interfaces.  If the option is omitted then the client-side interface
will be chosen by the system software.
.\" OPTION: -myport
.TP
\fB\-myport\fI port\fR
.
\fIPort\fR specifies an integer port number (or service name, where
supported and understood by the host operating system) to use for the
client's
side of the connection.  If this option is omitted, the client's
port number will be chosen at random by the system software.
.\" OPTION: -async
.TP
\fB\-async\fR
.
This option will cause the client socket to be connected
asynchronously. This means that the socket will be created immediately
but may not yet be connected to the server, when the call to
\fBsocket\fR returns.
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
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







+
-
+
+

-
+
+



















+











+





+







is in progress, because it may have to do several connection attempts
in the background. Running the event loop also allows you to set up a
writable channel event on the socket to get notified when the
asynchronous connection has succeeded or failed. See the \fBvwait\fR
and the \fBchan\fR commands for more details on the event loop and
channel events.
.PP
The \fBchan configure\fR option \fB\-connecting\fR may be used to check
The \fBchan configure\fR option \fB-connecting\fR may be used to check if the connect is still running. To verify a successful connect, the option \fB-error\fR may be checked when \fB-connecting\fR returned 0.
if the connect is still running. To verify a successful connect, the
option \fB\-error\fR may be checked when \fB\-connecting\fR returned 0.
.PP
Operation without the event queue requires at the moment calls to \fBchan configure\fR to advance the internal state machine.
Operation without the event queue requires at the moment calls to
\fBchan configure\fR to advance the internal state machine.
.RE
.SH "SERVER SOCKETS"
.PP
If the \fB\-server\fR option is specified then the new socket will be
a server that listens on the given \fIport\fR (either an integer or a
service name, where supported and understood by the host operating
system; if \fIport\fR is zero, the operating system will allocate a
free port to the server socket which may be discovered by using
\fBchan configure\fR to read the \fB\-sockname\fR option). If the host
supports both, IPv4 and IPv6, the socket will listen on both address
families. Tcl will automatically accept connections to the given port.
For each connection Tcl will create a new channel that may be used to
communicate with the client.  Tcl then invokes \fIcommand\fR (properly
a command prefix list, see the \fBEXAMPLES\fR below) with three
additional arguments: the name of the new channel, the address, in
network address notation, of the client's host, and the client's port
number.
.PP
The following additional option may also be specified before \fIport\fR:
.\" OPTION: -myaddr
.TP
\fB\-myaddr\fI addr\fR
.
\fIAddr\fR gives the domain-style name or numerical IP address of the
server-side network interface to use for the connection.  This option
may be useful if the server machine has multiple network interfaces.
If the option is omitted then the server socket is bound to the
wildcard address so that it can accept connections from any
interface. If \fIaddr\fR is a domain name that resolves to multiple IP
addresses that are available on the local machine, the socket will
listen on all of them.
.\" OPTION: -reuseaddr
.TP
\fB\-reuseaddr\fI boolean\fR
.
Tells the kernel whether to reuse the local address if there is no socket
actively listening on it. This is the default on Windows.
.\" OPTION: -reuseport
.TP
\fB\-reuseport\fI boolean\fR
.
Tells the kernel whether to allow the binding of multiple sockets to the same
address and port.
.PP
Server channels cannot be used for input or output; their sole use is to
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
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







-
+
+
+












+

















+








+



-
+
+
+
+
+
+
+
+
+
+
+
+
+
+







an unused port for use as a server socket.  The port number actually
allocated may be retrieved from the created server socket using the
\fBchan configure\fR command to retrieve the \fB\-sockname\fR option as
described below.
.SH "CONFIGURATION OPTIONS"
.PP
The \fBchan configure\fR command can be used to query several readonly
configuration options for socket channels:
configuration options for socket channels or in some cases to set
alternative properties on socket channels:
.\" OPTION: -error
.TP
\fB\-error\fR
.
This option gets the current error status of the given socket.  This
is useful when you need to determine if an asynchronous connect
operation succeeded.  If there was an error, the error message is
returned.  If there was no error, an empty string is returned.
.RS
.PP
Note that the error status is reset by the read operation; this mimics
the underlying getsockopt(SO_ERROR) call.
.RE
.\" OPTION: -sockname
.TP
\fB\-sockname\fR
.
For client sockets (including the channels that get created when a
client connects to a server socket) this option returns a list of
three elements, the address, the host name and the port number for the
socket. If the host name cannot be computed, the second element is
identical to the address, the first element of the list.
.RS
.PP
For server sockets this option returns a list of a multiple of three
elements each group of which have the same meaning as described
above. The list contains more than one group when the server socket
was created without \fB\-myaddr\fR or with the argument to
\fB\-myaddr\fR being a domain name that resolves multiple IP addresses
that are local to the invoking host.
.RE
.\" OPTION: -peername
.TP
\fB\-peername\fR
.
This option is not supported by server sockets. For client and accepted
sockets, this option returns a list of three elements; these are the
address, the host name and the port to which the peer socket is connected
or bound. If the host name cannot be computed, the second element of the
list is identical to the address, its first element.
.\" OPTION: -connecting
.TP
\fB\-connecting\fR
.
This option is not supported by server sockets. For client sockets, this option returns 1 if an asyncroneous connect is still in progress, 0 otherwise.
This option is not supported by server sockets. For client sockets, this
option returns 1 if an asynchronous connect is still in progress, 0 otherwise.
.\" OPTION: -keepalive
.TP
\fB\-keepalive\fR
.
This option sets or queries the TCP keepalive option on the socket as 1 if
keepalive is turned on, 0 otherwise.
.\" OPTION: -nodelay
.TP
\fB\-nodelay\fR
.
This option sets or queries the TCP nodelay option on the socket as 1 if
nodelay is turned on, 0 otherwise.
.PP
.SH "EXAMPLES"
.PP
Here is a very simple time server:
.PP
.CS
proc Server {startTime channel clientaddr clientport} {
230
231
232
233
234
235
236
237
238
239
240
241
242


243
244
245
257
258
259
260
261
262
263


264
265
266

267
268
269
270
271







-
-



-
+
+



set sockChan [\fBsocket\fR $server 9900]
gets $sockChan line1
gets $sockChan line2
close $sockChan
puts "The time on $server is $line1"
puts "That is [lindex $line2 0]s since the server started"
.CE
.SH "HISTORY"
Support for IPv6 was added in Tcl 8.6.
.SH "SEE ALSO"
chan(n), flush(n), open(n), read(n)
.SH KEYWORDS
asynchronous I/O, bind, channel, connection, domain name, host, network address, socket, tcp
asynchronous I/O, bind, channel, connection, domain name, host,
network address, socket, tcp
'\" Local Variables:
'\" mode: nroff
'\" End:

Changes to doc/source.n.

33
34
35
36
37
38
39
40

41
42
43
44
45
46


47
48
49
50
51
52
53
33
34
35
36
37
38
39

40


41
42
43

44
45
46
47
48
49
50
51
52







-
+
-
-



-
+
+







(^Z) for all platforms.
The source command will read files up to this character.  This
restriction does not exist for the \fBread\fR or \fBgets\fR commands,
allowing for files containing code and data segments (scripted documents).
If you require a
.QW ^Z
in code for string comparison, you can use
.QW \e032
.QW \ex1A ,
or
.QW \eu001a ,
which will be safely substituted by the Tcl interpreter into
.QW ^Z .
.PP
A leading BOM (Byte order mark) contained in the file is ignored for unicode encodings (utf-8, utf-16, ucs-2).
A leading BOM (Byte order mark) contained in the file is ignored for
unicode encodings (utf-8, utf-16, ucs-2).
.PP
The \fB\-encoding\fR option is used to specify the encoding of
the data stored in \fIfileName\fR.  When the \fB\-encoding\fR option
is omitted, the utf-8 encoding is assumed.
.SH EXAMPLE
.PP
Run the script in the file \fBfoo.tcl\fR and then the script in the

Changes to doc/string.n.

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
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







+














+










+









+







.SH SYNOPSIS
\fBstring \fIoption arg \fR?\fIarg ...\fR?
.BE
.SH DESCRIPTION
.PP
Performs one of several string operations, depending on \fIoption\fR.
The legal \fIoption\fRs (which may be abbreviated) are:
.\" METHOD: cat
.TP
\fBstring cat\fR ?\fIstring1\fR? ?\fIstring2...\fR?
.
Concatenate the given \fIstring\fRs just like placing them directly
next to each other and return the resulting compound string.  If no
\fIstring\fRs are present, the result is an empty string.
.RS
.PP
This primitive is occasionally handier than juxtaposition of strings
when mixed quoting is wanted, or when the aim is to return the result
of a concatenation without resorting to \fBreturn\fR \fB\-level 0\fR,
and is more efficient than building a list of arguments and using
\fBjoin\fR with an empty join string.
.RE
.\" METHOD: compare
.TP
\fBstring compare\fR ?\fB\-nocase\fR? ?\fB\-length\fI length\fR? \fIstring1 string2\fR
.
Perform a character-by-character comparison of strings \fIstring1\fR
and \fIstring2\fR.  Returns \-1, 0, or 1, depending on whether
\fIstring1\fR is lexicographically less than, equal to, or greater
than \fIstring2\fR.  If \fB\-length\fR is specified, then only the
first \fIlength\fR characters are used in the comparison.  If
\fB\-length\fR is negative, it is ignored.  If \fB\-nocase\fR is
specified, then the strings are compared in a case-insensitive manner.
.\" METHOD: equal
.TP
\fBstring equal\fR ?\fB\-nocase\fR? ?\fB\-length\fI length\fR? \fIstring1 string2\fR
.
Perform a character-by-character comparison of strings \fIstring1\fR
and \fIstring2\fR.  Returns 1 if \fIstring1\fR and \fIstring2\fR are
identical, or 0 when not.  If \fB\-length\fR is specified, then only
the first \fIlength\fR characters are used in the comparison.  If
\fB\-length\fR is negative, it is ignored.  If \fB\-nocase\fR is
specified, then the strings are compared in a case-insensitive manner.
.\" METHOD: first
.TP
\fBstring first \fIneedleString haystackString\fR ?\fIstartIndex\fR?
.
Search \fIhaystackString\fR for a sequence of characters that exactly match
the characters in \fIneedleString\fR.  If found, return the index of the
first character in the first such match within \fIhaystackString\fR.  If not
found, return \-1.  If \fIstartIndex\fR is specified (in any of the
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
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







+












+


















+







.PP
.CS
\fBstring first a 0123456789abcdef 11\fR
.CE
.PP
will return \fB\-1\fR.
.RE
.\" METHOD: index
.TP
\fBstring index \fIstring charIndex\fR
.
Returns the \fIcharIndex\fR'th character of the \fIstring\fR argument.
A \fIcharIndex\fR of 0 corresponds to the first character of the
string.  \fIcharIndex\fR may be specified as described in the
\fBSTRING INDICES\fR section.
.RS
.PP
If \fIcharIndex\fR is less than 0 or greater than or equal to the
length of the string then this command returns an empty string.
.RE
.\" METHOD: insert
.TP
\fBstring insert \fIstring index insertString\fR
.VS "TIP 504"
Returns a copy of \fIstring\fR with \fIinsertString\fR inserted at the
\fIindex\fR'th character.  The \fIindex\fR may be specified as described in the
\fBSTRING INDICES\fR section.
.RS
.PP
If \fIindex\fR is start-relative, the first character inserted in the returned
string will be at the specified index.  If \fIindex\fR is end-relative, the last
character inserted in the returned string will be at the specified index.
.PP
If \fIindex\fR is at or before the start of \fIstring\fR (e.g., \fIindex\fR is
\fB0\fR), \fIinsertString\fR is prepended to \fIstring\fR.  If \fIindex\fR is at
or after the end of \fIstring\fR (e.g., \fIindex\fR is \fBend\fR),
\fIinsertString\fR is appended to \fIstring\fR.
.RE
.VE "TIP 504"
.\" METHOD: is
.TP
\fBstring is \fIclass\fR ?\fB\-strict\fR? ?\fB\-failindex \fIvarname\fR? \fIstring\fR
.
Returns 1 if \fIstring\fR is a valid member of the specified character
class, otherwise returns 0.  If \fB\-strict\fR is specified, then an
empty string returns 0, otherwise an empty string will return 1 on
any class.  If \fB\-failindex\fR is specified, then if the function
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
146
147
148
149
150
151
152

153


154
155
156
157
158
159



160
161
162
163
164
165
166
167
168
169







-
+
-
-






-
-
-
+
+
+







.IP \fBdigit\fR 12
Any Unicode digit character.  Note that this includes characters
outside of the [0\-9] range.
.IP \fBdouble\fR 12
Any of the forms allowed to \fBTcl_GetDoubleFromObj\fR.
.IP \fBentier\fR 12
.
Any of the valid string formats for an integer value of arbitrary size
Synonym for \fBinteger\fR.
in Tcl, with optional surrounding whitespace. The formats accepted are
exactly those accepted by the C routine \fBTcl_GetBignumFromObj\fR.
.IP \fBfalse\fR 12
Any of the forms allowed to \fBTcl_GetBoolean\fR where the value is
false.
.IP \fBgraph\fR 12
Any Unicode printing character, except space.
.IP \fBinteger\fR 12
Any of the valid string formats for a 32-bit integer value in Tcl,
with optional surrounding whitespace.  In case of overflow in
the value, 0 is returned and the \fIvarname\fR will contain \-1.
Any of the valid string formats for an integer value of arbitrary size
in Tcl, with optional surrounding whitespace. The formats accepted are
exactly those accepted by the C routine \fBTcl_GetBignumFromObj\fR.
.IP \fBlist\fR 12
Any proper list structure, with optional surrounding whitespace. In
case of improper list structure, 0 is returned and the \fIvarname\fR
will contain the index of the
.QW element
where the list parsing fails, or \-1 if this cannot be determined.
.IP \fBlower\fR 12
186
187
188
189
190
191
192

193
194
195
196
197
198
199
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205







+







.IP \fBxdigit\fR 12
Any hexadecimal digit character ([0\-9A\-Fa\-f]).
.PP
In the case of \fBboolean\fR, \fBtrue\fR and \fBfalse\fR, if the
function will return 0, then the \fIvarname\fR will always be set to
0, due to the varied nature of a valid boolean value.
.RE
.\" METHOD: last
.TP
\fBstring last \fIneedleString haystackString\fR ?\fIlastIndex\fR?
.
Search \fIhaystackString\fR for a sequence of characters that exactly match
the characters in \fIneedleString\fR.  If found, return the index of the
first character in the last such match within \fIhaystackString\fR.  If there
is no match, then return \-1.  If \fIlastIndex\fR is specified (in any
210
211
212
213
214
215
216

217
218
219
220
221
222
223
224

225
226
227
228
229
230
231
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239







+








+







.PP
.CS
\fBstring last a 0a23456789abcdef 9\fR
.CE
.PP
will return \fB1\fR.
.RE
.\" METHOD: length
.TP
\fBstring length \fIstring\fR
.
Returns a decimal string giving the number of characters in
\fIstring\fR.  Note that this is not necessarily the same as the
number of bytes used to store the string.  If the value is a
byte array value (such as those returned from reading a binary encoded
channel), then this will return the actual byte length of the value.
.\" METHOD: map
.TP
\fBstring map\fR ?\fB\-nocase\fR? \fImapping string\fR
.
Replaces substrings in \fIstring\fR based on the key-value pairs in
\fImapping\fR.  \fImapping\fR is a list of \fIkey value key value ...\fR
as in the form returned by \fBarray get\fR.  Each instance of a
key in the string will be replaced with its corresponding value.  If
249
250
251
252
253
254
255

256
257

258
259
260
261
262
263
264
257
258
259
260
261
262
263
264
265

266
267
268
269
270
271
272
273







+

-
+







.PP
.CS
\fBstring map {1 0 ab 2 a 3 abc 1} 1abcaababcabababc\fR
.CE
.PP
it will return the string \fB02c322c222c\fR.
.RE
.\" METHOD: match
.TP
\fBstring match\fR ?\fB\-nocase\fR? \fIpattern\fR \fIstring\fR
\fBstring match\fR ?\fB\-nocase\fR? \fIpattern string\fR
.
See if \fIpattern\fR matches \fIstring\fR; return 1 if it does, 0 if
it does not.  If \fB\-nocase\fR is specified, then the pattern attempts
to match against the string in a case insensitive manner.  For the two
strings to match, their contents must be identical except that the
following special sequences may appear in \fIpattern\fR:
.RS
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

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
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
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







+














+






+












-
-
-
+
+
+
+
+





+









+











+









+







+







+












-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-









+







with \fB\-nocase\fR this is considered like {[A\-Za\-z]} (and
probably what was meant in the first place).
.IP \fB\e\fIx\fR 10
Matches the single character \fIx\fR.  This provides a way of avoiding
the special interpretation of the characters \fB*?[]\e\fR in
\fIpattern\fR.
.RE
.\" METHOD: range
.TP
\fBstring range \fIstring first last\fR
.
Returns a range of consecutive characters from \fIstring\fR, starting
with the character whose index is \fIfirst\fR and ending with the
character whose index is \fIlast\fR (using the forms described in
\fBSTRING INDICES\fR). An index of \fB0\fR refers to the first
character of the string; an index of \fBend\fR refers to last
character of the string.  \fIfirst\fR and \fIlast\fR may be specified
as for the \fBindex\fR method.  If \fIfirst\fR is less than zero then
it is treated as if it were zero, and if \fIlast\fR is greater than or
equal to the length of the string then it is treated as if it were
\fBend\fR.  If \fIfirst\fR is greater than \fIlast\fR then an empty
string is returned.
.\" METHOD: repeat
.TP
\fBstring repeat \fIstring count\fR
.
Returns a string consisting of \fIstring\fR concatenated with itself
\fIcount\fR times. If \fIcount\fR is 0, the empty string will be
returned.
.\" METHOD: replace
.TP
\fBstring replace \fIstring first last\fR ?\fInewstring\fR?
.
Removes a range of consecutive characters from \fIstring\fR, starting
with the character whose index is \fIfirst\fR and ending with the
character whose index is \fIlast\fR (using the forms described in
\fBSTRING INDICES\fR).  An index of 0 refers to the
first character of the string.  \fIFirst\fR and \fIlast\fR may be
specified as for the \fBindex\fR method.  If \fInewstring\fR is
specified, then it is placed in the removed character range.  If
\fIfirst\fR is less than zero then it is treated as if it were zero,
and if \fIlast\fR is greater than or equal to the length of the string
then it is treated as if it were \fBend\fR.  If \fIfirst\fR is greater
than \fIlast\fR or the length of the initial string, or \fIlast\fR is
less than 0, then the initial string is returned untouched.
then it is treated as if it were \fBend\fR.  The initial string is
returned untouched, if \fIfirst\fR is greater than \fIlast\fR, or if
\fIfirst\fR is equal to or greater than the length of the initial string,
or \fIlast\fR is less than 0.
.\" METHOD: reverse
.TP
\fBstring reverse \fIstring\fR
.
Returns a string that is the same length as \fIstring\fR but with its
characters in the reverse order.
.\" METHOD: tolower
.TP
\fBstring tolower \fIstring\fR ?\fIfirst\fR? ?\fIlast\fR?
.
Returns a value equal to \fIstring\fR except that all upper (or title)
case letters have been converted to lower case.  If \fIfirst\fR is
specified, it refers to the first char index in the string to start
modifying.  If \fIlast\fR is specified, it refers to the char index in
the string to stop at (inclusive).  \fIfirst\fR and \fIlast\fR may be
specified using the forms described in \fBSTRING INDICES\fR.
.\" METHOD: totitle
.TP
\fBstring totitle \fIstring\fR ?\fIfirst\fR? ?\fIlast\fR?
.
Returns a value equal to \fIstring\fR except that the first character
in \fIstring\fR is converted to its Unicode title case variant (or
upper case if there is no title case variant) and the rest of the
string is converted to lower case.  If \fIfirst\fR is specified, it
refers to the first char index in the string to start modifying.  If
\fIlast\fR is specified, it refers to the char index in the string to
stop at (inclusive).  \fIfirst\fR and \fIlast\fR may be specified
using the forms described in \fBSTRING INDICES\fR.
.\" METHOD: toupper
.TP
\fBstring toupper \fIstring\fR ?\fIfirst\fR? ?\fIlast\fR?
.
Returns a value equal to \fIstring\fR except that all lower (or title)
case letters have been converted to upper case.  If \fIfirst\fR is
specified, it refers to the first char index in the string to start
modifying.  If \fIlast\fR is specified, it refers to the char index in
the string to stop at (inclusive).  \fIfirst\fR and \fIlast\fR may be
specified using the forms described in \fBSTRING INDICES\fR.
.\" METHOD: trim
.TP
\fBstring trim \fIstring\fR ?\fIchars\fR?
.
Returns a value equal to \fIstring\fR except that any leading or
trailing characters present in the string given by \fIchars\fR are removed.  If
\fIchars\fR is not specified then white space is removed (any character
for which \fBstring is space\fR returns 1, and "\e0").
.\" METHOD: trimleft
.TP
\fBstring trimleft \fIstring\fR ?\fIchars\fR?
.
Returns a value equal to \fIstring\fR except that any leading
characters present in the string given by \fIchars\fR are removed.  If
\fIchars\fR is not specified then white space is removed (any character
for which \fBstring is space\fR returns 1, and "\e0").
.\" METHOD: trimright
.TP
\fBstring trimright \fIstring\fR ?\fIchars\fR?
.
Returns a value equal to \fIstring\fR except that any trailing
characters present in the string given by \fIchars\fR are removed.  If
\fIchars\fR is not specified then white space is removed (any character
for which \fBstring is space\fR returns 1, and "\e0").
.SS "OBSOLETE SUBCOMMANDS"
.PP
These subcommands are currently supported, but are likely to go away in a
future release as their functionality is either virtually never used or highly
misleading.
.TP
\fBstring bytelength \fIstring\fR
.
Returns a decimal string giving the number of bytes used to represent
\fIstring\fR in memory when encoded as Tcl's internal modified UTF\-8;
Tcl may use other encodings for \fIstring\fR as well, and does not
guarantee to only use a single encoding for a particular \fIstring\fR.
Because UTF\-8 uses a variable number of bytes to represent Unicode
characters, the byte length will not be the same as the character
length in general.  The cases where a script cares about the byte
length are rare.
.\" METHOD: wordend
.RS
.PP
In almost all cases, you should use the
\fBstring length\fR operation (including determining the length of a
Tcl byte array value).  Refer to the \fBTcl_NumUtfChars\fR manual
entry for more details on the UTF\-8 representation.
.PP
Formally, the \fBstring bytelength\fR operation returns the content of
the \fIlength\fR field of the \fBTcl_Obj\fR structure, after calling
\fBTcl_GetString\fR to ensure that the \fIbytes\fR field is populated.
This is highly unlikely to be useful to Tcl scripts, as Tcl's internal
encoding is not strict UTF\-8, but rather a modified CESU\-8 with a
denormalized NUL (identical to that used in a number of places by
Java's serialization mechanism) to enable basic processing with
non-Unicode-aware C functions.  As this representation should only
ever be used by Tcl's implementation, the number of bytes used to
store the representation is of very low value (except to C extension
code, which has direct access for the purpose of memory management,
etc.)
.PP
\fICompatibility note:\fR it is likely that this subcommand will be
withdrawn in a future version of Tcl. It is better to use the
\fBencoding convertto\fR command to convert a string to a known
encoding and then apply \fBstring length\fR to that.
.PP
.CS
\fBstring length\fR [encoding convertto utf-8 $theString]
.CE
.RE
.TP
\fBstring wordend \fIstring charIndex\fR
.
Returns the index of the character just after the last one in the word
containing character \fIcharIndex\fR of \fIstring\fR.  \fIcharIndex\fR
may be specified using the forms in \fBSTRING INDICES\fR.  A word is
considered to be any contiguous range of alphanumeric (Unicode letters
or decimal digits) or underscore (Unicode connector punctuation)
characters, or any single character other than these.
.\" METHOD: wordstart
.TP
\fBstring wordstart \fIstring charIndex\fR
.
Returns the index of the first character in the word containing character
\fIcharIndex\fR of \fIstring\fR.  \fIcharIndex\fR may be specified using the
forms in \fBSTRING INDICES\fR.  A word is considered to be any contiguous
range of alphanumeric (Unicode letters or decimal digits) or underscore
495
496
497
498
499
500
501
502

503
504
505
506
507
508
509


510
511
512
477
478
479
480
481
482
483

484
485
486
487
488
489


490
491
492
493
494







-
+





-
-
+
+



prefix of the string \fBfoobar\fR.
.PP
.CS
set length [\fBstring length\fR $string]
if {$length == 0} {
    set isPrefix 0
} else {
    set isPrefix [\fBstring equal\fR \-length $length $string "foobar"]
    set isPrefix [\fBstring equal\fR -length $length $string "foobar"]
}
.CE
.SH "SEE ALSO"
expr(n), list(n)
.SH KEYWORDS
case conversion, compare, index, integer value, match, pattern, string, word, equal,
ctype, character, reverse
case conversion, compare, index, integer value, match, pattern, string,
word, equal, ctype, character, reverse
.\" Local Variables:
.\" mode: nroff
.\" End:

Changes to doc/subst.n.

154
155
156
157
158
159
160
161


162
163
164
154
155
156
157
158
159
160

161
162
163
164
165







-
+
+



also returns
.QW \fBabc,foo,def\fR ,
not
.QW \fBabc,3,def\fR .
.SH "SEE ALSO"
Tcl(n), eval(n), break(n), continue(n)
.SH KEYWORDS
backslash substitution, command substitution, quoting, substitution, variable substitution
backslash substitution, command substitution, quoting, substitution,
variable substitution
.\" Local Variables:
.\" mode: nroff
.\" End:

Changes to doc/switch.n.

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
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







+





+





+






+




+

-
+











+

-
+















+







.PP
If the initial arguments to \fBswitch\fR start with \fB\-\fR then
they are treated as options
unless there are exactly two arguments to \fBswitch\fR (in which case the
first must the \fIstring\fR and the second must be the
\fIpattern\fR/\fIbody\fR list).
The following options are currently supported:
.\" OPTION: -exact
.TP 10
\fB\-exact\fR
.
Use exact matching when comparing \fIstring\fR to a pattern.  This
is the default.
.\" OPTION: -glob
.TP 10
\fB\-glob\fR
.
When matching \fIstring\fR to the patterns, use glob-style matching
(i.e. the same as implemented by the \fBstring match\fR command).
.\" OPTION: -regexp
.TP 10
\fB\-regexp\fR
.
When matching \fIstring\fR to the patterns, use regular
expression matching
(as described in the \fBre_syntax\fR reference page).
.\" OPTION: -nocase
.TP 10
\fB\-nocase\fR
.
Causes comparisons to be handled in a case-insensitive manner.
.\" OPTION: -matchvar
.TP 10
\fB\-matchvar\fR \fIvarName\fR
\fB\-matchvar\fI varName\fR
.
This option (only legal when \fB\-regexp\fR is also specified)
specifies the name of a variable into which the list of matches
found by the regular expression engine will be written.  The first
element of the list written will be the overall substring of the input
string (i.e. the \fIstring\fR argument to \fBswitch\fR) matched, the
second element of the list will be the substring matched by the first
capturing parenthesis in the regular expression that matched, and so
on.  When a \fBdefault\fR branch is taken, the variable will have the
empty list written to it.  This option may be specified at the same
time as the \fB\-indexvar\fR option.
.\" OPTION: -indexvar
.TP 10
\fB\-indexvar\fR \fIvarName\fR
\fB\-indexvar\fI varName\fR
.
This option (only legal when \fB\-regexp\fR is also specified)
specifies the name of a variable into which the list of indices
referring to matching substrings
found by the regular expression engine will be written.  The first
element of the list written will be a two-element list specifying the
index of the start and index of the first character after the end of
the overall substring of the input
string (i.e. the \fIstring\fR argument to \fBswitch\fR) matched, in a
similar way to the \fB\-indices\fR option to the \fBregexp\fR can
obtain.  Similarly, the second element of the list refers to the first
capturing parenthesis in the regular expression that matched, and so
on.  When a \fBdefault\fR branch is taken, the variable will have the
empty list written to it.  This option may be specified at the same
time as the \fB\-matchvar\fR option.
.\" OPTION: --
.TP 10
\fB\-\|\-\fR
.
Marks the end of options.  The argument following this one will
be treated as \fIstring\fR even if it starts with a \fB\-\fR.
This is not required when the matching patterns and bodies are grouped
together in a single argument.
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
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







-
+







-
-
+
+











-
+

















-
+







.SH "EXAMPLES"
.PP
The \fBswitch\fR command can match against variables and not just
literals, as shown here (the result is \fI2\fR):
.PP
.CS
set foo "abc"
\fBswitch\fR abc a \- b {expr {1}} $foo {expr {2}} default {expr {3}}
\fBswitch\fR abc a - b {expr {1}} $foo {expr {2}} default {expr {3}}
.CE
.PP
Using glob matching and the fall-through body is an alternative to
writing regular expressions with alternations, as can be seen here
(this returns \fI1\fR):
.PP
.CS
\fBswitch\fR \-glob aaab {
    a*b     \-
\fBswitch\fR -glob aaab {
    a*b     -
    b       {expr {1}}
    a*      {expr {2}}
    default {expr {3}}
}
.CE
.PP
Whenever nothing matches, the \fBdefault\fR clause (which must be
last) is taken.  This example has a result of \fI3\fR:
.PP
.CS
\fBswitch\fR xyz {
    a \-
    a -
    b {
        # Correct Comment Placement
        expr {1}
    }
    c {
        expr {2}
    }
    default {
        expr {3}
    }
}
.CE
.PP
When matching against regular expressions, information about what
exactly matched is easily obtained using the \fB\-matchvar\fR option:
.PP
.CS
\fBswitch\fR \-regexp \-matchvar foo \-\- $bar {
\fBswitch\fR -regexp -matchvar foo -- $bar {
    a(b*)c {
        puts "Found [string length [lindex $foo 1]] 'b's"
    }
    d(e*)f(g*)h {
        puts "Found [string length [lindex $foo 1]] 'e's and\e
                [string length [lindex $foo 2]] 'g's"
    }

Changes to doc/tclsh.1.

34
35
36
37
38
39
40
41
42

43
44
45
46

47
48
49
50
51
52
53
54
55
56
34
35
36
37
38
39
40


41
42
43
44

45



46
47
48
49
50
51
52







-
-
+



-
+
-
-
-







the text data stored in that script file. Any additional arguments
are made available to the script as variables (see below).
Instead of reading commands from standard input \fBtclsh\fR will
read Tcl commands from the named file;  \fBtclsh\fR will exit
when it reaches the end of the file.
The end of the file may be marked either by the physical end of
the medium, or by the character,
.QW \e032
.PQ \eu001a ", control-Z" .
.PQ \ex1A ", control-Z" .
If this character is present in the file, the \fBtclsh\fR application
will read text up to but not including the character.  An application
that requires this character in the file may safely encode it as
.QW \e032 ,
.QW \ex1A ;
.QW \ex1a ,
or
.QW \eu001a ;
or may generate it by use of commands such as \fBformat\fR or \fBbinary\fR.
There is no automatic evaluation of \fB.tclshrc\fR when the name
of a script file is presented on the \fBtclsh\fR command
line, but the script file can always \fBsource\fR it if desired.
.PP
If you create a Tcl script in a file whose first line is
.PP
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

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







+
+
+
+
+
+
+
+
+
+
+





+





+





+





+







+
+
















-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
+
line to be treated as part of the comment on the second line.
.PP
You should note that it is also common practice to install tclsh with
its version number as part of the name.  This has the advantage of
allowing multiple versions of Tcl to exist on the same system at once,
but also the disadvantage of making it harder to write scripts that
start up uniformly across different versions of Tcl.
.PP
Alternatively, you can use /usr/bin/env to locate tclsh on the path,
like this:
.PP
.CS
\fB#!/usr/bin/env tclsh\fR
.CE
.PP
That has the advantages of being succinct and simple, but the
disadvantage of not being flexible in the face of varying names for
the binary.
.SH "VARIABLES"
.PP
\fBTclsh\fR sets the following global Tcl variables in addition to those
created by the Tcl library itself (such as \fBenv\fR, which maps
environment variables such as \fBPATH\fR into Tcl):
.\" VARIABLE: argc
.TP 15
\fBargc\fR
.
Contains a count of the number of \fIarg\fR arguments (0 if none),
not including the name of the script file.
.\" VARIABLE: argv
.TP 15
\fBargv\fR
.
Contains a Tcl list whose elements are the \fIarg\fR arguments,
in order, or an empty string if there are no \fIarg\fR arguments.
.\" VARIABLE: argv0
.TP 15
\fBargv0\fR
.
Contains \fIfileName\fR if it was specified.
Otherwise, contains the name by which \fBtclsh\fR was invoked.
.\" VARIABLE: tcl_interactive
.TP 15
\fBtcl_interactive\fR
.
Contains 1 if \fBtclsh\fR is running interactively (no
\fIfileName\fR was specified and standard input is a terminal-like
device), 0 otherwise.
.SH PROMPTS
.\" VARIABLE: tcl_prompt1
.\" VARIABLE: tcl_prompt2
.PP
When \fBtclsh\fR is invoked interactively it normally prompts for each
command with
.QW "\fB% \fR" .
You can change the prompt by setting the global
variables \fBtcl_prompt1\fR and \fBtcl_prompt2\fR.  If variable
\fBtcl_prompt1\fR exists then it must consist of a Tcl script
to output a prompt;  instead of outputting a prompt \fBtclsh\fR
will evaluate the script in \fBtcl_prompt1\fR.
The variable \fBtcl_prompt2\fR is used in a similar way when
a newline is typed but the current command is not yet complete;
if \fBtcl_prompt2\fR is not set then no prompt is output for
incomplete commands.
.SH "STANDARD CHANNELS"
.PP
See \fBTcl_StandardChannels\fR for more explanations.
.SH ZIPVFS
.SH "ZIPFS VIRTUAL FILE SYSTEM"
.PP
When a zipfile is concatenated to the end of a \fBtclsh\fR, on
startup the contents of the zip archive will be mounted as the
virtual file system /zvfs. If a top level directory tcl8.6 is
present in the zip archive, it will become the directory loaded
as env(TCL_LIBRARY). If a file named \fBmain.tcl\fR is present
in the top level directory of the zip archive, it will be sourced
instead of the shell's normal command line handing.
When a zipfile is concatenated to the end of a \fBtclsh\fR, on startup
the contents of the zip archive will be mounted under a virtual file
system (VFS). The root of that VFS can be retrieved using the \fBzipfs root\fR
command. The zip archive is mounted under the \fBapp\fR directory within the
VFS. If a file named \fBmain.tcl\fR is present in the top
level directory of the zip archive, it will be sourced instead of
tclsh's normal command line handing. If a top level directory \fBtcl_library\fR is
present in the zip archive, it will become the directory loaded as
env(TCL_LIBRARY). If a file named \fBmain.tcl\fR is present in the top
level directory of the zip archive, it will be sourced instead of the
shell's normal command line handling.
.PP
Only one zipfile can be concatenated to the end of executable image
(tclsh, or wish). However, if multiple zipfiles are
concatenated, only the last one is used.

This filesystem is read-only. Files cannot be added or modified within
this mounted file system.  See zipfs(n) for complete details.

.SH "SEE ALSO"
auto_path(n), encoding(n), env(n), fconfigure(n)
auto_path(n), encoding(n), env(n), fconfigure(n), zipfs(n)
.SH KEYWORDS
application, argument, interpreter, prompt, script file, shell
application, argument, interpreter, prompt, script file, shell, zipfs

Changes to doc/tcltest.n.

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
54
55
56
57
58
59
60

61
62
63
64
65
66
67







-







\fBtcltest::skipDirectories \fR?\fIpatternList\fR?
\fBtcltest::skipFiles \fR?\fIpatternList\fR?
\fBtcltest::temporaryDirectory \fR?\fIdirectory\fR?
\fBtcltest::testsDirectory \fR?\fIdirectory\fR?
\fBtcltest::verbose \fR?\fIlevel\fR?

\fBtcltest::test \fIname description optionList\fR
\fBtcltest::bytestring \fIstring\fR
\fBtcltest::normalizeMsg \fImsg\fR
\fBtcltest::normalizePath \fIpathVar\fR
\fBtcltest::workingDirectory \fR?\fIdir\fR?
.fi
.BE
.SH DESCRIPTION
.PP
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
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







+

-
+













-
+




-
+





+









+

-
+














+

-
+






+

-
+








+

-
+







+

-
+











+




















+









+







\fBtest\fR and the collection of many \fBtest\fR commands into
test suites.
.PP
See \fBCREATING TEST SUITES WITH TCLTEST\fR below for an extended example
of how to use the commands of \fBtcltest\fR to produce test suites
for your Tcl-enabled code.
.SH COMMANDS
.\" COMMAND: test
.TP
\fBtest\fR \fIname description\fR ?\fI\-option value ...\fR?
\fBtest\fI name description\fR ?\fI\-option value ...\fR?
.
Defines and possibly runs a test with the name \fIname\fR and
description \fIdescription\fR.  The name and description of a test
are used in messages reported by \fBtest\fR during the
test, as configured by the options of \fBtcltest\fR.  The
remaining \fIoption value\fR arguments to \fBtest\fR
define the test, including the scripts to run, the conditions
under which to run them, the expected result, and the means
by which the expected and actual results should be compared.
See \fBTESTS\fR below for a complete description of the valid
options and how they define a test.  The \fBtest\fR command
returns an empty string.
.TP
\fBtest\fR \fIname description\fR ?\fIconstraints\fR? \fIbody result\fR
\fBtest\fI name description\fR ?\fIconstraints\fR? \fIbody result\fR
.
This form of \fBtest\fR is provided to support test suites written
for version 1 of the \fBtcltest\fR package, and also a simpler
interface for a common usage.  It is the same as
.QW "\fBtest\fR \fIname description\fB \-constraints \fIconstraints\fB \-body \fIbody\fB \-result \fIresult\fR" .
.QW "\fBtest\fI name description\fB \-constraints \fIconstraints\fB \-body \fIbody\fB \-result \fIresult\fR" .
All other options to \fBtest\fR
take their default values.  When \fIconstraints\fR is omitted, this
form of \fBtest\fR can be distinguished from the first because
all \fIoption\fRs begin with
.QW \- .
.\" COMMAND: loadTestedCommands
.TP
\fBloadTestedCommands\fR
.
Evaluates in the caller's context the script specified by
\fBconfigure \-load\fR or \fBconfigure \-loadfile\fR.
Returns the result of that script evaluation, including any error
raised by the script.  Use this command and the related
configuration options to provide the commands to be tested to
the interpreter running the test suite.
.\" COMMAND: makeFile
.TP
\fBmakeFile\fR \fIcontents name\fR ?\fIdirectory\fR?
\fBmakeFile\fI contents name\fR ?\fIdirectory\fR?
.
Creates a file named \fIname\fR relative to
directory \fIdirectory\fR and write \fIcontents\fR
to that file using the encoding \fBencoding system\fR.
If \fIcontents\fR does not end with a newline, a newline
will be appended so that the file named \fIname\fR
does end with a newline.  Because the system encoding is used,
this command is only suitable for making text files.
The file will be removed by the next evaluation
of \fBcleanupTests\fR, unless it is removed by
\fBremoveFile\fR first.  The default value of
\fIdirectory\fR is the directory \fBconfigure \-tmpdir\fR.
Returns the full path of the file created.  Use this command
to create any text file required by a test with contents as needed.
.\" COMMAND: removeFile
.TP
\fBremoveFile\fR \fIname\fR ?\fIdirectory\fR?
\fBremoveFile\fI name\fR ?\fIdirectory\fR?
.
Forces the file referenced by \fIname\fR to be removed.  This file name
should be relative to \fIdirectory\fR.   The default value of
\fIdirectory\fR is the directory \fBconfigure \-tmpdir\fR.
Returns an empty string.  Use this command to delete files
created by \fBmakeFile\fR.
.\" COMMAND: makeDirectory
.TP
\fBmakeDirectory\fR \fIname\fR ?\fIdirectory\fR?
\fBmakeDirectory\fI name\fR ?\fIdirectory\fR?
.
Creates a directory named \fIname\fR relative to directory \fIdirectory\fR.
The directory will be removed by the next evaluation of \fBcleanupTests\fR,
unless it is removed by \fBremoveDirectory\fR first.
The default value of \fIdirectory\fR is the directory
\fBconfigure \-tmpdir\fR.
Returns the full path of the directory created.  Use this command
to create any directories that are required to exist by a test.
.\" COMMAND: removeDirectory
.TP
\fBremoveDirectory\fR \fIname\fR ?\fIdirectory\fR?
\fBremoveDirectory\fI name\fR ?\fIdirectory\fR?
.
Forces the directory referenced by \fIname\fR to be removed. This
directory should be relative to \fIdirectory\fR.
The default value of \fIdirectory\fR is the directory
\fBconfigure \-tmpdir\fR.
Returns an empty string.  Use this command to delete any directories
created by \fBmakeDirectory\fR.
.\" COMMAND: viewFile
.TP
\fBviewFile\fR \fIfile\fR ?\fIdirectory\fR?
\fBviewFile\fI file\fR ?\fIdirectory\fR?
.
Returns the contents of \fIfile\fR, except for any
final newline, just as \fBread \-nonewline\fR would return.
This file name should be relative to \fIdirectory\fR.
The default value of \fIdirectory\fR is the directory
\fBconfigure \-tmpdir\fR.  Use this command
as a convenient way to turn the contents of a file generated
by a test into the result of that test for matching against
an expected result.  The contents of the file are read using
the system encoding, so its usefulness is limited to text
files.
.\" COMMAND: cleanupTests
.TP
\fBcleanupTests\fR
.
Intended to clean up and summarize after several tests have been
run.  Typically called once per test file, at the end of the file
after all tests have been completed.  For best effectiveness, be
sure that the \fBcleanupTests\fR is evaluated even if an error
occurs earlier in the test file evaluation.
.RS
.PP
Prints statistics about the tests run and removes files that were
created by \fBmakeDirectory\fR and \fBmakeFile\fR since the
last \fBcleanupTests\fR.  Names of files and directories
in the directory \fBconfigure \-tmpdir\fR created since
the last \fBcleanupTests\fR, but not created by
\fBmakeFile\fR or \fBmakeDirectory\fR are printed
to \fBoutputChannel\fR.  This command also restores the original
shell environment, as described by the global \fBenv\fR
array. Returns an empty string.
.RE
.\" COMMAND: runAllTests
.TP
\fBrunAllTests\fR
.
This is a main command meant to run an entire suite of tests,
spanning multiple files and/or directories, as governed by
the configurable options of \fBtcltest\fR.  See \fBRUNNING ALL TESTS\fR
below for a complete description of the many variations possible
with \fBrunAllTests\fR.
.SS "CONFIGURATION COMMANDS"
.\" COMMAND: configure
.TP
\fBconfigure\fR
.
Returns the list of configurable options supported by \fBtcltest\fR.
See \fBCONFIGURABLE OPTIONS\fR below for the full list of options,
their valid values, and their effect on \fBtcltest\fR operations.
.TP
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
366
367
368
369
370
371
372
373
374
375

376
377
378
379
380
381
382
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
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







+














+





+








+







+








+










+





+





+





+





+





+





+





+





+





+





+





+





+





+





+












-
+







.PP
If the environment variable \fB::env(TCLTEST_OPTIONS)\fR exists when
the \fBtcltest\fR package is loaded (by \fBpackage require\fR \fBtcltest\fR)
then its value is taken as a list of arguments to pass to \fBconfigure\fR.
This allows the default values of the configuration options to be
set by the environment.
.RE
.\" COMMAND: customMatch
.TP
\fBcustomMatch \fImode script\fR
.
Registers \fImode\fR as a new legal value of the \fB\-match\fR option
to \fBtest\fR.  When the \fB\-match \fImode\fR option is
passed to \fBtest\fR, the script \fIscript\fR will be evaluated
to compare the actual result of evaluating the body of the test
to the expected result.
To perform the match, the \fIscript\fR is completed with two additional
words, the expected result, and the actual result, and the completed script
is evaluated in the global namespace.
The completed script is expected to return a boolean value indicating
whether or not the results match.  The built-in matching modes of
\fBtest\fR are \fBexact\fR, \fBglob\fR, and \fBregexp\fR.
.\" COMMAND: testConstraint
.TP
\fBtestConstraint \fIconstraint\fR ?\fIboolean\fR?
.
Sets or returns the boolean value associated with the named \fIconstraint\fR.
See \fBTEST CONSTRAINTS\fR below for more information.
.\" COMMAND: interpreter
.TP
\fBinterpreter\fR ?\fIexecutableName\fR?
.
Sets or returns the name of the executable to be \fBexec\fRed by
\fBrunAllTests\fR to run each test file when
\fBconfigure \-singleproc\fR is false.
The default value for \fBinterpreter\fR is the name of the
currently running program as returned by \fBinfo nameofexecutable\fR.
.\" COMMAND: outputChannel
.TP
\fBoutputChannel\fR ?\fIchannelID\fR?
.
Sets or returns the output channel ID.  This defaults to \fBstdout\fR.
Any test that prints test related output should send
that output to \fBoutputChannel\fR rather than letting
that output default to \fBstdout\fR.
.\" COMMAND: errorChannel
.TP
\fBerrorChannel\fR ?\fIchannelID\fR?
.
Sets or returns the error channel ID.  This defaults to \fBstderr\fR.
Any test that prints error messages should send
that output to \fBerrorChannel\fR rather than printing
directly to \fBstderr\fR.
.SS "SHORTCUT CONFIGURATION COMMANDS"
.\" COMMAND: debug
.TP
\fBdebug\fR ?\fIlevel\fR?
.
Same as
.QW "\fBconfigure \-debug\fR ?\fIlevel\fR?" .
.TP
\fBerrorFile\fR ?\fIfilename\fR?
.
Same as
.QW "\fBconfigure \-errfile\fR ?\fIfilename\fR?" .
.\" COMMAND: limitConstraints
.TP
\fBlimitConstraints\fR ?\fIboolean\fR?
.
Same as
.QW "\fBconfigure \-limitconstraints\fR ?\fIboolean\fR?" .
.\" COMMAND: loadFile
.TP
\fBloadFile\fR ?\fIfilename\fR?
.
Same as
.QW "\fBconfigure \-loadfile\fR ?\fIfilename\fR?" .
.\" COMMAND: loadScript
.TP
\fBloadScript\fR ?\fIscript\fR?
.
Same as
.QW "\fBconfigure \-load\fR ?\fIscript\fR?" .
.\" COMMAND: match
.TP
\fBmatch\fR ?\fIpatternList\fR?
.
Same as
.QW "\fBconfigure \-match\fR ?\fIpatternList\fR?" .
.\" COMMAND: matchDirectories
.TP
\fBmatchDirectories\fR ?\fIpatternList\fR?
.
Same as
.QW "\fBconfigure \-relateddir\fR ?\fIpatternList\fR?" .
.\" COMMAND: matchFiles
.TP
\fBmatchFiles\fR ?\fIpatternList\fR?
.
Same as
.QW "\fBconfigure \-file\fR ?\fIpatternList\fR?" .
.\" COMMAND: outputFile
.TP
\fBoutputFile\fR ?\fIfilename\fR?
.
Same as
.QW "\fBconfigure \-outfile\fR ?\fIfilename\fR?" .
.\" COMMAND: preserveCore
.TP
\fBpreserveCore\fR ?\fIlevel\fR?
.
Same as
.QW "\fBconfigure \-preservecore\fR ?\fIlevel\fR?" .
.\" COMMAND: singleProcess
.TP
\fBsingleProcess\fR ?\fIboolean\fR?
.
Same as
.QW "\fBconfigure \-singleproc\fR ?\fIboolean\fR?" .
.\" COMMAND: skip
.TP
\fBskip\fR ?\fIpatternList\fR?
.
Same as
.QW "\fBconfigure \-skip\fR ?\fIpatternList\fR?" .
.\" COMMAND: skipDirectories
.TP
\fBskipDirectories\fR ?\fIpatternList\fR?
.
Same as
.QW "\fBconfigure \-asidefromdir\fR ?\fIpatternList\fR?" .
.\" COMMAND: skipFiles
.TP
\fBskipFiles\fR ?\fIpatternList\fR?
.
Same as
.QW "\fBconfigure \-notfile\fR ?\fIpatternList\fR?" .
.\" COMMAND: temporaryDirectory
.TP
\fBtemporaryDirectory\fR ?\fIdirectory\fR?
.
Same as
.QW "\fBconfigure \-tmpdir\fR ?\fIdirectory\fR?" .
.\" COMMAND: testsDirectory
.TP
\fBtestsDirectory\fR ?\fIdirectory\fR?
.
Same as
.QW "\fBconfigure \-testdir\fR ?\fIdirectory\fR?" .
.\" COMMAND: verbose
.TP
\fBverbose\fR ?\fIlevel\fR?
.
Same as
.QW "\fBconfigure \-verbose\fR ?\fIlevel\fR?" .
.SS "OTHER COMMANDS"
.PP
The remaining commands provided by \fBtcltest\fR have better
alternatives provided by \fBtcltest\fR or \fBTcl\fR itself.  They
are retained to support existing test suites, but should be avoided
in new code.
.TP
\fBtest\fR \fIname description optionList\fR
\fBtest\fI name description optionList\fR
.
This form of \fBtest\fR was provided to enable passing many
options spanning several lines to \fBtest\fR as a single
argument quoted by braces, rather than needing to backslash quote
the newlines between arguments to \fBtest\fR.  The \fIoptionList\fR
argument is expected to be a list with an even number of elements
representing \fIoption\fR and \fIvalue\fR arguments to pass
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
442
443
444
445
446
447
448

449
450
451
452
453
454
455
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
467
468
469

470
471
472
473
474
475
476
477







+







+











+







-
-
-
-
-
-
-
-
-
-
-













-
+







for that reason this form is not recommended.  See the examples in
\fBCREATING TEST SUITES WITH TCLTEST\fR below to see that this
form is really not necessary to avoid backslash-quoted newlines.
If you insist on using this form, examine
the source code of \fBtcltest\fR if you want to know the substitution
details, or just enclose the third through last argument
to \fBtest\fR in braces and hope for the best.
.\" COMMAND: workingDirectory
.TP
\fBworkingDirectory\fR ?\fIdirectoryName\fR?
.
Sets or returns the current working directory when the test suite is
running.  The default value for workingDirectory is the directory in
which the test suite was launched.  The Tcl commands \fBcd\fR and
\fBpwd\fR are sufficient replacements.
.\" COMMAND: normalizeMsg
.TP
\fBnormalizeMsg \fImsg\fR
.
Returns the result of removing the
.QW extra
newlines from \fImsg\fR, where
.QW extra
is rather imprecise.  Tcl offers plenty of string
processing commands to modify strings as you wish, and
\fBcustomMatch\fR allows flexible matching of actual and expected
results.
.\" COMMAND: normalizePath
.TP
\fBnormalizePath \fIpathVar\fR
.
Resolves symlinks in a path, thus creating a path without internal
redirection.  It is assumed that \fIpathVar\fR is absolute.
\fIpathVar\fR is modified in place.  The Tcl command \fBfile normalize\fR
is a sufficient replacement.
.TP
\fBbytestring \fIstring\fR
.
Construct a string that consists of the requested sequence of bytes,
as opposed to a string of properly formed UTF-8 characters using the
value supplied in \fIstring\fR.  This allows the tester to create
denormalized or improperly formed strings to pass to C procedures that
are supposed to accept strings with embedded NULL types and confirm
that a string result has a certain pattern of bytes.  This is
exactly equivalent to the Tcl command \fBencoding convertfrom\fR
\fBidentity\fR.
.SH TESTS
.PP
The \fBtest\fR command is the heart of the \fBtcltest\fR package.
Its essential function is to evaluate a Tcl script and compare
the result with an expected result.  The options of \fBtest\fR
define the test script, the environment in which to evaluate it,
the expected result, and how the compare the actual result to
the expected result.  Some configuration options of \fBtcltest\fR
also influence how \fBtest\fR operates.
.PP
The valid options for \fBtest\fR are summarized:
.PP
.CS
\fBtest\fR \fIname\fR \fIdescription\fR
\fBtest\fI name description\fR
        ?\fB\-constraints \fIkeywordList|expression\fR?
        ?\fB\-setup \fIsetupScript\fR?
        ?\fB\-body \fItestScript\fR?
        ?\fB\-cleanup \fIcleanupScript\fR?
        ?\fB\-result \fIexpectedAnswer\fR?
        ?\fB\-output \fIexpectedOutput\fR?
        ?\fB\-errorOutput \fIexpectedError\fR?
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
558
559
560

561
562
563
564
565
566
567
568
569

570
571
572
573
574
575
576
577
578
579
580

581
582
583
584
585
586
587
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623







+










+
+



+









+
+







+









+







+








+






+









+









+











+







test, typically test failure messages.  Good \fIdescription\fR values
should briefly explain the purpose of the test to users of a test suite.
The name of a Tcl or C function being tested should be included in the
description for regression tests.  If the test case exists to reproduce
a bug, include the bug ID in the description.
.PP
Valid attributes and associated values are:
.\" OPTION: -constraints
.TP
\fB\-constraints \fIkeywordList\fR|\fIexpression\fR
.
The optional \fB\-constraints\fR attribute can be list of one or more
keywords or an expression.  If the \fB\-constraints\fR value is a list of
keywords, each of these keywords should be the name of a constraint
defined by a call to \fBtestConstraint\fR.  If any of the listed
constraints is false or does not exist, the test is skipped.  If the
\fB\-constraints\fR value is an expression, that expression
is evaluated. If the expression evaluates to true, then the test is run.
.RS
.PP
Note that the expression form of \fB\-constraints\fR may interfere with the
operation of \fBconfigure \-constraints\fR and
\fBconfigure \-limitconstraints\fR, and is not recommended.
.PP
Appropriate constraints should be added to any tests that should
not always be run.  That is, conditional evaluation of a test
should be accomplished by the \fB\-constraints\fR option, not by
conditional evaluation of \fBtest\fR.  In that way, the same
number of tests are always reported by the test suite, though
the number skipped may change based on the testing environment.
The default value is an empty list.
See \fBTEST CONSTRAINTS\fR below for a list of built-in constraints
and information on how to add your own constraints.
.RE
.\" OPTION: -setup
.TP
\fB\-setup \fIscript\fR
.
The optional \fB\-setup\fR attribute indicates a \fIscript\fR that will be run
before the script indicated by the \fB\-body\fR attribute.  If evaluation
of \fIscript\fR raises an error, the test will fail.  The default value
is an empty script.
.\" OPTION: -body
.TP
\fB\-body \fIscript\fR
.
The \fB\-body\fR attribute indicates the \fIscript\fR to run to carry out the
test, which must return a result that can be checked for correctness.
If evaluation of \fIscript\fR raises an error, the test will fail
(unless the \fB\-returnCodes\fR option is used to state that an error
is expected).
The default value is an empty script.
.\" OPTION: -cleanup
.TP
\fB\-cleanup \fIscript\fR
.
The optional \fB\-cleanup\fR attribute indicates a \fIscript\fR that will be
run after the script indicated by the \fB\-body\fR attribute.
If evaluation of \fIscript\fR raises an error, the test will fail.
The default value is an empty script.
.\" OPTION: -match
.TP
\fB\-match \fImode\fR
.
The \fB\-match\fR attribute determines how expected answers supplied by
\fB\-result\fR, \fB\-output\fR, and \fB\-errorOutput\fR are compared.  Valid
values for \fImode\fR are \fBregexp\fR, \fBglob\fR, \fBexact\fR, and
any value registered by a prior call to \fBcustomMatch\fR.  The default
value is \fBexact\fR.
.\" OPTION: -result
.TP
\fB\-result \fIexpectedValue\fR
.
The \fB\-result\fR attribute supplies the \fIexpectedValue\fR against which
the return value from script will be compared. The default value is
an empty string.
.\" OPTION: -output
.TP
\fB\-output \fIexpectedValue\fR
.
The \fB\-output\fR attribute supplies the \fIexpectedValue\fR against which
any output sent to \fBstdout\fR or \fBoutputChannel\fR during evaluation
of the script(s) will be compared.  Note that only output printed using
the global \fBputs\fR command is used for comparison.  If \fB\-output\fR is
not specified, output sent to \fBstdout\fR and \fBoutputChannel\fR is not
processed for comparison.
.\" OPTION: -errorOutput
.TP
\fB\-errorOutput \fIexpectedValue\fR
.
The \fB\-errorOutput\fR attribute supplies the \fIexpectedValue\fR against
which any output sent to \fBstderr\fR or \fBerrorChannel\fR during
evaluation of the script(s) will be compared. Note that only output
printed using the global \fBputs\fR command is used for comparison.  If
\fB\-errorOutput\fR is not specified, output sent to \fBstderr\fR and
\fBerrorChannel\fR is not processed for comparison.
.\" OPTION: -returnCodes
.TP
\fB\-returnCodes \fIexpectedCodeList\fR
.
The optional \fB\-returnCodes\fR attribute supplies \fIexpectedCodeList\fR,
a list of return codes that may be accepted from evaluation of the
\fB\-body\fR script.  If evaluation of the \fB\-body\fR script returns
a code not in the \fIexpectedCodeList\fR, the test fails.  All
return codes known to \fBreturn\fR, in both numeric and symbolic
form, including extended return codes, are acceptable elements in
the \fIexpectedCodeList\fR.  Default value is
.QW "\fBok return\fR" .
.\" OPTION: -errorCode
.TP
\fB\-errorCode \fIexpectedErrorCode\fR
.
The optional \fB\-errorCode\fR attribute supplies \fIexpectedErrorCode\fR,
a glob pattern that should match the error code reported from evaluation of the
\fB\-body\fR script.  If evaluation of the \fB\-body\fR script returns
a code not matching \fIexpectedErrorCode\fR, the test fails.  Default value is
621
622
623
624
625
626
627
628

629
630
631
632
633
634
635

636
637
638

639
640
641
642
643

644
645
646
647

648
649
650
651

652
653
654
655

656
657
658
659

660
661
662
663

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
707
708
709

710
711
712
713
714
715
716
717

718
719
720
721
722
723

724
725
726

727
728

729
730
731
732
733

734
735
736
737
738

739
740
741
742
743
744

745
746
747
748

749
750
751
752

753
754
755
756

757
758
759
760
761
762
763

764
765
766
767
768
769
770
771
657
658
659
660
661
662
663

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
707
708
709


710

711
712
713


714

715
716
717
718
719


720

721
722
723


724

725

726


727

728
729


730

731
732


733

734
735
736


737

738


739

740


741

742


743

744
745
746
747


748

749
750
751
752
753
754
755







-
+






-
+

-
-
+
-


-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-


-
-
+
-


-
-
+
-


-
-
+
-


-
-
+
-


-
-
+
-




-
-
+
-



-
-
+
-





-
-
+
-



-
-
+
-

-
+
-
-
+
-


-
-
+
-


-
-
+
-



-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-




-
-
+
-







way to define any conditions required for the test to be possible or
meaningful.  For example, a \fBtest\fR with \fB\-constraints unix\fR
will only be run if the constraint \fBunix\fR is true, which indicates
the test suite is being run on a Unix platform.
.PP
Each \fBtest\fR should include whatever \fB\-constraints\fR are
required to constrain it to run only where appropriate.  Several
constraints are pre-defined in the \fBtcltest\fR package, listed
constraints are predefined in the \fBtcltest\fR package, listed
below.  The registration of user-defined constraints is performed
by the \fBtestConstraint\fR command.  User-defined constraints
may appear within a test file, or within the script specified
by the \fBconfigure \-load\fR or \fBconfigure \-loadfile\fR
options.
.PP
The following is a list of constraints pre-defined by the
The following is a list of constraints predefined by the
\fBtcltest\fR package itself:
.TP
\fIsingleTestInterp\fR
.IP \fIsingleTestInterp\fR
.
This test can only be run if all test files are sourced into a single
interpreter.
.TP
\fIunix\fR
.IP \fIunix\fR
.
This test can only be run on any Unix platform.
.TP
\fIwin\fR
.IP \fIwin\fR
.
This test can only be run on any Windows platform.
.TP
\fInt\fR
.IP \fInt\fR
.
This test can only be run on any Windows NT platform.
.TP
\fImac\fR
.IP \fImac\fR
.
This test can only be run on any Mac platform.
.TP
\fIunixOrWin\fR
.IP \fIunixOrWin\fR
.
This test can only be run on a Unix or Windows platform.
.TP
\fImacOrWin\fR
.IP \fImacOrWin\fR
.
This test can only be run on a Mac or Windows platform.
.TP
\fImacOrUnix\fR
.IP \fImacOrUnix\fR
.
This test can only be run on a Mac or Unix platform.
.TP
\fItempNotWin\fR
.IP \fItempNotWin\fR
.
This test can not be run on Windows.  This flag is used to temporarily
disable a test.
.TP
\fItempNotMac\fR
.IP \fItempNotMac\fR
.
This test can not be run on a Mac.  This flag is used
to temporarily disable a test.
.TP
\fIunixCrash\fR
.IP \fIunixCrash\fR
.
This test crashes if it is run on Unix.  This flag is used to temporarily
disable a test.
.TP
\fIwinCrash\fR
.IP \fIwinCrash\fR
.
This test crashes if it is run on Windows.  This flag is used to temporarily
disable a test.
.TP
\fImacCrash\fR
.IP \fImacCrash\fR
.
This test crashes if it is run on a Mac.  This flag is used to temporarily
disable a test.
.TP
\fIemptyTest\fR
.IP \fIemptyTest\fR
.
This test is empty, and so not worth running, but it remains as a
place-holder for a test to be written in the future.  This constraint
has value false to cause tests to be skipped unless the user specifies
otherwise.
.TP
\fIknownBug\fR
.IP \fIknownBug\fR
.
This test is known to fail and the bug is not yet fixed.  This constraint
has value false to cause tests to be skipped unless the user specifies
otherwise.
.TP
\fInonPortable\fR
.IP \fInonPortable\fR
.
This test can only be run in some known development environment.
Some tests are inherently non-portable because they depend on things
like word length, file system configuration, window manager, etc.
This constraint has value false to cause tests to be skipped unless
the user specifies otherwise.
.TP
\fIuserInteraction\fR
.IP \fIuserInteraction\fR
.
This test requires interaction from the user.  This constraint has
value false to causes tests to be skipped unless the user specifies
otherwise.
.TP
\fIinteractive\fR
.IP \fIinteractive\fR
.
This test can only be run in if the interpreter is in interactive mode
(when the global tcl_interactive variable is set to 1).
(when the global \fB::tcl_interactive\fR variable is set to 1).
.TP
\fInonBlockFiles\fR
.IP \fInonBlockFiles\fR
.
This test can only be run if platform supports setting files into
nonblocking mode.
.TP
\fIasyncPipeClose\fR
.IP \fIasyncPipeClose\fR
.
This test can only be run if platform supports async flush and async close
on a pipe.
.TP
\fIunixExecs\fR
.IP \fIunixExecs\fR
.
This test can only be run if this machine has Unix-style commands
\fBcat\fR, \fBecho\fR, \fBsh\fR, \fBwc\fR, \fBrm\fR, \fBsleep\fR,
\fBfgrep\fR, \fBps\fR, \fBchmod\fR, and \fBmkdir\fR available.
.TP
\fIhasIsoLocale\fR
.IP \fIhasIsoLocale\fR
.
This test can only be run if can switch to an ISO locale.
.TP
\fIroot\fR
.IP \fIroot\fR
.
This test can only run if Unix user is root.
.TP
\fInotRoot\fR
.IP \fInotRoot\fR
.
This test can only run if Unix user is not root.
.TP
\fIeformat\fR
.IP \fIeformat\fR
.
This test can only run if app has a working version of sprintf with respect
to the
.QW e
format of floating-point numbers.
.TP
\fIstdio\fR
.IP \fIstdio\fR
.
This test can only be run if \fBinterpreter\fR can be \fBopen\fRed
as a pipe.
.PP
The alternative mode of constraint control is enabled by setting
\fBconfigure \-limitconstraints\fR to true.  With that configuration
setting, all existing constraints other than those in the constraint
list returned by \fBconfigure \-constraints\fR are set to false.
842
843
844
845
846
847
848

849
850
851
852
853
854

855
856
857
858
859
860
861
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847







+






+







\fBconfigure \-asidefromdir\fR patterns.  In this way,
many directories in a directory tree can have all their
test files evaluated by a single \fBrunAllTests\fR
command.
.SH "CONFIGURABLE OPTIONS"
The \fBconfigure\fR command is used to set and query the configurable
options of \fBtcltest\fR.  The valid options are:
.\" OPTION: -singleproc
.TP
\fB\-singleproc \fIboolean\fR
.
Controls whether or not \fBrunAllTests\fR spawns a child process for
each test file.  No spawning when \fIboolean\fR is true.  Default
value is false.
.\" OPTION: -debug
.TP
\fB\-debug \fIlevel\fR
.
Sets the debug level to \fIlevel\fR, an integer value indicating how
much debugging information should be printed to \fBstdout\fR.  Note that
debug messages always go to \fBstdout\fR, independent of the value of
\fBconfigure \-outfile\fR.  Default value is 0.  Levels are defined as:
873
874
875
876
877
878
879

880
881
882
883
884
885
886
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873







+







Display the flag array parsed by the command line processor, the
contents of the global \fBenv\fR array, and all user-defined variables
that exist in the current namespace as they are used.
.IP 3
Display information regarding what individual procs in the test
harness are doing.
.RE
.\" OPTION: -verbose
.TP
\fB\-verbose \fIlevel\fR
.
Sets the type of output verbosity desired to \fIlevel\fR,
a list of zero or more of the elements \fBbody\fR, \fBpass\fR,
\fBskip\fR, \fBstart\fR, \fBerror\fR, \fBline\fR, \fBmsec\fR and \fBusec\fR.
Default value is
902
903
904
905
906
907
908
909

910
911
912
913
914
915
916
917
918
919

920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936

937
938
939
940
941

942
943
944
945
946
947
948

949
950
951
952
953
954
955
956

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

1016
1017
1018
1019
1020
1021
1022
889
890
891
892
893
894
895

896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
1016
1017
1018
1019
1020
1021
1022
1023
1024







-
+










+

















+





+







+








+





+






+







+







+






+






+





+





+






+






+







Print source file line information of failed tests
.IP "msec (\fBm\fR)"
Print each test's execution time in milliseconds
.IP "usec (\fBu\fR)"
Print each test's execution time in microseconds
.PP
Note that the \fBmsec\fR and \fBusec\fR verbosity levels are provided as
indicative measures only. They do not tackle the problem of repeatibility which
indicative measures only. They do not tackle the problem of repeatability which
should be considered in performance tests or benchmarks. To use these verbosity
levels to thoroughly track performance degradations, consider wrapping your
test bodies with \fBtime\fR commands.
.PP
The single letter abbreviations noted above are also recognized
so that
.QW "\fBconfigure \-verbose pt\fR"
is the same as
.QW "\fBconfigure \-verbose {pass start}\fR" .
.RE
.\" OPTION: -preservecore
.TP
\fB\-preservecore \fIlevel\fR
.
Sets the core preservation level to \fIlevel\fR.  This level
determines how stringent checks for core files are.  Default
value is 0.  Levels are defined as:
.RS
.IP 0
No checking \(em do not check for core files at the end of each test
command, but do check for them in \fBrunAllTests\fR after all
test files have been evaluated.
.IP 1
Also check for core files at the end of each \fBtest\fR command.
.IP 2
Check for core files at all times described above, and save a
copy of each core file produced in \fBconfigure \-tmpdir\fR.
.RE
.\" OPTION: -limitconstraints
.TP
\fB\-limitconstraints \fIboolean\fR
.
Sets the mode by which \fBtest\fR honors constraints as described
in \fBTESTS\fR above.  Default value is false.
.\" OPTION: -constraints
.TP
\fB\-constraints \fIlist\fR
.
Sets all the constraints in \fIlist\fR to true.  Also used in
combination with \fBconfigure \-limitconstraints true\fR to control an
alternative constraint mode as described in \fBTESTS\fR above.
Default value is an empty list.
.\" OPTION: -tmpdir
.TP
\fB\-tmpdir \fIdirectory\fR
.
Sets the temporary directory to be used by \fBmakeFile\fR,
\fBmakeDirectory\fR, \fBviewFile\fR, \fBremoveFile\fR,
and \fBremoveDirectory\fR as the default directory where
temporary files and directories created by test files should
be created.  Default value is \fBworkingDirectory\fR.
.\" OPTION: -testdir
.TP
\fB\-testdir \fIdirectory\fR
.
Sets the directory searched by \fBrunAllTests\fR for test files
and subdirectories.  Default value is \fBworkingDirectory\fR.
.\" OPTION: -file
.TP
\fB\-file \fIpatternList\fR
.
Sets the list of patterns used by \fBrunAllTests\fR to determine
what test files to evaluate.  Default value is
.QW \fB*.test\fR .
.\" OPTION: -notfile
.TP
\fB\-notfile \fIpatternList\fR
.
Sets the list of patterns used by \fBrunAllTests\fR to determine
what test files to skip.  Default value is
.QW \fBl.*.test\fR ,
so that any SCCS lock files are skipped.
.\" OPTION: -relateddir
.TP
\fB\-relateddir \fIpatternList\fR
.
Sets the list of patterns used by \fBrunAllTests\fR to determine
what subdirectories to search for an \fBall.tcl\fR file.  Default
value is
.QW \fB*\fR .
.\" OPTION: -asidefromdir
.TP
\fB\-asidefromdir \fIpatternList\fR
.
Sets the list of patterns used by \fBrunAllTests\fR to determine
what subdirectories to skip when searching for an \fBall.tcl\fR file.
Default value is an empty list.
.\" OPTION: -match
.TP
\fB\-match \fIpatternList\fR
.
Set the list of patterns used by \fBtest\fR to determine whether
a test should be run.  Default value is
.QW \fB*\fR .
.\" OPTION: -skip
.TP
\fB\-skip \fIpatternList\fR
.
Set the list of patterns used by \fBtest\fR to determine whether
a test should be skipped.  Default value is an empty list.
.\" OPTION: -load
.TP
\fB\-load \fIscript\fR
.
Sets a script to be evaluated by \fBloadTestedCommands\fR.
Default value is an empty script.
.\" OPTION: -loadfile
.TP
\fB\-loadfile \fIfilename\fR
.
Sets the filename from which to read a script to be evaluated
by \fBloadTestedCommands\fR.  This is an alternative to
\fB\-load\fR.  They cannot be used together.
.\" OPTION: -outfile
.TP
\fB\-outfile \fIfilename\fR
.
Sets the file to which all output produced by tcltest should be
written.  A file named \fIfilename\fR will be \fBopen\fRed for writing,
and the resulting channel will be set as the value of \fBoutputChannel\fR.
.\" OPTION: -errfile
.TP
\fB\-errfile \fIfilename\fR
.
Sets the file to which all error output produced by tcltest
should be written.  A file named \fIfilename\fR will be \fBopen\fRed
for writing, and the resulting channel will be set as the value
of \fBerrorChannel\fR.
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1177
1178
1179
1180
1181
1182
1183

1184
1185
1186
1187
1188
1189
1190







-







because that is the default name used by \fBrunAllTests\fR when combining
multiple test suites into one testing run.
.IP [8]
Here is a sketch of a sample test suite main script:
.RS
.PP
.CS
package require Tcl 8.6
package require tcltest 2.5
package require example
\fB::tcltest::configure\fR -testdir \e
        [file dirname [file normalize [info script]]]
eval \fB::tcltest::configure\fR $argv
\fB::tcltest::runAllTests\fR
.CE

Changes to doc/tclvars.n.

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
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







+










+



+
+
+
+






+







argc, argv, argv0, auto_path, env, errorCode, errorInfo, tcl_interactive, tcl_library, tcl_nonwordchars, tcl_patchLevel, tcl_pkgPath, tcl_platform, tcl_rcFileName, tcl_traceCompile, tcl_traceExec, tcl_wordchars, tcl_version \- Variables used by Tcl
.BE
.SH DESCRIPTION
.PP
The following global variables are created and managed automatically
by the Tcl library.  Except where noted below, these variables should
normally be treated as read-only by application-specific code and by users.
.\" VARIABLE: auto_path
.TP
\fBauto_path\fR
.
If set, then it must contain a valid Tcl list giving directories to
search during auto-load operations (including for package index
files when using the default \fBpackage unknown\fR handler).
This variable is initialized during startup to contain, in order:
the directories listed in the \fBTCLLIBPATH\fR environment variable,
the directory named by the \fBtcl_library\fR global variable,
the parent directory of \fBtcl_library\fR,
\fB[file dirname [file dirname [info nameofexecutable]]]/lib\fR,
the directories listed in the \fBtcl_pkgPath\fR variable.
Additional locations to look for files and package indices should
normally be added to this variable using \fBlappend\fR.
Initialization of auto_path from the TCLLIBPATH environment
variable undergoes tilde substitution (see \fBfilename\fR) on each
path. Any tilde substitution that fails because the user is unknown
will be omitted from auto_path.
.RS
.PP
Additional variables relating to package management exist. More
details are listed in the \fBVARIABLES\fR section of the \fBlibrary\fR
manual page.
.RE
.\" VARIABLE: env
.TP
\fBenv\fR
.
This variable is maintained by Tcl as an array
whose elements are the environment variables for the process.
Reading an element will return the value of the corresponding
environment variable.
69
70
71
72
73
74
75
76

77
78
79
80




81
82
83
84
85
86
87
76
77
78
79
80
81
82

83




84
85
86
87
88
89
90
91
92
93
94







-
+
-
-
-
-
+
+
+
+







will not work on Windows and is discouraged for cross-platform usage.
.PP
The following elements of \fBenv\fR are special to Tcl:
.TP
\fBenv(HOME)\fR
.
This environment variable, if set, gives the location of the directory
considered to be the current user's home directory, and to which a
considered to be the current user's home directory. The value of this variable
call of \fBcd\fR without arguments or with just
.QW ~
as an argument will change into. Most platforms set this correctly by
default; it does not normally need to be set by user code.
is returned by the \fBfile home\fR command. Most platforms set this correctly by
default; it does not normally need to be set by user code. On Windows, if not
already set, it is set to the value of the \fBUSERPROFILE\fR environment
variable.
.TP
\fBenv(TCL_LIBRARY)\fR
.
If set, then it specifies the location of the directory containing
library scripts (the value of this variable will be
assigned to the \fBtcl_library\fR variable and therefore returned by
the command \fBinfo library\fR).  If this variable is not set then
113
114
115
116
117
118
119

120
121
122
123
124
125
126
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134







+







.TP
\fBenv(TCL_INTERP_DEBUG_FRAME)\fR
.
If existing, it has the same effect as running \fBinterp debug\fR
\fB{} -frame 1\fR
as the very first command of each new Tcl interpreter.
.RE
.\" VARIABLE: errorCode
.TP
\fBerrorCode\fR
.
This variable holds the value of the \fB\-errorcode\fR return option
set by the most recent error that occurred in this interpreter.
This list value represents additional information about the error
in a form that is easy to process with programs.
209
210
211
212
213
214
215

216
217
218
219
220
221
222
223
224
225

226
227
228
229
230
231
232
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







+










+







procedures such as \fBTcl_SetObjErrorCode\fR, \fBTcl_SetReturnOptions\fR,
and \fBTcl_PosixError\fR, or they may invoke the \fB\-errorcode\fR
option of the \fBreturn\fR command.
If none of these methods for setting the error code has been used,
the Tcl interpreter will reset the variable to \fBNONE\fR after
the next error.
.RE
.\" VARIABLE: errorInfo
.TP
\fBerrorInfo\fR
.
This variable holds the value of the \fB\-errorinfo\fR return option
set by the most recent error that occurred in this interpreter.
This string value will contain one or more lines
identifying the Tcl commands and procedures that were being executed
when the most recent error occurred.
Its contents take the form of a stack trace showing the various
nested Tcl commands that had been invoked at the time of the error.
.\" VARIABLE: tcl_library
.TP
\fBtcl_library\fR
.
This variable holds the name of a directory containing the
system library of Tcl scripts, such as those used for auto-loading.
The value of this variable is returned by the \fBinfo library\fR command.
See the \fBlibrary\fR manual entry for details of the facilities
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
366
367
368
369
370
371
372

373

374
375
376
377
378
379
380
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
366
367
368
369
370
371
372
373







+









+



















+












-
-
+
-


-
-
+
-





-
-
+
-


-
-
+
-



-
-
+
-



-
-
+
-


-
-
+



-
-
+
-


-
-
+
-


-
-
+
-


-
-
+
-




-
-
+
-



+

















+

+







found that contains an appropriate Tcl startup script.
If the \fBTCL_LIBRARY\fR environment variable exists, then
the directory it names is checked first.
If \fBTCL_LIBRARY\fR is not set or doesn't refer to an appropriate
directory, then Tcl checks several other directories based on a
compiled-in default location, the location of the binary containing
the application, and the current working directory.
.\" VARIABLE: tcl_patchLevel
.TP
\fBtcl_patchLevel\fR
.
When an interpreter is created Tcl initializes this variable to
hold a string giving the current patch level for Tcl, such as
\fB8.4.16\fR for Tcl 8.4 with the first sixteen official patches, or
\fB8.5b3\fR for the third beta release of Tcl 8.5.
The value of this variable is returned by the \fBinfo patchlevel\fR
command.
.\" VARIABLE: tcl_pkgPath
.TP
\fBtcl_pkgPath\fR
.
This variable holds a list of directories indicating where packages are
normally installed.  It is not used on Windows.  It typically contains
either one or two entries; if it contains two entries, the first is
normally a directory for platform-dependent packages (e.g., shared library
binaries) and the second is normally a directory for platform-independent
packages (e.g., script files). Typically a package is installed as a
subdirectory of one of the entries in the \fBtcl_pkgPath\fR
variable. The directories in the \fBtcl_pkgPath\fR variable are
included by default in the \fBauto_path\fR
variable, so they and their immediate subdirectories are automatically
searched for packages during \fBpackage require\fR commands.  Note:
\fBtcl_pkgPath\fR is not intended to be modified by the application.  Its
value is added to \fBauto_path\fR at startup; changes to \fBtcl_pkgPath\fR
are not reflected in \fBauto_path\fR.  If you want Tcl to search additional
directories for packages you should add the names of those directories to
\fBauto_path\fR, not \fBtcl_pkgPath\fR.
.\" VARIABLE: tcl_platform
.TP
\fBtcl_platform\fR
.
This is an associative array whose elements contain information about
the platform on which the application is running, such as the name of
the operating system, its current release number, and the machine's
instruction set.  The elements listed below will always
be defined, but they may have empty strings as values if Tcl could not
retrieve any relevant information.  In addition, extensions
and applications may add additional values to the array.  The
predefined elements are:
.RS
.TP
\fBbyteOrder\fR
.IP \fBbyteOrder\fR
.
The native byte order of this machine: either \fBlittleEndian\fR or
\fBbigEndian\fR.
.TP
\fBdebug\fR
.IP \fBdebug\fR
.
If this variable exists, then the interpreter was compiled with and linked
to a debug-enabled C run-time.  This variable will only exist on Windows,
so extension writers can specify which package to load depending on the
C run-time library that is in use.  This is not an indication that this core
contains symbols.
.TP
\fBengine\fR
.IP \fBengine\fR
.
The name of the Tcl language implementation.  When the interpreter is first
created, this is always set to the string \fBTcl\fR.
.TP
\fBmachine\fR
.IP \fBmachine\fR
.
The instruction set executed by this machine, such as
\fBintel\fR, \fBPPC\fR, \fB68k\fR, or \fBsun4m\fR.  On UNIX machines, this
is the value returned by \fBuname -m\fR.
.TP
\fBos\fR
.IP \fBos\fR
.
The name of the operating system running on this machine,
such as \fBWindows NT\fR or \fBSunOS\fR.
On UNIX machines, this is the value returned by \fBuname -s\fR.
.TP
\fBosVersion\fR
.IP \fBosVersion\fR
.
The version number for the operating system running on this machine.
On UNIX machines, this is the value returned by \fBuname -r\fR.
.TP
\fBpathSeparator\fR
.IP \fBpathSeparator\fR
'\" Defined by TIP #315
The character that should be used to \fBsplit\fR PATH-like environment
variables into their corresponding list of directory names.
.TP
\fBplatform\fR
.IP \fBplatform\fR
.
Either \fBwindows\fR, or \fBunix\fR.  This identifies the
general operating environment of the machine.
.TP
\fBpointerSize\fR
.IP \fBpointerSize\fR
.
This gives the size of the native-machine pointer in bytes (strictly, it
is same as the result of evaluating \fIsizeof(void*)\fR in C.)
.TP
\fBthreaded\fR
.IP \fBthreaded\fR
.
If this variable exists, then the interpreter
was compiled with threads enabled.
.TP
\fBuser\fR
.IP \fBuser\fR
.
This identifies the
current user based on the login information available on the platform.
This value comes from the getuid() and getpwuid() system calls on Unix,
and the value from the GetUserName() system call on Windows.
.TP
\fBwordSize\fR
.IP \fBwordSize\fR
.
This gives the size of the native-machine word in bytes (strictly, it
is same as the result of evaluating \fIsizeof(long)\fR in C.)
.RE
.\" VARIABLE: tcl_traceCompile
.TP
\fBtcl_traceCompile\fR
.
The value of this variable can be set to control
how much tracing information
is displayed during bytecode compilation.
By default, \fBtcl_traceCompile\fR is zero and no information is displayed.
Setting \fBtcl_traceCompile\fR to 1 generates a one-line summary in \fBstdout\fR
whenever a procedure or top-level command is compiled.
Setting it to 2 generates a detailed listing in \fBstdout\fR of the
bytecode instructions emitted during every compilation.
This variable is useful in
tracking down suspected problems with the Tcl compiler.
.PP
.RS
This variable and functionality only exist if
\fBTCL_COMPILE_DEBUG\fR was defined during Tcl's compilation.
.\" tcl::unsupported::disassemble always works, but we don't document it
.RE
.\" VARIABLE: tcl_traceExec
.TP
\fBtcl_traceExec\fR
.
The value of this variable can be set to control
how much tracing information
is displayed during bytecode execution.
By default, \fBtcl_traceExec\fR is zero and no information is displayed.
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
442
443
444

445
446
447
448
449
450

451
452
453
454
455
456
457
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
442
443
444
445
446
447
448
449
450
451







+






-
-
-
-
-
+
+
+






-
-
-
-
+

+















+




+




+






+







tracking down suspected problems with the bytecode compiler
and interpreter.
.PP
.RS
This variable and functionality only exist if
\fBTCL_COMPILE_DEBUG\fR was defined during Tcl's compilation.
.RE
.\" VARIABLE: tcl_wordchars
.TP
\fBtcl_wordchars\fR
.
The value of this variable is a regular expression that can be set to
control what are considered
.QW word
characters, for instances like
selecting a word by double-clicking in text in Tk.  It is platform
dependent.  On Windows, it defaults to \fB\eS\fR, meaning anything
but a Unicode space character.  Otherwise it defaults to \fB\ew\fR,
which is any Unicode word character (number, letter, or underscore).
characters.  It defaults to \fB\ew\fR, which is any Unicode
word character (number, letter, or underscore).
.\" VARIABLE: tcl_nonwordchars
.TP
\fBtcl_nonwordchars\fR
.
The value of this variable is a regular expression that can be set to
control what are considered
.QW non-word
characters, for instances like
selecting a word by double-clicking in text in Tk.  It is platform
dependent.  On Windows, it defaults to \fB\es\fR, meaning any Unicode space
character.  Otherwise it defaults to \fB\eW\fR, which is anything but a
characters.  It defaults to \fB\eW\fR, which is anything but a
Unicode word character (number, letter, or underscore).
.\" VARIABLE: tcl_version
.TP
\fBtcl_version\fR
.
When an interpreter is created Tcl initializes this variable to
hold the version number for this version of Tcl in the form \fIx.y\fR.
Changes to \fIx\fR represent major changes with probable
incompatibilities and changes to \fIy\fR represent small enhancements and
bug fixes that retain backward compatibility.
The value of this variable is returned by the \fBinfo tclversion\fR
command.
.SH "OTHER GLOBAL VARIABLES"
.PP
The following variables are only guaranteed to exist in \fBtclsh\fR
and \fBwish\fR executables; the Tcl library does not define them
itself but many Tcl environments do.
.\" VARIABLE: argc
.TP 6
\fBargc\fR
.
The number of arguments to \fBtclsh\fR or \fBwish\fR.
.\" VARIABLE: argv
.TP 6
\fBargv\fR
.
Tcl list of arguments to \fBtclsh\fR or \fBwish\fR.
.\" VARIABLE: argv0
.TP 6
\fBargv0\fR
.
The script that \fBtclsh\fR or \fBwish\fR started executing (if it was
specified) or otherwise the name by which \fBtclsh\fR or \fBwish\fR
was invoked.
.\" VARIABLE: tcl_interactive
.TP 6
\fBtcl_interactive\fR
.
Contains 1 if \fBtclsh\fR or \fBwish\fR is running interactively (no
script was specified and standard input is a terminal-like device), 0
otherwise.
.SH EXAMPLES

Changes to doc/tell.n.

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
8
9
10
11
12
13
14

15
16
17
18


















19








20
21



22
23
24
25
26







-
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+

-
-
-
+




.TH tell n 8.1 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
tell \- Return current access position for an open channel
.SH SYNOPSIS
\fBtell \fIchannelId\fR
\fBtell \fIchannel\fR
.BE
.SH DESCRIPTION
.PP
Returns an integer giving the current access position in
\fIchannelId\fR.  This value returned is a byte offset that can be passed to
\fBseek\fR in order to set the channel to a particular position.  Note
that this value is in terms of bytes, not characters like \fBread\fR.
The value returned is -1 for channels that do not support
seeking.
.PP
\fIChannelId\fR must be an identifier for an open channel such as a
Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR),
the return value from an invocation of \fBopen\fR or \fBsocket\fR, or
the result of a channel creation command provided by a Tcl extension.
.SH EXAMPLE
.PP
Read a line from a file channel only if it starts with \fBfoobar\fR:
.PP
.CS
# Save the offset in case we need to undo the read...
set offset [\fBtell\fR $chan]
The \fBtell\fR command has been superceded by the \fBchan tell\fR
if {[read $chan 6] eq "foobar"} {
    gets $chan line
} else {
    set line {}
    # Undo the read...
    seek $chan $offset
}
.CE
command which supports the same syntax and options.
.SH "SEE ALSO"
file(n), open(n), close(n), gets(n), seek(n), Tcl_StandardChannels(3)
.SH KEYWORDS
access position, channel, seeking
chan(n)
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/timerate.n.

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
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
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
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













+

-
-
+
-

+
















-
+


-
+

-
-
+
+







-
+
+





-
+
+


+











+
-
+

+

-
+

-
+
+




+



-
+




-
-
+
+

-
-
-
-
+
+
+
+
+







'\"
'\" Copyright (c) 2005 Sergey Brester aka sebres.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH timerate n "" Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
timerate \- Calibrated performance measurements of script execution time
.SH SYNOPSIS
.nf
\fBtimerate \fIscript\fR ?\fItime\fR? ?\fImax-count\fR?
.sp
\fBtimerate \fR?\fB\-direct\fR? ?\fB\-overhead\fI double\fR? \fIscript\fR ?\fItime\fR? ?\fImax-count\fR?
\fBtimerate \fR?\fB\-direct\fR? ?\fB\-overhead\fI estimate\fR? \fIscript\fR ?\fItime\fR? ?\fImax-count\fR?
.sp
\fBtimerate \fR?\fB\-calibrate\fR? ?\fB\-direct\fR? \fIscript\fR ?\fItime\fR? ?\fImax-count\fR?
.fi
.BE
.SH DESCRIPTION
.PP
The \fBtimerate\fR command does calibrated performance measurement of a Tcl
command or script, \fIscript\fR. The \fIscript\fR should be written so that it
can be executed multiple times during the performance measurement process.
Time is measured in elapsed time using the finest timer resolution as possible,
not CPU time; if \fIscript\fR interacts with the OS, the cost of that
interaction is included.
This command may be used to provide information as to how well a script or
Tcl command is performing, and can help determine bottlenecks and fine-tune
application performance.
.PP
The first and second form will evaluate \fIscript\fR until the interval
\fItime\fR given in milliseconds elapses, or for 1000 milliseconds (1 second)
if \fItime\fR is not specified.
.sp
.PP
The parameter \fImax-count\fR could additionally impose a further restriction
by the maximal number of iterations to evaluate the script.
If \fImax-count\fR is specified, the evalution will stop either this count of
If \fImax-count\fR is specified, the evaluation will stop either this count of
iterations is reached or the time is exceeded.
.sp
It will then return a canonical tcl-list of the form:
.PP
It will then return a canonical Tcl-list of the form:
.PP
.CS
\fB0.095977 \(mcs/# 52095836 # 10419167 #/sec 5000.000 net-ms\fR
.CE
.PP
which indicates:
.IP \(bu 3
the average amount of time required per iteration, in microseconds ([\fBlindex\fR $result 0])
the average amount of time required per iteration, in microseconds
([\fBlindex\fR $result 0])
.IP \(bu 3
the count how many times it was executed ([\fBlindex\fR $result 2])
.IP \(bu 3
the estimated rate per second ([\fBlindex\fR $result 4])
.IP \(bu 3
the estimated real execution time without measurement overhead ([\fBlindex\fR $result 6])
the estimated real execution time without measurement overhead
([\fBlindex\fR $result 6])
.PP
The following options may be supplied to the \fBtimerate\fR command:
.\" OPTION: -calibrate
.TP
\fB\-calibrate\fR
.
To measure very fast scripts as exactly as possible, a calibration process
may be required.
The \fB\-calibrate\fR option is used to calibrate \fBtimerate\fR itself,
calculating the estimated overhead of the given script as the default overhead
for future invocations of the \fBtimerate\fR command. If the \fItime\fR
parameter is not specified, the calibrate procedure runs for up to 10 seconds.
.RS
.PP
Note that the calibration process is not thread safe in the current
Note that calibration is not thread safe in the current implementation.
implementation.
.RE
.\" OPTION: -overhead
.TP
\fB\-overhead \fIdouble\fR
\fB\-overhead \fIestimate\fR
.
The \fB\-overhead\fR parameter supplies an estimate (in microseconds) of the
The \fB\-overhead\fR parameter supplies an estimate (in microseconds, which may
be a floating point number) of the
measurement overhead of each iteration of the tested script. This quantity
will be subtracted from the measured time prior to reporting results. This can
be useful for removing the cost of interpreter state reset commands from the
script being measured.
.\" OPTION: -direct
.TP
\fB\-direct\fR
.
The \fB-direct\fR option causes direct execution of the supplied script,
The \fB\-direct\fR option causes direct execution of the supplied script,
without compilation, in a manner similar to the \fBtime\fR command. It can be
used to measure the cost of \fBTcl_EvalObjEx\fR, of the invocation of canonical
lists, and of the uncompiled versions of bytecoded commands.
.PP
As opposed to the \fBtime\fR commmand, which runs the tested script for a fixed
number of iterations, the timerate command runs it for a fixed time.
As opposed to the \fBtime\fR command, which runs the tested script for a fixed
number of iterations, the \fBtimerate\fR command runs it for a fixed time.
Additionally, the compiled variant of the script will be used during the entire
measurement, as if the script were part of a compiled procedure, if the \fB\-direct\fR
option is not specified. The fixed time period and possibility of compilation allow
for more precise results and prevent very long execution times by slow scripts, making
it practical for measuring scripts with highly uncertain execution times.
measurement, as if the script were part of a compiled procedure,
if the \fB\-direct\fR option is not specified. The fixed time period and
possibility of compilation allow for more precise results and prevent very long
execution times by slow scripts, making it practical for measuring scripts with
highly uncertain execution times.
.SH EXAMPLES
Estimate how fast it takes for a simple Tcl \fBfor\fR loop (including
operations on variable \fIi\fR) to count to ten:
.PP
.CS
\fI# calibrate\fR
\fBtimerate\fR -calibrate {}
112
113
114
115
116
117
118
119
120
121



122
123
124
125
126
127
128
120
121
122
123
124
125
126



127
128
129
130
131
132
133
134
135
136







-
-
-
+
+
+








\fI# measure\fR
\fBtimerate\fR {
    for {set i 0} {$i<10} {incr i} {}
} 5000
.CE
.PP
Estimate the speed of calculating the hour of the day using \fBclock format\fR only,
ignoring overhead of the portion of the script that prepares the time for it to
calculate:
Estimate the speed of calculating the hour of the day using \fBclock format\fR
only, ignoring overhead of the portion of the script that prepares the time for
it to calculate:
.PP
.CS
\fI# calibrate\fR
\fBtimerate\fR -calibrate {}

\fI# estimate overhead\fR
set tm 0

Changes to doc/tm.n.

11
12
13
14
15
16
17
18

19
20
21
22
23
24
25


26
27
28
29
30
31
32
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34







-
+







+
+







.SH NAME
tm \- Facilities for locating and loading of Tcl Modules
.SH SYNOPSIS
.nf
\fB::tcl::tm::path add \fR?\fIpath\fR...?
\fB::tcl::tm::path remove \fR?\fIpath\fR...?
\fB::tcl::tm::path list\fR
\fB::tcl::tm::roots \fR?\fIpath\fR...?
\fB::tcl::tm::roots \fR\fIpaths\fR
.fi
.BE
.SH DESCRIPTION
.PP
This document describes the facilities for locating and loading Tcl
Modules (see \fBMODULE DEFINITION\fR for the definition of a Tcl Module).
The following commands are supported:
.\" COMMAND: path
.\" METHOD: add
.TP
\fB::tcl::tm::path add \fR?\fIpath\fR...?
.
The paths are added at the head to the list of module paths, in order
of appearance. This means that the last argument ends up as the new
head of the list.
.RS
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
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







+





+





+

-
+


-
+







action will be taken.
.PP
Paths are searched later in the order of their appearance in the
list. As they are added to the front of the list they are searched in
reverse order of addition. In other words, the paths added last are
looked at first.
.RE
.\" METHOD: remove
.TP
\fB::tcl::tm::path remove \fR?\fIpath\fR...?
.
Removes the paths from the list of module paths. The command silently
ignores all paths which are not on the list.
.\" METHOD: list
.TP
\fB::tcl::tm::path list\fR
.
Returns a list containing all registered module paths, in the order
that they are searched for modules.
.\" COMMAND: roots
.TP
\fB::tcl::tm::roots \fR?\fIpath\fR...?
\fB::tcl::tm::roots \fR\fIpaths\fR
.
Similar to \fBpath add\fR, and layered on top of it. This command
takes a list of paths, extends each with
takes a single argument containing a list of paths, extends each with
.QW "\fBtcl\fIX\fB/site-tcl\fR" ,
and
.QW "\fBtcl\fIX\fB/\fIX\fB.\fIy\fR" ,
for major version \fIX\fR of the
Tcl interpreter and minor version \fIy\fR less than or equal to the
minor version of the interpreter, and adds the resulting set of paths
to the list of paths to search.
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
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







-
+



-
-
-
-
-
+
+

+
+
+
+



-
+

-
+





variable has been kept only for backward compatibility with the
original specification, i.e. TIP 189.
.PP
These paths are seen and therefore shared by all Tcl shells in the
\fB$::env(PATH)\fR of the user.
.PP
Note that \fIX\fR and \fIy\fR follow the general rules set out
above. In other words, Tcl 8.4, for example, will look at these 10
above. In other words, Tcl 9.1, for example, will look at these 4
environment variables:
.PP
.CS
\fB$::env(TCL8.4_TM_PATH)\fR  \fB$::env(TCL8_4_TM_PATH)\fR
\fB$::env(TCL8.3_TM_PATH)\fR  \fB$::env(TCL8_3_TM_PATH)\fR
\fB$::env(TCL8.2_TM_PATH)\fR  \fB$::env(TCL8_2_TM_PATH)\fR
\fB$::env(TCL8.1_TM_PATH)\fR  \fB$::env(TCL8_1_TM_PATH)\fR
\fB$::env(TCL8.0_TM_PATH)\fR  \fB$::env(TCL8_0_TM_PATH)\fR
\fB$::env(TCL9.1_TM_PATH)\fR  \fB$::env(TCL9_1_TM_PATH)\fR
\fB$::env(TCL9.0_TM_PATH)\fR  \fB$::env(TCL9_0_TM_PATH)\fR
.CE
.PP
Paths initialized from the environment variables undergo tilde
substitution (see \fBfilename\fR). Any path whose tilde substitution
fails because the user is unknown will be omitted from search paths.
.SH "SEE ALSO"
package(n), Tcl Improvement Proposal #189
.QW "\fITcl Modules\fR"
(online at http://tip.tcl.tk/189.html), Tcl Improvement Proposal #190
(online at https://tip.tcl-lang.org/189.html), Tcl Improvement Proposal #190
.QW "\fIImplementation Choices for Tcl Modules\fR"
(online at http://tip.tcl.tk/190.html)
(online at https://tip.tcl-lang.org/190.html)
.SH "KEYWORDS"
modules, package
.\" Local Variables:
.\" mode: nroff
.\" End:

Changes to doc/trace.n.

15
16
17
18
19
20
21

22
23
24
25
26
27
28

29
30
31
32
33
34
35
15
16
17
18
19
20
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36







+






-
+







.SH SYNOPSIS
\fBtrace \fIoption\fR ?\fIarg arg ...\fR?
.BE
.SH DESCRIPTION
.PP
This command causes Tcl commands to be executed whenever certain operations are
invoked.  The legal \fIoption\fRs (which may be abbreviated) are:
.\" METHOD: add
.TP
\fBtrace add \fItype name ops\fR ?\fIargs\fR?
.
Where \fItype\fR is \fBcommand\fR, \fBexecution\fR, or \fBvariable\fR.
.RS
.TP
\fBtrace add command\fR \fIname ops commandPrefix\fR
\fBtrace add command\fI name ops commandPrefix\fR
.
Arrange for \fIcommandPrefix\fR to be executed (with additional arguments)
whenever command \fIname\fR is modified in one of the ways given by the list
\fIops\fR. \fIName\fR will be resolved using the usual namespace resolution
rules used by commands. If the command does not exist, an error will be
thrown.
.RS
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
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







-
+












+




+







of the same type to be evaluated, so a delete trace which itself
deletes the command, or a rename trace which itself renames the
command will not cause further trace evaluations to occur.
Both \fIoldName\fR and \fInewName\fR are fully qualified with any namespace(s)
in which they appear.
.RE
.TP
\fBtrace add execution\fR \fIname ops commandPrefix\fR
\fBtrace add execution\fI name ops commandPrefix\fR
.
Arrange for \fIcommandPrefix\fR to be executed (with additional arguments)
whenever command \fIname\fR is executed, with traces occurring at the points
indicated by the list \fIops\fR.  \fIName\fR will be resolved using the usual
namespace resolution rules used by commands.  If the command does not exist,
an error will be thrown.
.RS
.PP
\fIOps\fR indicates which operations are of interest, and is a list of
one or more of the following items:
.TP
\fBenter\fR
.
Invoke \fIcommandPrefix\fR whenever the command \fIname\fR is executed,
just before the actual execution takes place.
.TP
\fBleave\fR
.
Invoke \fIcommandPrefix\fR whenever the command \fIname\fR is executed,
just after the actual execution takes place.
.TP
\fBenterstep\fR
.
Invoke \fIcommandPrefix\fR for every Tcl command which is executed from the
start of the execution of the procedure \fIname\fR until that
152
153
154
155
156
157
158

159
160
161
162
163
164
165
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169







+







arbitrary command for a \fBenterstep\fR operation), including
all arguments in their fully expanded form.
\fICode\fR gives the result code of that execution, and \fIresult\fR
the result string.
\fIOp\fR indicates what operation is being performed on the
command execution, and is one of \fBleave\fR or \fBleavestep\fR as
defined above.
.PP
Note that the creation of many \fBenterstep\fR or
\fBleavestep\fR traces can lead to unintuitive results, since the
invoked commands from one trace can themselves lead to further
command invocations for other traces.
.PP
\fICommandPrefix\fR executes in the same context as the code that invoked
the traced operation: thus the \fIcommandPrefix\fR, if invoked from a
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
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







+















+







+



+



+














-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+


-
-
-
-







commands are invoked in the original order of creation.
.PP
The behavior of execution traces is currently undefined for a command
\fIname\fR imported into another namespace.
.RE
.TP
\fBtrace add variable\fI name ops commandPrefix\fR
.
Arrange for \fIcommandPrefix\fR to be executed whenever variable \fIname\fR
is accessed in one of the ways given by the list \fIops\fR.  \fIName\fR may
refer to a normal variable, an element of an array, or to an array
as a whole (i.e. \fIname\fR may be just the name of an array, with no
parenthesized index).  If \fIname\fR refers to a whole array, then
\fIcommandPrefix\fR is invoked whenever any element of the array is
manipulated.  If the variable does not exist, it will be created but
will not be given a value, so it will be visible to \fBnamespace which\fR
queries, but not to \fBinfo exists\fR queries.
.RS
.PP
\fIOps\fR indicates which operations are of interest, and is a list of
one or more of the following items:
.TP
\fBarray\fR
.
Invoke \fIcommandPrefix\fR whenever the variable is accessed or modified via
the \fBarray\fR command, provided that \fIname\fR is not a scalar
variable at the time that the \fBarray\fR command is invoked.  If
\fIname\fR is a scalar variable, the access via the \fBarray\fR
command will not trigger the trace.
.TP
\fBread\fR
.
Invoke \fIcommandPrefix\fR whenever the variable is read.
.TP
\fBwrite\fR
.
Invoke \fIcommandPrefix\fR whenever the variable is written.
.TP
\fBunset\fR
.
Invoke \fIcommandPrefix\fR whenever the variable is unset.  Variables
can be unset explicitly with the \fBunset\fR command, or
implicitly when procedures return (all of their local variables
are unset).  Variables are also unset when interpreters are
deleted, but traces will not be invoked because there is no
interpreter in which to execute them.
.PP
When the trace triggers, three arguments are appended to
\fIcommandPrefix\fR so that the actual command is as follows:
.PP
.CS
\fIcommandPrefix name1 name2 op\fR
.CE
.PP
\fIName1\fR and \fIname2\fR give the name(s) for the variable
being accessed:  if the variable is a scalar then \fIname1\fR
gives the variable's name and \fIname2\fR is an empty string;
if the variable is an array element then \fIname1\fR gives the
name of the array and name2 gives the index into the array;
if an entire array is being deleted and the trace was registered
\fIName1\fR gives the name for the variable being accessed.
This is not necessarily the same as the name used in the
\fBtrace add variable\fR command:  the \fBupvar\fR command allows a
procedure to reference a variable under a different name.
If the trace was originally set on an array or array element,
\fIname2\fR provides which index into the array was affected.
This information is present even when \fIname1\fR refers to a
scalar, which may happen if the \fBupvar\fR command was used to
create a reference to a single array element.
If an entire array is being deleted and the trace was registered
on the overall array, rather than a single element, then \fIname1\fR
gives the array name and \fIname2\fR is an empty string.
\fIName1\fR and \fIname2\fR are not necessarily the same as the
name used in the \fBtrace variable\fR command:  the \fBupvar\fR
command allows a procedure to reference a variable under a
different name.
\fIOp\fR indicates what operation is being performed on the
variable, and is one of \fBread\fR, \fBwrite\fR, or \fBunset\fR as
defined above.
.PP
\fICommandPrefix\fR executes in the same context as the code that invoked
the traced operation:  if the variable was accessed as part of a Tcl
procedure, then \fIcommandPrefix\fR will have access to the same local
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
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
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
366
367
368
369
370
371
372
373
374
375
376
377




















378
379
380
381
382
383
384







+


+




+







+







+





+


+




+








+








+







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







until the variable is unset, or until the interpreter is deleted.
Unsetting an element of array will remove any traces on that element,
but will not remove traces on the overall array.
.PP
This command returns an empty string.
.RE
.RE
.\" METHOD: remove
.TP
\fBtrace remove \fItype name opList commandPrefix\fR
.
Where \fItype\fR is either \fBcommand\fR, \fBexecution\fR or \fBvariable\fR.
.RS
.TP
\fBtrace remove command\fI name opList commandPrefix\fR
.
If there is a trace set on command \fIname\fR with the operations and
command given by \fIopList\fR and \fIcommandPrefix\fR, then the trace is
removed, so that \fIcommandPrefix\fR will never again be invoked.  Returns
an empty string.   If \fIname\fR does not exist, the command will throw
an error.
.TP
\fBtrace remove execution\fI name opList commandPrefix\fR
.
If there is a trace set on command \fIname\fR with the operations and
command given by \fIopList\fR and \fIcommandPrefix\fR, then the trace is
removed, so that \fIcommandPrefix\fR will never again be invoked.  Returns
an empty string.   If \fIname\fR does not exist, the command will throw
an error.
.TP
\fBtrace remove variable\fI name opList commandPrefix\fR
.
If there is a trace set on variable \fIname\fR with the operations and
command given by \fIopList\fR and \fIcommandPrefix\fR, then the trace is
removed, so that \fIcommandPrefix\fR will never again be invoked.  Returns
an empty string.
.RE
.\" METHOD: info
.TP
\fBtrace info \fItype name\fR
.
Where \fItype\fR is either \fBcommand\fR, \fBexecution\fR or \fBvariable\fR.
.RS
.TP
\fBtrace info command\fI name\fR
.
Returns a list containing one element for each trace currently set on
command \fIname\fR. Each element of the list is itself a list
containing two elements, which are the \fIopList\fR and \fIcommandPrefix\fR
associated with the trace.  If \fIname\fR does not have any traces set,
then the result of the command will be an empty string.  If \fIname\fR
does not exist, the command will throw an error.
.TP
\fBtrace info execution\fI name\fR
.
Returns a list containing one element for each trace currently set on
command \fIname\fR. Each element of the list is itself a list
containing two elements, which are the \fIopList\fR and \fIcommandPrefix\fR
associated with the trace.  If \fIname\fR does not have any traces set,
then the result of the command will be an empty string.  If \fIname\fR
does not exist, the command will throw an error.
.TP
\fBtrace info variable\fI name\fR
.
Returns a list containing one element for each trace currently set on
variable \fIname\fR.  Each element of the list is itself a list
containing two elements, which are the \fIopList\fR and \fIcommandPrefix\fR
associated with the trace.  If \fIname\fR does not exist or does not
have any traces set, then the result of the command will be an empty
string.
.RE
.PP
For backwards compatibility, three other subcommands are available:
.RS
.TP
\fBtrace variable \fIname ops command\fR
This is equivalent to \fBtrace add variable \fIname ops command\fR.
.TP
\fBtrace vdelete \fIname ops command\fR
This is equivalent to \fBtrace remove variable \fIname ops command\fR
.TP
\fBtrace vinfo \fIname\fR
This is equivalent to \fBtrace info variable \fIname\fR
.RE
.PP
These subcommands are deprecated and will likely be removed in a
future version of Tcl.  They use an older syntax in which \fBarray\fR,
\fBread\fR, \fBwrite\fR, \fBunset\fR are replaced by \fBa\fR, \fBr\fR,
\fBw\fR and \fBu\fR respectively, and the \fIops\fR argument is not a
list, but simply a string concatenation of the operations, such as
\fBrwua\fR.
.SH EXAMPLES
.PP
Print a message whenever either of the global variables \fBfoo\fR and
\fBbar\fR are updated, even if they have a different local name at the
time (which can be done with the \fBupvar\fR command):
.PP
.CS

Changes to doc/transchan.n.

1
2
3
4
5
6
7
8
9
10
11
12
13


14










15
16
17
18
19
20
21
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
30
31
32













+
+
-
+
+
+
+
+
+
+
+
+
+







'\"
'\" Copyright (c) 2008 Donal K. Fellows
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH transchan n 8.6 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
transchan \- command handler API of channel transforms
.SH SYNOPSIS
.nf
\fBchan push \fIchannel cmdPrefix\fR
\fBcmdPrefix \fIoption\fR ?\fIarg arg ...\fR?

\fIcmdPrefix \fBclear \fIhandle\fR
\fIcmdPrefix \fBdrain \fIhandle\fR
\fIcmdPrefix \fBfinalize \fIhandle\fR
\fIcmdPrefix \fBflush \fIhandle\fR
\fIcmdPrefix \fBinitialize \fIhandle mode\fR
\fIcmdPrefix \fBlimit? \fIhandle\fR
\fIcmdPrefix \fBread \fIhandle buffer\fR
\fIcmdPrefix \fBwrite \fIhandle buffer\fR
.fi
.BE
.SH DESCRIPTION
.PP
The Tcl-level handler for a channel transformation has to be a command with
subcommands (termed an \fIensemble\fR despite not implying that it must be
created with \fBnamespace ensemble create\fR; this mechanism is not tied to
\fBnamespace ensemble\fR in any way). Note that \fIcmdPrefix\fR is whatever
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
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







+







+








+








-
-
+
-

-
-
+
-












+














+








+







.PP
Note that in the descriptions below \fIcmdPrefix\fR may be more than one word,
and \fIhandle\fR is the value returned by the \fBchan push\fR call used to
create the transformation.
.SS "GENERIC SUBCOMMANDS"
.PP
The following subcommands are relevant to all types of channel.
.\" METHOD: clear
.TP
\fIcmdPrefix \fBclear \fIhandle\fR
.
This optional subcommand is called to signify to the transformation that any
data stored in internal buffers (either incoming or outgoing) must be
cleared. It is called when a \fBchan seek\fR is performed on the channel being
transformed.
.\" METHOD: finalize
.TP
\fIcmdPrefix \fBfinalize \fIhandle\fR
.
This mandatory subcommand is called last for the given \fIhandle\fR, and then
never again, and it exists to allow for cleaning up any Tcl-level data
structures associated with the transformation. \fIWarning!\fR Any errors
thrown by this subcommand will be ignored. It is not guaranteed to be called
if the interpreter is deleted.
.\" METHOD: initialize
.TP
\fIcmdPrefix \fBinitialize \fIhandle mode\fR
.
This mandatory subcommand is called first, and then never again (for the given
\fIhandle\fR). Its responsibility is to initialize all parts of the
transformation at the Tcl level. The \fImode\fR is a list containing any of
\fBread \fRand \fBwrite\fR.
.RS
.TP
\fBwrite\fR
.IP \fBwrite\fR
.
implies that the channel is writable.
.TP
\fBread\fR
.IP \fBread\fR
.
implies that the channel is readable.
.PP
The return value of the subcommand should be a list containing the names of
all subcommands supported by this handler. Any error thrown by the subcommand
will prevent the creation of the transformation. The thrown error will appear
as error thrown by \fBchan push\fR.
.RE
.SS "READ-RELATED SUBCOMMANDS"
.PP
These subcommands are used for handling transformations applied to readable
channels; though strictly \fBread \fRis optional, it must be supported if any
of the others is or the channel will be made non-readable.
.\" METHOD: drain
.TP
\fIcmdPrefix \fBdrain \fIhandle\fR
.
This optional subcommand is called whenever data in the transformation input
(i.e. read) buffer has to be forced upward, i.e. towards the user or script.
The result returned by the method is taken as the \fIbinary\fR data to push
upward to the level above this transformation (the reader or a higher-level
transformation).
.RS
.PP
In other words, when this method is called the transformation cannot defer the
actual transformation operation anymore and has to transform all data waiting
in its internal read buffers and return the result of that action.
.RE
.\" METHOD: limit?
.TP
\fIcmdPrefix \fBlimit? \fIhandle\fR
.
This optional subcommand is called to allow the Tcl I/O engine to determine
how far ahead it should read. If present, it should return an integer number
greater than zero which indicates how many bytes ahead should be read, or an
integer less than zero to indicate that the I/O engine may read as far ahead
as it likes.
.\" METHOD: read
.TP
\fIcmdPrefix \fBread \fIhandle buffer\fR
.
This subcommand, which must be present if the transformation is to work with
readable channels, is called whenever the base channel, or a transformation
below this transformation, pushes data upward. The \fIbuffer\fR contains the
binary data which has been given to us from below. It is the responsibility of
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
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







+














+







defer the actual transformation until it has more data.
.RE
.SS "WRITE-RELATED SUBCOMMANDS"
.PP
These subcommands are used for handling transformations applied to writable
channels; though strictly \fBwrite\fR is optional, it must be supported if any
of the others is or the channel will be made non-writable.
.\" METHOD: flush
.TP
\fIcmdPrefix \fBflush \fIhandle\fR
.
This optional subcommand is called whenever data in the transformation 'write'
buffer has to be forced downward, i.e. towards the base channel. The result
returned by the subcommand is taken as the binary data to write to the
transformation below the current transformation. This can be the base channel
as well.
.RS
.PP
In other words, when this subcommand is called the transformation cannot defer
the actual transformation operation anymore and has to transform all data
waiting in its internal write buffers and return the result of that action.
.RE
.\" METHOD: write
.TP
\fIcmdPrefix \fBwrite \fIhandle buffer\fR
.
This subcommand, which must be present if the transformation is to work with
writable channels, is called whenever the user, or a transformation above this
transformation, writes data downward. The \fIbuffer\fR contains the binary
data which has been written to us. It is the responsibility of this subcommand

Changes to doc/try.n.

83
84
85
86
87
88
89
90

91
92
93
94
95

















96
97
98
99
100
101
102
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







-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







}
.CE
.PP
Handle different reasons for a file to not be openable for reading:
.PP
.CS
\fBtry\fR {
    set f [open /some/file/name w]
    set f [open /some/file/name r]
} \fBtrap\fR {POSIX EISDIR} {} {
    puts "failed to open /some/file/name: it's a directory"
} \fBtrap\fR {POSIX ENOENT} {} {
    puts "failed to open /some/file/name: it doesn't exist"
}
.CE
.PP
Proc to read a file in utf-8 encoding and return its contents.
The file is closed in success and error case by the finally clause.
It is allowed to call \fBreturn\fR within the \fBtry\fR block.
Remark that with tcl 9, the read command may also throw utf-8 conversion errors:
.PP
.CS
proc readfile {filename} {
    set f [open $filename r]
    \fBtry\fR {
        fconfigure $f -encoding utf-8 -profile strict
        \fBreturn\fR [read $f]
    } \fBfinally\fR {
        close $f
    }
}
.CE
.SH "SEE ALSO"
catch(n), error(n), return(n), throw(n)
.SH "KEYWORDS"
cleanup, error, exception, final, resource management
'\" Local Variables:
'\" mode: nroff

Changes to doc/unknown.n.

43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57







-
+







The result of the \fBunknown\fR command is used as the result for
the original non-existent command.
.PP
The default implementation of \fBunknown\fR behaves as follows.
It first calls the \fBauto_load\fR library procedure to load the command.
If this succeeds, then it executes the original command with its
original arguments.
If the auto-load fails then \fBunknown\fR calls \fBauto_execok\fR
If the auto-load fails and Tcl is run interactively then \fBunknown\fR calls \fBauto_execok\fR
to see if there is an executable file by the name \fIcmd\fR.
If so, it invokes the Tcl \fBexec\fR command
with \fIcmd\fR and all the \fIargs\fR as arguments.
If \fIcmd\fR cannot be auto-executed, \fBunknown\fR checks to
see if the command was invoked at top-level and outside of any
script.  If so, then \fBunknown\fR takes two additional steps.
First, it sees if \fIcmd\fR has one of the following three forms:

Changes to doc/unload.n.

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
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







-
+

-
+








-
+











+





+





+




















-
+

-
-
+
+

-
+









-
-
-
-
+
+
+
+





-
+







.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
unload \- Unload machine code
.SH SYNOPSIS
\fBunload \fR?\fIswitches\fR? \fIfileName\fR
.br
\fBunload \fR?\fIswitches\fR? \fIfileName packageName\fR
\fBunload \fR?\fIswitches\fR? \fIfileName prefix\fR
.br
\fBunload \fR?\fIswitches\fR? \fIfileName packageName interp\fR
\fBunload \fR?\fIswitches\fR? \fIfileName prefix interp\fR
.BE
.SH DESCRIPTION
.PP
This command tries to unload shared libraries previously loaded
with \fBload\fR from the application's address space.  \fIfileName\fR
is the name of the file containing the library file to be unload;  it
must be the same as the filename provided to \fBload\fR for
loading the library.
The \fIpackageName\fR argument is the name of the package (as
The \fIprefix\fR argument is the prefix (as
determined by or passed to \fBload\fR), and is used to
compute the name of the unload procedure; if not supplied, it is
computed from \fIfileName\fR in the same manner as \fBload\fR.
The \fIinterp\fR argument is the path name of the interpreter from
which to unload the package (see the \fBinterp\fR manual entry for
details); if \fIinterp\fR is omitted, it defaults to the
interpreter in which the \fBunload\fR command was invoked.
.PP
If the initial arguments to \fBunload\fR start with \fB\-\fR then
they are treated as switches.  The following switches are
currently supported:
.\" OPTION: -nocomplain
.TP
\fB\-nocomplain\fR
.
Suppresses all error messages. If this switch is given, \fBunload\fR will
never report an error.
.\" OPTION: -keeplibrary
.TP
\fB\-keeplibrary\fR
.
This switch will prevent \fBunload\fR from issuing the operating system call
that will unload the library from the process.
.\" OPTION: --
.TP
\fB\-\|\-\fR
.
Marks the end of switches.  The argument following this one will
be treated as a \fIfileName\fR even if it starts with a \fB\-\fR.
.SS "UNLOAD OPERATION"
.PP
When a file containing a shared library is loaded through the
\fBload\fR command, Tcl associates two reference counts to the library
file. The first counter shows how many times the library has been
loaded into normal (trusted) interpreters while the second describes how many
times the library has been loaded into safe interpreters. As a file containing
a shared library can be loaded only once by Tcl (with the first \fBload\fR
call on the file), these counters track how many interpreters use the library.
Each subsequent call to \fBload\fR after the first simply increments the
proper reference count.
.PP
\fBunload\fR works in the opposite direction. As a first step, \fBunload\fR
will check whether the library is unloadable: an unloadable library exports
a special unload procedure. The name of the unload procedure is determined by
\fIpackageName\fR and whether or not the target interpreter
\fIprefix\fR and whether or not the target interpreter
is a safe one.  For normal interpreters the name of the initialization
procedure will have the form \fIpkg\fB_Unload\fR, where \fIpkg\fR
is the same as \fIpackageName\fR except that the first letter is
procedure will have the form \fIpfx\fB_Unload\fR, where \fIpfx\fR
is the same as \fIprefix\fR except that the first letter is
converted to upper case and all other letters
are converted to lower case.  For example, if \fIpackageName\fR is
are converted to lower case.  For example, if \fIprefix\fR is
\fBfoo\fR or \fBFOo\fR, the initialization procedure's name will
be \fBFoo_Unload\fR.
If the target interpreter is a safe interpreter, then the name
of the initialization procedure will be \fIpkg\fB_SafeUnload\fR
instead of \fIpkg\fB_Unload\fR.
.PP
If \fBunload\fR determines that a library is not unloadable (or unload
functionality has been disabled during compilation), an error will be returned.
If the library is unloadable, then \fBunload\fR will call the unload
procedure. If the unload procedure returns \fBTCL_OK\fR, \fBunload\fR will proceed
and decrease the proper reference count (depending on the target interpreter
type). When both reference counts have reached 0, the library will be
detached from the process.
procedure. If the unload procedure returns \fBTCL_OK\fR, \fBunload\fR will
proceed and decrease the proper reference count (depending on the target
interpreter type). When both reference counts have reached 0, the library will
be detached from the process.
.SS "UNLOAD HOOK PROTOTYPE"
.PP
The unload procedure must match the following prototype:
.PP
.CS
typedef int \fBTcl_PackageUnloadProc\fR(
typedef int \fBTcl_LibraryUnloadProc\fR(
        Tcl_Interp *\fIinterp\fR,
        int \fIflags\fR);
.CE
.PP
The \fIinterp\fR argument identifies the interpreter from which the
library is to be unloaded.  The unload procedure must return
\fBTCL_OK\fR or \fBTCL_ERROR\fR to indicate whether or not it completed
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
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







-
+


-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+


-
+







library is used only by the target interpreter and the library will be
detached from the application as soon as the unload procedure returns,
the \fIflags\fR argument will be set to \fBTCL_UNLOAD_DETACH_FROM_PROCESS\fR.
.SS NOTES
.PP
The \fBunload\fR command cannot unload libraries that are statically
linked with the application.
If \fIfileName\fR is an empty string, then the \fIpackageName\fR argument must
If \fIfileName\fR is an empty string, then the \fIprefix\fR argument must
be specified.
.PP
If \fIpackageName\fR is omitted or specified as an empty string,
Tcl tries to guess the name of the package.
This may be done differently on different platforms.
The default guess, which is used on most UNIX platforms, is to
take the last element of \fIfileName\fR, strip off the first
three characters if they are \fBlib\fR, and use any following
alphabetic and underline characters as the module name.
For example, the command \fBunload libxyz4.2.so\fR uses the module
name \fBxyz\fR and the command \fBunload bin/last.so {}\fR uses the
module name \fBlast\fR.
If \fIprefix\fR is omitted or specified as an empty string,
Tcl tries to guess the prefix. This may be done differently on
different platforms. The default guess, which is used on most
UNIX platforms, is to take the last element of
\fIfileName\fR, strip off the first three characters if they
are \fBlib\fR, then strip off the next three characters if they
are \fBtcl9\fR, and use any following wordchars but not digits,
converted to titlecase as the prefix.
For example, the command \fBunload libxyz4.2.so\fR uses the prefix
\fBXyz\fR and the command \fBunload bin/last.so {}\fR uses the
prefix \fBLast\fR.
.SH "PORTABILITY ISSUES"
.TP
\fBUnix\fR\0\0\0\0\0
\fBUnix\fR
.
Not all unix operating systems support library unloading. Under such
an operating system \fBunload\fR returns an error (unless \fB\-nocomplain\fR
has been specified).
.SH BUGS
.PP
If the same file is \fBload\fRed by different \fIfileName\fRs, it will

Changes to doc/uplevel.n.

22
23
24
25
26
27
28
29


30
31
32
33
34
35
36
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36
37







-
+
+







the result of that evaluation.
.PP
If \fIlevel\fR is an integer then
it gives a distance (up the procedure calling stack) to move before
executing the command.  If \fIlevel\fR consists of \fB#\fR followed by
a integer then the level gives an absolute level.  If \fIlevel\fR
is omitted then it defaults to \fB1\fR.  \fILevel\fR cannot be
defaulted if the first \fIcommand\fR argument is an integer or starts with \fB#\fR.
defaulted if the first \fIcommand\fR argument is an integer or starts
with \fB#\fR.
.PP
For example, suppose that procedure \fBa\fR was invoked
from top-level, and that it called \fBb\fR, and that \fBb\fR called \fBc\fR.
Suppose that \fBc\fR invokes the \fBuplevel\fR command.  If \fIlevel\fR
is \fB1\fR or \fB#2\fR  or omitted, then the command will be executed
in the variable context of \fBb\fR.  If \fIlevel\fR is \fB2\fR or \fB#1\fR
then the command will be executed in the variable context of \fBa\fR.

Changes to doc/upvar.n.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
10
11
12
13
14
15
16

17
18
19
20
21
22
23







-







.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
upvar \- Create link to variable in a different stack frame
.SH SYNOPSIS
\fBupvar \fR?\fIlevel\fR? \fIotherVar myVar \fR?\fIotherVar myVar \fR...?
.BE

.SH DESCRIPTION
.PP
This command arranges for one or more local variables in the current
procedure to refer to variables in an enclosing procedure call or
to global variables.
\fILevel\fR may have any of the forms permitted for the \fBuplevel\fR
command, and may be omitted (it defaults to \fB1\fR).
90
91
92
93
94
95
96
97

98
99
100
101
102



103
104
105
106
107
108
109
110
111
112
89
90
91
92
93
94
95

96
97
98
99


100
101
102



103
104
105
106
107
108
109







-
+



-
-
+
+
+
-
-
-







    puts $name
}
proc \fIsetByUpvar\fR { name value } {
    \fBupvar\fR $name localVar
    set localVar $value
}
set originalVar 1
trace variable originalVar w \fItraceproc\fR
trace add variable originalVar write \fItraceproc\fR
\fIsetByUpvar\fR originalVar 2
.CE
.PP
If \fIotherVar\fR refers to an element of an array, then variable
traces set for the entire array will not be invoked when \fImyVar\fR
If \fIotherVar\fR refers to an element of an array, then the element
name is passed as the second argument to the trace procedure. This
may be important information in case of traces set on an entire array.
is accessed (but traces on the particular element will still be
invoked).  In particular, if the array is \fBenv\fR, then changes
made to \fImyVar\fR will not be passed to subprocesses correctly.
.SH EXAMPLE
A \fBdecr\fR command that works like \fBincr\fR except it subtracts
the value from the variable instead of adding it:
.PP
.CS
proc decr {varName {decrement 1}} {
    \fBupvar\fR 1 $varName var

Changes to doc/vwait.n.

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
30
31
32
33
34
35
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
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













-
+
+
+












+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+







'\"
'\" Copyright (c) 1995-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH vwait n 8.0 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
vwait \- Process events until a variable is written
.SH SYNOPSIS
\fBvwait\fR \fIvarName\fR
\fBvwait\fI varName\fR
.sp
\fBvwait\fR ?\fIoptions\fR? ?\fIvarName ...\fR?
.BE
.SH DESCRIPTION
.PP
This command enters the Tcl event loop to process events, blocking
the application if no events are ready.  It continues processing
events until some event handler sets the value of the global variable
\fIvarName\fR.  Once \fIvarName\fR has been set, the \fBvwait\fR
command will return as soon as the event handler that modified
\fIvarName\fR completes.  The \fIvarName\fR argument is always interpreted as
a variable name with respect to the global namespace, but can refer to any
namespace's variables if the fully-qualified name is given.
.PP
In the second more complex command form \fIoptions\fR allow for finer
control of the wait operation and to deal with multiple event sources.
\fIOptions\fR can be made up of:
.\" OPTION: --
.TP
\fB\-\-\fR
.
Marks the end of options. All following arguments are handled as
variable names.
.\" OPTION: -all
.TP
\fB\-all\fR
.
All conditions for the wait operation must be met to complete the
wait operation. Otherwise (the default) the first event completes
the wait.
.\" OPTION: -extended
.TP
\fB\-extended\fR
.
An extended result in list form is returned, see below for explanation.
.\" OPTION: -nofileevents
.TP
\fB\-nofileevents\fR
.
File events are not handled in the wait operation.
.\" OPTION: -noidleevents
.TP
\fB\-noidleevents\fR
.
Idle handlers are not invoked during the wait operation.
.\" OPTION: -notimerevents
.TP
\fB\-notimerevents\fR
.
Timer handlers are not serviced during the wait operation.
.\" OPTION: -nowindowevents
.TP
\fB\-nowindowevents\fR
.
Events of the windowing system are not handled during the wait operation.
.\" OPTION: -readable
.TP
\fB\-readable\fI channel\fR
.
\fIChannel\fR must name a Tcl channel open for reading. If \fIchannel\fR
is or becomes readable the wait operation completes.
.\" OPTION: -timeout
.TP
\fB\-timeout\fI milliseconds\fR
.
The wait operation is constrained to \fImilliseconds\fR.
.\" OPTION: -variable
.TP
\fB\-variable\fI varName\fR
.
\fIVarName\fR must be the name of a global variable. Writing or
unsetting this variable completes the wait operation.
.\" OPTION: -writable
.TP
\fB\-writable\fI channel\fR
.
\fIChannel\fR must name a Tcl channel open for writing. If \fIchannel\fR
is or becomes writable the wait operation completes.
.PP
The result returned by \fBvwait\fR is for the simple form an empty
string. If the \fB\-timeout\fR option is specified, the result is the
number of milliseconds remaining when the wait condition has been
met, or -1 if the wait operation timed out.
.PP
If the \fB\-extended\fR option is specified, the result is made up
of a Tcl list with an even number of elements. Odd elements
take the values \fBreadable\fR, \fBtimeleft\fR, \fBvariable\fR,
and \fBwritable\fR. Even elements are the corresponding variable
and channel names or the remaining number of milliseconds.
The list is ordered by the occurrences of the event(s) with the
exception of \fBtimeleft\fR which always comes last.
.PP
In some cases the \fBvwait\fR command may not return immediately
after \fIvarName\fR is set.  This happens if the event handler
after \fIvarName\fR et.al. is set. This happens if the event handler
that sets \fIvarName\fR does not complete immediately.  For example,
if an event handler sets \fIvarName\fR and then itself calls
\fBvwait\fR to wait for a different variable, then it may not return
for a long time.  During this time the top-level \fBvwait\fR is
blocked waiting for the event handler to complete, so it cannot
return either. (See the \fBNESTED VWAITS BY EXAMPLE\fR below.)
.PP

Changes to doc/while.n.

26
27
28
29
30
31
32
33

34
35
36
37
38
39
40
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40







-
+







evaluates to a false boolean value.  \fBContinue\fR
commands may be executed inside \fIbody\fR to terminate the current
iteration of the loop, and \fBbreak\fR
commands may be executed inside \fIbody\fR to cause immediate
termination of the \fBwhile\fR command.  The \fBwhile\fR command
always returns an empty string.
.PP
Note: \fItest\fR should almost always be enclosed in braces.  If not,
Note that \fItest\fR should almost always be enclosed in braces.  If not,
variable substitutions will be made before the \fBwhile\fR
command starts executing, which means that variable changes
made by the loop body will not be considered in the expression.
This is likely to result in an infinite loop.  If \fItest\fR is
enclosed in braces, variable substitutions are delayed until the
expression is evaluated (before
each loop iteration), so changes in the variables will be visible.

Changes to doc/zipfs.3.

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
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
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
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








-
+



-
+


-
-
+
+


-
+


-
+


-
+



















-
+

















-
-
+
+
-


-
+



-
+

-
+






-
-
+
+


-
+

-
+

-
-
-
+
+
+
+
-
-
+

+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
+
+
-
-
-
+
+
-
+
+

-
+









'\"
'\" Copyright (c) 2015 Jan Nijtmans <jan.nijtmans@gmail.com>
'\" Copyright (c) 2015 Christian Werner <chw@ch-werner.de>
'\" Copyright (c) 2017 Sean Woods <yoda@etoyoc.com>
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH Tclzipfs 3 8.7 Tcl "Tcl Library Procedures"
.TH Tclzipfs 3 9.0 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
TclZipfs_AppHook, Tclzipfs_Mount, TclZipfs_MountBuffer, Tclzipfs_Unmount \- handle ZIP files as Tcl virtual filesystems
TclZipfs_AppHook, TclZipfs_Mount, TclZipfs_MountBuffer, TclZipfs_Unmount \- handle ZIP files as Tcl virtual filesystems
.SH SYNOPSIS
.nf
int
\fBTclZipfs_AppHook(\fIargcPtr, argvPtr\fR)
const char *
\fBTclZipfs_AppHook\fR(\fIargcPtr, argvPtr\fR)
.sp
int
\fBTclzipfs_Mount\fR(\fIinterp, mountpoint, zipname, password\fR)
\fBTclZipfs_Mount\fR(\fIinterp, zipname, mountpoint, password\fR)
.sp
int
\fBTclZipfs_MountBuffer\fR(\fIinterp, mountpoint, data, dataLen, copy\fR)
\fBTclZipfs_MountBuffer\fR(\fIinterp, data, dataLen, mountpoint, copy\fR)
.sp
int
\fBTclzipfs_Unmount\fR(\fIinterp, mountpoint\fR)
\fBTclZipfs_Unmount\fR(\fIinterp, mountpoint\fR)
.fi
.SH ARGUMENTS
.AS Tcl_Interp *mountpoint in
.AP "int" *argcPtr in
Pointer to a variable holding the number of command line arguments from
\fBmain\fR().
.AP "char" ***argvPtr in
Pointer to an array of strings containing the command line arguments to
\fBmain\fR().
.AP Tcl_Interp *interp in
Interpreter in which the ZIP file system is mounted.  The interpreter's result is
modified to hold the result or error message from the script.
.AP "const char" *zipname in
Name of a ZIP file. Must not be NULL when either mounting or unmounting a ZIP.
.AP "const char" *mountpoint in
Name of a mount point, which must be a legal Tcl file or directory name. May
be NULL to query current mount points.
.AP "const char" *password in
An (optional) password. Use NULL if no password is wanted to read the file.
.AP "unsigned char" *data in
.AP "const void" *data in
A data buffer to mount. The data buffer must hold the contents of a ZIP
archive, and must not be NULL.
.AP size_t dataLen in
The number of bytes in the supplied data buffer argument, \fIdata\fR.
.AP int copy in
If non-zero, the ZIP archive in the data buffer will be internally copied
before mounting, allowing the data buffer to be disposed once
\fBTclZipfs_MountBuffer\fR returns. If zero, the caller guarantees that the
buffer will be valid to read from for the duration of the mount.
.BE
.SH DESCRIPTION
\fBTclZipfs_AppHook\fR is a utility function to perform standard application
initialization procedures, taking into account available ZIP archives as
follows:
.IP [1]
If the current application has a mountable ZIP archive, that archive is
mounted under \fIZIPFS_VOLUME\fB/app\fR as a read-only Tcl virtual file
system. \fIZIPFS_VOLUME\fR is usually \fB//zipfs:\fR on all platforms, but
\fBzipfs:\fR may also be used on Windows (due to differences in the
system (VFS). The value of \fIZIPFS_VOLUME\fR can be retrieved using the
Tcl command \fBzipfs root\fR.
platform's filename parsing).
.IP [2]
If a file named \fBmain.tcl\fR is located in the root directory of that file
system (i.e., at \fIZIPROOT\fB/app/main.tcl\fR after the ZIP archive is
system (i.e., at \fIZIPFS_VOLUME\fB/app/main.tcl\fR after the ZIP archive is
mounted as described above) it is treated as the startup script for the
process.
.IP [3]
If the file \fIZIPROOT\fB/app/tcl_library/init.tcl\fR is present, the
If the file \fIZIPFS_VOLUME\fB/app/tcl_library/init.tcl\fR is present, the
\fBtcl_library\fR global variable in the initial Tcl interpreter is set to
\fIZIPROOT\fB/app/tcl_library\fR.
\fIZIPFS_VOLUME\fB/app/tcl_library\fR.
.IP [4]
If the directory \fBtcl_library\fR was not found in the main application
mount, the system will then search for it as either a VFS attached to the
application dynamic library, or as a zip archive named
\fBlibtcl_\fImajor\fB_\fIminor\fB_\fIpatchlevel\fB.zip\fR either in the
present working directory or in the standard Tcl install location. (For
example, the Tcl 8.7.2 release would be searched for in a file
\fBlibtcl_8_7_2.zip\fR.) That archive, if located, is also mounted read-only.
example, the Tcl 9.0.2 release would be searched for in a file
\fBlibtcl_9_0_2.zip\fR.) That archive, if located, is also mounted read-only.
.PP
On Windows, \fBTclZipfs_AppHook\fR has a slightly different signature, since
it uses WCHAR instead of char. As a result, it requires your application to
it uses WCHAR instead of char. As a result, it requires the application to
be compiled with the UNICODE preprocessor symbol defined (e.g., via the
\fB-DUNICODE\fR compiler flag).
\fB\-DUNICODE\fR compiler flag).
.PP
The result of \fBTclZipfs_AppHook\fR is a Tcl result code (e.g., \fBTCL_OK\fR
when the function is successful). The function \fImay\fR modify the variables
pointed to by \fIargcPtr\fR and \fIargvPtr\fR to remove arguments; the
The result of \fBTclZipfs_AppHook\fR is the full Tcl version with build
information (e.g., \fB9.0.0+abcdef...abcdef.gcc-1002\fR).
The function \fImay\fR modify the variables pointed to by \fIargcPtr\fR and
\fIargvPtr\fR to remove arguments; the current implementation does not do so,
current implementation does not do so, but callers \fIshould not\fR assume
that this will be true in the future.
but callers \fIshould not\fR assume that this will be true in the future.
.PP
\fBTclZipfs_Mount\fR is used to mount ZIP archives and to retrieve information
about currently mounted archives. If \fImountpoint\fR and \fIzipname\fR are both
\fBTclzipfs_Mount\fR mounts the ZIP archive \fIzipname\fR on the mount point
given in \fImountpoint\fR using the optional ZIP password \fIpassword\fR.
Errors during that process are reported in the interpreter \fIinterp\fR.  If
\fImountpoint\fR is a NULL pointer, information on all currently mounted ZIP
file systems is written into \fIinterp\fR's result as a sequence of mount
points and ZIP file names.  The result of this call is a standard Tcl result
specified (i.e. non-NULL), the function mounts the ZIP archive \fIzipname\fR on
the mount point given in \fImountpoint\fR. If \fIpassword\fR is not NULL, it
should point to the NUL terminated password protecting the archive. If not under
the zipfs file system root, \fImountpoint\fR is normalized with respect to it.
For example, a mount point passed as either \fBmt\fR or \fB/mt\fR would be
normalized to \fB//zipfs:/mt\fR, given that \fIZIPFS_VOLUME\fR as returned
by \fBzipfs root\fR is
.QW //zipfs:/ .
An error is raised if the mount point includes
a drive or UNC volume. On success, \fIinterp\fR's result is set to the
normalized mount point path.
.PP
If \fImountpoint\fR is a NULL pointer, information on all currently mounted ZIP
file systems is stored in \fIinterp\fR's result as a sequence of mount
points and ZIP file names.
.PP
If \fImountpoint\fR is not NULL but \fIzipfile\fR
is NULL, the path to the archive mounted at that mount point is stored
as \fIinterp\fR's result. The function returns a standard Tcl result
code.
.PP
\fBTclzipfs_MountBuffer\fR mounts the ZIP archive in the buffer pointed to by
\fIdata\fR on the mount point given in \fImountpoint\fR. The ZIP archive is
\fBTclZipfs_MountBuffer\fR mounts the ZIP archive content \fIdata\fR on the
mount point given in \fImountpoint\fR. Both \fImountpoint\fR and \fIdata\fR must
assumed to be not password protected.  Errors during that process are reported
in the interpreter \fIinterp\fR. The \fIcopy\fR argument determines whether
the buffer is internally copied before mounting or not. The result of this
be specified as non-NULL. The \fIcopy\fR argument determines whether the buffer
is internally copied before mounting or not. The ZIP archive is assumed to be
call is a standard Tcl result code.
not password protected. On success, \fIinterp\fR's result is set to the
normalized mount point path.
.PP
\fBTclzipfs_Unmount\fR undoes the effect of \fBTclzipfs_Mount\fR, i.e., it
\fBTclZipfs_Unmount\fR undoes the effect of \fBTclZipfs_Mount\fR, i.e., it
unmounts the mounted ZIP file system that was mounted from \fIzipname\fR (at
\fImountpoint\fR). Errors are reported in the interpreter \fIinterp\fR.  The
result of this call is a standard Tcl result code.
.PP
\fBTclZipfs_AppHook\fR can not be used in stub-enabled extensions.
.SH "SEE ALSO"
zipfs(n)
.SH KEYWORDS
compress, filesystem, zip

Changes to doc/zipfs.n.

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
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







-
-
-
-
-
-
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+

-
+

-
-



-
-
-
+
+
+
+


+
+
+
+
+
+
+
+
+

-
+




-
-
+
+

-
+


+

-
+

-
+
-
-
-
+
+
+
+

-
+













-
-
+
+
+

+



-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+
+
-


+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+








+
+
+
+
+
+




-
-
-
+
+
+
-




+
+



+

-
+





-
+






+

-
+



-
+
+




-
-
+
+
+



+
+








-
-
+
+
+
+
+
+
+
+
+
+
+

+

-
+



+

-
+





+

-
+





+
+
+
+
+









-
+





-
+







.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
zipfs \- Mount and work with ZIP files within Tcl
.SH SYNOPSIS
.nf
\fBpackage require zipfs \fR?\fB1.0\fR?
.sp
\fBzipfs canonical\fR ?\fImntpnt\fR? \fIfilename\fR ?\fIZIPFS\fR?
\fBzipfs exists\fR \fIfilename\fR
\fBzipfs find\fR \fIdirectoryName\fR
\fBzipfs info\fR \fIfilename\fR
\fBzipfs canonical\fR ?\fImountpoint\fR? \fIfilename\fR
\fBzipfs exists\fI filename\fR
\fBzipfs find\fI directoryName\fR
\fBzipfs info\fI filename\fR
\fBzipfs list\fR ?(\fB\-glob\fR|\fB\-regexp\fR)? ?\fIpattern\fR?
\fBzipfs lmkimg\fR \fIoutfile inlist\fR ?\fIpassword infile\fR?
\fBzipfs lmkzip\fR \fIoutfile inlist\fR ?\fIpassword\fR?
\fBzipfs mkimg\fR \fIoutfile indir\fR ?\fIstrip\fR? ?\fIpassword\fR? ?\fIinfile\fR?
\fBzipfs mkkey\fR \fIpassword\fR
\fBzipfs mkzip\fR \fIoutfile indir\fR ?\fIstrip\fR? ?\fIpassword\fR?
\fBzipfs mount\fR ?\fImountpoint\fR? ?\fIzipfile\fR? ?\fIpassword\fR?
\fBzipfs lmkimg\fI outfile inlist\fR ?\fIpassword\fR? ?\fIinfile\fR?
\fBzipfs lmkzip\fI outfile inlist\fR ?\fIpassword\fR?
\fBzipfs mkimg\fI outfile indir\fR ?\fIstrip\fR? ?\fIpassword\fR? ?\fIinfile\fR?
\fBzipfs mkkey\fI password\fR
\fBzipfs mkzip\fI outfile indir\fR ?\fIstrip\fR? ?\fIpassword\fR?
\fBzipfs mount\fR ?\fIzipfile\fR? ?\fImountpoint\fR? ?\fIpassword\fR?
\fBzipfs mountdata\fR \fIdata\fR \fImountpoint\fR
\fBzipfs root\fR
\fBzipfs unmount\fR \fImountpoint\fR
\fBzipfs unmount\fI mountpoint\fR
.fi
'\" The following subcommand is *UNDOCUMENTED*
'\" \fBzipfs mount_data\fR ?\fImountpoint\fR? ?\fIdata\fR?
.BE
.SH DESCRIPTION
.PP
The \fBzipfs\fR command (the sole public command provided by the built-in
package with the same name) provides Tcl with the ability to mount the
contents of a ZIP archive file as a virtual file system. ZIP archives support
The \fBzipfs\fR command provides Tcl with the ability to mount the
contents of a ZIP archive file as a virtual file system. Tcl's ZIP
archive support is limited to basic features and options.
Supported storage methods include only STORE and DEFLATE with optional
simple encryption, sufficient to prevent casual inspection of their contents
but not able to prevent access by even a moderately determined attacker.
Strong encryption, multi-part archives, platform metadata,
zip64 formats and other compression methods like bzip2 are not supported.
.PP
Files within mounted archives can be written to but new files or directories
cannot be created. Further, modifications to files are limited to the
mounted archive in memory and are not persisted to disk.
.PP
Paths in mounted archives are case-sensitive on all platforms.
.\" METHOD: canonical
.TP
\fBzipfs canonical\fR ?\fImountpoint\fR? \fIfilename\fR ?\fIinZipfs\fR?
\fBzipfs canonical\fR ?\fImountpoint\fR? \fIfilename\fR
.
This takes the name of a file, \fIfilename\fR, and produces where it would be
mapped into a zipfs mount as its result. If specified, \fImountpoint\fR says
within which mount the mapping will be done; if omitted, the main root of the
zipfs system is used. The \fIinZipfs\fR argument is a an optional boolean
which controls whether to fully canonicalise the name; it defaults to true.
zipfs system is used.
.\" METHOD: exists
.TP
\fBzipfs exists\fR \fIfilename\fR
\fBzipfs exists\fI filename\fR
.
Return 1 if the given filename exists in the mounted zipfs and 0 if it does not.
.\" METHOD: find
.TP
\fBzipfs find\fR \fIdirectoryName\fR
\fBzipfs find\fI directoryName\fR
.
Recursively lists files including and below the directory \fIdirectoryName\fR.
Returns the list of paths under directory \fIdirectoryName\fR which need not be
The result list consists of relative path names starting from the given
directory. This command is also used by the \fBzipfs mkzip\fR and \fBzipfs
mkimg\fR commands.
within a zipfs mounted archive. The paths are prefixed with \fIdirectoryName\fR.
This command is also used by the \fBzipfs mkzip\fR and \fBzipfs mkimg\fR
commands.
.\" METHOD: info
.TP
\fBzipfs info\fR \fIfile\fR
\fBzipfs info\fI file\fR
.
Return information about the given \fIfile\fR in the mounted zipfs.  The
information consists of:
.RS
.IP (1)
the name of the ZIP archive file that contains the file,
.IP (2)
the size of the file after decompressions,
.IP (3)
the compressed size of the file, and
.IP (4)
the offset of the compressed data in the ZIP archive file.
.PP
Note: querying the mount point gives the start of the zip data as the offset
in (4), which can be used to truncate the zip information from an executable.
As a special case, querying the mount point gives the start of the zip data
as the offset in (4), which can be used to truncate the zip information from
an executable. Querying an ancestor of a mount point will raise an error.
.RE
.\" METHOD: list
.TP
\fBzipfs list\fR ?(\fB\-glob\fR|\fB\-regexp\fR)? ?\fIpattern\fR?
.
Return a list of all files in the mounted zipfs, or just those matching
\fIpattern\fR (optionally controlled by the option parameters).  The order of
the names in the list is arbitrary.
If \fIpattern\fR is not specified, the command returns a list of files across
all zipfs mounted archives. If \fIpattern\fR is specified, only those paths
matching the pattern are returned. By default, or with the \fB\-glob\fR option,
the pattern is treated as a glob pattern and matching is done as described for
the \fBstring match\fR command. Alternatively, the \fB\-regexp\fR option may be
used to specify matching \fBpattern\fR as a regular expression. The file names
are returned in arbitrary order. Note that path separators are treated as
ordinary characters in the matching. Thus forward slashes should be used
as path separators in the pattern. The returned paths only include those
actually in the archive and does not include intermediate directories in
mount paths.
.\" METHOD: mount
.TP
\fBzipfs mount ?\fImountpoint\fR? ?\fIzipfile\fR? ?\fIpassword\fR?
.
The \fBzipfs mount\fR command mounts a ZIP archive file as a Tcl virtual
filesystem at \fImountpoint\fR.  After this command executes, files contained
\fBzipfs mount\fR
.TP
\fBzipfs mount\fI mountpoint\fR
.TP
\fBzipfs mount\fI zipfile mountpoint\fR ?\fIpassword\fR?
in \fIzipfile\fR will appear to Tcl to be regular files at the mount point.
.RS
.PP
The \fBzipfs mount\fR command mounts ZIP archives as Tcl virtual file systems
and returns information about current mounts.
.PP
With no arguments, the command returns a dictionary mapping
mount points to the path of the corresponding ZIP archive.
.PP
In the single argument form, the command returns the file path
of the ZIP archive mounted at the specified mount point.
.PP
In the third form, the command mounts the ZIP archive \fIzipfile\fR as a Tcl
With no \fIzipfile\fR, returns the zipfile mounted at \fImountpoint\fR.  With
no \fImountpoint\fR, return all zipfile/mount pairs.  If \fImountpoint\fR is
specified as an empty string, mount on file path.
virtual filesystem at \fImountpoint\fR.  After this command executes, files
contained in \fIzipfile\fR will appear to Tcl to be regular files at the
mount point. If \fImountpoint\fR is
specified as an empty string, it is defaulted to the \fB[zipfs root]\fR.
The command returns the normalized mount point path.
.PP
If not under the zipfs file system root, \fImountpoint\fR is normalized with
respect to it. For example, a mount point passed as either \fBmt\fR or \fB/mt\fR
would be normalized to \fB//zipfs:/mt\fR (given that \fBzipfs root\fR
returns
.QW //zipfs:/ ).
An error is raised if the mount point includes a drive or UNC volume.
.PP
\fBNB:\fR because the current working directory is a concept maintained by the
operating system, using \fBcd\fR into a mounted archive will only work in the
current process, and then not entirely consistently (e.g., if a shared library
uses direct access to the OS rather than through Tcl's filesystem API, it will
not see the current directory as being inside the mount and will not be able
to access the files inside the mount).
.RE
.\" METHOD: mountdata
.TP
\fBzipfs mountdata\fR \fIdata\fR \fImountpoint\fR
Mounts the ZIP archive content \fIdata\fR as a Tcl virtual filesystem at
\fImountpoint\fR.
.\" METHOD: root
.TP
\fBzipfs root\fR
.
Returns a constant string which indicates the mount point for zipfs volumes
for the current platform. On Windows, this value is
.QW \fBzipfs:/\fR .
On Unix, this value is
for the current platform. User should not rely on the mount point being
the same constant string for all platforms.
.\" METHOD: unmount
.QW \fB//zipfs:/\fR .
.TP
\fBzipfs unmount \fImountpoint\fR
.
Unmounts a previously mounted ZIP archive mounted to \fImountpoint\fR.
The command will fail with an error exception if
there are any files within the mounted archive are open.
.SS "ZIP CREATION COMMANDS"
This package also provides several commands to aid the creation of ZIP
archives as Tcl applications.
.\" METHOD: mkzip
.TP
\fBzipfs mkzip\fR \fIoutfile indir\fR ?\fIstrip\fR? ?\fIpassword\fR?
\fBzipfs mkzip\fI outfile indir\fR ?\fIstrip\fR? ?\fIpassword\fR?
.
Creates a ZIP archive file named \fIoutfile\fR from the contents of the input
directory \fIindir\fR (contained regular files only) with optional ZIP
password \fIpassword\fR. While processing the files below \fIindir\fR the
optional file name prefix given in \fIstrip\fR is stripped off the beginning
of the respective file name.  When stripping, it is common to remove either
of the respective file name if non-empty.  When stripping, it is common to remove either
the whole source directory name or the name of its parent directory.
.RS
.PP
\fBCaution:\fR the choice of the \fIindir\fR parameter (less the optional
stripped prefix) determines the later root name of the archive's content.
.RE
.\" METHOD: mkimg
.TP
\fBzipfs mkimg\fR \fIoutfile indir\fR ?\fIstrip\fR? ?\fIpassword\fR? ?\fIinfile\fR?
\fBzipfs mkimg\fI outfile indir\fR ?\fIstrip\fR? ?\fIpassword\fR? ?\fIinfile\fR?
.
Creates an image (potentially a new executable file) similar to \fBzipfs
mkzip\fR; see that command for a description of most parameters to this
command, as they behave identically here.
command, as they behave identically here. If \fIoutfile\fR exists, it will
be silently overwritten.
.RS
.PP
If the \fIinfile\fR parameter is specified, this file is prepended in front of
the ZIP archive, otherwise the file returned by \fBinfo nameofexecutable\fR
(i.e., the executable file of the running process) is used. If the
\fIpassword\fR parameter is not empty, an obfuscated version of that password
(i.e., the executable file of the running process,
typically \fBwish\fR or \fBtclsh\fR) is used. If the
\fIpassword\fR parameter is not the empty string, an obfuscated version of that password
(see \fBzipfs mkkey\fR) is placed between the image and ZIP chunks of the
output file and the contents of the ZIP chunk are protected with that
password.
If the starting image has a ZIP archive already attached to it, it is removed
from the copy in \fIoutfile\fR before the new ZIP archive is added.
.PP
If there is a file, \fBmain.tcl\fR, in the root directory of the resulting
archive and the image file that the archive is attached to is a \fBtclsh\fR
(or \fBwish\fR) instance (true by default, but depends on your configuration),
then the resulting image is an executable that will \fBsource\fR the script in
that \fBmain.tcl\fR after mounting the ZIP archive, and will \fBexit\fR once
that script has been executed.
.PP
\fBCaution:\fR highly experimental, not usable on Android, only partially
tested on Linux and Windows.
\fBNote:\fR \fBtclsh\fR and \fBwish\fR can be built using either
dynamic binding or static binding of the core implementation
libraries. With a dynamic binding, the base application Tcl_Library
contents are attached to the \fBlibtcl\fR and \fBlibtk\fR shared
library, respectively. With a static binding, the Tcl_Library
contents, etc., are attached to the application, \fBtclsh\fR or
\fBwish\fR. When using \fBmkimg\fR with a statically built tclsh, it is
the user's responsibility to preserve the attached archive by first
extracting it to a temporary location, and then add whatever
additional files desired, before creating and attaching the new
archive to the new application.
.RE
.\" METHOD: mkkey
.TP
\fBzipfs mkkey\fR \fIpassword\fR
\fBzipfs mkkey\fI password\fR
.
Given the clear text \fIpassword\fR argument, an obfuscated string version is
returned with the same format used in the \fBzipfs mkimg\fR command.
.\" METHOD: lmkimg
.TP
\fBzipfs lmkimg\fR \fIoutfile inlist\fR ?\fIpassword infile\fR?
\fBzipfs lmkimg\fI outfile inlist\fR ?\fIpassword\fR? ?\fIinfile\fR?
.
This command is like \fBzipfs mkimg\fR, but instead of an input directory,
\fIinlist\fR must be a Tcl list where the odd elements are the names of files
to be copied into the archive in the image, and the even elements are their
respective names within that archive.
.\" METHOD: lmkzip
.TP
\fBzipfs lmkzip\fR \fIoutfile inlist\fR ?\fIpassword\fR?
\fBzipfs lmkzip\fI outfile inlist\fR ?\fIpassword\fR?
.
This command is like \fBzipfs mkzip\fR, but instead of an input directory,
\fIinlist\fR must be a Tcl list where the odd elements are the names of files
to be copied into the archive, and the even elements are their respective
names within that archive.
.SH "NOTE"
.PP
The current syntax for certain subcommands using multiple optional parameters might
change in the future to support an \fI?-option value?\fR pattern instead.
Therfore, the current syntax should not be considered stable.
.SH "EXAMPLES"
.PP
Mounting an ZIP archive as an application directory and running code out of it
before unmounting it again:
.PP
.CS
set zip myApp.zip
set base [file join [\fBzipfs root\fR] myApp]

\fBzipfs mount\fR $base $zip
\fBzipfs mount\fR $zip $base
# $base now has the contents of myApp.zip

source [file join $base app.tcl]
# use the contents, load libraries from it, etc...

\fBzipfs unmount\fR $zip
\fBzipfs unmount\fR $base
.CE
.PP
Creating a ZIP archive, given that a directory exists containing the content
to put in the archive. Note that the source directory is given twice, in order
to strip the exterior directory name from each filename in the archive.
.PP
.CS
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
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







-
+


+
+
+
+











-
+





-
+

+
+
+



+
-
+








set password "hunter2"
set base [file join [\fBzipfs root\fR] myApp]

# Create with password
\fBzipfs mkzip\fR $targetZip $sourceDir $sourceDir $password

# Mount with password
\fBzipfs mount\fR $base $zip $password
\fBzipfs mount\fR $zip $base $password
.CE
.PP
The following example creates an executable application by appending a ZIP archive
to the tclsh file it was called from and storing the resulting executable in
the file
.QW myApp.bin .
When creating an executable image with a password, the password is placed
within the executable in a shrouded form so that the application can read
files inside the embedded ZIP archive yet casual inspection cannot read it.
.PP
.CS
set appDir [file normalize myApp]
set img "myApp.bin"
set password "hunter2"

# Create some simple content to define a basic application
file mkdir $appDir
set f [open $appDir/main.tcl]
set f [open $appDir/main.tcl w]
puts $f {
    puts "Hi. This is [info script]"
}
close $f

# Create the executable
# Create the executable application
\fBzipfs mkimg\fR $img $appDir $appDir $password

# remove the now obsolete temporary appDir folder
file delete -force $appDir

# Launch the executable, printing its output to stdout
exec $img >@stdout
# prints the following line assuming [zipfs root] returns "//zipfs:/":
#    prints: \fIHi. This is //zipfs:/app/main.tcl\fR
# \fIHi. This is //zipfs:/app/main.tcl\fR
.CE
.SH "SEE ALSO"
tclsh(1), file(n), zipfs(3), zlib(n)
.SH "KEYWORDS"
compress, filesystem, zip
'\" Local Variables:
'\" mode: nroff
'\" End:

Changes to doc/zlib.n.

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
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







+






+






+






+








-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-



-
-
+
-

-
-
+
-



-
-
+
-


+









-
-
+
-

-
-
+
-



-
-
+
-

-
-
+
-


-
-
+
-


-
-
+
-


+







+









-
-
+
-


-
-
+
-


-
-
+
-


-
-
+
-


-
-
+
-


-
-
+
-







+











+





+





+



















+







+











+









+






+








+







.BE
.SH DESCRIPTION
.PP
The \fBzlib\fR command provides access to the compression and check-summing
facilities of the Zlib library by Jean-loup Gailly and Mark Adler. It has the
following subcommands.
.SS "COMPRESSION SUBCOMMANDS"
.\" METHOD: compress
.TP
\fBzlib compress\fI string\fR ?\fIlevel\fR?
.
Returns the zlib-format compressed binary data of the binary string in
\fIstring\fR. If present, \fIlevel\fR gives the compression level to use (from
0, which is uncompressed, to 9, maximally compressed).
.\" METHOD: decompress
.TP
\fBzlib decompress\fI string\fR ?\fIbufferSize\fR?
.
Returns the uncompressed version of the raw compressed binary data in
\fIstring\fR. If present, \fIbufferSize\fR is a hint as to what size of buffer
is to be used to receive the data.
.\" METHOD: deflate
.TP
\fBzlib deflate\fI string\fR ?\fIlevel\fR?
.
Returns the raw compressed binary data of the binary string in \fIstring\fR.
If present, \fIlevel\fR gives the compression level to use (from 0, which is
uncompressed, to 9, maximally compressed).
.\" METHOD: gunzip
.TP
\fBzlib gunzip\fI string\fR ?\fB\-headerVar \fIvarName\fR?
.
Return the uncompressed contents of binary string \fIstring\fR, which must
have been in gzip format. If \fB\-headerVar\fR is given, store a dictionary
describing the contents of the gzip header in the variable called
\fIvarName\fR. The keys of the dictionary that may be present are:
.RS
.TP
\fBcomment\fR
.IP \fBcomment\fR
.
The comment field from the header, if present.
.TP
\fBcrc\fR
.IP \fBcrc\fR
.
A boolean value describing whether a CRC of the header is computed.
.TP
\fBfilename\fR
.IP \fBfilename\fR
.
The filename field from the header, if present.
.TP
\fBos\fR
.IP \fBos\fR
.
The operating system type code field from the header (if not the
QW unknown
value). See RFC 1952 for the meaning of these codes.
.TP
\fBsize\fR
.IP \fBsize\fR
.
The size of the uncompressed data.
.TP
\fBtime\fR
.IP \fBtime\fR
.
The time field from the header if non-zero, expected to be time that the file
named by the \fBfilename\fR field was modified. Suitable for use with
\fBclock format\fR.
.TP
\fBtype\fR
.IP \fBtype\fR
.
The type of the uncompressed data (\fBbinary\fR or \fBtext\fR) if known.
.RE
.\" METHOD: gzip
.TP
\fBzlib gzip\fI string\fR ?\fB\-level \fIlevel\fR? ?\fB\-header \fIdict\fR?
.
Return the compressed contents of binary string \fIstring\fR in gzip format.
If \fB\-level\fR is given, \fIlevel\fR gives the compression level to use
(from 0, which is uncompressed, to 9, maximally compressed). If \fB\-header\fR
is given, \fIdict\fR is a dictionary containing values used for the gzip
header. The following keys may be defined:
.RS
.TP
\fBcomment\fR
.IP \fBcomment\fR
.
Add the given comment to the header of the gzip-format data.
.TP
\fBcrc\fR
.IP \fBcrc\fR
.
A boolean saying whether to compute a CRC of the header. Note that if the data
is to be interchanged with the \fBgzip\fR program, a header CRC should
\fInot\fR be computed.
.TP
\fBfilename\fR
.IP \fBfilename\fR
.
The name of the file that the data to be compressed came from.
.TP
\fBos\fR
.IP \fBos\fR
.
The operating system type code, which should be one of the values described in
RFC 1952.
.TP
\fBtime\fR
.IP \fBtime\fR
.
The time that the file named in the \fBfilename\fR key was last modified. This
will be in the same as is returned by \fBclock seconds\fR or \fBfile mtime\fR.
.TP
\fBtype\fR
.IP \fBtype\fR
.
The type of the data being compressed, being \fBbinary\fR or \fBtext\fR.
.RE
.\" METHOD: inflate
.TP
\fBzlib inflate\fI string\fR ?\fIbufferSize\fR?
.
Returns the uncompressed version of the raw compressed binary data in
\fIstring\fR. If present, \fIbufferSize\fR is a hint as to what size of buffer
is to be used to receive the data.
.SS "CHANNEL SUBCOMMAND"
.\" METHOD: push
.TP
\fBzlib push\fI mode channel\fR ?\fIoptions ...\fR?
.
Pushes a compressing or decompressing transformation onto the channel
\fIchannel\fR.
The transformation can be removed again with \fBchan pop\fR.
The \fImode\fR argument determines what type of transformation
is pushed; the following are supported:
.RS
.TP
\fBcompress\fR
.IP \fBcompress\fR
.
The transformation will be a compressing transformation that produces
zlib-format data on \fIchannel\fR, which must be writable.
.TP
\fBdecompress\fR
.IP \fBdecompress\fR
.
The transformation will be a decompressing transformation that reads
zlib-format data from \fIchannel\fR, which must be readable.
.TP
\fBdeflate\fR
.IP \fBdeflate\fR
.
The transformation will be a compressing transformation that produces raw
compressed data on \fIchannel\fR, which must be writable.
.TP
\fBgunzip\fR
.IP \fBgunzip\fR
.
The transformation will be a decompressing transformation that reads
gzip-format data from \fIchannel\fR, which must be readable.
.TP
\fBgzip\fR
.IP \fBgzip\fR
.
The transformation will be a compressing transformation that produces
gzip-format data on \fIchannel\fR, which must be writable.
.TP
\fBinflate\fR
.IP \fBinflate\fR
.
The transformation will be a decompressing transformation that reads raw
compressed data from \fIchannel\fR, which must be readable.
.PP
The following options may be set when creating a transformation via
the
.QW "\fIoptions ...\fR"
to the \fBzlib push\fR command:
.\" OPTION: -dictionary
.TP
\fB\-dictionary\fI binData\fR
.VS "TIP 400"
Sets the compression dictionary to use when working with compressing or
decompressing the data to be \fIbinData\fR. Not valid for transformations that
work with gzip-format data.  The dictionary should consist of strings (byte
sequences) that are likely to be encountered later in the data to be compressed,
with the most commonly used strings preferably put towards the end of the
dictionary. Tcl provides no mechanism for choosing a good such dictionary for
a particular data sequence.
.VE
.\" OPTION: -header
.TP
\fB\-header\fI dictionary\fR
.
Passes a description of the gzip header to create, in the same format that
\fBzlib gzip\fR understands.
.\" OPTION: -level
.TP
\fB\-level\fI compressionLevel\fR
.
How hard to compress the data. Must be an integer from 0 (uncompressed) to 9
(maximally compressed).
.\" OPTION: -limit
.TP
\fB\-limit\fI readaheadLimit\fR
.
The maximum number of bytes ahead to read when decompressing.
.RS
.PP
This option has become \fBirrelevant\fR. It was originally introduced
to prevent Tcl from reading beyond the end of a compressed stream in
multi-stream channels to ensure that the data after was left alone for
further reading, at the cost of speed.
.PP
Tcl now automatically returns any bytes it has read beyond the end of
a compressed stream back to the channel, making them appear as unread
to further readers.
.RE
.PP
Both compressing and decompressing channel transformations add extra
configuration options that may be accessed through \fBchan configure\fR. The
options are:
.\" OPTION: -checksum
.TP
\fB\-checksum\fI checksum\fR
.
This read-only option gets the current checksum for the uncompressed data that
the compression engine has seen so far. It is valid for both compressing and
decompressing transforms, but not for the raw inflate and deflate formats. The
compression algorithm depends on what format is being produced or consumed.
.\" OPTION: -dictionary
.TP
\fB\-dictionary\fI binData\fR
.VS "TIP 400"
This read-write options gets or sets the initial compression dictionary to use
when working with compressing or decompressing the data to be \fIbinData\fR.
It is not valid for transformations that work with gzip-format data, and should
not normally be set on compressing transformations other than at the point where
the transformation is stacked. Note that this cannot be used to get the
current active compression dictionary mid-stream, as that information is not
exposed by the underlying library.
.VE
.\" OPTION: -flush
.TP
\fB\-flush\fI type\fR
.
This write-only operation flushes the current state of the compressor to the
underlying channel. It is only valid for compressing transformations. The
\fItype\fR must be either \fBsync\fR or \fBfull\fR for a normal flush or an
expensive flush respectively. Flushing degrades the compression ratio, but
makes it easier for a decompressor to recover more of the file in the case of
data corruption.
.\" OPTION: -header
.TP
\fB\-header\fI dictionary\fR
.
This read-only option, only valid for decompressing transforms that are
processing gzip-format data, returns the dictionary describing the header read
off the data stream.
.\" OPTION: -limit
.TP
\fB\-limit\fI readaheadLimit\fR
.
This read-write option is used by decompressing channels to control the
maximum number of bytes ahead to read from the underlying data source. See
above for more information.
.RE
.SS "STREAMING SUBCOMMAND"
.\" METHOD: stream
.TP
\fBzlib stream\fI mode\fR ?\fIoptions\fR?
.
Creates a streaming compression or decompression command based on the
\fImode\fR, and return the name of the command. For a description of how that
command works, see \fBSTREAMING INSTANCE COMMAND\fR below. The following modes
and \fIoptions\fR are supported:
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
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
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
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







+





+














+







+




+




+






+





+





+





+






+
-
+





+








+






+













+











+













+







.VS "TIP 400"
If \fIbindata\fR is supplied, it is a compression dictionary to use. Note that
there are no checks in place to determine whether the compression dictionary
is correct.
.VE
.RE
.SS "CHECKSUMMING SUBCOMMANDS"
.\" METHOD: adler32
.TP
\fBzlib adler32\fI string\fR ?\fIinitValue\fR?
.
Compute a checksum of binary string \fIstring\fR using the Adler-32 algorithm.
If given, \fIinitValue\fR is used to initialize the checksum engine.
.\" METHOD: crc32
.TP
\fBzlib crc32\fI string\fR ?\fIinitValue\fR?
.
Compute a checksum of binary string \fIstring\fR using the CRC-32 algorithm.
If given, \fIinitValue\fR is used to initialize the checksum engine.
.SH "STREAMING INSTANCE COMMAND"
.PP
Streaming compression instance commands are produced by the \fBzlib stream\fR
command. They are used by calling their \fBput\fR subcommand one or more times
to load data in, and their \fBget\fR subcommand one or more times to extract
the transformed data.
.PP
The full set of subcommands supported by a streaming instance command,
\fIstream\fR, is as follows:
.\" METHOD: add
.TP
\fIstream \fBadd\fR ?\fIoption...\fR? \fIdata\fR
.
A short-cut for
.QW "\fIstream \fBput \fR?\fIoption...\fR? \fIdata\fR"
followed by
.QW "\fIstream \fBget\fR" .
.\" METHOD: checksum
.TP
\fIstream \fBchecksum\fR
.
Returns the checksum of the uncompressed data seen so far by this stream.
.\" METHOD: close
.TP
\fIstream \fBclose\fR
.
Deletes this stream and frees up all resources associated with it.
.\" METHOD: eof
.TP
\fIstream \fBeof\fR
.
Returns a boolean indicating whether the end of the stream (as determined by
the compressed data itself) has been reached. Not all formats support
detection of the end of the stream.
.\" METHOD: finalize
.TP
\fIstream \fBfinalize\fR
.
A short-cut for
.QW "\fIstream \fBput \-finalize {}\fR" .
.\" METHOD: flush
.TP
\fIstream \fBflush\fR
.
A short-cut for
.QW "\fIstream \fBput \-flush {}\fR" .
.\" METHOD: fullflush
.TP
\fIstream \fBfullflush\fR
.
A short-cut for
.QW "\fIstream \fBput \-fullflush {}\fR" .
.\" METHOD: get
.TP
\fIstream \fBget \fR?\fIcount\fR?
.
Return up to \fIcount\fR bytes from \fIstream\fR's internal buffers with the
transformation applied. If \fIcount\fR is omitted, the entire contents of the
buffers are returned.
.\" METHOD: header
.
.TP
\fIstream \fBheader\fR
.
Return the gzip header description dictionary extracted from the stream. Only
supported for streams created with their \fImode\fR parameter set to
\fBgunzip\fR.
.\" METHOD: put
.TP
\fIstream \fBput\fR ?\fIoption...\fR? \fIdata\fR
.
Append the contents of the binary string \fIdata\fR to \fIstream\fR's internal
buffers while applying the transformation. The following \fIoption\fRs are
supported (or an unambiguous prefix of them), which are used to modify the
way in which the transformation is applied:
.RS
.\" OPTION: -dictionary
.TP
\fB\-dictionary\fI binData\fR
.VS "TIP 400"
Sets the compression dictionary to use when working with compressing or
decompressing the data to be \fIbinData\fR.
.VE
.\" OPTION: -finalize
.TP
\fB\-finalize\fR
.
Mark the stream as finished, ensuring that all bytes have been wholly
compressed or decompressed. For gzip streams, this also ensures that the
footer is written to the stream. The stream will need to be reset before
having more data written to it after this, though data can still be read out
of the stream with the \fBget\fR subcommand.
.RS
.PP
This option is mutually exclusive with the \fB\-flush\fR and \fB\-fullflush\fR
options.
.RE
.\" OPTION: -flush
.TP
\fB\-flush\fR
.
Ensure that a decompressor consuming the bytes that the current (compressing)
stream is producing will be able to produce all the bytes that have been
compressed so far, at some performance penalty.
.RS
.PP
This option is mutually exclusive with the \fB\-finalize\fR and
\fB\-fullflush\fR options.
.RE
.\" OPTION: -fullflush
.TP
\fB\-fullflush\fR
.
Ensure that not only can a decompressor handle all the bytes produced so far
(as with \fB\-flush\fR above) but also that it can restart from this point if
it detects that the stream is partially corrupt. This incurs a substantial
performance penalty.
.RS
.PP
This option is mutually exclusive with the \fB\-finalize\fR and \fB\-flush\fR
options.
.RE
.RE
.\" METHOD: reset
.TP
\fIstream \fBreset\fR
.
Puts any stream, including those that have been finalized or that have reached
eof, back into a state where it can process more data. Throws away all
internally buffered data.
.SH EXAMPLES

Changes to generic/regc_color.c.

1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







/*
 * colorings of characters
 * This file is #included by regcomp.c.
 *
 * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
 * Copyright © 1998, 1999 Henry Spencer. All rights reserved.
 *
 * Development of this software was funded, in part, by Cray Research Inc.,
 * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
 * Corporation, none of whom are responsible for the results. The author
 * thanks all of them.
 *
 * Redistribution and use in source and binary forms -- with or without
426
427
428
429
430
431
432
433

434
435
436
437
438
439
440
426
427
428
429
430
431
432

433
434
435
436
437
438
439
440







-
+








    return sco;
}

/*
 - subrange - allocate new subcolors to this range of chrs, fill in arcs
 ^ static void subrange(struct vars *, pchr, pchr, struct state *,
 ^ 	struct state *);
 ^	struct state *);
 */
static void
subrange(
    struct vars *v,
    pchr from,
    pchr to,
    struct state *lp,
685
686
687
688
689
690
691
692

693
694
695
696
697
698
699
685
686
687
688
689
690
691

692
693
694
695
696
697
698
699







-
+







    a->colorchain = NULL;	/* paranoia */
    a->colorchainRev = NULL;
}

/*
 - rainbow - add arcs of all full colors (but one) between specified states
 ^ static void rainbow(struct nfa *, struct colormap *, int, pcolor,
 ^ 	struct state *, struct state *);
 ^	struct state *, struct state *);
 */
static void
rainbow(
    struct nfa *nfa,
    struct colormap *cm,
    int type,
    pcolor but,			/* COLORLESS if no exceptions */
712
713
714
715
716
717
718
719

720
721
722
723
724
725
726
712
713
714
715
716
717
718

719
720
721
722
723
724
725
726







-
+







    }
}

/*
 - colorcomplement - add arcs of complementary colors
 * The calling sequence ought to be reconciled with cloneouts().
 ^ static void colorcomplement(struct nfa *, struct colormap *, int,
 ^ 	struct state *, struct state *, struct state *);
 ^	struct state *, struct state *, struct state *);
 */
static void
colorcomplement(
    struct nfa *nfa,
    struct colormap *cm,
    int type,
    struct state *of,		/* complements of this guy's PLAIN outarcs */
755
756
757
758
759
760
761
762

763
764

765
766
767
768
769
770
771
755
756
757
758
759
760
761

762
763

764
765
766
767
768
769
770
771







-
+

-
+







    struct colormap *cm,
    FILE *f)
{
    struct colordesc *cd;
    struct colordesc *end;
    color co;
    chr c;
    char *has;
    const char *has;

    fprintf(f, "max %ld\n", (long) cm->max);
    fprintf(f, "max %" TCL_Z_MODIFIER "u\n", cm->max);
    if (NBYTS > 1) {
	fillcheck(cm, cm->tree, 0, f);
    }
    end = CDEND(cm);
    for (cd=cm->cd+1, co=1 ; cd<end ; cd++, co++) {	/* skip 0 */
	if (!UNUSEDCOLOR(cd)) {
	    assert(cd->nchrs > 0);

Changes to generic/regc_cvec.c.

1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







/*
 * Utility functions for handling cvecs
 * This file is #included by regcomp.c.
 *
 * Copyright (c) 1998, 1999 Henry Spencer.  All rights reserved.
 * Copyright © 1998, 1999 Henry Spencer.  All rights reserved.
 *
 * Development of this software was funded, in part, by Cray Research Inc.,
 * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
 * Corporation, none of whom are responsible for the results. The author
 * thanks all of them.
 *
 * Redistribution and use in source and binary forms -- with or without
32
33
34
35
36
37
38
39

40
41
42
43
44


45
46

47
48
49
50
51
52
53
32
33
34
35
36
37
38

39
40
41
42


43
44
45

46
47
48
49
50
51
52
53







-
+



-
-
+
+

-
+







/*
 * Notes:
 * Only (selected) functions in _this_ file should treat chr* as non-constant.
 */

/*
 - newcvec - allocate a new cvec
 ^ static struct cvec *newcvec(int, int);
 ^ static struct cvec *newcvec(size_t, size_t);
 */
static struct cvec *
newcvec(
    int nchrs,			/* to hold this many chrs... */
    int nranges)		/* ... and this many ranges... */
    size_t nchrs,		/* to hold this many chrs... */
    size_t nranges)		/* ... and this many ranges... */
{
    size_t nc = (size_t)nchrs + (size_t)nranges*2;
    size_t nc = nchrs + nranges*2;
    size_t n = sizeof(struct cvec) + nc*sizeof(chr);
    struct cvec *cv = (struct cvec *) MALLOC(n);

    if (cv == NULL) {
	return NULL;
    }
    cv->chrspace = nchrs;
104
105
106
107
108
109
110
111
112


113
114
115
116
117
118
119
104
105
106
107
108
109
110


111
112
113
114
115
116
117
118
119







-
-
+
+







/*
 - getcvec - get a cvec, remembering it as v->cv
 ^ static struct cvec *getcvec(struct vars *, int, int);
 */
static struct cvec *
getcvec(
    struct vars *v,		/* context */
    int nchrs,			/* to hold this many chrs... */
    int nranges)		/* ... and this many ranges... */
    size_t nchrs,		/* to hold this many chrs... */
    size_t nranges)		/* ... and this many ranges... */
{
    if ((v->cv != NULL) && (nchrs <= v->cv->chrspace) &&
	    (nranges <= v->cv->rangespace)) {
	return clearcvec(v->cv);
    }

    if (v->cv != NULL) {

Changes to generic/regc_lex.c.

1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







/*
 * lexical analyzer
 * This file is #included by regcomp.c.
 *
 * Copyright (c) 1998, 1999 Henry Spencer.  All rights reserved.
 * Copyright © 1998, 1999 Henry Spencer.  All rights reserved.
 *
 * Development of this software was funded, in part, by Cray Research Inc.,
 * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
 * Corporation, none of whom are responsible for the results.  The author
 * thanks all of them.
 *
 * Redistribution and use in source and binary forms -- with or without
423
424
425
426
427
428
429
430

431
432
433
434
435
436
437
423
424
425
426
427
428
429

430
431
432
433
434
435
436
437







-
+







		FAILW(REG_BADBR);
	    }
	    break;
	case CHR('\\'):		/* BRE bound ends with \} */
	    if (INCON(L_BBND) && NEXT1('}')) {
		v->now++;
		INTOCON(L_BRE);
		RET('}');
		RETV('}', 1);
	    } else {
		FAILW(REG_BADBR);
	    }
	    break;
	default:
	    FAILW(REG_BADBR);
	    break;
771
772
773
774
775
776
777
778

779
780
781
782
783
784
785
771
772
773
774
775
776
777

778
779
780
781
782
783
784
785







-
+







    if (!iscalnum(c)) {
	RETV(PLAIN, c);
    }

    NOTE(REG_UNONPOSIX);
    switch (c) {
    case CHR('a'):
	RETV(PLAIN, chrnamed(v, alert, ENDOF(alert), CHR('\007')));
	RETV(PLAIN, chrnamed(v, alert, ENDOF(alert), CHR('\x07')));
	break;
    case CHR('A'):
	RETV(SBEGIN, 0);
	break;
    case CHR('b'):
	RETV(PLAIN, CHR('\b'));
	break;
799
800
801
802
803
804
805
806

807
808
809
810
811
812
813
799
800
801
802
803
804
805

806
807
808
809
810
811
812
813







-
+







	break;
    case CHR('D'):
	NOTE(REG_ULOCALE);
	RETV(CCLASS, 'D');
	break;
    case CHR('e'):
	NOTE(REG_UUNPORT);
	RETV(PLAIN, chrnamed(v, esc, ENDOF(esc), CHR('\033')));
	RETV(PLAIN, chrnamed(v, esc, ENDOF(esc), CHR('\x1B')));
	break;
    case CHR('f'):
	RETV(PLAIN, CHR('\f'));
	break;
    case CHR('m'):
	RET('<');
	break;
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
839
840
841
842
843
844
845





846
847
848
849
850
851
852







-
-
-
-
-







	RETV(PLAIN, c);
	break;
    case CHR('U'):
	i = lexdigits(v, 16, 1, 8);
	if (ISERR()) {
	    FAILW(REG_EESCAPE);
	}
	if (i > 0xFFFF) {
	    /* TODO: output a Surrogate pair
	     */
	    i = 0xFFFD;
	}
	RETV(PLAIN, (uchr) i);
	break;
    case CHR('v'):
	RETV(PLAIN, CHR('\v'));
	break;
    case CHR('w'):
	NOTE(REG_ULOCALE);
1001
1002
1003
1004
1005
1006
1007
1008

1009
1010
1011
1012
1013
1014
1015
996
997
998
999
1000
1001
1002

1003
1004
1005
1006
1007
1008
1009
1010







-
+







    chr c = (chr)pc;

    switch (c) {
    case CHR('*'):
	if (LASTTYPE(EMPTY) || LASTTYPE('(') || LASTTYPE('^')) {
	    RETV(PLAIN, c);
	}
	RET('*');
	RETV('*', 1);
	break;
    case CHR('['):
	if (HAVE(6) &&	*(v->now+0) == CHR('[') &&
		*(v->now+1) == CHR(':') &&
		(*(v->now+2) == CHR('<') || *(v->now+2) == CHR('>')) &&
		*(v->now+3) == CHR(':') &&
		*(v->now+4) == CHR(']') &&

Changes to generic/regc_locale.c.

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
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
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
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






-
+











-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







/*
 * regc_locale.c --
 *
 *	This file contains the Unicode locale specific regexp routines.
 *	This file is #included by regcomp.c.
 *
 * Copyright (c) 1998 by Scriptics Corporation.
 * Copyright © 1998 Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

/* ASCII character-name table */

static const struct cname {
    const char *name;
    const char code;
} cnames[] = {
    {"NUL",		'\0'},
    {"SOH",		'\001'},
    {"STX",		'\002'},
    {"ETX",		'\003'},
    {"EOT",		'\004'},
    {"ENQ",		'\005'},
    {"ACK",		'\006'},
    {"BEL",		'\007'},
    {"alert",		'\007'},
    {"BS",		'\010'},
    {"backspace",	'\b'},
    {"HT",		'\011'},
    {"tab",		'\t'},
    {"LF",		'\012'},
    {"newline",		'\n'},
    {"VT",		'\013'},
    {"vertical-tab",	'\v'},
    {"FF",		'\014'},
    {"form-feed",	'\f'},
    {"CR",		'\015'},
    {"carriage-return",	'\r'},
    {"SO",		'\016'},
    {"SI",		'\017'},
    {"DLE",		'\020'},
    {"DC1",		'\021'},
    {"DC2",		'\022'},
    {"DC3",		'\023'},
    {"DC4",		'\024'},
    {"NAK",		'\025'},
    {"SYN",		'\026'},
    {"ETB",		'\027'},
    {"CAN",		'\030'},
    {"EM",		'\031'},
    {"SUB",		'\032'},
    {"ESC",		'\033'},
    {"IS4",		'\034'},
    {"FS",		'\034'},
    {"IS3",		'\035'},
    {"GS",		'\035'},
    {"IS2",		'\036'},
    {"RS",		'\036'},
    {"IS1",		'\037'},
    {"US",		'\037'},
    {"NUL",		'\x00'},
    {"SOH",		'\x01'},
    {"STX",		'\x02'},
    {"ETX",		'\x03'},
    {"EOT",		'\x04'},
    {"ENQ",		'\x05'},
    {"ACK",		'\x06'},
    {"BEL",		'\x07'},
    {"alert",		'\x07'},
    {"BS",		'\x08'},
    {"backspace",	'\x08'},
    {"HT",		'\x09'},
    {"tab",		'\x09'},
    {"LF",		'\x0A'},
    {"newline",		'\x0A'},
    {"VT",		'\x0B'},
    {"vertical-tab",	'\x0B'},
    {"FF",		'\x0C'},
    {"form-feed",	'\x0C'},
    {"CR",		'\x0D'},
    {"carriage-return",	'\x0D'},
    {"SO",		'\x0E'},
    {"SI",		'\x0F'},
    {"DLE",		'\x10'},
    {"DC1",		'\x11'},
    {"DC2",		'\x12'},
    {"DC3",		'\x13'},
    {"DC4",		'\x14'},
    {"NAK",		'\x15'},
    {"SYN",		'\x16'},
    {"ETB",		'\x17'},
    {"CAN",		'\x18'},
    {"EM",		'\x19'},
    {"SUB",		'\x1A'},
    {"ESC",		'\x1B'},
    {"IS4",		'\x1C'},
    {"FS",		'\x1C'},
    {"IS3",		'\x1D'},
    {"GS",		'\x1D'},
    {"IS2",		'\x1E'},
    {"RS",		'\x1E'},
    {"IS1",		'\x1F'},
    {"US",		'\x1F'},
    {"space",		' '},
    {"exclamation-mark",'!'},
    {"quotation-mark",	'"'},
    {"number-sign",	'#'},
    {"dollar-sign",	'$'},
    {"percent-sign",	'%'},
    {"ampersand",	'&'},
106
107
108
109
110
111
112
113

114
115
116
117
118
119
120
106
107
108
109
110
111
112

113
114
115
116
117
118
119
120







-
+







    {"grave-accent",	'`'},
    {"left-brace",	'{'},
    {"left-curly-bracket", '{'},
    {"vertical-line",	'|'},
    {"right-brace",	'}'},
    {"right-curly-bracket", '}'},
    {"tilde",		'~'},
    {"DEL",		'\177'},
    {"DEL",		'\x7F'},
    {NULL,		0}
};

/*
 * Unicode character-class tables.
 */

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
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
442
443


444
445
446
447

448
449
450
451
452
453
454
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
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
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
467
468
469
470







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+

-
+






-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+








+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+



-
+










-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+



-
+







-
+
-

-
+
-



-
+


-
+





-
+

















-
-
-
-
-
-
+
+
+
+
+
+
+
+
+



-
+











-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-


-
-
-
-
-
+
+
+
+
+
+




-
+





-
-
-
-
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
+
+
+
+
+



-
+









-
+






-
+
















-
+



-
+
+






-
+
+



-
+







static const crange alphaRangeTable[] = {
    {0x41, 0x5A}, {0x61, 0x7A}, {0xC0, 0xD6}, {0xD8, 0xF6},
    {0xF8, 0x2C1}, {0x2C6, 0x2D1}, {0x2E0, 0x2E4}, {0x370, 0x374},
    {0x37A, 0x37D}, {0x388, 0x38A}, {0x38E, 0x3A1}, {0x3A3, 0x3F5},
    {0x3F7, 0x481}, {0x48A, 0x52F}, {0x531, 0x556}, {0x560, 0x588},
    {0x5D0, 0x5EA}, {0x5EF, 0x5F2}, {0x620, 0x64A}, {0x671, 0x6D3},
    {0x6FA, 0x6FC}, {0x712, 0x72F}, {0x74D, 0x7A5}, {0x7CA, 0x7EA},
    {0x800, 0x815}, {0x840, 0x858}, {0x860, 0x86A}, {0x8A0, 0x8B4},
    {0x8B6, 0x8C7}, {0x904, 0x939}, {0x958, 0x961}, {0x971, 0x980},
    {0x985, 0x98C}, {0x993, 0x9A8}, {0x9AA, 0x9B0}, {0x9B6, 0x9B9},
    {0x9DF, 0x9E1}, {0xA05, 0xA0A}, {0xA13, 0xA28}, {0xA2A, 0xA30},
    {0xA59, 0xA5C}, {0xA72, 0xA74}, {0xA85, 0xA8D}, {0xA8F, 0xA91},
    {0xA93, 0xAA8}, {0xAAA, 0xAB0}, {0xAB5, 0xAB9}, {0xB05, 0xB0C},
    {0xB13, 0xB28}, {0xB2A, 0xB30}, {0xB35, 0xB39}, {0xB5F, 0xB61},
    {0xB85, 0xB8A}, {0xB8E, 0xB90}, {0xB92, 0xB95}, {0xBA8, 0xBAA},
    {0xBAE, 0xBB9}, {0xC05, 0xC0C}, {0xC0E, 0xC10}, {0xC12, 0xC28},
    {0xC2A, 0xC39}, {0xC58, 0xC5A}, {0xC85, 0xC8C}, {0xC8E, 0xC90},
    {0xC92, 0xCA8}, {0xCAA, 0xCB3}, {0xCB5, 0xCB9}, {0xD04, 0xD0C},
    {0xD0E, 0xD10}, {0xD12, 0xD3A}, {0xD54, 0xD56}, {0xD5F, 0xD61},
    {0xD7A, 0xD7F}, {0xD85, 0xD96}, {0xD9A, 0xDB1}, {0xDB3, 0xDBB},
    {0xDC0, 0xDC6}, {0xE01, 0xE30}, {0xE40, 0xE46}, {0xE86, 0xE8A},
    {0xE8C, 0xEA3}, {0xEA7, 0xEB0}, {0xEC0, 0xEC4}, {0xEDC, 0xEDF},
    {0xF40, 0xF47}, {0xF49, 0xF6C}, {0xF88, 0xF8C}, {0x1000, 0x102A},
    {0x1050, 0x1055}, {0x105A, 0x105D}, {0x106E, 0x1070}, {0x1075, 0x1081},
    {0x10A0, 0x10C5}, {0x10D0, 0x10FA}, {0x10FC, 0x1248}, {0x124A, 0x124D},
    {0x1250, 0x1256}, {0x125A, 0x125D}, {0x1260, 0x1288}, {0x128A, 0x128D},
    {0x1290, 0x12B0}, {0x12B2, 0x12B5}, {0x12B8, 0x12BE}, {0x12C2, 0x12C5},
    {0x12C8, 0x12D6}, {0x12D8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135A},
    {0x1380, 0x138F}, {0x13A0, 0x13F5}, {0x13F8, 0x13FD}, {0x1401, 0x166C},
    {0x166F, 0x167F}, {0x1681, 0x169A}, {0x16A0, 0x16EA}, {0x16F1, 0x16F8},
    {0x1700, 0x170C}, {0x170E, 0x1711}, {0x1720, 0x1731}, {0x1740, 0x1751},
    {0x800, 0x815}, {0x840, 0x858}, {0x860, 0x86A}, {0x870, 0x887},
    {0x889, 0x88E}, {0x8A0, 0x8C9}, {0x904, 0x939}, {0x958, 0x961},
    {0x971, 0x980}, {0x985, 0x98C}, {0x993, 0x9A8}, {0x9AA, 0x9B0},
    {0x9B6, 0x9B9}, {0x9DF, 0x9E1}, {0xA05, 0xA0A}, {0xA13, 0xA28},
    {0xA2A, 0xA30}, {0xA59, 0xA5C}, {0xA72, 0xA74}, {0xA85, 0xA8D},
    {0xA8F, 0xA91}, {0xA93, 0xAA8}, {0xAAA, 0xAB0}, {0xAB5, 0xAB9},
    {0xB05, 0xB0C}, {0xB13, 0xB28}, {0xB2A, 0xB30}, {0xB35, 0xB39},
    {0xB5F, 0xB61}, {0xB85, 0xB8A}, {0xB8E, 0xB90}, {0xB92, 0xB95},
    {0xBA8, 0xBAA}, {0xBAE, 0xBB9}, {0xC05, 0xC0C}, {0xC0E, 0xC10},
    {0xC12, 0xC28}, {0xC2A, 0xC39}, {0xC58, 0xC5A}, {0xC85, 0xC8C},
    {0xC8E, 0xC90}, {0xC92, 0xCA8}, {0xCAA, 0xCB3}, {0xCB5, 0xCB9},
    {0xD04, 0xD0C}, {0xD0E, 0xD10}, {0xD12, 0xD3A}, {0xD54, 0xD56},
    {0xD5F, 0xD61}, {0xD7A, 0xD7F}, {0xD85, 0xD96}, {0xD9A, 0xDB1},
    {0xDB3, 0xDBB}, {0xDC0, 0xDC6}, {0xE01, 0xE30}, {0xE40, 0xE46},
    {0xE86, 0xE8A}, {0xE8C, 0xEA3}, {0xEA7, 0xEB0}, {0xEC0, 0xEC4},
    {0xEDC, 0xEDF}, {0xF40, 0xF47}, {0xF49, 0xF6C}, {0xF88, 0xF8C},
    {0x1000, 0x102A}, {0x1050, 0x1055}, {0x105A, 0x105D}, {0x106E, 0x1070},
    {0x1075, 0x1081}, {0x10A0, 0x10C5}, {0x10D0, 0x10FA}, {0x10FC, 0x1248},
    {0x124A, 0x124D}, {0x1250, 0x1256}, {0x125A, 0x125D}, {0x1260, 0x1288},
    {0x128A, 0x128D}, {0x1290, 0x12B0}, {0x12B2, 0x12B5}, {0x12B8, 0x12BE},
    {0x12C2, 0x12C5}, {0x12C8, 0x12D6}, {0x12D8, 0x1310}, {0x1312, 0x1315},
    {0x1318, 0x135A}, {0x1380, 0x138F}, {0x13A0, 0x13F5}, {0x13F8, 0x13FD},
    {0x1401, 0x166C}, {0x166F, 0x167F}, {0x1681, 0x169A}, {0x16A0, 0x16EA},
    {0x16F1, 0x16F8}, {0x1700, 0x1711}, {0x171F, 0x1731}, {0x1740, 0x1751},
    {0x1760, 0x176C}, {0x176E, 0x1770}, {0x1780, 0x17B3}, {0x1820, 0x1878},
    {0x1880, 0x1884}, {0x1887, 0x18A8}, {0x18B0, 0x18F5}, {0x1900, 0x191E},
    {0x1950, 0x196D}, {0x1970, 0x1974}, {0x1980, 0x19AB}, {0x19B0, 0x19C9},
    {0x1A00, 0x1A16}, {0x1A20, 0x1A54}, {0x1B05, 0x1B33}, {0x1B45, 0x1B4B},
    {0x1A00, 0x1A16}, {0x1A20, 0x1A54}, {0x1B05, 0x1B33}, {0x1B45, 0x1B4C},
    {0x1B83, 0x1BA0}, {0x1BBA, 0x1BE5}, {0x1C00, 0x1C23}, {0x1C4D, 0x1C4F},
    {0x1C5A, 0x1C7D}, {0x1C80, 0x1C88}, {0x1C90, 0x1CBA}, {0x1CBD, 0x1CBF},
    {0x1C5A, 0x1C7D}, {0x1C80, 0x1C8A}, {0x1C90, 0x1CBA}, {0x1CBD, 0x1CBF},
    {0x1CE9, 0x1CEC}, {0x1CEE, 0x1CF3}, {0x1D00, 0x1DBF}, {0x1E00, 0x1F15},
    {0x1F18, 0x1F1D}, {0x1F20, 0x1F45}, {0x1F48, 0x1F4D}, {0x1F50, 0x1F57},
    {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4}, {0x1FB6, 0x1FBC}, {0x1FC2, 0x1FC4},
    {0x1FC6, 0x1FCC}, {0x1FD0, 0x1FD3}, {0x1FD6, 0x1FDB}, {0x1FE0, 0x1FEC},
    {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFC}, {0x2090, 0x209C}, {0x210A, 0x2113},
    {0x2119, 0x211D}, {0x212A, 0x212D}, {0x212F, 0x2139}, {0x213C, 0x213F},
    {0x2145, 0x2149}, {0x2C00, 0x2C2E}, {0x2C30, 0x2C5E}, {0x2C60, 0x2CE4},
    {0x2CEB, 0x2CEE}, {0x2D00, 0x2D25}, {0x2D30, 0x2D67}, {0x2D80, 0x2D96},
    {0x2DA0, 0x2DA6}, {0x2DA8, 0x2DAE}, {0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE},
    {0x2DC0, 0x2DC6}, {0x2DC8, 0x2DCE}, {0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE},
    {0x3031, 0x3035}, {0x3041, 0x3096}, {0x309D, 0x309F}, {0x30A1, 0x30FA},
    {0x30FC, 0x30FF}, {0x3105, 0x312F}, {0x3131, 0x318E}, {0x31A0, 0x31BF},
    {0x31F0, 0x31FF}, {0x3400, 0x4DBF}, {0x4E00, 0x9FFC}, {0xA000, 0xA48C},
    {0xA4D0, 0xA4FD}, {0xA500, 0xA60C}, {0xA610, 0xA61F}, {0xA640, 0xA66E},
    {0xA67F, 0xA69D}, {0xA6A0, 0xA6E5}, {0xA717, 0xA71F}, {0xA722, 0xA788},
    {0xA78B, 0xA7BF}, {0xA7C2, 0xA7CA}, {0xA7F5, 0xA801}, {0xA803, 0xA805},
    {0xA807, 0xA80A}, {0xA80C, 0xA822}, {0xA840, 0xA873}, {0xA882, 0xA8B3},
    {0xA8F2, 0xA8F7}, {0xA90A, 0xA925}, {0xA930, 0xA946}, {0xA960, 0xA97C},
    {0xA984, 0xA9B2}, {0xA9E0, 0xA9E4}, {0xA9E6, 0xA9EF}, {0xA9FA, 0xA9FE},
    {0xAA00, 0xAA28}, {0xAA40, 0xAA42}, {0xAA44, 0xAA4B}, {0xAA60, 0xAA76},
    {0xAA7E, 0xAAAF}, {0xAAB9, 0xAABD}, {0xAADB, 0xAADD}, {0xAAE0, 0xAAEA},
    {0xAAF2, 0xAAF4}, {0xAB01, 0xAB06}, {0xAB09, 0xAB0E}, {0xAB11, 0xAB16},
    {0xAB20, 0xAB26}, {0xAB28, 0xAB2E}, {0xAB30, 0xAB5A}, {0xAB5C, 0xAB69},
    {0xAB70, 0xABE2}, {0xAC00, 0xD7A3}, {0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB},
    {0xF900, 0xFA6D}, {0xFA70, 0xFAD9}, {0xFB00, 0xFB06}, {0xFB13, 0xFB17},
    {0xFB1F, 0xFB28}, {0xFB2A, 0xFB36}, {0xFB38, 0xFB3C}, {0xFB46, 0xFBB1},
    {0xFBD3, 0xFD3D}, {0xFD50, 0xFD8F}, {0xFD92, 0xFDC7}, {0xFDF0, 0xFDFB},
    {0xFE70, 0xFE74}, {0xFE76, 0xFEFC}, {0xFF21, 0xFF3A}, {0xFF41, 0xFF5A},
    {0xFF66, 0xFFBE}, {0xFFC2, 0xFFC7}, {0xFFCA, 0xFFCF}, {0xFFD2, 0xFFD7},
    {0xFFDA, 0xFFDC}
    {0x2145, 0x2149}, {0x2C00, 0x2CE4}, {0x2CEB, 0x2CEE}, {0x2D00, 0x2D25},
    {0x2D30, 0x2D67}, {0x2D80, 0x2D96}, {0x2DA0, 0x2DA6}, {0x2DA8, 0x2DAE},
    {0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE}, {0x2DC0, 0x2DC6}, {0x2DC8, 0x2DCE},
    {0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE}, {0x3031, 0x3035}, {0x3041, 0x3096},
    {0x309D, 0x309F}, {0x30A1, 0x30FA}, {0x30FC, 0x30FF}, {0x3105, 0x312F},
    {0x3131, 0x318E}, {0x31A0, 0x31BF}, {0x31F0, 0x31FF}, {0x3400, 0x4DBF},
    {0x4E00, 0xA48C}, {0xA4D0, 0xA4FD}, {0xA500, 0xA60C}, {0xA610, 0xA61F},
    {0xA640, 0xA66E}, {0xA67F, 0xA69D}, {0xA6A0, 0xA6E5}, {0xA717, 0xA71F},
    {0xA722, 0xA788}, {0xA78B, 0xA7CD}, {0xA7D5, 0xA7DC}, {0xA7F2, 0xA801},
    {0xA803, 0xA805}, {0xA807, 0xA80A}, {0xA80C, 0xA822}, {0xA840, 0xA873},
    {0xA882, 0xA8B3}, {0xA8F2, 0xA8F7}, {0xA90A, 0xA925}, {0xA930, 0xA946},
    {0xA960, 0xA97C}, {0xA984, 0xA9B2}, {0xA9E0, 0xA9E4}, {0xA9E6, 0xA9EF},
    {0xA9FA, 0xA9FE}, {0xAA00, 0xAA28}, {0xAA40, 0xAA42}, {0xAA44, 0xAA4B},
    {0xAA60, 0xAA76}, {0xAA7E, 0xAAAF}, {0xAAB9, 0xAABD}, {0xAADB, 0xAADD},
    {0xAAE0, 0xAAEA}, {0xAAF2, 0xAAF4}, {0xAB01, 0xAB06}, {0xAB09, 0xAB0E},
    {0xAB11, 0xAB16}, {0xAB20, 0xAB26}, {0xAB28, 0xAB2E}, {0xAB30, 0xAB5A},
    {0xAB5C, 0xAB69}, {0xAB70, 0xABE2}, {0xAC00, 0xD7A3}, {0xD7B0, 0xD7C6},
    {0xD7CB, 0xD7FB}, {0xF900, 0xFA6D}, {0xFA70, 0xFAD9}, {0xFB00, 0xFB06},
    {0xFB13, 0xFB17}, {0xFB1F, 0xFB28}, {0xFB2A, 0xFB36}, {0xFB38, 0xFB3C},
    {0xFB46, 0xFBB1}, {0xFBD3, 0xFD3D}, {0xFD50, 0xFD8F}, {0xFD92, 0xFDC7},
    {0xFDF0, 0xFDFB}, {0xFE70, 0xFE74}, {0xFE76, 0xFEFC}, {0xFF21, 0xFF3A},
    {0xFF41, 0xFF5A}, {0xFF66, 0xFFBE}, {0xFFC2, 0xFFC7}, {0xFFCA, 0xFFCF},
    {0xFFD2, 0xFFD7}, {0xFFDA, 0xFFDC}
#if CHRBITS > 16
    ,{0x10000, 0x1000B}, {0x1000D, 0x10026}, {0x10028, 0x1003A}, {0x1003F, 0x1004D},
    {0x10050, 0x1005D}, {0x10080, 0x100FA}, {0x10280, 0x1029C}, {0x102A0, 0x102D0},
    {0x10300, 0x1031F}, {0x1032D, 0x10340}, {0x10342, 0x10349}, {0x10350, 0x10375},
    {0x10380, 0x1039D}, {0x103A0, 0x103C3}, {0x103C8, 0x103CF}, {0x10400, 0x1049D},
    {0x104B0, 0x104D3}, {0x104D8, 0x104FB}, {0x10500, 0x10527}, {0x10530, 0x10563},
    {0x10570, 0x1057A}, {0x1057C, 0x1058A}, {0x1058C, 0x10592}, {0x10597, 0x105A1},
    {0x105A3, 0x105B1}, {0x105B3, 0x105B9}, {0x105C0, 0x105F3}, {0x10600, 0x10736},
    {0x10600, 0x10736}, {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10800, 0x10805},
    {0x1080A, 0x10835}, {0x1083F, 0x10855}, {0x10860, 0x10876}, {0x10880, 0x1089E},
    {0x108E0, 0x108F2}, {0x10900, 0x10915}, {0x10920, 0x10939}, {0x10980, 0x109B7},
    {0x10A10, 0x10A13}, {0x10A15, 0x10A17}, {0x10A19, 0x10A35}, {0x10A60, 0x10A7C},
    {0x10A80, 0x10A9C}, {0x10AC0, 0x10AC7}, {0x10AC9, 0x10AE4}, {0x10B00, 0x10B35},
    {0x10B40, 0x10B55}, {0x10B60, 0x10B72}, {0x10B80, 0x10B91}, {0x10C00, 0x10C48},
    {0x10C80, 0x10CB2}, {0x10CC0, 0x10CF2}, {0x10D00, 0x10D23}, {0x10E80, 0x10EA9},
    {0x10F00, 0x10F1C}, {0x10F30, 0x10F45}, {0x10FB0, 0x10FC4}, {0x10FE0, 0x10FF6},
    {0x11003, 0x11037}, {0x11083, 0x110AF}, {0x110D0, 0x110E8}, {0x11103, 0x11126},
    {0x11150, 0x11172}, {0x11183, 0x111B2}, {0x111C1, 0x111C4}, {0x11200, 0x11211},
    {0x11213, 0x1122B}, {0x11280, 0x11286}, {0x1128A, 0x1128D}, {0x1128F, 0x1129D},
    {0x1129F, 0x112A8}, {0x112B0, 0x112DE}, {0x11305, 0x1130C}, {0x11313, 0x11328},
    {0x1132A, 0x11330}, {0x11335, 0x11339}, {0x1135D, 0x11361}, {0x11400, 0x11434},
    {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10780, 0x10785}, {0x10787, 0x107B0},
    {0x107B2, 0x107BA}, {0x10800, 0x10805}, {0x1080A, 0x10835}, {0x1083F, 0x10855},
    {0x10860, 0x10876}, {0x10880, 0x1089E}, {0x108E0, 0x108F2}, {0x10900, 0x10915},
    {0x10920, 0x10939}, {0x10980, 0x109B7}, {0x10A10, 0x10A13}, {0x10A15, 0x10A17},
    {0x10A19, 0x10A35}, {0x10A60, 0x10A7C}, {0x10A80, 0x10A9C}, {0x10AC0, 0x10AC7},
    {0x10AC9, 0x10AE4}, {0x10B00, 0x10B35}, {0x10B40, 0x10B55}, {0x10B60, 0x10B72},
    {0x10B80, 0x10B91}, {0x10C00, 0x10C48}, {0x10C80, 0x10CB2}, {0x10CC0, 0x10CF2},
    {0x10D00, 0x10D23}, {0x10D4A, 0x10D65}, {0x10D6F, 0x10D85}, {0x10E80, 0x10EA9},
    {0x10EC2, 0x10EC4}, {0x10F00, 0x10F1C}, {0x10F30, 0x10F45}, {0x10F70, 0x10F81},
    {0x10FB0, 0x10FC4}, {0x10FE0, 0x10FF6}, {0x11003, 0x11037}, {0x11083, 0x110AF},
    {0x110D0, 0x110E8}, {0x11103, 0x11126}, {0x11150, 0x11172}, {0x11183, 0x111B2},
    {0x111C1, 0x111C4}, {0x11200, 0x11211}, {0x11213, 0x1122B}, {0x11280, 0x11286},
    {0x1128A, 0x1128D}, {0x1128F, 0x1129D}, {0x1129F, 0x112A8}, {0x112B0, 0x112DE},
    {0x11305, 0x1130C}, {0x11313, 0x11328}, {0x1132A, 0x11330}, {0x11335, 0x11339},
    {0x1135D, 0x11361}, {0x11380, 0x11389}, {0x11390, 0x113B5}, {0x11400, 0x11434},
    {0x11447, 0x1144A}, {0x1145F, 0x11461}, {0x11480, 0x114AF}, {0x11580, 0x115AE},
    {0x115D8, 0x115DB}, {0x11600, 0x1162F}, {0x11680, 0x116AA}, {0x11700, 0x1171A},
    {0x11800, 0x1182B}, {0x118A0, 0x118DF}, {0x118FF, 0x11906}, {0x1190C, 0x11913},
    {0x11918, 0x1192F}, {0x119A0, 0x119A7}, {0x119AA, 0x119D0}, {0x11A0B, 0x11A32},
    {0x11A5C, 0x11A89}, {0x11AC0, 0x11AF8}, {0x11C00, 0x11C08}, {0x11C0A, 0x11C2E},
    {0x11C72, 0x11C8F}, {0x11D00, 0x11D06}, {0x11D0B, 0x11D30}, {0x11D60, 0x11D65},
    {0x11D6A, 0x11D89}, {0x11EE0, 0x11EF2}, {0x12000, 0x12399}, {0x12480, 0x12543},
    {0x13000, 0x1342E}, {0x14400, 0x14646}, {0x16800, 0x16A38}, {0x16A40, 0x16A5E},
    {0x16AD0, 0x16AED}, {0x16B00, 0x16B2F}, {0x16B40, 0x16B43}, {0x16B63, 0x16B77},
    {0x16B7D, 0x16B8F}, {0x16E40, 0x16E7F}, {0x16F00, 0x16F4A}, {0x16F93, 0x16F9F},
    {0x17000, 0x187F7}, {0x18800, 0x18CD5}, {0x18D00, 0x18D08}, {0x1B000, 0x1B11E},
    {0x11740, 0x11746}, {0x11800, 0x1182B}, {0x118A0, 0x118DF}, {0x118FF, 0x11906},
    {0x1190C, 0x11913}, {0x11918, 0x1192F}, {0x119A0, 0x119A7}, {0x119AA, 0x119D0},
    {0x11A0B, 0x11A32}, {0x11A5C, 0x11A89}, {0x11AB0, 0x11AF8}, {0x11BC0, 0x11BE0},
    {0x11C00, 0x11C08}, {0x11C0A, 0x11C2E}, {0x11C72, 0x11C8F}, {0x11D00, 0x11D06},
    {0x11D0B, 0x11D30}, {0x11D60, 0x11D65}, {0x11D6A, 0x11D89}, {0x11EE0, 0x11EF2},
    {0x11F04, 0x11F10}, {0x11F12, 0x11F33}, {0x12000, 0x12399}, {0x12480, 0x12543},
    {0x12F90, 0x12FF0}, {0x13000, 0x1342F}, {0x13441, 0x13446}, {0x13460, 0x143FA},
    {0x14400, 0x14646}, {0x16100, 0x1611D}, {0x16800, 0x16A38}, {0x16A40, 0x16A5E},
    {0x16A70, 0x16ABE}, {0x16AD0, 0x16AED}, {0x16B00, 0x16B2F}, {0x16B40, 0x16B43},
    {0x16B63, 0x16B77}, {0x16B7D, 0x16B8F}, {0x16D40, 0x16D6C}, {0x16E40, 0x16E7F},
    {0x16F00, 0x16F4A}, {0x16F93, 0x16F9F}, {0x17000, 0x187F7}, {0x18800, 0x18CD5},
    {0x18CFF, 0x18D08}, {0x1AFF0, 0x1AFF3}, {0x1AFF5, 0x1AFFB}, {0x1B000, 0x1B122},
    {0x1B150, 0x1B152}, {0x1B164, 0x1B167}, {0x1B170, 0x1B2FB}, {0x1BC00, 0x1BC6A},
    {0x1BC70, 0x1BC7C}, {0x1BC80, 0x1BC88}, {0x1BC90, 0x1BC99}, {0x1D400, 0x1D454},
    {0x1D456, 0x1D49C}, {0x1D4A9, 0x1D4AC}, {0x1D4AE, 0x1D4B9}, {0x1D4BD, 0x1D4C3},
    {0x1D4C5, 0x1D505}, {0x1D507, 0x1D50A}, {0x1D50D, 0x1D514}, {0x1D516, 0x1D51C},
    {0x1D51E, 0x1D539}, {0x1D53B, 0x1D53E}, {0x1D540, 0x1D544}, {0x1D54A, 0x1D550},
    {0x1D552, 0x1D6A5}, {0x1D6A8, 0x1D6C0}, {0x1D6C2, 0x1D6DA}, {0x1D6DC, 0x1D6FA},
    {0x1D6FC, 0x1D714}, {0x1D716, 0x1D734}, {0x1D736, 0x1D74E}, {0x1D750, 0x1D76E},
    {0x1D770, 0x1D788}, {0x1D78A, 0x1D7A8}, {0x1D7AA, 0x1D7C2}, {0x1D7C4, 0x1D7CB},
    {0x1DF00, 0x1DF1E}, {0x1DF25, 0x1DF2A}, {0x1E030, 0x1E06D}, {0x1E100, 0x1E12C},
    {0x1E100, 0x1E12C}, {0x1E137, 0x1E13D}, {0x1E2C0, 0x1E2EB}, {0x1E800, 0x1E8C4},
    {0x1E900, 0x1E943}, {0x1EE00, 0x1EE03}, {0x1EE05, 0x1EE1F}, {0x1EE29, 0x1EE32},
    {0x1EE34, 0x1EE37}, {0x1EE4D, 0x1EE4F}, {0x1EE67, 0x1EE6A}, {0x1EE6C, 0x1EE72},
    {0x1EE74, 0x1EE77}, {0x1EE79, 0x1EE7C}, {0x1EE80, 0x1EE89}, {0x1EE8B, 0x1EE9B},
    {0x1EEA1, 0x1EEA3}, {0x1EEA5, 0x1EEA9}, {0x1EEAB, 0x1EEBB}, {0x20000, 0x2A6DD},
    {0x2A700, 0x2B734}, {0x2B740, 0x2B81D}, {0x2B820, 0x2CEA1}, {0x2CEB0, 0x2EBE0},
    {0x2F800, 0x2FA1D}, {0x30000, 0x3134A}
    {0x1E137, 0x1E13D}, {0x1E290, 0x1E2AD}, {0x1E2C0, 0x1E2EB}, {0x1E4D0, 0x1E4EB},
    {0x1E5D0, 0x1E5ED}, {0x1E7E0, 0x1E7E6}, {0x1E7E8, 0x1E7EB}, {0x1E7F0, 0x1E7FE},
    {0x1E800, 0x1E8C4}, {0x1E900, 0x1E943}, {0x1EE00, 0x1EE03}, {0x1EE05, 0x1EE1F},
    {0x1EE29, 0x1EE32}, {0x1EE34, 0x1EE37}, {0x1EE4D, 0x1EE4F}, {0x1EE67, 0x1EE6A},
    {0x1EE6C, 0x1EE72}, {0x1EE74, 0x1EE77}, {0x1EE79, 0x1EE7C}, {0x1EE80, 0x1EE89},
    {0x1EE8B, 0x1EE9B}, {0x1EEA1, 0x1EEA3}, {0x1EEA5, 0x1EEA9}, {0x1EEAB, 0x1EEBB},
    {0x20000, 0x2A6DF}, {0x2A700, 0x2B739}, {0x2B740, 0x2B81D}, {0x2B820, 0x2CEA1},
    {0x2CEB0, 0x2EBE0}, {0x2EBF0, 0x2EE5D}, {0x2F800, 0x2FA1D}, {0x30000, 0x3134A},
    {0x31350, 0x323AF}
#endif
};

#define NUM_ALPHA_RANGE (sizeof(alphaRangeTable)/sizeof(crange))
#define NUM_ALPHA_RANGE ((int)(sizeof(alphaRangeTable)/sizeof(crange)))

static const chr alphaCharTable[] = {
    0xAA, 0xB5, 0xBA, 0x2EC, 0x2EE, 0x376, 0x377, 0x37F, 0x386,
    0x38C, 0x559, 0x66E, 0x66F, 0x6D5, 0x6E5, 0x6E6, 0x6EE, 0x6EF,
    0x6FF, 0x710, 0x7B1, 0x7F4, 0x7F5, 0x7FA, 0x81A, 0x824, 0x828,
    0x93D, 0x950, 0x98F, 0x990, 0x9B2, 0x9BD, 0x9CE, 0x9DC, 0x9DD,
    0x9F0, 0x9F1, 0x9FC, 0xA0F, 0xA10, 0xA32, 0xA33, 0xA35, 0xA36,
    0xA38, 0xA39, 0xA5E, 0xAB2, 0xAB3, 0xABD, 0xAD0, 0xAE0, 0xAE1,
    0xAF9, 0xB0F, 0xB10, 0xB32, 0xB33, 0xB3D, 0xB5C, 0xB5D, 0xB71,
    0xB83, 0xB99, 0xB9A, 0xB9C, 0xB9E, 0xB9F, 0xBA3, 0xBA4, 0xBD0,
    0xC3D, 0xC60, 0xC61, 0xC80, 0xCBD, 0xCDE, 0xCE0, 0xCE1, 0xCF1,
    0xCF2, 0xD3D, 0xD4E, 0xDBD, 0xE32, 0xE33, 0xE81, 0xE82, 0xE84,
    0xEA5, 0xEB2, 0xEB3, 0xEBD, 0xEC6, 0xF00, 0x103F, 0x1061, 0x1065,
    0x1066, 0x108E, 0x10C7, 0x10CD, 0x1258, 0x12C0, 0x17D7, 0x17DC, 0x18AA,
    0x1AA7, 0x1BAE, 0x1BAF, 0x1CF5, 0x1CF6, 0x1CFA, 0x1F59, 0x1F5B, 0x1F5D,
    0x1FBE, 0x2071, 0x207F, 0x2102, 0x2107, 0x2115, 0x2124, 0x2126, 0x2128,
    0x214E, 0x2183, 0x2184, 0x2CF2, 0x2CF3, 0x2D27, 0x2D2D, 0x2D6F, 0x2E2F,
    0x3005, 0x3006, 0x303B, 0x303C, 0xA62A, 0xA62B, 0xA8FB, 0xA8FD, 0xA8FE,
    0xA9CF, 0xAA7A, 0xAAB1, 0xAAB5, 0xAAB6, 0xAAC0, 0xAAC2, 0xFB1D, 0xFB3E,
    0xFB40, 0xFB41, 0xFB43, 0xFB44
    0xC3D, 0xC5D, 0xC60, 0xC61, 0xC80, 0xCBD, 0xCDD, 0xCDE, 0xCE0,
    0xCE1, 0xCF1, 0xCF2, 0xD3D, 0xD4E, 0xDBD, 0xE32, 0xE33, 0xE81,
    0xE82, 0xE84, 0xEA5, 0xEB2, 0xEB3, 0xEBD, 0xEC6, 0xF00, 0x103F,
    0x1061, 0x1065, 0x1066, 0x108E, 0x10C7, 0x10CD, 0x1258, 0x12C0, 0x17D7,
    0x17DC, 0x18AA, 0x1AA7, 0x1BAE, 0x1BAF, 0x1CF5, 0x1CF6, 0x1CFA, 0x1F59,
    0x1F5B, 0x1F5D, 0x1FBE, 0x2071, 0x207F, 0x2102, 0x2107, 0x2115, 0x2124,
    0x2126, 0x2128, 0x214E, 0x2183, 0x2184, 0x2CF2, 0x2CF3, 0x2D27, 0x2D2D,
    0x2D6F, 0x2E2F, 0x3005, 0x3006, 0x303B, 0x303C, 0xA62A, 0xA62B, 0xA7D0,
    0xA7D1, 0xA7D3, 0xA8FB, 0xA8FD, 0xA8FE, 0xA9CF, 0xAA7A, 0xAAB1, 0xAAB5,
    0xAAB6, 0xAAC0, 0xAAC2, 0xFB1D, 0xFB3E, 0xFB40, 0xFB41, 0xFB43, 0xFB44
#if CHRBITS > 16
    ,0x1003C, 0x1003D, 0x10594, 0x10595, 0x105BB, 0x105BC, 0x10808, 0x10837, 0x10838,
    ,0x1003C, 0x1003D, 0x10808, 0x10837, 0x10838, 0x1083C, 0x108F4, 0x108F5, 0x109BE,
    0x109BF, 0x10A00, 0x10EB0, 0x10EB1, 0x10F27, 0x11144, 0x11147, 0x11176, 0x111DA,
    0x111DC, 0x11288, 0x1130F, 0x11310, 0x11332, 0x11333, 0x1133D, 0x11350, 0x114C4,
    0x114C5, 0x114C7, 0x11644, 0x116B8, 0x11909, 0x11915, 0x11916, 0x1193F, 0x11941,
    0x119E1, 0x119E3, 0x11A00, 0x11A3A, 0x11A50, 0x11A9D, 0x11C40, 0x11D08, 0x11D09,
    0x11D46, 0x11D67, 0x11D68, 0x11D98, 0x11FB0, 0x16F50, 0x16FE0, 0x16FE1, 0x16FE3,
    0x1D49E, 0x1D49F, 0x1D4A2, 0x1D4A5, 0x1D4A6, 0x1D4BB, 0x1D546, 0x1E14E, 0x1E94B,
    0x1EE21, 0x1EE22, 0x1EE24, 0x1EE27, 0x1EE39, 0x1EE3B, 0x1EE42, 0x1EE47, 0x1EE49,
    0x1EE4B, 0x1EE51, 0x1EE52, 0x1EE54, 0x1EE57, 0x1EE59, 0x1EE5B, 0x1EE5D, 0x1EE5F,
    0x1EE61, 0x1EE62, 0x1EE64, 0x1EE7E
    0x1083C, 0x108F4, 0x108F5, 0x109BE, 0x109BF, 0x10A00, 0x10EB0, 0x10EB1, 0x10F27,
    0x11071, 0x11072, 0x11075, 0x11144, 0x11147, 0x11176, 0x111DA, 0x111DC, 0x1123F,
    0x11240, 0x11288, 0x1130F, 0x11310, 0x11332, 0x11333, 0x1133D, 0x11350, 0x1138B,
    0x1138E, 0x113B7, 0x113D1, 0x113D3, 0x114C4, 0x114C5, 0x114C7, 0x11644, 0x116B8,
    0x11909, 0x11915, 0x11916, 0x1193F, 0x11941, 0x119E1, 0x119E3, 0x11A00, 0x11A3A,
    0x11A50, 0x11A9D, 0x11C40, 0x11D08, 0x11D09, 0x11D46, 0x11D67, 0x11D68, 0x11D98,
    0x11F02, 0x11FB0, 0x16F50, 0x16FE0, 0x16FE1, 0x16FE3, 0x1AFFD, 0x1AFFE, 0x1B132,
    0x1B155, 0x1D49E, 0x1D49F, 0x1D4A2, 0x1D4A5, 0x1D4A6, 0x1D4BB, 0x1D546, 0x1E14E,
    0x1E5F0, 0x1E7ED, 0x1E7EE, 0x1E94B, 0x1EE21, 0x1EE22, 0x1EE24, 0x1EE27, 0x1EE39,
    0x1EE3B, 0x1EE42, 0x1EE47, 0x1EE49, 0x1EE4B, 0x1EE51, 0x1EE52, 0x1EE54, 0x1EE57,
    0x1EE59, 0x1EE5B, 0x1EE5D, 0x1EE5F, 0x1EE61, 0x1EE62, 0x1EE64, 0x1EE7E
#endif
};

#define NUM_ALPHA_CHAR (sizeof(alphaCharTable)/sizeof(chr))
#define NUM_ALPHA_CHAR ((int)(sizeof(alphaCharTable)/sizeof(chr)))

/*
 * Unicode: control characters.
 */

static const crange controlRangeTable[] = {
    {0x0, 0x1F}, {0x7F, 0x9F}, {0x600, 0x605}, {0x200B, 0x200F},
    {0x202A, 0x202E}, {0x2060, 0x2064}, {0x2066, 0x206F}, {0xE000, 0xF8FF},
    {0x202A, 0x202E}, {0x2060, 0x2064}, {0x2066, 0x206F}, {0xFFF9, 0xFFFB}
    {0xFFF9, 0xFFFB}
#if CHRBITS > 16
    ,{0x13430, 0x13438}, {0x1BCA0, 0x1BCA3}, {0x1D173, 0x1D17A}, {0xE0020, 0xE007F},
    ,{0x13430, 0x1343F}, {0x1BCA0, 0x1BCA3}, {0x1D173, 0x1D17A}, {0xE0020, 0xE007F}
    {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}
#endif
};

#define NUM_CONTROL_RANGE (sizeof(controlRangeTable)/sizeof(crange))
#define NUM_CONTROL_RANGE ((int)(sizeof(controlRangeTable)/sizeof(crange)))

static const chr controlCharTable[] = {
    0xAD, 0x61C, 0x6DD, 0x70F, 0x8E2, 0x180E, 0xFEFF
    0xAD, 0x61C, 0x6DD, 0x70F, 0x890, 0x891, 0x8E2, 0x180E, 0xFEFF
#if CHRBITS > 16
    ,0x110BD, 0x110CD, 0xE0001
#endif
};

#define NUM_CONTROL_CHAR (sizeof(controlCharTable)/sizeof(chr))
#define NUM_CONTROL_CHAR ((int)(sizeof(controlCharTable)/sizeof(chr)))

/*
 * Unicode: decimal digit characters.
 */

static const crange digitRangeTable[] = {
    {0x30, 0x39}, {0x660, 0x669}, {0x6F0, 0x6F9}, {0x7C0, 0x7C9},
    {0x966, 0x96F}, {0x9E6, 0x9EF}, {0xA66, 0xA6F}, {0xAE6, 0xAEF},
    {0xB66, 0xB6F}, {0xBE6, 0xBEF}, {0xC66, 0xC6F}, {0xCE6, 0xCEF},
    {0xD66, 0xD6F}, {0xDE6, 0xDEF}, {0xE50, 0xE59}, {0xED0, 0xED9},
    {0xF20, 0xF29}, {0x1040, 0x1049}, {0x1090, 0x1099}, {0x17E0, 0x17E9},
    {0x1810, 0x1819}, {0x1946, 0x194F}, {0x19D0, 0x19D9}, {0x1A80, 0x1A89},
    {0x1A90, 0x1A99}, {0x1B50, 0x1B59}, {0x1BB0, 0x1BB9}, {0x1C40, 0x1C49},
    {0x1C50, 0x1C59}, {0xA620, 0xA629}, {0xA8D0, 0xA8D9}, {0xA900, 0xA909},
    {0xA9D0, 0xA9D9}, {0xA9F0, 0xA9F9}, {0xAA50, 0xAA59}, {0xABF0, 0xABF9},
    {0xFF10, 0xFF19}
#if CHRBITS > 16
    ,{0x104A0, 0x104A9}, {0x10D30, 0x10D39}, {0x11066, 0x1106F}, {0x110F0, 0x110F9},
    {0x11136, 0x1113F}, {0x111D0, 0x111D9}, {0x112F0, 0x112F9}, {0x11450, 0x11459},
    {0x114D0, 0x114D9}, {0x11650, 0x11659}, {0x116C0, 0x116C9}, {0x11730, 0x11739},
    {0x118E0, 0x118E9}, {0x11950, 0x11959}, {0x11C50, 0x11C59}, {0x11D50, 0x11D59},
    {0x11DA0, 0x11DA9}, {0x16A60, 0x16A69}, {0x16B50, 0x16B59}, {0x1D7CE, 0x1D7FF},
    {0x1E140, 0x1E149}, {0x1E2F0, 0x1E2F9}, {0x1E950, 0x1E959}, {0x1FBF0, 0x1FBF9}
    ,{0x104A0, 0x104A9}, {0x10D30, 0x10D39}, {0x10D40, 0x10D49}, {0x11066, 0x1106F},
    {0x110F0, 0x110F9}, {0x11136, 0x1113F}, {0x111D0, 0x111D9}, {0x112F0, 0x112F9},
    {0x11450, 0x11459}, {0x114D0, 0x114D9}, {0x11650, 0x11659}, {0x116C0, 0x116C9},
    {0x116D0, 0x116E3}, {0x11730, 0x11739}, {0x118E0, 0x118E9}, {0x11950, 0x11959},
    {0x11BF0, 0x11BF9}, {0x11C50, 0x11C59}, {0x11D50, 0x11D59}, {0x11DA0, 0x11DA9},
    {0x11F50, 0x11F59}, {0x16130, 0x16139}, {0x16A60, 0x16A69}, {0x16AC0, 0x16AC9},
    {0x16B50, 0x16B59}, {0x16D70, 0x16D79}, {0x1CCF0, 0x1CCF9}, {0x1D7CE, 0x1D7FF},
    {0x1E140, 0x1E149}, {0x1E2F0, 0x1E2F9}, {0x1E4F0, 0x1E4F9}, {0x1E5F1, 0x1E5FA},
    {0x1E950, 0x1E959}, {0x1FBF0, 0x1FBF9}
#endif
};

#define NUM_DIGIT_RANGE (sizeof(digitRangeTable)/sizeof(crange))
#define NUM_DIGIT_RANGE ((int)(sizeof(digitRangeTable)/sizeof(crange)))

/*
 * no singletons of digit characters.
 */

/*
 * Unicode: punctuation characters.
 */

static const crange punctRangeTable[] = {
    {0x21, 0x23}, {0x25, 0x2A}, {0x2C, 0x2F}, {0x5B, 0x5D},
    {0x55A, 0x55F}, {0x66A, 0x66D}, {0x700, 0x70D}, {0x7F7, 0x7F9},
    {0x830, 0x83E}, {0xF04, 0xF12}, {0xF3A, 0xF3D}, {0xFD0, 0xFD4},
    {0x104A, 0x104F}, {0x1360, 0x1368}, {0x16EB, 0x16ED}, {0x17D4, 0x17D6},
    {0x17D8, 0x17DA}, {0x1800, 0x180A}, {0x1AA0, 0x1AA6}, {0x1AA8, 0x1AAD},
    {0x1B5A, 0x1B60}, {0x1BFC, 0x1BFF}, {0x1C3B, 0x1C3F}, {0x1CC0, 0x1CC7},
    {0x2010, 0x2027}, {0x2030, 0x2043}, {0x2045, 0x2051}, {0x2053, 0x205E},
    {0x2308, 0x230B}, {0x2768, 0x2775}, {0x27E6, 0x27EF}, {0x2983, 0x2998},
    {0x29D8, 0x29DB}, {0x2CF9, 0x2CFC}, {0x2E00, 0x2E2E}, {0x2E30, 0x2E4F},
    {0x3001, 0x3003}, {0x3008, 0x3011}, {0x3014, 0x301F}, {0xA60D, 0xA60F},
    {0xA6F2, 0xA6F7}, {0xA874, 0xA877}, {0xA8F8, 0xA8FA}, {0xA9C1, 0xA9CD},
    {0xAA5C, 0xAA5F}, {0xFE10, 0xFE19}, {0xFE30, 0xFE52}, {0xFE54, 0xFE61},
    {0xFF01, 0xFF03}, {0xFF05, 0xFF0A}, {0xFF0C, 0xFF0F}, {0xFF3B, 0xFF3D},
    {0x55A, 0x55F}, {0x61D, 0x61F}, {0x66A, 0x66D}, {0x700, 0x70D},
    {0x7F7, 0x7F9}, {0x830, 0x83E}, {0xF04, 0xF12}, {0xF3A, 0xF3D},
    {0xFD0, 0xFD4}, {0x104A, 0x104F}, {0x1360, 0x1368}, {0x16EB, 0x16ED},
    {0x17D4, 0x17D6}, {0x17D8, 0x17DA}, {0x1800, 0x180A}, {0x1AA0, 0x1AA6},
    {0x1AA8, 0x1AAD}, {0x1B5A, 0x1B60}, {0x1B7D, 0x1B7F}, {0x1BFC, 0x1BFF},
    {0x1C3B, 0x1C3F}, {0x1CC0, 0x1CC7}, {0x2010, 0x2027}, {0x2030, 0x2043},
    {0x2045, 0x2051}, {0x2053, 0x205E}, {0x2308, 0x230B}, {0x2768, 0x2775},
    {0x27E6, 0x27EF}, {0x2983, 0x2998}, {0x29D8, 0x29DB}, {0x2CF9, 0x2CFC},
    {0x2E00, 0x2E2E}, {0x2E30, 0x2E4F}, {0x2E52, 0x2E5D}, {0x3001, 0x3003},
    {0x3008, 0x3011}, {0x3014, 0x301F}, {0xA60D, 0xA60F}, {0xA6F2, 0xA6F7},
    {0xA874, 0xA877}, {0xA8F8, 0xA8FA}, {0xA9C1, 0xA9CD}, {0xAA5C, 0xAA5F},
    {0xFE10, 0xFE19}, {0xFE30, 0xFE52}, {0xFE54, 0xFE61}, {0xFF01, 0xFF03},
    {0xFF05, 0xFF0A}, {0xFF0C, 0xFF0F}, {0xFF3B, 0xFF3D}, {0xFF5F, 0xFF65}
    {0xFF5F, 0xFF65}
#if CHRBITS > 16
    ,{0x10100, 0x10102}, {0x10A50, 0x10A58}, {0x10AF0, 0x10AF6}, {0x10B39, 0x10B3F},
    {0x10B99, 0x10B9C}, {0x10F55, 0x10F59}, {0x11047, 0x1104D}, {0x110BE, 0x110C1},
    {0x11140, 0x11143}, {0x111C5, 0x111C8}, {0x111DD, 0x111DF}, {0x11238, 0x1123D},
    {0x1144B, 0x1144F}, {0x115C1, 0x115D7}, {0x11641, 0x11643}, {0x11660, 0x1166C},
    {0x1173C, 0x1173E}, {0x11944, 0x11946}, {0x11A3F, 0x11A46}, {0x11A9A, 0x11A9C},
    {0x11A9E, 0x11AA2}, {0x11C41, 0x11C45}, {0x12470, 0x12474}, {0x16B37, 0x16B3B},
    {0x10B99, 0x10B9C}, {0x10F55, 0x10F59}, {0x10F86, 0x10F89}, {0x11047, 0x1104D},
    {0x110BE, 0x110C1}, {0x11140, 0x11143}, {0x111C5, 0x111C8}, {0x111DD, 0x111DF},
    {0x11238, 0x1123D}, {0x1144B, 0x1144F}, {0x115C1, 0x115D7}, {0x11641, 0x11643},
    {0x11660, 0x1166C}, {0x1173C, 0x1173E}, {0x11944, 0x11946}, {0x11A3F, 0x11A46},
    {0x11A9A, 0x11A9C}, {0x11A9E, 0x11AA2}, {0x11B00, 0x11B09}, {0x11C41, 0x11C45},
    {0x11F43, 0x11F4F}, {0x12470, 0x12474}, {0x16B37, 0x16B3B}, {0x16D6D, 0x16D6F},
    {0x16E97, 0x16E9A}, {0x1DA87, 0x1DA8B}
#endif
};

#define NUM_PUNCT_RANGE (sizeof(punctRangeTable)/sizeof(crange))
#define NUM_PUNCT_RANGE ((int)(sizeof(punctRangeTable)/sizeof(crange)))

static const chr punctCharTable[] = {
    0x3A, 0x3B, 0x3F, 0x40, 0x5F, 0x7B, 0x7D, 0xA1, 0xA7,
    0xAB, 0xB6, 0xB7, 0xBB, 0xBF, 0x37E, 0x387, 0x589, 0x58A,
    0x5BE, 0x5C0, 0x5C3, 0x5C6, 0x5F3, 0x5F4, 0x609, 0x60A, 0x60C,
    0x60D, 0x61B, 0x61E, 0x61F, 0x6D4, 0x85E, 0x964, 0x965, 0x970,
    0x9FD, 0xA76, 0xAF0, 0xC77, 0xC84, 0xDF4, 0xE4F, 0xE5A, 0xE5B,
    0xF14, 0xF85, 0xFD9, 0xFDA, 0x10FB, 0x1400, 0x166E, 0x169B, 0x169C,
    0x1735, 0x1736, 0x1944, 0x1945, 0x1A1E, 0x1A1F, 0x1C7E, 0x1C7F, 0x1CD3,
    0x60D, 0x61B, 0x6D4, 0x85E, 0x964, 0x965, 0x970, 0x9FD, 0xA76,
    0xAF0, 0xC77, 0xC84, 0xDF4, 0xE4F, 0xE5A, 0xE5B, 0xF14, 0xF85,
    0xFD9, 0xFDA, 0x10FB, 0x1400, 0x166E, 0x169B, 0x169C, 0x1735, 0x1736,
    0x1944, 0x1945, 0x1A1E, 0x1A1F, 0x1B4E, 0x1B4F, 0x1C7E, 0x1C7F, 0x1CD3,
    0x207D, 0x207E, 0x208D, 0x208E, 0x2329, 0x232A, 0x27C5, 0x27C6, 0x29FC,
    0x29FD, 0x2CFE, 0x2CFF, 0x2D70, 0x2E52, 0x3030, 0x303D, 0x30A0, 0x30FB,
    0xA4FE, 0xA4FF, 0xA673, 0xA67E, 0xA8CE, 0xA8CF, 0xA8FC, 0xA92E, 0xA92F,
    0xA95F, 0xA9DE, 0xA9DF, 0xAADE, 0xAADF, 0xAAF0, 0xAAF1, 0xABEB, 0xFD3E,
    0xFD3F, 0xFE63, 0xFE68, 0xFE6A, 0xFE6B, 0xFF1A, 0xFF1B, 0xFF1F, 0xFF20,
    0xFF3F, 0xFF5B, 0xFF5D
    0x29FD, 0x2CFE, 0x2CFF, 0x2D70, 0x3030, 0x303D, 0x30A0, 0x30FB, 0xA4FE,
    0xA4FF, 0xA673, 0xA67E, 0xA8CE, 0xA8CF, 0xA8FC, 0xA92E, 0xA92F, 0xA95F,
    0xA9DE, 0xA9DF, 0xAADE, 0xAADF, 0xAAF0, 0xAAF1, 0xABEB, 0xFD3E, 0xFD3F,
    0xFE63, 0xFE68, 0xFE6A, 0xFE6B, 0xFF1A, 0xFF1B, 0xFF1F, 0xFF20, 0xFF3F,
    0xFF5B, 0xFF5D
#if CHRBITS > 16
    ,0x1039F, 0x103D0, 0x1056F, 0x10857, 0x1091F, 0x1093F, 0x10A7F, 0x10EAD, 0x110BB,
    0x110BC, 0x11174, 0x11175, 0x111CD, 0x111DB, 0x112A9, 0x1145A, 0x1145B, 0x1145D,
    0x114C6, 0x1183B, 0x119E2, 0x11C70, 0x11C71, 0x11EF7, 0x11EF8, 0x11FFF, 0x16A6E,
    0x16A6F, 0x16AF5, 0x16B44, 0x16FE2, 0x1BC9F, 0x1E95E, 0x1E95F
    ,0x1039F, 0x103D0, 0x1056F, 0x10857, 0x1091F, 0x1093F, 0x10A7F, 0x10D6E, 0x10EAD,
    0x110BB, 0x110BC, 0x11174, 0x11175, 0x111CD, 0x111DB, 0x112A9, 0x113D4, 0x113D5,
    0x113D7, 0x113D8, 0x1145A, 0x1145B, 0x1145D, 0x114C6, 0x116B9, 0x1183B, 0x119E2,
    0x11BE1, 0x11C70, 0x11C71, 0x11EF7, 0x11EF8, 0x11FFF, 0x12FF1, 0x12FF2, 0x16A6E,
    0x16A6F, 0x16AF5, 0x16B44, 0x16FE2, 0x1BC9F, 0x1E5FF, 0x1E95E, 0x1E95F
#endif
};

#define NUM_PUNCT_CHAR (sizeof(punctCharTable)/sizeof(chr))
#define NUM_PUNCT_CHAR ((int)(sizeof(punctCharTable)/sizeof(chr)))

/*
 * Unicode: white space characters.
 */

static const crange spaceRangeTable[] = {
    {0x9, 0xD}, {0x2000, 0x200B}
};

#define NUM_SPACE_RANGE (sizeof(spaceRangeTable)/sizeof(crange))
#define NUM_SPACE_RANGE ((int)(sizeof(spaceRangeTable)/sizeof(crange)))

static const chr spaceCharTable[] = {
    0x20, 0x85, 0xA0, 0x1680, 0x180E, 0x2028, 0x2029, 0x202F, 0x205F,
    0x2060, 0x3000, 0xFEFF
};

#define NUM_SPACE_CHAR (sizeof(spaceCharTable)/sizeof(chr))
#define NUM_SPACE_CHAR ((int)(sizeof(spaceCharTable)/sizeof(chr)))

/*
 * Unicode: lowercase characters.
 */

static const crange lowerRangeTable[] = {
    {0x61, 0x7A}, {0xDF, 0xF6}, {0xF8, 0xFF}, {0x17E, 0x180},
    {0x199, 0x19B}, {0x1BD, 0x1BF}, {0x233, 0x239}, {0x24F, 0x293},
    {0x295, 0x2AF}, {0x37B, 0x37D}, {0x3AC, 0x3CE}, {0x3D5, 0x3D7},
    {0x3EF, 0x3F3}, {0x430, 0x45F}, {0x560, 0x588}, {0x10D0, 0x10FA},
    {0x10FD, 0x10FF}, {0x13F8, 0x13FD}, {0x1C80, 0x1C88}, {0x1D00, 0x1D2B},
    {0x1D6B, 0x1D77}, {0x1D79, 0x1D9A}, {0x1E95, 0x1E9D}, {0x1EFF, 0x1F07},
    {0x1F10, 0x1F15}, {0x1F20, 0x1F27}, {0x1F30, 0x1F37}, {0x1F40, 0x1F45},
    {0x1F50, 0x1F57}, {0x1F60, 0x1F67}, {0x1F70, 0x1F7D}, {0x1F80, 0x1F87},
    {0x1F90, 0x1F97}, {0x1FA0, 0x1FA7}, {0x1FB0, 0x1FB4}, {0x1FC2, 0x1FC4},
    {0x1FD0, 0x1FD3}, {0x1FE0, 0x1FE7}, {0x1FF2, 0x1FF4}, {0x2146, 0x2149},
    {0x2C30, 0x2C5E}, {0x2C76, 0x2C7B}, {0x2D00, 0x2D25}, {0xA72F, 0xA731},
    {0x2C30, 0x2C5F}, {0x2C76, 0x2C7B}, {0x2D00, 0x2D25}, {0xA72F, 0xA731},
    {0xA771, 0xA778}, {0xA793, 0xA795}, {0xAB30, 0xAB5A}, {0xAB60, 0xAB68},
    {0xAB70, 0xABBF}, {0xFB00, 0xFB06}, {0xFB13, 0xFB17}, {0xFF41, 0xFF5A}
#if CHRBITS > 16
    ,{0x10428, 0x1044F}, {0x104D8, 0x104FB}, {0x10CC0, 0x10CF2}, {0x118C0, 0x118DF},
    ,{0x10428, 0x1044F}, {0x104D8, 0x104FB}, {0x10597, 0x105A1}, {0x105A3, 0x105B1},
    {0x105B3, 0x105B9}, {0x10CC0, 0x10CF2}, {0x10D70, 0x10D85}, {0x118C0, 0x118DF},
    {0x16E60, 0x16E7F}, {0x1D41A, 0x1D433}, {0x1D44E, 0x1D454}, {0x1D456, 0x1D467},
    {0x1D482, 0x1D49B}, {0x1D4B6, 0x1D4B9}, {0x1D4BD, 0x1D4C3}, {0x1D4C5, 0x1D4CF},
    {0x1D4EA, 0x1D503}, {0x1D51E, 0x1D537}, {0x1D552, 0x1D56B}, {0x1D586, 0x1D59F},
    {0x1D5BA, 0x1D5D3}, {0x1D5EE, 0x1D607}, {0x1D622, 0x1D63B}, {0x1D656, 0x1D66F},
    {0x1D68A, 0x1D6A5}, {0x1D6C2, 0x1D6DA}, {0x1D6DC, 0x1D6E1}, {0x1D6FC, 0x1D714},
    {0x1D716, 0x1D71B}, {0x1D736, 0x1D74E}, {0x1D750, 0x1D755}, {0x1D770, 0x1D788},
    {0x1D78A, 0x1D78F}, {0x1D7AA, 0x1D7C2}, {0x1D7C4, 0x1D7C9}, {0x1E922, 0x1E943}
    {0x1D78A, 0x1D78F}, {0x1D7AA, 0x1D7C2}, {0x1D7C4, 0x1D7C9}, {0x1DF00, 0x1DF09},
    {0x1DF0B, 0x1DF1E}, {0x1DF25, 0x1DF2A}, {0x1E922, 0x1E943}
#endif
};

#define NUM_LOWER_RANGE (sizeof(lowerRangeTable)/sizeof(crange))
#define NUM_LOWER_RANGE ((int)(sizeof(lowerRangeTable)/sizeof(crange)))

static const chr lowerCharTable[] = {
    0xB5, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F,
    0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121,
    0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133,
    0x135, 0x137, 0x138, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144,
    0x146, 0x148, 0x149, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155,
472
473
474
475
476
477
478
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
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
558
559
560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
575







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+



-
+














-
+



-
+
+










-
+







    0x4A9, 0x4AB, 0x4AD, 0x4AF, 0x4B1, 0x4B3, 0x4B5, 0x4B7, 0x4B9,
    0x4BB, 0x4BD, 0x4BF, 0x4C2, 0x4C4, 0x4C6, 0x4C8, 0x4CA, 0x4CC,
    0x4CE, 0x4CF, 0x4D1, 0x4D3, 0x4D5, 0x4D7, 0x4D9, 0x4DB, 0x4DD,
    0x4DF, 0x4E1, 0x4E3, 0x4E5, 0x4E7, 0x4E9, 0x4EB, 0x4ED, 0x4EF,
    0x4F1, 0x4F3, 0x4F5, 0x4F7, 0x4F9, 0x4FB, 0x4FD, 0x4FF, 0x501,
    0x503, 0x505, 0x507, 0x509, 0x50B, 0x50D, 0x50F, 0x511, 0x513,
    0x515, 0x517, 0x519, 0x51B, 0x51D, 0x51F, 0x521, 0x523, 0x525,
    0x527, 0x529, 0x52B, 0x52D, 0x52F, 0x1E01, 0x1E03, 0x1E05, 0x1E07,
    0x1E09, 0x1E0B, 0x1E0D, 0x1E0F, 0x1E11, 0x1E13, 0x1E15, 0x1E17, 0x1E19,
    0x1E1B, 0x1E1D, 0x1E1F, 0x1E21, 0x1E23, 0x1E25, 0x1E27, 0x1E29, 0x1E2B,
    0x1E2D, 0x1E2F, 0x1E31, 0x1E33, 0x1E35, 0x1E37, 0x1E39, 0x1E3B, 0x1E3D,
    0x1E3F, 0x1E41, 0x1E43, 0x1E45, 0x1E47, 0x1E49, 0x1E4B, 0x1E4D, 0x1E4F,
    0x1E51, 0x1E53, 0x1E55, 0x1E57, 0x1E59, 0x1E5B, 0x1E5D, 0x1E5F, 0x1E61,
    0x1E63, 0x1E65, 0x1E67, 0x1E69, 0x1E6B, 0x1E6D, 0x1E6F, 0x1E71, 0x1E73,
    0x1E75, 0x1E77, 0x1E79, 0x1E7B, 0x1E7D, 0x1E7F, 0x1E81, 0x1E83, 0x1E85,
    0x1E87, 0x1E89, 0x1E8B, 0x1E8D, 0x1E8F, 0x1E91, 0x1E93, 0x1E9F, 0x1EA1,
    0x1EA3, 0x1EA5, 0x1EA7, 0x1EA9, 0x1EAB, 0x1EAD, 0x1EAF, 0x1EB1, 0x1EB3,
    0x1EB5, 0x1EB7, 0x1EB9, 0x1EBB, 0x1EBD, 0x1EBF, 0x1EC1, 0x1EC3, 0x1EC5,
    0x1EC7, 0x1EC9, 0x1ECB, 0x1ECD, 0x1ECF, 0x1ED1, 0x1ED3, 0x1ED5, 0x1ED7,
    0x1ED9, 0x1EDB, 0x1EDD, 0x1EDF, 0x1EE1, 0x1EE3, 0x1EE5, 0x1EE7, 0x1EE9,
    0x1EEB, 0x1EED, 0x1EEF, 0x1EF1, 0x1EF3, 0x1EF5, 0x1EF7, 0x1EF9, 0x1EFB,
    0x1EFD, 0x1FB6, 0x1FB7, 0x1FBE, 0x1FC6, 0x1FC7, 0x1FD6, 0x1FD7, 0x1FF6,
    0x1FF7, 0x210A, 0x210E, 0x210F, 0x2113, 0x212F, 0x2134, 0x2139, 0x213C,
    0x213D, 0x214E, 0x2184, 0x2C61, 0x2C65, 0x2C66, 0x2C68, 0x2C6A, 0x2C6C,
    0x2C71, 0x2C73, 0x2C74, 0x2C81, 0x2C83, 0x2C85, 0x2C87, 0x2C89, 0x2C8B,
    0x2C8D, 0x2C8F, 0x2C91, 0x2C93, 0x2C95, 0x2C97, 0x2C99, 0x2C9B, 0x2C9D,
    0x2C9F, 0x2CA1, 0x2CA3, 0x2CA5, 0x2CA7, 0x2CA9, 0x2CAB, 0x2CAD, 0x2CAF,
    0x2CB1, 0x2CB3, 0x2CB5, 0x2CB7, 0x2CB9, 0x2CBB, 0x2CBD, 0x2CBF, 0x2CC1,
    0x2CC3, 0x2CC5, 0x2CC7, 0x2CC9, 0x2CCB, 0x2CCD, 0x2CCF, 0x2CD1, 0x2CD3,
    0x2CD5, 0x2CD7, 0x2CD9, 0x2CDB, 0x2CDD, 0x2CDF, 0x2CE1, 0x2CE3, 0x2CE4,
    0x2CEC, 0x2CEE, 0x2CF3, 0x2D27, 0x2D2D, 0xA641, 0xA643, 0xA645, 0xA647,
    0xA649, 0xA64B, 0xA64D, 0xA64F, 0xA651, 0xA653, 0xA655, 0xA657, 0xA659,
    0xA65B, 0xA65D, 0xA65F, 0xA661, 0xA663, 0xA665, 0xA667, 0xA669, 0xA66B,
    0xA66D, 0xA681, 0xA683, 0xA685, 0xA687, 0xA689, 0xA68B, 0xA68D, 0xA68F,
    0xA691, 0xA693, 0xA695, 0xA697, 0xA699, 0xA69B, 0xA723, 0xA725, 0xA727,
    0xA729, 0xA72B, 0xA72D, 0xA733, 0xA735, 0xA737, 0xA739, 0xA73B, 0xA73D,
    0xA73F, 0xA741, 0xA743, 0xA745, 0xA747, 0xA749, 0xA74B, 0xA74D, 0xA74F,
    0xA751, 0xA753, 0xA755, 0xA757, 0xA759, 0xA75B, 0xA75D, 0xA75F, 0xA761,
    0xA763, 0xA765, 0xA767, 0xA769, 0xA76B, 0xA76D, 0xA76F, 0xA77A, 0xA77C,
    0xA77F, 0xA781, 0xA783, 0xA785, 0xA787, 0xA78C, 0xA78E, 0xA791, 0xA797,
    0xA799, 0xA79B, 0xA79D, 0xA79F, 0xA7A1, 0xA7A3, 0xA7A5, 0xA7A7, 0xA7A9,
    0xA7AF, 0xA7B5, 0xA7B7, 0xA7B9, 0xA7BB, 0xA7BD, 0xA7BF, 0xA7C3, 0xA7C8,
    0xA7CA, 0xA7F6, 0xA7FA
    0x527, 0x529, 0x52B, 0x52D, 0x52F, 0x1C8A, 0x1E01, 0x1E03, 0x1E05,
    0x1E07, 0x1E09, 0x1E0B, 0x1E0D, 0x1E0F, 0x1E11, 0x1E13, 0x1E15, 0x1E17,
    0x1E19, 0x1E1B, 0x1E1D, 0x1E1F, 0x1E21, 0x1E23, 0x1E25, 0x1E27, 0x1E29,
    0x1E2B, 0x1E2D, 0x1E2F, 0x1E31, 0x1E33, 0x1E35, 0x1E37, 0x1E39, 0x1E3B,
    0x1E3D, 0x1E3F, 0x1E41, 0x1E43, 0x1E45, 0x1E47, 0x1E49, 0x1E4B, 0x1E4D,
    0x1E4F, 0x1E51, 0x1E53, 0x1E55, 0x1E57, 0x1E59, 0x1E5B, 0x1E5D, 0x1E5F,
    0x1E61, 0x1E63, 0x1E65, 0x1E67, 0x1E69, 0x1E6B, 0x1E6D, 0x1E6F, 0x1E71,
    0x1E73, 0x1E75, 0x1E77, 0x1E79, 0x1E7B, 0x1E7D, 0x1E7F, 0x1E81, 0x1E83,
    0x1E85, 0x1E87, 0x1E89, 0x1E8B, 0x1E8D, 0x1E8F, 0x1E91, 0x1E93, 0x1E9F,
    0x1EA1, 0x1EA3, 0x1EA5, 0x1EA7, 0x1EA9, 0x1EAB, 0x1EAD, 0x1EAF, 0x1EB1,
    0x1EB3, 0x1EB5, 0x1EB7, 0x1EB9, 0x1EBB, 0x1EBD, 0x1EBF, 0x1EC1, 0x1EC3,
    0x1EC5, 0x1EC7, 0x1EC9, 0x1ECB, 0x1ECD, 0x1ECF, 0x1ED1, 0x1ED3, 0x1ED5,
    0x1ED7, 0x1ED9, 0x1EDB, 0x1EDD, 0x1EDF, 0x1EE1, 0x1EE3, 0x1EE5, 0x1EE7,
    0x1EE9, 0x1EEB, 0x1EED, 0x1EEF, 0x1EF1, 0x1EF3, 0x1EF5, 0x1EF7, 0x1EF9,
    0x1EFB, 0x1EFD, 0x1FB6, 0x1FB7, 0x1FBE, 0x1FC6, 0x1FC7, 0x1FD6, 0x1FD7,
    0x1FF6, 0x1FF7, 0x210A, 0x210E, 0x210F, 0x2113, 0x212F, 0x2134, 0x2139,
    0x213C, 0x213D, 0x214E, 0x2184, 0x2C61, 0x2C65, 0x2C66, 0x2C68, 0x2C6A,
    0x2C6C, 0x2C71, 0x2C73, 0x2C74, 0x2C81, 0x2C83, 0x2C85, 0x2C87, 0x2C89,
    0x2C8B, 0x2C8D, 0x2C8F, 0x2C91, 0x2C93, 0x2C95, 0x2C97, 0x2C99, 0x2C9B,
    0x2C9D, 0x2C9F, 0x2CA1, 0x2CA3, 0x2CA5, 0x2CA7, 0x2CA9, 0x2CAB, 0x2CAD,
    0x2CAF, 0x2CB1, 0x2CB3, 0x2CB5, 0x2CB7, 0x2CB9, 0x2CBB, 0x2CBD, 0x2CBF,
    0x2CC1, 0x2CC3, 0x2CC5, 0x2CC7, 0x2CC9, 0x2CCB, 0x2CCD, 0x2CCF, 0x2CD1,
    0x2CD3, 0x2CD5, 0x2CD7, 0x2CD9, 0x2CDB, 0x2CDD, 0x2CDF, 0x2CE1, 0x2CE3,
    0x2CE4, 0x2CEC, 0x2CEE, 0x2CF3, 0x2D27, 0x2D2D, 0xA641, 0xA643, 0xA645,
    0xA647, 0xA649, 0xA64B, 0xA64D, 0xA64F, 0xA651, 0xA653, 0xA655, 0xA657,
    0xA659, 0xA65B, 0xA65D, 0xA65F, 0xA661, 0xA663, 0xA665, 0xA667, 0xA669,
    0xA66B, 0xA66D, 0xA681, 0xA683, 0xA685, 0xA687, 0xA689, 0xA68B, 0xA68D,
    0xA68F, 0xA691, 0xA693, 0xA695, 0xA697, 0xA699, 0xA69B, 0xA723, 0xA725,
    0xA727, 0xA729, 0xA72B, 0xA72D, 0xA733, 0xA735, 0xA737, 0xA739, 0xA73B,
    0xA73D, 0xA73F, 0xA741, 0xA743, 0xA745, 0xA747, 0xA749, 0xA74B, 0xA74D,
    0xA74F, 0xA751, 0xA753, 0xA755, 0xA757, 0xA759, 0xA75B, 0xA75D, 0xA75F,
    0xA761, 0xA763, 0xA765, 0xA767, 0xA769, 0xA76B, 0xA76D, 0xA76F, 0xA77A,
    0xA77C, 0xA77F, 0xA781, 0xA783, 0xA785, 0xA787, 0xA78C, 0xA78E, 0xA791,
    0xA797, 0xA799, 0xA79B, 0xA79D, 0xA79F, 0xA7A1, 0xA7A3, 0xA7A5, 0xA7A7,
    0xA7A9, 0xA7AF, 0xA7B5, 0xA7B7, 0xA7B9, 0xA7BB, 0xA7BD, 0xA7BF, 0xA7C1,
    0xA7C3, 0xA7C8, 0xA7CA, 0xA7CD, 0xA7D1, 0xA7D3, 0xA7D5, 0xA7D7, 0xA7D9,
    0xA7DB, 0xA7F6, 0xA7FA
#if CHRBITS > 16
    ,0x1D4BB, 0x1D7CB
    ,0x105BB, 0x105BC, 0x1D4BB, 0x1D7CB
#endif
};

#define NUM_LOWER_CHAR (sizeof(lowerCharTable)/sizeof(chr))
#define NUM_LOWER_CHAR ((int)(sizeof(lowerCharTable)/sizeof(chr)))

/*
 * Unicode: uppercase characters.
 */

static const crange upperRangeTable[] = {
    {0x41, 0x5A}, {0xC0, 0xD6}, {0xD8, 0xDE}, {0x189, 0x18B},
    {0x18E, 0x191}, {0x196, 0x198}, {0x1B1, 0x1B3}, {0x1F6, 0x1F8},
    {0x243, 0x246}, {0x388, 0x38A}, {0x391, 0x3A1}, {0x3A3, 0x3AB},
    {0x3D2, 0x3D4}, {0x3FD, 0x42F}, {0x531, 0x556}, {0x10A0, 0x10C5},
    {0x13A0, 0x13F5}, {0x1C90, 0x1CBA}, {0x1CBD, 0x1CBF}, {0x1F08, 0x1F0F},
    {0x1F18, 0x1F1D}, {0x1F28, 0x1F2F}, {0x1F38, 0x1F3F}, {0x1F48, 0x1F4D},
    {0x1F68, 0x1F6F}, {0x1FB8, 0x1FBB}, {0x1FC8, 0x1FCB}, {0x1FD8, 0x1FDB},
    {0x1FE8, 0x1FEC}, {0x1FF8, 0x1FFB}, {0x210B, 0x210D}, {0x2110, 0x2112},
    {0x2119, 0x211D}, {0x212A, 0x212D}, {0x2130, 0x2133}, {0x2C00, 0x2C2E},
    {0x2119, 0x211D}, {0x212A, 0x212D}, {0x2130, 0x2133}, {0x2C00, 0x2C2F},
    {0x2C62, 0x2C64}, {0x2C6D, 0x2C70}, {0x2C7E, 0x2C80}, {0xA7AA, 0xA7AE},
    {0xA7B0, 0xA7B4}, {0xA7C4, 0xA7C7}, {0xFF21, 0xFF3A}
#if CHRBITS > 16
    ,{0x10400, 0x10427}, {0x104B0, 0x104D3}, {0x10C80, 0x10CB2}, {0x118A0, 0x118BF},
    ,{0x10400, 0x10427}, {0x104B0, 0x104D3}, {0x10570, 0x1057A}, {0x1057C, 0x1058A},
    {0x1058C, 0x10592}, {0x10C80, 0x10CB2}, {0x10D50, 0x10D65}, {0x118A0, 0x118BF},
    {0x16E40, 0x16E5F}, {0x1D400, 0x1D419}, {0x1D434, 0x1D44D}, {0x1D468, 0x1D481},
    {0x1D4A9, 0x1D4AC}, {0x1D4AE, 0x1D4B5}, {0x1D4D0, 0x1D4E9}, {0x1D507, 0x1D50A},
    {0x1D50D, 0x1D514}, {0x1D516, 0x1D51C}, {0x1D53B, 0x1D53E}, {0x1D540, 0x1D544},
    {0x1D54A, 0x1D550}, {0x1D56C, 0x1D585}, {0x1D5A0, 0x1D5B9}, {0x1D5D4, 0x1D5ED},
    {0x1D608, 0x1D621}, {0x1D63C, 0x1D655}, {0x1D670, 0x1D689}, {0x1D6A8, 0x1D6C0},
    {0x1D6E2, 0x1D6FA}, {0x1D71C, 0x1D734}, {0x1D756, 0x1D76E}, {0x1D790, 0x1D7A8},
    {0x1E900, 0x1E921}
#endif
};

#define NUM_UPPER_RANGE (sizeof(upperRangeTable)/sizeof(crange))
#define NUM_UPPER_RANGE ((int)(sizeof(upperRangeTable)/sizeof(crange)))

static const chr upperCharTable[] = {
    0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110,
    0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122,
    0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134,
    0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147,
    0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A,
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616



































617
618
619


620
621
622
623

624
625
626
627
628
629
630
631
632
633

634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653



















654
655
656
657
658
659

660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732



























733
734
735
736
737
738
739
740
741
742











743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772

































773
774
775
776

777
778
779
780
781
782
783
784

785
786
787
788


789
790
791
792
793
794
795
796
797
798
799












800
801
802
803

804
805
806
807
808
809
810
594
595
596
597
598
599
600


































601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636


637
638
639
640
641

642
643
644
645
646
647
648
649
650
651

652
653



















654
655
656
657
658
659
660
661
662
663
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
707











708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727






















728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756








757
758
759
760
761
762
763
764
765
766
767
768





























769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804

805
806
807
808
809
810
811
812

813
814
815


816
817
818










819
820
821
822
823
824
825
826
827
828
829
830
831
832
833

834
835
836
837
838
839
840
841







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+



-
+









-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+






-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+










-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+







-
+


-
-
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+



-
+







    0x4B0, 0x4B2, 0x4B4, 0x4B6, 0x4B8, 0x4BA, 0x4BC, 0x4BE, 0x4C0,
    0x4C1, 0x4C3, 0x4C5, 0x4C7, 0x4C9, 0x4CB, 0x4CD, 0x4D0, 0x4D2,
    0x4D4, 0x4D6, 0x4D8, 0x4DA, 0x4DC, 0x4DE, 0x4E0, 0x4E2, 0x4E4,
    0x4E6, 0x4E8, 0x4EA, 0x4EC, 0x4EE, 0x4F0, 0x4F2, 0x4F4, 0x4F6,
    0x4F8, 0x4FA, 0x4FC, 0x4FE, 0x500, 0x502, 0x504, 0x506, 0x508,
    0x50A, 0x50C, 0x50E, 0x510, 0x512, 0x514, 0x516, 0x518, 0x51A,
    0x51C, 0x51E, 0x520, 0x522, 0x524, 0x526, 0x528, 0x52A, 0x52C,
    0x52E, 0x10C7, 0x10CD, 0x1E00, 0x1E02, 0x1E04, 0x1E06, 0x1E08, 0x1E0A,
    0x1E0C, 0x1E0E, 0x1E10, 0x1E12, 0x1E14, 0x1E16, 0x1E18, 0x1E1A, 0x1E1C,
    0x1E1E, 0x1E20, 0x1E22, 0x1E24, 0x1E26, 0x1E28, 0x1E2A, 0x1E2C, 0x1E2E,
    0x1E30, 0x1E32, 0x1E34, 0x1E36, 0x1E38, 0x1E3A, 0x1E3C, 0x1E3E, 0x1E40,
    0x1E42, 0x1E44, 0x1E46, 0x1E48, 0x1E4A, 0x1E4C, 0x1E4E, 0x1E50, 0x1E52,
    0x1E54, 0x1E56, 0x1E58, 0x1E5A, 0x1E5C, 0x1E5E, 0x1E60, 0x1E62, 0x1E64,
    0x1E66, 0x1E68, 0x1E6A, 0x1E6C, 0x1E6E, 0x1E70, 0x1E72, 0x1E74, 0x1E76,
    0x1E78, 0x1E7A, 0x1E7C, 0x1E7E, 0x1E80, 0x1E82, 0x1E84, 0x1E86, 0x1E88,
    0x1E8A, 0x1E8C, 0x1E8E, 0x1E90, 0x1E92, 0x1E94, 0x1E9E, 0x1EA0, 0x1EA2,
    0x1EA4, 0x1EA6, 0x1EA8, 0x1EAA, 0x1EAC, 0x1EAE, 0x1EB0, 0x1EB2, 0x1EB4,
    0x1EB6, 0x1EB8, 0x1EBA, 0x1EBC, 0x1EBE, 0x1EC0, 0x1EC2, 0x1EC4, 0x1EC6,
    0x1EC8, 0x1ECA, 0x1ECC, 0x1ECE, 0x1ED0, 0x1ED2, 0x1ED4, 0x1ED6, 0x1ED8,
    0x1EDA, 0x1EDC, 0x1EDE, 0x1EE0, 0x1EE2, 0x1EE4, 0x1EE6, 0x1EE8, 0x1EEA,
    0x1EEC, 0x1EEE, 0x1EF0, 0x1EF2, 0x1EF4, 0x1EF6, 0x1EF8, 0x1EFA, 0x1EFC,
    0x1EFE, 0x1F59, 0x1F5B, 0x1F5D, 0x1F5F, 0x2102, 0x2107, 0x2115, 0x2124,
    0x2126, 0x2128, 0x213E, 0x213F, 0x2145, 0x2183, 0x2C60, 0x2C67, 0x2C69,
    0x2C6B, 0x2C72, 0x2C75, 0x2C82, 0x2C84, 0x2C86, 0x2C88, 0x2C8A, 0x2C8C,
    0x2C8E, 0x2C90, 0x2C92, 0x2C94, 0x2C96, 0x2C98, 0x2C9A, 0x2C9C, 0x2C9E,
    0x2CA0, 0x2CA2, 0x2CA4, 0x2CA6, 0x2CA8, 0x2CAA, 0x2CAC, 0x2CAE, 0x2CB0,
    0x2CB2, 0x2CB4, 0x2CB6, 0x2CB8, 0x2CBA, 0x2CBC, 0x2CBE, 0x2CC0, 0x2CC2,
    0x2CC4, 0x2CC6, 0x2CC8, 0x2CCA, 0x2CCC, 0x2CCE, 0x2CD0, 0x2CD2, 0x2CD4,
    0x2CD6, 0x2CD8, 0x2CDA, 0x2CDC, 0x2CDE, 0x2CE0, 0x2CE2, 0x2CEB, 0x2CED,
    0x2CF2, 0xA640, 0xA642, 0xA644, 0xA646, 0xA648, 0xA64A, 0xA64C, 0xA64E,
    0xA650, 0xA652, 0xA654, 0xA656, 0xA658, 0xA65A, 0xA65C, 0xA65E, 0xA660,
    0xA662, 0xA664, 0xA666, 0xA668, 0xA66A, 0xA66C, 0xA680, 0xA682, 0xA684,
    0xA686, 0xA688, 0xA68A, 0xA68C, 0xA68E, 0xA690, 0xA692, 0xA694, 0xA696,
    0xA698, 0xA69A, 0xA722, 0xA724, 0xA726, 0xA728, 0xA72A, 0xA72C, 0xA72E,
    0xA732, 0xA734, 0xA736, 0xA738, 0xA73A, 0xA73C, 0xA73E, 0xA740, 0xA742,
    0xA744, 0xA746, 0xA748, 0xA74A, 0xA74C, 0xA74E, 0xA750, 0xA752, 0xA754,
    0xA756, 0xA758, 0xA75A, 0xA75C, 0xA75E, 0xA760, 0xA762, 0xA764, 0xA766,
    0xA768, 0xA76A, 0xA76C, 0xA76E, 0xA779, 0xA77B, 0xA77D, 0xA77E, 0xA780,
    0xA782, 0xA784, 0xA786, 0xA78B, 0xA78D, 0xA790, 0xA792, 0xA796, 0xA798,
    0xA79A, 0xA79C, 0xA79E, 0xA7A0, 0xA7A2, 0xA7A4, 0xA7A6, 0xA7A8, 0xA7B6,
    0xA7B8, 0xA7BA, 0xA7BC, 0xA7BE, 0xA7C2, 0xA7C9, 0xA7F5
    0x52E, 0x10C7, 0x10CD, 0x1C89, 0x1E00, 0x1E02, 0x1E04, 0x1E06, 0x1E08,
    0x1E0A, 0x1E0C, 0x1E0E, 0x1E10, 0x1E12, 0x1E14, 0x1E16, 0x1E18, 0x1E1A,
    0x1E1C, 0x1E1E, 0x1E20, 0x1E22, 0x1E24, 0x1E26, 0x1E28, 0x1E2A, 0x1E2C,
    0x1E2E, 0x1E30, 0x1E32, 0x1E34, 0x1E36, 0x1E38, 0x1E3A, 0x1E3C, 0x1E3E,
    0x1E40, 0x1E42, 0x1E44, 0x1E46, 0x1E48, 0x1E4A, 0x1E4C, 0x1E4E, 0x1E50,
    0x1E52, 0x1E54, 0x1E56, 0x1E58, 0x1E5A, 0x1E5C, 0x1E5E, 0x1E60, 0x1E62,
    0x1E64, 0x1E66, 0x1E68, 0x1E6A, 0x1E6C, 0x1E6E, 0x1E70, 0x1E72, 0x1E74,
    0x1E76, 0x1E78, 0x1E7A, 0x1E7C, 0x1E7E, 0x1E80, 0x1E82, 0x1E84, 0x1E86,
    0x1E88, 0x1E8A, 0x1E8C, 0x1E8E, 0x1E90, 0x1E92, 0x1E94, 0x1E9E, 0x1EA0,
    0x1EA2, 0x1EA4, 0x1EA6, 0x1EA8, 0x1EAA, 0x1EAC, 0x1EAE, 0x1EB0, 0x1EB2,
    0x1EB4, 0x1EB6, 0x1EB8, 0x1EBA, 0x1EBC, 0x1EBE, 0x1EC0, 0x1EC2, 0x1EC4,
    0x1EC6, 0x1EC8, 0x1ECA, 0x1ECC, 0x1ECE, 0x1ED0, 0x1ED2, 0x1ED4, 0x1ED6,
    0x1ED8, 0x1EDA, 0x1EDC, 0x1EDE, 0x1EE0, 0x1EE2, 0x1EE4, 0x1EE6, 0x1EE8,
    0x1EEA, 0x1EEC, 0x1EEE, 0x1EF0, 0x1EF2, 0x1EF4, 0x1EF6, 0x1EF8, 0x1EFA,
    0x1EFC, 0x1EFE, 0x1F59, 0x1F5B, 0x1F5D, 0x1F5F, 0x2102, 0x2107, 0x2115,
    0x2124, 0x2126, 0x2128, 0x213E, 0x213F, 0x2145, 0x2183, 0x2C60, 0x2C67,
    0x2C69, 0x2C6B, 0x2C72, 0x2C75, 0x2C82, 0x2C84, 0x2C86, 0x2C88, 0x2C8A,
    0x2C8C, 0x2C8E, 0x2C90, 0x2C92, 0x2C94, 0x2C96, 0x2C98, 0x2C9A, 0x2C9C,
    0x2C9E, 0x2CA0, 0x2CA2, 0x2CA4, 0x2CA6, 0x2CA8, 0x2CAA, 0x2CAC, 0x2CAE,
    0x2CB0, 0x2CB2, 0x2CB4, 0x2CB6, 0x2CB8, 0x2CBA, 0x2CBC, 0x2CBE, 0x2CC0,
    0x2CC2, 0x2CC4, 0x2CC6, 0x2CC8, 0x2CCA, 0x2CCC, 0x2CCE, 0x2CD0, 0x2CD2,
    0x2CD4, 0x2CD6, 0x2CD8, 0x2CDA, 0x2CDC, 0x2CDE, 0x2CE0, 0x2CE2, 0x2CEB,
    0x2CED, 0x2CF2, 0xA640, 0xA642, 0xA644, 0xA646, 0xA648, 0xA64A, 0xA64C,
    0xA64E, 0xA650, 0xA652, 0xA654, 0xA656, 0xA658, 0xA65A, 0xA65C, 0xA65E,
    0xA660, 0xA662, 0xA664, 0xA666, 0xA668, 0xA66A, 0xA66C, 0xA680, 0xA682,
    0xA684, 0xA686, 0xA688, 0xA68A, 0xA68C, 0xA68E, 0xA690, 0xA692, 0xA694,
    0xA696, 0xA698, 0xA69A, 0xA722, 0xA724, 0xA726, 0xA728, 0xA72A, 0xA72C,
    0xA72E, 0xA732, 0xA734, 0xA736, 0xA738, 0xA73A, 0xA73C, 0xA73E, 0xA740,
    0xA742, 0xA744, 0xA746, 0xA748, 0xA74A, 0xA74C, 0xA74E, 0xA750, 0xA752,
    0xA754, 0xA756, 0xA758, 0xA75A, 0xA75C, 0xA75E, 0xA760, 0xA762, 0xA764,
    0xA766, 0xA768, 0xA76A, 0xA76C, 0xA76E, 0xA779, 0xA77B, 0xA77D, 0xA77E,
    0xA780, 0xA782, 0xA784, 0xA786, 0xA78B, 0xA78D, 0xA790, 0xA792, 0xA796,
    0xA798, 0xA79A, 0xA79C, 0xA79E, 0xA7A0, 0xA7A2, 0xA7A4, 0xA7A6, 0xA7A8,
    0xA7B6, 0xA7B8, 0xA7BA, 0xA7BC, 0xA7BE, 0xA7C0, 0xA7C2, 0xA7C9, 0xA7CB,
    0xA7CC, 0xA7D0, 0xA7D6, 0xA7D8, 0xA7DA, 0xA7DC, 0xA7F5
#if CHRBITS > 16
    ,0x1D49C, 0x1D49E, 0x1D49F, 0x1D4A2, 0x1D4A5, 0x1D4A6, 0x1D504, 0x1D505, 0x1D538,
    0x1D539, 0x1D546, 0x1D7CA
    ,0x10594, 0x10595, 0x1D49C, 0x1D49E, 0x1D49F, 0x1D4A2, 0x1D4A5, 0x1D4A6, 0x1D504,
    0x1D505, 0x1D538, 0x1D539, 0x1D546, 0x1D7CA
#endif
};

#define NUM_UPPER_CHAR (sizeof(upperCharTable)/sizeof(chr))
#define NUM_UPPER_CHAR ((int)(sizeof(upperCharTable)/sizeof(chr)))

/*
 * Unicode: unicode print characters excluding space.
 */

static const crange graphRangeTable[] = {
    {0x21, 0x7E}, {0xA1, 0xAC}, {0xAE, 0x377}, {0x37A, 0x37F},
    {0x384, 0x38A}, {0x38E, 0x3A1}, {0x3A3, 0x52F}, {0x531, 0x556},
    {0x559, 0x58A}, {0x58D, 0x58F}, {0x591, 0x5C7}, {0x5D0, 0x5EA},
    {0x5EF, 0x5F4}, {0x606, 0x61B}, {0x61E, 0x6DC}, {0x6DE, 0x70D},
    {0x5EF, 0x5F4}, {0x606, 0x61B}, {0x61D, 0x6DC}, {0x6DE, 0x70D},
    {0x710, 0x74A}, {0x74D, 0x7B1}, {0x7C0, 0x7FA}, {0x7FD, 0x82D},
    {0x830, 0x83E}, {0x840, 0x85B}, {0x860, 0x86A}, {0x8A0, 0x8B4},
    {0x8B6, 0x8C7}, {0x8D3, 0x8E1}, {0x8E3, 0x983}, {0x985, 0x98C},
    {0x993, 0x9A8}, {0x9AA, 0x9B0}, {0x9B6, 0x9B9}, {0x9BC, 0x9C4},
    {0x9CB, 0x9CE}, {0x9DF, 0x9E3}, {0x9E6, 0x9FE}, {0xA01, 0xA03},
    {0xA05, 0xA0A}, {0xA13, 0xA28}, {0xA2A, 0xA30}, {0xA3E, 0xA42},
    {0xA4B, 0xA4D}, {0xA59, 0xA5C}, {0xA66, 0xA76}, {0xA81, 0xA83},
    {0xA85, 0xA8D}, {0xA8F, 0xA91}, {0xA93, 0xAA8}, {0xAAA, 0xAB0},
    {0xAB5, 0xAB9}, {0xABC, 0xAC5}, {0xAC7, 0xAC9}, {0xACB, 0xACD},
    {0xAE0, 0xAE3}, {0xAE6, 0xAF1}, {0xAF9, 0xAFF}, {0xB01, 0xB03},
    {0xB05, 0xB0C}, {0xB13, 0xB28}, {0xB2A, 0xB30}, {0xB35, 0xB39},
    {0xB3C, 0xB44}, {0xB4B, 0xB4D}, {0xB55, 0xB57}, {0xB5F, 0xB63},
    {0xB66, 0xB77}, {0xB85, 0xB8A}, {0xB8E, 0xB90}, {0xB92, 0xB95},
    {0xBA8, 0xBAA}, {0xBAE, 0xBB9}, {0xBBE, 0xBC2}, {0xBC6, 0xBC8},
    {0xBCA, 0xBCD}, {0xBE6, 0xBFA}, {0xC00, 0xC0C}, {0xC0E, 0xC10},
    {0xC12, 0xC28}, {0xC2A, 0xC39}, {0xC3D, 0xC44}, {0xC46, 0xC48},
    {0xC4A, 0xC4D}, {0xC58, 0xC5A}, {0xC60, 0xC63}, {0xC66, 0xC6F},
    {0xC77, 0xC8C}, {0xC8E, 0xC90}, {0xC92, 0xCA8}, {0xCAA, 0xCB3},
    {0xCB5, 0xCB9}, {0xCBC, 0xCC4}, {0xCC6, 0xCC8}, {0xCCA, 0xCCD},
    {0xCE0, 0xCE3}, {0xCE6, 0xCEF}, {0xD00, 0xD0C}, {0xD0E, 0xD10},
    {0x830, 0x83E}, {0x840, 0x85B}, {0x860, 0x86A}, {0x870, 0x88E},
    {0x897, 0x8E1}, {0x8E3, 0x983}, {0x985, 0x98C}, {0x993, 0x9A8},
    {0x9AA, 0x9B0}, {0x9B6, 0x9B9}, {0x9BC, 0x9C4}, {0x9CB, 0x9CE},
    {0x9DF, 0x9E3}, {0x9E6, 0x9FE}, {0xA01, 0xA03}, {0xA05, 0xA0A},
    {0xA13, 0xA28}, {0xA2A, 0xA30}, {0xA3E, 0xA42}, {0xA4B, 0xA4D},
    {0xA59, 0xA5C}, {0xA66, 0xA76}, {0xA81, 0xA83}, {0xA85, 0xA8D},
    {0xA8F, 0xA91}, {0xA93, 0xAA8}, {0xAAA, 0xAB0}, {0xAB5, 0xAB9},
    {0xABC, 0xAC5}, {0xAC7, 0xAC9}, {0xACB, 0xACD}, {0xAE0, 0xAE3},
    {0xAE6, 0xAF1}, {0xAF9, 0xAFF}, {0xB01, 0xB03}, {0xB05, 0xB0C},
    {0xB13, 0xB28}, {0xB2A, 0xB30}, {0xB35, 0xB39}, {0xB3C, 0xB44},
    {0xB4B, 0xB4D}, {0xB55, 0xB57}, {0xB5F, 0xB63}, {0xB66, 0xB77},
    {0xB85, 0xB8A}, {0xB8E, 0xB90}, {0xB92, 0xB95}, {0xBA8, 0xBAA},
    {0xBAE, 0xBB9}, {0xBBE, 0xBC2}, {0xBC6, 0xBC8}, {0xBCA, 0xBCD},
    {0xBE6, 0xBFA}, {0xC00, 0xC0C}, {0xC0E, 0xC10}, {0xC12, 0xC28},
    {0xC2A, 0xC39}, {0xC3C, 0xC44}, {0xC46, 0xC48}, {0xC4A, 0xC4D},
    {0xC58, 0xC5A}, {0xC60, 0xC63}, {0xC66, 0xC6F}, {0xC77, 0xC8C},
    {0xC8E, 0xC90}, {0xC92, 0xCA8}, {0xCAA, 0xCB3}, {0xCB5, 0xCB9},
    {0xCBC, 0xCC4}, {0xCC6, 0xCC8}, {0xCCA, 0xCCD}, {0xCE0, 0xCE3},
    {0xCE6, 0xCEF}, {0xCF1, 0xCF3}, {0xD00, 0xD0C}, {0xD0E, 0xD10},
    {0xD12, 0xD44}, {0xD46, 0xD48}, {0xD4A, 0xD4F}, {0xD54, 0xD63},
    {0xD66, 0xD7F}, {0xD81, 0xD83}, {0xD85, 0xD96}, {0xD9A, 0xDB1},
    {0xDB3, 0xDBB}, {0xDC0, 0xDC6}, {0xDCF, 0xDD4}, {0xDD8, 0xDDF},
    {0xDE6, 0xDEF}, {0xDF2, 0xDF4}, {0xE01, 0xE3A}, {0xE3F, 0xE5B},
    {0xE86, 0xE8A}, {0xE8C, 0xEA3}, {0xEA7, 0xEBD}, {0xEC0, 0xEC4},
    {0xEC8, 0xECD}, {0xED0, 0xED9}, {0xEDC, 0xEDF}, {0xF00, 0xF47},
    {0xEC8, 0xECE}, {0xED0, 0xED9}, {0xEDC, 0xEDF}, {0xF00, 0xF47},
    {0xF49, 0xF6C}, {0xF71, 0xF97}, {0xF99, 0xFBC}, {0xFBE, 0xFCC},
    {0xFCE, 0xFDA}, {0x1000, 0x10C5}, {0x10D0, 0x1248}, {0x124A, 0x124D},
    {0x1250, 0x1256}, {0x125A, 0x125D}, {0x1260, 0x1288}, {0x128A, 0x128D},
    {0x1290, 0x12B0}, {0x12B2, 0x12B5}, {0x12B8, 0x12BE}, {0x12C2, 0x12C5},
    {0x12C8, 0x12D6}, {0x12D8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135A},
    {0x135D, 0x137C}, {0x1380, 0x1399}, {0x13A0, 0x13F5}, {0x13F8, 0x13FD},
    {0x1400, 0x167F}, {0x1681, 0x169C}, {0x16A0, 0x16F8}, {0x1700, 0x170C},
    {0x170E, 0x1714}, {0x1720, 0x1736}, {0x1740, 0x1753}, {0x1760, 0x176C},
    {0x176E, 0x1770}, {0x1780, 0x17DD}, {0x17E0, 0x17E9}, {0x17F0, 0x17F9},
    {0x1800, 0x180D}, {0x1810, 0x1819}, {0x1820, 0x1878}, {0x1880, 0x18AA},
    {0x18B0, 0x18F5}, {0x1900, 0x191E}, {0x1920, 0x192B}, {0x1930, 0x193B},
    {0x1944, 0x196D}, {0x1970, 0x1974}, {0x1980, 0x19AB}, {0x19B0, 0x19C9},
    {0x19D0, 0x19DA}, {0x19DE, 0x1A1B}, {0x1A1E, 0x1A5E}, {0x1A60, 0x1A7C},
    {0x1A7F, 0x1A89}, {0x1A90, 0x1A99}, {0x1AA0, 0x1AAD}, {0x1AB0, 0x1AC0},
    {0x1B00, 0x1B4B}, {0x1B50, 0x1B7C}, {0x1B80, 0x1BF3}, {0x1BFC, 0x1C37},
    {0x1C3B, 0x1C49}, {0x1C4D, 0x1C88}, {0x1C90, 0x1CBA}, {0x1CBD, 0x1CC7},
    {0x1400, 0x167F}, {0x1681, 0x169C}, {0x16A0, 0x16F8}, {0x1700, 0x1715},
    {0x171F, 0x1736}, {0x1740, 0x1753}, {0x1760, 0x176C}, {0x176E, 0x1770},
    {0x1780, 0x17DD}, {0x17E0, 0x17E9}, {0x17F0, 0x17F9}, {0x1800, 0x180D},
    {0x180F, 0x1819}, {0x1820, 0x1878}, {0x1880, 0x18AA}, {0x18B0, 0x18F5},
    {0x1900, 0x191E}, {0x1920, 0x192B}, {0x1930, 0x193B}, {0x1944, 0x196D},
    {0x1970, 0x1974}, {0x1980, 0x19AB}, {0x19B0, 0x19C9}, {0x19D0, 0x19DA},
    {0x19DE, 0x1A1B}, {0x1A1E, 0x1A5E}, {0x1A60, 0x1A7C}, {0x1A7F, 0x1A89},
    {0x1A90, 0x1A99}, {0x1AA0, 0x1AAD}, {0x1AB0, 0x1ACE}, {0x1B00, 0x1B4C},
    {0x1B4E, 0x1BF3}, {0x1BFC, 0x1C37}, {0x1C3B, 0x1C49}, {0x1C4D, 0x1C8A},
    {0x1C90, 0x1CBA}, {0x1CBD, 0x1CC7}, {0x1CD0, 0x1CFA}, {0x1D00, 0x1F15},
    {0x1CD0, 0x1CFA}, {0x1D00, 0x1DF9}, {0x1DFB, 0x1F15}, {0x1F18, 0x1F1D},
    {0x1F20, 0x1F45}, {0x1F48, 0x1F4D}, {0x1F50, 0x1F57}, {0x1F5F, 0x1F7D},
    {0x1F80, 0x1FB4}, {0x1FB6, 0x1FC4}, {0x1FC6, 0x1FD3}, {0x1FD6, 0x1FDB},
    {0x1FDD, 0x1FEF}, {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFE}, {0x2010, 0x2027},
    {0x2030, 0x205E}, {0x2074, 0x208E}, {0x2090, 0x209C}, {0x20A0, 0x20BF},
    {0x20D0, 0x20F0}, {0x2100, 0x218B}, {0x2190, 0x2426}, {0x2440, 0x244A},
    {0x2460, 0x2B73}, {0x2B76, 0x2B95}, {0x2B97, 0x2C2E}, {0x2C30, 0x2C5E},
    {0x2C60, 0x2CF3}, {0x2CF9, 0x2D25}, {0x2D30, 0x2D67}, {0x2D7F, 0x2D96},
    {0x2DA0, 0x2DA6}, {0x2DA8, 0x2DAE}, {0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE},
    {0x2DC0, 0x2DC6}, {0x2DC8, 0x2DCE}, {0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE},
    {0x2DE0, 0x2E52}, {0x2E80, 0x2E99}, {0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5},
    {0x2FF0, 0x2FFB}, {0x3001, 0x303F}, {0x3041, 0x3096}, {0x3099, 0x30FF},
    {0x3105, 0x312F}, {0x3131, 0x318E}, {0x3190, 0x31E3}, {0x31F0, 0x321E},
    {0x3220, 0x9FFC}, {0xA000, 0xA48C}, {0xA490, 0xA4C6}, {0xA4D0, 0xA62B},
    {0x1F18, 0x1F1D}, {0x1F20, 0x1F45}, {0x1F48, 0x1F4D}, {0x1F50, 0x1F57},
    {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4}, {0x1FB6, 0x1FC4}, {0x1FC6, 0x1FD3},
    {0x1FD6, 0x1FDB}, {0x1FDD, 0x1FEF}, {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFE},
    {0x2010, 0x2027}, {0x2030, 0x205E}, {0x2074, 0x208E}, {0x2090, 0x209C},
    {0x20A0, 0x20C0}, {0x20D0, 0x20F0}, {0x2100, 0x218B}, {0x2190, 0x2429},
    {0x2440, 0x244A}, {0x2460, 0x2B73}, {0x2B76, 0x2B95}, {0x2B97, 0x2CF3},
    {0x2CF9, 0x2D25}, {0x2D30, 0x2D67}, {0x2D7F, 0x2D96}, {0x2DA0, 0x2DA6},
    {0x2DA8, 0x2DAE}, {0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE}, {0x2DC0, 0x2DC6},
    {0x2DC8, 0x2DCE}, {0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE}, {0x2DE0, 0x2E5D},
    {0x2E80, 0x2E99}, {0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5}, {0x2FF0, 0x2FFF},
    {0x3001, 0x303F}, {0x3041, 0x3096}, {0x3099, 0x30FF}, {0x3105, 0x312F},
    {0x3131, 0x318E}, {0x3190, 0x31E5}, {0x31EF, 0x321E}, {0x3220, 0xA48C},
    {0xA490, 0xA4C6}, {0xA4D0, 0xA62B}, {0xA640, 0xA6F7}, {0xA700, 0xA7CD},
    {0xA640, 0xA6F7}, {0xA700, 0xA7BF}, {0xA7C2, 0xA7CA}, {0xA7F5, 0xA82C},
    {0xA830, 0xA839}, {0xA840, 0xA877}, {0xA880, 0xA8C5}, {0xA8CE, 0xA8D9},
    {0xA8E0, 0xA953}, {0xA95F, 0xA97C}, {0xA980, 0xA9CD}, {0xA9CF, 0xA9D9},
    {0xA9DE, 0xA9FE}, {0xAA00, 0xAA36}, {0xAA40, 0xAA4D}, {0xAA50, 0xAA59},
    {0xAA5C, 0xAAC2}, {0xAADB, 0xAAF6}, {0xAB01, 0xAB06}, {0xAB09, 0xAB0E},
    {0xAB11, 0xAB16}, {0xAB20, 0xAB26}, {0xAB28, 0xAB2E}, {0xAB30, 0xAB6B},
    {0xAB70, 0xABED}, {0xABF0, 0xABF9}, {0xAC00, 0xD7A3}, {0xD7B0, 0xD7C6},
    {0xD7CB, 0xD7FB}, {0xF900, 0xFA6D}, {0xFA70, 0xFAD9}, {0xFB00, 0xFB06},
    {0xFB13, 0xFB17}, {0xFB1D, 0xFB36}, {0xFB38, 0xFB3C}, {0xFB46, 0xFBC1},
    {0xFBD3, 0xFD3F}, {0xFD50, 0xFD8F}, {0xFD92, 0xFDC7}, {0xFDF0, 0xFDFD},
    {0xFE00, 0xFE19}, {0xFE20, 0xFE52}, {0xFE54, 0xFE66}, {0xFE68, 0xFE6B},
    {0xA7D5, 0xA7DC}, {0xA7F2, 0xA82C}, {0xA830, 0xA839}, {0xA840, 0xA877},
    {0xA880, 0xA8C5}, {0xA8CE, 0xA8D9}, {0xA8E0, 0xA953}, {0xA95F, 0xA97C},
    {0xA980, 0xA9CD}, {0xA9CF, 0xA9D9}, {0xA9DE, 0xA9FE}, {0xAA00, 0xAA36},
    {0xAA40, 0xAA4D}, {0xAA50, 0xAA59}, {0xAA5C, 0xAAC2}, {0xAADB, 0xAAF6},
    {0xAB01, 0xAB06}, {0xAB09, 0xAB0E}, {0xAB11, 0xAB16}, {0xAB20, 0xAB26},
    {0xAB28, 0xAB2E}, {0xAB30, 0xAB6B}, {0xAB70, 0xABED}, {0xABF0, 0xABF9},
    {0xAC00, 0xD7A3}, {0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB}, {0xF900, 0xFA6D},
    {0xFA70, 0xFAD9}, {0xFB00, 0xFB06}, {0xFB13, 0xFB17}, {0xFB1D, 0xFB36},
    {0xFB38, 0xFB3C}, {0xFB46, 0xFBC2}, {0xFBD3, 0xFD8F}, {0xFD92, 0xFDC7},
    {0xFDF0, 0xFE19}, {0xFE20, 0xFE52}, {0xFE54, 0xFE66}, {0xFE68, 0xFE6B},
    {0xFE70, 0xFE74}, {0xFE76, 0xFEFC}, {0xFF01, 0xFFBE}, {0xFFC2, 0xFFC7},
    {0xFFCA, 0xFFCF}, {0xFFD2, 0xFFD7}, {0xFFDA, 0xFFDC}, {0xFFE0, 0xFFE6},
    {0xFFE8, 0xFFEE}
#if CHRBITS > 16
    ,{0x10000, 0x1000B}, {0x1000D, 0x10026}, {0x10028, 0x1003A}, {0x1003F, 0x1004D},
    {0x10050, 0x1005D}, {0x10080, 0x100FA}, {0x10100, 0x10102}, {0x10107, 0x10133},
    {0x10137, 0x1018E}, {0x10190, 0x1019C}, {0x101D0, 0x101FD}, {0x10280, 0x1029C},
    {0x102A0, 0x102D0}, {0x102E0, 0x102FB}, {0x10300, 0x10323}, {0x1032D, 0x1034A},
    {0x10350, 0x1037A}, {0x10380, 0x1039D}, {0x1039F, 0x103C3}, {0x103C8, 0x103D5},
    {0x10400, 0x1049D}, {0x104A0, 0x104A9}, {0x104B0, 0x104D3}, {0x104D8, 0x104FB},
    {0x10500, 0x10527}, {0x10530, 0x10563}, {0x10600, 0x10736}, {0x10740, 0x10755},
    {0x10760, 0x10767}, {0x10800, 0x10805}, {0x1080A, 0x10835}, {0x1083F, 0x10855},
    {0x10857, 0x1089E}, {0x108A7, 0x108AF}, {0x108E0, 0x108F2}, {0x108FB, 0x1091B},
    {0x1091F, 0x10939}, {0x10980, 0x109B7}, {0x109BC, 0x109CF}, {0x109D2, 0x10A03},
    {0x10A0C, 0x10A13}, {0x10A15, 0x10A17}, {0x10A19, 0x10A35}, {0x10A38, 0x10A3A},
    {0x10A3F, 0x10A48}, {0x10A50, 0x10A58}, {0x10A60, 0x10A9F}, {0x10AC0, 0x10AE6},
    {0x10AEB, 0x10AF6}, {0x10B00, 0x10B35}, {0x10B39, 0x10B55}, {0x10B58, 0x10B72},
    {0x10B78, 0x10B91}, {0x10B99, 0x10B9C}, {0x10BA9, 0x10BAF}, {0x10C00, 0x10C48},
    {0x10C80, 0x10CB2}, {0x10CC0, 0x10CF2}, {0x10CFA, 0x10D27}, {0x10D30, 0x10D39},
    {0x10E60, 0x10E7E}, {0x10E80, 0x10EA9}, {0x10EAB, 0x10EAD}, {0x10F00, 0x10F27},
    {0x10F30, 0x10F59}, {0x10FB0, 0x10FCB}, {0x10FE0, 0x10FF6}, {0x11000, 0x1104D},
    {0x11052, 0x1106F}, {0x1107F, 0x110BC}, {0x110BE, 0x110C1}, {0x110D0, 0x110E8},
    {0x110F0, 0x110F9}, {0x11100, 0x11134}, {0x11136, 0x11147}, {0x11150, 0x11176},
    {0x11180, 0x111DF}, {0x111E1, 0x111F4}, {0x11200, 0x11211}, {0x11213, 0x1123E},
    {0x11280, 0x11286}, {0x1128A, 0x1128D}, {0x1128F, 0x1129D}, {0x1129F, 0x112A9},
    {0x112B0, 0x112EA}, {0x112F0, 0x112F9}, {0x11300, 0x11303}, {0x11305, 0x1130C},
    {0x11313, 0x11328}, {0x1132A, 0x11330}, {0x11335, 0x11339}, {0x1133B, 0x11344},
    {0x1134B, 0x1134D}, {0x1135D, 0x11363}, {0x11366, 0x1136C}, {0x11370, 0x11374},
    {0x11400, 0x1145B}, {0x1145D, 0x11461}, {0x11480, 0x114C7}, {0x114D0, 0x114D9},
    {0x11580, 0x115B5}, {0x115B8, 0x115DD}, {0x11600, 0x11644}, {0x11650, 0x11659},
    {0x11660, 0x1166C}, {0x11680, 0x116B8}, {0x116C0, 0x116C9}, {0x11700, 0x1171A},
    {0x1171D, 0x1172B}, {0x11730, 0x1173F}, {0x11800, 0x1183B}, {0x118A0, 0x118F2},
    {0x10500, 0x10527}, {0x10530, 0x10563}, {0x1056F, 0x1057A}, {0x1057C, 0x1058A},
    {0x1058C, 0x10592}, {0x10597, 0x105A1}, {0x105A3, 0x105B1}, {0x105B3, 0x105B9},
    {0x105C0, 0x105F3}, {0x10600, 0x10736}, {0x10740, 0x10755}, {0x10760, 0x10767},
    {0x10780, 0x10785}, {0x10787, 0x107B0}, {0x107B2, 0x107BA}, {0x10800, 0x10805},
    {0x1080A, 0x10835}, {0x1083F, 0x10855}, {0x10857, 0x1089E}, {0x108A7, 0x108AF},
    {0x108E0, 0x108F2}, {0x108FB, 0x1091B}, {0x1091F, 0x10939}, {0x10980, 0x109B7},
    {0x109BC, 0x109CF}, {0x109D2, 0x10A03}, {0x10A0C, 0x10A13}, {0x10A15, 0x10A17},
    {0x10A19, 0x10A35}, {0x10A38, 0x10A3A}, {0x10A3F, 0x10A48}, {0x10A50, 0x10A58},
    {0x10A60, 0x10A9F}, {0x10AC0, 0x10AE6}, {0x10AEB, 0x10AF6}, {0x10B00, 0x10B35},
    {0x10B39, 0x10B55}, {0x10B58, 0x10B72}, {0x10B78, 0x10B91}, {0x10B99, 0x10B9C},
    {0x10BA9, 0x10BAF}, {0x10C00, 0x10C48}, {0x10C80, 0x10CB2}, {0x10CC0, 0x10CF2},
    {0x10CFA, 0x10D27}, {0x10D30, 0x10D39}, {0x10D40, 0x10D65}, {0x10D69, 0x10D85},
    {0x10E60, 0x10E7E}, {0x10E80, 0x10EA9}, {0x10EAB, 0x10EAD}, {0x10EC2, 0x10EC4},
    {0x10EFC, 0x10F27}, {0x10F30, 0x10F59}, {0x10F70, 0x10F89}, {0x10FB0, 0x10FCB},
    {0x10FE0, 0x10FF6}, {0x11000, 0x1104D}, {0x11052, 0x11075}, {0x1107F, 0x110BC},
    {0x110BE, 0x110C2}, {0x110D0, 0x110E8}, {0x110F0, 0x110F9}, {0x11100, 0x11134},
    {0x11136, 0x11147}, {0x11150, 0x11176}, {0x11180, 0x111DF}, {0x111E1, 0x111F4},
    {0x11200, 0x11211}, {0x11213, 0x11241}, {0x11280, 0x11286}, {0x1128A, 0x1128D},
    {0x1128F, 0x1129D}, {0x1129F, 0x112A9}, {0x112B0, 0x112EA}, {0x112F0, 0x112F9},
    {0x11300, 0x11303}, {0x11305, 0x1130C}, {0x11313, 0x11328}, {0x1132A, 0x11330},
    {0x11335, 0x11339}, {0x1133B, 0x11344}, {0x1134B, 0x1134D}, {0x1135D, 0x11363},
    {0x11366, 0x1136C}, {0x11370, 0x11374}, {0x11380, 0x11389}, {0x11390, 0x113B5},
    {0x113B7, 0x113C0}, {0x113C7, 0x113CA}, {0x113CC, 0x113D5}, {0x11400, 0x1145B},
    {0x1145D, 0x11461}, {0x11480, 0x114C7}, {0x114D0, 0x114D9}, {0x11580, 0x115B5},
    {0x115B8, 0x115DD}, {0x11600, 0x11644}, {0x11650, 0x11659}, {0x11660, 0x1166C},
    {0x11680, 0x116B9}, {0x116C0, 0x116C9}, {0x116D0, 0x116E3}, {0x11700, 0x1171A},
    {0x1171D, 0x1172B}, {0x11730, 0x11746}, {0x11800, 0x1183B}, {0x118A0, 0x118F2},
    {0x118FF, 0x11906}, {0x1190C, 0x11913}, {0x11918, 0x11935}, {0x1193B, 0x11946},
    {0x11950, 0x11959}, {0x119A0, 0x119A7}, {0x119AA, 0x119D7}, {0x119DA, 0x119E4},
    {0x11A00, 0x11A47}, {0x11A50, 0x11AA2}, {0x11AC0, 0x11AF8}, {0x11C00, 0x11C08},
    {0x11C0A, 0x11C36}, {0x11C38, 0x11C45}, {0x11C50, 0x11C6C}, {0x11C70, 0x11C8F},
    {0x11C92, 0x11CA7}, {0x11CA9, 0x11CB6}, {0x11D00, 0x11D06}, {0x11D0B, 0x11D36},
    {0x11D3F, 0x11D47}, {0x11D50, 0x11D59}, {0x11D60, 0x11D65}, {0x11D6A, 0x11D8E},
    {0x11D93, 0x11D98}, {0x11DA0, 0x11DA9}, {0x11EE0, 0x11EF8}, {0x11FC0, 0x11FF1},
    {0x11FFF, 0x12399}, {0x12400, 0x1246E}, {0x12470, 0x12474}, {0x12480, 0x12543},
    {0x13000, 0x1342E}, {0x14400, 0x14646}, {0x16800, 0x16A38}, {0x16A40, 0x16A5E},
    {0x16A60, 0x16A69}, {0x16AD0, 0x16AED}, {0x16AF0, 0x16AF5}, {0x16B00, 0x16B45},
    {0x11A00, 0x11A47}, {0x11A50, 0x11AA2}, {0x11AB0, 0x11AF8}, {0x11B00, 0x11B09},
    {0x11BC0, 0x11BE1}, {0x11BF0, 0x11BF9}, {0x11C00, 0x11C08}, {0x11C0A, 0x11C36},
    {0x11C38, 0x11C45}, {0x11C50, 0x11C6C}, {0x11C70, 0x11C8F}, {0x11C92, 0x11CA7},
    {0x11CA9, 0x11CB6}, {0x11D00, 0x11D06}, {0x11D0B, 0x11D36}, {0x11D3F, 0x11D47},
    {0x11D50, 0x11D59}, {0x11D60, 0x11D65}, {0x11D6A, 0x11D8E}, {0x11D93, 0x11D98},
    {0x11DA0, 0x11DA9}, {0x11EE0, 0x11EF8}, {0x11F00, 0x11F10}, {0x11F12, 0x11F3A},
    {0x11F3E, 0x11F5A}, {0x11FC0, 0x11FF1}, {0x11FFF, 0x12399}, {0x12400, 0x1246E},
    {0x12470, 0x12474}, {0x12480, 0x12543}, {0x12F90, 0x12FF2}, {0x13000, 0x1342F},
    {0x13440, 0x13455}, {0x13460, 0x143FA}, {0x14400, 0x14646}, {0x16100, 0x16139},
    {0x16800, 0x16A38}, {0x16A40, 0x16A5E}, {0x16A60, 0x16A69}, {0x16A6E, 0x16ABE},
    {0x16AC0, 0x16AC9}, {0x16AD0, 0x16AED}, {0x16AF0, 0x16AF5}, {0x16B00, 0x16B45},
    {0x16B50, 0x16B59}, {0x16B5B, 0x16B61}, {0x16B63, 0x16B77}, {0x16B7D, 0x16B8F},
    {0x16E40, 0x16E9A}, {0x16F00, 0x16F4A}, {0x16F4F, 0x16F87}, {0x16F8F, 0x16F9F},
    {0x16FE0, 0x16FE4}, {0x17000, 0x187F7}, {0x18800, 0x18CD5}, {0x18D00, 0x18D08},
    {0x1B000, 0x1B11E}, {0x1B150, 0x1B152}, {0x1B164, 0x1B167}, {0x1B170, 0x1B2FB},
    {0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C}, {0x1BC80, 0x1BC88}, {0x1BC90, 0x1BC99},
    {0x1BC9C, 0x1BC9F}, {0x1D000, 0x1D0F5}, {0x1D100, 0x1D126}, {0x1D129, 0x1D172},
    {0x1D17B, 0x1D1E8}, {0x1D200, 0x1D245}, {0x1D2E0, 0x1D2F3}, {0x1D300, 0x1D356},
    {0x1D360, 0x1D378}, {0x1D400, 0x1D454}, {0x1D456, 0x1D49C}, {0x1D4A9, 0x1D4AC},
    {0x1D4AE, 0x1D4B9}, {0x1D4BD, 0x1D4C3}, {0x1D4C5, 0x1D505}, {0x1D507, 0x1D50A},
    {0x1D50D, 0x1D514}, {0x1D516, 0x1D51C}, {0x1D51E, 0x1D539}, {0x1D53B, 0x1D53E},
    {0x1D540, 0x1D544}, {0x1D54A, 0x1D550}, {0x1D552, 0x1D6A5}, {0x1D6A8, 0x1D7CB},
    {0x1D7CE, 0x1DA8B}, {0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF}, {0x1E000, 0x1E006},
    {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, {0x1E026, 0x1E02A}, {0x1E100, 0x1E12C},
    {0x1E130, 0x1E13D}, {0x1E140, 0x1E149}, {0x1E2C0, 0x1E2F9}, {0x1E800, 0x1E8C4},
    {0x1E8C7, 0x1E8D6}, {0x1E900, 0x1E94B}, {0x1E950, 0x1E959}, {0x1EC71, 0x1ECB4},
    {0x1ED01, 0x1ED3D}, {0x1EE00, 0x1EE03}, {0x1EE05, 0x1EE1F}, {0x1EE29, 0x1EE32},
    {0x1EE34, 0x1EE37}, {0x1EE4D, 0x1EE4F}, {0x1EE67, 0x1EE6A}, {0x1EE6C, 0x1EE72},
    {0x1EE74, 0x1EE77}, {0x1EE79, 0x1EE7C}, {0x1EE80, 0x1EE89}, {0x1EE8B, 0x1EE9B},
    {0x1EEA1, 0x1EEA3}, {0x1EEA5, 0x1EEA9}, {0x1EEAB, 0x1EEBB}, {0x1F000, 0x1F02B},
    {0x1F030, 0x1F093}, {0x1F0A0, 0x1F0AE}, {0x1F0B1, 0x1F0BF}, {0x1F0C1, 0x1F0CF},
    {0x1F0D1, 0x1F0F5}, {0x1F100, 0x1F1AD}, {0x1F1E6, 0x1F202}, {0x1F210, 0x1F23B},
    {0x1F240, 0x1F248}, {0x1F260, 0x1F265}, {0x1F300, 0x1F6D7}, {0x1F6E0, 0x1F6EC},
    {0x1F6F0, 0x1F6FC}, {0x1F700, 0x1F773}, {0x1F780, 0x1F7D8}, {0x1F7E0, 0x1F7EB},
    {0x1F800, 0x1F80B}, {0x1F810, 0x1F847}, {0x1F850, 0x1F859}, {0x1F860, 0x1F887},
    {0x1F890, 0x1F8AD}, {0x1F900, 0x1F978}, {0x1F97A, 0x1F9CB}, {0x1F9CD, 0x1FA53},
    {0x1FA60, 0x1FA6D}, {0x1FA70, 0x1FA74}, {0x1FA78, 0x1FA7A}, {0x1FA80, 0x1FA86},
    {0x1FA90, 0x1FAA8}, {0x1FAB0, 0x1FAB6}, {0x1FAC0, 0x1FAC2}, {0x1FAD0, 0x1FAD6},
    {0x1FB00, 0x1FB92}, {0x1FB94, 0x1FBCA}, {0x1FBF0, 0x1FBF9}, {0x20000, 0x2A6DD},
    {0x2A700, 0x2B734}, {0x2B740, 0x2B81D}, {0x2B820, 0x2CEA1}, {0x2CEB0, 0x2EBE0},
    {0x2F800, 0x2FA1D}, {0x30000, 0x3134A}, {0xE0100, 0xE01EF}
    {0x16D40, 0x16D79}, {0x16E40, 0x16E9A}, {0x16F00, 0x16F4A}, {0x16F4F, 0x16F87},
    {0x16F8F, 0x16F9F}, {0x16FE0, 0x16FE4}, {0x17000, 0x187F7}, {0x18800, 0x18CD5},
    {0x18CFF, 0x18D08}, {0x1AFF0, 0x1AFF3}, {0x1AFF5, 0x1AFFB}, {0x1B000, 0x1B122},
    {0x1B150, 0x1B152}, {0x1B164, 0x1B167}, {0x1B170, 0x1B2FB}, {0x1BC00, 0x1BC6A},
    {0x1BC70, 0x1BC7C}, {0x1BC80, 0x1BC88}, {0x1BC90, 0x1BC99}, {0x1BC9C, 0x1BC9F},
    {0x1CC00, 0x1CCF9}, {0x1CD00, 0x1CEB3}, {0x1CF00, 0x1CF2D}, {0x1CF30, 0x1CF46},
    {0x1CF50, 0x1CFC3}, {0x1D000, 0x1D0F5}, {0x1D100, 0x1D126}, {0x1D129, 0x1D172},
    {0x1D17B, 0x1D1EA}, {0x1D200, 0x1D245}, {0x1D2C0, 0x1D2D3}, {0x1D2E0, 0x1D2F3},
    {0x1D300, 0x1D356}, {0x1D360, 0x1D378}, {0x1D400, 0x1D454}, {0x1D456, 0x1D49C},
    {0x1D4A9, 0x1D4AC}, {0x1D4AE, 0x1D4B9}, {0x1D4BD, 0x1D4C3}, {0x1D4C5, 0x1D505},
    {0x1D507, 0x1D50A}, {0x1D50D, 0x1D514}, {0x1D516, 0x1D51C}, {0x1D51E, 0x1D539},
    {0x1D53B, 0x1D53E}, {0x1D540, 0x1D544}, {0x1D54A, 0x1D550}, {0x1D552, 0x1D6A5},
    {0x1D6A8, 0x1D7CB}, {0x1D7CE, 0x1DA8B}, {0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF},
    {0x1DF00, 0x1DF1E}, {0x1DF25, 0x1DF2A}, {0x1E000, 0x1E006}, {0x1E008, 0x1E018},
    {0x1E01B, 0x1E021}, {0x1E026, 0x1E02A}, {0x1E030, 0x1E06D}, {0x1E100, 0x1E12C},
    {0x1E130, 0x1E13D}, {0x1E140, 0x1E149}, {0x1E290, 0x1E2AE}, {0x1E2C0, 0x1E2F9},
    {0x1E4D0, 0x1E4F9}, {0x1E5D0, 0x1E5FA}, {0x1E7E0, 0x1E7E6}, {0x1E7E8, 0x1E7EB},
    {0x1E7F0, 0x1E7FE}, {0x1E800, 0x1E8C4}, {0x1E8C7, 0x1E8D6}, {0x1E900, 0x1E94B},
    {0x1E950, 0x1E959}, {0x1EC71, 0x1ECB4}, {0x1ED01, 0x1ED3D}, {0x1EE00, 0x1EE03},
    {0x1EE05, 0x1EE1F}, {0x1EE29, 0x1EE32}, {0x1EE34, 0x1EE37}, {0x1EE4D, 0x1EE4F},
    {0x1EE67, 0x1EE6A}, {0x1EE6C, 0x1EE72}, {0x1EE74, 0x1EE77}, {0x1EE79, 0x1EE7C},
    {0x1EE80, 0x1EE89}, {0x1EE8B, 0x1EE9B}, {0x1EEA1, 0x1EEA3}, {0x1EEA5, 0x1EEA9},
    {0x1EEAB, 0x1EEBB}, {0x1F000, 0x1F02B}, {0x1F030, 0x1F093}, {0x1F0A0, 0x1F0AE},
    {0x1F0B1, 0x1F0BF}, {0x1F0C1, 0x1F0CF}, {0x1F0D1, 0x1F0F5}, {0x1F100, 0x1F1AD},
    {0x1F1E6, 0x1F202}, {0x1F210, 0x1F23B}, {0x1F240, 0x1F248}, {0x1F260, 0x1F265},
    {0x1F300, 0x1F6D7}, {0x1F6DC, 0x1F6EC}, {0x1F6F0, 0x1F6FC}, {0x1F700, 0x1F776},
    {0x1F77B, 0x1F7D9}, {0x1F7E0, 0x1F7EB}, {0x1F800, 0x1F80B}, {0x1F810, 0x1F847},
    {0x1F850, 0x1F859}, {0x1F860, 0x1F887}, {0x1F890, 0x1F8AD}, {0x1F8B0, 0x1F8BB},
    {0x1F900, 0x1FA53}, {0x1FA60, 0x1FA6D}, {0x1FA70, 0x1FA7C}, {0x1FA80, 0x1FA89},
    {0x1FA8F, 0x1FAC6}, {0x1FACE, 0x1FADC}, {0x1FADF, 0x1FAE9}, {0x1FAF0, 0x1FAF8},
    {0x1FB00, 0x1FB92}, {0x1FB94, 0x1FBF9}, {0x20000, 0x2A6DF}, {0x2A700, 0x2B739},
    {0x2B740, 0x2B81D}, {0x2B820, 0x2CEA1}, {0x2CEB0, 0x2EBE0}, {0x2EBF0, 0x2EE5D},
    {0x2F800, 0x2FA1D}, {0x30000, 0x3134A}, {0x31350, 0x323AF}, {0xE0100, 0xE01EF}
#endif
};

#define NUM_GRAPH_RANGE (sizeof(graphRangeTable)/sizeof(crange))
#define NUM_GRAPH_RANGE ((int)(sizeof(graphRangeTable)/sizeof(crange)))

static const chr graphCharTable[] = {
    0x38C, 0x85E, 0x98F, 0x990, 0x9B2, 0x9C7, 0x9C8, 0x9D7, 0x9DC,
    0x9DD, 0xA0F, 0xA10, 0xA32, 0xA33, 0xA35, 0xA36, 0xA38, 0xA39,
    0xA3C, 0xA47, 0xA48, 0xA51, 0xA5E, 0xAB2, 0xAB3, 0xAD0, 0xB0F,
    0xB10, 0xB32, 0xB33, 0xB47, 0xB48, 0xB5C, 0xB5D, 0xB82, 0xB83,
    0xB99, 0xB9A, 0xB9C, 0xB9E, 0xB9F, 0xBA3, 0xBA4, 0xBD0, 0xBD7,
    0xC55, 0xC56, 0xCD5, 0xCD6, 0xCDE, 0xCF1, 0xCF2, 0xDBD, 0xDCA,
    0xC55, 0xC56, 0xC5D, 0xCD5, 0xCD6, 0xCDD, 0xCDE, 0xDBD, 0xDCA,
    0xDD6, 0xE81, 0xE82, 0xE84, 0xEA5, 0xEC6, 0x10C7, 0x10CD, 0x1258,
    0x12C0, 0x1772, 0x1773, 0x1940, 0x1F59, 0x1F5B, 0x1F5D, 0x2070, 0x2071,
    0x2D27, 0x2D2D, 0x2D6F, 0x2D70, 0xFB3E, 0xFB40, 0xFB41, 0xFB43, 0xFB44,
    0xFFFC, 0xFFFD
    0x2D27, 0x2D2D, 0x2D6F, 0x2D70, 0xA7D0, 0xA7D1, 0xA7D3, 0xFB3E, 0xFB40,
    0xFB41, 0xFB43, 0xFB44, 0xFDCF, 0xFFFC, 0xFFFD
#if CHRBITS > 16
    ,0x1003C, 0x1003D, 0x101A0, 0x1056F, 0x10808, 0x10837, 0x10838, 0x1083C, 0x108F4,
    0x108F5, 0x1093F, 0x10A05, 0x10A06, 0x10EB0, 0x10EB1, 0x11288, 0x1130F, 0x11310,
    0x11332, 0x11333, 0x11347, 0x11348, 0x11350, 0x11357, 0x11909, 0x11915, 0x11916,
    0x11937, 0x11938, 0x11D08, 0x11D09, 0x11D3A, 0x11D3C, 0x11D3D, 0x11D67, 0x11D68,
    0x11D90, 0x11D91, 0x11FB0, 0x16A6E, 0x16A6F, 0x16FF0, 0x16FF1, 0x1D49E, 0x1D49F,
    0x1D4A2, 0x1D4A5, 0x1D4A6, 0x1D4BB, 0x1D546, 0x1E023, 0x1E024, 0x1E14E, 0x1E14F,
    0x1E2FF, 0x1E95E, 0x1E95F, 0x1EE21, 0x1EE22, 0x1EE24, 0x1EE27, 0x1EE39, 0x1EE3B,
    0x1EE42, 0x1EE47, 0x1EE49, 0x1EE4B, 0x1EE51, 0x1EE52, 0x1EE54, 0x1EE57, 0x1EE59,
    0x1EE5B, 0x1EE5D, 0x1EE5F, 0x1EE61, 0x1EE62, 0x1EE64, 0x1EE7E, 0x1EEF0, 0x1EEF1,
    0x1F250, 0x1F251, 0x1F8B0, 0x1F8B1
    ,0x1003C, 0x1003D, 0x101A0, 0x10594, 0x10595, 0x105BB, 0x105BC, 0x10808, 0x10837,
    0x10838, 0x1083C, 0x108F4, 0x108F5, 0x1093F, 0x10A05, 0x10A06, 0x10D8E, 0x10D8F,
    0x10EB0, 0x10EB1, 0x11288, 0x1130F, 0x11310, 0x11332, 0x11333, 0x11347, 0x11348,
    0x11350, 0x11357, 0x1138B, 0x1138E, 0x113C2, 0x113C5, 0x113D7, 0x113D8, 0x113E1,
    0x113E2, 0x11909, 0x11915, 0x11916, 0x11937, 0x11938, 0x11D08, 0x11D09, 0x11D3A,
    0x11D3C, 0x11D3D, 0x11D67, 0x11D68, 0x11D90, 0x11D91, 0x11FB0, 0x16FF0, 0x16FF1,
    0x1AFFD, 0x1AFFE, 0x1B132, 0x1B155, 0x1D49E, 0x1D49F, 0x1D4A2, 0x1D4A5, 0x1D4A6,
    0x1D4BB, 0x1D546, 0x1E023, 0x1E024, 0x1E08F, 0x1E14E, 0x1E14F, 0x1E2FF, 0x1E5FF,
    0x1E7ED, 0x1E7EE, 0x1E95E, 0x1E95F, 0x1EE21, 0x1EE22, 0x1EE24, 0x1EE27, 0x1EE39,
    0x1EE3B, 0x1EE42, 0x1EE47, 0x1EE49, 0x1EE4B, 0x1EE51, 0x1EE52, 0x1EE54, 0x1EE57,
    0x1EE59, 0x1EE5B, 0x1EE5D, 0x1EE5F, 0x1EE61, 0x1EE62, 0x1EE64, 0x1EE7E, 0x1EEF0,
    0x1EEF1, 0x1F250, 0x1F251, 0x1F7F0, 0x1F8C0, 0x1F8C1
#endif
};

#define NUM_GRAPH_CHAR (sizeof(graphCharTable)/sizeof(chr))
#define NUM_GRAPH_CHAR ((int)(sizeof(graphCharTable)/sizeof(chr)))

/*
 *	End of auto-generated Unicode character ranges declarations.
 */

/*
 - element - map collating-element name to celt
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

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
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







-
-
+











+


-
+














-
+


-
+




-
-
-
-













-
+
+
+
+







    int cases)			/* case-independent? */
{
    size_t len;
    struct cvec *cv = NULL;
    Tcl_DString ds;
    const char *np;
    const char *const *namePtr;
    size_t i;
    int index;
    int i;

    /*
     * The following arrays define the valid character class names.
     */

    static const char *const classNames[] = {
	"alnum", "alpha", "ascii", "blank", "cntrl", "digit", "graph",
	"lower", "print", "punct", "space", "upper", "xdigit", NULL
    };

    enum classes {
	CC_NULL = -1,
	CC_ALNUM, CC_ALPHA, CC_ASCII, CC_BLANK, CC_CNTRL, CC_DIGIT, CC_GRAPH,
	CC_LOWER, CC_PRINT, CC_PUNCT, CC_SPACE, CC_UPPER, CC_XDIGIT
    };
    } index;


    /*
     * Extract the class name
     */

    len = endp - startp;
    Tcl_DStringInit(&ds);
    np = Tcl_UniCharToUtfDString(startp, len, &ds);

    /*
     * Map the name to the corresponding enumerated value.
     */

    index = -1;
    index = CC_NULL;
    for (namePtr=classNames,i=0 ; *namePtr!=NULL ; namePtr++,i++) {
	if ((strlen(*namePtr) == len) && (strncmp(*namePtr, np, len) == 0)) {
	    index = i;
	    index = (enum classes)i;
	    break;
	}
    }
    Tcl_DStringFree(&ds);
    if (index == -1) {
	ERR(REG_ECTYPE);
	return NULL;
    }

    /*
     * Remap lower and upper to alpha if the match is case insensitive.
     */

    if (cases && ((index == CC_LOWER) || (index == CC_UPPER))) {
	index = CC_ALNUM;
    }

    /*
     * Now compute the character class contents.
     */

    switch((enum classes) index) {
    switch (index) {
    case CC_NULL:
	ERR(REG_ECTYPE);
	return NULL;
    case CC_ALNUM:
	cv = getcvec(v, NUM_ALPHA_CHAR, NUM_DIGIT_RANGE + NUM_ALPHA_RANGE);
	if (cv) {
	    for (i=0 ; i<NUM_ALPHA_CHAR ; i++) {
		addchr(cv, alphaCharTable[i]);
	    }
	    for (i=0 ; i<NUM_ALPHA_RANGE ; i++) {
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189


















1190
1191
1192
1193
1194
1195
1196
1195
1196
1197
1198
1199
1200
1201


















1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    }
	    for (i=0 ; i<NUM_UPPER_CHAR ; i++) {
		addchr(cv, upperCharTable[i]);
	    }
	}
	break;
    case CC_PRINT:
    	cv  = getcvec(v, NUM_SPACE_CHAR + NUM_GRAPH_CHAR, NUM_SPACE_RANGE + NUM_GRAPH_RANGE  - 1);
    	if (cv) {
    	    for (i=1 ; i<NUM_SPACE_RANGE ; i++) {
    		addrange(cv, spaceRangeTable[i].start,
    				spaceRangeTable[i].end);
    	    }
    	    for (i=0 ; i<NUM_SPACE_CHAR ; i++) {
    		addchr(cv, spaceCharTable[i]);
    	    }
    	    for (i=0 ; i<NUM_GRAPH_RANGE ; i++) {
    		addrange(cv, graphRangeTable[i].start,
    				graphRangeTable[i].end);
    	    }
    	    for (i=0 ; i<NUM_GRAPH_CHAR ; i++) {
    		addchr(cv, graphCharTable[i]);
    	    }
    	}
    	break;
	cv  = getcvec(v, NUM_SPACE_CHAR + NUM_GRAPH_CHAR, NUM_SPACE_RANGE + NUM_GRAPH_RANGE  - 1);
	if (cv) {
	    for (i=1 ; i<NUM_SPACE_RANGE ; i++) {
		addrange(cv, spaceRangeTable[i].start,
				spaceRangeTable[i].end);
	    }
	    for (i=0 ; i<NUM_SPACE_CHAR ; i++) {
		addchr(cv, spaceCharTable[i]);
	    }
	    for (i=0 ; i<NUM_GRAPH_RANGE ; i++) {
		addrange(cv, graphRangeTable[i].start,
				graphRangeTable[i].end);
	    }
	    for (i=0 ; i<NUM_GRAPH_CHAR ; i++) {
		addchr(cv, graphCharTable[i]);
	    }
	}
	break;
    case CC_GRAPH:
	cv  = getcvec(v, NUM_GRAPH_CHAR, NUM_GRAPH_RANGE);
	if (cv) {
	    for (i=0 ; i<NUM_GRAPH_RANGE ; i++) {
		addrange(cv, graphRangeTable[i].start,
			graphRangeTable[i].end);
	    }

Changes to generic/regc_nfa.c.

1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







/*
 * NFA utilities.
 * This file is #included by regcomp.c.
 *
 * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
 * Copyright © 1998, 1999 Henry Spencer. All rights reserved.
 *
 * Development of this software was funded, in part, by Cray Research Inc.,
 * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
 * Corporation, none of whom are responsible for the results. The author
 * thanks all of them.
 *
 * Redistribution and use in source and binary forms -- with or without
104
105
106
107
108
109
110
111

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

111
112
113
114
115
116
117
118







-
+







    }
    while ((s = nfa->free) != NULL) {
	nfa->free = s->next;
	destroystate(nfa, s);
    }

    nfa->slast = NULL;
    nfa->nstates = -1;
    nfa->nstates = FREESTATE;
    nfa->pre = NULL;
    nfa->post = NULL;
    FREE(nfa);
}

/*
 - newstate - allocate an NFA state, with zero flag value
139
140
141
142
143
144
145
146

147
148
149
150
151
152
153
139
140
141
142
143
144
145

146
147
148
149
150
151
152
153







-
+







	}
	nfa->v->spaceused += sizeof(struct state);
	s->oas.next = NULL;
	s->free = NULL;
	s->noas = 0;
    }

    assert(nfa->nstates >= 0);
    assert(nfa->nstates != FREESTATE);
    s->no = nfa->nstates++;
    s->flag = 0;
    if (nfa->states == NULL) {
	nfa->states = s;
    }
    s->nins = 0;
    s->ins = NULL;
483
484
485
486
487
488
489
490

491
492
493
494
495
496
497
483
484
485
486
487
488
489

490
491
492
493
494
495
496
497







-
+







    victim->freechain = from->free;
    from->free = victim;
}

/*
 * changearctarget - flip an arc to have a different to state
 *
 * Caller must have verified that there is no pre-existing duplicate arc.
 * Caller must have verified that there is no preexisting duplicate arc.
 *
 * Note that because we store arcs in their from state, we can't easily have
 * a similar changearcsource function.
 */
static void
changearctarget(struct arc * a, struct state * newto)
{
566
567
568
569
570
571
572
573

574
575
576
577
578
579
580
566
567
568
569
570
571
572

573
574
575
576
577
578
579
580







-
+







    }
    return NULL;
}

/*
 - cparc - allocate a new arc within an NFA, copying details from old one
 ^ static void cparc(struct nfa *, struct arc *, struct state *,
 ^ 	struct state *);
 ^	struct state *);
 */
static void
cparc(
    struct nfa *nfa,
    struct arc *oa,
    struct state *from,
    struct state *to)
637
638
639
640
641
642
643
644

645
646
647

648
649
650

651
652
653

654
655
656

657
658
659
660
661
662
663
637
638
639
640
641
642
643

644
645
646

647
648
649

650
651
652

653
654
655

656
657
658
659
660
661
662
663







-
+


-
+


-
+


-
+


-
+







    const struct arc *bb = *((const struct arc * const *) b);

    /* we check the fields in the order they are most likely to be different */
    if (aa->from->no < bb->from->no) {
	return -1;
    }
    if (aa->from->no > bb->from->no) {
 	return 1;
	return 1;
    }
    if (aa->co < bb->co) {
 	return -1;
	return -1;
    }
    if (aa->co > bb->co) {
 	return 1;
	return 1;
    }
    if (aa->type < bb->type) {
 	return -1;
	return -1;
    }
    if (aa->type > bb->type) {
 	return 1;
	return 1;
    }
    return 0;
}

/*
 * sortouts - sort the out arcs of a state by to/color/type
 */
1114
1115
1116
1117
1118
1119
1120
1121

1122
1123
1124
1125
1126
1127
1128
1114
1115
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
1128







-
+







	/* With not too many arcs, just do them one at a time */
	struct arc *a;

	for (a = oldState->outs; a != NULL; a = a->outchain) {
	    cparc(nfa, a, newState, a->to);
	}
    } else {
 	/*
	/*
	 * With many arcs, use a sort-merge approach.  Note that createarc()
	 * will put new arcs onto the front of newState's chain, so it does
	 * not break our walk through the sorted part of the chain.
	 */
	struct arc *oa;
	struct arc *na;

1173
1174
1175
1176
1177
1178
1179
1180

1181
1182
1183
1184
1185
1186
1187
1173
1174
1175
1176
1177
1178
1179

1180
1181
1182
1183
1184
1185
1186
1187







-
+







	}
    }
}

/*
 - cloneouts - copy out arcs of a state to another state pair, modifying type
 ^ static void cloneouts(struct nfa *, struct state *, struct state *,
 ^ 	struct state *, int);
 ^	struct state *, int);
 */
static void
cloneouts(
    struct nfa *nfa,
    struct state *old,
    struct state *from,
    struct state *to,
1263
1264
1265
1266
1267
1268
1269
1270

1271
1272
1273
1274
1275
1276
1277
1263
1264
1265
1266
1267
1268
1269

1270
1271
1272
1273
1274
1275
1276
1277







-
+








/*
 - dupnfa - duplicate sub-NFA
 * Another recursive traversal, this time using tmp to point to duplicates as
 * well as mark already-seen states. (You knew there was a reason why it's a
 * state pointer, didn't you? :-))
 ^ static void dupnfa(struct nfa *, struct state *, struct state *,
 ^ 	struct state *, struct state *);
 ^	struct state *, struct state *);
 */
static void
dupnfa(
    struct nfa *nfa,
    struct state *start,	/* duplicate of subNFA starting here */
    struct state *stop,		/* and stopping here */
    struct state *from,		/* stringing duplicate from here */
1511
1512
1513
1514
1515
1516
1517
1518

1519
1520
1521
1522
1523
1524
1525
1511
1512
1513
1514
1515
1516
1517

1518
1519
1520
1521
1522
1523
1524
1525







-
+








/*
 - pull - pull a back constraint backward past its source state
 *
 * Returns 1 if successful (which it always is unless the source is the
 * start state or we have an internal error), 0 if nothing happened.
 *
 * A significant property of this function is that it deletes no pre-existing
 * A significant property of this function is that it deletes no preexisting
 * states, and no outarcs of the constraint's from state other than the given
 * constraint arc.  This makes the loops in pullback() safe, at the cost that
 * we may leave useless states behind.  Therefore, we leave it to pullback()
 * to delete such states.
 *
 * If the from state has multiple back-constraint outarcs, and/or multiple
 * compatible constraint inarcs, we only need to create one new intermediate
1595
1596
1597
1598
1599
1600
1601
1602

1603
1604
1605


1606
1607
1608
1609
1610
1611
1612
1595
1596
1597
1598
1599
1600
1601

1602
1603


1604
1605
1606
1607
1608
1609
1610
1611
1612







-
+

-
-
+
+







		s = newstate(nfa);
		if (NISERR()) {
		    return 0;
		}
		s->tmp = *intermediates;
		*intermediates = s;
	    }
  	    cparc(nfa, con, a->from, s);
	    cparc(nfa, con, a->from, s);
	    cparc(nfa, a, s, to);
 	    freearc(nfa, a);
  	    break;
	    freearc(nfa, a);
	    break;
	default:
	    assert(NOTREACHED);
	    break;
	}
    }

    /*
1690
1691
1692
1693
1694
1695
1696
1697

1698
1699
1700
1701
1702
1703
1704
1690
1691
1692
1693
1694
1695
1696

1697
1698
1699
1700
1701
1702
1703
1704







-
+








/*
 - push - push a forward constraint forward past its destination state
 *
 * Returns 1 if successful (which it always is unless the destination is the
 * post state or we have an internal error), 0 if nothing happened.
 *
 * A significant property of this function is that it deletes no pre-existing
 * A significant property of this function is that it deletes no preexisting
 * states, and no inarcs of the constraint's to state other than the given
 * constraint arc.  This makes the loops in pushfwd() safe, at the cost that
 * we may leave useless states behind.  Therefore, we leave it to pushfwd()
 * to delete such states.
 *
 * If the to state has multiple forward-constraint inarcs, and/or multiple
 * compatible constraint outarcs, we only need to create one new intermediate
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784



1785
1786
1787
1788
1789
1790
1791
1775
1776
1777
1778
1779
1780
1781



1782
1783
1784
1785
1786
1787
1788
1789
1790
1791







-
-
-
+
+
+







		if (NISERR()) {
		    return 0;
		}
		s->tmp = *intermediates;
		*intermediates = s;
	    }
	    cparc(nfa, con, s, a->to);
  	    cparc(nfa, a, from, s);
  	    freearc(nfa, a);
  	    break;
	    cparc(nfa, a, from, s);
	    freearc(nfa, a);
	    break;
	default:
	    assert(NOTREACHED);
	    break;
	}
    }

    /*
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028





2029
2030
2031
2032
2033
2034
2035
2017
2018
2019
2020
2021
2022
2023





2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035







-
-
-
-
-
+
+
+
+
+







	    /* Add s2's original inarcs to arcarray[], but ignore empties */
	    for (a = inarcsorig[s2->no]; a != NULL; a = a->inchain) {
		if (a->type != EMPTY) {
		    arcarray[arccount++] = a;
		}
	    }

  	    /* Reset the tmp fields as we walk back */
  	    nexts = s2->tmp;
  	    s2->tmp = NULL;
  	}
  	s->tmp = NULL;
	    /* Reset the tmp fields as we walk back */
	    nexts = s2->tmp;
	    s2->tmp = NULL;
	}
	s->tmp = NULL;
	assert(arccount <= totalinarcs);

	/* Remember how many original inarcs this state has */
	prevnins = s->nins;

	/* Add non-duplicate inarcs to target state */
	mergeins(nfa, s, arcarray, arccount);
2181
2182
2183
2184
2185
2186
2187
2188

2189
2190
2191
2192
2193



2194
2195
2196
2197
2198
2199
2200
2181
2182
2183
2184
2185
2186
2187

2188
2189
2190



2191
2192
2193
2194
2195
2196
2197
2198
2199
2200







-
+


-
-
-
+
+
+







	for (a = s->outs; a != NULL && !NISERR(); a = nexta) {
	    nexta = a->outchain;
	    if (isconstraintarc(a)) {
		if (a->to == s) {
		    freearc(nfa, a);
		} else {
		    hasconstraints = 1;
 		}
		}
	    }
	}
 	/* If we removed all the outarcs, the state is useless. */
 	if (s->nouts == 0 && !s->flag) {
 	    dropstate(nfa, s);
	/* If we removed all the outarcs, the state is useless. */
	if (s->nouts == 0 && !s->flag) {
	    dropstate(nfa, s);
	}
    }

    /* Nothing to do if no remaining constraint arcs */
    if (NISERR() || !hasconstraints) {
	return;
    }
2231
2232
2233
2234
2235
2236
2237
2238

2239
2240
2241
2242
2243
2244
2245
2231
2232
2233
2234
2235
2236
2237

2238
2239
2240
2241
2242
2243
2244
2245







-
+







	s->tmp = NULL;
	if ((s->nins == 0 || s->nouts == 0) && !s->flag) {
	    dropstate(nfa, s);
	}
    }

    if (f != NULL) {
 	dumpnfa(nfa, f);
	dumpnfa(nfa, f);
    }
}

/*
 * findconstraintloop - recursively find a loop of constraint arcs
 *
 * If we find a loop, break it by calling breakconstraintloop(), then
2463
2464
2465
2466
2467
2468
2469
2470

2471
2472
2473
2474
2475
2476
2477
2463
2464
2465
2466
2467
2468
2469

2470
2471
2472
2473
2474
2475
2476
2477







-
+







 * For each cloned successor state, we transiently create a "donemap" that is
 * a boolean array showing which source states we've already visited for this
 * clone state.  This prevents infinite recursion as well as useless repeat
 * visits to the same state subtree (which can add up fast, since typical NFAs
 * have multiple redundant arc pathways).  Each donemap is a char array
 * indexed by state number.  The donemaps are all of the same size "nstates",
 * which is nfa->nstates as of the start of the recursion.  This is enough to
 * have entries for all pre-existing states, but *not* entries for clone
 * have entries for all preexisting states, but *not* entries for clone
 * states created during the recursion.  That's okay since we have no need to
 * mark those.
 *
 * curdonemap is NULL when recursing to a new sclone state, or sclone's
 * donemap when we are recursing without having created a new state (which we
 * do when we decide we can merge a successor state into the current clone
 * state).  outerdonemap is NULL at the top level and otherwise the parent
2490
2491
2492
2493
2494
2495
2496
2497

2498
2499
2500
2501
2502
2503
2504
2490
2491
2492
2493
2494
2495
2496

2497
2498
2499
2500
2501
2502
2503
2504







-
+







    struct nfa * nfa,
    struct state * ssource,
    struct state * sclone,
    struct state * spredecessor,
    struct arc * refarc,
    char *curdonemap,
    char *outerdonemap,
    int nstates)
    size_t nstates)
{
    char *donemap;
    struct arc *a;

    /* Since this is recursive, it could be driven to stack overflow */
    if (STACK_TOO_DEEP(nfa->v->re)) {
	NERR(REG_ETOOBIG);
2687
2688
2689
2690
2691
2692
2693
2694

2695
2696
2697
2698
2699
2700
2701
2687
2688
2689
2690
2691
2692
2693

2694
2695
2696
2697
2698
2699
2700
2701







-
+







 */
static void
cleanup(
    struct nfa *nfa)
{
    struct state *s;
    struct state *nexts;
    int n;
    size_t n;

    /*
     * Clear out unreachable or dead-end states. Use pre to mark reachable,
     * then post to mark can-reach-post.
     */

    markreachable(nfa, nfa->pre, NULL, nfa->pre);
2721
2722
2723
2724
2725
2726
2727
2728

2729
2730
2731
2732
2733
2734
2735
2721
2722
2723
2724
2725
2726
2727

2728
2729
2730
2731
2732
2733
2734
2735







-
+







    }
    nfa->nstates = n;
}

/*
 - markreachable - recursive marking of reachable states
 ^ static void markreachable(struct nfa *, struct state *, struct state *,
 ^ 	struct state *);
 ^	struct state *);
 */
static void
markreachable(
    struct nfa *nfa,
    struct state *s,
    struct state *okay,		/* consider only states with this mark */
    struct state *mark)		/* the value to mark with */
2745
2746
2747
2748
2749
2750
2751
2752

2753
2754
2755
2756
2757
2758
2759
2745
2746
2747
2748
2749
2750
2751

2752
2753
2754
2755
2756
2757
2758
2759







-
+







	markreachable(nfa, a->to, okay, mark);
    }
}

/*
 - markcanreach - recursive marking of states which can reach here
 ^ static void markcanreach(struct nfa *, struct state *, struct state *,
 ^ 	struct state *);
 ^	struct state *);
 */
static void
markcanreach(
    struct nfa *nfa,
    struct state *s,
    struct state *okay,		/* consider only states with this mark */
    struct state *mark)		/* the value to mark with */
2770
2771
2772
2773
2774
2775
2776
2777

2778
2779
2780
2781
2782
2783
2784
2770
2771
2772
2773
2774
2775
2776

2777
2778
2779
2780
2781
2782
2783
2784







-
+







    }
}

/*
 - analyze - ascertain potentially-useful facts about an optimized NFA
 ^ static long analyze(struct nfa *);
 */
static long			/* re_info bits to be ORed in */
static long			/* re_info bits to be OR'ed in */
analyze(
    struct nfa *nfa)
{
    struct arc *a;
    struct arc *aa;

    if (nfa->pre->outs == NULL) {
2843
2844
2845
2846
2847
2848
2849
2850

2851
2852
2853
2854
2855
2856
2857
2843
2844
2845
2846
2847
2848
2849

2850
2851
2852
2853
2854
2855
2856
2857







-
+







    cnfa->eos[0] = nfa->eos[0];
    cnfa->eos[1] = nfa->eos[1];
    cnfa->ncolors = maxcolor(nfa->cm) + 1;
    cnfa->flags = 0;

    ca = cnfa->arcs;
    for (s = nfa->states; s != NULL; s = s->next) {
	assert((size_t) s->no < nstates);
	assert(s->no < nstates);
	cnfa->stflags[s->no] = 0;
	cnfa->states[s->no] = ca;
	first = ca;
	for (a = s->outs; a != NULL; a = a->outchain) {
	    switch (a->type) {
	    case PLAIN:
		ca->co = a->co;
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
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







-
-
+
+

-
+


















-
+







static void
dumpnfa(
    struct nfa *nfa,
    FILE *f)
{
#ifdef REG_DEBUG
    struct state *s;
    int nstates = 0;
    int narcs = 0;
    size_t nstates = 0;
    size_t narcs = 0;

    fprintf(f, "pre %d, post %d", nfa->pre->no, nfa->post->no);
    fprintf(f, "pre %" TCL_Z_MODIFIER "u, post %" TCL_Z_MODIFIER "u", nfa->pre->no, nfa->post->no);
    if (nfa->bos[0] != COLORLESS) {
	fprintf(f, ", bos [%ld]", (long) nfa->bos[0]);
    }
    if (nfa->bos[1] != COLORLESS) {
	fprintf(f, ", bol [%ld]", (long) nfa->bos[1]);
    }
    if (nfa->eos[0] != COLORLESS) {
	fprintf(f, ", eos [%ld]", (long) nfa->eos[0]);
    }
    if (nfa->eos[1] != COLORLESS) {
	fprintf(f, ", eol [%ld]", (long) nfa->eos[1]);
    }
    fprintf(f, "\n");
    for (s = nfa->states; s != NULL; s = s->next) {
	dumpstate(s, f);
	nstates++;
	narcs += s->nouts;
    }
    fprintf(f, "total of %d states, %d arcs\n", nstates, narcs);
    fprintf(f, "total of %" TCL_Z_MODIFIER "u states, %" TCL_Z_MODIFIER "u arcs\n", nstates, narcs);
    if (nfa->parent == NULL) {
	dumpcolors(nfa->cm, f);
    }
    fflush(f);
#else
    (void)nfa;
    (void)f;
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
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







-
+












-
+







static void
dumpstate(
    struct state *s,
    FILE *f)
{
    struct arc *a;

    fprintf(f, "%d%s%c", s->no, (s->tmp != NULL) ? "T" : "",
    fprintf(f, "%" TCL_Z_MODIFIER "u%s%c", s->no, (s->tmp != NULL) ? "T" : "",
	    (s->flag) ? s->flag : '.');
    if (s->prev != NULL && s->prev->next != s) {
	fprintf(f, "\tstate chain bad\n");
    }
    if (s->nouts == 0) {
	fprintf(f, "\tno out arcs\n");
    } else {
	dumparcs(s, f);
    }
    fflush(f);
    for (a = s->ins; a != NULL; a = a->inchain) {
	if (a->to != s) {
	    fprintf(f, "\tlink from %d to %d on %d's in-chain\n",
	    fprintf(f, "\tlink from %" TCL_Z_MODIFIER "u to %" TCL_Z_MODIFIER "u on %" TCL_Z_MODIFIER "u's in-chain\n",
		    a->from->no, a->to->no, s->no);
	}
    }
}

/*
 - dumparcs - dump out-arcs in human-readable form
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
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







-
+



















-
+







    case EMPTY:
	break;
    default:
	fprintf(f, "0x%x/0%lo", a->type, (long) a->co);
	break;
    }
    if (a->from != s) {
	fprintf(f, "?%d?", a->from->no);
	fprintf(f, "?%" TCL_Z_MODIFIER "u?", a->from->no);
    }
    for (ab = &a->from->oas; ab != NULL; ab = ab->next) {
	for (aa = &ab->a[0]; aa < &ab->a[ABSIZE]; aa++) {
	    if (aa == a) {
		break;		/* NOTE BREAK OUT */
	    }
	}
	if (aa < &ab->a[ABSIZE]) {	/* propagate break */
	    break;		/* NOTE BREAK OUT */
	}
    }
    if (ab == NULL) {
	fprintf(f, "?!?");	/* not in allocated space */
    }
    fprintf(f, "->");
    if (a->to == NULL) {
	fprintf(f, "NULL");
	return;
    }
    fprintf(f, "%d", a->to->no);
    fprintf(f, "%" TCL_Z_MODIFIER "u", a->to->no);
    for (aa = a->to->ins; aa != NULL; aa = aa->inchain) {
	if (aa == a) {
	    break;		/* NOTE BREAK OUT */
	}
    }
    if (aa == NULL) {
	fprintf(f, "?!?");	/* missing from in-chain */
3133
3134
3135
3136
3137
3138
3139
3140

3141
3142

3143
3144
3145
3146
3147
3148
3149
3133
3134
3135
3136
3137
3138
3139

3140
3141

3142
3143
3144
3145
3146
3147
3148
3149







-
+

-
+







 */
static void
dumpcnfa(
    struct cnfa *cnfa,
    FILE *f)
{
#ifdef REG_DEBUG
    int st;
    size_t st;

    fprintf(f, "pre %d, post %d", cnfa->pre, cnfa->post);
    fprintf(f, "pre %" TCL_Z_MODIFIER "u, post %" TCL_Z_MODIFIER "u", cnfa->pre, cnfa->post);
    if (cnfa->bos[0] != COLORLESS) {
	fprintf(f, ", bos [%ld]", (long) cnfa->bos[0]);
    }
    if (cnfa->bos[1] != COLORLESS) {
	fprintf(f, ", bol [%ld]", (long) cnfa->bos[1]);
    }
    if (cnfa->eos[0] != COLORLESS) {
3178
3179
3180
3181
3182
3183
3184
3185

3186
3187
3188
3189
3190
3191

3192
3193

3194
3195
3196
3197
3198
3199
3200
3178
3179
3180
3181
3182
3183
3184

3185
3186
3187
3188
3189
3190

3191
3192

3193
3194
3195
3196
3197
3198
3199
3200







-
+





-
+

-
+







static void
dumpcstate(
    int st,
    struct cnfa *cnfa,
    FILE *f)
{
    struct carc *ca;
    int pos;
    size_t pos;

    fprintf(f, "%d%s", st, (cnfa->stflags[st] & CNFA_NOPROGRESS) ? ":" : ".");
    pos = 1;
    for (ca = cnfa->states[st]; ca->co != COLORLESS; ca++) {
	if (ca->co < cnfa->ncolors) {
	    fprintf(f, "\t[%ld]->%d", (long) ca->co, ca->to);
	    fprintf(f, "\t[%d]->%" TCL_Z_MODIFIER "u", ca->co, ca->to);
	} else {
	    fprintf(f, "\t:%ld:->%d", (long) (ca->co - cnfa->ncolors), ca->to);
	    fprintf(f, "\t:%d:->%" TCL_Z_MODIFIER "u", ca->co - cnfa->ncolors, ca->to);
	}
	if (pos == 5) {
	    fprintf(f, "\n");
	    pos = 1;
	} else {
	    pos++;
	}

Changes to generic/regcomp.c.

1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







/*
 * re_*comp and friends - compile REs
 * This file #includes several others (see the bottom).
 *
 * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
 * Copyright © 1998, 1999 Henry Spencer. All rights reserved.
 *
 * Development of this software was funded, in part, by Cray Research Inc.,
 * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
 * Corporation, none of whom are responsible for the results. The author
 * thanks all of them.
 *
 * Redistribution and use in source and binary forms -- with or without
152
153
154
155
156
157
158
159

160
161
162
163
164
165
166
152
153
154
155
156
157
158

159
160
161
162
163
164
165
166







-
+







			struct state *, struct arc **);
static int	isconstraintarc(struct arc *);
static int	hasconstraintout(struct state *);
static void fixconstraintloops(struct nfa *, FILE *);
static int	findconstraintloop(struct nfa *, struct state *);
static void breakconstraintloop(struct nfa *, struct state *);
static void clonesuccessorstates(struct nfa *, struct state *, struct state *,
		 struct state *, struct arc *, char *, char *, int);
		 struct state *, struct arc *, char *, char *, size_t);
static void cleanup(struct nfa *);
static void markreachable(struct nfa *, struct state *, struct state *, struct state *);
static void markcanreach(struct nfa *, struct state *, struct state *, struct state *);
static long analyze(struct nfa *);
static void compact(struct nfa *, struct cnfa *);
static void carcsort(struct carc *, size_t);
static int carc_cmp(const void *, const void *);
175
176
177
178
179
180
181
182
183


184
185
186
187
188
189
190
175
176
177
178
179
180
181


182
183
184
185
186
187
188
189
190







-
-
+
+







#ifdef REG_DEBUG
static void dumpcstate(int, struct cnfa *, FILE *);
#endif
/* === regc_cvec.c === */
static struct cvec *clearcvec(struct cvec *);
static void addchr(struct cvec *, pchr);
static void addrange(struct cvec *, pchr, pchr);
static struct cvec *newcvec(int, int);
static struct cvec *getcvec(struct vars *, int, int);
static struct cvec *newcvec(size_t, size_t);
static struct cvec *getcvec(struct vars *, size_t, size_t);
static void freecvec(struct cvec *);
/* === regc_locale.c === */
static celt element(struct vars *, const chr *, const chr *);
static struct cvec *range(struct vars *, celt, celt, int);
static int before(celt, celt);
static struct cvec *eclass(struct vars *, celt, int);
static struct cvec *cclass(struct vars *, const chr *, const chr *, int);
406
407
408
409
410
411
412
413

414
415
416
417
418
419
420
406
407
408
409
410
411
412

413
414
415
416
417
418
419
420







-
+







     */

    re->re_info |= nfatree(v, v->tree, debug);
    CNOERR();
    assert(v->nlacons == 0 || v->lacons != NULL);
    for (i = 1; i < v->nlacons; i++) {
	if (debug != NULL) {
	    fprintf(debug, "\n\n\n========= LA%" TCL_Z_MODIFIER "d ==========\n", i);
	    fprintf(debug, "\n\n\n========= LA%" TCL_Z_MODIFIER "u ==========\n", i);
	}
	nfanode(v, &v->lacons[i], debug);
    }
    CNOERR();
    if (v->tree->flags&SHORTER) {
	NOTE(REG_USHORTEST);
    }
640
641
642
643
644
645
646
647

648
649
650
651
652
653
654
640
641
642
643
644
645
646

647
648
649
650
651
652
653
654







-
+








/*
 - parse - parse an RE
 * This is actually just the top level, which parses a bunch of branches tied
 * together with '|'. They appear in the tree as the left children of a chain
 * of '|' subres.
 ^ static struct subre *parse(struct vars *, int, int, struct state *,
 ^ 	struct state *);
 ^	struct state *);
 */
static struct subre *
parse(
    struct vars *v,
    int stopper,		/* EOS or ')' */
    int type,			/* LACON (lookahead subRE) or PLAIN */
    struct state *init,		/* initial state */
722
723
724
725
726
727
728
729

730
731
732
733
734
735
736
722
723
724
725
726
727
728

729
730
731
732
733
734
735
736







-
+








/*
 - parsebranch - parse one branch of an RE
 * This mostly manages concatenation, working closely with parseqatom().
 * Concatenated things are bundled up as much as possible, with separate
 * ',' nodes introduced only when necessary due to substructure.
 ^ static struct subre *parsebranch(struct vars *, int, int, struct state *,
 ^ 	struct state *, int);
 ^	struct state *, int);
 */
static struct subre *
parsebranch(
    struct vars *v,
    int stopper,		/* EOS or ')' */
    int type,			/* LACON (lookahead subRE) or PLAIN */
    struct state *left,		/* leftmost state */
771
772
773
774
775
776
777
778

779
780
781
782
783
784
785
771
772
773
774
775
776
777

778
779
780
781
782
783
784
785







-
+








/*
 - parseqatom - parse one quantified atom or constraint of an RE
 * The bookkeeping near the end cooperates very closely with parsebranch(); in
 * particular, it contains a recursion that can involve parsing the rest of
 * the branch, making this function's name somewhat inaccurate.
 ^ static void parseqatom(struct vars *, int, int, struct state *,
 ^ 	struct state *, struct subre *);
 ^	struct state *, struct subre *);
 */
static void
parseqatom(
    struct vars *v,
    int stopper,		/* EOS or ')' */
    int type,			/* LACON (lookahead subRE) or PLAIN */
    struct state *lp,		/* left state to hang it on */
1645
1646
1647
1648
1649
1650
1651
1652

1653
1654
1655
1656
1657
1658
1659
1645
1646
1647
1648
1649
1650
1651

1652
1653
1654
1655
1656
1657
1658
1659







-
+








    dovec(v, allcases(v, c), lp, rp);
}

/*
 - dovec - fill in arcs for each element of a cvec
 ^ static void dovec(struct vars *, struct cvec *, struct state *,
 ^ 	struct state *);
 ^	struct state *);
 */
static void
dovec(
    struct vars *v,
    struct cvec *cv,
    struct state *lp,
    struct state *rp)
2043
2044
2045
2046
2047
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
2043
2044
2045
2046
2047
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







-
+
















-
+








-
+







static void
dump(
    regex_t *re,
    FILE *f)
{
#ifdef REG_DEBUG
    struct guts *g;
    int i;
    size_t i;

    if (re->re_magic != REMAGIC) {
	fprintf(f, "bad magic number (0x%x not 0x%x)\n",
		re->re_magic, REMAGIC);
    }
    if (re->re_guts == NULL) {
	fprintf(f, "NULL guts!!!\n");
	return;
    }
    g = (struct guts *) re->re_guts;
    if (g->magic != GUTSMAGIC) {
	fprintf(f, "bad guts magic number (0x%x not 0x%x)\n",
		g->magic, GUTSMAGIC);
    }

    fprintf(f, "\n\n\n========= DUMP ==========\n");
    fprintf(f, "nsub %" TCL_Z_MODIFIER "d, info 0%lo, ntree %d\n",
    fprintf(f, "nsub %" TCL_Z_MODIFIER "u, info 0%lo, ntree %" TCL_Z_MODIFIER "u\n",
	    re->re_nsub, re->re_info, g->ntree);

    dumpcolors(&g->cmap, f);
    if (!NULLCNFA(g->search)) {
	fprintf(f, "\nsearch:\n");
	dumpcnfa(&g->search, f);
    }
    for (i = 1; i < g->nlacons; i++) {
	fprintf(f, "\nla%d (%s):\n", i,
	fprintf(f, "\nla%" TCL_Z_MODIFIER "u (%s):\n", i,
		(g->lacons[i].subno) ? "positive" : "negative");
	dumpcnfa(&g->lacons[i].cnfa, f);
    }
    fprintf(f, "\n");
    dumpst(g->tree, f, 0);
#else
    (void)re;
2141
2142
2143
2144
2145
2146
2147
2148

2149
2150
2151
2152
2153
2154
2155
2141
2142
2143
2144
2145
2146
2147

2148
2149
2150
2151
2152
2153
2154
2155







-
+







	fprintf(f, " {%d,", t->min);
	if (t->max != DUPINF) {
	    fprintf(f, "%d", t->max);
	}
	fprintf(f, "}");
    }
    if (nfapresent) {
	fprintf(f, " %ld-%ld", (long)t->begin->no, (long)t->end->no);
	fprintf(f, " %" TCL_Z_MODIFIER "u-%" TCL_Z_MODIFIER "u", t->begin->no, t->end->no);
    }
    if (t->left != NULL) {
	fprintf(f, " L:%s", stid(t->left, idbuf, sizeof(idbuf)));
    }
    if (t->right != NULL) {
	fprintf(f, " R:%s", stid(t->right, idbuf, sizeof(idbuf)));
    }
2180
2181
2182
2183
2184
2185
2186
2187

2188
2189

2190
2191
2192
2193
2194
2195
2196
2180
2181
2182
2183
2184
2185
2186

2187
2188

2189
2190
2191
2192
2193
2194
2195
2196







-
+

-
+







     * Big enough for hex int or decimal t->id?
     */

    if (bufsize < sizeof(void*)*2 + 3 || bufsize < sizeof(t->id)*3 + 1) {
	return "unable";
    }
    if (t->id != 0) {
	sprintf(buf, "%d", t->id);
	snprintf(buf, bufsize, "%d", t->id);
    } else {
	sprintf(buf, "%p", t);
	snprintf(buf, bufsize, "%p", t);
    }
    return buf;
}

#include "regc_lex.c"
#include "regc_color.c"
#include "regc_nfa.c"

Changes to generic/regcustom.h.

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
80
81
82
83
84
85
86

87
88
89





90
91
92
93
94
95
96







-



-
-
-
-
-







typedef Tcl_UniChar chr;	/* The type itself. */
typedef int pchr;		/* What it promotes to. */
typedef unsigned uchr;		/* Unsigned type that will hold a chr. */
typedef int celt;		/* Type to hold chr, or NOCELT */
#define	NOCELT (-1)		/* Celt value which is not valid chr */
#define	CHR(c) (UCHAR(c))	/* Turn char literal into chr literal */
#define	DIGITVAL(c) ((c)-'0')	/* Turn chr digit into its value */
#if TCL_UTF_MAX > 3
#define	CHRBITS	32		/* Bits in a chr; must not use sizeof */
#define	CHR_MIN	0x00000000	/* Smallest and largest chr; the value */
#define	CHR_MAX	0x10FFFF	/* CHR_MAX-CHR_MIN+1 should fit in uchr */
#else
#define	CHRBITS	16		/* Bits in a chr; must not use sizeof */
#define	CHR_MIN	0x0000		/* Smallest and largest chr; the value */
#define	CHR_MAX	0xFFFF		/* CHR_MAX-CHR_MIN+1 should fit in uchr */
#endif

/*
 * Functions operating on chr.
 */

#define	iscalnum(x)	Tcl_UniCharIsAlnum(x)
#define	iscalpha(x)	Tcl_UniCharIsAlpha(x)

Changes to generic/rege_dfa.c.

1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







/*
 * DFA routines
 * This file is #included by regexec.c.
 *
 * Copyright (c) 1998, 1999 Henry Spencer.  All rights reserved.
 * Copyright © 1998, 1999 Henry Spencer.  All rights reserved.
 *
 * Development of this software was funded, in part, by Cray Research Inc.,
 * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
 * Corporation, none of whom are responsible for the results.  The author
 * thanks all of them.
 *
 * Redistribution and use in source and binary forms -- with or without
43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57







-
+







    int *const hitstopp)	/* record whether hit v->stop, if non-NULL */
{
    chr *cp;
    chr *realstop = (stop == v->stop) ? stop : stop + 1;
    color co;
    struct sset *css, *ss;
    chr *post;
    int i;
    size_t i;
    struct colormap *cm = d->cm;

    /*
     * Initialize.
     */

    css = initialize(v, d, start);
155
156
157
158
159
160
161
162

163
164
165
166
167
168
169
155
156
157
158
159
160
161

162
163
164
165
166
167
168
169







-
+








    return NULL;
}

/*
 - shortest - shortest-preferred matching engine
 ^ static chr *shortest(struct vars *, struct dfa *, chr *, chr *, chr *,
 ^ 	chr **, int *);
 ^	chr **, int *);
 */
static chr *			/* endpoint, or NULL */
shortest(
    struct vars *const v,
    struct dfa *const d,
    chr *const start,		/* where the match should start */
    chr *const min,		/* match must end at or after here */
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
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







-
+















-
+










-
+







static chr *			/* endpoint, or NULL */
lastCold(
    struct vars *const v,
    struct dfa *const d)
{
    struct sset *ss;
    chr *nopr = d->lastnopr;
    int i;
    size_t i;

    if (nopr == NULL) {
	nopr = v->start;
    }
    for (ss = d->ssets, i = d->nssused; i > 0; ss++, i--) {
	if ((ss->flags&NOPROGRESS) && nopr < ss->lastseen) {
	    nopr = ss->lastseen;
	}
    }
    return nopr;
}

/*
 - newDFA - set up a fresh DFA
 ^ static struct dfa *newDFA(struct vars *, struct cnfa *,
 ^ 	struct colormap *, struct smalldfa *);
 ^	struct colormap *, struct smalldfa *);
 */
static struct dfa *
newDFA(
    struct vars *const v,
    struct cnfa *const cnfa,
    struct colormap *const cm,
    struct smalldfa *sml)	/* preallocated space, may be NULL */
{
    struct dfa *d;
    size_t nss = cnfa->nstates * 2;
    int wordsper = (cnfa->nstates + UBITS - 1) / UBITS;
    size_t wordsper = (cnfa->nstates + UBITS - 1) / UBITS;
    struct smalldfa *smallwas = sml;

    assert(cnfa != NULL && cnfa->nstates != 0);

    if (nss <= FEWSTATES && cnfa->ncolors <= FEWCOLORS) {
	assert(wordsper == 1);
	if (sml == NULL) {
415
416
417
418
419
420
421
422

423
424
425
426
427
428
429
415
416
417
418
419
420
421

422
423
424
425
426
427
428
429







-
+







 - hash - construct a hash code for a bitvector
 * There are probably better ways, but they're more expensive.
 ^ static unsigned hash(unsigned *, int);
 */
static unsigned
hash(
    unsigned *const uv,
    const int n)
    int n)
{
    int i;
    unsigned h;

    h = 0;
    for (i = 0; i < n; i++) {
	h ^= uv[i];
438
439
440
441
442
443
444
445

446
447
448
449
450
451
452
438
439
440
441
442
443
444

445
446
447
448
449
450
451
452







-
+







static struct sset *
initialize(
    struct vars *const v,	/* used only for debug flags */
    struct dfa *const d,
    chr *const start)
{
    struct sset *ss;
    int i;
    size_t i;

    /*
     * Is previous one still there?
     */

    if (d->nssused > 0 && (d->ssets[0].flags&STARTER)) {
	ss = &d->ssets[0];
473
474
475
476
477
478
479
480

481
482
483
484
485
486
487
488
489
490
491
492
493
494

495

496
497
498
499
500
501
502
473
474
475
476
477
478
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







-
+














+
-
+







    d->lastnopr = NULL;
    return ss;
}

/*
 - miss - handle a cache miss
 ^ static struct sset *miss(struct vars *, struct dfa *, struct sset *,
 ^ 	pcolor, chr *, chr *);
 ^	pcolor, chr *, chr *);
 */
static struct sset *		/* NULL if goes to empty set */
miss(
    struct vars *const v,	/* used only for debug flags */
    struct dfa *const d,
    struct sset *const css,
    const pcolor co,
    chr *const cp,		/* next chr */
    chr *const start)		/* where the attempt got started */
{
    struct cnfa *cnfa = d->cnfa;
    unsigned h;
    struct carc *ca;
    struct sset *p;
    size_t i;
    int i, isPost, noProgress, gotState, doLAConstraints, sawLAConstraints;
    int isPost, noProgress, gotState, doLAConstraints, sawLAConstraints;

    /*
     * For convenience, we can be called even if it might not be a miss.
     */

    if (css->outs[co] != NULL) {
	FDEBUG(("hit\n"));
522
523
524
525
526
527
528
529

530
531
532
533
534
535
536
523
524
525
526
527
528
529

530
531
532
533
534
535
536
537







-
+







		    gotState = 1;
		    if (ca->to == cnfa->post) {
			isPost = 1;
		    }
		    if (!(cnfa->stflags[ca->to] & CNFA_NOPROGRESS)) {
			noProgress = 0;
		    }
		    FDEBUG(("%d -> %d\n", i, ca->to));
		    FDEBUG(("%" TCL_Z_MODIFIER "u -> %" TCL_Z_MODIFIER "u\n", i, ca->to));
		}
	    }
	}
    }
    doLAConstraints = (gotState ? (cnfa->flags&HASLACONS) : 0);
    sawLAConstraints = 0;
    while (doLAConstraints) {		/* transitive closure */
552
553
554
555
556
557
558
559

560
561
562
563
564
565
566
553
554
555
556
557
558
559

560
561
562
563
564
565
566
567







-
+







		    doLAConstraints = 1;
		    if (ca->to == cnfa->post) {
			isPost = 1;
		    }
		    if (!(cnfa->stflags[ca->to] & CNFA_NOPROGRESS)) {
			noProgress = 0;
		    }
		    FDEBUG(("%d :> %d\n", i, ca->to));
		    FDEBUG(("%" TCL_Z_MODIFIER "u :> %" TCL_Z_MODIFIER"u\n", i, ca->to));
		}
	    }
	}
    }
    if (!gotState) {
	return NULL;
    }
611
612
613
614
615
616
617
618

619
620
621
622
623
624
625
626

627
628
629
630
631
632
633
634
635

636
637
638
639
640
641
642
612
613
614
615
616
617
618

619
620
621
622
623
624
625
626

627
628
629
630
631
632
633
634
635

636
637
638
639
640
641
642
643







-
+







-
+








-
+







static int			/* predicate:  constraint satisfied? */
checkLAConstraint(
    struct vars *const v,
    struct cnfa *const pcnfa,	/* parent cnfa */
    chr *const cp,
    const pcolor co)		/* "color" of the lookahead constraint */
{
    int n;
    size_t n;
    struct subre *sub;
    struct dfa *d;
    struct smalldfa sd;
    chr *end;

    n = co - pcnfa->ncolors;
    assert(n < v->g->nlacons && v->g->lacons != NULL);
    FDEBUG(("=== testing lacon %d\n", n));
    FDEBUG(("=== testing lacon %" TCL_Z_MODIFIER "u\n", n));
    sub = &v->g->lacons[n];
    d = newDFA(v, &sub->cnfa, &v->g->cmap, &sd);
    if (d == NULL) {
	ERR(REG_ESPACE);
	return 0;
    }
    end = longest(v, d, cp, v->stop, NULL);
    freeDFA(d);
    FDEBUG(("=== lacon %d match %d\n", n, (end != NULL)));
    FDEBUG(("=== lacon %" TCL_Z_MODIFIER "u match %d\n", n, (end != NULL)));
    return (sub->subno) ? (end != NULL) : (end == NULL);
}

/*
 - getVacantSS - get a vacant state set
 * This routine clears out the inarcs and outarcs, but does not otherwise
 * clear the innards of the state set -- that's up to the caller.
734
735
736
737
738
739
740
741

742
743
744


745
746
747
748
749
750

751
752
753
754
755


756
757
758
759
760
761
762
763
764
765
766
767

768
769
770
771
772
773
774
775
776

777
778
779
780
781
782
783
784

785
786
787
788
789
790
791
792
793

794
795
796
797
798
799
800
801
802
803
804
805
735
736
737
738
739
740
741

742
743


744
745
746
747
748
749
750

751
752
753
754


755
756
757
758
759
760
761
762
763
764
765
766
767

768
769
770
771
772
773
774
775
776

777
778
779
780
781
782
783
784

785
786
787
788
789
790
791
792
793

794
795
796
797
798
799
800
801
802
803
804
805
806







-
+

-
-
+
+





-
+



-
-
+
+











-
+








-
+







-
+








-
+












    chr *ancient;

    /*
     * Shortcut for cases where cache isn't full.
     */

    if (d->nssused < d->nssets) {
	i = d->nssused;
	size_t j = d->nssused;
	d->nssused++;
	ss = &d->ssets[i];
	FDEBUG(("new c%d\n", i));
	ss = &d->ssets[j];
	FDEBUG(("new c%" TCL_Z_MODIFIER "u\n", j));

	/*
	 * Set up innards.
	 */

	ss->states = &d->statesarea[i * d->wordsper];
	ss->states = &d->statesarea[j * d->wordsper];
	ss->flags = 0;
	ss->ins.ss = NULL;
	ss->ins.co = WHITE;	/* give it some value */
	ss->outs = &d->outsarea[i * d->ncolors];
	ss->inchain = &d->incarea[i * d->ncolors];
	ss->outs = &d->outsarea[j * d->ncolors];
	ss->inchain = &d->incarea[j * d->ncolors];
	for (i = 0; i < d->ncolors; i++) {
	    ss->outs[i] = NULL;
	    ss->inchain[i].ss = NULL;
	}
	return ss;
    }

    /*
     * Look for oldest, or old enough anyway.
     */

    if (cp - start > d->nssets*2/3) {	/* oldest 33% are expendable */
    if ((size_t)(cp - start) > d->nssets*2/3) {	/* oldest 33% are expendable */
	ancient = cp - d->nssets*2/3;
    } else {
	ancient = start;
    }
    for (ss = d->search, end = &d->ssets[d->nssets]; ss < end; ss++) {
	if ((ss->lastseen == NULL || ss->lastseen < ancient)
		&& !(ss->flags&LOCKED)) {
	    d->search = ss + 1;
	    FDEBUG(("replacing c%d\n", (int) (ss - d->ssets)));
	    FDEBUG(("replacing c%" TCL_Z_MODIFIER "u\n", (size_t)(ss - d->ssets)));
	    return ss;
	}
    }
    for (ss = d->ssets, end = d->search; ss < end; ss++) {
	if ((ss->lastseen == NULL || ss->lastseen < ancient)
		&& !(ss->flags&LOCKED)) {
	    d->search = ss + 1;
	    FDEBUG(("replacing c%d\n", (int) (ss - d->ssets)));
	    FDEBUG(("replacing c%" TCL_Z_MODIFIER "u\n", (size_t)(ss - d->ssets)));
	    return ss;
	}
    }

    /*
     * Nobody's old enough?!? -- something's really wrong.
     */

    FDEBUG(("can't find victim to replace!\n"));
    FDEBUG(("cannot find victim to replace!\n"));
    assert(NOTREACHED);
    ERR(REG_ASSERT);
    return d->ssets;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/regerror.c.

1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







/*
 * regerror - error-code expansion
 *
 * Copyright (c) 1998, 1999 Henry Spencer.  All rights reserved.
 * Copyright © 1998, 1999 Henry Spencer.  All rights reserved.
 *
 * Development of this software was funded, in part, by Cray Research Inc.,
 * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
 * Corporation, none of whom are responsible for the results.  The author
 * thanks all of them.
 *
 * Redistribution and use in source and binary forms -- with or without
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
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







-
+












-
+












-
+







    switch (code) {
    case REG_ATOI:		/* Convert name to number */
	for (r = rerrs; r->code >= 0; r++) {
	    if (strcmp(r->name, errbuf) == 0) {
		break;
	    }
	}
	sprintf(convbuf, "%d", r->code); /* -1 for unknown */
	snprintf(convbuf, sizeof(convbuf), "%d", r->code); /* -1 for unknown */
	msg = convbuf;
	break;
    case REG_ITOA:		/* Convert number to name */
	icode = atoi(errbuf);	/* Not our problem if this fails */
	for (r = rerrs; r->code >= 0; r++) {
	    if (r->code == icode) {
		break;
	    }
	}
	if (r->code >= 0) {
	    msg = r->name;
	} else {		/* Unknown; tell him the number */
	    sprintf(convbuf, "REG_%u", icode);
	    snprintf(convbuf, sizeof(convbuf), "REG_%u", icode);
	    msg = convbuf;
	}
	break;
    default:			/* A real, normal error code */
	for (r = rerrs; r->code >= 0; r++) {
	    if (r->code == code) {
		break;
	    }
	}
	if (r->code >= 0) {
	    msg = r->explain;
	} else {		/* Unknown; say so */
	    sprintf(convbuf, unk, code);
	    snprintf(convbuf, sizeof(convbuf), unk, code);
	    msg = convbuf;
	}
	break;
    }

    len = strlen(msg) + 1;	/* Space needed, including NUL */
    if (errbuf_size > 0) {

Changes to generic/regerrs.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15


16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12
13


14
15
16
17
18
19
20













-
-
+
+





{ REG_OKAY,	"REG_OKAY",	"no errors detected" },
{ REG_NOMATCH,	"REG_NOMATCH",	"failed to match" },
{ REG_BADPAT,	"REG_BADPAT",	"invalid regexp (reg version 0.8)" },
{ REG_ECOLLATE,	"REG_ECOLLATE",	"invalid collating element" },
{ REG_ECTYPE,	"REG_ECTYPE",	"invalid character class" },
{ REG_EESCAPE,	"REG_EESCAPE",	"invalid escape \\ sequence" },
{ REG_ESUBREG,	"REG_ESUBREG",	"invalid backreference number" },
{ REG_EBRACK,	"REG_EBRACK",	"brackets [] not balanced" },
{ REG_EPAREN,	"REG_EPAREN",	"parentheses () not balanced" },
{ REG_EBRACE,	"REG_EBRACE",	"braces {} not balanced" },
{ REG_BADBR,	"REG_BADBR",	"invalid repetition count(s)" },
{ REG_ERANGE,	"REG_ERANGE",	"invalid character range" },
{ REG_ESPACE,	"REG_ESPACE",	"out of memory" },
{ REG_BADRPT,	"REG_BADRPT",	"quantifier operand invalid" },
{ REG_ASSERT,	"REG_ASSERT",	"\"can't happen\" -- you found a bug" },
{ REG_BADRPT,	"REG_BADRPT",	"invalid quantifier operand" },
{ REG_ASSERT,	"REG_ASSERT",	"\"cannot happen\" -- you found a bug" },
{ REG_INVARG,	"REG_INVARG",	"invalid argument to regex function" },
{ REG_MIXED,	"REG_MIXED",	"character widths of regex and string differ" },
{ REG_BADOPT,	"REG_BADOPT",	"invalid embedded option" },
{ REG_ETOOBIG,	"REG_ETOOBIG",	"regular expression is too complex" },
{ REG_ECOLORS,	"REG_ECOLORS",	"too many colors" },

Changes to generic/regexec.c.

1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







/*
 * re_*exec and friends - match REs
 *
 * Copyright (c) 1998, 1999 Henry Spencer.  All rights reserved.
 * Copyright © 1998, 1999 Henry Spencer.  All rights reserved.
 *
 * Development of this software was funded, in part, by Cray Research Inc.,
 * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
 * Corporation, none of whom are responsible for the results.  The author
 * thanks all of them.
 *
 * Redistribution and use in source and binary forms -- with or without
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
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







-
-
-
+
+
+
+

-
+










-







    struct arcp ins;		/* chain of inarcs pointing here */
    chr *lastseen;		/* last entered on arrival here */
    struct sset **outs;		/* outarc vector indexed by color */
    struct arcp *inchain;	/* chain-pointer vector for outarcs */
};

struct dfa {
    int nssets;			/* size of cache */
    int nssused;		/* how many entries occupied yet */
    int nstates;		/* number of states */
    size_t nssets;			/* size of cache */
    size_t nssused;		/* how many entries occupied yet */
    size_t nstates;		/* number of states */
    size_t wordsper;		/* length of state-set bitvectors */
    int ncolors;		/* length of outarc and inchain vectors */
    int wordsper;		/* length of state-set bitvectors */
    int cptsmalloced;		/* were the areas individually malloced? */
    struct sset *ssets;		/* state-set cache */
    unsigned *statesarea;	/* bitvector storage */
    unsigned *work;		/* pointer to work area within statesarea */
    struct sset **outsarea;	/* outarc-vector storage */
    struct arcp *incarea;	/* inchain storage */
    struct cnfa *cnfa;
    struct colormap *cm;
    chr *lastpost;		/* location of last cache-flushed success */
    chr *lastnopr;		/* location of last cache-flushed NOPROGRESS */
    struct sset *search;	/* replacement-search-pointer memory */
    int cptsmalloced;		/* were the areas individually malloced? */
    char *mallocarea;		/* self, or malloced area, or NULL */
};

#define	WORK	1		/* number of work bitvectors needed */

/*
 * Setup for non-malloc allocation for small cases.
112
113
114
115
116
117
118
119

120
121
122
123
124
125
126
112
113
114
115
116
117
118

119
120
121
122
123
124
125
126







-
+







};
#define	VISERR(vv) ((vv)->err != 0)	/* have we seen an error yet? */
#define	ISERR()	VISERR(v)
#define VERR(vv,e) ((vv)->err = ((vv)->err ? (vv)->err : (e)))
#define	ERR(e)	VERR(v, e)	/* record an error */
#define	NOERR()	{if (ISERR()) return v->err;}	/* if error seen, return it */
#define	OFF(p)	((p) - v->start)
#define	LOFF(p)	((long)OFF(p))
#define	LOFF(p)	((size_t)OFF(p))

/*
 * forward declarations
 */
/* =====^!^===== begin forwards =====^!^===== */
/* automatically gathered by fwd; do not hand-edit */
/* === regexec.c === */
141
142
143
144
145
146
147
148

149
150
151
152
153
154
155
141
142
143
144
145
146
147

148
149
150
151
152
153
154
155







-
+







static int creviterdissect(struct vars *, struct subre *, chr *, chr *);
/* === rege_dfa.c === */
static chr *longest(struct vars *const, struct dfa *const, chr *const, chr *const, int *const);
static chr *shortest(struct vars *const, struct dfa *const, chr *const, chr *const, chr *const, chr **const, int *const);
static chr *lastCold(struct vars *const, struct dfa *const);
static struct dfa *newDFA(struct vars *const, struct cnfa *const, struct colormap *const, struct smalldfa *);
static void freeDFA(struct dfa *const);
static unsigned hash(unsigned *const, const int);
static unsigned hash(unsigned *const, int);
static struct sset *initialize(struct vars *const, struct dfa *const, chr *const);
static struct sset *miss(struct vars *const, struct dfa *const, struct sset *const, const pcolor, chr *const, chr *const);
static int checkLAConstraint(struct vars *const, struct cnfa *const, chr *const, const pcolor);
static struct sset *getVacantSS(struct vars *const, struct dfa *const, chr *const, chr *const);
static struct sset *pickNextSS(struct vars *const, struct dfa *const, chr *const, chr *const);
/* automatically gathered by fwd; do not hand-edit */
/* =====^!^===== end forwards =====^!^===== */
228
229
230
231
232
233
234
235

236
237

238

239
240

241

242
243
244
245
246
247
248
228
229
230
231
232
233
234

235
236

237
238
239
240

241
242
243
244
245
246
247
248
249
250







-
+

-
+

+

-
+

+







    }
    v->details = details;
    v->start = (chr *)string;
    v->stop = (chr *)string + len;
    v->err = 0;
    assert(v->g->ntree >= 0);
    n = v->g->ntree;
    if (n <= LOCALDFAS)
    if (n <= LOCALDFAS) {
	v->subdfas = subdfas;
    else
    } else {
	v->subdfas = (struct dfa **) MALLOC(n * sizeof(struct dfa *));
    }
    if (v->subdfas == NULL) {
	if (v->pmatch != pmatch && v->pmatch != mat)
	if (v->pmatch != pmatch && v->pmatch != mat) {
	    FREE(v->pmatch);
	}
	FreeVars(v);
	return REG_ESPACE;
    }
    for (i = 0; i < n; i++)
	v->subdfas[i] = NULL;

    /*
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
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







-
+

-
-
+
+
+

+















-
+

+







     */

    if (v->pmatch != pmatch && v->pmatch != mat) {
	FREE(v->pmatch);
    }
    n = v->g->ntree;
    for (i = 0; i < n; i++) {
	if (v->subdfas[i] != NULL)
	if (v->subdfas[i] != NULL) {
	    freeDFA(v->subdfas[i]);
    }
    if (v->subdfas != subdfas)
	}
    }
    if (v->subdfas != subdfas) {
	FREE(v->subdfas);
    }
    FreeVars(v);
    return st;
}

/*
 - getsubdfa - create or re-fetch the DFA for a subre node
 * We only need to create the DFA once per overall regex execution.
 * The DFA will be freed by the cleanup step in exec().
 */
static struct dfa *
getsubdfa(struct vars * v,
	  struct subre * t)
{
    if (v->subdfas[t->id] == NULL) {
	v->subdfas[t->id] = newDFA(v, &t->cnfa, &v->g->cmap, NULL);
	if (ISERR())
	if (ISERR()) {
	    return NULL;
	}
    }
    return v->subdfas[t->id];
}

/*
 - simpleFind - find a match for the main NFA (no-complications case)
 ^ static int simpleFind(struct vars *, struct cnfa *, struct colormap *);
322
323
324
325
326
327
328
329

330
331
332
333
334
335
336
327
328
329
330
331
332
333

334
335
336
337
338
339
340
341







-
+







    /*
     * First, a shot with the search RE.
     */

    s = newDFA(v, &v->g->search, cm, &v->dfa1);
    assert(!(ISERR() && s != NULL));
    NOERR();
    MDEBUG(("\nsearch at %ld\n", LOFF(v->start)));
    MDEBUG(("\nsearch at %" TCL_Z_MODIFIER "u\n", LOFF(v->start)));
    cold = NULL;
    close = shortest(v, s, v->start, v->start, v->stop, &cold, NULL);
    freeDFA(s);
    NOERR();
    if (v->g->cflags&REG_EXPECT) {
	assert(v->details != NULL);
	if (cold != NULL) {
350
351
352
353
354
355
356
357

358
359
360
361
362

363
364
365
366
367
368
369
355
356
357
358
359
360
361

362
363
364
365
366

367
368
369
370
371
372
373
374







-
+




-
+







    /*
     * Find starting point and match.
     */

    assert(cold != NULL);
    open = cold;
    cold = NULL;
    MDEBUG(("between %ld and %ld\n", LOFF(open), LOFF(close)));
    MDEBUG(("between %" TCL_Z_MODIFIER "u and %" TCL_Z_MODIFIER "u\n", LOFF(open), LOFF(close)));
    d = newDFA(v, cnfa, cm, &v->dfa1);
    assert(!(ISERR() && d != NULL));
    NOERR();
    for (begin = open; begin <= close; begin++) {
	MDEBUG(("\nfind trying at %ld\n", LOFF(begin)));
	MDEBUG(("\nfind trying at %" TCL_Z_MODIFIER "u\n", LOFF(begin)));
	if (shorter) {
	    end = shortest(v, d, begin, begin, v->stop, NULL, &hitend);
	} else {
	    end = longest(v, d, begin, v->stop, &hitend);
	}
	if (ISERR()) {
	    freeDFA(d);
466
467
468
469
470
471
472
473

474
475
476
477
478
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
471
472
473
474
475
476
477

478
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







-
+







-
+

-
+















-
+







    int er, hitend;
    int shorter = v->g->tree->flags&SHORTER;

    assert(d != NULL && s != NULL);
    cold = NULL;
    close = v->start;
    do {
	MDEBUG(("\ncsearch at %ld\n", LOFF(close)));
	MDEBUG(("\ncsearch at %" TCL_Z_MODIFIER "u\n", LOFF(close)));
	close = shortest(v, s, close, close, v->stop, &cold, NULL);
	if (close == NULL) {
	    break;		/* NOTE BREAK */
	}
	assert(cold != NULL);
	open = cold;
	cold = NULL;
	MDEBUG(("cbetween %ld and %ld\n", LOFF(open), LOFF(close)));
	MDEBUG(("cbetween %" TCL_Z_MODIFIER "u and %" TCL_Z_MODIFIER "u\n", LOFF(open), LOFF(close)));
	for (begin = open; begin <= close; begin++) {
	    MDEBUG(("\ncomplicatedFind trying at %ld\n", LOFF(begin)));
	    MDEBUG(("\ncomplicatedFind trying at %" TCL_Z_MODIFIER "u\n", LOFF(begin)));
	    estart = begin;
	    estop = v->stop;
	    for (;;) {
		if (shorter) {
		    end = shortest(v, d, begin, estart, estop, NULL, &hitend);
		} else {
		    end = longest(v, d, begin, estop, &hitend);
		}
		if (hitend && cold == NULL) {
		    cold = begin;
		}
		if (end == NULL) {
		    break;	/* NOTE BREAK OUT */
		}

		MDEBUG(("tentative end %ld\n", LOFF(end)));
		MDEBUG(("tentative end %" TCL_Z_MODIFIER "u\n", LOFF(end)));
		zapallsubs(v->pmatch, v->nmatch);
		er = cdissect(v, v->g->tree, begin, end);
		if (er == REG_OKAY) {
		    if (v->nmatch > 0) {
			v->pmatch[0].rm_so = OFF(begin);
			v->pmatch[0].rm_eo = OFF(end);
		    }
541
542
543
544
545
546
547
548
549


550
551
552
553
554
555
556
557
558
559
560
561
562
563

564
565
566
567



568
569
570
571
572
573
574
546
547
548
549
550
551
552


553
554
555
556
557
558
559
560
561
562
563
564
565
566
567

568
569



570
571
572
573
574
575
576
577
578
579







-
-
+
+













-
+

-
-
-
+
+
+







zapallsubs(
    regmatch_t *const p,
    const size_t n)
{
    size_t i;

    for (i = n-1; i > 0; i--) {
	p[i].rm_so = -1;
	p[i].rm_eo = -1;
	p[i].rm_so = FREESTATE;
	p[i].rm_eo = FREESTATE;
    }
}

/*
 - zaptreesubs - initialize subexpressions within subtree to "no match"
 ^ static void zaptreesubs(struct vars *, struct subre *);
 */
static void
zaptreesubs(
    struct vars *const v,
    struct subre *const t)
{
    if (t->op == '(') {
	int n = t->subno;
	size_t n = t->subno;
	assert(n > 0);
	if ((size_t) n < v->nmatch) {
	    v->pmatch[n].rm_so = -1;
	    v->pmatch[n].rm_eo = -1;
	if (n < v->nmatch) {
	    v->pmatch[n].rm_so = FREESTATE;
	    v->pmatch[n].rm_eo = FREESTATE;
	}
    }

    if (t->left != NULL) {
	zaptreesubs(v, t->left);
    }
    if (t->right != NULL) {
619
620
621
622
623
624
625
626

627
628
629
630
631
632
633
634
635
636
637
638
639

640
641

642

643
644
645
646
647
648
649
650

651
652

653

654
655
656
657
658
659
660
624
625
626
627
628
629
630

631
632
633
634
635
636
637
638
639
640
641
642
643

644
645

646
647
648
649
650
651
652
653
654
655

656
657

658
659
660
661
662
663
664
665
666
667







-
+












-
+

-
+

+







-
+

-
+

+







    struct subre *t,
    chr *begin,		/* beginning of relevant substring */
    chr *end)		/* end of same */
{
    int er;

    assert(t != NULL);
    MDEBUG(("cdissect %ld-%ld %c\n", LOFF(begin), LOFF(end), t->op));
    MDEBUG(("cdissect %" TCL_Z_MODIFIER "u-%" TCL_Z_MODIFIER "u %c\n", LOFF(begin), LOFF(end), t->op));

    switch (t->op) {
    case '=':			/* terminal node */
	assert(t->left == NULL && t->right == NULL);
	er = REG_OKAY;		/* no action, parent did the work */
	break;
    case 'b':			/* back reference */
	assert(t->left == NULL && t->right == NULL);
	er = cbrdissect(v, t, begin, end);
	break;
    case '.':			/* concatenation */
	assert(t->left != NULL && t->right != NULL);
	if (t->left->flags & SHORTER) /* reverse scan */
	if (t->left->flags & SHORTER) {/* reverse scan */
	    er = crevcondissect(v, t, begin, end);
	else
	} else {
	    er = ccondissect(v, t, begin, end);
	}
	break;
    case '|':			/* alternation */
	assert(t->left != NULL);
	er = caltdissect(v, t, begin, end);
	break;
    case '*':			/* iteration */
	assert(t->left != NULL);
	if (t->left->flags & SHORTER) /* reverse scan */
	if (t->left->flags & SHORTER) {/* reverse scan */
	    er = creviterdissect(v, t, begin, end);
	else
	} else {
	    er = citerdissect(v, t, begin, end);
	}
	break;
    case '(':			/* capturing */
	assert(t->left != NULL && t->right == NULL);
	assert(t->subno > 0);
	er = cdissect(v, t->left, begin, end);
	if (er == REG_OKAY) {
	    subset(v, t, begin, end);
704
705
706
707
708
709
710
711

712
713
714
715
716
717
718
711
712
713
714
715
716
717

718
719
720
721
722
723
724
725







-
+







    /*
     * Pick a tentative midpoint.
     */
    mid = longest(v, d, begin, end, (int *) NULL);
    if (mid == NULL) {
	return REG_NOMATCH;
    }
    MDEBUG(("tentative midpoint %ld\n", LOFF(mid)));
    MDEBUG(("tentative midpoint %" TCL_Z_MODIFIER "u\n", LOFF(mid)));

    /*
     * Iterate until satisfaction or failure.
     */

    for (;;) {
	/*
755
756
757
758
759
760
761
762

763
764
765
766
767
768
769
762
763
764
765
766
767
768

769
770
771
772
773
774
775
776







-
+







	    /*
	     * Failed to find a new one.
	     */

	    MDEBUG(("%d failed midpoint\n", t->id));
	    return REG_NOMATCH;
	}
	MDEBUG(("%d: new midpoint %ld\n", t->id, LOFF(mid)));
	MDEBUG(("%d: new midpoint %" TCL_Z_MODIFIER "u\n", t->id, LOFF(mid)));
	zaptreesubs(v, t->left);
	zaptreesubs(v, t->right);
    }
}

/*
 - crevcondissect - dissect match for concatenation node, shortest-first
795
796
797
798
799
800
801
802

803
804
805
806
807
808
809
802
803
804
805
806
807
808

809
810
811
812
813
814
815
816







-
+







     * Pick a tentative midpoint.
     */

    mid = shortest(v, d, begin, begin, end, (chr **) NULL, (int *) NULL);
    if (mid == NULL) {
	return REG_NOMATCH;
    }
    MDEBUG(("tentative midpoint %ld\n", LOFF(mid)));
    MDEBUG(("tentative midpoint %" TCL_Z_MODIFIER "u\n", LOFF(mid)));

    /*
     * Iterate until satisfaction or failure.
     */

    for (;;) {
	/*
846
847
848
849
850
851
852
853

854
855
856
857
858
859
860
853
854
855
856
857
858
859

860
861
862
863
864
865
866
867







-
+







	    /*
	     * Failed to find a new one.
	     */

	    MDEBUG(("%d failed midpoint\n", t->id));
	    return REG_NOMATCH;
	}
	MDEBUG(("%d: new midpoint %ld\n", t->id, LOFF(mid)));
	MDEBUG(("%d: new midpoint %" TCL_Z_MODIFIER "u\n", t->id, LOFF(mid)));
	zaptreesubs(v, t->left);
	zaptreesubs(v, t->right);
    }
}

/*
 - cbrdissect - dissect match for backref node
878
879
880
881
882
883
884
885

886
887
888
889
890
891
892
885
886
887
888
889
890
891

892
893
894
895
896
897
898
899







-
+







    assert(t->op == 'b');
    assert(n >= 0);
    assert((size_t)n < v->nmatch);

    MDEBUG(("cbackref n%d %d{%d-%d}\n", t->id, n, min, max));

    /* get the backreferenced string */
    if (v->pmatch[n].rm_so == TCL_INDEX_NONE) {
    if (v->pmatch[n].rm_so == FREESTATE) {
	return REG_NOMATCH;
    }
    brstring = v->start + v->pmatch[n].rm_so;
    brlen = v->pmatch[n].rm_eo - v->pmatch[n].rm_so;

    /* special cases for zero-length strings */
    if (brlen == 0) {
912
913
914
915
916
917
918
919

920

921
922

923

924
925
926
927
928

929

930
931
932
933
934
935
936
919
920
921
922
923
924
925

926
927
928
929

930
931
932
933
934
935
936

937
938
939
940
941
942
943
944
945
946







-
+

+

-
+

+




-
+

+







    /*
     * check target length to see if it could possibly be an allowed number of
     * repetitions of brstring
     */

    assert(end > begin);
    tlen = end - begin;
    if (tlen % brlen != 0)
    if (tlen % brlen != 0) {
	return REG_NOMATCH;
    }
    numreps = tlen / brlen;
    if (numreps < (size_t)min || (numreps > (size_t)max && max != DUPINF))
    if (numreps < (size_t)min || (numreps > (size_t)max && max != DUPINF)) {
	return REG_NOMATCH;
    }

    /* okay, compare the actual string contents */
    p = begin;
    while (numreps-- > 0) {
	if ((*v->g->compare) (brstring, p, brlen) != 0)
	if ((*v->g->compare) (brstring, p, brlen) != 0) {
	    return REG_NOMATCH;
	}
	p += brlen;
    }

    MDEBUG(("cbackref matched\n"));
    return REG_OKAY;
}

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
1024
1025
1026
1027
1028
1029
1009
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







-
+

+













-
+

+







    /*
     * If zero matches are allowed, and target string is empty, just declare
     * victory.  OTOH, if target string isn't empty, zero matches can't work
     * so we pretend the min is 1.
     */
    min_matches = t->min;
    if (min_matches <= 0) {
	if (begin == end)
	if (begin == end) {
	    return REG_OKAY;
	}
	min_matches = 1;
    }

    /*
     * We need workspace to track the endpoints of each sub-match.  Normally
     * we consider only nonzero-length sub-matches, so there can be at most
     * end-begin of them.  However, if min is larger than that, we will also
     * consider zero-length sub-matches in order to find enough matches.
     *
     * For convenience, endpts[0] contains the "begin" pointer and we store
     * sub-match endpoints in endpts[1..max_matches].
     */
    max_matches = end - begin;
    if (max_matches > (size_t)t->max && t->max != DUPINF)
    if (max_matches > (size_t)t->max && t->max != DUPINF) {
	max_matches = t->max;
    }
    if (max_matches < (size_t)min_matches)
	max_matches = min_matches;
    endpts = (chr **) MALLOC((max_matches + 1) * sizeof(chr *));
    if (endpts == NULL)
	return REG_ESPACE;
    endpts[0] = begin;

1054
1055
1056
1057
1058
1059
1060
1061

1062
1063
1064
1065

1066

1067
1068
1069
1070
1071
1072
1073
1066
1067
1068
1069
1070
1071
1072

1073
1074
1075
1076

1077
1078
1079
1080
1081
1082
1083
1084
1085
1086







-
+



-
+

+







	/* try to find an endpoint for the k'th sub-match */
	endpts[k] = longest(v, d, endpts[k - 1], limit, (int *) NULL);
	if (endpts[k] == NULL) {
	    /* no match possible, so see if we can shorten previous one */
	    k--;
	    goto backtrack;
	}
	MDEBUG(("%d: working endpoint %d: %ld\n",
	MDEBUG(("%d: working endpoint %d: %" TCL_Z_MODIFIER "u\n",
		t->id, k, LOFF(endpts[k])));

	/* k'th sub-match can no longer be considered verified */
	if (nverified >= k)
	if (nverified >= k) {
	    nverified = k - 1;
	}

	if (endpts[k] != end) {
	    /* haven't reached end yet, try another iteration if allowed */
	    if ((size_t)k >= max_matches) {
		/* must try to shorten some previous match */
		k--;
		goto backtrack;
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
1098
1099
1100
1101
1102
1103
1104

1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117

1118
1119
1120
1121
1122
1123
1124
1125
1126
1127







-
+

+










-
+

+








	/*
	 * We've identified a way to divide the string into k sub-matches
	 * that works so far as the child DFA can tell.  If k is an allowed
	 * number of matches, start the slow part: recurse to verify each
	 * sub-match.  We always have k <= max_matches, needn't check that.
	 */
	if (k < min_matches)
	if (k < min_matches) {
	    goto backtrack;
	}

	MDEBUG(("%d: verifying %d..%d\n", t->id, nverified + 1, k));

	for (i = nverified + 1; i <= k; i++) {
	    zaptreesubs(v, t->left);
	    er = cdissect(v, t->left, endpts[i - 1], endpts[i]);
	    if (er == REG_OKAY) {
		nverified = i;
		continue;
	    }
	    if (er == REG_NOMATCH)
	    if (er == REG_NOMATCH) {
		break;
	    }
	    /* oops, something failed */
	    FREE(endpts);
	    return er;
	}

	if (i > k) {
	    /* satisfaction */
1172
1173
1174
1175
1176
1177
1178
1179

1180

1181
1182
1183
1184
1185
1186
1187
1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1201
1202
1203







-
+

+







    /*
     * If zero matches are allowed, and target string is empty, just declare
     * victory.  OTOH, if target string isn't empty, zero matches can't work
     * so we pretend the min is 1.
     */
    min_matches = t->min;
    if (min_matches <= 0) {
	if (begin == end)
	if (begin == end) {
	    return REG_OKAY;
	}
	min_matches = 1;
    }

    /*
     * We need workspace to track the endpoints of each sub-match.  Normally
     * we consider only nonzero-length sub-matches, so there can be at most
     * end-begin of them.  However, if min is larger than that, we will also
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
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







-
+

+









-
+



-
+

+




















-
+

+










-
+

+







	/* disallow zero-length match unless necessary to achieve min */
	if (limit == endpts[k - 1] &&
	    limit != end &&
	    (k >= min_matches || min_matches - k < end - limit))
	    limit++;

	/* if this is the last allowed sub-match, it must reach to the end */
	if ((size_t)k >= max_matches)
	if ((size_t)k >= max_matches) {
	    limit = end;
	}

	/* try to find an endpoint for the k'th sub-match */
	endpts[k] = shortest(v, d, endpts[k - 1], limit, end,
			     (chr **) NULL, (int *) NULL);
	if (endpts[k] == NULL) {
	    /* no match possible, so see if we can lengthen previous one */
	    k--;
	    goto backtrack;
	}
	MDEBUG(("%d: working endpoint %d: %ld\n",
	MDEBUG(("%d: working endpoint %d: %" TCL_Z_MODIFIER "u\n",
		t->id, k, LOFF(endpts[k])));

	/* k'th sub-match can no longer be considered verified */
	if (nverified >= k)
	if (nverified >= k) {
	    nverified = k - 1;
	}

	if (endpts[k] != end) {
	    /* haven't reached end yet, try another iteration if allowed */
	    if ((size_t)k >= max_matches) {
		/* must try to lengthen some previous match */
		k--;
		goto backtrack;
	    }

	    k++;
	    limit = endpts[k - 1];
	    continue;
	}

	/*
	 * We've identified a way to divide the string into k sub-matches
	 * that works so far as the child DFA can tell.  If k is an allowed
	 * number of matches, start the slow part: recurse to verify each
	 * sub-match.  We always have k <= max_matches, needn't check that.
	 */
	if (k < min_matches)
	if (k < min_matches) {
	    goto backtrack;
	}

	MDEBUG(("%d: verifying %d..%d\n", t->id, nverified + 1, k));

	for (i = nverified + 1; i <= k; i++) {
	    zaptreesubs(v, t->left);
	    er = cdissect(v, t->left, endpts[i - 1], endpts[i]);
	    if (er == REG_OKAY) {
		nverified = i;
		continue;
	    }
	    if (er == REG_NOMATCH)
	    if (er == REG_NOMATCH) {
		break;
	    }
	    /* oops, something failed */
	    FREE(endpts);
	    return er;
	}

	if (i > k) {
	    /* satisfaction */

Changes to generic/regfree.c.

1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







/*
 * regfree - free an RE
 *
 * Copyright (c) 1998, 1999 Henry Spencer.  All rights reserved.
 * Copyright © 1998, 1999 Henry Spencer.  All rights reserved.
 *
 * Development of this software was funded, in part, by Cray Research Inc.,
 * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
 * Corporation, none of whom are responsible for the results.  The author
 * thanks all of them.
 *
 * Redistribution and use in source and binary forms -- with or without

Changes to generic/regfronts.c.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * regcomp and regexec - front ends to re_ routines
 *
 * Mostly for implementation of backward-compatibility kludges. Note that
 * these routines exist ONLY in char versions.
 *
 * Copyright (c) 1998, 1999 Henry Spencer.  All rights reserved.
 * Copyright © 1998, 1999 Henry Spencer.  All rights reserved.
 *
 * Development of this software was funded, in part, by Cray Research Inc.,
 * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
 * Corporation, none of whom are responsible for the results.  The author
 * thanks all of them.
 *
 * Redistribution and use in source and binary forms -- with or without

Changes to generic/regguts.h.

199
200
201
202
203
204
205
206
207


208
209
210


211
212
213
214
215
216
217
199
200
201
202
203
204
205


206
207
208


209
210
211
212
213
214
215
216
217







-
-
+
+

-
-
+
+








/*
 * Interface definitions for locale-interface functions in locale.c.
 */

/* Representation of a set of characters. */
struct cvec {
    int nchrs;			/* number of chrs */
    int chrspace;		/* number of chrs possible */
    size_t nchrs;		/* number of chrs */
    size_t chrspace;		/* number of chrs possible */
    chr *chrs;			/* pointer to vector of chrs */
    int nranges;		/* number of ranges (chr pairs) */
    int rangespace;		/* number of chrs possible */
    size_t nranges;		/* number of ranges (chr pairs) */
    size_t rangespace;		/* number of chrs possible */
    chr *ranges;		/* pointer to vector of chr pairs */
};

/*
 * definitions for non-deterministic finite autmaton (NFA) internal
 * representation
 *
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
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







-
-
+
+

-
+

-
+






-
+



-
+


-
-
+
+







struct arcbatch {		/* for bulk allocation of arcs */
    struct arcbatch *next;
#define	ABSIZE	10
    struct arc a[ABSIZE];
};

struct state {
    int no;
#define	FREESTATE	(-1)
    size_t no;
#define	FREESTATE	((size_t)-1)
    char flag;			/* marks special states */
    int nins;			/* number of inarcs */
    size_t nins;		/* number of inarcs */
    struct arc *ins;		/* chain of inarcs */
    int nouts;			/* number of outarcs */
    size_t nouts;		/* number of outarcs */
    struct arc *outs;		/* chain of outarcs */
    struct arc *free;		/* chain of free arcs */
    struct state *tmp;		/* temporary for traversal algorithms */
    struct state *next;		/* chain for traversing all */
    struct state *prev;		/* back chain */
    struct arcbatch oas;	/* first arcbatch, avoid malloc in easy case */
    int noas;			/* number of arcs used in first arcbatch */
    size_t noas;		/* number of arcs used in first arcbatch */
};

struct nfa {
    struct state *pre;		/* pre-initial state */
    struct state *pre;		/* preinitial state */
    struct state *init;		/* initial state */
    struct state *final;	/* final state */
    struct state *post;		/* post-final state */
    int nstates;		/* for numbering states */
    struct state *post;		/* postfinal state */
    size_t nstates;		/* for numbering states */
    struct state *states;	/* state-chain header */
    struct state *slast;	/* tail of the chain */
    struct state *free;		/* free list */
    struct colormap *cm;	/* the color map */
    color bos[2];		/* colors, if any, assigned to BOS and BOL */
    color eos[2];		/* colors, if any, assigned to EOS and EOL */
    struct vars *v;		/* simplifies compile error reporting */
286
287
288
289
290
291
292
293

294
295
296
297

298
299
300
301
302


303
304
305
306
307
308
309
286
287
288
289
290
291
292

293
294
295
296

297
298
299
300


301
302
303
304
305
306
307
308
309







-
+



-
+



-
-
+
+







 * Plain arcs just store the transition color number as "co".  LACON arcs
 * store the lookahead constraint number plus cnfa.ncolors as "co".  LACON
 * arcs can be distinguished from plain by testing for co >= cnfa.ncolors.
 */

struct carc {
    color co;			/* COLORLESS is list terminator */
    int to;			/* next-state number */
    size_t to;			/* next-state number */
};

struct cnfa {
    int nstates;		/* number of states */
    size_t nstates;	/* number of states */
    int ncolors;		/* number of colors */
    int flags;
#define	HASLACONS	01	/* uses lookahead constraints */
    int pre;			/* setup state number */
    int post;			/* teardown state number */
    size_t pre;			/* setup state number */
    size_t post;			/* teardown state number */
    color bos[2];		/* colors, if any, assigned to BOS and BOL */
    color eos[2];		/* colors, if any, assigned to EOS and EOL */
    char *stflags;		/* vector of per-state flags bytes */
#define CNFA_NOPROGRESS	01	/* flag bit for a no-progress state */
    struct carc **states;	/* vector of pointers to outarc lists */
    /* states[n] are pointers into a single malloc'd array of arcs */
    struct carc *arcs;		/* the area for the lists */
392
393
394
395
396
397
398
399

400
401
402
403

404
405
406
407
408
409
410
392
393
394
395
396
397
398

399
400
401
402

403
404
405
406
407
408
409
410







-
+



-
+







    int magic;
#define	GUTSMAGIC	0xFED9
    int cflags;			/* copy of compile flags */
    long info;			/* copy of re_info */
    size_t nsub;		/* copy of re_nsub */
    struct subre *tree;
    struct cnfa search;		/* for fast preliminary search */
    int ntree;			/* number of subre's, plus one */
    size_t ntree;		/* number of subre's, plus one */
    struct colormap cmap;
    int (*compare) (const chr *, const chr *, size_t);
    struct subre *lacons;	/* lookahead-constraint vector */
    int nlacons;		/* size of lacons */
    size_t nlacons;		/* size of lacons */
};

/*
 * Magic for allocating a variable workspace. This default version is
 * stack-hungry.
 */

Changes to generic/tcl.decls.

1
2
3
4
5
6
7
8
9
10



11
12
13
14
15
16
17
1
2
3
4
5
6
7



8
9
10
11
12
13
14
15
16
17







-
-
-
+
+
+







# tcl.decls --
#
#	This file contains the declarations for all supported public
#	functions that are exported by the Tcl library via the stubs table.
#	This file is used to generate the tclDecls.h, tclPlatDecls.h
#	and tclStubInit.c files.
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2001, 2002 by Kevin B. Kenny.  All rights reserved.
# Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2001, 2002 Kevin B. Kenny.  All rights reserved.
# Copyright © 2007 Daniel A. Steffen <das@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

library tcl

# Define the tcl interface with several sub interfaces:
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
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







-
+





-
+


-
+





-
+



-
+



-
+



-
+


















-
+


-
+














-
-
-
-

-
-
+
+






-
+


-
-
-
-




-
+









-
+



-
+

+

-
+








-
-
-
-
-













-
+













-
-
+
+


-
+



-
-
+
+


-
-
+
+

-
-
-
-

-
+




-
-
-
-

-
+

-
-
-
-




-
+

-
-
-
-

-
+



-
+




-
-
-
-

-
+

-
-
-
-

-
+


-
+

-
-
-
-
-
-
-
-
-







	    const char *name, const char *version, int exact,
	    void *clientDataPtr)
}
declare 2 {
    TCL_NORETURN void Tcl_Panic(const char *format, ...)
}
declare 3 {
    void *Tcl_Alloc(size_t size)
    void *Tcl_Alloc(TCL_HASH_TYPE size)
}
declare 4 {
    void Tcl_Free(void *ptr)
}
declare 5 {
    void *Tcl_Realloc(void *ptr, size_t size)
    void *Tcl_Realloc(void *ptr, TCL_HASH_TYPE size)
}
declare 6 {
    void *Tcl_DbCkalloc(size_t size, const char *file, int line)
    void *Tcl_DbCkalloc(TCL_HASH_TYPE size, const char *file, int line)
}
declare 7 {
    void Tcl_DbCkfree(void *ptr, const char *file, int line)
}
declare 8 {
    void *Tcl_DbCkrealloc(void *ptr, size_t size,
    void *Tcl_DbCkrealloc(void *ptr, TCL_HASH_TYPE size,
	    const char *file, int line)
}

# Tcl_CreateFileHandler and Tcl_DeleteFileHandler are only available on unix,
# Tcl_CreateFileHandler and Tcl_DeleteFileHandler are only available on Unix,
# but they are part of the old generic interface, so we include them here for
# compatibility reasons.

declare 9 unix {
declare 9 {
    void Tcl_CreateFileHandler(int fd, int mask, Tcl_FileProc *proc,
	    void *clientData)
}
declare 10 unix {
declare 10 {
    void Tcl_DeleteFileHandler(int fd)
}
declare 11 {
    void Tcl_SetTimer(const Tcl_Time *timePtr)
}
declare 12 {
    void Tcl_Sleep(int ms)
}
declare 13 {
    int Tcl_WaitForEvent(const Tcl_Time *timePtr)
}
declare 14 {
    int Tcl_AppendAllObjTypes(Tcl_Interp *interp, Tcl_Obj *objPtr)
}
declare 15 {
    void Tcl_AppendStringsToObj(Tcl_Obj *objPtr, ...)
}
declare 16 {
    void Tcl_AppendToObj(Tcl_Obj *objPtr, const char *bytes, size_t length)
    void Tcl_AppendToObj(Tcl_Obj *objPtr, const char *bytes, Tcl_Size length)
}
declare 17 {
    Tcl_Obj *Tcl_ConcatObj(int objc, Tcl_Obj *const objv[])
    Tcl_Obj *Tcl_ConcatObj(Tcl_Size objc, Tcl_Obj *const objv[])
}
declare 18 {
    int Tcl_ConvertToType(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    const Tcl_ObjType *typePtr)
}
declare 19 {
    void Tcl_DbDecrRefCount(Tcl_Obj *objPtr, const char *file, int line)
}
declare 20 {
    void Tcl_DbIncrRefCount(Tcl_Obj *objPtr, const char *file, int line)
}
declare 21 {
    int Tcl_DbIsShared(Tcl_Obj *objPtr, const char *file, int line)
}
# Removed in 9.0 (changed to macro):
#declare 22 {
#    Tcl_Obj *Tcl_DbNewBooleanObj(int boolValue, const char *file, int line)
#}
declare 23 {
    Tcl_Obj *Tcl_DbNewByteArrayObj(const unsigned char *bytes, size_t length,
	    const char *file, int line)
    Tcl_Obj *Tcl_DbNewByteArrayObj(const unsigned char *bytes,
	    Tcl_Size numBytes, const char *file, int line)
}
declare 24 {
    Tcl_Obj *Tcl_DbNewDoubleObj(double doubleValue, const char *file,
	    int line)
}
declare 25 {
    Tcl_Obj *Tcl_DbNewListObj(int objc, Tcl_Obj *const *objv,
    Tcl_Obj *Tcl_DbNewListObj(Tcl_Size objc, Tcl_Obj *const *objv,
	    const char *file, int line)
}
# Removed in 9.0 (changed to macro):
#declare 26 {
#    Tcl_Obj *Tcl_DbNewLongObj(long longValue, const char *file, int line)
#}
declare 27 {
    Tcl_Obj *Tcl_DbNewObj(const char *file, int line)
}
declare 28 {
    Tcl_Obj *Tcl_DbNewStringObj(const char *bytes, size_t length,
    Tcl_Obj *Tcl_DbNewStringObj(const char *bytes, Tcl_Size length,
	    const char *file, int line)
}
declare 29 {
    Tcl_Obj *Tcl_DuplicateObj(Tcl_Obj *objPtr)
}
declare 30 {
    void TclFreeObj(Tcl_Obj *objPtr)
}
declare 31 {
    int Tcl_GetBoolean(Tcl_Interp *interp, const char *src, int *boolPtr)
    int Tcl_GetBoolean(Tcl_Interp *interp, const char *src, int *intPtr)
}
declare 32 {
    int Tcl_GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    int *boolPtr)
	    int *intPtr)
}
# Only available in Tcl 8.x, NULL in Tcl 9.0
declare 33 {
    unsigned char *Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr, int *lengthPtr)
    unsigned char *Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr, Tcl_Size *numBytesPtr)
}
declare 34 {
    int Tcl_GetDouble(Tcl_Interp *interp, const char *src, double *doublePtr)
}
declare 35 {
    int Tcl_GetDoubleFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    double *doublePtr)
}
# Removed in 9.0, replaced by macro.
#declare 36 {
#    int Tcl_GetIndexFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
#	    const char *const *tablePtr, const char *msg, int flags, int *indexPtr)
#}
declare 37 {
    int Tcl_GetInt(Tcl_Interp *interp, const char *src, int *intPtr)
}
declare 38 {
    int Tcl_GetIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr)
}
declare 39 {
    int Tcl_GetLongFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, long *longPtr)
}
declare 40 {
    const Tcl_ObjType *Tcl_GetObjType(const char *typeName)
}
declare 41 {
    char *Tcl_GetStringFromObj(Tcl_Obj *objPtr, int *lengthPtr)
    char *TclGetStringFromObj(Tcl_Obj *objPtr, void *lengthPtr)
}
declare 42 {
    void Tcl_InvalidateStringRep(Tcl_Obj *objPtr)
}
declare 43 {
    int Tcl_ListObjAppendList(Tcl_Interp *interp, Tcl_Obj *listPtr,
	    Tcl_Obj *elemListPtr)
}
declare 44 {
    int Tcl_ListObjAppendElement(Tcl_Interp *interp, Tcl_Obj *listPtr,
	    Tcl_Obj *objPtr)
}
declare 45 {
    int Tcl_ListObjGetElements(Tcl_Interp *interp, Tcl_Obj *listPtr,
	    int *objcPtr, Tcl_Obj ***objvPtr)
    int TclListObjGetElements(Tcl_Interp *interp, Tcl_Obj *listPtr,
	    void *objcPtr, Tcl_Obj ***objvPtr)
}
declare 46 {
    int Tcl_ListObjIndex(Tcl_Interp *interp, Tcl_Obj *listPtr, int index,
    int Tcl_ListObjIndex(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size index,
	    Tcl_Obj **objPtrPtr)
}
declare 47 {
    int Tcl_ListObjLength(Tcl_Interp *interp, Tcl_Obj *listPtr,
	    int *lengthPtr)
    int TclListObjLength(Tcl_Interp *interp, Tcl_Obj *listPtr,
	    void *lengthPtr)
}
declare 48 {
    int Tcl_ListObjReplace(Tcl_Interp *interp, Tcl_Obj *listPtr, int first,
	    int count, int objc, Tcl_Obj *const objv[])
    int Tcl_ListObjReplace(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size first,
	    Tcl_Size count, Tcl_Size objc, Tcl_Obj *const objv[])
}
# Removed in 9.0 (changed to macro):
#declare 49 {
#    Tcl_Obj *Tcl_NewBooleanObj(int boolValue)
#}
declare 50 {
    Tcl_Obj *Tcl_NewByteArrayObj(const unsigned char *bytes, size_t length)
    Tcl_Obj *Tcl_NewByteArrayObj(const unsigned char *bytes, Tcl_Size numBytes)
}
declare 51 {
    Tcl_Obj *Tcl_NewDoubleObj(double doubleValue)
}
# Removed in 9.0 (changed to macro):
#declare 52 {
#    Tcl_Obj *Tcl_NewIntObj(int intValue)
#}
declare 53 {
    Tcl_Obj *Tcl_NewListObj(int objc, Tcl_Obj *const objv[])
    Tcl_Obj *Tcl_NewListObj(Tcl_Size objc, Tcl_Obj *const objv[])
}
# Removed in 9.0 (changed to macro):
#declare 54 {
#    Tcl_Obj *Tcl_NewLongObj(long longValue)
#}
declare 55 {
    Tcl_Obj *Tcl_NewObj(void)
}
declare 56 {
    Tcl_Obj *Tcl_NewStringObj(const char *bytes, size_t length)
    Tcl_Obj *Tcl_NewStringObj(const char *bytes, Tcl_Size length)
}
# Removed in 9.0 (changed to macro):
#declare 57 {
#    void Tcl_SetBooleanObj(Tcl_Obj *objPtr, int boolValue)
#}
declare 58 {
    unsigned char *Tcl_SetByteArrayLength(Tcl_Obj *objPtr, size_t length)
    unsigned char *Tcl_SetByteArrayLength(Tcl_Obj *objPtr, Tcl_Size numBytes)
}
declare 59 {
    void Tcl_SetByteArrayObj(Tcl_Obj *objPtr, const unsigned char *bytes,
	    size_t length)
	    Tcl_Size numBytes)
}
declare 60 {
    void Tcl_SetDoubleObj(Tcl_Obj *objPtr, double doubleValue)
}
# Removed in 9.0 (changed to macro):
#declare 61 {
#    void Tcl_SetIntObj(Tcl_Obj *objPtr, int intValue)
#}
declare 62 {
    void Tcl_SetListObj(Tcl_Obj *objPtr, int objc, Tcl_Obj *const objv[])
    void Tcl_SetListObj(Tcl_Obj *objPtr, Tcl_Size objc, Tcl_Obj *const objv[])
}
# Removed in 9.0 (changed to macro):
#declare 63 {
#    void Tcl_SetLongObj(Tcl_Obj *objPtr, long longValue)
#}
declare 64 {
    void Tcl_SetObjLength(Tcl_Obj *objPtr, size_t length)
    void Tcl_SetObjLength(Tcl_Obj *objPtr, Tcl_Size length)
}
declare 65 {
    void Tcl_SetStringObj(Tcl_Obj *objPtr, const char *bytes, size_t length)
    void Tcl_SetStringObj(Tcl_Obj *objPtr, const char *bytes, Tcl_Size length)
}
# Removed in 9.0, replaced by macro.
#declare 66 {
#    void Tcl_AddErrorInfo(Tcl_Interp *interp, const char *message)
#}
# Removed in 9.0, replaced by macro.
#declare 67 {
#    void Tcl_AddObjErrorInfo(Tcl_Interp *interp, const char *message,
#	    int length)
#}
declare 68 {
    void Tcl_AllowExceptions(Tcl_Interp *interp)
}
declare 69 {
    void Tcl_AppendElement(Tcl_Interp *interp, const char *element)
}
declare 70 {
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
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







-
-
-
-
-
-
-
-











-
-
-
+
+
+
-
+




-
+


-
+


-
+




-
+




-
+







}
declare 74 {
    void Tcl_AsyncMark(Tcl_AsyncHandler async)
}
declare 75 {
    int Tcl_AsyncReady(void)
}
# Removed in 9.0
#declare 76 {
#    void Tcl_BackgroundError(Tcl_Interp *interp)
#}
# Removed in 9.0:
#declare 77 {
#    char Tcl_Backslash(const char *src, int *readPtr)
#}
declare 78 {
    int Tcl_BadChannelOption(Tcl_Interp *interp, const char *optionName,
	    const char *optionList)
}
declare 79 {
    void Tcl_CallWhenDeleted(Tcl_Interp *interp, Tcl_InterpDeleteProc *proc,
	    void *clientData)
}
declare 80 {
    void Tcl_CancelIdleCall(Tcl_IdleProc *idleProc, void *clientData)
}
# Removed in 9.0:
#declare 81 {
#    int Tcl_Close(Tcl_Interp *interp, Tcl_Channel chan)
# Only available in Tcl 8.x, NULL in Tcl 9.0
declare 81 {
    int Tcl_Close(Tcl_Interp *interp, Tcl_Channel chan)
#}
}
declare 82 {
    int Tcl_CommandComplete(const char *cmd)
}
declare 83 {
    char *Tcl_Concat(int argc, const char *const *argv)
    char *Tcl_Concat(Tcl_Size argc, const char *const *argv)
}
declare 84 {
    size_t Tcl_ConvertElement(const char *src, char *dst, int flags)
    Tcl_Size Tcl_ConvertElement(const char *src, char *dst, int flags)
}
declare 85 {
    size_t Tcl_ConvertCountedElement(const char *src, size_t length, char *dst,
    Tcl_Size Tcl_ConvertCountedElement(const char *src, Tcl_Size length, char *dst,
	    int flags)
}
declare 86 {
    int Tcl_CreateAlias(Tcl_Interp *childInterp, const char *childCmd,
	    Tcl_Interp *target, const char *targetCmd, int argc,
	    Tcl_Interp *target, const char *targetCmd, Tcl_Size argc,
	    const char *const *argv)
}
declare 87 {
    int Tcl_CreateAliasObj(Tcl_Interp *childInterp, const char *childCmd,
	    Tcl_Interp *target, const char *targetCmd, int objc,
	    Tcl_Interp *target, const char *targetCmd, Tcl_Size objc,
	    Tcl_Obj *const objv[])
}
declare 88 {
    Tcl_Channel Tcl_CreateChannel(const Tcl_ChannelType *typePtr,
	    const char *chanName, void *instanceData, int mask)
}
declare 89 {
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
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







-
-
-
-
-
-















-
+







}
declare 93 {
    void Tcl_CreateExitHandler(Tcl_ExitProc *proc, void *clientData)
}
declare 94 {
    Tcl_Interp *Tcl_CreateInterp(void)
}
# Removed in 9.0:
#declare 95 {
#    void Tcl_CreateMathFunc(Tcl_Interp *interp, const char *name,
#	    int numArgs, Tcl_ValueType *argTypes,
#	    Tcl_MathProc *proc, void *clientData)
#}
declare 96 {
    Tcl_Command Tcl_CreateObjCommand(Tcl_Interp *interp,
	    const char *cmdName,
	    Tcl_ObjCmdProc *proc, void *clientData,
	    Tcl_CmdDeleteProc *deleteProc)
}
declare 97 {
    Tcl_Interp *Tcl_CreateChild(Tcl_Interp *interp, const char *name,
	    int isSafe)
}
declare 98 {
    Tcl_TimerToken Tcl_CreateTimerHandler(int milliseconds,
	    Tcl_TimerProc *proc, void *clientData)
}
declare 99 {
    Tcl_Trace Tcl_CreateTrace(Tcl_Interp *interp, int level,
    Tcl_Trace Tcl_CreateTrace(Tcl_Interp *interp, Tcl_Size level,
	    Tcl_CmdTraceProc *proc, void *clientData)
}
declare 100 {
    void Tcl_DeleteAssocData(Tcl_Interp *interp, const char *name)
}
declare 101 {
    void Tcl_DeleteChannelHandler(Tcl_Channel chan, Tcl_ChannelProc *proc,
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
467
468
469
470

471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
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







-
+


















-
+




















-
+













-
-
-
-



-
-
-
-







declare 109 {
    void Tcl_DeleteHashTable(Tcl_HashTable *tablePtr)
}
declare 110 {
    void Tcl_DeleteInterp(Tcl_Interp *interp)
}
declare 111 {
    void Tcl_DetachPids(int numPids, Tcl_Pid *pidPtr)
    void Tcl_DetachPids(Tcl_Size numPids, Tcl_Pid *pidPtr)
}
declare 112 {
    void Tcl_DeleteTimerHandler(Tcl_TimerToken token)
}
declare 113 {
    void Tcl_DeleteTrace(Tcl_Interp *interp, Tcl_Trace trace)
}
declare 114 {
    void Tcl_DontCallWhenDeleted(Tcl_Interp *interp,
	    Tcl_InterpDeleteProc *proc, void *clientData)
}
declare 115 {
    int Tcl_DoOneEvent(int flags)
}
declare 116 {
    void Tcl_DoWhenIdle(Tcl_IdleProc *proc, void *clientData)
}
declare 117 {
    char *Tcl_DStringAppend(Tcl_DString *dsPtr, const char *bytes, size_t length)
    char *Tcl_DStringAppend(Tcl_DString *dsPtr, const char *bytes, Tcl_Size length)
}
declare 118 {
    char *Tcl_DStringAppendElement(Tcl_DString *dsPtr, const char *element)
}
declare 119 {
    void Tcl_DStringEndSublist(Tcl_DString *dsPtr)
}
declare 120 {
    void Tcl_DStringFree(Tcl_DString *dsPtr)
}
declare 121 {
    void Tcl_DStringGetResult(Tcl_Interp *interp, Tcl_DString *dsPtr)
}
declare 122 {
    void Tcl_DStringInit(Tcl_DString *dsPtr)
}
declare 123 {
    void Tcl_DStringResult(Tcl_Interp *interp, Tcl_DString *dsPtr)
}
declare 124 {
    void Tcl_DStringSetLength(Tcl_DString *dsPtr, size_t length)
    void Tcl_DStringSetLength(Tcl_DString *dsPtr, Tcl_Size length)
}
declare 125 {
    void Tcl_DStringStartSublist(Tcl_DString *dsPtr)
}
declare 126 {
    int Tcl_Eof(Tcl_Channel chan)
}
declare 127 {
    const char *Tcl_ErrnoId(void)
}
declare 128 {
    const char *Tcl_ErrnoMsg(int err)
}
# Removed in 9.0, replaced by macro.
#declare 129 {
#    int Tcl_Eval(Tcl_Interp *interp, const char *script)
#}
declare 130 {
    int Tcl_EvalFile(Tcl_Interp *interp, const char *fileName)
}
# Removed in 9.0, replaced by macro.
#declare 131 {
#    int Tcl_EvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr)
#}
declare 132 {
    void Tcl_EventuallyFree(void *clientData, Tcl_FreeProc *freeProc)
}
declare 133 {
    TCL_NORETURN void Tcl_Exit(int status)
}
declare 134 {
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
558
559
560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
459
460
461
462
463
464
465




466
467
468
469
470
471
472









473

474
475

476
477
478
479
480
481
482
483
484
485
486

487
488
489
490
491
492
493
494







-
-
-
-







-
-
-
-
-
-
-
-
-

-
+

-
+










-
+







}
declare 142 {
    int Tcl_ExprString(Tcl_Interp *interp, const char *expr)
}
declare 143 {
    void Tcl_Finalize(void)
}
# Removed in 9.0 (stub entry only)
#declare 144 {
#    void Tcl_FindExecutable(const char *argv0)
#}
declare 145 {
    Tcl_HashEntry *Tcl_FirstHashEntry(Tcl_HashTable *tablePtr,
	    Tcl_HashSearch *searchPtr)
}
declare 146 {
    int Tcl_Flush(Tcl_Channel chan)
}
# Removed in 9.0, TIP 559
#declare 147 {
#    void Tcl_FreeResult(Tcl_Interp *interp)
#}
declare 148 {
    int Tcl_GetAlias(Tcl_Interp *interp, const char *childCmd,
	    Tcl_Interp **targetInterpPtr, const char **targetCmdPtr,
	    int *argcPtr, const char ***argvPtr)
}
declare 149 {
    int Tcl_GetAliasObj(Tcl_Interp *interp, const char *childCmd,
    int TclGetAliasObj(Tcl_Interp *interp, const char *childCmd,
	    Tcl_Interp **targetInterpPtr, const char **targetCmdPtr,
	    int *objcPtr, Tcl_Obj ***objv)
	    int *objcPtr, Tcl_Obj ***objvPtr)
}
declare 150 {
    void *Tcl_GetAssocData(Tcl_Interp *interp, const char *name,
	    Tcl_InterpDeleteProc **procPtr)
}
declare 151 {
    Tcl_Channel Tcl_GetChannel(Tcl_Interp *interp, const char *chanName,
	    int *modePtr)
}
declare 152 {
    int Tcl_GetChannelBufferSize(Tcl_Channel chan)
    Tcl_Size Tcl_GetChannelBufferSize(Tcl_Channel chan)
}
declare 153 {
    int Tcl_GetChannelHandle(Tcl_Channel chan, int direction,
	    void **handlePtr)
}
declare 154 {
    void *Tcl_GetChannelInstanceData(Tcl_Channel chan)
612
613
614
615
616
617
618
619
620
621



622
623
624
625
626
627
628
629

630
631
632

633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
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
558
559
560
561
562









563
564
565
566








567
568
569
570
571
572
573







-
-
-
+
+
+







-
+


-
+










-
-
-
-
-
-
-
-
-




-
-
-
-
-
-
-
-







declare 166 {
    Tcl_Obj *Tcl_GetObjResult(Tcl_Interp *interp)
}

# Tcl_GetOpenFile is only available on unix, but it is a part of the old
# generic interface, so we include it here for compatibility reasons.

declare 167 unix {
    int Tcl_GetOpenFile(Tcl_Interp *interp, const char *chanID, int forWriting,
	    int checkUsage, void **filePtr)
declare 167 {
    int Tcl_GetOpenFile(Tcl_Interp *interp, const char *chanID,
	    int forWriting, int checkUsage, void **filePtr)
}
# Obsolete.  Should now use Tcl_FSGetPathType which is objectified
# and therefore usually faster.
declare 168 {
    Tcl_PathType Tcl_GetPathType(const char *path)
}
declare 169 {
    size_t Tcl_Gets(Tcl_Channel chan, Tcl_DString *dsPtr)
    Tcl_Size Tcl_Gets(Tcl_Channel chan, Tcl_DString *dsPtr)
}
declare 170 {
    size_t Tcl_GetsObj(Tcl_Channel chan, Tcl_Obj *objPtr)
    Tcl_Size Tcl_GetsObj(Tcl_Channel chan, Tcl_Obj *objPtr)
}
declare 171 {
    int Tcl_GetServiceMode(void)
}
declare 172 {
    Tcl_Interp *Tcl_GetChild(Tcl_Interp *interp, const char *name)
}
declare 173 {
    Tcl_Channel Tcl_GetStdChannel(int type)
}
# Removed in 9.0, replaced by macro.
#declare 174 {
#    const char *Tcl_GetStringResult(Tcl_Interp *interp)
#}
# Removed in 9.0, replaced by macro.
#declare 175 {
#    const char *Tcl_GetVar(Tcl_Interp *interp, const char *varName,
#	    int flags)
#}
declare 176 {
    const char *Tcl_GetVar2(Tcl_Interp *interp, const char *part1,
	    const char *part2, int flags)
}
# Removed in 9.0, replaced by macro.
#declare 177 {
#    int Tcl_GlobalEval(Tcl_Interp *interp, const char *command)
#}
# Removed in 9.0, replaced by macro.
#declare 178 {
#    int Tcl_GlobalEvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr)
#}
declare 179 {
    int Tcl_HideCommand(Tcl_Interp *interp, const char *cmdName,
	    const char *hiddenCmdToken)
}
declare 180 {
    int Tcl_Init(Tcl_Interp *interp)
}
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
707
708
709
710
711

712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728

729
730
731
732
733
734
735
736
737
738

739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758

759
760
761

762
763
764
765
766
767
768
584
585
586
587
588
589
590

591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606



607
608
609
610

611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627

628
629
630
631
632
633
634
635
636
637

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

658
659
660

661
662
663
664
665
666
667
668







-
+















-
-
-




-
+
















-
+









-
+



















-
+


-
+







    int Tcl_InterpDeleted(Tcl_Interp *interp)
}
declare 185 {
    int Tcl_IsSafe(Tcl_Interp *interp)
}
# Obsolete, use Tcl_FSJoinPath
declare 186 {
    char *Tcl_JoinPath(int argc, const char *const *argv,
    char *Tcl_JoinPath(Tcl_Size argc, const char *const *argv,
	    Tcl_DString *resultPtr)
}
declare 187 {
    int Tcl_LinkVar(Tcl_Interp *interp, const char *varName, void *addr,
	    int type)
}

# This slot is reserved for use by the plus patch:
#  declare 188 {
#	Tcl_MainLoop
#  }

declare 189 {
    Tcl_Channel Tcl_MakeFileChannel(void *handle, int mode)
}
declare 190 {
    int Tcl_MakeSafe(Tcl_Interp *interp)
}
declare 191 {
    Tcl_Channel Tcl_MakeTcpClientChannel(void *tcpSocket)
}
declare 192 {
    char *Tcl_Merge(int argc, const char *const *argv)
    char *Tcl_Merge(Tcl_Size argc, const char *const *argv)
}
declare 193 {
    Tcl_HashEntry *Tcl_NextHashEntry(Tcl_HashSearch *searchPtr)
}
declare 194 {
    void Tcl_NotifyChannel(Tcl_Channel channel, int mask)
}
declare 195 {
    Tcl_Obj *Tcl_ObjGetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
	    Tcl_Obj *part2Ptr, int flags)
}
declare 196 {
    Tcl_Obj *Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
	    Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags)
}
declare 197 {
    Tcl_Channel Tcl_OpenCommandChannel(Tcl_Interp *interp, int argc,
    Tcl_Channel Tcl_OpenCommandChannel(Tcl_Interp *interp, Tcl_Size argc,
	    const char **argv, int flags)
}
# This is obsolete, use Tcl_FSOpenFileChannel
declare 198 {
    Tcl_Channel Tcl_OpenFileChannel(Tcl_Interp *interp, const char *fileName,
	    const char *modeString, int permissions)
}
declare 199 {
    Tcl_Channel Tcl_OpenTcpClient(Tcl_Interp *interp, int port,
	    const char *address, const char *myaddr, int myport, int async)
	    const char *address, const char *myaddr, int myport, int flags)
}
declare 200 {
    Tcl_Channel Tcl_OpenTcpServer(Tcl_Interp *interp, int port,
	    const char *host, Tcl_TcpAcceptProc *acceptProc,
	    void *callbackData)
}
declare 201 {
    void Tcl_Preserve(void *data)
}
declare 202 {
    void Tcl_PrintDouble(Tcl_Interp *interp, double value, char *dst)
}
declare 203 {
    int Tcl_PutEnv(const char *assignment)
}
declare 204 {
    const char *Tcl_PosixError(Tcl_Interp *interp)
}
declare 205 {
    void Tcl_QueueEvent(Tcl_Event *evPtr, Tcl_QueuePosition position)
    void Tcl_QueueEvent(Tcl_Event *evPtr, int position)
}
declare 206 {
    size_t Tcl_Read(Tcl_Channel chan, char *bufPtr, size_t toRead)
    Tcl_Size Tcl_Read(Tcl_Channel chan, char *bufPtr, Tcl_Size toRead)
}
declare 207 {
    void Tcl_ReapDetachedProcs(void)
}
declare 208 {
    int Tcl_RecordAndEval(Tcl_Interp *interp, const char *cmd, int flags)
}
783
784
785
786
787
788
789
790

791
792
793
794
795
796
797
798
799
800

801
802
803

804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820

821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844

845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916

917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
683
684
685
686
687
688
689

690
691
692
693
694
695
696
697
698
699

700
701
702

703
704




705
706
707
708
709
710
711
712
713
714
715

716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734




735

736
737





738
739
740
741
742
743
744
745
746
747
748
749





750
751
752
753
754
755
756
757
758
759
760
761
762
763

764
765
766
767
768

769
770


















771
772
773
774
775
776
777
778
779

780
781
782
783
784
785
786
787




788
789
790
791





792
793
794
795
796
797
798
799





800
801
802
803
804
805
806





807
808
809
810
811
812

813
814
815

816
817
818
819
820
821
822
823
824








825
826
827
828
829
830
831





832
833
834
835
836



















837
838
839




840
841
842
843
844
845
846







-
+









-
+


-
+

-
-
-
-











-
+


















-
-
-
-

-
+

-
-
-
-
-












-
-
-
-
-














-
+




-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-









-
+







-
-
-
-




-
-
-
-
-








-
-
-
-
-







-
-
-
-
-






-
+


-
+








-
-
-
-
-
-
-
-







-
-
-
-
-





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-



-
-
-
-







	    const char *text, const char *start)
}
declare 214 {
    int Tcl_RegExpMatch(Tcl_Interp *interp, const char *text,
	    const char *pattern)
}
declare 215 {
    void Tcl_RegExpRange(Tcl_RegExp regexp, size_t index,
    void Tcl_RegExpRange(Tcl_RegExp regexp, Tcl_Size index,
	    const char **startPtr, const char **endPtr)
}
declare 216 {
    void Tcl_Release(void *clientData)
}
declare 217 {
    void Tcl_ResetResult(Tcl_Interp *interp)
}
declare 218 {
    size_t Tcl_ScanElement(const char *src, int *flagPtr)
    Tcl_Size Tcl_ScanElement(const char *src, int *flagPtr)
}
declare 219 {
    size_t Tcl_ScanCountedElement(const char *src, size_t length, int *flagPtr)
    Tcl_Size Tcl_ScanCountedElement(const char *src, Tcl_Size length, int *flagPtr)
}
# Removed in 9.0:
#declare 220 {
#    int Tcl_SeekOld(Tcl_Channel chan, int offset, int mode)
#}
declare 221 {
    int Tcl_ServiceAll(void)
}
declare 222 {
    int Tcl_ServiceEvent(int flags)
}
declare 223 {
    void Tcl_SetAssocData(Tcl_Interp *interp, const char *name,
	    Tcl_InterpDeleteProc *proc, void *clientData)
}
declare 224 {
    void Tcl_SetChannelBufferSize(Tcl_Channel chan, int sz)
    void Tcl_SetChannelBufferSize(Tcl_Channel chan, Tcl_Size sz)
}
declare 225 {
    int Tcl_SetChannelOption(Tcl_Interp *interp, Tcl_Channel chan,
	    const char *optionName, const char *newValue)
}
declare 226 {
    int Tcl_SetCommandInfo(Tcl_Interp *interp, const char *cmdName,
	    const Tcl_CmdInfo *infoPtr)
}
declare 227 {
    void Tcl_SetErrno(int err)
}
declare 228 {
    void Tcl_SetErrorCode(Tcl_Interp *interp, ...)
}
declare 229 {
    void Tcl_SetMaxBlockTime(const Tcl_Time *timePtr)
}
# Removed in 9.0 (stub entry only)
#declare 230 {
#    void Tcl_SetPanicProc(TCL_NORETURN1 Tcl_PanicProc *panicProc)
#}
declare 231 {
    int Tcl_SetRecursionLimit(Tcl_Interp *interp, int depth)
    Tcl_Size Tcl_SetRecursionLimit(Tcl_Interp *interp, Tcl_Size depth)
}
# Removed in 9.0, replaced by macro.
#declare 232 {
#    void Tcl_SetResult(Tcl_Interp *interp, char *result,
#	    Tcl_FreeProc *freeProc)
#}
declare 233 {
    int Tcl_SetServiceMode(int mode)
}
declare 234 {
    void Tcl_SetObjErrorCode(Tcl_Interp *interp, Tcl_Obj *errorObjPtr)
}
declare 235 {
    void Tcl_SetObjResult(Tcl_Interp *interp, Tcl_Obj *resultObjPtr)
}
declare 236 {
    void Tcl_SetStdChannel(Tcl_Channel channel, int type)
}
# Removed in 9.0, replaced by macro.
#declare 237 {
#    const char *Tcl_SetVar(Tcl_Interp *interp, const char *varName,
#	    const char *newValue, int flags)
#}
declare 238 {
    const char *Tcl_SetVar2(Tcl_Interp *interp, const char *part1,
	    const char *part2, const char *newValue, int flags)
}
declare 239 {
    const char *Tcl_SignalId(int sig)
}
declare 240 {
    const char *Tcl_SignalMsg(int sig)
}
declare 241 {
    void Tcl_SourceRCFile(Tcl_Interp *interp)
}
declare 242 {
    int Tcl_SplitList(Tcl_Interp *interp, const char *listStr, int *argcPtr,
    int TclSplitList(Tcl_Interp *interp, const char *listStr, void *argcPtr,
	    const char ***argvPtr)
}
# Obsolete, use Tcl_FSSplitPath
declare 243 {
    void Tcl_SplitPath(const char *path, int *argcPtr, const char ***argvPtr)
    void TclSplitPath(const char *path, void *argcPtr, const char ***argvPtr)
}
# Removed in 9.0 (stub entry only)
#declare 244  {
#    void Tcl_StaticPackage(Tcl_Interp *interp, const char *pkgName,
#	    Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc)
#}
# Removed in 9.0 (stub entry only)
#declare 245 {
#    int Tcl_StringMatch(const char *str, const char *pattern)
#}
# Removed in 9.0:
#declare 246 {
#    int Tcl_TellOld(Tcl_Channel chan)
#}
# Removed in 9.0, replaced by macro.
#declare 247 {
#    int Tcl_TraceVar(Tcl_Interp *interp, const char *varName, int flags,
#	    Tcl_VarTraceProc *proc, ClientData clientData)
#}
declare 248 {
    int Tcl_TraceVar2(Tcl_Interp *interp, const char *part1, const char *part2,
	    int flags, Tcl_VarTraceProc *proc, void *clientData)
}
declare 249 {
    char *Tcl_TranslateFileName(Tcl_Interp *interp, const char *name,
	    Tcl_DString *bufferPtr)
}
declare 250 {
    size_t Tcl_Ungets(Tcl_Channel chan, const char *str, size_t len, int atHead)
    Tcl_Size Tcl_Ungets(Tcl_Channel chan, const char *str, Tcl_Size len, int atHead)
}
declare 251 {
    void Tcl_UnlinkVar(Tcl_Interp *interp, const char *varName)
}
declare 252 {
    int Tcl_UnregisterChannel(Tcl_Interp *interp, Tcl_Channel chan)
}
# Removed in 9.0, replaced by macro.
#declare 253 {
#    int Tcl_UnsetVar(Tcl_Interp *interp, const char *varName, int flags)
#}
declare 254 {
    int Tcl_UnsetVar2(Tcl_Interp *interp, const char *part1, const char *part2,
	    int flags)
}
# Removed in 9.0, replaced by macro.
#declare 255 {
#    void Tcl_UntraceVar(Tcl_Interp *interp, const char *varName, int flags,
#	    Tcl_VarTraceProc *proc, ClientData clientData)
#}
declare 256 {
    void Tcl_UntraceVar2(Tcl_Interp *interp, const char *part1,
	    const char *part2, int flags, Tcl_VarTraceProc *proc,
	    void *clientData)
}
declare 257 {
    void Tcl_UpdateLinkedVar(Tcl_Interp *interp, const char *varName)
}
# Removed in 9.0, replaced by macro.
#declare 258 {
#    int Tcl_UpVar(Tcl_Interp *interp, const char *frameName,
#	    const char *varName, const char *localName, int flags)
#}
declare 259 {
    int Tcl_UpVar2(Tcl_Interp *interp, const char *frameName, const char *part1,
	    const char *part2, const char *localName, int flags)
}
declare 260 {
    int Tcl_VarEval(Tcl_Interp *interp, ...)
}
# Removed in 9.0, replaced by macro.
#declare 261 {
#    ClientData Tcl_VarTraceInfo(Tcl_Interp *interp, const char *varName,
#	    int flags, Tcl_VarTraceProc *procPtr, ClientData prevClientData)
#}
declare 262 {
    void *Tcl_VarTraceInfo2(Tcl_Interp *interp, const char *part1,
	    const char *part2, int flags, Tcl_VarTraceProc *procPtr,
	    void *prevClientData)
}
declare 263 {
    size_t Tcl_Write(Tcl_Channel chan, const char *s, size_t slen)
    Tcl_Size Tcl_Write(Tcl_Channel chan, const char *s, Tcl_Size slen)
}
declare 264 {
    void Tcl_WrongNumArgs(Tcl_Interp *interp, int objc,
    void Tcl_WrongNumArgs(Tcl_Interp *interp, Tcl_Size objc,
	    Tcl_Obj *const objv[], const char *message)
}
declare 265 {
    int Tcl_DumpActiveMemory(const char *fileName)
}
declare 266 {
    void Tcl_ValidateAllMemory(const char *file, int line)
}
# Removed in 9.0:
#declare 267 {
#    void Tcl_AppendResultVA(Tcl_Interp *interp, va_list argList)
#}
# Removed in 9.0:
#declare 268 {
#    void Tcl_AppendStringsToObjVA(Tcl_Obj *objPtr, va_list argList)
#}
declare 269 {
    char *Tcl_HashStats(Tcl_HashTable *tablePtr)
}
declare 270 {
    const char *Tcl_ParseVar(Tcl_Interp *interp, const char *start,
	    const char **termPtr)
}
# Removed in 9.0, replaced by macro.
#declare 271 {
#    const char *Tcl_PkgPresent(Tcl_Interp *interp, const char *name,
#	    const char *version, int exact)
#}
declare 272 {
    const char *Tcl_PkgPresentEx(Tcl_Interp *interp,
	    const char *name, const char *version, int exact,
	    void *clientDataPtr)
}
# Removed in 9.0, replaced by macro.
#declare 273 {
#    int Tcl_PkgProvide(Tcl_Interp *interp, const char *name,
#	    const char *version)
#}
# TIP #268: The internally used new Require function is in slot 573.
# Removed in 9.0, replaced by macro.
#declare 274 {
#    const char *Tcl_PkgRequire(Tcl_Interp *interp, const char *name,
#	    const char *version, int exact)
#}
# Removed in 9.0:
#declare 275 {
#    void Tcl_SetErrorCodeVA(Tcl_Interp *interp, va_list argList)
#}
# Removed in 9.0:
#declare 276 {
#    int  Tcl_VarEvalVA(Tcl_Interp *interp, va_list argList)
#}
declare 277 {
    Tcl_Pid Tcl_WaitPid(Tcl_Pid pid, int *statPtr, int options)
}
# Removed in 9.0:
#declare 278 {
#    TCL_NORETURN void Tcl_PanicVA(const char *format, va_list argList)
#}
declare 279 {
    void Tcl_GetVersion(int *major, int *minor, int *patchLevel, int *type)
}
declare 280 {
    void Tcl_InitMemory(Tcl_Interp *interp)
}

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
1116
1117
1118
1119
1120
871
872
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




898

899
900
901
902

903
904
905
906
907
908
909
910
911
912
913


914
915
916
917
918
919

920
921
922
923
924
925
926
927







-
-
-
+
+
+
+
+















-
-
-
-

-
+



-
+










-
-
+
+




-
+







}

# 284 was reserved, but added in 8.4a2
declare 284 {
    void Tcl_SetMainLoop(Tcl_MainLoopProc *proc)
}

# Reserved for future use (8.0.x vs. 8.1)
#  declare 285 {
#  }
declare 285 {
    int Tcl_GetAliasObj(Tcl_Interp *interp, const char *childCmd,
	    Tcl_Interp **targetInterpPtr, const char **targetCmdPtr,
	    Tcl_Size *objcPtr, Tcl_Obj ***objvPtr)
}

# Added in 8.1:

declare 286 {
    void Tcl_AppendObjToObj(Tcl_Obj *objPtr, Tcl_Obj *appendObjPtr)
}
declare 287 {
    Tcl_Encoding Tcl_CreateEncoding(const Tcl_EncodingType *typePtr)
}
declare 288 {
    void Tcl_CreateThreadExitHandler(Tcl_ExitProc *proc, void *clientData)
}
declare 289 {
    void Tcl_DeleteThreadExitHandler(Tcl_ExitProc *proc, void *clientData)
}
# Removed in 9.0, replaced by macro.
#declare 290 {
#    void Tcl_DiscardResult(Tcl_SavedResult *statePtr)
#}
declare 291 {
    int Tcl_EvalEx(Tcl_Interp *interp, const char *script, size_t numBytes,
    int Tcl_EvalEx(Tcl_Interp *interp, const char *script, Tcl_Size numBytes,
	    int flags)
}
declare 292 {
    int Tcl_EvalObjv(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[],
    int Tcl_EvalObjv(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[],
	    int flags)
}
declare 293 {
    int Tcl_EvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags)
}
declare 294 {
    TCL_NORETURN void Tcl_ExitThread(int status)
}
declare 295 {
    int Tcl_ExternalToUtf(Tcl_Interp *interp, Tcl_Encoding encoding,
	    const char *src, size_t srcLen, int flags,
	    Tcl_EncodingState *statePtr, char *dst, size_t dstLen,
	    const char *src, Tcl_Size srcLen, int flags,
	    Tcl_EncodingState *statePtr, char *dst, Tcl_Size dstLen,
	    int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr)
}
declare 296 {
    char *Tcl_ExternalToUtfDString(Tcl_Encoding encoding,
	    const char *src, size_t srcLen, Tcl_DString *dsPtr)
	    const char *src, Tcl_Size srcLen, Tcl_DString *dsPtr)
}
declare 297 {
    void Tcl_FinalizeThread(void)
}
declare 298 {
    void Tcl_FinalizeNotifier(void *clientData)
}
1131
1132
1133
1134
1135
1136
1137
1138
1139


1140
1141
1142

1143
1144
1145
1146
1147
1148
1149
938
939
940
941
942
943
944


945
946
947
948

949
950
951
952
953
954
955
956







-
-
+
+


-
+







    const char *Tcl_GetEncodingName(Tcl_Encoding encoding)
}
declare 303 {
    void Tcl_GetEncodingNames(Tcl_Interp *interp)
}
declare 304 {
    int Tcl_GetIndexFromObjStruct(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    const void *tablePtr, size_t offset, const char *msg, int flags,
	    int *indexPtr)
	    const void *tablePtr, Tcl_Size offset, const char *msg, int flags,
	    void *indexPtr)
}
declare 305 {
    void *Tcl_GetThreadData(Tcl_ThreadDataKey *keyPtr, size_t size)
    void *Tcl_GetThreadData(Tcl_ThreadDataKey *keyPtr, Tcl_Size size)
}
declare 306 {
    Tcl_Obj *Tcl_GetVar2Ex(Tcl_Interp *interp, const char *part1,
	    const char *part2, int flags)
}
declare 307 {
    void *Tcl_InitNotifier(void)
1158
1159
1160
1161
1162
1163
1164
1165

1166
1167
1168
1169


1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191

1192
1193
1194

1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206

1207
1208
1209

1210
1211
1212

1213
1214
1215

1216
1217
1218
1219
1220
1221
1222
1223
1224

1225
1226
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
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
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







-
+


-
-
+
+

-
-
-
-
-
-
-
-












-
+


-
+











-
+


-
+


-
+


-
+








-
+


-
+



-
-
+
+




-
+


-
+


-
+


-
+


-
+


-
+


-
+




-
-
-
-
-
-
-
-







    void Tcl_ConditionNotify(Tcl_Condition *condPtr)
}
declare 311 {
    void Tcl_ConditionWait(Tcl_Condition *condPtr, Tcl_Mutex *mutexPtr,
	    const Tcl_Time *timePtr)
}
declare 312 {
    size_t Tcl_NumUtfChars(const char *src, size_t length)
    Tcl_Size TclNumUtfChars(const char *src, Tcl_Size length)
}
declare 313 {
    size_t Tcl_ReadChars(Tcl_Channel channel, Tcl_Obj *objPtr,
	    size_t charsToRead, int appendFlag)
    Tcl_Size Tcl_ReadChars(Tcl_Channel channel, Tcl_Obj *objPtr,
	    Tcl_Size charsToRead, int appendFlag)
}
# Removed in 9.0, replaced by macro.
#declare 314 {
#    void Tcl_RestoreResult(Tcl_Interp *interp, Tcl_SavedResult *statePtr)
#}
# Removed in 9.0, replaced by macro.
#declare 315 {
#    void Tcl_SaveResult(Tcl_Interp *interp, Tcl_SavedResult *statePtr)
#}
declare 316 {
    int Tcl_SetSystemEncoding(Tcl_Interp *interp, const char *name)
}
declare 317 {
    Tcl_Obj *Tcl_SetVar2Ex(Tcl_Interp *interp, const char *part1,
	    const char *part2, Tcl_Obj *newValuePtr, int flags)
}
declare 318 {
    void Tcl_ThreadAlert(Tcl_ThreadId threadId)
}
declare 319 {
    void Tcl_ThreadQueueEvent(Tcl_ThreadId threadId, Tcl_Event *evPtr,
	    Tcl_QueuePosition position)
	    int position)
}
declare 320 {
    int Tcl_UniCharAtIndex(const char *src, size_t index)
    int Tcl_UniCharAtIndex(const char *src, Tcl_Size index)
}
declare 321 {
    int Tcl_UniCharToLower(int ch)
}
declare 322 {
    int Tcl_UniCharToTitle(int ch)
}
declare 323 {
    int Tcl_UniCharToUpper(int ch)
}
declare 324 {
    int Tcl_UniCharToUtf(int ch, char *buf)
    Tcl_Size Tcl_UniCharToUtf(int ch, char *buf)
}
declare 325 {
    const char *Tcl_UtfAtIndex(const char *src, size_t index)
    const char *TclUtfAtIndex(const char *src, Tcl_Size index)
}
declare 326 {
    int Tcl_UtfCharComplete(const char *src, size_t length)
    int TclUtfCharComplete(const char *src, Tcl_Size length)
}
declare 327 {
    size_t Tcl_UtfBackslash(const char *src, int *readPtr, char *dst)
    Tcl_Size Tcl_UtfBackslash(const char *src, int *readPtr, char *dst)
}
declare 328 {
    const char *Tcl_UtfFindFirst(const char *src, int ch)
}
declare 329 {
    const char *Tcl_UtfFindLast(const char *src, int ch)
}
declare 330 {
    const char *Tcl_UtfNext(const char *src)
    const char *TclUtfNext(const char *src)
}
declare 331 {
    const char *Tcl_UtfPrev(const char *src, const char *start)
    const char *TclUtfPrev(const char *src, const char *start)
}
declare 332 {
    int Tcl_UtfToExternal(Tcl_Interp *interp, Tcl_Encoding encoding,
	    const char *src, size_t srcLen, int flags,
	    Tcl_EncodingState *statePtr, char *dst, size_t dstLen,
	    const char *src, Tcl_Size srcLen, int flags,
	    Tcl_EncodingState *statePtr, char *dst, Tcl_Size dstLen,
	    int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr)
}
declare 333 {
    char *Tcl_UtfToExternalDString(Tcl_Encoding encoding,
	    const char *src, size_t srcLen, Tcl_DString *dsPtr)
	    const char *src, Tcl_Size srcLen, Tcl_DString *dsPtr)
}
declare 334 {
    int Tcl_UtfToLower(char *src)
    Tcl_Size Tcl_UtfToLower(char *src)
}
declare 335 {
    int Tcl_UtfToTitle(char *src)
    Tcl_Size Tcl_UtfToTitle(char *src)
}
declare 336 {
    int Tcl_UtfToChar16(const char *src, unsigned short *chPtr)
    Tcl_Size Tcl_UtfToChar16(const char *src, unsigned short *chPtr)
}
declare 337 {
    int Tcl_UtfToUpper(char *src)
    Tcl_Size Tcl_UtfToUpper(char *src)
}
declare 338 {
    size_t Tcl_WriteChars(Tcl_Channel chan, const char *src, size_t srcLen)
    Tcl_Size Tcl_WriteChars(Tcl_Channel chan, const char *src, Tcl_Size srcLen)
}
declare 339 {
    size_t Tcl_WriteObj(Tcl_Channel chan, Tcl_Obj *objPtr)
    Tcl_Size Tcl_WriteObj(Tcl_Channel chan, Tcl_Obj *objPtr)
}
declare 340 {
    char *Tcl_GetString(Tcl_Obj *objPtr)
}
# Removed in 9.0:
#declare 341 {
#    const char *Tcl_GetDefaultEncodingDir(void)
#}
# Removed in 9.0:
#declare 342 {
#    void Tcl_SetDefaultEncodingDir(const char *path)
#}
declare 343 {
    void Tcl_AlertNotifier(void *clientData)
}
declare 344 {
    void Tcl_ServiceModeHook(int mode)
}
declare 345 {
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
1354
1355
1356
1357
1358
1359
1360
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
1387

1388
1389
1390
1391
1392
1393

1394
1395
1396
1397

1398
1399
1400

1401
1402
1403

1404
1405
1406
1407
1408
1409
1410

1411
1412
1413
1414
1415



1416

1417
1418
1419
1420
1421
1422

1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435

1436
1437
1438
1439
1440
1441
1442
1443
1444
1445

1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
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
1116
1117


1118
1119
1120
1121
1122

1123
1124
1125
1126
1127

1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144

1145
1146
1147

1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166

1167
1168
1169
1170
1171
1172

1173
1174
1175
1176

1177
1178
1179

1180
1181
1182

1183
1184




1185

1186
1187




1188
1189
1190

1191
1192
1193
1194
1195
1196

1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209

1210
1211
1212
1213
1214
1215
1216
1217
1218
1219

1220
1221
1222
1223
1224

1225
1226
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







-
-
-
+
+
-
-
-
-
-
-
+


-
+



-
+





-
-
-
-
-





-
+



-
+




-
+


-
-
+
+



-
+




-
+
















-
+


-
+


















-
+





-
+



-
+


-
+


-
+

-
-
-
-

-
+

-
-
-
-
+
+
+
-
+





-
+












-
+









-
+




-
+


-
+


















-
-
-
-
-












-
-
-
-
-







}
declare 350 {
    int Tcl_UniCharIsUpper(int ch)
}
declare 351 {
    int Tcl_UniCharIsWordChar(int ch)
}
# Removed in 9.0:
#declare 352 {
#    size_t Tcl_UniCharLen(const Tcl_UniChar *uniStr)
declare 352 {
    Tcl_Size Tcl_Char16Len(const unsigned short *uniStr)
#}
# Removed in 9.0:
#declare 353 {
#    int Tcl_UniCharNcmp(const Tcl_UniChar *ucs, const Tcl_UniChar *uct,
#	    size_t numChars)
#}
}
declare 354 {
    char *Tcl_Char16ToUtfDString(const unsigned short *uniStr,
	    size_t uniLength, Tcl_DString *dsPtr)
	    Tcl_Size uniLength, Tcl_DString *dsPtr)
}
declare 355 {
    unsigned short *Tcl_UtfToChar16DString(const char *src,
	    size_t length, Tcl_DString *dsPtr)
	    Tcl_Size length, Tcl_DString *dsPtr)
}
declare 356 {
    Tcl_RegExp Tcl_GetRegExpFromObj(Tcl_Interp *interp, Tcl_Obj *patObj,
	    int flags)
}
# Removed in 9.0:
#declare 357 {
#    Tcl_Obj *Tcl_EvalTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr,
#	    int count)
#}
declare 358 {
    void Tcl_FreeParse(Tcl_Parse *parsePtr)
}
declare 359 {
    void Tcl_LogCommandInfo(Tcl_Interp *interp, const char *script,
	    const char *command, size_t length)
	    const char *command, Tcl_Size length)
}
declare 360 {
    int Tcl_ParseBraces(Tcl_Interp *interp, const char *start,
	    size_t numBytes, Tcl_Parse *parsePtr, int append,
	    Tcl_Size numBytes, Tcl_Parse *parsePtr, int append,
	    const char **termPtr)
}
declare 361 {
    int Tcl_ParseCommand(Tcl_Interp *interp, const char *start,
	    size_t numBytes, int nested, Tcl_Parse *parsePtr)
	    Tcl_Size numBytes, int nested, Tcl_Parse *parsePtr)
}
declare 362 {
    int Tcl_ParseExpr(Tcl_Interp *interp, const char *start, size_t numBytes,
	    Tcl_Parse *parsePtr)
    int Tcl_ParseExpr(Tcl_Interp *interp, const char *start,
	    Tcl_Size numBytes, Tcl_Parse *parsePtr)
}
declare 363 {
    int Tcl_ParseQuotedString(Tcl_Interp *interp, const char *start,
	    size_t numBytes, Tcl_Parse *parsePtr, int append,
	    Tcl_Size numBytes, Tcl_Parse *parsePtr, int append,
	    const char **termPtr)
}
declare 364 {
    int Tcl_ParseVarName(Tcl_Interp *interp, const char *start,
	    size_t numBytes, Tcl_Parse *parsePtr, int append)
	    Tcl_Size numBytes, Tcl_Parse *parsePtr, int append)
}
# These 4 functions are obsolete, use Tcl_FSGetCwd, Tcl_FSChdir,
# Tcl_FSAccess and Tcl_FSStat
declare 365 {
    char *Tcl_GetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr)
}
declare 366 {
   int Tcl_Chdir(const char *dirName)
}
declare 367 {
   int Tcl_Access(const char *path, int mode)
}
declare 368 {
    int Tcl_Stat(const char *path, struct stat *bufPtr)
}
declare 369 {
    int Tcl_UtfNcmp(const char *s1, const char *s2, size_t n)
    int TclUtfNcmp(const char *s1, const char *s2, size_t n)
}
declare 370 {
    int Tcl_UtfNcasecmp(const char *s1, const char *s2, size_t n)
    int TclUtfNcasecmp(const char *s1, const char *s2, size_t n)
}
declare 371 {
    int Tcl_StringCaseMatch(const char *str, const char *pattern, int nocase)
}
declare 372 {
    int Tcl_UniCharIsControl(int ch)
}
declare 373 {
    int Tcl_UniCharIsGraph(int ch)
}
declare 374 {
    int Tcl_UniCharIsPrint(int ch)
}
declare 375 {
    int Tcl_UniCharIsPunct(int ch)
}
declare 376 {
    int Tcl_RegExpExecObj(Tcl_Interp *interp, Tcl_RegExp regexp,
	    Tcl_Obj *textObj, size_t offset, size_t nmatches, int flags)
	    Tcl_Obj *textObj, Tcl_Size offset, Tcl_Size nmatches, int flags)
}
declare 377 {
    void Tcl_RegExpGetInfo(Tcl_RegExp regexp, Tcl_RegExpInfo *infoPtr)
}
declare 378 {
    Tcl_Obj *Tcl_NewUnicodeObj(const Tcl_UniChar *unicode, size_t numChars)
    Tcl_Obj *Tcl_NewUnicodeObj(const Tcl_UniChar *unicode, Tcl_Size numChars)
}
declare 379 {
    void Tcl_SetUnicodeObj(Tcl_Obj *objPtr, const Tcl_UniChar *unicode,
	    size_t numChars)
	    Tcl_Size numChars)
}
declare 380 {
    size_t Tcl_GetCharLength(Tcl_Obj *objPtr)
    Tcl_Size TclGetCharLength(Tcl_Obj *objPtr)
}
declare 381 {
    int Tcl_GetUniChar(Tcl_Obj *objPtr, size_t index)
    int TclGetUniChar(Tcl_Obj *objPtr, Tcl_Size index)
}
# Removed in 9.0, replaced by macro.
#declare 382 {
#    Tcl_UniChar *Tcl_GetUnicode(Tcl_Obj *objPtr)
#}
declare 383 {
    Tcl_Obj *Tcl_GetRange(Tcl_Obj *objPtr, size_t first, size_t last)
    Tcl_Obj *TclGetRange(Tcl_Obj *objPtr, Tcl_Size first, Tcl_Size last)
}
# Removed in 9.0
#declare 384 {
#    void Tcl_AppendUnicodeToObj(Tcl_Obj *objPtr, const Tcl_UniChar *unicode,
#	    size_t length)
declare 384 {
    void Tcl_AppendUnicodeToObj(Tcl_Obj *objPtr, const Tcl_UniChar *unicode,
	    Tcl_Size length)
#}
}
declare 385 {
    int Tcl_RegExpMatchObj(Tcl_Interp *interp, Tcl_Obj *textObj,
	    Tcl_Obj *patternObj)
}
declare 386 {
    void Tcl_SetNotifier(Tcl_NotifierProcs *notifierProcPtr)
    void Tcl_SetNotifier(const Tcl_NotifierProcs *notifierProcPtr)
}
declare 387 {
    Tcl_Mutex *Tcl_GetAllocMutex(void)
}
declare 388 {
    int Tcl_GetChannelNames(Tcl_Interp *interp)
}
declare 389 {
    int Tcl_GetChannelNamesEx(Tcl_Interp *interp, const char *pattern)
}
declare 390 {
    int Tcl_ProcObjCmd(void *clientData, Tcl_Interp *interp,
	    int objc, Tcl_Obj *const objv[])
	    Tcl_Size objc, Tcl_Obj *const objv[])
}
declare 391 {
    void Tcl_ConditionFinalize(Tcl_Condition *condPtr)
}
declare 392 {
    void Tcl_MutexFinalize(Tcl_Mutex *mutex)
}
declare 393 {
    int Tcl_CreateThread(Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc,
	    void *clientData, size_t stackSize, int flags)
	    void *clientData, TCL_HASH_TYPE stackSize, int flags)
}

# Introduced in 8.3.2
declare 394 {
    size_t Tcl_ReadRaw(Tcl_Channel chan, char *dst, size_t bytesToRead)
    Tcl_Size Tcl_ReadRaw(Tcl_Channel chan, char *dst, Tcl_Size bytesToRead)
}
declare 395 {
    size_t Tcl_WriteRaw(Tcl_Channel chan, const char *src, size_t srcLen)
    Tcl_Size Tcl_WriteRaw(Tcl_Channel chan, const char *src, Tcl_Size srcLen)
}
declare 396 {
    Tcl_Channel Tcl_GetTopChannel(Tcl_Channel chan)
}
declare 397 {
    int Tcl_ChannelBuffered(Tcl_Channel chan)
}
declare 398 {
    const char *Tcl_ChannelName(const Tcl_ChannelType *chanTypePtr)
}
declare 399 {
    Tcl_ChannelTypeVersion Tcl_ChannelVersion(
	    const Tcl_ChannelType *chanTypePtr)
}
declare 400 {
    Tcl_DriverBlockModeProc *Tcl_ChannelBlockModeProc(
	    const Tcl_ChannelType *chanTypePtr)
}
# Removed in 9.0
#declare 401 {
#    Tcl_DriverCloseProc *Tcl_ChannelCloseProc(
#	    const Tcl_ChannelType *chanTypePtr)
#}
declare 402 {
    Tcl_DriverClose2Proc *Tcl_ChannelClose2Proc(
	    const Tcl_ChannelType *chanTypePtr)
}
declare 403 {
    Tcl_DriverInputProc *Tcl_ChannelInputProc(
	    const Tcl_ChannelType *chanTypePtr)
}
declare 404 {
    Tcl_DriverOutputProc *Tcl_ChannelOutputProc(
	    const Tcl_ChannelType *chanTypePtr)
}
# Removed in 9.0
#declare 405 {
#    Tcl_DriverSeekProc *Tcl_ChannelSeekProc(
#	    const Tcl_ChannelType *chanTypePtr)
#}
declare 406 {
    Tcl_DriverSetOptionProc *Tcl_ChannelSetOptionProc(
	    const Tcl_ChannelType *chanTypePtr)
}
declare 407 {
    Tcl_DriverGetOptionProc *Tcl_ChannelGetOptionProc(
	    const Tcl_ChannelType *chanTypePtr)
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1299
1300
1301
1302
1303
1304
1305



















1306
1307
1308
1309
1310
1311
1312







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







}
declare 417 {
    void Tcl_ClearChannelHandlers(Tcl_Channel channel)
}
declare 418 {
    int Tcl_IsChannelExisting(const char *channelName)
}
# Removed in 9.0:
#declare 419 {
#    int Tcl_UniCharNcasecmp(const Tcl_UniChar *ucs, const Tcl_UniChar *uct,
#	    size_t numChars)
#}
# Removed in 9.0:
#declare 420 {
#    int Tcl_UniCharCaseMatch(const Tcl_UniChar *uniStr,
#	    const Tcl_UniChar *uniPattern, int nocase)
#}
# Removed in 9.0, as it is actually a macro:
#declare 421 {
#    Tcl_HashEntry *Tcl_FindHashEntry(Tcl_HashTable *tablePtr, const void *key)
#}
# Removed in 9.0, as it is actually a macro:
#declare 422 {
#    Tcl_HashEntry *Tcl_CreateHashEntry(Tcl_HashTable *tablePtr,
#	    const void *key, int *newPtr)
#}
declare 423 {
    void Tcl_InitCustomHashTable(Tcl_HashTable *tablePtr, int keyType,
	    const Tcl_HashKeyType *typePtr)
}
declare 424 {
    void Tcl_InitObjHashTable(Tcl_HashTable *tablePtr)
}
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
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
1354
1355
1356
1357
1358







-
+


-
+


-
+


-
+



-
+









-
+

-
-
-
-
-
-
-
-
-
-
-
-







	    Tcl_CommandTraceProc *proc, void *clientData)
}
declare 427 {
    void Tcl_UntraceCommand(Tcl_Interp *interp, const char *varName,
	    int flags, Tcl_CommandTraceProc *proc, void *clientData)
}
declare 428 {
    void *Tcl_AttemptAlloc(size_t size)
    void *Tcl_AttemptAlloc(TCL_HASH_TYPE size)
}
declare 429 {
    void *Tcl_AttemptDbCkalloc(size_t size, const char *file, int line)
    void *Tcl_AttemptDbCkalloc(TCL_HASH_TYPE size, const char *file, int line)
}
declare 430 {
    void *Tcl_AttemptRealloc(void *ptr, size_t size)
    void *Tcl_AttemptRealloc(void *ptr, TCL_HASH_TYPE size)
}
declare 431 {
    void *Tcl_AttemptDbCkrealloc(void *ptr, size_t size,
    void *Tcl_AttemptDbCkrealloc(void *ptr, TCL_HASH_TYPE size,
	    const char *file, int line)
}
declare 432 {
    int Tcl_AttemptSetObjLength(Tcl_Obj *objPtr, size_t length)
    int Tcl_AttemptSetObjLength(Tcl_Obj *objPtr, Tcl_Size length)
}

# TIP#10 (thread-aware channels) akupries
declare 433 {
    Tcl_ThreadId Tcl_GetChannelThread(Tcl_Channel channel)
}

# introduced in 8.4a3
declare 434 {
    Tcl_UniChar *Tcl_GetUnicodeFromObj(Tcl_Obj *objPtr, int *lengthPtr)
    Tcl_UniChar *TclGetUnicodeFromObj(Tcl_Obj *objPtr, void *lengthPtr)
}

# TIP#15 (math function introspection) dkf
# Removed in 9.0:
#declare 435 {
#    int Tcl_GetMathFuncInfo(Tcl_Interp *interp, const char *name,
#	    int *numArgsPtr, Tcl_ValueType **argTypesPtr,
#	    Tcl_MathProc **procPtr, void **clientDataPtr)
#}
# Removed in 9.0:
#declare 436 {
#    Tcl_Obj *Tcl_ListMathFuncs(Tcl_Interp *interp, const char *pattern)
#}

# TIP#36 (better access to 'subst') dkf
declare 437 {
    Tcl_Obj *Tcl_SubstObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags)
}

# TIP#17 (virtual filesystem layer) vdarley
1639
1640
1641
1642
1643
1644
1645
1646
1647


1648
1649
1650
1651
1652
1653
1654
1373
1374
1375
1376
1377
1378
1379


1380
1381
1382
1383
1384
1385
1386
1387
1388







-
-
+
+







    int	Tcl_FSCreateDirectory(Tcl_Obj *pathPtr)
}
declare 443 {
    int	Tcl_FSDeleteFile(Tcl_Obj *pathPtr)
}
declare 444 {
    int	Tcl_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *sym1,
	    const char *sym2, Tcl_PackageInitProc **proc1Ptr,
	    Tcl_PackageInitProc **proc2Ptr, Tcl_LoadHandle *handlePtr,
	    const char *sym2, Tcl_LibraryInitProc **proc1Ptr,
	    Tcl_LibraryInitProc **proc2Ptr, Tcl_LoadHandle *handlePtr,
	    Tcl_FSUnloadFileProc **unloadProcPtr)
}
declare 445 {
    int	Tcl_FSMatchInDirectory(Tcl_Interp *interp, Tcl_Obj *result,
	    Tcl_Obj *pathPtr, const char *pattern, Tcl_GlobTypeData *types)
}
declare 446 {
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
1429
1430
1431
1432
1433
1434
1435

1436
1437
1438

1439
1440
1441
1442
1443
1444
1445
1446
1447

1448
1449
1450
1451
1452
1453
1454
1455







-
+


-
+








-
+







declare 458 {
    int Tcl_FSChdir(Tcl_Obj *pathPtr)
}
declare 459 {
    int Tcl_FSConvertToPathType(Tcl_Interp *interp, Tcl_Obj *pathPtr)
}
declare 460 {
    Tcl_Obj *Tcl_FSJoinPath(Tcl_Obj *listObj, int elements)
    Tcl_Obj *Tcl_FSJoinPath(Tcl_Obj *listObj, Tcl_Size elements)
}
declare 461 {
    Tcl_Obj *Tcl_FSSplitPath(Tcl_Obj *pathPtr, int *lenPtr)
    Tcl_Obj *TclFSSplitPath(Tcl_Obj *pathPtr, void *lenPtr)
}
declare 462 {
    int Tcl_FSEqualPaths(Tcl_Obj *firstPtr, Tcl_Obj *secondPtr)
}
declare 463 {
    Tcl_Obj *Tcl_FSGetNormalizedPath(Tcl_Interp *interp, Tcl_Obj *pathPtr)
}
declare 464 {
    Tcl_Obj *Tcl_FSJoinToPath(Tcl_Obj *pathPtr, int objc,
    Tcl_Obj *Tcl_FSJoinToPath(Tcl_Obj *pathPtr, Tcl_Size objc,
	    Tcl_Obj *const objv[])
}
declare 465 {
    void *Tcl_FSGetInternalRep(Tcl_Obj *pathPtr,
	    const Tcl_Filesystem *fsPtr)
}
declare 466 {
1767
1768
1769
1770
1771
1772
1773
1774

1775
1776
1777
1778
1779
1780
1781
1782
1783
1784

1785
1786
1787
1788
1789
1790
1791
1501
1502
1503
1504
1505
1506
1507

1508
1509
1510
1511
1512
1513
1514
1515
1516
1517

1518
1519
1520
1521
1522
1523
1524
1525







-
+









-
+







declare 480 {
    void Tcl_FSMountsChanged(const Tcl_Filesystem *fsPtr)
}

# TIP#56 (evaluate a parsed script) msofer
declare 481 {
    int Tcl_EvalTokensStandard(Tcl_Interp *interp, Tcl_Token *tokenPtr,
	    size_t count)
	    Tcl_Size count)
}

# TIP#73 (access to current time) kbk
declare 482 {
    void Tcl_GetTime(Tcl_Time *timeBuf)
}

# TIP#32 (object-enabled traces) kbk
declare 483 {
    Tcl_Trace Tcl_CreateObjTrace(Tcl_Interp *interp, int level, int flags,
    Tcl_Trace Tcl_CreateObjTrace(Tcl_Interp *interp, Tcl_Size level, int flags,
	    Tcl_CmdObjTraceProc *objProc, void *clientData,
	    Tcl_CmdObjTraceDeleteProc *delProc)
}
declare 484 {
    int Tcl_GetCommandInfoFromToken(Tcl_Command token, Tcl_CmdInfo *infoPtr)
}
declare 485 {
1809
1810
1811
1812
1813
1814
1815
1816

1817
1818
1819

1820
1821
1822
1823
1824
1825
1826
1543
1544
1545
1546
1547
1548
1549

1550
1551
1552

1553
1554
1555
1556
1557
1558
1559
1560







-
+


-
+







declare 489 {
    void Tcl_SetWideIntObj(Tcl_Obj *objPtr, Tcl_WideInt wideValue)
}
declare 490 {
    Tcl_StatBuf *Tcl_AllocStatBuf(void)
}
declare 491 {
    Tcl_WideInt Tcl_Seek(Tcl_Channel chan, Tcl_WideInt offset, int mode)
    long long Tcl_Seek(Tcl_Channel chan, long long offset, int mode)
}
declare 492 {
    Tcl_WideInt Tcl_Tell(Tcl_Channel chan)
    long long Tcl_Tell(Tcl_Channel chan)
}

# TIP#91 (back-compat enhancements for channels) dkf
declare 493 {
    Tcl_DriverWideSeekProc *Tcl_ChannelWideSeekProc(
	    const Tcl_ChannelType *chanTypePtr)
}
1837
1838
1839
1840
1841
1842
1843
1844

1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860

1861
1862
1863
1864

1865
1866
1867
1868
1869
1870
1871
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







-
+















-
+



-
+







	    Tcl_Obj **valuePtrPtr)
}
declare 496 {
    int Tcl_DictObjRemove(Tcl_Interp *interp, Tcl_Obj *dictPtr,
	    Tcl_Obj *keyPtr)
}
declare 497 {
    int Tcl_DictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr, int *sizePtr)
    int TclDictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr, void *sizePtr)
}
declare 498 {
    int Tcl_DictObjFirst(Tcl_Interp *interp, Tcl_Obj *dictPtr,
	    Tcl_DictSearch *searchPtr,
	    Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr)
}
declare 499 {
    void Tcl_DictObjNext(Tcl_DictSearch *searchPtr,
	    Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr)
}
declare 500 {
    void Tcl_DictObjDone(Tcl_DictSearch *searchPtr)
}
declare 501 {
    int Tcl_DictObjPutKeyList(Tcl_Interp *interp, Tcl_Obj *dictPtr,
	    int keyc, Tcl_Obj *const *keyv, Tcl_Obj *valuePtr)
	    Tcl_Size keyc, Tcl_Obj *const *keyv, Tcl_Obj *valuePtr)
}
declare 502 {
    int Tcl_DictObjRemoveKeyList(Tcl_Interp *interp, Tcl_Obj *dictPtr,
	    int keyc, Tcl_Obj *const *keyv)
	    Tcl_Size keyc, Tcl_Obj *const *keyv)
}
declare 503 {
    Tcl_Obj *Tcl_NewDictObj(void)
}
declare 504 {
    Tcl_Obj *Tcl_DbNewDictObj(const char *file, int line)
}
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

1958
1959
1960
1961
1962
1963
1964
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







-
-
-
-
-




















-
+








# TIP#137 (encoding-aware source command) dgp for Anton Kovalenko
declare 518 {
    int Tcl_FSEvalFileEx(Tcl_Interp *interp, Tcl_Obj *fileName,
	    const char *encodingName)
}

# Removed in 9.0 (stub entry only)
#declare 519 {nostub {Don't use this function in a stub-enabled extension}} {
#    Tcl_ExitProc *Tcl_SetExitProc(TCL_NORETURN1 Tcl_ExitProc *proc)
#}

# TIP#143 (resource limits) dkf
declare 520 {
    void Tcl_LimitAddHandler(Tcl_Interp *interp, int type,
	    Tcl_LimitHandlerProc *handlerProc, void *clientData,
	    Tcl_LimitHandlerDeleteProc *deleteProc)
}
declare 521 {
    void Tcl_LimitRemoveHandler(Tcl_Interp *interp, int type,
	    Tcl_LimitHandlerProc *handlerProc, void *clientData)
}
declare 522 {
    int Tcl_LimitReady(Tcl_Interp *interp)
}
declare 523 {
    int Tcl_LimitCheck(Tcl_Interp *interp)
}
declare 524 {
    int Tcl_LimitExceeded(Tcl_Interp *interp)
}
declare 525 {
    void Tcl_LimitSetCommands(Tcl_Interp *interp, int commandLimit)
    void Tcl_LimitSetCommands(Tcl_Interp *interp, Tcl_Size commandLimit)
}
declare 526 {
    void Tcl_LimitSetTime(Tcl_Interp *interp, Tcl_Time *timeLimitPtr)
}
declare 527 {
    void Tcl_LimitSetGranularity(Tcl_Interp *interp, int type, int granularity)
}
2084
2085
2086
2087
2088
2089
2090
2091

2092
2093
2094
2095
2096
2097
2098
1813
1814
1815
1816
1817
1818
1819

1820
1821
1822
1823
1824
1825
1826
1827







-
+







}
declare 559 {
    int Tcl_TakeBignumFromObj(Tcl_Interp *interp, Tcl_Obj *obj, void *value)
}

# TIP #208 ('chan' command) jeffh
declare 560 {
    int Tcl_TruncateChannel(Tcl_Channel chan, Tcl_WideInt length)
    int Tcl_TruncateChannel(Tcl_Channel chan, long long length)
}
declare 561 {
    Tcl_DriverTruncateProc *Tcl_ChannelTruncateProc(
	    const Tcl_ChannelType *chanTypePtr)
}

# TIP#219 (channel reflection api) akupries
2139
2140
2141
2142
2143
2144
2145
2146

2147
2148
2149
2150
2151
2152
2153
2154
2155

2156
2157
2158

2159
2160
2161
2162
2163

2164
2165
2166
2167
2168
2169
2170
1868
1869
1870
1871
1872
1873
1874

1875
1876
1877
1878
1879
1880
1881
1882
1883

1884
1885
1886

1887
1888
1889
1890
1891

1892
1893
1894
1895
1896
1897
1898
1899







-
+








-
+


-
+




-
+







declare 572 {
    const char *Tcl_GetEncodingNameFromEnvironment(Tcl_DString *bufPtr)
}

# TIP#268 (extended version numbers and requirements) akupries
declare 573 {
    int Tcl_PkgRequireProc(Tcl_Interp *interp, const char *name,
	    int objc, Tcl_Obj *const objv[], void *clientDataPtr)
	    Tcl_Size objc, Tcl_Obj *const objv[], void *clientDataPtr)
}

# TIP#270 (utility C routines for string formatting) dgp
declare 574 {
    void Tcl_AppendObjToErrorInfo(Tcl_Interp *interp, Tcl_Obj *objPtr)
}
declare 575 {
    void Tcl_AppendLimitedToObj(Tcl_Obj *objPtr, const char *bytes,
	    size_t length, size_t limit, const char *ellipsis)
	    Tcl_Size length, Tcl_Size limit, const char *ellipsis)
}
declare 576 {
    Tcl_Obj *Tcl_Format(Tcl_Interp *interp, const char *format, int objc,
    Tcl_Obj *Tcl_Format(Tcl_Interp *interp, const char *format, Tcl_Size objc,
	    Tcl_Obj *const objv[])
}
declare 577 {
    int Tcl_AppendFormatToObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    const char *format, int objc, Tcl_Obj *const objv[])
	    const char *format, Tcl_Size objc, Tcl_Obj *const objv[])
}
declare 578 {
    Tcl_Obj *Tcl_ObjPrintf(const char *format, ...)
}
declare 579 {
    void Tcl_AppendPrintfToObj(Tcl_Obj *objPtr, const char *format, ...)
}
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
2222
2223
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







-
+



-
+











-
+







	    Tcl_ObjCmdProc *nreProc, void *clientData,
	    Tcl_CmdDeleteProc *deleteProc)
}
declare 584 {
    int Tcl_NREvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags)
}
declare 585 {
    int Tcl_NREvalObjv(Tcl_Interp *interp, int objc,
    int Tcl_NREvalObjv(Tcl_Interp *interp, Tcl_Size objc,
	    Tcl_Obj *const objv[], int flags)
}
declare 586 {
    int Tcl_NRCmdSwap(Tcl_Interp *interp, Tcl_Command cmd, int objc,
    int Tcl_NRCmdSwap(Tcl_Interp *interp, Tcl_Command cmd, Tcl_Size objc,
	    Tcl_Obj *const objv[], int flags)
}
declare 587 {
    void Tcl_NRAddCallback(Tcl_Interp *interp, Tcl_NRPostProc *postProcPtr,
	    void *data0, void *data1, void *data2,
	    void *data3)
}
# For use by NR extenders, to have a simple way to also provide a (required!)
# classic objProc
declare 588 {
    int Tcl_NRCallObjProc(Tcl_Interp *interp, Tcl_ObjCmdProc *objProc,
	    void *clientData, int objc, Tcl_Obj *const objv[])
	    void *clientData, Tcl_Size objc, Tcl_Obj *const objv[])
}

# TIP#316 (Tcl_StatBuf reader functions) dkf
declare 589 {
    unsigned Tcl_GetFSDeviceFromStat(const Tcl_StatBuf *statPtr)
}
declare 590 {
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
2273


2274
2275
2276
2277
2278
2279
2280
1964
1965
1966
1967
1968
1969
1970

1971
1972
1973

1974
1975
1976

1977
1978
1979

1980
1981
1982

1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000


2001
2002
2003
2004
2005
2006
2007
2008
2009







-
+


-
+


-
+


-
+


-
+

















-
-
+
+







declare 594 {
    int Tcl_GetGroupIdFromStat(const Tcl_StatBuf *statPtr)
}
declare 595 {
    int Tcl_GetDeviceTypeFromStat(const Tcl_StatBuf *statPtr)
}
declare 596 {
    Tcl_WideInt Tcl_GetAccessTimeFromStat(const Tcl_StatBuf *statPtr)
    long long Tcl_GetAccessTimeFromStat(const Tcl_StatBuf *statPtr)
}
declare 597 {
    Tcl_WideInt Tcl_GetModificationTimeFromStat(const Tcl_StatBuf *statPtr)
    long long Tcl_GetModificationTimeFromStat(const Tcl_StatBuf *statPtr)
}
declare 598 {
    Tcl_WideInt Tcl_GetChangeTimeFromStat(const Tcl_StatBuf *statPtr)
    long long Tcl_GetChangeTimeFromStat(const Tcl_StatBuf *statPtr)
}
declare 599 {
    Tcl_WideUInt Tcl_GetSizeFromStat(const Tcl_StatBuf *statPtr)
    unsigned long long Tcl_GetSizeFromStat(const Tcl_StatBuf *statPtr)
}
declare 600 {
    Tcl_WideUInt Tcl_GetBlocksFromStat(const Tcl_StatBuf *statPtr)
    unsigned long long Tcl_GetBlocksFromStat(const Tcl_StatBuf *statPtr)
}
declare 601 {
    unsigned Tcl_GetBlockSizeFromStat(const Tcl_StatBuf *statPtr)
}

# TIP#314 (ensembles with parameters) dkf for Lars Hellstr"om
declare 602 {
    int Tcl_SetEnsembleParameterList(Tcl_Interp *interp, Tcl_Command token,
	    Tcl_Obj *paramList)
}
declare 603 {
    int Tcl_GetEnsembleParameterList(Tcl_Interp *interp, Tcl_Command token,
	    Tcl_Obj **paramListPtr)
}

# TIP#265 (option parser) dkf for Sam Bromley
declare 604 {
    int Tcl_ParseArgsObjv(Tcl_Interp *interp, const Tcl_ArgvInfo *argTable,
	    int *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv)
    int TclParseArgsObjv(Tcl_Interp *interp, const Tcl_ArgvInfo *argTable,
	    void *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv)
}

# TIP#336 (manipulate the error line) dgp
declare 605 {
    int Tcl_GetErrorLine(Tcl_Interp *interp)
}
declare 606 {
2300
2301
2302
2303
2304
2305
2306
2307

2308
2309
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
2029
2030
2031
2032
2033
2034
2035

2036
2037
2038
2039

2040
2041
2042
2043

2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063

2064
2065
2066
2067
2068
2069
2070
2071







-
+



-
+



-
+



















-
+







# TIP#234 (zlib interface) dkf/Pascal Scheffers
declare 610 {
    int Tcl_ZlibDeflate(Tcl_Interp *interp, int format, Tcl_Obj *data,
	    int level, Tcl_Obj *gzipHeaderDictObj)
}
declare 611 {
    int Tcl_ZlibInflate(Tcl_Interp *interp, int format, Tcl_Obj *data,
	    size_t buffersize, Tcl_Obj *gzipHeaderDictObj)
	    Tcl_Size buffersize, Tcl_Obj *gzipHeaderDictObj)
}
declare 612 {
    unsigned int Tcl_ZlibCRC32(unsigned int crc, const unsigned char *buf,
	    size_t len)
	    Tcl_Size len)
}
declare 613 {
    unsigned int Tcl_ZlibAdler32(unsigned int adler, const unsigned char *buf,
	    size_t len)
	    Tcl_Size len)
}
declare 614 {
    int Tcl_ZlibStreamInit(Tcl_Interp *interp, int mode, int format,
	    int level, Tcl_Obj *dictObj, Tcl_ZlibStream *zshandle)
}
declare 615 {
    Tcl_Obj *Tcl_ZlibStreamGetCommandName(Tcl_ZlibStream zshandle)
}
declare 616 {
    int Tcl_ZlibStreamEof(Tcl_ZlibStream zshandle)
}
declare 617 {
    int Tcl_ZlibStreamChecksum(Tcl_ZlibStream zshandle)
}
declare 618 {
    int Tcl_ZlibStreamPut(Tcl_ZlibStream zshandle, Tcl_Obj *data, int flush)
}
declare 619 {
    int Tcl_ZlibStreamGet(Tcl_ZlibStream zshandle, Tcl_Obj *data,
	    size_t count)
	    Tcl_Size count)
}
declare 620 {
    int Tcl_ZlibStreamClose(Tcl_ZlibStream zshandle)
}
declare 621 {
    int Tcl_ZlibStreamReset(Tcl_ZlibStream zshandle)
}
2382
2383
2384
2385
2386
2387
2388
2389

2390
2391
2392
2393


2394
2395
2396
2397
2398
2399


2400
2401
2402
2403
2404
2405
2406
2407
2408
2409


2410
2411
2412
2413
2414

2415
2416
2417
2418

2419
2420
2421

2422
2423
2424
2425


2426
2427
2428
2429
2430
2431
2432
2111
2112
2113
2114
2115
2116
2117

2118
2119
2120


2121
2122
2123
2124
2125
2126


2127
2128
2129
2130
2131
2132
2133
2134
2135
2136


2137
2138
2139
2140
2141
2142

2143
2144
2145
2146

2147
2148
2149

2150
2151
2152


2153
2154
2155
2156
2157
2158
2159
2160
2161







-
+


-
-
+
+




-
-
+
+








-
-
+
+




-
+



-
+


-
+


-
-
+
+







declare 630 {
    void Tcl_ZlibStreamSetCompressionDictionary(Tcl_ZlibStream zhandle,
	    Tcl_Obj *compressionDictionaryObj)
}

# ----- BASELINE -- FOR -- 8.6.0 ----- #

# TIP #456
# TIP #456/#468
declare 631 {
    Tcl_Channel Tcl_OpenTcpServerEx(Tcl_Interp *interp, const char *service,
	    const char *host, unsigned int flags, Tcl_TcpAcceptProc *acceptProc,
	    void *callbackData)
	    const char *host, unsigned int flags, int backlog,
	    Tcl_TcpAcceptProc *acceptProc, void *callbackData)
}

# TIP #430
declare 632 {
    int TclZipfs_Mount(Tcl_Interp *interp, const char *mountPoint,
	    const char *zipname, const char *passwd)
    int TclZipfs_Mount(Tcl_Interp *interp, const char *zipname,
	    const char *mountPoint, const char *passwd)
}
declare 633 {
    int TclZipfs_Unmount(Tcl_Interp *interp, const char *mountPoint)
}
declare 634 {
    Tcl_Obj *TclZipfs_TclLibrary(void)
}
declare 635 {
    int TclZipfs_MountBuffer(Tcl_Interp *interp, const char *mountPoint,
	    unsigned char *data, size_t datalen, int copy)
    int TclZipfs_MountBuffer(Tcl_Interp *interp, const void *data,
	    size_t datalen, const char *mountPoint, int copy)
}

# TIP #445
declare 636 {
    void Tcl_FreeIntRep(Tcl_Obj *objPtr)
    void Tcl_FreeInternalRep(Tcl_Obj *objPtr)
}
declare 637 {
    char *Tcl_InitStringRep(Tcl_Obj *objPtr, const char *bytes,
	    size_t numBytes)
	    TCL_HASH_TYPE numBytes)
}
declare 638 {
    Tcl_ObjIntRep *Tcl_FetchIntRep(Tcl_Obj *objPtr, const Tcl_ObjType *typePtr)
    Tcl_ObjInternalRep *Tcl_FetchInternalRep(Tcl_Obj *objPtr, const Tcl_ObjType *typePtr)
}
declare 639 {
    void Tcl_StoreIntRep(Tcl_Obj *objPtr, const Tcl_ObjType *typePtr,
	    const Tcl_ObjIntRep *irPtr)
    void Tcl_StoreInternalRep(Tcl_Obj *objPtr, const Tcl_ObjType *typePtr,
	    const Tcl_ObjInternalRep *irPtr)
}
declare 640 {
    int Tcl_HasStringRep(Tcl_Obj *objPtr)
}

# TIP #506
declare 641 {
2440
2441
2442
2443
2444
2445
2446
2447

2448
2449
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
2489
2490
2491
2492


2493
2494

2495
2496
2497
2498
2499
2500
2501
2502
2503


2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514


2515
2516
2517
2518


2519
2520
2521

2522
2523
2524

2525
2526
2527

2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545

2546




2547
2548
2549
2550
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395

2396
2397




2398
2399
2400
2401
2402
2403
2404





2405
2406
2407

2408









2409
2410


2411
2412
2413
2414
2415
2416
2417


2418
2419
2420
2421


2422
2423
2424
2425

2426
2427
2428

2429
2430
2431

2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449

2450
2451
2452
2453
2454
2455
2456
2457
2458
2459







-
+




-
+




-
+



-
+



-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+
+
+
+
+













-
+

-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
+
+

-
+
-
-
-
-
-
-
-
-
-
+
+
-
-







-
-
+
+


-
-
+
+


-
+


-
+


-
+

















-
+

+
+
+
+




declare 643 {
    int Tcl_IsShared(Tcl_Obj *objPtr)
}

# TIP#312 New Tcl_LinkArray() function
declare 644 {
    int Tcl_LinkArray(Tcl_Interp *interp, const char *varName, void *addr,
	    int type, size_t size)
	    int type, Tcl_Size size)
}

declare 645 {
    int Tcl_GetIntForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    size_t endValue, size_t *indexPtr)
	    Tcl_Size endValue, Tcl_Size *indexPtr)
}

# TIP #548
declare 646 {
    int Tcl_UtfToUniChar(const char *src, int *chPtr)
    Tcl_Size Tcl_UtfToUniChar(const char *src, int *chPtr)
}
declare 647 {
    char *Tcl_UniCharToUtfDString(const int *uniStr,
	    size_t uniLength, Tcl_DString *dsPtr)
	    Tcl_Size uniLength, Tcl_DString *dsPtr)
}
declare 648 {
    int *Tcl_UtfToUniCharDString(const char *src,
	    size_t length, Tcl_DString *dsPtr)
	    Tcl_Size length, Tcl_DString *dsPtr)
}

# TIP #568
declare 649 {
    unsigned char *TclGetBytesFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    void *numBytesPtr)
}
declare 650 {
    unsigned char *Tcl_GetBytesFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    Tcl_Size *numBytesPtr)
}

# TIP #481
declare 651 {
    char *Tcl_GetStringFromObj(Tcl_Obj *objPtr, Tcl_Size *lengthPtr)
}
declare 652 {
    Tcl_UniChar *Tcl_GetUnicodeFromObj(Tcl_Obj *objPtr, Tcl_Size *lengthPtr)
}

# TIP 660
declare 653 {
    int Tcl_GetSizeIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    Tcl_Size *sizePtr)
}

# TIP #575
declare 654 {
    int Tcl_UtfCharComplete(const char *src, Tcl_Size length)
}
declare 655 {
    const char *Tcl_UtfNext(const char *src)
}
declare 656 {
    const char *Tcl_UtfPrev(const char *src, const char *start)
}

# TIP 701
declare 657 {
    int Tcl_FSTildeExpand(Tcl_Interp *interp, const char *path,
	Tcl_DString *dsPtr)
}

# TIP 656
declare 658 {
    int Tcl_ExternalToUtfDStringEx(Tcl_Interp *interp, Tcl_Encoding encoding,
	    const char *src, Tcl_Size srcLen, int flags, Tcl_DString *dsPtr,
	    Tcl_Size *errorLocationPtr)
}
declare 659 {
    int Tcl_UtfToExternalDStringEx(Tcl_Interp *interp, Tcl_Encoding encoding,
	    const char *src, Tcl_Size srcLen, int flags, Tcl_DString *dsPtr,
	    Tcl_Size *errorLocationPtr)
}

# TIP #511
declare 660 {
    int Tcl_AsyncMarkFromSignal(Tcl_AsyncHandler async, int sigNumber)
}

# TIP #616
declare 661 {
    int Tcl_ListObjGetElements(Tcl_Interp *interp, Tcl_Obj *listPtr,
	    Tcl_Size *objcPtr, Tcl_Obj ***objvPtr)
}
declare 662 {
    int Tcl_ListObjLength(Tcl_Interp *interp, Tcl_Obj *listPtr,
	    Tcl_Size *lengthPtr)
}
declare 663 {
    int Tcl_DictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Size *sizePtr)
}
declare 664 {
    int Tcl_SplitList(Tcl_Interp *interp, const char *listStr, Tcl_Size *argcPtr,
	    const char ***argvPtr)
}
declare 665 {
    void Tcl_SplitPath(const char *path, Tcl_Size *argcPtr, const char ***argvPtr)
}
declare 666 {
    Tcl_Obj *Tcl_FSSplitPath(Tcl_Obj *pathPtr, Tcl_Size *lenPtr)
}
declare 667 {
    int Tcl_ParseArgsObjv(Tcl_Interp *interp, const Tcl_ArgvInfo *argTable,
	    Tcl_Size *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv)
}

# TIP #617
declare 668 {
    Tcl_Size Tcl_UniCharLen(const int *uniStr)
}
declare 669 {
    Tcl_Size Tcl_NumUtfChars(const char *src, Tcl_Size length)
}
declare 670 {
    Tcl_Size Tcl_GetCharLength(Tcl_Obj *objPtr)
}
declare 671 {
    const char *Tcl_UtfAtIndex(const char *src, Tcl_Size index)
}
declare 672 {
    Tcl_Obj *Tcl_GetRange(Tcl_Obj *objPtr, Tcl_Size first, Tcl_Size last)
}
declare 673 {
    int Tcl_GetUniChar(Tcl_Obj *objPtr, Tcl_Size index)
}

declare 674 {
    int Tcl_GetBool(Tcl_Interp *interp, const char *src, int flags,
	    char *charPtr)
}
declare 675 {
    int Tcl_GetBoolFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    int flags, char *charPtr)
}
declare 676 {
    Tcl_Command Tcl_CreateObjCommand2(Tcl_Interp *interp,
	    const char *cmdName,
	    Tcl_ObjCmdProc2 *proc2, void *clientData,
	    Tcl_CmdDeleteProc *deleteProc)
}
declare 677 {
    Tcl_Trace Tcl_CreateObjTrace2(Tcl_Interp *interp, Tcl_Size level, int flags,
	    Tcl_CmdObjTraceProc2 *objProc2, void *clientData,
	    Tcl_CmdObjTraceDeleteProc *delProc)
}
declare 678 {
    Tcl_Command Tcl_NRCreateCommand2(Tcl_Interp *interp,
	    const char *cmdName, Tcl_ObjCmdProc2 *proc,
	    Tcl_ObjCmdProc2 *nreProc2, void *clientData,
	    Tcl_CmdDeleteProc *deleteProc)
}
declare 679 {
    int Tcl_NRCallObjProc2(Tcl_Interp *interp, Tcl_ObjCmdProc2 *objProc2,
	    void *clientData, Tcl_Size objc, Tcl_Obj *const objv[])
}

# TIP #638.
declare 680 {
    int Tcl_GetNumberFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    void **clientDataPtr, int *typePtr)
}
declare 681 {
    int Tcl_GetNumber(Tcl_Interp *interp, const char *bytes, Tcl_Size numBytes,
	    void **clientDataPtr, int *typePtr)
}

# TIP #220.
declare 682 {
    int Tcl_RemoveChannelMode(Tcl_Interp *interp, Tcl_Channel chan, int mode)
}

# TIP 643
declare 683 {
   Tcl_Size Tcl_GetEncodingNulLength(Tcl_Encoding encoding)
}

# TIP #650
declare 684 {
    int Tcl_GetWideUIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    Tcl_WideUInt *uwidePtr)
}

# TIP 651
declare 685 {
    Tcl_Obj *Tcl_DStringToObj(Tcl_DString *dsPtr)
}

declare 686 {
    int Tcl_UtfNcmp(const char *s1, const char *s2, size_t n)
}
declare 687 {
    int Tcl_UtfNcasecmp(const char *s1, const char *s2, size_t n)
}

# TIP #648
declare 688 {
    Tcl_Obj *Tcl_NewWideUIntObj(Tcl_WideUInt wideValue)
}
declare 689 {
    void Tcl_SetWideUIntObj(Tcl_Obj *objPtr, Tcl_WideUInt uwideValue)
}

# ----- BASELINE -- FOR -- 8.7.0 ----- #
# ----- BASELINE -- FOR -- 8.7.0 / 9.0.0 ----- #

declare 690 {
    void TclUnusedStubEntry(void)
}

##############################################################################

# Define the platform specific public Tcl interface. These functions are only
# available on the designated platform.

interface tclPlat

################################
# Unix specific functions
#   (none)

################################
# Windows specific functions
# Mac OS X specific functions

# Added in Tcl 8.1, Removed in Tcl 9.0 (converted to macro)

#declare 0 win {
#    TCHAR *Tcl_WinUtfToTChar(const char *str, size_t len, Tcl_DString *dsPtr)
declare 1 {
    int Tcl_MacOSXOpenVersionedBundleResources(Tcl_Interp *interp,
	    const char *bundleName, const char *bundleVersion,
	    int hasResourceFile, Tcl_Size maxPathLen, char *libraryPath)
}
declare 2 {
    void Tcl_MacOSXNotifierAddRunLoopMode(const void *runLoopMode)
#}
#declare 1 win {
#    char *Tcl_WinTCharToUtf(const TCHAR *str, size_t len, Tcl_DString *dsPtr)
#}

}

################################
# Mac OS X specific functions
# Windows specific functions

# Removed in 9.0
#declare 0 macosx {
#    int Tcl_MacOSXOpenBundleResources(Tcl_Interp *interp,
#	    const char *bundleName, int hasResourceFile,
#	    size_t maxPathLen, char *libraryPath)
#}
declare 1 macosx {
    int Tcl_MacOSXOpenVersionedBundleResources(Tcl_Interp *interp,
declare 3 {
    void Tcl_WinConvertError(unsigned errCode)
	    const char *bundleName, const char *bundleVersion,
	    int hasResourceFile, size_t maxPathLen, char *libraryPath)
}

##############################################################################

# Public functions that are not accessible via the stubs table.

export {
    void Tcl_MainEx(int argc, char **argv, Tcl_AppInitProc *appInitProc,
    Tcl_Interp *interp)
    TCL_NORETURN void Tcl_MainEx(Tcl_Size argc, char **argv, Tcl_AppInitProc *appInitProc,
	Tcl_Interp *interp)
}
export {
    void Tcl_StaticPackage(Tcl_Interp *interp, const char *pkgName,
	    Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc)
    void Tcl_StaticLibrary(Tcl_Interp *interp, const char *prefix,
	    Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc)
}
export {
    void Tcl_SetPanicProc(TCL_NORETURN1 Tcl_PanicProc *panicProc)
    const char *Tcl_SetPanicProc(Tcl_PanicProc *panicProc)
}
export {
    Tcl_ExitProc *Tcl_SetExitProc(TCL_NORETURN1 Tcl_ExitProc *proc)
    Tcl_ExitProc *Tcl_SetExitProc(Tcl_ExitProc *proc)
}
export {
    void Tcl_FindExecutable(const char *argv0)
    const char *Tcl_FindExecutable(const char *argv0)
}
export {
    const char *Tcl_InitStubs(Tcl_Interp *interp, const char *version,
	int exact)
}
export {
    const char *TclTomMathInitializeStubs(Tcl_Interp* interp,
	const char* version, int epoch, int revision)
}
export {
    const char *Tcl_PkgInitStubsCheck(Tcl_Interp *interp, const char *version,
	int exact)
}
export {
    void Tcl_GetMemoryInfo(Tcl_DString *dsPtr)
}
export {
    void Tcl_InitSubsystems(void)
    const char *Tcl_InitSubsystems(void)
}
export {
    const char *TclZipfs_AppHook(int *argc, char ***argv)
}


# Local Variables:
# mode: tcl
# End:

Changes to generic/tcl.h.

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
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







-
+
-


-


+
-
-
-
-
+
+
+
+
+
+

-
-
+
+
+







 * When version numbers change here, must also go into the following files and
 * update the version numbers:
 *
 * library/init.tcl	(1 LOC patch)
 * unix/configure.ac	(2 LOC Major, 2 LOC minor, 1 LOC patch)
 * win/configure.ac	(as above)
 * win/tcl.m4		(not patchlevel)
 * README		(sections 0 and 2, with and without separator)
 * README.md		(sections 0 and 2, with and without separator)
 * macosx/Tcl-Common.xcconfig (not patchlevel) 1 LOC
 * win/README		(not patchlevel) (sections 0 and 2)
 * unix/tcl.spec	(1 LOC patch)
 * tools/tcl.hpj.in	(not patchlevel, for windows installer)
 */

#if !defined(TCL_MAJOR_VERSION)
#define TCL_MAJOR_VERSION   9
#define TCL_MINOR_VERSION   0
#define TCL_RELEASE_LEVEL   TCL_ALPHA_RELEASE
#define TCL_RELEASE_SERIAL  2
#   define TCL_MAJOR_VERSION	9
#endif
#if TCL_MAJOR_VERSION == 9
#   define TCL_MINOR_VERSION	0
#   define TCL_RELEASE_LEVEL	TCL_FINAL_RELEASE
#   define TCL_RELEASE_SERIAL	1

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

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
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







-
+
+












+


+
+
+
-
+
+





-
-
+
+








#ifndef RC_INVOKED

/*
 * Special macro to define mutexes.
 */

#define TCL_DECLARE_MUTEX(name) static Tcl_Mutex name;
#define TCL_DECLARE_MUTEX(name) \
    static Tcl_Mutex name;

/*
 * Tcl's public routine Tcl_FSSeek() uses the values SEEK_SET, SEEK_CUR, and
 * SEEK_END, all #define'd by stdio.h .
 *
 * Also, many extensions need stdio.h, and they've grown accustomed to tcl.h
 * providing it for them rather than #include-ing it themselves as they
 * should, so also for their sake, we keep the #include to be consistent with
 * prior Tcl releases.
 */

#include <stdio.h>
#include <stddef.h>

#if defined(__GNUC__) && (__GNUC__ > 2)
#   if defined(_WIN32) && defined(__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO
#	define TCL_FORMAT_PRINTF(a,b) __attribute__ ((__format__ (__MINGW_PRINTF_FORMAT, a, b)))
#   else
#   define TCL_FORMAT_PRINTF(a,b) __attribute__ ((__format__ (__printf__, a, b)))
#	define TCL_FORMAT_PRINTF(a,b) __attribute__ ((__format__ (__printf__, a, b)))
#   endif
#   define TCL_NORETURN __attribute__ ((noreturn))
#   define TCL_NOINLINE __attribute__ ((noinline))
#   define TCL_NORETURN1 __attribute__ ((noreturn))
#else
#   define TCL_FORMAT_PRINTF(a,b)
#   if defined(_MSC_VER) && (_MSC_VER >= 1310)
#	define TCL_NORETURN _declspec(noreturn)
#   if defined(_MSC_VER)
#	define TCL_NORETURN __declspec(noreturn)
#	define TCL_NOINLINE __declspec(noinline)
#   else
#	define TCL_NORETURN /* nothing */
#	define TCL_NOINLINE /* nothing */
#   endif
#   define TCL_NORETURN1 /* nothing */
#endif
145
146
147
148
149
150
151
152
153

154
155
156
157
158
159
160
153
154
155
156
157
158
159


160
161
162
163
164
165
166
167







-
-
+







 *
 * Note: when building static but linking dynamically to MSVCRT we must still
 *       correctly decorate the C library imported function.  Use CRTIMPORT
 *       for this purpose.  _DLL is defined by the compiler when linking to
 *       MSVCRT.
 */

#if (defined(_WIN32) && (defined(_MSC_VER) || (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0550)) || defined(__LCC__) || defined(__WATCOMC__) || (defined(__GNUC__) && defined(__declspec))))
#   define HAVE_DECLSPEC 1
#ifdef _WIN32
#   ifdef STATIC_BUILD
#       define DLLIMPORT
#       define DLLEXPORT
#       ifdef _DLL
#           define CRTIMPORT __declspec(dllimport)
#       else
#           define CRTIMPORT
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
366
367
368
369
370
371
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














366
367


368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384







-



-





+
+
+
+
+
+
+
















-
-
-
-


-
+
-
-
-
-
-
-
-
-
-




-
-
-
+
+
+
-
-
-
+
+









+
+
+
-
+
+




+
+




+
+
+
+
+
+
+
+
+
+





+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+


-
+






-
+


-
-
-
+
+
+

-
-







-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-


-
-









+







/*
 * Darwin specific configure overrides (to support fat compiles, where
 * configure runs only once for multiple architectures):
 */

#ifdef __APPLE__
#   ifdef __LP64__
#	undef TCL_WIDE_INT_TYPE
#	define TCL_WIDE_INT_IS_LONG 1
#	define TCL_CFG_DO64BIT 1
#    else /* !__LP64__ */
#	define TCL_WIDE_INT_TYPE long long
#	undef TCL_WIDE_INT_IS_LONG
#	undef TCL_CFG_DO64BIT
#    endif /* __LP64__ */
#    undef HAVE_STRUCT_STAT64
#endif /* __APPLE__ */

/* Cross-compiling 32-bit on a 64-bit platform? Then our
 * configure script does the wrong thing. Correct that here.
 */
#if defined(__GNUC__) && !defined(_WIN32) && !defined(__LP64__)
#   undef TCL_WIDE_INT_IS_LONG
#endif

/*
 * Define Tcl_WideInt to be a type that is (at least) 64-bits wide, and define
 * Tcl_WideUInt to be the unsigned variant of that type (assuming that where
 * we have one, we can have the other.)
 *
 * Also defines the following macros:
 * TCL_WIDE_INT_IS_LONG - if wide ints are really longs (i.e. we're on a
 *	LP64 system such as modern Solaris or Linux ... not including Win64)
 * Tcl_WideAsLong - forgetful converter from wideInt to long.
 * Tcl_LongAsWide - sign-extending converter from long to wideInt.
 * Tcl_WideAsDouble - converter from wideInt to double.
 * Tcl_DoubleAsWide - converter from double to wideInt.
 *
 * The following invariant should hold for any long value 'longVal':
 *	longVal == Tcl_WideAsLong(Tcl_LongAsWide(longVal))
 *
 * Note on converting between Tcl_WideInt and strings. This implementation (in
 * tclObj.c) depends on the function
 * sprintf(...,"%" TCL_LL_MODIFIER "d",...).
 */

#if !defined(TCL_WIDE_INT_TYPE)&&!defined(TCL_WIDE_INT_IS_LONG)
#if !defined(TCL_WIDE_INT_TYPE) && !defined(TCL_WIDE_INT_IS_LONG) && !defined(_WIN32) && !defined(__GNUC__)
#   if defined(_WIN32) && (!defined(__USE_MINGW_ANSI_STDIO) || !__USE_MINGW_ANSI_STDIO)
#      define TCL_WIDE_INT_TYPE __int64
#      define TCL_LL_MODIFIER	"I64"
#      if defined(_WIN64)
#         define TCL_Z_MODIFIER	"I"
#      endif
#   elif defined(__GNUC__)
#      define TCL_Z_MODIFIER	"z"
#   else /* ! _WIN32 && ! __GNUC__ */
/*
 * Don't know what platform it is and configure hasn't discovered what is
 * going on for us. Try to guess...
 */
#      include <limits.h>
#      if defined(LLONG_MAX) && (LLONG_MAX == LONG_MAX)
#         define TCL_WIDE_INT_IS_LONG	1
#   include <limits.h>
#   if defined(LLONG_MAX) && (LLONG_MAX == LONG_MAX)
#	define TCL_WIDE_INT_IS_LONG	1
#      endif
#   endif /* _WIN32 */
#endif /* !TCL_WIDE_INT_TYPE & !TCL_WIDE_INT_IS_LONG */
#   endif
#endif

#ifndef TCL_WIDE_INT_TYPE
#   define TCL_WIDE_INT_TYPE		long long
#endif /* !TCL_WIDE_INT_TYPE */

typedef TCL_WIDE_INT_TYPE		Tcl_WideInt;
typedef unsigned TCL_WIDE_INT_TYPE	Tcl_WideUInt;

#ifndef TCL_LL_MODIFIER
#   if defined(_WIN32) && (!defined(__USE_MINGW_ANSI_STDIO) || !__USE_MINGW_ANSI_STDIO)
#	define TCL_LL_MODIFIER	"I64"
#   else
#   define TCL_LL_MODIFIER	"ll"
#	define TCL_LL_MODIFIER	"ll"
#   endif
#endif /* !TCL_LL_MODIFIER */
#ifndef TCL_Z_MODIFIER
#   if defined(__GNUC__) && !defined(_WIN32)
#	define TCL_Z_MODIFIER	"z"
#   elif defined(_WIN64)
#	define TCL_Z_MODIFIER	TCL_LL_MODIFIER
#   else
#	define TCL_Z_MODIFIER	""
#   endif
#endif /* !TCL_Z_MODIFIER */
#ifndef TCL_T_MODIFIER
#   if defined(__GNUC__) && !defined(_WIN32)
#	define TCL_T_MODIFIER	"t"
#   elif defined(_WIN64)
#	define TCL_T_MODIFIER	TCL_LL_MODIFIER
#   else
#	define TCL_T_MODIFIER	TCL_Z_MODIFIER
#   endif
#endif /* !TCL_T_MODIFIER */

#define Tcl_WideAsLong(val)	((long)((Tcl_WideInt)(val)))
#define Tcl_LongAsWide(val)	((Tcl_WideInt)((long)(val)))
#define Tcl_WideAsDouble(val)	((double)((Tcl_WideInt)(val)))
#define Tcl_DoubleAsWide(val)	((Tcl_WideInt)((double)(val)))

#if TCL_MAJOR_VERSION < 9
    typedef int Tcl_Size;
#   define TCL_SIZE_MAX ((int)(((unsigned int)-1)>>1))
#   define TCL_SIZE_MODIFIER ""
#else
    typedef ptrdiff_t Tcl_Size;
#   define TCL_SIZE_MAX ((Tcl_Size)(((size_t)-1)>>1))
#   define TCL_SIZE_MODIFIER TCL_T_MODIFIER
#endif /* TCL_MAJOR_VERSION */

#if defined(_WIN32)
    typedef struct __stat64 Tcl_StatBuf;
#ifdef _WIN32
#   if TCL_MAJOR_VERSION > 8 || defined(_WIN64) || defined(_USE_64BIT_TIME_T)
	typedef struct __stat64 Tcl_StatBuf;
#   elif defined(_USE_32BIT_TIME_T)
	typedef struct _stati64	Tcl_StatBuf;
#   else
	typedef struct _stat32i64 Tcl_StatBuf;
#   endif
#elif defined(__CYGWIN__)
    typedef struct {
	dev_t st_dev;
	unsigned st_dev;
	unsigned short st_ino;
	unsigned short st_mode;
	short st_nlink;
	short st_uid;
	short st_gid;
	/* Here is a 2-byte gap */
	dev_t st_rdev;
	unsigned st_rdev;
	/* Here is a 4-byte gap */
	long long st_size;
	struct {long long tv_sec;} st_atim;
	struct {long long tv_sec;} st_mtim;
	struct {long long tv_sec;} st_ctim;
	struct {long tv_sec;} st_atim;
	struct {long tv_sec;} st_mtim;
	struct {long tv_sec;} st_ctim;
    } Tcl_StatBuf;
#elif defined(HAVE_STRUCT_STAT64) && !defined(__APPLE__)
    typedef struct stat64 Tcl_StatBuf;
#else
    typedef struct stat Tcl_StatBuf;
#endif

/*
 *----------------------------------------------------------------------------
 * Data structures defined opaquely in this module. The definitions below just
 * provide dummy types. A few fields are made visible in Tcl_Interp
 * provide dummy types.
 * structures, namely those used for returning a string result from commands.
 * Direct access to the result field is discouraged in Tcl 8.0. The
 * interpreter result is either an object or a string, and the two values are
 * kept consistent unless some C code sets interp->result directly.
 * Programmers should use either the function Tcl_GetObjResult() or
 * Tcl_GetStringResult() to read the interpreter's result. See the SetResult
 * man page for details.
 *
 * Note: any change to the Tcl_Interp definition below must be mirrored in the
 * "real" definition in tclInt.h.
 *
 * Note: Tcl_ObjCmdProc functions do not directly set result and freeProc.
 * Instead, they set a Tcl_Obj member in the "real" structure that can be
 * accessed with Tcl_GetObjResult() and Tcl_SetObjResult().
 */

typedef struct Tcl_Interp Tcl_Interp;

typedef struct Tcl_AsyncHandler_ *Tcl_AsyncHandler;
typedef struct Tcl_Channel_ *Tcl_Channel;
typedef struct Tcl_ChannelTypeVersion_ *Tcl_ChannelTypeVersion;
typedef struct Tcl_Command_ *Tcl_Command;
typedef struct Tcl_Condition_ *Tcl_Condition;
typedef struct Tcl_Dict_ *Tcl_Dict;
typedef struct Tcl_EncodingState_ *Tcl_EncodingState;
typedef struct Tcl_Encoding_ *Tcl_Encoding;
typedef struct Tcl_Event Tcl_Event;
typedef struct Tcl_Interp Tcl_Interp;
typedef struct Tcl_InterpState_ *Tcl_InterpState;
typedef struct Tcl_LoadHandle_ *Tcl_LoadHandle;
typedef struct Tcl_Mutex_ *Tcl_Mutex;
typedef struct Tcl_Pid_ *Tcl_Pid;
typedef struct Tcl_RegExp_ *Tcl_RegExp;
typedef struct Tcl_ThreadDataKey_ *Tcl_ThreadDataKey;
typedef struct Tcl_ThreadId_ *Tcl_ThreadId;
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
467
468
469
470
471
449
450
451
452
453
454
455

456
457
458
459
460
461
462
463
464
465
466

467
468

469
470
471
472
473
474
475
476
477

478
479
480
481

482
483
484
485
486
487
488
489
490
491
492
493
494







-
+









+
-
+

-
+

+
+
+
+



-
+


+
-
+

+
+
+
+







#define	TCL_REG_CANMATCH	001000  /* Report details on partial/limited
					 * matches. */

/*
 * Flags values passed to Tcl_RegExpExecObj.
 */

#define	TCL_REG_NOTBOL	0001	/* Beginning of string does not match ^.  */
#define	TCL_REG_NOTBOL	0001	/* Beginning of string does not match ^. */
#define	TCL_REG_NOTEOL	0002	/* End of string does not match $. */

/*
 * Structures filled in by Tcl_RegExpInfo. Note that all offset values are
 * relative to the start of the match string, not the beginning of the entire
 * string.
 */

typedef struct Tcl_RegExpIndices {
#if TCL_MAJOR_VERSION > 8
    size_t start;			/* Character offset of first character in
    Tcl_Size start;		/* Character offset of first character in
				 * match. */
    size_t end;			/* Character offset of first character after
    Tcl_Size end;		/* Character offset of first character after
				 * the match. */
#else
    long start;
    long end;
#endif
} Tcl_RegExpIndices;

typedef struct Tcl_RegExpInfo {
    size_t nsubs;			/* Number of subexpressions in the compiled
    Tcl_Size nsubs;		/* Number of subexpressions in the compiled
				 * expression. */
    Tcl_RegExpIndices *matches;	/* Array of nsubs match offset pairs. */
#if TCL_MAJOR_VERSION > 8
    size_t extendStart;		/* The offset at which a subsequent match
    Tcl_Size extendStart;	/* The offset at which a subsequent match
				 * might begin. */
#else
    long extendStart;
    long reserved;		/* Reserved for later use. */
#endif
} Tcl_RegExpInfo;

/*
 * Picky compilers complain if this typdef doesn't appear before the struct's
 * reference in tclDecls.h.
 */

487
488
489
490
491
492
493


494
495
496
497
498
499
500


501
502
503
504
505
506
507
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







+
+







+
+







 * TCL_RETURN		The command requests that the current function return;
 *			the interpreter's result contains the function's
 *			return value.
 * TCL_BREAK		The command requests that the innermost loop be
 *			exited; the interpreter's result is meaningless.
 * TCL_CONTINUE		Go on to the next iteration of the current loop; the
 *			interpreter's result is meaningless.
 * Integer return codes in the range TCL_CODE_USER_MIN to TCL_CODE_USER_MAX are
 * reserved for the use of packages.
 */

#define TCL_OK			0
#define TCL_ERROR		1
#define TCL_RETURN		2
#define TCL_BREAK		3
#define TCL_CONTINUE		4
#define TCL_CODE_USER_MIN	5
#define TCL_CODE_USER_MAX	0x3fffffff /*  1073741823 */

/*
 *----------------------------------------------------------------------------
 * Flags to control what substitutions are performed by Tcl_SubstObj():
 */

#define TCL_SUBST_COMMANDS	001
537
538
539
540
541
542
543
544

545
546
547
548
549

550
551

552
553
554
555
556
557
558
559
















560
561


562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
























581
582
583
584
585
586
587
564
565
566
567
568
569
570

571
572
573
574
575

576
577

578
579

580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601


602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653







-
+




-
+

-
+

-






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+



















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	struct Tcl_Obj *const *objv);
typedef void (Tcl_CmdObjTraceDeleteProc) (void *clientData);
typedef void (Tcl_DupInternalRepProc) (struct Tcl_Obj *srcPtr,
	struct Tcl_Obj *dupPtr);
typedef int (Tcl_EncodingConvertProc) (void *clientData, const char *src,
	int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst,
	int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr);
#define Tcl_EncodingFreeProc Tcl_FreeProc
typedef void (Tcl_EncodingFreeProc) (void *clientData);
typedef int (Tcl_EventProc) (Tcl_Event *evPtr, int flags);
typedef void (Tcl_EventCheckProc) (void *clientData, int flags);
typedef int (Tcl_EventDeleteProc) (Tcl_Event *evPtr, void *clientData);
typedef void (Tcl_EventSetupProc) (void *clientData, int flags);
#define Tcl_ExitProc Tcl_FreeProc
typedef void (Tcl_ExitProc) (void *clientData);
typedef void (Tcl_FileProc) (void *clientData, int mask);
#define Tcl_FileFreeProc Tcl_FreeProc
typedef void (Tcl_FileFreeProc) (void *clientData);
typedef void (Tcl_FreeInternalRepProc) (struct Tcl_Obj *objPtr);
typedef void (Tcl_FreeProc) (void *blockPtr);
typedef void (Tcl_IdleProc) (void *clientData);
typedef void (Tcl_InterpDeleteProc) (void *clientData,
	Tcl_Interp *interp);
typedef void (Tcl_NamespaceDeleteProc) (void *clientData);
typedef int (Tcl_ObjCmdProc) (void *clientData, Tcl_Interp *interp,
	int objc, struct Tcl_Obj *const *objv);
#if TCL_MAJOR_VERSION > 8
typedef int (Tcl_ObjCmdProc2) (void *clientData, Tcl_Interp *interp,
	Tcl_Size objc, struct Tcl_Obj *const *objv);
typedef int (Tcl_CmdObjTraceProc2) (void *clientData, Tcl_Interp *interp,
	Tcl_Size level, const char *command, Tcl_Command commandInfo, Tcl_Size objc,
	struct Tcl_Obj *const *objv);
typedef void (Tcl_FreeProc) (void *blockPtr);
#define Tcl_ExitProc Tcl_FreeProc
#define Tcl_FileFreeProc Tcl_FreeProc
#define Tcl_FileFreeProc Tcl_FreeProc
#define Tcl_EncodingFreeProc Tcl_FreeProc
#else
#define Tcl_ObjCmdProc2 Tcl_ObjCmdProc
#define Tcl_CmdObjTraceProc2 Tcl_CmdObjTraceProc
typedef void (Tcl_FreeProc) (char *blockPtr);
#endif
typedef int (Tcl_PackageInitProc) (Tcl_Interp *interp);
typedef int (Tcl_PackageUnloadProc) (Tcl_Interp *interp, int flags);
typedef int (Tcl_LibraryInitProc) (Tcl_Interp *interp);
typedef int (Tcl_LibraryUnloadProc) (Tcl_Interp *interp, int flags);
typedef void (Tcl_PanicProc) (const char *format, ...);
typedef void (Tcl_TcpAcceptProc) (void *callbackData, Tcl_Channel chan,
	char *address, int port);
typedef void (Tcl_TimerProc) (void *clientData);
typedef int (Tcl_SetFromAnyProc) (Tcl_Interp *interp, struct Tcl_Obj *objPtr);
typedef void (Tcl_UpdateStringProc) (struct Tcl_Obj *objPtr);
typedef char * (Tcl_VarTraceProc) (void *clientData, Tcl_Interp *interp,
	const char *part1, const char *part2, int flags);
typedef void (Tcl_CommandTraceProc) (void *clientData, Tcl_Interp *interp,
	const char *oldName, const char *newName, int flags);
typedef void (Tcl_CreateFileHandlerProc) (int fd, int mask, Tcl_FileProc *proc,
	void *clientData);
typedef void (Tcl_DeleteFileHandlerProc) (int fd);
typedef void (Tcl_AlertNotifierProc) (void *clientData);
typedef void (Tcl_ServiceModeHookProc) (int mode);
typedef void *(Tcl_InitNotifierProc) (void);
typedef void (Tcl_FinalizeNotifierProc) (void *clientData);
typedef void (Tcl_MainLoopProc) (void);

/* Abstract List functions */
typedef Tcl_Size (Tcl_ObjTypeLengthProc) (struct Tcl_Obj *listPtr);
typedef int (Tcl_ObjTypeIndexProc) (Tcl_Interp *interp, struct Tcl_Obj *listPtr,
	Tcl_Size index, struct Tcl_Obj** elemObj);
typedef int (Tcl_ObjTypeSliceProc) (Tcl_Interp *interp, struct Tcl_Obj *listPtr,
	Tcl_Size fromIdx, Tcl_Size toIdx, struct Tcl_Obj **newObjPtr);
typedef int (Tcl_ObjTypeReverseProc) (Tcl_Interp *interp,
	struct Tcl_Obj *listPtr, struct Tcl_Obj **newObjPtr);
typedef int (Tcl_ObjTypeGetElements) (Tcl_Interp *interp,
	struct Tcl_Obj *listPtr, Tcl_Size *objcptr, struct Tcl_Obj ***objvptr);
typedef	struct Tcl_Obj *(Tcl_ObjTypeSetElement) (Tcl_Interp *interp,
	struct Tcl_Obj *listPtr, Tcl_Size indexCount,
	struct Tcl_Obj *const indexArray[], struct Tcl_Obj *valueObj);
typedef int (Tcl_ObjTypeReplaceProc) (Tcl_Interp *interp,
	struct Tcl_Obj *listObj, Tcl_Size first, Tcl_Size numToDelete,
	Tcl_Size numToInsert, struct Tcl_Obj *const insertObjs[]);
typedef int (Tcl_ObjTypeInOperatorProc) (Tcl_Interp *interp,
	struct Tcl_Obj *valueObj, struct Tcl_Obj *listObj, int *boolResult);

#ifndef TCL_NO_DEPRECATED
#   define Tcl_PackageInitProc Tcl_LibraryInitProc
#   define Tcl_PackageUnloadProc Tcl_LibraryUnloadProc
#endif

/*
 *----------------------------------------------------------------------------
 * The following structure represents a type of object, which is a particular
 * internal representation for an object plus a set of functions that provide
 * standard operations on objects of that type.
 */

597
598
599
600
601
602
603

























604
605













606
607
608


609
610

611
612
613

614
615
616
617
618
619
620
621
622
623
624
625
626
627

628
629
630
631
632
633
634
635
636

637
638
639
640
641
642
643
644
645
646
647
648

649
650
651
652
653

654

655
656

657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680

681
682
683
684
685
686
687
663
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
707
708
709
710


711
712
713

714
715
716

717
718
719
720
721
722
723
724
725
726
727
728
729
730

731
732
733
734
735
736
737
738
739

740
741
742
743
744
745
746
747
748
749
750
751

752
753
754
755
756
757
758

759
760

761









762
763
764
765
766
767
768
769
770
771
772
773
774
775

776
777
778
779
780
781
782
783







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+

-
+


-
+













-
+








-
+











-
+





+
-
+

-
+
-
-
-
-
-
-
-
-
-














-
+







    Tcl_UpdateStringProc *updateStringProc;
				/* Called to update the string rep from the
				 * type's internal representation. */
    Tcl_SetFromAnyProc *setFromAnyProc;
				/* Called to convert the object's internal rep
				 * to this type. Frees the internal rep of the
				 * old type. Returns TCL_ERROR on failure. */
#if TCL_MAJOR_VERSION > 8
    size_t version;		/* Version field for future-proofing. */

    /* List emulation functions - ObjType Version 1 */
    Tcl_ObjTypeLengthProc *lengthProc;
				/* Return the [llength] of the AbstractList */
    Tcl_ObjTypeIndexProc *indexProc;
				/* Return a value (Tcl_Obj) at a given index */
    Tcl_ObjTypeSliceProc *sliceProc;
				/* Return an AbstractList for
				 * [lrange $al $start $end] */
    Tcl_ObjTypeReverseProc *reverseProc;
				/* Return an AbstractList for [lreverse $al] */
    Tcl_ObjTypeGetElements *getElementsProc;
				/* Return an objv[] of all elements in the list */
    Tcl_ObjTypeSetElement *setElementProc;
				/* Replace the element at the indicies with the
				 * given valueObj. */
    Tcl_ObjTypeReplaceProc *replaceProc;
				/* Replace sublist with another sublist */
    Tcl_ObjTypeInOperatorProc *inOperProc;
				/* "in" and "ni" expr list operation.
				 * Determine if the given string value matches
				 * an element in the list. */
#endif
} Tcl_ObjType;

#if TCL_MAJOR_VERSION > 8
#   define TCL_OBJTYPE_V0 0, \
	   0,0,0,0,0,0,0,0	/* Pre-Tcl 9 */
#   define TCL_OBJTYPE_V1(a) offsetof(Tcl_ObjType, indexProc), \
	   a,0,0,0,0,0,0,0	/* Tcl 9 Version 1 */
#   define TCL_OBJTYPE_V2(a,b,c,d,e,f,g,h) sizeof(Tcl_ObjType),  \
	   a,b,c,d,e,f,g,h	/* Tcl 9 - AbstractLists */
#else
#   define TCL_OBJTYPE_V0 /* just empty */
#   define TCL_OBJTYPE_V1(a) /* just empty */
#   define TCL_OBJTYPE_V2(a,b,c,d,e,f,g,h) /* just empty */
#endif

/*
 * The following structure stores an internal representation (intrep) for
 * a Tcl value. An intrep is associated with an Tcl_ObjType when both
 * The following structure stores an internal representation (internalrep) for
 * a Tcl value. An internalrep is associated with an Tcl_ObjType when both
 * are stored in the same Tcl_Obj.  The routines of the Tcl_ObjType govern
 * the handling of the intrep.
 * the handling of the internalrep.
 */

typedef union Tcl_ObjIntRep {	/* The internal representation: */
typedef union Tcl_ObjInternalRep {	/* The internal representation: */
    long longValue;		/*   - an long integer value. */
    double doubleValue;		/*   - a double-precision floating value. */
    void *otherValuePtr;	/*   - another, type-specific value, */
				/*     not used internally any more. */
    Tcl_WideInt wideValue;	/*   - an integer value >= 64bits */
    struct {			/*   - internal rep as two pointers. */
	void *ptr1;
	void *ptr2;
    } twoPtrValue;
    struct {			/*   - internal rep as a pointer and a long, */
	void *ptr;		/*     not used internally any more. */
	unsigned long value;
    } ptrAndLongRep;
} Tcl_ObjIntRep;
} Tcl_ObjInternalRep;

/*
 * One of the following structures exists for each object in the Tcl system.
 * An object stores a value as either a string, some internal representation,
 * or both.
 */

typedef struct Tcl_Obj {
    size_t refCount;		/* When 0 the object will be freed. */
    Tcl_Size refCount;		/* When 0 the object will be freed. */
    char *bytes;		/* This points to the first byte of the
				 * object's string representation. The array
				 * must be followed by a null byte (i.e., at
				 * offset length) but may also contain
				 * embedded null characters. The array's
				 * storage is allocated by Tcl_Alloc. NULL means
				 * the string rep is invalid and must be
				 * regenerated from the internal rep.  Clients
				 * should use Tcl_GetStringFromObj or
				 * Tcl_GetString to get a pointer to the byte
				 * array as a readonly value. */
    size_t length;		/* The number of bytes at *bytes, not
    Tcl_Size length;		/* The number of bytes at *bytes, not
				 * including the terminating null. */
    const Tcl_ObjType *typePtr;	/* Denotes the object's type. Always
				 * corresponds to the type of the object's
				 * internal rep. NULL indicates the object has
				 * no internal rep (has no type). */
    Tcl_ObjInternalRep internalRep;
    Tcl_ObjIntRep internalRep;	/* The internal representation: */
				/* The internal representation: */
} Tcl_Obj;



/*
 *----------------------------------------------------------------------------
 * The following type contains the state needed by Tcl_SaveResult. It
 * is typically allocated on the stack.
 */

typedef Tcl_Obj *Tcl_SavedResult;

/*
 *----------------------------------------------------------------------------
 * The following definitions support Tcl's namespace facility. Note: the first
 * five fields must match exactly the fields in a Namespace structure (see
 * tclInt.h).
 */

typedef struct Tcl_Namespace {
    char *name;			/* The namespace's name within its parent
				 * namespace. This contains no ::'s. The name
				 * of the global namespace is "" although "::"
				 * is an synonym. */
    char *fullName;		/* The namespace's fully qualified name. This
				 * starts with ::. */
    void *clientData;	/* Arbitrary value associated with this
    void *clientData;		/* Arbitrary value associated with this
				 * namespace. */
    Tcl_NamespaceDeleteProc *deleteProc;
				/* Function invoked when deleting the
				 * namespace to, e.g., free clientData. */
    struct Tcl_Namespace *parentPtr;
				/* Points to the namespace that contains this
				 * one. NULL if this is the global
708
709
710
711
712
713
714
715

716
717

718
719
720
721

722
723
724

725
726
727
728
729
730
731
804
805
806
807
808
809
810

811
812

813
814
815
816

817
818
819

820
821
822
823
824
825
826
827







-
+

-
+



-
+


-
+







 * declared as "dummyX".
 *
 * WARNING!! The structure definition must be kept consistent with the
 * CallFrame structure in tclInt.h. If you change one, change the other.
 */

typedef struct Tcl_CallFrame {
    Tcl_Namespace *nsPtr;
    Tcl_Namespace *nsPtr;	/* Current namespace for the call frame. */
    int dummy1;
    int dummy2;
    Tcl_Size dummy2;
    void *dummy3;
    void *dummy4;
    void *dummy5;
    int dummy6;
    Tcl_Size dummy6;
    void *dummy7;
    void *dummy8;
    int dummy9;
    Tcl_Size dummy9;
    void *dummy10;
    void *dummy11;
    void *dummy12;
    void *dummy13;
} Tcl_CallFrame;

/*
739
740
741
742
743
744
745
746

747
748
749



750
751
752
753
754

755
756
757
758

759
760
761
762
763
764


765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780



781
782
783
784
785
786
787
835
836
837
838
839
840
841

842
843


844
845
846

847
848
849

850
851
852
853

854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875



876
877
878
879
880
881
882
883
884
885







-
+

-
-
+
+
+
-



-
+



-
+






+
+













-
-
-
+
+
+







 * is set to 1 if an object-based function was registered by
 * Tcl_CreateObjCommand, and to 0 if a string-based function was registered by
 * Tcl_CreateCommand. The other function is typically set to a compatibility
 * wrapper that does string-to-object or object-to-string argument conversions
 * then calls the other function.
 */

typedef struct Tcl_CmdInfo {
typedef struct {
    int isNativeObjectProc;	/* 1 if objProc was registered by a call to
				 * Tcl_CreateObjCommand; 0 otherwise.
				 * Tcl_SetCmdInfo does not modify this
				 * Tcl_CreateObjCommand; 2 if objProc was registered by
				 * a call to Tcl_CreateObjCommand2; 0 otherwise.
				 * Tcl_SetCmdInfo does not modify this field. */
				 * field. */
    Tcl_ObjCmdProc *objProc;	/* Command's object-based function. */
    void *objClientData;	/* ClientData for object proc. */
    Tcl_CmdProc *proc;		/* Command's string-based function. */
    void *clientData;	/* ClientData for string proc. */
    void *clientData;		/* ClientData for string proc. */
    Tcl_CmdDeleteProc *deleteProc;
				/* Function to call when command is
				 * deleted. */
    void *deleteData;	/* Value to pass to deleteProc (usually the
    void *deleteData;		/* Value to pass to deleteProc (usually the
				 * same as clientData). */
    Tcl_Namespace *namespacePtr;/* Points to the namespace that contains this
				 * command. Note that Tcl_SetCmdInfo will not
				 * change a command's namespace; use
				 * TclRenameCommand or Tcl_Eval (of 'rename')
				 * to do that. */
    Tcl_ObjCmdProc2 *objProc2;	/* Command's object2-based function. */
    void *objClientData2;	/* ClientData for object2 proc. */
} Tcl_CmdInfo;

/*
 *----------------------------------------------------------------------------
 * The structure defined below is used to hold dynamic strings. The only
 * fields that clients should use are string and length, accessible via the
 * macros Tcl_DStringValue and Tcl_DStringLength.
 */

#define TCL_DSTRING_STATIC_SIZE 200
typedef struct Tcl_DString {
    char *string;		/* Points to beginning of string: either
				 * staticSpace below or a malloced array. */
    size_t length;		/* Number of non-NULL characters in the
				 * string. */
    size_t spaceAvl;		/* Total number of bytes available for the
    Tcl_Size length;		/* Number of bytes in string excluding
				 * terminating nul */
    Tcl_Size spaceAvl;		/* Total number of bytes available for the
				 * string and its terminating NULL char. */
    char staticSpace[TCL_DSTRING_STATIC_SIZE];
				/* Space to use in common case where string is
				 * small. */
} Tcl_DString;

#define Tcl_DStringLength(dsPtr) ((dsPtr)->length)
798
799
800
801
802
803
804
805















806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822


823
824
825
826
827

828

829










830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

849
850
851
852
853
854
855
896
897
898
899
900
901
902

903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942

943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972

973
974
975
976
977
978
979
980







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

















+
+





+
-
+

+
+
+
+
+
+
+
+
+
+


















-
+








/*
 * Definition for a number of bytes of buffer space sufficient to hold the
 * string representation of an integer in base 10 (assuming the existence of
 * 64-bit integers).
 */

#define TCL_INTEGER_SPACE	24
#define TCL_INTEGER_SPACE	(3*(int)sizeof(Tcl_WideInt))

/*
 *----------------------------------------------------------------------------
 * Type values returned by Tcl_GetNumberFromObj
 *	TCL_NUMBER_INT		Representation is a Tcl_WideInt
 *	TCL_NUMBER_BIG		Representation is an mp_int
 *	TCL_NUMBER_DOUBLE	Representation is a double
 *	TCL_NUMBER_NAN		Value is NaN.
 */

#define TCL_NUMBER_INT          2
#define TCL_NUMBER_BIG          3
#define TCL_NUMBER_DOUBLE       4
#define TCL_NUMBER_NAN          5

/*
 * Flag values passed to Tcl_ConvertElement.
 * TCL_DONT_USE_BRACES forces it not to enclose the element in braces, but to
 *	use backslash quoting instead.
 * TCL_DONT_QUOTE_HASH disables the default quoting of the '#' character. It
 *	is safe to leave the hash unquoted when the element is not the first
 *	element of a list, and this flag can be used by the caller to indicate
 *	that condition.
 */

#define TCL_DONT_USE_BRACES	1
#define TCL_DONT_QUOTE_HASH	8

/*
 * Flags that may be passed to Tcl_GetIndexFromObj.
 * TCL_EXACT disallows abbreviated strings.
 * TCL_NULL_OK allows the empty string or NULL to return TCL_OK.
 *      The returned value will be -1;
 * TCL_INDEX_TEMP_TABLE disallows caching of lookups. A possible use case is
 *      a table that will not live long enough to make it worthwhile.
 */

#define TCL_EXACT		1
#define TCL_NULL_OK		32
#define TCL_INDEX_TEMP_TABLE	2
#define TCL_INDEX_TEMP_TABLE	64

/*
 * Flags that may be passed to Tcl_UniCharToUtf.
 * TCL_COMBINE Combine surrogates
 */

#if TCL_MAJOR_VERSION > 8
#    define TCL_COMBINE		0x1000000
#else
#    define TCL_COMBINE		0
#endif
/*
 *----------------------------------------------------------------------------
 * Flag values passed to Tcl_RecordAndEval, Tcl_EvalObj, Tcl_EvalObjv.
 * WARNING: these bit choices must not conflict with the bit choices for
 * evalFlag bits in tclInt.h!
 *
 * Meanings:
 *	TCL_NO_EVAL:		Just record this command
 *	TCL_EVAL_GLOBAL:	Execute script in global namespace
 *	TCL_EVAL_DIRECT:	Do not compile this script
 *	TCL_EVAL_INVOKE:	Magical Tcl_EvalObjv mode for aliases/ensembles
 *				o Run in iPtr->lookupNsPtr or global namespace
 *				o Cut out of error traces
 *				o Don't reset the flags controlling ensemble
 *				  error message rewriting.
 *	TCL_CANCEL_UNWIND:	Magical Tcl_CancelEval mode that causes the
 *				stack for the script in progress to be
 *				completely unwound.
 *	TCL_EVAL_NOERR:	Do no exception reporting at all, just return
 *	TCL_EVAL_NOERR:		Do no exception reporting at all, just return
 *				as the caller will report.
 */

#define TCL_NO_EVAL		0x010000
#define TCL_EVAL_GLOBAL		0x020000
#define TCL_EVAL_DIRECT		0x040000
#define TCL_EVAL_INVOKE		0x080000
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
1003
1004
1005
1006
1007
1008
1009




1010
1011
1012
1013
1014
1015
1016







-
-
-
-







#define TCL_TRACE_READS		 0x10
#define TCL_TRACE_WRITES	 0x20
#define TCL_TRACE_UNSETS	 0x40
#define TCL_TRACE_DESTROYED	 0x80

#define TCL_LEAVE_ERR_MSG	 0x200
#define TCL_TRACE_ARRAY		 0x800
#ifndef TCL_REMOVE_OBSOLETE_TRACES
/* Required to support old variable/vdelete/vinfo traces. */
#define TCL_TRACE_OLD_STYLE	 0x1000
#endif
/* Indicate the semantics of the result of a trace. */
#define TCL_TRACE_RESULT_DYNAMIC 0x8000
#define TCL_TRACE_RESULT_OBJECT  0x10000

/*
 * Flag values for ensemble commands.
 */
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936

937
938
939
940
941
942

943



944
945
946
947
948
949
950
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







-


-
-
-
-





-
+






+

+
+
+







#define TCL_LINK_STRING		4
#define TCL_LINK_WIDE_INT	5
#define TCL_LINK_CHAR		6
#define TCL_LINK_UCHAR		7
#define TCL_LINK_SHORT		8
#define TCL_LINK_USHORT		9
#define TCL_LINK_UINT		10
#if defined(TCL_WIDE_INT_IS_LONG) || defined(_WIN32) || defined(__CYGWIN__)
#define TCL_LINK_LONG		((sizeof(long) != sizeof(int)) ? TCL_LINK_WIDE_INT : TCL_LINK_INT)
#define TCL_LINK_ULONG		((sizeof(long) != sizeof(int)) ? TCL_LINK_WIDE_UINT : TCL_LINK_UINT)
#else
#define TCL_LINK_LONG		11
#define TCL_LINK_ULONG		12
#endif
#define TCL_LINK_FLOAT		13
#define TCL_LINK_WIDE_UINT	14
#define TCL_LINK_CHARS		15
#define TCL_LINK_BINARY		16
#define TCL_LINK_READ_ONLY	0x80


/*
 *----------------------------------------------------------------------------
 * Forward declarations of Tcl_HashTable and related types.
 */

#ifndef TCL_HASH_TYPE
#if TCL_MAJOR_VERSION > 8
#  define TCL_HASH_TYPE size_t
#else
#  define TCL_HASH_TYPE unsigned
#endif
#endif

typedef struct Tcl_HashKeyType Tcl_HashKeyType;
typedef struct Tcl_HashTable Tcl_HashTable;
typedef struct Tcl_HashEntry Tcl_HashEntry;

typedef TCL_HASH_TYPE (Tcl_HashKeyProc) (Tcl_HashTable *tablePtr, void *keyPtr);
985
986
987
988
989
990
991







992
993
994
995

996
997
998
999
1000
1001
1002
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130







+
+
+
+
+
+
+




+







 *				the lower bits. If this flag is set then the
 *				hash table will attempt to rectify this by
 *				randomising the bits and then using the upper
 *				N bits as the index into the table.
 * TCL_HASH_KEY_SYSTEM_HASH -	If this flag is set then all memory internally
 *                              allocated for the hash table that is not for an
 *                              entry will use the system heap.
 * TCL_HASH_KEY_DIRECT_COMPARE -
 *	                        Allows fast comparison for hash keys directly
 *                              by compare of their key.oneWordValue values,
 *                              before call of compareKeysProc (much slower
 *                              than a direct compare, so it is speed-up only
 *                              flag). Don't use it if keys contain values rather
 *                              than pointers.
 */

#define TCL_HASH_KEY_RANDOMIZE_HASH 0x1
#define TCL_HASH_KEY_SYSTEM_HASH    0x2
#define TCL_HASH_KEY_DIRECT_COMPARE 0x4

/*
 * Structure definition for the methods associated with a hash table key type.
 */

#define TCL_HASH_KEY_TYPE_VERSION 1
struct Tcl_HashKeyType {
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
1175
1176
1177
1178
1179
1180
1181

1182
1183

1184
1185

1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216

1217
1218
1219
1220
1221
1222
1223
1224







-
+

-
+

-
+

+

+



+
+
+




















-
+







struct Tcl_HashTable {
    Tcl_HashEntry **buckets;	/* Pointer to bucket array. Each element
				 * points to first entry in bucket's hash
				 * chain, or NULL. */
    Tcl_HashEntry *staticBuckets[TCL_SMALL_HASH_TABLE];
				/* Bucket array used for small tables (to
				 * avoid mallocs and frees). */
    size_t numBuckets;		/* Total number of buckets allocated at
    Tcl_Size numBuckets;	/* Total number of buckets allocated at
				 * **bucketPtr. */
    size_t numEntries;		/* Total number of entries present in
    Tcl_Size numEntries;	/* Total number of entries present in
				 * table. */
    size_t rebuildSize;		/* Enlarge table when numEntries gets to be
    Tcl_Size rebuildSize;	/* Enlarge table when numEntries gets to be
				 * this large. */
#if TCL_MAJOR_VERSION > 8
    size_t mask;		/* Mask value used in hashing function. */
#endif
    int downShift;		/* Shift count used in hashing function.
				 * Designed to use high-order bits of
				 * randomized keys. */
#if TCL_MAJOR_VERSION < 9
    int mask;			/* Mask value used in hashing function. */
#endif
    int keyType;		/* Type of keys used in this table. It's
				 * either TCL_CUSTOM_KEYS, TCL_STRING_KEYS,
				 * TCL_ONE_WORD_KEYS, or an integer giving the
				 * number of ints that is the size of the
				 * key. */
    Tcl_HashEntry *(*findProc) (Tcl_HashTable *tablePtr, const char *key);
    Tcl_HashEntry *(*createProc) (Tcl_HashTable *tablePtr, const char *key,
	    int *newPtr);
    const Tcl_HashKeyType *typePtr;
				/* Type of the keys used in the
				 * Tcl_HashTable. */
};

/*
 * Structure definition for information used to keep track of searches through
 * hash tables:
 */

typedef struct Tcl_HashSearch {
    Tcl_HashTable *tablePtr;	/* Table being searched. */
    size_t nextIndex;		/* Index of next bucket to be enumerated after
    Tcl_Size nextIndex;		/* Index of next bucket to be enumerated after
				 * present one. */
    Tcl_HashEntry *nextEntryPtr;/* Next entry to be enumerated in the current
				 * bucket. */
} Tcl_HashSearch;

/*
 * Acceptable key types for hash tables:
1118
1119
1120
1121
1122
1123
1124
1125

1126
1127
1128
1129
1130
1131
1132
1251
1252
1253
1254
1255
1256
1257

1258
1259
1260
1261
1262
1263
1264
1265







-
+







 * dictionaries. These fields should not be accessed by code outside
 * tclDictObj.c
 */

typedef struct {
    void *next;			/* Search position for underlying hash
				 * table. */
    size_t epoch;		/* Epoch marker for dictionary being searched,
    TCL_HASH_TYPE epoch;	/* Epoch marker for dictionary being searched,
				 * or 0 if search has terminated. */
    Tcl_Dict dictionaryPtr;	/* Reference to dictionary being searched. */
} Tcl_DictSearch;

/*
 *----------------------------------------------------------------------------
 * Flag values to pass to Tcl_DoOneEvent to disable searches for some kinds of
1151
1152
1153
1154
1155
1156
1157
1158

1159
1160
1161
1162


1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179



1180




1181

1182
1183
1184
1185
1186
1187
1188
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







-
+



-
+
+

















+
+
+

+
+
+
+

+








struct Tcl_Event {
    Tcl_EventProc *proc;	/* Function to call to service this event. */
    struct Tcl_Event *nextPtr;	/* Next in list of pending events, or NULL. */
};

/*
 * Positions to pass to Tcl_QueueEvent:
 * Positions to pass to Tcl_QueueEvent/Tcl_ThreadQueueEvent:
 */

typedef enum {
    TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, TCL_QUEUE_MARK
    TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, TCL_QUEUE_MARK,
    TCL_QUEUE_ALERT_IF_EMPTY=4
} Tcl_QueuePosition;

/*
 * Values to pass to Tcl_SetServiceMode to specify the behavior of notifier
 * event routines.
 */

#define TCL_SERVICE_NONE 0
#define TCL_SERVICE_ALL 1

/*
 * The following structure keeps is used to hold a time value, either as an
 * absolute time (the number of seconds from the epoch) or as an elapsed time.
 * On Unix systems the epoch is Midnight Jan 1, 1970 GMT.
 */

typedef struct Tcl_Time {
#if TCL_MAJOR_VERSION > 8
    long long sec;		/* Seconds. */
#else
    long sec;			/* Seconds. */
#endif
#if defined(_CYGWIN_) && TCL_MAJOR_VERSION > 8
    int usec;			/* Microseconds. */
#else
    long usec;			/* Microseconds. */
#endif
} Tcl_Time;

typedef void (Tcl_SetTimerProc) (const Tcl_Time *timePtr);
typedef int (Tcl_WaitForEventProc) (const Tcl_Time *timePtr);

/*
 * TIP #233 (Virtualized Time)
1221
1222
1223
1224
1225
1226
1227

1228




1229
1230
1231
1232
1233
1234
1235
1363
1364
1365
1366
1367
1368
1369
1370

1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381







+
-
+
+
+
+







#define TCL_CLOSE_WRITE		(1<<2)

/*
 * Value to use as the closeProc for a channel that supports the close2Proc
 * interface.
 */

#if TCL_MAJOR_VERSION > 8
#define TCL_CLOSE2PROC		NULL
#   define TCL_CLOSE2PROC		NULL
#else
#   define TCL_CLOSE2PROC		((void *) 1)
#endif

/*
 * Channel version tag. This was introduced in 8.3.2/8.4.
 */

#define TCL_CHANNEL_VERSION_5	((Tcl_ChannelTypeVersion) 0x5)

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
1407
1408
1409
1410
1411
1412
1413


1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424

1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443

1444

1445
1446
1447
1448

1449

1450
1451
1452
1453
1454
1455
1456







-
-
+
+









-
+


















-
+
-




-
+
-







			Tcl_DString *dsPtr);
typedef void	(Tcl_DriverWatchProc) (void *instanceData, int mask);
typedef int	(Tcl_DriverGetHandleProc) (void *instanceData,
			int direction, void **handlePtr);
typedef int	(Tcl_DriverFlushProc) (void *instanceData);
typedef int	(Tcl_DriverHandlerProc) (void *instanceData,
			int interestMask);
typedef Tcl_WideInt (Tcl_DriverWideSeekProc) (void *instanceData,
			Tcl_WideInt offset, int mode, int *errorCodePtr);
typedef long long (Tcl_DriverWideSeekProc) (void *instanceData,
			long long offset, int mode, int *errorCodePtr);
/*
 * TIP #218, Channel Thread Actions
 */
typedef void	(Tcl_DriverThreadActionProc) (void *instanceData,
			int action);
/*
 * TIP #208, File Truncation (etc.)
 */
typedef int	(Tcl_DriverTruncateProc) (void *instanceData,
			Tcl_WideInt length);
			long long length);

/*
 * struct Tcl_ChannelType:
 *
 * One such structure exists for each type (kind) of channel. It collects
 * together in one place all the functions that are part of the specific
 * channel type.
 *
 * It is recommend that the Tcl_Channel* functions are used to access elements
 * of this structure, instead of direct accessing.
 */

typedef struct Tcl_ChannelType {
    const char *typeName;	/* The name of the channel type in Tcl
				 * commands. This storage is owned by channel
				 * type. */
    Tcl_ChannelTypeVersion version;
				/* Version of the channel type. */
    void *closeProc;
    void *closeProc;		/* Not used any more. */
				/* Not used any more. */
    Tcl_DriverInputProc *inputProc;
				/* Function to call for input on channel. */
    Tcl_DriverOutputProc *outputProc;
				/* Function to call for output on channel. */
    void *seekProc;
    void *seekProc;		/* Not used any more. */
				/* Not used any more. */
    Tcl_DriverSetOptionProc *setOptionProc;
				/* Set an option on a channel. */
    Tcl_DriverGetOptionProc *getOptionProc;
				/* Get an option from a channel. */
    Tcl_DriverWatchProc *watchProc;
				/* Set up the notifier to watch for events on
				 * this channel. */
1472
1473
1474
1475
1476
1477
1478
1479

1480
1481
1482
1483
1484
1485
1486
1616
1617
1618
1619
1620
1621
1622

1623
1624
1625
1626
1627
1628
1629
1630







-
+







 * Not all entries need be non-NULL; any which are NULL are simply ignored.
 * However, a complete filesystem should provide all of these functions. The
 * explanations in the structure show the importance of each function.
 */

typedef struct Tcl_Filesystem {
    const char *typeName;	/* The name of the filesystem. */
    size_t structureLength;	/* Length of this structure, so future binary
    Tcl_Size structureLength;	/* Length of this structure, so future binary
				 * compatibility can be assured. */
    Tcl_FSVersion version;	/* Version of the filesystem type. */
    Tcl_FSPathInFilesystemProc *pathInFilesystemProc;
				/* Determines whether the pathname is in this
				 * filesystem. This is the most important
				 * filesystem function. */
    Tcl_FSDupInternalRepProc *dupInternalRepProc;
1541
1542
1543
1544
1545
1546
1547
1548

1549
1550
1551
1552
1553
1554
1555
1685
1686
1687
1688
1689
1690
1691

1692
1693
1694
1695
1696
1697
1698
1699







-
+







				 * arbitrary additional data to files in a
				 * filesystem. */
    Tcl_FSFileAttrsGetProc *fileAttrsGetProc;
				/* Called by 'Tcl_FSFileAttrsGet()' and by
				 * 'file attributes'. */
    Tcl_FSFileAttrsSetProc *fileAttrsSetProc;
				/* Called by 'Tcl_FSFileAttrsSet()' and by
				 * 'file attributes'.  */
				 * 'file attributes'. */
    Tcl_FSCreateDirectoryProc *createDirectoryProc;
				/* Called by 'Tcl_FSCreateDirectory()'.  May be
				 * NULL if the filesystem is read-only. */
    Tcl_FSRemoveDirectoryProc *removeDirectoryProc;
				/* Called by 'Tcl_FSRemoveDirectory()'.  May be
				 * NULL if the filesystem is read-only. */
    Tcl_FSDeleteFileProc *deleteFileProc;
1634
1635
1636
1637
1638
1639
1640
1641
1642


1643
1644
1645
1646
1647
1648
1649
1778
1779
1780
1781
1782
1783
1784


1785
1786
1787
1788
1789
1790
1791
1792
1793







-
-
+
+







 * token.
 */

typedef struct Tcl_Token {
    int type;			/* Type of token, such as TCL_TOKEN_WORD; see
				 * below for valid types. */
    const char *start;		/* First character in token. */
    size_t size;			/* Number of bytes in token. */
    size_t numComponents;		/* If this token is composed of other tokens,
    Tcl_Size size;		/* Number of bytes in token. */
    Tcl_Size numComponents;	/* If this token is composed of other tokens,
				 * this field tells how many of them there are
				 * (including components of components, etc.).
				 * The component tokens immediately follow
				 * this one. */
} Tcl_Token;

/*
1701
1702
1703
1704
1705
1706
1707
1708

1709
1710
1711
1712
1713
1714
1715
1845
1846
1847
1848
1849
1850
1851

1852
1853
1854
1855
1856
1857
1858
1859







-
+







 *				is described by a TCL_TOKEN_SUB_EXPR token
 *				followed by the TCL_TOKEN_OPERATOR token for
 *				the operator, then TCL_TOKEN_SUB_EXPR tokens
 *				for the left then the right operands.
 * TCL_TOKEN_OPERATOR -		The token describes one expression operator.
 *				An operator might be the name of a math
 *				function such as "abs". A TCL_TOKEN_OPERATOR
 *				token is always preceeded by one
 *				token is always preceded by one
 *				TCL_TOKEN_SUB_EXPR token for the operator's
 *				subexpression, and is followed by zero or more
 *				TCL_TOKEN_SUB_EXPR tokens for the operator's
 *				operands. NumComponents is always 0.
 * TCL_TOKEN_EXPAND_WORD -	This token is just like TCL_TOKEN_WORD except
 *				that it marks a word that began with the
 *				literal character prefix "{*}". This word is
1749
1750
1751
1752
1753
1754
1755
1756

1757
1758
1759
1760
1761
1762

1763
1764
1765
1766

1767
1768
1769
1770
1771
1772
1773
1774


1775
1776
1777






1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795

1796

1797
1798
1799

1800
1801
1802
1803
1804
1805
1806
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







-
+





-
+



-
+






-
-
+
+



+
+
+
+
+
+


















+
-
+
-
-
-
+







 */

#define NUM_STATIC_TOKENS 20

typedef struct Tcl_Parse {
    const char *commentStart;	/* Pointer to # that begins the first of one
				 * or more comments preceding the command. */
    size_t commentSize;		/* Number of bytes in comments (up through
    Tcl_Size commentSize;	/* Number of bytes in comments (up through
				 * newline character that terminates the last
				 * comment). If there were no comments, this
				 * field is 0. */
    const char *commandStart;	/* First character in first word of
				 * command. */
    int commandSize;		/* Number of bytes in command, including first
    Tcl_Size commandSize;	/* Number of bytes in command, including first
				 * character of first word, up through the
				 * terminating newline, close bracket, or
				 * semicolon. */
    int numWords;		/* Total number of words in command. May be
    Tcl_Size numWords;		/* Total number of words in command. May be
				 * 0. */
    Tcl_Token *tokenPtr;	/* Pointer to first token representing the
				 * words of the command. Initially points to
				 * staticTokens, but may change to point to
				 * malloc-ed space if command exceeds space in
				 * staticTokens. */
    int numTokens;		/* Total number of tokens in command. */
    int tokensAvailable;	/* Total number of tokens available at
    Tcl_Size numTokens;		/* Total number of tokens in command. */
    Tcl_Size tokensAvailable;	/* Total number of tokens available at
				 * *tokenPtr. */
    int errorType;		/* One of the parsing error types defined
				 * above. */
#if TCL_MAJOR_VERSION > 8
    int incomplete;		/* This field is set to 1 by Tcl_ParseCommand
				 * if the command appears to be incomplete.
				 * This information is used by
				 * Tcl_CommandComplete. */
#endif

    /*
     * The fields below are intended only for the private use of the parser.
     * They should not be used by functions that invoke Tcl_ParseCommand.
     */

    const char *string;		/* The original command string passed to
				 * Tcl_ParseCommand. */
    const char *end;		/* Points to the character just after the last
				 * one in the command string. */
    Tcl_Interp *interp;		/* Interpreter to use for error reporting, or
				 * NULL. */
    const char *term;		/* Points to character in string that
				 * terminated most recent token. Filled in by
				 * ParseTokens. If an error occurs, points to
				 * beginning of region where the error
				 * occurred (e.g. the open brace if the close
				 * brace is missing). */
#if TCL_MAJOR_VERSION < 9
    int incomplete;		/* This field is set to 1 by Tcl_ParseCommand
    int incomplete;
				 * if the command appears to be incomplete.
				 * This information is used by
				 * Tcl_CommandComplete. */
#endif
    Tcl_Token staticTokens[NUM_STATIC_TOKENS];
				/* Initial space for tokens for command. This
				 * space should be large enough to accommodate
				 * most commands; dynamic space is allocated
				 * for very large commands that don't fit
				 * here. */
} Tcl_Parse;
1817
1818
1819
1820
1821
1822
1823
1824

1825
1826
1827

1828
1829

1830
1831
1832
1833

1834
1835
1836
1837
1838
1839
1840
1966
1967
1968
1969
1970
1971
1972

1973

1974

1975
1976

1977
1978
1979
1980

1981
1982
1983
1984
1985
1986
1987
1988







-
+
-

-
+

-
+



-
+







				 * encoding type. */
    Tcl_EncodingConvertProc *toUtfProc;
				/* Function to convert from external encoding
				 * into UTF-8. */
    Tcl_EncodingConvertProc *fromUtfProc;
				/* Function to convert from UTF-8 into
				 * external encoding. */
    Tcl_FreeProc *freeProc;
    Tcl_FreeProc *freeProc;	/* If non-NULL, function to call when this
				/* If non-NULL, function to call when this
				 * encoding is deleted. */
    void *clientData;	/* Arbitrary value associated with encoding
    void *clientData;		/* Arbitrary value associated with encoding
				 * type. Passed to conversion functions. */
    int nullSize;		/* Number of zero bytes that signify
    Tcl_Size nullSize;		/* Number of zero bytes that signify
				 * end-of-string in this encoding. This number
				 * is used to determine the source string
				 * length when the srcLen argument is
				 * negative. Must be 1 or 2. */
				 * negative. Must be 1, 2, or 4. */
} Tcl_EncodingType;

/*
 * The following definitions are used as values for the conversion control
 * flags argument when converting text from one character set to another:
 *
 * TCL_ENCODING_START -		Signifies that the source buffer is the first
1849
1850
1851
1852
1853
1854
1855
1856

1857
1858
1859
1860
1861
1862
1863
1864

1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877






1878
1879
1880
1881



1882


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
1997
1998
1999
2000
2001
2002
2003

2004








2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031

2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097

2098
2099
2100

2101
2102
2103
2104

2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115







-
+
-
-
-
-
-
-
-
-
+













+
+
+
+
+
+




+
+
+
-
+
+


+
+
+
+
+
+
+
+
+
+




















-
+
-
-


-
+
-









-
+
-






+
-
+
+
+
+







-
+


-
+



-
+

+
+







 *				block in a (potentially multi-block) input
 *				stream. Tells the conversion routine to
 *				perform any finalization that needs to occur
 *				after the last byte is converted and then to
 *				reset to an initial state. If the source
 *				buffer contains the entire input stream to be
 *				converted, this flag should be set.
 * TCL_ENCODING_STOPONERROR -	If set, the converter returns immediately upon
 * TCL_ENCODING_STOPONERROR -	Not used any more.
 *				encountering an invalid byte sequence or a
 *				source character that has no mapping in the
 *				target encoding. If clear, the converter
 *				substitues the problematic character(s) with
 *				one or more "close" characters in the
 *				destination buffer and then continues to
 *				convert the source.
 * TCL_ENCODING_NO_TERMINATE - 	If set, Tcl_ExternalToUtf does not append a
 * TCL_ENCODING_NO_TERMINATE -	If set, Tcl_ExternalToUtf does not append a
 *				terminating NUL byte.  Since it does not need
 *				an extra byte for a terminating NUL, it fills
 *				all dstLen bytes with encoded UTF-8 content if
 *				needed.  If clear, a byte is reserved in the
 *				dst space for NUL termination, and a
 *				terminating NUL is appended.
 * TCL_ENCODING_CHAR_LIMIT -	If set and dstCharsPtr is not NULL, then
 *				Tcl_ExternalToUtf takes the initial value of
 *				*dstCharsPtr as a limit of the maximum number
 *				of chars to produce in the encoded UTF-8
 *				content.  Otherwise, the number of chars
 *				produced is controlled only by other limiting
 *				factors.
 * TCL_ENCODING_PROFILE_* -	Mutually exclusive encoding profile ids. Note
 *				these are bit masks.
 *
 * NOTE: THESE BIT DEFINITIONS SHOULD NOT OVERLAP WITH INTERNAL USE BITS
 * DEFINED IN tclEncoding.c (ENCODING_INPUT et al). Be cognizant of this
 * when adding bits.
 */

#define TCL_ENCODING_START		0x01
#define TCL_ENCODING_END		0x02
#if TCL_MAJOR_VERSION > 8
#   define TCL_ENCODING_STOPONERROR	0x0 /* Not used any more */
#else
#define TCL_ENCODING_STOPONERROR	0x04
#   define TCL_ENCODING_STOPONERROR	0x04
#endif
#define TCL_ENCODING_NO_TERMINATE	0x08
#define TCL_ENCODING_CHAR_LIMIT		0x10
/* Internal use bits, do not define bits in this space. See above comment */
#define TCL_ENCODING_INTERNAL_USE_MASK  0xFF00
/*
 * Reserve top byte for profile values (disjoint, not a mask). In case of
 * changes, ensure ENCODING_PROFILE_* macros in tclInt.h are modified if
 * necessary.
 */
#define TCL_ENCODING_PROFILE_STRICT   TCL_ENCODING_STOPONERROR
#define TCL_ENCODING_PROFILE_TCL8     0x01000000
#define TCL_ENCODING_PROFILE_REPLACE  0x02000000

/*
 * The following definitions are the error codes returned by the conversion
 * routines:
 *
 * TCL_OK -			All characters were converted.
 * TCL_CONVERT_NOSPACE -	The output buffer would not have been large
 *				enough for all of the converted data; as many
 *				characters as could fit were converted though.
 * TCL_CONVERT_MULTIBYTE -	The last few bytes in the source string were
 *				the beginning of a multibyte sequence, but
 *				more bytes were needed to complete this
 *				sequence. A subsequent call to the conversion
 *				routine should pass the beginning of this
 *				unconverted sequence plus additional bytes
 *				from the source stream to properly convert the
 *				formerly split-up multibyte sequence.
 * TCL_CONVERT_SYNTAX -		The source stream contained an invalid
 *				character sequence. This may occur if the
 *				input stream has been damaged or if the input
 *				encoding method was misidentified. This error
 *				encoding method was misidentified.
 *				is reported only if TCL_ENCODING_STOPONERROR
 *				was specified.
 * TCL_CONVERT_UNKNOWN -	The source string contained a character that
 *				could not be represented in the target
 *				encoding. This error is reported only if
 *				encoding.
 *				TCL_ENCODING_STOPONERROR was specified.
 */

#define TCL_CONVERT_MULTIBYTE	(-1)
#define TCL_CONVERT_SYNTAX	(-2)
#define TCL_CONVERT_UNKNOWN	(-3)
#define TCL_CONVERT_NOSPACE	(-4)

/*
 * The maximum number of bytes that are necessary to represent a single
 * Unicode character in UTF-8. The valid values are 3 and 4
 * Unicode character in UTF-8. The valid values are 3 and 4. If > 3,
 * (or perhaps 1 if we want to support a non-unicode enabled core). If > 3,
 * then Tcl_UniChar must be 4-bytes in size (UCS-4) (the default). If == 3,
 * then Tcl_UniChar must be 2-bytes in size (UTF-16). Since Tcl 9.0, UCS-4
 * mode is the default and recommended mode.
 */

#ifndef TCL_UTF_MAX
#   if TCL_MAJOR_VERSION > 8
#define TCL_UTF_MAX		4
#	define TCL_UTF_MAX		4
#   else
#	define TCL_UTF_MAX		3
#   endif
#endif

/*
 * This represents a Unicode character. Any changes to this should also be
 * reflected in regcustom.h.
 */

#if TCL_UTF_MAX > 3
#if TCL_UTF_MAX == 4
    /*
     * int isn't 100% accurate as it should be a strict 4-byte value
     * (perhaps wchar_t). ILP64/SILP64 systems may have troubles. The
     * (perhaps int32_t). ILP64/SILP64 systems may have troubles. The
     * size of this value must be reflected correctly in regcustom.h.
     */
typedef int Tcl_UniChar;
#else
#elif TCL_UTF_MAX == 3 && !defined(BUILD_tcl)
typedef unsigned short Tcl_UniChar;
#else
#   error "This TCL_UTF_MAX value is not supported"
#endif

/*
 *----------------------------------------------------------------------------
 * TIP #59: The following structure is used in calls 'Tcl_RegisterConfig' to
 * provide the system with the embedded configuration data.
 */
1969
1970
1971
1972
1973
1974
1975



1976

1977
1978
1979
1980
1981
1982
1983
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150







+
+
+

+








/*
 * Structure containing information about a limit handler to be called when a
 * command- or time-limit is exceeded by an interpreter.
 */

typedef void (Tcl_LimitHandlerProc) (void *clientData, Tcl_Interp *interp);
#if TCL_MAJOR_VERSION > 8
#define Tcl_LimitHandlerDeleteProc Tcl_FreeProc
#else
typedef void (Tcl_LimitHandlerDeleteProc) (void *clientData);
#endif

#if 0
/*
 *----------------------------------------------------------------------------
 * We would like to provide an anonymous structure "mp_int" here, which is
 * compatible with libtommath's "mp_int", but without duplicating anything
 * from <tommath.h> or including <tommath.h> here. But the libtommath project
2007
2008
2009
2010
2011
2012
2013
2014

2015
2016
2017
2018
2019
2020
2021
2174
2175
2176
2177
2178
2179
2180

2181
2182
2183
2184
2185
2186
2187
2188







-
+







				 * argv array. */
    void *srcPtr;		/* Value to be used in setting dst; usage
				 * depends on type.*/
    void *dstPtr;		/* Address of value to be modified; usage
				 * depends on type.*/
    const char *helpStr;	/* Documentation message describing this
				 * option. */
    void *clientData;	/* Word to pass to function callbacks. */
    void *clientData;		/* Word to pass to function callbacks. */
} Tcl_ArgvInfo;

/*
 * Legal values for the type field of a Tcl_ArgInfo: see the user
 * documentation for details.
 */

2032
2033
2034
2035
2036
2037
2038
2039
2040


2041
2042
2043
2044
2045
2046
2047
2199
2200
2201
2202
2203
2204
2205


2206
2207
2208
2209
2210
2211
2212
2213
2214







-
-
+
+







/*
 * Types of callback functions for the TCL_ARGV_FUNC and TCL_ARGV_GENFUNC
 * argument types:
 */

typedef int (Tcl_ArgvFuncProc)(void *clientData, Tcl_Obj *objPtr,
	void *dstPtr);
typedef int (Tcl_ArgvGenFuncProc)(void *clientData, Tcl_Interp *interp,
	int objc, Tcl_Obj *const *objv, void *dstPtr);
typedef Tcl_Size (Tcl_ArgvGenFuncProc)(void *clientData, Tcl_Interp *interp,
	Tcl_Size objc, Tcl_Obj *const *objv, void *dstPtr);

/*
 * Shorthand for commonly used argTable entries.
 */

#define TCL_ARGV_AUTO_HELP \
    {TCL_ARGV_HELP,	"-help",	NULL,	NULL, \
2105
2106
2107
2108
2109
2110
2111
2112

2113
2114
2115
2116
2117



2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132

2133




2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145


2146
2147

2148
2149

2150
2151
2152












2153

2154
2155
2156
2157
2158
2159
2160
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
2272
2273
2274
2275
2276
2277
2278

2279
2280
2281



2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300

2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391

2392
2393

2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436







-
+


-
-
-
+
+
+















+
-
+
+
+
+












+
+

-
+

-
+



+
+
+
+
+
+
+
+
+
+
+
+
-
+






-
-
+
+



+
+
+
+
-
+















-
-
-
+
+
+
+



-
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *----------------------------------------------------------------------------
 * Definitions needed for the Tcl_OpenTcpServerEx function. [TIP #456]
 */
#define TCL_TCPSERVER_REUSEADDR (1<<0)
#define TCL_TCPSERVER_REUSEPORT (1<<1)

/*
 * Constants for special size_t-typed values, see TIP #494
 * Constants for special Tcl_Size-typed values, see TIP #494
 */

#define TCL_IO_FAILURE	((size_t)-1)
#define TCL_AUTO_LENGTH	((size_t)-1)
#define TCL_INDEX_NONE  ((size_t)-1)
#define TCL_IO_FAILURE	((Tcl_Size)-1)
#define TCL_AUTO_LENGTH	((Tcl_Size)-1)
#define TCL_INDEX_NONE  ((Tcl_Size)-1)

/*
 *----------------------------------------------------------------------------
 * Single public declaration for NRE.
 */

typedef int (Tcl_NRPostProc) (void *data[], Tcl_Interp *interp,
				int result);

/*
 *----------------------------------------------------------------------------
 * The following constant is used to test for older versions of Tcl in the
 * stubs tables.
 */

#if TCL_MAJOR_VERSION > 8
#define TCL_STUB_MAGIC		((int) 0xFCA3BACB + (int) sizeof(void *))
#   define TCL_STUB_MAGIC	((int) 0xFCA3BACB + (int) sizeof(void *))
#else
#   define TCL_STUB_MAGIC	((int) 0xFCA3BACF)
#endif

/*
 * The following function is required to be defined in all stubs aware
 * extensions. The function is actually implemented in the stub library, not
 * the main Tcl library, although there is a trivial implementation in the
 * main library in case an extension is statically linked into an application.
 */

const char *		Tcl_InitStubs(Tcl_Interp *interp, const char *version,
			    int exact, int magic);
const char *		TclTomMathInitializeStubs(Tcl_Interp *interp,
			    const char *version, int epoch, int revision);
const char *		TclInitStubTable(const char *version);
void *			TclStubCall(void *arg);
#if defined(_WIN32)
    TCL_NORETURN1 void Tcl_ConsolePanic(const char *format, ...);
    TCL_NORETURN void	Tcl_ConsolePanic(const char *format, ...);
#else
#   define Tcl_ConsolePanic NULL
#   define Tcl_ConsolePanic ((Tcl_PanicProc *)NULL)
#endif

#ifdef USE_TCL_STUBS
#if TCL_MAJOR_VERSION < 9
# if TCL_UTF_MAX < 4
#   define Tcl_InitStubs(interp, version, exact) \
	(Tcl_InitStubs)(interp, version, \
	    (exact)|(TCL_MAJOR_VERSION<<8)|(0xFF<<16), \
	    TCL_STUB_MAGIC)
# else
#   define Tcl_InitStubs(interp, version, exact) \
	(Tcl_InitStubs)(interp, "8.7b1", \
	    (exact)|(TCL_MAJOR_VERSION<<8)|(0xFF<<16), \
	    TCL_STUB_MAGIC)
# endif
#if TCL_RELEASE_LEVEL == TCL_FINAL_RELEASE
#elif TCL_RELEASE_LEVEL == TCL_FINAL_RELEASE
#   define Tcl_InitStubs(interp, version, exact) \
	(Tcl_InitStubs)(interp, version, \
	    (exact)|(TCL_MAJOR_VERSION<<8)|(TCL_MINOR_VERSION<<16), \
	    TCL_STUB_MAGIC)
#else
#   define Tcl_InitStubs(interp, version, exact) \
	(Tcl_InitStubs)(interp, TCL_PATCH_LEVEL, \
	    1|(TCL_MAJOR_VERSION<<8)|(TCL_MINOR_VERSION<<16), \
	(Tcl_InitStubs)(interp, (((exact)&1) ? (version) : "9.0.0"), \
	    (exact)|(TCL_MAJOR_VERSION<<8)|(TCL_MINOR_VERSION<<16), \
	    TCL_STUB_MAGIC)
#endif
#else
#if TCL_MAJOR_VERSION < 9
#   define Tcl_InitStubs(interp, version, exact) \
	Tcl_Panic(((void)interp, (void)version, \
		(void)exact, "Please define -DUSE_TCL_STUBS"))
#if TCL_RELEASE_LEVEL == TCL_FINAL_RELEASE
#elif TCL_RELEASE_LEVEL == TCL_FINAL_RELEASE
#   define Tcl_InitStubs(interp, version, exact) \
	Tcl_PkgInitStubsCheck(interp, version, \
		(exact)|(TCL_MAJOR_VERSION<<8)|(TCL_MINOR_VERSION<<16))
#else
#   define Tcl_InitStubs(interp, version, exact) \
	Tcl_PkgInitStubsCheck(interp, TCL_PATCH_LEVEL, \
		1|(TCL_MAJOR_VERSION<<8)|(TCL_MINOR_VERSION<<16))
#endif
#endif

/*
 * Public functions that are not accessible via the stubs table.
 * Tcl_GetMemoryInfo is needed for AOLserver. [Bug 1868171]
 */

#define Tcl_Main(argc, argv, proc) Tcl_MainEx(argc, argv, proc, \
	    ((Tcl_SetPanicProc(Tcl_ConsolePanic), Tcl_CreateInterp)()))
EXTERN TCL_NORETURN void Tcl_MainEx(int argc, char **argv,
#define Tcl_Main(argc, argv, proc) \
	Tcl_MainEx(argc, argv, proc, \
	    ((Tcl_SetPanicProc(Tcl_ConsolePanic), Tcl_CreateInterp())))
EXTERN TCL_NORETURN void Tcl_MainEx(Tcl_Size argc, char **argv,
			    Tcl_AppInitProc *appInitProc, Tcl_Interp *interp);
EXTERN const char *	Tcl_PkgInitStubsCheck(Tcl_Interp *interp,
			    const char *version, int exact);
EXTERN void		Tcl_InitSubsystems(void);
EXTERN const char *	Tcl_InitSubsystems(void);
EXTERN void		Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
EXTERN void		Tcl_FindExecutable(const char *argv0);
EXTERN void		Tcl_SetPanicProc(
			    TCL_NORETURN1 Tcl_PanicProc *panicProc);
EXTERN void		Tcl_StaticPackage(Tcl_Interp *interp,
			    const char *pkgName,
			    Tcl_PackageInitProc *initProc,
			    Tcl_PackageInitProc *safeInitProc);
EXTERN Tcl_ExitProc *Tcl_SetExitProc(TCL_NORETURN1 Tcl_ExitProc *proc);
EXTERN const char *	Tcl_FindExecutable(const char *argv0);
EXTERN const char *	Tcl_SetPreInitScript(const char *string);
EXTERN const char *	Tcl_SetPanicProc(
			    Tcl_PanicProc *panicProc);
EXTERN void		Tcl_StaticLibrary(Tcl_Interp *interp,
			    const char *prefix,
			    Tcl_LibraryInitProc *initProc,
			    Tcl_LibraryInitProc *safeInitProc);
#ifndef TCL_NO_DEPRECATED
#   define Tcl_StaticPackage Tcl_StaticLibrary
#endif
EXTERN Tcl_ExitProc *	Tcl_SetExitProc(Tcl_ExitProc *proc);
#ifdef _WIN32
EXTERN int		TclZipfs_AppHook(int *argc, wchar_t ***argv);
EXTERN const char *	TclZipfs_AppHook(int *argc, wchar_t ***argv);
#else
EXTERN int		TclZipfs_AppHook(int *argc, char ***argv);
EXTERN const char *TclZipfs_AppHook(int *argc, char ***argv);
#endif
#if defined(_WIN32) && defined(UNICODE)
#ifndef USE_TCL_STUBS
#   define Tcl_FindExecutable(arg) ((Tcl_FindExecutable)((const char *)(arg)))
#endif
#   define Tcl_MainEx Tcl_MainExW
    EXTERN TCL_NORETURN void Tcl_MainExW(Tcl_Size argc, wchar_t **argv,
	    Tcl_AppInitProc *appInitProc, Tcl_Interp *interp);
#endif
#if defined(USE_TCL_STUBS) && (TCL_MAJOR_VERSION > 8)
#define Tcl_SetPanicProc(panicProc) \
    TclInitStubTable(((const char *(*)(Tcl_PanicProc *))TclStubCall((void *)panicProc))(panicProc))
#define Tcl_InitSubsystems() \
    TclInitStubTable(((const char *(*)(void))TclStubCall((void *)1))())
#define Tcl_FindExecutable(argv0) \
    TclInitStubTable(((const char *(*)(const char *))TclStubCall((void *)2))(argv0))
#define TclZipfs_AppHook(argcp, argvp) \
	TclInitStubTable(((const char *(*)(int *, void *))TclStubCall((void *)3))(argcp, argvp))
#define Tcl_MainExW(argc, argv, appInitProc, interp) \
	(void)((const char *(*)(Tcl_Size, const void *, Tcl_AppInitProc *, Tcl_Interp *)) \
	TclStubCall((void *)4))(argc, argv, appInitProc, interp)
#if !defined(_WIN32) || !defined(UNICODE)
#define Tcl_MainEx(argc, argv, appInitProc, interp) \
	(void)((const char *(*)(Tcl_Size, const void *, Tcl_AppInitProc *, Tcl_Interp *)) \
	TclStubCall((void *)5))(argc, argv, appInitProc, interp)
#endif
#define Tcl_StaticLibrary(interp, pkgName, initProc, safeInitProc) \
	(void)((const char *(*)(Tcl_Interp *, const char *, Tcl_LibraryInitProc *, Tcl_LibraryInitProc *)) \
	TclStubCall((void *)6))(interp, pkgName, initProc, safeInitProc)
#define Tcl_SetExitProc(proc) \
	((Tcl_ExitProc *(*)(Tcl_ExitProc *))TclStubCall((void *)7))(proc)
#define Tcl_GetMemoryInfo(dsPtr) \
	(void)((const char *(*)(Tcl_DString *))TclStubCall((void *)8))(dsPtr)
#define Tcl_SetPreInitScript(string) \
	((const char *(*)(const char *))TclStubCall((void *)9))(string)
#endif

/*
 *----------------------------------------------------------------------------
 * Include the public function declarations that are accessible via the stubs
 * table.
 */
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237



2238
2239
2240
2241
2242
2243
2244
2457
2458
2459
2460
2461
2462
2463



2464
2465
2466
2467
2468
2469
2470
2471
2472
2473







-
-
-
+
+
+







 */

#ifndef BUILD_tcl
#   define ckalloc Tcl_Alloc
#   define attemptckalloc Tcl_AttemptAlloc
#   ifdef _MSC_VER
	/* Silence invalid C4090 warnings */
#	define ckfree(a) Tcl_Free((char *)(a))
#	define ckrealloc(a,b) Tcl_Realloc((char *)(a),(b))
#	define attemptckrealloc(a,b) Tcl_AttemptRealloc((char *)(a),(b))
#	define ckfree(a) Tcl_Free((void *)(a))
#	define ckrealloc(a,b) Tcl_Realloc((void *)(a),(b))
#	define attemptckrealloc(a,b) Tcl_AttemptRealloc((void *)(a),(b))
#   else
#	define ckfree Tcl_Free
#	define ckrealloc Tcl_Realloc
#	define attemptckrealloc Tcl_AttemptRealloc
#   endif
#endif

2265
2266
2267
2268
2269
2270
2271























2272
2273
2274
2275

2276
2277
2278

2279
2280
2281
2282
2283
2284
2285
2286





2287
2288
2289
2290



















2291
2292
2293
2294
2295
2296
2297
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526

2527
2528
2529

2530
2531
2532
2533





2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+


-
+



-
-
-
-
-
+
+
+
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	Tcl_DbIncrRefCount(objPtr, __FILE__, __LINE__)
#   undef Tcl_DecrRefCount
#   define Tcl_DecrRefCount(objPtr) \
	Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__)
#   undef Tcl_IsShared
#   define Tcl_IsShared(objPtr) \
	Tcl_DbIsShared(objPtr, __FILE__, __LINE__)
/*
 * Free the Obj by effectively doing:
 *
 *   Tcl_IncrRefCount(objPtr);
 *   Tcl_DecrRefCount(objPtr);
 *
 * This will free the obj if there are no references to the obj.
 */
#   define Tcl_BounceRefCount(objPtr) \
    TclBounceRefCount(objPtr, __FILE__, __LINE__)

static inline void
TclBounceRefCount(
    Tcl_Obj* objPtr,
    const char* fn,
    int line)
{
    if (objPtr) {
	if ((objPtr)->refCount == 0) {
	    Tcl_DbDecrRefCount(objPtr, fn, line);
	}
    }
}
#else
#   undef Tcl_IncrRefCount
#   define Tcl_IncrRefCount(objPtr) \
	++(objPtr)->refCount
	((void)++(objPtr)->refCount)
    /*
     * Use do/while0 idiom for optimum correctness without compiler warnings.
     * http://c2.com/cgi/wiki?TrivialDoWhileLoop
     * https://wiki.c2.com/?TrivialDoWhileLoop
     */
#   undef Tcl_DecrRefCount
#   define Tcl_DecrRefCount(objPtr) \
	do { \
	    Tcl_Obj *_objPtr = (objPtr); \
	    if (_objPtr->refCount-- <= 1) { \
		TclFreeObj(_objPtr); \
	    } \
	do {								\
	    Tcl_Obj *_objPtr = (objPtr);				\
	    if (_objPtr->refCount-- <= 1) {				\
		TclFreeObj(_objPtr);					\
	    }								\
	} while(0)
#   undef Tcl_IsShared
#   define Tcl_IsShared(objPtr) \
	((objPtr)->refCount > 1)

/*
 * Declare that obj will no longer be used or referenced.
 * This will free the obj if there are no references to the obj.
 */
#   define Tcl_BounceRefCount(objPtr) \
    TclBounceRefCount(objPtr);

static inline void
TclBounceRefCount(
    Tcl_Obj* objPtr)
{
    if (objPtr) {
	if ((objPtr)->refCount == 0) {
	    Tcl_DecrRefCount(objPtr);
	}
    }
}

#endif

/*
 * Macros and definitions that help to debug the use of Tcl objects. When
 * TCL_MEM_DEBUG is defined, the Tcl_New declarations are overridden to call
 * debugging versions of the object creation functions.
 */
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
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







-
+

-
-
-
-
+
+
+
+






+


+








/*
 *----------------------------------------------------------------------------
 * Macros for clients to use to access fields of hash entries:
 */

#define Tcl_GetHashValue(h) ((h)->clientData)
#define Tcl_SetHashValue(h, value) ((h)->clientData = (void *) (value))
#define Tcl_SetHashValue(h, value) ((h)->clientData = (void *)(value))
#define Tcl_GetHashKey(tablePtr, h) \
	((void *) (((tablePtr)->keyType == TCL_ONE_WORD_KEYS || \
		    (tablePtr)->keyType == TCL_CUSTOM_PTR_KEYS) \
		   ? (h)->key.oneWordValue \
		   : (h)->key.string))
	((void *) (((tablePtr)->keyType == TCL_ONE_WORD_KEYS ||		\
		    (tablePtr)->keyType == TCL_CUSTOM_PTR_KEYS)		\
		? (h)->key.oneWordValue					\
		: (h)->key.string))

/*
 * Macros to use for clients to use to invoke find and create functions for
 * hash tables:
 */

#undef  Tcl_FindHashEntry
#define Tcl_FindHashEntry(tablePtr, key) \
	(*((tablePtr)->findProc))(tablePtr, (const char *)(key))
#undef  Tcl_CreateHashEntry
#define Tcl_CreateHashEntry(tablePtr, key, newPtr) \
	(*((tablePtr)->createProc))(tablePtr, (const char *)(key), newPtr)

#endif /* RC_INVOKED */

/*
 * end block for C++

Changes to generic/tclAlloc.c.

1
2
3
4
5
6
7
8
9
10
11



12
13
14
15
16
17
18
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
16
17
18








-
-
-
+
+
+







/*
 * tclAlloc.c --
 *
 *	This is a very fast storage allocator. It allocates blocks of a small
 *	number of different sizes, and keeps free lists of each size. Blocks
 *	that don't exactly fit are passed up to the next larger size. Blocks
 *	over a certain size are directly allocated from the system.
 *
 * Copyright (c) 1983 Regents of the University of California.
 * Copyright (c) 1996-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright © 1983 Regents of the University of California.
 * Copyright © 1996-1997 Sun Microsystems, Inc.
 * Copyright © 1998-1999 Scriptics Corporation.
 *
 * Portions contributed by Chris Kingsley, Jack Jansen and Ray Johnson.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

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
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







-
+















-
-
+
+
+

-
-
-
-
+
+
+
+

-
+

-
+








-







#if defined(USE_TCLALLOC) && USE_TCLALLOC

/*
 * We should really make use of AC_CHECK_TYPE(caddr_t) here, but it can wait
 * until Tcl uses config.h properly.
 */

#if defined(_MSC_VER) || defined(__MSVCRT__) || defined(__BORLANDC__)
#if defined(_MSC_VER) || defined(__MSVCRT__)
typedef size_t caddr_t;
#endif

/*
 * The overhead on a block is at least 8 bytes. When free, this space contains
 * a pointer to the next free block, and the bottom two bits must be zero.
 * When in use, the first byte is set to MAGIC, and the second byte is the
 * size index. The remaining bytes are for alignment. If range checking is
 * enabled then a second word holds the size of the requested block, less 1,
 * rounded up to a multiple of sizeof(RMAGIC). The order of elements is
 * critical: ov.magic must overlay the low order bits of ov.next, and ov.magic
 * can not be a valid ov.next bit pattern.
 */

union overhead {
    union overhead *next;		/* when free */
    unsigned char padding[TCL_ALLOCALIGN];	/* align struct to TCL_ALLOCALIGN bytes */
    union overhead *next;	/* when free */
    unsigned char padding[TCL_ALLOCALIGN];
				/* align struct to TCL_ALLOCALIGN bytes */
    struct {
	unsigned char magic0;		/* magic number */
	unsigned char index;		/* bucket # */
	unsigned char unused;		/* unused */
	unsigned char magic1;		/* other magic number */
	unsigned char magic0;	/* magic number */
	unsigned char index;	/* bucket # */
	unsigned char unused;	/* unused */
	unsigned char magic1;	/* other magic number */
#ifndef NDEBUG
	unsigned short rmagic;		/* range magic number */
	unsigned short rmagic;	/* range magic number */
	size_t size;		/* actual block size */
	unsigned short unused2;		/* padding to 8-byte align */
	unsigned short unused2;	/* padding to 8-byte align */
#endif
    } ovu;
#define overMagic0	ovu.magic0
#define overMagic1	ovu.magic1
#define bucketIndex	ovu.index
#define rangeCheckMagic	ovu.rmagic
#define realBlockSize	ovu.size
};


#define MAGIC		0xEF	/* magic # on accounting info */
#define RMAGIC		0x5555	/* magic # on range info */

#ifndef NDEBUG
#define	RSLOP		sizeof(unsigned short)
#else
88
89
90
91
92
93
94

95

96
97

98
99
100
101
102
103
104
88
89
90
91
92
93
94
95

96
97

98
99
100
101
102
103
104
105







+
-
+

-
+








/*
 * nextf[i] is the pointer to the next free block of size 2^(i+3). The
 * smallest allocatable block is MINBLOCK bytes. The overhead information
 * precedes the data area returned to the user.
 */

#define MINBLOCK \
#define MINBLOCK	((sizeof(union overhead) + (TCL_ALLOCALIGN-1)) & ~(TCL_ALLOCALIGN-1))
    ((sizeof(union overhead) + (TCL_ALLOCALIGN-1)) & ~(TCL_ALLOCALIGN-1))
#define NBUCKETS	(13 - (MINBLOCK >> 4))
#define MAXMALLOC	(1<<(NBUCKETS+2))
#define MAXMALLOC	((size_t)1 << (NBUCKETS+2))
static union overhead *nextf[NBUCKETS];

/*
 * The following structure is used to keep track of all system memory
 * currently owned by Tcl. When finalizing, all this memory will be returned
 * to the system.
 */
112
113
114
115
116
117
118
119

120
121
122
123
124
125
126
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127







-
+







static struct block *blockList;	/* Tracks the suballocated blocks. */
static struct block bigBlocks={	/* Big blocks aren't suballocated. */
    &bigBlocks, &bigBlocks
};

/*
 * The allocator is protected by a special mutex that must be explicitly
 * initialized. Futhermore, because Tcl_Alloc may be used before anything else
 * initialized. Furthermore, because Tcl_Alloc may be used before anything else
 * in Tcl, we make this module self-initializing after all with the allocInit
 * variable.
 */

#if TCL_THREADS
static Tcl_Mutex *allocMutexPtr;
#endif
247
248
249
250
251
252
253
254

255
256
257
258
259
260
261
248
249
250
251
252
253
254

255
256
257
258
259
260
261
262







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

void *
TclpAlloc(
    size_t numBytes)	/* Number of bytes to allocate. */
    size_t numBytes)		/* Number of bytes to allocate. */
{
    union overhead *overPtr;
    size_t bucket;
    size_t amount;
    struct block *bigBlockPtr = NULL;

    if (!allocInit) {
381
382
383
384
385
386
387
388

389
390
391

392
393
394
395
396
397
398
382
383
384
385
386
387
388

389
390
391

392
393
394
395
396
397
398
399







-
+


-
+







 *	Attempts to get more memory from the system.
 *
 *----------------------------------------------------------------------
 */

static void
MoreCore(
    size_t bucket)	/* What bucket to allocate to. */
    size_t bucket)		/* What bucket to allocate to. */
{
    union overhead *overPtr;
    size_t size;	/* size of desired block */
    size_t size;		/* size of desired block */
    size_t amount;		/* amount to allocate */
    size_t numBlocks;		/* how many blocks we get */
    struct block *blockPtr;

    /*
     * sbrk_size <= 0 only for big, FLUFFY, requests (about 2^30 bytes on a
     * VAX, I think) or for a negative arg.
506
507
508
509
510
511
512
513
514


515
516
517
518
519
520
521
507
508
509
510
511
512
513


514
515
516
517
518
519
520
521
522







-
-
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

void *
TclpRealloc(
    void *oldPtr,		/* Pointer to alloced block. */
    size_t numBytes)	/* New size of memory. */
    void *oldPtr,		/* Pointer to alloc'ed block. */
    size_t numBytes)		/* New size of memory. */
{
    int i;
    union overhead *overPtr;
    struct block *bigBlockPtr;
    int expensive;
    size_t maxSize;

578
579
580
581
582
583
584
585

586
587
588
589
590
591
592
579
580
581
582
583
584
585

586
587
588
589
590
591
592
593







-
+







	overPtr->realBlockSize = (numBytes + RSLOP - 1) & ~(RSLOP - 1);
	BLOCK_END(overPtr) = RMAGIC;
#endif

	Tcl_MutexUnlock(allocMutexPtr);
	return (void *)(overPtr+1);
    }
    maxSize = 1 << (i+3);
    maxSize = (size_t)1 << (i+3);
    expensive = 0;
    if (numBytes+OVERHEAD > maxSize) {
	expensive = 1;
    } else if (i>0 && numBytes+OVERHEAD < maxSize/2) {
	expensive = 1;
    }

605
606
607
608
609
610
611
612

613
614
615
616
617
618
619
606
607
608
609
610
611
612

613
614
615
616
617
618
619
620







-
+







	}
	memcpy(newPtr, oldPtr, numBytes);
	TclpFree(oldPtr);
	return newPtr;
    }

    /*
     * Ok, we don't have to copy, it fits as-is
     * No need to copy. It fits as-is.
     */

#ifndef NDEBUG
    overPtr->realBlockSize = (numBytes + RSLOP - 1) & ~(RSLOP - 1);
    BLOCK_END(overPtr) = RMAGIC;
#endif

651
652
653
654
655
656
657
658

659
660
661
662
663
664

665
666
667
668
669

670
671
672
673
674
675
676
652
653
654
655
656
657
658

659
660
661
662
663
664

665
666
667
668
669

670
671
672
673
674
675
676
677







-
+





-
+




-
+







    Tcl_MutexLock(allocMutexPtr);

    fprintf(stderr, "Memory allocation statistics %s\nTclpFree:\t", s);
    for (i = 0; i < NBUCKETS; i++) {
	for (j=0, overPtr=nextf[i]; overPtr; overPtr=overPtr->next, j++) {
	    fprintf(stderr, " %u", j);
	}
	totalFree += ((size_t)j) * (1 << (i + 3));
	totalFree += ((size_t)j) * ((size_t)1 << (i + 3));
    }

    fprintf(stderr, "\nused:\t");
    for (i = 0; i < NBUCKETS; i++) {
	fprintf(stderr, " %" TCL_Z_MODIFIER "u", numMallocs[i]);
	totalUsed += numMallocs[i] * (1 << (i + 3));
	totalUsed += numMallocs[i] * ((size_t)1 << (i + 3));
    }

    fprintf(stderr, "\n\tTotal small in use: %" TCL_Z_MODIFIER "u, total free: %" TCL_Z_MODIFIER "u\n",
	totalUsed, totalFree);
    fprintf(stderr, "\n\tNumber of big (>%d) blocks in use: %" TCL_Z_MODIFIER "u\n",
    fprintf(stderr, "\n\tNumber of big (>%" TCL_Z_MODIFIER "u) blocks in use: %" TCL_Z_MODIFIER "u\n",
	    MAXMALLOC, numMallocs[NBUCKETS]);

    Tcl_MutexUnlock(allocMutexPtr);
}
#endif

#else	/* !USE_TCLALLOC */
739
740
741
742
743
744
745
746

747
748
749
750
751


752
753
754
755
756
757
758
759
760
740
741
742
743
744
745
746

747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763







-
+





+
+









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

void *
TclpRealloc(
    void *oldPtr,		/* Pointer to alloced block. */
    size_t numBytes)	/* New size of memory. */
    size_t numBytes)		/* New size of memory. */
{
    return realloc(oldPtr, numBytes);
}

#endif /* !USE_TCLALLOC */
#else
TCL_MAC_EMPTY_FILE(generic_tclAlloc_c)
#endif /* !TCL_THREADS */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Added generic/tclArithSeries.c.




























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tclArithSeries.c --
 *
 *     This file contains the ArithSeries concrete abstract list
 *     implementation. It implements the inner workings of the lseq command.
 *
 * Copyright © 2022 Brian S. Griffin.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include <assert.h>
#include <math.h>

/*
 * The structure below defines the arithmetic series Tcl object type by
 * means of procedures that can be invoked by generic object code.
 *
 * The arithmetic series object is a special case of Tcl list representing
 * an interval of an arithmetic series in constant space.
 *
 * The arithmetic series is internally represented with three integers,
 * *start*, *end*, and *step*, Where the length is calculated with
 * the following algorithm:
 *
 * if RANGE == 0 THEN
 *   ERROR
 * if RANGE > 0
 *   LEN is (((END-START)-1)/STEP) + 1
 * else if RANGE < 0
 *   LEN is (((END-START)-1)/STEP) - 1
 *
 * And where the equivalent's list I-th element is calculated
 * as:
 *
 * LIST[i] = START + (STEP * i)
 *
 * Zero elements ranges, like in the case of START=10 END=10 STEP=1
 * are valid and will be equivalent to the empty list.
 */

/*
 * The structure used for the ArithSeries internal representation.
 * Note that the len can in theory be always computed by start,end,step
 * but it's faster to cache it inside the internal representation.
 */

typedef struct {
    Tcl_Size len;
    Tcl_Obj **elements;
    int isDouble;
} ArithSeries;

typedef struct {
    ArithSeries base;
    Tcl_WideInt start;
    Tcl_WideInt end;
    Tcl_WideInt step;
} ArithSeriesInt;

typedef struct {
    ArithSeries base;
    double start;
    double end;
    double step;
    unsigned precision;		/* Number of decimal places to render. */
} ArithSeriesDbl;

/* Forward declarations. */

static int		TclArithSeriesObjIndex(TCL_UNUSED(Tcl_Interp *),
			    Tcl_Obj *arithSeriesObj, Tcl_Size index,
			    Tcl_Obj **elemObj);
static Tcl_Size		ArithSeriesObjLength(Tcl_Obj *arithSeriesObj);
static int		TclArithSeriesObjRange(Tcl_Interp *interp,
			    Tcl_Obj *arithSeriesObj, Tcl_Size fromIdx,
			    Tcl_Size toIdx, Tcl_Obj **newObjPtr);
static int		TclArithSeriesObjReverse(Tcl_Interp *interp,
			    Tcl_Obj *arithSeriesObj, Tcl_Obj **newObjPtr);
static int		TclArithSeriesGetElements(Tcl_Interp *interp,
			    Tcl_Obj *objPtr, Tcl_Size *objcPtr,
			    Tcl_Obj ***objvPtr);
static void		DupArithSeriesInternalRep(Tcl_Obj *srcPtr,
			    Tcl_Obj *copyPtr);
static void		FreeArithSeriesInternalRep(Tcl_Obj *arithSeriesObjPtr);
static void		UpdateStringOfArithSeries(Tcl_Obj *arithSeriesObjPtr);
static int		SetArithSeriesFromAny(Tcl_Interp *interp,
			    Tcl_Obj *objPtr);
static int		ArithSeriesInOperation(Tcl_Interp *interp,
			    Tcl_Obj *valueObj, Tcl_Obj *arithSeriesObj,
			    int *boolResult);
static int		TclArithSeriesObjStep(Tcl_Obj *arithSeriesObj,
			    Tcl_Obj **stepObj);

/* ------------------------ ArithSeries object type -------------------------- */

static const Tcl_ObjType arithSeriesType = {
    "arithseries",			/* name */
    FreeArithSeriesInternalRep,		/* freeIntRepProc */
    DupArithSeriesInternalRep,		/* dupIntRepProc */
    UpdateStringOfArithSeries,		/* updateStringProc */
    SetArithSeriesFromAny,		/* setFromAnyProc */
    TCL_OBJTYPE_V2(
    ArithSeriesObjLength,
    TclArithSeriesObjIndex,
    TclArithSeriesObjRange,
    TclArithSeriesObjReverse,
    TclArithSeriesGetElements,
    NULL, // SetElement
    NULL, // Replace
    ArithSeriesInOperation) // "in" operator
};

/*
 * Helper functions
 *
 * - power10 -- Fast version of pow(10, (int) n) for common cases.
 * - ArithRound -- Round doubles to the number of significant fractional
 *                 digits
 * - ArithSeriesIndexDbl -- base list indexing operation for doubles
 * - ArithSeriesIndexInt --   "    "      "        "      "  integers
 * - ArithSeriesGetInternalRep -- Return the internal rep from a Tcl_Obj
 * - Precision -- determine the number of factional digits for the given
 *   double value
 * - maxPrecision -- Using the values provide, determine the longest percision
 *   in the arithSeries
 */

static inline double
power10(
    unsigned n)
{
    static const double powers[] = {
	1, 10, 100, 1000, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12,
	1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20
    };

    if (n < sizeof(powers) / sizeof(*powers)) {
	return powers[n];
    } else {
	// Not an expected case. Doesn't need to be so fast
	return pow(10, n);
    }
}

static inline double
ArithRound(
    double d,
    unsigned n)
{
    double scalefactor = power10(n);
    return round(d * scalefactor) / scalefactor;
}

static inline double
ArithSeriesIndexDbl(
    ArithSeries *arithSeriesRepPtr,
    Tcl_WideInt index)
{
    if (arithSeriesRepPtr->isDouble) {
	ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl *) arithSeriesRepPtr;
	double d = dblRepPtr->start + (index * dblRepPtr->step);

	return ArithRound(d, dblRepPtr->precision);
    } else {
	ArithSeriesInt *intRepPtr = (ArithSeriesInt *) arithSeriesRepPtr;
	return (double)(intRepPtr->start + (index * intRepPtr->step));
    }
}

static inline Tcl_WideInt
ArithSeriesIndexInt(
    ArithSeries *arithSeriesRepPtr,
    Tcl_WideInt index)
{
    if (arithSeriesRepPtr->isDouble) {
	ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl *) arithSeriesRepPtr;
	return (Tcl_WideInt) (dblRepPtr->start + (index * dblRepPtr->step));
    } else {
	ArithSeriesInt *intRepPtr = (ArithSeriesInt *) arithSeriesRepPtr;
	return intRepPtr->start + (index * intRepPtr->step);
    }
}

static inline ArithSeries *
ArithSeriesGetInternalRep(
    Tcl_Obj *objPtr)
{
    const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objPtr,
	    &arithSeriesType);
    return irPtr ? (ArithSeries *) irPtr->twoPtrValue.ptr1 : NULL;
}

/*
 * Compute number of significant fractional digits
 */
static inline unsigned
Precision(
    double d)
{
    char tmp[TCL_DOUBLE_SPACE + 2], *off;

    tmp[0] = 0;
    Tcl_PrintDouble(NULL, d, tmp);
    off = strchr(tmp, '.');
    return (off ? strlen(off + 1) : 0);
}

/*
 * Find longest number of digits after the decimal point.
 */
static inline unsigned
maxPrecision(
    double start,
    double end,
    double step)
{
    unsigned dp = Precision(step);
    unsigned i = Precision(start);

    dp = i>dp ? i : dp;
    i  = Precision(end);
    dp = i>dp ? i : dp;
    return dp;
}

/*
 *----------------------------------------------------------------------
 *
 * ArithSeriesLen --
 *
 *	Compute the length of the equivalent list where
 *	every element is generated starting from *start*,
 *	and adding *step* to generate every successive element
 *	that's < *end* for positive steps, or > *end* for negative
 *	steps.
 *
 * Results:
 *	The length of the list generated by the given range,
 *	that may be zero.
 *	The function returns -1 if the list is of length infinite.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
static Tcl_WideInt
ArithSeriesLenInt(
    Tcl_WideInt start,
    Tcl_WideInt end,
    Tcl_WideInt step)
{
    Tcl_WideInt len;

    if (step == 0) {
	return 0;
    }
    len = 1 + ((end - start) / step);
    return (len < 0) ? -1 : len;
}

static Tcl_WideInt
ArithSeriesLenDbl(
    double start,
    double end,
    double step,
    unsigned precision)
{
    double istart, iend, istep, ilen;

    if (step == 0) {
	return 0;
    }
    istart = start * power10(precision);
    iend = end * power10(precision);
    istep = step * power10(precision);
    ilen = (iend - istart + istep) / istep;
    return floor(ilen);
}

/*
 *----------------------------------------------------------------------
 *
 * DupArithSeriesInternalRep --
 *
 *	Initialize the internal representation of a arithseries Tcl_Obj to a
 *	copy of the internal representation of an existing arithseries object.
 *	The copy does not share the cache of the elements.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	We set "copyPtr"s internal rep to a pointer to a
 *	newly allocated ArithSeries structure.
 *
 *----------------------------------------------------------------------
 */

static void
DupArithSeriesInternalRep(
    Tcl_Obj *srcPtr,		/* Object with internal rep to copy. */
    Tcl_Obj *copyPtr)		/* Object with internal rep to set. */
{
    ArithSeries *srcRepPtr = (ArithSeries *)
	    srcPtr->internalRep.twoPtrValue.ptr1;

    if (srcRepPtr->isDouble) {
	ArithSeriesDbl *srcDblPtr = (ArithSeriesDbl *) srcRepPtr;
	ArithSeriesDbl *copyDblPtr = (ArithSeriesDbl *)
		Tcl_Alloc(sizeof(ArithSeriesDbl));

	*copyDblPtr = *srcDblPtr;
	copyDblPtr->base.elements = NULL;
	copyPtr->internalRep.twoPtrValue.ptr1 = copyDblPtr;
    } else {
	ArithSeriesInt *srcIntPtr = (ArithSeriesInt *) srcRepPtr;
	ArithSeriesInt *copyIntPtr = (ArithSeriesInt *)
		Tcl_Alloc(sizeof(ArithSeriesInt));

	*copyIntPtr = *srcIntPtr;
	copyIntPtr->base.elements = NULL;
	copyPtr->internalRep.twoPtrValue.ptr1 = copyIntPtr;
    }
    copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
    copyPtr->typePtr = &arithSeriesType;
}

/*
 *----------------------------------------------------------------------
 *
 * FreeArithSeriesInternalRep --
 *
 *	Free any allocated memory in the ArithSeries Rep
 *
 * Results:
 *	None.
 *
 * Side effects:
 *
 *----------------------------------------------------------------------
 */

static inline void
FreeElements(
    ArithSeries *arithSeriesRepPtr)
{
    if (arithSeriesRepPtr->elements) {
	Tcl_WideInt i, len = arithSeriesRepPtr->len;

	for (i=0; i<len; i++) {
	    Tcl_DecrRefCount(arithSeriesRepPtr->elements[i]);
	}
	Tcl_Free((char *) arithSeriesRepPtr->elements);
	arithSeriesRepPtr->elements = NULL;
    }
}

static void
FreeArithSeriesInternalRep(
    Tcl_Obj *arithSeriesObjPtr)
{
    ArithSeries *arithSeriesRepPtr = (ArithSeries *)
	    arithSeriesObjPtr->internalRep.twoPtrValue.ptr1;

    if (arithSeriesRepPtr) {
	FreeElements(arithSeriesRepPtr);
	Tcl_Free((char *) arithSeriesRepPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * NewArithSeriesInt --
 *
 *	Creates a new ArithSeries object. The returned object has
 *	refcount = 0.
 *
 * Results:
 *	A Tcl_Obj pointer to the created ArithSeries object.
 *	A NULL pointer of the range is invalid.
 *
 * Side Effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
static Tcl_Obj *
NewArithSeriesInt(
    Tcl_WideInt start,
    Tcl_WideInt end,
    Tcl_WideInt step,
    Tcl_WideInt len)
{
    Tcl_WideInt length;
    Tcl_Obj *arithSeriesObj;
    ArithSeriesInt *arithSeriesRepPtr;

    length = len>=0 ? len : -1;
    if (length < 0) {
	length = -1;
    }

    TclNewObj(arithSeriesObj);

    if (length <= 0) {
	return arithSeriesObj;
    }

    arithSeriesRepPtr = (ArithSeriesInt *) Tcl_Alloc(sizeof(ArithSeriesInt));
    arithSeriesRepPtr->base.len = length;
    arithSeriesRepPtr->base.elements = NULL;
    arithSeriesRepPtr->base.isDouble = 0;
    arithSeriesRepPtr->start = start;
    arithSeriesRepPtr->end = end;
    arithSeriesRepPtr->step = step;
    arithSeriesObj->internalRep.twoPtrValue.ptr1 = arithSeriesRepPtr;
    arithSeriesObj->internalRep.twoPtrValue.ptr2 = NULL;
    arithSeriesObj->typePtr = &arithSeriesType;
    if (length > 0) {
	Tcl_InvalidateStringRep(arithSeriesObj);
    }

    return arithSeriesObj;
}

/*
 *----------------------------------------------------------------------
 *
 * NewArithSeriesDbl --
 *
 *	Creates a new ArithSeries object with doubles. The returned object has
 *	refcount = 0.
 *
 * Results:
 *	A Tcl_Obj pointer to the created ArithSeries object.
 *	A NULL pointer of the range is invalid.
 *
 * Side Effects:
 *	None.
 *----------------------------------------------------------------------
 */
static Tcl_Obj *
NewArithSeriesDbl(
    double start,
    double end,
    double step,
    Tcl_WideInt len)
{
    Tcl_WideInt length;
    Tcl_Obj *arithSeriesObj;
    ArithSeriesDbl *arithSeriesRepPtr;

    length = len>=0 ? len : -1;
    if (length < 0) {
	length = -1;
    }

    TclNewObj(arithSeriesObj);

    if (length <= 0) {
	return arithSeriesObj;
    }

    arithSeriesRepPtr = (ArithSeriesDbl *) Tcl_Alloc(sizeof(ArithSeriesDbl));
    arithSeriesRepPtr->base.len = length;
    arithSeriesRepPtr->base.elements = NULL;
    arithSeriesRepPtr->base.isDouble = 1;
    arithSeriesRepPtr->start = start;
    arithSeriesRepPtr->end = end;
    arithSeriesRepPtr->step = step;
    arithSeriesRepPtr->precision = maxPrecision(start, end, step);
    arithSeriesObj->internalRep.twoPtrValue.ptr1 = arithSeriesRepPtr;
    arithSeriesObj->internalRep.twoPtrValue.ptr2 = NULL;
    arithSeriesObj->typePtr = &arithSeriesType;

    if (length > 0) {
	Tcl_InvalidateStringRep(arithSeriesObj);
    }

    return arithSeriesObj;
}

/*
 *----------------------------------------------------------------------
 *
 * assignNumber --
 *
 *	Create the appropriate Tcl_Obj value for the given numeric values.
 *      Used locally only for decoding [lseq] numeric arguments.
 *	refcount = 0.
 *
 * Results:
 *	A Tcl_Obj pointer.  No assignment on error.
 *
 * Side Effects:
 *	None.
 *----------------------------------------------------------------------
 */
static int
assignNumber(
    Tcl_Interp *interp,
    int useDoubles,
    Tcl_WideInt *intNumberPtr,
    double *dblNumberPtr,
    Tcl_Obj *numberObj)
{
    void *clientData;
    int tcl_number_type;

    if (Tcl_GetNumberFromObj(interp, numberObj, &clientData,
		&tcl_number_type) != TCL_OK) {
	return TCL_ERROR;
    }
    if (tcl_number_type == TCL_NUMBER_BIG) {
	/* bignum is not supported yet. */
	Tcl_WideInt w;
	(void)Tcl_GetWideIntFromObj(interp, numberObj, &w);
	return TCL_ERROR;
    }
    if (useDoubles) {
	if (tcl_number_type != TCL_NUMBER_INT) {
	    *dblNumberPtr = *(double *)clientData;
	} else {
	    *dblNumberPtr = (double)*(Tcl_WideInt *)clientData;
	}
    } else {
	if (tcl_number_type == TCL_NUMBER_INT) {
	    *intNumberPtr = *(Tcl_WideInt *)clientData;
	} else {
	    *intNumberPtr = (Tcl_WideInt)*(double *)clientData;
	}
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclNewArithSeriesObj --
 *
 *	Creates a new ArithSeries object. Some arguments may be NULL and will
 *	be computed based on the other given arguments.
 *      refcount = 0.
 *
 * Results:
 *	A Tcl_Obj pointer to the created ArithSeries object.
 *	NULL if the range is invalid.
 *
 * Side Effects:
 *	None.
 *----------------------------------------------------------------------
 */
Tcl_Obj *
TclNewArithSeriesObj(
    Tcl_Interp *interp,       /* For error reporting */
    int useDoubles,           /* Flag indicates values start,
			      ** end, step, are treated as doubles */
    Tcl_Obj *startObj,        /* Starting value */
    Tcl_Obj *endObj,          /* Ending limit */
    Tcl_Obj *stepObj,         /* increment value */
    Tcl_Obj *lenObj)          /* Number of elements */
{
    double dstart, dend, dstep;
    Tcl_WideInt start, end, step;
    Tcl_WideInt len = -1;
    Tcl_Obj *objPtr;

    if (startObj) {
	if (assignNumber(interp, useDoubles, &start, &dstart, startObj) != TCL_OK) {
	    return NULL;
	}
    } else {
	start = 0;
	dstart = start;
    }
    if (stepObj) {
	if (assignNumber(interp, useDoubles, &step, &dstep, stepObj) != TCL_OK) {
	    return NULL;
	}
	if (useDoubles) {
	    step = dstep;
	} else {
	    dstep = step;
	}
	if (dstep == 0) {
	    TclNewObj(objPtr);
	    return objPtr;
	}
    }
    if (endObj) {
	if (assignNumber(interp, useDoubles, &end, &dend, endObj) != TCL_OK) {
	    return NULL;
	}
    }
    if (lenObj) {
	if (TCL_OK != Tcl_GetWideIntFromObj(interp, lenObj, &len)) {
	    return NULL;
	}
    }

    if (startObj && endObj) {
	if (!stepObj) {
	    if (useDoubles) {
		dstep = (dstart < dend) ? 1.0 : -1.0;
		step = dstep;
	    } else {
		step = (start < end) ? 1 : -1;
		dstep = step;
	    }
	}
	assert(dstep!=0);
	if (!lenObj) {
	    if (useDoubles) {
		unsigned precision = maxPrecision(dstart, dend, dstep);
		len = ArithSeriesLenDbl(dstart, dend, dstep, precision);
	    } else {
		len = ArithSeriesLenInt(start, end, step);
	    }
	}
    }

    if (!endObj) {
	if (useDoubles) {
	    // Compute precision based on given command argument values
	    unsigned precision = maxPrecision(dstart, len, dstep);

	    dend = dstart + (dstep * (len-1));
	    // Make computed end value match argument(s) precision
	    dend = ArithRound(dend, precision);
	    end = dend;
	} else {
	    end = start + (step * (len - 1));
	    dend = end;
	}
    }

    if (len > TCL_SIZE_MAX) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"max length of a Tcl list exceeded", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
	return NULL;
    }

    objPtr = (useDoubles)
	    ? NewArithSeriesDbl(dstart, dend, dstep, len)
	    : NewArithSeriesInt(start, end, step, len);
    return objPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TclArithSeriesObjIndex --
 *
 *	Returns the element with the specified index in the list
 *	represented by the specified Arithmetic Sequence object.
 *	If the index is out of range, TCL_ERROR is returned,
 *	otherwise TCL_OK is returned and the integer value of the
 *	element is stored in *element.
 *
 * Results:
 *	TCL_OK on success.
 *
 * Side Effects:
 *	On success, the integer pointed by *element is modified.
 *	An empty string ("") is assigned if index is out-of-bounds.
 *
 *----------------------------------------------------------------------
 */
int
TclArithSeriesObjIndex(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Obj *arithSeriesObj,	/* List obj */
    Tcl_Size index,		/* index to element of interest */
    Tcl_Obj **elemObj)		/* Return value */
{
    ArithSeries *arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);

    if (index < 0 || arithSeriesRepPtr->len <= index) {
	*elemObj = NULL;
    } else {
	/* List[i] = Start + (Step * index) */
	if (arithSeriesRepPtr->isDouble) {
	    *elemObj = Tcl_NewDoubleObj(ArithSeriesIndexDbl(arithSeriesRepPtr, index));
	} else {
	    *elemObj = Tcl_NewWideIntObj(ArithSeriesIndexInt(arithSeriesRepPtr, index));
	}
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ArithSeriesObjLength
 *
 *	Returns the length of the arithmetic series.
 *
 * Results:
 *	The length of the series as Tcl_WideInt.
 *
 * Side Effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
Tcl_Size
ArithSeriesObjLength(
    Tcl_Obj *arithSeriesObj)
{
    ArithSeries *arithSeriesRepPtr = (ArithSeries *)
	    arithSeriesObj->internalRep.twoPtrValue.ptr1;
    return arithSeriesRepPtr->len;
}

/*
 *----------------------------------------------------------------------
 *
 * TclArithSeriesObjStep --
 *
 *	Return a Tcl_Obj with the step value from the give ArithSeries Obj.
 *	refcount = 0.
 *
 * Results:
 *	A Tcl_Obj pointer to the created ArithSeries object.
 *	A NULL pointer of the range is invalid.
 *
 * Side Effects:
 *	None.
 *----------------------------------------------------------------------
 */

int
TclArithSeriesObjStep(
    Tcl_Obj *arithSeriesObj,
    Tcl_Obj **stepObj)
{
    ArithSeries *arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);

    if (arithSeriesRepPtr->isDouble) {
	*stepObj = Tcl_NewDoubleObj(((ArithSeriesDbl *) arithSeriesRepPtr)->step);
    } else {
	*stepObj = Tcl_NewWideIntObj(((ArithSeriesInt *) arithSeriesRepPtr)->step);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * SetArithSeriesFromAny --
 *
 *	The Arithmetic Series object is just an way to optimize
 *	Lists space complexity, so no one should try to convert
 *	a string to an Arithmetic Series object.
 *
 *	This function is here just to populate the Type structure.
 *
 * Results:
 *	The result is always TCL_ERROR. But see Side Effects.
 *
 * Side effects:
 *	Tcl Panic if called.
 *
 *----------------------------------------------------------------------
 */

static int
SetArithSeriesFromAny(
    TCL_UNUSED(Tcl_Interp *),		/* Used for error reporting if not NULL. */
    TCL_UNUSED(Tcl_Obj *))		/* The object to convert. */
{
    Tcl_Panic("SetArithSeriesFromAny: should never be called");
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TclArithSeriesObjRange --
 *
 *	Makes a slice of an ArithSeries value.
 *      *arithSeriesObj must be known to be a valid list.
 *
 * Results:
 *	Returns a pointer to the sliced series.
 *      This may be a new object or the same object if not shared.
 *
 * Side effects:
 *	?The possible conversion of the object referenced by listPtr?
 *	?to a list object.?
 *
 *----------------------------------------------------------------------
 */

int
TclArithSeriesObjRange(
    Tcl_Interp *interp,         /* For error message(s) */
    Tcl_Obj *arithSeriesObj,	/* List object to take a range from. */
    Tcl_Size fromIdx,		/* Index of first element to include. */
    Tcl_Size toIdx,		/* Index of last element to include. */
    Tcl_Obj **newObjPtr)        /* return value */
{
    ArithSeries *arithSeriesRepPtr;
    Tcl_Obj *startObj, *endObj, *stepObj;

    (void)interp; /* silence compiler */

    arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);

    if (fromIdx == TCL_INDEX_NONE) {
	fromIdx = 0;
    }

    if (toIdx >= arithSeriesRepPtr->len) {
	toIdx = arithSeriesRepPtr->len-1;
    }

    if (fromIdx > toIdx || fromIdx >= arithSeriesRepPtr->len) {
	TclNewObj(*newObjPtr);
	return TCL_OK;
    }

    if (fromIdx < 0) {
	fromIdx = 0;
    }
    if (toIdx < 0) {
	toIdx = 0;
    }
    if (toIdx > arithSeriesRepPtr->len - 1) {
	toIdx = arithSeriesRepPtr->len - 1;
    }

    TclArithSeriesObjIndex(interp, arithSeriesObj, fromIdx, &startObj);
    Tcl_IncrRefCount(startObj);
    TclArithSeriesObjIndex(interp, arithSeriesObj, toIdx, &endObj);
    Tcl_IncrRefCount(endObj);
    TclArithSeriesObjStep(arithSeriesObj, &stepObj);
    Tcl_IncrRefCount(stepObj);

    if (Tcl_IsShared(arithSeriesObj) || ((arithSeriesObj->refCount > 1))) {
	Tcl_Obj *newSlicePtr = TclNewArithSeriesObj(interp,
	    arithSeriesRepPtr->isDouble, startObj, endObj, stepObj, NULL);
	*newObjPtr = newSlicePtr;
	Tcl_DecrRefCount(startObj);
	Tcl_DecrRefCount(endObj);
	Tcl_DecrRefCount(stepObj);
	return newSlicePtr ? TCL_OK : TCL_ERROR;
    }

    /*
     * In-place is possible.
     */

    /*
     * Even if nothing below causes any changes, we still want the
     * string-canonizing effect of [lrange 0 end].
     */

    TclInvalidateStringRep(arithSeriesObj);

    if (arithSeriesRepPtr->isDouble) {
	ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl *) arithSeriesRepPtr;
	double start, end, step;

	Tcl_GetDoubleFromObj(NULL, startObj, &start);
	Tcl_GetDoubleFromObj(NULL, endObj, &end);
	Tcl_GetDoubleFromObj(NULL, stepObj, &step);
	dblRepPtr->start = start;
	dblRepPtr->end = end;
	dblRepPtr->step = step;
	dblRepPtr->precision = maxPrecision(start, end, step);
	FreeElements(arithSeriesRepPtr);
	dblRepPtr->base.len =
		ArithSeriesLenDbl(start, end, step, dblRepPtr->precision);
    } else {
	ArithSeriesInt *intRepPtr = (ArithSeriesInt *) arithSeriesRepPtr;
	Tcl_WideInt start, end, step;

	Tcl_GetWideIntFromObj(NULL, startObj, &start);
	Tcl_GetWideIntFromObj(NULL, endObj, &end);
	Tcl_GetWideIntFromObj(NULL, stepObj, &step);
	intRepPtr->start = start;
	intRepPtr->end = end;
	intRepPtr->step = step;
	FreeElements(arithSeriesRepPtr);
	intRepPtr->base.len = ArithSeriesLenInt(start, end, step);
    }

    Tcl_DecrRefCount(startObj);
    Tcl_DecrRefCount(endObj);
    Tcl_DecrRefCount(stepObj);

    *newObjPtr = arithSeriesObj;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclArithSeriesGetElements --
 *
 *	This function returns an (objc,objv) array of the elements in a list
 *	object.
 *
 * Results:
 *	The return value is normally TCL_OK; in this case *objcPtr is set to
 *	the count of list elements and *objvPtr is set to a pointer to an
 *	array of (*objcPtr) pointers to each list element. If listPtr does not
 *	refer to an Abstract List object and the object can not be converted
 *	to one, TCL_ERROR is returned and an error message will be left in the
 *	interpreter's result if interp is not NULL.
 *
 *	The objects referenced by the returned array should be treated as
 *	readonly and their ref counts are _not_ incremented; the caller must
 *	do that if it holds on to a reference. Furthermore, the pointer and
 *	length returned by this function may change as soon as any function is
 *	called on the list object; be careful about retaining the pointer in a
 *	local data structure.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclArithSeriesGetElements(
    Tcl_Interp *interp,		/* Used to report errors if not NULL. */
    Tcl_Obj *objPtr,		/* ArithSeries object for which an element
				 * array is to be returned. */
    Tcl_Size *objcPtr,		/* Where to store the count of objects
				 * referenced by objv. */
    Tcl_Obj ***objvPtr)		/* Where to store the pointer to an array of
				 * pointers to the list's objects. */
{
    if (TclHasInternalRep(objPtr, &arithSeriesType)) {
	ArithSeries *arithSeriesRepPtr = ArithSeriesGetInternalRep(objPtr);
	Tcl_Obj **objv;
	Tcl_Size objc = arithSeriesRepPtr->len;

	if (objc > 0) {
	    if (arithSeriesRepPtr->elements) {
		/* If this exists, it has already been populated */
		objv = arithSeriesRepPtr->elements;
	    } else {
		/* Construct the elements array */
		objv = (Tcl_Obj **) Tcl_Alloc(sizeof(Tcl_Obj*) * objc);
		if (objv == NULL) {
		    if (interp) {
			Tcl_SetObjResult(interp, Tcl_NewStringObj(
				"max length of a Tcl list exceeded",
				TCL_AUTO_LENGTH));
			Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
		    }
		    return TCL_ERROR;
		}
		arithSeriesRepPtr->elements = objv;

		Tcl_Size i;
		for (i = 0; i < objc; i++) {
		    int status = TclArithSeriesObjIndex(interp, objPtr, i, &objv[i]);

		    if (status) {
			return TCL_ERROR;
		    }
		    Tcl_IncrRefCount(objv[i]);
		}
	    }
	} else {
	    objv = NULL;
	}
	*objvPtr = objv;
	*objcPtr = objc;
    } else {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "value is not an arithseries", TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "UNKNOWN", (char *)NULL);
	}
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclArithSeriesObjReverse --
 *
 *	Reverse the order of the ArithSeries value. The arithSeriesObj is
 *	assumed to be a valid ArithSeries. The new Obj has the Start and End
 *	values appropriately swapped and the Step value sign is changed.
 *
 * Results:
 *      The result will be an ArithSeries in the reverse order.
 *
 * Side effects:
 *      The ogiginal obj will be modified and returned if it is not Shared.
 *
 *----------------------------------------------------------------------
 */
int
TclArithSeriesObjReverse(
    Tcl_Interp *interp,         /* For error message(s) */
    Tcl_Obj *arithSeriesObj,	/* List object to reverse. */
    Tcl_Obj **newObjPtr)
{
    ArithSeries *arithSeriesRepPtr;
    Tcl_Obj *startObj, *endObj, *stepObj;
    Tcl_Obj *resultObj;
    Tcl_WideInt start, end, step, len;
    double dstart, dend, dstep;
    int isDouble;

    (void)interp;

    if (newObjPtr == NULL) {
	return TCL_ERROR;
    }

    arithSeriesRepPtr = ArithSeriesGetInternalRep(arithSeriesObj);

    isDouble = arithSeriesRepPtr->isDouble;
    len = arithSeriesRepPtr->len;

    TclArithSeriesObjIndex(NULL, arithSeriesObj, len - 1, &startObj);
    Tcl_IncrRefCount(startObj);
    TclArithSeriesObjIndex(NULL, arithSeriesObj, 0, &endObj);
    Tcl_IncrRefCount(endObj);
    TclArithSeriesObjStep(arithSeriesObj, &stepObj);
    Tcl_IncrRefCount(stepObj);

    if (isDouble) {
	Tcl_GetDoubleFromObj(NULL, startObj, &dstart);
	Tcl_GetDoubleFromObj(NULL, endObj, &dend);
	Tcl_GetDoubleFromObj(NULL, stepObj, &dstep);
	dstep = -dstep;
	TclSetDoubleObj(stepObj, dstep);
    } else {
	Tcl_GetWideIntFromObj(NULL, startObj, &start);
	Tcl_GetWideIntFromObj(NULL, endObj, &end);
	Tcl_GetWideIntFromObj(NULL, stepObj, &step);
	step = -step;
	TclSetIntObj(stepObj, step);
    }

    if (Tcl_IsShared(arithSeriesObj) || (arithSeriesObj->refCount > 1)) {
	Tcl_Obj *lenObj;

	TclNewIntObj(lenObj, len);
	resultObj = TclNewArithSeriesObj(interp, isDouble,
	    startObj, endObj, stepObj, lenObj);
	Tcl_DecrRefCount(lenObj);
    } else {
	/*
	 * In-place is possible.
	 */

	TclInvalidateStringRep(arithSeriesObj);

	if (isDouble) {
	    ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl *) arithSeriesRepPtr;

	    dblRepPtr->start = dstart;
	    dblRepPtr->end = dend;
	    dblRepPtr->step = dstep;
	} else {
	    ArithSeriesInt *intRepPtr = (ArithSeriesInt *) arithSeriesRepPtr;
	    intRepPtr->start = start;
	    intRepPtr->end = end;
	    intRepPtr->step = step;
	}
	FreeElements(arithSeriesRepPtr);
	resultObj = arithSeriesObj;
    }

    Tcl_DecrRefCount(startObj);
    Tcl_DecrRefCount(endObj);
    Tcl_DecrRefCount(stepObj);

    *newObjPtr = resultObj;

    return resultObj ? TCL_OK : TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * UpdateStringOfArithSeries --
 *
 *	Update the string representation for an arithseries object.
 *	Note: This procedure does not invalidate an existing old string rep
 *	so storage will be lost if this has not already been done.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The object's string is set to a valid string that results from
 *	the list-to-string conversion. This string will be empty if the
 *	list has no elements. The list internal representation
 *	should not be NULL and we assume it is not NULL.
 *
 * Notes:
 *	At the cost of overallocation it's possible to estimate
 *	the length of the string representation and make this procedure
 *	much faster. Because the programmer shouldn't expect the
 *	string conversion of a big arithmetic sequence to be fast
 *	this version takes more care of space than time.
 *
 *----------------------------------------------------------------------
 */
static void
UpdateStringOfArithSeries(
    Tcl_Obj *arithSeriesObjPtr)
{
    ArithSeries *arithSeriesRepPtr = (ArithSeries *)
	    arithSeriesObjPtr->internalRep.twoPtrValue.ptr1;
    char *p;
    Tcl_Obj *eleObj;
    Tcl_Size i, bytlen = 0;

    /*
     * Pass 1: estimate space.
     */
    if (!arithSeriesRepPtr->isDouble) {
	for (i = 0; i < arithSeriesRepPtr->len; i++) {
	    double d = ArithSeriesIndexInt(arithSeriesRepPtr, i);
	    size_t slen = d>0 ? log10(d)+1 : d<0 ? log10(-d)+2 : 1;

	    bytlen += slen;
	}
    } else {
	for (i = 0; i < arithSeriesRepPtr->len; i++) {
	    double d = ArithSeriesIndexDbl(arithSeriesRepPtr, i);
	    char tmp[TCL_DOUBLE_SPACE + 2];

	    tmp[0] = 0;
	    Tcl_PrintDouble(NULL,d,tmp);
	    if ((bytlen + strlen(tmp)) > TCL_SIZE_MAX) {
		break; // overflow
	    }
	    bytlen += strlen(tmp);
	}
    }
    bytlen += arithSeriesRepPtr->len; // Space for each separator

    /*
     * Pass 2: generate the string repr.
     */

    p = Tcl_InitStringRep(arithSeriesObjPtr, NULL, bytlen);
    for (i = 0; i < arithSeriesRepPtr->len; i++) {
	if (TclArithSeriesObjIndex(NULL, arithSeriesObjPtr, i, &eleObj) == TCL_OK) {
	    Tcl_Size slen;
	    char *str = TclGetStringFromObj(eleObj, &slen);

	    strcpy(p, str);
	    p[slen] = ' ';
	    p += slen + 1;
	    Tcl_DecrRefCount(eleObj);
	} // else TODO: report error here?
    }
    if (bytlen > 0) {
	arithSeriesObjPtr->bytes[bytlen - 1] = '\0';
    }
    arithSeriesObjPtr->length = bytlen - 1;
}

/*
 *----------------------------------------------------------------------
 *
 * ArithSeriesInOperator --
 *
 *	Evaluate the "in" operation for expr
 *
 *      This can be done more efficiently in the Arith Series relative to
 *      doing a linear search as implemented in expr.
 *
 * Results:
 *	Boolean true or false (1/0)
 *
 * Side effects:
 *      None
 *
 *----------------------------------------------------------------------
 */

static int
ArithSeriesInOperation(
    Tcl_Interp *interp,
    Tcl_Obj *valueObj,
    Tcl_Obj *arithSeriesObjPtr,
    int *boolResult)
{
    ArithSeries *repPtr = (ArithSeries *)
	    arithSeriesObjPtr->internalRep.twoPtrValue.ptr1;
    int status;
    Tcl_Size index, incr, elen, vlen;

    if (repPtr->isDouble) {
	ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl *) repPtr;
	double y;
	int test = 0;

	incr = 0; // Check index+incr where incr is 0 and 1
	status = Tcl_GetDoubleFromObj(interp, valueObj, &y);
	if (status != TCL_OK) {
	    test = 0;
	} else {
	    const char *vstr = TclGetStringFromObj(valueObj, &vlen);
	    index = (y - dblRepPtr->start) / dblRepPtr->step;
	    while (incr<2) {
		Tcl_Obj *elemObj;

		elen = 0;
		TclArithSeriesObjIndex(interp, arithSeriesObjPtr, (index+incr), &elemObj);

		const char *estr = elemObj ? TclGetStringFromObj(elemObj, &elen) : "";

		/* "in" operation defined as a string compare */
		test = (elen == vlen) ? (memcmp(estr, vstr, elen) == 0) : 0;
		Tcl_BounceRefCount(elemObj);
		/* Stop if we have a match */
		if (test) {
		    break;
		}
		incr++;
	    }
	}
	if (boolResult) {
	    *boolResult = test;
	}
    } else {
	ArithSeriesInt *intRepPtr = (ArithSeriesInt *) repPtr;
	Tcl_WideInt y;

	status = Tcl_GetWideIntFromObj(NULL, valueObj, &y);
	if (status != TCL_OK) {
	    if (boolResult) {
		*boolResult = 0;
	    }
	} else {
	    Tcl_Obj *elemObj;

	    elen = 0;
	    index = (y - intRepPtr->start) / intRepPtr->step;
	    TclArithSeriesObjIndex(interp, arithSeriesObjPtr, index, &elemObj);

	    char const *vstr = TclGetStringFromObj(valueObj, &vlen);
	    char const *estr = elemObj ? TclGetStringFromObj(elemObj, &elen) : "";

	    if (boolResult) {
		*boolResult = (elen == vlen) ? (memcmp(estr, vstr, elen) == 0) : 0;
	    }
	    Tcl_BounceRefCount(elemObj);
	}
    }
    return TCL_OK;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclAssembly.c.

1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17








-
-
+
+







/*
 * tclAssembly.c --
 *
 *	Assembler for Tcl bytecodes.
 *
 * This file contains the procedures that convert Tcl Assembly Language (TAL)
 * to a sequence of bytecode instructions for the Tcl execution engine.
 *
 * Copyright (c) 2010 by Ozgur Dogan Ugurlu.
 * Copyright (c) 2010 by Kevin B. Kenny.
 * Copyright © 2010 Ozgur Dogan Ugurlu.
 * Copyright © 2010 Kevin B. Kenny.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

/*-
 *- THINGS TO DO:
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
47
48
49
50
51
52
53

54
55
56
57
58
59
60
61







-
+







 * State identified for a basic block's catch context.
 */

typedef enum BasicBlockCatchState {
    BBCS_UNKNOWN = 0,		/* Catch context has not yet been identified */
    BBCS_NONE,			/* Block is outside of any catch */
    BBCS_INCATCH,		/* Block is within a catch context */
    BBCS_CAUGHT 		/* Block is within a catch context and
    BBCS_CAUGHT			/* Block is within a catch context and
				 * may be executed after an exception fires */
} BasicBlockCatchState;

/*
 * Structure that defines a basic block - a linear sequence of bytecode
 * instructions with no jumps in or out (including not changing the
 * state of any exception range).
218
219
220
221
222
223
224
225

226
227

228
229
230
231
232
233
234
218
219
220
221
222
223
224

225
226

227
228
229
230
231
232
233
234







-
+

-
+







typedef struct AssemblyEnv {
    CompileEnv* envPtr;		/* Compilation environment being used for code
				 * generation */
    Tcl_Parse* parsePtr;	/* Parse of the current line of source */
    Tcl_HashTable labelHash;	/* Hash table whose keys are labels and whose
				 * values are 'label' objects storing the code
				 * offsets of the labels. */
    int cmdLine;		/* Current line number within the assembly
    Tcl_Size cmdLine;	/* Current line number within the assembly
				 * code */
    int* clNext;		/* Invisible continuation line for
    Tcl_Size* clNext;	/* Invisible continuation line for
				 * [info frame] */
    BasicBlock* head_bb;	/* First basic block in the code */
    BasicBlock* curr_bb;	/* Current basic block */
    int maxDepth;		/* Maximum stack depth encountered */
    int curCatchDepth;		/* Current depth of catches */
    int maxCatchDepth;		/* Maximum depth of catches encountered */
    int flags;			/* Compilation flags (TCL_EVAL_DIRECT) */
273
274
275
276
277
278
279
280

281
282
283
284
285
286
287
273
274
275
276
277
278
279

280
281
282
283
284
285
286
287







-
+







static void		CompileEmbeddedScript(AssemblyEnv*, Tcl_Token*,
			    const TalInstDesc*);
static int		DefineLabel(AssemblyEnv* envPtr, const char* label);
static void		DeleteMirrorJumpTable(JumptableInfo* jtPtr);
static void		FillInJumpOffsets(AssemblyEnv*);
static int		CreateMirrorJumpTable(AssemblyEnv* assemEnvPtr,
			    Tcl_Obj* jumpTable);
static int		FindLocalVar(AssemblyEnv* envPtr,
static size_t	FindLocalVar(AssemblyEnv* envPtr,
			    Tcl_Token** tokenPtrPtr);
static int		FinishAssembly(AssemblyEnv*);
static void		FreeAssemblyEnv(AssemblyEnv*);
static int		GetBooleanOperand(AssemblyEnv*, Tcl_Token**, int*);
static int		GetListIndexOperand(AssemblyEnv*, Tcl_Token**, int*);
static int		GetIntegerOperand(AssemblyEnv*, Tcl_Token**, int*);
static int		GetNextOperand(AssemblyEnv*, Tcl_Token**, Tcl_Obj**);
321
322
323
324
325
326
327
328


329
330
331
332
333
334
335
321
322
323
324
325
326
327

328
329
330
331
332
333
334
335
336







-
+
+







static Tcl_DupInternalRepProc	DupAssembleCodeInternalRep;

static const Tcl_ObjType assembleCodeType = {
    "assemblecode",
    FreeAssembleCodeInternalRep, /* freeIntRepProc */
    DupAssembleCodeInternalRep,	 /* dupIntRepProc */
    NULL,			 /* updateStringProc */
    NULL			 /* setFromAnyProc */
    NULL,			 /* setFromAnyProc */
    TCL_OBJTYPE_V0
};

/*
 * Source instructions recognized in the Tcl Assembly Language (TAL)
 */

static const TalInstDesc TalInstructionTable[] = {
766
767
768
769
770
771
772
773

774
775
776
777
778
779
780
781
782
783
784
785
786
787
788

789
790
791
792
793
794
795
767
768
769
770
771
772
773

774
775
776
777
778
779
780
781
782
783
784
785
786
787
788

789
790
791
792
793
794
795
796







-
+














-
+







 *	include whatever the code does.
 *
 *-----------------------------------------------------------------------------
 */

int
Tcl_AssembleObjCmd(
    ClientData clientData,		/* clientData */
    void *clientData,		/* clientData */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    /*
     * Boilerplate - make sure that there is an NRE trampoline on the C stack
     * because there needs to be one in place to execute bytecode.
     */

    return Tcl_NRCallObjProc(interp, TclNRAssembleObjCmd, clientData, objc, objv);
}

int
TclNRAssembleObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    ByteCode *codePtr;		/* Pointer to the bytecode to execute */
    Tcl_Obj* backtrace;		/* Object where extra error information is
				 * constructed. */
852
853
854
855
856
857
858
859

860
861
862
863
864
865
866

867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883

884
885
886
887
888
889
890
853
854
855
856
857
858
859

860
861
862
863
864
865
866

867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883

884
885
886
887
888
889
890
891







-
+






-
+
















-
+







    CompileEnv compEnv;		/* Compilation environment structure */
    ByteCode *codePtr = NULL;
				/* Bytecode resulting from the assembly */
    Namespace* namespacePtr;	/* Namespace in which variable and command
				 * names in the bytecode resolve */
    int status;			/* Status return from Tcl_AssembleCode */
    const char* source;		/* String representation of the source code */
    size_t sourceLen;		/* Length of the source code in bytes */
    Tcl_Size sourceLen;		/* Length of the source code in bytes */

    /*
     * Get the expression ByteCode from the object. If it exists, make sure it
     * is valid in the current context.
     */

    ByteCodeGetIntRep(objPtr, &assembleCodeType, codePtr);
    ByteCodeGetInternalRep(objPtr, &assembleCodeType, codePtr);

    if (codePtr) {
	namespacePtr = iPtr->varFramePtr->nsPtr;
	if (((Interp *) *codePtr->interpHandle == iPtr)
		&& (codePtr->compileEpoch == iPtr->compileEpoch)
		&& (codePtr->nsPtr == namespacePtr)
		&& (codePtr->nsEpoch == namespacePtr->resolverEpoch)
		&& (codePtr->localCachePtr
			== iPtr->varFramePtr->localCachePtr)) {
	    return codePtr;
	}

	/*
	 * Not valid, so free it and regenerate.
	 */

	Tcl_StoreIntRep(objPtr, &assembleCodeType, NULL);
	Tcl_StoreInternalRep(objPtr, &assembleCodeType, NULL);
    }

    /*
     * Set up the compilation environment, and assemble the code.
     */

    source = TclGetStringFromObj(objPtr, &sourceLen);
917
918
919
920
921
922
923
924
925
926

927
928
929
930
931
932
933
934
935
936
918
919
920
921
922
923
924



925



926
927
928
929
930
931
932







-
-
-
+
-
-
-







	codePtr->localCachePtr->refCount++;
    }

    /*
     * Report on what the assembler did.
     */

#ifdef TCL_COMPILE_DEBUG
    if (tclTraceCompile >= 2) {
	TclPrintByteCodeObj(interp, objPtr);
    TclDebugPrintByteCodeObj(objPtr);
	fflush(stdout);
    }
#endif /* TCL_COMPILE_DEBUG */

    return codePtr;
}

/*
 *-----------------------------------------------------------------------------
 *
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
955
956
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







-
+

-
+



















-







    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    Tcl_Token *tokenPtr;	/* Token in the input script */

    int numCommands = envPtr->numCommands;
    size_t numCommands = envPtr->numCommands;
    int offset = envPtr->codeNext - envPtr->codeStart;
    int depth = envPtr->currStackDepth;
    size_t depth = envPtr->currStackDepth;
    /*
     * Make sure that the command has a single arg that is a simple word.
     */

    if (parsePtr->numWords != 2) {
	return TCL_ERROR;
    }
    tokenPtr = TokenAfter(parsePtr->tokenPtr);
    if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	return TCL_ERROR;
    }

    /*
     * Compile the code and convert any error from the compilation into
     * bytecode reporting the error;
     */

    if (TCL_ERROR == TclAssembleCode(envPtr, tokenPtr[1].start,
	    tokenPtr[1].size, TCL_EVAL_DIRECT)) {

	Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
		"\n    (\"%.*s\" body, line %d)",
		(int)parsePtr->tokenPtr->size, parsePtr->tokenPtr->start,
		Tcl_GetErrorLine(interp)));
	envPtr->numCommands = numCommands;
	envPtr->codeNext = envPtr->codeStart + offset;
	envPtr->currStackDepth = depth;
1264
1265
1266
1267
1268
1269
1270
1271

1272
1273
1274

1275
1276
1277
1278
1279
1280
1281
1259
1260
1261
1262
1263
1264
1265

1266
1267
1268

1269
1270
1271
1272
1273
1274
1275
1276







-
+


-
+







    Tcl_Obj* instNameObj;	/* Name of the instruction */
    int tblIdx;			/* Index in TalInstructionTable of the
				 * instruction */
    TalInstType instType;	/* Type of the instruction */
    Tcl_Obj* operand1Obj = NULL;
				/* First operand to the instruction */
    const char* operand1;	/* String rep of the operand */
    size_t operand1Len;		/* String length of the operand */
    Tcl_Size operand1Len;	/* String length of the operand */
    int opnd;			/* Integer representation of an operand */
    int litIndex;		/* Literal pool index of a constant */
    int localVar;		/* LVT index of a local variable */
    Tcl_Size localVar;	/* LVT index of a local variable */
    int flags;			/* Flags for a basic block */
    JumptableInfo* jtPtr;	/* Pointer to a jumptable */
    int infoIndex;		/* Index of the jumptable in auxdata */
    int status = TCL_ERROR;	/* Return value from this function */

    /*
     * Make sure that the instruction name is known at compile time.
1379
1380
1381
1382
1383
1384
1385
1386
1387


1388
1389
1390
1391
1392
1393
1394
1374
1375
1376
1377
1378
1379
1380


1381
1382
1383
1384
1385
1386
1387
1388
1389







-
-
+
+







	    goto cleanup;
	}
	if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK) {
	    goto cleanup;
	}
	if (opnd < 0 || opnd > 3) {
	    Tcl_SetObjResult(interp,
			     Tcl_NewStringObj("operand must be [0..3]", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "OPERAND<0,>3", NULL);
		     Tcl_NewStringObj("operand must be [0..3]", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "OPERAND<0,>3", (char *)NULL);
	    goto cleanup;
	}
	BBEmitInstInt1(assemEnvPtr, tblIdx, opnd, opnd);
	break;

    case ASSEM_CONCAT1:
	if (parsePtr->numWords != 2) {
1621
1622
1623
1624
1625
1626
1627
1628

1629
1630
1631
1632
1633
1634
1635
1616
1617
1618
1619
1620
1621
1622

1623
1624
1625
1626
1627
1628
1629
1630







-
+







	if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK) {
	    goto cleanup;
	}
	if (opnd < 2) {
	    if (assemEnvPtr->flags & TCL_EVAL_DIRECT) {
		Tcl_SetObjResult(interp,
			Tcl_NewStringObj("operand must be >=2", -1));
		Tcl_SetErrorCode(interp, "TCL", "ASSEM", "OPERAND>=2", NULL);
		Tcl_SetErrorCode(interp, "TCL", "ASSEM", "OPERAND>=2", (char *)NULL);
	    }
	    goto cleanup;
	}
	BBEmitInstInt4(assemEnvPtr, tblIdx, opnd, opnd);
	break;

    case ASSEM_LVT:
1807
1808
1809
1810
1811
1812
1813
1814
1815


1816
1817
1818
1819
1820
1821
1822

1823
1824
1825
1826
1827
1828
1829
1802
1803
1804
1805
1806
1807
1808


1809
1810
1811
1812
1813
1814
1815
1816

1817
1818
1819
1820
1821
1822
1823
1824







-
-
+
+






-
+







     *
     * Save away the stack depth and reset it before compiling the script.
     * We'll record the stack usage of the script in the BasicBlock, and
     * accumulate it together with the stack usage of the enclosing assembly
     * code.
     */

    int savedStackDepth = envPtr->currStackDepth;
    int savedMaxStackDepth = envPtr->maxStackDepth;
    size_t savedStackDepth = envPtr->currStackDepth;
    size_t savedMaxStackDepth = envPtr->maxStackDepth;
    int savedExceptArrayNext = envPtr->exceptArrayNext;

    envPtr->currStackDepth = 0;
    envPtr->maxStackDepth = 0;

    StartBasicBlock(assemEnvPtr, BB_FALLTHRU, NULL);
    switch(instPtr->tclInstCode) {
    switch (instPtr->tclInstCode) {
    case INST_EVAL_STK:
	TclCompileScript(interp, tokenPtr->start, tokenPtr->size, envPtr);
	break;
    case INST_EXPR_STK:
	TclCompileExpr(interp, tokenPtr->start, tokenPtr->size, envPtr, 1);
	break;
    default:
1931
1932
1933
1934
1935
1936
1937
1938

1939
1940
1941
1942
1943
1944
1945
1926
1927
1928
1929
1930
1931
1932

1933
1934
1935
1936
1937
1938
1939
1940







-
+







     */

    DEBUG_PRINT("basic block %p has %d exceptions starting at %d\n",
	    curr_bb, exceptionCount, savedExceptArrayNext);
    curr_bb->foreignExceptionBase = savedExceptArrayNext;
    curr_bb->foreignExceptionCount = exceptionCount;
    curr_bb->foreignExceptions =
    		(ExceptionRange*)Tcl_Alloc(exceptionCount * sizeof(ExceptionRange));
		(ExceptionRange*)Tcl_Alloc(exceptionCount * sizeof(ExceptionRange));
    memcpy(curr_bb->foreignExceptions,
	    envPtr->exceptArrayPtr + savedExceptArrayNext,
	    exceptionCount * sizeof(ExceptionRange));
    for (i = 0; i < exceptionCount; ++i) {
	curr_bb->foreignExceptions[i].nestingLevel -= envPtr->exceptDepth;
    }
    envPtr->exceptArrayNext = savedExceptArrayNext;
1964
1965
1966
1967
1968
1969
1970
1971

1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984

1985
1986

1987
1988
1989
1990
1991
1992
1993
1994

1995
1996



1997
1998
1999
2000
2001
2002
2003
1959
1960
1961
1962
1963
1964
1965

1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978

1979
1980

1981
1982
1983
1984
1985
1986
1987
1988

1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001







-
+












-
+

-
+







-
+


+
+
+







 */

static int
CreateMirrorJumpTable(
    AssemblyEnv* assemEnvPtr,	/* Assembly environment */
    Tcl_Obj* jumps)		/* List of alternating keywords and labels */
{
    int objc;			/* Number of elements in the 'jumps' list */
    Tcl_Size objc;			/* Number of elements in the 'jumps' list */
    Tcl_Obj** objv;		/* Pointers to the elements in the list */
    CompileEnv* envPtr = assemEnvPtr->envPtr;
				/* Compilation environment */
    Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr;
				/* Tcl interpreter */
    BasicBlock* bbPtr = assemEnvPtr->curr_bb;
				/* Current basic block */
    JumptableInfo* jtPtr;
    Tcl_HashTable* jtHashPtr;	/* Hashtable in the JumptableInfo */
    Tcl_HashEntry* hashEntry;	/* Entry for a key in the hashtable */
    int isNew;			/* Flag==1 if the key is not yet in the
				 * table. */
    int i;
    Tcl_Size i;

    if (Tcl_ListObjGetElements(interp, jumps, &objc, &objv) != TCL_OK) {
    if (TclListObjLength(interp, jumps, &objc) != TCL_OK) {
	return TCL_ERROR;
    }
    if (objc % 2 != 0) {
	if (assemEnvPtr->flags & TCL_EVAL_DIRECT) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "jump table must have an even number of list elements",
		    -1));
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADJUMPTABLE", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADJUMPTABLE", (char *)NULL);
	}
	return TCL_ERROR;
    }
    if (TclListObjGetElements(interp, jumps, &objc, &objv) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Allocate the jumptable.
     */

    jtPtr = (JumptableInfo*)Tcl_Alloc(sizeof(JumptableInfo));
2015
2016
2017
2018
2019
2020
2021
2022

2023
2024
2025
2026
2027
2028
2029
2013
2014
2015
2016
2017
2018
2019

2020
2021
2022
2023
2024
2025
2026
2027







-
+







	hashEntry = Tcl_CreateHashEntry(jtHashPtr, TclGetString(objv[i]),
		&isNew);
	if (!isNew) {
	    if (assemEnvPtr->flags & TCL_EVAL_DIRECT) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"duplicate entry in jump table for \"%s\"",
			TclGetString(objv[i])));
		Tcl_SetErrorCode(interp, "TCL", "ASSEM", "DUPJUMPTABLEENTRY");
		Tcl_SetErrorCode(interp, "TCL", "ASSEM", "DUPJUMPTABLEENTRY", (char *)NULL);
		DeleteMirrorJumpTable(jtPtr);
		return TCL_ERROR;
	    }
	}
	Tcl_SetHashValue(hashEntry, objv[i+1]);
	Tcl_IncrRefCount(objv[i+1]);
    }
2100
2101
2102
2103
2104
2105
2106
2107

2108
2109
2110
2111
2112
2113
2114
2098
2099
2100
2101
2102
2103
2104

2105
2106
2107
2108
2109
2110
2111
2112







-
+








    TclNewObj(operandObj);
    if (!TclWordKnownAtCompileTime(*tokenPtrPtr, operandObj)) {
	Tcl_DecrRefCount(operandObj);
	if (assemEnvPtr->flags & TCL_EVAL_DIRECT) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "assembly code may not contain substitutions", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NOSUBST", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NOSUBST", (char *)NULL);
	}
	return TCL_ERROR;
    }
    *tokenPtrPtr = TokenAfter(*tokenPtrPtr);
    Tcl_IncrRefCount(operandObj);
    *operandObjPtr = operandObj;
    return TCL_OK;
2239
2240
2241
2242
2243
2244
2245
2246

2247
2248
2249
2250
2251
2252
2253
2237
2238
2239
2240
2241
2242
2243

2244
2245
2246
2247
2248
2249
2250
2251







-
+







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

static int
GetListIndexOperand(
    AssemblyEnv* assemEnvPtr,	/* Assembly environment */
    Tcl_Token** tokenPtrPtr,	/* Current token from the parser */
    int* result)		/* OUTPUT: Integer extracted from the token */
    int* result)		/* OUTPUT: encoded index derived from the token */
{
    CompileEnv* envPtr = assemEnvPtr->envPtr;
				/* Compilation environment */
    Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr;
				/* Tcl interpreter */
    Tcl_Token* tokenPtr = *tokenPtrPtr;
				/* INOUT: Pointer to the next token in the
2291
2292
2293
2294
2295
2296
2297
2298

2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2289
2290
2291
2292
2293
2294
2295

2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309


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







-
+













-
-
+
+


-
+




-
+



-
+




-
+

-
+







 * Side effects:
 *	Advances the token pointer.  May define a new LVT slot if the variable
 *	has not yet been seen and the execution context allows for it.
 *
 *-----------------------------------------------------------------------------
 */

static int
static size_t
FindLocalVar(
    AssemblyEnv* assemEnvPtr,	/* Assembly environment */
    Tcl_Token** tokenPtrPtr)
{
    CompileEnv* envPtr = assemEnvPtr->envPtr;
				/* Compilation environment */
    Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr;
				/* Tcl interpreter */
    Tcl_Token* tokenPtr = *tokenPtrPtr;
				/* INOUT: Pointer to the next token in the
				 * source code. */
    Tcl_Obj* varNameObj;	/* Name of the variable */
    const char* varNameStr;
    size_t varNameLen;
    int localVar;		/* Index of the variable in the LVT */
    Tcl_Size varNameLen;
    Tcl_Size localVar;		/* Index of the variable in the LVT */

    if (GetNextOperand(assemEnvPtr, tokenPtrPtr, &varNameObj) != TCL_OK) {
	return -1;
	return TCL_INDEX_NONE;
    }
    varNameStr = TclGetStringFromObj(varNameObj, &varNameLen);
    if (CheckNamespaceQualifiers(interp, varNameStr, varNameLen)) {
	Tcl_DecrRefCount(varNameObj);
	return -1;
	return TCL_INDEX_NONE;
    }
    localVar = TclFindCompiledLocal(varNameStr, varNameLen, 1, envPtr);
    Tcl_DecrRefCount(varNameObj);
    if (localVar == -1) {
    if (localVar < 0) {
	if (assemEnvPtr->flags & TCL_EVAL_DIRECT) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "cannot use this instruction to create a variable"
		    " in a non-proc context", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "LVT", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "LVT", (char *)NULL);
	}
	return -1;
	return TCL_INDEX_NONE;
    }
    *tokenPtrPtr = TokenAfter(tokenPtr);
    return localVar;
}

/*
 *-----------------------------------------------------------------------------
2358
2359
2360
2361
2362
2363
2364
2365

2366
2367
2368
2369
2370
2371
2372
2356
2357
2358
2359
2360
2361
2362

2363
2364
2365
2366
2367
2368
2369
2370







-
+







{
    const char* p;

    for (p = name; p+2 < name+nameLen;  p++) {
	if ((*p == ':') && (p[1] == ':')) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "variable \"%s\" is not local", name));
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NONLOCAL", name, NULL);
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NONLOCAL", name, (char *)NULL);
	    return TCL_ERROR;
	}
    }
    return TCL_OK;
}

/*
2394
2395
2396
2397
2398
2399
2400
2401

2402
2403
2404
2405
2406
2407
2408
2392
2393
2394
2395
2396
2397
2398

2399
2400
2401
2402
2403
2404
2405
2406







-
+







    int value)			/* Value to check */
{
    Tcl_Obj* result;		/* Error message */

    if (value < 0 || value > 0xFF) {
	result = Tcl_NewStringObj("operand does not fit in one byte", -1);
	Tcl_SetObjResult(interp, result);
	Tcl_SetErrorCode(interp, "TCL", "ASSEM", "1BYTE", NULL);
	Tcl_SetErrorCode(interp, "TCL", "ASSEM", "1BYTE", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *-----------------------------------------------------------------------------
2429
2430
2431
2432
2433
2434
2435
2436

2437
2438
2439
2440
2441
2442
2443
2427
2428
2429
2430
2431
2432
2433

2434
2435
2436
2437
2438
2439
2440
2441







-
+







    int value)			/* Value to check */
{
    Tcl_Obj* result;		/* Error message */

    if (value > 0x7F || value < -0x80) {
	result = Tcl_NewStringObj("operand does not fit in one byte", -1);
	Tcl_SetObjResult(interp, result);
	Tcl_SetErrorCode(interp, "TCL", "ASSEM", "1BYTE", NULL);
	Tcl_SetErrorCode(interp, "TCL", "ASSEM", "1BYTE", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *-----------------------------------------------------------------------------
2462
2463
2464
2465
2466
2467
2468
2469

2470
2471
2472
2473
2474
2475
2476
2460
2461
2462
2463
2464
2465
2466

2467
2468
2469
2470
2471
2472
2473
2474







-
+







    int value)			/* Value to check */
{
    Tcl_Obj* result;		/* Error message */

    if (value < 0) {
	result = Tcl_NewStringObj("operand must be nonnegative", -1);
	Tcl_SetObjResult(interp, result);
	Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NONNEGATIVE", NULL);
	Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NONNEGATIVE", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *-----------------------------------------------------------------------------
2495
2496
2497
2498
2499
2500
2501
2502

2503
2504
2505
2506
2507
2508
2509
2493
2494
2495
2496
2497
2498
2499

2500
2501
2502
2503
2504
2505
2506
2507







-
+







    int value)			/* Value to check */
{
    Tcl_Obj* result;		/* Error message */

    if (value <= 0) {
	result = Tcl_NewStringObj("operand must be positive", -1);
	Tcl_SetObjResult(interp, result);
	Tcl_SetErrorCode(interp, "TCL", "ASSEM", "POSITIVE", NULL);
	Tcl_SetErrorCode(interp, "TCL", "ASSEM", "POSITIVE", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *-----------------------------------------------------------------------------
2547
2548
2549
2550
2551
2552
2553
2554

2555
2556
2557
2558
2559
2560
2561
2545
2546
2547
2548
2549
2550
2551

2552
2553
2554
2555
2556
2557
2558
2559







-
+







	 * This is a duplicate label.
	 */

	if (assemEnvPtr->flags & TCL_EVAL_DIRECT) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "duplicate definition of label \"%s\"", labelName));
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "DUPLABEL", labelName,
		    NULL);
		    (char *)NULL);
	}
	return TCL_ERROR;
    }

    /*
     * This is the first appearance of the label in the code.
     */
2948
2949
2950
2951
2952
2953
2954
2955

2956
2957
2958
2959
2960
2961
2962
2946
2947
2948
2949
2950
2951
2952

2953
2954
2955
2956
2957
2958
2959
2960







-
+







    Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr;
				/* Tcl interpreter */

    if (assemEnvPtr->flags & TCL_EVAL_DIRECT) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"undefined label \"%s\"", TclGetString(jumpTarget)));
	Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NOLABEL",
		TclGetString(jumpTarget), NULL);
		TclGetString(jumpTarget), (char *)NULL);
	Tcl_SetErrorLine(interp, bbPtr->jumpLine);
    }
}

/*
 *-----------------------------------------------------------------------------
 *
3233
3234
3235
3236
3237
3238
3239
3240

3241
3242
3243
3244
3245
3246
3247
3231
3232
3233
3234
3235
3236
3237

3238
3239
3240
3241
3242
3243
3244
3245







-
+








	    if (assemEnvPtr->flags & TCL_EVAL_DIRECT) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"\"%s\" instruction may not appear in "
			"a context where an exception has been "
			"caught and not disposed of.",
			tclInstructionTable[opcode].name));
		Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADTHROW", NULL);
		Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADTHROW", (char *)NULL);
		AddBasicBlockRangeToErrorInfo(assemEnvPtr, blockPtr);
	    }
	    return TCL_ERROR;
	}
	offset += tclInstructionTable[opcode].numBytes;
    }
    return TCL_OK;
3313
3314
3315
3316
3317
3318
3319
3320

3321
3322
3323
3324
3325
3326
3327
3311
3312
3313
3314
3315
3316
3317

3318
3319
3320
3321
3322
3323
3324
3325







-
+








static int
CheckStack(
    AssemblyEnv* assemEnvPtr)	/* Assembly environment */
{
    CompileEnv* envPtr = assemEnvPtr->envPtr;
				/* Compilation environment */
    int maxDepth;		/* Maximum stack depth overall */
    Tcl_Size maxDepth;		/* Maximum stack depth overall */

    /*
     * Checking the head block will check all the other blocks recursively.
     */

    assemEnvPtr->maxDepth = 0;
    if (StackCheckBasicBlock(assemEnvPtr, assemEnvPtr->head_bb, NULL,
3413
3414
3415
3416
3417
3418
3419
3420

3421
3422
3423
3424
3425
3426
3427
3411
3412
3413
3414
3415
3416
3417

3418
3419
3420
3421
3422
3423
3424
3425







-
+







		    "inconsistent stack depths on two execution paths", -1));

	    /*
	     * TODO - add execution trace of both paths
	     */

	    Tcl_SetErrorLine(interp, blockPtr->startLine);
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACK", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACK", (char *)NULL);
	}
	return TCL_ERROR;
    }

    /*
     * If the block is not already visited, set the 'predecessor' link to
     * indicate how control got to it. Set the initial stack depth to the
3436
3437
3438
3439
3440
3441
3442
3443

3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462

3463
3464
3465
3466
3467
3468
3469
3434
3435
3436
3437
3438
3439
3440

3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459

3460
3461
3462
3463
3464
3465
3466
3467







-
+


















-
+







     * Calculate minimum stack depth, and flag an error if the block
     * underflows the stack.
     */

    if (initialStackDepth + blockPtr->minStackDepth < 0) {
	if (assemEnvPtr->flags & TCL_EVAL_DIRECT) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj("stack underflow", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACK", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACK", (char *)NULL);
	    AddBasicBlockRangeToErrorInfo(assemEnvPtr, blockPtr);
	    Tcl_SetErrorLine(interp, blockPtr->startLine);
	}
	return TCL_ERROR;
    }

    /*
     * Make sure that the block doesn't try to pop below the stack level of an
     * enclosing catch.
     */

    if (blockPtr->enclosingCatch != 0 &&
	    initialStackDepth + blockPtr->minStackDepth
	    < (blockPtr->enclosingCatch->initialStackDepth
		+ blockPtr->enclosingCatch->finalStackDepth)) {
	if (assemEnvPtr->flags & TCL_EVAL_DIRECT) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "code pops stack below level of enclosing catch", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACKINCATCH", -1);
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACKINCATCH", (char *)NULL);
	    AddBasicBlockRangeToErrorInfo(assemEnvPtr, blockPtr);
	    Tcl_SetErrorLine(interp, blockPtr->startLine);
	}
	return TCL_ERROR;
    }

    /*
3583
3584
3585
3586
3587
3588
3589
3590

3591
3592
3593
3594
3595
3596
3597
3581
3582
3583
3584
3585
3586
3587

3588
3589
3590
3591
3592
3593
3594
3595







-
+







	 */

	if (depth != 1) {
	    if (assemEnvPtr->flags & TCL_EVAL_DIRECT) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"stack is unbalanced on exit from the code (depth=%d)",
			depth));
		Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACK", NULL);
		Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACK", (char *)NULL);
	    }
	    return TCL_ERROR;
	}

	/*
	 * Record stack usage.
	 */
3728
3729
3730
3731
3732
3733
3734
3735

3736
3737
3738
3739
3740
3741
3742
3726
3727
3728
3729
3730
3731
3732

3733
3734
3735
3736
3737
3738
3739
3740







-
+







	bbPtr->enclosingCatch = enclosing;
    } else if (bbPtr->enclosingCatch != enclosing) {
	if (assemEnvPtr->flags & TCL_EVAL_DIRECT) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "execution reaches an instruction in inconsistent "
		    "exception contexts", -1));
	    Tcl_SetErrorLine(interp, bbPtr->startLine);
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADCATCH", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADCATCH", (char *)NULL);
	}
	return TCL_ERROR;
    }
    if (state > bbPtr->catchState) {
	bbPtr->catchState = state;
	changed = 1;
    }
3787
3788
3789
3790
3791
3792
3793
3794

3795
3796
3797
3798
3799
3800
3801
3785
3786
3787
3788
3789
3790
3791

3792
3793
3794
3795
3796
3797
3798
3799







-
+







	 */

	if (enclosing == NULL) {
	    if (assemEnvPtr->flags & TCL_EVAL_DIRECT) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"endCatch without a corresponding beginCatch", -1));
		Tcl_SetErrorLine(interp, bbPtr->startLine);
		Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADENDCATCH", NULL);
		Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADENDCATCH", (char *)NULL);
	    }
	    return TCL_ERROR;
	}
	fallThruEnclosing = enclosing->enclosingCatch;
	fallThruState = enclosing->catchState;
	--catchDepth;
    }
3863
3864
3865
3866
3867
3868
3869
3870

3871
3872
3873
3874
3875
3876
3877
3861
3862
3863
3864
3865
3866
3867

3868
3869
3870
3871
3872
3873
3874
3875







-
+








    if (assemEnvPtr->curr_bb->catchState >= BBCS_INCATCH) {
	if (assemEnvPtr->flags & TCL_EVAL_DIRECT) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "catch still active on exit from assembly code", -1));
	    Tcl_SetErrorLine(interp,
		    assemEnvPtr->curr_bb->enclosingCatch->startLine);
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "UNCLOSEDCATCH", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "ASSEM", "UNCLOSEDCATCH", (char *)NULL);
	}
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
4122
4123
4124
4125
4126
4127
4128
4129

4130
4131
4132
4133
4134
4135
4136
4120
4121
4122
4123
4124
4125
4126

4127
4128
4129
4130
4131
4132
4133
4134







-
+







	     */

	    block = catches[catchDepth];
	    catchIndices[catchDepth] =
		    TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr);
	    range = envPtr->exceptArrayPtr + catchIndices[catchDepth];
	    range->nestingLevel = envPtr->exceptDepth + catchDepth;
	    envPtr->maxExceptDepth =
	    envPtr->maxExceptDepth=
		    TclMax(range->nestingLevel + 1, envPtr->maxExceptDepth);
	    range->codeOffset = bbPtr->startOffset;

	    entryPtr = Tcl_FindHashEntry(&assemEnvPtr->labelHash,
		    TclGetString(block->jumpTarget));
	    if (entryPtr == NULL) {
		Tcl_Panic("undefined label in tclAssembly.c:"
4159
4160
4161
4162
4163
4164
4165
4166

4167
4168
4169
4170
4171
4172
4173
4157
4158
4159
4160
4161
4162
4163

4164
4165
4166
4167
4168
4169
4170
4171







-
+







    AssemblyEnv* assemEnvPtr)	/* Assembly environment */
{
    CompileEnv* envPtr = assemEnvPtr->envPtr;
				/* Compilation environment */
    BasicBlock* bbPtr;		/* Current basic block */
    int rangeBase;		/* Base of the foreign exception ranges when
				 * they are reinstalled */
    int rangeIndex;		/* Index of the current foreign exception
    size_t rangeIndex;		/* Index of the current foreign exception
				 * range as reinstalled */
    ExceptionRange* range;	/* Current foreign exception range */
    unsigned char opcode;	/* Current instruction's opcode */
    int catchIndex;		/* Index of the exception range to which the
				 * current instruction refers */
    int i;

4186
4187
4188
4189
4190
4191
4192
4193

4194
4195
4196
4197
4198
4199
4200
4184
4185
4186
4187
4188
4189
4190

4191
4192
4193
4194
4195
4196
4197
4198







-
+







	    rangeBase = envPtr->exceptArrayNext;
	    for (i = 0; i < bbPtr->foreignExceptionCount; ++i) {
		range = bbPtr->foreignExceptions + i;
		rangeIndex = TclCreateExceptRange(range->type, envPtr);
		range->nestingLevel += envPtr->exceptDepth + bbPtr->catchDepth;
		memcpy(envPtr->exceptArrayPtr + rangeIndex, range,
			sizeof(ExceptionRange));
		if (range->nestingLevel >= envPtr->maxExceptDepth) {
		if (range->nestingLevel + 1 >= envPtr->maxExceptDepth + 1) {
		    envPtr->maxExceptDepth = range->nestingLevel + 1;
		}
	    }

	    /*
	     * Walk through the bytecode of the basic block, and relocate
	     * INST_BEGIN_CATCH4 instructions to the new locations
4283
4284
4285
4286
4287
4288
4289
4290

4291
4292
4293
4294
4295
4296
4297
4298
4299

4300
4301
4302
4303
4304
4305
4306
4281
4282
4283
4284
4285
4286
4287

4288
4289
4290
4291
4292
4293
4294
4295
4296

4297
4298
4299
4300
4301
4302
4303
4304







-
+








-
+








/*
 *-----------------------------------------------------------------------------
 *
 * DupAssembleCodeInternalRep --
 *
 *	Part of the Tcl object type implementation for Tcl assembly language
 *	bytecode. We do not copy the bytecode intrep. Instead, we return
 *	bytecode. We do not copy the bytecode internalrep. Instead, we return
 *	without setting copyPtr->typePtr, so the copy is a plain string copy
 *	of the assembly source, and if it is to be used as a compiled
 *	expression, it will need to be reprocessed.
 *
 *	This makes sense, because with Tcl's copy-on-write practices, the
 *	usual (only?) time Tcl_DuplicateObj() will be called is when the copy
 *	is about to be modified, which would invalidate any copied bytecode
 *	anyway. The only reason it might make sense to copy the bytecode is if
 *	we had some modifying routines that operated directly on the intrep,
 *	we had some modifying routines that operated directly on the internalrep,
 *	as we do for lists and dicts.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
4336
4337
4338
4339
4340
4341
4342
4343

4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4334
4335
4336
4337
4338
4339
4340

4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353







-
+













static void
FreeAssembleCodeInternalRep(
    Tcl_Obj *objPtr)
{
    ByteCode *codePtr;

    ByteCodeGetIntRep(objPtr, &assembleCodeType, codePtr);
    ByteCodeGetInternalRep(objPtr, &assembleCodeType, codePtr);
    assert(codePtr != NULL);

    TclReleaseByteCode(codePtr);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclAsync.c.

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
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
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
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







-
-
+
+


















-
-
-
+
+
+


-
+







+



-
-
-
-
-
-
-










-
-


+
+
+
+
+
+
+






-
+






-
+







+
+
-
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+







/*
 * tclAsync.c --
 *
 *	This file provides low-level support needed to invoke signal handlers
 *	in a safe way. The code here doesn't actually handle signals, though.
 *	This code is based on proposals made by Mark Diekhans and Don Libes.
 *
 * Copyright (c) 1993 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 * Copyright © 1993 The Regents of the University of California.
 * Copyright © 1994 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

/* Forward declaration */
struct ThreadSpecificData;

/*
 * One of the following structures exists for each asynchronous handler:
 */

typedef struct AsyncHandler {
    int ready;			/* Non-zero means this handler should be
				 * invoked in the next call to
				 * Tcl_AsyncInvoke. */
    struct AsyncHandler *nextPtr;
				/* Next in list of all handlers for the
				 * process. */
    struct AsyncHandler *nextPtr, *prevPtr;
				/* Next, previous in list of all handlers
				 * for the process. */
    Tcl_AsyncProc *proc;	/* Procedure to call when handler is
				 * invoked. */
    ClientData clientData;	/* Value to pass to handler when it is
    void *clientData;	/* Value to pass to handler when it is
				 * invoked. */
    struct ThreadSpecificData *originTsd;
				/* Used in Tcl_AsyncMark to modify thread-
				 * specific data from outside the thread it is
				 * associated to. */
    Tcl_ThreadId originThrdId;	/* Origin thread where this token was created
				 * and where it will be yielded. */
    void *notifierData;	/* Platform notifier data or NULL. */
} AsyncHandler;

typedef struct ThreadSpecificData {
    /*
     * The variables below maintain a list of all existing handlers specific
     * to the calling thread.
     */
    AsyncHandler *firstHandler;	/* First handler defined for process, or NULL
				 * if none. */
    AsyncHandler *lastHandler;	/* Last handler or NULL. */
    int asyncReady;		/* This is set to 1 whenever a handler becomes
				 * ready and it is cleared to zero whenever
				 * Tcl_AsyncInvoke is called. It can be
				 * checked elsewhere in the application by
				 * calling Tcl_AsyncReady to see if
				 * Tcl_AsyncInvoke should be invoked. */
    int asyncActive;		/* Indicates whether Tcl_AsyncInvoke is
				 * currently working. If so then we won't set
				 * asyncReady again until Tcl_AsyncInvoke
				 * returns. */
    Tcl_Mutex asyncMutex;	/* Thread-specific AsyncHandler linked-list
				 * lock */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;

/* Mutex to protect linked-list of AsyncHandlers in the process. */
TCL_DECLARE_MUTEX(asyncMutex)

/* List of all existing handlers of the process. */
static AsyncHandler *firstHandler = NULL;
static AsyncHandler *lastHandler = NULL;

/*
 *----------------------------------------------------------------------
 *
 * TclFinalizeAsync --
 *
 *	Finalizes the mutex in the thread local data structure for the async
 *	Finalizes the thread local data structure for the async
 *	subsystem.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Forgets knowledge of the mutex should it have been created.
 *	Cleans up left-over async handlers for the calling thread.
 *
 *----------------------------------------------------------------------
 */

void
TclFinalizeAsync(void)
{
    AsyncHandler *token, *toDelete = NULL;
    Tcl_ThreadId self = Tcl_GetCurrentThread();
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    Tcl_MutexLock(&asyncMutex);
    for (token = firstHandler; token != NULL;) {
	AsyncHandler *nextToken = token->nextPtr;

	if (token->originThrdId == self) {
	    if (token->prevPtr == NULL) {
		firstHandler = token->nextPtr;
		if (firstHandler == NULL) {
		    lastHandler = NULL;
		    break;
		}
	    } else {
		token->prevPtr->nextPtr = token->nextPtr;
		if (token == lastHandler) {
		    lastHandler = token->prevPtr;
		}
	    }
    if (tsdPtr->asyncMutex != NULL) {
	Tcl_MutexFinalize(&tsdPtr->asyncMutex);
	    if (token->nextPtr != NULL) {
		token->nextPtr->prevPtr = token->prevPtr;
	    }
	    token->nextPtr = toDelete;
	    token->prevPtr = NULL;
	    toDelete = token;
	}
	token = nextToken;
    }
    Tcl_MutexUnlock(&asyncMutex);
    while (toDelete != NULL) {
	token = toDelete;
	toDelete = toDelete->nextPtr;
	Tcl_Free(token);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AsyncCreate --
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
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







-
+







+




+

-
-
-
+
+
+

+
-
+

-
-
+
+







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

Tcl_AsyncHandler
Tcl_AsyncCreate(
    Tcl_AsyncProc *proc,	/* Procedure to call when handler is
				 * invoked. */
    ClientData clientData)	/* Argument to pass to handler. */
    void *clientData)	/* Argument to pass to handler. */
{
    AsyncHandler *asyncPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    asyncPtr = (AsyncHandler*)Tcl_Alloc(sizeof(AsyncHandler));
    asyncPtr->ready = 0;
    asyncPtr->nextPtr = NULL;
    asyncPtr->prevPtr = NULL;
    asyncPtr->proc = proc;
    asyncPtr->clientData = clientData;
    asyncPtr->originTsd = tsdPtr;
    asyncPtr->originThrdId = Tcl_GetCurrentThread();
    asyncPtr->notifierData = TclpNotifierData();

    Tcl_MutexLock(&tsdPtr->asyncMutex);
    if (tsdPtr->firstHandler == NULL) {
	tsdPtr->firstHandler = asyncPtr;
    Tcl_MutexLock(&asyncMutex);
    if (firstHandler == NULL) {
	firstHandler = asyncPtr;
    } else {
	asyncPtr->prevPtr = lastHandler;
	tsdPtr->lastHandler->nextPtr = asyncPtr;
	lastHandler->nextPtr = asyncPtr;
    }
    tsdPtr->lastHandler = asyncPtr;
    Tcl_MutexUnlock(&tsdPtr->asyncMutex);
    lastHandler = asyncPtr;
    Tcl_MutexUnlock(&asyncMutex);
    return (Tcl_AsyncHandler) asyncPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AsyncMark --
158
159
160
161
162
163
164
165

166
167
168
169
170
171










































































172
173
174
175
176
177
178
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







-
+





-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








void
Tcl_AsyncMark(
    Tcl_AsyncHandler async)		/* Token for handler. */
{
    AsyncHandler *token = (AsyncHandler *) async;

    Tcl_MutexLock(&token->originTsd->asyncMutex);
    Tcl_MutexLock(&asyncMutex);
    token->ready = 1;
    if (!token->originTsd->asyncActive) {
	token->originTsd->asyncReady = 1;
	Tcl_ThreadAlert(token->originThrdId);
    }
    Tcl_MutexUnlock(&token->originTsd->asyncMutex);
    Tcl_MutexUnlock(&asyncMutex);

}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AsyncMarkFromSignal --
 *
 *	This procedure is similar to Tcl_AsyncMark but must be used
 *	in POSIX signal contexts. In addition to Tcl_AsyncMark the
 *	signal number is passed.
 *
 * Results:
 *	True, when the handler will be marked, false otherwise.
 *
 * Side effects:
 *	The handler gets marked for invocation later.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_AsyncMarkFromSignal(
    Tcl_AsyncHandler async,		/* Token for handler. */
    int sigNumber)			/* Signal number. */
{
#if TCL_THREADS
    AsyncHandler *token = (AsyncHandler *) async;

    return TclAsyncNotifier(sigNumber, token->originThrdId,
	    token->notifierData, &token->ready, -1);
#else
    (void)sigNumber;

    Tcl_AsyncMark(async);
    return 1;
#endif
}

/*
 *----------------------------------------------------------------------
 *
 * TclAsyncMarkFromNotifier --
 *
 *	This procedure is called from the notifier thread and
 *	invokes Tcl_AsyncMark for specifically marked handlers.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Handlers get marked for invocation later.
 *
 *----------------------------------------------------------------------
 */

void
TclAsyncMarkFromNotifier(void)
{
    AsyncHandler *token;

    Tcl_MutexLock(&asyncMutex);
    for (token = firstHandler; token != NULL;
	    token = token->nextPtr) {
	if (token->ready == -1) {
	    token->ready = 1;
	    if (!token->originTsd->asyncActive) {
		token->originTsd->asyncReady = 1;
		Tcl_ThreadAlert(token->originThrdId);
	    }
	}
    }
    Tcl_MutexUnlock(&asyncMutex);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AsyncInvoke --
 *
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
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







+

-
+


-
+



















-
+

+
+
+








-
+

-
+


-
+







				 * interpreter. Otherwise it is NULL. */
    int code)			/* If interp is non-NULL, this gives
				 * completion code from command that just
				 * completed. */
{
    AsyncHandler *asyncPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    Tcl_ThreadId self = Tcl_GetCurrentThread();

    Tcl_MutexLock(&tsdPtr->asyncMutex);
    Tcl_MutexLock(&asyncMutex);

    if (tsdPtr->asyncReady == 0) {
	Tcl_MutexUnlock(&tsdPtr->asyncMutex);
	Tcl_MutexUnlock(&asyncMutex);
	return code;
    }
    tsdPtr->asyncReady = 0;
    tsdPtr->asyncActive = 1;
    if (interp == NULL) {
	code = 0;
    }

    /*
     * Make one or more passes over the list of handlers, invoking at most one
     * handler in each pass. After invoking a handler, go back to the start of
     * the list again so that (a) if a new higher-priority handler gets marked
     * while executing a lower priority handler, we execute the higher-
     * priority handler next, and (b) if a handler gets deleted during the
     * execution of a handler, then the list structure may change so it isn't
     * safe to continue down the list anyway.
     */

    while (1) {
	for (asyncPtr = tsdPtr->firstHandler; asyncPtr != NULL;
	for (asyncPtr = firstHandler; asyncPtr != NULL;
		asyncPtr = asyncPtr->nextPtr) {
	    if (asyncPtr->originThrdId != self) {
		continue;
	    }
	    if (asyncPtr->ready) {
		break;
	    }
	}
	if (asyncPtr == NULL) {
	    break;
	}
	asyncPtr->ready = 0;
	Tcl_MutexUnlock(&tsdPtr->asyncMutex);
	Tcl_MutexUnlock(&asyncMutex);
	code = asyncPtr->proc(asyncPtr->clientData, interp, code);
	Tcl_MutexLock(&tsdPtr->asyncMutex);
	Tcl_MutexLock(&asyncMutex);
    }
    tsdPtr->asyncActive = 0;
    Tcl_MutexUnlock(&tsdPtr->asyncMutex);
    Tcl_MutexUnlock(&asyncMutex);
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AsyncDelete --
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
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







-

-









-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
+
-
-
-
+
+

-
-
-
-
+
+
-
-
-
+
+


+
+
+
-
+







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

void
Tcl_AsyncDelete(
    Tcl_AsyncHandler async)		/* Token for handler to delete. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    AsyncHandler *asyncPtr = (AsyncHandler *) async;
    AsyncHandler *prevPtr, *thisPtr;

    /*
     * Assure early handling of the constraint
     */

    if (asyncPtr->originThrdId != Tcl_GetCurrentThread()) {
	Tcl_Panic("Tcl_AsyncDelete: async handler deleted by the wrong thread");
    }

    /*
     * If we come to this point when TSD's for the current
     * thread have already been garbage-collected, we are
     * in the _serious_ trouble. OTOH, we tolerate calling
     * with already cleaned-up handler list (should we?).
     */

    Tcl_MutexLock(&tsdPtr->asyncMutex);
    Tcl_MutexLock(&asyncMutex);
    if (tsdPtr->firstHandler != NULL) {
	prevPtr = thisPtr = tsdPtr->firstHandler;
	while (thisPtr != NULL && thisPtr != asyncPtr) {
	    prevPtr = thisPtr;
	    thisPtr = thisPtr->nextPtr;
    if (asyncPtr->prevPtr == NULL) {
	firstHandler = asyncPtr->nextPtr;
	}
	if (thisPtr == NULL) {
	    Tcl_Panic("Tcl_AsyncDelete: cannot find async handler");
	if (firstHandler == NULL) {
	    lastHandler = NULL;
	}
	if (asyncPtr == tsdPtr->firstHandler) {
	    tsdPtr->firstHandler = asyncPtr->nextPtr;
	} else {
	    prevPtr->nextPtr = asyncPtr->nextPtr;
    } else {
	asyncPtr->prevPtr->nextPtr = asyncPtr->nextPtr;
	}
	if (asyncPtr == tsdPtr->lastHandler) {
	    tsdPtr->lastHandler = prevPtr;
	if (asyncPtr == lastHandler) {
	    lastHandler = asyncPtr->prevPtr;
	}
    }
    if (asyncPtr->nextPtr != NULL) {
	asyncPtr->nextPtr->prevPtr = asyncPtr->prevPtr;
    }
    Tcl_MutexUnlock(&tsdPtr->asyncMutex);
    Tcl_MutexUnlock(&asyncMutex);
    Tcl_Free(asyncPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AsyncReady --

Changes to generic/tclBasic.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14







15
16
17
18
19
20
21
1
2
3
4
5
6
7







8
9
10
11
12
13
14
15
16
17
18
19
20
21







-
-
-
-
-
-
-
+
+
+
+
+
+
+







/*
 * tclBasic.c --
 *
 *	Contains the basic facilities for TCL command interpretation,
 *	including interpreter creation and deletion, command creation and
 *	deletion, and command/script execution.
 *
 * Copyright (c) 1987-1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright (c) 2001, 2002 by Kevin B. Kenny.  All rights reserved.
 * Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
 * Copyright (c) 2006-2008 by Joe Mistachkin.  All rights reserved.
 * Copyright (c) 2008 Miguel Sofer <msofer@users.sourceforge.net>
 * Copyright © 1987-1994 The Regents of the University of California.
 * Copyright © 1994-1997 Sun Microsystems, Inc.
 * Copyright © 1998-1999 Scriptics Corporation.
 * Copyright © 2001, 2002 Kevin B. Kenny.  All rights reserved.
 * Copyright © 2007 Daniel A. Steffen <das@users.sourceforge.net>
 * Copyright © 2006-2008 Joe Mistachkin.  All rights reserved.
 * Copyright © 2008 Miguel Sofer <msofer@users.sourceforge.net>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclOOInt.h"
59
60
61
62
63
64
65




66






























67
68
69
70
71
72
73
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







+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 * double layout and a 32-bit 'int' type).
 */
#define TCL_FPCLASSIFY_MODE 2
#endif /* !fpclassify */
/* actually there is no fallback to builtin fpclassify */
#endif /* !TCL_FPCLASSIFY_MODE */

/*
 * Bug 7371b6270b: to check C call stack depth, prefer an approach which is
 * compatible with AddressSanitizer (ASan) use-after-return detection.
 */

#if defined(_MSC_VER) && defined(HAVE_INTRIN_H)
#include <intrin.h> /* for _AddressOfReturnAddress() */
#endif

/*
 * As suggested by
 * https://clang.llvm.org/docs/LanguageExtensions.html#has-builtin
 */
#ifndef __has_builtin
#define __has_builtin(x) 0 /* for non-clang compilers */
#endif

void *
TclGetCStackPtr(void)
{
#if defined( __GNUC__ ) || __has_builtin(__builtin_frame_address)
    return __builtin_frame_address(0);
#elif defined(_MSC_VER) && defined(HAVE_INTRIN_H)
    return _AddressOfReturnAddress();
#else
    ptrdiff_t unused = 0;
    /*
     * LLVM recommends using volatile:
     * https://github.com/llvm/llvm-project/blob/llvmorg-10.0.0-rc1/clang/lib/Basic/Stack.cpp#L31
     */
    ptrdiff_t *volatile stackLevel = &unused;
    return (void *)stackLevel;
#endif
}

#define INTERP_STACK_INITIAL_SIZE 2000
#define CORO_STACK_INITIAL_SIZE    200

/*
 * Determine whether we're using IEEE floating point
 */

89
90
91
92
93
94
95
96
97


98
99
100
101
102
103
104
123
124
125
126
127
128
129


130
131
132
133
134
135
136
137
138







-
-
+
+








typedef struct {
    Tcl_Interp *interp;		/* Interp this struct belongs to. */
    Tcl_AsyncHandler async;	/* Async handler token for script
				 * cancellation. */
    char *result;		/* The script cancellation result or NULL for
				 * a default result. */
    size_t length;		/* Length of the above error message. */
    ClientData clientData;		/* Not used. */
    Tcl_Size length;		/* Length of the above error message. */
    void *clientData;		/* Not used. */
    int flags;			/* Additional flags */
} CancelInfo;
static Tcl_HashTable cancelTable;
static int cancelTableInitialized = 0;	/* 0 means not yet initialized. */
TCL_DECLARE_MUTEX(cancelLock);

/*
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
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







-
+



-
+


-
-
-
+
+
+






+








-
-
-
-
-
-
+
+
+
+
+
+








-
+











-
+


-
+


-
+












-














-
-
+
+

-
-
+
+













-
-
-
+
+
+













-
-
-
-
-
-
-
+
+
+
+
+
+
+





+
+
+
+
+
+
+
+
+
+











+

-
-
+
+







-
+






+







-
+




+



-
+







    iPtr->cmdFramePtr = (context).cmdFramePtr;		\
    iPtr->lineLABCPtr = (context).lineLABCPtr

/*
 * Static functions in this file:
 */

static Tcl_ObjCmdProc   BadEnsembleSubcommand;
static Tcl_ObjCmdProc	BadEnsembleSubcommand;
static char *		CallCommandTraces(Interp *iPtr, Command *cmdPtr,
			    const char *oldName, const char *newName,
			    int flags);
static int		CancelEvalProc(ClientData clientData,
static int		CancelEvalProc(void *clientData,
			    Tcl_Interp *interp, int code);
static int		CheckDoubleResult(Tcl_Interp *interp, double dResult);
static void		DeleteCoroutine(ClientData clientData);
static void		DeleteInterpProc(Tcl_Interp *interp);
static void		DeleteOpCmdClientData(ClientData clientData);
static void		DeleteCoroutine(void *clientData);
static Tcl_FreeProc	DeleteInterpProc;
static void		DeleteOpCmdClientData(void *clientData);
#ifdef USE_DTRACE
static Tcl_ObjCmdProc	DTraceObjCmd;
static Tcl_NRPostProc	DTraceCmdReturn;
#else
#   define DTraceCmdReturn	NULL
#endif /* USE_DTRACE */
static Tcl_ObjCmdProc	InvokeStringCommand;
static Tcl_ObjCmdProc	ExprAbsFunc;
static Tcl_ObjCmdProc	ExprBinaryFunc;
static Tcl_ObjCmdProc	ExprBoolFunc;
static Tcl_ObjCmdProc	ExprCeilFunc;
static Tcl_ObjCmdProc	ExprDoubleFunc;
static Tcl_ObjCmdProc	ExprFloorFunc;
static Tcl_ObjCmdProc	ExprIntFunc;
static Tcl_ObjCmdProc	ExprIsqrtFunc;
static Tcl_ObjCmdProc   ExprIsFiniteFunc;
static Tcl_ObjCmdProc   ExprIsInfinityFunc;
static Tcl_ObjCmdProc   ExprIsNaNFunc;
static Tcl_ObjCmdProc   ExprIsNormalFunc;
static Tcl_ObjCmdProc   ExprIsSubnormalFunc;
static Tcl_ObjCmdProc   ExprIsUnorderedFunc;
static Tcl_ObjCmdProc	ExprIsFiniteFunc;
static Tcl_ObjCmdProc	ExprIsInfinityFunc;
static Tcl_ObjCmdProc	ExprIsNaNFunc;
static Tcl_ObjCmdProc	ExprIsNormalFunc;
static Tcl_ObjCmdProc	ExprIsSubnormalFunc;
static Tcl_ObjCmdProc	ExprIsUnorderedFunc;
static Tcl_ObjCmdProc	ExprMaxFunc;
static Tcl_ObjCmdProc	ExprMinFunc;
static Tcl_ObjCmdProc	ExprRandFunc;
static Tcl_ObjCmdProc	ExprRoundFunc;
static Tcl_ObjCmdProc	ExprSqrtFunc;
static Tcl_ObjCmdProc	ExprSrandFunc;
static Tcl_ObjCmdProc	ExprUnaryFunc;
static Tcl_ObjCmdProc	ExprWideFunc;
static Tcl_ObjCmdProc   FloatClassifyObjCmd;
static Tcl_ObjCmdProc	FloatClassifyObjCmd;
static void		MathFuncWrongNumArgs(Tcl_Interp *interp, int expected,
			    int actual, Tcl_Obj *const *objv);
static Tcl_NRPostProc	NRCoroutineCallerCallback;
static Tcl_NRPostProc	NRCoroutineExitCallback;
static Tcl_NRPostProc	NRCommand;

static void		ProcessUnexpectedResult(Tcl_Interp *interp,
			    int returnCode);
static int		RewindCoroutine(CoroutineData *corPtr, int result);
static void		TEOV_SwitchVarFrame(Tcl_Interp *interp);
static void		TEOV_PushExceptionHandlers(Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[], int flags);
			    Tcl_Size objc, Tcl_Obj *const objv[], int flags);
static inline Command *	TEOV_LookupCmdFromObj(Tcl_Interp *interp,
			    Tcl_Obj *namePtr, Namespace *lookupNsPtr);
static int		TEOV_NotFound(Tcl_Interp *interp, int objc,
static int		TEOV_NotFound(Tcl_Interp *interp, Tcl_Size objc,
			    Tcl_Obj *const objv[], Namespace *lookupNsPtr);
static int		TEOV_RunEnterTraces(Tcl_Interp *interp,
			    Command **cmdPtrPtr, Tcl_Obj *commandPtr, int objc,
			    Command **cmdPtrPtr, Tcl_Obj *commandPtr, Tcl_Size objc,
			    Tcl_Obj *const objv[]);
static Tcl_NRPostProc	RewindCoroutineCallback;
static Tcl_NRPostProc	TEOEx_ByteCodeCallback;
static Tcl_NRPostProc	TEOEx_ListCallback;
static Tcl_NRPostProc	TEOV_Error;
static Tcl_NRPostProc	TEOV_Exception;
static Tcl_NRPostProc	TEOV_NotFoundCallback;
static Tcl_NRPostProc	TEOV_RestoreVarFrame;
static Tcl_NRPostProc	TEOV_RunLeaveTraces;
static Tcl_NRPostProc	EvalObjvCore;
static Tcl_NRPostProc	Dispatch;

static Tcl_ObjCmdProc NRInjectObjCmd;
static Tcl_NRPostProc NRPostInvoke;
static Tcl_ObjCmdProc CoroTypeObjCmd;
static Tcl_ObjCmdProc TclNRCoroInjectObjCmd;
static Tcl_ObjCmdProc TclNRCoroProbeObjCmd;
static Tcl_NRPostProc InjectHandler;
static Tcl_NRPostProc InjectHandlerPostCall;

MODULE_SCOPE const TclStubs tclStubs;

/*
 * Magical counts for the number of arguments accepted by a coroutine command
 * after particular kinds of [yield].
 */

#define CORO_ACTIVATE_YIELD    PTR2INT(NULL)
#define CORO_ACTIVATE_YIELDM   PTR2INT(NULL)+1
#define CORO_ACTIVATE_YIELD	NULL
#define CORO_ACTIVATE_YIELDM	INT2PTR(1)

#define COROUTINE_ARGUMENTS_SINGLE_OPTIONAL     (-1)
#define COROUTINE_ARGUMENTS_ARBITRARY           (-2)
#define COROUTINE_ARGUMENTS_SINGLE_OPTIONAL	(-1)
#define COROUTINE_ARGUMENTS_ARBITRARY		(-2)

/*
 * The following structure define the commands in the Tcl core.
 */

typedef struct {
    const char *name;		/* Name of object-based command. */
    Tcl_ObjCmdProc *objProc;	/* Object-based function for command. */
    CompileProc *compileProc;	/* Function called to compile command. */
    Tcl_ObjCmdProc *nreProc;	/* NR-based function for command */
    int flags;			/* Various flag bits, as defined below. */
} CmdInfo;

#define CMD_IS_SAFE         1   /* Whether this command is part of the set of
                                 * commands present by default in a safe
                                 * interpreter. */
#define CMD_IS_SAFE 1		/* Whether this command is part of the set of
				 * commands present by default in a safe
				 * interpreter. */
/* CMD_COMPILES_EXPANDED - Whether the compiler for this command can handle
 * expansion for itself rather than needing the generic layer to take care of
 * it for it. Defined in tclInt.h. */

/*
 * The following struct states that the command it talks about (a subcommand
 * of one of Tcl's built-in ensembles) is unsafe and must be hidden when an
 * interpreter is made safe. (TclHideUnsafeCommands accesses an array of these
 * structs.) Alas, we can't sensibly just store the information directly in
 * the commands.
 */

typedef struct {
    const char *ensembleNsName; /* The ensemble's name within ::tcl. NULL for
                                 * the end of the list of commands to hide. */
    const char *commandName;    /* The name of the command within the
                                 * ensemble. If this is NULL, we want to also
                                 * make the overall command be hidden, an ugly
                                 * hack because it is expected by security
                                 * policies in the wild. */
    const char *ensembleNsName;	/* The ensemble's name within ::tcl. NULL for
				 * the end of the list of commands to hide. */
    const char *commandName;	/* The name of the command within the
				 * ensemble. If this is NULL, we want to also
				 * make the overall command be hidden, an ugly
				 * hack because it is expected by security
				 * policies in the wild. */
} UnsafeEnsembleInfo;

/*
 * The built-in commands, and the functions that implement them:
 */

static int
procObjCmd(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    return Tcl_ProcObjCmd(clientData, interp, objc, objv);
}

static const CmdInfo builtInCmds[] = {
    /*
     * Commands in the generic core.
     */

    {"append",		Tcl_AppendObjCmd,	TclCompileAppendCmd,	NULL,	CMD_IS_SAFE},
    {"apply",		Tcl_ApplyObjCmd,	NULL,			TclNRApplyObjCmd,	CMD_IS_SAFE},
    {"break",		Tcl_BreakObjCmd,	TclCompileBreakCmd,	NULL,	CMD_IS_SAFE},
    {"catch",		Tcl_CatchObjCmd,	TclCompileCatchCmd,	TclNRCatchObjCmd,	CMD_IS_SAFE},
    {"concat",		Tcl_ConcatObjCmd,	TclCompileConcatCmd,	NULL,	CMD_IS_SAFE},
    {"const",		Tcl_ConstObjCmd,	TclCompileConstCmd,	NULL,	CMD_IS_SAFE},
    {"continue",	Tcl_ContinueObjCmd,	TclCompileContinueCmd,	NULL,	CMD_IS_SAFE},
    {"coroinject",	NULL,			NULL,                   TclNRCoroInjectObjCmd,	CMD_IS_SAFE},
    {"coroprobe",	NULL,			NULL,                   TclNRCoroProbeObjCmd,	CMD_IS_SAFE},
    {"coroinject",	NULL,			NULL,			TclNRCoroInjectObjCmd,	CMD_IS_SAFE},
    {"coroprobe",	NULL,			NULL,			TclNRCoroProbeObjCmd,	CMD_IS_SAFE},
    {"coroutine",	NULL,			NULL,			TclNRCoroutineObjCmd,	CMD_IS_SAFE},
    {"error",		Tcl_ErrorObjCmd,	TclCompileErrorCmd,	NULL,	CMD_IS_SAFE},
    {"eval",		Tcl_EvalObjCmd,		NULL,			TclNREvalObjCmd,	CMD_IS_SAFE},
    {"expr",		Tcl_ExprObjCmd,		TclCompileExprCmd,	TclNRExprObjCmd,	CMD_IS_SAFE},
    {"for",		Tcl_ForObjCmd,		TclCompileForCmd,	TclNRForObjCmd,	CMD_IS_SAFE},
    {"foreach",		Tcl_ForeachObjCmd,	TclCompileForeachCmd,	TclNRForeachCmd,	CMD_IS_SAFE},
    {"format",		Tcl_FormatObjCmd,	TclCompileFormatCmd,	NULL,	CMD_IS_SAFE},
    {"fpclassify",      FloatClassifyObjCmd,    NULL,                   NULL,   CMD_IS_SAFE},
    {"fpclassify",	FloatClassifyObjCmd,    NULL,			NULL,	CMD_IS_SAFE},
    {"global",		Tcl_GlobalObjCmd,	TclCompileGlobalCmd,	NULL,	CMD_IS_SAFE},
    {"if",		Tcl_IfObjCmd,		TclCompileIfCmd,	TclNRIfObjCmd,	CMD_IS_SAFE},
    {"incr",		Tcl_IncrObjCmd,		TclCompileIncrCmd,	NULL,	CMD_IS_SAFE},
    {"join",		Tcl_JoinObjCmd,		NULL,			NULL,	CMD_IS_SAFE},
    {"lappend",		Tcl_LappendObjCmd,	TclCompileLappendCmd,	NULL,	CMD_IS_SAFE},
    {"lassign",		Tcl_LassignObjCmd,	TclCompileLassignCmd,	NULL,	CMD_IS_SAFE},
    {"ledit",		Tcl_LeditObjCmd,	NULL,			NULL,	CMD_IS_SAFE},
    {"lindex",		Tcl_LindexObjCmd,	TclCompileLindexCmd,	NULL,	CMD_IS_SAFE},
    {"linsert",		Tcl_LinsertObjCmd,	TclCompileLinsertCmd,	NULL,	CMD_IS_SAFE},
    {"list",		Tcl_ListObjCmd,		TclCompileListCmd,	NULL,	CMD_IS_SAFE|CMD_COMPILES_EXPANDED},
    {"llength",		Tcl_LlengthObjCmd,	TclCompileLlengthCmd,	NULL,	CMD_IS_SAFE},
    {"lmap",		Tcl_LmapObjCmd,		TclCompileLmapCmd,	TclNRLmapCmd,	CMD_IS_SAFE},
    {"lpop",		Tcl_LpopObjCmd,		NULL,			NULL,	CMD_IS_SAFE},
    {"lrange",		Tcl_LrangeObjCmd,	TclCompileLrangeCmd,	NULL,	CMD_IS_SAFE},
    {"lremove", 	Tcl_LremoveObjCmd,	NULL,           	NULL,	CMD_IS_SAFE},
    {"lremove",		Tcl_LremoveObjCmd,	NULL,			NULL,	CMD_IS_SAFE},
    {"lrepeat",		Tcl_LrepeatObjCmd,	NULL,			NULL,	CMD_IS_SAFE},
    {"lreplace",	Tcl_LreplaceObjCmd,	TclCompileLreplaceCmd,	NULL,	CMD_IS_SAFE},
    {"lreverse",	Tcl_LreverseObjCmd,	NULL,			NULL,	CMD_IS_SAFE},
    {"lsearch",		Tcl_LsearchObjCmd,	NULL,			NULL,	CMD_IS_SAFE},
    {"lseq",		Tcl_LseqObjCmd,		NULL,			NULL,	CMD_IS_SAFE},
    {"lset",		Tcl_LsetObjCmd,		TclCompileLsetCmd,	NULL,	CMD_IS_SAFE},
    {"lsort",		Tcl_LsortObjCmd,	NULL,			NULL,	CMD_IS_SAFE},
    {"package",		Tcl_PackageObjCmd,	NULL,			TclNRPackageObjCmd,	CMD_IS_SAFE},
    {"proc",		Tcl_ProcObjCmd,		NULL,			NULL,	CMD_IS_SAFE},
    {"proc",		procObjCmd,		NULL,			NULL,	CMD_IS_SAFE},
    {"regexp",		Tcl_RegexpObjCmd,	TclCompileRegexpCmd,	NULL,	CMD_IS_SAFE},
    {"regsub",		Tcl_RegsubObjCmd,	TclCompileRegsubCmd,	NULL,	CMD_IS_SAFE},
    {"rename",		Tcl_RenameObjCmd,	NULL,			NULL,	CMD_IS_SAFE},
    {"return",		Tcl_ReturnObjCmd,	TclCompileReturnCmd,	NULL,	CMD_IS_SAFE},
    {"scan",		Tcl_ScanObjCmd,		NULL,			NULL,	CMD_IS_SAFE},
    {"set",		Tcl_SetObjCmd,		TclCompileSetCmd,	NULL,	CMD_IS_SAFE},
    {"split",		Tcl_SplitObjCmd,	NULL,			NULL,	CMD_IS_SAFE},
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
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
467

468
469
470

471
472
473
474

475
476
477
478
479
480
481
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
467
468
469

470
471
472
473
474
475
476
477
478
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







+


















+











+
+
+
+
-
+
+
+
+
+






-
+
+








+
+
+
+




-
+






-
+


-
+



-
+

-
-
+
+

-
-
-
-
+
+
+
+

-
-
-
+
+
+



-
+


-
+



-
+







    {"file", "attributes"},
    {"file", "copy"},
    {"file", "delete"},
    {"file", "dirname"},
    {"file", "executable"},
    {"file", "exists"},
    {"file", "extension"},
    {"file", "home"},
    {"file", "isdirectory"},
    {"file", "isfile"},
    {"file", "link"},
    {"file", "lstat"},
    {"file", "mtime"},
    {"file", "mkdir"},
    {"file", "nativename"},
    {"file", "normalize"},
    {"file", "owned"},
    {"file", "readable"},
    {"file", "readlink"},
    {"file", "rename"},
    {"file", "rootname"},
    {"file", "size"},
    {"file", "stat"},
    {"file", "tail"},
    {"file", "tempdir"},
    {"file", "tempfile"},
    {"file", "tildeexpand"},
    {"file", "type"},
    {"file", "volumes"},
    {"file", "writable"},
    /* [info] has two unsafe commands */
    {"info", "cmdtype"},
    {"info", "nameofexecutable"},
    /* [tcl::process] has ONLY unsafe commands! */
    {"process", "list"},
    {"process", "status"},
    {"process", "purge"},
    {"process", "autopurge"},
    /*
     * [zipfs] perhaps has some safe commands. But like file make it inaccessible
     * until they are analyzed to be safe.
     */
    /* [zipfs] has MANY unsafe commands! */
    {"zipfs", NULL},
    {"zipfs", "canonical"},
    {"zipfs", "exists"},
    {"zipfs", "info"},
    {"zipfs", "list"},
    {"zipfs", "lmkimg"},
    {"zipfs", "lmkzip"},
    {"zipfs", "mkimg"},
    {"zipfs", "mkkey"},
    {"zipfs", "mkzip"},
    {"zipfs", "mount"},
    {"zipfs", "mount_data"},
    {"zipfs", "mountdata"},
    {"zipfs", "root"},
    {"zipfs", "unmount"},
    {NULL, NULL}
};

/*
 * Math functions. All are safe.
 */

typedef double (BuiltinUnaryFunc)(double x);
typedef double (BuiltinBinaryFunc)(double x, double y);
#define BINARY_TYPECAST(fn) \
	(BuiltinUnaryFunc *)(void *)(BuiltinBinaryFunc *) fn
typedef struct {
    const char *name;		/* Name of the function. The full name is
				 * "::tcl::mathfunc::<name>". */
    Tcl_ObjCmdProc *objCmdProc;	/* Function that evaluates the function */
    double (*fn)(double x);	/* Real function pointer */
    BuiltinUnaryFunc *fn;	/* Real function pointer */
} BuiltinFuncDef;
static const BuiltinFuncDef BuiltinFuncTable[] = {
    { "abs",	ExprAbsFunc,	NULL			},
    { "acos",	ExprUnaryFunc,	acos			},
    { "asin",	ExprUnaryFunc,	asin			},
    { "atan",	ExprUnaryFunc,	atan			},
    { "atan2",	ExprBinaryFunc,	(double (*)(double))(void *)(double (*)(double, double)) atan2},
    { "atan2",	ExprBinaryFunc,	BINARY_TYPECAST(atan2)	},
    { "bool",	ExprBoolFunc,	NULL			},
    { "ceil",	ExprCeilFunc,	NULL			},
    { "cos",	ExprUnaryFunc,	cos				},
    { "cos",	ExprUnaryFunc,	cos			},
    { "cosh",	ExprUnaryFunc,	cosh			},
    { "double",	ExprDoubleFunc,	NULL			},
    { "entier",	ExprIntFunc,	NULL			},
    { "exp",	ExprUnaryFunc,	exp				},
    { "exp",	ExprUnaryFunc,	exp			},
    { "floor",	ExprFloorFunc,	NULL			},
    { "fmod",	ExprBinaryFunc,	(double (*)(double))(void *)(double (*)(double, double)) fmod},
    { "hypot",	ExprBinaryFunc,	(double (*)(double))(void *)(double (*)(double, double)) hypot},
    { "fmod",	ExprBinaryFunc,	BINARY_TYPECAST(fmod)	},
    { "hypot",	ExprBinaryFunc,	BINARY_TYPECAST(hypot)	},
    { "int",	ExprIntFunc,	NULL			},
    { "isfinite", ExprIsFiniteFunc, NULL        	},
    { "isinf",	ExprIsInfinityFunc, NULL        	},
    { "isnan",	ExprIsNaNFunc,	NULL            	},
    { "isnormal", ExprIsNormalFunc, NULL        	},
    { "isfinite", ExprIsFiniteFunc, NULL		},
    { "isinf",	ExprIsInfinityFunc, NULL		},
    { "isnan",	ExprIsNaNFunc,	NULL			},
    { "isnormal", ExprIsNormalFunc, NULL		},
    { "isqrt",	ExprIsqrtFunc,	NULL			},
    { "issubnormal", ExprIsSubnormalFunc, NULL,         },
    { "isunordered", ExprIsUnorderedFunc, NULL,         },
    { "log",	ExprUnaryFunc,	log				},
    { "issubnormal", ExprIsSubnormalFunc, NULL,		},
    { "isunordered", ExprIsUnorderedFunc, NULL,		},
    { "log",	ExprUnaryFunc,	log			},
    { "log10",	ExprUnaryFunc,	log10			},
    { "max",	ExprMaxFunc,	NULL			},
    { "min",	ExprMinFunc,	NULL			},
    { "pow",	ExprBinaryFunc,	(double (*)(double))(void *)(double (*)(double, double)) pow},
    { "pow",	ExprBinaryFunc,	BINARY_TYPECAST(pow)	},
    { "rand",	ExprRandFunc,	NULL			},
    { "round",	ExprRoundFunc,	NULL			},
    { "sin",	ExprUnaryFunc,	sin				},
    { "sin",	ExprUnaryFunc,	sin			},
    { "sinh",	ExprUnaryFunc,	sinh			},
    { "sqrt",	ExprSqrtFunc,	NULL			},
    { "srand",	ExprSrandFunc,	NULL			},
    { "tan",	ExprUnaryFunc,	tan				},
    { "tan",	ExprUnaryFunc,	tan			},
    { "tanh",	ExprUnaryFunc,	tanh			},
    { "wide",	ExprWideFunc,	NULL			},
    { NULL, NULL, NULL }
};

/*
 * TIP#174's math operators. All are safe.
575
576
577
578
579
580
581
582
583


584
585
586
587










































































































































588
589
590
591
592
593
594
637
638
639
640
641
642
643


644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794







-
-
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	Tcl_DeleteHashTable(&cancelTable);
	cancelTableInitialized = 0;
    }
    Tcl_MutexUnlock(&cancelLock);

    Tcl_MutexLock(&commandTypeLock);
    if (commandTypeInit) {
        Tcl_DeleteHashTable(&commandTypeTable);
        commandTypeInit = 0;
	Tcl_DeleteHashTable(&commandTypeTable);
	commandTypeInit = 0;
    }
    Tcl_MutexUnlock(&commandTypeLock);
}

/*
 *----------------------------------------------------------------------
 *
 * buildInfoObjCmd --
 *
 *	Implements tcl::build-info command.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
buildInfoObjCmd2(
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Size objc,		/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *buildData = (const char *) clientData;
    char buf[80];
    const char *arg, *p, *q;
    Tcl_Size len;
    int idx;
    static const char *identifiers[] = {
	"commit", "compiler", "patchlevel", "version", NULL
    };
    enum Identifiers {
	ID_COMMIT, ID_COMPILER, ID_PATCHLEVEL, ID_VERSION, ID_OTHER
    };

    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?option?");
	return TCL_ERROR;
    } else if (objc < 2) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(buildData, TCL_INDEX_NONE));
	return TCL_OK;
    }

    /*
     * Query for a specific piece of build info
     */

    if (Tcl_GetIndexFromObj(NULL, objv[1], identifiers, NULL, TCL_EXACT,
	    &idx) != TCL_OK) {
	idx = ID_OTHER;
    }

    switch (idx) {
    case ID_PATCHLEVEL:
	if ((p = strchr(buildData, '+')) != NULL) {
	    memcpy(buf, buildData, p - buildData);
	    buf[p - buildData] = '\0';
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, TCL_INDEX_NONE));
	}
	return TCL_OK;
    case ID_VERSION:
	if ((p = strchr(buildData, '.')) != NULL) {
	    const char *r = strchr(p++, '+');
	    q = strchr(p, '.');
	    p = (q < r) ? q : r;
	}
	if (p != NULL) {
	    memcpy(buf, buildData, p - buildData);
	    buf[p - buildData] = '\0';
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, TCL_INDEX_NONE));
	}
	return TCL_OK;
    case ID_COMMIT:
	if ((p = strchr(buildData, '+')) != NULL) {
	    if ((q = strchr(p++, '.')) != NULL) {
		memcpy(buf, p, q - p);
		buf[q - p] = '\0';
		Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, TCL_INDEX_NONE));
	    } else {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(p, TCL_INDEX_NONE));
	    }
	}
	return TCL_OK;
    case ID_COMPILER:
	for (p = strchr(buildData, '.'); p++; p = strchr(p, '.')) {
	    /*
	     * Does the word begin with one of the standard prefixes?
	     */
	    if (!strncmp(p, "clang-", 6)
		    || !strncmp(p, "gcc-", 4)
		    || !strncmp(p, "icc-", 4)
		    || !strncmp(p, "msvc-", 5)) {
		if ((q = strchr(p, '.')) != NULL) {
		    memcpy(buf, p, q - p);
		    buf[q - p] = '\0';
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, TCL_INDEX_NONE));
		} else {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(p, TCL_INDEX_NONE));
		}
		return TCL_OK;
	    }
	}
	break;
    default:		/* Boolean test for other identifiers' presence */
	arg = TclGetStringFromObj(objv[1], &len);
	for (p = strchr(buildData, '.'); p++; p = strchr(p, '.')) {
	    if (!strncmp(p, arg, len)
		    && ((p[len] == '.') || (p[len] == '-') || (p[len] == '\0'))) {
		if (p[len] == '-') {
		    p += len;
		    q = strchr(++p, '.');
		    if (!q) {
			q = p + strlen(p);
		    }
		    memcpy(buf, p, q - p);
		    buf[q - p] = '\0';
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, TCL_INDEX_NONE));
		} else {
		    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
		}
		return TCL_OK;
	    }
	}
    }
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
    return TCL_OK;
}

static int
buildInfoObjCmd(
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return buildInfoObjCmd2(clientData, interp, objc, objv);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_CreateInterp --
 *
 *	Create a new TCL command interpreter.
 *
621
622
623
624
625
626
627
628
629

630
631
632
633
634
635
636
821
822
823
824
825
826
827


828
829
830
831
832
833
834
835







-
-
+







	short s;
    } order;
#ifdef TCL_COMPILE_STATS
    ByteCodeStats *statsPtr;
#endif /* TCL_COMPILE_STATS */
    char mathFuncName[32];
    CallFrame *framePtr;

    Tcl_InitSubsystems();
    const char *version = Tcl_InitSubsystems();

    /*
     * Panic if someone updated the CallFrame structure without also updating
     * the Tcl_CallFrame structure (or vice versa).
     */

    if (sizeof(Tcl_CallFrame) < sizeof(CallFrame)) {
653
654
655
656
657
658
659

660
661
662
663
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
852
853
854
855
856
857
858
859
860










861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887

888
889
890
891
892
893
894
895







+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

















-
+







	    Tcl_InitHashTable(&cancelTable, TCL_ONE_WORD_KEYS);
	    cancelTableInitialized = 1;
	}

	Tcl_MutexUnlock(&cancelLock);
    }

#undef TclObjInterpProc
    if (commandTypeInit == 0) {
        TclRegisterCommandTypeName(TclObjInterpProc, "proc");
        TclRegisterCommandTypeName(TclEnsembleImplementationCmd, "ensemble");
        TclRegisterCommandTypeName(TclAliasObjCmd, "alias");
        TclRegisterCommandTypeName(TclLocalAliasObjCmd, "alias");
        TclRegisterCommandTypeName(TclChildObjCmd, "interp");
        TclRegisterCommandTypeName(TclInvokeImportedCmd, "import");
        TclRegisterCommandTypeName(TclOOPublicObjectCmd, "object");
        TclRegisterCommandTypeName(TclOOPrivateObjectCmd, "privateObject");
        TclRegisterCommandTypeName(TclOOMyClassObjCmd, "privateClass");
        TclRegisterCommandTypeName(TclNRInterpCoroutine, "coroutine");
	TclRegisterCommandTypeName(TclObjInterpProc, "proc");
	TclRegisterCommandTypeName(TclEnsembleImplementationCmd, "ensemble");
	TclRegisterCommandTypeName(TclAliasObjCmd, "alias");
	TclRegisterCommandTypeName(TclLocalAliasObjCmd, "alias");
	TclRegisterCommandTypeName(TclChildObjCmd, "interp");
	TclRegisterCommandTypeName(TclInvokeImportedCmd, "import");
	TclRegisterCommandTypeName(TclOOPublicObjectCmd, "object");
	TclRegisterCommandTypeName(TclOOPrivateObjectCmd, "privateObject");
	TclRegisterCommandTypeName(TclOOMyClassObjCmd, "privateClass");
	TclRegisterCommandTypeName(TclNRInterpCoroutine, "coroutine");
    }

    /*
     * Initialize support for namespaces and create the global namespace
     * (whose name is ""; an alias is "::"). This also initializes the Tcl
     * object type table and other object management code.
     */

    iPtr = (Interp *)Tcl_Alloc(sizeof(Interp));
    interp = (Tcl_Interp *) iPtr;

    iPtr->legacyResult = NULL;
    /* Special invalid value: Any attempt to free the legacy result
     * will cause a crash. */
    iPtr->legacyFreeProc = (void (*) (void))-1;
    iPtr->errorLine = 0;
    iPtr->stubTable = &tclStubs;
    iPtr->objResultPtr = Tcl_NewObj();
    TclNewObj(iPtr->objResultPtr);
    Tcl_IncrRefCount(iPtr->objResultPtr);
    iPtr->handle = TclHandleCreate(iPtr);
    iPtr->globalNsPtr = NULL;
    iPtr->hiddenCmdTablePtr = NULL;
    iPtr->interpInfo = NULL;

    iPtr->optimizer = TclOptimizeBytecode;
739
740
741
742
743
744
745




746
747
748
749
750
751
752
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956







+
+
+
+







    iPtr->returnCode = TCL_OK;

    iPtr->rootFramePtr = NULL;	/* Initialise as soon as :: is available */
    iPtr->lookupNsPtr = NULL;

    Tcl_InitHashTable(&iPtr->packageTable, TCL_STRING_KEYS);
    iPtr->packageUnknown = NULL;

#ifdef _WIN32
#   define getenv(x) _wgetenv(L##x) /* On Windows, use _wgetenv below */
#endif

    /* TIP #268 */
#if (TCL_RELEASE_LEVEL == TCL_FINAL_RELEASE)
    if (getenv("TCL_PKG_PREFER_LATEST") == NULL) {
	iPtr->packagePrefer = PKG_PREFER_STABLE;
    } else
#endif
762
763
764
765
766
767
768
769

770
771
772
773
774
775
776
777
778
779

780
781
782
783
784
785
786
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







-
+









-
+







    iPtr->flags = 0;
    iPtr->tracePtr = NULL;
    iPtr->tracesForbiddingInline = 0;
    iPtr->activeCmdTracePtr = NULL;
    iPtr->activeInterpTracePtr = NULL;
    iPtr->assocData = NULL;
    iPtr->execEnvPtr = NULL;	/* Set after namespaces initialized. */
    iPtr->emptyObjPtr = Tcl_NewObj();
    TclNewObj(iPtr->emptyObjPtr);
				/* Another empty object. */
    Tcl_IncrRefCount(iPtr->emptyObjPtr);
    iPtr->threadId = Tcl_GetCurrentThread();

    /* TIP #378 */
#ifdef TCL_INTERP_DEBUG_FRAME
    iPtr->flags |= INTERP_DEBUG_FRAME;
#else
    if (getenv("TCL_INTERP_DEBUG_FRAME") != NULL) {
        iPtr->flags |= INTERP_DEBUG_FRAME;
	iPtr->flags |= INTERP_DEBUG_FRAME;
    }
#endif

    /*
     * Initialise the tables for variable traces and searches *before*
     * creating the global ns - so that the trace on errorInfo can be
     * recorded.
826
827
828
829
830
831
832
833

834
835
836
837
838
839
840
1030
1031
1032
1033
1034
1035
1036

1037
1038
1039
1040
1041
1042
1043
1044







-
+








    iPtr->chanMsg = NULL;

    /*
     * TIP #285, Script cancellation support.
     */

    iPtr->asyncCancelMsg = Tcl_NewObj();
    TclNewObj(iPtr->asyncCancelMsg);

    cancelInfo = (CancelInfo *)Tcl_Alloc(sizeof(CancelInfo));
    cancelInfo->interp = interp;

    iPtr->asyncCancel = Tcl_AsyncCreate(CancelEvalProc, cancelInfo);
    cancelInfo->async = iPtr->asyncCancel;
    cancelInfo->result = NULL;
901
902
903
904
905
906
907
908
909
910



911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934

935
936
937
938
939
940
941
942
943



944
945
946
947
948
949
950
1105
1106
1107
1108
1109
1110
1111



1112
1113
1114





1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132

1133
1134
1135
1136
1137
1138
1139



1140
1141
1142
1143
1144
1145
1146
1147
1148
1149







-
-
-
+
+
+
-
-
-
-
-


















-
+






-
-
-
+
+
+







    iPtr->allocCache = NULL;
#endif
    iPtr->pendingObjDataPtr = NULL;
    iPtr->asyncReadyPtr = TclGetAsyncReadyPtr();
    iPtr->deferredCallbacks = NULL;

    /*
     * Create the core commands. Do it here, rather than calling
     * Tcl_CreateCommand, because it's faster (there's no need to check for a
     * pre-existing command by the same name). If a command has a Tcl_CmdProc
     * Create the core commands. Do it here, rather than calling Tcl_CreateObjCommand,
     * because it's faster (there's no need to check for a preexisting command
     * by the same name). Set the Tcl_CmdProc to NULL.
     * but no Tcl_ObjCmdProc, set the Tcl_ObjCmdProc to
     * TclInvokeStringCommand. This is an object-based wrapper function that
     * extracts strings, calls the string function, and creates an object for
     * the result. Similarly, if a command has a Tcl_ObjCmdProc but no
     * Tcl_CmdProc, set the Tcl_CmdProc to TclInvokeObjectCommand.
     */

    for (cmdInfoPtr = builtInCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) {
	if ((cmdInfoPtr->objProc == NULL)
		&& (cmdInfoPtr->compileProc == NULL)
		&& (cmdInfoPtr->nreProc == NULL)) {
	    Tcl_Panic("builtin command with NULL object command proc and a NULL compile proc");
	}

	hPtr = Tcl_CreateHashEntry(&iPtr->globalNsPtr->cmdTable,
		cmdInfoPtr->name, &isNew);
	if (isNew) {
	    cmdPtr = (Command *)Tcl_Alloc(sizeof(Command));
	    cmdPtr->hPtr = hPtr;
	    cmdPtr->nsPtr = iPtr->globalNsPtr;
	    cmdPtr->refCount = 1;
	    cmdPtr->cmdEpoch = 0;
	    cmdPtr->compileProc = cmdInfoPtr->compileProc;
	    cmdPtr->proc = TclInvokeObjectCommand;
	    cmdPtr->proc = NULL;
	    cmdPtr->clientData = cmdPtr;
	    cmdPtr->objProc = cmdInfoPtr->objProc;
	    cmdPtr->objClientData = NULL;
	    cmdPtr->deleteProc = NULL;
	    cmdPtr->deleteData = NULL;
	    cmdPtr->flags = 0;
            if (cmdInfoPtr->flags & CMD_COMPILES_EXPANDED) {
                cmdPtr->flags |= CMD_COMPILES_EXPANDED;
            }
	    if (cmdInfoPtr->flags & CMD_COMPILES_EXPANDED) {
		cmdPtr->flags |= CMD_COMPILES_EXPANDED;
	    }
	    cmdPtr->importRefPtr = NULL;
	    cmdPtr->tracePtr = NULL;
	    cmdPtr->nreProc = cmdInfoPtr->nreProc;
	    Tcl_SetHashValue(hPtr, cmdPtr);
	}
    }

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
1024
1025
1195
1196
1197
1198
1199
1200
1201


1202
1203
1204
1205
1206




1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218

1219
1220
1221
1222
1223
1224
1225







-
-
+
+



-
-
-
-
+
+
+
+
+
+






-







    Tcl_CreateObjCommand(interp, "::tcl::unsupported::getbytecode",
	    Tcl_DisassembleObjCmd, INT2PTR(1), NULL);
    Tcl_CreateObjCommand(interp, "::tcl::unsupported::representation",
	    Tcl_RepresentationCmd, NULL, NULL);

    /* Adding the bytecode assembler command */
    cmdPtr = (Command *) Tcl_NRCreateCommand(interp,
            "::tcl::unsupported::assemble", Tcl_AssembleObjCmd,
            TclNRAssembleObjCmd, NULL, NULL);
	    "::tcl::unsupported::assemble", Tcl_AssembleObjCmd,
	    TclNRAssembleObjCmd, NULL, NULL);
    cmdPtr->compileProc = &TclCompileAssembleCmd;

    /* Coroutine monkeybusiness */
    Tcl_NRCreateCommand(interp, "::tcl::unsupported::inject", NULL,
	    NRInjectObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "::tcl::unsupported::corotype",
            CoroTypeObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "::tcl::unsupported::corotype",
	    CoroTypeObjCmd, NULL, NULL);

    /* Load and intialize ICU */
    Tcl_CreateObjCommand(interp, "::tcl::unsupported::loadIcu",
	    TclLoadIcuObjCmd, NULL, NULL);

    /* Export unsupported commands */
    nsPtr = Tcl_FindNamespace(interp, "::tcl::unsupported", NULL, 0);
    if (nsPtr) {
	Tcl_Export(interp, nsPtr, "*", 1);
    }


#ifdef USE_DTRACE
    /*
     * Register the tcl::dtrace command.
     */

    Tcl_CreateObjCommand(interp, "::tcl::dtrace", DTraceObjCmd, NULL, NULL);
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
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







-
+











-
+







    if (nsPtr == NULL) {
	Tcl_Panic("Can't create math function namespace");
    }
#define MATH_FUNC_PREFIX_LEN 17 /* == strlen("::tcl::mathfunc::") */
    memcpy(mathFuncName, "::tcl::mathfunc::", MATH_FUNC_PREFIX_LEN);
    for (builtinFuncPtr = BuiltinFuncTable; builtinFuncPtr->name != NULL;
	    builtinFuncPtr++) {
	strcpy(mathFuncName+MATH_FUNC_PREFIX_LEN, builtinFuncPtr->name);
	strcpy(mathFuncName + MATH_FUNC_PREFIX_LEN, builtinFuncPtr->name);
	Tcl_CreateObjCommand(interp, mathFuncName,
		builtinFuncPtr->objCmdProc, (void *)builtinFuncPtr->fn, NULL);
	Tcl_Export(interp, nsPtr, builtinFuncPtr->name, 0);
    }

    /*
     * Register the mathematical "operator" commands. [TIP #174]
     */

    nsPtr = Tcl_CreateNamespace(interp, "::tcl::mathop", NULL, NULL);
    if (nsPtr == NULL) {
	Tcl_Panic("can't create math operator namespace");
	Tcl_Panic("cannot create math operator namespace");
    }
    Tcl_Export(interp, nsPtr, "*", 1);
#define MATH_OP_PREFIX_LEN 15 /* == strlen("::tcl::mathop::") */
    memcpy(mathFuncName, "::tcl::mathop::", MATH_OP_PREFIX_LEN);
    for (opcmdInfoPtr=mathOpCmds ; opcmdInfoPtr->name!=NULL ; opcmdInfoPtr++){
	TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)Tcl_Alloc(sizeof(TclOpCmdClientData));

1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131

1132
1133
1134








1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150

1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164

1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179




1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194


1195
1196
1197

1198
1199
1200
1201



1202
1203
1204
1205
1206
1207





1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221

1222
1223
1224
1225

1226
1227
1228
1229



1230
1231
1232
1233
1234
1235
1236
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
1354
1355
1356
1357
1358
1359
1360
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



1387
1388
1389
1390





1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408

1409
1410
1411
1412

1413
1414



1415
1416
1417
1418
1419
1420
1421
1422
1423
1424







-
-
-
-
-
-
-
-
-
-
-



+



+
+
+
+
+
+
+
+









-
-
-
-
-
-
-
+


-
-
-
-







-
+











-
-
-
-
+
+
+
+













-
-
+
+


-
+

-
-
-
+
+
+

-
-
-
-
-
+
+
+
+
+













-
+



-
+

-
-
-
+
+
+







     * Set up other variables such as tcl_version and tcl_library
     */

    Tcl_SetVar2(interp, "tcl_patchLevel", NULL, TCL_PATCH_LEVEL, TCL_GLOBAL_ONLY);
    Tcl_SetVar2(interp, "tcl_version", NULL, TCL_VERSION, TCL_GLOBAL_ONLY);
    TclpSetVariables(interp);

#if TCL_THREADS
    /*
     * The existence of the "threaded" element of the tcl_platform array
     * indicates that this particular Tcl shell has been compiled with threads
     * turned on. Using "info exists tcl_platform(threaded)" a Tcl script can
     * introspect on the interpreter level of thread safety.
     */

    Tcl_SetVar2(interp, "tcl_platform", "threaded", "1", TCL_GLOBAL_ONLY);
#endif

    /*
     * Register Tcl's version number.
     * TIP #268: Full patchlevel instead of just major.minor
     * TIP #599: Extended build information "+<UUID>.<tag1>.<tag2>...."
     */

    Tcl_PkgProvideEx(interp, "Tcl", TCL_PATCH_LEVEL, &tclStubs);
    Tcl_PkgProvideEx(interp, "tcl", TCL_PATCH_LEVEL, &tclStubs);
    Tcl_CmdInfo info2;
    Tcl_Command buildInfoCmd = Tcl_CreateObjCommand(interp, "::tcl::build-info",
	    buildInfoObjCmd, (void *)version, NULL);
    Tcl_GetCommandInfoFromToken(buildInfoCmd, &info2);
    info2.objProc2 = buildInfoObjCmd2;
    info2.objClientData2 = (void *)version;
    Tcl_SetCommandInfoFromToken(buildInfoCmd, &info2);

    if (TclTommath_Init(interp) != TCL_OK) {
	Tcl_Panic("%s", Tcl_GetStringResult(interp));
    }

    if (TclOOInit(interp) != TCL_OK) {
	Tcl_Panic("%s", Tcl_GetStringResult(interp));
    }

    /*
     * Only build in zlib support if we've successfully detected a library to
     * compile and link against.
     */

#ifdef HAVE_ZLIB
    if (TclZlibInit(interp) != TCL_OK) {
    if (TclZlibInit(interp) != TCL_OK || TclZipfs_Init(interp) != TCL_OK) {
	Tcl_Panic("%s", Tcl_GetStringResult(interp));
    }
    if (TclZipfs_Init(interp) != TCL_OK) {
	Tcl_Panic("%s", Tcl_GetStringResult(interp));
    }
#endif

    TOP_CB(iPtr) = NULL;
    return interp;
}

static void
DeleteOpCmdClientData(
    ClientData clientData)
    void *clientData)
{
    TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)clientData;

    Tcl_Free(occdPtr);
}

/*
 * ---------------------------------------------------------------------
 *
 * TclRegisterCommandTypeName, TclGetCommandTypeName --
 *
 *      Command type registration and lookup mechanism. Everything is keyed by
 *      the Tcl_ObjCmdProc for the command, and that is used as the *key* into
 *      the hash table that maps to constant strings that are names. (It is
 *      recommended that those names be ASCII.)
 *	Command type registration and lookup mechanism. Everything is keyed by
 *	the Tcl_ObjCmdProc for the command, and that is used as the *key* into
 *	the hash table that maps to constant strings that are names. (It is
 *	recommended that those names be ASCII.)
 *
 * ---------------------------------------------------------------------
 */

void
TclRegisterCommandTypeName(
    Tcl_ObjCmdProc *implementationProc,
    const char *nameStr)
{
    Tcl_HashEntry *hPtr;

    Tcl_MutexLock(&commandTypeLock);
    if (commandTypeInit == 0) {
        Tcl_InitHashTable(&commandTypeTable, TCL_ONE_WORD_KEYS);
        commandTypeInit = 1;
	Tcl_InitHashTable(&commandTypeTable, TCL_ONE_WORD_KEYS);
	commandTypeInit = 1;
    }
    if (nameStr != NULL) {
        int isNew;
	int isNew;

        hPtr = Tcl_CreateHashEntry(&commandTypeTable,
                (void *) implementationProc, &isNew);
        Tcl_SetHashValue(hPtr, (void *) nameStr);
	hPtr = Tcl_CreateHashEntry(&commandTypeTable,
		implementationProc, &isNew);
	Tcl_SetHashValue(hPtr, (void *) nameStr);
    } else {
        hPtr = Tcl_FindHashEntry(&commandTypeTable,
                (void *) implementationProc);
        if (hPtr != NULL) {
            Tcl_DeleteHashEntry(hPtr);
        }
	hPtr = Tcl_FindHashEntry(&commandTypeTable,
		implementationProc);
	if (hPtr != NULL) {
	    Tcl_DeleteHashEntry(hPtr);
	}
    }
    Tcl_MutexUnlock(&commandTypeLock);
}

const char *
TclGetCommandTypeName(
    Tcl_Command command)
{
    Command *cmdPtr = (Command *) command;
    Tcl_ObjCmdProc *procPtr = cmdPtr->objProc;
    const char *name = "native";

    if (procPtr == NULL) {
        procPtr = cmdPtr->nreProc;
	procPtr = cmdPtr->nreProc;
    }
    Tcl_MutexLock(&commandTypeLock);
    if (commandTypeInit) {
        Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&commandTypeTable, procPtr);
	Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&commandTypeTable, procPtr);

        if (hPtr && Tcl_GetHashValue(hPtr)) {
            name = (const char *) Tcl_GetHashValue(hPtr);
        }
	if (hPtr && Tcl_GetHashValue(hPtr)) {
	    name = (const char *) Tcl_GetHashValue(hPtr);
	}
    }
    Tcl_MutexUnlock(&commandTypeLock);

    return name;
}

/*
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
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
1478
1479
1480
1481
1482
1483
1484
1485
1486







1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500







-
-
-
-
-
+
+
+
+
+

-
-
-
-
+
+
+
+

+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+







    for (cmdInfoPtr = builtInCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) {
	if (!(cmdInfoPtr->flags & CMD_IS_SAFE)) {
	    Tcl_HideCommand(interp, cmdInfoPtr->name, cmdInfoPtr->name);
	}
    }

    for (unsafePtr = unsafeEnsembleCommands;
            unsafePtr->ensembleNsName; unsafePtr++) {
        if (unsafePtr->commandName) {
            /*
             * Hide an ensemble subcommand.
             */
	    unsafePtr->ensembleNsName; unsafePtr++) {
	if (unsafePtr->commandName) {
	    /*
	     * Hide an ensemble subcommand.
	     */

            Tcl_Obj *cmdName = Tcl_ObjPrintf("::tcl::%s::%s",
                    unsafePtr->ensembleNsName, unsafePtr->commandName);
            Tcl_Obj *hideName = Tcl_ObjPrintf("tcl:%s:%s",
                    unsafePtr->ensembleNsName, unsafePtr->commandName);
	    Tcl_Obj *cmdName = Tcl_ObjPrintf("::tcl::%s::%s",
		    unsafePtr->ensembleNsName, unsafePtr->commandName);
	    Tcl_Obj *hideName = Tcl_ObjPrintf("tcl:%s:%s",
		    unsafePtr->ensembleNsName, unsafePtr->commandName);

#define INTERIM_HACK_NAME "___tmp"

            if (TclRenameCommand(interp, TclGetString(cmdName),
                        "___tmp") != TCL_OK
                    || Tcl_HideCommand(interp, "___tmp",
                            TclGetString(hideName)) != TCL_OK) {
                Tcl_Panic("problem making '%s %s' safe: %s",
                        unsafePtr->ensembleNsName, unsafePtr->commandName,
                        Tcl_GetStringResult(interp));
            }
            Tcl_CreateObjCommand(interp, TclGetString(cmdName),
                    BadEnsembleSubcommand, (void *)unsafePtr, NULL);
            TclDecrRefCount(cmdName);
            TclDecrRefCount(hideName);
        } else {
            /*
             * Hide an ensemble main command (for compatibility).
             */
	    if (TclRenameCommand(interp, TclGetString(cmdName),
			INTERIM_HACK_NAME) != TCL_OK
		    || Tcl_HideCommand(interp, INTERIM_HACK_NAME,
			    TclGetString(hideName)) != TCL_OK) {
		Tcl_Panic("problem making '%s %s' safe: %s",
			unsafePtr->ensembleNsName, unsafePtr->commandName,
			Tcl_GetStringResult(interp));
	    }
	    Tcl_CreateObjCommand(interp, TclGetString(cmdName),
		    BadEnsembleSubcommand, (void *)unsafePtr, NULL);
	    TclDecrRefCount(cmdName);
	    TclDecrRefCount(hideName);
	} else {
	    /*
	     * Hide an ensemble main command (for compatibility).
	     */

            if (Tcl_HideCommand(interp, unsafePtr->ensembleNsName,
                    unsafePtr->ensembleNsName) != TCL_OK) {
                Tcl_Panic("problem making '%s' safe: %s",
                        unsafePtr->ensembleNsName,
                        Tcl_GetStringResult(interp));
            }
        }
	    if (Tcl_HideCommand(interp, unsafePtr->ensembleNsName,
		    unsafePtr->ensembleNsName) != TCL_OK) {
		Tcl_Panic("problem making '%s' safe: %s",
			unsafePtr->ensembleNsName,
			Tcl_GetStringResult(interp));
	    }
	}
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
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
1512
1513
1514
1515
1516
1517
1518

1519
1520
1521
1522
1523
1524
1525
1526



1527
1528
1529
1530
1531
1532
1533
1534
1535
1536







-
+







-
-
-
+
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
BadEnsembleSubcommand(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    TCL_UNUSED(int) /*objc*/,
    TCL_UNUSED(Tcl_Obj *const *) /* objv */)
{
    const UnsafeEnsembleInfo *infoPtr = (const UnsafeEnsembleInfo *)clientData;

    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
            "not allowed to invoke subcommand %s of %s",
            infoPtr->commandName, infoPtr->ensembleNsName));
    Tcl_SetErrorCode(interp, "TCL", "SAFE", "SUBCOMMAND", NULL);
	    "not allowed to invoke subcommand %s of %s",
	    infoPtr->commandName, infoPtr->ensembleNsName));
    Tcl_SetErrorCode(interp, "TCL", "SAFE", "SUBCOMMAND", (char *)NULL);
    return TCL_ERROR;
}

/*
 *--------------------------------------------------------------
 *
 * Tcl_CallWhenDeleted --
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
1387
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







-
+



-
-
+
+





-
+







 */

void
Tcl_CallWhenDeleted(
    Tcl_Interp *interp,		/* Interpreter to watch. */
    Tcl_InterpDeleteProc *proc,	/* Function to call when interpreter is about
				 * to be deleted. */
    ClientData clientData)	/* One-word value to pass to proc. */
    void *clientData)		/* One-word value to pass to proc. */
{
    Interp *iPtr = (Interp *) interp;
    static Tcl_ThreadDataKey assocDataCounterKey;
    int *assocDataCounterPtr =
	    (int *)Tcl_GetThreadData(&assocDataCounterKey, sizeof(int));
    int *assocDataCounterPtr = (int *)
	    Tcl_GetThreadData(&assocDataCounterKey, sizeof(int));
    int isNew;
    char buffer[32 + TCL_INTEGER_SPACE];
    AssocData *dPtr = (AssocData *)Tcl_Alloc(sizeof(AssocData));
    Tcl_HashEntry *hPtr;

    sprintf(buffer, "Assoc Data Key #%d", *assocDataCounterPtr);
    snprintf(buffer, sizeof(buffer), "Assoc Data Key #%d", *assocDataCounterPtr);
    (*assocDataCounterPtr)++;

    if (iPtr->assocData == NULL) {
	iPtr->assocData = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));
	Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);
    }
    hPtr = Tcl_CreateHashEntry(iPtr->assocData, buffer, &isNew);
1410
1411
1412
1413
1414
1415
1416
1417

1418
1419
1420
1421
1422
1423
1424
1600
1601
1602
1603
1604
1605
1606

1607
1608
1609
1610
1611
1612
1613
1614







-
+







 */

void
Tcl_DontCallWhenDeleted(
    Tcl_Interp *interp,		/* Interpreter to watch. */
    Tcl_InterpDeleteProc *proc,	/* Function to call when interpreter is about
				 * to be deleted. */
    ClientData clientData)	/* One-word value to pass to proc. */
    void *clientData)		/* One-word value to pass to proc. */
{
    Interp *iPtr = (Interp *) interp;
    Tcl_HashTable *hTablePtr;
    Tcl_HashSearch hSearch;
    Tcl_HashEntry *hPtr;
    AssocData *dPtr;

1458
1459
1460
1461
1462
1463
1464
1465

1466
1467
1468
1469
1470
1471
1472
1648
1649
1650
1651
1652
1653
1654

1655
1656
1657
1658
1659
1660
1661
1662







-
+








void
Tcl_SetAssocData(
    Tcl_Interp *interp,		/* Interpreter to associate with. */
    const char *name,		/* Name for association. */
    Tcl_InterpDeleteProc *proc,	/* Proc to call when interpreter is about to
				 * be deleted. */
    ClientData clientData)	/* One-word value to pass to proc. */
    void *clientData)		/* One-word value to pass to proc. */
{
    Interp *iPtr = (Interp *) interp;
    AssocData *dPtr;
    Tcl_HashEntry *hPtr;
    int isNew;

    if (iPtr->assocData == NULL) {
1515
1516
1517
1518
1519
1520
1521

1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547

1548
1549
1550
1551
1552
1553
1554
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







+




-




















-
+







	return;
    }
    hPtr = Tcl_FindHashEntry(iPtr->assocData, name);
    if (hPtr == NULL) {
	return;
    }
    dPtr = (AssocData *)Tcl_GetHashValue(hPtr);
    Tcl_DeleteHashEntry(hPtr);
    if (dPtr->proc != NULL) {
	dPtr->proc(dPtr->clientData, interp);
    }
    Tcl_Free(dPtr);
    Tcl_DeleteHashEntry(hPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetAssocData --
 *
 *	Returns the client data associated with this name in the specified
 *	interpreter.
 *
 * Results:
 *	The client data in the AssocData record denoted by the named
 *	association, or NULL.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

ClientData
void *
Tcl_GetAssocData(
    Tcl_Interp *interp,		/* Interpreter associated with. */
    const char *name,		/* Name of association. */
    Tcl_InterpDeleteProc **procPtr)
				/* Pointer to place to store address of
				 * current deletion callback. */
{
1640
1641
1642
1643
1644
1645
1646
1647

1648
1649
1650
1651
1652
1653
1654
1830
1831
1832
1833
1834
1835
1836

1837
1838
1839
1840
1841
1842
1843
1844







-
+







    iPtr->flags |= DELETED;
    iPtr->compileEpoch++;

    /*
     * Ensure that the interpreter is eventually deleted.
     */

    Tcl_EventuallyFree(interp, (Tcl_FreeProc *) DeleteInterpProc);
    Tcl_EventuallyFree(interp, DeleteInterpProc);
}

/*
 *----------------------------------------------------------------------
 *
 * DeleteInterpProc --
 *
1666
1667
1668
1669
1670
1671
1672
1673

1674

1675
1676
1677
1678
1679
1680

1681
1682
1683
1684
1685
1686
1687
1856
1857
1858
1859
1860
1861
1862

1863
1864
1865
1866
1867
1868
1869
1870

1871
1872
1873
1874
1875
1876
1877
1878







-
+

+





-
+







 *	by the interpreter.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteInterpProc(
    Tcl_Interp *interp)		/* Interpreter to delete. */
    void *blockPtr)		/* Interpreter to delete. */
{
    Tcl_Interp *interp = (Tcl_Interp *) blockPtr;
    Interp *iPtr = (Interp *) interp;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    Tcl_HashTable *hTablePtr;
    ResolverScheme *resPtr, *nextResPtr;
    int i;
    Tcl_Size i;

    /*
     * Punt if there is an error in the Tcl_Release/Tcl_Preserve matchup,
	 * unless we are exiting.
     */

    if ((iPtr->numLevels > 0) && !TclInExit()) {
1708
1709
1710
1711
1712
1713
1714
1715

1716
1717
1718
1719
1720
1721
1722
1899
1900
1901
1902
1903
1904
1905

1906
1907
1908
1909
1910
1911
1912
1913







-
+








    /*
     * TIP #285, Script cancellation support. Delete this interp from the
     * global hash table of CancelInfo structs.
     */

    Tcl_MutexLock(&cancelLock);
    hPtr = Tcl_FindHashEntry(&cancelTable, (char *) iPtr);
    hPtr = Tcl_FindHashEntry(&cancelTable, iPtr);
    if (hPtr != NULL) {
	CancelInfo *cancelInfo = (CancelInfo *)Tcl_GetHashValue(hPtr);

	if (cancelInfo != NULL) {
	    if (cancelInfo->result != NULL) {
		Tcl_Free(cancelInfo->result);
	    }
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786

1787
1788
1789
1790




1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802

1803
1804
1805
1806
1807
1808
1809
1965
1966
1967
1968
1969
1970
1971






1972
1973
1974
1975

1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999







-
-
-
-
-
-
+



-
+
+
+
+












+







	for (; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
	    Tcl_DeleteCommandFromToken(interp, (Tcl_Command)Tcl_GetHashValue(hPtr));
	}
	Tcl_DeleteHashTable(hTablePtr);
	Tcl_Free(hTablePtr);
    }

    /*
     * Invoke deletion callbacks; note that a callback can create new
     * callbacks, so we iterate.
     */

    while (iPtr->assocData != NULL) {
    if (iPtr->assocData != NULL) {
	AssocData *dPtr;

	hTablePtr = iPtr->assocData;
	iPtr->assocData = NULL;
	/*
	 * Invoke deletion callbacks; note that a callback can create new
	 * callbacks, so we iterate.
	 */
	for (hPtr = Tcl_FirstHashEntry(hTablePtr, &search);
		hPtr != NULL;
		hPtr = Tcl_FirstHashEntry(hTablePtr, &search)) {
	    dPtr = (AssocData *)Tcl_GetHashValue(hPtr);
	    Tcl_DeleteHashEntry(hPtr);
	    if (dPtr->proc != NULL) {
		dPtr->proc(dPtr->clientData, interp);
	    }
	    Tcl_Free(dPtr);
	}
	Tcl_DeleteHashTable(hTablePtr);
	Tcl_Free(hTablePtr);
	iPtr->assocData = NULL;
    }

    /*
     * Pop the root frame pointer and finish deleting the global
     * namespace. The order is important [Bug 1658572].
     */

1903
1904
1905
1906
1907
1908
1909
1910

1911
1912
1913
1914
1915
1916
1917
2093
2094
2095
2096
2097
2098
2099

2100
2101
2102
2103
2104
2105
2106
2107







-
+







	    hPtr != NULL;
	    hPtr = Tcl_NextHashEntry(&search)) {
	ExtCmdLoc *eclPtr = (ExtCmdLoc *)Tcl_GetHashValue(hPtr);

	if (eclPtr->type == TCL_LOCATION_SOURCE) {
	    Tcl_DecrRefCount(eclPtr->path);
	}
	for (i=0; i< eclPtr->nuloc; i++) {
	for (i=0; i<eclPtr->nuloc; i++) {
	    Tcl_Free(eclPtr->loc[i].line);
	}

	if (eclPtr->loc != NULL) {
	    Tcl_Free(eclPtr->loc);
	}

2026
2027
2028
2029
2030
2031
2032
2033
2034


2035
2036
2037
2038
2039
2040
2041
2216
2217
2218
2219
2220
2221
2222


2223
2224
2225
2226
2227
2228
2229
2230
2231







-
-
+
+







     * the source, in order to avoid potential confusion, lets prevent "::" in
     * the token too. - dl
     */

    if (strstr(hiddenCmdToken, "::") != NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"cannot use namespace qualifiers in hidden command"
		" token (rename)", -1));
        Tcl_SetErrorCode(interp, "TCL", "VALUE", "HIDDENTOKEN", NULL);
		" token (rename)", TCL_INDEX_NONE));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "HIDDENTOKEN", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Find the command to hide. An error is returned if cmdName can't be
     * found. Look up the command only from the global namespace. Full path of
     * the command must be given if using namespaces.
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059



2060
2061
2062
2063
2064
2065
2066
2240
2241
2242
2243
2244
2245
2246



2247
2248
2249
2250
2251
2252
2253
2254
2255
2256







-
-
-
+
+
+








    /*
     * Check that the command is really in global namespace
     */

    if (cmdPtr->nsPtr != iPtr->globalNsPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
                "can only hide global namespace commands (use rename then hide)",
                -1));
        Tcl_SetErrorCode(interp, "TCL", "HIDE", "NON_GLOBAL", NULL);
		"can only hide global namespace commands (use rename then hide)",
		TCL_INDEX_NONE));
	Tcl_SetErrorCode(interp, "TCL", "HIDE", "NON_GLOBAL", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Initialize the hidden command table if necessary.
     */

2076
2077
2078
2079
2080
2081
2082
2083
2084
2085



2086
2087
2088
2089
2090

2091
2092
2093
2094
2095
2096
2097
2098


2099
2100
2101
2102
2103
2104
2105
2266
2267
2268
2269
2270
2271
2272



2273
2274
2275
2276
2277
2278
2279

2280
2281
2282
2283
2284
2285
2286


2287
2288
2289
2290
2291
2292
2293
2294
2295







-
-
-
+
+
+




-
+






-
-
+
+







     * hiddenCmdToken if a hidden command with the name hiddenCmdToken already
     * exists.
     */

    hPtr = Tcl_CreateHashEntry(hiddenCmdTablePtr, hiddenCmdToken, &isNew);
    if (!isNew) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "hidden command named \"%s\" already exists",
                hiddenCmdToken));
        Tcl_SetErrorCode(interp, "TCL", "HIDE", "ALREADY_HIDDEN", NULL);
		"hidden command named \"%s\" already exists",
		hiddenCmdToken));
	Tcl_SetErrorCode(interp, "TCL", "HIDE", "ALREADY_HIDDEN", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * NB: This code is currently 'like' a rename to a specialy set apart name
     * NB: This code is currently 'like' a rename to a special separate name
     * table. Changes here and in TclRenameCommand must be kept in synch until
     * the common parts are actually factorized out.
     */

    /*
     * Remove the hash entry for the command from the interpreter command
     * table. This is like deleting the command, so bump its command epoch;
     * this invalidates any cached references that point to the command.
     * table. This is like deleting the command, so bump its command epoch
     * to invalidate any cached references that point to the command.
     */

    if (cmdPtr->hPtr != NULL) {
	Tcl_DeleteHashEntry(cmdPtr->hPtr);
	cmdPtr->hPtr = NULL;
	cmdPtr->cmdEpoch++;
    }
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
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
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
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408

2409
2410
2411
2412
2413
2414

2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432


2433
2434
2435
2436
2437
2438
2439
2440
2441







-
-
-
+
+
+














-
-
-
+
+
+












-
+





-
+

















-
-
+
+







     * Check that we have a regular name for the command (that the user is not
     * trying to do an expose and a rename (to another namespace) at the same
     * time).
     */

    if (strstr(cmdName, "::") != NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
                "cannot expose to a namespace (use expose to toplevel, then rename)",
                -1));
        Tcl_SetErrorCode(interp, "TCL", "EXPOSE", "NON_GLOBAL", NULL);
		"cannot expose to a namespace (use expose to toplevel, then rename)",
		TCL_INDEX_NONE));
	Tcl_SetErrorCode(interp, "TCL", "EXPOSE", "NON_GLOBAL", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Get the command from the hidden command table:
     */

    hPtr = NULL;
    hiddenCmdTablePtr = iPtr->hiddenCmdTablePtr;
    if (hiddenCmdTablePtr != NULL) {
	hPtr = Tcl_FindHashEntry(hiddenCmdTablePtr, hiddenCmdToken);
    }
    if (hPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "unknown hidden command \"%s\"", hiddenCmdToken));
        Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "HIDDENTOKEN",
                hiddenCmdToken, NULL);
		"unknown hidden command \"%s\"", hiddenCmdToken));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "HIDDENTOKEN",
		hiddenCmdToken, (char *)NULL);
	return TCL_ERROR;
    }
    cmdPtr = (Command *)Tcl_GetHashValue(hPtr);

    /*
     * Check that we have a true global namespace command (enforced by
     * Tcl_HideCommand but let's double check. (If it was not, we would not
     * really know how to handle it).
     */

    if (cmdPtr->nsPtr != iPtr->globalNsPtr) {
	/*
	 * This case is theoritically impossible, we might rather Tcl_Panic
	 * This case is theoretically impossible, we might rather Tcl_Panic
	 * than 'nicely' erroring out ?
	 */

	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"trying to expose a non-global command namespace command",
		-1));
		TCL_INDEX_NONE));
	return TCL_ERROR;
    }

    /*
     * This is the global table.
     */

    nsPtr = cmdPtr->nsPtr;

    /*
     * It is an error to overwrite an existing exposed command as a result of
     * exposing a previously hidden command.
     */

    hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, cmdName, &isNew);
    if (!isNew) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "exposed command \"%s\" already exists", cmdName));
        Tcl_SetErrorCode(interp, "TCL", "EXPOSE", "COMMAND_EXISTS", NULL);
		"exposed command \"%s\" already exists", cmdName));
	Tcl_SetErrorCode(interp, "TCL", "EXPOSE", "COMMAND_EXISTS", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Command resolvers (per-interp, per-namespace) might have resolved to a
     * command for the given namespace scope with this command not being
     * registered with the namespace's command table. During BC compilation,
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
2508
2509
2510
2511
2512
2513
2514

2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530

2531
2532
2533
2534
2535
2536
2537
2538







-
+















-
+







 *	future calls to Tcl_GetCommandName.
 *
 * Side effects:
 *	If a command named cmdName already exists for interp, it is deleted.
 *	In the future, when cmdName is seen as the name of a command by
 *	Tcl_Eval, proc will be called. To support the bytecode interpreter,
 *	the command is created with a wrapper Tcl_ObjCmdProc
 *	(TclInvokeStringCommand) that eventially calls proc. When the command
 *	(InvokeStringCommand) that eventually calls proc. When the command
 *	is deleted from the table, deleteProc will be called. See the manual
 *	entry for details on the calling sequence.
 *
 *----------------------------------------------------------------------
 */

Tcl_Command
Tcl_CreateCommand(
    Tcl_Interp *interp,		/* Token for command interpreter returned by a
				 * previous call to Tcl_CreateInterp. */
    const char *cmdName,	/* Name of command. If it contains namespace
				 * qualifiers, the new command is put in the
				 * specified namespace; otherwise it is put in
				 * the global namespace. */
    Tcl_CmdProc *proc,		/* Function to associate with cmdName. */
    ClientData clientData,	/* Arbitrary value passed to string proc. */
    void *clientData,		/* Arbitrary value passed to string proc. */
    Tcl_CmdDeleteProc *deleteProc)
				/* If not NULL, gives a function to call when
				 * this command is deleted. */
{
    Interp *iPtr = (Interp *) interp;
    ImportRef *oldRefPtr = NULL;
    Namespace *nsPtr;
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
2399
2400
2401
2402
2403


2404
2405
2406
2407
2408
2409
2410
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







-
-
-
+
+
+

-
+

-
+





-
+

-
+


-
+

-
+










-
-
+
+







     * If the command name we seek to create already exists, we need to
     * delete that first.  That can be tricky in the presence of traces.
     * Loop until we no longer find an existing command in the way, or
     * until we've deleted one command and that didn't finish the job.
     */

    while (1) {
        /*
         * Determine where the command should reside. If its name contains
         * namespace qualifiers, we put it in the specified namespace;
	/*
	 * Determine where the command should reside. If its name contains
	 * namespace qualifiers, we put it in the specified namespace;
	 * otherwise, we always put it in the global namespace.
         */
	 */

        if (strstr(cmdName, "::") != NULL) {
	if (strstr(cmdName, "::") != NULL) {
	    Namespace *dummy1, *dummy2;

	    TclGetNamespaceForQualName(interp, cmdName, NULL,
		    TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
	    if ((nsPtr == NULL) || (tail == NULL)) {
	        return (Tcl_Command) NULL;
		return (Tcl_Command) NULL;
	    }
        } else {
	} else {
	    nsPtr = iPtr->globalNsPtr;
	    tail = cmdName;
        }
	}

        hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
	hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);

	if (isNew || deleted) {
	    /*
	     * isNew - No conflict with existing command.
	     * deleted - We've already deleted a conflicting command
	     */
	    break;
	}

	/*
         * An existing command conflicts. Try to delete it...
         */
	 * An existing command conflicts. Try to delete it...
	 */

	cmdPtr = (Command *)Tcl_GetHashValue(hPtr);

	/*
	 * Be careful to preserve any existing import links so we can restore
	 * them down below. That way, you can redefine a command and its
	 * import status will remain intact.
2460
2461
2462
2463
2464
2465
2466
2467

2468
2469
2470
2471
2472
2473
2474
2650
2651
2652
2653
2654
2655
2656

2657
2658
2659
2660
2661
2662
2663
2664







-
+







    cmdPtr = (Command *)Tcl_Alloc(sizeof(Command));
    Tcl_SetHashValue(hPtr, cmdPtr);
    cmdPtr->hPtr = hPtr;
    cmdPtr->nsPtr = nsPtr;
    cmdPtr->refCount = 1;
    cmdPtr->cmdEpoch = 0;
    cmdPtr->compileProc = NULL;
    cmdPtr->objProc = TclInvokeStringCommand;
    cmdPtr->objProc = InvokeStringCommand;
    cmdPtr->objClientData = cmdPtr;
    cmdPtr->proc = proc;
    cmdPtr->clientData = clientData;
    cmdPtr->deleteProc = deleteProc;
    cmdPtr->deleteData = clientData;
    cmdPtr->flags = 0;
    cmdPtr->importRefPtr = NULL;
2520
2521
2522
2523
2524
2525
2526































































2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538

2539
2540

2541
2542
2543
2544
2545

2546
2547
2548
2549
2550
2551
2552
2553
2554

2555
2556
2557
2558
2559
2560
2561
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
+

-
+


-

-
+








-
+







 *	the name of a command by Tcl_EvalObj or Tcl_Eval, the object-based
 *	Tcl_ObjCmdProc proc will be called. When the command is deleted from
 *	the table, deleteProc will be called. See the manual entry for details
 *	on the calling sequence.
 *
 *----------------------------------------------------------------------
 */

typedef struct {
    Tcl_ObjCmdProc2 *proc;
    void *clientData; /* Arbitrary value to pass to proc function. */
    Tcl_CmdDeleteProc *deleteProc;
    void *deleteData; /* Arbitrary value to pass to deleteProc function. */
    Tcl_ObjCmdProc2 *nreProc;
} CmdWrapperInfo;

static int
cmdWrapperProc(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj * const *objv)
{
    CmdWrapperInfo *info = (CmdWrapperInfo *) clientData;
    if (objc < 0) {
	objc = -1;
    }
    return info->proc(info->clientData, interp, objc, objv);
}

static void
cmdWrapperDeleteProc(
    void *clientData)
{
    CmdWrapperInfo *info = (CmdWrapperInfo *) clientData;

    clientData = info->deleteData;
    Tcl_CmdDeleteProc *deleteProc = info->deleteProc;
    Tcl_Free(info);
    if (deleteProc != NULL) {
	deleteProc(clientData);
    }
}

Tcl_Command
Tcl_CreateObjCommand2(
    Tcl_Interp *interp,		/* Token for command interpreter (returned by
				 * previous call to Tcl_CreateInterp). */
    const char *cmdName,	/* Name of command. If it contains namespace
				 * qualifiers, the new command is put in the
				 * specified namespace; otherwise it is put in
				 * the global namespace. */
    Tcl_ObjCmdProc2 *proc,	/* Object-based function to associate with
				 * name. */
    void *clientData,		/* Arbitrary value to pass to object
				 * function. */
    Tcl_CmdDeleteProc *deleteProc)
				/* If not NULL, gives a function to call when
				 * this command is deleted. */
{
    CmdWrapperInfo *info = (CmdWrapperInfo *)Tcl_Alloc(sizeof(CmdWrapperInfo));
    info->proc = proc;
    info->clientData = clientData;
    info->deleteProc = deleteProc;
    info->deleteData = clientData;

    return Tcl_CreateObjCommand(interp, cmdName,
	    (proc ? cmdWrapperProc : NULL),
	    info, cmdWrapperDeleteProc);
}

Tcl_Command
Tcl_CreateObjCommand(
    Tcl_Interp *interp,		/* Token for command interpreter (returned by
				 * previous call to Tcl_CreateInterp). */
    const char *cmdName,	/* Name of command. If it contains namespace
				 * qualifiers, the new command is put in the
				 * specified namespace; otherwise it is put in
				 * the global namespace. */
    Tcl_ObjCmdProc *proc,	/* Object-based function to associate with
				 * name. */
    ClientData clientData,	/* Arbitrary value to pass to object
    void *clientData,		/* Arbitrary value to pass to object
				 * function. */
    Tcl_CmdDeleteProc *deleteProc
    Tcl_CmdDeleteProc *deleteProc)
				/* If not NULL, gives a function to call when
				 * this command is deleted. */
)
{
    Interp *iPtr = (Interp *) interp;
    Interp *iPtr = (Interp *)interp;
    Namespace *nsPtr;
    const char *tail;

    if (iPtr->flags & DELETED) {
	/*
	 * The interpreter is being deleted. Don't create any new commands;
	 * it's not safe to muck with the interpreter anymore.
	 */
	return (Tcl_Command) NULL;
	return NULL;
    }

    /*
     * Determine where the command should reside. If its name contains
     * namespace qualifiers, we put it in the specified namespace;
     * otherwise, we always put it in the global namespace.
     */
2577
2578
2579
2580
2581
2582
2583
2584
2585


2586
2587
2588

2589
2590
2591
2592
2593
2594
2595
2829
2830
2831
2832
2833
2834
2835


2836
2837
2838
2839

2840
2841
2842
2843
2844
2845
2846
2847







-
-
+
+


-
+







	proc, clientData, deleteProc);
}

Tcl_Command
TclCreateObjCommandInNs(
    Tcl_Interp *interp,
    const char *cmdName,	/* Name of command, without any namespace
                                 * components. */
    Tcl_Namespace *namesp,   /* The namespace to create the command in */
				 * components. */
    Tcl_Namespace *namesp,	/* The namespace to create the command in */
    Tcl_ObjCmdProc *proc,	/* Object-based function to associate with
				 * name. */
    ClientData clientData,	/* Arbitrary value to pass to object
    void *clientData,		/* Arbitrary value to pass to object
				 * function. */
    Tcl_CmdDeleteProc *deleteProc)
				/* If not NULL, gives a function to call when
				 * this command is deleted. */
{
    int deleted = 0, isNew = 0;
    Command *cmdPtr;
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
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







-
-
+
+
















-
-
+
+





-
+







	     * isNew - No conflict with existing command.
	     * deleted - We've already deleted a conflicting command
	     */
	    break;
	}

	/*
         * An existing command conflicts. Try to delete it...
         */
	 * An existing command conflicts. Try to delete it...
	 */

	cmdPtr = (Command *)Tcl_GetHashValue(hPtr);

	/*
	 * Command already exists; delete it. Be careful to preserve any
	 * existing import links so we can restore them down below. That way,
	 * you can redefine a command and its import status will remain
	 * intact.
	 */

	cmdPtr->refCount++;
	if (cmdPtr->importRefPtr) {
	    cmdPtr->flags |= CMD_REDEF_IN_PROGRESS;
	}

	/*
         * Make sure namespace doesn't get deallocated.
         */
	 * Make sure namespace doesn't get deallocated.
	 */

	cmdPtr->nsPtr->refCount++;

	Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
	nsPtr = (Namespace *) TclEnsureNamespace(interp,
                (Tcl_Namespace *) cmdPtr->nsPtr);
		(Tcl_Namespace *) cmdPtr->nsPtr);
	TclNsDecrRefCount(cmdPtr->nsPtr);

	if (cmdPtr->flags & CMD_REDEF_IN_PROGRESS) {
	    oldRefPtr = cmdPtr->importRefPtr;
	    cmdPtr->importRefPtr = NULL;
	}
	TclCleanupCommandMacro(cmdPtr);
2689
2690
2691
2692
2693
2694
2695
2696

2697
2698
2699
2700
2701
2702
2703
2941
2942
2943
2944
2945
2946
2947

2948
2949
2950
2951
2952
2953
2954
2955







-
+







    cmdPtr->hPtr = hPtr;
    cmdPtr->nsPtr = nsPtr;
    cmdPtr->refCount = 1;
    cmdPtr->cmdEpoch = 0;
    cmdPtr->compileProc = NULL;
    cmdPtr->objProc = proc;
    cmdPtr->objClientData = clientData;
    cmdPtr->proc = TclInvokeObjectCommand;
    cmdPtr->proc = NULL;
    cmdPtr->clientData = cmdPtr;
    cmdPtr->deleteProc = deleteProc;
    cmdPtr->deleteData = clientData;
    cmdPtr->flags = 0;
    cmdPtr->importRefPtr = NULL;
    cmdPtr->tracePtr = NULL;
    cmdPtr->nreProc = NULL;
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
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







-
+












-
+





-
-
+
+







    TclResetShadowedCmdRefs(interp, cmdPtr);
    return (Tcl_Command) cmdPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TclInvokeStringCommand --
 * InvokeStringCommand --
 *
 *	"Wrapper" Tcl_ObjCmdProc used to call an existing string-based
 *	Tcl_CmdProc if no object-based function exists for a command. A
 *	pointer to this function is stored as the Tcl_ObjCmdProc in a Command
 *	structure. It simply turns around and calls the string Tcl_CmdProc in
 *	the Command structure.
 *
 * Results:
 *	A standard Tcl object result value.
 *
 * Side effects:
 *	Besides those side effects of the called Tcl_CmdProc,
 *	TclInvokeStringCommand allocates and frees storage.
 *	InvokeStringCommand allocates and frees storage.
 *
 *----------------------------------------------------------------------
 */

int
TclInvokeStringCommand(
    ClientData clientData,	/* Points to command's Command structure. */
InvokeStringCommand(
    void *clientData,	/* Points to command's Command structure. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,		/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Command *cmdPtr = (Command *)clientData;
    int i, result;
    const char **argv = (const char **)
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
3026
3027
3028
3029
3030
3031
3032

































































3033
3034
3035
3036
3037
3038
3039







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







     */

    result = cmdPtr->proc(cmdPtr->clientData, interp, objc, argv);

    TclStackFree(interp, (void *) argv);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TclInvokeObjectCommand --
 *
 *	"Wrapper" Tcl_CmdProc used to call an existing object-based
 *	Tcl_ObjCmdProc if no string-based function exists for a command. A
 *	pointer to this function is stored as the Tcl_CmdProc in a Command
 *	structure. It simply turns around and calls the object Tcl_ObjCmdProc
 *	in the Command structure.
 *
 * Results:
 *	A standard Tcl result value.
 *
 * Side effects:
 *	Besides those side effects of the called Tcl_ObjCmdProc,
 *	TclInvokeObjectCommand allocates and frees storage.
 *
 *----------------------------------------------------------------------
 */

int
TclInvokeObjectCommand(
    ClientData clientData,	/* Points to command's Command structure. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)	/* Argument strings. */
{
    Command *cmdPtr = ( Command *) clientData;
    Tcl_Obj *objPtr;
    int i, length, result;
    Tcl_Obj **objv = (Tcl_Obj **)
	    TclStackAlloc(interp, (argc * sizeof(Tcl_Obj *)));

    for (i = 0; i < argc; i++) {
	length = strlen(argv[i]);
	TclNewStringObj(objPtr, argv[i], length);
	Tcl_IncrRefCount(objPtr);
	objv[i] = objPtr;
    }

    /*
     * Invoke the command's object-based Tcl_ObjCmdProc.
     */

    if (cmdPtr->objProc != NULL) {
	result = cmdPtr->objProc(cmdPtr->objClientData, interp, argc, objv);
    } else {
	result = Tcl_NRCallObjProc(interp, cmdPtr->nreProc,
		cmdPtr->objClientData, argc, objv);
    }

    /*
     * Decrement the ref counts for the argument objects created above, then
     * free the objv array if malloc'ed storage was used.
     */

    for (i = 0; i < argc; i++) {
	objPtr = objv[i];
	Tcl_DecrRefCount(objPtr);
    }
    TclStackFree(interp, objv);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TclRenameCommand --
 *
 *	Called to give an existing Tcl command a different name. Both the old
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
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







-
-
+
+

-
+














-
+






-
+







-
-
+
+





-
-
-
+
+
+







     * found.
     */

    cmd = Tcl_FindCommand(interp, oldName, NULL, /*flags*/ 0);
    cmdPtr = (Command *) cmd;
    if (cmdPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "can't %s \"%s\": command doesn't exist",
		((newName == NULL)||(*newName == '\0'))? "delete":"rename",
		"can't %s \"%s\": command doesn't exist",
		((newName == NULL) || (*newName == '\0')) ? "delete" : "rename",
		oldName));
        Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", oldName, NULL);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", oldName, (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * If the new command name is NULL or empty, delete the command. Do this
     * with Tcl_DeleteCommandFromToken, since we already have the command.
     */

    if ((newName == NULL) || (*newName == '\0')) {
	Tcl_DeleteCommandFromToken(interp, cmd);
	return TCL_OK;
    }

    cmdNsPtr = cmdPtr->nsPtr;
    oldFullName = Tcl_NewObj();
    TclNewObj(oldFullName);
    Tcl_IncrRefCount(oldFullName);
    Tcl_GetCommandFullName(interp, cmd, oldFullName);

    /*
     * Make sure that the destination command does not already exist. The
     * rename operation is like creating a command, so we should automatically
     * create the containing namespaces just like Tcl_CreateCommand would.
     * create the containing namespaces just like Tcl_CreateObjCommand would.
     */

    TclGetNamespaceForQualName(interp, newName, NULL,
	    TCL_CREATE_NS_IF_UNKNOWN, &newNsPtr, &dummy1, &dummy2, &newTail);

    if ((newNsPtr == NULL) || (newTail == NULL)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "can't rename to \"%s\": bad command name", newName));
        Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", NULL);
		"can't rename to \"%s\": bad command name", newName));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", (char *)NULL);
	result = TCL_ERROR;
	goto done;
    }
    if (Tcl_FindHashEntry(&newNsPtr->cmdTable, newTail) != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "can't rename to \"%s\": command already exists", newName));
        Tcl_SetErrorCode(interp, "TCL", "OPERATION", "RENAME",
                "TARGET_EXISTS", NULL);
		"can't rename to \"%s\": command already exists", newName));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "RENAME",
		"TARGET_EXISTS", (char *)NULL);
	result = TCL_ERROR;
	goto done;
    }

    /*
     * Warning: any changes done in the code here are likely to be needed in
     * Tcl_HideCommand code too (until the common parts are extracted out).
3002
3003
3004
3005
3006
3007
3008
3009

3010
3011
3012
3013

3014
3015
3016
3017
3018
3019
3020
3189
3190
3191
3192
3193
3194
3195

3196
3197
3198
3199

3200
3201
3202
3203
3204
3205
3206
3207







-
+



-
+







     * The trace function needs to get a fully qualified name for old and new
     * commands [Tcl bug #651271], or else there's no way for the trace
     * function to get the namespace from which the old command is being
     * renamed!
     */

    Tcl_DStringInit(&newFullName);
    Tcl_DStringAppend(&newFullName, newNsPtr->fullName, -1);
    Tcl_DStringAppend(&newFullName, newNsPtr->fullName, TCL_INDEX_NONE);
    if (newNsPtr != iPtr->globalNsPtr) {
	TclDStringAppendLiteral(&newFullName, "::");
    }
    Tcl_DStringAppend(&newFullName, newTail, -1);
    Tcl_DStringAppend(&newFullName, newTail, TCL_INDEX_NONE);
    cmdPtr->refCount++;
    CallCommandTraces(iPtr, cmdPtr, TclGetString(oldFullName),
	    Tcl_DStringValue(&newFullName), TCL_TRACE_RENAME);
    Tcl_DStringFree(&newFullName);

    /*
     * The new command name is okay, so remove the command from its current
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
3134
3135
3136


























3137
3138




3139
3140
3141
3142
3143
3144
3145
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349

3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385


3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




















-
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+







 *	returned. If the command doesn't exist then 0 is returned.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
invokeObj2Command(
    void *clientData,		/* Points to command's Command structure. */
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Size objc,		/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int result;
    Command *cmdPtr = (Command *)clientData;

    if (objc > INT_MAX) {
	return TclCommandWordLimitError(interp, objc);
    }
    if (cmdPtr->objProc != NULL) {
	result = cmdPtr->objProc(cmdPtr->objClientData, interp, objc, objv);
    } else {
	result = Tcl_NRCallObjProc(interp, cmdPtr->nreProc,
		cmdPtr->objClientData, objc, objv);
    }
    return result;
}

static int
cmdWrapper2Proc(
    void *clientData,
    Tcl_Interp *interp,
    Tcl_Size objc,
    Tcl_Obj *const objv[])
{
    Command *cmdPtr = (Command *) clientData;
    if (objc > INT_MAX) {
	return TclCommandWordLimitError(interp, objc);
    }
    return cmdPtr->objProc(cmdPtr->objClientData, interp, objc, objv);
}

int
Tcl_SetCommandInfoFromToken(
    Tcl_Command cmd,
    const Tcl_CmdInfo *infoPtr)
{
    Command *cmdPtr;		/* Internal representation of the command */

    if (cmd == NULL) {
	return 0;
    }

    /*
     * The isNativeObjectProc and nsPtr members of *infoPtr are ignored.
     */

    cmdPtr = (Command *) cmd;
    cmdPtr->proc = infoPtr->proc;
    cmdPtr->clientData = infoPtr->clientData;
    if (infoPtr->objProc == NULL) {
	cmdPtr->objProc = TclInvokeStringCommand;
	cmdPtr->objProc = InvokeStringCommand;
	cmdPtr->objClientData = cmdPtr;
	cmdPtr->nreProc = NULL;
    } else {
	if (infoPtr->objProc != cmdPtr->objProc) {
	    cmdPtr->nreProc = NULL;
	    cmdPtr->objProc = infoPtr->objProc;
	}
	cmdPtr->objClientData = infoPtr->objClientData;
    }
    if (cmdPtr->deleteProc == cmdWrapperDeleteProc) {
	CmdWrapperInfo *info = (CmdWrapperInfo *) cmdPtr->deleteData;
	if (infoPtr->objProc2 == NULL) {
	    info->proc = invokeObj2Command;
	    info->clientData = cmdPtr;
	    info->nreProc = NULL;
	} else {
	    if (infoPtr->objProc2 != info->proc) {
		info->nreProc = NULL;
		info->proc = infoPtr->objProc2;
	    }
	    info->clientData = infoPtr->objClientData2;
	}
	info->deleteProc = infoPtr->deleteProc;
	info->deleteData = infoPtr->deleteData;
    } else {
	if ((infoPtr->objProc2 != NULL) && (infoPtr->objProc2 != cmdWrapper2Proc)) {
	    CmdWrapperInfo *info = (CmdWrapperInfo *)Tcl_Alloc(sizeof(CmdWrapperInfo));
	    info->proc = infoPtr->objProc2;
	    info->clientData = infoPtr->objClientData2;
	    info->nreProc = NULL;
	    info->deleteProc = infoPtr->deleteProc;
	    info->deleteData = infoPtr->deleteData;
	    cmdPtr->deleteProc = cmdWrapperDeleteProc;
	    cmdPtr->deleteData = info;
	} else {
    cmdPtr->deleteProc = infoPtr->deleteProc;
    cmdPtr->deleteData = infoPtr->deleteData;
	    cmdPtr->deleteProc = infoPtr->deleteProc;
	    cmdPtr->deleteData = infoPtr->deleteData;
	}
    }
    return 1;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetCommandInfo --
3198
3199
3200
3201
3202
3203
3204
3205


3206
3207
3208
3209
3210

3211
3212
3213
3214










3215
3216
3217
3218






3219
3220
3221
3222
3223
3224
3225
3226
3227

3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243

3244
3245
3246
3247
3248
3249
3250
3449
3450
3451
3452
3453
3454
3455

3456
3457
3458
3459
3460
3461

3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476




3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490

3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506

3507
3508
3509
3510
3511
3512
3513
3514







-
+
+




-
+




+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+








-
+















-
+








    if (cmd == NULL) {
	return 0;
    }

    /*
     * Set isNativeObjectProc 1 if objProc was registered by a call to
     * Tcl_CreateObjCommand. Otherwise set it to 0.
     * Tcl_CreateObjCommand. Set isNativeObjectProc 2 if objProc was
     * registered by a call to Tcl_CreateObjCommand2. Otherwise set it to 0.
     */

    cmdPtr = (Command *) cmd;
    infoPtr->isNativeObjectProc =
	    (cmdPtr->objProc != TclInvokeStringCommand);
	    (cmdPtr->objProc != InvokeStringCommand);
    infoPtr->objProc = cmdPtr->objProc;
    infoPtr->objClientData = cmdPtr->objClientData;
    infoPtr->proc = cmdPtr->proc;
    infoPtr->clientData = cmdPtr->clientData;
    if (cmdPtr->deleteProc == cmdWrapperDeleteProc) {
	CmdWrapperInfo *info = (CmdWrapperInfo *)cmdPtr->deleteData;
	infoPtr->deleteProc = info->deleteProc;
	infoPtr->deleteData = info->deleteData;
	infoPtr->objProc2 = info->proc;
	infoPtr->objClientData2 = info->clientData;
	if (cmdPtr->objProc == cmdWrapperProc) {
	    infoPtr->isNativeObjectProc = 2;
	}
    } else {
    infoPtr->deleteProc = cmdPtr->deleteProc;
    infoPtr->deleteData = cmdPtr->deleteData;
    infoPtr->namespacePtr = (Tcl_Namespace *) cmdPtr->nsPtr;

	infoPtr->deleteProc = cmdPtr->deleteProc;
	infoPtr->deleteData = cmdPtr->deleteData;
	infoPtr->objProc2 = cmdWrapper2Proc;
	infoPtr->objClientData2 = cmdPtr;
    }
    infoPtr->namespacePtr = (Tcl_Namespace *) cmdPtr->nsPtr;
    return 1;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetCommandName --
 *
 *	Given a token returned by Tcl_CreateCommand, this function returns the
 *	Given a token returned by Tcl_CreateObjCommand, this function returns the
 *	current name of the command (which may have changed due to renaming).
 *
 * Results:
 *	The return value is the name of the given command.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

const char *
Tcl_GetCommandName(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Command command)	/* Token for command returned by a previous
				 * call to Tcl_CreateCommand. The command must
				 * call to Tcl_CreateObjCommand. The command must
				 * not have been deleted. */
{
    Command *cmdPtr = (Command *) command;

    if ((cmdPtr == NULL) || (cmdPtr->hPtr == NULL)) {
	/*
	 * This should only happen if command was "created" after the
3259
3260
3261
3262
3263
3264
3265
3266

3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285

3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302

3303
3304
3305
3306
3307
3308
3309

3310
3311
3312
3313
3314
3315
3316
3523
3524
3525
3526
3527
3528
3529

3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548

3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565

3566
3567
3568
3569
3570
3571
3572

3573
3574
3575
3576
3577
3578
3579
3580







-
+


















-
+
















-
+






-
+







}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetCommandFullName --
 *
 *	Given a token returned by, e.g., Tcl_CreateCommand or Tcl_FindCommand,
 *	Given a token returned by, e.g., Tcl_CreateObjCommand or Tcl_FindCommand,
 *	this function appends to an object the command's full name, qualified
 *	by a sequence of parent namespace names. The command's fully-qualified
 *	name may have changed due to renaming.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The command's fully-qualified name is appended to the string
 *	representation of objPtr.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_GetCommandFullName(
    Tcl_Interp *interp,		/* Interpreter containing the command. */
    Tcl_Command command,	/* Token for command returned by a previous
				 * call to Tcl_CreateCommand. The command must
				 * call to Tcl_CreateObjCommand. The command must
				 * not have been deleted. */
    Tcl_Obj *objPtr)		/* Points to the object onto which the
				 * command's full name is appended. */

{
    Interp *iPtr = (Interp *) interp;
    Command *cmdPtr = (Command *) command;
    char *name;

    /*
     * Add the full name of the containing namespace, followed by the "::"
     * separator, and the command name.
     */

    if ((cmdPtr != NULL) && TclRoutineHasName(cmdPtr)) {
	if (cmdPtr->nsPtr != NULL) {
	    Tcl_AppendToObj(objPtr, cmdPtr->nsPtr->fullName, -1);
	    Tcl_AppendToObj(objPtr, cmdPtr->nsPtr->fullName, TCL_INDEX_NONE);
	    if (cmdPtr->nsPtr != iPtr->globalNsPtr) {
		Tcl_AppendToObj(objPtr, "::", 2);
	    }
	}
	if (cmdPtr->hPtr != NULL) {
	    name = (char *)Tcl_GetHashKey(cmdPtr->hPtr->tablePtr, cmdPtr->hPtr);
	    Tcl_AppendToObj(objPtr, name, -1);
	    Tcl_AppendToObj(objPtr, name, TCL_INDEX_NONE);
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
3418
3419
3420
3421
3422
3423
3424
3425

3426
3427
3428
3429
3430
3431
3432


3433
3434
3435
3436
3437
3438
3439
3682
3683
3684
3685
3686
3687
3688

3689

3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704







-
+
-






+
+







     * declares that a delete is in progress and that recursive deletes should
     * be ignored.
     */

    cmdPtr->flags |= CMD_DYING;

    /*
     * Call trace functions for the command being deleted. Then delete its
     * Call each functions and then delete the trace.
     * traces.
     */

    cmdPtr->nsPtr->refCount++;

    if (cmdPtr->tracePtr != NULL) {
	CommandTrace *tracePtr;
	/* CallCommandTraces() does not cmdPtr, that's
	 * done just before Tcl_DeleteCommandFromToken() returns */
	CallCommandTraces(iPtr,cmdPtr,NULL,NULL,TCL_TRACE_DELETE);

	/*
	 * Now delete these traces.
	 */

	tracePtr = cmdPtr->tracePtr;
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3860
3861
3862
3863
3864
3865
3866

3867
3868
3869
3870
3871
3872
3873







-







	    flags &= ~TCL_TRACE_RENAME;
	}
	if (flags == 0) {
	    return NULL;
	}
    }
    cmdPtr->flags |= CMD_TRACE_ACTIVE;
    cmdPtr->refCount++;

    result = NULL;
    active.nextPtr = iPtr->activeCmdTracePtr;
    active.reverseScan = 0;
    iPtr->activeCmdTracePtr = &active;

    if (flags & TCL_TRACE_DELETE) {
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681

3682
3683
3684
3685
3686
3687
3688

3689
3690
3691
3692
3693
3694
3695
3917
3918
3919
3920
3921
3922
3923

3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943

3944
3945
3946
3947
3948
3949
3950

3951
3952
3953
3954
3955
3956
3957
3958







-




















-
+






-
+








    /*
     * Restore the variable's flags, remove the record of our active traces,
     * and then return.
     */

    cmdPtr->flags &= ~CMD_TRACE_ACTIVE;
    cmdPtr->refCount--;
    iPtr->activeCmdTracePtr = active.nextPtr;
    Tcl_Release(iPtr);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * CancelEvalProc --
 *
 *	Marks this interpreter as being canceled. This causes current
 *	executions to be unwound as the interpreter enters a state where it
 *	refuses to execute more commands or handle [catch] or [try], yet the
 *	interpreter is still able to execute further commands after the
 *	cancelation is cleared (unlike if it is deleted).
 *
 * Results:
 *	The value given for the code argument.
 *
 * Side effects:
 *	Transfers a message from the cancelation message to the interpreter.
 *	Transfers a message from the cancellation message to the interpreter.
 *
 *----------------------------------------------------------------------
 */

static int
CancelEvalProc(
    ClientData clientData,	/* Interp to cancel the script in progress. */
    void *clientData,	/* Interp to cancel the script in progress. */
    TCL_UNUSED(Tcl_Interp *),
    int code)			/* Current return code from command. */
{
    CancelInfo *cancelInfo = (CancelInfo *)clientData;
    Interp *iPtr;

    if (cancelInfo != NULL) {
3804
3805
3806
3807
3808
3809
3810
3811

3812
3813

3814
3815
3816
3817
3818
3819
3820
4067
4068
4069
4070
4071
4072
4073

4074
4075

4076
4077
4078
4079
4080
4081
4082
4083







-
+

-
+








    /*
     * If the interpreter has been deleted, return an error.
     */

    if (iPtr->flags & DELETED) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to call eval in deleted interpreter", -1));
		"attempt to call eval in deleted interpreter", TCL_INDEX_NONE));
	Tcl_SetErrorCode(interp, "TCL", "IDELETE",
		"attempt to call eval in deleted interpreter", NULL);
		"attempt to call eval in deleted interpreter", (char *)NULL);
	return TCL_ERROR;
    }

    if (iPtr->execEnvPtr->rewind) {
	return TCL_ERROR;
    }

3828
3829
3830
3831
3832
3833
3834
3835

3836
3837
3838
3839
3840
3841


3842
3843
3844
3845
3846
3847
3848
4091
4092
4093
4094
4095
4096
4097

4098
4099
4100
4101
4102


4103
4104
4105
4106
4107
4108
4109
4110
4111







-
+




-
-
+
+







    }

    /*
     * Check depth of nested calls to Tcl_Eval: if this gets too large, it's
     * probably because of an infinite loop somewhere.
     */

    if (((iPtr->numLevels) <= iPtr->maxNestingDepth)) {
    if ((iPtr->numLevels <= iPtr->maxNestingDepth)) {
	return TCL_OK;
    }

    Tcl_SetObjResult(interp, Tcl_NewStringObj(
	    "too many nested evaluations (infinite loop?)", -1));
    Tcl_SetErrorCode(interp, "TCL", "LIMIT", "STACK", NULL);
	    "too many nested evaluations (infinite loop?)", TCL_INDEX_NONE));
    Tcl_SetErrorCode(interp, "TCL", "LIMIT", "STACK", (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TclResetCancellation --
3911
3912
3913
3914
3915
3916
3917
3918

3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939

3940
3941
3942
3943
3944
3945
3946
3947
3948
3949


3950
3951
3952
3953
3954




3955
3956
3957
3958
3959
3960





3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972











3973
3974
3975


3976
3977
3978
3979
3980
3981
3982
4174
4175
4176
4177
4178
4179
4180

4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201

4202
4203
4204
4205
4206
4207
4208
4209
4210


4211
4212
4213




4214
4215
4216
4217
4218





4219
4220
4221
4222
4223
4224











4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236


4237
4238
4239
4240
4241
4242
4243
4244
4245







-
+




















-
+








-
-
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+








    /*
     * Has the current script in progress for this interpreter been canceled
     * or is the stack being unwound due to the previous script cancellation?
     */

    if (!TclCanceled(iPtr)) {
        return TCL_OK;
	return TCL_OK;
    }

    /*
     * The CANCELED flag is a one-shot flag that is reset immediately upon
     * being detected; however, if the TCL_CANCEL_UNWIND flag is set we will
     * continue to report that the script in progress has been canceled
     * thereby allowing the evaluation stack for the interp to be fully
     * unwound.
     */

    iPtr->flags &= ~CANCELED;

    /*
     * The CANCELED flag was detected and reset; however, if the caller
     * specified the TCL_CANCEL_UNWIND flag, we only return TCL_ERROR
     * (indicating that the script in progress has been canceled) if the
     * evaluation stack for the interp is being fully unwound.
     */

    if ((flags & TCL_CANCEL_UNWIND) && !(iPtr->flags & TCL_CANCEL_UNWIND)) {
        return TCL_OK;
	return TCL_OK;
    }

    /*
     * If the TCL_LEAVE_ERR_MSG flags bit is set, place an error in the
     * interp's result; otherwise, we leave it alone.
     */

    if (flags & TCL_LEAVE_ERR_MSG) {
        const char *id, *message = NULL;
        size_t length;
	const char *id, *message = NULL;
	Tcl_Size length;

        /*
         * Setup errorCode variables so that we can differentiate between
         * being canceled and unwound.
         */
	/*
	 * Setup errorCode variables so that we can differentiate between
	 * being canceled and unwound.
	 */

        if (iPtr->asyncCancelMsg != NULL) {
            message = TclGetStringFromObj(iPtr->asyncCancelMsg, &length);
        } else {
            length = 0;
        }
	if (iPtr->asyncCancelMsg != NULL) {
	    message = TclGetStringFromObj(iPtr->asyncCancelMsg, &length);
	} else {
	    length = 0;
	}

        if (iPtr->flags & TCL_CANCEL_UNWIND) {
            id = "IUNWIND";
            if (length == 0) {
                message = "eval unwound";
            }
        } else {
            id = "ICANCEL";
            if (length == 0) {
                message = "eval canceled";
            }
        }
	if (iPtr->flags & TCL_CANCEL_UNWIND) {
	    id = "IUNWIND";
	    if (length == 0) {
		message = "eval unwound";
	    }
	} else {
	    id = "ICANCEL";
	    if (length == 0) {
		message = "eval canceled";
	    }
	}

        Tcl_SetObjResult(interp, Tcl_NewStringObj(message, -1));
        Tcl_SetErrorCode(interp, "TCL", "CANCEL", id, message, NULL);
	Tcl_SetObjResult(interp, Tcl_NewStringObj(message, TCL_INDEX_NONE));
	Tcl_SetErrorCode(interp, "TCL", "CANCEL", id, message, (char *)NULL);
    }

    /*
     * Return TCL_ERROR to the caller (not necessarily just the Tcl core
     * itself) that indicates further processing of the script or command in
     * progress should halt gracefully and as soon as possible.
     */
4007
4008
4009
4010
4011
4012
4013
4014

4015
4016
4017
4018
4019
4020
4021
4270
4271
4272
4273
4274
4275
4276

4277
4278
4279
4280
4281
4282
4283
4284







-
+








int
Tcl_CancelEval(
    Tcl_Interp *interp,		/* Interpreter in which to cancel the
				 * script. */
    Tcl_Obj *resultObjPtr,	/* The script cancellation error message or
				 * NULL for a default error message. */
    ClientData clientData,	/* Passed to CancelEvalProc. */
    void *clientData,		/* Passed to CancelEvalProc. */
    int flags)			/* Collection of OR-ed bits that control
				 * the cancellation of the script. Only
				 * TCL_CANCEL_UNWIND is currently
				 * supported. */
{
    Tcl_HashEntry *hPtr;
    CancelInfo *cancelInfo;
4030
4031
4032
4033
4034
4035
4036
4037

4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057

4058
4059
4060
4061
4062
4063
4064
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







-
+



















-
+







    if (cancelTableInitialized != 1) {
	/*
	 * No CancelInfo hash table (Tcl_CreateInterp has never been called?)
	 */

	goto done;
    }
    hPtr = Tcl_FindHashEntry(&cancelTable, (char *) interp);
    hPtr = Tcl_FindHashEntry(&cancelTable, interp);
    if (hPtr == NULL) {
	/*
	 * No CancelInfo record for this interpreter.
	 */

	goto done;
    }
    cancelInfo = (CancelInfo *)Tcl_GetHashValue(hPtr);

    /*
     * Populate information needed by the interpreter thread to fulfill the
     * cancellation request. Currently, clientData is ignored. If the
     * TCL_CANCEL_UNWIND flags bit is set, the script in progress is not
     * allowed to catch the script cancellation because the evaluation stack
     * for the interp is completely unwound.
     */

    if (resultObjPtr != NULL) {
	result = TclGetStringFromObj(resultObjPtr, &cancelInfo->length);
	cancelInfo->result = (char *)Tcl_Realloc(cancelInfo->result,cancelInfo->length);
	cancelInfo->result = (char *)Tcl_Realloc(cancelInfo->result, cancelInfo->length);
	memcpy(cancelInfo->result, result, cancelInfo->length);
	TclDecrRefCount(resultObjPtr);	/* Discard their result object. */
    } else {
	cancelInfo->result = NULL;
	cancelInfo->length = 0;
    }
    cancelInfo->clientData = clientData;
4113
4114
4115
4116
4117
4118
4119
4120

4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139

4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160

4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173

4174
4175
4176
4177
4178
4179

4180
4181
4182
4183
4184
4185
4186
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

4436
4437
4438
4439
4440
4441

4442
4443
4444
4445
4446
4447
4448
4449







-
+


















-
+




















-
+












-
+





-
+







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

int
Tcl_EvalObjv(
    Tcl_Interp *interp,		/* Interpreter in which to evaluate the
				 * command. Also used for error reporting. */
    int objc,			/* Number of words in command. */
    Tcl_Size objc,		/* Number of words in command. */
    Tcl_Obj *const objv[],	/* An array of pointers to objects that are
				 * the words that make up the command. */
    int flags)			/* Collection of OR-ed bits that control the
				 * evaluation of the script. Only
				 * TCL_EVAL_GLOBAL, TCL_EVAL_INVOKE and
				 * TCL_EVAL_NOERR are currently supported. */
{
    int result;
    NRE_callback *rootPtr = TOP_CB(interp);

    result = TclNREvalObjv(interp, objc, objv, flags, NULL);
    return TclNRRunCallbacks(interp, result, rootPtr);
}

int
TclNREvalObjv(
    Tcl_Interp *interp,		/* Interpreter in which to evaluate the
				 * command. Also used for error reporting. */
    int objc,			/* Number of words in command. */
    Tcl_Size objc,		/* Number of words in command. */
    Tcl_Obj *const objv[],	/* An array of pointers to objects that are
				 * the words that make up the command. */
    int flags,			/* Collection of OR-ed bits that control the
				 * evaluation of the script. Only
				 * TCL_EVAL_GLOBAL, TCL_EVAL_INVOKE and
				 * TCL_EVAL_NOERR are currently supported. */
    Command *cmdPtr)		/* NULL if the Command is to be looked up
				 * here, otherwise the pointer to the
				 * requested Command struct to be invoked. */
{
    Interp *iPtr = (Interp *) interp;

    /*
     * data[1] stores a marker for use by tailcalls; it will be set to 1 by
     * command redirectors (imports, alias, ensembles) so that tailcall skips
     * this callback (that marks the end of the target command) and goes back
     * to the end of the source command.
     */

    if (iPtr->deferredCallbacks) {
        iPtr->deferredCallbacks = NULL;
	iPtr->deferredCallbacks = NULL;
    } else {
	TclNRAddCallback(interp, NRCommand, NULL, NULL, NULL, NULL);
    }

    iPtr->numLevels++;
    TclNRAddCallback(interp, EvalObjvCore, cmdPtr, INT2PTR(flags),
	    INT2PTR(objc), objv);
    return TCL_OK;
}

static int
EvalObjvCore(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int) /*result*/)
{
    Command *cmdPtr = NULL, *preCmdPtr = (Command *)data[0];
    int flags = PTR2INT(data[1]);
    int objc = PTR2INT(data[2]);
    Tcl_Size objc = PTR2INT(data[2]);
    Tcl_Obj **objv = (Tcl_Obj **)data[3];
    Interp *iPtr = (Interp *) interp;
    Namespace *lookupNsPtr = NULL;
    int enterTracesDone = 0;

    /*
     * Push records for task to be done on return, in INVERSE order. First, if
4196
4197
4198
4199
4200
4201
4202




4203
4204
4205
4206
4207
4208
4209
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476







+
+
+
+







    }

    if (objc == 0) {
	return TCL_OK;
    }

    if (TclLimitExceeded(iPtr->limit)) {
	/* generate error message if not yet already logged at this stage */
	if (!(iPtr->flags & ERR_ALREADY_LOGGED)) {
	    Tcl_LimitCheck(interp);
	}
	return TCL_ERROR;
    }

    /*
     * Configure evaluation context to match the requested flags.
     */

4241
4242
4243
4244
4245
4246
4247
4248
4249


4250
4251
4252
4253
4254


4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265

4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279

4280
4281
4282
4283
4284
4285
4286
4508
4509
4510
4511
4512
4513
4514


4515
4516
4517
4518
4519


4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531

4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545

4546
4547
4548
4549
4550
4551
4552
4553







-
-
+
+



-
-
+
+










-
+













-
+







     * Lookup the Command to dispatch.
     */

    reresolve:
    assert(cmdPtr == NULL);
    if (preCmdPtr) {
	/*
         * Caller gave it to us.
         */
	 * Caller gave it to us.
	 */

	if (!(preCmdPtr->flags & CMD_DEAD)) {
	    /*
             * So long as it exists, use it.
             */
	     * So long as it exists, use it.
	     */

	    cmdPtr = preCmdPtr;
	} else if (flags & TCL_EVAL_NORESOLVE) {
	    /*
	     * When it's been deleted, and we're told not to attempt resolving
	     * it ourselves, all we can do is raise an error.
	     */

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "attempt to invoke a deleted command"));
	    Tcl_SetErrorCode(interp, "TCL", "EVAL", "DELETEDCOMMAND", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "EVAL", "DELETEDCOMMAND", (char *)NULL);
	    return TCL_ERROR;
	}
    }
    if (cmdPtr == NULL) {
	cmdPtr = TEOV_LookupCmdFromObj(interp, objv[0], lookupNsPtr);
	if (!cmdPtr) {
	    return TEOV_NotFound(interp, objc, objv, lookupNsPtr);
	}
    }

    if (enterTracesDone || iPtr->tracePtr
	    || (cmdPtr->flags & CMD_HAS_EXEC_TRACES)) {
	Tcl_Obj *commandPtr = TclGetSourceFromFrame(
		flags & TCL_EVAL_SOURCE_IN_FRAME ?  iPtr->cmdFramePtr : NULL,
		flags & TCL_EVAL_SOURCE_IN_FRAME ? iPtr->cmdFramePtr : NULL,
		objc, objv);

	Tcl_IncrRefCount(commandPtr);
	if (!enterTracesDone) {
	    int code = TEOV_RunEnterTraces(interp, &cmdPtr, commandPtr,
		    objc, objv);

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
4582
4583
4584
4585
4586
4587
4588

4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599

4600
4601
4602
4603
4604


4605
4606
4607
4608
4609
4610
4611
4612

4613
4614
4615
4616
4617
4618
4619
4620
4621
4622

4623
4624
4625
4626
4627
4628
4629
4630







-
+










-
+




-
-
+
+






-
+









-
+







	 * Schedule leave traces.  Raise the refCount on the resolved cmdPtr,
	 * so that when it passes to the leave traces we know it's still
	 * valid.
	 */

	cmdPtr->refCount++;
	TclNRAddCallback(interp, TEOV_RunLeaveTraces, INT2PTR(objc),
		    commandPtr, cmdPtr, objv);
		commandPtr, cmdPtr, objv);
    }

    TclNRAddCallback(interp, Dispatch,
	    cmdPtr->nreProc ? cmdPtr->nreProc : cmdPtr->objProc,
	    cmdPtr->objClientData, INT2PTR(objc), objv);
    return TCL_OK;
}

static int
Dispatch(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int) /*result*/)
{
    Tcl_ObjCmdProc *objProc = (Tcl_ObjCmdProc *)data[0];
    ClientData clientData = data[1];
    int objc = PTR2INT(data[2]);
    void *clientData = data[1];
    Tcl_Size objc = PTR2INT(data[2]);
    Tcl_Obj **objv = (Tcl_Obj **)data[3];
    Interp *iPtr = (Interp *) interp;

#ifdef USE_DTRACE
    if (TCL_DTRACE_CMD_ARGS_ENABLED()) {
	const char *a[10];
	int i = 0;
	Tcl_Size i = 0;

	while (i < 10) {
	    a[i] = i < objc ? TclGetString(objv[i]) : NULL; i++;
	}
	TCL_DTRACE_CMD_ARGS(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7],
		a[8], a[9]);
    }
    if (TCL_DTRACE_CMD_INFO_ENABLED() && iPtr->cmdFramePtr) {
	Tcl_Obj *info = TclInfoFrame(interp, iPtr->cmdFramePtr);
	const char *a[6]; int i[2];
	const char *a[6]; Tcl_Size i[2];

	TclDTraceInfo(info, a, i);
	TCL_DTRACE_CMD_INFO(a[0], a[1], a[2], a[3], i[0], i[1], a[4], a[5]);
	TclDecrRefCount(info);
    }
    if ((TCL_DTRACE_CMD_RETURN_ENABLED() || TCL_DTRACE_CMD_RESULT_ENABLED())
	    && objc) {
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
4645
4646
4647
4648
4649
4650
4651


4652
4653
4654
4655
4656
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
4688







-
-
+
+










-
+




+



-
-
-
+
+
+


+
+
+
-
+







    Tcl_Interp *interp,
    int result,
    struct NRE_callback *rootPtr)
				/* All callbacks down to rootPtr not inclusive
				 * are to be run. */
{
    while (TOP_CB(interp) != rootPtr) {
        NRE_callback *callbackPtr = TOP_CB(interp);
        Tcl_NRPostProc *procPtr = callbackPtr->procPtr;
	NRE_callback *callbackPtr = TOP_CB(interp);
	Tcl_NRPostProc *procPtr = callbackPtr->procPtr;

	TOP_CB(interp) = callbackPtr->nextPtr;
	result = procPtr(callbackPtr->data, interp, result);
	TCLNR_FREE(interp, callbackPtr);
    }
    return result;
}

static int
NRCommand(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *listPtr;

    iPtr->numLevels--;

     /*
      * If there is a tailcall, schedule it next
      */
    /*
     * If there is a tailcall, schedule it next
     */

    if (data[1] && (data[1] != INT2PTR(1))) {
	listPtr = (Tcl_Obj *)data[1];
	data[1] = NULL;

        TclNRAddCallback(interp, TclNRTailcallEval, data[1], NULL, NULL, NULL);
	TclNRAddCallback(interp, TclNRTailcallEval, listPtr, NULL, NULL, NULL);
    }

    /* OPT ??
     * Do not interrupt a series of cleanups with async or limit checks:
     * just check at the end?
     */

4441
4442
4443
4444
4445
4446
4447
4448

4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466

4467
4468
4469
4470
4471
4472
4473
4712
4713
4714
4715
4716
4717
4718

4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736

4737
4738
4739
4740
4741
4742
4743
4744







-
+

















-
+







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

static void
TEOV_PushExceptionHandlers(
    Tcl_Interp *interp,
    int objc,
    Tcl_Size objc,
    Tcl_Obj *const objv[],
    int flags)
{
    Interp *iPtr = (Interp *) interp;

    /*
     * If any error processing is necessary, push the appropriate records.
     * Note that we have to push them in the inverse order: first the one that
     * has to run last.
     */

    if (!(flags & TCL_EVAL_INVOKE)) {
	/*
	 * Error messages
	 */

	TclNRAddCallback(interp, TEOV_Error, INT2PTR(objc),
		(ClientData) objv, NULL, NULL);
		objv, NULL, NULL);
    }

    if (iPtr->numLevels == 1) {
	/*
	 * No CONTINUE or BREAK at level 0, manage RETURN
	 */

4490
4491
4492
4493
4494
4495
4496
4497

4498
4499
4500
4501
4502
4503
4504
4505
4506
4507

4508
4509
4510
4511
4512
4513
4514
4761
4762
4763
4764
4765
4766
4767

4768
4769
4770
4771
4772
4773
4774
4775
4776
4777

4778
4779
4780
4781
4782
4783
4784
4785







-
+









-
+







    TclNRAddCallback(interp, TEOV_RestoreVarFrame, iPtr->varFramePtr, NULL,
	    NULL, NULL);
    iPtr->varFramePtr = iPtr->rootFramePtr;
}

static int
TEOV_RestoreVarFrame(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    ((Interp *) interp)->varFramePtr = (CallFrame *)data[0];
    return result;
}

static int
TEOV_Exception(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    int allowExceptions = (PTR2INT(data[0]) & TCL_ALLOW_EXCEPTIONS);

    if (result != TCL_OK) {
4529
4530
4531
4532
4533
4534
4535
4536

4537
4538
4539
4540
4541
4542
4543
4544


4545
4546
4547
4548
4549
4550
4551
4800
4801
4802
4803
4804
4805
4806

4807
4808
4809
4810
4811
4812
4813


4814
4815
4816
4817
4818
4819
4820
4821
4822







-
+






-
-
+
+








    TclUnsetCancelFlags(iPtr);
    return result;
}

static int
TEOV_Error(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *listPtr;
    const char *cmdString;
    size_t cmdLen;
    int objc = PTR2INT(data[0]);
    Tcl_Size cmdLen;
    Tcl_Size objc = PTR2INT(data[0]);
    Tcl_Obj **objv = (Tcl_Obj **)data[1];

    if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
	/*
	 * If there was an error, a command string will be needed for the
	 * error log: get it out of the itemPtr. The details depend on the
	 * type.
4559
4560
4561
4562
4563
4564
4565
4566

4567
4568
4569
4570
4571
4572

4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584

4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600

4601
4602
4603
4604

4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619

4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636



4637
4638
4639
4640
4641
4642
4643
4830
4831
4832
4833
4834
4835
4836

4837
4838
4839
4840
4841
4842

4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854

4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870

4871
4872
4873
4874

4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889

4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904



4905
4906
4907
4908
4909
4910
4911
4912
4913
4914







-
+





-
+











-
+















-
+



-
+














-
+














-
-
-
+
+
+







    iPtr->flags &= ~ERR_ALREADY_LOGGED;
    return result;
}

static int
TEOV_NotFound(
    Tcl_Interp *interp,
    int objc,
    Tcl_Size objc,
    Tcl_Obj *const objv[],
    Namespace *lookupNsPtr)
{
    Command * cmdPtr;
    Interp *iPtr = (Interp *) interp;
    int i, newObjc, handlerObjc;
    Tcl_Size i, newObjc, handlerObjc;
    Tcl_Obj **newObjv, **handlerObjv;
    CallFrame *varFramePtr = iPtr->varFramePtr;
    Namespace *currNsPtr = NULL;/* Used to check for and invoke any registered
				 * unknown command handler for the current
				 * namespace (TIP 181). */
    Namespace *savedNsPtr = NULL;

    currNsPtr = varFramePtr->nsPtr;
    if ((currNsPtr == NULL) || (currNsPtr->unknownHandlerPtr == NULL)) {
	currNsPtr = iPtr->globalNsPtr;
	if (currNsPtr == NULL) {
	    Tcl_Panic("Tcl_EvalObjv: NULL global namespace pointer");
	    Tcl_Panic("TEOV_NotFound: NULL global namespace pointer");
	}
    }

    /*
     * Check to see if the resolution namespace has lost its unknown handler.
     * If so, reset it to "::unknown".
     */

    if (currNsPtr->unknownHandlerPtr == NULL) {
	TclNewLiteralStringObj(currNsPtr->unknownHandlerPtr, "::unknown");
	Tcl_IncrRefCount(currNsPtr->unknownHandlerPtr);
    }

    /*
     * Get the list of words for the unknown handler and allocate enough space
     * to hold both the handler prefix and all words of the command invokation
     * to hold both the handler prefix and all words of the command invocation
     * itself.
     */

    Tcl_ListObjGetElements(NULL, currNsPtr->unknownHandlerPtr,
    TclListObjGetElements(NULL, currNsPtr->unknownHandlerPtr,
	    &handlerObjc, &handlerObjv);
    newObjc = objc + handlerObjc;
    newObjv = (Tcl_Obj **)TclStackAlloc(interp, sizeof(Tcl_Obj *) * newObjc);

    /*
     * Copy command prefix from unknown handler and add on the real command's
     * full argument list. Note that we only use memcpy() once because we have
     * to increment the reference count of all the handler arguments anyway.
     */

    for (i = 0; i < handlerObjc; ++i) {
	newObjv[i] = handlerObjv[i];
	Tcl_IncrRefCount(newObjv[i]);
    }
    memcpy(newObjv+handlerObjc, objv, sizeof(Tcl_Obj *) * objc);
    memcpy(newObjv + handlerObjc, objv, sizeof(Tcl_Obj *) * objc);

    /*
     * Look up and invoke the handler (by recursive call to this function). If
     * there is no handler at all, instead of doing the recursive call we just
     * generate a generic error message; it would be an infinite-recursion
     * nightmare otherwise.
     *
     * In this case we worry a bit less about recursion for now, and call the
     * "blocking" interface.
     */

    cmdPtr = TEOV_LookupCmdFromObj(interp, newObjv[0], lookupNsPtr);
    if (cmdPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "invalid command name \"%s\"", TclGetString(objv[0])));
        Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND",
                TclGetString(objv[0]), NULL);
		"invalid command name \"%s\"", TclGetString(objv[0])));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND",
		TclGetString(objv[0]), (char *)NULL);

	/*
	 * Release any resources we locked and allocated during the handler
	 * call.
	 */

	for (i = 0; i < handlerObjc; ++i) {
4655
4656
4657
4658
4659
4660
4661
4662

4663
4664
4665
4666
4667

4668
4669
4670
4671

4672
4673
4674
4675
4676
4677
4678
4926
4927
4928
4929
4930
4931
4932

4933
4934
4935
4936
4937

4938
4939
4940
4941

4942
4943
4944
4945
4946
4947
4948
4949







-
+




-
+



-
+







    TclNRAddCallback(interp, TEOV_NotFoundCallback, INT2PTR(handlerObjc),
	    newObjv, savedNsPtr, NULL);
    return TclNREvalObjv(interp, newObjc, newObjv, TCL_EVAL_NOERR, NULL);
}

static int
TEOV_NotFoundCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    int objc = PTR2INT(data[0]);
    Tcl_Size objc = PTR2INT(data[0]);
    Tcl_Obj **objv = (Tcl_Obj **)data[1];
    Namespace *savedNsPtr = (Namespace *)data[2];

    int i;
    Tcl_Size i;

    if (savedNsPtr) {
	iPtr->varFramePtr->nsPtr = savedNsPtr;
    }

    /*
     * Release any resources we locked and allocated during the handler call.
4687
4688
4689
4690
4691
4692
4693
4694

4695
4696
4697
4698
4699

4700
4701
4702
4703
4704
4705
4706
4958
4959
4960
4961
4962
4963
4964

4965
4966
4967
4968
4969

4970
4971
4972
4973
4974
4975
4976
4977







-
+




-
+







}

static int
TEOV_RunEnterTraces(
    Tcl_Interp *interp,
    Command **cmdPtrPtr,
    Tcl_Obj *commandPtr,
    int objc,
    Tcl_Size objc,
    Tcl_Obj *const objv[])
{
    Interp *iPtr = (Interp *) interp;
    Command *cmdPtr = *cmdPtrPtr;
    size_t length, newEpoch, cmdEpoch = cmdPtr->cmdEpoch;
    Tcl_Size length, newEpoch, cmdEpoch = cmdPtr->cmdEpoch;
    int traceCode = TCL_OK;
    const char *command = TclGetStringFromObj(commandPtr, &length);

    /*
     * Call trace functions.
     * Execute any command or execution traces. Note that we bump up the
     * command's reference count for the duration of the calling of the
4735
4736
4737
4738
4739
4740
4741
4742

4743
4744
4745
4746
4747
4748

4749
4750
4751
4752

4753
4754
4755
4756
4757
4758
4759
5006
5007
5008
5009
5010
5011
5012

5013
5014
5015
5016
5017
5018

5019
5020
5021
5022

5023
5024
5025
5026
5027
5028
5029
5030







-
+





-
+



-
+







	*cmdPtrPtr = NULL;
    }
    return TCL_OK;
}

static int
TEOV_RunLeaveTraces(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    int traceCode = TCL_OK;
    int objc = PTR2INT(data[0]);
    Tcl_Size objc = PTR2INT(data[0]);
    Tcl_Obj *commandPtr = (Tcl_Obj *)data[1];
    Command *cmdPtr = (Command *)data[2];
    Tcl_Obj **objv = (Tcl_Obj **)data[3];
    size_t length;
    Tcl_Size length;
    const char *command = TclGetStringFromObj(commandPtr, &length);

    if (!(cmdPtr->flags & CMD_DYING)) {
	if (cmdPtr->flags & CMD_HAS_EXEC_TRACES) {
	    traceCode = TclCheckExecutionTraces(interp, command, length,
		    cmdPtr, result, TCL_TRACE_LEAVE_EXEC, objc, objv);
	}
4828
4829
4830
4831
4832
4833
4834
4835

4836
4837
4838
4839
4840
4841
4842
5099
5100
5101
5102
5103
5104
5105

5106
5107
5108
5109
5110
5111
5112
5113







-
+







int
Tcl_EvalTokensStandard(
    Tcl_Interp *interp,		/* Interpreter in which to lookup variables,
				 * execute nested commands, and report
				 * errors. */
    Tcl_Token *tokenPtr,	/* Pointer to first in an array of tokens to
				 * evaluate and concatenate. */
    size_t count)			/* Number of tokens to consider at tokenPtr.
    Tcl_Size count)		/* Number of tokens to consider at tokenPtr.
				 * Must be at least 1. */
{
    return TclSubstTokens(interp, tokenPtr, count, /* numLeftPtr */ NULL, 1,
	    NULL, NULL);
}

/*
4861
4862
4863
4864
4865
4866
4867
4868

4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883

4884
4885
4886
4887
4888
4889
4890


4891
4892
4893
4894
4895

4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910

4911
4912


4913
4914
4915


4916
4917
4918
4919
4920

4921
4922
4923
4924
4925
4926
4927

4928
4929
4930

4931
4932
4933

4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949

4950
4951
4952
4953
4954
4955
4956
5132
5133
5134
5135
5136
5137
5138

5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153

5154
5155
5156
5157
5158
5159


5160
5161
5162
5163
5164
5165

5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180

5181
5182

5183
5184
5185


5186
5187
5188
5189
5190
5191

5192
5193
5194
5195
5196
5197
5198

5199

5200

5201
5202
5203

5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219

5220
5221
5222
5223
5224
5225
5226
5227







-
+














-
+





-
-
+
+




-
+














-
+

-
+
+

-
-
+
+




-
+






-
+
-

-
+


-
+















-
+







 */

int
Tcl_EvalEx(
    Tcl_Interp *interp,		/* Interpreter in which to evaluate the
				 * script. Also used for error reporting. */
    const char *script,		/* First character of script to evaluate. */
    size_t numBytes,		/* Number of bytes in script. If -1, the
    Tcl_Size numBytes,		/* Number of bytes in script. If -1, the
				 * script consists of all bytes up to the
				 * first null character. */
    int flags)			/* Collection of OR-ed bits that control the
				 * evaluation of the script. Only
				 * TCL_EVAL_GLOBAL is currently supported. */
{
    return TclEvalEx(interp, script, numBytes, flags, 1, NULL, script);
}

int
TclEvalEx(
    Tcl_Interp *interp,		/* Interpreter in which to evaluate the
				 * script. Also used for error reporting. */
    const char *script,		/* First character of script to evaluate. */
    size_t numBytes,		/* Number of bytes in script. If -1, the
    Tcl_Size numBytes,		/* Number of bytes in script. If -1, the
				 * script consists of all bytes up to the
				 * first NUL character. */
    int flags,			/* Collection of OR-ed bits that control the
				 * evaluation of the script. Only
				 * TCL_EVAL_GLOBAL is currently supported. */
    int line,			/* The line the script starts on. */
    int *clNextOuter,		/* Information about an outer context for */
    Tcl_Size line,		/* The line the script starts on. */
    Tcl_Size *clNextOuter,	/* Information about an outer context for */
    const char *outerScript)	/* continuation line data. This is set only in
				 * TclSubstTokens(), to properly handle
				 * [...]-nested commands. The 'outerScript'
				 * refers to the most-outer script containing
				 * the embedded command, which is refered to
				 * the embedded command, which is referred to
				 * by 'script'. The 'clNextOuter' refers to
				 * the current entry in the table of
				 * continuation lines in this "main script",
				 * and the character offsets are relative to
				 * the 'outerScript' as well.
				 *
				 * If outerScript == script, then this call is
				 * for the outer-most script/command. See
				 * Tcl_EvalEx() and TclEvalObjEx() for places
				 * generating arguments for which this is
				 * true. */
{
    Interp *iPtr = (Interp *) interp;
    const char *p, *next;
    const unsigned int minObjs = 20;
    const int minObjs = 20;
    Tcl_Obj **objv, **objvSpace;
    int *expand, *lines, *lineSpace;
    int *expand;
    Tcl_Size *lines, *lineSpace;
    Tcl_Token *tokenPtr;
    int bytesLeft, expandRequested, code = TCL_OK;
    size_t commandLength;
    int expandRequested, code = TCL_OK;
    Tcl_Size bytesLeft, commandLength;
    CallFrame *savedVarFramePtr;/* Saves old copy of iPtr->varFramePtr in case
				 * TCL_EVAL_GLOBAL was set. */
    int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS);
    int gotParse = 0;
    unsigned int i, objectsUsed = 0;
    Tcl_Size i, objectsUsed = 0;
				/* These variables keep track of how much
				 * state has been allocated while evaluating
				 * the script, so that it can be freed
				 * properly if an error occurs. */
    Tcl_Parse *parsePtr = (Tcl_Parse *)TclStackAlloc(interp, sizeof(Tcl_Parse));
    CmdFrame *eeFramePtr = (CmdFrame *)TclStackAlloc(interp, sizeof(CmdFrame));
    Tcl_Obj **stackObjArray = (Tcl_Obj **)
    Tcl_Obj **stackObjArray = (Tcl_Obj **)TclStackAlloc(interp, minObjs * sizeof(Tcl_Obj *));
	    TclStackAlloc(interp, minObjs * sizeof(Tcl_Obj *));
    int *expandStack = (int *)TclStackAlloc(interp, minObjs * sizeof(int));
    int *linesStack = (int *)TclStackAlloc(interp, minObjs * sizeof(int));
    Tcl_Size *linesStack = (Tcl_Size *)TclStackAlloc(interp, minObjs * sizeof(Tcl_Size));
				/* TIP #280 Structures for tracking of command
				 * locations. */
    int *clNext = NULL;		/* Pointer for the tracking of invisible
    Tcl_Size *clNext = NULL;	/* Pointer for the tracking of invisible
				 * continuation lines. Initialized only if the
				 * caller gave us a table of locations to
				 * track, via scriptCLLocPtr. It always refers
				 * to the table entry holding the location of
				 * the next invisible continuation line to
				 * look for, while parsing the script. */

    if (iPtr->scriptCLLocPtr) {
	if (clNextOuter) {
	    clNext = clNextOuter;
	} else {
	    clNext = &iPtr->scriptCLLocPtr->loc[0];
	}
    }

    if (numBytes == TCL_INDEX_NONE) {
    if (numBytes < 0) {
	numBytes = strlen(script);
    }
    Tcl_ResetResult(interp);

    savedVarFramePtr = iPtr->varFramePtr;
    if (flags & TCL_EVAL_GLOBAL) {
	iPtr->varFramePtr = iPtr->rootFramePtr;
5048
5049
5050
5051
5052
5053
5054
5055

5056
5057
5058
5059



5060
5061
5062
5063
5064
5065
5066
5067
5068





5069
5070
5071
5072
5073
5074
5075
5076
5077



5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098

5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110

5111
5112
5113
5114
5115
5116
5117
5118
5119
5120

5121
5122
5123
5124
5125
5126
5127


5128
5129





5130




5131

5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150



5151
5152
5153
5154
5155


5156
5157
5158
5159
5160
5161

5162
5163
5164

5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179

5180
5181
5182
5183
5184
5185
5186
5319
5320
5321
5322
5323
5324
5325

5326
5327



5328
5329
5330
5331
5332
5333
5334
5335
5336



5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349

5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372

5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384

5385
5386
5387
5388
5389
5390
5391
5392
5393
5394

5395
5396
5397
5398
5399
5400
5401

5402
5403
5404
5405
5406
5407
5408
5409
5410

5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432



5433
5434
5435
5436
5437



5438
5439
5440
5441
5442
5443
5444

5445
5446
5447

5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462

5463
5464
5465
5466
5467
5468
5469
5470







-
+

-
-
-
+
+
+






-
-
-
+
+
+
+
+








-
+
+
+




















-
+











-
+









-
+






-
+
+


+
+
+
+
+
-
+
+
+
+

+
















-
-
-
+
+
+


-
-
-
+
+





-
+


-
+














-
+







	    /*
	     * TIP #280. Track lines within the words of the current
	     * command. We use a separate pointer into the table of
	     * continuation line locations to not lose our position for the
	     * per-command parsing.
	     */

	    int wordLine = line;
	    Tcl_Size wordLine = line;
	    const char *wordStart = parsePtr->commandStart;
	    int *wordCLNext = clNext;
	    unsigned int objectsNeeded = 0;
	    unsigned int numWords = parsePtr->numWords;
	    Tcl_Size *wordCLNext = clNext;
	    Tcl_Size objectsNeeded = 0;
	    Tcl_Size numWords = parsePtr->numWords;

	    /*
	     * Generate an array of objects for the words of the command.
	     */

	    if (numWords > minObjs) {
		expand =    (int *)Tcl_Alloc(numWords * sizeof(int));
		objvSpace = (Tcl_Obj **)Tcl_Alloc(numWords * sizeof(Tcl_Obj *));
		lineSpace = (int *)Tcl_Alloc(numWords * sizeof(int));
		expand = (int *)Tcl_Alloc(numWords * sizeof(int));
		objvSpace = (Tcl_Obj **)
			Tcl_Alloc(numWords * sizeof(Tcl_Obj *));
		lineSpace = (Tcl_Size *)
			Tcl_Alloc(numWords * sizeof(Tcl_Size));
	    }
	    expandRequested = 0;
	    objv = objvSpace;
	    lines = lineSpace;

	    iPtr->cmdFramePtr = eeFramePtr->nextPtr;
	    for (objectsUsed = 0, tokenPtr = parsePtr->tokenPtr;
		    objectsUsed < numWords;
		    objectsUsed++, tokenPtr += tokenPtr->numComponents+1) {
		    objectsUsed++, tokenPtr += tokenPtr->numComponents + 1) {
		Tcl_Size additionalObjsCount;

		/*
		 * TIP #280. Track lines to current word. Save the information
		 * on a per-word basis, signaling dynamic words as needed.
		 * Make the information available to the recursively called
		 * evaluator as well, including the type of context (source
		 * vs. eval).
		 */

		TclAdvanceLines(&wordLine, wordStart, tokenPtr->start);
		TclAdvanceContinuations(&wordLine, &wordCLNext,
			tokenPtr->start - outerScript);
		wordStart = tokenPtr->start;

		lines[objectsUsed] = TclWordKnownAtCompileTime(tokenPtr, NULL)
			? wordLine : -1;

		if (eeFramePtr->type == TCL_LOCATION_SOURCE) {
		    iPtr->evalFlags |= TCL_EVAL_FILE;
		}

		code = TclSubstTokens(interp, tokenPtr+1,
		code = TclSubstTokens(interp, tokenPtr + 1,
			tokenPtr->numComponents, NULL, wordLine,
			wordCLNext, outerScript);

		iPtr->evalFlags = 0;

		if (code != TCL_OK) {
		    break;
		}
		objv[objectsUsed] = Tcl_GetObjResult(interp);
		Tcl_IncrRefCount(objv[objectsUsed]);
		if (tokenPtr->type == TCL_TOKEN_EXPAND_WORD) {
		    int numElements;
		    Tcl_Size numElements;

		    code = TclListObjLength(interp, objv[objectsUsed],
			    &numElements);
		    if (code == TCL_ERROR) {
			/*
			 * Attempt to expand a non-list.
			 */

			Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
				"\n    (expanding word %d)", objectsUsed));
				"\n    (expanding word %" TCL_SIZE_MODIFIER "d)", objectsUsed));
			Tcl_DecrRefCount(objv[objectsUsed]);
			break;
		    }
		    expandRequested = 1;
		    expand[objectsUsed] = 1;

		    objectsNeeded += (numElements ? numElements : 1);
		    additionalObjsCount = (numElements ? numElements : 1);

		} else {
		    expand[objectsUsed] = 0;
		    additionalObjsCount = 1;
		}

		/* Currently max command words in INT_MAX */
		if (additionalObjsCount > INT_MAX ||
		    objectsNeeded++;
			objectsNeeded > (INT_MAX - additionalObjsCount)) {
		    code = TclCommandWordLimitError(interp, -1);
		    Tcl_DecrRefCount(objv[objectsUsed]);
		    break;
		}
		objectsNeeded += additionalObjsCount;

		if (wordCLNext) {
		    TclContinuationsEnterDerived(objv[objectsUsed],
			    wordStart - outerScript, wordCLNext);
		}
	    } /* for loop */
	    iPtr->cmdFramePtr = eeFramePtr;
	    if (code != TCL_OK) {
		goto error;
	    }
	    if (expandRequested) {
		/*
		 * Some word expansion was requested. Check for objv resize.
		 */

		Tcl_Obj **copy = objvSpace;
		int *lcopy = lineSpace;
		int wordIdx = numWords;
		int objIdx = objectsNeeded - 1;
		Tcl_Size *lcopy = lineSpace;
		Tcl_Size wordIdx = numWords;
		Tcl_Size objIdx = objectsNeeded - 1;

		if ((numWords > minObjs) || (objectsNeeded > minObjs)) {
		    objv = objvSpace =
			    (Tcl_Obj **)Tcl_Alloc(objectsNeeded * sizeof(Tcl_Obj *));
		    lines = lineSpace = (int *)Tcl_Alloc(objectsNeeded * sizeof(int));
		    objv = objvSpace = (Tcl_Obj **)Tcl_Alloc(objectsNeeded * sizeof(Tcl_Obj *));
		    lines = lineSpace = (Tcl_Size *)Tcl_Alloc(objectsNeeded * sizeof(Tcl_Size));
		}

		objectsUsed = 0;
		while (wordIdx--) {
		    if (expand[wordIdx]) {
			int numElements;
			Tcl_Size numElements;
			Tcl_Obj **elements, *temp = copy[wordIdx];

			Tcl_ListObjGetElements(NULL, temp, &numElements,
			TclListObjGetElements(NULL, temp, &numElements,
				&elements);
			objectsUsed += numElements;
			while (numElements--) {
			    lines[objIdx] = -1;
			    objv[objIdx--] = elements[numElements];
			    Tcl_IncrRefCount(elements[numElements]);
			}
			Tcl_DecrRefCount(temp);
		    } else {
			lines[objIdx] = lcopy[wordIdx];
			objv[objIdx--] = copy[wordIdx];
			objectsUsed++;
		    }
		}
		objv += objIdx+1;
		objv += objIdx + 1;

		if (copy != stackObjArray) {
		    Tcl_Free(copy);
		}
		if (lcopy != linesStack) {
		    Tcl_Free(lcopy);
		}
5347
5348
5349
5350
5351
5352
5353
5354

5355
5356
5357
5358
5359
5360
5361
5631
5632
5633
5634
5635
5636
5637

5638
5639
5640
5641
5642
5643
5644
5645







-
+







 *
 * TIP #280
 *----------------------------------------------------------------------
 */

void
TclAdvanceLines(
    int *line,
    Tcl_Size *line,
    const char *start,
    const char *end)
{
    const char *p;

    for (p = start; p < end; p++) {
	if (*p == '\n') {
5382
5383
5384
5385
5386
5387
5388
5389
5390


5391
5392
5393
5394
5395
5396
5397
5666
5667
5668
5669
5670
5671
5672


5673
5674
5675
5676
5677
5678
5679
5680
5681







-
-
+
+







 *
 * TIP #280
 *----------------------------------------------------------------------
 */

void
TclAdvanceContinuations(
    int *line,
    int **clNextPtrPtr,
    Tcl_Size *line,
    Tcl_Size **clNextPtrPtr,
    int loc)
{
    /*
     * Track the invisible continuation lines embedded in a script, if any.
     * Here they are just spaces (already). They were removed by
     * TclSubstTokens via TclParseBackslash.
     *
5442
5443
5444
5445
5446
5447
5448
5449

5450
5451
5452
5453


5454
5455
5456
5457
5458
5459
5460
5461
5462


5463
5464
5465
5466
5467
5468
5469
5726
5727
5728
5729
5730
5731
5732

5733
5734
5735
5736

5737
5738
5739
5740
5741
5742
5743
5744
5745


5746
5747
5748
5749
5750
5751
5752
5753
5754







-
+



-
+
+







-
-
+
+







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

void
TclArgumentEnter(
    Tcl_Interp *interp,
    Tcl_Obj **objv,
    int objc,
    Tcl_Size objc,
    CmdFrame *cfPtr)
{
    Interp *iPtr = (Interp *) interp;
    int isNew, i;
    int isNew;
    Tcl_Size i;
    Tcl_HashEntry *hPtr;
    CFWord *cfwPtr;

    for (i = 1; i < objc; i++) {
	/*
	 * Ignore argument words without line information (= dynamic). If they
	 * are variables they may have location information associated with
	 * that, either through globally recorded 'set' invokations, or
	 * literals in bytecode. Eitehr way there is no need to record
	 * that, either through globally recorded 'set' invocations, or
	 * literals in bytecode. Either way there is no need to record
	 * something here.
	 */

	if (cfPtr->line[i] < 0) {
	    continue;
	}
	hPtr = Tcl_CreateHashEntry(iPtr->lineLAPtr, objv[i], &isNew);
5510
5511
5512
5513
5514
5515
5516
5517

5518
5519
5520

5521
5522
5523
5524

5525
5526
5527
5528
5529
5530
5531
5532
5795
5796
5797
5798
5799
5800
5801

5802
5803
5804

5805
5806
5807
5808

5809

5810
5811
5812
5813
5814
5815
5816







-
+


-
+



-
+
-







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

void
TclArgumentRelease(
    Tcl_Interp *interp,
    Tcl_Obj **objv,
    int objc)
    Tcl_Size objc)
{
    Interp *iPtr = (Interp *) interp;
    int i;
    Tcl_Size i;

    for (i = 1; i < objc; i++) {
	CFWord *cfwPtr;
	Tcl_HashEntry *hPtr =
	Tcl_HashEntry *hPtr = Tcl_FindHashEntry(iPtr->lineLAPtr, objv[i]);
		Tcl_FindHashEntry(iPtr->lineLAPtr, (char *) objv[i]);

	if (!hPtr) {
	    continue;
	}
	cfwPtr = (CFWord *)Tcl_GetHashValue(hPtr);

	if (cfwPtr->refCount-- > 1) {
5558
5559
5560
5561
5562
5563
5564
5565

5566
5567
5568
5569


5570
5571
5572

5573
5574
5575
5576

5577
5578
5579
5580
5581
5582
5583
5584
5842
5843
5844
5845
5846
5847
5848

5849
5850
5851


5852
5853
5854
5855

5856
5857
5858
5859

5860

5861
5862
5863
5864
5865
5866
5867







-
+


-
-
+
+


-
+



-
+
-







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

void
TclArgumentBCEnter(
    Tcl_Interp *interp,
    Tcl_Obj *objv[],
    int objc,
    Tcl_Size objc,
    void *codePtr,
    CmdFrame *cfPtr,
    int cmd,
    size_t pc)
    Tcl_Size cmd,
    Tcl_Size pc)
{
    ExtCmdLoc *eclPtr;
    int word;
    Tcl_Size word;
    ECL *ePtr;
    CFWordBC *lastPtr = NULL;
    Interp *iPtr = (Interp *) interp;
    Tcl_HashEntry *hePtr =
    Tcl_HashEntry *hePtr = Tcl_FindHashEntry(iPtr->lineBCPtr, codePtr);
	    Tcl_FindHashEntry(iPtr->lineBCPtr, (char *) codePtr);

    if (!hePtr) {
	return;
    }
    eclPtr = (ExtCmdLoc *)Tcl_GetHashValue(hePtr);
    ePtr = &eclPtr->loc[cmd];

5592
5593
5594
5595
5596
5597
5598
5599

5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617

5618
5619
5620
5621
5622
5623
5624
5875
5876
5877
5878
5879
5880
5881

5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899

5900
5901
5902
5903
5904
5905
5906
5907







-
+

















-
+







     * evaluation are not supposed to get compiled, because a command
     * such as [info level] in the script can expose some of the dispatch
     * shenanigans.  This means that we don't have to tend to the
     * housekeeping, and can escape now.
     */

    if (ePtr->nline != objc) {
        return;
	return;
    }

    /*
     * Having disposed of the ensemble cases, we can state...
     * A few truths ...
     * (1) ePtr->nline == objc
     * (2) (ePtr->line[word] < 0) => !literal, for all words
     * (3) (word == 0) => !literal
     *
     * Item (2) is why we can use objv to get the literals, and do not
     * have to save them at compile time.
     */

    for (word = 1; word < objc; word++) {
	if (ePtr->line[word] >= 0) {
	    int isNew;
	    Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(iPtr->lineLABCPtr,
		objv[word], &isNew);
		    objv[word], &isNew);
	    CFWordBC *cfwPtr = (CFWordBC *)Tcl_Alloc(sizeof(CFWordBC));

	    cfwPtr->framePtr = cfPtr;
	    cfwPtr->obj = objv[word];
	    cfwPtr->pc = pc;
	    cfwPtr->word = word;
	    cfwPtr->nextPtr = lastPtr;
5676
5677
5678
5679
5680
5681
5682
5683

5684
5685
5686
5687
5688
5689
5690
5959
5960
5961
5962
5963
5964
5965

5966
5967
5968
5969
5970
5971
5972
5973







-
+







{
    Interp *iPtr = (Interp *) interp;
    CFWordBC *cfwPtr = (CFWordBC *) cfPtr->litarg;

    while (cfwPtr) {
	CFWordBC *nextPtr = cfwPtr->nextPtr;
	Tcl_HashEntry *hPtr =
		Tcl_FindHashEntry(iPtr->lineLABCPtr, (char *) cfwPtr->obj);
		Tcl_FindHashEntry(iPtr->lineLABCPtr, cfwPtr->obj);
	CFWordBC *xPtr = (CFWordBC *)Tcl_GetHashValue(hPtr);

	if (xPtr != cfwPtr) {
	    Tcl_Panic("TclArgumentBC Enter/Release Mismatch");
	}

	if (cfwPtr->prevPtr) {
5741
5742
5743
5744
5745
5746
5747
5748

5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762

5763
5764
5765
5766
5767
5768
5769
6024
6025
6026
6027
6028
6029
6030

6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044

6045
6046
6047
6048
6049
6050
6051
6052







-
+













-
+







    }

    /*
     * First look for location information recorded in the argument
     * stack. That is nearest.
     */

    hPtr = Tcl_FindHashEntry(iPtr->lineLAPtr, (char *) obj);
    hPtr = Tcl_FindHashEntry(iPtr->lineLAPtr, obj);
    if (hPtr) {
	CFWord *cfwPtr = (CFWord *)Tcl_GetHashValue(hPtr);

	*wordPtr = cfwPtr->word;
	*cfPtrPtr = cfwPtr->framePtr;
	return;
    }

    /*
     * Check if the Tcl_Obj has location information as a bytecode literal, in
     * that stack.
     */

    hPtr = Tcl_FindHashEntry(iPtr->lineLABCPtr, (char *) obj);
    hPtr = Tcl_FindHashEntry(iPtr->lineLABCPtr, obj);
    if (hPtr) {
	CFWordBC *cfwPtr = (CFWordBC *)Tcl_GetHashValue(hPtr);

	framePtr = cfwPtr->framePtr;
	framePtr->data.tebc.pc = (char *) (((ByteCode *)
		framePtr->data.tebc.codePtr)->codeStart + cfwPtr->pc);
	*cfPtrPtr = cfwPtr->framePtr;
5800
5801
5802
5803
5804
5805
5806
5807

5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820

5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839

5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858

5859
5860
5861
5862
5863
5864
5865
6083
6084
6085
6086
6087
6088
6089

6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102

6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121

6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140

6141
6142
6143
6144
6145
6146
6147
6148







-
+












-
+


















-
+


















-
+







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

int
Tcl_EvalObjEx(
    Tcl_Interp *interp,		/* Token for command interpreter (returned by
				 * a previous call to Tcl_CreateInterp). */
    Tcl_Obj *objPtr,	/* Pointer to object containing commands to
    Tcl_Obj *objPtr,		/* Pointer to object containing commands to
				 * execute. */
    int flags)			/* Collection of OR-ed bits that control the
				 * evaluation of the script. Supported values
				 * are TCL_EVAL_GLOBAL and TCL_EVAL_DIRECT. */
{
    return TclEvalObjEx(interp, objPtr, flags, NULL, 0);
}

int
TclEvalObjEx(
    Tcl_Interp *interp,		/* Token for command interpreter (returned by
				 * a previous call to Tcl_CreateInterp). */
    Tcl_Obj *objPtr,	/* Pointer to object containing commands to
    Tcl_Obj *objPtr,		/* Pointer to object containing commands to
				 * execute. */
    int flags,			/* Collection of OR-ed bits that control the
				 * evaluation of the script. Supported values
				 * are TCL_EVAL_GLOBAL and TCL_EVAL_DIRECT. */
    const CmdFrame *invoker,	/* Frame of the command doing the eval. */
    int word)			/* Index of the word which is in objPtr. */
{
    int result = TCL_OK;
    NRE_callback *rootPtr = TOP_CB(interp);

    result = TclNREvalObjEx(interp, objPtr, flags, invoker, word);
    return TclNRRunCallbacks(interp, result, rootPtr);
}

int
TclNREvalObjEx(
    Tcl_Interp *interp,		/* Token for command interpreter (returned by
				 * a previous call to Tcl_CreateInterp). */
    Tcl_Obj *objPtr,	/* Pointer to object containing commands to
    Tcl_Obj *objPtr,		/* Pointer to object containing commands to
				 * execute. */
    int flags,			/* Collection of OR-ed bits that control the
				 * evaluation of the script. Supported values
				 * are TCL_EVAL_GLOBAL and TCL_EVAL_DIRECT. */
    const CmdFrame *invoker,	/* Frame of the command doing the eval. */
    int word)			/* Index of the word which is in objPtr. */
{
    Interp *iPtr = (Interp *) interp;
    int result;

    /*
     * This function consists of three independent blocks for: direct
     * evaluation of canonical lists, compilation and bytecode execution and
     * finally direct evaluation. Precisely one of these blocks will be run.
     */

    if (TclListObjIsCanonical(objPtr)) {
	CmdFrame *eoFramePtr = NULL;
	int objc;
	Tcl_Size objc;
	Tcl_Obj *listPtr, **objv;

	/*
	 * Canonical List Optimization:  In this case, we
	 * can safely use Tcl_EvalObjv instead and get an appreciable
	 * improvement in execution speed. This is because it allows us to
	 * avoid a setFromAny step that would just pack everything into a
5917
5918
5919
5920
5921
5922
5923
5924

5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947



5948
5949
5950
5951
5952
5953
5954
5955
5956
5957

5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968

5969
5970
5971
5972
5973
5974
5975
6200
6201
6202
6203
6204
6205
6206

6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227



6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239

6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250

6251
6252
6253
6254
6255
6256
6257
6258







-
+




















-
-
-
+
+
+









-
+










-
+








	    iPtr->cmdFramePtr = eoFramePtr;

	    flags |= TCL_EVAL_SOURCE_IN_FRAME;
	}

	TclMarkTailcall(interp);
        TclNRAddCallback(interp, TEOEx_ListCallback, listPtr, eoFramePtr,
	TclNRAddCallback(interp, TEOEx_ListCallback, listPtr, eoFramePtr,
		objPtr, NULL);

	TclListObjGetElements(NULL, listPtr, &objc, &objv);
	return TclNREvalObjv(interp, objc, objv, flags, NULL);
    }

    if (!(flags & TCL_EVAL_DIRECT)) {
	/*
	 * Let the compiler/engine subsystem do the evaluation.
	 *
	 * TIP #280 The invoker provides us with the context for the script.
	 * We transfer this to the byte code compiler.
	 */

	int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS);
	ByteCode *codePtr;
	CallFrame *savedVarFramePtr = NULL;	/* Saves old copy of
						 * iPtr->varFramePtr in case
						 * TCL_EVAL_GLOBAL was set. */

        if (TclInterpReady(interp) != TCL_OK) {
            return TCL_ERROR;
        }
	if (TclInterpReady(interp) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (flags & TCL_EVAL_GLOBAL) {
	    savedVarFramePtr = iPtr->varFramePtr;
	    iPtr->varFramePtr = iPtr->rootFramePtr;
	}
	Tcl_IncrRefCount(objPtr);
	codePtr = TclCompileObj(interp, objPtr, invoker, word);

	TclNRAddCallback(interp, TEOEx_ByteCodeCallback, savedVarFramePtr,
		objPtr, INT2PTR(allowExceptions), NULL);
        return TclNRExecuteByteCode(interp, codePtr);
	return TclNRExecuteByteCode(interp, codePtr);
    }

    {
	/*
	 * We're not supposed to use the compiler or byte-code
	 * interpreter. Let Tcl_EvalEx evaluate the command directly (and
	 * probably more slowly).
	 */

	const char *script;
	size_t numSrcBytes;
	Tcl_Size numSrcBytes;

	/*
	 * Now we check if we have data about invisible continuation lines for
	 * the script, and make it available to the direct script parser and
	 * evaluator we are about to call, if so.
	 *
	 * It may be possible that the script Tcl_Obj* can be free'd while the
6000
6001
6002
6003
6004
6005
6006
6007

6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022

6023
6024
6025
6026
6027
6028
6029
6283
6284
6285
6286
6287
6288
6289

6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304

6305
6306
6307
6308
6309
6310
6311
6312







-
+














-
+







	iPtr->scriptCLLocPtr = saveCLLocPtr;
	return result;
    }
}

static int
TEOEx_ByteCodeCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    CallFrame *savedVarFramePtr = (CallFrame *)data[0];
    Tcl_Obj *objPtr = (Tcl_Obj *)data[1];
    int allowExceptions = PTR2INT(data[2]);

    if (iPtr->numLevels == 0) {
	if (result == TCL_RETURN) {
	    result = TclUpdateReturnInfo(iPtr);
	}
	if ((result != TCL_OK) && (result != TCL_ERROR) && !allowExceptions) {
	    const char *script;
	    size_t numSrcBytes;
	    Tcl_Size numSrcBytes;

	    ProcessUnexpectedResult(interp, result);
	    result = TCL_ERROR;
	    script = TclGetStringFromObj(objPtr, &numSrcBytes);
	    Tcl_LogCommandInfo(interp, script, script, numSrcBytes);
	}

6046
6047
6048
6049
6050
6051
6052
6053

6054
6055
6056
6057
6058
6059
6060
6329
6330
6331
6332
6333
6334
6335

6336
6337
6338
6339
6340
6341
6342
6343







-
+








    TclDecrRefCount(objPtr);
    return result;
}

static int
TEOEx_ListCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *listPtr = (Tcl_Obj *)data[0];
    CmdFrame *eoFramePtr = (CmdFrame *)data[1];
    Tcl_Obj *objPtr = (Tcl_Obj *)data[2];
6100
6101
6102
6103
6104
6105
6106
6107

6108
6109
6110

6111
6112
6113
6114
6115
6116


6117
6118
6119
6120
6121
6122
6123
6383
6384
6385
6386
6387
6388
6389

6390
6391
6392

6393
6394
6395
6396
6397


6398
6399
6400
6401
6402
6403
6404
6405
6406







-
+


-
+




-
-
+
+







    int returnCode)		/* The unexpected result code. */
{
    char buf[TCL_INTEGER_SPACE];

    Tcl_ResetResult(interp);
    if (returnCode == TCL_BREAK) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"invoked \"break\" outside of a loop", -1));
		"invoked \"break\" outside of a loop", TCL_INDEX_NONE));
    } else if (returnCode == TCL_CONTINUE) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"invoked \"continue\" outside of a loop", -1));
		"invoked \"continue\" outside of a loop", TCL_INDEX_NONE));
    } else {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"command returned bad code: %d", returnCode));
    }
    sprintf(buf, "%d", returnCode);
    Tcl_SetErrorCode(interp, "TCL", "UNEXPECTED_RESULT_CODE", buf, NULL);
    snprintf(buf, sizeof(buf), "%d", returnCode);
    Tcl_SetErrorCode(interp, "TCL", "UNEXPECTED_RESULT_CODE", buf, (char *)NULL);
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean --
 *
6149
6150
6151
6152
6153
6154
6155
6156

6157
6158
6159
6160
6161
6162
6163
6432
6433
6434
6435
6436
6437
6438

6439
6440
6441
6442
6443
6444
6445
6446







-
+







    if (*exprstring == '\0') {
	/*
	 * Legacy compatibility - return 0 for the zero-length string.
	 */

	*ptr = 0;
    } else {
	exprPtr = Tcl_NewStringObj(exprstring, -1);
	exprPtr = Tcl_NewStringObj(exprstring, TCL_INDEX_NONE);
	Tcl_IncrRefCount(exprPtr);
	result = Tcl_ExprLongObj(interp, exprPtr, ptr);
	Tcl_DecrRefCount(exprPtr);
    }
    return result;
}

6174
6175
6176
6177
6178
6179
6180
6181

6182
6183
6184
6185
6186
6187
6188
6457
6458
6459
6460
6461
6462
6463

6464
6465
6466
6467
6468
6469
6470
6471







-
+







    if (*exprstring == '\0') {
	/*
	 * Legacy compatibility - return 0 for the zero-length string.
	 */

	*ptr = 0.0;
    } else {
	exprPtr = Tcl_NewStringObj(exprstring, -1);
	exprPtr = Tcl_NewStringObj(exprstring, TCL_INDEX_NONE);
	Tcl_IncrRefCount(exprPtr);
	result = Tcl_ExprDoubleObj(interp, exprPtr, ptr);
	Tcl_DecrRefCount(exprPtr);
				/* Discard the expression object. */
    }
    return result;
}
6199
6200
6201
6202
6203
6204
6205
6206

6207
6208
6209
6210
6211
6212
6213
6482
6483
6484
6485
6486
6487
6488

6489
6490
6491
6492
6493
6494
6495
6496







-
+







	 * An empty string. Just set the result boolean to 0 (false).
	 */

	*ptr = 0;
	return TCL_OK;
    } else {
	int result;
	Tcl_Obj *exprPtr = Tcl_NewStringObj(exprstring, -1);
	Tcl_Obj *exprPtr = Tcl_NewStringObj(exprstring, TCL_INDEX_NONE);

	Tcl_IncrRefCount(exprPtr);
	result = Tcl_ExprBooleanObj(interp, exprPtr, ptr);
	Tcl_DecrRefCount(exprPtr);
	return result;
    }
}
6233
6234
6235
6236
6237
6238
6239
6240

6241
6242
6243
6244
6245
6246

6247
6248
6249
6250
6251
6252
6253

6254
6255
6256
6257
6258
6259
6260
6516
6517
6518
6519
6520
6521
6522

6523
6524
6525
6526
6527
6528

6529
6530
6531
6532
6533
6534
6535

6536
6537
6538
6539
6540
6541
6542
6543







-
+





-
+






-
+







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

int
Tcl_ExprLongObj(
    Tcl_Interp *interp,		/* Context in which to evaluate the
				 * expression. */
    Tcl_Obj *objPtr,	/* Expression to evaluate. */
    Tcl_Obj *objPtr,		/* Expression to evaluate. */
    long *ptr)			/* Where to store long result. */
{
    Tcl_Obj *resultPtr;
    int result, type;
    double d;
    ClientData internalPtr;
    void *internalPtr;

    result = Tcl_ExprObj(interp, objPtr, &resultPtr);
    if (result != TCL_OK) {
	return TCL_ERROR;
    }

    if (TclGetNumberFromObj(interp, resultPtr, &internalPtr, &type)!=TCL_OK) {
    if (Tcl_GetNumberFromObj(interp, resultPtr, &internalPtr, &type) != TCL_OK) {
	return TCL_ERROR;
    }

    switch (type) {
    case TCL_NUMBER_DOUBLE: {
	mp_int big;

6280
6281
6282
6283
6284
6285
6286
6287

6288
6289
6290
6291
6292

6293
6294
6295
6296
6297
6298
6299

6300
6301
6302
6303
6304
6305
6306
6563
6564
6565
6566
6567
6568
6569

6570
6571
6572
6573
6574

6575
6576
6577
6578
6579
6580
6581

6582
6583
6584
6585
6586
6587
6588
6589







-
+




-
+






-
+







    return result;
}

int
Tcl_ExprDoubleObj(
    Tcl_Interp *interp,		/* Context in which to evaluate the
				 * expression. */
    Tcl_Obj *objPtr,	/* Expression to evaluate. */
    Tcl_Obj *objPtr,		/* Expression to evaluate. */
    double *ptr)		/* Where to store double result. */
{
    Tcl_Obj *resultPtr;
    int result, type;
    ClientData internalPtr;
    void *internalPtr;

    result = Tcl_ExprObj(interp, objPtr, &resultPtr);
    if (result != TCL_OK) {
	return TCL_ERROR;
    }

    result = TclGetNumberFromObj(interp, resultPtr, &internalPtr, &type);
    result = Tcl_GetNumberFromObj(interp, resultPtr, &internalPtr, &type);
    if (result == TCL_OK) {
	switch (type) {
	case TCL_NUMBER_NAN:
#ifndef ACCEPT_NAN
	    result = Tcl_GetDoubleFromObj(interp, resultPtr, ptr);
	    break;
#endif
6316
6317
6318
6319
6320
6321
6322
6323

6324
6325
6326
6327
6328
6329
6330
6599
6600
6601
6602
6603
6604
6605

6606
6607
6608
6609
6610
6611
6612
6613







-
+







    return result;
}

int
Tcl_ExprBooleanObj(
    Tcl_Interp *interp,		/* Context in which to evaluate the
				 * expression. */
    Tcl_Obj *objPtr,	/* Expression to evaluate. */
    Tcl_Obj *objPtr,		/* Expression to evaluate. */
    int *ptr)			/* Where to store 0/1 result. */
{
    Tcl_Obj *resultPtr;
    int result;

    result = Tcl_ExprObj(interp, objPtr, &resultPtr);
    if (result == TCL_OK) {
6356
6357
6358
6359
6360
6361
6362
6363

6364
6365
6366
6367
6368
6369
6370
6639
6640
6641
6642
6643
6644
6645

6646
6647
6648
6649
6650
6651
6652
6653







-
+







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

int
TclObjInvokeNamespace(
    Tcl_Interp *interp,		/* Interpreter in which command is to be
				 * invoked. */
    int objc,			/* Count of arguments. */
    Tcl_Size objc,		/* Count of arguments. */
    Tcl_Obj *const objv[],	/* Argument objects; objv[0] points to the
				 * name of the command to invoke. */
    Tcl_Namespace *nsPtr,	/* The namespace to use. */
    int flags)			/* Combination of flags controlling the call:
				 * TCL_INVOKE_HIDDEN, TCL_INVOKE_NO_UNKNOWN,
				 * or TCL_INVOKE_NO_TRACEBACK. */
{
6400
6401
6402
6403
6404
6405
6406
6407

6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419

6420
6421
6422
6423
6424
6425
6426
6683
6684
6685
6686
6687
6688
6689

6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701

6702
6703
6704
6705
6706
6707
6708
6709







-
+











-
+







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

int
TclObjInvoke(
    Tcl_Interp *interp,		/* Interpreter in which command is to be
				 * invoked. */
    int objc,			/* Count of arguments. */
    Tcl_Size objc,		/* Count of arguments. */
    Tcl_Obj *const objv[],	/* Argument objects; objv[0] points to the
				 * name of the command to invoke. */
    int flags)			/* Combination of flags controlling the call:
				 * TCL_INVOKE_HIDDEN, TCL_INVOKE_NO_UNKNOWN,
				 * or TCL_INVOKE_NO_TRACEBACK. */
{
    if (interp == NULL) {
	return TCL_ERROR;
    }
    if ((objc < 1) || (objv == NULL)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
                "illegal argument vector", -1));
		"illegal argument vector", TCL_INDEX_NONE));
	return TCL_ERROR;
    }
    if ((flags & TCL_INVOKE_HIDDEN) == 0) {
	Tcl_Panic("TclObjInvoke: called without TCL_INVOKE_HIDDEN");
    }
    return Tcl_NRCallObjProc(interp, TclNRInvoke, NULL, objc, objv);
}
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450



6451
6452
6453
6454
6455
6456
6457
6724
6725
6726
6727
6728
6729
6730



6731
6732
6733
6734
6735
6736
6737
6738
6739
6740







-
-
-
+
+
+







    cmdName = TclGetString(objv[0]);
    hTblPtr = iPtr->hiddenCmdTablePtr;
    if (hTblPtr != NULL) {
	hPtr = Tcl_FindHashEntry(hTblPtr, cmdName);
    }
    if (hPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "invalid hidden command name \"%s\"", cmdName));
        Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "HIDDENTOKEN", cmdName,
                NULL);
		"invalid hidden command name \"%s\"", cmdName));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "HIDDENTOKEN", cmdName,
		(char *)NULL);
	return TCL_ERROR;
    }
    cmdPtr = (Command *)Tcl_GetHashValue(hPtr);

    /*
     * Avoid the exception-handling brain damage when numLevels == 0
     */
6466
6467
6468
6469
6470
6471
6472
6473

6474
6475
6476
6477
6478
6479
6480
6749
6750
6751
6752
6753
6754
6755

6756
6757
6758
6759
6760
6761
6762
6763







-
+







     */

    return TclNREvalObjv(interp, objc, objv, TCL_EVAL_NORESOLVE, cmdPtr);
}

static int
NRPostInvoke(
    TCL_UNUSED(ClientData *),
    TCL_UNUSED(void **),
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *)interp;

    iPtr->numLevels--;
    return result;
6511
6512
6513
6514
6515
6516
6517
6518

6519
6520
6521
6522
6523
6524
6525
6794
6795
6796
6797
6798
6799
6800

6801
6802
6803
6804
6805
6806
6807
6808







-
+







    if (expr[0] == '\0') {
	/*
	 * An empty string. Just set the interpreter's result to 0.
	 */

	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(0));
    } else {
	Tcl_Obj *resultPtr, *exprObj = Tcl_NewStringObj(expr, -1);
	Tcl_Obj *resultPtr, *exprObj = Tcl_NewStringObj(expr, TCL_INDEX_NONE);

	Tcl_IncrRefCount(exprObj);
	code = Tcl_ExprObj(interp, exprObj, &resultPtr);
	Tcl_DecrRefCount(exprObj);
	if (code == TCL_OK) {
	    Tcl_SetObjResult(interp, resultPtr);
	    Tcl_DecrRefCount(resultPtr);
6549
6550
6551
6552
6553
6554
6555
6556

6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572

6573
6574
6575
6576
6577
6578
6579
6832
6833
6834
6835
6836
6837
6838

6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854

6855
6856
6857
6858
6859
6860
6861
6862







-
+















-
+








void
Tcl_AppendObjToErrorInfo(
    Tcl_Interp *interp,		/* Interpreter to which error information
				 * pertains. */
    Tcl_Obj *objPtr)		/* Message to record. */
{
    size_t length;
    Tcl_Size length;
    const char *message = TclGetStringFromObj(objPtr, &length);
    Interp *iPtr = (Interp *) interp;

    Tcl_IncrRefCount(objPtr);

    /*
     * If we are just starting to log an error, errorInfo is initialized from
     * the error message in the interpreter's result.
     */

    iPtr->flags |= ERR_LEGACY_COPY;
    if (iPtr->errorInfo == NULL) {
	iPtr->errorInfo = iPtr->objResultPtr;
	Tcl_IncrRefCount(iPtr->errorInfo);
	if (!iPtr->errorCode) {
	    Tcl_SetErrorCode(interp, "NONE", NULL);
	    Tcl_SetErrorCode(interp, "NONE", (char *)NULL);
	}
    }

    /*
     * Now append "message" to the end of errorInfo.
     */

6625
6626
6627
6628
6629
6630
6631
6632

6633
6634
6635

6636
6637
6638
6639
6640
6641
6642
6908
6909
6910
6911
6912
6913
6914

6915
6916
6917

6918
6919
6920
6921
6922
6923
6924
6925







-
+


-
+








    Tcl_DStringInit(&buf);
    while (1) {
	string = va_arg(argList, char *);
	if (string == NULL) {
	    break;
	}
	Tcl_DStringAppend(&buf, string, -1);
	Tcl_DStringAppend(&buf, string, TCL_INDEX_NONE);
    }

    result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
    result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), TCL_INDEX_NONE, 0);
    Tcl_DStringFree(&buf);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
6650
6651
6652
6653
6654
6655
6656
6657

6658
6659
6660
6661

6662
6663
6664

6665
6666
6667
6668
6669
6670
6671
6933
6934
6935
6936
6937
6938
6939

6940
6941
6942
6943

6944
6945
6946

6947
6948
6949
6950
6951
6952
6953
6954







-
+



-
+


-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_Size
Tcl_SetRecursionLimit(
    Tcl_Interp *interp,		/* Interpreter whose nesting limit is to be
				 * set. */
    int depth)			/* New value for maximimum depth. */
    Tcl_Size depth)		/* New value for maximum depth. */
{
    Interp *iPtr = (Interp *) interp;
    int old;
    Tcl_Size old;

    old = iPtr->maxNestingDepth;
    if (depth > 0) {
	iPtr->maxNestingDepth = depth;
    }
    return old;
}
6770
6771
6772
6773
6774
6775
6776
6777

6778
6779
6780
6781
6782
6783
6784
7053
7054
7055
7056
7057
7058
7059

7060
7061
7062
7063
7064
7065
7066
7067







-
+







    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }
    code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
#ifdef ACCEPT_NAN
    if (code != TCL_OK) {
	const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objv[1], &tclDoubleType);
	const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], &tclDoubleType);

	if (irPtr) {
	    Tcl_SetObjResult(interp, objv[1]);
	    return TCL_OK;
	}
    }
#endif
6810
6811
6812
6813
6814
6815
6816
6817

6818
6819
6820
6821
6822
6823
6824
7093
7094
7095
7096
7097
7098
7099

7100
7101
7102
7103
7104
7105
7106
7107







-
+







    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }
    code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
#ifdef ACCEPT_NAN
    if (code != TCL_OK) {
	const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objv[1], &tclDoubleType);
	const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], &tclDoubleType);

	if (irPtr) {
	    Tcl_SetObjResult(interp, objv[1]);
	    return TCL_OK;
	}
    }
#endif
6838
6839
6840
6841
6842
6843
6844
6845

6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866

6867
6868
6869
6870
6871
6872
6873
7121
7122
7123
7124
7125
7126
7127

7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148

7149
7150
7151
7152
7153
7154
7155
7156







-
+




















-
+







static int
ExprIsqrtFunc(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* The interpreter in which to execute. */
    int objc,			/* Actual parameter count. */
    Tcl_Obj *const *objv)	/* Actual parameter list. */
{
    ClientData ptr;
    void *ptr;
    int type;
    double d;
    Tcl_WideInt w;
    mp_int big;
    int exact = 0;		/* Flag ==1 if the argument can be represented
				 * in a double as an exact integer. */

    /*
     * Check syntax.
     */

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }

    /*
     * Make sure that the arg is a number.
     */

    if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
    if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
	return TCL_ERROR;
    }

    switch (type) {
    case TCL_NUMBER_NAN:
	Tcl_GetDoubleFromObj(interp, objv[1], &d);
	return TCL_ERROR;
6931
6932
6933
6934
6935
6936
6937
6938

6939
6940

6941
6942
6943
6944
6945
6946
6947
7214
7215
7216
7217
7218
7219
7220

7221
7222

7223
7224
7225
7226
7227
7228
7229
7230







-
+

-
+







	}
	Tcl_SetObjResult(interp, Tcl_NewBignumObj(&root));
    }
    return TCL_OK;

  negarg:
    Tcl_SetObjResult(interp, Tcl_NewStringObj(
            "square root of negative argument", -1));
	    "square root of negative argument", TCL_INDEX_NONE));
    Tcl_SetErrorCode(interp, "ARITH", "DOMAIN",
	    "domain error: argument not in valid range", NULL);
	    "domain error: argument not in valid range", (char *)NULL);
    return TCL_ERROR;
}

static int
ExprSqrtFunc(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* The interpreter in which to execute the
6956
6957
6958
6959
6960
6961
6962
6963

6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974

6975
6976
6977
6978
6979
6980
6981
7239
7240
7241
7242
7243
7244
7245

7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256

7257
7258
7259
7260
7261
7262
7263
7264







-
+










-
+







    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }
    code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
#ifdef ACCEPT_NAN
    if (code != TCL_OK) {
	const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objv[1], &tclDoubleType);
	const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], &tclDoubleType);

	if (irPtr) {
	    Tcl_SetObjResult(interp, objv[1]);
	    return TCL_OK;
	}
    }
#endif
    if (code != TCL_OK) {
	return TCL_ERROR;
    }
    if ((d >= 0.0) && TclIsInfinite(d)
    if ((d >= 0.0) && isinf(d)
	    && (Tcl_GetBignumFromObj(NULL, objv[1], &big) == TCL_OK)) {
	mp_int root;
	mp_err err;

	err = mp_init(&root);
	if (err == MP_OKAY) {
	    err = mp_sqrt(&big, &root);
6991
6992
6993
6994
6995
6996
6997
6998

6999
7000
7001
7002
7003
7004
7005
7006
7007
7008

7009
7010
7011
7012
7013
7014
7015
7016
7017

7018
7019
7020
7021
7022
7023
7024
7274
7275
7276
7277
7278
7279
7280

7281
7282
7283
7284
7285
7286
7287
7288
7289
7290

7291
7292
7293
7294
7295
7296
7297
7298
7299

7300
7301
7302
7303
7304
7305
7306
7307







-
+









-
+








-
+







	Tcl_SetObjResult(interp, Tcl_NewDoubleObj(sqrt(d)));
    }
    return TCL_OK;
}

static int
ExprUnaryFunc(
    ClientData clientData,	/* Contains the address of a function that
    void *clientData,		/* Contains the address of a function that
				 * takes one double argument and returns a
				 * double result. */
    Tcl_Interp *interp,		/* The interpreter in which to execute the
				 * function. */
    int objc,			/* Actual parameter count */
    Tcl_Obj *const *objv)	/* Actual parameter list */
{
    int code;
    double d;
    double (*func)(double) = (double (*)(double)) clientData;
    BuiltinUnaryFunc *func = (BuiltinUnaryFunc *) clientData;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }
    code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
#ifdef ACCEPT_NAN
    if (code != TCL_OK) {
	const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objv[1], &tclDoubleType);
	const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], &tclDoubleType);

	if (irPtr) {
	    d = irPtr->doubleValue;
	    Tcl_ResetResult(interp);
	    code = TCL_OK;
	}
    }
7032
7033
7034
7035
7036
7037
7038
7039

7040
7041
7042
7043
7044

7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062

7063
7064
7065
7066
7067
7068
7069
7070
7071
7072

7073
7074
7075
7076
7077
7078
7079
7080
7081

7082
7083
7084
7085
7086
7087
7088
7089
7090
7091
7092
7093
7094
7095
7096

7097
7098
7099
7100
7101
7102
7103
7315
7316
7317
7318
7319
7320
7321

7322
7323
7324
7325
7326

7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344

7345
7346
7347
7348
7349
7350
7351
7352
7353
7354

7355
7356
7357
7358
7359
7360
7361
7362
7363

7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378

7379
7380
7381
7382
7383
7384
7385
7386







-
+




-
+

















-
+









-
+








-
+














-
+








static int
CheckDoubleResult(
    Tcl_Interp *interp,
    double dResult)
{
#ifndef ACCEPT_NAN
    if (TclIsNaN(dResult)) {
    if (isnan(dResult)) {
	TclExprFloatError(interp, dResult);
	return TCL_ERROR;
    }
#endif
    if ((errno == ERANGE) && ((dResult == 0.0) || TclIsInfinite(dResult))) {
    if ((errno == ERANGE) && ((dResult == 0.0) || isinf(dResult))) {
	/*
	 * When ERANGE signals under/overflow, just accept 0.0 or +/-Inf
	 */
    } else if (errno != 0) {
	/*
	 * Report other errno values as errors.
	 */

	TclExprFloatError(interp, dResult);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(dResult));
    return TCL_OK;
}

static int
ExprBinaryFunc(
    ClientData clientData,	/* Contains the address of a function that
    void *clientData,		/* Contains the address of a function that
				 * takes two double arguments and returns a
				 * double result. */
    Tcl_Interp *interp,		/* The interpreter in which to execute the
				 * function. */
    int objc,			/* Actual parameter count. */
    Tcl_Obj *const *objv)	/* Parameter vector. */
{
    int code;
    double d1, d2;
    double (*func)(double, double) = (double (*)(double, double)) clientData;
    BuiltinBinaryFunc *func = (BuiltinBinaryFunc *)clientData;

    if (objc != 3) {
	MathFuncWrongNumArgs(interp, 3, objc, objv);
	return TCL_ERROR;
    }
    code = Tcl_GetDoubleFromObj(interp, objv[1], &d1);
#ifdef ACCEPT_NAN
    if (code != TCL_OK) {
	const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objv[1], &tclDoubleType);
	const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], &tclDoubleType);

	if (irPtr) {
	    d1 = irPtr->doubleValue;
	    Tcl_ResetResult(interp);
	    code = TCL_OK;
	}
    }
#endif
    if (code != TCL_OK) {
	return TCL_ERROR;
    }
    code = Tcl_GetDoubleFromObj(interp, objv[2], &d2);
#ifdef ACCEPT_NAN
    if (code != TCL_OK) {
	const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objv[1], &tclDoubleType);
	const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], &tclDoubleType);

	if (irPtr) {
	    d2 = irPtr->doubleValue;
	    Tcl_ResetResult(interp);
	    code = TCL_OK;
	}
    }
7113
7114
7115
7116
7117
7118
7119
7120

7121
7122
7123
7124
7125
7126
7127
7128
7129

7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140

7141
7142
7143
7144
7145
7146
7147
7148


7149
7150
7151
7152









7153

7154
7155
7156
7157
7158
7159
7160
7396
7397
7398
7399
7400
7401
7402

7403
7404
7405
7406
7407
7408
7409
7410
7411

7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422

7423
7424
7425
7426
7427
7428
7429
7430

7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445

7446
7447
7448
7449
7450
7451
7452
7453







-
+








-
+










-
+







-
+
+




+
+
+
+
+
+
+
+
+
-
+







ExprAbsFunc(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* The interpreter in which to execute the
				 * function. */
    int objc,			/* Actual parameter count. */
    Tcl_Obj *const *objv)	/* Parameter vector. */
{
    ClientData ptr;
    void *ptr;
    int type;
    mp_int big;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }

    if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
    if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
	return TCL_ERROR;
    }

    if (type == TCL_NUMBER_INT) {
	Tcl_WideInt l = *((const Tcl_WideInt *) ptr);

	if (l > 0) {
	    goto unChanged;
	} else if (l == 0) {
	    if (TclHasStringRep(objv[1])) {
		size_t numBytes;
		Tcl_Size numBytes;
		const char *bytes = TclGetStringFromObj(objv[1], &numBytes);

		while (numBytes) {
		    if (*bytes == '-') {
			Tcl_SetObjResult(interp, Tcl_NewWideIntObj(0));
			return TCL_OK;
		    }
		    bytes++; numBytes--;
		    bytes++;
		    numBytes--;
		}
	    }
	    goto unChanged;
	} else if (l == WIDE_MIN) {
	    if (sizeof(Tcl_WideInt) > sizeof(int64_t)) {
		Tcl_WideUInt ul = -(Tcl_WideUInt)WIDE_MIN;
		if (mp_init(&big) != MP_OKAY || mp_unpack(&big, 1, 1,
			sizeof(Tcl_WideInt), 0, 0, &ul) != MP_OKAY) {
		    return TCL_ERROR;
		}
		if (mp_neg(&big, &big) != MP_OKAY) {
		    return TCL_ERROR;
		}
	    if (mp_init_i64(&big, l) != MP_OKAY) {
	    } else if (mp_init_i64(&big, l) != MP_OKAY) {
		return TCL_ERROR;
	    }
	    goto tooLarge;
	}
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-l));
	return TCL_OK;
    }
7241
7242
7243
7244
7245
7246
7247
7248

7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269

7270
7271
7272
7273
7274
7275

7276
7277
7278
7279
7280
7281
7282
7534
7535
7536
7537
7538
7539
7540

7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561

7562
7563
7564
7565
7566
7567

7568
7569
7570
7571
7572
7573
7574
7575







-
+




















-
+





-
+








    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }
    if (Tcl_GetDoubleFromObj(interp, objv[1], &dResult) != TCL_OK) {
#ifdef ACCEPT_NAN
	if (TclHasIntRep(objv[1], &tclDoubleType)) {
	if (TclHasInternalRep(objv[1], &tclDoubleType)) {
	    Tcl_SetObjResult(interp, objv[1]);
	    return TCL_OK;
	}
#endif
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(dResult));
    return TCL_OK;
}

static int
ExprIntFunc(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* The interpreter in which to execute the
				 * function. */
    int objc,			/* Actual parameter count. */
    Tcl_Obj *const *objv)	/* Actual parameter vector. */
{
    double d;
    int type;
    ClientData ptr;
    void *ptr;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }
    if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
    if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
	return TCL_ERROR;
    }

    if (type == TCL_NUMBER_DOUBLE) {
	d = *((const double *) ptr);
	if ((d >= (double)WIDE_MAX) || (d <= (double)WIDE_MIN)) {
	    mp_int big;
7340
7341
7342
7343
7344
7345
7346
7347
7348



7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362







7363
7364
7365
7366
7367
7368
7369






7370
7371
7372
7373
7374
7375
7376
7633
7634
7635
7636
7637
7638
7639


7640
7641
7642
7643
7644
7645
7646
7647
7648
7649







7650
7651
7652
7653
7654
7655
7656
7657






7658
7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669
7670







-
-
+
+
+







-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+







				 * function. */
    int objc,			/* Actual parameter count. */
    Tcl_Obj *const *objv,	/* Actual parameter vector. */
    int op)			/* Comparison direction */
{
    Tcl_Obj *res;
    double d;
    int type, i;
    ClientData ptr;
    int type;
    int i;
    void *ptr;

    if (objc < 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }
    res = objv[1];
    for (i = 1; i < objc; i++) {
        if (TclGetNumberFromObj(interp, objv[i], &ptr, &type) != TCL_OK) {
            return TCL_ERROR;
        }
        if (type == TCL_NUMBER_NAN) {
            /*
             * Get the error message for NaN.
             */
	if (Tcl_GetNumberFromObj(interp, objv[i], &ptr, &type) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (type == TCL_NUMBER_NAN) {
	    /*
	     * Get the error message for NaN.
	     */

            Tcl_GetDoubleFromObj(interp, objv[i], &d);
            return TCL_ERROR;
        }
        if (TclCompareTwoNumbers(objv[i], res) == op)  {
            res = objv[i];
        }
	    Tcl_GetDoubleFromObj(interp, objv[i], &d);
	    return TCL_ERROR;
	}
	if (TclCompareTwoNumbers(objv[i], res) == op) {
	    res = objv[i];
	}
    }

    Tcl_SetObjResult(interp, res);
    return TCL_OK;
}

static int
7418
7419
7420
7421
7422
7423
7424
7425

7426
7427
7428
7429
7430
7431
7432
7433



7434
7435
7436
7437
7438
7439
7440
7712
7713
7714
7715
7716
7717
7718

7719
7720
7721
7722
7723
7724



7725
7726
7727
7728
7729
7730
7731
7732
7733
7734







-
+





-
-
-
+
+
+







	iPtr->flags |= RAND_SEED_INITIALIZED;

	/*
	 * To ensure different seeds in different threads (bug #416643),
	 * take into consideration the thread this interp is running in.
	 */

	iPtr->randSeed = TclpGetClicks() + (PTR2INT(Tcl_GetCurrentThread())<<12);
	iPtr->randSeed = TclpGetClicks() + PTR2UINT(Tcl_GetCurrentThread()) * 4093U;

	/*
	 * Make sure 1 <= randSeed <= (2^31) - 2. See below.
	 */

	iPtr->randSeed &= 0x7FFFFFFF;
	if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7FFFFFFF)) {
	    iPtr->randSeed ^= 123459876;
	iPtr->randSeed &= 0x7FFFFFFFL;
	if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7FFFFFFFL)) {
	    iPtr->randSeed ^= 123459876L;
	}
    }

    /*
     * Generate the random number using the linear congruential generator
     * defined by the following recurrence:
     *		seed = ( IA * seed ) mod IM
7493
7494
7495
7496
7497
7498
7499
7500

7501
7502
7503
7504
7505
7506
7507
7508

7509
7510
7511
7512
7513
7514
7515
7787
7788
7789
7790
7791
7792
7793

7794
7795
7796
7797
7798
7799
7800
7801

7802
7803
7804
7805
7806
7807
7808
7809







-
+







-
+







    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* The interpreter in which to execute the
				 * function. */
    int objc,			/* Actual parameter count. */
    Tcl_Obj *const *objv)	/* Parameter vector. */
{
    double d;
    ClientData ptr;
    void *ptr;
    int type;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }

    if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
    if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
	return TCL_ERROR;
    }

    if (type == TCL_NUMBER_DOUBLE) {
	double fractPart, intPart;
	Tcl_WideInt max = WIDE_MAX, min = WIDE_MIN;

7615
7616
7617
7618
7619
7620
7621
7622
7623


7624
7625
7626
7627
7628
7629
7630
7909
7910
7911
7912
7913
7914
7915


7916
7917
7918
7919
7920
7921
7922
7923
7924







-
-
+
+







 *----------------------------------------------------------------------
 *
 * Double Classification Functions --
 *
 *	This page contains the functions that implement all of the built-in
 *	math functions for classifying IEEE doubles.
 *
 *      These have to be a little bit careful while Tcl_GetDoubleFromObj()
 *      rejects NaN values, which these functions *explicitly* accept.
 *	These have to be a little bit careful while Tcl_GetDoubleFromObj()
 *	rejects NaN values, which these functions *explicitly* accept.
 *
 * Results:
 *	Each function returns TCL_OK if it succeeds and pushes an Tcl object
 *	holding the result. If it fails it returns TCL_ERROR and leaves an
 *	error message in the interpreter's result.
 *
 * Side effects:
7650
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660
7661





7662
7663
7664
7665
7666

7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685










7686
7687
7688


7689
7690
7691
7692
7693
7694
7695
7696



7697
7698
7699
7700
7701
7702
7703
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717



7718
7719

7720
7721
7722
7723



7724
7725

7726
7727
7728
7729



7730
7731

7732
7733
7734
7735
7736
7737

7738
7739
7740

7741
7742
7743

7744
7745
7746

7747
7748

7749
7750
7751

7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768

7769
7770
7771
7772
7773
7774
7775
7776
7777


7778
7779
7780
7781
7782
7783
7784





7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799

7800
7801
7802
7803
7804
7805
7806
7807
7808


7809
7810
7811
7812
7813
7814




7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829

7830
7831
7832
7833
7834
7835
7836
7837
7838


7839
7840
7841
7842
7843
7844




7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859

7860
7861
7862
7863
7864
7865
7866
7867
7868


7869
7870
7871
7872
7873
7874




7875
7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889

7890
7891
7892
7893
7894
7895
7896
7897
7898


7899
7900
7901
7902
7903
7904




7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917
7918
7919

7920
7921
7922
7923
7924
7925
7926
7927
7928


7929
7930
7931

7932
7933
7934


7935
7936
7937
7938


7939
7940
7941

7942
7943
7944


7945
7946
7947
7948
7949
7950
7951
7952
7953
7954
7955
7956
7957
7958
7959
7960
7961

7962
7963
7964
7965

7966
7967
7968
7969
7970


7971
7972
7973

7974
7975

7976
7977
7978
7979
7980


7981
7982
7983
7984


7985
7986
7987


7988
7989
7990


7991
7992
7993


7994
7995
7996
7997



7998
7999
8000
8001
8002
8003
8004
7944
7945
7946
7947
7948
7949
7950





7951
7952
7953
7954
7955
7956
7957
7958
7959

7960
7961
7962
7963
7964
7965
7966
7967
7968
7969










7970
7971
7972
7973
7974
7975
7976
7977
7978
7979
7980


7981
7982
7983
7984
7985
7986
7987



7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999
8000
8001
8002
8003
8004
8005
8006
8007
8008



8009
8010
8011
8012

8013
8014



8015
8016
8017
8018

8019
8020



8021
8022
8023
8024

8025
8026
8027
8028
8029
8030

8031
8032
8033

8034
8035
8036

8037
8038
8039

8040
8041

8042
8043
8044

8045
8046
8047
8048
8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060
8061

8062
8063
8064
8065
8066
8067
8068
8069


8070
8071
8072
8073





8074
8075
8076
8077
8078
8079
8080
8081
8082
8083
8084
8085
8086
8087
8088
8089
8090
8091
8092

8093
8094
8095
8096
8097
8098
8099
8100


8101
8102
8103
8104




8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122

8123
8124
8125
8126
8127
8128
8129
8130


8131
8132
8133
8134




8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
8148
8149
8150
8151
8152

8153
8154
8155
8156
8157
8158
8159
8160


8161
8162
8163
8164




8165
8166
8167
8168
8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181
8182

8183
8184
8185
8186
8187
8188
8189
8190


8191
8192
8193
8194




8195
8196
8197
8198
8199
8200
8201
8202
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212

8213
8214
8215
8216
8217
8218
8219
8220


8221
8222
8223
8224

8225
8226


8227
8228
8229
8230


8231
8232
8233
8234

8235
8236


8237
8238
8239
8240
8241
8242
8243
8244
8245
8246
8247
8248
8249
8250
8251
8252
8253
8254

8255
8256
8257
8258

8259
8260
8261
8262


8263
8264
8265
8266

8267
8268

8269
8270
8271
8272


8273
8274
8275
8276


8277
8278
8279


8280
8281
8282


8283
8284
8285


8286
8287
8288



8289
8290
8291
8292
8293
8294
8295
8296
8297
8298







-
-
-
-
-
+
+
+
+
+




-
+









-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
+
+





-
-
-
+
+
+


















-
-
-
+
+
+

-
+

-
-
-
+
+
+

-
+

-
-
-
+
+
+

-
+





-
+


-
+


-
+


-
+

-
+


-
+
















-
+







-
-
+
+


-
-
-
-
-
+
+
+
+
+














-
+







-
-
+
+


-
-
-
-
+
+
+
+














-
+







-
-
+
+


-
-
-
-
+
+
+
+














-
+







-
-
+
+


-
-
-
-
+
+
+
+














-
+







-
-
+
+


-
-
-
-
+
+
+
+














-
+







-
-
+
+


-
+

-
-
+
+


-
-
+
+


-
+

-
-
+
+
















-
+



-
+



-
-
+
+


-
+

-
+



-
-
+
+


-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
-
+
+
+







    return fpclassify(d);
#else /* TCL_FPCLASSIFY_MODE != 0 */
    /*
     * If we don't have fpclassify(), we also don't have the values it returns.
     * Hence we define those here.
     */
#ifndef FP_NAN
#   define FP_NAN          1	/* Value is NaN */
#   define FP_INFINITE     2	/* Value is an infinity */
#   define FP_ZERO         3	/* Value is a zero */
#   define FP_NORMAL       4	/* Value is a normal float */
#   define FP_SUBNORMAL    5	/* Value has lost accuracy */
#   define FP_NAN	1	/* Value is NaN */
#   define FP_INFINITE	2	/* Value is an infinity */
#   define FP_ZERO	3	/* Value is a zero */
#   define FP_NORMAL	4	/* Value is a normal float */
#   define FP_SUBNORMAL	5	/* Value has lost accuracy */
#endif /* !FP_NAN */

#if TCL_FPCLASSIFY_MODE == 3
    return __builtin_fpclassify(
            FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, d);
	    FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, d);
#elif TCL_FPCLASSIFY_MODE == 2
    /*
     * We assume this hack is only needed on little-endian systems.
     * Specifically, x86 running Windows.  It's fairly easy to enable for
     * others if they need it (because their libc/libm is broken) but we'll
     * jump that hurdle when requred.  We can solve the word ordering then.
     */

    union {
        double d;               /* Interpret as double */
        struct {
            unsigned int low;   /* Lower 32 bits */
            unsigned int high;  /* Upper 32 bits */
        } w;                    /* Interpret as unsigned integer words */
    } doubleMeaning;            /* So we can look at the representation of a
                                 * double directly. Platform (i.e., processor)
                                 * specific; this is for x86 (and most other
                                 * little-endian processors, but those are
                                 * untested). */
	double d;		/* Interpret as double */
	struct {
	    unsigned int low;	/* Lower 32 bits */
	    unsigned int high;	/* Upper 32 bits */
	} w;			/* Interpret as unsigned integer words */
    } doubleMeaning;		/* So we can look at the representation of a
				 * double directly. Platform (i.e., processor)
				 * specific; this is for x86 (and most other
				 * little-endian processors, but those are
				 * untested). */
    unsigned int exponent, mantissaLow, mantissaHigh;
                                /* The pieces extracted from the double. */
    int zeroMantissa;           /* Was the mantissa zero? That's special. */
				/* The pieces extracted from the double. */
    int zeroMantissa;		/* Was the mantissa zero? That's special. */

    /*
     * Shifts and masks to use with the doubleMeaning variable above.
     */

#define EXPONENT_MASK   0x7FF   /* 11 bits (after shifting) */
#define EXPONENT_SHIFT  20      /* Moves exponent to bottom of word */
#define MANTISSA_MASK   0xFFFFF /* 20 bits (plus 32 from other word) */
#define EXPONENT_MASK   0x7FF	/* 11 bits (after shifting) */
#define EXPONENT_SHIFT  20	/* Moves exponent to bottom of word */
#define MANTISSA_MASK   0xFFFFF	/* 20 bits (plus 32 from other word) */

    /*
     * Extract the exponent (11 bits) and mantissa (52 bits).  Note that we
     * totally ignore the sign bit.
     */

    doubleMeaning.d = d;
    exponent = (doubleMeaning.w.high >> EXPONENT_SHIFT) & EXPONENT_MASK;
    mantissaLow = doubleMeaning.w.low;
    mantissaHigh = doubleMeaning.w.high & MANTISSA_MASK;
    zeroMantissa = (mantissaHigh == 0 && mantissaLow == 0);

    /*
     * Look for the special cases of exponent.
     */

    switch (exponent) {
    case 0:
        /*
         * When the exponent is all zeros, it's a ZERO or a SUBNORMAL.
         */
	/*
	 * When the exponent is all zeros, it's a ZERO or a SUBNORMAL.
	 */

        return zeroMantissa ? FP_ZERO : FP_SUBNORMAL;
	return zeroMantissa ? FP_ZERO : FP_SUBNORMAL;
    case EXPONENT_MASK:
        /*
         * When the exponent is all ones, it's an INF or a NAN.
         */
	/*
	 * When the exponent is all ones, it's an INF or a NAN.
	 */

        return zeroMantissa ? FP_INFINITE : FP_NAN;
	return zeroMantissa ? FP_INFINITE : FP_NAN;
    default:
        /*
         * Everything else is a NORMAL double precision float.
         */
	/*
	 * Everything else is a NORMAL double precision float.
	 */

        return FP_NORMAL;
	return FP_NORMAL;
    }
#elif TCL_FPCLASSIFY_MODE == 1
    switch (_fpclass(d)) {
    case _FPCLASS_NZ:
    case _FPCLASS_PZ:
        return FP_ZERO;
	return FP_ZERO;
    case _FPCLASS_NN:
    case _FPCLASS_PN:
        return FP_NORMAL;
	return FP_NORMAL;
    case _FPCLASS_ND:
    case _FPCLASS_PD:
        return FP_SUBNORMAL;
	return FP_SUBNORMAL;
    case _FPCLASS_NINF:
    case _FPCLASS_PINF:
        return FP_INFINITE;
	return FP_INFINITE;
    default:
        Tcl_Panic("result of _fpclass() outside documented range!");
	Tcl_Panic("result of _fpclass() outside documented range!");
    case _FPCLASS_QNAN:
    case _FPCLASS_SNAN:
        return FP_NAN;
	return FP_NAN;
    }
#else /* TCL_FPCLASSIFY_MODE not in (0..3) */
#error "unknown or unexpected TCL_FPCLASSIFY_MODE"
#endif /* TCL_FPCLASSIFY_MODE */
#endif /* !fpclassify */
}

static int
ExprIsFiniteFunc(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* The interpreter in which to execute the
				 * function. */
    int objc,			/* Actual parameter count */
    Tcl_Obj *const *objv)	/* Actual parameter list */
{
    double d;
    ClientData ptr;
    void *ptr;
    int type, result = 0;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }

    if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
        return TCL_ERROR;
    if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
	return TCL_ERROR;
    }
    if (type != TCL_NUMBER_NAN) {
        if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) {
            return TCL_ERROR;
        }
        type = ClassifyDouble(d);
        result = (type != FP_INFINITE && type != FP_NAN);
	if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) {
	    return TCL_ERROR;
	}
	type = ClassifyDouble(d);
	result = (type != FP_INFINITE && type != FP_NAN);
    }
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result));
    return TCL_OK;
}

static int
ExprIsInfinityFunc(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* The interpreter in which to execute the
				 * function. */
    int objc,			/* Actual parameter count */
    Tcl_Obj *const *objv)	/* Actual parameter list */
{
    double d;
    ClientData ptr;
    void *ptr;
    int type, result = 0;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }

    if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
        return TCL_ERROR;
    if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
	return TCL_ERROR;
    }
    if (type != TCL_NUMBER_NAN) {
        if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) {
            return TCL_ERROR;
        }
        result = (ClassifyDouble(d) == FP_INFINITE);
	if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) {
	    return TCL_ERROR;
	}
	result = (ClassifyDouble(d) == FP_INFINITE);
    }
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result));
    return TCL_OK;
}

static int
ExprIsNaNFunc(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* The interpreter in which to execute the
				 * function. */
    int objc,			/* Actual parameter count */
    Tcl_Obj *const *objv)	/* Actual parameter list */
{
    double d;
    ClientData ptr;
    void *ptr;
    int type, result = 1;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }

    if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
        return TCL_ERROR;
    if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
	return TCL_ERROR;
    }
    if (type != TCL_NUMBER_NAN) {
        if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) {
            return TCL_ERROR;
        }
        result = (ClassifyDouble(d) == FP_NAN);
	if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) {
	    return TCL_ERROR;
	}
	result = (ClassifyDouble(d) == FP_NAN);
    }
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result));
    return TCL_OK;
}

static int
ExprIsNormalFunc(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* The interpreter in which to execute the
				 * function. */
    int objc,			/* Actual parameter count */
    Tcl_Obj *const *objv)	/* Actual parameter list */
{
    double d;
    ClientData ptr;
    void *ptr;
    int type, result = 0;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }

    if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
        return TCL_ERROR;
    if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
	return TCL_ERROR;
    }
    if (type != TCL_NUMBER_NAN) {
        if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) {
            return TCL_ERROR;
        }
        result = (ClassifyDouble(d) == FP_NORMAL);
	if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) {
	    return TCL_ERROR;
	}
	result = (ClassifyDouble(d) == FP_NORMAL);
    }
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result));
    return TCL_OK;
}

static int
ExprIsSubnormalFunc(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* The interpreter in which to execute the
				 * function. */
    int objc,			/* Actual parameter count */
    Tcl_Obj *const *objv)	/* Actual parameter list */
{
    double d;
    ClientData ptr;
    void *ptr;
    int type, result = 0;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }

    if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
        return TCL_ERROR;
    if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
	return TCL_ERROR;
    }
    if (type != TCL_NUMBER_NAN) {
        if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) {
            return TCL_ERROR;
        }
        result = (ClassifyDouble(d) == FP_SUBNORMAL);
	if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) {
	    return TCL_ERROR;
	}
	result = (ClassifyDouble(d) == FP_SUBNORMAL);
    }
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result));
    return TCL_OK;
}

static int
ExprIsUnorderedFunc(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* The interpreter in which to execute the
				 * function. */
    int objc,			/* Actual parameter count */
    Tcl_Obj *const *objv)	/* Actual parameter list */
{
    double d;
    ClientData ptr;
    void *ptr;
    int type, result = 0;

    if (objc != 3) {
	MathFuncWrongNumArgs(interp, 3, objc, objv);
	return TCL_ERROR;
    }

    if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
        return TCL_ERROR;
    if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
	return TCL_ERROR;
    }
    if (type == TCL_NUMBER_NAN) {
        result = 1;
	result = 1;
    } else {
        d = *((const double *) ptr);
        result = (ClassifyDouble(d) == FP_NAN);
	d = *((const double *) ptr);
	result = (ClassifyDouble(d) == FP_NAN);
    }

    if (TclGetNumberFromObj(interp, objv[2], &ptr, &type) != TCL_OK) {
        return TCL_ERROR;
    if (Tcl_GetNumberFromObj(interp, objv[2], &ptr, &type) != TCL_OK) {
	return TCL_ERROR;
    }
    if (type == TCL_NUMBER_NAN) {
        result |= 1;
	result |= 1;
    } else {
        d = *((const double *) ptr);
        result |= (ClassifyDouble(d) == FP_NAN);
	d = *((const double *) ptr);
	result |= (ClassifyDouble(d) == FP_NAN);
    }

    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result));
    return TCL_OK;
}

static int
FloatClassifyObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* The interpreter in which to execute the
				 * function. */
    int objc,			/* Actual parameter count */
    Tcl_Obj *const *objv)	/* Actual parameter list */
{
    double d;
    Tcl_Obj *objPtr;
    ClientData ptr;
    void *ptr;
    int type;

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

    if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
        return TCL_ERROR;
    if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
	return TCL_ERROR;
    }
    if (type == TCL_NUMBER_NAN) {
        goto gotNaN;
	goto gotNaN;
    } else if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) {
        return TCL_ERROR;
	return TCL_ERROR;
    }
    switch (ClassifyDouble(d)) {
    case FP_INFINITE:
        TclNewLiteralStringObj(objPtr, "infinite");
        break;
	TclNewLiteralStringObj(objPtr, "infinite");
	break;
    case FP_NAN:
    gotNaN:
        TclNewLiteralStringObj(objPtr, "nan");
        break;
	TclNewLiteralStringObj(objPtr, "nan");
	break;
    case FP_NORMAL:
        TclNewLiteralStringObj(objPtr, "normal");
        break;
	TclNewLiteralStringObj(objPtr, "normal");
	break;
    case FP_SUBNORMAL:
        TclNewLiteralStringObj(objPtr, "subnormal");
        break;
	TclNewLiteralStringObj(objPtr, "subnormal");
	break;
    case FP_ZERO:
        TclNewLiteralStringObj(objPtr, "zero");
        break;
	TclNewLiteralStringObj(objPtr, "zero");
	break;
    default:
        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "unable to classify number: %f", d));
        return TCL_ERROR;
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"unable to classify number: %f", d));
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, objPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
8023
8024
8025
8026
8027
8028
8029
8030

8031
8032
8033

8034
8035
8036
8037
8038
8039
8040

8041
8042
8043
8044
8045
8046
8047
8317
8318
8319
8320
8321
8322
8323

8324
8325
8326

8327
8328
8329
8330
8331
8332
8333

8334
8335
8336
8337
8338
8339
8340
8341







-
+


-
+






-
+







    int expected,		/* Formal parameter count. */
    int found,			/* Actual parameter count. */
    Tcl_Obj *const *objv)	/* Actual parameter vector. */
{
    const char *name = TclGetString(objv[0]);
    const char *tail = name + strlen(name);

    while (tail > name+1) {
    while (tail > name + 1) {
	tail--;
	if (*tail == ':' && tail[-1] == ':') {
	    name = tail+1;
	    name = tail + 1;
	    break;
	}
    }
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "%s arguments for math function \"%s\"",
	    (found < expected ? "not enough" : "too many"), name));
    Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL);
    Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (char *)NULL);
}

#ifdef USE_DTRACE
/*
 *----------------------------------------------------------------------
 *
 * DTraceObjCmd --
8093
8094
8095
8096
8097
8098
8099
8100

8101
8102
8103
8104
8105
8106
8107
8387
8388
8389
8390
8391
8392
8393

8394
8395
8396
8397
8398
8399
8400
8401







-
+







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

void
TclDTraceInfo(
    Tcl_Obj *info,
    const char **args,
    int *argsi)
    Tcl_Size *argsi)
{
    static Tcl_Obj *keys[10] = { NULL };
    Tcl_Obj **k = keys, *val;
    int i = 0;

    if (!*k) {
#define kini(s) TclNewLiteralStringObj(keys[i], s); i++
8133
8134
8135
8136
8137
8138
8139
8140

8141
8142
8143
8144
8145
8146
8147
8427
8428
8429
8430
8431
8432
8433

8434
8435
8436
8437
8438
8439
8440
8441







-
+







	Tcl_DictObjGet(NULL, info, *k, &val);
	args[5] = val ? TclGetString(val) : NULL;
    }
    k++;
    for (i = 0; i < 2; i++) {
	Tcl_DictObjGet(NULL, info, *k++, &val);
	if (val) {
	    TclGetIntFromObj(NULL, val, &argsi[i]);
	    Tcl_GetSizeIntFromObj(NULL, val, &argsi[i]);
	} else {
	    argsi[i] = 0;
	}
    }
}

/*
8158
8159
8160
8161
8162
8163
8164
8165

8166
8167
8168
8169
8170
8171
8172
8452
8453
8454
8455
8456
8457
8458

8459
8460
8461
8462
8463
8464
8465
8466







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
DTraceCmdReturn(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    char *cmdName = TclGetString((Tcl_Obj *) data[0]);

    if (TCL_DTRACE_CMD_RETURN_ENABLED()) {
	TCL_DTRACE_CMD_RETURN(cmdName, result);
8203
8204
8205
8206
8207
8208
8209
8210
8211


8212
8213
8214
8215
8216
8217
8218
8219
8220








































8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
8233
8234
8235

8236
8237
8238
8239
8240
8241
8242
8243
8244
8245
8246
8247















































8248
8249
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260
8261
8262

8263
8264
8265
8266
8267
8268
8269
8270

8271
8272
8273
8274
8275
8276
8277
8278
8279
8280
8281
8282
8283

8284
8285
8286
8287
8288


8289
8290
8291
8292
8293
8294
8295
8497
8498
8499
8500
8501
8502
8503


8504
8505
8506
8507
8508
8509
8510
8511
8512
8513
8514
8515
8516
8517
8518
8519
8520
8521
8522
8523
8524
8525
8526
8527
8528
8529
8530
8531
8532
8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544
8545
8546
8547
8548
8549
8550
8551
8552
8553
8554
8555
8556
8557
8558
8559
8560
8561
8562
8563
8564
8565
8566
8567
8568

8569
8570
8571
8572
8573
8574
8575
8576
8577
8578
8579
8580
8581
8582
8583
8584
8585
8586
8587
8588
8589
8590
8591
8592
8593
8594
8595
8596
8597
8598
8599
8600
8601
8602
8603
8604
8605
8606
8607
8608
8609
8610
8611
8612
8613
8614
8615
8616
8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628
8629
8630
8631
8632
8633
8634
8635
8636
8637
8638
8639
8640
8641
8642

8643
8644
8645
8646
8647
8648
8649
8650

8651
8652
8653
8654
8655
8656
8657
8658
8659
8660
8661
8662
8663

8664
8665
8666
8667


8668
8669
8670
8671
8672
8673
8674
8675
8676







-
-
+
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














-
+












+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














-
+







-
+












-
+



-
-
+
+







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

int
Tcl_NRCallObjProc(
    Tcl_Interp *interp,
    Tcl_ObjCmdProc *objProc,
    ClientData clientData,
    int objc,
    void *clientData,
    Tcl_Size objc,
    Tcl_Obj *const objv[])
{
    NRE_callback *rootPtr = TOP_CB(interp);

    TclNRAddCallback(interp, Dispatch, objProc, clientData,
	    INT2PTR(objc), objv);
    return TclNRRunCallbacks(interp, TCL_OK, rootPtr);
}

static int
wrapperNRObjProc(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    CmdWrapperInfo *info = (CmdWrapperInfo *) clientData;
    clientData = info->clientData;
    Tcl_ObjCmdProc2 *proc = info->proc;
    Tcl_Free(info);
    if (objc < 0) {
	objc = -1;
    }
    return proc(clientData, interp, (Tcl_Size) objc, objv);
}

int
Tcl_NRCallObjProc2(
    Tcl_Interp *interp,
    Tcl_ObjCmdProc2 *objProc,
    void *clientData,
    Tcl_Size objc,
    Tcl_Obj *const objv[])
{
    if (objc > INT_MAX) {
	Tcl_WrongNumArgs(interp, 1, objv, "?args?");
	return TCL_ERROR;
    }

    NRE_callback *rootPtr = TOP_CB(interp);
    CmdWrapperInfo *info = (CmdWrapperInfo *)Tcl_Alloc(sizeof(CmdWrapperInfo));
    info->clientData = clientData;
    info->proc = objProc;

    TclNRAddCallback(interp, Dispatch, wrapperNRObjProc, info,
	    INT2PTR(objc), objv);
    return TclNRRunCallbacks(interp, TCL_OK, rootPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_NRCreateCommand --
 *
 *	Define a new NRE-enabled object-based command in a command table.
 *
 * Results:
 *	The return value is a token for the command, which can be used in
 *	future calls to Tcl_GetCommandName.
 *
 * Side effects:
 *	If no command named "cmdName" already exists for interp, one is
 *	created. Otherwise, if a command does exist, then if the object-based
 *	Tcl_ObjCmdProc is TclInvokeStringCommand, we assume Tcl_CreateCommand
 *	Tcl_ObjCmdProc is InvokeStringCommand, we assume Tcl_CreateCommand
 *	was called previously for the same command and just set its
 *	Tcl_ObjCmdProc to the argument "proc"; otherwise, we delete the old
 *	command.
 *
 *	In the future, during bytecode evaluation when "cmdName" is seen as
 *	the name of a command by Tcl_EvalObj or Tcl_Eval, the object-based
 *	Tcl_ObjCmdProc proc will be called. When the command is deleted from
 *	the table, deleteProc will be called. See the manual entry for details
 *	on the calling sequence.
 *
 *----------------------------------------------------------------------
 */

static int
cmdWrapperNreProc(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    CmdWrapperInfo *info = (CmdWrapperInfo *) clientData;

    if (objc < 0) {
	objc = -1;
    }
    return info->nreProc(info->clientData, interp, objc, objv);
}

Tcl_Command
Tcl_NRCreateCommand2(
    Tcl_Interp *interp,		/* Token for command interpreter (returned by
				 * previous call to Tcl_CreateInterp). */
    const char *cmdName,	/* Name of command. If it contains namespace
				 * qualifiers, the new command is put in the
				 * specified namespace; otherwise it is put in
				 * the global namespace. */
    Tcl_ObjCmdProc2 *proc,	/* Object-based function to associate with
				 * name, provides direct access for direct
				 * calls. */
    Tcl_ObjCmdProc2 *nreProc,	/* Object-based function to associate with
				 * name, provides NR implementation */
    void *clientData,		/* Arbitrary value to pass to object
				 * function. */
    Tcl_CmdDeleteProc *deleteProc)
				/* If not NULL, gives a function to call when
				 * this command is deleted. */
{
    CmdWrapperInfo *info = (CmdWrapperInfo *)Tcl_Alloc(sizeof(CmdWrapperInfo));

    info->proc = proc;
    info->clientData = clientData;
    info->nreProc = nreProc;
    info->deleteProc = deleteProc;
    info->deleteData = clientData;
    return Tcl_NRCreateCommand(interp, cmdName,
	    (proc ? cmdWrapperProc : NULL),
	    (nreProc ? cmdWrapperNreProc : NULL),
	    info, cmdWrapperDeleteProc);
}

Tcl_Command
Tcl_NRCreateCommand(
    Tcl_Interp *interp,		/* Token for command interpreter (returned by
				 * previous call to Tcl_CreateInterp). */
    const char *cmdName,	/* Name of command. If it contains namespace
				 * qualifiers, the new command is put in the
				 * specified namespace; otherwise it is put in
				 * the global namespace. */
    Tcl_ObjCmdProc *proc,	/* Object-based function to associate with
				 * name, provides direct access for direct
				 * calls. */
    Tcl_ObjCmdProc *nreProc,	/* Object-based function to associate with
				 * name, provides NR implementation */
    ClientData clientData,	/* Arbitrary value to pass to object
    void *clientData,		/* Arbitrary value to pass to object
				 * function. */
    Tcl_CmdDeleteProc *deleteProc)
				/* If not NULL, gives a function to call when
				 * this command is deleted. */
{
    Command *cmdPtr = (Command *)
	    Tcl_CreateObjCommand(interp, cmdName, proc, clientData,
                    deleteProc);
		    deleteProc);

    cmdPtr->nreProc = nreProc;
    return (Tcl_Command) cmdPtr;
}

Tcl_Command
TclNRCreateCommandInNs(
    Tcl_Interp *interp,
    const char *cmdName,
    Tcl_Namespace *nsPtr,
    Tcl_ObjCmdProc *proc,
    Tcl_ObjCmdProc *nreProc,
    ClientData clientData,
    void *clientData,
    Tcl_CmdDeleteProc *deleteProc)
{
    Command *cmdPtr = (Command *)
            TclCreateObjCommandInNs(interp, cmdName, nsPtr, proc, clientData,
                    deleteProc);
	    TclCreateObjCommandInNs(interp, cmdName, nsPtr, proc, clientData,
		    deleteProc);

    cmdPtr->nreProc = nreProc;
    return (Tcl_Command) cmdPtr;
}

/****************************************************************************
 * Stuff for the public api
8304
8305
8306
8307
8308
8309
8310
8311

8312
8313
8314
8315
8316
8317
8318
8319
8320
8321
8322
8323
8324
8325
8326

8327
8328
8329
8330
8331
8332
8333
8685
8686
8687
8688
8689
8690
8691

8692
8693
8694
8695
8696
8697
8698
8699
8700
8701
8702
8703
8704
8705
8706

8707
8708
8709
8710
8711
8712
8713
8714







-
+














-
+







    return TclNREvalObjEx(interp, objPtr, flags, NULL, INT_MIN);
}

int
Tcl_NREvalObjv(
    Tcl_Interp *interp,		/* Interpreter in which to evaluate the
				 * command. Also used for error reporting. */
    int objc,			/* Number of words in command. */
    Tcl_Size objc,		/* Number of words in command. */
    Tcl_Obj *const objv[],	/* An array of pointers to objects that are
				 * the words that make up the command. */
    int flags)			/* Collection of OR-ed bits that control the
				 * evaluation of the script. Only
				 * TCL_EVAL_GLOBAL, TCL_EVAL_INVOKE and
				 * TCL_EVAL_NOERR are currently supported. */
{
    return TclNREvalObjv(interp, objc, objv, flags, NULL);
}

int
Tcl_NRCmdSwap(
    Tcl_Interp *interp,
    Tcl_Command cmd,
    int objc,
    Tcl_Size objc,
    Tcl_Obj *const objv[],
    int flags)
{
    return TclNREvalObjv(interp, objc, objv, flags|TCL_EVAL_NOERR,
	    (Command *) cmd);
}

8345
8346
8347
8348
8349
8350
8351
8352

8353
8354
8355
8356



8357
8358
8359


8360
8361
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371


8372
8373
8374
8375
8376
8377
8378
8726
8727
8728
8729
8730
8731
8732

8733
8734



8735
8736
8737
8738


8739
8740
8741
8742
8743
8744
8745
8746
8747
8748
8749
8750


8751
8752
8753
8754
8755
8756
8757
8758
8759







-
+

-
-
-
+
+
+

-
-
+
+










-
-
+
+







 *   3. when the NRCommand callback runs, it schedules the tailcall callback
 *      to run immediately after it returns
 *
 *   One delicate point is to properly define the NRCommand where the tailcall
 *   will execute. There are functions whose purpose is to help define the
 *   precise spot:
 *     TclMarkTailcall: if the NEXT command to be pushed tailcalls, execution
 *         should continue right here
 *	 should continue right here
 *     TclSkipTailcall:  if the NEXT command to be pushed tailcalls, execution
 *         should continue after the CURRENT command is fully returned ("skip
 *         the next command: we are redirecting to it, tailcalls should run
 *         after WE return")
 *	 should continue after the CURRENT command is fully returned ("skip
 *	 the next command: we are redirecting to it, tailcalls should run
 *	 after WE return")
 *     TclPushTailcallPoint: the search for a tailcalling spot cannot traverse
 *         this point. This is special for OO, as some of the oo constructs
 *         that behave like commands may not push an NRCommand callback.
 *	 this point. This is special for OO, as some of the oo constructs
 *	 that behave like commands may not push an NRCommand callback.
 */

void
TclMarkTailcall(
    Tcl_Interp *interp)
{
    Interp *iPtr = (Interp *) interp;

    if (iPtr->deferredCallbacks == NULL) {
	TclNRAddCallback(interp, NRCommand, NULL, NULL,
                NULL, NULL);
        iPtr->deferredCallbacks = TOP_CB(interp);
		NULL, NULL);
	iPtr->deferredCallbacks = TOP_CB(interp);
    }
}

void
TclSkipTailcall(
    Tcl_Interp *interp)
{
8411
8412
8413
8414
8415
8416
8417
8418
8419
8420



8421
8422
8423

8424
8425
8426
8427
8428
8429
8430
8792
8793
8794
8795
8796
8797
8798



8799
8800
8801
8802
8803

8804
8805
8806
8807
8808
8809
8810
8811







-
-
-
+
+
+


-
+







     * being tailcalled. Note that we skip NRCommands marked by a 1 in data[1]
     * (used by command redirectors).
     */

    NRE_callback *runPtr;

    for (runPtr = TOP_CB(interp); runPtr; runPtr = runPtr->nextPtr) {
        if (((runPtr->procPtr) == NRCommand) && !runPtr->data[1]) {
            break;
        }
	if (((runPtr->procPtr) == NRCommand) && !runPtr->data[1]) {
	    break;
	}
    }
    if (!runPtr) {
        Tcl_Panic("tailcall cannot find the right splicing spot: should not happen!");
	Tcl_Panic("tailcall cannot find the right splicing spot: should not happen!");
    }
    runPtr->data[1] = listPtr;
}

/*
 *----------------------------------------------------------------------
 *
8452
8453
8454
8455
8456
8457
8458
8459
8460
8461



8462
8463
8464
8465
8466
8467
8468
8469
8470
8471
8472


8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483


8484
8485
8486
8487
8488




8489
8490
8491
8492


8493
8494

8495
8496
8497
8498
8499
8500
8501
8502
8503
8504
8505
8506
8507
8508
8509
8510
8511

8512
8513
8514
8515
8516
8517
8518

8519
8520
8521

8522
8523
8524
8525
8526
8527
8528
8529
8530
8531
8532




8533
8534
8535

8536
8537
8538
8539
8540
8541
8542
8543
8544
8545

8546
8547
8548
8549
8550

8551
8552
8553
8554
8555
8556
8557
8558
8559
8560
8561
8562
8563
8564
8565
8566
8567
8568
8569
8570
8571
8572
8573
8574




8575
8576
8577
8578
8579
8580
8581
8833
8834
8835
8836
8837
8838
8839



8840
8841
8842
8843
8844
8845
8846
8847
8848
8849
8850
8851


8852
8853
8854
8855
8856
8857
8858
8859
8860
8861
8862


8863
8864
8865




8866
8867
8868
8869
8870



8871
8872
8873

8874
8875
8876
8877
8878
8879
8880
8881
8882
8883
8884
8885
8886
8887
8888
8889
8890

8891
8892
8893
8894
8895
8896
8897

8898
8899
8900

8901
8902
8903
8904
8905
8906
8907
8908




8909
8910
8911
8912
8913
8914

8915
8916
8917
8918
8919
8920
8921
8922
8923
8924

8925
8926
8927
8928
8929

8930
8931
8932
8933
8934
8935
8936
8937
8938
8939
8940
8941
8942
8943
8944
8945
8946
8947
8948
8949
8950




8951
8952
8953
8954
8955
8956
8957
8958
8959
8960
8961







-
-
-
+
+
+









-
-
+
+









-
-
+
+

-
-
-
-
+
+
+
+

-
-
-
+
+

-
+
















-
+






-
+


-
+







-
-
-
-
+
+
+
+


-
+









-
+




-
+




















-
-
-
-
+
+
+
+








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

    if (!(iPtr->varFramePtr->isProcCallFrame & 1)) {
        Tcl_SetObjResult(interp, Tcl_NewStringObj(
                "tailcall can only be called from a proc, lambda or method", -1));
        Tcl_SetErrorCode(interp, "TCL", "TAILCALL", "ILLEGAL", NULL);
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"tailcall can only be called from a proc, lambda or method", TCL_INDEX_NONE));
	Tcl_SetErrorCode(interp, "TCL", "TAILCALL", "ILLEGAL", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Invocation without args just clears a scheduled tailcall; invocation
     * with an argument replaces any previously scheduled tailcall.
     */

    if (iPtr->varFramePtr->tailcallPtr) {
        Tcl_DecrRefCount(iPtr->varFramePtr->tailcallPtr);
        iPtr->varFramePtr->tailcallPtr = NULL;
	Tcl_DecrRefCount(iPtr->varFramePtr->tailcallPtr);
	iPtr->varFramePtr->tailcallPtr = NULL;
    }

    /*
     * Create the callback to actually evaluate the tailcalled
     * command, then set it in the varFrame so that PopCallFrame can use it
     * at the proper time.
     */

    if (objc > 1) {
        Tcl_Obj *listPtr, *nsObjPtr;
        Tcl_Namespace *nsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr;
	Tcl_Obj *listPtr;
	Tcl_Namespace *nsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr;

        /*
         * The tailcall data is in a Tcl list: the first element is the
         * namespace, the rest the command to be tailcalled.
         */
	/*
	 * The tailcall data is in a Tcl list: the first element is the
	 * namespace, the rest the command to be tailcalled.
	 */

        nsObjPtr = Tcl_NewStringObj(nsPtr->fullName, -1);
        listPtr = Tcl_NewListObj(objc, objv);
 	TclListObjSetElement(interp, listPtr, 0, nsObjPtr);
	listPtr = Tcl_NewListObj(objc, objv);
	TclListObjSetElement(NULL, listPtr, 0, TclNewNamespaceObj(nsPtr));

        iPtr->varFramePtr->tailcallPtr = listPtr;
	iPtr->varFramePtr->tailcallPtr = listPtr;
    }
    return TCL_RETURN;
}

/*
 *----------------------------------------------------------------------
 *
 * TclNRTailcallEval --
 *
 *	This NREcallback actually causes the tailcall to be evaluated.
 *
 *----------------------------------------------------------------------
 */

int
TclNRTailcallEval(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *listPtr = (Tcl_Obj *)data[0], *nsObjPtr;
    Tcl_Namespace *nsPtr;
    int objc;
    Tcl_Size objc;
    Tcl_Obj **objv;

    Tcl_ListObjGetElements(interp, listPtr, &objc, &objv);
    TclListObjGetElements(interp, listPtr, &objc, &objv);
    nsObjPtr = objv[0];

    if (result == TCL_OK) {
	result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr);
    }

    if (result != TCL_OK) {
        /*
         * Tailcall execution was preempted, eg by an intervening catch or by
         * a now-gone namespace: cleanup and return.
         */
	/*
	 * Tailcall execution was preempted, eg by an intervening catch or by
	 * a now-gone namespace: cleanup and return.
	 */

	Tcl_DecrRefCount(listPtr);
        return result;
	return result;
    }

    /*
     * Perform the tailcall
     */

    TclMarkTailcall(interp);
    TclNRAddCallback(interp, TclNRReleaseValues, listPtr, NULL, NULL,NULL);
    iPtr->lookupNsPtr = (Namespace *) nsPtr;
    return TclNREvalObjv(interp, objc-1, objv+1, 0, NULL);
    return TclNREvalObjv(interp, objc - 1, objv + 1, 0, NULL);
}

int
TclNRReleaseValues(
    ClientData data[],
    void *data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    int i = 0;

    while (i < 4) {
	if (data[i]) {
	    Tcl_DecrRefCount((Tcl_Obj *) data[i]);
	} else {
	    break;
	}
	i++;
    }
    return result;
}

void
Tcl_NRAddCallback(
    Tcl_Interp *interp,
    Tcl_NRPostProc *postProcPtr,
    ClientData data0,
    ClientData data1,
    ClientData data2,
    ClientData data3)
    void *data0,
    void *data1,
    void *data2,
    void *data3)
{
    if (!(postProcPtr)) {
	Tcl_Panic("Adding a callback without an objProc?!");
    }
    TclNRAddCallback(interp, postProcPtr, data0, data1, data2, data3);
}

8601
8602
8603
8604
8605
8606
8607
8608

8609
8610
8611
8612
8613
8614
8615
8616
8617
8618
8619
8620
8621
8622
8623


8624
8625
8626
8627
8628
8629
8630
8631
8632
8633

8634
8635
8636
8637
8638
8639
8640
8641
8642
8643
8644
8645
8646

8647
8648
8649
8650
8651
8652
8653
8654
8655
8656


8657
8658
8659
8660
8661
8662
8663
8664
8665





8666
8667
8668
8669
8670
8671
8672
8673
8674
8675
8676

8677
8678
8679
8680
8681
8682

8683

8684
8685
8686

8687
8688
8689
8690
8691

8692
8693
8694
8695
8696
8697
8698
8981
8982
8983
8984
8985
8986
8987

8988
8989
8990
8991
8992
8993
8994
8995
8996
8997
8998
8999
9000
9001


9002
9003
9004
9005
9006
9007
9008
9009
9010
9011
9012

9013
9014
9015
9016
9017
9018
9019
9020
9021
9022
9023
9024

9025
9026
9027
9028
9029
9030
9031
9032
9033
9034


9035
9036
9037
9038
9039
9040





9041
9042
9043
9044
9045
9046
9047
9048
9049
9050
9051
9052
9053
9054


9055
9056
9057
9058
9059
9060
9061
9062
9063
9064
9065
9066

9067
9068
9069
9070
9071

9072
9073
9074
9075
9076
9077
9078
9079







-
+













-
-
+
+









-
+











-

+








-
-
+
+




-
-
-
-
-
+
+
+
+
+









-
-
+






+

+


-
+




-
+







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

#define iPtr ((Interp *) interp)

int
TclNRYieldObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    CoroutineData *corPtr = iPtr->execEnvPtr->corPtr;

    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?returnValue?");
	return TCL_ERROR;
    }

    if (!corPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
                "yield can only be called in a coroutine", -1));
	Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ILLEGAL_YIELD", NULL);
		"yield can only be called in a coroutine", TCL_INDEX_NONE));
	Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ILLEGAL_YIELD", (char *)NULL);
	return TCL_ERROR;
    }

    if (objc == 2) {
	Tcl_SetObjResult(interp, objv[1]);
    }

    NRE_ASSERT(!COR_IS_SUSPENDED(corPtr));
    TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr,
            clientData, NULL, NULL);
	    clientData, NULL, NULL);
    return TCL_OK;
}

int
TclNRYieldToObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    CoroutineData *corPtr = iPtr->execEnvPtr->corPtr;
    Tcl_Obj *listPtr, *nsObjPtr;
    Tcl_Namespace *nsPtr = TclGetCurrentNamespace(interp);
    Tcl_Obj *listPtr;

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

    if (!corPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
                "yieldto can only be called in a coroutine", -1));
	Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ILLEGAL_YIELD", NULL);
		"yieldto can only be called in a coroutine", TCL_INDEX_NONE));
	Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ILLEGAL_YIELD", (char *)NULL);
	return TCL_ERROR;
    }

    if (((Namespace *) nsPtr)->flags & NS_DYING) {
        Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"yieldto called in deleted namespace", -1));
        Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "YIELDTO_IN_DELETED",
		NULL);
        return TCL_ERROR;
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"yieldto called in deleted namespace", TCL_INDEX_NONE));
	Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "YIELDTO_IN_DELETED",
		(char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Add the tailcall in the caller env, then just yield.
     *
     * This is essentially code from TclNRTailcallObjCmd
     */

    listPtr = Tcl_NewListObj(objc, objv);
    nsObjPtr = Tcl_NewStringObj(nsPtr->fullName, -1);
    TclListObjSetElement(interp, listPtr, 0, nsObjPtr);
    TclListObjSetElement(NULL, listPtr, 0, TclNewNamespaceObj(nsPtr));

    /*
     * Add the callback in the caller's env, then instruct TEBC to yield.
     */

    iPtr->execEnvPtr = corPtr->callerEEPtr;
    /* Not calling Tcl_IncrRefCount(listPtr) here because listPtr is private */
    TclSetTailcall(interp, listPtr);
    corPtr->yieldPtr = listPtr;
    iPtr->execEnvPtr = corPtr->eePtr;

    return TclNRYieldObjCmd(INT2PTR(CORO_ACTIVATE_YIELDM), interp, 1, objv);
    return TclNRYieldObjCmd(CORO_ACTIVATE_YIELDM, interp, 1, objv);
}

static int
RewindCoroutineCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int) /*result*/)
{
    return Tcl_RestoreInterpState(interp, (Tcl_InterpState)data[0]);
}

static int
8711
8712
8713
8714
8715
8716
8717
8718

8719
8720
8721
8722
8723
8724
8725
8726
8727
8728
8729
8730
8731

8732
8733
8734
8735
8736
8737
8738
9092
9093
9094
9095
9096
9097
9098

9099
9100
9101
9102
9103
9104
9105
9106
9107
9108
9109
9110
9111

9112
9113
9114
9115
9116
9117
9118
9119







-
+












-
+







    TclNRAddCallback(interp, RewindCoroutineCallback, state,
	    NULL, NULL, NULL);
    return TclNRInterpCoroutine(corPtr, interp, 0, NULL);
}

static void
DeleteCoroutine(
    ClientData clientData)
    void *clientData)
{
    CoroutineData *corPtr = (CoroutineData *)clientData;
    Tcl_Interp *interp = corPtr->eePtr->interp;
    NRE_callback *rootPtr = TOP_CB(interp);

    if (COR_IS_SUSPENDED(corPtr)) {
	TclNRRunCallbacks(interp, RewindCoroutine(corPtr,TCL_OK), rootPtr);
    }
}

static int
NRCoroutineCallerCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    CoroutineData *corPtr = (CoroutineData *)data[0];
    Command *cmdPtr = corPtr->cmdPtr;

    /*
8770
8771
8772
8773
8774
8775
8776
8777

8778
8779
8780
8781
8782
8783
8784
9151
9152
9153
9154
9155
9156
9157

9158
9159
9160
9161
9162
9163
9164
9165







-
+







    }

    return result;
}

static int
NRCoroutineExitCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    CoroutineData *corPtr = (CoroutineData *)data[0];
    Command *cmdPtr = corPtr->cmdPtr;

    /*
8821
8822
8823
8824
8825
8826
8827
8828
8829


8830
8831
8832
8833
8834
8835





8836
8837
8838
8839
8840
8841
8842

8843
8844
8845
8846
8847
8848
8849

8850
8851
8852
8853
8854
8855
8856





8857
8858
8859


8860
8861
8862
8863
8864




8865
8866
8867
8868



8869
8870
8871
8872
8873
8874





8875
8876
8877
8878



8879
8880
8881
8882
8883
8884
8885
8886






















8887

8888
8889
8890
8891
8892
8893
8894







8895

8896

8897
8898
8899
8900



8901
8902

8903
8904
8905
8906
8907
8908
8909
8910
8911
8912
8913
8914
8915
8916
8917
8918
8919
8920
8921
8922
8923
8924
8925
8926
8927
8928
8929
8930
8931
8932
8933
8934
8935
8936
8937
8938
8939
8940
8941
8942

8943
8944
8945
8946
8947
8948
8949
9202
9203
9204
9205
9206
9207
9208


9209
9210
9211





9212
9213
9214
9215
9216
9217
9218
9219
9220
9221
9222

9223
9224
9225
9226
9227



9228
9229
9230





9231
9232
9233
9234
9235
9236


9237
9238
9239




9240
9241
9242
9243
9244



9245
9246
9247
9248





9249
9250
9251
9252
9253
9254



9255
9256
9257
9258







9259
9260
9261
9262
9263
9264
9265
9266
9267
9268
9269
9270
9271
9272
9273
9274
9275
9276
9277
9278
9279
9280
9281
9282







9283
9284
9285
9286
9287
9288
9289
9290
9291

9292
9293



9294
9295
9296
9297

9298
9299
9300
9301
9302
9303
9304
9305
9306





























9307
9308

9309
9310
9311
9312
9313
9314
9315
9316







-
-
+
+

-
-
-
-
-
+
+
+
+
+






-
+




-
-
-
+


-
-
-
-
-
+
+
+
+
+

-
-
+
+

-
-
-
-
+
+
+
+

-
-
-
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
-
-
-
-
-
-
-
+
+
+
+
+
+
+

+
-
+

-
-
-
+
+
+

-
+








-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


-
+







}

/*
 *----------------------------------------------------------------------
 *
 * TclNRCoroutineActivateCallback --
 *
 *      This is the workhorse for coroutines: it implements both yield and
 *      resume.
 *	This is the workhorse for coroutines: it implements both yield and
 *	resume.
 *
 *      It is important that both be implemented in the same callback: the
 *      detection of the impossibility to suspend due to a busy C-stack relies
 *      on the precise position of a local variable in the stack. We do not
 *      want the compiler to play tricks on us, either by moving things around
 *      or inlining.
 *	It is important that both be implemented in the same callback: the
 *	detection of the impossibility to suspend due to a busy C-stack relies
 *	on the precise position of a local variable in the stack. We do not
 *	want the compiler to play tricks on us, either by moving things around
 *	or inlining.
 *
 *----------------------------------------------------------------------
 */

int
TclNRCoroutineActivateCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int) /*result*/)
{
    CoroutineData *corPtr = (CoroutineData *)data[0];
    int type = PTR2INT(data[1]);
    int numLevels, unused;
    int *stackLevel = &unused;
    void *stackLevel = TclGetCStackPtr();

    if (!corPtr->stackLevel) {
        /*
         * -- Coroutine is suspended --
         * Push the callback to restore the caller's context on yield or
         * return.
         */
	/*
	 * -- Coroutine is suspended --
	 * Push the callback to restore the caller's context on yield or
	 * return.
	 */

        TclNRAddCallback(interp, NRCoroutineCallerCallback, corPtr,
                NULL, NULL, NULL);
	TclNRAddCallback(interp, NRCoroutineCallerCallback, corPtr,
		NULL, NULL, NULL);

        /*
         * Record the stackLevel at which the resume is happening, then swap
         * the interp's environment to make it suitable to run this coroutine.
         */
	/*
	 * Record the stackLevel at which the resume is happening, then swap
	 * the interp's environment to make it suitable to run this coroutine.
	 */

        corPtr->stackLevel = stackLevel;
        numLevels = corPtr->auxNumLevels;
        corPtr->auxNumLevels = iPtr->numLevels;
	corPtr->stackLevel = stackLevel;
	Tcl_Size numLevels = corPtr->auxNumLevels;
	corPtr->auxNumLevels = iPtr->numLevels;

        SAVE_CONTEXT(corPtr->caller);
        corPtr->callerEEPtr = iPtr->execEnvPtr;
        RESTORE_CONTEXT(corPtr->running);
        iPtr->execEnvPtr = corPtr->eePtr;
        iPtr->numLevels += numLevels;
	SAVE_CONTEXT(corPtr->caller);
	corPtr->callerEEPtr = iPtr->execEnvPtr;
	RESTORE_CONTEXT(corPtr->running);
	iPtr->execEnvPtr = corPtr->eePtr;
	iPtr->numLevels += numLevels;
    } else {
        /*
         * Coroutine is active: yield
         */
	/*
	 * Coroutine is active: yield
	 */

        if (corPtr->stackLevel != stackLevel) {
            Tcl_SetObjResult(interp, Tcl_NewStringObj(
                    "cannot yield: C stack busy", -1));
            Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "CANT_YIELD",
                    NULL);
            return TCL_ERROR;
        }
	if (corPtr->stackLevel != stackLevel) {
	    NRE_callback *runPtr;

	    iPtr->execEnvPtr = corPtr->callerEEPtr;
	    if (corPtr->yieldPtr) {
		for (runPtr = TOP_CB(interp); runPtr; runPtr = runPtr->nextPtr) {
		    if (runPtr->data[1] == corPtr->yieldPtr) {
			Tcl_DecrRefCount((Tcl_Obj *)runPtr->data[1]);
			runPtr->data[1] = NULL;
			corPtr->yieldPtr = NULL;
			break;
		    }
		}
	    }
	    iPtr->execEnvPtr = corPtr->eePtr;

	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "cannot yield: C stack busy", TCL_INDEX_NONE));
	    Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "CANT_YIELD",
		    (char *)NULL);
	    return TCL_ERROR;
	}

	void *type = data[1];
        if (type == CORO_ACTIVATE_YIELD) {
            corPtr->nargs = COROUTINE_ARGUMENTS_SINGLE_OPTIONAL;
        } else if (type == CORO_ACTIVATE_YIELDM) {
            corPtr->nargs = COROUTINE_ARGUMENTS_ARBITRARY;
        } else {
            Tcl_Panic("Yield received an option which is not implemented");
        }
	if (type == CORO_ACTIVATE_YIELD) {
	    corPtr->nargs = COROUTINE_ARGUMENTS_SINGLE_OPTIONAL;
	} else if (type == CORO_ACTIVATE_YIELDM) {
	    corPtr->nargs = COROUTINE_ARGUMENTS_ARBITRARY;
	} else {
	    Tcl_Panic("Yield received an option which is not implemented");
	}

	corPtr->yieldPtr = NULL;
        corPtr->stackLevel = NULL;
	corPtr->stackLevel = NULL;

        numLevels = iPtr->numLevels;
        iPtr->numLevels = corPtr->auxNumLevels;
        corPtr->auxNumLevels = numLevels - corPtr->auxNumLevels;
	Tcl_Size numLevels = iPtr->numLevels;
	iPtr->numLevels = corPtr->auxNumLevels;
	corPtr->auxNumLevels = numLevels - corPtr->auxNumLevels;

        iPtr->execEnvPtr = corPtr->callerEEPtr;
	iPtr->execEnvPtr = corPtr->callerEEPtr;
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclNREvalList --
 *
 *      Callback to invoke command as list, used in order to delayed
 *	processing of canonical list command in sane environment.
 *
 *----------------------------------------------------------------------
 */

static int
TclNREvalList(
    ClientData data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int) /*result*/)
{
    int objc;
    Tcl_Obj **objv;
    Tcl_Obj *listPtr = (Tcl_Obj *)data[0];

    Tcl_IncrRefCount(listPtr);

    TclMarkTailcall(interp);
    TclNRAddCallback(interp, TclNRReleaseValues, listPtr, NULL, NULL,NULL);
    TclListObjGetElements(NULL, listPtr, &objc, &objv);
    return TclNREvalObjv(interp, objc, objv, 0, NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * CoroTypeObjCmd --
 *
 *      Implementation of [::tcl::unsupported::corotype] command.
 *	Implementation of [::tcl::unsupported::corotype] command.
 *
 *----------------------------------------------------------------------
 */

static int
CoroTypeObjCmd(
    TCL_UNUSED(void *),
8961
8962
8963
8964
8965
8966
8967
8968
8969
8970
8971
8972





8973
8974
8975
8976
8977
8978
8979
8980
8981
8982
8983


8984
8985
8986
8987
8988
8989
8990
8991
8992
8993
8994


8995
8996
8997


8998
8999
9000
9001
9002




9003
9004
9005
9006
9007
9008
9009
9010
9011

9012
9013
9014
9015
9016
9017
9018
9019
9020
9021
9022
9023
9024
9025
9026
9027
9028
9029
9030
9031
9032




9033
9034
9035
9036
9037
9038
9039
9040
9041
9042
9043
9044
9045
9046
9047
9048
9049
9050
9051
9052
9053
9054
9055
9056
9057
9058

9059
9060

9061
9062
9063
9064
9065
9066




9067
9068
9069
9070
9071
9072
9073

9074
9075
9076

9077
9078
9079
9080
9081
9082
9083
9084
9085
9086
9087
9088
9089
9090
9091
9092
9093
9094
9095
9096
9097
9098
9099
9100
9101
9102
9103
9104
9105

9106
9107

9108
9109
9110
9111
9112
9113
9114





9115
9116
9117
9118
9119
9120
9121

9122
9123
9124

9125
9126
9127
9128
9129
9130
9131
9132
9133
9134
9135

9136
9137
9138
9139
9140
9141
9142
9143


9144
9145
9146
9147
9148
9149
9150
9151
9152
9153
9154
9155
9156
9157
9158
9159
9160
9161
9162
9163
9164


9165
9166
9167
9168
9169
9170





9171
9172
9173
9174



9175
9176
9177
9178
9179
9180
9181

9182
9183
9184
9185
9186
9187
9188
9189



9190
9191
9192
9193
9194
9195



9196
9197
9198
9199
9200
9201
9202
9203
9204
9205
9206
9207
9208
9209
9210















9211
9212
9213
9214
9215
9216
9217
9218
9219
9220

9221
9222
9223
9224
9225
9226
9227

9228
9229
9230
9231
9232
9233
9234


9235
9236
9237
9238
9239
9240
9241
9242
9243
9244
9245
9246
9247
9248
9249
9250
9251
9252
9253
9254
9255
9256
9257
9258
9259
9260










9261
9262
9263
9264
9265
9266
9267
9268
9269
9270
9271
9272
9273
9274
9275
9276
9277
9278
9279
9280
9281
9282
9283
9284
9285
9286
9287
9288
9289
9290
9291
9292
9293
9294
9295
9296
9297
9298
9299
9300
9301
9302
9303
9304
9305
9306
9307
9308
9309
9310
9311
9312
9313
9314
9315
9316
9317
9318
9319
9320
9321
9322

9323
9324
9325
9326
9327
9328
9329
9330
9331
9332
9333



9334
9335
9336
9337
9338
9339
9340
9341
9342
9343
9344
9345
9346
9347
9348
9349
9350
9351







9352
9353
9354
9355
9356
9357
9358
9359
9360








9361
9362
9363
9364
9365




9366
9367
9368
9369

9370
9371
9372
9373
9374
9375
9376
9377
9378
9379


9380
9381
9382
9383
9384
9385
9386
9328
9329
9330
9331
9332
9333
9334





9335
9336
9337
9338
9339
9340
9341
9342
9343
9344
9345
9346
9347
9348


9349
9350
9351
9352
9353
9354
9355
9356
9357
9358
9359


9360
9361
9362


9363
9364
9365




9366
9367
9368
9369
9370
9371
9372
9373
9374
9375
9376
9377

9378
9379
9380
9381
9382
9383
9384
9385
9386
9387
9388
9389
9390
9391
9392
9393
9394
9395




9396
9397
9398
9399
9400
9401
9402
9403
9404
9405
9406
9407
9408
9409
9410
9411

9412
9413
9414
9415
9416
9417
9418
9419
9420
9421
9422
9423

9424
9425

9426
9427
9428




9429
9430
9431
9432
9433
9434
9435
9436
9437
9438
9439
9440
9441
9442

9443
9444
9445
9446
9447
9448
9449
9450
9451
9452
9453
9454
9455
9456



9457
9458
9459
9460
9461
9462
9463
9464
9465
9466
9467
9468

9469
9470

9471
9472
9473





9474
9475
9476
9477
9478
9479
9480
9481
9482
9483
9484
9485
9486
9487
9488

9489
9490
9491
9492
9493
9494
9495
9496
9497
9498
9499

9500
9501
9502
9503
9504
9505
9506


9507
9508
9509
9510
9511
9512
9513
9514
9515
9516
9517
9518
9519
9520
9521
9522
9523
9524
9525
9526
9527


9528
9529
9530





9531
9532
9533
9534
9535
9536



9537
9538
9539
9540
9541
9542
9543
9544
9545

9546
9547
9548
9549
9550
9551



9552
9553
9554
9555
9556
9557



9558
9559
9560
9561














9562
9563
9564
9565
9566
9567
9568
9569
9570
9571
9572
9573
9574
9575
9576
9577
9578
9579
9580
9581
9582
9583
9584
9585

9586
9587
9588
9589
9590
9591
9592

9593
9594
9595
9596
9597
9598


9599
9600

9601
9602
9603
9604
9605
9606
9607
9608
9609
9610
9611
9612
9613
9614
9615










9616
9617
9618
9619
9620
9621
9622
9623
9624
9625
9626
9627
9628
9629























































9630
9631

9632
9633
9634
9635
9636
9637
9638
9639
9640



9641
9642
9643
9644
9645
9646
9647
9648
9649
9650
9651
9652
9653
9654







9655
9656
9657
9658
9659
9660
9661
9662








9663
9664
9665
9666
9667
9668
9669
9670
9671




9672
9673
9674
9675
9676
9677
9678

9679
9680
9681
9682
9683
9684
9685
9686
9687


9688
9689
9690
9691
9692
9693
9694
9695
9696







-
-
-
-
-
+
+
+
+
+









-
-
+
+









-
-
+
+

-
-
+
+

-
-
-
-
+
+
+
+








-
+

















-
-
-
-
+
+
+
+












-












-
+

-
+


-
-
-
-
+
+
+
+







+


-
+













-
-
-












-
+

-
+


-
-
-
-
-
+
+
+
+
+







+


-
+










-
+






-
-
+
+



















-
-
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
+
+
+






-
+





-
-
-
+
+
+



-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+






-
+





-
-
+
+
-















-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


-
+








-
-
-
+
+
+











-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+



-
+








-
-
+
+








    /*
     * Look up the coroutine.
     */

    cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[1]);
    if ((!cmdPtr) || (cmdPtr->nreProc != TclNRInterpCoroutine)) {
        Tcl_SetObjResult(interp, Tcl_NewStringObj(
                "can only get coroutine type of a coroutine", -1));
        Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COROUTINE",
                TclGetString(objv[1]), NULL);
        return TCL_ERROR;
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"can only get coroutine type of a coroutine", TCL_INDEX_NONE));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COROUTINE",
		TclGetString(objv[1]), (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * An active coroutine is "active". Can't tell what it might do in the
     * future.
     */

    corPtr = (CoroutineData *)cmdPtr->objClientData;
    if (!COR_IS_SUSPENDED(corPtr)) {
        Tcl_SetObjResult(interp, Tcl_NewStringObj("active", -1));
        return TCL_OK;
	Tcl_SetObjResult(interp, Tcl_NewStringObj("active", TCL_INDEX_NONE));
	return TCL_OK;
    }

    /*
     * Inactive coroutines are classified by the (effective) command used to
     * suspend them, which matters when you're injecting a probe.
     */

    switch (corPtr->nargs) {
    case COROUTINE_ARGUMENTS_SINGLE_OPTIONAL:
        Tcl_SetObjResult(interp, Tcl_NewStringObj("yield", -1));
        return TCL_OK;
	Tcl_SetObjResult(interp, Tcl_NewStringObj("yield", TCL_INDEX_NONE));
	return TCL_OK;
    case COROUTINE_ARGUMENTS_ARBITRARY:
        Tcl_SetObjResult(interp, Tcl_NewStringObj("yieldto", -1));
        return TCL_OK;
	Tcl_SetObjResult(interp, Tcl_NewStringObj("yieldto", TCL_INDEX_NONE));
	return TCL_OK;
    default:
        Tcl_SetObjResult(interp, Tcl_NewStringObj(
                "unknown coroutine type", -1));
        Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "BAD_TYPE", NULL);
        return TCL_ERROR;
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"unknown coroutine type", TCL_INDEX_NONE));
	Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "BAD_TYPE", (char *)NULL);
	return TCL_ERROR;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclNRCoroInjectObjCmd, TclNRCoroProbeObjCmd --
 *
 *      Implementation of [coroinject] and [coroprobe] commands.
 *	Implementation of [coroinject] and [coroprobe] commands.
 *
 *----------------------------------------------------------------------
 */

static inline CoroutineData *
GetCoroutineFromObj(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    const char *errMsg)
{
    /*
     * How to get a coroutine from its handle.
     */

    Command *cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objPtr);

    if ((!cmdPtr) || (cmdPtr->nreProc != TclNRInterpCoroutine)) {
        Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, -1));
        Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COROUTINE",
                TclGetString(objPtr), NULL);
        return NULL;
	Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, TCL_INDEX_NONE));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COROUTINE",
		TclGetString(objPtr), (char *)NULL);
	return NULL;
    }
    return (CoroutineData *)cmdPtr->objClientData;
}

static int
TclNRCoroInjectObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    CoroutineData *corPtr;
    ExecEnv *savedEEPtr = iPtr->execEnvPtr;

    /*
     * Usage more or less like tailcall:
     *   coroinject coroName cmd ?arg1 arg2 ...?
     */

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "coroName cmd ?arg1 arg2 ...?");
	return TCL_ERROR;
    }

    corPtr = GetCoroutineFromObj(interp, objv[1],
            "can only inject a command into a coroutine");
	    "can only inject a command into a coroutine");
    if (!corPtr) {
        return TCL_ERROR;
	return TCL_ERROR;
    }
    if (!COR_IS_SUSPENDED(corPtr)) {
        Tcl_SetObjResult(interp, Tcl_NewStringObj(
                "can only inject a command into a suspended coroutine", -1));
        Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ACTIVE", NULL);
        return TCL_ERROR;
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"can only inject a command into a suspended coroutine", TCL_INDEX_NONE));
	Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ACTIVE", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Add the callback to the coro's execEnv, so that it is the first thing
     * to happen when the coro is resumed.
     */

    ExecEnv *savedEEPtr = iPtr->execEnvPtr;
    iPtr->execEnvPtr = corPtr->eePtr;
    TclNRAddCallback(interp, InjectHandler, corPtr,
            Tcl_NewListObj(objc - 2, objv + 2), INT2PTR(corPtr->nargs), NULL);
	    Tcl_NewListObj(objc - 2, objv + 2), INT2PTR(corPtr->nargs), NULL);
    iPtr->execEnvPtr = savedEEPtr;

    return TCL_OK;
}

static int
TclNRCoroProbeObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    CoroutineData *corPtr;
    ExecEnv *savedEEPtr = iPtr->execEnvPtr;
    int numLevels, unused;
    int *stackLevel = &unused;

    /*
     * Usage more or less like tailcall:
     *   coroprobe coroName cmd ?arg1 arg2 ...?
     */

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "coroName cmd ?arg1 arg2 ...?");
	return TCL_ERROR;
    }

    corPtr = GetCoroutineFromObj(interp, objv[1],
            "can only inject a probe command into a coroutine");
	    "can only inject a probe command into a coroutine");
    if (!corPtr) {
        return TCL_ERROR;
	return TCL_ERROR;
    }
    if (!COR_IS_SUSPENDED(corPtr)) {
        Tcl_SetObjResult(interp, Tcl_NewStringObj(
                "can only inject a probe command into a suspended coroutine",
                -1));
        Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ACTIVE", NULL);
        return TCL_ERROR;
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"can only inject a probe command into a suspended coroutine",
		TCL_INDEX_NONE));
	Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ACTIVE", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Add the callback to the coro's execEnv, so that it is the first thing
     * to happen when the coro is resumed.
     */

    ExecEnv *savedEEPtr = iPtr->execEnvPtr;
    iPtr->execEnvPtr = corPtr->eePtr;
    TclNRAddCallback(interp, InjectHandler, corPtr,
            Tcl_NewListObj(objc - 2, objv + 2), INT2PTR(corPtr->nargs), corPtr);
	    Tcl_NewListObj(objc - 2, objv + 2), INT2PTR(corPtr->nargs), corPtr);
    iPtr->execEnvPtr = savedEEPtr;

    /*
     * Now we immediately transfer control to the coroutine to run our probe.
     * TRICKY STUFF copied from the [yield] implementation.
     *
     * Push the callback to restore the caller's context on yield back.
     */

    TclNRAddCallback(interp, NRCoroutineCallerCallback, corPtr,
            NULL, NULL, NULL);
	    NULL, NULL, NULL);

    /*
     * Record the stackLevel at which the resume is happening, then swap
     * the interp's environment to make it suitable to run this coroutine.
     */

    corPtr->stackLevel = stackLevel;
    numLevels = corPtr->auxNumLevels;
    corPtr->stackLevel = &corPtr;
    Tcl_Size numLevels = corPtr->auxNumLevels;
    corPtr->auxNumLevels = iPtr->numLevels;

    /*
     * Do the actual stack swap.
     */

    SAVE_CONTEXT(corPtr->caller);
    corPtr->callerEEPtr = iPtr->execEnvPtr;
    RESTORE_CONTEXT(corPtr->running);
    iPtr->execEnvPtr = corPtr->eePtr;
    iPtr->numLevels += numLevels;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * InjectHandler, InjectHandlerPostProc --
 *
 *      Part of the implementation of [coroinject] and [coroprobe]. These are
 *      run inside the context of the coroutine being injected/probed into.
 *	Part of the implementation of [coroinject] and [coroprobe]. These are
 *	run inside the context of the coroutine being injected/probed into.
 *
 *      InjectHandler runs a script (possibly adding arguments) in the context
 *      of the coroutine. The script is specified as a one-shot list (with
 *      reference count equal to 1) in data[1]. This function also arranges
 *      for InjectHandlerPostProc to be the part that runs after the script
 *      completes.
 *	InjectHandler runs a script (possibly adding arguments) in the context
 *	of the coroutine. The script is specified as a one-shot list (with
 *	reference count equal to 1) in data[1]. This function also arranges
 *	for InjectHandlerPostProc to be the part that runs after the script
 *	completes.
 *
 *      InjectHandlerPostProc cleans up after InjectHandler (deleting the
 *      list) and, for the [coroprobe] command *only*, yields back to the
 *      caller context (i.e., where [coroprobe] was run).
 *	InjectHandlerPostProc cleans up after InjectHandler (deleting the
 *	list) and, for the [coroprobe] command *only*, yields back to the
 *	caller context (i.e., where [coroprobe] was run).
 *s
 *----------------------------------------------------------------------
 */

static int
InjectHandler(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int) /*result*/)
{
    CoroutineData *corPtr = (CoroutineData *)data[0];
    Tcl_Obj *listPtr = (Tcl_Obj *)data[1];
    int nargs = PTR2INT(data[2]);
    ClientData isProbe = data[3];
    int objc;
    Tcl_Size nargs = PTR2INT(data[2]);
    void *isProbe = data[3];
    Tcl_Size objc;
    Tcl_Obj **objv;

    if (!isProbe) {
        /*
         * If this is [coroinject], add the extra arguments now.
         */
	/*
	 * If this is [coroinject], add the extra arguments now.
	 */

        if (nargs == COROUTINE_ARGUMENTS_SINGLE_OPTIONAL) {
            Tcl_ListObjAppendElement(NULL, listPtr,
                    Tcl_NewStringObj("yield", -1));
        } else if (nargs == COROUTINE_ARGUMENTS_ARBITRARY) {
            Tcl_ListObjAppendElement(NULL, listPtr,
                    Tcl_NewStringObj("yieldto", -1));
        } else {
            /*
             * I don't think this is reachable...
             */

            Tcl_ListObjAppendElement(NULL, listPtr, Tcl_NewIntObj(nargs));
        }
        Tcl_ListObjAppendElement(NULL, listPtr, Tcl_GetObjResult(interp));
	if (nargs == COROUTINE_ARGUMENTS_SINGLE_OPTIONAL) {
	    Tcl_ListObjAppendElement(NULL, listPtr,
		    Tcl_NewStringObj("yield", TCL_INDEX_NONE));
	} else if (nargs == COROUTINE_ARGUMENTS_ARBITRARY) {
	    Tcl_ListObjAppendElement(NULL, listPtr,
		    Tcl_NewStringObj("yieldto", TCL_INDEX_NONE));
	} else {
	    /*
	     * I don't think this is reachable...
	     */
	    Tcl_Obj *nargsObj;
	    TclNewIndexObj(nargsObj, nargs);
	    Tcl_ListObjAppendElement(NULL, listPtr, nargsObj);
	}
	Tcl_ListObjAppendElement(NULL, listPtr, Tcl_GetObjResult(interp));
    }

    /*
     * Call the user's script; we're in the right place.
     */

    Tcl_IncrRefCount(listPtr);
    TclMarkTailcall(interp);
    TclNRAddCallback(interp, InjectHandlerPostCall, corPtr, listPtr,
            INT2PTR(nargs), isProbe);
	    INT2PTR(nargs), isProbe);
    TclListObjGetElements(NULL, listPtr, &objc, &objv);
    return TclNREvalObjv(interp, objc, objv, 0, NULL);
}

static int
InjectHandlerPostCall(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    CoroutineData *corPtr = (CoroutineData *)data[0];
    Tcl_Obj *listPtr = (Tcl_Obj *)data[1];
    int nargs = PTR2INT(data[2]);
    ClientData isProbe = data[3];
    Tcl_Size nargs = PTR2INT(data[2]);
    void *isProbe = data[3];
    int numLevels;

    /*
     * Delete the command words for what we just executed.
     */

    Tcl_DecrRefCount(listPtr);

    /*
     * If we were doing a probe, splice ourselves back out of the stack
     * cleanly here. General injection should instead just look after itself.
     *
     * Code from guts of [yield] implementation.
     */

    if (isProbe) {
        if (result == TCL_ERROR) {
            Tcl_AddErrorInfo(interp,
                    "\n    (injected coroutine probe command)");
        }
        corPtr->nargs = nargs;
        corPtr->stackLevel = NULL;
        numLevels = iPtr->numLevels;
        iPtr->numLevels = corPtr->auxNumLevels;
        corPtr->auxNumLevels = numLevels - corPtr->auxNumLevels;
        iPtr->execEnvPtr = corPtr->callerEEPtr;
	if (result == TCL_ERROR) {
	    Tcl_AddErrorInfo(interp,
		    "\n    (injected coroutine probe command)");
	}
	corPtr->nargs = nargs;
	corPtr->stackLevel = NULL;
	Tcl_Size numLevels = iPtr->numLevels;
	iPtr->numLevels = corPtr->auxNumLevels;
	corPtr->auxNumLevels = numLevels - corPtr->auxNumLevels;
	iPtr->execEnvPtr = corPtr->callerEEPtr;
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * NRInjectObjCmd --
 *
 *      Implementation of [::tcl::unsupported::inject] command.
 *
 *----------------------------------------------------------------------
 */

static int
NRInjectObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    CoroutineData *corPtr;
    ExecEnv *savedEEPtr = iPtr->execEnvPtr;

    /*
     * Usage more or less like tailcall:
     *   inject coroName cmd ?arg1 arg2 ...?
     */

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "coroName cmd ?arg1 arg2 ...?");
	return TCL_ERROR;
    }

    corPtr = GetCoroutineFromObj(interp, objv[1],
            "can only inject a command into a coroutine");
    if (!corPtr) {
        return TCL_ERROR;
    }
    if (!COR_IS_SUSPENDED(corPtr)) {
        Tcl_SetObjResult(interp, Tcl_NewStringObj(
                "can only inject a command into a suspended coroutine", -1));
        Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ACTIVE", NULL);
        return TCL_ERROR;
    }

    /*
     * Add the callback to the coro's execEnv, so that it is the first thing
     * to happen when the coro is resumed.
     */

    iPtr->execEnvPtr = corPtr->eePtr;
    TclNRAddCallback(interp, TclNREvalList, Tcl_NewListObj(objc-2, objv+2),
	NULL, NULL, NULL);
    iPtr->execEnvPtr = savedEEPtr;

    return TCL_OK;
}

int
TclNRInterpCoroutine(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    CoroutineData *corPtr = (CoroutineData *)clientData;

    if (!COR_IS_SUSPENDED(corPtr)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "coroutine \"%s\" is already running",
                TclGetString(objv[0])));
	Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "BUSY", NULL);
		"coroutine \"%s\" is already running",
		TclGetString(objv[0])));
	Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "BUSY", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Parse all the arguments to work out what to feed as the result of the
     * [yield]. TRICKY POINT: objc==0 happens here! It occurs when a coroutine
     * is deleted!
     */

    switch (corPtr->nargs) {
    case COROUTINE_ARGUMENTS_SINGLE_OPTIONAL:
        if (objc == 2) {
            Tcl_SetObjResult(interp, objv[1]);
        } else if (objc > 2) {
            Tcl_WrongNumArgs(interp, 1, objv, "?arg?");
            return TCL_ERROR;
        }
        break;
	if (objc == 2) {
	    Tcl_SetObjResult(interp, objv[1]);
	} else if (objc > 2) {
	    Tcl_WrongNumArgs(interp, 1, objv, "?arg?");
	    return TCL_ERROR;
	}
	break;
    default:
        if (corPtr->nargs != objc-1) {
            Tcl_SetObjResult(interp,
                    Tcl_NewStringObj("wrong coro nargs; how did we get here? "
                    "not implemented!", -1));
            Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL);
            return TCL_ERROR;
        }
        /* fallthrough */
	if (corPtr->nargs + 1 != objc) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("wrong coro nargs; how did we get here? "
		    "not implemented!", TCL_INDEX_NONE));
	    Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (char *)NULL);
	    return TCL_ERROR;
	}
	/* fallthrough */
    case COROUTINE_ARGUMENTS_ARBITRARY:
        if (objc > 1) {
            Tcl_SetObjResult(interp, Tcl_NewListObj(objc-1, objv+1));
        }
        break;
	if (objc > 1) {
	    Tcl_SetObjResult(interp, Tcl_NewListObj(objc - 1, objv + 1));
	}
	break;
    }

    TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr,
            NULL, NULL, NULL);
	    NULL, NULL, NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclNRCoroutineObjCmd --
 *
 *      Implementation of [coroutine] command; see documentation for
 *      description of what this does.
 *	Implementation of [coroutine] command; see documentation for
 *	description of what this does.
 *
 *----------------------------------------------------------------------
 */

int
TclNRCoroutineObjCmd(
    TCL_UNUSED(void *),
9402
9403
9404
9405
9406
9407
9408
9409
9410
9411



9412
9413
9414
9415
9416
9417
9418



9419
9420
9421
9422
9423
9424
9425
9426
9427
9428
9429
9430
9431
9432
9433
9434
9435
9436
9437
9438
9439

9440
9441
9442
9443
9444
9445
9446
9712
9713
9714
9715
9716
9717
9718



9719
9720
9721
9722
9723
9724
9725



9726
9727
9728
9729
9730
9731
9732
9733
9734
9735
9736
9737
9738
9739
9740
9741
9742
9743
9744
9745
9746
9747
9748

9749
9750
9751
9752
9753
9754
9755
9756







-
-
-
+
+
+




-
-
-
+
+
+




















-
+








    procName = TclGetString(objv[1]);
    TclGetNamespaceForQualName(interp, procName, inNsPtr, 0,
	    &nsPtr, &altNsPtr, &cxtNsPtr, &simpleName);

    if (nsPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "can't create procedure \"%s\": unknown namespace",
                procName));
        Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", NULL);
		"can't create procedure \"%s\": unknown namespace",
		procName));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", (char *)NULL);
	return TCL_ERROR;
    }
    if (simpleName == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "can't create procedure \"%s\": bad procedure name",
                procName));
        Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", procName, NULL);
		"can't create procedure \"%s\": bad procedure name",
		procName));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", procName, (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * We ARE creating the coroutine command: allocate the corresponding
     * struct and create the corresponding command.
     */

    corPtr = (CoroutineData *)Tcl_Alloc(sizeof(CoroutineData));

    cmdPtr = (Command *) TclNRCreateCommandInNs(interp, simpleName,
	    (Tcl_Namespace *)nsPtr, /*objProc*/ NULL, TclNRInterpCoroutine,
	    corPtr, DeleteCoroutine);

    corPtr->cmdPtr = cmdPtr;
    cmdPtr->refCount++;

    /*
     * #280.
     * Provide the new coroutine with its own copy of the lineLABCPtr
     * hashtable for literal command arguments in bytecode. Note that that
     * hashtable for literal command arguments in bytecode. Note that
     * CFWordBC chains are not duplicated, only the entrypoints to them. This
     * means that in the presence of coroutines each chain is potentially a
     * tree. Like the chain -> tree conversion of the CmdFrame stack.
     */

    {
	Tcl_HashSearch hSearch;
9467
9468
9469
9470
9471
9472
9473

9474
9475
9476
9477
9478
9479
9480
9777
9778
9779
9780
9781
9782
9783
9784
9785
9786
9787
9788
9789
9790
9791







+








    corPtr->running.framePtr = iPtr->rootFramePtr;
    corPtr->running.varFramePtr = iPtr->rootFramePtr;
    corPtr->running.cmdFramePtr = NULL;
    corPtr->running.lineLABCPtr = corPtr->lineLABCPtr;
    corPtr->stackLevel = NULL;
    corPtr->auxNumLevels = 0;
    corPtr->yieldPtr = NULL;

    /*
     * Create the coro's execEnv, switch to it to push the exit and coro
     * command callbacks, then switch back.
     */

    corPtr->eePtr = TclCreateExecEnv(interp, CORO_STACK_INITIAL_SIZE);
9502
9503
9504
9505
9506
9507
9508
9509

9510
9511
9512
9513
9514
9515
9516
9813
9814
9815
9816
9817
9818
9819

9820
9821
9822
9823
9824
9825
9826
9827







-
+







    iPtr->execEnvPtr = corPtr->callerEEPtr;

    /*
     * Now just resume the coroutine.
     */

    TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr,
            NULL, NULL, NULL);
	    NULL, NULL, NULL);
    return TCL_OK;
}

/*
 * This is used in the [info] ensemble
 */

Changes to generic/tclBinary.c.

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

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
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
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






-
-
+
+
















-
-
+
+


-
+










-
+

















-
-




-


-
+


-
+







-
+
-
-
-
+
-
-

-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-







/*
 * tclBinary.c --
 *
 *	This file contains the implementation of the "binary" Tcl built-in
 *	command and the Tcl binary data object.
 *
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright © 1997 Sun Microsystems, Inc.
 * Copyright © 1998-1999 Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclTomMath.h"

#include <math.h>
#include <assert.h>

/*
 * The following constants are used by GetFormatSpec to indicate various
 * special conditions in the parsing of a format specifier.
 */

#define BINARY_ALL ((size_t)-1)		/* Use all elements in the argument. */
#define BINARY_NOCOUNT ((size_t)-2)	/* No count was specified in format. */
#define BINARY_ALL -1		/* Use all elements in the argument. */
#define BINARY_NOCOUNT -2	/* No count was specified in format. */

/*
 * The following flags may be ORed together and returned by GetFormatSpec
 * The following flags may be OR'ed together and returned by GetFormatSpec
 */

#define BINARY_SIGNED 0		/* Field to be read as signed data */
#define BINARY_UNSIGNED 1	/* Field to be read as unsigned data */

/*
 * The following defines the maximum number of different (integer) numbers
 * placed in the object cache by 'binary scan' before it bails out and
 * switches back to Plan A (creating a new object for each value.)
 * Theoretically, it would be possible to keep the cache about for the values
 * that are already in it, but that makes the code slower in practise when
 * that are already in it, but that makes the code slower in practice when
 * overflow happens, and makes little odds the rest of the time (as measured
 * on my machine.) It is also slower (on the sample I tried at least) to grow
 * the cache to hold all items we might want to put in it; presumably the
 * extra cost of managing the memory for the enlarged table outweighs the
 * benefit from allocating fewer objects. This is probably because as the
 * number of objects increases, the likelihood of reuse of any particular one
 * drops, and there is very little gain from larger maximum cache sizes (the
 * value below is chosen to allow caching to work in full with conversion of
 * bytes.) - DKF
 */

#define BINARY_SCAN_MAX_CACHE	260

/*
 * Prototypes for local procedures defined in this file:
 */

static void		DupByteArrayInternalRep(Tcl_Obj *srcPtr,
			    Tcl_Obj *copyPtr);
static void		DupProperByteArrayInternalRep(Tcl_Obj *srcPtr,
			    Tcl_Obj *copyPtr);
static int		FormatNumber(Tcl_Interp *interp, int type,
			    Tcl_Obj *src, unsigned char **cursorPtr);
static void		FreeByteArrayInternalRep(Tcl_Obj *objPtr);
static void		FreeProperByteArrayInternalRep(Tcl_Obj *objPtr);
static int		GetFormatSpec(const char **formatPtr, char *cmdPtr,
			    size_t *countPtr, int *flagsPtr);
			    Tcl_Size *countPtr, int *flagsPtr);
static Tcl_Obj *	ScanNumber(unsigned char *buffer, int type,
			    int flags, Tcl_HashTable **numberCachePtr);
static int		SetByteArrayFromAny(Tcl_Interp *interp,
static int		SetByteArrayFromAny(Tcl_Interp *interp, Tcl_Size limit,
			    Tcl_Obj *objPtr);
static void		UpdateStringOfByteArray(Tcl_Obj *listPtr);
static void		DeleteScanNumberCache(Tcl_HashTable *numberCachePtr);
static int		NeedReversing(int format);
static void		CopyNumber(const void *from, void *to,
			    size_t length, int type);
/* Binary ensemble commands */
static int		BinaryFormatCmd(ClientData clientData,
static Tcl_ObjCmdProc	BinaryFormatCmd;
			    Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		BinaryScanCmd(ClientData clientData,
static Tcl_ObjCmdProc	BinaryScanCmd;
			    Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
/* Binary encoding sub-ensemble commands */
static int		BinaryEncodeHex(ClientData clientData,
static Tcl_ObjCmdProc	BinaryEncodeHex;
			    Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		BinaryDecodeHex(ClientData clientData,
static Tcl_ObjCmdProc	BinaryDecodeHex;
			    Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		BinaryEncode64(ClientData clientData,
static Tcl_ObjCmdProc	BinaryEncode64;
			    Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		BinaryDecode64(ClientData clientData,
static Tcl_ObjCmdProc	BinaryDecode64;
			    Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		BinaryEncodeUu(ClientData clientData,
static Tcl_ObjCmdProc	BinaryEncodeUu;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		BinaryDecodeUu(ClientData clientData,
static Tcl_ObjCmdProc	BinaryDecodeUu;
			    Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);

/*
 * The following tables are used by the binary encoders
 */

static const char HexDigits[16] = {
    '0', '1', '2', '3', '4', '5', '6', '7',
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
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
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







-
+




-
-
-
-


-
+




-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+







-
+
-
-
+
-
-
-
-
-
-










-
-
-
-
+

-
+






+

+
+
-
+








-
+











-
+














-
+
+


-
+




-
+




















-
+













-
+
+








-
+







-
-
+
+



-
+







    { "hex",      BinaryDecodeHex, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 },
    { "uuencode", BinaryDecodeUu,  TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 },
    { "base64",   BinaryDecode64,  TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 },
    { NULL, NULL, NULL, NULL, NULL, 0 }
};

/*
 * The following object types represent an array of bytes. The intent is to
 * The following Tcl_ObjType represents an array of bytes. The intent is to
 * allow arbitrary binary data to pass through Tcl as a Tcl value without loss
 * or damage. Such values are useful for things like encoded strings or Tk
 * images to name just two.
 *
 * It's strange to have two Tcl_ObjTypes in place for this task when one would
 * do, so a bit of detail and history how we got to this point and where we
 * might go from here.
 *
 * A bytearray is an ordered sequence of bytes. Each byte is an integer value
 * in the range [0-255].  To be a Tcl value type, we need a way to encode each
 * value in the value set as a Tcl string.  The simplest encoding is to
 * value in the value set as a Tcl string.  A simple encoding is to
 * represent each byte value as the same codepoint value.  A bytearray of N
 * bytes is encoded into a Tcl string of N characters where the codepoint of
 * each character is the value of corresponding byte.  This approach creates a
 * one-to-one map between all bytearray values and a subset of Tcl string
 * values.
 * values.  Tcl string values outside that subset do no represent any valid
 *
 * When converting a Tcl string value to the bytearray internal rep, the
 * question arises what to do with strings outside that subset?  That is,
 * those Tcl strings containing at least one codepoint greater than 255?  The
 * obviously correct answer is to raise an error!  That string value does not
 * represent any valid bytearray value. Full Stop.  The setFromAnyProc
 * bytearray value.  Attempts to treat those values as bytearrays will lead
 * signature has a completion code return value for just this reason, to
 * reject invalid inputs.
 *
 * Unfortunately this was not the path taken by the authors of the original
 * tclByteArrayType.  They chose to accept all Tcl string values as acceptable
 * string encodings of the bytearray values that result from masking away the
 * high bits of any codepoint value at all. This meant that every bytearray
 * value had multiple accepted string representations.
 *
 * The implications of this choice are truly ugly.  When a Tcl value has a
 * string representation, we are required to accept that as the true value.
 * Bytearray values that possess a string representation cannot be processed
 * as bytearrays because we cannot know which true value that bytearray
 * represents.  The consequence is that we drag around an internal rep that we
 * cannot make any use of.  This painful price is extracted at any point after
 * a string rep happens to be generated for the value.  This happens even when
 * the troublesome codepoints outside the byte range never show up.  This
 * happens rather routinely in normal Tcl operations unless we burden the
 * script writer with the cognitive burden of avoiding it.  The price is also
 * paid by callers of the C interface.  The routine
 *
 *	unsigned char *Tcl_GetByteArrayFromObj(objPtr, lenPtr)
 *
 * has a guarantee to always return a non-NULL value, but that value points to
 * a byte sequence that cannot be used by the caller to process the Tcl value
 * absent some sideband testing that objPtr is "pure".  Tcl offers no public
 * interface to perform this test, so callers either break encapsulation or
 * are unavoidably buggy.  Tcl has defined a public interface that cannot be
 * used correctly. The Tcl source code itself suffers the same problem, and
 * has been buggy, but progressively less so as more and more portions of the
 * code have been retrofitted with the required "purity testing".  The set of
 * values able to pass the purity test can be increased via the introduction
 * of a "canonical" flag marker, but the only way the broken interface itself
 * can be discarded is to start over and define the Tcl_ObjType properly.
 * Bytearrays should simply be usable as bytearrays without a kabuki dance of
 * testing.
 *
 * The Tcl_ObjType "properByteArrayType" is (nearly) a correct implementation
 * of bytearrays.  Any Tcl value with the type properByteArrayType can have
 * its bytearray value fetched and used with confidence that acting on that
 * value is equivalent to acting on the true Tcl string value.  This still
 * implies a side testing burden -- past mistakes will not let us avoid that
 * immediately, but it is at least a conventional test of type, and can be
 * implemented entirely by examining the objPtr fields, with no need to query
 * the intrep, as a canonical flag would require.
 *
 * Until Tcl_GetByteArrayFromObj() and Tcl_SetByteArrayLength() can be revised
 * to admit the possibility of returning NULL when the true value is not a
 * valid bytearray, we need a mechanism to retain compatibility with the
 * deployed callers of the broken interface.  That's what the retained
 * "tclByteArrayType" provides.  In those unusual circumstances where we
 * convert an invalid bytearray value to a bytearray type, it is to this
 * legacy type.  Essentially any time this legacy type gets used, it's a
 * signal of a bug being ignored.  A TIP should be drafted to remove this
 * connection to the broken past so that Tcl 9 will no longer have any trace
 * of it.  Prescribing a migration path will be the key element of that work.
 * The internal changes now in place are the limit of what can be done short
 * of interface repair.  They provide a great expansion of the histories over
 * which bytearray values can be useful in the meanwhile.
 * to errors.  See TIP 568 for how this differs from Tcl 8.
 */

static const Tcl_ObjType properByteArrayType = {
    "bytearray",
    FreeProperByteArrayInternalRep,
    DupProperByteArrayInternalRep,
    UpdateStringOfByteArray,
    NULL
    NULL,
};

    TCL_OBJTYPE_V0
const Tcl_ObjType tclByteArrayType = {
    "bytearray",
    FreeByteArrayInternalRep,
    DupByteArrayInternalRep,
    NULL,
    SetByteArrayFromAny
};

/*
 * The following structure is the internal rep for a ByteArray object. Keeps
 * track of how much memory has been used and how much has been allocated for
 * the byte array to enable growing and shrinking of the ByteArray object with
 * fewer mallocs.
 */

typedef struct {
    size_t bad;			/* Index of the character that is a nonbyte.
				 * If all characters are bytes, bad = used,
				 * though then we should never read it. */
    size_t used;		/* The number of bytes used in the byte
    Tcl_Size used;		/* The number of bytes used in the byte
				 * array. */
    size_t allocated;		/* The amount of space actually allocated
    Tcl_Size allocated;		/* The amount of space actually allocated
				 * minus 1 byte. */
    unsigned char bytes[TCLFLEXARRAY];	/* The array of bytes. The actual size of this
				 * field depends on the 'allocated' field
				 * above. */
} ByteArray;

#define BYTEARRAY_MAX_LEN (TCL_SIZE_MAX - (Tcl_Size)offsetof(ByteArray, bytes))
#define BYTEARRAY_SIZE(len) \
	( (len < 0 || BYTEARRAY_MAX_LEN < (len)) \
	? (Tcl_Panic("negative length specified or max size of a Tcl value exceeded"), 0) \
		(offsetof(ByteArray, bytes) + (len))
	: (offsetof(ByteArray, bytes) + (len)) )
#define GET_BYTEARRAY(irPtr) ((ByteArray *) (irPtr)->twoPtrValue.ptr1)
#define SET_BYTEARRAY(irPtr, baPtr) \
		(irPtr)->twoPtrValue.ptr1 = (baPtr)

int
TclIsPureByteArray(
    Tcl_Obj * objPtr)
{
    return TclHasIntRep(objPtr, &properByteArrayType);
    return TclHasInternalRep(objPtr, &properByteArrayType);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_NewByteArrayObj --
 *
 *	This procedure is creates a new ByteArray object and initializes it
 *	from the given array of bytes.
 *
 * Results:
 *	The newly create object is returned. This object will have no initial
 *	The newly created object is returned. This object has no initial
 *	string representation. The returned object has a ref count of 0.
 *
 * Side effects:
 *	Memory allocated for new object and copy of byte array argument.
 *
 *----------------------------------------------------------------------
 */

#undef Tcl_NewByteArrayObj

Tcl_Obj *
Tcl_NewByteArrayObj(
    const unsigned char *bytes,	/* The array of bytes used to initialize the
				 * new object. */
    size_t length)		/* Length of the array of bytes */
    Tcl_Size numBytes)		/* Number of bytes in the array,
				 * must be >= 0. */
{
#ifdef TCL_MEM_DEBUG
    return Tcl_DbNewByteArrayObj(bytes, length, "unknown", 0);
    return Tcl_DbNewByteArrayObj(bytes, numBytes, "unknown", 0);
#else /* if not TCL_MEM_DEBUG */
    Tcl_Obj *objPtr;

    TclNewObj(objPtr);
    Tcl_SetByteArrayObj(objPtr, bytes, length);
    Tcl_SetByteArrayObj(objPtr, bytes, numBytes);
    return objPtr;
#endif /* TCL_MEM_DEBUG */
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DbNewByteArrayObj --
 *
 *	This procedure is normally called when debugging: i.e., when
 *	TCL_MEM_DEBUG is defined. It is the same as the Tcl_NewByteArrayObj
 *	above except that it calls Tcl_DbCkalloc directly with the file name
 *	and line number from its caller. This simplifies debugging since then
 *	the [memory active] command will report the correct file name and line
 *	number when reporting objects that haven't been freed.
 *
 *	When TCL_MEM_DEBUG is not defined, this procedure just returns the
 *	result of calling Tcl_NewByteArrayObj.
 *
 * Results:
 *	The newly create object is returned. This object will have no initial
 *	The newly created object is returned. This object has no initial
 *	string representation. The returned object has a ref count of 0.
 *
 * Side effects:
 *	Memory allocated for new object and copy of byte array argument.
 *
 *----------------------------------------------------------------------
 */

#ifdef TCL_MEM_DEBUG
Tcl_Obj *
Tcl_DbNewByteArrayObj(
    const unsigned char *bytes,	/* The array of bytes used to initialize the
				 * new object. */
    size_t length,		/* Length of the array of bytes. */
    Tcl_Size numBytes,		/* Number of bytes in the array,
				 * must be >= 0. */
    const char *file,		/* The name of the source file calling this
				 * procedure; used for debugging. */
    int line)			/* Line number in the source file; used for
				 * debugging. */
{
    Tcl_Obj *objPtr;

    TclDbNewObj(objPtr, file, line);
    Tcl_SetByteArrayObj(objPtr, bytes, length);
    Tcl_SetByteArrayObj(objPtr, bytes, numBytes);
    return objPtr;
}
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
Tcl_DbNewByteArrayObj(
    const unsigned char *bytes,	/* The array of bytes used to initialize the
				 * new object. */
    size_t length,		/* Length of the array of bytes, which must be
				 * >= 0. */
    Tcl_Size numBytes,		/* Number of bytes in the array,
				 * must be >= 0. */
    TCL_UNUSED(const char *) /*file*/,
    TCL_UNUSED(int) /*line*/)
{
    return Tcl_NewByteArrayObj(bytes, length);
    return Tcl_NewByteArrayObj(bytes, numBytes);
}
#endif /* TCL_MEM_DEBUG */

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_SetByteArrayObj --
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
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
467
468
469
470
471

472
473
474

475
476
477
478
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
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
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







-
-
-
+
+
+


-
+






+
-
+
-
-
-
+
+

-
-
+
+



-
+









-
+



-
-
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
+
+

-
+
-
-
+
-
-
-
-
-
-
-

-
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-


-
+




+







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

void
Tcl_SetByteArrayObj(
    Tcl_Obj *objPtr,		/* Object to initialize as a ByteArray. */
    const unsigned char *bytes,	/* The array of bytes to use as the new value.
				 * May be NULL even if length > 0. */
    size_t length)			/* Length of the array of bytes, which must
				 * be >= 0. */
				 * May be NULL even if numBytes > 0. */
    Tcl_Size numBytes)		/* Number of bytes in the array,
				 * must be >= 0 */
{
    ByteArray *byteArrayPtr;
    Tcl_ObjIntRep ir;
    Tcl_ObjInternalRep ir;

    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayObj");
    }
    TclInvalidateStringRep(objPtr);

    assert(numBytes >= 0);
    byteArrayPtr = (ByteArray *)Tcl_Alloc(BYTEARRAY_SIZE(length));
    byteArrayPtr = (ByteArray *)Tcl_Alloc(BYTEARRAY_SIZE(numBytes));
    byteArrayPtr->bad = length;
    byteArrayPtr->used = length;
    byteArrayPtr->allocated = length;
    byteArrayPtr->used = numBytes;
    byteArrayPtr->allocated = numBytes;

    if ((bytes != NULL) && (length > 0)) {
	memcpy(byteArrayPtr->bytes, bytes, length);
    if ((bytes != NULL) && (numBytes > 0)) {
	memcpy(byteArrayPtr->bytes, bytes, numBytes);
    }
    SET_BYTEARRAY(&ir, byteArrayPtr);

    Tcl_StoreIntRep(objPtr, &properByteArrayType, &ir);
    Tcl_StoreInternalRep(objPtr, &properByteArrayType, &ir);
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetBytesFromObj --
 *
 *	Attempt to extract the value from objPtr in the representation
 *	of a byte sequence. On success return the extracted byte sequence.
 *	On failures, return NULL and record error message and code in
 *	On failure, return NULL and record error message and code in
 *	interp (if not NULL).
 *
 * Results:
 *	Pointer to array of bytes, or NULL. representing the ByteArray object.
 *	Writes number of bytes in array to *lengthPtr.
 *	NULL or pointer to array of bytes representing the ByteArray object.
 *	Writes number of bytes in array to *numBytesPtr.
 *
 *----------------------------------------------------------------------
 */

#undef Tcl_GetBytesFromObj
unsigned char *
Tcl_GetBytesFromObj(
    Tcl_Interp *interp,		/* For error reporting */
    Tcl_Obj *objPtr,		/* Value to extract from */
    Tcl_Size *numBytesPtr)	/* If non-NULL, write the number of bytes
				 * in the array here */
{
    ByteArray *baPtr;
    const Tcl_ObjInternalRep *irPtr
	    = TclFetchInternalRep(objPtr, &properByteArrayType);

    if (irPtr == NULL) {
	if (TCL_ERROR == SetByteArrayFromAny(interp, TCL_INDEX_NONE, objPtr)) {
	    return NULL;
	}
	irPtr = TclFetchInternalRep(objPtr, &properByteArrayType);
    }
    baPtr = GET_BYTEARRAY(irPtr);

    if (numBytesPtr != NULL) {
	*numBytesPtr = baPtr->used;
    }
    return baPtr->bytes;
}

#if !defined(TCL_NO_DEPRECATED)
unsigned char *
TclGetBytesFromObj(
    Tcl_Interp *interp,		/* For error reporting */
    Tcl_Obj *objPtr,		/* Value to extract from */
    size_t *lengthPtr)		/* If non-NULL, filled with length of the
				 * array of bytes in the ByteArray object. */
    void *numBytesPtr)		/* If non-NULL, write the number of bytes
				 * in the array here */
{
    ByteArray *baPtr;
    Tcl_Size numBytes = 0;
    const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objPtr, &properByteArrayType);

    unsigned char *bytes = Tcl_GetBytesFromObj(interp, objPtr, &numBytes);
    if (irPtr == NULL) {
	SetByteArrayFromAny(NULL, objPtr);
	irPtr = TclFetchIntRep(objPtr, &properByteArrayType);
	if (irPtr == NULL) {
	    if (interp) {
		const char *nonbyte;
		int ucs4;

		irPtr = TclFetchIntRep(objPtr, &tclByteArrayType);
		baPtr = GET_BYTEARRAY(irPtr);
    if (bytes && numBytesPtr) {
		nonbyte = Tcl_UtfAtIndex(Tcl_GetString(objPtr), baPtr->bad);
		TclUtfToUCS4(nonbyte, &ucs4);

	if (numBytes > INT_MAX) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"expected byte sequence but character %" TCL_Z_MODIFIER "u "
			"was '%1s' (U+%06X)", baPtr->bad, nonbyte, ucs4));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "BYTES", NULL);
	    }
	    return NULL;
	}
    }
    baPtr = GET_BYTEARRAY(irPtr);

	    /* Caller asked for numBytes to be written to an int, but the
    if (lengthPtr != NULL) {
	*lengthPtr = baPtr->used;
    }
    return baPtr->bytes;
}

	     * value is outside the int range. */
/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetByteArrayFromObj --
 *
 *	Attempt to get the array of bytes from the Tcl object. If the object
 *	is not already a ByteArray object, an attempt will be made to convert
 *	it to one.
 *

 * Results:
 *	Pointer to array of bytes representing the ByteArray object.
 *
 * Side effects:
 *	Frees old internal rep. Allocates memory for new internal rep.
 *
 *----------------------------------------------------------------------
 */

	    if (interp) {
unsigned char *
Tcl_GetByteArrayFromObj(
    Tcl_Obj *objPtr,		/* The ByteArray object. */
    int *lengthPtr)		/* If non-NULL, filled with length of the
				 * array of bytes in the ByteArray object. */
{
    size_t numBytes = 0;
    unsigned char *bytes = TclGetBytesFromObj(NULL, objPtr, &numBytes);

		Tcl_SetObjResult(interp, Tcl_NewStringObj(
    if (bytes == NULL) {
	ByteArray *baPtr;
	const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objPtr, &tclByteArrayType);

			"byte sequence length exceeds INT_MAX", -1));
	assert(irPtr != NULL);

		Tcl_SetErrorCode(interp, "TCL", "API", "OUTDATED", (char *)NULL);
	baPtr = GET_BYTEARRAY(irPtr);
	bytes = baPtr->bytes;
	numBytes = baPtr->used;
    }
	    }

    /* Macro TclGetByteArrayFromObj passes NULL for lengthPtr as
     * a trick to get around changing size. */
    if (lengthPtr) {
	if (numBytes > INT_MAX) {
	    /* Caller asked for an int length, but true length is outside
	     * the int range. This case will be developed out of existence
	     * in Tcl 9. As interim measure, fail. */

	    *lengthPtr = 0;
	    return NULL;
	} else {
	    *lengthPtr = (int) numBytes;
	    *(int *)numBytesPtr = (int) numBytes;
	}
    }
    return bytes;
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetByteArrayLength --
 *
 *	This procedure changes the length of the byte array for this object.
564
565
566
567
568
569
570
571


572
573
574

575

576
577
578
579
580

581
582
583
584

585
586

587
588

589

590
591
592
593
594
595




596
597
598




























599
600
601
602
603































































604
605
606
607
608
609
610
611
612
613

614
615
616

617
618
619
620
621
622
623


624
625
626
627
628
629
630
631

632
633
634
635
636
637


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

660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743

744
745

746
747

748
749
750
751
752
753
754
755
756
757

758
759
760
761
762
763
764
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568

569
570
571

572
573
574
575
576
577
578

579
580
581
582




583

584
585





586
587
588
589













590






591





592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611







612
613
614
615

616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636






















637
638
639
640

641
642

643
644

645
646
647
648

649
650
651
652
653

654
655
656
657
658
659
660
661







-
+
+


-
+

+




-
+

-
-
-
+
-
-
+
-
-
+
-
+



-
-
-
+
+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+


-
+






-
+
+


-
-
-
-

-
+

-
-
-
-
-
+
+


-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
+
-
-
-
-
-




















-
-
-
-
-
-
-




-
+




















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-




-
+

-
+

-
+



-





-
+







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

unsigned char *
Tcl_SetByteArrayLength(
    Tcl_Obj *objPtr,		/* The ByteArray object. */
    size_t length)		/* New length for internal byte array. */
    Tcl_Size numBytes)		/* Number of bytes in resized array
				 * Must be >= 0 */
{
    ByteArray *byteArrayPtr;
    Tcl_ObjIntRep *irPtr;
    Tcl_ObjInternalRep *irPtr;

    assert(numBytes >= 0);
    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayLength");
    }

    irPtr = TclFetchIntRep(objPtr, &properByteArrayType);
    irPtr = TclFetchInternalRep(objPtr, &properByteArrayType);
    if (irPtr == NULL) {
	irPtr = TclFetchIntRep(objPtr, &tclByteArrayType);
	if (irPtr == NULL) {
	    SetByteArrayFromAny(NULL, objPtr);
	if (TCL_ERROR == SetByteArrayFromAny(NULL, numBytes, objPtr)) {
	    irPtr = TclFetchIntRep(objPtr, &properByteArrayType);
	    if (irPtr == NULL) {
	    return NULL;
		irPtr = TclFetchIntRep(objPtr, &tclByteArrayType);
	    }
	}
	}
	irPtr = TclFetchInternalRep(objPtr, &properByteArrayType);
    }

    byteArrayPtr = GET_BYTEARRAY(irPtr);
    if (length > byteArrayPtr->allocated) {
	byteArrayPtr = (ByteArray *)Tcl_Realloc(byteArrayPtr, BYTEARRAY_SIZE(length));
	byteArrayPtr->allocated = length;
    if (numBytes > byteArrayPtr->allocated) {
	byteArrayPtr = (ByteArray *)Tcl_Realloc(byteArrayPtr,
		BYTEARRAY_SIZE(numBytes));
	byteArrayPtr->allocated = numBytes;
	SET_BYTEARRAY(irPtr, byteArrayPtr);
    }
    TclInvalidateStringRep(objPtr);
    byteArrayPtr->used = numBytes;
    return byteArrayPtr->bytes;
}

/*
 *----------------------------------------------------------------------
 *
 * MakeByteArray --
 *
 *	Generate a ByteArray internal rep from the string rep of objPtr.
 *	The generated byte sequence may have no more than limit bytes.
 *	A negative value for limit indicates no limit imposed. If
 *	boolean argument demandProper is true, then no byte sequence should
 *	be output to the caller (write NULL instead). When no bytes sequence
 *	is output and interp is not NULL, leave an error message and error
 *	code in interp explaining why a proper byte sequence could not be
 *	made.
 *
 * Results:
 *	Returns a boolean indicating whether the bytes generated (up to
 *	limit bytes) are a proper representation of (a limited prefix of)
 *	the string. Writes a pointer to the generated ByteArray to
 *	*byteArrayPtrPtr. If not NULL it needs to be released with Tcl_Free().
 *
 *----------------------------------------------------------------------
 */

static int
    objPtr->typePtr = &properByteArrayType;
    byteArrayPtr->bad = length;
    byteArrayPtr->used = length;
    return byteArrayPtr->bytes;
}
MakeByteArray(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    Tcl_Size limit,
    int demandProper,
    ByteArray **byteArrayPtrPtr)
{
    Tcl_Size length;
    const char *src = TclGetStringFromObj(objPtr, &length);
    Tcl_Size numBytes = (limit >= 0 && limit < length) ? limit : length;
    ByteArray *byteArrayPtr = (ByteArray *)Tcl_Alloc(BYTEARRAY_SIZE(numBytes));
    unsigned char *dst = byteArrayPtr->bytes;
    unsigned char *dstEnd = dst + numBytes;
    const char *srcEnd = src + length;
    int proper = 1;

    for (; src < srcEnd && dst < dstEnd; ) {
	int ch;
	int count = TclUtfToUniChar(src, &ch);

	if (ch > 255) {
	    proper = 0;
	    if (demandProper) {
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "expected byte sequence but character %"
			    TCL_Z_MODIFIER "u was '%1s' (U+%06X)",
			    dst - byteArrayPtr->bytes, src, ch));
		    Tcl_SetErrorCode(interp, "TCL", "VALUE", "BYTES", (char *)NULL);
		}
		Tcl_Free(byteArrayPtr);
		*byteArrayPtrPtr = NULL;
		return proper;
	    }
	}
	src += count;
	*dst++ = UCHAR(ch);
    }
    byteArrayPtr->used = dst - byteArrayPtr->bytes;
    byteArrayPtr->allocated = numBytes;

    *byteArrayPtrPtr = byteArrayPtr;
    return proper;
}

static Tcl_Obj *
TclNarrowToBytes(
    Tcl_Obj *objPtr)
{
    if (NULL == TclFetchInternalRep(objPtr, &properByteArrayType)) {
	Tcl_ObjInternalRep ir;
	ByteArray *byteArrayPtr;

	if (0 == MakeByteArray(NULL, objPtr, TCL_INDEX_NONE, 0, &byteArrayPtr)) {
	    TclNewObj(objPtr);
	    TclInvalidateStringRep(objPtr);
	}
	SET_BYTEARRAY(&ir, byteArrayPtr);
	Tcl_StoreInternalRep(objPtr, &properByteArrayType, &ir);
    }
    Tcl_IncrRefCount(objPtr);
    return objPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * SetByteArrayFromAny --
 *
 *	Generate the ByteArray internal rep from the string rep.
 *
 * Results:
 *	The return value is always TCL_OK.
 *	Tcl return code indicating OK or ERROR.
 *
 * Side effects:
 *	A ByteArray object is stored as the internal rep of objPtr.
 *	A ByteArray struct may be stored as the internal rep of objPtr.
 *
 *----------------------------------------------------------------------
 */

static int
SetByteArrayFromAny(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Interp *interp,		/* For error reporting. */
    Tcl_Size limit,		/* Create no more than this many bytes */
    Tcl_Obj *objPtr)		/* The object to convert to type ByteArray. */
{
    size_t length, bad;
    const char *src, *srcEnd;
    unsigned char *dst;
    Tcl_UniChar ch = 0;
    ByteArray *byteArrayPtr;
    Tcl_ObjIntRep ir;
    Tcl_ObjInternalRep ir;

    if (TclHasIntRep(objPtr, &properByteArrayType)) {
	return TCL_OK;
    }
    if (TclHasIntRep(objPtr, &tclByteArrayType)) {
	return TCL_OK;
    if (0 == MakeByteArray(interp, objPtr, limit, 1, &byteArrayPtr)) {
	return TCL_ERROR;
    }

    src = TclGetStringFromObj(objPtr, &length);
    bad = length;
    srcEnd = src + length;

    byteArrayPtr = (ByteArray *)Tcl_Alloc(BYTEARRAY_SIZE(length));
    for (dst = byteArrayPtr->bytes; src < srcEnd; ) {
	src += TclUtfToUniChar(src, &ch);
	if ((bad == length) && (ch > 255)) {
	    bad = dst - byteArrayPtr->bytes;
	}
	*dst++ = UCHAR(ch);
    }

    SET_BYTEARRAY(&ir, byteArrayPtr);
    byteArrayPtr->allocated = length;
    byteArrayPtr->used = dst - byteArrayPtr->bytes;

    if (bad == length) {
	byteArrayPtr->bad = byteArrayPtr->used;
	Tcl_StoreIntRep(objPtr, &properByteArrayType, &ir);
    Tcl_StoreInternalRep(objPtr, &properByteArrayType, &ir);
    } else {
	byteArrayPtr->bad = bad;
	Tcl_StoreIntRep(objPtr, &tclByteArrayType, &ir);
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * FreeByteArrayInternalRep --
 *
 *	Deallocate the storage associated with a ByteArray data object's
 *	internal representation.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Frees memory.
 *
 *----------------------------------------------------------------------
 */

static void
FreeByteArrayInternalRep(
    Tcl_Obj *objPtr)		/* Object with internal rep to free. */
{
    Tcl_Free(GET_BYTEARRAY(TclFetchIntRep(objPtr, &tclByteArrayType)));
}

static void
FreeProperByteArrayInternalRep(
    Tcl_Obj *objPtr)		/* Object with internal rep to free. */
{
    Tcl_Free(GET_BYTEARRAY(TclFetchIntRep(objPtr, &properByteArrayType)));
    Tcl_Free(GET_BYTEARRAY(TclFetchInternalRep(objPtr, &properByteArrayType)));
}

/*
 *----------------------------------------------------------------------
 *
 * DupByteArrayInternalRep --
 *
 *	Initialize the internal representation of a ByteArray Tcl_Obj to a
 *	copy of the internal representation of an existing ByteArray object.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Allocates memory.
 *
 *----------------------------------------------------------------------
 */

static void
DupByteArrayInternalRep(
    Tcl_Obj *srcPtr,		/* Object with internal rep to copy. */
    Tcl_Obj *copyPtr)		/* Object with internal rep to set. */
{
    size_t length;
    ByteArray *srcArrayPtr, *copyArrayPtr;
    Tcl_ObjIntRep ir;

    srcArrayPtr = GET_BYTEARRAY(TclFetchIntRep(srcPtr, &tclByteArrayType));
    length = srcArrayPtr->used;

    copyArrayPtr = (ByteArray *)Tcl_Alloc(BYTEARRAY_SIZE(length));
    copyArrayPtr->bad = srcArrayPtr->bad;
    copyArrayPtr->used = length;
    copyArrayPtr->allocated = length;
    memcpy(copyArrayPtr->bytes, srcArrayPtr->bytes, length);

    SET_BYTEARRAY(&ir, copyArrayPtr);
    Tcl_StoreIntRep(copyPtr, &tclByteArrayType, &ir);
}

static void
DupProperByteArrayInternalRep(
    Tcl_Obj *srcPtr,		/* Object with internal rep to copy. */
    Tcl_Obj *copyPtr)		/* Object with internal rep to set. */
{
    unsigned int length;
    Tcl_Size length;
    ByteArray *srcArrayPtr, *copyArrayPtr;
    Tcl_ObjIntRep ir;
    Tcl_ObjInternalRep ir;

    srcArrayPtr = GET_BYTEARRAY(TclFetchIntRep(srcPtr, &properByteArrayType));
    srcArrayPtr = GET_BYTEARRAY(TclFetchInternalRep(srcPtr, &properByteArrayType));
    length = srcArrayPtr->used;

    copyArrayPtr = (ByteArray *)Tcl_Alloc(BYTEARRAY_SIZE(length));
    copyArrayPtr->bad = length;
    copyArrayPtr->used = length;
    copyArrayPtr->allocated = length;
    memcpy(copyArrayPtr->bytes, srcArrayPtr->bytes, length);

    SET_BYTEARRAY(&ir, copyArrayPtr);
    Tcl_StoreIntRep(copyPtr, &properByteArrayType, &ir);
    Tcl_StoreInternalRep(copyPtr, &properByteArrayType, &ir);
}

/*
 *----------------------------------------------------------------------
 *
 * UpdateStringOfByteArray --
 *
775
776
777
778
779
780
781
782

783
784
785
786


787
788
789
790
791
792
793
672
673
674
675
676
677
678

679
680
681


682
683
684
685
686
687
688
689
690







-
+


-
-
+
+







 */

static void
UpdateStringOfByteArray(
    Tcl_Obj *objPtr)		/* ByteArray object whose string rep to
				 * update. */
{
    const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objPtr, &properByteArrayType);
    const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objPtr, &properByteArrayType);
    ByteArray *byteArrayPtr = GET_BYTEARRAY(irPtr);
    unsigned char *src = byteArrayPtr->bytes;
    size_t i, length = byteArrayPtr->used;
    size_t size = length;
    Tcl_Size i, length = byteArrayPtr->used;
    Tcl_Size size = length;

    /*
     * How much space will string rep need?
     */

    for (i = 0; i < length; i++) {
	if ((src[i] == 0) || (src[i] > 127)) {
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
699
700
701
702
703
704
705

706
707
708
709
710
711
712







-







    } else {
	char *dst = Tcl_InitStringRep(objPtr, NULL, size);

	TclOOM(dst, size);
	for (i = 0; i < length; i++) {
	    dst += Tcl_UniCharToUtf(src[i], dst);
	}
	(void) Tcl_InitStringRep(objPtr, NULL, size);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclAppendBytesToByteArray --
829
830
831
832
833
834
835
836

837
838
839
840


841
842
843
844
845

846
847
848
849
850
851
852
853
854
855
856
857

858
859
860
861

862
863
864
865


866

867
868
869
870
871
872
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
898
899

900
901

902
903
904
905
906
907
908


909
910
911
912




913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
725
726
727
728
729
730
731

732
733
734


735
736
737
738
739
740

741
742
743
744
745
746
747
748
749
750
751
752

753
754



755




756
757

758
759
760
761





762
763
764
765

766



767





768



769






770
771



772


773







774
775




776
777
778
779
780
781
782
783
784
785
786
787

788
789
790
791
792
793
794







-
+


-
-
+
+




-
+











-
+

-
-
-
+
-
-
-
-
+
+
-
+



-
-
-
-
-




-
+
-
-
-
+
-
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
+
-
-
-
+
-
-
+
-
-
-
-
-
-
-
+
+
-
-
-
-
+
+
+
+








-







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

void
TclAppendBytesToByteArray(
    Tcl_Obj *objPtr,
    const unsigned char *bytes,
    size_t len)
    Tcl_Size len)
{
    ByteArray *byteArrayPtr;
    size_t needed;
    Tcl_ObjIntRep *irPtr;
    Tcl_Size needed;
    Tcl_ObjInternalRep *irPtr;

    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object","TclAppendBytesToByteArray");
    }
    if (len == TCL_INDEX_NONE) {
    if (len < 0) {
	Tcl_Panic("%s must be called with definite number of bytes to append",
		"TclAppendBytesToByteArray");
    }
    if (len == 0) {
	/*
	 * Append zero bytes is a no-op.
	 */

	return;
    }

    irPtr = TclFetchIntRep(objPtr, &properByteArrayType);
    irPtr = TclFetchInternalRep(objPtr, &properByteArrayType);
    if (irPtr == NULL) {
	irPtr = TclFetchIntRep(objPtr, &tclByteArrayType);
	if (irPtr == NULL) {
	    SetByteArrayFromAny(NULL, objPtr);
	if (TCL_ERROR == SetByteArrayFromAny(NULL, TCL_INDEX_NONE, objPtr)) {
	    irPtr = TclFetchIntRep(objPtr, &properByteArrayType);
	    if (irPtr == NULL) {
		irPtr = TclFetchIntRep(objPtr, &tclByteArrayType);
	    }
	    Tcl_Panic("attempt to append bytes to non-bytearray");
	}
	}
	irPtr = TclFetchInternalRep(objPtr, &properByteArrayType);
    }
    byteArrayPtr = GET_BYTEARRAY(irPtr);

    if (len > UINT_MAX - byteArrayPtr->used) {
	Tcl_Panic("max size for a Tcl value (%u bytes) exceeded", UINT_MAX);
    }

    needed = byteArrayPtr->used + len;
    /*
     * If we need to, resize the allocated space in the byte array.
     */

    if (needed > byteArrayPtr->allocated) {
    if ((BYTEARRAY_MAX_LEN - byteArrayPtr->used) < len) {
	ByteArray *ptr = NULL;
	size_t attempt;

	/* Will wrap around !! */
	if (needed <= INT_MAX/2) {
	    /*
	     * Try to allocate double the total space that is needed.
	     */

	Tcl_Panic("max size of a byte array exceeded");
	    attempt = 2 * needed;
	    ptr = (ByteArray *)Tcl_AttemptRealloc(byteArrayPtr, BYTEARRAY_SIZE(attempt));
	}
    }
	if (ptr == NULL) {
	    /*
	     * Try to allocate double the increment that is needed (plus).
	     */

	    size_t limit = UINT_MAX - needed;
    needed = byteArrayPtr->used + len;
    if (needed > byteArrayPtr->allocated) {
	    size_t extra = len + TCL_MIN_GROWTH;
	    size_t growth = (extra > limit) ? limit : extra;

	Tcl_Size newCapacity;
	    attempt = needed + growth;
	    ptr = (ByteArray *)Tcl_AttemptRealloc(byteArrayPtr, BYTEARRAY_SIZE(attempt));
	byteArrayPtr =
	}
	if (ptr == NULL) {
	    /*
	     * Last chance: Try to allocate exactly what is needed.
	     */

	    attempt = needed;
	    (ByteArray *)TclReallocElemsEx(byteArrayPtr,
					   needed,
	    ptr = (ByteArray *)Tcl_Realloc(byteArrayPtr, BYTEARRAY_SIZE(attempt));
	}
	byteArrayPtr = ptr;
	byteArrayPtr->allocated = attempt;
					   1,
					   offsetof(ByteArray, bytes),
					   &newCapacity);
	byteArrayPtr->allocated = newCapacity;
	SET_BYTEARRAY(irPtr, byteArrayPtr);
    }

    if (bytes) {
	memcpy(byteArrayPtr->bytes + byteArrayPtr->used, bytes, len);
    }
    byteArrayPtr->used += len;
    TclInvalidateStringRep(objPtr);
    objPtr->typePtr = &properByteArrayType;
}

/*
 *----------------------------------------------------------------------
 *
 * TclInitBinaryCmd --
 *
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
830
831
832
833
834
835
836

837
838
839
840
841
842
843
844
845

846
847
848
849
850
851
852
853
854
855
856
857

858

859
860
861
862
863
864
865







-
+








-
+











-
+
-







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
BinaryFormatCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int arg;			/* Index of next argument to consume. */
    int value = 0;		/* Current integer value to be packed.
				 * Initialized to avoid compiler warning. */
    char cmd;			/* Current format character. */
    size_t count;			/* Count associated with current format
    Tcl_Size count;		/* Count associated with current format
				 * character. */
    int flags;			/* Format field flags */
    const char *format;		/* Pointer to current position in format
				 * string. */
    Tcl_Obj *resultPtr = NULL;	/* Object holding result buffer. */
    unsigned char *buffer;	/* Start of result buffer. */
    unsigned char *cursor;	/* Current position within result buffer. */
    unsigned char *maxPos;	/* Greatest position within result buffer that
				 * cursor has visited.*/
    const char *errorString;
    const char *errorValue, *str;
    int offset, size;
    Tcl_Size offset, size, length;
    size_t length;

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

    /*
1025
1026
1027
1028
1029
1030
1031
1032



1033
1034
1035
1036
1037
1038
1039
890
891
892
893
894
895
896

897
898
899
900
901
902
903
904
905
906







-
+
+
+







	     * of bytes in a single argument.
	     */

	    if (arg >= objc) {
		goto badIndex;
	    }
	    if (count == BINARY_ALL) {
		(void)TclGetByteArrayFromObj(objv[arg], &count);
		if (Tcl_GetBytesFromObj(NULL, objv[arg], &count) == NULL) {
		    count = Tcl_GetCharLength(objv[arg]);
		}
	    } else if (count == BINARY_NOCOUNT) {
		count = 1;
	    }
	    arg++;
	    if (cmd == 'a' || cmd == 'A') {
		offset += count;
	    } else if (cmd == 'b' || cmd == 'B') {
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128

1129
1130
1131

1132
1133
1134
1135
1136
1137

1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153

1154
1155
1156
1157
1158
1159
1160
1161

1162
1163
1164
1165
1166
1167
1168
949
950
951
952
953
954
955

956
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
1016
1017
1018
1019
1020
1021
1022

1023
1024
1025
1026
1027
1028
1029
1030

1031
1032
1033
1034
1035
1036
1037
1038







-
+






-
+
-


-



-
+





+
+
+
+
+


















-
+


-
+





-
+















-
+







-
+







	     * non-list value.
	     */

	    if (count == BINARY_NOCOUNT) {
		arg++;
		count = 1;
	    } else {
		int listc;
		Tcl_Size listc;
		Tcl_Obj **listv;

		/*
		 * The macro evals its args more than once: avoid arg++
		 */

		if (TclListObjGetElements(interp, objv[arg], &listc,
		if (TclListObjLength(interp, objv[arg], &listc) != TCL_OK) {
			&listv) != TCL_OK) {
		    return TCL_ERROR;
		}
		arg++;

		if (count == BINARY_ALL) {
		    count = listc;
		} else if (count > (size_t)listc) {
		} else if (count > listc) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "number of elements in list does not match count",
			    -1));
		    return TCL_ERROR;
		}
		if (TclListObjGetElements(interp, objv[arg], &listc,
			&listv) != TCL_OK) {
		    return TCL_ERROR;
		}
		arg++;
	    }
	    offset += count*size;
	    break;

	case 'x':
	    if (count == BINARY_ALL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"cannot use \"*\" in format string with \"x\"", -1));
		return TCL_ERROR;
	    } else if (count == BINARY_NOCOUNT) {
		count = 1;
	    }
	    offset += count;
	    break;
	case 'X':
	    if (count == BINARY_NOCOUNT) {
		count = 1;
	    }
	    if ((count > (size_t)offset) || (count == BINARY_ALL)) {
	    if ((count > offset) || (count == BINARY_ALL)) {
		count = offset;
	    }
	    if (offset > (int)length) {
	    if (offset > length) {
		length = offset;
	    }
	    offset -= count;
	    break;
	case '@':
	    if (offset > (int)length) {
	    if (offset > length) {
		length = offset;
	    }
	    if (count == BINARY_ALL) {
		offset = length;
	    } else if (count == BINARY_NOCOUNT) {
		goto badCount;
	    } else {
		offset = count;
	    }
	    break;
	default:
	    errorString = str;
	    goto badField;
	}
    }
    if (offset > (int)length) {
    if (offset > length) {
	length = offset;
    }
    if (length == 0) {
	return TCL_OK;
    }

    /*
     * Prepare the result object by preallocating the caclulated number of
     * Prepare the result object by preallocating the calculated number of
     * bytes and filling with nulls.
     */

    TclNewObj(resultPtr);
    buffer = Tcl_SetByteArrayLength(resultPtr, length);
    memset(buffer, 0, length);

1188
1189
1190
1191
1192
1193
1194

1195
1196
1197


1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209

1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
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
1116

1117
1118
1119
1120
1121
1122
1123
1124







+

-
-
+
+












+




















-
+














-
+







	    continue;
	}
	switch (cmd) {
	case 'a':
	case 'A': {
	    char pad = (char) (cmd == 'a' ? '\0' : ' ');
	    unsigned char *bytes;
	    Tcl_Obj *copy = TclNarrowToBytes(objv[arg++]);

	    bytes = TclGetByteArrayFromObj(objv[arg], &length);
	    arg++;
	    bytes = Tcl_GetBytesFromObj(NULL, copy, &length);

	    if (count == BINARY_ALL) {
		count = length;
	    } else if (count == BINARY_NOCOUNT) {
		count = 1;
	    }
	    if (length >= count) {
		memcpy(cursor, bytes, count);
	    } else {
		memcpy(cursor, bytes, length);
		memset(cursor + length, pad, count - length);
	    }
	    cursor += count;
	    Tcl_DecrRefCount(copy);
	    break;
	}
	case 'b':
	case 'B': {
	    unsigned char *last;

	    str = TclGetStringFromObj(objv[arg], &length);
	    arg++;
	    if (count == BINARY_ALL) {
		count = length;
	    } else if (count == BINARY_NOCOUNT) {
		count = 1;
	    }
	    last = cursor + ((count + 7) / 8);
	    if (count > length) {
		count = length;
	    }
	    value = 0;
	    errorString = "binary";
	    if (cmd == 'B') {
		for (offset = 0; (size_t)offset < count; offset++) {
		for (offset = 0; offset < count; offset++) {
		    value <<= 1;
		    if (str[offset] == '1') {
			value |= 1;
		    } else if (str[offset] != '0') {
			errorValue = str;
			Tcl_DecrRefCount(resultPtr);
			goto badValue;
		    }
		    if (((offset + 1) % 8) == 0) {
			*cursor++ = UCHAR(value);
			value = 0;
		    }
		}
	    } else {
		for (offset = 0; (size_t)offset < count; offset++) {
		for (offset = 0; offset < count; offset++) {
		    value >>= 1;
		    if (str[offset] == '1') {
			value |= 128;
		    } else if (str[offset] != '0') {
			errorValue = str;
			Tcl_DecrRefCount(resultPtr);
			goto badValue;
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
1157
1158
1159
1160
1161
1162
1163

1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184

1185
1186
1187
1188
1189
1190
1191
1192







-
+




















-
+







	    last = cursor + ((count + 1) / 2);
	    if (count > length) {
		count = length;
	    }
	    value = 0;
	    errorString = "hexadecimal";
	    if (cmd == 'H') {
		for (offset = 0; (size_t)offset < count; offset++) {
		for (offset = 0; offset < count; offset++) {
		    value <<= 4;
		    if (!isxdigit(UCHAR(str[offset]))) {     /* INTL: digit */
			errorValue = str;
			Tcl_DecrRefCount(resultPtr);
			goto badValue;
		    }
		    c = str[offset] - '0';
		    if (c > 9) {
			c += ('0' - 'A') + 10;
		    }
		    if (c > 16) {
			c += ('A' - 'a');
		    }
		    value |= (c & 0xF);
		    if (offset % 2) {
			*cursor++ = (char) value;
			value = 0;
		    }
		}
	    } else {
		for (offset = 0; (size_t)offset < count; offset++) {
		for (offset = 0; offset < count; offset++) {
		    value >>= 4;

		    if (!isxdigit(UCHAR(str[offset]))) {     /* INTL: digit */
			errorValue = str;
			Tcl_DecrRefCount(resultPtr);
			goto badValue;
		    }
1358
1359
1360
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
1387
1388
1389
1390
1391
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







-
+


















-
+







	case 'W':
	case 'r':
	case 'R':
	case 'd':
	case 'q':
	case 'Q':
	case 'f': {
	    int listc, i;
	    Tcl_Size listc, i;
	    Tcl_Obj **listv;

	    if (count == BINARY_NOCOUNT) {
		/*
		 * Note that we are casting away the const-ness of objv, but
		 * this is safe since we aren't going to modify the array.
		 */

		listv = (Tcl_Obj **) (objv + arg);
		listc = 1;
		count = 1;
	    } else {
		TclListObjGetElements(interp, objv[arg], &listc, &listv);
		if (count == BINARY_ALL) {
		    count = listc;
		}
	    }
	    arg++;
	    for (i = 0; (size_t)i < count; i++) {
	    for (i = 0; i < count; i++) {
		if (FormatNumber(interp, cmd, listv[i], &cursor) != TCL_OK) {
		    Tcl_DecrRefCount(resultPtr);
		    return TCL_ERROR;
		}
	    }
	    break;
	}
1399
1400
1401
1402
1403
1404
1405
1406

1407
1408
1409
1410
1411
1412
1413
1271
1272
1273
1274
1275
1276
1277

1278
1279
1280
1281
1282
1283
1284
1285







-
+







	case 'X':
	    if (cursor > maxPos) {
		maxPos = cursor;
	    }
	    if (count == BINARY_NOCOUNT) {
		count = 1;
	    }
	    if ((count == BINARY_ALL) || (count > (size_t)(cursor - buffer))) {
	    if ((count == BINARY_ALL) || (count > (cursor - buffer))) {
		cursor = buffer;
	    } else {
		cursor -= count;
	    }
	    break;
	case '@':
	    if (cursor > maxPos) {
1468
1469
1470
1471
1472
1473
1474
1475

1476
1477

1478
1479
1480
1481
1482
1483
1484
1485
1486

1487
1488
1489
1490
1491
1492
1493
1494
1495

1496
1497
1498
1499
1500
1501
1502
1503
1504
1505




1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520

1521

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

1535
1536
1537
1538
1539
1540
1541
1542

1543

1544
1545
1546








1547
1548
1549
1550
1551
1552
1553
1340
1341
1342
1343
1344
1345
1346

1347
1348

1349
1350
1351
1352
1353
1354
1355
1356
1357

1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395

1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408

1409
1410
1411
1412
1413
1414
1415
1416
1417
1418

1419
1420
1421

1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436







-
+

-
+








-
+








-
+
-









+
+
+
+



-











+
-
+












-
+








+
-
+


-
+
+
+
+
+
+
+
+







 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
static int
BinaryScanCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int arg;			/* Index of next argument to consume. */
    int value = 0;		/* Current integer value to be packed.
				 * Initialized to avoid compiler warning. */
    char cmd;			/* Current format character. */
    size_t count;			/* Count associated with current format
    Tcl_Size count;		/* Count associated with current format
				 * character. */
    int flags;			/* Format field flags */
    const char *format;		/* Pointer to current position in format
				 * string. */
    Tcl_Obj *resultPtr = NULL;	/* Object holding result buffer. */
    unsigned char *buffer;	/* Start of result buffer. */
    const char *errorString;
    const char *str;
    int offset, size, i;
    Tcl_Size offset, size, length = 0, i;
    size_t length = 0;

    Tcl_Obj *valuePtr, *elementPtr;
    Tcl_HashTable numberCacheHash;
    Tcl_HashTable *numberCachePtr;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"value formatString ?varName ...?");
	return TCL_ERROR;
    }
    buffer = Tcl_GetBytesFromObj(interp, objv[1], &length);
    if (buffer == NULL) {
	return TCL_ERROR;
    }
    numberCachePtr = &numberCacheHash;
    Tcl_InitHashTable(numberCachePtr, TCL_ONE_WORD_KEYS);
    buffer = TclGetByteArrayFromObj(objv[1], &length);
    format = TclGetString(objv[2]);
    arg = 3;
    offset = 0;
    while (*format != '\0') {
	str = format;
	flags = 0;
	if (!GetFormatSpec(&format, &cmd, &count, &flags)) {
	    goto done;
	}
	switch (cmd) {
	case 'a':
	case 'A':
	case 'A': {
	case 'C': {
	    unsigned char *src;

	    if (arg >= objc) {
		DeleteScanNumberCache(numberCachePtr);
		goto badIndex;
	    }
	    if (count == BINARY_ALL) {
		count = length - offset;
	    } else {
		if (count == BINARY_NOCOUNT) {
		    count = 1;
		}
		if (count > length - offset) {
		if (count > (length - offset)) {
		    goto done;
		}
	    }

	    src = buffer + offset;
	    size = count;

	    /*
	     * Apply C string semantics or trim trailing
	     * Trim trailing nulls and spaces, if necessary.
	     * nulls and spaces, if necessary.
	     */

	    if (cmd == 'A') {
	    if (cmd == 'C') {
		for (i = 0; i < size; i++) {
		    if (src[i] == '\0') {
			size = i;
			break;
		    }
		}
	    } else if (cmd == 'A') {
		while (size > 0) {
		    if (src[size - 1] != '\0' && src[size - 1] != ' ') {
			break;
		    }
		    size--;
		}
	    }
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
1469
1470
1471
1472
1473
1474
1475

1476
1477
1478
1479
1480
1481
1482
1483
1484
1485

1486
1487
1488
1489
1490
1491
1492
1493
1494

1495
1496
1497
1498
1499
1500
1501
1502







-
+









-
+








-
+







	    }
	    if (count == BINARY_ALL) {
		count = (length - offset) * 8;
	    } else {
		if (count == BINARY_NOCOUNT) {
		    count = 1;
		}
		if (count > (size_t)(length - offset) * 8) {
		if (count > (length - offset) * 8) {
		    goto done;
		}
	    }
	    src = buffer + offset;
	    TclNewObj(valuePtr);
	    Tcl_SetObjLength(valuePtr, count);
	    dest = TclGetString(valuePtr);

	    if (cmd == 'b') {
		for (i = 0; (size_t)i < count; i++) {
		for (i = 0; i < count; i++) {
		    if (i % 8) {
			value >>= 1;
		    } else {
			value = *src++;
		    }
		    *dest++ = (char) ((value & 1) ? '1' : '0');
		}
	    } else {
		for (i = 0; (size_t)i < count; i++) {
		for (i = 0; i < count; i++) {
		    if (i % 8) {
			value <<= 1;
		    } else {
			value = *src++;
		    }
		    *dest++ = (char) ((value & 0x80) ? '1' : '0');
		}
1651
1652
1653
1654
1655
1656
1657
1658

1659
1660
1661
1662
1663
1664
1665
1666
1667

1668
1669
1670
1671
1672
1673
1674
1534
1535
1536
1537
1538
1539
1540

1541
1542
1543
1544
1545
1546
1547
1548
1549

1550
1551
1552
1553
1554
1555
1556
1557







-
+








-
+







	    }
	    src = buffer + offset;
	    TclNewObj(valuePtr);
	    Tcl_SetObjLength(valuePtr, count);
	    dest = TclGetString(valuePtr);

	    if (cmd == 'h') {
		for (i = 0; (size_t)i < count; i++) {
		for (i = 0; i < count; i++) {
		    if (i % 2) {
			value >>= 4;
		    } else {
			value = *src++;
		    }
		    *dest++ = hexdigit[value & 0xF];
		}
	    } else {
		for (i = 0; (size_t)i < count; i++) {
		for (i = 0; i < count; i++) {
		    if (i % 2) {
			value <<= 4;
		    } else {
			value = *src++;
		    }
		    *dest++ = hexdigit[(value >> 4) & 0xF];
		}
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760

1761
1762
1763
1764
1765
1766
1767
1768
1769
1770

1771
1772
1773
1774
1775
1776
1777
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







-
+














-
+




















-
+









-
+








	scanNumber:
	    if (arg >= objc) {
		DeleteScanNumberCache(numberCachePtr);
		goto badIndex;
	    }
	    if (count == BINARY_NOCOUNT) {
		if ((length - offset) < (size_t)size) {
		if (length < (size + offset)) {
		    goto done;
		}
		valuePtr = ScanNumber(buffer+offset, cmd, flags,
			&numberCachePtr);
		offset += size;
	    } else {
		if (count == BINARY_ALL) {
		    count = (length - offset) / size;
		}
		if ((length - offset) < (count * size)) {
		    goto done;
		}
		TclNewObj(valuePtr);
		src = buffer + offset;
		for (i = 0; (size_t)i < count; i++) {
		for (i = 0; i < count; i++) {
		    elementPtr = ScanNumber(src, cmd, flags, &numberCachePtr);
		    src += size;
		    Tcl_ListObjAppendElement(NULL, valuePtr, elementPtr);
		}
		offset += count * size;
	    }

	    resultPtr = Tcl_ObjSetVar2(interp, objv[arg], NULL, valuePtr,
		    TCL_LEAVE_ERR_MSG);
	    arg++;
	    if (resultPtr == NULL) {
		DeleteScanNumberCache(numberCachePtr);
		return TCL_ERROR;
	    }
	    break;
	}
	case 'x':
	    if (count == BINARY_NOCOUNT) {
		count = 1;
	    }
	    if ((count == BINARY_ALL) || (count > length - offset)) {
	    if ((count == BINARY_ALL) || (count > (length - offset))) {
		offset = length;
	    } else {
		offset += count;
	    }
	    break;
	case 'X':
	    if (count == BINARY_NOCOUNT) {
		count = 1;
	    }
	    if ((count == BINARY_ALL) || (count > (size_t)offset)) {
	    if ((count == BINARY_ALL) || (count > offset)) {
		offset = 0;
	    } else {
		offset -= count;
	    }
	    break;
	case '@':
	    if (count == BINARY_NOCOUNT) {
1847
1848
1849
1850
1851
1852
1853
1854

1855
1856
1857
1858
1859
1860
1861
1730
1731
1732
1733
1734
1735
1736

1737
1738
1739
1740
1741
1742
1743
1744







-
+







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

static int
GetFormatSpec(
    const char **formatPtr,	/* Pointer to format string. */
    char *cmdPtr,		/* Pointer to location of command char. */
    size_t *countPtr,		/* Pointer to repeat count value. */
    Tcl_Size *countPtr,		/* Pointer to repeat count value. */
    int *flagsPtr)		/* Pointer to field flags */
{
    /*
     * Skip any leading blanks.
     */

    while (**formatPtr == ' ') {
1880
1881
1882
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
1763
1764
1765
1766
1767
1768
1769

1770
1771
1772



1773
1774
1775
1776

1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791

1792
1793
1794
1795
1796
1797
1798
1799







-
+


-
-
-
+
+
+

-
+














-
+







	(*formatPtr)++;
	*flagsPtr |= BINARY_UNSIGNED;
    }
    if (**formatPtr == '*') {
	(*formatPtr)++;
	*countPtr = BINARY_ALL;
    } else if (isdigit(UCHAR(**formatPtr))) { /* INTL: digit */
	unsigned long int count;
	unsigned long long count;

	errno = 0;
	count = strtoul(*formatPtr, (char **) formatPtr, 10);
	if (errno || (count > (unsigned long) INT_MAX)) {
	    *countPtr = INT_MAX;
	count = strtoull(*formatPtr, (char **) formatPtr, 10);
	if (errno || (count > TCL_SIZE_MAX)) {
	    *countPtr = TCL_SIZE_MAX;
	} else {
	    *countPtr = (int) count;
	    *countPtr = count;
	}
    } else {
	*countPtr = BINARY_NOCOUNT;
    }
    return 1;
}

/*
 *----------------------------------------------------------------------
 *
 * NeedReversing --
 *
 *	This routine determines, if bytes of a number need to be re-ordered,
 *	and returns a numeric code indicating the re-ordering to be done.
 *	This depends on the endiannes of the machine and the desired format.
 *	This depends on the endianness of the machine and the desired format.
 *	It is in effect a table (whose contents depend on the endianness of
 *	the system) describing whether a value needs reversing or not. Anyone
 *	porting the code to a big-endian platform should take care to make
 *	sure that they define WORDS_BIGENDIAN though this is already done by
 *	configure for the Unix build; little-endian platforms (including
 *	Windows) don't need to do anything.
 *
2115
2116
2117
2118
2119
2120
2121
2122

2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142

2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156



2157

2158
2159
2160
2161
2162
2163
2164
1998
1999
2000
2001
2002
2003
2004

2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024

2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051







-
+



















-
+














+
+
+

+







	/*
	 * Double-precision floating point values. Tcl_GetDoubleFromObj
	 * returns TCL_ERROR for NaN, but we can check by comparing the
	 * object's type pointer.
	 */

	if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) {
	    const Tcl_ObjIntRep *irPtr = TclFetchIntRep(src, &tclDoubleType);
	    const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(src, &tclDoubleType);
	    if (irPtr == NULL) {
		return TCL_ERROR;
	    }
	    dvalue = irPtr->doubleValue;
	}
	CopyNumber(&dvalue, *cursorPtr, sizeof(double), type);
	*cursorPtr += sizeof(double);
	return TCL_OK;

    case 'f':
    case 'r':
    case 'R':
	/*
	 * Single-precision floating point values. Tcl_GetDoubleFromObj
	 * returns TCL_ERROR for NaN, but we can check by comparing the
	 * object's type pointer.
	 */

	if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) {
	    const Tcl_ObjIntRep *irPtr = TclFetchIntRep(src, &tclDoubleType);
	    const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(src, &tclDoubleType);

	    if (irPtr == NULL) {
		return TCL_ERROR;
	    }
	    dvalue = irPtr->doubleValue;
	}

	/*
	 * Because some compilers will generate floating point exceptions on
	 * an overflow cast (e.g. Borland), we restrict the values to the
	 * valid range for float.
	 */

	if (fabs(dvalue) > (double) FLT_MAX) {
	    if (fabs(dvalue) > (FLT_MAX + pow(2, (FLT_MAX_EXP - FLT_MANT_DIG - 1)))) {
		fvalue = (dvalue >= 0.0) ? INFINITY : -INFINITY;	// c99
	    } else {
	    fvalue = (dvalue >= 0.0) ? FLT_MAX : -FLT_MAX;
	    }
	} else {
	    fvalue = (float) dvalue;
	}
	CopyNumber(&fvalue, *cursorPtr, sizeof(float), type);
	*cursorPtr += sizeof(float);
	return TCL_OK;

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
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







-
+




-
+













-
-
-
+
+
+







    case 'i':
    case 'I':
    case 'n':
	if (NeedReversing(type)) {
	    value = (long) (buffer[0]
		    + (buffer[1] << 8)
		    + (buffer[2] << 16)
		    + (((long)buffer[3]) << 24));
		    + (((unsigned long)buffer[3]) << 24));
	} else {
	    value = (long) (buffer[3]
		    + (buffer[2] << 8)
		    + (buffer[1] << 16)
		    + (((long) buffer[0]) << 24));
		    + (((unsigned long) buffer[0]) << 24));
	}

	/*
	 * Check to see if the value was sign extended properly on systems
	 * where an int is more than 32-bits.
	 *
	 * We avoid caching unsigned integers as we cannot distinguish between
	 * 32bit signed and unsigned in the hash (short and char are ok).
	 */

	if (flags & BINARY_UNSIGNED) {
	    return Tcl_NewWideIntObj((Tcl_WideInt)(unsigned long)value);
	}
	if ((value & (((unsigned) 1) << 31)) && (value > 0)) {
	    value -= (((unsigned) 1) << 31);
	    value -= (((unsigned) 1) << 31);
	if ((value & (1U << 31)) && (value > 0)) {
	    value -= (1U << 31);
	    value -= (1U << 31);
	}

    returnNumericObject:
	if (*numberCachePtrPtr == NULL) {
	    return Tcl_NewWideIntObj(value);
	} else {
	    Tcl_HashTable *tablePtr = *numberCachePtrPtr;
2508
2509
2510
2511
2512
2513
2514
2515

2516
2517
2518
2519
2520
2521
2522
2395
2396
2397
2398
2399
2400
2401

2402
2403
2404
2405
2406
2407
2408
2409







-
+







}

/*
 * ----------------------------------------------------------------------
 *
 * NOTES --
 *
 *	Some measurements show that it is faster to use a table to to perform
 *	Some measurements show that it is faster to use a table to perform
 *	uuencode and base64 value encoding than to calculate the output (at
 *	least on intel P4 arch).
 *
 *	Conversely using a lookup table for the decoding is slower than just
 *	calculating the values. We therefore use the fastest of each method.
 *
 *	Presumably this has to do with the size of the tables. The base64
2539
2540
2541
2542
2543
2544
2545
2546

2547
2548
2549
2550
2551
2552
2553
2554

2555
2556
2557
2558
2559
2560





2561
2562
2563
2564
2565
2566
2567
2568
2569
2426
2427
2428
2429
2430
2431
2432

2433
2434
2435
2436
2437
2438
2439
2440

2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453

2454
2455
2456
2457
2458
2459
2460







-
+







-
+






+
+
+
+
+

-







 *	None
 *
 *----------------------------------------------------------------------
 */

static int
BinaryEncodeHex(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *resultObj = NULL;
    unsigned char *data = NULL;
    unsigned char *cursor = NULL;
    size_t offset = 0, count = 0;
    Tcl_Size offset = 0, count = 0;

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

    data = Tcl_GetBytesFromObj(interp, objv[1], &count);
    if (data == NULL) {
	return TCL_ERROR;
    }

    TclNewObj(resultObj);
    data = TclGetByteArrayFromObj(objv[1], &count);
    cursor = Tcl_SetByteArrayLength(resultObj, count * 2);
    for (offset = 0; offset < count; ++offset) {
	*cursor++ = HexDigits[(data[offset] >> 4) & 0x0F];
	*cursor++ = HexDigits[data[offset] & 0x0F];
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
2583
2584
2585
2586
2587
2588
2589
2590

2591
2592
2593
2594
2595
2596
2597
2598
2599

2600
2601
2602
2603
2604
2605
2606
2474
2475
2476
2477
2478
2479
2480

2481
2482
2483
2484
2485
2486
2487
2488
2489

2490
2491
2492
2493
2494
2495
2496
2497







-
+








-
+







 *	None
 *
 *----------------------------------------------------------------------
 */

static int
BinaryDecodeHex(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *resultObj = NULL;
    unsigned char *data, *datastart, *dataend;
    unsigned char *begin, *cursor, c;
    int i, index, value, pure = 1, strict = 0;
    size_t size, cut = 0, count = 0;
    Tcl_Size size, cut = 0, count = 0;
    int ucs4;
    enum {OPT_STRICT };
    static const char *const optStrings[] = { "-strict", NULL };

    if (objc < 2 || objc > 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "?options? data");
	return TCL_ERROR;
2614
2615
2616
2617
2618
2619
2620
2621

2622
2623
2624

2625
2626
2627
2628
2629
2630
2631
2505
2506
2507
2508
2509
2510
2511

2512
2513
2514

2515
2516
2517
2518
2519
2520
2521
2522







-
+


-
+







	case OPT_STRICT:
	    strict = 1;
	    break;
	}
    }

    TclNewObj(resultObj);
    data = TclGetBytesFromObj(NULL, objv[objc - 1], &count);
    data = Tcl_GetBytesFromObj(NULL, objv[objc - 1], &count);
    if (data == NULL) {
	pure = 0;
	data = (unsigned char *) TclGetStringFromObj(objv[objc - 1], &count);
	data = (unsigned char *)TclGetStringFromObj(objv[objc - 1], &count);
    }
    datastart = data;
    dataend = data + count;
    size = (count + 1) / 2;
    begin = cursor = Tcl_SetByteArrayLength(resultObj, size);
    while (data < dataend) {
	value = 0;
2667
2668
2669
2670
2671
2672
2673
2674

2675
2676
2677
2678
2679
2680

2681
2682
2683
2684
2685
2686
2687
2558
2559
2560
2561
2562
2563
2564

2565
2566
2567
2568
2569
2570

2571
2572
2573
2574
2575
2576
2577
2578







-
+





-
+







    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;

  badChar:
    if (pure) {
	ucs4 = c;
    } else {
	TclUtfToUCS4((const char *)(data - 1), &ucs4);
	TclUtfToUniChar((const char *)(data - 1), &ucs4);
    }
    TclDecrRefCount(resultObj);
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "invalid hexadecimal digit \"%c\" (U+%06X) at position %"
	    TCL_Z_MODIFIER "u", ucs4, ucs4, data - datastart - 1));
    Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "INVALID", NULL);
    Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "INVALID", (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * BinaryEncode64 --
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
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







-
+






-
+

-
-
-
+
+
+















-
+






-
+




-
+












+
+
+
+

-







	if (cursor > limit) {				\
	    Tcl_Panic("limit hit");			\
	}						\
    } while (0)

static int
BinaryEncode64(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *resultObj;
    unsigned char *data, *limit;
    int maxlen = 0;
    Tcl_WideInt maxlen = 0;
    const char *wrapchar = "\n";
    size_t wrapcharlen = 1;
    int i, index, size, outindex = 0, purewrap = 1;
    size_t offset, count = 0;
    Tcl_Size wrapcharlen = 1;
    int index, purewrap = 1;
    Tcl_Size i, offset, size, outindex = 0, count = 0;
    enum { OPT_MAXLEN, OPT_WRAPCHAR };
    static const char *const optStrings[] = { "-maxlen", "-wrapchar", NULL };

    if (objc < 2 || objc % 2 != 0) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"?-maxlen len? ?-wrapchar char? data");
	return TCL_ERROR;
    }
    for (i = 1; i < objc - 1; i += 2) {
	if (Tcl_GetIndexFromObj(interp, objv[i], optStrings, "option",
		TCL_EXACT, &index) != TCL_OK) {
	    return TCL_ERROR;
	}
	switch (index) {
	case OPT_MAXLEN:
	    if (Tcl_GetIntFromObj(interp, objv[i + 1], &maxlen) != TCL_OK) {
	    if (TclGetWideIntFromObj(interp, objv[i + 1], &maxlen) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (maxlen < 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"line length out of range", -1));
		Tcl_SetErrorCode(interp, "TCL", "BINARY", "ENCODE",
			"LINE_LENGTH", NULL);
			"LINE_LENGTH", (char *)NULL);
		return TCL_ERROR;
	    }
	    break;
	case OPT_WRAPCHAR:
	    wrapchar = (const char *)TclGetBytesFromObj(NULL,
	    wrapchar = (const char *)Tcl_GetBytesFromObj(NULL,
		    objv[i + 1], &wrapcharlen);
	    if (wrapchar == NULL) {
		purewrap = 0;
		wrapchar = TclGetStringFromObj(objv[i + 1], &wrapcharlen);
	    }
	    break;
	}
    }
    if (wrapcharlen == 0) {
	maxlen = 0;
    }

    data = Tcl_GetBytesFromObj(interp, objv[objc - 1], &count);
    if (data == NULL) {
	return TCL_ERROR;
    }
    TclNewObj(resultObj);
    data = TclGetByteArrayFromObj(objv[objc - 1], &count);
    if (count > 0) {
	unsigned char *cursor = NULL;

	size = (((count * 4) / 3) + 3) & ~3;	/* ensure 4 byte chunks */
	if (maxlen > 0 && size > maxlen) {
	    int adjusted = size + (wrapcharlen * (size / maxlen));

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
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







-
+






-
+
+



-
+







 *	None
 *
 *----------------------------------------------------------------------
 */

static int
BinaryEncodeUu(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *resultObj;
    unsigned char *data, *start, *cursor;
    int rawLength, n, i, bits, index;
    int i, bits, index;
    unsigned int n;
    int lineLength = 61;
    const unsigned char SingleNewline[] = { UCHAR('\n') };
    const unsigned char *wrapchar = SingleNewline;
    size_t j, offset, count = 0, wrapcharlen = sizeof(SingleNewline);
    Tcl_Size j, rawLength, offset, count = 0, wrapcharlen = sizeof(SingleNewline);
    enum { OPT_MAXLEN, OPT_WRAPCHAR };
    static const char *const optStrings[] = { "-maxlen", "-wrapchar", NULL };

    if (objc < 2 || objc % 2 != 0) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"?-maxlen len? ?-wrapchar char? data");
	return TCL_ERROR;
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
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







-
+





-
+



-
+


















-
+
















-

-
+
+
+
+
+














-
+







		    &lineLength) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (lineLength < 5 || lineLength > 85) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"line length out of range", -1));
		Tcl_SetErrorCode(interp, "TCL", "BINARY", "ENCODE",
			"LINE_LENGTH", NULL);
			"LINE_LENGTH", (char *)NULL);
		return TCL_ERROR;
	    }
	    lineLength = ((lineLength - 1) & -4) + 1; /* 5, 9, 13 ... */
	    break;
	case OPT_WRAPCHAR:
	    wrapchar = (const unsigned char *) TclGetStringFromObj(
	    wrapchar = (const unsigned char *)TclGetStringFromObj(
		    objv[i + 1], &wrapcharlen);
	    {
		const unsigned char *p = wrapchar;
		size_t numBytes = wrapcharlen;
		Tcl_Size numBytes = wrapcharlen;

		while (numBytes) {
		    switch (*p) {
			case '\t':
			case '\v':
			case '\f':
			case '\r':
			    p++; numBytes--;
			    continue;
			case '\n':
			    numBytes--;
			    break;
			default:
			badwrap:
			    Tcl_SetObjResult(interp, Tcl_NewStringObj(
				    "invalid wrapchar; will defeat decoding",
				    -1));
			    Tcl_SetErrorCode(interp, "TCL", "BINARY",
				    "ENCODE", "WRAPCHAR", NULL);
				    "ENCODE", "WRAPCHAR", (char *)NULL);
			    return TCL_ERROR;
		    }
		}
		if (numBytes) {
		    goto badwrap;
		}
	    }
	    break;
	}
    }

    /*
     * Allocate the buffer. This is a little bit too long, but is "good
     * enough".
     */

    TclNewObj(resultObj);
    offset = 0;
    data = TclGetByteArrayFromObj(objv[objc - 1], &count);
    data = Tcl_GetBytesFromObj(interp, objv[objc - 1], &count);
    if (data == NULL) {
	return TCL_ERROR;
    }
    TclNewObj(resultObj);
    rawLength = (lineLength - 1) * 3 / 4;
    start = cursor = Tcl_SetByteArrayLength(resultObj,
	    (lineLength + wrapcharlen) *
	    ((count + (rawLength - 1)) / rawLength));
    n = bits = 0;

    /*
     * Encode the data. Each output line first has the length of raw data
     * encoded by the output line described in it by one encoded byte, then
     * the encoded data follows (encoding each 6 bits as one character).
     * Encoded lines are always terminated by a newline.
     */

    while (offset < count) {
	int lineLen = count - offset;
	Tcl_Size lineLen = count - offset;

	if (lineLen > rawLength) {
	    lineLen = rawLength;
	}
	*cursor++ = UueDigits[lineLen];
	for (i = 0 ; i < lineLen ; i++) {
	    n <<= 8;
2979
2980
2981
2982
2983
2984
2985
2986

2987
2988
2989
2990
2991
2992
2993
2994
2995

2996
2997
2998
2999
3000
3001
3002
2877
2878
2879
2880
2881
2882
2883

2884
2885
2886
2887
2888
2889
2890
2891
2892

2893
2894
2895
2896
2897
2898
2899
2900







-
+








-
+







 *	None
 *
 *----------------------------------------------------------------------
 */

static int
BinaryDecodeUu(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *resultObj = NULL;
    unsigned char *data, *datastart, *dataend;
    unsigned char *begin, *cursor;
    int i, index, pure = 1, strict = 0, lineLen;
    size_t size, count = 0;
    Tcl_Size size, count = 0;
    unsigned char c;
    int ucs4;
    enum { OPT_STRICT };
    static const char *const optStrings[] = { "-strict", NULL };

    if (objc < 2 || objc > 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "?options? data");
3011
3012
3013
3014
3015
3016
3017
3018

3019
3020
3021
3022
3023
3024
3025
2909
2910
2911
2912
2913
2914
2915

2916
2917
2918
2919
2920
2921
2922
2923







-
+







	case OPT_STRICT:
	    strict = 1;
	    break;
	}
    }

    TclNewObj(resultObj);
    data = TclGetBytesFromObj(NULL, objv[objc - 1], &count);
    data = Tcl_GetBytesFromObj(NULL, objv[objc - 1], &count);
    if (data == NULL) {
	pure = 0;
	data = (unsigned char *) TclGetStringFromObj(objv[objc - 1], &count);
    }
    datastart = data;
    dataend = data + count;
    size = ((count + 3) & ~3) * 3 / 4;
3117
3118
3119
3120
3121
3122
3123
3124

3125
3126
3127
3128
3129
3130
3131
3132

3133
3134
3135
3136
3137

3138
3139
3140
3141
3142
3143
3144
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







-
+







-
+




-
+







    }
    Tcl_SetByteArrayLength(resultObj, cursor - begin);
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;

  shortUu:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf("short uuencode data"));
    Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "SHORT", NULL);
    Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "SHORT", (char *)NULL);
    TclDecrRefCount(resultObj);
    return TCL_ERROR;

  badUu:
    if (pure) {
	ucs4 = c;
    } else {
	TclUtfToUCS4((const char *)(data - 1), &ucs4);
	TclUtfToUniChar((const char *)(data - 1), &ucs4);
    }
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "invalid uuencode character \"%c\" (U+%06X) at position %"
	    TCL_Z_MODIFIER "u", ucs4, ucs4, data - datastart - 1));
    Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "INVALID", NULL);
    Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "INVALID", (char *)NULL);
    TclDecrRefCount(resultObj);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
3153
3154
3155
3156
3157
3158
3159
3160

3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171

3172
3173
3174
3175
3176
3177
3178
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







-
+










-
+







 *	None
 *
 *----------------------------------------------------------------------
 */

static int
BinaryDecode64(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *resultObj = NULL;
    unsigned char *data, *datastart, *dataend, c = '\0';
    unsigned char *begin = NULL;
    unsigned char *cursor = NULL;
    int pure = 1, strict = 0;
    int i, index, cut = 0;
    size_t size, count = 0;
    Tcl_Size size, count = 0;
    int ucs4;
    enum { OPT_STRICT };
    static const char *const optStrings[] = { "-strict", NULL };

    if (objc < 2 || objc > 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "?options? data");
	return TCL_ERROR;
3186
3187
3188
3189
3190
3191
3192
3193

3194
3195
3196
3197
3198
3199
3200
3084
3085
3086
3087
3088
3089
3090

3091
3092
3093
3094
3095
3096
3097
3098







-
+







	case OPT_STRICT:
	    strict = 1;
	    break;
	}
    }

    TclNewObj(resultObj);
    data = TclGetBytesFromObj(NULL, objv[objc - 1], &count);
    data = Tcl_GetBytesFromObj(NULL, objv[objc - 1], &count);
    if (data == NULL) {
	pure = 0;
	data = (unsigned char *) TclGetStringFromObj(objv[objc - 1], &count);
    }
    datastart = data;
    dataend = data + count;
    size = ((count + 3) & ~3) * 3 / 4;
3300
3301
3302
3303
3304
3305
3306
3307

3308
3309
3310
3311
3312
3313

3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3198
3199
3200
3201
3202
3203
3204

3205
3206
3207
3208
3209
3210

3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222







-
+





-
+











	ucs4 = c;
    } else {
	/* The decoder is byte-oriented. If we saw a byte that's not a
	 * valid member of the base64 alphabet, it could be the lead byte
	 * of a multi-byte character. */

	/* Safe because we know data is NUL-terminated */
	TclUtfToUCS4((const char *)(data - 1), &ucs4);
	TclUtfToUniChar((const char *)(data - 1), &ucs4);
    }

    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "invalid base64 character \"%c\" (U+%06X) at position %"
	    TCL_Z_MODIFIER "u", ucs4, ucs4, data - datastart - 1));
    Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "INVALID", NULL);
    Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "INVALID", (char *)NULL);
    TclDecrRefCount(resultObj);
    return TCL_ERROR;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclCkalloc.c.

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
30
31
32
33
34
35
36
37
38
39

40
41
42
43
44

45
46
47
48
49
50
51
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
30
31
32
33
34
35
36
37
38
39

40
41
42
43
44

45
46
47
48
49
50
51
52







-
-
-
+
+
+








+




















-
+




-
+







/*
 * tclCkalloc.c --
 *
 *    Interface to malloc and free that provides support for debugging
 *    problems involving overwritten, double freeing memory and loss of
 *    memory.
 *
 * Copyright (c) 1991-1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright © 1991-1994 The Regents of the University of California.
 * Copyright © 1994-1997 Sun Microsystems, Inc.
 * Copyright © 1998-1999 Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * This code contributed by Karl Lehenbauer and Mark Diekhans
 */

#include "tclInt.h"
#include <assert.h>

#define FALSE	0
#define TRUE	1

#undef Tcl_Alloc
#undef Tcl_Free
#undef Tcl_Realloc
#undef Tcl_AttemptAlloc
#undef Tcl_AttemptRealloc

#ifdef TCL_MEM_DEBUG

/*
 * One of the following structures is allocated each time the
 * "memory tag" command is invoked, to hold the current tag.
 */

typedef struct {
    size_t refCount;		/* Number of mem_headers referencing this
				 * tag. */
    char string[1];		/* Actual size of string will be as large as
    char string[TCLFLEXARRAY];	/* Actual size of string will be as large as
				 * needed for actual tag. This must be the
				 * last field in the structure. */
} MemTag;

#define TAG_SIZE(bytesInString) ((offsetof(MemTag, string) + 1) + bytesInString)
#define TAG_SIZE(bytesInString) ((offsetof(MemTag, string) + 1U) + (bytesInString))

static MemTag *curTagPtr = NULL;/* Tag to use in all future mem_headers (set
				 * by "memory tag" command). */

/*
 * One of the following structures is allocated just before each dynamically
 * allocated chunk of memory, both to record information about the chunk and
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
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







-
+





-
+

















-
-
+
+


-
-
-
-
+
+
+
+







    const char *file;
    size_t length;
    int line;
    unsigned char low_guard[LOW_GUARD_SIZE];
				/* Aligns body on 8-byte boundary, plus
				 * provides at least 8 additional guard bytes
				 * to detect underruns. */
    char body[1];		/* First byte of client's space. Actual size
    char body[TCLFLEXARRAY];	/* First byte of client's space. Actual size
				 * of this field will be larger than one. */
};

static struct mem_header *allocHead = NULL;  /* List of allocated structures */

#define GUARD_VALUE  0141
#define GUARD_VALUE  0x61

/*
 * The following macro determines the amount of guard space *above* each chunk
 * of memory.
 */

#define HIGH_GUARD_SIZE 8

/*
 * The following macro computes the offset of the "body" field within
 * mem_header. It is used to get back to the header pointer from the body
 * pointer that's used by clients.
 */

#define BODY_OFFSET \
	((size_t) (&((struct mem_header *) 0)->body))

static unsigned int total_mallocs = 0;
static unsigned int total_frees = 0;
static size_t total_mallocs = 0;
static size_t total_frees = 0;
static size_t current_bytes_malloced = 0;
static size_t maximum_bytes_malloced = 0;
static unsigned int current_malloc_packets = 0;
static unsigned int  maximum_malloc_packets = 0;
static unsigned int break_on_malloc = 0;
static unsigned int trace_on_at_malloc = 0;
static size_t current_malloc_packets = 0;
static size_t  maximum_malloc_packets = 0;
static size_t break_on_malloc = 0;
static size_t trace_on_at_malloc = 0;
static int alloc_tracing = FALSE;
static int init_malloced_bodies = TRUE;
#ifdef MEM_VALIDATE
static int validate_memory = TRUE;
#else
static int validate_memory = FALSE;
#endif
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
124
125
126
127
128
129
130













131
132
133
134
135
136
137







-
-
-
-
-
-
-
-
-
-
-
-
-







 * explicitly initialized. This is necessary because the self initializing
 * mutexes use Tcl_Alloc...
 */

static Tcl_Mutex *ckallocMutexPtr;
static int ckallocInit = 0;

/*
 * Prototypes for procedures defined in this file:
 */

static int		CheckmemCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		MemoryCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static void		ValidateMemory(struct mem_header *memHeaderP,
			    const char *file, int line, int nukeGuards);

/*
 *----------------------------------------------------------------------
 *
 * TclInitDbCkalloc --
 *
 *	Initialize the locks used by the allocator. This is only appropriate
 *	to call in a single threaded environment, such as during
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
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







-
+





-
+

-
-
-
-
+
+
+
+

-
+







 *	Display the global memory management statistics.
 *
 *----------------------------------------------------------------------
 */

int
TclDumpMemoryInfo(
    ClientData clientData,
    void *clientData,
    int flags)
{
    char buf[1024];

    if (clientData == NULL) {
        return 0;
	return 0;
    }
    sprintf(buf,
	    "total mallocs             %10u\n"
	    "total frees               %10u\n"
	    "current packets allocated %10u\n"
    snprintf(buf, sizeof(buf),
	    "total mallocs             %10" TCL_Z_MODIFIER "u\n"
	    "total frees               %10" TCL_Z_MODIFIER "u\n"
	    "current packets allocated %10" TCL_Z_MODIFIER "u\n"
	    "current bytes allocated   %10" TCL_Z_MODIFIER "u\n"
	    "maximum packets allocated %10u\n"
	    "maximum packets allocated %10" TCL_Z_MODIFIER "u\n"
	    "maximum bytes allocated   %10" TCL_Z_MODIFIER "u\n",
	    total_mallocs,
	    total_frees,
	    current_malloc_packets,
	    current_bytes_malloced,
	    maximum_malloc_packets,
	    maximum_bytes_malloced);
259
260
261
262
263
264
265
266

267
268
269
270
271
272
273
247
248
249
250
251
252
253

254
255
256
257
258
259
260
261







-
+







	fprintf(stderr, "%" TCL_Z_MODIFIER "u bytes allocated at (%s %d)\n", memHeaderP->length,
		memHeaderP->file, memHeaderP->line);
	Tcl_Panic("Memory validation failure");
    }

    hiPtr = (unsigned char *)memHeaderP->body + memHeaderP->length;
    for (idx = 0; idx < HIGH_GUARD_SIZE; idx++) {
	byte = *(hiPtr + idx);
	byte = hiPtr[idx];
	if (byte != GUARD_VALUE) {
	    guard_failed = TRUE;
	    fflush(stdout);
	    byte &= 0xFF;
	    fprintf(stderr, "hi guard byte %" TCL_Z_MODIFIER "u is 0x%x  \t%c\n", idx, byte,
		    (isprint(UCHAR(byte)) ? byte : ' ')); /* INTL: bytes */
	}
377
378
379
380
381
382
383
384

385
386
387
388
389
390
391
365
366
367
368
369
370
371

372
373
374
375
376
377
378
379







-
+








/*
 *----------------------------------------------------------------------
 *
 * Tcl_DbCkalloc - debugging Tcl_Alloc
 *
 *	Allocate the requested amount of space plus some extra for guard bands
 *	at both ends of the request, plus a size, panicing if there isn't
 *	at both ends of the request, plus a size, panicking if there isn't
 *	enough space, then write in the guard bands and return the address of
 *	the space in the middle that the user asked for.
 *
 *	The second and third arguments are file and line, these contain the
 *	filename and line number corresponding to the caller. These are sent
 *	by the Tcl_Alloc macro; it uses the preprocessor autodefines __FILE__
 *	and __LINE__.
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
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







-
+

-
+















-
+







    struct mem_header *result = NULL;

    if (validate_memory) {
	Tcl_ValidateAllMemory(file, line);
    }

    /* Don't let size argument to TclpAlloc overflow */
    if (size <= UINT_MAX - HIGH_GUARD_SIZE -sizeof(struct mem_header)) {
    if (size <= (size_t)-2 - offsetof(struct mem_header, body) - HIGH_GUARD_SIZE) {
	result = (struct mem_header *) TclpAlloc(size +
		sizeof(struct mem_header) + HIGH_GUARD_SIZE);
		offsetof(struct mem_header, body) + 1U + HIGH_GUARD_SIZE);
    }
    if (result == NULL) {
	fflush(stdout);
	TclDumpMemoryInfo(stderr, 0);
	Tcl_Panic("unable to alloc %" TCL_Z_MODIFIER "u bytes, %s line %d", size, file, line);
    }

    /*
     * Fill in guard zones and size. Also initialize the contents of the block
     * with bogus bytes to detect uses of initialized data. Link into
     * allocated list.
     */

    if (init_malloced_bodies) {
	memset(result, GUARD_VALUE,
		size + sizeof(struct mem_header) + HIGH_GUARD_SIZE);
		offsetof(struct mem_header, body) + 1U + HIGH_GUARD_SIZE + size);
    } else {
	memset(result->low_guard, GUARD_VALUE, LOW_GUARD_SIZE);
	memset(result->body + size, GUARD_VALUE, HIGH_GUARD_SIZE);
    }
    if (!ckallocInit) {
	TclInitDbCkalloc();
    }
447
448
449
450
451
452
453
454

455
456
457
458
459
460
461
462
463
464
465
466
467
468
469

470
471
472
473
474
475
476
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







-
+














-
+







	allocHead->blink = result;
    }
    allocHead = result;

    total_mallocs++;
    if (trace_on_at_malloc && (total_mallocs >= trace_on_at_malloc)) {
	(void) fflush(stdout);
	fprintf(stderr, "reached malloc trace enable point (%u)\n",
	fprintf(stderr, "reached malloc trace enable point (%" TCL_Z_MODIFIER "u)\n",
		total_mallocs);
	fflush(stderr);
	alloc_tracing = TRUE;
	trace_on_at_malloc = 0;
    }

    if (alloc_tracing) {
	fprintf(stderr,"Tcl_Alloc %p %" TCL_Z_MODIFIER "u %s %d\n",
		result->body, size, file, line);
    }

    if (break_on_malloc && (total_mallocs >= break_on_malloc)) {
	break_on_malloc = 0;
	(void) fflush(stdout);
	Tcl_Panic("reached malloc break limit (%u)", total_mallocs);
	Tcl_Panic("reached malloc break limit (%" TCL_Z_MODIFIER "u)", total_mallocs);
    }

    current_malloc_packets++;
    if (current_malloc_packets > maximum_malloc_packets) {
	maximum_malloc_packets = current_malloc_packets;
    }
    current_bytes_malloced += size;
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
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







-
+

-
+














-
+







    struct mem_header *result = NULL;

    if (validate_memory) {
	Tcl_ValidateAllMemory(file, line);
    }

    /* Don't let size argument to TclpAlloc overflow */
    if (size <= UINT_MAX - HIGH_GUARD_SIZE - sizeof(struct mem_header)) {
    if (size <= (size_t)-2 - offsetof(struct mem_header, body) - HIGH_GUARD_SIZE) {
	result = (struct mem_header *) TclpAlloc(size +
		sizeof(struct mem_header) + HIGH_GUARD_SIZE);
		offsetof(struct mem_header, body) + 1U + HIGH_GUARD_SIZE);
    }
    if (result == NULL) {
	fflush(stdout);
	TclDumpMemoryInfo(stderr, 0);
	return NULL;
    }

    /*
     * Fill in guard zones and size. Also initialize the contents of the block
     * with bogus bytes to detect uses of initialized data. Link into
     * allocated list.
     */
    if (init_malloced_bodies) {
	memset(result, GUARD_VALUE,
		size + sizeof(struct mem_header) + HIGH_GUARD_SIZE);
		offsetof(struct mem_header, body) + 1U + HIGH_GUARD_SIZE + size);
    } else {
	memset(result->low_guard, GUARD_VALUE, LOW_GUARD_SIZE);
	memset(result->body + size, GUARD_VALUE, HIGH_GUARD_SIZE);
    }
    if (!ckallocInit) {
	TclInitDbCkalloc();
    }
536
537
538
539
540
541
542
543

544
545
546
547
548
549
550
551
552
553
554
555
556
557
558

559
560
561
562
563
564
565
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







-
+














-
+







	allocHead->blink = result;
    }
    allocHead = result;

    total_mallocs++;
    if (trace_on_at_malloc && (total_mallocs >= trace_on_at_malloc)) {
	(void) fflush(stdout);
	fprintf(stderr, "reached malloc trace enable point (%d)\n",
	fprintf(stderr, "reached malloc trace enable point (%" TCL_Z_MODIFIER "u)\n",
		total_mallocs);
	fflush(stderr);
	alloc_tracing = TRUE;
	trace_on_at_malloc = 0;
    }

    if (alloc_tracing) {
	fprintf(stderr,"Tcl_Alloc %p %" TCL_Z_MODIFIER "u %s %d\n",
		result->body, size, file, line);
    }

    if (break_on_malloc && (total_mallocs >= break_on_malloc)) {
	break_on_malloc = 0;
	(void) fflush(stdout);
	Tcl_Panic("reached malloc break limit (%d)", total_mallocs);
	Tcl_Panic("reached malloc break limit (%" TCL_Z_MODIFIER "u)", total_mallocs);
    }

    current_malloc_packets++;
    if (current_malloc_packets > maximum_malloc_packets) {
	maximum_malloc_packets = current_malloc_packets;
    }
    current_bytes_malloced += size;
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
715
716
717
718
719
720
721

722
723
724
725
726
727
728







-







    if (newPtr == NULL) {
	return NULL;
    }
    memcpy(newPtr, ptr, copySize);
    Tcl_DbCkfree(ptr, file, line);
    return newPtr;
}


/*
 *----------------------------------------------------------------------
 *
 * Tcl_Alloc, et al. --
 *
 *	These functions are defined in terms of the debugging versions when
806
807
808
809
810
811
812
813

814
815
816
817
818
819
820
793
794
795
796
797
798
799

800
801
802
803
804
805
806
807







-
+







 * Results:
 *	Standard TCL results.
 *
 *----------------------------------------------------------------------
 */
static int
MemoryCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Obj values of arguments. */
{
    const char *fileName;
    FILE *fileP;
    Tcl_DString buffer;
835
836
837
838
839
840
841
842

843
844
845
846
847
848

849
850
851
852

853
854
855

856
857
858
859
860

861
862
863
864
865
866
867
822
823
824
825
826
827
828

829
830
831
832
833
834

835
836
837
838

839
840
841

842
843
844
845
846

847
848
849
850
851
852
853
854







-
+





-
+



-
+


-
+




-
+







	if (fileName == NULL) {
	    return TCL_ERROR;
	}
	result = Tcl_DumpActiveMemory(fileName);
	Tcl_DStringFree(&buffer);
	if (result != TCL_OK) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf("error accessing %s: %s",
                    TclGetString(objv[2]), Tcl_PosixError(interp)));
		    TclGetString(objv[2]), Tcl_PosixError(interp)));
	    return TCL_ERROR;
	}
	return TCL_OK;
    }
    if (strcmp(TclGetString(objv[1]),"break_on_malloc") == 0) {
	int value;
	Tcl_WideInt value;
	if (objc != 3) {
	    goto argError;
	}
	if (Tcl_GetIntFromObj(interp, objv[2], &value) != TCL_OK) {
	if (TclGetWideIntFromObj(interp, objv[2], &value) != TCL_OK) {
	    return TCL_ERROR;
	}
	break_on_malloc = (unsigned int) value;
	break_on_malloc = value;
	return TCL_OK;
    }
    if (strcmp(TclGetString(objv[1]),"info") == 0) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"%-25s %10u\n%-25s %10u\n%-25s %10u\n%-25s %10" TCL_Z_MODIFIER"u\n%-25s %10u\n%-25s %10" TCL_Z_MODIFIER "u\n",
		"%-25s %10" TCL_Z_MODIFIER "u\n%-25s %10" TCL_Z_MODIFIER "u\n%-25s %10" TCL_Z_MODIFIER "u\n%-25s %10" TCL_Z_MODIFIER "u\n%-25s %10" TCL_Z_MODIFIER "u\n%-25s %10" TCL_Z_MODIFIER "u\n",
		"total mallocs", total_mallocs, "total frees", total_frees,
		"current packets allocated", current_malloc_packets,
		"current bytes allocated", current_bytes_malloced,
		"maximum packets allocated", maximum_malloc_packets,
		"maximum bytes allocated", maximum_bytes_malloced));
	return TCL_OK;
    }
880
881
882
883
884
885
886
887
888


889
890
891
892
893
894
895
867
868
869
870
871
872
873


874
875
876
877
878
879
880
881
882







-
-
+
+







	fileName = Tcl_TranslateFileName(interp, TclGetString(objv[2]), &buffer);
	if (fileName == NULL) {
	    return TCL_ERROR;
	}
	fileP = fopen(fileName, "w");
	if (fileP == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "cannot open output file: %s",
                    Tcl_PosixError(interp)));
		    "cannot open output file: %s",
		    Tcl_PosixError(interp)));
	    return TCL_ERROR;
	}
	TclDbDumpActiveObjects(fileP);
	fclose(fileP);
	Tcl_DStringFree(&buffer);
	return TCL_OK;
    }
926
927
928
929
930
931
932
933

934
935
936
937

938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954



955
956
957
958
959
960
961
913
914
915
916
917
918
919

920
921
922
923

924
925
926
927
928
929
930
931
932
933
934
935
936
937
938



939
940
941
942
943
944
945
946
947
948







-
+



-
+














-
-
-
+
+
+







	    goto bad_suboption;
	}
	alloc_tracing = (strcmp(TclGetString(objv[2]),"on") == 0);
	return TCL_OK;
    }

    if (strcmp(TclGetString(objv[1]),"trace_on_at_malloc") == 0) {
	int value;
	Tcl_WideInt value;
	if (objc != 3) {
	    goto argError;
	}
	if (Tcl_GetIntFromObj(interp, objv[2], &value) != TCL_OK) {
	if (TclGetWideIntFromObj(interp, objv[2], &value) != TCL_OK) {
	    return TCL_ERROR;
	}
	trace_on_at_malloc = value;
	return TCL_OK;
    }
    if (strcmp(TclGetString(objv[1]),"validate") == 0) {
	if (objc != 3) {
	    goto bad_suboption;
	}
	validate_memory = (strcmp(TclGetString(objv[2]),"on") == 0);
	return TCL_OK;
    }

    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
            "bad option \"%s\": should be active, break_on_malloc, info, "
            "init, objs, onexit, tag, trace, trace_on_at_malloc, or validate",
            TclGetString(objv[1])));
	    "bad option \"%s\": should be active, break_on_malloc, info, "
	    "init, objs, onexit, tag, trace, trace_on_at_malloc, or validate",
	    TclGetString(objv[1])));
    return TCL_ERROR;

  argError:
    Tcl_WrongNumArgs(interp, 2, objv, "count");
    return TCL_ERROR;

  bad_suboption:
976
977
978
979
980
981
982
983
984
985
986
987
988
989

990
991
992
993
994
995
996
963
964
965
966
967
968
969




970
971

972
973
974
975
976
977
978
979







-
-
-
-


-
+







 *	Returns a standard Tcl completion code.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
static int		CheckmemCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);

static int
CheckmemCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Interpreter for evaluation. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Obj values of arguments. */
{
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "fileName");
	return TCL_ERROR;
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1005
1006
1007
1008
1009
1010
1011

1012
1013
1014
1015
1016
1017
1018

1019
1020
1021
1022
1023
1024
1025







-







-







				 * added */
{
    TclInitDbCkalloc();
    Tcl_CreateObjCommand(interp, "memory", MemoryCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "checkmem", CheckmemCmd, NULL, NULL);
}


#else	/* TCL_MEM_DEBUG */

/* This is the !TCL_MEM_DEBUG case */

#undef Tcl_InitMemory
#undef Tcl_DumpActiveMemory
#undef Tcl_ValidateAllMemory


/*
 *----------------------------------------------------------------------
 *
 * Tcl_Alloc --
 *
 *	Interface to TclpAlloc when TCL_MEM_DEBUG is disabled. It does check
1238
1239
1240
1241
1242
1243
1244
1245

1246
1247
1248
1249
1250
1251














































































































































1252
1253
1254
1255
1256
1257
1258
1219
1220
1221
1222
1223
1224
1225

1226
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
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381







-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    TCL_UNUSED(const char *) /*file*/,
    TCL_UNUSED(int) /*line*/)
{
}

int
TclDumpMemoryInfo(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    TCL_UNUSED(int) /*flags*/)
{
    return 1;
}

#endif	/* TCL_MEM_DEBUG */

/*
 *------------------------------------------------------------------------
 *
 * TclAllocElemsEx --
 *
 *    See TclAttemptAllocElemsEx. This function differs in that it panics
 *    on failure.
 *
 * Results:
 *    Non-NULL pointer to allocated memory block.
 *
 * Side effects:
 *    Panics if memory of at least the requested size could not be
 *    allocated.
 *
 *------------------------------------------------------------------------
 */
void *
TclAllocElemsEx(
    Tcl_Size elemCount,		/* Allocation will store at least these many... */
    Tcl_Size elemSize,		/* ...elements of this size */
    Tcl_Size leadSize,		/* Additional leading space in bytes */
    Tcl_Size *capacityPtr)	/* OUTPUT: Actual capacity is stored here if
				 * non-NULL. Only modified on success */
{
    void *ptr = TclAttemptReallocElemsEx(
	NULL, elemCount, elemSize, leadSize, capacityPtr);
    if (ptr == NULL) {
	Tcl_Panic("Failed to allocate %" TCL_SIZE_MODIFIER
		  "d elements of size %" TCL_SIZE_MODIFIER "d bytes.",
		  elemCount,
		  elemSize);
    }
    return ptr;
}

/*
 *------------------------------------------------------------------------
 *
 * TclAttemptReallocElemsEx --
 *
 *    Attempts to allocate (oldPtr == NULL) or reallocate memory of the
 *    requested size plus some more for future growth. The amount of
 *    reallocation is adjusted depending on failure.
 *
 *
 * Results:
 *    Pointer to allocated memory block which is at least as large
 *    as the requested size or NULL if allocation failed.
 *
 *------------------------------------------------------------------------
 */
void *
TclAttemptReallocElemsEx(
    void *oldPtr,		/* Pointer to memory block to reallocate or
				 * NULL to indicate this is a new allocation */
    Tcl_Size elemCount,		/* Allocation will store at least these many... */
    Tcl_Size elemSize,		/* ...elements of this size */
    Tcl_Size leadSize,		/* Additional leading space in bytes */
    Tcl_Size *capacityPtr)	/* OUTPUT: Actual capacity is stored here if
				 * non-NULL. Only modified on success */
{
    void *ptr;
    Tcl_Size limit;
    Tcl_Size attempt;

    assert(elemCount > 0);
    assert(elemSize > 0);
    assert(elemSize < TCL_SIZE_MAX);
    assert(leadSize >= 0);
    assert(leadSize < TCL_SIZE_MAX);

    limit = (TCL_SIZE_MAX - leadSize) / elemSize;
    if (elemCount > limit) {
	return NULL;
    }
    /* Loop trying for extra space, reducing request each time */
    attempt = TclUpsizeAlloc(0, elemCount, limit);
    ptr = NULL;
    while (attempt > elemCount) {
	if (oldPtr) {
	    ptr = Tcl_AttemptRealloc(oldPtr, leadSize + attempt * elemSize);
	} else {
	    ptr = Tcl_AttemptAlloc(leadSize + attempt * elemSize);
	}
	if (ptr) {
	    break;
	}
	attempt = TclUpsizeRetry(elemCount, attempt);
    }
    /* Try exact size as a last resort */
    if (ptr == NULL) {
	attempt = elemCount;
	if (oldPtr) {
	    ptr = Tcl_AttemptRealloc(oldPtr, leadSize + attempt * elemSize);
	} else {
	    ptr = Tcl_AttemptAlloc(leadSize + attempt * elemSize);
	}
    }
    if (ptr && capacityPtr) {
	*capacityPtr = attempt;
    }
    return ptr;
}

/*
 *------------------------------------------------------------------------
 *
 * TclReallocElemsEx --
 *
 *    See TclAttemptReallocElemsEx. This function differs in that it panics
 *    on failure.
 *
 * Results:
 *    Non-NULL pointer to allocated memory block.
 *
 * Side effects:
 *    Panics if memory of at least the requested size could not be
 *    allocated.
 *
 *------------------------------------------------------------------------
 */
void *
TclReallocElemsEx(
    void *oldPtr,		/* Pointer to memory block to reallocate */
    Tcl_Size elemCount,		/* Allocation will store at least these many... */
    Tcl_Size elemSize,		/* ...elements of this size */
    Tcl_Size leadSize,		/* Additional leading space in bytes */
    Tcl_Size *capacityPtr)	/* OUTPUT: Actual capacity is stored here if
				 * non-NULL. Only modified on success */
{
    void *ptr = TclAttemptReallocElemsEx(
	oldPtr, elemCount, elemSize, leadSize, capacityPtr);
    if (ptr == NULL) {
	Tcl_Panic("Failed to reallocate %" TCL_SIZE_MODIFIER
		  "d elements of size %" TCL_SIZE_MODIFIER "d bytes.",
		  elemCount,
		  elemSize);
    }
    return ptr;
}

/*
 *---------------------------------------------------------------------------
 *
 * TclFinalizeMemorySubsystem --
 *
 *	This procedure is called to finalize all the structures that are used

Changes to generic/tclClock.c.

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
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
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
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







-
-
-
+
+
+
+






-
+
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-


















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
+
-
-
-
+
-
-
+
-
-
-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-




















-
-
+
+
-
-
+


-
-
+
+

-
+
+


-
+
-



-
-
-
-
-
+
+
-
-
-
+
-
-
-
-
-
-
+
+
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
+
+
-
-
-
+
+
-
-
+

-
-
-
+
+
+
+








-
+


+
+
+



+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+







/*
 * tclClock.c --
 *
 *	Contains the time and date related commands. This code is derived from
 *	the time and date facilities of TclX, by Mark Diekhans and Karl
 *	Lehenbauer.
 *
 * Copyright 1991-1995 Karl Lehenbauer and Mark Diekhans.
 * Copyright (c) 1995 Sun Microsystems, Inc.
 * Copyright (c) 2004 by Kevin B. Kenny. All rights reserved.
 * Copyright © 1991-1995 Karl Lehenbauer & Mark Diekhans.
 * Copyright © 1995 Sun Microsystems, Inc.
 * Copyright © 2004 Kevin B. Kenny. All rights reserved.
 * Copyright © 2015 Sergey G. Brester aka sebres. All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

#include "tclTomMath.h"
/*
 * Windows has mktime. The configurators do not check.
 */

#include "tclStrIdxTree.h"
#ifdef _WIN32
#define HAVE_MKTIME 1
#endif

#include "tclDate.h"
/*
 * Constants
 */

#define JULIAN_DAY_POSIX_EPOCH		2440588
#define SECONDS_PER_DAY			86400
#define JULIAN_SEC_POSIX_EPOCH	      (((Tcl_WideInt) JULIAN_DAY_POSIX_EPOCH) \
					* SECONDS_PER_DAY)
#define FOUR_CENTURIES			146097	/* days */
#define JDAY_1_JAN_1_CE_JULIAN		1721424
#define JDAY_1_JAN_1_CE_GREGORIAN	1721426
#define ONE_CENTURY_GREGORIAN		36524	/* days */
#define FOUR_YEARS			1461	/* days */
#define ONE_YEAR			365	/* days */

/*
 * Table of the days in each month, leap and common years
 */

static const int hath[2][12] = {
    {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
static const int daysInPriorMonths[2][13] = {
    {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
    {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
};

/*
 * Enumeration of the string literals used in [clock]
 */

typedef enum ClockLiteral {
    LIT__NIL,
    LIT__DEFAULT_FORMAT,
    LIT_BCE,		LIT_C,
    LIT_CANNOT_USE_GMT_AND_TIMEZONE,
    LIT_CE,
    LIT_DAYOFMONTH,	LIT_DAYOFWEEK,		LIT_DAYOFYEAR,
    LIT_ERA,		LIT_GMT,		LIT_GREGORIAN,
    LIT_INTEGER_VALUE_TOO_LARGE,
    LIT_ISO8601WEEK,	LIT_ISO8601YEAR,
    LIT_JULIANDAY,	LIT_LOCALSECONDS,
    LIT_MONTH,
    LIT_SECONDS,	LIT_TZNAME,		LIT_TZOFFSET,
    LIT_YEAR,
    LIT__END
} ClockLiteral;
CLOCK_LITERAL_ARRAY(Literals);
static const char *const literals[] = {
    "",
    "%a %b %d %H:%M:%S %Z %Y",
    "BCE",		"C",
    "cannot use -gmt and -timezone in same call",
    "CE",
    "dayOfMonth",	"dayOfWeek",		"dayOfYear",
    "era",		":GMT",			"gregorian",
    "integer value too large to represent",
    "iso8601Week",	"iso8601Year",
    "julianDay",	"localSeconds",
    "month",
    "seconds",		"tzName",		"tzOffset",
    "year"
};

/*
 * Structure containing the client data for [clock]
 */

/* Msgcat literals for exact match (mcKey) */
typedef struct {
    size_t refCount;		/* Number of live references. */
    Tcl_Obj **literals;		/* Pool of object literals. */
CLOCK_LOCALE_LITERAL_ARRAY(MsgCtLiterals, "");
} ClockClientData;

/* Msgcat index literals prefixed with _IDX_, used for quick dictionary search */
/*
 * Structure containing the fields used in [clock format] and [clock scan]
 */
CLOCK_LOCALE_LITERAL_ARRAY(MsgCtLitIdxs, "_IDX_");

typedef struct {
    Tcl_WideInt seconds;	/* Time expressed in seconds from the Posix
				 * epoch */
    Tcl_WideInt localSeconds;	/* Local time expressed in nominal seconds
				 * from the Posix epoch */
    int tzOffset;		/* Time zone offset in seconds east of
				 * Greenwich */
    Tcl_Obj *tzName;		/* Time zone name */
    int julianDay;		/* Julian Day Number in local time zone */
    int isBce;			/* 1 if BCE */
    int gregorian;		/* Flag == 1 if the date is Gregorian */
    int year;			/* Year of the era */
    int dayOfYear;		/* Day of the year (1 January == 1) */
    int month;			/* Month number */
    int dayOfMonth;		/* Day of the month */
    int iso8601Year;		/* ISO8601 week-based year */
    int iso8601Week;		/* ISO8601 week number */
    int dayOfWeek;		/* Day of the week */
} TclDateFields;
static const char *const eras[] = { "CE", "BCE", NULL };

/*
 * Thread specific data block holding a 'struct tm' for the 'gmtime' and
 * 'localtime' library calls.
 */

static Tcl_ThreadDataKey tmKey;

/*
 * Mutex protecting 'gmtime', 'localtime' and 'mktime' calls and the statics
 * in the date parsing code.
 */

TCL_DECLARE_MUTEX(clockMutex)

/*
 * Function prototypes for local procedures in this file:
 */

static int		ConvertUTCToLocal(Tcl_Interp *,
			    TclDateFields *, Tcl_Obj *, int);
static int		ConvertUTCToLocalUsingTable(Tcl_Interp *,
			    TclDateFields *, Tcl_Size, Tcl_Obj *const[],
static int		ConvertUTCToLocalUsingTable(Tcl_Interp *,
			    TclDateFields *, int, Tcl_Obj *const[]);
			    Tcl_WideInt *rangesVal);
static int		ConvertUTCToLocalUsingC(Tcl_Interp *,
			    TclDateFields *, int);
static int		ConvertLocalToUTC(Tcl_Interp *,
			    TclDateFields *, Tcl_Obj *, int);
static int		ConvertLocalToUTC(ClockClientData *, Tcl_Interp *,
			    TclDateFields *, Tcl_Obj *timezoneObj, int);
static int		ConvertLocalToUTCUsingTable(Tcl_Interp *,
			    TclDateFields *, int, Tcl_Obj *const[]);
			    TclDateFields *, int, Tcl_Obj *const[],
			    Tcl_WideInt *rangesVal);
static int		ConvertLocalToUTCUsingC(Tcl_Interp *,
			    TclDateFields *, int);
static Tcl_Obj *	LookupLastTransition(Tcl_Interp *, Tcl_WideInt,
static Tcl_ObjCmdProc	ClockConfigureObjCmd;
			    int, Tcl_Obj *const *);
static void		GetYearWeekDay(TclDateFields *, int);
static void		GetGregorianEraYearDay(TclDateFields *, int);
static void		GetMonthDay(TclDateFields *);
static void		GetJulianDayFromEraYearWeekDay(TclDateFields *, int);
static void		GetJulianDayFromEraYearMonthDay(TclDateFields *, int);
static int		IsGregorianLeapYear(TclDateFields *);
static int		WeekdayOnOrBefore(int, int);
static int		ClockClicksObjCmd(
static Tcl_WideInt	WeekdayOnOrBefore(int, Tcl_WideInt);
static Tcl_ObjCmdProc	ClockClicksObjCmd;
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		ClockConvertlocaltoutcObjCmd(
static Tcl_ObjCmdProc	ClockConvertlocaltoutcObjCmd;
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		ClockGetdatefieldsObjCmd(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		ClockGetjuliandayfromerayearmonthdayObjCmd(
static int		ClockGetDateFields(ClockClientData *,
			    Tcl_Interp *interp, TclDateFields *fields,
			    Tcl_Obj *timezoneObj, int changeover);
static Tcl_ObjCmdProc	ClockGetdatefieldsObjCmd;
static Tcl_ObjCmdProc	ClockGetjuliandayfromerayearmonthdayObjCmd;
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		ClockGetjuliandayfromerayearweekdayObjCmd(
static Tcl_ObjCmdProc	ClockGetjuliandayfromerayearweekdayObjCmd;
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		ClockGetenvObjCmd(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		ClockMicrosecondsObjCmd(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		ClockMillisecondsObjCmd(
static Tcl_ObjCmdProc	ClockGetenvObjCmd;
static Tcl_ObjCmdProc	ClockMicrosecondsObjCmd;
static Tcl_ObjCmdProc	ClockMillisecondsObjCmd;
static Tcl_ObjCmdProc	ClockSecondsObjCmd;
static Tcl_ObjCmdProc	ClockFormatObjCmd;
static Tcl_ObjCmdProc	ClockScanObjCmd;
static int		ClockScanCommit(DateInfo *info,
			    ClockFmtScnCmdArgs *opts);
static int		ClockFreeScan(DateInfo *info,
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		ClockParseformatargsObjCmd(
			    Tcl_Obj *strObj, ClockFmtScnCmdArgs *opts);
static int		ClockCalcRelTime(DateInfo *info);
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		ClockSecondsObjCmd(
static Tcl_ObjCmdProc	ClockAddObjCmd;
static int		ClockValidDate(DateInfo *,
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
			    ClockFmtScnCmdArgs *, int stage);
static struct tm *	ThreadSafeLocalTime(const time_t *);
static void		TzsetIfNecessary(void);
static void		ClockDeleteCmdProc(ClientData);

static size_t		TzsetIfNecessary(void);
static void		ClockDeleteCmdProc(void *);
static Tcl_ObjCmdProc	ClockSafeCatchCmd;
static void		ClockFinalize(void *);
/*
 * Structure containing description of "native" clock commands to create.
 */

struct ClockCommand {
    const char *name;		/* The tail of the command name. The full name
				 * is "::tcl::clock::<name>". When NULL marks
				 * the end of the table. */
    Tcl_ObjCmdProc *objCmdProc;	/* Function that implements the command. This
    Tcl_ObjCmdProc *objCmdProc; /* Function that implements the command. This
				 * will always have the ClockClientData sent
				 * to it, but may well ignore this data. */
    CompileProc *compileProc;	/* The compiler for the command. */
    void *clientData;		/* Any clientData to give the command (if NULL
				 * a reference to ClockClientData will be sent) */
};

static const struct ClockCommand clockCommands[] = {
    {"add",		ClockAddObjCmd,		TclCompileBasicMin1ArgCmd, NULL},
    {"clicks",		ClockClicksObjCmd,	TclCompileClockClicksCmd,  NULL},
    {"format",		ClockFormatObjCmd,	TclCompileBasicMin1ArgCmd, NULL},
    { "getenv",			ClockGetenvObjCmd },
    { "Oldscan",		TclClockOldscanObjCmd },
    { "ConvertLocalToUTC",	ClockConvertlocaltoutcObjCmd },
    { "GetDateFields",		ClockGetdatefieldsObjCmd },
    { "GetJulianDayFromEraYearMonthDay",
		ClockGetjuliandayfromerayearmonthdayObjCmd },
    { "GetJulianDayFromEraYearWeekDay",
		ClockGetjuliandayfromerayearweekdayObjCmd },
    {"getenv",		ClockGetenvObjCmd,	TclCompileBasicMin1ArgCmd, NULL},
    {"microseconds",	ClockMicrosecondsObjCmd,TclCompileClockReadingCmd, INT2PTR(1)},
    {"milliseconds",	ClockMillisecondsObjCmd,TclCompileClockReadingCmd, INT2PTR(2)},
    {"scan",		ClockScanObjCmd,	TclCompileBasicMin1ArgCmd, NULL},
    {"seconds",		ClockSecondsObjCmd,	TclCompileClockReadingCmd, INT2PTR(3)},
    {"ConvertLocalToUTC", ClockConvertlocaltoutcObjCmd,		NULL, NULL},
    {"GetDateFields",	  ClockGetdatefieldsObjCmd,		NULL, NULL},
    {"GetJulianDayFromEraYearMonthDay",
		ClockGetjuliandayfromerayearmonthdayObjCmd,	NULL, NULL},
    {"GetJulianDayFromEraYearWeekDay",
		ClockGetjuliandayfromerayearweekdayObjCmd,	NULL, NULL},
    { "ParseFormatArgs",	ClockParseformatargsObjCmd },
    { NULL, NULL }
    {"catch",		ClockSafeCatchCmd,	TclCompileBasicMin1ArgCmd, NULL},
    {NULL, NULL, NULL, NULL}
};

/*
 *----------------------------------------------------------------------
 *
 * TclClockInit --
 *
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
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
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
467
468
469
470
471

472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401

1402
1403
1404
1405
1406

1407

1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420

1421
1422
1423
1424

1425
1426
1427
1428
1429
1430

1431
1432
1433

1434



1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491

1492
1493
1494
1495
1496
1497
1498


1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509

1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522

1523
1524
1525
1526
1527

1528


1529
1530

1531
1532
1533
1534




1535










1536
1537
1538
1539
1540
1541
1542







+



+
+
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-


















-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+


-





+
+

+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
+



-
+















-
+




-
+
-







+





-
+



-
+





-
+


-
+
-
-
-
+
+













-
+



















-
+



-
+
-

















-
+






-
-
+
+

+
+






-
+












-
+




-
+
-
-

+
-
+



-
-
-
-
+
-
-
-
-
-
-
-
-
-
-







TclClockInit(
    Tcl_Interp *interp)		/* Tcl interpreter */
{
    const struct ClockCommand *clockCmdPtr;
    char cmdName[50];		/* Buffer large enough to hold the string
				 *::tcl::clock::GetJulianDayFromEraYearMonthDay
				 * plus a terminating NUL. */
    Command *cmdPtr;
    ClockClientData *data;
    int i;

    static int initialized = 0;	/* global clock engine initialized (in process) */
    /*
    /* Structure of the 'clock' ensemble */

     * Register handler to finalize clock on exit.
     */
    if (!initialized) {
	Tcl_CreateExitHandler(ClockFinalize, NULL);
	initialized = 1;
    }
    static const EnsembleImplMap clockImplMap[] = {
	{"add",          NULL,                    TclCompileBasicMin1ArgCmd, NULL, NULL,       0},
	{"clicks",       ClockClicksObjCmd,       TclCompileClockClicksCmd,  NULL, NULL,       0},
	{"format",       NULL,                    TclCompileBasicMin1ArgCmd, NULL, NULL,       0},
	{"microseconds", ClockMicrosecondsObjCmd, TclCompileClockReadingCmd, NULL, INT2PTR(1), 0},
	{"milliseconds", ClockMillisecondsObjCmd, TclCompileClockReadingCmd, NULL, INT2PTR(2), 0},
	{"scan",         NULL,                    TclCompileBasicMin1ArgCmd, NULL, NULL      , 0},
	{"seconds",      ClockSecondsObjCmd,      TclCompileClockReadingCmd, NULL, INT2PTR(3), 0},
	{NULL,           NULL,                    NULL,                      NULL, NULL,       0}
    };

    /*
     * Safe interps get [::clock] as alias to a parent, so do not need their
     * own copies of the support routines.
     */

    if (Tcl_IsSafe(interp)) {
	return;
    }

    /*
     * Create the client data, which is a refcounted literal pool.
     */

    data = (ClockClientData *)Tcl_Alloc(sizeof(ClockClientData));
    data->refCount = 0;
    data->literals = (Tcl_Obj **)Tcl_Alloc(LIT__END * sizeof(Tcl_Obj*));
    for (i = 0; i < LIT__END; ++i) {
	data->literals[i] = Tcl_NewStringObj(literals[i], -1);
	Tcl_IncrRefCount(data->literals[i]);
    }
	TclInitObjRef(data->literals[i], Tcl_NewStringObj(
		Literals[i], TCL_AUTO_LENGTH));
    }
    data->mcLiterals = NULL;
    data->mcLitIdxs = NULL;
    data->mcDicts = NULL;
    data->lastTZEpoch = 0;
    data->currentYearCentury = ClockDefaultYearCentury;
    data->yearOfCenturySwitch = ClockDefaultCenturySwitch;
    data->validMinYear = INT_MIN;
    data->validMaxYear = INT_MAX;
    /* corresponds max of JDN in sqlite - 9999-12-31 23:59:59 per default */
    data->maxJDN = 5373484.499999994;

    data->systemTimeZone = NULL;
    data->systemSetupTZData = NULL;
    data->gmtSetupTimeZoneUnnorm = NULL;
    data->gmtSetupTimeZone = NULL;
    data->gmtSetupTZData = NULL;
    data->gmtTZName = NULL;
    data->lastSetupTimeZoneUnnorm = NULL;
    data->lastSetupTimeZone = NULL;
    data->lastSetupTZData = NULL;
    data->prevSetupTimeZoneUnnorm = NULL;
    data->prevSetupTimeZone = NULL;
    data->prevSetupTZData = NULL;

    data->defaultLocale = NULL;
    data->defaultLocaleDict = NULL;
    data->currentLocale = NULL;
    data->currentLocaleDict = NULL;
    data->lastUsedLocaleUnnorm = NULL;
    data->lastUsedLocale = NULL;
    data->lastUsedLocaleDict = NULL;
    data->prevUsedLocaleUnnorm = NULL;
    data->prevUsedLocale = NULL;
    data->prevUsedLocaleDict = NULL;

    data->lastBase.timezoneObj = NULL;

    memset(&data->lastTZOffsCache, 0, sizeof(data->lastTZOffsCache));

    data->defFlags = CLF_VALIDATE;

    /*
     * Install the commands.
     * TODO - Let Tcl_MakeEnsemble do this?
     */

#define TCL_CLOCK_PREFIX_LEN 14 /* == strlen("::tcl::clock::") */
    memcpy(cmdName, "::tcl::clock::", TCL_CLOCK_PREFIX_LEN);
    for (clockCmdPtr=clockCommands ; clockCmdPtr->name!=NULL ; clockCmdPtr++) {
	void *clientData;

	strcpy(cmdName + TCL_CLOCK_PREFIX_LEN, clockCmdPtr->name);
	if (!(clientData = clockCmdPtr->clientData)) {
	    clientData = data;
	data->refCount++;
	Tcl_CreateObjCommand(interp, cmdName, clockCmdPtr->objCmdProc, data,
		ClockDeleteCmdProc);
    }

    /* Make the clock ensemble */

    TclMakeEnsemble(interp, "clock", clockImplMap);
	    data->refCount++;
	}
	cmdPtr = (Command *)Tcl_CreateObjCommand(interp, cmdName,
		clockCmdPtr->objCmdProc, clientData,
		clockCmdPtr->clientData ? NULL : ClockDeleteCmdProc);
	cmdPtr->compileProc = clockCmdPtr->compileProc ?
		clockCmdPtr->compileProc : TclCompileBasicMin0ArgCmd;
    }
    cmdPtr = (Command *) Tcl_CreateObjCommand(interp,
	    "::tcl::unsupported::clock::configure",
	    ClockConfigureObjCmd, data, ClockDeleteCmdProc);
    data->refCount++;
    cmdPtr->compileProc = TclCompileBasicMin0ArgCmd;
}

/*
 *----------------------------------------------------------------------
 *
 * ClockConfigureClear --
 *
 *	Clean up cached resp. run-time storages used in clock commands.
 *
 *	Shared usage for clean-up (ClockDeleteCmdProc) and "configure -clear".
 *
 * Results:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
ClockConfigureClear(
    ClockClientData *data)
{
    ClockFrmScnClearCaches();

    data->lastTZEpoch = 0;
    TclUnsetObjRef(data->systemTimeZone);
    TclUnsetObjRef(data->systemSetupTZData);
    TclUnsetObjRef(data->gmtSetupTimeZoneUnnorm);
    TclUnsetObjRef(data->gmtSetupTimeZone);
    TclUnsetObjRef(data->gmtSetupTZData);
    TclUnsetObjRef(data->gmtTZName);
    TclUnsetObjRef(data->lastSetupTimeZoneUnnorm);
    TclUnsetObjRef(data->lastSetupTimeZone);
    TclUnsetObjRef(data->lastSetupTZData);
    TclUnsetObjRef(data->prevSetupTimeZoneUnnorm);
    TclUnsetObjRef(data->prevSetupTimeZone);
    TclUnsetObjRef(data->prevSetupTZData);

    TclUnsetObjRef(data->defaultLocale);
    data->defaultLocaleDict = NULL;
    TclUnsetObjRef(data->currentLocale);
    data->currentLocaleDict = NULL;
    TclUnsetObjRef(data->lastUsedLocaleUnnorm);
    TclUnsetObjRef(data->lastUsedLocale);
    data->lastUsedLocaleDict = NULL;
    TclUnsetObjRef(data->prevUsedLocaleUnnorm);
    TclUnsetObjRef(data->prevUsedLocale);
    data->prevUsedLocaleDict = NULL;

    TclUnsetObjRef(data->lastBase.timezoneObj);

    TclUnsetObjRef(data->lastTZOffsCache[0].timezoneObj);
    TclUnsetObjRef(data->lastTZOffsCache[0].tzName);
    TclUnsetObjRef(data->lastTZOffsCache[1].timezoneObj);
    TclUnsetObjRef(data->lastTZOffsCache[1].tzName);

    TclUnsetObjRef(data->mcDicts);
}

/*
 *----------------------------------------------------------------------
 *
 * ClockDeleteCmdProc --
 *
 *	Remove a reference to the clock client data, and clean up memory
 *	when it's all gone.
 *
 * Results:
 *	None.
 *
 *----------------------------------------------------------------------
 */
static void
ClockDeleteCmdProc(
    void *clientData)	/* Opaque pointer to the client data */
{
    ClockClientData *data = (ClockClientData *)clientData;
    int i;

    if (data->refCount-- <= 1) {
	for (i = 0; i < LIT__END; ++i) {
	    Tcl_DecrRefCount(data->literals[i]);
	}
	if (data->mcLiterals != NULL) {
	    for (i = 0; i < MCLIT__END; ++i) {
		Tcl_DecrRefCount(data->mcLiterals[i]);
	    }
	    Tcl_Free(data->mcLiterals);
	    data->mcLiterals = NULL;
	}
	if (data->mcLitIdxs != NULL) {
	    for (i = 0; i < MCLIT__END; ++i) {
		Tcl_DecrRefCount(data->mcLitIdxs[i]);
	    }
	    Tcl_Free(data->mcLitIdxs);
	    data->mcLitIdxs = NULL;
	}

	ClockConfigureClear(data);

	Tcl_Free(data->literals);
	Tcl_Free(data);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * SavePrevTimezoneObj --
 *
 *	Used to store previously used/cached time zone (makes it reusable).
 *
 *	This enables faster switch between time zones (e. g. to convert from
 *	one to another).
 *
 * Results:
 *	None.
 *
 *----------------------------------------------------------------------
 */
static inline void
SavePrevTimezoneObj(
    ClockClientData *dataPtr)	/* Client data containing literal pool */
{
    Tcl_Obj *timezoneObj = dataPtr->lastSetupTimeZone;

    if (timezoneObj && timezoneObj != dataPtr->prevSetupTimeZone) {
	TclSetObjRef(dataPtr->prevSetupTimeZoneUnnorm, dataPtr->lastSetupTimeZoneUnnorm);
	TclSetObjRef(dataPtr->prevSetupTimeZone, timezoneObj);
	TclSetObjRef(dataPtr->prevSetupTZData, dataPtr->lastSetupTZData);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * NormTimezoneObj --
 *
 *	Normalizes the timezone object (used for caching puposes).
 *
 *	If already cached time zone could be found, returns this
 *	object (last setup or last used, system (current) or gmt).
 *
 * Results:
 *	Normalized tcl object pointer.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Obj *
NormTimezoneObj(
    ClockClientData *dataPtr,	/* Client data containing literal pool */
    Tcl_Obj *timezoneObj,	/* Name of zone to find */
    int *loaded)		/* Used to recognized TZ was loaded */
{
    const char *tz;

    *loaded = 1;
    if (timezoneObj == dataPtr->lastSetupTimeZoneUnnorm
	    && dataPtr->lastSetupTimeZone != NULL) {
	return dataPtr->lastSetupTimeZone;
    }
    if (timezoneObj == dataPtr->prevSetupTimeZoneUnnorm
	    && dataPtr->prevSetupTimeZone != NULL) {
	return dataPtr->prevSetupTimeZone;
    }
    if (timezoneObj == dataPtr->gmtSetupTimeZoneUnnorm
	    && dataPtr->gmtSetupTimeZone != NULL) {
	return dataPtr->literals[LIT_GMT];
    }
    if (timezoneObj == dataPtr->lastSetupTimeZone
	    || timezoneObj == dataPtr->prevSetupTimeZone
	    || timezoneObj == dataPtr->gmtSetupTimeZone
	    || timezoneObj == dataPtr->systemTimeZone) {
	return timezoneObj;
    }

    tz = TclGetString(timezoneObj);
    if (dataPtr->lastSetupTimeZone != NULL
	    && strcmp(tz, TclGetString(dataPtr->lastSetupTimeZone)) == 0) {
	TclSetObjRef(dataPtr->lastSetupTimeZoneUnnorm, timezoneObj);
	return dataPtr->lastSetupTimeZone;
    }
    if (dataPtr->prevSetupTimeZone != NULL
	    && strcmp(tz, TclGetString(dataPtr->prevSetupTimeZone)) == 0) {
	TclSetObjRef(dataPtr->prevSetupTimeZoneUnnorm, timezoneObj);
	return dataPtr->prevSetupTimeZone;
    }
    if (dataPtr->systemTimeZone != NULL
	    && strcmp(tz, TclGetString(dataPtr->systemTimeZone)) == 0) {
	return dataPtr->systemTimeZone;
    }
    if (strcmp(tz, Literals[LIT_GMT]) == 0) {
	TclSetObjRef(dataPtr->gmtSetupTimeZoneUnnorm, timezoneObj);
	if (dataPtr->gmtSetupTimeZone == NULL) {
	    *loaded = 0;
	}
	return dataPtr->literals[LIT_GMT];
    }
    /* unknown/unloaded tz - recache/revalidate later as last-setup if needed */
    *loaded = 0;
    return timezoneObj;
}

/*
 *----------------------------------------------------------------------
 *
 * ClockGetSystemLocale --
 *
 *	Returns system locale.
 *
 *	Executes ::tcl::clock::GetSystemLocale in given interpreter.
 *
 * Results:
 *	Returns system locale tcl object.
 *
 *----------------------------------------------------------------------
 */

static inline Tcl_Obj *
ClockGetSystemLocale(
    ClockClientData *dataPtr,	/* Opaque pointer to literal pool, etc. */
    Tcl_Interp *interp)		/* Tcl interpreter */
{
    if (Tcl_EvalObjv(interp, 1, &dataPtr->literals[LIT_GETSYSTEMLOCALE], 0) != TCL_OK) {
	return NULL;
    }

    return Tcl_GetObjResult(interp);
}
/*
 *----------------------------------------------------------------------
 *
 * ClockGetCurrentLocale --
 *
 *	Returns current locale.
 *
 *	Executes ::tcl::clock::mclocale in given interpreter.
 *
 * Results:
 *	Returns current locale tcl object.
 *
 *----------------------------------------------------------------------
 */

static inline Tcl_Obj *
ClockGetCurrentLocale(
    ClockClientData *dataPtr,	/* Client data containing literal pool */
    Tcl_Interp *interp)		/* Tcl interpreter */
{
    if (Tcl_EvalObjv(interp, 1, &dataPtr->literals[LIT_GETCURRENTLOCALE], 0) != TCL_OK) {
	return NULL;
    }

    TclSetObjRef(dataPtr->currentLocale, Tcl_GetObjResult(interp));
    dataPtr->currentLocaleDict = NULL;
    Tcl_ResetResult(interp);

    return dataPtr->currentLocale;
}

/*
 *----------------------------------------------------------------------
 *
 * SavePrevLocaleObj --
 *
 *	Used to store previously used/cached locale (makes it reusable).
 *
 *	This enables faster switch between locales (e. g. to convert from one to another).
 *
 * Results:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static inline void
SavePrevLocaleObj(
    ClockClientData *dataPtr)	/* Client data containing literal pool */
{
    Tcl_Obj *localeObj = dataPtr->lastUsedLocale;

    if (localeObj && localeObj != dataPtr->prevUsedLocale) {
	TclSetObjRef(dataPtr->prevUsedLocaleUnnorm, dataPtr->lastUsedLocaleUnnorm);
	TclSetObjRef(dataPtr->prevUsedLocale, localeObj);
	/* mcDicts owns reference to dict */
	dataPtr->prevUsedLocaleDict = dataPtr->lastUsedLocaleDict;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * NormLocaleObj --
 *
 *	Normalizes the locale object (used for caching puposes).
 *
 *	If already cached locale could be found, returns this
 *	object (current, system (OS) or last used locales).
 *
 * Results:
 *	Normalized tcl object pointer.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Obj *
NormLocaleObj(
    ClockClientData *dataPtr,	/* Client data containing literal pool */
    Tcl_Interp *interp,		/* Tcl interpreter */
    Tcl_Obj *localeObj,
    Tcl_Obj **mcDictObj)
{
    const char *loc, *loc2;

    if (localeObj == NULL
	    || localeObj == dataPtr->literals[LIT_C]
	    || localeObj == dataPtr->defaultLocale) {
	*mcDictObj = dataPtr->defaultLocaleDict;
	return dataPtr->defaultLocale ?
		dataPtr->defaultLocale : dataPtr->literals[LIT_C];
    }

    if (localeObj == dataPtr->currentLocale
	    || localeObj == dataPtr->literals[LIT_CURRENT]) {
	if (dataPtr->currentLocale == NULL) {
	    ClockGetCurrentLocale(dataPtr, interp);
	}
	*mcDictObj = dataPtr->currentLocaleDict;
	return dataPtr->currentLocale;
    }

    if (localeObj == dataPtr->lastUsedLocale
	    || localeObj == dataPtr->lastUsedLocaleUnnorm) {
	*mcDictObj = dataPtr->lastUsedLocaleDict;
	return dataPtr->lastUsedLocale;
    }

    if (localeObj == dataPtr->prevUsedLocale
	    || localeObj == dataPtr->prevUsedLocaleUnnorm) {
	*mcDictObj = dataPtr->prevUsedLocaleDict;
	return dataPtr->prevUsedLocale;
    }

    loc = TclGetString(localeObj);
    if (dataPtr->currentLocale != NULL
	    && (localeObj == dataPtr->currentLocale
	    || (localeObj->length == dataPtr->currentLocale->length
	    && strcasecmp(loc, TclGetString(dataPtr->currentLocale)) == 0))) {
	*mcDictObj = dataPtr->currentLocaleDict;
	return dataPtr->currentLocale;
    }

    if (dataPtr->lastUsedLocale != NULL
	    && (localeObj == dataPtr->lastUsedLocale
	    || (localeObj->length == dataPtr->lastUsedLocale->length
	    && strcasecmp(loc, TclGetString(dataPtr->lastUsedLocale)) == 0))) {
	*mcDictObj = dataPtr->lastUsedLocaleDict;
	TclSetObjRef(dataPtr->lastUsedLocaleUnnorm, localeObj);
	return dataPtr->lastUsedLocale;
    }

    if (dataPtr->prevUsedLocale != NULL
	    && (localeObj == dataPtr->prevUsedLocale
	    || (localeObj->length == dataPtr->prevUsedLocale->length
	    && strcasecmp(loc, TclGetString(dataPtr->prevUsedLocale)) == 0))) {
	*mcDictObj = dataPtr->prevUsedLocaleDict;
	TclSetObjRef(dataPtr->prevUsedLocaleUnnorm, localeObj);
	return dataPtr->prevUsedLocale;
    }

    if ((localeObj->length == 1 /* C */
	    && strcasecmp(loc, Literals[LIT_C]) == 0)
	    || (dataPtr->defaultLocale && (loc2 = TclGetString(dataPtr->defaultLocale))
	    && localeObj->length == dataPtr->defaultLocale->length
	    && strcasecmp(loc, loc2) == 0)) {
	*mcDictObj = dataPtr->defaultLocaleDict;
	return dataPtr->defaultLocale ?
		dataPtr->defaultLocale : dataPtr->literals[LIT_C];
    }

    if (localeObj->length == 7 /* current */
	    && strcasecmp(loc, Literals[LIT_CURRENT]) == 0) {
	if (dataPtr->currentLocale == NULL) {
	    ClockGetCurrentLocale(dataPtr, interp);
	}
	*mcDictObj = dataPtr->currentLocaleDict;
	return dataPtr->currentLocale;
    }

    if ((localeObj->length == 6 /* system */
	    && strcasecmp(loc, Literals[LIT_SYSTEM]) == 0)) {
	SavePrevLocaleObj(dataPtr);
	TclSetObjRef(dataPtr->lastUsedLocaleUnnorm, localeObj);
	localeObj = ClockGetSystemLocale(dataPtr, interp);
	TclSetObjRef(dataPtr->lastUsedLocale, localeObj);
	*mcDictObj = NULL;
	return localeObj;
    }

    *mcDictObj = NULL;
    return localeObj;
}

/*
 *----------------------------------------------------------------------
 *
 * ClockMCDict --
 *
 *	Retrieves a localized storage dictionary object for the given
 *	locale object.
 *
 *	This corresponds with call `::tcl::clock::mcget locale`.
 *	Cached representation stored in options (for further access).
 *
 * Results:
 *	Tcl-object contains smart reference to msgcat dictionary.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
ClockMCDict(
    ClockFmtScnCmdArgs *opts)
{
    ClockClientData *dataPtr = opts->dataPtr;

    /* if dict not yet retrieved */
    if (opts->mcDictObj == NULL) {

	/* if locale was not yet used */
	if (!(opts->flags & CLF_LOCALE_USED)) {
	    opts->localeObj = NormLocaleObj(dataPtr, opts->interp,
		    opts->localeObj, &opts->mcDictObj);

	    if (opts->localeObj == NULL) {
		Tcl_SetObjResult(opts->interp, Tcl_NewStringObj(
			"locale not specified and no default locale set",
			TCL_AUTO_LENGTH));
		Tcl_SetErrorCode(opts->interp, "CLOCK", "badOption", (char *)NULL);
		return NULL;
	    }
	    opts->flags |= CLF_LOCALE_USED;

	    /* check locale literals already available (on demand creation) */
	    if (dataPtr->mcLiterals == NULL) {
		int i;

		dataPtr->mcLiterals = (Tcl_Obj **)
			Tcl_Alloc(MCLIT__END * sizeof(Tcl_Obj*));
		for (i = 0; i < MCLIT__END; ++i) {
		    TclInitObjRef(dataPtr->mcLiterals[i], Tcl_NewStringObj(
			    MsgCtLiterals[i], TCL_AUTO_LENGTH));
		}
	    }
	}

	/* check or obtain mcDictObj (be sure it's modifiable) */
	if (opts->mcDictObj == NULL || opts->mcDictObj->refCount > 1) {
	    Tcl_Size ref = 1;

	    /* first try to find locale catalog dict */
	    if (dataPtr->mcDicts == NULL) {
		TclSetObjRef(dataPtr->mcDicts, Tcl_NewDictObj());
	    }
	    Tcl_DictObjGet(NULL, dataPtr->mcDicts,
		    opts->localeObj, &opts->mcDictObj);

	    if (opts->mcDictObj == NULL) {
		/* get msgcat dictionary - ::tcl::clock::mcget locale */
		Tcl_Obj *callargs[2];

		callargs[0] = dataPtr->literals[LIT_MCGET];
		callargs[1] = opts->localeObj;

		if (Tcl_EvalObjv(opts->interp, 2, callargs, 0) != TCL_OK) {
		    return NULL;
		}

		opts->mcDictObj = Tcl_GetObjResult(opts->interp);
		Tcl_ResetResult(opts->interp);
		ref = 0; /* new object is not yet referenced */
	    }

	    /* be sure that object reference doesn't increase (dict changeable) */
	    if (opts->mcDictObj->refCount > ref) {
		/* smart reference (shared dict as object with no ref-counter) */
		opts->mcDictObj = TclDictObjSmartRef(opts->interp,
			opts->mcDictObj);
	    }

	    /* create exactly one reference to catalog / make it searchable for future */
	    Tcl_DictObjPut(NULL, dataPtr->mcDicts, opts->localeObj,
		    opts->mcDictObj);

	    if (opts->localeObj == dataPtr->literals[LIT_C]
		    || opts->localeObj == dataPtr->defaultLocale) {
		dataPtr->defaultLocaleDict = opts->mcDictObj;
	    }
	    if (opts->localeObj == dataPtr->currentLocale) {
		dataPtr->currentLocaleDict = opts->mcDictObj;
	    } else if (opts->localeObj == dataPtr->lastUsedLocale) {
		dataPtr->lastUsedLocaleDict = opts->mcDictObj;
	    } else {
		SavePrevLocaleObj(dataPtr);
		TclSetObjRef(dataPtr->lastUsedLocale, opts->localeObj);
		TclUnsetObjRef(dataPtr->lastUsedLocaleUnnorm);
		dataPtr->lastUsedLocaleDict = opts->mcDictObj;
	    }
	}
    }

    return opts->mcDictObj;
}

/*
 *----------------------------------------------------------------------
 *
 * ClockMCGet --
 *
 *	Retrieves a msgcat value for the given literal integer mcKey
 *	from localized storage (corresponding given locale object)
 *	by mcLiterals[mcKey] (e. g. MONTHS_FULL).
 *
 * Results:
 *	Tcl-object contains localized value.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
ClockMCGet(
    ClockFmtScnCmdArgs *opts,
    int mcKey)
{
    Tcl_Obj *valObj = NULL;

    if (opts->mcDictObj == NULL) {
	ClockMCDict(opts);
	if (opts->mcDictObj == NULL) {
	    return NULL;
	}
    }

    Tcl_DictObjGet(opts->interp, opts->mcDictObj,
	    opts->dataPtr->mcLiterals[mcKey], &valObj);
    return valObj; /* or NULL in obscure case if Tcl_DictObjGet failed */
}

/*
 *----------------------------------------------------------------------
 *
 * ClockMCGetIdx --
 *
 *	Retrieves an indexed msgcat value for the given literal integer mcKey
 *	from localized storage (corresponding given locale object)
 *	by mcLitIdxs[mcKey] (e. g. _IDX_MONTHS_FULL).
 *
 * Results:
 *	Tcl-object contains localized indexed value.
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE Tcl_Obj *
ClockMCGetIdx(
    ClockFmtScnCmdArgs *opts,
    int mcKey)
{
    ClockClientData *dataPtr = opts->dataPtr;
    Tcl_Obj *valObj = NULL;

    if (opts->mcDictObj == NULL) {
	ClockMCDict(opts);
	if (opts->mcDictObj == NULL) {
	    return NULL;
	}
    }

    /* try to get indices object */
    if (dataPtr->mcLitIdxs == NULL) {
	return NULL;
    }

    if (Tcl_DictObjGet(NULL, opts->mcDictObj,
	    dataPtr->mcLitIdxs[mcKey], &valObj) != TCL_OK) {
	return NULL;
    }
    return valObj;
}

/*
 *----------------------------------------------------------------------
 *
 * ClockMCSetIdx --
 *
 *	Sets an indexed msgcat value for the given literal integer mcKey
 *	in localized storage (corresponding given locale object)
 *	by mcLitIdxs[mcKey] (e. g. _IDX_MONTHS_FULL).
 *
 * Results:
 *	Returns a standard Tcl result.
 *
 *----------------------------------------------------------------------
 */

int
ClockMCSetIdx(
    ClockFmtScnCmdArgs *opts,
    int mcKey,
    Tcl_Obj *valObj)
{
    ClockClientData *dataPtr = opts->dataPtr;

    if (opts->mcDictObj == NULL) {
	ClockMCDict(opts);
	if (opts->mcDictObj == NULL) {
	    return TCL_ERROR;
	}
    }

    /* if literal storage for indices not yet created */
    if (dataPtr->mcLitIdxs == NULL) {
	int i;

	dataPtr->mcLitIdxs = (Tcl_Obj **)Tcl_Alloc(MCLIT__END * sizeof(Tcl_Obj*));
	for (i = 0; i < MCLIT__END; ++i) {
	    TclInitObjRef(dataPtr->mcLitIdxs[i],
		    Tcl_NewStringObj(MsgCtLitIdxs[i], TCL_AUTO_LENGTH));
	}
    }

    return Tcl_DictObjPut(opts->interp, opts->mcDictObj,
	    dataPtr->mcLitIdxs[mcKey], valObj);
}

static void
TimezoneLoaded(
    ClockClientData *dataPtr,
    Tcl_Obj *timezoneObj,	/* Name of zone was loaded */
    Tcl_Obj *tzUnnormObj)	/* Name of zone was loaded */
{
    /* don't overwrite last-setup with GMT (special case) */
    if (timezoneObj == dataPtr->literals[LIT_GMT]) {
	/* mark GMT zone loaded */
	if (dataPtr->gmtSetupTimeZone == NULL) {
	    TclSetObjRef(dataPtr->gmtSetupTimeZone,
		    dataPtr->literals[LIT_GMT]);
	}
	TclSetObjRef(dataPtr->gmtSetupTimeZoneUnnorm, tzUnnormObj);
	return;
    }

    /* last setup zone loaded */
    if (dataPtr->lastSetupTimeZone != timezoneObj) {
	SavePrevTimezoneObj(dataPtr);
	TclSetObjRef(dataPtr->lastSetupTimeZone, timezoneObj);
	TclUnsetObjRef(dataPtr->lastSetupTZData);
    }
    TclSetObjRef(dataPtr->lastSetupTimeZoneUnnorm, tzUnnormObj);
}
/*
 *----------------------------------------------------------------------
 *
 * ClockConfigureObjCmd --
 *
 *	This function is invoked to process the Tcl "::tcl::unsupported::clock::configure"
 *	(internal, unsupported) command.
 *
 * Usage:
 *	::tcl::unsupported::clock::configure ?-option ?value??
 *
 * Results:
 *	Returns a standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
ClockConfigureObjCmd(
    void *clientData,		/* Client data containing literal pool */
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const objv[])	/* Parameter vector */
{
    ClockClientData *dataPtr = (ClockClientData *)clientData;
    static const char *const options[] = {
	"-default-locale",	"-clear",	  "-current-locale",
	"-year-century",  "-century-switch",
	"-min-year", "-max-year", "-max-jdn", "-validate",
	"-init-complete",	  "-setup-tz", "-system-tz", NULL
    };
    enum optionInd {
	CLOCK_DEFAULT_LOCALE, CLOCK_CLEAR_CACHE, CLOCK_CURRENT_LOCALE,
	CLOCK_YEAR_CENTURY, CLOCK_CENTURY_SWITCH,
	CLOCK_MIN_YEAR, CLOCK_MAX_YEAR, CLOCK_MAX_JDN, CLOCK_VALIDATE,
	CLOCK_INIT_COMPLETE,  CLOCK_SETUP_TZ, CLOCK_SYSTEM_TZ
    };
    int optionIndex;		/* Index of an option. */
    Tcl_Size i;

    for (i = 1; i < objc; i++) {
	if (Tcl_GetIndexFromObj(interp, objv[i++], options,
		"option", 0, &optionIndex) != TCL_OK) {
	    Tcl_SetErrorCode(interp, "CLOCK", "badOption",
		    TclGetString(objv[i - 1]), (char *)NULL);
	    return TCL_ERROR;
	}
	switch (optionIndex) {
	case CLOCK_SYSTEM_TZ: {
	    /* validate current tz-epoch */
	    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;
	}
	case CLOCK_SETUP_TZ:
	    if (i < objc) {
		int loaded;
		Tcl_Obj *timezoneObj = NormTimezoneObj(dataPtr, objv[i], &loaded);

		if (!loaded) {
		    TimezoneLoaded(dataPtr, timezoneObj, objv[i]);
		}
		Tcl_SetObjResult(interp, timezoneObj);
	    } else if (i + 1 >= objc && dataPtr->lastSetupTimeZone != NULL) {
		Tcl_SetObjResult(interp, dataPtr->lastSetupTimeZone);
	    }
	    break;
	case CLOCK_DEFAULT_LOCALE:
	    if (i < objc) {
		if (dataPtr->defaultLocale != objv[i]) {
		    TclSetObjRef(dataPtr->defaultLocale, objv[i]);
		    dataPtr->defaultLocaleDict = NULL;
		}
	    }
	    if (i + 1 >= objc) {
		Tcl_SetObjResult(interp, dataPtr->defaultLocale ?
			dataPtr->defaultLocale : dataPtr->literals[LIT_C]);
	    }
	    break;
	case CLOCK_CURRENT_LOCALE:
	    if (i < objc) {
		if (dataPtr->currentLocale != objv[i]) {
		    TclSetObjRef(dataPtr->currentLocale, objv[i]);
		    dataPtr->currentLocaleDict = NULL;
		}
	    }
	    if (i + 1 >= objc && dataPtr->currentLocale != NULL) {
		Tcl_SetObjResult(interp, dataPtr->currentLocale);
	    }
	    break;
	case CLOCK_YEAR_CENTURY:
	    if (i < objc) {
		int year;

		if (TclGetIntFromObj(interp, objv[i], &year) != TCL_OK) {
		    return TCL_ERROR;
		}
		dataPtr->currentYearCentury = year;
		if (i + 1 >= objc) {
		    Tcl_SetObjResult(interp, objv[i]);
		}
		continue;
	    }
	    if (i + 1 >= objc) {
		Tcl_SetObjResult(interp,
			Tcl_NewWideIntObj(dataPtr->currentYearCentury));
	    }
	    break;
	case CLOCK_CENTURY_SWITCH:
	    if (i < objc) {
		int year;

		if (TclGetIntFromObj(interp, objv[i], &year) != TCL_OK) {
		    return TCL_ERROR;
		}
		dataPtr->yearOfCenturySwitch = year;
		Tcl_SetObjResult(interp, objv[i]);
		continue;
	    }
	    if (i + 1 >= objc) {
		Tcl_SetObjResult(interp,
			Tcl_NewWideIntObj(dataPtr->yearOfCenturySwitch));
	    }
	    break;
	case CLOCK_MIN_YEAR:
	    if (i < objc) {
		int year;

		if (TclGetIntFromObj(interp, objv[i], &year) != TCL_OK) {
		    return TCL_ERROR;
		}
		dataPtr->validMinYear = year;
		Tcl_SetObjResult(interp, objv[i]);
		continue;
	    }
	    if (i + 1 >= objc) {
		Tcl_SetObjResult(interp,
			Tcl_NewWideIntObj(dataPtr->validMinYear));
	    }
	    break;
	case CLOCK_MAX_YEAR:
	    if (i < objc) {
		int year;

		if (TclGetIntFromObj(interp, objv[i], &year) != TCL_OK) {
		    return TCL_ERROR;
		}
		dataPtr->validMaxYear = year;
		Tcl_SetObjResult(interp, objv[i]);
		continue;
	    }
	    if (i + 1 >= objc) {
		Tcl_SetObjResult(interp,
			Tcl_NewWideIntObj(dataPtr->validMaxYear));
	    }
	    break;
	case CLOCK_MAX_JDN:
	    if (i < objc) {
		double jd;

		if (Tcl_GetDoubleFromObj(interp, objv[i], &jd) != TCL_OK) {
		    return TCL_ERROR;
		}
		dataPtr->maxJDN = jd;
		Tcl_SetObjResult(interp, objv[i]);
		continue;
	    }
	    if (i + 1 >= objc) {
		Tcl_SetObjResult(interp, Tcl_NewDoubleObj(dataPtr->maxJDN));
	    }
	    break;
	case CLOCK_VALIDATE:
	    if (i < objc) {
		int val;

		if (Tcl_GetBooleanFromObj(interp, objv[i], &val) != TCL_OK) {
		    return TCL_ERROR;
		}
		if (val) {
		    dataPtr->defFlags |= CLF_VALIDATE;
		} else {
		    dataPtr->defFlags &= ~CLF_VALIDATE;
		}
	    }
	    if (i + 1 >= objc) {
		Tcl_SetObjResult(interp,
			Tcl_NewBooleanObj(dataPtr->defFlags & CLF_VALIDATE));
	    }
	    break;
	case CLOCK_CLEAR_CACHE:
	    ClockConfigureClear(dataPtr);
	    break;
	case CLOCK_INIT_COMPLETE: {
	    /*
	     * Init completed.
	     * Compile clock ensemble (performance purposes).
	     */
	    Tcl_Command token = Tcl_FindCommand(interp, "::clock",
		    NULL, TCL_GLOBAL_ONLY);
	    if (!token) {
		return TCL_ERROR;
	    }
	    int ensFlags = 0;
	    if (Tcl_GetEnsembleFlags(interp, token, &ensFlags) != TCL_OK) {
		return TCL_ERROR;
	    }
	    ensFlags |= ENSEMBLE_COMPILE;
	    if (Tcl_SetEnsembleFlags(interp, token, ensFlags) != TCL_OK) {
		return TCL_ERROR;
	    }
	    break;
	}
	}
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ClockGetTZData --
 *
 *	Retrieves tzdata table for given normalized timezone.
 *
 * Results:
 *	Returns a tcl object with tzdata.
 *
 * Side effects:
 *	The tzdata can be cached in ClockClientData structure.
 *
 *----------------------------------------------------------------------
 */

static inline Tcl_Obj *
ClockGetTZData(
    ClockClientData *dataPtr,	/* Opaque pointer to literal pool, etc. */
    Tcl_Interp *interp,		/* Tcl interpreter */
    Tcl_Obj *timezoneObj)	/* Name of the timezone */
{
    Tcl_Obj *ret, **out = NULL;

    /* if cached (if already setup this one) */
    if (timezoneObj == dataPtr->lastSetupTimeZone
	    || timezoneObj == dataPtr->lastSetupTimeZoneUnnorm) {
	if (dataPtr->lastSetupTZData != NULL) {
	    return dataPtr->lastSetupTZData;
	}
	out = &dataPtr->lastSetupTZData;
    }
    /* differentiate GMT and system zones, because used often */
    /* simple caching, because almost used the tz-data of last timezone
     */
    if (timezoneObj == dataPtr->systemTimeZone) {
	if (dataPtr->systemSetupTZData != NULL) {
	    return dataPtr->systemSetupTZData;
	}
	out = &dataPtr->systemSetupTZData;
    } else if (timezoneObj == dataPtr->literals[LIT_GMT]
	    || timezoneObj == dataPtr->gmtSetupTimeZoneUnnorm) {
	if (dataPtr->gmtSetupTZData != NULL) {
	    return dataPtr->gmtSetupTZData;
	}
	out = &dataPtr->gmtSetupTZData;
    } else if (timezoneObj == dataPtr->prevSetupTimeZone
	    || timezoneObj == dataPtr->prevSetupTimeZoneUnnorm) {
	if (dataPtr->prevSetupTZData != NULL) {
	    return dataPtr->prevSetupTZData;
	}
	out = &dataPtr->prevSetupTZData;
    }

    ret = Tcl_ObjGetVar2(interp, dataPtr->literals[LIT_TZDATA],
	    timezoneObj, TCL_LEAVE_ERR_MSG);

    /* cache using corresponding slot and as last used */
    if (out != NULL) {
	TclSetObjRef(*out, ret);
    } else if (dataPtr->lastSetupTimeZone != timezoneObj) {
	SavePrevTimezoneObj(dataPtr);
	TclSetObjRef(dataPtr->lastSetupTimeZone, timezoneObj);
	TclUnsetObjRef(dataPtr->lastSetupTimeZoneUnnorm);
	TclSetObjRef(dataPtr->lastSetupTZData, ret);
    }
    return ret;
}

/*
 *----------------------------------------------------------------------
 *
 * ClockGetSystemTimeZone --
 *
 *	Returns system (current) timezone.
 *
 *	If system zone not yet cached, it executes ::tcl::clock::GetSystemTimeZone
 *	in given interpreter and caches its result.
 *
 * Results:
 *	Returns normalized timezone object.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Obj *
ClockGetSystemTimeZone(
    ClockClientData *dataPtr,	/* Pointer to literal pool, etc. */
    Tcl_Interp *interp)		/* Tcl interpreter */
{
    /* if known (cached and same epoch) - return now */
    if (dataPtr->systemTimeZone != NULL
	    && dataPtr->lastTZEpoch == TzsetIfNecessary()) {
	return dataPtr->systemTimeZone;
    }

    TclUnsetObjRef(dataPtr->systemTimeZone);
    TclUnsetObjRef(dataPtr->systemSetupTZData);

    if (Tcl_EvalObjv(interp, 1, &dataPtr->literals[LIT_GETSYSTEMTIMEZONE], 0) != TCL_OK) {
	return NULL;
    }
    if (dataPtr->systemTimeZone == NULL) {
	TclSetObjRef(dataPtr->systemTimeZone, Tcl_GetObjResult(interp));
    }
    Tcl_ResetResult(interp);
    return dataPtr->systemTimeZone;
}

/*
 *----------------------------------------------------------------------
 *
 * ClockSetupTimeZone --
 *
 *	Sets up the timezone. Loads tzdata, etc.
 *
 * Results:
 *	Returns normalized timezone object.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
ClockSetupTimeZone(
    ClockClientData *dataPtr,	/* Pointer to literal pool, etc. */
    Tcl_Interp *interp,		/* Tcl interpreter */
    Tcl_Obj *timezoneObj)
{
    int loaded;
    Tcl_Obj *callargs[2];

    /* if cached (if already setup this one) */
    if (timezoneObj == dataPtr->literals[LIT_GMT]
	    && dataPtr->gmtSetupTZData != NULL) {
	return timezoneObj;
    }
    if ((timezoneObj == dataPtr->lastSetupTimeZone
	    || timezoneObj == dataPtr->lastSetupTimeZoneUnnorm)
	    && dataPtr->lastSetupTimeZone != NULL) {
	return dataPtr->lastSetupTimeZone;
    }
    if ((timezoneObj == dataPtr->prevSetupTimeZone
	    || timezoneObj == dataPtr->prevSetupTimeZoneUnnorm)
	    && dataPtr->prevSetupTimeZone != NULL) {
	return dataPtr->prevSetupTimeZone;
    }

    /* differentiate normalized (last, GMT and system) zones, because used often and already set */
    callargs[1] = NormTimezoneObj(dataPtr, timezoneObj, &loaded);
    /* if loaded (setup already called for this TZ) */
    if (loaded) {
	return callargs[1];
    }

    /* before setup just take a look in TZData variable */
    if (Tcl_ObjGetVar2(interp, dataPtr->literals[LIT_TZDATA], timezoneObj, 0)) {
	/* put it to last slot and return normalized */
	TimezoneLoaded(dataPtr, callargs[1], timezoneObj);
	return callargs[1];
    }
    /* setup now */
    callargs[0] = dataPtr->literals[LIT_SETUPTIMEZONE];
    if (Tcl_EvalObjv(interp, 2, callargs, 0) == TCL_OK) {
	/* save unnormalized last used */
	TclSetObjRef(dataPtr->lastSetupTimeZoneUnnorm, timezoneObj);
	return callargs[1];
    }
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * ClockFormatNumericTimeZone --
 *
 *	Formats a time zone as +hhmmss
 *
 * Parameters:
 *	z - Time zone in seconds east of Greenwich
 *
 * Results:
 *	Returns the time zone object (formatted in a numeric form)
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
ClockFormatNumericTimeZone(
    int z)
{
    char buf[12 + 1], *p;

    if (z < 0) {
	z = -z;
	*buf = '-';
    } else {
	*buf = '+';
    }
    TclItoAw(buf + 1, z / 3600, '0', 2);
    z %= 3600;
    p = TclItoAw(buf + 3, z / 60, '0', 2);
    z %= 60;
    if (z != 0) {
	p = TclItoAw(buf + 5, z, '0', 2);
    }
    return Tcl_NewStringObj(buf, p - buf);
}

/*
 *----------------------------------------------------------------------
 *
 * ClockConvertlocaltoutcObjCmd --
 *
 *	Tcl command that converts a UTC time to a local time by whatever means
 *	is available.
 *
 * Usage:
 *	::tcl::clock::ConvertUTCToLocal dictionary tzdata changeover
 *	::tcl::clock::ConvertUTCToLocal dictionary timezone changeover
 *
 * Parameters:
 *	dict - Dictionary containing a 'localSeconds' entry.
 *	tzdata - Time zone data
 *	timezone - Time zone
 *	changeover - Julian Day of the adoption of the Gregorian calendar.
 *
 * Results:
 *	Returns a standard Tcl result.
 *
 * Side effects:
 *	On success, sets the interpreter result to the given dictionary
 *	augmented with a 'seconds' field giving the UTC time. On failure,
 *	leaves an error message in the interpreter result.
 *
 *----------------------------------------------------------------------
 */

static int
ClockConvertlocaltoutcObjCmd(
    ClientData clientData,	/* Client data */
    void *clientData,		/* Literal table */
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const *objv)	/* Parameter vector */
{
    ClockClientData *data = (ClockClientData *)clientData;
    ClockClientData *dataPtr = (ClockClientData *)clientData;
    Tcl_Obj *const *lit = data->literals;
    Tcl_Obj *secondsObj;
    Tcl_Obj *dict;
    int changeover;
    TclDateFields fields;
    int created = 0;
    int status;

    fields.tzName = NULL;
    /*
     * Check params and convert time.
     */

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "dict tzdata changeover");
	Tcl_WrongNumArgs(interp, 1, objv, "dict timezone changeover");
	return TCL_ERROR;
    }
    dict = objv[1];
    if (Tcl_DictObjGet(interp, dict, lit[LIT_LOCALSECONDS],
    if (Tcl_DictObjGet(interp, dict, dataPtr->literals[LIT_LOCALSECONDS],
	    &secondsObj)!= TCL_OK) {
	return TCL_ERROR;
    }
    if (secondsObj == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("key \"localseconds\" not "
		"found in dictionary", -1));
		"found in dictionary", TCL_AUTO_LENGTH));
	return TCL_ERROR;
    }
    if ((TclGetWideIntFromObj(interp, secondsObj,
    if ((TclGetWideIntFromObj(interp, secondsObj, &fields.localSeconds) != TCL_OK)
	    &fields.localSeconds) != TCL_OK)
	|| (TclGetIntFromObj(interp, objv[3], &changeover) != TCL_OK)
	|| ConvertLocalToUTC(interp, &fields, objv[2], changeover)) {
	    || (TclGetIntFromObj(interp, objv[3], &changeover) != TCL_OK)
	    || ConvertLocalToUTC(dataPtr, interp, &fields, objv[2], changeover)) {
	return TCL_ERROR;
    }

    /*
     * Copy-on-write; set the 'seconds' field in the dictionary and place the
     * modified dictionary in the interpreter result.
     */

    if (Tcl_IsShared(dict)) {
	dict = Tcl_DuplicateObj(dict);
	created = 1;
	Tcl_IncrRefCount(dict);
    }
    status = Tcl_DictObjPut(interp, dict, lit[LIT_SECONDS],
    status = Tcl_DictObjPut(interp, dict, dataPtr->literals[LIT_SECONDS],
	    Tcl_NewWideIntObj(fields.seconds));
    if (status == TCL_OK) {
	Tcl_SetObjResult(interp, dict);
    }
    if (created) {
	Tcl_DecrRefCount(dict);
    }
    return status;
}

/*
 *----------------------------------------------------------------------
 *
 * ClockGetdatefieldsObjCmd --
 *
 *	Tcl command that determines the values that [clock format] will use in
 *	formatting a date, and populates a dictionary with them.
 *
 * Usage:
 *	::tcl::clock::GetDateFields seconds tzdata changeover
 *	::tcl::clock::GetDateFields seconds timezone changeover
 *
 * Parameters:
 *	seconds - Time expressed in seconds from the Posix epoch.
 *	tzdata - Time zone data of the time zone in which time is to be
 *	timezone - Time zone in which time is to be expressed.
 *		 expressed.
 *	changeover - Julian Day Number at which the current locale adopted
 *		     the Gregorian calendar
 *
 * Results:
 *	Returns a dictonary populated with the fields:
 *		seconds - Seconds from the Posix epoch
 *		localSeconds - Nominal seconds from the Posix epoch in the
 *			       local time zone.
 *		tzOffset - Time zone offset in seconds east of Greenwich
 *		tzName - Time zone name
 *		julianDay - Julian Day Number in the local time zone
 *
 *----------------------------------------------------------------------
 */

int
ClockGetdatefieldsObjCmd(
    ClientData clientData,	/* Opaque pointer to literal pool, etc. */
    void *clientData,		/* Opaque pointer to literal pool, etc. */
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const *objv)	/* Parameter vector */
{
    TclDateFields fields;
    Tcl_Obj *dict;
    ClockClientData *data = (ClockClientData *)clientData;
    Tcl_Obj *const *lit = data->literals;
    ClockClientData *dataPtr = (ClockClientData *)clientData;
    Tcl_Obj *const *lit = dataPtr->literals;
    int changeover;

    fields.tzName = NULL;

    /*
     * Check params.
     */

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "seconds tzdata changeover");
	Tcl_WrongNumArgs(interp, 1, objv, "seconds timezone changeover");
	return TCL_ERROR;
    }
    if (TclGetWideIntFromObj(interp, objv[1], &fields.seconds) != TCL_OK
	    || TclGetIntFromObj(interp, objv[3], &changeover) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * fields.seconds could be an unsigned number that overflowed. Make sure
     * that it isn't.
     */

    if (TclHasIntRep(objv[1], &tclBignumType)) {
    if (TclHasInternalRep(objv[1], &tclBignumType)) {
	Tcl_SetObjResult(interp, lit[LIT_INTEGER_VALUE_TOO_LARGE]);
	return TCL_ERROR;
    }

    /*
    /* Extract fields */
     * Convert UTC time to local.
     */

    if (ClockGetDateFields(dataPtr, interp, &fields, objv[2],
    if (ConvertUTCToLocal(interp, &fields, objv[2], changeover) != TCL_OK) {
	    changeover) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Extract Julian day.
     */

    /* Make dict of fields */
    fields.julianDay = (int) ((fields.localSeconds + JULIAN_SEC_POSIX_EPOCH)
	    / SECONDS_PER_DAY);

    /*
     * Convert to Julian or Gregorian calendar.
     */

    GetGregorianEraYearDay(&fields, changeover);
    GetMonthDay(&fields);
    GetYearWeekDay(&fields, changeover);

    dict = Tcl_NewDictObj();
    Tcl_DictObjPut(NULL, dict, lit[LIT_LOCALSECONDS],
	    Tcl_NewWideIntObj(fields.localSeconds));
    Tcl_DictObjPut(NULL, dict, lit[LIT_SECONDS],
	    Tcl_NewWideIntObj(fields.seconds));
    Tcl_DictObjPut(NULL, dict, lit[LIT_TZNAME], fields.tzName);
507
508
509
510
511
512
513




















































514
515
516
517
518
519
520
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    Tcl_NewWideIntObj(fields.iso8601Year));
    Tcl_DictObjPut(NULL, dict, lit[LIT_ISO8601WEEK],
	    Tcl_NewWideIntObj(fields.iso8601Week));
    Tcl_DictObjPut(NULL, dict, lit[LIT_DAYOFWEEK],
	    Tcl_NewWideIntObj(fields.dayOfWeek));
    Tcl_SetObjResult(interp, dict);

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ClockGetDateFields --
 *
 *	Converts given UTC time (seconds in a TclDateFields structure)
 *	to local time and determines the values that clock routines will
 *	use in scanning or formatting a date.
 *
 * Results:
 *	Date-time values are stored in structure "fields".
 *	Returns a standard Tcl result.
 *
 *----------------------------------------------------------------------
 */

int
ClockGetDateFields(
    ClockClientData *dataPtr,	/* Literal pool, etc. */
    Tcl_Interp *interp,		/* Tcl interpreter */
    TclDateFields *fields,	/* Pointer to result fields, where
				 * fields->seconds contains date to extract */
    Tcl_Obj *timezoneObj,	/* Time zone object or NULL for gmt */
    int changeover)		/* Julian Day Number */
{
    /*
     * Convert UTC time to local.
     */

    if (ConvertUTCToLocal(dataPtr, interp, fields, timezoneObj,
	    changeover) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Extract Julian day and seconds of the day.
     */

    ClockExtractJDAndSODFromSeconds(fields->julianDay, fields->secondOfDay,
	    fields->localSeconds);

    /*
     * Convert to Julian or Gregorian calendar.
     */

    GetGregorianEraYearDay(fields, changeover);
    GetMonthDay(fields);
    GetYearWeekDay(fields, changeover);

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ClockGetjuliandayfromerayearmonthdayObjCmd --
545
546
547
548
549
550
551
552

553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572

573
574
575
576
577
578
579
580

581
582
583
584
585
586
587
588
589
590
591
592


593
594
595
596
597
598
599
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







-
+



















-
+







-
+












+
+







    Tcl_Obj *value = NULL;

    if (Tcl_DictObjGet(interp, dict, key, &value) != TCL_OK) {
	return TCL_ERROR;
    }
    if (value == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"expected key(s) not found in dictionary", -1));
		"expected key(s) not found in dictionary", TCL_AUTO_LENGTH));
	return TCL_ERROR;
    }
    return Tcl_GetIndexFromObj(interp, value, eras, "era", TCL_EXACT, storePtr);
}

static int
FetchIntField(
    Tcl_Interp *interp,
    Tcl_Obj *dict,
    Tcl_Obj *key,
    int *storePtr)
{
    Tcl_Obj *value = NULL;

    if (Tcl_DictObjGet(interp, dict, key, &value) != TCL_OK) {
	return TCL_ERROR;
    }
    if (value == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"expected key(s) not found in dictionary", -1));
		"expected key(s) not found in dictionary", TCL_AUTO_LENGTH));
	return TCL_ERROR;
    }
    return TclGetIntFromObj(interp, value, storePtr);
}

static int
ClockGetjuliandayfromerayearmonthdayObjCmd(
    ClientData clientData,	/* Opaque pointer to literal pool, etc. */
    void *clientData,		/* Opaque pointer to literal pool, etc. */
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const *objv)	/* Parameter vector */
{
    TclDateFields fields;
    Tcl_Obj *dict;
    ClockClientData *data = (ClockClientData *)clientData;
    Tcl_Obj *const *lit = data->literals;
    int changeover;
    int copied = 0;
    int status;
    int isBce = 0;

    fields.tzName = NULL;

    /*
     * Check params.
     */

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "dict changeover");
657
658
659
660
661
662
663
664

665
666
667
668
669
670
671
672
673
674
675
676


677
678
679
680
681
682
683
1765
1766
1767
1768
1769
1770
1771

1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793







-
+












+
+







 *	result being an error message.
 *
 *----------------------------------------------------------------------
 */

static int
ClockGetjuliandayfromerayearweekdayObjCmd(
    ClientData clientData,	/* Opaque pointer to literal pool, etc. */
    void *clientData,		/* Opaque pointer to literal pool, etc. */
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const *objv)	/* Parameter vector */
{
    TclDateFields fields;
    Tcl_Obj *dict;
    ClockClientData *data = (ClockClientData *)clientData;
    Tcl_Obj *const *lit = data->literals;
    int changeover;
    int copied = 0;
    int status;
    int isBce = 0;

    fields.tzName = NULL;

    /*
     * Check params.
     */

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "dict changeover");
738
739
740
741
742
743
744

745
746
747

748
749

750

751


752







753



























754
755





756
757
758
759
760
761
762
763
764
765
766
767






768


769
770









































771
772
773
774
775
776
777
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857

1858
1859
1860
1861

1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976







+


-
+


+
-
+

+
+

+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+











-
+
+
+
+
+
+

+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *	in the interpreter result on failure.
 *
 *----------------------------------------------------------------------
 */

static int
ConvertLocalToUTC(
    ClockClientData *dataPtr,	/* Literal pool, etc. */
    Tcl_Interp *interp,		/* Tcl interpreter */
    TclDateFields *fields,	/* Fields of the time */
    Tcl_Obj *tzdata,		/* Time zone data */
    Tcl_Obj *timezoneObj,	/* Time zone */
    int changeover)		/* Julian Day of the Gregorian transition */
{
    Tcl_Obj *tzdata;		/* Time zone data */
    int rowc;			/* Number of rows in tzdata */
    Tcl_Size rowc;		/* Number of rows in tzdata */
    Tcl_Obj **rowv;		/* Pointers to the rows */
    Tcl_WideInt seconds;
    ClockLastTZOffs * ltzoc = NULL;

    /* fast phase-out for shared GMT-object (don't need to convert UTC 2 UTC) */
    if (timezoneObj == dataPtr->literals[LIT_GMT]) {
	fields->seconds = fields->localSeconds;
	fields->tzOffset = 0;
	return TCL_OK;
    }

    /*
     * Check cacheable conversion could be used
     * (last-period UTC2Local cache within the same TZ and seconds)
     */
    for (rowc = 0; rowc < 2; rowc++) {
	ltzoc = &dataPtr->lastTZOffsCache[rowc];
	if (timezoneObj != ltzoc->timezoneObj || changeover != ltzoc->changeover) {
	    ltzoc = NULL;
	    continue;
	}
	seconds = fields->localSeconds - ltzoc->tzOffset;
	if (seconds >= ltzoc->rangesVal[0]
		&& seconds < ltzoc->rangesVal[1]) {
	    /* the same time zone and offset (UTC time inside the last minute) */
	    fields->tzOffset = ltzoc->tzOffset;
	    fields->seconds = seconds;
	    return TCL_OK;
	}
	/* in the DST-hole (because of the check above) - correct localSeconds */
	if (fields->localSeconds == ltzoc->localSeconds) {
	    /* the same time zone and offset (but we'll shift local-time) */
	    fields->tzOffset = ltzoc->tzOffset;
	    fields->seconds = seconds;
	    goto dstHole;
	}
    }

    /*
     * Unpack the tz data.
     */

    tzdata = ClockGetTZData(dataPtr, interp, timezoneObj);
    if (tzdata == NULL) {
	return TCL_ERROR;
    }

    if (TclListObjGetElements(interp, tzdata, &rowc, &rowv) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Special case: If the time zone is :localtime, the tzdata will be empty.
     * Use 'mktime' to convert the time to local
     */

    if (rowc == 0) {
	return ConvertLocalToUTCUsingC(interp, fields, changeover);
	if (ConvertLocalToUTCUsingC(interp, fields, changeover) != TCL_OK) {
	    return TCL_ERROR;
	}

	/* we cannot cache (ranges unknown yet) - todo: check later the DST-hole here */
	return TCL_OK;
    } else {
	Tcl_WideInt rangesVal[2];

	return ConvertLocalToUTCUsingTable(interp, fields, rowc, rowv);
    }
	if (ConvertLocalToUTCUsingTable(interp, fields, rowc, rowv,
		rangesVal) != TCL_OK) {
	    return TCL_ERROR;
	}

	seconds = fields->seconds;

	/* Cache the last conversion */
	if (ltzoc != NULL) { /* slot was found above */
	    /* timezoneObj and changeover are the same */
	    TclSetObjRef(ltzoc->tzName, fields->tzName); /* may be NULL */
	} else {
	    /* no TZ in cache - just move second slot down and use the first one */
	    ltzoc = &dataPtr->lastTZOffsCache[0];
	    TclUnsetObjRef(dataPtr->lastTZOffsCache[1].timezoneObj);
	    TclUnsetObjRef(dataPtr->lastTZOffsCache[1].tzName);
	    memcpy(&dataPtr->lastTZOffsCache[1], ltzoc, sizeof(*ltzoc));
	    TclInitObjRef(ltzoc->timezoneObj, timezoneObj);
	    ltzoc->changeover = changeover;
	    TclInitObjRef(ltzoc->tzName, fields->tzName); /* may be NULL */
	}
	ltzoc->localSeconds = fields->localSeconds;
	ltzoc->rangesVal[0] = rangesVal[0];
	ltzoc->rangesVal[1] = rangesVal[1];
	ltzoc->tzOffset = fields->tzOffset;
    }

    /* check DST-hole: if retrieved seconds is out of range */
    if (ltzoc->rangesVal[0] > seconds || seconds >= ltzoc->rangesVal[1]) {
    dstHole:
#if 0
	printf("given local-time is outside the time-zone (in DST-hole): "
		"%" TCL_LL_MODIFIER "d - offs %d => %" TCL_LL_MODIFIER "d <= %" TCL_LL_MODIFIER "d < %" TCL_LL_MODIFIER "d\n",
		fields->localSeconds, fields->tzOffset,
		ltzoc->rangesVal[0], seconds, ltzoc->rangesVal[1]);
#endif
	/* because we don't know real TZ (we're outsize), just invalidate local
	 * time (which could be verified in ClockValidDate later) */
	fields->localSeconds = TCL_INV_SECONDS; /* not valid seconds */
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ConvertLocalToUTCUsingTable --
 *
789
790
791
792
793
794
795
796


797
798
799

800



801

802
803

804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820



821
822
823
824
825
826
827
828
829
830
831



832
833
834
835
836
837
838
839





840
841
842


843

844


845
846
847
848
849
850
851
1988
1989
1990
1991
1992
1993
1994

1995
1996
1997
1998

1999
2000
2001
2002
2003

2004
2005

2006

2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017

2018
2019


2020
2021
2022
2023
2024
2025
2026
2027
2028
2029




2030
2031
2032

2033
2034





2035
2036
2037
2038
2039

2040
2041
2042
2043

2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054







-
+
+


-
+

+
+
+
-
+

-
+
-











-


-
-
+
+
+







-
-
-
-
+
+
+
-


-
-
-
-
-
+
+
+
+
+
-


+
+
-
+

+
+







 */

static int
ConvertLocalToUTCUsingTable(
    Tcl_Interp *interp,		/* Tcl interpreter */
    TclDateFields *fields,	/* Time to convert, with 'seconds' filled in */
    int rowc,			/* Number of points at which time changes */
    Tcl_Obj *const rowv[])	/* Points at which time changes */
    Tcl_Obj *const rowv[],	/* Points at which time changes */
    Tcl_WideInt *rangesVal)	/* Return bounds for time period */
{
    Tcl_Obj *row;
    int cellc;
    Tcl_Size cellc;
    Tcl_Obj **cellv;
    struct {
	Tcl_Obj *tzName;
	int tzOffset;
    int have[8];
    } have[8];
    int nHave = 0;
    int i;
    Tcl_Size i;
    int found;

    /*
     * Perform an initial lookup assuming that local == UTC, and locate the
     * last time conversion prior to that time. Get the offset from that row,
     * and look up again. Continue until we find an offset that we found
     * before. This definition, rather than "the same offset" ensures that we
     * don't enter an endless loop, as would otherwise happen when trying to
     * convert a non-existent time such as 02:30 during the US Spring Daylight
     * Saving Time transition.
     */

    found = 0;
    fields->tzOffset = 0;
    fields->seconds = fields->localSeconds;
    while (!found) {
	row = LookupLastTransition(interp, fields->seconds, rowc, rowv);
    while (1) {
	row = LookupLastTransition(interp, fields->seconds, rowc, rowv,
		rangesVal);
	if ((row == NULL)
		|| TclListObjGetElements(interp, row, &cellc,
		    &cellv) != TCL_OK
		|| TclGetIntFromObj(interp, cellv[1],
		    &fields->tzOffset) != TCL_OK) {
	    return TCL_ERROR;
	}
	found = 0;
	for (i = 0; !found && i < nHave; ++i) {
	    if (have[i] == fields->tzOffset) {
		found = 1;
	for (i = 0; i < nHave; ++i) {
	    if (have[i].tzOffset == fields->tzOffset) {
		goto found;
		break;
	    }
	}
	if (!found) {
	    if (nHave == 8) {
		Tcl_Panic("loop in ConvertLocalToUTCUsingTable");
	    }
	    have[nHave++] = fields->tzOffset;
	if (nHave == 8) {
	    Tcl_Panic("loop in ConvertLocalToUTCUsingTable");
	}
	have[nHave].tzName = cellv[3];
	have[nHave++].tzOffset = fields->tzOffset;
	}
	fields->seconds = fields->localSeconds - fields->tzOffset;
    }

  found:
    fields->tzOffset = have[i];
    fields->tzOffset = have[i].tzOffset;
    fields->seconds = fields->localSeconds - fields->tzOffset;
    TclSetObjRef(fields->tzName, have[i].tzName);

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ConvertLocalToUTCUsingC --
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882

883
884
885
886
887


888
889
890
891
892
893
894
2071
2072
2073
2074
2075
2076
2077

2078
2079
2080
2081
2082


2083





2084
2085
2086
2087
2088
2089
2090
2091
2092







-





-
-
+
-
-
-
-
-
+
+







    Tcl_Interp *interp,		/* Tcl interpreter */
    TclDateFields *fields,	/* Time to convert, with 'seconds' filled in */
    int changeover)		/* Julian Day of the Gregorian transition */
{
    struct tm timeVal;
    int localErrno;
    int secondOfDay;
    Tcl_WideInt jsec;

    /*
     * Convert the given time to a date.
     */

    jsec = fields->localSeconds + JULIAN_SEC_POSIX_EPOCH;
    fields->julianDay = (int) (jsec / SECONDS_PER_DAY);
    ClockExtractJDAndSODFromSeconds(fields->julianDay, secondOfDay,
    secondOfDay = (int)(jsec % SECONDS_PER_DAY);
    if (secondOfDay < 0) {
	secondOfDay += SECONDS_PER_DAY;
	fields->julianDay--;
    }
	    fields->localSeconds);

    GetGregorianEraYearDay(fields, changeover);
    GetMonthDay(fields);

    /*
     * Convert the date/time to a 'struct tm'.
     */

907
908
909
910
911
912
913
914

915
916
917
918
919
920
921
922
923
924

925
926
927
928
929
930
931
2105
2106
2107
2108
2109
2110
2111

2112
2113
2114
2115
2116
2117
2118
2119
2120
2121

2122
2123
2124
2125
2126
2127
2128
2129







-
+









-
+







     * platforms, so seize a mutex before attempting this.
     */

    TzsetIfNecessary();
    Tcl_MutexLock(&clockMutex);
    errno = 0;
    fields->seconds = (Tcl_WideInt) mktime(&timeVal);
    localErrno = errno;
    localErrno = (fields->seconds == -1) ? errno : 0;
    Tcl_MutexUnlock(&clockMutex);

    /*
     * If conversion fails, report an error.
     */

    if (localErrno != 0
	    || (fields->seconds == -1 && timeVal.tm_yday == -1)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"time value too large/small to represent", -1));
		"time value too large/small to represent", TCL_AUTO_LENGTH));
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
939
940
941
942
943
944
945
946

947

948
949
950

951
952

953

954

955


















956




















957
958





959
960
961
962
963
964
965
966
967
968
969
970








971


972
973





























974
975
976
977
978
979
980
2137
2138
2139
2140
2141
2142
2143

2144
2145
2146
2147
2148

2149
2150
2151
2152

2153
2154
2155
2156
2157
2158
2159
2160
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
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







-
+

+


-
+


+
-
+

+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+











-
+
+
+
+
+
+
+
+

+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *
 * Side effects:
 *	Populates the 'tzName' and 'tzOffset' fields.
 *
 *----------------------------------------------------------------------
 */

static int
int
ConvertUTCToLocal(
    ClockClientData *dataPtr,	/* Literal pool, etc. */
    Tcl_Interp *interp,		/* Tcl interpreter */
    TclDateFields *fields,	/* Fields of the time */
    Tcl_Obj *tzdata,		/* Time zone data */
    Tcl_Obj *timezoneObj,	/* Time zone */
    int changeover)		/* Julian Day of the Gregorian transition */
{
    Tcl_Obj *tzdata;		/* Time zone data */
    int rowc;			/* Number of rows in tzdata */
    Tcl_Size rowc;		/* Number of rows in tzdata */
    Tcl_Obj **rowv;		/* Pointers to the rows */
    ClockLastTZOffs * ltzoc = NULL;

    /* fast phase-out for shared GMT-object (don't need to convert UTC 2 UTC) */
    if (timezoneObj == dataPtr->literals[LIT_GMT]) {
	fields->localSeconds = fields->seconds;
	fields->tzOffset = 0;
	if (dataPtr->gmtTZName == NULL) {
	    Tcl_Obj *tzName;

	    tzdata = ClockGetTZData(dataPtr, interp, timezoneObj);
	    if (TclListObjGetElements(interp, tzdata, &rowc, &rowv) != TCL_OK
		    || Tcl_ListObjIndex(interp, rowv[0], 3, &tzName) != TCL_OK) {
		return TCL_ERROR;
	    }
	    TclSetObjRef(dataPtr->gmtTZName, tzName);
	}
	TclSetObjRef(fields->tzName, dataPtr->gmtTZName);
	return TCL_OK;
    }

    /*
     * Check cacheable conversion could be used
     * (last-period UTC2Local cache within the same TZ and seconds)
     */
    for (rowc = 0; rowc < 2; rowc++) {
	ltzoc = &dataPtr->lastTZOffsCache[rowc];
	if (timezoneObj != ltzoc->timezoneObj || changeover != ltzoc->changeover) {
	    ltzoc = NULL;
	    continue;
	}
	if (fields->seconds >= ltzoc->rangesVal[0]
		&& fields->seconds < ltzoc->rangesVal[1]) {
	    /* the same time zone and offset (UTC time inside the last minute) */
	    fields->tzOffset = ltzoc->tzOffset;
	    fields->localSeconds = fields->seconds + fields->tzOffset;
	    TclSetObjRef(fields->tzName, ltzoc->tzName);
	    return TCL_OK;
	}
    }

    /*
     * Unpack the tz data.
     */

    tzdata = ClockGetTZData(dataPtr, interp, timezoneObj);
    if (tzdata == NULL) {
	return TCL_ERROR;
    }

    if (TclListObjGetElements(interp, tzdata, &rowc, &rowv) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Special case: If the time zone is :localtime, the tzdata will be empty.
     * Use 'localtime' to convert the time to local
     */

    if (rowc == 0) {
	return ConvertUTCToLocalUsingC(interp, fields, changeover);
	if (ConvertUTCToLocalUsingC(interp, fields, changeover) != TCL_OK) {
	    return TCL_ERROR;
	}

	/* signal we need to revalidate TZ epoch next time fields gets used. */
	fields->flags |= CLF_CTZ;

	/* we cannot cache (ranges unknown yet) */
    } else {
	Tcl_WideInt rangesVal[2];

	return ConvertUTCToLocalUsingTable(interp, fields, rowc, rowv);
    }
	if (ConvertUTCToLocalUsingTable(interp, fields, rowc, rowv,
		rangesVal) != TCL_OK) {
	    return TCL_ERROR;
	}

	/* converted using table (TZ isn't :localtime) */
	fields->flags &= ~CLF_CTZ;

	/* Cache the last conversion */
	if (ltzoc != NULL) { /* slot was found above */
	    /* timezoneObj and changeover are the same */
	    TclSetObjRef(ltzoc->tzName, fields->tzName);
	} else {
	    /* no TZ in cache - just move second slot down and use the first one */
	    ltzoc = &dataPtr->lastTZOffsCache[0];
	    TclUnsetObjRef(dataPtr->lastTZOffsCache[1].timezoneObj);
	    TclUnsetObjRef(dataPtr->lastTZOffsCache[1].tzName);
	    memcpy(&dataPtr->lastTZOffsCache[1], ltzoc, sizeof(*ltzoc));
	    TclInitObjRef(ltzoc->timezoneObj, timezoneObj);
	    ltzoc->changeover = changeover;
	    TclInitObjRef(ltzoc->tzName, fields->tzName);
	}
	ltzoc->localSeconds = fields->localSeconds;
	ltzoc->rangesVal[0] = rangesVal[0];
	ltzoc->rangesVal[1] = rangesVal[1];
	ltzoc->tzOffset = fields->tzOffset;
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ConvertUTCToLocalUsingTable --
 *
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
1024
1025
1026
1027
1028
1029
2271
2272
2273
2274
2275
2276
2277

2278
2279

2280
2281
2282
2283

2284
2285
2286
2287
2288
2289
2290




2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301

2302

2303
2304
2305
2306
2307
2308
2309







-
+

-
+
+


-
+






-
-
-
-
+
+
+
+







-
+
-







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

static int
ConvertUTCToLocalUsingTable(
    Tcl_Interp *interp,		/* Tcl interpreter */
    TclDateFields *fields,	/* Fields of the date */
    int rowc,			/* Number of rows in the conversion table
    Tcl_Size rowc,		/* Number of rows in the conversion table
				 * (>= 1) */
    Tcl_Obj *const rowv[])	/* Rows of the conversion table */
    Tcl_Obj *const rowv[],	/* Rows of the conversion table */
    Tcl_WideInt *rangesVal)	/* Return bounds for time period */
{
    Tcl_Obj *row;		/* Row containing the current information */
    int cellc;			/* Count of cells in the row (must be 4) */
    Tcl_Size cellc;		/* Count of cells in the row (must be 4) */
    Tcl_Obj **cellv;		/* Pointers to the cells */

    /*
     * Look up the nearest transition time.
     */

    row = LookupLastTransition(interp, fields->seconds, rowc, rowv);
    if (row == NULL ||
	    TclListObjGetElements(interp, row, &cellc, &cellv) != TCL_OK ||
	    TclGetIntFromObj(interp, cellv[1], &fields->tzOffset) != TCL_OK) {
    row = LookupLastTransition(interp, fields->seconds, rowc, rowv, rangesVal);
    if (row == NULL
	    || TclListObjGetElements(interp, row, &cellc, &cellv) != TCL_OK
	    || TclGetIntFromObj(interp, cellv[1], &fields->tzOffset) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Convert the time.
     */

    fields->tzName = cellv[3];
    TclSetObjRef(fields->tzName, cellv[3]);
    Tcl_IncrRefCount(fields->tzName);
    fields->localSeconds = fields->seconds + fields->tzOffset;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
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

1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134

1135
1136
1137
1138
1139



1140
1141
1142

1143
1144

1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160





1161
1162
1163
1164
1165
1166
1167
1168
1169

1170
1171

1172
1173
1174
1175
1176
1177
1178

1179
1180


1181
1182





1183
1184
1185
1186
1187
1188
1189
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

2390
2391


2392
2393
2394

2395

2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412

2413
2414
2415
2416


2417
2418
2419
2420


2421
2422

2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438

2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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







-
+








-
-
+
+







-
-
+
+

















-
+















-
+

-
+

-
-
+
+

-
+
-

















-
+



-
-
+
+
+

-
-
+

-
+















-
+
+
+
+
+








-
+

-
+







+

-
+
+


+
+
+
+
+







    Tcl_Interp *interp,		/* Tcl interpreter */
    TclDateFields *fields,	/* Time to convert, with 'seconds' filled in */
    int changeover)		/* Julian Day of the Gregorian transition */
{
    time_t tock;
    struct tm *timeVal;		/* Time after conversion */
    int diff;			/* Time zone diff local-Greenwich */
    char buffer[16];		/* Buffer for time zone name */
    char buffer[16], *p;	/* Buffer for time zone name */

    /*
     * Use 'localtime' to determine local year, month, day, time of day.
     */

    tock = (time_t) fields->seconds;
    if ((Tcl_WideInt) tock != fields->seconds) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"number too large to represent as a Posix time", -1));
	Tcl_SetErrorCode(interp, "CLOCK", "argTooLarge", NULL);
		"number too large to represent as a Posix time", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "CLOCK", "argTooLarge", (char *)NULL);
	return TCL_ERROR;
    }
    TzsetIfNecessary();
    timeVal = ThreadSafeLocalTime(&tock);
    if (timeVal == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"localtime failed (clock value may be too "
		"large/small to represent)", -1));
	Tcl_SetErrorCode(interp, "CLOCK", "localtimeFailed", NULL);
		"large/small to represent)", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "CLOCK", "localtimeFailed", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Fill in the date in 'fields' and use it to derive Julian Day.
     */

    fields->isBce = 0;
    fields->year = timeVal->tm_year + 1900;
    fields->month = timeVal->tm_mon + 1;
    fields->dayOfMonth = timeVal->tm_mday;
    GetJulianDayFromEraYearMonthDay(fields, changeover);

    /*
     * Convert that value to seconds.
     */

    fields->localSeconds = (((fields->julianDay * (Tcl_WideInt) 24
    fields->localSeconds = (((fields->julianDay * 24LL
	    + timeVal->tm_hour) * 60 + timeVal->tm_min) * 60
	    + timeVal->tm_sec) - JULIAN_SEC_POSIX_EPOCH;

    /*
     * Determine a time zone offset and name; just use +hhmm for the name.
     */

    diff = (int) (fields->localSeconds - fields->seconds);
    fields->tzOffset = diff;
    if (diff < 0) {
	*buffer = '-';
	diff = -diff;
    } else {
	*buffer = '+';
    }
    sprintf(buffer+1, "%02d", diff / 3600);
    TclItoAw(buffer + 1, diff / 3600, '0', 2);
    diff %= 3600;
    sprintf(buffer+3, "%02d", diff / 60);
    p = TclItoAw(buffer + 3, diff / 60, '0', 2);
    diff %= 60;
    if (diff > 0) {
	sprintf(buffer+5, "%02d", diff);
    if (diff != 0) {
	p = TclItoAw(buffer + 5, diff, '0', 2);
    }
    fields->tzName = Tcl_NewStringObj(buffer, -1);
    TclSetObjRef(fields->tzName, Tcl_NewStringObj(buffer, p - buffer));
    Tcl_IncrRefCount(fields->tzName);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * LookupLastTransition --
 *
 *	Given a UTC time and a tzdata array, looks up the last transition on
 *	or before the given time.
 *
 * Results:
 *	Returns a pointer to the row, or NULL if an error occurs.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Obj *
Tcl_Obj *
LookupLastTransition(
    Tcl_Interp *interp,		/* Interpreter for error messages */
    Tcl_WideInt tick,		/* Time from the epoch */
    int rowc,			/* Number of rows of tzdata */
    Tcl_Obj *const *rowv)	/* Rows in tzdata */
    Tcl_Size rowc,		/* Number of rows of tzdata */
    Tcl_Obj *const *rowv,	/* Rows in tzdata */
    Tcl_WideInt *rangesVal)	/* Return bounds for time period */
{
    int l;
    int u;
    Tcl_Size l, u;
    Tcl_Obj *compObj;
    Tcl_WideInt compVal;
    Tcl_WideInt compVal, fromVal = LLONG_MIN, toVal = LLONG_MAX;

    /*
     * Examine the first row to make sure we're in bounds.
     */

    if (Tcl_ListObjIndex(interp, rowv[0], 0, &compObj) != TCL_OK
	    || TclGetWideIntFromObj(interp, compObj, &compVal) != TCL_OK) {
	return NULL;
    }

    /*
     * Bizarre case - first row doesn't begin at MIN_WIDE_INT. Return it
     * anyway.
     */

    if (tick < compVal) {
    if (tick < (fromVal = compVal)) {
	if (rangesVal) {
	    rangesVal[0] = fromVal;
	    rangesVal[1] = toVal;
	}
	return rowv[0];
    }

    /*
     * Binary-search to find the transition.
     */

    l = 0;
    u = rowc-1;
    u = rowc - 1;
    while (l < u) {
	int m = (l + u + 1) / 2;
	Tcl_Size m = (l + u + 1) / 2;

	if (Tcl_ListObjIndex(interp, rowv[m], 0, &compObj) != TCL_OK ||
		TclGetWideIntFromObj(interp, compObj, &compVal) != TCL_OK) {
	    return NULL;
	}
	if (tick >= compVal) {
	    l = m;
	    fromVal = compVal;
	} else {
	    u = m-1;
	    u = m - 1;
	    toVal = compVal;
	}
    }

    if (rangesVal) {
	rangesVal[0] = fromVal;
	rangesVal[1] = toVal;
    }
    return rowv[l];
}

/*
 *----------------------------------------------------------------------
 *
 * GetYearWeekDay --
1205
1206
1207
1208
1209
1210
1211


1212
1213
1214
1215
1216
1217
1218
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510







+
+







GetYearWeekDay(
    TclDateFields *fields,	/* Date to convert, must have 'julianDay' */
    int changeover)		/* Julian Day Number of the Gregorian
				 * transition */
{
    TclDateFields temp;
    int dayOfFiscalYear;

    temp.tzName = NULL;

    /*
     * Find the given date, minus three days, plus one year. That date's
     * iso8601 year is an upper bound on the ISO8601 year of the given date.
     */

    temp.julianDay = fields->julianDay - 3;
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279




1280
1281
1282
1283
1284
1285
1286
2561
2562
2563
2564
2565
2566
2567




2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578







-
-
-
-
+
+
+
+







 */

static void
GetGregorianEraYearDay(
    TclDateFields *fields,	/* Date fields containing 'julianDay' */
    int changeover)		/* Gregorian transition date */
{
    int jday = fields->julianDay;
    int day;
    int year;
    int n;
    Tcl_WideInt jday = fields->julianDay;
    Tcl_WideInt day;
    Tcl_WideInt year;
    Tcl_WideInt n;

    if (jday >= changeover) {
	/*
	 * Gregorian calendar.
	 */

	fields->gregorian = 1;
1386
1387
1388
1389
1390
1391
1392
1393

1394












1395
1396
1397
1398








1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419

1420
1421
1422
1423
1424
1425

1426
1427


1428
1429
1430
1431
1432
1433
1434
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







-
+

+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+




















-
+





-
+


+
+








static void
GetMonthDay(
    TclDateFields *fields)	/* Date to convert */
{
    int day = fields->dayOfYear;
    int month;
    const int *h = hath[IsGregorianLeapYear(fields)];
    const int *dipm = daysInPriorMonths[IsGregorianLeapYear(fields)];

    /*
     * Estimate month by calculating `dayOfYear / (365/12)`
     */
    month = (day*12) / dipm[12];
    /* then do forwards backwards correction */
    while (1) {
	if (day > dipm[month]) {
	    if (month >= 11 || day <= dipm[month + 1]) {
		break;
	    }
	    month++;
	} else {
    for (month = 0; month < 12 && day > h[month]; ++month) {
	day -= h[month];
    }
    fields->month = month+1;
	    if (month == 0) {
		break;
	    }
	    month--;
	}
    }
    day -= dipm[month];
    fields->month = month + 1;
    fields->dayOfMonth = day;
}

/*
 *----------------------------------------------------------------------
 *
 * GetJulianDayFromEraYearWeekDay --
 *
 *	Given a TclDateFields structure containing era, ISO8601 year, ISO8601
 *	week, and day of week, computes the Julian Day Number.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Stores 'julianDay' in the fields.
 *
 *----------------------------------------------------------------------
 */

static void
void
GetJulianDayFromEraYearWeekDay(
    TclDateFields *fields,	/* Date to convert */
    int changeover)		/* Julian Day Number of the Gregorian
				 * transition */
{
    int firstMonday;		/* Julian day number of week 1, day 1 in the
    Tcl_WideInt firstMonday;	/* Julian day number of week 1, day 1 in the
				 * given year */
    TclDateFields firstWeek;

    firstWeek.tzName = NULL;

    /*
     * Find January 4 in the ISO8601 year, which will always be in week 1.
     */

    firstWeek.isBce = fields->isBce;
    firstWeek.year = fields->iso8601Year;
1463
1464
1465
1466
1467
1468
1469
1470

1471
1472
1473
1474

1475

1476
1477
1478
1479
1480
1481
1482
2773
2774
2775
2776
2777
2778
2779

2780
2781
2782
2783
2784
2785

2786
2787
2788
2789
2790
2791
2792
2793







-
+




+
-
+







 *
 * Side effects:
 *	Stores day number in 'julianDay'
 *
 *----------------------------------------------------------------------
 */

static void
void
GetJulianDayFromEraYearMonthDay(
    TclDateFields *fields,	/* Date to convert */
    int changeover)		/* Gregorian transition date as a Julian Day */
{
    Tcl_WideInt year, ym1, ym1o4, ym1o100, ym1o400;
    int year, ym1, month, mm1, q, r, ym1o4, ym1o100, ym1o400;
    int month, mm1, q, r;

    if (fields->isBce) {
	year = 1 - fields->year;
    } else {
	year = fields->year;
    }

1499
1500
1501
1502
1503
1504
1505
1506

1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523

1524
1525

1526
1527
1528
1529
1530
1531
1532
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







-
+
















-
+

-
+







    /*
     * Adjust the year after reducing the month.
     */

    fields->gregorian = 1;
    if (year < 1) {
	fields->isBce = 1;
	fields->year = 1-year;
	fields->year = 1 - year;
    } else {
	fields->isBce = 0;
	fields->year = year;
    }

    /*
     * Try an initial conversion in the Gregorian calendar.
     */

#if 0 /* BUG https://core.tcl-lang.org/tcl/tktview?name=da340d4f32 */
    ym1o4 = ym1 / 4;
#else
    /*
     * Have to make sure quotient is truncated towards 0 when negative.
     * See above bug for details. The casts are necessary.
     */
    if (ym1 >= 0)
    if (ym1 >= 0) {
	ym1o4 = ym1 / 4;
    else {
    } else {
	ym1o4 = - (int) (((unsigned int) -ym1) / 4);
    }
#endif
    if (ym1 % 4 < 0) {
	ym1o4--;
    }
    ym1o100 = ym1 / 100;
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
+



-
+




-
+



-
+

-
+




















-
+


-
+







		+ ym1o4;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * GetJulianDayFromEraYearDay --
 *
 *	Given era, year, and dayOfYear (in TclDateFields), and the
 *	Gregorian transition date, computes the Julian Day Number.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Stores day number in 'julianDay'
 *
 *----------------------------------------------------------------------
 */

void
GetJulianDayFromEraYearDay(
    TclDateFields *fields,	/* Date to convert */
    int changeover)		/* Gregorian transition date as a Julian Day */
{
    Tcl_WideInt year, ym1;

    /* Get absolute year number from the civil year */
    if (fields->isBce) {
	year = 1 - fields->year;
    } else {
	year = fields->year;
    }

    ym1 = year - 1;

    /* Try the Gregorian calendar first. */
    fields->gregorian = 1;
    fields->julianDay =
	    1721425
	    + fields->dayOfYear
	    + (365 * ym1)
	    + (ym1 / 4)
	    - (ym1 / 100)
	    + (ym1 / 400);

    /* If the date is before the Gregorian change, use the Julian calendar. */

    if (fields->julianDay < changeover) {
	fields->gregorian = 0;
	fields->julianDay =
		1721423
		+ fields->dayOfYear
		+ (365 * ym1)
		+ (ym1 / 4);
    }
}
/*
 *----------------------------------------------------------------------
 *
 * IsGregorianLeapYear --
 *
 *	Tests whether a given year is a leap year, in either Julian or
 *	Gregorian calendar.
 *
 * Results:
 *	Returns 1 for a leap year, 0 otherwise.
 *
 *----------------------------------------------------------------------
 */

static int
int
IsGregorianLeapYear(
    TclDateFields *fields)	/* Date to test */
{
    int year = fields->year;
    Tcl_WideInt year = fields->year;

    if (fields->isBce) {
	year = 1 - year;
    }
    if (year%4 != 0) {
    if (year % 4 != 0) {
	return 0;
    } else if (!(fields->gregorian)) {
	return 1;
    } else if (year%400 == 0) {
    } else if (year % 400 == 0) {
	return 1;
    } else if (year%100 == 0) {
    } else if (year % 100 == 0) {
	return 0;
    } else {
	return 1;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * WeekdayOnOrBefore --
 *
 *	Finds the Julian Day Number of a given day of the week that falls on
 *	or before a given date, expressed as Julian Day Number.
 *
 * Results:
 *	Returns the Julian Day Number
 *
 *----------------------------------------------------------------------
 */

static int
static Tcl_WideInt
WeekdayOnOrBefore(
    int dayOfWeek,		/* Day of week; Sunday == 0 or 7 */
    int julianDay)		/* Reference date */
    Tcl_WideInt julianDay)	/* Reference date */
{
    int k = (dayOfWeek + 6) % 7;
    if (k < 0) {
	k += 7;
    }
    return julianDay - ((julianDay - k) % 7);
}
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
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







-
+




+
+
+
+
+


+





+
+
+
+
+
+
+
+
+
+
+
+


-
-
+
+
+

-
+







 *	the value of the variable if the variable does exist,
 *
 *----------------------------------------------------------------------
 */

int
ClockGetenvObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
#ifdef _WIN32
    const WCHAR *varName;
    const WCHAR *varValue;
    Tcl_DString ds;
#else
    const char *varName;
    const char *varValue;
#endif

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name");
	return TCL_ERROR;
    }
#ifdef _WIN32
    Tcl_DStringInit(&ds);
    varName = Tcl_UtfToWCharDString(TclGetString(objv[1]), -1, &ds);
    varValue = _wgetenv(varName);
    if (varValue == NULL) {
	Tcl_DStringFree(&ds);
    } else {
	Tcl_DStringSetLength(&ds, 0);
	Tcl_WCharToUtfDString(varValue, -1, &ds);
	Tcl_DStringResult(interp, &ds);
    }
#else
    varName = TclGetString(objv[1]);
    varValue = getenv(varName);
    if (varValue == NULL) {
	varValue = "";
    if (varValue != NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		varValue, TCL_AUTO_LENGTH));
    }
    Tcl_SetObjResult(interp, Tcl_NewStringObj(varValue, -1));
#endif
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ThreadSafeLocalTime --
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
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







-
+









-
+







{
    /*
     * Get a thread-local buffer to hold the returned time.
     */

    struct tm *tmPtr = (struct tm *)Tcl_GetThreadData(&tmKey, sizeof(struct tm));
#ifdef HAVE_LOCALTIME_R
    localtime_r(timePtr, tmPtr);
    tmPtr = localtime_r(timePtr, tmPtr);
#else
    struct tm *sysTmPtr;

    Tcl_MutexLock(&clockMutex);
    sysTmPtr = localtime(timePtr);
    if (sysTmPtr == NULL) {
	Tcl_MutexUnlock(&clockMutex);
	return NULL;
    }
    memcpy(tmPtr, localtime(timePtr), sizeof(struct tm));
    memcpy(tmPtr, sysTmPtr, sizeof(struct tm));
    Tcl_MutexUnlock(&clockMutex);
#endif
    return tmPtr;
}

/*----------------------------------------------------------------------
 *
1726
1727
1728
1729
1730
1731
1732
1733

1734
1735
1736
1737
1738
1739
1740
3110
3111
3112
3113
3114
3115
3116

3117
3118
3119
3120
3121
3122
3123
3124







-
+







 * documentation for details on what it does.
 *
 *----------------------------------------------------------------------
 */

int
ClockClicksObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const *objv)	/* Parameter values */
{
    static const char *const clicksSwitches[] = {
	"-milliseconds", "-microseconds", NULL
    };
1751
1752
1753
1754
1755
1756
1757
1758

1759
1760
1761
1762
1763
1764
1765

1766
1767
1768
1769
1770
1771

1772
1773
1774
1775
1776
1777
1778
3135
3136
3137
3138
3139
3140
3141

3142
3143
3144
3145
3146
3147
3148

3149
3150
3151
3152
3153
3154

3155
3156
3157
3158
3159
3160
3161
3162







-
+






-
+





-
+







    case 2:
	if (Tcl_GetIndexFromObj(interp, objv[1], clicksSwitches, "option", 0,
		&index) != TCL_OK) {
	    return TCL_ERROR;
	}
	break;
    default:
	Tcl_WrongNumArgs(interp, 1, objv, "?-switch?");
	Tcl_WrongNumArgs(interp, 0, objv, "clock clicks ?-switch?");
	return TCL_ERROR;
    }

    switch (index) {
    case CLICKS_MILLIS:
	Tcl_GetTime(&now);
	clicks = (Tcl_WideInt) now.sec * 1000 + now.usec / 1000;
	clicks = now.sec * 1000LL + now.usec / 1000;
	break;
    case CLICKS_NATIVE:
#ifdef TCL_WIDE_CLICKS
	clicks = TclpGetWideClicks();
#else
	clicks = (Tcl_WideInt) TclpGetClicks();
	clicks = (Tcl_WideInt)TclpGetClicks();
#endif
	break;
    case CLICKS_MICROS:
	clicks = TclpGetMicroseconds();
	break;
    }

1796
1797
1798
1799
1800
1801
1802
1803

1804
1805
1806
1807
1808

1809
1810
1811

1812
1813
1814
1815
1816



1817
1818
1819
1820
1821
1822
1823
3180
3181
3182
3183
3184
3185
3186

3187
3188
3189
3190
3191
3192
3193
3194
3195

3196
3197
3198
3199


3200
3201
3202
3203
3204
3205
3206
3207
3208
3209







-
+





+


-
+



-
-
+
+
+







 * user documentation for details on what it does.
 *
 *----------------------------------------------------------------------
 */

int
ClockMillisecondsObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const *objv)	/* Parameter values */
{
    Tcl_Time now;
    Tcl_Obj *timeObj;

    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	Tcl_WrongNumArgs(interp, 0, objv, "clock milliseconds");
	return TCL_ERROR;
    }
    Tcl_GetTime(&now);
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt)
	    now.sec * 1000 + now.usec / 1000));
    TclNewUIntObj(timeObj, (Tcl_WideUInt)
	    now.sec * 1000 + now.usec / 1000);
    Tcl_SetObjResult(interp, timeObj);
    return TCL_OK;
}

/*----------------------------------------------------------------------
 *
 * ClockMicrosecondsObjCmd -
 *
1833
1834
1835
1836
1837
1838
1839
1840

1841
1842
1843
1844
1845
1846

1847
1848
1849
1850
1851
1852











1853
1854
1855
1856

1857
1858

1859




1860
1861
1862


1863
1864
1865
1866
1867
1868
1869






1870
1871
1872

1873
1874
1875
1876







1877

1878

1879
1880
1881
1882
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
1958
1959
1960

1961
1962
1963
1964
1965
1966
1967
1968

















1969
1970
1971
1972
1973
1974
1975
3219
3220
3221
3222
3223
3224
3225

3226
3227
3228
3229
3230
3231

3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252

3253
3254

3255
3256
3257
3258
3259
3260
3261


3262
3263
3264




3265
3266
3267
3268
3269
3270
3271
3272
3273
3274

3275




3276
3277
3278
3279
3280
3281
3282
3283
3284

3285





3286



3287
3288
3289
3290


3291
3292
3293
3294
3295
3296

3297

3298
3299

3300





3301
3302
3303
3304




3305
3306
3307
3308
3309
3310
3311



3312
3313
3314
3315
3316
3317
3318
3319
3320
3321




3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333

3334
3335
3336


3337
3338
3339
3340
3341
3342


3343
3344
3345
3346
3347


3348
3349
3350


3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380







3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394

3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
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
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
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489

4490
4491
4492






4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516







-
+





-
+






+
+
+
+
+
+
+
+
+
+
+



-
+

-
+

+
+
+
+

-
-
+
+

-
-
-
-


+
+
+
+
+
+


-
+
-
-
-
-
+
+
+
+
+
+
+

+
-
+
-
-
-
-
-

-
-
-
+
+
+

-
-
+
+



+
-
+
-

+
-
+
-
-
-
-
-
+
+
+
+
-
-
-
-
+






-
-
-

+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+


-
-
+
+
+
+
+

-
-
+
+



-
-
+
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
-
-
-
-
-
-
+
+
+
+
+



+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+


-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 * user documentation for details on what it does.
 *
 *----------------------------------------------------------------------
 */

int
ClockMicrosecondsObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const *objv)	/* Parameter values */
{
    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	Tcl_WrongNumArgs(interp, 0, objv, "clock microseconds");
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(TclpGetMicroseconds()));
    return TCL_OK;
}

static inline void
ClockInitFmtScnArgs(
    ClockClientData *dataPtr,
    Tcl_Interp *interp,
    ClockFmtScnCmdArgs *opts)
{
    memset(opts, 0, sizeof(*opts));
    opts->dataPtr = dataPtr;
    opts->interp = interp;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ClockParseformatargsObjCmd --
 * ClockParseFmtScnArgs --
 *
 *	Parses the arguments for [clock format].
 *	Parses the arguments for sub-commands "scan", "format" and "add".
 *
 *	Note:	common options table used here, because for the options often used
 *		the same literals (objects), so it avoids permanent "recompiling" of
 *		option object representation to indexType with another table.
 *
 * Results:
 *	Returns a standard Tcl result, whose value is a four-element list
 *	comprising the time format, the locale, and the timezone.
 *	Returns a standard Tcl result, and stores parsed options
 *	(format, the locale, timezone and base) in structure "opts".
 *
 * This function exists because the loop that parses the [clock format]
 * options is a known performance "hot spot", and is implemented in an effort
 * to speed that particular code up.
 *
 *-----------------------------------------------------------------------------
 */

typedef enum ClockOperation {
    CLC_OP_FMT = 0,		/* Doing [clock format] */
    CLC_OP_SCN,			/* Doing [clock scan] */
    CLC_OP_ADD			/* Doing [clock add] */
} ClockOperation;

static int
ClockParseformatargsObjCmd(
ClockParseFmtScnArgs(
    ClientData clientData,	/* Client data containing literal pool */
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const objv[])	/* Parameter vector */
    ClockFmtScnCmdArgs *opts,	/* Result vector: format, locale, timezone... */
    TclDateFields *date,	/* Extracted date-time corresponding base
				 * (by scan or add) resp. clockval (by format) */
    Tcl_Size objc,			/* Parameter count */
    Tcl_Obj *const objv[],	/* Parameter vector */
    ClockOperation operation,	/* What operation are we doing: format, scan, add */
    const char *syntax)		/* Syntax of the current command */
{
    Tcl_Interp *interp = opts->interp;
    ClockClientData *dataPtr = (ClockClientData *)clientData;
    ClockClientData *dataPtr = opts->dataPtr;
    Tcl_Obj **litPtr = dataPtr->literals;
    Tcl_Obj *results[3];	/* Format, locale and timezone */
#define formatObj results[0]
#define localeObj results[1]
#define timezoneObj results[2]
    int gmtFlag = 0;
    static const char *const options[] = { /* Command line options expected */
	"-format",	"-gmt",		"-locale",
	"-timezone",	NULL };
    static const char *const options[] = {
	"-base", "-format", "-gmt", "-locale", "-timezone", "-validate", NULL
    };
    enum optionInd {
	CLOCK_FORMAT_FORMAT,	CLOCK_FORMAT_GMT,	CLOCK_FORMAT_LOCALE,
	CLOCK_FORMAT_TIMEZONE
	CLC_ARGS_BASE, CLC_ARGS_FORMAT, CLC_ARGS_GMT, CLC_ARGS_LOCALE,
	CLC_ARGS_TIMEZONE, CLC_ARGS_VALIDATE
    };
    int optionIndex;		/* Index of an option. */
    int saw = 0;		/* Flag == 1 if option was seen already. */
    Tcl_Size i, baseIdx;
    Tcl_WideInt clockVal;	/* Clock value - just used to parse. */
    Tcl_WideInt baseVal;	/* Base time, expressed in seconds from the Epoch */
    int i;

    if (operation == CLC_OP_SCN) {
    /*
	/* default flags (from configure) */
     * Args consist of a time followed by keyword-value pairs.
     */

    if (objc < 2 || (objc % 2) != 0) {
	Tcl_WrongNumArgs(interp, 0, objv,
	opts->flags |= dataPtr->defFlags & CLF_VALIDATE;
    } else {
	/* clock value (as current base) */
	opts->baseObj = objv[(baseIdx = 1)];
		"clock format clockval ?-format string? "
		"?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?");
	Tcl_SetErrorCode(interp, "CLOCK", "wrongNumArgs", NULL);
	return TCL_ERROR;
	saw |= 1 << CLC_ARGS_BASE;
    }

    /*
     * Extract values for the keywords.
     */

    formatObj = litPtr[LIT__DEFAULT_FORMAT];
    localeObj = litPtr[LIT_C];
    timezoneObj = litPtr[LIT__NIL];
    for (i = 2; i < objc; i+=2) {
	/* bypass integers (offsets) by "clock add" */
	if (operation == CLC_OP_ADD) {
	    Tcl_WideInt num;

	    if (TclGetWideIntFromObj(NULL, objv[i], &num) == TCL_OK) {
		continue;
	    }
	}
	/* get option */
	if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
		&optionIndex) != TCL_OK) {
	    Tcl_SetErrorCode(interp, "CLOCK", "badOption",
		    TclGetString(objv[i]), NULL);
	if (Tcl_GetIndexFromObj(interp, objv[i], options,
		"option", 0, &optionIndex) != TCL_OK) {
	    goto badOptionMsg;
	}
	/* if already specified */
	if (saw & (1 << optionIndex)) {
	    if (operation != CLC_OP_SCN && optionIndex == CLC_ARGS_BASE) {
		goto badOptionMsg;
	    }
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad option \"%s\": doubly present",
		    TclGetString(objv[i])));
	    return TCL_ERROR;
	    goto badOption;
	}
	switch (optionIndex) {
	case CLOCK_FORMAT_FORMAT:
	    formatObj = objv[i+1];
	case CLC_ARGS_FORMAT:
	    if (operation == CLC_OP_ADD) {
		goto badOptionMsg;
	    }
	    opts->formatObj = objv[i + 1];
	    break;
	case CLOCK_FORMAT_GMT:
	    if (Tcl_GetBooleanFromObj(interp, objv[i+1], &gmtFlag) != TCL_OK){
	case CLC_ARGS_GMT:
	    if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &gmtFlag) != TCL_OK){
		return TCL_ERROR;
	    }
	    break;
	case CLOCK_FORMAT_LOCALE:
	    localeObj = objv[i+1];
	case CLC_ARGS_LOCALE:
	    opts->localeObj = objv[i + 1];
	    break;
	case CLOCK_FORMAT_TIMEZONE:
	    timezoneObj = objv[i+1];
	case CLC_ARGS_TIMEZONE:
	    opts->timezoneObj = objv[i + 1];
	    break;
	case CLC_ARGS_BASE:
	    opts->baseObj = objv[(baseIdx = i + 1)];
	    break;
	case CLC_ARGS_VALIDATE:
	    if (operation != CLC_OP_SCN) {
		goto badOptionMsg;
	    } else {
		int val;

		if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &val) != TCL_OK) {
		    return TCL_ERROR;
		}
		if (val) {
		    opts->flags |= CLF_VALIDATE;
		} else {
		    opts->flags &= ~CLF_VALIDATE;
		}
	    }
	    break;
	}
	saw |= 1 << optionIndex;
    }

    /*
     * Check options.
     */

    if (TclGetWideIntFromObj(interp, objv[1], &clockVal) != TCL_OK) {
	return TCL_ERROR;
    }
    if ((saw & (1 << CLOCK_FORMAT_GMT))
	    && (saw & (1 << CLOCK_FORMAT_TIMEZONE))) {
	Tcl_SetObjResult(interp, litPtr[LIT_CANNOT_USE_GMT_AND_TIMEZONE]);
	Tcl_SetErrorCode(interp, "CLOCK", "gmtWithTimezone", NULL);
    if ((saw & (1 << CLC_ARGS_GMT))
	    && (saw & (1 << CLC_ARGS_TIMEZONE))) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"cannot use -gmt and -timezone in same call", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "CLOCK", "gmtWithTimezone", (char *)NULL);
	return TCL_ERROR;
    }
    if (gmtFlag) {
	opts->timezoneObj = dataPtr->literals[LIT_GMT];
    } else if (opts->timezoneObj == NULL
	    || TclGetString(opts->timezoneObj) == NULL
	    || opts->timezoneObj->length == 0) {
	/* If time zone not specified use system time zone */
	opts->timezoneObj = ClockGetSystemTimeZone(dataPtr, interp);
	timezoneObj = litPtr[LIT_GMT];
	if (opts->timezoneObj == NULL) {
	    return TCL_ERROR;
	}
    }

    /* Setup timezone (normalize object if needed and load TZ on demand) */

    opts->timezoneObj = ClockSetupTimeZone(dataPtr, interp, opts->timezoneObj);
    if (opts->timezoneObj == NULL) {
	return TCL_ERROR;
    }

    /* Base (by scan or add) or clock value (by format) */

    if (opts->baseObj != NULL) {
	Tcl_Obj *baseObj = opts->baseObj;

	/* bypass integer recognition if looks like "now" or "-now" */
	if ((baseObj->bytes &&
		((baseObj->length == 3 && baseObj->bytes[0] == 'n') ||
		 (baseObj->length == 4 && baseObj->bytes[1] == 'n')))
		|| TclGetWideIntFromObj(NULL, baseObj, &baseVal) != TCL_OK) {
	    /* we accept "now" and "-now" as current date-time */
	    static const char *const nowOpts[] = {
		"now", "-now", NULL
	    };
	    int idx;

	    if (Tcl_GetIndexFromObj(NULL, baseObj, nowOpts, "seconds",
		    TCL_EXACT, &idx) == TCL_OK) {
		goto baseNow;
	    }

	    if (TclHasInternalRep(baseObj, &tclBignumType)) {
		goto baseOverflow;
	    }

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"bad seconds \"%s\": must be now or integer",
		TclGetString(baseObj)));
	    i = baseIdx;
	    goto badOption;
	}
	/*
	 * Seconds could be an unsigned number that overflowed. Make sure
	 * that it isn't. Additionally it may be too complex to calculate
	 * julianday etc (forwards/backwards) by too large/small values, thus
	 * just let accept a bit shorter values to avoid overflow.
	 * Note the year is currently an integer, thus avoid to overflow it also.
	 */

	if (TclHasInternalRep(baseObj, &tclBignumType)
		|| baseVal < TCL_MIN_SECONDS || baseVal > TCL_MAX_SECONDS) {
	baseOverflow:
	    Tcl_SetObjResult(interp, dataPtr->literals[LIT_INTEGER_VALUE_TOO_LARGE]);
	    i = baseIdx;
	    goto badOption;
	}
    } else {
	Tcl_Time now;

    baseNow:
	Tcl_GetTime(&now);
	baseVal = (Tcl_WideInt) now.sec;
    }

    /*
     * Extract year, month and day from the base time for the parser to use as
     * defaults
     */

    /* check base fields already cached (by TZ, last-second cache) */
    if (dataPtr->lastBase.timezoneObj == opts->timezoneObj
	    && dataPtr->lastBase.date.seconds == baseVal
	    && (!(dataPtr->lastBase.date.flags & CLF_CTZ)
	    || dataPtr->lastTZEpoch == TzsetIfNecessary())) {
	memcpy(date, &dataPtr->lastBase.date, ClockCacheableDateFieldsSize);
    } else {
	/* extact fields from base */
	date->seconds = baseVal;
	if (ClockGetDateFields(dataPtr, interp, date, opts->timezoneObj,
	      GREGORIAN_CHANGE_DATE) != TCL_OK) {
	    /* TODO - GREGORIAN_CHANGE_DATE should be locale-dependent */
	    return TCL_ERROR;
	}
	/* cache last base */
	memcpy(&dataPtr->lastBase.date, date, ClockCacheableDateFieldsSize);
	TclSetObjRef(dataPtr->lastBase.timezoneObj, opts->timezoneObj);
    }

    return TCL_OK;

  badOptionMsg:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "bad option \"%s\": must be %s",
	    TclGetString(objv[i]), syntax));

  badOption:
    Tcl_SetErrorCode(interp, "CLOCK", "badOption",
	    (i < objc) ? TclGetString(objv[i]) : (char *)NULL, (char *)NULL);
    return TCL_ERROR;
}

/*----------------------------------------------------------------------
 *
 * ClockFormatObjCmd -- , clock format --
 *
 *	This function is invoked to process the Tcl "clock format" command.
 *
 *	Formats a count of seconds since the Posix Epoch as a time of day.
 *
 *	The 'clock format' command formats times of day for output.  Refer
 *	to the user documentation to see what it does.
 *
 * Results:
 *	Returns a standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
ClockFormatObjCmd(
    void *clientData,		/* Client data containing literal pool */
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const objv[])	/* Parameter values */
{
    ClockClientData *dataPtr = (ClockClientData *)clientData;
    static const char *syntax = "clock format clockval|now "
	    "?-format string? "
	    "?-gmt boolean? "
	    "?-locale LOCALE? ?-timezone ZONE?";
    int ret;
    ClockFmtScnCmdArgs opts;	/* Format, locale, timezone and base */
    DateFormat dateFmt;		/* Common structure used for formatting */

    /* even number of arguments */
    if ((objc & 1) == 1) {
	Tcl_WrongNumArgs(interp, 0, objv, syntax);
	Tcl_SetErrorCode(interp, "CLOCK", "wrongNumArgs", (char *)NULL);
	return TCL_ERROR;
    }

    memset(&dateFmt, 0, sizeof(dateFmt));

    /*
     * Extract values for the keywords.
     */

    ClockInitFmtScnArgs(dataPtr, interp, &opts);
    ret = ClockParseFmtScnArgs(&opts, &dateFmt.date, objc, objv,
	    CLC_OP_FMT, "-format, -gmt, -locale, or -timezone");
    if (ret != TCL_OK) {
	goto done;
    }

    /* Default format */
    if (opts.formatObj == NULL) {
	opts.formatObj = dataPtr->literals[LIT__DEFAULT_FORMAT];
    }

    /* Use compiled version of Format - */
    ret = ClockFormat(&dateFmt, &opts);

  done:
    TclUnsetObjRef(dateFmt.date.tzName);
    return ret;
}

/*----------------------------------------------------------------------
 *
 * ClockScanObjCmd -- , clock scan --
 *
 *	This function is invoked to process the Tcl "clock scan" command.
 *
 *	Inputs a count of seconds since the Posix Epoch as a time of day.
 *
 *	The 'clock scan' command scans times of day on input. Refer to the
 *	user documentation to see what it does.
 *
 * Results:
 *	Returns a standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
ClockScanObjCmd(
    void *clientData,		/* Client data containing literal pool */
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const objv[])	/* Parameter values */
{
    ClockClientData *dataPtr = (ClockClientData *)clientData;
    static const char *syntax = "clock scan string "
	    "?-base seconds? "
	    "?-format string? "
	    "?-gmt boolean? "
	    "?-locale LOCALE? ?-timezone ZONE? ?-validate boolean?";
    int ret;
    ClockFmtScnCmdArgs opts;	/* Format, locale, timezone and base */
    DateInfo yy;		/* Common structure used for parsing */
    DateInfo *info = &yy;

    /* even number of arguments */
    if ((objc & 1) == 1) {
	Tcl_WrongNumArgs(interp, 0, objv, syntax);
	Tcl_SetErrorCode(interp, "CLOCK", "wrongNumArgs", (char *)NULL);
	return TCL_ERROR;
    }

    ClockInitDateInfo(&yy);

    /*
     * Extract values for the keywords.
     */

    ClockInitFmtScnArgs(dataPtr, interp, &opts);
    ret = ClockParseFmtScnArgs(&opts, &yy.date, objc, objv,
	    CLC_OP_SCN, "-base, -format, -gmt, -locale, -timezone or -validate");
    if (ret != TCL_OK) {
	goto done;
    }

    /* seconds are in localSeconds (relative base date), so reset time here */
    yyHour = yyMinutes = yySeconds = yySecondOfDay = 0; yyMeridian = MER24;

    /* If free scan */
    if (opts.formatObj == NULL) {
	/* Use compiled version of FreeScan - */

	/* [SB] TODO: Perhaps someday we'll localize the legacy code. Right now,
	 * it's not localized. */
	if (opts.localeObj != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "legacy [clock scan] does not support -locale", TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(interp, "CLOCK", "flagWithLegacyFormat", (char *)NULL);
	    ret = TCL_ERROR;
	    goto done;
	}
	ret = ClockFreeScan(&yy, objv[1], &opts);
    } else {
	/* Use compiled version of Scan - */

	ret = ClockScan(&yy, objv[1], &opts);
    }

    if (ret != TCL_OK) {
	goto done;
    }

    /*
     * If no GMT and not free-scan (where valid stage 1 is done in-between),
     * validate with stage 1 before local time conversion, otherwise it may
     * adjust date/time tokens to valid values
     */
    if ((opts.flags & CLF_VALIDATE_S1)
	    && info->flags & (CLF_ASSEMBLE_SECONDS|CLF_LOCALSEC)) {
	ret = ClockValidDate(&yy, &opts, CLF_VALIDATE_S1);
	if (ret != TCL_OK) {
	    goto done;
	}
    }

    /* Convert date info structure into UTC seconds */

    ret = ClockScanCommit(&yy, &opts);
    if (ret != TCL_OK) {
	goto done;
    }

    /* Apply remaining validation rules, if expected */
    if (opts.flags & CLF_VALIDATE) {
	ret = ClockValidDate(&yy, &opts, opts.flags & CLF_VALIDATE);
	if (ret != TCL_OK) {
	    goto done;
	}
    }

  done:
    TclUnsetObjRef(yy.date.tzName);
    if (ret != TCL_OK) {
	return ret;
    }
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(yy.date.seconds));
    return TCL_OK;
}

/*----------------------------------------------------------------------
 *
 * ClockScanCommit --
 *
 *	Converts date info structure into UTC seconds.
 *
 * Results:
 *	Returns a standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
ClockScanCommit(
    DateInfo *info,		/* Clock scan info structure */
    ClockFmtScnCmdArgs *opts)	/* Format, locale, timezone and base */
{
    /* If needed assemble julianDay using year, month, etc. */
    if (info->flags & CLF_ASSEMBLE_JULIANDAY) {
	if (info->flags & CLF_ISO8601WEEK) {
	    GetJulianDayFromEraYearWeekDay(&yydate, GREGORIAN_CHANGE_DATE);
	} else if (!(info->flags & CLF_DAYOFYEAR) /* no day of year */
		|| (info->flags & (CLF_DAYOFMONTH|CLF_MONTH)) /* yymmdd over yyddd */
		== (CLF_DAYOFMONTH|CLF_MONTH)) {
	    GetJulianDayFromEraYearMonthDay(&yydate, GREGORIAN_CHANGE_DATE);
	} else {
	    GetJulianDayFromEraYearDay(&yydate, GREGORIAN_CHANGE_DATE);
	}
	info->flags |= CLF_ASSEMBLE_SECONDS;
	info->flags &= ~CLF_ASSEMBLE_JULIANDAY;
    }

    /* some overflow checks */
    if (info->flags & CLF_JULIANDAY) {
	double curJDN = (double)yydate.julianDay
		+ ((double)yySecondOfDay - SECONDS_PER_DAY/2) / SECONDS_PER_DAY;
	if (curJDN > opts->dataPtr->maxJDN) {
	    Tcl_SetObjResult(opts->interp, Tcl_NewStringObj(
		    "requested date too large to represent", TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(opts->interp, "CLOCK", "dateTooLarge", (char *)NULL);
	    return TCL_ERROR;
	}
    }

    /* If seconds overflows the day (no validate but not "24:00" or leap-second case), increase days */
    if (yySecondOfDay >= SECONDS_PER_DAY + ((info->flags & CLF_TIME) && ((yyHour == 24) || (yySeconds == 60)))) {
	yydate.julianDay += (yySecondOfDay / SECONDS_PER_DAY);
	yySecondOfDay %= SECONDS_PER_DAY;
    }

    /* Local seconds to UTC (stored in yydate.seconds) */

    if (info->flags & CLF_ASSEMBLE_SECONDS) {
	yydate.localSeconds =
		-210866803200LL
		+ (SECONDS_PER_DAY * yydate.julianDay)
		+ yySecondOfDay;
    }

    if (info->flags & (CLF_ASSEMBLE_SECONDS | CLF_LOCALSEC)) {
	if (ConvertLocalToUTC(opts->dataPtr, opts->interp, &yydate,
		opts->timezoneObj, GREGORIAN_CHANGE_DATE) != TCL_OK) {
	    return TCL_ERROR;
	}
    }

    /* Increment UTC seconds with relative time */

    yydate.seconds += yyRelSeconds;
    return TCL_OK;
}

/*----------------------------------------------------------------------
 *
 * ClockValidDate --
 *
 *	Validate date info structure for wrong data (e. g. out of ranges).
 *
 * Results:
 *	Returns a standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
ClockValidDate(
    DateInfo *info,		/* Clock scan info structure */
    ClockFmtScnCmdArgs *opts,	/* Scan options */
    int stage)			/* Stage to validate (1, 2 or 3 for both) */
{
    const char *errMsg = "", *errCode = "";
    TclDateFields temp;
    int tempCpyFlg = 0;
    ClockClientData *dataPtr = opts->dataPtr;

#if 0
    printf("yyMonth %d, yyDay %d, yyDayOfYear %d, yyHour %d, yyMinutes %d, yySeconds %" TCL_LL_MODIFIER "d, "
	    "yySecondOfDay %" TCL_LL_MODIFIER "d, sec %" TCL_LL_MODIFIER "d, daySec %" TCL_LL_MODIFIER "d, tzOffset %d\n",
	    yyMonth, yyDay, yydate.dayOfYear, yyHour, yyMinutes, yySeconds,
	    yySecondOfDay, yydate.localSeconds, yydate.localSeconds % SECONDS_PER_DAY,
	    yydate.tzOffset);
#endif

    if (!(stage & CLF_VALIDATE_S1) || !(opts->flags & CLF_VALIDATE_S1)) {
	goto stage_2;
    }
    opts->flags &= ~CLF_VALIDATE_S1; /* stage 1 is done */

    /* first year (used later in hath / daysInPriorMonths) */
    if ((info->flags & (CLF_YEAR | CLF_ISO8601YEAR))) {
	if ((info->flags & CLF_ISO8601YEAR)) {
	    if (yydate.iso8601Year < dataPtr->validMinYear
		    || yydate.iso8601Year > dataPtr->validMaxYear) {
		errMsg = "invalid iso year";
		errCode = "iso year";
		goto error;
	    }
	}
	if (info->flags & CLF_YEAR) {
	    if (yyYear < dataPtr->validMinYear
		    || yyYear > dataPtr->validMaxYear) {
		errMsg = "invalid year";
		errCode = "year";
		goto error;
	    }
	} else if ((info->flags & CLF_ISO8601YEAR)) {
	    yyYear = yydate.iso8601Year; /* used to recognize leap */
	}
	if ((info->flags & (CLF_ISO8601YEAR | CLF_YEAR))
		== (CLF_ISO8601YEAR | CLF_YEAR)) {
	    if (yyYear != yydate.iso8601Year) {
		errMsg = "ambiguous year";
		errCode = "year";
		goto error;
	    }
	}
    }
    /* and month (used later in hath) */
    if (info->flags & CLF_MONTH) {
	if (yyMonth < 1 || yyMonth > 12) {
	    errMsg = "invalid month";
	    errCode = "month";
	    goto error;
	}
    }
    /* day of month */
    if (info->flags & (CLF_DAYOFMONTH|CLF_DAYOFWEEK)) {
	if (yyDay < 1 || yyDay > 31) {
	    errMsg = "invalid day";
	    errCode = "day";
	    goto error;
	}
	if ((info->flags & CLF_MONTH)) {
	    const int *h = hath[IsGregorianLeapYear(&yydate)];

	    if (yyDay > h[yyMonth - 1]) {
		errMsg = "invalid day";
		errCode = "day";
		goto error;
	    }
	}
    }
    if (info->flags & CLF_DAYOFYEAR) {
	if (yydate.dayOfYear < 1
		|| yydate.dayOfYear > daysInPriorMonths[IsGregorianLeapYear(&yydate)][12]) {
	    errMsg = "invalid day of year";
	    errCode = "day of year";
	    goto error;
	}
    }

    /* mmdd !~ ddd */
    if ((info->flags & (CLF_DAYOFYEAR|CLF_DAYOFMONTH|CLF_MONTH))
	    == (CLF_DAYOFYEAR|CLF_DAYOFMONTH|CLF_MONTH)) {
	if (!tempCpyFlg) {
	    memcpy(&temp, &yydate, sizeof(temp));
	    tempCpyFlg = 1;
	}
	GetJulianDayFromEraYearDay(&temp, GREGORIAN_CHANGE_DATE);
	if (temp.julianDay != yydate.julianDay) {
	    errMsg = "ambiguous day";
	    errCode = "day";
	    goto error;
	}
    }

    if (info->flags & CLF_TIME) {
	/* hour */
	if (yyHour < 0 || yyHour > ((yyMeridian == MER24) ? 24 : 12)) {
	    errMsg = "invalid time (hour)";
	    errCode = "hour";
	    goto error;
	}
	/* minutes */
	if (yyMinutes < 0 || yyMinutes > 59 || (yyMinutes && (yyHour == 24))) {
	    errMsg = "invalid time (minutes)";
	    errCode = "minutes";
	    goto error;
	}
	/* oldscan could return secondOfDay (parsedTime) -1 by invalid time (ex.: 25:00:00) */
	if (yySeconds < 0 || yySeconds > 59 || yySecondOfDay <= -1 || (yySeconds && (yyHour == 24))) {
	    errMsg = "invalid time";
	    errCode = "seconds";
	    goto error;
	}
    }

    if (!(stage & CLF_VALIDATE_S2) || !(opts->flags & CLF_VALIDATE_S2)) {
	return TCL_OK;
    }
    opts->flags &= ~CLF_VALIDATE_S2; /* stage 2 is done */

    /*
     * Further tests expected ready calculated julianDay (inclusive relative),
     * and time-zone conversion (local to UTC time).
     */
  stage_2:

    /* time, regarding the modifications by the time-zone (looks for given time
     * in between DST-time hole, so does not exist in this time-zone) */
    if (info->flags & CLF_TIME) {
	/*
	 * we don't need to do the backwards time-conversion (UTC to local) and
	 * compare results, because the after conversion (local to UTC) we
	 * should have valid localSeconds (was not invalidated to TCL_INV_SECONDS),
	 * so if it was invalidated - invalid time, outside the time-zone (in DST-hole)
	 */
	if (yydate.localSeconds == TCL_INV_SECONDS) {
	    errMsg = "invalid time (does not exist in this time-zone)";
	    errCode = "out-of-time";
	    goto error;
	}
    }

    /* day of week */
    if (info->flags & CLF_DAYOFWEEK) {
	if (!tempCpyFlg) {
	    memcpy(&temp, &yydate, sizeof(temp));
	    tempCpyFlg = 1;
	}
	GetYearWeekDay(&temp, GREGORIAN_CHANGE_DATE);
	if (temp.dayOfWeek != yyDayOfWeek) {
	    errMsg = "invalid day of week";
	    errCode = "day of week";
	    goto error;
	}
    }

    return TCL_OK;

  error:
    Tcl_SetObjResult(opts->interp, Tcl_ObjPrintf(
	    "unable to convert input string: %s", errMsg));
    Tcl_SetErrorCode(opts->interp, "CLOCK", "invInpStr", errCode, (char *)NULL);
    return TCL_ERROR;
}

/*----------------------------------------------------------------------
 *
 * ClockFreeScan --
 *
 *	Used by ClockScanObjCmd for free scanning without format.
 *
 * Results:
 *	Returns a standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
ClockFreeScan(
    DateInfo *info,		/* Date fields used for parsing & converting
				 * simultaneously a yy-parse structure of the
				 * TclClockFreeScan */
    Tcl_Obj *strObj,		/* String containing the time to scan */
    ClockFmtScnCmdArgs *opts)	/* Command options */
{
    Tcl_Interp *interp = opts->interp;
    ClockClientData *dataPtr = opts->dataPtr;
    int ret = TCL_ERROR;

    /*
     * Parse the date. The parser will fill a structure "info" with date,
     * time, time zone, relative month/day/seconds, relative weekday, ordinal
     * month.
     * Notice that many yy-defines point to values in the "info" or "date"
     * structure, e. g. yySecondOfDay -> info->date.secondOfDay or
     *			yyMonth -> info->date.month (same as yydate.month)
     */
    yyInput = TclGetString(strObj);

    if (TclClockFreeScan(interp, info) != TCL_OK) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"unable to convert date-time string \"%s\": %s",
		TclGetString(strObj), Tcl_GetString(Tcl_GetObjResult(interp))));
	goto done;
    }

    /*
     * If the caller supplied a date in the string, update the date with
     * the value. If the caller didn't specify a time with the date, default to
     * midnight.
     */

    if (info->flags & CLF_YEAR) {
	if (yyYear < 100) {
	    if (yyYear >= dataPtr->yearOfCenturySwitch) {
		yyYear -= 100;
	    }
	    yyYear += dataPtr->currentYearCentury;
	}
	yydate.isBce = 0;
	info->flags |= CLF_ASSEMBLE_JULIANDAY|CLF_ASSEMBLE_SECONDS;
    }

    /*
     * If the caller supplied a time zone in the string, make it into a time
     * zone indicator of +-hhmm and setup this time zone.
     */

    if (info->flags & CLF_ZONE) {
	if (yyTimezone || !yyDSTmode) {
	    /* Real time zone from numeric zone */
	    Tcl_Obj *tzObjStor = NULL;
	    int minEast = -yyTimezone;
	    int dstFlag = 1 - yyDSTmode;

	    tzObjStor = ClockFormatNumericTimeZone(
		    60 * minEast + 3600 * dstFlag);
	    Tcl_IncrRefCount(tzObjStor);

	    opts->timezoneObj = ClockSetupTimeZone(dataPtr, interp, tzObjStor);

	    Tcl_DecrRefCount(tzObjStor);
	} else {
	    /* simplest case - GMT / UTC */
	    opts->timezoneObj = ClockSetupTimeZone(dataPtr, interp,
		    dataPtr->literals[LIT_GMT]);
	}
	if (opts->timezoneObj == NULL) {
	    goto done;
	}

	// TclSetObjRef(yydate.tzName, opts->timezoneObj);

	info->flags |= CLF_ASSEMBLE_SECONDS;
    }

    /*
     * For freescan apply validation rules (stage 1) before mixed with
     * relative time (otherwise always valid recalculated date & time).
     */
    if (opts->flags & CLF_VALIDATE) {
	if (ClockValidDate(info, opts, CLF_VALIDATE_S1) != TCL_OK) {
	    goto done;
	}
    }

    /*
     * Assemble date, time, zone into seconds-from-epoch
     */

    if ((info->flags & (CLF_TIME | CLF_HAVEDATE)) == CLF_HAVEDATE) {
	yySecondOfDay = 0;
	info->flags |= CLF_ASSEMBLE_SECONDS;
    } else if (info->flags & CLF_TIME) {
	yySecondOfDay = ToSeconds(yyHour, yyMinutes, yySeconds, yyMeridian);
	info->flags |= CLF_ASSEMBLE_SECONDS;
    } else if ((info->flags & (CLF_DAYOFWEEK | CLF_HAVEDATE)) == CLF_DAYOFWEEK
	    || (info->flags & CLF_ORDINALMONTH)
	    || ((info->flags & CLF_RELCONV)
	    && (yyRelMonth != 0 || yyRelDay != 0))) {
	yySecondOfDay = 0;
	info->flags |= CLF_ASSEMBLE_SECONDS;
    } else {
	yySecondOfDay = yydate.localSeconds % SECONDS_PER_DAY;
    }

    /*
     * Do relative times
     */

    ret = ClockCalcRelTime(info);

    /* Free scanning completed - date ready */

  done:
    return ret;
}

/*----------------------------------------------------------------------
 *
 * ClockCalcRelTime --
 *
 *	Used for calculating of relative times.
 *
 * Results:
 *	Returns a standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
int
ClockCalcRelTime(
    DateInfo *info)		/* Date fields used for converting */
{
    int prevDayOfWeek = yyDayOfWeek;	/* preserve unchanged day of week */

    /*
     * Because some calculations require in-between conversion of the
     * julian day, we can repeat this processing multiple times
     */
  repeat_rel:
    if (info->flags & CLF_RELCONV) {
	/*
	 * Relative conversion normally possible in UTC time only, because
	 * of possible wrong local time increment if ignores in-between DST-hole.
	 * (see test-cases clock-34.53, clock-34.54).
	 * So increment date in julianDay, but time inside day in UTC (seconds).
	 */

	/* add months (or years in months) */

	if (yyRelMonth != 0) {
	    int m, h;

	    /* if needed extract year, month, etc. again */
	    if (info->flags & CLF_ASSEMBLE_DATE) {
		GetGregorianEraYearDay(&yydate, GREGORIAN_CHANGE_DATE);
		GetMonthDay(&yydate);
		GetYearWeekDay(&yydate, GREGORIAN_CHANGE_DATE);
		info->flags &= ~CLF_ASSEMBLE_DATE;
	    }

	    /* add the requisite number of months */
	    yyMonth += yyRelMonth - 1;
	    yyYear += yyMonth / 12;
	    m = yyMonth % 12;
	    /* compiler fix for negative offs - wrap y, m = (0, -1) -> (-1, 11) */
	    if (m < 0) {
		yyYear--;
		m = 12 + m;
	    }
	    yyMonth = m + 1;

	    /* if the day doesn't exist in the current month, repair it */
	    h = hath[IsGregorianLeapYear(&yydate)][m];
	    if (yyDay > h) {
		yyDay = h;
	    }

	    /* on demand (lazy) assemble julianDay using new year, month, etc. */
	    info->flags |= CLF_ASSEMBLE_JULIANDAY | CLF_ASSEMBLE_SECONDS;

	    yyRelMonth = 0;
	}

	/* add days (or other parts aligned to days) */
	if (yyRelDay) {
	    /* assemble julianDay using new year, month, etc. */
	    if (info->flags & CLF_ASSEMBLE_JULIANDAY) {
		GetJulianDayFromEraYearMonthDay(&yydate, GREGORIAN_CHANGE_DATE);
		info->flags &= ~CLF_ASSEMBLE_JULIANDAY;
	    }
	    yydate.julianDay += yyRelDay;

	    /* julianDay was changed, on demand (lazy) extract year, month, etc. again */
	    info->flags |= CLF_ASSEMBLE_DATE|CLF_ASSEMBLE_SECONDS;
	    yyRelDay = 0;
	}

	/* relative time (seconds), if exceeds current date, do the day conversion and
	 * leave rest of the increment in yyRelSeconds to add it hereafter in UTC seconds */
	if (yyRelSeconds) {
	    Tcl_WideInt newSecs = yySecondOfDay + yyRelSeconds;

	    /* if seconds increment outside of current date, increment day */
	    if (newSecs / SECONDS_PER_DAY != yySecondOfDay / SECONDS_PER_DAY) {
		yyRelDay += newSecs / SECONDS_PER_DAY;
		yySecondOfDay = 0;
		yyRelSeconds = newSecs % SECONDS_PER_DAY;

		goto repeat_rel;
	    }
	}

	info->flags &= ~CLF_RELCONV;
    }

    /*
     * Do relative (ordinal) month
     */

    if (info->flags & CLF_ORDINALMONTH) {
	int monthDiff;

	/* if needed extract year, month, etc. again */
	if (info->flags & CLF_ASSEMBLE_DATE) {
	    GetGregorianEraYearDay(&yydate, GREGORIAN_CHANGE_DATE);
	    GetMonthDay(&yydate);
	    GetYearWeekDay(&yydate, GREGORIAN_CHANGE_DATE);
	    info->flags &= ~CLF_ASSEMBLE_DATE;
	}

	if (yyMonthOrdinalIncr > 0) {
	    monthDiff = yyMonthOrdinal - yyMonth;
	    if (monthDiff <= 0) {
		monthDiff += 12;
	    }
	    yyMonthOrdinalIncr--;
	} else {
	    monthDiff = yyMonth - yyMonthOrdinal;
	    if (monthDiff >= 0) {
		monthDiff -= 12;
	    }
	    yyMonthOrdinalIncr++;
	}

	/* process it further via relative times */
	yyYear += yyMonthOrdinalIncr;
	yyRelMonth += monthDiff;
	info->flags &= ~CLF_ORDINALMONTH;
	info->flags |= CLF_RELCONV|CLF_ASSEMBLE_JULIANDAY|CLF_ASSEMBLE_SECONDS;

	goto repeat_rel;
    }

    /*
     * Do relative weekday
     */

    if ((info->flags & (CLF_DAYOFWEEK|CLF_HAVEDATE)) == CLF_DAYOFWEEK) {
	/* restore scanned day of week */
	yyDayOfWeek = prevDayOfWeek;

	/* if needed assemble julianDay now */
	if (info->flags & CLF_ASSEMBLE_JULIANDAY) {
	    GetJulianDayFromEraYearMonthDay(&yydate, GREGORIAN_CHANGE_DATE);
	    info->flags &= ~CLF_ASSEMBLE_JULIANDAY;
	}

	yydate.isBce = 0;
	yydate.julianDay = WeekdayOnOrBefore(yyDayOfWeek, yydate.julianDay + 6)
		+ 7 * yyDayOrdinal;
	if (yyDayOrdinal > 0) {
	    yydate.julianDay -= 7;
	}
	info->flags |= CLF_ASSEMBLE_DATE|CLF_ASSEMBLE_SECONDS;
    }

    return TCL_OK;
}

/*----------------------------------------------------------------------
 *
 * ClockWeekdaysOffs --
 *
 *	Get offset in days for the number of week days corresponding the
 *	given day of week (skipping Saturdays and Sundays).
 *
 *
 * Results:
 *	Returns a day increment adjusted the given weekdays
 *
 *----------------------------------------------------------------------
 */

static inline int
ClockWeekdaysOffs(
    int dayOfWeek,
    int offs)
{
    int weeks, resDayOfWeek;

    /* offset in days */
    weeks = offs / 5;
    offs = offs % 5;
    /* compiler fix for negative offs - wrap (0, -1) -> (-1, 4) */
    if (offs < 0) {
	weeks--;
	offs = 5 + offs;
    }
    offs += 7 * weeks;

    /* resulting day of week */
    {
	int day = (offs % 7);

	/* compiler fix for negative offs - wrap (0, -1) -> (-1, 6) */
	if (day < 0) {
	    day = 7 + day;
	}
	resDayOfWeek = dayOfWeek + day;
    }

    /* adjust if we start from a weekend */
    if (dayOfWeek > 5) {
	int adj = 5 - dayOfWeek;

	offs += adj;
	resDayOfWeek += adj;
    }

    /* adjust if we end up on a weekend */
    if (resDayOfWeek > 5) {
	offs += 2;
    }

    return offs;
}

/*----------------------------------------------------------------------
 *
 * ClockAddObjCmd -- , clock add --
 *
 *	Adds an offset to a given time.
 *
 *	Refer to the user documentation to see what it exactly does.
 *
 * Syntax:
 *   clock add clockval ?count unit?... ?-option value?
 *
 * Parameters:
 *   clockval -- Starting time value
 *   count -- Amount of a unit of time to add
 *   unit -- Unit of time to add, must be one of:
 *	     years year months month weeks week
 *	     days day hours hour minutes minute
 *	     seconds second
 *
 * Options:
 *   -gmt BOOLEAN
 *	 Flag synonymous with '-timezone :GMT'
 *   -timezone ZONE
 *	 Name of the time zone in which calculations are to be done.
 *   -locale NAME
 *	 Name of the locale in which calculations are to be done.
 *	 Used to determine the Gregorian change date.
 *
 * Results:
 *	Returns a standard Tcl result with the given time adjusted
 *	by the given offset(s) in order.
 *
 * Notes:
 *   It is possible that adding a number of months or years will adjust the
 *   day of the month as well.	For instance, the time at one month after
 *   31 January is either 28 or 29 February, because February has fewer
 *   than 31 days.
 *
 *----------------------------------------------------------------------
 */

int
ClockAddObjCmd(
    void *clientData,		/* Client data containing literal pool */
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const objv[])	/* Parameter values */
{
    static const char *syntax = "clock add clockval|now ?number units?..."
	    "?-gmt boolean? "
	    "?-locale LOCALE? ?-timezone ZONE?";
    ClockClientData *dataPtr = (ClockClientData *)clientData;
    int ret;
    ClockFmtScnCmdArgs opts;	/* Format, locale, timezone and base */
    DateInfo yy;		/* Common structure used for parsing */
    DateInfo *info = &yy;

    /* add "week" to units also (because otherwise ambiguous) */
    static const char *const units[] = {
	"years",	"months",	    "week",	    "weeks",
	"days",		"weekdays",
	"hours",	"minutes",	    "seconds",
	NULL
    };
    enum unitInd {
	CLC_ADD_YEARS,	CLC_ADD_MONTHS,	    CLC_ADD_WEEK,   CLC_ADD_WEEKS,
	CLC_ADD_DAYS,	CLC_ADD_WEEKDAYS,
	CLC_ADD_HOURS,	CLC_ADD_MINUTES,    CLC_ADD_SECONDS
    };
    int unitIndex;		/* Index of an option. */
    Tcl_Size i;
    Tcl_WideInt offs;

    /* even number of arguments */
    if ((objc & 1) == 1) {
	Tcl_WrongNumArgs(interp, 0, objv, syntax);
	Tcl_SetErrorCode(interp, "CLOCK", "wrongNumArgs", (char *)NULL);
	return TCL_ERROR;
    }

    ClockInitDateInfo(&yy);

    /*
     * Extract values for the keywords.
     */

    ClockInitFmtScnArgs(dataPtr, interp, &opts);
    ret = ClockParseFmtScnArgs(&opts, &yy.date, objc, objv,
	    CLC_OP_ADD, "-gmt, -locale, or -timezone");
    if (ret != TCL_OK) {
	goto done;
    }

    /* time together as seconds of the day */
    yySecondOfDay = yySeconds = yydate.localSeconds % SECONDS_PER_DAY;
    /* seconds are in localSeconds (relative base date), so reset time here */
    yyHour = 0;
    yyMinutes = 0;
    yyMeridian = MER24;

    ret = TCL_ERROR;

    /*
     * Find each offset and process date increment
     */

    for (i = 2; i < objc; i+=2) {
	/* bypass not integers (options, allready processed above in ClockParseFmtScnArgs) */
	if (TclGetWideIntFromObj(NULL, objv[i], &offs) != TCL_OK) {
	    continue;
	}
	/* get unit */
	if (Tcl_GetIndexFromObj(interp, objv[i + 1], units, "unit", 0,
		&unitIndex) != TCL_OK) {
	    goto done;
	}
	if (TclHasInternalRep(objv[i], &tclBignumType)
		|| offs > (unitIndex < CLC_ADD_HOURS ? 0x7fffffff : TCL_MAX_SECONDS)
		|| offs < (unitIndex < CLC_ADD_HOURS ? -0x7fffffff : TCL_MIN_SECONDS)) {
	    Tcl_SetObjResult(interp, dataPtr->literals[LIT_INTEGER_VALUE_TOO_LARGE]);
	    goto done;
	}

	/* nothing to do if zero quantity */
	if (!offs) {
	    continue;
	}

	/* if in-between conversion needed (already have relative date/time),
	 * correct date info, because the date may be changed,
	 * so refresh it now */

	if ((info->flags & CLF_RELCONV)
		&& (unitIndex == CLC_ADD_WEEKDAYS
		/* some months can be shorter as another */
		|| yyRelMonth || yyRelDay
		/* day changed */
		|| yySeconds + yyRelSeconds > SECONDS_PER_DAY
		|| yySeconds + yyRelSeconds < 0)) {
	    if (ClockCalcRelTime(info) != TCL_OK) {
		goto done;
	    }
	}

	/* process increment by offset + unit */
	info->flags |= CLF_RELCONV;
	switch (unitIndex) {
	case CLC_ADD_YEARS:
	    yyRelMonth += offs * 12;
	    break;
	case CLC_ADD_MONTHS:
	    yyRelMonth += offs;
	    break;
	case CLC_ADD_WEEK:
	case CLC_ADD_WEEKS:
	    yyRelDay += offs * 7;
	    break;
	case CLC_ADD_DAYS:
	    yyRelDay += offs;
	    break;
	case CLC_ADD_WEEKDAYS:
	    /* add number of week days (skipping Saturdays and Sundays)
	     * to a relative days value. */
	    offs = ClockWeekdaysOffs(yy.date.dayOfWeek, offs);
	    yyRelDay += offs;
	    break;
	case CLC_ADD_HOURS:
	    yyRelSeconds += offs * 60 * 60;
	    break;
	case CLC_ADD_MINUTES:
	    yyRelSeconds += offs * 60;
	    break;
	case CLC_ADD_SECONDS:
	    yyRelSeconds += offs;
	    break;
	}
    }

    /*
     * Return options as a list.
     * Do relative times (if not yet already processed interim):
     */

    Tcl_SetObjResult(interp, Tcl_NewListObj(3, results));
    return TCL_OK;

#undef timezoneObj
#undef localeObj
#undef formatObj
    if (info->flags & CLF_RELCONV) {
	if (ClockCalcRelTime(info) != TCL_OK) {
	    goto done;
	}
    }

    /* Convert date info structure into UTC seconds */

    ret = ClockScanCommit(&yy, &opts);

  done:
    TclUnsetObjRef(yy.date.tzName);
    if (ret != TCL_OK) {
	return ret;
    }
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(yy.date.seconds));
    return TCL_OK;
}

/*----------------------------------------------------------------------
 *
 * ClockSecondsObjCmd -
 *
 *	Returns a count of microseconds since the epoch.
1984
1985
1986
1987
1988
1989
1990
1991

1992
1993
1994
1995
1996

1997
1998
1999

2000
2001
2002


2003

2004
2005






































































2006
2007
2008
2009
2010
2011
2012
2013
2014
2015

2016

2017
2018
2019
2020
2021
2022
2023


























2024

2025
2026



2027
2028
2029














2030

2031


2032
2033
2034




2035
2036
2037


2038
2039
2040
2041




2042

2043
2044






2045
2046
2047
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
4525
4526
4527
4528
4529
4530
4531

4532
4533
4534
4535
4536
4537
4538
4539
4540

4541
4542
4543
4544
4545
4546

4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630

4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
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
4688
4689



4690
4691
4692
4693
4694


4695
4696
4697



4698
4699
4700
4701
4702
4703


4704
4705
4706
4707
4708
4709
4710
4711


4712
4713
4714



4715











4716

4717

4718
4719


4720
4721

4722



4723
4724



4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735







-
+





+


-
+



+
+
-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










+
-
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+


+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+

+
+
-
-
-
+
+
+
+

-
-
+
+

-
-
-
+
+
+
+

+
-
-
+
+
+
+
+
+


-
-
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-

-
+
-
+

-
-
+

-
+
-
-
-
+
+
-
-
-
+
+









 * documentation for details on what it does.
 *
 *----------------------------------------------------------------------
 */

int
ClockSecondsObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const *objv)	/* Parameter values */
{
    Tcl_Time now;
    Tcl_Obj *timeObj;

    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	Tcl_WrongNumArgs(interp, 0, objv, "clock seconds");
	return TCL_ERROR;
    }
    Tcl_GetTime(&now);
    TclNewUIntObj(timeObj, (Tcl_WideUInt)now.sec);

    Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) now.sec));
    Tcl_SetObjResult(interp, timeObj);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ClockSafeCatchCmd --
 *
 *	Same as "::catch" command but avoids overwriting of interp state.
 *
 *	See [554117edde] for more info (and proper solution).
 *
 *----------------------------------------------------------------------
 */
int
ClockSafeCatchCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    typedef struct {
	int status;			/* return code status */
	int flags;			/* Each remaining field saves the */
	int returnLevel;		/* corresponding field of the Interp */
	int returnCode;			/* struct. These fields taken together are */
	Tcl_Obj *errorInfo;		/* the "state" of the interp. */
	Tcl_Obj *errorCode;
	Tcl_Obj *returnOpts;
	Tcl_Obj *objResult;
	Tcl_Obj *errorStack;
	int resetErrorStack;
    } InterpState;

    Interp *iPtr = (Interp *)interp;
    int ret, flags = 0;
    InterpState *statePtr;

    if (objc == 1) {
	/* wrong # args : */
	return Tcl_CatchObjCmd(NULL, interp, objc, objv);
    }

    statePtr = (InterpState *)Tcl_SaveInterpState(interp, 0);
    if (!statePtr->errorInfo) {
	/* todo: avoid traced get of errorInfo here */
	TclInitObjRef(statePtr->errorInfo,
		Tcl_ObjGetVar2(interp, iPtr->eiVar, NULL, 0));
	flags |= ERR_LEGACY_COPY;
    }
    if (!statePtr->errorCode) {
	/* todo: avoid traced get of errorCode here */
	TclInitObjRef(statePtr->errorCode,
		Tcl_ObjGetVar2(interp, iPtr->ecVar, NULL, 0));
	flags |= ERR_LEGACY_COPY;
    }

    /* original catch */
    ret = Tcl_CatchObjCmd(NULL, interp, objc, objv);

    if (ret == TCL_ERROR) {
	Tcl_DiscardInterpState((Tcl_InterpState)statePtr);
	return TCL_ERROR;
    }
    /* overwrite result in state with catch result */
    TclSetObjRef(statePtr->objResult, Tcl_GetObjResult(interp));
    /* set result (together with restore state) to interpreter */
    (void) Tcl_RestoreInterpState(interp, (Tcl_InterpState)statePtr);
    /* todo: unless ERR_LEGACY_COPY not set in restore (branch [bug-554117edde] not merged yet) */
    iPtr->flags |= (flags & ERR_LEGACY_COPY);
    return ret;
}

/*
 *----------------------------------------------------------------------
 *
 * TzsetIfNecessary --
 *
 *	Calls the tzset() library function if the contents of the TZ
 *	environment variable has changed.
 *
 * Results:
 *	An epoch counter to allow efficient checking if the timezone has
 *	None.
 *	changed.
 *
 * Side effects:
 *	Calls tzset.
 *
 *----------------------------------------------------------------------
 */

#ifdef _WIN32
#define getenv(x) _wgetenv(L##x)
#else
#define WCHAR char
#define wcslen strlen
#define wcscmp strcmp
#define wcscpy strcpy
#endif
#define TZ_INIT_MARKER	((WCHAR *) INT2PTR(-1))

typedef struct ClockTzStatic {
    WCHAR *was;			/* Previous value of TZ. */
#if TCL_MAJOR_VERSION > 8
    long long lastRefresh;	/* Used for latency before next refresh. */
#else
    long lastRefresh;		/* Used for latency before next refresh. */
#endif
    size_t epoch;		/* Epoch, signals that TZ changed. */
    size_t envEpoch;		/* Last env epoch, for faster signaling,
				 * that TZ changed via TCL */
} ClockTzStatic;
static ClockTzStatic tz = {	/* Global timezone info; protected by
				 * clockMutex.*/
    TZ_INIT_MARKER, 0, 0, 0
};

static void
static size_t
TzsetIfNecessary(void)
{
    const WCHAR *tzNow;		/* Current value of TZ. */
    Tcl_Time now;		/* Current time. */
    size_t epoch;		/* The tz.epoch that the TZ was read at. */
    static char* tzWas = (char *)INT2PTR(-1);	/* Previous value of TZ, protected by
				 * clockMutex. */
    const char *tzIsNow;	/* Current value of TZ */

    /*
     * Prevent performance regression on some platforms by resolving of system time zone:
     * small latency for check whether environment was changed (once per second)
     * no latency if environment was changed with tcl-env (compare both epoch values)
     */

    Tcl_GetTime(&now);
    if (now.sec == tz.lastRefresh && tz.envEpoch == TclEnvEpoch) {
	return tz.epoch;
    }

    tz.envEpoch = TclEnvEpoch;
    tz.lastRefresh = now.sec;

    /* check in lock */
    Tcl_MutexLock(&clockMutex);
    tzNow = getenv("TCL_TZ");
    if (tzNow == NULL) {
    tzIsNow = getenv("TZ");
    if (tzIsNow != NULL && (tzWas == NULL || tzWas == INT2PTR(-1)
	    || strcmp(tzIsNow, tzWas) != 0)) {
	tzNow = getenv("TZ");
    }
    if (tzNow != NULL && (tz.was == NULL || tz.was == TZ_INIT_MARKER
	    || wcscmp(tzNow, tz.was) != 0)) {
	tzset();
	if (tzWas != NULL && tzWas != INT2PTR(-1)) {
	    Tcl_Free(tzWas);
	if (tz.was != NULL && tz.was != TZ_INIT_MARKER) {
	    Tcl_Free(tz.was);
	}
	tzWas = (char *)Tcl_Alloc(strlen(tzIsNow) + 1);
	strcpy(tzWas, tzIsNow);
    } else if (tzIsNow == NULL && tzWas != NULL) {
	tz.was = (WCHAR *)Tcl_Alloc(sizeof(WCHAR) * (wcslen(tzNow) + 1));
	wcscpy(tz.was, tzNow);
	epoch = ++tz.epoch;
    } else if (tzNow == NULL && tz.was != NULL) {
	tzset();
	if (tz.was != TZ_INIT_MARKER) {
	if (tzWas != INT2PTR(-1)) Tcl_Free(tzWas);
	tzWas = NULL;
	    Tcl_Free(tz.was);
	}
	tz.was = NULL;
	epoch = ++tz.epoch;
    } else {
	epoch = tz.epoch;
    }
    Tcl_MutexUnlock(&clockMutex);
}


    return epoch;
}
/*
 *----------------------------------------------------------------------
 *

 * ClockDeleteCmdProc --
 *
 *	Remove a reference to the clock client data, and clean up memory
 *	when it's all gone.
 *
 * Results:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
ClockDeleteCmdProc(
ClockFinalize(
    ClientData clientData)	/* Opaque pointer to the client data */
    TCL_UNUSED(void *))
{
    ClockClientData *data = (ClockClientData *)clientData;
    int i;
    ClockFrmScnFinalize();

    if (data->refCount-- <= 1) {
    if (tz.was && tz.was != TZ_INIT_MARKER) {
	for (i = 0; i < LIT__END; ++i) {
	    Tcl_DecrRefCount(data->literals[i]);
	}
	Tcl_Free(tz.was);
    }
	Tcl_Free(data->literals);
	Tcl_Free(data);
    }

    Tcl_MutexFinalize(&clockMutex);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Added generic/tclClockFmt.c.



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
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
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tclClockFmt.c --
 *
 *	Contains the date format (and scan) routines. This code is back-ported
 *	from the time and date facilities of tclSE engine, by Serg G. Brester.
 *
 * Copyright (c) 2015 by Sergey G. Brester aka sebres. All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclStrIdxTree.h"
#include "tclDate.h"

/*
 * Miscellaneous forward declarations and functions used within this file
 */

static void		ClockFmtObj_DupInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
static void		ClockFmtObj_FreeInternalRep(Tcl_Obj *objPtr);
static int		ClockFmtObj_SetFromAny(Tcl_Interp *, Tcl_Obj *objPtr);
static void		ClockFmtObj_UpdateString(Tcl_Obj *objPtr);
static Tcl_HashEntry *	ClockFmtScnStorageAllocProc(Tcl_HashTable *, void *keyPtr);
static void		ClockFmtScnStorageFreeProc(Tcl_HashEntry *hPtr);
static void		ClockFmtScnStorageDelete(ClockFmtScnStorage *fss);

TCL_DECLARE_MUTEX(ClockFmtMutex);	/* Serializes access to common format list. */

#ifndef TCL_CLOCK_FULL_COMPAT
#define TCL_CLOCK_FULL_COMPAT 1
#endif

/*
 * Derivation of tclStringHashKeyType with extra memory management trickery.
 */

static const Tcl_HashKeyType ClockFmtScnStorageHashKeyType = {
    TCL_HASH_KEY_TYPE_VERSION,		/* version */
    0,					/* flags */
    TclHashStringKey,			/* hashKeyProc */
    TclCompareStringKeys,		/* compareKeysProc */
    ClockFmtScnStorageAllocProc,	/* allocEntryProc */
    ClockFmtScnStorageFreeProc		/* freeEntryProc */
};

#define IntFieldAt(info, offset) \
	((int *) (((char *) (info)) + (offset)))
#define WideFieldAt(info, offset) \
	((Tcl_WideInt *) (((char *) (info)) + (offset)))

/*
 * Clock scan and format facilities.
 */

/*
 *----------------------------------------------------------------------
 *
 * Clock_str2int, Clock_str2wideInt --
 *
 *	Fast inline-convertion of string to signed int or wide int by given
 *	start/end.
 *
 *	The given string should contain numbers chars only (because already
 *	pre-validated within parsing routines)
 *
 * Results:
 *	Returns a standard Tcl result.
 *	TCL_OK - by successful conversion, TCL_ERROR by (wide) int overflow
 *
 *----------------------------------------------------------------------
 */

static inline void
Clock_str2int_no(
    int *out,
    const char *p,
    const char *e,
    int sign)
{
    /* assert(e <= p + 10); */
    int val = 0;

    /* overflow impossible for 10 digits ("9..9"), so no needs to check at all */
    while (p < e) {				/* never overflows */
	val = val * 10 + (*p++ - '0');
    }
    if (sign < 0) {
	val = -val;
    }
    *out = val;
}

static inline void
Clock_str2wideInt_no(
    Tcl_WideInt *out,
    const char *p,
    const char *e,
    int sign)
{
    /* assert(e <= p + 18); */
    Tcl_WideInt val = 0;

    /* overflow impossible for 18 digits ("9..9"), so no needs to check at all */
    while (p < e) {				/* never overflows */
	val = val * 10 + (*p++ - '0');
    }
    if (sign < 0) {
	val = -val;
    }
    *out = val;
}

/* int & Tcl_WideInt overflows may happens here (expected case) */
#if (defined(__GNUC__) || defined(__GNUG__)) && !defined(__clang__)
# pragma GCC optimize("no-trapv")
#endif

static inline int
Clock_str2int(
    int *out,
    const char *p,
    const char *e,
    int sign)
{
    int val = 0;
    /* overflow impossible for 10 digits ("9..9"), so no needs to check before */
    const char *eNO = p + 10;

    if (eNO > e) {
	eNO = e;
    }
    while (p < eNO) {				/* never overflows */
	val = val * 10 + (*p++ - '0');
    }
    if (sign >= 0) {
	while (p < e) {				/* check for overflow */
	    int prev = val;

	    val = val * 10 + (*p++ - '0');
	    if (val / 10 < prev) {
		return TCL_ERROR;
	    }
	}
    } else {
	val = -val;
	while (p < e) {				/* check for overflow */
	    int prev = val;

	    val = val * 10 - (*p++ - '0');
	    if (val / 10 > prev) {
		return TCL_ERROR;
	    }
	}
    }
    *out = val;
    return TCL_OK;
}

static inline int
Clock_str2wideInt(
    Tcl_WideInt *out,
    const char *p,
    const char *e,
    int sign)
{
    Tcl_WideInt val = 0;
    /* overflow impossible for 18 digits ("9..9"), so no needs to check before */
    const char *eNO = p + 18;

    if (eNO > e) {
	eNO = e;
    }
    while (p < eNO) {				/* never overflows */
	val = val * 10 + (*p++ - '0');
    }
    if (sign >= 0) {
	while (p < e) {				/* check for overflow */
	    Tcl_WideInt prev = val;

	    val = val * 10 + (*p++ - '0');
	    if (val / 10 < prev) {
		return TCL_ERROR;
	    }
	}
    } else {
	val = -val;
	while (p < e) {				/* check for overflow */
	    Tcl_WideInt prev = val;

	    val = val * 10 - (*p++ - '0');
	    if (val / 10 > prev) {
		return TCL_ERROR;
	    }
	}
    }
    *out = val;
    return TCL_OK;
}

int
TclAtoWIe(
    Tcl_WideInt *out,
    const char *p,
    const char *e,
    int sign)
{
    return Clock_str2wideInt(out, p, e, sign);
}

#if (defined(__GNUC__) || defined(__GNUG__)) && !defined(__clang__)
# pragma GCC reset_options
#endif

/*
 *----------------------------------------------------------------------
 *
 * Clock_itoaw, Clock_witoaw --
 *
 *	Fast inline-convertion of signed int or wide int to string, using
 *	given padding with specified padchar and width (or without padding).
 *
 *	This is a very fast replacement for sprintf("%02d").
 *
 * Results:
 *	Returns position in buffer after end of conversion result.
 *
 *----------------------------------------------------------------------
 */

static inline char *
Clock_itoaw(
    char *buf,
    int val,
    char padchar,
    unsigned short width)
{
    char *p;
    static const int wrange[] = {
	1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
    };

    /* positive integer */

    if (val >= 0) {
	/* check resp. recalculate width */
	while (width <= 9 && val >= wrange[width]) {
	    width++;
	}
	/* number to string backwards */
	p = buf + width;
	*p-- = '\0';
	do {
	    char c = val % 10;

	    val /= 10;
	    *p-- = '0' + c;
	} while (val > 0);
	/* filling with pad-char */
	while (p >= buf) {
	    *p-- = padchar;
	}

	return buf + width;
    }
    /* negative integer */

    if (!width) {
	width++;
    }
    /* check resp. recalculate width (regarding sign) */
    width--;
    while (width <= 9 && val <= -wrange[width]) {
	width++;
    }
    width++;
    /* number to string backwards */
    p = buf + width;
    *p-- = '\0';
    /* differentiate platforms with -1 % 10 == 1 and -1 % 10 == -1 */
    if (-1 % 10 == -1) {
	do {
	    char c = val % 10;

	    val /= 10;
	    *p-- = '0' - c;
	} while (val < 0);
    } else {
	do {
	    char c = val % 10;

	    val /= 10;
	    *p-- = '0' + c;
	} while (val < 0);
    }
    /* sign by 0 padding */
    if (padchar != '0') {
	*p-- = '-';
    }
    /* filling with pad-char */
    while (p >= buf + 1) {
	*p-- = padchar;
    }
    /* sign by non 0 padding */
    if (padchar == '0') {
	*p = '-';
    }

    return buf + width;
}
char *
TclItoAw(
    char *buf,
    int val,
    char padchar,
    unsigned short width)
{
    return Clock_itoaw(buf, val, padchar, width);
}

static inline char *
Clock_witoaw(
    char *buf,
    Tcl_WideInt val,
    char padchar,
    unsigned short width)
{
    char *p;
    static const int wrange[] = {
	1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
    };

    /* positive integer */

    if (val >= 0) {
	/* check resp. recalculate width */
	if (val >= 10000000000LL) {
	    Tcl_WideInt val2 = val / 10000000000LL;

	    while (width <= 9 && val2 >= wrange[width]) {
		width++;
	    }
	    width += 10;
	} else {
	    while (width <= 9 && val >= wrange[width]) {
		width++;
	    }
	}
	/* number to string backwards */
	p = buf + width;
	*p-- = '\0';
	do {
	    char c = (val % 10);
	    val /= 10;
	    *p-- = '0' + c;
	} while (val > 0);
	/* filling with pad-char */
	while (p >= buf) {
	    *p-- = padchar;
	}

	return buf + width;
    }

    /* negative integer */

    if (!width) {
	width++;
    }
    /* check resp. recalculate width (regarding sign) */
    width--;
    if (val <= -10000000000LL) {
	Tcl_WideInt val2 = val / 10000000000LL;

	while (width <= 9 && val2 <= -wrange[width]) {
	    width++;
	}
	width += 10;
    } else {
	while (width <= 9 && val <= -wrange[width]) {
	    width++;
	}
    }
    width++;
    /* number to string backwards */
    p = buf + width;
    *p-- = '\0';
    /* differentiate platforms with -1 % 10 == 1 and -1 % 10 == -1 */
    if (-1 % 10 == -1) {
	do {
	    char c = val % 10;

	    val /= 10;
	    *p-- = '0' - c;
	} while (val < 0);
    } else {
	do {
	    char c = val % 10;

	    val /= 10;
	    *p-- = '0' + c;
	} while (val < 0);
    }
    /* sign by 0 padding */
    if (padchar != '0') {
	*p-- = '-';
    }
    /* filling with pad-char */
    while (p >= buf + 1) {
	*p-- = padchar;
    }
    /* sign by non 0 padding */
    if (padchar == '0') {
	*p = '-';
    }

    return buf + width;
}

/*
 * Global GC as LIFO for released scan/format object storages.
 *
 * Used to holds last released CLOCK_FMT_SCN_STORAGE_GC_SIZE formats
 * (after last reference from Tcl-object will be removed). This is helpful
 * to avoid continuous (re)creation and compiling by some dynamically resp.
 * variable format objects, that could be often reused.
 *
 * As long as format storage is used resp. belongs to GC, it takes place in
 * FmtScnHashTable also.
 */

#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0

static struct ClockFmtScnStorage_GC {
    ClockFmtScnStorage *stackPtr;
    ClockFmtScnStorage *stackBound;
    unsigned count;
} ClockFmtScnStorage_GC = {NULL, NULL, 0};

/*
 *----------------------------------------------------------------------
 *
 * ClockFmtScnStorageGC_In --
 *
 *	Adds an format storage object to GC.
 *
 *	If current GC is full (size larger as CLOCK_FMT_SCN_STORAGE_GC_SIZE)
 *	this removes last unused storage at begin of GC stack (LIFO).
 *
 *	Assumes caller holds the ClockFmtMutex.
 *
 * Results:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static inline void
ClockFmtScnStorageGC_In(
    ClockFmtScnStorage *entry)
{
    /* add new entry */
    TclSpliceIn(entry, ClockFmtScnStorage_GC.stackPtr);
    if (ClockFmtScnStorage_GC.stackBound == NULL) {
	ClockFmtScnStorage_GC.stackBound = entry;
    }
    ClockFmtScnStorage_GC.count++;

    /* if GC ist full */
    if (ClockFmtScnStorage_GC.count > CLOCK_FMT_SCN_STORAGE_GC_SIZE) {
	/* GC stack is LIFO: delete first inserted entry */
	ClockFmtScnStorage *delEnt = ClockFmtScnStorage_GC.stackBound;

	ClockFmtScnStorage_GC.stackBound = delEnt->prevPtr;
	TclSpliceOut(delEnt, ClockFmtScnStorage_GC.stackPtr);
	ClockFmtScnStorage_GC.count--;
	delEnt->prevPtr = delEnt->nextPtr = NULL;
	/* remove it now */
	ClockFmtScnStorageDelete(delEnt);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ClockFmtScnStorage_GC_Out --
 *
 *	Restores (for reusing) given format storage object from GC.
 *
 *	Assumes caller holds the ClockFmtMutex.
 *
 * Results:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static inline void
ClockFmtScnStorage_GC_Out(
    ClockFmtScnStorage *entry)
{
    TclSpliceOut(entry, ClockFmtScnStorage_GC.stackPtr);
    ClockFmtScnStorage_GC.count--;
    if (ClockFmtScnStorage_GC.stackBound == entry) {
	ClockFmtScnStorage_GC.stackBound = entry->prevPtr;
    }
    entry->prevPtr = entry->nextPtr = NULL;
}
#endif

/*
 * Global format storage hash table of type ClockFmtScnStorageHashKeyType
 * (contains list of scan/format object storages, shared across all threads).
 *
 * Used for fast searching by format string.
 */
static Tcl_HashTable FmtScnHashTable;
static int initialized = 0;

/*
 * Wrappers between pointers to hash entry and format storage object
 */
static inline Tcl_HashEntry *
HashEntry4FmtScn(
    ClockFmtScnStorage *fss)
{
    return (Tcl_HashEntry*)(fss + 1);
}

static inline ClockFmtScnStorage *
FmtScn4HashEntry(
    Tcl_HashEntry *hKeyPtr)
{
    return (ClockFmtScnStorage*)(((char*)hKeyPtr) - sizeof(ClockFmtScnStorage));
}

/*
 *----------------------------------------------------------------------
 *
 * ClockFmtScnStorageAllocProc --
 *
 *	Allocate space for a hash entry containing format storage together
 *	with the string key.
 *
 * Results:
 *	The return value is a pointer to the created entry.
 *
 *----------------------------------------------------------------------
 */

static Tcl_HashEntry *
ClockFmtScnStorageAllocProc(
    TCL_UNUSED(Tcl_HashTable *),/* Hash table. */
    void *keyPtr)		/* Key to store in the hash table entry. */
{
    ClockFmtScnStorage *fss;
    const char *string = (const char *) keyPtr;
    Tcl_HashEntry *hPtr;
    unsigned size = strlen(string) + 1;
    unsigned allocsize = sizeof(ClockFmtScnStorage) + sizeof(Tcl_HashEntry);

    allocsize += size;
    if (size > sizeof(hPtr->key)) {
	allocsize -= sizeof(hPtr->key);
    }

    fss = (ClockFmtScnStorage *)Tcl_Alloc(allocsize);

    /* initialize */
    memset(fss, 0, sizeof(*fss));

    hPtr = HashEntry4FmtScn(fss);
    memcpy(&hPtr->key.string, string, size);
    hPtr->clientData = 0;	/* currently unused */

    return hPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * ClockFmtScnStorageFreeProc --
 *
 *	Free format storage object and space of given hash entry.
 *
 * Results:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
ClockFmtScnStorageFreeProc(
    Tcl_HashEntry *hPtr)
{
    ClockFmtScnStorage *fss = FmtScn4HashEntry(hPtr);

    if (fss->scnTok != NULL) {
	Tcl_Free(fss->scnTok);
	fss->scnTok = NULL;
	fss->scnTokC = 0;
    }
    if (fss->fmtTok != NULL) {
	Tcl_Free(fss->fmtTok);
	fss->fmtTok = NULL;
	fss->fmtTokC = 0;
    }

    Tcl_Free(fss);
}

/*
 *----------------------------------------------------------------------
 *
 * ClockFmtScnStorageDelete --
 *
 *	Delete format storage object.
 *
 * Results:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
ClockFmtScnStorageDelete(
    ClockFmtScnStorage *fss)
{
    Tcl_HashEntry *hPtr = HashEntry4FmtScn(fss);
    /*
     * This will delete a hash entry and call "Tcl_Free" for storage self, if
     * some additionally handling required, freeEntryProc can be used instead
     */
    Tcl_DeleteHashEntry(hPtr);
}

/*
 * Type definition of clock-format tcl object type.
 */

static const Tcl_ObjType ClockFmtObjType = {
    "clock-format",			/* name */
    ClockFmtObj_FreeInternalRep,	/* freeIntRepProc */
    ClockFmtObj_DupInternalRep,		/* dupIntRepProc */
    ClockFmtObj_UpdateString,		/* updateStringProc */
    ClockFmtObj_SetFromAny,		/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

#define ObjClockFmtScn(objPtr) \
    (*((ClockFmtScnStorage **)&(objPtr)->internalRep.twoPtrValue.ptr1))

#define ObjLocFmtKey(objPtr) \
    (*((Tcl_Obj **)&(objPtr)->internalRep.twoPtrValue.ptr2))

static void
ClockFmtObj_DupInternalRep(
    Tcl_Obj *srcPtr,
    Tcl_Obj *copyPtr)
{
    ClockFmtScnStorage *fss = ObjClockFmtScn(srcPtr);

    if (fss != NULL) {
	Tcl_MutexLock(&ClockFmtMutex);
	fss->objRefCount++;
	Tcl_MutexUnlock(&ClockFmtMutex);
    }

    ObjClockFmtScn(copyPtr) = fss;
    /* regards special case - format not localizable */
    if (ObjLocFmtKey(srcPtr) != srcPtr) {
	TclInitObjRef(ObjLocFmtKey(copyPtr), ObjLocFmtKey(srcPtr));
    } else {
	ObjLocFmtKey(copyPtr) = copyPtr;
    }
    copyPtr->typePtr = &ClockFmtObjType;

    /* if no format representation, dup string representation */
    if (fss == NULL) {
	copyPtr->bytes = (char *)Tcl_Alloc(srcPtr->length + 1);
	memcpy(copyPtr->bytes, srcPtr->bytes, srcPtr->length + 1);
	copyPtr->length = srcPtr->length;
    }
}

static void
ClockFmtObj_FreeInternalRep(
    Tcl_Obj *objPtr)
{
    ClockFmtScnStorage *fss = ObjClockFmtScn(objPtr);
    if (fss != NULL && initialized) {
	Tcl_MutexLock(&ClockFmtMutex);
	/* decrement object reference count of format/scan storage */
	if (--fss->objRefCount <= 0) {
#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0
	    /* don't remove it right now (may be reusable), just add to GC */
	    ClockFmtScnStorageGC_In(fss);
#else
	    /* remove storage (format representation) */
	    ClockFmtScnStorageDelete(fss);
#endif
	}
	Tcl_MutexUnlock(&ClockFmtMutex);
    }
    ObjClockFmtScn(objPtr) = NULL;
    if (ObjLocFmtKey(objPtr) != objPtr) {
	TclUnsetObjRef(ObjLocFmtKey(objPtr));
    } else {
	ObjLocFmtKey(objPtr) = NULL;
    }
    objPtr->typePtr = NULL;
}

static int
ClockFmtObj_SetFromAny(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Obj *objPtr)
{
    /* validate string representation before free old internal representation */
    (void)TclGetString(objPtr);

    /* free old internal representation */
    TclFreeInternalRep(objPtr);

    /* initial state of format object */
    ObjClockFmtScn(objPtr) = NULL;
    ObjLocFmtKey(objPtr) = NULL;
    objPtr->typePtr = &ClockFmtObjType;

    return TCL_OK;
}

static void
ClockFmtObj_UpdateString(
    Tcl_Obj *objPtr)
{
    const char *name = "UNKNOWN";
    size_t len;
    ClockFmtScnStorage *fss = ObjClockFmtScn(objPtr);

    if (fss != NULL) {
	Tcl_HashEntry *hPtr = HashEntry4FmtScn(fss);
	name = hPtr->key.string;
    }
    len = strlen(name);
    objPtr->length = len++,
    objPtr->bytes = (char *)Tcl_AttemptAlloc(len);
    if (objPtr->bytes) {
	memcpy(objPtr->bytes, name, len);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ClockFrmObjGetLocFmtKey --
 *
 *	Retrieves format key object used to search localized format.
 *
 *	This is normally stored in second pointer of internal representation.
 *	If format object is not localizable, it is equal the given format
 *	pointer (special case to fast fallback by not-localizable formats).
 *
 * Results:
 *	Returns tcl object with key or format object if not localizable.
 *
 * Side effects:
 *	Converts given format object to ClockFmtObjType on demand for caching
 *	the key inside its internal representation.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj*
ClockFrmObjGetLocFmtKey(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr)
{
    Tcl_Obj *keyObj;

    if (objPtr->typePtr != &ClockFmtObjType) {
	if (ClockFmtObj_SetFromAny(interp, objPtr) != TCL_OK) {
	    return NULL;
	}
    }

    keyObj = ObjLocFmtKey(objPtr);
    if (keyObj) {
	return keyObj;
    }

    keyObj = Tcl_ObjPrintf("FMT_%s", TclGetString(objPtr));
    TclInitObjRef(ObjLocFmtKey(objPtr), keyObj);

    return keyObj;
}

/*
 *----------------------------------------------------------------------
 *
 * FindOrCreateFmtScnStorage --
 *
 *	Retrieves format storage for given string format.
 *
 *	This will find the given format in the global storage hash table
 *	or create a format storage object on demaind and save the
 *	reference in the first pointer of internal representation of given
 *	object.
 *
 * Results:
 *	Returns scan/format storage pointer to ClockFmtScnStorage.
 *
 * Side effects:
 *	Converts given format object to ClockFmtObjType on demand for caching
 *	the format storage reference inside its internal representation.
 *	Increments objRefCount of the ClockFmtScnStorage reference.
 *
 *----------------------------------------------------------------------
 */

static ClockFmtScnStorage *
FindOrCreateFmtScnStorage(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr)
{
    const char *strFmt = TclGetString(objPtr);
    ClockFmtScnStorage *fss = NULL;
    int isNew;
    Tcl_HashEntry *hPtr;

    Tcl_MutexLock(&ClockFmtMutex);

    /* if not yet initialized */
    if (!initialized) {
	/* initialize hash table */
	Tcl_InitCustomHashTable(&FmtScnHashTable, TCL_CUSTOM_TYPE_KEYS,
		&ClockFmtScnStorageHashKeyType);

	initialized = 1;
    }

    /* get or create entry (and alocate storage) */
    hPtr = Tcl_CreateHashEntry(&FmtScnHashTable, strFmt, &isNew);
    if (hPtr != NULL) {
	fss = FmtScn4HashEntry(hPtr);

#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0
	/* unlink if it is currently in GC */
	if (isNew == 0 && fss->objRefCount == 0) {
	    ClockFmtScnStorage_GC_Out(fss);
	}
#endif

	/* new reference, so increment in lock right now */
	fss->objRefCount++;
	ObjClockFmtScn(objPtr) = fss;
    }

    Tcl_MutexUnlock(&ClockFmtMutex);

    if (fss == NULL && interp != NULL) {
	Tcl_AppendResult(interp, "retrieve clock format failed \"",
		strFmt ? strFmt : "", "\"", (char *)NULL);
	Tcl_SetErrorCode(interp, "TCL", "EINVAL", (char *)NULL);
    }

    return fss;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetClockFrmScnFromObj --
 *
 *	Returns a clock format/scan representation of (*objPtr), if possible.
 *	If something goes wrong, NULL is returned, and if interp is non-NULL,
 *	an error message is written there.
 *
 * Results:
 *	Valid representation of type ClockFmtScnStorage.
 *
 * Side effects:
 *	Caches the ClockFmtScnStorage reference as the internal rep of (*objPtr)
 *	and in global hash table, shared across all threads.
 *
 *----------------------------------------------------------------------
 */

ClockFmtScnStorage *
Tcl_GetClockFrmScnFromObj(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr)
{
    ClockFmtScnStorage *fss;

    if (objPtr->typePtr != &ClockFmtObjType) {
	if (ClockFmtObj_SetFromAny(interp, objPtr) != TCL_OK) {
	    return NULL;
	}
    }

    fss = ObjClockFmtScn(objPtr);

    if (fss == NULL) {
	fss = FindOrCreateFmtScnStorage(interp, objPtr);
    }

    return fss;
}
/*
 *----------------------------------------------------------------------
 *
 * ClockLocalizeFormat --
 *
 *	Wrap the format object in options to the localized format,
 *	corresponding given locale.
 *
 *	This searches localized format in locale catalog, and if not yet
 *	exists, it executes ::tcl::clock::LocalizeFormat in given interpreter
 *	and caches its result in the locale catalog.
 *
 * Results:
 *	Localized format object.
 *
 * Side effects:
 *	Caches the localized format inside locale catalog.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
ClockLocalizeFormat(
    ClockFmtScnCmdArgs *opts)
{
    ClockClientData *dataPtr = opts->dataPtr;
    Tcl_Obj *valObj = NULL, *keyObj;

    keyObj = ClockFrmObjGetLocFmtKey(opts->interp, opts->formatObj);

    /* special case - format object is not localizable */
    if (keyObj == opts->formatObj) {
	return opts->formatObj;
    }

    /* prevents loss of key object if the format object (where key stored)
     * becomes changed (loses its internal representation during evals) */
    Tcl_IncrRefCount(keyObj);

    if (opts->mcDictObj == NULL) {
	ClockMCDict(opts);
	if (opts->mcDictObj == NULL) {
	    goto done;
	}
    }

    /* try to find in cache within locale mc-catalog */
    if (Tcl_DictObjGet(NULL, opts->mcDictObj, keyObj, &valObj) != TCL_OK) {
	goto done;
    }

    /* call LocalizeFormat locale format fmtkey */
    if (valObj == NULL) {
	Tcl_Obj *callargs[4];

	callargs[0] = dataPtr->literals[LIT_LOCALIZE_FORMAT];
	callargs[1] = opts->localeObj;
	callargs[2] = opts->formatObj;
	callargs[3] = opts->mcDictObj;
	if (Tcl_EvalObjv(opts->interp, 4, callargs, 0) == TCL_OK) {
	    valObj = Tcl_GetObjResult(opts->interp);
	}

	/* ensure mcDictObj remains unshared */
	if (opts->mcDictObj->refCount > 1) {
	    /* smart reference (shared dict as object with no ref-counter) */
	    opts->mcDictObj = TclDictObjSmartRef(opts->interp,
		    opts->mcDictObj);
	}
	if (!valObj) {
	    goto done;
	}
	/* cache it inside mc-dictionary (this incr. ref count of keyObj/valObj) */
	if (Tcl_DictObjPut(opts->interp, opts->mcDictObj, keyObj, valObj) != TCL_OK) {
	    valObj = NULL;
	    goto done;
	}

	Tcl_ResetResult(opts->interp);

	/* check special case - format object is not localizable */
	if (valObj == opts->formatObj) {
	    /* mark it as unlocalizable, by setting self as key (without refcount incr) */
	    if (valObj->typePtr == &ClockFmtObjType) {
		TclUnsetObjRef(ObjLocFmtKey(valObj));
		ObjLocFmtKey(valObj) = valObj;
	    }
	}
    }

done:

    TclUnsetObjRef(keyObj);
    return (opts->formatObj = valObj);
}

/*
 *----------------------------------------------------------------------
 *
 * FindTokenBegin --
 *
 *	Find begin of given scan token in string, corresponding token type.
 *
 * Results:
 *	Position of token inside string if found. Otherwise - end of string.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static const char *
FindTokenBegin(
    const char *p,
    const char *end,
    ClockScanToken *tok,
    int flags)
{
    if (p < end) {
	char c;

	/* next token a known token type */
	switch (tok->map->type) {
	case CTOKT_INT:
	case CTOKT_WIDE:
	    if (!(flags & CLF_STRICT)) {
		/* should match at least one digit or space */
		while (!isdigit(UCHAR(*p)) && !isspace(UCHAR(*p)) &&
			(p = Tcl_UtfNext(p)) < end) {}
	    } else {
		/* should match at least one digit */
		while (!isdigit(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {}
	    }
	    return p;

	case CTOKT_WORD:
	    c = *(tok->tokWord.start);
	    goto findChar;

	case CTOKT_SPACE:
	    while (!isspace(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {}
	    return p;

	case CTOKT_CHAR:
	    c = *((char *)tok->map->data);
findChar:
	    if (!(flags & CLF_STRICT)) {
		/* should match the char or space */
		while (*p != c && !isspace(UCHAR(*p)) &&
			(p = Tcl_UtfNext(p)) < end) {}
	    } else {
		/* should match the char */
		while (*p != c && (p = Tcl_UtfNext(p)) < end) {}
	    }
	    return p;
	}
    }
    return p;
}

/*
 *----------------------------------------------------------------------
 *
 * DetermineGreedySearchLen --
 *
 *	Determine min/max lengths as exact as possible (speed, greedy match).
 *
 * Results:
 *	None. Lengths are stored in *minLenPtr, *maxLenPtr.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
DetermineGreedySearchLen(
    ClockFmtScnCmdArgs *opts,
    DateInfo *info,
    ClockScanToken *tok,
    int *minLenPtr,
    int *maxLenPtr)
{
    int minLen = tok->map->minSize;
    int maxLen;
    const char *p = yyInput + minLen;
    const char *end = info->dateEnd;

    /* if still tokens available, try to correct minimum length */
    if ((tok + 1)->map) {
	end -= tok->endDistance + yySpaceCount;
	/* find position of next known token */
	p = FindTokenBegin(p, end, tok + 1,
		TCL_CLOCK_FULL_COMPAT ? opts->flags : CLF_STRICT);
	if (p < end) {
	    minLen = p - yyInput;
	}
    }

    /* max length to the end regarding distance to end (min-width of following tokens) */
    maxLen = end - yyInput;
    /* several amendments */
    if (maxLen > tok->map->maxSize) {
	maxLen = tok->map->maxSize;
    }
    if (minLen < tok->map->minSize) {
	minLen = tok->map->minSize;
    }
    if (minLen > maxLen) {
	maxLen = minLen;
    }
    if (maxLen > info->dateEnd - yyInput) {
	maxLen = info->dateEnd - yyInput;
    }

    /* check digits rigth now */
    if (tok->map->type == CTOKT_INT || tok->map->type == CTOKT_WIDE) {
	p = yyInput;
	end = p + maxLen;
	if (end > info->dateEnd) {
	    end = info->dateEnd;
	}
	while (isdigit(UCHAR(*p)) && p < end) {
	    p++;
	}
	maxLen = p - yyInput;
    }

    /* try to get max length more precise for greedy match,
     * check the next ahead token available there */
    if (minLen < maxLen && tok->lookAhTok) {
	ClockScanToken *laTok = tok + tok->lookAhTok + 1;

	p = yyInput + maxLen;
	/* regards all possible spaces here (because they are optional) */
	end = p + tok->lookAhMax + yySpaceCount + 1;
	if (end > info->dateEnd) {
	    end = info->dateEnd;
	}
	p += tok->lookAhMin;
	if (laTok->map && p < end) {

	    /* try to find laTok between [lookAhMin, lookAhMax] */
	    while (minLen < maxLen) {
		const char *f = FindTokenBegin(p, end, laTok,
				    TCL_CLOCK_FULL_COMPAT ? opts->flags : CLF_STRICT);
		/* if found (not below lookAhMax) */
		if (f < end) {
		    break;
		}
		/* try again with fewer length */
		maxLen--;
		p--;
		end--;
	    }
	} else if (p > end) {
	    maxLen -= (p - end);
	    if (maxLen < minLen) {
		maxLen = minLen;
	    }
	}
    }

    *minLenPtr = minLen;
    *maxLenPtr = maxLen;
}

/*
 *----------------------------------------------------------------------
 *
 * ObjListSearch --
 *
 *	Find largest part of the input string from start regarding min and
 *	max lengths in the given list (utf-8, case sensitive).
 *
 * Results:
 *	TCL_OK - match found, TCL_RETURN - not matched, TCL_ERROR in error case.
 *
 * Side effects:
 *	Input points to end of the found token in string.
 *
 *----------------------------------------------------------------------
 */

static inline int
ObjListSearch(
    DateInfo *info,
    int *val,
    Tcl_Obj **lstv,
    Tcl_Size lstc,
    int minLen,
    int maxLen)
{
    Tcl_Size i, l, lf = -1;
    const char *s, *f, *sf;

    /* search in list */
    for (i = 0; i < lstc; i++) {
	s = TclGetStringFromObj(lstv[i], &l);

	if (l >= minLen
		&& (f = TclUtfFindEqualNC(yyInput, yyInput + maxLen, s, s + l, &sf)) > yyInput) {
	    l = f - yyInput;
	    if (l < minLen) {
		continue;
	    }
	    /* found, try to find longest value (greedy search) */
	    if (l < maxLen && minLen != maxLen) {
		lf = i;
		minLen = l + 1;
		continue;
	    }
	    /* max possible - end of search */
	    *val = i;
	    yyInput += l;
	    break;
	}
    }

    /* if found */
    if (i < lstc) {
	return TCL_OK;
    }
    if (lf >= 0) {
	*val = lf;
	yyInput += minLen - 1;
	return TCL_OK;
    }
    return TCL_RETURN;
}
#if 0
/* currently unused */

static int
LocaleListSearch(
    ClockFmtScnCmdArgs *opts,
    DateInfo *info,
    int mcKey,
    int *val,
    int minLen,
    int maxLen)
{
    Tcl_Obj **lstv;
    Tcl_Size lstc;
    Tcl_Obj *valObj;

    /* get msgcat value */
    valObj = ClockMCGet(opts, mcKey);
    if (valObj == NULL) {
	return TCL_ERROR;
    }

    /* is a list */
    if (TclListObjGetElements(opts->interp, valObj, &lstc, &lstv) != TCL_OK) {
	return TCL_ERROR;
    }

    /* search in list */
    return ObjListSearch(info, val, lstv, lstc,
	    minLen, maxLen);
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * ClockMCGetListIdxTree --
 *
 *	Retrieves localized string indexed tree in the locale catalog for
 *	given literal index mcKey (and builds it on demand).
 *
 *	Searches localized index in locale catalog, and if not yet exists,
 *	creates string indexed tree and stores it in the locale catalog.
 *
 * Results:
 *	Localized string index tree.
 *
 * Side effects:
 *	Caches the localized string index tree inside locale catalog.
 *
 *----------------------------------------------------------------------
 */

static TclStrIdxTree *
ClockMCGetListIdxTree(
    ClockFmtScnCmdArgs *opts,
    int mcKey)
{
    TclStrIdxTree *idxTree;
    Tcl_Obj *objPtr = ClockMCGetIdx(opts, mcKey);

    if (objPtr != NULL
	    && (idxTree = TclStrIdxTreeGetFromObj(objPtr)) != NULL) {
	return idxTree;
    } else {
	/* build new index */

	Tcl_Obj **lstv;
	Tcl_Size lstc;
	Tcl_Obj *valObj;

	objPtr = TclStrIdxTreeNewObj();
	if ((idxTree = TclStrIdxTreeGetFromObj(objPtr)) == NULL) {
	    goto done;	/* unexpected, but ...*/
	}

	valObj = ClockMCGet(opts, mcKey);
	if (valObj == NULL) {
	    goto done;
	}
	if (TclListObjGetElements(opts->interp, valObj, &lstc, &lstv) != TCL_OK) {
	    goto done;
	}
	if (TclStrIdxTreeBuildFromList(idxTree, lstc, lstv, NULL) != TCL_OK) {
	    goto done;
	}

	ClockMCSetIdx(opts, mcKey, objPtr);
	objPtr = NULL;
    }

  done:
    if (objPtr) {
	Tcl_DecrRefCount(objPtr);
	idxTree = NULL;
    }

    return idxTree;
}

/*
 *----------------------------------------------------------------------
 *
 * ClockMCGetMultiListIdxTree --
 *
 *	Retrieves localized string indexed tree in the locale catalog for
 *	multiple lists by literal indices mcKeys (and builds it on demand).
 *
 *	Searches localized index in locale catalog for mcKey, and if not
 *	yet exists, creates string indexed tree and stores it in the
 *	locale catalog.
 *
 * Results:
 *	Localized string index tree.
 *
 * Side effects:
 *	Caches the localized string index tree inside locale catalog.
 *
 *----------------------------------------------------------------------
 */

static TclStrIdxTree *
ClockMCGetMultiListIdxTree(
    ClockFmtScnCmdArgs *opts,
    int	mcKey,
    int *mcKeys)
{
    TclStrIdxTree * idxTree;
    Tcl_Obj *objPtr = ClockMCGetIdx(opts, mcKey);

    if (objPtr != NULL
	    && (idxTree = TclStrIdxTreeGetFromObj(objPtr)) != NULL) {
	return idxTree;
    } else {
	/* build new index */

	Tcl_Obj **lstv;
	Tcl_Size lstc;
	Tcl_Obj *valObj;

	objPtr = TclStrIdxTreeNewObj();
	if ((idxTree = TclStrIdxTreeGetFromObj(objPtr)) == NULL) {
	    goto done;	/* unexpected, but ...*/
	}

	while (*mcKeys) {
	    valObj = ClockMCGet(opts, *mcKeys);
	    if (valObj == NULL) {
		goto done;
	    }
	    if (TclListObjGetElements(opts->interp, valObj, &lstc, &lstv) != TCL_OK) {
		goto done;
	    }
	    if (TclStrIdxTreeBuildFromList(idxTree, lstc, lstv, NULL) != TCL_OK) {
		goto done;
	    }
	    mcKeys++;
	}

	ClockMCSetIdx(opts, mcKey, objPtr);
	objPtr = NULL;
    }

  done:
    if (objPtr) {
	Tcl_DecrRefCount(objPtr);
	idxTree = NULL;
    }

    return idxTree;
}

/*
 *----------------------------------------------------------------------
 *
 * ClockStrIdxTreeSearch --
 *
 *	Find largest part of the input string from start regarding lengths
 *	in the given localized string indexed tree (utf-8, case sensitive).
 *
 * Results:
 *	TCL_OK - match found and the index stored in *val,
 *	TCL_RETURN - not matched or ambigous,
 *	TCL_ERROR - in error case.
 *
 * Side effects:
 *	Input points to end of the found token in string.
 *
 *----------------------------------------------------------------------
 */

static inline int
ClockStrIdxTreeSearch(
    DateInfo *info,
    TclStrIdxTree *idxTree,
    int *val,
    int minLen,
    int maxLen)
{
    TclStrIdx *foundItem;
    const char *f = TclStrIdxTreeSearch(NULL, &foundItem, idxTree,
	    yyInput, yyInput + maxLen);

    if (f <= yyInput || (f - yyInput) < minLen) {
	/* not found */
	return TCL_RETURN;
    }
    if (!foundItem->value) {
	/* ambigous */
	return TCL_RETURN;
    }

    *val = PTR2INT(foundItem->value);

    /* shift input pointer */
    yyInput = f;

    return TCL_OK;
}
#if 0
/* currently unused */

static int
StaticListSearch(
    ClockFmtScnCmdArgs *opts,
    DateInfo *info,
    const char **lst,
    int *val)
{
    size_t len;
    const char **s = lst;

    while (*s != NULL) {
	len = strlen(*s);
	if (len <= info->dateEnd - yyInput
		&& strncasecmp(yyInput, *s, len) == 0) {
	    *val = (s - lst);
	    yyInput += len;
	    break;
	}
	s++;
    }
    if (*s != NULL) {
	return TCL_OK;
    }
    return TCL_RETURN;
}
#endif

static inline const char *
FindWordEnd(
    ClockScanToken *tok,
    const char *p,
    const char *end)
{
    const char *x = tok->tokWord.start;
    const char *pfnd = p;

    if (x == tok->tokWord.end - 1) { /* fast phase-out for single char word */
	if (*p == *x) {
	    return ++p;
	}
    }
    /* multi-char word */
    x = TclUtfFindEqualNC(x, tok->tokWord.end, p, end, &pfnd);
    if (x < tok->tokWord.end) {
	/* no match -> error */
	return NULL;
    }
    return pfnd;
}

static int
ClockScnToken_Month_Proc(
    ClockFmtScnCmdArgs *opts,
    DateInfo *info,
    ClockScanToken *tok)
{
#if 0
/* currently unused, test purposes only */
    static const char * months[] = {
	/* full */
	"January", "February", "March",
	"April",   "May",      "June",
	"July",	   "August",   "September",
	"October", "November", "December",
	/* abbr */
	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
	NULL
    };
    int val;
    if (StaticListSearch(opts, info, months, &val) != TCL_OK) {
	return TCL_RETURN;
    }
    yyMonth = (val % 12) + 1;
#else
    static int monthsKeys[] = {MCLIT_MONTHS_FULL, MCLIT_MONTHS_ABBREV, 0};

    int ret, val;
    int minLen, maxLen;
    TclStrIdxTree *idxTree;

    DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen);

    /* get or create tree in msgcat dict */

    idxTree = ClockMCGetMultiListIdxTree(opts, MCLIT_MONTHS_COMB, monthsKeys);
    if (idxTree == NULL) {
	return TCL_ERROR;
    }

    ret = ClockStrIdxTreeSearch(info, idxTree, &val, minLen, maxLen);
    if (ret != TCL_OK) {
	return ret;
    }

    yyMonth = val;
#endif
    return TCL_OK;
}

static int
ClockScnToken_DayOfWeek_Proc(
    ClockFmtScnCmdArgs *opts,
    DateInfo *info,
    ClockScanToken *tok)
{
    static int dowKeys[] = {MCLIT_DAYS_OF_WEEK_ABBREV, MCLIT_DAYS_OF_WEEK_FULL, 0};

    int ret, val;
    int minLen, maxLen;
    char curTok = *tok->tokWord.start;
    TclStrIdxTree *idxTree;

    DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen);

    /* %u %w %Ou %Ow */
    if (curTok != 'a' && curTok != 'A'
	    && ((minLen <= 1 && maxLen >= 1) || PTR2INT(tok->map->data))) {
	val = -1;

	if (PTR2INT(tok->map->data) == 0) {
	    if (*yyInput >= '0' && *yyInput <= '9') {
		val = *yyInput - '0';
	    }
	} else {
	    idxTree = ClockMCGetListIdxTree(opts, PTR2INT(tok->map->data) /* mcKey */);
	    if (idxTree == NULL) {
		return TCL_ERROR;
	    }

	    ret = ClockStrIdxTreeSearch(info, idxTree, &val, minLen, maxLen);
	    if (ret != TCL_OK) {
		return ret;
	    }
	    --val;
	}

	if (val == -1) {
	    return TCL_RETURN;
	}

	if (val == 0) {
	    val = 7;
	}
	if (val > 7) {
	    Tcl_SetObjResult(opts->interp, Tcl_NewStringObj(
		    "day of week is greater than 7", TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(opts->interp, "CLOCK", "badDayOfWeek", (char *)NULL);
	    return TCL_ERROR;
	}
	info->date.dayOfWeek = val;
	yyInput++;
	return TCL_OK;
    }

    /* %a %A */
    idxTree = ClockMCGetMultiListIdxTree(opts, MCLIT_DAYS_OF_WEEK_COMB, dowKeys);
    if (idxTree == NULL) {
	return TCL_ERROR;
    }

    ret = ClockStrIdxTreeSearch(info, idxTree, &val, minLen, maxLen);
    if (ret != TCL_OK) {
	return ret;
    }
    --val;

    if (val == 0) {
	val = 7;
    }
    info->date.dayOfWeek = val;
    return TCL_OK;
}

static int
ClockScnToken_amPmInd_Proc(
    ClockFmtScnCmdArgs *opts,
    DateInfo *info,
    ClockScanToken *tok)
{
    int ret, val;
    int minLen, maxLen;
    Tcl_Obj *amPmObj[2];

    DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen);

    amPmObj[0] = ClockMCGet(opts, MCLIT_AM);
    amPmObj[1] = ClockMCGet(opts, MCLIT_PM);

    if (amPmObj[0] == NULL || amPmObj[1] == NULL) {
	return TCL_ERROR;
    }

    ret = ObjListSearch(info, &val, amPmObj, 2, minLen, maxLen);
    if (ret != TCL_OK) {
	return ret;
    }

    if (val == 0) {
	yyMeridian = MERam;
    } else {
	yyMeridian = MERpm;
    }

    return TCL_OK;
}

static int
ClockScnToken_LocaleERA_Proc(
    ClockFmtScnCmdArgs *opts,
    DateInfo *info,
    ClockScanToken *tok)
{
    ClockClientData *dataPtr = opts->dataPtr;

    int ret, val;
    int minLen, maxLen;
    Tcl_Obj *eraObj[6];

    DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen);

    eraObj[0] = ClockMCGet(opts, MCLIT_BCE);
    eraObj[1] = ClockMCGet(opts, MCLIT_CE);
    eraObj[2] = dataPtr->mcLiterals[MCLIT_BCE2];
    eraObj[3] = dataPtr->mcLiterals[MCLIT_CE2];
    eraObj[4] = dataPtr->mcLiterals[MCLIT_BCE3];
    eraObj[5] = dataPtr->mcLiterals[MCLIT_CE3];

    if (eraObj[0] == NULL || eraObj[1] == NULL) {
	return TCL_ERROR;
    }

    ret = ObjListSearch(info, &val, eraObj, 6, minLen, maxLen);
    if (ret != TCL_OK) {
	return ret;
    }

    if (val & 1) {
	yydate.isBce = 0;
    } else {
	yydate.isBce = 1;
    }

    return TCL_OK;
}

static int
ClockScnToken_LocaleListMatcher_Proc(
    ClockFmtScnCmdArgs *opts,
    DateInfo *info,
    ClockScanToken *tok)
{
    int ret, val;
    int minLen, maxLen;
    TclStrIdxTree *idxTree;

    DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen);

    /* get or create tree in msgcat dict */

    idxTree = ClockMCGetListIdxTree(opts, PTR2INT(tok->map->data) /* mcKey */);
    if (idxTree == NULL) {
	return TCL_ERROR;
    }

    ret = ClockStrIdxTreeSearch(info, idxTree, &val, minLen, maxLen);
    if (ret != TCL_OK) {
	return ret;
    }

    if (tok->map->offs > 0) {
	*IntFieldAt(info, tok->map->offs) = --val;
    }

    return TCL_OK;
}

static int
ClockScnToken_JDN_Proc(
    ClockFmtScnCmdArgs *opts,
    DateInfo *info,
    ClockScanToken *tok)
{
    int minLen, maxLen;
    const char *p = yyInput, *end, *s;
    Tcl_WideInt intJD;
    int fractJD = 0, fractJDDiv = 1;

    DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen);

    end = yyInput + maxLen;

    /* currently positive astronomic dates only */
    if (*p == '+' || *p == '-') {
	p++;
    }
    s = p;
    while (p < end && isdigit(UCHAR(*p))) {
	p++;
    }
    if (Clock_str2wideInt(&intJD, s, p, (*yyInput != '-' ? 1 : -1)) != TCL_OK) {
	return TCL_RETURN;
    }
    yyInput = p;
    if (p >= end || *p++ != '.') { /* allow pure integer JDN */
	/* by astronomical JD the seconds of day offs is 12 hours */
	if (tok->map->offs) {
	    goto done;
	}
	/* calendar JD */
	yydate.julianDay = intJD;
	return TCL_OK;
    }
    s = p;
    while (p < end && isdigit(UCHAR(*p))) {
	fractJDDiv *= 10;
	p++;
    }
    if (Clock_str2int(&fractJD, s, p, 1) != TCL_OK) {
	return TCL_RETURN;
    }
    yyInput = p;

  done:
    /*
     * Build a date from julian day (integer and fraction).
     * Note, astronomical JDN starts at noon in opposite to calendar julianday.
     */

    fractJD = (int)tok->map->offs /* 0 for calendar or 43200 for astro JD */
	    + (int)((Tcl_WideInt)SECONDS_PER_DAY * fractJD / fractJDDiv);
    if (fractJD >= SECONDS_PER_DAY) {
	fractJD %= SECONDS_PER_DAY;
	intJD += 1;
    }
    yydate.secondOfDay = fractJD;
    yydate.julianDay = intJD;

    yydate.seconds =
	    -210866803200LL
	    + (SECONDS_PER_DAY * intJD)
	    + fractJD;

    info->flags |= CLF_POSIXSEC;

    return TCL_OK;
}

static int
ClockScnToken_TimeZone_Proc(
    ClockFmtScnCmdArgs *opts,
    DateInfo *info,
    ClockScanToken *tok)
{
    int minLen, maxLen;
    int len = 0;
    const char *p = yyInput;
    Tcl_Obj *tzObjStor = NULL;

    DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen);

    /* numeric timezone */
    if (*p == '+' || *p == '-') {
	/* max chars in numeric zone = "+00:00:00" */
#define MAX_ZONE_LEN 9
	char buf[MAX_ZONE_LEN + 1];
	char *bp = buf;

	*bp++ = *p++;
	len++;
	if (maxLen > MAX_ZONE_LEN) {
	    maxLen = MAX_ZONE_LEN;
	}
	/* cumulate zone into buf without ':' */
	while (len + 1 < maxLen) {
	    if (!isdigit(UCHAR(*p))) {
		break;
	    }
	    *bp++ = *p++;
	    len++;
	    if (!isdigit(UCHAR(*p))) {
		break;
	    }
	    *bp++ = *p++;
	    len++;
	    if (len + 2 < maxLen) {
		if (*p == ':') {
		    p++;
		    len++;
		}
	    }
	}
	*bp = '\0';

	if (len < minLen) {
	    return TCL_RETURN;
	}
#undef MAX_ZONE_LEN

	/* timezone */
	tzObjStor = Tcl_NewStringObj(buf, bp - buf);
    } else {
	/* legacy (alnum) timezone like CEST, etc. */
	if (maxLen > 4) {
	    maxLen = 4;
	}
	while (len < maxLen) {
	    if ((*p & 0x80)
		    || (!isalpha(UCHAR(*p)) && !isdigit(UCHAR(*p)))) {	/* INTL: ISO only. */
		break;
	    }
	    p++;
	    len++;
	}

	if (len < minLen) {
	    return TCL_RETURN;
	}

	/* timezone */
	tzObjStor = Tcl_NewStringObj(yyInput, p - yyInput);

	/* convert using dict */
    }

    /* try to apply new time zone */
    Tcl_IncrRefCount(tzObjStor);

    opts->timezoneObj = ClockSetupTimeZone(opts->dataPtr, opts->interp,
	    tzObjStor);

    Tcl_DecrRefCount(tzObjStor);
    if (opts->timezoneObj == NULL) {
	return TCL_ERROR;
    }

    yyInput += len;
    return TCL_OK;
}

static int
ClockScnToken_StarDate_Proc(
    ClockFmtScnCmdArgs *opts,
    DateInfo *info,
    ClockScanToken *tok)
{
    int minLen, maxLen;
    const char *p = yyInput, *end, *s;
    int year, fractYear, fractDayDiv, fractDay;
    static const char *stardatePref = "stardate ";

    DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen);

    end = yyInput + maxLen;

    /* stardate string */
    p = TclUtfFindEqualNCInLwr(p, end, stardatePref, stardatePref + 9, &s);
    if (p >= end || p - yyInput < 9) {
	return TCL_RETURN;
    }
    /* bypass spaces */
    while (p < end && isspace(UCHAR(*p))) {
	p++;
    }
    if (p >= end) {
	return TCL_RETURN;
    }
    /* currently positive stardate only */
    if (*p == '+') {
	p++;
    }
    s = p;
    while (p < end && isdigit(UCHAR(*p))) {
	p++;
    }
    if (p >= end || p - s < 4) {
	return TCL_RETURN;
    }
    if (Clock_str2int(&year, s, p - 3, 1) != TCL_OK
	    || Clock_str2int(&fractYear, p - 3, p, 1) != TCL_OK) {
	return TCL_RETURN;
    }
    if (*p++ != '.') {
	return TCL_RETURN;
    }
    s = p;
    fractDayDiv = 1;
    while (p < end && isdigit(UCHAR(*p))) {
	fractDayDiv *= 10;
	p++;
    }
    if (Clock_str2int(&fractDay, s, p, 1) != TCL_OK) {
	return TCL_RETURN;
    }
    yyInput = p;

    /* Build a date from year and fraction. */

    yydate.year = year + RODDENBERRY;
    yydate.isBce = 0;
    yydate.gregorian = 1;

    if (IsGregorianLeapYear(&yydate)) {
	fractYear *= 366;
    } else {
	fractYear *= 365;
    }
    yydate.dayOfYear = fractYear / 1000 + 1;
    if (fractYear % 1000 >= 500) {
	yydate.dayOfYear++;
    }

    GetJulianDayFromEraYearDay(&yydate, GREGORIAN_CHANGE_DATE);

    yydate.localSeconds =
	    -210866803200LL
	    + (SECONDS_PER_DAY * yydate.julianDay)
	    + (SECONDS_PER_DAY * fractDay / fractDayDiv);

    return TCL_OK;
}

/*
 * Descriptors for the various fields in [clock scan].
 */

static const char *ScnSTokenMapIndex = "dmbyYHMSpJjCgGVazUsntQ";
static const ClockScanTokenMap ScnSTokenMap[] = {
    /* %d %e */
    {CTOKT_INT, CLF_DAYOFMONTH, 0, 1, 2, offsetof(DateInfo, date.dayOfMonth),
	NULL, NULL},
    /* %m %N */
    {CTOKT_INT, CLF_MONTH, 0, 1, 2, offsetof(DateInfo, date.month),
	NULL, NULL},
    /* %b %B %h */
    {CTOKT_PARSER, CLF_MONTH, 0, 0, 0xffff, 0,
	    ClockScnToken_Month_Proc, NULL},
    /* %y */
    {CTOKT_INT, CLF_YEAR, 0, 1, 2, offsetof(DateInfo, date.year),
	NULL, NULL},
    /* %Y */
    {CTOKT_INT, CLF_YEAR | CLF_CENTURY, 0, 4, 4, offsetof(DateInfo, date.year),
	NULL, NULL},
    /* %H %k %I %l */
    {CTOKT_INT, CLF_TIME, 0, 1, 2, offsetof(DateInfo, date.hour),
	NULL, NULL},
    /* %M */
    {CTOKT_INT, CLF_TIME, 0, 1, 2, offsetof(DateInfo, date.minutes),
	NULL, NULL},
    /* %S */
    {CTOKT_INT, CLF_TIME, 0, 1, 2, offsetof(DateInfo, date.secondOfMin),
	NULL, NULL},
    /* %p %P */
    {CTOKT_PARSER, 0, 0, 0, 0xffff, 0,
	ClockScnToken_amPmInd_Proc, NULL},
    /* %J */
    {CTOKT_WIDE, CLF_JULIANDAY | CLF_SIGNED, 0, 1, 0xffff, offsetof(DateInfo, date.julianDay),
	NULL, NULL},
    /* %j */
    {CTOKT_INT, CLF_DAYOFYEAR, 0, 1, 3, offsetof(DateInfo, date.dayOfYear),
	NULL, NULL},
    /* %C */
    {CTOKT_INT, CLF_CENTURY|CLF_ISO8601CENTURY, 0, 1, 2, offsetof(DateInfo, dateCentury),
	NULL, NULL},
    /* %g */
    {CTOKT_INT, CLF_ISO8601YEAR, 0, 2, 2, offsetof(DateInfo, date.iso8601Year),
	NULL, NULL},
    /* %G */
    {CTOKT_INT, CLF_ISO8601YEAR | CLF_ISO8601CENTURY, 0, 4, 4, offsetof(DateInfo, date.iso8601Year),
	NULL, NULL},
    /* %V */
    {CTOKT_INT, CLF_ISO8601WEEK, 0, 1, 2, offsetof(DateInfo, date.iso8601Week),
	NULL, NULL},
    /* %a %A %u %w */
    {CTOKT_PARSER, CLF_DAYOFWEEK, 0, 0, 0xffff, 0,
	ClockScnToken_DayOfWeek_Proc, NULL},
    /* %z %Z */
    {CTOKT_PARSER, CLF_OPTIONAL, 0, 0, 0xffff, 0,
	ClockScnToken_TimeZone_Proc, NULL},
    /* %U %W */
    {CTOKT_INT, CLF_OPTIONAL, 0, 1, 2, 0, /* currently no capture, parse only token */
	NULL, NULL},
    /* %s */
    {CTOKT_WIDE, CLF_POSIXSEC | CLF_SIGNED, 0, 1, 0xffff, offsetof(DateInfo, date.seconds),
	NULL, NULL},
    /* %n */
    {CTOKT_CHAR, 0, 0, 1, 1, 0, NULL, "\n"},
    /* %t */
    {CTOKT_CHAR, 0, 0, 1, 1, 0, NULL, "\t"},
    /* %Q */
    {CTOKT_PARSER, CLF_LOCALSEC, 0, 16, 30, 0,
	ClockScnToken_StarDate_Proc, NULL},
};
static const char *ScnSTokenMapAliasIndex[2] = {
    "eNBhkIlPAuwZW",
    "dmbbHHHpaaazU"
};

static const char *ScnETokenMapIndex = "EJjys";
static const ClockScanTokenMap ScnETokenMap[] = {
    /* %EE */
    {CTOKT_PARSER, 0, 0, 0, 0xffff, offsetof(DateInfo, date.year),
	ClockScnToken_LocaleERA_Proc, (void *)MCLIT_LOCALE_NUMERALS},
    /* %EJ */
    {CTOKT_PARSER, CLF_JULIANDAY | CLF_SIGNED, 0, 1, 0xffff, 0, /* calendar JDN starts at midnight */
	ClockScnToken_JDN_Proc, NULL},
    /* %Ej */
    {CTOKT_PARSER, CLF_JULIANDAY | CLF_SIGNED, 0, 1, 0xffff, (SECONDS_PER_DAY/2), /* astro JDN starts at noon */
	ClockScnToken_JDN_Proc, NULL},
    /* %Ey */
    {CTOKT_PARSER, 0, 0, 0, 0xffff, 0, /* currently no capture, parse only token */
	ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS},
    /* %Es */
    {CTOKT_WIDE, CLF_LOCALSEC | CLF_SIGNED, 0, 1, 0xffff, offsetof(DateInfo, date.localSeconds),
	NULL, NULL},
};
static const char *ScnETokenMapAliasIndex[2] = {
    "",
    ""
};

static const char *ScnOTokenMapIndex = "dmyHMSu";
static const ClockScanTokenMap ScnOTokenMap[] = {
    /* %Od %Oe */
    {CTOKT_PARSER, CLF_DAYOFMONTH, 0, 0, 0xffff, offsetof(DateInfo, date.dayOfMonth),
	ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS},
    /* %Om */
    {CTOKT_PARSER, CLF_MONTH, 0, 0, 0xffff, offsetof(DateInfo, date.month),
	ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS},
    /* %Oy */
    {CTOKT_PARSER, CLF_YEAR, 0, 0, 0xffff, offsetof(DateInfo, date.year),
	ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS},
    /* %OH %Ok %OI %Ol */
    {CTOKT_PARSER, CLF_TIME, 0, 0, 0xffff, offsetof(DateInfo, date.hour),
	ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS},
    /* %OM */
    {CTOKT_PARSER, CLF_TIME, 0, 0, 0xffff, offsetof(DateInfo, date.minutes),
	ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS},
    /* %OS */
    {CTOKT_PARSER, CLF_TIME, 0, 0, 0xffff, offsetof(DateInfo, date.secondOfMin),
	ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS},
    /* %Ou Ow */
    {CTOKT_PARSER, CLF_DAYOFWEEK, 0, 0, 0xffff, 0,
	ClockScnToken_DayOfWeek_Proc, (void *)MCLIT_LOCALE_NUMERALS},
};
static const char *ScnOTokenMapAliasIndex[2] = {
    "ekIlw",
    "dHHHu"
};

/* Token map reserved for CTOKT_SPACE */
static const ClockScanTokenMap ScnSpaceTokenMap = {
    CTOKT_SPACE, 0, 0, 1, 1, 0, NULL, NULL
};

static const ClockScanTokenMap ScnWordTokenMap = {
    CTOKT_WORD, 0, 0, 1, 1, 0, NULL, NULL
};

static inline unsigned
EstimateTokenCount(
    const char *fmt,
    const char *end)
{
    const char *p = fmt;
    unsigned tokcnt;
    /* estimate token count by % char and format length */
    tokcnt = 0;
    while (p <= end) {
	if (*p++ == '%') {
	    tokcnt++;
	    p++;
	}
    }
    p = fmt + tokcnt * 2;
    if (p < end) {
	if ((unsigned)(end - p) < tokcnt) {
	    tokcnt += (end - p);
	} else {
	    tokcnt += tokcnt;
	}
    }
    return ++tokcnt;
}

#define AllocTokenInChain(tok, chain, tokCnt, type)			 \
    if (++(tok) >= (chain) + (tokCnt)) {				 \
	chain = (type)Tcl_Realloc((char *)(chain),			 \
	    (tokCnt + CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE) * sizeof(*(tok))); \
	(tok) = (chain) + (tokCnt);					 \
	(tokCnt) += CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE;			 \
    }									 \
    memset(tok, 0, sizeof(*(tok)));

/*
 *----------------------------------------------------------------------
 */
ClockFmtScnStorage *
ClockGetOrParseScanFormat(
    Tcl_Interp *interp,		/* Tcl interpreter */
    Tcl_Obj *formatObj)		/* Format container */
{
    ClockFmtScnStorage *fss;

    fss = Tcl_GetClockFrmScnFromObj(interp, formatObj);
    if (fss == NULL) {
	return NULL;
    }

    /* if format (scnTok) already tokenized */
    if (fss->scnTok != NULL) {
	return fss;
    }

    Tcl_MutexLock(&ClockFmtMutex);

    /* first time scanning - tokenize format */
    if (fss->scnTok == NULL) {
	ClockScanToken *tok, *scnTok;
	unsigned tokCnt;
	const char *p, *e, *cp;

	e = p = HashEntry4FmtScn(fss)->key.string;
	e += strlen(p);

	/* estimate token count by % char and format length */
	fss->scnTokC = EstimateTokenCount(p, e);

	fss->scnSpaceCount = 0;

	scnTok = tok = (ClockScanToken *)Tcl_Alloc(sizeof(*tok) * fss->scnTokC);
	memset(tok, 0, sizeof(*tok));
	tokCnt = 1;
	while (p < e) {
	    switch (*p) {
	    case '%': {
		const ClockScanTokenMap *scnMap = ScnSTokenMap;
		const char *mapIndex = ScnSTokenMapIndex;
		const char **aliasIndex = ScnSTokenMapAliasIndex;

		if (p + 1 >= e) {
		    goto word_tok;
		}
		p++;
		/* try to find modifier: */
		switch (*p) {
		case '%':
		    /* begin new word token - don't join with previous word token,
		     * because current mapping should be "...%%..." -> "...%..." */
		    tok->map = &ScnWordTokenMap;
		    tok->tokWord.start = p;
		    tok->tokWord.end = p + 1;
		    AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *);
		    tokCnt++;
		    p++;
		    continue;
		case 'E':
		    scnMap = ScnETokenMap,
		    mapIndex =	ScnETokenMapIndex,
		    aliasIndex = ScnETokenMapAliasIndex;
		    p++;
		    break;
		case 'O':
		    scnMap = ScnOTokenMap,
		    mapIndex = ScnOTokenMapIndex,
		    aliasIndex = ScnOTokenMapAliasIndex;
		    p++;
		    break;
		}
		/* search direct index */
		cp = strchr(mapIndex, *p);
		if (!cp || *cp == '\0') {
		    /* search wrapper index (multiple chars for same token) */
		    cp = strchr(aliasIndex[0], *p);
		    if (!cp || *cp == '\0') {
			p--;
			if (scnMap != ScnSTokenMap) {
			    p--;
			}
			goto word_tok;
		    }
		    cp = strchr(mapIndex, aliasIndex[1][cp - aliasIndex[0]]);
		    if (!cp || *cp == '\0') { /* unexpected, but ... */
#ifdef DEBUG
			Tcl_Panic("token \"%c\" has no map in wrapper resolver", *p);
#endif
			p--;
			if (scnMap != ScnSTokenMap) {
			    p--;
			}
			goto word_tok;
		    }
		}
		tok->map = &scnMap[cp - mapIndex];
		tok->tokWord.start = p;

		/* calculate look ahead value by standing together tokens */
		if (tok > scnTok) {
		    ClockScanToken *prevTok = tok - 1;

		    while (prevTok >= scnTok) {
			if (prevTok->map->type != tok->map->type) {
			    break;
			}
			prevTok->lookAhMin += tok->map->minSize;
			prevTok->lookAhMax += tok->map->maxSize;
			prevTok->lookAhTok++;
			prevTok--;
		    }
		}

		/* increase space count used in format */
		if (tok->map->type == CTOKT_CHAR
			&& isspace(UCHAR(*((char *)tok->map->data)))) {
		    fss->scnSpaceCount++;
		}

		/* next token */
		AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *);
		tokCnt++;
		p++;
		continue;
	    }
	    default:
		if (isspace(UCHAR(*p))) {
		    tok->map = &ScnSpaceTokenMap;
		    tok->tokWord.start = p++;
		    while (p < e && isspace(UCHAR(*p))) {
			p++;
		    }
		    tok->tokWord.end = p;
		    /* increase space count used in format */
		    fss->scnSpaceCount++;
		    /* next token */
		    AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *);
		    tokCnt++;
		    continue;
		}
	      word_tok:
		{
		/* try continue with previous word token */
		ClockScanToken *wordTok = tok - 1;

		if (wordTok < scnTok || wordTok->map != &ScnWordTokenMap) {
		    /* start with new word token */
		    wordTok = tok;
		    wordTok->tokWord.start = p;
		    wordTok->map = &ScnWordTokenMap;
		}

		do {
		    if (isspace(UCHAR(*p))) {
			fss->scnSpaceCount++;
		    }
		    p = Tcl_UtfNext(p);
		} while (p < e && *p != '%');
		wordTok->tokWord.end = p;

		if (wordTok == tok) {
		    AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *);
		    tokCnt++;
		}
		}
		break;
	    }
	}

	/* calculate end distance value for each tokens */
	if (tok > scnTok) {
	    unsigned endDist = 0;
	    ClockScanToken *prevTok = tok - 1;

	    while (prevTok >= scnTok) {
		prevTok->endDistance = endDist;
		if (prevTok->map->type != CTOKT_WORD) {
		    endDist += prevTok->map->minSize;
		} else {
		    endDist += prevTok->tokWord.end - prevTok->tokWord.start;
		}
		prevTok--;
	    }
	}

	/* correct count of real used tokens and free mem if desired
	 * (1 is acceptable delta to prevent memory fragmentation) */
	if (fss->scnTokC > tokCnt + (CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE / 2)) {
	    if ((tok = (ClockScanToken *)
		    Tcl_AttemptRealloc(scnTok, tokCnt * sizeof(*tok))) != NULL) {
		scnTok = tok;
	    }
	}

	/* now we're ready - assign now to storage (note the threaded race condition) */
	fss->scnTok = scnTok;
	fss->scnTokC = tokCnt;
    }

    Tcl_MutexUnlock(&ClockFmtMutex);
    return fss;
}

/*
 *----------------------------------------------------------------------
 */
int
ClockScan(
    DateInfo *info,		/* Date fields used for parsing & converting */
    Tcl_Obj *strObj,		/* String containing the time to scan */
    ClockFmtScnCmdArgs *opts)	/* Command options */
{
    ClockClientData *dataPtr = opts->dataPtr;
    ClockFmtScnStorage *fss;
    ClockScanToken *tok;
    const ClockScanTokenMap *map;
    const char *p, *x, *end;
    unsigned short flags = 0;
    int ret = TCL_ERROR;

    /* get localized format */
    if (ClockLocalizeFormat(opts) == NULL) {
	return TCL_ERROR;
    }

    if (!(fss = ClockGetOrParseScanFormat(opts->interp, opts->formatObj))
	    || !(tok = fss->scnTok)) {
	return TCL_ERROR;
    }

    /* prepare parsing */

    yyMeridian = MER24;

    p = TclGetString(strObj);
    end = p + strObj->length;
    /* in strict mode - bypass spaces at begin / end only (not between tokens) */
    if (opts->flags & CLF_STRICT) {
	while (p < end && isspace(UCHAR(*p))) {
	    p++;
	}
    }
    yyInput = p;
    /* look ahead to count spaces (bypass it by count length and distances) */
    x = end;
    while (p < end) {
	if (isspace(UCHAR(*p))) {
	    x = ++p;	/* after first space in space block */
	    yySpaceCount++;
	    while (p < end && isspace(UCHAR(*p))) {
		p++;
		yySpaceCount++;
	    }
	    continue;
	}
	x = end;
	p++;
    }
    /* ignore more as 1 space at end */
    yySpaceCount -= (end - x);
    end = x;
    /* ignore mandatory spaces used in format */
    yySpaceCount -= fss->scnSpaceCount;
    if (yySpaceCount < 0) {
	yySpaceCount = 0;
    }
    info->dateStart = p = yyInput;
    info->dateEnd = end;

    /* parse string */
    for (; tok->map != NULL; tok++) {
	map = tok->map;
	/* bypass spaces at begin of input before parsing each token */
	if (!(opts->flags & CLF_STRICT)
		&& (map->type != CTOKT_SPACE
		&& map->type != CTOKT_WORD
		&& map->type != CTOKT_CHAR)) {
	    while (p < end && isspace(UCHAR(*p))) {
		yySpaceCount--;
		p++;
	    }
	}
	yyInput = p;
	/* end of input string */
	if (p >= end) {
	    break;
	}
	switch (map->type) {
	case CTOKT_INT:
	case CTOKT_WIDE: {
	    int minLen, size;
	    int sign = 1;

	    if (map->flags & CLF_SIGNED) {
		if (*p == '+') {
		    yyInput = ++p;
		} else if (*p == '-') {
		    yyInput = ++p;
		    sign = -1;
		}
	    }

	    DetermineGreedySearchLen(opts, info, tok, &minLen, &size);

	    if (size < map->minSize) {
		/* missing input -> error */
		if ((map->flags & CLF_OPTIONAL)) {
		    continue;
		}
		goto not_match;
	    }
	    /* string 2 number, put number into info structure by offset */
	    if (map->offs) {
		p = yyInput;
		x = p + size;
		if (map->type == CTOKT_INT) {
		    if (size <= 10) {
			Clock_str2int_no(IntFieldAt(info, map->offs),
				p, x, sign);
		    } else if (Clock_str2int(
			    IntFieldAt(info, map->offs), p, x, sign) != TCL_OK) {
			goto overflow;
		    }
		    p = x;
		} else {
		    if (size <= 18) {
			Clock_str2wideInt_no(
				WideFieldAt(info, map->offs), p, x, sign);
		    } else if (Clock_str2wideInt(
			    WideFieldAt(info, map->offs), p, x, sign) != TCL_OK) {
			goto overflow;
		    }
		    p = x;
		}
		flags = (flags & ~map->clearFlags) | map->flags;
	    }
	    break;
	}
	case CTOKT_PARSER:
	    switch (map->parser(opts, info, tok)) {
	    case TCL_OK:
		break;
	    case TCL_RETURN:
		if ((map->flags & CLF_OPTIONAL)) {
		    yyInput = p;
		    continue;
		}
		goto not_match;
	    default:
		goto done;
	    }
	    /* decrement count for possible spaces in match */
	    while (p < yyInput) {
		if (isspace(UCHAR(*p))) {
		    yySpaceCount--;
		}
		p++;
	    }
	    p = yyInput;
	    flags = (flags & ~map->clearFlags) | map->flags;
	    break;
	case CTOKT_SPACE:
	    /* at least one space */
	    if (!isspace(UCHAR(*p))) {
		/* unmatched -> error */
		goto not_match;
	    }
	    /* don't decrement yySpaceCount by regular (first expected space),
	     * already considered above with fss->scnSpaceCount */;
	    p++;
	    while (p < end && isspace(UCHAR(*p))) {
		yySpaceCount--;
		p++;
	    }
	    break;
	case CTOKT_WORD:
	    x = FindWordEnd(tok, p, end);
	    if (!x) {
		/* no match -> error */
		goto not_match;
	    }
	    p = x;
	    break;
	case CTOKT_CHAR:
	    x = (char *)map->data;
	    if (*x != *p) {
		/* no match -> error */
		goto not_match;
	    }
	    if (isspace(UCHAR(*x))) {
		yySpaceCount--;
	    }
	    p++;
	    break;
	}
    }
    /* check end was reached */
    if (p < end) {
	/* in non-strict mode bypass spaces at end of input */
	if (!(opts->flags & CLF_STRICT) && isspace(UCHAR(*p))) {
	    p++;
	    while (p < end && isspace(UCHAR(*p))) {
		p++;
	    }
	}
	/* something after last token - wrong format */
	if (p < end) {
	    goto not_match;
	}
    }
    /* end of string, check only optional tokens at end, otherwise - not match */
    while (tok->map != NULL) {
	if (!(opts->flags & CLF_STRICT) && (tok->map->type == CTOKT_SPACE)) {
	    tok++;
	    if (tok->map == NULL) {
		/* no tokens anymore - trailing spaces are mandatory */
		goto not_match;
	    }
	}
	if (!(tok->map->flags & CLF_OPTIONAL)) {
	    goto not_match;
	}
	tok++;
    }

    /*
     * Invalidate result
     */
    flags |= info->flags;

    /* seconds token (%s) take precedence over all other tokens */
    if ((opts->flags & CLF_EXTENDED) || !(flags & CLF_POSIXSEC)) {
	if (flags & CLF_DATE) {

	    if (!(flags & CLF_JULIANDAY)) {
		info->flags |= CLF_ASSEMBLE_SECONDS|CLF_ASSEMBLE_JULIANDAY;

		/* dd precedence below ddd */
		switch (flags & (CLF_MONTH|CLF_DAYOFYEAR|CLF_DAYOFMONTH)) {
		case (CLF_DAYOFYEAR | CLF_DAYOFMONTH):
		    /* miss month: ddd over dd (without month) */
		    flags &= ~CLF_DAYOFMONTH;
		    /* fallthrough */
		case CLF_DAYOFYEAR:
		    /* ddd over naked weekday */
		    if (!(flags & CLF_ISO8601YEAR)) {
			flags &= ~CLF_ISO8601WEEK;
		    }
		    break;
		case CLF_MONTH | CLF_DAYOFYEAR | CLF_DAYOFMONTH:
		    /* both available: mmdd over ddd */
		case CLF_MONTH | CLF_DAYOFMONTH:
		case CLF_DAYOFMONTH:
		    /* mmdd / dd over naked weekday */
		    if (!(flags & CLF_ISO8601YEAR)) {
			flags &= ~CLF_ISO8601WEEK;
		    }
		    break;
		    /* neither mmdd nor ddd available */
		case 0:
		    /* but we have day of the week, which can be used */
		    if (flags & CLF_DAYOFWEEK) {
			/* prefer week based calculation of julianday */
			flags |= CLF_ISO8601WEEK;
		    }
		}

		/* YearWeekDay below YearMonthDay */
		if ((flags & CLF_ISO8601WEEK)
			&& ((flags & (CLF_YEAR | CLF_DAYOFYEAR)) == (CLF_YEAR | CLF_DAYOFYEAR)
			|| (flags & (CLF_YEAR | CLF_DAYOFMONTH | CLF_MONTH)) == (
				CLF_YEAR | CLF_DAYOFMONTH | CLF_MONTH))) {
		    /* yy precedence below yyyy */
		    if (!(flags & CLF_ISO8601CENTURY) && (flags & CLF_CENTURY)) {
			/* normally precedence of ISO is higher, but no century - so put it down */
			flags &= ~CLF_ISO8601WEEK;
		    } else if (!(flags & CLF_ISO8601YEAR)) {
			/* yymmdd or yyddd over naked weekday */
			flags &= ~CLF_ISO8601WEEK;
		    }
		}

		if (flags & CLF_YEAR) {
		    if (yyYear < 100) {
			if (!(flags & CLF_CENTURY)) {
			    if (yyYear >= dataPtr->yearOfCenturySwitch) {
				yyYear -= 100;
			    }
			    yyYear += dataPtr->currentYearCentury;
			} else {
			    yyYear += info->dateCentury * 100;
			}
		    }
		}
		if (flags & (CLF_ISO8601WEEK | CLF_ISO8601YEAR)) {
		    if ((flags & (CLF_ISO8601YEAR | CLF_YEAR)) == CLF_YEAR) {
			/* for calculations expected iso year */
			info->date.iso8601Year = yyYear;
		    } else if (info->date.iso8601Year < 100) {
			if (!(flags & CLF_ISO8601CENTURY)) {
			    if (info->date.iso8601Year >= dataPtr->yearOfCenturySwitch) {
				info->date.iso8601Year -= 100;
			    }
			    info->date.iso8601Year += dataPtr->currentYearCentury;
			} else {
			    info->date.iso8601Year += info->dateCentury * 100;
			}
		    }
		    if ((flags & (CLF_ISO8601YEAR | CLF_YEAR)) == CLF_ISO8601YEAR) {
			/* for calculations expected year (e. g. CLF_ISO8601WEEK not set) */
			yyYear = info->date.iso8601Year;
		    }
		}
	    }
	}

	/* if no time - reset time */
	if (!(flags & (CLF_TIME | CLF_LOCALSEC | CLF_POSIXSEC))) {
	    info->flags |= CLF_ASSEMBLE_SECONDS;
	    yydate.localSeconds = 0;
	}

	if (flags & CLF_TIME) {
	    info->flags |= CLF_ASSEMBLE_SECONDS;
	    yySecondOfDay = ToSeconds(yyHour, yyMinutes,
		    yySeconds, yyMeridian);
	} else if (!(flags & (CLF_LOCALSEC | CLF_POSIXSEC))) {
	    info->flags |= CLF_ASSEMBLE_SECONDS;
	    yySecondOfDay = yydate.localSeconds % SECONDS_PER_DAY;
	}
    }

    /* tell caller which flags were set */
    info->flags |= flags;

    ret = TCL_OK;
  done:
    return ret;

    /* Error case reporting. */

  overflow:
    Tcl_SetObjResult(opts->interp, Tcl_NewStringObj(
	    "integer value too large to represent", TCL_AUTO_LENGTH));
    Tcl_SetErrorCode(opts->interp, "CLOCK", "dateTooLarge", (char *)NULL);
    goto done;

  not_match:
#if 1
    Tcl_SetObjResult(opts->interp, Tcl_NewStringObj(
	    "input string does not match supplied format", TCL_AUTO_LENGTH));
#else
    /* to debug where exactly scan breaks */
    Tcl_SetObjResult(opts->interp, Tcl_ObjPrintf(
	    "input string \"%s\" does not match supplied format \"%s\","
	    " locale \"%s\" - token \"%s\"",
	    info->dateStart, HashEntry4FmtScn(fss)->key.string,
	    TclGetString(opts->localeObj),
	    tok && tok->tokWord.start ? tok->tokWord.start : "NULL"));
#endif
    Tcl_SetErrorCode(opts->interp, "CLOCK", "badInputString", (char *)NULL);
    goto done;
}

#define FrmResultIsAllocated(dateFmt) \
    (dateFmt->resEnd - dateFmt->resMem > MIN_FMT_RESULT_BLOCK_ALLOC)

static inline int
FrmResultAllocate(
    DateFormat *dateFmt,
    int len)
{
    int needed = dateFmt->output + len - dateFmt->resEnd;
    if (needed >= 0) {		/* >= 0 - regards NTS zero */
	int newsize = dateFmt->resEnd - dateFmt->resMem
		+ needed + MIN_FMT_RESULT_BLOCK_ALLOC * 2;
	char *newRes;
	/* differentiate between stack and memory */
	if (!FrmResultIsAllocated(dateFmt)) {
	    newRes = (char *)Tcl_AttemptAlloc(newsize);
	    if (newRes == NULL) {
		return TCL_ERROR;
	    }
	    memcpy(newRes, dateFmt->resMem, dateFmt->output - dateFmt->resMem);
	} else {
	    newRes = (char *)Tcl_AttemptRealloc(dateFmt->resMem, newsize);
	    if (newRes == NULL) {
		return TCL_ERROR;
	    }
	}
	dateFmt->output = newRes + (dateFmt->output - dateFmt->resMem);
	dateFmt->resMem = newRes;
	dateFmt->resEnd = newRes + newsize;
    }
    return TCL_OK;
}

static int
ClockFmtToken_HourAMPM_Proc(
    TCL_UNUSED(ClockFmtScnCmdArgs *),
    TCL_UNUSED(DateFormat *),
    TCL_UNUSED(ClockFormatToken *),
    int *val)
{
    *val = ((*val + SECONDS_PER_DAY - 3600) / 3600) % 12 + 1;
    return TCL_OK;
}

static int
ClockFmtToken_AMPM_Proc(
    ClockFmtScnCmdArgs *opts,
    DateFormat *dateFmt,
    ClockFormatToken *tok,
    int *val)
{
    Tcl_Obj *mcObj;
    const char *s;
    Tcl_Size len;

    if (*val < (SECONDS_PER_DAY / 2)) {
	mcObj = ClockMCGet(opts, MCLIT_AM);
    } else {
	mcObj = ClockMCGet(opts, MCLIT_PM);
    }
    if (mcObj == NULL) {
	return TCL_ERROR;
    }
    s = TclGetStringFromObj(mcObj, &len);
    if (FrmResultAllocate(dateFmt, len) != TCL_OK) {
	return TCL_ERROR;
    }
    memcpy(dateFmt->output, s, len + 1);
    if (*tok->tokWord.start == 'p') {
	len = Tcl_UtfToUpper(dateFmt->output);
    }
    dateFmt->output += len;

    return TCL_OK;
}

static int
ClockFmtToken_StarDate_Proc(
    TCL_UNUSED(ClockFmtScnCmdArgs *),
    DateFormat *dateFmt,
    TCL_UNUSED(ClockFormatToken *),
    TCL_UNUSED(int *))
{
    int fractYear;
    /* Get day of year, zero based */
    int v = dateFmt->date.dayOfYear - 1;

    /* Convert day of year to a fractional year */
    if (IsGregorianLeapYear(&dateFmt->date)) {
	fractYear = 1000 * v / 366;
    } else {
	fractYear = 1000 * v / 365;
    }

    /* Put together the StarDate as "Stardate %02d%03d.%1d" */
    if (FrmResultAllocate(dateFmt, 30) != TCL_OK) {
	return TCL_ERROR;
    }
    memcpy(dateFmt->output, "Stardate ", 9);
    dateFmt->output += 9;
    dateFmt->output = Clock_itoaw(dateFmt->output,
	    dateFmt->date.year - RODDENBERRY, '0', 2);
    dateFmt->output = Clock_itoaw(dateFmt->output,
	    fractYear, '0', 3);
    *dateFmt->output++ = '.';
    /* be sure positive after decimal point (note: clock-value can be negative) */
    v = dateFmt->date.secondOfDay / (SECONDS_PER_DAY / 10);
    if (v < 0) {
	v = 10 + v;
    }
    dateFmt->output = Clock_itoaw(dateFmt->output, v, '0', 1);
    return TCL_OK;
}
static int
ClockFmtToken_WeekOfYear_Proc(
    TCL_UNUSED(ClockFmtScnCmdArgs *),
    DateFormat *dateFmt,
    ClockFormatToken *tok,
    int *val)
{
    int dow = dateFmt->date.dayOfWeek;

    if (*tok->tokWord.start == 'U') {
	if (dow == 7) {
	    dow = 0;
	}
	dow++;
    }
    *val = (dateFmt->date.dayOfYear - dow + 7) / 7;
    return TCL_OK;
}
static int
ClockFmtToken_JDN_Proc(
    TCL_UNUSED(ClockFmtScnCmdArgs *),
    DateFormat *dateFmt,
    ClockFormatToken *tok,
    TCL_UNUSED(int *))
{
    Tcl_WideInt intJD = dateFmt->date.julianDay;
    int fractJD;

    /* Convert to JDN parts (regarding start offset) and time fraction */
    fractJD = dateFmt->date.secondOfDay
	    - (int)tok->map->offs;	/* 0 for calendar or 43200 for astro JD */
    if (fractJD < 0) {
	intJD--;
	fractJD += SECONDS_PER_DAY;
    }
    if (fractJD && intJD < 0) {		/* avoid jump over 0, by negative JD's */
	intJD++;
	if (intJD == 0) {
	    /* -0.0 / -0.9 has zero integer part, so append "-" extra */
	    if (FrmResultAllocate(dateFmt, 1) != TCL_OK) {
		return TCL_ERROR;
	    }
	    *dateFmt->output++ = '-';
	}
	/* and inverse seconds of day, -0(75) -> -0.25 as float */
	fractJD = SECONDS_PER_DAY - fractJD;
    }

    /* 21 is max width of (negative) wide-int (rather smaller, but anyway a time fraction below) */
    if (FrmResultAllocate(dateFmt, 21) != TCL_OK) {
	return TCL_ERROR;
    }
    dateFmt->output = Clock_witoaw(dateFmt->output, intJD, '0', 1);
    /* simplest cases .0 and .5 */
    if (!fractJD || fractJD == (SECONDS_PER_DAY / 2)) {
	/* point + 0 or 5 */
	if (FrmResultAllocate(dateFmt, 1 + 1) != TCL_OK) {
	    return TCL_ERROR;
	}
	*dateFmt->output++ = '.';
	*dateFmt->output++ = !fractJD ? '0' : '5';
	*dateFmt->output = '\0';
	return TCL_OK;
    } else {
	/* wrap the time fraction */
#define JDN_MAX_PRECISION 8
#define JDN_MAX_PRECBOUND 100000000 /* 10**JDN_MAX_PRECISION */
	char *p;

	/* to float (part after floating point, + 0.5 to round it up) */
	fractJD = (int)(
		(double)fractJD * JDN_MAX_PRECBOUND / SECONDS_PER_DAY + 0.5);

	/* point + integer (as time fraction after floating point) */
	if (FrmResultAllocate(dateFmt, 1 + JDN_MAX_PRECISION) != TCL_OK) {
	    return TCL_ERROR;
	}
	*dateFmt->output++ = '.';
	p = Clock_itoaw(dateFmt->output, fractJD, '0', JDN_MAX_PRECISION);

	/* remove trailing zero's */
	dateFmt->output++;
	while (p > dateFmt->output && p[-1] == '0') {
	    p--;
	}
	*p = '\0';
	dateFmt->output = p;
    }
    return TCL_OK;
}
static int
ClockFmtToken_TimeZone_Proc(
    ClockFmtScnCmdArgs *opts,
    DateFormat *dateFmt,
    ClockFormatToken *tok,
    TCL_UNUSED(int *))
{
    if (*tok->tokWord.start == 'z') {
	int z = dateFmt->date.tzOffset;
	char sign = '+';

	if (z < 0) {
	    z = -z;
	    sign = '-';
	}
	if (FrmResultAllocate(dateFmt, 7) != TCL_OK) {
	    return TCL_ERROR;
	}
	*dateFmt->output++ = sign;
	dateFmt->output = Clock_itoaw(dateFmt->output, z / 3600, '0', 2);
	z %= 3600;
	dateFmt->output = Clock_itoaw(dateFmt->output, z / 60, '0', 2);
	z %= 60;
	if (z != 0) {
	    dateFmt->output = Clock_itoaw(dateFmt->output, z, '0', 2);
	}
    } else {
	Tcl_Obj * objPtr;
	const char *s;
	Tcl_Size len;

	/* convert seconds to local seconds to obtain tzName object */
	if (ConvertUTCToLocal(opts->dataPtr, opts->interp,
		&dateFmt->date, opts->timezoneObj,
		GREGORIAN_CHANGE_DATE) != TCL_OK) {
	    return TCL_ERROR;
	}
	objPtr = dateFmt->date.tzName;
	s = TclGetStringFromObj(objPtr, &len);
	if (FrmResultAllocate(dateFmt, len) != TCL_OK) {
	    return TCL_ERROR;
	}
	memcpy(dateFmt->output, s, len + 1);
	dateFmt->output += len;
    }
    return TCL_OK;
}

static int
ClockFmtToken_LocaleERA_Proc(
    ClockFmtScnCmdArgs *opts,
    DateFormat *dateFmt,
    TCL_UNUSED(ClockFormatToken *),
    TCL_UNUSED(int *))
{
    Tcl_Obj *mcObj;
    const char *s;
    Tcl_Size len;

    if (dateFmt->date.isBce) {
	mcObj = ClockMCGet(opts, MCLIT_BCE);
    } else {
	mcObj = ClockMCGet(opts, MCLIT_CE);
    }
    if (mcObj == NULL) {
	return TCL_ERROR;
    }
    s = TclGetStringFromObj(mcObj, &len);
    if (FrmResultAllocate(dateFmt, len) != TCL_OK) {
	return TCL_ERROR;
    }

    memcpy(dateFmt->output, s, len + 1);
    dateFmt->output += len;
    return TCL_OK;
}

static int
ClockFmtToken_LocaleERAYear_Proc(
    ClockFmtScnCmdArgs *opts,
    DateFormat *dateFmt,
    ClockFormatToken *tok,
    int *val)
{
    Tcl_Size rowc;
    Tcl_Obj **rowv;

    if (dateFmt->localeEra == NULL) {
	Tcl_Obj *mcObj = ClockMCGet(opts, MCLIT_LOCALE_ERAS);
	if (mcObj == NULL) {
	    return TCL_ERROR;
	}
	if (TclListObjGetElements(opts->interp, mcObj, &rowc, &rowv) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (rowc != 0) {
	    dateFmt->localeEra = LookupLastTransition(opts->interp,
		    dateFmt->date.localSeconds, rowc, rowv, NULL);
	}
	if (dateFmt->localeEra == NULL) {
	    dateFmt->localeEra = (Tcl_Obj*)1;
	}
    }

    /* if no LOCALE_ERAS in catalog or era not found */
    if (dateFmt->localeEra == (Tcl_Obj*)1) {
	if (FrmResultAllocate(dateFmt, 11) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (*tok->tokWord.start == 'C') {	/* %EC */
	    *val = dateFmt->date.year / 100;
	    dateFmt->output = Clock_itoaw(dateFmt->output, *val, '0', 2);
	} else {				/* %Ey */
	    *val = dateFmt->date.year % 100;
	    dateFmt->output = Clock_itoaw(dateFmt->output, *val, '0', 2);
	}
    } else {
	Tcl_Obj *objPtr;
	const char *s;
	Tcl_Size len;

	if (*tok->tokWord.start == 'C') {	/* %EC */
	    if (Tcl_ListObjIndex(opts->interp, dateFmt->localeEra, 1,
		    &objPtr) != TCL_OK) {
		return TCL_ERROR;
	    }
	} else {				/* %Ey */
	    if (Tcl_ListObjIndex(opts->interp, dateFmt->localeEra, 2,
		    &objPtr) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (Tcl_GetIntFromObj(opts->interp, objPtr, val) != TCL_OK) {
		return TCL_ERROR;
	    }
	    *val = dateFmt->date.year - *val;
	    /* if year in locale numerals */
	    if (*val >= 0 && *val < 100) {
		/* year as integer */
		Tcl_Obj * mcObj = ClockMCGet(opts, MCLIT_LOCALE_NUMERALS);
		if (mcObj == NULL) {
		    return TCL_ERROR;
		}
		if (Tcl_ListObjIndex(opts->interp, mcObj, *val, &objPtr) != TCL_OK) {
		    return TCL_ERROR;
		}
	    } else {
		/* year as integer */
		if (FrmResultAllocate(dateFmt, 11) != TCL_OK) {
		    return TCL_ERROR;
		}
		dateFmt->output = Clock_itoaw(dateFmt->output, *val, '0', 2);
		return TCL_OK;
	    }
	}
	s = TclGetStringFromObj(objPtr, &len);
	if (FrmResultAllocate(dateFmt, len) != TCL_OK) {
	    return TCL_ERROR;
	}
	memcpy(dateFmt->output, s, len + 1);
	dateFmt->output += len;
    }
    return TCL_OK;
}

/*
 * Descriptors for the various fields in [clock format].
 */

static const char *FmtSTokenMapIndex =
    "demNbByYCHMSIklpaAuwUVzgGjJsntQ";
static const ClockFormatTokenMap FmtSTokenMap[] = {
    /* %d */
    {CTOKT_INT, "0", 2, 0, 0, 0, offsetof(DateFormat, date.dayOfMonth), NULL, NULL},
    /* %e */
    {CTOKT_INT, " ", 2, 0, 0, 0, offsetof(DateFormat, date.dayOfMonth), NULL, NULL},
    /* %m */
    {CTOKT_INT, "0", 2, 0, 0, 0, offsetof(DateFormat, date.month), NULL, NULL},
    /* %N */
    {CTOKT_INT, " ", 2, 0, 0, 0, offsetof(DateFormat, date.month), NULL, NULL},
    /* %b %h */
    {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX | CLFMT_DECR, 0, 12, offsetof(DateFormat, date.month),
	NULL, (void *)MCLIT_MONTHS_ABBREV},
    /* %B */
    {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX | CLFMT_DECR, 0, 12, offsetof(DateFormat, date.month),
	NULL, (void *)MCLIT_MONTHS_FULL},
    /* %y */
    {CTOKT_INT, "0", 2, 0, 0, 100, offsetof(DateFormat, date.year), NULL, NULL},
    /* %Y */
    {CTOKT_INT, "0", 4, 0, 0, 0, offsetof(DateFormat, date.year), NULL, NULL},
    /* %C */
    {CTOKT_INT, "0", 2, 0, 100, 0, offsetof(DateFormat, date.year), NULL, NULL},
    /* %H */
    {CTOKT_INT, "0", 2, 0, 3600, 24, offsetof(DateFormat, date.secondOfDay), NULL, NULL},
    /* %M */
    {CTOKT_INT, "0", 2, 0, 60, 60, offsetof(DateFormat, date.secondOfDay), NULL, NULL},
    /* %S */
    {CTOKT_INT, "0", 2, 0, 0, 60, offsetof(DateFormat, date.secondOfDay), NULL, NULL},
    /* %I */
    {CTOKT_INT, "0", 2, CLFMT_CALC, 0, 0, offsetof(DateFormat, date.secondOfDay),
	ClockFmtToken_HourAMPM_Proc, NULL},
    /* %k */
    {CTOKT_INT, " ", 2, 0, 3600, 24, offsetof(DateFormat, date.secondOfDay), NULL, NULL},
    /* %l */
    {CTOKT_INT, " ", 2, CLFMT_CALC, 0, 0, offsetof(DateFormat, date.secondOfDay),
	ClockFmtToken_HourAMPM_Proc, NULL},
    /* %p %P */
    {CTOKT_INT, NULL, 0, 0, 0, 0, offsetof(DateFormat, date.secondOfDay),
	ClockFmtToken_AMPM_Proc, NULL},
    /* %a */
    {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 7, offsetof(DateFormat, date.dayOfWeek),
	NULL, (void *)MCLIT_DAYS_OF_WEEK_ABBREV},
    /* %A */
    {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 7, offsetof(DateFormat, date.dayOfWeek),
	NULL, (void *)MCLIT_DAYS_OF_WEEK_FULL},
    /* %u */
    {CTOKT_INT, " ", 1, 0, 0, 0, offsetof(DateFormat, date.dayOfWeek), NULL, NULL},
    /* %w */
    {CTOKT_INT, " ", 1, 0, 0, 7, offsetof(DateFormat, date.dayOfWeek), NULL, NULL},
    /* %U %W */
    {CTOKT_INT, "0", 2, CLFMT_CALC, 0, 0, offsetof(DateFormat, date.dayOfYear),
	ClockFmtToken_WeekOfYear_Proc, NULL},
    /* %V */
    {CTOKT_INT, "0", 2, 0, 0, 0, offsetof(DateFormat, date.iso8601Week), NULL, NULL},
    /* %z %Z */
    {CFMTT_PROC, NULL, 0, 0, 0, 0, 0,
	ClockFmtToken_TimeZone_Proc, NULL},
    /* %g */
    {CTOKT_INT, "0", 2, 0, 0, 100, offsetof(DateFormat, date.iso8601Year), NULL, NULL},
    /* %G */
    {CTOKT_INT, "0", 4, 0, 0, 0, offsetof(DateFormat, date.iso8601Year), NULL, NULL},
    /* %j */
    {CTOKT_INT, "0", 3, 0, 0, 0, offsetof(DateFormat, date.dayOfYear), NULL, NULL},
    /* %J */
    {CTOKT_WIDE, "0", 7, 0, 0, 0, offsetof(DateFormat, date.julianDay), NULL, NULL},
    /* %s */
    {CTOKT_WIDE, "0", 1, 0, 0, 0, offsetof(DateFormat, date.seconds), NULL, NULL},
    /* %n */
    {CTOKT_CHAR, "\n", 0, 0, 0, 0, 0, NULL, NULL},
    /* %t */
    {CTOKT_CHAR, "\t", 0, 0, 0, 0, 0, NULL, NULL},
    /* %Q */
    {CFMTT_PROC, NULL, 0, 0, 0, 0, 0,
	ClockFmtToken_StarDate_Proc, NULL},
};
static const char *FmtSTokenMapAliasIndex[2] = {
    "hPWZ",
    "bpUz"
};

static const char *FmtETokenMapIndex = "EJjys";
static const ClockFormatTokenMap FmtETokenMap[] = {
    /* %EE */
    {CFMTT_PROC, NULL, 0, 0, 0, 0, 0,
	ClockFmtToken_LocaleERA_Proc, NULL},
    /* %EJ */
    {CFMTT_PROC, NULL, 0, 0, 0, 0, 0, /* calendar JDN starts at midnight */
	ClockFmtToken_JDN_Proc, NULL},
    /* %Ej */
    {CFMTT_PROC, NULL, 0, 0, 0, 0, (SECONDS_PER_DAY/2), /* astro JDN starts at noon */
	ClockFmtToken_JDN_Proc, NULL},
    /* %Ey %EC */
    {CTOKT_INT, NULL, 0, 0, 0, 0, offsetof(DateFormat, date.year),
	ClockFmtToken_LocaleERAYear_Proc, NULL},
    /* %Es */
    {CTOKT_WIDE, "0", 1, 0, 0, 0, offsetof(DateFormat, date.localSeconds), NULL, NULL},
};
static const char *FmtETokenMapAliasIndex[2] = {
    "C",
    "y"
};

static const char *FmtOTokenMapIndex = "dmyHIMSuw";
static const ClockFormatTokenMap FmtOTokenMap[] = {
    /* %Od %Oe */
    {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, offsetof(DateFormat, date.dayOfMonth),
	NULL, (void *)MCLIT_LOCALE_NUMERALS},
    /* %Om */
    {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, offsetof(DateFormat, date.month),
	NULL, (void *)MCLIT_LOCALE_NUMERALS},
    /* %Oy */
    {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, offsetof(DateFormat, date.year),
	NULL, (void *)MCLIT_LOCALE_NUMERALS},
    /* %OH %Ok */
    {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 3600, 24, offsetof(DateFormat, date.secondOfDay),
	NULL, (void *)MCLIT_LOCALE_NUMERALS},
    /* %OI %Ol */
    {CTOKT_INT, NULL, 0, CLFMT_CALC | CLFMT_LOCALE_INDX, 0, 0, offsetof(DateFormat, date.secondOfDay),
	ClockFmtToken_HourAMPM_Proc, (void *)MCLIT_LOCALE_NUMERALS},
    /* %OM */
    {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 60, 60, offsetof(DateFormat, date.secondOfDay),
	NULL, (void *)MCLIT_LOCALE_NUMERALS},
    /* %OS */
    {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 60, offsetof(DateFormat, date.secondOfDay),
	NULL, (void *)MCLIT_LOCALE_NUMERALS},
    /* %Ou */
    {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, offsetof(DateFormat, date.dayOfWeek),
	NULL, (void *)MCLIT_LOCALE_NUMERALS},
    /* %Ow */
    {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 7, offsetof(DateFormat, date.dayOfWeek),
	NULL, (void *)MCLIT_LOCALE_NUMERALS},
};
static const char *FmtOTokenMapAliasIndex[2] = {
    "ekl",
    "dHI"
};

static const ClockFormatTokenMap FmtWordTokenMap = {
    CTOKT_WORD, NULL, 0, 0, 0, 0, 0, NULL, NULL
};

/*
 *----------------------------------------------------------------------
 */
ClockFmtScnStorage *
ClockGetOrParseFmtFormat(
    Tcl_Interp *interp,		/* Tcl interpreter */
    Tcl_Obj *formatObj)		/* Format container */
{
    ClockFmtScnStorage *fss;

    fss = Tcl_GetClockFrmScnFromObj(interp, formatObj);
    if (fss == NULL) {
	return NULL;
    }

    /* if format (fmtTok) already tokenized */
    if (fss->fmtTok != NULL) {
	return fss;
    }

    Tcl_MutexLock(&ClockFmtMutex);

    /* first time formatting - tokenize format */
    if (fss->fmtTok == NULL) {
	ClockFormatToken *tok, *fmtTok;
	unsigned tokCnt;
	const char *p, *e, *cp;

	e = p = HashEntry4FmtScn(fss)->key.string;
	e += strlen(p);

	/* estimate token count by % char and format length */
	fss->fmtTokC = EstimateTokenCount(p, e);

	fmtTok = tok = (ClockFormatToken *)Tcl_Alloc(sizeof(*tok) * fss->fmtTokC);
	memset(tok, 0, sizeof(*tok));
	tokCnt = 1;
	while (p < e) {
	    switch (*p) {
	    case '%': {
		const ClockFormatTokenMap *fmtMap = FmtSTokenMap;
		const char *mapIndex =	FmtSTokenMapIndex;
		const char **aliasIndex = FmtSTokenMapAliasIndex;

		if (p + 1 >= e) {
		    goto word_tok;
		}
		p++;
		/* try to find modifier: */
		switch (*p) {
		case '%':
		    /* begin new word token - don't join with previous word token,
		     * because current mapping should be "...%%..." -> "...%..." */
		    tok->map = &FmtWordTokenMap;
		    tok->tokWord.start = p;
		    tok->tokWord.end = p + 1;
		    AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *);
		    tokCnt++;
		    p++;
		    continue;
		case 'E':
		    fmtMap = FmtETokenMap,
		    mapIndex =	FmtETokenMapIndex,
		    aliasIndex = FmtETokenMapAliasIndex;
		    p++;
		    break;
		case 'O':
		    fmtMap = FmtOTokenMap,
		    mapIndex = FmtOTokenMapIndex,
		    aliasIndex = FmtOTokenMapAliasIndex;
		    p++;
		    break;
		}
		/* search direct index */
		cp = strchr(mapIndex, *p);
		if (!cp || *cp == '\0') {
		    /* search wrapper index (multiple chars for same token) */
		    cp = strchr(aliasIndex[0], *p);
		    if (!cp || *cp == '\0') {
			p--;
			if (fmtMap != FmtSTokenMap) {
			    p--;
			}
			goto word_tok;
		    }
		    cp = strchr(mapIndex, aliasIndex[1][cp - aliasIndex[0]]);
		    if (!cp || *cp == '\0') {	/* unexpected, but ... */
#ifdef DEBUG
			Tcl_Panic("token \"%c\" has no map in wrapper resolver", *p);
#endif
			p--;
			if (fmtMap != FmtSTokenMap) {
			    p--;
			}
			goto word_tok;
		    }
		}
		tok->map = &fmtMap[cp - mapIndex];
		tok->tokWord.start = p;
		/* next token */
		AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *);
		tokCnt++;
		p++;
		continue;
	    }
	    default:
	      word_tok:
		{
		/* try continue with previous word token */
		ClockFormatToken *wordTok = tok - 1;

		if (wordTok < fmtTok || wordTok->map != &FmtWordTokenMap) {
		    /* start with new word token */
		    wordTok = tok;
		    wordTok->tokWord.start = p;
		    wordTok->map = &FmtWordTokenMap;
		}
		do {
		    p = Tcl_UtfNext(p);
		} while (p < e && *p != '%');
		wordTok->tokWord.end = p;

		if (wordTok == tok) {
		    AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *);
		    tokCnt++;
		}
		}
		break;
	    }
	}

	/* correct count of real used tokens and free mem if desired
	 * (1 is acceptable delta to prevent memory fragmentation) */
	if (fss->fmtTokC > tokCnt + (CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE / 2)) {
	    if ((tok = (ClockFormatToken *)
		    Tcl_AttemptRealloc(fmtTok, tokCnt * sizeof(*tok))) != NULL) {
		fmtTok = tok;
	    }
	}

	/* now we're ready - assign now to storage (note the threaded race condition) */
	fss->fmtTok = fmtTok;
	fss->fmtTokC = tokCnt;
    }

    Tcl_MutexUnlock(&ClockFmtMutex);
    return fss;
}

/*
 *----------------------------------------------------------------------
 */
int
ClockFormat(
    DateFormat *dateFmt,	/* Date fields used for parsing & converting */
    ClockFmtScnCmdArgs *opts)	/* Command options */
{
    ClockFmtScnStorage *fss;
    ClockFormatToken *tok;
    const ClockFormatTokenMap *map;
    char resMem[MIN_FMT_RESULT_BLOCK_ALLOC];

    /* get localized format */
    if (ClockLocalizeFormat(opts) == NULL) {
	return TCL_ERROR;
    }

    if (!(fss = ClockGetOrParseFmtFormat(opts->interp, opts->formatObj))
	    || !(tok = fss->fmtTok)) {
	return TCL_ERROR;
    }

    /* result container object */
    dateFmt->resMem = resMem;
    dateFmt->resEnd = dateFmt->resMem + sizeof(resMem);
    if (fss->fmtMinAlloc > sizeof(resMem)) {
	dateFmt->resMem = (char *)Tcl_AttemptAlloc(fss->fmtMinAlloc);
	if (dateFmt->resMem == NULL) {
	    return TCL_ERROR;
	}
	dateFmt->resEnd = dateFmt->resMem + fss->fmtMinAlloc;
    }
    dateFmt->output = dateFmt->resMem;
    *dateFmt->output = '\0';

    /* do format each token */
    for (; tok->map != NULL; tok++) {
	map = tok->map;
	switch (map->type) {
	case CTOKT_INT: {
	    int val = *IntFieldAt(dateFmt, map->offs);

	    if (map->fmtproc == NULL) {
		if (map->flags & CLFMT_DECR) {
		    val--;
		}
		if (map->flags & CLFMT_INCR) {
		    val++;
		}
		if (map->divider) {
		    val /= map->divider;
		}
		if (map->divmod) {
		    val %= map->divmod;
		}
	    } else {
		if (map->fmtproc(opts, dateFmt, tok, &val) != TCL_OK) {
		    goto done;
		}
		/* if not calculate only (output inside fmtproc) */
		if (!(map->flags & CLFMT_CALC)) {
		    continue;
		}
	    }
	    if (!(map->flags & CLFMT_LOCALE_INDX)) {
		if (FrmResultAllocate(dateFmt, 11) != TCL_OK) {
		    goto error;
		}
		if (map->width) {
		    dateFmt->output = Clock_itoaw(
			    dateFmt->output, val, *map->tostr, map->width);
		} else {
		    dateFmt->output += sprintf(dateFmt->output, map->tostr, val);
		}
	    } else {
		const char *s;
		Tcl_Obj * mcObj = ClockMCGet(opts, PTR2INT(map->data) /* mcKey */);

		if (mcObj == NULL) {
		    goto error;
		}
		if (Tcl_ListObjIndex(opts->interp, mcObj, val, &mcObj) != TCL_OK
			|| mcObj == NULL) {
		    goto error;
		}
		s = TclGetString(mcObj);
		if (FrmResultAllocate(dateFmt, mcObj->length) != TCL_OK) {
		    goto error;
		}
		memcpy(dateFmt->output, s, mcObj->length + 1);
		dateFmt->output += mcObj->length;
	    }
	    break;
	}
	case CTOKT_WIDE: {
	    Tcl_WideInt val = *WideFieldAt(dateFmt, map->offs);

	    if (FrmResultAllocate(dateFmt, 21) != TCL_OK) {
		goto error;
	    }
	    if (map->width) {
		dateFmt->output = Clock_witoaw(dateFmt->output, val, *map->tostr, map->width);
	    } else {
		dateFmt->output += sprintf(dateFmt->output, map->tostr, val);
	    }
	    break;
	}
	case CTOKT_CHAR:
	    if (FrmResultAllocate(dateFmt, 1) != TCL_OK) {
		goto error;
	    }
	    *dateFmt->output++ = *map->tostr;
	    break;
	case CFMTT_PROC:
	    if (map->fmtproc(opts, dateFmt, tok, NULL) != TCL_OK) {
		goto error;
	    }
	    break;
	case CTOKT_WORD: {
	    Tcl_Size len = tok->tokWord.end - tok->tokWord.start;

	    if (FrmResultAllocate(dateFmt, len) != TCL_OK) {
		goto error;
	    }
	    if (len == 1) {
		*dateFmt->output++ = *tok->tokWord.start;
	    } else {
		memcpy(dateFmt->output, tok->tokWord.start, len);
		dateFmt->output += len;
	    }
	    break;
	}
	}
    }
    goto done;

  error:
    if (dateFmt->resMem != resMem) {
	Tcl_Free(dateFmt->resMem);
    }
    dateFmt->resMem = NULL;

  done:
    if (dateFmt->resMem) {
	size_t size;
	Tcl_Obj *result;

	TclNewObj(result);
	result->length = dateFmt->output - dateFmt->resMem;
	size = result->length + 1;
	if (dateFmt->resMem == resMem) {
	    result->bytes = (char *)Tcl_AttemptAlloc(size);
	    if (result->bytes == NULL) {
		return TCL_ERROR;
	    }
	    memcpy(result->bytes, dateFmt->resMem, size);
	} else if ((dateFmt->resEnd - dateFmt->resMem) / size > MAX_FMT_RESULT_THRESHOLD) {
	    result->bytes = (char *)Tcl_AttemptRealloc(dateFmt->resMem, size);
	    if (result->bytes == NULL) {
		result->bytes = dateFmt->resMem;
	    }
	} else {
	    result->bytes = dateFmt->resMem;
	}
	/* save last used buffer length */
	if (dateFmt->resMem != resMem
		&& fss->fmtMinAlloc < size + MIN_FMT_RESULT_BLOCK_DELTA) {
	    fss->fmtMinAlloc = size + MIN_FMT_RESULT_BLOCK_DELTA;
	}
	result->bytes[result->length] = '\0';
	Tcl_SetObjResult(opts->interp, result);
	return TCL_OK;
    }

    return TCL_ERROR;
}


void
ClockFrmScnClearCaches(void)
{
    Tcl_MutexLock(&ClockFmtMutex);
    /* clear caches ... */
    Tcl_MutexUnlock(&ClockFmtMutex);
}

void
ClockFrmScnFinalize(void)
{
    if (!initialized) {
	return;
    }
    Tcl_MutexLock(&ClockFmtMutex);
#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0
    /* clear GC */
    ClockFmtScnStorage_GC.stackPtr = NULL;
    ClockFmtScnStorage_GC.stackBound = NULL;
    ClockFmtScnStorage_GC.count = 0;
#endif
    if (initialized) {
	initialized = 0;
	Tcl_DeleteHashTable(&FmtScnHashTable);
    }
    Tcl_MutexUnlock(&ClockFmtMutex);
    Tcl_MutexFinalize(&ClockFmtMutex);
}
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclCmdAH.c.

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
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
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
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






-
-
+
+






+
+












-
-
-
-
-
+
+
+
+
+


-
+

















+










-
+







/*
 * tclCmdAH.c --
 *
 *	This file contains the top-level command routines for most of the Tcl
 *	built-in commands whose names begin with the letters A to H.
 *
 * Copyright (c) 1987-1993 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright © 1987-1993 The Regents of the University of California.
 * Copyright © 1994-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclIO.h"
#include "tclTomMath.h"
#ifdef _WIN32
#   include "tclWinInt.h"
#endif

/*
 * The state structure used by [foreach]. Note that the actual structure has
 * all its working arrays appended afterwards so they can be allocated and
 * freed in a single step.
 */

struct ForeachState {
    Tcl_Obj *bodyPtr;		/* The script body of the command. */
    int bodyIdx;		/* The argument index of the body. */
    int j, maxj;		/* Number of loop iterations. */
    int numLists;		/* Count of value lists. */
    int *index;			/* Array of value list indices. */
    int *varcList;		/* # loop variables per list. */
    Tcl_Size bodyIdx;		/* The argument index of the body. */
    Tcl_Size j, maxj;		/* Number of loop iterations. */
    Tcl_Size numLists;		/* Count of value lists. */
    Tcl_Size *index;		/* Array of value list indices. */
    Tcl_Size *varcList;		/* # loop variables per list. */
    Tcl_Obj ***varvList;	/* Array of var name lists. */
    Tcl_Obj **vCopyList;	/* Copies of var name list arguments. */
    int *argcList;		/* Array of value list sizes. */
    Tcl_Size *argcList;		/* Array of value list sizes. */
    Tcl_Obj ***argvList;	/* Array of value lists. */
    Tcl_Obj **aCopyList;	/* Copies of value list arguments. */
    Tcl_Obj *resultList;	/* List of result values from the loop body,
				 * or NULL if we're not collecting them
				 * ([lmap] vs [foreach]). */
};

/*
 * Prototypes for local procedures defined in this file:
 */

static int		CheckAccess(Tcl_Interp *interp, Tcl_Obj *pathPtr,
			    int mode);
static Tcl_ObjCmdProc	EncodingConvertfromObjCmd;
static Tcl_ObjCmdProc	EncodingConverttoObjCmd;
static Tcl_ObjCmdProc	EncodingDirsObjCmd;
static Tcl_ObjCmdProc	EncodingNamesObjCmd;
static Tcl_ObjCmdProc	EncodingProfilesObjCmd;
static Tcl_ObjCmdProc	EncodingSystemObjCmd;
static inline int	ForeachAssignments(Tcl_Interp *interp,
			    struct ForeachState *statePtr);
static inline void	ForeachCleanup(Tcl_Interp *interp,
			    struct ForeachState *statePtr);
static int		GetStatBuf(Tcl_Interp *interp, Tcl_Obj *pathPtr,
			    Tcl_FSStatProc *statProc, Tcl_StatBuf *statPtr);
static const char *	GetTypeFromMode(int mode);
static int		StoreStatData(Tcl_Interp *interp, Tcl_Obj *varName,
			    Tcl_StatBuf *statPtr);
static int	EachloopCmd(Tcl_Interp *interp, int collect,
static int		EachloopCmd(Tcl_Interp *interp, int collect,
			    int objc, Tcl_Obj *const objv[]);
static Tcl_NRPostProc	CatchObjCmdCallback;
static Tcl_NRPostProc	ExprCallback;
static Tcl_NRPostProc	ForSetupCallback;
static Tcl_NRPostProc	ForCondCallback;
static Tcl_NRPostProc	ForNextCallback;
static Tcl_NRPostProc	ForPostNextCallback;
115
116
117
118
119
120
121
122

123
124
125
126
127
128
129
118
119
120
121
122
123
124

125
126
127
128
129
130
131
132







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_BreakObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
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
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







-
+









-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_CatchObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, TclNRCatchObjCmd, clientData, objc, objv);
}

int
TclNRCatchObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *varNamePtr = NULL;
    Tcl_Obj *optionVarNamePtr = NULL;
    Interp *iPtr = (Interp *) interp;
190
191
192
193
194
195
196
197

198
199
200
201
202
203
204
193
194
195
196
197
198
199

200
201
202
203
204
205
206
207







-
+







     */

    return TclNREvalObjEx(interp, objv[1], 0, iPtr->cmdFramePtr, 1);
}

static int
CatchObjCmdCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    int objc = PTR2INT(data[0]);
    Tcl_Obj *varNamePtr = (Tcl_Obj *)data[1];
    Tcl_Obj *optionVarNamePtr = (Tcl_Obj *)data[2];
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
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







-
+















+
-
+
+
+





+
+
+
+
-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_CdObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *dir;
    int result;

    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?dirName?");
	return TCL_ERROR;
    }

    if (objc == 2) {
	dir = objv[1];
    } else {
	dir = TclGetHomeDirObj(interp, NULL);
	TclNewLiteralStringObj(dir, "~");
	if (dir == NULL) {
	    return TCL_ERROR;
	}
	Tcl_IncrRefCount(dir);
    }
    if (Tcl_FSConvertToPathType(interp, dir) != TCL_OK) {
	result = TCL_ERROR;
    } else {
	Tcl_DString ds;
	result = Tcl_UtfToExternalDStringEx(NULL, TCLFSENCODING, TclGetString(dir), -1, 0, &ds, NULL);
	Tcl_DStringFree(&ds);
	if (result == TCL_OK) {
	result = Tcl_FSChdir(dir);
	    result = Tcl_FSChdir(dir);
	}
	if (result != TCL_OK) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "couldn't change working directory to \"%s\": %s",
		    TclGetString(dir), Tcl_PosixError(interp)));
	    result = TCL_ERROR;
	}
    }
306
307
308
309
310
311
312
313

314
315
316
317
318
319
320
317
318
319
320
321
322
323

324
325
326
327
328
329
330
331







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ConcatObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    if (objc >= 2) {
	Tcl_SetObjResult(interp, Tcl_ConcatObj(objc-1, objv+1));
    }
340
341
342
343
344
345
346
347

348
349
350
351
352
353
354
351
352
353
354
355
356
357

358
359
360
361
362
363
364
365







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ContinueObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
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
442

443
444
445

446
447
448
449
450
451
452
453
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573

574
575



576
577
578
579
580
581
582
583
584
585
586
587
588
589

590
591


592

593
594
595
596
597
598
599







-
-
+
+


+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
















-
+







-
+

+
+
+
+

+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+



+
-
+

-
-
-
+
+
+
+
+
+
+
+
+





-
+

-
-
+
-







 */

Tcl_Command
TclInitEncodingCmd(
    Tcl_Interp* interp)		/* Tcl interpreter */
{
    static const EnsembleImplMap encodingImplMap[] = {
	{"convertfrom", EncodingConvertfromObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
	{"convertto",   EncodingConverttoObjCmd,   TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
	{"convertfrom", EncodingConvertfromObjCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0},
	{"convertto",   EncodingConverttoObjCmd,   TclCompileBasic1To3ArgCmd, NULL, NULL, 0},
	{"dirs",        EncodingDirsObjCmd,        TclCompileBasic0Or1ArgCmd, NULL, NULL, 1},
	{"names",       EncodingNamesObjCmd,       TclCompileBasic0ArgCmd,    NULL, NULL, 0},
	{"profiles",    EncodingProfilesObjCmd,    TclCompileBasic0ArgCmd,    NULL, NULL, 0},
	{"system",      EncodingSystemObjCmd,      TclCompileBasic0Or1ArgCmd, NULL, NULL, 1},
	{NULL,          NULL,                      NULL,                      NULL, NULL, 0}
    };

    return TclMakeEnsemble(interp, "encoding", encodingImplMap);
}

/*
 *------------------------------------------------------------------------
 *
 * EncodingConvertParseOptions --
 *
 *    Common routine for parsing arguments passed to encoding convertfrom
 *    and encoding convertto.
 *
 * Results:
 *    TCL_OK or TCL_ERROR.
 *
 * Side effects:
 *    On success,
 *    - *encPtr is set to the encoding. Must be freed with Tcl_FreeEncoding
 *      if non-NULL
 *    - *dataObjPtr is set to the Tcl_Obj containing the data to encode or
 *      decode
 *    - *profilePtr is set to encoding error handling profile
 *    - *failVarPtr is set to -failindex option value or NULL
 *    On error, all of the above are uninitialized.
 *
 *------------------------------------------------------------------------
 */
static int
EncodingConvertParseOptions(
    Tcl_Interp *interp,		/* For error messages. May be NULL */
    int objc,			/* Number of arguments */
    Tcl_Obj *const objv[],	/* Argument objects as passed to command. */
    Tcl_Encoding *encPtr,	/* Where to store the encoding */
    Tcl_Obj **dataObjPtr,	/* Where to store ptr to Tcl_Obj containing data */
    int *profilePtr,		/* Bit mask of encoding option profile */
    Tcl_Obj **failVarPtr)	/* Where to store -failindex option value */
{
    static const char *const options[] = {"-profile", "-failindex", NULL};
    enum convertfromOptions { PROFILE, FAILINDEX } optIndex;
    Tcl_Encoding encoding;
    Tcl_Obj *dataObj;
    Tcl_Obj *failVarObj;
    int profile = TCL_ENCODING_PROFILE_STRICT;

    /*
     * Possible combinations:
     * 1) data						-> objc = 2
     * 2) ?options? encoding data			-> objc >= 3
     * It is intentional that specifying option forces encoding to be
     * specified. Less prone to user error. This should have always been
     * the case even in 8.6 imho where there were no options (ie (1)
     * should never have been allowed)
     */

    if (objc == 1) {
    numArgsError: /* ONLY jump here if nothing needs to be freed!!! */
	Tcl_WrongNumArgs(interp, 1, objv,
		"?-profile profile? ?-failindex var? encoding data");
	((Interp *)interp)->flags |= INTERP_ALTERNATE_WRONG_ARGS;
	Tcl_WrongNumArgs(interp, 1, objv, "data");
	return TCL_ERROR;
    }

    failVarObj = NULL;
    if (objc == 2) {
	encoding = Tcl_GetEncoding(interp, NULL);
	dataObj = objv[1];
    } else {
	int argIndex;
	for (argIndex = 1; argIndex < (objc-2); ++argIndex) {
	    if (Tcl_GetIndexFromObj(interp, objv[argIndex], options, "option",
		    0, &optIndex) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (++argIndex == (objc - 2)) {
		goto numArgsError;
	    }
	    switch (optIndex) {
	    case PROFILE:
		if (TclEncodingProfileNameToId(interp,
			Tcl_GetString(objv[argIndex]), &profile) != TCL_OK) {
		    return TCL_ERROR;
		}
		break;
	    case FAILINDEX:
		failVarObj = objv[argIndex];
		break;
	    }
	}
	/* Get encoding after opts so no need to free it on option error */
	if (Tcl_GetEncodingFromObj(interp, objv[objc - 2], &encoding) != TCL_OK) {
	    return TCL_ERROR;
	}
	dataObj = objv[objc - 1];
    }

    *encPtr = encoding;
    *dataObjPtr = dataObj;
    *profilePtr = profile;
    *failVarPtr = failVarObj;

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * EncodingConvertfromObjCmd --
 *
 *	This command converts a byte array in an external encoding into a
 *	Tcl string
 *
 * Results:
 *	A standard Tcl result.
 *
 *----------------------------------------------------------------------
 */

int
EncodingConvertfromObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *data;		/* Byte array to convert */
    Tcl_DString ds;		/* Buffer to hold the string */
    Tcl_Encoding encoding;	/* Encoding to use */
    size_t length = 0;			/* Length of the byte array being converted */
    Tcl_Size length = 0;			/* Length of the byte array being converted */
    const char *bytesPtr;	/* Pointer to the first byte of the array */
    int flags;
    int result;
    Tcl_Obj *failVarObj;
    Tcl_Size errorLocation;

    if (EncodingConvertParseOptions(interp, objc, objv, &encoding, &data,
	    &flags, &failVarObj) != TCL_OK) {
	return TCL_ERROR;
    }
    if (objc == 2) {
	encoding = Tcl_GetEncoding(interp, NULL);
	data = objv[1];
    } else if (objc == 3) {

    /*
     * Convert the string into a byte array in 'ds'.
     */
    bytesPtr = (char *) Tcl_GetBytesFromObj(interp, data, &length);

    if (bytesPtr == NULL) {
	if (Tcl_GetEncodingFromObj(interp, objv[1], &encoding) != TCL_OK) {
	    return TCL_ERROR;
	}
	data = objv[2];
    } else {
	Tcl_WrongNumArgs(interp, 1, objv, "?encoding? data");
	return TCL_ERROR;
    }
    result = Tcl_ExternalToUtfDStringEx(interp, encoding, bytesPtr, length, flags,
	    &ds, failVarObj ? &errorLocation : NULL);
    /* NOTE: ds must be freed beyond this point even on error */
    switch (result) {
    case TCL_OK:
	errorLocation = TCL_INDEX_NONE;
	break;
    case TCL_ERROR:
	/* Error in parameters. Should not happen. interp will have error */
	Tcl_DStringFree(&ds);
	return TCL_ERROR;
    default:
	/*
	 * One of the TCL_CONVERT_* errors. If we were not interested in the
	 * error location, interp result would already have been filled in
	 * and we can just return the error. Otherwise, we have to return
	 * what could be decoded and the returned error location.
	 */
	if (failVarObj == NULL) {
	    Tcl_DStringFree(&ds);
	    return TCL_ERROR;
	}
	break;
    }

    /*
     * TCL_OK or a TCL_CONVERT_* error where the caller wants back as much
     * Convert the string into a byte array in 'ds'
     * data as was converted.
     */
    bytesPtr = (char *) TclGetByteArrayFromObj(data, &length);
    Tcl_ExternalToUtfDString(encoding, bytesPtr, length, &ds);

    if (failVarObj) {
	Tcl_Obj *failIndex;
	TclNewIndexObj(failIndex, errorLocation);
	if (Tcl_ObjSetVar2(interp, failVarObj, NULL, failIndex,
		TCL_LEAVE_ERR_MSG) == NULL) {
	    Tcl_DStringFree(&ds);
	    return TCL_ERROR;
	}
    }
    /*
     * Note that we cannot use Tcl_DStringResult here because it will
     * truncate the string at the first null byte.
     */

    Tcl_SetObjResult(interp, TclDStringToObj(&ds));
    Tcl_SetObjResult(interp, Tcl_DStringToObj(&ds));

    /*
     * We're done with the encoding
    /* We're done with the encoding */
     */

    Tcl_FreeEncoding(encoding);
    return TCL_OK;

}

/*
462
463
464
465
466
467
468
469

470
471
472
473
474
475
476
477

478
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
608
609
610
611
612
613
614

615
616
617
618
619
620
621
622

623
624

625




626
627
628





629



630
631
632
633
634
635
636
637
638
639




640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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







-
+







-
+

-
+
-
-
-
-
+
+
+
-
-
-
-
-
+
-
-
-
+
+








-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
+
-







 *	A standard Tcl result.
 *
 *----------------------------------------------------------------------
 */

int
EncodingConverttoObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *data;		/* String to convert */
    Tcl_DString ds;		/* Buffer to hold the byte array */
    Tcl_Encoding encoding;	/* Encoding to use */
    size_t length;			/* Length of the string being converted */
    Tcl_Size length;		/* Length of the string being converted */
    const char *stringPtr;	/* Pointer to the first byte of the string */

    int result;
    /* TODO - ADJUST OBJ INDICES WHEN ENSEMBLIFYING THIS */

    if (objc == 2) {
	encoding = Tcl_GetEncoding(interp, NULL);
    int flags;
    Tcl_Obj *failVarObj;
    Tcl_Size errorLocation;
	data = objv[1];
    } else if (objc == 3) {
	if (Tcl_GetEncodingFromObj(interp, objv[1], &encoding) != TCL_OK) {
	    return TCL_ERROR;
	}

	data = objv[2];
    } else {
	Tcl_WrongNumArgs(interp, 1, objv, "?encoding? data");
    if (EncodingConvertParseOptions(interp, objc, objv, &encoding, &data,
	    &flags, &failVarObj) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Convert the string to a byte array in 'ds'
     */

    stringPtr = TclGetStringFromObj(data, &length);
    Tcl_UtfToExternalDString(encoding, stringPtr, length, &ds);
    Tcl_SetObjResult(interp,
		     Tcl_NewByteArrayObj((unsigned char*) Tcl_DStringValue(&ds),
					 Tcl_DStringLength(&ds)));
    result = Tcl_UtfToExternalDStringEx(interp, encoding, stringPtr, length, flags,
	    &ds, failVarObj ? &errorLocation : NULL);
    /* NOTE: ds must be freed beyond this point even on error */

    switch (result) {
    case TCL_OK:
	errorLocation = TCL_INDEX_NONE;
	break;
    case TCL_ERROR:
	/* Error in parameters. Should not happen. interp will have error */
	Tcl_DStringFree(&ds);
	return TCL_ERROR;
    default:
	/*
	 * One of the TCL_CONVERT_* errors. If we were not interested in the
	 * error location, interp result would already have been filled in
	 * and we can just return the error. Otherwise, we have to return
	 * what could be decoded and the returned error location.
	 */
	if (failVarObj == NULL) {
	    Tcl_DStringFree(&ds);
	    return TCL_ERROR;
	}
	break;
    }
    /*
     * TCL_OK or a TCL_CONVERT_* error where the caller wants back as much
     * data as was converted.
     */
    if (failVarObj) {
	Tcl_Obj *failIndex;

	TclNewIndexObj(failIndex, errorLocation);
	if (Tcl_ObjSetVar2(interp, failVarObj, NULL, failIndex,
		TCL_LEAVE_ERR_MSG) == NULL) {
	    Tcl_DStringFree(&ds);
	    return TCL_ERROR;
	}
    }

    Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(
	    (unsigned char*) Tcl_DStringValue(&ds),
	    Tcl_DStringLength(&ds)));
    Tcl_DStringFree(&ds);

    /*
     * We're done with the encoding
    /* We're done with the encoding */
     */

    Tcl_FreeEncoding(encoding);
    return TCL_OK;

}

/*
526
527
528
529
530
531
532
533

534
535
536
537
538
539
540
703
704
705
706
707
708
709

710
711
712
713
714
715
716
717







-
+







 *	Can set the encoding search path.
 *
 *----------------------------------------------------------------------
 */

int
EncodingDirsObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *dirListObj;

    if (objc > 2) {
548
549
550
551
552
553
554
555

556
557
558
559
560
561
562
725
726
727
728
729
730
731

732
733
734
735
736
737
738
739







-
+








    dirListObj = objv[1];
    if (Tcl_SetEncodingSearchPath(dirListObj) == TCL_ERROR) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"expected directory list but got \"%s\"",
		TclGetString(dirListObj)));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "ENCODING", "BADPATH",
		NULL);
		(char *)NULL);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, dirListObj);
    return TCL_OK;
}

/*
570
571
572
573
574
575
576
577

578
579
580
581
582
583
584
585
586
587
588




























589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608

609
610
611
612
613
614
615
616
617
618
619

620
621
622
623
624
625
626
747
748
749
750
751
752
753

754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812

813
814
815
816
817
818
819
820
821
822
823

824
825
826
827
828
829
830
831







-
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



















-
+










-
+







 *	Returns a standard Tcl result
 *
 *-----------------------------------------------------------------------------
 */

int
EncodingNamesObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp* interp,	    /* Tcl interpreter */
    int objc,		    /* Number of command line args */
    Tcl_Obj* const objv[])  /* Vector of command line args */
{
    if (objc > 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
    }
    Tcl_GetEncodingNames(interp);
    return TCL_OK;
}

/*
 *-----------------------------------------------------------------------------
 *
 * EncodingProfilesObjCmd --
 *
 *	This command returns a list of the available encoding profiles
 *
 * Results:
 *	Returns a standard Tcl result
 *
 *-----------------------------------------------------------------------------
 */

int
EncodingProfilesObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp* interp,	    /* Tcl interpreter */
    int objc,		    /* Number of command line args */
    Tcl_Obj* const objv[])  /* Vector of command line args */
{
    if (objc > 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
    }
    TclGetEncodingProfiles(interp);
    return TCL_OK;
}

/*
 *-----------------------------------------------------------------------------
 *
 * EncodingSystemObjCmd --
 *
 *	This command retrieves or changes the system encoding
 *
 * Results:
 *	Returns a standard Tcl result
 *
 * Side effects:
 *	May change the system encoding.
 *
 *-----------------------------------------------------------------------------
 */

int
EncodingSystemObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp* interp,     /* Tcl interpreter */
    int objc,		    /* Number of command line args */
    Tcl_Obj* const objv[])  /* Vector of command line args */
{
    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?encoding?");
	return TCL_ERROR;
    }
    if (objc == 1) {
	Tcl_SetObjResult(interp,
			 Tcl_NewStringObj(Tcl_GetEncodingName(NULL), -1));
		Tcl_NewStringObj(Tcl_GetEncodingName(NULL), -1));
    } else {
	return Tcl_SetSystemEncoding(interp, TclGetString(objv[1]));
    }
    return TCL_OK;
}

/*
638
639
640
641
642
643
644
645

646
647
648
649
650
651
652
843
844
845
846
847
848
849

850
851
852
853
854
855
856
857







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ErrorObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *options, *optName;

    if ((objc < 2) || (objc > 4)) {
687
688
689
690
691
692
693
694

695
696
697
698
699
700
701
702
703
704
705
706
707

708
709
710
711
712
713
714
715
716
717

718
719
720
721
722
723
724
892
893
894
895
896
897
898

899
900
901
902
903
904
905
906
907
908
909
910
911

912
913
914
915
916
917
918
919
920
921

922
923
924
925
926
927
928
929







-
+












-
+









-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
EvalCmdErrMsg(
    TCL_UNUSED(ClientData *),
    TCL_UNUSED(void **),
    Tcl_Interp *interp,
    int result)
{
    if (result == TCL_ERROR) {
	Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
		"\n    (\"eval\" body line %d)", Tcl_GetErrorLine(interp)));
    }
    return result;
}

int
Tcl_EvalObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, TclNREvalObjCmd, clientData, objc, objv);
}

int
TclNREvalObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *objPtr;
    Interp *iPtr = (Interp *) interp;
    CmdFrame *invoker = NULL;
769
770
771
772
773
774
775
776

777
778
779
780
781
782
783
974
975
976
977
978
979
980

981
982
983
984
985
986
987
988







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ExitObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_WideInt value;

    if ((objc != 1) && (objc != 2)) {
816
817
818
819
820
821
822
823

824
825
826
827
828
829
830
831
832
833

834
835
836
837
838
839
840
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







-
+









-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ExprObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, TclNRExprObjCmd, clientData, objc, objv);
}

int
TclNRExprObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *resultPtr, *objPtr;

    if (objc < 2) {
853
854
855
856
857
858
859
860

861
862
863
864
865
866
867
1058
1059
1060
1061
1062
1063
1064

1065
1066
1067
1068
1069
1070
1071
1072







-
+







    }

    return Tcl_NRExprObj(interp, objPtr, resultPtr);
}

static int
ExprCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj *resultPtr = (Tcl_Obj *)data[0];
    Tcl_Obj *objPtr = (Tcl_Obj *)data[1];

    if (objPtr != NULL) {
912
913
914
915
916
917
918

919
920
921
922
923
924
925
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131







+







	{"channels",	TclChannelNamesCmd,	TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
	{"copy",	TclFileCopyCmd,		NULL, NULL, NULL, 1},
	{"delete",	TclFileDeleteCmd,	TclCompileBasicMin0ArgCmd, NULL, NULL, 1},
	{"dirname",	PathDirNameCmd,		TclCompileBasic1ArgCmd, NULL, NULL, 1},
	{"executable",	FileAttrIsExecutableCmd, TclCompileBasic1ArgCmd, NULL, NULL, 1},
	{"exists",	FileAttrIsExistingCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 1},
	{"extension",	PathExtensionCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 1},
	{"home",	TclFileHomeCmd,		TclCompileBasic0Or1ArgCmd, NULL, NULL, 1},
	{"isdirectory",	FileAttrIsDirectoryCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 1},
	{"isfile",	FileAttrIsFileCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 1},
	{"join",	PathJoinCmd,		TclCompileBasicMin1ArgCmd, NULL, NULL, 0},
	{"link",	TclFileLinkCmd,		TclCompileBasic1To3ArgCmd, NULL, NULL, 1},
	{"lstat",	FileAttrLinkStatCmd,	TclCompileBasic2ArgCmd, NULL, NULL, 1},
	{"mtime",	FileAttrModifyTimeCmd,	TclCompileBasic1Or2ArgCmd, NULL, NULL, 1},
	{"mkdir",	TclFileMakeDirsCmd,	TclCompileBasicMin0ArgCmd, NULL, NULL, 1},
935
936
937
938
939
940
941

942
943
944
945
946
947
948
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155







+







	{"size",	FileAttrSizeCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 1},
	{"split",	PathSplitCmd,		TclCompileBasic1ArgCmd, NULL, NULL, 0},
	{"stat",	FileAttrStatCmd,	TclCompileBasic2ArgCmd, NULL, NULL, 1},
	{"system",	PathFilesystemCmd,	TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
	{"tail",	PathTailCmd,		TclCompileBasic1ArgCmd, NULL, NULL, 1},
	{"tempdir",	TclFileTempDirCmd,	TclCompileBasic0Or1ArgCmd, NULL, NULL, 1},
	{"tempfile",	TclFileTemporaryCmd,	TclCompileBasic0To2ArgCmd, NULL, NULL, 1},
	{"tildeexpand",	TclFileTildeExpandCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 1},
	{"type",	FileAttrTypeCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 1},
	{"volumes",	FilesystemVolumesCmd,	TclCompileBasic0ArgCmd, NULL, NULL, 1},
	{"writable",	FileAttrIsWritableCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 1},
	{NULL, NULL, NULL, NULL, NULL, 0}
    };
    return TclMakeEnsemble(interp, "file", initMap);
}
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
1169
1170
1171
1172
1173
1174
1175

1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193




1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204







-
+

















-
-
-
-
+
+
+
+







 *	May update the access time on the file, if requested by the user.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrAccessTimeCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_StatBuf buf;
    struct utimbuf tval;

    if (objc < 2 || objc > 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "name ?time?");
	return TCL_ERROR;
    }
    if (GetStatBuf(interp, objv[1], Tcl_FSStat, &buf) != TCL_OK) {
	return TCL_ERROR;
    }
#if defined(_WIN32)
    /* We use a value of 0 to indicate the access time not available */
    if (Tcl_GetAccessTimeFromStat(&buf) == 0) {
        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                             "could not get access time for file \"%s\"",
                             TclGetString(objv[1])));
        return TCL_ERROR;
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"could not get access time for file \"%s\"",
		TclGetString(objv[1])));
	return TCL_ERROR;
    }
#endif

    if (objc == 3) {
	/*
	 * Need separate variable for reading longs from an object on 64-bit
	 * platforms. [Bug 698146]
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
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







-
+

















-
-
-
-
+
+
+
+







 *	user.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrModifyTimeCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_StatBuf buf;
    struct utimbuf tval;

    if (objc < 2 || objc > 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "name ?time?");
	return TCL_ERROR;
    }
    if (GetStatBuf(interp, objv[1], Tcl_FSStat, &buf) != TCL_OK) {
	return TCL_ERROR;
    }
#if defined(_WIN32)
    /* We use a value of 0 to indicate the modification time not available */
    if (Tcl_GetModificationTimeFromStat(&buf) == 0) {
        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                             "could not get modification time for file \"%s\"",
                             TclGetString(objv[1])));
        return TCL_ERROR;
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"could not get modification time for file \"%s\"",
		TclGetString(objv[1])));
	return TCL_ERROR;
    }
#endif
    if (objc == 3) {
	/*
	 * Need separate variable for reading longs from an object on 64-bit
	 * platforms. [Bug 698146]
	 */
1123
1124
1125
1126
1127
1128
1129
1130

1131
1132
1133
1134
1135
1136
1137
1138


1139
1140
1141
1142
1143



1144


1145
1146
1147
1148
1149
1150
1151
1330
1331
1332
1333
1334
1335
1336

1337
1338
1339
1340
1341
1342
1343


1344
1345
1346
1347
1348
1349
1350
1351
1352
1353

1354
1355
1356
1357
1358
1359
1360
1361
1362







-
+






-
-
+
+





+
+
+
-
+
+







 *	Writes to an array named by the user.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrLinkStatCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_StatBuf buf;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "name varName");
    if (objc < 2 || objc > 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "name ?varName?");
	return TCL_ERROR;
    }
    if (GetStatBuf(interp, objv[1], Tcl_FSLstat, &buf) != TCL_OK) {
	return TCL_ERROR;
    }
    if (objc == 2) {
	return StoreStatData(interp, NULL, &buf);
    } else {
    return StoreStatData(interp, objv[2], &buf);
	return StoreStatData(interp, objv[2], &buf);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * FileAttrStatCmd --
 *
1159
1160
1161
1162
1163
1164
1165
1166

1167
1168
1169
1170
1171
1172
1173
1174


1175
1176
1177
1178
1179



1180


1181
1182
1183
1184
1185
1186
1187
1370
1371
1372
1373
1374
1375
1376

1377
1378
1379
1380
1381
1382
1383


1384
1385
1386
1387
1388
1389
1390
1391
1392
1393

1394
1395
1396
1397
1398
1399
1400
1401
1402







-
+






-
-
+
+





+
+
+
-
+
+







 *	Writes to an array named by the user.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrStatCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_StatBuf buf;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "name varName");
    if (objc < 2 || objc > 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "name ?varName?");
	return TCL_ERROR;
    }
    if (GetStatBuf(interp, objv[1], Tcl_FSStat, &buf) != TCL_OK) {
	return TCL_ERROR;
    }
    if (objc == 2) {
	return StoreStatData(interp, NULL, &buf);
    } else {
    return StoreStatData(interp, objv[2], &buf);
	return StoreStatData(interp, objv[2], &buf);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * FileAttrTypeCmd --
 *
1195
1196
1197
1198
1199
1200
1201
1202

1203
1204
1205
1206
1207
1208
1209
1410
1411
1412
1413
1414
1415
1416

1417
1418
1419
1420
1421
1422
1423
1424







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrTypeCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_StatBuf buf;

    if (objc != 2) {
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
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







-
+













-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrSizeCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_StatBuf buf;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name");
	return TCL_ERROR;
    }
    if (GetStatBuf(interp, objv[1], Tcl_FSStat, &buf) != TCL_OK) {
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) buf.st_size));
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(buf.st_size));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * FileAttrIsDirectoryCmd --
1270
1271
1272
1273
1274
1275
1276
1277

1278
1279
1280
1281
1282
1283
1284
1485
1486
1487
1488
1489
1490
1491

1492
1493
1494
1495
1496
1497
1498
1499







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsDirectoryCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_StatBuf buf;
    int value = 0;

1308
1309
1310
1311
1312
1313
1314
1315

1316
1317
1318
1319
1320
1321
1322
1523
1524
1525
1526
1527
1528
1529

1530
1531
1532
1533
1534
1535
1536
1537







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsExecutableCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name");
	return TCL_ERROR;
1339
1340
1341
1342
1343
1344
1345
1346

1347
1348
1349
1350
1351
1352
1353
1554
1555
1556
1557
1558
1559
1560

1561
1562
1563
1564
1565
1566
1567
1568







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsExistingCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name");
	return TCL_ERROR;
1370
1371
1372
1373
1374
1375
1376
1377

1378
1379
1380
1381
1382
1383
1384
1585
1586
1587
1588
1589
1590
1591

1592
1593
1594
1595
1596
1597
1598
1599







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsFileCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_StatBuf buf;
    int value = 0;

1408
1409
1410
1411
1412
1413
1414
1415

1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431















1432
1433
1434
1435
1436
1437
1438
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







-
+
















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsOwnedCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
#ifdef __CYGWIN__
#define geteuid() (short)(geteuid)()
#endif
#if !defined(_WIN32)
    Tcl_StatBuf buf;
#endif
    int value = 0;

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

    Tcl_Obj *normPathPtr = Tcl_FSGetNormalizedPath(interp, objv[1]);
    /* Note normPathPtr owned by Tcl, no need to free it */
    if (normPathPtr) {
	if (TclIsZipfsPath(TclGetString(normPathPtr))) {
	    return CheckAccess(interp, objv[1], F_OK);
	}
	/* Not zipfs, try native. */
    }

    /*
     * Note use objv[1] below, NOT normPathPtr even if not NULL because
     * for native paths we may not want links to be resolved.
     */

#if defined(_WIN32)
    value = TclWinFileOwned(objv[1]);
#else
    if (GetStatBuf(NULL, objv[1], Tcl_FSStat, &buf) == TCL_OK) {
	value = (geteuid() == buf.st_uid);
    }
#endif
1455
1456
1457
1458
1459
1460
1461
1462

1463
1464
1465
1466
1467
1468
1469
1685
1686
1687
1688
1689
1690
1691

1692
1693
1694
1695
1696
1697
1698
1699







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsReadableCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name");
	return TCL_ERROR;
1486
1487
1488
1489
1490
1491
1492
1493

1494
1495
1496
1497
1498
1499
1500
1716
1717
1718
1719
1720
1721
1722

1723
1724
1725
1726
1727
1728
1729
1730







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsWritableCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name");
	return TCL_ERROR;
1517
1518
1519
1520
1521
1522
1523
1524

1525
1526
1527
1528
1529
1530
1531
1747
1748
1749
1750
1751
1752
1753

1754
1755
1756
1757
1758
1759
1760
1761







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathDirNameCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *dirPtr;

    if (objc != 2) {
1556
1557
1558
1559
1560
1561
1562
1563

1564
1565
1566
1567
1568
1569
1570
1786
1787
1788
1789
1790
1791
1792

1793
1794
1795
1796
1797
1798
1799
1800







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathExtensionCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *dirPtr;

    if (objc != 2) {
1595
1596
1597
1598
1599
1600
1601
1602

1603
1604
1605
1606
1607
1608
1609
1825
1826
1827
1828
1829
1830
1831

1832
1833
1834
1835
1836
1837
1838
1839







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathRootNameCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *dirPtr;

    if (objc != 2) {
1634
1635
1636
1637
1638
1639
1640
1641

1642
1643
1644
1645
1646
1647
1648
1864
1865
1866
1867
1868
1869
1870

1871
1872
1873
1874
1875
1876
1877
1878







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathTailCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *dirPtr;

    if (objc != 2) {
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
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







-
+














-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathFilesystemCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *fsInfo;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name");
	return TCL_ERROR;
    }
    fsInfo = Tcl_FSFileSystemInfo(objv[1]);
    if (fsInfo == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("unrecognised path", -1));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "FILESYSTEM",
		TclGetString(objv[1]), NULL);
		TclGetString(objv[1]), (char *)NULL);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, fsInfo);
    return TCL_OK;
}

/*
1714
1715
1716
1717
1718
1719
1720
1721

1722
1723
1724
1725
1726
1727
1728
1944
1945
1946
1947
1948
1949
1950

1951
1952
1953
1954
1955
1956
1957
1958







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathJoinCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name ?name ...?");
	return TCL_ERROR;
1746
1747
1748
1749
1750
1751
1752
1753

1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767

1768
1769
1770
1771
1772
1773
1774
1976
1977
1978
1979
1980
1981
1982

1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996

1997
1998
1999
2000
2001
2002
2003
2004







-
+













-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathNativeNameCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_DString ds;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name");
	return TCL_ERROR;
    }
    if (Tcl_TranslateFileName(interp, TclGetString(objv[1]), &ds) == NULL) {
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, TclDStringToObj(&ds));
    Tcl_SetObjResult(interp, Tcl_DStringToObj(&ds));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * PathNormalizeCmd --
1783
1784
1785
1786
1787
1788
1789
1790

1791
1792
1793
1794
1795
1796
1797
2013
2014
2015
2016
2017
2018
2019

2020
2021
2022
2023
2024
2025
2026
2027







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathNormalizeCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *fileName;

    if (objc != 2) {
1821
1822
1823
1824
1825
1826
1827
1828

1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839

1840
1841
1842
1843
1844
1845

1846
1847
1848
1849
1850
1851
1852
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







-
+










-
+





-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathSplitCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *res;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name");
	return TCL_ERROR;
    }
    res = Tcl_FSSplitPath(objv[1], NULL);
    res = Tcl_FSSplitPath(objv[1], (Tcl_Size *)NULL);
    if (res == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"could not read \"%s\": no such file or directory",
		TclGetString(objv[1])));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PATHSPLIT", "NONESUCH",
		NULL);
		(char *)NULL);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, res);
    return TCL_OK;
}

/*
1864
1865
1866
1867
1868
1869
1870
1871

1872
1873
1874
1875
1876
1877
1878
2094
2095
2096
2097
2098
2099
2100

2101
2102
2103
2104
2105
2106
2107
2108







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathTypeCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *typeName;

    if (objc != 2) {
1912
1913
1914
1915
1916
1917
1918
1919

1920
1921
1922
1923
1924
1925
1926
2142
2143
2144
2145
2146
2147
2148

2149
2150
2151
2152
2153
2154
2155
2156







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FilesystemSeparatorCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc < 1 || objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?name?");
	return TCL_ERROR;
1940
1941
1942
1943
1944
1945
1946
1947

1948
1949
1950
1951
1952
1953
1954
2170
2171
2172
2173
2174
2175
2176

2177
2178
2179
2180
2181
2182
2183
2184







-
+







    } else {
	Tcl_Obj *separatorObj = Tcl_FSPathSeparator(objv[1]);

	if (separatorObj == NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "unrecognised path", -1));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "FILESYSTEM",
		    TclGetString(objv[1]), NULL);
		    TclGetString(objv[1]), (char *)NULL);
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, separatorObj);
    }
    return TCL_OK;
}

1967
1968
1969
1970
1971
1972
1973
1974

1975
1976
1977
1978
1979
1980
1981
2197
2198
2199
2200
2201
2202
2203

2204
2205
2206
2207
2208
2209
2210
2211







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FilesystemVolumesCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
2007
2008
2009
2010
2011
2012
2013

2014
2015
2016




2017

2018
2019
2020
2021
2022
2023
2024
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260







+



+
+
+
+

+







    Tcl_Interp *interp,		/* Interp for status return. Must not be
				 * NULL. */
    Tcl_Obj *pathPtr,		/* Name of file to check. */
    int mode)			/* Attribute to check; passed as argument to
				 * access(). */
{
    int value;
    Tcl_DString ds;

    if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) {
	value = 0;
    } else if (Tcl_UtfToExternalDStringEx(NULL, TCLFSENCODING, TclGetString(pathPtr),
	    TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	value = 0;
	Tcl_DStringFree(&ds);
    } else {
	Tcl_DStringFree(&ds);
	value = (Tcl_FSAccess(pathPtr, mode) == 0);
    }
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));

    return TCL_OK;
}

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
2095
2096
2097
2098
2099
2100

2101
2102
2103
2104
2105
































2106
2107
2108
2109
2110
2111
2112
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300

2301
2302
2303
2304
2305
2306
2307
2308
2309
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







+





+
+
+
+
-
+
+
+



















-
+



















-
+


-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    Tcl_Obj *pathPtr,		/* Path name to examine. */
    Tcl_FSStatProc *statProc,	/* Either stat() or lstat() depending on
				 * desired behavior. */
    Tcl_StatBuf *statPtr)	/* Filled with info about file obtained by
				 * calling (*statProc)(). */
{
    int status;
    Tcl_DString ds;

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

    if (Tcl_UtfToExternalDStringEx(NULL, TCLFSENCODING, TclGetString(pathPtr),
	    TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	status = -1;
    } else {
    status = statProc(pathPtr, statPtr);
	status = statProc(pathPtr, statPtr);
    }
    Tcl_DStringFree(&ds);

    if (status < 0) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "could not read \"%s\": %s",
		    TclGetString(pathPtr), Tcl_PosixError(interp)));
	}
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * StoreStatData --
 *
 *	This is a utility procedure that breaks out the fields of a "stat"
 *	structure and stores them in textual form into the elements of an
 *	associative array.
 *	associative array (if given) or returns a dictionary.
 *
 * Results:
 *	Returns a standard Tcl return value. If an error occurs then a message
 *	is left in interp's result.
 *
 * Side effects:
 *	Elements of the associative array given by "varName" are modified.
 *
 *----------------------------------------------------------------------
 */

static int
StoreStatData(
    Tcl_Interp *interp,		/* Interpreter for error reports. */
    Tcl_Obj *varName,		/* Name of associative array variable in which
				 * to store stat results. */
    Tcl_StatBuf *statPtr)	/* Pointer to buffer containing stat data to
				 * store in varName. */
{
    Tcl_Obj *field, *value;
    Tcl_Obj *field, *value, *result;
    unsigned short mode;

    /*
     * Assume Tcl_ObjSetVar2() does not keep a copy of the field name!
     *
    if (varName == NULL) {
	TclNewObj(result);
	Tcl_IncrRefCount(result);
#define DOBJPUT(key, objValue)                  \
	Tcl_DictObjPut(NULL, result,            \
	    Tcl_NewStringObj((key), -1),        \
	    (objValue));
	DOBJPUT("dev",	Tcl_NewWideIntObj((long)statPtr->st_dev));
	DOBJPUT("ino",	Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_ino));
	DOBJPUT("nlink",	Tcl_NewWideIntObj((long)statPtr->st_nlink));
	DOBJPUT("uid",	Tcl_NewWideIntObj((long)statPtr->st_uid));
	DOBJPUT("gid",	Tcl_NewWideIntObj((long)statPtr->st_gid));
	DOBJPUT("size",	Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_size));
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
	DOBJPUT("blocks",	Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_blocks));
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
	DOBJPUT("blksize", Tcl_NewWideIntObj((long)statPtr->st_blksize));
#endif
	DOBJPUT("atime",	Tcl_NewWideIntObj(Tcl_GetAccessTimeFromStat(statPtr)));
	DOBJPUT("mtime",	Tcl_NewWideIntObj(Tcl_GetModificationTimeFromStat(statPtr)));
	DOBJPUT("ctime",	Tcl_NewWideIntObj(Tcl_GetChangeTimeFromStat(statPtr)));
	mode = (unsigned short) statPtr->st_mode;
	DOBJPUT("mode",	Tcl_NewWideIntObj(mode));
	DOBJPUT("type",	Tcl_NewStringObj(GetTypeFromMode(mode), -1));
#undef DOBJPUT
	Tcl_SetObjResult(interp, result);
	Tcl_DecrRefCount(result);
	return TCL_OK;
    }

    /*
     * Might be a better idea to call Tcl_SetVar2Ex() instead, except we want
     * to have an object (i.e. possibly cached) array variable name but a
     * string element name, so no API exists. Messy.
     */

#define STORE_ARY(fieldName, object) \
    TclNewLiteralStringObj(field, fieldName);				\
2120
2121
2122
2123
2124
2125
2126
2127

2128
2129
2130
2131

2132
2133

2134
2135
2136
2137





2138
2139


2140
2141
2142
2143
2144
2145
2146
2392
2393
2394
2395
2396
2397
2398

2399
2400
2401
2402

2403
2404

2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415

2416
2417
2418
2419
2420
2421
2422
2423
2424







-
+



-
+

-
+




+
+
+
+
+

-
+
+








    /*
     * Watch out porters; the inode is meant to be an *unsigned* value, so the
     * cast might fail when there isn't a real arithmetic 'long long' type...
     */

    STORE_ARY("dev",	Tcl_NewWideIntObj((long)statPtr->st_dev));
    STORE_ARY("ino",	Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_ino));
    STORE_ARY("ino",	Tcl_NewWideIntObj(statPtr->st_ino));
    STORE_ARY("nlink",	Tcl_NewWideIntObj((long)statPtr->st_nlink));
    STORE_ARY("uid",	Tcl_NewWideIntObj((long)statPtr->st_uid));
    STORE_ARY("gid",	Tcl_NewWideIntObj((long)statPtr->st_gid));
    STORE_ARY("size",	Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_size));
    STORE_ARY("size",	Tcl_NewWideIntObj(statPtr->st_size));
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
    STORE_ARY("blocks",	Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_blocks));
    STORE_ARY("blocks",	Tcl_NewWideIntObj(statPtr->st_blocks));
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
    STORE_ARY("blksize", Tcl_NewWideIntObj((long)statPtr->st_blksize));
#endif
#ifdef HAVE_STRUCT_STAT_ST_RDEV
    if (S_ISCHR(statPtr->st_mode) || S_ISBLK(statPtr->st_mode)) {
	STORE_ARY("rdev", Tcl_NewWideIntObj((long) statPtr->st_rdev));
    }
#endif
    STORE_ARY("atime",	Tcl_NewWideIntObj(Tcl_GetAccessTimeFromStat(statPtr)));
    STORE_ARY("mtime",	Tcl_NewWideIntObj(Tcl_GetModificationTimeFromStat(statPtr)));
    STORE_ARY("mtime",	Tcl_NewWideIntObj(
	    Tcl_GetModificationTimeFromStat(statPtr)));
    STORE_ARY("ctime",	Tcl_NewWideIntObj(Tcl_GetChangeTimeFromStat(statPtr)));
    mode = (unsigned short) statPtr->st_mode;
    STORE_ARY("mode",	Tcl_NewWideIntObj(mode));
    STORE_ARY("type",	Tcl_NewStringObj(GetTypeFromMode(mode), -1));
#undef STORE_ARY

    return TCL_OK;
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
2505
2506
2507
2508
2509
2510
2511

2512
2513
2514
2515
2516
2517
2518
2519
2520
2521

2522
2523
2524
2525
2526
2527
2528
2529







-
+









-
+







 *					|____________________|
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ForObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, TclNRForObjCmd, clientData, objc, objv);
}

int
TclNRForObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    ForIterData *iterPtr;

2268
2269
2270
2271
2272
2273
2274
2275

2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294

2295
2296
2297
2298
2299
2300
2301
2546
2547
2548
2549
2550
2551
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







-
+


















-
+







     */

    return TclNREvalObjEx(interp, objv[1], 0, iPtr->cmdFramePtr, 1);
}

static int
ForSetupCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    ForIterData *iterPtr = (ForIterData *)data[0];

    if (result != TCL_OK) {
	if (result == TCL_ERROR) {
	    Tcl_AddErrorInfo(interp, "\n    (\"for\" initial command)");
	}
	TclSmallFreeEx(interp, iterPtr);
	return result;
    }
    TclNRAddCallback(interp, TclNRForIterCallback, iterPtr, NULL, NULL, NULL);
    return TCL_OK;
}

int
TclNRForIterCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    ForIterData *iterPtr = (ForIterData *)data[0];
    Tcl_Obj *boolObj;

    switch (result) {
2322
2323
2324
2325
2326
2327
2328
2329

2330
2331
2332
2333
2334
2335
2336
2600
2601
2602
2603
2604
2605
2606

2607
2608
2609
2610
2611
2612
2613
2614







-
+







    }
    TclSmallFreeEx(interp, iterPtr);
    return result;
}

static int
ForCondCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    ForIterData *iterPtr = (ForIterData *)data[0];
    Tcl_Obj *boolObj = (Tcl_Obj *)data[1];
    int value;
2360
2361
2362
2363
2364
2365
2366
2367

2368
2369
2370
2371
2372
2373
2374
2638
2639
2640
2641
2642
2643
2644

2645
2646
2647
2648
2649
2650
2651
2652







-
+







    }
    TclSmallFreeEx(interp, iterPtr);
    return result;
}

static int
ForNextCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    ForIterData *iterPtr = (ForIterData *)data[0];
    Tcl_Obj *next = iterPtr->next;

2385
2386
2387
2388
2389
2390
2391
2392

2393
2394
2395
2396
2397
2398
2399
2663
2664
2665
2666
2667
2668
2669

2670
2671
2672
2673
2674
2675
2676
2677







-
+








    TclNRAddCallback(interp, TclNRForIterCallback, iterPtr, NULL, NULL, NULL);
    return result;
}

static int
ForPostNextCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    ForIterData *iterPtr = (ForIterData *)data[0];

    if ((result != TCL_BREAK) && (result != TCL_OK)) {
	if (result == TCL_ERROR) {
2421
2422
2423
2424
2425
2426
2427
2428

2429
2430
2431
2432
2433
2434
2435
2436
2437
2438

2439
2440
2441
2442
2443
2444
2445
2446
2447
2448

2449
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
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







-
+









-
+









-
+









-
+


















-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ForeachObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, TclNRForeachCmd, clientData, objc, objv);
}

int
TclNRForeachCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    return EachloopCmd(interp, TCL_EACH_KEEP_NONE, objc, objv);
}

int
Tcl_LmapObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, TclNRLmapCmd, clientData, objc, objv);
}

int
TclNRLmapCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    return EachloopCmd(interp, TCL_EACH_COLLECT, objc, objv);
}

static int
EachloopCmd(
    Tcl_Interp *interp,		/* Our context for variables and script
				 * evaluation. */
    int collect,		/* Select collecting or accumulating mode
				 * (TCL_EACH_*) */
    int objc,			/* The arguments being passed in... */
    Tcl_Obj *const objv[])
{
    int numLists = (objc-2) / 2;
    struct ForeachState *statePtr;
    int i, j, result;
    int i, result;
    Tcl_Size j;

    if (objc < 4 || (objc%2 != 0)) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"varList list ?varList list ...? command");
	return TCL_ERROR;
    }

2494
2495
2496
2497
2498
2499
2500
2501

2502
2503
2504

2505
2506
2507
2508
2509
2510

2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528


2529
2530
2531
2532
2533
2534
2535






2536
2537
2538
2539


2540
2541
2542


2543
2544
2545


2546












2547
2548
2549
2550
2551
2552






2553


2554



2555
2556
2557
2558
2559
2560
2561
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







-
+


-
+





-
+


















+
+





-
-
+
+
+
+
+
+


-
-
+
+

-
-
+
+



+
+

+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+

+
+
-
+
+
+







     *
     * The setting up of all of these pointers is moderately messy, but allows
     * the rest of this code to be simple and for us to use a single memory
     * allocation for better performance.
     */

    statePtr = (struct ForeachState *)TclStackAlloc(interp,
	    sizeof(struct ForeachState) + 3 * numLists * sizeof(int)
	    sizeof(struct ForeachState) + 3 * numLists * sizeof(Tcl_Size)
	    + 2 * numLists * (sizeof(Tcl_Obj **) + sizeof(Tcl_Obj *)));
    memset(statePtr, 0,
	    sizeof(struct ForeachState) + 3 * numLists * sizeof(int)
	    sizeof(struct ForeachState) + 3 * numLists * sizeof(Tcl_Size)
	    + 2 * numLists * (sizeof(Tcl_Obj **) + sizeof(Tcl_Obj *)));
    statePtr->varvList = (Tcl_Obj ***) (statePtr + 1);
    statePtr->argvList = statePtr->varvList + numLists;
    statePtr->vCopyList = (Tcl_Obj **) (statePtr->argvList + numLists);
    statePtr->aCopyList = statePtr->vCopyList + numLists;
    statePtr->index = (int *) (statePtr->aCopyList + numLists);
    statePtr->index = (Tcl_Size *) (statePtr->aCopyList + numLists);
    statePtr->varcList = statePtr->index + numLists;
    statePtr->argcList = statePtr->varcList + numLists;

    statePtr->numLists = numLists;
    statePtr->bodyPtr = objv[objc - 1];
    statePtr->bodyIdx = objc - 1;

    if (collect == TCL_EACH_COLLECT) {
	statePtr->resultList = Tcl_NewListObj(0, NULL);
    } else {
	statePtr->resultList = NULL;
    }

    /*
     * Break up the value lists and variable lists into elements.
     */

    for (i=0 ; i<numLists ; i++) {
	/* List */
	/* Variables */
	statePtr->vCopyList[i] = TclListObjCopy(interp, objv[1+i*2]);
	if (statePtr->vCopyList[i] == NULL) {
	    result = TCL_ERROR;
	    goto done;
	}
	TclListObjGetElements(NULL, statePtr->vCopyList[i],
		&statePtr->varcList[i], &statePtr->varvList[i]);
	result = TclListObjLength(interp, statePtr->vCopyList[i],
	    &statePtr->varcList[i]);
	if (result != TCL_OK) {
	    result = TCL_ERROR;
	    goto done;
	}
	if (statePtr->varcList[i] < 1) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "%s varlist is empty",
		    (statePtr->resultList != NULL ? "lmap" : "foreach")));
		"%s varlist is empty",
		(statePtr->resultList != NULL ? "lmap" : "foreach")));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION",
		    (statePtr->resultList != NULL ? "LMAP" : "FOREACH"),
		    "NEEDVARS", NULL);
		(statePtr->resultList != NULL ? "LMAP" : "FOREACH"),
		"NEEDVARS", (char *)NULL);
	    result = TCL_ERROR;
	    goto done;
	}
	TclListObjGetElements(NULL, statePtr->vCopyList[i],
	    &statePtr->varcList[i], &statePtr->varvList[i]);

	/* Values */
	if (TclObjTypeHasProc(objv[2+i*2],indexProc)) {
	    /* Special case for AbstractList */
	    statePtr->aCopyList[i] = Tcl_DuplicateObj(objv[2+i*2]);
	    if (statePtr->aCopyList[i] == NULL) {
		result = TCL_ERROR;
		goto done;
	    }
	    /* Don't compute values here, wait until the last moment */
	    statePtr->argcList[i] = TclObjTypeLength(statePtr->aCopyList[i]);
	} else {
	    /* List values */
	statePtr->aCopyList[i] = TclListObjCopy(interp, objv[2+i*2]);
	if (statePtr->aCopyList[i] == NULL) {
	    result = TCL_ERROR;
	    goto done;
	}
	TclListObjGetElements(NULL, statePtr->aCopyList[i],
	    statePtr->aCopyList[i] = TclListObjCopy(interp, objv[2+i*2]);
	    if (statePtr->aCopyList[i] == NULL) {
		result = TCL_ERROR;
		goto done;
	    }
	    result = TclListObjGetElements(interp, statePtr->aCopyList[i],
		&statePtr->argcList[i], &statePtr->argvList[i]);
	    if (result != TCL_OK) {
		goto done;

	    }
	}
	/* account for variable <> value mismatch */
	j = statePtr->argcList[i] / statePtr->varcList[i];
	if ((statePtr->argcList[i] % statePtr->varcList[i]) != 0) {
	    j++;
	}
	if (j > statePtr->maxj) {
	    statePtr->maxj = j;
	}
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
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







-
+
















-
-
+
+
+
+
+
+








/*
 * Post-body processing handler.
 */

static int
ForeachLoopStep(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    struct ForeachState *statePtr = (struct ForeachState *)data[0];

    /*
     * Process the result code from this run of the [foreach] body. Note that
     * this switch uses fallthroughs in several places. Maintainer aware!
     */

    switch (result) {
    case TCL_CONTINUE:
	result = TCL_OK;
	break;
    case TCL_OK:
	if (statePtr->resultList != NULL) {
	    Tcl_ListObjAppendElement(interp, statePtr->resultList,
		    Tcl_GetObjResult(interp));
	    result = Tcl_ListObjAppendElement(
		interp, statePtr->resultList, Tcl_GetObjResult(interp));
	    if (result != TCL_OK) {
		/* e.g. memory alloc failure on big data tests */
		goto done;
	    }
	}
	break;
    case TCL_BREAK:
	result = TCL_OK;
	goto finish;
    case TCL_ERROR:
	Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
2665
2666
2667
2668
2669
2670
2671
2672


2673
2674
2675



2676
2677
2678
2679









2680


2681
2682
2683
2684
2685
2686
2687
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







-
+
+



+
+
+


-

+
+
+
+
+
+
+
+
+
-
+
+







 */

static inline int
ForeachAssignments(
    Tcl_Interp *interp,
    struct ForeachState *statePtr)
{
    int i, v, k;
    int i;
    Tcl_Size v, k;
    Tcl_Obj *valuePtr, *varValuePtr;

    for (i=0 ; i<statePtr->numLists ; i++) {
	int isAbstractList =
		TclObjTypeHasProc(statePtr->aCopyList[i],indexProc) != NULL;

	for (v=0 ; v<statePtr->varcList[i] ; v++) {
	    k = statePtr->index[i]++;

	    if (k < statePtr->argcList[i]) {
		if (isAbstractList) {
		    if (TclObjTypeIndex(interp, statePtr->aCopyList[i], k, &valuePtr) != TCL_OK) {
			Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
				"\n    (setting %s loop variable \"%s\")",
				(statePtr->resultList != NULL ? "lmap" : "foreach"),
				TclGetString(statePtr->varvList[i][v])));
			return TCL_ERROR;
		    }
		} else {
		valuePtr = statePtr->argvList[i][k];
		    valuePtr = statePtr->argvList[i][k];
		}
	    } else {
		TclNewObj(valuePtr);	/* Empty string */
	    }

	    varValuePtr = Tcl_ObjSetVar2(interp, statePtr->varvList[i][v],
		    NULL, valuePtr, TCL_LEAVE_ERR_MSG);

2738
2739
2740
2741
2742
2743
2744
2745

2746
2747
2748
2749
2750
2751
2752
3058
3059
3060
3061
3062
3063
3064

3065
3066
3067
3068
3069
3070
3071
3072







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FormatObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *resultPtr;		/* Where result is stored finally. */

    if (objc < 2) {

Changes to generic/tclCmdIL.c.

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
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
30
31








-
-
-
-
-
-
+
+
+
+
+
+







+
+
+







/*
 * tclCmdIL.c --
 *
 *	This file contains the top-level command routines for most of the Tcl
 *	built-in commands whose names begin with the letters I through L. It
 *	contains only commands in the generic core (i.e., those that don't
 *	depend much upon UNIX facilities).
 *
 * Copyright (c) 1987-1993 The Regents of the University of California.
 * Copyright (c) 1993-1997 Lucent Technologies.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
 * Copyright (c) 2005 Donal K. Fellows.
 * Copyright © 1987-1993 The Regents of the University of California.
 * Copyright © 1993-1997 Lucent Technologies.
 * Copyright © 1994-1997 Sun Microsystems, Inc.
 * Copyright © 1998-1999 Scriptics Corporation.
 * Copyright © 2001 Kevin B. Kenny. All rights reserved.
 * Copyright © 2005 Donal K. Fellows.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclRegexp.h"
#include "tclTomMath.h"
#include <math.h>
#include <assert.h>

/*
 * During execution of the "lsort" command, structures of the following type
 * are used to arrange the objects being sorted into a collection of linked
 * lists.
 */

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
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







-
+













-
+








-
+








/*
 * These function pointer types are used with the "lsearch" and "lsort"
 * commands to facilitate the "-nocase" option.
 */

typedef int (*SortStrCmpFn_t) (const char *, const char *);
typedef int (*SortMemCmpFn_t) (const void *, const void *, size_t);
typedef int (*SortMemCmpFn_t) (const void *, const void *, Tcl_Size);

/*
 * The "lsort" command needs to pass certain information down to the function
 * that compares two list elements, and the comparison function needs to pass
 * success or failure information back up to the top-level "lsort" command.
 * The following structure is used to pass this information.
 */

typedef struct {
    int isIncreasing;		/* Nonzero means sort in increasing order. */
    int sortMode;		/* The sort mode. One of SORTMODE_* values
				 * defined below. */
    Tcl_Obj *compareCmdPtr;	/* The Tcl comparison command when sortMode is
				 * SORTMODE_COMMAND. Pre-initialized to hold
				 * SORTMODE_COMMAND. Preinitialized to hold
				 * base of command. */
    int *indexv;		/* If the -index option was specified, this
				 * holds an encoding of the indexes contained
				 * in the list supplied as an argument to
				 * that option.
				 * NULL if no indexes supplied, and points to
				 * singleIndex field when only one
				 * supplied. */
    int indexc;			/* Number of indexes in indexv array. */
    Tcl_Size indexc;		/* Number of indexes in indexv array. */
    int singleIndex;		/* Static space for common index case. */
    int unique;
    int numElements;
    Tcl_Interp *interp;		/* The interpreter in which the sort is being
				 * done. */
    int resultCode;		/* Completion code for the lsort command. If
				 * an error occurs during the sort this is
89
90
91
92
93
94
95













96
97
98
99
100
101
102
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







+
+
+
+
+
+
+
+
+
+
+
+
+







#define SORTMODE_ASCII		0
#define SORTMODE_INTEGER	1
#define SORTMODE_REAL		2
#define SORTMODE_COMMAND	3
#define SORTMODE_DICTIONARY	4
#define SORTMODE_ASCII_NC	8

/*
 * Definitions for [lseq] command
 */
static const char *const seq_operations[] = {
    "..", "to", "count", "by", NULL
};
typedef enum {
    LSEQ_DOTS, LSEQ_TO, LSEQ_COUNT, LSEQ_BY
} SequenceOperators;
typedef enum {
     NoneArg, NumericArg, RangeKeywordArg, ErrArg, LastArg = 8
} SequenceDecoded;

/*
 * Forward declarations for procedures defined in this file:
 */

static int		DictionaryCompare(const char *left, const char *right);
static Tcl_NRPostProc	IfConditionCallback;
static Tcl_ObjCmdProc	InfoArgsCmd;
136
137
138
139
140
141
142


143
144
145
146
147
148
149
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167







+
+







static const EnsembleImplMap defaultInfoMap[] = {
    {"args",		   InfoArgsCmd,		    TclCompileBasic1ArgCmd, NULL, NULL, 0},
    {"body",		   InfoBodyCmd,		    TclCompileBasic1ArgCmd, NULL, NULL, 0},
    {"cmdcount",	   InfoCmdCountCmd,	    TclCompileBasic0ArgCmd, NULL, NULL, 0},
    {"cmdtype",		   InfoCmdTypeCmd,	    TclCompileBasic1ArgCmd, NULL, NULL, 1},
    {"commands",	   InfoCommandsCmd,	    TclCompileInfoCommandsCmd, NULL, NULL, 0},
    {"complete",	   InfoCompleteCmd,	    TclCompileBasic1ArgCmd, NULL, NULL, 0},
    {"constant",	   TclInfoConstantCmd,	    TclCompileBasic1ArgCmd, NULL, NULL, 0},
    {"consts",		   TclInfoConstsCmd,	    TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
    {"coroutine",	   TclInfoCoroutineCmd,     TclCompileInfoCoroutineCmd, NULL, NULL, 0},
    {"default",		   InfoDefaultCmd,	    TclCompileBasic3ArgCmd, NULL, NULL, 0},
    {"errorstack",	   InfoErrorStackCmd,	    TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
    {"exists",		   TclInfoExistsCmd,	    TclCompileInfoExistsCmd, NULL, NULL, 0},
    {"frame",		   InfoFrameCmd,	    TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
    {"functions",	   InfoFunctionsCmd,	    TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
    {"globals",		   TclInfoGlobalsCmd,	    TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
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
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







-
+









-
+










-
+











-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_IfObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, TclNRIfObjCmd, clientData, objc, objv);
}

int
TclNRIfObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *boolObj;

    if (objc <= 1) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"wrong # args: no expression after \"%s\" argument",
		TclGetString(objv[0])));
	Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL);
	Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * At this point, objv[1] refers to the main expression to test. The
     * arguments after the expression must be "then" (optional) and a script
     * to execute if the expression is true.
     */

    TclNewObj(boolObj);
    Tcl_NRAddCallback(interp, IfConditionCallback, INT2PTR(objc),
	    (ClientData) objv, INT2PTR(1), boolObj);
	    (void *) objv, INT2PTR(1), boolObj);
    return Tcl_NRExprObj(interp, objv[1], boolObj);
}

static int
IfConditionCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    int objc = PTR2INT(data[0]);
    Tcl_Obj *const *objv = (Tcl_Obj *const *)data[1];
    int i = PTR2INT(data[2]);
293
294
295
296
297
298
299
300

301
302
303
304
305
306
307
311
312
313
314
315
316
317

318
319
320
321
322
323
324
325







-
+







	 * (optional) and a script to execute if the expression is true.
	 */

	if (i >= objc) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "wrong # args: no expression after \"%s\" argument",
		    clause));
	    Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (char *)NULL);
	    return TCL_ERROR;
	}
	if (!thenScriptIndex) {
	    TclNewObj(boolObj);
	    Tcl_NRAddCallback(interp, IfConditionCallback, data[0], data[1],
		    INT2PTR(i), boolObj);
	    return Tcl_NRExprObj(interp, objv[i], boolObj);
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
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







-
+
















-
+







	    goto missingScript;
	}
    }
    if (i < objc - 1) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"wrong # args: extra words after \"else\" clause in \"if\" command",
		-1));
	Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL);
	Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (char *)NULL);
	return TCL_ERROR;
    }
    if (thenScriptIndex) {
	/*
	 * TIP #280. Make invoking context available to branch/else.
	 */

	return TclNREvalObjEx(interp, objv[thenScriptIndex], 0,
		iPtr->cmdFramePtr, thenScriptIndex);
    }
    return TclNREvalObjEx(interp, objv[i], 0, iPtr->cmdFramePtr, i);

  missingScript:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "wrong # args: no script following \"%s\" argument",
	    TclGetString(objv[i-1])));
    Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL);
    Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_IncrObjCmd --
364
365
366
367
368
369
370
371

372
373
374
375
376
377
378
382
383
384
385
386
387
388

389
390
391
392
393
394
395
396







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_IncrObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *newValuePtr, *incrPtr;

    if ((objc != 2) && (objc != 3)) {
445
446
447
448
449
450
451
452

453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473

474
475
476
477
478
479
480
463
464
465
466
467
468
469

470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490

491
492
493
494
495
496
497
498







-
+




















-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoArgsCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    const char *name;
    Proc *procPtr;
    CompiledLocal *localPtr;
    Tcl_Obj *listObjPtr;

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

    name = TclGetString(objv[1]);
    procPtr = TclFindProc(iPtr, name);
    if (procPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"\"%s\" isn't a procedure", name));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PROCEDURE", name, NULL);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PROCEDURE", name, (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Build a return list containing the arguments.
     */

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
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
558
559
560







-
+







-
+











-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoBodyCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    const char *name, *bytes;
    Proc *procPtr;
    size_t numBytes;
    Tcl_Size numBytes;

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

    name = TclGetString(objv[1]);
    procPtr = TclFindProc(iPtr, name);
    if (procPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"\"%s\" isn't a procedure", name));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PROCEDURE", name, NULL);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PROCEDURE", name, (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Here we used to return procPtr->bodyPtr, except when the body was
     * bytecompiled - in that case, the return was a copy of the body's string
     * rep. In order to better isolate the implementation details of the
569
570
571
572
573
574
575
576

577
578
579
580
581
582
583
587
588
589
590
591
592
593

594
595
596
597
598
599
600
601







-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoCmdCountCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;

    if (objc != 1) {
611
612
613
614
615
616
617
618

619
620
621
622
623
624
625
626
627
628
629
630
631
632
633

634
635
636
637
638
639
640
629
630
631
632
633
634
635

636
637
638
639
640
641
642
643
644
645
646
647
648
649
650

651
652
653
654
655
656
657
658







-
+














-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoCommandsCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *cmdName, *pattern;
    const char *simplePattern;
    Tcl_HashEntry *entryPtr;
    Tcl_HashSearch search;
    Namespace *nsPtr;
    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
    Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
    Tcl_Obj *listPtr, *elemObjPtr;
    int specificNsInPattern = 0;/* Init. to avoid compiler warning. */
    Tcl_Command cmd;
    size_t i;
    Tcl_Size i;

    /*
     * Get the pattern and find the "effective namespace" in which to list
     * commands.
     */

    if (objc == 1) {
687
688
689
690
691
692
693
694

695
696
697
698
699
700
701
705
706
707
708
709
710
711

712
713
714
715
716
717
718
719







-
+







	 * special characters. This lets us avoid scans of any hash tables.
	 */

	entryPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, simplePattern);
	if (entryPtr != NULL) {
	    if (specificNsInPattern) {
		cmd = (Tcl_Command)Tcl_GetHashValue(entryPtr);
		elemObjPtr = Tcl_NewObj();
		TclNewObj(elemObjPtr);
		Tcl_GetCommandFullName(interp, cmd, elemObjPtr);
	    } else {
		cmdName = (const char *)Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr);
		elemObjPtr = Tcl_NewStringObj(cmdName, -1);
	    }
	    Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
	    Tcl_SetObjResult(interp, listPtr);
738
739
740
741
742
743
744
745

746
747
748
749
750
751
752
756
757
758
759
760
761
762

763
764
765
766
767
768
769
770







-
+







	entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
	while (entryPtr != NULL) {
	    cmdName = (const char *)Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr);
	    if ((simplePattern == NULL)
		    || Tcl_StringMatch(cmdName, simplePattern)) {
		if (specificNsInPattern) {
		    cmd = (Tcl_Command)Tcl_GetHashValue(entryPtr);
		    elemObjPtr = Tcl_NewObj();
		    TclNewObj(elemObjPtr);
		    Tcl_GetCommandFullName(interp, cmd, elemObjPtr);
		} else {
		    elemObjPtr = Tcl_NewStringObj(cmdName, -1);
		}
		Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
	    }
	    entryPtr = Tcl_NextHashEntry(&search);
848
849
850
851
852
853
854
855

856
857
858
859
860
861
862
866
867
868
869
870
871
872

873
874
875
876
877
878
879
880







-
+







	    entryPtr = Tcl_FirstHashEntry(&globalNsPtr->cmdTable, &search);
	    while (entryPtr != NULL) {
		cmdName = (const char *)Tcl_GetHashKey(&globalNsPtr->cmdTable, entryPtr);
		if ((simplePattern == NULL)
			|| Tcl_StringMatch(cmdName, simplePattern)) {
		    elemObjPtr = Tcl_NewStringObj(cmdName, -1);
		    if (Tcl_FindHashEntry(&addedCommandsTable,
			    (char *) elemObjPtr) == NULL) {
			    elemObjPtr) == NULL) {
			Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
		    } else {
			TclDecrRefCount(elemObjPtr);
		    }
		}
		entryPtr = Tcl_NextHashEntry(&search);
	    }
888
889
890
891
892
893
894
895

896
897
898
899
900
901
902
906
907
908
909
910
911
912

913
914
915
916
917
918
919
920







-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoCompleteCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "command");
	return TCL_ERROR;
925
926
927
928
929
930
931
932

933
934
935
936
937
938
939
943
944
945
946
947
948
949

950
951
952
953
954
955
956
957







-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoDefaultCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    const char *procName, *argName;
    Proc *procPtr;
949
950
951
952
953
954
955
956

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
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







-
+













-
+

-
+
+






-
+








-
+







    argName = TclGetString(objv[2]);

    procPtr = TclFindProc(iPtr, procName);
    if (procPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"\"%s\" isn't a procedure", procName));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PROCEDURE", procName,
		NULL);
		(char *)NULL);
	return TCL_ERROR;
    }

    for (localPtr = procPtr->firstLocalPtr;  localPtr != NULL;
	    localPtr = localPtr->nextPtr) {
	if (TclIsVarArgument(localPtr)
		&& (strcmp(argName, localPtr->name) == 0)) {
	    if (localPtr->defValuePtr != NULL) {
		valueObjPtr = Tcl_ObjSetVar2(interp, objv[3], NULL,
			localPtr->defValuePtr, TCL_LEAVE_ERR_MSG);
		if (valueObjPtr == NULL) {
		    return TCL_ERROR;
		}
		Tcl_SetObjResult(interp, Tcl_NewWideIntObj(1));
		Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
	    } else {
		Tcl_Obj *nullObjPtr = Tcl_NewObj();
		Tcl_Obj *nullObjPtr;
		TclNewObj(nullObjPtr);

		valueObjPtr = Tcl_ObjSetVar2(interp, objv[3], NULL,
			nullObjPtr, TCL_LEAVE_ERR_MSG);
		if (valueObjPtr == NULL) {
		    return TCL_ERROR;
		}
		Tcl_SetObjResult(interp, Tcl_NewWideIntObj(0));
		Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
	    }
	    return TCL_OK;
	}
    }

    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "procedure \"%s\" doesn't have an argument \"%s\"",
	    procName, argName));
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARGUMENT", argName, NULL);
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARGUMENT", argName, (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * InfoErrorStackCmd --
1007
1008
1009
1010
1011
1012
1013
1014

1015
1016
1017
1018
1019
1020
1021
1026
1027
1028
1029
1030
1031
1032

1033
1034
1035
1036
1037
1038
1039
1040







-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoErrorStackCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Interp *target;
    Interp *iPtr;

1056
1057
1058
1059
1060
1061
1062
1063

1064
1065
1066
1067
1068
1069
1070
1075
1076
1077
1078
1079
1080
1081

1082
1083
1084
1085
1086
1087
1088
1089







-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

int
TclInfoExistsCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *varName;
    Var *varPtr;

1101
1102
1103
1104
1105
1106
1107
1108

1109
1110
1111
1112
1113
1114
1115
1120
1121
1122
1123
1124
1125
1126

1127
1128
1129
1130
1131
1132
1133
1134







-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoFrameCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    int level, code = TCL_OK;
    CmdFrame *framePtr, **cmdFramePtrPtr = &iPtr->cmdFramePtr;
1127
1128
1129
1130
1131
1132
1133
1134

1135
1136

1137
1138
1139
1140
1141
1142
1143
1146
1147
1148
1149
1150
1151
1152

1153
1154

1155
1156
1157
1158
1159
1160
1161
1162







-
+

-
+







	    cmdFramePtrPtr = &((*cmdFramePtrPtr)->nextPtr);
	}
	if (corPtr->caller.cmdFramePtr) {
	    *cmdFramePtrPtr = corPtr->caller.cmdFramePtr;
	}
	corPtr = corPtr->callerEEPtr->corPtr;
    }
    topLevel += (*cmdFramePtrPtr)->level;
    topLevel += *cmdFramePtrPtr ? (*cmdFramePtrPtr)->level : 1;

    if (topLevel != iPtr->cmdFramePtr->level) {
    if (iPtr->cmdFramePtr && topLevel != iPtr->cmdFramePtr->level) {
	framePtr = iPtr->cmdFramePtr;
	while (framePtr) {
	    framePtr->level = topLevel--;
	    framePtr = framePtr->nextPtr;
	}
	if (topLevel) {
	    Tcl_Panic("Broken frame level calculation");
1164
1165
1166
1167
1168
1169
1170
1171

1172
1173
1174
1175
1176
1177
1178
1183
1184
1185
1186
1187
1188
1189

1190
1191
1192
1193
1194
1195
1196
1197







-
+







    }

    if ((level > topLevel) || (level <= - topLevel)) {
    levelError:
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"bad level \"%s\"", TclGetString(objv[1])));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LEVEL",
		TclGetString(objv[1]), NULL);
		TclGetString(objv[1]), (char *)NULL);
	code = TCL_ERROR;
	goto done;
    }

    /*
     * Let us convert to relative so that we know how many levels to go back
     */
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
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







-
+









-
+


+
+
+
+
+







Tcl_Obj *
TclInfoFrame(
    Tcl_Interp *interp,		/* Current interpreter. */
    CmdFrame *framePtr)		/* Frame to get info for. */
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *tmpObj;
    Tcl_Obj *lv[20];		/* Keep uptodate when more keys are added to
    Tcl_Obj *lv[20] = {NULL};		/* Keep uptodate when more keys are added to
				 * the dict. */
    int lc = 0;
    /*
     * This array is indexed by the TCL_LOCATION_... values, except
     * for _LAST.
     */
    static const char *const typeString[TCL_LOCATION_LAST] = {
	"eval", "eval", "eval", "precompiled", "source", "proc"
    };
    Proc *procPtr = framePtr->framePtr ? framePtr->framePtr->procPtr : NULL;
    Proc *procPtr = NULL;
    int needsFree = -1;

    if (!framePtr) {
	goto precompiled;
    }
    procPtr = framePtr->framePtr ? framePtr->framePtr->procPtr : NULL;

    /*
     * Pull the information and construct the dictionary to return, as list.
     * Regarding use of the CmdFrame fields see tclInt.h, and its definition.
     */

#define ADD_PAIR(name, value) \
	TclNewLiteralStringObj(tmpObj, name); \
1276
1277
1278
1279
1280
1281
1282

1283
1284
1285
1286
1287

1288
1289
1290
1291
1292
1293
1294
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310


1311
1312
1313
1314
1315
1316
1317
1318







+



-
-
+







	} else {
	    ADD_PAIR("line", Tcl_NewWideIntObj(1));
	}
	ADD_PAIR("cmd", TclGetSourceFromFrame(framePtr, 0, NULL));
	break;

    case TCL_LOCATION_PREBC:
      precompiled:
	/*
	 * Precompiled. Result contains the type as signal, nothing else.
	 */

	ADD_PAIR("type", Tcl_NewStringObj(typeString[framePtr->type], -1));
	ADD_PAIR("type", Tcl_NewStringObj(typeString[TCL_LOCATION_PREBC], -1));
	break;

    case TCL_LOCATION_BC: {
	/*
	 * Execution of bytecode. Talk to the BC engine to fill out the frame.
	 */

1371
1372
1373
1374
1375
1376
1377
1378

1379
1380
1381
1382
1383
1384
1385
1395
1396
1397
1398
1399
1400
1401

1402
1403
1404
1405
1406
1407
1408
1409







-
+








	    TclNewObj(procNameObj);
	    Tcl_GetCommandFullName(interp, (Tcl_Command) procPtr->cmdPtr,
		    procNameObj);
	    ADD_PAIR("proc", procNameObj);
	} else if (procPtr->cmdPtr->clientData) {
	    ExtraFrameInfo *efiPtr = (ExtraFrameInfo *)procPtr->cmdPtr->clientData;
	    size_t i;
	    Tcl_Size i;

	    /*
	     * This is a non-standard command. Luckily, it's told us how to
	     * render extra information about its frame.
	     */

	    for (i=0 ; i<efiPtr->length ; i++) {
1395
1396
1397
1398
1399
1400
1401
1402

1403
1404
1405
1406
1407
1408
1409
1419
1420
1421
1422
1423
1424
1425

1426
1427
1428
1429
1430
1431
1432
1433







-
+







    }

    /*
     * 'level'. Common to all frame types. Conditional on having an associated
     * _visible_ CallFrame.
     */

    if ((framePtr->framePtr != NULL) && (iPtr->varFramePtr != NULL)) {
    if (framePtr && (framePtr->framePtr != NULL) && (iPtr->varFramePtr != NULL)) {
	CallFrame *current = framePtr->framePtr;
	CallFrame *top = iPtr->varFramePtr;
	CallFrame *idx;

	for (idx=top ; idx!=NULL ; idx=idx->callerVarPtr) {
	    if (idx == current) {
		int c = framePtr->framePtr->level;
1441
1442
1443
1444
1445
1446
1447
1448

1449
1450
1451
1452
1453
1454
1455
1465
1466
1467
1468
1469
1470
1471

1472
1473
1474
1475
1476
1477
1478
1479







-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoFunctionsCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *script;
    int code;

1506
1507
1508
1509
1510
1511
1512
1513

1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533

1534
1535
1536
1537
1538
1539
1540
1530
1531
1532
1533
1534
1535
1536

1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556

1557
1558
1559
1560
1561
1562
1563
1564







-
+



















-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoHostnameCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *name;

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

    name = Tcl_GetHostName();
    if (name) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(name, -1));
	return TCL_OK;
    }

    Tcl_SetObjResult(interp, Tcl_NewStringObj(
	    "unable to determine name of host", -1));
    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "HOSTNAME", "UNKNOWN", NULL);
    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "HOSTNAME", "UNKNOWN", (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * InfoLevelCmd --
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
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







-
+







-
+


















-
+



















-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoLevelCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;

    if (objc == 1) {		/* Just "info level" */
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iPtr->varFramePtr->level));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj((int)iPtr->varFramePtr->level));
	return TCL_OK;
    }

    if (objc == 2) {
	int level;
	CallFrame *framePtr, *rootFramePtr = iPtr->rootFramePtr;

	if (TclGetIntFromObj(interp, objv[1], &level) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (level <= 0) {
	    if (iPtr->varFramePtr == rootFramePtr) {
		goto levelError;
	    }
	    level += iPtr->varFramePtr->level;
	}
	for (framePtr=iPtr->varFramePtr ; framePtr!=rootFramePtr;
		framePtr=framePtr->callerVarPtr) {
	    if (framePtr->level == level) {
	    if ((int)framePtr->level == level) {
		break;
	    }
	}
	if (framePtr == rootFramePtr) {
	    goto levelError;
	}

	Tcl_SetObjResult(interp,
		Tcl_NewListObj(framePtr->objc, framePtr->objv));
	return TCL_OK;
    }

    Tcl_WrongNumArgs(interp, 1, objv, "?number?");
    return TCL_ERROR;

  levelError:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "bad level \"%s\"", TclGetString(objv[1])));
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LEVEL",
	    TclGetString(objv[1]), NULL);
	    TclGetString(objv[1]), (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * InfoLibraryCmd --
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
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







-
+



















-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoLibraryCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *libDirName;

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

    libDirName = Tcl_GetVar2(interp, "tcl_library", NULL, TCL_GLOBAL_ONLY);
    if (libDirName != NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(libDirName, -1));
	return TCL_OK;
    }

    Tcl_SetObjResult(interp, Tcl_NewStringObj(
	    "no library has been specified for Tcl", -1));
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", "tcl_library",NULL);
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", "tcl_library", (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * InfoLoadedCmd --
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
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







-
+




-
+


-
+









-
+

-
+

-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoLoadedCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *interpName, *packageName;
    const char *interpName, *prefix;

    if (objc > 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "?interp? ?packageName?");
	Tcl_WrongNumArgs(interp, 1, objv, "?interp? ?prefix?");
	return TCL_ERROR;
    }

    if (objc < 2) {		/* Get loaded pkgs in all interpreters. */
	interpName = NULL;
    } else {			/* Get pkgs just in specified interp. */
	interpName = TclGetString(objv[1]);
    }
    if (objc < 3) {		/* Get loaded files in all packages. */
	packageName = NULL;
	prefix = NULL;
    } else {			/* Get pkgs just in specified interp. */
	packageName = TclGetString(objv[2]);
	prefix = TclGetString(objv[2]);
    }
    return TclGetLoadedPackagesEx(interp, interpName, packageName);
    return TclGetLoadedLibraries(interp, interpName, prefix);
}

/*
 *----------------------------------------------------------------------
 *
 * InfoNameOfExecutableCmd --
 *
1721
1722
1723
1724
1725
1726
1727
1728

1729
1730
1731
1732
1733
1734
1735
1745
1746
1747
1748
1749
1750
1751

1752
1753
1754
1755
1756
1757
1758
1759







-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoNameOfExecutableCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
1757
1758
1759
1760
1761
1762
1763
1764

1765
1766
1767
1768
1769
1770
1771
1781
1782
1783
1784
1785
1786
1787

1788
1789
1790
1791
1792
1793
1794
1795







-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoPatchLevelCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *patchlevel;

    if (objc != 1) {
1804
1805
1806
1807
1808
1809
1810
1811

1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1828
1829
1830
1831
1832
1833
1834

1835
1836
1837
1838
1839
1840
1841
1842



1843
1844
1845
1846
1847
1848
1849







-
+







-
-
-







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoProcsCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *cmdName, *pattern;
    const char *simplePattern;
    Namespace *nsPtr;
#ifdef INFO_PROCS_SEARCH_GLOBAL_NS
    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
#endif
    Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
    Tcl_Obj *listPtr, *elemObjPtr;
    int specificNsInPattern = 0;/* Init. to avoid compiler warning. */
    Tcl_HashEntry *entryPtr;
    Tcl_HashSearch search;
    Command *cmdPtr, *realCmdPtr;

1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
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







-














-
+








-
+
-
-
















-
+










-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







     * Scan through the effective namespace's command table and create a list
     * with all procs that match the pattern. If a specific namespace was
     * requested in the pattern, qualify the command names with the namespace
     * name.
     */

    listPtr = Tcl_NewListObj(0, NULL);
#ifndef INFO_PROCS_SEARCH_GLOBAL_NS
    if (simplePattern != NULL && TclMatchIsTrivial(simplePattern)) {
	entryPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, simplePattern);
	if (entryPtr != NULL) {
	    cmdPtr = (Command *)Tcl_GetHashValue(entryPtr);

	    if (!TclIsProc(cmdPtr)) {
		realCmdPtr = (Command *)
			TclGetOriginalCommand((Tcl_Command) cmdPtr);
		if (realCmdPtr != NULL && TclIsProc(realCmdPtr)) {
		    goto simpleProcOK;
		}
	    } else {
	    simpleProcOK:
		if (specificNsInPattern) {
		    elemObjPtr = Tcl_NewObj();
		    TclNewObj(elemObjPtr);
		    Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr,
			    elemObjPtr);
		} else {
		    elemObjPtr = Tcl_NewStringObj(simplePattern, -1);
		}
		Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
	    }
	}
    } else
    } else {
#endif /* !INFO_PROCS_SEARCH_GLOBAL_NS */
    {
	entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
	while (entryPtr != NULL) {
	    cmdName = (const char *)Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr);
	    if ((simplePattern == NULL)
		    || Tcl_StringMatch(cmdName, simplePattern)) {
		cmdPtr = (Command *)Tcl_GetHashValue(entryPtr);

		if (!TclIsProc(cmdPtr)) {
		    realCmdPtr = (Command *)
			    TclGetOriginalCommand((Tcl_Command) cmdPtr);
		    if (realCmdPtr != NULL && TclIsProc(realCmdPtr)) {
			goto procOK;
		    }
		} else {
		procOK:
		    if (specificNsInPattern) {
			elemObjPtr = Tcl_NewObj();
			TclNewObj(elemObjPtr);
			Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr,
				elemObjPtr);
		    } else {
			elemObjPtr = Tcl_NewStringObj(cmdName, -1);
		    }
		    Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
		}
	    }
	    entryPtr = Tcl_NextHashEntry(&search);
	}

	/*
	 * If the effective namespace isn't the global :: namespace, and a
	 * specific namespace wasn't requested in the pattern, then add in all
	 * global :: procs that match the simple pattern. Of course, we add in
	 * only those procs that aren't hidden by a proc in the effective
	 * namespace.
	 */

#ifdef INFO_PROCS_SEARCH_GLOBAL_NS
	/*
	 * If "info procs" worked like "info commands", returning the commands
	 * also seen in the global namespace, then you would include this
	 * code. As this could break backwards compatibility with 8.0-8.2, we
	 * decided not to "fix" it in 8.3, leaving the behavior slightly
	 * different.
	 */

	if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
	    entryPtr = Tcl_FirstHashEntry(&globalNsPtr->cmdTable, &search);
	    while (entryPtr != NULL) {
		cmdName = (const char *)Tcl_GetHashKey(&globalNsPtr->cmdTable, entryPtr);
		if ((simplePattern == NULL)
			|| Tcl_StringMatch(cmdName, simplePattern)) {
		    if (Tcl_FindHashEntry(&nsPtr->cmdTable,cmdName) == NULL) {
			cmdPtr = (Command *)Tcl_GetHashValue(entryPtr);
			realCmdPtr = (Command *) TclGetOriginalCommand(
				(Tcl_Command) cmdPtr);

			if (TclIsProc(cmdPtr) || ((realCmdPtr != NULL)
				&& TclIsProc(realCmdPtr))) {
			    Tcl_ListObjAppendElement(interp, listPtr,
				    Tcl_NewStringObj(cmdName, -1));
			}
		    }
		}
		entryPtr = Tcl_NextHashEntry(&search);
	    }
	}
#endif
    }

    Tcl_SetObjResult(interp, listPtr);
    return TCL_OK;
}

/*
1991
1992
1993
1994
1995
1996
1997
1998

1999
2000
2001
2002
2003
2004
2005
1969
1970
1971
1972
1973
1974
1975

1976
1977
1978
1979
1980
1981
1982
1983







-
+







 *	script filename.
 *
 *----------------------------------------------------------------------
 */

static int
InfoScriptCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;

    if ((objc != 1) && (objc != 2)) {
2039
2040
2041
2042
2043
2044
2045
2046

2047
2048
2049
2050
2051
2052
2053
2017
2018
2019
2020
2021
2022
2023

2024
2025
2026
2027
2028
2029
2030
2031







-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoSharedlibCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
2077
2078
2079
2080
2081
2082
2083
2084

2085
2086
2087
2088
2089
2090
2091
2055
2056
2057
2058
2059
2060
2061

2062
2063
2064
2065
2066
2067
2068
2069







-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoTclVersionCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *version;

    if (objc != 1) {
2120
2121
2122
2123
2124
2125
2126
2127

2128
2129
2130
2131
2132
2133
2134
2098
2099
2100
2101
2102
2103
2104

2105
2106
2107
2108
2109
2110
2111
2112







-
+







 *	message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoCmdTypeCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Command command;

    if (objc != 2) {
2144
2145
2146
2147
2148
2149
2150
2151

2152
2153
2154
2155
2156
2157
2158
2122
2123
2124
2125
2126
2127
2128

2129
2130
2131
2132
2133
2134
2135
2136







-
+







    /*
     * There's one special case: safe child interpreters can't see aliases as
     * aliases as they're part of the security mechanisms.
     */

    if (Tcl_IsSafe(interp)
	    && (((Command *) command)->objProc == TclAliasObjCmd)) {
	Tcl_AppendResult(interp, "native", NULL);
	Tcl_AppendResult(interp, "native", (char *)NULL);
    } else {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj(TclGetCommandTypeName(command), -1));
    }
    return TCL_OK;
}

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

2222
2223
2224
2225
2226
2227
2228
2149
2150
2151
2152
2153
2154
2155

2156
2157
2158
2159
2160


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
2222







-
+




-
-
+
+












+
+
+
+
+
+
+
-
+










+
-
+
+
+
+
+
+
+
+
+






-
+



-
+

-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_JoinObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    size_t length;
    int listLen;
    Tcl_Size length, listLen;
    int isAbstractList = 0;
    Tcl_Obj *resObjPtr = NULL, *joinObjPtr, **elemPtrs;

    if ((objc < 2) || (objc > 3)) {
	Tcl_WrongNumArgs(interp, 1, objv, "list ?joinString?");
	return TCL_ERROR;
    }

    /*
     * Make sure the list argument is a list object and get its length and a
     * pointer to its array of element pointers.
     */

    if (TclObjTypeHasProc(objv[1], getElementsProc)) {
	listLen = TclObjTypeLength(objv[1]);
	isAbstractList = (listLen ? 1 : 0);
	if (listLen > 1 && TclObjTypeGetElements(interp, objv[1],
		&listLen, &elemPtrs) != TCL_OK) {
	    return TCL_ERROR;
	}
    if (TclListObjGetElements(interp, objv[1], &listLen,
    } else if (TclListObjGetElements(interp, objv[1], &listLen,
	    &elemPtrs) != TCL_OK) {
	return TCL_ERROR;
    }

    if (listLen == 0) {
	/* No elements to join; default empty result is correct. */
	return TCL_OK;
    }
    if (listLen == 1) {
	/* One element; return it */
	if (!isAbstractList) {
	Tcl_SetObjResult(interp, elemPtrs[0]);
	    Tcl_SetObjResult(interp, elemPtrs[0]);
	} else {
	    Tcl_Obj *elemObj;

	    if (TclObjTypeIndex(interp, objv[1], 0, &elemObj) != TCL_OK) {
		return TCL_ERROR;
	    }
	    Tcl_SetObjResult(interp, elemObj);
	}
	return TCL_OK;
    }

    joinObjPtr = (objc == 2) ? Tcl_NewStringObj(" ", 1) : objv[2];
    Tcl_IncrRefCount(joinObjPtr);

    (void) TclGetStringFromObj(joinObjPtr, &length);
    (void)TclGetStringFromObj(joinObjPtr, &length);
    if (length == 0) {
	resObjPtr = TclStringCat(interp, listLen, elemPtrs, 0);
    } else {
	int i;
	Tcl_Size i;

	resObjPtr = Tcl_NewObj();
	TclNewObj(resObjPtr);
	for (i = 0;  i < listLen;  i++) {
	    if (i > 0) {

		/*
		 * NOTE: This code is relying on Tcl_AppendObjToObj() **NOT**
		 * to shimmer joinObjPtr.  If it did, then the case where
		 * objv[1] and objv[2] are the same value would not be safe.
2257
2258
2259
2260
2261
2262
2263
2264

2265
2266
2267
2268
2269

2270
2271
2272



2273
2274
2275
2276
2277
2278








2279
2280



2281
2282
2283

2284
2285
2286
2287


2288
2289












2290

2291

2292


2293
2294
2295



2296
2297


2298
2299
2300
2301
2302

2303
2304

2305

2306
2307
2308
2309
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
2251
2252
2253
2254
2255
2256
2257

2258
2259
2260
2261
2262

2263



2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280


2281
2282
2283
2284
2285

2286

2287
2288
2289
2290
2291


2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305

2306
2307
2308
2309



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







-
+




-
+
-
-
-
+
+
+






+
+
+
+
+
+
+
+
-
-
+
+
+


-
+
-



+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+

+
-
+

+
+
-
-
-
+
+
+
-
-
+
+




-
+


+
-
+





-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
+

-
+



















-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LassignObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *listCopyPtr;
    Tcl_Obj *listPtr;
    Tcl_Obj **listObjv;		/* The contents of the list. */
    int listObjc;		/* The length of the list. */
    int code = TCL_OK;
    Tcl_Size listObjc;		/* The length of the list. */
    Tcl_Size origListObjc;	/* Original length */
    int i;

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

    /*
     * Note: no need to Dup the list to avoid shimmering. That is only
     * needed when Tcl_ListObjGetElements is used since that returns
     * pointers to internal structures. Using Tcl_ListObjIndex does not
     * have that problem. However, we now have to IncrRef each elemObj
     * (see below). I see that as preferable as duping lists is potentially
     * expensive for abstract lists when they have a string representation.
     */
    listCopyPtr = TclListObjCopy(interp, objv[1]);
    if (listCopyPtr == NULL) {
    listPtr = objv[1];

    if (TclListObjLength(interp, listPtr, &listObjc) != TCL_OK) {
	return TCL_ERROR;
    }

    origListObjc = listObjc;
    TclListObjGetElements(NULL, listCopyPtr, &listObjc, &listObjv);

    objc -= 2;
    objv += 2;
    for (i = 0; i < objc && i < listObjc; ++i) {
	Tcl_Obj *elemObj;
    while (code == TCL_OK && objc > 0 && listObjc > 0) {
	if (Tcl_ObjSetVar2(interp, *objv++, NULL, *listObjv++,

	if (Tcl_ListObjIndex(interp, listPtr, i, &elemObj) != TCL_OK) {
	    return TCL_ERROR;
	}
	/*
	 * Must incrref elemObj. If the var name being set is same as the
	 * list value, ObjSetVar2 will shimmer the list to a VAR freeing
	 * the elements in the list (in case list refCount was 1) BEFORE
	 * the elemObj is stored in the var. See tests 6.{25,26}
	 */
	Tcl_IncrRefCount(elemObj);
	if (Tcl_ObjSetVar2(interp, *objv++, NULL, elemObj,
		TCL_LEAVE_ERR_MSG) == NULL) {
	    Tcl_DecrRefCount(elemObj);
	    code = TCL_ERROR;
	    return TCL_ERROR;
	}
	Tcl_DecrRefCount(elemObj);
    }
	objc--;
	listObjc--;
    }
    objc -= i;
    listObjc -= i;


    if (code == TCL_OK && objc > 0) {
    if (objc > 0) {
	/* Still some variables left to be assigned */
	Tcl_Obj *emptyObj;

	TclNewObj(emptyObj);
	Tcl_IncrRefCount(emptyObj);
	while (code == TCL_OK && objc-- > 0) {
	while (objc-- > 0) {
	    if (Tcl_ObjSetVar2(interp, *objv++, NULL, emptyObj,
		    TCL_LEAVE_ERR_MSG) == NULL) {
		Tcl_DecrRefCount(emptyObj);
		code = TCL_ERROR;
		return TCL_ERROR;
	    }
	}
	Tcl_DecrRefCount(emptyObj);
    }

    if (code == TCL_OK && listObjc > 0) {
	Tcl_SetObjResult(interp, Tcl_NewListObj(listObjc, listObjv));
    if (listObjc > 0) {
	Tcl_Obj *resultObjPtr = NULL;
	Tcl_Size fromIdx = origListObjc - listObjc;
	Tcl_Size toIdx = origListObjc - 1;
	if (TclObjTypeHasProc(listPtr, sliceProc)) {
	    if (TclObjTypeSlice(
		    interp, listPtr, fromIdx, toIdx, &resultObjPtr) != TCL_OK) {
		return TCL_ERROR;
	    }
	} else {
	    resultObjPtr = TclListObjRange(
		interp, listPtr, origListObjc - listObjc, origListObjc - 1);
	    if (resultObjPtr == NULL) {
		return TCL_ERROR;
	    }
	}
	Tcl_SetObjResult(interp, resultObjPtr);
    }

    Tcl_DecrRefCount(listCopyPtr);
    return code;
    return TCL_OK;
}


/*
 *----------------------------------------------------------------------
 *
 * Tcl_LindexObjCmd --
 *
 *	This object-based procedure is invoked to process the "lindex" Tcl
 *	command. See the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LindexObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *elemPtr;		/* Pointer to the element being extracted. */

    if (objc < 2) {
2389
2390
2391
2392
2393
2394
2395
2396

2397
2398
2399
2400
2401
2402
2403


2404
2405
2406
2407
2408
2409
2410
2421
2422
2423
2424
2425
2426
2427

2428
2429
2430
2431
2432
2433


2434
2435
2436
2437
2438
2439
2440
2441
2442







-
+





-
-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LinsertObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,		/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *listPtr;
    size_t index;
    int len, result;
    Tcl_Size len, index;
    int copied = 0, result;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "list index ?element ...?");
	return TCL_ERROR;
    }

    result = TclListObjLength(interp, objv[1], &len);
2418
2419
2420
2421
2422
2423
2424
2425

2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436

2437
2438
2439

2440
2441
2442
2443
2444







2445
2446
2447



2448
2449
2450
2451
2452
2453
2454
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
2489
2490
2491
2492
2493
2494
2495
2496







-
+











+


-
+




-
+
+
+
+
+
+
+



+
+
+







     * appended to the list.
     */

    result = TclGetIntForIndexM(interp, objv[2], /*end*/ len, &index);
    if (result != TCL_OK) {
	return result;
    }
    if (index + 1 > (size_t)len + 1) {
    if (index > len) {
	index = len;
    }

    /*
     * If the list object is unshared we can modify it directly. Otherwise we
     * create a copy to modify: this is "copy on write".
     */

    listPtr = objv[1];
    if (Tcl_IsShared(listPtr)) {
	listPtr = TclListObjCopy(NULL, listPtr);
	copied = 1;
    }

    if ((objc == 4) && (index == (size_t)len)) {
    if ((objc == 4) && (index == len)) {
	/*
	 * Special case: insert one element at the end of the list.
	 */

	Tcl_ListObjAppendElement(NULL, listPtr, objv[3]);
	result = Tcl_ListObjAppendElement(NULL, listPtr, objv[3]);
	if (result != TCL_OK) {
	    if (copied) {
		Tcl_DecrRefCount(listPtr);
	    }
	    return result;
	}
    } else {
	if (TCL_OK != Tcl_ListObjReplace(interp, listPtr, index, 0,
		(objc-3), &(objv[3]))) {
	    if (copied) {
		Tcl_DecrRefCount(listPtr);
	    }
	    return TCL_ERROR;
	}
    }

    /*
     * Set the interpreter's object result.
     */
2472
2473
2474
2475
2476
2477
2478
2479

2480
2481
2482
2483
2484
2485
2486
2514
2515
2516
2517
2518
2519
2520

2521
2522
2523
2524
2525
2526
2527
2528







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ListObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,		/* Number of arguments. */
    Tcl_Obj *const objv[])
				/* The argument objects. */
{
    /*
     * If there are no list elements, the result is an empty object.
2508
2509
2510
2511
2512
2513
2514
2515

2516
2517
2518
2519
2520

2521


2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537

2538

2539
2540
2541
2542
2543
2544
2545
2550
2551
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







-
+





+
-
+
+
















+
-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LlengthObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])
				/* Argument objects. */
{
    Tcl_Size listLen;
    int listLen, result;
    int result;
    Tcl_Obj *objPtr;

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

    result = TclListObjLength(interp, objv[1], &listLen);
    if (result != TCL_OK) {
	return result;
    }

    /*
     * Set the interpreter's object result to an integer object holding the
     * length.
     */

    TclNewUIntObj(objPtr, listLen);
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(listLen));
    Tcl_SetObjResult(interp, objPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_LpopObjCmd --
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
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







-
+





-
+
+

-
+











-
+














-
+
-


-
+
+
+
+
+
+



















+



+
+
+


+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

+
+
+




-







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LpopObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])
				/* Argument objects. */
{
    int listLen, result;
    Tcl_Size listLen;
    int copied = 0, result;
    Tcl_Obj *elemPtr, *stored;
    Tcl_Obj *listPtr, **elemPtrs;
    Tcl_Obj *listPtr;

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

    listPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG);
    if (listPtr == NULL) {
	return TCL_ERROR;
    }

    result = TclListObjGetElements(interp, listPtr, &listLen, &elemPtrs);
    result = TclListObjLength(interp, listPtr, &listLen);
    if (result != TCL_OK) {
	return result;
    }

    /*
     * First, extract the element to be returned.
     * TclLindexFlat adds a ref count which is handled.
     */

    if (objc == 2) {
	if (!listLen) {
	    /* empty list, throw the same error as with index "end" */
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"index \"end\" out of range", -1));
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX"
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", "OUTOFRANGE", (char *)NULL);
		"OUTOFRANGE", NULL);
	    return TCL_ERROR;
	}
	elemPtr = elemPtrs[listLen - 1];

	result = Tcl_ListObjIndex(interp, listPtr, (listLen-1),	&elemPtr);
	if (result != TCL_OK) {
	    return result;
	}

	Tcl_IncrRefCount(elemPtr);
    } else {
	elemPtr = TclLindexFlat(interp, listPtr, objc-2, objv+2);

	if (elemPtr == NULL) {
	    return TCL_ERROR;
	}
    }
    Tcl_SetObjResult(interp, elemPtr);
    Tcl_DecrRefCount(elemPtr);

    /*
     * Second, remove the element.
     * TclLsetFlat adds a ref count which is handled.
     */

    if (objc == 2) {
	if (Tcl_IsShared(listPtr)) {
	    listPtr = TclListObjCopy(NULL, listPtr);
	    copied = 1;
	}
	result = Tcl_ListObjReplace(interp, listPtr, listLen - 1, 1, 0, NULL);
	if (result != TCL_OK) {
	    if (copied) {
		Tcl_DecrRefCount(listPtr);
	    }
	    return result;
	}
    } else {
	Tcl_IncrRefCount(listPtr);
    } else {
	listPtr = TclLsetFlat(interp, listPtr, objc-2, objv+2, NULL);

	if (listPtr == NULL) {
	Tcl_Obj *newListPtr;
	Tcl_ObjTypeSetElement *proc = TclObjTypeHasProc(listPtr, setElementProc);
	if (proc) {
	    newListPtr = proc(interp, listPtr, objc-2, objv+2, NULL);
	} else {
	    newListPtr = TclLsetFlat(interp, listPtr, objc-2, objv+2, NULL);
	}
	if (newListPtr == NULL) {
	    if (copied) {
		Tcl_DecrRefCount(listPtr);
	    }
	    return TCL_ERROR;
	} else {
	    listPtr = newListPtr;
	    TclUndoRefCount(listPtr);
	}
    }

    stored = Tcl_ObjSetVar2(interp, objv[1], NULL, listPtr, TCL_LEAVE_ERR_MSG);
    Tcl_DecrRefCount(listPtr);
    if (stored == NULL) {
	return TCL_ERROR;
    }

    return TCL_OK;
}

2655
2656
2657
2658
2659
2660
2661
2662

2663
2664
2665
2666
2667
2668
2669


2670
2671
2672
2673
2674
2675
2676
2677
2718
2719
2720
2721
2722
2723
2724

2725
2726
2727
2728
2729
2730


2731
2732

2733
2734
2735
2736
2737
2738
2739







-
+





-
-
+
+
-







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LrangeObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])
				/* Argument objects. */
{
    int listLen, result;
    size_t first, last;
    int result;
    Tcl_Size listLen, first, last;

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "list first last");
	return TCL_ERROR;
    }

    result = TclListObjLength(interp, objv[1], &listLen);
    if (result != TCL_OK) {
2686
2687
2688
2689
2690
2691
2692




2693











2694
2695
2696
2697
2698
2699
2700
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







+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+








    result = TclGetIntForIndexM(interp, objv[3], /*endValue*/ listLen - 1,
	    &last);
    if (result != TCL_OK) {
	return result;
    }

    if (TclObjTypeHasProc(objv[1], sliceProc)) {
	Tcl_Obj *resultObj;
	int status = TclObjTypeSlice(interp, objv[1], first, last, &resultObj);
	if (status == TCL_OK) {
    Tcl_SetObjResult(interp, TclListObjRange(objv[1], first, last));
	    Tcl_SetObjResult(interp, resultObj);
	} else {
	    return TCL_ERROR;
	}
    } else {
	Tcl_Obj *resultObj = TclListObjRange(interp, objv[1], first, last);
	if (resultObj == NULL) {
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, resultObj);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_LremoveObjCmd --
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
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







-
-
+
+










-
+




-
-
+
+

+




















-
+

-
-
+
+
-
-
+
+









-
+








+




-
+







 */

static int
LremoveIndexCompare(
    const void *el1Ptr,
    const void *el2Ptr)
{
    size_t idx1 = *((const size_t *) el1Ptr);
    size_t idx2 = *((const size_t *) el2Ptr);
    Tcl_Size idx1 = *((const Tcl_Size *) el1Ptr);
    Tcl_Size idx2 = *((const Tcl_Size *) el2Ptr);

    /*
     * This will put the larger element first.
     */

    return (idx1 < idx2) ? 1 : (idx1 > idx2) ? -1 : 0;
}

int
Tcl_LremoveObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int i, idxc, listLen, prevIdx, first, num;
    size_t *idxv;
    Tcl_Size i, idxc, prevIdx, first, num;
    Tcl_Size *idxv, listLen;
    Tcl_Obj *listObj;
    int copied = 0, status = TCL_OK;

    /*
     * Parse the arguments.
     */

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

    listObj = objv[1];
    if (TclListObjLength(interp, listObj, &listLen) != TCL_OK) {
	return TCL_ERROR;
    }

    idxc = objc - 2;
    if (idxc == 0) {
	Tcl_SetObjResult(interp, listObj);
	return TCL_OK;
    }
    idxv = (size_t *)Tcl_Alloc((objc - 2) * sizeof(size_t));
    idxv = (Tcl_Size *)Tcl_Alloc((objc - 2) * sizeof(*idxv));
    for (i = 2; i < objc; i++) {
	if (TclGetIntForIndexM(interp, objv[i], /*endValue*/ listLen - 1,
		&idxv[i - 2]) != TCL_OK) {
	status = (TclGetIntForIndexM(interp, objv[i], /*endValue*/ listLen - 1,
		&idxv[i - 2]) != TCL_OK);
	    Tcl_Free(idxv);
	    return TCL_ERROR;
	if (status != TCL_OK) {
	    goto done;
	}
    }

    /*
     * Sort the indices, large to small so that when we remove an index we
     * don't change the indices still to be processed.
     */

    if (idxc > 1) {
	qsort(idxv, idxc, sizeof(size_t), LremoveIndexCompare);
	qsort(idxv, idxc, sizeof(*idxv), LremoveIndexCompare);
    }

    /*
     * Make our working copy, then do the actual removes piecemeal.
     */

    if (Tcl_IsShared(listObj)) {
	listObj = TclListObjCopy(NULL, listObj);
	copied = 1;
    }
    num = 0;
    first = listLen;
    for (i = 0, prevIdx = -1 ; i < idxc ; i++) {
	int idx = idxv[i];
	Tcl_Size idx = idxv[i];

	/*
	 * Repeated index and sanity check.
	 */

	if (idx == prevIdx) {
	    continue;
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
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







-
+
+
+
+






-
-
+
+
+
+
+
-
+
+
+

+
+
-
+







	    first = idx;
	} else {
	    /*
	     * Note that this operation can't fail now; we know we have a list
	     * and we're only ever contracting that list.
	     */

	    (void) Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL);
	    status = Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL);
	    if (status != TCL_OK) {
		goto done;
	    }
	    listLen -= num;
	    num = 1;
	    first = idx;
	}
    }
    if (num != 0) {
	(void) Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL);
    }
	status = Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL);
	if (status != TCL_OK) {
	    if (copied) {
		Tcl_DecrRefCount(listObj);
	    }
    Tcl_Free(idxv);
	    goto done;
	}
    }
    Tcl_SetObjResult(interp, listObj);
done:
    Tcl_Free(idxv);
    return TCL_OK;
    return status;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_LrepeatObjCmd --
 *
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
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







-
+





-
+
+











-
+




-
+

-
+














-
-
+
+











-
-
+
+
+
+
+
+
+
+
+
-
-


















-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LrepeatObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,		/* Number of arguments. */
    Tcl_Obj *const objv[])
				/* The argument objects. */
{
    int elementCount, i, totalElems;
    Tcl_WideInt elementCount, i;
    Tcl_Size totalElems;
    Tcl_Obj *listPtr, **dataArray = NULL;

    /*
     * Check arguments for legality:
     *		lrepeat count ?value ...?
     */

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "count ?value ...?");
	return TCL_ERROR;
    }
    if (TCL_OK != TclGetIntFromObj(interp, objv[1], &elementCount)) {
    if (TCL_OK != TclGetWideIntFromObj(interp, objv[1], &elementCount)) {
	return TCL_ERROR;
    }
    if (elementCount < 0) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"bad count \"%d\": must be integer >= 0", elementCount));
		"bad count \"%" TCL_LL_MODIFIER "d\": must be integer >= 0", elementCount));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LREPEAT", "NEGARG",
		NULL);
		(char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Skip forward to the interesting arguments now we've finished parsing.
     */

    objc -= 2;
    objv += 2;

    /* Final sanity check. Do not exceed limits on max list length. */

    if (elementCount && objc > LIST_MAX/elementCount) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"max length of a Tcl list (%d elements) exceeded", LIST_MAX));
	Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
		"max length of a Tcl list (%" TCL_SIZE_MODIFIER "d elements) exceeded", LIST_MAX));
	Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
	return TCL_ERROR;
    }
    totalElems = objc * elementCount;

    /*
     * Get an empty list object that is allocated large enough to hold each
     * init value elementCount times.
     */

    listPtr = Tcl_NewListObj(totalElems, NULL);
    if (totalElems) {
	List *listRepPtr = ListRepPtr(listPtr);

	ListRep listRep;
	ListObjGetRep(listPtr, &listRep);
	dataArray = ListRepElementsBase(&listRep);
	listRep.storePtr->numUsed = totalElems;
	if (listRep.spanPtr) {
	    /* Future proofing in case Tcl_NewListObj returns a span */
	    listRep.spanPtr->spanStart = listRep.storePtr->firstUsed;
	    listRep.spanPtr->spanLength = listRep.storePtr->numUsed;
	}
	listRepPtr->elemCount = elementCount*objc;
	dataArray = &listRepPtr->elements;
    }

    /*
     * Set the elements. Note that we handle the common degenerate case of a
     * single value being repeated separately to permit the compiler as much
     * room as possible to optimize a loop that might be run a very large
     * number of times.
     */

    CLANG_ASSERT(dataArray || totalElems == 0 );
    if (objc == 1) {
	Tcl_Obj *tmpPtr = objv[0];

	tmpPtr->refCount += elementCount;
	for (i=0 ; i<elementCount ; i++) {
	    dataArray[i] = tmpPtr;
	}
    } else {
	int j, k = 0;
	Tcl_Size j, k = 0;

	for (i=0 ; i<elementCount ; i++) {
	    for (j=0 ; j<objc ; j++) {
		Tcl_IncrRefCount(objv[j]);
		dataArray[k++] = objv[j];
	    }
	}
2952
2953
2954
2955
2956
2957
2958
2959

2960
2961
2962
2963
2964
2965
2966


2967
2968
2969
2970
2971
2972
2973
3046
3047
3048
3049
3050
3051
3052

3053
3054
3055
3056
3057
3058


3059
3060
3061
3062
3063
3064
3065
3066
3067







-
+





-
-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LreplaceObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *listPtr;
    size_t first, last;
    int listLen, numToDelete, result;
    Tcl_Size numToDelete, listLen, first, last;
    int result;

    if (objc < 4) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"list first last ?element ...?");
	return TCL_ERROR;
    }

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
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







-
+

-
+



-
+


-
-
+
+







    }

    result = TclGetIntForIndexM(interp, objv[3], /*end*/ listLen-1, &last);
    if (result != TCL_OK) {
	return result;
    }

    if (first == TCL_INDEX_NONE) {
    if (first < 0) {
	first = 0;
    } else if (first > (size_t)listLen) {
    } else if (first > listLen) {
	first = listLen;
    }

    if (last + 1 > (size_t)listLen) {
    if (last >= listLen) {
	last = listLen - 1;
    }
    if (first + 1 <= last + 1) {
	numToDelete = last - first + 1;
    if (first <= last) {
	numToDelete = (size_t)last - (size_t)first + 1; /* See [3d3124d01d] */
    } else {
	numToDelete = 0;
    }

    /*
     * If the list object is unshared we can modify it directly, otherwise we
     * create a copy to modify: this is "copy on write".
3023
3024
3025
3026
3027
3028
3029

3030
3031
3032
3033
3034
3035
3036
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131







+







     * elements are removed or added), but by making the call we are assured
     * we end up with a list in canonical form. Resist any temptation to
     * optimize this case away.
     */

    if (TCL_OK != Tcl_ListObjReplace(interp, listPtr, first, numToDelete,
	    objc-4, objv+4)) {
	Tcl_DecrRefCount(listPtr);
	return TCL_ERROR;
    }

    /*
     * Set the interpreter's object result.
     */

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
3148
3149
3150
3151
3152
3153
3154

3155
3156
3157
3158
3159
3160

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
3199

3200
3201
3202



3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219







-
+





-
+





-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











+
+
-
+
+

-
+

-
+


-
-
-
+
+
+
+
+
+
+
+
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LreverseObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    Tcl_Obj **elemv;
    int elemc, i, j;
    Tcl_Size elemc, i, j;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "list");
	return TCL_ERROR;
    }
    if (TclListObjGetElements(interp, objv[1], &elemc, &elemv) != TCL_OK) {

    /*
     *  Handle AbstractList special case - do not shimmer into a list, if it
     *  supports a private Reverse function, just to reverse it.
     */
    if (TclObjTypeHasProc(objv[1], reverseProc)) {
	Tcl_Obj *resultObj;

	if (TclObjTypeReverse(interp, objv[1], &resultObj) == TCL_OK) {
	    Tcl_SetObjResult(interp, resultObj);
	    return TCL_OK;
	}
    } /* end Abstract List */

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

    /*
     * If the list is empty, just return it. [Bug 1876793]
     */

    if (!elemc) {
	Tcl_SetObjResult(interp, objv[1]);
	return TCL_OK;
    }
    if (TclListObjGetElements(interp, objv[1], &elemc, &elemv) != TCL_OK) {
	return TCL_ERROR;

    }

    if (Tcl_IsShared(objv[1])
	    || (ListRepPtr(objv[1])->refCount > 1)) {	/* Bug 1675044 */
	    || ListObjRepIsShared(objv[1])) { /* Bug 1675044 */
	Tcl_Obj *resultObj, **dataArray;
	List *listRepPtr;
	ListRep listRep;

	resultObj = Tcl_NewListObj(elemc, NULL);
	listRepPtr = ListRepPtr(resultObj);
	listRepPtr->elemCount = elemc;
	dataArray = &listRepPtr->elements;

	/* Modify the internal rep in-place */
	ListObjGetRep(resultObj, &listRep);
	listRep.storePtr->numUsed = elemc;
	dataArray = ListRepElementsBase(&listRep);
	if (listRep.spanPtr) {
	    /* Future proofing */
	    listRep.spanPtr->spanStart = listRep.storePtr->firstUsed;
	    listRep.spanPtr->spanLength = listRep.storePtr->numUsed;
	}

	for (i=0,j=elemc-1 ; i<elemc ; i++,j--) {
	    dataArray[j] = elemv[i];
	    Tcl_IncrRefCount(elemv[i]);
	}

	Tcl_SetObjResult(interp, resultObj);
3132
3133
3134
3135
3136
3137
3138
3139

3140
3141
3142
3143
3144
3145
3146



3147
3148
3149


3150
3151
3152
3153

3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172

3173
3174
3175
3176
3177
3178
3179
3251
3252
3253
3254
3255
3256
3257

3258
3259
3260
3261
3262
3263


3264
3265
3266
3267


3268
3269
3270
3271
3272

3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291

3292
3293
3294
3295
3296
3297
3298
3299







-
+





-
-
+
+
+

-
-
+
+



-
+


















-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LsearchObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    const char *bytes, *patternBytes;
    int i, match, index, result=TCL_OK, listc, bisect;
    size_t length = 0, elemLen, start, groupSize, groupOffset, lower, upper;
    int match, result=TCL_OK, bisect;
    Tcl_Size i, length = 0, listc, elemLen, start, index;
    Tcl_Size groupOffset, lower, upper;
    int allocatedIndexVector = 0;
    int dataType, isIncreasing;
    Tcl_WideInt patWide, objWide, wide;
    int isIncreasing;
    Tcl_WideInt patWide, objWide, wide, groupSize;
    int allMatches, inlineReturn, negatedMatch, returnSubindices, noCase;
    double patDouble, objDouble;
    SortInfo sortInfo;
    Tcl_Obj *patObj, **listv, *listPtr, *startPtr, *itemPtr;
    Tcl_Obj *patObj, **listv, *listPtr, *startPtr, *itemPtr = NULL;
    SortStrCmpFn_t strCmpFn = TclUtfCmp;
    Tcl_RegExp regexp = NULL;
    static const char *const options[] = {
	"-all",	    "-ascii",   "-bisect", "-decreasing", "-dictionary",
	"-exact",   "-glob",    "-increasing", "-index",
	"-inline",  "-integer", "-nocase",     "-not",
	"-real",    "-regexp",  "-sorted",     "-start", "-stride",
	"-subindices", NULL
    };
    enum lsearchoptions {
	LSEARCH_ALL, LSEARCH_ASCII, LSEARCH_BISECT, LSEARCH_DECREASING,
	LSEARCH_DICTIONARY, LSEARCH_EXACT, LSEARCH_GLOB, LSEARCH_INCREASING,
	LSEARCH_INDEX, LSEARCH_INLINE, LSEARCH_INTEGER, LSEARCH_NOCASE,
	LSEARCH_NOT, LSEARCH_REAL, LSEARCH_REGEXP, LSEARCH_SORTED,
	LSEARCH_START, LSEARCH_STRIDE, LSEARCH_SUBINDICES
    };
    enum datatypes {
	ASCII, DICTIONARY, INTEGER, REAL
    };
    } dataType;
    enum modes {
	EXACT, GLOB, REGEXP, SORTED
    };
    enum modes mode;

    mode = GLOB;
    dataType = ASCII;
3199
3200
3201
3202
3203
3204
3205

3206

3207
3208
3209
3210
3211

3212
3213
3214
3215
3216
3217
3218
3319
3320
3321
3322
3323
3324
3325
3326

3327
3328
3329
3330
3331

3332
3333
3334
3335
3336
3337
3338
3339







+
-
+




-
+








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

    for (i = 1; i < objc-2; i++) {
	enum lsearchoptions idx;
	if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0, &index)
	if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0, &idx)
		!= TCL_OK) {
	    result = TCL_ERROR;
	    goto done;
	}
	switch ((enum lsearchoptions) index) {
	switch (idx) {
	case LSEARCH_ALL:		/* -all */
	    allMatches = 1;
	    break;
	case LSEARCH_ASCII:		/* -ascii */
	    dataType = ASCII;
	    break;
	case LSEARCH_BISECT:		/* -bisect */
3270
3271
3272
3273
3274
3275
3276
3277

3278
3279
3280
3281
3282
3283
3284
3391
3392
3393
3394
3395
3396
3397

3398
3399
3400
3401
3402
3403
3404
3405







-
+







	    if (startPtr != NULL) {
		Tcl_DecrRefCount(startPtr);
		startPtr = NULL;
	    }
	    if (i > objc-4) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"missing starting index", -1));
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (char *)NULL);
		result = TCL_ERROR;
		goto done;
	    }
	    i++;
	    if (objv[i] == objv[objc - 2]) {
		/*
		 * Take copy to prevent shimmering problems. Note that it does
3294
3295
3296
3297
3298
3299
3300
3301

3302
3303
3304
3305

3306
3307
3308
3309
3310
3311
3312
3313

3314
3315
3316
3317
3318
3319
3320
3321
3322

3323
3324
3325
3326
3327
3328
3329
3330
3331
3332

3333
3334
3335
3336
3337
3338
3339
3415
3416
3417
3418
3419
3420
3421

3422
3423
3424
3425

3426
3427
3428
3429
3430
3431
3432
3433

3434
3435
3436
3437
3438
3439
3440
3441
3442

3443
3444
3445
3446
3447
3448
3449
3450
3451
3452

3453
3454
3455
3456
3457
3458
3459
3460







-
+



-
+







-
+








-
+









-
+







	    Tcl_IncrRefCount(startPtr);
	    break;
	case LSEARCH_STRIDE:		/* -stride */
	    if (i > objc-4) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"\"-stride\" option must be "
			"followed by stride length", -1));
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (char *)NULL);
		result = TCL_ERROR;
		goto done;
	    }
	    if (Tcl_GetWideIntFromObj(interp, objv[i+1], &wide) != TCL_OK) {
	    if (TclGetWideIntFromObj(interp, objv[i+1], &wide) != TCL_OK) {
		result = TCL_ERROR;
		goto done;
	    }
	    if (wide < 1) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"stride length must be at least 1", -1));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSEARCH",
			"BADSTRIDE", NULL);
			"BADSTRIDE", (char *)NULL);
		result = TCL_ERROR;
		goto done;
	    }
	    groupSize = wide;
	    i++;
	    break;
	case LSEARCH_INDEX: {		/* -index */
	    Tcl_Obj **indices;
	    int j;
	    Tcl_Size j;

	    if (allocatedIndexVector) {
		TclStackFree(interp, sortInfo.indexv);
		allocatedIndexVector = 0;
	    }
	    if (i > objc-4) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"\"-index\" option must be followed by list index",
			-1));
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (char *)NULL);
		result = TCL_ERROR;
		goto done;
	    }

	    /*
	     * Store the extracted indices for processing by sublist
	     * extraction. Note that we don't do this using objects because
3372
3373
3374
3375
3376
3377
3378
3379

3380
3381
3382
3383
3384
3385

3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403

3404
3405
3406
3407
3408
3409
3410
3411
3412

3413
3414
3415
3416
3417
3418
3419
3493
3494
3495
3496
3497
3498
3499

3500

3501
3502
3503
3504

3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522

3523
3524
3525
3526
3527
3528
3529
3530
3531

3532
3533
3534
3535
3536
3537
3538
3539







-
+
-




-
+

















-
+








-
+







			TCL_INDEX_NONE, &encoded) != TCL_OK) {
		    result = TCL_ERROR;
		}
		if (encoded == (int)TCL_INDEX_NONE) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "index \"%s\" out of range",
			    TclGetString(indices[j])));
		    Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX"
		    Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", "OUTOFRANGE", (char *)NULL);
			    "OUTOFRANGE", NULL);
		    result = TCL_ERROR;
		}
		if (result == TCL_ERROR) {
		    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
			    "\n    (-index option item number %d)", j));
			    "\n    (-index option item number %" TCL_Z_MODIFIER "u)", j));
		    goto done;
		}
		sortInfo.indexv[j] = encoded;
	    }
	    break;
	}
	}
    }

    /*
     * Subindices only make sense if asked for with -index option set.
     */

    if (returnSubindices && sortInfo.indexc==0) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"-subindices cannot be used without -index option", -1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSEARCH",
		"BAD_OPTION_MIX", NULL);
		"BAD_OPTION_MIX", (char *)NULL);
	result = TCL_ERROR;
	goto done;
    }

    if (bisect && (allMatches || negatedMatch)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"-bisect is not compatible with -all or -not", -1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSEARCH",
		"BAD_OPTION_MIX", NULL);
		"BAD_OPTION_MIX", (char *)NULL);
	result = TCL_ERROR;
	goto done;
    }

    if (mode == REGEXP) {
	/*
	 * We can shimmer regexp/list if listv[i] == pattern, so get the
3459
3460
3461
3462
3463
3464
3465
3466

3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477

3478
3479
3480
3481
3482

3483
3484
3485
3486
3487
3488
3489
3579
3580
3581
3582
3583
3584
3585

3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596

3597
3598
3599
3600
3601

3602
3603
3604
3605
3606
3607
3608
3609







-
+










-
+




-
+








    if (groupSize > 1) {
	if (listc % groupSize) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "list size must be a multiple of the stride length",
		    -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSEARCH", "BADSTRIDE",
		    NULL);
		    (char *)NULL);
	    result = TCL_ERROR;
	    goto done;
	}
	if (sortInfo.indexc > 0) {
	    /*
	     * Use the first value in the list supplied to -index as the
	     * offset of the element within each group by which to sort.
	     */

	    groupOffset = TclIndexDecode(sortInfo.indexv[0], groupSize - 1);
	    if (groupOffset >= groupSize) {
	    if (groupOffset < 0 || groupOffset >= groupSize) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"when used with \"-stride\", the leading \"-index\""
			" value must be within the group", -1));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSEARCH",
			"BADINDEX", NULL);
			"BADINDEX", (char *)NULL);
		result = TCL_ERROR;
		goto done;
	    }
	    if (sortInfo.indexc == 1) {
		sortInfo.indexc = 0;
		sortInfo.indexv = NULL;
	    } else {
3510
3511
3512
3513
3514
3515
3516
3517

3518
3519
3520
3521

3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539

3540
3541
3542
3543
3544
3545
3546
3630
3631
3632
3633
3634
3635
3636

3637
3638
3639
3640

3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658

3659
3660
3661
3662
3663
3664
3665
3666







-
+



-
+

















-
+







	}

	/*
	 * If the search started past the end of the list, we just return a
	 * "did not match anything at all" result straight away. [Bug 1374778]
	 */

	if (start >= (size_t)listc) {
	if (start >= listc) {
	    if (allMatches || inlineReturn) {
		Tcl_ResetResult(interp);
	    } else {
		TclNewIndexObj(itemPtr, TCL_INDEX_NONE);
		TclNewIntObj(itemPtr, -1);
		Tcl_SetObjResult(interp, itemPtr);
	    }
	    goto done;
	}

	/*
	 * If start points within a group, it points to the start of the group.
	 */

	if (groupSize > 1) {
	    start -= (start % groupSize);
	}
    }

    patObj = objv[objc - 1];
    patternBytes = NULL;
    if (mode == EXACT || mode == SORTED) {
	switch ((enum datatypes) dataType) {
	switch (dataType) {
	case ASCII:
	case DICTIONARY:
	    patternBytes = TclGetStringFromObj(patObj, &length);
	    break;
	case INTEGER:
	    result = TclGetWideIntFromObj(interp, patObj, &patWide);
	    if (result != TCL_OK) {
3590
3591
3592
3593
3594
3595
3596

3597
3598
3599




3600
3601
3602
3603
3604
3605
3606
3607
3608
3609

3610
3611
3612
3613
3614
3615
3616
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733

3734
3735
3736
3737
3738
3739
3740
3741







+



+
+
+
+









-
+








	/*
	 * With -stride, lower, upper and i are kept as multiples of groupSize.
	 */

	lower = start - groupSize;
	upper = listc;
	itemPtr = NULL;
	while (lower + groupSize != upper && sortInfo.resultCode == TCL_OK) {
	    i = (lower + upper)/2;
	    i -= i % groupSize;

	    Tcl_BounceRefCount(itemPtr);
	    itemPtr = NULL;

	    if (sortInfo.indexc != 0) {
		itemPtr = SelectObjFromSublist(listv[i+groupOffset], &sortInfo);
		if (sortInfo.resultCode != TCL_OK) {
		    result = sortInfo.resultCode;
		    goto done;
		}
	    } else {
		itemPtr = listv[i+groupOffset];
	    }
	    switch ((enum datatypes) dataType) {
	    switch (dataType) {
	    case ASCII:
		bytes = TclGetString(itemPtr);
		match = strCmpFn(patternBytes, bytes);
		break;
	    case DICTIONARY:
		bytes = TclGetString(itemPtr);
		match = DictionaryCompare(patternBytes, bytes);
3691
3692
3693
3694
3695
3696
3697



3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714

3715
3716
3717
3718
3719
3720
3721
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841

3842
3843
3844
3845
3846
3847
3848
3849







+
+
+
















-
+







	 */

	if (allMatches) {
	    listPtr = Tcl_NewListObj(0, NULL);
	}
	for (i = start; i < listc; i += groupSize) {
	    match = 0;
	    Tcl_BounceRefCount(itemPtr);
	    itemPtr = NULL;

	    if (sortInfo.indexc != 0) {
		itemPtr = SelectObjFromSublist(listv[i+groupOffset], &sortInfo);
		if (sortInfo.resultCode != TCL_OK) {
		    if (listPtr != NULL) {
			Tcl_DecrRefCount(listPtr);
		    }
		    result = sortInfo.resultCode;
		    goto done;
		}
	    } else {
		itemPtr = listv[i+groupOffset];
	    }

	    switch (mode) {
	    case SORTED:
	    case EXACT:
		switch ((enum datatypes) dataType) {
		switch (dataType) {
		case ASCII:
		    bytes = TclGetStringFromObj(itemPtr, &elemLen);
		    if (length == elemLen) {
			/*
			 * This split allows for more optimal compilation of
			 * memcmp/strcasecmp.
			 */
3790
3791
3792
3793
3794
3795
3796

3797
3798
3799
3800
3801
3802
3803

3804
3805
3806
3807
3808

3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823



3824
3825
3826
3827
3828
3829
3830
3831
3832

3833
3834
3835
3836
3837
3838
3839
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937

3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964

3965
3966
3967
3968
3969
3970
3971
3972







+







+




-
+















+
+
+








-
+







		break;
	    } else if (inlineReturn) {
		/*
		 * Note that these appends are not expected to fail.
		 */

		if (returnSubindices && (sortInfo.indexc != 0)) {
		    Tcl_BounceRefCount(itemPtr);
		    itemPtr = SelectObjFromSublist(listv[i+groupOffset],
			    &sortInfo);
		    Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
		} else if (groupSize > 1) {
		    Tcl_ListObjReplace(interp, listPtr, LIST_MAX, 0,
			    groupSize, &listv[i]);
		} else {
		    Tcl_BounceRefCount(itemPtr);
		    itemPtr = listv[i];
		    Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
		}
	    } else if (returnSubindices) {
		int j;
		Tcl_Size j;

		TclNewIndexObj(itemPtr, i+groupOffset);
		for (j=0 ; j<sortInfo.indexc ; j++) {
		    Tcl_Obj *elObj;
		    size_t elValue = TclIndexDecode(sortInfo.indexv[j], listc);
		    TclNewIndexObj(elObj, elValue);
		    Tcl_ListObjAppendElement(interp, itemPtr, elObj);
		}
		Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
	    } else {
		Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewWideIntObj(i));
	    }
	}
    }

    Tcl_BounceRefCount(itemPtr);
    itemPtr = NULL;

    /*
     * Return everything or a single value.
     */

    if (allMatches) {
	Tcl_SetObjResult(interp, listPtr);
    } else if (!inlineReturn) {
	if (returnSubindices) {
	    int j;
	    Tcl_Size j;

	    TclNewIndexObj(itemPtr, index+groupOffset);
	    for (j=0 ; j<sortInfo.indexc ; j++) {
		Tcl_Obj *elObj;
		size_t elValue = TclIndexDecode(sortInfo.indexv[j], listc);
		TclNewIndexObj(elObj, elValue);
		Tcl_ListObjAppendElement(interp, itemPtr, elObj);
3864
3865
3866
3867
3868
3869
3870



3871
3872
3873
3874
3875
3876
3877
3878
































































































































































































































































































































































































3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899

3900
3901
3902
3903
3904
3905
3906
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
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
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418

4419
4420
4421
4422
4423
4424
4425
4426







+
+
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




















-
+







    result = TCL_OK;

    /*
     * Cleanup the index list array.
     */

  done:
    /* potential lingering abstract list element */
    Tcl_BounceRefCount(itemPtr);

    if (startPtr != NULL) {
	Tcl_DecrRefCount(startPtr);
    }
    if (allocatedIndexVector) {
	TclStackFree(interp, sortInfo.indexv);
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * SequenceIdentifyArgument --
 *   (for [lseq] command)
 *
 *  Given a Tcl_Obj, identify if it is a keyword or a number
 *
 *  Return Value
 *    0 - failure, unexpected value
 *    1 - value is a number
 *    2 - value is an operand keyword
 *    3 - value is a by keyword
 *
 *  The decoded value will be assigned to the appropriate
 *  pointer, numValuePtr reference count is incremented.
 */

static SequenceDecoded
SequenceIdentifyArgument(
     Tcl_Interp *interp,        /* for error reporting  */
     Tcl_Obj *argPtr,           /* Argument to decode   */
     int allowedArgs,		/* Flags if keyword or numeric allowed. */
     Tcl_Obj **numValuePtr,     /* Return numeric value */
     int *keywordIndexPtr)      /* Return keyword enum  */
{
    int result = TCL_ERROR;
    SequenceOperators opmode;
    void *internalPtr;

    if (allowedArgs & NumericArg) {
	/* speed-up a bit (and avoid shimmer for compiled expressions) */
	if (TclHasInternalRep(argPtr, &tclExprCodeType)) {
	   goto doExpr;
	}
	result = Tcl_GetNumberFromObj(NULL, argPtr, &internalPtr, keywordIndexPtr);
	if (result == TCL_OK) {
	    *numValuePtr = argPtr;
	    Tcl_IncrRefCount(argPtr);
	    return NumericArg;
	}
    }
    if (allowedArgs & RangeKeywordArg) {
	result = Tcl_GetIndexFromObj(NULL, argPtr, seq_operations,
			"range operation", 0, &opmode);
    }
    if (result == TCL_OK) {
	if (allowedArgs & LastArg) {
	    /* keyword found, but no followed number */
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		  "missing \"%s\" value.", TclGetString(argPtr)));
	    return ErrArg;
	}
	*keywordIndexPtr = opmode;
	return RangeKeywordArg;
    } else {
	Tcl_Obj *exprValueObj;
	if (!(allowedArgs & NumericArg)) {
	    return NoneArg;
	}
    doExpr:
	/* Check for an index expression */
	if (Tcl_ExprObj(interp, argPtr, &exprValueObj) != TCL_OK) {
	    return ErrArg;
	}
	int keyword;
	/* Determine if result of expression is double or int */
	if (Tcl_GetNumberFromObj(interp, exprValueObj, &internalPtr,
		&keyword) != TCL_OK
	) {
	    return ErrArg;
	}
	*numValuePtr = exprValueObj; /* incremented in Tcl_ExprObj */
	*keywordIndexPtr = keyword; /* type of expression result */
	return NumericArg;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_LseqObjCmd --
 *
 *	This procedure is invoked to process the "lseq" Tcl command.
 *	See the user documentation for details on what it does.
 *
 * Enumerated possible argument patterns:
 *
 * 1:
 *    lseq n
 * 2:
 *    lseq n n
 * 3:
 *    lseq n n n
 *    lseq n 'to' n
 *    lseq n 'count' n
 *    lseq n 'by' n
 * 4:
 *    lseq n 'to' n n
 *    lseq n n 'by' n
 *    lseq n 'count' n n
 * 5:
 *    lseq n 'to' n 'by' n
 *    lseq n 'count' n 'by' n
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LseqObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,	   /* Current interpreter. */
    int objc,		   /* Number of arguments. */
    Tcl_Obj *const objv[]) /* The argument objects. */
{
    Tcl_Obj *elementCount = NULL;
    Tcl_Obj *start = NULL, *end = NULL, *step = NULL;
    Tcl_WideInt values[5];
    Tcl_Obj *numValues[5];
    Tcl_Obj *numberObj;
    int status = TCL_ERROR, keyword, allowedArgs = NumericArg;
    int useDoubles = 0;
    int remNums = 3;
    Tcl_Obj *arithSeriesPtr;
    SequenceOperators opmode;
    SequenceDecoded decoded;
    int i, arg_key = 0, value_i = 0;
    /* Default constants */
    #define zero ((Interp *)interp)->execEnvPtr->constants[0];
    #define one ((Interp *)interp)->execEnvPtr->constants[1];

    /*
     * Create a decoding key by looping through the arguments and identify
     * what kind of argument each one is.  Encode each argument as a decimal
     * digit.
     */
    if (objc > 6) {
	/* Too many arguments */
	goto syntax;
    }
    for (i = 1; i < objc; i++) {
	arg_key = (arg_key * 10);
	numValues[value_i] = NULL;
	decoded = SequenceIdentifyArgument(interp, objv[i],
			allowedArgs | (i == objc-1 ? LastArg : 0),
			&numberObj, &keyword);
	switch (decoded) {
	  case NoneArg:
	    /*
	     * Unrecognizable argument
	     * Reproduce operation error message
	     */
	    status = Tcl_GetIndexFromObj(interp, objv[i], seq_operations,
			"operation", 0, &opmode);
	    goto done;

	  case NumericArg:
	    remNums--;
	    arg_key += NumericArg;
	    allowedArgs = RangeKeywordArg;
	    /* if last number but 2 arguments remain, next is not numeric */
	    if ((remNums != 1) || ((objc-1-i) != 2)) {
		allowedArgs |= NumericArg;
	    }
	    numValues[value_i] = numberObj;
	    values[value_i] = keyword;  /* TCL_NUMBER_* */
	    useDoubles += (keyword == TCL_NUMBER_DOUBLE) ? 1 : 0;
	    value_i++;
	    break;

	  case RangeKeywordArg:
	    arg_key += RangeKeywordArg;
	    allowedArgs = NumericArg;   /* after keyword always numeric only */
	    values[value_i] = keyword;  /* SequenceOperators */
	    value_i++;
	    break;

	  default: /* Error state */
	    status = TCL_ERROR;
	    goto done;
	}
    }

    /*
     * The key encoding defines a valid set of arguments, or indicates an
     * error condition; process the values accordningly.
     */
    switch (arg_key) {

/*    lseq n */
    case 1:
	start = zero;
	elementCount = numValues[0];
	end = NULL;
	step = one;
	useDoubles = 0; // Can only have Integer value. If a fractional value
			// is given, this will fail later. In other words,
			// "3.0" is allowed and used as Integer, but "3.1"
			// will be flagged as an error. (bug f4a4bd7f1070)
	break;

/*    lseq n n */
    case 11:
	start = numValues[0];
	end = numValues[1];
	break;

/*    lseq n n n */
    case 111:
	start = numValues[0];
	end = numValues[1];
	step = numValues[2];
	break;

/*    lseq n 'to' n    */
/*    lseq n 'count' n */
/*    lseq n 'by' n    */
    case 121:
	opmode = (SequenceOperators)values[1];
	switch (opmode) {
	case LSEQ_DOTS:
	case LSEQ_TO:
	    start = numValues[0];
	    end = numValues[2];
	    break;
	case LSEQ_BY:
	    start = zero;
	    elementCount = numValues[0];
	    step = numValues[2];
	    break;
	case LSEQ_COUNT:
	    start = numValues[0];
	    elementCount = numValues[2];
	    step = one;
	    break;
	default:
	    goto done;
	}
	break;

/*    lseq n 'to' n n    */
/*    lseq n 'count' n n */
    case 1211:
	opmode = (SequenceOperators)values[1];
	switch (opmode) {
	case LSEQ_DOTS:
	case LSEQ_TO:
	    start = numValues[0];
	    end = numValues[2];
	    step = numValues[3];
	    break;
	case LSEQ_COUNT:
	    start = numValues[0];
	    elementCount = numValues[2];
	    step = numValues[3];
	    break;
	case LSEQ_BY:
	    /* Error case */
	    goto done;
	    break;
	default:
	    goto done;
	    break;
	}
	break;

/*    lseq n n 'by' n */
    case 1121:
	start = numValues[0];
	end = numValues[1];
	opmode = (SequenceOperators)values[2];
	switch (opmode) {
	case LSEQ_BY:
	    step = numValues[3];
	    break;
	case LSEQ_DOTS:
	case LSEQ_TO:
	case LSEQ_COUNT:
	default:
	    goto done;
	    break;
	}
	break;

/*    lseq n 'to' n 'by' n    */
/*    lseq n 'count' n 'by' n */
    case 12121:
	start = numValues[0];
	opmode = (SequenceOperators)values[3];
	switch (opmode) {
	case LSEQ_BY:
	    step = numValues[4];
	    break;
	default:
	    goto done;
	    break;
	}
	opmode = (SequenceOperators)values[1];
	switch (opmode) {
	case LSEQ_DOTS:
	case LSEQ_TO:
	    start = numValues[0];
	    end = numValues[2];
	    break;
	case LSEQ_COUNT:
	    start = numValues[0];
	    elementCount = numValues[2];
	    break;
	default:
	    goto done;
	    break;
	}
	break;

/*    All other argument errors */
    default:
      syntax:
	 Tcl_WrongNumArgs(interp, 1, objv, "n ??op? n ??by? n??");
	 goto done;
	 break;
    }

    /* Count needs to be integer, so try to convert if possible */
    if (elementCount && TclHasInternalRep(elementCount, &tclDoubleType)) {
	double d;
	// Don't consider Count type to indicate using double values in seqence
	useDoubles -= (useDoubles > 0) ? 1 : 0;
	(void)Tcl_GetDoubleFromObj(NULL, elementCount, &d);
	if (floor(d) == d) {
	    if ((d >= (double)WIDE_MAX) || (d <= (double)WIDE_MIN)) {
		mp_int big;

		if (Tcl_InitBignumFromDouble(NULL, d, &big) == TCL_OK) {
		    elementCount = Tcl_NewBignumObj(&big);
		    keyword = TCL_NUMBER_INT;
		}
		/* Infinity, don't convert, let fail later */
	    } else {
		elementCount = Tcl_NewWideIntObj((Tcl_WideInt)d);
		keyword = TCL_NUMBER_INT;
	    }
	}
    }


    /*
     * Success!  Now lets create the series object.
     */
    arithSeriesPtr = TclNewArithSeriesObj(interp,
		  useDoubles, start, end, step, elementCount);

    status = TCL_ERROR;
    if (arithSeriesPtr) {
	status = TCL_OK;
	Tcl_SetObjResult(interp, arithSeriesPtr);
    }

 done:
    // Free number arguments.
    while (--value_i>=0) {
	if (numValues[value_i]) {
	    if (elementCount == numValues[value_i]) {
		elementCount = NULL;
	    }
	    Tcl_DecrRefCount(numValues[value_i]);
	}
    }
    if (elementCount) {
	Tcl_DecrRefCount(elementCount);
    }

    /* Undef constants */
    #undef zero
    #undef one

    return status;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_LsetObjCmd --
 *
 *	This procedure is invoked to process the "lset" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LsetObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    Tcl_Obj *listPtr;		/* Pointer to the list being altered. */
    Tcl_Obj *finalValuePtr;	/* Value finally assigned to the variable. */

3927
3928
3929
3930
3931
3932
3933







3934
3935



3936
3937
3938
3939
3940
3941
3942
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460


4461
4462
4463
4464
4465
4466
4467
4468
4469
4470







+
+
+
+
+
+
+
-
-
+
+
+







     * Substitute the value in the value. Return either the value or else an
     * unshared copy of it.
     */

    if (objc == 4) {
	finalValuePtr = TclLsetList(interp, listPtr, objv[2], objv[3]);
    } else {
	if (TclObjTypeHasProc(listPtr, setElementProc)) {
	    finalValuePtr = TclObjTypeSetElement(interp, listPtr,
						       objc-3, objv+2, objv[objc-1]);
	    if (finalValuePtr) {
		Tcl_IncrRefCount(finalValuePtr);
	    }
	} else {
	finalValuePtr = TclLsetFlat(interp, listPtr, objc-3, objv+2,
		objv[objc-1]);
	    finalValuePtr = TclLsetFlat(interp, listPtr, objc-3, objv+2,
					objv[objc-1]);
	}
    }

    /*
     * If substitution has failed, bail out.
     */

    if (finalValuePtr == NULL) {
3977
3978
3979
3980
3981
3982
3983
3984

3985
3986
3987
3988
3989

3990
3991
3992
3993


3994
3995

3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015

4016
4017
4018
4019
4020
4021
4022
4505
4506
4507
4508
4509
4510
4511

4512
4513
4514
4515
4516

4517
4518
4519


4520
4521
4522

4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542

4543
4544
4545
4546
4547
4548
4549
4550







-
+




-
+


-
-
+
+

-
+



















-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LsortObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    int i, index, indices, length, nocase = 0, indexc;
    int indices, nocase = 0, indexc;
    int sortMode = SORTMODE_ASCII;
    int group, allocatedIndexVector = 0;
    size_t j, idx, groupSize, groupOffset;
    Tcl_WideInt wide;
    Tcl_Size j, idx, groupOffset, length;
    Tcl_WideInt wide, groupSize;
    Tcl_Obj *resultPtr, *cmdPtr, **listObjPtrs, *listObj, *indexPtr;
    size_t elmArrSize;
    Tcl_Size i, elmArrSize;
    SortElement *elementArray = NULL, *elementPtr;
    SortInfo sortInfo;		/* Information about this sort that needs to
				 * be passed to the comparison function. */
#   define MAXCALLOC 1024000
#   define NUM_LISTS 30
    SortElement *subList[NUM_LISTS+1];
				/* This array holds pointers to temporary
				 * lists built during the merge sort. Element
				 * i of the array holds a list of length
				 * 2**i. */
    static const char *const switches[] = {
	"-ascii", "-command", "-decreasing", "-dictionary", "-increasing",
	"-index", "-indices", "-integer", "-nocase", "-real", "-stride",
	"-unique", NULL
    };
    enum Lsort_Switches {
	LSORT_ASCII, LSORT_COMMAND, LSORT_DECREASING, LSORT_DICTIONARY,
	LSORT_INCREASING, LSORT_INDEX, LSORT_INDICES, LSORT_INTEGER,
	LSORT_NOCASE, LSORT_REAL, LSORT_STRIDE, LSORT_UNIQUE
    };
    } index;

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

    /*
4038
4039
4040
4041
4042
4043
4044
4045

4046
4047
4048
4049
4050
4051
4052
4053
4054

4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072

4073
4074
4075
4076
4077
4078
4079

4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097

4098
4099
4100
4101
4102
4103
4104
4105
4106

4107
4108
4109
4110
4111
4112

4113
4114
4115
4116
4117
4118
4119
4566
4567
4568
4569
4570
4571
4572

4573
4574
4575
4576
4577
4578
4579
4580
4581

4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599

4600
4601
4602
4603
4604
4605
4606

4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624

4625
4626
4627
4628
4629
4630
4631
4632
4633

4634

4635
4636
4637
4638

4639
4640
4641
4642
4643
4644
4645
4646







-
+








-
+

















-
+






-
+

















-
+








-
+
-




-
+







    indexPtr = NULL;
    for (i = 1; i < objc-1; i++) {
	if (Tcl_GetIndexFromObj(interp, objv[i], switches, "option", 0,
		&index) != TCL_OK) {
	    sortInfo.resultCode = TCL_ERROR;
	    goto done;
	}
	switch ((enum Lsort_Switches) index) {
	switch (index) {
	case LSORT_ASCII:
	    sortInfo.sortMode = SORTMODE_ASCII;
	    break;
	case LSORT_COMMAND:
	    if (i == objc-2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"\"-command\" option must be followed "
			"by comparison command", -1));
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (char *)NULL);
		sortInfo.resultCode = TCL_ERROR;
		goto done;
	    }
	    sortInfo.sortMode = SORTMODE_COMMAND;
	    cmdPtr = objv[i+1];
	    i++;
	    break;
	case LSORT_DECREASING:
	    sortInfo.isIncreasing = 0;
	    break;
	case LSORT_DICTIONARY:
	    sortInfo.sortMode = SORTMODE_DICTIONARY;
	    break;
	case LSORT_INCREASING:
	    sortInfo.isIncreasing = 1;
	    break;
	case LSORT_INDEX: {
	    int sortindex;
	    Tcl_Size sortindex;
	    Tcl_Obj **indexv;

	    if (i == objc-2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"\"-index\" option must be followed by list index",
			-1));
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (char *)NULL);
		sortInfo.resultCode = TCL_ERROR;
		goto done;
	    }
	    if (TclListObjGetElements(interp, objv[i+1], &sortindex,
		    &indexv) != TCL_OK) {
		sortInfo.resultCode = TCL_ERROR;
		goto done;
	    }

	    /*
	     * Check each of the indices for syntactic correctness. Note that
	     * we do not store the converted values here because we do not
	     * know if this is the only -index option yet and so we can't
	     * allocate any space; that happens after the scan through all the
	     * options is done.
	     */

	    for (j=0 ; j<(size_t)sortindex ; j++) {
	    for (j=0 ; j<sortindex ; j++) {
		int encoded = 0;
		int result = TclIndexEncode(interp, indexv[j],
			TCL_INDEX_NONE, TCL_INDEX_NONE, &encoded);

		if ((result == TCL_OK) && (encoded == (int)TCL_INDEX_NONE)) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "index \"%s\" out of range",
			    TclGetString(indexv[j])));
		    Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX"
		    Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", "OUTOFRANGE", (char *)NULL);
			    "OUTOFRANGE", NULL);
		    result = TCL_ERROR;
		}
		if (result == TCL_ERROR) {
		    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
			    "\n    (-index option item number %" TCL_Z_MODIFIER "d)", j));
			    "\n    (-index option item number %" TCL_Z_MODIFIER "u)", j));
		    sortInfo.resultCode = TCL_ERROR;
		    goto done;
		}
	    }
	    indexPtr = objv[i+1];
	    i++;
	    break;
4134
4135
4136
4137
4138
4139
4140
4141

4142
4143
4144
4145

4146
4147
4148
4149
4150
4151
4152
4153

4154
4155
4156
4157
4158
4159
4160
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







-
+



-
+







-
+







	    indices = 1;
	    break;
	case LSORT_STRIDE:
	    if (i == objc-2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"\"-stride\" option must be "
			"followed by stride length", -1));
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (char *)NULL);
		sortInfo.resultCode = TCL_ERROR;
		goto done;
	    }
	    if (Tcl_GetWideIntFromObj(interp, objv[i+1], &wide) != TCL_OK) {
	    if (TclGetWideIntFromObj(interp, objv[i+1], &wide) != TCL_OK) {
		sortInfo.resultCode = TCL_ERROR;
		goto done;
	    }
	    if (wide < 2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"stride length must be at least 2", -1));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSORT",
			"BADSTRIDE", NULL);
			"BADSTRIDE", (char *)NULL);
		sortInfo.resultCode = TCL_ERROR;
		goto done;
	    }
	    groupSize = wide;
	    group = 1;
	    i++;
	    break;
4183
4184
4185
4186
4187
4188
4189
4190

4191
4192
4193
4194
4195
4196
4197
4710
4711
4712
4713
4714
4715
4716

4717
4718
4719
4720
4721
4722
4723
4724







-
+







	    break;
	default:
	    sortInfo.indexv = (int *)
		    TclStackAlloc(interp, sizeof(int) * sortInfo.indexc);
	    allocatedIndexVector = 1;	/* Cannot use indexc field, as it
					 * might be decreased by 1 later. */
	}
	for (j=0 ; j<(size_t)sortInfo.indexc ; j++) {
	for (j=0 ; j<sortInfo.indexc ; j++) {
	    /* Prescreened values, no errors or out of range possible */
	    TclIndexEncode(NULL, indexv[j], TCL_INDEX_NONE,
		    TCL_INDEX_NONE, &sortInfo.indexv[j]);
	}
    }

    listObj = objv[objc-1];
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235




4236

4237

4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253

4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265

4266
4267
4268
4269
4270

4271
4272
4273
4274
4275
4276
4277
4746
4747
4748
4749
4750
4751
4752


4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764

4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782

4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794

4795
4796
4797
4798
4799

4800
4801
4802
4803
4804
4805
4806
4807







-
-








+
+
+
+
-
+

+















-
+











-
+




-
+








	newCommandPtr = Tcl_DuplicateObj(cmdPtr);
	TclNewObj(newObjPtr);
	Tcl_IncrRefCount(newCommandPtr);
	if (Tcl_ListObjAppendElement(interp, newCommandPtr, newObjPtr)
		!= TCL_OK) {
	    TclDecrRefCount(newCommandPtr);
	    TclDecrRefCount(listObj);
	    Tcl_IncrRefCount(newObjPtr);
	    TclDecrRefCount(newObjPtr);
	    sortInfo.resultCode = TCL_ERROR;
	    goto done;
	}
	Tcl_ListObjAppendElement(interp, newCommandPtr, Tcl_NewObj());
	sortInfo.compareCmdPtr = newCommandPtr;
    }

    if (TclObjTypeHasProc(objv[1], getElementsProc)) {
	sortInfo.resultCode =
	    TclObjTypeGetElements(interp, listObj, &length, &listObjPtrs);
    } else {
    sortInfo.resultCode = TclListObjGetElements(interp, listObj,
	sortInfo.resultCode = TclListObjGetElements(interp, listObj,
	    &length, &listObjPtrs);
    }
    if (sortInfo.resultCode != TCL_OK || length <= 0) {
	goto done;
    }

    /*
     * Check for sanity when grouping elements of the overall list together
     * because of the -stride option. [TIP #326]
     */

    if (group) {
	if (length % groupSize) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "list size must be a multiple of the stride length",
		    -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSORT", "BADSTRIDE",
		    NULL);
		    (char *)NULL);
	    sortInfo.resultCode = TCL_ERROR;
	    goto done;
	}
	length = length / groupSize;
	if (sortInfo.indexc > 0) {
	    /*
	     * Use the first value in the list supplied to -index as the
	     * offset of the element within each group by which to sort.
	     */

	    groupOffset = TclIndexDecode(sortInfo.indexv[0], groupSize - 1);
	    if (groupOffset >= groupSize) {
	    if (groupOffset < 0 || groupOffset >= groupSize) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"when used with \"-stride\", the leading \"-index\""
			" value must be within the group", -1));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSORT",
			"BADINDEX", NULL);
			"BADINDEX", (char *)NULL);
		sortInfo.resultCode = TCL_ERROR;
		goto done;
	    }
	    if (sortInfo.indexc == 1) {
		sortInfo.indexc = 0;
		sortInfo.indexv = NULL;
	    } else {
4324
4325
4326
4327
4328
4329
4330
4331
4332


4333
4334
4335
4336
4337
4338
4339
4854
4855
4856
4857
4858
4859
4860


4861
4862
4863
4864
4865
4866
4867
4868
4869







-
-
+
+







    if (elmArrSize <= MAXCALLOC) {
	elementArray = (SortElement *)Tcl_Alloc(elmArrSize);
    } else {
	elementArray = (SortElement *)malloc(elmArrSize);
    }
    if (!elementArray) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"no enough memory to proccess sort of %d items", length));
	Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
		"no enough memory to proccess sort of %" TCL_Z_MODIFIER "u items", length));
	Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
	sortInfo.resultCode = TCL_ERROR;
	goto done;
    }

    for (i=0; i < length; i++) {
	idx = groupSize * i + groupOffset;
	if (indexc) {
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
4891
4892
4893
4894
4895
4896
4897

4898

4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918

4919
4920
4921
4922
4923
4924
4925
4926







-
+
-




















-
+







		sortInfo.resultCode = TCL_ERROR;
		goto done;
	    }
	    elementArray[i].collationKey.wideValue = a;
	} else if (sortMode == SORTMODE_REAL) {
	    double a;

	    if (Tcl_GetDoubleFromObj(sortInfo.interp, indexPtr,
	    if (Tcl_GetDoubleFromObj(sortInfo.interp, indexPtr, &a) != TCL_OK) {
		    &a) != TCL_OK) {
		sortInfo.resultCode = TCL_ERROR;
		goto done;
	    }
	    elementArray[i].collationKey.doubleValue = a;
	} else {
	    elementArray[i].collationKey.objValuePtr = indexPtr;
	}

	/*
	 * Determine the representation of this element in the result: either
	 * the objPtr itself, or its index in the original list.
	 */

	if (indices || group) {
	    elementArray[i].payload.index = idx;
	} else {
	    elementArray[i].payload.objPtr = listObjPtrs[idx];
	}

	/*
	 * Merge this element in the pre-existing sublists (and merge together
	 * Merge this element in the preexisting sublists (and merge together
	 * sublists when we have two of the same size).
	 */

	elementArray[i].nextPtr = NULL;
	elementPtr = &elementArray[i];
	for (j=0 ; subList[j] ; j++) {
	    elementPtr = MergeLists(subList[j], elementPtr, &sortInfo);
4413
4414
4415
4416
4417
4418
4419
4420

4421
4422
4423
4424
4425


4426
4427
4428
4429
4430
4431
4432
4942
4943
4944
4945
4946
4947
4948

4949
4950
4951
4952


4953
4954
4955
4956
4957
4958
4959
4960
4961







-
+



-
-
+
+







    }

    /*
     * Now store the sorted elements in the result list.
     */

    if (sortInfo.resultCode == TCL_OK) {
	List *listRepPtr;
	ListRep listRep;
	Tcl_Obj **newArray, *objPtr;

	resultPtr = Tcl_NewListObj(sortInfo.numElements * groupSize, NULL);
	listRepPtr = ListRepPtr(resultPtr);
	newArray = &listRepPtr->elements;
	ListObjGetRep(resultPtr, &listRep);
	newArray = ListRepElementsBase(&listRep);
	if (group) {
	    for (i=0; elementPtr!=NULL ; elementPtr=elementPtr->nextPtr) {
		idx = elementPtr->payload.index;
		for (j = 0; j < groupSize; j++) {
		    if (indices) {
			TclNewIndexObj(objPtr, idx + j - groupOffset);
			newArray[i++] = objPtr;
4447
4448
4449
4450
4451
4452
4453

4454




4455
4456
4457
4458
4459
4460
4461
4976
4977
4978
4979
4980
4981
4982
4983

4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994







+
-
+
+
+
+







	} else {
	    for (i=0; elementPtr != NULL ; elementPtr = elementPtr->nextPtr) {
		objPtr = elementPtr->payload.objPtr;
		newArray[i++] = objPtr;
		Tcl_IncrRefCount(objPtr);
	    }
	}
	listRep.storePtr->numUsed = i;
	listRepPtr->elemCount = i;
	if (listRep.spanPtr) {
	    listRep.spanPtr->spanStart = listRep.storePtr->firstUsed;
	    listRep.spanPtr->spanLength = listRep.storePtr->numUsed;
	}
	Tcl_SetObjResult(interp, resultPtr);
    }

  done:
    if (sortMode == SORTMODE_COMMAND) {
	TclDecrRefCount(sortInfo.compareCmdPtr);
	TclDecrRefCount(listObj);
4469
4470
4471
4472
4473
4474
4475













































































































4476
4477
4478
4479
4480
4481
4482
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    Tcl_Free(elementArray);
	} else {
	    free((char *)elementArray);
	}
    }
    return sortInfo.resultCode;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_LeditObjCmd --
 *
 *	This procedure is invoked to process the "ledit" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LeditObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    Tcl_Obj *listPtr;		/* Pointer to the list being altered. */
    Tcl_Obj *finalValuePtr;	/* Value finally assigned to the variable. */
    int createdNewObj;
    int result;
    Tcl_Size first;
    Tcl_Size last;
    Tcl_Size listLen;
    Tcl_Size numToDelete;

    if (objc < 4) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"listVar first last ?element ...?");
	return TCL_ERROR;
    }

    listPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG);
    if (listPtr == NULL) {
	return TCL_ERROR;
    }

    /*
     * TODO - refactor the index extraction into a common function shared
     * by Tcl_{Lrange,Lreplace,Ledit}ObjCmd
     */

    result = TclListObjLength(interp, listPtr, &listLen);
    if (result != TCL_OK) {
	return result;
    }

    result = TclGetIntForIndexM(interp, objv[2], /*end*/ listLen-1, &first);
    if (result != TCL_OK) {
	return result;
    }

    result = TclGetIntForIndexM(interp, objv[3], /*end*/ listLen-1, &last);
    if (result != TCL_OK) {
	return result;
    }

    if (first < 0) {
	first = 0;
    } else if (first > listLen) {
	first = listLen;
    }

    if (last >= listLen) {
	last = listLen - 1;
    }
    if (first <= last) {
	numToDelete = (size_t)last - (size_t)first + 1; /* See [3d3124d01d] */
    } else {
	numToDelete = 0;
    }

    if (Tcl_IsShared(listPtr)) {
	listPtr = TclListObjCopy(NULL, listPtr);
	createdNewObj = 1;
    } else {
	createdNewObj = 0;
    }

    result =
	Tcl_ListObjReplace(interp, listPtr, first, numToDelete, objc - 4, objv + 4);
    if (result != TCL_OK) {
	if (createdNewObj) {
	    Tcl_DecrRefCount(listPtr);
	}
	return result;
    }

    /*
     * Tcl_ObjSetVar2 may return a value different from listPtr in the
     * presence of traces etc.
     */
    finalValuePtr =
	Tcl_ObjSetVar2(interp, objv[1], NULL, listPtr, TCL_LEAVE_ERR_MSG);
    if (finalValuePtr == NULL) {
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, finalValuePtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * MergeLists -
 *
 *	This procedure combines two sorted lists of SortElement structures
4579
4580
4581
4582
4583
4584
4585
4586

4587
4588
4589
4590
4591
4592
4593
5221
5222
5223
5224
5225
5226
5227

5228
5229
5230
5231
5232
5233
5234
5235







-
+







 *
 * SortCompare --
 *
 *	This procedure is invoked by MergeLists to determine the proper
 *	ordering between two elements.
 *
 * Results:
 *	A negative results means the the first element comes before the
 *	A negative results means the first element comes before the
 *	second, and a positive results means that the second element should
 *	come first. A result of zero means the two elements are equal and it
 *	doesn't matter which comes first.
 *
 * Side effects:
 *	None, unless a user-defined comparison command does something weird.
 *
4622
4623
4624
4625
4626
4627
4628
4629

4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
5264
5265
5266
5267
5268
5269
5270

5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281

5282
5283
5284
5285
5286
5287
5288







-
+










-







	double a, b;

	a = elemPtr1->collationKey.doubleValue;
	b = elemPtr2->collationKey.doubleValue;
	order = ((a >= b) - (a <= b));
    } else {
	Tcl_Obj **objv, *paramObjv[2];
	int objc;
	Tcl_Size objc;
	Tcl_Obj *objPtr1, *objPtr2;

	if (infoPtr->resultCode != TCL_OK) {
	    /*
	     * Once an error has occurred, skip any future comparisons so as
	     * to preserve the error message in sortInterp->result.
	     */

	    return 0;
	}


	objPtr1 = elemPtr1->collationKey.objValuePtr;
	objPtr2 = elemPtr2->collationKey.objValuePtr;

	paramObjv[0] = objPtr1;
	paramObjv[1] = objPtr2;

4668
4669
4670
4671
4672
4673
4674
4675

4676
4677
4678
4679
4680
4681
4682
5309
5310
5311
5312
5313
5314
5315

5316
5317
5318
5319
5320
5321
5322
5323







-
+







	 */

	if (TclGetIntFromObj(infoPtr->interp,
		Tcl_GetObjResult(infoPtr->interp), &order) != TCL_OK) {
	    Tcl_SetObjResult(infoPtr->interp, Tcl_NewStringObj(
		    "-compare command returned non-integer result", -1));
	    Tcl_SetErrorCode(infoPtr->interp, "TCL", "OPERATION", "LSORT",
		    "COMPARISONFAILED", NULL);
		    "COMPARISONFAILED", (char *)NULL);
	    infoPtr->resultCode = TCL_ERROR;
	    return 0;
	}
    }
    if (!infoPtr->isIncreasing) {
	order = -order;
    }
4712
4713
4714
4715
4716
4717
4718
4719

4720
4721
4722
4723
4724
4725
4726
5353
5354
5355
5356
5357
5358
5359

5360
5361
5362
5363
5364
5365
5366
5367







-
+







    const char *left, const char *right)	/* The strings to compare. */
{
    int uniLeft = 0, uniRight = 0, uniLeftLower, uniRightLower;
    int diff, zeros;
    int secondaryDiff = 0;

    while (1) {
	if (isdigit(UCHAR(*right))		/* INTL: digit */
		if (isdigit(UCHAR(*right))		/* INTL: digit */
		&& isdigit(UCHAR(*left))) {	/* INTL: digit */
	    /*
	     * There are decimal numbers embedded in the two strings. Compare
	     * them as numbers, rather than strings. If one number has more
	     * leading zeros than the other, the number with more leading
	     * zeros sorts later, but only as a secondary choice.
	     */
4776
4777
4778
4779
4780
4781
4782
4783
4784


4785
4786
4787
4788

4789
4790
4791
4792
4793
4794
4795
5417
5418
5419
5420
5421
5422
5423


5424
5425
5426
5427
5428

5429
5430
5431
5432
5433
5434
5435
5436







-
-
+
+



-
+







	/*
	 * Convert character to Unicode for comparison purposes. If either
	 * string is at the terminating null, do a byte-wise comparison and
	 * bail out immediately.
	 */

	if ((*left != '\0') && (*right != '\0')) {
	    left += TclUtfToUCS4(left, &uniLeft);
	    right += TclUtfToUCS4(right, &uniRight);
	    left += TclUtfToUniChar(left, &uniLeft);
	    right += TclUtfToUniChar(right, &uniRight);

	    /*
	     * Convert both chars to lower for the comparison, because
	     * dictionary sorts are case insensitve. Covert to lower, not
	     * dictionary sorts are case-insensitive. Covert to lower, not
	     * upper, so chars between Z and a will sort before A (where most
	     * other interesting punctuations occur).
	     */

	    uniLeftLower = Tcl_UniCharToLower(uniLeft);
	    uniRightLower = Tcl_UniCharToLower(uniRight);
	} else {
4840
4841
4842
4843
4844
4845
4846
4847

4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862

4863
4864


4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879

4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890

4891
4892
4893
4894


4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
5481
5482
5483
5484
5485
5486
5487

5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504


5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520

5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531

5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550







-
+















+
-
-
+
+














-
+










-
+




+
+













static Tcl_Obj *
SelectObjFromSublist(
    Tcl_Obj *objPtr,		/* Obj to select sublist from. */
    SortInfo *infoPtr)		/* Information passed from the top-level
				 * "lsearch" or "lsort" command. */
{
    int i;
    Tcl_Size i;

    /*
     * Quick check for case when no "-index" option is there.
     */

    if (infoPtr->indexc == 0) {
	return objPtr;
    }

    /*
     * Iterate over the indices, traversing through the nested sublists as we
     * go.
     */

    for (i=0 ; i<infoPtr->indexc ; i++) {
	Tcl_Size listLen;
	int listLen, index;
	Tcl_Obj *currentObj;
	int index;
	Tcl_Obj *currentObj, *lastObj=NULL;

	if (TclListObjLength(infoPtr->interp, objPtr, &listLen) != TCL_OK) {
	    infoPtr->resultCode = TCL_ERROR;
	    return NULL;
	}

	index = TclIndexDecode(infoPtr->indexv[i], listLen - 1);

	if (Tcl_ListObjIndex(infoPtr->interp, objPtr, index,
		&currentObj) != TCL_OK) {
	    infoPtr->resultCode = TCL_ERROR;
	    return NULL;
	}
	if (currentObj == NULL) {
	    if (index == (int)TCL_INDEX_NONE) {
	    if (index == TCL_INDEX_NONE) {
		index = TCL_INDEX_END - infoPtr->indexv[i];
		Tcl_SetObjResult(infoPtr->interp, Tcl_ObjPrintf(
			"element end-%d missing from sublist \"%s\"",
			index, TclGetString(objPtr)));
	    } else {
		Tcl_SetObjResult(infoPtr->interp, Tcl_ObjPrintf(
			"element %d missing from sublist \"%s\"",
			index, TclGetString(objPtr)));
	    }
	    Tcl_SetErrorCode(infoPtr->interp, "TCL", "OPERATION", "LSORT",
		    "INDEXFAILED", NULL);
		    "INDEXFAILED", (char *)NULL);
	    infoPtr->resultCode = TCL_ERROR;
	    return NULL;
	}
	objPtr = currentObj;
	Tcl_BounceRefCount(lastObj);
	lastObj = currentObj;
    }
    return objPtr;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * tab-width: 8
 * End:
 */

Changes to generic/tclCmdMZ.c.

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
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
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
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








-
-
-
-
-
+
+
+
+
+









+









+
+
+







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







/*
 * tclCmdMZ.c --
 *
 *	This file contains the top-level command routines for most of the Tcl
 *	built-in commands whose names begin with the letters M to Z. It
 *	contains only commands in the generic core (i.e. those that don't
 *	depend much upon UNIX facilities).
 *
 * Copyright (c) 1987-1993 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 Scriptics Corporation.
 * Copyright (c) 2002 ActiveState Corporation.
 * Copyright (c) 2003-2009 Donal K. Fellows.
 * Copyright © 1987-1993 The Regents of the University of California.
 * Copyright © 1994-1997 Sun Microsystems, Inc.
 * Copyright © 1998-2000 Scriptics Corporation.
 * Copyright © 2002 ActiveState Corporation.
 * Copyright © 2003-2009 Donal K. Fellows.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclCompile.h"
#include "tclRegexp.h"
#include "tclStringTrim.h"
#include "tclTomMath.h"

static inline Tcl_Obj *	During(Tcl_Interp *interp, int resultCode,
			    Tcl_Obj *oldOptions, Tcl_Obj *errorInfo);
static Tcl_NRPostProc	SwitchPostProc;
static Tcl_NRPostProc	TryPostBody;
static Tcl_NRPostProc	TryPostFinal;
static Tcl_NRPostProc	TryPostHandler;
static int		UniCharIsAscii(int character);
static int		UniCharIsHexDigit(int character);
static int		StringCmpOpts(Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[], int *nocase,
			    Tcl_Size *reqlength);

/*
 * Default set of characters to trim in [string trim] and friends. This is a
 * UTF-8 literal string containing all Unicode space characters [TIP #413]
 */

const char tclDefaultTrimSet[] =
	"\x09\x0a\x0b\x0c\x0d " /* ASCII */
	"\xc0\x80" /*     nul (U+0000) */
	"\xc2\x85" /*     next line (U+0085) */
	"\xc2\xa0" /*     non-breaking space (U+00a0) */
	"\xe1\x9a\x80" /* ogham space mark (U+1680) */
	"\xe1\xa0\x8e" /* mongolian vowel separator (U+180e) */
	"\xe2\x80\x80" /* en quad (U+2000) */
	"\xe2\x80\x81" /* em quad (U+2001) */
	"\xe2\x80\x82" /* en space (U+2002) */
	"\xe2\x80\x83" /* em space (U+2003) */
	"\xe2\x80\x84" /* three-per-em space (U+2004) */
	"\xe2\x80\x85" /* four-per-em space (U+2005) */
	"\xe2\x80\x86" /* six-per-em space (U+2006) */
	"\xe2\x80\x87" /* figure space (U+2007) */
	"\xe2\x80\x88" /* punctuation space (U+2008) */
	"\xe2\x80\x89" /* thin space (U+2009) */
	"\xe2\x80\x8a" /* hair space (U+200a) */
	"\xe2\x80\x8b" /* zero width space (U+200b) */
	"\xe2\x80\xa8" /* line separator (U+2028) */
	"\xe2\x80\xa9" /* paragraph separator (U+2029) */
	"\xe2\x80\xaf" /* narrow no-break space (U+202f) */
	"\xe2\x81\x9f" /* medium mathematical space (U+205f) */
	"\xe2\x81\xa0" /* word joiner (U+2060) */
	"\xe3\x80\x80" /* ideographic space (U+3000) */
	"\xef\xbb\xbf" /* zero width no-break space (U+feff) */
	"\x09\x0A\x0B\x0C\x0D " /* ASCII */
	"\xC0\x80" /*     nul (U+0000) */
	"\xC2\x85" /*     next line (U+0085) */
	"\xC2\xA0" /*     non-breaking space (U+00a0) */
	"\xE1\x9A\x80" /* ogham space mark (U+1680) */
	"\xE1\xA0\x8E" /* mongolian vowel separator (U+180e) */
	"\xE2\x80\x80" /* en quad (U+2000) */
	"\xE2\x80\x81" /* em quad (U+2001) */
	"\xE2\x80\x82" /* en space (U+2002) */
	"\xE2\x80\x83" /* em space (U+2003) */
	"\xE2\x80\x84" /* three-per-em space (U+2004) */
	"\xE2\x80\x85" /* four-per-em space (U+2005) */
	"\xE2\x80\x86" /* six-per-em space (U+2006) */
	"\xE2\x80\x87" /* figure space (U+2007) */
	"\xE2\x80\x88" /* punctuation space (U+2008) */
	"\xE2\x80\x89" /* thin space (U+2009) */
	"\xE2\x80\x8A" /* hair space (U+200a) */
	"\xE2\x80\x8B" /* zero width space (U+200b) */
	"\xE2\x80\xA8" /* line separator (U+2028) */
	"\xE2\x80\xA9" /* paragraph separator (U+2029) */
	"\xE2\x80\xAF" /* narrow no-break space (U+202f) */
	"\xE2\x81\x9F" /* medium mathematical space (U+205f) */
	"\xE2\x81\xA0" /* word joiner (U+2060) */
	"\xE3\x80\x80" /* ideographic space (U+3000) */
	"\xEF\xBB\xBF" /* zero width no-break space (U+feff) */
;

/*
 *----------------------------------------------------------------------
 *
 * Tcl_PwdObjCmd --
 *
78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
82
83
84
85
86
87
88

89
90
91
92
93
94
95
96







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_PwdObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *retVal;

    if (objc != 1) {
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
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







-
+




-
+













-
+










-









-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_RegexpObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    size_t offset, stringLength, matchLength, cflags, eflags;
    Tcl_Size offset, stringLength, matchLength, cflags, eflags;
    int i, indices, match, about, all, doinline, numMatchesSaved;
    Tcl_RegExp regExpr;
    Tcl_Obj *objPtr, *startIndex = NULL, *resultPtr = NULL;
    Tcl_RegExpInfo info;
    static const char *const options[] = {
	"-all",		"-about",	"-indices",	"-inline",
	"-expanded",	"-line",	"-linestop",	"-lineanchor",
	"-nocase",	"-start",	"--",		NULL
    };
    enum regexpoptions {
	REGEXP_ALL,	REGEXP_ABOUT,	REGEXP_INDICES,	REGEXP_INLINE,
	REGEXP_EXPANDED,REGEXP_LINE,	REGEXP_LINESTOP,REGEXP_LINEANCHOR,
	REGEXP_NOCASE,	REGEXP_START,	REGEXP_LAST
    };
    } index;

    indices = 0;
    about = 0;
    cflags = TCL_REG_ADVANCED;
    offset = TCL_INDEX_START;
    all = 0;
    doinline = 0;

    for (i = 1; i < objc; i++) {
	const char *name;
	int index;

	name = TclGetString(objv[i]);
	if (name[0] != '-') {
	    break;
	}
	if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", TCL_EXACT,
		&index) != TCL_OK) {
	    goto optionError;
	}
	switch ((enum regexpoptions) index) {
	switch (index) {
	case REGEXP_ALL:
	    all = 1;
	    break;
	case REGEXP_INDICES:
	    indices = 1;
	    break;
	case REGEXP_INLINE:
187
188
189
190
191
192
193
194

195
196
197
198

199
200
201
202
203
204
205
190
191
192
193
194
195
196

197
198
199
200

201
202
203
204
205
206
207
208







-
+



-
+







	case REGEXP_LINESTOP:
	    cflags |= TCL_REG_NLSTOP;
	    break;
	case REGEXP_LINEANCHOR:
	    cflags |= TCL_REG_NLANCH;
	    break;
	case REGEXP_START: {
	    size_t temp;
	    Tcl_Size temp;
	    if (++i >= objc) {
		goto endOfForLoop;
	    }
	    if (TclGetIntForIndexM(interp, objv[i], (size_t)WIDE_MAX - 1, &temp) != TCL_OK) {
	    if (TclGetIntForIndexM(interp, objv[i], TCL_SIZE_MAX - 1, &temp) != TCL_OK) {
		goto optionError;
	    }
	    if (startIndex) {
		Tcl_DecrRefCount(startIndex);
	    }
	    startIndex = objv[i];
	    Tcl_IncrRefCount(startIndex);
225
226
227
228
229
230
231
232

233
234
235
236
237
238
239
228
229
230
231
232
233
234

235
236
237
238
239
240
241
242







-
+







     * no-no.
     */

    if (doinline && ((objc - 2) != 0)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"regexp match variables not allowed when using -inline", -1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "REGEXP",
		"MIX_VAR_INLINE", NULL);
		"MIX_VAR_INLINE", (char *)NULL);
	goto optionError;
    }

    /*
     * Handle the odd about case separately.
     */

257
258
259
260
261
262
263
264

265
266
267
268
269
270
271
260
261
262
263
264
265
266

267
268
269
270
271
272
273
274







-
+








    objPtr = objv[1];
    stringLength = Tcl_GetCharLength(objPtr);

    if (startIndex) {
	TclGetIntForIndexM(interp, startIndex, stringLength, &offset);
	Tcl_DecrRefCount(startIndex);
	if (offset == TCL_INDEX_NONE) {
	if (offset < 0) {
	    offset = TCL_INDEX_START;
	}
    }

    regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags);
    if (regExpr == NULL) {
	return TCL_ERROR;
304
305
306
307
308
309
310
311

312
313
314
315
316
317
318
307
308
309
310
311
312
313

314
315
316
317
318
319
320
321







-
+







	 * considered the start of the line. If for example the pattern {^} is
	 * passed and -start is positive, then the pattern will not match the
	 * start of the string unless the previous character is a newline.
	 */

	if (offset == TCL_INDEX_START) {
	    eflags = 0;
	} else if (offset + 1 > stringLength + 1) {
	} else if (offset > stringLength) {
	    eflags = TCL_REG_NOTBOL;
	} else if (Tcl_GetUniChar(objPtr, offset-1) == '\n') {
	    eflags = 0;
	} else {
	    eflags = TCL_REG_NOTBOL;
	}

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
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







-
+






-
+







-
+








-
+












-
+




-
+







	    /*
	     * It's the number of substitutions, plus one for the matchVar at
	     * index 0
	     */

	    objc = info.nsubs + 1;
	    if (all <= 1) {
		resultPtr = Tcl_NewObj();
		TclNewObj(resultPtr);
	    }
	}
	for (i = 0; i < objc; i++) {
	    Tcl_Obj *newPtr;

	    if (indices) {
		size_t start, end;
		Tcl_Size start, end;
		Tcl_Obj *objs[2];

		/*
		 * Only adjust the match area if there was a match for that
		 * area. (Scriptics Bug 4391/SF Bug #219232)
		 */

		if (i <= (int)info.nsubs && info.matches[i].start != TCL_INDEX_NONE) {
		if (i <= (int)info.nsubs && info.matches[i].start >= 0) {
		    start = offset + info.matches[i].start;
		    end = offset + info.matches[i].end;

		    /*
		     * Adjust index so it refers to the last character in the
		     * match instead of the first character after the match.
		     */

		    if (end + 1 >= offset + 1) {
		    if (end >= offset) {
			end--;
		    }
		} else {
		    start = TCL_INDEX_NONE;
		    end = TCL_INDEX_NONE;
		}

		TclNewIndexObj(objs[0], start);
		TclNewIndexObj(objs[1], end);

		newPtr = Tcl_NewListObj(2, objs);
	    } else {
		if (i <= (int)info.nsubs) {
		if ((i <= (int)info.nsubs) && (info.matches[i].end > 0)) {
		    newPtr = Tcl_GetRange(objPtr,
			    offset + info.matches[i].start,
			    offset + info.matches[i].end - 1);
		} else {
		    newPtr = Tcl_NewObj();
		    TclNewObj(newPtr);
		}
	    }
	    if (doinline) {
		if (Tcl_ListObjAppendElement(interp, resultPtr, newPtr)
			!= TCL_OK) {
		    Tcl_DecrRefCount(newPtr);
		    Tcl_DecrRefCount(resultPtr);
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
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







-
+
















-
+








	/*
	 * Adjust the offset to the character just after the last one in the
	 * matchVar and increment all to count how many times we are making a
	 * match. We always increment the offset by at least one to prevent
	 * endless looping (as in the case: regexp -all {a*} a). Otherwise,
	 * when we match the NULL string at the end of the input string, we
	 * will loop indefinately (because the length of the match is 0, so
	 * will loop indefinitely (because the length of the match is 0, so
	 * offset never changes).
	 */

	matchLength = (info.matches[0].end - info.matches[0].start);

	offset += info.matches[0].end;

	/*
	 * A match of length zero could happen for {^} {$} or {.*} and in
	 * these cases we always want to bump the index up one.
	 */

	if (matchLength == 0) {
	    offset++;
	}
	all++;
	if (offset + 1 >= stringLength + 1) {
	if (offset >= stringLength) {
	    break;
	}
    }

    /*
     * Set the interpreter's object result to an integer object with value 1
     * if -all wasn't specified, otherwise it's all-1 (the number of times
478
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
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







-
+




-
-
-
+
+
+














-
+







-
+

-









-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_RegsubObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int result, cflags, all, match, command, numParts;
    size_t idx, wlen, wsublen = 0, offset, numMatches;
    size_t start, end, subStart, subEnd;
    int result, cflags, all, match, command;
    Tcl_Size idx, wlen, wsublen = 0, offset, numMatches, numParts;
    Tcl_Size start, end, subStart, subEnd;
    Tcl_RegExp regExpr;
    Tcl_RegExpInfo info;
    Tcl_Obj *resultPtr, *subPtr, *objPtr, *startIndex = NULL;
    Tcl_UniChar ch, *wsrc, *wfirstChar, *wstring, *wsubspec = 0, *wend;

    static const char *const options[] = {
	"-all",		"-command",	"-expanded",	"-line",
	"-linestop",	"-lineanchor",	"-nocase",	"-start",
	"--",		NULL
    };
    enum regsubobjoptions {
	REGSUB_ALL,	 REGSUB_COMMAND,    REGSUB_EXPANDED, REGSUB_LINE,
	REGSUB_LINESTOP, REGSUB_LINEANCHOR, REGSUB_NOCASE,   REGSUB_START,
	REGSUB_LAST
    };
    } index;

    cflags = TCL_REG_ADVANCED;
    all = 0;
    offset = TCL_INDEX_START;
    command = 0;
    resultPtr = NULL;

    for (idx = 1; idx < (size_t)objc; idx++) {
    for (idx = 1; idx < objc; idx++) {
	const char *name;
	int index;

	name = TclGetString(objv[idx]);
	if (name[0] != '-') {
	    break;
	}
	if (Tcl_GetIndexFromObj(interp, objv[idx], options, "option",
		TCL_EXACT, &index) != TCL_OK) {
	    goto optionError;
	}
	switch ((enum regsubobjoptions) index) {
	switch (index) {
	case REGSUB_ALL:
	    all = 1;
	    break;
	case REGSUB_NOCASE:
	    cflags |= TCL_REG_NOCASE;
	    break;
	case REGSUB_COMMAND:
543
544
545
546
547
548
549
550
551


552
553
554

555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571

572
573
574
575
576
577
578
579
580
581
582
583
584
585

586
587
588
589
590


591
592
593
594

595
596
597
598
599
600
601
602

603
604
605
606
607
608
609
610
611
612
613



614
615
616
617
618
619
620
621
622
623
624
625
626
627
628


629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644

645
646
647
648
649
650
651

652
653
654
655
656
657
658
545
546
547
548
549
550
551


552
553
554
555

556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572

573
574
575
576
577
578
579
580
581
582
583
584
585
586

587
588
589
590


591
592
593
594
595

596
597
598
599
600
601
602
603

604
605
606
607
608
609
610
611
612



613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628


629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645

646
647
648
649
650
651
652

653
654
655
656
657
658
659
660







-
-
+
+


-
+
















-
+













-
+



-
-
+
+



-
+







-
+








-
-
-
+
+
+













-
-
+
+















-
+






-
+







	case REGSUB_LINESTOP:
	    cflags |= TCL_REG_NLSTOP;
	    break;
	case REGSUB_LINEANCHOR:
	    cflags |= TCL_REG_NLANCH;
	    break;
	case REGSUB_START: {
	    size_t temp;
	    if (++idx >= (size_t)objc) {
	    Tcl_Size temp;
	    if (++idx >= objc) {
		goto endOfForLoop;
	    }
	    if (TclGetIntForIndexM(interp, objv[idx], (size_t)WIDE_MAX - 1, &temp) != TCL_OK) {
	    if (TclGetIntForIndexM(interp, objv[idx], TCL_SIZE_MAX - 1, &temp) != TCL_OK) {
		goto optionError;
	    }
	    if (startIndex) {
		Tcl_DecrRefCount(startIndex);
	    }
	    startIndex = objv[idx];
	    Tcl_IncrRefCount(startIndex);
	    break;
	}
	case REGSUB_LAST:
	    idx++;
	    goto endOfForLoop;
	}
    }

  endOfForLoop:
    if ((size_t)objc < idx + 3 || (size_t)objc > idx + 4) {
    if (objc < idx + 3 || objc > idx + 4) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"?-option ...? exp string subSpec ?varName?");
    optionError:
	if (startIndex) {
	    Tcl_DecrRefCount(startIndex);
	}
	return TCL_ERROR;
    }

    objc -= idx;
    objv += idx;

    if (startIndex) {
	size_t stringLength = Tcl_GetCharLength(objv[1]);
	Tcl_Size stringLength = Tcl_GetCharLength(objv[1]);

	TclGetIntForIndexM(interp, startIndex, stringLength, &offset);
	Tcl_DecrRefCount(startIndex);
	if (offset == TCL_INDEX_NONE) {
	    offset = TCL_INDEX_START;
	if (offset < 0) {
	    offset = 0;
	}
    }

    if (all && (offset == TCL_INDEX_START) && (command == 0)
    if (all && (offset == 0) && (command == 0)
	    && (strpbrk(TclGetString(objv[2]), "&\\") == NULL)
	    && (strpbrk(TclGetString(objv[0]), "*+?{}()[].\\|^$") == NULL)) {
	/*
	 * This is a simple one pair string map situation. We make use of a
	 * slightly modified version of the one pair STR_MAP code.
	 */

	size_t slen;
	Tcl_Size slen;
	int nocase, wsrclc;
	int (*strCmpFn)(const Tcl_UniChar*,const Tcl_UniChar*,size_t);
	Tcl_UniChar *p;

	numMatches = 0;
	nocase = (cflags & TCL_REG_NOCASE);
	strCmpFn = nocase ? TclUniCharNcasecmp : TclUniCharNcmp;

	wsrc = TclGetUnicodeFromObj(objv[0], &slen);
	wstring = TclGetUnicodeFromObj(objv[1], &wlen);
	wsubspec = TclGetUnicodeFromObj(objv[2], &wsublen);
	wsrc = Tcl_GetUnicodeFromObj(objv[0], &slen);
	wstring = Tcl_GetUnicodeFromObj(objv[1], &wlen);
	wsubspec = Tcl_GetUnicodeFromObj(objv[2], &wsublen);
	wend = wstring + wlen - (slen ? slen - 1 : 0);
	result = TCL_OK;

	if (slen == 0) {
	    /*
	     * regsub behavior for "" matches between each character. 'string
	     * map' skips the "" case.
	     */

	    if (wstring < wend) {
		resultPtr = Tcl_NewUnicodeObj(wstring, 0);
		Tcl_IncrRefCount(resultPtr);
		for (; wstring < wend; wstring++) {
		    TclAppendUnicodeToObj(resultPtr, wsubspec, wsublen);
		    TclAppendUnicodeToObj(resultPtr, wstring, 1);
		    Tcl_AppendUnicodeToObj(resultPtr, wsubspec, wsublen);
		    Tcl_AppendUnicodeToObj(resultPtr, wstring, 1);
		    numMatches++;
		}
		wlen = 0;
	    }
	} else {
	    wsrclc = Tcl_UniCharToLower(*wsrc);
	    for (p = wfirstChar = wstring; wstring < wend; wstring++) {
		if ((*wstring == *wsrc ||
			(nocase && Tcl_UniCharToLower(*wstring)==wsrclc)) &&
			(slen==1 || (strCmpFn(wstring, wsrc, slen) == 0))) {
		    if (numMatches == 0) {
			resultPtr = Tcl_NewUnicodeObj(wstring, 0);
			Tcl_IncrRefCount(resultPtr);
		    }
		    if (p != wstring) {
			TclAppendUnicodeToObj(resultPtr, p, wstring - p);
			Tcl_AppendUnicodeToObj(resultPtr, p, wstring - p);
			p = wstring + slen;
		    } else {
			p += slen;
		    }
		    wstring = p - 1;

		    TclAppendUnicodeToObj(resultPtr, wsubspec, wsublen);
		    Tcl_AppendUnicodeToObj(resultPtr, wsubspec, wsublen);
		    numMatches++;
		}
	    }
	    if (numMatches) {
		wlen    = wfirstChar + wlen - p;
		wstring = p;
	    }
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
707
708
709
710

711
712
713
714
715
716
717
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
707
708
709
710
711

712
713
714
715
716
717
718
719







-
+







-
+
















-
+






-
+







	/*
	 * In command-prefix mode, we require that the third non-option
	 * argument be a list, so we enforce that here. Afterwards, we fetch
	 * the RE compilation again in case objv[0] and objv[2] are the same
	 * object. (If they aren't, that's cheap to do.)
	 */

	if (Tcl_ListObjLength(interp, objv[2], &numParts) != TCL_OK) {
	if (TclListObjLength(interp, objv[2], &numParts) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (numParts < 1) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "command prefix must be a list of at least one element",
		    -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "REGSUB",
		    "CMDEMPTY", NULL);
		    "CMDEMPTY", (char *)NULL);
	    return TCL_ERROR;
	}
	regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags);
    }

    /*
     * Make sure to avoid problems where the objects are shared. This can
     * cause RegExpObj <> UnicodeObj shimmering that causes data corruption.
     * [Bug #461322]
     */

    if (objv[1] == objv[0]) {
	objPtr = Tcl_DuplicateObj(objv[1]);
    } else {
	objPtr = objv[1];
    }
    wstring = TclGetUnicodeFromObj(objPtr, &wlen);
    wstring = Tcl_GetUnicodeFromObj(objPtr, &wlen);
    if (objv[2] == objv[0]) {
	subPtr = Tcl_DuplicateObj(objv[2]);
    } else {
	subPtr = objv[2];
    }
    if (!command) {
	wsubspec = TclGetUnicodeFromObj(subPtr, &wsublen);
	wsubspec = Tcl_GetUnicodeFromObj(subPtr, &wsublen);
    }

    result = TCL_OK;

    /*
     * The following loop is to handle multiple matches within the same source
     * string; each iteration handles one match and its corresponding
747
748
749
750
751
752
753
754

755
756
757
758
759
760
761
762
763
764
765
766
767

768
769
770
771
772
773
774
775
776
777
778

779
780

781
782
783
784
785
786
787
788

789
790
791
792
793
794
795
749
750
751
752
753
754
755

756
757
758
759
760
761
762
763
764
765
766
767
768

769
770
771
772
773
774
775
776
777
778
779

780
781

782
783
784
785
786
787
788
789

790
791
792
793
794
795
796
797







-
+












-
+










-
+

-
+







-
+







	    Tcl_IncrRefCount(resultPtr);
	    if (offset > TCL_INDEX_START) {
		/*
		 * Copy the initial portion of the string in if an offset was
		 * specified.
		 */

		TclAppendUnicodeToObj(resultPtr, wstring, offset);
		Tcl_AppendUnicodeToObj(resultPtr, wstring, offset);
	    }
	}
	numMatches++;

	/*
	 * Copy the portion of the source string before the match to the
	 * result variable.
	 */

	Tcl_RegExpGetInfo(regExpr, &info);
	start = info.matches[0].start;
	end = info.matches[0].end;
	TclAppendUnicodeToObj(resultPtr, wstring + offset, start);
	Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, start);

	/*
	 * In command-prefix mode, the substitutions are added as quoted
	 * arguments to the subSpec to form a command, that is then executed
	 * and the result used as the string to substitute in. Actually,
	 * everything is passed through Tcl_EvalObjv, as that's much faster.
	 */

	if (command) {
	    Tcl_Obj **args = NULL, **parts;
	    int numArgs;
	    Tcl_Size numArgs;

	    Tcl_ListObjGetElements(interp, subPtr, &numParts, &parts);
	    TclListObjGetElements(interp, subPtr, &numParts, &parts);
	    numArgs = numParts + info.nsubs + 1;
	    args = (Tcl_Obj **)Tcl_Alloc(sizeof(Tcl_Obj*) * numArgs);
	    memcpy(args, parts, sizeof(Tcl_Obj*) * numParts);

	    for (idx = 0 ; idx <= info.nsubs ; idx++) {
		subStart = info.matches[idx].start;
		subEnd = info.matches[idx].end;
		if ((subStart != TCL_INDEX_NONE) && (subEnd != TCL_INDEX_NONE)) {
		if ((subStart >= 0) && (subEnd >= 0)) {
		    args[idx + numParts] = Tcl_NewUnicodeObj(
			    wstring + offset + subStart, subEnd - subStart);
		} else {
		    args[idx + numParts] = Tcl_NewObj();
		}
		Tcl_IncrRefCount(args[idx + numParts]);
	    }
823
824
825
826
827
828
829
830

831
832
833
834
835
836
837
838
839
840
841
842

843
844
845
846
847
848
849
825
826
827
828
829
830
831

832
833
834
835
836
837
838
839
840
841
842
843

844
845
846
847
848
849
850
851







-
+











-
+







	    Tcl_ResetResult(interp);

	    /*
	     * Refetch the unicode, in case the representation was smashed by
	     * the user code.
	     */

	    wstring = TclGetUnicodeFromObj(objPtr, &wlen);
	    wstring = Tcl_GetUnicodeFromObj(objPtr, &wlen);

	    offset += end;
	    if (end == 0 || start == end) {
		/*
		 * Always consume at least one character of the input string
		 * in order to prevent infinite loops, even when we
		 * technically matched the empty string; we must not match
		 * again at the same spot.
		 */

		if (offset < wlen) {
		    TclAppendUnicodeToObj(resultPtr, wstring + offset, 1);
		    Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, 1);
		}
		offset++;
	    }
	    if (all) {
		continue;
	    } else {
		break;
864
865
866
867
868
869
870
871

872
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
898
899
900
901
902
903
904
905

906
907
908
909
910
911
912
913
914
915

916
917
918
919
920
921
922
923
924
925
926
927

928
929
930
931
932
933
934
866
867
868
869
870
871
872

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
898
899
900
901
902
903
904
905
906

907
908
909
910
911
912
913
914
915
916

917
918
919
920
921
922
923
924
925
926
927
928

929
930
931
932
933
934
935
936







-
+













-
+






-
-
+
+











-
+









-
+











-
+







		idx = 0;
	    } else if (ch == '\\') {
		ch = wsrc[1];
		if ((ch >= '0') && (ch <= '9')) {
		    idx = ch - '0';
		} else if ((ch == '\\') || (ch == '&')) {
		    *wsrc = ch;
		    TclAppendUnicodeToObj(resultPtr, wfirstChar,
		    Tcl_AppendUnicodeToObj(resultPtr, wfirstChar,
			    wsrc - wfirstChar + 1);
		    *wsrc = '\\';
		    wfirstChar = wsrc + 2;
		    wsrc++;
		    continue;
		} else {
		    continue;
		}
	    } else {
		continue;
	    }

	    if (wfirstChar != wsrc) {
		TclAppendUnicodeToObj(resultPtr, wfirstChar,
		Tcl_AppendUnicodeToObj(resultPtr, wfirstChar,
			wsrc - wfirstChar);
	    }

	    if (idx <= info.nsubs) {
		subStart = info.matches[idx].start;
		subEnd = info.matches[idx].end;
		if ((subStart != TCL_INDEX_NONE) && (subEnd != TCL_INDEX_NONE)) {
		    TclAppendUnicodeToObj(resultPtr,
		if ((subStart >= 0) && (subEnd >= 0)) {
		    Tcl_AppendUnicodeToObj(resultPtr,
			    wstring + offset + subStart, subEnd - subStart);
		}
	    }

	    if (*wsrc == '\\') {
		wsrc++;
	    }
	    wfirstChar = wsrc + 1;
	}

	if (wfirstChar != wsrc) {
	    TclAppendUnicodeToObj(resultPtr, wfirstChar, wsrc - wfirstChar);
	    Tcl_AppendUnicodeToObj(resultPtr, wfirstChar, wsrc - wfirstChar);
	}

	if (end == 0) {
	    /*
	     * Always consume at least one character of the input string in
	     * order to prevent infinite loops.
	     */

	    if (offset < wlen) {
		TclAppendUnicodeToObj(resultPtr, wstring + offset, 1);
		Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, 1);
	    }
	    offset++;
	} else {
	    offset += end;
	    if (start == end) {
		/*
		 * We matched an empty string, which means we must go forward
		 * one more step so we don't match again at the same spot.
		 */

		if (offset < wlen) {
		    TclAppendUnicodeToObj(resultPtr, wstring + offset, 1);
		    Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, 1);
		}
		offset++;
	    }
	}
	if (!all) {
	    break;
	}
945
946
947
948
949
950
951
952

953
954
955
956
957
958
959
947
948
949
950
951
952
953

954
955
956
957
958
959
960
961







-
+







	 * On zero matches, just ignore the offset, since it shouldn't matter
	 * to us in this case, and the user may have skewed it.
	 */

	resultPtr = objv[1];
	Tcl_IncrRefCount(resultPtr);
    } else if (offset < wlen) {
	TclAppendUnicodeToObj(resultPtr, wstring + offset, wlen - offset);
	Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, wlen - offset);
    }
    if (objc == 4) {
	if (Tcl_ObjSetVar2(interp, objv[3], NULL, resultPtr,
		TCL_LEAVE_ERR_MSG) == NULL) {
	    result = TCL_ERROR;
	} else {
	    /*
999
1000
1001
1002
1003
1004
1005
1006

1007
1008
1009
1010
1011
1012
1013
1001
1002
1003
1004
1005
1006
1007

1008
1009
1010
1011
1012
1013
1014
1015







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_RenameObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *oldName, *newName;

    if (objc != 3) {
1035
1036
1037
1038
1039
1040
1041
1042

1043
1044
1045
1046
1047
1048
1049
1037
1038
1039
1040
1041
1042
1043

1044
1045
1046
1047
1048
1049
1050
1051







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ReturnObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int code, level;
    Tcl_Obj *returnOpts;

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
1116
1117
1118
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
1116
1117
1118
1119
1120







-
+









-
+











-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_SourceObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, TclNRSourceObjCmd, clientData, objc, objv);
}

int
TclNRSourceObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *encodingName = NULL;
    Tcl_Obj *fileName;
    int result;
    void **pkgFiles = NULL;
    void *names = NULL;

    if (objc < 2 || objc > 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "?-encoding name? fileName");
	Tcl_WrongNumArgs(interp, 1, objv, "?-encoding encoding? fileName");
	return TCL_ERROR;
    }

    fileName = objv[objc-1];

    if (objc == 4) {
	static const char *const options[] = {
1166
1167
1168
1169
1170
1171
1172
1173

1174
1175
1176
1177
1178
1179
1180
1181
1182
1183

1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198

1199
1200
1201
1202
1203
1204
1205
1168
1169
1170
1171
1172
1173
1174

1175
1176
1177
1178
1179
1180
1181
1182
1183
1184

1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199

1200
1201
1202
1203
1204
1205
1206
1207







-
+









-
+














-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_SplitObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int ch = 0;
    int len;
    const char *splitChars;
    const char *stringPtr;
    const char *end;
    size_t splitCharLen, stringLen;
    Tcl_Size splitCharLen, stringLen;
    Tcl_Obj *listPtr, *objPtr;

    if (objc == 2) {
	splitChars = " \n\t\r";
	splitCharLen = 4;
    } else if (objc == 3) {
	splitChars = TclGetStringFromObj(objv[2], &splitCharLen);
    } else {
	Tcl_WrongNumArgs(interp, 1, objv, "string ?splitChars?");
	return TCL_ERROR;
    }

    stringPtr = TclGetStringFromObj(objv[1], &stringLen);
    end = stringPtr + stringLen;
    listPtr = Tcl_NewObj();
    TclNewObj(listPtr);

    if (stringLen == 0) {
	/*
	 * Do nothing.
	 */
    } else if (splitCharLen == 0) {
	Tcl_HashTable charReuseTable;
1214
1215
1216
1217
1218
1219
1220
1221

1222
1223
1224
1225
1226
1227
1228
1216
1217
1218
1219
1220
1221
1222

1223
1224
1225
1226
1227
1228
1229
1230







-
+







	 * is a *major* win when splitting on a long string (especially in the
	 * megabyte range!) - DKF
	 */

	Tcl_InitHashTable(&charReuseTable, TCL_ONE_WORD_KEYS);

	for ( ; stringPtr < end; stringPtr += len) {
	    len = TclUtfToUCS4(stringPtr, &ch);
	    len = TclUtfToUniChar(stringPtr, &ch);
	    hPtr = Tcl_CreateHashEntry(&charReuseTable, INT2PTR(ch), &isNew);
	    if (isNew) {
		TclNewStringObj(objPtr, stringPtr, len);

		/*
		 * Don't need to fiddle with refcount...
		 */
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
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







-
+












-
+










-
+

-
+







	Tcl_DeleteHashTable(&charReuseTable);

    } else if (splitCharLen == 1) {
	const char *p;

	/*
	 * Handle the special case of splitting on a single character. This is
	 * only true for the one-char ASCII case, as one unicode char is > 1
	 * only true for the one-char ASCII case, as one Unicode char is > 1
	 * byte in length.
	 */

	while (*stringPtr && (p=strchr(stringPtr,*splitChars)) != NULL) {
	    objPtr = Tcl_NewStringObj(stringPtr, p - stringPtr);
	    Tcl_ListObjAppendElement(NULL, listPtr, objPtr);
	    stringPtr = p + 1;
	}
	TclNewStringObj(objPtr, stringPtr, end - stringPtr);
	Tcl_ListObjAppendElement(NULL, listPtr, objPtr);
    } else {
	const char *element, *p, *splitEnd;
	size_t splitLen;
	Tcl_Size splitLen;
	int splitChar;

	/*
	 * Normal case: split on any of a given set of characters. Discard
	 * instances of the split characters.
	 */

	splitEnd = splitChars + splitCharLen;

	for (element = stringPtr; stringPtr < end; stringPtr += len) {
	    len = TclUtfToUCS4(stringPtr, &ch);
	    len = TclUtfToUniChar(stringPtr, &ch);
	    for (p = splitChars; p < splitEnd; p += splitLen) {
		splitLen = TclUtfToUCS4(p, &splitChar);
		splitLen = TclUtfToUniChar(p, &splitChar);
		if (ch == splitChar) {
		    TclNewStringObj(objPtr, element, stringPtr - element);
		    Tcl_ListObjAppendElement(NULL, listPtr, objPtr);
		    element = stringPtr + len;
		    break;
		}
	    }
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
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







-
+




-
+








-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringFirstCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    size_t start = TCL_INDEX_START;
    Tcl_Size start = TCL_INDEX_START;

    if (objc < 3 || objc > 4) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"needleString haystackString ?startIndex?");
	return TCL_ERROR;
    }

    if (objc == 4) {
	size_t end = Tcl_GetCharLength(objv[2]) - 1;
	Tcl_Size end = Tcl_GetCharLength(objv[2]) - 1;

	if (TCL_OK != TclGetIntForIndexM(interp, objv[3], end, &start)) {
	    return TCL_ERROR;
	}
    }
    Tcl_SetObjResult(interp, TclStringFirst(objv[1], objv[2], start));
    return TCL_OK;
1343
1344
1345
1346
1347
1348
1349
1350

1351
1352
1353
1354
1355

1356
1357
1358
1359
1360
1361
1362
1363
1364

1365
1366
1367
1368
1369
1370
1371
1345
1346
1347
1348
1349
1350
1351

1352
1353
1354
1355
1356

1357
1358
1359
1360
1361
1362
1363
1364
1365

1366
1367
1368
1369
1370
1371
1372
1373







-
+




-
+








-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringLastCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    size_t last = TCL_INDEX_END;
    Tcl_Size last = TCL_SIZE_MAX;

    if (objc < 3 || objc > 4) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"needleString haystackString ?lastIndex?");
	return TCL_ERROR;
    }

    if (objc == 4) {
	size_t end = Tcl_GetCharLength(objv[2]) - 1;
	Tcl_Size end = Tcl_GetCharLength(objv[2]) - 1;

	if (TCL_OK != TclGetIntForIndexM(interp, objv[3], end, &last)) {
	    return TCL_ERROR;
	}
    }
    Tcl_SetObjResult(interp, TclStringLast(objv[1], objv[2], last));
    return TCL_OK;
1387
1388
1389
1390
1391
1392
1393
1394

1395
1396
1397
1398
1399

1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415

1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1389
1390
1391
1392
1393
1394
1395

1396
1397
1398
1399
1400

1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416

1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436



1437
1438
1439
1440
1441
1442
1443







-
+




-
+















-
+



















-
-
-







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringIndexCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    size_t index, end;
    Tcl_Size index, end;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "string charIndex");
	return TCL_ERROR;
    }

    /*
     * Get the char length to calculate what 'end' means.
     */

    end = Tcl_GetCharLength(objv[1]) - 1;
    if (TclGetIntForIndexM(interp, objv[2], end, &index) != TCL_OK) {
	return TCL_ERROR;
    }

    if ((index != TCL_INDEX_NONE) && (index + 1 <= end + 1)) {
    if ((index >= 0) && (index <= end)) {
	int ch = Tcl_GetUniChar(objv[1], index);

	if (ch == -1) {
	    return TCL_OK;
	}

	/*
	 * If we have a ByteArray object, we're careful to generate a new
	 * bytearray for a result.
	 */

	if (TclIsPureByteArray(objv[1])) {
	    unsigned char uch = UCHAR(ch);

	    Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(&uch, 1));
	} else {
	    char buf[4] = "";

	    end = Tcl_UniCharToUtf(ch, buf);
	    if ((ch >= 0xD800) && (end < 3)) {
		end += Tcl_UniCharToUtf(-1, buf + end);
	    }
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, end));
	}
    }
    return TCL_OK;
}

/*
1457
1458
1459
1460
1461
1462
1463
1464

1465
1466
1467
1468
1469
1470


1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483

1484
1485
1486
1487
1488
1489
1490
1456
1457
1458
1459
1460
1461
1462

1463
1464
1465
1466
1467


1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481

1482
1483
1484
1485
1486
1487
1488
1489







-
+




-
-
+
+












-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringInsertCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter */
    int objc,			/* Number of arguments */
    Tcl_Obj *const objv[])	/* Argument objects */
{
    size_t length;		/* String length */
    size_t index;		/* Insert index */
    Tcl_Size length;		/* String length */
    Tcl_Size index;		/* Insert index */
    Tcl_Obj *outObj;		/* Output object */

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "string index insertString");
	return TCL_ERROR;
    }

    length = Tcl_GetCharLength(objv[1]);
    if (TclGetIntForIndexM(interp, objv[2], length, &index) != TCL_OK) {
	return TCL_ERROR;
    }

    if (index == TCL_INDEX_NONE) {
    if (index < 0) {
	index = TCL_INDEX_START;
    }
    if (index > length) {
	index = length;
    }

    outObj = TclStringReplace(interp, objv[1], index, 0, objv[3],
1514
1515
1516
1517
1518
1519
1520
1521

1522
1523
1524
1525
1526
1527
1528

1529
1530

1531
1532
1533
1534
1535
1536
1537
1538
1539
1540


1541
1542
1543
1544
1545
1546
1547
1548
1549



1550
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
1513
1514
1515
1516
1517
1518
1519

1520
1521
1522
1523
1524
1525
1526

1527


1528
1529
1530
1531
1532
1533
1534
1535
1536


1537
1538
1539
1540
1541
1542
1543
1544



1545
1546
1547
1548
1549
1550
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







-
+






-
+
-
-
+








-
-
+
+






-
-
-
+
+
+





-
+













-
-




-
+


















-
+









-
+












-
+
















-
+
+












-
+
-







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringIsCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *string1, *end, *stop;
    int (*chcomp)(int) = NULL;	/* The UniChar comparison function. */
    int i, result = 1, strict = 0, index, length3;
    int i, result = 1, strict = 0;
    size_t failat = 0;
    size_t length1, length2;
    Tcl_Size failat = 0, length1, length2, length3;
    Tcl_Obj *objPtr, *failVarObj = NULL;
    Tcl_WideInt w;

    static const char *const isClasses[] = {
	"alnum",	"alpha",	"ascii",	"control",
	"boolean",	"dict",		"digit",	"double",
	"entier",	"false",	"graph",	"integer",
	"list",		"lower",	"print",	"punct",
	"space",	"true",		"upper",	"wideinteger",
	"wordchar",	"xdigit",	NULL
	"space",	"true",		"upper",
	"wideinteger", "wordchar",	"xdigit",	NULL
    };
    enum isClassesEnum {
	STR_IS_ALNUM,	STR_IS_ALPHA,	STR_IS_ASCII,	STR_IS_CONTROL,
	STR_IS_BOOL,	STR_IS_DICT,	STR_IS_DIGIT,	STR_IS_DOUBLE,
	STR_IS_ENTIER,	STR_IS_FALSE,	STR_IS_GRAPH,	STR_IS_INT,
	STR_IS_LIST,	STR_IS_LOWER,	STR_IS_PRINT,	STR_IS_PUNCT,
	STR_IS_SPACE,	STR_IS_TRUE,	STR_IS_UPPER,	STR_IS_WIDE,
	STR_IS_WORD,	STR_IS_XDIGIT
    };
	STR_IS_SPACE,	STR_IS_TRUE,	STR_IS_UPPER,
	STR_IS_WIDE,	STR_IS_WORD,	STR_IS_XDIGIT
    } index;
    static const char *const isOptions[] = {
	"-strict", "-failindex", NULL
    };
    enum isOptionsEnum {
	OPT_STRICT, OPT_FAILIDX
    };
    } idx2;

    if (objc < 3 || objc > 6) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"class ?-strict? ?-failindex var? str");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], isClasses, "class", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }

    if (objc != 3) {
	for (i = 2; i < objc-1; i++) {
	    int idx2;

	    if (Tcl_GetIndexFromObj(interp, objv[i], isOptions, "option", 0,
		    &idx2) != TCL_OK) {
		return TCL_ERROR;
	    }
	    switch ((enum isOptionsEnum) idx2) {
	    switch (idx2) {
	    case OPT_STRICT:
		strict = 1;
		break;
	    case OPT_FAILIDX:
		if (i+1 >= objc-1) {
		    Tcl_WrongNumArgs(interp, 2, objv,
			    "?-strict? ?-failindex var? str");
		    return TCL_ERROR;
		}
		failVarObj = objv[++i];
		break;
	    }
	}
    }

    /*
     * We get the objPtr so that we can short-cut for some classes by checking
     * the object type (int and double), but we need the string otherwise,
     * because we don't want any conversion of type occuring (as, for example,
     * because we don't want any conversion of type occurring (as, for example,
     * Tcl_Get*FromObj would do).
     */

    objPtr = objv[objc-1];

    /*
     * When entering here, result == 1 and failat == 0.
     */

    switch ((enum isClassesEnum) index) {
    switch (index) {
    case STR_IS_ALNUM:
	chcomp = Tcl_UniCharIsAlnum;
	break;
    case STR_IS_ALPHA:
	chcomp = Tcl_UniCharIsAlpha;
	break;
    case STR_IS_ASCII:
	chcomp = UniCharIsAscii;
	break;
    case STR_IS_BOOL:
    case STR_IS_TRUE:
    case STR_IS_FALSE:
	if (!TclHasIntRep(objPtr, &tclBooleanType)
	if (!TclHasInternalRep(objPtr, &tclBooleanType)
		&& (TCL_OK != TclSetBooleanFromAny(NULL, objPtr))) {
	    if (strict) {
		result = 0;
	    } else {
		string1 = TclGetStringFromObj(objPtr, &length1);
		result = length1 == 0;
	    }
	} else if ((objPtr->internalRep.wideValue != 0)
		? (index == STR_IS_FALSE) : (index == STR_IS_TRUE)) {
	    result = 0;
	}
	break;
    case STR_IS_CONTROL:
	chcomp = Tcl_UniCharIsControl;
	break;
    case STR_IS_DICT: {
	int dresult, dsize;
	int dresult;
	Tcl_Size dsize;

	dresult = Tcl_DictObjSize(interp, objPtr, &dsize);
	Tcl_ResetResult(interp);
	result = (dresult == TCL_OK) ? 1 : 0;
	if (dresult != TCL_OK && failVarObj != NULL) {
	    /*
	     * Need to figure out where the list parsing failed, which is
	     * fairly expensive. This is adapted from the core of
	     * SetDictFromAny().
	     */

	    const char *elemStart, *nextElem;
	    int lenRemain;
	    Tcl_Size lenRemain, elemSize;
	    size_t elemSize;
	    const char *p;

	    string1 = TclGetStringFromObj(objPtr, &length1);
	    end = string1 + length1;
	    failat = -1;
	    for (p=string1, lenRemain=length1; lenRemain > 0;
		    p=nextElem, lenRemain=end-nextElem) {
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
1749
1750
1751
1752
1753
1754
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
1749
1750







-
-
-
+
+
+










-
+







-
+









-
-
+
+










-
+

















-
+







	}
	break;
    }
    case STR_IS_DIGIT:
	chcomp = Tcl_UniCharIsDigit;
	break;
    case STR_IS_DOUBLE: {
	if (TclHasIntRep(objPtr, &tclDoubleType) ||
		TclHasIntRep(objPtr, &tclIntType) ||
		TclHasIntRep(objPtr, &tclBignumType)) {
	if (TclHasInternalRep(objPtr, &tclDoubleType) ||
		TclHasInternalRep(objPtr, &tclIntType) ||
		TclHasInternalRep(objPtr, &tclBignumType)) {
	    break;
	}
	string1 = TclGetStringFromObj(objPtr, &length1);
	if (length1 == 0) {
	    if (strict) {
		result = 0;
	    }
	    goto str_is_done;
	}
	end = string1 + length1;
	if (TclParseNumber(NULL, objPtr, NULL, NULL, -1,
	if (TclParseNumber(NULL, objPtr, NULL, NULL, TCL_INDEX_NONE,
		(const char **) &stop, 0) != TCL_OK) {
	    result = 0;
	    failat = 0;
	} else {
	    failat = stop - string1;
	    if (stop < end) {
		result = 0;
		TclFreeIntRep(objPtr);
		TclFreeInternalRep(objPtr);
	    }
	}
	break;
    }
    case STR_IS_GRAPH:
	chcomp = Tcl_UniCharIsGraph;
	break;
    case STR_IS_INT:
    case STR_IS_ENTIER:
	if (TclHasIntRep(objPtr, &tclIntType) ||
		TclHasIntRep(objPtr, &tclBignumType)) {
	if (TclHasInternalRep(objPtr, &tclIntType) ||
		TclHasInternalRep(objPtr, &tclBignumType)) {
	    break;
	}
	string1 = TclGetStringFromObj(objPtr, &length1);
	if (length1 == 0) {
	    if (strict) {
		result = 0;
	    }
	    goto str_is_done;
	}
	end = string1 + length1;
	if (TclParseNumber(NULL, objPtr, NULL, NULL, -1,
	if (TclParseNumber(NULL, objPtr, NULL, NULL, TCL_INDEX_NONE,
		(const char **) &stop, TCL_PARSE_INTEGER_ONLY) == TCL_OK) {
	    if (stop == end) {
		/*
		 * Entire string parses as an integer.
		 */

		break;
	    } else {
		/*
		 * Some prefix parsed as an integer, but not the whole string,
		 * so return failure index as the point where parsing stopped.
		 * Clear out the internal rep, since keeping it would leave
		 * *objPtr in an inconsistent state.
		 */

		result = 0;
		failat = stop - string1;
		TclFreeIntRep(objPtr);
		TclFreeInternalRep(objPtr);
	    }
	} else {
	    /*
	     * No prefix is a valid integer. Fail at beginning.
	     */

	    result = 0;
1773
1774
1775
1776
1777
1778
1779
1780

1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800

1801
1802
1803
1804
1805
1806
1807
1769
1770
1771
1772
1773
1774
1775

1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795

1796
1797
1798
1799
1800
1801
1802
1803







-
+



















-
+







	     * Don't bother computing the failure point if we're not going to
	     * return it.
	     */

	    break;
	}
	end = string1 + length1;
	if (TclParseNumber(NULL, objPtr, NULL, NULL, -1,
	if (TclParseNumber(NULL, objPtr, NULL, NULL, TCL_INDEX_NONE,
		(const char **) &stop, TCL_PARSE_INTEGER_ONLY) == TCL_OK) {
	    if (stop == end) {
		/*
		 * Entire string parses as an integer, but rejected by
		 * Tcl_Get(Wide)IntFromObj() so we must have overflowed the
		 * target type, and our convention is to return failure at
		 * index -1 in that situation.
		 */

		failat = -1;
	    } else {
		/*
		 * Some prefix parsed as an integer, but not the whole string,
		 * so return failure index as the point where parsing stopped.
		 * Clear out the internal rep, since keeping it would leave
		 * *objPtr in an inconsistent state.
		 */

		failat = stop - string1;
		TclFreeIntRep(objPtr);
		TclFreeInternalRep(objPtr);
	    }
	} else {
	    /*
	     * No prefix is a valid integer. Fail at beginning.
	     */

	    failat = 0;
1821
1822
1823
1824
1825
1826
1827
1828
1829


1830
1831
1832
1833
1834
1835
1836
1817
1818
1819
1820
1821
1822
1823


1824
1825
1826
1827
1828
1829
1830
1831
1832







-
-
+
+







	    /*
	     * Need to figure out where the list parsing failed, which is
	     * fairly expensive. This is adapted from the core of
	     * SetListFromAny().
	     */

	    const char *elemStart, *nextElem;
	    size_t lenRemain;
	    size_t elemSize;
	    Tcl_Size lenRemain;
	    Tcl_Size elemSize;
	    const char *p;

	    string1 = TclGetStringFromObj(objPtr, &length1);
	    end = string1 + length1;
	    failat = -1;
	    for (p=string1, lenRemain=length1; lenRemain > 0;
		    p=nextElem, lenRemain=end-nextElem) {
1891
1892
1893
1894
1895
1896
1897
1898

1899
1900
1901
1902
1903
1904
1905
1887
1888
1889
1890
1891
1892
1893

1894
1895
1896
1897
1898
1899
1900
1901







-
+







	    }
	    goto str_is_done;
	}
	end = string1 + length1;
	for (; string1 < end; string1 += length2, failat++) {
	    int ucs4;

	    length2 = TclUtfToUCS4(string1, &ucs4);
	    length2 = TclUtfToUniChar(string1, &ucs4);
	    if (!chcomp(ucs4)) {
		result = 0;
		break;
	    }
	}
    }

1949
1950
1951
1952
1953
1954
1955
1956

1957
1958
1959
1960
1961

1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982

1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994



1995
1996
1997
1998
1999
2000
2001
1945
1946
1947
1948
1949
1950
1951

1952
1953
1954
1955
1956

1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977

1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988


1989
1990
1991
1992
1993
1994
1995
1996
1997
1998







-
+




-
+




















-
+










-
-
+
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringMapCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    size_t length1, length2,  mapElemc, index;
    Tcl_Size length1, length2,  mapElemc, index;
    int nocase = 0, mapWithDict = 0, copySource = 0;
    Tcl_Obj **mapElemv, *sourceObj, *resultPtr;
    Tcl_UniChar *ustring1, *ustring2, *p, *end;
    int (*strCmpFn)(const Tcl_UniChar*, const Tcl_UniChar*, size_t);

    if (objc < 3 || objc > 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "?-nocase? charMap string");
	return TCL_ERROR;
    }

    if (objc == 4) {
	const char *string = TclGetStringFromObj(objv[1], &length2);

	if ((length2 > 1) &&
		strncmp(string, "-nocase", length2) == 0) {
	    nocase = 1;
	} else {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad option \"%s\": must be -nocase", string));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option",
		    string, NULL);
		    string, (char *)NULL);
	    return TCL_ERROR;
	}
    }

    /*
     * This test is tricky, but has to be that way or you get other strange
     * inconsistencies (see test string-10.20.1 for illustration why!)
     */

    if (!TclHasStringRep(objv[objc-2])
	    && TclHasIntRep(objv[objc-2], &tclDictType)) {
	int i, done;
	    && TclHasInternalRep(objv[objc-2], &tclDictType)) {
	Tcl_Size i;
	int done;
	Tcl_DictSearch search;

	/*
	 * We know the type exactly, so all dict operations will succeed for
	 * sure. This shortens this code quite a bit.
	 */

2021
2022
2023
2024
2025
2026
2027
2028

2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095

2096
2097
2098
2099
2100
2101
2102
2103
2104

2105
2106
2107
2108
2109
2110
2111
2112

2113
2114
2115
2116
2117
2118
2119

2120
2121
2122
2123
2124
2125

2126
2127
2128
2129

2130
2131
2132
2133
2134
2135
2136

2137
2138
2139
2140
2141

2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158

2159
2160
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
2018
2019
2020
2021
2022
2023
2024

2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045

2046
2047
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
2095
2096
2097
2098
2099
2100

2101
2102
2103
2104
2105
2106
2107
2108

2109
2110
2111
2112
2113
2114
2115

2116
2117
2118
2119
2120
2121

2122
2123
2124
2125

2126
2127
2128
2129
2130
2131
2132

2133
2134
2135
2136
2137

2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154

2155
2156
2157
2158
2159
2160
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







-
+




















-
+















-
+









-
+















-
+



-
+








-
+







-
+






-
+





-
+



-
+






-
+




-
+
















-
+






-
+












-
+


-
+
















-
+







	Tcl_DictObjFirst(interp, objv[objc-2], &search, mapElemv+0,
		mapElemv+1, &done);
	for (index=2 ; index<mapElemc ; index+=2) {
	    Tcl_DictObjNext(&search, mapElemv+index, mapElemv+index+1, &done);
	}
	Tcl_DictObjDone(&search);
    } else {
	int i;
	Tcl_Size i;
	if (TclListObjGetElements(interp, objv[objc-2], &i,
		&mapElemv) != TCL_OK) {
	    return TCL_ERROR;
	}
	mapElemc = i;
	if (mapElemc == 0) {
	    /*
	     * empty charMap, just return whatever string was given.
	     */

	    Tcl_SetObjResult(interp, objv[objc-1]);
	    return TCL_OK;
	} else if (mapElemc & 1) {
	    /*
	     * The charMap must be an even number of key/value items.
	     */

	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("char map list unbalanced", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "MAP",
		    "UNBALANCED", NULL);
		    "UNBALANCED", (char *)NULL);
	    return TCL_ERROR;
	}
    }

    /*
     * Take a copy of the source string object if it is the same as the map
     * string to cut out nasty sharing crashes. [Bug 1018562]
     */

    if (objv[objc-2] == objv[objc-1]) {
	sourceObj = Tcl_DuplicateObj(objv[objc-1]);
	copySource = 1;
    } else {
	sourceObj = objv[objc-1];
    }
    ustring1 = TclGetUnicodeFromObj(sourceObj, &length1);
    ustring1 = Tcl_GetUnicodeFromObj(sourceObj, &length1);
    if (length1 == 0) {
	/*
	 * Empty input string, just stop now.
	 */

	goto done;
    }
    end = ustring1 + length1;

    strCmpFn = (nocase ? TclUniCharNcasecmp : TclUniCharNcmp);
    strCmpFn = nocase ? TclUniCharNcasecmp : TclUniCharNcmp;

    /*
     * Force result to be Unicode
     */

    resultPtr = Tcl_NewUnicodeObj(ustring1, 0);

    if (mapElemc == 2) {
	/*
	 * Special case for one map pair which avoids the extra for loop and
	 * extra calls to get Unicode data. The algorithm is otherwise
	 * identical to the multi-pair case. This will be >30% faster on
	 * larger strings.
	 */

	size_t mapLen;
	Tcl_Size mapLen;
	int u2lc;
	Tcl_UniChar *mapString;

	ustring2 = TclGetUnicodeFromObj(mapElemv[0], &length2);
	ustring2 = Tcl_GetUnicodeFromObj(mapElemv[0], &length2);
	p = ustring1;
	if ((length2 > length1) || (length2 == 0)) {
	    /*
	     * Match string is either longer than input or empty.
	     */

	    ustring1 = end;
	} else {
	    mapString = TclGetUnicodeFromObj(mapElemv[1], &mapLen);
	    mapString = Tcl_GetUnicodeFromObj(mapElemv[1], &mapLen);
	    u2lc = (nocase ? Tcl_UniCharToLower(*ustring2) : 0);
	    for (; ustring1 < end; ustring1++) {
		if (((*ustring1 == *ustring2) ||
			(nocase&&Tcl_UniCharToLower(*ustring1)==u2lc)) &&
			(length2==1 || strCmpFn(ustring1, ustring2,
				length2) == 0)) {
		    if (p != ustring1) {
			TclAppendUnicodeToObj(resultPtr, p, ustring1-p);
			Tcl_AppendUnicodeToObj(resultPtr, p, ustring1-p);
			p = ustring1 + length2;
		    } else {
			p += length2;
		    }
		    ustring1 = p - 1;

		    TclAppendUnicodeToObj(resultPtr, mapString, mapLen);
		    Tcl_AppendUnicodeToObj(resultPtr, mapString, mapLen);
		}
	    }
	}
    } else {
	Tcl_UniChar **mapStrings;
	size_t *mapLens;
	Tcl_Size *mapLens;
	int *u2lc = 0;

	/*
	 * Precompute pointers to the unicode string and length. This saves us
	 * Precompute pointers to the Unicode string and length. This saves us
	 * repeated function calls later, significantly speeding up the
	 * algorithm. We only need the lowercase first char in the nocase
	 * case.
	 */

	mapStrings = (Tcl_UniChar **)TclStackAlloc(interp, mapElemc*sizeof(Tcl_UniChar *)*2);
	mapLens = (size_t *)TclStackAlloc(interp, mapElemc * sizeof(size_t) * 2);
	mapLens = (Tcl_Size *)TclStackAlloc(interp, mapElemc * sizeof(Tcl_Size) * 2);
	if (nocase) {
	    u2lc = (int *)TclStackAlloc(interp, mapElemc * sizeof(int));
	}
	for (index = 0; index < mapElemc; index++) {
	    mapStrings[index] = TclGetUnicodeFromObj(mapElemv[index],
	    mapStrings[index] = Tcl_GetUnicodeFromObj(mapElemv[index],
		    mapLens+index);
	    if (nocase && ((index % 2) == 0)) {
		u2lc[index/2] = Tcl_UniCharToLower(*mapStrings[index]);
	    }
	}
	for (p = ustring1; ustring1 < end; ustring1++) {
	    for (index = 0; index < mapElemc; index += 2) {
		/*
		 * Get the key string to match on.
		 */

		ustring2 = mapStrings[index];
		length2 = mapLens[index];
		if ((length2 > 0) && ((*ustring1 == *ustring2) || (nocase &&
			(Tcl_UniCharToLower(*ustring1) == u2lc[index/2]))) &&
			/* Restrict max compare length. */
			((size_t)(end-ustring1) >= length2) && ((length2 == 1) ||
			((end-ustring1) >= length2) && ((length2 == 1) ||
			!strCmpFn(ustring2, ustring1, length2))) {
		    if (p != ustring1) {
			/*
			 * Put the skipped chars onto the result first.
			 */

			TclAppendUnicodeToObj(resultPtr, p, ustring1-p);
			Tcl_AppendUnicodeToObj(resultPtr, p, ustring1-p);
			p = ustring1 + length2;
		    } else {
			p += length2;
		    }

		    /*
		     * Adjust len to be full length of matched string.
		     */

		    ustring1 = p - 1;

		    /*
		     * Append the map value to the unicode string.
		     * Append the map value to the Unicode string.
		     */

		    TclAppendUnicodeToObj(resultPtr,
		    Tcl_AppendUnicodeToObj(resultPtr,
			    mapStrings[index+1], mapLens[index+1]);
		    break;
		}
	    }
	}
	if (nocase) {
	    TclStackFree(interp, u2lc);
	}
	TclStackFree(interp, mapLens);
	TclStackFree(interp, mapStrings);
    }
    if (p != ustring1) {
	/*
	 * Put the rest of the unmapped chars onto result.
	 */

	TclAppendUnicodeToObj(resultPtr, p, ustring1 - p);
	Tcl_AppendUnicodeToObj(resultPtr, p, ustring1 - p);
    }
    Tcl_SetObjResult(interp, resultPtr);
  done:
    if (mapWithDict) {
	TclStackFree(interp, mapElemv);
    }
    if (copySource) {
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
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







-
+












-
+


-
-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringMatchCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int nocase = 0;

    if (objc < 3 || objc > 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "?-nocase? pattern string");
	return TCL_ERROR;
    }

    if (objc == 4) {
	size_t length;
	Tcl_Size length;
	const char *string = TclGetStringFromObj(objv[1], &length);

	if ((length > 1) &&
	    strncmp(string, "-nocase", length) == 0) {
	if ((length > 1) && strncmp(string, "-nocase", length) == 0) {
	    nocase = TCL_MATCH_NOCASE;
	} else {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad option \"%s\": must be -nocase", string));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option",
		    string, NULL);
		    string, (char *)NULL);
	    return TCL_ERROR;
	}
    }
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
		TclStringMatchObj(objv[objc-1], objv[objc-2], nocase)));
    return TCL_OK;
}
2276
2277
2278
2279
2280
2281
2282
2283

2284
2285
2286
2287
2288

2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310

2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2272
2273
2274
2275
2276
2277
2278

2279
2280
2281
2282
2283

2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302




2303



2304
2305
2306
2307
2308
2309
2310







-
+




-
+


















-
-
-
-
+
-
-
-







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringRangeCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    size_t first, last, end;
    Tcl_Size first, last, end;

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "string first last");
	return TCL_ERROR;
    }

    /*
     * Get the length in actual characters; Then reduce it by one because
     * 'end' refers to the last character, not one past it.
     */

    end = Tcl_GetCharLength(objv[1]) - 1;

    if (TclGetIntForIndexM(interp, objv[2], end, &first) != TCL_OK ||
	    TclGetIntForIndexM(interp, objv[3], end, &last) != TCL_OK) {
	return TCL_ERROR;
    }

    if (first == TCL_INDEX_NONE) {
	first = TCL_INDEX_START;
    }
    if (last + 1 >= end + 1) {
    if (last >= 0) {
	last = end;
    }
    if (last + 1 >= first + 1) {
	Tcl_SetObjResult(interp, Tcl_GetRange(objv[1], first, last));
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
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
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







-
+




-
+







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringReptCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int count;
    Tcl_WideInt count;
    Tcl_Obj *resultPtr;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "string count");
	return TCL_ERROR;
    }

    if (TclGetIntFromObj(interp, objv[2], &count) != TCL_OK) {
    if (TclGetWideIntFromObj(interp, objv[2], &count) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Check for cases that allow us to skip copying stuff.
     */

2388
2389
2390
2391
2392
2393
2394
2395

2396
2397
2398
2399
2400

2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422



2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433

2434
2435
2436

2437
2438
2439
2440
2441
2442
2443



2444
2445
2446
2447
2448
2449
2450
2378
2379
2380
2381
2382
2383
2384

2385
2386
2387
2388
2389

2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409



2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422

2423
2424
2425

2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443







-
+




-
+



















-
-
-
+
+
+










-
+


-
+







+
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringRplcCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
	size_t first, last, end;
    Tcl_Size first, last, end;

    if (objc < 4 || objc > 5) {
	Tcl_WrongNumArgs(interp, 1, objv, "string first last ?string?");
	return TCL_ERROR;
    }

    end = Tcl_GetCharLength(objv[1]) - 1;

    if (TclGetIntForIndexM(interp, objv[2], end, &first) != TCL_OK ||
	    TclGetIntForIndexM(interp, objv[3], end, &last) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * The following test screens out most empty substrings as candidates for
     * replacement. When they are detected, no replacement is done, and the
     * result is the original string.
     */

    if ((last == TCL_INDEX_NONE) ||	/* Range ends before start of string */
	    (first + 1 > end + 1) ||	/* Range begins after end of string */
	    (last + 1 < first + 1)) {	/* Range begins after it starts */
    if ((last < 0) ||	/* Range ends before start of string */
	    (first > end) ||	/* Range begins after end of string */
	    (last < first)) {	/* Range begins after it starts */
	/*
	 * BUT!!! when (end < 0) -- an empty original string -- we can
	 * have (first <= end < 0 <= last) and an empty string is permitted
	 * to be replaced.
	 */

	Tcl_SetObjResult(interp, objv[1]);
    } else {
	Tcl_Obj *resultPtr;

	if (first == TCL_INDEX_NONE) {
	if (first < 0) {
	    first = TCL_INDEX_START;
	}
	if (last + 1 > end + 1) {
	if (last > end) {
	    last = end;
	}

	resultPtr = TclStringReplace(interp, objv[1], first,
		last + 1 - first, (objc == 5) ? objv[4] : NULL,
		TCL_STRING_IN_PLACE);

	if (resultPtr == NULL) {
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, resultPtr);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
2462
2463
2464
2465
2466
2467
2468
2469

2470
2471
2472
2473
2474
2475
2476
2455
2456
2457
2458
2459
2460
2461

2462
2463
2464
2465
2466
2467
2468
2469







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringRevCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "string");
	return TCL_ERROR;
2495
2496
2497
2498
2499
2500
2501
2502

2503
2504
2505
2506
2507
2508
2509


2510
2511
2512
2513
2514
2515
2516
2517

2518
2519

2520
2521
2522
2523
2524


2525
2526
2527
2528


2529
2530

2531
2532
2533

2534
2535
2536
2537
2538
2539

2540
2541

2542

2543
2544
2545
2546
2547
2548
2549
2488
2489
2490
2491
2492
2493
2494

2495
2496
2497
2498
2499
2500


2501
2502
2503
2504
2505
2506
2507
2508
2509

2510


2511
2512
2513



2514
2515
2516
2517


2518
2519
2520

2521
2522
2523

2524
2525
2526
2527
2528
2529

2530
2531
2532
2533

2534
2535
2536
2537
2538
2539
2540
2541







-
+





-
-
+
+







-
+
-
-
+


-
-
-
+
+


-
-
+
+

-
+


-
+





-
+


+
-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringStartCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int ch;
    const char *p, *string;
    size_t numChars, length, cur, index;
    const Tcl_UniChar *p, *string;
    Tcl_Size cur, index, length;
    Tcl_Obj *obj;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "string index");
	return TCL_ERROR;
    }

    string = TclGetStringFromObj(objv[1], &length);
    string = Tcl_GetUnicodeFromObj(objv[1], &length);
    numChars = Tcl_NumUtfChars(string, length) - 1;
    if (TclGetIntForIndexM(interp, objv[2], numChars, &index) != TCL_OK) {
    if (TclGetIntForIndexM(interp, objv[2], length-1, &index) != TCL_OK) {
	return TCL_ERROR;
    }
    string = TclGetString(objv[1]);
    if (index + 1 > numChars + 1) {
	index = numChars;
    if (index >= length) {
	index = length - 1;
    }
    cur = 0;
    if (index + 1 > 1) {
	p = Tcl_UtfAtIndex(string, index);
    if (index > 0) {
	p = &string[index];

	TclUtfToUCS4(p, &ch);
	ch = *p;
	for (cur = index; cur != TCL_INDEX_NONE; cur--) {
	    int delta = 0;
	    const char *next;
	    const Tcl_UniChar *next;

	    if (!Tcl_UniCharIsWordChar(ch)) {
		break;
	    }

	    next = TclUtfPrev(p, string);
	    next = ((p > string) ? (p - 1) : p);
	    do {
		next += delta;
		ch = *next;
		delta = TclUtfToUCS4(next, &ch);
		delta = 1;
	    } while (next + delta < p);
	    p = next;
	}
	if (cur != index) {
	    cur += 1;
	}
    }
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
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







-
+





-
-
+
+







-
+
-
-
+


-
-
-
+
+

-
-
+
+


-
+








-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringEndCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int ch;
    const char *p, *end, *string;
    size_t length, numChars, cur, index;
    const Tcl_UniChar *p, *end, *string;
    Tcl_Size cur, index, length;
    Tcl_Obj *obj;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "string index");
	return TCL_ERROR;
    }

    string = TclGetStringFromObj(objv[1], &length);
    string = Tcl_GetUnicodeFromObj(objv[1], &length);
    numChars = Tcl_NumUtfChars(string, length) - 1;
    if (TclGetIntForIndexM(interp, objv[2], numChars, &index) != TCL_OK) {
    if (TclGetIntForIndexM(interp, objv[2], length-1, &index) != TCL_OK) {
	return TCL_ERROR;
    }
    string = TclGetStringFromObj(objv[1], &length);
    if (index == TCL_INDEX_NONE) {
	index = TCL_INDEX_START;
    if (index < 0) {
	index = 0;
    }
    if (index + 1 <= numChars + 1) {
	p = Tcl_UtfAtIndex(string, index);
    if (index < length) {
	p = &string[index];
	end = string+length;
	for (cur = index; p < end; cur++) {
	    p += TclUtfToUCS4(p, &ch);
	    ch = *p++;
	    if (!Tcl_UniCharIsWordChar(ch)) {
		break;
	    }
	}
	if (cur == index) {
	    cur++;
	}
    } else {
	cur = numChars + 1;
	cur = length;
    }
    TclNewIndexObj(obj, cur);
    Tcl_SetObjResult(interp, obj);
    return TCL_OK;
}

/*
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
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







-
+











-
-
+
+
+


















-
+

+
+
+






-
+










-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringEqualCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    /*
     * Remember to keep code here in some sync with the byte-compiled versions
     * in tclExecute.c (INST_STR_EQ, INST_STR_NEQ and INST_STR_CMP as well as
     * the expr string comparison in INST_EQ/INST_NEQ/INST_LT/...).
     */

    const char *string2;
    int i, match, nocase = 0, reqlength = -1;
    size_t length;
    int i, match, nocase = 0;
    Tcl_Size length;
    Tcl_WideInt reqlength = -1;

    if (objc < 3 || objc > 6) {
    str_cmp_args:
	Tcl_WrongNumArgs(interp, 1, objv,
		"?-nocase? ?-length int? string1 string2");
	return TCL_ERROR;
    }

    for (i = 1; i < objc-2; i++) {
	string2 = TclGetStringFromObj(objv[i], &length);
	if ((length > 1) && !strncmp(string2, "-nocase", length)) {
	    nocase = 1;
	} else if ((length > 1)
		&& !strncmp(string2, "-length", length)) {
	    if (i+1 >= objc-2) {
		goto str_cmp_args;
	    }
	    i++;
	    if (TclGetIntFromObj(interp, objv[i], &reqlength) != TCL_OK) {
	    if (TclGetWideIntFromObj(interp, objv[i], &reqlength) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if ((Tcl_WideUInt)reqlength > TCL_SIZE_MAX) {
		reqlength = -1;
	    }
	} else {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad option \"%s\": must be -nocase or -length",
		    string2));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option",
		    string2, NULL);
		    string2, (char *)NULL);
	    return TCL_ERROR;
	}
    }

    /*
     * From now on, we only access the two objects at the end of the argument
     * array.
     */

    objv += objc-2;
    match = TclStringCmp(objv[0], objv[1], 0, nocase, reqlength);
    match = TclStringCmp(objv[0], objv[1], 1, nocase, reqlength);
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(match ? 0 : 1));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
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
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







-
+










-
+
+

-
+











-
+




-
+


-
+

+

-


















-
+

+
+
+
+
+






-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringCmpCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    /*
     * Remember to keep code here in some sync with the byte-compiled versions
     * in tclExecute.c (INST_STR_EQ, INST_STR_NEQ and INST_STR_CMP as well as
     * the expr string comparison in INST_EQ/INST_NEQ/INST_LT/...).
     */

    int match, nocase, reqlength, status;
    int match, nocase, status;
    Tcl_Size reqlength = -1;

    status = TclStringCmpOpts(interp, objc, objv, &nocase, &reqlength);
    status = StringCmpOpts(interp, objc, objv, &nocase, &reqlength);
    if (status != TCL_OK) {
	return status;
    }

    objv += objc-2;
    match = TclStringCmp(objv[0], objv[1], 0, nocase, reqlength);
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(match));
    return TCL_OK;
}

int
TclStringCmpOpts(
StringCmpOpts(
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[],	/* Argument objects. */
    int *nocase,
    int *reqlength)
    Tcl_Size *reqlength)
{
    int i;
    size_t length;
    Tcl_Size length;
    const char *string;
    Tcl_WideInt wreqlength = -1;

    *reqlength = -1;
    *nocase = 0;
    if (objc < 3 || objc > 6) {
    str_cmp_args:
	Tcl_WrongNumArgs(interp, 1, objv,
		"?-nocase? ?-length int? string1 string2");
	return TCL_ERROR;
    }

    for (i = 1; i < objc-2; i++) {
	string = TclGetStringFromObj(objv[i], &length);
	if ((length > 1) && !strncmp(string, "-nocase", length)) {
	    *nocase = 1;
	} else if ((length > 1)
		&& !strncmp(string, "-length", length)) {
	    if (i+1 >= objc-2) {
		goto str_cmp_args;
	    }
	    i++;
	    if (TclGetIntFromObj(interp, objv[i], reqlength) != TCL_OK) {
	    if (TclGetWideIntFromObj(interp, objv[i], &wreqlength) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if ((Tcl_WideUInt)wreqlength > TCL_SIZE_MAX) {
		*reqlength = -1;
	    } else {
		*reqlength = wreqlength;
	    }
	} else {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad option \"%s\": must be -nocase or -length",
		    string));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option",
		    string, NULL);
		    string, (char *)NULL);
	    return TCL_ERROR;
	}
    }
    return TCL_OK;
}

/*
2796
2797
2798
2799
2800
2801
2802
2803

2804
2805
2806
2807
2808
2809
2810
2796
2797
2798
2799
2800
2801
2802

2803
2804
2805
2806
2807
2808
2809
2810







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringCatCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *objResultPtr;

    if (objc < 2) {
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

















-
+








    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * StringBytesCmd --
 *
 *	This procedure is invoked to process the "string bytelength" Tcl
 *	command. See the user documentation for details on what it does. Note
 *	that this command only functions correctly on properly formed Tcl UTF
 *	strings.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringBytesCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    size_t length;

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

    (void) TclGetStringFromObj(objv[1], &length);
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(length));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * StringLenCmd --
 *
 *	This procedure is invoked to process the "string length" Tcl command.
 *	See the user documentation for details on what it does. Note that this
 *	command only functions correctly on properly formed Tcl UTF strings.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringLenCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "string");
	return TCL_ERROR;
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
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







-
+




-
+

















-
+







-
+









-
+


-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringLowerCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    size_t length1, length2;
    Tcl_Size length1, length2;
    const char *string1;
    char *string2;

    if (objc < 2 || objc > 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "string ?first? ?last?");
	return TCL_ERROR;
    }

    string1 = TclGetStringFromObj(objv[1], &length1);

    if (objc == 2) {
	Tcl_Obj *resultPtr = Tcl_NewStringObj(string1, length1);

	length1 = Tcl_UtfToLower(TclGetString(resultPtr));
	Tcl_SetObjLength(resultPtr, length1);
	Tcl_SetObjResult(interp, resultPtr);
    } else {
	size_t first, last;
	Tcl_Size first, last;
	const char *start, *end;
	Tcl_Obj *resultPtr;

	length1 = Tcl_NumUtfChars(string1, length1) - 1;
	if (TclGetIntForIndexM(interp,objv[2],length1, &first) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (first == TCL_INDEX_NONE) {
	if (first < 0) {
	    first = 0;
	}
	last = first;

	if ((objc == 4) && (TclGetIntForIndexM(interp, objv[3], length1,
		&last) != TCL_OK)) {
	    return TCL_ERROR;
	}

	if (last + 1 >= length1 + 1) {
	if (last >= length1) {
	    last = length1;
	}
	if (last + 1 < first + 1) {
	if (last < first) {
	    Tcl_SetObjResult(interp, objv[1]);
	    return TCL_OK;
	}

	string1 = TclGetStringFromObj(objv[1], &length1);
	start = Tcl_UtfAtIndex(string1, first);
	end = Tcl_UtfAtIndex(start, last - first + 1);
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
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







-
+




-
+

















-
+







-
-
+
+








-
+


-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringUpperCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    size_t length1, length2;
    Tcl_Size length1, length2;
    const char *string1;
    char *string2;

    if (objc < 2 || objc > 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "string ?first? ?last?");
	return TCL_ERROR;
    }

    string1 = TclGetStringFromObj(objv[1], &length1);

    if (objc == 2) {
	Tcl_Obj *resultPtr = Tcl_NewStringObj(string1, length1);

	length1 = Tcl_UtfToUpper(TclGetString(resultPtr));
	Tcl_SetObjLength(resultPtr, length1);
	Tcl_SetObjResult(interp, resultPtr);
    } else {
	size_t first, last;
	Tcl_Size first, last;
	const char *start, *end;
	Tcl_Obj *resultPtr;

	length1 = Tcl_NumUtfChars(string1, length1) - 1;
	if (TclGetIntForIndexM(interp,objv[2],length1, &first) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (first == TCL_INDEX_NONE) {
	    first = TCL_INDEX_START;
	if (first < 0) {
	    first = 0;
	}
	last = first;

	if ((objc == 4) && (TclGetIntForIndexM(interp, objv[3], length1,
		&last) != TCL_OK)) {
	    return TCL_ERROR;
	}

	if (last + 1 >= length1 + 1) {
	if (last >= length1) {
	    last = length1;
	}
	if (last + 1 < first + 1) {
	if (last < first) {
	    Tcl_SetObjResult(interp, objv[1]);
	    return TCL_OK;
	}

	string1 = TclGetStringFromObj(objv[1], &length1);
	start = Tcl_UtfAtIndex(string1, first);
	end = Tcl_UtfAtIndex(start, last - first + 1);
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
3134

3135
3136
3137
3138
3139
3140
3141
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







-
+




-
+

















-
+







-
-
+
+








-
+


-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringTitleCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    size_t length1, length2;
    Tcl_Size length1, length2;
    const char *string1;
    char *string2;

    if (objc < 2 || objc > 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "string ?first? ?last?");
	return TCL_ERROR;
    }

    string1 = TclGetStringFromObj(objv[1], &length1);

    if (objc == 2) {
	Tcl_Obj *resultPtr = Tcl_NewStringObj(string1, length1);

	length1 = Tcl_UtfToTitle(TclGetString(resultPtr));
	Tcl_SetObjLength(resultPtr, length1);
	Tcl_SetObjResult(interp, resultPtr);
    } else {
	size_t first, last;
	Tcl_Size first, last;
	const char *start, *end;
	Tcl_Obj *resultPtr;

	length1 = Tcl_NumUtfChars(string1, length1) - 1;
	if (TclGetIntForIndexM(interp,objv[2],length1, &first) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (first == TCL_INDEX_NONE) {
	    first = TCL_INDEX_START;
	if (first < 0) {
	    first = 0;
	}
	last = first;

	if ((objc == 4) && (TclGetIntForIndexM(interp, objv[3], length1,
		&last) != TCL_OK)) {
	    return TCL_ERROR;
	}

	if (last + 1 >= length1 + 1) {
	if (last >= length1) {
	    last = length1;
	}
	if (last + 1 < first + 1) {
	if (last < first) {
	    Tcl_SetObjResult(interp, objv[1]);
	    return TCL_OK;
	}

	string1 = TclGetStringFromObj(objv[1], &length1);
	start = Tcl_UtfAtIndex(string1, first);
	end = Tcl_UtfAtIndex(start, last - first + 1);
3168
3169
3170
3171
3172
3173
3174
3175

3176
3177
3178
3179
3180
3181

3182
3183
3184
3185
3186
3187
3188
3130
3131
3132
3133
3134
3135
3136

3137
3138
3139
3140
3141
3142

3143
3144
3145
3146
3147
3148
3149
3150







-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringTrimCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *string1, *string2;
    size_t triml, trimr, length1, length2;
    Tcl_Size triml, trimr, length1, length2;

    if (objc == 3) {
	string2 = TclGetStringFromObj(objv[2], &length2);
    } else if (objc == 2) {
	string2 = tclDefaultTrimSet;
	length2 = strlen(tclDefaultTrimSet);
    } else {
3215
3216
3217
3218
3219
3220
3221
3222

3223
3224
3225
3226
3227
3228
3229

3230
3231
3232
3233
3234
3235
3236
3177
3178
3179
3180
3181
3182
3183

3184
3185
3186
3187
3188
3189
3190

3191
3192
3193
3194
3195
3196
3197
3198







-
+






-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringTrimLCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *string1, *string2;
    int trim;
    size_t length1, length2;
    Tcl_Size length1, length2;

    if (objc == 3) {
	string2 = TclGetStringFromObj(objv[2], &length2);
    } else if (objc == 2) {
	string2 = tclDefaultTrimSet;
	length2 = strlen(tclDefaultTrimSet);
    } else {
3262
3263
3264
3265
3266
3267
3268
3269

3270
3271
3272
3273
3274
3275
3276

3277
3278
3279
3280
3281
3282
3283
3224
3225
3226
3227
3228
3229
3230

3231
3232
3233
3234
3235
3236
3237

3238
3239
3240
3241
3242
3243
3244
3245







-
+






-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringTrimRCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *string1, *string2;
    int trim;
    size_t length1, length2;
    Tcl_Size length1, length2;

    if (objc == 3) {
	string2 = TclGetStringFromObj(objv[2], &length2);
    } else if (objc == 2) {
	string2 = tclDefaultTrimSet;
	length2 = strlen(tclDefaultTrimSet);
    } else {
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3278
3279
3280
3281
3282
3283
3284

3285
3286
3287
3288
3289
3290
3291







-







 */

Tcl_Command
TclInitStringCmd(
    Tcl_Interp *interp)		/* Current interpreter. */
{
    static const EnsembleImplMap stringImplMap[] = {
	{"bytelength",	StringBytesCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 0},
	{"cat",		StringCatCmd,	TclCompileStringCatCmd, NULL, NULL, 0},
	{"compare",	StringCmpCmd,	TclCompileStringCmpCmd, NULL, NULL, 0},
	{"equal",	StringEqualCmd,	TclCompileStringEqualCmd, NULL, NULL, 0},
	{"first",	StringFirstCmd,	TclCompileStringFirstCmd, NULL, NULL, 0},
	{"index",	StringIndexCmd,	TclCompileStringIndexCmd, NULL, NULL, 0},
	{"insert",	StringInsertCmd, TclCompileStringInsertCmd, NULL, NULL, 0},
	{"is",		StringIsCmd,	TclCompileStringIsCmd, NULL, NULL, 0},
3367
3368
3369
3370
3371
3372
3373
3374

3375
3376
3377
3378
3379
3380
3381
3328
3329
3330
3331
3332
3333
3334

3335
3336
3337
3338
3339
3340
3341
3342







-
+







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

int
TclSubstOptions(
    Tcl_Interp *interp,
    int numOpts,
    Tcl_Size numOpts,
    Tcl_Obj *const opts[],
    int *flagPtr)
{
    static const char *const substOptions[] = {
	"-nobackslashes", "-nocommands", "-novariables", NULL
    };
    enum {
3406
3407
3408
3409
3410
3411
3412
3413

3414
3415
3416
3417
3418
3419
3420
3421
3422
3423

3424
3425
3426
3427
3428
3429
3430
3367
3368
3369
3370
3371
3372
3373

3374
3375
3376
3377
3378
3379
3380
3381
3382
3383

3384
3385
3386
3387
3388
3389
3390
3391







-
+









-
+







    }
    *flagPtr = flags;
    return TCL_OK;
}

int
Tcl_SubstObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, TclNRSubstObjCmd, clientData, objc, objv);
}

int
TclNRSubstObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int flags;

    if (objc < 2) {
3454
3455
3456
3457
3458
3459
3460
3461

3462
3463
3464
3465
3466
3467
3468
3469
3470

3471
3472
3473
3474
3475

3476
3477

3478
3479
3480
3481
3482
3483
3484
3415
3416
3417
3418
3419
3420
3421

3422
3423
3424
3425
3426
3427
3428
3429
3430

3431
3432
3433
3434
3435

3436
3437

3438
3439
3440
3441
3442
3443
3444
3445







-
+








-
+




-
+

-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_SwitchObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, TclNRSwitchObjCmd, clientData, objc, objv);
}
int
TclNRSwitchObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int i, index, mode, foundmode, splitObjs, numMatchesSaved;
    int i, mode, foundmode, splitObjs, numMatchesSaved;
    int noCase;
    size_t patternLength, j;
    Tcl_Size patternLength, j;
    const char *pattern;
    Tcl_Obj *stringObj, *indexVarObj, *matchVarObj;
    Tcl_Obj *const *savedObjv = objv;
    Tcl_RegExp regExpr = NULL;
    Interp *iPtr = (Interp *) interp;
    int pc = 0;
    int bidx = 0;		/* Index of body argument. */
3494
3495
3496
3497
3498
3499
3500
3501

3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519

3520
3521
3522
3523
3524
3525
3526
3455
3456
3457
3458
3459
3460
3461

3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479

3480
3481
3482
3483
3484
3485
3486
3487







-
+

















-
+







    static const char *const options[] = {
	"-exact", "-glob", "-indexvar", "-matchvar", "-nocase", "-regexp",
	"--", NULL
    };
    enum switchOptionsEnum {
	OPT_EXACT, OPT_GLOB, OPT_INDEXV, OPT_MATCHV, OPT_NOCASE, OPT_REGEXP,
	OPT_LAST
    };
    } index;
    typedef int (*strCmpFn_t)(const char *, const char *);
    strCmpFn_t strCmpFn = TclUtfCmp;

    mode = OPT_EXACT;
    foundmode = 0;
    indexVarObj = NULL;
    matchVarObj = NULL;
    numMatchesSaved = 0;
    noCase = 0;
    for (i = 1; i < objc-2; i++) {
	if (TclGetString(objv[i])[0] != '-') {
	    break;
	}
	if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
		&index) != TCL_OK) {
	    return TCL_ERROR;
	}
	switch ((enum switchOptionsEnum) index) {
	switch (index) {
	    /*
	     * General options.
	     */

	case OPT_LAST:
	    i++;
	    goto finishedOptions;
3539
3540
3541
3542
3543
3544
3545
3546

3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565

3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578

3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597

3598
3599
3600
3601
3602
3603
3604

3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624

3625
3626
3627

3628
3629
3630
3631
3632
3633
3634
3635

3636
3637
3638
3639




3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654

3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672

3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691

3692
3693
3694
3695
3696
3697
3698
3500
3501
3502
3503
3504
3505
3506

3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525

3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538

3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557

3558
3559
3560
3561
3562
3563
3564

3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588

3589
3590
3591
3592
3593
3594
3595
3596

3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619

3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637

3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656

3657
3658
3659
3660
3661
3662
3663
3664







-
+


















-
+












-
+


















-
+






-
+




















+


-
+







-
+




+
+
+
+














-
+

















-
+


















-
+







		 * Mode already set via -exact, -glob, or -regexp.
		 */

		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"bad option \"%s\": %s option already found",
			TclGetString(objv[i]), options[mode]));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH",
			"DOUBLEOPT", NULL);
			"DOUBLEOPT", (char *)NULL);
		return TCL_ERROR;
	    }
	    foundmode = 1;
	    mode = index;
	    break;

	    /*
	     * Check for TIP#75 options specifying the variables to write
	     * regexp information into.
	     */

	case OPT_INDEXV:
	    i++;
	    if (i >= objc-2) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"missing variable name argument to %s option",
			"-indexvar"));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH",
			"NOVAR", NULL);
			"NOVAR", (char *)NULL);
		return TCL_ERROR;
	    }
	    indexVarObj = objv[i];
	    numMatchesSaved = -1;
	    break;
	case OPT_MATCHV:
	    i++;
	    if (i >= objc-2) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"missing variable name argument to %s option",
			"-matchvar"));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH",
			"NOVAR", NULL);
			"NOVAR", (char *)NULL);
		return TCL_ERROR;
	    }
	    matchVarObj = objv[i];
	    numMatchesSaved = -1;
	    break;
	}
    }

  finishedOptions:
    if (objc - i < 2) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"?-option ...? string ?pattern body ...? ?default body?");
	return TCL_ERROR;
    }
    if (indexVarObj != NULL && mode != OPT_REGEXP) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"%s option requires -regexp option", "-indexvar"));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH",
		"MODERESTRICTION", NULL);
		"MODERESTRICTION", (char *)NULL);
	return TCL_ERROR;
    }
    if (matchVarObj != NULL && mode != OPT_REGEXP) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"%s option requires -regexp option", "-matchvar"));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH",
		"MODERESTRICTION", NULL);
		"MODERESTRICTION", (char *)NULL);
	return TCL_ERROR;
    }

    stringObj = objv[i];
    objc -= i + 1;
    objv += i + 1;
    bidx = i + 1;		/* First after the match string. */

    /*
     * If all of the pattern/command pairs are lumped into a single argument,
     * split them out again.
     *
     * TIP #280: Determine the lines the words in the list start at, based on
     * the same data for the list word itself. The cmdFramePtr line
     * information is manipulated directly.
     */

    splitObjs = 0;
    if (objc == 1) {
	Tcl_Obj **listv;
	Tcl_Size listc;

	blist = objv[0];
	if (TclListObjGetElements(interp, objv[0], &objc, &listv) != TCL_OK) {
	if (TclListObjLength(interp, objv[0], &listc) != TCL_OK) {
	    return TCL_ERROR;
	}

	/*
	 * Ensure that the list is non-empty.
	 */

	if (objc < 1) {
	if (listc < 1 || listc > INT_MAX) {
	    Tcl_WrongNumArgs(interp, 1, savedObjv,
		    "?-option ...? string {?pattern body ...? ?default body?}");
	    return TCL_ERROR;
	}
	if (TclListObjGetElements(interp, objv[0], &listc, &listv) != TCL_OK) {
	    return TCL_ERROR;
	}
	objc = listc;
	objv = listv;
	splitObjs = 1;
    }

    /*
     * Complain if there is an odd number of words in the list of patterns and
     * bodies.
     */

    if (objc % 2) {
	Tcl_ResetResult(interp);
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"extra switch pattern with no body", -1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", "BADARM",
		NULL);
		(char *)NULL);

	/*
	 * Check if this can be due to a badly placed comment in the switch
	 * block.
	 *
	 * The following is an heuristic to detect the infamous "comment in
	 * switch" error: just check if a pattern begins with '#'.
	 */

	if (splitObjs) {
	    for (i=0 ; i<objc ; i+=2) {
		if (TclGetString(objv[i])[0] == '#') {
		    Tcl_AppendToObj(Tcl_GetObjResult(interp),
			    ", this may be due to a comment incorrectly"
			    " placed outside of a switch body - see the"
			    " \"switch\" documentation", -1);
		    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH",
			    "BADARM", "COMMENT?", NULL);
			    "BADARM", "COMMENT?", (char *)NULL);
		    break;
		}
	    }
	}

	return TCL_ERROR;
    }

    /*
     * Complain if the last body is a continuation. Note that this check
     * assumes that the list is non-empty!
     */

    if (strcmp(TclGetString(objv[objc-1]), "-") == 0) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"no body specified for pattern \"%s\"",
		TclGetString(objv[objc-2])));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", "BADARM",
		"FALLTHROUGH", NULL);
		"FALLTHROUGH", (char *)NULL);
	return TCL_ERROR;
    }

    for (i = 0; i < objc; i += 2) {
	/*
	 * See if the pattern matches the string.
	 */
3781
3782
3783
3784
3785
3786
3787
3788

3789
3790
3791
3792

3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806

3807
3808





3809
3810
3811
3812
3813
3814
3815
3747
3748
3749
3750
3751
3752
3753

3754
3755
3756
3757

3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773


3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785







-
+



-
+














+
-
-
+
+
+
+
+







	    TclNewObj(indicesObj);
	}

	for (j=0 ; j<=info.nsubs ; j++) {
	    if (indexVarObj != NULL) {
		Tcl_Obj *rangeObjAry[2];

		if (info.matches[j].end + 1 > 1) {
		if (info.matches[j].end > 0) {
		    TclNewIndexObj(rangeObjAry[0], info.matches[j].start);
		    TclNewIndexObj(rangeObjAry[1], info.matches[j].end-1);
		} else {
		    TclNewIndexObj(rangeObjAry[1], TCL_INDEX_NONE);
		    TclNewIntObj(rangeObjAry[1], -1);
		    rangeObjAry[0] = rangeObjAry[1];
		}

		/*
		 * Never fails; the object is always clean at this point.
		 */

		Tcl_ListObjAppendElement(NULL, indicesObj,
			Tcl_NewListObj(2, rangeObjAry));
	    }

	    if (matchVarObj != NULL) {
		Tcl_Obj *substringObj;

		if (info.matches[j].end > 0) {
		substringObj = Tcl_GetRange(stringObj,
			info.matches[j].start, info.matches[j].end-1);
		    substringObj = Tcl_GetRange(stringObj,
			    info.matches[j].start, info.matches[j].end-1);
		} else {
		    TclNewObj(substringObj);
		}

		/*
		 * Never fails; the object is always clean at this point.
		 */

		Tcl_ListObjAppendElement(NULL, matchesObj, substringObj);
	    }
3878
3879
3880
3881
3882
3883
3884
3885

3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899

3900
3901
3902
3903
3904
3905
3906
3907
3908

3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926

3927
3928
3929
3930
3931
3932

3933
3934
3935
3936
3937
3938
3939
3940
3941
3942

3943
3944
3945
3946
3947
3948
3949
3848
3849
3850
3851
3852
3853
3854

3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868

3869
3870
3871
3872
3873
3874
3875
3876
3877

3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895

3896
3897
3898
3899
3900
3901

3902
3903
3904
3905
3906
3907
3908
3909
3910
3911

3912
3913
3914
3915
3916
3917
3918
3919







-
+













-
+








-
+

















-
+





-
+









-
+







	     * own.
	     */
	}

	if (ctxPtr->type == TCL_LOCATION_SOURCE && ctxPtr->line[bidx] >= 0) {
	    int bline = ctxPtr->line[bidx];

	    ctxPtr->line = (int *)Tcl_Alloc(objc * sizeof(int));
	    ctxPtr->line = (Tcl_Size *)Tcl_Alloc(objc * sizeof(Tcl_Size));
	    ctxPtr->nline = objc;
	    TclListLines(blist, bline, objc, ctxPtr->line, objv);
	} else {
	    /*
	     * This is either a dynamic code word, when all elements are
	     * relative to themselves, or something else less expected and
	     * where we have no information. The result is the same in both
	     * cases; tell the code to come that it doesn't know where it is,
	     * which triggers reversion to the old behavior.
	     */

	    int k;

	    ctxPtr->line = (int *)Tcl_Alloc(objc * sizeof(int));
	    ctxPtr->line = (Tcl_Size *)Tcl_Alloc(objc * sizeof(Tcl_Size));
	    ctxPtr->nline = objc;
	    for (k=0; k < objc; k++) {
		ctxPtr->line[k] = -1;
	    }
	}
    }

    for (j = i + 1; ; j += 2) {
	if (j >= (size_t)objc) {
	if (j >= objc) {
	    /*
	     * This shouldn't happen since we've checked that the last body is
	     * not a continuation...
	     */

	    Tcl_Panic("fall-out when searching for body to match pattern");
	}
	if (strcmp(TclGetString(objv[j]), "-") != 0) {
	    break;
	}
    }

    /*
     * TIP #280: Make invoking context available to switch branch.
     */

    Tcl_NRAddCallback(interp, SwitchPostProc, INT2PTR(splitObjs), ctxPtr,
	    INT2PTR(pc), (ClientData) pattern);
	    INT2PTR(pc), (void *)pattern);
    return TclNREvalObjEx(interp, objv[j], 0, ctxPtr, splitObjs ? j : bidx+j);
}

static int
SwitchPostProc(
    ClientData data[],		/* Data passed from Tcl_NRAddCallback above */
    void *data[],		/* Data passed from Tcl_NRAddCallback above */
    Tcl_Interp *interp,		/* Tcl interpreter */
    int result)			/* Result to return*/
{
    /* Unpack the preserved data */

    int splitObjs = PTR2INT(data[0]);
    CmdFrame *ctxPtr = (CmdFrame *)data[1];
    int pc = PTR2INT(data[2]);
    const char *pattern = (const char *)data[3];
    size_t patternLength = strlen(pattern);
    Tcl_Size patternLength = strlen(pattern);

    /*
     * Clean up TIP 280 context information
     */

    if (splitObjs) {
	Tcl_Free(ctxPtr->line);
3957
3958
3959
3960
3961
3962
3963
3964

3965
3966
3967
3968
3969

3970
3971
3972
3973
3974
3975
3976
3927
3928
3929
3930
3931
3932
3933

3934
3935
3936
3937
3938

3939
3940
3941
3942
3943
3944
3945
3946







-
+




-
+







    }

    /*
     * Generate an error message if necessary.
     */

    if (result == TCL_ERROR) {
	unsigned limit = 50;
	int limit = 50;
	int overflow = (patternLength > limit);

	Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
		"\n    (\"%.*s%s\" arm line %d)",
		(overflow ? limit : (unsigned)patternLength), pattern,
		(int) (overflow ? limit : patternLength), pattern,
		(overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
    }
    TclStackFree(interp, ctxPtr);
    return result;
}

/*
3988
3989
3990
3991
3992
3993
3994
3995

3996
3997
3998
3999
4000
4001

4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012

4013
4014
4015
4016
4017
4018

4019
4020
4021
4022
4023
4024
4025
3958
3959
3960
3961
3962
3963
3964

3965
3966
3967
3968
3969
3970

3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981

3982
3983
3984
3985
3986
3987

3988
3989
3990
3991
3992
3993
3994
3995







-
+





-
+










-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ThrowObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *options;
    int len;
    Tcl_Size len;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "type message");
	return TCL_ERROR;
    }

    /*
     * The type must be a list of at least length 1.
     */

    if (Tcl_ListObjLength(interp, objv[1], &len) != TCL_OK) {
    if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
	return TCL_ERROR;
    } else if (len < 1) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"type must be non-empty list", -1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "THROW", "BADEXCEPTION",
		NULL);
		(char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Now prepare the result options dictionary. We use the list API as it is
     * slightly more convenient.
     */
4050
4051
4052
4053
4054
4055
4056
4057

4058
4059
4060
4061
4062
4063
4064
4020
4021
4022
4023
4024
4025
4026

4027
4028
4029
4030
4031
4032
4033
4034







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_TimeObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *objPtr;
    Tcl_Obj *objs[4];
    int i, result;
4105
4106
4107
4108
4109
4110
4111
4112

4113
4114

4115
4116
4117
4118
4119
4120
4121
4075
4076
4077
4078
4079
4080
4081

4082
4083

4084
4085
4086
4087
4088
4089
4090
4091







-
+

-
+







#endif

    if (count <= 1) {
	/*
	 * Use int obj since we know time is not fractional. [Bug 1202178]
	 */

	objs[0] = Tcl_NewWideIntObj((count <= 0) ? 0 : (Tcl_WideInt)totalMicroSec);
	TclNewIntObj(objs[0], (count <= 0) ? 0 : (Tcl_WideInt)totalMicroSec);
    } else {
	objs[0] = Tcl_NewDoubleObj(totalMicroSec/count);
	TclNewDoubleObj(objs[0], totalMicroSec/count);
    }

    /*
     * Construct the result as a list because many programs have always parsed
     * as such (extracting the first element, typically).
     */

4148
4149
4150
4151
4152
4153
4154
4155

4156
4157
4158
4159
4160
4161
4162
4118
4119
4120
4121
4122
4123
4124

4125
4126
4127
4128
4129
4130
4131
4132







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_TimeRateObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static double measureOverhead = 0;
				/* global measure-overhead */
    double overhead = -1;	/* given measure-overhead */
4185
4186
4187
4188
4189
4190
4191
4192

4193
4194
4195
4196
4197
4198
4199
4200
4201
4202

4203
4204
4205
4206
4207
4208
4209
4155
4156
4157
4158
4159
4160
4161

4162
4163
4164
4165
4166
4167
4168
4169
4170
4171

4172
4173
4174
4175
4176
4177
4178
4179







-
+









-
+







    enum timeRateOptionsEnum {
	TMRT_EV_DIRECT,	TMRT_OVERHEAD,	TMRT_CALIBRATE,	TMRT_LAST
    };
    NRE_callback *rootPtr;
    ByteCode *codePtr = NULL;

    for (i = 1; i < objc - 1; i++) {
	int index;
	enum timeRateOptionsEnum index;

	if (Tcl_GetIndexFromObj(NULL, objv[i], options, "option", TCL_EXACT,
		&index) != TCL_OK) {
	    break;
	}
	if (index == TMRT_LAST) {
	    i++;
	    break;
	}
	switch ((enum timeRateOptionsEnum)index) {
	switch (index) {
	case TMRT_EV_DIRECT:
	    direct = objv[i];
	    break;
	case TMRT_OVERHEAD:
	    if (++i >= objc - 1) {
		goto usage;
	    }
4224
4225
4226
4227
4228
4229
4230
4231


4232
4233
4234
4235
4236
4237
4238

4239
4240
4241
4242
4243
4244
4245
4194
4195
4196
4197
4198
4199
4200

4201
4202
4203
4204
4205
4206
4207
4208

4209
4210
4211
4212
4213
4214
4215
4216







-
+
+






-
+







	Tcl_WrongNumArgs(interp, 1, objv,
		"?-direct? ?-calibrate? ?-overhead double? "
		"command ?time ?max-count??");
	return TCL_ERROR;
    }
    objPtr = objv[i++];
    if (i < objc) {	/* max-time */
	result = Tcl_GetWideIntFromObj(interp, objv[i++], &maxms);
	result = TclGetWideIntFromObj(interp, objv[i], &maxms);
	i++; // Keep this separate from TclGetWideIntFromObj macro above!
	if (result != TCL_OK) {
	    return result;
	}
	if (i < objc) {	/* max-count*/
	    Tcl_WideInt v;

	    result = Tcl_GetWideIntFromObj(interp, objv[i], &v);
	    result = TclGetWideIntFromObj(interp, objv[i], &v);
	    if (result != TCL_OK) {
		return result;
	    }
	    maxcnt = (v > 0) ? v : 0;
	}
    }

4592
4593
4594
4595
4596
4597
4598
4599

4600
4601
4602
4603
4604
4605
4606
4563
4564
4565
4566
4567
4568
4569

4570
4571
4572
4573
4574
4575
4576
4577







-
+







	    /*
	     * Calibration: obtaining new measurement overhead.
	     */

	    if (measureOverhead > ((double) usec) / count) {
		measureOverhead = ((double) usec) / count;
	    }
	    objs[0] = Tcl_NewDoubleObj(measureOverhead);
	    TclNewDoubleObj(objs[0], measureOverhead);
	    TclNewLiteralStringObj(objs[1], "\xC2\xB5s/#-overhead"); /* mics */
	    objs += 2;
	}

	val = usec / count;		/* microsecs per iteration */
	if (val >= 1000000) {
	    TclNewIntObj(objs[0], val);
4694
4695
4696
4697
4698
4699
4700
4701

4702
4703
4704
4705
4706
4707
4708
4709
4710
4711

4712
4713
4714
4715
4716
4717


4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737

4738
4739
4740
4741

4742
4743
4744
4745
4746
4747
4748
4749

4750
4751
4752
4753
4754
4755
4756

4757
4758
4759
4760
4761
4762
4763
4764

4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777

4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796

4797
4798
4799
4800

4801
4802
4803
4804
4805
4806

4807
4808
4809
4810
4811
4812

4813
4814
4815
4816
4817
4818
4819
4665
4666
4667
4668
4669
4670
4671

4672
4673
4674
4675
4676
4677
4678
4679
4680
4681

4682
4683
4684
4685
4686
4687

4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708

4709
4710
4711
4712

4713
4714
4715
4716
4717
4718
4719
4720

4721
4722
4723
4724
4725
4726
4727

4728
4729
4730
4731
4732
4733
4734
4735

4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748

4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767

4768
4769
4770
4771

4772
4773
4774
4775
4776
4777

4778
4779
4780
4781
4782
4783

4784
4785
4786
4787
4788
4789
4790
4791







-
+









-
+





-
+
+



















-
+



-
+







-
+






-
+







-
+












-
+


















-
+



-
+





-
+





-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_TryObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, TclNRTryObjCmd, clientData, objc, objv);
}

int
TclNRTryObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *bodyObj, *handlersObj, *finallyObj = NULL;
    int i, bodyShared, haveHandlers, dummy, code;
    int i, bodyShared, haveHandlers, code;
    Tcl_Size dummy;
    static const char *const handlerNames[] = {
	"finally", "on", "trap", NULL
    };
    enum Handlers {
	TryFinally, TryOn, TryTrap
    };

    /*
     * Parse the arguments. The handlers are passed to subsequent callbacks as
     * a Tcl_Obj list of the 5-tuples like (type, returnCode, errorCodePrefix,
     * bindVariables, script), and the finally script is just passed as it is.
     */

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"body ?handler ...? ?finally script?");
	return TCL_ERROR;
    }
    bodyObj = objv[1];
    handlersObj = Tcl_NewObj();
    TclNewObj(handlersObj);
    bodyShared = 0;
    haveHandlers = 0;
    for (i=2 ; i<objc ; i++) {
	int type;
	enum Handlers type;
	Tcl_Obj *info[5];

	if (Tcl_GetIndexFromObj(interp, objv[i], handlerNames, "handler type",
		0, &type) != TCL_OK) {
	    Tcl_DecrRefCount(handlersObj);
	    return TCL_ERROR;
	}
	switch ((enum Handlers) type) {
	switch (type) {
	case TryFinally:	/* finally script */
	    if (i < objc-2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"finally clause must be last", -1));
		Tcl_DecrRefCount(handlersObj);
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRY", "FINALLY",
			"NONTERMINAL", NULL);
			"NONTERMINAL", (char *)NULL);
		return TCL_ERROR;
	    } else if (i == objc-1) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"wrong # args to finally clause: must be"
			" \"... finally script\"", -1));
		Tcl_DecrRefCount(handlersObj);
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRY", "FINALLY",
			"ARGUMENT", NULL);
			"ARGUMENT", (char *)NULL);
		return TCL_ERROR;
	    }
	    finallyObj = objv[++i];
	    break;

	case TryOn:		/* on code variableList script */
	    if (i > objc-4) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"wrong # args to on clause: must be \"... on code"
			" variableList script\"", -1));
		Tcl_DecrRefCount(handlersObj);
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRY", "ON",
			"ARGUMENT", NULL);
			"ARGUMENT", (char *)NULL);
		return TCL_ERROR;
	    }
	    if (TclGetCompletionCodeFromObj(interp, objv[i+1],
		    &code) != TCL_OK) {
		Tcl_DecrRefCount(handlersObj);
		return TCL_ERROR;
	    }
	    info[2] = NULL;
	    goto commonHandler;

	case TryTrap:		/* trap pattern variableList script */
	    if (i > objc-4) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"wrong # args to trap clause: "
			"must be \"... trap pattern variableList script\"",
			-1));
		Tcl_DecrRefCount(handlersObj);
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRY", "TRAP",
			"ARGUMENT", NULL);
			"ARGUMENT", (char *)NULL);
		return TCL_ERROR;
	    }
	    code = 1;
	    if (Tcl_ListObjLength(NULL, objv[i+1], &dummy) != TCL_OK) {
	    if (TclListObjLength(NULL, objv[i+1], &dummy) != TCL_OK) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"bad prefix '%s': must be a list",
			TclGetString(objv[i+1])));
		Tcl_DecrRefCount(handlersObj);
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRY", "TRAP",
			"EXNFORMAT", NULL);
			"EXNFORMAT", (char *)NULL);
		return TCL_ERROR;
	    }
	    info[2] = objv[i+1];

	commonHandler:
	    if (Tcl_ListObjLength(interp, objv[i+2], &dummy) != TCL_OK) {
	    if (TclListObjLength(interp, objv[i+2], &dummy) != TCL_OK) {
		Tcl_DecrRefCount(handlersObj);
		return TCL_ERROR;
	    }

	    info[0] = objv[i];			/* type */
	    TclNewIntObj(info[1], code);	/* returnCode */
	    if (info[2] == NULL) {		/* errorCodePrefix */
4831
4832
4833
4834
4835
4836
4837
4838

4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851

4852
4853
4854
4855
4856
4857
4858
4803
4804
4805
4806
4807
4808
4809

4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822

4823
4824
4825
4826
4827
4828
4829
4830







-
+












-
+







	}
    }
    if (bodyShared) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"last non-finally clause must not have a body of \"-\"", -1));
	Tcl_DecrRefCount(handlersObj);
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRY", "BADFALLTHROUGH",
		NULL);
		(char *)NULL);
	return TCL_ERROR;
    }
    if (!haveHandlers) {
	Tcl_DecrRefCount(handlersObj);
	handlersObj = NULL;
    }

    /*
     * Execute the body.
     */

    Tcl_NRAddCallback(interp, TryPostBody, handlersObj, finallyObj,
	    (ClientData)objv, INT2PTR(objc));
	    (void *)objv, INT2PTR(objc));
    return TclNREvalObjEx(interp, bodyObj, 0,
	    ((Interp *) interp)->cmdFramePtr, 1);
}

/*
 *----------------------------------------------------------------------
 *
4874
4875
4876
4877
4878
4879
4880
4881

4882
4883
4884
4885
4886
4887
4888
4889

4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909

4910
4911
4912
4913
4914
4915


4916
4917
4918
4919
4920
4921
4922
4846
4847
4848
4849
4850
4851
4852

4853
4854
4855
4856
4857
4858



4859

4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877

4878
4879
4880
4881
4882


4883
4884
4885
4886
4887
4888
4889
4890
4891







-
+





-
-
-
+
-


















-
+




-
-
+
+







    int resultCode,		/* The result code from the just-evaluated
				 * script. */
    Tcl_Obj *oldOptions,	/* The old option dictionary. */
    Tcl_Obj *errorInfo)		/* An object to append to the errorinfo and
				 * release, or NULL if nothing is to be added.
				 * Designed to be used with Tcl_ObjPrintf. */
{
    Tcl_Obj *during, *options;
    Tcl_Obj *options;

    if (errorInfo != NULL) {
	Tcl_AppendObjToErrorInfo(interp, errorInfo);
    }
    options = Tcl_GetReturnOptions(interp, resultCode);
    TclNewLiteralStringObj(during, "-during");
    Tcl_IncrRefCount(during);
    Tcl_DictObjPut(interp, options, during, oldOptions);
    TclDictPut(interp, options, "-during", oldOptions);
    Tcl_DecrRefCount(during);
    Tcl_IncrRefCount(options);
    Tcl_DecrRefCount(oldOptions);
    return options;
}

/*
 *----------------------------------------------------------------------
 *
 * TryPostBody --
 *
 *	Callback to handle the outcome of the execution of the body of a 'try'
 *	command.
 *
 *----------------------------------------------------------------------
 */

static int
TryPostBody(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj *resultObj, *options, *handlersObj, *finallyObj, *cmdObj, **objv;
    int i, code, objc;
    int numHandlers = 0;
    int code, objc;
    Tcl_Size i, numHandlers = 0;

    handlersObj = (Tcl_Obj *)data[0];
    finallyObj = (Tcl_Obj *)data[1];
    objv = (Tcl_Obj **)data[2];
    objc = PTR2INT(data[3]);

    cmdObj = objv[0];
4955
4956
4957
4958
4959
4960
4961
4962

4963
4964
4965

4966
4967

4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983


4984
4985
4986

4987
4988
4989


4990
4991
4992
4993
4994
4995
4996
4997
4998


4999
5000
5001
5002
5003
5004
5005
4924
4925
4926
4927
4928
4929
4930

4931
4932
4933

4934
4935

4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950


4951
4952
4953


4954



4955
4956
4957
4958
4959
4960
4961
4962
4963


4964
4965
4966
4967
4968
4969
4970
4971
4972







-
+


-
+

-
+














-
-
+
+

-
-
+
-
-
-
+
+







-
-
+
+







     * Handle the results.
     */

    if (handlersObj != NULL) {
	int found = 0;
	Tcl_Obj **handlers, **info;

	Tcl_ListObjGetElements(NULL, handlersObj, &numHandlers, &handlers);
	TclListObjGetElements(NULL, handlersObj, &numHandlers, &handlers);
	for (i=0 ; i<numHandlers ; i++) {
	    Tcl_Obj *handlerBodyObj;
	    int numElems = 0;
	    Tcl_Size numElems = 0;

	    Tcl_ListObjGetElements(NULL, handlers[i], &numElems, &info);
	    TclListObjGetElements(NULL, handlers[i], &numElems, &info);
	    if (!found) {
		Tcl_GetIntFromObj(NULL, info[1], &code);
		if (code != result) {
		    continue;
		}

		/*
		 * When processing an error, we must also perform list-prefix
		 * matching of the errorcode list. However, if this was an
		 * 'on' handler, the list that we are matching against will be
		 * empty.
		 */

		if (code == TCL_ERROR) {
		    Tcl_Obj *errorCodeName, *errcode, **bits1, **bits2;
		    int len1, len2, j;
		    Tcl_Obj *errcode, **bits1, **bits2;
		    Tcl_Size len1, len2, j;

		    TclNewLiteralStringObj(errorCodeName, "-errorcode");
		    Tcl_DictObjGet(NULL, options, errorCodeName, &errcode);
		    TclDictGet(NULL, options, "-errorcode", &errcode);
		    Tcl_DecrRefCount(errorCodeName);
		    Tcl_ListObjGetElements(NULL, info[2], &len1, &bits1);
		    if (Tcl_ListObjGetElements(NULL, errcode, &len2,
		    TclListObjGetElements(NULL, info[2], &len1, &bits1);
		    if (TclListObjGetElements(NULL, errcode, &len2,
			    &bits2) != TCL_OK) {
			continue;
		    }
		    if (len2 < len1) {
			continue;
		    }
		    for (j=0 ; j<len1 ; j++) {
			if (strcmp(TclGetString(bits1[j]),
				TclGetString(bits2[j])) != 0) {
			if (TclStringCmp(bits1[j], bits2[j], 1, 0,
				TCL_INDEX_NONE) != 0) {
			    /*
			     * Really want 'continue outerloop;', but C does
			     * not give us that.
			     */

			    goto didNotMatch;
			}
5022
5023
5024
5025
5026
5027
5028
5029

5030
5031
5032
5033
5034
5035
5036
4989
4990
4991
4992
4993
4994
4995

4996
4997
4998
4999
5000
5001
5002
5003







-
+







	    /*
	     * Bind the variables. We already know this is a list of variable
	     * names, but it might be empty.
	     */

	    Tcl_ResetResult(interp);
	    result = TCL_ERROR;
	    Tcl_ListObjLength(NULL, info[3], &numElems);
	    TclListObjLength(NULL, info[3], &numElems);
	    if (numElems> 0) {
		Tcl_Obj *varName;

		Tcl_ListObjIndex(NULL, info[3], 0, &varName);
		if (Tcl_ObjSetVar2(interp, varName, NULL, resultObj,
			TCL_LEAVE_ERR_MSG) == NULL) {
		    Tcl_DecrRefCount(resultObj);
5118
5119
5120
5121
5122
5123
5124
5125

5126
5127
5128
5129
5130
5131

5132
5133
5134
5135
5136

5137
5138
5139

5140
5141
5142
5143
5144
5145
5146
5085
5086
5087
5088
5089
5090
5091

5092
5093
5094
5095
5096
5097

5098
5099
5100
5101
5102

5103
5104
5105

5106
5107
5108
5109
5110
5111
5112
5113







-
+





-
+




-
+


-
+







 *	'try' command.
 *
 *----------------------------------------------------------------------
 */

static int
TryPostHandler(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj *resultObj, *cmdObj, *options, *handlerKindObj, **objv;
    Tcl_Obj *finallyObj;
    int finally;
    int finallyIndex;

    objv = (Tcl_Obj **)data[0];
    options = (Tcl_Obj *)data[1];
    handlerKindObj = (Tcl_Obj *)data[2];
    finally = PTR2INT(data[3]);
    finallyIndex = PTR2INT(data[3]);

    cmdObj = objv[0];
    finallyObj = finally ? objv[finally] : 0;
    finallyObj = finallyIndex ? objv[finallyIndex] : 0;

    /*
     * Check for limits/rewinding, which override normal trapping behaviour.
     */

    if (((Interp*) interp)->execEnvPtr->rewind || Tcl_LimitExceeded(interp)) {
	options = During(interp, result, options, Tcl_ObjPrintf(
5176
5177
5178
5179
5180
5181
5182
5183

5184
5185
5186
5187
5188
5189
5190
5143
5144
5145
5146
5147
5148
5149

5150
5151
5152
5153
5154
5155
5156
5157







-
+







	Interp *iPtr = (Interp *) interp;

	Tcl_NRAddCallback(interp, TryPostFinal, resultObj, options, cmdObj,
		NULL);

	/* The 'finally' script is always the last argument word. */
	return TclNREvalObjEx(interp, finallyObj, 0, iPtr->cmdFramePtr,
		finally);
		finallyIndex);
    }

    /*
     * Install the correct result/options into the interpreter and clean up
     * any temporary storage.
     */

5204
5205
5206
5207
5208
5209
5210
5211

5212
5213
5214
5215
5216
5217
5218
5171
5172
5173
5174
5175
5176
5177

5178
5179
5180
5181
5182
5183
5184
5185







-
+







 *	of a 'try' command.
 *
 *----------------------------------------------------------------------
 */

static int
TryPostFinal(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj *resultObj, *options, *cmdObj;

    resultObj = (Tcl_Obj *)data[0];
    options = (Tcl_Obj *)data[1];
5271
5272
5273
5274
5275
5276
5277
5278

5279
5280
5281
5282
5283
5284
5285
5286
5287
5288

5289
5290
5291
5292
5293
5294
5295
5238
5239
5240
5241
5242
5243
5244

5245
5246
5247
5248
5249
5250
5251
5252
5253
5254

5255
5256
5257
5258
5259
5260
5261
5262







-
+









-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_WhileObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, TclNRWhileObjCmd, clientData, objc, objv);
}

int
TclNRWhileObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    ForIterData *iterPtr;

    if (objc != 3) {
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339



5340
5341
5342
5343
5344
5345

5346
5347
5348

5349
5350
5351
5352
5353
5354
5355
5297
5298
5299
5300
5301
5302
5303



5304
5305
5306
5307
5308
5309
5310
5311

5312
5313
5314

5315
5316
5317
5318
5319
5320
5321
5322







-
-
-
+
+
+





-
+


-
+







 */

void
TclListLines(
    Tcl_Obj *listObj,		/* Pointer to obj holding a string with list
				 * structure. Assumed to be valid. Assumed to
				 * contain n elements. */
    int line,			/* Line the list as a whole starts on. */
    int n,			/* #elements in lines */
    int *lines,			/* Array of line numbers, to fill. */
    Tcl_Size line,		/* Line the list as a whole starts on. */
    Tcl_Size n,			/* #elements in lines */
    Tcl_Size *lines,		/* Array of line numbers, to fill. */
    Tcl_Obj *const *elems)      /* The list elems as Tcl_Obj*, in need of
				 * derived continuation data */
{
    const char *listStr = TclGetString(listObj);
    const char *listHead = listStr;
    int i, length = strlen(listStr);
    Tcl_Size i, length = strlen(listStr);
    const char *element = NULL, *next = NULL;
    ContLineLoc *clLocPtr = TclContinuationsGet(listObj);
    int *clNext = (clLocPtr ? &clLocPtr->loc[0] : NULL);
    Tcl_Size *clNext = (clLocPtr ? &clLocPtr->loc[0] : NULL);

    for (i = 0; i < n; i++) {
	TclFindElement(NULL, listStr, length, &element, &next, NULL, NULL);

	TclAdvanceLines(&line, listStr, element);
				/* Leading whitespace */
	TclAdvanceContinuations(&line, &clNext, element - listHead);

Changes to generic/tclCompCmds.c.

1
2
3
4
5
6
7
8
9
10




11
12
13
14
15
16
17
1
2
3
4
5
6




7
8
9
10
11
12
13
14
15
16
17






-
-
-
-
+
+
+
+







/*
 * tclCompCmds.c --
 *
 *	This file contains compilation procedures that compile various Tcl
 *	commands into a sequence of instructions ("bytecodes").
 *
 * Copyright (c) 1997-1998 Sun Microsystems, Inc.
 * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
 * Copyright (c) 2002 ActiveState Corporation.
 * Copyright (c) 2004-2013 by Donal K. Fellows.
 * Copyright © 1997-1998 Sun Microsystems, Inc.
 * Copyright © 2001 Kevin B. Kenny.  All rights reserved.
 * Copyright © 2002 ActiveState Corporation.
 * Copyright © 2004-2013 Donal K. Fellows.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclCompile.h"
118
119
120
121
122
123
124
125

126
127
128
129
130
131
132
118
119
120
121
122
123
124

125
126
127
128
129
130
131
132







-
+







 */

int
TclCompileAppendCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *varTokenPtr, *valueTokenPtr;
    int isScalar, localIndex, numWords, i;

226
227
228
229
230
231
232
233

234
235
236
237
238
239
240
226
227
228
229
230
231
232

233
234
235
236
237
238
239
240







-
+







}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileArray*Cmd --
 *
 *	Functions called to compile "array" sucommands.
 *	Functions called to compile "array" subcommands.
 *
 * Results:
 *	All return TCL_OK for a successful compile, and TCL_ERROR to defer
 *	evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "array" subcommand at
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
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







-
+






-
+
+














-
+







}

int
TclCompileArraySetCmd(
    Tcl_Interp *interp,		/* Used for looking up stuff. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *varTokenPtr, *dataTokenPtr;
    int isScalar, localIndex, code = TCL_OK;
    int isDataLiteral, isDataValid, isDataEven, len;
    int isDataLiteral, isDataValid, isDataEven;
    Tcl_Size len;
    int keyVar, valVar, infoIndex;
    int fwd, offsetBack, offsetFwd;
    Tcl_Obj *literalObj;
    ForeachInfo *infoPtr;

    if (parsePtr->numWords != 3) {
	return TCL_ERROR;
    }

    varTokenPtr = TokenAfter(parsePtr->tokenPtr);
    dataTokenPtr = TokenAfter(varTokenPtr);
    TclNewObj(literalObj);
    isDataLiteral = TclWordKnownAtCompileTime(dataTokenPtr, literalObj);
    isDataValid = (isDataLiteral
	    && Tcl_ListObjLength(NULL, literalObj, &len) == TCL_OK);
	    && TclListObjLength(NULL, literalObj, &len) == TCL_OK);
    isDataEven = (isDataValid && (len & 1) == 0);

    /*
     * Special case: literal odd-length argument is always an error.
     */

    if (isDataValid && !isDataEven) {
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
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







-
-
-
+
+
+











-
+







	 * a non-local variable: upvar from a local one! This consumes the
	 * variable name that was left at stacktop.
	 */

	localIndex = TclFindCompiledLocal(varTokenPtr->start,
		varTokenPtr->size, 1, envPtr);
	PushStringLiteral(envPtr, "0");
	TclEmitInstInt4(INST_REVERSE, 2,        		envPtr);
	TclEmitInstInt4(INST_UPVAR, localIndex, 		envPtr);
	TclEmitOpcode(INST_POP,          			envPtr);
	TclEmitInstInt4(INST_REVERSE, 2,			envPtr);
	TclEmitInstInt4(INST_UPVAR, localIndex,			envPtr);
	TclEmitOpcode(INST_POP,					envPtr);
    }

    /*
     * Prepare for the internal foreach.
     */

    keyVar = AnonymousLocal(envPtr);
    valVar = AnonymousLocal(envPtr);

    infoPtr = (ForeachInfo *)Tcl_Alloc(offsetof(ForeachInfo, varLists) + sizeof(ForeachVarList *));
    infoPtr->numLists = 1;
    infoPtr->varLists[0] = (ForeachVarList *)Tcl_Alloc(offsetof(ForeachVarList, varIndexes) + 2 * sizeof(int));
    infoPtr->varLists[0] = (ForeachVarList *)Tcl_Alloc(offsetof(ForeachVarList, varIndexes) + 2 * sizeof(Tcl_Size));
    infoPtr->varLists[0]->numVars = 2;
    infoPtr->varLists[0]->varIndexes[0] = keyVar;
    infoPtr->varLists[0]->varIndexes[1] = valVar;
    infoIndex = TclCreateAuxData(infoPtr, &newForeachInfoType, envPtr);

    /*
     * Start issuing instructions to write to the array.
448
449
450
451
452
453
454
455

456
457
458
459
460
461
462
449
450
451
452
453
454
455

456
457
458
459
460
461
462
463







-
+







}

int
TclCompileArrayUnsetCmd(
    Tcl_Interp *interp,		/* Used for looking up stuff. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr);
    int isScalar, localIndex;

579
580
581
582
583
584
585
586

587
588
589
590
591
592
593
594
595

596
597
598
599
600
601
602
603
604
605
606

607
608
609
610
611
612
613
580
581
582
583
584
585
586

587
588
589
590
591
592
593
594
595

596
597
598
599
600
601
602
603
604
605
606

607
608
609
610
611
612
613
614







-
+








-
+










-
+







    int depth = TclGetStackDepth(envPtr);

    /*
     * If syntax does not match what we expect for [catch], do not compile.
     * Let runtime checks determine if syntax has changed.
     */

    if ((parsePtr->numWords < 2) || (parsePtr->numWords > 4)) {
    if (((int)parsePtr->numWords < 2) || ((int)parsePtr->numWords > 4)) {
	return TCL_ERROR;
    }

    /*
     * If variables were specified and the catch command is at global level
     * (not in a procedure), don't compile it inline: the payoff is too small.
     */

    if ((parsePtr->numWords >= 3) && !EnvHasLVT(envPtr)) {
    if (((int)parsePtr->numWords >= 3) && !EnvHasLVT(envPtr)) {
	return TCL_ERROR;
    }

    /*
     * Make sure the variable names, if any, have no substitutions and just
     * refer to local scalars.
     */

    resultIndex = optsIndex = -1;
    cmdTokenPtr = TokenAfter(parsePtr->tokenPtr);
    if (parsePtr->numWords >= 3) {
    if ((int)parsePtr->numWords >= 3) {
	resultNameTokenPtr = TokenAfter(cmdTokenPtr);
	/* DGP */
	resultIndex = LocalScalarFromToken(resultNameTokenPtr, envPtr);
	if (resultIndex < 0) {
	    return TCL_ERROR;
	}

630
631
632
633
634
635
636
637

638
639
640
641
642
643
644
631
632
633
634
635
636
637

638
639
640
641
642
643
644
645







-
+







     * Otherwise, compile instructions to substitute the body text before
     * starting the catch, then BEGIN_CATCH, and then EVAL_STK to evaluate the
     * substituted body.
     * Care has to be taken to make sure that substitution happens outside the
     * catch range so that errors in the substitution are not caught.
     * [Bug 219184]
     * The reason for duplicating the script is that EVAL_STK would otherwise
     * begin by undeflowing the stack below the mark set by BEGIN_CATCH4.
     * begin by underflowing the stack below the mark set by BEGIN_CATCH4.
     */

    range = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr);
    if (cmdTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
	TclEmitInstInt4(	INST_BEGIN_CATCH4, range,	envPtr);
	ExceptionRangeStarts(envPtr, range);
	BODY(cmdTokenPtr, 1);
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
653
654
655
656
657
658
659

660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679

680
681
682
683
684
685
686







-




















-







	/* drop the script */
	dropScript = 1;
	TclEmitInstInt4(	INST_REVERSE, 2,		envPtr);
	TclEmitOpcode(		INST_POP,			envPtr);
    }
    ExceptionRangeEnds(envPtr, range);


    /*
     * Emit the "no errors" epilogue: push "0" (TCL_OK) as the catch result,
     * and jump around the "error case" code.
     */

    TclCheckStackDepth(depth+1, envPtr);
    PushStringLiteral(envPtr, "0");
    TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup);

    /*
     * Emit the "error case" epilogue. Push the interpreter result and the
     * return code.
     */

    ExceptionRangeTarget(envPtr, range, catchOffset);
    TclSetStackDepth(depth + dropScript, envPtr);

    if (dropScript) {
	TclEmitOpcode(		INST_POP,			envPtr);
    }


    /* Stack at this point is empty */
    TclEmitOpcode(		INST_PUSH_RESULT,		envPtr);
    TclEmitOpcode(		INST_PUSH_RETURN_CODE,		envPtr);

    /* Stack at this point on both branches: result returnCode */

767
768
769
770
771
772
773
774
775


776
777
778

779
780
781
782

783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
766
767
768
769
770
771
772


773
774
775
776

777
778
779
780

781
782
783
784
785
786
787
788
789
790
791

792
793
794
795
796
797
798







-
-
+
+


-
+



-
+










-







	break;
    case 2:
	/*
	 * -milliseconds or -microseconds
	 */
	tokenPtr = TokenAfter(parsePtr->tokenPtr);
	if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD
	    || tokenPtr[1].size < 4
	    || tokenPtr[1].size > 13) {
		|| tokenPtr[1].size < 4
		|| tokenPtr[1].size > 13) {
	    return TCL_ERROR;
	} else if (!strncmp(tokenPtr[1].start, "-microseconds",
			    tokenPtr[1].size)) {
		tokenPtr[1].size)) {
	    TclEmitInstInt1(INST_CLOCK_READ, 1, envPtr);
	    break;
	} else if (!strncmp(tokenPtr[1].start, "-milliseconds",
			    tokenPtr[1].size)) {
		tokenPtr[1].size)) {
	    TclEmitInstInt1(INST_CLOCK_READ, 2, envPtr);
	    break;
	} else {
	    return TCL_ERROR;
	}
    default:
	return TCL_ERROR;
    }
    return TCL_OK;
}


/*----------------------------------------------------------------------
 *
 * TclCompileClockReadingCmd --
 *
 *	Procedure called to compile the "tcl::clock::microseconds",
 *	"tcl::clock::milliseconds" and "tcl::clock::seconds" commands.
812
813
814
815
816
817
818
819

820
821
822
823
824
825
826
810
811
812
813
814
815
816

817
818
819
820
821
822
823
824







-
+







 */

int
TclCompileClockReadingCmd(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    if (parsePtr->numWords != 1) {
	return TCL_ERROR;
    }

872
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
898
899
900
901
902
903
904
905
906
907
908
909

910
911
912
913
914
915
916
917














































































918
919
920
921
922
923
924
870
871
872
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
898
899
900
901
902
903
904
905

906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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







-
+













-
-
+

-
+












-
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








    /*
     * Test if all arguments are compile-time known. If they are, we can
     * implement with a simple push.
     */

    TclNewObj(listObj);
    for (i = 1, tokenPtr = parsePtr->tokenPtr; i < parsePtr->numWords; i++) {
    for (i = 1, tokenPtr = parsePtr->tokenPtr; i < (int)parsePtr->numWords; i++) {
	tokenPtr = TokenAfter(tokenPtr);
	TclNewObj(objPtr);
	if (!TclWordKnownAtCompileTime(tokenPtr, objPtr)) {
	    Tcl_DecrRefCount(objPtr);
	    Tcl_DecrRefCount(listObj);
	    listObj = NULL;
	    break;
	}
	(void) Tcl_ListObjAppendElement(NULL, listObj, objPtr);
    }
    if (listObj != NULL) {
	Tcl_Obj **objs;
	const char *bytes;
	int len;
	size_t slen;
	Tcl_Size len, slen;

	Tcl_ListObjGetElements(NULL, listObj, &len, &objs);
	TclListObjGetElements(NULL, listObj, &len, &objs);
	objPtr = Tcl_ConcatObj(len, objs);
	Tcl_DecrRefCount(listObj);
	bytes = TclGetStringFromObj(objPtr, &slen);
	PushLiteral(envPtr, bytes, slen);
	Tcl_DecrRefCount(objPtr);
	return TCL_OK;
    }

    /*
     * General case: runtime concat.
     */

    for (i = 1, tokenPtr = parsePtr->tokenPtr; i < parsePtr->numWords; i++) {
    for (i = 1, tokenPtr = parsePtr->tokenPtr; i < (int)parsePtr->numWords; i++) {
	tokenPtr = TokenAfter(tokenPtr);
	CompileWord(envPtr, tokenPtr, interp, i);
    }

    TclEmitInstInt4(	INST_CONCAT_STK, i-1,		envPtr);

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileConstCmd --
 *
 *	Procedure called to compile the "const" command.
 *
 * Results:
 *	Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
 *	evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "const" command at
 *	runtime.
 *
 *----------------------------------------------------------------------
 */

int
TclCompileConstCmd(
    Tcl_Interp *interp,		/* The interpreter. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *varTokenPtr, *valueTokenPtr;
    int isScalar, localIndex;

    /*
     * Need exactly two arguments.
     */
    if (parsePtr->numWords != 3) {
	return TCL_ERROR;
    }

    /*
     * Decide if we can use a frame slot for the var/array name or if we need
     * to emit code to compute and push the name at runtime. We use a frame
     * slot (entry in the array of local vars) if we are compiling a procedure
     * body and if the name is simple text that does not include namespace
     * qualifiers.
     */

    varTokenPtr = TokenAfter(parsePtr->tokenPtr);
    PushVarNameWord(interp, varTokenPtr, envPtr, 0,
	    &localIndex, &isScalar, 1);

    /*
     * If the user specified an array element, we don't bother handling
     * that.
     */
    if (!isScalar) {
	return TCL_ERROR;
    }

    /*
     * We are doing an assignment to set the value of the constant. This will
     * need to be extended to push a value for each argument.
     */

    valueTokenPtr = TokenAfter(varTokenPtr);
    CompileWord(envPtr, valueTokenPtr, interp, 2);

    if (localIndex < 0) {
	TclEmitOpcode(INST_CONST_STK, envPtr);
    } else {
	TclEmitInstInt4(INST_CONST_IMM, localIndex, envPtr);
    }

    /*
     * The const command's result is an empty string.
     */
    PushStringLiteral(envPtr, "");
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileContinueCmd --
 *
 *	Procedure called to compile the "continue" command.
979
980
981
982
983
984
985
986

987
988
989
990
991
992
993
1054
1055
1056
1057
1058
1059
1060

1061
1062
1063
1064
1065
1066
1067
1068







-
+







}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileDict*Cmd --
 *
 *	Functions called to compile "dict" sucommands.
 *	Functions called to compile "dict" subcommands.
 *
 * Results:
 *	All return TCL_OK for a successful compile, and TCL_ERROR to defer
 *	evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "dict" subcommand at
1009
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
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
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131

1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143

1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155

1156
1157
1158
1159
1160
1161
1162
1163







-
+




















-
+








-
+










-
+











-
+











-
+







    int i, dictVarIndex;
    Tcl_Token *varTokenPtr;

    /*
     * There must be at least one argument after the command.
     */

    if (parsePtr->numWords < 4) {
    if ((int)parsePtr->numWords < 4) {
	return TCL_ERROR;
    }

    /*
     * The dictionary variable must be a local scalar that is knowable at
     * compile time; anything else exceeds the complexity of the opcode. So
     * discover what the index is.
     */

    varTokenPtr = TokenAfter(parsePtr->tokenPtr);
    dictVarIndex = LocalScalarFromToken(varTokenPtr, envPtr);
    if (dictVarIndex < 0) {
	return TCL_ERROR;
    }

    /*
     * Remaining words (key path and value to set) can be handled normally.
     */

    tokenPtr = TokenAfter(varTokenPtr);
    for (i=2 ; i< parsePtr->numWords ; i++) {
    for (i=2 ; i< (int)parsePtr->numWords ; i++) {
	CompileWord(envPtr, tokenPtr, interp, i);
	tokenPtr = TokenAfter(tokenPtr);
    }

    /*
     * Now emit the instruction to do the dict manipulation.
     */

    TclEmitInstInt4( INST_DICT_SET, parsePtr->numWords-3,	envPtr);
    TclEmitInstInt4( INST_DICT_SET, (int)parsePtr->numWords-3,	envPtr);
    TclEmitInt4(     dictVarIndex,			envPtr);
    TclAdjustStackDepth(-1, envPtr);
    return TCL_OK;
}

int
TclCompileDictIncrCmd(
    Tcl_Interp *interp,		/* Used for looking up stuff. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *varTokenPtr, *keyTokenPtr;
    int dictVarIndex, incrAmount;

    /*
     * There must be at least two arguments after the command.
     */

    if (parsePtr->numWords < 3 || parsePtr->numWords > 4) {
    if ((int)parsePtr->numWords < 3 || (int)parsePtr->numWords > 4) {
	return TCL_ERROR;
    }
    varTokenPtr = TokenAfter(parsePtr->tokenPtr);
    keyTokenPtr = TokenAfter(varTokenPtr);

    /*
     * Parse the increment amount, if present.
     */

    if (parsePtr->numWords == 4) {
	const char *word;
	size_t numBytes;
	Tcl_Size numBytes;
	int code;
	Tcl_Token *incrTokenPtr;
	Tcl_Obj *intObj;

	incrTokenPtr = TokenAfter(keyTokenPtr);
	if (incrTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	    return TclCompileBasic2Or3ArgCmd(interp, parsePtr,cmdPtr, envPtr);
1136
1137
1138
1139
1140
1141
1142
1143

1144
1145
1146
1147
1148
1149
1150
1151
1152

1153
1154
1155
1156

1157
1158
1159
1160
1161
1162
1163
1211
1212
1213
1214
1215
1216
1217

1218
1219
1220
1221
1222
1223
1224
1225
1226

1227
1228
1229
1230

1231
1232
1233
1234
1235
1236
1237
1238







-
+








-
+



-
+








    /*
     * There must be at least two arguments after the command (the single-arg
     * case is legal, but too special and magic for us to deal with here).
     */

    /* TODO: Consider support for compiling expanded args. */
    if (parsePtr->numWords < 3) {
    if ((int)parsePtr->numWords < 3) {
	return TCL_ERROR;
    }
    tokenPtr = TokenAfter(parsePtr->tokenPtr);

    /*
     * Only compile this because we need INST_DICT_GET anyway.
     */

    for (i=1 ; i<parsePtr->numWords ; i++) {
    for (i=1 ; i<(int)parsePtr->numWords ; i++) {
	CompileWord(envPtr, tokenPtr, interp, i);
	tokenPtr = TokenAfter(tokenPtr);
    }
    TclEmitInstInt4(INST_DICT_GET, parsePtr->numWords-2, envPtr);
    TclEmitInstInt4(INST_DICT_GET, (int)parsePtr->numWords-2, envPtr);
    TclAdjustStackDepth(-1, envPtr);
    return TCL_OK;
}

int
TclCompileDictGetWithDefaultCmd(
    Tcl_Interp *interp,		/* Used for looking up stuff. */
1171
1172
1173
1174
1175
1176
1177
1178

1179
1180
1181
1182
1183

1184
1185
1186
1187

1188
1189
1190
1191
1192
1193
1194
1246
1247
1248
1249
1250
1251
1252

1253
1254
1255
1256
1257

1258
1259
1260
1261

1262
1263
1264
1265
1266
1267
1268
1269







-
+




-
+



-
+







    int i;

    /*
     * There must be at least three arguments after the command.
     */

    /* TODO: Consider support for compiling expanded args. */
    if (parsePtr->numWords < 4) {
    if ((int)parsePtr->numWords < 4) {
	return TCL_ERROR;
    }
    tokenPtr = TokenAfter(parsePtr->tokenPtr);

    for (i=1 ; i<parsePtr->numWords ; i++) {
    for (i=1 ; i<(int)parsePtr->numWords ; i++) {
	CompileWord(envPtr, tokenPtr, interp, i);
	tokenPtr = TokenAfter(tokenPtr);
    }
    TclEmitInstInt4(INST_DICT_GET_DEF, parsePtr->numWords-3, envPtr);
    TclEmitInstInt4(INST_DICT_GET_DEF, (int)parsePtr->numWords-3, envPtr);
    TclAdjustStackDepth(-2, envPtr);
    return TCL_OK;
}

int
TclCompileDictExistsCmd(
    Tcl_Interp *interp,		/* Used for looking up stuff. */
1203
1204
1205
1206
1207
1208
1209
1210

1211
1212
1213
1214
1215
1216
1217
1218
1219

1220
1221
1222
1223

1224
1225
1226
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
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
1354
1355
1356
1357
1358
1359
1360

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
1387
1388
1389
1390
1391







-
+








-
+



-
+









-
+













-
+



















-
+








-
+









-
+









-
+












-
+








    /*
     * There must be at least two arguments after the command (the single-arg
     * case is legal, but too special and magic for us to deal with here).
     */

    /* TODO: Consider support for compiling expanded args. */
    if (parsePtr->numWords < 3) {
    if ((int)parsePtr->numWords < 3) {
	return TCL_ERROR;
    }
    tokenPtr = TokenAfter(parsePtr->tokenPtr);

    /*
     * Now we do the code generation.
     */

    for (i=1 ; i<parsePtr->numWords ; i++) {
    for (i=1 ; i<(int)parsePtr->numWords ; i++) {
	CompileWord(envPtr, tokenPtr, interp, i);
	tokenPtr = TokenAfter(tokenPtr);
    }
    TclEmitInstInt4(INST_DICT_EXISTS, parsePtr->numWords-2, envPtr);
    TclEmitInstInt4(INST_DICT_EXISTS, (int)parsePtr->numWords-2, envPtr);
    TclAdjustStackDepth(-1, envPtr);
    return TCL_OK;
}

int
TclCompileDictUnsetCmd(
    Tcl_Interp *interp,		/* Used for looking up stuff. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr;
    int i, dictVarIndex;

    /*
     * There must be at least one argument after the variable name for us to
     * compile to bytecode.
     */

    /* TODO: Consider support for compiling expanded args. */
    if (parsePtr->numWords < 3) {
    if ((int)parsePtr->numWords < 3) {
	return TCL_ERROR;
    }

    /*
     * The dictionary variable must be a local scalar that is knowable at
     * compile time; anything else exceeds the complexity of the opcode. So
     * discover what the index is.
     */

    tokenPtr = TokenAfter(parsePtr->tokenPtr);
    dictVarIndex = LocalScalarFromToken(tokenPtr, envPtr);
    if (dictVarIndex < 0) {
	return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
    }

    /*
     * Remaining words (the key path) can be handled normally.
     */

    for (i=2 ; i<parsePtr->numWords ; i++) {
    for (i=2 ; i<(int)parsePtr->numWords ; i++) {
	tokenPtr = TokenAfter(tokenPtr);
	CompileWord(envPtr, tokenPtr, interp, i);
    }

    /*
     * Now emit the instruction to do the dict manipulation.
     */

    TclEmitInstInt4( INST_DICT_UNSET, parsePtr->numWords-2,	envPtr);
    TclEmitInstInt4( INST_DICT_UNSET, (int)parsePtr->numWords-2,	envPtr);
    TclEmitInt4(	dictVarIndex,				envPtr);
    return TCL_OK;
}

int
TclCompileDictCreateCmd(
    Tcl_Interp *interp,		/* Used for looking up stuff. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    int worker;			/* Temp var for building the value in. */
    Tcl_Token *tokenPtr;
    Tcl_Obj *keyObj, *valueObj, *dictObj;
    const char *bytes;
    int i;
    size_t len;
    Tcl_Size len;

    if ((parsePtr->numWords & 1) == 0) {
	return TCL_ERROR;
    }

    /*
     * See if we can build the value at compile time...
     */

    tokenPtr = TokenAfter(parsePtr->tokenPtr);
    TclNewObj(dictObj);
    Tcl_IncrRefCount(dictObj);
    for (i=1 ; i<parsePtr->numWords ; i+=2) {
    for (i=1 ; i<(int)parsePtr->numWords ; i+=2) {
	TclNewObj(keyObj);
	Tcl_IncrRefCount(keyObj);
	if (!TclWordKnownAtCompileTime(tokenPtr, keyObj)) {
	    Tcl_DecrRefCount(keyObj);
	    Tcl_DecrRefCount(dictObj);
	    goto nonConstant;
	}
1352
1353
1354
1355
1356
1357
1358
1359

1360
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
1387
1388
1389
1390
1391
1392
1393
1394

1395
1396
1397
1398
1399
1400
1401
1427
1428
1429
1430
1431
1432
1433

1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
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
1474
1475
1476







-
+




















-
+













-
+







	return TclCompileBasicMin0ArgCmd(interp, parsePtr, cmdPtr, envPtr);
    }

    PushStringLiteral(envPtr,		"");
    Emit14Inst(			INST_STORE_SCALAR, worker,	envPtr);
    TclEmitOpcode(		INST_POP,			envPtr);
    tokenPtr = TokenAfter(parsePtr->tokenPtr);
    for (i=1 ; i<parsePtr->numWords ; i+=2) {
    for (i=1 ; i<(int)parsePtr->numWords ; i+=2) {
	CompileWord(envPtr, tokenPtr, interp, i);
	tokenPtr = TokenAfter(tokenPtr);
	CompileWord(envPtr, tokenPtr, interp, i+1);
	tokenPtr = TokenAfter(tokenPtr);
	TclEmitInstInt4(	INST_DICT_SET, 1,		envPtr);
	TclEmitInt4(			worker,			envPtr);
	TclAdjustStackDepth(-1, envPtr);
	TclEmitOpcode(		INST_POP,			envPtr);
    }
    Emit14Inst(			INST_LOAD_SCALAR, worker,	envPtr);
    TclEmitInstInt1(		INST_UNSET_SCALAR, 0,		envPtr);
    TclEmitInt4(			worker,			envPtr);
    return TCL_OK;
}

int
TclCompileDictMergeCmd(
    Tcl_Interp *interp,		/* Used for looking up stuff. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr;
    int i, workerIndex, infoIndex, outLoop;

    /*
     * Deal with some special edge cases. Note that in the case with one
     * argument, the only thing to do is to verify the dict-ness.
     */

    /* TODO: Consider support for compiling expanded args. (less likely) */
    if (parsePtr->numWords < 2) {
    if ((int)parsePtr->numWords < 2) {
	PushStringLiteral(envPtr, "");
	return TCL_OK;
    } else if (parsePtr->numWords == 2) {
	tokenPtr = TokenAfter(parsePtr->tokenPtr);
	CompileWord(envPtr, tokenPtr, interp, 1);
	TclEmitOpcode(		INST_DUP,			envPtr);
	TclEmitOpcode(		INST_DICT_VERIFY,		envPtr);
1429
1430
1431
1432
1433
1434
1435
1436

1437
1438
1439
1440
1441
1442
1443
1504
1505
1506
1507
1508
1509
1510

1511
1512
1513
1514
1515
1516
1517
1518







-
+







    /*
     * For each of the remaining dictionaries...
     */

    outLoop = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr);
    TclEmitInstInt4(		INST_BEGIN_CATCH4, outLoop,	envPtr);
    ExceptionRangeStarts(envPtr, outLoop);
    for (i=2 ; i<parsePtr->numWords ; i++) {
    for (i=2 ; i<(int)parsePtr->numWords ; i++) {
	/*
	 * Get the dictionary, and merge its pairs into the first dict (using
	 * a small loop).
	 */

	tokenPtr = TokenAfter(tokenPtr);
	CompileWord(envPtr, tokenPtr, interp, i);
1487
1488
1489
1490
1491
1492
1493
1494

1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507

1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520

1521
1522
1523
1524
1525
1526
1527
1528
1529
1530

1531

1532
1533
1534
1535
1536
1537
1538
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







-
+












-
+












-
+










+
-
+







}

int
TclCompileDictForCmd(
    Tcl_Interp *interp,		/* Used for looking up stuff. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    return CompileDictEachCmd(interp, parsePtr, cmdPtr, envPtr,
	    TCL_EACH_KEEP_NONE);
}

int
TclCompileDictMapCmd(
    Tcl_Interp *interp,		/* Used for looking up stuff. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    return CompileDictEachCmd(interp, parsePtr, cmdPtr, envPtr,
	    TCL_EACH_COLLECT);
}

int
CompileDictEachCmd(
    Tcl_Interp *interp,		/* Used for looking up stuff. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr,		/* Holds resulting instructions. */
    int collect)		/* Flag == TCL_EACH_COLLECT to collect and
				 * construct a new dictionary with the loop
				 * body result. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *varsTokenPtr, *dictTokenPtr, *bodyTokenPtr;
    int keyVarIndex, valueVarIndex, nameChars, loopRange, catchRange;
    int infoIndex, jumpDisplacement, bodyTargetOffset, emptyTargetOffset;
    Tcl_Size numVars;
    int numVars, endTargetOffset;
    int endTargetOffset;
    int collectVar = -1;	/* Index of temp var holding the result
				 * dict. */
    const char **argv;
    Tcl_DString buffer;

    /*
     * There must be three arguments after the command.
1685
1686
1687
1688
1689
1690
1691
1692

1693
1694
1695
1696
1697
1698
1699
1761
1762
1763
1764
1765
1766
1767

1768
1769
1770
1771
1772
1773
1774
1775







-
+







    jumpDisplacement = bodyTargetOffset - CurrentOffset(envPtr);
    TclEmitInstInt4(	INST_JUMP_FALSE4, jumpDisplacement,	envPtr);
    endTargetOffset = CurrentOffset(envPtr);
    TclEmitInstInt1(	INST_JUMP1, 0,				envPtr);

    /*
     * Error handler "finally" clause, which force-terminates the iteration
     * and rethrows the error.
     * and re-throws the error.
     */

    TclAdjustStackDepth(-1, envPtr);
    ExceptionRangeTarget(envPtr, catchRange, catchOffset);
    TclEmitOpcode(	INST_PUSH_RETURN_OPTIONS,		envPtr);
    TclEmitOpcode(	INST_PUSH_RESULT,			envPtr);
    TclEmitOpcode(	INST_END_CATCH,				envPtr);
1742
1743
1744
1745
1746
1747
1748
1749

1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763

1764
1765
1766
1767
1768
1769
1770
1771
1772

1773
1774
1775
1776
1777
1778
1779
1818
1819
1820
1821
1822
1823
1824

1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838

1839
1840
1841
1842
1843
1844
1845
1846
1847

1848
1849
1850
1851
1852
1853
1854
1855







-
+













-
+








-
+







}

int
TclCompileDictUpdateCmd(
    Tcl_Interp *interp,		/* Used for looking up stuff. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    int i, dictIndex, numVars, range, infoIndex;
    Tcl_Token **keyTokenPtrs, *dictVarTokenPtr, *bodyTokenPtr, *tokenPtr;
    DictUpdateInfo *duiPtr;
    JumpFixup jumpFixup;

    /*
     * There must be at least one argument after the command.
     */

    if (parsePtr->numWords < 5) {
    if ((int)parsePtr->numWords < 5) {
	return TCL_ERROR;
    }

    /*
     * Parse the command. Expect the following:
     *   dict update <lit(eral)> <any> <lit> ?<any> <lit> ...? <lit>
     */

    if ((parsePtr->numWords - 1) & 1) {
    if (((int)parsePtr->numWords - 1) & 1) {
	return TCL_ERROR;
    }
    numVars = (parsePtr->numWords - 3) / 2;

    /*
     * The dictionary variable must be a local scalar that is knowable at
     * compile time; anything else exceeds the complexity of the opcode. So
1788
1789
1790
1791
1792
1793
1794
1795

1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814

1815
1816
1817
1818
1819
1820
1821
1864
1865
1866
1867
1868
1869
1870

1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889

1890
1891
1892
1893
1894
1895
1896
1897







-
+


















-
+








    /*
     * Assemble the instruction metadata. This is complex enough that it is
     * represented as auxData; it holds an ordered list of variable indices
     * that are to be used.
     */

    duiPtr = (DictUpdateInfo *)Tcl_Alloc(offsetof(DictUpdateInfo, varIndices) + sizeof(int) * numVars);
    duiPtr = (DictUpdateInfo *)Tcl_Alloc(offsetof(DictUpdateInfo, varIndices) + sizeof(size_t) * numVars);
    duiPtr->length = numVars;
    keyTokenPtrs = (Tcl_Token **)TclStackAlloc(interp, sizeof(Tcl_Token *) * numVars);
    tokenPtr = TokenAfter(dictVarTokenPtr);

    for (i=0 ; i<numVars ; i++) {
	/*
	 * Put keys to one side for later compilation to bytecode.
	 */

	keyTokenPtrs[i] = tokenPtr;
	tokenPtr = TokenAfter(tokenPtr);

	/*
	 * Stash the index in the auxiliary data (if it is indeed a local
	 * scalar that is resolvable at compile-time).
	 */

	duiPtr->varIndices[i] = LocalScalarFromToken(tokenPtr, envPtr);
	if (duiPtr->varIndices[i] < 0) {
	if (duiPtr->varIndices[i] == TCL_INDEX_NONE) {
	    goto failedUpdateInfoAssembly;
	}
	tokenPtr = TokenAfter(tokenPtr);
    }
    if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	goto failedUpdateInfoAssembly;
    }
1857
1858
1859
1860
1861
1862
1863
1864

1865
1866
1867
1868
1869
1870
1871
1933
1934
1935
1936
1937
1938
1939

1940
1941
1942
1943
1944
1945
1946
1947







-
+







     */

    TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup);

    /*
     * Termination code for non-ok returns: stash the result and return
     * options in the stack, bring up the key list, finish the update code,
     * and finally return with the catched return data
     * and finally return with the caught return data
     */

    ExceptionRangeTarget(envPtr, range, catchOffset);
    TclEmitOpcode(	INST_PUSH_RESULT,			envPtr);
    TclEmitOpcode(	INST_PUSH_RETURN_OPTIONS,		envPtr);
    TclEmitOpcode(	INST_END_CATCH,				envPtr);
    TclEmitInstInt4(	INST_REVERSE, 3,			envPtr);
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
1958
1959
1960
1961
1962
1969
1970
1971
1972
1973
1974
1975

1976
1977
1978
1979
1980
1981
1982
1983
1984
1985

1986
1987
1988
1989
1990

1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009

2010
2011
2012
2013


2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030

2031
2032
2033
2034
2035
2036
2037
2038







-
+









-
+




-
+


















-
+



-
-
+
+















-
+







}

int
TclCompileDictAppendCmd(
    Tcl_Interp *interp,		/* Used for looking up stuff. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr;
    int i, dictVarIndex;

    /*
     * There must be at least two argument after the command. And we impose an
     * (arbirary) safe limit; anyone exceeding it should stop worrying about
     * (arbitrary) safe limit; anyone exceeding it should stop worrying about
     * speed quite so much. ;-)
     */

    /* TODO: Consider support for compiling expanded args. */
    if (parsePtr->numWords<4 || parsePtr->numWords>100) {
    if ((int)parsePtr->numWords<4 || (int)parsePtr->numWords>100) {
	return TCL_ERROR;
    }

    /*
     * Get the index of the local variable that we will be working with.
     */

    tokenPtr = TokenAfter(parsePtr->tokenPtr);
    dictVarIndex = LocalScalarFromToken(tokenPtr, envPtr);
    if (dictVarIndex < 0) {
	return TclCompileBasicMin2ArgCmd(interp, parsePtr,cmdPtr, envPtr);
    }

    /*
     * Produce the string to concatenate onto the dictionary entry.
     */

    tokenPtr = TokenAfter(tokenPtr);
    for (i=2 ; i<parsePtr->numWords ; i++) {
    for (i=2 ; i<(int)parsePtr->numWords ; i++) {
	CompileWord(envPtr, tokenPtr, interp, i);
	tokenPtr = TokenAfter(tokenPtr);
    }
    if (parsePtr->numWords > 4) {
	TclEmitInstInt1(INST_STR_CONCAT1, parsePtr->numWords-3, envPtr);
    if ((int)parsePtr->numWords > 4) {
	TclEmitInstInt1(INST_STR_CONCAT1, (int)parsePtr->numWords-3, envPtr);
    }

    /*
     * Do the concatenation.
     */

    TclEmitInstInt4(INST_DICT_APPEND, dictVarIndex, envPtr);
    return TCL_OK;
}

int
TclCompileDictLappendCmd(
    Tcl_Interp *interp,		/* Used for looking up stuff. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *varTokenPtr, *keyTokenPtr, *valueTokenPtr;
    int dictVarIndex;

1993
1994
1995
1996
1997
1998
1999
2000

2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016

2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027

2028
2029
2030
2031
2032
2033
2034
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
2095
2096
2097
2098
2099
2100
2101
2102

2103
2104
2105
2106
2107
2108
2109
2110







-
+















-
+










-
+







}

int
TclCompileDictWithCmd(
    Tcl_Interp *interp,		/* Used for looking up stuff. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    int i, range, varNameTmp = -1, pathTmp = -1, keysTmp, gotPath;
    int dictVar, bodyIsEmpty = 1;
    Tcl_Token *varTokenPtr, *tokenPtr;
    JumpFixup jumpFixup;
    const char *ptr, *end;

    /*
     * There must be at least one argument after the command.
     */

    /* TODO: Consider support for compiling expanded args. */
    if (parsePtr->numWords < 3) {
    if ((int)parsePtr->numWords < 3) {
	return TCL_ERROR;
    }

    /*
     * Parse the command (trivially). Expect the following:
     *   dict with <any (varName)> ?<any> ...? <literal>
     */

    varTokenPtr = TokenAfter(parsePtr->tokenPtr);
    tokenPtr = TokenAfter(varTokenPtr);
    for (i=3 ; i<parsePtr->numWords ; i++) {
    for (i=3 ; i<(int)parsePtr->numWords ; i++) {
	tokenPtr = TokenAfter(tokenPtr);
    }
    if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
    }

    /*
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
2124
2125
2126
2127
2128
2129
2130

2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149

2150
2151
2152
2153

2154
2155
2156
2157
2158
2159
2160
2161







-
+


















-
+



-
+







	}
    }

    /*
     * Determine if we're manipulating a dict in a simple local variable.
     */

    gotPath = (parsePtr->numWords > 3);
    gotPath = ((int)parsePtr->numWords > 3);
    dictVar = LocalScalarFromToken(varTokenPtr, envPtr);

    /*
     * Special case: an empty body means we definitely have no need to issue
     * try-finally style code or to allocate local variable table entries for
     * storing temporaries. Still need to do both INST_DICT_EXPAND and
     * INST_DICT_RECOMBINE_* though, because we can't determine if we're free
     * of traces.
     */

    if (bodyIsEmpty) {
	if (dictVar >= 0) {
	    if (gotPath) {
		/*
		 * Case: Path into dict in LVT with empty body.
		 */

		tokenPtr = TokenAfter(varTokenPtr);
		for (i=2 ; i<parsePtr->numWords-1 ; i++) {
		for (i=2 ; i<(int)parsePtr->numWords-1 ; i++) {
		    CompileWord(envPtr, tokenPtr, interp, i);
		    tokenPtr = TokenAfter(tokenPtr);
		}
		TclEmitInstInt4(INST_LIST, parsePtr->numWords-3,envPtr);
		TclEmitInstInt4(INST_LIST, (int)parsePtr->numWords-3,envPtr);
		Emit14Inst(	INST_LOAD_SCALAR, dictVar,	envPtr);
		TclEmitInstInt4(INST_OVER, 1,			envPtr);
		TclEmitOpcode(	INST_DICT_EXPAND,		envPtr);
		TclEmitInstInt4(INST_DICT_RECOMBINE_IMM, dictVar, envPtr);
	    } else {
		/*
		 * Case: Direct dict in LVT with empty body.
2094
2095
2096
2097
2098
2099
2100
2101

2102
2103
2104
2105

2106
2107
2108
2109
2110
2111
2112
2170
2171
2172
2173
2174
2175
2176

2177
2178
2179
2180

2181
2182
2183
2184
2185
2186
2187
2188







-
+



-
+







	} else {
	    if (gotPath) {
		/*
		 * Case: Path into dict in non-simple var with empty body.
		 */

		tokenPtr = varTokenPtr;
		for (i=1 ; i<parsePtr->numWords-1 ; i++) {
		for (i=1 ; i<(int)parsePtr->numWords-1 ; i++) {
		    CompileWord(envPtr, tokenPtr, interp, i);
		    tokenPtr = TokenAfter(tokenPtr);
		}
		TclEmitInstInt4(INST_LIST, parsePtr->numWords-3,envPtr);
		TclEmitInstInt4(INST_LIST, (int)parsePtr->numWords-3,envPtr);
		TclEmitInstInt4(INST_OVER, 1,			envPtr);
		TclEmitOpcode(	INST_LOAD_STK,			envPtr);
		TclEmitInstInt4(INST_OVER, 1,			envPtr);
		TclEmitOpcode(	INST_DICT_EXPAND,		envPtr);
		TclEmitOpcode(	INST_DICT_RECOMBINE_STK,	envPtr);
	    } else {
		/*
2149
2150
2151
2152
2153
2154
2155
2156

2157
2158
2159
2160

2161
2162
2163
2164
2165
2166
2167
2225
2226
2227
2228
2229
2230
2231

2232
2233
2234
2235

2236
2237
2238
2239
2240
2241
2242
2243







-
+



-
+








    if (dictVar == -1) {
	CompileWord(envPtr, varTokenPtr, interp, 1);
	Emit14Inst(		INST_STORE_SCALAR, varNameTmp,	envPtr);
    }
    tokenPtr = TokenAfter(varTokenPtr);
    if (gotPath) {
	for (i=2 ; i<parsePtr->numWords-1 ; i++) {
	for (i=2 ; i<(int)parsePtr->numWords-1 ; i++) {
	    CompileWord(envPtr, tokenPtr, interp, i);
	    tokenPtr = TokenAfter(tokenPtr);
	}
	TclEmitInstInt4(	INST_LIST, parsePtr->numWords-3,envPtr);
	TclEmitInstInt4(	INST_LIST, (int)parsePtr->numWords-3,envPtr);
	Emit14Inst(		INST_STORE_SCALAR, pathTmp,	envPtr);
	TclEmitOpcode(		INST_POP,			envPtr);
    }
    if (dictVar == -1) {
	TclEmitOpcode(		INST_LOAD_STK,			envPtr);
    } else {
	Emit14Inst(		INST_LOAD_SCALAR, dictVar,	envPtr);
2215
2216
2217
2218
2219
2220
2221
2222

2223
2224
2225
2226
2227
2228
2229
2291
2292
2293
2294
2295
2296
2297

2298
2299
2300
2301
2302
2303
2304
2305







-
+







    ExceptionRangeTarget(envPtr, range, catchOffset);
    TclEmitOpcode(		INST_PUSH_RETURN_OPTIONS,	envPtr);
    TclEmitOpcode(		INST_PUSH_RESULT,		envPtr);
    TclEmitOpcode(		INST_END_CATCH,			envPtr);
    if (dictVar == -1) {
	Emit14Inst(		INST_LOAD_SCALAR, varNameTmp,	envPtr);
    }
    if (parsePtr->numWords > 3) {
    if ((int)parsePtr->numWords > 3) {
	Emit14Inst(		INST_LOAD_SCALAR, pathTmp,	envPtr);
    } else {
	PushStringLiteral(envPtr, "");
    }
    Emit14Inst(			INST_LOAD_SCALAR, keysTmp,	envPtr);
    if (dictVar == -1) {
	TclEmitOpcode(		INST_DICT_RECOMBINE_STK,	envPtr);
2262
2263
2264
2265
2266
2267
2268
2269

2270
2271

2272
2273
2274
2275
2276
2277

2278
2279
2280
2281
2282
2283
2284
2285

2286
2287
2288
2289
2290
2291
2292

2293
2294
2295

2296
2297
2298

2299
2300
2301
2302
2303
2304

2305
2306
2307
2308
2309
2310

2311
2312
2313

2314
2315
2316

2317
2318
2319
2320
2321
2322
2323
2324
2325

2326
2327
2328
2329
2330
2331
2332
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
2399


2400
2401
2402
2403
2404
2405
2406
2407







-
+

-
+





-
+







-
+






-
+


-
+


-
+





-
+





-
+


-
+


-
+







-
-
+







 *	FreeDictUpdateInfo: releases memory
 *	PrintDictUpdateInfo: none
 *	DisassembleDictUpdateInfo: none
 *
 *----------------------------------------------------------------------
 */

static ClientData
static void *
DupDictUpdateInfo(
    ClientData clientData)
    void *clientData)
{
    DictUpdateInfo *dui1Ptr, *dui2Ptr;
    size_t len;

    dui1Ptr = (DictUpdateInfo *)clientData;
    len = offsetof(DictUpdateInfo, varIndices) + sizeof(int) * dui1Ptr->length;
    len = offsetof(DictUpdateInfo, varIndices) + sizeof(size_t) * dui1Ptr->length;
    dui2Ptr = (DictUpdateInfo *)Tcl_Alloc(len);
    memcpy(dui2Ptr, dui1Ptr, len);
    return dui2Ptr;
}

static void
FreeDictUpdateInfo(
    ClientData clientData)
    void *clientData)
{
    Tcl_Free(clientData);
}

static void
PrintDictUpdateInfo(
    ClientData clientData,
    void *clientData,
    Tcl_Obj *appendObj,
    TCL_UNUSED(ByteCode *),
    TCL_UNUSED(unsigned int))
    TCL_UNUSED(size_t))
{
    DictUpdateInfo *duiPtr = (DictUpdateInfo *)clientData;
    size_t i;
    Tcl_Size i;

    for (i=0 ; i<duiPtr->length ; i++) {
	if (i) {
	    Tcl_AppendToObj(appendObj, ", ", -1);
	}
	Tcl_AppendPrintfToObj(appendObj, "%%v%u", duiPtr->varIndices[i]);
	Tcl_AppendPrintfToObj(appendObj, "%%v%" TCL_Z_MODIFIER "u", duiPtr->varIndices[i]);
    }
}

static void
DisassembleDictUpdateInfo(
    ClientData clientData,
    void *clientData,
    Tcl_Obj *dictObj,
    TCL_UNUSED(ByteCode *),
    TCL_UNUSED(unsigned int))
    TCL_UNUSED(size_t))
{
    DictUpdateInfo *duiPtr = (DictUpdateInfo *)clientData;
    size_t i;
    Tcl_Size i;
    Tcl_Obj *variables;

    TclNewObj(variables);
    for (i=0 ; i<duiPtr->length ; i++) {
	Tcl_ListObjAppendElement(NULL, variables,
		Tcl_NewWideIntObj(duiPtr->varIndices[i]));
    }
    Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("variables", -1),
	    variables);
    TclDictPut(NULL, dictObj, "variables", variables);
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileErrorCmd --
 *
2354
2355
2356
2357
2358
2359
2360
2361

2362
2363
2364
2365
2366
2367
2368
2429
2430
2431
2432
2433
2434
2435

2436
2437
2438
2439
2440
2441
2442
2443







-
+







    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr;

    /*
     * General syntax: [error message ?errorInfo? ?errorCode?]
     */

    if (parsePtr->numWords < 2 || parsePtr->numWords > 4) {
    if ((int)parsePtr->numWords < 2 || (int)parsePtr->numWords > 4) {
	return TCL_ERROR;
    }

    /*
     * Handle the message.
     */

2434
2435
2436
2437
2438
2439
2440
2441

2442
2443
2444
2445
2446
2447
2448
2509
2510
2511
2512
2513
2514
2515

2516
2517
2518
2519
2520
2521
2522
2523







-
+







     * TIP #280: Use the per-word line information of the current command.
     */

    envPtr->line = envPtr->extCmdMapPtr->loc[
	    envPtr->extCmdMapPtr->nuloc-1].line[1];

    firstWordPtr = TokenAfter(parsePtr->tokenPtr);
    TclCompileExprWords(interp, firstWordPtr, parsePtr->numWords-1, envPtr);
    TclCompileExprWords(interp, firstWordPtr, (int)parsePtr->numWords-1, envPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileForCmd --
2609
2610
2611
2612
2613
2614
2615
2616

2617
2618
2619
2620
2621
2622
2623
2684
2685
2686
2687
2688
2689
2690

2691
2692
2693
2694
2695
2696
2697
2698







-
+







 */

int
TclCompileForeachCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    return CompileEachloopCmd(interp, parsePtr, cmdPtr, envPtr,
	    TCL_EACH_KEEP_NONE);
}

2640
2641
2642
2643
2644
2645
2646
2647
2648


2649
2650
2651
2652
2653
2654
2655
2715
2716
2717
2718
2719
2720
2721


2722
2723
2724
2725
2726
2727
2728
2729
2730







-
-
+
+







 */

int
TclCompileLmapCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
				 * compiled. */
    Command *cmdPtr,		/* Points to the definition of the command
				 *  being compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    return CompileEachloopCmd(interp, parsePtr, cmdPtr, envPtr,
	    TCL_EACH_COLLECT);
}

/*
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
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







-
+
+











-
+





-
+







    Proc *procPtr = envPtr->procPtr;
    ForeachInfo *infoPtr=NULL;	/* Points to the structure describing this
				 * foreach command. Stored in a AuxData
				 * record in the ByteCode. */

    Tcl_Token *tokenPtr, *bodyTokenPtr;
    int jumpBackOffset, infoIndex, range;
    int numWords, numLists, i, j, code = TCL_OK;
    int numWords, numLists, i, code = TCL_OK;
    Tcl_Size j;
    Tcl_Obj *varListObj = NULL;

    /*
     * If the foreach command isn't in a procedure, don't compile it inline:
     * the payoff is too small.
     */

    if (procPtr == NULL) {
	return TCL_ERROR;
    }

    numWords = parsePtr->numWords;
    numWords = (int)parsePtr->numWords;
    if ((numWords < 4) || (numWords%2 != 0)) {
	return TCL_ERROR;
    }

    /*
     * Bail out if the body requires substitutions in order to insure correct
     * Bail out if the body requires substitutions in order to ensure correct
     * behaviour. [Bug 219166]
     */

    for (i = 0, tokenPtr = parsePtr->tokenPtr; i < numWords-1; i++) {
	tokenPtr = TokenAfter(tokenPtr);
    }
    bodyTokenPtr = tokenPtr;
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
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







-
+












-
+






-
+








-
+
-







     */

    TclNewObj(varListObj);
    for (i = 0, tokenPtr = parsePtr->tokenPtr;
	    i < numWords-1;
	    i++, tokenPtr = TokenAfter(tokenPtr)) {
	ForeachVarList *varListPtr;
	int numVars;
	Tcl_Size numVars;

	if (i%2 != 1) {
	    continue;
	}

	/*
	 * If the variable list is empty, we can enter an infinite loop when
	 * the interpreted version would not.  Take care to ensure this does
	 * not happen.  [Bug 1671138]
	 */

	if (!TclWordKnownAtCompileTime(tokenPtr, varListObj) ||
		TCL_OK != Tcl_ListObjLength(NULL, varListObj, &numVars) ||
		TCL_OK != TclListObjLength(NULL, varListObj, &numVars) ||
		numVars == 0) {
	    code = TCL_ERROR;
	    goto done;
	}

	varListPtr = (ForeachVarList *)Tcl_Alloc(offsetof(ForeachVarList, varIndexes)
		+ numVars * sizeof(int));
		+ numVars * sizeof(varListPtr->varIndexes[0]));
	varListPtr->numVars = numVars;
	infoPtr->varLists[i/2] = varListPtr;
	infoPtr->numLists++;

	for (j = 0;  j < numVars;  j++) {
	    Tcl_Obj *varNameObj;
	    const char *bytes;
	    int varIndex;
	    size_t length;
	    Tcl_Size length;


	    Tcl_ListObjIndex(NULL, varListObj, j, &varNameObj);
	    bytes = TclGetStringFromObj(varNameObj, &length);
	    varIndex = LocalScalar(bytes, length, envPtr);
	    if (varIndex < 0) {
		code = TCL_ERROR;
		goto done;
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
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







-
+

-
+

















-
+







 *	original ForeachInfo structure pointed to any ForeachVarList records,
 *	these structures are also copied and pointers to them are stored in
 *	the new ForeachInfo record.
 *
 *----------------------------------------------------------------------
 */

static ClientData
static void *
DupForeachInfo(
    ClientData clientData)	/* The foreach command's compilation auxiliary
    void *clientData)	/* The foreach command's compilation auxiliary
				 * data to duplicate. */
{
    ForeachInfo *srcPtr = (ForeachInfo *)clientData;
    ForeachInfo *dupPtr;
    ForeachVarList *srcListPtr, *dupListPtr;
    int numVars, i, j, numLists = srcPtr->numLists;

    dupPtr = (ForeachInfo *)Tcl_Alloc(offsetof(ForeachInfo, varLists)
	    + numLists * sizeof(ForeachVarList *));
    dupPtr->numLists = numLists;
    dupPtr->firstValueTemp = srcPtr->firstValueTemp;
    dupPtr->loopCtTemp = srcPtr->loopCtTemp;

    for (i = 0;  i < numLists;  i++) {
	srcListPtr = srcPtr->varLists[i];
	numVars = srcListPtr->numVars;
	dupListPtr = (ForeachVarList *)Tcl_Alloc(offsetof(ForeachVarList, varIndexes)
		+ numVars * sizeof(int));
		+ numVars * sizeof(size_t));
	dupListPtr->numVars = numVars;
	for (j = 0;  j < numVars;  j++) {
	    dupListPtr->varIndexes[j] =	srcListPtr->varIndexes[j];
	}
	dupPtr->varLists[i] = dupListPtr;
    }
    return dupPtr;
2934
2935
2936
2937
2938
2939
2940
2941

2942
2943
2944
2945
2946

2947
2948
2949
2950
2951
2952
2953
2954
3009
3010
3011
3012
3013
3014
3015

3016
3017
3018
3019
3020

3021

3022
3023
3024
3025
3026
3027
3028







-
+




-
+
-







 *	ForeachInfo structure.
 *
 *----------------------------------------------------------------------
 */

static void
FreeForeachInfo(
    ClientData clientData)	/* The foreach command's compilation auxiliary
    void *clientData)	/* The foreach command's compilation auxiliary
				 * data to free. */
{
    ForeachInfo *infoPtr = (ForeachInfo *)clientData;
    ForeachVarList *listPtr;
    int numLists = infoPtr->numLists;
    size_t i, numLists = infoPtr->numLists;
    int i;

    for (i = 0;  i < numLists;  i++) {
	listPtr = infoPtr->varLists[i];
	Tcl_Free(listPtr);
    }
    Tcl_Free(infoPtr);
}
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
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
3134
3135
3136
3137

3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
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
3199
3200
3201
3202
3203







-
+


-
+



-
+







-
-
+
+

-
-
+
+




-
-
+
+





-
-
+
+







-
+


-
+



-
+

-
+











-
-
+
+







-
+


-
+



-
+











-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
PrintForeachInfo(
    ClientData clientData,
    void *clientData,
    Tcl_Obj *appendObj,
    TCL_UNUSED(ByteCode *),
    TCL_UNUSED(unsigned int))
    TCL_UNUSED(size_t))
{
    ForeachInfo *infoPtr = (ForeachInfo *)clientData;
    ForeachVarList *varsPtr;
    int i, j;
    Tcl_Size i, j;

    Tcl_AppendToObj(appendObj, "data=[", -1);

    for (i=0 ; i<infoPtr->numLists ; i++) {
	if (i) {
	    Tcl_AppendToObj(appendObj, ", ", -1);
	}
	Tcl_AppendPrintfToObj(appendObj, "%%v%u",
		(unsigned) (infoPtr->firstValueTemp + i));
	Tcl_AppendPrintfToObj(appendObj, "%%v%" TCL_Z_MODIFIER "u",
		(infoPtr->firstValueTemp + i));
    }
    Tcl_AppendPrintfToObj(appendObj, "], loop=%%v%u",
	    (unsigned) infoPtr->loopCtTemp);
    Tcl_AppendPrintfToObj(appendObj, "], loop=%%v%" TCL_Z_MODIFIER "u",
	    infoPtr->loopCtTemp);
    for (i=0 ; i<infoPtr->numLists ; i++) {
	if (i) {
	    Tcl_AppendToObj(appendObj, ",", -1);
	}
	Tcl_AppendPrintfToObj(appendObj, "\n\t\t it%%v%u\t[",
		(unsigned) (infoPtr->firstValueTemp + i));
	Tcl_AppendPrintfToObj(appendObj, "\n\t\t it%%v%" TCL_Z_MODIFIER "u\t[",
		(infoPtr->firstValueTemp + i));
	varsPtr = infoPtr->varLists[i];
	for (j=0 ; j<varsPtr->numVars ; j++) {
	    if (j) {
		Tcl_AppendToObj(appendObj, ", ", -1);
	    }
	    Tcl_AppendPrintfToObj(appendObj, "%%v%u",
		    (unsigned) varsPtr->varIndexes[j]);
	    Tcl_AppendPrintfToObj(appendObj, "%%v%" TCL_Z_MODIFIER "u",
		    varsPtr->varIndexes[j]);
	}
	Tcl_AppendToObj(appendObj, "]", -1);
    }
}

static void
PrintNewForeachInfo(
    ClientData clientData,
    void *clientData,
    Tcl_Obj *appendObj,
    TCL_UNUSED(ByteCode *),
    TCL_UNUSED(unsigned int))
    TCL_UNUSED(size_t))
{
    ForeachInfo *infoPtr = (ForeachInfo *)clientData;
    ForeachVarList *varsPtr;
    int i, j;
    Tcl_Size i, j;

    Tcl_AppendPrintfToObj(appendObj, "jumpOffset=%+d, vars=",
    Tcl_AppendPrintfToObj(appendObj, "jumpOffset=%+" TCL_Z_MODIFIER "d, vars=",
	    infoPtr->loopCtTemp);
    for (i=0 ; i<infoPtr->numLists ; i++) {
	if (i) {
	    Tcl_AppendToObj(appendObj, ",", -1);
	}
	Tcl_AppendToObj(appendObj, "[", -1);
	varsPtr = infoPtr->varLists[i];
	for (j=0 ; j<varsPtr->numVars ; j++) {
	    if (j) {
		Tcl_AppendToObj(appendObj, ",", -1);
	    }
	    Tcl_AppendPrintfToObj(appendObj, "%%v%u",
		    (unsigned) varsPtr->varIndexes[j]);
	    Tcl_AppendPrintfToObj(appendObj, "%%v%" TCL_Z_MODIFIER "u",
		    varsPtr->varIndexes[j]);
	}
	Tcl_AppendToObj(appendObj, "]", -1);
    }
}

static void
DisassembleForeachInfo(
    ClientData clientData,
    void *clientData,
    Tcl_Obj *dictObj,
    TCL_UNUSED(ByteCode *),
    TCL_UNUSED(unsigned int))
    TCL_UNUSED(size_t))
{
    ForeachInfo *infoPtr = (ForeachInfo *)clientData;
    ForeachVarList *varsPtr;
    int i, j;
    Tcl_Size i, j;
    Tcl_Obj *objPtr, *innerPtr;

    /*
     * Data stores.
     */

    TclNewObj(objPtr);
    for (i=0 ; i<infoPtr->numLists ; i++) {
	Tcl_ListObjAppendElement(NULL, objPtr,
		Tcl_NewWideIntObj(infoPtr->firstValueTemp + i));
    }
    Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("data", -1), objPtr);
    TclDictPut(NULL, dictObj, "data", objPtr);

    /*
     * Loop counter.
     */

    TclDictPut(NULL, dictObj, "loop", Tcl_NewWideIntObj(infoPtr->loopCtTemp));

    /*
     * Assignment targets.
     */

    TclNewObj(objPtr);
    for (i=0 ; i<infoPtr->numLists ; i++) {
	TclNewObj(innerPtr);
	varsPtr = infoPtr->varLists[i];
	for (j=0 ; j<varsPtr->numVars ; j++) {
	    Tcl_ListObjAppendElement(NULL, innerPtr,
		    Tcl_NewWideIntObj(varsPtr->varIndexes[j]));
	}
	Tcl_ListObjAppendElement(NULL, objPtr, innerPtr);
    }
    TclDictPut(NULL, dictObj, "assign", objPtr);
}

static void
DisassembleNewForeachInfo(
    void *clientData,
    Tcl_Obj *dictObj,
    TCL_UNUSED(ByteCode *),
    TCL_UNUSED(size_t))
{
    ForeachInfo *infoPtr = (ForeachInfo *)clientData;
    ForeachVarList *varsPtr;
    Tcl_Size i, j;
    Tcl_Obj *objPtr, *innerPtr;

    /*
     * Jump offset.
     */

    Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("loop", -1),
	   Tcl_NewWideIntObj(infoPtr->loopCtTemp));
    TclDictPut(NULL, dictObj, "jumpOffset",
	    Tcl_NewWideIntObj(infoPtr->loopCtTemp));

    /*
     * Assignment targets.
     */

    TclNewObj(objPtr);
    for (i=0 ; i<infoPtr->numLists ; i++) {
	TclNewObj(innerPtr);
	varsPtr = infoPtr->varLists[i];
	for (j=0 ; j<varsPtr->numVars ; j++) {
	    Tcl_ListObjAppendElement(NULL, innerPtr,
		    Tcl_NewWideIntObj(varsPtr->varIndexes[j]));
	}
	Tcl_ListObjAppendElement(NULL, objPtr, innerPtr);
    }
    Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("assign", -1), objPtr);
}

static void
DisassembleNewForeachInfo(
    ClientData clientData,
    Tcl_Obj *dictObj,
    TCL_UNUSED(ByteCode *),
    TCL_UNUSED(unsigned int))
{
    ForeachInfo *infoPtr = (ForeachInfo *)clientData;
    ForeachVarList *varsPtr;
    int i, j;
    Tcl_Obj *objPtr, *innerPtr;

    /*
     * Jump offset.
     */

    Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("jumpOffset", -1),
    TclDictPut(NULL, dictObj, "assign", objPtr);
	   Tcl_NewWideIntObj(infoPtr->loopCtTemp));

    /*
     * Assignment targets.
     */

    TclNewObj(objPtr);
    for (i=0 ; i<infoPtr->numLists ; i++) {
	TclNewObj(innerPtr);
	varsPtr = infoPtr->varLists[i];
	for (j=0 ; j<varsPtr->numVars ; j++) {
	    Tcl_ListObjAppendElement(NULL, innerPtr,
		    Tcl_NewWideIntObj(varsPtr->varIndexes[j]));
	}
	Tcl_ListObjAppendElement(NULL, objPtr, innerPtr);
    }
    Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("assign", -1), objPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileFormatCmd --
 *
3151
3152
3153
3154
3155
3156
3157
3158

3159
3160
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
3199
3200
3201
3202
3203
3204
3224
3225
3226
3227
3228
3229
3230

3231
3232
3233
3234
3235
3236

3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253


3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269

3270
3271
3272
3273
3274
3275
3276
3277







-
+





-
+
















-
-
+
+














-
+







    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = parsePtr->tokenPtr;
    Tcl_Obj **objv, *formatObj, *tmpObj;
    const char *bytes, *start;
    int i, j;
    size_t len;
    Tcl_Size len;

    /*
     * Don't handle any guaranteed-error cases.
     */

    if (parsePtr->numWords < 2) {
    if ((int)parsePtr->numWords < 2) {
	return TCL_ERROR;
    }

    /*
     * Check if the argument words are all compile-time-known literals; that's
     * a case we can handle by compiling to a constant.
     */

    TclNewObj(formatObj);
    Tcl_IncrRefCount(formatObj);
    tokenPtr = TokenAfter(tokenPtr);
    if (!TclWordKnownAtCompileTime(tokenPtr, formatObj)) {
	Tcl_DecrRefCount(formatObj);
	return TCL_ERROR;
    }

    objv = (Tcl_Obj **)Tcl_Alloc((parsePtr->numWords-2) * sizeof(Tcl_Obj *));
    for (i=0 ; i+2 < parsePtr->numWords ; i++) {
    objv = (Tcl_Obj **)Tcl_Alloc(((int)parsePtr->numWords-2) * sizeof(Tcl_Obj *));
    for (i=0 ; i+2 < (int)parsePtr->numWords ; i++) {
	tokenPtr = TokenAfter(tokenPtr);
	TclNewObj(objv[i]);
	Tcl_IncrRefCount(objv[i]);
	if (!TclWordKnownAtCompileTime(tokenPtr, objv[i])) {
	    goto checkForStringConcatCase;
	}
    }

    /*
     * Everything is a literal, so the result is constant too (or an error if
     * the format is broken). Do the format now.
     */

    tmpObj = Tcl_Format(interp, TclGetString(formatObj),
	    parsePtr->numWords-2, objv);
	    (int)parsePtr->numWords-2, objv);
    for (; --i>=0 ;) {
	Tcl_DecrRefCount(objv[i]);
    }
    Tcl_Free(objv);
    Tcl_DecrRefCount(formatObj);
    if (tmpObj == NULL) {
	TclCompileSyntaxError(interp, envPtr);
3251
3252
3253
3254
3255
3256
3257
3258

3259
3260
3261
3262
3263
3264
3265
3324
3325
3326
3327
3328
3329
3330

3331
3332
3333
3334
3335
3336
3337
3338







-
+







	}
    }

    /*
     * Check if the number of things to concatenate will fit in a byte.
     */

    if (i+2 != parsePtr->numWords || i > 125) {
    if (i+2 != (int)parsePtr->numWords || i > 125) {
	Tcl_DecrRefCount(formatObj);
	return TCL_ERROR;
    }

    /*
     * Generate the pushes of the things to concatenate, a sequence of
     * literals and compiled tokens (of which at least one is non-literal or
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348




3349
3350
3351

3352
3353
3354
3355
3356

3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370

3371
3372
3373
3374
3375
3376
3377




3378
3379
3380
3381
3382
3383
3384
3411
3412
3413
3414
3415
3416
3417




3418
3419
3420
3421
3422
3423

3424
3425
3426
3427
3428

3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442

3443
3444
3445
3446
3447
3448


3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459







-
-
-
-
+
+
+
+


-
+




-
+













-
+





-
-
+
+
+
+







 *
 * TclLocalScalarFromToken --
 *
 *	Get the index into the table of compiled locals that corresponds
 *	to a local scalar variable name.
 *
 * Results:
 * 	Returns the non-negative integer index value into the table of
 * 	compiled locals corresponding to a local scalar variable name.
 * 	If the arguments passed in do not identify a local scalar variable
 * 	then return -1.
 *	Returns the non-negative integer index value into the table of
 *	compiled locals corresponding to a local scalar variable name.
 *	If the arguments passed in do not identify a local scalar variable
 *	then return TCL_INDEX_NONE.
 *
 * Side effects:
 *	May add an entery into the table of compiled locals.
 *	May add an entry into the table of compiled locals.
 *
 *----------------------------------------------------------------------
 */

int
size_t
TclLocalScalarFromToken(
    Tcl_Token *tokenPtr,
    CompileEnv *envPtr)
{
    int isScalar, index;

    TclPushVarName(NULL, tokenPtr, envPtr, TCL_NO_ELEMENT, &index, &isScalar);
    if (!isScalar) {
	index = -1;
    }
    return index;
}

int
size_t
TclLocalScalar(
    const char *bytes,
    size_t numBytes,
    CompileEnv *envPtr)
{
    Tcl_Token token[2] =        {{TCL_TOKEN_SIMPLE_WORD, NULL, 0, 1},
                                 {TCL_TOKEN_TEXT, NULL, 0, 0}};
    Tcl_Token token[2] = {
	{TCL_TOKEN_SIMPLE_WORD, NULL, 0, 1},
	{TCL_TOKEN_TEXT, NULL, 0, 0}
    };

    token[1].start = bytes;
    token[1].size = numBytes;
    return TclLocalScalarFromToken(token, envPtr);
}

/*
3487
3488
3489
3490
3491
3492
3493
3494
3495


3496
3497
3498
3499
3500
3501
3502
3562
3563
3564
3565
3566
3567
3568


3569
3570
3571
3572
3573
3574
3575
3576
3577







-
-
+
+







	    && (varTokenPtr[n].type == TCL_TOKEN_TEXT)
	    && (*(varTokenPtr[n].start + varTokenPtr[n].size - 1) == ')')) {
	/*
	 * Check for parentheses inside first token.
	 */

	simpleVarName = 0;
	for (p = varTokenPtr[1].start,
	     last = p + varTokenPtr[1].size;  p < last;  p++) {
	for (p = varTokenPtr[1].start, last = p + varTokenPtr[1].size;
		p < last;  p++) {
	    if (*p == '(') {
		simpleVarName = 1;
		break;
	    }
	}
	if (simpleVarName) {
	    size_t remainingLen;
3557
3558
3559
3560
3561
3562
3563
3564

3565
3566
3567
3568
3569
3570
3571
3632
3633
3634
3635
3636
3637
3638

3639
3640
3641
3642
3643
3644
3645
3646







-
+







	/*
	 * See whether name has any namespace separators (::'s).
	 */

	int hasNsQualifiers = 0;

	for (p = name, last = p + nameLen-1;  p < last;  p++) {
	    if ((*p == ':') && (*(p+1) == ':')) {
	    if ((p[0] == ':') && (p[1] == ':')) {
		hasNsQualifiers = 1;
		break;
	    }
	}

	/*
	 * Look up the var name's index in the array of local vars in the proc

Changes to generic/tclCompCmdsGR.c.

1
2
3
4
5
6
7
8
9
10
11




12
13
14
15
16
17
18
1
2
3
4
5
6
7




8
9
10
11
12
13
14
15
16
17
18







-
-
-
-
+
+
+
+







/*
 * tclCompCmdsGR.c --
 *
 *	This file contains compilation procedures that compile various Tcl
 *	commands (beginning with the letters 'g' through 'r') into a sequence
 *	of instructions ("bytecodes").
 *
 * Copyright (c) 1997-1998 Sun Microsystems, Inc.
 * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
 * Copyright (c) 2002 ActiveState Corporation.
 * Copyright (c) 2004-2013 by Donal K. Fellows.
 * Copyright © 1997-1998 Sun Microsystems, Inc.
 * Copyright © 2001 Kevin B. Kenny.  All rights reserved.
 * Copyright © 2002 ActiveState Corporation.
 * Copyright © 2004-2013 Donal K. Fellows.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclCompile.h"
177
178
179
180
181
182
183
184
185


186
187
188
189
190
191
192
177
178
179
180
181
182
183


184
185
186
187
188
189
190
191
192







-
-
+
+







				 * test when its target PC is determined. */
    JumpFixupArray jumpEndFixupArray;
				/* Used to fix the jump after each "then" body
				 * to the end of the "if" when that PC is
				 * determined. */
    Tcl_Token *tokenPtr, *testTokenPtr;
    int jumpIndex = 0;		/* Avoid compiler warning. */
	size_t numBytes;
    int jumpFalseDist, numWords, wordIdx, j, code;
	size_t numBytes, j;
    int jumpFalseDist, numWords, wordIdx, code;
    const char *word;
    int realCond = 1;		/* Set to 0 for static conditions:
				 * "if 0 {..}" */
    int boolVal;		/* Value of static condition. */
    int compileScripts = 1;

    /*
412
413
414
415
416
417
418
419

420
421
422
423
424
425
426
412
413
414
415
416
417
418

419
420
421
422
423
424
425
426







-
+







     */

    for (j = jumpEndFixupArray.next;  j > 0;  j--) {
	jumpIndex = (j - 1);	/* i.e. process the closest jump first. */
	if (TclFixupForwardJumpToHere(envPtr,
		jumpEndFixupArray.fixup + jumpIndex, 127)) {
	    /*
	     * Adjust the immediately preceeding "ifFalse" jump. We moved it's
	     * Adjust the immediately preceding "ifFalse" jump. We moved it's
	     * target (just after this jump) down three bytes.
	     */

	    unsigned char *ifFalsePc = envPtr->codeStart
		    + jumpFalseFixupArray.fixup[jumpIndex].codeOffset;
	    unsigned char opCode = *ifFalsePc;

472
473
474
475
476
477
478
479


480
481
482
483
484
485
486
472
473
474
475
476
477
478

479
480
481
482
483
484
485
486
487







-
+
+







    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *varTokenPtr, *incrTokenPtr;
    int isScalar, localIndex, haveImmValue, immValue;
    int isScalar, localIndex, haveImmValue;
    Tcl_WideInt immValue;

    if ((parsePtr->numWords != 2) && (parsePtr->numWords != 3)) {
	return TCL_ERROR;
    }

    varTokenPtr = TokenAfter(parsePtr->tokenPtr);

499
500
501
502
503
504
505
506

507
508
509
510

511
512
513
514
515
516
517
500
501
502
503
504
505
506

507

508
509
510
511
512
513
514
515
516
517
518







-
+
-



+







	if (incrTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
	    const char *word = incrTokenPtr[1].start;
	    size_t numBytes = incrTokenPtr[1].size;
	    int code;
	    Tcl_Obj *intObj = Tcl_NewStringObj(word, numBytes);

	    Tcl_IncrRefCount(intObj);
	    code = TclGetIntFromObj(NULL, intObj, &immValue);
	    code = TclGetWideIntFromObj(NULL, intObj, &immValue);
	    TclDecrRefCount(intObj);
	    if ((code == TCL_OK) && (-127 <= immValue) && (immValue <= 127)) {
		haveImmValue = 1;
	    }
	    TclDecrRefCount(intObj);
	    if (!haveImmValue) {
		PushLiteral(envPtr, word, numBytes);
	    }
	} else {
	    SetLineInformation(2);
	    CompileTokens(envPtr, incrTokenPtr, interp);
	}
577
578
579
580
581
582
583
584

585
586
587
588
589
590
591
578
579
580
581
582
583
584

585
586
587
588
589
590
591
592







-
+







 */

int
TclCompileInfoCommandsCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr;
    Tcl_Obj *objPtr;
    const char *bytes;
615
616
617
618
619
620
621
622
623


624
625
626
627
628
629
630
616
617
618
619
620
621
622


623
624
625
626
627
628
629
630
631







-
-
+
+








    if (bytes[0] != ':' || bytes[1] != ':' || !TclMatchIsTrivial(bytes)) {
	goto notCompilable;
    }
    Tcl_DecrRefCount(objPtr);

    /*
     * Confirmed as a literal that will not frighten the horses. Compile. Note
     * that the result needs to be list-ified.
     * Confirmed as a literal that will not frighten the horses. Compile.
     * The result must be made into a list.
     */

    /* TODO: Just push the known value */
    CompileWord(envPtr, tokenPtr,		interp, 1);
    TclEmitOpcode(	INST_RESOLVE_COMMAND,	envPtr);
    TclEmitOpcode(	INST_DUP,		envPtr);
    TclEmitOpcode(	INST_STR_LEN,		envPtr);
1352
1353
1354
1355
1356
1357
1358
1359
1360


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

1387
1388
1389
1390
1391
1392
1393
1394

1395
1396
1397
1398
1399
1400
1401



1402
1403
1404
1405
1406
1407
1408


1409
1410
1411
1412
1413

1414
1415
1416
1417

1418
1419


1420
1421

1422
1423
1424


1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1353
1354
1355
1356
1357
1358
1359


1360
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
1387












1388
1389
1390
1391
1392
1393
1394







-
-
+
+

-
+


-

-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
+
+



-

-
-
+
+
-
-
-
-
-
+
-
-
-
-
+
-
-
+
+
-
-
+
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-







    Tcl_Interp *interp,		/* Tcl interpreter for context. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the
				 * command. */
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds the resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr, *listTokenPtr;
    int idx, i;
    Tcl_Token *tokenPtr;
    int i;

    if (parsePtr->numWords < 3) {
    if ((int)parsePtr->numWords < 3) {
	return TCL_ERROR;
    }
    listTokenPtr = TokenAfter(parsePtr->tokenPtr);

    /*
     * Parse the index. Will only compile if it is constant and not an
     * _integer_ less than zero (since we reserve negative indices here for
     * end-relative indexing) or an end-based index greater than 'end' itself.
     */

    tokenPtr = TokenAfter(listTokenPtr);

    /* Push list, insertion index onto the stack */
    tokenPtr = TokenAfter(parsePtr->tokenPtr);
    CompileWord(envPtr, tokenPtr, interp, 1);
    /*
     * NOTE: This command treats all inserts at indices before the list
     * the same as inserts at the start of the list, and all inserts
     * after the list the same as inserts at the end of the list. We
     * make that transformation here so we can use the optimized bytecode
     * as much as possible.
     */
    if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_START, TCL_INDEX_END,
	    &idx) != TCL_OK) {
	return TCL_ERROR;
    }

    tokenPtr = TokenAfter(tokenPtr);
    /*
     * There are four main cases. If there are no values to insert, this is
     * just a confirm-listiness check. If the index is '0', this is a prepend.
     * If the index is 'end' (== TCL_INDEX_END), this is an append. Otherwise,
     * this is a splice (== split, insert values as list, concat-3).
     */

    CompileWord(envPtr, listTokenPtr, interp, 1);
    CompileWord(envPtr, tokenPtr, interp, 2);
    if (parsePtr->numWords == 3) {
	TclEmitInstInt4(	INST_LIST_RANGE_IMM, 0,		envPtr);
	TclEmitInt4(			(int)TCL_INDEX_END,		envPtr);
	return TCL_OK;
    }

    for (i=3 ; i<parsePtr->numWords ; i++) {

    /* Push new elements to be inserted */
    for (i=3 ; i<(int)parsePtr->numWords ; i++) {
	tokenPtr = TokenAfter(tokenPtr);
	CompileWord(envPtr, tokenPtr, interp, i);
    }
    TclEmitInstInt4(		INST_LIST, i - 3,		envPtr);

    if (idx == (int)TCL_INDEX_START) {
	TclEmitInstInt4(	INST_REVERSE, 2,		envPtr);
    /* First operand is count of arguments */
    TclEmitInstInt4(INST_LREPLACE4, parsePtr->numWords - 1, envPtr);
	TclEmitOpcode(		INST_LIST_CONCAT,		envPtr);
    } else if (idx == (int)TCL_INDEX_END) {
	TclEmitOpcode(		INST_LIST_CONCAT,		envPtr);
    } else {
	/*
    /*
	 * Here we handle two ranges for idx. First when idx > 0, we
	 * want the first half of the split to end at index idx-1 and
	 * the second half to start at index idx.
	 * Second when idx < TCL_INDEX_END, indicating "end-N" indexing,
     * Second operand is bitmask
	 * we want the first half of the split to end at index end-N and
	 * the second half to start at index end-N+1. We accomplish this
     *  TCL_LREPLACE4_END_IS_LAST - end refers to last element
     *  TCL_LREPLACE4_SINGLE_INDEX - second index is not present
	 * with a pre-adjustment of the end-N value.
	 * The root of this is that the commands [lrange] and [linsert]
     *     indicating this is a pure insert
	 * differ in their interpretation of the "end" index.
	 */

     */
    TclEmitInt1(TCL_LREPLACE4_SINGLE_INDEX, envPtr);
	if (idx < (int)TCL_INDEX_END) {
	    idx++;
	}
	TclEmitInstInt4(	INST_OVER, 1,			envPtr);
	TclEmitInstInt4(	INST_LIST_RANGE_IMM, 0,		envPtr);
	TclEmitInt4(			idx - 1,		envPtr);
	TclEmitInstInt4(	INST_REVERSE, 3,		envPtr);
	TclEmitInstInt4(	INST_LIST_RANGE_IMM, idx,	envPtr);
	TclEmitInt4(			(int)TCL_INDEX_END,		envPtr);
	TclEmitOpcode(		INST_LIST_CONCAT,		envPtr);
	TclEmitOpcode(		INST_LIST_CONCAT,		envPtr);
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
1454
1455
1456
1457
1458
1459
1460
1461
1462


1463
1464
1465
1466
1467
1468
1469

1470

1471
1472
1473
1474
1475

1476
1477
1478
1479
1480
1481

1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492

1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507

1508
1509
1510

1511
1512
1513

1514
1515
1516
1517

1518
1519

1520
1521
1522
1523

1524
1525
1526

1527
1528

1529
1530
1531
1532



1533
1534
1535
1536
1537

1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1405
1406
1407
1408
1409
1410
1411


1412
1413

1414
1415
1416
1417

1418
1419

1420





1421
1422





1423











1424















1425
1426


1427



1428

1429


1430


1431
1432



1433



1434


1435




1436
1437
1438





1439

































1440
1441
1442
1443
1444
1445
1446







-
-
+
+
-




-

+
-
+
-
-
-
-
-
+

-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+

-
-
+
-
-
-
+
-

-
-
+
-
-
+

-
-
-
+
-
-
-
+
-
-
+
-
-
-
-
+
+
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    Tcl_Interp *interp,		/* Tcl interpreter for context. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the
				 * command. */
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds the resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr, *listTokenPtr;
    int idx1, idx2, i;
    Tcl_Token *tokenPtr;
    int i;
    int emptyPrefix=1, suffixStart = 0;

    if (parsePtr->numWords < 4) {
	return TCL_ERROR;
    }
    listTokenPtr = TokenAfter(parsePtr->tokenPtr);

    /* Push list, first, last onto the stack */
    tokenPtr = TokenAfter(listTokenPtr);
    tokenPtr = TokenAfter(parsePtr->tokenPtr);
    if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_START, TCL_INDEX_NONE,
	    &idx1) != TCL_OK) {
	return TCL_ERROR;
    }

    CompileWord(envPtr, tokenPtr, interp, 1);
    tokenPtr = TokenAfter(tokenPtr);
    if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_NONE, TCL_INDEX_END,
	    &idx2) != TCL_OK) {
	return TCL_ERROR;
    }

    CompileWord(envPtr, tokenPtr, interp, 2);
    /*
     * General structure of the [lreplace] result is
     *		prefix replacement suffix
     * In a few cases we can predict various parts will be empty and
     * take advantage.
     *
     * The proper suffix begins with the greater of indices idx1 or
     * idx2 + 1. If we cannot tell at compile time which is greater,
     * we must defer to direct evaluation.
     */

    tokenPtr = TokenAfter(tokenPtr);
    if (idx1 == (int)TCL_INDEX_NONE) {
	suffixStart = (int)TCL_INDEX_NONE;
    } else if (idx2 == (int)TCL_INDEX_NONE) {
	suffixStart = idx1;
    } else if (idx2 == (int)TCL_INDEX_END) {
	suffixStart = (int)TCL_INDEX_NONE;
    } else if (((idx2 < (int)TCL_INDEX_END) && (idx1 <= (int)TCL_INDEX_END))
	    || ((idx2 >= (int)TCL_INDEX_START) && (idx1 >= (int)TCL_INDEX_START))) {
	suffixStart = (idx1 > idx2 + 1) ? idx1 : idx2 + 1;
    } else {
	return TCL_ERROR;
    }

    /* All paths start with computing/pushing the original value. */
    CompileWord(envPtr, listTokenPtr, interp, 1);
    CompileWord(envPtr, tokenPtr, interp, 3);

    /*
     * Push all the replacement values next so any errors raised in
    /* Push new elements to be inserted */
     * creating them get raised first.
     */
    if (parsePtr->numWords > 4) {
    for (i=4 ; i< (int)parsePtr->numWords ; i++) {
	/* Push the replacement arguments */
	tokenPtr = TokenAfter(tokenPtr);
	for (i=4 ; i<parsePtr->numWords ; i++) {
	    CompileWord(envPtr, tokenPtr, interp, i);
	CompileWord(envPtr, tokenPtr, interp, i);
	    tokenPtr = TokenAfter(tokenPtr);
	}
    }

	/* Make a list of them... */
	TclEmitInstInt4(	INST_LIST, i - 4,		envPtr);

    /* First operand is count of arguments */
	emptyPrefix = 0;
    }

    TclEmitInstInt4(INST_LREPLACE4, parsePtr->numWords - 1, envPtr);
    if ((idx1 == suffixStart) && (parsePtr->numWords == 4)) {
	/*
    /*
	 * This is a "no-op". Example: [lreplace {a b c} 2 0]
	 * We still do a list operation to get list-verification
	 * and canonicalization side effects.
	 */
     * Second operand is bitmask
     *  TCL_LREPLACE4_END_IS_LAST - end refers to last element
     */
	TclEmitInstInt4(	INST_LIST_RANGE_IMM, 0,		envPtr);
	TclEmitInt4(			(int)TCL_INDEX_END,		envPtr);
	return TCL_OK;
    }

    TclEmitInt1(TCL_LREPLACE4_END_IS_LAST, envPtr);
    if (idx1 != (int)TCL_INDEX_START) {
	/* Prefix may not be empty; generate bytecode to push it */
	if (emptyPrefix) {
	    TclEmitOpcode(	INST_DUP,			envPtr);
	} else {
	    TclEmitInstInt4(	INST_OVER, 1,			envPtr);
	}
	TclEmitInstInt4(	INST_LIST_RANGE_IMM, 0,		envPtr);
	TclEmitInt4(			idx1 - 1,		envPtr);
	if (!emptyPrefix) {
	    TclEmitInstInt4(	INST_REVERSE, 2,		envPtr);
	    TclEmitOpcode(	INST_LIST_CONCAT,		envPtr);
	}
	emptyPrefix = 0;
    }

    if (!emptyPrefix) {
	TclEmitInstInt4(	INST_REVERSE, 2,		envPtr);
    }

    if (suffixStart == (int)TCL_INDEX_NONE) {
	TclEmitOpcode(		INST_POP,			envPtr);
	if (emptyPrefix) {
	    PushStringLiteral(envPtr, "");
	}
    } else {
	/* Suffix may not be empty; generate bytecode to push it */
	TclEmitInstInt4(	INST_LIST_RANGE_IMM, suffixStart, envPtr);
	TclEmitInt4(			(int)TCL_INDEX_END,		envPtr);
	if (!emptyPrefix) {
	    TclEmitOpcode(	INST_LIST_CONCAT,		envPtr);
	}
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
1630
1631
1632
1633
1634
1635
1636
1637

1638
1639
1640
1641
1642
1643
1644
1499
1500
1501
1502
1503
1504
1505

1506
1507
1508
1509
1510
1511
1512
1513







-
+







    int i;

    /*
     * Check argument count.
     */

    /* TODO: Consider support for compiling expanded args. */
    if (parsePtr->numWords < 3) {
    if ((int)parsePtr->numWords < 3) {
	/*
	 * Fail at run time, not in compilation.
	 */

	return TCL_ERROR;
    }

1654
1655
1656
1657
1658
1659
1660
1661

1662
1663
1664
1665
1666
1667
1668
1523
1524
1525
1526
1527
1528
1529

1530
1531
1532
1533
1534
1535
1536
1537







-
+







    PushVarNameWord(interp, varTokenPtr, envPtr, 0,
	    &localIndex, &isScalar, 1);

    /*
     * Push the "index" args and the new element value.
     */

    for (i=2 ; i<parsePtr->numWords ; ++i) {
    for (i=2 ; i<(int)parsePtr->numWords ; ++i) {
	varTokenPtr = TokenAfter(varTokenPtr);
	CompileWord(envPtr, varTokenPtr, interp, i);
    }

    /*
     * Duplicate the variable name if it's been pushed.
     */
1939
1940
1941
1942
1943
1944
1945
1946

1947
1948
1949
1950
1951
1952
1953
1808
1809
1810
1811
1812
1813
1814

1815
1816
1817
1818
1819
1820
1821
1822







-
+







	return TCL_ERROR;
    }

    /*
     * Only compile [namespace upvar ...]: needs an even number of args, >=4
     */

    numWords = parsePtr->numWords;
    numWords = (int)parsePtr->numWords;
    if ((numWords % 2) || (numWords < 4)) {
	return TCL_ERROR;
    }

    /*
     * Push the namespace
     */
1991
1992
1993
1994
1995
1996
1997
1998

1999
2000
2001
2002
2003
2004
2005
1860
1861
1862
1863
1864
1865
1866

1867
1868
1869
1870
1871
1872
1873
1874







-
+







    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr, *opt;
    int idx;

    if (parsePtr->numWords < 2 || parsePtr->numWords > 3) {
    if ((int)parsePtr->numWords < 2 || (int)parsePtr->numWords > 3) {
	return TCL_ERROR;
    }
    tokenPtr = TokenAfter(parsePtr->tokenPtr);
    idx = 1;

    /*
     * If there's an option, check that it's "-command". We don't handle
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
2095
2096
2097
2098
2099
2100
2101

2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112

2113
2114
2115
2116
2117
2118
2119
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969

1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980

1981
1982
1983
1984
1985
1986
1987
1988







-
+














-
+














-
+










-
+







    /*
     * We are only interested in compiling simple regexp cases. Currently
     * supported compile cases are:
     *   regexp ?-nocase? ?--? staticString $var
     *   regexp ?-nocase? ?--? {^staticString$} $var
     */

    if (parsePtr->numWords < 3) {
    if ((int)parsePtr->numWords < 3) {
	return TCL_ERROR;
    }

    simple = 0;
    nocase = 0;
    sawLast = 0;
    varTokenPtr = parsePtr->tokenPtr;

    /*
     * We only look for -nocase and -- as options. Everything else gets pushed
     * to runtime execution. This is different than regexp's runtime option
     * handling, but satisfies our stricter needs.
     */

    for (i = 1; i < parsePtr->numWords - 2; i++) {
    for (i = 1; i < (int)parsePtr->numWords - 2; i++) {
	varTokenPtr = TokenAfter(varTokenPtr);
	if (varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	    /*
	     * Not a simple string, so punt to runtime.
	     */

	    return TCL_ERROR;
	}
	str = varTokenPtr[1].start;
	len = varTokenPtr[1].size;
	if ((len == 2) && (str[0] == '-') && (str[1] == '-')) {
	    sawLast++;
	    i++;
	    break;
	} else if ((len > 1) && (strncmp(str,"-nocase", len) == 0)) {
	} else if ((len > 1) && (strncmp(str, "-nocase", len) == 0)) {
	    nocase = 1;
	} else {
	    /*
	     * Not an option we recognize.
	     */

	    return TCL_ERROR;
	}
    }

    if ((parsePtr->numWords - i) != 2) {
    if (((int)parsePtr->numWords - i) != 2) {
	/*
	 * We don't support capturing to variables.
	 */

	return TCL_ERROR;
    }

2158
2159
2160
2161
2162
2163
2164
2165

2166
2167
2168
2169
2170
2171
2172
2173

2174
2175
2176
2177
2178
2179
2180
2027
2028
2029
2030
2031
2032
2033

2034
2035
2036
2037
2038
2039
2040
2041

2042
2043
2044
2045
2046
2047
2048
2049







-
+







-
+







	    simple = 1;
	    PushLiteral(envPtr, Tcl_DStringValue(&ds),Tcl_DStringLength(&ds));
	    Tcl_DStringFree(&ds);
	}
    }

    if (!simple) {
	CompileWord(envPtr, varTokenPtr, interp, parsePtr->numWords - 2);
	CompileWord(envPtr, varTokenPtr, interp, (int)parsePtr->numWords - 2);
    }

    /*
     * Push the string arg.
     */

    varTokenPtr = TokenAfter(varTokenPtr);
    CompileWord(envPtr, varTokenPtr, interp, parsePtr->numWords - 1);
    CompileWord(envPtr, varTokenPtr, interp, (int)parsePtr->numWords - 1);

    if (simple) {
	if (exact && !nocase) {
	    TclEmitOpcode(	INST_STR_EQ,			envPtr);
	} else {
	    TclEmitInstInt1(	INST_STR_MATCH, nocase,		envPtr);
	}
2241
2242
2243
2244
2245
2246
2247
2248

2249
2250

2251
2252
2253
2254
2255
2256
2257
2110
2111
2112
2113
2114
2115
2116

2117
2118

2119
2120
2121
2122
2123
2124
2125
2126







-
+

-
+








    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr, *stringTokenPtr;
    Tcl_Obj *patternObj = NULL, *replacementObj = NULL;
    Tcl_DString pattern;
    const char *bytes;
    int exact, quantified, result = TCL_ERROR;
    size_t len;
    Tcl_Size len;

    if (parsePtr->numWords < 5 || parsePtr->numWords > 6) {
    if ((int)parsePtr->numWords < 5 || (int)parsePtr->numWords > 6) {
	return TCL_ERROR;
    }

    /*
     * Parse the "-all", which must be the first argument (other options not
     * supported, non-"-all" substitution we can't compile).
     */
2350
2351
2352
2353
2354
2355
2356
2357

2358
2359
2360
2361
2362
2363
2364
2219
2220
2221
2222
2223
2224
2225

2226
2227
2228
2229
2230
2231
2232
2233







-
+







     */

    result = TCL_OK;
    bytes = Tcl_DStringValue(&pattern) + 1;
    PushLiteral(envPtr,	bytes, len);
    bytes = TclGetStringFromObj(replacementObj, &len);
    PushLiteral(envPtr,	bytes, len);
    CompileWord(envPtr,	stringTokenPtr, interp, parsePtr->numWords - 2);
    CompileWord(envPtr,	stringTokenPtr, interp, (int)parsePtr->numWords - 2);
    TclEmitOpcode(	INST_STR_MAP,	envPtr);

  done:
    Tcl_DStringFree(&pattern);
    if (patternObj) {
	Tcl_DecrRefCount(patternObj);
    }
2395
2396
2397
2398
2399
2400
2401
2402


2403
2404
2405
2406
2407
2408
2409
2264
2265
2266
2267
2268
2269
2270

2271
2272
2273
2274
2275
2276
2277
2278
2279







-
+
+







    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    /*
     * General syntax: [return ?-option value ...? ?result?]
     * An even number of words means an explicit result argument is present.
     */
    int level, code, objc, size, status = TCL_OK;
    int level, code, objc, status = TCL_OK;
    Tcl_Size size;
    int numWords = parsePtr->numWords;
    int explicitResult = (0 == (numWords % 2));
    int numOptionWords = numWords - 1 - explicitResult;
    Tcl_Obj *returnOpts, **objv;
    Tcl_Token *wordTokenPtr = TokenAfter(parsePtr->tokenPtr);

    /*
2505
2506
2507
2508
2509
2510
2511
2512

2513
2514
2515
2516
2517
2518
2519
2375
2376
2377
2378
2379
2380
2381

2382
2383
2384
2385
2386
2387
2388
2389







-
+







	int index = envPtr->exceptArrayNext - 1;
	int enclosingCatch = 0;

	while (index >= 0) {
	    ExceptionRange range = envPtr->exceptArrayPtr[index];

	    if ((range.type == CATCH_EXCEPTION_RANGE)
		    && (range.catchOffset == -1)) {
		    && (range.catchOffset == TCL_INDEX_NONE)) {
		enclosingCatch = 1;
		break;
	    }
	    index--;
	}
	if (!enclosingCatch) {
	    /*
2605
2606
2607
2608
2609
2610
2611
2612

2613
2614
2615
2616
2617
2618
2619
2475
2476
2477
2478
2479
2480
2481

2482
2483
2484
2485
2486
2487
2488
2489







-
+








void
TclCompileSyntaxError(
    Tcl_Interp *interp,
    CompileEnv *envPtr)
{
    Tcl_Obj *msg = Tcl_GetObjResult(interp);
    size_t numBytes;
    Tcl_Size numBytes;
    const char *bytes = TclGetStringFromObj(msg, &numBytes);

    TclErrorStackResetIf(interp, bytes, numBytes);
    TclEmitPush(TclRegisterLiteral(envPtr, bytes, numBytes, 0), envPtr);
    CompileReturnInternal(envPtr, INST_SYNTAX, TCL_ERROR, 0,
	    TclNoErrorStack(interp, Tcl_GetReturnOptions(interp, TCL_ERROR)));
    Tcl_ResetResult(interp);
2832
2833
2834
2835
2836
2837
2838
2839

2840
2841
2842
2843
2844
2845
2846
2702
2703
2704
2705
2706
2707
2708

2709
2710
2711
2712
2713
2714
2715
2716







-
+







    TCL_UNUSED(Tcl_Interp *),
    Tcl_Token *varTokenPtr,	/* Token representing the variable name */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    Tcl_Obj *tailPtr;
    const char *tailName, *p;
    int n = varTokenPtr->numComponents;
    size_t len;
    Tcl_Size len;
    Tcl_Token *lastTokenPtr;
    int full, localIndex;

    /*
     * Determine if the tail is (a) known at compile time, and (b) not an
     * array element. Should any of these fail, return an error so that the
     * non-compiled command will be called at runtime.
2881
2882
2883
2884
2885
2886
2887
2888

2889
2890
2891
2892
2893
2894
2895
2751
2752
2753
2754
2755
2756
2757

2758
2759
2760
2761
2762
2763
2764
2765







-
+







	}

	/*
	 * Get the tail: immediately after the last '::'
	 */

	for (p = tailName + len -1; p > tailName; p--) {
	    if ((*p == ':') && (*(p - 1) == ':')) {
	    if ((p[0] == ':') && (p[- 1] == ':')) {
		p++;
		break;
	    }
	}
	if (!full && (p == tailName)) {
	    /*
	     * No :: in the last component.
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
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







-
+



-
+



















-
+



-
+







    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = parsePtr->tokenPtr;
    int i;

    if (parsePtr->numWords > 255) {
    if ((int)parsePtr->numWords > 255) {
	return TCL_ERROR;
    }

    for (i=0 ; i<parsePtr->numWords ; i++) {
    for (i=0 ; i<(int)parsePtr->numWords ; i++) {
	CompileWord(envPtr, tokenPtr, interp, i);
	tokenPtr = TokenAfter(tokenPtr);
    }
    TclEmitInstInt1(	INST_TCLOO_NEXT, i,		envPtr);
    return TCL_OK;
}

int
TclCompileObjectNextToCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = parsePtr->tokenPtr;
    int i;

    if (parsePtr->numWords < 2 || parsePtr->numWords > 255) {
    if ((int)parsePtr->numWords < 2 || (int)parsePtr->numWords > 255) {
	return TCL_ERROR;
    }

    for (i=0 ; i<parsePtr->numWords ; i++) {
    for (i=0 ; i<(int)parsePtr->numWords ; i++) {
	CompileWord(envPtr, tokenPtr, interp, i);
	tokenPtr = TokenAfter(tokenPtr);
    }
    TclEmitInstInt1(	INST_TCLOO_NEXT_CLASS, i,	envPtr);
    return TCL_OK;
}

Changes to generic/tclCompCmdsSZ.c.

1
2
3
4
5
6
7
8
9
10
11
12




13
14
15
16
17
18
19
1
2
3
4
5
6
7
8




9
10
11
12
13
14
15
16
17
18
19








-
-
-
-
+
+
+
+







/*
 * tclCompCmdsSZ.c --
 *
 *	This file contains compilation procedures that compile various Tcl
 *	commands (beginning with the letters 's' through 'z', except for
 *	[upvar] and [variable]) into a sequence of instructions ("bytecodes").
 *	Also includes the operator command compilers.
 *
 * Copyright (c) 1997-1998 Sun Microsystems, Inc.
 * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
 * Copyright (c) 2002 ActiveState Corporation.
 * Copyright (c) 2004-2010 by Donal K. Fellows.
 * Copyright © 1997-1998 Sun Microsystems, Inc.
 * Copyright © 2001 Kevin B. Kenny.  All rights reserved.
 * Copyright © 2002 ActiveState Corporation.
 * Copyright © 2004-2010 Donal K. Fellows.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclCompile.h"
37
38
39
40
41
42
43
44
45


46
47
48
49


50
51
52
53
54
55
56
37
38
39
40
41
42
43


44
45
46
47


48
49
50
51
52
53
54
55
56







-
-
+
+


-
-
+
+







			    Tcl_Parse *parsePtr, int instruction,
			    CompileEnv *envPtr);
static int		CompileUnaryOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, int instruction,
			    CompileEnv *envPtr);
static void		IssueSwitchChainedTests(Tcl_Interp *interp,
			    CompileEnv *envPtr, int mode, int noCase,
			    int numWords, Tcl_Token **bodyToken,
				int *bodyLines, int **bodyNext);
			    Tcl_Size numWords, Tcl_Token **bodyToken,
			    Tcl_Size *bodyLines, Tcl_Size **bodyNext);
static void		IssueSwitchJumpTable(Tcl_Interp *interp,
			    CompileEnv *envPtr, int numWords,
				Tcl_Token **bodyToken, int *bodyLines,
				int **bodyContLines);
			    Tcl_Token **bodyToken, Tcl_Size *bodyLines,
			    Tcl_Size **bodyContLines);
static int		IssueTryClausesInstructions(Tcl_Interp *interp,
			    CompileEnv *envPtr, Tcl_Token *bodyToken,
			    int numHandlers, int *matchCodes,
			    Tcl_Obj **matchClauses, int *resultVarIndices,
			    int *optionVarIndices, Tcl_Token **handlerTokens);
static int		IssueTryClausesFinallyInstructions(Tcl_Interp *interp,
			    CompileEnv *envPtr, Tcl_Token *bodyToken,
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
97
98
99
100
101
102
103

104
105
106
107
108
109
110







-







    TclStoreInt1AtPtr(CurrentOffset(envPtr)-(var),envPtr->codeStart+(var)+1)
#define LOAD(idx) \
    if ((idx)<256) {OP1(LOAD_SCALAR1,(idx));} else {OP4(LOAD_SCALAR4,(idx));}
#define STORE(idx) \
    if ((idx)<256) {OP1(STORE_SCALAR1,(idx));} else {OP4(STORE_SCALAR4,(idx));}
#define INVOKE(name) \
    TclEmitInvoke(envPtr,INST_##name)


/*
 *----------------------------------------------------------------------
 *
 * TclCompileSetCmd --
 *
 *	Procedure called to compile the "set" command.
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
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







-
+
















-
+

















-
+








    if (numWords<2) {
	PushStringLiteral(envPtr, "");
	return TCL_OK;
    }

    /* General case: issue CONCAT1's (by chunks of 254 if needed), folding
       contiguous constants along the way */
     * contiguous constants along the way */

    numArgs = 0;
    folded = NULL;
    wordTokenPtr = TokenAfter(parsePtr->tokenPtr);
    for (i = 1; i < numWords; i++) {
	TclNewObj(obj);
	if (TclWordKnownAtCompileTime(wordTokenPtr, obj)) {
	    if (folded) {
		Tcl_AppendObjToObj(folded, obj);
		Tcl_DecrRefCount(obj);
	    } else {
		folded = obj;
	    }
	} else {
	    Tcl_DecrRefCount(obj);
	    if (folded) {
		size_t len;
		Tcl_Size len;
		const char *bytes = TclGetStringFromObj(folded, &len);

		PushLiteral(envPtr, bytes, len);
		Tcl_DecrRefCount(folded);
		folded = NULL;
		numArgs ++;
	    }
	    CompileWord(envPtr, wordTokenPtr, interp, i);
	    numArgs ++;
	    if (numArgs >= 254) { /* 254 to take care of the possible +1 of "folded" above */
		TclEmitInstInt1(INST_STR_CONCAT1, numArgs, envPtr);
		numArgs = 1;	/* concat pushes 1 obj, the result */
	    }
	}
	wordTokenPtr = TokenAfter(wordTokenPtr);
    }
    if (folded) {
	size_t len;
	Tcl_Size len;
	const char *bytes = TclGetStringFromObj(folded, &len);

	PushLiteral(envPtr, bytes, len);
	Tcl_DecrRefCount(folded);
	folded = NULL;
	numArgs ++;
    }
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
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







-
+







-
-
-
-
-
+
+
+
+
+



-
-
-
-
-
-
-
+
+
+
+
+
+
+







}

int
TclCompileStringIsCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr);
    static const char *const isClasses[] = {
	"alnum",	"alpha",	"ascii",	"control",
	"boolean",	"dict", "digit",	"double",	"entier",
	"false",	"graph",	"integer",	"list",
	"lower",	"print",	"punct",	"space",
	"true",		"upper",	"wideinteger",	"wordchar",
	"xdigit",	NULL
	"boolean",	"dict",		"digit",	"double",
	"entier",	"false",	"graph",	"integer",
	"list",		"lower",	"print",	"punct",
	"space",	"true",		"upper",
	"wideinteger", "wordchar",	"xdigit",	NULL
    };
    enum isClassesEnum {
	STR_IS_ALNUM,	STR_IS_ALPHA,	STR_IS_ASCII,	STR_IS_CONTROL,
	STR_IS_BOOL,	STR_IS_DICT, STR_IS_DIGIT,	STR_IS_DOUBLE,	STR_IS_ENTIER,
	STR_IS_FALSE,	STR_IS_GRAPH,	STR_IS_INT,	STR_IS_LIST,
	STR_IS_LOWER,	STR_IS_PRINT,	STR_IS_PUNCT,	STR_IS_SPACE,
	STR_IS_TRUE,	STR_IS_UPPER,	STR_IS_WIDE,	STR_IS_WORD,
	STR_IS_XDIGIT
    };
    int t, range, allowEmpty = 0, end;
	STR_IS_BOOL,	STR_IS_DICT,	STR_IS_DIGIT,	STR_IS_DOUBLE,
	STR_IS_ENTIER,	STR_IS_FALSE,	STR_IS_GRAPH,	STR_IS_INT,
	STR_IS_LIST,	STR_IS_LOWER,	STR_IS_PRINT,	STR_IS_PUNCT,
	STR_IS_SPACE,	STR_IS_TRUE,	STR_IS_UPPER,
	STR_IS_WIDE,	STR_IS_WORD,	STR_IS_XDIGIT
    } t;
    int range, allowEmpty = 0, end;
    InstStringClassType strClassType;
    Tcl_Obj *isClass;

    if (parsePtr->numWords < 3 || parsePtr->numWords > 6) {
	return TCL_ERROR;
    }
    TclNewObj(isClass);
569
570
571
572
573
574
575
576

577
578

579
580
581
582
583
584
585
568
569
570
571
572
573
574

575
576

577
578
579
580
581
582
583
584







-
+

-
+







     *	1. Character classes
     *	2. Booleans
     *	3. Integers
     *	4. Floats
     *	5. Lists
     */

    CompileWord(envPtr, tokenPtr, interp, parsePtr->numWords-1);
    CompileWord(envPtr, tokenPtr, interp, (int)parsePtr->numWords-1);

    switch ((enum isClassesEnum) t) {
    switch (t) {
    case STR_IS_ALNUM:
	strClassType = STR_CLASS_ALNUM;
	goto compileStrClass;
    case STR_IS_ALPHA:
	strClassType = STR_CLASS_ALPHA;
	goto compileStrClass;
    case STR_IS_ASCII:
676
677
678
679
680
681
682


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







+
+







	    } else {
		OP(	POP);
		PUSH(	"1");
	    }
	    FIXJUMP1(	over);
	    OP(		LNOT);
	    return TCL_OK;
	default:
	    break;
	}
    break;

    case STR_IS_DOUBLE: {
	int satisfied, isEmpty;

	if (allowEmpty) {
741
742
743
744
745
746
747


748
749
750
751
752
753
754
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757







+
+







	    OP(		LE);
	    break;
	case STR_IS_INT:
	case STR_IS_ENTIER:
	    PUSH(	"3");
	    OP(		LE);
	    break;
	default:
	    break;
	}
	FIXJUMP1(	end);
	return TCL_OK;
    case STR_IS_DICT:
	range = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr);
	OP4(		BEGIN_CATCH4, range);
	ExceptionRangeStarts(envPtr, range);
781
782
783
784
785
786
787
788

789
790
791
792
793
794
795
784
785
786
787
788
789
790

791
792
793
794
795
796
797
798







-
+







}

int
TclCompileStringMatchCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr;
	size_t length;
    int i, exactMatch = 0, nocase = 0;
886
887
888
889
890
891
892
893

894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909

910
911
912
913
914
915
916
917
918

919
920
921
922
923
924
925
889
890
891
892
893
894
895

896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911

912
913
914
915
916
917
918
919


920
921
922
923
924
925
926
927







-
+















-
+







-
-
+







	 * something with backslashes). Just push the actual character (not
	 * byte) length.
	 */

	char buf[TCL_INTEGER_SPACE];
	size_t len = Tcl_GetCharLength(objPtr);

	len = sprintf(buf, "%" TCL_Z_MODIFIER "d", len);
	len = snprintf(buf, sizeof(buf), "%" TCL_Z_MODIFIER "u", len);
	PushLiteral(envPtr, buf, len);
    } else {
	SetLineInformation(1);
	CompileTokens(envPtr, tokenPtr, interp);
	TclEmitOpcode(INST_STR_LEN, envPtr);
    }
    TclDecrRefCount(objPtr);
    return TCL_OK;
}

int
TclCompileStringMapCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *mapTokenPtr, *stringTokenPtr;
    Tcl_Obj *mapObj, **objv;
    const char *bytes;
    int len;
    size_t slen;
    Tcl_Size len, slen;

    /*
     * We only handle the case:
     *
     *    string map {foo bar} $thing
     *
     * That is, a literal two-element list (doesn't need to be brace-quoted,
933
934
935
936
937
938
939
940

941
942
943
944
945
946
947
935
936
937
938
939
940
941

942
943
944
945
946
947
948
949







-
+







    mapTokenPtr = TokenAfter(parsePtr->tokenPtr);
    stringTokenPtr = TokenAfter(mapTokenPtr);
    TclNewObj(mapObj);
    Tcl_IncrRefCount(mapObj);
    if (!TclWordKnownAtCompileTime(mapTokenPtr, mapObj)) {
	Tcl_DecrRefCount(mapObj);
	return TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
    } else if (Tcl_ListObjGetElements(NULL, mapObj, &len, &objv) != TCL_OK) {
    } else if (TclListObjGetElements(NULL, mapObj, &len, &objv) != TCL_OK) {
	Tcl_DecrRefCount(mapObj);
	return TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
    } else if (len != 2) {
	Tcl_DecrRefCount(mapObj);
	return TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
    }

1048
1049
1050
1051
1052
1053
1054
1055

1056
1057
1058
1059
1060
1061
1062
1050
1051
1052
1053
1054
1055
1056

1057
1058
1059
1060
1061
1062
1063
1064







-
+







    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds the resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr, *valueTokenPtr;
    int first, last;

    if (parsePtr->numWords < 4 || parsePtr->numWords > 5) {
    if ((int)parsePtr->numWords < 4 || (int)parsePtr->numWords > 5) {
	return TCL_ERROR;
    }

    /* Bytecode to compute/push string argument being replaced */
    valueTokenPtr = TokenAfter(parsePtr->tokenPtr);
    CompileWord(envPtr, valueTokenPtr, interp, 1);

1320
1321
1322
1323
1324
1325
1326
1327

1328
1329
1330
1331
1332
1333
1334
1322
1323
1324
1325
1326
1327
1328

1329
1330
1331
1332
1333
1334
1335
1336







-
+







}

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

    if (parsePtr->numWords != 2) {
1342
1343
1344
1345
1346
1347
1348
1349

1350
1351
1352
1353
1354
1355
1356
1344
1345
1346
1347
1348
1349
1350

1351
1352
1353
1354
1355
1356
1357
1358







-
+







}

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

    if (parsePtr->numWords != 2) {
1364
1365
1366
1367
1368
1369
1370
1371

1372
1373
1374
1375
1376
1377
1378
1366
1367
1368
1369
1370
1371
1372

1373
1374
1375
1376
1377
1378
1379
1380







-
+







}

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

    if (parsePtr->numWords != 2) {
1506
1507
1508
1509
1510
1511
1512
1513

1514
1515

1516
1517
1518
1519


1520
1521
1522
1523
1524
1525
1526
1508
1509
1510
1511
1512
1513
1514

1515
1516

1517
1518
1519
1520

1521
1522
1523
1524
1525
1526
1527
1528
1529







-
+

-
+



-
+
+







    return TCL_OK;
}

void
TclSubstCompile(
    Tcl_Interp *interp,
    const char *bytes,
    size_t numBytes,
    Tcl_Size numBytes,
    int flags,
    int line,
    Tcl_Size line,
    CompileEnv *envPtr)
{
    Tcl_Token *endTokenPtr, *tokenPtr;
    int breakOffset = 0, count = 0, bline = line;
    int breakOffset = 0, count = 0;
    Tcl_Size bline = line;
    Tcl_Parse parse;
    Tcl_InterpState state = NULL;

    TclSubstParse(interp, bytes, numBytes, flags, &parse, &state);
    if (state != NULL) {
	Tcl_ResetResult(interp);
    }
1537
1538
1539
1540
1541
1542
1543
1544

1545
1546
1547
1548
1549
1550
1551
1540
1541
1542
1543
1544
1545
1546

1547
1548
1549
1550
1551
1552
1553
1554







-
+







    if (tokenPtr->type != TCL_TOKEN_TEXT && tokenPtr->type != TCL_TOKEN_BS) {
	PUSH("");
	count++;
    }

    for (endTokenPtr = tokenPtr + parse.numTokens;
	    tokenPtr < endTokenPtr; tokenPtr = TokenAfter(tokenPtr)) {
	size_t length;
	Tcl_Size length;
	int literal, catchRange, breakJump;
	char buf[4] = "";
	JumpFixup startFixup, okFixup, returnFixup, breakFixup;
	JumpFixup continueFixup, otherFixup, endFixup;

	switch (tokenPtr->type) {
	case TCL_TOKEN_TEXT:
1569
1570
1571
1572
1573
1574
1575
1576

1577
1578
1579
1580
1581
1582
1583
1572
1573
1574
1575
1576
1577
1578

1579
1580
1581
1582
1583
1584
1585
1586







-
+







	     * TCL_OK or TCL_ERROR from the substituted variable read; if so,
	     * there is no need to generate elaborate exception-management
	     * code. Note that the first component of TCL_TOKEN_VARIABLE is
	     * always TCL_TOKEN_TEXT...
	     */

	    if (tokenPtr->numComponents > 1) {
		size_t i;
		Tcl_Size i;
		int foundCommand = 0;

		for (i=2 ; i<=tokenPtr->numComponents ; i++) {
		    if (tokenPtr[i].type == TCL_TOKEN_COMMAND) {
			foundCommand = 1;
			break;
		    }
1788
1789
1790
1791
1792
1793
1794
1795

1796
1797

1798
1799
1800
1801
1802

1803
1804
1805
1806
1807
1808
1809
1791
1792
1793
1794
1795
1796
1797

1798
1799

1800
1801
1802
1803
1804

1805
1806
1807
1808
1809
1810
1811
1812







-
+

-
+




-
+








    Tcl_Token *valueTokenPtr;	/* Token for the value to switch on. */
    enum {Switch_Exact, Switch_Glob, Switch_Regexp} mode;
				/* What kind of switch are we doing? */

    Tcl_Token *bodyTokenArray;	/* Array of real pattern list items. */
    Tcl_Token **bodyToken;	/* Array of pointers to pattern list items. */
    int *bodyLines;		/* Array of line numbers for body list
    Tcl_Size *bodyLines;	/* Array of line numbers for body list
				 * items. */
    int **bodyContLines;	/* Array of continuation line info. */
    Tcl_Size **bodyContLines;	/* Array of continuation line info. */
    int noCase;			/* Has the -nocase flag been given? */
    int foundMode = 0;		/* Have we seen a mode flag yet? */
    int i, valueIndex;
    int result = TCL_ERROR;
    int *clNext = envPtr->clNext;
    Tcl_Size *clNext = envPtr->clNext;

    /*
     * Only handle the following versions:
     *   switch         ?--? word {pattern body ...}
     *   switch -exact  ?--? word {pattern body ...}
     *   switch -glob   ?--? word {pattern body ...}
     *   switch -regexp ?--? word {pattern body ...}
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
1958
1959
1960


1961
1962
1963
1964
1965
1966
1967
1936
1937
1938
1939
1940
1941
1942


1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961


1962
1963
1964
1965
1966
1967
1968
1969
1970







-
-
+
+

















-
-
+
+







     * copies of the string from the input token for the generated tokens (it
     * causes a crash during exception handling). When multiple tokens are
     * available at this point, this is pretty easy.
     */

    if (numWords == 1) {
	const char *bytes;
	size_t maxLen, numBytes;
	int bline;		/* TIP #280: line of the pattern/action list,
	Tcl_Size maxLen, numBytes;
	Tcl_Size bline;		/* TIP #280: line of the pattern/action list,
				 * and start of list for when tracking the
				 * location. This list comes immediately after
				 * the value we switch on. */

	if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	    return TCL_ERROR;
	}
	bytes = tokenPtr[1].start;
	numBytes = tokenPtr[1].size;

	/* Allocate enough space to work in. */
	maxLen = TclMaxListLength(bytes, numBytes, NULL);
	if (maxLen < 2)  {
	    return TCL_ERROR;
	}
	bodyTokenArray = (Tcl_Token *)Tcl_Alloc(sizeof(Tcl_Token) * maxLen);
	bodyToken = (Tcl_Token **)Tcl_Alloc(sizeof(Tcl_Token *) * maxLen);
	bodyLines = (int *)Tcl_Alloc(sizeof(int) * maxLen);
	bodyContLines = (int **)Tcl_Alloc(sizeof(int*) * maxLen);
	bodyLines = (Tcl_Size *)Tcl_Alloc(sizeof(Tcl_Size) * maxLen);
	bodyContLines = (Tcl_Size **)Tcl_Alloc(sizeof(Tcl_Size*) * maxLen);

	bline = mapPtr->loc[eclIndex].line[valueIndex+1];
	numWords = 0;

	while (numBytes > 0) {
	    const char *prevBytes = bytes;
	    int literal;
2013
2014
2015
2016
2017
2018
2019
2020
2021


2022
2023
2024
2025
2026
2027
2028
2016
2017
2018
2019
2020
2021
2022


2023
2024
2025
2026
2027
2028
2029
2030
2031







-
-
+
+







	return TCL_ERROR;
    } else {
	/*
	 * Multi-word definition of patterns & actions.
	 */

	bodyToken = (Tcl_Token **)Tcl_Alloc(sizeof(Tcl_Token *) * numWords);
	bodyLines = (int *)Tcl_Alloc(sizeof(int) * numWords);
	bodyContLines = (int **)Tcl_Alloc(sizeof(int*) * numWords);
	bodyLines = (Tcl_Size *)Tcl_Alloc(sizeof(Tcl_Size) * numWords);
	bodyContLines = (Tcl_Size **)Tcl_Alloc(sizeof(Tcl_Size*) * numWords);
	bodyTokenArray = NULL;
	for (i=0 ; i<numWords ; i++) {
	    /*
	     * We only handle the very simplest case. Anything more complex is
	     * a good reason to go to the interpreted case anyway due to
	     * traces, etc.
	     */
2104
2105
2106
2107
2108
2109
2110
2111

2112
2113
2114
2115

2116
2117

2118
2119
2120
2121
2122
2123
2124
2107
2108
2109
2110
2111
2112
2113

2114
2115
2116
2117

2118
2119

2120
2121
2122
2123
2124
2125
2126
2127







-
+



-
+

-
+








static void
IssueSwitchChainedTests(
    Tcl_Interp *interp,		/* Context for compiling script bodies. */
    CompileEnv *envPtr,		/* Holds resulting instructions. */
    int mode,			/* Exact, Glob or Regexp */
    int noCase,			/* Case-insensitivity flag. */
    int numBodyTokens,		/* Number of tokens describing things the
    Tcl_Size numBodyTokens,	/* Number of tokens describing things the
				 * switch can match against and bodies to
				 * execute when the match succeeds. */
    Tcl_Token **bodyToken,	/* Array of pointers to pattern list items. */
    int *bodyLines,		/* Array of line numbers for body list
    Tcl_Size *bodyLines,		/* Array of line numbers for body list
				 * items. */
    int **bodyContLines)	/* Array of continuation line info. */
    Tcl_Size **bodyContLines)	/* Array of continuation line info. */
{
    enum {Switch_Exact, Switch_Glob, Switch_Regexp};
    int foundDefault;		/* Flag to indicate whether a "default" clause
				 * is present. */
    JumpFixup *fixupArray;	/* Array of forward-jump fixup records. */
    unsigned int *fixupTargetArray; /* Array of places for fixups to point at. */
    int fixupCount;		/* Number of places to fix up. */
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
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







-
+

-
+











-
+







IssueSwitchJumpTable(
    Tcl_Interp *interp,		/* Context for compiling script bodies. */
    CompileEnv *envPtr,		/* Holds resulting instructions. */
    int numBodyTokens,		/* Number of tokens describing things the
				 * switch can match against and bodies to
				 * execute when the match succeeds. */
    Tcl_Token **bodyToken,	/* Array of pointers to pattern list items. */
    int *bodyLines,		/* Array of line numbers for body list
    Tcl_Size *bodyLines,		/* Array of line numbers for body list
				 * items. */
    int **bodyContLines)	/* Array of continuation line info. */
    Tcl_Size **bodyContLines)	/* Array of continuation line info. */
{
    JumptableInfo *jtPtr;
    int infoIndex, isNew, *finalFixups, numRealBodies = 0, jumpLocation;
    int mustGenerate, foundDefault, jumpToDefault, i;
    Tcl_DString buffer;
    Tcl_HashEntry *hPtr;

    /*
     * Compile the switch by using a jump table, which is basically a
     * hashtable that maps from literal values to match against to the offset
     * (relative to the INST_JUMP_TABLE instruction) to jump to. The jump
     * table itself is independent of any invokation of the bytecode, and as
     * table itself is independent of any invocation of the bytecode, and as
     * such is stored in an auxData block.
     *
     * Start by allocating the jump table itself, plus some workspace.
     */

    jtPtr = (JumptableInfo *)Tcl_Alloc(sizeof(JumptableInfo));
    Tcl_InitHashTable(&jtPtr->hashTable, TCL_STRING_KEYS);
2423
2424
2425
2426
2427
2428
2429
2430

2431
2432
2433
2434
2435
2436
2437
2426
2427
2428
2429
2430
2431
2432

2433
2434
2435
2436
2437
2438
2439
2440







-
+







		    Tcl_DStringValue(&buffer), &isNew);
	    if (isNew) {
		/*
		 * First time we've encountered this match clause, so it must
		 * point to here.
		 */

		Tcl_SetHashValue(hPtr, CurrentOffset(envPtr) - jumpLocation);
		Tcl_SetHashValue(hPtr, INT2PTR(CurrentOffset(envPtr) - jumpLocation));
	    }
	    Tcl_DStringFree(&buffer);
	} else {
	    /*
	     * This is a default clause, so patch up the fallthrough from the
	     * INST_JUMP_TABLE instruction to here.
	     */
2543
2544
2545
2546
2547
2548
2549
2550

2551
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
2546
2547
2548
2549
2550
2551
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







-
+

-
+









-
+









-
+









-
+


-
+





-
+












-
+






-
+


-
+













-
-
+

-
+







 *	FreeJumptableInfo: releases memory
 *	PrintJumptableInfo: none
 *	DisassembleJumptableInfo: none
 *
 *----------------------------------------------------------------------
 */

static ClientData
static void *
DupJumptableInfo(
    ClientData clientData)
    void *clientData)
{
    JumptableInfo *jtPtr = (JumptableInfo *)clientData;
    JumptableInfo *newJtPtr = (JumptableInfo *)Tcl_Alloc(sizeof(JumptableInfo));
    Tcl_HashEntry *hPtr, *newHPtr;
    Tcl_HashSearch search;
    int isNew;

    Tcl_InitHashTable(&newJtPtr->hashTable, TCL_STRING_KEYS);
    hPtr = Tcl_FirstHashEntry(&jtPtr->hashTable, &search);
    while (hPtr != NULL) {
    for (; hPtr ; hPtr = Tcl_NextHashEntry(&search)) {
	newHPtr = Tcl_CreateHashEntry(&newJtPtr->hashTable,
		Tcl_GetHashKey(&jtPtr->hashTable, hPtr), &isNew);
	Tcl_SetHashValue(newHPtr, Tcl_GetHashValue(hPtr));
    }
    return newJtPtr;
}

static void
FreeJumptableInfo(
    ClientData clientData)
    void *clientData)
{
    JumptableInfo *jtPtr = (JumptableInfo *)clientData;

    Tcl_DeleteHashTable(&jtPtr->hashTable);
    Tcl_Free(jtPtr);
}

static void
PrintJumptableInfo(
    ClientData clientData,
    void *clientData,
    Tcl_Obj *appendObj,
    TCL_UNUSED(ByteCode *),
    unsigned int pcOffset)
    size_t pcOffset)
{
    JumptableInfo *jtPtr = (JumptableInfo *)clientData;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    const char *keyPtr;
    int offset, i = 0;
    size_t offset, i = 0;

    hPtr = Tcl_FirstHashEntry(&jtPtr->hashTable, &search);
    for (; hPtr ; hPtr = Tcl_NextHashEntry(&search)) {
	keyPtr = (const char *)Tcl_GetHashKey(&jtPtr->hashTable, hPtr);
	offset = PTR2INT(Tcl_GetHashValue(hPtr));

	if (i++) {
	    Tcl_AppendToObj(appendObj, ", ", -1);
	    if (i%4==0) {
		Tcl_AppendToObj(appendObj, "\n\t\t", -1);
	    }
	}
	Tcl_AppendPrintfToObj(appendObj, "\"%s\"->pc %d",
	Tcl_AppendPrintfToObj(appendObj, "\"%s\"->pc %" TCL_Z_MODIFIER "u",
		keyPtr, pcOffset + offset);
    }
}

static void
DisassembleJumptableInfo(
    ClientData clientData,
    void *clientData,
    Tcl_Obj *dictObj,
    TCL_UNUSED(ByteCode *),
    TCL_UNUSED(unsigned int))
    TCL_UNUSED(size_t))
{
    JumptableInfo *jtPtr = (JumptableInfo *)clientData;
    Tcl_Obj *mapping;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    const char *keyPtr;
    size_t offset;

    TclNewObj(mapping);
    hPtr = Tcl_FirstHashEntry(&jtPtr->hashTable, &search);
    for (; hPtr ; hPtr = Tcl_NextHashEntry(&search)) {
	keyPtr = (const char *)Tcl_GetHashKey(&jtPtr->hashTable, hPtr);
	offset = PTR2INT(Tcl_GetHashValue(hPtr));
	Tcl_DictObjPut(NULL, mapping, Tcl_NewStringObj(keyPtr, -1),
		Tcl_NewWideIntObj(offset));
	TclDictPut(NULL, mapping, keyPtr, Tcl_NewWideIntObj(offset));
    }
    Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("mapping", -1), mapping);
    TclDictPut(NULL, dictObj, "mapping", mapping);
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileTailcallCmd --
 *
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
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







-
+







-
+



-
+







    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = parsePtr->tokenPtr;
    int i;

    if (parsePtr->numWords < 2 || parsePtr->numWords > 256
    if (parsePtr->numWords < 2 || parsePtr->numWords >= 256
	    || envPtr->procPtr == NULL) {
	return TCL_ERROR;
    }

    /* make room for the nsObjPtr */
    /* TODO: Doesn't this have to be a known value? */
    CompileWord(envPtr, tokenPtr, interp, 0);
    for (i=1 ; i<parsePtr->numWords ; i++) {
    for (i=1 ; i<(int)parsePtr->numWords ; i++) {
	tokenPtr = TokenAfter(tokenPtr);
	CompileWord(envPtr, tokenPtr, interp, i);
    }
    TclEmitInstInt1(	INST_TAILCALL, parsePtr->numWords,	envPtr);
    TclEmitInstInt1(	INST_TAILCALL, (int)parsePtr->numWords,	envPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileThrowCmd --
2703
2704
2705
2706
2707
2708
2709
2710


2711
2712
2713
2714
2715
2716
2717
2705
2706
2707
2708
2709
2710
2711

2712
2713
2714
2715
2716
2717
2718
2719
2720







-
+
+







    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    int numWords = parsePtr->numWords;
    Tcl_Token *codeToken, *msgToken;
    Tcl_Obj *objPtr;
    int codeKnown, codeIsList, codeIsValid, len;
    int codeKnown, codeIsList, codeIsValid;
    Tcl_Size len;

    if (numWords != 3) {
	return TCL_ERROR;
    }
    codeToken = TokenAfter(parsePtr->tokenPtr);
    msgToken = TokenAfter(codeToken);

2727
2728
2729
2730
2731
2732
2733
2734

2735
2736
2737
2738

2739
2740
2741
2742

2743
2744
2745
2746
2747
2748
2749
2730
2731
2732
2733
2734
2735
2736

2737
2738
2739
2740

2741
2742

2743

2744
2745
2746
2747
2748
2749
2750
2751







-
+



-
+

-

-
+







    if (!codeKnown) {
	CompileWord(envPtr, codeToken, interp, 1);
	PUSH(			"-errorcode");
    }
    CompileWord(envPtr, msgToken, interp, 2);

    codeIsList = codeKnown && (TCL_OK ==
	    Tcl_ListObjLength(interp, objPtr, &len));
	    TclListObjLength(interp, objPtr, &len));
    codeIsValid = codeIsList && (len != 0);

    if (codeIsValid) {
	Tcl_Obj *errPtr, *dictPtr;
	Tcl_Obj *dictPtr;

	TclNewLiteralStringObj(errPtr, "-errorcode");
	TclNewObj(dictPtr);
	Tcl_DictObjPut(NULL, dictPtr, errPtr, objPtr);
	TclDictPut(NULL, dictPtr, "-errorcode", objPtr);
	TclEmitPush(TclAddLiteralObj(envPtr, dictPtr, NULL), envPtr);
    }
    TclDecrRefCount(objPtr);

    /*
     * Simpler bytecodes when we detect invalid arguments at compile time.
     */
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
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







-
+















-
+







	memset(matchClauses, 0, sizeof(Tcl_Obj *) * numHandlers);
	matchCodes = (int *)TclStackAlloc(interp, sizeof(int) * numHandlers);
	resultVarIndices = (int *)TclStackAlloc(interp, sizeof(int) * numHandlers);
	optionVarIndices = (int *)TclStackAlloc(interp, sizeof(int) * numHandlers);

	for (i=0 ; i<numHandlers ; i++) {
	    Tcl_Obj *tmpObj, **objv;
	    int objc;
	    Tcl_Size objc;

	    if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
		goto failedToCompile;
	    }
	    if (tokenPtr[1].size == 4
		    && !strncmp(tokenPtr[1].start, "trap", 4)) {
		/*
		 * Parse the list of errorCode words to match against.
		 */

		matchCodes[i] = TCL_ERROR;
		tokenPtr = TokenAfter(tokenPtr);
		TclNewObj(tmpObj);
		Tcl_IncrRefCount(tmpObj);
		if (!TclWordKnownAtCompileTime(tokenPtr, tmpObj)
			|| Tcl_ListObjLength(NULL, tmpObj, &objc) != TCL_OK
			|| TclListObjLength(NULL, tmpObj, &objc) != TCL_OK
			|| (objc == 0)) {
		    TclDecrRefCount(tmpObj);
		    goto failedToCompile;
		}
		Tcl_ListObjReplace(NULL, tmpObj, 0, 0, 0, NULL);
		matchClauses[i] = tmpObj;
	    } else if (tokenPtr[1].size == 2
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
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







-
+





-
+











-
+







	    tokenPtr = TokenAfter(tokenPtr);
	    TclNewObj(tmpObj);
	    Tcl_IncrRefCount(tmpObj);
	    if (!TclWordKnownAtCompileTime(tokenPtr, tmpObj)) {
		TclDecrRefCount(tmpObj);
		goto failedToCompile;
	    }
	    if (Tcl_ListObjGetElements(NULL, tmpObj, &objc, &objv) != TCL_OK
	    if (TclListObjGetElements(NULL, tmpObj, &objc, &objv) != TCL_OK
		    || (objc > 2)) {
		TclDecrRefCount(tmpObj);
		goto failedToCompile;
	    }
	    if (objc > 0) {
		size_t len;
		Tcl_Size len;
		const char *varname = TclGetStringFromObj(objv[0], &len);

		resultVarIndices[i] = LocalScalar(varname, len, envPtr);
		if (resultVarIndices[i] < 0) {
		    TclDecrRefCount(tmpObj);
		    goto failedToCompile;
		}
	    } else {
		resultVarIndices[i] = -1;
	    }
	    if (objc == 2) {
		size_t len;
		Tcl_Size len;
		const char *varname = TclGetStringFromObj(objv[1], &len);

		optionVarIndices[i] = LocalScalar(varname, len, envPtr);
		if (optionVarIndices[i] < 0) {
		    TclDecrRefCount(tmpObj);
		    goto failedToCompile;
		}
2968
2969
2970
2971
2972
2973
2974



2975
2976
2977
2978
2979
2980
2981
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986







+
+
+







	finallyToken = NULL;
    } else if (numWords == 2) {
	if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD || tokenPtr[1].size != 7
		|| strncmp(tokenPtr[1].start, "finally", 7)) {
	    goto failedToCompile;
	}
	finallyToken = TokenAfter(tokenPtr);
	if (finallyToken->type != TCL_TOKEN_SIMPLE_WORD) {
	    goto failedToCompile;
	}
    } else {
	goto failedToCompile;
    }

    /*
     * Issue the bytecode.
     */
3039
3040
3041
3042
3043
3044
3045
3046
3047


3048
3049
3050
3051
3052
3053
3054
3044
3045
3046
3047
3048
3049
3050


3051
3052
3053
3054
3055
3056
3057
3058
3059







-
-
+
+







    Tcl_Obj **matchClauses,
    int *resultVars,
    int *optionVars,
    Tcl_Token **handlerTokens)
{
    DefineLineInformation;	/* TIP #280 */
    int range, resultVar, optionsVar;
    int i, j, len, forwardsNeedFixing = 0, trapZero = 0, afterBody = 0;
    size_t slen;
    int i, j, forwardsNeedFixing = 0, trapZero = 0, afterBody = 0;
    Tcl_Size slen, len;
    int *addrsToFix, *forwardsToFix, notCodeJumpSource, notECJumpSource;
    int *noError;
    char buf[TCL_INTEGER_SPACE];

    resultVar = AnonymousLocal(envPtr);
    optionsVar = AnonymousLocal(envPtr);
    if (resultVar < 0 || optionsVar < 0) {
3108
3109
3110
3111
3112
3113
3114
3115

3116
3117
3118
3119
3120
3121
3122

3123
3124
3125
3126
3127
3128
3129
3113
3114
3115
3116
3117
3118
3119

3120
3121
3122
3123
3124
3125
3126

3127
3128
3129
3130
3131
3132
3133
3134







-
+






-
+








    addrsToFix = (int *)TclStackAlloc(interp, sizeof(int)*numHandlers);
    forwardsToFix = (int *)TclStackAlloc(interp, sizeof(int)*numHandlers);
    noError = (int *)TclStackAlloc(interp, sizeof(int)*numHandlers);

    for (i=0 ; i<numHandlers ; i++) {
	noError[i] = -1;
	sprintf(buf, "%d", matchCodes[i]);
	snprintf(buf, sizeof(buf), "%d", matchCodes[i]);
	OP(				DUP);
	PushLiteral(envPtr, buf, strlen(buf));
	OP(				EQ);
	JUMP4(				JUMP_FALSE, notCodeJumpSource);
	if (matchClauses[i]) {
	    const char *p;
	    Tcl_ListObjLength(NULL, matchClauses[i], &len);
	    TclListObjLength(NULL, matchClauses[i], &len);

	    /*
	     * Match the errorcode according to try/trap rules.
	     */

	    LOAD(			optionsVar);
	    PUSH(			"-errorcode");
3250
3251
3252
3253
3254
3255
3256
3257

3258
3259
3260
3261

3262
3263
3264
3265
3266
3267
3268
3255
3256
3257
3258
3259
3260
3261

3262
3263
3264
3265

3266
3267
3268
3269
3270
3271
3272
3273







-
+



-
+







    Tcl_Obj **matchClauses,
    int *resultVars,
    int *optionVars,
    Tcl_Token **handlerTokens,
    Tcl_Token *finallyToken)	/* Not NULL */
{
    DefineLineInformation;	/* TIP #280 */
    int range, resultVar, optionsVar, i, j, len, forwardsNeedFixing = 0;
    int range, resultVar, optionsVar, i, j, forwardsNeedFixing = 0;
    int trapZero = 0, afterBody = 0, finalOK, finalError, noFinalError;
    int *addrsToFix, *forwardsToFix, notCodeJumpSource, notECJumpSource;
    char buf[TCL_INTEGER_SPACE];
    size_t slen;
    Tcl_Size slen, len;

    resultVar = AnonymousLocal(envPtr);
    optionsVar = AnonymousLocal(envPtr);
    if (resultVar < 0 || optionsVar < 0) {
	return TCL_ERROR;
    }

3321
3322
3323
3324
3325
3326
3327
3328

3329
3330
3331
3332
3333
3334

3335
3336
3337
3338
3339
3340
3341
3326
3327
3328
3329
3330
3331
3332

3333
3334
3335
3336
3337
3338

3339
3340
3341
3342
3343
3344
3345
3346







-
+





-
+







    addrsToFix = (int *)TclStackAlloc(interp, sizeof(int)*numHandlers);
    forwardsToFix = (int *)TclStackAlloc(interp, sizeof(int)*numHandlers);

    for (i=0 ; i<numHandlers ; i++) {
	int noTrapError, trapError;
	const char *p;

	sprintf(buf, "%d", matchCodes[i]);
	snprintf(buf, sizeof(buf), "%d", matchCodes[i]);
	OP(				DUP);
	PushLiteral(envPtr, buf, strlen(buf));
	OP(				EQ);
	JUMP4(				JUMP_FALSE, notCodeJumpSource);
	if (matchClauses[i]) {
	    Tcl_ListObjLength(NULL, matchClauses[i], &len);
	    TclListObjLength(NULL, matchClauses[i], &len);

	    /*
	     * Match the errorcode according to try/trap rules.
	     */

	    LOAD(			optionsVar);
	    PUSH(			"-errorcode");
3625
3626
3627
3628
3629
3630
3631
3632

3633
3634
3635
3636
3637
3638
3639
3630
3631
3632
3633
3634
3635
3636

3637
3638
3639
3640
3641
3642
3643
3644







-
+








    /*
     * Verify that all words - except the first non-option one - are known at
     * compile time so that we can handle them without needing to do a nasty
     * push/rotate. [Bug 3970f54c4e]
     */

    for (i=1,varTokenPtr=parsePtr->tokenPtr ; i<parsePtr->numWords ; i++) {
    for (i=1,varTokenPtr=parsePtr->tokenPtr ; i<(int)parsePtr->numWords ; i++) {
	Tcl_Obj *leadingWord;

	TclNewObj(leadingWord);
	varTokenPtr = TokenAfter(varTokenPtr);
	if (!TclWordKnownAtCompileTime(varTokenPtr, leadingWord)) {
	    TclDecrRefCount(leadingWord);

3664
3665
3666
3667
3668
3669
3670
3671

3672
3673
3674
3675
3676
3677
3678
3669
3670
3671
3672
3673
3674
3675

3676
3677
3678
3679
3680
3681
3682
3683







-
+







		    continue;
		}
	    }
	    return TCL_ERROR;
	}
	if (varCount == 0) {
	    const char *bytes;
	    size_t len;
	    Tcl_Size len;

	    bytes = TclGetStringFromObj(leadingWord, &len);
	    if (i == 1 && len == 11 && !strncmp("-nocomplain", bytes, 11)) {
		flags = 0;
		haveFlags++;
	    } else if (i == (2 - flags) && len == 2 && !strncmp("--", bytes, 2)) {
		haveFlags++;
3689
3690
3691
3692
3693
3694
3695
3696

3697
3698
3699
3700
3701
3702
3703
3694
3695
3696
3697
3698
3699
3700

3701
3702
3703
3704
3705
3706
3707
3708







-
+







     * Issue instructions to unset each of the named variables.
     */

    varTokenPtr = TokenAfter(parsePtr->tokenPtr);
    for (i=0; i<haveFlags;i++) {
	varTokenPtr = TokenAfter(varTokenPtr);
    }
    for (i=1+haveFlags ; i<parsePtr->numWords ; i++) {
    for (i=1+haveFlags ; i<(int)parsePtr->numWords ; i++) {
	/*
	 * Decide if we can use a frame slot for the var/array name or if we
	 * need to emit code to compute and push the name at runtime. We use a
	 * frame slot (entry in the array of local vars) if we are compiling a
	 * procedure body and if the name is simple text that does not include
	 * namespace qualifiers.
	 */
3974
3975
3976
3977
3978
3979
3980
3981

3982
3983
3984
3985
3986

3987
3988
3989
3990
3991
3992
3993
3979
3980
3981
3982
3983
3984
3985

3986
3987
3988
3989
3990

3991
3992
3993
3994
3995
3996
3997
3998







-
+




-
+







    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr);
    int i;

    if (parsePtr->numWords < 2) {
    if ((int)parsePtr->numWords < 2) {
	return TCL_ERROR;
    }

    OP(		NS_CURRENT);
    for (i = 1 ; i < parsePtr->numWords ; i++) {
    for (i = 1 ; i < (int)parsePtr->numWords ; i++) {
	CompileWord(envPtr, tokenPtr, interp, i);
	tokenPtr = TokenAfter(tokenPtr);
    }
    OP4(	LIST, i);
    OP(		YIELD_TO_INVOKE);
    return TCL_OK;
}
4057
4058
4059
4060
4061
4062
4063
4064

4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078

4079
4080
4081
4082
4083
4084
4085
4062
4063
4064
4065
4066
4067
4068

4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082

4083
4084
4085
4086
4087
4088
4089
4090







-
+













-
+







    Tcl_Parse *parsePtr,
    const char *identity,
    int instruction,
    CompileEnv *envPtr)
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = parsePtr->tokenPtr;
    int words;
    Tcl_Size words;

    /* TODO: Consider support for compiling expanded args. */
    for (words=1 ; words<parsePtr->numWords ; words++) {
	tokenPtr = TokenAfter(tokenPtr);
	CompileWord(envPtr, tokenPtr, interp, words);
    }
    if (parsePtr->numWords <= 2) {
	PushLiteral(envPtr, identity, -1);
	words++;
    }
    if (words > 3) {
	/*
	 * Reverse order of arguments to get precise agreement with [expr] in
	 * calcuations, including roundoff errors.
	 * calculations, including roundoff errors.
	 */

	OP4(	REVERSE, words-1);
    }
    while (--words > 1) {
	TclEmitOpcode(instruction, envPtr);
    }
4144
4145
4146
4147
4148
4149
4150
4151

4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167

4168
4169
4170
4171
4172
4173
4174
4149
4150
4151
4152
4153
4154
4155

4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171

4172
4173
4174
4175
4176
4177
4178
4179







-
+















-
+







    int instruction,
    CompileEnv *envPtr)
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr;

    /* TODO: Consider support for compiling expanded args. */
    if (parsePtr->numWords < 3) {
    if ((int)parsePtr->numWords < 3) {
	PUSH("1");
    } else if (parsePtr->numWords == 3) {
	tokenPtr = TokenAfter(parsePtr->tokenPtr);
	CompileWord(envPtr, tokenPtr, interp, 1);
	tokenPtr = TokenAfter(tokenPtr);
	CompileWord(envPtr, tokenPtr, interp, 2);
	TclEmitOpcode(instruction, envPtr);
    } else if (envPtr->procPtr == NULL) {
	/*
	 * No local variable space!
	 */

	return TCL_ERROR;
    } else {
	int tmpIndex = AnonymousLocal(envPtr);
	int words;
	Tcl_Size words;

	tokenPtr = TokenAfter(parsePtr->tokenPtr);
	CompileWord(envPtr, tokenPtr, interp, 1);
	tokenPtr = TokenAfter(tokenPtr);
	CompileWord(envPtr, tokenPtr, interp, 2);
	STORE(tmpIndex);
	TclEmitOpcode(instruction, envPtr);
4296
4297
4298
4299
4300
4301
4302
4303

4304
4305
4306
4307
4308
4309
4310
4301
4302
4303
4304
4305
4306
4307

4308
4309
4310
4311
4312
4313
4314
4315







-
+







    Tcl_Interp *interp,
    Tcl_Parse *parsePtr,
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = parsePtr->tokenPtr;
    int words;
    Tcl_Size words;

    /*
     * This one has its own implementation because the ** operator is the only
     * one with right associativity.
     */

    for (words=1 ; words<parsePtr->numWords ; words++) {
4497
4498
4499
4500
4501
4502
4503
4504

4505
4506
4507
4508
4509
4510
4511
4502
4503
4504
4505
4506
4507
4508

4509
4510
4511
4512
4513
4514
4515
4516







-
+







    Tcl_Interp *interp,
    Tcl_Parse *parsePtr,
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = parsePtr->tokenPtr;
    int words;
    Tcl_Size words;

    /* TODO: Consider support for compiling expanded args. */
    if (parsePtr->numWords == 1) {
	/*
	 * Fallback to direct eval to report syntax error.
	 */

4522
4523
4524
4525
4526
4527
4528
4529

4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549

4550
4551
4552
4553
4554
4555
4556
4527
4528
4529
4530
4531
4532
4533

4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553

4554
4555
4556
4557
4558
4559
4560
4561







-
+



















-
+







    if (words == 3) {
	TclEmitOpcode(INST_SUB, envPtr);
	return TCL_OK;
    }

    /*
     * Reverse order of arguments to get precise agreement with [expr] in
     * calcuations, including roundoff errors.
     * calculations, including roundoff errors.
     */

    TclEmitInstInt4(INST_REVERSE, words-1, envPtr);
    while (--words > 1) {
	TclEmitInstInt4(INST_REVERSE, 2, envPtr);
	TclEmitOpcode(INST_SUB, envPtr);
    }
    return TCL_OK;
}

int
TclCompileDivOpCmd(
    Tcl_Interp *interp,
    Tcl_Parse *parsePtr,
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = parsePtr->tokenPtr;
    int words;
    Tcl_Size words;

    /* TODO: Consider support for compiling expanded args. */
    if (parsePtr->numWords == 1) {
	/*
	 * Fallback to direct eval to report syntax error.
	 */

4566
4567
4568
4569
4570
4571
4572
4573

4574
4575
4576
4577
4578
4579
4580
4571
4572
4573
4574
4575
4576
4577

4578
4579
4580
4581
4582
4583
4584
4585







-
+







    if (words <= 3) {
	TclEmitOpcode(INST_DIV, envPtr);
	return TCL_OK;
    }

    /*
     * Reverse order of arguments to get precise agreement with [expr] in
     * calcuations, including roundoff errors.
     * calculations, including roundoff errors.
     */

    TclEmitInstInt4(INST_REVERSE, words-1, envPtr);
    while (--words > 1) {
	TclEmitInstInt4(INST_REVERSE, 2, envPtr);
	TclEmitOpcode(INST_DIV, envPtr);
    }

Changes to generic/tclCompExpr.c.

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
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







-
+




















-
-
-
-
-
-
-
-








+
+
+
+
+
+
+

-
+



-
+



-
+







+

+
-
+

-
+

-
+

-
+


-
+

-
+

+
+

-
+

-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+



-
+

-
-
-
+
+
+















-
-
+




-
-
+




-
-
+
+

-
+

-
-
+
+
-
-
+






-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
-
-
+






-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+


-
-
+
+
-
-
+














-
-
-
-
+
+
+
+
-
-
+





+







 *
 * While the parse tree is being constructed, the same memory space is used to
 * hold the p.prev field which chains together a stack of incomplete trees
 * awaiting their right operands.
 *
 * The lexeme field is filled in with the lexeme of the operator that is
 * returned by the ParseLexeme() routine. Only lexemes for unary and binary
 * operators get stored in an OpNode. Other lexmes get different treatement.
 * operators get stored in an OpNode. Other lexmes get different treatment.
 *
 * The precedence field provides a place to store the precedence of the
 * operator, so it need not be looked up again and again.
 *
 * The mark field is use to control the traversal of the tree, so that it can
 * be done non-recursively. The mark values are:
 */

enum Marks {
    MARK_LEFT,		/* Next step of traversal is to visit left subtree */
    MARK_RIGHT,		/* Next step of traversal is to visit right subtree */
    MARK_PARENT		/* Next step of traversal is to return to parent */
};

/*
 * The constant field is a boolean flag marking which subexpressions are
 * completely known at compile time, and are eligible for computing then
 * rather than waiting until run time.
 */

/*
 * Each lexeme belongs to one of four categories, which determine its place in
 * the parse tree. We use the two high bits of the (unsigned char) value to
 * store a NODE_TYPE code.
 */

#define NODE_TYPE	0xC0

/*
 * The four category values are LEAF, UNARY, and BINARY, explained below, and
 * "uncategorized", which is used either temporarily, until context determines
 * which of the other three categories is correct, or for lexemes like
 * INVALID, which aren't really lexemes at all, but indicators of a parsing
 * error. Note that the codes must be distinct to distinguish categories, but
 * need not take the form of a bit array.
 */
enum LexemeTypes {
    /*
     * Each lexeme belongs to one of four categories, which determine its place
     * in the parse tree. We use the two high bits of the (unsigned char) value
     * to store a NODE_TYPE code.
     */
    NODE_TYPE = 0xC0,

#define BINARY		0x40	/* This lexeme is a binary operator. An OpNode
    BINARY = 0x40,		/* This lexeme is a binary operator. An OpNode
				 * representing it should go into the parse
				 * tree, and two operands should be parsed for
				 * it in the expression. */
#define UNARY		0x80	/* This lexeme is a unary operator. An OpNode
    UNARY = 0x80,		/* This lexeme is a unary operator. An OpNode
				 * representing it should go into the parse
				 * tree, and one operand should be parsed for
				 * it in the expression. */
#define LEAF		0xC0	/* This lexeme is a leaf operand in the parse
    LEAF = 0xC0			/* This lexeme is a leaf operand in the parse
				 * tree. No OpNode will be placed in the tree
				 * for it. Either a literal value will be
				 * appended to the list of literals in this
				 * expression, or appropriate Tcl_Tokens will
				 * be appended in a Tcl_Parse struct to
				 * represent those leaves that require some
				 * form of substitution. */
};

enum LexemeCodes {
/* Uncategorized lexemes */
    /* Uncategorized lexemes */

#define PLUS		1	/* Ambiguous. Resolves to UNARY_PLUS or
    PLUS = 1,			/* Ambiguous. Resolves to UNARY_PLUS or
				 * BINARY_PLUS according to context. */
#define MINUS		2	/* Ambiguous. Resolves to UNARY_MINUS or
    MINUS = 2,			/* Ambiguous. Resolves to UNARY_MINUS or
				 * BINARY_MINUS according to context. */
#define BAREWORD	3	/* Ambigous. Resolves to BOOLEAN or to
    BAREWORD = 3,		/* Ambiguous. Resolves to BOOL_LIT or to
				 * FUNCTION or a parse error according to
				 * context and value. */
#define INCOMPLETE	4	/* A parse error. Used only when the single
    INCOMPLETE = 4,		/* A parse error. Used only when the single
				 * "=" is encountered.  */
#define INVALID		5	/* A parse error. Used when any punctuation
    INVALID = 5,		/* A parse error. Used when any punctuation
				 * appears that's not a supported operator. */
    COMMENT = 6,		/* Comment. Lasts to end of line or end of
				 * expression, whichever comes first. */

/* Leaf lexemes */
    /* Leaf lexemes */

#define NUMBER		(LEAF | 1)
				/* For literal numbers */
    NUMBER = LEAF | 1,		/* For literal numbers */
#define SCRIPT		(LEAF | 2)
				/* Script substitution; [foo] */
    SCRIPT = LEAF | 2,		/* Script substitution; [foo] */
#define BOOLEAN		(LEAF | BAREWORD)
				/* For literal booleans */
    BOOL_LIT = LEAF | BAREWORD,	/* For literal booleans */
#define BRACED		(LEAF | 4)
				/* Braced string; {foo bar} */
    BRACED = LEAF | 4,		/* Braced string; {foo bar} */
#define VARIABLE	(LEAF | 5)
				/* Variable substitution; $x */
    VARIABLE = LEAF | 5,	/* Variable substitution; $x */
#define QUOTED		(LEAF | 6)
				/* Quoted string; "foo $bar [soom]" */
    QUOTED = LEAF | 6,		/* Quoted string; "foo $bar [soom]" */
#define EMPTY		(LEAF | 7)
				/* Used only for an empty argument list to a
    EMPTY = LEAF | 7,		/* Used only for an empty argument list to a
				 * function. Represents the empty string
				 * within parens in the expression: rand() */

/* Unary operator lexemes */
    /* Unary operator lexemes */

#define UNARY_PLUS	(UNARY | PLUS)
#define UNARY_MINUS	(UNARY | MINUS)
#define FUNCTION	(UNARY | BAREWORD)
    UNARY_PLUS = UNARY | PLUS,
    UNARY_MINUS = UNARY | MINUS,
    FUNCTION = UNARY | BAREWORD,
				/* This is a bit of "creative interpretation"
				 * on the part of the parser. A function call
				 * is parsed into the parse tree according to
				 * the perspective that the function name is a
				 * unary operator and its argument list,
				 * enclosed in parens, is its operand. The
				 * additional requirements not implied
				 * generally by treatment as a unary operator
				 * -- for example, the requirement that the
				 * operand be enclosed in parens -- are hard
				 * coded in the relevant portions of
				 * ParseExpr(). We trade off the need to
				 * include such exceptional handling in the
				 * code against the need we would otherwise
				 * have for more lexeme categories. */
#define START		(UNARY | 4)
				/* This lexeme isn't parsed from the
    START = UNARY | 4,		/* This lexeme isn't parsed from the
				 * expression text at all. It represents the
				 * start of the expression and sits at the
				 * root of the parse tree where it serves as
				 * the start/end point of traversals. */
#define OPEN_PAREN	(UNARY | 5)
				/* Another bit of creative interpretation,
    OPEN_PAREN = UNARY | 5,	/* Another bit of creative interpretation,
				 * where we treat "(" as a unary operator with
				 * the sub-expression between it and its
				 * matching ")" as its operand. See
				 * CLOSE_PAREN below. */
#define NOT		(UNARY | 6)
#define BIT_NOT		(UNARY | 7)
    NOT = UNARY | 6,
    BIT_NOT = UNARY | 7,

/* Binary operator lexemes */
    /* Binary operator lexemes */

#define BINARY_PLUS	(BINARY |  PLUS)
#define BINARY_MINUS	(BINARY |  MINUS)
    BINARY_PLUS = BINARY | PLUS,
    BINARY_MINUS = BINARY | MINUS,
#define COMMA		(BINARY |  3)
				/* The "," operator is a low precedence binary
    COMMA = BINARY | 3,		/* The "," operator is a low precedence binary
				 * operator that separates the arguments in a
				 * function call. The additional constraint
				 * that this operator can only legally appear
				 * at the right places within a function call
				 * argument list are hard coded within
				 * ParseExpr().  */
#define MULT		(BINARY |  4)
#define DIVIDE		(BINARY |  5)
#define MOD		(BINARY |  6)
#define LESS		(BINARY |  7)
#define GREATER		(BINARY |  8)
#define BIT_AND		(BINARY |  9)
#define BIT_XOR		(BINARY | 10)
    MULT = BINARY | 4,
    DIVIDE = BINARY | 5,
    MOD = BINARY | 6,
    LESS = BINARY | 7,
    GREATER = BINARY | 8,
    BIT_AND = BINARY | 9,
    BIT_XOR = BINARY | 10,
#define BIT_OR		(BINARY | 11)
#define QUESTION	(BINARY | 12)
				/* These two lexemes make up the */
    BIT_OR = BINARY | 11,
    QUESTION = BINARY | 12,	/* These two lexemes make up the */
#define COLON		(BINARY | 13)
				/* ternary conditional operator, $x ? $y : $z.
    COLON = BINARY | 13,	/* ternary conditional operator, $x ? $y : $z.
				 * We treat them as two binary operators to
				 * avoid another lexeme category, and code the
				 * additional constraints directly in
				 * ParseExpr(). For instance, the right
				 * operand of a "?" operator must be a ":"
				 * operator. */
#define LEFT_SHIFT	(BINARY | 14)
#define RIGHT_SHIFT	(BINARY | 15)
#define LEQ		(BINARY | 16)
#define GEQ		(BINARY | 17)
#define EQUAL		(BINARY | 18)
#define NEQ		(BINARY | 19)
#define AND		(BINARY | 20)
#define OR		(BINARY | 21)
#define STREQ		(BINARY | 22)
#define STRNEQ		(BINARY | 23)
    LEFT_SHIFT = BINARY | 14,
    RIGHT_SHIFT = BINARY | 15,
    LEQ = BINARY | 16,
    GEQ = BINARY | 17,
    EQUAL = BINARY | 18,
    NEQ = BINARY | 19,
    AND = BINARY | 20,
    OR = BINARY | 21,
    STREQ = BINARY | 22,
    STRNEQ = BINARY | 23,
#define EXPON		(BINARY | 24)
				/* Unlike the other binary operators, EXPON is
    EXPON = BINARY | 24,	/* Unlike the other binary operators, EXPON is
				 * right associative and this distinction is
				 * coded directly in ParseExpr(). */
#define IN_LIST		(BINARY | 25)
#define NOT_IN_LIST	(BINARY | 26)
    IN_LIST = BINARY | 25,
    NOT_IN_LIST = BINARY | 26,
#define CLOSE_PAREN	(BINARY | 27)
				/* By categorizing the CLOSE_PAREN lexeme as a
    CLOSE_PAREN = BINARY | 27,	/* By categorizing the CLOSE_PAREN lexeme as a
				 * BINARY operator, the normal parsing rules
				 * for binary operators assure that a close
				 * paren will not directly follow another
				 * operator, and the machinery already in
				 * place to connect operands to operators
				 * according to precedence performs most of
				 * the work of matching open and close parens
				 * for us. In the end though, a close paren is
				 * not really a binary operator, and some
				 * special coding in ParseExpr() make sure we
				 * never put an actual CLOSE_PAREN node in the
				 * parse tree. The sub-expression between
				 * parens becomes the single argument of the
				 * matching OPEN_PAREN unary operator. */
#define STR_LT		(BINARY | 28)
#define STR_GT		(BINARY | 29)
#define STR_LEQ		(BINARY | 30)
#define STR_GEQ		(BINARY | 31)
    STR_LT = BINARY | 28,
    STR_GT = BINARY | 29,
    STR_LEQ = BINARY | 30,
    STR_GEQ = BINARY | 31,
#define END		(BINARY | 32)
				/* This lexeme represents the end of the
    END = BINARY | 32		/* This lexeme represents the end of the
				 * string being parsed. Treating it as a
				 * binary operator follows the same logic as
				 * the CLOSE_PAREN lexeme and END pairs with
				 * START, in the same way that CLOSE_PAREN
				 * pairs with OPEN_PAREN. */
};

/*
 * When ParseExpr() builds the parse tree it must choose which operands to
 * connect to which operators.  This is done according to operator precedence.
 * The greater an operator's precedence the greater claim it has to link to an
 * available operand.  The Precedence enumeration lists the precedence values
 * used by Tcl expression operators, from lowest to highest claim.  Each
458
459
460
461
462
463
464
465

466
467
468
469
470
471
472
447
448
449
450
451
452
453

454
455
456
457
458
459
460
461







-
+







	INVALID		/* DC4 */,	INVALID		/* NAK */,
	INVALID		/* SYN */,	INVALID		/* ETB */,
	INVALID		/* CAN */,	INVALID		/* EM */,
	INVALID		/* SUB */,	INVALID		/* ESC */,
	INVALID		/* FS */,	INVALID		/* GS */,
	INVALID		/* RS */,	INVALID		/* US */,
	INVALID		/* SPACE */,	0		/* ! or != */,
	QUOTED		/* " */,	INVALID		/* # */,
	QUOTED		/* " */,	0		/* # */,
	VARIABLE	/* $ */,	MOD		/* % */,
	0		/* & or && */,	INVALID		/* ' */,
	OPEN_PAREN	/* ( */,	CLOSE_PAREN	/* ) */,
	0		/* * or ** */,	PLUS		/* + */,
	COMMA		/* , */,	MINUS		/* - */,
	0		/* . */,	DIVIDE		/* / */,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,			/* 0-9 */
505
506
507
508
509
510
511
512

513
514
515
516
517
518

519
520
521

522
523
524
525
526
527
528
494
495
496
497
498
499
500

501
502
503
504
505
506

507
508
509

510
511
512
513
514
515
516
517







-
+





-
+


-
+







 * Declarations for local functions to this file:
 */

static void		CompileExprTree(Tcl_Interp *interp, OpNode *nodes,
			    int index, Tcl_Obj *const **litObjvPtr,
			    Tcl_Obj *const *funcObjv, Tcl_Token *tokenPtr,
			    CompileEnv *envPtr, int optimize);
static void		ConvertTreeToTokens(const char *start, size_t numBytes,
static void		ConvertTreeToTokens(const char *start, Tcl_Size numBytes,
			    OpNode *nodes, Tcl_Token *tokenPtr,
			    Tcl_Parse *parsePtr);
static int		ExecConstantExprTree(Tcl_Interp *interp, OpNode *nodes,
			    int index, Tcl_Obj * const **litObjvPtr);
static int		ParseExpr(Tcl_Interp *interp, const char *start,
			    size_t numBytes, OpNode **opTreePtr,
			    Tcl_Size numBytes, OpNode **opTreePtr,
			    Tcl_Obj *litList, Tcl_Obj *funcList,
			    Tcl_Parse *parsePtr, int parseOnly);
static size_t		ParseLexeme(const char *start, size_t numBytes,
static Tcl_Size		ParseLexeme(const char *start, Tcl_Size numBytes,
			    unsigned char *lexemePtr, Tcl_Obj **literalPtr);

/*
 *----------------------------------------------------------------------
 *
 * ParseExpr --
 *
552
553
554
555
556
557
558
559

560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577

578
579
580
581
582

583
584
585
586
587
588
589
541
542
543
544
545
546
547

548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565

566
567
568
569
570

571
572
573
574
575
576
577
578







-
+

















-
+




-
+







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

static int
ParseExpr(
    Tcl_Interp *interp,		/* Used for error reporting. */
    const char *start,		/* Start of source string to parse. */
    size_t numBytes,		/* Number of bytes in string. */
    Tcl_Size numBytes,		/* Number of bytes in string. */
    OpNode **opTreePtr,		/* Points to space where a pointer to the
				 * allocated OpNode tree should go. */
    Tcl_Obj *litList,		/* List to append literals to. */
    Tcl_Obj *funcList,		/* List to append function names to. */
    Tcl_Parse *parsePtr,	/* Structure to fill with tokens representing
				 * those operands that require run time
				 * substitutions. */
    int parseOnly)		/* A boolean indicating whether the caller's
				 * aim is just a parse, or whether it will go
				 * on to compile the expression. Different
				 * optimizations are appropriate for the two
				 * scenarios. */
{
    OpNode *nodes = NULL;	/* Pointer to the OpNode storage array where
				 * we build the parse tree. */
    unsigned int nodesAvailable = 64; /* Initial size of the storage array. This
				 * value establishes a minimum tree memory
				 * cost of only about 1 kibyte, and is large
				 * cost of only about 1 kilobyte, and is large
				 * enough for most expressions to parse with
				 * no need for array growth and
				 * reallocation. */
    unsigned int nodesUsed = 0;	/* Number of OpNodes filled. */
    size_t scanned = 0;		/* Capture number of byte scanned by parsing
    Tcl_Size scanned = 0;	/* Capture number of byte scanned by parsing
				 * routines. */
    int lastParsed;		/* Stores info about what the lexeme parsed
				 * the previous pass through the parsing loop
				 * was. If it was an operator, lastParsed is
				 * the index of the OpNode for that operator.
				 * If it was not an operator, lastParsed holds
				 * an OperandTypes value encoding what we need
619
620
621
622
623
624
625
626

627
628
629
630
631
632
633
608
609
610
611
612
613
614

615
616
617
618
619
620
621
622







-
+







				 * message where the error location is
				 * reported, this "mark" substring is inserted
				 * into the string being parsed to aid in
				 * pinpointing the location of the syntax
				 * error in the expression. */
    int insertMark = 0;		/* A boolean controlling whether the "mark"
				 * should be inserted. */
    const unsigned limit = 25;	/* Portions of the error message are
    const int limit = 25;	/* Portions of the error message are
				 * constructed out of substrings of the
				 * original expression. In order to keep the
				 * error message readable, we impose this
				 * limit on the substring size we extract. */

    TclParseInit(interp, start, numBytes, parsePtr);

670
671
672
673
674
675
676
677
678
679




680
681
682
683
684
685
686
659
660
661
662
663
664
665



666
667
668
669
670
671
672
673
674
675
676







-
-
-
+
+
+
+







	 */

	if (nodesUsed >= nodesAvailable) {
	    unsigned int size = nodesUsed * 2;
	    OpNode *newPtr = NULL;

	    do {
	      if (size <= UINT_MAX/sizeof(OpNode)) {
		newPtr = (OpNode *)Tcl_AttemptRealloc(nodes, size * sizeof(OpNode));
	      }
		if (size <= UINT_MAX/sizeof(OpNode)) {
		    newPtr = (OpNode *) Tcl_AttemptRealloc(nodes,
			    size * sizeof(OpNode));
		}
	    } while ((newPtr == NULL)
		    && ((size -= (size - nodesUsed) / 2) > nodesUsed));
	    if (newPtr == NULL) {
		TclNewLiteralStringObj(msg,
			"not enough memory to parse expression");
		errCode = "NOMEM";
		goto error;
704
705
706
707
708
709
710




711
712
713
714
715
716
717
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711







+
+
+
+







	 * Use context to categorize the lexemes that are ambiguous.
	 */

	if ((NODE_TYPE & lexeme) == 0) {
	    int b;

	    switch (lexeme) {
	    case COMMENT:
		start += scanned;
		numBytes -= scanned;
		continue;
	    case INVALID:
		msg = Tcl_ObjPrintf("invalid character \"%.*s\"",
			(int)scanned, start);
		errCode = "BADCHAR";
		goto error;
	    case INCOMPLETE:
		msg = Tcl_ObjPrintf("incomplete operator \"%.*s\"",
736
737
738
739
740
741
742
743

744


























745
746
747

748
749
750
751

752
753

754
755
756

757
758
759
760
761
762
763
730
731
732
733
734
735
736

737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766

767
768
769
770

771
772

773
774
775

776
777
778
779
780
781
782
783







-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+



-
+

-
+


-
+







		     * name, and there's no place in the parse tree to store
		     * it, so we keep a separate list of all the function
		     * names we've parsed in the order we found them.
		     */

		    Tcl_ListObjAppendElement(NULL, funcList, literal);
		} else if (Tcl_GetBooleanFromObj(NULL,literal,&b) == TCL_OK) {
		    lexeme = BOOLEAN;
		    lexeme = BOOL_LIT;
		} else {
		    /*
		     * Tricky case: see test expr-62.10
		     */

		    int scanned2 = scanned;
		    do {
			scanned2 += TclParseAllWhiteSpace(
				start + scanned2, numBytes - scanned2);
			scanned2 += ParseLexeme(
				start + scanned2, numBytes - scanned2, &lexeme,
				NULL);
		    } while (lexeme == COMMENT);
		    if (lexeme == OPEN_PAREN) {
			/*
			 * Actually a function call, but with obscuring
			 * comments.  Skip to the start of the parentheses.
			 * Note that we assume that open parentheses are one
			 * byte long.
			 */

			lexeme = FUNCTION;
			Tcl_ListObjAppendElement(NULL, funcList, literal);
			scanned = scanned2 - 1;
			break;
		    }

		    Tcl_DecrRefCount(literal);
		    msg = Tcl_ObjPrintf("invalid bareword \"%.*s%s\"",
			    (scanned < limit) ? (int)scanned : (int)limit - 3, start,
			    (int)((scanned < limit) ? scanned : limit - 3), start,
			    (scanned < limit) ? "" : "...");
		    post = Tcl_ObjPrintf(
			    "should be \"$%.*s%s\" or \"{%.*s%s}\"",
			    (scanned < limit) ? (int)scanned : (int)limit - 3,
			    (int) ((scanned < limit) ? scanned : limit - 3),
			    start, (scanned < limit) ? "" : "...",
			    (scanned < limit) ? (int)scanned : (int)limit - 3,
			    (int) ((scanned < limit) ? scanned : limit - 3),
			    start, (scanned < limit) ? "" : "...");
		    Tcl_AppendPrintfToObj(post, " or \"%.*s%s(...)\" or ...",
			    (scanned < limit) ? (int)scanned : (int)limit - 3,
			    (int) ((scanned < limit) ? scanned : limit - 3),
			    start, (scanned < limit) ? "" : "...");
		    errCode = "BAREWORD";
		    if (start[0] == '0') {
			const char *stop;
			TclParseNumber(NULL, NULL, NULL, start, scanned,
				&stop, TCL_PARSE_NO_WHITESPACE);

836
837
838
839
840
841
842
843

844
845
846
847
848
849
850
851

852
853
854
855
856
857
858
856
857
858
859
860
861
862

863
864
865
866
867
868
869
870

871
872
873
874
875
876
877
878







-
+







-
+







		scanned = 0;
		insertMark = 1;

		/*
		 * Free any literal to avoid a memleak.
		 */

		if ((lexeme == NUMBER) || (lexeme == BOOLEAN)) {
		if ((lexeme == NUMBER) || (lexeme == BOOL_LIT)) {
		    Tcl_DecrRefCount(literal);
		}
		goto error;
	    }

	    switch (lexeme) {
	    case NUMBER:
	    case BOOLEAN:
	    case BOOL_LIT:
		/*
		 * TODO: Consider using a dict or hash to collapse all
		 * duplicate literals into a single representative value.
		 * (Like what is done with [split $s {}]).
		 * Pro:	~75% memory saving on expressions like
		 *	{1+1+1+1+1+.....+1} (Convert "pointer + Tcl_Obj" cost
		 *	to "pointer" cost only)
1442
1443
1444
1445
1446
1447
1448
1449

1450
1451
1452
1453
1454
1455
1456
1462
1463
1464
1465
1466
1467
1468

1469
1470
1471
1472
1473
1474
1475
1476







-
+







	numBytes = parsePtr->end - parsePtr->string;
	Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
		"\n    (parsing expression \"%.*s%s\")",
		(numBytes < limit) ? (int)numBytes : (int)limit - 3,
		parsePtr->string, (numBytes < limit) ? "" : "..."));
	if (errCode) {
	    Tcl_SetErrorCode(interp, "TCL", "PARSE", "EXPR", errCode,
		    subErrCode, NULL);
		    subErrCode, (char *)NULL);
	}
    }

    return TCL_ERROR;
}

/*
1475
1476
1477
1478
1479
1480
1481
1482

1483
1484
1485
1486
1487
1488
1489
1495
1496
1497
1498
1499
1500
1501

1502
1503
1504
1505
1506
1507
1508
1509







-
+







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

static void
ConvertTreeToTokens(
    const char *start,
    size_t numBytes,
    Tcl_Size numBytes,
    OpNode *nodes,
    Tcl_Token *tokenPtr,
    Tcl_Parse *parsePtr)
{
    int subExprTokenIdx = 0;
    OpNode *nodePtr = nodes;
    int next = nodePtr->right;
1693
1694
1695
1696
1697
1698
1699
1700

1701
1702
1703
1704
1705
1706
1707
1713
1714
1715
1716
1717
1718
1719

1720
1721
1722
1723
1724
1725
1726
1727







-
+







	    /*
	     * Here we scan from the string the operator corresponding to
	     * nodePtr->lexeme.
	     */

	    scanned = ParseLexeme(start, numBytes, &lexeme, NULL);

	    switch(nodePtr->lexeme) {
	    switch (nodePtr->lexeme) {
	    case OPEN_PAREN:
	    case COMMA:
	    case COLON:

		/*
		 * No tokens for these lexemes -> nothing to do.
		 */
1769
1770
1771
1772
1773
1774
1775
1776

1777
1778
1779
1780
1781
1782
1783
1789
1790
1791
1792
1793
1794
1795

1796
1797
1798
1799
1800
1801
1802
1803







-
+







		 * All the Tcl_Tokens allocated and filled belong to
		 * this subexpression. The first token is the leading
		 * TCL_TOKEN_SUB_EXPR token, and all the rest (one fewer)
		 * are its components.
		 */

		subExprTokenPtr->numComponents =
			(parsePtr->numTokens - subExprTokenIdx) - 1;
			((int)parsePtr->numTokens - subExprTokenIdx) - 1;

		/*
		 * Finally, as we return up the tree to our parent, pop the
		 * parent subexpression off our subexpression stack, and
		 * fill in the zero numComponents for the operator Tcl_Token.
		 */

1823
1824
1825
1826
1827
1828
1829
1830

1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846

1847
1848
1849
1850
1851
1852
1853
1843
1844
1845
1846
1847
1848
1849

1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865

1866
1867
1868
1869
1870
1871
1872
1873







-
+















-
+







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

int
Tcl_ParseExpr(
    Tcl_Interp *interp,		/* Used for error reporting. */
    const char *start,		/* Start of source string to parse. */
    size_t numBytes,		/* Number of bytes in string. If -1, the
    Tcl_Size numBytes,		/* Number of bytes in string. If -1, the
				 * string consists of all bytes up to the
				 * first null character. */
    Tcl_Parse *parsePtr)	/* Structure to fill with information about
				 * the parsed expression; any previous
				 * information in the structure is ignored. */
{
    int code;
    OpNode *opTree = NULL;	/* Will point to the tree of operators. */
    Tcl_Obj *litList;	/* List to hold the literals. */
    Tcl_Obj *funcList;	/* List to hold the functon names. */
    Tcl_Parse *exprParsePtr = (Tcl_Parse *)TclStackAlloc(interp, sizeof(Tcl_Parse));
				/* Holds the Tcl_Tokens of substitutions. */

    TclNewObj(litList);
    TclNewObj(funcList);
    if (numBytes == TCL_INDEX_NONE) {
    if (numBytes < 0) {
	numBytes = (start ? strlen(start) : 0);
    }

    code = ParseExpr(interp, start, numBytes, &opTree, litList, funcList,
	    exprParsePtr, 1 /* parseOnly */);
    Tcl_DecrRefCount(funcList);
    Tcl_DecrRefCount(litList);
1875
1876
1877
1878
1879
1880
1881
1882

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
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







-
+




-
+


-
+



-
+


-
+













+
+
+
+
+
+
+
+
+
+
+
+
+







 *	Parse a single lexeme from the start of a string, scanning no more
 *	than numBytes bytes.
 *
 * Results:
 *	Returns the number of bytes scanned to produce the lexeme.
 *
 * Side effects:
 *	Code identifying lexeme parsed is writen to *lexemePtr.
 *	Code identifying lexeme parsed is written to *lexemePtr.
 *
 *----------------------------------------------------------------------
 */

static size_t
static Tcl_Size
ParseLexeme(
    const char *start,		/* Start of lexeme to parse. */
    size_t numBytes,		/* Number of bytes in string. */
    Tcl_Size numBytes,		/* Number of bytes in string. */
    unsigned char *lexemePtr,	/* Write code of parsed lexeme to this
				 * storage. */
    Tcl_Obj **literalPtr)	/* Write corresponding literal value to this
				   storage, if non-NULL. */
				 * storage, if non-NULL. */
{
    const char *end;
    Tcl_UniChar ch = 0;
    int ch;
    Tcl_Obj *literal = NULL;
    unsigned char byte;

    if (numBytes == 0) {
	*lexemePtr = END;
	return 0;
    }
    byte = UCHAR(*start);
    if (byte < sizeof(Lexeme) && Lexeme[byte] != 0) {
	*lexemePtr = Lexeme[byte];
	return 1;
    }
    switch (byte) {
    case '#': {
	/*
	 * Scan forward over the comment contents.
	 */
	Tcl_Size size;

	for (size = 0; byte != '\n' && byte != 0 && size < numBytes; size++) {
	    byte = UCHAR(start[size]);
	}
	*lexemePtr = COMMENT;
	return size - (byte == '\n');
    }

    case '*':
	if ((numBytes > 1) && (start[1] == '*')) {
	    *lexemePtr = EXPON;
	    return 2;
	}
	*lexemePtr = MULT;
	return 1;
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100

2101
2102
2103
2104
2105
2106
2107
2108







-


+















-
+








    TclNewObj(literal);
    if (TclParseNumber(NULL, literal, NULL, start, numBytes, &end,
	    TCL_PARSE_NO_WHITESPACE) == TCL_OK) {
	if (end < start + numBytes && !TclIsBareword(*end)) {

	number:
	    TclInitStringRep(literal, start, end-start);
	    *lexemePtr = NUMBER;
	    if (literalPtr) {
		TclInitStringRep(literal, start, end-start);
		*literalPtr = literal;
	    } else {
		Tcl_DecrRefCount(literal);
	    }
	    return (end-start);
	} else {
	    unsigned char lexeme;

	    /*
	     * We have a number followed directly by bareword characters
	     * (alpha, digit, underscore).  Is this a number followed by
	     * bareword syntax error?  Or should we join into one bareword?
	     * Example: Inf + luence + () becomes a valid function call.
	     * [Bug 3401704]
	     */
	    if (TclHasIntRep(literal, &tclDoubleType)) {
	    if (TclHasInternalRep(literal, &tclDoubleType)) {
		const char *p = start;

		while (p < end) {
		    if (!TclIsBareword(*p++)) {
			/*
			 * The number has non-bareword characters, so we
			 * must treat it as a number.
2097
2098
2099
2100
2101
2102
2103
2104

2105
2106
2107
2108

2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125

2126
2127
2128
2129
2130
2131
2132
2130
2131
2132
2133
2134
2135
2136

2137
2138
2139
2140

2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157

2158
2159
2160
2161
2162
2163
2164
2165







-
+



-
+
















-
+







    /*
     * We reject leading underscores in bareword.  No sensible reason why.
     * Might be inspired by reserved identifier rules in C, which of course
     * have no direct relevance here.
     */

    if (!TclIsBareword(*start) || *start == '_') {
	size_t scanned;
	Tcl_Size scanned;
	if (Tcl_UtfCharComplete(start, numBytes)) {
	    scanned = TclUtfToUniChar(start, &ch);
	} else {
	    char utfBytes[4];
	    char utfBytes[8];

	    memcpy(utfBytes, start, numBytes);
	    utfBytes[numBytes] = '\0';
	    scanned = TclUtfToUniChar(utfBytes, &ch);
	}
	*lexemePtr = INVALID;
	Tcl_DecrRefCount(literal);
	return scanned;
    }
    end = start;
    while (numBytes && TclIsBareword(*end)) {
	end += 1;
	numBytes -= 1;
    }
    *lexemePtr = BAREWORD;
    if (literalPtr) {
	Tcl_SetStringObj(literal, start, (int) (end-start));
	Tcl_SetStringObj(literal, start, end-start);
	*literalPtr = literal;
    } else {
	Tcl_DecrRefCount(literal);
    }
    return (end-start);
}

2147
2148
2149
2150
2151
2152
2153
2154

2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175

2176
2177
2178
2179
2180
2181
2182
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







-
+




















-
+







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

void
TclCompileExpr(
    Tcl_Interp *interp,		/* Used for error reporting. */
    const char *script,		/* The source script to compile. */
    size_t numBytes,		/* Number of bytes in script. */
    Tcl_Size numBytes,		/* Number of bytes in script. */
    CompileEnv *envPtr,		/* Holds resulting instructions. */
    int optimize)		/* 0 for one-off expressions. */
{
    OpNode *opTree = NULL;	/* Will point to the tree of operators */
    Tcl_Obj *litList;		/* List to hold the literals */
    Tcl_Obj *funcList;		/* List to hold the functon names*/
    Tcl_Parse *parsePtr = (Tcl_Parse *)TclStackAlloc(interp, sizeof(Tcl_Parse));
				/* Holds the Tcl_Tokens of substitutions */
    int code;

    TclNewObj(litList);
    TclNewObj(funcList);
    code = ParseExpr(interp, script, numBytes, &opTree, litList,
	    funcList, parsePtr, 0 /* parseOnly */);

    if (code == TCL_OK) {
	/*
	 * Valid parse; compile the tree.
	 */

	int objc;
	Tcl_Size objc;
	Tcl_Obj *const *litObjv;
	Tcl_Obj **funcObjv;

	/* TIP #280 : Track Lines within the expression */
	TclAdvanceLines(&envPtr->line, script,
		script + TclParseAllWhiteSpace(script, numBytes));

2298
2299
2300
2301
2302
2303
2304
2305

2306
2307
2308
2309
2310
2311
2312
2331
2332
2333
2334
2335
2336
2337

2338
2339
2340
2341
2342
2343
2344
2345







-
+







	} else if (nodePtr->mark == MARK_RIGHT) {
	    next = nodePtr->right;

	    switch (nodePtr->lexeme) {
	    case FUNCTION: {
		Tcl_DString cmdName;
		const char *p;
		size_t length;
		Tcl_Size length;

		Tcl_DStringInit(&cmdName);
		TclDStringAppendLiteral(&cmdName, "tcl::mathfunc::");
		p = TclGetStringFromObj(*funcObjv, &length);
		funcObjv++;
		Tcl_DStringAppend(&cmdName, p, length);
		TclEmitPush(TclRegisterLiteral(envPtr,
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
2489
2490
2491
2492
2493

2494
2495

2496
2497
2498
2499
2500
2501
2502
2490
2491
2492
2493
2494
2495
2496

2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512

2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525

2526
2527

2528
2529
2530
2531
2532
2533
2534
2535







-
+















-
+












-
+

-
+







	    numWords = 1;	/* No arguments, so just the command */
	    break;
	case OT_LITERAL: {
	    Tcl_Obj *const *litObjv = *litObjvPtr;
	    Tcl_Obj *literal = *litObjv;

	    if (optimize) {
		size_t length;
		Tcl_Size length;
		const char *bytes = TclGetStringFromObj(literal, &length);
		int idx = TclRegisterLiteral(envPtr, bytes, length, 0);
		Tcl_Obj *objPtr = TclFetchLiteral(envPtr, idx);

		if ((objPtr->typePtr == NULL) && (literal->typePtr != NULL)) {
		    /*
		     * Would like to do this:
		     *
		     * lePtr->objPtr = literal;
		     * Tcl_IncrRefCount(literal);
		     * Tcl_DecrRefCount(objPtr);
		     *
		     * However, the design of the "global" and "local"
		     * LiteralTable does not permit the value of lePtr->objPtr
		     * to change. So rather than replace lePtr->objPtr, we do
		     * surgery to transfer our desired intrep into it.
		     * surgery to transfer our desired internalrep into it.
		     */

		    objPtr->typePtr = literal->typePtr;
		    objPtr->internalRep = literal->internalRep;
		    literal->typePtr = NULL;
		}
		TclEmitPush(idx, envPtr);
	    } else {
		/*
		 * When optimize==0, we know the expression is a one-off and
		 * there's nothing to be gained from sharing literals when
		 * they won't live long, and the copies we have already have
		 * an appropriate intrep. In this case, skip literal
		 * an appropriate internalrep. In this case, skip literal
		 * registration that would enable sharing, and use the routine
		 * that preserves intreps.
		 * that preserves internalreps.
		 */

		TclEmitPush(TclAddLiteralObj(envPtr, literal, NULL), envPtr);
	    }
	    (*litObjvPtr)++;
	    break;
	}
2516
2517
2518
2519
2520
2521
2522
2523

2524
2525
2526
2527
2528
2529
2530
2531
2532

2533
2534
2535
2536
2537
2538
2539
2549
2550
2551
2552
2553
2554
2555

2556
2557
2558
2559
2560
2561
2562
2563
2564

2565
2566
2567
2568
2569
2570
2571
2572







-
+








-
+







		    /*
		     * Don't generate a string rep, but if we have one
		     * already, then use it to share via the literal table.
		     */

		    if (TclHasStringRep(objPtr)) {
			Tcl_Obj *tableValue;
			size_t numBytes;
			Tcl_Size numBytes;
			const char *bytes
				= TclGetStringFromObj(objPtr, &numBytes);

			idx = TclRegisterLiteral(envPtr, bytes, numBytes, 0);
			tableValue = TclFetchLiteral(envPtr, idx);
			if ((tableValue->typePtr == NULL) &&
				(objPtr->typePtr != NULL)) {
			    /*
			     * Same intrep surgery as for OT_LITERAL.
			     * Same internalrep surgery as for OT_LITERAL.
			     */

			    tableValue->typePtr = objPtr->typePtr;
			    tableValue->internalRep = objPtr->internalRep;
			    objPtr->typePtr = NULL;
			}
		    } else {
2569
2570
2571
2572
2573
2574
2575
2576

2577
2578
2579
2580
2581
2582
2583
2602
2603
2604
2605
2606
2607
2608

2609
2610
2611
2612
2613
2614
2615
2616







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclSingleOpCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)clientData;
    unsigned char lexeme;
    OpNode nodes[2];
2622
2623
2624
2625
2626
2627
2628
2629

2630
2631
2632
2633
2634
2635
2636
2655
2656
2657
2658
2659
2660
2661

2662
2663
2664
2665
2666
2667
2668
2669







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclSortingOpCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    int code = TCL_OK;

    if (objc < 3) {
2702
2703
2704
2705
2706
2707
2708
2709

2710
2711
2712
2713
2714
2715
2716
2735
2736
2737
2738
2739
2740
2741

2742
2743
2744
2745
2746
2747
2748
2749







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclVariadicOpCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)clientData;
    unsigned char lexeme;
    int code;
2740
2741
2742
2743
2744
2745
2746
2747

2748
2749
2750
2751
2752
2753
2754
2773
2774
2775
2776
2777
2778
2779

2780
2781
2782
2783
2784
2785
2786
2787







-
+







	    nodes[1].lexeme = lexeme;
	    nodes[1].mark = MARK_LEFT;
	    nodes[1].left = OT_LITERAL;
	    nodes[1].right = OT_LITERAL;
	    nodes[1].p.parent = 0;
	} else {
	    if (lexeme == DIVIDE) {
		litObjv[0] = Tcl_NewDoubleObj(1.0);
		TclNewDoubleObj(litObjv[0], 1.0);
	    } else {
		TclNewIntObj(litObjv[0], occdPtr->i.identity);
	    }
	    Tcl_IncrRefCount(litObjv[0]);
	    litObjv[1] = objv[1];
	    nodes[0].lexeme = START;
	    nodes[0].mark = MARK_RIGHT;
2821
2822
2823
2824
2825
2826
2827
2828

2829
2830
2831
2832
2833
2834
2835
2854
2855
2856
2857
2858
2859
2860

2861
2862
2863
2864
2865
2866
2867
2868







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclNoIdentOpCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)clientData;

    if (objc < 2) {

Changes to generic/tclCompile.c.

1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16







-
-
+
+







/*
 * tclCompile.c --
 *
 *	This file contains procedures that compile Tcl commands or parts of
 *	commands (like quoted strings or nested sub-commands) into a sequence
 *	of instructions ("bytecodes").
 *
 * Copyright (c) 1996-1998 Sun Microsystems, Inc.
 * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
 * Copyright © 1996-1998 Sun Microsystems, Inc.
 * Copyright © 2001 Kevin B. Kenny. All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclCompile.h"
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
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







-
-
-
+
+
+


-
-
+
+


-
-
+
+







	/* Make array element cease to exist; element is stktop, array name is
	 * stknext; op1 is 1 for errors on problems, 0 otherwise */
    {"unsetStk",	 2,    -1,        1,	{OPERAND_UINT1}},
	/* Make general variable cease to exist; unparsed variable name is
	 * stktop; op1 is 1 for errors on problems, 0 otherwise */

    {"dictExpand",       1,    -1,        0,    {OPERAND_NONE}},
        /* Probe into a dict and extract it (or a subdict of it) into
         * variables with matched names. Produces list of keys bound as
         * result. Part of [dict with].
	/* Probe into a dict and extract it (or a subdict of it) into
	 * variables with matched names. Produces list of keys bound as
	 * result. Part of [dict with].
	 * Stack:  ... dict path => ... keyList */
    {"dictRecombineStk", 1,    -3,        0,    {OPERAND_NONE}},
        /* Map variable contents back into a dictionary in a variable. Part of
         * [dict with].
	/* Map variable contents back into a dictionary in a variable. Part of
	 * [dict with].
	 * Stack:  ... dictVarName path keyList => ... */
    {"dictRecombineImm", 5,    -2,        1,    {OPERAND_LVT4}},
        /* Map variable contents back into a dictionary in the local variable
         * indicated by the LVT index. Part of [dict with].
	/* Map variable contents back into a dictionary in the local variable
	 * indicated by the LVT index. Part of [dict with].
	 * Stack:  ... path keyList => ... */
    {"dictExists",	 5,	INT_MIN,  1,	{OPERAND_UINT4}},
	/* The top op4 words (min 1) are a key path into the dictionary just
	 * below the keys on the stack, and all those values are replaced by a
	 * boolean indicating whether it is possible to read out a value from
	 * that key-path (like [dict exists]).
	 * Stack:  ... dict key1 ... keyN => ... boolean */
633
634
635
636
637
638
639
640

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














660
661
662
663
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
707
708
709
710
711


712
713
714
715
716


717
718
719
720
721
722
723
724

725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744



745
746
747
748
749


750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767

768
769
770
771
772

773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791

792
793
794
795
796
797
798
799

800

801
802
803
804
805
806


807
808

809
810
811
812
813
814
815
816
817
818
819

820
821
822
823
824
825
826
827
828
829



830
831
832
833
834
835
836
633
634
635
636
637
638
639

640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708

709
710

711
712
713
714
715
716
717

718

719
720
721
722
723
724
725

726
727
728
729
730


731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757




758
759
760
761
762
763


764
765

766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781

782
783
784
785
786

787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805

806
807
808
809
810
811
812
813
814
815

816

817
818
819


820
821


822
823
824
825
826
827
828
829
830
831
832

833
834
835
836
837
838
839
840



841
842
843
844
845
846
847
848
849
850







-
+



















+
+
+
+
+
+
+
+
+
+
+
+
+
+
















-
+

-
+
















-
+

-
+
+




+
-
+
-







-
+
+



-
-
+
+








+
















-
-
-
-
+
+
+



-
-
+
+
-
















-
+




-
+


















-
+








+
-
+
-



-
-
+
+
-
-
+










-
+







-
-
-
+
+
+







	/* Lappend list to array element.
	 * Stack:  ... arrayName elem list => ... listVarContents */
    {"lappendListStk",	 1,	-1,	0,	{OPERAND_NONE}},
	/* Lappend list to general variable.
	 * Stack:  ... varName list => ... listVarContents */

    {"clockRead",	 2,	+1,	1,	{OPERAND_UINT1}},
        /* Read clock out to the stack. Operand is which clock to read
	/* Read clock out to the stack. Operand is which clock to read
	 * 0=clicks, 1=microseconds, 2=milliseconds, 3=seconds.
	 * Stack: ... => ... time */

    {"dictGetDef",	  5,	INT_MIN,   1,	{OPERAND_UINT4}},
	/* The top word is the default, the next op4 words (min 1) are a key
	 * path into the dictionary just below the keys on the stack, and all
	 * those values are replaced by the value read out of that key-path
	 * (like [dict get]) except if there is no such key, when instead the
	 * default is pushed instead.
	 * Stack:  ... dict key1 ... keyN default => ... value */

    {"strlt",		  1,   -1,         0,	{OPERAND_NONE}},
	/* String Less:			push (stknext < stktop) */
    {"strgt",		  1,   -1,         0,	{OPERAND_NONE}},
	/* String Greater:		push (stknext > stktop) */
    {"strle",		  1,   -1,         0,	{OPERAND_NONE}},
	/* String Less or equal:	push (stknext <= stktop) */
    {"strge",		  1,   -1,         0,	{OPERAND_NONE}},
	/* String Greater or equal:	push (stknext >= stktop) */
    {"lreplace4",	  6,   INT_MIN,    2,	{OPERAND_UINT4, OPERAND_UINT1}},
	/* Operands: number of arguments, flags
	 * flags: Combination of TCL_LREPLACE4_* flags
	 * Stack: ... listobj index1 ?index2? new1 ... newN => ... newlistobj
	 * where index2 is present only if TCL_LREPLACE_SINGLE_INDEX is not
	 * set in flags.
	 */

    {"constImm",	  5,   -1,	   1,	{OPERAND_LVT4}},
	/* Create constant. Index into LVT is immediate, value is on stack.
	 * Stack: ... value => ... */
    {"constStk",	  1,   -2,	   0,	{OPERAND_NONE}},
	/* Create constant. Variable name and value on stack.
	 * Stack: ... varName value => ... */

    {NULL, 0, 0, 0, {OPERAND_NONE}}
};

/*
 * Prototypes for procedures defined later in this file:
 */

static void		CleanupByteCode(ByteCode *codePtr);
static ByteCode *	CompileSubstObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    int flags);
static void		DupByteCodeInternalRep(Tcl_Obj *srcPtr,
			    Tcl_Obj *copyPtr);
static unsigned char *	EncodeCmdLocMap(CompileEnv *envPtr,
			    ByteCode *codePtr, unsigned char *startPtr);
static void		EnterCmdExtentData(CompileEnv *envPtr,
			    int cmdNumber, int numSrcBytes, int numCodeBytes);
			    Tcl_Size cmdNumber, Tcl_Size numSrcBytes, Tcl_Size numCodeBytes);
static void		EnterCmdStartData(CompileEnv *envPtr,
			    int cmdNumber, int srcOffset, int codeOffset);
			    Tcl_Size cmdNumber, Tcl_Size srcOffset, Tcl_Size codeOffset);
static void		FreeByteCodeInternalRep(Tcl_Obj *objPtr);
static void		FreeSubstCodeInternalRep(Tcl_Obj *objPtr);
static int		GetCmdLocEncodingSize(CompileEnv *envPtr);
static int		IsCompactibleCompileEnv(CompileEnv *envPtr);
static void		PreventCycle(Tcl_Obj *objPtr, CompileEnv *envPtr);
#ifdef TCL_COMPILE_STATS
static void		RecordByteCodeStats(ByteCode *codePtr);
#endif /* TCL_COMPILE_STATS */
static int		SetByteCodeFromAny(Tcl_Interp *interp,
			    Tcl_Obj *objPtr);
static void		StartExpanding(CompileEnv *envPtr);

/*
 * TIP #280: Helper for building the per-word line information of all compiled
 * commands.
 */
static void		EnterCmdWordData(ExtCmdLoc *eclPtr, int srcOffset,
static void		EnterCmdWordData(ExtCmdLoc *eclPtr, Tcl_Size srcOffset,
			    Tcl_Token *tokenPtr, const char *cmd,
			    int numWords, int line, int *clNext, int **lines,
			    Tcl_Size numWords, Tcl_Size line,
			    Tcl_Size *clNext, Tcl_Size **lines,
			    CompileEnv *envPtr);
static void		ReleaseCmdWordData(ExtCmdLoc *eclPtr);

/*
 * tclByteCodeType provides the standard type management procedures for the
 * The structure below defines the bytecode Tcl object type by means of
 * bytecode type.
 * procedures that can be invoked by generic object code.
 */

const Tcl_ObjType tclByteCodeType = {
    "bytecode",			/* name */
    FreeByteCodeInternalRep,	/* freeIntRepProc */
    DupByteCodeInternalRep,	/* dupIntRepProc */
    NULL,			/* updateStringProc */
    SetByteCodeFromAny		/* setFromAnyProc */
    SetByteCodeFromAny,		/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

/*
 * The structure below defines a bytecode Tcl object type to hold the
 * compiled bytecode for the [subst]itution of Tcl values.
 * substCodeType provides the standard type management procedures for the
 * substcode type, which represents substitution within a Tcl value.
 */

static const Tcl_ObjType substCodeType = {
    "substcode",		/* name */
    FreeSubstCodeInternalRep,	/* freeIntRepProc */
    DupByteCodeInternalRep,	/* dupIntRepProc - shared with bytecode */
    NULL,			/* updateStringProc */
    NULL,			/* setFromAnyProc */
    TCL_OBJTYPE_V0
};
#define SubstFlags(objPtr) (objPtr)->internalRep.twoPtrValue.ptr2

/*
 * Helper macros.
 */

#define TclIncrUInt4AtPtr(ptr, delta) \
    TclStoreInt4AtPtr(TclGetUInt4AtPtr(ptr)+(delta), (ptr))

/*
 *----------------------------------------------------------------------
 *
 * TclSetByteCodeFromAny --
 *
 *	Part of the bytecode Tcl object type implementation. Attempts to
 *	generate an byte code internal form for the Tcl object "objPtr" by
 *	compiling its string representation. This function also takes a hook
 *	procedure that will be invoked to perform any needed post processing
 *	on the compilation results before generating byte codes. interp is
 *	compile the string representation of the objPtr into bytecode.  Accepts
 *	a hook routine that is invoked to perform any needed post-processing on
 *	the compilation results before generating byte codes.  interp is the
 *	compilation context and may not be NULL.
 *
 * Results:
 *	The return value is a standard Tcl object result. If an error occurs
 *	during compilation, an error message is left in the interpreter's
 *	A standard Tcl object result. If an error occurs during compilation, an
 *	error message is left in the interpreter's result.
 *	result.
 *
 * Side effects:
 *	Frees the old internal representation. If no error occurs, then the
 *	compiled code is stored as "objPtr"s bytecode representation. Also, if
 *	debugging, initializes the "tcl_traceCompile" Tcl variable used to
 *	trace compilations.
 *
 *----------------------------------------------------------------------
 */

int
TclSetByteCodeFromAny(
    Tcl_Interp *interp,		/* The interpreter for which the code is being
				 * compiled. Must not be NULL. */
    Tcl_Obj *objPtr,		/* The object to make a ByteCode object. */
    CompileHookProc *hookProc,	/* Procedure to invoke after compilation. */
    ClientData clientData)	/* Hook procedure private data. */
    void *clientData)	/* Hook procedure private data. */
{
    Interp *iPtr = (Interp *) interp;
    CompileEnv compEnv;		/* Compilation environment structure allocated
				 * in frame. */
    size_t length;
    Tcl_Size length;
    int result = TCL_OK;
    const char *stringPtr;
    Proc *procPtr = iPtr->compiledProcPtr;
    ContLineLoc *clLocPtr;

#ifdef TCL_COMPILE_DEBUG
    if (!traceInitialized) {
	if (Tcl_LinkVar(interp, "tcl_traceCompile",
		&tclTraceCompile, TCL_LINK_INT) != TCL_OK) {
	    Tcl_Panic("SetByteCodeFromAny: unable to create link for tcl_traceCompile variable");
	}
	traceInitialized = 1;
    }
#endif

    stringPtr = TclGetStringFromObj(objPtr, &length);

    /*
     * TIP #280: Pick up the CmdFrame in which the BC compiler was invoked and
     * TIP #280: Pick up the CmdFrame in which the BC compiler was invoked, and
     * use to initialize the tracking in the compiler. This information was
     * stored by TclCompEvalObj and ProcCompileProc.
     */

    TclInitCompileEnv(interp, &compEnv, stringPtr, length,
	    iPtr->invokeCmdFramePtr, iPtr->invokeWord);

    /*
     * Make available to the compilation environment any data about invisible
     * Now we check if we have data about invisible continuation lines for the
     * continuation lines for the script.
     * script, and make it available to the compile environment, if so.
     *
     * It is not clear if the script Tcl_Obj* can be free'd while the compiler
     * is using it, leading to the release of the associated ContLineLoc
     * structure as well. To ensure that the latter doesn't happen we set a
     * lock on it. We release this lock in the function TclFreeCompileEnv(),
     * structure as well. To ensure that the latter doesn't happen set a lock
     * on it, which is released in TclFreeCompileEnv().  The "lineCLPtr"
     * found in this file. The "lineCLPtr" hashtable is managed in the file
     * "tclObj.c".
     * hashtable tclObj.c.
     */

    clLocPtr = TclContinuationsGet(objPtr);
    if (clLocPtr) {
	compEnv.clNext = &clLocPtr->loc[0];
    }

    TclCompileScript(interp, stringPtr, length, &compEnv);

    /*
     * Successful compilation. Add a "done" instruction at the end.
     * Compilation succeeded. Add a "done" instruction at the end.
     */

    TclEmitOpcode(INST_DONE, &compEnv);

    /*
     * Check for optimizations!
     *
     * Test if the generated code is free of most hazards; if so, recompile
     * but with generation of INST_START_CMD disabled. This produces somewhat
     * faster code in some cases, and more compact code in more.
     * If the generated code is free of most hazards, recompile with generation
     * of INST_START_CMD disabled to produce code that more compact in many
     * cases, and also sometimes more performant.
     */

    if (Tcl_GetParent(interp) == NULL &&
	    !Tcl_LimitTypeEnabled(interp, TCL_LIMIT_COMMANDS|TCL_LIMIT_TIME)
	    && IsCompactibleCompileEnv(&compEnv)) {
	TclFreeCompileEnv(&compEnv);
	iPtr->compiledProcPtr = procPtr;
852
853
854
855
856
857
858
859

860
861
862
863
864












865
866
867
868

869
870
871
872
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
898
899
900
901



902
903
904

905
906
907
908
909
910
911
912
913
914
915
916

917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932



933
934
935
936
937
938
939
866
867
868
869
870
871
872

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
898
899
900
901
902



903



904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919



920
921
922
923
924

925
926
927
928
929
930
931
932
933
934
935
936

937
938
939
940
941
942
943
944
945
946
947
948
949
950



951
952
953
954
955
956
957
958
959
960







-
+





+
+
+
+
+
+
+
+
+
+
+
+



-
+








-
-
-
+
-
-
-
















-
-
-
+
+
+


-
+











-
+













-
-
-
+
+
+







     */

    if (iPtr->optimizer) {
	(iPtr->optimizer)(&compEnv);
    }

    /*
     * Invoke the compilation hook procedure if one exists.
     * Invoke the compilation hook procedure if there is one.
     */

    if (hookProc) {
	result = hookProc(interp, &compEnv, clientData);
    }

    /*
     * After optimization is all done, check that byte code length limits
     * are not exceeded. Bug [27b3ce2997].
     */
    if ((compEnv.codeNext - compEnv.codeStart) > INT_MAX) {
	/*
	 * Cannot just return TCL_ERROR as callers ignore return value.
	 * TODO - May be use TclCompileSyntaxError here?
	 */
	Tcl_Panic("Maximum byte code length %d exceeded.", INT_MAX);
    }

    /*
     * Change the object into a ByteCode object. Ownership of the literal
     * objects and aux data items is given to the ByteCode object.
     * objects and aux data items passes to the ByteCode object.
     */

#ifdef TCL_COMPILE_DEBUG
    TclVerifyLocalLiteralTable(&compEnv);
#endif /*TCL_COMPILE_DEBUG*/

    if (result == TCL_OK) {
	(void) TclInitByteCodeObj(objPtr, &tclByteCodeType, &compEnv);
#ifdef TCL_COMPILE_DEBUG
	if (tclTraceCompile >= 2) {
	    TclPrintByteCodeObj(interp, objPtr);
	TclDebugPrintByteCodeObj(objPtr);
	    fflush(stdout);
	}
#endif /* TCL_COMPILE_DEBUG */
    }

    TclFreeCompileEnv(&compEnv);
    return result;
}

/*
 *-----------------------------------------------------------------------
 *
 * SetByteCodeFromAny --
 *
 *	Part of the bytecode Tcl object type implementation. Attempts to
 *	generate an byte code internal form for the Tcl object "objPtr" by
 *	compiling its string representation.
 *
 * Results:
 *	The return value is a standard Tcl object result. If an error occurs
 *	during compilation, an error message is left in the interpreter's
 *	result unless "interp" is NULL.
 *	A standard Tcl object result. If an error occurs during compilation and
 *	"interp" is not null, an error message is left in the interpreter's
 *	result.
 *
 * Side effects:
 *	Frees the old internal representation. If no error occurs, then the
 *	Frees the old internal representation. If no error occurs then the
 *	compiled code is stored as "objPtr"s bytecode representation. Also, if
 *	debugging, initializes the "tcl_traceCompile" Tcl variable used to
 *	trace compilations.
 *
 *----------------------------------------------------------------------
 */

static int
SetByteCodeFromAny(
    Tcl_Interp *interp,		/* The interpreter for which the code is being
				 * compiled. Must not be NULL. */
    Tcl_Obj *objPtr)		/* The object to make a ByteCode object. */
    Tcl_Obj *objPtr)		/* The object to compile to bytecode */
{
    if (interp == NULL) {
	return TCL_ERROR;
    }
    return TclSetByteCodeFromAny(interp, objPtr, NULL, NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * DupByteCodeInternalRep --
 *
 *	Part of the bytecode Tcl object type implementation. However, it does
 *	not copy the internal representation of a bytecode Tcl_Obj, but
 *	instead leaves the new object untyped (with a NULL type pointer).
 *	Code will be compiled for the new object only if necessary.
 *	not copy the internal representation of a bytecode Tcl_Obj, instead
 *	assigning NULL to the type pointer of the new object.  Code is compiled
 *	for the new object only if necessary.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
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
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
1024
1025







-
-
-
+
+
+










-
+










-
-
-
+
+
+





-
-
+
+







 *	associated with a bytecode object's internal representation unless its
 *	code is actively being executed.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The bytecode object's internal rep is marked invalid and its code gets
 *	freed unless the code is actively being executed. In that case the
 *	cleanup is delayed until the last execution of the code completes.
 *	The bytecode object's internal rep is invalidated and its code is freed
 *	unless the code is actively being executed, in which case cleanup is
 *	delayed until the last execution of the code completes.
 *
 *----------------------------------------------------------------------
 */

static void
FreeByteCodeInternalRep(
    Tcl_Obj *objPtr)	/* Object whose internal rep to free. */
{
    ByteCode *codePtr;

    ByteCodeGetIntRep(objPtr, &tclByteCodeType, codePtr);
    ByteCodeGetInternalRep(objPtr, &tclByteCodeType, codePtr);
    assert(codePtr != NULL);

    TclReleaseByteCode(codePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TclReleaseByteCode --
 *
 *	This procedure does all the real work of freeing up a bytecode
 *	object's ByteCode structure. It's called only when the structure's
 *	reference count becomes zero.
 *	Does all the real work of freeing up a bytecode object's ByteCode
 *	structure. Called only when the structure's reference count
 *	is zero.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Frees objPtr's bytecode internal representation and sets its type NULL
 *	Also releases its literals and frees its auxiliary data items.
 *	Frees objPtr's bytecode internal representation and sets its type to
 *	NULL.  Also releases its literals and frees its auxiliary data items.
 *
 *----------------------------------------------------------------------
 */

void
TclPreserveByteCode(
    ByteCode *codePtr)
1035
1036
1037
1038
1039
1040
1041
1042

1043
1044
1045
1046
1047
1048
1049
1056
1057
1058
1059
1060
1061
1062

1063
1064
1065
1066
1067
1068
1069
1070







-
+







	ByteCodeStats *statsPtr;
	Tcl_Time destroyTime;
	int lifetimeSec, lifetimeMicroSec, log2;

	statsPtr = &iPtr->stats;

	statsPtr->numByteCodesFreed++;
	statsPtr->currentSrcBytes -= (double) codePtr->numSrcBytes;
	statsPtr->currentSrcBytes -= (double)codePtr->numSrcBytes;
	statsPtr->currentByteCodeBytes -= (double) codePtr->structureSize;

	statsPtr->currentInstBytes -= (double) codePtr->numCodeBytes;
	statsPtr->currentLitBytes -= (double)
		codePtr->numLitObjects * sizeof(Tcl_Obj *);
	statsPtr->currentExceptBytes -= (double)
		codePtr->numExceptRanges * sizeof(ExceptionRange);
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
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







-
-
+
+








-
-
-
+
+
+

-
+







	statsPtr->lifetimeCount[log2]++;
    }
#endif /* TCL_COMPILE_STATS */

    /*
     * A single heap object holds the ByteCode structure and its code, object,
     * command location, and auxiliary data arrays. This means we only need to
     * 1) decrement the ref counts of the LiteralEntry's in its literal array,
     * 2) call the free procs for the auxiliary data items, 3) free the
     * 1) decrement the ref counts of each LiteralEntry in the literal array,
     * 2) call the free procedures for the auxiliary data items, 3) free the
     * localCache if it is unused, and finally 4) free the ByteCode
     * structure's heap object.
     *
     * The case for TCL_BYTECODE_PRECOMPILED (precompiled ByteCodes, like
     * those generated from tbcload) is special, as they doesn't make use of
     * the global literal table. They instead maintain private references to
     * their literals which must be decremented.
     *
     * In order to insure a proper and efficient cleanup of the literal array
     * when it contains non-shared literals [Bug 983660], we also distinguish
     * the case of an interpreter being deleted (signaled by interp == NULL).
     * In order to ensure proper and efficient cleanup of the literal array
     * when it contains non-shared literals [Bug 983660], distinguish the case
     * of an interpreter being deleted, which is signaled by interp == NULL.
     * Also, as the interp deletion will remove the global literal table
     * anyway, we avoid the extra cost of updating it for each literal being
     * anyway, avoid the extra cost of updating it for each literal being
     * released.
     */

    if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {

	objArrayPtr = codePtr->objArrayPtr;
	for (i = 0;  i < numLitObjects;  i++) {
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121



1122
1123
1124
1125
1126
1127
1128

1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150


1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164

1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183




1184
1185
1186
1187
1188
1189
1190
1133
1134
1135
1136
1137
1138
1139



1140
1141
1142
1143
1144
1145
1146
1147
1148

1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169


1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184

1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200




1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211







-
-
-
+
+
+






-
+




















-
-
+
+













-
+















-
-
-
-
+
+
+
+







	if (auxDataPtr->type->freeProc != NULL) {
	    auxDataPtr->type->freeProc(auxDataPtr->clientData);
	}
	auxDataPtr++;
    }

    /*
     * TIP #280. Release the location data associated with this byte code
     * structure, if any. NOTE: The interp we belong to may be gone already,
     * and the data with it.
     * TIP #280. Release the location data associated with this bytecode
     * structure, if any. The associated interp may be gone already, and the
     * data with it.
     *
     * See also tclBasic.c, DeleteInterpProc
     */

    if (iPtr) {
	Tcl_HashEntry *hePtr = Tcl_FindHashEntry(iPtr->lineBCPtr,
		(char *) codePtr);
		codePtr);

	if (hePtr) {
	    ReleaseCmdWordData((ExtCmdLoc *)Tcl_GetHashValue(hePtr));
	    Tcl_DeleteHashEntry(hePtr);
	}
    }

    if (codePtr->localCachePtr && (codePtr->localCachePtr->refCount-- <= 1)) {
	TclFreeLocalCache(interp, codePtr->localCachePtr);
    }

    TclHandleRelease(codePtr->interpHandle);
    Tcl_Free(codePtr);
}

/*
 * ---------------------------------------------------------------------
 *
 * IsCompactibleCompileEnv --
 *
 *	Checks to see if we may apply some basic compaction optimizations to a
 *	piece of bytecode. Idempotent.
 *	Determines whether some basic compaction optimizations may be applied
 *	to a piece of bytecode. Idempotent.
 *
 * ---------------------------------------------------------------------
 */

static int
IsCompactibleCompileEnv(
    CompileEnv *envPtr)
{
    unsigned char *pc;
    int size;

    /*
     * Special: procedures in the '::tcl' namespace (or its children) are
     * considered to be well-behaved and so can have compaction applied even
     * considered to be well-behaved, so compaction can be applied to them even
     * if it would otherwise be invalid.
     */

    if (envPtr->procPtr != NULL && envPtr->procPtr->cmdPtr != NULL
	    && envPtr->procPtr->cmdPtr->nsPtr != NULL) {
	Namespace *nsPtr = envPtr->procPtr->cmdPtr->nsPtr;

	if (strcmp(nsPtr->fullName, "::tcl") == 0
		|| strncmp(nsPtr->fullName, "::tcl::", 7) == 0) {
	    return 1;
	}
    }

    /*
     * Go through and ensure that no operation involved can cause a desired
     * change of bytecode sequence during running. This comes down to ensuring
     * that there are no mapped variables (due to traces) or calls to external
     * commands (traces, [uplevel] trickery). This is actually a very
     * conservative check; it turns down a lot of code that is OK in practice.
     * change of bytecode sequence during its execution. This comes down to
     * ensuring that there are no mapped variables (due to traces) or calls to
     * external commands (traces, [uplevel] trickery). This is actually a very
     * conservative check.  It turns down a lot of code that is OK in practice.
     */

    for (pc = envPtr->codeStart ; pc < envPtr->codeNext ; pc += size) {
	switch (*pc) {
	    /* Invokes */
	case INST_INVOKE_STK1:
	case INST_INVOKE_STK4:
1212
1213
1214
1215
1216
1217
1218
1219
1220


1221
1222
1223
1224
1225
1226
1227
1233
1234
1235
1236
1237
1238
1239


1240
1241
1242
1243
1244
1245
1246
1247
1248







-
-
+
+







}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SubstObj --
 *
 *	This function performs the substitutions specified on the given string
 *	as described in the user documentation for the "subst" Tcl command.
 *	Performs substitutions on the given string as described in the user
 *	documentation for "subst".
 *
 * Results:
 *	A Tcl_Obj* containing the substituted string, or NULL to indicate that
 *	an error occurred.
 *
 * Side effects:
 *	See the user documentation.
1245
1246
1247
1248
1249
1250
1251
1252

1253
1254
1255

1256
1257
1258
1259

1260
1261
1262
1263
1264
1265
1266
1266
1267
1268
1269
1270
1271
1272

1273
1274
1275

1276
1277
1278
1279

1280
1281
1282
1283
1284
1285
1286
1287







-
+


-
+



-
+







}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_NRSubstObj --
 *
 *	Request substitution of a Tcl value by the NR stack.
 *	Adds substitution within the value of objPtr to the NR execution stack.
 *
 * Results:
 *	Returns TCL_OK.
 *	TCL_OK.
 *
 * Side effects:
 *	Compiles objPtr into bytecode that performs the substitutions as
 *	governed by flags and places callbacks on the NR stack to execute
 *	governed by flags, adds a callback to the NR execution stack to execute
 *	the bytecode and store the result in the interp.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_NRSubstObj(
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
1354
1355
1356
1357
1358
1359



1360
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
1387
1388

1389
1390
1391
1392
1393
1394
1395
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393

1394
1395
1396
1397
1398
1399
1400
1401
1402
1403

1404
1405
1406
1407
1408
1409
1410
1411







-
-
+
+


-
+



















-
+











-
+





-
+
















-
-
-
+
-
-
-









-
-
-
+
+
+


















-
+









-
+







}

/*
 *----------------------------------------------------------------------
 *
 * CompileSubstObj --
 *
 *	Compile a Tcl value into ByteCode implementing its substitution, as
 *	governed by flags.
 *	Compiles a value into bytecode that performs substitution within the
 *	value, as governed by flags.
 *
 * Results:
 *	A (ByteCode *) is returned pointing to the resulting ByteCode.
 *	A (ByteCode *) is pointing to the resulting ByteCode.
 *
 * Side effects:
 *	The Tcl_ObjType of objPtr is changed to the "substcode" type, and the
 *	ByteCode and governing flags value are kept in the internal rep for
 *	faster operations the next time CompileSubstObj is called on the same
 *	value.
 *
 *----------------------------------------------------------------------
 */

static ByteCode *
CompileSubstObj(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    int flags)
{
    Interp *iPtr = (Interp *) interp;
    ByteCode *codePtr = NULL;

    ByteCodeGetIntRep(objPtr, &substCodeType, codePtr);
    ByteCodeGetInternalRep(objPtr, &substCodeType, codePtr);

    if (codePtr != NULL) {
	Namespace *nsPtr = iPtr->varFramePtr->nsPtr;

	if (flags != PTR2INT(SubstFlags(objPtr))
		|| ((Interp *) *codePtr->interpHandle != iPtr)
		|| (codePtr->compileEpoch != iPtr->compileEpoch)
		|| (codePtr->nsPtr != nsPtr)
		|| (codePtr->nsEpoch != nsPtr->resolverEpoch)
		|| (codePtr->localCachePtr !=
		iPtr->varFramePtr->localCachePtr)) {
	    Tcl_StoreIntRep(objPtr, &substCodeType, NULL);
	    Tcl_StoreInternalRep(objPtr, &substCodeType, NULL);
	    codePtr = NULL;
	}
    }
    if (codePtr == NULL) {
	CompileEnv compEnv;
	size_t numBytes;
	Tcl_Size numBytes;
	const char *bytes = TclGetStringFromObj(objPtr, &numBytes);

	/* TODO: Check for more TIP 280 */
	TclInitCompileEnv(interp, &compEnv, bytes, numBytes, NULL, 0);

	TclSubstCompile(interp, bytes, numBytes, flags, 1, &compEnv);

	TclEmitOpcode(INST_DONE, &compEnv);
	codePtr = TclInitByteCodeObj(objPtr, &substCodeType, &compEnv);
	TclFreeCompileEnv(&compEnv);

	SubstFlags(objPtr) = INT2PTR(flags);
	if (iPtr->varFramePtr->localCachePtr) {
	    codePtr->localCachePtr = iPtr->varFramePtr->localCachePtr;
	    codePtr->localCachePtr->refCount++;
	}
#ifdef TCL_COMPILE_DEBUG
	if (tclTraceCompile >= 2) {
	    TclPrintByteCodeObj(interp, objPtr);
	TclDebugPrintByteCodeObj(objPtr);
	    fflush(stdout);
	}
#endif /* TCL_COMPILE_DEBUG */
    }
    return codePtr;
}

/*
 *----------------------------------------------------------------------
 *
 * FreeSubstCodeInternalRep --
 *
 *	Part of the substcode Tcl object type implementation. Frees the
 *	storage associated with a substcode object's internal representation
 *	unless its code is actively being executed.
 *	Part of the "substcode" Tcl object type implementation. Frees the
 *	storage associated with the substcode internal representation of a
 *	Tcl_Obj unless its code is actively being executed.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The substcode object's internal rep is marked invalid and its code
 *	gets freed unless the code is actively being executed. In that case
 *	the cleanup is delayed until the last execution of the code completes.
 *
 *----------------------------------------------------------------------
 */

static void
FreeSubstCodeInternalRep(
    Tcl_Obj *objPtr)	/* Object whose internal rep to free. */
{
    ByteCode *codePtr;

    ByteCodeGetIntRep(objPtr, &substCodeType, codePtr);
    ByteCodeGetInternalRep(objPtr, &substCodeType, codePtr);
    assert(codePtr != NULL);

    TclReleaseByteCode(codePtr);
}

static void
ReleaseCmdWordData(
    ExtCmdLoc *eclPtr)
{
    int i;
    Tcl_Size i;

    if (eclPtr->type == TCL_LOCATION_SOURCE) {
	Tcl_DecrRefCount(eclPtr->path);
    }
    for (i=0 ; i<eclPtr->nuloc ; i++) {
	Tcl_Free(eclPtr->loc[i].line);
    }
1606
1607
1608
1609
1610
1611
1612
1613

1614
1615
1616
1617
1618
1619
1620

1621
1622
1623
1624
1625
1626
1627
1622
1623
1624
1625
1626
1627
1628

1629
1630
1631
1632
1633
1634
1635

1636
1637
1638
1639
1640
1641
1642
1643







-
+






-
+







}

/*
 *----------------------------------------------------------------------
 *
 * TclFreeCompileEnv --
 *
 *	Free the storage allocated in a CompileEnv compilation environment
 *	Frees the storage allocated in a CompileEnv compilation environment
 *	structure.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Allocated storage in the CompileEnv structure is freed. Note that its
 *	Allocated storage in the CompileEnv structure is freed, although its
 *	local literal table is not deleted and its literal objects are not
 *	released. In addition, storage referenced by its auxiliary data items
 *	is not freed. This is done so that, when compilation is successful,
 *	"ownership" of these objects and aux data items is handed over to the
 *	corresponding ByteCode structure.
 *
 *----------------------------------------------------------------------
1637
1638
1639
1640
1641
1642
1643
1644

1645
1646
1647
1648
1649
1650
1651
1653
1654
1655
1656
1657
1658
1659

1660
1661
1662
1663
1664
1665
1666
1667







-
+







    }
    if (envPtr->iPtr) {
	/*
	 * We never converted to Bytecode, so free the things we would
	 * have transferred to it.
	 */

	int i;
	Tcl_Size i;
	LiteralEntry *entryPtr = envPtr->literalArrayPtr;
	AuxData *auxDataPtr = envPtr->auxDataArrayPtr;

	for (i = 0;  i < envPtr->literalArrayNext;  i++) {
	    TclReleaseLiteral((Tcl_Interp *)envPtr->iPtr, entryPtr->objPtr);
	    entryPtr++;
	}
1684
1685
1686
1687
1688
1689
1690
1691


1692
1693
1694

1695
1696
1697
1698
1699
1700
1701
1700
1701
1702
1703
1704
1705
1706

1707
1708
1709
1710

1711
1712
1713
1714
1715
1716
1717
1718







-
+
+


-
+







}

/*
 *----------------------------------------------------------------------
 *
 * TclWordKnownAtCompileTime --
 *
 *	Test whether the value of a token is completely known at compile time.
 *	Determines whether the value of a token is completely known at compile
 *	time.
 *
 * Results:
 *	Returns true if the tokenPtr argument points to a word value that is
 *	True if the tokenPtr argument points to a word value that is
 *	completely known at compile time. Generally, values that are known at
 *	compile time can be compiled to their values, while values that cannot
 *	be known until substitution at runtime must be compiled to bytecode
 *	instructions that perform that substitution. For several commands,
 *	whether or not arguments are known at compile time determine whether
 *	it is worthwhile to compile at all.
 *
1764
1765
1766
1767
1768
1769
1770
1771

1772
1773
1774
1775



1776
1777
1778
1779
1780
1781
1782
1783
1781
1782
1783
1784
1785
1786
1787

1788
1789
1790


1791
1792
1793

1794
1795
1796
1797
1798
1799
1800







-
+


-
-
+
+
+
-







}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileScript --
 *
 *	Compile a Tcl script in a string.
 *	Compiles a Tcl script in a string.
 *
 * Results:
 *	The return value is TCL_OK on a successful compilation and TCL_ERROR
 *	on failure. If TCL_ERROR is returned, then the interpreter's result
 *
 *	A standard Tcl result. If an error occurs, an
 *	error message is left in the interpreter's result.
 *	contains an error message.
 *
 * Side effects:
 *	Adds instructions to envPtr to evaluate the script at runtime.
 *
 *----------------------------------------------------------------------
 */

1801
1802
1803
1804
1805
1806
1807
1808

1809
1810
1811
1812
1813
1814
1815
1818
1819
1820
1821
1822
1823
1824

1825
1826
1827
1828
1829
1830
1831
1832







-
+







    Tcl_Interp *interp,
    Tcl_Obj *cmdObj,
    CompileEnv *envPtr)
{
    const char *bytes;
    Command *cmdPtr;
    int cmdLitIdx, extraLiteralFlags = LITERAL_CMD_NAME;
    size_t length;
    Tcl_Size length;

    cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, cmdObj);
    if ((cmdPtr != NULL) && (cmdPtr->flags & CMD_VIA_RESOLVER)) {
	extraLiteralFlags |= LITERAL_UNSHARED;
    }

    bytes = TclGetStringFromObj(cmdObj, &length);
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
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
1958

1959
1960
1961







1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975







-
+



-
+


-
+















-
+
+



-
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+







	}
	TclEmitPush(objIdx, envPtr);
    }

    /*
     * The stack depth during argument expansion can only be managed at
     * runtime, as the number of elements in the expanded lists is not known
     * at compile time. We adjust here the stack depth estimate so that it is
     * at compile time.  Adjust the stack depth estimate here so that it is
     * correct after the command with expanded arguments returns.
     *
     * The end effect of this command's invocation is that all the words of
     * the command are popped from the stack, and the result is pushed: the
     * the command are popped from the stack and the result is pushed: The
     * stack top changes by (1-wordIdx).
     *
     * Note that the estimates are not correct while the command is being
     * The estimates are not correct while the command is being
     * prepared and run, INST_EXPAND_STKTOP is not stack-neutral in general.
     */

    TclEmitInvoke(envPtr, INST_INVOKE_EXPANDED, wordIdx);
    TclCheckStackDepth(depth+1, envPtr);
}

static int
CompileCmdCompileProc(
    Tcl_Interp *interp,
    Tcl_Parse *parsePtr,
    Command *cmdPtr,
    CompileEnv *envPtr)
{
    DefineLineInformation;
    int unwind = 0, incrOffset = -1;
    int unwind = 0;
    Tcl_Size incrOffset = -1;
    int depth = TclGetStackDepth(envPtr);

    /*
     * Emit of the INST_START_CMD instruction is controlled by the value of
     * Emission of the INST_START_CMD instruction is controlled by the value of
     * envPtr->atCmdStart:
     *
     * atCmdStart == 2	: We are not using the INST_START_CMD instruction.
     * atCmdStart == 1	: INST_START_CMD was the last instruction emitted.
     *			: We do not need to emit another.  Instead we
     *			: increment the number of cmds started at it (except
     *			: for the special case at the start of a script.)
     * atCmdStart == 0	: The last instruction was something else.  We need
     *			: to emit INST_START_CMD here.
     * atCmdStart == 2	: Don't use the INST_START_CMD instruction.
     * atCmdStart == 1	: INST_START_CMD was the last instruction emitted,
     *			: so no need to emit another.  Instead
     *			: increment the number of cmds started at it, except
     *			: for the special case at the start of a script.
     * atCmdStart == 0	: The last instruction was something else.
     *			: Emit INST_START_CMD here.
     */

    switch (envPtr->atCmdStart) {
    case 0:
	unwind = tclInstructionTable[INST_START_CMD].numBytes;
	TclEmitInstInt4(INST_START_CMD, 0, envPtr);
	incrOffset = envPtr->codeNext - envPtr->codeStart;
1966
1967
1968
1969
1970
1971
1972
1973

1974
1975
1976
1977
1978
1979
1980
1984
1985
1986
1987
1988
1989
1990

1991
1992
1993
1994
1995
1996
1997
1998







-
+







	/* Nothing to do */
	;
    }

    if (TCL_OK == TclAttemptCompileProc(interp, parsePtr, 1, cmdPtr, envPtr)) {
	if (incrOffset >= 0) {
	    /*
	     * We successfully compiled a command.  Increment the number of
	     * Command compiled succesfully.  Increment the number of
	     * commands that start at the currently active INST_START_CMD.
	     */

	    unsigned char *incrPtr = envPtr->codeStart + incrOffset;
	    unsigned char *startPtr = incrPtr - 5;

	    TclIncrUInt4AtPtr(incrPtr, 1);
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028





2029
2030
2031

2032
2033

2034
2035
2036
2037
2038
2039
2040
2041
2042

2043
2044
2045
2046
2047
2048
2049
2035
2036
2037
2038
2039
2040
2041





2042
2043
2044
2045
2046
2047
2048

2049
2050

2051
2052
2053
2054
2055
2056
2057
2058
2059

2060
2061
2062
2063
2064
2065
2066
2067







-
-
-
-
-
+
+
+
+
+


-
+

-
+








-
+







    Interp *iPtr = (Interp *) interp;
    Tcl_Token *tokenPtr = parsePtr->tokenPtr;
    ExtCmdLoc *eclPtr = envPtr->extCmdMapPtr;
    Tcl_Obj *cmdObj;
    Command *cmdPtr = NULL;
    int code = TCL_ERROR;
    int cmdKnown, expand = -1;
    int *wlines, wlineat;
    int cmdLine = envPtr->line;
    int *clNext = envPtr->clNext;
    int cmdIdx = envPtr->numCommands;
    int startCodeOffset = envPtr->codeNext - envPtr->codeStart;
    Tcl_Size *wlines, wlineat;
    Tcl_Size cmdLine = envPtr->line;
    Tcl_Size *clNext = envPtr->clNext;
    Tcl_Size cmdIdx = envPtr->numCommands;
    Tcl_Size startCodeOffset = envPtr->codeNext - envPtr->codeStart;
    int depth = TclGetStackDepth(envPtr);

    assert (parsePtr->numWords > 0);
    assert ((int)parsePtr->numWords > 0);

    /* Pre-Compile */
    /* Precompile */

    TclNewObj(cmdObj);
    envPtr->numCommands++;
    EnterCmdStartData(envPtr, cmdIdx,
	    parsePtr->commandStart - envPtr->source, startCodeOffset);

    /*
     * TIP #280. Scan the words and compute the extended location information.
     * The map first contain full per-word line information for use by the
     * At first the map first contains full per-word line information for use by the
     * compiler. This is later replaced by a reduced form which signals
     * non-literal words, stored in 'wlines'.
     */

    EnterCmdWordData(eclPtr, parsePtr->commandStart - envPtr->source,
	    parsePtr->tokenPtr, parsePtr->commandStart,
	    parsePtr->numWords, cmdLine,
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
2095
2096

2097
2098
2099

2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112


2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132

2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153




2154
2155
2156
2157
2158


2159
2160
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
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
2087
2088
2089
2090
2091
2092
2093

2094
2095
2096
2097
2098
2099
2100
2101

2102
2103
2104
2105
2106
2107
2108

2109
2110
2111
2112
2113

2114
2115
2116

2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128


2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149

2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274





2275
2276
2277
2278
2279
2280

2281
2282

2283
2284



2285
2286
2287
2288





2289
2290
2291
2292
2293
2294

2295
2296
2297
2298
2299
2300
2301
2302







-
+







-
+






-
+




-
+


-
+











-
-
+
+



















-
+

















-
-
-
-
+
+
+
+



-
-
+
+




+
+
+
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+


-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+


-
-
-
-
+
+
+
+

-
-
-
+
+
+

-
-
-
+
+
+

-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
+

-
+

-
-
-
+
+
+

-
-
-
-
-
+
+
+
+
+

-
+







	    if ((cmdPtr->compileProc == NULL)
		    || (cmdPtr->nsPtr->flags & NS_SUPPRESS_COMPILATION)
		    || (cmdPtr->flags & CMD_HAS_EXEC_TRACES)) {
		cmdPtr = NULL;
	    }
	}
	if (cmdPtr && !(cmdPtr->flags & CMD_COMPILES_EXPANDED)) {
	    expand = ExpandRequested(parsePtr->tokenPtr, parsePtr->numWords);
	    expand = ExpandRequested(parsePtr->tokenPtr, (int)parsePtr->numWords);
	    if (expand) {
		/* We need to expand, but compileProc cannot. */
		cmdPtr = NULL;
	    }
	}
    }

    /* If cmdPtr != NULL, we will try to call cmdPtr->compileProc */
    /* If cmdPtr != NULL, try to call cmdPtr->compileProc */
    if (cmdPtr) {
	code = CompileCmdCompileProc(interp, parsePtr, cmdPtr, envPtr);
    }

    if (code == TCL_ERROR) {
	if (expand < 0) {
	    expand = ExpandRequested(parsePtr->tokenPtr, parsePtr->numWords);
	    expand = ExpandRequested(parsePtr->tokenPtr, (int)parsePtr->numWords);
	}

	if (expand) {
	    CompileExpanded(interp, parsePtr->tokenPtr,
		    cmdKnown ? cmdObj : NULL, parsePtr->numWords, envPtr);
		    cmdKnown ? cmdObj : NULL, (int)parsePtr->numWords, envPtr);
	} else {
	    TclCompileInvocation(interp, parsePtr->tokenPtr,
		    cmdKnown ? cmdObj : NULL, parsePtr->numWords, envPtr);
		    cmdKnown ? cmdObj : NULL, (int)parsePtr->numWords, envPtr);
	}
    }

    Tcl_DecrRefCount(cmdObj);

    TclEmitOpcode(INST_POP, envPtr);
    EnterCmdExtentData(envPtr, cmdIdx,
	    parsePtr->term - parsePtr->commandStart,
	    (envPtr->codeNext-envPtr->codeStart) - startCodeOffset);

    /*
     * TIP #280: Free full form of per-word line data and insert the reduced
     * form now
     * TIP #280: Free the full form of per-word line data and insert the
     * reduced form now.
     */

    envPtr->line = cmdLine;
    envPtr->clNext = clNext;
    Tcl_Free(eclPtr->loc[wlineat].line);
    Tcl_Free(eclPtr->loc[wlineat].next);
    eclPtr->loc[wlineat].line = wlines;
    eclPtr->loc[wlineat].next = NULL;

    TclCheckStackDepth(depth, envPtr);
    return cmdIdx;
}

void
TclCompileScript(
    Tcl_Interp *interp,		/* Used for error and status reporting. Also
				 * serves as context for finding and compiling
				 * commands. May not be NULL. */
    const char *script,		/* The source script to compile. */
    size_t numBytes,		/* Number of bytes in script. If -1, the
    Tcl_Size numBytes,		/* Number of bytes in script. If < 0, the
				 * script consists of all bytes up to the
				 * first null character. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    int lastCmdIdx = -1;	/* Index into envPtr->cmdMapPtr of the last
				 * command this routine compiles into bytecode.
				 * Initial value of -1 indicates this routine
				 * has not yet generated any bytecode. */
    const char *p = script;	/* Where we are in our compile. */
    int depth = TclGetStackDepth(envPtr);
    Interp *iPtr = (Interp *) interp;

    if (envPtr->iPtr == NULL) {
	Tcl_Panic("TclCompileScript() called on uninitialized CompileEnv");
    }
    /*
     * Check depth to avoid overflow of the C execution stack by too many
     * nested calls of TclCompileScript (considering interp recursionlimit).
     * Factor 5/4 (1.25) is used to avoid too mistaken limit recognition
     * during "mixed" evaluation and compilation process (nested eval+compile)
     * and is good enough for default recursionlimit (1000).
     * nested calls of TclCompileScript, considering interp recursionlimit.
     * Use factor 5/4 (1.25) to avoid being too mistaken when recognizing the
     * limit during "mixed" evaluation and compilation process (nested
     * eval+compile) and is good enough for default recursionlimit (1000).
     */
    if (iPtr->numLevels / 5 > iPtr->maxNestingDepth / 4) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
	    "too many nested compilations (infinite loop?)", -1));
	Tcl_SetErrorCode(interp, "TCL", "LIMIT", "STACK", NULL);
		"too many nested compilations (infinite loop?)", -1));
	Tcl_SetErrorCode(interp, "TCL", "LIMIT", "STACK", (char *)NULL);
	TclCompileSyntaxError(interp, envPtr);
	return;
    }

    if (numBytes < 0) {
	numBytes = strlen(script);
    }

    /* Each iteration compiles one command from the script. */

    if (numBytes + 1 > 1) {
      /*
       * Don't use system stack (size of Tcl_Parse is ca. 400 bytes), so
       * many nested compilations (body enclosed in body) can cause abnormal
       * program termination with a stack overflow exception, bug [fec0c17d39].
       */
      Tcl_Parse *parsePtr = (Tcl_Parse *)Tcl_Alloc(sizeof(Tcl_Parse));
    if (numBytes > 0) {
	if (numBytes >= INT_MAX) {
	    /*
	     * Note this gets -errorline as 1. Not worth figuring out which line
	     * crosses the limit to get -errorline for this error case.
	     */
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "Script length %" TCL_SIZE_MODIFIER
		    "d exceeds max permitted length %d.",
		    numBytes, INT_MAX-1));
	    Tcl_SetErrorCode(interp, "TCL", "LIMIT", "SCRIPTLENGTH", (char *)NULL);
	    TclCompileSyntaxError(interp, envPtr);
	    return;
	}
	/*
	 * Don't use system stack (size of Tcl_Parse is ca. 400 bytes), so
	 * many nested compilations (body enclosed in body) can cause abnormal
	 * program termination with a stack overflow exception, bug [fec0c17d39].
	 */
	Tcl_Parse *parsePtr = (Tcl_Parse *)Tcl_Alloc(sizeof(Tcl_Parse));

      do {
	const char *next;
	do {
	    const char *next;

	if (TCL_OK != Tcl_ParseCommand(interp, p, numBytes, 0, parsePtr)) {
	    /*
	     * Compile bytecodes to report the parsePtr error at runtime.
	     */
	    if (TCL_OK != Tcl_ParseCommand(interp, p, numBytes, 0, parsePtr)) {
		/*
		* Compile bytecodes to report the parsePtr error at runtime.
		*/

	    Tcl_LogCommandInfo(interp, script, parsePtr->commandStart,
		    parsePtr->term + 1 - parsePtr->commandStart);
	    TclCompileSyntaxError(interp, envPtr);
	    Tcl_Free(parsePtr);
	    return;
	}
		Tcl_LogCommandInfo(interp, script, parsePtr->commandStart,
			parsePtr->term + 1 - parsePtr->commandStart);
		TclCompileSyntaxError(interp, envPtr);
		Tcl_Free(parsePtr);
		return;
	    }

#ifdef TCL_COMPILE_DEBUG
	/*
	 * If tracing, print a line for each top level command compiled.
	 * TODO: Suppress when numWords == 0 ?
	 */
	    /*
	     * If tracing, print a line for each top level command compiled.
	     * TODO: Suppress when numWords == 0 ?
	     */

	if ((tclTraceCompile >= 1) && (envPtr->procPtr == NULL)) {
	    int commandLength = parsePtr->term - parsePtr->commandStart;
	    fprintf(stdout, "  Compiling: ");
	    TclPrintSource(stdout, parsePtr->commandStart,
		    TclMin(commandLength, 55));
	    fprintf(stdout, "\n");
	}
	    if ((tclTraceCompile >= 1) && (envPtr->procPtr == NULL)) {
		int commandLength = parsePtr->term - parsePtr->commandStart;
		fprintf(stdout, "  Compiling: ");
		TclPrintSource(stdout, parsePtr->commandStart,
			TclMin(commandLength, 55));
		fprintf(stdout, "\n");
	    }
#endif

	/*
	 * TIP #280: Count newlines before the command start.
	 * (See test info-30.33).
	 */
	    /*
	     * TIP #280: Count newlines before the command start.
	     * (See test info-30.33).
	     */

	TclAdvanceLines(&envPtr->line, p, parsePtr->commandStart);
	TclAdvanceContinuations(&envPtr->line, &envPtr->clNext,
		parsePtr->commandStart - envPtr->source);
	    TclAdvanceLines(&envPtr->line, p, parsePtr->commandStart);
	    TclAdvanceContinuations(&envPtr->line, &envPtr->clNext,
		    parsePtr->commandStart - envPtr->source);

	/*
	 * Advance parser to the next command in the script.
	 */
	    /*
	     * Advance parser to the next command in the script.
	     */

	next = parsePtr->commandStart + parsePtr->commandSize;
	numBytes -= next - p;
	p = next;
	    next = parsePtr->commandStart + parsePtr->commandSize;
	    numBytes -= next - p;
	    p = next;

	if (parsePtr->numWords == 0) {
	    /*
	     * The "command" parsed has no words.  In this case we can skip
	     * the rest of the loop body.  With no words, clearly
	     * CompileCommandTokens() has nothing to do.  Since the parser
	     * aggressively sucks up leading comment and white space,
	     * including newlines, parsePtr->commandStart must be pointing at
	     * either the end of script, or a command-terminating semi-colon.
	     * In either case, the TclAdvance*() calls have nothing to do.
	     * Finally, when no words are parsed, no tokens have been
	     * allocated at parsePtr->tokenPtr so there's also nothing for
	     * Tcl_FreeParse() to do.
	     *
	     * The advantage of this shortcut is that CompileCommandTokens()
	     * can be written with an assumption that parsePtr->numWords > 0, with
	     * the implication the CCT() always generates bytecode.
	     */
	    continue;
	}
	    if (parsePtr->numWords == 0) {
		/*
		 * The "command" parsed has no words.  In this case we can skip
		 * the rest of the loop body.  With no words, clearly
		 * CompileCommandTokens() has nothing to do.  Since the parser
		 * aggressively sucks up leading comment and white space,
		 * including newlines, parsePtr->commandStart must be pointing at
		 * either the end of script, or a command-terminating semi-colon.
		 * In either case, the TclAdvance*() calls have nothing to do.
		 * Finally, when no words are parsed, no tokens have been
		 * allocated at parsePtr->tokenPtr so there's also nothing for
		 * Tcl_FreeParse() to do.
		 *
		 * The advantage of this shortcut is that CompileCommandTokens()
		 * can be written with an assumption that (int)parsePtr->numWords > 0, with
		 * the implication the CCT() always generates bytecode.
		 */
		continue;
	    }

	/*
	 * Avoid stack exhaustion by too many nested calls of TclCompileScript
	 * (considering interp recursionlimit).
	 */
	iPtr->numLevels++;
	    /*
	     * Avoid stack exhaustion by too many nested calls of TclCompileScript
	     * (considering interp recursionlimit).
	     */
	    iPtr->numLevels++;

	lastCmdIdx = CompileCommandTokens(interp, parsePtr, envPtr);
	    lastCmdIdx = CompileCommandTokens(interp, parsePtr, envPtr);

	iPtr->numLevels--;
	    iPtr->numLevels--;

	/*
	 * TIP #280: Track lines in the just compiled command.
	 */
	    /*
	     * TIP #280: Track lines in the just compiled command.
	     */

	TclAdvanceLines(&envPtr->line, parsePtr->commandStart, p);
	TclAdvanceContinuations(&envPtr->line, &envPtr->clNext,
		p - envPtr->source);
	Tcl_FreeParse(parsePtr);
      } while (numBytes > 0);
	    TclAdvanceLines(&envPtr->line, parsePtr->commandStart, p);
	    TclAdvanceContinuations(&envPtr->line, &envPtr->clNext,
		    p - envPtr->source);
	    Tcl_FreeParse(parsePtr);
	} while (numBytes > 0);

      Tcl_Free(parsePtr);
	Tcl_Free(parsePtr);
    }

    if (lastCmdIdx == -1) {
	/*
	 * Compiling the script yielded no bytecode.  The script must be all
	 * whitespace, comments, and empty commands.  Such scripts are defined
	 * to successfully produce the empty string result, so we emit the
2289
2290
2291
2292
2293
2294
2295
2296
2297


2298
2299
2300
2301
2302
2303
2304
2324
2325
2326
2327
2328
2329
2330


2331
2332
2333
2334
2335
2336
2337
2338
2339







-
-
+
+







}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileTokens --
 *
 *	Given an array of tokens parsed from a Tcl command (e.g., the tokens
 *	that make up a word) this procedure emits instructions to evaluate the
 *	Given an array of tokens parsed from a Tcl command, e.g. the tokens
 *	that make up a word, emits instructions to evaluate the
 *	tokens and concatenate their values to form a single result value on
 *	the interpreter's runtime evaluation stack.
 *
 * Results:
 *	The return value is a standard Tcl result. If an error occurs, an
 *	error message is left in the interpreter's result.
 *
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
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







-
-
+
+
+










-
+


-
+

-
+







void
TclCompileVarSubst(
    Tcl_Interp *interp,
    Tcl_Token *tokenPtr,
    CompileEnv *envPtr)
{
    const char *p, *name = tokenPtr[1].start;
    size_t i, nameBytes = tokenPtr[1].size;
    int localVar, localVarName = 1;
    Tcl_Size i, nameBytes = tokenPtr[1].size;
    Tcl_Size localVar;
    int localVarName = 1;

    /*
     * Determine how the variable name should be handled: if it contains any
     * namespace qualifiers it is not a local variable (localVarName=-1); if
     * it looks like an array element and the token has a single component, it
     * should not be created here [Bug 569438] (localVarName=0); otherwise,
     * the local variable can safely be created (localVarName=1).
     */

    for (i = 0, p = name;  i < nameBytes;  i++, p++) {
	if ((*p == ':') && (i < nameBytes-1) && (*(p+1) == ':')) {
	if ((p[0] == ':') && (i < nameBytes-1) && (p[1] == ':')) {
	    localVarName = -1;
	    break;
	} else if ((*p == '(')
	} else if ((p[0] == '(')
		&& (tokenPtr->numComponents == 1)
		&& (*(name + nameBytes - 1) == ')')) {
		&& (name[nameBytes - 1] == ')')) {
	    localVarName = 0;
	    break;
	}
    }

    /*
     * Either push the variable's name, or find its index in the array
2380
2381
2382
2383
2384
2385
2386
2387

2388
2389
2390
2391
2392
2393
2394

2395
2396
2397
2398
2399



2400

2401
2402
2403
2404
2405


2406
2407

2408
2409
2410


2411
2412
2413
2414




2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430

2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2416
2417
2418
2419
2420
2421
2422

2423
2424
2425
2426
2427
2428
2429

2430
2431
2432
2433


2434
2435
2436
2437
2438
2439
2440



2441
2442


2443
2444


2445
2446




2447
2448
2449
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
2489
2490




2491
2492
2493
2494



2495
2496
2497
2498
2499

2500
2501
2502
2503
2504
2505


2506
2507
2508
2509
2510
2511
2512
2513
2514







-
+






-
+



-
-
+
+
+

+


-
-
-
+
+
-
-
+

-
-
+
+
-
-
-
-
+
+
+
+















-
+



















-
-
+
+



-
-
-
-
+
+
+
+
-
-
-
+
+



-
+





-
-
+
+







}

void
TclCompileTokens(
    Tcl_Interp *interp,		/* Used for error and status reporting. */
    Tcl_Token *tokenPtr,	/* Pointer to first in an array of tokens to
				 * compile. */
    int count,			/* Number of tokens to consider at tokenPtr.
    size_t count1,		/* Number of tokens to consider at tokenPtr.
				 * Must be at least 1. */
    CompileEnv *envPtr)		/* Holds the resulting instructions. */
{
    Tcl_DString textBuffer;	/* Holds concatenated chars from adjacent
				 * TCL_TOKEN_TEXT, TCL_TOKEN_BS tokens. */
    char buffer[4] = "";
    int i, numObjsToConcat, adjust;
    Tcl_Size i, numObjsToConcat, adjust;
    size_t length;
    unsigned char *entryCodeNext = envPtr->codeNext;
#define NUM_STATIC_POS 20
    int isLiteral, maxNumCL, numCL;
    int *clPosition = NULL;
    int isLiteral;
    Tcl_Size maxNumCL, numCL;
    Tcl_Size *clPosition = NULL;
    int depth = TclGetStackDepth(envPtr);
    int count = count1;

    /*
     * For the handling of continuation lines in literals we first check if
     * this is actually a literal. For if not we can forego the additional
     * processing. Otherwise we pre-allocate a small table to store the
     * If this is actually a literal, handle continuation lines by
     * preallocating a small table to store the locations of any continuation
     * locations of all continuation lines we find in this literal, if any.
     * The table is extended if needed.
     * lines found in this literal.  The table is extended if needed.
     *
     * Note: Different to the equivalent code in function 'TclSubstTokens()'
     * (see file "tclParse.c") we do not seem to need the 'adjust' variable.
     * Note: In contrast with the analagous code in 'TclSubstTokens()' the
     * 'adjust' variable seems unneeded here.  The code which merges
     * We also do not seem to need code which merges continuation line
     * information of multiple words which concat'd at runtime. Either that or
     * I have not managed to find a test case for these two possibilities yet.
     * It might be a difference between compile- versus run-time processing.
     * continuation line information of multiple words which concat'd at
     * runtime also seems unneeded. Either that or I have not managed to find a
     * test case for these two possibilities yet.  It might be a difference
     * between compile- versus run-time processing.
     */

    numCL = 0;
    maxNumCL = 0;
    isLiteral = 1;
    for (i=0 ; i < count; i++) {
	if ((tokenPtr[i].type != TCL_TOKEN_TEXT)
		&& (tokenPtr[i].type != TCL_TOKEN_BS)) {
	    isLiteral = 0;
	    break;
	}
    }

    if (isLiteral) {
	maxNumCL = NUM_STATIC_POS;
	clPosition = (int *)Tcl_Alloc(maxNumCL * sizeof(int));
	clPosition = (Tcl_Size *)Tcl_Alloc(maxNumCL * sizeof(Tcl_Size));
    }

    adjust = 0;
    Tcl_DStringInit(&textBuffer);
    numObjsToConcat = 0;
    for ( ;  count > 0;  count--, tokenPtr++) {
	switch (tokenPtr->type) {
	case TCL_TOKEN_TEXT:
	    TclDStringAppendToken(&textBuffer, tokenPtr);
	    TclAdvanceLines(&envPtr->line, tokenPtr->start,
		    tokenPtr->start + tokenPtr->size);
	    break;

	case TCL_TOKEN_BS:
	    length = TclParseBackslash(tokenPtr->start, tokenPtr->size,
		    NULL, buffer);
	    Tcl_DStringAppend(&textBuffer, buffer, length);

	    /*
	     * If the backslash sequence we found is in a literal, and
	     * represented a continuation line, we compute and store its
	     * If the identified backslash sequence is in a literal and
	     * represented a continuation line, compute and store its
	     * location (as char offset to the beginning of the _result_
	     * script). We may have to extend the table of locations.
	     *
	     * Note that the continuation line information is relevant even if
	     * the word we are processing is not a literal, as it can affect
	     * nested commands. See the branch for TCL_TOKEN_COMMAND below,
	     * where the adjustment we are tracking here is taken into
	     * The continuation line information is relevant even if the word
	     * being processed is not a literal, as it can affect nested
	     * commands. See the branch below for TCL_TOKEN_COMMAND, where the
	     * adjustment being tracked here is taken into account. The good
	     * account. The good thing is that we do not need a table of
	     * everything, just the number of lines we have to add as
	     * correction.
	     * thing is a table of everything is not needed, just the number of
	     * lines to add as correction.
	     */

	    if ((length == 1) && (buffer[0] == ' ') &&
		(tokenPtr->start[1] == '\n')) {
		    (tokenPtr->start[1] == '\n')) {
		if (isLiteral) {
		    int clPos = Tcl_DStringLength(&textBuffer);

		    if (numCL >= maxNumCL) {
			maxNumCL *= 2;
			clPosition = (int *)Tcl_Realloc(clPosition,
                                maxNumCL * sizeof(int));
			clPosition = (Tcl_Size *)Tcl_Realloc(clPosition,
				maxNumCL * sizeof(Tcl_Size));
		    }
		    clPosition[numCL] = clPos;
		    numCL ++;
		}
		adjust++;
	    }
	    break;
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
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







-
-
-
-
+
+
+
+


-
+













-
+



+
+


-
+






-
-
-
+
+
+













-
-
-
+
+
+
-


-
+












-
+
-
-
+






+








/*
 *----------------------------------------------------------------------
 *
 * TclCompileCmdWord --
 *
 *	Given an array of parse tokens for a word containing one or more Tcl
 *	commands, emit inline instructions to execute them. This procedure
 *	differs from TclCompileTokens in that a simple word such as a loop
 *	body enclosed in braces is not just pushed as a string, but is itself
 *	parsed into tokens and compiled.
 *	commands, emits inline instructions to execute them.  In contrast with
 *	TclCompileTokens, a simple word such as a loop body enclosed in braces
 *	is not just pushed as a string, but is itself parsed into tokens and
 *	compiled.
 *
 * Results:
 *	The return value is a standard Tcl result. If an error occurs, an
 *	A standard Tcl result. If an error occurs, an
 *	error message is left in the interpreter's result.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the tokens at runtime.
 *
 *----------------------------------------------------------------------
 */

void
TclCompileCmdWord(
    Tcl_Interp *interp,		/* Used for error and status reporting. */
    Tcl_Token *tokenPtr,	/* Pointer to first in an array of tokens for
				 * a command word to compile inline. */
    int count,			/* Number of tokens to consider at tokenPtr.
    size_t count1,			/* Number of tokens to consider at tokenPtr.
				 * Must be at least 1. */
    CompileEnv *envPtr)		/* Holds the resulting instructions. */
{
    int count = count1;

    if ((count == 1) && (tokenPtr->type == TCL_TOKEN_TEXT)) {
	/*
	 * Handle the common case: if there is a single text token, compile it
	 * The common case that there is a single text token. Compile it
	 * into an inline sequence of instructions.
	 */

	TclCompileScript(interp, tokenPtr->start, tokenPtr->size, envPtr);
    } else {
	/*
	 * Multiple tokens or the single token involves substitutions. Emit
	 * instructions to invoke the eval command procedure at runtime on the
	 * result of evaluating the tokens.
	 * Either there are multiple tokens, or the single token involves
	 * substitutions. Emit instructions to invoke the eval command
	 * procedure at runtime on the result of evaluating the tokens.
	 */

	TclCompileTokens(interp, tokenPtr, count, envPtr);
	TclEmitInvoke(envPtr, INST_EVAL_STK);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileExprWords --
 *
 *	Given an array of parse tokens representing one or more words that
 *	contain a Tcl expression, emit inline instructions to execute the
 *	expression. This procedure differs from TclCompileExpr in that it
 *	supports Tcl's two-level substitution semantics for expressions that
 *	contain a Tcl expression, emits inline instructions to execute the
 *	expression. In contrast with TclCompileExpr, supports Tcl's two-level
 *	substitution semantics for an expression that appears as command words.
 *	appear as command words.
 *
 * Results:
 *	The return value is a standard Tcl result. If an error occurs, an
 *	A standard Tcl result. If an error occurs, an
 *	error message is left in the interpreter's result.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the expression.
 *
 *----------------------------------------------------------------------
 */

void
TclCompileExprWords(
    Tcl_Interp *interp,		/* Used for error and status reporting. */
    Tcl_Token *tokenPtr,	/* Points to first in an array of word tokens
				 * tokens for the expression to compile
				 * for the expression to compile inline. */
				 * inline. */
    int numWords,		/* Number of word tokens starting at tokenPtr.
    size_t numWords1,		/* Number of word tokens starting at tokenPtr.
				 * Must be at least 1. Each word token
				 * contains one or more subtokens. */
    CompileEnv *envPtr)		/* Holds the resulting instructions. */
{
    Tcl_Token *wordPtr;
    int i, concatItems;
    int numWords = numWords1;

    /*
     * If the expression is a single word that doesn't require substitutions,
     * just compile its string into inline instructions.
     */

    if ((numWords == 1) && (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD)) {
2697
2698
2699
2700
2701
2702
2703
2704

2705
2706
2707

2708
2709
2710
2711
2712
2713
2714
2733
2734
2735
2736
2737
2738
2739

2740
2741
2742

2743
2744
2745
2746
2747
2748
2749
2750







-
+


-
+







}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileNoOp --
 *
 *	Function called to compile no-op's
 *	Compiles no-op's
 *
 * Results:
 *	The return value is TCL_OK, indicating successful compilation.
 *	TCL_OK if completion was successful.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute a no-op at runtime. No
 *	result is pushed onto the stack: the compiler has to take care of this
 *	itself if the last compiled command is a NoOp.
 *
 *----------------------------------------------------------------------
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
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







-
+
















-
+






-
+

















-
+




-
+






-
-
+
+

-
+







    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    Tcl_Token *tokenPtr;
    int i;

    tokenPtr = parsePtr->tokenPtr;
    for (i = 1; i < parsePtr->numWords; i++) {
    for (i = 1; i < (int)parsePtr->numWords; i++) {
	tokenPtr = tokenPtr + tokenPtr->numComponents + 1;

	if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	    CompileTokens(envPtr, tokenPtr, interp);
	    TclEmitOpcode(INST_POP, envPtr);
	}
    }
    PushStringLiteral(envPtr, "");
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclInitByteCodeObj --
 *
 *	Create a ByteCode structure and initialize it from a CompileEnv
 *	Creates a ByteCode structure and initializes it from a CompileEnv
 *	compilation environment structure. The ByteCode structure is smaller
 *	and contains just that information needed to execute the bytecode
 *	instructions resulting from compiling a Tcl script. The resulting
 *	structure is placed in the specified object.
 *
 * Results:
 *	A newly constructed ByteCode object is stored in the internal
 *	A newly-constructed ByteCode object is stored in the internal
 *	representation of the objPtr.
 *
 * Side effects:
 *	A single heap object is allocated to hold the new ByteCode structure
 *	and its code, object, command location, and aux data arrays. Note that
 *	"ownership" (i.e., the pointers to) the Tcl objects and aux data items
 *	will be handed over to the new ByteCode structure from the CompileEnv
 *	structure.
 *
 *----------------------------------------------------------------------
 */

static void
PreventCycle(
    Tcl_Obj *objPtr,
    CompileEnv *envPtr)
{
    int i;
    Tcl_Size i;

    for (i = 0;  i < envPtr->literalArrayNext; i++) {
	if (objPtr == TclFetchLiteral(envPtr, i)) {
	    /*
	     * Prevent circular reference where the bytecode intrep of
	     * Prevent circular reference where the bytecode internalrep of
	     * a value contains a literal which is that same value.
	     * If this is allowed to happen, refcount decrements may not
	     * reach zero, and memory may leak.  Bugs 467523, 3357771
	     *
	     * NOTE:  [Bugs 3392070, 3389764] We make a copy based completely
	     * on the string value, and do not call Tcl_DuplicateObj() so we
             * can be sure we do not have any lingering cycles hiding in
	     * the intrep.
	     * can be sure we do not have any lingering cycles hiding in
	     * the internalrep.
	     */
	    size_t numBytes;
	    Tcl_Size numBytes;
	    const char *bytes = TclGetStringFromObj(objPtr, &numBytes);
	    Tcl_Obj *copyPtr = Tcl_NewStringObj(bytes, numBytes);

	    Tcl_IncrRefCount(copyPtr);
	    TclReleaseLiteral((Tcl_Interp *)envPtr->iPtr, objPtr);

	    envPtr->literalArrayPtr[i].objPtr = copyPtr;
2822
2823
2824
2825
2826
2827
2828




2829
2830
2831

2832
2833
2834
2835
2836
2837
2838
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870

2871
2872
2873
2874
2875
2876
2877
2878







+
+
+
+


-
+







    objArrayBytes = envPtr->literalArrayNext * sizeof(Tcl_Obj *);
    exceptArrayBytes = envPtr->exceptArrayNext * sizeof(ExceptionRange);
    auxDataArrayBytes = envPtr->auxDataArrayNext * sizeof(AuxData);
    cmdLocBytes = GetCmdLocEncodingSize(envPtr);

    /*
     * Compute the total number of bytes needed for this bytecode.
     *
     * Note that code bytes need not be aligned but since later elements are we
     * need to pad anyway, either directly after ByteCode or after codeBytes,
     * and it's easier and more consistent to do the former.
     */

    structureSize = sizeof(ByteCode);
    structureSize = TCL_ALIGN(sizeof(ByteCode));  /* align code bytes */
    structureSize += TCL_ALIGN(codeBytes);	  /* align object array */
    structureSize += TCL_ALIGN(objArrayBytes);	  /* align exc range arr */
    structureSize += TCL_ALIGN(exceptArrayBytes); /* align AuxData array */
    structureSize += auxDataArrayBytes;
    structureSize += cmdLocBytes;

    if (envPtr->iPtr->varFramePtr != NULL) {
2863
2864
2865
2866
2867
2868
2869
2870

2871
2872
2873
2874
2875
2876
2877
2903
2904
2905
2906
2907
2908
2909

2910
2911
2912
2913
2914
2915
2916
2917







-
+







    codePtr->numLitObjects = numLitObjects;
    codePtr->numExceptRanges = envPtr->exceptArrayNext;
    codePtr->numAuxDataItems = envPtr->auxDataArrayNext;
    codePtr->numCmdLocBytes = cmdLocBytes;
    codePtr->maxExceptDepth = envPtr->maxExceptDepth;
    codePtr->maxStackDepth = envPtr->maxStackDepth;

    p += sizeof(ByteCode);
    p += TCL_ALIGN(sizeof(ByteCode));	/* align code bytes */
    codePtr->codeStart = p;
    memcpy(p, envPtr->codeStart, codeBytes);

    p += TCL_ALIGN(codeBytes);		/* align object array */
    codePtr->objArrayPtr = (Tcl_Obj **) p;
    for (i = 0;  i < numLitObjects;  i++) {
	codePtr->objArrayPtr[i] = TclFetchLiteral(envPtr, i);
2948
2949
2950
2951
2952
2953
2954
2955

2956
2957
2958
2959
2960
2961
2962
2988
2989
2990
2991
2992
2993
2994

2995
2996
2997
2998
2999
3000
3001
3002







-
+







    codePtr = TclInitByteCode(envPtr);

    /*
     * Free the old internal rep then convert the object to a bytecode object
     * by making its internal rep point to the just compiled ByteCode.
     */

    ByteCodeSetIntRep(objPtr, typePtr, codePtr);
    ByteCodeSetInternalRep(objPtr, typePtr, codePtr);
    return codePtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TclFindCompiledLocal --
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
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







-
+




-
+





-
-
+
+


















-
+


-
+











-
+



-
+







 * Side effects:
 *	Creates and registers a new local variable if create is 1 and the
 *	variable is unknown, or if the name is NULL.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_Size
TclFindCompiledLocal(
    const char *name,	/* Points to first character of the name of a
				 * scalar or array variable. If NULL, a
				 * temporary var should be created. */
    size_t nameBytes,		/* Number of bytes in the name. */
    Tcl_Size nameBytes,		/* Number of bytes in the name. */
    int create,			/* If 1, allocate a local frame entry for the
				 * variable if it is new. */
    CompileEnv *envPtr)		/* Points to the current compile environment*/
{
    CompiledLocal *localPtr;
    int localVar = -1;
    int i;
    Tcl_Size localVar = TCL_INDEX_NONE;
    Tcl_Size i;
    Proc *procPtr;

    /*
     * If not creating a temporary, does a local variable of the specified
     * name already exist?
     */

    procPtr = envPtr->procPtr;

    if (procPtr == NULL) {
	/*
	 * Compiling a non-body script: give it read access to the LVT in the
	 * current localCache
	 */

	LocalCache *cachePtr = envPtr->iPtr->varFramePtr->localCachePtr;
	const char *localName;
	Tcl_Obj **varNamePtr;
	size_t len;
	Tcl_Size len;

	if (!cachePtr || !name) {
	    return -1;
	    return TCL_INDEX_NONE;
	}

	varNamePtr = &cachePtr->varName0;
	for (i=0; i < cachePtr->numVars; varNamePtr++, i++) {
	    if (*varNamePtr) {
		localName = TclGetStringFromObj(*varNamePtr, &len);
		if ((len == nameBytes) && !strncmp(name, localName, len)) {
		    return i;
		}
	    }
	}
	return -1;
	return TCL_INDEX_NONE;
    }

    if (name != NULL) {
	int localCt = procPtr->numCompiledLocals;
	Tcl_Size localCt = procPtr->numCompiledLocals;

	localPtr = procPtr->firstLocalPtr;
	for (i = 0;  i < localCt;  i++) {
	    if (!TclIsVarTemporary(localPtr)) {
		char *localName = localPtr->name;

		if ((nameBytes == localPtr->nameLength) &&
3049
3050
3051
3052
3053
3054
3055
3056

3057
3058
3059
3060
3061
3062
3063
3089
3090
3091
3092
3093
3094
3095

3096
3097
3098
3099
3100
3101
3102
3103







-
+








    /*
     * Create a new variable if appropriate.
     */

    if (create || (name == NULL)) {
	localVar = procPtr->numCompiledLocals;
	localPtr = (CompiledLocal *)Tcl_Alloc(offsetof(CompiledLocal, name) + nameBytes + 1);
	localPtr = (CompiledLocal *)Tcl_Alloc(offsetof(CompiledLocal, name) + 1U + nameBytes);
	if (procPtr->firstLocalPtr == NULL) {
	    procPtr->firstLocalPtr = procPtr->lastLocalPtr = localPtr;
	} else {
	    procPtr->lastLocalPtr->nextPtr = localPtr;
	    procPtr->lastLocalPtr = localPtr;
	}
	localPtr->nextPtr = NULL;
3080
3081
3082
3083
3084
3085
3086
3087

3088
3089
3090
3091
3092
3093
3094
3095
3096



3097
3098
3099
3100
3101
3102
3103
3120
3121
3122
3123
3124
3125
3126

3127

3128
3129
3130
3131
3132



3133
3134
3135
3136
3137
3138
3139
3140
3141
3142







-
+
-





-
-
-
+
+
+







}

/*
 *----------------------------------------------------------------------
 *
 * TclExpandCodeArray --
 *
 *	Procedure that uses malloc to allocate more storage for a CompileEnv's
 *	Uses malloc to allocate more storage for a CompileEnv's code array.
 *	code array.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The byte code array in *envPtr is reallocated to a new array of double
 *	the size, and if envPtr->mallocedCodeArray is non-zero the old array
 *	is freed. Byte codes are copied from the old array to the new one.
 *	The size of the bytecode array is doubled. If envPtr->mallocedCodeArray
 *	is non-zero the old array is freed. Byte codes are copied from the old
 *	array to the new one.
 *
 *----------------------------------------------------------------------
 */

void
TclExpandCodeArray(
    void *envArgPtr)		/* Points to the CompileEnv whose code array
3116
3117
3118
3119
3120
3121
3122
3123
3124


3125
3126
3127
3128
3129
3130
3131
3155
3156
3157
3158
3159
3160
3161


3162
3163
3164
3165
3166
3167
3168
3169
3170







-
-
+
+







    size_t currBytes = envPtr->codeNext - envPtr->codeStart;
    size_t newBytes = 2 * (envPtr->codeEnd - envPtr->codeStart);

    if (envPtr->mallocedCodeArray) {
	envPtr->codeStart = (unsigned char *)Tcl_Realloc(envPtr->codeStart, newBytes);
    } else {
	/*
	 * envPtr->codeStart isn't a Tcl_Alloc'd pointer, so we must code a
	 * Tcl_Realloc equivalent for ourselves.
	 * envPtr->exceptArrayPtr isn't a Tcl_Alloc'd pointer, so
	 * perform the equivalent of Tcl_Realloc directly.
	 */

	unsigned char *newPtr = (unsigned char *)Tcl_Alloc(newBytes);

	memcpy(newPtr, envPtr->codeStart, currBytes);
	envPtr->codeStart = newPtr;
	envPtr->mallocedCodeArray = 1;
3156
3157
3158
3159
3160
3161
3162
3163

3164
3165
3166


3167
3168
3169
3170
3171


3172
3173
3174
3175
3176
3177
3178
3195
3196
3197
3198
3199
3200
3201

3202
3203


3204
3205
3206
3207
3208


3209
3210
3211
3212
3213
3214
3215
3216
3217







-
+

-
-
+
+



-
-
+
+







 */

static void
EnterCmdStartData(
    CompileEnv *envPtr,		/* Points to the compilation environment
				 * structure in which to enter command
				 * location information. */
    int cmdIndex,		/* Index of the command whose start data is
    Tcl_Size cmdIndex,		/* Index of the command whose start data is
				 * being set. */
    int srcOffset,		/* Offset of first char of the command. */
    int codeOffset)		/* Offset of first byte of command code. */
    Tcl_Size srcOffset,		/* Offset of first char of the command. */
    Tcl_Size codeOffset)		/* Offset of first byte of command code. */
{
    CmdLocation *cmdLocPtr;

    if ((cmdIndex < 0) || (cmdIndex >= envPtr->numCommands)) {
	Tcl_Panic("EnterCmdStartData: bad command index %d", cmdIndex);
    if (cmdIndex < 0 || cmdIndex >= envPtr->numCommands) {
	Tcl_Panic("EnterCmdStartData: bad command index %" TCL_Z_MODIFIER "u", cmdIndex);
    }

    if (cmdIndex >= envPtr->cmdMapEnd) {
	/*
	 * Expand the command location array by allocating more storage from
	 * the heap. The currently allocated CmdLocation entries are stored
	 * from cmdMapPtr[0] up to cmdMapPtr[envPtr->cmdMapEnd] (inclusive).
3205
3206
3207
3208
3209
3210
3211
3212
3213


3214
3215
3216
3217
3218
3219
3220
3244
3245
3246
3247
3248
3249
3250


3251
3252
3253
3254
3255
3256
3257
3258
3259







-
-
+
+







	    Tcl_Panic("EnterCmdStartData: cmd map not sorted by code offset");
	}
    }

    cmdLocPtr = &envPtr->cmdMapPtr[cmdIndex];
    cmdLocPtr->codeOffset = codeOffset;
    cmdLocPtr->srcOffset = srcOffset;
    cmdLocPtr->numSrcBytes = -1;
    cmdLocPtr->numCodeBytes = -1;
    cmdLocPtr->numSrcBytes = TCL_INDEX_NONE;
    cmdLocPtr->numCodeBytes = TCL_INDEX_NONE;
}

/*
 *----------------------------------------------------------------------
 *
 * EnterCmdExtentData --
 *
3235
3236
3237
3238
3239
3240
3241
3242

3243
3244
3245


3246
3247
3248
3249
3250


3251
3252
3253
3254

3255
3256
3257
3258
3259
3260
3261
3274
3275
3276
3277
3278
3279
3280

3281
3282


3283
3284
3285
3286
3287


3288
3289
3290
3291
3292

3293
3294
3295
3296
3297
3298
3299
3300







-
+

-
-
+
+



-
-
+
+



-
+







 */

static void
EnterCmdExtentData(
    CompileEnv *envPtr,		/* Points to the compilation environment
				 * structure in which to enter command
				 * location information. */
    int cmdIndex,		/* Index of the command whose source and code
    Tcl_Size cmdIndex,		/* Index of the command whose source and code
				 * length data is being set. */
    int numSrcBytes,		/* Number of command source chars. */
    int numCodeBytes)		/* Offset of last byte of command code. */
    Tcl_Size numSrcBytes,		/* Number of command source chars. */
    Tcl_Size numCodeBytes)		/* Offset of last byte of command code. */
{
    CmdLocation *cmdLocPtr;

    if ((cmdIndex < 0) || (cmdIndex >= envPtr->numCommands)) {
	Tcl_Panic("EnterCmdExtentData: bad command index %d", cmdIndex);
    if (cmdIndex < 0 || cmdIndex >= envPtr->numCommands) {
	Tcl_Panic("EnterCmdExtentData: bad command index %" TCL_Z_MODIFIER "u", cmdIndex);
    }

    if (cmdIndex > envPtr->cmdMapEnd) {
	Tcl_Panic("EnterCmdExtentData: missing start data for command %d",
	Tcl_Panic("EnterCmdExtentData: missing start data for command %" TCL_Z_MODIFIER "u",
		cmdIndex);
    }

    cmdLocPtr = &envPtr->cmdMapPtr[cmdIndex];
    cmdLocPtr->numSrcBytes = numSrcBytes;
    cmdLocPtr->numCodeBytes = numCodeBytes;
}
3281
3282
3283
3284
3285
3286
3287
3288

3289
3290
3291
3292
3293
3294




3295
3296
3297
3298

3299

3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319


3320
3321

3322
3323
3324
3325
3326
3327
3328
3320
3321
3322
3323
3324
3325
3326

3327
3328
3329




3330
3331
3332
3333
3334
3335
3336
3337
3338

3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357


3358
3359
3360

3361
3362
3363
3364
3365
3366
3367
3368







-
+


-
-
-
-
+
+
+
+




+
-
+


















-
-
+
+

-
+







 */

static void
EnterCmdWordData(
    ExtCmdLoc *eclPtr,		/* Points to the map environment structure in
				 * which to enter command location
				 * information. */
    int srcOffset,		/* Offset of first char of the command. */
    Tcl_Size srcOffset,		/* Offset of first char of the command. */
    Tcl_Token *tokenPtr,
    const char *cmd,
    int numWords,
    int line,
    int *clNext,
    int **wlines,
    Tcl_Size numWords,
    Tcl_Size line,
    Tcl_Size *clNext,
    Tcl_Size **wlines,
    CompileEnv *envPtr)
{
    ECL *ePtr;
    const char *last;
    Tcl_Size wordIdx, wordLine;
    int wordIdx, wordLine, *wwlines, *wordNext;
    Tcl_Size *wwlines, *wordNext;

    if (eclPtr->nuloc >= eclPtr->nloc) {
	/*
	 * Expand the ECL array by allocating more storage from the heap. The
	 * currently allocated ECL entries are stored from eclPtr->loc[0] up
	 * to eclPtr->loc[eclPtr->nuloc-1] (inclusive).
	 */

	size_t currElems = eclPtr->nloc;
	size_t newElems = (currElems ? 2*currElems : 1);
	size_t newBytes = newElems * sizeof(ECL);

	eclPtr->loc = (ECL *)Tcl_Realloc(eclPtr->loc, newBytes);
	eclPtr->nloc = newElems;
    }

    ePtr = &eclPtr->loc[eclPtr->nuloc];
    ePtr->srcOffset = srcOffset;
    ePtr->line = (int *)Tcl_Alloc(numWords * sizeof(int));
    ePtr->next = (int **)Tcl_Alloc(numWords * sizeof(int *));
    ePtr->line = (Tcl_Size *)Tcl_Alloc(numWords * sizeof(Tcl_Size));
    ePtr->next = (Tcl_Size **)Tcl_Alloc(numWords * sizeof(Tcl_Size *));
    ePtr->nline = numWords;
    wwlines = (int *)Tcl_Alloc(numWords * sizeof(int));
    wwlines = (Tcl_Size *)Tcl_Alloc(numWords * sizeof(Tcl_Size));

    last = cmd;
    wordLine = line;
    wordNext = clNext;
    for (wordIdx=0 ; wordIdx<numWords;
	    wordIdx++, tokenPtr += tokenPtr->numComponents + 1) {
	TclAdvanceLines(&wordLine, last, tokenPtr->start);
3357
3358
3359
3360
3361
3362
3363
3364

3365
3366
3367
3368
3369
3370
3371
3372

3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384

3385
3386
3387
3388
3389
3390
3391
3397
3398
3399
3400
3401
3402
3403

3404
3405
3406
3407
3408
3409
3410
3411

3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423

3424
3425
3426
3427
3428
3429
3430
3431







-
+







-
+











-
+







 *	the array in expanded: a new array of double the size is allocated, if
 *	envPtr->mallocedExceptArray is non-zero the old array is freed, and
 *	ExceptionRange entries are copied from the old array to the new one.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_Size
TclCreateExceptRange(
    ExceptionRangeType type,	/* The kind of ExceptionRange desired. */
    CompileEnv *envPtr)/* Points to CompileEnv for which to create a
				 * new ExceptionRange structure. */
{
    ExceptionRange *rangePtr;
    ExceptionAux *auxPtr;
    int index = envPtr->exceptArrayNext;
    Tcl_Size index = envPtr->exceptArrayNext;

    if (index >= envPtr->exceptArrayEnd) {
	/*
	 * Expand the ExceptionRange array. The currently allocated entries
	 * are stored between elements 0 and (envPtr->exceptArrayNext - 1)
	 * [inclusive].
	 */

	size_t currBytes =
		envPtr->exceptArrayNext * sizeof(ExceptionRange);
	size_t currBytes2 = envPtr->exceptArrayNext * sizeof(ExceptionAux);
	int newElems = 2*envPtr->exceptArrayEnd;
	size_t newElems = 2*envPtr->exceptArrayEnd;
	size_t newBytes = newElems * sizeof(ExceptionRange);
	size_t newBytes2 = newElems * sizeof(ExceptionAux);

	if (envPtr->mallocedExceptArray) {
	    envPtr->exceptArrayPtr =
		    (ExceptionRange *)Tcl_Realloc(envPtr->exceptArrayPtr, newBytes);
	    envPtr->exceptAuxArrayPtr =
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419





3420
3421
3422
3423
3424

3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440

3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454

3455
3456
3457
3458
3459
3460
3461
3462



3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482

3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504


3505
3506
3507

3508
3509
3510
3511
3512
3513
3514
3448
3449
3450
3451
3452
3453
3454





3455
3456
3457
3458
3459
3460
3461
3462
3463

3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479

3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493

3494
3495
3496
3497
3498
3499



3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521

3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542


3543
3544
3545
3546

3547
3548
3549
3550
3551
3552
3553
3554







-
-
-
-
-
+
+
+
+
+




-
+















-
+













-
+





-
-
-
+
+
+



















-
+




















-
-
+
+


-
+







	envPtr->exceptArrayEnd = newElems;
    }
    envPtr->exceptArrayNext++;

    rangePtr = &envPtr->exceptArrayPtr[index];
    rangePtr->type = type;
    rangePtr->nestingLevel = envPtr->exceptDepth;
    rangePtr->codeOffset = -1;
    rangePtr->numCodeBytes = -1;
    rangePtr->breakOffset = -1;
    rangePtr->continueOffset = -1;
    rangePtr->catchOffset = -1;
    rangePtr->codeOffset = TCL_INDEX_NONE;
    rangePtr->numCodeBytes = TCL_INDEX_NONE;
    rangePtr->breakOffset = TCL_INDEX_NONE;
    rangePtr->continueOffset = TCL_INDEX_NONE;
    rangePtr->catchOffset = TCL_INDEX_NONE;
    auxPtr = &envPtr->exceptAuxArrayPtr[index];
    auxPtr->supportsContinue = 1;
    auxPtr->stackDepth = envPtr->currStackDepth;
    auxPtr->expandTarget = envPtr->expandCount;
    auxPtr->expandTargetDepth = -1;
    auxPtr->expandTargetDepth = TCL_INDEX_NONE;
    auxPtr->numBreakTargets = 0;
    auxPtr->breakTargets = NULL;
    auxPtr->allocBreakTargets = 0;
    auxPtr->numContinueTargets = 0;
    auxPtr->continueTargets = NULL;
    auxPtr->allocContinueTargets = 0;
    return index;
}

/*
 * ---------------------------------------------------------------------
 *
 * TclGetInnermostExceptionRange --
 *
 *	Returns the innermost exception range that covers the current code
 *	creation point, and (optionally) the stack depth that is expected at
 *	creation point, and optionally the stack depth that is expected at
 *	that point. Relies on the fact that the range has a numCodeBytes = -1
 *	when it is being populated and that inner ranges come after outer
 *	ranges.
 *
 * ---------------------------------------------------------------------
 */

ExceptionRange *
TclGetInnermostExceptionRange(
    CompileEnv *envPtr,
    int returnCode,
    ExceptionAux **auxPtrPtr)
{
    int i = envPtr->exceptArrayNext;
    size_t i = envPtr->exceptArrayNext;
    ExceptionRange *rangePtr = envPtr->exceptArrayPtr + i;

    while (i > 0) {
	rangePtr--; i--;

	if (CurrentOffset(envPtr) >= rangePtr->codeOffset &&
		(rangePtr->numCodeBytes == -1 || CurrentOffset(envPtr) <
			rangePtr->codeOffset+rangePtr->numCodeBytes) &&
	if (CurrentOffset(envPtr) >= (int)rangePtr->codeOffset &&
		(rangePtr->numCodeBytes == TCL_INDEX_NONE || CurrentOffset(envPtr) <
			(int)rangePtr->codeOffset+(int)rangePtr->numCodeBytes) &&
		(returnCode != TCL_CONTINUE ||
			envPtr->exceptAuxArrayPtr[i].supportsContinue)) {

	    if (auxPtrPtr) {
		*auxPtrPtr = envPtr->exceptAuxArrayPtr + i;
	    }
	    return rangePtr;
	}
    }
    return NULL;
}

/*
 * ---------------------------------------------------------------------
 *
 * TclAddLoopBreakFixup, TclAddLoopContinueFixup --
 *
 *	Adds a place that wants to break/continue to the loop exception range
 *	tracking that will be fixed up once the loop can be finalized. These
 *	functions will generate an INST_JUMP4 that will be fixed up during the
 *	functions generate an INST_JUMP4 that is fixed up during the
 *	loop finalization.
 *
 * ---------------------------------------------------------------------
 */

void
TclAddLoopBreakFixup(
    CompileEnv *envPtr,
    ExceptionAux *auxPtr)
{
    int range = auxPtr - envPtr->exceptAuxArrayPtr;

    if (envPtr->exceptArrayPtr[range].type != LOOP_EXCEPTION_RANGE) {
	Tcl_Panic("trying to add 'break' fixup to full exception range");
    }

    if (++auxPtr->numBreakTargets > auxPtr->allocBreakTargets) {
	auxPtr->allocBreakTargets *= 2;
	auxPtr->allocBreakTargets += 2;
	if (auxPtr->breakTargets) {
	    auxPtr->breakTargets = (unsigned int *)Tcl_Realloc(auxPtr->breakTargets,
		    sizeof(int) * auxPtr->allocBreakTargets);
	    auxPtr->breakTargets = (size_t *)Tcl_Realloc(auxPtr->breakTargets,
		    sizeof(size_t) * auxPtr->allocBreakTargets);
	} else {
	    auxPtr->breakTargets =
		    (unsigned int *)Tcl_Alloc(sizeof(int) * auxPtr->allocBreakTargets);
		    (size_t *)Tcl_Alloc(sizeof(size_t) * auxPtr->allocBreakTargets);
	}
    }
    auxPtr->breakTargets[auxPtr->numBreakTargets - 1] = CurrentOffset(envPtr);
    TclEmitInstInt4(INST_JUMP4, 0, envPtr);
}

void
3522
3523
3524
3525
3526
3527
3528
3529
3530


3531
3532
3533

3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547


3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558

3559
3560
3561
3562
3563
3564
3565

3566
3567
3568
3569
3570
3571
3572
3562
3563
3564
3565
3566
3567
3568


3569
3570
3571
3572

3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585


3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597

3598
3599
3600
3601
3602
3603
3604

3605
3606
3607
3608
3609
3610
3611
3612







-
-
+
+


-
+












-
-
+
+










-
+






-
+







	Tcl_Panic("trying to add 'continue' fixup to full exception range");
    }

    if (++auxPtr->numContinueTargets > auxPtr->allocContinueTargets) {
	auxPtr->allocContinueTargets *= 2;
	auxPtr->allocContinueTargets += 2;
	if (auxPtr->continueTargets) {
	    auxPtr->continueTargets = (unsigned int *)Tcl_Realloc(auxPtr->continueTargets,
		    sizeof(int) * auxPtr->allocContinueTargets);
	    auxPtr->continueTargets = (size_t *)Tcl_Realloc(auxPtr->continueTargets,
		    sizeof(size_t) * auxPtr->allocContinueTargets);
	} else {
	    auxPtr->continueTargets =
		    (unsigned int *)Tcl_Alloc(sizeof(int) * auxPtr->allocContinueTargets);
		    (size_t *)Tcl_Alloc(sizeof(size_t) * auxPtr->allocContinueTargets);
	}
    }
    auxPtr->continueTargets[auxPtr->numContinueTargets - 1] =
	    CurrentOffset(envPtr);
    TclEmitInstInt4(INST_JUMP4, 0, envPtr);
}

/*
 * ---------------------------------------------------------------------
 *
 * TclCleanupStackForBreakContinue --
 *
 *	Ditch the extra elements from the auxiliary stack and the main stack.
 *	How to do this exactly depends on whether there are any elements on
 *	Removes the extra elements from the auxiliary stack and the main stack.
 *	How this is done depends on whether there are any elements on
 *	the auxiliary stack to pop.
 *
 * ---------------------------------------------------------------------
 */

void
TclCleanupStackForBreakContinue(
    CompileEnv *envPtr,
    ExceptionAux *auxPtr)
{
    int savedStackDepth = envPtr->currStackDepth;
    size_t savedStackDepth = envPtr->currStackDepth;
    int toPop = envPtr->expandCount - auxPtr->expandTarget;

    if (toPop > 0) {
	while (toPop --> 0) {
	    TclEmitOpcode(INST_EXPAND_DROP, envPtr);
	}
	TclAdjustStackDepth(auxPtr->expandTargetDepth - envPtr->currStackDepth,
	TclAdjustStackDepth((int)(auxPtr->expandTargetDepth - envPtr->currStackDepth),
		envPtr);
	envPtr->currStackDepth = auxPtr->expandTargetDepth;
    }
    toPop = envPtr->currStackDepth - auxPtr->stackDepth;
    while (toPop --> 0) {
	TclEmitOpcode(INST_POP, envPtr);
    }
3594
3595
3596
3597
3598
3599
3600
3601

3602
3603
3604
3605
3606
3607
3608
3609

3610
3611
3612

3613
3614
3615
3616
3617

3618
3619
3620
3621
3622
3623
3624
3625
3626
3627

3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640

3641
3642
3643
3644
3645
3646
3647
3634
3635
3636
3637
3638
3639
3640

3641
3642
3643
3644
3645
3646
3647
3648

3649
3650
3651

3652
3653
3654
3655
3656

3657
3658
3659
3660
3661
3662
3663
3664
3665
3666

3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679

3680
3681
3682
3683
3684
3685
3686
3687







-
+







-
+


-
+




-
+









-
+












-
+







    TclEmitOpcode(INST_EXPAND_START, envPtr);

    /*
     * Update inner exception ranges with information about the environment
     * where this expansion started.
     */

    for (i=0 ; i<envPtr->exceptArrayNext ; i++) {
    for (i=0 ; i<(int)envPtr->exceptArrayNext ; i++) {
	ExceptionRange *rangePtr = &envPtr->exceptArrayPtr[i];
	ExceptionAux *auxPtr = &envPtr->exceptAuxArrayPtr[i];

	/*
	 * Ignore loops unless they're still being built.
	 */

	if (rangePtr->codeOffset > CurrentOffset(envPtr)) {
	if ((int)rangePtr->codeOffset > CurrentOffset(envPtr)) {
	    continue;
	}
	if (rangePtr->numCodeBytes != -1) {
	if (rangePtr->numCodeBytes != TCL_INDEX_NONE) {
	    continue;
	}

	/*
	 * Adequate condition: further out loops and further in exceptions
	 * Adequate condition: loops further out and exceptions further in
	 * don't actually need this information.
	 */

	if (auxPtr->expandTarget == envPtr->expandCount) {
	    auxPtr->expandTargetDepth = envPtr->currStackDepth;
	}
    }

    /*
     * There's now one more expansion being processed on the auxiliary stack.
     * One more expansion is now being processed on the auxiliary stack.
     */

    envPtr->expandCount++;
}

/*
 * ---------------------------------------------------------------------
 *
 * TclFinalizeLoopExceptionRange --
 *
 *	Finalizes a loop exception range, binding the registered [break] and
 *	[continue] implementations so that they jump to the correct place.
 *	Note that this must only be called after *all* the exception range
 *	This must be called only after *all* the exception range
 *	target offsets have been set.
 *
 * ---------------------------------------------------------------------
 */

void
TclFinalizeLoopExceptionRange(
3658
3659
3660
3661
3662
3663
3664
3665

3666
3667
3668
3669
3670

3671
3672

3673
3674
3675
3676
3677
3678
3679
3698
3699
3700
3701
3702
3703
3704

3705
3706
3707
3708
3709

3710
3711

3712
3713
3714
3715
3716
3717
3718
3719







-
+




-
+

-
+







    }

    /*
     * Do the jump fixups. Note that these are always issued as INST_JUMP4 so
     * there is no need to fuss around with updating code offsets.
     */

    for (i=0 ; i<auxPtr->numBreakTargets ; i++) {
    for (i=0 ; i<(int)auxPtr->numBreakTargets ; i++) {
	site = envPtr->codeStart + auxPtr->breakTargets[i];
	offset = rangePtr->breakOffset - auxPtr->breakTargets[i];
	TclUpdateInstInt4AtPc(INST_JUMP4, offset, site);
    }
    for (i=0 ; i<auxPtr->numContinueTargets ; i++) {
    for (i=0 ; i<(int)auxPtr->numContinueTargets ; i++) {
	site = envPtr->codeStart + auxPtr->continueTargets[i];
	if (rangePtr->continueOffset == -1) {
	if (rangePtr->continueOffset == TCL_INDEX_NONE) {
	    int j;

	    /*
	     * WTF? Can't bind, so revert to an INST_CONTINUE. Not enough
	     * space to do anything else.
	     */

3704
3705
3706
3707
3708
3709
3710
3711

3712
3713
3714
3715
3716
3717

3718
3719
3720

3721
3722
3723
3724

3725
3726
3727
3728
3729

3730
3731

3732
3733
3734
3735
3736
3737
3738

3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751

3752
3753
3754
3755
3756
3757
3758
3744
3745
3746
3747
3748
3749
3750

3751
3752
3753
3754
3755
3756

3757
3758
3759

3760




3761

3762
3763
3764

3765
3766

3767
3768
3769
3770
3771
3772
3773

3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786

3787
3788
3789
3790
3791
3792
3793
3794







-
+





-
+


-
+
-
-
-
-
+
-



-
+

-
+






-
+












-
+







}

/*
 *----------------------------------------------------------------------
 *
 * TclCreateAuxData --
 *
 *	Procedure that allocates and initializes a new AuxData structure in a
 *	Allocates and initializes a new AuxData structure in a
 *	CompileEnv's array of compilation auxiliary data records. These
 *	AuxData records hold information created during compilation by
 *	CompileProcs and used by instructions during execution.
 *
 * Results:
 *	Returns the index for the newly created AuxData structure.
 *	The index of the newly-created AuxData structure in the array.
 *
 * Side effects:
 *	If there is not enough room in the CompileEnv's AuxData array, the
 *	If there is not enough room in the CompileEnv's AuxData array, its size
 *	AuxData array in expanded: a new array of double the size is
 *	allocated, if envPtr->mallocedAuxDataArray is non-zero the old array
 *	is freed, and AuxData entries are copied from the old array to the new
 *	one.
 *	is doubled.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_Size
TclCreateAuxData(
    ClientData clientData,	/* The compilation auxiliary data to store in
    void *clientData,	/* The compilation auxiliary data to store in
				 * the new aux data record. */
    const AuxDataType *typePtr,	/* Pointer to the type to attach to this
				 * AuxData */
    CompileEnv *envPtr)/* Points to the CompileEnv for which a new
				 * aux data structure is to be allocated. */
{
    int index;			/* Index for the new AuxData structure. */
    Tcl_Size index;		/* Index for the new AuxData structure. */
    AuxData *auxDataPtr;
				/* Points to the new AuxData structure */

    index = envPtr->auxDataArrayNext;
    if (index >= envPtr->auxDataArrayEnd) {
	/*
	 * Expand the AuxData array. The currently allocated entries are
	 * stored between elements 0 and (envPtr->auxDataArrayNext - 1)
	 * [inclusive].
	 */

	size_t currBytes = envPtr->auxDataArrayNext * sizeof(AuxData);
	int newElems = 2*envPtr->auxDataArrayEnd;
	size_t newElems = 2*envPtr->auxDataArrayEnd;
	size_t newBytes = newElems * sizeof(AuxData);

	if (envPtr->mallocedAuxDataArray) {
	    envPtr->auxDataArrayPtr =
		    (AuxData *)Tcl_Realloc(envPtr->auxDataArrayPtr, newBytes);
	} else {
	    /*
3806
3807
3808
3809
3810
3811
3812
3813

3814
3815
3816
3817
3818
3819
3820
3821
3842
3843
3844
3845
3846
3847
3848

3849

3850
3851
3852
3853
3854
3855
3856







-
+
-







}

/*
 *----------------------------------------------------------------------
 *
 * TclExpandJumpFixupArray --
 *
 *	Procedure that uses malloc to allocate more storage for a jump fixup
 *	Uses malloc to allocate more storage for a jump fixup array.
 *	array.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The jump fixup array in *fixupArrayPtr is reallocated to a new array
 *	of double the size, and if fixupArrayPtr->mallocedArray is non-zero
3834
3835
3836
3837
3838
3839
3840
3841

3842
3843
3844
3845
3846
3847
3848
3869
3870
3871
3872
3873
3874
3875

3876
3877
3878
3879
3880
3881
3882
3883







-
+







    /*
     * The currently allocated jump fixup entries are stored from fixup[0] up
     * to fixup[fixupArrayPtr->fixupNext] (*not* inclusive). We assume
     * fixupArrayPtr->fixupNext is equal to fixupArrayPtr->fixupEnd.
     */

    size_t currBytes = fixupArrayPtr->next * sizeof(JumpFixup);
    int newElems = 2*(fixupArrayPtr->end + 1);
    size_t newElems = 2*(fixupArrayPtr->end + 1);
    size_t newBytes = newElems * sizeof(JumpFixup);

    if (fixupArrayPtr->mallocedArray) {
	fixupArrayPtr->fixup = (JumpFixup *)Tcl_Realloc(fixupArrayPtr->fixup, newBytes);
    } else {
	/*
	 * fixupArrayPtr->fixup isn't a Tcl_Alloc'd pointer, so we must code a
3886
3887
3888
3889
3890
3891
3892
3893

3894
3895
3896




3897
3898
3899
3900
3901
3902
3903
3921
3922
3923
3924
3925
3926
3927

3928



3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939







-
+
-
-
-
+
+
+
+







}

/*
 *----------------------------------------------------------------------
 *
 * TclEmitForwardJump --
 *
 *	Procedure to emit a two-byte forward jump of kind "jumpType". Since
 *	Emits a two-byte forward jump of kind "jumpType".  Also initializes a
 *	the jump may later have to be grown to five bytes if the jump target
 *	is more than, say, 127 bytes away, this procedure also initializes a
 *	JumpFixup record with information about the jump.
 *	JumpFixup record with information about the jump.  Since may later be
 *	necessary to increase the size of the jump instruction to five bytes if
 *	the jump target is more than, say, 127 bytes away.
 *
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The JumpFixup record pointed to by "jumpFixupPtr" is initialized with
 *	information needed later if the jump is to be grown. Also, a two byte
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955






3956
3957
3958
3959
3960



3961
3962
3963
3964
3965
3966
3967
3980
3981
3982
3983
3984
3985
3986





3987
3988
3989
3990
3991
3992
3993
3994



3995
3996
3997
3998
3999
4000
4001
4002
4003
4004







-
-
-
-
-
+
+
+
+
+
+


-
-
-
+
+
+







}

/*
 *----------------------------------------------------------------------
 *
 * TclFixupForwardJump --
 *
 *	Procedure that updates a previously-emitted forward jump to jump a
 *	specified number of bytes, "jumpDist". If necessary, the jump is grown
 *	from two to five bytes; this is done if the jump distance is greater
 *	than "distThreshold" (normally 127 bytes). The jump is described by a
 *	JumpFixup record previously initialized by TclEmitForwardJump.
 *	Modifies a previously-emitted forward jump to jump a specified number
 *	of bytes, "jumpDist". If necessary, the size of the jump instruction is
 *	increased from two to five bytes.  This is done if the jump distance is
 *	greater than "distThreshold" (normally 127 bytes). The jump is
 *	described by a JumpFixup record previously initialized by
 *	TclEmitForwardJump.
 *
 * Results:
 *	1 if the jump was grown and subsequent instructions had to be moved;
 *	otherwise 0. This result is returned to allow callers to update any
 *	additional code offsets they may hold.
 *	1 if the jump was grown and subsequent instructions had to be moved, or
 *	0 otherwsie. This allows callers to update any additional code offsets
 *	they may hold.
 *
 * Side effects:
 *	The jump may be grown and subsequent instructions moved. If this
 *	happens, the code offsets for any commands and any ExceptionRange
 *	records between the jump and the current code address will be updated
 *	to reflect the moved code. Also, the bytecode instruction array in the
 *	CompileEnv structure may be grown and reallocated.
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006




4007
4008
4009
4010
4011
4012
4013
4033
4034
4035
4036
4037
4038
4039




4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050







-
-
-
-
+
+
+
+







	    TclUpdateInstInt1AtPc(INST_JUMP_FALSE1, jumpDist, jumpPc);
	    break;
	}
	return 0;
    }

    /*
     * We must grow the jump then move subsequent instructions down. Note that
     * if we expand the space for generated instructions, code addresses might
     * change; be careful about updating any of these addresses held in
     * variables.
     * Increase the size of the jump instruction, and then move subsequent
     * instructions down.  Expanding the space for generated instructions means
     * that code addresses might change.  Be careful about updating any of
     * these addresses held in variables.
     */

    if ((envPtr->codeNext + 3) > envPtr->codeEnd) {
	TclExpandCodeArray(envPtr);
    }
    jumpPc = envPtr->codeStart + jumpFixupPtr->codeOffset;
    numBytes = envPtr->codeNext-jumpPc-2;
4046
4047
4048
4049
4050
4051
4052
4053

4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066

4067
4068
4069
4070

4071
4072
4073
4074
4075

4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090

4091
4092
4093
4094
4095
4096
4097
4098
4099
4100

4101
4102
4103
4104
4105
4106
4107
4083
4084
4085
4086
4087
4088
4089

4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102

4103
4104
4105
4106

4107
4108
4109
4110
4111

4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126

4127
4128
4129
4130
4131
4132
4133
4134
4135
4136

4137
4138
4139
4140
4141
4142
4143
4144







-
+












-
+



-
+




-
+














-
+









-
+







    for (k = firstRange;  k <= lastRange;  k++) {
	ExceptionRange *rangePtr = &envPtr->exceptArrayPtr[k];

	rangePtr->codeOffset += 3;
	switch (rangePtr->type) {
	case LOOP_EXCEPTION_RANGE:
	    rangePtr->breakOffset += 3;
	    if (rangePtr->continueOffset != -1) {
	    if (rangePtr->continueOffset != TCL_INDEX_NONE) {
		rangePtr->continueOffset += 3;
	    }
	    break;
	case CATCH_EXCEPTION_RANGE:
	    rangePtr->catchOffset += 3;
	    break;
	default:
	    Tcl_Panic("TclFixupForwardJump: bad ExceptionRange type %d",
		    rangePtr->type);
	}
    }

    for (k = 0 ; k < envPtr->exceptArrayNext ; k++) {
    for (k = 0 ; k < (int)envPtr->exceptArrayNext ; k++) {
	ExceptionAux *auxPtr = &envPtr->exceptAuxArrayPtr[k];
	int i;

	for (i=0 ; i<auxPtr->numBreakTargets ; i++) {
	for (i=0 ; i<(int)auxPtr->numBreakTargets ; i++) {
	    if (jumpFixupPtr->codeOffset < auxPtr->breakTargets[i]) {
		auxPtr->breakTargets[i] += 3;
	    }
	}
	for (i=0 ; i<auxPtr->numContinueTargets ; i++) {
	for (i=0 ; i<(int)auxPtr->numContinueTargets ; i++) {
	    if (jumpFixupPtr->codeOffset < auxPtr->continueTargets[i]) {
		auxPtr->continueTargets[i] += 3;
	    }
	}
    }

    return 1;			/* the jump was grown */
}

/*
 *----------------------------------------------------------------------
 *
 * TclEmitInvoke --
 *
 *	Emit one of the invoke-related instructions, wrapping it if necessary
 *	Emits one of the invoke-related instructions, wrapping it if necessary
 *	in code that ensures that any break or continue operation passing
 *	through it gets the stack unwinding correct, converting it into an
 *	internal jump if in an appropriate context.
 *
 * Results:
 *	None
 *
 * Side effects:
 *	Issues the jump with all correct stack management. May create another
 *	loop exception range; pointers to ExceptionRange and ExceptionAux
 *	loop exception range.  Pointers to ExceptionRange and ExceptionAux
 *	structures should not be held across this call.
 *
 *----------------------------------------------------------------------
 */

void
TclEmitInvoke(
4151
4152
4153
4154
4155
4156
4157
4158
4159


4160
4161
4162
4163


4164
4165
4166
4167
4168
4169
4170
4171

4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182


4183
4184
4185
4186
4187
4188
4189
4188
4189
4190
4191
4192
4193
4194


4195
4196

4197


4198
4199
4200
4201
4202
4203
4204
4205
4206

4207
4208
4209
4210
4211
4212
4213
4214
4215
4216


4217
4218
4219
4220
4221
4222
4223
4224
4225







-
-
+
+
-

-
-
+
+







-
+









-
-
+
+







	arg2 = 0;
	expandCount = 1;
	break;
    }
    va_end(argList);

    /*
     * Determine if we need to handle break and continue exceptions with a
     * special handling exception range (so that we can correctly unwind the
     * If the exceptions is for break or continue handle it with special
     * handling exception range so the stack may be correctly unwound.
     * stack).
     *
     * These must be done separately; they can be different (especially for
     * calls from inside a [for] increment clause).
     * These must be done separately since they can be different, especially
     * for calls from inside a [for] increment clause.
     */

    rangePtr = TclGetInnermostExceptionRange(envPtr, TCL_CONTINUE,
	    &auxContinuePtr);
    if (rangePtr == NULL || rangePtr->type != LOOP_EXCEPTION_RANGE) {
	auxContinuePtr = NULL;
    } else if (auxContinuePtr->stackDepth == envPtr->currStackDepth-wordCount
	    && auxContinuePtr->expandTarget == envPtr->expandCount-expandCount) {
	    && (auxContinuePtr->expandTarget+expandCount == envPtr->expandCount)) {
	auxContinuePtr = NULL;
    } else {
	continueRange = auxContinuePtr - envPtr->exceptAuxArrayPtr;
    }

    rangePtr = TclGetInnermostExceptionRange(envPtr, TCL_BREAK, &auxBreakPtr);
    if (rangePtr == NULL || rangePtr->type != LOOP_EXCEPTION_RANGE) {
	auxBreakPtr = NULL;
    } else if (auxContinuePtr == NULL
	    && auxBreakPtr->stackDepth == envPtr->currStackDepth-wordCount
	    && auxBreakPtr->expandTarget == envPtr->expandCount-expandCount) {
	    && auxBreakPtr->stackDepth+wordCount == envPtr->currStackDepth
	    && auxBreakPtr->expandTarget+expandCount == envPtr->expandCount) {
	auxBreakPtr = NULL;
    } else {
	breakRange = auxBreakPtr - envPtr->exceptAuxArrayPtr;
    }

    if (auxBreakPtr != NULL || auxContinuePtr != NULL) {
	loopRange = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr);
4221
4222
4223
4224
4225
4226
4227
4228
4229


4230
4231
4232
4233
4234
4235
4236
4257
4258
4259
4260
4261
4262
4263


4264
4265
4266
4267
4268
4269
4270
4271
4272







-
-
+
+








    /*
     * If we're generating a special wrapper exception range, we need to
     * finish that up now.
     */

    if (auxBreakPtr != NULL || auxContinuePtr != NULL) {
	int savedStackDepth = envPtr->currStackDepth;
	int savedExpandCount = envPtr->expandCount;
	size_t savedStackDepth = envPtr->currStackDepth;
	size_t savedExpandCount = envPtr->expandCount;
	JumpFixup nonTrapFixup;

	if (auxBreakPtr != NULL) {
	    auxBreakPtr = envPtr->exceptAuxArrayPtr + breakRange;
	}
	if (auxContinuePtr != NULL) {
	    auxContinuePtr = envPtr->exceptAuxArrayPtr + continueRange;
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
4412
4413
4414
4415
4416
4417
4418

4419
4420

4421
4422
4423

4424
4425
4426
4427

4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447

4448
4449


4450
4451
4452
4453
4454
4455
4456
4457







-
+

-
+


-
+



-
+


















+
-
+

-
-
+







}

/*
 *----------------------------------------------------------------------
 *
 * EncodeCmdLocMap --
 *
 *	Encode the command location information for some compiled code into a
 *	Encodes the command location information for some compiled code into a
 *	ByteCode structure. The encoded command location map is stored as
 *	three adjacent byte sequences.
 *	three-adjacent-byte sequences.
 *
 * Results:
 *	Pointer to the first byte after the encoded command location
 *	A pointer to the first byte after the encoded command location
 *	information.
 *
 * Side effects:
 *	The encoded information is stored into the block of memory headed by
 *	Stores encoded information into the block of memory headed by
 *	codePtr. Also records pointers to the start of the four byte sequences
 *	in fields in codePtr's ByteCode header structure.
 *
 *----------------------------------------------------------------------
 */

static unsigned char *
EncodeCmdLocMap(
    CompileEnv *envPtr,		/* Points to compilation environment structure
				 * containing the CmdLocation structure to
				 * encode. */
    ByteCode *codePtr,		/* ByteCode in which to encode envPtr's
				 * command location information. */
    unsigned char *startPtr)	/* Points to the first byte in codePtr's
				 * memory block where the location information
				 * is to be stored. */
{
    CmdLocation *mapPtr = envPtr->cmdMapPtr;
    Tcl_Size i, codeDelta, codeLen, srcLen, prevOffset;
    int numCmds = envPtr->numCommands;
    Tcl_Size numCmds = envPtr->numCommands;
    unsigned char *p = startPtr;
    int codeDelta, codeLen, srcDelta, srcLen, prevOffset;
    int i;
    int srcDelta;

    /*
     * Encode the code offset for each command as a sequence of deltas.
     */

    codePtr->codeDeltaStart = p;
    prevOffset = 0;
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509



4510
4511
4512
4513
4514
4515
4516
4536
4537
4538
4539
4540
4541
4542



4543
4544
4545
4546
4547
4548
4549
4550
4551
4552







-
-
-
+
+
+








#ifdef TCL_COMPILE_STATS
/*
 *----------------------------------------------------------------------
 *
 * RecordByteCodeStats --
 *
 *	Accumulates various compilation-related statistics for each newly
 *	compiled ByteCode. Called by the TclInitByteCodeObj when Tcl is
 *	compiled with the -DTCL_COMPILE_STATS flag
 *	Accumulates compilation-related statistics for each newly-compiled
 *	ByteCode. Called by the TclInitByteCodeObj when Tcl is compiled with
 *	the -DTCL_COMPILE_STATS flag
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Accumulates aggregate code-related statistics in the interpreter's
 *	ByteCodeStats structure. Records statistics specific to a ByteCode in
4530
4531
4532
4533
4534
4535
4536
4537

4538
4539

4540
4541
4542

4543
4544
4545
4546
4547
4548
4549
4566
4567
4568
4569
4570
4571
4572

4573
4574

4575
4576
4577

4578
4579
4580
4581
4582
4583
4584
4585







-
+

-
+


-
+







    if (iPtr == NULL) {
	/* Avoid segfaulting in case we're called in a deleted interp */
	return;
    }
    statsPtr = &(iPtr->stats);

    statsPtr->numCompilations++;
    statsPtr->totalSrcBytes += (double) codePtr->numSrcBytes;
    statsPtr->totalSrcBytes += (double)codePtr->numSrcBytes;
    statsPtr->totalByteCodeBytes += (double) codePtr->structureSize;
    statsPtr->currentSrcBytes += (double) codePtr->numSrcBytes;
    statsPtr->currentSrcBytes += (double) (int)codePtr->numSrcBytes;
    statsPtr->currentByteCodeBytes += (double) codePtr->structureSize;

    statsPtr->srcCount[TclLog2(codePtr->numSrcBytes)]++;
    statsPtr->srcCount[TclLog2((int)codePtr->numSrcBytes)]++;
    statsPtr->byteCodeCount[TclLog2((int) codePtr->structureSize)]++;

    statsPtr->currentInstBytes += (double) codePtr->numCodeBytes;
    statsPtr->currentLitBytes += (double)
	    codePtr->numLitObjects * sizeof(Tcl_Obj *);
    statsPtr->currentExceptBytes += (double)
	    codePtr->numExceptRanges * sizeof(ExceptionRange);

Changes to generic/tclCompile.h.

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
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







-
+











-
+







 * what level of tracing is desired:
 *    0: no compilation tracing
 *    1: summarize compilation of top level cmds and proc bodies
 *    2: display all instructions of each ByteCode compiled
 * This variable is linked to the Tcl variable "tcl_traceCompile".
 */

MODULE_SCOPE int 	tclTraceCompile;
MODULE_SCOPE int	tclTraceCompile;

/*
 * Variable that controls whether execution tracing is enabled and, if so,
 * what level of tracing is desired:
 *    0: no execution tracing
 *    1: trace invocations of Tcl procs only
 *    2: trace invocations of all (not compiled away) commands
 *    3: display each instruction executed
 * This variable is linked to the Tcl variable "tcl_traceExec".
 */

MODULE_SCOPE int 	tclTraceExec;
MODULE_SCOPE int	tclTraceExec;
#endif

/*
 * The type of lambda expressions. Note that every lambda will *always* have a
 * string representation.
 */

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
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







-
+


-
+

-
-
+
+

-
-
-
+
+
+


-
+















-
+



-
+




-
+




-
+


-
+





-
-
+
+


+
-
+





+
-
+











-
-
-
-
+
+
+
+














-
-
-
+
+
+

-
+






-
+





-
-
+
+

















-
-
-
-
-
+
+
+
+
+







    CATCH_EXCEPTION_RANGE	/* Exception's range is controlled by a catch
				 * command. Errors in the range cause a jump
				 * to a catch PC offset. */
} ExceptionRangeType;

typedef struct {
    ExceptionRangeType type;	/* The kind of ExceptionRange. */
    int nestingLevel;		/* Static depth of the exception range. Used
    Tcl_Size nestingLevel;	/* Static depth of the exception range. Used
				 * to find the most deeply-nested range
				 * surrounding a PC at runtime. */
    int codeOffset;		/* Offset of the first instruction byte of the
    Tcl_Size codeOffset;	/* Offset of the first instruction byte of the
				 * code range. */
    int numCodeBytes;		/* Number of bytes in the code range. */
    int breakOffset;		/* If LOOP_EXCEPTION_RANGE, the target PC
    Tcl_Size numCodeBytes;	/* Number of bytes in the code range. */
    Tcl_Size breakOffset;	/* If LOOP_EXCEPTION_RANGE, the target PC
				 * offset for a break command in the range. */
    int continueOffset;		/* If LOOP_EXCEPTION_RANGE and not -1, the
				 * target PC offset for a continue command in
				 * the code range. Otherwise, ignore this
    Tcl_Size continueOffset;	/* If LOOP_EXCEPTION_RANGE and not TCL_INDEX_NONE,
				 * the target PC offset for a continue command
				 * in the code range. Otherwise, ignore this
				 * range when processing a continue
				 * command. */
    int catchOffset;		/* If a CATCH_EXCEPTION_RANGE, the target PC
    Tcl_Size catchOffset;	/* If a CATCH_EXCEPTION_RANGE, the target PC
				 * offset for any "exception" in range. */
} ExceptionRange;

/*
 * Auxiliary data used when issuing (currently just loop) exception ranges,
 * but which is not required during execution.
 */

typedef struct ExceptionAux {
    int supportsContinue;	/* Whether this exception range will have a
				 * continueOffset created for it; if it is a
				 * loop exception range that *doesn't* have
				 * one (see [for] next-clause) then we must
				 * not pick up the range when scanning for a
				 * target to continue to. */
    int stackDepth;		/* The stack depth at the point where the
    Tcl_Size stackDepth;	/* The stack depth at the point where the
				 * exception range was created. This is used
				 * to calculate the number of POPs required to
				 * restore the stack to its prior state. */
    int expandTarget;		/* The number of expansions expected on the
    Tcl_Size expandTarget;	/* The number of expansions expected on the
				 * auxData stack at the time the loop starts;
				 * we can't currently discard them except by
				 * doing INST_INVOKE_EXPANDED; this is a known
				 * problem. */
    int expandTargetDepth;	/* The stack depth expected at the outermost
    Tcl_Size expandTargetDepth;	/* The stack depth expected at the outermost
				 * expansion within the loop. Not meaningful
				 * if there are no open expansions between the
				 * looping level and the point of jump
				 * issue. */
    int numBreakTargets;	/* The number of [break]s that want to be
    Tcl_Size numBreakTargets;	/* The number of [break]s that want to be
				 * targeted to the place where this loop
				 * exception will be bound to. */
    unsigned int *breakTargets;	/* The offsets of the INST_JUMP4 instructions
    TCL_HASH_TYPE *breakTargets;/* The offsets of the INST_JUMP4 instructions
				 * issued by the [break]s that we must
				 * update. Note that resizing a jump (via
				 * TclFixupForwardJump) can cause the contents
				 * of this array to be updated. When
				 * numBreakTargets==0, this is NULL. */
    int allocBreakTargets;	/* The size of the breakTargets array. */
    int numContinueTargets;	/* The number of [continue]s that want to be
    Tcl_Size allocBreakTargets;	/* The size of the breakTargets array. */
    Tcl_Size numContinueTargets;/* The number of [continue]s that want to be
				 * targeted to the place where this loop
				 * exception will be bound to. */
    TCL_HASH_TYPE *continueTargets;
    unsigned int *continueTargets; /* The offsets of the INST_JUMP4 instructions
				/* The offsets of the INST_JUMP4 instructions
				 * issued by the [continue]s that we must
				 * update. Note that resizing a jump (via
				 * TclFixupForwardJump) can cause the contents
				 * of this array to be updated. When
				 * numContinueTargets==0, this is NULL. */
    Tcl_Size allocContinueTargets;
    int allocContinueTargets;	/* The size of the continueTargets array. */
				/* The size of the continueTargets array. */
} ExceptionAux;

/*
 * Structure used to map between instruction pc and source locations. It
 * defines for each compiled Tcl command its code's starting offset and its
 * source's starting offset and length. Note that the code offset increases
 * monotonically: that is, the table is sorted in code offset order. The
 * source offset is not monotonic.
 */

typedef struct {
    int codeOffset;		/* Offset of first byte of command code. */
    int numCodeBytes;		/* Number of bytes for command's code. */
    int srcOffset;		/* Offset of first char of the command. */
    int numSrcBytes;		/* Number of command source chars. */
    Tcl_Size codeOffset;	/* Offset of first byte of command code. */
    Tcl_Size numCodeBytes;	/* Number of bytes for command's code. */
    Tcl_Size srcOffset;		/* Offset of first char of the command. */
    Tcl_Size numSrcBytes;	/* Number of command source chars. */
} CmdLocation;

/*
 * TIP #280
 * Structure to record additional location information for byte code. This
 * information is internal and not saved. i.e. tbcload'ed code will not have
 * this information. It records the lines for all words of all commands found
 * in the byte code. The association with a ByteCode structure BC is done
 * through the 'lineBCPtr' HashTable in Interp, keyed by the address of BC.
 * Also recorded is information coming from the context, i.e. type of the
 * frame and associated information, like the path of a sourced file.
 */

typedef struct {
    size_t srcOffset;		/* Command location to find the entry. */
    int nline;			/* Number of words in the command */
    int *line;			/* Line information for all words in the
    Tcl_Size srcOffset;		/* Command location to find the entry. */
    Tcl_Size nline;		/* Number of words in the command */
    Tcl_Size *line;		/* Line information for all words in the
				 * command. */
    int **next;			/* Transient information used by the compiler
    Tcl_Size **next;		/* Transient information used by the compiler
				 * for tracking of hidden continuation
				 * lines. */
} ECL;

typedef struct {
    int type;			/* Context type. */
    int start;			/* Starting line for compiled script. Needed
    Tcl_Size start;		/* Starting line for compiled script. Needed
				 * for the extended recompile check in
				 * tclCompileObj. */
    Tcl_Obj *path;		/* Path of the sourced file the command is
				 * in. */
    ECL *loc;			/* Command word locations (lines). */
    int nloc;			/* Number of allocated entries in 'loc'. */
    int nuloc;			/* Number of used entries in 'loc'. */
    Tcl_Size nloc;		/* Number of allocated entries in 'loc'. */
    Tcl_Size nuloc;		/* Number of used entries in 'loc'. */
} ExtCmdLoc;

/*
 * CompileProcs need the ability to record information during compilation that
 * can be used by bytecode instructions during execution. The AuxData
 * structure provides this "auxiliary data" mechanism. An arbitrary number of
 * these structures can be stored in the ByteCode record (during compilation
 * they are stored in a CompileEnv structure). Each AuxData record holds one
 * word of client-specified data (often a pointer) and is given an index that
 * instructions can later use to look up the structure and its data.
 *
 * The following definitions declare the types of procedures that are called
 * to duplicate or free this auxiliary data when the containing ByteCode
 * objects are duplicated and freed. Pointers to these procedures are kept in
 * the AuxData structure.
 */

typedef void *(AuxDataDupProc)  (void *clientData);
typedef void	   (AuxDataFreeProc) (void *clientData);
typedef void	   (AuxDataPrintProc)(void *clientData,
			    Tcl_Obj *appendObj, struct ByteCode *codePtr,
			    unsigned int pcOffset);
typedef void *	(AuxDataDupProc) (void *clientData);
typedef void	(AuxDataFreeProc) (void *clientData);
typedef void	(AuxDataPrintProc) (void *clientData,
	Tcl_Obj *appendObj, struct ByteCode *codePtr,
	TCL_HASH_TYPE pcOffset);

/*
 * We define a separate AuxDataType struct to hold type-related information
 * for the AuxData structure. This separation makes it possible for clients
 * outside of the TCL core to manipulate (in a limited fashion!) AuxData; for
 * example, it makes it possible to pickle and unpickle AuxData structs.
 */
262
263
264
265
266
267
268
269

270
271
272
273
274
275
276
264
265
266
267
268
269
270

271
272
273
274
275
276
277
278







-
+







 * during compilation by CompileProcs and used by instructions during
 * execution.
 */

typedef struct AuxData {
    const AuxDataType *type;	/* Pointer to the AuxData type associated with
				 * this ClientData. */
    void *clientData;	/* The compilation data itself. */
    void *clientData;		/* The compilation data itself. */
} AuxData;

/*
 * Structure defining the compilation environment. After compilation, fields
 * describing bytecode instructions are copied out into the more compact
 * ByteCode structure defined below.
 */
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
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
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


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







-
+





-
-
-
-
-
-
+
+
+
+
+
+
+
+


-
+











+
+
+
+

-
-
-
+
+
+



-
+

-
+



-
+

+
-
+
-
+









-
+


+
+
+
+

-
+



-
-
+
+
+
-
+
















-
+








-
+



-
+







				 * compiled. Commands and their compile procs
				 * are specific to an interpreter so the code
				 * emitted will depend on the interpreter. */
    const char *source;		/* The source string being compiled by
				 * SetByteCodeFromAny. This pointer is not
				 * owned by the CompileEnv and must not be
				 * freed or changed by it. */
    int numSrcBytes;		/* Number of bytes in source. */
    Tcl_Size numSrcBytes;	/* Number of bytes in source. */
    Proc *procPtr;		/* If a procedure is being compiled, a pointer
				 * to its Proc structure; otherwise NULL. Used
				 * to compile local variables. Set from
				 * information provided by ObjInterpProc in
				 * tclProc.c. */
    int numCommands;		/* Number of commands compiled. */
    int exceptDepth;		/* Current exception range nesting level; -1
				 * if not in any range currently. */
    int maxExceptDepth;		/* Max nesting level of exception ranges; -1
				 * if no ranges have been compiled. */
    int maxStackDepth;		/* Maximum number of stack elements needed to
    Tcl_Size numCommands;	/* Number of commands compiled. */
    Tcl_Size exceptDepth;	/* Current exception range nesting level;
				 * TCL_INDEX_NONE if not in any range
				 * currently. */
    Tcl_Size maxExceptDepth;	/* Max nesting level of exception ranges;
				 * TCL_INDEX_NONE if no ranges have been
				 * compiled. */
    Tcl_Size maxStackDepth;	/* Maximum number of stack elements needed to
				 * execute the code. Set by compilation
				 * procedures before returning. */
    int currStackDepth;		/* Current stack depth. */
    Tcl_Size currStackDepth;	/* Current stack depth. */
    LiteralTable localLitTable;	/* Contains LiteralEntry's describing all Tcl
				 * objects referenced by this compiled code.
				 * Indexed by the string representations of
				 * the literals. Used to avoid creating
				 * duplicate objects. */
    unsigned char *codeStart;	/* Points to the first byte of the code. */
    unsigned char *codeNext;	/* Points to next code array byte to use. */
    unsigned char *codeEnd;	/* Points just after the last allocated code
				 * array byte. */
    int mallocedCodeArray;	/* Set 1 if code array was expanded and
				 * codeStart points into the heap.*/
#if TCL_MAJOR_VERSION > 8
    int mallocedExceptArray;	/* 1 if ExceptionRange array was expanded and
				 * exceptArrayPtr points in heap, else 0. */
#endif
    LiteralEntry *literalArrayPtr;
    				/* Points to start of LiteralEntry array. */
    int literalArrayNext;	/* Index of next free object array entry. */
    int literalArrayEnd;	/* Index just after last obj array entry. */
				/* Points to start of LiteralEntry array. */
    Tcl_Size literalArrayNext;	/* Index of next free object array entry. */
    Tcl_Size literalArrayEnd;	/* Index just after last obj array entry. */
    int mallocedLiteralArray;	/* 1 if object array was expanded and objArray
				 * points into the heap, else 0. */
    ExceptionRange *exceptArrayPtr;
    				/* Points to start of the ExceptionRange
				/* Points to start of the ExceptionRange
				 * array. */
    int exceptArrayNext;	/* Next free ExceptionRange array index.
    Tcl_Size exceptArrayNext;	/* Next free ExceptionRange array index.
				 * exceptArrayNext is the number of ranges and
				 * (exceptArrayNext-1) is the index of the
				 * current range's array entry. */
    int exceptArrayEnd;		/* Index after the last ExceptionRange array
    Tcl_Size exceptArrayEnd;	/* Index after the last ExceptionRange array
				 * entry. */
#if TCL_MAJOR_VERSION < 9
    int mallocedExceptArray;	/* 1 if ExceptionRange array was expanded and
    int mallocedExceptArray;
				 * exceptArrayPtr points in heap, else 0. */
#endif
    ExceptionAux *exceptAuxArrayPtr;
				/* Array of information used to restore the
				 * state when processing BREAK/CONTINUE
				 * exceptions. Must be the same size as the
				 * exceptArrayPtr. */
    CmdLocation *cmdMapPtr;	/* Points to start of CmdLocation array.
				 * numCommands is the index of the next entry
				 * to use; (numCommands-1) is the entry index
				 * for the last command. */
    int cmdMapEnd;		/* Index after last CmdLocation entry. */
    Tcl_Size cmdMapEnd;		/* Index after last CmdLocation entry. */
    int mallocedCmdMap;		/* 1 if command map array was expanded and
				 * cmdMapPtr points in the heap, else 0. */
#if TCL_MAJOR_VERSION > 8
    int mallocedAuxDataArray;	/* 1 if aux data array was expanded and
				 * auxDataArrayPtr points in heap else 0. */
#endif
    AuxData *auxDataArrayPtr;	/* Points to auxiliary data array start. */
    int auxDataArrayNext;	/* Next free compile aux data array index.
    Tcl_Size auxDataArrayNext;	/* Next free compile aux data array index.
				 * auxDataArrayNext is the number of aux data
				 * items and (auxDataArrayNext-1) is index of
				 * current aux data array entry. */
    int auxDataArrayEnd;	/* Index after last aux data array entry. */
    int mallocedAuxDataArray;	/* 1 if aux data array was expanded and
    Tcl_Size auxDataArrayEnd;	/* Index after last aux data array entry. */
#if TCL_MAJOR_VERSION < 9
    int mallocedAuxDataArray;
				 * auxDataArrayPtr points in heap else 0. */
#endif
    unsigned char staticCodeSpace[COMPILEENV_INIT_CODE_BYTES];
				/* Initial storage for code. */
    LiteralEntry staticLiteralSpace[COMPILEENV_INIT_NUM_OBJECTS];
				/* Initial storage of LiteralEntry array. */
    ExceptionRange staticExceptArraySpace[COMPILEENV_INIT_EXCEPT_RANGES];
				/* Initial ExceptionRange array storage. */
    ExceptionAux staticExAuxArraySpace[COMPILEENV_INIT_EXCEPT_RANGES];
				/* Initial static except auxiliary info array
				 * storage. */
    CmdLocation staticCmdMapSpace[COMPILEENV_INIT_CMD_MAP_SIZE];
				/* Initial storage for cmd location map. */
    AuxData staticAuxDataArraySpace[COMPILEENV_INIT_AUX_DATA_SIZE];
				/* Initial storage for aux data array. */
    /* TIP #280 */
    ExtCmdLoc *extCmdMapPtr;	/* Extended command location information for
				 * 'info frame'. */
    int line;			/* First line of the script, based on the
    Tcl_Size line;		/* First line of the script, based on the
				 * invoking context, then the line of the
				 * command currently compiled. */
    int atCmdStart;		/* Flag to say whether an INST_START_CMD
				 * should be issued; they should never be
				 * issued repeatedly, as that is significantly
				 * inefficient. If set to 2, that instruction
				 * should not be issued at all (by the generic
				 * part of the command compiler). */
    int expandCount;		/* Number of INST_EXPAND_START instructions
    Tcl_Size expandCount;	/* Number of INST_EXPAND_START instructions
				 * encountered that have not yet been paired
				 * with a corresponding
				 * INST_INVOKE_EXPANDED. */
    int *clNext;		/* If not NULL, it refers to the next slot in
    Tcl_Size *clNext;		/* If not NULL, it refers to the next slot in
				 * clLoc to check for an invisible
				 * continuation line. */
} CompileEnv;

/*
 * The structure defining the bytecode instructions resulting from compiling a
 * Tcl script. Note that this structure is variable length: a single heap
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
467
468
469
470
471

472
473
474
475
476
477
478
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
467
468
469
470
471
472
473



474
475
476
477
478
479
480
481
482
483
484

485
486
487
488
489
490
491
492







-
+







-
+



-
+




-
+














-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
+
+
+








-
+








typedef struct ByteCode {
    TclHandle interpHandle;	/* Handle for interpreter containing the
				 * compiled code. Commands and their compile
				 * procs are specific to an interpreter so the
				 * code emitted will depend on the
				 * interpreter. */
    size_t compileEpoch;	/* Value of iPtr->compileEpoch when this
    Tcl_Size compileEpoch;	/* Value of iPtr->compileEpoch when this
				 * ByteCode was compiled. Used to invalidate
				 * code when, e.g., commands with compile
				 * procs are redefined. */
    Namespace *nsPtr;		/* Namespace context in which this code was
				 * compiled. If the code is executed if a
				 * different namespace, it must be
				 * recompiled. */
    size_t nsEpoch;		/* Value of nsPtr->resolverEpoch when this
    Tcl_Size nsEpoch;		/* Value of nsPtr->resolverEpoch when this
				 * ByteCode was compiled. Used to invalidate
				 * code when new namespace resolution rules
				 * are put into effect. */
    size_t refCount;		/* Reference count: set 1 when created plus 1
    Tcl_Size refCount;		/* Reference count: set 1 when created plus 1
				 * for each execution of the code currently
				 * active. This structure can be freed when
				 * refCount becomes zero. */
    unsigned int flags;		/* flags describing state for the codebyte.
				 * this variable holds ORed values from the
				 * this variable holds OR'ed values from the
				 * TCL_BYTECODE_ masks defined above */
    const char *source;		/* The source string from which this ByteCode
				 * was compiled. Note that this pointer is not
				 * owned by the ByteCode and must not be freed
				 * or modified by it. */
    Proc *procPtr;		/* If the ByteCode was compiled from a
				 * procedure body, this is a pointer to its
				 * Proc structure; otherwise NULL. This
				 * pointer is also not owned by the ByteCode
				 * and must not be freed by it. */
    size_t structureSize;	/* Number of bytes in the ByteCode structure
				 * itself. Does not include heap space for
				 * literal Tcl objects or storage referenced
				 * by AuxData entries. */
    int numCommands;		/* Number of commands compiled. */
    int numSrcBytes;		/* Number of source bytes compiled. */
    int numCodeBytes;		/* Number of code bytes. */
    int numLitObjects;		/* Number of objects in literal array. */
    int numExceptRanges;	/* Number of ExceptionRange array elems. */
    int numAuxDataItems;	/* Number of AuxData items. */
    int numCmdLocBytes;		/* Number of bytes needed for encoded command
    Tcl_Size numCommands;	/* Number of commands compiled. */
    Tcl_Size numSrcBytes;	/* Number of source bytes compiled. */
    Tcl_Size numCodeBytes;	/* Number of code bytes. */
    Tcl_Size numLitObjects;	/* Number of objects in literal array. */
    Tcl_Size numExceptRanges;	/* Number of ExceptionRange array elems. */
    Tcl_Size numAuxDataItems;	/* Number of AuxData items. */
    Tcl_Size numCmdLocBytes;	/* Number of bytes needed for encoded command
				 * location information. */
    int maxExceptDepth;		/* Maximum nesting level of ExceptionRanges;
				 * -1 if no ranges were compiled. */
    int maxStackDepth;		/* Maximum number of stack elements needed to
    Tcl_Size maxExceptDepth;	/* Maximum nesting level of ExceptionRanges;
				 * TCL_INDEX_NONE if no ranges were compiled. */
    Tcl_Size maxStackDepth;	/* Maximum number of stack elements needed to
				 * execute the code. */
    unsigned char *codeStart;	/* Points to the first byte of the code. This
				 * is just after the final ByteCode member
				 * cmdMapPtr. */
    Tcl_Obj **objArrayPtr;	/* Points to the start of the literal object
				 * array. This is just after the last code
				 * byte. */
    ExceptionRange *exceptArrayPtr;
    				/* Points to the start of the ExceptionRange
				/* Points to the start of the ExceptionRange
				 * array. This is just after the last object
				 * in the object array. */
    AuxData *auxDataArrayPtr;	/* Points to the start of the auxiliary data
				 * array. This is just after the last entry in
				 * the ExceptionRange array. */
    unsigned char *codeDeltaStart;
				/* Points to the first of a sequence of bytes
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
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







-
+

-
+


-
+


-
-
-
+

-
-
-
+
+
+







				 * variables. */
#ifdef TCL_COMPILE_STATS
    Tcl_Time createTime;	/* Absolute time when the ByteCode was
				 * created. */
#endif /* TCL_COMPILE_STATS */
} ByteCode;

#define ByteCodeSetIntRep(objPtr, typePtr, codePtr)			\
#define ByteCodeSetInternalRep(objPtr, typePtr, codePtr) \
    do {								\
	Tcl_ObjIntRep ir;						\
	Tcl_ObjInternalRep ir;						\
	ir.twoPtrValue.ptr1 = (codePtr);				\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreIntRep((objPtr), (typePtr), &ir);			\
	Tcl_StoreInternalRep((objPtr), (typePtr), &ir);			\
    } while (0)



#define ByteCodeGetIntRep(objPtr, typePtr, codePtr)			\
#define ByteCodeGetInternalRep(objPtr, typePtr, codePtr) \
    do {								\
	const Tcl_ObjIntRep *irPtr;					\
	irPtr = TclFetchIntRep((objPtr), (typePtr));			\
	(codePtr) = irPtr ? (ByteCode*)irPtr->twoPtrValue.ptr1 : NULL;		\
	const Tcl_ObjInternalRep *irPtr;				\
	irPtr = TclFetchInternalRep((objPtr), (typePtr));		\
	(codePtr) = irPtr ? (ByteCode*)irPtr->twoPtrValue.ptr1 : NULL;	\
    } while (0)

/*
 * Opcodes for the Tcl bytecode instructions. These must correspond to the
 * entries in the table of instruction descriptions, tclInstructionTable, in
 * tclCompile.c. Also, the order and number of the expression opcodes (e.g.,
 * INST_BITOR) must match the entries in the array operatorStrings in
815
816
817
818
819
820
821
822
823
824
825
826











827
828
829
830
831
832
833
827
828
829
830
831
832
833





834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851







-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+







    INST_LAPPEND_LIST_ARRAY_STK,
    INST_LAPPEND_LIST_STK,

    INST_CLOCK_READ,

    INST_DICT_GET_DEF,

	/* TIP 461 */
	INST_STR_LT,
	INST_STR_GT,
	INST_STR_LE,
	INST_STR_GE,
    /* TIP 461 */
    INST_STR_LT,
    INST_STR_GT,
    INST_STR_LE,
    INST_STR_GE,

    INST_LREPLACE4,

    /* TIP 667: const */
    INST_CONST_IMM,
    INST_CONST_STK,

    /* The last opcode */
    LAST_INST_OPCODE
};

/*
 * Table describing the Tcl bytecode instructions: their name (for displaying
861
862
863
864
865
866
867
868

869
870
871
872
873
874
875
879
880
881
882
883
884
885

886
887
888
889
890
891
892
893







-
+







    OPERAND_LIT4,		/* Four byte unsigned index into table of
				 * literals. */
    OPERAND_SCLS1		/* Index into tclStringClassTable. */
} InstOperandType;

typedef struct InstructionDesc {
    const char *name;		/* Name of instruction. */
    size_t numBytes;		/* Total number of bytes for instruction. */
    Tcl_Size numBytes;		/* Total number of bytes for instruction. */
    int stackEffect;		/* The worst-case balance stack effect of the
				 * instruction, used for stack requirements
				 * computations. The value INT_MIN signals
				 * that the instruction's worst case effect is
				 * (1-opnd1). */
    int numOperands;		/* Number of operands. */
    InstOperandType opTypes[MAX_INSTRUCTION_OPERANDS];
896
897
898
899
900
901
902
903

904
905
906
907
908
909
910
914
915
916
917
918
919
920

921
922
923
924
925
926
927
928







-
+







    STR_CLASS_PRINT,		/* Unicode printing characters, including
				 * spaces. */
    STR_CLASS_PUNCT,		/* Unicode punctuation characters. */
    STR_CLASS_SPACE,		/* Unicode space characters. */
    STR_CLASS_UPPER,		/* Unicode upper-case alphabet characters. */
    STR_CLASS_WORD,		/* Unicode word (alphabetic, digit, connector
				 * punctuation) characters. */
    STR_CLASS_XDIGIT		/* Characters that can be used as digits in
    STR_CLASS_XDIGIT,		/* Characters that can be used as digits in
				 * hexadecimal numbers ([0-9A-Fa-f]). */
} InstStringClassType;

typedef struct StringClassDesc {
    char name[8];		/* Name of the class. */
    int (*comparator)(int);	/* Function to test if a single unicode
				 * character is a member of the class. */
948
949
950
951
952
953
954
955
956


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
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







-
-
+
+














-
-
+
+
+















-
+

-
+

-
+



-
+
+







				 * to 5 bytes. */
} JumpFixup;

#define JUMPFIXUP_INIT_ENTRIES	10

typedef struct JumpFixupArray {
    JumpFixup *fixup;		/* Points to start of jump fixup array. */
    int next;			/* Index of next free array entry. */
    int end;			/* Index of last usable entry in array. */
    Tcl_Size next;		/* Index of next free array entry. */
    Tcl_Size end;		/* Index of last usable entry in array. */
    int mallocedArray;		/* 1 if array was expanded and fixups points
				 * into the heap, else 0. */
    JumpFixup staticFixupSpace[JUMPFIXUP_INIT_ENTRIES];
				/* Initial storage for jump fixup array. */
} JumpFixupArray;

/*
 * The structure describing one variable list of a foreach command. Note that
 * only foreach commands inside procedure bodies are compiled inline so a
 * ForeachVarList structure always describes local variables. Furthermore,
 * only scalar variables are supported for inline-compiled foreach loops.
 */

typedef struct ForeachVarList {
    int numVars;		/* The number of variables in the list. */
    int varIndexes[TCLFLEXARRAY];/* An array of the indexes ("slot numbers")
    Tcl_Size numVars;		/* The number of variables in the list. */
    Tcl_Size varIndexes[TCLFLEXARRAY];
				/* An array of the indexes ("slot numbers")
				 * for each variable in the procedure's array
				 * of local variables. Only scalar variables
				 * are supported. The actual size of this
				 * field will be large enough to numVars
				 * indexes. THIS MUST BE THE LAST FIELD IN THE
				 * STRUCTURE! */
} ForeachVarList;

/*
 * Structure used to hold information about a foreach command that is needed
 * during program execution. These structures are stored in CompileEnv and
 * ByteCode structures as auxiliary data.
 */

typedef struct ForeachInfo {
    int numLists;		/* The number of both the variable and value
    Tcl_Size numLists;		/* The number of both the variable and value
				 * lists of the foreach command. */
    int firstValueTemp;		/* Index of the first temp var in a proc frame
    Tcl_Size firstValueTemp;	/* Index of the first temp var in a proc frame
				 * used to point to a value list. */
    int loopCtTemp;		/* Index of temp var in a proc frame holding
    Tcl_Size loopCtTemp;	/* Index of temp var in a proc frame holding
				 * the loop's iteration count. Used to
				 * determine next value list element to assign
				 * each loop var. */
    ForeachVarList *varLists[TCLFLEXARRAY];/* An array of pointers to ForeachVarList
    ForeachVarList *varLists[TCLFLEXARRAY];
				/* An array of pointers to ForeachVarList
				 * structures describing each var list. The
				 * actual size of this field will be large
				 * enough to numVars indexes. THIS MUST BE THE
				 * LAST FIELD IN THE STRUCTURE! */
} ForeachInfo;

/*
1019
1020
1021
1022
1023
1024
1025
1026
1027



1028
1029
1030
1031
1032
1033
1034
1039
1040
1041
1042
1043
1044
1045


1046
1047
1048
1049
1050
1051
1052
1053
1054
1055







-
-
+
+
+







/*
 * Structure used to hold information about a [dict update] command that is
 * needed during program execution. These structures are stored in CompileEnv
 * and ByteCode structures as auxiliary data.
 */

typedef struct {
    size_t length;		/* Size of array */
    int varIndices[TCLFLEXARRAY];		/* Array of variable indices to manage when
    Tcl_Size length;		/* Size of array */
    Tcl_Size varIndices[TCLFLEXARRAY];
				/* Array of variable indices to manage when
				 * processing the start and end of a [dict
				 * update]. There is really more than one
				 * entry, and the structure is allocated to
				 * take account of this. MUST BE LAST FIELD IN
				 * STRUCTURE. */
} DictUpdateInfo;

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
1116
1117
1118
1119


1120
1121
1122
1123
1124
1125
1126
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

1116
1117
1118
1119

1120
1121

1122
1123
1124
1125

1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139


1140
1141
1142
1143
1144
1145
1146
1147
1148







+



















-
+




-
+


-
+

-
+





-
+




-
+



-
+

-
+



-
+













-
-
+
+








/*
 *----------------------------------------------------------------
 * Procedures exported by tclBasic.c to be used within the engine.
 *----------------------------------------------------------------
 */

#if TCL_MAJOR_VERSION > 8
MODULE_SCOPE Tcl_ObjCmdProc	TclNRInterpCoroutine;

/*
 *----------------------------------------------------------------
 * Procedures exported by the engine to be used by tclBasic.c
 *----------------------------------------------------------------
 */

MODULE_SCOPE ByteCode *	TclCompileObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    const CmdFrame *invoker, int word);

/*
 *----------------------------------------------------------------
 * Procedures shared among Tcl bytecode compilation and execution modules but
 * not used outside:
 *----------------------------------------------------------------
 */

MODULE_SCOPE int	TclAttemptCompileProc(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, int depth, Command *cmdPtr,
			    Tcl_Parse *parsePtr, Tcl_Size depth, Command *cmdPtr,
			    CompileEnv *envPtr);
MODULE_SCOPE void	TclCleanupStackForBreakContinue(CompileEnv *envPtr,
			    ExceptionAux *auxPtr);
MODULE_SCOPE void	TclCompileCmdWord(Tcl_Interp *interp,
			    Tcl_Token *tokenPtr, int count,
			    Tcl_Token *tokenPtr, size_t count,
			    CompileEnv *envPtr);
MODULE_SCOPE void	TclCompileExpr(Tcl_Interp *interp, const char *script,
			    size_t numBytes, CompileEnv *envPtr, int optimize);
			    Tcl_Size numBytes, CompileEnv *envPtr, int optimize);
MODULE_SCOPE void	TclCompileExprWords(Tcl_Interp *interp,
			    Tcl_Token *tokenPtr, int numWords,
			    Tcl_Token *tokenPtr, size_t numWords,
			    CompileEnv *envPtr);
MODULE_SCOPE void	TclCompileInvocation(Tcl_Interp *interp,
			    Tcl_Token *tokenPtr, Tcl_Obj *cmdObj, size_t numWords,
			    CompileEnv *envPtr);
MODULE_SCOPE void	TclCompileScript(Tcl_Interp *interp,
			    const char *script, size_t numBytes,
			    const char *script, Tcl_Size numBytes,
			    CompileEnv *envPtr);
MODULE_SCOPE void	TclCompileSyntaxError(Tcl_Interp *interp,
			    CompileEnv *envPtr);
MODULE_SCOPE void	TclCompileTokens(Tcl_Interp *interp,
			    Tcl_Token *tokenPtr, int count,
			    Tcl_Token *tokenPtr, size_t count,
			    CompileEnv *envPtr);
MODULE_SCOPE void	TclCompileVarSubst(Tcl_Interp *interp,
			    Tcl_Token *tokenPtr, CompileEnv *envPtr);
MODULE_SCOPE int	TclCreateAuxData(void *clientData,
MODULE_SCOPE Tcl_Size	TclCreateAuxData(void *clientData,
			    const AuxDataType *typePtr, CompileEnv *envPtr);
MODULE_SCOPE int	TclCreateExceptRange(ExceptionRangeType type,
MODULE_SCOPE Tcl_Size	TclCreateExceptRange(ExceptionRangeType type,
			    CompileEnv *envPtr);
MODULE_SCOPE ExecEnv *	TclCreateExecEnv(Tcl_Interp *interp, size_t size);
MODULE_SCOPE Tcl_Obj *	TclCreateLiteral(Interp *iPtr, const char *bytes,
			    size_t length, size_t hash, int *newPtr,
			    Tcl_Size length, size_t hash, int *newPtr,
			    Namespace *nsPtr, int flags,
			    LiteralEntry **globalPtrPtr);
MODULE_SCOPE void	TclDeleteExecEnv(ExecEnv *eePtr);
MODULE_SCOPE void	TclDeleteLiteralTable(Tcl_Interp *interp,
			    LiteralTable *tablePtr);
MODULE_SCOPE void	TclEmitForwardJump(CompileEnv *envPtr,
			    TclJumpType jumpType, JumpFixup *jumpFixupPtr);
MODULE_SCOPE void	TclEmitInvoke(CompileEnv *envPtr, int opcode, ...);
MODULE_SCOPE ExceptionRange * TclGetExceptionRangeForPc(unsigned char *pc,
			    int catchOnly, ByteCode *codePtr);
MODULE_SCOPE void	TclExpandJumpFixupArray(JumpFixupArray *fixupArrayPtr);
MODULE_SCOPE int	TclNRExecuteByteCode(Tcl_Interp *interp,
			    ByteCode *codePtr);
MODULE_SCOPE Tcl_Obj *	TclFetchLiteral(CompileEnv *envPtr, size_t index);
MODULE_SCOPE int	TclFindCompiledLocal(const char *name, size_t nameChars,
MODULE_SCOPE Tcl_Obj *	TclFetchLiteral(CompileEnv *envPtr, Tcl_Size index);
MODULE_SCOPE Tcl_Size	TclFindCompiledLocal(const char *name, Tcl_Size nameChars,
			    int create, CompileEnv *envPtr);
MODULE_SCOPE int	TclFixupForwardJump(CompileEnv *envPtr,
			    JumpFixup *jumpFixupPtr, int jumpDist,
			    int distThreshold);
MODULE_SCOPE void	TclFreeCompileEnv(CompileEnv *envPtr);
MODULE_SCOPE void	TclFreeJumpFixupArray(JumpFixupArray *fixupArrayPtr);
MODULE_SCOPE int	TclGetIndexFromToken(Tcl_Token *tokenPtr,
1141
1142
1143
1144
1145
1146
1147
1148

1149
1150

1151
1152
1153
1154
1155



1156
1157
1158
1159
1160

1161
1162

1163
1164
1165
1166
1167
1168
1169
1170
1171
1172

1173
1174
1175

1176
1177
1178

1179
1180
1181

1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192

1193
1194

1195
1196

1197
1198

1199
1200

1201
1202
1203
1204
1205
1206
1207
1163
1164
1165
1166
1167
1168
1169

1170
1171

1172
1173
1174
1175


1176
1177
1178
1179
1180
1181
1182

1183
1184

1185
1186
1187
1188
1189
1190
1191
1192
1193
1194

1195



1196



1197



1198


1199
1200
1201
1202
1203
1204
1205
1206

1207
1208

1209
1210

1211
1212

1213
1214

1215
1216
1217
1218
1219
1220
1221
1222







-
+

-
+



-
-
+
+
+




-
+

-
+









-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-








-
+

-
+

-
+

-
+

-
+







			    ExceptionAux *auxPtr);
MODULE_SCOPE void	TclFinalizeLoopExceptionRange(CompileEnv *envPtr,
			    int range);
#ifdef TCL_COMPILE_STATS
MODULE_SCOPE char *	TclLiteralStats(LiteralTable *tablePtr);
MODULE_SCOPE int	TclLog2(int value);
#endif
MODULE_SCOPE int	TclLocalScalar(const char *bytes, size_t numBytes,
MODULE_SCOPE size_t	TclLocalScalar(const char *bytes, size_t numBytes,
			    CompileEnv *envPtr);
MODULE_SCOPE int	TclLocalScalarFromToken(Tcl_Token *tokenPtr,
MODULE_SCOPE size_t	TclLocalScalarFromToken(Tcl_Token *tokenPtr,
			    CompileEnv *envPtr);
MODULE_SCOPE void	TclOptimizeBytecode(void *envPtr);
#ifdef TCL_COMPILE_DEBUG
MODULE_SCOPE void	TclPrintByteCodeObj(Tcl_Interp *interp,
			    Tcl_Obj *objPtr);
MODULE_SCOPE void	TclDebugPrintByteCodeObj(Tcl_Obj *objPtr);
#else
#define TclDebugPrintByteCodeObj(objPtr) (void)(objPtr)
#endif
MODULE_SCOPE int	TclPrintInstruction(ByteCode *codePtr,
			    const unsigned char *pc);
MODULE_SCOPE void	TclPrintObject(FILE *outFile,
			    Tcl_Obj *objPtr, size_t maxChars);
			    Tcl_Obj *objPtr, Tcl_Size maxChars);
MODULE_SCOPE void	TclPrintSource(FILE *outFile,
			    const char *string, size_t maxChars);
			    const char *string, Tcl_Size maxChars);
MODULE_SCOPE void	TclPushVarName(Tcl_Interp *interp,
			    Tcl_Token *varTokenPtr, CompileEnv *envPtr,
			    int flags, int *localIndexPtr,
			    int *isScalarPtr);
MODULE_SCOPE void	TclPreserveByteCode(ByteCode *codePtr);
MODULE_SCOPE void	TclReleaseByteCode(ByteCode *codePtr);
MODULE_SCOPE void	TclReleaseLiteral(Tcl_Interp *interp, Tcl_Obj *objPtr);
MODULE_SCOPE void	TclInvalidateCmdLiteral(Tcl_Interp *interp,
			    const char *name, Namespace *nsPtr);
MODULE_SCOPE int	TclSingleOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclSingleOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclSortingOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclSortingOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclVariadicOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclVariadicOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclNoIdentOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclNoIdentOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
#ifdef TCL_COMPILE_DEBUG
MODULE_SCOPE void	TclVerifyGlobalLiteralTable(Interp *iPtr);
MODULE_SCOPE void	TclVerifyLocalLiteralTable(CompileEnv *envPtr);
#endif
MODULE_SCOPE int	TclWordKnownAtCompileTime(Tcl_Token *tokenPtr,
			    Tcl_Obj *valuePtr);
MODULE_SCOPE void	TclLogCommandInfo(Tcl_Interp *interp,
			    const char *script, const char *command,
			    size_t length, const unsigned char *pc,
			    Tcl_Size length, const unsigned char *pc,
			    Tcl_Obj **tosPtr);
MODULE_SCOPE Tcl_Obj	*TclGetInnerContext(Tcl_Interp *interp,
MODULE_SCOPE Tcl_Obj *	TclGetInnerContext(Tcl_Interp *interp,
			    const unsigned char *pc, Tcl_Obj **tosPtr);
MODULE_SCOPE Tcl_Obj	*TclNewInstNameObj(unsigned char inst);
MODULE_SCOPE Tcl_Obj *	TclNewInstNameObj(unsigned char inst);
MODULE_SCOPE int	TclPushProcCallFrame(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Interp *interp, Tcl_Size objc,
			    Tcl_Obj *const objv[], int isLambda);

#endif /* TCL_MAJOR_VERSION > 8 */

/*
 *----------------------------------------------------------------
 * Macros and flag values used by Tcl bytecode compilation and execution
 * modules inside the Tcl core but not used outside.
 *----------------------------------------------------------------
 */
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
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







-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+


-
+


+
+
+
+
+
-
+
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
+


-
-
+
+



-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
-
-
+
+
-
-
+
+









-
-
+
+










-
-
-
-
-
-
-
+
+
+
+
+
+
+







    (envPtr)->auxDataArrayPtr[(index)].clientData

#define LITERAL_ON_HEAP		0x01
#define LITERAL_CMD_NAME	0x02
#define LITERAL_UNSHARED	0x04

/*
 * Macro used to manually adjust the stack requirements; used in cases where
 * the stack effect cannot be computed from the opcode and its operands, but
 * is still known at compile time.
 *
 * void TclAdjustStackDepth(int delta, CompileEnv *envPtr);
 */

 * Adjust the stack requirements. Manually used in cases where the stack
 * effect cannot be computed from the opcode and its operands, but is still
 * known at compile time.
 */
static inline void
TclAdjustStackDepth(
    int delta,
    CompileEnv *envPtr)
{
#define TclAdjustStackDepth(delta, envPtr) \
    do {								\
	if ((delta) < 0) {						\
	    if ((envPtr)->maxStackDepth < (envPtr)->currStackDepth) {	\
		(envPtr)->maxStackDepth = (envPtr)->currStackDepth;	\
    if (delta < 0) {
	if ((int) envPtr->maxStackDepth < (int) envPtr->currStackDepth) {
	    envPtr->maxStackDepth = envPtr->currStackDepth;
	    }								\
	}								\
	(envPtr)->currStackDepth += (delta);				\
	}
    }
    envPtr->currStackDepth += delta;
    } while (0)

#define TclGetStackDepth(envPtr)		\
}

#define TclGetStackDepth(envPtr) \
    ((envPtr)->currStackDepth)

#define TclSetStackDepth(depth, envPtr)		\
#define TclSetStackDepth(depth, envPtr) \
    (envPtr)->currStackDepth = (depth)

/*
 * Verify that the current stack depth is what we think it should be. When
 * this is wrong, code generation is broken!
 */
static inline void
#define TclCheckStackDepth(depth, envPtr)				\
TclCheckStackDepth(
    do {								\
	int _dd = (depth);						\
	if (_dd != (envPtr)->currStackDepth) {				\
	    Tcl_Panic("bad stack depth computations: is %i, should be %i", \
		    (envPtr)->currStackDepth, _dd);		\
    size_t depth,
    CompileEnv *envPtr)
{
    if (depth != (size_t) envPtr->currStackDepth) {
	Tcl_Panic("bad stack depth computations: "
		"is %" TCL_Z_MODIFIER "u, should be %" TCL_Z_MODIFIER "u",
		(size_t) envPtr->currStackDepth, depth);
	}								\
    } while (0)
    }
}

/*
 * Macro used to update the stack requirements. It is called by the macros
 * TclEmitOpCode, TclEmitInst1 and TclEmitInst4.
 * Update the stack requirements based on the instruction definition. It is
 * called by the macros TclEmitOpCode, TclEmitInst1 and TclEmitInst4.
 * Remark that the very last instruction of a bytecode always reduces the
 * stack level: INST_DONE or INST_POP, so that the maxStackdepth is always
 * updated.
 *
 * void TclUpdateStackReqs(unsigned char op, int i, CompileEnv *envPtr);
 */

 */
static inline void
TclUpdateStackReqs(
    unsigned char op,
    int i,
    CompileEnv *envPtr)
{
#define TclUpdateStackReqs(op, i, envPtr) \
    do {							\
	int _delta = tclInstructionTable[(op)].stackEffect;	\
	if (_delta) {						\
	    if (_delta == INT_MIN) {				\
		_delta = 1 - (i);				\
    int delta = tclInstructionTable[op].stackEffect;
    if (delta) {
	if (delta == INT_MIN) {
	    delta = 1 - i;
	    }							\
	    TclAdjustStackDepth(_delta, envPtr);			\
	}
	TclAdjustStackDepth(delta, envPtr);
	}							\
    } while (0)
    }
}

/*
 * Macros used to update the flag that indicates if we are at the start of a
 * command, based on whether the opcode is INST_START_COMMAND.
 *
 * void TclUpdateAtCmdStart(unsigned char op, CompileEnv *envPtr);
 */

#define TclUpdateAtCmdStart(op, envPtr) \
    if ((envPtr)->atCmdStart < 2) {				     \
	(envPtr)->atCmdStart = ((op) == INST_START_CMD ? 1 : 0);     \
    if ((envPtr)->atCmdStart < 2) {					\
	(envPtr)->atCmdStart = ((op) == INST_START_CMD ? 1 : 0);	\
    }

/*
 * Macro to emit an opcode byte into a CompileEnv's code array. The ANSI C
 * "prototype" for this macro is:
 *
 * void TclEmitOpcode(unsigned char op, CompileEnv *envPtr);
 */

#define TclEmitOpcode(op, envPtr) \
    do {							\
	if ((envPtr)->codeNext == (envPtr)->codeEnd) {		\
	    TclExpandCodeArray(envPtr);				\
	}							\
	*(envPtr)->codeNext++ = (unsigned char) (op);		\
	TclUpdateAtCmdStart(op, envPtr);			\
	TclUpdateStackReqs(op, 0, envPtr);			\
    do {								\
	if ((envPtr)->codeNext == (envPtr)->codeEnd) {			\
	    TclExpandCodeArray(envPtr);					\
	}								\
	*(envPtr)->codeNext++ = (unsigned char) (op);			\
	TclUpdateAtCmdStart(op, envPtr);				\
	TclUpdateStackReqs(op, 0, envPtr);				\
    } while (0)

/*
 * Macros to emit an integer operand. The ANSI C "prototype" for these macros
 * are:
 *
 * void TclEmitInt1(int i, CompileEnv *envPtr);
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391







1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411





1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426



1427
1428
1429
1430
1431
1432



1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446

1447
1448
1449
1450
1451
1452
1453
1374
1375
1376
1377
1378
1379
1380















1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407







1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429





1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446



1447
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












-
-
-
-
-
-
-
+
+
+
+
+
+
+















-
-
-
-
-
+
+
+
+
+












-
-
-
+
+
+



-
-
-
+
+
+













-
+







	*(envPtr)->codeNext++ = (unsigned char) (op);			\
	*(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i));	\
	TclUpdateAtCmdStart(op, envPtr);				\
	TclUpdateStackReqs(op, i, envPtr);				\
    } while (0)

#define TclEmitInstInt4(op, i, envPtr) \
    do {							\
	if (((envPtr)->codeNext + 5) > (envPtr)->codeEnd) {	\
	    TclExpandCodeArray(envPtr);				\
	}							\
	*(envPtr)->codeNext++ = (unsigned char) (op);		\
	*(envPtr)->codeNext++ =					\
		(unsigned char) ((unsigned int) (i) >> 24);	\
	*(envPtr)->codeNext++ =					\
		(unsigned char) ((unsigned int) (i) >> 16);	\
	*(envPtr)->codeNext++ =					\
		(unsigned char) ((unsigned int) (i) >>  8);	\
	*(envPtr)->codeNext++ =					\
		(unsigned char) ((unsigned int) (i)      );	\
	TclUpdateAtCmdStart(op, envPtr);			\
	TclUpdateStackReqs(op, i, envPtr);			\
    do {								\
	if (((envPtr)->codeNext + 5) > (envPtr)->codeEnd) {		\
	    TclExpandCodeArray(envPtr);					\
	}								\
	*(envPtr)->codeNext++ = (unsigned char) (op);			\
	*(envPtr)->codeNext++ =						\
		(unsigned char) ((unsigned int) (i) >> 24);		\
	*(envPtr)->codeNext++ =						\
		(unsigned char) ((unsigned int) (i) >> 16);		\
	*(envPtr)->codeNext++ =						\
		(unsigned char) ((unsigned int) (i) >>  8);		\
	*(envPtr)->codeNext++ =						\
		(unsigned char) ((unsigned int) (i)      );		\
	TclUpdateAtCmdStart(op, envPtr);				\
	TclUpdateStackReqs(op, i, envPtr);				\
    } while (0)

/*
 * Macro to push a Tcl object onto the Tcl evaluation stack. It emits the
 * object's one or four byte array index into the CompileEnv's code array.
 * These support, respectively, a maximum of 256 (2**8) and 2**32 objects in a
 * CompileEnv. The ANSI C "prototype" for this macro is:
 *
 * void	TclEmitPush(int objIndex, CompileEnv *envPtr);
 */

#define TclEmitPush(objIndex, envPtr) \
    do {							 \
	int _objIndexCopy = (objIndex);			 \
	if (_objIndexCopy <= 255) {				 \
	    TclEmitInstInt1(INST_PUSH1, _objIndexCopy, (envPtr)); \
	} else {						 \
	    TclEmitInstInt4(INST_PUSH4, _objIndexCopy, (envPtr)); \
	}							 \
    do {								\
	int _objIndexCopy = (objIndex);					\
	if (_objIndexCopy <= 255) {					\
	    TclEmitInstInt1(INST_PUSH1, _objIndexCopy, (envPtr));	\
	} else {							\
	    TclEmitInstInt4(INST_PUSH4, _objIndexCopy, (envPtr));	\
	}								\
    } while (0)

/*
 * Macros to update a (signed or unsigned) integer starting at a pointer. The
 * two variants depend on the number of bytes. The ANSI C "prototypes" for
 * these macros are:
 *
 * void TclStoreInt1AtPtr(int i, unsigned char *p);
 * void TclStoreInt4AtPtr(int i, unsigned char *p);
 */

#define TclStoreInt1AtPtr(i, p) \
    *(p)   = (unsigned char) ((unsigned int) (i))

#define TclStoreInt4AtPtr(i, p) \
    do {							\
	*(p)   = (unsigned char) ((unsigned int) (i) >> 24);	\
	*(p+1) = (unsigned char) ((unsigned int) (i) >> 16);	\
	*(p+2) = (unsigned char) ((unsigned int) (i) >>  8);	\
	*(p+3) = (unsigned char) ((unsigned int) (i)      );	\
    do {								\
	*(p)   = (unsigned char) ((unsigned int) (i) >> 24);		\
	*(p+1) = (unsigned char) ((unsigned int) (i) >> 16);		\
	*(p+2) = (unsigned char) ((unsigned int) (i) >>  8);		\
	*(p+3) = (unsigned char) ((unsigned int) (i)      );		\
    } while (0)

/*
 * Macros to update instructions at a particular pc with a new op code and a
 * (signed or unsigned) int operand. The ANSI C "prototypes" for these macros
 * are:
 *
 * void TclUpdateInstInt1AtPc(unsigned char op, int i, unsigned char *pc);
 * void TclUpdateInstInt4AtPc(unsigned char op, int i, unsigned char *pc);
 */

#define TclUpdateInstInt1AtPc(op, i, pc) \
    do {					\
	*(pc) = (unsigned char) (op);		\
	TclStoreInt1AtPtr((i), ((pc)+1));	\
    do {								\
	*(pc) = (unsigned char) (op);					\
	TclStoreInt1AtPtr((i), ((pc)+1));				\
    } while (0)

#define TclUpdateInstInt4AtPc(op, i, pc) \
    do {					\
	*(pc) = (unsigned char) (op);		\
	TclStoreInt4AtPtr((i), ((pc)+1));	\
    do {								\
	*(pc) = (unsigned char) (op);					\
	TclStoreInt4AtPtr((i), ((pc)+1));				\
    } while (0)

/*
 * Macro to fix up a forward jump to point to the current code-generation
 * position in the bytecode being created (the most common case). The ANSI C
 * "prototypes" for this macro is:
 *
 * int TclFixupForwardJumpToHere(CompileEnv *envPtr, JumpFixup *fixupPtr,
 *				 int threshold);
 */

#define TclFixupForwardJumpToHere(envPtr, fixupPtr, threshold) \
    TclFixupForwardJump((envPtr), (fixupPtr),				\
	    (envPtr)->codeNext-(envPtr)->codeStart-(fixupPtr)->codeOffset, \
	    (envPtr)->codeNext-(envPtr)->codeStart-(int)(fixupPtr)->codeOffset, \
	    (threshold))

/*
 * Macros to get a signed integer (GET_INT{1,2}) or an unsigned int
 * (GET_UINT{1,2}) from a pointer. There are two variants for each return type
 * that depend on the number of bytes fetched. The ANSI C "prototypes" for
 * these macros are:
1468
1469
1470
1471
1472
1473
1474
1475

1476
1477
1478
1479
1480
1481
1482




1483
1484
1485
1486
1487
1488
1489
1490




1491
1492
1493

1494
1495
1496
1497


1498
1499
1500
1501


1502
1503
1504
1505
1506
1507
1508
1509
1510

1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531

1532
1533
1534
1535
1536
1537

1538
1539

1540
1541
1542
1543
1544
1545
1546
1491
1492
1493
1494
1495
1496
1497

1498
1499
1500
1501




1502
1503
1504
1505
1506
1507
1508
1509




1510
1511
1512
1513
1514
1515

1516
1517
1518


1519
1520
1521
1522


1523
1524
1525
1526
1527
1528
1529
1530
1531
1532

1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553

1554
1555
1556
1557
1558
1559

1560
1561

1562
1563
1564
1565
1566
1567
1568
1569







-
+



-
-
-
-
+
+
+
+




-
-
-
-
+
+
+
+


-
+


-
-
+
+


-
-
+
+








-
+




















-
+





-
+

-
+








#ifndef __CHAR_UNSIGNED__
#   define TclGetInt1AtPtr(p) ((int) *((char *) p))
#elif defined(HAVE_SIGNED_CHAR)
#   define TclGetInt1AtPtr(p) ((int) *((signed char *) p))
#else
#   define TclGetInt1AtPtr(p) \
    (((int) *((char *) p)) | ((*(p) & 0200) ? (-256) : 0))
    ((int) ((*((char *) p)) | ((*(p) & 0200) ? (-256) : 0)))
#endif

#define TclGetInt4AtPtr(p) \
    (((int) (TclGetUInt1AtPtr(p) << 24)) |				\
		     (*((p)+1) << 16) |				\
		     (*((p)+2) <<  8) |				\
		     (*((p)+3)))
    ((int) ((TclGetUInt1AtPtr(p) << 24) |				\
		       (*((p)+1) << 16) |				\
		       (*((p)+2) <<  8) |				\
		       (*((p)+3))))

#define TclGetUInt1AtPtr(p) \
    ((unsigned int) *(p))
#define TclGetUInt4AtPtr(p) \
    ((unsigned int) (*(p)     << 24) |				\
		    (*((p)+1) << 16) |				\
		    (*((p)+2) <<  8) |				\
		    (*((p)+3)))
    ((unsigned int) ((*(p)     << 24) |					\
		     (*((p)+1) << 16) |					\
		     (*((p)+2) <<  8) |					\
		     (*((p)+3))))

/*
 * Macros used to compute the minimum and maximum of two integers. The ANSI C
 * Macros used to compute the minimum and maximum of two values. The ANSI C
 * "prototypes" for these macros are:
 *
 * int TclMin(int i, int j);
 * int TclMax(int i, int j);
 * size_t TclMin(size_t i, size_t j);
 * size_t TclMax(size_t i, size_t j);
 */

#define TclMin(i, j)	((((int) i) < ((int) j))? (i) : (j))
#define TclMax(i, j)	((((int) i) > ((int) j))? (i) : (j))
#define TclMin(i, j)	((((size_t) i) + 1 < ((size_t) j) + 1 )? (i) : (j))
#define TclMax(i, j)	((((size_t) i) + 1 > ((size_t) j) + 1 )? (i) : (j))

/*
 * Convenience macros for use when compiling bodies of commands. The ANSI C
 * "prototype" for these macros are:
 *
 * static void		BODY(Tcl_Token *tokenPtr, int word);
 */

#define BODY(tokenPtr, word)						\
#define BODY(tokenPtr, word) \
    SetLineInformation((word));						\
    TclCompileCmdWord(interp, (tokenPtr)+1, (tokenPtr)->numComponents,	\
	    envPtr)

/*
 * Convenience macro for use when compiling tokens to be pushed. The ANSI C
 * "prototype" for this macro is:
 *
 * static void		CompileTokens(CompileEnv *envPtr, Tcl_Token *tokenPtr,
 *			    Tcl_Interp *interp);
 */

#define CompileTokens(envPtr, tokenPtr, interp) \
    TclCompileTokens((interp), (tokenPtr)+1, (tokenPtr)->numComponents, \
	    (envPtr));
/*
 * Convenience macros for use when pushing literals. The ANSI C "prototype" for
 * these macros are:
 *
 * static void		PushLiteral(CompileEnv *envPtr,
 *			    const char *string, size_t length);
 *			    const char *string, Tcl_Size length);
 * static void		PushStringLiteral(CompileEnv *envPtr,
 *			    const char *string);
 */

#define PushLiteral(envPtr, string, length) \
    TclEmitPush(TclRegisterLiteral(envPtr, string, length, 0), (envPtr))
    TclEmitPush(TclRegisterLiteral((envPtr), (string), (length), 0), (envPtr))
#define PushStringLiteral(envPtr, string) \
    PushLiteral(envPtr, string, sizeof(string "") - 1)
    PushLiteral((envPtr), (string), sizeof(string "") - 1)

/*
 * Macro to advance to the next token; it is more mnemonic than the address
 * arithmetic that it replaces. The ANSI C "prototype" for this macro is:
 *
 * static Tcl_Token *	TokenAfter(Tcl_Token *tokenPtr);
 */
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
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







-
-
-
+
+
+










-
+







/*
 * Note: the exceptDepth is a bit of a misnomer: TEBC only needs the
 * maximal depth of nested CATCH ranges in order to alloc runtime
 * memory. These macros should compute precisely that? OTOH, the nesting depth
 * of LOOP ranges is an interesting datum for debugging purposes, and that is
 * what we compute now.
 *
 * static int	ExceptionRangeStarts(CompileEnv *envPtr, int index);
 * static void	ExceptionRangeEnds(CompileEnv *envPtr, int index);
 * static void	ExceptionRangeTarget(CompileEnv *envPtr, int index, LABEL);
 * static int	ExceptionRangeStarts(CompileEnv *envPtr, Tcl_Size index);
 * static void	ExceptionRangeEnds(CompileEnv *envPtr, Tcl_Size index);
 * static void	ExceptionRangeTarget(CompileEnv *envPtr, Tcl_Size index, LABEL);
 */

#define ExceptionRangeStarts(envPtr, index) \
    (((envPtr)->exceptDepth++),						\
    ((envPtr)->maxExceptDepth =						\
	    TclMax((envPtr)->exceptDepth, (envPtr)->maxExceptDepth)),	\
    ((envPtr)->exceptArrayPtr[(index)].codeOffset = CurrentOffset(envPtr)))
#define ExceptionRangeEnds(envPtr, index) \
    (((envPtr)->exceptDepth--),						\
    ((envPtr)->exceptArrayPtr[(index)].numCodeBytes =			\
	CurrentOffset(envPtr) - (envPtr)->exceptArrayPtr[(index)].codeOffset))
	CurrentOffset(envPtr) - (int)(envPtr)->exceptArrayPtr[(index)].codeOffset))
#define ExceptionRangeTarget(envPtr, index, targetType) \
    ((envPtr)->exceptArrayPtr[(index)].targetType = CurrentOffset(envPtr))

/*
 * Check if there is an LVT for compiled locals
 */

1622
1623
1624
1625
1626
1627
1628
1629

1630
1631
1632
1633
1634
1635
1636
1645
1646
1647
1648
1649
1650
1651

1652
1653
1654
1655
1656
1657
1658
1659







-
+







 * change during the course of the function.
 *
 * Macro to encapsulate the variable definition and setup.
 */

#define DefineLineInformation \
    ExtCmdLoc *mapPtr = envPtr->extCmdMapPtr;				\
    int eclIndex = mapPtr->nuloc - 1
    Tcl_Size eclIndex = mapPtr->nuloc - 1

#define SetLineInformation(word) \
    envPtr->line = mapPtr->loc[eclIndex].line[(word)];			\
    envPtr->clNext = mapPtr->loc[eclIndex].next[(word)]

#define PushVarNameWord(i,v,e,f,l,sc,word) \
    SetLineInformation(word);						\
1663
1664
1665
1666
1667
1668
1669






1670
1671
1672
1673
1674
1675
1676
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705







+
+
+
+
+
+







/*
 * Flags bits used by TclPushVarName.
 */

#define TCL_NO_LARGE_INDEX 1	/* Do not return localIndex value > 255 */
#define TCL_NO_ELEMENT 2	/* Do not push the array element. */

/*
 * Flags bits used by lreplace4 instruction
 */
#define TCL_LREPLACE4_END_IS_LAST  1 /* "end" refers to last element */
#define TCL_LREPLACE4_SINGLE_INDEX 2 /* Second index absent (pure insert) */

/*
 * DTrace probe macros (NOPs if DTrace support is not enabled).
 */

/*
 * Define the following macros to enable debug logging of the DTrace proc,
 * cmd, and inst probes. Note that this does _not_ require a platform with
1737
1738
1739
1740
1741
1742
1743
1744

1745
1746
1747
1748
1749
1750
1751
1766
1767
1768
1769
1770
1771
1772

1773
1774
1775
1776
1777
1778
1779
1780







-
+







#define TCL_DTRACE_TCL_PROBE_ENABLED()	    unlikely(TCL_TCL_PROBE_ENABLED())
#define TCL_DTRACE_TCL_PROBE(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \
	TCL_TCL_PROBE(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)

#define TCL_DTRACE_DEBUG_LOG()

MODULE_SCOPE void	TclDTraceInfo(Tcl_Obj *info, const char **args,
			    int *argsi);
			    Tcl_Size *argsi);

#else /* USE_DTRACE */

#define TCL_DTRACE_PROC_ENTRY_ENABLED()	    0
#define TCL_DTRACE_PROC_RETURN_ENABLED()    0
#define TCL_DTRACE_PROC_RESULT_ENABLED()    0
#define TCL_DTRACE_PROC_ARGS_ENABLED()	    0
1792
1793
1794
1795
1796
1797
1798
1799

1800
1801
1802
1803
1804
1805
1806
1807
1808
1809








1810
1811
1812
1813
1814
1815
1816
1821
1822
1823
1824
1825
1826
1827

1828
1829
1830








1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845







-
+


-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+







#undef TCL_DTRACE_DEBUG_INST_PROBES
#define TCL_DTRACE_DEBUG_INST_PROBES 0
#endif

MODULE_SCOPE int tclDTraceDebugEnabled, tclDTraceDebugIndent;
MODULE_SCOPE FILE *tclDTraceDebugLog;
MODULE_SCOPE void TclDTraceOpenDebugLog(void);
MODULE_SCOPE void TclDTraceInfo(Tcl_Obj *info, const char **args, int *argsi);
MODULE_SCOPE void TclDTraceInfo(Tcl_Obj *info, const char **args, Tcl_Size *argsi);

#define TCL_DTRACE_DEBUG_LOG() \
    int tclDTraceDebugEnabled = TCL_DTRACE_DEBUG_LOG_ENABLED;	\
    int tclDTraceDebugIndent = 0;				\
    FILE *tclDTraceDebugLog = NULL;				\
    void TclDTraceOpenDebugLog(void) {				\
	char n[35];						\
	sprintf(n, "/tmp/tclDTraceDebug-%" TCL_Z_MODIFIER "u.log",		\
		(size_t) getpid());			\
	tclDTraceDebugLog = fopen(n, "a");			\
    int tclDTraceDebugEnabled = TCL_DTRACE_DEBUG_LOG_ENABLED;		\
    int tclDTraceDebugIndent = 0;					\
    FILE *tclDTraceDebugLog = NULL;					\
    void TclDTraceOpenDebugLog(void) {					\
	char n[35];							\
	snprintf(n, sizeof(n), "/tmp/tclDTraceDebug-%" TCL_Z_MODIFIER "u.log", \
		(size_t) getpid());					\
	tclDTraceDebugLog = fopen(n, "a");				\
    }

#define TclDTraceDbgMsg(p, m, ...) \
    do {								\
	if (tclDTraceDebugEnabled) {					\
	    int _l, _t = 0;						\
	    if (!tclDTraceDebugLog) { TclDTraceOpenDebugLog(); }	\
1829
1830
1831
1832
1833
1834
1835
1836
1837


1838
1839

1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857


1858
1859

1860
1861
1862
1863
1864
1865
1866
1867

1868
1869
1870
1871
1872
1873
1874
1858
1859
1860
1861
1862
1863
1864


1865
1866
1867

1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884


1885
1886
1887

1888
1889
1890
1891
1892
1893
1894
1895

1896
1897
1898
1899
1900
1901
1902
1903







-
-
+
+

-
+
















-
-
+
+

-
+







-
+








#define TCL_DTRACE_PROC_ENTRY_ENABLED()	    1
#define TCL_DTRACE_PROC_RETURN_ENABLED()    1
#define TCL_DTRACE_PROC_RESULT_ENABLED()    1
#define TCL_DTRACE_PROC_ARGS_ENABLED()	    1
#define TCL_DTRACE_PROC_INFO_ENABLED()	    1
#define TCL_DTRACE_PROC_ENTRY(a0, a1, a2) \
	tclDTraceDebugIndent++; \
	TclDTraceDbgMsg("-> proc-entry", "%s %d %p", a0, a1, a2)
	tclDTraceDebugIndent++;						\
	TclDTraceDbgMsg("-> proc-entry", "%s %" TCL_SIZE_MODIFIER "d %p", a0, a1, a2)
#define TCL_DTRACE_PROC_RETURN(a0, a1) \
	TclDTraceDbgMsg("<- proc-return", "%s %d", a0, a1); \
	TclDTraceDbgMsg("<- proc-return", "%s %d", a0, a1);		\
	tclDTraceDebugIndent--
#define TCL_DTRACE_PROC_RESULT(a0, a1, a2, a3) \
	TclDTraceDbgMsg(" | proc-result", "%s %d %s %p", a0, a1, a2, a3)
#define TCL_DTRACE_PROC_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \
	TclDTraceDbgMsg(" | proc-args", "%s %s %s %s %s %s %s %s %s %s", a0, \
		a1, a2, a3, a4, a5, a6, a7, a8, a9)
#define TCL_DTRACE_PROC_INFO(a0, a1, a2, a3, a4, a5, a6, a7) \
	TclDTraceDbgMsg(" | proc-info", "%s %s %s %s %d %d %s %s", a0, a1, \
		a2, a3, a4, a5, a6, a7)

#define TCL_DTRACE_CMD_ENTRY_ENABLED()	    1
#define TCL_DTRACE_CMD_RETURN_ENABLED()	    1
#define TCL_DTRACE_CMD_RESULT_ENABLED()	    1
#define TCL_DTRACE_CMD_ARGS_ENABLED()	    1
#define TCL_DTRACE_CMD_INFO_ENABLED()	    1
#define TCL_DTRACE_CMD_ENTRY(a0, a1, a2) \
	tclDTraceDebugIndent++; \
	TclDTraceDbgMsg("-> cmd-entry", "%s %d %p", a0, a1, a2)
	tclDTraceDebugIndent++;						\
	TclDTraceDbgMsg("-> cmd-entry", "%s %" TCL_SIZE_MODIFIER "d %p", a0, a1, a2)
#define TCL_DTRACE_CMD_RETURN(a0, a1) \
	TclDTraceDbgMsg("<- cmd-return", "%s %d", a0, a1); \
	TclDTraceDbgMsg("<- cmd-return", "%s %d", a0, a1);		\
	tclDTraceDebugIndent--
#define TCL_DTRACE_CMD_RESULT(a0, a1, a2, a3) \
	TclDTraceDbgMsg(" | cmd-result", "%s %d %s %p", a0, a1, a2, a3)
#define TCL_DTRACE_CMD_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \
	TclDTraceDbgMsg(" | cmd-args", "%s %s %s %s %s %s %s %s %s %s", a0, \
		a1, a2, a3, a4, a5, a6, a7, a8, a9)
#define TCL_DTRACE_CMD_INFO(a0, a1, a2, a3, a4, a5, a6, a7) \
	TclDTraceDbgMsg(" | cmd-info", "%s %s %s %s %d %d %s %s", a0, a1, \
	TclDTraceDbgMsg(" | cmd-info", "%s %s %s %s %" TCL_SIZE_MODIFIER "d %" TCL_SIZE_MODIFIER "d %s %s", a0, a1, \
		a2, a3, a4, a5, a6, a7)

#define TCL_DTRACE_INST_START_ENABLED()	    TCL_DTRACE_DEBUG_INST_PROBES
#define TCL_DTRACE_INST_DONE_ENABLED()	    TCL_DTRACE_DEBUG_INST_PROBES
#define TCL_DTRACE_INST_START(a0, a1, a2) \
	TclDTraceDbgMsg(" | inst-start", "%s %d %p", a0, a1, a2)
#define TCL_DTRACE_INST_DONE(a0, a1, a2) \

Changes to generic/tclConfig.c.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tclConfig.c --
 *
 *	This file provides the facilities which allow Tcl and other packages
 *	to embed configuration information into their binary libraries.
 *
 * Copyright (c) 2002 Andreas Kupries <andreas_kupries@users.sourceforge.net>
 * Copyright © 2002 Andreas Kupries <andreas_kupries@users.sourceforge.net>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

123
124
125
126
127
128
129
130

131
132
133
134
135
136
137
123
124
125
126
127
128
129

130
131
132
133
134
135
136
137







-
+







    /*
     * Extend the package configuration...
     * We cannot assume that the encodings are initialized, therefore
     * store the value as-is in a byte array. See Bug [9b2e636361].
     */

    for (cfg=configuration ; cfg->key!=NULL && cfg->key[0]!='\0' ; cfg++) {
	Tcl_DictObjPut(interp, pkgDict, Tcl_NewStringObj(cfg->key, -1),
	TclDictPut(interp, pkgDict, cfg->key,
		Tcl_NewByteArrayObj((unsigned char *)cfg->value, strlen(cfg->value)));
    }

    /*
     * Write the changes back into the overall database.
     */

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
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







-
+


-
+









-
+


-
+




-
+
-





-
+








/*
 *----------------------------------------------------------------------
 *
 * QueryConfigObjCmd --
 *
 *	Implementation of "::<package>::pkgconfig", the command to query
 *	configuration information embedded into a binary library.
 *	configuration information embedded into a library.
 *
 * Results:
 *	A standard tcl result.
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the manual for what this command does.
 *
 *----------------------------------------------------------------------
 */

static int
QueryConfigObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    struct Tcl_Obj *const *objv)
    Tcl_Obj *const *objv)
{
    QCCD *cdPtr = (QCCD *)clientData;
    Tcl_Obj *pkgName = cdPtr->pkg;
    Tcl_Obj *pDB, *pkgDict, *val, *listPtr;
    size_t n = 0;
    Tcl_Size m, n = 0;
    int index, m;
    static const char *const subcmdStrings[] = {
	"get", "list", NULL
    };
    enum subcmds {
	CFG_GET, CFG_LIST
    };
    } index;
    Tcl_DString conv;
    Tcl_Encoding venc = NULL;
    const char *value;

    if ((objc < 2) || (objc > 3)) {
	Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?arg?");
	return TCL_ERROR;
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
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







-
+



-
+










-
+













-
+
+
+
+


















-
+







	/*
	 * Maybe a Tcl_Panic is better, because the package data has to be
	 * present.
	 */

	Tcl_SetObjResult(interp, Tcl_NewStringObj("package not known", -1));
	Tcl_SetErrorCode(interp, "TCL", "FATAL", "PKGCFG_BASE",
		TclGetString(pkgName), NULL);
		TclGetString(pkgName), (char *)NULL);
	return TCL_ERROR;
    }

    switch ((enum subcmds) index) {
    switch (index) {
    case CFG_GET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "key");
	    return TCL_ERROR;
	}

	if (Tcl_DictObjGet(interp, pkgDict, objv[2], &val) != TCL_OK
		|| val == NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj("key not known", -1));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CONFIG",
		    TclGetString(objv[2]), NULL);
		    TclGetString(objv[2]), (char *)NULL);
	    return TCL_ERROR;
	}

	if (cdPtr->encoding) {
	    venc = Tcl_GetEncoding(interp, cdPtr->encoding);
	    if (!venc) {
		return TCL_ERROR;
	    }
	}
	/*
	 * Value is stored as-is in a byte array, see Bug [9b2e636361],
	 * so we have to decode it first.
	 */
	value = (const char *) TclGetByteArrayFromObj(val, &n);
	value = (const char *) Tcl_GetBytesFromObj(interp, val, &n);
	if (value == NULL) {
	    return TCL_ERROR;
	}
	value = Tcl_ExternalToUtfDString(venc, value, n, &conv);
	Tcl_SetObjResult(interp, Tcl_NewStringObj(value,
		Tcl_DStringLength(&conv)));
	Tcl_DStringFree(&conv);
	return TCL_OK;

    case CFG_LIST:
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}

	Tcl_DictObjSize(interp, pkgDict, &m);
	listPtr = Tcl_NewListObj(m, NULL);

	if (!listPtr) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "insufficient memory to create list", -1));
	    Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
	    return TCL_ERROR;
	}

	if (m) {
	    Tcl_DictSearch s;
	    Tcl_Obj *key;
	    int done;
318
319
320
321
322
323
324
325

326
327
328
329
330
331
332
320
321
322
323
324
325
326

327
328
329
330
331
332
333
334







-
+







 *	Deallocates all non-transient memory allocated by Tcl_RegisterConfig.
 *
 *-------------------------------------------------------------------------
 */

static void
QueryConfigDelete(
    ClientData clientData)
    void *clientData)
{
    QCCD *cdPtr = (QCCD *)clientData;
    Tcl_Obj *pkgName = cdPtr->pkg;
    Tcl_Obj *pDB = GetConfigDict(cdPtr->interp);

    Tcl_DictObjRemove(NULL, pDB, pkgName);
    Tcl_DecrRefCount(pkgName);
385
386
387
388
389
390
391
392

393
394
395
396
397
398
399
400
401
402
403
404
387
388
389
390
391
392
393

394
395
396
397
398
399
400
401
402
403
404
405
406







-
+












 *	The package metadata database is freed.
 *
 *----------------------------------------------------------------------
 */

static void
ConfigDictDeleteProc(
    ClientData clientData,	/* Pointer to Tcl_Obj. */
    void *clientData,	/* Pointer to Tcl_Obj. */
    TCL_UNUSED(Tcl_Interp *))
{
    Tcl_DecrRefCount((Tcl_Obj *)clientData);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclDTrace.d.

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
30
31
32
33
34
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
30
31
32
33
34
35
36












+
+











-
+


-
+







/*
 * tclDTrace.d --
 *
 *	Tcl DTrace provider.
 *
 * Copyright (c) 2007-2008 Daniel A. Steffen <das@users.sourceforge.net>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

typedef struct Tcl_Obj Tcl_Obj;

typedef ptrdiff_t Tcl_Size;

/*
 * Tcl DTrace probes
 */

provider tcl {
    /***************************** proc probes *****************************/
    /*
     *	tcl*:::proc-entry probe
     *	    triggered immediately before proc bytecode execution
     *		arg0: proc name				(string)
     *		arg1: number of arguments		(int)
     *		arg1: number of arguments		(Tcl_Size)
     *		arg2: array of proc argument objects	(Tcl_Obj**)
     */
    probe proc__entry(const char *name, int objc, struct Tcl_Obj **objv);
    probe proc__entry(const char *name, Tcl_Size objc, struct Tcl_Obj **objv);
    /*
     *	tcl*:::proc-return probe
     *	    triggered immediately after proc bytecode execution
     *		arg0: proc name				(string)
     *		arg1: return code			(int)
     */
    probe proc__return(const char *name, int code);
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
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







-
+




-
+







-
+


-
+







     *	    triggered before proc-entry probe, gives access to TIP 280
     *	    information for the proc invocation (i.e. [info frame 0])
     *		arg0: TIP 280 cmd			(string)
     *		arg1: TIP 280 type			(string)
     *		arg2: TIP 280 proc			(string)
     *		arg3: TIP 280 file			(string)
     *		arg4: TIP 280 line			(int)
     *		arg5: TIP 280 level			(int)
     *		arg5: TIP 280 level			(Tcl_Size)
     *		arg6: TclOO method			(string)
     *		arg7: TclOO class/object		(string)
     */
    probe proc__info(const char *cmd, const char *type, const char *proc,
	    const char *file, int line, int level, const char *method,
	    const char *file, int line, Tcl_Size level, const char *method,
	    const char *class);

    /***************************** cmd probes ******************************/
    /*
     *	tcl*:::cmd-entry probe
     *	    triggered immediately before commmand execution
     *		arg0: command name			(string)
     *		arg1: number of arguments		(int)
     *		arg1: number of arguments		(Tcl_Size)
     *		arg2: array of command argument objects	(Tcl_Obj**)
     */
    probe cmd__entry(const char *name, int objc, struct Tcl_Obj **objv);
    probe cmd__entry(const char *name, Tcl_Size objc, struct Tcl_Obj **objv);
    /*
     *	tcl*:::cmd-return probe
     *	    triggered immediately after commmand execution
     *		arg0: command name			(string)
     *		arg1: return code			(int)
     */
    probe cmd__return(const char *name, int code);
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
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







-
+







-
+


-
+




-
+


-
+







     *		arg3: TIP 280 file			(string)
     *		arg4: TIP 280 line			(int)
     *		arg5: TIP 280 level			(int)
     *		arg6: TclOO method			(string)
     *		arg7: TclOO class/object		(string)
     */
    probe cmd__info(const char *cmd, const char *type, const char *proc,
	    const char *file, int line, int level, const char *method,
	    const char *file, int line, Tcl_Size level, const char *method,
	    const char *class);

    /***************************** inst probes *****************************/
    /*
     *	tcl*:::inst-start probe
     *	    triggered immediately before execution of a bytecode
     *		arg0: bytecode name			(string)
     *		arg1: depth of stack			(int)
     *		arg1: depth of stack			(Tcl_Size)
     *		arg2: top of stack			(Tcl_Obj**)
     */
    probe inst__start(const char *name, int depth, struct Tcl_Obj **stack);
    probe inst__start(const char *name, Tcl_Size depth, struct Tcl_Obj **stack);
    /*
     *	tcl*:::inst-done probe
     *	    triggered immediately after execution of a bytecode
     *		arg0: bytecode name			(string)
     *		arg1: depth of stack			(int)
     *		arg1: depth of stack			(Tcl_Size)
     *		arg2: top of stack			(Tcl_Obj**)
     */
    probe inst__done(const char *name, int depth, struct Tcl_Obj **stack);
    probe inst__done(const char *name, Tcl_Size depth, struct Tcl_Obj **stack);

    /***************************** obj probes ******************************/
    /*
     *	tcl*:::obj-create probe
     *	    triggered immediately after a new Tcl_Obj has been created
     *		arg0: object created			(Tcl_Obj*)
     */
174
175
176
177
178
179
180









181
182
183
184

185
186

187
188
189
190
191
192
193
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







+
+
+
+
+
+
+
+
+



-
+

-
+








typedef struct Tcl_ObjType {
    const char *name;
    void *freeIntRepProc;
    void *dupIntRepProc;
    void *updateStringProc;
    void *setFromAnyProc;
    size_t version;
    void *lengthProc;
    void *indexProc;
    void *sliceProc;
    void *reverseProc;
    void *getElementsProc;
    void *setElementProc;
    void *replaceProc;
    void *inOperProc;
} Tcl_ObjType;

struct Tcl_Obj {
    size_t refCount;
    Tcl_Size refCount;
    char *bytes;
    size_t length;
    Tcl_Size length;
    const Tcl_ObjType *typePtr;
    union {
	long longValue;
	double doubleValue;
	void *otherValuePtr;
	int64_t wideValue;
	struct {

Changes to generic/tclDate.c.

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
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

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
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
-
+



-
+
+












-
+

















+
+
+
+







-
-
+
+

-
-
+
+







/* A Bison parser, made by GNU Bison 3.1.  */
/* A Bison parser, made by GNU Bison 3.8.2.  */

/* Bison implementation for Yacc-like parsers in C

   Copyright (C) 1984, 1989-1990, 2000-2015, 2018 Free Software Foundation, Inc.
   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
   Inc.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */

/* As a special exception, you may create a larger work that contains
   part or all of the Bison parser skeleton and distribute that work
   under terms of your choice, so long as that work isn't itself a
   parser generator using the skeleton or a modified version thereof
   as a parser skeleton.  Alternatively, if you modify or redistribute
   the parser skeleton itself, you may (at your option) remove this
   special exception, which will cause the skeleton and the resulting
   Bison output files to be licensed under the GNU General Public
   License without this special exception.

   This special exception was added by the Free Software Foundation in
   version 2.2 of Bison.  */

/* C LALR(1) parser skeleton written by Richard Stallman, by
   simplifying the original so-called "semantic" parser.  */

/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
   especially those whose name start with YY_ or yy_.  They are
   private implementation details that can be changed or removed.  */

/* All symbols defined below should begin with yy or YY, to avoid
   infringing on user name space.  This should be done even for local
   variables, as they might otherwise be expanded by user macros.
   There are some unavoidable exceptions within include files to
   define necessary library symbols; they are noted "INFRINGES ON
   USER NAME SPACE" below.  */

/* Identify Bison output.  */
#define YYBISON 1
/* Identify Bison output, and Bison version.  */
#define YYBISON 30802

/* Bison version.  */
#define YYBISON_VERSION "3.1"
/* Bison version string.  */
#define YYBISON_VERSION "3.8.2"

/* Skeleton name.  */
#define YYSKELETON_NAME "yacc.c"

/* Pure parsers.  */
#define YYPURE 1

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
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
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
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
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

467
468




469
470
471



472




473
474

475
476
477
478
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







-
-
+
-







-
-
+
+
+
















-
-
-
-
-
+
+
-
-
+






-
-
+
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-











-
-
-
+
+
+
+
+
+
+
+
+





-
+


-
+












-
+
+
+
+
+
+
+
+
+

-
-
+
+
+
+
+
+

-
+



-
-
-
-
-
-
-
-









-
+




+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

+




-



-
-
+




-





















+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+

+







-
+

-
+

-
-









+
+
+
-
-
-
+
+
+
+
+
+
+
-


+
+
+
+
-
-
+
+
+
+
+




-
-
+
+
+
+

-
+


+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+













+
-
+
-
-
+
-
-
+

-
+

-
-
-
-



-
-
-
+
-
-
-
-
+

-
+





-
+

-
+


-

+
+
-
-
-
+
+
+
+
+
+
+

+
-
+












+
+
+
+
+
+
+
+
+
+
+

+
+
+
-
+







/* Substitute the variable and function names.  */
#define yyparse         TclDateparse
#define yylex           TclDatelex
#define yyerror         TclDateerror
#define yydebug         TclDatedebug
#define yynerrs         TclDatenerrs


/* Copy the first part of user declarations.  */
/* First part of user prologue.  */


/*
 * tclDate.c --
 *
 *	This file is generated from a yacc grammar defined in the file
 *	tclGetDate.y. It should not be edited directly.
 *
 * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1992-1995 Karl Lehenbauer & Mark Diekhans.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2015 Sergey G. Brester aka sebres.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */
#include "tclInt.h"

/*
 * Bison generates several labels that happen to be unused. MS Visual C++
 * doesn't like that, and complains. Tell it to shut up.
 */

#ifdef _MSC_VER
#pragma warning( disable : 4102 )
#endif /* _MSC_VER */

/*
 * Meridian: am, pm, or 24-hour style.
 */

typedef enum _MERIDIAN {
#if 0
#define YYDEBUG 1
    MERam, MERpm, MER24
} MERIDIAN;
#endif

/*
 * yyparse will accept a 'struct DateInfo' as its parameter; that's where the
 * parsed fields will be returned.
 */

typedef struct DateInfo {

#include "tclDate.h"
    Tcl_Obj* messages;		/* Error messages */
    const char* separatrix;	/* String separating messages */

    time_t dateYear;
    time_t dateMonth;
    time_t dateDay;
    int dateHaveDate;

    time_t dateHour;
    time_t dateMinutes;
    time_t dateSeconds;
    MERIDIAN dateMeridian;
    int dateHaveTime;

    time_t dateTimezone;
    int dateDSTmode;
    int dateHaveZone;

    time_t dateRelMonth;
    time_t dateRelDay;
    time_t dateRelSeconds;
    int dateHaveRel;

    time_t dateMonthOrdinal;
    int dateHaveOrdinalMonth;

    time_t dateDayOrdinal;
    time_t dateDayNumber;
    int dateHaveDay;

    const char *dateStart;
    const char *dateInput;
    time_t *dateRelPointer;

    int dateDigitCount;
} DateInfo;

#define YYMALLOC	Tcl_Alloc
#define YYFREE(x)	(Tcl_Free((void*) (x)))

#define yyDSTmode	(info->dateDSTmode)
#define yyDayOrdinal	(info->dateDayOrdinal)
#define yyDayNumber	(info->dateDayNumber)
#define yyMonthOrdinal	(info->dateMonthOrdinal)
#define yyHaveDate	(info->dateHaveDate)
#define yyHaveDay	(info->dateHaveDay)
#define yyHaveOrdinalMonth (info->dateHaveOrdinalMonth)
#define yyHaveRel	(info->dateHaveRel)
#define yyHaveTime	(info->dateHaveTime)
#define yyHaveZone	(info->dateHaveZone)
#define yyTimezone	(info->dateTimezone)
#define yyDay		(info->dateDay)
#define yyMonth		(info->dateMonth)
#define yyYear		(info->dateYear)
#define yyHour		(info->dateHour)
#define yyMinutes	(info->dateMinutes)
#define yySeconds	(info->dateSeconds)
#define yyMeridian	(info->dateMeridian)
#define yyRelMonth	(info->dateRelMonth)
#define yyRelDay	(info->dateRelDay)
#define yyRelSeconds	(info->dateRelSeconds)
#define yyRelPointer	(info->dateRelPointer)
#define yyInput		(info->dateInput)
#define yyDigitCount	(info->dateDigitCount)

#define EPOCH		1970
#define START_OF_TIME	1902
#define END_OF_TIME	2037

/*
 * The offset of tm_year of struct tm returned by localtime, gmtime, etc.
 * Posix requires 1900.
 */

#define TM_YEAR_BASE	1900

#define HOUR(x)		((int) (60 * x))
#define SECSPERDAY	(24L * 60L * 60L)
#define IsLeapYear(x)	((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0))
#define HOUR(x)		((60 * (int)(x)))
#define IsLeapYear(x)	(((x) % 4 == 0) && ((x) % 100 != 0 || (x) % 400 == 0))

#define yyIncrFlags(f)				\
    do {					\
	info->errFlags |= (info->flags & (f));	\
	if (info->errFlags) { YYABORT; }	\
	info->flags |= (f);			\
    } while (0);

/*
 * An entry in the lexical lookup table.
 */

typedef struct _TABLE {
typedef struct {
    const char *name;
    int type;
    time_t value;
    int value;
} TABLE;

/*
 * Daylight-savings mode: on, off, or not yet known.
 */

typedef enum _DSTMODE {
    DSTon, DSToff, DSTmaybe
} DSTMODE;




# ifndef YY_CAST
#  ifdef __cplusplus
#   define YY_CAST(Type, Val) static_cast<Type> (Val)
#   define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast<Type> (Val)
#  else
#   define YY_CAST(Type, Val) ((Type) (Val))
#   define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val))
#  endif
# endif
# ifndef YY_NULLPTR
#  if defined __cplusplus && 201103L <= __cplusplus
#   define YY_NULLPTR nullptr
#  if defined __cplusplus
#   if 201103L <= __cplusplus
#    define YY_NULLPTR nullptr
#   else
#    define YY_NULLPTR 0
#   endif
#  else
#   define YY_NULLPTR 0
#   define YY_NULLPTR ((void*)0)
#  endif
# endif

/* Enabling verbose error messages.  */
#ifdef YYERROR_VERBOSE
# undef YYERROR_VERBOSE
# define YYERROR_VERBOSE 1
#else
# define YYERROR_VERBOSE 0
#endif


/* Debug traces.  */
#ifndef YYDEBUG
# define YYDEBUG 0
#endif
#if YYDEBUG
extern int TclDatedebug;
#endif

/* Token type.  */
/* Token kinds.  */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
  enum yytokentype
  {
    YYEMPTY = -2,
    YYEOF = 0,                     /* "end of file"  */
    YYerror = 256,                 /* error  */
    YYUNDEF = 257,                 /* "invalid token"  */
    tAGO = 258,
    tDAY = 259,
    tDAYZONE = 260,
    tID = 261,
    tMERIDIAN = 262,
    tMONTH = 263,
    tMONTH_UNIT = 264,
    tSTARDATE = 265,
    tSEC_UNIT = 266,
    tAGO = 258,                    /* tAGO  */
    tDAY = 259,                    /* tDAY  */
    tDAYZONE = 260,                /* tDAYZONE  */
    tID = 261,                     /* tID  */
    tMERIDIAN = 262,               /* tMERIDIAN  */
    tMONTH = 263,                  /* tMONTH  */
    tMONTH_UNIT = 264,             /* tMONTH_UNIT  */
    tSTARDATE = 265,               /* tSTARDATE  */
    tSEC_UNIT = 266,               /* tSEC_UNIT  */
    tSNUMBER = 267,
    tUNUMBER = 268,
    tZONE = 269,
    tEPOCH = 270,
    tDST = 271,
    tISOBASE = 272,
    tDAY_UNIT = 273,
    tNEXT = 274
    tUNUMBER = 267,                /* tUNUMBER  */
    tZONE = 268,                   /* tZONE  */
    tZONEwO4 = 269,                /* tZONEwO4  */
    tZONEwO2 = 270,                /* tZONEwO2  */
    tEPOCH = 271,                  /* tEPOCH  */
    tDST = 272,                    /* tDST  */
    tISOBAS8 = 273,                /* tISOBAS8  */
    tISOBAS6 = 274,                /* tISOBAS6  */
    tISOBASL = 275,                /* tISOBASL  */
    tDAY_UNIT = 276,               /* tDAY_UNIT  */
    tNEXT = 277,                   /* tNEXT  */
    SP = 278                       /* SP  */
  };
  typedef enum yytokentype yytoken_kind_t;
#endif

/* Value type.  */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED

union YYSTYPE
{


    time_t Number;
    Tcl_WideInt Number;
    enum _MERIDIAN Meridian;


};

typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
#endif

/* Location type.  */
#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
typedef struct YYLTYPE YYLTYPE;
struct YYLTYPE
{
  int first_line;
  int first_column;
  int last_line;
  int last_column;
};
# define YYLTYPE_IS_DECLARED 1
# define YYLTYPE_IS_TRIVIAL 1
#endif




int TclDateparse (DateInfo* info);



/* Symbol kind.  */
enum yysymbol_kind_t
{
  YYSYMBOL_YYEMPTY = -2,
  YYSYMBOL_YYEOF = 0,                      /* "end of file"  */
  YYSYMBOL_YYerror = 1,                    /* error  */
  YYSYMBOL_YYUNDEF = 2,                    /* "invalid token"  */
  YYSYMBOL_tAGO = 3,                       /* tAGO  */
  YYSYMBOL_tDAY = 4,                       /* tDAY  */
  YYSYMBOL_tDAYZONE = 5,                   /* tDAYZONE  */
  YYSYMBOL_tID = 6,                        /* tID  */
  YYSYMBOL_tMERIDIAN = 7,                  /* tMERIDIAN  */
  YYSYMBOL_tMONTH = 8,                     /* tMONTH  */
  YYSYMBOL_tMONTH_UNIT = 9,                /* tMONTH_UNIT  */
  YYSYMBOL_tSTARDATE = 10,                 /* tSTARDATE  */
  YYSYMBOL_tSEC_UNIT = 11,                 /* tSEC_UNIT  */
  YYSYMBOL_tUNUMBER = 12,                  /* tUNUMBER  */
  YYSYMBOL_tZONE = 13,                     /* tZONE  */
  YYSYMBOL_tZONEwO4 = 14,                  /* tZONEwO4  */
  YYSYMBOL_tZONEwO2 = 15,                  /* tZONEwO2  */
  YYSYMBOL_tEPOCH = 16,                    /* tEPOCH  */
  YYSYMBOL_tDST = 17,                      /* tDST  */
  YYSYMBOL_tISOBAS8 = 18,                  /* tISOBAS8  */
  YYSYMBOL_tISOBAS6 = 19,                  /* tISOBAS6  */
  YYSYMBOL_tISOBASL = 20,                  /* tISOBASL  */
  YYSYMBOL_tDAY_UNIT = 21,                 /* tDAY_UNIT  */
  YYSYMBOL_tNEXT = 22,                     /* tNEXT  */
  YYSYMBOL_SP = 23,                        /* SP  */
  YYSYMBOL_24_ = 24,                       /* ':'  */
  YYSYMBOL_25_ = 25,                       /* ','  */
  YYSYMBOL_26_ = 26,                       /* '-'  */
  YYSYMBOL_27_ = 27,                       /* '/'  */
  YYSYMBOL_28_T_ = 28,                     /* 'T'  */
  YYSYMBOL_29_ = 29,                       /* '.'  */
  YYSYMBOL_30_ = 30,                       /* '+'  */
  YYSYMBOL_YYACCEPT = 31,                  /* $accept  */
  YYSYMBOL_spec = 32,                      /* spec  */
  YYSYMBOL_item = 33,                      /* item  */
  YYSYMBOL_iextime = 34,                   /* iextime  */
  YYSYMBOL_time = 35,                      /* time  */
  YYSYMBOL_zone = 36,                      /* zone  */
  YYSYMBOL_comma = 37,                     /* comma  */
  YYSYMBOL_day = 38,                       /* day  */
  YYSYMBOL_iexdate = 39,                   /* iexdate  */
  YYSYMBOL_date = 40,                      /* date  */
  YYSYMBOL_ordMonth = 41,                  /* ordMonth  */
  YYSYMBOL_isosep = 42,                    /* isosep  */
  YYSYMBOL_isodate = 43,                   /* isodate  */
  YYSYMBOL_isotime = 44,                   /* isotime  */
  YYSYMBOL_iso = 45,                       /* iso  */
  YYSYMBOL_trek = 46,                      /* trek  */
  YYSYMBOL_relspec = 47,                   /* relspec  */
  YYSYMBOL_relunits = 48,                  /* relunits  */
  YYSYMBOL_sign = 49,                      /* sign  */
  YYSYMBOL_unit = 50,                      /* unit  */
  YYSYMBOL_INTNUM = 51,                    /* INTNUM  */
  YYSYMBOL_numitem = 52,                   /* numitem  */
  YYSYMBOL_o_merid = 53                    /* o_merid  */
};
typedef enum yysymbol_kind_t yysymbol_kind_t;
/* Copy the second part of user declarations.  */


/* Second part of user prologue.  */


/*
 * Prototypes of internal functions.
 */

static int		LookupWord(YYSTYPE* yylvalPtr, char *buff);
 static void		TclDateerror(YYLTYPE* location,
static void		TclDateerror(YYLTYPE* location,
				     DateInfo* info, const char *s);
 static int		TclDatelex(YYSTYPE* yylvalPtr, YYLTYPE* location,
static int		TclDatelex(YYSTYPE* yylvalPtr, YYLTYPE* location,
				   DateInfo* info);
static time_t		ToSeconds(time_t Hours, time_t Minutes,
			    time_t Seconds, MERIDIAN Meridian);
MODULE_SCOPE int	yyparse(DateInfo*);




#ifdef short
# undef short
#endif

/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure
   <limits.h> and (if available) <stdint.h> are included
   so that the code can choose integer types of a good width.  */
#ifdef YYTYPE_UINT8
typedef YYTYPE_UINT8 yytype_uint8;
#else

#ifndef __PTRDIFF_MAX__
# include <limits.h> /* INFRINGES ON USER NAME SPACE */
# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
#  include <stdint.h> /* INFRINGES ON USER NAME SPACE */
#  define YY_STDINT_H
# endif
typedef unsigned char yytype_uint8;
#endif

/* Narrow types that promote to a signed type and that can represent a
   signed or unsigned integer of at least N bits.  In tables they can
   save space and decrease cache pressure.  Promoting to a signed type
   helps avoid bugs in integer arithmetic.  */
#ifdef YYTYPE_INT8
typedef YYTYPE_INT8 yytype_int8;

#ifdef __INT_LEAST8_MAX__
typedef __INT_LEAST8_TYPE__ yytype_int8;
#elif defined YY_STDINT_H
typedef int_least8_t yytype_int8;
#else
typedef signed char yytype_int8;
#endif

#ifdef YYTYPE_UINT16
typedef YYTYPE_UINT16 yytype_uint16;
#ifdef __INT_LEAST16_MAX__
typedef __INT_LEAST16_TYPE__ yytype_int16;
#elif defined YY_STDINT_H
typedef int_least16_t yytype_int16;
#else
typedef unsigned short yytype_uint16;
typedef short yytype_int16;
#endif

/* Work around bug in HP-UX 11.23, which defines these macros
   incorrectly for preprocessor constants.  This workaround can likely
   be removed in 2023, as HPE has promised support for HP-UX 11.23
   (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of
   <https://h20195.www2.hpe.com/V2/getpdf.aspx/4AA4-7673ENW.pdf>.  */
#ifdef YYTYPE_INT16
typedef YYTYPE_INT16 yytype_int16;
#ifdef __hpux
# undef UINT_LEAST8_MAX
# undef UINT_LEAST16_MAX
# define UINT_LEAST8_MAX 255
# define UINT_LEAST16_MAX 65535
#endif

#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__
typedef __UINT_LEAST8_TYPE__ yytype_uint8;
#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \
       && UINT_LEAST8_MAX <= INT_MAX)
typedef uint_least8_t yytype_uint8;
#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX
typedef unsigned char yytype_uint8;
#else
typedef short yytype_int16;
typedef short yytype_uint8;
#endif

#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__
typedef __UINT_LEAST16_TYPE__ yytype_uint16;
#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \
       && UINT_LEAST16_MAX <= INT_MAX)
typedef uint_least16_t yytype_uint16;
#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX
typedef unsigned short yytype_uint16;
#else
typedef int yytype_uint16;
#endif

#ifndef YYPTRDIFF_T
# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__
#  define YYPTRDIFF_T __PTRDIFF_TYPE__
#  define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__
# elif defined PTRDIFF_MAX
#  ifndef ptrdiff_t
#   include <stddef.h> /* INFRINGES ON USER NAME SPACE */
#  endif
#  define YYPTRDIFF_T ptrdiff_t
#  define YYPTRDIFF_MAXIMUM PTRDIFF_MAX
# else
#  define YYPTRDIFF_T long
#  define YYPTRDIFF_MAXIMUM LONG_MAX
# endif
#endif

#ifndef YYSIZE_T
# ifdef __SIZE_TYPE__
#  define YYSIZE_T __SIZE_TYPE__
# elif defined size_t
#  define YYSIZE_T size_t
# elif ! defined YYSIZE_T
# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
#  define YYSIZE_T size_t
# else
#  define YYSIZE_T unsigned
# endif
#endif

#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
#define YYSIZE_MAXIMUM                                  \
  YY_CAST (YYPTRDIFF_T,                                 \
           (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1)  \
            ? YYPTRDIFF_MAXIMUM                         \
            : YY_CAST (YYSIZE_T, -1)))

#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X))


/* Stored state numbers (used for stacks). */
typedef yytype_int8 yy_state_t;

/* State numbers in computations.  */
typedef int yy_state_fast_t;

#ifndef YY_
# if defined YYENABLE_NLS && YYENABLE_NLS
#  if ENABLE_NLS
#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
#  endif
# endif
# ifndef YY_
#  define YY_(Msgid) Msgid
# endif
#endif


#ifndef YY_ATTRIBUTE
#ifndef YY_ATTRIBUTE_PURE
# if (defined __GNUC__                                               \
      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
#  define YY_ATTRIBUTE_PURE __attribute__ ((__pure__))
# else
#  define YY_ATTRIBUTE(Spec) /* empty */
#  define YY_ATTRIBUTE_PURE
# endif
#endif

#ifndef YY_ATTRIBUTE_PURE
# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
#endif

#ifndef YY_ATTRIBUTE_UNUSED
# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
#endif

# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__)
#if !defined _Noreturn \
     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
# if defined _MSC_VER && 1200 <= _MSC_VER
#  define _Noreturn __declspec (noreturn)
#  define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__))
# else
#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
#  define YY_ATTRIBUTE_UNUSED
# endif
#endif

/* Suppress unused-variable warnings by "using" E.  */
#if ! defined lint || defined __GNUC__
# define YYUSE(E) ((void) (E))
# define YY_USE(E) ((void) (E))
#else
# define YYUSE(E) /* empty */
# define YY_USE(E) /* empty */
#endif

#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__
# if __GNUC__ * 100 + __GNUC_MINOR__ < 407
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
    _Pragma ("GCC diagnostic push") \
    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
#  define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN                           \
    _Pragma ("GCC diagnostic push")                                     \
    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")
# else
#  define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN                           \
    _Pragma ("GCC diagnostic push")                                     \
    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")              \
    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
# endif
# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
# define YY_IGNORE_MAYBE_UNINITIALIZED_END      \
    _Pragma ("GCC diagnostic pop")
#else
# define YY_INITIAL_VALUE(Value) Value
#endif
#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
# define YY_IGNORE_MAYBE_UNINITIALIZED_END
#endif
#ifndef YY_INITIAL_VALUE
# define YY_INITIAL_VALUE(Value) /* Nothing. */
#endif

#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__
# define YY_IGNORE_USELESS_CAST_BEGIN                          \
    _Pragma ("GCC diagnostic push")                            \
    _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"")
# define YY_IGNORE_USELESS_CAST_END            \
    _Pragma ("GCC diagnostic pop")
#endif
#ifndef YY_IGNORE_USELESS_CAST_BEGIN
# define YY_IGNORE_USELESS_CAST_BEGIN
# define YY_IGNORE_USELESS_CAST_END
#endif


#define YY_ASSERT(E) ((void) (0 && (E)))

#if ! defined yyoverflow || YYERROR_VERBOSE
#if !defined yyoverflow

/* The parser invokes alloca or malloc; define the necessary symbols.  */

# ifdef YYSTACK_USE_ALLOCA
#  if YYSTACK_USE_ALLOCA
#   ifdef __GNUC__
#    define YYSTACK_ALLOC __builtin_alloca
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
558
559
560
561
562
563

564
565
566

567
568

569
570

571
572

573
574
575
576
577


578



579
580




581
582
583
584


585
586
587
588
589
590
591


592
593
594

595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613

614
615
616
617
618


619

620
621
622
623
624
625







626
627
628



629





630
631
632
633
634
635
636
637
638
639
640








641
642
643
644
645
646
647


648
649
650
651
652
653



654
655

656
657
658


659
660

661
662

663
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
707



708
709
710
711
712
713




714

715
716
717
718
719





720
721
722
723




724
725
726
727
728
729
730
731
732
733
734
735
736













737
738
739
740
741



742
743
744
745
746
747






748
749
750
751
752






753
754
755


756
757
758
759
760
761
762








763
764
765
766


767
768
769
770
771
772
773







774
775
776


777
778
779
780
781
782
783
784

785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
















805

806

807
808

809
810
811
812
813
814
815
816
584
585
586
587
588
589
590


591
592
593
594
595
596
597
598
599
600

601
602
603
604
605
606

607
608
609
610
611
612

613
614
615
616
617
618
619
620
621
622
623
624
625

626
627
628


629
630
631
632
633
634
635
636
637
638
639
640
641

642
643
644
645
646

647
648
649
650
651
652
653
654
655
656
657
658

659
660
661

662
663

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
707
708
709
710
711

712
713
714
715


716
717
718
719






720
721
722
723
724
725
726
727
728
729
730
731
732

733
734
735
736
737
738
739
740
741







742
743
744
745
746
747
748
749
750

751




752
753
754





755
756
757
758

759
760


761
762
763

764
765

766
767
768


769
770
771
772









773
774
775
776
777
778
779
780
781
782
783
784
785




786
787
788
789
790









791
792
793
794
795
796
797
798
799
800
801
802
803

804
805
806


807
808
809
810
811

812
813
814


815
816
817
818
819




820
821
822
823
824
825





826
827
828
829
830




831
832
833
834
835












836
837
838
839
840
841
842
843
844
845
846
847
848
849
850



851
852
853
854





855
856
857
858
859
860





861
862
863
864
865
866
867


868
869
870






871
872
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
898


899
900
901
902
903
904
905
906
907
















908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925

926


927

928
929
930
931
932
933
934







-
-
+









-
+





-
+




+
-
+












-
+


-
-
+
+











-
+




-
+











-
+


-
+

-
+

-
+

-
+

-
-
-
-
+
+

+
+
+
-
-
+
+
+
+


-
-
+
+





-
-
+
+


-
+


















-
+



-
-
+
+

+
-
-
-
-
-
-
+
+
+
+
+
+
+



+
+
+
-
+
+
+
+
+




-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-

-
-
-
-
+
+

-
-
-
-
-
+
+
+

-
+

-
-
+
+

-
+

-
+


-
-
+
+


-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+


-
+


-
-
+
+
+


-
+


-
-
+
+
+


-
-
-
-
+
+
+
+

+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
+
+
+

-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+

-
-
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+
+


-
-
+
+


-
-
-
-
-
+
+
+
+
+
+
+



+
+


-
-




+




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
-
+
-
-
+
-







#  ifndef YYFREE
#   define YYFREE free
#   if ! defined free && ! defined EXIT_SUCCESS
void free (void *); /* INFRINGES ON USER NAME SPACE */
#   endif
#  endif
# endif
#endif /* ! defined yyoverflow || YYERROR_VERBOSE */

#endif /* !defined yyoverflow */

#if (! defined yyoverflow \
     && (! defined __cplusplus \
         || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
             && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))

/* A type that is properly aligned for any stack member.  */
union yyalloc
{
  yytype_int16 yyss_alloc;
  yy_state_t yyss_alloc;
  YYSTYPE yyvs_alloc;
  YYLTYPE yyls_alloc;
};

/* The size of the maximum gap between one aligned stack and the next.  */
# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1)

/* The size of an array large to enough to hold all stacks, each with
   N elements.  */
# define YYSTACK_BYTES(N) \
     ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE) \
     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
             + YYSIZEOF (YYLTYPE)) \
      + 2 * YYSTACK_GAP_MAXIMUM)

# define YYCOPY_NEEDED 1

/* Relocate STACK from its old location to the new one.  The
   local variables YYSIZE and YYSTACKSIZE give the old and new number of
   elements in the stack, and YYPTR gives the new location of the
   stack.  Advance YYPTR to a properly aligned location for the next
   stack.  */
# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
    do                                                                  \
      {                                                                 \
        YYSIZE_T yynewbytes;                                            \
        YYPTRDIFF_T yynewbytes;                                         \
        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
        Stack = &yyptr->Stack_alloc;                                    \
        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
        yyptr += yynewbytes / sizeof (*yyptr);                          \
        yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \
        yyptr += yynewbytes / YYSIZEOF (*yyptr);                        \
      }                                                                 \
    while (0)

#endif

#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
/* Copy COUNT objects from SRC to DST.  The source and destination do
   not overlap.  */
# ifndef YYCOPY
#  if defined __GNUC__ && 1 < __GNUC__
#   define YYCOPY(Dst, Src, Count) \
      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
      __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src)))
#  else
#   define YYCOPY(Dst, Src, Count)              \
      do                                        \
        {                                       \
          YYSIZE_T yyi;                         \
          YYPTRDIFF_T yyi;                      \
          for (yyi = 0; yyi < (Count); yyi++)   \
            (Dst)[yyi] = (Src)[yyi];            \
        }                                       \
      while (0)
#  endif
# endif
#endif /* !YYCOPY_NEEDED */

/* YYFINAL -- State number of the termination state.  */
#define YYFINAL  2
/* YYLAST -- Last index in YYTABLE.  */
#define YYLAST   81
#define YYLAST   98

/* YYNTOKENS -- Number of terminals.  */
#define YYNTOKENS  26
#define YYNTOKENS  31
/* YYNNTS -- Number of nonterminals.  */
#define YYNNTS  16
#define YYNNTS  23
/* YYNRULES -- Number of rules.  */
#define YYNRULES  56
#define YYNRULES  72
/* YYNSTATES -- Number of states.  */
#define YYNSTATES  85
#define YYNSTATES  103

/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
   by yylex, with out-of-bounds checking.  */
#define YYUNDEFTOK  2
#define YYMAXUTOK   274
/* YYMAXUTOK -- Last valid token kind.  */
#define YYMAXUTOK   278


/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
   as returned by yylex, with out-of-bounds checking.  */
#define YYTRANSLATE(YYX)                                                \
  ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
#define YYTRANSLATE(YYX)                                \
  (0 <= (YYX) && (YYX) <= YYMAXUTOK                     \
   ? YY_CAST (yysymbol_kind_t, yytranslate[YYX])        \
   : YYSYMBOL_YYUNDEF)

/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
   as returned by yylex, without out-of-bounds checking.  */
static const yytype_uint8 yytranslate[] =
   as returned by yylex.  */
static const yytype_int8 yytranslate[] =
{
       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,    25,    21,    23,    24,    22,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,    20,     2,
       2,     2,     2,    30,    25,    26,    29,    27,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,    24,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,    28,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
      15,    16,    17,    18,    19
      15,    16,    17,    18,    19,    20,    21,    22,    23
};

#if YYDEBUG
  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
static const yytype_uint16 yyrline[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
static const yytype_int16 yyrline[] =
{
       0,   171,   171,   172,   176,   179,   182,   185,   188,   191,
       0,   223,   223,   224,   227,   230,   233,   236,   239,   242,
     245,   249,   254,   257,   263,   269,   277,   282,   287,   291,
     297,   301,   305,   309,   313,   319,   323,   328,   333,   338,
     343,   347,   352,   356,   361,   368,   372,   378,   388,   397,
     406,   416,   430,   435,   438,   441,   444,   447,   450,   455,
     458,   463,   467,   471,   477,   495,   498
     194,   197,   201,   204,   209,   215,   221,   226,   230,   234,
     238,   242,   246,   252,   253,   256,   260,   264,   268,   272,
     276,   282,   288,   292,   297,   298,   303,   307,   312,   316,
     321,   328,   332,   338,   338,   340,   345,   350,   352,   357,
     359,   360,   368,   379,   393,   398,   401,   404,   407,   410,
     413,   416,   421,   424,   429,   433,   437,   443,   446,   449,
     454,   472,   475
};
#endif

/** Accessing symbol of state STATE.  */
#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State])

#if YYDEBUG || YYERROR_VERBOSE || 0
#if YYDEBUG || 0
/* The user-facing name of the symbol whose (internal) number is
   YYSYMBOL.  No bounds checking.  */
static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED;

/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
static const char *const yytname[] =
{
  "$end", "error", "$undefined", "tAGO", "tDAY", "tDAYZONE", "tID",
  "tMERIDIAN", "tMONTH", "tMONTH_UNIT", "tSTARDATE", "tSEC_UNIT",
  "tSNUMBER", "tUNUMBER", "tZONE", "tEPOCH", "tDST", "tISOBASE",
  "tDAY_UNIT", "tNEXT", "':'", "','", "'/'", "'-'", "'.'", "'+'",
  "$accept", "spec", "item", "time", "zone", "day", "date", "ordMonth",
  "iso", "trek", "relspec", "relunits", "sign", "unit", "number",
  "o_merid", YY_NULLPTR
  "\"end of file\"", "error", "\"invalid token\"", "tAGO", "tDAY",
  "tDAYZONE", "tID", "tMERIDIAN", "tMONTH", "tMONTH_UNIT", "tSTARDATE",
  "tSEC_UNIT", "tUNUMBER", "tZONE", "tZONEwO4", "tZONEwO2", "tEPOCH",
  "tDST", "tISOBAS8", "tISOBAS6", "tISOBASL", "tDAY_UNIT", "tNEXT", "SP",
  "':'", "','", "'-'", "'/'", "'T'", "'.'", "'+'", "$accept", "spec",
  "item", "iextime", "time", "zone", "comma", "day", "iexdate", "date",
  "ordMonth", "isosep", "isodate", "isotime", "iso", "trek", "relspec",
  "relunits", "sign", "unit", "INTNUM", "numitem", "o_merid", YY_NULLPTR
};
#endif

# ifdef YYPRINT
/* YYTOKNUM[NUM] -- (External) token number corresponding to the
   (internal) symbol number NUM (which must be that of a token).  */
static const yytype_uint16 yytoknum[] =
static const char *
yysymbol_name (yysymbol_kind_t yysymbol)
{
       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      58,    44,    47,    45,    46,    43
};
# endif
  return yytname[yysymbol];
}
#endif

#define YYPACT_NINF -18
#define YYPACT_NINF (-21)

#define yypact_value_is_default(Yystate) \
  (!!((Yystate) == (-18)))
#define yypact_value_is_default(Yyn) \
  ((Yyn) == YYPACT_NINF)

#define YYTABLE_NINF -1
#define YYTABLE_NINF (-68)

#define yytable_value_is_error(Yytable_value) \
#define yytable_value_is_error(Yyn) \
  0

  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
     STATE-NUM.  */
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
   STATE-NUM.  */
static const yytype_int8 yypact[] =
{
     -18,     2,   -18,   -17,   -18,    -4,   -18,    10,   -18,    22,
       8,   -18,    18,   -18,    39,   -18,   -18,   -18,   -18,   -18,
     -18,   -18,   -18,   -18,   -18,   -18,    25,    21,   -18,   -18,
     -18,    16,    14,   -18,   -18,    28,    36,    41,    -5,   -18,
     -18,     5,   -18,   -18,   -18,    47,   -18,   -18,    42,    46,
      48,   -18,    -6,    40,    43,    44,    49,   -18,   -18,   -18,
     -18,   -18,   -18,   -18,   -18,    50,   -18,    51,    55,    57,
      58,    65,   -18,   -18,    59,    54,   -18,    62,    63,    60,
     -18,    64,    61,    66,   -18
     -21,    11,   -21,   -20,   -21,     5,   -21,    -9,   -21,    46,
      17,     9,     9,   -21,   -21,   -21,    24,   -21,    57,   -21,
     -21,   -21,    33,   -21,   -21,   -21,   -21,   -21,   -21,   -15,
     -21,   -21,   -21,    45,    26,   -21,    -7,   -21,    51,   -21,
     -20,   -21,   -21,   -21,    48,   -21,   -21,    67,    68,    52,
      69,   -21,    -9,    -9,   -21,   -21,   -21,   -21,    74,   -21,
      -7,   -21,   -21,   -21,   -21,    44,   -21,    79,    40,    -7,
     -21,   -21,    72,    73,   -21,    62,    61,    63,    64,   -21,
     -21,   -21,   -21,    66,   -21,   -21,   -21,   -21,    84,    -7,
     -21,   -21,   -21,    80,    81,    82,    83,   -21,   -21,   -21,
     -21,   -21,   -21
};

  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
     Performed when YYTABLE does not specify something else to do.  Zero
     means the default is an error.  */
static const yytype_uint8 yydefact[] =
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
   Performed when YYTABLE does not specify something else to do.  Zero
   means the default is an error.  */
static const yytype_int8 yydefact[] =
{
       2,     0,     1,    20,    18,     0,    53,     0,    51,    54,
      17,    33,    27,    52,     0,    49,    50,     3,     4,     5,
       8,     6,     7,    10,    11,     9,    43,     0,    48,    12,
      21,    30,     0,    22,    13,    32,     0,     0,     0,    45,
      16,     0,    40,    24,    35,     0,    46,    42,    19,     0,
       0,    34,    55,    25,     0,     0,     0,    38,    36,    47,
      23,    44,    31,    41,    56,     0,    14,     0,     0,     0,
       0,    55,    26,    28,    29,     0,    15,     0,     0,     0,
      39,     0,     0,     0,    37
       2,     0,     1,    25,    19,     0,    66,     0,    64,    70,
      18,     0,     0,    39,    45,    46,     0,    65,     0,    62,
      63,     3,    71,     4,     5,     8,    47,     6,     7,    34,
      10,    11,     9,    55,     0,    61,     0,    12,    23,    26,
      36,    67,    69,    68,     0,    27,    15,    38,     0,     0,
       0,    17,     0,     0,    52,    51,    30,    41,    67,    59,
       0,    72,    16,    44,    43,     0,    54,    67,     0,    22,
      58,    24,     0,     0,    40,    14,     0,     0,    32,    20,
      21,    42,    60,     0,    48,    49,    50,    29,    67,     0,
      57,    37,    53,     0,     0,     0,     0,    28,    56,    13,
      35,    31,    33
};

  /* YYPGOTO[NTERM-NUM].  */
/* YYPGOTO[NTERM-NUM].  */
static const yytype_int8 yypgoto[] =
{
     -18,   -18,   -18,   -18,   -18,   -18,   -18,   -18,   -18,   -18,
     -18,   -18,   -18,    -9,   -18,     7
     -21,   -21,   -21,    31,   -21,   -21,    58,   -21,   -21,   -21,
     -21,   -21,   -21,   -21,   -21,   -21,   -21,   -21,    -5,   -18,
      -6,   -21,   -21
};

  /* YYDEFGOTO[NTERM-NUM].  */
/* YYDEFGOTO[NTERM-NUM].  */
static const yytype_int8 yydefgoto[] =
{
      -1,     1,    17,    18,    19,    20,    21,    22,    23,    24,
      25,    26,    27,    28,    29,    66
       0,     1,    21,    22,    23,    24,    39,    25,    26,    27,
      28,    65,    29,    86,    30,    31,    32,    33,    34,    35,
      36,    37,    62
};

  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
     positive, shift that token.  If negative, reduce the rule whose
     number is the opposite.  If YYTABLE_NINF, syntax error.  */
static const yytype_uint8 yytable[] =
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
   positive, shift that token.  If negative, reduce the rule whose
   number is the opposite.  If YYTABLE_NINF, syntax error.  */
static const yytype_int8 yytable[] =
{
      59,    44,     6,    41,     8,    38,    52,    53,    63,    42,
      39,    64,     2,    54,    30,    46,     3,     4,    55,    31,
       5,     6,     7,     8,    65,     9,    10,    11,    56,    12,
      13,    14,    57,    32,    40,    15,    33,    16,    47,    34,
      35,     6,    41,     8,    48,    42,    59,    49,    50,    61,
      13,    51,    36,    43,    37,    38,    60,    44,     6,    52,
      43,     2,    60,    64,    17,     3,     4,    40,    70,     5,
       6,     7,     8,     9,    10,    11,    12,    13,    69,    14,
      15,    16,    17,    18,    51,    19,    54,    19,    67,    20,
      61,    20,    82,    55,    42,    43,    79,    80,    66,    68,
      45,    90,    88,    46,    47,   -67,    83,   -67,    42,    43,
       8,     6,    45,     8,    53,    58,     6,    13,     8,    62,
      13,    63,    67,    71,    72,    13,    68,    69,    73,    70,
      74,    75,    64,    77,    78,    79,    80,    82,    76,    84,
      81,    83
      76,    56,    89,    84,    77,    57,     6,   -67,     8,    58,
      48,    98,    49,    50,    71,    42,    43,    73,    17,    74,
      75,    78,    81,    87,    91,    92,    93,    94,    97,    95,
      48,    96,    99,   100,   101,   102,    85,     0,    72
};

static const yytype_uint8 yycheck[] =
{
       9,     7,     0,     8,    21,    14,     4,     5,    13,    13,
       8,     9,    10,    11,    20,    13,    14,    15,    13,    17,
      18,    19,    17,    13,    16,    23,     4,    25,     3,     7,
       8,     9,    14,    11,    13,    17,    45,    21,    24,    48,
      18,    13,    20,     4,    22,    23,     4,     8,     9,    13,
      11,     9,    13,    11,    13,     8,     9,    18,    11,    13,
      18,    13,    22,    13,    13,    18,    23,    23,    13,    20,
      13,    13,     7,    14,    20,    13,    13,    13,    71,    13,
      20,    20

static const yytype_int8 yycheck[] =
{
      18,     7,     9,    12,    11,    25,    11,    12,    23,    18,
      19,     0,    18,    28,    21,     4,     5,    12,    36,     8,
       9,    10,    11,    12,    13,    14,    15,    16,    34,    18,
      19,    20,    21,    22,    17,    26,    12,    26,    12,    30,
       7,    30,    60,    19,    18,    19,    52,    53,     3,    23,
       4,    69,    12,     7,     8,     9,    12,    11,    18,    19,
       8,     4,    68,    19,    12,     8,     9,    21,    11,    12,
      24,    89,    26,    27,    23,    18,    19,    29,    21,    12,
      12,    12,     8,     4,    12,    12,    24,    26,     4,    26,
      24,    27,    12,    12,    12,    12,    65,    -1,    40
};

  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
     symbol of state STATE-NUM.  */
static const yytype_uint8 yystos[] =
/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of
   state STATE-NUM.  */
static const yytype_int8 yystos[] =
{
       0,    27,     0,     4,     5,     8,     9,    10,    11,    13,
      14,    15,    17,    18,    19,    23,    25,    28,    29,    30,
      31,    32,    33,    34,    35,    36,    37,    38,    39,    40,
      21,    13,    13,     4,     7,     8,    20,    22,    23,    39,
      16,    14,    17,     4,     8,    13,    39,     3,    13,    21,
       0,    32,     0,     4,     5,     8,     9,    10,    11,    12,
      13,    14,    15,    16,    18,    19,    20,    21,    22,    26,
      30,    33,    34,    35,    36,    38,    39,    40,    41,    43,
      45,    46,    47,    48,    49,    50,    51,    52,    25,    37,
      12,    12,    18,    19,    51,     4,     7,     8,    24,    26,
      27,    17,    49,    49,    12,    19,     4,     8,    12,    50,
      24,    13,    13,    13,     8,    13,    13,    17,     8,    39,
       4,    39,    13,    13,     7,    20,    41,    22,    23,    23,
      20,    13,    13,    13,    13,    13,    41,    14,    20,    13,
      13,    20,    13,    20,    13
};
      51,     7,    53,    23,    28,    42,     3,    12,    23,    51,
      50,    23,    37,    29,    12,    12,     8,    12,    12,    51,
      51,     8,    50,    12,    19,    34,    44,     4,    12,    51,
      50,    12,    12,    24,    26,    26,    27,     4,    50,    12,
      12,    12,    12
};

  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
static const yytype_uint8 yyr1[] =
/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM.  */
static const yytype_int8 yyr1[] =
{
       0,    26,    27,    27,    28,    28,    28,    28,    28,    28,
      28,    28,    28,    29,    29,    29,    30,    30,    30,    30,
      31,    31,    31,    31,    31,    32,    32,    32,    32,    32,
      32,    32,    32,    32,    32,    33,    33,    34,    34,    34,
      34,    35,    36,    36,    37,    37,    37,    37,    37,    38,
      38,    39,    39,    39,    40,    41,    41
       0,    31,    32,    32,    33,    33,    33,    33,    33,    33,
      33,    33,    33,    34,    34,    35,    35,    36,    36,    36,
      36,    36,    36,    37,    37,    38,    38,    38,    38,    38,
      38,    39,    40,    40,    40,    40,    40,    40,    40,    40,
      40,    41,    41,    42,    42,    43,    43,    43,    44,    44,
      45,    45,    45,    46,    47,    47,    48,    48,    48,    48,
      48,    48,    49,    49,    50,    50,    50,    51,    51,    51,
      52,    53,    53
};

  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
static const yytype_uint8 yyr2[] =
/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM.  */
static const yytype_int8 yyr2[] =
{
       0,     2,     0,     2,     1,     1,     1,     1,     1,     1,
       1,     1,     1,     2,     4,     6,     2,     1,     1,     2,
       1,     2,     2,     3,     2,     3,     5,     1,     5,     5,
       2,     4,     2,     1,     3,     2,     3,    11,     3,     7,
       2,     4,     2,     1,     3,     2,     2,     3,     1,     1,
       1,     1,     1,     1,     1,     0,     1
       1,     1,     1,     5,     3,     2,     2,     2,     1,     1,
       3,     3,     2,     1,     2,     1,     2,     2,     4,     3,
       2,     5,     3,     5,     1,     5,     2,     4,     2,     1,
       3,     2,     3,     1,     1,     1,     1,     1,     1,     1,
       3,     2,     2,     4,     2,     1,     4,     3,     2,     2,
       3,     1,     1,     1,     1,     1,     1,     1,     1,     1,
       1,     0,     1
};


enum { YYENOMEM = -2 };

#define yyerrok         (yyerrstatus = 0)
#define yyclearin       (yychar = YYEMPTY)
#define YYEMPTY         (-2)
#define YYEOF           0

#define YYACCEPT        goto yyacceptlab
#define YYABORT         goto yyabortlab
#define YYERROR         goto yyerrorlab
#define YYNOMEM         goto yyexhaustedlab


#define YYRECOVERING()  (!!yyerrstatus)

#define YYBACKUP(Token, Value)                                  \
do                                                              \
  if (yychar == YYEMPTY)                                        \
    {                                                           \
      yychar = (Token);                                         \
      yylval = (Value);                                         \
      YYPOPSTACK (yylen);                                       \
      yystate = *yyssp;                                         \
      goto yybackup;                                            \
    }                                                           \
  else                                                          \
    {                                                           \
      yyerror (&yylloc, info, YY_("syntax error: cannot back up")); \
      YYERROR;                                                  \
    }                                                           \
while (0)
#define YYBACKUP(Token, Value)                                    \
  do                                                              \
    if (yychar == YYEMPTY)                                        \
      {                                                           \
        yychar = (Token);                                         \
        yylval = (Value);                                         \
        YYPOPSTACK (yylen);                                       \
        yystate = *yyssp;                                         \
        goto yybackup;                                            \
      }                                                           \
    else                                                          \
      {                                                           \
        yyerror (&yylloc, info, YY_("syntax error: cannot back up")); \
        YYERROR;                                                  \
      }                                                           \
  while (0)

/* Backward compatibility with an undocumented macro.
/* Error token number */
   Use YYerror or YYUNDEF. */
#define YYTERROR        1
#define YYERRCODE       256
#define YYERRCODE YYUNDEF


/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
   If N is 0, then set CURRENT to the empty location which ends
   the previous symbol: RHS[0] (always defined).  */

#ifndef YYLLOC_DEFAULT
# define YYLLOC_DEFAULT(Current, Rhs, N)                                \
846
847
848
849
850
851
852
853

854
855
856


857
858







859
860
861
862
863

864
865
866

867
868
869
870
871
872
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

898
899
900
901
902
903

904
905
906
907
908
909
910
911



912
913

914

915
916
917
918
919




920
921
922
923

924
925
926


927
928
929
930
931
932



933
934

935

936
937
938


939
940
941
942
943




944
945
946
947
948
949
950
951
952

953
954
955
956
957
958
959
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
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







-
+



+
+
-
-
+
+
+
+
+
+
+




-
+


-
+



















-
+

-
-
+
+
+
+
+

-
-
-
-
+
+
+
+
+
+
+
+
+


-
+





-
+





-
-
-
+
+
+


+
-
+

-
-
-
-
+
+
+
+


-
-
+
-
-
-
+
+



-
-
-
+
+
+


+
-
+

-
-
+
+

-
-
-
-
+
+
+
+








-
+







# define YYDPRINTF(Args)                        \
do {                                            \
  if (yydebug)                                  \
    YYFPRINTF Args;                             \
} while (0)


/* YY_LOCATION_PRINT -- Print the location on the stream.
/* YYLOCATION_PRINT -- Print the location on the stream.
   This macro was not mandated originally: define only if we know
   we won't break user code: when these are the locations we know.  */

# ifndef YYLOCATION_PRINT

#ifndef YY_LOCATION_PRINT
# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
#  if defined YY_LOCATION_PRINT

   /* Temporary convenience wrapper in case some people defined the
      undocumented and private YY_LOCATION_PRINT macros.  */
#   define YYLOCATION_PRINT(File, Loc)  YY_LOCATION_PRINT(File, *(Loc))

#  elif defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL

/* Print *YYLOCP on YYO.  Private, do not rely on its existence. */

YY_ATTRIBUTE_UNUSED
static unsigned
static int
yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp)
{
  unsigned res = 0;
  int res = 0;
  int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0;
  if (0 <= yylocp->first_line)
    {
      res += YYFPRINTF (yyo, "%d", yylocp->first_line);
      if (0 <= yylocp->first_column)
        res += YYFPRINTF (yyo, ".%d", yylocp->first_column);
    }
  if (0 <= yylocp->last_line)
    {
      if (yylocp->first_line < yylocp->last_line)
        {
          res += YYFPRINTF (yyo, "-%d", yylocp->last_line);
          if (0 <= end_col)
            res += YYFPRINTF (yyo, ".%d", end_col);
        }
      else if (0 <= end_col && yylocp->first_column < end_col)
        res += YYFPRINTF (yyo, "-%d", end_col);
    }
  return res;
 }
}

#  define YY_LOCATION_PRINT(File, Loc)          \
  yy_location_print_ (File, &(Loc))
#   define YYLOCATION_PRINT  yy_location_print_

    /* Temporary convenience wrapper in case some people defined the
       undocumented and private YY_LOCATION_PRINT macros.  */
#   define YY_LOCATION_PRINT(File, Loc)  YYLOCATION_PRINT(File, &(Loc))

# else
#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
# endif
#endif
#  else

#   define YYLOCATION_PRINT(File, Loc) ((void) 0)
    /* Temporary convenience wrapper in case some people defined the
       undocumented and private YY_LOCATION_PRINT macros.  */
#   define YY_LOCATION_PRINT  YYLOCATION_PRINT

#  endif
# endif /* !defined YYLOCATION_PRINT */


# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
# define YY_SYMBOL_PRINT(Title, Kind, Value, Location)                    \
do {                                                                      \
  if (yydebug)                                                            \
    {                                                                     \
      YYFPRINTF (stderr, "%s ", Title);                                   \
      yy_symbol_print (stderr,                                            \
                  Type, Value, Location, info); \
                  Kind, Value, Location, info); \
      YYFPRINTF (stderr, "\n");                                           \
    }                                                                     \
} while (0)


/*----------------------------------------.
| Print this symbol's value on YYOUTPUT.  |
`----------------------------------------*/
/*-----------------------------------.
| Print this symbol's value on YYO.  |
`-----------------------------------*/

static void
yy_symbol_value_print (FILE *yyo,
yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, DateInfo* info)
                       yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, DateInfo* info)
{
  FILE *yyo = yyoutput;
  YYUSE (yyo);
  YYUSE (yylocationp);
  YYUSE (info);
  FILE *yyoutput = yyo;
  YY_USE (yyoutput);
  YY_USE (yylocationp);
  YY_USE (info);
  if (!yyvaluep)
    return;
# ifdef YYPRINT
  if (yytype < YYNTOKENS)
  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
# endif
  YYUSE (yytype);
  YY_USE (yykind);
  YY_IGNORE_MAYBE_UNINITIALIZED_END
}


/*--------------------------------.
| Print this symbol on YYOUTPUT.  |
`--------------------------------*/
/*---------------------------.
| Print this symbol on YYO.  |
`---------------------------*/

static void
yy_symbol_print (FILE *yyo,
yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, DateInfo* info)
                 yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, DateInfo* info)
{
  YYFPRINTF (yyoutput, "%s %s (",
             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
  YYFPRINTF (yyo, "%s %s (",
             yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind));

  YY_LOCATION_PRINT (yyoutput, *yylocationp);
  YYFPRINTF (yyoutput, ": ");
  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, info);
  YYFPRINTF (yyoutput, ")");
  YYLOCATION_PRINT (yyo, yylocationp);
  YYFPRINTF (yyo, ": ");
  yy_symbol_value_print (yyo, yykind, yyvaluep, yylocationp, info);
  YYFPRINTF (yyo, ")");
}

/*------------------------------------------------------------------.
| yy_stack_print -- Print the state stack from its BOTTOM up to its |
| TOP (included).                                                   |
`------------------------------------------------------------------*/

static void
yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop)
{
  YYFPRINTF (stderr, "Stack now");
  for (; yybottom <= yytop; yybottom++)
    {
      int yybot = *yybottom;
      YYFPRINTF (stderr, " %d", yybot);
    }
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
1101
1102
1103
1104
1105
1106
1107

1108
1109
1110

1111
1112
1113

1114
1115
1116
1117
1118
1119
1120



1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137


1138
1139
1140
1141
1142
1143
1144
1145
1146







-
+
+

-
+


-
+






-
-
-
+
+
+














-
-
+
+









/*------------------------------------------------.
| Report that the YYRULE is going to be reduced.  |
`------------------------------------------------*/

static void
yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, DateInfo* info)
yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp,
                 int yyrule, DateInfo* info)
{
  unsigned long yylno = yyrline[yyrule];
  int yylno = yyrline[yyrule];
  int yynrhs = yyr2[yyrule];
  int yyi;
  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
  YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n",
             yyrule - 1, yylno);
  /* The symbols being reduced.  */
  for (yyi = 0; yyi < yynrhs; yyi++)
    {
      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
      yy_symbol_print (stderr,
                       yystos[yyssp[yyi + 1 - yynrhs]],
                       &(yyvsp[(yyi + 1) - (yynrhs)])
                       , &(yylsp[(yyi + 1) - (yynrhs)])                       , info);
                       YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]),
                       &yyvsp[(yyi + 1) - (yynrhs)],
                       &(yylsp[(yyi + 1) - (yynrhs)]), info);
      YYFPRINTF (stderr, "\n");
    }
}

# define YY_REDUCE_PRINT(Rule)          \
do {                                    \
  if (yydebug)                          \
    yy_reduce_print (yyssp, yyvsp, yylsp, Rule, info); \
} while (0)

/* Nonzero means print parse trace.  It is left uninitialized so that
   multiple parsers can coexist.  */
int yydebug;
#else /* !YYDEBUG */
# define YYDPRINTF(Args)
# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
# define YYDPRINTF(Args) ((void) 0)
# define YY_SYMBOL_PRINT(Title, Kind, Value, Location)
# define YY_STACK_PRINT(Bottom, Top)
# define YY_REDUCE_PRINT(Rule)
#endif /* !YYDEBUG */


/* YYINITDEPTH -- initial size of the parser's stacks.  */
#ifndef YYINITDEPTH
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389

1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401



1402
1403
1404
1405
1406

1407
1408
1409

1410
1411
1412
1413
1414

1415
1416
1417
1418
1419
1420

1421
1422


1423
1424

1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438

1439
1440



1441
1442
1443
1444

1445
1446
1447
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


1478











1479
1480
1481
1482
1483
1484
1485
1155
1156
1157
1158
1159
1160
1161

1162








1163





1164















































































































































































































1165
1166
1167
1168
1169
1170

1171
1172
1173



1174
1175
1176
1177
1178

1179
1180
1181

1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197

1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216

1217
1218

1219
1220

1221
1222






1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360

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
1387
1388
1389
1390

1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411







-

-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-






-
+
+

-
-
-
+
+
+


-
+


-
+


+
+











-
+


















-
+

-
+

-
+

-
-
-
-
-
-
+


+
+
+
-
-
-
-
+
+
+
+

-
+

-
-
+
+

-
+

-
-
+
+

-
-
-
-
-

+

-
-
+
+





-
+
-
-
-
-
+
+
+
-







-
-
-
-
-


-
-
-

+



+

-
+

-
+




+
+
+
+
-
-
+
+
+
+
+
+
+


+
+
+


-
+

-
+




+

-







-
-
-
+
+
+

-
-


+

-
-
+
-
-


-
+





-
+

-
+
+

-
+








-





+
-
-
+
+
+




+

-





+





-










-
+


-
+





-
+
+

+
+
+
+
+
+
+
+
+
+
+







   evaluated with infinite-precision integer arithmetic.  */

#ifndef YYMAXDEPTH
# define YYMAXDEPTH 10000
#endif


#if YYERROR_VERBOSE

# ifndef yystrlen
#  if defined __GLIBC__ && defined _STRING_H
#   define yystrlen strlen
#  else
/* Return the length of YYSTR.  */
static YYSIZE_T
yystrlen (const char *yystr)
{

  YYSIZE_T yylen;
  for (yylen = 0; yystr[yylen]; yylen++)
    continue;
  return yylen;
}

#  endif
# endif

# ifndef yystpcpy
#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
#   define yystpcpy stpcpy
#  else
/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
   YYDEST.  */
static char *
yystpcpy (char *yydest, const char *yysrc)
{
  char *yyd = yydest;
  const char *yys = yysrc;

  while ((*yyd++ = *yys++) != '\0')
    continue;

  return yyd - 1;
}
#  endif
# endif

# ifndef yytnamerr
/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
   quotes and backslashes, so that it's suitable for yyerror.  The
   heuristic is that double-quoting is unnecessary unless the string
   contains an apostrophe, a comma, or backslash (other than
   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
   null, do not copy; instead, return the length of what the result
   would have been.  */
static YYSIZE_T
yytnamerr (char *yyres, const char *yystr)
{
  if (*yystr == '"')
    {
      YYSIZE_T yyn = 0;
      char const *yyp = yystr;

      for (;;)
        switch (*++yyp)
          {
          case '\'':
          case ',':
            goto do_not_strip_quotes;

          case '\\':
            if (*++yyp != '\\')
              goto do_not_strip_quotes;
            /* Fall through.  */
          default:
            if (yyres)
              yyres[yyn] = *yyp;
            yyn++;
            break;

          case '"':
            if (yyres)
              yyres[yyn] = '\0';
            return yyn;
          }
    do_not_strip_quotes: ;
    }

  if (! yyres)
    return yystrlen (yystr);

  return yystpcpy (yyres, yystr) - yyres;
}
# endif

/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
   about the unexpected token YYTOKEN for the state stack whose top is
   YYSSP.

   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
   not large enough to hold the message.  In that case, also set
   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
   required number of bytes is too large to store.  */
static int
yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
                yytype_int16 *yyssp, int yytoken)
{
  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
  YYSIZE_T yysize = yysize0;
  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
  /* Internationalized format string. */
  const char *yyformat = YY_NULLPTR;
  /* Arguments of yyformat. */
  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
  /* Number of reported tokens (one for the "unexpected", one per
     "expected"). */
  int yycount = 0;

  /* There are many possibilities here to consider:
     - If this state is a consistent state with a default action, then
       the only way this function was invoked is if the default action
       is an error action.  In that case, don't check for expected
       tokens because there are none.
     - The only way there can be no lookahead present (in yychar) is if
       this state is a consistent state with a default action.  Thus,
       detecting the absence of a lookahead is sufficient to determine
       that there is no unexpected or expected token to report.  In that
       case, just report a simple "syntax error".
     - Don't assume there isn't a lookahead just because this state is a
       consistent state with a default action.  There might have been a
       previous inconsistent state, consistent state with a non-default
       action, or user semantic action that manipulated yychar.
     - Of course, the expected token list depends on states to have
       correct lookahead information, and it depends on the parser not
       to perform extra reductions after fetching a lookahead from the
       scanner and before detecting a syntax error.  Thus, state merging
       (from LALR or IELR) and default reductions corrupt the expected
       token list.  However, the list is correct for canonical LR with
       one exception: it will still contain any token that will not be
       accepted due to an error action in a later state.
  */
  if (yytoken != YYEMPTY)
    {
      int yyn = yypact[*yyssp];
      yyarg[yycount++] = yytname[yytoken];
      if (!yypact_value_is_default (yyn))
        {
          /* Start YYX at -YYN if negative to avoid negative indexes in
             YYCHECK.  In other words, skip the first -YYN actions for
             this state because they are default actions.  */
          int yyxbegin = yyn < 0 ? -yyn : 0;
          /* Stay within bounds of both yycheck and yytname.  */
          int yychecklim = YYLAST - yyn + 1;
          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
          int yyx;

          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
                && !yytable_value_is_error (yytable[yyx + yyn]))
              {
                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
                  {
                    yycount = 1;
                    yysize = yysize0;
                    break;
                  }
                yyarg[yycount++] = yytname[yyx];
                {
                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
                  if (! (yysize <= yysize1
                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
                    return 2;
                  yysize = yysize1;
                }
              }
        }
    }

  switch (yycount)
    {
# define YYCASE_(N, S)                      \
      case N:                               \
        yyformat = S;                       \
      break
    default: /* Avoid compiler warnings. */
      YYCASE_(0, YY_("syntax error"));
      YYCASE_(1, YY_("syntax error, unexpected %s"));
      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
# undef YYCASE_
    }

  {
    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
      return 2;
    yysize = yysize1;
  }

  if (*yymsg_alloc < yysize)
    {
      *yymsg_alloc = 2 * yysize;
      if (! (yysize <= *yymsg_alloc
             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
      return 1;
    }

  /* Avoid sprintf, as that infringes on the user's name space.
     Don't have undefined behavior even if the translation
     produced a string with the wrong number of "%s"s.  */
  {
    char *yyp = *yymsg;
    int yyi = 0;
    while ((*yyp = *yyformat) != '\0')
      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
        {
          yyp += yytnamerr (yyp, yyarg[yyi++]);
          yyformat += 2;
        }
      else
        {
          yyp++;
          yyformat++;
        }
  }
  return 0;
}
#endif /* YYERROR_VERBOSE */

/*-----------------------------------------------.
| Release the memory associated to this symbol.  |
`-----------------------------------------------*/

static void
yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, DateInfo* info)
yydestruct (const char *yymsg,
            yysymbol_kind_t yykind, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, DateInfo* info)
{
  YYUSE (yyvaluep);
  YYUSE (yylocationp);
  YYUSE (info);
  YY_USE (yyvaluep);
  YY_USE (yylocationp);
  YY_USE (info);
  if (!yymsg)
    yymsg = "Deleting";
  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
  YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp);

  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
  YYUSE (yytype);
  YY_USE (yykind);
  YY_IGNORE_MAYBE_UNINITIALIZED_END
}






/*----------.
| yyparse.  |
`----------*/

int
yyparse (DateInfo* info)
{
/* The lookahead symbol.  */
/* Lookahead token kind.  */
int yychar;


/* The semantic value of the lookahead symbol.  */
/* Default value used for initialization, for pacifying older GCCs
   or non-GCC compilers.  */
YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);

/* Location data for the lookahead symbol.  */
static YYLTYPE yyloc_default
# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
  = { 1, 1, 1, 1 }
# endif
;
YYLTYPE yylloc = yyloc_default;

    /* Number of syntax errors so far.  */
    int yynerrs;
    int yynerrs = 0;

    int yystate;
    yy_state_fast_t yystate = 0;
    /* Number of tokens to shift before error messages enabled.  */
    int yyerrstatus;
    int yyerrstatus = 0;

    /* The stacks and their tools:
       'yyss': related to states.
       'yyvs': related to semantic values.
       'yyls': related to locations.

       Refer to the stacks through separate pointers, to allow yyoverflow
    /* Refer to the stacks through separate pointers, to allow yyoverflow
       to reallocate them elsewhere.  */

    /* Their size.  */
    YYPTRDIFF_T yystacksize = YYINITDEPTH;

    /* The state stack.  */
    yytype_int16 yyssa[YYINITDEPTH];
    yytype_int16 *yyss;
    yytype_int16 *yyssp;
    /* The state stack: array, bottom, top.  */
    yy_state_t yyssa[YYINITDEPTH];
    yy_state_t *yyss = yyssa;
    yy_state_t *yyssp = yyss;

    /* The semantic value stack.  */
    /* The semantic value stack: array, bottom, top.  */
    YYSTYPE yyvsa[YYINITDEPTH];
    YYSTYPE *yyvs;
    YYSTYPE *yyvsp;
    YYSTYPE *yyvs = yyvsa;
    YYSTYPE *yyvsp = yyvs;

    /* The location stack.  */
    /* The location stack: array, bottom, top.  */
    YYLTYPE yylsa[YYINITDEPTH];
    YYLTYPE *yyls;
    YYLTYPE *yylsp;
    YYLTYPE *yyls = yylsa;
    YYLTYPE *yylsp = yyls;

    /* The locations where the error started and ended.  */
    YYLTYPE yyerror_range[3];

    YYSIZE_T yystacksize;

  int yyn;
  /* The return value of yyparse.  */
  int yyresult;
  /* Lookahead token as an internal (translated) token number.  */
  int yytoken = 0;
  /* Lookahead symbol kind.  */
  yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY;
  /* The variables used to return semantic value and location from the
     action routines.  */
  YYSTYPE yyval;
  YYLTYPE yyloc;

#if YYERROR_VERBOSE
  /* The locations where the error started and ended.  */
  /* Buffer for error messages, and its allocated size.  */
  char yymsgbuf[128];
  char *yymsg = yymsgbuf;
  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
  YYLTYPE yyerror_range[3];


#endif

#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N), yylsp -= (N))

  /* The number of symbols on the RHS of the reduced rule.
     Keep to zero when no symbol should be popped.  */
  int yylen = 0;

  yyssp = yyss = yyssa;
  yyvsp = yyvs = yyvsa;
  yylsp = yyls = yylsa;
  yystacksize = YYINITDEPTH;

  YYDPRINTF ((stderr, "Starting parse\n"));

  yystate = 0;
  yyerrstatus = 0;
  yynerrs = 0;
  yychar = YYEMPTY; /* Cause a token to be read.  */

  yylsp[0] = yylloc;
  goto yysetstate;


/*------------------------------------------------------------.
| yynewstate -- Push a new state, which is found in yystate.  |
| yynewstate -- push a new state, which is found in yystate.  |
`------------------------------------------------------------*/
 yynewstate:
yynewstate:
  /* In all cases, when you get here, the value and location stacks
     have just been pushed.  So pushing a state here evens the stacks.  */
  yyssp++;


/*--------------------------------------------------------------------.
| yysetstate -- set current state (the top of the stack) to yystate.  |
`--------------------------------------------------------------------*/
 yysetstate:
  *yyssp = yystate;
yysetstate:
  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
  YY_ASSERT (0 <= yystate && yystate < YYNSTATES);
  YY_IGNORE_USELESS_CAST_BEGIN
  *yyssp = YY_CAST (yy_state_t, yystate);
  YY_IGNORE_USELESS_CAST_END
  YY_STACK_PRINT (yyss, yyssp);

  if (yyss + yystacksize - 1 <= yyssp)
#if !defined yyoverflow && !defined YYSTACK_RELOCATE
    YYNOMEM;
#else
    {
      /* Get the current used size of the three stacks, in elements.  */
      YYSIZE_T yysize = yyssp - yyss + 1;
      YYPTRDIFF_T yysize = yyssp - yyss + 1;

#ifdef yyoverflow
# if defined yyoverflow
      {
        /* Give user a chance to reallocate the stack.  Use copies of
           these so that the &'s don't force the real ones into
           memory.  */
        yy_state_t *yyss1 = yyss;
        YYSTYPE *yyvs1 = yyvs;
        yytype_int16 *yyss1 = yyss;
        YYLTYPE *yyls1 = yyls;

        /* Each stack pointer address is followed by the size of the
           data in use in that stack, in bytes.  This used to be a
           conditional around just the two extra args, but that might
           be undefined if yyoverflow is a macro.  */
        yyoverflow (YY_("memory exhausted"),
                    &yyss1, yysize * sizeof (*yyssp),
                    &yyvs1, yysize * sizeof (*yyvsp),
                    &yyls1, yysize * sizeof (*yylsp),
                    &yyss1, yysize * YYSIZEOF (*yyssp),
                    &yyvs1, yysize * YYSIZEOF (*yyvsp),
                    &yyls1, yysize * YYSIZEOF (*yylsp),
                    &yystacksize);

        yyls = yyls1;
        yyss = yyss1;
        yyvs = yyvs1;
        yyls = yyls1;
      }
#else /* no yyoverflow */
# ifndef YYSTACK_RELOCATE
# else /* defined YYSTACK_RELOCATE */
      goto yyexhaustedlab;
# else
      /* Extend the stack our own way.  */
      if (YYMAXDEPTH <= yystacksize)
        goto yyexhaustedlab;
        YYNOMEM;
      yystacksize *= 2;
      if (YYMAXDEPTH < yystacksize)
        yystacksize = YYMAXDEPTH;

      {
        yytype_int16 *yyss1 = yyss;
        yy_state_t *yyss1 = yyss;
        union yyalloc *yyptr =
          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
          YY_CAST (union yyalloc *,
                   YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
        if (! yyptr)
          goto yyexhaustedlab;
          YYNOMEM;
        YYSTACK_RELOCATE (yyss_alloc, yyss);
        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
        YYSTACK_RELOCATE (yyls_alloc, yyls);
#  undef YYSTACK_RELOCATE
        if (yyss1 != yyssa)
          YYSTACK_FREE (yyss1);
      }
# endif
#endif /* no yyoverflow */

      yyssp = yyss + yysize - 1;
      yyvsp = yyvs + yysize - 1;
      yylsp = yyls + yysize - 1;

      YY_IGNORE_USELESS_CAST_BEGIN
      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
                  (unsigned long) yystacksize));
      YYDPRINTF ((stderr, "Stack size increased to %ld\n",
                  YY_CAST (long, yystacksize)));
      YY_IGNORE_USELESS_CAST_END

      if (yyss + yystacksize - 1 <= yyssp)
        YYABORT;
    }
#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */

  YYDPRINTF ((stderr, "Entering state %d\n", yystate));

  if (yystate == YYFINAL)
    YYACCEPT;

  goto yybackup;


/*-----------.
| yybackup.  |
`-----------*/
yybackup:

  /* Do appropriate processing given the current state.  Read a
     lookahead token if we need one and don't already have one.  */

  /* First try to decide what to do without reference to lookahead token.  */
  yyn = yypact[yystate];
  if (yypact_value_is_default (yyn))
    goto yydefault;

  /* Not known => get a lookahead token if don't already have one.  */

  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
  /* YYCHAR is either empty, or end-of-input, or a valid lookahead.  */
  if (yychar == YYEMPTY)
    {
      YYDPRINTF ((stderr, "Reading a token: "));
      YYDPRINTF ((stderr, "Reading a token\n"));
      yychar = yylex (&yylval, &yylloc, info);
    }

  if (yychar <= YYEOF)
    {
      yychar = yytoken = YYEOF;
      yychar = YYEOF;
      yytoken = YYSYMBOL_YYEOF;
      YYDPRINTF ((stderr, "Now at end of input.\n"));
    }
  else if (yychar == YYerror)
    {
      /* The scanner already issued an error message, process directly
         to error recovery.  But do not keep the error token as
         lookahead, it is too special and may lead us to an endless
         loop in error recovery. */
      yychar = YYUNDEF;
      yytoken = YYSYMBOL_YYerror;
      yyerror_range[1] = yylloc;
      goto yyerrlab1;
    }
  else
    {
      yytoken = YYTRANSLATE (yychar);
      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
    }

1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515



1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530

1531
1532
1533
1534
1535
1536
1537
1426
1427
1428
1429
1430
1431
1432




1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454

1455
1456
1457
1458
1459
1460
1461
1462







-
-
-
-





+
+
+














-
+







  /* Count tokens shifted since error; after three, turn off error
     status.  */
  if (yyerrstatus)
    yyerrstatus--;

  /* Shift the lookahead token.  */
  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);

  /* Discard the shifted token.  */
  yychar = YYEMPTY;

  yystate = yyn;
  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
  *++yyvsp = yylval;
  YY_IGNORE_MAYBE_UNINITIALIZED_END
  *++yylsp = yylloc;

  /* Discard the shifted token.  */
  yychar = YYEMPTY;
  goto yynewstate;


/*-----------------------------------------------------------.
| yydefault -- do the default action for the current state.  |
`-----------------------------------------------------------*/
yydefault:
  yyn = yydefact[yystate];
  if (yyn == 0)
    goto yyerrlab;
  goto yyreduce;


/*-----------------------------.
| yyreduce -- Do a reduction.  |
| yyreduce -- do a reduction.  |
`-----------------------------*/
yyreduce:
  /* yyn is the number of a rule to reduce with.  */
  yylen = yyr2[yyn];

  /* If YYLEN is nonzero, implement the default value of the action:
     '$$ = $1'.
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756


1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785


1786
1787
1788
1789
1790
1791
1792
1793
1794
1795


1796
1797
1798
1799
1800
1801
1802
1803
1804


1805
1806
1807
1808
1809
1810
1811
1812
1813


1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824


1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836




1837
1838
1839
1840
1841
1842
1843
1844
1845




1846
1847
1848
1849
1850
1851

1852

1853
1854
1855
1856
1857
1858
1859











1860
1861
1862
1863
1864
1865
1866


1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879

1880
1881
1882
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
1958
1959
1960
1961










1962
1963
1964
1965
1966


1967
1968
1969
1970
1971
1972
1973
1974


1975
1976
1977
1978
1979
1980
1981
1982


1983
1984
1985
1986
1987
1988
1989
1990


1991
1992
1993
1994
1995
1996
1997
1998
1999


2000
2001
2002
2003
2004
2005
2006
2007
2008


2009
2010
2011

2012




2013
2014
2015
2016
2017
2018















2019
2020
2021

2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038


2039
2040
2041
2042
2043
2044
2045
2046


2047
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
2095
2096
2097

2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124

2125
2126

2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
1470
1471
1472
1473
1474
1475
1476


1477
1478


1479
1480

1481
1482


1483
1484


1485
1486

1487
1488


1489
1490


1491
1492

1493
1494


1495
1496


1497
1498

1499
1500



1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511



1512
1513
1514
1515
1516
1517
1518



1519
1520

1521
1522
1523

1524
1525





1526
1527
1528
1529
1530
1531

1532
1533


1534
1535




1536
1537
1538
1539

1540
1541


1542
1543

1544
1545
1546
1547
1548

1549
1550


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










1749





1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770



1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781

1782
1783

1784
1785



1786
1787
1788
1789
1790
1791

1792
1793




1794
1795
1796
1797

1798
1799




1800
1801
1802
1803

1804
1805




1806
1807
1808
1809

1810
1811






1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823



1824
1825
1826
1827

1828
1829



1830
1831
1832
1833

1834
1835



1836
1837
1838
1839

1840
1841



1842
1843
1844
1845
1846

1847
1848



1849
1850
1851
1852
1853

1854
1855



1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868




1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959

1960




















1961


1962












1963

1964
1965
1966
1967
1968
1969
1970







-
-
+
+
-
-
+

-


-
-
+
+
-
-
+

-


-
-
+
+
-
-
+

-


-
-
+
+
-
-
+

-


-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+


-
-
-
+
+
-
+
+

-


-
-
-
-
-
+
+
+
+
+

-


-
-
+
+
-
-
-
-
+
+
+

-


-
-
+
+
-





-


-
-
+
+
-
-
-
-


-


-
-
+
+
-
-
-
-
-
+
+

-


-
-
-
-
+
+
+
+
+
+
+
+
+
+
-


-


-
-
+
+
-
-
+
-


-


-
-
+
+
-
-
-
+
+

-


-
-
+
+
-



-


-
-
+
+
-

-
+

-


-
-
+
+
-

-
+

-


-
-
+
+
-

-
+

+

+
+
+
+
+


-
-
+
+
-

-
+

-


-
-
-
+
+

-
+

+

+
+
+
+
+
+


-
-
-
+
+



-


-
-
-
+
+




-


-
-
-
+
+
-
-
-
-
-
-
-
-
-
-




-


-
-
-
-
-
-
-
-
-
-
-
-
+
+
-



-


-
-
-
+
+




-


-
-
+
+
-



-


-
-
+
+
-




-


-
-
-
+
+




-


-
-
-
-
-
+
+
+
+

-


-
-
-
-
-
+
+
+
+

-

-
-

+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-


-
-
-
+
+
-
-
-
-




-


-
-
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-







+

+
+
+
+
+
+
+
+
+
+


-
-
-
+
+









-
+

-


-
-
-
+
+




-


-
-
-
-
+
+
+

-


-
-
-
-
+
+
+

-


-
-
-
-
+
+
+

-


-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+


-
-
-
+
+


-


-
-
-
+
+


-


-
-
-
+
+


-


-
-
-
+
+



-


-
-
-
+
+



-


-
-
-
+
+



+

+
+
+
+


-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+











-


-
-
-
+
+


-


-
-
-
+
+


-

















-
+



-







-
-
-
+
+
+
-
-
-
+
+
-
-
+
+










-
+
-




-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-

-








  /* Default location. */
  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
  yyerror_range[1] = yyloc;
  YY_REDUCE_PRINT (yyn);
  switch (yyn)
    {
        case 4:

  case 4: /* item: time  */
               {
    {
	    yyHaveTime++;
	    yyIncrFlags(CLF_TIME);
	}

    break;

  case 5:

  case 5: /* item: zone  */
               {
    {
	    yyHaveZone++;
	    yyIncrFlags(CLF_ZONE);
	}

    break;

  case 6:

  case 6: /* item: date  */
               {
    {
	    yyHaveDate++;
	    yyIncrFlags(CLF_HAVEDATE);
	}

    break;

  case 7:

  case 7: /* item: ordMonth  */
                   {
    {
	    yyHaveOrdinalMonth++;
	    yyIncrFlags(CLF_ORDINALMONTH);
	}

    break;

  case 8:

    {
  case 8: /* item: day  */
              {
	    yyIncrFlags(CLF_DAYOFWEEK);
	}
    break;

  case 9: /* item: relspec  */
                  {
	    info->flags |= CLF_RELCONV;
	}
    break;
	    yyHaveDay++;
	}


  case 10: /* item: iso  */
              {
	    yyIncrFlags(CLF_TIME|CLF_HAVEDATE);
	}
    break;

  case 9:

    {
  case 11: /* item: trek  */
               {
	    yyHaveRel++;
	    yyIncrFlags(CLF_TIME|CLF_HAVEDATE);
	    info->flags |= CLF_RELCONV;
	}

    break;

  case 10:

    {
	    yyHaveTime++;
	    yyHaveDate++;
  case 13: /* iextime: tUNUMBER ':' tUNUMBER ':' tUNUMBER  */
                                             {
	    yyHour = (yyvsp[-4].Number);
	    yyMinutes = (yyvsp[-2].Number);
	    yySeconds = (yyvsp[0].Number);
	}

    break;

  case 11:

  case 14: /* iextime: tUNUMBER ':' tUNUMBER  */
                                {
    {
	    yyHaveTime++;
	    yyHaveDate++;
	    yyHaveRel++;
	    yyHour = (yyvsp[-2].Number);
	    yyMinutes = (yyvsp[0].Number);
	    yySeconds = 0;
	}

    break;

  case 13:

  case 15: /* time: tUNUMBER tMERIDIAN  */
                             {
    {
	    yyHour = (yyvsp[-1].Number);
	    yyMinutes = 0;
	    yySeconds = 0;
	    yyMeridian = (yyvsp[0].Meridian);
	}

    break;

  case 14:

  case 16: /* time: iextime o_merid  */
                          {
    {
	    yyHour = (yyvsp[-3].Number);
	    yyMinutes = (yyvsp[-1].Number);
	    yySeconds = 0;
	    yyMeridian = (yyvsp[0].Meridian);
	}

    break;

  case 15:

  case 17: /* zone: tZONE tDST  */
                     {
    {
	    yyHour = (yyvsp[-5].Number);
	    yyMinutes = (yyvsp[-3].Number);
	    yySeconds = (yyvsp[-1].Number);
	    yyMeridian = (yyvsp[0].Meridian);
	    yyTimezone = (yyvsp[-1].Number);
	    yyDSTmode = DSTon;
	}

    break;

  case 16:

    {
	    yyTimezone = (yyvsp[-1].Number);
  case 18: /* zone: tZONE  */
                {
	    yyTimezone = (yyvsp[0].Number);
	    yyDSTmode = DSToff;
	}
    break;

  case 19: /* zone: tDAYZONE  */
                   {
	    yyTimezone = (yyvsp[0].Number);
	    if (yyTimezone > HOUR( 12)) yyTimezone -= HOUR(100);
	    yyDSTmode = DSTon;
	}

    break;

  case 17:

  case 20: /* zone: tZONEwO4 sign INTNUM  */
                               { /* GMT+0100, GMT-1000, etc. */
    {
	    yyTimezone = (yyvsp[0].Number);
	    yyTimezone = (yyvsp[-2].Number) - (yyvsp[-1].Number)*((yyvsp[0].Number) % 100 + ((yyvsp[0].Number) / 100) * 60);
	    if (yyTimezone > HOUR( 12)) yyTimezone -= HOUR(100);
	    yyDSTmode = DSToff;
	}

    break;

  case 18:

  case 21: /* zone: tZONEwO2 sign INTNUM  */
                               { /* GMT+1, GMT-10, etc. */
    {
	    yyTimezone = (yyvsp[0].Number);
	    yyDSTmode = DSTon;
	    yyTimezone = (yyvsp[-2].Number) - (yyvsp[-1].Number)*((yyvsp[0].Number) * 60);
	    yyDSTmode = DSToff;
	}

    break;

  case 19:

  case 22: /* zone: sign INTNUM  */
                      { /* +0100, -0100 */
    {
	    yyTimezone = -(yyvsp[-1].Number)*((yyvsp[0].Number) % 100 + ((yyvsp[0].Number) / 100) * 60);
	    yyDSTmode = DSToff;
	}

    break;

  case 20:

  case 25: /* day: tDAY  */
               {
    {
	    yyDayOrdinal = 1;
	    yyDayNumber = (yyvsp[0].Number);
	    yyDayOfWeek = (yyvsp[0].Number);
	}

    break;

  case 21:

  case 26: /* day: tDAY comma  */
                     {
    {
	    yyDayOrdinal = 1;
	    yyDayNumber = (yyvsp[-1].Number);
	    yyDayOfWeek = (yyvsp[-1].Number);
	}

    break;

  case 22:

  case 27: /* day: tUNUMBER tDAY  */
                        {
    {
	    yyDayOrdinal = (yyvsp[-1].Number);
	    yyDayNumber = (yyvsp[0].Number);
	    yyDayOfWeek = (yyvsp[0].Number);
	}
    break;

  case 28: /* day: sign SP tUNUMBER tDAY  */
                                {
	    yyDayOrdinal = (yyvsp[-3].Number) * (yyvsp[-1].Number);
	    yyDayOfWeek = (yyvsp[0].Number);
	}
    break;

  case 23:

  case 29: /* day: sign tUNUMBER tDAY  */
                             {
    {
	    yyDayOrdinal = (yyvsp[-2].Number) * (yyvsp[-1].Number);
	    yyDayNumber = (yyvsp[0].Number);
	    yyDayOfWeek = (yyvsp[0].Number);
	}

    break;

  case 24:

    {
  case 30: /* day: tNEXT tDAY  */
                     {
	    yyDayOrdinal = 2;
	    yyDayNumber = (yyvsp[0].Number);
	    yyDayOfWeek = (yyvsp[0].Number);
	}
    break;

  case 31: /* iexdate: tUNUMBER '-' tUNUMBER '-' tUNUMBER  */
                                             {
	    yyMonth = (yyvsp[-2].Number);
	    yyDay = (yyvsp[0].Number);
	    yyYear = (yyvsp[-4].Number);
	}
    break;

  case 25:

    {
  case 32: /* date: tUNUMBER '/' tUNUMBER  */
                                {
	    yyMonth = (yyvsp[-2].Number);
	    yyDay = (yyvsp[0].Number);
	}

    break;

  case 26:

    {
  case 33: /* date: tUNUMBER '/' tUNUMBER '/' tUNUMBER  */
                                             {
	    yyMonth = (yyvsp[-4].Number);
	    yyDay = (yyvsp[-2].Number);
	    yyYear = (yyvsp[0].Number);
	}

    break;

  case 27:

    {
  case 35: /* date: tUNUMBER '-' tMONTH '-' tUNUMBER  */
                                           {
	    yyYear = (yyvsp[0].Number) / 10000;
	    yyMonth = ((yyvsp[0].Number) % 10000)/100;
	    yyDay = (yyvsp[0].Number) % 100;
	}

    break;

  case 28:

    {
	    yyDay = (yyvsp[-4].Number);
	    yyMonth = (yyvsp[-2].Number);
	    yyYear = (yyvsp[0].Number);
	}

    break;

  case 29:

    {
	    yyMonth = (yyvsp[-2].Number);
	    yyDay = (yyvsp[0].Number);
	    yyYear = (yyvsp[-4].Number);
	}

    break;

  case 30:

  case 36: /* date: tMONTH tUNUMBER  */
                          {
    {
	    yyMonth = (yyvsp[-1].Number);
	    yyDay = (yyvsp[0].Number);
	}

    break;

  case 31:

    {
  case 37: /* date: tMONTH tUNUMBER comma tUNUMBER  */
                                         {
	    yyMonth = (yyvsp[-3].Number);
	    yyDay = (yyvsp[-2].Number);
	    yyYear = (yyvsp[0].Number);
	}

    break;

  case 32:

  case 38: /* date: tUNUMBER tMONTH  */
                          {
    {
	    yyMonth = (yyvsp[0].Number);
	    yyDay = (yyvsp[-1].Number);
	}

    break;

  case 33:

  case 39: /* date: tEPOCH  */
                 {
    {
	    yyMonth = 1;
	    yyDay = 1;
	    yyYear = EPOCH;
	}

    break;

  case 34:

    {
  case 40: /* date: tUNUMBER tMONTH tUNUMBER  */
                                   {
	    yyMonth = (yyvsp[-1].Number);
	    yyDay = (yyvsp[-2].Number);
	    yyYear = (yyvsp[0].Number);
	}

    break;

  case 35:

    {
	    yyMonthOrdinal = 1;
	    yyMonth = (yyvsp[0].Number);
  case 41: /* ordMonth: tNEXT tMONTH  */
                       {
	    yyMonthOrdinalIncr = 1;
	    yyMonthOrdinal = (yyvsp[0].Number);
	}

    break;

  case 36:

    {
	    yyMonthOrdinal = (yyvsp[-1].Number);
	    yyMonth = (yyvsp[0].Number);
  case 42: /* ordMonth: tNEXT tUNUMBER tMONTH  */
                                {
	    yyMonthOrdinalIncr = (yyvsp[-1].Number);
	    yyMonthOrdinal = (yyvsp[0].Number);
	}

    break;

  case 37:

  case 45: /* isodate: tISOBAS8  */
    {
                   { /* YYYYMMDD */
	    if ((yyvsp[-5].Number) != HOUR( 7) + HOUR(100)) YYABORT;
	    yyYear = (yyvsp[-10].Number);
	    yyMonth = (yyvsp[-8].Number);
	    yyDay = (yyvsp[-6].Number);
	    yyHour = (yyvsp[-4].Number);
	    yyMinutes = (yyvsp[-2].Number);
	    yySeconds = (yyvsp[0].Number);
	    yyYear = (yyvsp[0].Number) / 10000;
	    yyMonth = ((yyvsp[0].Number) % 10000)/100;
	    yyDay = (yyvsp[0].Number) % 100;
	}
    break;

  case 46: /* isodate: tISOBAS6  */
                   { /* YYMMDD */
	    yyYear = (yyvsp[0].Number) / 10000;
	    yyMonth = ((yyvsp[0].Number) % 10000)/100;
	    yyDay = (yyvsp[0].Number) % 100;
	}

    break;

  case 38:

    {
  case 48: /* isotime: tISOBAS6  */
                   {
	    if ((yyvsp[-1].Number) != HOUR( 7) + HOUR(100)) YYABORT;
	    yyYear = (yyvsp[-2].Number) / 10000;
	    yyMonth = ((yyvsp[-2].Number) % 10000)/100;
	    yyDay = (yyvsp[-2].Number) % 100;
	    yyHour = (yyvsp[0].Number) / 10000;
	    yyMinutes = ((yyvsp[0].Number) % 10000)/100;
	    yySeconds = (yyvsp[0].Number) % 100;
	}

    break;

  case 39:

  case 51: /* iso: tISOBASL tISOBAS6  */
    {
	    if ((yyvsp[-5].Number) != HOUR( 7) + HOUR(100)) YYABORT;
	    yyYear = (yyvsp[-6].Number) / 10000;
	    yyMonth = ((yyvsp[-6].Number) % 10000)/100;
	    yyDay = (yyvsp[-6].Number) % 100;
	    yyHour = (yyvsp[-4].Number);
	    yyMinutes = (yyvsp[-2].Number);
	    yySeconds = (yyvsp[0].Number);
	}

                            { /* YYYYMMDDhhmmss */
    break;

  case 40:

    {
	    yyYear = (yyvsp[-1].Number) / 10000;
	    yyMonth = ((yyvsp[-1].Number) % 10000)/100;
	    yyDay = (yyvsp[-1].Number) % 100;
	    yyHour = (yyvsp[0].Number) / 10000;
	    yyMinutes = ((yyvsp[0].Number) % 10000)/100;
	    yySeconds = (yyvsp[0].Number) % 100;
	}
    break;

  case 52: /* iso: tISOBASL tUNUMBER  */
                            { /* YYYYMMDDhhmm */
	    if (yyDigitCount != 4) YYABORT; /* normally unreached */
	    yyYear = (yyvsp[-1].Number) / 10000;
	    yyMonth = ((yyvsp[-1].Number) % 10000)/100;
	    yyDay = (yyvsp[-1].Number) % 100;
	    yyHour = (yyvsp[0].Number) / 100;
	    yyMinutes = ((yyvsp[0].Number) % 100);
	    yySeconds = 0;
	}
    break;

  case 41:

    {
  case 53: /* trek: tSTARDATE INTNUM '.' tUNUMBER  */
                                        {
	    /*
	     * Offset computed year by -377 so that the returned years will be
	     * in a range accessible with a 32 bit clock seconds value.
	     */

	    yyYear = (yyvsp[-2].Number)/1000 + 2323 - 377;
	    yyDay  = 1;
	    yyMonth = 1;
	    yyRelDay += (((yyvsp[-2].Number)%1000)*(365 + IsLeapYear(yyYear)))/1000;
	    yyRelSeconds += (yyvsp[0].Number) * 144 * 60;
	    yyRelSeconds += (yyvsp[0].Number) * (144LL * 60LL);
	}

    break;

  case 42:

    {
  case 54: /* relspec: relunits tAGO  */
                        {
	    yyRelSeconds *= -1;
	    yyRelMonth *= -1;
	    yyRelDay *= -1;
	}

    break;

  case 44:

    {
	    *yyRelPointer += (yyvsp[-2].Number) * (yyvsp[-1].Number) * (yyvsp[0].Number);
  case 56: /* relunits: sign SP INTNUM unit  */
                               {
	    *yyRelPointer += (yyvsp[-3].Number) * (yyvsp[-1].Number) * (yyvsp[0].Number);
	}

    break;

  case 45:

    {
	    *yyRelPointer += (yyvsp[-1].Number) * (yyvsp[0].Number);
  case 57: /* relunits: sign INTNUM unit  */
                           {
	    *yyRelPointer += (yyvsp[-2].Number) * (yyvsp[-1].Number) * (yyvsp[0].Number);
	}

    break;

  case 46:

    {
	    *yyRelPointer += (yyvsp[0].Number);
  case 58: /* relunits: INTNUM unit  */
                      {
	    *yyRelPointer += (yyvsp[-1].Number) * (yyvsp[0].Number);
	}

    break;

  case 47:

    {
	    *yyRelPointer += (yyvsp[-1].Number) * (yyvsp[0].Number);
	}

  case 59: /* relunits: tNEXT unit  */
                     {
	    *yyRelPointer += (yyvsp[0].Number);
	}
    break;

  case 60: /* relunits: tNEXT INTNUM unit  */
                            {
	    *yyRelPointer += (yyvsp[-1].Number) * (yyvsp[0].Number);
	}
    break;

  case 48:

    {
  case 61: /* relunits: unit  */
               {
	    *yyRelPointer += (yyvsp[0].Number);
	}

    break;

  case 49:

    {
  case 62: /* sign: '-'  */
              {
	    (yyval.Number) = -1;
	}

    break;

  case 50:

    {
  case 63: /* sign: '+'  */
              {
	    (yyval.Number) =  1;
	}

    break;

  case 51:

    {
  case 64: /* unit: tSEC_UNIT  */
                    {
	    (yyval.Number) = (yyvsp[0].Number);
	    yyRelPointer = &yyRelSeconds;
	}

    break;

  case 52:

    {
  case 65: /* unit: tDAY_UNIT  */
                    {
	    (yyval.Number) = (yyvsp[0].Number);
	    yyRelPointer = &yyRelDay;
	}

    break;

  case 53:

    {
  case 66: /* unit: tMONTH_UNIT  */
                      {
	    (yyval.Number) = (yyvsp[0].Number);
	    yyRelPointer = &yyRelMonth;
	}
    break;

  case 67: /* INTNUM: tUNUMBER  */
                   {
	    (yyval.Number) = (yyvsp[0].Number);
	}
    break;

  case 54:

    {
	    if (yyHaveTime && yyHaveDate && !yyHaveRel) {
  case 68: /* INTNUM: tISOBAS6  */
                   {
	    (yyval.Number) = (yyvsp[0].Number);
	}
    break;

  case 69: /* INTNUM: tISOBAS8  */
                   {
	    (yyval.Number) = (yyvsp[0].Number);
	}
    break;

  case 70: /* numitem: tUNUMBER  */
                   {
	    if ((info->flags & (CLF_TIME|CLF_HAVEDATE|CLF_RELCONV)) == (CLF_TIME|CLF_HAVEDATE)) {
		yyYear = (yyvsp[0].Number);
	    } else {
		yyHaveTime++;
		yyIncrFlags(CLF_TIME);
		if (yyDigitCount <= 2) {
		    yyHour = (yyvsp[0].Number);
		    yyMinutes = 0;
		} else {
		    yyHour = (yyvsp[0].Number) / 100;
		    yyMinutes = (yyvsp[0].Number) % 100;
		}
		yySeconds = 0;
		yyMeridian = MER24;
	    }
	}

    break;

  case 55:

    {
  case 71: /* o_merid: %empty  */
                     {
	    (yyval.Meridian) = MER24;
	}

    break;

  case 56:

    {
  case 72: /* o_merid: tMERIDIAN  */
                    {
	    (yyval.Meridian) = (yyvsp[0].Meridian);
	}

    break;



      default: break;
    }
  /* User semantic actions sometimes alter yychar, and that requires
     that yytoken be updated with the new translation.  We take the
     approach of translating immediately before every use of yytoken.
     One alternative is translating here after every semantic action,
     but that translation would be missed if the semantic action invokes
     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
     incorrect destructor might then be invoked immediately.  In the
     case of YYERROR or YYBACKUP, subsequent parser actions might lead
     to an incorrect destructor call or verbose syntax error message
     before the lookahead is translated.  */
  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
  YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc);

  YYPOPSTACK (yylen);
  yylen = 0;
  YY_STACK_PRINT (yyss, yyssp);

  *++yyvsp = yyval;
  *++yylsp = yyloc;

  /* Now 'shift' the result of the reduction.  Determine what state
     that goes to, based on the state we popped back to and the rule
     number reduced by.  */

  yyn = yyr1[yyn];

  {
    const int yylhs = yyr1[yyn] - YYNTOKENS;
    const int yyi = yypgoto[yylhs] + *yyssp;
  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
    yystate = yytable[yystate];
    yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp
               ? yytable[yyi]
  else
    yystate = yydefgoto[yyn - YYNTOKENS];
               : yydefgoto[yylhs]);
  }

  goto yynewstate;


/*--------------------------------------.
| yyerrlab -- here on detecting error.  |
`--------------------------------------*/
yyerrlab:
  /* Make sure we have latest lookahead translation.  See comments at
     user semantic actions for why this is necessary.  */
  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
  yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar);

  /* If not already recovering from an error, report this error.  */
  if (!yyerrstatus)
    {
      ++yynerrs;
#if ! YYERROR_VERBOSE
      yyerror (&yylloc, info, YY_("syntax error"));
#else
# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
                                        yyssp, yytoken)
      {
        char const *yymsgp = YY_("syntax error");
        int yysyntax_error_status;
        yysyntax_error_status = YYSYNTAX_ERROR;
        if (yysyntax_error_status == 0)
          yymsgp = yymsg;
        else if (yysyntax_error_status == 1)
          {
            if (yymsg != yymsgbuf)
              YYSTACK_FREE (yymsg);
            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
            if (!yymsg)
              {
                yymsg = yymsgbuf;
                yymsg_alloc = sizeof yymsgbuf;
                yysyntax_error_status = 2;
              }
    }
            else
              {

                yysyntax_error_status = YYSYNTAX_ERROR;
                yymsgp = yymsg;
              }
          }
        yyerror (&yylloc, info, yymsgp);
        if (yysyntax_error_status == 2)
          goto yyexhaustedlab;
      }
# undef YYSYNTAX_ERROR
#endif
    }

  yyerror_range[1] = yylloc;

  if (yyerrstatus == 3)
    {
      /* If just tried and failed to reuse lookahead token after an
         error, discard it.  */

      if (yychar <= YYEOF)
        {
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
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
2273
2274

2275
2276
2277
2278
2279
2280
2281

2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
1985
1986
1987
1988
1989
1990
1991



1992
1993



1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018


2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033

2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044




2045
2046
2047
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
2095
2096
2097
2098

2099
2100
2101
2102
2103
2104
2105

2106



2107
2108
2109
2110
2111
2112
2113







-
-
-
+
+
-
-
-
+
+
+
















+





-
-
+
+













-
+










-
-
-
-
+
+


-
+










-
+
+






-
+

-
-
-
-
+
+
+
+



-
-
+
+

+
+
+
-
+















-
+






-
+
-
-
-







  goto yyerrlab1;


/*---------------------------------------------------.
| yyerrorlab -- error raised explicitly by YYERROR.  |
`---------------------------------------------------*/
yyerrorlab:

  /* Pacify compilers like GCC when the user code never invokes
     YYERROR and the label yyerrorlab therefore never appears in user
  /* Pacify compilers when the user code never invokes YYERROR and the
     label yyerrorlab therefore never appears in user code.  */
     code.  */
  if (/*CONSTCOND*/ 0)
     goto yyerrorlab;
  if (0)
    YYERROR;
  ++yynerrs;

  /* Do not reclaim the symbols of the rule whose action triggered
     this YYERROR.  */
  YYPOPSTACK (yylen);
  yylen = 0;
  YY_STACK_PRINT (yyss, yyssp);
  yystate = *yyssp;
  goto yyerrlab1;


/*-------------------------------------------------------------.
| yyerrlab1 -- common code for both syntax error and YYERROR.  |
`-------------------------------------------------------------*/
yyerrlab1:
  yyerrstatus = 3;      /* Each real token shifted decrements this.  */

  /* Pop stack until we find a state that shifts the error token.  */
  for (;;)
    {
      yyn = yypact[yystate];
      if (!yypact_value_is_default (yyn))
        {
          yyn += YYTERROR;
          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
          yyn += YYSYMBOL_YYerror;
          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror)
            {
              yyn = yytable[yyn];
              if (0 < yyn)
                break;
            }
        }

      /* Pop the current state because it cannot handle the error token.  */
      if (yyssp == yyss)
        YYABORT;

      yyerror_range[1] = *yylsp;
      yydestruct ("Error: popping",
                  yystos[yystate], yyvsp, yylsp, info);
                  YY_ACCESSING_SYMBOL (yystate), yyvsp, yylsp, info);
      YYPOPSTACK (1);
      yystate = *yyssp;
      YY_STACK_PRINT (yyss, yyssp);
    }

  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
  *++yyvsp = yylval;
  YY_IGNORE_MAYBE_UNINITIALIZED_END

  yyerror_range[2] = yylloc;
  /* Using YYLLOC is tempting, but would change the location of
     the lookahead.  YYLOC is available though.  */
  YYLLOC_DEFAULT (yyloc, yyerror_range, 2);
  *++yylsp = yyloc;
  ++yylsp;
  YYLLOC_DEFAULT (*yylsp, yyerror_range, 2);

  /* Shift the error token.  */
  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
  YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp);

  yystate = yyn;
  goto yynewstate;


/*-------------------------------------.
| yyacceptlab -- YYACCEPT comes here.  |
`-------------------------------------*/
yyacceptlab:
  yyresult = 0;
  goto yyreturn;
  goto yyreturnlab;


/*-----------------------------------.
| yyabortlab -- YYABORT comes here.  |
`-----------------------------------*/
yyabortlab:
  yyresult = 1;
  goto yyreturn;
  goto yyreturnlab;

#if !defined yyoverflow || YYERROR_VERBOSE
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here.  |
`-------------------------------------------------*/

/*-----------------------------------------------------------.
| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here.  |
`-----------------------------------------------------------*/
yyexhaustedlab:
  yyerror (&yylloc, info, YY_("memory exhausted"));
  yyresult = 2;
  /* Fall through.  */
#endif
  goto yyreturnlab;


/*----------------------------------------------------------.
| yyreturnlab -- parsing is finished, clean up and return.  |
`----------------------------------------------------------*/
yyreturn:
yyreturnlab:
  if (yychar != YYEMPTY)
    {
      /* Make sure we have latest lookahead translation.  See comments at
         user semantic actions for why this is necessary.  */
      yytoken = YYTRANSLATE (yychar);
      yydestruct ("Cleanup: discarding lookahead",
                  yytoken, &yylval, &yylloc, info);
    }
  /* Do not reclaim the symbols of the rule whose action triggered
     this YYABORT or YYACCEPT.  */
  YYPOPSTACK (yylen);
  YY_STACK_PRINT (yyss, yyssp);
  while (yyssp != yyss)
    {
      yydestruct ("Cleanup: popping",
                  yystos[*yyssp], yyvsp, yylsp, info);
                  YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, yylsp, info);
      YYPOPSTACK (1);
    }
#ifndef yyoverflow
  if (yyss != yyssa)
    YYSTACK_FREE (yyss);
#endif
#if YYERROR_VERBOSE

  if (yymsg != yymsgbuf)
    YYSTACK_FREE (yymsg);
#endif
  return yyresult;
}


/*
 * Month and day table.
 */
2300
2301
2302
2303
2304
2305
2306
2307

2308
2309
2310
2311
2312
2313
2314
2122
2123
2124
2125
2126
2127
2128

2129
2130
2131
2132
2133
2134
2135
2136







-
+







    { "july",		tMONTH,	 7 },
    { "august",		tMONTH,	 8 },
    { "september",	tMONTH,	 9 },
    { "sept",		tMONTH,	 9 },
    { "october",	tMONTH, 10 },
    { "november",	tMONTH, 11 },
    { "december",	tMONTH, 12 },
    { "sunday",		tDAY, 0 },
    { "sunday",		tDAY, 7 },
    { "monday",		tDAY, 1 },
    { "tuesday",	tDAY, 2 },
    { "tues",		tDAY, 2 },
    { "wednesday",	tDAY, 3 },
    { "wednes",		tDAY, 3 },
    { "thursday",	tDAY, 4 },
    { "thur",		tDAY, 4 },
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
2166
2167
2168
2169
2170
2171
2172














2173
2174
2175
2176
2177
2178
2179







-
-
-
-
-
-
-
-
-
-
-
-
-
-







    { "tomorrow",	tDAY_UNIT,	1 },
    { "yesterday",	tDAY_UNIT,	-1 },
    { "today",		tDAY_UNIT,	0 },
    { "now",		tSEC_UNIT,	0 },
    { "last",		tUNUMBER,	-1 },
    { "this",		tSEC_UNIT,	0 },
    { "next",		tNEXT,		1 },
#if 0
    { "first",		tUNUMBER,	1 },
    { "second",		tUNUMBER,	2 },
    { "third",		tUNUMBER,	3 },
    { "fourth",		tUNUMBER,	4 },
    { "fifth",		tUNUMBER,	5 },
    { "sixth",		tUNUMBER,	6 },
    { "seventh",	tUNUMBER,	7 },
    { "eighth",		tUNUMBER,	8 },
    { "ninth",		tUNUMBER,	9 },
    { "tenth",		tUNUMBER,	10 },
    { "eleventh",	tUNUMBER,	11 },
    { "twelfth",	tUNUMBER,	12 },
#endif
    { "ago",		tAGO,		1 },
    { "epoch",		tEPOCH,		0 },
    { "stardate",	tSTARDATE,	0 },
    { NULL, 0, 0 }
};

/*
2399
2400
2401
2402
2403
2404
2405


2406
2407
2408
2409
2410
2411
2412
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222







+
+







    { "cdt",	tDAYZONE,  HOUR( 6) },	    /* Central Daylight */
    { "mst",	tZONE,	   HOUR( 7) },	    /* Mountain Standard */
    { "mdt",	tDAYZONE,  HOUR( 7) },	    /* Mountain Daylight */
    { "pst",	tZONE,	   HOUR( 8) },	    /* Pacific Standard */
    { "pdt",	tDAYZONE,  HOUR( 8) },	    /* Pacific Daylight */
    { "yst",	tZONE,	   HOUR( 9) },	    /* Yukon Standard */
    { "ydt",	tDAYZONE,  HOUR( 9) },	    /* Yukon Daylight */
    { "akst",	tZONE,	   HOUR( 9) },	    /* Alaska Standard */
    { "akdt",	tDAYZONE,  HOUR( 9) },	    /* Alaska Daylight */
    { "hst",	tZONE,	   HOUR(10) },	    /* Hawaii Standard */
    { "hdt",	tDAYZONE,  HOUR(10) },	    /* Hawaii Daylight */
    { "cat",	tZONE,	   HOUR(10) },	    /* Central Alaska */
    { "ahst",	tZONE,	   HOUR(10) },	    /* Alaska-Hawaii Standard */
    { "nt",	tZONE,	   HOUR(11) },	    /* Nome */
    { "idlw",	tZONE,	   HOUR(12) },	    /* International Date Line West */
    { "cet",	tZONE,	  -HOUR( 1) },	    /* Central European */
2422
2423
2424
2425
2426
2427
2428
2429

2430
2431
2432
2433
2434
2435
2436
2232
2233
2234
2235
2236
2237
2238

2239
2240
2241
2242
2243
2244
2245
2246







-
+







    { "bt",	tZONE,	  -HOUR( 3) },	    /* Baghdad, USSR Zone 2 */
    { "it",	tZONE,	  -HOUR( 7/2) },    /* Iran */
    { "zp4",	tZONE,	  -HOUR( 4) },	    /* USSR Zone 3 */
    { "zp5",	tZONE,	  -HOUR( 5) },	    /* USSR Zone 4 */
    { "ist",	tZONE,	  -HOUR(11/2) },    /* Indian Standard */
    { "zp6",	tZONE,	  -HOUR( 6) },	    /* USSR Zone 5 */
#if	0
    /* For completeness.  NST is also Newfoundland Stanard, nad SST is
    /* For completeness.  NST is also Newfoundland Standard, and SST is
     * also Swedish Summer. */
    { "nst",	tZONE,	  -HOUR(13/2) },    /* North Sumatra */
    { "sst",	tZONE,	  -HOUR( 7) },	    /* South Sumatra, USSR Zone 6 */
#endif	/* 0 */
    { "wast",	tZONE,	  -HOUR( 7) },	    /* West Australian Standard */
    { "wadt",	tDAYZONE, -HOUR( 7) },	    /* West Australian Daylight */
    { "jt",	tZONE,	  -HOUR(15/2) },    /* Java (3pm in Cronusland!) */
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










2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500



2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517

2518
2519
2520
2521



2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532

2533
2534
2535

2536
2537
2538
2539
2540

2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563

2564
2565
2566
2567

2568
2569
2570
2571
2572
2573
2574
2265
2266
2267
2268
2269
2270
2271

























2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+












+
+
+
















-
+

-
-
-
+
+
+


-
-
-


-
-
-
-
+

-
-
+
-
-

-
-
+
-
-




















-
+



-
+







};

/*
 * Military timezone table.
 */

static const TABLE MilitaryTable[] = {
    { "a",	tZONE,	-HOUR( 1) + HOUR(100) },
    { "b",	tZONE,	-HOUR( 2) + HOUR(100) },
    { "c",	tZONE,	-HOUR( 3) + HOUR(100) },
    { "d",	tZONE,	-HOUR( 4) + HOUR(100) },
    { "e",	tZONE,	-HOUR( 5) + HOUR(100) },
    { "f",	tZONE,	-HOUR( 6) + HOUR(100) },
    { "g",	tZONE,	-HOUR( 7) + HOUR(100) },
    { "h",	tZONE,	-HOUR( 8) + HOUR(100) },
    { "i",	tZONE,	-HOUR( 9) + HOUR(100) },
    { "k",	tZONE,	-HOUR(10) + HOUR(100) },
    { "l",	tZONE,	-HOUR(11) + HOUR(100) },
    { "m",	tZONE,	-HOUR(12) + HOUR(100) },
    { "n",	tZONE,	HOUR(  1) + HOUR(100) },
    { "o",	tZONE,	HOUR(  2) + HOUR(100) },
    { "p",	tZONE,	HOUR(  3) + HOUR(100) },
    { "q",	tZONE,	HOUR(  4) + HOUR(100) },
    { "r",	tZONE,	HOUR(  5) + HOUR(100) },
    { "s",	tZONE,	HOUR(  6) + HOUR(100) },
    { "t",	tZONE,	HOUR(  7) + HOUR(100) },
    { "u",	tZONE,	HOUR(  8) + HOUR(100) },
    { "v",	tZONE,	HOUR(  9) + HOUR(100) },
    { "w",	tZONE,	HOUR( 10) + HOUR(100) },
    { "x",	tZONE,	HOUR( 11) + HOUR(100) },
    { "y",	tZONE,	HOUR( 12) + HOUR(100) },
    { "z",	tZONE,	HOUR( 0)  + HOUR(100) },
    { "a",	tZONE,	-HOUR( 1) },
    { "b",	tZONE,	-HOUR( 2) },
    { "c",	tZONE,	-HOUR( 3) },
    { "d",	tZONE,	-HOUR( 4) },
    { "e",	tZONE,	-HOUR( 5) },
    { "f",	tZONE,	-HOUR( 6) },
    { "g",	tZONE,	-HOUR( 7) },
    { "h",	tZONE,	-HOUR( 8) },
    { "i",	tZONE,	-HOUR( 9) },
    { "k",	tZONE,	-HOUR(10) },
    { "l",	tZONE,	-HOUR(11) },
    { "m",	tZONE,	-HOUR(12) },
    { "n",	tZONE,	HOUR(  1) },
    { "o",	tZONE,	HOUR(  2) },
    { "p",	tZONE,	HOUR(  3) },
    { "q",	tZONE,	HOUR(  4) },
    { "r",	tZONE,	HOUR(  5) },
    { "s",	tZONE,	HOUR(  6) },
    { "t",	tZONE,	HOUR(  7) },
    { "u",	tZONE,	HOUR(  8) },
    { "v",	tZONE,	HOUR(  9) },
    { "w",	tZONE,	HOUR( 10) },
    { "x",	tZONE,	HOUR( 11) },
    { "y",	tZONE,	HOUR( 12) },
    { "z",	tZONE,	HOUR( 0) },
    { NULL, 0, 0 }
};

static inline const char *
bypassSpaces(
    const char *s)
{
    while (TclIsSpaceProc(*s)) {
	s++;
    }
    return s;
}

/*
 * Dump error messages in the bit bucket.
 */

static void
TclDateerror(
    YYLTYPE* location,
    DateInfo* infoPtr,
    const char *s)
{
    Tcl_Obj* t;
    if (!infoPtr->messages) {
	TclNewObj(infoPtr->messages);
    }
    Tcl_AppendToObj(infoPtr->messages, infoPtr->separatrix, -1);
    Tcl_AppendToObj(infoPtr->messages, s, -1);
    Tcl_AppendToObj(infoPtr->messages, " (characters ", -1);
    TclNewIntObj(t, location->first_column);
    Tcl_IncrRefCount(t);
    Tcl_AppendObjToObj(infoPtr->messages, t);
    Tcl_DecrRefCount(t);
    Tcl_AppendToObj(infoPtr->messages, "-", -1);
    TclNewIntObj(t, location->last_column);
    Tcl_IncrRefCount(t);
    Tcl_AppendObjToObj(infoPtr->messages, t);
    Tcl_DecrRefCount(t);
    Tcl_AppendToObj(infoPtr->messages, ")", -1);
    infoPtr->separatrix = "\n";
}

static time_t
int
ToSeconds(
    time_t Hours,
    time_t Minutes,
    time_t Seconds,
    int Hours,
    int Minutes,
    int Seconds,
    MERIDIAN Meridian)
{
    if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59) {
	return -1;
    }
    switch (Meridian) {
    case MER24:
	if (Hours < 0 || Hours > 23) {
	    return -1;
	}
	return (Hours * 60L + Minutes) * 60L + Seconds;
	return (Hours * 60 + Minutes) * 60 + Seconds;
    case MERam:
	if (Hours < 1 || Hours > 12) {
	    return -1;
	return (((Hours / 24) * 24 + (Hours % 12)) * 60 + Minutes) * 60 + Seconds;
	}
	return ((Hours % 12) * 60L + Minutes) * 60L + Seconds;
    case MERpm:
	if (Hours < 1 || Hours > 12) {
	    return -1;
	return (((Hours / 24) * 24 + (Hours % 12) + 12) * 60 + Minutes) * 60 + Seconds;
	}
	return (((Hours % 12) + 12) * 60L + Minutes) * 60L + Seconds;
    }
    return -1;			/* Should never be reached */
}

static int
LookupWord(
    YYSTYPE* yylvalPtr,
    char *buff)
{
    char *p;
    char *q;
    const TABLE *tp;
    int i, abbrev;

    /*
     * Make it lowercase.
     */

    Tcl_UtfToLower(buff);

    if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
    if (*buff == 'a' && (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0)) {
	yylvalPtr->Meridian = MERam;
	return tMERIDIAN;
    }
    if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
    if (*buff == 'p' && (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0)) {
	yylvalPtr->Meridian = MERpm;
	return tMERIDIAN;
    }

    /*
     * See if we have an abbreviation for a month.
     */
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
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495




2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509

2510
2511





2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523





2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540




2541
2542
2543
2544





2545
2546
2547
2548
2549
2550
2551
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







+



-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

+

-
+

-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+

+


-
+






-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



















-
+

-
+
-

-
-
+

-
-
-
-


-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
-
-
-
-
-
-
-
+
-
-

-
-
+

-
-
+

-
+
-

+
-
+
-

-
-
-
-
-
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+


-
-
-
+
+





-
-
-
+
+

+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+









    YYLTYPE* location,
    DateInfo *info)
{
    char c;
    char *p;
    char buff[20];
    int Count;
    const char *tokStart;

    location->first_column = yyInput - info->dateStart;
    for ( ; ; ) {
	while (TclIsSpaceProcM(*yyInput)) {
	    yyInput++;
	}


	if (isspace(UCHAR(*yyInput))) {
	    yyInput = bypassSpaces(yyInput);
	    /* ignore space at end of text and before some words */
	    c = *yyInput;
	    if (c != '\0' && !isalpha(UCHAR(c))) {
		return SP;
	    }
	}
	tokStart = yyInput;

	if (isdigit(UCHAR(c = *yyInput))) { /* INTL: digit */

	    /*
	     * Convert the string into a number; count the number of digits.
	     * Count the number of digits.
	     */

	    Count = 0;
	    for (yylvalPtr->Number = 0;
		    isdigit(UCHAR(c = *yyInput++)); ) {	  /* INTL: digit */
		yylvalPtr->Number = 10 * yylvalPtr->Number + c - '0';
	    p = (char *)yyInput;
	    while (isdigit(UCHAR(*++p))) {};
	    yyDigitCount = p - yyInput;
	    /*
	     * A number with 12 or 14 digits is considered an ISO 8601 date.
	     */
	    if (yyDigitCount == 14 || yyDigitCount == 12) {
		/* long form of ISO 8601 (without separator), either
		 * YYYYMMDDhhmmss or YYYYMMDDhhmm, so reduce to date
		 * (8 chars is isodate) */
		p = (char *)yyInput+8;
		if (TclAtoWIe(&yylvalPtr->Number, yyInput, p, 1) != TCL_OK) {
		Count++;
	    }
	    yyInput--;
	    yyDigitCount = Count;

		    return tID; /* overflow*/
		}
		yyDigitCount = 8;
		yyInput = p;
		location->last_column = yyInput - info->dateStart - 1;
		return tISOBASL;
	    }
	    /*
	     * Convert the string into a number
	     */
	    if (TclAtoWIe(&yylvalPtr->Number, yyInput, p, 1) != TCL_OK) {
		return tID; /* overflow*/
	    }
	    yyInput = p;
	    /*
	     * A number with 6 or more digits is considered an ISO 8601 base.
	     */

	    if (Count >= 6) {
		location->last_column = yyInput - info->dateStart - 1;
		return tISOBASE;
	    location->last_column = yyInput - info->dateStart - 1;
	    if (yyDigitCount >= 6) {
		if (yyDigitCount == 8) {
		    return tISOBAS8;
	    } else {
		location->last_column = yyInput - info->dateStart - 1;
		return tUNUMBER;
	    }
	}
		}
		if (yyDigitCount == 6) {
		    return tISOBAS6;
		}
	    }
	    /* ignore spaces after digits (optional) */
	    yyInput = bypassSpaces(yyInput);
	    return tUNUMBER;
	}
	if (!(c & 0x80) && isalpha(UCHAR(c))) {		  /* INTL: ISO only. */
	    int ret;
	    for (p = buff; isalpha(UCHAR(c = *yyInput++)) /* INTL: ISO only. */
		     || c == '.'; ) {
		if (p < &buff[sizeof buff - 1]) {
		if (p < &buff[sizeof(buff) - 1]) {
		    *p++ = c;
		}
	    }
	    *p = '\0';
	    yyInput--;
	    location->last_column = yyInput - info->dateStart - 1;
	    return LookupWord(yylvalPtr, buff);
	    ret = LookupWord(yylvalPtr, buff);
	    /*
	     * lookahead:
	     *	for spaces to consider word boundaries (for instance
	     *	literal T in isodateTisotimeZ is not a TZ, but Z is UTC);
	     *	for +/- digit, to differentiate between "GMT+1000 day" and "GMT +1000 day";
	     * bypass spaces after token (but ignore by TZ+OFFS), because should
	     * recognize next SP token, if TZ only.
	     */
	    if (ret == tZONE || ret == tDAYZONE) {
		c = *yyInput;
		if (isdigit(UCHAR(c))) { /* literal not a TZ  */
		    yyInput = tokStart;
		    return *yyInput++;
		}
		if ((c == '+' || c == '-') && isdigit(UCHAR(*(yyInput+1)))) {
		    if ( !isdigit(UCHAR(*(yyInput+2)))
		      || !isdigit(UCHAR(*(yyInput+3)))) {
			/* GMT+1, GMT-10, etc. */
			return tZONEwO2;
		    }
		    if ( isdigit(UCHAR(*(yyInput+4)))
		      && !isdigit(UCHAR(*(yyInput+5)))) {
			/* GMT+1000, etc. */
			return tZONEwO4;
		    }
		}
	    }
	    yyInput = bypassSpaces(yyInput);
	    return ret;

	}
	if (c != '(') {
	    location->last_column = yyInput - info->dateStart;
	    return *yyInput++;
	}
	Count = 0;
	do {
	    c = *yyInput++;
	    if (c == '\0') {
		location->last_column = yyInput - info->dateStart - 1;
		return c;
	    } else if (c == '(') {
		Count++;
	    } else if (c == ')') {
		Count--;
	    }
	} while (Count > 0);
    }
}


int
TclClockOldscanObjCmd(
TclClockFreeScan(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Count of paraneters */
    Tcl_Obj *const *objv)	/* Parameters */
    DateInfo *info)		/* Input and result parameters */
{
    Tcl_Obj *result, *resultElement;
    int yr, mo, da;
    DateInfo dateInfo;
    DateInfo* info = &dateInfo;
    int status;

    if (objc != 5) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"stringToParse baseYear baseMonth baseDay" );
	return TCL_ERROR;
    }

    yyInput = TclGetString(objv[1]);
  #if YYDEBUG
    /* enable debugging if compiled with YYDEBUG */
    yydebug = 1;
  #endif

    /*
     * yyInput = stringToParse;
    dateInfo.dateStart = yyInput;

    yyHaveDate = 0;
     *
     * ClockInitDateInfo(info) should be executed to pre-init info;
    if (Tcl_GetIntFromObj(interp, objv[2], &yr) != TCL_OK
	    || Tcl_GetIntFromObj(interp, objv[3], &mo) != TCL_OK
	    || Tcl_GetIntFromObj(interp, objv[4], &da) != TCL_OK) {
	return TCL_ERROR;
    }
    yyYear = yr; yyMonth = mo; yyDay = da;

     */
    yyHaveTime = 0;
    yyHour = 0; yyMinutes = 0; yySeconds = 0; yyMeridian = MER24;

    yyHaveZone = 0;
    yyTimezone = 0; yyDSTmode = DSTmaybe;
    yyDSTmode = DSTmaybe;

    yyHaveOrdinalMonth = 0;
    yyMonthOrdinal = 0;
    info->separatrix = "";

    yyHaveDay = 0;
    info->dateStart = yyInput;
    yyDayOrdinal = 0; yyDayNumber = 0;

    /* ignore spaces at begin */
    yyHaveRel = 0;
    yyInput = bypassSpaces(yyInput);
    yyRelMonth = 0; yyRelDay = 0; yyRelSeconds = 0; yyRelPointer = NULL;

    TclNewObj(dateInfo.messages);
    dateInfo.separatrix = "";
    Tcl_IncrRefCount(dateInfo.messages);

    status = yyparse(&dateInfo);
    /* parse */
    status = yyparse(info);
    if (status == 1) {
	const char *msg = NULL;
	if (info->errFlags & CLF_HAVEDATE) {
	    msg = "more than one date in string";
	} else if (info->errFlags & CLF_TIME) {
	    msg = "more than one time of day in string";
	} else if (info->errFlags & CLF_ZONE) {
	    msg = "more than one time zone in string";
	} else if (info->errFlags & CLF_DAYOFWEEK) {
	    msg = "more than one weekday in string";
	} else if (info->errFlags & CLF_ORDINALMONTH) {
	    msg = "more than one ordinal month in string";
	}
	if (msg) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1));
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", (char *)NULL);
	} else {
	Tcl_SetObjResult(interp, dateInfo.messages);
	Tcl_DecrRefCount(dateInfo.messages);
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", NULL);
	return TCL_ERROR;
	    Tcl_SetObjResult(interp,
		info->messages ? info->messages : Tcl_NewObj());
	    info->messages = NULL;
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", (char *)NULL);
	}
	status = TCL_ERROR;
    } else if (status == 2) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("memory exhausted", -1));
	Tcl_DecrRefCount(dateInfo.messages);
	Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
	return TCL_ERROR;
	Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
	status = TCL_ERROR;
    } else if (status != 0) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("Unknown status returned "
						  "from date parser. Please "
						  "report this error as a "
						  "bug in Tcl.", -1));
	Tcl_DecrRefCount(dateInfo.messages);
	Tcl_SetErrorCode(interp, "TCL", "BUG", NULL);
	return TCL_ERROR;
	Tcl_SetErrorCode(interp, "TCL", "BUG", (char *)NULL);
	status = TCL_ERROR;
    }
    if (info->messages) {
    Tcl_DecrRefCount(dateInfo.messages);

	Tcl_DecrRefCount(info->messages);
    }
    if (yyHaveDate > 1) {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("more than one date in string", -1));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL);
	return TCL_ERROR;
    }
    if (yyHaveTime > 1) {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("more than one time of day in string", -1));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL);
	return TCL_ERROR;
    }
    if (yyHaveZone > 1) {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("more than one time zone in string", -1));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL);
	return TCL_ERROR;
    }
    if (yyHaveDay > 1) {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("more than one weekday in string", -1));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL);
	return TCL_ERROR;
    }
    if (yyHaveOrdinalMonth > 1) {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("more than one ordinal month in string", -1));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL);
	return TCL_ERROR;
    }

    TclNewObj(result);
    TclNewObj(resultElement);
    if (yyHaveDate) {
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyYear));
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyMonth));
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyDay));
    }
    Tcl_ListObjAppendElement(interp, result, resultElement);

    if (yyHaveTime) {
	Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj(
		ToSeconds(yyHour, yyMinutes, yySeconds, (MERIDIAN)yyMeridian)));
    } else {
	Tcl_ListObjAppendElement(interp, result, Tcl_NewObj());
    }

    TclNewObj(resultElement);
    if (yyHaveZone) {
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(-yyTimezone));
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(1 - yyDSTmode));
    }
    Tcl_ListObjAppendElement(interp, result, resultElement);

    TclNewObj(resultElement);
    if (yyHaveRel) {
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyRelMonth));
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyRelDay));
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyRelSeconds));
    }
    Tcl_ListObjAppendElement(interp, result, resultElement);

    TclNewObj(resultElement);
    if (yyHaveDay && !yyHaveDate) {
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyDayOrdinal));
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyDayNumber));
    }
    Tcl_ListObjAppendElement(interp, result, resultElement);

    TclNewObj(resultElement);
    if (yyHaveOrdinalMonth) {
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyMonthOrdinal));
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyMonth));
    }
    Tcl_ListObjAppendElement(interp, result, resultElement);

    Tcl_SetObjResult(interp, result);
    return TCL_OK;
    return status;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Added generic/tclDate.h.






















































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tclDate.h --
 *
 *	This header file handles common usage of clock primitives
 *	between tclDate.c (yacc), tclClock.c and tclClockFmt.c.
 *
 * Copyright (c) 2014 Serg G. Brester (aka sebres)
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _TCLCLOCK_H
#define _TCLCLOCK_H

/*
 * Constants
 */

#define JULIAN_DAY_POSIX_EPOCH		2440588
#define GREGORIAN_CHANGE_DATE		2361222
#define SECONDS_PER_DAY			86400
#define JULIAN_SEC_POSIX_EPOCH	      (((Tcl_WideInt) JULIAN_DAY_POSIX_EPOCH) \
					* SECONDS_PER_DAY)
#define FOUR_CENTURIES			146097	/* days */
#define JDAY_1_JAN_1_CE_JULIAN		1721424
#define JDAY_1_JAN_1_CE_GREGORIAN	1721426
#define ONE_CENTURY_GREGORIAN		36524	/* days */
#define FOUR_YEARS			1461	/* days */
#define ONE_YEAR			365	/* days */

#define RODDENBERRY			1946	/* Another epoch (Hi, Jeff!) */

enum DateInfoFlags {
    CLF_OPTIONAL = 1 << 0,	/* token is non mandatory */
    CLF_POSIXSEC = 1 << 1,
    CLF_LOCALSEC = 1 << 2,
    CLF_JULIANDAY = 1 << 3,
    CLF_TIME = 1 << 4,
    CLF_ZONE = 1 << 5,
    CLF_CENTURY = 1 << 6,
    CLF_DAYOFMONTH = 1 << 7,
    CLF_DAYOFYEAR = 1 << 8,
    CLF_MONTH = 1 << 9,
    CLF_YEAR = 1 << 10,
    CLF_DAYOFWEEK = 1 << 11,
    CLF_ISO8601YEAR = 1 << 12,
    CLF_ISO8601WEEK = 1 << 13,
    CLF_ISO8601CENTURY = 1 << 14,

    CLF_SIGNED = 1 << 15,

    /* Compounds */

    CLF_HAVEDATE = (CLF_DAYOFMONTH | CLF_MONTH | CLF_YEAR),
    CLF_DATE = (CLF_JULIANDAY | CLF_DAYOFMONTH | CLF_DAYOFYEAR
	    | CLF_MONTH | CLF_YEAR | CLF_ISO8601YEAR
	    | CLF_DAYOFWEEK | CLF_ISO8601WEEK),

    /*
     * Extra flags used outside of scan/format-tokens too (int, not a short).
     */

    CLF_RELCONV = 1 << 17,
    CLF_ORDINALMONTH = 1 << 18,

    /* On demand (lazy) assemble flags */

    CLF_ASSEMBLE_DATE = 1 << 28,/* assemble year, month, etc. using julianDay */
    CLF_ASSEMBLE_JULIANDAY = 1 << 29,
				/* assemble julianDay using year, month, etc. */
    CLF_ASSEMBLE_SECONDS = 1 << 30
				/* assemble localSeconds (and seconds at end) */
};

#define TCL_MIN_SECONDS		-0x00F0000000000000LL
#define TCL_MAX_SECONDS		 0x00F0000000000000LL
#define TCL_INV_SECONDS		(TCL_MIN_SECONDS - 1)

/*
 * Enumeration of the string literals used in [clock]
 */

typedef enum ClockLiteral {
    LIT__NIL,
    LIT__DEFAULT_FORMAT,
    LIT_SYSTEM,		LIT_CURRENT,		LIT_C,
    LIT_BCE,		LIT_CE,
    LIT_DAYOFMONTH,	LIT_DAYOFWEEK,		LIT_DAYOFYEAR,
    LIT_ERA,		LIT_GMT,		LIT_GREGORIAN,
    LIT_INTEGER_VALUE_TOO_LARGE,
    LIT_ISO8601WEEK,	LIT_ISO8601YEAR,
    LIT_JULIANDAY,	LIT_LOCALSECONDS,
    LIT_MONTH,
    LIT_SECONDS,	LIT_TZNAME,		LIT_TZOFFSET,
    LIT_YEAR,
    LIT_TZDATA,
    LIT_GETSYSTEMTIMEZONE,
    LIT_SETUPTIMEZONE,
    LIT_MCGET,
    LIT_GETSYSTEMLOCALE, LIT_GETCURRENTLOCALE,
    LIT_LOCALIZE_FORMAT,
    LIT__END
} ClockLiteral;

#define CLOCK_LITERAL_ARRAY(litarr) static const char *const litarr[] = { \
    "", \
    "%a %b %d %H:%M:%S %Z %Y", \
    "system",		"current",		"C", \
    "BCE",		"CE", \
    "dayOfMonth",	"dayOfWeek",		"dayOfYear", \
    "era",		":GMT",			"gregorian", \
    "integer value too large to represent", \
    "iso8601Week",	"iso8601Year", \
    "julianDay",	"localSeconds", \
    "month", \
    "seconds",		"tzName",		"tzOffset", \
    "year", \
    "::tcl::clock::TZData", \
    "::tcl::clock::GetSystemTimeZone", \
    "::tcl::clock::SetupTimeZone", \
    "::tcl::clock::mcget", \
    "::tcl::clock::GetSystemLocale", "::tcl::clock::mclocale", \
    "::tcl::clock::LocalizeFormat" \
}

/*
 * Enumeration of the msgcat literals used in [clock]
 */

typedef enum ClockMsgCtLiteral {
    MCLIT__NIL, /* placeholder */
    MCLIT_MONTHS_FULL,	MCLIT_MONTHS_ABBREV,  MCLIT_MONTHS_COMB,
    MCLIT_DAYS_OF_WEEK_FULL,  MCLIT_DAYS_OF_WEEK_ABBREV,  MCLIT_DAYS_OF_WEEK_COMB,
    MCLIT_AM,  MCLIT_PM,
    MCLIT_LOCALE_ERAS,
    MCLIT_BCE,	 MCLIT_CE,
    MCLIT_BCE2,	 MCLIT_CE2,
    MCLIT_BCE3,	 MCLIT_CE3,
    MCLIT_LOCALE_NUMERALS,
    MCLIT__END
} ClockMsgCtLiteral;

#define CLOCK_LOCALE_LITERAL_ARRAY(litarr, pref) static const char *const litarr[] = { \
    pref "", \
    pref "MONTHS_FULL", pref "MONTHS_ABBREV", pref "MONTHS_COMB", \
    pref "DAYS_OF_WEEK_FULL", pref "DAYS_OF_WEEK_ABBREV", pref "DAYS_OF_WEEK_COMB", \
    pref "AM", pref "PM", \
    pref "LOCALE_ERAS", \
    pref "BCE",	   pref "CE", \
    pref "b.c.e.", pref "c.e.", \
    pref "b.c.",   pref "a.d.", \
    pref "LOCALE_NUMERALS", \
}

/*
 * Structure containing the fields used in [clock format] and [clock scan]
 */

enum TclDateFieldsFlags {
    CLF_CTZ = (1 << 4)
};

typedef struct TclDateFields {
    /* Cacheable fields:	 */

    Tcl_WideInt seconds;	/* Time expressed in seconds from the Posix
				 * epoch */
    Tcl_WideInt localSeconds;	/* Local time expressed in nominal seconds
				 * from the Posix epoch */
    int tzOffset;		/* Time zone offset in seconds east of
				 * Greenwich */
    Tcl_WideInt julianDay;	/* Julian Day Number in local time zone */
    int isBce;			/* 1 if BCE */
    int gregorian;		/* Flag == 1 if the date is Gregorian */
    int year;			/* Year of the era */
    int dayOfYear;		/* Day of the year (1 January == 1) */
    int month;			/* Month number */
    int dayOfMonth;		/* Day of the month */
    int iso8601Year;		/* ISO8601 week-based year */
    int iso8601Week;		/* ISO8601 week number */
    int dayOfWeek;		/* Day of the week */
    int hour;			/* Hours of day (in-between time only calculation) */
    int minutes;		/* Minutes of hour (in-between time only calculation) */
    Tcl_WideInt secondOfMin;	/* Seconds of minute (in-between time only calculation) */
    Tcl_WideInt secondOfDay;	/* Seconds of day (in-between time only calculation) */

    int flags;			/* 0 or CLF_CTZ */

    /* Non cacheable fields:	 */

    Tcl_Obj *tzName;		/* Name (or corresponding DST-abbreviation) of the
				 * time zone, if set the refCount is incremented */
} TclDateFields;

#define ClockCacheableDateFieldsSize \
    offsetof(TclDateFields, tzName)

/*
 * Meridian: am, pm, or 24-hour style.
 */

typedef enum _MERIDIAN {
    MERam, MERpm, MER24
} MERIDIAN;

/*
 * Structure contains return parsed fields.
 */

typedef struct DateInfo {
    const char *dateStart;
    const char *dateInput;
    const char *dateEnd;

    TclDateFields date;

    int flags;			/* Signals parts of date/time get found */
    int errFlags;		/* Signals error (part of date/time found twice) */

    MERIDIAN dateMeridian;

    int dateTimezone;
    int dateDSTmode;

    Tcl_WideInt dateRelMonth;
    Tcl_WideInt dateRelDay;
    Tcl_WideInt dateRelSeconds;

    int dateMonthOrdinalIncr;
    int dateMonthOrdinal;

    int dateDayOrdinal;

    Tcl_WideInt *dateRelPointer;

    int dateSpaceCount;
    int dateDigitCount;

    int dateCentury;

    Tcl_Obj *messages;		/* Error messages */
    const char* separatrix;	/* String separating messages */
} DateInfo;

#define yydate	    (info->date)  /* Date fields used for converting */

#define yyDay	    (info->date.dayOfMonth)
#define yyMonth	    (info->date.month)
#define yyYear	    (info->date.year)

#define yyHour	    (info->date.hour)
#define yyMinutes   (info->date.minutes)
#define yySeconds   (info->date.secondOfMin)
#define yySecondOfDay (info->date.secondOfDay)

#define yyDSTmode   (info->dateDSTmode)
#define yyDayOrdinal	(info->dateDayOrdinal)
#define yyDayOfWeek (info->date.dayOfWeek)
#define yyMonthOrdinalIncr  (info->dateMonthOrdinalIncr)
#define yyMonthOrdinal	(info->dateMonthOrdinal)
#define yyTimezone  (info->dateTimezone)
#define yyMeridian  (info->dateMeridian)
#define yyRelMonth  (info->dateRelMonth)
#define yyRelDay    (info->dateRelDay)
#define yyRelSeconds	(info->dateRelSeconds)
#define yyRelPointer	(info->dateRelPointer)
#define yyInput	    (info->dateInput)
#define yyDigitCount	(info->dateDigitCount)
#define yySpaceCount	(info->dateSpaceCount)

static inline void
ClockInitDateInfo(
    DateInfo *info)
{
    memset(info, 0, sizeof(DateInfo));
}

/*
 * Structure containing the command arguments supplied to [clock format] and [clock scan]
 */

enum ClockFmtScnCmdArgsFlags {
    CLF_VALIDATE_S1 = (1 << 0),
    CLF_VALIDATE_S2 = (1 << 1),
    CLF_VALIDATE = (CLF_VALIDATE_S1|CLF_VALIDATE_S2),
    CLF_EXTENDED = (1 << 4),
    CLF_STRICT = (1 << 8),
    CLF_LOCALE_USED = (1 << 15)
};

typedef struct ClockClientData ClockClientData;

typedef struct ClockFmtScnCmdArgs {
    ClockClientData *dataPtr;	/* Pointer to literal pool, etc. */
    Tcl_Interp *interp;		/* Tcl interpreter */
    Tcl_Obj *formatObj;		/* Format */
    Tcl_Obj *localeObj;		/* Name of the locale where the time will be expressed. */
    Tcl_Obj *timezoneObj;	/* Default time zone in which the time will be expressed */
    Tcl_Obj *baseObj;		/* Base (scan and add) or clockValue (format) */
    int flags;			/* Flags control scanning */
    Tcl_Obj *mcDictObj;		/* Current dictionary of tcl::clock package for given localeObj*/
} ClockFmtScnCmdArgs;

/* Last-period cache for fast UTC to local and backwards conversion */
typedef struct ClockLastTZOffs {
    /* keys */
    Tcl_Obj *timezoneObj;
    int changeover;
    Tcl_WideInt localSeconds;
    Tcl_WideInt rangesVal[2];   /* Bounds for cached time zone offset */
    /* values */
    int tzOffset;
    Tcl_Obj *tzName;		/* Name (abbreviation) of this area in TZ */
} ClockLastTZOffs;

/*
 * Structure containing the client data for [clock]
 */

typedef struct ClockClientData {
    size_t refCount;		/* Number of live references. */
    Tcl_Obj **literals;		/* Pool of object literals (common, locale independent). */
    Tcl_Obj **mcLiterals;	/* Msgcat object literals with mc-keys for search with locale. */
    Tcl_Obj **mcLitIdxs;	/* Msgcat object indices prefixed with _IDX_,
				 * used for quick dictionary search */
    Tcl_Obj *mcDicts;		/* Msgcat collection, contains weak pointers to locale
				 * catalogs, and owns it references (onetime referenced) */

    /* Cache for current clock parameters, imparted via "configure" */
    size_t lastTZEpoch;
    int currentYearCentury;
    int yearOfCenturySwitch;
    int validMinYear;
    int validMaxYear;
    double maxJDN;

    Tcl_Obj *systemTimeZone;
    Tcl_Obj *systemSetupTZData;
    Tcl_Obj *gmtSetupTimeZoneUnnorm;
    Tcl_Obj *gmtSetupTimeZone;
    Tcl_Obj *gmtSetupTZData;
    Tcl_Obj *gmtTZName;
    Tcl_Obj *lastSetupTimeZoneUnnorm;
    Tcl_Obj *lastSetupTimeZone;
    Tcl_Obj *lastSetupTZData;
    Tcl_Obj *prevSetupTimeZoneUnnorm;
    Tcl_Obj *prevSetupTimeZone;
    Tcl_Obj *prevSetupTZData;

    Tcl_Obj *defaultLocale;
    Tcl_Obj *defaultLocaleDict;
    Tcl_Obj *currentLocale;
    Tcl_Obj *currentLocaleDict;
    Tcl_Obj *lastUsedLocaleUnnorm;
    Tcl_Obj *lastUsedLocale;
    Tcl_Obj *lastUsedLocaleDict;
    Tcl_Obj *prevUsedLocaleUnnorm;
    Tcl_Obj *prevUsedLocale;
    Tcl_Obj *prevUsedLocaleDict;

    /* Cache for last base (last-second fast convert if base/tz not changed) */
    struct {
	Tcl_Obj *timezoneObj;
	TclDateFields date;
    } lastBase;

    /* Last-period cache for fast UTC to Local and backwards conversion */
    ClockLastTZOffs lastTZOffsCache[2];

    int defFlags;		    /* Default flags (from configure), ATM
				     * only CLF_VALIDATE supported */
} ClockClientData;

#define ClockDefaultYearCentury 2000
#define ClockDefaultCenturySwitch 38

/*
 * Clock scan and format facilities.
 */

#ifndef TCL_MEM_DEBUG
# define CLOCK_FMT_SCN_STORAGE_GC_SIZE 32
#else
# define CLOCK_FMT_SCN_STORAGE_GC_SIZE 0
#endif

#define CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE 2

typedef struct ClockScanToken ClockScanToken;

typedef int ClockScanTokenProc(
	ClockFmtScnCmdArgs *opts,
	DateInfo *info,
	ClockScanToken *tok);

typedef enum _CLCKTOK_TYPE {
   CTOKT_INT = 1, CTOKT_WIDE, CTOKT_PARSER, CTOKT_SPACE, CTOKT_WORD, CTOKT_CHAR,
   CFMTT_PROC
} CLCKTOK_TYPE;

typedef struct ClockScanTokenMap {
    unsigned short type;
    unsigned short flags;
    unsigned short clearFlags;
    unsigned short minSize;
    unsigned short maxSize;
    unsigned short offs;
    ClockScanTokenProc *parser;
    const void *data;
} ClockScanTokenMap;

struct ClockScanToken {
    const ClockScanTokenMap *map;
    struct {
	const char *start;
	const char *end;
    } tokWord;
    unsigned short endDistance;
    unsigned short lookAhMin;
    unsigned short lookAhMax;
    unsigned short lookAhTok;
};

#define MIN_FMT_RESULT_BLOCK_ALLOC 80
#define MIN_FMT_RESULT_BLOCK_DELTA 0
/* Maximal permitted threshold (buffer size > result size) in percent,
 * to directly return the buffer without reallocate */
#define MAX_FMT_RESULT_THRESHOLD   2

typedef struct DateFormat {
    char *resMem;
    char *resEnd;
    char *output;
    TclDateFields date;
    Tcl_Obj *localeEra;
} DateFormat;

enum ClockFormatTokenMapFlags {
    CLFMT_INCR = (1 << 3),
    CLFMT_DECR = (1 << 4),
    CLFMT_CALC = (1 << 5),
    CLFMT_LOCALE_INDX = (1 << 8)
};

typedef struct ClockFormatToken ClockFormatToken;

typedef int ClockFormatTokenProc(
	ClockFmtScnCmdArgs *opts,
	DateFormat *dateFmt,
	ClockFormatToken *tok,
	int *val);

typedef struct ClockFormatTokenMap {
    unsigned short type;
    const char *tostr;
    unsigned short width;
    unsigned short flags;
    unsigned short divider;
    unsigned short divmod;
    unsigned short offs;
    ClockFormatTokenProc *fmtproc;
    void *data;
} ClockFormatTokenMap;

struct ClockFormatToken {
    const ClockFormatTokenMap *map;
    struct {
	const char *start;
	const char *end;
    } tokWord;
};

typedef struct ClockFmtScnStorage ClockFmtScnStorage;

struct ClockFmtScnStorage {
    int objRefCount;		/* Reference count shared across threads */
    ClockScanToken *scnTok;
    unsigned scnTokC;
    unsigned scnSpaceCount;	/* Count of mandatory spaces used in format */
    ClockFormatToken *fmtTok;
    unsigned fmtTokC;
#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0
    ClockFmtScnStorage *nextPtr;
    ClockFmtScnStorage *prevPtr;
#endif
    size_t fmtMinAlloc;
#if 0
    Tcl_HashEntry hashEntry		/* ClockFmtScnStorage is a derivate of Tcl_HashEntry,
					 * stored by offset +sizeof(self) */
#endif
};

/*
 * Clock macros.
 */

/*
 * Extracts Julian day and seconds of the day from posix seconds (tm).
 */
#define ClockExtractJDAndSODFromSeconds(jd, sod, tm) \
    do {								\
	jd = (tm + JULIAN_SEC_POSIX_EPOCH);				\
	if (jd >= SECONDS_PER_DAY || jd <= -SECONDS_PER_DAY) {		\
	    jd /= SECONDS_PER_DAY;					\
	    sod = (int)(tm % SECONDS_PER_DAY);				\
	} else {							\
	    sod = (int)jd, jd = 0;					\
	}								\
	if (sod < 0) {							\
	    sod += SECONDS_PER_DAY;					\
	    /* JD is affected, if switched into negative (avoid 24 hours difference) */ \
	    if (jd <= 0) {						\
		jd--;							\
	    }								\
	}								\
    } while(0)

/*
 * Prototypes of module functions.
 */

MODULE_SCOPE int	ToSeconds(int Hours, int Minutes,
			    int Seconds, MERIDIAN Meridian);
MODULE_SCOPE int	IsGregorianLeapYear(TclDateFields *);
MODULE_SCOPE void	GetJulianDayFromEraYearWeekDay(
			    TclDateFields *fields, int changeover);
MODULE_SCOPE void	GetJulianDayFromEraYearMonthDay(
			    TclDateFields *fields, int changeover);
MODULE_SCOPE void	GetJulianDayFromEraYearDay(
			    TclDateFields *fields, int changeover);
MODULE_SCOPE int	ConvertUTCToLocal(ClockClientData *dataPtr, Tcl_Interp *,
			    TclDateFields *, Tcl_Obj *timezoneObj, int);
MODULE_SCOPE Tcl_Obj *	LookupLastTransition(Tcl_Interp *, Tcl_WideInt,
			    Tcl_Size, Tcl_Obj *const *, Tcl_WideInt *rangesVal);
MODULE_SCOPE int	TclClockFreeScan(Tcl_Interp *interp, DateInfo *info);

/* tclClock.c module declarations */

MODULE_SCOPE Tcl_Obj *	ClockSetupTimeZone(ClockClientData *dataPtr,
			    Tcl_Interp *interp, Tcl_Obj *timezoneObj);
MODULE_SCOPE Tcl_Obj *	ClockMCDict(ClockFmtScnCmdArgs *opts);
MODULE_SCOPE Tcl_Obj *	ClockMCGet(ClockFmtScnCmdArgs *opts, int mcKey);
MODULE_SCOPE Tcl_Obj *	ClockMCGetIdx(ClockFmtScnCmdArgs *opts, int mcKey);
MODULE_SCOPE int	ClockMCSetIdx(ClockFmtScnCmdArgs *opts, int mcKey,
			    Tcl_Obj *valObj);

/* tclClockFmt.c module declarations */

MODULE_SCOPE char *	TclItoAw(char *buf, int val, char padchar, unsigned short width);
MODULE_SCOPE int	TclAtoWIe(Tcl_WideInt *out, const char *p, const char *e, int sign);

MODULE_SCOPE Tcl_Obj*	ClockFrmObjGetLocFmtKey(Tcl_Interp *interp,
			    Tcl_Obj *objPtr);
MODULE_SCOPE ClockFmtScnStorage *Tcl_GetClockFrmScnFromObj(Tcl_Interp *interp,
			    Tcl_Obj *objPtr);
MODULE_SCOPE Tcl_Obj *	ClockLocalizeFormat(ClockFmtScnCmdArgs *opts);
MODULE_SCOPE int	ClockScan(DateInfo *info, Tcl_Obj *strObj,
			    ClockFmtScnCmdArgs *opts);
MODULE_SCOPE int	ClockFormat(DateFormat *dateFmt,
			    ClockFmtScnCmdArgs *opts);
MODULE_SCOPE void	ClockFrmScnClearCaches(void);
MODULE_SCOPE void	ClockFrmScnFinalize();

#endif /* _TCLCLOCK_H */

Changes to generic/tclDecls.h.

8
9
10
11
12
13
14


15
16
17
18
19
20
21
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23







+
+







 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _TCLDECLS
#define _TCLDECLS

#include <stddef.h> /* for size_t */

#undef TCL_STORAGE_CLASS
#ifdef BUILD_tcl
#   define TCL_STORAGE_CLASS DLLEXPORT
#else
#   ifdef USE_TCL_STUBS
#      define TCL_STORAGE_CLASS
#   else
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
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







-
+



-
+

-
+




-
+

-



-
-
-
-
-
-
-


-
-
-
-
-













-
+

-
+















-
+
+




-
+





-
-
+
+






-
+


-
+


-
+



















-
+









-
-
+
+



-
+


-
-
+
+


-
-
+
+
+



-
+




-
+




-
+



-
+


-
+
+




-
+



-
+


-
+







/* 1 */
EXTERN const char *	Tcl_PkgRequireEx(Tcl_Interp *interp,
				const char *name, const char *version,
				int exact, void *clientDataPtr);
/* 2 */
EXTERN TCL_NORETURN void Tcl_Panic(const char *format, ...) TCL_FORMAT_PRINTF(1, 2);
/* 3 */
EXTERN void *		Tcl_Alloc(size_t size);
EXTERN void *		Tcl_Alloc(TCL_HASH_TYPE size);
/* 4 */
EXTERN void		Tcl_Free(void *ptr);
/* 5 */
EXTERN void *		Tcl_Realloc(void *ptr, size_t size);
EXTERN void *		Tcl_Realloc(void *ptr, TCL_HASH_TYPE size);
/* 6 */
EXTERN void *		Tcl_DbCkalloc(size_t size, const char *file,
EXTERN void *		Tcl_DbCkalloc(TCL_HASH_TYPE size, const char *file,
				int line);
/* 7 */
EXTERN void		Tcl_DbCkfree(void *ptr, const char *file, int line);
/* 8 */
EXTERN void *		Tcl_DbCkrealloc(void *ptr, size_t size,
EXTERN void *		Tcl_DbCkrealloc(void *ptr, TCL_HASH_TYPE size,
				const char *file, int line);
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
/* 9 */
EXTERN void		Tcl_CreateFileHandler(int fd, int mask,
				Tcl_FileProc *proc, void *clientData);
#endif /* UNIX */
#ifdef MAC_OSX_TCL /* MACOSX */
/* 9 */
EXTERN void		Tcl_CreateFileHandler(int fd, int mask,
				Tcl_FileProc *proc, void *clientData);
#endif /* MACOSX */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
/* 10 */
EXTERN void		Tcl_DeleteFileHandler(int fd);
#endif /* UNIX */
#ifdef MAC_OSX_TCL /* MACOSX */
/* 10 */
EXTERN void		Tcl_DeleteFileHandler(int fd);
#endif /* MACOSX */
/* 11 */
EXTERN void		Tcl_SetTimer(const Tcl_Time *timePtr);
/* 12 */
EXTERN void		Tcl_Sleep(int ms);
/* 13 */
EXTERN int		Tcl_WaitForEvent(const Tcl_Time *timePtr);
/* 14 */
EXTERN int		Tcl_AppendAllObjTypes(Tcl_Interp *interp,
				Tcl_Obj *objPtr);
/* 15 */
EXTERN void		Tcl_AppendStringsToObj(Tcl_Obj *objPtr, ...);
/* 16 */
EXTERN void		Tcl_AppendToObj(Tcl_Obj *objPtr, const char *bytes,
				size_t length);
				Tcl_Size length);
/* 17 */
EXTERN Tcl_Obj *	Tcl_ConcatObj(int objc, Tcl_Obj *const objv[]);
EXTERN Tcl_Obj *	Tcl_ConcatObj(Tcl_Size objc, Tcl_Obj *const objv[]);
/* 18 */
EXTERN int		Tcl_ConvertToType(Tcl_Interp *interp,
				Tcl_Obj *objPtr, const Tcl_ObjType *typePtr);
/* 19 */
EXTERN void		Tcl_DbDecrRefCount(Tcl_Obj *objPtr, const char *file,
				int line);
/* 20 */
EXTERN void		Tcl_DbIncrRefCount(Tcl_Obj *objPtr, const char *file,
				int line);
/* 21 */
EXTERN int		Tcl_DbIsShared(Tcl_Obj *objPtr, const char *file,
				int line);
/* Slot 22 is reserved */
/* 23 */
EXTERN Tcl_Obj *	Tcl_DbNewByteArrayObj(const unsigned char *bytes,
				size_t length, const char *file, int line);
				Tcl_Size numBytes, const char *file,
				int line);
/* 24 */
EXTERN Tcl_Obj *	Tcl_DbNewDoubleObj(double doubleValue,
				const char *file, int line);
/* 25 */
EXTERN Tcl_Obj *	Tcl_DbNewListObj(int objc, Tcl_Obj *const *objv,
EXTERN Tcl_Obj *	Tcl_DbNewListObj(Tcl_Size objc, Tcl_Obj *const *objv,
				const char *file, int line);
/* Slot 26 is reserved */
/* 27 */
EXTERN Tcl_Obj *	Tcl_DbNewObj(const char *file, int line);
/* 28 */
EXTERN Tcl_Obj *	Tcl_DbNewStringObj(const char *bytes, size_t length,
				const char *file, int line);
EXTERN Tcl_Obj *	Tcl_DbNewStringObj(const char *bytes,
				Tcl_Size length, const char *file, int line);
/* 29 */
EXTERN Tcl_Obj *	Tcl_DuplicateObj(Tcl_Obj *objPtr);
/* 30 */
EXTERN void		TclFreeObj(Tcl_Obj *objPtr);
/* 31 */
EXTERN int		Tcl_GetBoolean(Tcl_Interp *interp, const char *src,
				int *boolPtr);
				int *intPtr);
/* 32 */
EXTERN int		Tcl_GetBooleanFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, int *boolPtr);
				Tcl_Obj *objPtr, int *intPtr);
/* 33 */
EXTERN unsigned char *	Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr,
				int *lengthPtr);
				Tcl_Size *numBytesPtr);
/* 34 */
EXTERN int		Tcl_GetDouble(Tcl_Interp *interp, const char *src,
				double *doublePtr);
/* 35 */
EXTERN int		Tcl_GetDoubleFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, double *doublePtr);
/* Slot 36 is reserved */
/* 37 */
EXTERN int		Tcl_GetInt(Tcl_Interp *interp, const char *src,
				int *intPtr);
/* 38 */
EXTERN int		Tcl_GetIntFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, int *intPtr);
/* 39 */
EXTERN int		Tcl_GetLongFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, long *longPtr);
/* 40 */
EXTERN const Tcl_ObjType * Tcl_GetObjType(const char *typeName);
/* 41 */
EXTERN char *		Tcl_GetStringFromObj(Tcl_Obj *objPtr, int *lengthPtr);
EXTERN char *		TclGetStringFromObj(Tcl_Obj *objPtr, void *lengthPtr);
/* 42 */
EXTERN void		Tcl_InvalidateStringRep(Tcl_Obj *objPtr);
/* 43 */
EXTERN int		Tcl_ListObjAppendList(Tcl_Interp *interp,
				Tcl_Obj *listPtr, Tcl_Obj *elemListPtr);
/* 44 */
EXTERN int		Tcl_ListObjAppendElement(Tcl_Interp *interp,
				Tcl_Obj *listPtr, Tcl_Obj *objPtr);
/* 45 */
EXTERN int		Tcl_ListObjGetElements(Tcl_Interp *interp,
				Tcl_Obj *listPtr, int *objcPtr,
EXTERN int		TclListObjGetElements(Tcl_Interp *interp,
				Tcl_Obj *listPtr, void *objcPtr,
				Tcl_Obj ***objvPtr);
/* 46 */
EXTERN int		Tcl_ListObjIndex(Tcl_Interp *interp,
				Tcl_Obj *listPtr, int index,
				Tcl_Obj *listPtr, Tcl_Size index,
				Tcl_Obj **objPtrPtr);
/* 47 */
EXTERN int		Tcl_ListObjLength(Tcl_Interp *interp,
				Tcl_Obj *listPtr, int *lengthPtr);
EXTERN int		TclListObjLength(Tcl_Interp *interp,
				Tcl_Obj *listPtr, void *lengthPtr);
/* 48 */
EXTERN int		Tcl_ListObjReplace(Tcl_Interp *interp,
				Tcl_Obj *listPtr, int first, int count,
				int objc, Tcl_Obj *const objv[]);
				Tcl_Obj *listPtr, Tcl_Size first,
				Tcl_Size count, Tcl_Size objc,
				Tcl_Obj *const objv[]);
/* Slot 49 is reserved */
/* 50 */
EXTERN Tcl_Obj *	Tcl_NewByteArrayObj(const unsigned char *bytes,
				size_t length);
				Tcl_Size numBytes);
/* 51 */
EXTERN Tcl_Obj *	Tcl_NewDoubleObj(double doubleValue);
/* Slot 52 is reserved */
/* 53 */
EXTERN Tcl_Obj *	Tcl_NewListObj(int objc, Tcl_Obj *const objv[]);
EXTERN Tcl_Obj *	Tcl_NewListObj(Tcl_Size objc, Tcl_Obj *const objv[]);
/* Slot 54 is reserved */
/* 55 */
EXTERN Tcl_Obj *	Tcl_NewObj(void);
/* 56 */
EXTERN Tcl_Obj *	Tcl_NewStringObj(const char *bytes, size_t length);
EXTERN Tcl_Obj *	Tcl_NewStringObj(const char *bytes, Tcl_Size length);
/* Slot 57 is reserved */
/* 58 */
EXTERN unsigned char *	Tcl_SetByteArrayLength(Tcl_Obj *objPtr,
				size_t length);
				Tcl_Size numBytes);
/* 59 */
EXTERN void		Tcl_SetByteArrayObj(Tcl_Obj *objPtr,
				const unsigned char *bytes, size_t length);
				const unsigned char *bytes,
				Tcl_Size numBytes);
/* 60 */
EXTERN void		Tcl_SetDoubleObj(Tcl_Obj *objPtr, double doubleValue);
/* Slot 61 is reserved */
/* 62 */
EXTERN void		Tcl_SetListObj(Tcl_Obj *objPtr, int objc,
EXTERN void		Tcl_SetListObj(Tcl_Obj *objPtr, Tcl_Size objc,
				Tcl_Obj *const objv[]);
/* Slot 63 is reserved */
/* 64 */
EXTERN void		Tcl_SetObjLength(Tcl_Obj *objPtr, size_t length);
EXTERN void		Tcl_SetObjLength(Tcl_Obj *objPtr, Tcl_Size length);
/* 65 */
EXTERN void		Tcl_SetStringObj(Tcl_Obj *objPtr, const char *bytes,
				size_t length);
				Tcl_Size length);
/* Slot 66 is reserved */
/* Slot 67 is reserved */
/* 68 */
EXTERN void		Tcl_AllowExceptions(Tcl_Interp *interp);
/* 69 */
EXTERN void		Tcl_AppendElement(Tcl_Interp *interp,
				const char *element);
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
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







-
+
+



-
+

-
+


-
-
+
+



-
+




-
+







				const char *optionList);
/* 79 */
EXTERN void		Tcl_CallWhenDeleted(Tcl_Interp *interp,
				Tcl_InterpDeleteProc *proc, void *clientData);
/* 80 */
EXTERN void		Tcl_CancelIdleCall(Tcl_IdleProc *idleProc,
				void *clientData);
/* Slot 81 is reserved */
/* 81 */
EXTERN int		Tcl_Close(Tcl_Interp *interp, Tcl_Channel chan);
/* 82 */
EXTERN int		Tcl_CommandComplete(const char *cmd);
/* 83 */
EXTERN char *		Tcl_Concat(int argc, const char *const *argv);
EXTERN char *		Tcl_Concat(Tcl_Size argc, const char *const *argv);
/* 84 */
EXTERN size_t		Tcl_ConvertElement(const char *src, char *dst,
EXTERN Tcl_Size		Tcl_ConvertElement(const char *src, char *dst,
				int flags);
/* 85 */
EXTERN size_t		Tcl_ConvertCountedElement(const char *src,
				size_t length, char *dst, int flags);
EXTERN Tcl_Size		Tcl_ConvertCountedElement(const char *src,
				Tcl_Size length, char *dst, int flags);
/* 86 */
EXTERN int		Tcl_CreateAlias(Tcl_Interp *childInterp,
				const char *childCmd, Tcl_Interp *target,
				const char *targetCmd, int argc,
				const char *targetCmd, Tcl_Size argc,
				const char *const *argv);
/* 87 */
EXTERN int		Tcl_CreateAliasObj(Tcl_Interp *childInterp,
				const char *childCmd, Tcl_Interp *target,
				const char *targetCmd, int objc,
				const char *targetCmd, Tcl_Size objc,
				Tcl_Obj *const objv[]);
/* 88 */
EXTERN Tcl_Channel	Tcl_CreateChannel(const Tcl_ChannelType *typePtr,
				const char *chanName, void *instanceData,
				int mask);
/* 89 */
EXTERN void		Tcl_CreateChannelHandler(Tcl_Channel chan, int mask,
309
310
311
312
313
314
315
316

317
318
319
320
321
322
323
302
303
304
305
306
307
308

309
310
311
312
313
314
315
316







-
+







/* 97 */
EXTERN Tcl_Interp *	Tcl_CreateChild(Tcl_Interp *interp, const char *name,
				int isSafe);
/* 98 */
EXTERN Tcl_TimerToken	Tcl_CreateTimerHandler(int milliseconds,
				Tcl_TimerProc *proc, void *clientData);
/* 99 */
EXTERN Tcl_Trace	Tcl_CreateTrace(Tcl_Interp *interp, int level,
EXTERN Tcl_Trace	Tcl_CreateTrace(Tcl_Interp *interp, Tcl_Size level,
				Tcl_CmdTraceProc *proc, void *clientData);
/* 100 */
EXTERN void		Tcl_DeleteAssocData(Tcl_Interp *interp,
				const char *name);
/* 101 */
EXTERN void		Tcl_DeleteChannelHandler(Tcl_Channel chan,
				Tcl_ChannelProc *proc, void *clientData);
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
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







-
+













-
+

















-
+







/* 108 */
EXTERN void		Tcl_DeleteHashEntry(Tcl_HashEntry *entryPtr);
/* 109 */
EXTERN void		Tcl_DeleteHashTable(Tcl_HashTable *tablePtr);
/* 110 */
EXTERN void		Tcl_DeleteInterp(Tcl_Interp *interp);
/* 111 */
EXTERN void		Tcl_DetachPids(int numPids, Tcl_Pid *pidPtr);
EXTERN void		Tcl_DetachPids(Tcl_Size numPids, Tcl_Pid *pidPtr);
/* 112 */
EXTERN void		Tcl_DeleteTimerHandler(Tcl_TimerToken token);
/* 113 */
EXTERN void		Tcl_DeleteTrace(Tcl_Interp *interp, Tcl_Trace trace);
/* 114 */
EXTERN void		Tcl_DontCallWhenDeleted(Tcl_Interp *interp,
				Tcl_InterpDeleteProc *proc, void *clientData);
/* 115 */
EXTERN int		Tcl_DoOneEvent(int flags);
/* 116 */
EXTERN void		Tcl_DoWhenIdle(Tcl_IdleProc *proc, void *clientData);
/* 117 */
EXTERN char *		Tcl_DStringAppend(Tcl_DString *dsPtr,
				const char *bytes, size_t length);
				const char *bytes, Tcl_Size length);
/* 118 */
EXTERN char *		Tcl_DStringAppendElement(Tcl_DString *dsPtr,
				const char *element);
/* 119 */
EXTERN void		Tcl_DStringEndSublist(Tcl_DString *dsPtr);
/* 120 */
EXTERN void		Tcl_DStringFree(Tcl_DString *dsPtr);
/* 121 */
EXTERN void		Tcl_DStringGetResult(Tcl_Interp *interp,
				Tcl_DString *dsPtr);
/* 122 */
EXTERN void		Tcl_DStringInit(Tcl_DString *dsPtr);
/* 123 */
EXTERN void		Tcl_DStringResult(Tcl_Interp *interp,
				Tcl_DString *dsPtr);
/* 124 */
EXTERN void		Tcl_DStringSetLength(Tcl_DString *dsPtr,
				size_t length);
				Tcl_Size length);
/* 125 */
EXTERN void		Tcl_DStringStartSublist(Tcl_DString *dsPtr);
/* 126 */
EXTERN int		Tcl_Eof(Tcl_Channel chan);
/* 127 */
EXTERN const char *	Tcl_ErrnoId(void);
/* 128 */
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
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







-
+
-
-
-
-
-

-
+



-
+








-
+







/* Slot 144 is reserved */
/* 145 */
EXTERN Tcl_HashEntry *	Tcl_FirstHashEntry(Tcl_HashTable *tablePtr,
				Tcl_HashSearch *searchPtr);
/* 146 */
EXTERN int		Tcl_Flush(Tcl_Channel chan);
/* Slot 147 is reserved */
/* 148 */
/* Slot 148 is reserved */
EXTERN int		Tcl_GetAlias(Tcl_Interp *interp,
				const char *childCmd,
				Tcl_Interp **targetInterpPtr,
				const char **targetCmdPtr, int *argcPtr,
				const char ***argvPtr);
/* 149 */
EXTERN int		Tcl_GetAliasObj(Tcl_Interp *interp,
EXTERN int		TclGetAliasObj(Tcl_Interp *interp,
				const char *childCmd,
				Tcl_Interp **targetInterpPtr,
				const char **targetCmdPtr, int *objcPtr,
				Tcl_Obj ***objv);
				Tcl_Obj ***objvPtr);
/* 150 */
EXTERN void *		Tcl_GetAssocData(Tcl_Interp *interp,
				const char *name,
				Tcl_InterpDeleteProc **procPtr);
/* 151 */
EXTERN Tcl_Channel	Tcl_GetChannel(Tcl_Interp *interp,
				const char *chanName, int *modePtr);
/* 152 */
EXTERN int		Tcl_GetChannelBufferSize(Tcl_Channel chan);
EXTERN Tcl_Size		Tcl_GetChannelBufferSize(Tcl_Channel chan);
/* 153 */
EXTERN int		Tcl_GetChannelHandle(Tcl_Channel chan, int direction,
				void **handlePtr);
/* 154 */
EXTERN void *		Tcl_GetChannelInstanceData(Tcl_Channel chan);
/* 155 */
EXTERN int		Tcl_GetChannelMode(Tcl_Channel chan);
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
473
474
475
476
477
478
479

480
481
482
483







484
485
486

487
488

489
490
491
492
493
494
495
496







-




-
-
-
-
-
-
-



-
+

-
+







				Tcl_Interp *childInterp);
/* 164 */
EXTERN Tcl_Interp *	Tcl_GetParent(Tcl_Interp *interp);
/* 165 */
EXTERN const char *	Tcl_GetNameOfExecutable(void);
/* 166 */
EXTERN Tcl_Obj *	Tcl_GetObjResult(Tcl_Interp *interp);
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
/* 167 */
EXTERN int		Tcl_GetOpenFile(Tcl_Interp *interp,
				const char *chanID, int forWriting,
				int checkUsage, void **filePtr);
#endif /* UNIX */
#ifdef MAC_OSX_TCL /* MACOSX */
/* 167 */
EXTERN int		Tcl_GetOpenFile(Tcl_Interp *interp,
				const char *chanID, int forWriting,
				int checkUsage, void **filePtr);
#endif /* MACOSX */
/* 168 */
EXTERN Tcl_PathType	Tcl_GetPathType(const char *path);
/* 169 */
EXTERN size_t		Tcl_Gets(Tcl_Channel chan, Tcl_DString *dsPtr);
EXTERN Tcl_Size		Tcl_Gets(Tcl_Channel chan, Tcl_DString *dsPtr);
/* 170 */
EXTERN size_t		Tcl_GetsObj(Tcl_Channel chan, Tcl_Obj *objPtr);
EXTERN Tcl_Size		Tcl_GetsObj(Tcl_Channel chan, Tcl_Obj *objPtr);
/* 171 */
EXTERN int		Tcl_GetServiceMode(void);
/* 172 */
EXTERN Tcl_Interp *	Tcl_GetChild(Tcl_Interp *interp, const char *name);
/* 173 */
EXTERN Tcl_Channel	Tcl_GetStdChannel(int type);
/* Slot 174 is reserved */
534
535
536
537
538
539
540
541

542
543
544
545
546
547
548
549

550
551
552
553
554

555
556
557
558
559
560
561
562
563
564
565
566
567
568


569
570
571
572
573
574
575
576

577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592

593
594
595
596


597
598
599
600
601
602
603
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
558
559
560
561
562
563
564
565
566
567
568
569
570

571

572


573
574
575
576
577
578
579
580
581







-
+







-
+
-



-
+












-
-
+
+







-
+















-
+
-

-
-
+
+







/* 183 */
EXTERN int		Tcl_InputBuffered(Tcl_Channel chan);
/* 184 */
EXTERN int		Tcl_InterpDeleted(Tcl_Interp *interp);
/* 185 */
EXTERN int		Tcl_IsSafe(Tcl_Interp *interp);
/* 186 */
EXTERN char *		Tcl_JoinPath(int argc, const char *const *argv,
EXTERN char *		Tcl_JoinPath(Tcl_Size argc, const char *const *argv,
				Tcl_DString *resultPtr);
/* 187 */
EXTERN int		Tcl_LinkVar(Tcl_Interp *interp, const char *varName,
				void *addr, int type);
/* Slot 188 is reserved */
/* 189 */
EXTERN Tcl_Channel	Tcl_MakeFileChannel(void *handle, int mode);
/* 190 */
/* Slot 190 is reserved */
EXTERN int		Tcl_MakeSafe(Tcl_Interp *interp);
/* 191 */
EXTERN Tcl_Channel	Tcl_MakeTcpClientChannel(void *tcpSocket);
/* 192 */
EXTERN char *		Tcl_Merge(int argc, const char *const *argv);
EXTERN char *		Tcl_Merge(Tcl_Size argc, const char *const *argv);
/* 193 */
EXTERN Tcl_HashEntry *	Tcl_NextHashEntry(Tcl_HashSearch *searchPtr);
/* 194 */
EXTERN void		Tcl_NotifyChannel(Tcl_Channel channel, int mask);
/* 195 */
EXTERN Tcl_Obj *	Tcl_ObjGetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
				Tcl_Obj *part2Ptr, int flags);
/* 196 */
EXTERN Tcl_Obj *	Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
				Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr,
				int flags);
/* 197 */
EXTERN Tcl_Channel	Tcl_OpenCommandChannel(Tcl_Interp *interp, int argc,
				const char **argv, int flags);
EXTERN Tcl_Channel	Tcl_OpenCommandChannel(Tcl_Interp *interp,
				Tcl_Size argc, const char **argv, int flags);
/* 198 */
EXTERN Tcl_Channel	Tcl_OpenFileChannel(Tcl_Interp *interp,
				const char *fileName, const char *modeString,
				int permissions);
/* 199 */
EXTERN Tcl_Channel	Tcl_OpenTcpClient(Tcl_Interp *interp, int port,
				const char *address, const char *myaddr,
				int myport, int async);
				int myport, int flags);
/* 200 */
EXTERN Tcl_Channel	Tcl_OpenTcpServer(Tcl_Interp *interp, int port,
				const char *host,
				Tcl_TcpAcceptProc *acceptProc,
				void *callbackData);
/* 201 */
EXTERN void		Tcl_Preserve(void *data);
/* 202 */
EXTERN void		Tcl_PrintDouble(Tcl_Interp *interp, double value,
				char *dst);
/* 203 */
EXTERN int		Tcl_PutEnv(const char *assignment);
/* 204 */
EXTERN const char *	Tcl_PosixError(Tcl_Interp *interp);
/* 205 */
EXTERN void		Tcl_QueueEvent(Tcl_Event *evPtr,
EXTERN void		Tcl_QueueEvent(Tcl_Event *evPtr, int position);
				Tcl_QueuePosition position);
/* 206 */
EXTERN size_t		Tcl_Read(Tcl_Channel chan, char *bufPtr,
				size_t toRead);
EXTERN Tcl_Size		Tcl_Read(Tcl_Channel chan, char *bufPtr,
				Tcl_Size toRead);
/* 207 */
EXTERN void		Tcl_ReapDetachedProcs(void);
/* 208 */
EXTERN int		Tcl_RecordAndEval(Tcl_Interp *interp,
				const char *cmd, int flags);
/* 209 */
EXTERN int		Tcl_RecordAndEvalObj(Tcl_Interp *interp,
613
614
615
616
617
618
619
620

621
622
623
624
625
626
627

628
629
630


631
632
633
634
635
636
637
638
639
640
641


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


659
660
661
662
663
664
665
591
592
593
594
595
596
597

598
599
600
601
602
603
604

605
606


607
608
609
610
611
612
613
614
615
616
617
618

619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

637
638
639
640
641
642
643
644
645







-
+






-
+

-
-
+
+










-
+
+
















-
+
+







/* 213 */
EXTERN int		Tcl_RegExpExec(Tcl_Interp *interp, Tcl_RegExp regexp,
				const char *text, const char *start);
/* 214 */
EXTERN int		Tcl_RegExpMatch(Tcl_Interp *interp, const char *text,
				const char *pattern);
/* 215 */
EXTERN void		Tcl_RegExpRange(Tcl_RegExp regexp, size_t index,
EXTERN void		Tcl_RegExpRange(Tcl_RegExp regexp, Tcl_Size index,
				const char **startPtr, const char **endPtr);
/* 216 */
EXTERN void		Tcl_Release(void *clientData);
/* 217 */
EXTERN void		Tcl_ResetResult(Tcl_Interp *interp);
/* 218 */
EXTERN size_t		Tcl_ScanElement(const char *src, int *flagPtr);
EXTERN Tcl_Size		Tcl_ScanElement(const char *src, int *flagPtr);
/* 219 */
EXTERN size_t		Tcl_ScanCountedElement(const char *src,
				size_t length, int *flagPtr);
EXTERN Tcl_Size		Tcl_ScanCountedElement(const char *src,
				Tcl_Size length, int *flagPtr);
/* Slot 220 is reserved */
/* 221 */
EXTERN int		Tcl_ServiceAll(void);
/* 222 */
EXTERN int		Tcl_ServiceEvent(int flags);
/* 223 */
EXTERN void		Tcl_SetAssocData(Tcl_Interp *interp,
				const char *name, Tcl_InterpDeleteProc *proc,
				void *clientData);
/* 224 */
EXTERN void		Tcl_SetChannelBufferSize(Tcl_Channel chan, int sz);
EXTERN void		Tcl_SetChannelBufferSize(Tcl_Channel chan,
				Tcl_Size sz);
/* 225 */
EXTERN int		Tcl_SetChannelOption(Tcl_Interp *interp,
				Tcl_Channel chan, const char *optionName,
				const char *newValue);
/* 226 */
EXTERN int		Tcl_SetCommandInfo(Tcl_Interp *interp,
				const char *cmdName,
				const Tcl_CmdInfo *infoPtr);
/* 227 */
EXTERN void		Tcl_SetErrno(int err);
/* 228 */
EXTERN void		Tcl_SetErrorCode(Tcl_Interp *interp, ...);
/* 229 */
EXTERN void		Tcl_SetMaxBlockTime(const Tcl_Time *timePtr);
/* Slot 230 is reserved */
/* 231 */
EXTERN int		Tcl_SetRecursionLimit(Tcl_Interp *interp, int depth);
EXTERN Tcl_Size		Tcl_SetRecursionLimit(Tcl_Interp *interp,
				Tcl_Size depth);
/* Slot 232 is reserved */
/* 233 */
EXTERN int		Tcl_SetServiceMode(int mode);
/* 234 */
EXTERN void		Tcl_SetObjErrorCode(Tcl_Interp *interp,
				Tcl_Obj *errorObjPtr);
/* 235 */
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
707
708
655
656
657
658
659
660
661

662


663
664

665
666
667
668
669
670
671
672
673
674
675
676
677
678


679
680
681
682
683
684
685
686
687







-
+
-
-
+

-
+













-
-
+
+







/* 239 */
EXTERN const char *	Tcl_SignalId(int sig);
/* 240 */
EXTERN const char *	Tcl_SignalMsg(int sig);
/* 241 */
EXTERN void		Tcl_SourceRCFile(Tcl_Interp *interp);
/* 242 */
EXTERN int		Tcl_SplitList(Tcl_Interp *interp,
EXTERN int		TclSplitList(Tcl_Interp *interp, const char *listStr,
				const char *listStr, int *argcPtr,
				const char ***argvPtr);
				void *argcPtr, const char ***argvPtr);
/* 243 */
EXTERN void		Tcl_SplitPath(const char *path, int *argcPtr,
EXTERN void		TclSplitPath(const char *path, void *argcPtr,
				const char ***argvPtr);
/* Slot 244 is reserved */
/* Slot 245 is reserved */
/* Slot 246 is reserved */
/* Slot 247 is reserved */
/* 248 */
EXTERN int		Tcl_TraceVar2(Tcl_Interp *interp, const char *part1,
				const char *part2, int flags,
				Tcl_VarTraceProc *proc, void *clientData);
/* 249 */
EXTERN char *		Tcl_TranslateFileName(Tcl_Interp *interp,
				const char *name, Tcl_DString *bufferPtr);
/* 250 */
EXTERN size_t		Tcl_Ungets(Tcl_Channel chan, const char *str,
				size_t len, int atHead);
EXTERN Tcl_Size		Tcl_Ungets(Tcl_Channel chan, const char *str,
				Tcl_Size len, int atHead);
/* 251 */
EXTERN void		Tcl_UnlinkVar(Tcl_Interp *interp,
				const char *varName);
/* 252 */
EXTERN int		Tcl_UnregisterChannel(Tcl_Interp *interp,
				Tcl_Channel chan);
/* Slot 253 is reserved */
728
729
730
731
732
733
734
735
736


737
738

739
740
741
742
743
744
745
707
708
709
710
711
712
713


714
715
716

717
718
719
720
721
722
723
724







-
-
+
+

-
+







/* Slot 261 is reserved */
/* 262 */
EXTERN void *		Tcl_VarTraceInfo2(Tcl_Interp *interp,
				const char *part1, const char *part2,
				int flags, Tcl_VarTraceProc *procPtr,
				void *prevClientData);
/* 263 */
EXTERN size_t		Tcl_Write(Tcl_Channel chan, const char *s,
				size_t slen);
EXTERN Tcl_Size		Tcl_Write(Tcl_Channel chan, const char *s,
				Tcl_Size slen);
/* 264 */
EXTERN void		Tcl_WrongNumArgs(Tcl_Interp *interp, int objc,
EXTERN void		Tcl_WrongNumArgs(Tcl_Interp *interp, Tcl_Size objc,
				Tcl_Obj *const objv[], const char *message);
/* 265 */
EXTERN int		Tcl_DumpActiveMemory(const char *fileName);
/* 266 */
EXTERN void		Tcl_ValidateAllMemory(const char *file, int line);
/* Slot 267 is reserved */
/* Slot 268 is reserved */
773
774
775
776
777
778
779
780






781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

796
797

798
799
800
801
802
803
804
805
806
807

808
809

810
811
812
813

814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833


834
835
836

837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852

853
854
855


856
857
858
859
860
861
862
863
864
865
866
867
868
869

870
871

872
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
898

899
900

901
902
903
904

905
906
907

908
909

910
911

912
913
914

915
916
917


918
919

920
921
922
923
924
925
926
752
753
754
755
756
757
758

759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778

779
780

781
782
783
784
785
786
787
788
789
790

791
792

793
794
795
796

797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815


816
817
818
819

820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835

836
837


838
839
840
841
842
843
844
845
846
847
848
849
850
851
852

853
854

855
856
857
858
859
860
861
862

863
864

865
866

867
868

869
870
871
872
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

898
899


900
901
902

903
904
905
906
907
908
909
910







-
+
+
+
+
+
+














-
+

-
+









-
+

-
+



-
+


















-
-
+
+


-
+















-
+

-
-
+
+













-
+

-
+







-
+

-
+

-
+

-
+






-
+

-
+



-
+

-
+



-
+


-
+

-
+

-
+


-
+

-
-
+
+

-
+







/* 282 */
EXTERN int		Tcl_UnstackChannel(Tcl_Interp *interp,
				Tcl_Channel chan);
/* 283 */
EXTERN Tcl_Channel	Tcl_GetStackedChannel(Tcl_Channel chan);
/* 284 */
EXTERN void		Tcl_SetMainLoop(Tcl_MainLoopProc *proc);
/* Slot 285 is reserved */
/* 285 */
EXTERN int		Tcl_GetAliasObj(Tcl_Interp *interp,
				const char *childCmd,
				Tcl_Interp **targetInterpPtr,
				const char **targetCmdPtr, Tcl_Size *objcPtr,
				Tcl_Obj ***objvPtr);
/* 286 */
EXTERN void		Tcl_AppendObjToObj(Tcl_Obj *objPtr,
				Tcl_Obj *appendObjPtr);
/* 287 */
EXTERN Tcl_Encoding	Tcl_CreateEncoding(const Tcl_EncodingType *typePtr);
/* 288 */
EXTERN void		Tcl_CreateThreadExitHandler(Tcl_ExitProc *proc,
				void *clientData);
/* 289 */
EXTERN void		Tcl_DeleteThreadExitHandler(Tcl_ExitProc *proc,
				void *clientData);
/* Slot 290 is reserved */
/* 291 */
EXTERN int		Tcl_EvalEx(Tcl_Interp *interp, const char *script,
				size_t numBytes, int flags);
				Tcl_Size numBytes, int flags);
/* 292 */
EXTERN int		Tcl_EvalObjv(Tcl_Interp *interp, int objc,
EXTERN int		Tcl_EvalObjv(Tcl_Interp *interp, Tcl_Size objc,
				Tcl_Obj *const objv[], int flags);
/* 293 */
EXTERN int		Tcl_EvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr,
				int flags);
/* 294 */
EXTERN TCL_NORETURN void Tcl_ExitThread(int status);
/* 295 */
EXTERN int		Tcl_ExternalToUtf(Tcl_Interp *interp,
				Tcl_Encoding encoding, const char *src,
				size_t srcLen, int flags,
				Tcl_Size srcLen, int flags,
				Tcl_EncodingState *statePtr, char *dst,
				size_t dstLen, int *srcReadPtr,
				Tcl_Size dstLen, int *srcReadPtr,
				int *dstWrotePtr, int *dstCharsPtr);
/* 296 */
EXTERN char *		Tcl_ExternalToUtfDString(Tcl_Encoding encoding,
				const char *src, size_t srcLen,
				const char *src, Tcl_Size srcLen,
				Tcl_DString *dsPtr);
/* 297 */
EXTERN void		Tcl_FinalizeThread(void);
/* 298 */
EXTERN void		Tcl_FinalizeNotifier(void *clientData);
/* 299 */
EXTERN void		Tcl_FreeEncoding(Tcl_Encoding encoding);
/* 300 */
EXTERN Tcl_ThreadId	Tcl_GetCurrentThread(void);
/* 301 */
EXTERN Tcl_Encoding	Tcl_GetEncoding(Tcl_Interp *interp, const char *name);
/* 302 */
EXTERN const char *	Tcl_GetEncodingName(Tcl_Encoding encoding);
/* 303 */
EXTERN void		Tcl_GetEncodingNames(Tcl_Interp *interp);
/* 304 */
EXTERN int		Tcl_GetIndexFromObjStruct(Tcl_Interp *interp,
				Tcl_Obj *objPtr, const void *tablePtr,
				size_t offset, const char *msg, int flags,
				int *indexPtr);
				Tcl_Size offset, const char *msg, int flags,
				void *indexPtr);
/* 305 */
EXTERN void *		Tcl_GetThreadData(Tcl_ThreadDataKey *keyPtr,
				size_t size);
				Tcl_Size size);
/* 306 */
EXTERN Tcl_Obj *	Tcl_GetVar2Ex(Tcl_Interp *interp, const char *part1,
				const char *part2, int flags);
/* 307 */
EXTERN void *		Tcl_InitNotifier(void);
/* 308 */
EXTERN void		Tcl_MutexLock(Tcl_Mutex *mutexPtr);
/* 309 */
EXTERN void		Tcl_MutexUnlock(Tcl_Mutex *mutexPtr);
/* 310 */
EXTERN void		Tcl_ConditionNotify(Tcl_Condition *condPtr);
/* 311 */
EXTERN void		Tcl_ConditionWait(Tcl_Condition *condPtr,
				Tcl_Mutex *mutexPtr, const Tcl_Time *timePtr);
/* 312 */
EXTERN size_t		Tcl_NumUtfChars(const char *src, size_t length);
EXTERN Tcl_Size		TclNumUtfChars(const char *src, Tcl_Size length);
/* 313 */
EXTERN size_t		Tcl_ReadChars(Tcl_Channel channel, Tcl_Obj *objPtr,
				size_t charsToRead, int appendFlag);
EXTERN Tcl_Size		Tcl_ReadChars(Tcl_Channel channel, Tcl_Obj *objPtr,
				Tcl_Size charsToRead, int appendFlag);
/* Slot 314 is reserved */
/* Slot 315 is reserved */
/* 316 */
EXTERN int		Tcl_SetSystemEncoding(Tcl_Interp *interp,
				const char *name);
/* 317 */
EXTERN Tcl_Obj *	Tcl_SetVar2Ex(Tcl_Interp *interp, const char *part1,
				const char *part2, Tcl_Obj *newValuePtr,
				int flags);
/* 318 */
EXTERN void		Tcl_ThreadAlert(Tcl_ThreadId threadId);
/* 319 */
EXTERN void		Tcl_ThreadQueueEvent(Tcl_ThreadId threadId,
				Tcl_Event *evPtr, Tcl_QueuePosition position);
				Tcl_Event *evPtr, int position);
/* 320 */
EXTERN int		Tcl_UniCharAtIndex(const char *src, size_t index);
EXTERN int		Tcl_UniCharAtIndex(const char *src, Tcl_Size index);
/* 321 */
EXTERN int		Tcl_UniCharToLower(int ch);
/* 322 */
EXTERN int		Tcl_UniCharToTitle(int ch);
/* 323 */
EXTERN int		Tcl_UniCharToUpper(int ch);
/* 324 */
EXTERN int		Tcl_UniCharToUtf(int ch, char *buf);
EXTERN Tcl_Size		Tcl_UniCharToUtf(int ch, char *buf);
/* 325 */
EXTERN const char *	Tcl_UtfAtIndex(const char *src, size_t index);
EXTERN const char *	TclUtfAtIndex(const char *src, Tcl_Size index);
/* 326 */
EXTERN int		Tcl_UtfCharComplete(const char *src, size_t length);
EXTERN int		TclUtfCharComplete(const char *src, Tcl_Size length);
/* 327 */
EXTERN size_t		Tcl_UtfBackslash(const char *src, int *readPtr,
EXTERN Tcl_Size		Tcl_UtfBackslash(const char *src, int *readPtr,
				char *dst);
/* 328 */
EXTERN const char *	Tcl_UtfFindFirst(const char *src, int ch);
/* 329 */
EXTERN const char *	Tcl_UtfFindLast(const char *src, int ch);
/* 330 */
EXTERN const char *	Tcl_UtfNext(const char *src);
EXTERN const char *	TclUtfNext(const char *src);
/* 331 */
EXTERN const char *	Tcl_UtfPrev(const char *src, const char *start);
EXTERN const char *	TclUtfPrev(const char *src, const char *start);
/* 332 */
EXTERN int		Tcl_UtfToExternal(Tcl_Interp *interp,
				Tcl_Encoding encoding, const char *src,
				size_t srcLen, int flags,
				Tcl_Size srcLen, int flags,
				Tcl_EncodingState *statePtr, char *dst,
				size_t dstLen, int *srcReadPtr,
				Tcl_Size dstLen, int *srcReadPtr,
				int *dstWrotePtr, int *dstCharsPtr);
/* 333 */
EXTERN char *		Tcl_UtfToExternalDString(Tcl_Encoding encoding,
				const char *src, size_t srcLen,
				const char *src, Tcl_Size srcLen,
				Tcl_DString *dsPtr);
/* 334 */
EXTERN int		Tcl_UtfToLower(char *src);
EXTERN Tcl_Size		Tcl_UtfToLower(char *src);
/* 335 */
EXTERN int		Tcl_UtfToTitle(char *src);
EXTERN Tcl_Size		Tcl_UtfToTitle(char *src);
/* 336 */
EXTERN int		Tcl_UtfToChar16(const char *src,
EXTERN Tcl_Size		Tcl_UtfToChar16(const char *src,
				unsigned short *chPtr);
/* 337 */
EXTERN int		Tcl_UtfToUpper(char *src);
EXTERN Tcl_Size		Tcl_UtfToUpper(char *src);
/* 338 */
EXTERN size_t		Tcl_WriteChars(Tcl_Channel chan, const char *src,
				size_t srcLen);
EXTERN Tcl_Size		Tcl_WriteChars(Tcl_Channel chan, const char *src,
				Tcl_Size srcLen);
/* 339 */
EXTERN size_t		Tcl_WriteObj(Tcl_Channel chan, Tcl_Obj *objPtr);
EXTERN Tcl_Size		Tcl_WriteObj(Tcl_Channel chan, Tcl_Obj *objPtr);
/* 340 */
EXTERN char *		Tcl_GetString(Tcl_Obj *objPtr);
/* Slot 341 is reserved */
/* Slot 342 is reserved */
/* 343 */
EXTERN void		Tcl_AlertNotifier(void *clientData);
/* 344 */
935
936
937
938
939
940
941
942


943
944
945
946

947
948
949

950
951
952
953
954
955
956
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
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
919
920
921
922
923
924
925

926
927
928
929
930

931
932
933

934
935
936
937
938
939
940
941
942
943

944
945
946

947
948
949
950
951

952
953
954
955

956
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
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







-
+
+



-
+


-
+









-
+


-
+




-
+



-
+


-
+




-
+










-
+

-
+















+
-
+





-
+


-
+
+

-
+

-
+


-
-
-
+
+
+
+
+




-
+
+









-
+







-
+

-
-
+
+

-
-
+
+







EXTERN int		Tcl_UniCharIsLower(int ch);
/* 349 */
EXTERN int		Tcl_UniCharIsSpace(int ch);
/* 350 */
EXTERN int		Tcl_UniCharIsUpper(int ch);
/* 351 */
EXTERN int		Tcl_UniCharIsWordChar(int ch);
/* Slot 352 is reserved */
/* 352 */
EXTERN Tcl_Size		Tcl_Char16Len(const unsigned short *uniStr);
/* Slot 353 is reserved */
/* 354 */
EXTERN char *		Tcl_Char16ToUtfDString(const unsigned short *uniStr,
				size_t uniLength, Tcl_DString *dsPtr);
				Tcl_Size uniLength, Tcl_DString *dsPtr);
/* 355 */
EXTERN unsigned short *	 Tcl_UtfToChar16DString(const char *src,
				size_t length, Tcl_DString *dsPtr);
				Tcl_Size length, Tcl_DString *dsPtr);
/* 356 */
EXTERN Tcl_RegExp	Tcl_GetRegExpFromObj(Tcl_Interp *interp,
				Tcl_Obj *patObj, int flags);
/* Slot 357 is reserved */
/* 358 */
EXTERN void		Tcl_FreeParse(Tcl_Parse *parsePtr);
/* 359 */
EXTERN void		Tcl_LogCommandInfo(Tcl_Interp *interp,
				const char *script, const char *command,
				size_t length);
				Tcl_Size length);
/* 360 */
EXTERN int		Tcl_ParseBraces(Tcl_Interp *interp,
				const char *start, size_t numBytes,
				const char *start, Tcl_Size numBytes,
				Tcl_Parse *parsePtr, int append,
				const char **termPtr);
/* 361 */
EXTERN int		Tcl_ParseCommand(Tcl_Interp *interp,
				const char *start, size_t numBytes,
				const char *start, Tcl_Size numBytes,
				int nested, Tcl_Parse *parsePtr);
/* 362 */
EXTERN int		Tcl_ParseExpr(Tcl_Interp *interp, const char *start,
				size_t numBytes, Tcl_Parse *parsePtr);
				Tcl_Size numBytes, Tcl_Parse *parsePtr);
/* 363 */
EXTERN int		Tcl_ParseQuotedString(Tcl_Interp *interp,
				const char *start, size_t numBytes,
				const char *start, Tcl_Size numBytes,
				Tcl_Parse *parsePtr, int append,
				const char **termPtr);
/* 364 */
EXTERN int		Tcl_ParseVarName(Tcl_Interp *interp,
				const char *start, size_t numBytes,
				const char *start, Tcl_Size numBytes,
				Tcl_Parse *parsePtr, int append);
/* 365 */
EXTERN char *		Tcl_GetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr);
/* 366 */
EXTERN int		Tcl_Chdir(const char *dirName);
/* 367 */
EXTERN int		Tcl_Access(const char *path, int mode);
/* 368 */
EXTERN int		Tcl_Stat(const char *path, struct stat *bufPtr);
/* 369 */
EXTERN int		Tcl_UtfNcmp(const char *s1, const char *s2, size_t n);
EXTERN int		TclUtfNcmp(const char *s1, const char *s2, size_t n);
/* 370 */
EXTERN int		Tcl_UtfNcasecmp(const char *s1, const char *s2,
EXTERN int		TclUtfNcasecmp(const char *s1, const char *s2,
				size_t n);
/* 371 */
EXTERN int		Tcl_StringCaseMatch(const char *str,
				const char *pattern, int nocase);
/* 372 */
EXTERN int		Tcl_UniCharIsControl(int ch);
/* 373 */
EXTERN int		Tcl_UniCharIsGraph(int ch);
/* 374 */
EXTERN int		Tcl_UniCharIsPrint(int ch);
/* 375 */
EXTERN int		Tcl_UniCharIsPunct(int ch);
/* 376 */
EXTERN int		Tcl_RegExpExecObj(Tcl_Interp *interp,
				Tcl_RegExp regexp, Tcl_Obj *textObj,
				Tcl_Size offset, Tcl_Size nmatches,
				size_t offset, size_t nmatches, int flags);
				int flags);
/* 377 */
EXTERN void		Tcl_RegExpGetInfo(Tcl_RegExp regexp,
				Tcl_RegExpInfo *infoPtr);
/* 378 */
EXTERN Tcl_Obj *	Tcl_NewUnicodeObj(const Tcl_UniChar *unicode,
				size_t numChars);
				Tcl_Size numChars);
/* 379 */
EXTERN void		Tcl_SetUnicodeObj(Tcl_Obj *objPtr,
				const Tcl_UniChar *unicode, size_t numChars);
				const Tcl_UniChar *unicode,
				Tcl_Size numChars);
/* 380 */
EXTERN size_t		Tcl_GetCharLength(Tcl_Obj *objPtr);
EXTERN Tcl_Size		TclGetCharLength(Tcl_Obj *objPtr);
/* 381 */
EXTERN int		Tcl_GetUniChar(Tcl_Obj *objPtr, size_t index);
EXTERN int		TclGetUniChar(Tcl_Obj *objPtr, Tcl_Size index);
/* Slot 382 is reserved */
/* 383 */
EXTERN Tcl_Obj *	Tcl_GetRange(Tcl_Obj *objPtr, size_t first,
				size_t last);
/* Slot 384 is reserved */
EXTERN Tcl_Obj *	TclGetRange(Tcl_Obj *objPtr, Tcl_Size first,
				Tcl_Size last);
/* 384 */
EXTERN void		Tcl_AppendUnicodeToObj(Tcl_Obj *objPtr,
				const Tcl_UniChar *unicode, Tcl_Size length);
/* 385 */
EXTERN int		Tcl_RegExpMatchObj(Tcl_Interp *interp,
				Tcl_Obj *textObj, Tcl_Obj *patternObj);
/* 386 */
EXTERN void		Tcl_SetNotifier(Tcl_NotifierProcs *notifierProcPtr);
EXTERN void		Tcl_SetNotifier(
				const Tcl_NotifierProcs *notifierProcPtr);
/* 387 */
EXTERN Tcl_Mutex *	Tcl_GetAllocMutex(void);
/* 388 */
EXTERN int		Tcl_GetChannelNames(Tcl_Interp *interp);
/* 389 */
EXTERN int		Tcl_GetChannelNamesEx(Tcl_Interp *interp,
				const char *pattern);
/* 390 */
EXTERN int		Tcl_ProcObjCmd(void *clientData, Tcl_Interp *interp,
				int objc, Tcl_Obj *const objv[]);
				Tcl_Size objc, Tcl_Obj *const objv[]);
/* 391 */
EXTERN void		Tcl_ConditionFinalize(Tcl_Condition *condPtr);
/* 392 */
EXTERN void		Tcl_MutexFinalize(Tcl_Mutex *mutex);
/* 393 */
EXTERN int		Tcl_CreateThread(Tcl_ThreadId *idPtr,
				Tcl_ThreadCreateProc *proc, void *clientData,
				size_t stackSize, int flags);
				TCL_HASH_TYPE stackSize, int flags);
/* 394 */
EXTERN size_t		Tcl_ReadRaw(Tcl_Channel chan, char *dst,
				size_t bytesToRead);
EXTERN Tcl_Size		Tcl_ReadRaw(Tcl_Channel chan, char *dst,
				Tcl_Size bytesToRead);
/* 395 */
EXTERN size_t		Tcl_WriteRaw(Tcl_Channel chan, const char *src,
				size_t srcLen);
EXTERN Tcl_Size		Tcl_WriteRaw(Tcl_Channel chan, const char *src,
				Tcl_Size srcLen);
/* 396 */
EXTERN Tcl_Channel	Tcl_GetTopChannel(Tcl_Channel chan);
/* 397 */
EXTERN int		Tcl_ChannelBuffered(Tcl_Channel chan);
/* 398 */
EXTERN const char *	Tcl_ChannelName(const Tcl_ChannelType *chanTypePtr);
/* 399 */
1128
1129
1130
1131
1132
1133
1134
1135

1136
1137
1138


1139
1140

1141
1142

1143
1144
1145
1146

1147
1148
1149
1150
1151


1152
1153
1154
1155
1156
1157
1158
1118
1119
1120
1121
1122
1123
1124

1125
1126


1127
1128
1129

1130
1131

1132
1133
1134
1135

1136
1137
1138
1139


1140
1141
1142
1143
1144
1145
1146
1147
1148







-
+

-
-
+
+

-
+

-
+



-
+



-
-
+
+







				const char *varName, int flags,
				Tcl_CommandTraceProc *proc, void *clientData);
/* 427 */
EXTERN void		Tcl_UntraceCommand(Tcl_Interp *interp,
				const char *varName, int flags,
				Tcl_CommandTraceProc *proc, void *clientData);
/* 428 */
EXTERN void *		Tcl_AttemptAlloc(size_t size);
EXTERN void *		Tcl_AttemptAlloc(TCL_HASH_TYPE size);
/* 429 */
EXTERN void *		Tcl_AttemptDbCkalloc(size_t size, const char *file,
				int line);
EXTERN void *		Tcl_AttemptDbCkalloc(TCL_HASH_TYPE size,
				const char *file, int line);
/* 430 */
EXTERN void *		Tcl_AttemptRealloc(void *ptr, size_t size);
EXTERN void *		Tcl_AttemptRealloc(void *ptr, TCL_HASH_TYPE size);
/* 431 */
EXTERN void *		Tcl_AttemptDbCkrealloc(void *ptr, size_t size,
EXTERN void *		Tcl_AttemptDbCkrealloc(void *ptr, TCL_HASH_TYPE size,
				const char *file, int line);
/* 432 */
EXTERN int		Tcl_AttemptSetObjLength(Tcl_Obj *objPtr,
				size_t length);
				Tcl_Size length);
/* 433 */
EXTERN Tcl_ThreadId	Tcl_GetChannelThread(Tcl_Channel channel);
/* 434 */
EXTERN Tcl_UniChar *	Tcl_GetUnicodeFromObj(Tcl_Obj *objPtr,
				int *lengthPtr);
EXTERN Tcl_UniChar *	TclGetUnicodeFromObj(Tcl_Obj *objPtr,
				void *lengthPtr);
/* Slot 435 is reserved */
/* Slot 436 is reserved */
/* 437 */
EXTERN Tcl_Obj *	Tcl_SubstObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
				int flags);
/* 438 */
EXTERN int		Tcl_DetachChannel(Tcl_Interp *interp,
1168
1169
1170
1171
1172
1173
1174
1175
1176


1177
1178
1179
1180
1181
1182
1183
1158
1159
1160
1161
1162
1163
1164


1165
1166
1167
1168
1169
1170
1171
1172
1173







-
-
+
+







/* 442 */
EXTERN int		Tcl_FSCreateDirectory(Tcl_Obj *pathPtr);
/* 443 */
EXTERN int		Tcl_FSDeleteFile(Tcl_Obj *pathPtr);
/* 444 */
EXTERN int		Tcl_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr,
				const char *sym1, const char *sym2,
				Tcl_PackageInitProc **proc1Ptr,
				Tcl_PackageInitProc **proc2Ptr,
				Tcl_LibraryInitProc **proc1Ptr,
				Tcl_LibraryInitProc **proc2Ptr,
				Tcl_LoadHandle *handlePtr,
				Tcl_FSUnloadFileProc **unloadProcPtr);
/* 445 */
EXTERN int		Tcl_FSMatchInDirectory(Tcl_Interp *interp,
				Tcl_Obj *result, Tcl_Obj *pathPtr,
				const char *pattern, Tcl_GlobTypeData *types);
/* 446 */
1214
1215
1216
1217
1218
1219
1220
1221

1222
1223

1224
1225
1226
1227
1228
1229
1230
1231

1232
1233
1234
1235
1236
1237
1238
1204
1205
1206
1207
1208
1209
1210

1211
1212

1213
1214
1215
1216
1217
1218
1219
1220

1221
1222
1223
1224
1225
1226
1227
1228







-
+

-
+







-
+







EXTERN Tcl_Obj *	Tcl_FSGetCwd(Tcl_Interp *interp);
/* 458 */
EXTERN int		Tcl_FSChdir(Tcl_Obj *pathPtr);
/* 459 */
EXTERN int		Tcl_FSConvertToPathType(Tcl_Interp *interp,
				Tcl_Obj *pathPtr);
/* 460 */
EXTERN Tcl_Obj *	Tcl_FSJoinPath(Tcl_Obj *listObj, int elements);
EXTERN Tcl_Obj *	Tcl_FSJoinPath(Tcl_Obj *listObj, Tcl_Size elements);
/* 461 */
EXTERN Tcl_Obj *	Tcl_FSSplitPath(Tcl_Obj *pathPtr, int *lenPtr);
EXTERN Tcl_Obj *	TclFSSplitPath(Tcl_Obj *pathPtr, void *lenPtr);
/* 462 */
EXTERN int		Tcl_FSEqualPaths(Tcl_Obj *firstPtr,
				Tcl_Obj *secondPtr);
/* 463 */
EXTERN Tcl_Obj *	Tcl_FSGetNormalizedPath(Tcl_Interp *interp,
				Tcl_Obj *pathPtr);
/* 464 */
EXTERN Tcl_Obj *	Tcl_FSJoinToPath(Tcl_Obj *pathPtr, int objc,
EXTERN Tcl_Obj *	Tcl_FSJoinToPath(Tcl_Obj *pathPtr, Tcl_Size objc,
				Tcl_Obj *const objv[]);
/* 465 */
EXTERN void *		Tcl_FSGetInternalRep(Tcl_Obj *pathPtr,
				const Tcl_Filesystem *fsPtr);
/* 466 */
EXTERN Tcl_Obj *	Tcl_FSGetTranslatedPath(Tcl_Interp *interp,
				Tcl_Obj *pathPtr);
1266
1267
1268
1269
1270
1271
1272
1273

1274
1275
1276
1277
1278



1279
1280
1281
1282
1283
1284
1285
1256
1257
1258
1259
1260
1261
1262

1263
1264
1265
1266


1267
1268
1269
1270
1271
1272
1273
1274
1275
1276







-
+



-
-
+
+
+







EXTERN Tcl_PathType	Tcl_FSGetPathType(Tcl_Obj *pathPtr);
/* 479 */
EXTERN int		Tcl_OutputBuffered(Tcl_Channel chan);
/* 480 */
EXTERN void		Tcl_FSMountsChanged(const Tcl_Filesystem *fsPtr);
/* 481 */
EXTERN int		Tcl_EvalTokensStandard(Tcl_Interp *interp,
				Tcl_Token *tokenPtr, size_t count);
				Tcl_Token *tokenPtr, Tcl_Size count);
/* 482 */
EXTERN void		Tcl_GetTime(Tcl_Time *timeBuf);
/* 483 */
EXTERN Tcl_Trace	Tcl_CreateObjTrace(Tcl_Interp *interp, int level,
				int flags, Tcl_CmdObjTraceProc *objProc,
EXTERN Tcl_Trace	Tcl_CreateObjTrace(Tcl_Interp *interp,
				Tcl_Size level, int flags,
				Tcl_CmdObjTraceProc *objProc,
				void *clientData,
				Tcl_CmdObjTraceDeleteProc *delProc);
/* 484 */
EXTERN int		Tcl_GetCommandInfoFromToken(Tcl_Command token,
				Tcl_CmdInfo *infoPtr);
/* 485 */
EXTERN int		Tcl_SetCommandInfoFromToken(Tcl_Command token,
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
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







-
+


-
+













-
-
+
+













-
+



-
+







EXTERN Tcl_Obj *	Tcl_NewWideIntObj(Tcl_WideInt wideValue);
/* 489 */
EXTERN void		Tcl_SetWideIntObj(Tcl_Obj *objPtr,
				Tcl_WideInt wideValue);
/* 490 */
EXTERN Tcl_StatBuf *	Tcl_AllocStatBuf(void);
/* 491 */
EXTERN Tcl_WideInt	Tcl_Seek(Tcl_Channel chan, Tcl_WideInt offset,
EXTERN long long	Tcl_Seek(Tcl_Channel chan, long long offset,
				int mode);
/* 492 */
EXTERN Tcl_WideInt	Tcl_Tell(Tcl_Channel chan);
EXTERN long long	Tcl_Tell(Tcl_Channel chan);
/* 493 */
EXTERN Tcl_DriverWideSeekProc * Tcl_ChannelWideSeekProc(
				const Tcl_ChannelType *chanTypePtr);
/* 494 */
EXTERN int		Tcl_DictObjPut(Tcl_Interp *interp, Tcl_Obj *dictPtr,
				Tcl_Obj *keyPtr, Tcl_Obj *valuePtr);
/* 495 */
EXTERN int		Tcl_DictObjGet(Tcl_Interp *interp, Tcl_Obj *dictPtr,
				Tcl_Obj *keyPtr, Tcl_Obj **valuePtrPtr);
/* 496 */
EXTERN int		Tcl_DictObjRemove(Tcl_Interp *interp,
				Tcl_Obj *dictPtr, Tcl_Obj *keyPtr);
/* 497 */
EXTERN int		Tcl_DictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr,
				int *sizePtr);
EXTERN int		TclDictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr,
				void *sizePtr);
/* 498 */
EXTERN int		Tcl_DictObjFirst(Tcl_Interp *interp,
				Tcl_Obj *dictPtr, Tcl_DictSearch *searchPtr,
				Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr,
				int *donePtr);
/* 499 */
EXTERN void		Tcl_DictObjNext(Tcl_DictSearch *searchPtr,
				Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr,
				int *donePtr);
/* 500 */
EXTERN void		Tcl_DictObjDone(Tcl_DictSearch *searchPtr);
/* 501 */
EXTERN int		Tcl_DictObjPutKeyList(Tcl_Interp *interp,
				Tcl_Obj *dictPtr, int keyc,
				Tcl_Obj *dictPtr, Tcl_Size keyc,
				Tcl_Obj *const *keyv, Tcl_Obj *valuePtr);
/* 502 */
EXTERN int		Tcl_DictObjRemoveKeyList(Tcl_Interp *interp,
				Tcl_Obj *dictPtr, int keyc,
				Tcl_Obj *dictPtr, Tcl_Size keyc,
				Tcl_Obj *const *keyv);
/* 503 */
EXTERN Tcl_Obj *	Tcl_NewDictObj(void);
/* 504 */
EXTERN Tcl_Obj *	Tcl_DbNewDictObj(const char *file, int line);
/* 505 */
EXTERN void		Tcl_RegisterConfig(Tcl_Interp *interp,
1397
1398
1399
1400
1401
1402
1403
1404

1405
1406
1407
1408
1409
1410
1411
1388
1389
1390
1391
1392
1393
1394

1395
1396
1397
1398
1399
1400
1401
1402







-
+







EXTERN int		Tcl_LimitReady(Tcl_Interp *interp);
/* 523 */
EXTERN int		Tcl_LimitCheck(Tcl_Interp *interp);
/* 524 */
EXTERN int		Tcl_LimitExceeded(Tcl_Interp *interp);
/* 525 */
EXTERN void		Tcl_LimitSetCommands(Tcl_Interp *interp,
				int commandLimit);
				Tcl_Size commandLimit);
/* 526 */
EXTERN void		Tcl_LimitSetTime(Tcl_Interp *interp,
				Tcl_Time *timeLimitPtr);
/* 527 */
EXTERN void		Tcl_LimitSetGranularity(Tcl_Interp *interp, int type,
				int granularity);
/* 528 */
1494
1495
1496
1497
1498
1499
1500
1501

1502
1503
1504
1505
1506
1507
1508
1485
1486
1487
1488
1489
1490
1491

1492
1493
1494
1495
1496
1497
1498
1499







-
+







EXTERN int		Tcl_GetBignumFromObj(Tcl_Interp *interp,
				Tcl_Obj *obj, void *value);
/* 559 */
EXTERN int		Tcl_TakeBignumFromObj(Tcl_Interp *interp,
				Tcl_Obj *obj, void *value);
/* 560 */
EXTERN int		Tcl_TruncateChannel(Tcl_Channel chan,
				Tcl_WideInt length);
				long long length);
/* 561 */
EXTERN Tcl_DriverTruncateProc * Tcl_ChannelTruncateProc(
				const Tcl_ChannelType *chanTypePtr);
/* 562 */
EXTERN void		Tcl_SetChannelErrorInterp(Tcl_Interp *interp,
				Tcl_Obj *msg);
/* 563 */
1529
1530
1531
1532
1533
1534
1535
1536

1537
1538
1539
1540
1541
1542
1543
1544


1545
1546
1547

1548
1549
1550
1551

1552
1553
1554
1555
1556
1557
1558
1520
1521
1522
1523
1524
1525
1526

1527
1528
1529
1530
1531
1532
1533


1534
1535
1536
1537

1538
1539
1540
1541

1542
1543
1544
1545
1546
1547
1548
1549







-
+






-
-
+
+


-
+



-
+







/* 571 */
EXTERN int		Tcl_SetEncodingSearchPath(Tcl_Obj *searchPath);
/* 572 */
EXTERN const char *	Tcl_GetEncodingNameFromEnvironment(
				Tcl_DString *bufPtr);
/* 573 */
EXTERN int		Tcl_PkgRequireProc(Tcl_Interp *interp,
				const char *name, int objc,
				const char *name, Tcl_Size objc,
				Tcl_Obj *const objv[], void *clientDataPtr);
/* 574 */
EXTERN void		Tcl_AppendObjToErrorInfo(Tcl_Interp *interp,
				Tcl_Obj *objPtr);
/* 575 */
EXTERN void		Tcl_AppendLimitedToObj(Tcl_Obj *objPtr,
				const char *bytes, size_t length,
				size_t limit, const char *ellipsis);
				const char *bytes, Tcl_Size length,
				Tcl_Size limit, const char *ellipsis);
/* 576 */
EXTERN Tcl_Obj *	Tcl_Format(Tcl_Interp *interp, const char *format,
				int objc, Tcl_Obj *const objv[]);
				Tcl_Size objc, Tcl_Obj *const objv[]);
/* 577 */
EXTERN int		Tcl_AppendFormatToObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, const char *format,
				int objc, Tcl_Obj *const objv[]);
				Tcl_Size objc, Tcl_Obj *const objv[]);
/* 578 */
EXTERN Tcl_Obj *	Tcl_ObjPrintf(const char *format, ...) TCL_FORMAT_PRINTF(1, 2);
/* 579 */
EXTERN void		Tcl_AppendPrintfToObj(Tcl_Obj *objPtr,
				const char *format, ...) TCL_FORMAT_PRINTF(2, 3);
/* 580 */
EXTERN int		Tcl_CancelEval(Tcl_Interp *interp,
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
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







-
+



-
+
+







-
+















-
+

-
+


-
+

-
+

-
+









-
-
+
+


















-
+



-
+


-
+















-
+







				const char *cmdName, Tcl_ObjCmdProc *proc,
				Tcl_ObjCmdProc *nreProc, void *clientData,
				Tcl_CmdDeleteProc *deleteProc);
/* 584 */
EXTERN int		Tcl_NREvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
				int flags);
/* 585 */
EXTERN int		Tcl_NREvalObjv(Tcl_Interp *interp, int objc,
EXTERN int		Tcl_NREvalObjv(Tcl_Interp *interp, Tcl_Size objc,
				Tcl_Obj *const objv[], int flags);
/* 586 */
EXTERN int		Tcl_NRCmdSwap(Tcl_Interp *interp, Tcl_Command cmd,
				int objc, Tcl_Obj *const objv[], int flags);
				Tcl_Size objc, Tcl_Obj *const objv[],
				int flags);
/* 587 */
EXTERN void		Tcl_NRAddCallback(Tcl_Interp *interp,
				Tcl_NRPostProc *postProcPtr, void *data0,
				void *data1, void *data2, void *data3);
/* 588 */
EXTERN int		Tcl_NRCallObjProc(Tcl_Interp *interp,
				Tcl_ObjCmdProc *objProc, void *clientData,
				int objc, Tcl_Obj *const objv[]);
				Tcl_Size objc, Tcl_Obj *const objv[]);
/* 589 */
EXTERN unsigned		Tcl_GetFSDeviceFromStat(const Tcl_StatBuf *statPtr);
/* 590 */
EXTERN unsigned		Tcl_GetFSInodeFromStat(const Tcl_StatBuf *statPtr);
/* 591 */
EXTERN unsigned		Tcl_GetModeFromStat(const Tcl_StatBuf *statPtr);
/* 592 */
EXTERN int		Tcl_GetLinkCountFromStat(const Tcl_StatBuf *statPtr);
/* 593 */
EXTERN int		Tcl_GetUserIdFromStat(const Tcl_StatBuf *statPtr);
/* 594 */
EXTERN int		Tcl_GetGroupIdFromStat(const Tcl_StatBuf *statPtr);
/* 595 */
EXTERN int		Tcl_GetDeviceTypeFromStat(const Tcl_StatBuf *statPtr);
/* 596 */
EXTERN Tcl_WideInt	Tcl_GetAccessTimeFromStat(const Tcl_StatBuf *statPtr);
EXTERN long long	Tcl_GetAccessTimeFromStat(const Tcl_StatBuf *statPtr);
/* 597 */
EXTERN Tcl_WideInt	Tcl_GetModificationTimeFromStat(
EXTERN long long	Tcl_GetModificationTimeFromStat(
				const Tcl_StatBuf *statPtr);
/* 598 */
EXTERN Tcl_WideInt	Tcl_GetChangeTimeFromStat(const Tcl_StatBuf *statPtr);
EXTERN long long	Tcl_GetChangeTimeFromStat(const Tcl_StatBuf *statPtr);
/* 599 */
EXTERN Tcl_WideUInt	Tcl_GetSizeFromStat(const Tcl_StatBuf *statPtr);
EXTERN unsigned long long Tcl_GetSizeFromStat(const Tcl_StatBuf *statPtr);
/* 600 */
EXTERN Tcl_WideUInt	Tcl_GetBlocksFromStat(const Tcl_StatBuf *statPtr);
EXTERN unsigned long long Tcl_GetBlocksFromStat(const Tcl_StatBuf *statPtr);
/* 601 */
EXTERN unsigned		Tcl_GetBlockSizeFromStat(const Tcl_StatBuf *statPtr);
/* 602 */
EXTERN int		Tcl_SetEnsembleParameterList(Tcl_Interp *interp,
				Tcl_Command token, Tcl_Obj *paramList);
/* 603 */
EXTERN int		Tcl_GetEnsembleParameterList(Tcl_Interp *interp,
				Tcl_Command token, Tcl_Obj **paramListPtr);
/* 604 */
EXTERN int		Tcl_ParseArgsObjv(Tcl_Interp *interp,
				const Tcl_ArgvInfo *argTable, int *objcPtr,
EXTERN int		TclParseArgsObjv(Tcl_Interp *interp,
				const Tcl_ArgvInfo *argTable, void *objcPtr,
				Tcl_Obj *const *objv, Tcl_Obj ***remObjv);
/* 605 */
EXTERN int		Tcl_GetErrorLine(Tcl_Interp *interp);
/* 606 */
EXTERN void		Tcl_SetErrorLine(Tcl_Interp *interp, int lineNum);
/* 607 */
EXTERN void		Tcl_TransferResult(Tcl_Interp *sourceInterp,
				int code, Tcl_Interp *targetInterp);
/* 608 */
EXTERN int		Tcl_InterpActive(Tcl_Interp *interp);
/* 609 */
EXTERN void		Tcl_BackgroundException(Tcl_Interp *interp, int code);
/* 610 */
EXTERN int		Tcl_ZlibDeflate(Tcl_Interp *interp, int format,
				Tcl_Obj *data, int level,
				Tcl_Obj *gzipHeaderDictObj);
/* 611 */
EXTERN int		Tcl_ZlibInflate(Tcl_Interp *interp, int format,
				Tcl_Obj *data, size_t buffersize,
				Tcl_Obj *data, Tcl_Size buffersize,
				Tcl_Obj *gzipHeaderDictObj);
/* 612 */
EXTERN unsigned int	Tcl_ZlibCRC32(unsigned int crc,
				const unsigned char *buf, size_t len);
				const unsigned char *buf, Tcl_Size len);
/* 613 */
EXTERN unsigned int	Tcl_ZlibAdler32(unsigned int adler,
				const unsigned char *buf, size_t len);
				const unsigned char *buf, Tcl_Size len);
/* 614 */
EXTERN int		Tcl_ZlibStreamInit(Tcl_Interp *interp, int mode,
				int format, int level, Tcl_Obj *dictObj,
				Tcl_ZlibStream *zshandle);
/* 615 */
EXTERN Tcl_Obj *	Tcl_ZlibStreamGetCommandName(Tcl_ZlibStream zshandle);
/* 616 */
EXTERN int		Tcl_ZlibStreamEof(Tcl_ZlibStream zshandle);
/* 617 */
EXTERN int		Tcl_ZlibStreamChecksum(Tcl_ZlibStream zshandle);
/* 618 */
EXTERN int		Tcl_ZlibStreamPut(Tcl_ZlibStream zshandle,
				Tcl_Obj *data, int flush);
/* 619 */
EXTERN int		Tcl_ZlibStreamGet(Tcl_ZlibStream zshandle,
				Tcl_Obj *data, size_t count);
				Tcl_Obj *data, Tcl_Size count);
/* 620 */
EXTERN int		Tcl_ZlibStreamClose(Tcl_ZlibStream zshandle);
/* 621 */
EXTERN int		Tcl_ZlibStreamReset(Tcl_ZlibStream zshandle);
/* 622 */
EXTERN void		Tcl_SetStartupScript(Tcl_Obj *path,
				const char *encoding);
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
1749
1750

1751
1752
1753





































































































































1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768

1769
1770
1771


1772
1773

1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798


1799
1800
1801
1802
1803
1804

1805
1806

1807
1808
1809

1810
1811
1812
1813
1814



1815
1816
1817
1818
1819
1820
1821
1822

1823
1824
1825
1826
1827
1828
1829




1830
1831

1832
1833
1834

1835
1836
1837

1838
1839
1840


1841
1842
1843

1844
1845
1846


1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862

1863
1864
1865
1866
1867
1868





1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880

1881
1882
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
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969

1970
1971





1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987

1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999

2000
2001
2002
2003
2004
2005

2006
2007
2008
2009
2010
2011
2012

2013
2014
2015
2016
2017
2018
2019
2020







-
+




-
+








+
-
+
-

-
+


-
+

-
+


-
+

-
+











-
+


-
-
+
+

-
+


-
+


-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














-
+

-
-
+
+

-
+
-

-
-
-
-
-
-
-
-

-
-
-
-
-
-
-





-
-
+
+





-
+

-
+


-
+


-
-
-
+
+
+







-
+



-
-
-
-
+
+
+
+

-
+


-
+


-
+

-
-
+
+


-
+

-
-
+
+















-
+

-
-
-
-
-
+
+
+
+
+











-
+











-
+





-
+






-
+







/* 630 */
EXTERN void		Tcl_ZlibStreamSetCompressionDictionary(
				Tcl_ZlibStream zhandle,
				Tcl_Obj *compressionDictionaryObj);
/* 631 */
EXTERN Tcl_Channel	Tcl_OpenTcpServerEx(Tcl_Interp *interp,
				const char *service, const char *host,
				unsigned int flags,
				unsigned int flags, int backlog,
				Tcl_TcpAcceptProc *acceptProc,
				void *callbackData);
/* 632 */
EXTERN int		TclZipfs_Mount(Tcl_Interp *interp,
				const char *mountPoint, const char *zipname,
				const char *zipname, const char *mountPoint,
				const char *passwd);
/* 633 */
EXTERN int		TclZipfs_Unmount(Tcl_Interp *interp,
				const char *mountPoint);
/* 634 */
EXTERN Tcl_Obj *	TclZipfs_TclLibrary(void);
/* 635 */
EXTERN int		TclZipfs_MountBuffer(Tcl_Interp *interp,
				const void *data, size_t datalen,
				const char *mountPoint, unsigned char *data,
				const char *mountPoint, int copy);
				size_t datalen, int copy);
/* 636 */
EXTERN void		Tcl_FreeIntRep(Tcl_Obj *objPtr);
EXTERN void		Tcl_FreeInternalRep(Tcl_Obj *objPtr);
/* 637 */
EXTERN char *		Tcl_InitStringRep(Tcl_Obj *objPtr, const char *bytes,
				size_t numBytes);
				TCL_HASH_TYPE numBytes);
/* 638 */
EXTERN Tcl_ObjIntRep *	Tcl_FetchIntRep(Tcl_Obj *objPtr,
EXTERN Tcl_ObjInternalRep * Tcl_FetchInternalRep(Tcl_Obj *objPtr,
				const Tcl_ObjType *typePtr);
/* 639 */
EXTERN void		Tcl_StoreIntRep(Tcl_Obj *objPtr,
EXTERN void		Tcl_StoreInternalRep(Tcl_Obj *objPtr,
				const Tcl_ObjType *typePtr,
				const Tcl_ObjIntRep *irPtr);
				const Tcl_ObjInternalRep *irPtr);
/* 640 */
EXTERN int		Tcl_HasStringRep(Tcl_Obj *objPtr);
/* 641 */
EXTERN void		Tcl_IncrRefCount(Tcl_Obj *objPtr);
/* 642 */
EXTERN void		Tcl_DecrRefCount(Tcl_Obj *objPtr);
/* 643 */
EXTERN int		Tcl_IsShared(Tcl_Obj *objPtr);
/* 644 */
EXTERN int		Tcl_LinkArray(Tcl_Interp *interp,
				const char *varName, void *addr, int type,
				size_t size);
				Tcl_Size size);
/* 645 */
EXTERN int		Tcl_GetIntForIndex(Tcl_Interp *interp,
				Tcl_Obj *objPtr, size_t endValue,
				size_t *indexPtr);
				Tcl_Obj *objPtr, Tcl_Size endValue,
				Tcl_Size *indexPtr);
/* 646 */
EXTERN int		Tcl_UtfToUniChar(const char *src, int *chPtr);
EXTERN Tcl_Size		Tcl_UtfToUniChar(const char *src, int *chPtr);
/* 647 */
EXTERN char *		Tcl_UniCharToUtfDString(const int *uniStr,
				size_t uniLength, Tcl_DString *dsPtr);
				Tcl_Size uniLength, Tcl_DString *dsPtr);
/* 648 */
EXTERN int *		Tcl_UtfToUniCharDString(const char *src,
				size_t length, Tcl_DString *dsPtr);
				Tcl_Size length, Tcl_DString *dsPtr);
/* 649 */
EXTERN unsigned char *	TclGetBytesFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, void *numBytesPtr);
/* 650 */
EXTERN unsigned char *	Tcl_GetBytesFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, Tcl_Size *numBytesPtr);
/* 651 */
EXTERN char *		Tcl_GetStringFromObj(Tcl_Obj *objPtr,
				Tcl_Size *lengthPtr);
/* 652 */
EXTERN Tcl_UniChar *	Tcl_GetUnicodeFromObj(Tcl_Obj *objPtr,
				Tcl_Size *lengthPtr);
/* 653 */
EXTERN int		Tcl_GetSizeIntFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, Tcl_Size *sizePtr);
/* 654 */
EXTERN int		Tcl_UtfCharComplete(const char *src, Tcl_Size length);
/* 655 */
EXTERN const char *	Tcl_UtfNext(const char *src);
/* 656 */
EXTERN const char *	Tcl_UtfPrev(const char *src, const char *start);
/* 657 */
EXTERN int		Tcl_FSTildeExpand(Tcl_Interp *interp,
				const char *path, Tcl_DString *dsPtr);
/* 658 */
EXTERN int		Tcl_ExternalToUtfDStringEx(Tcl_Interp *interp,
				Tcl_Encoding encoding, const char *src,
				Tcl_Size srcLen, int flags,
				Tcl_DString *dsPtr,
				Tcl_Size *errorLocationPtr);
/* 659 */
EXTERN int		Tcl_UtfToExternalDStringEx(Tcl_Interp *interp,
				Tcl_Encoding encoding, const char *src,
				Tcl_Size srcLen, int flags,
				Tcl_DString *dsPtr,
				Tcl_Size *errorLocationPtr);
/* 660 */
EXTERN int		Tcl_AsyncMarkFromSignal(Tcl_AsyncHandler async,
				int sigNumber);
/* 661 */
EXTERN int		Tcl_ListObjGetElements(Tcl_Interp *interp,
				Tcl_Obj *listPtr, Tcl_Size *objcPtr,
				Tcl_Obj ***objvPtr);
/* 662 */
EXTERN int		Tcl_ListObjLength(Tcl_Interp *interp,
				Tcl_Obj *listPtr, Tcl_Size *lengthPtr);
/* 663 */
EXTERN int		Tcl_DictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr,
				Tcl_Size *sizePtr);
/* 664 */
EXTERN int		Tcl_SplitList(Tcl_Interp *interp,
				const char *listStr, Tcl_Size *argcPtr,
				const char ***argvPtr);
/* 665 */
EXTERN void		Tcl_SplitPath(const char *path, Tcl_Size *argcPtr,
				const char ***argvPtr);
/* 666 */
EXTERN Tcl_Obj *	Tcl_FSSplitPath(Tcl_Obj *pathPtr, Tcl_Size *lenPtr);
/* 667 */
EXTERN int		Tcl_ParseArgsObjv(Tcl_Interp *interp,
				const Tcl_ArgvInfo *argTable,
				Tcl_Size *objcPtr, Tcl_Obj *const *objv,
				Tcl_Obj ***remObjv);
/* 668 */
EXTERN Tcl_Size		Tcl_UniCharLen(const int *uniStr);
/* 669 */
EXTERN Tcl_Size		Tcl_NumUtfChars(const char *src, Tcl_Size length);
/* 670 */
EXTERN Tcl_Size		Tcl_GetCharLength(Tcl_Obj *objPtr);
/* 671 */
EXTERN const char *	Tcl_UtfAtIndex(const char *src, Tcl_Size index);
/* 672 */
EXTERN Tcl_Obj *	Tcl_GetRange(Tcl_Obj *objPtr, Tcl_Size first,
				Tcl_Size last);
/* 673 */
EXTERN int		Tcl_GetUniChar(Tcl_Obj *objPtr, Tcl_Size index);
/* 674 */
EXTERN int		Tcl_GetBool(Tcl_Interp *interp, const char *src,
				int flags, char *charPtr);
/* 675 */
EXTERN int		Tcl_GetBoolFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, int flags, char *charPtr);
/* 676 */
EXTERN Tcl_Command	Tcl_CreateObjCommand2(Tcl_Interp *interp,
				const char *cmdName, Tcl_ObjCmdProc2 *proc2,
				void *clientData,
				Tcl_CmdDeleteProc *deleteProc);
/* 677 */
EXTERN Tcl_Trace	Tcl_CreateObjTrace2(Tcl_Interp *interp,
				Tcl_Size level, int flags,
				Tcl_CmdObjTraceProc2 *objProc2,
				void *clientData,
				Tcl_CmdObjTraceDeleteProc *delProc);
/* 678 */
EXTERN Tcl_Command	Tcl_NRCreateCommand2(Tcl_Interp *interp,
				const char *cmdName, Tcl_ObjCmdProc2 *proc,
				Tcl_ObjCmdProc2 *nreProc2, void *clientData,
				Tcl_CmdDeleteProc *deleteProc);
/* 679 */
EXTERN int		Tcl_NRCallObjProc2(Tcl_Interp *interp,
				Tcl_ObjCmdProc2 *objProc2, void *clientData,
				Tcl_Size objc, Tcl_Obj *const objv[]);
/* 680 */
EXTERN int		Tcl_GetNumberFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, void **clientDataPtr,
				int *typePtr);
/* 681 */
EXTERN int		Tcl_GetNumber(Tcl_Interp *interp, const char *bytes,
				Tcl_Size numBytes, void **clientDataPtr,
				int *typePtr);
/* 682 */
EXTERN int		Tcl_RemoveChannelMode(Tcl_Interp *interp,
				Tcl_Channel chan, int mode);
/* 683 */
EXTERN Tcl_Size		Tcl_GetEncodingNulLength(Tcl_Encoding encoding);
/* 684 */
EXTERN int		Tcl_GetWideUIntFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, Tcl_WideUInt *uwidePtr);
/* 685 */
EXTERN Tcl_Obj *	Tcl_DStringToObj(Tcl_DString *dsPtr);
/* 686 */
EXTERN int		Tcl_UtfNcmp(const char *s1, const char *s2, size_t n);
/* 687 */
EXTERN int		Tcl_UtfNcasecmp(const char *s1, const char *s2,
				size_t n);
/* 688 */
EXTERN Tcl_Obj *	Tcl_NewWideUIntObj(Tcl_WideUInt wideValue);
/* 689 */
EXTERN void		Tcl_SetWideUIntObj(Tcl_Obj *objPtr,
				Tcl_WideUInt uwideValue);
/* 690 */
EXTERN void		TclUnusedStubEntry(void);

typedef struct {
    const struct TclPlatStubs *tclPlatStubs;
    const struct TclIntStubs *tclIntStubs;
    const struct TclIntPlatStubs *tclIntPlatStubs;
} TclStubHooks;

typedef struct TclStubs {
    int magic;
    const TclStubHooks *hooks;

    int (*tcl_PkgProvideEx) (Tcl_Interp *interp, const char *name, const char *version, const void *clientData); /* 0 */
    const char * (*tcl_PkgRequireEx) (Tcl_Interp *interp, const char *name, const char *version, int exact, void *clientDataPtr); /* 1 */
    TCL_NORETURN1 void (*tcl_Panic) (const char *format, ...) TCL_FORMAT_PRINTF(1, 2); /* 2 */
    void * (*tcl_Alloc) (size_t size); /* 3 */
    void * (*tcl_Alloc) (TCL_HASH_TYPE size); /* 3 */
    void (*tcl_Free) (void *ptr); /* 4 */
    void * (*tcl_Realloc) (void *ptr, size_t size); /* 5 */
    void * (*tcl_DbCkalloc) (size_t size, const char *file, int line); /* 6 */
    void * (*tcl_Realloc) (void *ptr, TCL_HASH_TYPE size); /* 5 */
    void * (*tcl_DbCkalloc) (TCL_HASH_TYPE size, const char *file, int line); /* 6 */
    void (*tcl_DbCkfree) (void *ptr, const char *file, int line); /* 7 */
    void * (*tcl_DbCkrealloc) (void *ptr, size_t size, const char *file, int line); /* 8 */
    void * (*tcl_DbCkrealloc) (void *ptr, TCL_HASH_TYPE size, const char *file, int line); /* 8 */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
    void (*tcl_CreateFileHandler) (int fd, int mask, Tcl_FileProc *proc, void *clientData); /* 9 */
#endif /* UNIX */
#if defined(_WIN32) /* WIN */
    void (*reserved9)(void);
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    void (*tcl_CreateFileHandler) (int fd, int mask, Tcl_FileProc *proc, void *clientData); /* 9 */
#endif /* MACOSX */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
    void (*tcl_DeleteFileHandler) (int fd); /* 10 */
#endif /* UNIX */
#if defined(_WIN32) /* WIN */
    void (*reserved10)(void);
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    void (*tcl_DeleteFileHandler) (int fd); /* 10 */
#endif /* MACOSX */
    void (*tcl_SetTimer) (const Tcl_Time *timePtr); /* 11 */
    void (*tcl_Sleep) (int ms); /* 12 */
    int (*tcl_WaitForEvent) (const Tcl_Time *timePtr); /* 13 */
    int (*tcl_AppendAllObjTypes) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 14 */
    void (*tcl_AppendStringsToObj) (Tcl_Obj *objPtr, ...); /* 15 */
    void (*tcl_AppendToObj) (Tcl_Obj *objPtr, const char *bytes, size_t length); /* 16 */
    Tcl_Obj * (*tcl_ConcatObj) (int objc, Tcl_Obj *const objv[]); /* 17 */
    void (*tcl_AppendToObj) (Tcl_Obj *objPtr, const char *bytes, Tcl_Size length); /* 16 */
    Tcl_Obj * (*tcl_ConcatObj) (Tcl_Size objc, Tcl_Obj *const objv[]); /* 17 */
    int (*tcl_ConvertToType) (Tcl_Interp *interp, Tcl_Obj *objPtr, const Tcl_ObjType *typePtr); /* 18 */
    void (*tcl_DbDecrRefCount) (Tcl_Obj *objPtr, const char *file, int line); /* 19 */
    void (*tcl_DbIncrRefCount) (Tcl_Obj *objPtr, const char *file, int line); /* 20 */
    int (*tcl_DbIsShared) (Tcl_Obj *objPtr, const char *file, int line); /* 21 */
    void (*reserved22)(void);
    Tcl_Obj * (*tcl_DbNewByteArrayObj) (const unsigned char *bytes, size_t length, const char *file, int line); /* 23 */
    Tcl_Obj * (*tcl_DbNewByteArrayObj) (const unsigned char *bytes, Tcl_Size numBytes, const char *file, int line); /* 23 */
    Tcl_Obj * (*tcl_DbNewDoubleObj) (double doubleValue, const char *file, int line); /* 24 */
    Tcl_Obj * (*tcl_DbNewListObj) (int objc, Tcl_Obj *const *objv, const char *file, int line); /* 25 */
    Tcl_Obj * (*tcl_DbNewListObj) (Tcl_Size objc, Tcl_Obj *const *objv, const char *file, int line); /* 25 */
    void (*reserved26)(void);
    Tcl_Obj * (*tcl_DbNewObj) (const char *file, int line); /* 27 */
    Tcl_Obj * (*tcl_DbNewStringObj) (const char *bytes, size_t length, const char *file, int line); /* 28 */
    Tcl_Obj * (*tcl_DbNewStringObj) (const char *bytes, Tcl_Size length, const char *file, int line); /* 28 */
    Tcl_Obj * (*tcl_DuplicateObj) (Tcl_Obj *objPtr); /* 29 */
    void (*tclFreeObj) (Tcl_Obj *objPtr); /* 30 */
    int (*tcl_GetBoolean) (Tcl_Interp *interp, const char *src, int *boolPtr); /* 31 */
    int (*tcl_GetBooleanFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *boolPtr); /* 32 */
    unsigned char * (*tcl_GetByteArrayFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 33 */
    int (*tcl_GetBoolean) (Tcl_Interp *interp, const char *src, int *intPtr); /* 31 */
    int (*tcl_GetBooleanFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr); /* 32 */
    unsigned char * (*tcl_GetByteArrayFromObj) (Tcl_Obj *objPtr, Tcl_Size *numBytesPtr); /* 33 */
    int (*tcl_GetDouble) (Tcl_Interp *interp, const char *src, double *doublePtr); /* 34 */
    int (*tcl_GetDoubleFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, double *doublePtr); /* 35 */
    void (*reserved36)(void);
    int (*tcl_GetInt) (Tcl_Interp *interp, const char *src, int *intPtr); /* 37 */
    int (*tcl_GetIntFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr); /* 38 */
    int (*tcl_GetLongFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, long *longPtr); /* 39 */
    const Tcl_ObjType * (*tcl_GetObjType) (const char *typeName); /* 40 */
    char * (*tcl_GetStringFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 41 */
    char * (*tclGetStringFromObj) (Tcl_Obj *objPtr, void *lengthPtr); /* 41 */
    void (*tcl_InvalidateStringRep) (Tcl_Obj *objPtr); /* 42 */
    int (*tcl_ListObjAppendList) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *elemListPtr); /* 43 */
    int (*tcl_ListObjAppendElement) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *objPtr); /* 44 */
    int (*tcl_ListObjGetElements) (Tcl_Interp *interp, Tcl_Obj *listPtr, int *objcPtr, Tcl_Obj ***objvPtr); /* 45 */
    int (*tcl_ListObjIndex) (Tcl_Interp *interp, Tcl_Obj *listPtr, int index, Tcl_Obj **objPtrPtr); /* 46 */
    int (*tcl_ListObjLength) (Tcl_Interp *interp, Tcl_Obj *listPtr, int *lengthPtr); /* 47 */
    int (*tcl_ListObjReplace) (Tcl_Interp *interp, Tcl_Obj *listPtr, int first, int count, int objc, Tcl_Obj *const objv[]); /* 48 */
    int (*tclListObjGetElements) (Tcl_Interp *interp, Tcl_Obj *listPtr, void *objcPtr, Tcl_Obj ***objvPtr); /* 45 */
    int (*tcl_ListObjIndex) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size index, Tcl_Obj **objPtrPtr); /* 46 */
    int (*tclListObjLength) (Tcl_Interp *interp, Tcl_Obj *listPtr, void *lengthPtr); /* 47 */
    int (*tcl_ListObjReplace) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size first, Tcl_Size count, Tcl_Size objc, Tcl_Obj *const objv[]); /* 48 */
    void (*reserved49)(void);
    Tcl_Obj * (*tcl_NewByteArrayObj) (const unsigned char *bytes, size_t length); /* 50 */
    Tcl_Obj * (*tcl_NewByteArrayObj) (const unsigned char *bytes, Tcl_Size numBytes); /* 50 */
    Tcl_Obj * (*tcl_NewDoubleObj) (double doubleValue); /* 51 */
    void (*reserved52)(void);
    Tcl_Obj * (*tcl_NewListObj) (int objc, Tcl_Obj *const objv[]); /* 53 */
    Tcl_Obj * (*tcl_NewListObj) (Tcl_Size objc, Tcl_Obj *const objv[]); /* 53 */
    void (*reserved54)(void);
    Tcl_Obj * (*tcl_NewObj) (void); /* 55 */
    Tcl_Obj * (*tcl_NewStringObj) (const char *bytes, size_t length); /* 56 */
    Tcl_Obj * (*tcl_NewStringObj) (const char *bytes, Tcl_Size length); /* 56 */
    void (*reserved57)(void);
    unsigned char * (*tcl_SetByteArrayLength) (Tcl_Obj *objPtr, size_t length); /* 58 */
    void (*tcl_SetByteArrayObj) (Tcl_Obj *objPtr, const unsigned char *bytes, size_t length); /* 59 */
    unsigned char * (*tcl_SetByteArrayLength) (Tcl_Obj *objPtr, Tcl_Size numBytes); /* 58 */
    void (*tcl_SetByteArrayObj) (Tcl_Obj *objPtr, const unsigned char *bytes, Tcl_Size numBytes); /* 59 */
    void (*tcl_SetDoubleObj) (Tcl_Obj *objPtr, double doubleValue); /* 60 */
    void (*reserved61)(void);
    void (*tcl_SetListObj) (Tcl_Obj *objPtr, int objc, Tcl_Obj *const objv[]); /* 62 */
    void (*tcl_SetListObj) (Tcl_Obj *objPtr, Tcl_Size objc, Tcl_Obj *const objv[]); /* 62 */
    void (*reserved63)(void);
    void (*tcl_SetObjLength) (Tcl_Obj *objPtr, size_t length); /* 64 */
    void (*tcl_SetStringObj) (Tcl_Obj *objPtr, const char *bytes, size_t length); /* 65 */
    void (*tcl_SetObjLength) (Tcl_Obj *objPtr, Tcl_Size length); /* 64 */
    void (*tcl_SetStringObj) (Tcl_Obj *objPtr, const char *bytes, Tcl_Size length); /* 65 */
    void (*reserved66)(void);
    void (*reserved67)(void);
    void (*tcl_AllowExceptions) (Tcl_Interp *interp); /* 68 */
    void (*tcl_AppendElement) (Tcl_Interp *interp, const char *element); /* 69 */
    void (*tcl_AppendResult) (Tcl_Interp *interp, ...); /* 70 */
    Tcl_AsyncHandler (*tcl_AsyncCreate) (Tcl_AsyncProc *proc, void *clientData); /* 71 */
    void (*tcl_AsyncDelete) (Tcl_AsyncHandler async); /* 72 */
    int (*tcl_AsyncInvoke) (Tcl_Interp *interp, int code); /* 73 */
    void (*tcl_AsyncMark) (Tcl_AsyncHandler async); /* 74 */
    int (*tcl_AsyncReady) (void); /* 75 */
    void (*reserved76)(void);
    void (*reserved77)(void);
    int (*tcl_BadChannelOption) (Tcl_Interp *interp, const char *optionName, const char *optionList); /* 78 */
    void (*tcl_CallWhenDeleted) (Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, void *clientData); /* 79 */
    void (*tcl_CancelIdleCall) (Tcl_IdleProc *idleProc, void *clientData); /* 80 */
    void (*reserved81)(void);
    int (*tcl_Close) (Tcl_Interp *interp, Tcl_Channel chan); /* 81 */
    int (*tcl_CommandComplete) (const char *cmd); /* 82 */
    char * (*tcl_Concat) (int argc, const char *const *argv); /* 83 */
    size_t (*tcl_ConvertElement) (const char *src, char *dst, int flags); /* 84 */
    size_t (*tcl_ConvertCountedElement) (const char *src, size_t length, char *dst, int flags); /* 85 */
    int (*tcl_CreateAlias) (Tcl_Interp *childInterp, const char *childCmd, Tcl_Interp *target, const char *targetCmd, int argc, const char *const *argv); /* 86 */
    int (*tcl_CreateAliasObj) (Tcl_Interp *childInterp, const char *childCmd, Tcl_Interp *target, const char *targetCmd, int objc, Tcl_Obj *const objv[]); /* 87 */
    char * (*tcl_Concat) (Tcl_Size argc, const char *const *argv); /* 83 */
    Tcl_Size (*tcl_ConvertElement) (const char *src, char *dst, int flags); /* 84 */
    Tcl_Size (*tcl_ConvertCountedElement) (const char *src, Tcl_Size length, char *dst, int flags); /* 85 */
    int (*tcl_CreateAlias) (Tcl_Interp *childInterp, const char *childCmd, Tcl_Interp *target, const char *targetCmd, Tcl_Size argc, const char *const *argv); /* 86 */
    int (*tcl_CreateAliasObj) (Tcl_Interp *childInterp, const char *childCmd, Tcl_Interp *target, const char *targetCmd, Tcl_Size objc, Tcl_Obj *const objv[]); /* 87 */
    Tcl_Channel (*tcl_CreateChannel) (const Tcl_ChannelType *typePtr, const char *chanName, void *instanceData, int mask); /* 88 */
    void (*tcl_CreateChannelHandler) (Tcl_Channel chan, int mask, Tcl_ChannelProc *proc, void *clientData); /* 89 */
    void (*tcl_CreateCloseHandler) (Tcl_Channel chan, Tcl_CloseProc *proc, void *clientData); /* 90 */
    Tcl_Command (*tcl_CreateCommand) (Tcl_Interp *interp, const char *cmdName, Tcl_CmdProc *proc, void *clientData, Tcl_CmdDeleteProc *deleteProc); /* 91 */
    void (*tcl_CreateEventSource) (Tcl_EventSetupProc *setupProc, Tcl_EventCheckProc *checkProc, void *clientData); /* 92 */
    void (*tcl_CreateExitHandler) (Tcl_ExitProc *proc, void *clientData); /* 93 */
    Tcl_Interp * (*tcl_CreateInterp) (void); /* 94 */
    void (*reserved95)(void);
    Tcl_Command (*tcl_CreateObjCommand) (Tcl_Interp *interp, const char *cmdName, Tcl_ObjCmdProc *proc, void *clientData, Tcl_CmdDeleteProc *deleteProc); /* 96 */
    Tcl_Interp * (*tcl_CreateChild) (Tcl_Interp *interp, const char *name, int isSafe); /* 97 */
    Tcl_TimerToken (*tcl_CreateTimerHandler) (int milliseconds, Tcl_TimerProc *proc, void *clientData); /* 98 */
    Tcl_Trace (*tcl_CreateTrace) (Tcl_Interp *interp, int level, Tcl_CmdTraceProc *proc, void *clientData); /* 99 */
    Tcl_Trace (*tcl_CreateTrace) (Tcl_Interp *interp, Tcl_Size level, Tcl_CmdTraceProc *proc, void *clientData); /* 99 */
    void (*tcl_DeleteAssocData) (Tcl_Interp *interp, const char *name); /* 100 */
    void (*tcl_DeleteChannelHandler) (Tcl_Channel chan, Tcl_ChannelProc *proc, void *clientData); /* 101 */
    void (*tcl_DeleteCloseHandler) (Tcl_Channel chan, Tcl_CloseProc *proc, void *clientData); /* 102 */
    int (*tcl_DeleteCommand) (Tcl_Interp *interp, const char *cmdName); /* 103 */
    int (*tcl_DeleteCommandFromToken) (Tcl_Interp *interp, Tcl_Command command); /* 104 */
    void (*tcl_DeleteEvents) (Tcl_EventDeleteProc *proc, void *clientData); /* 105 */
    void (*tcl_DeleteEventSource) (Tcl_EventSetupProc *setupProc, Tcl_EventCheckProc *checkProc, void *clientData); /* 106 */
    void (*tcl_DeleteExitHandler) (Tcl_ExitProc *proc, void *clientData); /* 107 */
    void (*tcl_DeleteHashEntry) (Tcl_HashEntry *entryPtr); /* 108 */
    void (*tcl_DeleteHashTable) (Tcl_HashTable *tablePtr); /* 109 */
    void (*tcl_DeleteInterp) (Tcl_Interp *interp); /* 110 */
    void (*tcl_DetachPids) (int numPids, Tcl_Pid *pidPtr); /* 111 */
    void (*tcl_DetachPids) (Tcl_Size numPids, Tcl_Pid *pidPtr); /* 111 */
    void (*tcl_DeleteTimerHandler) (Tcl_TimerToken token); /* 112 */
    void (*tcl_DeleteTrace) (Tcl_Interp *interp, Tcl_Trace trace); /* 113 */
    void (*tcl_DontCallWhenDeleted) (Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, void *clientData); /* 114 */
    int (*tcl_DoOneEvent) (int flags); /* 115 */
    void (*tcl_DoWhenIdle) (Tcl_IdleProc *proc, void *clientData); /* 116 */
    char * (*tcl_DStringAppend) (Tcl_DString *dsPtr, const char *bytes, size_t length); /* 117 */
    char * (*tcl_DStringAppend) (Tcl_DString *dsPtr, const char *bytes, Tcl_Size length); /* 117 */
    char * (*tcl_DStringAppendElement) (Tcl_DString *dsPtr, const char *element); /* 118 */
    void (*tcl_DStringEndSublist) (Tcl_DString *dsPtr); /* 119 */
    void (*tcl_DStringFree) (Tcl_DString *dsPtr); /* 120 */
    void (*tcl_DStringGetResult) (Tcl_Interp *interp, Tcl_DString *dsPtr); /* 121 */
    void (*tcl_DStringInit) (Tcl_DString *dsPtr); /* 122 */
    void (*tcl_DStringResult) (Tcl_Interp *interp, Tcl_DString *dsPtr); /* 123 */
    void (*tcl_DStringSetLength) (Tcl_DString *dsPtr, size_t length); /* 124 */
    void (*tcl_DStringSetLength) (Tcl_DString *dsPtr, Tcl_Size length); /* 124 */
    void (*tcl_DStringStartSublist) (Tcl_DString *dsPtr); /* 125 */
    int (*tcl_Eof) (Tcl_Channel chan); /* 126 */
    const char * (*tcl_ErrnoId) (void); /* 127 */
    const char * (*tcl_ErrnoMsg) (int err); /* 128 */
    void (*reserved129)(void);
    int (*tcl_EvalFile) (Tcl_Interp *interp, const char *fileName); /* 130 */
    void (*reserved131)(void);
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
1958
1959


1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975

1976
1977
1978
1979

1980
1981

1982
1983
1984
1985
1986

1987
1988

1989
1990
1991
1992
1993
1994
1995


1996
1997
1998
1999
2000
2001
2002
2003
2004

2005
2006
2007
2008


2009
2010
2011
2012
2013

2014
2015
2016
2017
2018
2019
2020

2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032


2033
2034
2035
2036
2037
2038
2039

2040
2041
2042
2043
2044
2045
2046
2047
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


2095
2096
2097
2098
2099
2100
2101
2102


2103
2104
2105
2106
2107
2108
2109


2110
2111
2112
2113
2114
2115
2116




2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128










2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141

2142
2143
2144


2145
2146
2147
2148
2149
2150
2151
2152
2153






2154
2155
2156
2157
2158
2159


2160
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
2030
2031
2032
2033
2034
2035
2036


2037
2038
2039
2040

2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103

2104
2105
2106


2107
2108
2109
2110
2111
2112

2113
2114
2115
2116
2117
2118
2119

2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130


2131
2132
2133
2134
2135
2136
2137
2138

2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151


2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274

2275
2276
2277
2278

2279
2280
2281



2282
2283
2284
2285
2286
2287
2288
2289
2290
2291







-
-
+
+


-
+














-

-
-
-
-
-
-
-

-
-
+
+















-
+



-
+

-
+




-
+

-
+





-
-
+
+








-
+


-
-
+
+




-
+






-
+










-
-
+
+






-
+












-
-
+
+




















-
+





-
-
+
+


-
-
+
+







-
-
+
+






-
-
+
+





-
-
+
+



-
-
-
-
+
+
+
+


-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+












-
+

-
-
+
+



-
-
-
-
-
-
+
+
+
+
+
+




-
-
+
+





-
+

-
-
-
-
+
+
+
+

-
-
+
+

-
+



-
+


-
-
-
+
+
+







    int (*tcl_ExprObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj **resultPtrPtr); /* 141 */
    int (*tcl_ExprString) (Tcl_Interp *interp, const char *expr); /* 142 */
    void (*tcl_Finalize) (void); /* 143 */
    void (*reserved144)(void);
    Tcl_HashEntry * (*tcl_FirstHashEntry) (Tcl_HashTable *tablePtr, Tcl_HashSearch *searchPtr); /* 145 */
    int (*tcl_Flush) (Tcl_Channel chan); /* 146 */
    void (*reserved147)(void);
    int (*tcl_GetAlias) (Tcl_Interp *interp, const char *childCmd, Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, int *argcPtr, const char ***argvPtr); /* 148 */
    int (*tcl_GetAliasObj) (Tcl_Interp *interp, const char *childCmd, Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, int *objcPtr, Tcl_Obj ***objv); /* 149 */
    void (*reserved148)(void);
    int (*tclGetAliasObj) (Tcl_Interp *interp, const char *childCmd, Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, int *objcPtr, Tcl_Obj ***objvPtr); /* 149 */
    void * (*tcl_GetAssocData) (Tcl_Interp *interp, const char *name, Tcl_InterpDeleteProc **procPtr); /* 150 */
    Tcl_Channel (*tcl_GetChannel) (Tcl_Interp *interp, const char *chanName, int *modePtr); /* 151 */
    int (*tcl_GetChannelBufferSize) (Tcl_Channel chan); /* 152 */
    Tcl_Size (*tcl_GetChannelBufferSize) (Tcl_Channel chan); /* 152 */
    int (*tcl_GetChannelHandle) (Tcl_Channel chan, int direction, void **handlePtr); /* 153 */
    void * (*tcl_GetChannelInstanceData) (Tcl_Channel chan); /* 154 */
    int (*tcl_GetChannelMode) (Tcl_Channel chan); /* 155 */
    const char * (*tcl_GetChannelName) (Tcl_Channel chan); /* 156 */
    int (*tcl_GetChannelOption) (Tcl_Interp *interp, Tcl_Channel chan, const char *optionName, Tcl_DString *dsPtr); /* 157 */
    const Tcl_ChannelType * (*tcl_GetChannelType) (Tcl_Channel chan); /* 158 */
    int (*tcl_GetCommandInfo) (Tcl_Interp *interp, const char *cmdName, Tcl_CmdInfo *infoPtr); /* 159 */
    const char * (*tcl_GetCommandName) (Tcl_Interp *interp, Tcl_Command command); /* 160 */
    int (*tcl_GetErrno) (void); /* 161 */
    const char * (*tcl_GetHostName) (void); /* 162 */
    int (*tcl_GetInterpPath) (Tcl_Interp *interp, Tcl_Interp *childInterp); /* 163 */
    Tcl_Interp * (*tcl_GetParent) (Tcl_Interp *interp); /* 164 */
    const char * (*tcl_GetNameOfExecutable) (void); /* 165 */
    Tcl_Obj * (*tcl_GetObjResult) (Tcl_Interp *interp); /* 166 */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
    int (*tcl_GetOpenFile) (Tcl_Interp *interp, const char *chanID, int forWriting, int checkUsage, void **filePtr); /* 167 */
#endif /* UNIX */
#if defined(_WIN32) /* WIN */
    void (*reserved167)(void);
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    int (*tcl_GetOpenFile) (Tcl_Interp *interp, const char *chanID, int forWriting, int checkUsage, void **filePtr); /* 167 */
#endif /* MACOSX */
    Tcl_PathType (*tcl_GetPathType) (const char *path); /* 168 */
    size_t (*tcl_Gets) (Tcl_Channel chan, Tcl_DString *dsPtr); /* 169 */
    size_t (*tcl_GetsObj) (Tcl_Channel chan, Tcl_Obj *objPtr); /* 170 */
    Tcl_Size (*tcl_Gets) (Tcl_Channel chan, Tcl_DString *dsPtr); /* 169 */
    Tcl_Size (*tcl_GetsObj) (Tcl_Channel chan, Tcl_Obj *objPtr); /* 170 */
    int (*tcl_GetServiceMode) (void); /* 171 */
    Tcl_Interp * (*tcl_GetChild) (Tcl_Interp *interp, const char *name); /* 172 */
    Tcl_Channel (*tcl_GetStdChannel) (int type); /* 173 */
    void (*reserved174)(void);
    void (*reserved175)(void);
    const char * (*tcl_GetVar2) (Tcl_Interp *interp, const char *part1, const char *part2, int flags); /* 176 */
    void (*reserved177)(void);
    void (*reserved178)(void);
    int (*tcl_HideCommand) (Tcl_Interp *interp, const char *cmdName, const char *hiddenCmdToken); /* 179 */
    int (*tcl_Init) (Tcl_Interp *interp); /* 180 */
    void (*tcl_InitHashTable) (Tcl_HashTable *tablePtr, int keyType); /* 181 */
    int (*tcl_InputBlocked) (Tcl_Channel chan); /* 182 */
    int (*tcl_InputBuffered) (Tcl_Channel chan); /* 183 */
    int (*tcl_InterpDeleted) (Tcl_Interp *interp); /* 184 */
    int (*tcl_IsSafe) (Tcl_Interp *interp); /* 185 */
    char * (*tcl_JoinPath) (int argc, const char *const *argv, Tcl_DString *resultPtr); /* 186 */
    char * (*tcl_JoinPath) (Tcl_Size argc, const char *const *argv, Tcl_DString *resultPtr); /* 186 */
    int (*tcl_LinkVar) (Tcl_Interp *interp, const char *varName, void *addr, int type); /* 187 */
    void (*reserved188)(void);
    Tcl_Channel (*tcl_MakeFileChannel) (void *handle, int mode); /* 189 */
    int (*tcl_MakeSafe) (Tcl_Interp *interp); /* 190 */
    void (*reserved190)(void);
    Tcl_Channel (*tcl_MakeTcpClientChannel) (void *tcpSocket); /* 191 */
    char * (*tcl_Merge) (int argc, const char *const *argv); /* 192 */
    char * (*tcl_Merge) (Tcl_Size argc, const char *const *argv); /* 192 */
    Tcl_HashEntry * (*tcl_NextHashEntry) (Tcl_HashSearch *searchPtr); /* 193 */
    void (*tcl_NotifyChannel) (Tcl_Channel channel, int mask); /* 194 */
    Tcl_Obj * (*tcl_ObjGetVar2) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags); /* 195 */
    Tcl_Obj * (*tcl_ObjSetVar2) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags); /* 196 */
    Tcl_Channel (*tcl_OpenCommandChannel) (Tcl_Interp *interp, int argc, const char **argv, int flags); /* 197 */
    Tcl_Channel (*tcl_OpenCommandChannel) (Tcl_Interp *interp, Tcl_Size argc, const char **argv, int flags); /* 197 */
    Tcl_Channel (*tcl_OpenFileChannel) (Tcl_Interp *interp, const char *fileName, const char *modeString, int permissions); /* 198 */
    Tcl_Channel (*tcl_OpenTcpClient) (Tcl_Interp *interp, int port, const char *address, const char *myaddr, int myport, int async); /* 199 */
    Tcl_Channel (*tcl_OpenTcpClient) (Tcl_Interp *interp, int port, const char *address, const char *myaddr, int myport, int flags); /* 199 */
    Tcl_Channel (*tcl_OpenTcpServer) (Tcl_Interp *interp, int port, const char *host, Tcl_TcpAcceptProc *acceptProc, void *callbackData); /* 200 */
    void (*tcl_Preserve) (void *data); /* 201 */
    void (*tcl_PrintDouble) (Tcl_Interp *interp, double value, char *dst); /* 202 */
    int (*tcl_PutEnv) (const char *assignment); /* 203 */
    const char * (*tcl_PosixError) (Tcl_Interp *interp); /* 204 */
    void (*tcl_QueueEvent) (Tcl_Event *evPtr, Tcl_QueuePosition position); /* 205 */
    size_t (*tcl_Read) (Tcl_Channel chan, char *bufPtr, size_t toRead); /* 206 */
    void (*tcl_QueueEvent) (Tcl_Event *evPtr, int position); /* 205 */
    Tcl_Size (*tcl_Read) (Tcl_Channel chan, char *bufPtr, Tcl_Size toRead); /* 206 */
    void (*tcl_ReapDetachedProcs) (void); /* 207 */
    int (*tcl_RecordAndEval) (Tcl_Interp *interp, const char *cmd, int flags); /* 208 */
    int (*tcl_RecordAndEvalObj) (Tcl_Interp *interp, Tcl_Obj *cmdPtr, int flags); /* 209 */
    void (*tcl_RegisterChannel) (Tcl_Interp *interp, Tcl_Channel chan); /* 210 */
    void (*tcl_RegisterObjType) (const Tcl_ObjType *typePtr); /* 211 */
    Tcl_RegExp (*tcl_RegExpCompile) (Tcl_Interp *interp, const char *pattern); /* 212 */
    int (*tcl_RegExpExec) (Tcl_Interp *interp, Tcl_RegExp regexp, const char *text, const char *start); /* 213 */
    int (*tcl_RegExpMatch) (Tcl_Interp *interp, const char *text, const char *pattern); /* 214 */
    void (*tcl_RegExpRange) (Tcl_RegExp regexp, size_t index, const char **startPtr, const char **endPtr); /* 215 */
    void (*tcl_RegExpRange) (Tcl_RegExp regexp, Tcl_Size index, const char **startPtr, const char **endPtr); /* 215 */
    void (*tcl_Release) (void *clientData); /* 216 */
    void (*tcl_ResetResult) (Tcl_Interp *interp); /* 217 */
    size_t (*tcl_ScanElement) (const char *src, int *flagPtr); /* 218 */
    size_t (*tcl_ScanCountedElement) (const char *src, size_t length, int *flagPtr); /* 219 */
    Tcl_Size (*tcl_ScanElement) (const char *src, int *flagPtr); /* 218 */
    Tcl_Size (*tcl_ScanCountedElement) (const char *src, Tcl_Size length, int *flagPtr); /* 219 */
    void (*reserved220)(void);
    int (*tcl_ServiceAll) (void); /* 221 */
    int (*tcl_ServiceEvent) (int flags); /* 222 */
    void (*tcl_SetAssocData) (Tcl_Interp *interp, const char *name, Tcl_InterpDeleteProc *proc, void *clientData); /* 223 */
    void (*tcl_SetChannelBufferSize) (Tcl_Channel chan, int sz); /* 224 */
    void (*tcl_SetChannelBufferSize) (Tcl_Channel chan, Tcl_Size sz); /* 224 */
    int (*tcl_SetChannelOption) (Tcl_Interp *interp, Tcl_Channel chan, const char *optionName, const char *newValue); /* 225 */
    int (*tcl_SetCommandInfo) (Tcl_Interp *interp, const char *cmdName, const Tcl_CmdInfo *infoPtr); /* 226 */
    void (*tcl_SetErrno) (int err); /* 227 */
    void (*tcl_SetErrorCode) (Tcl_Interp *interp, ...); /* 228 */
    void (*tcl_SetMaxBlockTime) (const Tcl_Time *timePtr); /* 229 */
    void (*reserved230)(void);
    int (*tcl_SetRecursionLimit) (Tcl_Interp *interp, int depth); /* 231 */
    Tcl_Size (*tcl_SetRecursionLimit) (Tcl_Interp *interp, Tcl_Size depth); /* 231 */
    void (*reserved232)(void);
    int (*tcl_SetServiceMode) (int mode); /* 233 */
    void (*tcl_SetObjErrorCode) (Tcl_Interp *interp, Tcl_Obj *errorObjPtr); /* 234 */
    void (*tcl_SetObjResult) (Tcl_Interp *interp, Tcl_Obj *resultObjPtr); /* 235 */
    void (*tcl_SetStdChannel) (Tcl_Channel channel, int type); /* 236 */
    void (*reserved237)(void);
    const char * (*tcl_SetVar2) (Tcl_Interp *interp, const char *part1, const char *part2, const char *newValue, int flags); /* 238 */
    const char * (*tcl_SignalId) (int sig); /* 239 */
    const char * (*tcl_SignalMsg) (int sig); /* 240 */
    void (*tcl_SourceRCFile) (Tcl_Interp *interp); /* 241 */
    int (*tcl_SplitList) (Tcl_Interp *interp, const char *listStr, int *argcPtr, const char ***argvPtr); /* 242 */
    void (*tcl_SplitPath) (const char *path, int *argcPtr, const char ***argvPtr); /* 243 */
    int (*tclSplitList) (Tcl_Interp *interp, const char *listStr, void *argcPtr, const char ***argvPtr); /* 242 */
    void (*tclSplitPath) (const char *path, void *argcPtr, const char ***argvPtr); /* 243 */
    void (*reserved244)(void);
    void (*reserved245)(void);
    void (*reserved246)(void);
    void (*reserved247)(void);
    int (*tcl_TraceVar2) (Tcl_Interp *interp, const char *part1, const char *part2, int flags, Tcl_VarTraceProc *proc, void *clientData); /* 248 */
    char * (*tcl_TranslateFileName) (Tcl_Interp *interp, const char *name, Tcl_DString *bufferPtr); /* 249 */
    size_t (*tcl_Ungets) (Tcl_Channel chan, const char *str, size_t len, int atHead); /* 250 */
    Tcl_Size (*tcl_Ungets) (Tcl_Channel chan, const char *str, Tcl_Size len, int atHead); /* 250 */
    void (*tcl_UnlinkVar) (Tcl_Interp *interp, const char *varName); /* 251 */
    int (*tcl_UnregisterChannel) (Tcl_Interp *interp, Tcl_Channel chan); /* 252 */
    void (*reserved253)(void);
    int (*tcl_UnsetVar2) (Tcl_Interp *interp, const char *part1, const char *part2, int flags); /* 254 */
    void (*reserved255)(void);
    void (*tcl_UntraceVar2) (Tcl_Interp *interp, const char *part1, const char *part2, int flags, Tcl_VarTraceProc *proc, void *clientData); /* 256 */
    void (*tcl_UpdateLinkedVar) (Tcl_Interp *interp, const char *varName); /* 257 */
    void (*reserved258)(void);
    int (*tcl_UpVar2) (Tcl_Interp *interp, const char *frameName, const char *part1, const char *part2, const char *localName, int flags); /* 259 */
    int (*tcl_VarEval) (Tcl_Interp *interp, ...); /* 260 */
    void (*reserved261)(void);
    void * (*tcl_VarTraceInfo2) (Tcl_Interp *interp, const char *part1, const char *part2, int flags, Tcl_VarTraceProc *procPtr, void *prevClientData); /* 262 */
    size_t (*tcl_Write) (Tcl_Channel chan, const char *s, size_t slen); /* 263 */
    void (*tcl_WrongNumArgs) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], const char *message); /* 264 */
    Tcl_Size (*tcl_Write) (Tcl_Channel chan, const char *s, Tcl_Size slen); /* 263 */
    void (*tcl_WrongNumArgs) (Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], const char *message); /* 264 */
    int (*tcl_DumpActiveMemory) (const char *fileName); /* 265 */
    void (*tcl_ValidateAllMemory) (const char *file, int line); /* 266 */
    void (*reserved267)(void);
    void (*reserved268)(void);
    char * (*tcl_HashStats) (Tcl_HashTable *tablePtr); /* 269 */
    const char * (*tcl_ParseVar) (Tcl_Interp *interp, const char *start, const char **termPtr); /* 270 */
    void (*reserved271)(void);
    const char * (*tcl_PkgPresentEx) (Tcl_Interp *interp, const char *name, const char *version, int exact, void *clientDataPtr); /* 272 */
    void (*reserved273)(void);
    void (*reserved274)(void);
    void (*reserved275)(void);
    void (*reserved276)(void);
    Tcl_Pid (*tcl_WaitPid) (Tcl_Pid pid, int *statPtr, int options); /* 277 */
    void (*reserved278)(void);
    void (*tcl_GetVersion) (int *major, int *minor, int *patchLevel, int *type); /* 279 */
    void (*tcl_InitMemory) (Tcl_Interp *interp); /* 280 */
    Tcl_Channel (*tcl_StackChannel) (Tcl_Interp *interp, const Tcl_ChannelType *typePtr, void *instanceData, int mask, Tcl_Channel prevChan); /* 281 */
    int (*tcl_UnstackChannel) (Tcl_Interp *interp, Tcl_Channel chan); /* 282 */
    Tcl_Channel (*tcl_GetStackedChannel) (Tcl_Channel chan); /* 283 */
    void (*tcl_SetMainLoop) (Tcl_MainLoopProc *proc); /* 284 */
    void (*reserved285)(void);
    int (*tcl_GetAliasObj) (Tcl_Interp *interp, const char *childCmd, Tcl_Interp **targetInterpPtr, const char **targetCmdPtr, Tcl_Size *objcPtr, Tcl_Obj ***objvPtr); /* 285 */
    void (*tcl_AppendObjToObj) (Tcl_Obj *objPtr, Tcl_Obj *appendObjPtr); /* 286 */
    Tcl_Encoding (*tcl_CreateEncoding) (const Tcl_EncodingType *typePtr); /* 287 */
    void (*tcl_CreateThreadExitHandler) (Tcl_ExitProc *proc, void *clientData); /* 288 */
    void (*tcl_DeleteThreadExitHandler) (Tcl_ExitProc *proc, void *clientData); /* 289 */
    void (*reserved290)(void);
    int (*tcl_EvalEx) (Tcl_Interp *interp, const char *script, size_t numBytes, int flags); /* 291 */
    int (*tcl_EvalObjv) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* 292 */
    int (*tcl_EvalEx) (Tcl_Interp *interp, const char *script, Tcl_Size numBytes, int flags); /* 291 */
    int (*tcl_EvalObjv) (Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], int flags); /* 292 */
    int (*tcl_EvalObjEx) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 293 */
    TCL_NORETURN1 void (*tcl_ExitThread) (int status); /* 294 */
    int (*tcl_ExternalToUtf) (Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, size_t srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, size_t dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); /* 295 */
    char * (*tcl_ExternalToUtfDString) (Tcl_Encoding encoding, const char *src, size_t srcLen, Tcl_DString *dsPtr); /* 296 */
    int (*tcl_ExternalToUtf) (Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, Tcl_Size srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, Tcl_Size dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); /* 295 */
    char * (*tcl_ExternalToUtfDString) (Tcl_Encoding encoding, const char *src, Tcl_Size srcLen, Tcl_DString *dsPtr); /* 296 */
    void (*tcl_FinalizeThread) (void); /* 297 */
    void (*tcl_FinalizeNotifier) (void *clientData); /* 298 */
    void (*tcl_FreeEncoding) (Tcl_Encoding encoding); /* 299 */
    Tcl_ThreadId (*tcl_GetCurrentThread) (void); /* 300 */
    Tcl_Encoding (*tcl_GetEncoding) (Tcl_Interp *interp, const char *name); /* 301 */
    const char * (*tcl_GetEncodingName) (Tcl_Encoding encoding); /* 302 */
    void (*tcl_GetEncodingNames) (Tcl_Interp *interp); /* 303 */
    int (*tcl_GetIndexFromObjStruct) (Tcl_Interp *interp, Tcl_Obj *objPtr, const void *tablePtr, size_t offset, const char *msg, int flags, int *indexPtr); /* 304 */
    void * (*tcl_GetThreadData) (Tcl_ThreadDataKey *keyPtr, size_t size); /* 305 */
    int (*tcl_GetIndexFromObjStruct) (Tcl_Interp *interp, Tcl_Obj *objPtr, const void *tablePtr, Tcl_Size offset, const char *msg, int flags, void *indexPtr); /* 304 */
    void * (*tcl_GetThreadData) (Tcl_ThreadDataKey *keyPtr, Tcl_Size size); /* 305 */
    Tcl_Obj * (*tcl_GetVar2Ex) (Tcl_Interp *interp, const char *part1, const char *part2, int flags); /* 306 */
    void * (*tcl_InitNotifier) (void); /* 307 */
    void (*tcl_MutexLock) (Tcl_Mutex *mutexPtr); /* 308 */
    void (*tcl_MutexUnlock) (Tcl_Mutex *mutexPtr); /* 309 */
    void (*tcl_ConditionNotify) (Tcl_Condition *condPtr); /* 310 */
    void (*tcl_ConditionWait) (Tcl_Condition *condPtr, Tcl_Mutex *mutexPtr, const Tcl_Time *timePtr); /* 311 */
    size_t (*tcl_NumUtfChars) (const char *src, size_t length); /* 312 */
    size_t (*tcl_ReadChars) (Tcl_Channel channel, Tcl_Obj *objPtr, size_t charsToRead, int appendFlag); /* 313 */
    Tcl_Size (*tclNumUtfChars) (const char *src, Tcl_Size length); /* 312 */
    Tcl_Size (*tcl_ReadChars) (Tcl_Channel channel, Tcl_Obj *objPtr, Tcl_Size charsToRead, int appendFlag); /* 313 */
    void (*reserved314)(void);
    void (*reserved315)(void);
    int (*tcl_SetSystemEncoding) (Tcl_Interp *interp, const char *name); /* 316 */
    Tcl_Obj * (*tcl_SetVar2Ex) (Tcl_Interp *interp, const char *part1, const char *part2, Tcl_Obj *newValuePtr, int flags); /* 317 */
    void (*tcl_ThreadAlert) (Tcl_ThreadId threadId); /* 318 */
    void (*tcl_ThreadQueueEvent) (Tcl_ThreadId threadId, Tcl_Event *evPtr, Tcl_QueuePosition position); /* 319 */
    int (*tcl_UniCharAtIndex) (const char *src, size_t index); /* 320 */
    void (*tcl_ThreadQueueEvent) (Tcl_ThreadId threadId, Tcl_Event *evPtr, int position); /* 319 */
    int (*tcl_UniCharAtIndex) (const char *src, Tcl_Size index); /* 320 */
    int (*tcl_UniCharToLower) (int ch); /* 321 */
    int (*tcl_UniCharToTitle) (int ch); /* 322 */
    int (*tcl_UniCharToUpper) (int ch); /* 323 */
    int (*tcl_UniCharToUtf) (int ch, char *buf); /* 324 */
    const char * (*tcl_UtfAtIndex) (const char *src, size_t index); /* 325 */
    int (*tcl_UtfCharComplete) (const char *src, size_t length); /* 326 */
    size_t (*tcl_UtfBackslash) (const char *src, int *readPtr, char *dst); /* 327 */
    Tcl_Size (*tcl_UniCharToUtf) (int ch, char *buf); /* 324 */
    const char * (*tclUtfAtIndex) (const char *src, Tcl_Size index); /* 325 */
    int (*tclUtfCharComplete) (const char *src, Tcl_Size length); /* 326 */
    Tcl_Size (*tcl_UtfBackslash) (const char *src, int *readPtr, char *dst); /* 327 */
    const char * (*tcl_UtfFindFirst) (const char *src, int ch); /* 328 */
    const char * (*tcl_UtfFindLast) (const char *src, int ch); /* 329 */
    const char * (*tcl_UtfNext) (const char *src); /* 330 */
    const char * (*tcl_UtfPrev) (const char *src, const char *start); /* 331 */
    int (*tcl_UtfToExternal) (Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, size_t srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, size_t dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); /* 332 */
    char * (*tcl_UtfToExternalDString) (Tcl_Encoding encoding, const char *src, size_t srcLen, Tcl_DString *dsPtr); /* 333 */
    int (*tcl_UtfToLower) (char *src); /* 334 */
    int (*tcl_UtfToTitle) (char *src); /* 335 */
    int (*tcl_UtfToChar16) (const char *src, unsigned short *chPtr); /* 336 */
    int (*tcl_UtfToUpper) (char *src); /* 337 */
    size_t (*tcl_WriteChars) (Tcl_Channel chan, const char *src, size_t srcLen); /* 338 */
    size_t (*tcl_WriteObj) (Tcl_Channel chan, Tcl_Obj *objPtr); /* 339 */
    const char * (*tclUtfNext) (const char *src); /* 330 */
    const char * (*tclUtfPrev) (const char *src, const char *start); /* 331 */
    int (*tcl_UtfToExternal) (Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, Tcl_Size srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, Tcl_Size dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); /* 332 */
    char * (*tcl_UtfToExternalDString) (Tcl_Encoding encoding, const char *src, Tcl_Size srcLen, Tcl_DString *dsPtr); /* 333 */
    Tcl_Size (*tcl_UtfToLower) (char *src); /* 334 */
    Tcl_Size (*tcl_UtfToTitle) (char *src); /* 335 */
    Tcl_Size (*tcl_UtfToChar16) (const char *src, unsigned short *chPtr); /* 336 */
    Tcl_Size (*tcl_UtfToUpper) (char *src); /* 337 */
    Tcl_Size (*tcl_WriteChars) (Tcl_Channel chan, const char *src, Tcl_Size srcLen); /* 338 */
    Tcl_Size (*tcl_WriteObj) (Tcl_Channel chan, Tcl_Obj *objPtr); /* 339 */
    char * (*tcl_GetString) (Tcl_Obj *objPtr); /* 340 */
    void (*reserved341)(void);
    void (*reserved342)(void);
    void (*tcl_AlertNotifier) (void *clientData); /* 343 */
    void (*tcl_ServiceModeHook) (int mode); /* 344 */
    int (*tcl_UniCharIsAlnum) (int ch); /* 345 */
    int (*tcl_UniCharIsAlpha) (int ch); /* 346 */
    int (*tcl_UniCharIsDigit) (int ch); /* 347 */
    int (*tcl_UniCharIsLower) (int ch); /* 348 */
    int (*tcl_UniCharIsSpace) (int ch); /* 349 */
    int (*tcl_UniCharIsUpper) (int ch); /* 350 */
    int (*tcl_UniCharIsWordChar) (int ch); /* 351 */
    void (*reserved352)(void);
    Tcl_Size (*tcl_Char16Len) (const unsigned short *uniStr); /* 352 */
    void (*reserved353)(void);
    char * (*tcl_Char16ToUtfDString) (const unsigned short *uniStr, size_t uniLength, Tcl_DString *dsPtr); /* 354 */
    unsigned short * (*tcl_UtfToChar16DString) (const char *src, size_t length, Tcl_DString *dsPtr); /* 355 */
    char * (*tcl_Char16ToUtfDString) (const unsigned short *uniStr, Tcl_Size uniLength, Tcl_DString *dsPtr); /* 354 */
    unsigned short * (*tcl_UtfToChar16DString) (const char *src, Tcl_Size length, Tcl_DString *dsPtr); /* 355 */
    Tcl_RegExp (*tcl_GetRegExpFromObj) (Tcl_Interp *interp, Tcl_Obj *patObj, int flags); /* 356 */
    void (*reserved357)(void);
    void (*tcl_FreeParse) (Tcl_Parse *parsePtr); /* 358 */
    void (*tcl_LogCommandInfo) (Tcl_Interp *interp, const char *script, const char *command, size_t length); /* 359 */
    int (*tcl_ParseBraces) (Tcl_Interp *interp, const char *start, size_t numBytes, Tcl_Parse *parsePtr, int append, const char **termPtr); /* 360 */
    int (*tcl_ParseCommand) (Tcl_Interp *interp, const char *start, size_t numBytes, int nested, Tcl_Parse *parsePtr); /* 361 */
    int (*tcl_ParseExpr) (Tcl_Interp *interp, const char *start, size_t numBytes, Tcl_Parse *parsePtr); /* 362 */
    int (*tcl_ParseQuotedString) (Tcl_Interp *interp, const char *start, size_t numBytes, Tcl_Parse *parsePtr, int append, const char **termPtr); /* 363 */
    int (*tcl_ParseVarName) (Tcl_Interp *interp, const char *start, size_t numBytes, Tcl_Parse *parsePtr, int append); /* 364 */
    void (*tcl_LogCommandInfo) (Tcl_Interp *interp, const char *script, const char *command, Tcl_Size length); /* 359 */
    int (*tcl_ParseBraces) (Tcl_Interp *interp, const char *start, Tcl_Size numBytes, Tcl_Parse *parsePtr, int append, const char **termPtr); /* 360 */
    int (*tcl_ParseCommand) (Tcl_Interp *interp, const char *start, Tcl_Size numBytes, int nested, Tcl_Parse *parsePtr); /* 361 */
    int (*tcl_ParseExpr) (Tcl_Interp *interp, const char *start, Tcl_Size numBytes, Tcl_Parse *parsePtr); /* 362 */
    int (*tcl_ParseQuotedString) (Tcl_Interp *interp, const char *start, Tcl_Size numBytes, Tcl_Parse *parsePtr, int append, const char **termPtr); /* 363 */
    int (*tcl_ParseVarName) (Tcl_Interp *interp, const char *start, Tcl_Size numBytes, Tcl_Parse *parsePtr, int append); /* 364 */
    char * (*tcl_GetCwd) (Tcl_Interp *interp, Tcl_DString *cwdPtr); /* 365 */
    int (*tcl_Chdir) (const char *dirName); /* 366 */
    int (*tcl_Access) (const char *path, int mode); /* 367 */
    int (*tcl_Stat) (const char *path, struct stat *bufPtr); /* 368 */
    int (*tcl_UtfNcmp) (const char *s1, const char *s2, size_t n); /* 369 */
    int (*tcl_UtfNcasecmp) (const char *s1, const char *s2, size_t n); /* 370 */
    int (*tclUtfNcmp) (const char *s1, const char *s2, size_t n); /* 369 */
    int (*tclUtfNcasecmp) (const char *s1, const char *s2, size_t n); /* 370 */
    int (*tcl_StringCaseMatch) (const char *str, const char *pattern, int nocase); /* 371 */
    int (*tcl_UniCharIsControl) (int ch); /* 372 */
    int (*tcl_UniCharIsGraph) (int ch); /* 373 */
    int (*tcl_UniCharIsPrint) (int ch); /* 374 */
    int (*tcl_UniCharIsPunct) (int ch); /* 375 */
    int (*tcl_RegExpExecObj) (Tcl_Interp *interp, Tcl_RegExp regexp, Tcl_Obj *textObj, size_t offset, size_t nmatches, int flags); /* 376 */
    int (*tcl_RegExpExecObj) (Tcl_Interp *interp, Tcl_RegExp regexp, Tcl_Obj *textObj, Tcl_Size offset, Tcl_Size nmatches, int flags); /* 376 */
    void (*tcl_RegExpGetInfo) (Tcl_RegExp regexp, Tcl_RegExpInfo *infoPtr); /* 377 */
    Tcl_Obj * (*tcl_NewUnicodeObj) (const Tcl_UniChar *unicode, size_t numChars); /* 378 */
    void (*tcl_SetUnicodeObj) (Tcl_Obj *objPtr, const Tcl_UniChar *unicode, size_t numChars); /* 379 */
    size_t (*tcl_GetCharLength) (Tcl_Obj *objPtr); /* 380 */
    int (*tcl_GetUniChar) (Tcl_Obj *objPtr, size_t index); /* 381 */
    Tcl_Obj * (*tcl_NewUnicodeObj) (const Tcl_UniChar *unicode, Tcl_Size numChars); /* 378 */
    void (*tcl_SetUnicodeObj) (Tcl_Obj *objPtr, const Tcl_UniChar *unicode, Tcl_Size numChars); /* 379 */
    Tcl_Size (*tclGetCharLength) (Tcl_Obj *objPtr); /* 380 */
    int (*tclGetUniChar) (Tcl_Obj *objPtr, Tcl_Size index); /* 381 */
    void (*reserved382)(void);
    Tcl_Obj * (*tcl_GetRange) (Tcl_Obj *objPtr, size_t first, size_t last); /* 383 */
    void (*reserved384)(void);
    Tcl_Obj * (*tclGetRange) (Tcl_Obj *objPtr, Tcl_Size first, Tcl_Size last); /* 383 */
    void (*tcl_AppendUnicodeToObj) (Tcl_Obj *objPtr, const Tcl_UniChar *unicode, Tcl_Size length); /* 384 */
    int (*tcl_RegExpMatchObj) (Tcl_Interp *interp, Tcl_Obj *textObj, Tcl_Obj *patternObj); /* 385 */
    void (*tcl_SetNotifier) (Tcl_NotifierProcs *notifierProcPtr); /* 386 */
    void (*tcl_SetNotifier) (const Tcl_NotifierProcs *notifierProcPtr); /* 386 */
    Tcl_Mutex * (*tcl_GetAllocMutex) (void); /* 387 */
    int (*tcl_GetChannelNames) (Tcl_Interp *interp); /* 388 */
    int (*tcl_GetChannelNamesEx) (Tcl_Interp *interp, const char *pattern); /* 389 */
    int (*tcl_ProcObjCmd) (void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 390 */
    int (*tcl_ProcObjCmd) (void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); /* 390 */
    void (*tcl_ConditionFinalize) (Tcl_Condition *condPtr); /* 391 */
    void (*tcl_MutexFinalize) (Tcl_Mutex *mutex); /* 392 */
    int (*tcl_CreateThread) (Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc, void *clientData, size_t stackSize, int flags); /* 393 */
    size_t (*tcl_ReadRaw) (Tcl_Channel chan, char *dst, size_t bytesToRead); /* 394 */
    size_t (*tcl_WriteRaw) (Tcl_Channel chan, const char *src, size_t srcLen); /* 395 */
    int (*tcl_CreateThread) (Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc, void *clientData, TCL_HASH_TYPE stackSize, int flags); /* 393 */
    Tcl_Size (*tcl_ReadRaw) (Tcl_Channel chan, char *dst, Tcl_Size bytesToRead); /* 394 */
    Tcl_Size (*tcl_WriteRaw) (Tcl_Channel chan, const char *src, Tcl_Size srcLen); /* 395 */
    Tcl_Channel (*tcl_GetTopChannel) (Tcl_Channel chan); /* 396 */
    int (*tcl_ChannelBuffered) (Tcl_Channel chan); /* 397 */
    const char * (*tcl_ChannelName) (const Tcl_ChannelType *chanTypePtr); /* 398 */
    Tcl_ChannelTypeVersion (*tcl_ChannelVersion) (const Tcl_ChannelType *chanTypePtr); /* 399 */
    Tcl_DriverBlockModeProc * (*tcl_ChannelBlockModeProc) (const Tcl_ChannelType *chanTypePtr); /* 400 */
    void (*reserved401)(void);
    Tcl_DriverClose2Proc * (*tcl_ChannelClose2Proc) (const Tcl_ChannelType *chanTypePtr); /* 402 */
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

2273
2274
2275
2276
2277
2278
2279
2280
2281


2282
2283
2284
2285
2286

2287
2288
2289
2290
2291


2292
2293
2294
2295
2296
2297
2298
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


2390
2391
2392
2393
2394
2395
2396
2397
2398







-
-
-
-
-
+
+
+
+
+

-
+









-
+















-
-
+
+


-
+
















-
+

-
+







-
-
+
+




-
+



-
-
+
+







    void (*reserved421)(void);
    void (*reserved422)(void);
    void (*tcl_InitCustomHashTable) (Tcl_HashTable *tablePtr, int keyType, const Tcl_HashKeyType *typePtr); /* 423 */
    void (*tcl_InitObjHashTable) (Tcl_HashTable *tablePtr); /* 424 */
    void * (*tcl_CommandTraceInfo) (Tcl_Interp *interp, const char *varName, int flags, Tcl_CommandTraceProc *procPtr, void *prevClientData); /* 425 */
    int (*tcl_TraceCommand) (Tcl_Interp *interp, const char *varName, int flags, Tcl_CommandTraceProc *proc, void *clientData); /* 426 */
    void (*tcl_UntraceCommand) (Tcl_Interp *interp, const char *varName, int flags, Tcl_CommandTraceProc *proc, void *clientData); /* 427 */
    void * (*tcl_AttemptAlloc) (size_t size); /* 428 */
    void * (*tcl_AttemptDbCkalloc) (size_t size, const char *file, int line); /* 429 */
    void * (*tcl_AttemptRealloc) (void *ptr, size_t size); /* 430 */
    void * (*tcl_AttemptDbCkrealloc) (void *ptr, size_t size, const char *file, int line); /* 431 */
    int (*tcl_AttemptSetObjLength) (Tcl_Obj *objPtr, size_t length); /* 432 */
    void * (*tcl_AttemptAlloc) (TCL_HASH_TYPE size); /* 428 */
    void * (*tcl_AttemptDbCkalloc) (TCL_HASH_TYPE size, const char *file, int line); /* 429 */
    void * (*tcl_AttemptRealloc) (void *ptr, TCL_HASH_TYPE size); /* 430 */
    void * (*tcl_AttemptDbCkrealloc) (void *ptr, TCL_HASH_TYPE size, const char *file, int line); /* 431 */
    int (*tcl_AttemptSetObjLength) (Tcl_Obj *objPtr, Tcl_Size length); /* 432 */
    Tcl_ThreadId (*tcl_GetChannelThread) (Tcl_Channel channel); /* 433 */
    Tcl_UniChar * (*tcl_GetUnicodeFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 434 */
    Tcl_UniChar * (*tclGetUnicodeFromObj) (Tcl_Obj *objPtr, void *lengthPtr); /* 434 */
    void (*reserved435)(void);
    void (*reserved436)(void);
    Tcl_Obj * (*tcl_SubstObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 437 */
    int (*tcl_DetachChannel) (Tcl_Interp *interp, Tcl_Channel channel); /* 438 */
    int (*tcl_IsStandardChannel) (Tcl_Channel channel); /* 439 */
    int (*tcl_FSCopyFile) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr); /* 440 */
    int (*tcl_FSCopyDirectory) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr, Tcl_Obj **errorPtr); /* 441 */
    int (*tcl_FSCreateDirectory) (Tcl_Obj *pathPtr); /* 442 */
    int (*tcl_FSDeleteFile) (Tcl_Obj *pathPtr); /* 443 */
    int (*tcl_FSLoadFile) (Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *sym1, const char *sym2, Tcl_PackageInitProc **proc1Ptr, Tcl_PackageInitProc **proc2Ptr, Tcl_LoadHandle *handlePtr, Tcl_FSUnloadFileProc **unloadProcPtr); /* 444 */
    int (*tcl_FSLoadFile) (Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *sym1, const char *sym2, Tcl_LibraryInitProc **proc1Ptr, Tcl_LibraryInitProc **proc2Ptr, Tcl_LoadHandle *handlePtr, Tcl_FSUnloadFileProc **unloadProcPtr); /* 444 */
    int (*tcl_FSMatchInDirectory) (Tcl_Interp *interp, Tcl_Obj *result, Tcl_Obj *pathPtr, const char *pattern, Tcl_GlobTypeData *types); /* 445 */
    Tcl_Obj * (*tcl_FSLink) (Tcl_Obj *pathPtr, Tcl_Obj *toPtr, int linkAction); /* 446 */
    int (*tcl_FSRemoveDirectory) (Tcl_Obj *pathPtr, int recursive, Tcl_Obj **errorPtr); /* 447 */
    int (*tcl_FSRenameFile) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr); /* 448 */
    int (*tcl_FSLstat) (Tcl_Obj *pathPtr, Tcl_StatBuf *buf); /* 449 */
    int (*tcl_FSUtime) (Tcl_Obj *pathPtr, struct utimbuf *tval); /* 450 */
    int (*tcl_FSFileAttrsGet) (Tcl_Interp *interp, int index, Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef); /* 451 */
    int (*tcl_FSFileAttrsSet) (Tcl_Interp *interp, int index, Tcl_Obj *pathPtr, Tcl_Obj *objPtr); /* 452 */
    const char *const * (*tcl_FSFileAttrStrings) (Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef); /* 453 */
    int (*tcl_FSStat) (Tcl_Obj *pathPtr, Tcl_StatBuf *buf); /* 454 */
    int (*tcl_FSAccess) (Tcl_Obj *pathPtr, int mode); /* 455 */
    Tcl_Channel (*tcl_FSOpenFileChannel) (Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *modeString, int permissions); /* 456 */
    Tcl_Obj * (*tcl_FSGetCwd) (Tcl_Interp *interp); /* 457 */
    int (*tcl_FSChdir) (Tcl_Obj *pathPtr); /* 458 */
    int (*tcl_FSConvertToPathType) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 459 */
    Tcl_Obj * (*tcl_FSJoinPath) (Tcl_Obj *listObj, int elements); /* 460 */
    Tcl_Obj * (*tcl_FSSplitPath) (Tcl_Obj *pathPtr, int *lenPtr); /* 461 */
    Tcl_Obj * (*tcl_FSJoinPath) (Tcl_Obj *listObj, Tcl_Size elements); /* 460 */
    Tcl_Obj * (*tclFSSplitPath) (Tcl_Obj *pathPtr, void *lenPtr); /* 461 */
    int (*tcl_FSEqualPaths) (Tcl_Obj *firstPtr, Tcl_Obj *secondPtr); /* 462 */
    Tcl_Obj * (*tcl_FSGetNormalizedPath) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 463 */
    Tcl_Obj * (*tcl_FSJoinToPath) (Tcl_Obj *pathPtr, int objc, Tcl_Obj *const objv[]); /* 464 */
    Tcl_Obj * (*tcl_FSJoinToPath) (Tcl_Obj *pathPtr, Tcl_Size objc, Tcl_Obj *const objv[]); /* 464 */
    void * (*tcl_FSGetInternalRep) (Tcl_Obj *pathPtr, const Tcl_Filesystem *fsPtr); /* 465 */
    Tcl_Obj * (*tcl_FSGetTranslatedPath) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 466 */
    int (*tcl_FSEvalFile) (Tcl_Interp *interp, Tcl_Obj *fileName); /* 467 */
    Tcl_Obj * (*tcl_FSNewNativePath) (const Tcl_Filesystem *fromFilesystem, void *clientData); /* 468 */
    const void * (*tcl_FSGetNativePath) (Tcl_Obj *pathPtr); /* 469 */
    Tcl_Obj * (*tcl_FSFileSystemInfo) (Tcl_Obj *pathPtr); /* 470 */
    Tcl_Obj * (*tcl_FSPathSeparator) (Tcl_Obj *pathPtr); /* 471 */
    Tcl_Obj * (*tcl_FSListVolumes) (void); /* 472 */
    int (*tcl_FSRegister) (void *clientData, const Tcl_Filesystem *fsPtr); /* 473 */
    int (*tcl_FSUnregister) (const Tcl_Filesystem *fsPtr); /* 474 */
    void * (*tcl_FSData) (const Tcl_Filesystem *fsPtr); /* 475 */
    const char * (*tcl_FSGetTranslatedStringPath) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 476 */
    const Tcl_Filesystem * (*tcl_FSGetFileSystemForPath) (Tcl_Obj *pathPtr); /* 477 */
    Tcl_PathType (*tcl_FSGetPathType) (Tcl_Obj *pathPtr); /* 478 */
    int (*tcl_OutputBuffered) (Tcl_Channel chan); /* 479 */
    void (*tcl_FSMountsChanged) (const Tcl_Filesystem *fsPtr); /* 480 */
    int (*tcl_EvalTokensStandard) (Tcl_Interp *interp, Tcl_Token *tokenPtr, size_t count); /* 481 */
    int (*tcl_EvalTokensStandard) (Tcl_Interp *interp, Tcl_Token *tokenPtr, Tcl_Size count); /* 481 */
    void (*tcl_GetTime) (Tcl_Time *timeBuf); /* 482 */
    Tcl_Trace (*tcl_CreateObjTrace) (Tcl_Interp *interp, int level, int flags, Tcl_CmdObjTraceProc *objProc, void *clientData, Tcl_CmdObjTraceDeleteProc *delProc); /* 483 */
    Tcl_Trace (*tcl_CreateObjTrace) (Tcl_Interp *interp, Tcl_Size level, int flags, Tcl_CmdObjTraceProc *objProc, void *clientData, Tcl_CmdObjTraceDeleteProc *delProc); /* 483 */
    int (*tcl_GetCommandInfoFromToken) (Tcl_Command token, Tcl_CmdInfo *infoPtr); /* 484 */
    int (*tcl_SetCommandInfoFromToken) (Tcl_Command token, const Tcl_CmdInfo *infoPtr); /* 485 */
    Tcl_Obj * (*tcl_DbNewWideIntObj) (Tcl_WideInt wideValue, const char *file, int line); /* 486 */
    int (*tcl_GetWideIntFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_WideInt *widePtr); /* 487 */
    Tcl_Obj * (*tcl_NewWideIntObj) (Tcl_WideInt wideValue); /* 488 */
    void (*tcl_SetWideIntObj) (Tcl_Obj *objPtr, Tcl_WideInt wideValue); /* 489 */
    Tcl_StatBuf * (*tcl_AllocStatBuf) (void); /* 490 */
    Tcl_WideInt (*tcl_Seek) (Tcl_Channel chan, Tcl_WideInt offset, int mode); /* 491 */
    Tcl_WideInt (*tcl_Tell) (Tcl_Channel chan); /* 492 */
    long long (*tcl_Seek) (Tcl_Channel chan, long long offset, int mode); /* 491 */
    long long (*tcl_Tell) (Tcl_Channel chan); /* 492 */
    Tcl_DriverWideSeekProc * (*tcl_ChannelWideSeekProc) (const Tcl_ChannelType *chanTypePtr); /* 493 */
    int (*tcl_DictObjPut) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr, Tcl_Obj *valuePtr); /* 494 */
    int (*tcl_DictObjGet) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr, Tcl_Obj **valuePtrPtr); /* 495 */
    int (*tcl_DictObjRemove) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr); /* 496 */
    int (*tcl_DictObjSize) (Tcl_Interp *interp, Tcl_Obj *dictPtr, int *sizePtr); /* 497 */
    int (*tclDictObjSize) (Tcl_Interp *interp, Tcl_Obj *dictPtr, void *sizePtr); /* 497 */
    int (*tcl_DictObjFirst) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_DictSearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr); /* 498 */
    void (*tcl_DictObjNext) (Tcl_DictSearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr); /* 499 */
    void (*tcl_DictObjDone) (Tcl_DictSearch *searchPtr); /* 500 */
    int (*tcl_DictObjPutKeyList) (Tcl_Interp *interp, Tcl_Obj *dictPtr, int keyc, Tcl_Obj *const *keyv, Tcl_Obj *valuePtr); /* 501 */
    int (*tcl_DictObjRemoveKeyList) (Tcl_Interp *interp, Tcl_Obj *dictPtr, int keyc, Tcl_Obj *const *keyv); /* 502 */
    int (*tcl_DictObjPutKeyList) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Size keyc, Tcl_Obj *const *keyv, Tcl_Obj *valuePtr); /* 501 */
    int (*tcl_DictObjRemoveKeyList) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Size keyc, Tcl_Obj *const *keyv); /* 502 */
    Tcl_Obj * (*tcl_NewDictObj) (void); /* 503 */
    Tcl_Obj * (*tcl_DbNewDictObj) (const char *file, int line); /* 504 */
    void (*tcl_RegisterConfig) (Tcl_Interp *interp, const char *pkgName, const Tcl_Config *configuration, const char *valEncoding); /* 505 */
    Tcl_Namespace * (*tcl_CreateNamespace) (Tcl_Interp *interp, const char *name, void *clientData, Tcl_NamespaceDeleteProc *deleteProc); /* 506 */
    void (*tcl_DeleteNamespace) (Tcl_Namespace *nsPtr); /* 507 */
    int (*tcl_AppendExportList) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, Tcl_Obj *objPtr); /* 508 */
    int (*tcl_Export) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, const char *pattern, int resetListFirst); /* 509 */
2307
2308
2309
2310
2311
2312
2313
2314

2315
2316
2317
2318
2319
2320
2321
2407
2408
2409
2410
2411
2412
2413

2414
2415
2416
2417
2418
2419
2420
2421







-
+







    int (*tcl_FSEvalFileEx) (Tcl_Interp *interp, Tcl_Obj *fileName, const char *encodingName); /* 518 */
    void (*reserved519)(void);
    void (*tcl_LimitAddHandler) (Tcl_Interp *interp, int type, Tcl_LimitHandlerProc *handlerProc, void *clientData, Tcl_LimitHandlerDeleteProc *deleteProc); /* 520 */
    void (*tcl_LimitRemoveHandler) (Tcl_Interp *interp, int type, Tcl_LimitHandlerProc *handlerProc, void *clientData); /* 521 */
    int (*tcl_LimitReady) (Tcl_Interp *interp); /* 522 */
    int (*tcl_LimitCheck) (Tcl_Interp *interp); /* 523 */
    int (*tcl_LimitExceeded) (Tcl_Interp *interp); /* 524 */
    void (*tcl_LimitSetCommands) (Tcl_Interp *interp, int commandLimit); /* 525 */
    void (*tcl_LimitSetCommands) (Tcl_Interp *interp, Tcl_Size commandLimit); /* 525 */
    void (*tcl_LimitSetTime) (Tcl_Interp *interp, Tcl_Time *timeLimitPtr); /* 526 */
    void (*tcl_LimitSetGranularity) (Tcl_Interp *interp, int type, int granularity); /* 527 */
    int (*tcl_LimitTypeEnabled) (Tcl_Interp *interp, int type); /* 528 */
    int (*tcl_LimitTypeExceeded) (Tcl_Interp *interp, int type); /* 529 */
    void (*tcl_LimitTypeSet) (Tcl_Interp *interp, int type); /* 530 */
    void (*tcl_LimitTypeReset) (Tcl_Interp *interp, int type); /* 531 */
    int (*tcl_LimitGetCommands) (Tcl_Interp *interp); /* 532 */
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
2399
2400
2401
2402



2403
2404
2405
2406
2407
2408

2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421


2422
2423
2424
2425
2426
2427
2428





2429
2430
2431
2432
2433
2434
2435
2436
2437















































2438
2439
2440
2441
2442
2443
2444
2442
2443
2444
2445
2446
2447
2448

2449
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
2489
2490
2491
2492

2493
2494
2495
2496
2497
2498
2499



2500
2501
2502
2503
2504
2505
2506
2507

2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519


2520
2521
2522
2523





2524
2525
2526
2527
2528
2529
2530
2531
2532





2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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







-
+












-
+

-
-
-
+
+
+







-
-
+
+

-
+







-
-
-
-
-
+
+
+
+
+



-
+






-
-
-
+
+
+





-
+











-
-
+
+


-
-
-
-
-
+
+
+
+
+




-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    void (*tcl_QueryTimeProc) (Tcl_GetTimeProc **getProc, Tcl_ScaleTimeProc **scaleProc, void **clientData); /* 553 */
    Tcl_DriverThreadActionProc * (*tcl_ChannelThreadActionProc) (const Tcl_ChannelType *chanTypePtr); /* 554 */
    Tcl_Obj * (*tcl_NewBignumObj) (void *value); /* 555 */
    Tcl_Obj * (*tcl_DbNewBignumObj) (void *value, const char *file, int line); /* 556 */
    void (*tcl_SetBignumObj) (Tcl_Obj *obj, void *value); /* 557 */
    int (*tcl_GetBignumFromObj) (Tcl_Interp *interp, Tcl_Obj *obj, void *value); /* 558 */
    int (*tcl_TakeBignumFromObj) (Tcl_Interp *interp, Tcl_Obj *obj, void *value); /* 559 */
    int (*tcl_TruncateChannel) (Tcl_Channel chan, Tcl_WideInt length); /* 560 */
    int (*tcl_TruncateChannel) (Tcl_Channel chan, long long length); /* 560 */
    Tcl_DriverTruncateProc * (*tcl_ChannelTruncateProc) (const Tcl_ChannelType *chanTypePtr); /* 561 */
    void (*tcl_SetChannelErrorInterp) (Tcl_Interp *interp, Tcl_Obj *msg); /* 562 */
    void (*tcl_GetChannelErrorInterp) (Tcl_Interp *interp, Tcl_Obj **msg); /* 563 */
    void (*tcl_SetChannelError) (Tcl_Channel chan, Tcl_Obj *msg); /* 564 */
    void (*tcl_GetChannelError) (Tcl_Channel chan, Tcl_Obj **msg); /* 565 */
    int (*tcl_InitBignumFromDouble) (Tcl_Interp *interp, double initval, void *toInit); /* 566 */
    Tcl_Obj * (*tcl_GetNamespaceUnknownHandler) (Tcl_Interp *interp, Tcl_Namespace *nsPtr); /* 567 */
    int (*tcl_SetNamespaceUnknownHandler) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, Tcl_Obj *handlerPtr); /* 568 */
    int (*tcl_GetEncodingFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Encoding *encodingPtr); /* 569 */
    Tcl_Obj * (*tcl_GetEncodingSearchPath) (void); /* 570 */
    int (*tcl_SetEncodingSearchPath) (Tcl_Obj *searchPath); /* 571 */
    const char * (*tcl_GetEncodingNameFromEnvironment) (Tcl_DString *bufPtr); /* 572 */
    int (*tcl_PkgRequireProc) (Tcl_Interp *interp, const char *name, int objc, Tcl_Obj *const objv[], void *clientDataPtr); /* 573 */
    int (*tcl_PkgRequireProc) (Tcl_Interp *interp, const char *name, Tcl_Size objc, Tcl_Obj *const objv[], void *clientDataPtr); /* 573 */
    void (*tcl_AppendObjToErrorInfo) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 574 */
    void (*tcl_AppendLimitedToObj) (Tcl_Obj *objPtr, const char *bytes, size_t length, size_t limit, const char *ellipsis); /* 575 */
    Tcl_Obj * (*tcl_Format) (Tcl_Interp *interp, const char *format, int objc, Tcl_Obj *const objv[]); /* 576 */
    int (*tcl_AppendFormatToObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, const char *format, int objc, Tcl_Obj *const objv[]); /* 577 */
    void (*tcl_AppendLimitedToObj) (Tcl_Obj *objPtr, const char *bytes, Tcl_Size length, Tcl_Size limit, const char *ellipsis); /* 575 */
    Tcl_Obj * (*tcl_Format) (Tcl_Interp *interp, const char *format, Tcl_Size objc, Tcl_Obj *const objv[]); /* 576 */
    int (*tcl_AppendFormatToObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, const char *format, Tcl_Size objc, Tcl_Obj *const objv[]); /* 577 */
    Tcl_Obj * (*tcl_ObjPrintf) (const char *format, ...) TCL_FORMAT_PRINTF(1, 2); /* 578 */
    void (*tcl_AppendPrintfToObj) (Tcl_Obj *objPtr, const char *format, ...) TCL_FORMAT_PRINTF(2, 3); /* 579 */
    int (*tcl_CancelEval) (Tcl_Interp *interp, Tcl_Obj *resultObjPtr, void *clientData, int flags); /* 580 */
    int (*tcl_Canceled) (Tcl_Interp *interp, int flags); /* 581 */
    int (*tcl_CreatePipe) (Tcl_Interp *interp, Tcl_Channel *rchan, Tcl_Channel *wchan, int flags); /* 582 */
    Tcl_Command (*tcl_NRCreateCommand) (Tcl_Interp *interp, const char *cmdName, Tcl_ObjCmdProc *proc, Tcl_ObjCmdProc *nreProc, void *clientData, Tcl_CmdDeleteProc *deleteProc); /* 583 */
    int (*tcl_NREvalObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 584 */
    int (*tcl_NREvalObjv) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* 585 */
    int (*tcl_NRCmdSwap) (Tcl_Interp *interp, Tcl_Command cmd, int objc, Tcl_Obj *const objv[], int flags); /* 586 */
    int (*tcl_NREvalObjv) (Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], int flags); /* 585 */
    int (*tcl_NRCmdSwap) (Tcl_Interp *interp, Tcl_Command cmd, Tcl_Size objc, Tcl_Obj *const objv[], int flags); /* 586 */
    void (*tcl_NRAddCallback) (Tcl_Interp *interp, Tcl_NRPostProc *postProcPtr, void *data0, void *data1, void *data2, void *data3); /* 587 */
    int (*tcl_NRCallObjProc) (Tcl_Interp *interp, Tcl_ObjCmdProc *objProc, void *clientData, int objc, Tcl_Obj *const objv[]); /* 588 */
    int (*tcl_NRCallObjProc) (Tcl_Interp *interp, Tcl_ObjCmdProc *objProc, void *clientData, Tcl_Size objc, Tcl_Obj *const objv[]); /* 588 */
    unsigned (*tcl_GetFSDeviceFromStat) (const Tcl_StatBuf *statPtr); /* 589 */
    unsigned (*tcl_GetFSInodeFromStat) (const Tcl_StatBuf *statPtr); /* 590 */
    unsigned (*tcl_GetModeFromStat) (const Tcl_StatBuf *statPtr); /* 591 */
    int (*tcl_GetLinkCountFromStat) (const Tcl_StatBuf *statPtr); /* 592 */
    int (*tcl_GetUserIdFromStat) (const Tcl_StatBuf *statPtr); /* 593 */
    int (*tcl_GetGroupIdFromStat) (const Tcl_StatBuf *statPtr); /* 594 */
    int (*tcl_GetDeviceTypeFromStat) (const Tcl_StatBuf *statPtr); /* 595 */
    Tcl_WideInt (*tcl_GetAccessTimeFromStat) (const Tcl_StatBuf *statPtr); /* 596 */
    Tcl_WideInt (*tcl_GetModificationTimeFromStat) (const Tcl_StatBuf *statPtr); /* 597 */
    Tcl_WideInt (*tcl_GetChangeTimeFromStat) (const Tcl_StatBuf *statPtr); /* 598 */
    Tcl_WideUInt (*tcl_GetSizeFromStat) (const Tcl_StatBuf *statPtr); /* 599 */
    Tcl_WideUInt (*tcl_GetBlocksFromStat) (const Tcl_StatBuf *statPtr); /* 600 */
    long long (*tcl_GetAccessTimeFromStat) (const Tcl_StatBuf *statPtr); /* 596 */
    long long (*tcl_GetModificationTimeFromStat) (const Tcl_StatBuf *statPtr); /* 597 */
    long long (*tcl_GetChangeTimeFromStat) (const Tcl_StatBuf *statPtr); /* 598 */
    unsigned long long (*tcl_GetSizeFromStat) (const Tcl_StatBuf *statPtr); /* 599 */
    unsigned long long (*tcl_GetBlocksFromStat) (const Tcl_StatBuf *statPtr); /* 600 */
    unsigned (*tcl_GetBlockSizeFromStat) (const Tcl_StatBuf *statPtr); /* 601 */
    int (*tcl_SetEnsembleParameterList) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *paramList); /* 602 */
    int (*tcl_GetEnsembleParameterList) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **paramListPtr); /* 603 */
    int (*tcl_ParseArgsObjv) (Tcl_Interp *interp, const Tcl_ArgvInfo *argTable, int *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv); /* 604 */
    int (*tclParseArgsObjv) (Tcl_Interp *interp, const Tcl_ArgvInfo *argTable, void *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv); /* 604 */
    int (*tcl_GetErrorLine) (Tcl_Interp *interp); /* 605 */
    void (*tcl_SetErrorLine) (Tcl_Interp *interp, int lineNum); /* 606 */
    void (*tcl_TransferResult) (Tcl_Interp *sourceInterp, int code, Tcl_Interp *targetInterp); /* 607 */
    int (*tcl_InterpActive) (Tcl_Interp *interp); /* 608 */
    void (*tcl_BackgroundException) (Tcl_Interp *interp, int code); /* 609 */
    int (*tcl_ZlibDeflate) (Tcl_Interp *interp, int format, Tcl_Obj *data, int level, Tcl_Obj *gzipHeaderDictObj); /* 610 */
    int (*tcl_ZlibInflate) (Tcl_Interp *interp, int format, Tcl_Obj *data, size_t buffersize, Tcl_Obj *gzipHeaderDictObj); /* 611 */
    unsigned int (*tcl_ZlibCRC32) (unsigned int crc, const unsigned char *buf, size_t len); /* 612 */
    unsigned int (*tcl_ZlibAdler32) (unsigned int adler, const unsigned char *buf, size_t len); /* 613 */
    int (*tcl_ZlibInflate) (Tcl_Interp *interp, int format, Tcl_Obj *data, Tcl_Size buffersize, Tcl_Obj *gzipHeaderDictObj); /* 611 */
    unsigned int (*tcl_ZlibCRC32) (unsigned int crc, const unsigned char *buf, Tcl_Size len); /* 612 */
    unsigned int (*tcl_ZlibAdler32) (unsigned int adler, const unsigned char *buf, Tcl_Size len); /* 613 */
    int (*tcl_ZlibStreamInit) (Tcl_Interp *interp, int mode, int format, int level, Tcl_Obj *dictObj, Tcl_ZlibStream *zshandle); /* 614 */
    Tcl_Obj * (*tcl_ZlibStreamGetCommandName) (Tcl_ZlibStream zshandle); /* 615 */
    int (*tcl_ZlibStreamEof) (Tcl_ZlibStream zshandle); /* 616 */
    int (*tcl_ZlibStreamChecksum) (Tcl_ZlibStream zshandle); /* 617 */
    int (*tcl_ZlibStreamPut) (Tcl_ZlibStream zshandle, Tcl_Obj *data, int flush); /* 618 */
    int (*tcl_ZlibStreamGet) (Tcl_ZlibStream zshandle, Tcl_Obj *data, size_t count); /* 619 */
    int (*tcl_ZlibStreamGet) (Tcl_ZlibStream zshandle, Tcl_Obj *data, Tcl_Size count); /* 619 */
    int (*tcl_ZlibStreamClose) (Tcl_ZlibStream zshandle); /* 620 */
    int (*tcl_ZlibStreamReset) (Tcl_ZlibStream zshandle); /* 621 */
    void (*tcl_SetStartupScript) (Tcl_Obj *path, const char *encoding); /* 622 */
    Tcl_Obj * (*tcl_GetStartupScript) (const char **encodingPtr); /* 623 */
    int (*tcl_CloseEx) (Tcl_Interp *interp, Tcl_Channel chan, int flags); /* 624 */
    int (*tcl_NRExprObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj *resultPtr); /* 625 */
    int (*tcl_NRSubstObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 626 */
    int (*tcl_LoadFile) (Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *const symv[], int flags, void *procPtrs, Tcl_LoadHandle *handlePtr); /* 627 */
    void * (*tcl_FindSymbol) (Tcl_Interp *interp, Tcl_LoadHandle handle, const char *symbol); /* 628 */
    int (*tcl_FSUnloadFile) (Tcl_Interp *interp, Tcl_LoadHandle handlePtr); /* 629 */
    void (*tcl_ZlibStreamSetCompressionDictionary) (Tcl_ZlibStream zhandle, Tcl_Obj *compressionDictionaryObj); /* 630 */
    Tcl_Channel (*tcl_OpenTcpServerEx) (Tcl_Interp *interp, const char *service, const char *host, unsigned int flags, Tcl_TcpAcceptProc *acceptProc, void *callbackData); /* 631 */
    int (*tclZipfs_Mount) (Tcl_Interp *interp, const char *mountPoint, const char *zipname, const char *passwd); /* 632 */
    Tcl_Channel (*tcl_OpenTcpServerEx) (Tcl_Interp *interp, const char *service, const char *host, unsigned int flags, int backlog, Tcl_TcpAcceptProc *acceptProc, void *callbackData); /* 631 */
    int (*tclZipfs_Mount) (Tcl_Interp *interp, const char *zipname, const char *mountPoint, const char *passwd); /* 632 */
    int (*tclZipfs_Unmount) (Tcl_Interp *interp, const char *mountPoint); /* 633 */
    Tcl_Obj * (*tclZipfs_TclLibrary) (void); /* 634 */
    int (*tclZipfs_MountBuffer) (Tcl_Interp *interp, const char *mountPoint, unsigned char *data, size_t datalen, int copy); /* 635 */
    void (*tcl_FreeIntRep) (Tcl_Obj *objPtr); /* 636 */
    char * (*tcl_InitStringRep) (Tcl_Obj *objPtr, const char *bytes, size_t numBytes); /* 637 */
    Tcl_ObjIntRep * (*tcl_FetchIntRep) (Tcl_Obj *objPtr, const Tcl_ObjType *typePtr); /* 638 */
    void (*tcl_StoreIntRep) (Tcl_Obj *objPtr, const Tcl_ObjType *typePtr, const Tcl_ObjIntRep *irPtr); /* 639 */
    int (*tclZipfs_MountBuffer) (Tcl_Interp *interp, const void *data, size_t datalen, const char *mountPoint, int copy); /* 635 */
    void (*tcl_FreeInternalRep) (Tcl_Obj *objPtr); /* 636 */
    char * (*tcl_InitStringRep) (Tcl_Obj *objPtr, const char *bytes, TCL_HASH_TYPE numBytes); /* 637 */
    Tcl_ObjInternalRep * (*tcl_FetchInternalRep) (Tcl_Obj *objPtr, const Tcl_ObjType *typePtr); /* 638 */
    void (*tcl_StoreInternalRep) (Tcl_Obj *objPtr, const Tcl_ObjType *typePtr, const Tcl_ObjInternalRep *irPtr); /* 639 */
    int (*tcl_HasStringRep) (Tcl_Obj *objPtr); /* 640 */
    void (*tcl_IncrRefCount) (Tcl_Obj *objPtr); /* 641 */
    void (*tcl_DecrRefCount) (Tcl_Obj *objPtr); /* 642 */
    int (*tcl_IsShared) (Tcl_Obj *objPtr); /* 643 */
    int (*tcl_LinkArray) (Tcl_Interp *interp, const char *varName, void *addr, int type, size_t size); /* 644 */
    int (*tcl_GetIntForIndex) (Tcl_Interp *interp, Tcl_Obj *objPtr, size_t endValue, size_t *indexPtr); /* 645 */
    int (*tcl_UtfToUniChar) (const char *src, int *chPtr); /* 646 */
    char * (*tcl_UniCharToUtfDString) (const int *uniStr, size_t uniLength, Tcl_DString *dsPtr); /* 647 */
    int * (*tcl_UtfToUniCharDString) (const char *src, size_t length, Tcl_DString *dsPtr); /* 648 */
    int (*tcl_LinkArray) (Tcl_Interp *interp, const char *varName, void *addr, int type, Tcl_Size size); /* 644 */
    int (*tcl_GetIntForIndex) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Size endValue, Tcl_Size *indexPtr); /* 645 */
    Tcl_Size (*tcl_UtfToUniChar) (const char *src, int *chPtr); /* 646 */
    char * (*tcl_UniCharToUtfDString) (const int *uniStr, Tcl_Size uniLength, Tcl_DString *dsPtr); /* 647 */
    int * (*tcl_UtfToUniCharDString) (const char *src, Tcl_Size length, Tcl_DString *dsPtr); /* 648 */
    unsigned char * (*tclGetBytesFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, void *numBytesPtr); /* 649 */
    unsigned char * (*tcl_GetBytesFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Size *numBytesPtr); /* 650 */
    char * (*tcl_GetStringFromObj) (Tcl_Obj *objPtr, Tcl_Size *lengthPtr); /* 651 */
    Tcl_UniChar * (*tcl_GetUnicodeFromObj) (Tcl_Obj *objPtr, Tcl_Size *lengthPtr); /* 652 */
    int (*tcl_GetSizeIntFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Size *sizePtr); /* 653 */
    int (*tcl_UtfCharComplete) (const char *src, Tcl_Size length); /* 654 */
    const char * (*tcl_UtfNext) (const char *src); /* 655 */
    const char * (*tcl_UtfPrev) (const char *src, const char *start); /* 656 */
    int (*tcl_FSTildeExpand) (Tcl_Interp *interp, const char *path, Tcl_DString *dsPtr); /* 657 */
    int (*tcl_ExternalToUtfDStringEx) (Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, Tcl_Size srcLen, int flags, Tcl_DString *dsPtr, Tcl_Size *errorLocationPtr); /* 658 */
    int (*tcl_UtfToExternalDStringEx) (Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, Tcl_Size srcLen, int flags, Tcl_DString *dsPtr, Tcl_Size *errorLocationPtr); /* 659 */
    int (*tcl_AsyncMarkFromSignal) (Tcl_AsyncHandler async, int sigNumber); /* 660 */
    int (*tcl_ListObjGetElements) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size *objcPtr, Tcl_Obj ***objvPtr); /* 661 */
    int (*tcl_ListObjLength) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size *lengthPtr); /* 662 */
    int (*tcl_DictObjSize) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Size *sizePtr); /* 663 */
    int (*tcl_SplitList) (Tcl_Interp *interp, const char *listStr, Tcl_Size *argcPtr, const char ***argvPtr); /* 664 */
    void (*tcl_SplitPath) (const char *path, Tcl_Size *argcPtr, const char ***argvPtr); /* 665 */
    Tcl_Obj * (*tcl_FSSplitPath) (Tcl_Obj *pathPtr, Tcl_Size *lenPtr); /* 666 */
    int (*tcl_ParseArgsObjv) (Tcl_Interp *interp, const Tcl_ArgvInfo *argTable, Tcl_Size *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv); /* 667 */
    Tcl_Size (*tcl_UniCharLen) (const int *uniStr); /* 668 */
    Tcl_Size (*tcl_NumUtfChars) (const char *src, Tcl_Size length); /* 669 */
    Tcl_Size (*tcl_GetCharLength) (Tcl_Obj *objPtr); /* 670 */
    const char * (*tcl_UtfAtIndex) (const char *src, Tcl_Size index); /* 671 */
    Tcl_Obj * (*tcl_GetRange) (Tcl_Obj *objPtr, Tcl_Size first, Tcl_Size last); /* 672 */
    int (*tcl_GetUniChar) (Tcl_Obj *objPtr, Tcl_Size index); /* 673 */
    int (*tcl_GetBool) (Tcl_Interp *interp, const char *src, int flags, char *charPtr); /* 674 */
    int (*tcl_GetBoolFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags, char *charPtr); /* 675 */
    Tcl_Command (*tcl_CreateObjCommand2) (Tcl_Interp *interp, const char *cmdName, Tcl_ObjCmdProc2 *proc2, void *clientData, Tcl_CmdDeleteProc *deleteProc); /* 676 */
    Tcl_Trace (*tcl_CreateObjTrace2) (Tcl_Interp *interp, Tcl_Size level, int flags, Tcl_CmdObjTraceProc2 *objProc2, void *clientData, Tcl_CmdObjTraceDeleteProc *delProc); /* 677 */
    Tcl_Command (*tcl_NRCreateCommand2) (Tcl_Interp *interp, const char *cmdName, Tcl_ObjCmdProc2 *proc, Tcl_ObjCmdProc2 *nreProc2, void *clientData, Tcl_CmdDeleteProc *deleteProc); /* 678 */
    int (*tcl_NRCallObjProc2) (Tcl_Interp *interp, Tcl_ObjCmdProc2 *objProc2, void *clientData, Tcl_Size objc, Tcl_Obj *const objv[]); /* 679 */
    int (*tcl_GetNumberFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, void **clientDataPtr, int *typePtr); /* 680 */
    int (*tcl_GetNumber) (Tcl_Interp *interp, const char *bytes, Tcl_Size numBytes, void **clientDataPtr, int *typePtr); /* 681 */
    int (*tcl_RemoveChannelMode) (Tcl_Interp *interp, Tcl_Channel chan, int mode); /* 682 */
    Tcl_Size (*tcl_GetEncodingNulLength) (Tcl_Encoding encoding); /* 683 */
    int (*tcl_GetWideUIntFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_WideUInt *uwidePtr); /* 684 */
    Tcl_Obj * (*tcl_DStringToObj) (Tcl_DString *dsPtr); /* 685 */
    int (*tcl_UtfNcmp) (const char *s1, const char *s2, size_t n); /* 686 */
    int (*tcl_UtfNcasecmp) (const char *s1, const char *s2, size_t n); /* 687 */
    Tcl_Obj * (*tcl_NewWideUIntObj) (Tcl_WideUInt wideValue); /* 688 */
    void (*tcl_SetWideUIntObj) (Tcl_Obj *objPtr, Tcl_WideUInt uwideValue); /* 689 */
    void (*tclUnusedStubEntry) (void); /* 690 */
} TclStubs;

extern const TclStubs *tclStubsPtr;

#ifdef __cplusplus
}
#endif
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
2489
2490
2491
2492
2605
2606
2607
2608
2609
2610
2611

2612
2613






2614
2615





2616
2617
2618
2619
2620
2621
2622







-


-
-
-
-
-
-


-
-
-
-
-







	(tclStubsPtr->tcl_Realloc) /* 5 */
#define Tcl_DbCkalloc \
	(tclStubsPtr->tcl_DbCkalloc) /* 6 */
#define Tcl_DbCkfree \
	(tclStubsPtr->tcl_DbCkfree) /* 7 */
#define Tcl_DbCkrealloc \
	(tclStubsPtr->tcl_DbCkrealloc) /* 8 */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
#define Tcl_CreateFileHandler \
	(tclStubsPtr->tcl_CreateFileHandler) /* 9 */
#endif /* UNIX */
#ifdef MAC_OSX_TCL /* MACOSX */
#define Tcl_CreateFileHandler \
	(tclStubsPtr->tcl_CreateFileHandler) /* 9 */
#endif /* MACOSX */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
#define Tcl_DeleteFileHandler \
	(tclStubsPtr->tcl_DeleteFileHandler) /* 10 */
#endif /* UNIX */
#ifdef MAC_OSX_TCL /* MACOSX */
#define Tcl_DeleteFileHandler \
	(tclStubsPtr->tcl_DeleteFileHandler) /* 10 */
#endif /* MACOSX */
#define Tcl_SetTimer \
	(tclStubsPtr->tcl_SetTimer) /* 11 */
#define Tcl_Sleep \
	(tclStubsPtr->tcl_Sleep) /* 12 */
#define Tcl_WaitForEvent \
	(tclStubsPtr->tcl_WaitForEvent) /* 13 */
#define Tcl_AppendAllObjTypes \
2536
2537
2538
2539
2540
2541
2542
2543
2544


2545
2546
2547
2548
2549
2550
2551
2552


2553
2554
2555
2556


2557
2558
2559
2560
2561
2562
2563
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







-
-
+
+






-
-
+
+


-
-
+
+







	(tclStubsPtr->tcl_GetInt) /* 37 */
#define Tcl_GetIntFromObj \
	(tclStubsPtr->tcl_GetIntFromObj) /* 38 */
#define Tcl_GetLongFromObj \
	(tclStubsPtr->tcl_GetLongFromObj) /* 39 */
#define Tcl_GetObjType \
	(tclStubsPtr->tcl_GetObjType) /* 40 */
#define Tcl_GetStringFromObj \
	(tclStubsPtr->tcl_GetStringFromObj) /* 41 */
#define TclGetStringFromObj \
	(tclStubsPtr->tclGetStringFromObj) /* 41 */
#define Tcl_InvalidateStringRep \
	(tclStubsPtr->tcl_InvalidateStringRep) /* 42 */
#define Tcl_ListObjAppendList \
	(tclStubsPtr->tcl_ListObjAppendList) /* 43 */
#define Tcl_ListObjAppendElement \
	(tclStubsPtr->tcl_ListObjAppendElement) /* 44 */
#define Tcl_ListObjGetElements \
	(tclStubsPtr->tcl_ListObjGetElements) /* 45 */
#define TclListObjGetElements \
	(tclStubsPtr->tclListObjGetElements) /* 45 */
#define Tcl_ListObjIndex \
	(tclStubsPtr->tcl_ListObjIndex) /* 46 */
#define Tcl_ListObjLength \
	(tclStubsPtr->tcl_ListObjLength) /* 47 */
#define TclListObjLength \
	(tclStubsPtr->tclListObjLength) /* 47 */
#define Tcl_ListObjReplace \
	(tclStubsPtr->tcl_ListObjReplace) /* 48 */
/* Slot 49 is reserved */
#define Tcl_NewByteArrayObj \
	(tclStubsPtr->tcl_NewByteArrayObj) /* 50 */
#define Tcl_NewDoubleObj \
	(tclStubsPtr->tcl_NewDoubleObj) /* 51 */
2606
2607
2608
2609
2610
2611
2612

2613

2614
2615
2616
2617
2618
2619
2620
2736
2737
2738
2739
2740
2741
2742
2743

2744
2745
2746
2747
2748
2749
2750
2751







+
-
+







/* Slot 77 is reserved */
#define Tcl_BadChannelOption \
	(tclStubsPtr->tcl_BadChannelOption) /* 78 */
#define Tcl_CallWhenDeleted \
	(tclStubsPtr->tcl_CallWhenDeleted) /* 79 */
#define Tcl_CancelIdleCall \
	(tclStubsPtr->tcl_CancelIdleCall) /* 80 */
#define Tcl_Close \
/* Slot 81 is reserved */
	(tclStubsPtr->tcl_Close) /* 81 */
#define Tcl_CommandComplete \
	(tclStubsPtr->tcl_CommandComplete) /* 82 */
#define Tcl_Concat \
	(tclStubsPtr->tcl_Concat) /* 83 */
#define Tcl_ConvertElement \
	(tclStubsPtr->tcl_ConvertElement) /* 84 */
#define Tcl_ConvertCountedElement \
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744



2745
2746
2747
2748
2749
2750
2751
2865
2866
2867
2868
2869
2870
2871




2872
2873
2874
2875
2876
2877
2878
2879
2880
2881







-
-
-
-
+
+
+







	(tclStubsPtr->tcl_Finalize) /* 143 */
/* Slot 144 is reserved */
#define Tcl_FirstHashEntry \
	(tclStubsPtr->tcl_FirstHashEntry) /* 145 */
#define Tcl_Flush \
	(tclStubsPtr->tcl_Flush) /* 146 */
/* Slot 147 is reserved */
#define Tcl_GetAlias \
	(tclStubsPtr->tcl_GetAlias) /* 148 */
#define Tcl_GetAliasObj \
	(tclStubsPtr->tcl_GetAliasObj) /* 149 */
/* Slot 148 is reserved */
#define TclGetAliasObj \
	(tclStubsPtr->tclGetAliasObj) /* 149 */
#define Tcl_GetAssocData \
	(tclStubsPtr->tcl_GetAssocData) /* 150 */
#define Tcl_GetChannel \
	(tclStubsPtr->tcl_GetChannel) /* 151 */
#define Tcl_GetChannelBufferSize \
	(tclStubsPtr->tcl_GetChannelBufferSize) /* 152 */
#define Tcl_GetChannelHandle \
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2902
2903
2904
2905
2906
2907
2908

2909
2910





2911
2912
2913
2914
2915
2916
2917







-


-
-
-
-
-







	(tclStubsPtr->tcl_GetInterpPath) /* 163 */
#define Tcl_GetParent \
	(tclStubsPtr->tcl_GetParent) /* 164 */
#define Tcl_GetNameOfExecutable \
	(tclStubsPtr->tcl_GetNameOfExecutable) /* 165 */
#define Tcl_GetObjResult \
	(tclStubsPtr->tcl_GetObjResult) /* 166 */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
#define Tcl_GetOpenFile \
	(tclStubsPtr->tcl_GetOpenFile) /* 167 */
#endif /* UNIX */
#ifdef MAC_OSX_TCL /* MACOSX */
#define Tcl_GetOpenFile \
	(tclStubsPtr->tcl_GetOpenFile) /* 167 */
#endif /* MACOSX */
#define Tcl_GetPathType \
	(tclStubsPtr->tcl_GetPathType) /* 168 */
#define Tcl_Gets \
	(tclStubsPtr->tcl_Gets) /* 169 */
#define Tcl_GetsObj \
	(tclStubsPtr->tcl_GetsObj) /* 170 */
#define Tcl_GetServiceMode \
2819
2820
2821
2822
2823
2824
2825
2826
2827

2828
2829
2830
2831
2832
2833
2834
2943
2944
2945
2946
2947
2948
2949


2950
2951
2952
2953
2954
2955
2956
2957







-
-
+







#define Tcl_JoinPath \
	(tclStubsPtr->tcl_JoinPath) /* 186 */
#define Tcl_LinkVar \
	(tclStubsPtr->tcl_LinkVar) /* 187 */
/* Slot 188 is reserved */
#define Tcl_MakeFileChannel \
	(tclStubsPtr->tcl_MakeFileChannel) /* 189 */
#define Tcl_MakeSafe \
	(tclStubsPtr->tcl_MakeSafe) /* 190 */
/* Slot 190 is reserved */
#define Tcl_MakeTcpClientChannel \
	(tclStubsPtr->tcl_MakeTcpClientChannel) /* 191 */
#define Tcl_Merge \
	(tclStubsPtr->tcl_Merge) /* 192 */
#define Tcl_NextHashEntry \
	(tclStubsPtr->tcl_NextHashEntry) /* 193 */
#define Tcl_NotifyChannel \
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929




2930
2931
2932
2933
2934
2935
2936
3042
3043
3044
3045
3046
3047
3048




3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059







-
-
-
-
+
+
+
+







	(tclStubsPtr->tcl_SetVar2) /* 238 */
#define Tcl_SignalId \
	(tclStubsPtr->tcl_SignalId) /* 239 */
#define Tcl_SignalMsg \
	(tclStubsPtr->tcl_SignalMsg) /* 240 */
#define Tcl_SourceRCFile \
	(tclStubsPtr->tcl_SourceRCFile) /* 241 */
#define Tcl_SplitList \
	(tclStubsPtr->tcl_SplitList) /* 242 */
#define Tcl_SplitPath \
	(tclStubsPtr->tcl_SplitPath) /* 243 */
#define TclSplitList \
	(tclStubsPtr->tclSplitList) /* 242 */
#define TclSplitPath \
	(tclStubsPtr->tclSplitPath) /* 243 */
/* Slot 244 is reserved */
/* Slot 245 is reserved */
/* Slot 246 is reserved */
/* Slot 247 is reserved */
#define Tcl_TraceVar2 \
	(tclStubsPtr->tcl_TraceVar2) /* 248 */
#define Tcl_TranslateFileName \
2989
2990
2991
2992
2993
2994
2995

2996

2997
2998
2999
3000
3001
3002
3003
3112
3113
3114
3115
3116
3117
3118
3119

3120
3121
3122
3123
3124
3125
3126
3127







+
-
+







	(tclStubsPtr->tcl_StackChannel) /* 281 */
#define Tcl_UnstackChannel \
	(tclStubsPtr->tcl_UnstackChannel) /* 282 */
#define Tcl_GetStackedChannel \
	(tclStubsPtr->tcl_GetStackedChannel) /* 283 */
#define Tcl_SetMainLoop \
	(tclStubsPtr->tcl_SetMainLoop) /* 284 */
#define Tcl_GetAliasObj \
/* Slot 285 is reserved */
	(tclStubsPtr->tcl_GetAliasObj) /* 285 */
#define Tcl_AppendObjToObj \
	(tclStubsPtr->tcl_AppendObjToObj) /* 286 */
#define Tcl_CreateEncoding \
	(tclStubsPtr->tcl_CreateEncoding) /* 287 */
#define Tcl_CreateThreadExitHandler \
	(tclStubsPtr->tcl_CreateThreadExitHandler) /* 288 */
#define Tcl_DeleteThreadExitHandler \
3041
3042
3043
3044
3045
3046
3047
3048
3049


3050
3051
3052
3053
3054
3055
3056
3165
3166
3167
3168
3169
3170
3171


3172
3173
3174
3175
3176
3177
3178
3179
3180







-
-
+
+







	(tclStubsPtr->tcl_MutexLock) /* 308 */
#define Tcl_MutexUnlock \
	(tclStubsPtr->tcl_MutexUnlock) /* 309 */
#define Tcl_ConditionNotify \
	(tclStubsPtr->tcl_ConditionNotify) /* 310 */
#define Tcl_ConditionWait \
	(tclStubsPtr->tcl_ConditionWait) /* 311 */
#define Tcl_NumUtfChars \
	(tclStubsPtr->tcl_NumUtfChars) /* 312 */
#define TclNumUtfChars \
	(tclStubsPtr->tclNumUtfChars) /* 312 */
#define Tcl_ReadChars \
	(tclStubsPtr->tcl_ReadChars) /* 313 */
/* Slot 314 is reserved */
/* Slot 315 is reserved */
#define Tcl_SetSystemEncoding \
	(tclStubsPtr->tcl_SetSystemEncoding) /* 316 */
#define Tcl_SetVar2Ex \
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
3189
3190
3191
3192
3193
3194
3195




3196
3197
3198
3199
3200
3201
3202
3203
3204
3205




3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216







-
-
-
-
+
+
+
+






-
-
-
-
+
+
+
+







	(tclStubsPtr->tcl_UniCharToLower) /* 321 */
#define Tcl_UniCharToTitle \
	(tclStubsPtr->tcl_UniCharToTitle) /* 322 */
#define Tcl_UniCharToUpper \
	(tclStubsPtr->tcl_UniCharToUpper) /* 323 */
#define Tcl_UniCharToUtf \
	(tclStubsPtr->tcl_UniCharToUtf) /* 324 */
#define Tcl_UtfAtIndex \
	(tclStubsPtr->tcl_UtfAtIndex) /* 325 */
#define Tcl_UtfCharComplete \
	(tclStubsPtr->tcl_UtfCharComplete) /* 326 */
#define TclUtfAtIndex \
	(tclStubsPtr->tclUtfAtIndex) /* 325 */
#define TclUtfCharComplete \
	(tclStubsPtr->tclUtfCharComplete) /* 326 */
#define Tcl_UtfBackslash \
	(tclStubsPtr->tcl_UtfBackslash) /* 327 */
#define Tcl_UtfFindFirst \
	(tclStubsPtr->tcl_UtfFindFirst) /* 328 */
#define Tcl_UtfFindLast \
	(tclStubsPtr->tcl_UtfFindLast) /* 329 */
#define Tcl_UtfNext \
	(tclStubsPtr->tcl_UtfNext) /* 330 */
#define Tcl_UtfPrev \
	(tclStubsPtr->tcl_UtfPrev) /* 331 */
#define TclUtfNext \
	(tclStubsPtr->tclUtfNext) /* 330 */
#define TclUtfPrev \
	(tclStubsPtr->tclUtfPrev) /* 331 */
#define Tcl_UtfToExternal \
	(tclStubsPtr->tcl_UtfToExternal) /* 332 */
#define Tcl_UtfToExternalDString \
	(tclStubsPtr->tcl_UtfToExternalDString) /* 333 */
#define Tcl_UtfToLower \
	(tclStubsPtr->tcl_UtfToLower) /* 334 */
#define Tcl_UtfToTitle \
3117
3118
3119
3120
3121
3122
3123

3124

3125
3126
3127
3128
3129
3130
3131
3241
3242
3243
3244
3245
3246
3247
3248

3249
3250
3251
3252
3253
3254
3255
3256







+
-
+







	(tclStubsPtr->tcl_UniCharIsLower) /* 348 */
#define Tcl_UniCharIsSpace \
	(tclStubsPtr->tcl_UniCharIsSpace) /* 349 */
#define Tcl_UniCharIsUpper \
	(tclStubsPtr->tcl_UniCharIsUpper) /* 350 */
#define Tcl_UniCharIsWordChar \
	(tclStubsPtr->tcl_UniCharIsWordChar) /* 351 */
#define Tcl_Char16Len \
/* Slot 352 is reserved */
	(tclStubsPtr->tcl_Char16Len) /* 352 */
/* Slot 353 is reserved */
#define Tcl_Char16ToUtfDString \
	(tclStubsPtr->tcl_Char16ToUtfDString) /* 354 */
#define Tcl_UtfToChar16DString \
	(tclStubsPtr->tcl_UtfToChar16DString) /* 355 */
#define Tcl_GetRegExpFromObj \
	(tclStubsPtr->tcl_GetRegExpFromObj) /* 356 */
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158




3159
3160
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
3273
3274
3275
3276
3277
3278
3279




3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301




3302
3303
3304
3305
3306



3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317







-
-
-
-
+
+
+
+


















-
-
-
-
+
+
+
+

-
-
-
+
+
+
+







	(tclStubsPtr->tcl_GetCwd) /* 365 */
#define Tcl_Chdir \
	(tclStubsPtr->tcl_Chdir) /* 366 */
#define Tcl_Access \
	(tclStubsPtr->tcl_Access) /* 367 */
#define Tcl_Stat \
	(tclStubsPtr->tcl_Stat) /* 368 */
#define Tcl_UtfNcmp \
	(tclStubsPtr->tcl_UtfNcmp) /* 369 */
#define Tcl_UtfNcasecmp \
	(tclStubsPtr->tcl_UtfNcasecmp) /* 370 */
#define TclUtfNcmp \
	(tclStubsPtr->tclUtfNcmp) /* 369 */
#define TclUtfNcasecmp \
	(tclStubsPtr->tclUtfNcasecmp) /* 370 */
#define Tcl_StringCaseMatch \
	(tclStubsPtr->tcl_StringCaseMatch) /* 371 */
#define Tcl_UniCharIsControl \
	(tclStubsPtr->tcl_UniCharIsControl) /* 372 */
#define Tcl_UniCharIsGraph \
	(tclStubsPtr->tcl_UniCharIsGraph) /* 373 */
#define Tcl_UniCharIsPrint \
	(tclStubsPtr->tcl_UniCharIsPrint) /* 374 */
#define Tcl_UniCharIsPunct \
	(tclStubsPtr->tcl_UniCharIsPunct) /* 375 */
#define Tcl_RegExpExecObj \
	(tclStubsPtr->tcl_RegExpExecObj) /* 376 */
#define Tcl_RegExpGetInfo \
	(tclStubsPtr->tcl_RegExpGetInfo) /* 377 */
#define Tcl_NewUnicodeObj \
	(tclStubsPtr->tcl_NewUnicodeObj) /* 378 */
#define Tcl_SetUnicodeObj \
	(tclStubsPtr->tcl_SetUnicodeObj) /* 379 */
#define Tcl_GetCharLength \
	(tclStubsPtr->tcl_GetCharLength) /* 380 */
#define Tcl_GetUniChar \
	(tclStubsPtr->tcl_GetUniChar) /* 381 */
#define TclGetCharLength \
	(tclStubsPtr->tclGetCharLength) /* 380 */
#define TclGetUniChar \
	(tclStubsPtr->tclGetUniChar) /* 381 */
/* Slot 382 is reserved */
#define Tcl_GetRange \
	(tclStubsPtr->tcl_GetRange) /* 383 */
/* Slot 384 is reserved */
#define TclGetRange \
	(tclStubsPtr->tclGetRange) /* 383 */
#define Tcl_AppendUnicodeToObj \
	(tclStubsPtr->tcl_AppendUnicodeToObj) /* 384 */
#define Tcl_RegExpMatchObj \
	(tclStubsPtr->tcl_RegExpMatchObj) /* 385 */
#define Tcl_SetNotifier \
	(tclStubsPtr->tcl_SetNotifier) /* 386 */
#define Tcl_GetAllocMutex \
	(tclStubsPtr->tcl_GetAllocMutex) /* 387 */
#define Tcl_GetChannelNames \
3270
3271
3272
3273
3274
3275
3276
3277
3278


3279
3280
3281
3282
3283
3284
3285
3396
3397
3398
3399
3400
3401
3402


3403
3404
3405
3406
3407
3408
3409
3410
3411







-
-
+
+







	(tclStubsPtr->tcl_AttemptRealloc) /* 430 */
#define Tcl_AttemptDbCkrealloc \
	(tclStubsPtr->tcl_AttemptDbCkrealloc) /* 431 */
#define Tcl_AttemptSetObjLength \
	(tclStubsPtr->tcl_AttemptSetObjLength) /* 432 */
#define Tcl_GetChannelThread \
	(tclStubsPtr->tcl_GetChannelThread) /* 433 */
#define Tcl_GetUnicodeFromObj \
	(tclStubsPtr->tcl_GetUnicodeFromObj) /* 434 */
#define TclGetUnicodeFromObj \
	(tclStubsPtr->tclGetUnicodeFromObj) /* 434 */
/* Slot 435 is reserved */
/* Slot 436 is reserved */
#define Tcl_SubstObj \
	(tclStubsPtr->tcl_SubstObj) /* 437 */
#define Tcl_DetachChannel \
	(tclStubsPtr->tcl_DetachChannel) /* 438 */
#define Tcl_IsStandardChannel \
3322
3323
3324
3325
3326
3327
3328
3329
3330


3331
3332
3333
3334
3335
3336
3337
3448
3449
3450
3451
3452
3453
3454


3455
3456
3457
3458
3459
3460
3461
3462
3463







-
-
+
+







	(tclStubsPtr->tcl_FSGetCwd) /* 457 */
#define Tcl_FSChdir \
	(tclStubsPtr->tcl_FSChdir) /* 458 */
#define Tcl_FSConvertToPathType \
	(tclStubsPtr->tcl_FSConvertToPathType) /* 459 */
#define Tcl_FSJoinPath \
	(tclStubsPtr->tcl_FSJoinPath) /* 460 */
#define Tcl_FSSplitPath \
	(tclStubsPtr->tcl_FSSplitPath) /* 461 */
#define TclFSSplitPath \
	(tclStubsPtr->tclFSSplitPath) /* 461 */
#define Tcl_FSEqualPaths \
	(tclStubsPtr->tcl_FSEqualPaths) /* 462 */
#define Tcl_FSGetNormalizedPath \
	(tclStubsPtr->tcl_FSGetNormalizedPath) /* 463 */
#define Tcl_FSJoinToPath \
	(tclStubsPtr->tcl_FSJoinToPath) /* 464 */
#define Tcl_FSGetInternalRep \
3394
3395
3396
3397
3398
3399
3400
3401
3402


3403
3404
3405
3406
3407
3408
3409
3520
3521
3522
3523
3524
3525
3526


3527
3528
3529
3530
3531
3532
3533
3534
3535







-
-
+
+







	(tclStubsPtr->tcl_ChannelWideSeekProc) /* 493 */
#define Tcl_DictObjPut \
	(tclStubsPtr->tcl_DictObjPut) /* 494 */
#define Tcl_DictObjGet \
	(tclStubsPtr->tcl_DictObjGet) /* 495 */
#define Tcl_DictObjRemove \
	(tclStubsPtr->tcl_DictObjRemove) /* 496 */
#define Tcl_DictObjSize \
	(tclStubsPtr->tcl_DictObjSize) /* 497 */
#define TclDictObjSize \
	(tclStubsPtr->tclDictObjSize) /* 497 */
#define Tcl_DictObjFirst \
	(tclStubsPtr->tcl_DictObjFirst) /* 498 */
#define Tcl_DictObjNext \
	(tclStubsPtr->tcl_DictObjNext) /* 499 */
#define Tcl_DictObjDone \
	(tclStubsPtr->tcl_DictObjDone) /* 500 */
#define Tcl_DictObjPutKeyList \
3607
3608
3609
3610
3611
3612
3613
3614
3615


3616
3617
3618
3619
3620
3621
3622
3733
3734
3735
3736
3737
3738
3739


3740
3741
3742
3743
3744
3745
3746
3747
3748







-
-
+
+







	(tclStubsPtr->tcl_GetBlocksFromStat) /* 600 */
#define Tcl_GetBlockSizeFromStat \
	(tclStubsPtr->tcl_GetBlockSizeFromStat) /* 601 */
#define Tcl_SetEnsembleParameterList \
	(tclStubsPtr->tcl_SetEnsembleParameterList) /* 602 */
#define Tcl_GetEnsembleParameterList \
	(tclStubsPtr->tcl_GetEnsembleParameterList) /* 603 */
#define Tcl_ParseArgsObjv \
	(tclStubsPtr->tcl_ParseArgsObjv) /* 604 */
#define TclParseArgsObjv \
	(tclStubsPtr->tclParseArgsObjv) /* 604 */
#define Tcl_GetErrorLine \
	(tclStubsPtr->tcl_GetErrorLine) /* 605 */
#define Tcl_SetErrorLine \
	(tclStubsPtr->tcl_SetErrorLine) /* 606 */
#define Tcl_TransferResult \
	(tclStubsPtr->tcl_TransferResult) /* 607 */
#define Tcl_InterpActive \
3671
3672
3673
3674
3675
3676
3677
3678
3679


3680
3681
3682
3683
3684
3685




3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703




















































































3704
3705
3706
3707
3708

3709
3710
3711
3712





3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743






3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763

3764
3765

3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795


















3796
3797
3798
3799
3800
3801
3802
3797
3798
3799
3800
3801
3802
3803


3804
3805
3806
3807




3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919




3920
3921
3922
3923
3924











3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938






3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963

3964
3965

3966
3967














3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981

3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006







-
-
+
+


-
-
-
-
+
+
+
+


















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-














-
-
-
-
-
-
+
+
+
+
+
+



















-
+

-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-














-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	(tclStubsPtr->tclZipfs_Mount) /* 632 */
#define TclZipfs_Unmount \
	(tclStubsPtr->tclZipfs_Unmount) /* 633 */
#define TclZipfs_TclLibrary \
	(tclStubsPtr->tclZipfs_TclLibrary) /* 634 */
#define TclZipfs_MountBuffer \
	(tclStubsPtr->tclZipfs_MountBuffer) /* 635 */
#define Tcl_FreeIntRep \
	(tclStubsPtr->tcl_FreeIntRep) /* 636 */
#define Tcl_FreeInternalRep \
	(tclStubsPtr->tcl_FreeInternalRep) /* 636 */
#define Tcl_InitStringRep \
	(tclStubsPtr->tcl_InitStringRep) /* 637 */
#define Tcl_FetchIntRep \
	(tclStubsPtr->tcl_FetchIntRep) /* 638 */
#define Tcl_StoreIntRep \
	(tclStubsPtr->tcl_StoreIntRep) /* 639 */
#define Tcl_FetchInternalRep \
	(tclStubsPtr->tcl_FetchInternalRep) /* 638 */
#define Tcl_StoreInternalRep \
	(tclStubsPtr->tcl_StoreInternalRep) /* 639 */
#define Tcl_HasStringRep \
	(tclStubsPtr->tcl_HasStringRep) /* 640 */
#define Tcl_IncrRefCount \
	(tclStubsPtr->tcl_IncrRefCount) /* 641 */
#define Tcl_DecrRefCount \
	(tclStubsPtr->tcl_DecrRefCount) /* 642 */
#define Tcl_IsShared \
	(tclStubsPtr->tcl_IsShared) /* 643 */
#define Tcl_LinkArray \
	(tclStubsPtr->tcl_LinkArray) /* 644 */
#define Tcl_GetIntForIndex \
	(tclStubsPtr->tcl_GetIntForIndex) /* 645 */
#define Tcl_UtfToUniChar \
	(tclStubsPtr->tcl_UtfToUniChar) /* 646 */
#define Tcl_UniCharToUtfDString \
	(tclStubsPtr->tcl_UniCharToUtfDString) /* 647 */
#define Tcl_UtfToUniCharDString \
	(tclStubsPtr->tcl_UtfToUniCharDString) /* 648 */
#define TclGetBytesFromObj \
	(tclStubsPtr->tclGetBytesFromObj) /* 649 */
#define Tcl_GetBytesFromObj \
	(tclStubsPtr->tcl_GetBytesFromObj) /* 650 */
#define Tcl_GetStringFromObj \
	(tclStubsPtr->tcl_GetStringFromObj) /* 651 */
#define Tcl_GetUnicodeFromObj \
	(tclStubsPtr->tcl_GetUnicodeFromObj) /* 652 */
#define Tcl_GetSizeIntFromObj \
	(tclStubsPtr->tcl_GetSizeIntFromObj) /* 653 */
#define Tcl_UtfCharComplete \
	(tclStubsPtr->tcl_UtfCharComplete) /* 654 */
#define Tcl_UtfNext \
	(tclStubsPtr->tcl_UtfNext) /* 655 */
#define Tcl_UtfPrev \
	(tclStubsPtr->tcl_UtfPrev) /* 656 */
#define Tcl_FSTildeExpand \
	(tclStubsPtr->tcl_FSTildeExpand) /* 657 */
#define Tcl_ExternalToUtfDStringEx \
	(tclStubsPtr->tcl_ExternalToUtfDStringEx) /* 658 */
#define Tcl_UtfToExternalDStringEx \
	(tclStubsPtr->tcl_UtfToExternalDStringEx) /* 659 */
#define Tcl_AsyncMarkFromSignal \
	(tclStubsPtr->tcl_AsyncMarkFromSignal) /* 660 */
#define Tcl_ListObjGetElements \
	(tclStubsPtr->tcl_ListObjGetElements) /* 661 */
#define Tcl_ListObjLength \
	(tclStubsPtr->tcl_ListObjLength) /* 662 */
#define Tcl_DictObjSize \
	(tclStubsPtr->tcl_DictObjSize) /* 663 */
#define Tcl_SplitList \
	(tclStubsPtr->tcl_SplitList) /* 664 */
#define Tcl_SplitPath \
	(tclStubsPtr->tcl_SplitPath) /* 665 */
#define Tcl_FSSplitPath \
	(tclStubsPtr->tcl_FSSplitPath) /* 666 */
#define Tcl_ParseArgsObjv \
	(tclStubsPtr->tcl_ParseArgsObjv) /* 667 */
#define Tcl_UniCharLen \
	(tclStubsPtr->tcl_UniCharLen) /* 668 */
#define Tcl_NumUtfChars \
	(tclStubsPtr->tcl_NumUtfChars) /* 669 */
#define Tcl_GetCharLength \
	(tclStubsPtr->tcl_GetCharLength) /* 670 */
#define Tcl_UtfAtIndex \
	(tclStubsPtr->tcl_UtfAtIndex) /* 671 */
#define Tcl_GetRange \
	(tclStubsPtr->tcl_GetRange) /* 672 */
#define Tcl_GetUniChar \
	(tclStubsPtr->tcl_GetUniChar) /* 673 */
#define Tcl_GetBool \
	(tclStubsPtr->tcl_GetBool) /* 674 */
#define Tcl_GetBoolFromObj \
	(tclStubsPtr->tcl_GetBoolFromObj) /* 675 */
#define Tcl_CreateObjCommand2 \
	(tclStubsPtr->tcl_CreateObjCommand2) /* 676 */
#define Tcl_CreateObjTrace2 \
	(tclStubsPtr->tcl_CreateObjTrace2) /* 677 */
#define Tcl_NRCreateCommand2 \
	(tclStubsPtr->tcl_NRCreateCommand2) /* 678 */
#define Tcl_NRCallObjProc2 \
	(tclStubsPtr->tcl_NRCallObjProc2) /* 679 */
#define Tcl_GetNumberFromObj \
	(tclStubsPtr->tcl_GetNumberFromObj) /* 680 */
#define Tcl_GetNumber \
	(tclStubsPtr->tcl_GetNumber) /* 681 */
#define Tcl_RemoveChannelMode \
	(tclStubsPtr->tcl_RemoveChannelMode) /* 682 */
#define Tcl_GetEncodingNulLength \
	(tclStubsPtr->tcl_GetEncodingNulLength) /* 683 */
#define Tcl_GetWideUIntFromObj \
	(tclStubsPtr->tcl_GetWideUIntFromObj) /* 684 */
#define Tcl_DStringToObj \
	(tclStubsPtr->tcl_DStringToObj) /* 685 */
#define Tcl_UtfNcmp \
	(tclStubsPtr->tcl_UtfNcmp) /* 686 */
#define Tcl_UtfNcasecmp \
	(tclStubsPtr->tcl_UtfNcasecmp) /* 687 */
#define Tcl_NewWideUIntObj \
	(tclStubsPtr->tcl_NewWideUIntObj) /* 688 */
#define Tcl_SetWideUIntObj \
	(tclStubsPtr->tcl_SetWideUIntObj) /* 689 */
#define TclUnusedStubEntry \
	(tclStubsPtr->tclUnusedStubEntry) /* 690 */

#endif /* defined(USE_TCL_STUBS) */

/* !END!: Do not edit above this line. */

#undef TclUnusedStubEntry
#if defined(USE_TCL_STUBS)
#   undef Tcl_CreateInterp
#   undef Tcl_Init
#   undef Tcl_ObjSetVar2

#ifdef _WIN32
#   undef Tcl_CreateFileHandler
#   undef Tcl_DeleteFileHandler
#   undef Tcl_GetOpenFile
#   define Tcl_CreateInterp() (tclStubsPtr->tcl_CreateInterp())
#   define Tcl_Init(interp) (tclStubsPtr->tcl_Init(interp))
#   define Tcl_ObjSetVar2(interp, part1, part2, newValue, flags) \
	    (tclStubsPtr->tcl_ObjSetVar2(interp, part1, part2, newValue, flags))
#endif

#if defined(_WIN32) && defined(UNICODE)
#   define Tcl_FindExecutable(arg) ((Tcl_FindExecutable)((const char *)(arg)))
#   define Tcl_MainEx Tcl_MainExW
    EXTERN TCL_NORETURN void Tcl_MainExW(int argc, wchar_t **argv,
	    Tcl_AppInitProc *appInitProc, Tcl_Interp *interp);
#endif

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#define Tcl_PkgPresent(interp, name, version, exact) \
	Tcl_PkgPresentEx(interp, name, version, exact, NULL)
#define Tcl_PkgProvide(interp, name, version) \
	Tcl_PkgProvideEx(interp, name, version, NULL)
#define Tcl_PkgRequire(interp, name, version, exact) \
	Tcl_PkgRequireEx(interp, name, version, exact, NULL)
#define Tcl_GetIndexFromObj(interp, objPtr, tablePtr, msg, flags, indexPtr) \
	Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, \
	sizeof(char *), msg, flags, indexPtr)
#define Tcl_NewBooleanObj(boolValue) \
	Tcl_NewWideIntObj((boolValue)!=0)
#define Tcl_DbNewBooleanObj(boolValue, file, line) \
	Tcl_DbNewWideIntObj((boolValue)!=0, file, line)
#define Tcl_SetBooleanObj(objPtr, boolValue) \
	Tcl_SetWideIntObj(objPtr, (boolValue)!=0)
#define Tcl_NewBooleanObj(intValue) \
	Tcl_NewWideIntObj((intValue)!=0)
#define Tcl_DbNewBooleanObj(intValue, file, line) \
	Tcl_DbNewWideIntObj((intValue)!=0, file, line)
#define Tcl_SetBooleanObj(objPtr, intValue) \
	Tcl_SetWideIntObj(objPtr, (intValue)!=0)
#define Tcl_SetVar(interp, varName, newValue, flags) \
	Tcl_SetVar2(interp, varName, NULL, newValue, flags)
#define Tcl_UnsetVar(interp, varName, flags) \
	Tcl_UnsetVar2(interp, varName, NULL, flags)
#define Tcl_GetVar(interp, varName, flags) \
	Tcl_GetVar2(interp, varName, NULL, flags)
#define Tcl_TraceVar(interp, varName, flags, proc, clientData) \
	Tcl_TraceVar2(interp, varName, NULL, flags, proc, clientData)
#define Tcl_UntraceVar(interp, varName, flags, proc, clientData) \
	Tcl_UntraceVar2(interp, varName, NULL, flags, proc, clientData)
#define Tcl_VarTraceInfo(interp, varName, flags, proc, prevClientData) \
	Tcl_VarTraceInfo2(interp, varName, NULL, flags, proc, prevClientData)
#define Tcl_UpVar(interp, frameName, varName, localName, flags) \
	Tcl_UpVar2(interp, frameName, varName, NULL, localName, flags)
#define Tcl_AddErrorInfo(interp, message) \
	Tcl_AppendObjToErrorInfo(interp, Tcl_NewStringObj(message, -1))
#define Tcl_AddObjErrorInfo(interp, message, length) \
	Tcl_AppendObjToErrorInfo(interp, Tcl_NewStringObj(message, length))
#define Tcl_Eval(interp, objPtr) \
	Tcl_EvalEx(interp, objPtr, -1, 0)
	Tcl_EvalEx(interp, objPtr, TCL_INDEX_NONE, 0)
#define Tcl_GlobalEval(interp, objPtr) \
	Tcl_EvalEx(interp, objPtr, -1, TCL_EVAL_GLOBAL)
	Tcl_EvalEx(interp, objPtr, TCL_INDEX_NONE, TCL_EVAL_GLOBAL)
#define Tcl_GetStringResult(interp) Tcl_GetString(Tcl_GetObjResult(interp))
#define Tcl_SaveResult(interp, statePtr) \
	do { \
	    *(statePtr) = Tcl_GetObjResult(interp); \
	    Tcl_IncrRefCount(*(statePtr)); \
	    Tcl_SetObjResult(interp, Tcl_NewObj()); \
	} while(0)
#define Tcl_RestoreResult(interp, statePtr) \
	do { \
	    Tcl_ResetResult(interp); \
   	    Tcl_SetObjResult(interp, *(statePtr)); \
   	    Tcl_DecrRefCount(*(statePtr)); \
	} while(0)
#define Tcl_DiscardResult(statePtr) \
	Tcl_DecrRefCount(*(statePtr))
#define Tcl_SetResult(interp, result, freeProc) \
	do { \
	    const char *__result = result; \
	    Tcl_FreeProc *__freeProc = freeProc; \
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(__result, -1)); \
	    if (__result != NULL && __freeProc != NULL && __freeProc != TCL_VOLATILE) { \
		if (__freeProc == TCL_DYNAMIC) { \
		    Tcl_Free((char *)__result); \
		} else { \
		    (*__freeProc)((char *)__result); \
		} \
	    } \
	} while(0)

#if defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS)
#if defined(USE_TCL_STUBS)
#   if defined(_WIN32) && defined(_WIN64) && TCL_MAJOR_VERSION < 9
#	undef Tcl_GetTime
/* Handle Win64 tk.dll being loaded in Cygwin64 (only needed for Tcl 8). */
#	define Tcl_GetTime(t) \
		do { \
		    struct { \
			Tcl_Time now; \
			long long reserved; \
		    } _t; \
		    _t.reserved = -1; \
		    tclStubsPtr->tcl_GetTime((&_t.now)); \
		    if (_t.reserved != -1) { \
			_t.now.usec = (long) _t.reserved; \
		    } \
		    *(t) = _t.now; \
		} while (0)
#   endif
#   if defined(__CYGWIN__) && defined(TCL_WIDE_INT_IS_LONG)
/* On Cygwin64, long is 64-bit while on Win64 long is 32-bit. Therefore
 * we have to make sure that all stub entries on Cygwin64 follow the
 * Win64 signature. Cygwin64 stubbed extensions cannot use those stub
 * entries any more, they should use the 64-bit alternatives where
 * possible. Tcl 9 must find a better solution, but that cannot be done
 * without introducing a binary incompatibility.
3817
3818
3819
3820
3821
3822
3823













































3824
3825
3826
3827
3828
3829
3830
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    int intValue;
	    int result = tclStubsPtr->tcl_ExprLongObj(interp, obj, (long *)&intValue);
	    if (result == TCL_OK) *ptr = (long)intValue;
	    return result;
	}
#   endif
#endif

#undef Tcl_GetString
#undef Tcl_GetUnicode
#define Tcl_GetString(objPtr) \
	Tcl_GetStringFromObj(objPtr, (Tcl_Size *)NULL)
#define Tcl_GetUnicode(objPtr) \
	Tcl_GetUnicodeFromObj(objPtr, (Tcl_Size *)NULL)
#undef Tcl_GetIndexFromObjStruct
#undef Tcl_GetBooleanFromObj
#undef Tcl_GetBoolean
#if !defined(TCLBOOLWARNING)
#if !defined(__cplusplus) && !defined(BUILD_tcl) && !defined(BUILD_tk) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
#	define TCLBOOLWARNING(boolPtr) (void)(sizeof(struct {_Static_assert(sizeof(*(boolPtr)) <= sizeof(int), "sizeof(boolPtr) too large");int dummy;})),
#elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
	/* If this gives: "error: size of array ‘_bool_Var’ is negative", it means that sizeof(*boolPtr)>sizeof(int), which is not allowed */
#   define TCLBOOLWARNING(boolPtr) ({__attribute__((unused)) char _bool_Var[sizeof(*(boolPtr)) <= sizeof(int) ? 1 : -1];}),
#else
#   define TCLBOOLWARNING(boolPtr)
#endif
#endif /* !TCLBOOLWARNING */
#if defined(USE_TCL_STUBS)
#define Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags, indexPtr) \
	(tclStubsPtr->tcl_GetIndexFromObjStruct((interp), (objPtr), (tablePtr), (offset), (msg), \
		(flags)|(int)(sizeof(*(indexPtr))<<1), (indexPtr)))
#define Tcl_GetBooleanFromObj(interp, objPtr, boolPtr) \
	((sizeof(*(boolPtr)) == sizeof(int) && (TCL_MAJOR_VERSION == 8)) ? tclStubsPtr->tcl_GetBooleanFromObj(interp, objPtr, (int *)(boolPtr)) : \
	((sizeof(*(boolPtr)) <= sizeof(int)) ? Tcl_GetBoolFromObj(interp, objPtr, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr)) : \
	(TCLBOOLWARNING(boolPtr)Tcl_Panic("sizeof(%s) must be <= sizeof(int)", & #boolPtr [1]),TCL_ERROR)))
#define Tcl_GetBoolean(interp, src, boolPtr) \
	((sizeof(*(boolPtr)) == sizeof(int) && (TCL_MAJOR_VERSION == 8)) ? tclStubsPtr->tcl_GetBoolean(interp, src, (int *)(boolPtr)) : \
	((sizeof(*(boolPtr)) <= sizeof(int)) ? Tcl_GetBool(interp, src, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr)) : \
	(TCLBOOLWARNING(boolPtr)Tcl_Panic("sizeof(%s) must be <= sizeof(int)", & #boolPtr [1]),TCL_ERROR)))
#else
#define Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags, indexPtr) \
	((Tcl_GetIndexFromObjStruct)((interp), (objPtr), (tablePtr), (offset), (msg), \
		(flags)|(int)(sizeof(*(indexPtr))<<1), (indexPtr)))
#define Tcl_GetBooleanFromObj(interp, objPtr, boolPtr) \
	((sizeof(*(boolPtr)) == sizeof(int) && (TCL_MAJOR_VERSION == 8)) ? Tcl_GetBooleanFromObj(interp, objPtr, (int *)(boolPtr)) : \
	((sizeof(*(boolPtr)) <= sizeof(int)) ? Tcl_GetBoolFromObj(interp, objPtr, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr)) : \
	(TCLBOOLWARNING(boolPtr)Tcl_Panic("sizeof(%s) must be <= sizeof(int)", & #boolPtr [1]),TCL_ERROR)))
#define Tcl_GetBoolean(interp, src, boolPtr) \
	((sizeof(*(boolPtr)) == sizeof(int) && (TCL_MAJOR_VERSION == 8)) ? Tcl_GetBoolean(interp, src, (int *)(boolPtr)) : \
	((sizeof(*(boolPtr)) <= sizeof(int)) ? Tcl_GetBool(interp, src, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr)) : \
	(TCLBOOLWARNING(boolPtr)Tcl_Panic("sizeof(%s) must be <= sizeof(int)", & #boolPtr [1]),TCL_ERROR)))
#endif

#ifdef TCL_MEM_DEBUG
#   undef Tcl_Alloc
#   define Tcl_Alloc(x) \
    (Tcl_DbCkalloc((x), __FILE__, __LINE__))
#   undef Tcl_Free
#   define Tcl_Free(x) \
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852

3853
3854
3855
3856
3857
3858
























3859
3860
3861
3862
3863


3864
3865
3866


3867
3868
3869





3870
3871
3872
3873


3874
3875
3876


3877
3878
3879





3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893


3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914

3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928

3929
3930

3931
3932
3933

3934
3935
3936
3937
3938
3939


























































































































































3940
4090
4091
4092
4093
4094
4095
4096

4097
4098
4099

4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133


4134
4135
4136


4137
4138
4139


4140
4141
4142
4143
4144
4145
4146


4147
4148
4149


4150
4151
4152


4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168



4169
4170





















4171










4172
4173


4174


4175



4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
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







-



-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
+
+

-
-
+
+

-
-
+
+
+
+
+


-
-
+
+

-
-
+
+

-
-
+
+
+
+
+











-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-


-
-
+
-
-
+
-
-
-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

#endif /* !TCL_MEM_DEBUG */

#define Tcl_NewLongObj(value) Tcl_NewWideIntObj((long)(value))
#define Tcl_NewIntObj(value) Tcl_NewWideIntObj((int)(value))
#define Tcl_DbNewLongObj(value, file, line) Tcl_DbNewWideIntObj((long)(value), file, line)
#define Tcl_SetIntObj(objPtr, value)	Tcl_SetWideIntObj((objPtr), (int)(value))
#define Tcl_SetLongObj(objPtr, value)	Tcl_SetWideIntObj((objPtr), (long)(value))
#define Tcl_GetUnicode(objPtr)	Tcl_GetUnicodeFromObj((objPtr), NULL)
#define Tcl_BackgroundError(interp)	Tcl_BackgroundException((interp), TCL_ERROR)
#define Tcl_StringMatch(str, pattern) Tcl_StringCaseMatch((str), (pattern), 0)

#if TCL_UTF_MAX <= 3
#if TCL_UTF_MAX < 4
#   undef Tcl_UniCharToUtfDString
#   define Tcl_UniCharToUtfDString Tcl_Char16ToUtfDString
#   undef Tcl_UtfToUniCharDString
#   define Tcl_UtfToUniCharDString Tcl_UtfToChar16DString
#   undef Tcl_UtfToUniChar
#   define Tcl_UtfToUniChar Tcl_UtfToChar16
#   undef Tcl_UniCharLen
#   define Tcl_UniCharLen Tcl_Char16Len
#   undef Tcl_UniCharToUtf
#   if defined(USE_TCL_STUBS)
#	define Tcl_UniCharToUtf(c, p) \
		(tclStubsPtr->tcl_UniCharToUtf((c)|TCL_COMBINE, (p)))
#   else
#	define Tcl_UniCharToUtf(c, p) \
		((Tcl_UniCharToUtf)((c)|TCL_COMBINE, (p)))
#   endif
#   undef Tcl_NumUtfChars
#   define Tcl_NumUtfChars TclNumUtfChars
#   undef Tcl_GetCharLength
#   define Tcl_GetCharLength TclGetCharLength
#   undef Tcl_UtfAtIndex
#   define Tcl_UtfAtIndex TclUtfAtIndex
#   undef Tcl_GetRange
#   define Tcl_GetRange TclGetRange
#   undef Tcl_GetUniChar
#   define Tcl_GetUniChar TclGetUniChar
#   undef Tcl_UtfNcmp
#   define Tcl_UtfNcmp TclUtfNcmp
#   undef Tcl_UtfNcasecmp
#   define Tcl_UtfNcasecmp TclUtfNcasecmp
#endif
#if defined(USE_TCL_STUBS)
#   define Tcl_WCharToUtfDString (sizeof(wchar_t) != sizeof(short) \
		? (char *(*)(const wchar_t *, size_t, Tcl_DString *))tclStubsPtr->tcl_UniCharToUtfDString \
		: (char *(*)(const wchar_t *, size_t, Tcl_DString *))Tcl_Char16ToUtfDString)
		? (char *(*)(const wchar_t *, Tcl_Size, Tcl_DString *))tclStubsPtr->tcl_UniCharToUtfDString \
		: (char *(*)(const wchar_t *, Tcl_Size, Tcl_DString *))Tcl_Char16ToUtfDString)
#   define Tcl_UtfToWCharDString (sizeof(wchar_t) != sizeof(short) \
		? (wchar_t *(*)(const char *, size_t, Tcl_DString *))tclStubsPtr->tcl_UtfToUniCharDString \
		: (wchar_t *(*)(const char *, size_t, Tcl_DString *))Tcl_UtfToChar16DString)
		? (wchar_t *(*)(const char *, Tcl_Size, Tcl_DString *))tclStubsPtr->tcl_UtfToUniCharDString \
		: (wchar_t *(*)(const char *, Tcl_Size, Tcl_DString *))Tcl_UtfToChar16DString)
#   define Tcl_UtfToWChar (sizeof(wchar_t) != sizeof(short) \
		? (int (*)(const char *, wchar_t *))tclStubsPtr->tcl_UtfToChar16 \
		: (int (*)(const char *, wchar_t *))Tcl_UtfToUniChar)
		? (Tcl_Size (*)(const char *, wchar_t *))tclStubsPtr->tcl_UtfToUniChar \
		: (Tcl_Size (*)(const char *, wchar_t *))Tcl_UtfToChar16)
#   define Tcl_WCharLen (sizeof(wchar_t) != sizeof(short) \
		? (Tcl_Size (*)(wchar_t *))tclStubsPtr->tcl_UniCharLen \
		: (Tcl_Size (*)(wchar_t *))Tcl_Char16Len)
#else
#   define Tcl_WCharToUtfDString (sizeof(wchar_t) != sizeof(short) \
		? (char *(*)(const wchar_t *, size_t, Tcl_DString *))Tcl_UniCharToUtfDString \
		: (char *(*)(const wchar_t *, size_t, Tcl_DString *))Tcl_Char16ToUtfDString)
		? (char *(*)(const wchar_t *, Tcl_Size, Tcl_DString *))Tcl_UniCharToUtfDString \
		: (char *(*)(const wchar_t *, Tcl_Size, Tcl_DString *))Tcl_Char16ToUtfDString)
#   define Tcl_UtfToWCharDString (sizeof(wchar_t) != sizeof(short) \
		? (wchar_t *(*)(const char *, size_t, Tcl_DString *))Tcl_UtfToUniCharDString \
		: (wchar_t *(*)(const char *, size_t, Tcl_DString *))Tcl_UtfToChar16DString)
		? (wchar_t *(*)(const char *, Tcl_Size, Tcl_DString *))Tcl_UtfToUniCharDString \
		: (wchar_t *(*)(const char *, Tcl_Size, Tcl_DString *))Tcl_UtfToChar16DString)
#   define Tcl_UtfToWChar (sizeof(wchar_t) != sizeof(short) \
		? (int (*)(const char *, wchar_t *))Tcl_UtfToChar16 \
		: (int (*)(const char *, wchar_t *))Tcl_UtfToUniChar)
		? (Tcl_Size (*)(const char *, wchar_t *))Tcl_UtfToUniChar \
		: (Tcl_Size (*)(const char *, wchar_t *))Tcl_UtfToChar16)
#   define Tcl_WCharLen (sizeof(wchar_t) != sizeof(short) \
		? (Tcl_Size (*)(wchar_t *))Tcl_UniCharLen \
		: (Tcl_Size (*)(wchar_t *))Tcl_Char16Len)
#endif

/*
 * Deprecated Tcl procedures:
 */

#define Tcl_EvalObj(interp, objPtr) \
    Tcl_EvalObjEx(interp, objPtr, 0)
#define Tcl_GlobalEvalObj(interp, objPtr) \
    Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL)

#if defined(TCL_8_COMPAT) && !defined(BUILD_tcl)
#   ifdef USE_TCL_STUBS
#	undef Tcl_Gets
#if TCL_MAJOR_VERSION > 8
#   undef Tcl_Close
#	undef Tcl_GetsObj
#	undef Tcl_Read
#	undef Tcl_Ungets
#	undef Tcl_Write
#	undef Tcl_ReadChars
#	undef Tcl_WriteChars
#	undef Tcl_WriteObj
#	undef Tcl_ReadRaw
#	undef Tcl_WriteRaw
#	define Tcl_Gets(chan, dsPtr) (((Tcl_WideInt)((tclStubsPtr->tcl_Gets)(chan, dsPtr)+1))-1)
#	define Tcl_GetsObj(chan, objPtr) (((Tcl_WideInt)((tclStubsPtr->tcl_GetsObj)(chan, objPtr)+1))-1)
#	define Tcl_Read(chan, bufPtr, toRead) (((Tcl_WideInt)((tclStubsPtr->tcl_Read)(chan, bufPtr, toRead)+1))-1)
#	define Tcl_Ungets(chan, str, len, atHead) (((Tcl_WideInt)((tclStubsPtr->tcl_Ungets)(chan, str, len, atHead)+1))-1)
#	define Tcl_Write(chan, s, slen) (((Tcl_WideInt)((tclStubsPtr->tcl_Write)(chan, s, slen)+1))-1)
#	define Tcl_ReadChars(channel, objPtr, charsToRead, appendFlag) (((Tcl_WideInt)((tclStubsPtr->tcl_ReadChars)(channel, objPtr, charsToRead, appendFlag)+1))-1)
#	define Tcl_WriteChars(chan, src, srcLen) (((Tcl_WideInt)((tclStubsPtr->tcl_WriteChars)(chan, src, srcLen)+1))-1)
#	define Tcl_WriteObj(chan, objPtr) (((Tcl_WideInt)((tclStubsPtr->tcl_WriteObj)(chan, objPtr)+1))-1)
#	define Tcl_ReadRaw(chan, dst, bytesToRead) (((Tcl_WideInt)((tclStubsPtr->tcl_ReadRaw)(chan, dst, bytesToRead)+1))-1)
#	define Tcl_WriteRaw(chan, src, srcLen) (((Tcl_WideInt)((tclStubsPtr->tcl_WriteRaw()(chan, src, srcLen)+1))-1)
#   else
#	define Tcl_Gets(chan, dsPtr) (((Tcl_WideInt)((Tcl_Gets)(chan, dsPtr)+1))-1)
#   define Tcl_Close(interp, chan) Tcl_CloseEx(interp, chan, 0)
#	define Tcl_GetsObj(chan, objPtr) (((Tcl_WideInt)((Tcl_GetsObj)(chan, objPtr)+1))-1)
#	define Tcl_Read(chan, bufPtr, toRead) (((Tcl_WideInt)((Tcl_Read)(chan, bufPtr, toRead)+1))-1)
#	define Tcl_Ungets(chan, str, len, atHead) (((Tcl_WideInt)((Tcl_Ungets)(chan, str, len, atHead)+1))-1)
#	define Tcl_Write(chan, s, slen) (((Tcl_WideInt)((Tcl_Write)(chan, s, slen)+1))-1)
#	define Tcl_ReadChars(channel, objPtr, charsToRead, appendFlag) (((Tcl_WideInt)((Tcl_ReadChars)(channel, objPtr, charsToRead, appendFlag)+1))-1)
#	define Tcl_WriteChars(chan, src, srcLen) (((Tcl_WideInt)((Tcl_WriteChars)(chan, src, srcLen)+1))-1)
#	define Tcl_WriteObj(chan, objPtr) (((Tcl_WideInt)((Tcl_WriteObj)(chan, objPtr)+1))-1)
#	define Tcl_ReadRaw(chan, dst, bytesToRead) (((Tcl_WideInt)((Tcl_ReadRaw)(chan, dst, bytesToRead)+1))-1)
#	define Tcl_WriteRaw(chan, src, srcLen) (((Tcl_WideInt)((Tcl_WriteRaw()(chan, src, srcLen)+1))-1)
#   endif
#endif

#define Tcl_Close(interp, chan) Tcl_CloseEx(interp, chan, 0)

#undef TclUtfCharComplete
#if defined(USE_TCL_STUBS) && (TCL_UTF_MAX <= 3)
#   undef Tcl_UtfCharComplete
#undef TclUtfNext
#   define Tcl_UtfCharComplete(src, length) (((unsigned)((unsigned char)*(src) - 0xF0) < 5) \
	    ? ((length) >= TCL_UTF_MAX) : tclStubsPtr->tcl_UtfCharComplete((src), (length)))
#endif
#undef TclUtfPrev
#ifndef TCL_NO_DEPRECATED
#   define Tcl_CreateSlave Tcl_CreateChild
#   define Tcl_GetSlave Tcl_GetChild
#   define Tcl_GetMaster Tcl_GetParent
#endif

/* Protect those 11 functions, make them useless through the stub table */
#undef TclGetStringFromObj
#undef TclGetBytesFromObj
#undef TclGetUnicodeFromObj
#undef TclListObjGetElements
#undef TclListObjLength
#undef TclDictObjSize
#undef TclSplitList
#undef TclSplitPath
#undef TclFSSplitPath
#undef TclParseArgsObjv
#undef TclGetAliasObj

#if TCL_MAJOR_VERSION < 9
    /* TIP #627 for 8.7 */
#   undef Tcl_CreateObjCommand2
#   define Tcl_CreateObjCommand2 Tcl_CreateObjCommand
#   undef Tcl_CreateObjTrace2
#   define Tcl_CreateObjTrace2 Tcl_CreateObjTrace
#   undef Tcl_NRCreateCommand2
#   define Tcl_NRCreateCommand2 Tcl_NRCreateCommand
#   undef Tcl_NRCallObjProc2
#   define Tcl_NRCallObjProc2 Tcl_NRCallObjProc
    /* TIP #660 for 8.7 */
#   undef Tcl_GetSizeIntFromObj
#   define Tcl_GetSizeIntFromObj Tcl_GetIntFromObj

#   undef Tcl_GetBytesFromObj
#   define Tcl_GetBytesFromObj(interp, objPtr, sizePtr) \
	    tclStubsPtr->tclGetBytesFromObj((interp), (objPtr), (sizePtr))
#   undef Tcl_GetStringFromObj
#   define Tcl_GetStringFromObj(objPtr, sizePtr) \
	    tclStubsPtr->tclGetStringFromObj((objPtr), (sizePtr))
#   undef Tcl_GetUnicodeFromObj
#   define Tcl_GetUnicodeFromObj(objPtr, sizePtr) \
	    tclStubsPtr->tclGetUnicodeFromObj((objPtr), (sizePtr))
#   undef Tcl_ListObjGetElements
#   define Tcl_ListObjGetElements(interp, listPtr, objcPtr, objvPtr) \
	    tclStubsPtr->tclListObjGetElements((interp), (listPtr), (objcPtr), (objvPtr))
#   undef Tcl_ListObjLength
#   define Tcl_ListObjLength(interp, listPtr, lengthPtr) \
	    tclStubsPtr->tclListObjLength((interp), (listPtr), (lengthPtr))
#   undef Tcl_DictObjSize
#   define Tcl_DictObjSize(interp, dictPtr, sizePtr) \
	    tclStubsPtr->tclDictObjSize((interp), (dictPtr), (sizePtr))
#   undef Tcl_SplitList
#   define Tcl_SplitList(interp, listStr, argcPtr, argvPtr) \
	    tclStubsPtr->tclSplitList((interp), (listStr), (argcPtr), (argvPtr))
#   undef Tcl_SplitPath
#   define Tcl_SplitPath(path, argcPtr, argvPtr) \
	    tclStubsPtr->tclSplitPath((path), (argcPtr), (argvPtr))
#   undef Tcl_FSSplitPath
#   define Tcl_FSSplitPath(pathPtr, lenPtr) \
	    tclStubsPtr->tclFSSplitPath((pathPtr), (lenPtr))
#   undef Tcl_ParseArgsObjv
#   define Tcl_ParseArgsObjv(interp, argTable, objcPtr, objv, remObjv) \
	    tclStubsPtr->tclParseArgsObjv((interp), (argTable), (objcPtr), (objv), (remObjv))
#   undef Tcl_GetAliasObj
#   define Tcl_GetAliasObj(interp, childCmd, targetInterpPtr, targetCmdPtr, objcPtr, objv) \
	    tclStubsPtr->tclGetAliasObj((interp), (childCmd), (targetInterpPtr), (targetCmdPtr), (objcPtr), (objv))
#elif defined(TCL_8_API)
#   undef Tcl_GetByteArrayFromObj
#   undef Tcl_GetBytesFromObj
#   undef Tcl_GetStringFromObj
#   undef Tcl_GetUnicodeFromObj
#   undef Tcl_ListObjGetElements
#   undef Tcl_ListObjLength
#   undef Tcl_DictObjSize
#   undef Tcl_SplitList
#   undef Tcl_SplitPath
#   undef Tcl_FSSplitPath
#   undef Tcl_ParseArgsObjv
#   undef Tcl_GetAliasObj
#   if !defined(USE_TCL_STUBS)
#	define Tcl_GetByteArrayFromObj(objPtr, sizePtr) (sizeof(*(sizePtr)) <= sizeof(int) ? \
		TclGetBytesFromObj(NULL, (objPtr), (sizePtr)) : \
		(Tcl_GetBytesFromObj)(NULL, (objPtr), (Tcl_Size *)(void *)(sizePtr)))
#	define Tcl_GetBytesFromObj(interp, objPtr, sizePtr) (sizeof(*(sizePtr)) <= sizeof(int) ? \
		TclGetBytesFromObj((interp), (objPtr), (sizePtr)) : \
		(Tcl_GetBytesFromObj)((interp), (objPtr), (Tcl_Size *)(void *)(sizePtr)))
#	define Tcl_GetStringFromObj(objPtr, sizePtr) (sizeof(*(sizePtr)) <= sizeof(int) ? \
		(TclGetStringFromObj)((objPtr), (sizePtr)) : \
		(Tcl_GetStringFromObj)((objPtr), (Tcl_Size *)(void *)(sizePtr)))
#	define Tcl_GetUnicodeFromObj(objPtr, sizePtr) (sizeof(*(sizePtr)) <= sizeof(int) ? \
		TclGetUnicodeFromObj((objPtr), (sizePtr)) : \
		(Tcl_GetUnicodeFromObj)((objPtr), (Tcl_Size *)(void *)(sizePtr)))
#	define Tcl_ListObjGetElements(interp, listPtr, objcPtr, objvPtr) (sizeof(*(objcPtr)) <= sizeof(int) ? \
		(TclListObjGetElements)((interp), (listPtr), (objcPtr), (objvPtr)) : \
		(Tcl_ListObjGetElements)((interp), (listPtr), (Tcl_Size *)(void *)(objcPtr), (objvPtr)))
#	define Tcl_ListObjLength(interp, listPtr, lengthPtr) (sizeof(*(lengthPtr)) <= sizeof(int) ? \
		(TclListObjLength)((interp), (listPtr), (lengthPtr)) : \
		(Tcl_ListObjLength)((interp), (listPtr), (Tcl_Size *)(void *)(lengthPtr)))
#	define Tcl_DictObjSize(interp, dictPtr, sizePtr) (sizeof(*(sizePtr)) <= sizeof(int) ? \
		TclDictObjSize((interp), (dictPtr), (sizePtr)) : \
		(Tcl_DictObjSize)((interp), (dictPtr), (Tcl_Size *)(void *)(sizePtr)))
#	define Tcl_SplitList(interp, listStr, argcPtr, argvPtr) (sizeof(*(argcPtr)) <= sizeof(int) ? \
		TclSplitList((interp), (listStr), (argcPtr), (argvPtr)) : \
		(Tcl_SplitList)((interp), (listStr), (Tcl_Size *)(void *)(argcPtr), (argvPtr)))
#	define Tcl_SplitPath(path, argcPtr, argvPtr) (sizeof(*(argcPtr)) <= sizeof(int) ? \
		TclSplitPath((path), (argcPtr), (argvPtr)) : \
		(Tcl_SplitPath)((path), (Tcl_Size *)(void *)(argcPtr), (argvPtr)))
#	define Tcl_FSSplitPath(pathPtr, lenPtr) (sizeof(*(lenPtr)) <= sizeof(int) ? \
		TclFSSplitPath((pathPtr), (lenPtr)) : \
		(Tcl_FSSplitPath)((pathPtr), (Tcl_Size *)(void *)(lenPtr)))
#	define Tcl_ParseArgsObjv(interp, argTable, objcPtr, objv, remObjv) (sizeof(*(objcPtr)) <= sizeof(int) ? \
		TclParseArgsObjv((interp), (argTable), (objcPtr), (objv), (remObjv)) : \
		(Tcl_ParseArgsObjv)((interp), (argTable), (Tcl_Size *)(void *)(objcPtr), (objv), (remObjv)))
#	define Tcl_GetAliasObj(interp, childCmd, targetInterpPtr, targetCmdPtr, objcPtr, objv) (sizeof(*(objcPtr)) <= sizeof(int) ? \
		TclGetAliasObj((interp), (childCmd), (targetInterpPtr), (targetCmdPtr), (objcPtr), (objv)) : \
		(Tcl_GetAliasObj)((interp), (childCmd), (targetInterpPtr), (targetCmdPtr), (Tcl_Size *)(void *)(objcPtr), (objv)))
#   elif !defined(BUILD_tcl)
#	define Tcl_GetByteArrayFromObj(objPtr, sizePtr) (sizeof(*(sizePtr)) <= sizeof(int) ? \
		tclStubsPtr->tclGetBytesFromObj(NULL, (objPtr), (sizePtr)) : \
		tclStubsPtr->tcl_GetBytesFromObj(NULL, (objPtr), (Tcl_Size *)(void *)(sizePtr)))
#	define Tcl_GetBytesFromObj(interp, objPtr, sizePtr) (sizeof(*(sizePtr)) <= sizeof(int) ? \
		tclStubsPtr->tclGetBytesFromObj((interp), (objPtr), (sizePtr)) : \
		tclStubsPtr->tcl_GetBytesFromObj((interp), (objPtr), (Tcl_Size *)(void *)(sizePtr)))
#	define Tcl_GetStringFromObj(objPtr, sizePtr) (sizeof(*(sizePtr)) <= sizeof(int) ? \
		tclStubsPtr->tclGetStringFromObj((objPtr), (sizePtr)) : \
		tclStubsPtr->tcl_GetStringFromObj((objPtr), (Tcl_Size *)(void *)(sizePtr)))
#	define Tcl_GetUnicodeFromObj(objPtr, sizePtr) (sizeof(*(sizePtr)) <= sizeof(int) ? \
		tclStubsPtr->tclGetUnicodeFromObj((objPtr), (sizePtr)) : \
		tclStubsPtr->tcl_GetUnicodeFromObj((objPtr), (Tcl_Size *)(void *)(sizePtr)))
#	define Tcl_ListObjGetElements(interp, listPtr, objcPtr, objvPtr) (sizeof(*(objcPtr)) <= sizeof(int) ? \
		tclStubsPtr->tclListObjGetElements((interp), (listPtr), (objcPtr), (objvPtr)) : \
		tclStubsPtr->tcl_ListObjGetElements((interp), (listPtr), (Tcl_Size *)(void *)(objcPtr), (objvPtr)))
#	define Tcl_ListObjLength(interp, listPtr, lengthPtr) (sizeof(*(lengthPtr)) <= sizeof(int) ? \
		tclStubsPtr->tclListObjLength((interp), (listPtr), (lengthPtr)) : \
		tclStubsPtr->tcl_ListObjLength((interp), (listPtr), (Tcl_Size *)(void *)(lengthPtr)))
#	define Tcl_DictObjSize(interp, dictPtr, sizePtr) (sizeof(*(sizePtr)) <= sizeof(int) ? \
		tclStubsPtr->tclDictObjSize((interp), (dictPtr), (sizePtr)) : \
		tclStubsPtr->tcl_DictObjSize((interp), (dictPtr), (Tcl_Size *)(void *)(sizePtr)))
#	define Tcl_SplitList(interp, listStr, argcPtr, argvPtr) (sizeof(*(argcPtr)) <= sizeof(int) ? \
		tclStubsPtr->tclSplitList((interp), (listStr), (argcPtr), (argvPtr)) : \
		tclStubsPtr->tcl_SplitList((interp), (listStr), (Tcl_Size *)(void *)(argcPtr), (argvPtr)))
#	define Tcl_SplitPath(path, argcPtr, argvPtr) (sizeof(*(argcPtr)) <= sizeof(int) ? \
		tclStubsPtr->tclSplitPath((path), (argcPtr), (argvPtr)) : \
		tclStubsPtr->tcl_SplitPath((path), (Tcl_Size *)(void *)(argcPtr), (argvPtr)))
#	define Tcl_FSSplitPath(pathPtr, lenPtr) (sizeof(*(lenPtr)) <= sizeof(int) ? \
		tclStubsPtr->tclFSSplitPath((pathPtr), (lenPtr)) : \
		tclStubsPtr->tcl_FSSplitPath((pathPtr), (Tcl_Size *)(void *)(lenPtr)))
#	define Tcl_ParseArgsObjv(interp, argTable, objcPtr, objv, remObjv) (sizeof(*(objcPtr)) <= sizeof(int) ? \
		tclStubsPtr->tclParseArgsObjv((interp), (argTable), (objcPtr), (objv), (remObjv)) : \
		tclStubsPtr->tcl_ParseArgsObjv((interp), (argTable), (Tcl_Size *)(void *)(objcPtr), (objv), (remObjv)))
#	define Tcl_GetAliasObj(interp, childCmd, targetInterpPtr, targetCmdPtr, objcPtr, objv) (sizeof(*(objcPtr)) <= sizeof(int) ? \
		tclStubsPtr->tclGetAliasObj((interp), (childCmd), (targetInterpPtr), (targetCmdPtr), (objcPtr), (objv)) : \
		tclStubsPtr->tcl_GetAliasObj((interp), (childCmd), (targetInterpPtr), (targetCmdPtr), (Tcl_Size *)(void *)(objcPtr), (objv)))
#   endif /* defined(USE_TCL_STUBS) */
#else /* !defined(TCL_8_API) */
#   undef Tcl_GetByteArrayFromObj
#   define Tcl_GetByteArrayFromObj(objPtr, sizePtr) \
	   Tcl_GetBytesFromObj(NULL, (objPtr), (sizePtr))
#endif /* defined(TCL_8_API) */

#endif /* _TCLDECLS */

Changes to generic/tclDictObj.c.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tclDictObj.c --
 *
 *	This file contains functions that implement the Tcl dict object type
 *	and its accessor command.
 *
 * Copyright (c) 2002-2010 by Donal K. Fellows.
 * Copyright © 2002-2010 Donal K. Fellows.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclTomMath.h"
76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
76
77
78
79
80
81
82

83
84
85
86
87
88
89
90







-
+







    {"getdef",	DictGetDefCmd,	TclCompileDictGetWithDefaultCmd, NULL,NULL,0},
    {"getwithdefault",	DictGetDefCmd,	TclCompileDictGetWithDefaultCmd,
	NULL, NULL, 0 },
    {"incr",	DictIncrCmd,	TclCompileDictIncrCmd, NULL, NULL, 0 },
    {"info",	DictInfoCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 0 },
    {"keys",	DictKeysCmd,	TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 },
    {"lappend",	DictLappendCmd,	TclCompileDictLappendCmd, NULL, NULL, 0 },
    {"map", 	NULL,       	TclCompileDictMapCmd, DictMapNRCmd, NULL, 0 },
    {"map",	NULL,		TclCompileDictMapCmd, DictMapNRCmd, NULL, 0 },
    {"merge",	DictMergeCmd,	TclCompileDictMergeCmd, NULL, NULL, 0 },
    {"remove",	DictRemoveCmd,	TclCompileBasicMin1ArgCmd, NULL, NULL, 0 },
    {"replace",	DictReplaceCmd, NULL, NULL, NULL, 0 },
    {"set",	DictSetCmd,	TclCompileDictSetCmd, NULL, NULL, 0 },
    {"size",	DictSizeCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 0 },
    {"unset",	DictUnsetCmd,	TclCompileDictUnsetCmd, NULL, NULL, 0 },
    {"update",	DictUpdateCmd,	TclCompileDictUpdateCmd, NULL, NULL, 0 },
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
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







-
-
-
-
+
+
+
+
+


-
+

-
-
-
-
+
+
+
+


-
+

-
-
-
+
+
+














-
+







/*
 * The structure below defines the dictionary object type by means of
 * functions that can be invoked by generic object code.
 */

const Tcl_ObjType tclDictType = {
    "dict",
    FreeDictInternalRep,		/* freeIntRepProc */
    DupDictInternalRep,			/* dupIntRepProc */
    UpdateStringOfDict,			/* updateStringProc */
    SetDictFromAny			/* setFromAnyProc */
    FreeDictInternalRep,	/* freeIntRepProc */
    DupDictInternalRep,		/* dupIntRepProc */
    UpdateStringOfDict,		/* updateStringProc */
    SetDictFromAny,		/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

#define DictSetIntRep(objPtr, dictRepPtr)				\
#define DictSetInternalRep(objPtr, dictRepPtr)				\
    do {                                                                \
        Tcl_ObjIntRep ir;                                               \
        ir.twoPtrValue.ptr1 = (dictRepPtr);                             \
        ir.twoPtrValue.ptr2 = NULL;                                     \
        Tcl_StoreIntRep((objPtr), &tclDictType, &ir);                   \
	Tcl_ObjInternalRep ir;						\
	ir.twoPtrValue.ptr1 = (dictRepPtr);                             \
	ir.twoPtrValue.ptr2 = NULL;                                     \
	Tcl_StoreInternalRep((objPtr), &tclDictType, &ir);		\
    } while (0)

#define DictGetIntRep(objPtr, dictRepPtr)				\
#define DictGetInternalRep(objPtr, dictRepPtr)				\
    do {                                                                \
        const Tcl_ObjIntRep *irPtr;                                     \
        irPtr = TclFetchIntRep((objPtr), &tclDictType);                \
        (dictRepPtr) = irPtr ? (Dict *)irPtr->twoPtrValue.ptr1 : NULL;          \
	const Tcl_ObjInternalRep *irPtr;				\
	irPtr = TclFetchInternalRep((objPtr), &tclDictType);		\
	(dictRepPtr) = irPtr ? (Dict *)irPtr->twoPtrValue.ptr1 : NULL;	\
    } while (0)

/*
 * The type of the specially adapted version of the Tcl_Obj*-containing hash
 * table defined in the tclObj.c code. This version differs in that it
 * allocates a bit more space in each hash entry in order to hold the pointers
 * used to keep the hash entries in a linked list.
 *
 * Note that this type of hash table is *only* suitable for direct use in
 * *this* file. Everything else should use the dict iterator API.
 */

static const Tcl_HashKeyType chainHashType = {
    TCL_HASH_KEY_TYPE_VERSION,
    0,
    TCL_HASH_KEY_DIRECT_COMPARE,        /* allows compare keys by pointers */
    TclHashObjKey,
    TclCompareObjKeys,
    AllocChainEntry,
    TclFreeObjEntry
};

/*
358
359
360
361
362
363
364
365

366
367
368
369
370
371
372
359
360
361
362
363
364
365

366
367
368
369
370
371
372
373







-
+







DupDictInternalRep(
    Tcl_Obj *srcPtr,
    Tcl_Obj *copyPtr)
{
    Dict *oldDict, *newDict = (Dict *)Tcl_Alloc(sizeof(Dict));
    ChainEntry *cPtr;

    DictGetIntRep(srcPtr, oldDict);
    DictGetInternalRep(srcPtr, oldDict);

    /*
     * Copy values across from the old hash table.
     */

    InitChainTable(newDict);
    for (cPtr=oldDict->entryChainHead ; cPtr!=NULL ; cPtr=cPtr->nextPtr) {
391
392
393
394
395
396
397
398

399
400
401
402
403
404
405
392
393
394
395
396
397
398

399
400
401
402
403
404
405
406







-
+







    newDict->chain = NULL;
    newDict->refCount = 1;

    /*
     * Store in the object.
     */

    DictSetIntRep(copyPtr, newDict);
    DictSetInternalRep(copyPtr, newDict);
}

/*
 *----------------------------------------------------------------------
 *
 * FreeDictInternalRep --
 *
418
419
420
421
422
423
424
425

426
427
428
429
430
431
432
419
420
421
422
423
424
425

426
427
428
429
430
431
432
433







-
+








static void
FreeDictInternalRep(
    Tcl_Obj *dictPtr)
{
    Dict *dict;

    DictGetIntRep(dictPtr, dict);
    DictGetInternalRep(dictPtr, dict);

    if (dict->refCount-- <= 1) {
	DeleteDict(dict);
    }
}

/*
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
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







+
-
+








-
+

-
+







    Tcl_Obj *dictPtr)
{
#define LOCAL_SIZE 64
    char localFlags[LOCAL_SIZE], *flagPtr = NULL;
    Dict *dict;
    ChainEntry *cPtr;
    Tcl_Obj *keyPtr, *valuePtr;
    Tcl_Size i, length;
    size_t i, length, bytesNeeded = 0;
    size_t bytesNeeded = 0;
    const char *elem;
    char *dst;

    /*
     * This field is the most useful one in the whole hash structure, and it
     * is not exposed by any API function...
     */

    size_t numElems;
    Tcl_Size numElems;

    DictGetIntRep(dictPtr, dict);
    DictGetInternalRep(dictPtr, dict);

    assert (dict != NULL);

    numElems = dict->table.numEntries * 2;

    /* Handle empty list case first, simplifies what follows */
    if (numElems == 0) {
552
553
554
555
556
557
558

559
560
561
562
563
564
565
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568







+








	flagPtr[i+1] |= TCL_DONT_QUOTE_HASH;
	valuePtr = (Tcl_Obj *)Tcl_GetHashValue(&cPtr->entry);
	elem = TclGetStringFromObj(valuePtr, &length);
	dst += TclConvertElement(elem, length, dst, flagPtr[i+1]);
	*dst++ = ' ';
    }
    /* Last space overwrote the terminating NUL; cal T_ISR again to restore */
    (void)Tcl_InitStringRep(dictPtr, NULL, bytesNeeded - 1);

    if (flagPtr != localFlags) {
	Tcl_Free(flagPtr);
    }
}

596
597
598
599
600
601
602
603
604


605
606
607
608
609
610
611
599
600
601
602
603
604
605


606
607
608
609
610
611
612
613
614







-
-
+
+








    /*
     * Since lists and dictionaries have very closely-related string
     * representations (i.e. the same parsing code) we can safely special-case
     * the conversion from lists to dictionaries.
     */

    if (TclHasIntRep(objPtr, &tclListType)) {
	int objc, i;
    if (TclHasInternalRep(objPtr, &tclListType)) {
	Tcl_Size objc, i;
	Tcl_Obj **objv;

	/* Cannot fail, we already know the Tcl_ObjType is "list". */
	TclListObjGetElements(NULL, objPtr, &objc, &objv);
	if (objc & 1) {
	    goto missingValue;
	}
627
628
629
630
631
632
633
634

635
636
637
638
639
640
641

642
643
644
645
646
647
648
630
631
632
633
634
635
636

637
638
639
640
641
642
643

644
645
646
647
648
649
650
651







-
+






-
+








		TclDecrRefCount(discardedValue);
	    }
	    Tcl_SetHashValue(hPtr, objv[i+1]);
	    Tcl_IncrRefCount(objv[i+1]); /* Since hash now holds ref to it */
	}
    } else {
	size_t length;
	Tcl_Size length;
	const char *nextElem = TclGetStringFromObj(objPtr, &length);
	const char *limit = (nextElem + length);

	while (nextElem < limit) {
	    Tcl_Obj *keyPtr, *valuePtr;
	    const char *elemStart;
	    size_t elemSize;
	    Tcl_Size elemSize;
	    int literal;

	    if (TclFindDictElement(interp, nextElem, (limit - nextElem),
		    &elemStart, &nextElem, &elemSize, &literal) != TCL_OK) {
		goto errorInFindDictElement;
	    }
	    if (elemStart == limit) {
704
705
706
707
708
709
710
711

712
713
714
715
716
717
718

719
720
721
722
723
724
725
726
727
728
729
730
731
732
733

734
735
736
737
738

739
740
741
742
743
744
745
707
708
709
710
711
712
713

714
715
716
717
718
719
720

721
722
723
724
725
726
727
728
729
730
731
732
733
734
735

736
737
738
739
740

741
742
743
744
745
746
747
748







-
+






-
+














-
+




-
+







     * as possible to allow the conversion code, in particular
     * Tcl_GetStringFromObj, to use that old internalRep.
     */

    dict->epoch = 1;
    dict->chain = NULL;
    dict->refCount = 1;
    DictSetIntRep(objPtr, dict);
    DictSetInternalRep(objPtr, dict);
    return TCL_OK;

  missingValue:
    if (interp != NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"missing value to go with key", -1));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "DICTIONARY", NULL);
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "DICTIONARY", (char *)NULL);
    }
  errorInFindDictElement:
    DeleteChainTable(dict);
    Tcl_Free(dict);
    return TCL_ERROR;
}

static Dict *
GetDictFromObj(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr)
{
    Dict *dict;

    DictGetIntRep(dictPtr, dict);
    DictGetInternalRep(dictPtr, dict);
    if (dict == NULL) {
	if (SetDictFromAny(interp, dictPtr) != TCL_OK) {
	    return NULL;
	}
	DictGetIntRep(dictPtr, dict);
	DictGetInternalRep(dictPtr, dict);
    }
    return dict;
}

/*
 *----------------------------------------------------------------------
 *
762
763
764
765
766
767
768
769

770
771
772
773
774
775
776
777
778
779

780
781
782
783
784

785
786

787
788
789
790
791

792
793
794
795
796
797
798
765
766
767
768
769
770
771

772
773
774
775
776
777
778
779
780
781

782
783
784
785
786

787
788

789
790
791
792
793

794
795
796
797
798
799
800
801







-
+









-
+




-
+

-
+




-
+







 *	effects (other than potential conversion of objects to dictionaries.)
 *	If the flags argument is DICT_PATH_UPDATE, the following additional
 *	side effects occur. Shared dictionaries along the path are converted
 *	into unshared objects, and a backward-pointing chain is built using
 *	the chain fields of the dictionaries (for easy invalidation of string
 *	representations using InvalidateDictChain). If the flags argument has
 *	the DICT_PATH_CREATE bits set (and not the DICT_PATH_EXISTS bit),
 *	non-existant keys will be inserted with a value of an empty
 *	non-extant keys will be inserted with a value of an empty
 *	dictionary, resulting in the path being built.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TclTraceDictPath(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr,
    int keyc,
    Tcl_Size keyc,
    Tcl_Obj *const keyv[],
    int flags)
{
    Dict *dict, *newDict;
    int i;
    Tcl_Size i;

    DictGetIntRep(dictPtr, dict);
    DictGetInternalRep(dictPtr, dict);
    if (dict == NULL) {
	if (SetDictFromAny(interp, dictPtr) != TCL_OK) {
	    return NULL;
	}
	DictGetIntRep(dictPtr, dict);
	DictGetInternalRep(dictPtr, dict);
    }
    if (flags & DICT_PATH_UPDATE) {
	dict->chain = NULL;
    }

    for (i=0 ; i<keyc ; i++) {
	Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&dict->table, keyv[i]);
806
807
808
809
810
811
812
813

814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829

830
831
832
833
834
835
836
837
838

839
840
841
842
843
844
845
846

847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862

863
864
865
866
867
868
869
870
871
872
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
898

899
900
901
902
903
904
905
809
810
811
812
813
814
815

816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831

832
833
834
835
836
837
838
839
840

841
842
843
844
845
846
847
848

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864

865
866
867
868
869
870
871
872
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
898
899
900

901
902
903
904
905
906
907
908







-
+















-
+








-
+







-
+















-
+




















-
+





-
-
+
+







-
+







	    }
	    if ((flags & DICT_PATH_CREATE) != DICT_PATH_CREATE) {
		if (interp != NULL) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "key \"%s\" not known in dictionary",
			    TclGetString(keyv[i])));
		    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "DICT",
			    TclGetString(keyv[i]), NULL);
			    TclGetString(keyv[i]), (char *)NULL);
		}
		return NULL;
	    }

	    /*
	     * The next line should always set isNew to 1.
	     */

	    hPtr = CreateChainEntry(dict, keyv[i], &isNew);
	    tmpObj = Tcl_NewDictObj();
	    Tcl_IncrRefCount(tmpObj);
	    Tcl_SetHashValue(hPtr, tmpObj);
	} else {
	    tmpObj = (Tcl_Obj *)Tcl_GetHashValue(hPtr);

	    DictGetIntRep(tmpObj, newDict);
	    DictGetInternalRep(tmpObj, newDict);

	    if (newDict == NULL) {
		if (SetDictFromAny(interp, tmpObj) != TCL_OK) {
		    return NULL;
		}
	    }
	}

	DictGetIntRep(tmpObj, newDict);
	DictGetInternalRep(tmpObj, newDict);
	if (flags & DICT_PATH_UPDATE) {
	    if (Tcl_IsShared(tmpObj)) {
		TclDecrRefCount(tmpObj);
		tmpObj = Tcl_DuplicateObj(tmpObj);
		Tcl_IncrRefCount(tmpObj);
		Tcl_SetHashValue(hPtr, tmpObj);
		dict->epoch++;
		DictGetIntRep(tmpObj, newDict);
		DictGetInternalRep(tmpObj, newDict);
	    }

	    newDict->chain = dictPtr;
	}
	dict = newDict;
	dictPtr = tmpObj;
    }
    return dictPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * InvalidateDictChain --
 *
 *	Go through a dictionary chain (built by an updating invokation of
 *	Go through a dictionary chain (built by an updating invocation of
 *	TclTraceDictPath) and invalidate the string representations of all the
 *	dictionaries on the chain.
 *
 * Results:
 *	None
 *
 * Side effects:
 *	String reps are invalidated and epoch counters (for detecting illegal
 *	concurrent modifications) are updated through the chain of updated
 *	dictionaries.
 *
 *----------------------------------------------------------------------
 */

static void
InvalidateDictChain(
    Tcl_Obj *dictObj)
{
    Dict *dict;

    DictGetIntRep(dictObj, dict);
    DictGetInternalRep(dictObj, dict);
    assert( dict != NULL);

    do {
	dict->refCount++;
	TclInvalidateStringRep(dictObj);
	TclFreeIntRep(dictObj);
	DictSetIntRep(dictObj, dict);
	TclFreeInternalRep(dictObj);
	DictSetInternalRep(dictObj, dict);

	dict->epoch++;
	dictObj = dict->chain;
	if (dictObj == NULL) {
	    break;
	}
	dict->chain = NULL;
	DictGetIntRep(dictObj, dict);
	DictGetInternalRep(dictObj, dict);
    } while (dict != NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DictObjPut --
937
938
939
940
941
942
943
944
945


946
947
948
949
950
951
952
940
941
942
943
944
945
946


947
948
949
950
951
952
953
954
955







-
-
+
+







    if (dict == NULL) {
	return TCL_ERROR;
    }

    TclInvalidateStringRep(dictPtr);
    hPtr = CreateChainEntry(dict, keyPtr, &isNew);
    dict->refCount++;
    TclFreeIntRep(dictPtr)
    DictSetIntRep(dictPtr, dict);
    TclFreeInternalRep(dictPtr)
    DictSetInternalRep(dictPtr, dict);
    Tcl_IncrRefCount(valuePtr);
    if (!isNew) {
	Tcl_Obj *oldValuePtr = (Tcl_Obj *)Tcl_GetHashValue(hPtr);

	TclDecrRefCount(oldValuePtr);
    }
    Tcl_SetHashValue(hPtr, valuePtr);
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+















+




-
+







    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DictGetSize
 *
 *	Returns the size of dictPtr.  Caller must ensure that dictPtr has type
 *	'tclDicttype'.
 *
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
TclDictGetSize(
    Tcl_Obj *dictPtr)
{
    Dict *dict;
    DictGetInternalRep(dictPtr, dict);
    return dict->table.numEntries;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DictObjSize --
 *
 *	How many key,value pairs are there in the dictionary?
 *
 * Results:
 *	A standard Tcl result. Updates the variable pointed to by sizePtr with
 *	the number of key,value pairs in the dictionary.
 *
 * Side effects:
 *	The dictPtr object is converted to a dictionary type if it is not a
 *	dictionary already.
 *
 *----------------------------------------------------------------------
 */

#undef Tcl_DictObjSize
int
Tcl_DictObjSize(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr,
    int *sizePtr)
    Tcl_Size *sizePtr)
{
    Dict *dict;

    dict = GetDictFromObj(interp, dictPtr);
    if (dict == NULL) {
	return TCL_ERROR;
    }
1180
1181
1182
1183
1184
1185
1186
1187

1188
1189
1190
1191
1192
1193
1194
1205
1206
1207
1208
1209
1210
1211

1212
1213
1214
1215
1216
1217
1218
1219







-
+







				 * written into when there are no further
				 * values in the dictionary, or a 0
				 * otherwise. */
{
    ChainEntry *cPtr;

    /*
     * If the searh is done; we do no work.
     * If the search is done; we do no work.
     */

    if (!searchPtr->epoch) {
	*donePtr = 1;
	return;
    }

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
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







-
+



















-
+







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

int
Tcl_DictObjPutKeyList(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr,
    int keyc,
    Tcl_Size keyc,
    Tcl_Obj *const keyv[],
    Tcl_Obj *valuePtr)
{
    Dict *dict;
    Tcl_HashEntry *hPtr;
    int isNew;

    if (Tcl_IsShared(dictPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_DictObjPutKeyList");
    }
    if (keyc < 1) {
	Tcl_Panic("%s called with empty key list", "Tcl_DictObjPutKeyList");
    }

    dictPtr = TclTraceDictPath(interp, dictPtr, keyc-1,keyv, DICT_PATH_CREATE);
    if (dictPtr == NULL) {
	return TCL_ERROR;
    }

    DictGetIntRep(dictPtr, dict);
    DictGetInternalRep(dictPtr, dict);
    assert(dict != NULL);
    hPtr = CreateChainEntry(dict, keyv[keyc-1], &isNew);
    Tcl_IncrRefCount(valuePtr);
    if (!isNew) {
	Tcl_Obj *oldValuePtr = (Tcl_Obj *)Tcl_GetHashValue(hPtr);

	TclDecrRefCount(oldValuePtr);
1334
1335
1336
1337
1338
1339
1340
1341

1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358

1359
1360
1361
1362
1363
1364
1365
1359
1360
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
1387
1388
1389
1390







-
+
















-
+







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

int
Tcl_DictObjRemoveKeyList(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr,
    int keyc,
    Tcl_Size keyc,
    Tcl_Obj *const keyv[])
{
    Dict *dict;

    if (Tcl_IsShared(dictPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_DictObjRemoveKeyList");
    }
    if (keyc < 1) {
	Tcl_Panic("%s called with empty key list", "Tcl_DictObjRemoveKeyList");
    }

    dictPtr = TclTraceDictPath(interp, dictPtr, keyc-1,keyv, DICT_PATH_UPDATE);
    if (dictPtr == NULL) {
	return TCL_ERROR;
    }

    DictGetIntRep(dictPtr, dict);
    DictGetInternalRep(dictPtr, dict);
    assert(dict != NULL);
    DeleteChainEntry(dict, keyv[keyc-1]);
    InvalidateDictChain(dictPtr);
    return TCL_OK;
}

/*
1398
1399
1400
1401
1402
1403
1404
1405

1406
1407
1408
1409
1410
1411
1412
1423
1424
1425
1426
1427
1428
1429

1430
1431
1432
1433
1434
1435
1436
1437







-
+







    TclNewObj(dictPtr);
    TclInvalidateStringRep(dictPtr);
    dict = (Dict *)Tcl_Alloc(sizeof(Dict));
    InitChainTable(dict);
    dict->epoch = 1;
    dict->chain = NULL;
    dict->refCount = 1;
    DictSetIntRep(dictPtr, dict);
    DictSetInternalRep(dictPtr, dict);
    return dictPtr;
#endif
}

/*
 *----------------------------------------------------------------------
 *
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
1471
1472
1473
1474
1475
1476
1477

1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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







-
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    TclDbNewObj(dictPtr, file, line);
    TclInvalidateStringRep(dictPtr);
    dict = (Dict *)Tcl_Alloc(sizeof(Dict));
    InitChainTable(dict);
    dict->epoch = 1;
    dict->chain = NULL;
    dict->refCount = 1;
    DictSetIntRep(dictPtr, dict);
    DictSetInternalRep(dictPtr, dict);
    return dictPtr;
}
#else /* !TCL_MEM_DEBUG */
Tcl_Obj *
Tcl_DbNewDictObj(
    TCL_UNUSED(const char *) /*file*/,
    TCL_UNUSED(int) /*line*/)
{
    return Tcl_NewDictObj();
}
#endif

/***** START OF FUNCTIONS ACTING AS HELPERS *****/

/*
 *----------------------------------------------------------------------
 *
 * TclDictGet --
 *
 *	Given a key, get its value from the dictionary (or NULL if key is not
 *	found in dictionary.)
 *
 * Results:
 *	A standard Tcl result. The variable pointed to by valuePtrPtr is
 *	updated with the value for the key. Note that it is not an error for
 *	the key to have no mapping in the dictionary.
 *
 * Side effects:
 *	The object pointed to by dictPtr is converted to a dictionary if it is
 *	not already one.
 *
 *----------------------------------------------------------------------
 */
int
TclDictGet(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr,
    const char *key,		/* The key in a C string. */
    Tcl_Obj **valuePtrPtr)	/* Where to write the value. */
{
    Tcl_Obj *keyPtr = Tcl_NewStringObj(key, -1);
    int code;

    Tcl_IncrRefCount(keyPtr);
    code = Tcl_DictObjGet(interp, dictPtr, keyPtr, valuePtrPtr);
    Tcl_DecrRefCount(keyPtr);
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * TclDictPut --
 *
 *	Add a key,value pair to a dictionary, or update the value for a key if
 *	that key already has a mapping in the dictionary.
 *
 *	If valuePtr is a zero-count object and is not written into the
 *	dictionary because of an error, it is freed by this routine. The caller
 *	does NOT need to do reference count management.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	The object pointed to by dictPtr is converted to a dictionary if it is
 *	not already one, and any string representation that it has is
 *	invalidated.
 *
 *----------------------------------------------------------------------
 */
int
TclDictPut(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr,
    const char *key,		/* The key in a C string. */
    Tcl_Obj *valuePtr)		/* The value to write in. */
{
    Tcl_Obj *keyPtr = Tcl_NewStringObj(key, -1);
    int code;

    Tcl_IncrRefCount(keyPtr);
    Tcl_IncrRefCount(valuePtr);
    code = Tcl_DictObjPut(interp, dictPtr, keyPtr, valuePtr);
    Tcl_DecrRefCount(keyPtr);
    Tcl_DecrRefCount(valuePtr);
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * TclDictPutString --
 *
 *	Add a key,value pair to a dictionary, or update the value for a key if
 *	that key already has a mapping in the dictionary.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	The object pointed to by dictPtr is converted to a dictionary if it is
 *	not already one, and any string representation that it has is
 *	invalidated.
 *
 *----------------------------------------------------------------------
 */
int
TclDictPutString(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr,
    const char *key,		/* The key in a C string. */
    const char *value)		/* The value in a C string. */
{
    Tcl_Obj *keyPtr = Tcl_NewStringObj(key, -1);
    Tcl_Obj *valuePtr = Tcl_NewStringObj(value, -1);
    int code;

    Tcl_IncrRefCount(keyPtr);
    Tcl_IncrRefCount(valuePtr);
    code = Tcl_DictObjPut(interp, dictPtr, keyPtr, valuePtr);
    Tcl_DecrRefCount(keyPtr);
    Tcl_DecrRefCount(valuePtr);
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * TclDictRemove --
 *
 *	Remove the key,value pair with the given key from the dictionary; the
 *	key does not need to be present in the dictionary.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	The object pointed to by dictPtr is converted to a dictionary if it is
 *	not already one, and any string representation that it has is
 *	invalidated.
 *
 *----------------------------------------------------------------------
 */
int
TclDictRemove(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr,
    const char *key)		/* The key in a C string. */
{
    Tcl_Obj *keyPtr = Tcl_NewStringObj(key, -1);
    int code;

    Tcl_IncrRefCount(keyPtr);
    code = Tcl_DictObjRemove(interp, dictPtr, keyPtr);
    Tcl_DecrRefCount(keyPtr);
    return code;
}

/***** START OF FUNCTIONS IMPLEMENTING TCL COMMANDS *****/

/*
 *----------------------------------------------------------------------
 *
 * DictCreateCmd --
1481
1482
1483
1484
1485
1486
1487
1488

1489
1490
1491
1492
1493
1494
1495
1653
1654
1655
1656
1657
1658
1659

1660
1661
1662
1663
1664
1665
1666
1667







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictCreateCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictObj;
    int i;

1531
1532
1533
1534
1535
1536
1537
1538

1539
1540
1541
1542
1543
1544
1545
1703
1704
1705
1706
1707
1708
1709

1710
1711
1712
1713
1714
1715
1716
1717







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictGetCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictPtr, *valuePtr = NULL;
    int result;

1597
1598
1599
1600
1601
1602
1603
1604

1605
1606
1607
1608
1609
1610
1611
1769
1770
1771
1772
1773
1774
1775

1776
1777
1778
1779
1780
1781
1782
1783







-
+







	return result;
    }
    if (valuePtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"key \"%s\" not known in dictionary",
		TclGetString(objv[objc-1])));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "DICT",
		TclGetString(objv[objc-1]), NULL);
		TclGetString(objv[objc-1]), (char *)NULL);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, valuePtr);
    return TCL_OK;
}

/*
1624
1625
1626
1627
1628
1629
1630
1631

1632
1633
1634
1635
1636
1637
1638
1796
1797
1798
1799
1800
1801
1802

1803
1804
1805
1806
1807
1808
1809
1810







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictGetDefCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictPtr, *keyPtr, *valuePtr, *defaultPtr;
    Tcl_Obj *const *keyPath;
    int numKeys;
1689
1690
1691
1692
1693
1694
1695
1696

1697
1698
1699
1700
1701
1702
1703
1861
1862
1863
1864
1865
1866
1867

1868
1869
1870
1871
1872
1873
1874
1875







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictReplaceCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictPtr;
    int i;

1737
1738
1739
1740
1741
1742
1743
1744

1745
1746
1747
1748
1749
1750
1751
1909
1910
1911
1912
1913
1914
1915

1916
1917
1918
1919
1920
1921
1922
1923







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictRemoveCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictPtr;
    int i;

1785
1786
1787
1788
1789
1790
1791
1792

1793
1794
1795
1796
1797
1798
1799
1957
1958
1959
1960
1961
1962
1963

1964
1965
1966
1967
1968
1969
1970
1971







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictMergeCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *targetObj, *keyObj = NULL, *valueObj = NULL;
    int allocatedDict = 0;
    int i, done;
1872
1873
1874
1875
1876
1877
1878
1879

1880
1881
1882
1883
1884
1885
1886
2044
2045
2046
2047
2048
2049
2050

2051
2052
2053
2054
2055
2056
2057
2058







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictKeysCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *listPtr;
    const char *pattern = NULL;

1951
1952
1953
1954
1955
1956
1957
1958

1959
1960
1961
1962
1963
1964
1965
2123
2124
2125
2126
2127
2128
2129

2130
2131
2132
2133
2134
2135
2136
2137







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictValuesCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *valuePtr = NULL, *listPtr;
    Tcl_DictSearch search;
    int done;
2011
2012
2013
2014
2015
2016
2017
2018

2019
2020
2021
2022
2023


2024
2025
2026
2027
2028
2029
2030
2031
2032






















































2033
2034
2035
2036
2037
2038
2039
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
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







-
+




-
+
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictSizeCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int result, size;
    int result;
    Tcl_Size size;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "dictionary");
	return TCL_ERROR;
    }
    result = Tcl_DictObjSize(interp, objv[1], &size);
    if (result == TCL_OK) {
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(size));
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TclDictObjSmartRef --
 *
 *	This function returns new tcl-object with the smart reference to
 *	dictionary object.
 *
 *	Object returned with this function is a smart reference (pointer),
 *	so new object of type tclDictType, that directly references given
 *	dictionary object (with internally increased refCount).
 *
 *	The usage of such pointer objects allows to hold more as one
 *	reference to the same real dictionary object, allows to make a pointer
 *	to part of another dictionary, allows to change the dictionary without
 *	regarding of the "shared" state of the dictionary object.
 *
 *	Prevents "called with shared object" exception if object is multiple
 *	referenced.
 *
 * Results:
 *	The newly create object (contains smart reference) is returned.
 *	The returned object has a ref count of 0.
 *
 * Side effects:
 *	Increases ref count of the referenced dictionary.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TclDictObjSmartRef(
    Tcl_Interp *interp,
    Tcl_Obj    *dictPtr)
{
    Tcl_Obj *result;
    Dict    *dict;

    if (!TclHasInternalRep(dictPtr, &tclDictType)
	    && SetDictFromAny(interp, dictPtr) != TCL_OK) {
	return NULL;
    }

    DictGetInternalRep(dictPtr, dict);

    result = Tcl_NewObj();
    DictSetInternalRep(result, dict);
    dict->refCount++;
    result->internalRep.twoPtrValue.ptr2 = NULL;
    result->typePtr = &tclDictType;

    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * DictExistsCmd --
2049
2050
2051
2052
2053
2054
2055
2056

2057
2058
2059
2060
2061
2062
2063
2276
2277
2278
2279
2280
2281
2282

2283
2284
2285
2286
2287
2288
2289
2290







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictExistsCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictPtr, *valuePtr;

    if (objc < 3) {
2091
2092
2093
2094
2095
2096
2097
2098

2099
2100
2101
2102
2103
2104
2105
2318
2319
2320
2321
2322
2323
2324

2325
2326
2327
2328
2329
2330
2331
2332







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictInfoCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Dict *dict;
    char *statsStr;

2135
2136
2137
2138
2139
2140
2141
2142

2143
2144
2145
2146
2147
2148
2149
2362
2363
2364
2365
2366
2367
2368

2369
2370
2371
2372
2373
2374
2375
2376







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictIncrCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int code = TCL_OK;
    Tcl_Obj *dictPtr, *valuePtr = NULL;

2256
2257
2258
2259
2260
2261
2262
2263

2264
2265
2266
2267
2268
2269
2270
2483
2484
2485
2486
2487
2488
2489

2490
2491
2492
2493
2494
2495
2496
2497







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictLappendCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictPtr, *valuePtr, *resultPtr;
    int i, allocatedDict = 0, allocatedValue = 0;

2343
2344
2345
2346
2347
2348
2349
2350

2351
2352
2353
2354
2355
2356
2357
2570
2571
2572
2573
2574
2575
2576

2577
2578
2579
2580
2581
2582
2583
2584







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictAppendCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictPtr, *valuePtr, *resultPtr;
    int allocatedDict = 0;

2445
2446
2447
2448
2449
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
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







-
+








+
-
+

















-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictForNRCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *scriptObj, *keyVarObj, *valueVarObj;
    Tcl_Obj **varv, *keyObj, *valueObj;
    Tcl_DictSearch *searchPtr;
    Tcl_Size varc;
    int varc, done;
    int done;

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"{keyVarName valueVarName} dictionary script");
	return TCL_ERROR;
    }

    /*
     * Parse arguments.
     */

    if (TclListObjGetElements(interp, objv[1], &varc, &varv) != TCL_OK) {
	return TCL_ERROR;
    }
    if (varc != 2) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"must have exactly two variable names", -1));
	Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "dict", "for", NULL);
	Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "dict", "for", (char *)NULL);
	return TCL_ERROR;
    }
    searchPtr = (Tcl_DictSearch *)TclStackAlloc(interp, sizeof(Tcl_DictSearch));
    if (Tcl_DictObjFirst(interp, objv[2], searchPtr, &keyObj, &valueObj,
	    &done) != TCL_OK) {
	TclStackFree(interp, searchPtr);
	return TCL_ERROR;
2540
2541
2542
2543
2544
2545
2546
2547

2548
2549
2550
2551
2552
2553
2554
2768
2769
2770
2771
2772
2773
2774

2775
2776
2777
2778
2779
2780
2781
2782







-
+







    Tcl_DictObjDone(searchPtr);
    TclStackFree(interp, searchPtr);
    return TCL_ERROR;
}

static int
DictForLoopCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_DictSearch *searchPtr = (Tcl_DictSearch *)data[0];
    Tcl_Obj *keyVarObj = (Tcl_Obj *)data[1];
    Tcl_Obj *valueVarObj = (Tcl_Obj *)data[2];
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
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







-
+







+
-
+

















-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictMapNRCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj **varv, *keyObj, *valueObj;
    DictMapStorage *storagePtr;
    Tcl_Size varc;
    int varc, done;
    int done;

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"{keyVarName valueVarName} dictionary script");
	return TCL_ERROR;
    }

    /*
     * Parse arguments.
     */

    if (TclListObjGetElements(interp, objv[1], &varc, &varv) != TCL_OK) {
	return TCL_ERROR;
    }
    if (varc != 2) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"must have exactly two variable names", -1));
	Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "dict", "map", NULL);
	Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "dict", "map", (char *)NULL);
	return TCL_ERROR;
    }
    storagePtr = (DictMapStorage *)TclStackAlloc(interp, sizeof(DictMapStorage));
    if (Tcl_DictObjFirst(interp, objv[2], &storagePtr->search, &keyObj,
	    &valueObj, &done) != TCL_OK) {
	TclStackFree(interp, storagePtr);
	return TCL_ERROR;
2744
2745
2746
2747
2748
2749
2750
2751

2752
2753
2754
2755
2756
2757
2758
2973
2974
2975
2976
2977
2978
2979

2980
2981
2982
2983
2984
2985
2986
2987







-
+







    Tcl_DictObjDone(&storagePtr->search);
    TclStackFree(interp, storagePtr);
    return TCL_ERROR;
}

static int
DictMapLoopCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    DictMapStorage *storagePtr = (DictMapStorage *)data[0];
    Tcl_Obj *keyObj, *valueObj;
    int done;
2852
2853
2854
2855
2856
2857
2858
2859

2860
2861
2862
2863
2864
2865
2866
3081
3082
3083
3084
3085
3086
3087

3088
3089
3090
3091
3092
3093
3094
3095







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictSetCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictPtr, *resultPtr;
    int result, allocatedDict = 0;

2912
2913
2914
2915
2916
2917
2918
2919

2920
2921
2922
2923
2924
2925
2926
3141
3142
3143
3144
3145
3146
3147

3148
3149
3150
3151
3152
3153
3154
3155







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictUnsetCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictPtr, *resultPtr;
    int result, allocatedDict = 0;

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
3200
3201
3202
3203
3204
3205
3206

3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217

3218
3219
3220
3221

3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234

3235
3236
3237
3238
3239
3240
3241
3242







-
+










-
+



-
+
+











-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictFilterCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Interp *iPtr = (Interp *) interp;
    static const char *const filters[] = {
	"key", "script", "value", NULL
    };
    enum FilterTypes {
	FILTER_KEYS, FILTER_SCRIPT, FILTER_VALUES
    };
    } index;
    Tcl_Obj *scriptObj, *keyVarObj, *valueVarObj;
    Tcl_Obj **varv, *keyObj = NULL, *valueObj = NULL, *resultObj, *boolObj;
    Tcl_DictSearch search;
    int index, varc, done, result, satisfied;
    int done, result, satisfied;
    Tcl_Size varc;
    const char *pattern;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "dictionary filterType ?arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[2], filters, "filterType",
	     0, &index) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum FilterTypes) index) {
    switch (index) {
    case FILTER_KEYS:
	/*
	 * Create a dictionary whose keys all match a certain pattern.
	 */

	if (Tcl_DictObjFirst(interp, objv[1], &search,
		&keyObj, &valueObj, &done) != TCL_OK) {
3105
3106
3107
3108
3109
3110
3111
3112

3113
3114
3115
3116
3117
3118
3119
3335
3336
3337
3338
3339
3340
3341

3342
3343
3344
3345
3346
3347
3348
3349







-
+








	if (TclListObjGetElements(interp, objv[3], &varc, &varv) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (varc != 2) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "must have exactly two variable names", -1));
	    Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "dict", "filter", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "dict", "filter", (char *)NULL);
	    return TCL_ERROR;
	}
	keyVarObj = varv[0];
	valueVarObj = varv[1];
	scriptObj = objv[4];

	/*
3256
3257
3258
3259
3260
3261
3262
3263

3264
3265
3266
3267
3268
3269
3270


3271
3272
3273
3274
3275
3276
3277
3486
3487
3488
3489
3490
3491
3492

3493
3494
3495
3496
3497
3498
3499

3500
3501
3502
3503
3504
3505
3506
3507
3508







-
+






-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictUpdateCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *dictPtr, *objPtr;
    int i, dummy;
    int i;
    Tcl_Size dummy;

    if (objc < 5 || !(objc & 1)) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"dictVarName key varName ?key varName ...? script");
	return TCL_ERROR;
    }

3310
3311
3312
3313
3314
3315
3316
3317

3318
3319
3320
3321
3322
3323

3324
3325
3326
3327
3328
3329
3330
3541
3542
3543
3544
3545
3546
3547

3548
3549
3550
3551
3552
3553

3554
3555
3556
3557
3558
3559
3560
3561







-
+





-
+







    TclNRAddCallback(interp, FinalizeDictUpdate, objv[1], objPtr, NULL,NULL);

    return TclNREvalObjEx(interp, objv[objc-1], 0, iPtr->cmdFramePtr, objc-1);
}

static int
FinalizeDictUpdate(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj *dictPtr, *objPtr, **objv;
    Tcl_InterpState state;
    int i, objc;
    Tcl_Size i, objc;
    Tcl_Obj *varName = (Tcl_Obj *)data[0];
    Tcl_Obj *argsObj = (Tcl_Obj *)data[1];

    /*
     * ErrorInfo handling.
     */

3360
3361
3362
3363
3364
3365
3366
3367

3368
3369
3370
3371
3372
3373
3374
3591
3592
3593
3594
3595
3596
3597

3598
3599
3600
3601
3602
3603
3604
3605







-
+







    }

    /*
     * Write back the values from the variables, treating failure to read as
     * an instruction to remove the key.
     */

    Tcl_ListObjGetElements(NULL, argsObj, &objc, &objv);
    TclListObjGetElements(NULL, argsObj, &objc, &objv);
    for (i=0 ; i<objc ; i+=2) {
	objPtr = Tcl_ObjGetVar2(interp, objv[i+1], NULL, 0);
	if (objPtr == NULL) {
	    Tcl_DictObjRemove(NULL, dictPtr, objv[i]);
	} else if (objPtr == dictPtr) {
	    /*
	     * Someone is messing us around, trying to build a recursive
3414
3415
3416
3417
3418
3419
3420
3421

3422
3423
3424
3425
3426
3427
3428
3645
3646
3647
3648
3649
3650
3651

3652
3653
3654
3655
3656
3657
3658
3659







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictWithCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *dictPtr, *keysPtr, *pathPtr;

3461
3462
3463
3464
3465
3466
3467
3468

3469
3470
3471
3472
3473

3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491

3492
3493
3494
3495
3496
3497
3498
3692
3693
3694
3695
3696
3697
3698

3699
3700
3701
3702
3703

3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721

3722
3723
3724
3725
3726
3727
3728
3729







-
+




-
+

















-
+







	    NULL);

    return TclNREvalObjEx(interp, objv[objc-1], 0, iPtr->cmdFramePtr, objc-1);
}

static int
FinalizeDictWith(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj **pathv;
    int pathc;
    Tcl_Size pathc;
    Tcl_InterpState state;
    Tcl_Obj *varName = (Tcl_Obj *)data[0];
    Tcl_Obj *keysPtr = (Tcl_Obj *)data[1];
    Tcl_Obj *pathPtr = (Tcl_Obj *)data[2];
    Var *varPtr, *arrayPtr;

    if (result == TCL_ERROR) {
	Tcl_AddErrorInfo(interp, "\n    (body of \"dict with\")");
    }

    /*
     * Save the result state; TDWF doesn't guarantee to not modify that on
     * TCL_OK result.
     */

    state = Tcl_SaveInterpState(interp, result);
    if (pathPtr != NULL) {
	Tcl_ListObjGetElements(NULL, pathPtr, &pathc, &pathv);
	TclListObjGetElements(NULL, pathPtr, &pathc, &pathv);
    } else {
	pathc = 0;
	pathv = NULL;
    }

    /*
     * Pack from local variables back into the dictionary.
3543
3544
3545
3546
3547
3548
3549
3550

3551
3552
3553
3554
3555
3556
3557
3774
3775
3776
3777
3778
3779
3780

3781
3782
3783
3784
3785
3786
3787
3788







-
+







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

Tcl_Obj *
TclDictWithInit(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr,
    int pathc,
    Tcl_Size pathc,
    Tcl_Obj *const pathv[])
{
    Tcl_DictSearch s;
    Tcl_Obj *keyPtr, *valPtr, *keysPtr;
    int done;

    if (pathc > 0) {
3630
3631
3632
3633
3634
3635
3636
3637

3638
3639
3640
3641
3642
3643
3644
3861
3862
3863
3864
3865
3866
3867

3868
3869
3870
3871
3872
3873
3874
3875







-
+







    int pathc,			/* The number of elements in the path into the
				 * dictionary. */
    Tcl_Obj *const pathv[],	/* The elements of the path to the subdict. */
    Tcl_Obj *keysPtr)		/* List of keys to be synchronized. This is
				 * the result value from TclDictWithInit. */
{
    Tcl_Obj *dictPtr, *leafPtr, *valPtr;
    int i, allocdict, keyc;
    Tcl_Size i, allocdict, keyc;
    Tcl_Obj **keyv;

    /*
     * If the dictionary variable doesn't exist, drop everything silently.
     */

    dictPtr = TclPtrGetVarIdx(interp, varPtr, arrayPtr, part1Ptr, part2Ptr,
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670



3671
3672
3673
3674
3675
3676
3677
3892
3893
3894
3895
3896
3897
3898



3899
3900
3901
3902
3903
3904
3905
3906
3907
3908







-
-
-
+
+
+







    } else {
	allocdict = 0;
    }

    if (pathc > 0) {
	/*
	 * Want to get to the dictionary which we will update; need to do
	 * prepare-for-update de-sharing along the path *but* avoid generating
	 * an error on a non-existant path (we'll treat that the same as a
	 * non-existant variable. Luckily, the de-sharing operation isn't
	 * prepare-for-update unsharing along the path *but* avoid generating
	 * an error on a non-extant path (we'll treat that the same as a
	 * non-extant variable. Luckily, the unsharing operation isn't
	 * deeply damaging if we don't go on to update; it's just less than
	 * perfectly efficient (but no memory should be leaked).
	 */

	leafPtr = TclTraceDictPath(interp, dictPtr, pathc, pathv,
		DICT_PATH_EXISTS | DICT_PATH_UPDATE);
	if (leafPtr == NULL) {
3754
3755
3756
3757
3758
3759
3760
3761

3762
3763
3764
3765
3766
3767
3768
3985
3986
3987
3988
3989
3990
3991

3992
3993
3994
3995
3996
3997
3998
3999







-
+








Tcl_Command
TclInitDictCmd(
    Tcl_Interp *interp)
{
    return TclMakeEnsemble(interp, "dict", implementationMap);
}


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

Changes to generic/tclDisassemble.c.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







/*
 * tclDisassemble.c --
 *
 *	This file contains procedures that disassemble bytecode into either
 *	human-readable or Tcl-processable forms.
 *
 * Copyright (c) 1996-1998 Sun Microsystems, Inc.
 * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
 * Copyright (c) 2013-2016 Donal K. Fellows.
 * Copyright © 1996-1998 Sun Microsystems, Inc.
 * Copyright © 2001 Kevin B. Kenny. All rights reserved.
 * Copyright © 2013-2016 Donal K. Fellows.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclCompile.h"
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
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







-
+













+


-
-
-
-
-
+
+
+
+
+


-
-
-
-
-
-
+
+
+
+
+
+

-







static Tcl_Obj *	DisassembleByteCodeAsDicts(Tcl_Obj *objPtr);
static Tcl_Obj *	DisassembleByteCodeObj(Tcl_Obj *objPtr);
static int		FormatInstruction(ByteCode *codePtr,
			    const unsigned char *pc, Tcl_Obj *bufferObj);
static void		GetLocationInformation(Proc *procPtr,
			    Tcl_Obj **fileObjPtr, int *linePtr);
static void		PrintSourceToObj(Tcl_Obj *appendObj,
			    const char *stringPtr, int maxChars);
			    const char *stringPtr, Tcl_Size maxChars);
static void		UpdateStringOfInstName(Tcl_Obj *objPtr);

/*
 * The structure below defines an instruction name Tcl object to allow
 * reporting of inner contexts in errorstack without string allocation.
 */

static const Tcl_ObjType instNameType = {
    "instname",			/* name */
    NULL,			/* freeIntRepProc */
    NULL,			/* dupIntRepProc */
    UpdateStringOfInstName,	/* updateStringProc */
    NULL,			/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

#define InstNameSetIntRep(objPtr, inst)				\
    do {							\
	Tcl_ObjIntRep ir;					\
	ir.wideValue = (inst);					\
	Tcl_StoreIntRep((objPtr), &instNameType, &ir);		\
#define InstNameSetInternalRep(objPtr, inst) \
    do {								\
	Tcl_ObjInternalRep ir;						\
	ir.wideValue = (inst);						\
	Tcl_StoreInternalRep((objPtr), &instNameType, &ir);		\
    } while (0)

#define InstNameGetIntRep(objPtr, inst)				\
    do {							\
	const Tcl_ObjIntRep *irPtr;				\
	irPtr = TclFetchIntRep((objPtr), &instNameType);	\
	assert(irPtr != NULL);					\
	(inst) = (size_t)irPtr->wideValue;			\
#define InstNameGetInternalRep(objPtr, inst) \
    do {								\
	const Tcl_ObjInternalRep *irPtr;				\
	irPtr = TclFetchInternalRep((objPtr), &instNameType);		\
	assert(irPtr != NULL);						\
	(inst) = irPtr->wideValue;					\
    } while (0)


/*
 *----------------------------------------------------------------------
 *
 * GetLocationInformation --
 *
 *	This procedure looks up the information about where a procedure was
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
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







-
+














-
+
-


+
-
+

-
-
+
+
+
+







    }
}

#ifdef TCL_COMPILE_DEBUG
/*
 *----------------------------------------------------------------------
 *
 * TclPrintByteCodeObj --
 * TclDebugPrintByteCodeObj --
 *
 *	This procedure prints ("disassembles") the instructions of a bytecode
 *	object to stdout.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TclPrintByteCodeObj(
TclDebugPrintByteCodeObj(
    TCL_UNUSED(Tcl_Interp *),	/* Stuck with this in internal stubs */
    Tcl_Obj *objPtr)		/* The bytecode object to disassemble. */
{
    if (tclTraceCompile >= 2) {
    Tcl_Obj *bufPtr = DisassembleByteCodeObj(objPtr);
	Tcl_Obj *bufPtr = DisassembleByteCodeObj(objPtr);

    fprintf(stdout, "\n%s", TclGetString(bufPtr));
    Tcl_DecrRefCount(bufPtr);
	fprintf(stdout, "\n%s", TclGetString(bufPtr));
	Tcl_DecrRefCount(bufPtr);
	fflush(stdout);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclPrintInstruction --
 *
189
190
191
192
193
194
195
196

197
198
199

200
201
202
203
204
205
206
191
192
193
194
195
196
197

198
199
200

201
202
203
204
205
206
207
208







-
+


-
+







 */

void
TclPrintObject(
    FILE *outFile,		/* The file to print the source to. */
    Tcl_Obj *objPtr,		/* Points to the Tcl object whose string
				 * representation should be printed. */
    size_t maxChars)		/* Maximum number of chars to print. */
    Tcl_Size maxChars)		/* Maximum number of chars to print. */
{
    char *bytes;
    size_t length;
    Tcl_Size length;

    bytes = TclGetStringFromObj(objPtr, &length);
    TclPrintSource(outFile, bytes, TclMin(length, maxChars));
}

/*
 *----------------------------------------------------------------------
220
221
222
223
224
225
226
227

228
229
230
231
232
233
234
222
223
224
225
226
227
228

229
230
231
232
233
234
235
236







-
+







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

void
TclPrintSource(
    FILE *outFile,		/* The file to print the source to. */
    const char *stringPtr,	/* The string to print. */
    size_t maxChars)		/* Maximum number of chars to print. */
    Tcl_Size maxChars)		/* Maximum number of chars to print. */
{
    Tcl_Obj *bufferObj;

    TclNewObj(bufferObj);
    PrintSourceToObj(bufferObj, stringPtr, maxChars);
    fprintf(outFile, "%s", TclGetString(bufferObj));
    Tcl_DecrRefCount(bufferObj);
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
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







-
+
+



-
+

















-
+










-
+











-
-
-
+
+
+
+

-
-
-
+
+
+











-
+


-
+







-
+







DisassembleByteCodeObj(
    Tcl_Obj *objPtr)		/* The bytecode object to disassemble. */
{
    ByteCode *codePtr;
    unsigned char *codeStart, *codeLimit, *pc;
    unsigned char *codeDeltaNext, *codeLengthNext;
    unsigned char *srcDeltaNext, *srcLengthNext;
    int codeOffset, codeLen, srcOffset, srcLen, numCmds, delta, i, line;
    int codeOffset, codeLen, srcOffset, srcLen, numCmds, delta, line;
    Tcl_Size i;
    Interp *iPtr;
    Tcl_Obj *bufferObj, *fileObj;

    ByteCodeGetIntRep(objPtr, &tclByteCodeType, codePtr);
    ByteCodeGetInternalRep(objPtr, &tclByteCodeType, codePtr);

    iPtr = (Interp *) *codePtr->interpHandle;

    TclNewObj(bufferObj);
    if (!codePtr->refCount) {
	return bufferObj;	/* Already freed. */
    }

    codeStart = codePtr->codeStart;
    codeLimit = codeStart + codePtr->numCodeBytes;
    numCmds = codePtr->numCommands;

    /*
     * Print header lines describing the ByteCode.
     */

    Tcl_AppendPrintfToObj(bufferObj,
	    "ByteCode %p, refCt %" TCL_Z_MODIFIER "u, epoch %" TCL_Z_MODIFIER "u, interp %p (epoch %" TCL_Z_MODIFIER "u)\n",
	    "ByteCode %p, refCt %" TCL_SIZE_MODIFIER "d, epoch %" TCL_SIZE_MODIFIER "d, interp %p (epoch %" TCL_SIZE_MODIFIER "d)\n",
	    codePtr, codePtr->refCount, codePtr->compileEpoch, iPtr, iPtr->compileEpoch);
    Tcl_AppendToObj(bufferObj, "  Source ", -1);
    PrintSourceToObj(bufferObj, codePtr->source,
	    TclMin(codePtr->numSrcBytes, 55));
    GetLocationInformation(codePtr->procPtr, &fileObj, &line);
    if (line >= 0 && fileObj != NULL) {
	Tcl_AppendPrintfToObj(bufferObj, "\n  File \"%s\" Line %d",
		TclGetString(fileObj), line);
    }
    Tcl_AppendPrintfToObj(bufferObj,
	    "\n  Cmds %d, src %d, inst %d, litObjs %u, aux %d, stkDepth %u, code/src %.2f\n",
	    "\n  Cmds %d, src %" TCL_SIZE_MODIFIER "d, inst %" TCL_SIZE_MODIFIER "d, litObjs %" TCL_SIZE_MODIFIER "d, aux %" TCL_SIZE_MODIFIER "d, stkDepth %" TCL_SIZE_MODIFIER "d, code/src %.2f\n",
	    numCmds, codePtr->numSrcBytes, codePtr->numCodeBytes,
	    codePtr->numLitObjects, codePtr->numAuxDataItems,
	    codePtr->maxStackDepth,
#ifdef TCL_COMPILE_STATS
	    codePtr->numSrcBytes?
		    codePtr->structureSize/(float)codePtr->numSrcBytes :
#endif
	    0.0);

#ifdef TCL_COMPILE_STATS
    Tcl_AppendPrintfToObj(bufferObj,
	    "  Code %lu = header %lu+inst %d+litObj %lu+exc %lu+aux %lu+cmdMap %d\n",
	    (unsigned long) codePtr->structureSize,
	    (unsigned long) (sizeof(ByteCode) - sizeof(size_t) - sizeof(Tcl_Time)),
	    "  Code %" TCL_Z_MODIFIER "u = header %" TCL_Z_MODIFIER "u+inst %" TCL_SIZE_MODIFIER "d+litObj %"
	    TCL_Z_MODIFIER "u+exc %" TCL_Z_MODIFIER "u+aux %" TCL_Z_MODIFIER "u+cmdMap %" TCL_SIZE_MODIFIER "d\n",
	    codePtr->structureSize,
	    offsetof(ByteCode, localCachePtr),
	    codePtr->numCodeBytes,
	    (unsigned long) (codePtr->numLitObjects * sizeof(Tcl_Obj *)),
	    (unsigned long) (codePtr->numExceptRanges*sizeof(ExceptionRange)),
	    (unsigned long) (codePtr->numAuxDataItems * sizeof(AuxData)),
	    codePtr->numLitObjects * sizeof(Tcl_Obj *),
	    codePtr->numExceptRanges*sizeof(ExceptionRange),
	    codePtr->numAuxDataItems * sizeof(AuxData),
	    codePtr->numCmdLocBytes);
#endif /* TCL_COMPILE_STATS */

    /*
     * If the ByteCode is the compiled body of a Tcl procedure, print
     * information about that procedure. Note that we don't know the
     * procedure's name since ByteCode's can be shared among procedures.
     */

    if (codePtr->procPtr != NULL) {
	Proc *procPtr = codePtr->procPtr;
	int numCompiledLocals = procPtr->numCompiledLocals;
	Tcl_Size numCompiledLocals = procPtr->numCompiledLocals;

	Tcl_AppendPrintfToObj(bufferObj,
		"  Proc %p, refCt %" TCL_Z_MODIFIER "u, args %d, compiled locals %d\n",
		"  Proc %p, refCt %" TCL_SIZE_MODIFIER "d, args %" TCL_SIZE_MODIFIER "d, compiled locals %" TCL_SIZE_MODIFIER "d\n",
		procPtr, procPtr->refCount, procPtr->numArgs,
		numCompiledLocals);
	if (numCompiledLocals > 0) {
	    CompiledLocal *localPtr = procPtr->firstLocalPtr;

	    for (i = 0;  i < numCompiledLocals;  i++) {
		Tcl_AppendPrintfToObj(bufferObj,
			"      slot %d%s%s%s%s%s%s", i,
			"      slot %" TCL_SIZE_MODIFIER "d%s%s%s%s%s%s", i,
			(localPtr->flags & (VAR_ARRAY|VAR_LINK)) ? "" : ", scalar",
			(localPtr->flags & VAR_ARRAY) ? ", array" : "",
			(localPtr->flags & VAR_LINK) ? ", link" : "",
			(localPtr->flags & VAR_ARGUMENT) ? ", arg" : "",
			(localPtr->flags & VAR_TEMPORARY) ? ", temp" : "",
			(localPtr->flags & VAR_RESOLVED) ? ", resolved" : "");
		if (TclIsVarTemporary(localPtr)) {
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
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







-
-
+
+

-
+



-
+






-
+



-
+







	}
    }

    /*
     * Print the ExceptionRange array.
     */

    if (codePtr->numExceptRanges > 0) {
	Tcl_AppendPrintfToObj(bufferObj, "  Exception ranges %d, depth %d:\n",
    if ((int)codePtr->numExceptRanges > 0) {
	Tcl_AppendPrintfToObj(bufferObj, "  Exception ranges %" TCL_SIZE_MODIFIER "d, depth %" TCL_SIZE_MODIFIER "d:\n",
		codePtr->numExceptRanges, codePtr->maxExceptDepth);
	for (i = 0;  i < codePtr->numExceptRanges;  i++) {
	for (i = 0;  i < (int)codePtr->numExceptRanges;  i++) {
	    ExceptionRange *rangePtr = &codePtr->exceptArrayPtr[i];

	    Tcl_AppendPrintfToObj(bufferObj,
		    "      %d: level %d, %s, pc %d-%d, ",
		    "      %" TCL_SIZE_MODIFIER "d: level %" TCL_SIZE_MODIFIER "d, %s, pc %" TCL_SIZE_MODIFIER "d-%" TCL_SIZE_MODIFIER "d, ",
		    i, rangePtr->nestingLevel,
		    (rangePtr->type==LOOP_EXCEPTION_RANGE ? "loop" : "catch"),
		    rangePtr->codeOffset,
		    (rangePtr->codeOffset + rangePtr->numCodeBytes - 1));
	    switch (rangePtr->type) {
	    case LOOP_EXCEPTION_RANGE:
		Tcl_AppendPrintfToObj(bufferObj, "continue %d, break %d\n",
		Tcl_AppendPrintfToObj(bufferObj, "continue %" TCL_SIZE_MODIFIER "d, break %" TCL_SIZE_MODIFIER "d\n",
			rangePtr->continueOffset, rangePtr->breakOffset);
		break;
	    case CATCH_EXCEPTION_RANGE:
		Tcl_AppendPrintfToObj(bufferObj, "catch %d\n",
		Tcl_AppendPrintfToObj(bufferObj, "catch %" TCL_SIZE_MODIFIER "d\n",
			rangePtr->catchOffset);
		break;
	    default:
		Tcl_Panic("DisassembleByteCodeObj: bad ExceptionRange type %d",
			rangePtr->type);
	    }
	}
439
440
441
442
443
444
445
446

447
448
449
450
451
452
453
443
444
445
446
447
448
449

450
451
452
453
454
455
456
457







-
+







	    srcLen = TclGetInt4AtPtr(srcLengthNext);
	    srcLengthNext += 4;
	} else {
	    srcLen = TclGetInt1AtPtr(srcLengthNext);
	    srcLengthNext++;
	}

	Tcl_AppendPrintfToObj(bufferObj, "%s%4d: pc %d-%d, src %d-%d",
	Tcl_AppendPrintfToObj(bufferObj, "%s%4" TCL_SIZE_MODIFIER "d: pc %d-%d, src %d-%d",
		((i % 2)? "     " : "\n   "),
		(i+1), codeOffset, (codeOffset + codeLen - 1),
		srcOffset, (srcOffset + srcLen - 1));
    }
    if (numCmds > 0) {
	Tcl_AppendToObj(bufferObj, "\n", -1);
    }
498
499
500
501
502
503
504
505

506
507
508
509
510
511
512
502
503
504
505
506
507
508

509
510
511
512
513
514
515
516







-
+







	 */

	while ((pc-codeStart) < codeOffset) {
	    Tcl_AppendToObj(bufferObj, "    ", -1);
	    pc += FormatInstruction(codePtr, pc, bufferObj);
	}

	Tcl_AppendPrintfToObj(bufferObj, "  Command %d: ", i+1);
	Tcl_AppendPrintfToObj(bufferObj, "  Command %" TCL_SIZE_MODIFIER "d: ", i+1);
	PrintSourceToObj(bufferObj, (codePtr->source + srcOffset),
		TclMin(srcLen, 55));
	Tcl_AppendToObj(bufferObj, "\n", -1);
    }
    if (pc < codeLimit) {
	/*
	 * Print instructions after the last command.
538
539
540
541
542
543
544
545

546
547
548
549
550
551
552
542
543
544
545
546
547
548

549
550
551
552
553
554
555
556







-
+







{
    Proc *procPtr = codePtr->procPtr;
    unsigned char opCode = *pc;
    const InstructionDesc *instDesc = &tclInstructionTable[opCode];
    unsigned char *codeStart = codePtr->codeStart;
    unsigned pcOffset = pc - codeStart;
    int opnd = 0, i, j, numBytes = 1;
    int localCt = procPtr ? procPtr->numCompiledLocals : 0;
    Tcl_Size localCt = procPtr ? procPtr->numCompiledLocals : 0;
    CompiledLocal *localPtr = procPtr ? procPtr->firstLocalPtr : NULL;
    char suffixBuffer[128];	/* Additional info to print after main opcode
				 * and immediates. */
    char *suffixSrc = NULL;
    Tcl_Obj *suffixObj = NULL;
    AuxData *auxPtr = NULL;

565
566
567
568
569
570
571
572

573
574
575
576
577
578
579

580
581
582
583
584
585

586
587

588
589
590
591
592
593
594
569
570
571
572
573
574
575

576
577
578
579
580
581
582

583
584
585
586
587
588

589
590

591
592
593
594
595
596
597
598







-
+






-
+





-
+

-
+







	case OPERAND_UINT1:
	    opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
	    Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd);
	    break;
	case OPERAND_UINT4:
	    opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4;
	    if (opCode == INST_START_CMD) {
		sprintf(suffixBuffer+strlen(suffixBuffer),
		snprintf(suffixBuffer+strlen(suffixBuffer), sizeof(suffixBuffer) - strlen(suffixBuffer),
			", %u cmds start here", opnd);
	    }
	    Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd);
	    break;
	case OPERAND_OFFSET1:
	    opnd = TclGetInt1AtPtr(pc+numBytes); numBytes++;
	    sprintf(suffixBuffer, "pc %u", pcOffset+opnd);
	    snprintf(suffixBuffer, sizeof(suffixBuffer), "pc %u", pcOffset+opnd);
	    Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd);
	    break;
	case OPERAND_OFFSET4:
	    opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4;
	    if (opCode == INST_START_CMD) {
		sprintf(suffixBuffer, "next cmd at pc %u", pcOffset+opnd);
		snprintf(suffixBuffer, sizeof(suffixBuffer), "next cmd at pc %u", pcOffset+opnd);
	    } else {
		sprintf(suffixBuffer, "pc %u", pcOffset+opnd);
		snprintf(suffixBuffer, sizeof(suffixBuffer), "pc %u", pcOffset+opnd);
	    }
	    Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd);
	    break;
	case OPERAND_LIT1:
	    opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
	    suffixObj = codePtr->objArrayPtr[opnd];
	    Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd);
619
620
621
622
623
624
625
626

627
628
629
630
631
632
633

634
635

636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653

654
655
656
657
658
659
660
623
624
625
626
627
628
629

630
631
632
633
634
635
636

637
638

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

657
658
659
660
661
662
663
664







-
+






-
+

-
+

















-
+







	    goto printLVTindex;
	case OPERAND_LVT4:
	    opnd = TclGetUInt4AtPtr(pc+numBytes);
	    numBytes += 4;
	printLVTindex:
	    if (localPtr != NULL) {
		if (opnd >= localCt) {
		    Tcl_Panic("FormatInstruction: bad local var index %u (%u locals)",
		    Tcl_Panic("FormatInstruction: bad local var index %u (%" TCL_SIZE_MODIFIER "d locals)",
			    opnd, localCt);
		}
		for (j = 0;  j < opnd;  j++) {
		    localPtr = localPtr->nextPtr;
		}
		if (TclIsVarTemporary(localPtr)) {
		    sprintf(suffixBuffer, "temp var %u", opnd);
		    snprintf(suffixBuffer, sizeof(suffixBuffer), "temp var %u", opnd);
		} else {
		    sprintf(suffixBuffer, "var ");
		    snprintf(suffixBuffer, sizeof(suffixBuffer), "var ");
		    suffixSrc = localPtr->name;
		}
	    }
	    Tcl_AppendPrintfToObj(bufferObj, "%%v%u ", opnd);
	    break;
	case OPERAND_SCLS1:
	    opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
	    Tcl_AppendPrintfToObj(bufferObj, "%s ",
		    tclStringClassTable[opnd].name);
	    break;
	case OPERAND_NONE:
	default:
	    break;
	}
    }
    if (suffixObj) {
	const char *bytes;
	size_t length;
	Tcl_Size length;

	Tcl_AppendToObj(bufferObj, "\t# ", -1);
	bytes = TclGetStringFromObj(codePtr->objArrayPtr[opnd], &length);
	PrintSourceToObj(bufferObj, bytes, TclMin(length, 40));
    } else if (suffixBuffer[0]) {
	Tcl_AppendPrintfToObj(bufferObj, "\t# %s", suffixBuffer);
	if (suffixSrc) {
684
685
686
687
688
689
690
691

692
693
694
695
696
697
698
699
700
701
702
703
704
705


706
707
708
709
710
711
712
688
689
690
691
692
693
694

695
696
697
698
699
700
701
702
703
704
705
706
707


708
709
710
711
712
713
714
715
716







-
+












-
-
+
+








Tcl_Obj *
TclGetInnerContext(
    Tcl_Interp *interp,
    const unsigned char *pc,
    Tcl_Obj **tosPtr)
{
    int objc = 0, off = 0;
    Tcl_Size objc = 0;
    Tcl_Obj *result;
    Interp *iPtr = (Interp *) interp;

    switch (*pc) {
    case INST_STR_LEN:
    case INST_LNOT:
    case INST_BITNOT:
    case INST_UMINUS:
    case INST_UPLUS:
    case INST_TRY_CVT_TO_NUMERIC:
    case INST_EXPAND_STKTOP:
    case INST_EXPR_STK:
        objc = 1;
        break;
	objc = 1;
	break;

    case INST_LIST_IN:
    case INST_LIST_NOT_IN:	/* Basic list containment operators. */
    case INST_STR_EQ:
    case INST_STR_NEQ:		/* String (in)equality check */
    case INST_STR_CMP:		/* String compare. */
    case INST_STR_INDEX:
725
726
727
728
729
730
731
732
733


734
735
736
737
738



739
740
741
742
743


744
745
746
747

748
749
750
751
752
753
754
755
756
757
758



759
760

761
762
763
764



765
766
767


768
769
770
771
772

773
774
775
776
777
778





779
780

781
782
783
784
785
786





787
788
789
790
791
792
793
729
730
731
732
733
734
735


736
737
738
739



740
741
742
743
744
745


746
747
748
749
750

751
752
753
754
755
756
757
758
759



760
761
762
763

764
765



766
767
768
769


770
771
772
773
774
775

776
777





778
779
780
781
782
783

784
785





786
787
788
789
790
791
792
793
794
795
796
797







-
-
+
+


-
-
-
+
+
+



-
-
+
+



-
+








-
-
-
+
+
+

-
+

-
-
-
+
+
+

-
-
+
+




-
+

-
-
-
-
-
+
+
+
+
+

-
+

-
-
-
-
-
+
+
+
+
+







    case INST_BITXOR:
    case INST_BITAND:
    case INST_EXPON:
    case INST_ADD:
    case INST_SUB:
    case INST_DIV:
    case INST_MULT:
        objc = 2;
        break;
	objc = 2;
	break;

    case INST_RETURN_STK:
        /* early pop. TODO: dig out opt dict too :/ */
        objc = 1;
        break;
	/* early pop. TODO: dig out opt dict too :/ */
	objc = 1;
	break;

    case INST_SYNTAX:
    case INST_RETURN_IMM:
        objc = 2;
        break;
	objc = 2;
	break;

    case INST_INVOKE_STK4:
	objc = TclGetUInt4AtPtr(pc+1);
        break;
	break;

    case INST_INVOKE_STK1:
	objc = TclGetUInt1AtPtr(pc+1);
	break;
    }

    result = iPtr->innerContext;
    if (Tcl_IsShared(result)) {
        Tcl_DecrRefCount(result);
        iPtr->innerContext = result = Tcl_NewListObj(objc + 1, NULL);
        Tcl_IncrRefCount(result);
	Tcl_DecrRefCount(result);
	iPtr->innerContext = result = Tcl_NewListObj(objc + 1, NULL);
	Tcl_IncrRefCount(result);
    } else {
        int len;
	Tcl_Size len;

        /*
         * Reset while keeping the list intrep as much as possible.
         */
	/*
	 * Reset while keeping the list internalrep as much as possible.
	 */

	Tcl_ListObjLength(interp, result, &len);
        Tcl_ListObjReplace(interp, result, 0, len, 0, NULL);
	TclListObjLength(interp, result, &len);
	Tcl_ListObjReplace(interp, result, 0, len, 0, NULL);
    }
    Tcl_ListObjAppendElement(NULL, result, TclNewInstNameObj(*pc));

    for (; objc>0 ; objc--) {
        Tcl_Obj *objPtr;
	Tcl_Obj *objPtr;

        objPtr = tosPtr[1 - objc + off];
        if (!objPtr) {
            Tcl_Panic("InnerContext: bad tos -- appending null object");
        }
        if ((objPtr->refCount<=0)
	objPtr = tosPtr[1 - objc];
	if (!objPtr) {
	    Tcl_Panic("InnerContext: bad tos -- appending null object");
	}
	if ((objPtr->refCount <= 0)
#ifdef TCL_MEM_DEBUG
                || (objPtr->refCount==0x61616161)
		|| (objPtr->refCount == 0x61616161)
#endif
        ) {
            Tcl_Panic("InnerContext: bad tos -- appending freed object %p",
                    objPtr);
        }
        Tcl_ListObjAppendElement(NULL, result, objPtr);
	) {
	    Tcl_Panic("InnerContext: bad tos -- appending freed object %p",
		    objPtr);
	}
	Tcl_ListObjAppendElement(NULL, result, objPtr);
    }

    return result;
}

/*
 *----------------------------------------------------------------------
803
804
805
806
807
808
809
810

811
812
813
814
815
816
817
807
808
809
810
811
812
813

814
815
816
817
818
819
820
821







-
+







TclNewInstNameObj(
    unsigned char inst)
{
    Tcl_Obj *objPtr;

    TclNewObj(objPtr);
    TclInvalidateStringRep(objPtr);
    InstNameSetIntRep(objPtr, (long) inst);
    InstNameSetInternalRep(objPtr, inst);

    return objPtr;
}

/*
 *----------------------------------------------------------------------
 *
825
826
827
828
829
830
831
832

833
834

835
836
837


838
839
840
841
842
843
844
829
830
831
832
833
834
835

836
837

838
839


840
841
842
843
844
845
846
847
848







-
+

-
+

-
-
+
+







static void
UpdateStringOfInstName(
    Tcl_Obj *objPtr)
{
    size_t inst;	/* NOTE: We know this is really an unsigned char */
    char *dst;

    InstNameGetIntRep(objPtr, inst);
    InstNameGetInternalRep(objPtr, inst);

    if (inst > LAST_INST_OPCODE) {
    if (inst >= LAST_INST_OPCODE) {
	dst = Tcl_InitStringRep(objPtr, NULL, TCL_INTEGER_SPACE + 5);
	TclOOM(dst, (size_t)TCL_INTEGER_SPACE + 5);
        sprintf(dst, "inst_%" TCL_Z_MODIFIER "u", inst);
	TclOOM(dst, TCL_INTEGER_SPACE + 5);
	snprintf(dst, TCL_INTEGER_SPACE + 5, "inst_%" TCL_Z_MODIFIER "u", inst);
	(void) Tcl_InitStringRep(objPtr, NULL, strlen(dst));
    } else {
	const char *s = tclInstructionTable[inst].name;
	size_t len = strlen(s);
	dst = Tcl_InitStringRep(objPtr, s, len);
	TclOOM(dst, len);
    }
854
855
856
857
858
859
860
861

862
863
864

865
866
867
868
869
870
871
872
873
874
875
876

877
878
879
880
881
882
883
858
859
860
861
862
863
864

865
866
867

868
869
870
871
872
873
874
875
876
877
878
879

880
881
882
883
884
885
886
887







-
+


-
+











-
+







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

static void
PrintSourceToObj(
    Tcl_Obj *appendObj,		/* The object to print the source to. */
    const char *stringPtr,	/* The string to print. */
    int maxChars)		/* Maximum number of chars to print. */
    Tcl_Size maxChars)		/* Maximum number of chars to print. */
{
    const char *p;
    int i = 0, len;
    Tcl_Size i = 0, len;

    if (stringPtr == NULL) {
	Tcl_AppendToObj(appendObj, "\"\"", -1);
	return;
    }

    Tcl_AppendToObj(appendObj, "\"", -1);
    p = stringPtr;
    for (;  (*p != '\0') && (i < maxChars);  p+=len) {
	int ucs4;

	len = TclUtfToUCS4(p, &ucs4);
	len = TclUtfToUniChar(p, &ucs4);
	switch (ucs4) {
	case '"':
	    Tcl_AppendToObj(appendObj, "\\\"", -1);
	    i += 2;
	    continue;
	case '\f':
	    Tcl_AppendToObj(appendObj, "\\f", -1);
937
938
939
940
941
942
943
944
945


946
947

948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964

965
966
967
968
969
970
971
941
942
943
944
945
946
947


948
949
950

951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967

968
969
970
971
972
973
974
975







-
-
+
+

-
+
















-
+







DisassembleByteCodeAsDicts(
    Tcl_Obj *objPtr)		/* The bytecode-holding value to take apart */
{
    ByteCode *codePtr;
    Tcl_Obj *description, *literals, *variables, *instructions, *inst;
    Tcl_Obj *aux, *exn, *commands, *file;
    unsigned char *pc, *opnd, *codeOffPtr, *codeLenPtr, *srcOffPtr, *srcLenPtr;
    int codeOffset, codeLength, sourceOffset, sourceLength;
    int i, val, line;
    int codeOffset, codeLength, sourceOffset, sourceLength, val, line;
    Tcl_Size i;

    ByteCodeGetIntRep(objPtr, &tclByteCodeType, codePtr);
    ByteCodeGetInternalRep(objPtr, &tclByteCodeType, codePtr);

    /*
     * Get the literals from the bytecode.
     */

    TclNewObj(literals);
    for (i=0 ; i<codePtr->numLitObjects ; i++) {
	Tcl_ListObjAppendElement(NULL, literals, codePtr->objArrayPtr[i]);
    }

    /*
     * Get the variables from the bytecode.
     */

    TclNewObj(variables);
    if (codePtr->procPtr) {
	int localCount = codePtr->procPtr->numCompiledLocals;
	Tcl_Size localCount = codePtr->procPtr->numCompiledLocals;
	CompiledLocal *localPtr = codePtr->procPtr->firstLocalPtr;

	for (i=0 ; i<localCount ; i++,localPtr=localPtr->nextPtr) {
	    Tcl_Obj *descriptor[2];

	    TclNewObj(descriptor[0]);
	    if (!(localPtr->flags & (VAR_ARRAY|VAR_LINK))) {
1107
1108
1109
1110
1111
1112
1113
1114

1115
1116
1117
1118
1119
1120
1121
1122

1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141

1142
1143
1144
1145
1146
1147

1148
1149
1150
1151
1152
1153
1154

1155
1156
1157
1158
1159
1160
1161
1111
1112
1113
1114
1115
1116
1117

1118
1119
1120
1121
1122
1123
1124
1125

1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144

1145
1146
1147
1148
1149
1150

1151
1152
1153
1154
1155
1156
1157

1158
1159
1160
1161
1162
1163
1164
1165







-
+







-
+


















-
+





-
+






-
+







    }

    /*
     * Get the auxiliary data from the bytecode.
     */

    TclNewObj(aux);
    for (i=0 ; i<codePtr->numAuxDataItems ; i++) {
    for (i=0 ; i<(int)codePtr->numAuxDataItems ; i++) {
	AuxData *auxData = &codePtr->auxDataArrayPtr[i];
	Tcl_Obj *auxDesc = Tcl_NewStringObj(auxData->type->name, -1);

	if (auxData->type->disassembleProc) {
	    Tcl_Obj *desc;

	    TclNewObj(desc);
	    Tcl_DictObjPut(NULL, desc, Tcl_NewStringObj("name", -1), auxDesc);
	    TclDictPut(NULL, desc, "name", auxDesc);
	    auxDesc = desc;
	    auxData->type->disassembleProc(auxData->clientData, auxDesc,
		    codePtr, 0);
	} else if (auxData->type->printProc) {
	    Tcl_Obj *desc;

	    TclNewObj(desc);
	    auxData->type->printProc(auxData->clientData, desc, codePtr, 0);
	    Tcl_ListObjAppendElement(NULL, auxDesc, desc);
	}
	Tcl_ListObjAppendElement(NULL, aux, auxDesc);
    }

    /*
     * Get the exception ranges from the bytecode.
     */

    TclNewObj(exn);
    for (i=0 ; i<codePtr->numExceptRanges ; i++) {
    for (i=0 ; i<(int)codePtr->numExceptRanges ; i++) {
	ExceptionRange *rangePtr = &codePtr->exceptArrayPtr[i];

	switch (rangePtr->type) {
	case LOOP_EXCEPTION_RANGE:
	    Tcl_ListObjAppendElement(NULL, exn, Tcl_ObjPrintf(
		    "type %s level %d from %d to %d break %d continue %d",
		    "type %s level %" TCL_SIZE_MODIFIER "d from %" TCL_SIZE_MODIFIER "d to %" TCL_SIZE_MODIFIER "d break %" TCL_SIZE_MODIFIER "d continue %" TCL_SIZE_MODIFIER "d",
		    "loop", rangePtr->nestingLevel, rangePtr->codeOffset,
		    rangePtr->codeOffset + rangePtr->numCodeBytes - 1,
		    rangePtr->breakOffset, rangePtr->continueOffset));
	    break;
	case CATCH_EXCEPTION_RANGE:
	    Tcl_ListObjAppendElement(NULL, exn, Tcl_ObjPrintf(
		    "type %s level %d from %d to %d catch %d",
		    "type %s level %" TCL_SIZE_MODIFIER "d from %" TCL_SIZE_MODIFIER "d to %" TCL_SIZE_MODIFIER "d catch %" TCL_SIZE_MODIFIER "d",
		    "catch", rangePtr->nestingLevel, rangePtr->codeOffset,
		    rangePtr->codeOffset + rangePtr->numCodeBytes - 1,
		    rangePtr->catchOffset));
	    break;
	}
    }

1174
1175
1176
1177
1178
1179
1180
1181

1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192



1193
1194
1195
1196
1197
1198
1199
1200


1201
1202
1203
1204
1205



1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224

1225
1226

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
1178
1179
1180
1181
1182
1183
1184

1185
1186
1187
1188
1189
1190
1191
1192




1193
1194
1195
1196
1197
1198
1199
1200
1201


1202
1203





1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224

1225


1226



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







-
+







-
-
-
-
+
+
+






-
-
+
+
-
-
-
-
-
+
+
+


















-
+
-
-
+
-
-
-
+
+
-
-
-
+
+
-
-
+

-
-
-
+
+
+

-
+


-
+
-



-
+
-



















-
+












-
-
+
+















-
+








    TclNewObj(commands);
    codeOffPtr = codePtr->codeDeltaStart;
    codeLenPtr = codePtr->codeLengthStart;
    srcOffPtr = codePtr->srcDeltaStart;
    srcLenPtr = codePtr->srcLengthStart;
    codeOffset = sourceOffset = 0;
    for (i=0 ; i<codePtr->numCommands ; i++) {
    for (i=0 ; i<(int)codePtr->numCommands ; i++) {
	Tcl_Obj *cmd;

	codeOffset += Decode(codeOffPtr);
	codeLength = Decode(codeLenPtr);
	sourceOffset += Decode(srcOffPtr);
	sourceLength = Decode(srcLenPtr);
	TclNewObj(cmd);
	Tcl_DictObjPut(NULL, cmd, Tcl_NewStringObj("codefrom", -1),
		Tcl_NewWideIntObj(codeOffset));
	Tcl_DictObjPut(NULL, cmd, Tcl_NewStringObj("codeto", -1),
		Tcl_NewWideIntObj(codeOffset + codeLength - 1));
	TclDictPut(NULL, cmd, "codefrom", Tcl_NewWideIntObj(codeOffset));
	TclDictPut(NULL, cmd, "codeto", Tcl_NewWideIntObj(
		codeOffset + codeLength - 1));

	/*
	 * Convert byte offsets to character offsets; important if multibyte
	 * characters are present in the source!
	 */

	Tcl_DictObjPut(NULL, cmd, Tcl_NewStringObj("scriptfrom", -1),
		Tcl_NewWideIntObj(Tcl_NumUtfChars(codePtr->source,
	TclDictPut(NULL, cmd, "scriptfrom", Tcl_NewWideIntObj(
		Tcl_NumUtfChars(codePtr->source, sourceOffset)));
			sourceOffset)));
	Tcl_DictObjPut(NULL, cmd, Tcl_NewStringObj("scriptto", -1),
		Tcl_NewWideIntObj(Tcl_NumUtfChars(codePtr->source,
			sourceOffset + sourceLength - 1)));
	Tcl_DictObjPut(NULL, cmd, Tcl_NewStringObj("script", -1),
	TclDictPut(NULL, cmd, "scriptto", Tcl_NewWideIntObj(
		Tcl_NumUtfChars(codePtr->source, sourceOffset + sourceLength - 1)));
	TclDictPut(NULL, cmd, "script",
		Tcl_NewStringObj(codePtr->source+sourceOffset, sourceLength));
	Tcl_ListObjAppendElement(NULL, commands, cmd);
    }

#undef Decode

    /*
     * Get the source file and line number information from the CmdFrame
     * system if it is available.
     */

    GetLocationInformation(codePtr->procPtr, &file, &line);

    /*
     * Build the overall result.
     */

    TclNewObj(description);
    Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("literals", -1),
    TclDictPut(NULL, description, "literals", literals);
	    literals);
    Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("variables", -1),
    TclDictPut(NULL, description, "variables", variables);
	    variables);
    Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("exception", -1), exn);
    Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("instructions", -1),
    TclDictPut(NULL, description, "exception", exn);
    TclDictPut(NULL, description, "instructions", instructions);
	    instructions);
    Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("auxiliary", -1), aux);
    Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("commands", -1),
    TclDictPut(NULL, description, "auxiliary", aux);
    TclDictPut(NULL, description, "commands", commands);
	    commands);
    Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("script", -1),
    TclDictPut(NULL, description, "script",
	    Tcl_NewStringObj(codePtr->source, codePtr->numSrcBytes));
    Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("namespace", -1),
	    Tcl_NewStringObj(codePtr->nsPtr->fullName, -1));
    Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("stackdepth", -1),
    TclDictPut(NULL, description, "namespace",
	    TclNewNamespaceObj((Tcl_Namespace *) codePtr->nsPtr));
    TclDictPut(NULL, description, "stackdepth",
	    Tcl_NewWideIntObj(codePtr->maxStackDepth));
    Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("exceptdepth", -1),
    TclDictPut(NULL, description, "exceptdepth",
	    Tcl_NewWideIntObj(codePtr->maxExceptDepth));
    if (line >= 0) {
	Tcl_DictObjPut(NULL, description,
	TclDictPut(NULL, description, "initiallinenumber",
		Tcl_NewStringObj("initiallinenumber", -1),
		Tcl_NewWideIntObj(line));
    }
    if (file) {
	Tcl_DictObjPut(NULL, description,
	TclDictPut(NULL, description, "sourcefile", file);
		Tcl_NewStringObj("sourcefile", -1), file);
    }
    return description;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DisassembleObjCmd --
 *
 *	Implementation of the "::tcl::unsupported::disassemble" command. This
 *	command is not documented, but will disassemble procedures, lambda
 *	terms and general scripts. Note that will compile terms if necessary
 *	in order to disassemble them.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_DisassembleObjCmd(
    ClientData clientData,	/* What type of operation. */
    void *clientData,	/* What type of operation. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static const char *const types[] = {
	"constructor", "destructor",
	"lambda", "method", "objmethod", "proc", "script", NULL
    };
    enum Types {
	DISAS_CLASS_CONSTRUCTOR, DISAS_CLASS_DESTRUCTOR,
	DISAS_LAMBDA, DISAS_CLASS_METHOD, DISAS_OBJECT_METHOD, DISAS_PROC,
	DISAS_SCRIPT
    };
    int idx, result;
    } idx;
    int result;
    Tcl_Obj *codeObjPtr = NULL;
    Proc *procPtr = NULL;
    Tcl_HashEntry *hPtr;
    Object *oPtr;
    ByteCode *codePtr;
    Method *methodPtr;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "type ...");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], types, "type", 0, &idx)!=TCL_OK){
	return TCL_ERROR;
    }

    switch ((enum Types) idx) {
    switch (idx) {
    case DISAS_LAMBDA: {
	Command cmd;
	Tcl_Obj *nsObjPtr;
	Tcl_Namespace *nsPtr;

	/*
	 * Compile (if uncompiled) and disassemble a lambda term.
1338
1339
1340
1341
1342
1343
1344
1345

1346
1347
1348
1349
1350
1351
1352
1333
1334
1335
1336
1337
1338
1339

1340
1341
1342
1343
1344
1345
1346
1347







-
+







	}

	procPtr = TclFindProc((Interp *) interp, TclGetString(objv[2]));
	if (procPtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "\"%s\" isn't a procedure", TclGetString(objv[2])));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PROC",
		    TclGetString(objv[2]), NULL);
		    TclGetString(objv[2]), (char *)NULL);
	    return TCL_ERROR;
	}

	/*
	 * Compile (if uncompiled) and disassemble a procedure.
	 */

1363
1364
1365
1366
1367
1368
1369
1370

1371
1372
1373
1374
1375
1376
1377
1358
1359
1360
1361
1362
1363
1364

1365
1366
1367
1368
1369
1370
1371
1372







-
+







	 */

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

	if (!TclHasIntRep(objv[2], &tclByteCodeType) && (TCL_OK
	if (!TclHasInternalRep(objv[2], &tclByteCodeType) && (TCL_OK
		!= TclSetByteCodeFromAny(interp, objv[2], NULL, NULL))) {
	    return TCL_ERROR;
	}
	codeObjPtr = objv[2];
	break;

    case DISAS_CLASS_CONSTRUCTOR:
1388
1389
1390
1391
1392
1393
1394
1395

1396
1397
1398
1399
1400
1401
1402
1403
1404
1405

1406
1407
1408
1409
1410
1411
1412
1413

1414
1415
1416
1417
1418
1419
1420
1421

1422
1423
1424
1425
1426
1427
1428
1383
1384
1385
1386
1387
1388
1389

1390
1391
1392
1393
1394
1395
1396
1397
1398
1399

1400
1401
1402
1403
1404
1405
1406
1407

1408
1409
1410
1411
1412
1413
1414
1415

1416
1417
1418
1419
1420
1421
1422
1423







-
+









-
+







-
+







-
+







	if (oPtr == NULL) {
	    return TCL_ERROR;
	}
	if (oPtr->classPtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "\"%s\" is not a class", TclGetString(objv[2])));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS",
		    TclGetString(objv[2]), NULL);
		    TclGetString(objv[2]), (char *)NULL);
	    return TCL_ERROR;
	}

	methodPtr = oPtr->classPtr->constructorPtr;
	if (methodPtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "\"%s\" has no defined constructor",
		    TclGetString(objv[2])));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
		    "CONSRUCTOR", NULL);
		    "CONSRUCTOR", (char *)NULL);
	    return TCL_ERROR;
	}
	procPtr = TclOOGetProcFromMethod(methodPtr);
	if (procPtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "body not available for this kind of constructor", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
		    "METHODTYPE", NULL);
		    "METHODTYPE", (char *)NULL);
	    return TCL_ERROR;
	}

	/*
	 * Compile if necessary.
	 */

	if (!TclHasIntRep(procPtr->bodyPtr, &tclByteCodeType)) {
	if (!TclHasInternalRep(procPtr->bodyPtr, &tclByteCodeType)) {
	    Command cmd;

	    /*
	     * Yes, this is ugly, but we need to pass the namespace in to the
	     * compiler in two places.
	     */

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
1478

1479
1480
1481
1482
1483
1484
1485
1486

1487
1488
1489
1490
1491
1492
1493
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
1478
1479
1480

1481
1482
1483
1484
1485
1486
1487
1488







-
+









-
+







-
+







-
+







	if (oPtr == NULL) {
	    return TCL_ERROR;
	}
	if (oPtr->classPtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "\"%s\" is not a class", TclGetString(objv[2])));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS",
		    TclGetString(objv[2]), NULL);
		    TclGetString(objv[2]), (char *)NULL);
	    return TCL_ERROR;
	}

	methodPtr = oPtr->classPtr->destructorPtr;
	if (methodPtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "\"%s\" has no defined destructor",
		    TclGetString(objv[2])));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
		    "DESRUCTOR", NULL);
		    "DESRUCTOR", (char *)NULL);
	    return TCL_ERROR;
	}
	procPtr = TclOOGetProcFromMethod(methodPtr);
	if (procPtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "body not available for this kind of destructor", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
		    "METHODTYPE", NULL);
		    "METHODTYPE", (char *)NULL);
	    return TCL_ERROR;
	}

	/*
	 * Compile if necessary.
	 */

	if (!TclHasIntRep(procPtr->bodyPtr, &tclByteCodeType)) {
	if (!TclHasInternalRep(procPtr->bodyPtr, &tclByteCodeType)) {
	    Command cmd;

	    /*
	     * Yes, this is ugly, but we need to pass the namespace in to the
	     * compiler in two places.
	     */

1518
1519
1520
1521
1522
1523
1524
1525

1526
1527
1528
1529

1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548

1549
1550
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
1513
1514
1515
1516
1517
1518
1519

1520
1521
1522
1523

1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542

1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554

1555
1556
1557
1558
1559
1560
1561
1562

1563
1564
1565

1566
1567
1568
1569
1570
1571
1572
1573







-
+



-
+


















-
+











-
+







-
+


-
+







	if (oPtr == NULL) {
	    return TCL_ERROR;
	}
	if (oPtr->classPtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "\"%s\" is not a class", TclGetString(objv[2])));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS",
		    TclGetString(objv[2]), NULL);
		    TclGetString(objv[2]), (char *)NULL);
	    return TCL_ERROR;
	}
	hPtr = Tcl_FindHashEntry(&oPtr->classPtr->classMethods,
		(char *) objv[3]);
		objv[3]);
	goto methodBody;
    case DISAS_OBJECT_METHOD:
	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "objectName methodName");
	    return TCL_ERROR;
	}

	/*
	 * Look up the body of an instance method.
	 */

	oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[2]);
	if (oPtr == NULL) {
	    return TCL_ERROR;
	}
	if (oPtr->methodsPtr == NULL) {
	    goto unknownMethod;
	}
	hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) objv[3]);
	hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, objv[3]);

	/*
	 * Compile (if necessary) and disassemble a method body.
	 */

    methodBody:
	if (hPtr == NULL) {
	unknownMethod:
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "unknown method \"%s\"", TclGetString(objv[3])));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
		    TclGetString(objv[3]), NULL);
		    TclGetString(objv[3]), (char *)NULL);
	    return TCL_ERROR;
	}
	procPtr = TclOOGetProcFromMethod((Method *)Tcl_GetHashValue(hPtr));
	if (procPtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "body not available for this kind of method", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
		    "METHODTYPE", NULL);
		    "METHODTYPE", (char *)NULL);
	    return TCL_ERROR;
	}
	if (!TclHasIntRep(procPtr->bodyPtr, &tclByteCodeType)) {
	if (!TclHasInternalRep(procPtr->bodyPtr, &tclByteCodeType)) {
	    Command cmd;

	    /*
	     * Yes, this is ugly, but we need to pass the namespace in to the
	     * compiler in two places.
	     */

1592
1593
1594
1595
1596
1597
1598
1599

1600
1601
1602
1603
1604
1605

1606
1607
1608
1609
1610
1611
1612
1587
1588
1589
1590
1591
1592
1593

1594
1595
1596
1597
1598
1599

1600
1601
1602
1603
1604
1605
1606
1607







-
+





-
+







	CLANG_ASSERT(0);
    }

    /*
     * Do the actual disassembly.
     */

    ByteCodeGetIntRep(codeObjPtr, &tclByteCodeType, codePtr);
    ByteCodeGetInternalRep(codeObjPtr, &tclByteCodeType, codePtr);

    if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"may not disassemble prebuilt bytecode", -1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE",
		"BYTECODE", NULL);
		"BYTECODE", (char *)NULL);
	return TCL_ERROR;
    }
    if (clientData) {
	Tcl_SetObjResult(interp,
		DisassembleByteCodeAsDicts(codeObjPtr));
    } else {
	Tcl_SetObjResult(interp,

Changes to generic/tclEncoding.c.

1
2
3
4
5
6

7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20





-
+






+







/*
 * tclEncoding.c --
 *
 *	Contains the implementation of the encoding conversion package.
 *
 * Copyright (c) 1996-1998 Sun Microsystems, Inc.
 * Copyright © 1996-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include <assert.h>

typedef size_t (LengthProc)(const char *src);

/*
 * The following data structure represents an encoding, which describes how to
 * convert between various character sets and UTF-8.
 */
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
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







+
+
-
+



-
+
-
-





-
+
+
+







				 * into UTF-8. */
    Tcl_EncodingConvertProc *fromUtfProc;
				/* Function to convert from UTF-8 into
				 * external encoding. */
    Tcl_EncodingFreeProc *freeProc;
				/* If non-NULL, function to call when this
				 * encoding is deleted. */
    void *clientData;		/* Arbitrary value associated with encoding
				 * type. Passed to conversion functions. */
    int nullSize;		/* Number of 0x00 bytes that signify
    Tcl_Size nullSize;		/* Number of 0x00 bytes that signify
				 * end-of-string in this encoding. This number
				 * is used to determine the source string
				 * length when the srcLen argument is
				 * negative. This number can be 1 or 2. */
				 * negative. This number can be 1, 2, or 4. */
    ClientData clientData;	/* Arbitrary value associated with encoding
				 * type. Passed to conversion functions. */
    LengthProc *lengthProc;	/* Function to compute length of
				 * null-terminated strings in this encoding.
				 * If nullSize is 1, this is strlen; if
				 * nullSize is 2, this is a function that
				 * returns the number of bytes in a 0x0000
				 * terminated string. */
				 * terminated string; if nullSize is 4, this
				 * is a function that returns the number of
				 * bytes in a 0x00000000 terminated string. */
    size_t refCount;		/* Number of uses of this structure. */
    Tcl_HashEntry *hPtr;	/* Hash table entry that owns this encoding. */
} Encoding;

/*
 * The following structure is the clientData for a dynamically-loaded,
 * table-driven encoding created by LoadTableEncoding(). It maps between
112
113
114
115
116
117
118
119


120
121
122
123
124
125
126
115
116
117
118
119
120
121

122
123
124
125
126
127
128
129
130







-
+
+







				 * conversion. */
    char prefixBytes[256];	/* If a byte in the input stream is the first
				 * character of one of the escape sequences in
				 * the following array, the corresponding
				 * entry in this array is 1, otherwise it is
				 * 0. */
    int numSubTables;		/* Length of following array. */
    EscapeSubTable subTables[TCLFLEXARRAY];/* Information about each EscapeSubTable used
    EscapeSubTable subTables[TCLFLEXARRAY];
				/* Information about each EscapeSubTable used
				 * by this encoding type. The actual size is
				 * as large as necessary to hold all
				 * EscapeSubTables. */
} EscapeEncodingData;

/*
 * Constants used when loading an encoding file to identify the type of the
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













-
+





-
+













-
+
+
+
+



-
-
-
-
-
-
-
+
-




-
-
-
+
+
+



-
+
+
+
+
+
+

+
-
+

-
+


-
+


-
+

-
-
-
+
+
+

-







 * If NULL is passed to one of the conversion routines, the current setting of
 * the system encoding is used to perform the conversion.
 */

static Tcl_Encoding defaultEncoding = NULL;
static Tcl_Encoding systemEncoding = NULL;
Tcl_Encoding tclIdentityEncoding = NULL;
Tcl_Encoding tclUtf8Encoding = NULL;

/*
 * Names of encoding profiles and corresponding integer values.
 * Keep alphabetical order for error messages.
 */
static const struct TclEncodingProfiles {
    const char *name;
    int value;
} encodingProfiles[] = {
    {"replace", TCL_ENCODING_PROFILE_REPLACE},
    {"strict", TCL_ENCODING_PROFILE_STRICT},
    {"tcl8", TCL_ENCODING_PROFILE_TCL8},
};

#define PROFILE_TCL8(flags_) \
    (ENCODING_PROFILE_GET(flags_) == TCL_ENCODING_PROFILE_TCL8)

#define PROFILE_REPLACE(flags_) \
    (ENCODING_PROFILE_GET(flags_) == TCL_ENCODING_PROFILE_REPLACE)

#define PROFILE_STRICT(flags_) \
    (!PROFILE_TCL8(flags_) && !PROFILE_REPLACE(flags_))

#define UNICODE_REPLACE_CHAR 0xFFFD
#define SURROGATE(c_)		(((c_) & ~0x7FF) == 0xD800)
#define HIGH_SURROGATE(c_)	(((c_) & ~0x3FF) == 0xD800)
#define LOW_SURROGATE(c_)	(((c_) & ~0x3FF) == 0xDC00)

/*
 * The following variable is used in the sparse matrix code for a
 * TableEncoding to represent a page in the table that has no entries.
 */

static unsigned short emptyPage[256];

/*
 * Functions used only in this module.
 */

static Tcl_EncodingConvertProc	BinaryProc;
static Tcl_DupInternalRepProc	DupEncodingIntRep;
static Tcl_DupInternalRepProc	DupEncodingInternalRep;
static Tcl_EncodingFreeProc	EscapeFreeProc;
static Tcl_EncodingConvertProc	EscapeFromUtfProc;
static Tcl_EncodingConvertProc	EscapeToUtfProc;
static void			FillEncodingFileMap(void);
static void			FreeEncoding(Tcl_Encoding encoding);
static Tcl_FreeInternalRepProc	FreeEncodingIntRep;
static Tcl_FreeInternalRepProc	FreeEncodingInternalRep;
static Encoding *		GetTableEncoding(EscapeEncodingData *dataPtr,
				    int state);
static Tcl_Encoding		LoadEncodingFile(Tcl_Interp *interp,
				    const char *name);
static Tcl_Encoding		LoadTableEncoding(const char *name, int type,
				    Tcl_Channel chan);
static Tcl_Encoding		LoadEscapeEncoding(const char *name,
				    Tcl_Channel chan);
static Tcl_Channel		OpenEncodingFileChannel(Tcl_Interp *interp,
				    const char *name);
static Tcl_EncodingFreeProc	TableFreeProc;
static Tcl_EncodingConvertProc	TableFromUtfProc;
static Tcl_EncodingConvertProc	TableToUtfProc;
static size_t			unilen(const char *src);
static size_t		unilen(const char *src);
static size_t		unilen4(const char *src);
static Tcl_EncodingConvertProc	Utf32ToUtfProc;
static Tcl_EncodingConvertProc	UtfToUtf32Proc;
static Tcl_EncodingConvertProc	Utf16ToUtfProc;
static Tcl_EncodingConvertProc	UtfToUtf16Proc;
static Tcl_EncodingConvertProc	UtfToUcs2Proc;
static int              	UtfToUtfProc(ClientData clientData,
	                            const char *src, int srcLen, int flags,
       		                    Tcl_EncodingState *statePtr, char *dst,
				    int dstLen, int *srcReadPtr,
				    int *dstWrotePtr, int *dstCharsPtr,
				    int pureNullMode);
static Tcl_EncodingConvertProc	UtfIntToUtfExtProc;
static Tcl_EncodingConvertProc	UtfToUtfProc;
static Tcl_EncodingConvertProc	UtfExtToUtfIntProc;
static Tcl_EncodingConvertProc	Iso88591FromUtfProc;
static Tcl_EncodingConvertProc	Iso88591ToUtfProc;

/*
 * A Tcl_ObjType for holding a cached Tcl_Encoding in the twoPtrValue.ptr1 field
 * of the intrep. This should help the lifetime of encodings be more useful.
 * See concerns raised in [Bug 1077262].
 * A Tcl_ObjType for holding a cached Tcl_Encoding in the twoPtrValue.ptr1
 * field of the internalrep. This should help the lifetime of encodings be more
 * useful. See concerns raised in [Bug 1077262].
 */

static const Tcl_ObjType encodingType = {
    "encoding", FreeEncodingIntRep, DupEncodingIntRep, NULL, NULL
    "encoding",
    FreeEncodingInternalRep,
    DupEncodingInternalRep,
    NULL,
    NULL,
    TCL_OBJTYPE_V0
};

#define EncodingSetIntRep(objPtr, encoding)				\
#define EncodingSetInternalRep(objPtr, encoding) \
    do {								\
	Tcl_ObjIntRep ir;						\
	Tcl_ObjInternalRep ir;						\
	ir.twoPtrValue.ptr1 = (encoding);				\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreIntRep((objPtr), &encodingType, &ir);			\
	Tcl_StoreInternalRep((objPtr), &encodingType, &ir);		\
    } while (0)

#define EncodingGetIntRep(objPtr, encoding)				\
#define EncodingGetInternalRep(objPtr, encoding) \
    do {								\
	const Tcl_ObjIntRep *irPtr;					\
	irPtr = TclFetchIntRep ((objPtr), &encodingType);		\
	(encoding) = irPtr ? (Tcl_Encoding)irPtr->twoPtrValue.ptr1 : NULL;		\
	const Tcl_ObjInternalRep *irPtr;				\
	irPtr = TclFetchInternalRep ((objPtr), &encodingType);		\
	(encoding) = irPtr ? (Tcl_Encoding)irPtr->twoPtrValue.ptr1 : NULL; \
    } while (0)


/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetEncodingFromObj --
 *
 *	Writes to (*encodingPtr) the Tcl_Encoding value of (*objPtr), if
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
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
366
367

368
369
370
371
372
373
374
375







-
+





-
+








-
+







-
+




-
+






-
+







-
+




-
+







    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    Tcl_Encoding *encodingPtr)
{
    Tcl_Encoding encoding;
    const char *name = TclGetString(objPtr);

    EncodingGetIntRep(objPtr, encoding);
    EncodingGetInternalRep(objPtr, encoding);
    if (encoding == NULL) {
	encoding = Tcl_GetEncoding(interp, name);
	if (encoding == NULL) {
	    return TCL_ERROR;
	}
	EncodingSetIntRep(objPtr, encoding);
	EncodingSetInternalRep(objPtr, encoding);
    }
    *encodingPtr = Tcl_GetEncoding(NULL, name);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * FreeEncodingIntRep --
 * FreeEncodingInternalRep --
 *
 *	The Tcl_FreeInternalRepProc for the "encoding" Tcl_ObjType.
 *
 *----------------------------------------------------------------------
 */

static void
FreeEncodingIntRep(
FreeEncodingInternalRep(
    Tcl_Obj *objPtr)
{
    Tcl_Encoding encoding;

    EncodingGetIntRep(objPtr, encoding);
    EncodingGetInternalRep(objPtr, encoding);
    Tcl_FreeEncoding(encoding);
}

/*
 *----------------------------------------------------------------------
 *
 * DupEncodingIntRep --
 * DupEncodingInternalRep --
 *
 *	The Tcl_DupInternalRepProc for the "encoding" Tcl_ObjType.
 *
 *----------------------------------------------------------------------
 */

static void
DupEncodingIntRep(
DupEncodingInternalRep(
    Tcl_Obj *srcPtr,
    Tcl_Obj *dupPtr)
{
    Tcl_Encoding encoding = Tcl_GetEncoding(NULL, TclGetString(srcPtr));
    EncodingSetIntRep(dupPtr, encoding);
    EncodingSetInternalRep(dupPtr, encoding);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetEncodingSearchPath --
 *
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
399
400
401
402
403
404
405

406
407

408
409
410

411
412
413














































414
415
416
417
418
419
420







-
+

-
+


-
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







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

int
Tcl_SetEncodingSearchPath(
    Tcl_Obj *searchPath)
{
    int dummy;
    Tcl_Size dummy;

    if (TCL_ERROR == Tcl_ListObjLength(NULL, searchPath, &dummy)) {
    if (TCL_ERROR == TclListObjLength(NULL, searchPath, &dummy)) {
	return TCL_ERROR;
    }
    TclSetProcessGlobalValue(&encodingSearchPath, searchPath, NULL);
    TclSetProcessGlobalValue(&encodingSearchPath, searchPath);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetLibraryPath --
 *
 *	Keeps the per-thread copy of the library path current with changes to
 *	the global copy.
 *
 * Results:
 *	Returns a "list" (Tcl_Obj *) that contains the library path.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TclGetLibraryPath(void)
{
    return TclGetProcessGlobalValue(&libraryPath);
}

/*
 *----------------------------------------------------------------------
 *
 * TclSetLibraryPath --
 *
 *	Keeps the per-thread copy of the library path current with changes to
 *	the global copy.
 *
 *	Since the result of this routine is void, if searchPath is not a valid
 *	list this routine silently does nothing.
 *
 *----------------------------------------------------------------------
 */

void
TclSetLibraryPath(
    Tcl_Obj *path)
{
    int dummy;

    if (TCL_ERROR == Tcl_ListObjLength(NULL, path, &dummy)) {
	return;
    }
    TclSetProcessGlobalValue(&libraryPath, path, NULL);
}

/*
 *---------------------------------------------------------------------------
 *
 * FillEncodingFileMap --
 *
 *	Called to update the encoding file map with the current value
449
450
451
452
453
454
455
456

457
458
459
460
461

462
463
464
465

466
467
468
469
470
471

472
473
474
475
476
477
478
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


558
559


560

561
562
563
564

565
566
567
568


569



570
571


572











573
574


575
576
577
578
579
580
581
582


583
584
585


586
587
588


589
590
591
592

593
594
595
596
597
598
599
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
467
468
469
470
471

472
473

474
475
476


477
478
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
558
559
560
561


562
563
564
565
566
567
568
569
570
571
572

573
574
575


576
577
578
579
580
581


582
583
584
585
586
587
588
589
590
591
592
593
594
595


596
597
598
599
600
601
602
603


604
605
606


607
608
609


610
611
612
613
614

615
616
617
618
619
620
621
622







-
+




-
+



-
+





-
+













-
+

-
+


-
-
+
+

-
+





-
+



















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
-
+
+

+





+

+
+



















-
-
+
+


+
+

+



-
+


-
-
+
+

+
+
+
-
-
+
+

+
+
+
+
+
+
+
+
+
+
+
-
-
+
+






-
-
+
+

-
-
+
+

-
-
+
+



-
+







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

static void
FillEncodingFileMap(void)
{
    int i, numDirs = 0;
    Tcl_Size i, numDirs = 0;
    Tcl_Obj *map, *searchPath;

    searchPath = Tcl_GetEncodingSearchPath();
    Tcl_IncrRefCount(searchPath);
    Tcl_ListObjLength(NULL, searchPath, &numDirs);
    TclListObjLength(NULL, searchPath, &numDirs);
    map = Tcl_NewDictObj();
    Tcl_IncrRefCount(map);

    for (i = numDirs-1; i >= 0; i--) {
    for (i = numDirs-1; i != TCL_INDEX_NONE; i--) {
	/*
	 * Iterate backwards through the search path so as we overwrite
	 * entries found, we favor files earlier on the search path.
	 */

	int j, numFiles;
	Tcl_Size j, numFiles;
	Tcl_Obj *directory, *matchFileList;
	Tcl_Obj **filev;
	Tcl_GlobTypeData readableFiles = {
	    TCL_GLOB_TYPE_FILE, TCL_GLOB_PERM_R, NULL, NULL
	};

	TclNewObj(matchFileList);
	Tcl_ListObjIndex(NULL, searchPath, i, &directory);
	Tcl_IncrRefCount(directory);
	Tcl_IncrRefCount(matchFileList);
	Tcl_FSMatchInDirectory(NULL, matchFileList, directory, "*.enc",
		&readableFiles);

	Tcl_ListObjGetElements(NULL, matchFileList, &numFiles, &filev);
	TclListObjGetElements(NULL, matchFileList, &numFiles, &filev);
	for (j=0; j<numFiles; j++) {
	    Tcl_Obj *encodingName, *fileObj;
	    Tcl_Obj *encoding, *fileObj;

	    fileObj = TclPathPart(NULL, filev[j], TCL_PATH_TAIL);
	    encodingName = TclPathPart(NULL, fileObj, TCL_PATH_ROOT);
	    Tcl_DictObjPut(NULL, map, encodingName, directory);
	    encoding = TclPathPart(NULL, fileObj, TCL_PATH_ROOT);
	    Tcl_DictObjPut(NULL, map, encoding, directory);
	    Tcl_DecrRefCount(fileObj);
	    Tcl_DecrRefCount(encodingName);
	    Tcl_DecrRefCount(encoding);
	}
	Tcl_DecrRefCount(matchFileList);
	Tcl_DecrRefCount(directory);
    }
    Tcl_DecrRefCount(searchPath);
    TclSetProcessGlobalValue(&encodingFileMap, map, NULL);
    TclSetProcessGlobalValue(&encodingFileMap, map);
    Tcl_DecrRefCount(map);
}

/*
 *---------------------------------------------------------------------------
 *
 * TclInitEncodingSubsystem --
 *
 *	Initialize all resources used by this subsystem on a per-process
 *	basis.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Depends on the memory, object, and IO subsystems.
 *
 *---------------------------------------------------------------------------
 */

/*
 * NOTE: THESE BIT DEFINITIONS SHOULD NOT OVERLAP WITH INTERNAL USE BITS
 * DEFINED IN tcl.h (TCL_ENCODING_* et al). Be cognizant of this
 * when adding bits. TODO - should really be defined in a single file.
 *
 * To prevent conflicting bits, only define bits within 0xff00 mask here.
 */
enum InternalEncodingFlags {
    TCL_ENCODING_LE = 0x100,	/* Used to distinguish LE/BE variants */
    ENCODING_UTF = 0x200,	/* For UTF-8 encoding, allow 4-byte output
				 * sequences */
    ENCODING_INPUT = 0x400	/* For UTF-8/CESU-8 encoding, means
				 * external -> internal */
};

void
TclInitEncodingSubsystem(void)
{
    Tcl_EncodingType type;
    TableEncodingData *dataPtr;
    unsigned size;
    unsigned short i;
    union {
        char c;
        short s;
	char c;
	short s;
    } isLe;
    int leFlags;

    if (encodingsInitialized) {
	return;
    }

    /* Note: This DEPENDS on TCL_ENCODING_LE being defined in least sig byte */
    isLe.s = 1;
    leFlags = isLe.c ? TCL_ENCODING_LE : 0;

    Tcl_MutexLock(&encodingMutex);
    Tcl_InitHashTable(&encodingTable, TCL_STRING_KEYS);
    Tcl_MutexUnlock(&encodingMutex);

    /*
     * Create a few initial encodings.  UTF-8 to UTF-8 translation is not a
     * no-op because it turns a stream of improperly formed UTF-8 into a
     * properly formed stream.
     */

    type.encodingName	= NULL;
    type.toUtfProc	= BinaryProc;
    type.fromUtfProc	= BinaryProc;
    type.freeProc	= NULL;
    type.nullSize	= 1;
    type.clientData	= NULL;
    tclIdentityEncoding = Tcl_CreateEncoding(&type);

    type.encodingName	= "utf-8";
    type.toUtfProc	= UtfExtToUtfIntProc;
    type.fromUtfProc	= UtfIntToUtfExtProc;
    type.toUtfProc	= UtfToUtfProc;
    type.fromUtfProc	= UtfToUtfProc;
    type.freeProc	= NULL;
    type.nullSize	= 1;
    type.clientData	= INT2PTR(ENCODING_UTF);
    tclUtf8Encoding = Tcl_CreateEncoding(&type);
    type.clientData	= NULL;
    type.encodingName	= "cesu-8";
    Tcl_CreateEncoding(&type);

    type.toUtfProc	= Utf16ToUtfProc;
    type.fromUtfProc    = UtfToUcs2Proc;
    type.fromUtfProc	= UtfToUcs2Proc;
    type.freeProc	= NULL;
    type.nullSize	= 2;
    type.encodingName   = "ucs-2le";
    type.clientData	= INT2PTR(1);
    type.encodingName	= "ucs-2le";
    type.clientData	= INT2PTR(TCL_ENCODING_LE);
    Tcl_CreateEncoding(&type);
    type.encodingName	= "ucs-2be";
    type.clientData	= NULL;
    Tcl_CreateEncoding(&type);
    type.encodingName   = "ucs-2be";
    type.clientData	= INT2PTR(0);
    type.encodingName	= "ucs-2";
    type.clientData	= INT2PTR(leFlags);
    Tcl_CreateEncoding(&type);

    type.toUtfProc	= Utf32ToUtfProc;
    type.fromUtfProc	= UtfToUtf32Proc;
    type.freeProc	= NULL;
    type.nullSize	= 4;
    type.encodingName	= "utf-32le";
    type.clientData	= INT2PTR(TCL_ENCODING_LE);
    Tcl_CreateEncoding(&type);
    type.encodingName	= "utf-32be";
    type.clientData	= NULL;
    Tcl_CreateEncoding(&type);
    type.encodingName   = "ucs-2";
    type.clientData	= INT2PTR(isLe.c);
    type.encodingName	= "utf-32";
    type.clientData	= INT2PTR(leFlags);
    Tcl_CreateEncoding(&type);

    type.toUtfProc	= Utf16ToUtfProc;
    type.fromUtfProc    = UtfToUtf16Proc;
    type.freeProc	= NULL;
    type.nullSize	= 2;
    type.encodingName   = "utf-16le";
    type.clientData	= INT2PTR(1);
    type.encodingName	= "utf-16le";
    type.clientData	= INT2PTR(TCL_ENCODING_LE);
    Tcl_CreateEncoding(&type);
    type.encodingName   = "utf-16be";
    type.clientData	= INT2PTR(0);
    type.encodingName	= "utf-16be";
    type.clientData	= NULL;
    Tcl_CreateEncoding(&type);
    type.encodingName   = "utf-16";
    type.clientData	= INT2PTR(isLe.c);
    type.encodingName	= "utf-16";
    type.clientData	= INT2PTR(leFlags);
    Tcl_CreateEncoding(&type);

#ifndef TCL_NO_DEPRECATED
    type.encodingName   = "unicode";
    type.encodingName	= "unicode";
    Tcl_CreateEncoding(&type);
#endif

    /*
     * Need the iso8859-1 encoding in order to process binary data, so force
     * it to always be embedded. Note that this encoding *must* be a proper
     * table encoding or some of the escape encodings crash! Hence the ugly
659
660
661
662
663
664
665


666
667
668
669
670
671
672
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697







+
+







    Tcl_MutexLock(&encodingMutex);
    encodingsInitialized = 0;
    FreeEncoding(systemEncoding);
    systemEncoding = NULL;
    defaultEncoding = NULL;
    FreeEncoding(tclIdentityEncoding);
    tclIdentityEncoding = NULL;
    FreeEncoding(tclUtf8Encoding);
    tclUtf8Encoding = NULL;

    hPtr = Tcl_FirstHashEntry(&encodingTable, &search);
    while (hPtr != NULL) {
	/*
	 * Call FreeEncoding instead of doing it directly to handle refcounts
	 * like escape encodings use. [Bug 524674] Make sure to call
	 * Tcl_FirstHashEntry repeatedly so that all encodings are eventually
800
801
802
803
804
805
806
807

808
809
810
811
812
813
814
825
826
827
828
829
830
831

832
833
834
835
836
837
838
839







-
+







}

/*
 *-------------------------------------------------------------------------
 *
 * Tcl_GetEncodingName --
 *
 *	Given an encoding, return the name that was used to constuct the
 *	Given an encoding, return the name that was used to construct the
 *	encoding.
 *
 * Results:
 *	The name of the encoding.
 *
 * Side effects:
 *	None.
865
866
867
868
869
870
871
872

873
874
875
876
877
878
879
890
891
892
893
894
895
896

897
898
899
900
901
902
903
904







-
+








    Tcl_MutexLock(&encodingMutex);
    for (hPtr = Tcl_FirstHashEntry(&encodingTable, &search); hPtr != NULL;
	    hPtr = Tcl_NextHashEntry(&search)) {
	Encoding *encodingPtr = (Encoding *)Tcl_GetHashValue(hPtr);

	Tcl_CreateHashEntry(&table,
		Tcl_NewStringObj(encodingPtr->name, -1), &dummy);
		Tcl_NewStringObj(encodingPtr->name, TCL_INDEX_NONE), &dummy);
    }
    Tcl_MutexUnlock(&encodingMutex);

    FillEncodingFileMap();
    map = TclGetProcessGlobalValue(&encodingFileMap);

    /*
893
894
895
896
897
898
899



























900
901
902
903
904
905
906
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    hPtr = Tcl_NextHashEntry(&search)) {
	Tcl_ListObjAppendElement(NULL, result,
		(Tcl_Obj *) Tcl_GetHashKey(&table, hPtr));
    }
    Tcl_SetObjResult(interp, result);
    Tcl_DeleteHashTable(&table);
}

/*
 *-------------------------------------------------------------------------
 *
 * Tcl_GetEncodingNulLength --
 *
 *	Given an encoding, return the number of nul bytes used for the
 *	string termination.
 *
 * Results:
 *	The number of nul bytes used for the string termination.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */
Tcl_Size
Tcl_GetEncodingNulLength(
    Tcl_Encoding encoding)
{
    if (encoding == NULL) {
	encoding = systemEncoding;
    }

    return ((Encoding *) encoding)->nullSize;
}

/*
 *------------------------------------------------------------------------
 *
 * Tcl_SetSystemEncoding --
 *
 *	Sets the default encoding that should be used whenever the user passes
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
1024


1025
1026
1027
1028
1029
1030
1031
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







-
-
+
+
+
+

-
+




-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
+
+
+

-
-
-
-
+
+
+
+

-
-
+
+







    Encoding *encodingPtr = (Encoding *)Tcl_Alloc(sizeof(Encoding));
    encodingPtr->name		= NULL;
    encodingPtr->toUtfProc	= typePtr->toUtfProc;
    encodingPtr->fromUtfProc	= typePtr->fromUtfProc;
    encodingPtr->freeProc	= typePtr->freeProc;
    encodingPtr->nullSize	= typePtr->nullSize;
    encodingPtr->clientData	= typePtr->clientData;
    if (typePtr->nullSize == 1) {
	encodingPtr->lengthProc = (LengthProc *) strlen;
    if (typePtr->nullSize == 2) {
	encodingPtr->lengthProc = (LengthProc *) unilen;
    } else if (typePtr->nullSize == 4) {
	encodingPtr->lengthProc = (LengthProc *) unilen4;
    } else {
	encodingPtr->lengthProc = (LengthProc *) unilen;
	encodingPtr->lengthProc = (LengthProc *) strlen;
    }
    encodingPtr->refCount	= 1;
    encodingPtr->hPtr		= NULL;

  if (typePtr->encodingName) {
    Tcl_HashEntry *hPtr;
    int isNew;
    char *name;
    if (typePtr->encodingName) {
	Tcl_HashEntry *hPtr;
	int isNew;
	char *name;

    Tcl_MutexLock(&encodingMutex);
    hPtr = Tcl_CreateHashEntry(&encodingTable, typePtr->encodingName, &isNew);
    if (isNew == 0) {
	/*
	 * Remove old encoding from hash table, but don't delete it until last
	 * reference goes away.
	 */
	Tcl_MutexLock(&encodingMutex);
	hPtr = Tcl_CreateHashEntry(&encodingTable, typePtr->encodingName, &isNew);
	if (isNew == 0) {
	    /*
	     * Remove old encoding from hash table, but don't delete it until last
	     * reference goes away.
	     */

	Encoding *replaceMe = (Encoding *)Tcl_GetHashValue(hPtr);
	replaceMe->hPtr = NULL;
    }
	    Encoding *replaceMe = (Encoding *)Tcl_GetHashValue(hPtr);
	    replaceMe->hPtr = NULL;
	}

    name = (char *)Tcl_Alloc(strlen(typePtr->encodingName) + 1);
    encodingPtr->name		= strcpy(name, typePtr->encodingName);
    encodingPtr->hPtr		= hPtr;
    Tcl_SetHashValue(hPtr, encodingPtr);
	name = (char *)Tcl_Alloc(strlen(typePtr->encodingName) + 1);
	encodingPtr->name	= strcpy(name, typePtr->encodingName);
	encodingPtr->hPtr	= hPtr;
	Tcl_SetHashValue(hPtr, encodingPtr);

    Tcl_MutexUnlock(&encodingMutex);
  }
	Tcl_MutexUnlock(&encodingMutex);
    }
    return (Tcl_Encoding) encodingPtr;
}

/*
 *-------------------------------------------------------------------------
 *
 * Tcl_ExternalToUtfDString --
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
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108

1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173


1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186

1187
1188
1189
1190
1191
1192
1193
1194
1195


1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212



1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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







+





-
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
+
+
+

+

+






-
+







+
-
-
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+

+
+
+
+
+
+
+
+
+
+
-
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+


+

-
-
+







 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

#undef Tcl_ExternalToUtfDString
char *
Tcl_ExternalToUtfDString(
    Tcl_Encoding encoding,	/* The encoding for the source string, or NULL
				 * for the default system encoding. */
    const char *src,		/* Source string in specified encoding. */
    size_t srcLen,		/* Source string length in bytes, or -1 for
    Tcl_Size srcLen,		/* Source string length in bytes, or < 0 for
				 * encoding-specific string length. */
    Tcl_DString *dstPtr)	/* Uninitialized or free DString in which the
				 * converted string is stored. */
{
    Tcl_ExternalToUtfDStringEx(
	NULL, encoding, src, srcLen, TCL_ENCODING_PROFILE_TCL8, dstPtr, NULL);
    return Tcl_DStringValue(dstPtr);
}

/*
 *-------------------------------------------------------------------------
 *
 * Tcl_ExternalToUtfDStringEx --
 *
 *	Convert a source buffer from the specified encoding into UTF-8.
 *	"flags" controls the behavior if any of the bytes in
 *	the source buffer are invalid or cannot be represented in utf-8.
 *	Possible flags values:
 *	target encoding. It should be composed by OR-ing the following:
 *	- *At most one* of TCL_ENCODING_PROFILE{DEFAULT,TCL8,STRICT}
 *
 * Results:
 *	The return value is one of
 *	  TCL_OK: success. Converted string in *dstPtr
 *	  TCL_ERROR: error in passed parameters. Error message in interp
 *	  TCL_CONVERT_MULTIBYTE: source ends in truncated multibyte sequence
 *	  TCL_CONVERT_SYNTAX: source is not conformant to encoding definition
 *	  TCL_CONVERT_UNKNOWN: source contained a character that could not
 *	      be represented in target encoding.
 *
 * Side effects:
 *	TCL_OK: The converted bytes are stored in the DString and NUL
 *	    terminated in an encoding-specific manner.
 *	TCL_ERROR: an error, message is stored in the interp if not NULL.
 *	TCL_CONVERT_*: if errorLocPtr is NULL, an error message is stored
 *	    in the interpreter (if not NULL). If errorLocPtr is not NULL,
 *	    no error message is stored as it is expected the caller is
 *	    interested in whatever is decoded so far and not treating this
 *	    as an error condition.
 *
 *	In addition, *dstPtr is always initialized and must be cleared
 *	by the caller irrespective of the return code.
 *
 *-------------------------------------------------------------------------
 */

int
Tcl_ExternalToUtfDStringEx(
    Tcl_Interp *interp,		/* For error messages. May be NULL. */
    Tcl_Encoding encoding,	/* The encoding for the source string, or NULL
				 * for the default system encoding. */
    const char *src,		/* Source string in specified encoding. */
    Tcl_Size srcLen,		/* Source string length in bytes, or < 0 for
				 * encoding-specific string length. */
    int flags,			/* Conversion control flags. */
    Tcl_DString *dstPtr,	/* Uninitialized or free DString in which the
				 * converted string is stored. */
    Tcl_Size *errorLocPtr)	/* Where to store the error location
				 * (or TCL_INDEX_NONE if no error). May
				 * be NULL. */
{
    char *dst;
    Tcl_EncodingState state;
    const Encoding *encodingPtr;
    int flags, result, soFar, srcRead, dstWrote, dstChars;
    size_t dstLen;
    int result;
    Tcl_Size dstLen, soFar;
    const char *srcStart = src;

    /* DO FIRST - Must always be initialized before returning */
    Tcl_DStringInit(dstPtr);

    dst = Tcl_DStringValue(dstPtr);
    dstLen = dstPtr->spaceAvl - 1;

    if (encoding == NULL) {
	encoding = systemEncoding;
    }
    encodingPtr = (Encoding *) encoding;
    encodingPtr = (Encoding *)encoding;

    if (src == NULL) {
	srcLen = 0;
    } else if (srcLen == TCL_INDEX_NONE) {
	srcLen = encodingPtr->lengthProc(src);
    }

    flags &= ~TCL_ENCODING_END;
    flags = TCL_ENCODING_START | TCL_ENCODING_END;

    flags |= TCL_ENCODING_START;
    if (encodingPtr->toUtfProc == UtfToUtfProc) {
	flags |= ENCODING_INPUT;
    }

    while (1) {
	int srcChunkLen, srcChunkRead;
	int dstChunkLen, dstChunkWrote, dstChunkChars;

	if (srcLen > INT_MAX) {
	    srcChunkLen = INT_MAX;
	} else {
	    srcChunkLen = srcLen;
	    flags |= TCL_ENCODING_END; /* Last chunk */
	}
	dstChunkLen = dstLen > INT_MAX ? INT_MAX : dstLen;

	result = encodingPtr->toUtfProc(encodingPtr->clientData, src, srcLen,
		flags, &state, dst, dstLen, &srcRead, &dstWrote, &dstChars);
	soFar = dst + dstWrote - Tcl_DStringValue(dstPtr);
	result = encodingPtr->toUtfProc(encodingPtr->clientData, src,
		srcChunkLen, flags, &state, dst, dstChunkLen,
		&srcChunkRead, &dstChunkWrote, &dstChunkChars);
	soFar = dst + dstChunkWrote - Tcl_DStringValue(dstPtr);

	src += srcChunkRead;

	/*
	 * Keep looping in two case -
	 *   - our destination buffer did not have enough room
	 *   - we had not passed in all the data and error indicated fragment
	 *     of a multibyte character
	 * In both cases we have to grow buffer, move the input source pointer
	 * and loop. Otherwise, return the result we got.
	 */
	if (result != TCL_CONVERT_NOSPACE) {
	if ((result != TCL_CONVERT_NOSPACE) &&
		!(result == TCL_CONVERT_MULTIBYTE && (flags & TCL_ENCODING_END))) {
	    Tcl_Size nBytesProcessed = (src - srcStart);

	    Tcl_DStringSetLength(dstPtr, soFar);
	    if (errorLocPtr) {
		/*
		 * Do not write error message into interpreter if caller
		 * wants to know error location.
		 */
		*errorLocPtr = result == TCL_OK
			? TCL_INDEX_NONE : nBytesProcessed;
	    } else {
		/* Caller wants error message on failure */
		if (result != TCL_OK && interp != NULL) {
		    char buf[TCL_INTEGER_SPACE];
		    snprintf(buf, sizeof(buf), "%" TCL_SIZE_MODIFIER "d",
			    nBytesProcessed);
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "unexpected byte sequence starting at index %"
			    TCL_SIZE_MODIFIER "d: '\\x%02X'",
			    nBytesProcessed, UCHAR(srcStart[nBytesProcessed])));
		    Tcl_SetErrorCode(
			    interp, "TCL", "ENCODING", "ILLEGALSEQUENCE", buf,
			    (char *)NULL);
		}
	    }
	    if (result != TCL_OK) {
		errno = (result == TCL_CONVERT_NOSPACE) ? ENOMEM : EILSEQ;
	    }
	    return Tcl_DStringValue(dstPtr);
	    return result;
	}

	/* Expand space and continue */
	flags &= ~TCL_ENCODING_START;
	src += srcRead;
	srcLen -= srcRead;
	srcLen -= srcChunkRead;
	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;
    }
1121
1122
1123
1124
1125
1126
1127
1128
1129



1130
1131
1132
1133
1134
1135
1136
1137
1138

1139
1140
1141
1142
1143
1144
1145
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







-
-
+
+
+








-
+








int
Tcl_ExternalToUtf(
    TCL_UNUSED(Tcl_Interp *),	/* TODO: Re-examine this. */
    Tcl_Encoding encoding,	/* The encoding for the source string, or NULL
				 * for the default system encoding. */
    const char *src,		/* Source string in specified encoding. */
    size_t srcLen,		/* Source string length in bytes, or -1
				 * for encoding-specific string length. */
    Tcl_Size srcLen,		/* Source string length in bytes, or
				 * TCL_INDEX_NONE for encoding-specific string
				 * length. */
    int flags,			/* Conversion control flags. */
    Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
				 * information used during a piecewise
				 * conversion. Contents of statePtr are
				 * initialized and/or reset by conversion
				 * routine under control of flags argument. */
    char *dst,			/* Output buffer in which converted string is
				 * stored. */
    size_t dstLen,		/* The maximum length of output buffer in
    Tcl_Size dstLen,		/* The maximum length of output buffer in
				 * bytes. */
    int *srcReadPtr,		/* Filled with the number of bytes from the
				 * source string that were converted. This may
				 * be less than the original source length if
				 * there was a problem converting some source
				 * characters. */
    int *dstWrotePtr,		/* Filled with the number of bytes that were
1165
1166
1167
1168
1169
1170
1171







1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186



1187
1188
1189

1190
1191
1192
1193
1194



1195





1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392

1393
1394
1395
1396
1397
1398
1399







+
+
+
+
+
+
+















+
+
+


-
+





+
+
+
-
+
+
+
+
+

-









-







	srcLen = 0;
    } else if (srcLen == TCL_INDEX_NONE) {
	srcLen = encodingPtr->lengthProc(src);
    }
    if (statePtr == NULL) {
	flags |= TCL_ENCODING_START | TCL_ENCODING_END;
	statePtr = &state;
    }
    if (srcLen > INT_MAX) {
	srcLen = INT_MAX;
	flags &= ~TCL_ENCODING_END;
    }
    if (dstLen > INT_MAX) {
	dstLen = INT_MAX;
    }
    if (srcReadPtr == NULL) {
	srcReadPtr = &srcRead;
    }
    if (dstWrotePtr == NULL) {
	dstWrotePtr = &dstWrote;
    }
    if (dstCharsPtr == NULL) {
	dstCharsPtr = &dstChars;
	flags &= ~TCL_ENCODING_CHAR_LIMIT;
    } else if (charLimited) {
	maxChars = *dstCharsPtr;
    }

    if (!noTerminate) {
	if (dstLen < 1) {
	    return TCL_CONVERT_NOSPACE;
	}
	/*
	 * If there are any null characters in the middle of the buffer,
	 * they will converted to the UTF-8 null character (\xC080). To get
	 * they will converted to the UTF-8 null character (\xC0\x80). To get
	 * the actual \0 at the end of the destination buffer, we need to
	 * append it manually.  First make room for it...
	 */

	dstLen--;
    } else {
	if (dstLen <= 0 && srcLen > 0) {
	    return TCL_CONVERT_NOSPACE;
    }
	}
    }
    if (encodingPtr->toUtfProc == UtfToUtfProc) {
	flags |= ENCODING_INPUT;
    }
    do {
	int savedFlags = flags;
	Tcl_EncodingState savedState = *statePtr;

	result = encodingPtr->toUtfProc(encodingPtr->clientData, src, srcLen,
		flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr,
		dstCharsPtr);
	if (*dstCharsPtr <= maxChars) {
	    break;
	}
	dstLen = Tcl_UtfAtIndex(dst, maxChars) - dst + (TCL_UTF_MAX - 1);
	flags = savedFlags;
	*statePtr = savedState;
    } while (1);
    if (!noTerminate) {
	/* ...and then append it */

	dst[*dstWrotePtr] = '\0';
    }
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
1416
1417
1418
1419
1420
1421
1422

1423
1424
1425
1426
1427
1428

1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492


1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514

1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528



1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543



1544
1545
1546
1547
1548
1549
1550
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







-
+





-
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
+
+
+

+

+













+
+
-
+

+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+

+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
+
+







 *	pointer to the value stored in the DString.
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

#undef Tcl_UtfToExternalDString
char *
Tcl_UtfToExternalDString(
    Tcl_Encoding encoding,	/* The encoding for the converted string, or
				 * NULL for the default system encoding. */
    const char *src,		/* Source string in UTF-8. */
    size_t srcLen,		/* Source string length in bytes, or -1 for
    Tcl_Size srcLen,		/* Source string length in bytes, or < 0 for
				 * strlen(). */
    Tcl_DString *dstPtr)	/* Uninitialized or free DString in which the
				 * converted string is stored. */
{
    Tcl_UtfToExternalDStringEx(
	NULL, encoding, src, srcLen, TCL_ENCODING_PROFILE_TCL8, dstPtr, NULL);
    return Tcl_DStringValue(dstPtr);
}

/*
 *-------------------------------------------------------------------------
 *
 * Tcl_UtfToExternalDStringEx --
 *
 *	Convert a source buffer from UTF-8 to the specified encoding.
 *	The parameter flags controls the behavior, if any of the bytes in
 *	the source buffer are invalid or cannot be represented in the
 *	target encoding. It should be composed by OR-ing the following:
 *	- *At most one* of TCL_ENCODING_PROFILE_*
 *
 * Results:
 *	The return value is one of
 *	  TCL_OK: success. Converted string in *dstPtr
 *	  TCL_ERROR: error in passed parameters. Error message in interp
 *	  TCL_CONVERT_MULTIBYTE: source ends in truncated multibyte sequence
 *	  TCL_CONVERT_SYNTAX: source is not conformant to encoding definition
 *	  TCL_CONVERT_UNKNOWN: source contained a character that could not
 *	      be represented in target encoding.
 *
 * Side effects:
 *	TCL_OK: The converted bytes are stored in the DString and NUL
 *	    terminated in an encoding-specific manner
 *	TCL_ERROR: an error, message is stored in the interp if not NULL.
 *	TCL_CONVERT_*: if errorLocPtr is NULL, an error message is stored
 *	    in the interpreter (if not NULL). If errorLocPtr is not NULL,
 *	    no error message is stored as it is expected the caller is
 *	    interested in whatever is decoded so far and not treating this
 *	    as an error condition.
 *
 *	In addition, *dstPtr is always initialized and must be cleared
 *	by the caller irrespective of the return code.
 *
 *-------------------------------------------------------------------------
 */

int
Tcl_UtfToExternalDStringEx(
    Tcl_Interp *interp,		/* For error messages. May be NULL. */
    Tcl_Encoding encoding,	/* The encoding for the converted string, or
				 * NULL for the default system encoding. */
    const char *src,		/* Source string in UTF-8. */
    Tcl_Size srcLen,		/* Source string length in bytes, or < 0 for
				 * strlen(). */
    int flags,			/* Conversion control flags. */
    Tcl_DString *dstPtr,	/* Uninitialized or free DString in which the
				 * converted string is stored. */
    Tcl_Size *errorLocPtr)	/* Where to store the error location
				 * (or TCL_INDEX_NONE if no error). May
				 * be NULL. */
{
    char *dst;
    Tcl_EncodingState state;
    const Encoding *encodingPtr;
    int flags, result, soFar, srcRead, dstWrote, dstChars;
    size_t dstLen;
    int result;
    const char *srcStart = src;
    Tcl_Size dstLen, soFar;

    /* DO FIRST - must always be initialized on return */
    Tcl_DStringInit(dstPtr);

    dst = Tcl_DStringValue(dstPtr);
    dstLen = dstPtr->spaceAvl - 1;

    if (encoding == NULL) {
	encoding = systemEncoding;
    }
    encodingPtr = (Encoding *) encoding;

    if (src == NULL) {
	srcLen = 0;
    } else if (srcLen == TCL_INDEX_NONE) {
	srcLen = strlen(src);
    }

    flags &= ~TCL_ENCODING_END;
    flags = TCL_ENCODING_START | TCL_ENCODING_END;
    flags |= TCL_ENCODING_START;
    while (1) {
	int srcChunkLen, srcChunkRead;
	int dstChunkLen, dstChunkWrote, dstChunkChars;

	if (srcLen > INT_MAX) {
	    srcChunkLen = INT_MAX;
	} else {
	    srcChunkLen = srcLen;
	    flags |= TCL_ENCODING_END; /* Last chunk */
	}
	dstChunkLen = dstLen > INT_MAX ? INT_MAX : dstLen;

	result = encodingPtr->fromUtfProc(encodingPtr->clientData, src,
		srcLen, flags, &state, dst, dstLen, &srcRead, &dstWrote,
		&dstChars);
	soFar = dst + dstWrote - Tcl_DStringValue(dstPtr);
		srcChunkLen, flags, &state, dst, dstChunkLen,
		&srcChunkRead, &dstChunkWrote, &dstChunkChars);
	soFar = dst + dstChunkWrote - Tcl_DStringValue(dstPtr);

	/* Move past the part processed in this go around */
	src += srcChunkRead;

	/*
	 * Keep looping in two case -
	 *   - our destination buffer did not have enough room
	 *   - we had not passed in all the data and error indicated fragment
	 *     of a multibyte character
	 * In both cases we have to grow buffer, move the input source pointer
	 * and loop. Otherwise, return the result we got.
	 */
	if (result != TCL_CONVERT_NOSPACE) {
	    if (encodingPtr->nullSize == 2) {
		Tcl_DStringSetLength(dstPtr, soFar + 1);
	if ((result != TCL_CONVERT_NOSPACE) &&
		!(result == TCL_CONVERT_MULTIBYTE && (flags & TCL_ENCODING_END))) {
	    Tcl_Size nBytesProcessed = (src - srcStart);
	    Tcl_Size i = soFar + encodingPtr->nullSize - 1;
	    /* Loop as DStringSetLength only stores one nul byte at a time */
	    while (i >= soFar) {
		Tcl_DStringSetLength(dstPtr, i--);
	    }
	    if (errorLocPtr) {
		/*
		 * Do not write error message into interpreter if caller
		 * wants to know error location.
		 */
		*errorLocPtr = result == TCL_OK
			? TCL_INDEX_NONE : nBytesProcessed;
	    } else {
		/* Caller wants error message on failure */
		if (result != TCL_OK && interp != NULL) {
		    Tcl_Size pos = Tcl_NumUtfChars(srcStart, nBytesProcessed);
		    int ucs4;
		    char buf[TCL_INTEGER_SPACE];
	    Tcl_DStringSetLength(dstPtr, soFar);
	    return Tcl_DStringValue(dstPtr);

		    TclUtfToUniChar(&srcStart[nBytesProcessed], &ucs4);
		    snprintf(buf, sizeof(buf), "%" TCL_SIZE_MODIFIER "d",
			    nBytesProcessed);
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "unexpected character at index %" TCL_SIZE_MODIFIER
			    "u: 'U+%06X'",
			    pos, ucs4));
		    Tcl_SetErrorCode(interp, "TCL", "ENCODING", "ILLEGALSEQUENCE",
			    buf, (char *)NULL);
		}
	    }
	    if (result != TCL_OK) {
		errno = (result == TCL_CONVERT_NOSPACE) ? ENOMEM : EILSEQ;
	    }
	    return result;
	}

	flags &= ~TCL_ENCODING_START;
	src += srcRead;
	srcLen -= srcRead;
	srcLen -= srcChunkRead;

	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;
    }
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
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







-
-
+
+








-
+








int
Tcl_UtfToExternal(
    TCL_UNUSED(Tcl_Interp *),	/* TODO: Re-examine this. */
    Tcl_Encoding encoding,	/* The encoding for the converted string, or
				 * NULL for the default system encoding. */
    const char *src,		/* Source string in UTF-8. */
    size_t srcLen,		/* Source string length in bytes, or -1
				 * for strlen(). */
    Tcl_Size srcLen,		/* Source string length in bytes, or
				 * TCL_INDEX_NONE for strlen(). */
    int flags,			/* Conversion control flags. */
    Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
				 * information used during a piecewise
				 * conversion. Contents of statePtr are
				 * initialized and/or reset by conversion
				 * routine under control of flags argument. */
    char *dst,			/* Output buffer in which converted string
				 * is stored. */
    size_t dstLen,		/* The maximum length of output buffer in
    Tcl_Size dstLen,		/* The maximum length of output buffer in
				 * bytes. */
    int *srcReadPtr,		/* Filled with the number of bytes from the
				 * source string that were converted. This may
				 * be less than the original source length if
				 * there was a problem converting some source
				 * characters. */
    int *dstWrotePtr,		/* Filled with the number of bytes that were
1354
1355
1356
1357
1358
1359
1360







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
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







+
+
+
+
+
+
+











+
+
+


-
-
-
+
+
+
+
+
+
+
-
-
-







	srcLen = 0;
    } else if (srcLen == TCL_INDEX_NONE) {
	srcLen = strlen(src);
    }
    if (statePtr == NULL) {
	flags |= TCL_ENCODING_START | TCL_ENCODING_END;
	statePtr = &state;
    }
    if (srcLen > INT_MAX) {
	srcLen = INT_MAX;
	flags &= ~TCL_ENCODING_END;
    }
    if (dstLen > INT_MAX) {
	dstLen = INT_MAX;
    }
    if (srcReadPtr == NULL) {
	srcReadPtr = &srcRead;
    }
    if (dstWrotePtr == NULL) {
	dstWrotePtr = &dstWrote;
    }
    if (dstCharsPtr == NULL) {
	dstCharsPtr = &dstChars;
    }

    if (dstLen < encodingPtr->nullSize) {
	return TCL_CONVERT_NOSPACE;
    }
    dstLen -= encodingPtr->nullSize;
    result = encodingPtr->fromUtfProc(encodingPtr->clientData, src, srcLen,
	    flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr,
	    dstCharsPtr);
    if (encodingPtr->nullSize == 2) {
	    flags, statePtr, dst, dstLen, srcReadPtr,
	    dstWrotePtr, dstCharsPtr);
    /*
     * Buffer is terminated irrespective of result. Not sure this is
     * reasonable but keep for historical/compatibility reasons.
     */
    memset(&dst[*dstWrotePtr], '\0', encodingPtr->nullSize);
	dst[*dstWrotePtr + 1] = '\0';
    }
    dst[*dstWrotePtr] = '\0';

    return result;
}

/*
 *---------------------------------------------------------------------------
 *
1395
1396
1397
1398
1399
1400
1401
1402

1403
1404
1405
1406
1407

1408
1409

1410
1411
1412
1413
1414
1415
1416
1705
1706
1707
1708
1709
1710
1711

1712
1713
1714
1715
1716

1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727







-
+




-
+


+







 * Side effects:
 *	The absolute pathname for the application is computed and stored to be
 *	returned later by [info nameofexecutable].
 *
 *---------------------------------------------------------------------------
 */
#undef Tcl_FindExecutable
void
const char *
Tcl_FindExecutable(
    const char *argv0)		/* The value of the application's argv[0]
				 * (native). */
{
    Tcl_InitSubsystems();
    const char *version = Tcl_InitSubsystems();
    TclpSetInitialEncodings();
    TclpFindExecutable(argv0);
    return version;
}

/*
 *---------------------------------------------------------------------------
 *
 * OpenEncodingFileChannel --
 *
1430
1431
1432
1433
1434
1435
1436
1437
1438

1439
1440
1441
1442
1443

1444
1445

1446
1447
1448
1449

1450
1451
1452
1453
1454
1455
1456
1741
1742
1743
1744
1745
1746
1747


1748
1749
1750
1751
1752

1753
1754

1755


1756

1757
1758
1759
1760
1761
1762
1763
1764







-
-
+




-
+

-
+
-
-

-
+








static Tcl_Channel
OpenEncodingFileChannel(
    Tcl_Interp *interp,		/* Interp for error reporting, if not NULL. */
    const char *name)		/* The name of the encoding file on disk and
				 * also the name for new encoding. */
{
    Tcl_Obj *nameObj = Tcl_NewStringObj(name, -1);
    Tcl_Obj *fileNameObj = Tcl_DuplicateObj(nameObj);
    Tcl_Obj *fileNameObj = Tcl_ObjPrintf("%s.enc", name);
    Tcl_Obj *searchPath = Tcl_DuplicateObj(Tcl_GetEncodingSearchPath());
    Tcl_Obj *map = TclGetProcessGlobalValue(&encodingFileMap);
    Tcl_Obj **dir, *path, *directory = NULL;
    Tcl_Channel chan = NULL;
    int i, numDirs;
    Tcl_Size i, numDirs;

    Tcl_ListObjGetElements(NULL, searchPath, &numDirs, &dir);
    TclListObjGetElements(NULL, searchPath, &numDirs, &dir);
    Tcl_IncrRefCount(nameObj);
    Tcl_AppendToObj(fileNameObj, ".enc", -1);
    Tcl_IncrRefCount(fileNameObj);
    Tcl_DictObjGet(NULL, map, nameObj, &directory);
    TclDictGet(NULL, map, name, &directory);

    /*
     * Check that any cached directory is still on the encoding search path.
     */

    if (NULL != directory) {
	int verified = 0;
1471
1472
1473
1474
1475
1476
1477
1478
1479


1480
1481
1482
1483
1484
1485
1486
1779
1780
1781
1782
1783
1784
1785


1786
1787
1788
1789
1790
1791
1792
1793
1794







-
-
+
+







	}
	if (!verified) {
	    /*
	     * Directory no longer on the search path. Remove from cache.
	     */

	    map = Tcl_DuplicateObj(map);
	    Tcl_DictObjRemove(NULL, map, nameObj);
	    TclSetProcessGlobalValue(&encodingFileMap, map, NULL);
	    TclDictRemove(NULL, map, name);
	    TclSetProcessGlobalValue(&encodingFileMap, map);
	    directory = NULL;
	}
    }

    if (NULL != directory) {
	/*
	 * Got a directory from the cache. Try to use it first.
1505
1506
1507
1508
1509
1510
1511
1512
1513


1514
1515
1516
1517
1518
1519
1520

1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1813
1814
1815
1816
1817
1818
1819


1820
1821
1822
1823
1824
1825
1826
1827

1828
1829
1830

1831
1832
1833
1834
1835
1836
1837







-
-
+
+






-
+


-







	Tcl_DecrRefCount(path);
	if (chan != NULL) {
	    /*
	     * Save directory in the cache.
	     */

	    map = Tcl_DuplicateObj(TclGetProcessGlobalValue(&encodingFileMap));
	    Tcl_DictObjPut(NULL, map, nameObj, dir[i]);
	    TclSetProcessGlobalValue(&encodingFileMap, map, NULL);
	    TclDictPut(NULL, map, name, dir[i]);
	    TclSetProcessGlobalValue(&encodingFileMap, map);
	}
    }

    if ((NULL == chan) && (interp != NULL)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"unknown encoding \"%s\"", name));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENCODING", name, NULL);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENCODING", name, (char *)NULL);
    }
    Tcl_DecrRefCount(fileNameObj);
    Tcl_DecrRefCount(nameObj);
    Tcl_DecrRefCount(searchPath);

    return chan;
}

/*
 *---------------------------------------------------------------------------
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
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







-
+




















-
+







    case 'E':
	encoding = LoadEscapeEncoding(name, chan);
	break;
    }
    if ((encoding == NULL) && (interp != NULL)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"invalid encoding file \"%s\"", name));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENCODING", name, NULL);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENCODING", name, (char *)NULL);
    }
    Tcl_CloseEx(NULL, chan, 0);

    return encoding;
}

/*
 *-------------------------------------------------------------------------
 *
 * LoadTableEncoding --
 *
 *	Helper function for LoadEncodingFile().  Creates a Tcl_EncodingType
 *	structure along with its corresponding TableEncodingData structure, and
 *	passes it to Tcl_Createncoding.
 *
 *	The file contains binary data but begins with a marker to indicate
 *	byte-ordering so a single binary file can be read on big or
 *	little-endian systems.
 *
 * Results:
 *	Returns the new Tcl_Encoding,  or NULL if it could could
 *	Returns the new Tcl_Encoding,  or NULL if it could
 *	not be created because the file contained invalid data.
 *
 * Side effects:
 *	See Tcl_CreateEncoding().
 *
 *-------------------------------------------------------------------------
 */
1659
1660
1661
1662
1663
1664
1665
1666

1667
1668
1669
1670
1671
1672
1673
1966
1967
1968
1969
1970
1971
1972

1973
1974
1975
1976
1977
1978
1979
1980







-
+







      0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 192 ... 207 */
      0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 208 ... 223 */
      0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 224 ... 239 */
      0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 240 ... 255 */
    };

    Tcl_DStringInit(&lineString);
    if (Tcl_Gets(chan, &lineString) == TCL_IO_FAILURE) {
    if (Tcl_Gets(chan, &lineString) < 0) {
	return NULL;
    }
    line = Tcl_DStringValue(&lineString);

    fallback = (int) strtol(line, &line, 16);
    symbol = (int) strtol(line, &line, 10);
    numPages = (int) strtol(line, &line, 10);
1701
1702
1703
1704
1705
1706
1707
1708

1709
1710
1711
1712
1713
1714
1715
2008
2009
2010
2011
2012
2013
2014

2015
2016
2017
2018
2019
2020
2021
2022







-
+







    pageMemPtr = (unsigned short *) (dataPtr->toUnicode + 256);

    TclNewObj(objPtr);
    Tcl_IncrRefCount(objPtr);
    for (i = 0; i < numPages; i++) {
	int ch;
	const char *p;
	size_t expected = 3 + 16 * (16 * 4 + 1);
	Tcl_Size expected = 3 + 16 * (16 * 4 + 1);

	if (Tcl_ReadChars(chan, objPtr, expected, 0) != expected) {
	    return NULL;
	}
	p = TclGetString(objPtr);
	hi = (staticHex[UCHAR(p[0])] << 4) + staticHex[UCHAR(p[1])];
	dataPtr->toUnicode[hi] = pageMemPtr;
1937
1938
1939
1940
1941
1942
1943
1944

1945
1946
1947
1948
1949
1950

1951
1952
1953
1954
1955
1956
1957
2244
2245
2246
2247
2248
2249
2250

2251
2252
2253
2254
2255
2256

2257
2258
2259
2260
2261
2262
2263
2264







-
+





-
+







    Tcl_EncodingType type;

    init[0] = '\0';
    final[0] = '\0';
    Tcl_DStringInit(&escapeData);

    while (1) {
	int argc;
	Tcl_Size argc;
	const char **argv;
	char *line;
	Tcl_DString lineString;

	Tcl_DStringInit(&lineString);
	if (Tcl_Gets(chan, &lineString) == TCL_IO_FAILURE) {
	if (Tcl_Gets(chan, &lineString) < 0) {
	    break;
	}
	line = Tcl_DStringValue(&lineString);
	if (Tcl_SplitList(NULL, line, &argc, &argv) != TCL_OK) {
	    Tcl_DStringFree(&lineString);
	    continue;
	}
1978
1979
1980
1981
1982
1983
1984
1985
1986


1987
1988
1989
1990
1991
1992

1993
1994
1995
1996
1997
1998
1999
2285
2286
2287
2288
2289
2290
2291


2292
2293
2294
2295
2296
2297
2298

2299
2300
2301
2302
2303
2304
2305
2306







-
-
+
+





-
+







		/*
		 * To avoid infinite recursion in [encoding system iso2022-*]
		 */

		e = (Encoding *) Tcl_GetEncoding(NULL, est.name);
		if ((e != NULL) && (e->toUtfProc != TableToUtfProc)
			&& (e->toUtfProc != Iso88591ToUtfProc)) {
		   Tcl_FreeEncoding((Tcl_Encoding) e);
		   e = NULL;
		    Tcl_FreeEncoding((Tcl_Encoding) e);
		    e = NULL;
		}
		est.encodingPtr = e;
		Tcl_DStringAppend(&escapeData, (char *) &est, sizeof(est));
	    }
	}
	Tcl_Free((void *)argv);
	Tcl_Free(argv);
	Tcl_DStringFree(&lineString);
    }

    size = offsetof(EscapeEncodingData, subTables)
	    + Tcl_DStringLength(&escapeData);
    dataPtr = (EscapeEncodingData *)Tcl_Alloc(size);
    dataPtr->initLen = strlen(init);
2047
2048
2049
2050
2051
2052
2053
2054

2055
2056
2057
2058
2059
2060
2061
2354
2355
2356
2357
2358
2359
2360

2361
2362
2363
2364
2365
2366
2367
2368







-
+







 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
BinaryProc(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    const char *src,		/* Source string (unknown encoding). */
    int srcLen,			/* Source string length in bytes. */
    int flags,			/* Conversion control flags. */
    TCL_UNUSED(Tcl_EncodingState *),
    char *dst,			/* Output buffer in which converted string is
				 * stored. */
    int dstLen,			/* The maximum length of output buffer in
2090
2091
2092
2093
2094
2095
2096
2097

2098
2099
2100
2101



2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150

2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163

2164
2165
2166

2167
2168
2169
2170
2171
2172
2173
2397
2398
2399
2400
2401
2402
2403

2404
2405



2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419






































2420













2421
2422
2423

2424
2425
2426
2427
2428
2429
2430
2431







-
+

-
-
-
+
+
+











-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+


-
+







    memcpy(dst, src, srcLen);
    return result;
}

/*
 *-------------------------------------------------------------------------
 *
 * UtfIntToUtfExtProc --
 * UtfToUtfProc --
 *
 *	Convert from UTF-8 to UTF-8. While converting null-bytes from the
 *	Tcl's internal representation (0xC0, 0x80) to the official
 *	representation (0x00). See UtfToUtfProc for details.
 *	Converts from UTF-8 to UTF-8. Note that the UTF-8 to UTF-8 translation
 *	is not a no-op, because it turns a stream of improperly formed
 *	UTF-8 into a properly-formed stream.
 *
 * Results:
 *	Returns TCL_OK if conversion was successful.
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
UtfIntToUtfExtProc(
    ClientData clientData,
    const char *src,		/* Source string in UTF-8. */
    int srcLen,			/* Source string length in bytes. */
    int flags,			/* Conversion control flags. */
    Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
				 * information used during a piecewise
				 * conversion. Contents of statePtr are
				 * initialized and/or reset by conversion
				 * routine under control of flags argument. */
    char *dst,			/* Output buffer in which converted string
				 * is stored. */
    int dstLen,			/* The maximum length of output buffer in
				 * bytes. */
    int *srcReadPtr,		/* Filled with the number of bytes from the
				 * source string that were converted. This may
				 * be less than the original source length if
				 * there was a problem converting some source
				 * characters. */
    int *dstWrotePtr,		/* Filled with the number of bytes that were
				 * stored in the output buffer as a result of
				 * the conversion. */
    int *dstCharsPtr)		/* Filled with the number of characters that
				 * correspond to the bytes stored in the
				 * output buffer. */
{
    return UtfToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
	    srcReadPtr, dstWrotePtr, dstCharsPtr, 1);
}

/*
 *-------------------------------------------------------------------------
 *
 * UtfExtToUtfIntProc --
 *
 *	Convert from UTF-8 to UTF-8 while converting null-bytes from the
 *	official representation (0x00) to Tcl's internal representation (0xC0,
 *	0x80). See UtfToUtfProc for details.
UtfToUtfProc(
 *
 * Results:
 *	Returns TCL_OK if conversion was successful.
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
UtfExtToUtfIntProc(
    ClientData clientData,
    void *clientData,		/* additional flags */
    const char *src,		/* Source string in UTF-8. */
    int srcLen,			/* Source string length in bytes. */
    int flags,			/* Conversion control flags. */
    int flags,			/* TCL_ENCODING_* conversion control flags. */
    Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
				 * information used during a piecewise
				 * conversion. Contents of statePtr are
				 * initialized and/or reset by conversion
				 * routine under control of flags argument. */
    char *dst,			/* Output buffer in which converted string is
				 * stored. */
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
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
2273
2274
2275
2276
2277

2278
2279
2280



2281
2282
2283




2284
2285
2286
2287
2288
2289

2290
2291
2292
2293
2294
2295
2296
2297
2298

2299
2300
2301






2302
2303
2304
2305
2306

2307
2308
2309
2310
2311



2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2439
2440
2441
2442
2443
2444
2445




















































2446
2447
2448

2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-



-
+
+


+
-
+













+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+












-
+
-
-
-
+
+
+
-
-
-
+
+
+
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-
-
-
+
+
+
+
+
+

-
-
-
-
+
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-







    int *dstWrotePtr,		/* Filled with the number of bytes that were
				 * stored in the output buffer as a result of
				 * the conversion. */
    int *dstCharsPtr)		/* Filled with the number of characters that
				 * correspond to the bytes stored in the
				 * output buffer. */
{
    return UtfToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
	    srcReadPtr, dstWrotePtr, dstCharsPtr, 0);
}

/*
 *-------------------------------------------------------------------------
 *
 * UtfToUtfProc --
 *
 *	Convert from UTF-8 to UTF-8. Note that the UTF-8 to UTF-8 translation
 *	is not a no-op, because it will turn a stream of improperly formed
 *	UTF-8 into a properly formed stream.
 *
 * Results:
 *	Returns TCL_OK if conversion was successful.
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
UtfToUtfProc(
    TCL_UNUSED(ClientData),
    const char *src,		/* Source string in UTF-8. */
    int srcLen,			/* Source string length in bytes. */
    int flags,			/* Conversion control flags. */
    Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
				 * information used during a piecewise
				 * conversion. Contents of statePtr are
				 * initialized and/or reset by conversion
				 * routine under control of flags argument. */
    char *dst,			/* Output buffer in which converted string is
				 * stored. */
    int dstLen,			/* The maximum length of output buffer in
				 * bytes. */
    int *srcReadPtr,		/* Filled with the number of bytes from the
				 * source string that were converted. This may
				 * be less than the original source length if
				 * there was a problem converting some source
				 * characters. */
    int *dstWrotePtr,		/* Filled with the number of bytes that were
				 * stored in the output buffer as a result of
				 * the conversion. */
    int *dstCharsPtr,		/* Filled with the number of characters that
				 * correspond to the bytes stored in the
				 * output buffer. */
    int pureNullMode)		/* Convert embedded nulls from internal
				 * representation to real null-bytes or vice
				 * versa. Also combine or separate surrogate pairs */
{
    const char *srcStart, *srcEnd, *srcClose;
    const char *dstStart, *dstEnd;
    int result, numChars, charLimit = INT_MAX;
    int *chPtr = (int *) statePtr;
    int ch;
    int profile;

    if (flags & TCL_ENCODING_START) {
	/* *statePtr will hold high surrogate in a split surrogate pair */
    	*statePtr = 0;
	*statePtr = 0;
    }
    result = TCL_OK;

    srcStart = src;
    srcEnd = src + srcLen;
    srcClose = srcEnd;
    if ((flags & TCL_ENCODING_END) == 0) {
	srcClose -= 6;
    }
    if (flags & TCL_ENCODING_CHAR_LIMIT) {
	charLimit = *dstCharsPtr;
    }

    dstStart = dst;
    flags |= PTR2INT(clientData);

    /*
     * If output is UTF-8 or encoding for Tcl's internal encoding,
     * max space needed is TCL_UTF_MAX. Otherwise, need 6 bytes (CESU-8)
     */
    dstEnd = dst + dstLen - ((flags & (ENCODING_INPUT|ENCODING_UTF)) ? TCL_UTF_MAX : 6);

    /*
     * Macro to output an isolated high surrogate when it is not followed
     * by a low surrogate. NOT to be called for strict profile since
     * that should raise an error.
     */
#define OUTPUT_ISOLATEDSURROGATE                                \
    do {                                                        \
	Tcl_UniChar high;                                       \
	if (PROFILE_REPLACE(profile)) {                         \
	    high = UNICODE_REPLACE_CHAR;                        \
	} else {                                                \
	    high = (Tcl_UniChar)(ptrdiff_t) *statePtr;          \
	}                                                       \
	assert(!(flags & ENCODING_UTF)); /* Must be CESU-8 */   \
	assert(HIGH_SURROGATE(high));                           \
	assert(!PROFILE_STRICT(profile));                       \
	dst += Tcl_UniCharToUtf(high, dst);                     \
	*statePtr = 0; /* Reset state */                        \
    } while (0)

    /*
     * Macro to check for isolated surrogate and either break with
     * an error if profile is strict, or output an appropriate
     * character for replace and tcl8 profiles and continue.
     */
#define CHECK_ISOLATEDSURROGATE                                         \
    if (*statePtr) {                                                    \
	if (PROFILE_STRICT(profile)) {                                  \
	    result = TCL_CONVERT_SYNTAX;                                \
	    break;                                                      \
	}                                                               \
	OUTPUT_ISOLATEDSURROGATE;                                       \
	continue; /* Rerun loop so length checks etc. repeated */       \
    } else                                                              \
	(void) 0

    profile = ENCODING_PROFILE_GET(flags);
    for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {

	if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
	    /*
	     * If there is more string to follow, this will ensure that the
	     * last UTF-8 character in the source buffer hasn't been cut off.
	     */

	    result = TCL_CONVERT_MULTIBYTE;
	    break;
	}
	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
	}
	if (UCHAR(*src) < 0x80 && !((UCHAR(*src) == 0) && (flags & ENCODING_INPUT))) {

	    CHECK_ISOLATEDSURROGATE;
	    /*
	     * Copy 7bit characters, but skip null-bytes when we are in input
	     * mode, so that they get converted to \xC0\x80.
	     */
	    *dst++ = *src++;
	} else if ((UCHAR(*src) == 0xC0) && (src + 1 < srcEnd) &&
		 (UCHAR(src[1]) == 0x80) &&
		 (!(flags & ENCODING_INPUT) || !PROFILE_TCL8(profile))) {
	    /* Special sequence \xC0\x80 */

	    CHECK_ISOLATEDSURROGATE;
	    if (!PROFILE_TCL8(profile) && (flags & ENCODING_INPUT)) {
		if (PROFILE_REPLACE(profile)) {
		    dst += Tcl_UniCharToUtf(UNICODE_REPLACE_CHAR, dst);
		    src += 2;
		} else {
		    /* PROFILE_STRICT */
		    result = TCL_CONVERT_SYNTAX;
		    break;
		}
	    } else {
		/*
		 * Convert 0xC080 to real nulls when we are in output mode,
		 * irrespective of the profile.
		 */
		*dst++ = 0;
		src += 2;
	    }

	} else if (!Tcl_UtfCharComplete(src, srcEnd - src)) {
	    /*
	     * Incomplete byte sequence not because there are insufficient
	     * bytes in source buffer (have already checked that above) but
	     * because the UTF-8 sequence is truncated.
	     */

	    CHECK_ISOLATEDSURROGATE;

	    if (flags & ENCODING_INPUT) {
		/* Incomplete bytes for modified UTF-8 target */
		if (PROFILE_STRICT(profile)) {
		    result = (flags & TCL_ENCODING_CHAR_LIMIT)
			    ? TCL_CONVERT_MULTIBYTE
			    : TCL_CONVERT_SYNTAX;
		    break;
		}
	    }
	    if (PROFILE_REPLACE(profile)) {
		ch = UNICODE_REPLACE_CHAR;
		++src;
	    } else {
		/* TCL_ENCODING_PROFILE_TCL8 */
		char chbuf[2];
		chbuf[0] = UCHAR(*src++); chbuf[1] = 0;
		TclUtfToUniChar(chbuf, &ch);
	    }
	    dst += Tcl_UniCharToUtf(ch, dst);
	} else {
	    /* Have a complete character */
	    size_t len = TclUtfToUniChar(src, &ch);

	    Tcl_UniChar savedSurrogate = (Tcl_UniChar) (ptrdiff_t)*statePtr;
	    *statePtr = 0; /* Reset surrogate */

	    if (flags & ENCODING_INPUT) {
		if (((len < 2) && (ch != 0)) || ((ch > 0xFFFF) && !(flags & ENCODING_UTF))) {
		    if (PROFILE_STRICT(profile)) {
			result = TCL_CONVERT_SYNTAX;
			break;
		    } else if (PROFILE_REPLACE(profile)) {
			ch = UNICODE_REPLACE_CHAR;
		    }
		}
	    }

	    const char *saveSrc = src;
	    src += len;
	    if (!(flags & ENCODING_UTF) && !(flags & ENCODING_INPUT)
		    && (ch > 0x7FF)) {
		assert(savedSurrogate == 0); /* Since this flag combo
						will never set *statePtr */
		if (ch > 0xFFFF) {
		    /* CESU-8 6-byte sequence for chars > U+FFFF */
		    ch -= 0x10000;
		    *dst++ = 0xED;
		    *dst++ = (char) (((ch >> 16) & 0x0F) | 0xA0);
		    *dst++ = (char) (((ch >> 10) & 0x3F) | 0x80);
		    ch = (ch & 0x03FF) | 0xDC00;
		}
		*dst++ = (char)(((ch >> 12) | 0xE0) & 0xEF);
		*dst++ = (char)(((ch >> 6) | 0x80) & 0xBF);
		*dst++ = (char)((ch | 0x80) & 0xBF);
		continue;
	    } else if (SURROGATE(ch)) {
		if ((flags & ENCODING_UTF)) {
		    /* UTF-8, not CESU-8, so surrogates should not appear */
		    if (PROFILE_STRICT(profile)) {
			result = (flags & ENCODING_INPUT)
			    ? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
			src = saveSrc;
			break;
		    } else if (PROFILE_REPLACE(profile)) {
			ch = UNICODE_REPLACE_CHAR;
		    } else {
			/* PROFILE_TCL8 - output as is */
		    }
		} else {
		    /* CESU-8 */
		    if (LOW_SURROGATE(ch)) {
			if (savedSurrogate) {
			    assert(HIGH_SURROGATE(savedSurrogate));
			    ch = 0x10000 + ((savedSurrogate - 0xd800) << 10) + (ch - 0xdc00);
			} else {
			    /* Isolated low surrogate */
			    if (PROFILE_STRICT(profile)) {
				result = (flags & ENCODING_INPUT)
				    ? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
				src = saveSrc;
				break;
			    } else if (PROFILE_REPLACE(profile)) {
				ch = UNICODE_REPLACE_CHAR;
			    } else {
				/* Tcl8 profile. Output low surrogate as is */
			    }
			}
		    } else {
			assert(HIGH_SURROGATE(ch));
			/* Save the high surrogate */
			*statePtr = (Tcl_EncodingState) (ptrdiff_t) ch;
			if (savedSurrogate) {
			    assert(HIGH_SURROGATE(savedSurrogate));
			    if (PROFILE_STRICT(profile)) {
				result = (flags & ENCODING_INPUT)
				    ? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
				src = saveSrc;
				break;
			    } else if (PROFILE_REPLACE(profile)) {
				ch = UNICODE_REPLACE_CHAR;
			    } else {
				/* Output the isolated high surrogate */
				ch = savedSurrogate;
			    }
			} else {
			    /* High surrogate saved in *statePtr. Do not output anything just yet. */
			    --numChars; /* Cancel the increment at end of loop */
			    continue;
			}
		    }
		}
	    } else {
		/* Normal character */
		CHECK_ISOLATEDSURROGATE;
	    }

	    dst += Tcl_UniCharToUtf(ch, dst);
	}
    }

    /* Check if an high surrogate left over */
    if (*statePtr) {
	assert(!(flags & ENCODING_UTF)); /* CESU-8, Not UTF-8 */
	if (!(flags & TCL_ENCODING_END)) {
	    /* More data coming */
	} else {
	    /* No more data coming */
	    if (PROFILE_STRICT(profile)) {
		result = (flags & ENCODING_INPUT)
		    ? TCL_CONVERT_SYNTAX : TCL_CONVERT_UNKNOWN;
	    } else {
		if (PROFILE_REPLACE(profile)) {
		    ch = UNICODE_REPLACE_CHAR;
		} else {
		    ch = (Tcl_UniChar) (ptrdiff_t) *statePtr;
		}
		if (dst < dstEnd) {
		    dst += Tcl_UniCharToUtf(ch, dst);
		    ++numChars;
		} else {
		    /* No room in destination */
		    result = TCL_CONVERT_NOSPACE;
		}
	    }
	}
    }

    *srcReadPtr = src - srcStart;
    *dstWrotePtr = dst - dstStart;
    *dstCharsPtr = numChars;
    return result;
}

/*
 *-------------------------------------------------------------------------
 *
 * Utf32ToUtfProc --
 *
 *	Convert from UTF-32 to UTF-8.
 *
 * Results:
 *	Returns TCL_OK if conversion was successful.
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
Utf32ToUtfProc(
    void *clientData,		/* additional flags, e.g. TCL_ENCODING_LE */
    const char *src,		/* Source string in Unicode. */
    int srcLen,			/* Source string length in bytes. */
    int flags,			/* Conversion control flags. */
    TCL_UNUSED(Tcl_EncodingState *),
    char *dst,			/* Output buffer in which converted string is
				 * stored. */
    int dstLen,			/* The maximum length of output buffer in
				 * bytes. */
    int *srcReadPtr,		/* Filled with the number of bytes from the
				 * source string that were converted. This may
				 * be less than the original source length if
				 * there was a problem converting some source
				 * characters. */
    int *dstWrotePtr,		/* Filled with the number of bytes that were
				 * stored in the output buffer as a result of
				 * the conversion. */
    int *dstCharsPtr)		/* Filled with the number of characters that
				 * correspond to the bytes stored in the
				 * output buffer. */
{
    const char *srcStart, *srcEnd;
    const char *dstEnd, *dstStart;
    int result, numChars, charLimit = INT_MAX;
    int ch = 0, bytesLeft = srcLen % 4;

    flags |= PTR2INT(clientData);
    if (flags & TCL_ENCODING_CHAR_LIMIT) {
	charLimit = *dstCharsPtr;
    }
    result = TCL_OK;

    /*
     * Check alignment with utf-32 (4 == sizeof(UTF-32))
     */
    if (bytesLeft != 0) {
	/* We have a truncated code unit */
	result = TCL_CONVERT_MULTIBYTE;
	srcLen -= bytesLeft;
    }

    srcStart = src;
    srcEnd = src + srcLen;

    dstStart = dst;
    dstEnd = dst + dstLen - TCL_UTF_MAX;

    for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
	}

	if (flags & TCL_ENCODING_LE) {
	    ch = (unsigned int)(src[3] & 0xFF) << 24 | (src[2] & 0xFF) << 16
		    | (src[1] & 0xFF) << 8 | (src[0] & 0xFF);
	} else {
	    ch = (unsigned int)(src[0] & 0xFF) << 24 | (src[1] & 0xFF) << 16
		    | (src[2] & 0xFF) << 8 | (src[3] & 0xFF);
	}
	if ((unsigned)ch > 0x10FFFF) {
	    if (PROFILE_STRICT(flags)) {
		result = TCL_CONVERT_SYNTAX;
		break;
	    }
	    ch = UNICODE_REPLACE_CHAR;
	} else if (SURROGATE(ch)) {
	    if (PROFILE_STRICT(flags)) {
		result = TCL_CONVERT_SYNTAX;
		break;
	    }
	    if (PROFILE_REPLACE(flags)) {
		ch = UNICODE_REPLACE_CHAR;
	    }
	}

	/*
	 * Special case for 1-byte utf chars for speed. Make sure we work with
	 * unsigned short-size data.
	 */

	if ((unsigned)ch - 1 < 0x7F) {
	    *dst++ = (ch & 0xFF);
	} else {
	    dst += Tcl_UniCharToUtf(ch, dst);
	}
	src += 4;
    }

    if ((flags & TCL_ENCODING_END) && (result == TCL_CONVERT_MULTIBYTE)) {
	/* We have a code fragment left-over at the end */
	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	} else {
	    /* destination is not full, so we really are at the end now */
	    if (PROFILE_STRICT(flags)) {
		result = TCL_CONVERT_SYNTAX;
	    } else {
		/* PROFILE_REPLACE or PROFILE_TCL8 */
		result = TCL_OK;
		dst += Tcl_UniCharToUtf(UNICODE_REPLACE_CHAR, dst);
		numChars++;
		src += bytesLeft; /* Go past truncated code unit */
	    }
	}
    }

    *srcReadPtr = src - srcStart;
    *dstWrotePtr = dst - dstStart;
    *dstCharsPtr = numChars;
    return result;
}

/*
 *-------------------------------------------------------------------------
 *
 * UtfToUtf32Proc --
 *
 *	Convert from UTF-8 to UTF-32.
 *
 * Results:
 *	Returns TCL_OK if conversion was successful.
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
UtfToUtf32Proc(
    void *clientData,		/* additional flags, e.g. TCL_ENCODING_LE */
    const char *src,		/* Source string in UTF-8. */
    int srcLen,			/* Source string length in bytes. */
    int flags,			/* Conversion control flags. */
    TCL_UNUSED(Tcl_EncodingState *),
    char *dst,			/* Output buffer in which converted string is
				 * stored. */
    int dstLen,			/* The maximum length of output buffer in
				 * bytes. */
    int *srcReadPtr,		/* Filled with the number of bytes from the
				 * source string that were converted. This may
				 * be less than the original source length if
				 * there was a problem converting some source
				 * characters. */
    int *dstWrotePtr,		/* Filled with the number of bytes that were
				 * stored in the output buffer as a result of
				 * the conversion. */
    int *dstCharsPtr)		/* Filled with the number of characters that
				 * correspond to the bytes stored in the
				 * output buffer. */
{
    const char *srcStart, *srcEnd, *srcClose, *dstStart, *dstEnd;
    int result, numChars;
    int ch, len;

    srcStart = src;
    srcEnd = src + srcLen;
    srcClose = srcEnd;
    if ((flags & TCL_ENCODING_END) == 0) {
	srcClose -= TCL_UTF_MAX;
    }

    dstStart = dst;
    dstEnd = dst + dstLen - sizeof(Tcl_UniChar);
    flags |= PTR2INT(clientData);

    result = TCL_OK;
    for (numChars = 0; src < srcEnd; numChars++) {
	if ((src > srcClose) && (!TclUCS4Complete(src, srcEnd - src))) {
	if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
	    /*
	     * If there is more string to follow, this will ensure that the
	     * last UTF-8 character in the source buffer hasn't been cut off.
	     */

	    result = TCL_CONVERT_MULTIBYTE;
	    break;
	}
	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
	}
	if (UCHAR(*src) < 0x80 && !(UCHAR(*src) == 0 && pureNullMode == 0)) {
	len = TclUtfToUniChar(src, &ch);
	    /*
	     * Copy 7bit characters, but skip null-bytes when we are in input
	     * mode, so that they get converted to 0xC080.
	if (SURROGATE(ch)) {
	    if (PROFILE_STRICT(flags)) {
		result = TCL_CONVERT_UNKNOWN;
	     */

	    *dst++ = *src++;
		break;
	    }
	    if (PROFILE_REPLACE(flags)) {
		ch = UNICODE_REPLACE_CHAR;
	} else if (pureNullMode == 1 && UCHAR(*src) == 0xC0 &&
		(src + 1 < srcEnd) && UCHAR(*(src+1)) == 0x80) {
	    /*
	     * Convert 0xC080 to real nulls when we are in output mode.
	     */

	    }
	    *dst++ = 0;
	    src += 2;
	} else if (!TclUCS4Complete(src, srcEnd - src)) {
	    /*
	     * Always check before using TclUtfToUCS4. Not doing can so
	     * cause it run beyond the end of the buffer! If we happen such an
	     * incomplete char its bytes are made to represent themselves.
	     */

	}
	    *chPtr = UCHAR(*src);
	    src += 1;
	    dst += Tcl_UniCharToUtf(*chPtr, dst);
	src += len;
	if (flags & TCL_ENCODING_LE) {
	    *dst++ = (ch & 0xFF);
	    *dst++ = ((ch >> 8) & 0xFF);
	    *dst++ = ((ch >> 16) & 0xFF);
	    *dst++ = ((ch >> 24) & 0xFF);
	} else {
	    src += TclUtfToUCS4(src, chPtr);
	    if ((*chPtr | 0x7FF) == 0xDFFF) {
		/* A surrogate character is detected, handle especially */
		int low = *chPtr;
	    *dst++ = ((ch >> 24) & 0xFF);
		size_t len = (src <= srcEnd-3) ? TclUtfToUCS4(src, &low) : 0;
		if (((low & ~0x3FF) != 0xDC00) || (*chPtr & 0x400)) {
			*dst++ = (char) (((*chPtr >> 12) | 0xE0) & 0xEF);
			*dst++ = (char) (((*chPtr >> 6) | 0x80) & 0xBF);
			*dst++ = (char) ((*chPtr | 0x80) & 0xBF);
	    *dst++ = ((ch >> 16) & 0xFF);
	    *dst++ = ((ch >> 8) & 0xFF);
	    *dst++ = (ch & 0xFF);
			continue;
		}
		src += len;
		dst += Tcl_UniCharToUtf(*chPtr, dst);
		*chPtr = low;
	    }
	    dst += Tcl_UniCharToUtf(*chPtr, dst);
	}
    }

    *srcReadPtr = src - srcStart;
    *dstWrotePtr = dst - dstStart;
    *dstCharsPtr = numChars;
    return result;
2339
2340
2341
2342
2343
2344
2345
2346

2347
2348
2349
2350
2351
2352
2353
2964
2965
2966
2967
2968
2969
2970

2971
2972
2973
2974
2975
2976
2977
2978







-
+







 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
Utf16ToUtfProc(
    ClientData clientData,	/* != NULL means LE, == NUL means BE */
    void *clientData,		/* additional flags, e.g. TCL_ENCODING_LE */
    const char *src,		/* Source string in Unicode. */
    int srcLen,			/* Source string length in bytes. */
    int flags,			/* Conversion control flags. */
    TCL_UNUSED(Tcl_EncodingState *),
    char *dst,			/* Output buffer in which converted string is
				 * stored. */
    int dstLen,			/* The maximum length of output buffer in
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
2399

2400

2401
2402
2403
2404


2405

2406
2407
2408
2409
2410



































2411











2412
2413
2414


























































































2415
2416
2417
2418
2419
2420
2421
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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
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







-
+

+





+
-
+
+
+




+
+
+
-
-
+
+
+
+
+
+



+







-
-
+
+




+
-
+




+
+
-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    int *dstCharsPtr)		/* Filled with the number of characters that
				 * correspond to the bytes stored in the
				 * output buffer. */
{
    const char *srcStart, *srcEnd;
    const char *dstEnd, *dstStart;
    int result, numChars, charLimit = INT_MAX;
    unsigned short ch;
    unsigned short ch = 0;

    flags |= PTR2INT(clientData);
    if (flags & TCL_ENCODING_CHAR_LIMIT) {
	charLimit = *dstCharsPtr;
    }
    result = TCL_OK;

    /*
    /* check alignment with utf-16 (2 == sizeof(UTF-16)) */
     * Check alignment with utf-16 (2 == sizeof(UTF-16))
     */

    if ((srcLen % 2) != 0) {
	result = TCL_CONVERT_MULTIBYTE;
	srcLen--;
    }

#if 0
    /*
    /* If last code point is a high surrogate, we cannot handle that yet */
    if ((srcLen >= 2) && ((src[srcLen - (clientData?1:2)] & 0xFC) == 0xD8)) {
     * If last code point is a high surrogate, we cannot handle that yet,
     * unless we are at the end.
     */

    if (!(flags & TCL_ENCODING_END) && (srcLen >= 2) &&
	    ((src[srcLen - ((flags & TCL_ENCODING_LE)?1:2)] & 0xFC) == 0xD8)) {
	result = TCL_CONVERT_MULTIBYTE;
	srcLen-= 2;
    }
#endif

    srcStart = src;
    srcEnd = src + srcLen;

    dstStart = dst;
    dstEnd = dst + dstLen - TCL_UTF_MAX;

    for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
	if (dst > dstEnd) {
    for (numChars = 0; src < srcEnd && numChars <= charLimit; src += 2, numChars++) {
	if (dst > dstEnd && !HIGH_SURROGATE(ch)) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
	}

	unsigned short prev = ch;
	if (clientData) {
	if (flags & TCL_ENCODING_LE) {
	    ch = (src[1] & 0xFF) << 8 | (src[0] & 0xFF);
	} else {
	    ch = (src[0] & 0xFF) << 8 | (src[1] & 0xFF);
	}
	if (HIGH_SURROGATE(prev)) {
	    if (LOW_SURROGATE(ch)) {
	/*
		/*
	 * Special case for 1-byte utf chars for speed. Make sure we work with
	 * unsigned short-size data.
	 */
	if (ch && ch < 0x80) {
	    *dst++ = (ch & 0xFF);
		 * High surrogate was followed by a low surrogate.
		 * Tcl_UniCharToUtf would have stashed away the state in dst.
		 * Call it again to combine that state with the low surrogate.
		 * We also have to compensate the numChars as two UTF-16 units
		 * have been combined into one character.
		 */
		dst += Tcl_UniCharToUtf(ch | TCL_COMBINE, dst);
	    } else {
		/* High surrogate was not followed by a low surrogate */
		if (PROFILE_STRICT(flags)) {
		    result = TCL_CONVERT_SYNTAX;
		    src -= 2;	/* Go back to beginning of high surrogate */
		    dst--;		/* Also undo writing a single byte too much */
		    break;
		}
		if (PROFILE_REPLACE(flags)) {
		    /*
		     * Previous loop wrote a single byte to mark the high surrogate.
		     * Replace it with the replacement character.
		     */
		    ch = UNICODE_REPLACE_CHAR;
		    dst--;
		    numChars++;
		    dst += Tcl_UniCharToUtf(ch, dst);
		} else {
		    /*
		     * Bug [10c2c17c32]. If Hi surrogate not followed by Lo
		     * surrogate, finish 3-byte UTF-8
		     */
		    dst += Tcl_UniCharToUtf(-1, dst);
		}
		/* Loop around again so destination space and other checks are done */
		prev = 0; /* Reset high surrogate tracker */
		src -= 2;
	    }
	} else {
	    /* Previous char was not a high surrogate */

	    /*
	     * Special case for 1-byte utf chars for speed. Make sure we work with
	     * unsigned short-size data. Order checks based on expected frequency.
	     */
	    if ((unsigned)ch - 1 < 0x7F) {
		/* ASCII except nul */
		*dst++ = (ch & 0xFF);
	    } else if (!SURROGATE(ch)) {
		/* Not ASCII, not surrogate */
	    dst += Tcl_UniCharToUtf(ch, dst);
	}
	src += sizeof(unsigned short);
		dst += Tcl_UniCharToUtf(ch, dst);
	    } else if (HIGH_SURROGATE(ch)) {
		dst += Tcl_UniCharToUtf(ch | TCL_COMBINE, dst);
		/* Do not count this just yet. Compensate for numChars++ in loop counter */
		numChars--;
	    } else {
		assert(LOW_SURROGATE(ch));
		if (PROFILE_STRICT(flags)) {
		    result = TCL_CONVERT_SYNTAX;
		    break;
		}
		if (PROFILE_REPLACE(flags)) {
		    ch = UNICODE_REPLACE_CHAR;
		}
		dst += Tcl_UniCharToUtf(ch, dst);
	    }
	}
    }

    /*
     * When the above loop ends, result may have the following values:
     * 1. TCL_OK - full source buffer was completely processed.
     *    src, dst, numChars will hold values up to that point BUT
     *    there may be a leftover high surrogate we need to deal with.
     * 2. TCL_CONVERT_NOSPACE - Ran out of room in the destination buffer.
     *    Same considerations as (1)
     * 3. TCL_CONVERT_SYNTAX - decoding error.
     * 4. TCL_CONVERT_MULTIBYTE - the buffer passed in was not fully
     *    processed, because there was a trailing single byte. However,
     *    we *may* have processed the requested number of characters already
     *    in which case the trailing byte does not matter. We still
     *    *may* still be a leftover high surrogate as in (1) and (2).
     */
    switch (result) {
    case TCL_CONVERT_MULTIBYTE: /* FALLTHRU */
    case TCL_OK: /* FALLTHRU */
    case TCL_CONVERT_NOSPACE:
	if (HIGH_SURROGATE(ch)) {
	    if (flags & TCL_ENCODING_END) {
		/*
		 * No more data expected. There will be space for output of
		 * one character (essentially overwriting the dst area holding
		 * high surrogate state)
		 */
		assert((dst-1) <= dstEnd);
		if (PROFILE_STRICT(flags)) {
		    result = TCL_CONVERT_SYNTAX;
		    src -= 2;
		    dst--;
		} else if (PROFILE_REPLACE(flags)) {
		    dst--;
		    numChars++;
		    dst += Tcl_UniCharToUtf(UNICODE_REPLACE_CHAR, dst);
		} else {
		    /* Bug [10c2c17c32]. If Hi surrogate, finish 3-byte UTF-8 */
		    numChars++;
		    dst += Tcl_UniCharToUtf(-1, dst);
		}
	    } else {
		/* More data is expected. Revert the surrogate state */
		src -= 2;
		dst--;
		/* Note: leave result of TCL_CONVERT_NOSPACE as is */
		if (result == TCL_OK) {
		    result = TCL_CONVERT_MULTIBYTE;
		}
	    }
	} else if ((flags & TCL_ENCODING_END) && (result == TCL_CONVERT_MULTIBYTE)) {
	    /*
	     * If we had a trailing byte at the end AND this is the last
	     * fragment AND profile is not "strict", stick FFFD in its place.
	     * Note in this case we DO need to check for room in dst.
	     */
	    if (dst > dstEnd) {
		result = TCL_CONVERT_NOSPACE;
	    } else {
		if (PROFILE_STRICT(flags)) {
		    result = TCL_CONVERT_SYNTAX;
		} else {
		    /* PROFILE_REPLACE or PROFILE_TCL8 */
		    result = TCL_OK;
		    dst += Tcl_UniCharToUtf(UNICODE_REPLACE_CHAR, dst);
		    numChars++;
		    src++;
		}
	    }
	}
	break;
    case TCL_CONVERT_SYNTAX:
	break; /* Nothing to do */
    }

    *srcReadPtr = src - srcStart;
    *dstWrotePtr = dst - dstStart;
    *dstCharsPtr = numChars;
    return result;
}
2434
2435
2436
2437
2438
2439
2440
2441

2442
2443
2444
2445

2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500







2501
2502
2503
2504







2505
2506
2507
2508
2509


2510
2511
2512
2513
2514
2515


2516
2517
2518
2519








2520
2521
2522
2523
2524




2525
2526
2527
2528
2529
2530

2531
2532
2533
2534
2535
2536
2537
3202
3203
3204
3205
3206
3207
3208

3209
3210
3211
3212

3213




3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231


3232



3233
3234
3235
3236
3237
3238
3239
3240
3241

3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259



3260
3261
3262
3263
3264
3265
3266




3267
3268
3269
3270
3271
3272
3273
3274




3275
3276
3277




3278
3279
3280




3281
3282
3283
3284
3285
3286
3287
3288
3289




3290
3291
3292
3293
3294




3295
3296
3297
3298
3299
3300
3301
3302
3303







-
+



-
+
-
-
-
-


















-
-
+
-
-
-
+








-
+
+
















-
-
-
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
+
+

-
-
-
-

+
+
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-

+







 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
UtfToUtf16Proc(
    ClientData clientData,	/* != NULL means LE, == NUL means BE */
    void *clientData,		/* additional flags, e.g. TCL_ENCODING_LE */
    const char *src,		/* Source string in UTF-8. */
    int srcLen,			/* Source string length in bytes. */
    int flags,			/* Conversion control flags. */
    Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
    TCL_UNUSED(Tcl_EncodingState *),
				 * information used during a piecewise
				 * conversion. Contents of statePtr are
				 * initialized and/or reset by conversion
				 * routine under control of flags argument. */
    char *dst,			/* Output buffer in which converted string is
				 * stored. */
    int dstLen,			/* The maximum length of output buffer in
				 * bytes. */
    int *srcReadPtr,		/* Filled with the number of bytes from the
				 * source string that were converted. This may
				 * be less than the original source length if
				 * there was a problem converting some source
				 * characters. */
    int *dstWrotePtr,		/* Filled with the number of bytes that were
				 * stored in the output buffer as a result of
				 * the conversion. */
    int *dstCharsPtr)		/* Filled with the number of characters that
				 * correspond to the bytes stored in the
				 * output buffer. */
{
    const char *srcStart, *srcEnd, *srcClose, *dstStart, *dstEnd;
    int result, numChars;
    Tcl_UniChar *chPtr = (Tcl_UniChar *) statePtr;

    int ch, len;
    if (flags & TCL_ENCODING_START) {
    	*statePtr = 0;
    }

    srcStart = src;
    srcEnd = src + srcLen;
    srcClose = srcEnd;
    if ((flags & TCL_ENCODING_END) == 0) {
	srcClose -= TCL_UTF_MAX;
    }

    dstStart = dst;
    dstEnd   = dst + dstLen - sizeof(Tcl_UniChar);
    dstEnd   = dst + dstLen - 2; /* 2 -> sizeof a UTF-16 code unit */
    flags |= PTR2INT(clientData);

    result = TCL_OK;
    for (numChars = 0; src < srcEnd; numChars++) {
	if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
	    /*
	     * If there is more string to follow, this will ensure that the
	     * last UTF-8 character in the source buffer hasn't been cut off.
	     */

	    result = TCL_CONVERT_MULTIBYTE;
	    break;
	}
	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
	}
	src += TclUtfToUniChar(src, chPtr);

	if (clientData) {
	len = TclUtfToUniChar(src, &ch);
	if (SURROGATE(ch)) {
	    if (PROFILE_STRICT(flags)) {
		result = TCL_CONVERT_UNKNOWN;
		break;
	    }
	    if (PROFILE_REPLACE(flags)) {
#if TCL_UTF_MAX > 3
	    if (*chPtr <= 0xFFFF) {
		*dst++ = (*chPtr & 0xFF);
		*dst++ = (*chPtr >> 8);
		ch = UNICODE_REPLACE_CHAR;
	    }
	}
	if (ch <= 0xFFFF) {
	    if (flags & TCL_ENCODING_LE) {
		*dst++ = (ch & 0xFF);
		*dst++ = (ch >> 8);
	    } else {
		*dst++ = (((*chPtr - 0x10000) >> 10) & 0xFF);
		*dst++ = (((*chPtr - 0x10000) >> 18) & 0x3) | 0xD8;
		*dst++ = (*chPtr & 0xFF);
		*dst++ = ((*chPtr & 0x3) >> 8) | 0xDC;
		*dst++ = (ch >> 8);
		*dst++ = (ch & 0xFF);
	    }
#else
	    *dst++ = (*chPtr & 0xFF);
	    *dst++ = (*chPtr >> 8);
#endif
	} else {
	    if ((dst+2) > dstEnd) {
		/* Surrogates need 2 more bytes! Bug [66da4d4228] */
#if TCL_UTF_MAX > 3
	    if (*chPtr <= 0xFFFF) {
		*dst++ = (*chPtr >> 8);
		*dst++ = (*chPtr & 0xFF);
		result = TCL_CONVERT_NOSPACE;
		break;
	    }
	    if (flags & TCL_ENCODING_LE) {
		*dst++ = (((ch - 0x10000) >> 10) & 0xFF);
		*dst++ = (((ch - 0x10000) >> 18) & 0x3) | 0xD8;
		*dst++ = (ch & 0xFF);
		*dst++ = ((ch >> 8) & 0x3) | 0xDC;
	    } else {
		*dst++ = ((*chPtr & 0x3) >> 8) | 0xDC;
		*dst++ = (*chPtr & 0xFF);
		*dst++ = (((*chPtr - 0x10000) >> 18) & 0x3) | 0xD8;
		*dst++ = (((*chPtr - 0x10000) >> 10) & 0xFF);
		*dst++ = (((ch - 0x10000) >> 18) & 0x3) | 0xD8;
		*dst++ = (((ch - 0x10000) >> 10) & 0xFF);
		*dst++ = ((ch >> 8) & 0x3) | 0xDC;
		*dst++ = (ch & 0xFF);
	    }
#else
	    *dst++ = (*chPtr >> 8);
	    *dst++ = (*chPtr & 0xFF);
#endif
	}
	src += len;
    }
    *srcReadPtr = src - srcStart;
    *dstWrotePtr = dst - dstStart;
    *dstCharsPtr = numChars;
    return result;
}

2549
2550
2551
2552
2553
2554
2555
2556

2557
2558
2559
2560
2561
2562
2563
3315
3316
3317
3318
3319
3320
3321

3322
3323
3324
3325
3326
3327
3328
3329







-
+







 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
UtfToUcs2Proc(
    ClientData clientData,	/* != NULL means LE, == NUL means BE */
    void *clientData,		/* additional flags, e.g. TCL_ENCODING_LE */
    const char *src,		/* Source string in UTF-8. */
    int srcLen,			/* Source string length in bytes. */
    int flags,			/* Conversion control flags. */
    TCL_UNUSED(Tcl_EncodingState *),
    char *dst,			/* Output buffer in which converted string is
				 * stored. */
    int dstLen,			/* The maximum length of output buffer in
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
3337
3338
3339
3340
3341
3342
3343

3344



3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355

3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372





3373
3374
3375
3376
3377
3378
3379
3380




3381
3382
3383
3384

3385
3386
3387
3388
3389
3390
3391
3392

3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405

3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425

3426
3427
3428
3429
3430
3431
3432
3433







-
+
-
-
-


+








-
+
















-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
+
+
+

-
+
+






-
+












-
+



















-
+







				 * stored in the output buffer as a result of
				 * the conversion. */
    int *dstCharsPtr)		/* Filled with the number of characters that
				 * correspond to the bytes stored in the
				 * output buffer. */
{
    const char *srcStart, *srcEnd, *srcClose, *dstStart, *dstEnd;
    int result, numChars;
    int result, numChars, len;
#if TCL_UTF_MAX <= 3
    int len;
#endif
    Tcl_UniChar ch = 0;

    flags |= PTR2INT(clientData);
    srcStart = src;
    srcEnd = src + srcLen;
    srcClose = srcEnd;
    if ((flags & TCL_ENCODING_END) == 0) {
	srcClose -= TCL_UTF_MAX;
    }

    dstStart = dst;
    dstEnd   = dst + dstLen - sizeof(Tcl_UniChar);
    dstEnd   = dst + dstLen - 2; /* 2 - size of UCS code unit */

    result = TCL_OK;
    for (numChars = 0; src < srcEnd; numChars++) {
	if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
	    /*
	     * If there is more string to follow, this will ensure that the
	     * last UTF-8 character in the source buffer hasn't been cut off.
	     */

	    result = TCL_CONVERT_MULTIBYTE;
	    break;
	}
	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
	}
#if TCL_UTF_MAX <= 3
	src += (len = TclUtfToUniChar(src, &ch));
	if ((ch >= 0xD800) && (len < 3)) {
	    src += TclUtfToUniChar(src, &ch);
	    ch = 0xFFFD;
	len = TclUtfToUniChar(src, &ch);
	if (ch > 0xFFFF) {
	    if (PROFILE_STRICT(flags)) {
		result = TCL_CONVERT_UNKNOWN;
		break;
	    }
	    ch = UNICODE_REPLACE_CHAR;
	}
#else
	src += TclUtfToUniChar(src, &ch);
	if (ch > 0xFFFF) {
	    ch = 0xFFFD;
	if (PROFILE_STRICT(flags) && SURROGATE(ch)) {
	    result = TCL_CONVERT_SYNTAX;
	    break;
	}
#endif

	src += len;

	/*
	 * Need to handle this in a way that won't cause misalignment by
	 * casting dst to a Tcl_UniChar. [Bug 1122671]
	 */

	if (clientData) {
	if (flags & TCL_ENCODING_LE) {
	    *dst++ = (ch & 0xFF);
	    *dst++ = (ch >> 8);
	} else {
	    *dst++ = (ch >> 8);
	    *dst++ = (ch & 0xFF);
	}
    }
    *srcReadPtr = src - srcStart;
    *dstWrotePtr = dst - dstStart;
    *dstCharsPtr = numChars;
    return result;
}


/*
 *-------------------------------------------------------------------------
 *
 * TableToUtfProc --
 *
 *	Convert from the encoding specified by the TableEncodingData into
 *	UTF-8.
 *
 * Results:
 *	Returns TCL_OK if conversion was successful.
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
TableToUtfProc(
    ClientData clientData,	/* TableEncodingData that specifies
    void *clientData,		/* TableEncodingData that specifies
				 * encoding. */
    const char *src,		/* Source string in specified encoding. */
    int srcLen,			/* Source string length in bytes. */
    int flags,			/* Conversion control flags. */
    TCL_UNUSED(Tcl_EncodingState *),
    char *dst,			/* Output buffer in which converted string is
				 * stored. */
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
3470
3471
3472
3473
3474
3475
3476







3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499

3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511

3512
3513
3514
3515
3516

3517
3518
3519

3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535







-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+
-
+






+
+
+
+
+
-
+
+



-
+


-
+







+







    for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
	}
	byte = *((unsigned char *) src);
	if (prefixBytes[byte]) {
	    src++;
	    if (src >= srcEnd) {
		src--;
		result = TCL_CONVERT_MULTIBYTE;
		break;
	    }
	    ch = toUnicode[byte][*((unsigned char *) src)];
	    if (src >= srcEnd-1) {
		/* Prefix byte but nothing after it */
		if (!(flags & TCL_ENCODING_END)) {
		    /* More data to come */
		    result = TCL_CONVERT_MULTIBYTE;
		    break;
		} else if (PROFILE_STRICT(flags)) {
		    result = TCL_CONVERT_SYNTAX;
		    break;
		} else if (PROFILE_REPLACE(flags)) {
		    ch = UNICODE_REPLACE_CHAR;
		} else {
		    /* For prefix bytes, we don't fallback to cp1252, see [1355b9a874] */
		    ch = byte;
		}
	    } else {
		ch = toUnicode[byte][*((unsigned char *)++src)];
	    }
	} else {
	    ch = pageZero[byte];
	}
	if ((ch == 0) && (byte != 0)) {
	    /* Prefix+suffix pair is invalid */
	    if (flags & TCL_ENCODING_STOPONERROR) {
	    if (PROFILE_STRICT(flags)) {
		result = TCL_CONVERT_SYNTAX;
		break;
	    }
	    if (prefixBytes[byte]) {
		src--;
	    }
	    if (PROFILE_REPLACE(flags)) {
		ch = UNICODE_REPLACE_CHAR;
	    } else {
		char chbuf[2];
		chbuf[0] = byte; chbuf[1] = 0;
	    ch = (Tcl_UniChar) byte;
		TclUtfToUniChar(chbuf, &ch);
	    }
	}

	/*
	 * Special case for 1-byte utf chars for speed.
	 * Special case for 1-byte Utf chars for speed.
	 */

	if (ch && ch < 0x80) {
	if ((unsigned)ch - 1 < 0x7F) {
	    *dst++ = (char) ch;
	} else {
	    dst += Tcl_UniCharToUtf(ch, dst);
	}
	src++;
    }

    assert(src <= srcEnd);
    *srcReadPtr = src - srcStart;
    *dstWrotePtr = dst - dstStart;
    *dstCharsPtr = numChars;
    return result;
}

/*
2762
2763
2764
2765
2766
2767
2768
2769

2770
2771
2772
2773
2774
2775
2776
3547
3548
3549
3550
3551
3552
3553

3554
3555
3556
3557
3558
3559
3560
3561







-
+







 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
TableFromUtfProc(
    ClientData clientData,	/* TableEncodingData that specifies
    void *clientData,		/* TableEncodingData that specifies
				 * encoding. */
    const char *src,		/* Source string in UTF-8. */
    int srcLen,			/* Source string length in bytes. */
    int flags,			/* Conversion control flags. */
    TCL_UNUSED(Tcl_EncodingState *),
    char *dst,			/* Output buffer in which converted string is
				 * stored. */
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
3603
3604
3605
3606
3607
3608
3609






3610
3611
3612

3613





3614

3615
3616
3617

3618
3619
3620
3621

3622
3623
3624
3625
3626
3627
3628
3629







-
-
-
-
-
-
+


-
+
-
-
-
-
-

-
+
+

-
+



-
+







	     */

	    result = TCL_CONVERT_MULTIBYTE;
	    break;
	}
	len = TclUtfToUniChar(src, &ch);

#if TCL_UTF_MAX > 3
	/*
	 * This prevents a crash condition. More evaluation is required for
	 * full support of int Tcl_UniChar. [Bug 1004065]
	 */

	/* Unicode chars > +U0FFFF cannot be represented in any table encoding */
	if (ch & 0xFFFF0000) {
	    word = 0;
	} else
	} else {
#else
	if (!len) {
	    word = 0;
	} else
#endif
	    word = fromUnicode[(ch >> 8)][ch & 0xFF];

	}

	if ((word == 0) && (ch != 0)) {
	    if (flags & TCL_ENCODING_STOPONERROR) {
	    if (PROFILE_STRICT(flags)) {
		result = TCL_CONVERT_UNKNOWN;
		break;
	    }
	    word = dataPtr->fallback;
	    word = dataPtr->fallback; /* Both profiles REPLACE and TCL8 */
	}
	if (prefixBytes[(word >> 8)] != 0) {
	    if (dst + 1 > dstEnd) {
		result = TCL_CONVERT_NOSPACE;
		break;
	    }
	    dst[0] = (char) (word >> 8);
2884
2885
2886
2887
2888
2889
2890
2891

2892
2893
2894
2895
2896
2897
2898
3660
3661
3662
3663
3664
3665
3666

3667
3668
3669
3670
3671
3672
3673
3674







-
+







 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
Iso88591ToUtfProc(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    const char *src,		/* Source string in specified encoding. */
    int srcLen,			/* Source string length in bytes. */
    int flags,			/* Conversion control flags. */
    TCL_UNUSED(Tcl_EncodingState *),
    char *dst,			/* Output buffer in which converted string is
				 * stored. */
    int dstLen,			/* The maximum length of output buffer in
2926
2927
2928
2929
2930
2931
2932
2933

2934
2935
2936
2937
2938
2939

2940
2941
2942
2943
2944
2945
2946
3702
3703
3704
3705
3706
3707
3708

3709
3710
3711
3712
3713
3714

3715
3716
3717
3718
3719
3720
3721
3722







-
+





-
+







    for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
	Tcl_UniChar ch = 0;

	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
	}
	ch = (Tcl_UniChar) *((unsigned char *) src);
	ch = *((unsigned char *) src);

	/*
	 * Special case for 1-byte utf chars for speed.
	 */

	if (ch && ch < 0x80) {
	if ((unsigned)ch - 1 < 0x7F) {
	    *dst++ = (char) ch;
	} else {
	    dst += Tcl_UniCharToUtf(ch, dst);
	}
	src++;
    }

2964
2965
2966
2967
2968
2969
2970
2971

2972
2973
2974
2975
2976
2977
2978
3740
3741
3742
3743
3744
3745
3746

3747
3748
3749
3750
3751
3752
3753
3754







-
+







 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
Iso88591FromUtfProc(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    const char *src,		/* Source string in UTF-8. */
    int srcLen,			/* Source string length in bytes. */
    int flags,			/* Conversion control flags. */
    TCL_UNUSED(Tcl_EncodingState *),
    char *dst,			/* Output buffer in which converted string is
				 * stored. */
    int dstLen,			/* The maximum length of output buffer in
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
3794
3795
3796
3797
3798
3799
3800

3801




3802

3803
3804
3805



3806
3807
3808
3809

3810
3811
3812
3813
3814
3815
3816
3817







-
+
-
-
-
-
+
-



-
-
-




-
+







	}
	len = TclUtfToUniChar(src, &ch);

	/*
	 * Check for illegal characters.
	 */

	if (ch > 0xFF
	if (ch > 0xFF) {
#if TCL_UTF_MAX <= 3
		|| ((ch >= 0xD800) && (len < 3))
#endif
		) {
	    if (PROFILE_STRICT(flags)) {
	    if (flags & TCL_ENCODING_STOPONERROR) {
		result = TCL_CONVERT_UNKNOWN;
		break;
	    }
#if TCL_UTF_MAX <= 3
	    if ((ch >= 0xD800) && (len < 3)) len = 4;
#endif
	    /*
	     * Plunge on, using '?' as a fallback character.
	     */

	    ch = (Tcl_UniChar) '?';
	    ch = '?'; /* Profiles TCL8 and REPLACE */
	}

	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
	}
	*(dst++) = (char) ch;
3070
3071
3072
3073
3074
3075
3076
3077

3078
3079
3080
3081
3082
3083
3084
3839
3840
3841
3842
3843
3844
3845

3846
3847
3848
3849
3850
3851
3852
3853







-
+







 *	Memory freed.
 *
 *---------------------------------------------------------------------------
 */

static void
TableFreeProc(
    ClientData clientData)	/* TableEncodingData that specifies
    void *clientData)		/* TableEncodingData that specifies
				 * encoding. */
{
    TableEncodingData *dataPtr = (TableEncodingData *)clientData;

    /*
     * Make sure we aren't freeing twice on shutdown. [Bug 219314]
     */
3105
3106
3107
3108
3109
3110
3111
3112

3113
3114
3115
3116
3117
3118
3119
3874
3875
3876
3877
3878
3879
3880

3881
3882
3883
3884
3885
3886
3887
3888







-
+







 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
EscapeToUtfProc(
    ClientData clientData,	/* EscapeEncodingData that specifies
    void *clientData,		/* EscapeEncodingData that specifies
				 * encoding. */
    const char *src,		/* Source string in specified encoding. */
    int srcLen,			/* Source string length in bytes. */
    int flags,			/* Conversion control flags. */
    Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
				 * information used during a piecewise
				 * conversion. Contents of statePtr are
3248
3249
3250
3251
3252
3253
3254
3255

3256
3257


3258
3259
3260


3261
3262
3263
3264
3265
3266
3267
4017
4018
4019
4020
4021
4022
4023

4024


4025
4026



4027
4028
4029
4030
4031
4032
4033
4034
4035







-
+
-
-
+
+
-
-
-
+
+







	     * We have a split-up or unrecognized escape sequence. If we
	     * checked all the sequences, then it's a syntax error, otherwise
	     * we need more bytes to determine a match.
	     */

	    if ((checked == dataPtr->numSubTables + 2)
		    || (flags & TCL_ENCODING_END)) {
		if ((flags & TCL_ENCODING_STOPONERROR) == 0) {
		if (!PROFILE_STRICT(flags)) {
		    /*
		     * Skip the unknown escape sequence.
		    unsigned skip = longest > left ? left : longest;
		    /* Unknown escape sequence */
		     */

		    src += longest;
		    dst += Tcl_UniCharToUtf(UNICODE_REPLACE_CHAR, dst);
		    src += skip;
		    continue;
		}
		result = TCL_CONVERT_SYNTAX;
	    } else {
		result = TCL_CONVERT_MULTIBYTE;
	    }
	    break;
3319
3320
3321
3322
3323
3324
3325
3326

3327
3328
3329
3330
3331
3332
3333
4087
4088
4089
4090
4091
4092
4093

4094
4095
4096
4097
4098
4099
4100
4101







-
+







 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
EscapeFromUtfProc(
    ClientData clientData,	/* EscapeEncodingData that specifies
    void *clientData,		/* EscapeEncodingData that specifies
				 * encoding. */
    const char *src,		/* Source string in UTF-8. */
    int srcLen,			/* Source string length in bytes. */
    int flags,			/* Conversion control flags. */
    Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
				 * information used during a piecewise
				 * conversion. Contents of statePtr are
3405
3406
3407
3408
3409
3410
3411









3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430

3431
3432
3433
3434
3435
3436
3437
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206

4207
4208
4209
4210
4211
4212
4213
4214







+
+
+
+
+
+
+
+
+


















-
+







	     * last UTF-8 character in the source buffer hasn't been cut off.
	     */

	    result = TCL_CONVERT_MULTIBYTE;
	    break;
	}
	len = TclUtfToUniChar(src, &ch);
	if (ch > 0xFFFF) {
	    /* Bug 201c7a3aa6 crash - tables are 256x256 (64K) */
	    if (PROFILE_STRICT(flags)) {
		result = TCL_CONVERT_SYNTAX;
		break;
	    }
	    /* Will be encoded as encoding specific replacement below */
	    ch = UNICODE_REPLACE_CHAR;
	}
	word = tableFromUnicode[(ch >> 8)][ch & 0xFF];

	if ((word == 0) && (ch != 0)) {
	    int oldState;
	    const EscapeSubTable *subTablePtr;

	    oldState = state;
	    for (state = 0; state < dataPtr->numSubTables; state++) {
		encodingPtr = GetTableEncoding(dataPtr, state);
		tableDataPtr = (const TableEncodingData *)encodingPtr->clientData;
		word = tableDataPtr->fromUnicode[(ch >> 8)][ch & 0xFF];
		if (word != 0) {
		    break;
		}
	    }

	    if (word == 0) {
		state = oldState;
		if (flags & TCL_ENCODING_STOPONERROR) {
		if (PROFILE_STRICT(flags)) {
		    result = TCL_CONVERT_UNKNOWN;
		    break;
		}
		encodingPtr = GetTableEncoding(dataPtr, state);
		tableDataPtr = (const TableEncodingData *)encodingPtr->clientData;
		word = tableDataPtr->fallback;
	    }
3530
3531
3532
3533
3534
3535
3536
3537

3538
3539
3540
3541
3542
3543
3544
4307
4308
4309
4310
4311
4312
4313

4314
4315
4316
4317
4318
4319
4320
4321







-
+







 *	Memory is freed.
 *
 *---------------------------------------------------------------------------
 */

static void
EscapeFreeProc(
    ClientData clientData)	/* EscapeEncodingData that specifies
    void *clientData)		/* EscapeEncodingData that specifies
				 * encoding. */
{
    EscapeEncodingData *dataPtr = (EscapeEncodingData *)clientData;
    EscapeSubTable *subTablePtr;
    int i;

    if (dataPtr == NULL) {
3607
3608
3609
3610
3611
3612
3613
3614

3615
3616
3617
3618
3619
3620
3621
4384
4385
4386
4387
4388
4389
4390

4391
4392
4393
4394
4395
4396
4397
4398







-
+








    return encodingPtr;
}

/*
 *---------------------------------------------------------------------------
 *
 * unilen --
 * unilen, unilen4 --
 *
 *	A helper function for the Tcl_ExternalToUtf functions. This function
 *	is similar to strlen for double-byte characters: it returns the number
 *	of bytes in a 0x0000 terminated string.
 *
 * Results:
 *	As above.
3631
3632
3633
3634
3635
3636
3637













3638
3639
3640
3641
3642
3643
3644
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







+
+
+
+
+
+
+
+
+
+
+
+
+







    const char *src)
{
    unsigned short *p;

    p = (unsigned short *) src;
    while (*p != 0x0000) {
	p++;
    }
    return (char *) p - src;
}

static size_t
unilen4(
    const char *src)
{
    unsigned int *p;

    p = (unsigned int *) src;
    while (*p != 0x00000000) {
	p++;
    }
    return (char *) p - src;
}

/*
 *-------------------------------------------------------------------------
 *
3665
3666
3667
3668
3669
3670
3671
3672

3673
3674
3675
3676
3677
3678
3679

3680
3681

3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704





3705
3706


















































































































3707
3708
3709
3710
3711
3712
3713
3714
4455
4456
4457
4458
4459
4460
4461

4462
4463
4464
4465
4466
4467
4468

4469
4470

4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491



4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620







-
+






-
+

-
+




















-
-
-
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








static void
InitializeEncodingSearchPath(
    char **valuePtr,
    size_t *lengthPtr,
    Tcl_Encoding *encodingPtr)
{
    const char *bytes;
    int i, numDirs;
    Tcl_Size i, numDirs, numBytes;
    Tcl_Obj *libPathObj, *encodingObj, *searchPathObj;

    TclNewLiteralStringObj(encodingObj, "encoding");
    TclNewObj(searchPathObj);
    Tcl_IncrRefCount(encodingObj);
    Tcl_IncrRefCount(searchPathObj);
    libPathObj = TclGetLibraryPath();
    libPathObj = TclGetProcessGlobalValue(&libraryPath);
    Tcl_IncrRefCount(libPathObj);
    Tcl_ListObjLength(NULL, libPathObj, &numDirs);
    TclListObjLength(NULL, libPathObj, &numDirs);

    for (i = 0; i < numDirs; i++) {
	Tcl_Obj *directoryObj, *pathObj;
	Tcl_StatBuf stat;

	Tcl_ListObjIndex(NULL, libPathObj, i, &directoryObj);
	pathObj = Tcl_FSJoinToPath(directoryObj, 1, &encodingObj);
	Tcl_IncrRefCount(pathObj);
	if ((0 == Tcl_FSStat(pathObj, &stat)) && S_ISDIR(stat.st_mode)) {
	    Tcl_ListObjAppendElement(NULL, searchPathObj, pathObj);
	}
	Tcl_DecrRefCount(pathObj);
    }

    Tcl_DecrRefCount(libPathObj);
    Tcl_DecrRefCount(encodingObj);
    *encodingPtr = libraryPath.encoding;
    if (*encodingPtr) {
	((Encoding *)(*encodingPtr))->refCount++;
    }
    bytes = TclGetStringFromObj(searchPathObj, lengthPtr);
    *valuePtr = (char *)Tcl_Alloc(*lengthPtr + 1);
    memcpy(*valuePtr, bytes, *lengthPtr + 1);
    bytes = TclGetStringFromObj(searchPathObj, &numBytes);

    *lengthPtr = numBytes;
    *valuePtr = (char *)Tcl_Alloc(numBytes + 1);
    memcpy(*valuePtr, bytes, numBytes + 1);
    Tcl_DecrRefCount(searchPathObj);
}

/*
 *------------------------------------------------------------------------
 *
 * TclEncodingProfileParseName --
 *
 *	Maps an encoding profile name to its integer equivalent.
 *
 * Results:
 *	TCL_OK on success or TCL_ERROR on failure.
 *
 * Side effects:
 *	Returns the profile enum value in *profilePtr
 *
 *------------------------------------------------------------------------
 */
int
TclEncodingProfileNameToId(
    Tcl_Interp *interp,		/* For error messages. May be NULL */
    const char *profileName,	/* Name of profile */
    int *profilePtr)		/* Output */
{
    size_t i;
    size_t numProfiles = sizeof(encodingProfiles) / sizeof(encodingProfiles[0]);

    for (i = 0; i < numProfiles; ++i) {
	if (!strcmp(profileName, encodingProfiles[i].name)) {
	    *profilePtr = encodingProfiles[i].value;
	    return TCL_OK;
	}
    }
    if (interp) {
	/* This code assumes at least two profiles :-) */
	Tcl_Obj *errorObj = Tcl_ObjPrintf("bad profile name \"%s\": must be",
		profileName);
	for (i = 0; i < (numProfiles - 1); ++i) {
	    Tcl_AppendStringsToObj(
		    errorObj, " ", encodingProfiles[i].name, ",", (char *)NULL);
	}
	Tcl_AppendStringsToObj(
		errorObj, " or ", encodingProfiles[numProfiles-1].name, (char *)NULL);

	Tcl_SetObjResult(interp, errorObj);
	Tcl_SetErrorCode(
		interp, "TCL", "ENCODING", "PROFILE", profileName, (char *)NULL);
    }
    return TCL_ERROR;
}

/*
 *------------------------------------------------------------------------
 *
 * TclEncodingProfileValueToName --
 *
 *	Maps an encoding profile value to its name.
 *
 * Results:
 *	Pointer to the name or NULL on failure. Caller must not make
 *	not modify the string and must make a copy to hold on to it.
 *
 * Side effects:
 *	None.
 *------------------------------------------------------------------------
 */
const char *
TclEncodingProfileIdToName(
    Tcl_Interp *interp,		/* For error messages. May be NULL */
    int profileValue)		/* Profile #define value */
{
    size_t i;

    for (i = 0; i < sizeof(encodingProfiles) / sizeof(encodingProfiles[0]); ++i) {
	if (profileValue == encodingProfiles[i].value) {
	    return encodingProfiles[i].name;
	}
    }
    if (interp) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"Internal error. Bad profile id \"%d\".", profileValue));
	Tcl_SetErrorCode(
		interp, "TCL", "ENCODING", "PROFILEID", (char *)NULL);
    }
    return NULL;
}

/*
 *------------------------------------------------------------------------
 *
 * TclGetEncodingProfiles --
 *
 *	Get the list of supported encoding profiles.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The list of profile names is stored in the interpreter result.
 *
 *------------------------------------------------------------------------
 */
void
TclGetEncodingProfiles(
    Tcl_Interp *interp)
{
    size_t i, n;
    Tcl_Obj *objPtr;
    n = sizeof(encodingProfiles) / sizeof(encodingProfiles[0]);
    objPtr = Tcl_NewListObj(n, NULL);
    for (i = 0; i < n; ++i) {
	Tcl_ListObjAppendElement(interp, objPtr,
		Tcl_NewStringObj(encodingProfiles[i].name, TCL_INDEX_NONE));
    }
    Tcl_SetObjResult(interp, objPtr);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclEnsemble.c.

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

30
31
32
33
34
35
36
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
30
31

32
33
34
35
36

37
38
39
40
41
42
43
44






-
+












+
+
+
+
+
+
+
+
-
+



-
+




-
+







/*
 * tclEnsemble.c --
 *
 *	Contains support for ensembles (see TIP#112), which provide simple
 *	mechanism for creating composite commands on top of namespaces.
 *
 * Copyright (c) 2005-2013 Donal K. Fellows.
 * Copyright © 2005-2013 Donal K. Fellows.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclCompile.h"

/*
 * Declarations for functions local to this file:
 */

static Tcl_Command	InitEnsembleFromOptions(Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		ReadOneEnsembleOption(Tcl_Interp *interp,
			    Tcl_Command token, Tcl_Obj *optionObj);
static int		ReadAllEnsembleOptions(Tcl_Interp *interp,
			    Tcl_Command token);
static int		SetEnsembleConfigOptions(Tcl_Interp *interp,
			    Tcl_Command token, int objc,
static inline Tcl_Obj *	NewNsObj(Tcl_Namespace *namespacePtr);
			    Tcl_Obj *const objv[]);
static inline int	EnsembleUnknownCallback(Tcl_Interp *interp,
			    EnsembleConfig *ensemblePtr, int objc,
			    Tcl_Obj *const objv[], Tcl_Obj **prefixObjPtr);
static int		NsEnsembleImplementationCmdNR(ClientData clientData,
static int		NsEnsembleImplementationCmdNR(void *clientData,
			    Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]);
static void		BuildEnsembleConfig(EnsembleConfig *ensemblePtr);
static int		NsEnsembleStringOrder(const void *strPtr1,
			    const void *strPtr2);
static void		DeleteEnsembleConfig(ClientData clientData);
static void		DeleteEnsembleConfig(void *clientData);
static void		MakeCachedEnsembleCommand(Tcl_Obj *objPtr,
			    EnsembleConfig *ensemblePtr, Tcl_HashEntry *hPtr,
			    Tcl_Obj *fix);
static void		FreeEnsembleCmdRep(Tcl_Obj *objPtr);
static void		DupEnsembleCmdRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);
static void		CompileToInvokedCommand(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Tcl_Obj *replacements,
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
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







-
-
+
+









-
+
+


-
+

-
+


-
+


-
+

-
-
-
+
+
+
+








-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-







};
enum EnsConfigOpts {
    CONF_MAP, CONF_NAMESPACE, CONF_PARAM, CONF_PREFIX, CONF_SUBCMDS,
    CONF_UNKNOWN
};

/*
 * This structure defines a Tcl object type that contains a reference to an
 * ensemble subcommand (e.g. the "length" in [string length ab]). It is used
 * ensembleCmdType is a Tcl object type that contains a reference to an
 * ensemble subcommand, e.g. the "length" in [string length ab]. It is used
 * to cache the mapping between the subcommand itself and the real command
 * that implements it.
 */

static const Tcl_ObjType ensembleCmdType = {
    "ensembleCommand",		/* the type's name */
    FreeEnsembleCmdRep,		/* freeIntRepProc */
    DupEnsembleCmdRep,		/* dupIntRepProc */
    NULL,			/* updateStringProc */
    NULL			/* setFromAnyProc */
    NULL,			/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

#define ECRSetIntRep(objPtr, ecRepPtr)					\
#define ECRSetInternalRep(objPtr, ecRepPtr) \
    do {								\
	Tcl_ObjIntRep ir;						\
	Tcl_ObjInternalRep ir;						\
	ir.twoPtrValue.ptr1 = (ecRepPtr);				\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreIntRep((objPtr), &ensembleCmdType, &ir);		\
	Tcl_StoreInternalRep((objPtr), &ensembleCmdType, &ir);		\
    } while (0)

#define ECRGetIntRep(objPtr, ecRepPtr)					\
#define ECRGetInternalRep(objPtr, ecRepPtr) \
    do {								\
	const Tcl_ObjIntRep *irPtr;					\
	irPtr = TclFetchIntRep((objPtr), &ensembleCmdType);		\
	(ecRepPtr) = irPtr ? (EnsembleCmdRep *)irPtr->twoPtrValue.ptr1 : NULL;		\
	const Tcl_ObjInternalRep *irPtr;				\
	irPtr = TclFetchInternalRep((objPtr), &ensembleCmdType);	\
	(ecRepPtr) = irPtr ? (EnsembleCmdRep *)				\
		irPtr->twoPtrValue.ptr1 : NULL;				\
    } while (0)

/*
 * The internal rep for caching ensemble subcommand lookups and spelling
 * corrections.
 */

typedef struct {
    size_t epoch;               /* Used to confirm when the data in this
                                 * really structure matches up with the
                                 * ensemble. */
    Command *token;             /* Reference to the command for which this
                                 * structure is a cache of the resolution. */
    Tcl_Obj *fix;               /* Corrected spelling, if needed. */
    Tcl_HashEntry *hPtr;        /* Direct link to entry in the subcommand hash
                                 * table. */
    Tcl_Size epoch;		/* Used to confirm when the data in this
				 * really structure matches up with the
				 * ensemble. */
    Command *token;		/* Reference to the command for which this
				 * structure is a cache of the resolution. */
    Tcl_Obj *fix;		/* Corrected spelling, if needed. */
    Tcl_HashEntry *hPtr;	/* Direct link to entry in the subcommand hash
				 * table. */
} EnsembleCmdRep;

static inline Tcl_Obj *
NewNsObj(
    Tcl_Namespace *namespacePtr)
{
    Namespace *nsPtr = (Namespace *) namespacePtr;

    if (namespacePtr == TclGetGlobalNamespace(nsPtr->interp)) {
	return Tcl_NewStringObj("::", 2);
    }
    return Tcl_NewStringObj(nsPtr->fullName, -1);
}

/*
 *----------------------------------------------------------------------
 *
 * TclNamespaceEnsembleCmd --
 *
 *	Invoked to implement the "namespace ensemble" command that creates and
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
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
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







-
+




-
-
+
-
-
+
-
-
-
-
+

-
+



-
-
+
+







-
-
+




-
-
+
+
-
-
-
-
-
-
-
-
-
-
-








-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-










-







 *	implementation prefix is configured.
 *
 *----------------------------------------------------------------------
 */

int
TclNamespaceEnsembleCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Namespace *namespacePtr;
    Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp), *cxtPtr,
    Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
	    *foundNsPtr, *altFoundNsPtr, *actualCxtPtr;
    Tcl_Command token;
    Tcl_Command token;		/* The ensemble command. */
    Tcl_DictSearch search;
    Tcl_Obj *listObj;
    const char *simpleName;
    int index, done;
    enum EnsSubcmds index;

    if (nsPtr == NULL || nsPtr->flags & NS_DYING) {
    if (nsPtr == NULL || nsPtr->flags & NS_DEAD) {
	if (!Tcl_InterpDeleted(interp)) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "tried to manipulate ensemble of deleted namespace",
		    -1));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "DEAD", NULL);
		    TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "DEAD", (char *)NULL);
	}
	return TCL_ERROR;
    }

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], ensembleSubcommands,
    } else if (Tcl_GetIndexFromObj(interp, objv[1], ensembleSubcommands,
	    "subcommand", 0, &index) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum EnsSubcmds) index) {
    case ENS_CREATE: {
    switch (index) {
    case ENS_CREATE:
	const char *name;
	int len, allocatedMapFlag = 0;
	/*
	 * Defaults
	 */
	Tcl_Obj *subcmdObj = NULL;
	Tcl_Obj *mapObj = NULL;
	int permitPrefix = 1;
	Tcl_Obj *unknownObj = NULL;
	Tcl_Obj *paramObj = NULL;

	/*
	 * Check that we've got option-value pairs... [Bug 1558654]
	 */

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

	token = InitEnsembleFromOptions(interp, objc - 2, objv + 2);
	name = nsPtr->name;
	cxtPtr = (Namespace *) nsPtr->parentPtr;

	/*
	 * Parse the option list, applying type checks as we go. Note that we
	 * are not incrementing any reference counts in the objects at this
	 * stage, so the presence of an option multiple times won't cause any
	 * memory leaks.
	 */

	for (; objc>1 ; objc-=2,objv+=2) {
	    if (Tcl_GetIndexFromObj(interp, objv[0], ensembleCreateOptions,
		    "option", 0, &index) != TCL_OK) {
		if (allocatedMapFlag) {
		    Tcl_DecrRefCount(mapObj);
		}
		return TCL_ERROR;
	    }
	    switch ((enum EnsCreateOpts) index) {
	    case CRT_CMD:
		name = TclGetString(objv[1]);
		cxtPtr = nsPtr;
		continue;
	    case CRT_SUBCMDS:
		if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
		    if (allocatedMapFlag) {
			Tcl_DecrRefCount(mapObj);
		    }
		    return TCL_ERROR;
		}
		subcmdObj = (len > 0 ? objv[1] : NULL);
		continue;
	    case CRT_PARAM:
		if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
		    if (allocatedMapFlag) {
			Tcl_DecrRefCount(mapObj);
		    }
		    return TCL_ERROR;
		}
		paramObj = (len > 0 ? objv[1] : NULL);
		continue;
	    case CRT_MAP: {
		Tcl_Obj *patchedDict = NULL, *subcmdWordsObj;

		/*
		 * Verify that the map is sensible.
		 */

		if (Tcl_DictObjFirst(interp, objv[1], &search,
			&subcmdWordsObj, &listObj, &done) != TCL_OK) {
		    if (allocatedMapFlag) {
			Tcl_DecrRefCount(mapObj);
		    }
		    return TCL_ERROR;
		}
		if (done) {
		    mapObj = NULL;
		    continue;
		}
		do {
		    Tcl_Obj **listv;
		    const char *cmd;

		    if (TclListObjGetElements(interp, listObj, &len,
			    &listv) != TCL_OK) {
			Tcl_DictObjDone(&search);
			if (patchedDict) {
			    Tcl_DecrRefCount(patchedDict);
			}
			if (allocatedMapFlag) {
			    Tcl_DecrRefCount(mapObj);
			}
			return TCL_ERROR;
		    }
		    if (len < 1) {
			Tcl_SetObjResult(interp, Tcl_NewStringObj(
				"ensemble subcommand implementations "
				"must be non-empty lists", -1));
			Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE",
				"EMPTY_TARGET", NULL);
			Tcl_DictObjDone(&search);
			if (patchedDict) {
			    Tcl_DecrRefCount(patchedDict);
			}
			if (allocatedMapFlag) {
			    Tcl_DecrRefCount(mapObj);
			}
			return TCL_ERROR;
		    }
		    cmd = TclGetString(listv[0]);
		    if (!(cmd[0] == ':' && cmd[1] == ':')) {
			Tcl_Obj *newList = Tcl_NewListObj(len, listv);
			Tcl_Obj *newCmd = NewNsObj((Tcl_Namespace *) nsPtr);

			if (nsPtr->parentPtr) {
			    Tcl_AppendStringsToObj(newCmd, "::", NULL);
			}
			Tcl_AppendObjToObj(newCmd, listv[0]);
			Tcl_ListObjReplace(NULL, newList, 0, 1, 1, &newCmd);
			if (patchedDict == NULL) {
	if (token == NULL) {
			    patchedDict = Tcl_DuplicateObj(objv[1]);
			}
			Tcl_DictObjPut(NULL, patchedDict, subcmdWordsObj,
				newList);
		    }
		    Tcl_DictObjNext(&search, &subcmdWordsObj, &listObj,
			    &done);
		} while (!done);

		if (allocatedMapFlag) {
		    Tcl_DecrRefCount(mapObj);
		}
		mapObj = (patchedDict ? patchedDict : objv[1]);
		if (patchedDict) {
		    allocatedMapFlag = 1;
		}
		continue;
	    }
	    case CRT_PREFIX:
		if (Tcl_GetBooleanFromObj(interp, objv[1],
			&permitPrefix) != TCL_OK) {
		    if (allocatedMapFlag) {
			Tcl_DecrRefCount(mapObj);
		    }
		    return TCL_ERROR;
		}
	    return TCL_ERROR;
	}
		continue;
	    case CRT_UNKNOWN:
		if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
		    if (allocatedMapFlag) {
			Tcl_DecrRefCount(mapObj);
		    }
		    return TCL_ERROR;
		}
		unknownObj = (len > 0 ? objv[1] : NULL);
		continue;
	    }
	}

	TclGetNamespaceForQualName(interp, name, cxtPtr,
		TCL_CREATE_NS_IF_UNKNOWN, &foundNsPtr, &altFoundNsPtr,
		&actualCxtPtr, &simpleName);

	/*
	 * Create the ensemble. Note that this might delete another ensemble
	 * linked to the same namespace, so we must be careful. However, we
	 * should be OK because we only link the namespace into the list once
	 * we've created it (and after any deletions have occurred.)
	 */

	token = TclCreateEnsembleInNs(interp, simpleName,
		(Tcl_Namespace *) foundNsPtr, (Tcl_Namespace *) nsPtr,
		(permitPrefix ? TCL_ENSEMBLE_PREFIX : 0));
	Tcl_SetEnsembleSubcommandList(interp, token, subcmdObj);
	Tcl_SetEnsembleMappingDict(interp, token, mapObj);
	Tcl_SetEnsembleUnknownHandler(interp, token, unknownObj);
	Tcl_SetEnsembleParameterList(interp, token, paramObj);

	/*
	 * Tricky! Must ensure that the result is not shared (command delete
	 * traces could have corrupted the pristine object that we started
	 * with). [Snit test rename-1.5]
	 */

	Tcl_ResetResult(interp);
	Tcl_GetCommandFullName(interp, token, Tcl_GetObjResult(interp));
	return TCL_OK;
    }

    case ENS_EXISTS:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "cmdname");
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650























































































































































































































































































































































































































































































































651
652
653
654
655
656
657
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746







-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	}
	token = Tcl_FindEnsemble(interp, objv[2], TCL_LEAVE_ERR_MSG);
	if (token == NULL) {
	    return TCL_ERROR;
	}

	if (objc == 4) {
	    Tcl_Obj *resultObj = NULL;		/* silence gcc 4 warning */

	    return ReadOneEnsembleOption(interp, token, objv[3]);
	    if (Tcl_GetIndexFromObj(interp, objv[3], ensembleConfigOptions,
		    "option", 0, &index) != TCL_OK) {
		return TCL_ERROR;
	    }
	    switch ((enum EnsConfigOpts) index) {
	    case CONF_SUBCMDS:
		Tcl_GetEnsembleSubcommandList(NULL, token, &resultObj);
		if (resultObj != NULL) {
		    Tcl_SetObjResult(interp, resultObj);
		}
		break;
	    case CONF_PARAM:
		Tcl_GetEnsembleParameterList(NULL, token, &resultObj);
		if (resultObj != NULL) {
		    Tcl_SetObjResult(interp, resultObj);
		}
		break;
	    case CONF_MAP:
		Tcl_GetEnsembleMappingDict(NULL, token, &resultObj);
		if (resultObj != NULL) {
		    Tcl_SetObjResult(interp, resultObj);
		}
		break;
	    case CONF_NAMESPACE:
		namespacePtr = NULL;		/* silence gcc 4 warning */
		Tcl_GetEnsembleNamespace(NULL, token, &namespacePtr);
		Tcl_SetObjResult(interp, NewNsObj(namespacePtr));
		break;
	    case CONF_PREFIX: {
		int flags = 0;			/* silence gcc 4 warning */

		Tcl_GetEnsembleFlags(NULL, token, &flags);
		Tcl_SetObjResult(interp,
			Tcl_NewBooleanObj(flags & TCL_ENSEMBLE_PREFIX));
		break;
	    }
	    case CONF_UNKNOWN:
		Tcl_GetEnsembleUnknownHandler(NULL, token, &resultObj);
		if (resultObj != NULL) {
		    Tcl_SetObjResult(interp, resultObj);
		}
		break;
	    }
	} else if (objc == 3) {
	    /*
	     * Produce list of all information.
	     */

	    return ReadAllEnsembleOptions(interp, token);
	    Tcl_Obj *resultObj, *tmpObj = NULL;	/* silence gcc 4 warning */
	    int flags = 0;			/* silence gcc 4 warning */

	    TclNewObj(resultObj);

	    /* -map option */
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    Tcl_NewStringObj(ensembleConfigOptions[CONF_MAP], -1));
	    Tcl_GetEnsembleMappingDict(NULL, token, &tmpObj);
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    (tmpObj != NULL) ? tmpObj : Tcl_NewObj());

	    /* -namespace option */
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    Tcl_NewStringObj(ensembleConfigOptions[CONF_NAMESPACE],
			    -1));
	    namespacePtr = NULL;		/* silence gcc 4 warning */
	    Tcl_GetEnsembleNamespace(NULL, token, &namespacePtr);
	    Tcl_ListObjAppendElement(NULL, resultObj, NewNsObj(namespacePtr));

	    /* -parameters option */
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    Tcl_NewStringObj(ensembleConfigOptions[CONF_PARAM], -1));
	    Tcl_GetEnsembleParameterList(NULL, token, &tmpObj);
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    (tmpObj != NULL) ? tmpObj : Tcl_NewObj());

	    /* -prefix option */
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    Tcl_NewStringObj(ensembleConfigOptions[CONF_PREFIX], -1));
	    Tcl_GetEnsembleFlags(NULL, token, &flags);
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    Tcl_NewBooleanObj(flags & TCL_ENSEMBLE_PREFIX));

	    /* -subcommands option */
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    Tcl_NewStringObj(ensembleConfigOptions[CONF_SUBCMDS],-1));
	    Tcl_GetEnsembleSubcommandList(NULL, token, &tmpObj);
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    (tmpObj != NULL) ? tmpObj : Tcl_NewObj());

	    /* -unknown option */
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    Tcl_NewStringObj(ensembleConfigOptions[CONF_UNKNOWN],-1));
	    Tcl_GetEnsembleUnknownHandler(NULL, token, &tmpObj);
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    (tmpObj != NULL) ? tmpObj : Tcl_NewObj());

	    Tcl_SetObjResult(interp, resultObj);
	} else {
	    int len, allocatedMapFlag = 0;
	    Tcl_Obj *subcmdObj = NULL, *mapObj = NULL, *paramObj = NULL,
		    *unknownObj = NULL; /* Defaults, silence gcc 4 warnings */
	    int permitPrefix, flags = 0;	/* silence gcc 4 warning */

	    return SetEnsembleConfigOptions(interp, token, objc - 3, objv + 3);
	    Tcl_GetEnsembleSubcommandList(NULL, token, &subcmdObj);
	    Tcl_GetEnsembleMappingDict(NULL, token, &mapObj);
	    Tcl_GetEnsembleParameterList(NULL, token, &paramObj);
	    Tcl_GetEnsembleUnknownHandler(NULL, token, &unknownObj);
	    Tcl_GetEnsembleFlags(NULL, token, &flags);
	    permitPrefix = (flags & TCL_ENSEMBLE_PREFIX) != 0;

	}
	    objv += 3;
	    objc -= 3;

	    /*
	     * Parse the option list, applying type checks as we go. Note that
	     * we are not incrementing any reference counts in the objects at
	     * this stage, so the presence of an option multiple times won't
	     * cause any memory leaks.
	     */

	    for (; objc>0 ; objc-=2,objv+=2) {
		if (Tcl_GetIndexFromObj(interp, objv[0],ensembleConfigOptions,
			"option", 0, &index) != TCL_OK) {
		freeMapAndError:
		    if (allocatedMapFlag) {
			Tcl_DecrRefCount(mapObj);
		    }
		    return TCL_ERROR;
		}
		switch ((enum EnsConfigOpts) index) {
		case CONF_SUBCMDS:
		    if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
			goto freeMapAndError;
		    }
		    subcmdObj = (len > 0 ? objv[1] : NULL);
		    continue;
		case CONF_PARAM:
		    if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
			goto freeMapAndError;
		    }
		    paramObj = (len > 0 ? objv[1] : NULL);
		    continue;
		case CONF_MAP: {
		    Tcl_Obj *patchedDict = NULL, *subcmdWordsObj, **listv;
		    const char *cmd;

		    /*
		     * Verify that the map is sensible.
		     */

		    if (Tcl_DictObjFirst(interp, objv[1], &search,
			    &subcmdWordsObj, &listObj, &done) != TCL_OK) {
			goto freeMapAndError;
		    }
		    if (done) {
			mapObj = NULL;
			continue;
		    }
		    do {
			if (TclListObjGetElements(interp, listObj, &len,
				&listv) != TCL_OK) {
			    Tcl_DictObjDone(&search);
			    if (patchedDict) {
				Tcl_DecrRefCount(patchedDict);
			    }
			    goto freeMapAndError;
			}
			if (len < 1) {
			    Tcl_SetObjResult(interp, Tcl_NewStringObj(
				    "ensemble subcommand implementations "
				    "must be non-empty lists", -1));
			    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE",
				    "EMPTY_TARGET", NULL);
			    Tcl_DictObjDone(&search);
			    if (patchedDict) {
				Tcl_DecrRefCount(patchedDict);
			    }
			    goto freeMapAndError;
			}
			cmd = TclGetString(listv[0]);
			if (!(cmd[0] == ':' && cmd[1] == ':')) {
			    Tcl_Obj *newList = Tcl_DuplicateObj(listObj);
			    Tcl_Obj *newCmd = NewNsObj((Tcl_Namespace*)nsPtr);

			    if (nsPtr->parentPtr) {
				Tcl_AppendStringsToObj(newCmd, "::", NULL);
			    }
			    Tcl_AppendObjToObj(newCmd, listv[0]);
			    Tcl_ListObjReplace(NULL, newList, 0, 1, 1,
				    &newCmd);
			    if (patchedDict == NULL) {
				patchedDict = Tcl_DuplicateObj(objv[1]);
			    }
			    Tcl_DictObjPut(NULL, patchedDict, subcmdWordsObj,
				    newList);
			}
			Tcl_DictObjNext(&search, &subcmdWordsObj, &listObj,
				&done);
		    } while (!done);
		    if (allocatedMapFlag) {
			Tcl_DecrRefCount(mapObj);
		    }
		    mapObj = (patchedDict ? patchedDict : objv[1]);
		    if (patchedDict) {
			allocatedMapFlag = 1;
		    }
		    continue;
		}
		case CONF_NAMESPACE:
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "option -namespace is read-only", -1));
		    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "READ_ONLY",
			    NULL);
		    goto freeMapAndError;
		case CONF_PREFIX:
		    if (Tcl_GetBooleanFromObj(interp, objv[1],
			    &permitPrefix) != TCL_OK) {
			goto freeMapAndError;
		    }
		    continue;
		case CONF_UNKNOWN:
		    if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
			goto freeMapAndError;
		    }
		    unknownObj = (len > 0 ? objv[1] : NULL);
		    continue;
		}
	    }

	    /*
	     * Update the namespace now that we've finished the parsing stage.
	     */

	    flags = (permitPrefix ? flags|TCL_ENSEMBLE_PREFIX
		    : flags&~TCL_ENSEMBLE_PREFIX);
	    Tcl_SetEnsembleSubcommandList(interp, token, subcmdObj);
	    Tcl_SetEnsembleMappingDict(interp, token, mapObj);
	    Tcl_SetEnsembleParameterList(interp, token, paramObj);
	    Tcl_SetEnsembleUnknownHandler(interp, token, unknownObj);
	    Tcl_SetEnsembleFlags(interp, token, flags);
	}
	return TCL_OK;

    default:
	Tcl_Panic("unexpected ensemble command");
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * InitEnsembleFromOptions --
 *
 *	Core of implementation of "namespace ensemble create".
 *
 * Results:
 *	Returns created ensemble's command token if successful, and NULL if
 *	anything goes wrong.
 *
 * Side effects:
 *	Creates the ensemble for the namespace if one did not previously
 *	exist.
 *
 * Note:
 *	Can't use SetEnsembleConfigOptions() here. Different (but overlapping)
 *	options are supported.
 *
 *----------------------------------------------------------------------
 */
static Tcl_Command
InitEnsembleFromOptions(
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
    Namespace *cxtPtr = nsPtr->parentPtr;
    Namespace *altFoundNsPtr, *actualCxtPtr;
    const char *name = nsPtr->name;
    Tcl_Size len;
    int allocatedMapFlag = 0;
    enum EnsCreateOpts index;
    Tcl_Command token;		/* The created ensemble command. */
    Namespace *foundNsPtr;
    const char *simpleName;
    /*
     * Defaults
     */
    Tcl_Obj *subcmdObj = NULL;
    Tcl_Obj *mapObj = NULL;
    int permitPrefix = 1;
    Tcl_Obj *unknownObj = NULL;
    Tcl_Obj *paramObj = NULL;

    /*
     * Parse the option list, applying type checks as we go. Note that we are
     * not incrementing any reference counts in the objects at this stage, so
     * the presence of an option multiple times won't cause any memory leaks.
     */

    for (; objc>1 ; objc-=2,objv+=2) {
	if (Tcl_GetIndexFromObj(interp, objv[0], ensembleCreateOptions,
		"option", 0, &index) != TCL_OK) {
	    goto error;
	}
	switch (index) {
	case CRT_CMD:
	    name = TclGetString(objv[1]);
	    cxtPtr = nsPtr;
	    continue;
	case CRT_SUBCMDS:
	    if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
		goto error;
	    }
	    subcmdObj = (len > 0 ? objv[1] : NULL);
	    continue;
	case CRT_PARAM:
	    if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
		goto error;
	    }
	    paramObj = (len > 0 ? objv[1] : NULL);
	    continue;
	case CRT_MAP: {
	    Tcl_Obj *patchedDict = NULL, *subcmdWordsObj, *listObj;
	    Tcl_DictSearch search;
	    int done;

	    /*
	     * Verify that the map is sensible.
	     */

	    if (Tcl_DictObjFirst(interp, objv[1], &search,
		    &subcmdWordsObj, &listObj, &done) != TCL_OK) {
		goto error;
	    } else if (done) {
		mapObj = NULL;
		continue;
	    }
	    do {
		Tcl_Obj **listv;
		const char *cmd;

		if (TclListObjGetElements(interp, listObj, &len,
			&listv) != TCL_OK) {
		    goto mapError;
		}
		if (len < 1) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "ensemble subcommand implementations "
			    "must be non-empty lists", TCL_AUTO_LENGTH));
		    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE",
			    "EMPTY_TARGET", (char *)NULL);
		    goto mapError;
		}
		cmd = TclGetString(listv[0]);
		if (!(cmd[0] == ':' && cmd[1] == ':')) {
		    Tcl_Obj *newList = Tcl_NewListObj(len, listv);
		    Tcl_Obj *newCmd = TclNewNamespaceObj(
			    (Tcl_Namespace *) nsPtr);

		    if (nsPtr->parentPtr) {
			Tcl_AppendStringsToObj(newCmd, "::", (char *)NULL);
		    }
		    Tcl_AppendObjToObj(newCmd, listv[0]);
		    Tcl_ListObjReplace(NULL, newList, 0, 1, 1, &newCmd);
		    if (patchedDict == NULL) {
			patchedDict = Tcl_DuplicateObj(objv[1]);
		    }
		    Tcl_DictObjPut(NULL, patchedDict, subcmdWordsObj, newList);
		}
		Tcl_DictObjNext(&search, &subcmdWordsObj, &listObj, &done);
	    } while (!done);

	    if (allocatedMapFlag) {
		Tcl_DecrRefCount(mapObj);
	    }
	    mapObj = (patchedDict ? patchedDict : objv[1]);
	    if (patchedDict) {
		allocatedMapFlag = 1;
	    }
	    continue;
	mapError:
	    Tcl_DictObjDone(&search);
	    if (patchedDict) {
		Tcl_DecrRefCount(patchedDict);
	    }
	    goto error;
	}
	case CRT_PREFIX:
	    if (Tcl_GetBooleanFromObj(interp, objv[1],
		    &permitPrefix) != TCL_OK) {
		goto error;
	    }
	    continue;
	case CRT_UNKNOWN:
	    if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
		goto error;
	    }
	    unknownObj = (len > 0 ? objv[1] : NULL);
	    continue;
	}
    }

    TclGetNamespaceForQualName(interp, name, cxtPtr,
	    TCL_CREATE_NS_IF_UNKNOWN, &foundNsPtr, &altFoundNsPtr,
	    &actualCxtPtr, &simpleName);

    /*
     * Create the ensemble. Note that this might delete another ensemble
     * linked to the same namespace, so we must be careful. However, we
     * should be OK because we only link the namespace into the list once
     * we've created it (and after any deletions have occurred.)
     */

    token = TclCreateEnsembleInNs(interp, simpleName,
	    (Tcl_Namespace *) foundNsPtr, (Tcl_Namespace *) nsPtr,
	    (permitPrefix ? TCL_ENSEMBLE_PREFIX : 0));
    Tcl_SetEnsembleSubcommandList(interp, token, subcmdObj);
    Tcl_SetEnsembleMappingDict(interp, token, mapObj);
    Tcl_SetEnsembleUnknownHandler(interp, token, unknownObj);
    Tcl_SetEnsembleParameterList(interp, token, paramObj);
    return token;

  error:
    if (allocatedMapFlag) {
	Tcl_DecrRefCount(mapObj);
    }
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * ReadOneEnsembleOption --
 *
 *	Core of implementation of "namespace ensemble configure" with just a
 *	single option name.
 *
 * Results:
 *	Tcl result code. Modifies the interpreter result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
static int
ReadOneEnsembleOption(
    Tcl_Interp *interp,
    Tcl_Command token,		/* The ensemble to read from. */
    Tcl_Obj *optionObj)		/* The name of the option to read. */
{
    Tcl_Obj *resultObj = NULL;			/* silence gcc 4 warning */
    enum EnsConfigOpts index;

    if (Tcl_GetIndexFromObj(interp, optionObj, ensembleConfigOptions,
	    "option", 0, &index) != TCL_OK) {
	return TCL_ERROR;
    }
    switch (index) {
    case CONF_SUBCMDS:
	Tcl_GetEnsembleSubcommandList(NULL, token, &resultObj);
	if (resultObj != NULL) {
	    Tcl_SetObjResult(interp, resultObj);
	}
	break;
    case CONF_PARAM:
	Tcl_GetEnsembleParameterList(NULL, token, &resultObj);
	if (resultObj != NULL) {
	    Tcl_SetObjResult(interp, resultObj);
	}
	break;
    case CONF_MAP:
	Tcl_GetEnsembleMappingDict(NULL, token, &resultObj);
	if (resultObj != NULL) {
	    Tcl_SetObjResult(interp, resultObj);
	}
	break;
    case CONF_NAMESPACE: {
	Tcl_Namespace *namespacePtr = NULL;	/* silence gcc 4 warning */
	Tcl_GetEnsembleNamespace(NULL, token, &namespacePtr);
	Tcl_SetObjResult(interp, TclNewNamespaceObj(namespacePtr));
	break;
    }
    case CONF_PREFIX: {
	int flags = 0;				/* silence gcc 4 warning */

	Tcl_GetEnsembleFlags(NULL, token, &flags);
	Tcl_SetObjResult(interp,
		Tcl_NewBooleanObj(flags & TCL_ENSEMBLE_PREFIX));
	break;
    }
    case CONF_UNKNOWN:
	Tcl_GetEnsembleUnknownHandler(NULL, token, &resultObj);
	if (resultObj != NULL) {
	    Tcl_SetObjResult(interp, resultObj);
	}
	break;
    }
    return TCL_OK;
}
/*
 *----------------------------------------------------------------------
 *
 * ReadAllEnsembleOptions --
 *
 *	Core of implementation of "namespace ensemble configure" without
 *	option names.
 *
 * Results:
 *	Tcl result code. Modifies the interpreter result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
static int
ReadAllEnsembleOptions(
    Tcl_Interp *interp,
    Tcl_Command token)		/* The ensemble to read from. */
{
    Tcl_Obj *resultObj, *tmpObj = NULL;	/* silence gcc 4 warning */
    int flags = 0;			/* silence gcc 4 warning */
    Tcl_Namespace *namespacePtr = NULL;	/* silence gcc 4 warning */

    TclNewObj(resultObj);

    /* -map option */
    Tcl_ListObjAppendElement(NULL, resultObj,
	    Tcl_NewStringObj(ensembleConfigOptions[CONF_MAP],
		    TCL_AUTO_LENGTH));
    Tcl_GetEnsembleMappingDict(NULL, token, &tmpObj);
    Tcl_ListObjAppendElement(NULL, resultObj,
	    (tmpObj != NULL) ? tmpObj : Tcl_NewObj());

    /* -namespace option */
    Tcl_ListObjAppendElement(NULL, resultObj,
	    Tcl_NewStringObj(ensembleConfigOptions[CONF_NAMESPACE],
		    TCL_AUTO_LENGTH));
    Tcl_GetEnsembleNamespace(NULL, token, &namespacePtr);
    Tcl_ListObjAppendElement(NULL, resultObj, TclNewNamespaceObj(namespacePtr));

    /* -parameters option */
    Tcl_ListObjAppendElement(NULL, resultObj,
	    Tcl_NewStringObj(ensembleConfigOptions[CONF_PARAM],
		    TCL_AUTO_LENGTH));
    Tcl_GetEnsembleParameterList(NULL, token, &tmpObj);
    Tcl_ListObjAppendElement(NULL, resultObj,
	    (tmpObj != NULL) ? tmpObj : Tcl_NewObj());

    /* -prefix option */
    Tcl_ListObjAppendElement(NULL, resultObj,
	    Tcl_NewStringObj(ensembleConfigOptions[CONF_PREFIX],
		    TCL_AUTO_LENGTH));
    Tcl_GetEnsembleFlags(NULL, token, &flags);
    Tcl_ListObjAppendElement(NULL, resultObj,
	    Tcl_NewBooleanObj(flags & TCL_ENSEMBLE_PREFIX));

    /* -subcommands option */
    Tcl_ListObjAppendElement(NULL, resultObj,
	    Tcl_NewStringObj(ensembleConfigOptions[CONF_SUBCMDS],
		    TCL_AUTO_LENGTH));
    Tcl_GetEnsembleSubcommandList(NULL, token, &tmpObj);
    Tcl_ListObjAppendElement(NULL, resultObj,
	    (tmpObj != NULL) ? tmpObj : Tcl_NewObj());

    /* -unknown option */
    Tcl_ListObjAppendElement(NULL, resultObj,
	    Tcl_NewStringObj(ensembleConfigOptions[CONF_UNKNOWN],
		    TCL_AUTO_LENGTH));
    Tcl_GetEnsembleUnknownHandler(NULL, token, &tmpObj);
    Tcl_ListObjAppendElement(NULL, resultObj,
	    (tmpObj != NULL) ? tmpObj : Tcl_NewObj());

    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}
/*
 *----------------------------------------------------------------------
 *
 * SetEnsembleConfigOptions --
 *
 *	Core of implementation of "namespace ensemble configure" with even
 *	number of arguments (where there is at least one pair).
 *
 * Results:
 *	Tcl result code. Modifies the interpreter result.
 *
 * Side effects:
 *	Modifies the ensemble's configuration.
 *
 *----------------------------------------------------------------------
 */
static int
SetEnsembleConfigOptions(
    Tcl_Interp *interp,
    Tcl_Command token,		/* The ensemble to configure. */
    int objc,			/* The count of option-related arguments. */
    Tcl_Obj *const objv[])	/* Option-related arguments. */
{
    Tcl_Size len;
    int allocatedMapFlag = 0;
    Tcl_Obj *subcmdObj = NULL, *mapObj = NULL, *paramObj = NULL,
	    *unknownObj = NULL;	/* Defaults, silence gcc 4 warnings */
    Tcl_Obj *listObj;
    Tcl_DictSearch search;
    int permitPrefix, flags = 0;	/* silence gcc 4 warning */
    enum EnsConfigOpts index;
    int done;

    Tcl_GetEnsembleSubcommandList(NULL, token, &subcmdObj);
    Tcl_GetEnsembleMappingDict(NULL, token, &mapObj);
    Tcl_GetEnsembleParameterList(NULL, token, &paramObj);
    Tcl_GetEnsembleUnknownHandler(NULL, token, &unknownObj);
    Tcl_GetEnsembleFlags(NULL, token, &flags);
    permitPrefix = (flags & TCL_ENSEMBLE_PREFIX) != 0;

    /*
     * Parse the option list, applying type checks as we go. Note that
     * we are not incrementing any reference counts in the objects at
     * this stage, so the presence of an option multiple times won't
     * cause any memory leaks.
     */

    for (; objc>0 ; objc-=2,objv+=2) {
	if (Tcl_GetIndexFromObj(interp, objv[0], ensembleConfigOptions,
		"option", 0, &index) != TCL_OK) {
	    goto freeMapAndError;
	}
	switch (index) {
	case CONF_SUBCMDS:
	    if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
		goto freeMapAndError;
	    }
	    subcmdObj = (len > 0 ? objv[1] : NULL);
	    continue;
	case CONF_PARAM:
	    if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
		goto freeMapAndError;
	    }
	    paramObj = (len > 0 ? objv[1] : NULL);
	    continue;
	case CONF_MAP: {
	    Tcl_Obj *patchedDict = NULL, *subcmdWordsObj, **listv;
	    Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
	    const char *cmd;

	    /*
	     * Verify that the map is sensible.
	     */

	    if (Tcl_DictObjFirst(interp, objv[1], &search,
		    &subcmdWordsObj, &listObj, &done) != TCL_OK) {
		goto freeMapAndError;
	    } else if (done) {
		mapObj = NULL;
		continue;
	    }

	    do {
		if (TclListObjLength(interp, listObj, &len) != TCL_OK) {
		    goto finishSearchAndError;
		}
		if (len < 1) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "ensemble subcommand implementations "
			    "must be non-empty lists", TCL_AUTO_LENGTH));
		    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE",
			    "EMPTY_TARGET", (char *)NULL);
		    goto finishSearchAndError;
		}
		if (TclListObjGetElements(interp, listObj, &len,
			&listv) != TCL_OK) {
		    goto finishSearchAndError;
		}
		cmd = TclGetString(listv[0]);
		if (!(cmd[0] == ':' && cmd[1] == ':')) {
		    Tcl_Obj *newList = Tcl_DuplicateObj(listObj);
		    Tcl_Obj *newCmd = TclNewNamespaceObj(
			    (Tcl_Namespace*) nsPtr);

		    if (nsPtr->parentPtr) {
			Tcl_AppendStringsToObj(newCmd, "::", (char *)NULL);
		    }
		    Tcl_AppendObjToObj(newCmd, listv[0]);
		    Tcl_ListObjReplace(NULL, newList, 0, 1, 1, &newCmd);
		    if (patchedDict == NULL) {
			patchedDict = Tcl_DuplicateObj(objv[1]);
		    }
		    Tcl_DictObjPut(NULL, patchedDict, subcmdWordsObj, newList);
		}
		Tcl_DictObjNext(&search, &subcmdWordsObj, &listObj, &done);
	    } while (!done);
	    if (allocatedMapFlag) {
		Tcl_DecrRefCount(mapObj);
	    }
	    mapObj = (patchedDict ? patchedDict : objv[1]);
	    if (patchedDict) {
		allocatedMapFlag = 1;
	    }
	    continue;

	finishSearchAndError:
	    Tcl_DictObjDone(&search);
	    if (patchedDict) {
		Tcl_DecrRefCount(patchedDict);
	    }
	    goto freeMapAndError;
	}
	case CONF_NAMESPACE:
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "option -namespace is read-only", TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "READ_ONLY",
		    (char *)NULL);
	    goto freeMapAndError;
	case CONF_PREFIX:
	    if (Tcl_GetBooleanFromObj(interp, objv[1],
		    &permitPrefix) != TCL_OK) {
		goto freeMapAndError;
	    }
	    continue;
	case CONF_UNKNOWN:
	    if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
		goto freeMapAndError;
	    }
	    unknownObj = (len > 0 ? objv[1] : NULL);
	    continue;
	}
    }

    /*
     * Update the namespace now that we've finished the parsing stage.
     */

    flags = (permitPrefix ? flags | TCL_ENSEMBLE_PREFIX
	    : flags & ~TCL_ENSEMBLE_PREFIX);
    Tcl_SetEnsembleSubcommandList(interp, token, subcmdObj);
    Tcl_SetEnsembleMappingDict(interp, token, mapObj);
    Tcl_SetEnsembleParameterList(interp, token, paramObj);
    Tcl_SetEnsembleUnknownHandler(interp, token, unknownObj);
    Tcl_SetEnsembleFlags(interp, token, flags);
    return TCL_OK;

  freeMapAndError:
    if (allocatedMapFlag) {
	Tcl_DecrRefCount(mapObj);
    }
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCreateEnsembleInNs --
 *
 *	Like Tcl_CreateEnsemble, but additionally accepts as an argument the
665
666
667
668
669
670
671
672


673
674
675
676
677
678

679
680
681
682
683
684
685
754
755
756
757
758
759
760

761
762
763
764
765
766
767

768
769
770
771
772
773
774
775







-
+
+





-
+







    Tcl_Interp *interp,
    const char *name,		/* Simple name of command to create (no
				 * namespace components). */
    Tcl_Namespace *nameNsPtr,	/* Name of namespace to create the command
				 * in. */
    Tcl_Namespace *ensembleNsPtr,
				/* Name of the namespace for the ensemble. */
    int flags)
    int flags)			/* Whether we need exact matching and whether
				 * we bytecode-compile the ensemble's uses. */
{
    Namespace *nsPtr = (Namespace *) ensembleNsPtr;
    EnsembleConfig *ensemblePtr;
    Tcl_Command token;

    ensemblePtr = (EnsembleConfig *)Tcl_Alloc(sizeof(EnsembleConfig));
    ensemblePtr = (EnsembleConfig *) Tcl_Alloc(sizeof(EnsembleConfig));
    token = TclNRCreateCommandInNs(interp, name,
	    (Tcl_Namespace *) nameNsPtr, TclEnsembleImplementationCmd,
	    NsEnsembleImplementationCmdNR, ensemblePtr, DeleteEnsembleConfig);
    if (token == NULL) {
	Tcl_Free(ensemblePtr);
	return NULL;
    }
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741




742
743
744
745
746
747
748
749
750
751
752
753
754
755



































































756
757
758
759
760
761
762
815
816
817
818
819
820
821

822
823
824
825
826
827



828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919







-






-
-
-
+
+
+
+














+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 * Value
 *
 *	The token for the command created.
 *
 * Effect
 *	The ensemble is created and marked for compilation.
 *
 *
 *----------------------------------------------------------------------
 */

Tcl_Command
Tcl_CreateEnsemble(
    Tcl_Interp *interp,
    const char *name,
    Tcl_Namespace *namespacePtr,
    int flags)
    const char *name,		/* The ensemble name. */
    Tcl_Namespace *namespacePtr,/* Context namespace. */
    int flags)			/* Whether we need exact matching and whether
				 * we bytecode-compile the ensemble's uses. */
{
    Namespace *nsPtr = (Namespace *) namespacePtr, *foundNsPtr, *altNsPtr,
	    *actualNsPtr;
    const char * simpleName;

    if (nsPtr == NULL) {
	nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
    }

    TclGetNamespaceForQualName(interp, name, nsPtr, TCL_CREATE_NS_IF_UNKNOWN,
	    &foundNsPtr, &altNsPtr, &actualNsPtr, &simpleName);
    return TclCreateEnsembleInNs(interp, simpleName,
	    (Tcl_Namespace *) foundNsPtr, (Tcl_Namespace *) nsPtr, flags);
}

/*
 *----------------------------------------------------------------------
 *
 * GetEnsembleFromCommand --
 *
 *	Standard check to see if a command is an ensemble.
 *
 * Results:
 *	The ensemble implementation if the command is an ensemble. NULL if it
 *	isn't.
 *
 * Side effects:
 *	Reports an error in the interpreter (if non-NULL) if the command is
 *	not an ensemble.
 *
 *----------------------------------------------------------------------
 */
static inline EnsembleConfig *
GetEnsembleFromCommand(
    Tcl_Interp *interp,		/* Where to report an error. May be NULL. */
    Tcl_Command token)		/* What to check for ensemble-ness. */
{
    Command *cmdPtr = (Command *) token;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "command is not an ensemble", TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(interp,
		    "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (char *)NULL);
	}
	return NULL;
    }
    return (EnsembleConfig *) cmdPtr->objClientData;
}

/*
 *----------------------------------------------------------------------
 *
 * BumpEpochIfNecessary --
 *
 *	Increments the compilation epoch if the (ensemble) command is one where
 *	changes would be seen by the compiler in some cases.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	May trigger later bytecode recompilations.
 *
 *----------------------------------------------------------------------
 */
static inline void
BumpEpochIfNecessary(
    Tcl_Interp *interp,
    Tcl_Command token)		/* The ensemble command to check. */
{
    /*
     * Special hack to make compiling of [info exists] work when the
     * dictionary is modified.
     */

    if (((Command *) token)->compileProc != NULL) {
	((Interp *) interp)->compileEpoch++;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetEnsembleSubcommandList --
 *
 *	Set the subcommand list for a particular ensemble.
770
771
772
773
774
775
776
777

778
779
780
781

782
783
784
785
786

787
788
789
790
791

792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819

820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
927
928
929
930
931
932
933

934
935
936


937
938
939



940

941
942
943

944
945
946
947
948
949
950
951
952
953

954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970

971









972
973
974
975
976
977
978







-
+


-
-
+


-
-
-
+
-



-
+









-

















-
+
-
-
-
-
-
-
-
-
-







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

int
Tcl_SetEnsembleSubcommandList(
    Tcl_Interp *interp,
    Tcl_Command token,
    Tcl_Command token,		/* The ensemble command to write to. */
    Tcl_Obj *subcmdList)
{
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    EnsembleConfig *ensemblePtr = GetEnsembleFromCommand(interp, token);
    Tcl_Obj *oldList;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"command is not an ensemble", -1));
    if (ensemblePtr == NULL) {
	Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL);
	return TCL_ERROR;
    }
    if (subcmdList != NULL) {
	int length;
	Tcl_Size length;

	if (TclListObjLength(interp, subcmdList, &length) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (length < 1) {
	    subcmdList = NULL;
	}
    }

    ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData;
    oldList = ensemblePtr->subcmdList;
    ensemblePtr->subcmdList = subcmdList;
    if (subcmdList != NULL) {
	Tcl_IncrRefCount(subcmdList);
    }
    if (oldList != NULL) {
	TclDecrRefCount(oldList);
    }

    /*
     * Trigger an eventual recomputation of the ensemble command set. Note
     * that this is slightly tricky, as it means that we are not actually
     * counting the number of namespace export actions, but it is the simplest
     * way to go!
     */

    ensemblePtr->nsPtr->exportLookupEpoch++;

    BumpEpochIfNecessary(interp, token);
    /*
     * Special hack to make compiling of [info exists] work when the
     * dictionary is modified.
     */

    if (cmdPtr->compileProc != NULL) {
	((Interp *) interp)->compileEpoch++;
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetEnsembleParameterList --
845
846
847
848
849
850
851
852

853
854
855
856

857
858

859
860
861
862

863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
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
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033

1034









1035
1036
1037
1038
1039
1040
1041







-
+


-
-
+

-
+

-
-
-
+
-













-


















-
+
-
-
-
-
-
-
-
-
-







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

int
Tcl_SetEnsembleParameterList(
    Tcl_Interp *interp,
    Tcl_Command token,
    Tcl_Command token,		/* The ensemble command to write to. */
    Tcl_Obj *paramList)
{
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    EnsembleConfig *ensemblePtr = GetEnsembleFromCommand(interp, token);
    Tcl_Obj *oldList;
    int length;
    Tcl_Size length;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"command is not an ensemble", -1));
    if (ensemblePtr == NULL) {
	Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL);
	return TCL_ERROR;
    }
    if (paramList == NULL) {
	length = 0;
    } else {
	if (TclListObjLength(interp, paramList, &length) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (length < 1) {
	    paramList = NULL;
	}
    }

    ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData;
    oldList = ensemblePtr->parameterList;
    ensemblePtr->parameterList = paramList;
    if (paramList != NULL) {
	Tcl_IncrRefCount(paramList);
    }
    if (oldList != NULL) {
	TclDecrRefCount(oldList);
    }
    ensemblePtr->numParameters = length;

    /*
     * Trigger an eventual recomputation of the ensemble command set. Note
     * that this is slightly tricky, as it means that we are not actually
     * counting the number of namespace export actions, but it is the simplest
     * way to go!
     */

    ensemblePtr->nsPtr->exportLookupEpoch++;

    BumpEpochIfNecessary(interp, token);
    /*
     * Special hack to make compiling of [info exists] work when the
     * dictionary is modified.
     */

    if (cmdPtr->compileProc != NULL) {
	((Interp *) interp)->compileEpoch++;
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetEnsembleMappingDict --
922
923
924
925
926
927
928
929

930
931
932
933

934
935
936
937
938

939
940
941
942

943

944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119

1120









1121
1122
1123
1124
1125
1126
1127







-
+


-
-
+


-
-
-
+
-



+
-
+




















-
+

-
+










-

















-
+
-
-
-
-
-
-
-
-
-







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

int
Tcl_SetEnsembleMappingDict(
    Tcl_Interp *interp,
    Tcl_Command token,
    Tcl_Command token,		/* The ensemble command to write to. */
    Tcl_Obj *mapDict)
{
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    EnsembleConfig *ensemblePtr = GetEnsembleFromCommand(interp, token);
    Tcl_Obj *oldDict;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"command is not an ensemble", -1));
    if (ensemblePtr == NULL) {
	Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL);
	return TCL_ERROR;
    }
    if (mapDict != NULL) {
	Tcl_Size size;
	int size, done;
	int done;
	Tcl_DictSearch search;
	Tcl_Obj *valuePtr;

	if (Tcl_DictObjSize(interp, mapDict, &size) != TCL_OK) {
	    return TCL_ERROR;
	}

	for (Tcl_DictObjFirst(NULL, mapDict, &search, NULL, &valuePtr, &done);
		!done; Tcl_DictObjNext(&search, NULL, &valuePtr, &done)) {
	    Tcl_Obj *cmdObjPtr;
	    const char *bytes;

	    if (Tcl_ListObjIndex(interp, valuePtr, 0, &cmdObjPtr) != TCL_OK) {
		Tcl_DictObjDone(&search);
		return TCL_ERROR;
	    }
	    bytes = TclGetString(cmdObjPtr);
	    if (bytes[0] != ':' || bytes[1] != ':') {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"ensemble target is not a fully-qualified command",
			-1));
			TCL_AUTO_LENGTH));
		Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE",
			"UNQUALIFIED_TARGET", NULL);
			"UNQUALIFIED_TARGET", (char *)NULL);
		Tcl_DictObjDone(&search);
		return TCL_ERROR;
	    }
	}

	if (size < 1) {
	    mapDict = NULL;
	}
    }

    ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData;
    oldDict = ensemblePtr->subcommandDict;
    ensemblePtr->subcommandDict = mapDict;
    if (mapDict != NULL) {
	Tcl_IncrRefCount(mapDict);
    }
    if (oldDict != NULL) {
	TclDecrRefCount(oldDict);
    }

    /*
     * Trigger an eventual recomputation of the ensemble command set. Note
     * that this is slightly tricky, as it means that we are not actually
     * counting the number of namespace export actions, but it is the simplest
     * way to go!
     */

    ensemblePtr->nsPtr->exportLookupEpoch++;

    BumpEpochIfNecessary(interp, token);
    /*
     * Special hack to make compiling of [info exists] work when the
     * dictionary is modified.
     */

    if (cmdPtr->compileProc != NULL) {
	((Interp *) interp)->compileEpoch++;
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetEnsembleUnknownHandler --
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
1137
1138
1139
1140
1141
1142
1143

1144
1145
1146


1147
1148
1149



1150

1151
1152
1153

1154
1155
1156
1157
1158
1159
1160
1161
1162
1163

1164
1165
1166
1167
1168
1169
1170







-
+


-
-
+


-
-
-
+
-



-
+









-







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

int
Tcl_SetEnsembleUnknownHandler(
    Tcl_Interp *interp,
    Tcl_Command token,
    Tcl_Command token,		/* The ensemble command to write to. */
    Tcl_Obj *unknownList)
{
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    EnsembleConfig *ensemblePtr = GetEnsembleFromCommand(interp, token);
    Tcl_Obj *oldList;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"command is not an ensemble", -1));
    if (ensemblePtr == NULL) {
	Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL);
	return TCL_ERROR;
    }
    if (unknownList != NULL) {
	int length;
	Tcl_Size length;

	if (TclListObjLength(interp, unknownList, &length) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (length < 1) {
	    unknownList = NULL;
	}
    }

    ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData;
    oldList = ensemblePtr->unknownHandler;
    ensemblePtr->unknownHandler = unknownList;
    if (unknownList != NULL) {
	Tcl_IncrRefCount(unknownList);
    }
    if (oldList != NULL) {
	TclDecrRefCount(oldList);
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
1116
1117
1198
1199
1200
1201
1202
1203
1204

1205
1206
1207



1208
1209
1210



1211

1212
1213
1214



1215
1216
1217
1218
1219
1220
1221







-
+


-
-
-
+
+

-
-
-
+
-



-
-
-







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

int
Tcl_SetEnsembleFlags(
    Tcl_Interp *interp,
    Tcl_Command token,
    Tcl_Command token,		/* The ensemble command to write to. */
    int flags)
{
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    int wasCompiled;
    EnsembleConfig *ensemblePtr = GetEnsembleFromCommand(interp, token);
    int changedFlags = flags ^ ensemblePtr->flags;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"command is not an ensemble", -1));
    if (ensemblePtr == NULL) {
	Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL);
	return TCL_ERROR;
    }

    ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData;
    wasCompiled = ensemblePtr->flags & ENSEMBLE_COMPILE;

    /*
     * This API refuses to set the ENSEMBLE_DEAD flag...
     */

    ensemblePtr->flags &= ENSEMBLE_DEAD;
    ensemblePtr->flags |= flags & ~ENSEMBLE_DEAD;

1126
1127
1128
1129
1130
1131
1132
1133

1134
1135

1136
1137
1138
1139

1140
1141

1142
1143
1144
1145
1146
1147
1148
1149
1230
1231
1232
1233
1234
1235
1236

1237


1238




1239


1240

1241
1242
1243
1244
1245
1246
1247







-
+
-
-
+
-
-
-
-
+
-
-
+
-








    /*
     * If the ENSEMBLE_COMPILE flag status was changed, install or remove the
     * compiler function and bump the interpreter's compilation epoch so that
     * bytecode gets regenerated.
     */

    if (flags & ENSEMBLE_COMPILE) {
    if (changedFlags & ENSEMBLE_COMPILE) {
	if (!wasCompiled) {
	    ((Command*) ensemblePtr->token)->compileProc = TclCompileEnsemble;
	((Command*) ensemblePtr->token)->compileProc =
	    ((Interp *) interp)->compileEpoch++;
	}
    } else {
	if (wasCompiled) {
		((flags & ENSEMBLE_COMPILE) ? TclCompileEnsemble : NULL);
	    ((Command *) ensemblePtr->token)->compileProc = NULL;
	    ((Interp *) interp)->compileEpoch++;
	((Interp *) interp)->compileEpoch++;
	}
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
1164
1165
1166
1167
1168
1169
1170
1171

1172
1173
1174
1175

1176
1177
1178

1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1262
1263
1264
1265
1266
1267
1268

1269
1270
1271


1272
1273


1274




1275
1276


1277
1278
1279
1280
1281
1282
1283







-
+


-
-
+

-
-
+
-
-
-
-


-
-







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

int
Tcl_GetEnsembleSubcommandList(
    Tcl_Interp *interp,
    Tcl_Command token,
    Tcl_Command token,		/* The ensemble command to read from. */
    Tcl_Obj **subcmdListPtr)
{
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    EnsembleConfig *ensemblePtr = GetEnsembleFromCommand(interp, token);

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (interp != NULL) {
    if (ensemblePtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "command is not an ensemble", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL);
	}
	return TCL_ERROR;
    }

    ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData;
    *subcmdListPtr = ensemblePtr->subcmdList;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
1206
1207
1208
1209
1210
1211
1212
1213

1214
1215
1216
1217

1218
1219
1220

1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1296
1297
1298
1299
1300
1301
1302

1303
1304
1305


1306
1307


1308




1309
1310


1311
1312
1313
1314
1315
1316
1317







-
+


-
-
+

-
-
+
-
-
-
-


-
-







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

int
Tcl_GetEnsembleParameterList(
    Tcl_Interp *interp,
    Tcl_Command token,
    Tcl_Command token,		/* The ensemble command to read from. */
    Tcl_Obj **paramListPtr)
{
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    EnsembleConfig *ensemblePtr = GetEnsembleFromCommand(interp, token);

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (interp != NULL) {
    if (ensemblePtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "command is not an ensemble", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL);
	}
	return TCL_ERROR;
    }

    ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData;
    *paramListPtr = ensemblePtr->parameterList;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
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
1330
1331
1332
1333
1334
1335
1336

1337
1338
1339


1340
1341


1342




1343
1344


1345
1346
1347
1348
1349
1350
1351







-
+


-
-
+

-
-
+
-
-
-
-


-
-







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

int
Tcl_GetEnsembleMappingDict(
    Tcl_Interp *interp,
    Tcl_Command token,
    Tcl_Command token,		/* The ensemble command to read from. */
    Tcl_Obj **mapDictPtr)
{
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    EnsembleConfig *ensemblePtr = GetEnsembleFromCommand(interp, token);

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (interp != NULL) {
    if (ensemblePtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "command is not an ensemble", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL);
	}
	return TCL_ERROR;
    }

    ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData;
    *mapDictPtr = ensemblePtr->subcommandDict;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
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
1363
1364
1365
1366
1367
1368
1369

1370
1371
1372


1373
1374


1375




1376
1377


1378
1379
1380
1381
1382
1383
1384







-
+


-
-
+

-
-
+
-
-
-
-


-
-







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

int
Tcl_GetEnsembleUnknownHandler(
    Tcl_Interp *interp,
    Tcl_Command token,
    Tcl_Command token,		/* The ensemble command to read from. */
    Tcl_Obj **unknownListPtr)
{
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    EnsembleConfig *ensemblePtr = GetEnsembleFromCommand(interp, token);

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (interp != NULL) {
    if (ensemblePtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "command is not an ensemble", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL);
	}
	return TCL_ERROR;
    }

    ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData;
    *unknownListPtr = ensemblePtr->unknownHandler;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
1330
1331
1332
1333
1334
1335
1336
1337

1338
1339
1340
1341

1342
1343
1344

1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1396
1397
1398
1399
1400
1401
1402

1403
1404
1405


1406
1407


1408




1409
1410


1411
1412
1413
1414
1415
1416
1417







-
+


-
-
+

-
-
+
-
-
-
-


-
-







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

int
Tcl_GetEnsembleFlags(
    Tcl_Interp *interp,
    Tcl_Command token,
    Tcl_Command token,		/* The ensemble command to read from. */
    int *flagsPtr)
{
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    EnsembleConfig *ensemblePtr = GetEnsembleFromCommand(interp, token);

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (interp != NULL) {
    if (ensemblePtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "command is not an ensemble", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL);
	}
	return TCL_ERROR;
    }

    ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData;
    *flagsPtr = ensemblePtr->flags;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
1371
1372
1373
1374
1375
1376
1377
1378

1379
1380
1381
1382

1383
1384
1385

1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1429
1430
1431
1432
1433
1434
1435

1436
1437
1438


1439
1440


1441




1442
1443


1444
1445
1446
1447
1448
1449
1450







-
+


-
-
+

-
-
+
-
-
-
-


-
-







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

int
Tcl_GetEnsembleNamespace(
    Tcl_Interp *interp,
    Tcl_Command token,
    Tcl_Command token,		/* The ensemble command to read from. */
    Tcl_Namespace **namespacePtrPtr)
{
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    EnsembleConfig *ensemblePtr = GetEnsembleFromCommand(interp, token);

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (interp != NULL) {
    if (ensemblePtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "command is not an ensemble", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL);
	}
	return TCL_ERROR;
    }

    ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData;
    *namespacePtrPtr = (Tcl_Namespace *) ensemblePtr->nsPtr;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
1419
1420
1421
1422
1423
1424
1425
1426

1427
1428
1429
1430


1431
1432
1433
1434

1435
1436
1437
1438
1439
1440

1441
1442
1443


1444
1445
1446
1447
1448
1449

1450
1451
1452
1453
1454
1455

1456
1457
1458
1459
1460
1461
1462
1469
1470
1471
1472
1473
1474
1475

1476
1477



1478
1479
1480
1481
1482

1483
1484
1485
1486
1487
1488

1489
1490


1491
1492
1493
1494
1495
1496
1497

1498
1499
1500
1501
1502
1503

1504
1505
1506
1507
1508
1509
1510
1511







-
+

-
-
-
+
+



-
+





-
+

-
-
+
+





-
+





-
+







    Tcl_Interp *interp,		/* Where to do the lookup, and where to write
				 * the errors if TCL_LEAVE_ERR_MSG is set in
				 * the flags. */
    Tcl_Obj *cmdNameObj,	/* Name of command to look up. */
    int flags)			/* Either 0 or TCL_LEAVE_ERR_MSG; other flags
				 * are probably not useful. */
{
    Command *cmdPtr;
    Tcl_Command token;

    cmdPtr = (Command *)
	    Tcl_FindCommand(interp, TclGetString(cmdNameObj), NULL, flags);
    if (cmdPtr == NULL) {
    token = Tcl_FindCommand(interp, TclGetString(cmdNameObj), NULL, flags);
    if (token == NULL) {
	return NULL;
    }

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
    if (((Command *) token)->objProc != TclEnsembleImplementationCmd) {
	/*
	 * Reuse existing infrastructure for following import link chains
	 * rather than duplicating it.
	 */

	cmdPtr = (Command *) TclGetOriginalCommand((Tcl_Command) cmdPtr);
	token = TclGetOriginalCommand(token);

	if (cmdPtr == NULL
		|| cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (token == NULL ||
		((Command *) token)->objProc != TclEnsembleImplementationCmd) {
	    if (flags & TCL_LEAVE_ERR_MSG) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"\"%s\" is not an ensemble command",
			TclGetString(cmdNameObj)));
		Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENSEMBLE",
			TclGetString(cmdNameObj), NULL);
			TclGetString(cmdNameObj), (char *)NULL);
	    }
	    return NULL;
	}
    }

    return (Tcl_Command) cmdPtr;
    return token;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_IsEnsemble --
 *
1470
1471
1472
1473
1474
1475
1476
1477

1478
1479
1480
1481
1482
1483
1484
1519
1520
1521
1522
1523
1524
1525

1526
1527
1528
1529
1530
1531
1532
1533







-
+







 *	None
 *
 *----------------------------------------------------------------------
 */

int
Tcl_IsEnsemble(
    Tcl_Command token)
    Tcl_Command token)		/* The command to check. */
{
    Command *cmdPtr = (Command *) token;

    if (cmdPtr->objProc == TclEnsembleImplementationCmd) {
	return 1;
    }
    cmdPtr = (Command *) TclGetOriginalCommand((Tcl_Command) cmdPtr);
1499
1500
1501
1502
1503
1504
1505





1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519


1520
1521
1522
1523
1524
1525

1526

1527
1528
1529
1530
1531
1532
1533
1534
1535

1536
1537
1538
1539
1540
1541
1542
1543
1544

1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560

1561
1562
1563
1564
1565
1566
1567
1548
1549
1550
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







+
+
+
+
+












-
-
+
+






+
-
+








-
+








-
+















-
+







 *
 *	The 'name' parameter may be a single command name or a list if
 *	creating an ensemble subcommand (see the binary implementation).
 *
 *	Currently, the TCL_ENSEMBLE_PREFIX ensemble flag is only used on
 *	top-level ensemble commands.
 *
 *	This code is not safe to run in Safe interpreter after user code has
 *	executed. That's OK right now because it's just used to set up Tcl,
 *	but it means we mustn't expose it at all, not even to Tk (until we can
 *	hide commands in namespaces directly).
 *
 * Results:
 *	Handle for the new ensemble, or NULL on failure.
 *
 * Side effects:
 *	May advance the bytecode compilation epoch.
 *
 *----------------------------------------------------------------------
 */

Tcl_Command
TclMakeEnsemble(
    Tcl_Interp *interp,
    const char *name,		 /* The ensemble name (as explained above) */
    const EnsembleImplMap map[]) /* The subcommands to create */
    const char *name,		/* The ensemble name (as explained above) */
    const EnsembleImplMap map[])/* The subcommands to create */
{
    Tcl_Command ensemble;
    Tcl_Namespace *ns;
    Tcl_DString buf, hiddenBuf;
    const char **nameParts = NULL;
    const char *cmdName = NULL;
    Tcl_Size i, nameCount = 0;
    int i, nameCount = 0, ensembleFlags = 0, hiddenLen;
    int ensembleFlags = 0, hiddenLen;

    /*
     * Construct the path for the ensemble namespace and create it.
     */

    Tcl_DStringInit(&buf);
    Tcl_DStringInit(&hiddenBuf);
    TclDStringAppendLiteral(&hiddenBuf, "tcl:");
    Tcl_DStringAppend(&hiddenBuf, name, -1);
    Tcl_DStringAppend(&hiddenBuf, name, TCL_AUTO_LENGTH);
    TclDStringAppendLiteral(&hiddenBuf, ":");
    hiddenLen = Tcl_DStringLength(&hiddenBuf);
    if (name[0] == ':' && name[1] == ':') {
	/*
	 * An absolute name, so use it directly.
	 */

	cmdName = name;
	Tcl_DStringAppend(&buf, name, -1);
	Tcl_DStringAppend(&buf, name, TCL_AUTO_LENGTH);
	ensembleFlags = TCL_ENSEMBLE_PREFIX;
    } else {
	/*
	 * Not an absolute name, so do munging of it. Note that this treats a
	 * multi-word list differently to a single word.
	 */

	TclDStringAppendLiteral(&buf, "::tcl");

	if (Tcl_SplitList(NULL, name, &nameCount, &nameParts) != TCL_OK) {
	    Tcl_Panic("invalid ensemble name '%s'", name);
	}

	for (i = 0; i < nameCount; ++i) {
	    TclDStringAppendLiteral(&buf, "::");
	    Tcl_DStringAppend(&buf, nameParts[i], -1);
	    Tcl_DStringAppend(&buf, nameParts[i], TCL_AUTO_LENGTH);
	}
    }

    ns = Tcl_FindNamespace(interp, Tcl_DStringValue(&buf), NULL,
	    TCL_CREATE_NS_IF_UNKNOWN);
    if (!ns) {
	Tcl_Panic("unable to find or create %s namespace!",
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







-
+





-


-
-
+
+
















-
+
+


+
+









-
-
+
+







    ensemble = Tcl_CreateEnsemble(interp, cmdName, ns, ensembleFlags);

    /*
     * Create the ensemble mapping dictionary and the ensemble command procs.
     */

    if (ensemble != NULL) {
	Tcl_Obj *mapDict, *fromObj, *toObj;
	Tcl_Obj *mapDict, *toObj;
	Command *cmdPtr;

	TclDStringAppendLiteral(&buf, "::");
	TclNewObj(mapDict);
	for (i=0 ; map[i].name != NULL ; i++) {
	    fromObj = Tcl_NewStringObj(map[i].name, -1);
	    TclNewStringObj(toObj, Tcl_DStringValue(&buf),
		    Tcl_DStringLength(&buf));
	    Tcl_AppendToObj(toObj, map[i].name, -1);
	    Tcl_DictObjPut(NULL, mapDict, fromObj, toObj);
	    Tcl_AppendToObj(toObj, map[i].name, TCL_AUTO_LENGTH);
	    TclDictPut(NULL, mapDict, map[i].name, toObj);

	    if (map[i].proc || map[i].nreProc) {
		/*
		 * If the command is unsafe, hide it when we're in a safe
		 * interpreter. The code to do this is really hokey! It also
		 * doesn't work properly yet; this function is always
		 * currently called before the safe-interp flag is set so the
		 * Tcl_IsSafe check fails.
		 */

		if (map[i].unsafe && Tcl_IsSafe(interp)) {
		    cmdPtr = (Command *)
			    Tcl_NRCreateCommand(interp, "___tmp", map[i].proc,
			    map[i].nreProc, map[i].clientData, NULL);
		    Tcl_DStringSetLength(&hiddenBuf, hiddenLen);
		    if (Tcl_HideCommand(interp, "___tmp",
			    Tcl_DStringAppend(&hiddenBuf, map[i].name, -1))) {
			    Tcl_DStringAppend(&hiddenBuf, map[i].name,
				    TCL_AUTO_LENGTH))) {
			Tcl_Panic("%s", Tcl_GetStringResult(interp));
		    }
		    /* don't compile unsafe subcommands in safe interp */
		    cmdPtr->compileProc = NULL;
		} else {
		    /*
		     * Not hidden, so just create it. Yay!
		     */

		    cmdPtr = (Command *)
			    Tcl_NRCreateCommand(interp, TclGetString(toObj),
			    map[i].proc, map[i].nreProc, map[i].clientData,
			    NULL);
		}
		cmdPtr->compileProc = map[i].compileProc;
		    cmdPtr->compileProc = map[i].compileProc;
		}
	    }
	}
	Tcl_SetEnsembleMappingDict(interp, ensemble, mapDict);
    }

    Tcl_DStringFree(&buf);
    Tcl_DStringFree(&hiddenBuf);
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


1749
1750
1751
1752
1753
1754
1755
1756


1757
1758
1759
1760
1761
1762

1763
1764
1765
1766


1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781


1782
1783
1784
1785
1786
1787
1788
1789

1790
1791
1792
1793
1794
1795

1796
1797
1798
1799
1800
1801
1802


1803
1804
1805
1806
1807


1808
1809
1810
1811


1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826




1827
1828
1829
1830
1831
1832
1833
1834
1835
1836


1837
1838
1839
1840
1841
1842
1843
1844

1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859

1860
1861
1862
1863
1864
1865
1866
1867
1868
1869

1870
1871
1872
1873
1874

1875
1876
1877
1878
1879




1880
1881
1882
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
1958
1959
1960
1961

1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973


1974
1975

1976
1977
1978


1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990

1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004


2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021


2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033

2034
2035
2036
2037
2038
2039
2040
1727
1728
1729
1730
1731
1732
1733

1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744

1745
1746
1747
1748
1749

1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760

1761
1762
1763

1764
1765
1766
1767
1768
1769

1770
1771

1772
1773
1774
1775
1776
1777
1778


1779
1780
1781
1782
1783
1784
1785
1786
1787
1788

1789
1790
1791
1792
1793
1794
1795


1796
1797
1798
1799
1800
1801
1802
1803


1804
1805
1806
1807
1808
1809
1810
1811


1812
1813


1814
1815
1816

1817
1818
1819


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


1835
1836
1837
1838
1839
1840
1841

1842

1843
1844
1845
1846
1847
1848

1849
1850
1851
1852
1853
1854


1855
1856

1857
1858


1859
1860

1861


1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874




1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959


1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975


1976
1977
1978
1979
1980
1981
1982



1983
1984
1985

1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000




2001
2002
2003
2004
2005
2006
2007
2008

2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020

2021
2022
2023

2024
2025
2026

2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039

2040
2041
2042
2043
2044
2045
2046
2047
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







-
+










-
+




-
+










-
+


-
+





-
+

-
+






-
-
+









-
+






-
-
+
+
+





-
-
+
+






-
-
+
+
-
-



-
+


-
-
+
+













-
-
+
+





-

-
+





-
+





-
-
+
+
-


-
-
+
+
-

-
-
+
+











-
-
-
-
+
+
+
+







-
-
-
+
+







-
+














-
+









-
+




-
+
-
-
-
-
-
+
+
+
+



-
+
-



-
+


-
+

-
+

















-
-
+
+














-
-
+
+





-
-
-
+
+
+
-















-
-
-
-
+
+
+
+




-
+











-
+
+

-
+


-
+
+











-
+












-
-
+
+















-
-
+
+











-
+







 *	placed in the interpreter's result.
 *
 *----------------------------------------------------------------------
 */

int
TclEnsembleImplementationCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    return Tcl_NRCallObjProc(interp, NsEnsembleImplementationCmdNR,
	    clientData, objc, objv);
}

static int
NsEnsembleImplementationCmdNR(
    ClientData clientData,
    void *clientData,		/* The ensemble this is the impl. of. */
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    EnsembleConfig *ensemblePtr = (EnsembleConfig *)clientData;
    EnsembleConfig *ensemblePtr = (EnsembleConfig *) clientData;
				/* The ensemble itself. */
    Tcl_Obj *prefixObj;		/* An object containing the prefix words of
				 * the command that implements the
				 * subcommand. */
    Tcl_HashEntry *hPtr;	/* Used for efficient lookup of fully
				 * specified but not yet cached command
				 * names. */
    int reparseCount = 0;	/* Number of reparses. */
    Tcl_Obj *errorObj;		/* Used for building error messages. */
    Tcl_Obj *subObj;
    size_t subIdx;
    Tcl_Size subIdx;

    /*
     * Must recheck objc, since numParameters might have changed. Cf. test
     * Must recheck objc since numParameters might have changed. See test
     * namespace-53.9.
     */

  restartEnsembleParse:
    subIdx = 1 + ensemblePtr->numParameters;
    if ((size_t)objc < subIdx + 1) {
    if (objc < subIdx + 1) {
	/*
	 * We don't have a subcommand argument. Make error message.
	 * No subcommand argument. Make error message.
	 */

	Tcl_DString buf;	/* Message being built */

	Tcl_DStringInit(&buf);
	if (ensemblePtr->parameterList) {
	    Tcl_DStringAppend(&buf,
		    TclGetString(ensemblePtr->parameterList), -1);
	    TclDStringAppendObj(&buf, ensemblePtr->parameterList);
	    TclDStringAppendLiteral(&buf, " ");
	}
	TclDStringAppendLiteral(&buf, "subcommand ?arg ...?");
	Tcl_WrongNumArgs(interp, 1, objv, Tcl_DStringValue(&buf));
	Tcl_DStringFree(&buf);

	return TCL_ERROR;
    }

    if (ensemblePtr->nsPtr->flags & NS_DYING) {
    if (ensemblePtr->nsPtr->flags & NS_DEAD) {
	/*
	 * Don't know how we got here, but make things give up quickly.
	 */

	if (!Tcl_InterpDeleted(interp)) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "ensemble activated for deleted namespace", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "DEAD", NULL);
		    "ensemble activated for deleted namespace",
		    TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "DEAD", (char *)NULL);
	}
	return TCL_ERROR;
    }

    /*
     * Determine if the table of subcommands is right. If so, we can just look
     * up in there and go straight to dispatch.
     * If the table of subcommands is valid just lookup up the command there
     * and go to dispatch.
     */

    subObj = objv[subIdx];

    if (ensemblePtr->epoch == ensemblePtr->nsPtr->exportLookupEpoch) {
	/*
	 * Table of subcommands is still valid; therefore there might be a
	 * valid cache of discovered information which we can reuse. Do the
	 * Table of subcommands is still valid so if the internal representtion
	 * is an ensembleCmd, just call it.
	 * check here, and if we're still valid, we can jump straight to the
	 * part where we do the invocation of the subcommand.
	 */
	EnsembleCmdRep *ensembleCmd;

	ECRGetIntRep(subObj, ensembleCmd);
	ECRGetInternalRep(subObj, ensembleCmd);
	if (ensembleCmd) {
	    if (ensembleCmd->epoch == ensemblePtr->epoch &&
		    ensembleCmd->token == (Command *)ensemblePtr->token) {
		prefixObj = (Tcl_Obj *)Tcl_GetHashValue(ensembleCmd->hPtr);
		    ensembleCmd->token == (Command *) ensemblePtr->token) {
		prefixObj = (Tcl_Obj *) Tcl_GetHashValue(ensembleCmd->hPtr);
		Tcl_IncrRefCount(prefixObj);
		if (ensembleCmd->fix) {
		    TclSpellFix(interp, objv, objc, subIdx, subObj, ensembleCmd->fix);
		}
		goto runResultingSubcommand;
	    }
	}
    } else {
	BuildEnsembleConfig(ensemblePtr);
	ensemblePtr->epoch = ensemblePtr->nsPtr->exportLookupEpoch;
    }

    /*
     * Look in the hashtable for the subcommand name; this is the fastest way
     * of all if there is no cache in operation.
     * Look in the hashtable for the named subcommand.  This is the fastest
     * path if there is no cache in operation.
     */

    hPtr = Tcl_FindHashEntry(&ensemblePtr->subcommandTable,
	    TclGetString(subObj));
    if (hPtr != NULL) {

	/*
	 * Cache for later in the subcommand object.
	 * Cache ensemble in the subcommand object for later.
	 */

	MakeCachedEnsembleCommand(subObj, ensemblePtr, hPtr, NULL);
    } else if (!(ensemblePtr->flags & TCL_ENSEMBLE_PREFIX)) {
	/*
	 * Could not map, no prefixing, go to unknown/error handling.
	 * Could not map.  No prefixing.  Go to unknown/error handling.
	 */

	goto unknownOrAmbiguousSubcommand;
    } else {
	/*
	 * If we've not already confirmed the command with the hash as part of
	 * building our export table, we need to scan the sorted array for
	 * If the command isn't yet confirmed with the hash as part of building
	 * the export table, scan the sorted array for matches.
	 * matches.
	 */

	const char *subcmdName; /* Name of the subcommand, or unique prefix of
				 * it (will be an error for a non-unique
	const char *subcmdName; /* Name of the subcommand or unique prefix of
				 * it (a non-unique prefix produces an error). */
				 * prefix). */
	char *fullName = NULL;	/* Full name of the subcommand. */
	size_t stringLength, i;
	size_t tableLength = ensemblePtr->subcommandTable.numEntries;
	Tcl_Size stringLength, i;
	Tcl_Size tableLength = ensemblePtr->subcommandTable.numEntries;
	Tcl_Obj *fix;

	subcmdName = TclGetStringFromObj(subObj, &stringLength);
	for (i=0 ; i<tableLength ; i++) {
	    int cmp = strncmp(subcmdName,
		    ensemblePtr->subcommandArrayPtr[i],
		    stringLength);

	    if (cmp == 0) {
		if (fullName != NULL) {
		    /*
		     * Since there's never the exact-match case to worry about
		     * (hash search filters this), getting here indicates that
		     * our subcommand is an ambiguous prefix of (at least) two
		     * exported subcommands, which is an error case.
		     * Hash search filters out the exact-match case, so getting
		     * here indicates that the subcommand is an ambiguous
		     * prefix of at least two exported subcommands, which is an
		     * error case.
		     */

		    goto unknownOrAmbiguousSubcommand;
		}
		fullName = ensemblePtr->subcommandArrayPtr[i];
	    } else if (cmp < 0) {
		/*
		 * Because we are searching a sorted table, we can now stop
		 * searching because we have gone past anything that could
		 * possibly match.
		 * The table is sorted so stop searching because a match would
		 * have been found already.
		 */

		break;
	    }
	}
	if (fullName == NULL) {
	    /*
	     * The subcommand is not a prefix of anything, so bail out!
	     * The subcommand is not a prefix of anything. Bail out!
	     */

	    goto unknownOrAmbiguousSubcommand;
	}
	hPtr = Tcl_FindHashEntry(&ensemblePtr->subcommandTable, fullName);
	if (hPtr == NULL) {
	    Tcl_Panic("full name %s not found in supposedly synchronized hash",
		    fullName);
	}

	/*
	 * Record the spelling correction for usage message.
	 */

	fix = Tcl_NewStringObj(fullName, -1);
	fix = Tcl_NewStringObj(fullName, TCL_AUTO_LENGTH);

	/*
	 * Cache for later in the subcommand object.
	 */

	MakeCachedEnsembleCommand(subObj, ensemblePtr, hPtr, fix);
	TclSpellFix(interp, objv, objc, subIdx, subObj, fix);
    }

    prefixObj = (Tcl_Obj *)Tcl_GetHashValue(hPtr);
    prefixObj = (Tcl_Obj *) Tcl_GetHashValue(hPtr);
    Tcl_IncrRefCount(prefixObj);
  runResultingSubcommand:

    /*
     * Do the real work of execution of the subcommand by building an array of
     * Execute the subcommand by populating an array of objects, which might
     * objects (note that this is potentially not the same length as the
     * number of arguments to this ensemble command), populating it and then
     * feeding it back through the main command-lookup engine. In theory, we
     * could look up the command in the namespace ourselves, as we already
     * have the namespace in which it is guaranteed to exist,
     * not be the same length as the number of arguments to this ensemble
     * command, and then handing it to the main command-lookup engine. In
     * theory, the command could be looked up right here using the namespace in
     * which it is guaranteed to exist,
     *
     *   ((Q: That's not true if the -map option is used, is it?))
     *
     * but we don't do that (the cacheing of the command object used should
     * but don't do that because caching of the command object should help.
     * help with that.)
     */

    {
	Tcl_Obj *copyPtr;	/* The actual list of words to dispatch to.
	Tcl_Obj *copyPtr;	/* The list of words to dispatch on.
				 * Will be freed by the dispatch engine. */
	Tcl_Obj **copyObjv;
	int copyObjc, prefixObjc;
	Tcl_Size copyObjc, prefixObjc;

	Tcl_ListObjLength(NULL, prefixObj, &prefixObjc);
	TclListObjLength(NULL, prefixObj, &prefixObjc);

	if (objc == 2) {
	    copyPtr = TclListObjCopy(NULL, prefixObj);
	} else {
	    copyPtr = Tcl_NewListObj(objc - 2 + prefixObjc, NULL);
	    Tcl_ListObjAppendList(NULL, copyPtr, prefixObj);
	    Tcl_ListObjReplace(NULL, copyPtr, LIST_MAX, 0,
		    ensemblePtr->numParameters, objv + 1);
	    Tcl_ListObjReplace(NULL, copyPtr, LIST_MAX, 0,
		    objc - 2 - ensemblePtr->numParameters,
		    objv + 2 + ensemblePtr->numParameters);
	}
	Tcl_IncrRefCount(copyPtr);
	TclNRAddCallback(interp, TclNRReleaseValues, copyPtr, NULL, NULL, NULL);
	TclDecrRefCount(prefixObj);

	/*
	 * Record what arguments the script sent in so that things like
	 * Tcl_WrongNumArgs can give the correct error message. Parameters
	 * Record the words of the command as given so that routines like
	 * Tcl_WrongNumArgs can produce the correct error message. Parameters
	 * count both as inserted and removed arguments.
	 */

	if (TclInitRewriteEnsemble(interp, 2 + ensemblePtr->numParameters,
		prefixObjc + ensemblePtr->numParameters, objv)) {
	    TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL,
		    NULL);
	}

	/*
	 * Hand off to the target command.
	 */

	TclSkipTailcall(interp);
	Tcl_ListObjGetElements(NULL, copyPtr, &copyObjc, &copyObjv);
	((Interp *)interp)->lookupNsPtr = ensemblePtr->nsPtr;
	TclListObjGetElements(NULL, copyPtr, &copyObjc, &copyObjv);
	((Interp *) interp)->lookupNsPtr = ensemblePtr->nsPtr;
	return TclNREvalObjv(interp, copyObjc, copyObjv, TCL_EVAL_INVOKE, NULL);
    }

  unknownOrAmbiguousSubcommand:
    /*
     * Have not been able to match the subcommand asked for with a real
     * subcommand that we export. See whether a handler has been registered
     * for dealing with this situation. Will only call (at most) once for any
     * The named subcommand did not match any exported command. If there is a
     * handler registered unknown subcommands, call it, but not more than once
     * for this call.
     * particular ensemble invocation.
     */

    if (ensemblePtr->unknownHandler != NULL && reparseCount++ < 1) {
	switch (EnsembleUnknownCallback(interp, ensemblePtr, objc, objv,
		&prefixObj)) {
	case TCL_OK:
	    goto runResultingSubcommand;
	case TCL_ERROR:
	    return TCL_ERROR;
	case TCL_CONTINUE:
	    goto restartEnsembleParse;
	}
    }

    /*
     * We cannot determine what subcommand to hand off to, so generate a
     * (standard) failure message. Note the one odd case compared with
     * standard ensemble-like command, which is where a namespace has no
     * exported commands at all...
     * Could not find a routine for the named subcommand so generate a standard
     * failure message.  The one odd case compared with a standard
     * ensemble-like command is where a namespace has no exported commands at
     * all...
     */

    Tcl_ResetResult(interp);
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "SUBCOMMAND",
	    TclGetString(subObj), NULL);
	    TclGetString(subObj), (char *)NULL);
    if (ensemblePtr->subcommandTable.numEntries == 0) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"unknown subcommand \"%s\": namespace %s does not"
		" export any commands", TclGetString(subObj),
		ensemblePtr->nsPtr->fullName));
	return TCL_ERROR;
    }
    errorObj = Tcl_ObjPrintf("unknown%s subcommand \"%s\": must be ",
	    (ensemblePtr->flags & TCL_ENSEMBLE_PREFIX ? " or ambiguous" : ""),
	    TclGetString(subObj));
    if (ensemblePtr->subcommandTable.numEntries == 1) {
	Tcl_AppendToObj(errorObj, ensemblePtr->subcommandArrayPtr[0], -1);
	Tcl_AppendToObj(errorObj, ensemblePtr->subcommandArrayPtr[0],
		TCL_AUTO_LENGTH);
    } else {
	size_t i;
	Tcl_Size i;

	for (i=0 ; i<ensemblePtr->subcommandTable.numEntries-1 ; i++) {
	    Tcl_AppendToObj(errorObj, ensemblePtr->subcommandArrayPtr[i], -1);
	    Tcl_AppendToObj(errorObj, ensemblePtr->subcommandArrayPtr[i],
		    TCL_AUTO_LENGTH);
	    Tcl_AppendToObj(errorObj, ", ", 2);
	}
	Tcl_AppendPrintfToObj(errorObj, "or %s",
		ensemblePtr->subcommandArrayPtr[i]);
    }
    Tcl_SetObjResult(interp, errorObj);
    return TCL_ERROR;
}

int
TclClearRootEnsemble(
    TCL_UNUSED(ClientData *),
    TCL_UNUSED(void **),
    Tcl_Interp *interp,
    int result)
{
    TclResetRewriteEnsemble(interp, 1);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TclInitRewriteEnsemble --
 *
 *	Applies a rewrite of arguments so that an ensemble subcommand will
 *	report error messages correctly for the overall command.
 *	Applies a rewrite of arguments so that an ensemble subcommand
 *	correctly reports any error messages for the overall command.
 *
 * Results:
 *	Whether this is the first rewrite applied, a value which must be
 *	passed to TclResetRewriteEnsemble when undoing this command's
 *	behaviour.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclInitRewriteEnsemble(
    Tcl_Interp *interp,
    size_t numRemoved,
    size_t numInserted,
    Tcl_Size numRemoved,
    Tcl_Size numInserted,
    Tcl_Obj *const *objv)
{
    Interp *iPtr = (Interp *) interp;

    int isRootEnsemble = (iPtr->ensembleRewrite.sourceObjs == NULL);

    if (isRootEnsemble) {
	iPtr->ensembleRewrite.sourceObjs = objv;
	iPtr->ensembleRewrite.numRemovedObjs = numRemoved;
	iPtr->ensembleRewrite.numInsertedObjs = numInserted;
    } else {
	size_t numIns = iPtr->ensembleRewrite.numInsertedObjs;
	Tcl_Size numIns = iPtr->ensembleRewrite.numInsertedObjs;

	if (numIns < numRemoved) {
	    iPtr->ensembleRewrite.numRemovedObjs += numRemoved - numIns;
	    iPtr->ensembleRewrite.numInsertedObjs = numInserted;
	} else {
	    iPtr->ensembleRewrite.numInsertedObjs += numInserted - numRemoved;
	}
2075
2076
2077
2078
2079
2080
2081
2082

2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096

2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113


2114
2115
2116
2117
2118
2119
2120
2121


2122
2123
2124
2125
2126
2127
2128
2125
2126
2127
2128
2129
2130
2131

2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145

2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161


2162
2163
2164
2165
2166
2167
2168
2169


2170
2171
2172
2173
2174
2175
2176
2177
2178







-
+













-
+















-
-
+
+






-
-
+
+







}

/*
 *----------------------------------------------------------------------
 *
 * TclSpellFix --
 *
 *	Record a spelling correction that needs making in the generation of
 *	Records a spelling correction that needs making in the generation of
 *	the WrongNumArgs usage message.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Can create an alternative ensemble rewrite structure.
 *
 *----------------------------------------------------------------------
 */

static int
FreeER(
    ClientData data[],
    void *data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    Tcl_Obj **tmp = (Tcl_Obj **) data[0];
    Tcl_Obj **store = (Tcl_Obj **) data[1];

    Tcl_Free(store);
    Tcl_Free(tmp);
    return result;
}

void
TclSpellFix(
    Tcl_Interp *interp,
    Tcl_Obj *const *objv,
    int objc,
    size_t badIdx,
    Tcl_Size objc,
    Tcl_Size badIdx,
    Tcl_Obj *bad,
    Tcl_Obj *fix)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *const *search;
    Tcl_Obj **store;
    size_t idx;
    size_t size;
    Tcl_Size idx;
    Tcl_Size size;

    if (iPtr->ensembleRewrite.sourceObjs == NULL) {
	iPtr->ensembleRewrite.sourceObjs = objv;
	iPtr->ensembleRewrite.numRemovedObjs = 0;
	iPtr->ensembleRewrite.numInsertedObjs = 0;
    }

2140
2141
2142
2143
2144
2145
2146
2147
2148


2149
2150
2151
2152
2153
2154
2155
2190
2191
2192
2193
2194
2195
2196


2197
2198
2199
2200
2201
2202
2203
2204
2205







-
-
+
+







	 */

	search = (Tcl_Obj *const *) search[1];
    }

    if (badIdx < iPtr->ensembleRewrite.numInsertedObjs) {
	/*
	 * Misspelled value was inserted. We cannot directly jump to the bad
	 * value, but have to search.
	 * Misspelled value was inserted. Cannot directly jump to the bad
	 * value.  Must search.
	 */

	idx = 1;
	while (idx < size) {
	    if (search[idx] == bad) {
		break;
	    }
2172
2173
2174
2175
2176
2177
2178
2179

2180
2181

2182
2183
2184
2185
2186
2187
2188
2222
2223
2224
2225
2226
2227
2228

2229
2230

2231
2232
2233
2234
2235
2236
2237
2238







-
+

-
+







	}
    }

    search = iPtr->ensembleRewrite.sourceObjs;
    if (search[0] == NULL) {
	store = (Tcl_Obj **) search[2];
    }  else {
	Tcl_Obj **tmp = (Tcl_Obj **)Tcl_Alloc(3 * sizeof(Tcl_Obj *));
	Tcl_Obj **tmp = (Tcl_Obj **) Tcl_Alloc(3 * sizeof(Tcl_Obj *));

	store = (Tcl_Obj **)Tcl_Alloc(size * sizeof(Tcl_Obj *));
	store = (Tcl_Obj **) Tcl_Alloc(size * sizeof(Tcl_Obj *));
	memcpy(store, iPtr->ensembleRewrite.sourceObjs,
		size * sizeof(Tcl_Obj *));

	/*
	 * Awful casting abuse here! Note that the NULL in the first element
	 * indicates that the initial objects are a raw array in the second
	 * element and the rewritten ones are a raw array in the third.
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
2273
2274

2275
2276
2277
2278
2279
2280
2281

2282
2283
2284
2285
2286
2287
2288
2289
2290



2291
2292
2293
2294
2295
2296
2297
2298
2299
2300


2301
2302

2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392

2393
2394
2395


2396
2397
2398
2399
2400
2401
2402
2403
2404
2405





2406
2407
2408
2409

2410
2411
2412
2413
2414
2415
2416
2417

2418
2419
2420
2421
2422


2423
2424
2425
2426
2427
2428
2429
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292

2293
2294
2295
2296


2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308

2309
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
2390


2391
2392


2393
2394
2395
2396
2397
2398
2399
2400
2401




2402

2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414

2415
2416
2417
2418
2419
2420
2421
2422

2423
2424
2425
2426
2427
2428
2429

2430
2431
2432
2433

2434
2435
2436
2437

2438
2439
2440
2441

2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490

2491
2492
2493
2494
2495
2496
2497
2498

2499

2500
2501


2502
2503
2504
2505
2506
2507
2508
2509
2510







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













-




-
-
+
+

+





+
+
+
-
+
+
+








-
+

-
-
-
-
-
+
+
+
+
+




-
-
+
+


-
+







-
-
-
-
+
+
+
+
+
+

+
+
-
+



-
+






-
+






-
-
-
+
+
+
-








-
+
+

-
+






-
-
+
+
-
-
+








-
-
-
-
+
-












-
+







-
+






-
+
+


-
+
+


-
+
+


-
+
+








-
+














-
-
-
+
+
+
-


-
+


-
+
+






-
-
-
-
+
+
+
+
+



-
+







-
+
-


-
-
+
+







    Tcl_IncrRefCount(fix);
    TclNRAddCallback(interp, TclNRReleaseValues, fix, NULL, NULL, NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * TclEnsembleGetRewriteValues --
 *
 *	Get the original arguments to the current command before any rewrite
 *	rules (from aliases, ensembles, and method forwards) were applied.
 *
 *----------------------------------------------------------------------
 */
Tcl_Obj *const *
TclEnsembleGetRewriteValues(
    Tcl_Interp *interp)		/* Current interpreter. */
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *const *origObjv = iPtr->ensembleRewrite.sourceObjs;

    if (origObjv[0] == NULL) {
	origObjv = (Tcl_Obj *const *) origObjv[2];
    }
    return origObjv;
}

/*
 *----------------------------------------------------------------------
 *
 * TclFetchEnsembleRoot --
 *
 *	Returns the root of ensemble rewriting, if any.
 *	If no root exists, returns objv instead.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *const *
TclFetchEnsembleRoot(
    Tcl_Interp *interp,
    Tcl_Obj *const *objv,
    int objc,
    int *objcPtr)
    Tcl_Size objc,
    Tcl_Size *objcPtr)
{
    Tcl_Obj *const *sourceObjs;
    Interp *iPtr = (Interp *) interp;

    if (iPtr->ensembleRewrite.sourceObjs) {
	*objcPtr = objc + iPtr->ensembleRewrite.numRemovedObjs
		- iPtr->ensembleRewrite.numInsertedObjs;
	if (iPtr->ensembleRewrite.sourceObjs[0] == NULL) {
	    sourceObjs = (Tcl_Obj *const *) iPtr->ensembleRewrite.sourceObjs[1];
	} else {
	return iPtr->ensembleRewrite.sourceObjs;
	    sourceObjs = iPtr->ensembleRewrite.sourceObjs;
	}
	return sourceObjs;
    }
    *objcPtr = objc;
    return objv;
}

/*
 * ----------------------------------------------------------------------
 *
 * EnsmebleUnknownCallback --
 * EnsembleUnknownCallback --
 *
 *	Helper for the ensemble engine that handles the procesing of unknown
 *	callbacks. See the user documentation of the ensemble unknown handler
 *	for details; this function is only ever called when such a function is
 *	defined, and is only ever called once per ensemble dispatch (i.e. if a
 *	reparse still fails, this isn't called again).
 *	Helper for the ensemble engine.  Calls the routine registered for
 *	"ensemble unknown" case.  See the user documentation of the
 *	ensemble unknown handler for details.  Only called when such a
 *	function is defined, and is only called once per ensemble dispatch.
 *	I.e. even if a reparse still fails, this isn't called again.
 *
 * Results:
 *	TCL_OK -	*prefixObjPtr contains the command words to dispatch
 *			to.
 *	TCL_CONTINUE -	Need to reparse (*prefixObjPtr is invalid).
 *	TCL_ERROR -	Something went wrong! Error message in interpreter.
 *	TCL_CONTINUE -	Need to reparse, i.e. *prefixObjPtr is invalid
 *	TCL_ERROR -	Something went wrong. Error message in interpreter.
 *
 * Side effects:
 *	Calls the Tcl interpreter, so arbitrary.
 *	Arbitrary, due to evaluation of script provided by client.
 *
 * ----------------------------------------------------------------------
 */

static inline int
EnsembleUnknownCallback(
    Tcl_Interp *interp,
    EnsembleConfig *ensemblePtr,
    int objc,
    Tcl_Obj *const objv[],
    Tcl_Obj **prefixObjPtr)
    EnsembleConfig *ensemblePtr,/* The ensemble structure. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[],	/* Actual arguments. */
    Tcl_Obj **prefixObjPtr)	/* Where to write the prefix suggested by the
				 * unknown callback. Must not be NULL. Only has
				 * a meaningful value on TCL_OK. */
{
    Tcl_Size paramc;
    int result;
    int paramc, i, result, prefixObjc;
    Tcl_Size i, prefixObjc;
    Tcl_Obj **paramv, *unknownCmd, *ensObj;

    /*
     * Create the unknown command callback to determine what to do.
     * Create the "unknown" command callback to determine what to do.
     */

    unknownCmd = Tcl_DuplicateObj(ensemblePtr->unknownHandler);
    TclNewObj(ensObj);
    Tcl_GetCommandFullName(interp, ensemblePtr->token, ensObj);
    Tcl_ListObjAppendElement(NULL, unknownCmd, ensObj);
    for (i=1 ; i<objc ; i++) {
    for (i = 1 ; i < objc ; i++) {
	Tcl_ListObjAppendElement(NULL, unknownCmd, objv[i]);
    }
    TclListObjGetElements(NULL, unknownCmd, &paramc, &paramv);
    Tcl_IncrRefCount(unknownCmd);

    /*
     * Now call the unknown handler. (We don't bother NRE-enabling this; deep
     * recursing through unknown handlers is horribly perverse.) Note that it
     * is always an error for an unknown handler to delete its ensemble; don't
     * Call the "unknown" handler.  No attempt to NRE-enable this as deep
     * recursion through unknown handlers is perverse. It is always an error
     * for an unknown handler to delete its ensemble. Don't do that.
     * do that!
     */

    Tcl_Preserve(ensemblePtr);
    TclSkipTailcall(interp);
    result = Tcl_EvalObjv(interp, paramc, paramv, 0);
    if ((result == TCL_OK) && (ensemblePtr->flags & ENSEMBLE_DEAD)) {
	if (!Tcl_InterpDeleted(interp)) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "unknown subcommand handler deleted its ensemble", -1));
		    "unknown subcommand handler deleted its ensemble",
		    TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "UNKNOWN_DELETED",
		    NULL);
		    (char *)NULL);
	}
	result = TCL_ERROR;
    }
    Tcl_Release(ensemblePtr);

    /*
     * If we succeeded, we should either have a list of words that form the
     * command to be executed, or an empty list. In the empty-list case, the
     * On success the result is a list of words that form the command to be
     * executed.  If the list is empty, the ensemble should have been updated,
     * ensemble is believed to be updated so we should ask the ensemble engine
     * to reparse the original command.
     * so ask the ensemble engine to reparse the original command.
     */

    if (result == TCL_OK) {
	*prefixObjPtr = Tcl_GetObjResult(interp);
	Tcl_IncrRefCount(*prefixObjPtr);
	TclDecrRefCount(unknownCmd);
	Tcl_ResetResult(interp);

	/*
	 * Namespace is still there. Check if the result is a valid list. If
	 * it is, and it is non-empty, that list is what we are using as our
	 * replacement.
	/* A non-empty list is the replacement command. */
	 */

	if (TclListObjLength(interp, *prefixObjPtr, &prefixObjc) != TCL_OK) {
	    TclDecrRefCount(*prefixObjPtr);
	    Tcl_AddErrorInfo(interp, "\n    while parsing result of "
		    "ensemble unknown subcommand handler");
	    return TCL_ERROR;
	}
	if (prefixObjc > 0) {
	    return TCL_OK;
	}

	/*
	 * Namespace alive & empty result => reparse.
	 * Empty result => reparse.
	 */

	TclDecrRefCount(*prefixObjPtr);
	return TCL_CONTINUE;
    }

    /*
     * Oh no! An exceptional result. Convert to an error.
     * Convert exceptional result to an error.
     */

    if (!Tcl_InterpDeleted(interp)) {
	if (result != TCL_ERROR) {
	    Tcl_ResetResult(interp);
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "unknown subcommand handler returned bad code: ", -1));
		    "unknown subcommand handler returned bad code: ",
		    TCL_AUTO_LENGTH));
	    switch (result) {
	    case TCL_RETURN:
		Tcl_AppendToObj(Tcl_GetObjResult(interp), "return", -1);
		Tcl_AppendToObj(Tcl_GetObjResult(interp), "return",
			TCL_AUTO_LENGTH);
		break;
	    case TCL_BREAK:
		Tcl_AppendToObj(Tcl_GetObjResult(interp), "break", -1);
		Tcl_AppendToObj(Tcl_GetObjResult(interp), "break",
			TCL_AUTO_LENGTH);
		break;
	    case TCL_CONTINUE:
		Tcl_AppendToObj(Tcl_GetObjResult(interp), "continue", -1);
		Tcl_AppendToObj(Tcl_GetObjResult(interp), "continue",
			TCL_AUTO_LENGTH);
		break;
	    default:
		Tcl_AppendPrintfToObj(Tcl_GetObjResult(interp), "%d", result);
	    }
	    Tcl_AddErrorInfo(interp, "\n    result of "
		    "ensemble unknown subcommand handler: ");
	    Tcl_AppendObjToErrorInfo(interp, unknownCmd);
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "UNKNOWN_RESULT",
		    NULL);
		    (char *)NULL);
	} else {
	    Tcl_AddErrorInfo(interp,
		    "\n    (ensemble unknown subcommand handler)");
	}
    }
    TclDecrRefCount(unknownCmd);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * MakeCachedEnsembleCommand --
 *
 *	Cache what we've computed so far; it's not nice to repeatedly copy
 *	strings about. Note that to do this, we start by deleting any old
 *	representation that there was (though if it was an out of date
 *	Caches what has been computed so far to minimize string copying.
 *	Starts by deleting any existing representation but reusing the existing
 *	structure if it is an ensembleCmd.
 *	ensemble rep, we can skip some of the deallocation process.)
 *
 * Results:
 *	None
 *	None.
 *
 * Side effects:
 *	Alters the internal representation of the first object parameter.
 *	Converts the internal representation of the given object to an
 *	ensembleCmd.
 *
 *----------------------------------------------------------------------
 */

static void
MakeCachedEnsembleCommand(
    Tcl_Obj *objPtr,
    EnsembleConfig *ensemblePtr,
    Tcl_HashEntry *hPtr,
    Tcl_Obj *fix)
    Tcl_Obj *objPtr,		/* Object to cache in. */
    EnsembleConfig *ensemblePtr,/* Ensemble implementation. */
    Tcl_HashEntry *hPtr,	/* What to cache; what the object maps to. */
    Tcl_Obj *fix)		/* Spelling correction for later error, or NULL
				 * if no correction. */
{
    EnsembleCmdRep *ensembleCmd;

    ECRGetIntRep(objPtr, ensembleCmd);
    ECRGetInternalRep(objPtr, ensembleCmd);
    if (ensembleCmd) {
	TclCleanupCommandMacro(ensembleCmd->token);
	if (ensembleCmd->fix) {
	    Tcl_DecrRefCount(ensembleCmd->fix);
	}
    } else {
	/*
	 * Kill the old internal rep, and replace it with a brand new one of
	 * Replace any old internal representation with a new one.
	 * our own.
	 */

	ensembleCmd = (EnsembleCmdRep *)Tcl_Alloc(sizeof(EnsembleCmdRep));
	ECRSetIntRep(objPtr, ensembleCmd);
	ensembleCmd = (EnsembleCmdRep *) Tcl_Alloc(sizeof(EnsembleCmdRep));
	ECRSetInternalRep(objPtr, ensembleCmd);
    }

    /*
     * Populate the internal rep.
     */

    ensembleCmd->epoch = ensemblePtr->epoch;
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447




2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2518
2519
2520
2521
2522
2523
2524




2525
2526
2527
2528

2529
2530
2531
2532
2533

2534
2535
2536
2537
2538
2539
2540

2541
2542
2543
2544
2545


2546
2547
2548






2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560

2561
2562

2563
2564
2565


2566


2567
2568
2569
2570
2571
2572
2573







-
-
-
-
+
+
+
+
-





-
+






-
+




-
-
+
+

-
-
-
-
-
-
+
+
+
+
+
+






-
+

-
+


-
-
+
-
-







}

/*
 *----------------------------------------------------------------------
 *
 * DeleteEnsembleConfig --
 *
 *	Destroys the data structure used to represent an ensemble. This is
 *	called when the ensemble's command is deleted (which happens
 *	automatically if the ensemble's namespace is deleted.) Maintainers
 *	should note that ensembles should be deleted by deleting their
 *	Destroys the data structure used to represent an ensemble.  Called when
 *	the procedure for the ensemble is deleted, which happens automatically
 *	if the namespace for the ensemble is deleted.  Deleting the procedure
 *	for an ensemble is the right way to initiate cleanup.
 *	commands.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Memory is (eventually) deallocated.
 *	Memory is eventually deallocated.
 *
 *----------------------------------------------------------------------
 */

static void
ClearTable(
    EnsembleConfig *ensemblePtr)
    EnsembleConfig *ensemblePtr)/* Ensemble to clear table of. */
{
    Tcl_HashTable *hash = &ensemblePtr->subcommandTable;

    if (hash->numEntries != 0) {
        Tcl_HashSearch search;
        Tcl_HashEntry *hPtr = Tcl_FirstHashEntry(hash, &search);
	Tcl_HashSearch search;
	Tcl_HashEntry *hPtr = Tcl_FirstHashEntry(hash, &search);

        while (hPtr != NULL) {
            Tcl_Obj *prefixObj = (Tcl_Obj *)Tcl_GetHashValue(hPtr);
            Tcl_DecrRefCount(prefixObj);
            hPtr = Tcl_NextHashEntry(&search);
        }
        Tcl_Free(ensemblePtr->subcommandArrayPtr);
	while (hPtr != NULL) {
	    Tcl_Obj *prefixObj = (Tcl_Obj *) Tcl_GetHashValue(hPtr);
	    Tcl_DecrRefCount(prefixObj);
	    hPtr = Tcl_NextHashEntry(&search);
	}
	Tcl_Free(ensemblePtr->subcommandArrayPtr);
    }
    Tcl_DeleteHashTable(hash);
}

static void
DeleteEnsembleConfig(
    ClientData clientData)
    void *clientData)		/* Ensemble to delete. */
{
    EnsembleConfig *ensemblePtr = (EnsembleConfig *)clientData;
    EnsembleConfig *ensemblePtr = (EnsembleConfig *) clientData;
    Namespace *nsPtr = ensemblePtr->nsPtr;

    /*
     * Unlink from the ensemble chain if it has not been marked as having been
    /* Unlink from the ensemble chain if it not already marked as unlinked. */
     * done already.
     */

    if (ensemblePtr->next != ensemblePtr) {
	EnsembleConfig *ensPtr = (EnsembleConfig *) nsPtr->ensembles;

	if (ensPtr == ensemblePtr) {
	    nsPtr->ensembles = (Tcl_Ensemble *) ensemblePtr->next;
	} else {
2508
2509
2510
2511
2512
2513
2514
2515

2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533

2534
2535
2536


2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551





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
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







-
+

















-
+
-
-
-
+
+










-
-
-
-
-
+
+
+
+
+







-
+






-
+

-
-
+
+
-
-
+










-
-
-
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+

-
+



-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
+
+
+
+
+


-
-
-
-
+
+
+
-
-
-
-
+
+
+

-
-
+
+
-




-
-
+
+



















-
+
















-
+

-
-
-
+
+
+

-
-
-
+
+
+


-
-
+
+


-
-
-
+
+
+







-
-
-
-
-
+
+
+
+
+






-
+
+




-
+
+













-
-
+
+













-
-
+
+







     * Mark the namespace as dead so code that uses Tcl_Preserve() can tell
     * whether disaster happened anyway.
     */

    ensemblePtr->flags |= ENSEMBLE_DEAD;

    /*
     * Kill the pointer-containing fields.
     * Release the fields that contain pointers.
     */

    ClearTable(ensemblePtr);
    if (ensemblePtr->subcmdList != NULL) {
	Tcl_DecrRefCount(ensemblePtr->subcmdList);
    }
    if (ensemblePtr->parameterList != NULL) {
	Tcl_DecrRefCount(ensemblePtr->parameterList);
    }
    if (ensemblePtr->subcommandDict != NULL) {
	Tcl_DecrRefCount(ensemblePtr->subcommandDict);
    }
    if (ensemblePtr->unknownHandler != NULL) {
	Tcl_DecrRefCount(ensemblePtr->unknownHandler);
    }

    /*
     * Arrange for the structure to be reclaimed. Note that this is complex
     * Arrange for the structure to be reclaimed. This is complex because it is
     * because we have to make sure that we can react sensibly when an
     * ensemble is deleted during the process of initialising the ensemble
     * (especially the unknown callback.)
     * necessary to react sensibly when an ensemble is deleted during its
     * initialisation, particularly in the case of an unknown callback.
     */

    Tcl_EventuallyFree(ensemblePtr, TCL_DYNAMIC);
}

/*
 *----------------------------------------------------------------------
 *
 * BuildEnsembleConfig --
 *
 *	Create the internal data structures that describe how an ensemble
 *	looks, being a hash mapping from the full command name to the Tcl list
 *	that describes the implementation prefix words, and a sorted array of
 *	all the full command names to allow for reasonably efficient
 *	unambiguous prefix handling.
 *	Creates the internal data structures that describe how an ensemble
 *	looks.  The structures are a hash map from the full command name to the
 *	Tcl list that describes the implementation prefix words, and a sorted
 *	array of all the full command names to allow for reasonably efficient
 *	handling of an unambiguous prefix.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Reallocates and rebuilds the hash table and array stored at the
 *	ensemblePtr argument. For large ensembles or large namespaces, this is
 *	a potentially expensive operation.
 *	may be an expensive operation.
 *
 *----------------------------------------------------------------------
 */

static void
BuildEnsembleConfig(
    EnsembleConfig *ensemblePtr)
    EnsembleConfig *ensemblePtr)/* Ensemble to set up. */
{
    Tcl_HashSearch search;	/* Used for scanning the set of commands in
				 * the namespace that backs up this
    Tcl_HashSearch search;	/* Used for scanning the commands in
				 * the namespace for this ensemble. */
				 * ensemble. */
    size_t i, j;
    Tcl_Size i, j;
    int isNew;
    Tcl_HashTable *hash = &ensemblePtr->subcommandTable;
    Tcl_HashEntry *hPtr;
    Tcl_Obj *mapDict = ensemblePtr->subcommandDict;
    Tcl_Obj *subList = ensemblePtr->subcmdList;

    ClearTable(ensemblePtr);
    Tcl_InitHashTable(hash, TCL_STRING_KEYS);

    if (subList) {
        int subc;
        Tcl_Obj **subv, *target, *cmdObj, *cmdPrefixObj;
        const char *name;
	Tcl_Size subc;
	Tcl_Obj **subv, *target, *cmdObj, *cmdPrefixObj;
	const char *name;

        /*
         * There is a list of exactly what subcommands go in the table.
         * Must determine the target for each.
         */
	/*
	 * There is a list of exactly what subcommands go in the table.
	 * Determine the target for each.
	 */

        Tcl_ListObjGetElements(NULL, subList, &subc, &subv);
        if (subList == mapDict) {
            /*
             * Strange case where explicit list of subcommands is same value
             * as the dict mapping to targets.
             */
	TclListObjGetElements(NULL, subList, &subc, &subv);
	if (subList == mapDict) {
	    /*
	     * Unusual case where explicit list of subcommands is same value
	     * as the dict mapping to targets.
	     */

            for (i = 0; i < (size_t)subc; i += 2) {
                name = TclGetString(subv[i]);
                hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
                if (!isNew) {
                    cmdObj = (Tcl_Obj *)Tcl_GetHashValue(hPtr);
                    Tcl_DecrRefCount(cmdObj);
                }
                Tcl_SetHashValue(hPtr, subv[i+1]);
                Tcl_IncrRefCount(subv[i+1]);
	    for (i = 0; i < subc; i += 2) {
		name = TclGetString(subv[i]);
		hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
		if (!isNew) {
		    cmdObj = (Tcl_Obj *) Tcl_GetHashValue(hPtr);
		    Tcl_DecrRefCount(cmdObj);
		}
		Tcl_SetHashValue(hPtr, subv[i + 1]);
		Tcl_IncrRefCount(subv[i + 1]);

                name = TclGetString(subv[i+1]);
                hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
                if (isNew) {
                    cmdObj = Tcl_NewStringObj(name, -1);
                    cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
                    Tcl_SetHashValue(hPtr, cmdPrefixObj);
                    Tcl_IncrRefCount(cmdPrefixObj);
                }
            }
        } else {
            /*
		name = TclGetString(subv[i + 1]);
		hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
		if (isNew) {
		    cmdObj = Tcl_NewStringObj(name, TCL_AUTO_LENGTH);
		    cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
		    Tcl_SetHashValue(hPtr, cmdPrefixObj);
		    Tcl_IncrRefCount(cmdPrefixObj);
		}
	    }
	} else {
	    /*
	     * Usual case where we can freely act on the list and dict.
	     */

            for (i = 0; i < (size_t)subc; i++) {
                name = TclGetString(subv[i]);
                hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
                if (!isNew) {
                    continue;
                }
	    for (i = 0; i < subc; i++) {
		name = TclGetString(subv[i]);
		hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
		if (!isNew) {
		    continue;
		}

                /*
		/*
		 * Lookup target in the dictionary.
		 */

                if (mapDict) {
                    Tcl_DictObjGet(NULL, mapDict, subv[i], &target);
                    if (target) {
                        Tcl_SetHashValue(hPtr, target);
                        Tcl_IncrRefCount(target);
                        continue;
                    }
                }
		if (mapDict) {
		    Tcl_DictObjGet(NULL, mapDict, subv[i], &target);
		    if (target) {
			Tcl_SetHashValue(hPtr, target);
			Tcl_IncrRefCount(target);
			continue;
		    }
		}

                /*
                 * target was not in the dictionary so map onto the namespace.
                 * Note in this case that we do not guarantee that the command
                 * is actually there; that is the programmer's responsibility
                 * (or [::unknown] of course).
                 */
		/*
		 * Target was not in the dictionary.  Map onto the namespace.
		 * In this case there is no guarantee that the command is
		 * actually there.  It is the responsibility of the programmer
		 * (or [::unknown] of course) to provide the procedure.
		 */

                cmdObj = Tcl_NewStringObj(name, -1);
                cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
                Tcl_SetHashValue(hPtr, cmdPrefixObj);
                Tcl_IncrRefCount(cmdPrefixObj);
            }
        }
		cmdObj = Tcl_NewStringObj(name, TCL_AUTO_LENGTH);
		cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
		Tcl_SetHashValue(hPtr, cmdPrefixObj);
		Tcl_IncrRefCount(cmdPrefixObj);
	    }
	}
    } else if (mapDict) {
        /*
         * No subcmd list, but we do have a mapping dictionary so we should
         * use the keys of that. Convert the dictionary's contents into the
         * form required for the ensemble's internal hashtable.
         */
	/*
	 * No subcmd list, but there is a mapping dictionary, so use
	 * the keys of that. Convert the contents of the dictionary into the
	 * form required for the internal hashtable of the ensemble.
	 */

        Tcl_DictSearch dictSearch;
        Tcl_Obj *keyObj, *valueObj;
        int done;
	Tcl_DictSearch dictSearch;
	Tcl_Obj *keyObj, *valueObj;
	int done;

        Tcl_DictObjFirst(NULL, ensemblePtr->subcommandDict, &dictSearch,
                &keyObj, &valueObj, &done);
        while (!done) {
            const char *name = TclGetString(keyObj);
	Tcl_DictObjFirst(NULL, ensemblePtr->subcommandDict, &dictSearch,
		&keyObj, &valueObj, &done);
	while (!done) {
	    const char *name = TclGetString(keyObj);

            hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
            Tcl_SetHashValue(hPtr, valueObj);
            Tcl_IncrRefCount(valueObj);
            Tcl_DictObjNext(&dictSearch, &keyObj, &valueObj, &done);
        }
	    hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
	    Tcl_SetHashValue(hPtr, valueObj);
	    Tcl_IncrRefCount(valueObj);
	    Tcl_DictObjNext(&dictSearch, &keyObj, &valueObj, &done);
	}
    } else {
	/*
	 * Discover what commands are actually exported by the namespace.
	 * What we have is an array of patterns and a hash table whose keys
	 * are the command names exported by the namespace (the contents do
	 * not matter here.) We must find out what commands are actually
	 * Use the array of patterns and the hash table whose keys are the
	 * commands exported by the namespace.  The corresponding values do not
	 * matter here.  Filter the commands in the namespace against the
	 * exported by filtering each command in the namespace against each of
	 * the patterns in the export list. Note that we use an intermediate
	 * hash table to make memory management easier, and because that makes
	 * exact matching far easier too.
	 * patterns in the export list to find out what commands are actually
	 * exported. Use an intermediate hash table to make memory management
	 * easier and to make exact matching much easier.
	 *
	 * Suggestion for future enhancement: compute the unique prefixes and
	 * place them in the hash too, which should make for even faster
	 * Suggestion for future enhancement: Compute the unique prefixes and
	 * place them in the hash too for even faster matching.
	 * matching.
	 */

	hPtr = Tcl_FirstHashEntry(&ensemblePtr->nsPtr->cmdTable, &search);
	for (; hPtr!= NULL ; hPtr=Tcl_NextHashEntry(&search)) {
	    char *nsCmdName =		/* Name of command in namespace. */
		    (char *)Tcl_GetHashKey(&ensemblePtr->nsPtr->cmdTable, hPtr);
	    char *nsCmdName = (char *)	/* Name of command in namespace. */
		    Tcl_GetHashKey(&ensemblePtr->nsPtr->cmdTable, hPtr);

	    for (i=0 ; i<ensemblePtr->nsPtr->numExportPatterns ; i++) {
		if (Tcl_StringMatch(nsCmdName,
			ensemblePtr->nsPtr->exportArrayPtr[i])) {
		    hPtr = Tcl_CreateHashEntry(hash, nsCmdName, &isNew);

		    /*
		     * Remember, hash entries have a full reference to the
		     * substituted part of the command (as a list) as their
		     * content!
		     */

		    if (isNew) {
			Tcl_Obj *cmdObj, *cmdPrefixObj;

			TclNewObj(cmdObj);
			Tcl_AppendStringsToObj(cmdObj,
				ensemblePtr->nsPtr->fullName,
				(ensemblePtr->nsPtr->parentPtr ? "::" : ""),
				nsCmdName, NULL);
				nsCmdName, (char *)NULL);
			cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
			Tcl_SetHashValue(hPtr, cmdPrefixObj);
			Tcl_IncrRefCount(cmdPrefixObj);
		    }
		    break;
		}
	    }
	}
    }

    if (hash->numEntries == 0) {
	ensemblePtr->subcommandArrayPtr = NULL;
	return;
    }

    /*
     * Create a sorted array of all subcommands in the ensemble; hash tables
     * Create a sorted array of all subcommands in the ensemble.  Hash tables
     * are all very well for a quick look for an exact match, but they can't
     * determine things like whether a string is a prefix of another (not
     * without lots of preparation anyway) and they're no good for when we're
     * generating the error message either.
     * determine things like whether a string is a prefix of another, at least
     * not without a lot of preparation, and they're not useful for generating
     * the error message either.
     *
     * We do this by filling an array with the names (we use the hash keys
     * directly to save a copy, since any time we change the array we change
     * the hash too, and vice versa) and running quicksort over the array.
     * Do this by filling an array with the names:  Use the hash keys
     * directly to save a copy since any time we change the array we change
     * the hash too, and vice versa, and run quicksort over the array.
     */

    ensemblePtr->subcommandArrayPtr =
	    (char **)Tcl_Alloc(sizeof(char *) * hash->numEntries);
    ensemblePtr->subcommandArrayPtr = (char **)
	    Tcl_Alloc(sizeof(char *) * hash->numEntries);

    /*
     * Fill array from both ends as this makes us less likely to end up with
     * performance problems in qsort(), which is good. Note that doing this
     * makes this code much more opaque, but the naive alternatve:
     * Fill the array from both ends as this reduces the likelihood of
     * performance problems in qsort(). This makes this code much more opaque,
     * but the naive alternatve:
     *
     * for (hPtr=Tcl_FirstHashEntry(hash,&search),i=0 ;
     *	       hPtr!=NULL ; hPtr=Tcl_NextHashEntry(&search),i++) {
     *     ensemblePtr->subcommandArrayPtr[i] = Tcl_GetHashKey(hash, &hPtr);
     * }
     *
     * can produce long runs of precisely ordered table entries when the
     * commands in the namespace are declared in a sorted fashion (an ordering
     * some people like) and the hashing functions (or the command names
     * themselves) are fairly unfortunate. By filling from both ends, it
     * requires active malice (and probably a debugger) to get qsort() to have
     * awful runtime behaviour.
     * commands in the namespace are declared in a sorted fashion,  which is an
     * ordering some people like, and the hashing functions or the command
     * names themselves are fairly unfortunate. Filling from both ends means
     * that it requires active malice, and probably a debugger, to get qsort()
     * to have awful runtime behaviour.
     */

    i = 0;
    j = hash->numEntries;
    hPtr = Tcl_FirstHashEntry(hash, &search);
    while (hPtr != NULL) {
	ensemblePtr->subcommandArrayPtr[i++] = (char *)Tcl_GetHashKey(hash, hPtr);
	ensemblePtr->subcommandArrayPtr[i++] = (char *)
		Tcl_GetHashKey(hash, hPtr);
	hPtr = Tcl_NextHashEntry(&search);
	if (hPtr == NULL) {
	    break;
	}
	ensemblePtr->subcommandArrayPtr[--j] = (char *)Tcl_GetHashKey(hash, hPtr);
	ensemblePtr->subcommandArrayPtr[--j] = (char *)
		Tcl_GetHashKey(hash, hPtr);
	hPtr = Tcl_NextHashEntry(&search);
    }
    if (hash->numEntries > 1) {
	qsort(ensemblePtr->subcommandArrayPtr, hash->numEntries,
		sizeof(char *), NsEnsembleStringOrder);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * NsEnsembleStringOrder --
 *
 *	Helper function to compare two pointers to two strings for use with
 *	qsort().
 *	Helper to for use with qsort() that compares two array entries that
 *	contain string pointers.
 *
 * Results:
 *	-1 if the first string is smaller, 1 if the second string is smaller,
 *	and 0 if they are equal.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
NsEnsembleStringOrder(
    const void *strPtr1,
    const void *strPtr2)
    const void *strPtr1,	/* Points to first array entry */
    const void *strPtr2)	/* Points to second array entry */
{
    return strcmp(*(const char **)strPtr1, *(const char **)strPtr2);
}

/*
 *----------------------------------------------------------------------
 *
2826
2827
2828
2829
2830
2831
2832
2833

2834
2835
2836
2837
2838
2839
2840
2900
2901
2902
2903
2904
2905
2906

2907
2908
2909
2910
2911
2912
2913
2914







-
+








static void
FreeEnsembleCmdRep(
    Tcl_Obj *objPtr)
{
    EnsembleCmdRep *ensembleCmd;

    ECRGetIntRep(objPtr, ensembleCmd);
    ECRGetInternalRep(objPtr, ensembleCmd);
    TclCleanupCommandMacro(ensembleCmd->token);
    if (ensembleCmd->fix) {
	Tcl_DecrRefCount(ensembleCmd->fix);
    }
    Tcl_Free(ensembleCmd);
}

2858
2859
2860
2861
2862
2863
2864
2865


2866
2867
2868


2869
2870
2871
2872
2873
2874
2875
2932
2933
2934
2935
2936
2937
2938

2939
2940
2941


2942
2943
2944
2945
2946
2947
2948
2949
2950







-
+
+

-
-
+
+








static void
DupEnsembleCmdRep(
    Tcl_Obj *objPtr,
    Tcl_Obj *copyPtr)
{
    EnsembleCmdRep *ensembleCmd;
    EnsembleCmdRep *ensembleCopy = (EnsembleCmdRep *)Tcl_Alloc(sizeof(EnsembleCmdRep));
    EnsembleCmdRep *ensembleCopy = (EnsembleCmdRep *)
	    Tcl_Alloc(sizeof(EnsembleCmdRep));

    ECRGetIntRep(objPtr, ensembleCmd);
    ECRSetIntRep(copyPtr, ensembleCopy);
    ECRGetInternalRep(objPtr, ensembleCmd);
    ECRSetInternalRep(copyPtr, ensembleCopy);

    ensembleCopy->epoch = ensembleCmd->epoch;
    ensembleCopy->token = ensembleCmd->token;
    ensembleCopy->token->refCount++;
    ensembleCopy->fix = ensembleCmd->fix;
    if (ensembleCopy->fix) {
	Tcl_IncrRefCount(ensembleCopy->fix);
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
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







-
+









-
+

-
+




-
-
+
+






-
+







 */

int
TclCompileEnsemble(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;
    Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr);
    Tcl_Obj *mapObj, *subcmdObj, *targetCmdObj, *listObj, **elems;
    Tcl_Obj *replaced, *replacement;
    Tcl_Command ensemble = (Tcl_Command) cmdPtr;
    Command *oldCmdPtr = cmdPtr, *newCmdPtr;
    int len, result, flags = 0, i, depth = 1, invokeAnyway = 0;
    int result, flags = 0, depth = 1, invokeAnyway = 0;
    int ourResult = TCL_ERROR;
    size_t numBytes;
    Tcl_Size i, len, numBytes;
    const char *word;

    TclNewObj(replaced);
    Tcl_IncrRefCount(replaced);
    if (parsePtr->numWords < depth + 1) {
	goto failed;
    if (parsePtr->numWords <= depth) {
	goto tryCompileToInv;
    }
    if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	/*
	 * Too hard.
	 */

	goto failed;
	goto tryCompileToInv;
    }

    /*
     * This is where we return to if we are parsing multiple nested compiled
     * ensembles. [info object] is such a beast.
     */

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
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







-
+













-
+

















-
+



-
-
+
+










-
+

















-
+





-
+



-
+







    if (Tcl_GetEnsembleMappingDict(NULL, ensemble, &mapObj) != TCL_OK
	    || mapObj == NULL) {
	/*
	 * Either not an ensemble or a mapping isn't installed. Crud. Too hard
	 * to proceed.
	 */

	goto failed;
	goto tryCompileToInv;
    }

    /*
     * Also refuse to compile anything that uses a formal parameter list for
     * now, on the grounds that it is too complex.
     */

    if (Tcl_GetEnsembleParameterList(NULL, ensemble, &listObj) != TCL_OK
	    || listObj != NULL) {
	/*
	 * Figuring out how to compile this has become too much. Bail out.
	 */

	goto failed;
	goto tryCompileToInv;
    }

    /*
     * Next, get the flags. We need them on several code paths so that we can
     * know whether we're to do prefix matching.
     */

    (void) Tcl_GetEnsembleFlags(NULL, ensemble, &flags);

    /*
     * Check to see if there's also a subcommand list; must check to see if
     * the subcommand we are calling is in that list if it exists, since that
     * list filters the entries in the map.
     */

    (void) Tcl_GetEnsembleSubcommandList(NULL, ensemble, &listObj);
    if (listObj != NULL) {
	size_t sclen;
	Tcl_Size sclen;
	const char *str;
	Tcl_Obj *matchObj = NULL;

	if (Tcl_ListObjGetElements(NULL, listObj, &len, &elems) != TCL_OK) {
	    goto failed;
	if (TclListObjGetElements(NULL, listObj, &len, &elems) != TCL_OK) {
	    goto tryCompileToInv;
	}
	for (i=0 ; i<len ; i++) {
	    str = TclGetStringFromObj(elems[i], &sclen);
	    if ((sclen == numBytes) && !memcmp(word, str, numBytes)) {
		/*
		 * Exact match! Excellent!
		 */

		result = Tcl_DictObjGet(NULL, mapObj,elems[i], &targetCmdObj);
		if (result != TCL_OK || targetCmdObj == NULL) {
		    goto failed;
		    goto tryCompileToInv;
		}
		replacement = elems[i];
		goto doneMapLookup;
	    }

	    /*
	     * Check to see if we've got a prefix match. A single prefix match
	     * is fine, and allows us to refine our dictionary lookup, but
	     * multiple prefix matches is a Bad Thing and will prevent us from
	     * making progress. Note that we cannot do the lookup immediately
	     * in the prefix case; might be another entry later in the list
	     * that causes things to fail.
	     */

	    if ((flags & TCL_ENSEMBLE_PREFIX)
		    && strncmp(word, str, numBytes) == 0) {
		if (matchObj != NULL) {
		    goto failed;
		    goto tryCompileToInv;
		}
		matchObj = elems[i];
	    }
	}
	if (matchObj == NULL) {
	    goto failed;
	    goto tryCompileToInv;
	}
	result = Tcl_DictObjGet(NULL, mapObj, matchObj, &targetCmdObj);
	if (result != TCL_OK || targetCmdObj == NULL) {
	    goto failed;
	    goto tryCompileToInv;
	}
	replacement = matchObj;
    } else {
	Tcl_DictSearch s;
	int done, matched;
	Tcl_Obj *tmpObj;

3055
3056
3057
3058
3059
3060
3061
3062

3063
3064
3065
3066
3067
3068
3069
3130
3131
3132
3133
3134
3135
3136

3137
3138
3139
3140
3141
3142
3143
3144







-
+








	/*
	 * We've not literally got a valid subcommand. But maybe we have a
	 * prefix. Check if prefix matches are allowed.
	 */

	if (!(flags & TCL_ENSEMBLE_PREFIX)) {
	    goto failed;
	    goto tryCompileToInv;
	}

	/*
	 * Iterate over the keys in the dictionary, checking to see if we're a
	 * prefix.
	 */

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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150

3151
3152
3153
3154
3155
3156
3157
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
3199
3200
3201
3202
3203

3204
3205
3206

3207
3208
3209
3210
3211

3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223

3224
3225
3226
3227
3228
3229
3230
3231







-
+














-
-
+
+















-
+


-
+




-












-
+







	/*
	 * If we have anything other than a single match, we've failed the
	 * unique prefix check.
	 */

	if (matched != 1) {
	    invokeAnyway = 1;
	    goto failed;
	    goto tryCompileToInv;
	}
    }

    /*
     * OK, we definitely map to something. But what?
     *
     * The command we map to is the first word out of the map element. Note
     * that we also reject dealing with multi-element rewrites if we are in a
     * safe interpreter, as there is otherwise a (highly gnarly!) way to make
     * Tcl crash open to exploit.
     */

  doneMapLookup:
    Tcl_ListObjAppendElement(NULL, replaced, replacement);
    if (Tcl_ListObjGetElements(NULL, targetCmdObj, &len, &elems) != TCL_OK) {
	goto failed;
    if (TclListObjGetElements(NULL, targetCmdObj, &len, &elems) != TCL_OK) {
	goto tryCompileToInv;
    } else if (len != 1) {
	/*
	 * Note that at this point we know we can't issue any special
	 * instruction sequence as the mapping isn't one that we support at
	 * the compiled level.
	 */

	goto cleanup;
    }
    targetCmdObj = elems[0];

    oldCmdPtr = cmdPtr;
    Tcl_IncrRefCount(targetCmdObj);
    newCmdPtr = (Command *) Tcl_GetCommandFromObj(interp, targetCmdObj);
    TclDecrRefCount(targetCmdObj);
    if (newCmdPtr == NULL || Tcl_IsSafe(interp)
    if (newCmdPtr == NULL || (Tcl_IsSafe(interp) && !cmdPtr->compileProc)
	    || newCmdPtr->nsPtr->flags & NS_SUPPRESS_COMPILATION
	    || newCmdPtr->flags & CMD_HAS_EXEC_TRACES
	    || ((Interp *)interp)->flags & DONT_COMPILE_CMDS_INLINE) {
	    || ((Interp *) interp)->flags & DONT_COMPILE_CMDS_INLINE) {
	/*
	 * Maps to an undefined command or a command without a compiler.
	 * Cannot compile.
	 */

	goto cleanup;
    }
    cmdPtr = newCmdPtr;
    depth++;

    /*
     * See whether we have a nested ensemble. If we do, we can go round the
     * mulberry bush again, consuming the next word.
     */

    if (cmdPtr->compileProc == TclCompileEnsemble) {
	tokenPtr = TokenAfter(tokenPtr);
	if (parsePtr->numWords < depth + 1
	if ((int)parsePtr->numWords < depth + 1
		|| tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	    /*
	     * Too hard because the user has done something unpleasant like
	     * omitting the sub-ensemble's command name or used a non-constant
	     * name for a sub-ensemble's command name; we respond by bailing
	     * out completely (this is a rare case). [Bug 6d2f249a01]
	     */
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186




3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201

3202
3203
3204
3205
3206
3207
3208
3250
3251
3252
3253
3254
3255
3256




3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274

3275
3276
3277
3278
3279
3280
3281
3282







-
-
-
-
+
+
+
+














-
+







	goto cleanup;
    }

    /*
     * Throw out any line information generated by the failed compile attempt.
     */

    while (mapPtr->nuloc - 1 > eclIndex) {
        mapPtr->nuloc--;
        Tcl_Free(mapPtr->loc[mapPtr->nuloc].line);
        mapPtr->loc[mapPtr->nuloc].line = NULL;
    while (mapPtr->nuloc > eclIndex + 1) {
	mapPtr->nuloc--;
	Tcl_Free(mapPtr->loc[mapPtr->nuloc].line);
	mapPtr->loc[mapPtr->nuloc].line = NULL;
    }

    /*
     * Reset the index of next command.  Toss out any from failed nested
     * partial compiles.
     */

    envPtr->numCommands = mapPtr->nuloc;

    /*
     * Failed to do a full compile for some reason. Try to do a direct invoke
     * instead of going through the ensemble lookup process again.
     */

  failed:
  tryCompileToInv:
    if (depth < 250) {
	if (depth > 1) {
	    if (!invokeAnyway) {
		cmdPtr = oldCmdPtr;
		depth--;
	    }
	}
3238
3239
3240
3241
3242
3243
3244
3245

3246
3247
3248
3249
3250


3251
3252
3253
3254
3255




3256
3257

3258
3259
3260
3261
3262
3263
3264
3312
3313
3314
3315
3316
3317
3318

3319
3320
3321
3322
3323

3324
3325
3326




3327
3328
3329
3330
3331

3332
3333
3334
3335
3336
3337
3338
3339







-
+




-
+
+

-
-
-
-
+
+
+
+

-
+







    return ourResult;
}

int
TclAttemptCompileProc(
    Tcl_Interp *interp,
    Tcl_Parse *parsePtr,
    int depth,
    Tcl_Size depth,
    Command *cmdPtr,
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;
    int result, i;
    int result;
    Tcl_Size i;
    Tcl_Token *saveTokenPtr = parsePtr->tokenPtr;
    int savedStackDepth = envPtr->currStackDepth;
    unsigned savedCodeNext = envPtr->codeNext - envPtr->codeStart;
    int savedAuxDataArrayNext = envPtr->auxDataArrayNext;
    int savedExceptArrayNext = envPtr->exceptArrayNext;
    Tcl_Size savedStackDepth = envPtr->currStackDepth;
    Tcl_Size savedCodeNext = envPtr->codeNext - envPtr->codeStart;
    Tcl_Size savedAuxDataArrayNext = envPtr->auxDataArrayNext;
    Tcl_Size savedExceptArrayNext = envPtr->exceptArrayNext;
#ifdef TCL_COMPILE_DEBUG
    int savedExceptDepth = envPtr->exceptDepth;
    Tcl_Size savedExceptDepth = envPtr->exceptDepth;
#endif

    if (cmdPtr->compileProc == NULL) {
	return TCL_ERROR;
    }

    /*
3310
3311
3312
3313
3314
3315
3316
3317

3318
3319
3320
3321
3322

3323
3324
3325
3326
3327
3328
3329
3385
3386
3387
3388
3389
3390
3391

3392
3393
3394
3395
3396

3397
3398
3399
3400
3401
3402
3403
3404







-
+




-
+







#endif

    if (result != TCL_OK) {
	ExceptionAux *auxPtr = envPtr->exceptAuxArrayPtr;

	for (i = 0; i < savedExceptArrayNext; i++) {
	    while (auxPtr->numBreakTargets > 0
		    && auxPtr->breakTargets[auxPtr->numBreakTargets - 1]
		    && (Tcl_Size) auxPtr->breakTargets[auxPtr->numBreakTargets - 1]
		    >= savedCodeNext) {
		auxPtr->numBreakTargets--;
	    }
	    while (auxPtr->numContinueTargets > 0
		    && auxPtr->continueTargets[auxPtr->numContinueTargets - 1]
		    && (Tcl_Size) auxPtr->continueTargets[auxPtr->numContinueTargets - 1]
		    >= savedCodeNext) {
		auxPtr->numContinueTargets--;
	    }
	    auxPtr++;
	}
	envPtr->exceptArrayNext = savedExceptArrayNext;

3379
3380
3381
3382
3383
3384
3385
3386
3387


3388
3389
3390
3391
3392
3393
3394
3395

3396
3397
3398
3399


3400
3401
3402
3403
3404
3405
3406
3454
3455
3456
3457
3458
3459
3460


3461
3462
3463
3464
3465
3466
3467
3468
3469

3470
3471
3472


3473
3474
3475
3476
3477
3478
3479
3480
3481







-
-
+
+







-
+


-
-
+
+







    Command *cmdPtr,
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;
    Tcl_Token *tokPtr;
    Tcl_Obj *objPtr, **words;
    const char *bytes;
    int i, numWords, cmdLit, extraLiteralFlags = LITERAL_CMD_NAME;
    size_t length;
    int cmdLit, extraLiteralFlags = LITERAL_CMD_NAME;
    Tcl_Size i, numWords, length;

    /*
     * Push the words of the command. Take care; the command words may be
     * scripts that have backslashes in them, and [info frame 0] can see the
     * difference. Hence the call to TclContinuationsEnterDerived...
     */

    Tcl_ListObjGetElements(NULL, replacements, &numWords, &words);
    TclListObjGetElements(NULL, replacements, &numWords, &words);
    for (i = 0, tokPtr = parsePtr->tokenPtr; i < parsePtr->numWords;
	    i++, tokPtr = TokenAfter(tokPtr)) {
	if (i > 0 && i < numWords+1) {
	    bytes = TclGetStringFromObj(words[i-1], &length);
	if (i > 0 && i <= numWords) {
	    bytes = TclGetStringFromObj(words[i - 1], &length);
	    PushLiteral(envPtr, bytes, length);
	    continue;
	}

	SetLineInformation(i);
	if (tokPtr->type == TCL_TOKEN_SIMPLE_WORD) {
	    int literal = TclRegisterLiteral(envPtr,
3434
3435
3436
3437
3438
3439
3440
3441


3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461

3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481

3482
3483
3484
3485
3486
3487
3488
3509
3510
3511
3512
3513
3514
3515

3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536

3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556

3557
3558
3559
3560
3561
3562
3563
3564







-
+
+



















-
+



















-
+







    TclEmitPush(cmdLit, envPtr);
    TclDecrRefCount(objPtr);

    /*
     * Do the replacing dispatch.
     */

    TclEmitInvoke(envPtr, INST_INVOKE_REPLACE, parsePtr->numWords,numWords+1);
    TclEmitInvoke(envPtr, INST_INVOKE_REPLACE, parsePtr->numWords,
	    numWords + 1);
}

/*
 * Helpers that do issuing of instructions for commands that "don't have
 * compilers" (well, they do; these). They all work by just generating base
 * code to invoke the command; they're intended for ensemble subcommands so
 * that the costs of INST_INVOKE_REPLACE can be avoided where we can work out
 * that they're not needed.
 *
 * Note that these are NOT suitable for commands where there's an argument
 * that is a script, as an [info level] or [info frame] in the inner context
 * can see the difference.
 */

static int
CompileBasicNArgCommand(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    Tcl_Obj *objPtr;

    TclNewObj(objPtr);
    Tcl_IncrRefCount(objPtr);
    Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, objPtr);
    TclCompileInvocation(interp, parsePtr->tokenPtr, objPtr,
	    parsePtr->numWords, envPtr);
    Tcl_DecrRefCount(objPtr);
    return TCL_OK;
}

int
TclCompileBasic0ArgCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    /*
     * Verify that the number of arguments is correct; that's the only case
     * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
     * which is the only code that sees the shenanigans of ensemble dispatch.
3496
3497
3498
3499
3500
3501
3502
3503

3504
3505
3506
3507
3508
3509
3510
3572
3573
3574
3575
3576
3577
3578

3579
3580
3581
3582
3583
3584
3585
3586







-
+







}

int
TclCompileBasic1ArgCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    /*
     * Verify that the number of arguments is correct; that's the only case
     * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
     * which is the only code that sees the shenanigans of ensemble dispatch.
3518
3519
3520
3521
3522
3523
3524
3525

3526
3527
3528
3529
3530
3531
3532
3594
3595
3596
3597
3598
3599
3600

3601
3602
3603
3604
3605
3606
3607
3608







-
+







}

int
TclCompileBasic2ArgCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    /*
     * Verify that the number of arguments is correct; that's the only case
     * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
     * which is the only code that sees the shenanigans of ensemble dispatch.
3540
3541
3542
3543
3544
3545
3546
3547

3548
3549
3550
3551
3552
3553
3554
3616
3617
3618
3619
3620
3621
3622

3623
3624
3625
3626
3627
3628
3629
3630







-
+







}

int
TclCompileBasic3ArgCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    /*
     * Verify that the number of arguments is correct; that's the only case
     * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
     * which is the only code that sees the shenanigans of ensemble dispatch.
3562
3563
3564
3565
3566
3567
3568
3569

3570
3571
3572
3573
3574
3575
3576
3638
3639
3640
3641
3642
3643
3644

3645
3646
3647
3648
3649
3650
3651
3652







-
+







}

int
TclCompileBasic0Or1ArgCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    /*
     * Verify that the number of arguments is correct; that's the only case
     * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
     * which is the only code that sees the shenanigans of ensemble dispatch.
3584
3585
3586
3587
3588
3589
3590
3591

3592
3593
3594
3595
3596
3597
3598
3660
3661
3662
3663
3664
3665
3666

3667
3668
3669
3670
3671
3672
3673
3674







-
+







}

int
TclCompileBasic1Or2ArgCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    /*
     * Verify that the number of arguments is correct; that's the only case
     * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
     * which is the only code that sees the shenanigans of ensemble dispatch.
3606
3607
3608
3609
3610
3611
3612
3613

3614
3615
3616
3617
3618
3619
3620
3682
3683
3684
3685
3686
3687
3688

3689
3690
3691
3692
3693
3694
3695
3696







-
+







}

int
TclCompileBasic2Or3ArgCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    /*
     * Verify that the number of arguments is correct; that's the only case
     * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
     * which is the only code that sees the shenanigans of ensemble dispatch.
3628
3629
3630
3631
3632
3633
3634
3635

3636
3637
3638
3639
3640
3641
3642
3704
3705
3706
3707
3708
3709
3710

3711
3712
3713
3714
3715
3716
3717
3718







-
+







}

int
TclCompileBasic0To2ArgCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    /*
     * Verify that the number of arguments is correct; that's the only case
     * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
     * which is the only code that sees the shenanigans of ensemble dispatch.
3650
3651
3652
3653
3654
3655
3656
3657

3658
3659
3660
3661
3662
3663
3664
3726
3727
3728
3729
3730
3731
3732

3733
3734
3735
3736
3737
3738
3739
3740







-
+







}

int
TclCompileBasic1To3ArgCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    /*
     * Verify that the number of arguments is correct; that's the only case
     * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
     * which is the only code that sees the shenanigans of ensemble dispatch.
3672
3673
3674
3675
3676
3677
3678
3679

3680
3681
3682
3683
3684
3685
3686
3687
3688
3689

3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701

3702
3703
3704
3705
3706
3707
3708
3709
3710
3711

3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723

3724
3725
3726
3727
3728
3729
3730
3731
3732
3733

3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3748
3749
3750
3751
3752
3753
3754

3755
3756
3757
3758
3759
3760
3761
3762
3763
3764

3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776

3777
3778
3779
3780
3781
3782
3783
3784
3785
3786

3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798

3799
3800
3801
3802
3803
3804
3805
3806
3807
3808

3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822







-
+









-
+











-
+









-
+











-
+









-
+













}

int
TclCompileBasicMin0ArgCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    /*
     * Verify that the number of arguments is correct; that's the only case
     * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
     * which is the only code that sees the shenanigans of ensemble dispatch.
     */

    if (parsePtr->numWords < 1) {
    if ((int)parsePtr->numWords < 1) {
	return TCL_ERROR;
    }

    return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr);
}

int
TclCompileBasicMin1ArgCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    /*
     * Verify that the number of arguments is correct; that's the only case
     * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
     * which is the only code that sees the shenanigans of ensemble dispatch.
     */

    if (parsePtr->numWords < 2) {
    if ((int)parsePtr->numWords < 2) {
	return TCL_ERROR;
    }

    return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr);
}

int
TclCompileBasicMin2ArgCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
    Command *cmdPtr,		/* Points to definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    /*
     * Verify that the number of arguments is correct; that's the only case
     * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time,
     * which is the only code that sees the shenanigans of ensemble dispatch.
     */

    if (parsePtr->numWords < 3) {
    if ((int)parsePtr->numWords < 3) {
	return TCL_ERROR;
    }

    return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclEnv.c.

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
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
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
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








-
-
+
+











-
-
-
-
+
+
+
+






-
-
-
-
+
+
+
+



+
+
+
+

-
+







-
+













-
+







/*
 * tclEnv.c --
 *
 *	Tcl support for environment variables, including a setenv function.
 *	This file contains the generic portion of the environment module. It
 *	is primarily responsible for keeping the "env" arrays in sync with the
 *	system environment variables.
 *
 * Copyright (c) 1991-1994 The Regents of the University of California.
 * Copyright (c) 1994-1998 Sun Microsystems, Inc.
 * Copyright © 1991-1994 The Regents of the University of California.
 * Copyright © 1994-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

TCL_DECLARE_MUTEX(envMutex)	/* To serialize access to environ. */

#if defined(_WIN32)
#  define tenviron _wenviron
#  define tenviron2utfdstr(string, len, dsPtr) (Tcl_DStringInit(dsPtr), \
		(char *)Tcl_Char16ToUtfDString((const unsigned short *)(string), ((((len) + 2) >> 1) - 1), (dsPtr)))
#  define utf2tenvirondstr(string, len, dsPtr) (Tcl_DStringInit(dsPtr), \
		(const WCHAR *)Tcl_UtfToChar16DString((string), (len), (dsPtr)))
#  define tenviron2utfdstr(str, dsPtr) (Tcl_DStringInit(dsPtr), \
	(char *)Tcl_Char16ToUtfDString((const unsigned short *)(str), -1, (dsPtr)))
#  define utf2tenvirondstr(str, dsPtr) (Tcl_DStringInit(dsPtr), \
	(const WCHAR *)Tcl_UtfToChar16DString((str), -1, (dsPtr)))
#  define techar WCHAR
#  ifdef USE_PUTENV
#    define putenv(env) _wputenv((const wchar_t *)env)
#  endif
#else
#  define tenviron environ
#  define tenviron2utfdstr(tenvstr, len, dstr) \
		Tcl_ExternalToUtfDString(NULL, tenvstr, len, dstr)
#  define utf2tenvirondstr(str, len, dstr) \
		Tcl_UtfToExternalDString(NULL, str, len, dstr)
#  define tenviron2utfdstr(str, dsPtr) \
	Tcl_ExternalToUtfDString(NULL, str, -1, dsPtr)
#  define utf2tenvirondstr(str, dsPtr) \
	Tcl_UtfToExternalDString(NULL, str, -1, dsPtr)
#  define techar char
#endif

/* MODULE_SCOPE */
size_t TclEnvEpoch = 0;	/* Epoch of the tcl environment
				 * (if changed with tcl-env). */

static struct {
    size_t cacheSize;		/* Number of env strings in cache. */
    Tcl_Size cacheSize;		/* Number of env strings in cache. */
    char **cache;		/* Array containing all of the environment
				 * strings that Tcl has allocated. */
#ifndef USE_PUTENV
    techar **ourEnviron;		/* Cache of the array that we allocate. We
				 * need to track this in case another
				 * subsystem swaps around the environ array
				 * like we do. */
    size_t ourEnvironSize;		/* Non-zero means that the environ array was
    Tcl_Size ourEnvironSize;	/* Non-zero means that the environ array was
				 * malloced and has this many total entries
				 * allocated to it (not all may be in use at
				 * once). Zero means that the environment
				 * array is in its original static state. */
#endif
} env;

#define tNTL sizeof(techar)

/*
 * Declarations for local functions defined in this file:
 */

static char *		EnvTraceProc(ClientData clientData, Tcl_Interp *interp,
static char *		EnvTraceProc(void *clientData, Tcl_Interp *interp,
			    const char *name1, const char *name2, int flags);
static void		ReplaceString(const char *oldStr, char *newStr);
MODULE_SCOPE void	TclSetEnv(const char *name, const char *value);
MODULE_SCOPE void	TclUnsetEnv(const char *name);

/*
 *----------------------------------------------------------------------
150
151
152
153
154
155
156
157





158
159
160
161
162
163
164
154
155
156
157
158
159
160

161
162
163
164
165
166
167
168
169
170
171
172







-
+
+
+
+
+








	Tcl_MutexLock(&envMutex);
	for (i = 0; tenviron[i] != NULL; i++) {
	    Tcl_Obj *obj1, *obj2;
	    const char *p1;
	    char *p2;

	    p1 = tenviron2utfdstr(tenviron[i], -1, &envString);
	    p1 = tenviron2utfdstr(tenviron[i], &envString);
	    if (p1 == NULL) {
		/* Ignore what cannot be decoded (should not happen) */
		continue;
	    }
	    p2 = (char *)strchr(p1, '=');
	    if (p2 == NULL) {
		/*
		 * This condition seem to happen occasionally under some
		 * versions of Solaris, or when encoding accidents swallow the
		 * '='; ignore the entry.
		 */
244
245
246
247
248
249
250
251
252


253
254
255
256
257
258
259
252
253
254
255
256
257
258


259
260
261
262
263
264
265
266
267







-
-
+
+







void
TclSetEnv(
    const char *name,		/* Name of variable whose value is to be set
				 * (UTF-8). */
    const char *value)		/* New value for variable (UTF-8). */
{
    Tcl_DString envString;
    size_t nameLength, valueLength;
    size_t index, length;
    Tcl_Size nameLength, valueLength;
    Tcl_Size index, length;
    char *p, *oldValue;
    const techar *p2;

    /*
     * Figure out where the entry is going to go. If the name doesn't already
     * exist, enlarge the array if necessary to make room. If the name exists,
     * free its old entry.
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
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







-
-
-
+
+
+




















-
+
+
+
+
+
+
+







	 * Compare the new value to the existing value. If they're the same
	 * then quit immediately (e.g. don't rewrite the value or propagate it
	 * to other interpreters). Otherwise, when there are N interpreters
	 * there will be N! propagations of the same value among the
	 * interpreters.
	 */

	oldEnv = tenviron2utfdstr(tenviron[index], -1, &envString);
	if (strcmp(value, oldEnv + (length + 1)) == 0) {
	    Tcl_DStringFree(&envString);
	oldEnv = tenviron2utfdstr(tenviron[index], &envString);
	if (oldEnv == NULL || strcmp(value, oldEnv + (length + 1)) == 0) {
	    Tcl_DStringFree(&envString); /* OK even if oldEnv is NULL */
	    Tcl_MutexUnlock(&envMutex);
	    return;
	}
	Tcl_DStringFree(&envString);

	oldValue = (char *)tenviron[index];
	nameLength = length;
    }

    /*
     * Create a new entry. Build a complete UTF string that contains a
     * "name=value" pattern. Then convert the string to the native encoding,
     * and set the environ array value.
     */

    valueLength = strlen(value);
    p = (char *)Tcl_Alloc(nameLength + valueLength + 2);
    memcpy(p, name, nameLength);
    p[nameLength] = '=';
    memcpy(p+nameLength+1, value, valueLength+1);
    p2 = utf2tenvirondstr(p, -1, &envString);
    p2 = utf2tenvirondstr(p, &envString);
    if (p2 == NULL) {
	/* No way to signal error from here :-( but should not happen */
	Tcl_Free(p);
	Tcl_MutexUnlock(&envMutex);
	return;
    }

    /*
     * Copy the native string to heap memory.
     */

    p = (char *)Tcl_Realloc(p, Tcl_DStringLength(&envString) + tNTL);
    memcpy(p, p2, Tcl_DStringLength(&envString) + tNTL);
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
369
370
371
372
373
374
375









376
377
378
379
380
381
382







-
-
-
-
-
-
-
-
-







	 */

	Tcl_Free(p);
#endif /* HAVE_PUTENV_THAT_COPIES */
    }

    Tcl_MutexUnlock(&envMutex);

    if (!strcmp(name, "HOME")) {
	/*
	 * If the user's home directory has changed, we must invalidate the
	 * filesystem cache, because '~' expansions will now be incorrect.
	 */

	Tcl_FSMountsChanged(NULL);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_PutEnv --
 *
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
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







-
+



-
+




+
+
+
+
+
+
+
+
+
+


+







    char *value;

    if (assignment == NULL) {
	return 0;
    }

    /*
     * First convert the native string to UTF. Then separate the string into
     * First convert the native string to Utf. Then separate the string into
     * name and value parts, and call TclSetEnv to do all of the real work.
     */

    name = Tcl_ExternalToUtfDString(NULL, assignment, -1, &nameString);
    name = Tcl_ExternalToUtfDString(NULL, assignment, TCL_INDEX_NONE, &nameString);
    value = (char *)strchr(name, '=');

    if ((value != NULL) && (value != name)) {
	value[0] = '\0';
#if defined(_WIN32)
	if (tenviron == NULL) {
	    /*
	     * When we are started from main(), the _wenviron array could
	     * be NULL and will be initialized by the first _wgetenv() call.
	     */

	(void) _wgetenv(L"WINDIR");
	}
#endif
	TclSetEnv(name, value+1);
    }
    TclEnvEpoch++;

    Tcl_DStringFree(&nameString);
    return 0;
}

/*
 *----------------------------------------------------------------------
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
467
468
469
470
471
472
458
459
460
461
462
463
464

465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480

481
482
483
484
485
486
487
488







-
+















-
+







 */

void
TclUnsetEnv(
    const char *name)		/* Name of variable to remove (UTF-8). */
{
    char *oldValue;
    size_t length, index;
    Tcl_Size length, index;
#ifdef USE_PUTENV_FOR_UNSET
    Tcl_DString envString;
    char *string;
#else
    char **envPtr;
#endif /* USE_PUTENV_FOR_UNSET */

    Tcl_MutexLock(&envMutex);
    index = TclpFindVariable(name, &length);

    /*
     * First make sure that the environment variable exists to avoid doing
     * needless work and to avoid recursion on the unset.
     */

    if (index == TCL_INDEX_NONE) {
    if (index == -1) {
	Tcl_MutexUnlock(&envMutex);
	return;
    }

    /*
     * Remember the old value so we can free it if Tcl created the string.
     */
491
492
493
494
495
496
497
498





499
500
501
502
503
504
505
507
508
509
510
511
512
513

514
515
516
517
518
519
520
521
522
523
524
525







-
+
+
+
+
+







    string[length+1] = '\0';
#else
    string = (char *)Tcl_Alloc(length + 1);
    memcpy(string, name, length);
    string[length] = '\0';
#endif /* _WIN32 */

    utf2tenvirondstr(string, -1, &envString);
    if (utf2tenvirondstr(string, &envString) == NULL) {
	/* Should not happen except memory alloc fail. */
	Tcl_MutexUnlock(&envMutex);
	return;
    }
    string = (char *)Tcl_Realloc(string, Tcl_DStringLength(&envString) + tNTL);
    memcpy(string, Tcl_DStringValue(&envString),
	    Tcl_DStringLength(&envString) + tNTL);
    Tcl_DStringFree(&envString);

    putenv(string);

557
558
559
560
561
562
563
564

565
566
567
568
569
570

571
572
573
574
575
576
577
578
579
580
581
582
583













584
585
586
587
588
589
590
577
578
579
580
581
582
583

584
585
586
587
588
589

590
591
592











593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612







-
+





-
+


-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+







TclGetEnv(
    const char *name,		/* Name of environment variable to find
				 * (UTF-8). */
    Tcl_DString *valuePtr)	/* Uninitialized or free DString in which the
				 * value of the environment variable is
				 * stored. */
{
    size_t length, index;
    Tcl_Size length, index;
    const char *result;

    Tcl_MutexLock(&envMutex);
    index = TclpFindVariable(name, &length);
    result = NULL;
    if (index != TCL_INDEX_NONE) {
    if (index != -1) {
	Tcl_DString envStr;

	result = tenviron2utfdstr(tenviron[index], -1, &envStr);
	result += length;
	if (*result == '=') {
	    result++;
	    Tcl_DStringInit(valuePtr);
	    Tcl_DStringAppend(valuePtr, result, -1);
	    result = Tcl_DStringValue(valuePtr);
	} else {
	    result = NULL;
	}
	Tcl_DStringFree(&envStr);
	result = tenviron2utfdstr(tenviron[index], &envStr);
	if (result) {
	    result += length;
	    if (*result == '=') {
		result++;
		Tcl_DStringInit(valuePtr);
		Tcl_DStringAppend(valuePtr, result, -1);
		result = Tcl_DStringValue(valuePtr);
	    } else {
		result = NULL;
	    }
	    Tcl_DStringFree(&envStr);
	}
    }
    Tcl_MutexUnlock(&envMutex);
    return result;
}

/*
 *----------------------------------------------------------------------
605
606
607
608
609
610
611
612

613
614
615
616
617
618
619
620
621
622
623
624
625

626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642

643
644










645

646
647
648
649
650
651
652
627
628
629
630
631
632
633

634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687







-
+













+

















+


+
+
+
+
+
+
+
+
+
+

+







 *	this happens because the whole interpreter is being deleted).
 *
 *----------------------------------------------------------------------
 */

static char *
EnvTraceProc(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Interpreter whose "env" variable is being
				 * modified. */
    const char *name1,		/* Better be "env". */
    const char *name2,		/* Name of variable being modified, or NULL if
				 * whole array is being deleted (UTF-8). */
    int flags)			/* Indicates what's happening. */
{
    /*
     * For array traces, let TclSetupEnv do all the work.
     */

    if (flags & TCL_TRACE_ARRAY) {
	TclSetupEnv(interp);
	TclEnvEpoch++;
	return NULL;
    }

    /*
     * If name2 is NULL, then return and do nothing.
     */

    if (name2 == NULL) {
	return NULL;
    }

    /*
     * If a value is being set, call TclSetEnv to do all of the work.
     */

    if (flags & TCL_TRACE_WRITES) {
	const char *value;
	Tcl_DString ds;

	value = Tcl_GetVar2(interp, "env", name2, TCL_GLOBAL_ONLY);
	Tcl_DStringInit(&ds);
	if (Tcl_UtfToExternalDStringEx(NULL, TCLFSENCODING, name2, -1, 0, &ds, NULL) != TCL_OK) {
	    Tcl_DStringFree(&ds);
	    return (char *) "encoding error";
	}
	if (Tcl_UtfToExternalDStringEx(NULL, TCLFSENCODING, value, -1, 0, &ds, NULL) != TCL_OK) {
	    Tcl_DStringFree(&ds);
	    return (char *) "encoding error";
	}
	Tcl_DStringFree(&ds);
	TclSetEnv(name2, value);
	TclEnvEpoch++;
    }

    /*
     * If a value is being read, call TclGetEnv to do all of the work.
     */

    if (flags & TCL_TRACE_READS) {
662
663
664
665
666
667
668

669
670
671
672
673
674
675
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711







+








    /*
     * For unset traces, let TclUnsetEnv do all the work.
     */

    if (flags & TCL_TRACE_UNSETS) {
	TclUnsetEnv(name2);
	TclEnvEpoch++;
    }
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
689
690
691
692
693
694
695
696

697
698
699
700
701
702
703
725
726
727
728
729
730
731

732
733
734
735
736
737
738
739







-
+







 */

static void
ReplaceString(
    const char *oldStr,		/* Old environment string. */
    char *newStr)		/* New environment string. */
{
    size_t i;
    Tcl_Size i;

    /*
     * Check to see if the old value was allocated by Tcl. If so, it needs to
     * be deallocated to avoid memory leaks. Note that this algorithm is O(n),
     * not O(1). This will result in n-squared behavior if lots of environment
     * changes are being made.
     */
768
769
770
771
772
773
774
775

776
777
778
779
780
781
782
804
805
806
807
808
809
810

811
812
813
814
815
816
817
818







-
+







     * determining which ones are ok to delete is n-squared, and is pretty
     * unlikely, so we don't bother.  However, in the case of DPURIFY, just
     * free all strings in the cache.
     */

    if (env.cache) {
#ifdef PURIFY
	size_t i;
	Tcl_Size i;
	for (i = 0; i < env.cacheSize; i++) {
	    Tcl_Free(env.cache[i]);
	}
#endif
	Tcl_Free(env.cache);
	env.cache = NULL;
	env.cacheSize = 0;

Changes to generic/tclEvent.c.

1
2
3
4
5
6
7
8
9
10



11
12
13
14
15
16




17
18
19
20
21
22
23
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







-
-
-
+
+
+






+
+
+
+







/*
 * tclEvent.c --
 *
 *	This file implements some general event related interfaces including
 *	background errors, exit handlers, and the "vwait" and "update" command
 *	functions.
 *
 * Copyright (c) 1990-1994 The Regents of the University of California.
 * Copyright (c) 1994-1998 Sun Microsystems, Inc.
 * Copyright (c) 2004 by Zoran Vasiljevic.
 * Copyright © 1990-1994 The Regents of the University of California.
 * Copyright © 1994-1998 Sun Microsystems, Inc.
 * Copyright © 2004 Zoran Vasiljevic.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclUuid.h"
#ifdef TCL_WITH_INTERNAL_ZLIB
#include "zlib.h"
#endif /* TCL_WITH_INTERNAL_ZLIB */

/*
 * The data structure below is used to report background errors. One such
 * structure is allocated for each error; it holds information about the
 * interpreter and the error until an idle handler command can be invoked.
 */

44
45
46
47
48
49
50













51
52
53
54
55
56
57
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







+
+
+
+
+
+
+
+
+
+
+
+
+







				 * waiting to be processed for this
				 * interpreter (NULL if none). */
    BgError *lastBgPtr;		/* Last in list of all background errors
				 * waiting to be processed for this
				 * interpreter (NULL if none). */
} ErrAssocData;

/*
 * For each "vwait" event source a structure of the following type
 * is used:
 */

typedef struct {
    int *donePtr;		/* Pointer to flag to signal or NULL. */
    int sequence;		/* Order of occurrence. */
    int mask;			/* 0, or TCL_READABLE/TCL_WRITABLE. */
    Tcl_Obj *sourceObj;		/* Name of the event source, either a
				 * variable name or channel name. */
} VwaitItem;

/*
 * For each exit handler created with a call to Tcl_Create(Late)ExitHandler
 * there is a structure of the following type:
 */

typedef struct ExitHandler {
    Tcl_ExitProc *proc;		/* Function to call when process exits. */
79
80
81
82
83
84
85


86
87
88
89
90
91
92

93
94
95
96
97
98
99
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

111
112
113
114
115
116
117
118







+
+






-
+







 * in closing of files and pipes.
 */

static int inExit = 0;

static int subsystemsInitialized = 0;

static const char ENCODING_ERROR[] = "\n\t(encoding error in stderr)";

/*
 * This variable contains the application wide exit handler. It will be called
 * by Tcl_Exit instead of the C-runtime exit if this variable is set to a
 * non-NULL value.
 */

static TCL_NORETURN1 Tcl_ExitProc *appExitPtr = NULL;
static Tcl_ExitProc *appExitPtr = NULL;

typedef struct ThreadSpecificData {
    ExitHandler *firstExitPtr;	/* First in list of all exit handlers for this
				 * thread. */
    int inExit;			/* True when this thread is exiting. This is
				 * used as a hack to decide to close the
				 * standard channels. */
111
112
113
114
115
116
117



118
119
120
121
122
123
124
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146







+
+
+







/*
 * Prototypes for functions referenced only in this file:
 */

static void		BgErrorDeleteProc(void *clientData,
			    Tcl_Interp *interp);
static void		HandleBgErrors(void *clientData);
static void		VwaitChannelReadProc(void *clientData, int mask);
static void		VwaitChannelWriteProc(void *clientData, int mask);
static void		VwaitTimeoutProc(void *clientData);
static char *		VwaitVarProc(void *clientData,
			    Tcl_Interp *interp, const char *name1,
			    const char *name2, int flags);
static void		InvokeExitHandlers(void);
static void		FinalizeThread(int quick);

/*
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
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







-
+
+











-
+







     * Tcl_SaveInterpState call before calling something like Tcl_DoOneEvent()
     * that could lead us here.
     */

    Tcl_Preserve(assocPtr);
    Tcl_Preserve(interp);
    while (assocPtr->firstBgPtr != NULL) {
	int code, prefixObjc;
	int code;
	Tcl_Size prefixObjc;
	Tcl_Obj **prefixObjv, **tempObjv;

	/*
	 * Note we copy the handler command prefix each pass through, so we do
	 * support one handler setting another handler.
	 */

	Tcl_Obj *copyObj = TclListObjCopy(NULL, assocPtr->cmdPrefix);

	errPtr = assocPtr->firstBgPtr;

	Tcl_ListObjGetElements(NULL, copyObj, &prefixObjc, &prefixObjv);
	TclListObjGetElements(NULL, copyObj, &prefixObjc, &prefixObjv);
	tempObjv = (Tcl_Obj**)Tcl_Alloc((prefixObjc+2) * sizeof(Tcl_Obj *));
	memcpy(tempObjv, prefixObjv, prefixObjc*sizeof(Tcl_Obj *));
	tempObjv[prefixObjc] = errPtr->errorMsg;
	tempObjv[prefixObjc+1] = errPtr->returnOpts;
	Tcl_AllowExceptions(interp);
	code = Tcl_EvalObjv(interp, prefixObjc+2, tempObjv, TCL_EVAL_GLOBAL);

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
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







-
+

-
-
-
+
-
-



-
+
+
+

-
+
+
+







		Tcl_Free(errPtr);
	    }
	} else if ((code == TCL_ERROR) && !Tcl_IsSafe(interp)) {
	    Tcl_Channel errChannel = Tcl_GetStdChannel(TCL_STDERR);

	    if (errChannel != NULL) {
		Tcl_Obj *options = Tcl_GetReturnOptions(interp, code);
		Tcl_Obj *keyPtr, *valuePtr = NULL;
		Tcl_Obj *valuePtr = NULL;

		TclNewLiteralStringObj(keyPtr, "-errorinfo");
		Tcl_IncrRefCount(keyPtr);
		Tcl_DictObjGet(NULL, options, keyPtr, &valuePtr);
		TclDictGet(NULL, options, "-errorinfo", &valuePtr);
		Tcl_DecrRefCount(keyPtr);

		Tcl_WriteChars(errChannel,
			"error in background error handler:\n", -1);
		if (valuePtr) {
		    Tcl_WriteObj(errChannel, valuePtr);
		    if (Tcl_WriteObj(errChannel, valuePtr) < 0) {
			Tcl_WriteChars(errChannel, ENCODING_ERROR, -1);
		    }
		} else {
		    Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
		    if (Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp)) < 0) {
			Tcl_WriteChars(errChannel, ENCODING_ERROR, -1);
		    }
		}
		Tcl_WriteChars(errChannel, "\n", 1);
		Tcl_Flush(errChannel);
		Tcl_DecrRefCount(options);
	    }
	}
    }
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
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
366







-
+













-
-
-
+
-



-
+





-
-
-
+
-



-
+







int
TclDefaultBgErrorHandlerObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *keyPtr, *valuePtr;
    Tcl_Obj *valuePtr;
    Tcl_Obj *tempObjv[2];
    int result, code, level;
    Tcl_InterpState saved;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "msg options");
	return TCL_ERROR;
    }

    /*
     * Check for a valid return options dictionary.
     */

    TclNewLiteralStringObj(keyPtr, "-level");
    Tcl_IncrRefCount(keyPtr);
    result = Tcl_DictObjGet(NULL, objv[2], keyPtr, &valuePtr);
    result = TclDictGet(NULL, objv[2], "-level", &valuePtr);
    Tcl_DecrRefCount(keyPtr);
    if (result != TCL_OK || valuePtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"missing return option \"-level\"", -1));
	Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
	Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (char *)NULL);
	return TCL_ERROR;
    }
    if (Tcl_GetIntFromObj(interp, valuePtr, &level) == TCL_ERROR) {
	return TCL_ERROR;
    }
    TclNewLiteralStringObj(keyPtr, "-code");
    Tcl_IncrRefCount(keyPtr);
    result = Tcl_DictObjGet(NULL, objv[2], keyPtr, &valuePtr);
    result = TclDictGet(NULL, objv[2], "-code", &valuePtr);
    Tcl_DecrRefCount(keyPtr);
    if (result != TCL_OK || valuePtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"missing return option \"-code\"", -1));
	Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
	Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (char *)NULL);
	return TCL_ERROR;
    }
    if (Tcl_GetIntFromObj(interp, valuePtr, &code) == TCL_ERROR) {
	return TCL_ERROR;
    }

    if (level != 0) {
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
410
411
412
413
414
415
416



417

418
419
420
421



422

423
424
425
426
427
428
429







-
-
-
+
-




-
-
-
+
-







    }
    Tcl_IncrRefCount(tempObjv[1]);

    if (code != TCL_ERROR) {
	Tcl_SetObjResult(interp, tempObjv[1]);
    }

    TclNewLiteralStringObj(keyPtr, "-errorcode");
    Tcl_IncrRefCount(keyPtr);
    result = Tcl_DictObjGet(NULL, objv[2], keyPtr, &valuePtr);
    result = TclDictGet(NULL, objv[2], "-errorcode", &valuePtr);
    Tcl_DecrRefCount(keyPtr);
    if (result == TCL_OK && valuePtr != NULL) {
	Tcl_SetObjErrorCode(interp, valuePtr);
    }

    TclNewLiteralStringObj(keyPtr, "-errorinfo");
    Tcl_IncrRefCount(keyPtr);
    result = Tcl_DictObjGet(NULL, objv[2], keyPtr, &valuePtr);
    result = TclDictGet(NULL, objv[2], "-errorinfo", &valuePtr);
    Tcl_DecrRefCount(keyPtr);
    if (result == TCL_OK && valuePtr != NULL) {
	Tcl_AppendObjToErrorInfo(interp, valuePtr);
    }

    if (code == TCL_ERROR) {
	Tcl_SetObjResult(interp, tempObjv[1]);
    }
450
451
452
453
454
455
456
457
458




459
460
461
462

463
464
465
466
467
468








469
470
471
472
473
474
475
461
462
463
464
465
466
467


468
469
470
471
472
473
474

475






476
477
478
479
480
481
482
483
484
485
486
487
488
489
490







-
-
+
+
+
+



-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+







	    if (errChannel != NULL) {
		Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);

		Tcl_IncrRefCount(resultPtr);
		if (Tcl_FindCommand(interp, "bgerror", NULL,
			TCL_GLOBAL_ONLY) == NULL) {
		    Tcl_RestoreInterpState(interp, saved);
		    Tcl_WriteObj(errChannel, Tcl_GetVar2Ex(interp,
			    "errorInfo", NULL, TCL_GLOBAL_ONLY));
		    if (Tcl_WriteObj(errChannel, Tcl_GetVar2Ex(interp,
			    "errorInfo", NULL, TCL_GLOBAL_ONLY)) < 0) {
			Tcl_WriteChars(errChannel, ENCODING_ERROR, -1);
		    }
		    Tcl_WriteChars(errChannel, "\n", -1);
		} else {
		    Tcl_DiscardInterpState(saved);
		    Tcl_WriteChars(errChannel,
		    Tcl_WriteChars(errChannel, "bgerror failed to handle"
			    "bgerror failed to handle background error.\n",-1);
		    Tcl_WriteChars(errChannel, "    Original error: ", -1);
		    Tcl_WriteObj(errChannel, tempObjv[1]);
		    Tcl_WriteChars(errChannel, "\n", -1);
		    Tcl_WriteChars(errChannel, "    Error in bgerror: ", -1);
		    Tcl_WriteObj(errChannel, resultPtr);
			    " background error.\n    Original error: ", -1);
		    if (Tcl_WriteObj(errChannel, tempObjv[1]) < 0) {
			Tcl_WriteChars(errChannel, ENCODING_ERROR, -1);
		    }
		    Tcl_WriteChars(errChannel, "\n    Error in bgerror: ", -1);
		    if (Tcl_WriteObj(errChannel, resultPtr) < 0) {
			Tcl_WriteChars(errChannel, ENCODING_ERROR, -1);
		    }
		    Tcl_WriteChars(errChannel, "\n", -1);
		}
		Tcl_DecrRefCount(resultPtr);
		Tcl_Flush(errChannel);
	    } else {
		Tcl_DiscardInterpState(saved);
	    }
567
568
569
570
571
572
573
574

575
576
577
578
579
580
581
582
583
584
585
586
587
588

589
590
591
592
593
594
595
596







-
+







/*
 *----------------------------------------------------------------------
 *
 * BgErrorDeleteProc --
 *
 *	This function is associated with the "tclBgError" assoc data for an
 *	interpreter; it is invoked when the interpreter is deleted in order to
 *	free the information assoicated with any pending error reports.
 *	free the information associated with any pending error reports.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Background error information is freed: if there were any pending error
 *	reports, they are canceled.
845
846
847
848
849
850
851
852

853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
860
861
862
863
864
865
866

867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882

883
884
885
886
887
888
889







-
+















-







 *	Sets the application wide exit handler to the specified value.
 *
 *----------------------------------------------------------------------
 */

Tcl_ExitProc *
Tcl_SetExitProc(
    TCL_NORETURN1 Tcl_ExitProc *proc)		/* New exit handler for app or NULL */
    Tcl_ExitProc *proc)		/* New exit handler for app or NULL */
{
    Tcl_ExitProc *prevExitProc;

    /*
     * Swap the old exit proc for the new one, saving the old one for our
     * return value.
     */

    Tcl_MutexLock(&exitMutex);
    prevExitProc = appExitPtr;
    appExitPtr = proc;
    Tcl_MutexUnlock(&exitMutex);

    return prevExitProc;
}


/*
 *----------------------------------------------------------------------
 *
 * InvokeExitHandlers --
 *
 *      Call the registered exit handlers.
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
917
918
919
920
921
922
923

924
925
926
927
928
929
930







-







	exitPtr->proc(exitPtr->clientData);
	Tcl_Free(exitPtr);
	Tcl_MutexLock(&exitMutex);
    }
    firstExitPtr = NULL;
    Tcl_MutexUnlock(&exitMutex);
}


/*
 *----------------------------------------------------------------------
 *
 * Tcl_Exit --
 *
 *	This function is called to terminate the application.
926
927
928
929
930
931
932
933

934
935
936
937
938
939
940
941
942

943
944
945
946
947
948
949
939
940
941
942
943
944
945

946
947
948
949
950
951
952
953
954

955
956
957
958
959
960
961
962







-
+








-
+







 */

TCL_NORETURN void
Tcl_Exit(
    int status)			/* Exit status for application; typically 0
				 * for normal return, 1 for error return. */
{
    TCL_NORETURN1 Tcl_ExitProc *currentAppExitPtr;
    Tcl_ExitProc *currentAppExitPtr;

    Tcl_MutexLock(&exitMutex);
    currentAppExitPtr = appExitPtr;
    Tcl_MutexUnlock(&exitMutex);

    /*
     * Warning: this function SHOULD NOT return, as there is code that depends
     * on Tcl_Exit never returning. In fact, we will Tcl_Panic if anyone
     * returns, so critical is this dependcy.
     * returns, so critical is this dependency.
     *
     * If subsystems are not (yet) initialized, proper Tcl-finalization is
     * impossible, so fallback to system exit, see bug-[f8a33ce3db5d8cc2].
     */

    if (currentAppExitPtr) {

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
1024
1025

1026
1027
1028
1029
1030
1031
1032
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129

1130
1131
1132
1133
1134
1135
1136
1137







-
+
-



















-
+







+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
+







	     * Tcl_Channels that may have data enqueued.
	     */

	    FinalizeThread(/* quick */ 1);
	}
    }

    TclpExit(status);
    exit(status);
    Tcl_Panic("OS exit failed!");
}

/*
 *-------------------------------------------------------------------------
 *
 * Tcl_InitSubsystems --
 *
 *	Initialize various subsytems in Tcl. This should be called the first
 *	time an interp is created, or before any of the subsystems are used.
 *	This function ensures an order for the initialization of subsystems:
 *
 *	1. that cannot be initialized in lazy order because they are mutually
 *	dependent.
 *
 *	2. so that they can be finalized in a known order w/o causing the
 *	subsequent re-initialization of a subsystem in the act of shutting
 *	down another.
 *
 * Results:
 *	None.
 *	The full Tcl version with build information.
 *
 * Side effects:
 *	Varied, see the respective initialization routines.
 *
 *-------------------------------------------------------------------------
 */

MODULE_SCOPE const TclStubs tclStubs;
void

#ifndef STRINGIFY
#  define STRINGIFY(x) STRINGIFY1(x)
#  define STRINGIFY1(x) #x
#endif

static const struct {
    const TclStubs *stubs;
    const char version[256];
} stubInfo = {
    &tclStubs, {TCL_PATCH_LEVEL "+" STRINGIFY(TCL_VERSION_UUID)
#if defined(__clang__) && defined(__clang_major__)
	    ".clang-" STRINGIFY(__clang_major__)
#if __clang_minor__ < 10
	    "0"
#endif
	    STRINGIFY(__clang_minor__)
#endif
#ifdef TCL_COMPILE_DEBUG
	    ".compiledebug"
#endif
#ifdef TCL_COMPILE_STATS
	    ".compilestats"
#endif
#if defined(__cplusplus) && !defined(__OBJC__)
	    ".cplusplus"
#endif
#ifndef NDEBUG
	    ".debug"
#endif
#if !defined(__clang__) && !defined(__INTEL_COMPILER) && defined(__GNUC__)
	    ".gcc-" STRINGIFY(__GNUC__)
#if __GNUC_MINOR__ < 10
	    "0"
#endif
	    STRINGIFY(__GNUC_MINOR__)
#endif
#ifdef __INTEL_COMPILER
	    ".icc-" STRINGIFY(__INTEL_COMPILER)
#endif
#if (defined(_WIN32) || (ULONG_MAX == 0xffffffffUL)) && !defined(_WIN64)
	    ".ilp32"
#endif
#ifdef TCL_MEM_DEBUG
	    ".memdebug"
#endif
#if defined(_MSC_VER)
	    ".msvc-" STRINGIFY(_MSC_VER)
#endif
#ifdef USE_NMAKE
	    ".nmake"
#endif
#ifdef TCL_NO_DEPRECATED
	    ".no-deprecate"
#endif
#if !TCL_THREADS
	    ".no-thread"
#endif
#ifndef TCL_CFG_OPTIMIZED
	    ".no-optimize"
#endif
#ifdef __OBJC__
	    ".objective-c"
#if defined(__cplusplus)
	    "plusplus"
#endif
#endif
#ifdef TCL_CFG_PROFILED
	    ".profile"
#endif
#ifdef PURIFY
	    ".purify"
#endif
#ifdef STATIC_BUILD
	    ".static"
#endif
#ifndef TCL_WITH_EXTERNAL_TOMMATH
	    ".tommath-0103"
#endif
#ifdef TCL_WITH_INTERNAL_ZLIB
	    ".zlib-"
#if ZLIB_VER_MAJOR < 10
	    "0"
#endif
	    STRINGIFY(ZLIB_VER_MAJOR)
#if ZLIB_VER_MINOR < 10
	    "0"
#endif
	    STRINGIFY(ZLIB_VER_MINOR)
#endif // TCL_WITH_INTERNAL_ZLIB
}};

const char *
Tcl_InitSubsystems(void)
{
    if (inExit != 0) {
	Tcl_Panic("Tcl_InitSubsystems called while exiting");
    }

    if (subsystemsInitialized == 0) {
	/*
	 * Double check inside the mutex. There are definitly calls back into
	 * Double check inside the mutex. There are definitely calls back into
	 * this routine from some of the functions below.
	 */

	TclpInitLock();
	if (subsystemsInitialized == 0) {

		/*
1056
1057
1058
1059
1060
1061
1062

1063
1064
1065
1066
1067
1068
1069
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175







+







	    TclInitEncodingSubsystem();	/* Process wide encoding init. */
	    TclInitNamespaceSubsystem();/* Register ns obj type (mutexed). */
	    subsystemsInitialized = 1;
	}
	TclpInitUnlock();
    }
    TclInitNotifier();
    return stubInfo.version;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Finalize --
 *
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400






1401
1402
1403
1404
1405
1406






1407
































1408




















































































































































































1409
1410
1411



1412
1413
1414
1415
1416
1417

1418
1419








1420

1421
1422
1423

1424
1425
1426
1427
1428
1429
1430
1431







1432

1433

1434
1435
1436
1437


1438
1439










1440
1441
1442
1443

1444
1445









1446
1447
1448




















































































































1449
1450
1451
1452
1453

1454
1455
1456
1457
1458
1459

1460



1461


1462
1463
1464
1465
1466
1467
1468
1494
1495
1496
1497
1498
1499
1500






1501
1502
1503
1504
1505
1506






1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545

1546
1547
1548
1549
1550
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
1749
1750
1751





1752
1753
1754
1755
1756
1757
1758
1759
1760

1761
1762
1763
1764
1765
1766
1767


1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780

1781

1782
1783
1784
1785
1786
1787
1788
1789
1790
1791



1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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







-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+






+


+
+
+
+
+
+
+
+
-
+
-
-
-
+



-
-
-
-
-
+
+
+
+
+
+
+

+
-
+




+
+
-
-
+
+
+
+
+
+
+
+
+
+



-
+
-

+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+





-
+

+
+
+
-
+
+







int
Tcl_VwaitObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int done, foundEvent;
    const char *nameString;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name");
	return TCL_ERROR;
    int i, done = 0, timedOut = 0, foundEvent, any = 1, timeout = 0;
    int numItems = 0, extended = 0, result, mode, mask = TCL_ALL_EVENTS;
    Tcl_InterpState saved = NULL;
    Tcl_TimerToken timer = NULL;
    Tcl_Time before, after;
    Tcl_Channel chan;
    }
    nameString = TclGetString(objv[1]);
    if (Tcl_TraceVar2(interp, nameString, NULL,
	    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
	    VwaitVarProc, &done) != TCL_OK) {
	return TCL_ERROR;
    Tcl_WideInt diff = -1;
    VwaitItem localItems[32], *vwaitItems = localItems;
    static const char *const vWaitOptionStrings[] = {
	"-all",	"-extended", "-nofileevents", "-noidleevents",
	"-notimerevents", "-nowindowevents", "-readable",
	"-timeout", "-variable", "-writable", "--", NULL
    };
    enum vWaitOptions {
	OPT_ALL, OPT_EXTD, OPT_NO_FEVTS, OPT_NO_IEVTS,
	OPT_NO_TEVTS, OPT_NO_WEVTS, OPT_READABLE,
	OPT_TIMEOUT, OPT_VARIABLE, OPT_WRITABLE, OPT_LAST
    } index;

    if ((objc == 2) && (strcmp(Tcl_GetString(objv[1]), "--") != 0)) {
	/*
	 * Legacy "vwait" syntax, skip option handling.
	 */
	i = 1;
	goto endOfOptionLoop;
    }

    if ((unsigned) objc - 1 > sizeof(localItems) / sizeof(localItems[0])) {
	vwaitItems = (VwaitItem *)Tcl_Alloc(sizeof(VwaitItem) * (objc - 1));
    }

    for (i = 1; i < objc; i++) {
	const char *name;

	name = TclGetString(objv[i]);
	if (name[0] != '-') {
	    break;
	}
	if (Tcl_GetIndexFromObj(interp, objv[i], vWaitOptionStrings, "option", 0,
		&index) != TCL_OK) {
	    result = TCL_ERROR;
	    goto done;
	}
	switch (index) {
	case OPT_ALL:
    done = 0;
	    any = 0;
	    break;
	case OPT_EXTD:
	    extended = 1;
	    break;
	case OPT_NO_FEVTS:
	    mask &= ~TCL_FILE_EVENTS;
	    break;
	case OPT_NO_IEVTS:
	    mask &= ~TCL_IDLE_EVENTS;
	    break;
	case OPT_NO_TEVTS:
	    mask &= ~TCL_TIMER_EVENTS;
	    break;
	case OPT_NO_WEVTS:
	    mask &= ~TCL_WINDOW_EVENTS;
	    break;
	case OPT_TIMEOUT:
	    if (++i >= objc) {
	needArg:
		Tcl_ResetResult(interp);
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"argument required for \"%s\"", vWaitOptionStrings[index]));
		Tcl_SetErrorCode(interp, "TCL", "EVENT", "ARGUMENT", (char *)NULL);
		result = TCL_ERROR;
		goto done;
	    }
	    if (Tcl_GetIntFromObj(interp, objv[i], &timeout) != TCL_OK) {
		result = TCL_ERROR;
		goto done;
	    }
	    if (timeout < 0) {
		Tcl_ResetResult(interp);
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"timeout must be positive", -1));
		Tcl_SetErrorCode(interp, "TCL", "EVENT", "NEGTIME", (char *)NULL);
		result = TCL_ERROR;
		goto done;
	    }
	    break;
	case OPT_LAST:
	    i++;
	    goto endOfOptionLoop;
	case OPT_VARIABLE:
	    if (++i >= objc) {
		goto needArg;
	    }
	    result = Tcl_TraceVar2(interp, TclGetString(objv[i]), NULL,
		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		    VwaitVarProc, &vwaitItems[numItems]);
	    if (result != TCL_OK) {
		goto done;
	    }
	    vwaitItems[numItems].donePtr = &done;
	    vwaitItems[numItems].sequence = -1;
	    vwaitItems[numItems].mask = 0;
	    vwaitItems[numItems].sourceObj = objv[i];
	    numItems++;
	    break;
	case OPT_READABLE:
	    if (++i >= objc) {
		goto needArg;
	    }
	    if (TclGetChannelFromObj(interp, objv[i], &chan, &mode, 0)
		    != TCL_OK) {
		result = TCL_ERROR;
		goto done;
	    }
	    if (!(mode & TCL_READABLE)) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"channel \"%s\" wasn't open for reading",
			TclGetString(objv[i])));
		result = TCL_ERROR;
		goto done;
	    }
	    Tcl_CreateChannelHandler(chan, TCL_READABLE,
		    VwaitChannelReadProc, &vwaitItems[numItems]);
	    vwaitItems[numItems].donePtr = &done;
	    vwaitItems[numItems].sequence = -1;
	    vwaitItems[numItems].mask = TCL_READABLE;
	    vwaitItems[numItems].sourceObj = objv[i];
	    numItems++;
	    break;
	case OPT_WRITABLE:
	    if (++i >= objc) {
		goto needArg;
	    }
	    if (TclGetChannelFromObj(interp, objv[i], &chan, &mode, 0)
		    != TCL_OK) {
		result = TCL_ERROR;
		goto done;
	    }
	    if (!(mode & TCL_WRITABLE)) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"channel \"%s\" wasn't open for writing",
			TclGetString(objv[i])));
		result = TCL_ERROR;
		goto done;
	    }
	    Tcl_CreateChannelHandler(chan, TCL_WRITABLE,
		    VwaitChannelWriteProc, &vwaitItems[numItems]);
	    vwaitItems[numItems].donePtr = &done;
	    vwaitItems[numItems].sequence = -1;
	    vwaitItems[numItems].mask = TCL_WRITABLE;
	    vwaitItems[numItems].sourceObj = objv[i];
	    numItems++;
	    break;
	}
    }

  endOfOptionLoop:
    if ((mask & (TCL_FILE_EVENTS | TCL_IDLE_EVENTS |
	    TCL_TIMER_EVENTS | TCL_WINDOW_EVENTS)) == 0) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"can't wait: would block forever", -1));
	Tcl_SetErrorCode(interp, "TCL", "EVENT", "NO_SOURCES", (char *)NULL);
	result = TCL_ERROR;
	goto done;
    }

    if ((timeout > 0) && ((mask & TCL_TIMER_EVENTS) == 0)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"timer events disabled with timeout specified", -1));
	Tcl_SetErrorCode(interp, "TCL", "EVENT", "NO_TIME", (char *)NULL);
	result = TCL_ERROR;
	goto done;
    }

    for (result = TCL_OK; i < objc; i++) {
	result = Tcl_TraceVar2(interp, TclGetString(objv[i]), NULL,
		TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		VwaitVarProc, &vwaitItems[numItems]);
	if (result != TCL_OK) {
	    break;
	}
	vwaitItems[numItems].donePtr = &done;
	vwaitItems[numItems].sequence = -1;
	vwaitItems[numItems].mask = 0;
	vwaitItems[numItems].sourceObj = objv[i];
	numItems++;
    }
    if (result != TCL_OK) {
	result = TCL_ERROR;
	goto done;
    }

    if (!(mask & TCL_FILE_EVENTS)) {
	for (i = 0; i < numItems; i++) {
	    if (vwaitItems[i].mask) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"file events disabled with channel(s) specified", -1));
		Tcl_SetErrorCode(interp, "TCL", "EVENT", "NO_FILE_EVENT", (char *)NULL);
		result = TCL_ERROR;
		goto done;
	    }
	}
    }

    if (timeout > 0) {
	vwaitItems[numItems].donePtr = &timedOut;
	vwaitItems[numItems].sequence = -1;
	vwaitItems[numItems].mask = 0;
	vwaitItems[numItems].sourceObj = NULL;
	timer = Tcl_CreateTimerHandler(timeout, VwaitTimeoutProc,
		&vwaitItems[numItems]);
	Tcl_GetTime(&before);
    } else {
	timeout = 0;
    }

    if ((numItems == 0) && (timeout == 0)) {
	/*
	 * "vwait" is equivalent to "update",
	 * "vwait -nofileevents -notimerevents -nowindowevents"
	 * is equivalent to "update idletasks"
	 */
	any = 1;
	mask |= TCL_DONT_WAIT;
    }

    foundEvent = 1;
    while (!done && foundEvent) {
	foundEvent = Tcl_DoOneEvent(TCL_ALL_EVENTS);
    while (!timedOut && foundEvent &&
	   ((!any && (done < numItems)) || (any && !done))) {
	foundEvent = Tcl_DoOneEvent(mask);
	if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) {
	    break;
	}
	if (Tcl_LimitExceeded(interp)) {
	    Tcl_ResetResult(interp);
	    Tcl_SetObjResult(interp, Tcl_NewStringObj("limit exceeded", -1));
	    Tcl_SetErrorCode(interp, "TCL", "EVENT", "LIMIT", (char *)NULL);
	    break;
	}
	if ((numItems == 0) && (timeout == 0)) {
	    /*
	     * Behavior like "update": clear interpreter's result because
	     * event handlers could have executed commands.
	     */
	    Tcl_ResetResult(interp);
	    result = TCL_OK;
	    goto done;
    }
	}
    Tcl_UntraceVar2(interp, nameString, NULL,
	    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
	    VwaitVarProc, &done);
    }

    if (!foundEvent) {
	Tcl_ResetResult(interp);
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't wait for variable \"%s\": would wait forever",
		nameString));
	Tcl_SetErrorCode(interp, "TCL", "EVENT", "NO_SOURCES", NULL);
	return TCL_ERROR;
	Tcl_SetObjResult(interp, Tcl_NewStringObj((numItems == 0) ?
		"can't wait: would wait forever" :
		"can't wait for variable(s)/channel(s): would wait forever",
		-1));
	Tcl_SetErrorCode(interp, "TCL", "EVENT", "NO_SOURCES", (char *)NULL);
	result = TCL_ERROR;
	goto done;
    }

    if (!done) {
    if (!done && !timedOut) {
	/*
	 * The interpreter's result was already set to the right error message
	 * prior to exiting the loop above.
	 */
	result = TCL_ERROR;
	goto done;

	return TCL_ERROR;
    }

    result = TCL_OK;
    if (timeout <= 0) {
	/*
	 * Clear out the interpreter's result, since it may have been set
	 * by event handlers.
	 */
	Tcl_ResetResult(interp);
	goto done;
    }

    /*
     * Clear out the interpreter's result, since it may have been set by event
     * When timeout was specified, report milliseconds left or -1 on timeout.
     * handlers.
     */
    if (timedOut) {
	diff = -1;
    } else {
	Tcl_GetTime(&after);
	diff = after.sec * 1000 + after.usec / 1000;
	diff -= before.sec * 1000 + before.usec / 1000;
	diff = timeout - diff;
	if (diff < 0) {
	    diff = 0;

    Tcl_ResetResult(interp);
    return TCL_OK;
	}
    }

  done:
    if ((timeout > 0) && (timer != NULL)) {
	Tcl_DeleteTimerHandler(timer);
    }
    if (result != TCL_OK) {
	saved = Tcl_SaveInterpState(interp, result);
    }
    for (i = 0; i < numItems; i++) {
	if (vwaitItems[i].mask & TCL_READABLE) {
	    if (TclGetChannelFromObj(interp, vwaitItems[i].sourceObj,
		    &chan, &mode, 0) == TCL_OK) {
		Tcl_DeleteChannelHandler(chan, VwaitChannelReadProc,
			&vwaitItems[i]);
	    }
	} else if (vwaitItems[i].mask & TCL_WRITABLE) {
	    if (TclGetChannelFromObj(interp, vwaitItems[i].sourceObj,
		    &chan, &mode, 0) == TCL_OK) {
		Tcl_DeleteChannelHandler(chan, VwaitChannelWriteProc,
			&vwaitItems[i]);
	    }
	} else {
	    Tcl_UntraceVar2(interp, TclGetString(vwaitItems[i].sourceObj),
		    NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		    VwaitVarProc, &vwaitItems[i]);
	}
    }

    if (result == TCL_OK) {
	if (extended) {
	    int k;
	    Tcl_Obj *listObj, *keyObj;

	    TclNewObj(listObj);
	    for (k = 0; k < done; k++) {
		for (i = 0; i < numItems; i++) {
		    if (vwaitItems[i].sequence != k) {
			continue;
		    }
		    if (vwaitItems[i].mask & TCL_READABLE) {
			TclNewLiteralStringObj(keyObj, "readable");
		    } else if (vwaitItems[i].mask & TCL_WRITABLE) {
			TclNewLiteralStringObj(keyObj, "writable");
		    } else {
			TclNewLiteralStringObj(keyObj, "variable");
		    }
		    Tcl_ListObjAppendElement(NULL, listObj, keyObj);
		    Tcl_ListObjAppendElement(NULL, listObj,
			    vwaitItems[i].sourceObj);
		}
	    }
	    if (timeout > 0) {
		TclNewLiteralStringObj(keyObj, "timeleft");
		Tcl_ListObjAppendElement(NULL, listObj, keyObj);
		Tcl_ListObjAppendElement(NULL, listObj,
			Tcl_NewWideIntObj(diff));
	    }
	    Tcl_SetObjResult(interp, listObj);
	} else if (timeout > 0) {
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(diff));
	}
    } else {
	result = Tcl_RestoreInterpState(interp, saved);
    }
    if (vwaitItems != localItems) {
	Tcl_Free(vwaitItems);
    }
    return result;
}

static void
VwaitChannelReadProc(
    void *clientData,		/* Pointer to vwait info record. */
    int mask)			/* Event mask, must be TCL_READABLE. */
{
    VwaitItem *itemPtr = (VwaitItem *) clientData;

    if (!(mask & TCL_READABLE)) {
	return;
    }
    if (itemPtr->donePtr != NULL) {
	itemPtr->sequence = itemPtr->donePtr[0];
	itemPtr->donePtr[0] += 1;
	itemPtr->donePtr = NULL;
    }
}

static void
VwaitChannelWriteProc(
    void *clientData,		/* Pointer to vwait info record. */
    int mask)			/* Event mask, must be TCL_WRITABLE. */
{
    VwaitItem *itemPtr = (VwaitItem *) clientData;

    if (!(mask & TCL_WRITABLE)) {
	return;
    }
    if (itemPtr->donePtr != NULL) {
	itemPtr->sequence = itemPtr->donePtr[0];
	itemPtr->donePtr[0] += 1;
	itemPtr->donePtr = NULL;
    }
}

static void
VwaitTimeoutProc(
    void *clientData)		/* Pointer to vwait info record. */
{
    VwaitItem *itemPtr = (VwaitItem *) clientData;

    if (itemPtr->donePtr != NULL) {
	itemPtr->donePtr[0] = 1;
	itemPtr->donePtr = NULL;
    }
}

static char *
VwaitVarProc(
    void *clientData,		/* Pointer to integer to set to 1. */
    void *clientData,		/* Pointer to vwait info record. */
    Tcl_Interp *interp,		/* Interpreter containing variable. */
    const char *name1,		/* Name of variable. */
    const char *name2,		/* Second part of variable name. */
    TCL_UNUSED(int) /*flags*/)	/* Information about what happened. */
{
    int *donePtr = (int *)clientData;
    VwaitItem *itemPtr = (VwaitItem *) clientData;

    if (itemPtr->donePtr != NULL) {
	itemPtr->sequence = itemPtr->donePtr[0];
	itemPtr->donePtr[0] += 1;
    *donePtr = 1;
	itemPtr->donePtr = NULL;
    }
    Tcl_UntraceVar2(interp, name1, name2, TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
	    VwaitVarProc, clientData);
    return NULL;
}

/*
 *----------------------------------------------------------------------
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494

1495
1496
1497
1498
1499
1500
1501
1502
1503

1504
1505

1506
1507
1508
1509
1510
1511
1512
1947
1948
1949
1950
1951
1952
1953

1954
1955

1956
1957
1958
1959
1960
1961
1962
1963
1964

1965
1966

1967
1968
1969
1970
1971
1972
1973
1974







-


-
+








-
+

-
+







int
Tcl_UpdateObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int optionIndex;
    int flags = 0;		/* Initialized to avoid compiler warning. */
    static const char *const updateOptions[] = {"idletasks", NULL};
    enum updateOptionsEnum {OPT_IDLETASKS};
    enum updateOptionsEnum {OPT_IDLETASKS} optionIndex;

    if (objc == 1) {
	flags = TCL_ALL_EVENTS|TCL_DONT_WAIT;
    } else if (objc == 2) {
	if (Tcl_GetIndexFromObj(interp, objv[1], updateOptions,
		"option", 0, &optionIndex) != TCL_OK) {
	    return TCL_ERROR;
	}
	switch ((enum updateOptionsEnum) optionIndex) {
	switch (optionIndex) {
	case OPT_IDLETASKS:
	    flags = TCL_WINDOW_EVENTS|TCL_IDLE_EVENTS|TCL_DONT_WAIT;
	    flags = TCL_IDLE_EVENTS|TCL_DONT_WAIT;
	    break;
	default:
	    Tcl_Panic("Tcl_UpdateObjCmd: bad option index to UpdateOptions");
	}
    } else {
	Tcl_WrongNumArgs(interp, 1, objv, "?idletasks?");
	return TCL_ERROR;
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
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







-
-
+
+















+
+
+
+
+
+











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

int
Tcl_CreateThread(
    Tcl_ThreadId *idPtr,	/* Return, the ID of the thread */
    Tcl_ThreadCreateProc *proc,	/* Main() function of the thread */
    void *clientData,	/* The one argument to Main() */
    size_t stackSize,		/* Size of stack for the new thread */
    void *clientData,		/* The one argument to Main() */
    size_t stackSize,	/* Size of stack for the new thread */
    int flags)			/* Flags controlling behaviour of the new
				 * thread. */
{
#if TCL_THREADS
    ThreadClientData *cdPtr = (ThreadClientData *)Tcl_Alloc(sizeof(ThreadClientData));
    int result;

    cdPtr->proc = proc;
    cdPtr->clientData = clientData;
    result = TclpThreadCreate(idPtr, NewThreadProc, cdPtr, stackSize, flags);
    if (result != TCL_OK) {
	Tcl_Free(cdPtr);
    }
    return result;
#else
    (void)idPtr;
    (void)proc;
    (void)clientData;
    (void)stackSize;
    (void)flags;

    return TCL_ERROR;
#endif /* TCL_THREADS */
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclExecute.c.

1
2
3
4
5
6
7
8
9
10
11
12







13
14
15
16
17
18
19
1
2
3
4
5







6
7
8
9
10
11
12
13
14
15
16
17
18
19





-
-
-
-
-
-
-
+
+
+
+
+
+
+







/*
 * tclExecute.c --
 *
 *	This file contains procedures that execute byte-compiled Tcl commands.
 *
 * Copyright (c) 1996-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 by Scriptics Corporation.
 * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
 * Copyright (c) 2002-2010 by Miguel Sofer.
 * Copyright (c) 2005-2007 by Donal K. Fellows.
 * Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
 * Copyright (c) 2006-2008 by Joe Mistachkin.  All rights reserved.
 * Copyright © 1996-1997 Sun Microsystems, Inc.
 * Copyright © 1998-2000 Scriptics Corporation.
 * Copyright © 2001 Kevin B. Kenny. All rights reserved.
 * Copyright © 2002-2010 Miguel Sofer.
 * Copyright © 2005-2007 Donal K. Fellows.
 * Copyright © 2007 Daniel A. Steffen <das@users.sourceforge.net>
 * Copyright © 2006-2008 Joe Mistachkin.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclCompile.h"
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
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







-
-
-
+
+
+
-
-
+



















-
+

-
-
+
+







 * Helpers for NR - non-recursive calls to TEBC
 * Minimal data required to fully reconstruct the execution state.
 */

typedef struct {
    ByteCode *codePtr;		/* Constant until the BC returns */
				/* -----------------------------------------*/
    ptrdiff_t *catchTop;	/* These fields are used on return TO this */
    Tcl_Obj *auxObjList;	/* this level: they record the state when a */
    CmdFrame cmdFrame;		/* new codePtr was received for NR */
    Tcl_Obj **catchTop;		/* These fields are used on return TO this */
    Tcl_Obj *auxObjList;	/* level: they record the state when a new */
    CmdFrame cmdFrame;		/* codePtr was received for NR execution. */
                                /* execution. */
    void *stack[1];		/* Start of the actual combined catch and obj
    Tcl_Obj *stack[1];		/* Start of the actual combined catch and obj
				 * stacks; the struct will be expanded as
				 * necessary */
} TEBCdata;

#define TEBC_YIELD() \
    do {						\
	esPtr->tosPtr = tosPtr;				\
	TclNRAddCallback(interp, TEBCresume,		\
		TD, pc, INT2PTR(cleanup), NULL);	\
    } while (0)

#define TEBC_DATA_DIG() \
    do {					\
	tosPtr = esPtr->tosPtr;			\
    } while (0)

#define PUSH_TAUX_OBJ(objPtr) \
    do {							\
	if (auxObjList) {					\
	    objPtr->length += auxObjList->length;		\
	    (objPtr)->length += auxObjList->length;		\
	}							\
	objPtr->internalRep.twoPtrValue.ptr1 = auxObjList;	\
	auxObjList = objPtr;					\
	(objPtr)->internalRep.twoPtrValue.ptr1 = auxObjList;	\
	auxObjList = (objPtr);					\
    } while (0)

#define POP_TAUX_OBJ() \
    do {							\
	tmpPtr = auxObjList;					\
	auxObjList = (Tcl_Obj *)tmpPtr->internalRep.twoPtrValue.ptr1;	\
	Tcl_DecrRefCount(tmpPtr);				\
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
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







-
+









-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+


-
+


-
+


-
+







-
+








-
+


-
+


-
+


-
+







-
+







 * We use the new compile-time assertions to check that nCleanup is constant
 * and within range.
 */

/* Verify the stack depth, only when no expansion is in progress */

#ifdef TCL_COMPILE_DEBUG
#define CHECK_STACK()							\
#define CHECK_STACK() \
    do {								\
	ValidatePcAndStackTop(codePtr, pc, CURR_DEPTH,			\
		/*checkStack*/ !(starting || auxObjList));		\
	starting = 0;							\
    } while (0)
#else
#define CHECK_STACK()
#endif

#define NEXT_INST_F(pcAdjustment, nCleanup, resultHandling)	\
    do {							\
	TCL_CT_ASSERT((nCleanup >= 0) && (nCleanup <= 2));	\
	CHECK_STACK();						\
	if (nCleanup == 0) {					\
	    if (resultHandling != 0) {				\
		if ((resultHandling) > 0) {			\
		    PUSH_OBJECT(objResultPtr);			\
		} else {					\
		    *(++tosPtr) = objResultPtr;			\
		}						\
	    }							\
	    pc += (pcAdjustment);				\
	    goto cleanup0;					\
	} else if (resultHandling != 0) {			\
	    if ((resultHandling) > 0) {				\
		Tcl_IncrRefCount(objResultPtr);			\
	    }							\
	    pc += (pcAdjustment);				\
	    switch (nCleanup) {					\
	    case 1: goto cleanup1_pushObjResultPtr;		\
	    case 2: goto cleanup2_pushObjResultPtr;		\
	    case 0: break;					\
	    }							\
	} else {						\
	    pc += (pcAdjustment);				\
	    switch (nCleanup) {					\
	    case 1: goto cleanup1;				\
	    case 2: goto cleanup2;				\
	    case 0: break;					\
	    }							\
	}							\
#define NEXT_INST_F(pcAdjustment, nCleanup, resultHandling) \
    do {								\
	TCL_CT_ASSERT((nCleanup >= 0) && (nCleanup <= 2));		\
	CHECK_STACK();							\
	if (nCleanup == 0) {						\
	    if (resultHandling != 0) {					\
		if ((resultHandling) > 0) {				\
		    PUSH_OBJECT(objResultPtr);				\
		} else {						\
		    *(++tosPtr) = objResultPtr;				\
		}							\
	    }								\
	    pc += (pcAdjustment);					\
	    goto cleanup0;						\
	} else if (resultHandling != 0) {				\
	    if ((resultHandling) > 0) {					\
		Tcl_IncrRefCount(objResultPtr);				\
	    }								\
	    pc += (pcAdjustment);					\
	    switch (nCleanup) {						\
	    case 1: goto cleanup1_pushObjResultPtr;			\
	    case 2: goto cleanup2_pushObjResultPtr;			\
	    case 0: break;						\
	    }								\
	} else {							\
	    pc += (pcAdjustment);					\
	    switch (nCleanup) {						\
	    case 1: goto cleanup1;					\
	    case 2: goto cleanup2;					\
	    case 0: break;						\
	    }								\
	}								\
    } while (0)

#define NEXT_INST_V(pcAdjustment, nCleanup, resultHandling)	\
    CHECK_STACK();						\
    do {							\
	pc += (pcAdjustment);					\
	cleanup = (nCleanup);					\
	if (resultHandling) {					\
	    if ((resultHandling) > 0) {				\
		Tcl_IncrRefCount(objResultPtr);			\
	    }							\
	    goto cleanupV_pushObjResultPtr;			\
	} else {						\
	    goto cleanupV;					\
	}							\
#define NEXT_INST_V(pcAdjustment, nCleanup, resultHandling) \
    CHECK_STACK();							\
    do {								\
	pc += (pcAdjustment);						\
	cleanup = (nCleanup);						\
	if (resultHandling) {						\
	    if ((resultHandling) > 0) {					\
		Tcl_IncrRefCount(objResultPtr);				\
	    }								\
	    goto cleanupV_pushObjResultPtr;				\
	} else {							\
	    goto cleanupV;						\
	}								\
    } while (0)

#ifndef TCL_COMPILE_DEBUG
#define JUMP_PEEPHOLE_F(condition, pcAdjustment, cleanup) \
    do {								\
	pc += (pcAdjustment);						\
	switch (*pc) {							\
	case INST_JUMP_FALSE1:						\
	    NEXT_INST_F(((condition)? 2 : TclGetInt1AtPtr(pc+1)), (cleanup), 0); \
	break; \
	    break;							\
	case INST_JUMP_TRUE1:						\
	    NEXT_INST_F(((condition)? TclGetInt1AtPtr(pc+1) : 2), (cleanup), 0); \
	break; \
	    break;							\
	case INST_JUMP_FALSE4:						\
	    NEXT_INST_F(((condition)? 5 : TclGetInt4AtPtr(pc+1)), (cleanup), 0); \
	break; \
	    break;							\
	case INST_JUMP_TRUE4:						\
	    NEXT_INST_F(((condition)? TclGetInt4AtPtr(pc+1) : 5), (cleanup), 0); \
	break; \
	    break;							\
	default:							\
	    if ((condition) < 0) {					\
		TclNewIntObj(objResultPtr, -1);				\
	    } else {							\
		objResultPtr = TCONST((condition) > 0);			\
	    }								\
	    NEXT_INST_F(0, (cleanup), 1);				\
	break; \
	    break;							\
	}								\
    } while (0)
#define JUMP_PEEPHOLE_V(condition, pcAdjustment, cleanup) \
    do {								\
	pc += (pcAdjustment);						\
	switch (*pc) {							\
	case INST_JUMP_FALSE1:						\
	    NEXT_INST_V(((condition)? 2 : TclGetInt1AtPtr(pc+1)), (cleanup), 0); \
	break; \
	    break;							\
	case INST_JUMP_TRUE1:						\
	    NEXT_INST_V(((condition)? TclGetInt1AtPtr(pc+1) : 2), (cleanup), 0); \
	break; \
	    break;							\
	case INST_JUMP_FALSE4:						\
	    NEXT_INST_V(((condition)? 5 : TclGetInt4AtPtr(pc+1)), (cleanup), 0); \
	break; \
	    break;							\
	case INST_JUMP_TRUE4:						\
	    NEXT_INST_V(((condition)? TclGetInt4AtPtr(pc+1) : 5), (cleanup), 0); \
	break; \
	    break;							\
	default:							\
	    if ((condition) < 0) {					\
		TclNewIntObj(objResultPtr, -1);				\
	    } else {							\
		objResultPtr = TCONST((condition) > 0);			\
	    }								\
	    NEXT_INST_V(0, (cleanup), 1);				\
	break; \
	    break;							\
	}								\
    } while (0)
#else /* TCL_COMPILE_DEBUG */
#define JUMP_PEEPHOLE_F(condition, pcAdjustment, cleanup) \
    do{									\
	if ((condition) < 0) {						\
	    TclNewIntObj(objResultPtr, -1);				\
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
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







-
+

-
+

-
+











-
-
-
-
-
-
-
+
+
+
+
+
+
+
+









-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+







#define PUSH_OBJECT(objPtr) \
    Tcl_IncrRefCount(*(++tosPtr) = (objPtr))

#define POP_OBJECT()	*(tosPtr--)

#define OBJ_AT_TOS	*tosPtr

#define OBJ_UNDER_TOS	*(tosPtr-1)
#define OBJ_UNDER_TOS	tosPtr[-1]

#define OBJ_AT_DEPTH(n)	*(tosPtr-(n))
#define OBJ_AT_DEPTH(n)	tosPtr[-(n)]

#define CURR_DEPTH	((ptrdiff_t) (tosPtr - initTosPtr))
#define CURR_DEPTH	(tosPtr - initTosPtr)

#define STACK_BASE(esPtr) ((esPtr)->stackWords - 1)

/*
 * Macros used to trace instruction execution. The macros TRACE,
 * TRACE_WITH_OBJ, and O2S are only used inside TclNRExecuteByteCode. O2S is
 * only used in TRACE* calls to get a string from an object.
 */

#ifdef TCL_COMPILE_DEBUG
#   define TRACE(a) \
    while (traceInstructions) {					\
	fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels,	\
		(int) CURR_DEPTH,				\
		(unsigned) (pc - codePtr->codeStart),		\
		GetOpcodeName(pc));				\
	printf a;						\
	break;							\
    while (traceInstructions) {						\
	fprintf(stdout, "%2" TCL_SIZE_MODIFIER "d: %2" TCL_T_MODIFIER	\
		"d (%" TCL_T_MODIFIER "d) %s ", iPtr->numLevels,	\
		CURR_DEPTH,						\
		(pc - codePtr->codeStart),				\
		GetOpcodeName(pc));					\
	printf a;							\
	break;								\
    }
#   define TRACE_APPEND(a) \
    while (traceInstructions) {		\
	printf a;			\
	break;				\
    }
#   define TRACE_ERROR(interp) \
    TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
#   define TRACE_WITH_OBJ(a, objPtr) \
    while (traceInstructions) {					\
	fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels,	\
		(int) CURR_DEPTH,				\
		(unsigned) (pc - codePtr->codeStart),		\
		GetOpcodeName(pc));				\
	printf a;						\
	TclPrintObject(stdout, objPtr, 30);			\
	fprintf(stdout, "\n");					\
	break;							\
    while (traceInstructions) {						\
	fprintf(stdout, "%2" TCL_SIZE_MODIFIER "d: %2" TCL_T_MODIFIER	\
		"d (%" TCL_T_MODIFIER "d) %s ", iPtr->numLevels,	\
		CURR_DEPTH,						\
		(pc - codePtr->codeStart),				\
		GetOpcodeName(pc));					\
	printf a;							\
	TclPrintObject(stdout, objPtr, 30);				\
	fprintf(stdout, "\n");						\
	break;								\
    }
#   define O2S(objPtr) \
    (objPtr ? TclGetString(objPtr) : "")
#else /* !TCL_COMPILE_DEBUG */
#   define TRACE(a)
#   define TRACE_APPEND(a)
#   define TRACE_ERROR(interp)
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

467
468
469
470
471
472
473
474
475
476
477
478
479


480
481
482
483
484
485
486
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

467
468
469
470
471
472
473
474
475
476
477
478
479

480
481
482
483
484
485
486
487
488







-
+


-
+



-
+

-
+

-
-
+
+


-
+



-
+












-
+
+







	if (TCL_DTRACE_INST_DONE_ENABLED() && curInstName) {		\
	    TCL_DTRACE_INST_DONE(curInstName, (int) CURR_DEPTH, tosPtr);\
	}								\
    } while (0)

/*
 * Macro used in this file to save a function call for common uses of
 * TclGetNumberFromObj(). The ANSI C "prototype" is:
 * Tcl_GetNumberFromObj(). The ANSI C "prototype" is:
 *
 * MODULE_SCOPE int GetNumberFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
 *			ClientData *ptrPtr, int *tPtr);
 *			void **ptrPtr, int *tPtr);
 */

#define GetNumberFromObj(interp, objPtr, ptrPtr, tPtr) \
    ((TclHasIntRep((objPtr), &tclIntType))					\
    ((TclHasInternalRep((objPtr), &tclIntType))				\
	?	(*(tPtr) = TCL_NUMBER_INT,				\
		*(ptrPtr) = (void *)				\
		*(ptrPtr) = (void *)					\
		    (&((objPtr)->internalRep.wideValue)), TCL_OK) :	\
    TclHasIntRep((objPtr), &tclDoubleType)				\
	?	(((TclIsNaN((objPtr)->internalRep.doubleValue))		\
    TclHasInternalRep((objPtr), &tclDoubleType)				\
	?	(((isnan((objPtr)->internalRep.doubleValue))		\
		    ?	(*(tPtr) = TCL_NUMBER_NAN)			\
		    :	(*(tPtr) = TCL_NUMBER_DOUBLE)),			\
		*(ptrPtr) = (void *)				\
		*(ptrPtr) = (void *)					\
		    (&((objPtr)->internalRep.doubleValue)), TCL_OK) :	\
    (((objPtr)->bytes != NULL) && ((objPtr)->length == 0))		\
	? TCL_ERROR :			\
    TclGetNumberFromObj((interp), (objPtr), (ptrPtr), (tPtr)))
    Tcl_GetNumberFromObj((interp), (objPtr), (ptrPtr), (tPtr)))

/*
 * Macro used to make the check for type overflow more mnemonic. This works by
 * comparing sign bits; the rest of the word is irrelevant. The ANSI C
 * "prototype" (where inttype_t is any integer type) is:
 *
 * MODULE_SCOPE int Overflowing(inttype_t a, inttype_t b, inttype_t sum);
 *
 * Check first the condition most likely to fail in usual code (at least for
 * usage in [incr]: do the first summand and the sum have != signs?
 */

#define Overflowing(a,b,sum) ((((a)^(sum)) < 0) && (((a)^(b)) >= 0))
#define Overflowing(a,b,sum) \
    ((((a)^(sum)) < 0) && (((a)^(b)) >= 0))

/*
 * Macro for checking whether the type is NaN, used when we're thinking about
 * throwing an error for supplying a non-number number.
 */

#ifndef ACCEPT_NAN
607
608
609
610
611
612
613
614

615
616
617
618
619
620
621
622
623

624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641



642
643

644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662

663
664
665
666
667


668
669
670
671
672
673
674
675
676
677
678


679
680
681
682
683
684
685
609
610
611
612
613
614
615

616


617
618
619
620
621
622

623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638



639
640
641
642

643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661

662
663
664
665
666

667
668
669
670
671
672
673
674
675
676
677
678

679
680
681
682
683
684
685
686
687







-
+
-
-






-
+















-
-
-
+
+
+

-
+


















-
+




-
+
+










-
+
+







#define OUT_OF_MEMORY ((Tcl_Obj *) -4)

/*
 * Declarations for local procedures to this file:
 */

#ifdef TCL_COMPILE_STATS
static int		EvalStatsCmd(ClientData clientData,
static Tcl_ObjCmdProc EvalStatsCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
#endif /* TCL_COMPILE_STATS */
#ifdef TCL_COMPILE_DEBUG
static const char *	GetOpcodeName(const unsigned char *pc);
static void		PrintByteCodeInfo(ByteCode *codePtr);
static const char *	StringForResultCode(int result);
static void		ValidatePcAndStackTop(ByteCode *codePtr,
			    const unsigned char *pc, int stackTop,
			    const unsigned char *pc, size_t stackTop,
			    int checkStack);
#endif /* TCL_COMPILE_DEBUG */
static ByteCode *	CompileExprObj(Tcl_Interp *interp, Tcl_Obj *objPtr);
static void		DeleteExecStack(ExecStack *esPtr);
static void		DupExprCodeInternalRep(Tcl_Obj *srcPtr,
			    Tcl_Obj *copyPtr);
static Tcl_Obj *	ExecuteExtendedBinaryMathOp(Tcl_Interp *interp,
			    int opcode, Tcl_Obj **constants,
			    Tcl_Obj *valuePtr, Tcl_Obj *value2Ptr);
static Tcl_Obj *	ExecuteExtendedUnaryMathOp(int opcode,
			    Tcl_Obj *valuePtr);
static void		FreeExprCodeInternalRep(Tcl_Obj *objPtr);
static ExceptionRange *	GetExceptRangeForPc(const unsigned char *pc,
			    int searchMode, ByteCode *codePtr);
static const char *	GetSrcInfoForPc(const unsigned char *pc,
			    ByteCode *codePtr, size_t *lengthPtr,
			    const unsigned char **pcBeg, int *cmdIdxPtr);
static Tcl_Obj **	GrowEvaluationStack(ExecEnv *eePtr, int growth,
			    ByteCode *codePtr, Tcl_Size *lengthPtr,
			    const unsigned char **pcBeg, Tcl_Size *cmdIdxPtr);
static Tcl_Obj **	GrowEvaluationStack(ExecEnv *eePtr, size_t growth,
			    int move);
static void		IllegalExprOperandType(Tcl_Interp *interp,
static void		IllegalExprOperandType(Tcl_Interp *interp, const char *ord,
			    const unsigned char *pc, Tcl_Obj *opndPtr);
static void		InitByteCodeExecution(Tcl_Interp *interp);
static inline int	wordSkip(void *ptr);
static void		ReleaseDictIterator(Tcl_Obj *objPtr);
/* Useful elsewhere, make available in tclInt.h or stubs? */
static Tcl_Obj **	StackAllocWords(Tcl_Interp *interp, size_t numWords);
static Tcl_Obj **	StackReallocWords(Tcl_Interp *interp, size_t numWords);
static Tcl_NRPostProc	CopyCallback;
static Tcl_NRPostProc	ExprObjCallback;
static Tcl_NRPostProc	FinalizeOONext;
static Tcl_NRPostProc	FinalizeOONextFilter;
static Tcl_NRPostProc   TEBCresume;

/*
 * The structure below defines a bytecode Tcl object type to hold the
 * compiled bytecode for Tcl expressions.
 */

static const Tcl_ObjType exprCodeType = {
const Tcl_ObjType tclExprCodeType = {
    "exprcode",
    FreeExprCodeInternalRep,	/* freeIntRepProc */
    DupExprCodeInternalRep,	/* dupIntRepProc */
    NULL,			/* updateStringProc */
    NULL			/* setFromAnyProc */
    NULL,			/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

/*
 * Custom object type only used in this file; values of its type should never
 * be seen by user scripts.
 */

static const Tcl_ObjType dictIteratorType = {
    "dictIterator",
    ReleaseDictIterator,
    NULL, NULL, NULL
    NULL, NULL, NULL,
    TCL_OBJTYPE_V0
};

/*
 *----------------------------------------------------------------------
 *
 * ReleaseDictIterator --
 *
697
698
699
700
701
702
703
704

705
706

707
708
709
710
711
712
713
699
700
701
702
703
704
705

706
707

708
709
710
711
712
713
714
715







-
+

-
+








static void
ReleaseDictIterator(
    Tcl_Obj *objPtr)
{
    Tcl_DictSearch *searchPtr;
    Tcl_Obj *dictPtr;
    const Tcl_ObjIntRep *irPtr;
    const Tcl_ObjInternalRep *irPtr;

    irPtr = TclFetchIntRep(objPtr, &dictIteratorType);
    irPtr = TclFetchInternalRep(objPtr, &dictIteratorType);
    assert(irPtr != NULL);

    /*
     * First kill the search, and then release the reference to the dictionary
     * that we were holding.
     */

789
790
791
792
793
794
795
796

797
798
799
800
801
802
803
791
792
793
794
795
796
797

798
799
800
801
802
803
804
805







-
+







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

ExecEnv *
TclCreateExecEnv(
    Tcl_Interp *interp,		/* Interpreter for which the execution
				 * environment is being created. */
    size_t size)			/* The initial stack size, in number of words
    size_t size)		/* The initial stack size, in number of words
				 * [sizeof(Tcl_Obj*)] */
{
    ExecEnv *eePtr = (ExecEnv *)Tcl_Alloc(sizeof(ExecEnv));
    ExecStack *esPtr = (ExecStack *)Tcl_Alloc(offsetof(ExecStack, stackWords)
	    + size * sizeof(Tcl_Obj *));

    eePtr->execStackPtr = esPtr;
971
972
973
974
975
976
977
978

979
980
981
982
983

984

985
986

987
988
989
990
991
992
993
973
974
975
976
977
978
979

980
981
982
983
984
985
986

987
988

989
990
991
992
993
994
995
996







-
+





+
-
+

-
+







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

static Tcl_Obj **
GrowEvaluationStack(
    ExecEnv *eePtr,		/* Points to the ExecEnv with an evaluation
				 * stack to enlarge. */
    int growth,			/* How much larger than the current used
    size_t growth1,		/* How much larger than the current used
				 * size. */
    int move)			/* 1 if move words since last marker. */
{
    ExecStack *esPtr = eePtr->execStackPtr, *oldPtr = NULL;
    size_t newBytes;
    Tcl_Size growth = growth1;
    int newElems, currElems, needed = growth - (esPtr->endPtr - esPtr->tosPtr);
    Tcl_Size newElems, currElems, needed = growth - (esPtr->endPtr - esPtr->tosPtr);
    Tcl_Obj **markerPtr = esPtr->markerPtr, **memStart;
    int moveWords = 0;
    Tcl_Size moveWords = 0;

    if (move) {
	if (!markerPtr) {
	    Tcl_Panic("STACK: Reallocating with no previous alloc");
	}
	if (needed <= 0) {
	    return MEMSTART(markerPtr);
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1022
1023
1024
1025
1026
1027
1028

1029
1030
1031
1032
1033
1034
1035







-







     * the marker, (WALLOCALIGN-1) for the maximal possible offset.
     */

    if (move) {
	moveWords = esPtr->tosPtr - MEMSTART(markerPtr) + 1;
    }
    needed = growth + moveWords + WALLOCALIGN;


    /*
     * Check if there is enough room in the next stack (if there is one, it
     * should be both empty and the last one!)
     */

    if (esPtr->nextPtr) {
1225
1226
1227
1228
1229
1230
1231
1232

1233
1234
1235
1236
1237
1238
1239
1227
1228
1229
1230
1231
1232
1233

1234
1235
1236
1237
1238
1239
1240
1241







-
+







    Tcl_Interp *interp,
    size_t numBytes)
{
    Interp *iPtr = (Interp *) interp;
    size_t numWords;

    if (iPtr == NULL || iPtr->execEnvPtr == NULL) {
	return (void *) Tcl_Alloc(numBytes);
	return Tcl_Alloc(numBytes);
    }
    numWords = (numBytes + (sizeof(Tcl_Obj *) - 1))/sizeof(Tcl_Obj *);
    return StackAllocWords(interp, numWords);
}

void *
TclStackRealloc(
1303
1304
1305
1306
1307
1308
1309
1310

1311
1312
1313
1314
1315
1316
1317
1305
1306
1307
1308
1309
1310
1311

1312
1313
1314
1315
1316
1317
1318
1319







-
+







	    NULL, NULL);
    Tcl_NRExprObj(interp, objPtr, resultPtr);
    return TclNRRunCallbacks(interp, TCL_OK, rootPtr);
}

static int
CopyCallback(
    ClientData data[],
    void *data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    Tcl_Obj **resultPtrPtr = (Tcl_Obj **)data[0];
    Tcl_Obj *resultPtr = (Tcl_Obj *)data[1];

    if (result == TCL_OK) {
1361
1362
1363
1364
1365
1366
1367
1368

1369
1370
1371
1372
1373
1374
1375
1363
1364
1365
1366
1367
1368
1369

1370
1371
1372
1373
1374
1375
1376
1377







-
+







    Tcl_NRAddCallback(interp, ExprObjCallback, state, resultPtr,
	    NULL, NULL);
    return TclNRExecuteByteCode(interp, codePtr);
}

static int
ExprObjCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_InterpState state = (Tcl_InterpState)data[0];
    Tcl_Obj *resultPtr = (Tcl_Obj *)data[1];

    if (result == TCL_OK) {
1403
1404
1405
1406
1407
1408
1409
1410

1411
1412
1413
1414
1415
1416
1417
1418
1419

1420
1421
1422
1423
1424
1425
1426
1427
1428
1429

1430
1431
1432
1433
1434
1435
1436
1437
1438
1439

1440
1441
1442
1443
1444
1445
1446
1405
1406
1407
1408
1409
1410
1411

1412

1413
1414
1415
1416
1417
1418
1419

1420
1421
1422
1423
1424
1425
1426
1427
1428
1429

1430
1431
1432
1433
1434
1435
1436
1437
1438
1439

1440
1441
1442
1443
1444
1445
1446
1447







-
+
-







-
+









-
+









-
+







CompileExprObj(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr)
{
    Interp *iPtr = (Interp *) interp;
    CompileEnv compEnv;		/* Compilation environment structure allocated
				 * in frame. */
    ByteCode *codePtr = NULL;
    ByteCode *codePtr = NULL;	/* Tcl Internal type of bytecode. Initialized
				/* Tcl Internal type of bytecode. Initialized
				 * to avoid compiler warning. */

    /*
     * Get the expression ByteCode from the object. If it exists, make sure it
     * is valid in the current context.
     */

    ByteCodeGetIntRep(objPtr, &exprCodeType, codePtr);
    ByteCodeGetInternalRep(objPtr, &tclExprCodeType, codePtr);

    if (codePtr != NULL) {
	Namespace *namespacePtr = iPtr->varFramePtr->nsPtr;

	if (((Interp *) *codePtr->interpHandle != iPtr)
		|| (codePtr->compileEpoch != iPtr->compileEpoch)
		|| (codePtr->nsPtr != namespacePtr)
		|| (codePtr->nsEpoch != namespacePtr->resolverEpoch)
		|| (codePtr->localCachePtr != iPtr->varFramePtr->localCachePtr)) {
	    Tcl_StoreIntRep(objPtr, &exprCodeType, NULL);
	    Tcl_StoreInternalRep(objPtr, &tclExprCodeType, NULL);
	    codePtr = NULL;
	}
    }

    if (codePtr == NULL) {
	/*
	 * TIP #280: No invoker (yet) - Expression compilation.
	 */

	size_t length;
	Tcl_Size length;
	const char *string = TclGetStringFromObj(objPtr, &length);

	TclInitCompileEnv(interp, &compEnv, string, length, NULL, 0);
	TclCompileExpr(interp, string, length, &compEnv, 0);

	/*
	 * Successful compilation. If the expression yielded no instructions,
1455
1456
1457
1458
1459
1460
1461
1462

1463
1464
1465
1466
1467
1468
1469
1470

1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484

1485
1486
1487
1488
1489
1490
1491
1492
1493

1494
1495
1496
1497
1498
1499
1500
1456
1457
1458
1459
1460
1461
1462

1463
1464
1465
1466
1467
1468



1469



1470
1471
1472
1473
1474
1475
1476
1477
1478
1479

1480
1481
1482
1483
1484
1485
1486
1487
1488

1489
1490
1491
1492
1493
1494
1495
1496







-
+





-
-
-
+
-
-
-










-
+








-
+







	/*
	 * Add a "done" instruction as the last instruction and change the
	 * object into a ByteCode object. Ownership of the literal objects and
	 * aux data items is given to the ByteCode object.
	 */

	TclEmitOpcode(INST_DONE, &compEnv);
	codePtr = TclInitByteCodeObj(objPtr, &exprCodeType, &compEnv);
	codePtr = TclInitByteCodeObj(objPtr, &tclExprCodeType, &compEnv);
	TclFreeCompileEnv(&compEnv);
	if (iPtr->varFramePtr->localCachePtr) {
	    codePtr->localCachePtr = iPtr->varFramePtr->localCachePtr;
	    codePtr->localCachePtr->refCount++;
	}
#ifdef TCL_COMPILE_DEBUG
	if (tclTraceCompile == 2) {
	    TclPrintByteCodeObj(interp, objPtr);
	TclDebugPrintByteCodeObj(objPtr);
	    fflush(stdout);
	}
#endif /* TCL_COMPILE_DEBUG */
    }
    return codePtr;
}

/*
 *----------------------------------------------------------------------
 *
 * DupExprCodeInternalRep --
 *
 *	Part of the Tcl object type implementation for Tcl expression
 *	bytecode. We do not copy the bytecode intrep. Instead, we return
 *	bytecode. We do not copy the bytecode internalrep. Instead, we return
 *	without setting copyPtr->typePtr, so the copy is a plain string copy
 *	of the expression value, and if it is to be used as a compiled
 *	expression, it will just need a recompile.
 *
 *	This makes sense, because with Tcl's copy-on-write practices, the
 *	usual (only?) time Tcl_DuplicateObj() will be called is when the copy
 *	is about to be modified, which would invalidate any copied bytecode
 *	anyway. The only reason it might make sense to copy the bytecode is if
 *	we had some modifying routines that operated directly on the intrep,
 *	we had some modifying routines that operated directly on the internalrep,
 *	like we do for lists and dicts.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
1529
1530
1531
1532
1533
1534
1535
1536

1537
1538
1539
1540
1541
1542
1543
1525
1526
1527
1528
1529
1530
1531

1532
1533
1534
1535
1536
1537
1538
1539







-
+







 */

static void
FreeExprCodeInternalRep(
    Tcl_Obj *objPtr)
{
    ByteCode *codePtr;
    ByteCodeGetIntRep(objPtr, &exprCodeType, codePtr);
    ByteCodeGetInternalRep(objPtr, &tclExprCodeType, codePtr);
    assert(codePtr != NULL);

    TclReleaseByteCode(codePtr);
}

/*
 *----------------------------------------------------------------------
1559
1560
1561
1562
1563
1564
1565
1566

1567
1568
1569
1570
1571
1572
1573
1574
1575

1576
1577
1578
1579
1580
1581
1582
1555
1556
1557
1558
1559
1560
1561

1562
1563
1564
1565
1566
1567
1568
1569
1570

1571
1572
1573
1574
1575
1576
1577
1578







-
+








-
+







TclCompileObj(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    const CmdFrame *invoker,
    int word)
{
    Interp *iPtr = (Interp *) interp;
    ByteCode *codePtr;	/* Tcl Internal type of bytecode. */
    ByteCode *codePtr;		/* Tcl Internal type of bytecode. */
    Namespace *namespacePtr = iPtr->varFramePtr->nsPtr;

    /*
     * If the object is not already of tclByteCodeType, compile it (and reset
     * the compilation flags in the interpreter; this should be done after any
     * compilation). Otherwise, check that it is "fresh" enough.
     */

    ByteCodeGetIntRep(objPtr, &tclByteCodeType, codePtr);
    ByteCodeGetInternalRep(objPtr, &tclByteCodeType, codePtr);
    if (codePtr != NULL) {
	/*
	 * Make sure the Bytecode hasn't been invalidated by, e.g., someone
	 * redefining a command with a compile procedure (this might make the
	 * compiled code wrong). The object needs to be recompiled if it was
	 * compiled in/for a different interpreter, or for a different
	 * namespace, or for the same namespace but with different name
1629
1630
1631
1632
1633
1634
1635
1636

1637
1638
1639
1640
1641
1642
1643
1625
1626
1627
1628
1629
1630
1631

1632
1633
1634
1635
1636
1637
1638
1639







-
+







	 * has to be recompiled to get the correct locations. Not doing this
	 * will execute the saved bytecode with data for a different location,
	 * causing 'info frame' to point to the wrong place in the sources.
	 *
	 * Future optimizations ...
	 * (1) Save the location data (ExtCmdLoc) keyed by start line. In that
	 *     case we recompile once per location of the literal, but not
	 *     continously, because the moment we have all locations we do not
	 *     continuously, because the moment we have all locations we do not
	 *     need to recompile any longer.
	 *
	 * (2) Alternative: Do not recompile, tell the execution engine the
	 *     offset between saved starting line and actual one. Then modify
	 *     the users to adjust the locations they have by this offset.
	 *
	 * (3) Alternative 2: Do not fully recompile, adjust just the location
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
1749
1750
1751
1752
1753
1754
1755

1756
1757
1758
1759
1760
1761
1762
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
1749
1750

1751
1752
1753
1754
1755
1756
1757
1758







-
+












-
+









-
+










-
+







     * information.
     */

    iPtr->invokeCmdFramePtr = invoker;
    iPtr->invokeWord = word;
    TclSetByteCodeFromAny(interp, objPtr, NULL, NULL);
    iPtr->invokeCmdFramePtr = NULL;
    ByteCodeGetIntRep(objPtr, &tclByteCodeType, codePtr);
    ByteCodeGetInternalRep(objPtr, &tclByteCodeType, codePtr);
    if (iPtr->varFramePtr->localCachePtr) {
	codePtr->localCachePtr = iPtr->varFramePtr->localCachePtr;
	codePtr->localCachePtr->refCount++;
    }
    return codePtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TclIncrObj --
 *
 *	Increment an integeral value in a Tcl_Obj by an integeral value held
 *	Increment an integral value in a Tcl_Obj by an integral value held
 *	in another Tcl_Obj. Caller is responsible for making sure we can
 *	update the first object.
 *
 * Results:
 *	TCL_ERROR if either object is non-integer, and TCL_OK otherwise. On
 *	error, an error message is left in the interpreter (if it is not NULL,
 *	of course).
 *
 * Side effects:
 *	valuePtr gets the new incrmented value.
 *	valuePtr gets the new incremented value.
 *
 *----------------------------------------------------------------------
 */

int
TclIncrObj(
    Tcl_Interp *interp,
    Tcl_Obj *valuePtr,
    Tcl_Obj *incrPtr)
{
    ClientData ptr1, ptr2;
    void *ptr1, *ptr2;
    int type1, type2;
    mp_int value, incr;
    mp_err err;

    if (Tcl_IsShared(valuePtr)) {
	Tcl_Panic("%s called with shared object", "TclIncrObj");
    }
1796
1797
1798
1799
1800
1801
1802
1803

1804
1805
1806
1807
1808
1809
1810
1792
1793
1794
1795
1796
1797
1798

1799
1800
1801
1802
1803
1804
1805
1806







-
+







    }

    if ((type1 == TCL_NUMBER_INT) && (type2 == TCL_NUMBER_INT)) {
	Tcl_WideInt w1, w2, sum;

	w1 = *((const Tcl_WideInt *)ptr1);
	w2 = *((const Tcl_WideInt *)ptr2);
	sum = w1 + w2;
	sum = (Tcl_WideInt)((Tcl_WideUInt)w1 + (Tcl_WideUInt)w2);

	/*
	 * Check for overflow.
	 */

	if (!Overflowing(w1, w2, sum)) {
	    TclSetIntObj(valuePtr, sum);
1843
1844
1845
1846
1847
1848
1849
1850

1851
1852
1853

1854
1855
1856
1857
1858
1859
1860
1839
1840
1841
1842
1843
1844
1845

1846
1847
1848

1849
1850
1851
1852
1853
1854
1855
1856







-
+


-
+








static void
ArgumentBCEnter(
    Tcl_Interp *interp,
    ByteCode *codePtr,
    TEBCdata *tdPtr,
    const unsigned char *pc,
    int objc,
    Tcl_Size objc,
    Tcl_Obj **objv)
{
    int cmd;
    Tcl_Size cmd;

    if (GetSrcInfoForPc(pc, codePtr, NULL, NULL, &cmd)) {
	TclArgumentBCEnter(interp, objv, objc, codePtr, &tdPtr->cmdFrame, cmd,
		pc - codePtr->codeStart);
    }
}

1873
1874
1875
1876
1877
1878
1879
1880
1881


1882
1883
1884
1885
1886
1887
1888
1889
1890
1891

1892
1893
1894

1895
1896
1897
1898
1899
1900
1901
1869
1870
1871
1872
1873
1874
1875


1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886

1887
1888
1889

1890
1891
1892
1893
1894
1895
1896
1897







-
-
+
+









-
+


-
+







 *
 * Side effects:
 *	Almost certainly, depending on the ByteCode's instructions.
 *
 *----------------------------------------------------------------------
 */
#define	bcFramePtr	(&TD->cmdFrame)
#define	initCatchTop	((ptrdiff_t *) (TD->stack-1))
#define	initTosPtr	((Tcl_Obj **) (initCatchTop+codePtr->maxExceptDepth))
#define	initCatchTop	(TD->stack-1)
#define	initTosPtr	(initCatchTop+codePtr->maxExceptDepth)
#define esPtr		(iPtr->execEnvPtr->execStackPtr)

int
TclNRExecuteByteCode(
    Tcl_Interp *interp,		/* Token for command interpreter. */
    ByteCode *codePtr)		/* The bytecode sequence to interpret. */
{
    Interp *iPtr = (Interp *) interp;
    TEBCdata *TD;
    int size = sizeof(TEBCdata) - 1
    size_t size = sizeof(TEBCdata) - 1
	    + (codePtr->maxStackDepth + codePtr->maxExceptDepth)
		* sizeof(void *);
    int numWords = (size + sizeof(Tcl_Obj *) - 1) / sizeof(Tcl_Obj *);
    size_t numWords = (size + sizeof(Tcl_Obj *) - 1) / sizeof(Tcl_Obj *);

    TclPreserveByteCode(codePtr);

    /*
     * Reserve the stack, setup the TEBCdataPtr (TD) and CallFrame
     *
     * The execution uses a unified stack: first a TEBCdata, immediately
1945
1946
1947
1948
1949
1950
1951
1952

1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965

1966
1967
1968
1969
1970
1971
1972
1941
1942
1943
1944
1945
1946
1947

1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960

1961
1962
1963
1964
1965
1966
1967
1968







-
+












-
+







    TclResetRewriteEnsemble(interp, 1);

    /*
     * Push the callback for bytecode execution
     */

    TclNRAddCallback(interp, TEBCresume, TD, /* pc */ NULL,
	    /* cleanup */ INT2PTR(0), INT2PTR(iPtr->evalFlags));
	    /* cleanup */ NULL, INT2PTR(iPtr->evalFlags));

    /*
     * Reset discard result flag - because it is applicable for this call only,
     * and should not affect all the nested invocations may return result.
     */
    iPtr->evalFlags &= ~TCL_EVAL_DISCARD_RESULT;

    return TCL_OK;
}

static int
TEBCresume(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    /*
     * Compiler cast directive - not a real variable.
     *	   Interp *iPtr = (Interp *) interp;
     */
2023
2024
2025
2026
2027
2028
2029
2030
2031


2032
2033
2034
2035
2036
2037
2038
2039
2040

2041
2042
2043
2044
2045
2046
2047
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
2019
2020
2021
2022
2023
2024
2025


2026
2027
2028
2029
2030
2031
2032
2033
2034
2035

2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046


2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063

2064
2065
2066
2067
2068
2069
2070
2071







-
-
+
+








-
+










-
-
+
+















-
+







    /*
     * Globals: variables that store state, must remain valid at all times.
     */

    Tcl_Obj **tosPtr;		/* Cached pointer to top of evaluation
				 * stack. */
    const unsigned char *pc = (const unsigned char *)data[1];
                                /* The current program counter. */
    unsigned char inst;         /* The currently running instruction */
				/* The current program counter. */
    unsigned char inst;		/* The currently running instruction */

    /*
     * Transfer variables - needed only between opcodes, but not while
     * executing an instruction.
     */

    int cleanup = PTR2INT(data[2]);
    Tcl_Obj *objResultPtr;
    int checkInterp = 0;        /* Indicates when a check of interp readyness
    int checkInterp = 0;	/* Indicates when a check of interp readyness
				 * is necessary. Set by CACHE_STACK_INFO() */

    /*
     * Locals - variables that are used within opcodes or bounded sections of
     * the file (jumps between opcodes within a family).
     * NOTE: These are now mostly defined locally where needed.
     */

    Tcl_Obj *objPtr, *valuePtr, *value2Ptr, *part1Ptr, *part2Ptr, *tmpPtr;
    Tcl_Obj **objv = NULL;
    int objc = 0;
    int opnd, length, pcAdjustment;
    Tcl_Size length, objc = 0;
    int opnd, pcAdjustment;
    Var *varPtr, *arrayPtr;
#ifdef TCL_COMPILE_DEBUG
    char cmdNameBuf[21];
#endif

#ifdef TCL_COMPILE_DEBUG
    int starting = 1;
    traceInstructions = (tclTraceExec == 3);
#endif

    TEBC_DATA_DIG();

#ifdef TCL_COMPILE_DEBUG
    if (!pc && (tclTraceExec >= 2)) {
	PrintByteCodeInfo(codePtr);
	fprintf(stdout, "  Starting stack top=%d\n", (int) CURR_DEPTH);
	fprintf(stdout, "  Starting stack top=%" TCL_T_MODIFIER "d\n", CURR_DEPTH);
	fflush(stdout);
    }
#endif

    if (!pc) {
	/* bytecode is starting from scratch */
	pc = codePtr->codeStart;
2087
2088
2089
2090
2091
2092
2093
2094

2095
2096
2097
2098
2099
2100
2101
2083
2084
2085
2086
2087
2088
2089

2090
2091
2092
2093
2094
2095
2096
2097







-
+







	    TclNewObj(objPtr);
	    Tcl_IncrRefCount(objPtr);
	    iPtr->objResultPtr = objPtr;
	}

	goto cleanup0;
    } else {
        /* resume from invocation */
	/* resume from invocation */
	CACHE_STACK_INFO();

	NRE_ASSERT(iPtr->cmdFramePtr == bcFramePtr);
	if (bcFramePtr->cmdObj) {
	    Tcl_DecrRefCount(bcFramePtr->cmdObj);
	    bcFramePtr->cmdObj = NULL;
	    bcFramePtr->cmd = NULL;
2120
2121
2122
2123
2124
2125
2126
2127

2128
2129
2130
2131
2132
2133
2134
2116
2117
2118
2119
2120
2121
2122

2123
2124
2125
2126
2127
2128
2129
2130







-
+







	}

	/*
	 * Push the call's object result and continue execution with the next
	 * instruction.
	 */

	TRACE_WITH_OBJ(("%u => ... after \"%.20s\": TCL_OK, result=",
	TRACE_WITH_OBJ(("%" TCL_SIZE_MODIFIER "d => ... after \"%.20s\": TCL_OK, result=",
		objc, cmdNameBuf), Tcl_GetObjResult(interp));

	/*
	 * Obtain and reset interp's result to avoid possible duplications of
	 * objects [Bug 781585]. We do not call Tcl_ResetResult to avoid any
	 * side effects caused by the resetting of errorInfo and errorCode
	 * [Bug 804681], which are not needed here. We chose instead to
2265
2266
2267
2268
2269
2270
2271
2272

2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284

2285
2286
2287
2288
2289
2290
2291
2292

2293
2294
2295
2296


2297
2298
2299
2300
2301
2302
2303
2261
2262
2263
2264
2265
2266
2267

2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279

2280
2281
2282
2283
2284
2285
2286
2287

2288
2289
2290


2291
2292
2293
2294
2295
2296
2297
2298
2299







-
+











-
+







-
+


-
-
+
+







#ifdef TCL_COMPILE_DEBUG
    /*
     * Skip the stack depth check if an expansion is in progress.
     */

    CHECK_STACK();
    if (traceInstructions) {
	fprintf(stdout, "%2d: %2d ", iPtr->numLevels, (int) CURR_DEPTH);
	fprintf(stdout, "%2" TCL_SIZE_MODIFIER "d: %2" TCL_T_MODIFIER "d ", iPtr->numLevels, CURR_DEPTH);
	TclPrintInstruction(codePtr, pc);
	fflush(stdout);
    }
#endif /* TCL_COMPILE_DEBUG */

    TCL_DTRACE_INST_NEXT();

    if (inst == INST_LOAD_SCALAR1) {
	goto instLoadScalar1;
    } else if (inst == INST_PUSH1) {
	PUSH_OBJECT(codePtr->objArrayPtr[TclGetUInt1AtPtr(pc+1)]);
	TRACE_WITH_OBJ(("%u => ", TclGetUInt1AtPtr(pc+1)), OBJ_AT_TOS);
	TRACE_WITH_OBJ(("%u => ", TclGetUInt1AtPtr(pc + 1)), OBJ_AT_TOS);
	inst = *(pc += 2);
	goto peepholeStart;
    } else if (inst == INST_START_CMD) {
	/*
	 * Peephole: do not run INST_START_CMD, just skip it
	 */

	iPtr->cmdCount += TclGetUInt4AtPtr(pc+5);
	iPtr->cmdCount += TclGetUInt4AtPtr(pc + 5);
	if (checkInterp) {
	    if (((codePtr->compileEpoch != iPtr->compileEpoch) ||
		 (codePtr->nsEpoch != iPtr->varFramePtr->nsPtr->resolverEpoch)) &&
		!(codePtr->flags & TCL_BYTECODE_PRECOMPILED)) {
		    (codePtr->nsEpoch != iPtr->varFramePtr->nsPtr->resolverEpoch)) &&
		    !(codePtr->flags & TCL_BYTECODE_PRECOMPILED)) {
		goto instStartCmdFailed;
	    }
	    checkInterp = 0;
	}
	inst = *(pc += 9);
	goto peepholeStart;
    } else if (inst == INST_NOP) {
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
2399

2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413

2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424

2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436


2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
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
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408

2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419

2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430


2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444

2445
2446
2447
2448
2449

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
2489







-
+










-
+









-
-
+
+





-
+













-
+










-
+










-
-
+
+












-

+

+

-
+

















-
+




-
+








-
+







	}
	cleanup = 1;
	TRACE_APPEND(("\n"));
	goto processExceptionReturn;

    {
	CoroutineData *corPtr;
	int yieldParameter;
	void *yieldParameter;

    case INST_YIELD:
	corPtr = iPtr->execEnvPtr->corPtr;
	TRACE(("%.30s => ", O2S(OBJ_AT_TOS)));
	if (!corPtr) {
	    TRACE_APPEND(("ERROR: yield outside coroutine\n"));
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "yield can only be called in a coroutine", -1));
	    DECACHE_STACK_INFO();
	    Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ILLEGAL_YIELD",
		    NULL);
		    (char *)NULL);
	    CACHE_STACK_INFO();
	    goto gotError;
	}

#ifdef TCL_COMPILE_DEBUG
	if (tclTraceExec >= 2) {
	    if (traceInstructions) {
		TRACE_APPEND(("YIELD...\n"));
	    } else {
		fprintf(stdout, "%d: (%u) yielding value \"%.30s\"\n",
			iPtr->numLevels, (unsigned)(pc - codePtr->codeStart),
		fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_T_MODIFIER "d) yielding value \"%.30s\"\n",
			iPtr->numLevels, (pc - codePtr->codeStart),
			Tcl_GetString(OBJ_AT_TOS));
	    }
	    fflush(stdout);
	}
#endif
	yieldParameter = 0;
	yieldParameter = NULL;	/*==CORO_ACTIVATE_YIELD*/
	Tcl_SetObjResult(interp, OBJ_AT_TOS);
	goto doYield;

    case INST_YIELD_TO_INVOKE:
	corPtr = iPtr->execEnvPtr->corPtr;
	valuePtr = OBJ_AT_TOS;
	if (!corPtr) {
	    TRACE(("[%.30s] => ERROR: yield outside coroutine\n",
		    O2S(valuePtr)));
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "yieldto can only be called in a coroutine", -1));
	    DECACHE_STACK_INFO();
	    Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ILLEGAL_YIELD",
		    NULL);
		    (char *)NULL);
	    CACHE_STACK_INFO();
	    goto gotError;
	}
	if (((Namespace *)TclGetCurrentNamespace(interp))->flags & NS_DYING) {
	    TRACE(("[%.30s] => ERROR: yield in deleted\n",
		    O2S(valuePtr)));
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "yieldto called in deleted namespace", -1));
	    DECACHE_STACK_INFO();
	    Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "YIELDTO_IN_DELETED",
		    NULL);
		    (char *)NULL);
	    CACHE_STACK_INFO();
	    goto gotError;
	}

#ifdef TCL_COMPILE_DEBUG
	if (tclTraceExec >= 2) {
	    if (traceInstructions) {
		TRACE(("[%.30s] => YIELD...\n", O2S(valuePtr)));
	    } else {
		/* FIXME: What is the right thing to trace? */
		fprintf(stdout, "%d: (%u) yielding to [%.30s]\n",
			iPtr->numLevels, (unsigned)(pc - codePtr->codeStart),
		fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_T_MODIFIER "d) yielding to [%.30s]\n",
			iPtr->numLevels, (pc - codePtr->codeStart),
			TclGetString(valuePtr));
	    }
	    fflush(stdout);
	}
#endif

	/*
	 * Install a tailcall record in the caller and continue with the
	 * yield. The yield is switched into multi-return mode (via the
	 * 'yieldParameter').
	 */

	Tcl_IncrRefCount(valuePtr);
	iPtr->execEnvPtr = corPtr->callerEEPtr;
	Tcl_IncrRefCount(valuePtr);
	TclSetTailcall(interp, valuePtr);
	corPtr->yieldPtr = valuePtr;
	iPtr->execEnvPtr = corPtr->eePtr;
	yieldParameter = (PTR2INT(NULL)+1);	/*==CORO_ACTIVATE_YIELDM*/
	yieldParameter = INT2PTR(1);	/*==CORO_ACTIVATE_YIELDM*/

    doYield:
	/* TIP #280: Record the last piece of info needed by
	 * 'TclGetSrcInfoForPc', and push the frame.
	 */

	bcFramePtr->data.tebc.pc = (char *) pc;
	iPtr->cmdFramePtr = bcFramePtr;

	if (iPtr->flags & INTERP_DEBUG_FRAME) {
	    ArgumentBCEnter(interp, codePtr, TD, pc, objc, objv);
	}

	pc++;
	cleanup = 1;
	TEBC_YIELD();
	TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr,
		INT2PTR(yieldParameter), NULL, NULL);
		yieldParameter, NULL, NULL);
	return TCL_OK;
    }

    case INST_TAILCALL: {
	Tcl_Obj *listPtr, *nsObjPtr;
	Tcl_Obj *listPtr;

	opnd = TclGetUInt1AtPtr(pc+1);

	if (!(iPtr->varFramePtr->isProcCallFrame & 1)) {
	    TRACE(("%d => ERROR: tailcall in non-proc context\n", opnd));
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "tailcall can only be called from a proc or lambda", -1));
	    DECACHE_STACK_INFO();
	    Tcl_SetErrorCode(interp, "TCL", "TAILCALL", "ILLEGAL", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "TAILCALL", "ILLEGAL", (char *)NULL);
	    CACHE_STACK_INFO();
	    goto gotError;
	}

#ifdef TCL_COMPILE_DEBUG
	/* FIXME: What is the right thing to trace? */
	{
2505
2506
2507
2508
2509
2510
2511

2512

2513
2514
2515
2516
2517
2518
2519
2520
2502
2503
2504
2505
2506
2507
2508
2509

2510

2511
2512
2513
2514
2515
2516
2517







+
-
+
-








	/*
	 * Push the evaluation of the called command into the NR callback
	 * stack.
	 */

	listPtr = Tcl_NewListObj(opnd, &OBJ_AT_DEPTH(opnd-1));
	TclListObjSetElement(NULL, listPtr, 0, TclNewNamespaceObj(
	nsObjPtr = Tcl_NewStringObj(iPtr->varFramePtr->nsPtr->fullName, -1);
		(Tcl_Namespace *) iPtr->varFramePtr->nsPtr));
	TclListObjSetElement(interp, listPtr, 0, nsObjPtr);
	if (iPtr->varFramePtr->tailcallPtr) {
	    Tcl_DecrRefCount(iPtr->varFramePtr->tailcallPtr);
	}
	iPtr->varFramePtr->tailcallPtr = listPtr;

	result = TCL_RETURN;
	cleanup = opnd;
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
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







-
-
+
+

-
+



-
+
+









+



+




+











-
+







	TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
	NEXT_INST_F(5, 0, 1);
    break;

    case INST_REVERSE: {
	Tcl_Obj **a, **b;

	opnd = TclGetUInt4AtPtr(pc+1);
	a = tosPtr-(opnd-1);
	opnd = TclGetUInt4AtPtr(pc + 1);
	a = tosPtr - (opnd - 1);
	b = tosPtr;
	while (a<b) {
	while (a < b) {
	    tmpPtr = *a;
	    *a = *b;
	    *b = tmpPtr;
	    a++; b--;
	    a++;
	    b--;
	}
	TRACE(("%u => OK\n", opnd));
	NEXT_INST_F(5, 0, 0);
    }
    break;

    case INST_STR_CONCAT1:

	opnd = TclGetUInt1AtPtr(pc+1);
	DECACHE_STACK_INFO();
	objResultPtr = TclStringCat(interp, opnd, &OBJ_AT_DEPTH(opnd-1),
		TCL_STRING_IN_PLACE);
	if (objResultPtr == NULL) {
	    CACHE_STACK_INFO();
	    TRACE_ERROR(interp);
	    goto gotError;
	}

	CACHE_STACK_INFO();
	TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
	NEXT_INST_V(2, opnd, 1);
    break;

    case INST_CONCAT_STK:
	/*
	 * Pop the opnd (objc) top stack elements, run through Tcl_ConcatObj,
	 * and then decrement their ref counts.
	 */

	opnd = TclGetUInt4AtPtr(pc+1);
	objResultPtr = Tcl_ConcatObj(opnd, &OBJ_AT_DEPTH(opnd-1));
	objResultPtr = Tcl_ConcatObj(opnd, &OBJ_AT_DEPTH(opnd - 1));
	TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
	NEXT_INST_V(5, opnd, 1);
    break;

    case INST_EXPAND_START:
	/*
	 * Push an element to the auxObjList. This records the current
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
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







-
+

















-
+



-
-
+
+
+







	 * error, also in INST_EXPAND_STKTOP).
	 */

	TclNewObj(objPtr);
	objPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(CURR_DEPTH);
	objPtr->length = 0;
	PUSH_TAUX_OBJ(objPtr);
	TRACE(("=> mark depth as %d\n", (int) CURR_DEPTH));
	TRACE(("=> mark depth as %" TCL_T_MODIFIER "d\n", CURR_DEPTH));
	NEXT_INST_F(1, 0, 0);
    break;

    case INST_EXPAND_DROP:
	/*
	 * Drops an element of the auxObjList, popping stack elements to
	 * restore the stack to the state before the point where the aux
	 * element was created.
	 */

	CLANG_ASSERT(auxObjList);
	objc = CURR_DEPTH - PTR2INT(auxObjList->internalRep.twoPtrValue.ptr2);
	POP_TAUX_OBJ();
#ifdef TCL_COMPILE_DEBUG
	/* Ugly abuse! */
	starting = 1;
#endif
	TRACE(("=> drop %d items\n", objc));
	TRACE(("=> drop %" TCL_SIZE_MODIFIER "d items\n", objc));
	NEXT_INST_V(1, objc, 0);

    case INST_EXPAND_STKTOP: {
	int i;
	ptrdiff_t moved;
	Tcl_Size i;
	TEBCdata *newTD;
	Tcl_Size oldCatchTopOff, oldTosPtrOff;

	/*
	 * Make sure that the element at stackTop is a list; if not, just
	 * leave with an error. Note that the element from the expand list
	 * will be removed at checkForCatch.
	 */

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
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







+
+
+
-
+
-
-
+






-
+

-
-
+
+








	auxObjList->length += objc - 1;
	if ((objc > 1) && (auxObjList->length > 0)) {
	    length = auxObjList->length /* Total expansion room we need */
		    + codePtr->maxStackDepth /* Beyond the original max */
		    - CURR_DEPTH;	/* Relative to where we are */
	    DECACHE_STACK_INFO();
	    oldCatchTopOff = catchTop - initCatchTop;
	    oldTosPtrOff = tosPtr - initTosPtr;
	    newTD = (TEBCdata *)
	    moved = GrowEvaluationStack(iPtr->execEnvPtr, length, 1)
		    GrowEvaluationStack(iPtr->execEnvPtr, length, 1);
		    - (Tcl_Obj **) TD;
	    if (moved) {
	    if (newTD != TD) {
		/*
		 * Change the global data to point to the new stack: move the
		 * TEBCdataPtr TD, recompute the position of every other
		 * stack-allocated parameter, update the stack pointers.
		 */

		TD = (TEBCdata *) (((Tcl_Obj **)TD) + moved);
		TD = newTD;

		catchTop += moved;
		tosPtr += moved;
		catchTop = initCatchTop + oldCatchTopOff;
		tosPtr = initTosPtr + oldTosPtrOff;
	    }
	}

	/*
	 * Expand the list at stacktop onto the stack; free the list. Knowing
	 * that it has a freeIntRepProc we use Tcl_DecrRefCount().
	 */
2780
2781
2782
2783
2784
2785
2786
2787

2788
2789
2790
2791

2792
2793
2794


2795
2796
2797
2798
2799
2800
2801
2784
2785
2786
2787
2788
2789
2790

2791
2792
2793
2794

2795
2796


2797
2798
2799
2800
2801
2802
2803
2804
2805







-
+



-
+

-
-
+
+








    doInvocation:
	objv = &OBJ_AT_DEPTH(objc-1);
	cleanup = objc;

#ifdef TCL_COMPILE_DEBUG
	if (tclTraceExec >= 2) {
	    int i;
	    Tcl_Size i;

	    if (traceInstructions) {
		strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
		TRACE(("%u => call ", objc));
		TRACE(("%" TCL_SIZE_MODIFIER "d => call ", objc));
	    } else {
		fprintf(stdout, "%d: (%u) invoking ", iPtr->numLevels,
			(unsigned)(pc - codePtr->codeStart));
		fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_T_MODIFIER "d) invoking ", iPtr->numLevels,
			(pc - codePtr->codeStart));
	    }
	    for (i = 0;  i < objc;  i++) {
		TclPrintObject(stdout, objv[i], 15);
		fprintf(stdout, " ");
	    }
	    fprintf(stdout, "\n");
	    fflush(stdout);
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
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







+
+
+
-
+

+









-
+



-
+


-
-
+
+







	    ArgumentBCEnter(interp, codePtr, TD, pc, objc, objv);
	}

	DECACHE_STACK_INFO();

	pc += pcAdjustment;
	TEBC_YIELD();
	if (objc > INT_MAX) {
	    return TclCommandWordLimitError(interp, objc);
	} else {
	return TclNREvalObjv(interp, objc, objv,
	    return TclNREvalObjv(interp, objc, objv,
		TCL_EVAL_NOERR | TCL_EVAL_SOURCE_IN_FRAME, NULL);
	}

    case INST_INVOKE_REPLACE:
	objc = TclGetUInt4AtPtr(pc+1);
	opnd = TclGetUInt1AtPtr(pc+5);
	objPtr = POP_OBJECT();
	objv = &OBJ_AT_DEPTH(objc-1);
	cleanup = objc;
#ifdef TCL_COMPILE_DEBUG
	if (tclTraceExec >= 2) {
	    int i;
	    Tcl_Size i;

	    if (traceInstructions) {
		strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
		TRACE(("%u => call (implementation %s) ", objc, O2S(objPtr)));
		TRACE(("%" TCL_Z_MODIFIER "u => call (implementation %s) ", objc, O2S(objPtr)));
	    } else {
		fprintf(stdout,
			"%d: (%u) invoking (using implementation %s) ",
			iPtr->numLevels, (unsigned)(pc - codePtr->codeStart),
			"%" TCL_Z_MODIFIER "d: (%" TCL_T_MODIFIER "u) invoking (using implementation %s) ",
			iPtr->numLevels, (pc - codePtr->codeStart),
			O2S(objPtr));
	    }
	    for (i = 0;  i < objc;  i++) {
		if (i < opnd) {
		    fprintf(stdout, "<");
		    TclPrintObject(stdout, objv[i], 15);
		    fprintf(stdout, ">");
2877
2878
2879
2880
2881
2882
2883
2884

2885
2886
2887
2888
2889
2890
2891
2885
2886
2887
2888
2889
2890
2891

2892
2893
2894
2895
2896
2897
2898
2899







-
+








	DECACHE_STACK_INFO();
	pc += 6;
	TEBC_YIELD();

	TclMarkTailcall(interp);
	TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
	Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv);
	TclListObjGetElements(NULL, objPtr, &objc, &objv);
	TclNRAddCallback(interp, TclNRReleaseValues, objPtr, NULL, NULL, NULL);
	return TclNREvalObjv(interp, objc, objv, TCL_EVAL_INVOKE, NULL);

    /*
     * -----------------------------------------------------------------
     *	   Start of INST_LOAD instructions.
     *
3037
3038
3039
3040
3041
3042
3043
3044


3045
3046
3047
3048
3049
3050
3051
3045
3046
3047
3048
3049
3050
3051

3052
3053
3054
3055
3056
3057
3058
3059
3060







-
+
+







     *
     * WARNING: more 'goto' here than your doctor recommended! The different
     * instructions set the value of some variables and then jump to somme
     * common execution code.
     */

    {
	int storeFlags, len;
	int storeFlags;
	Tcl_Size len;

    case INST_STORE_ARRAY4:
	opnd = TclGetUInt4AtPtr(pc+1);
	pcAdjustment = 5;
	goto doStoreArrayDirect;

    case INST_STORE_ARRAY1:
3107
3108
3109
3110
3111
3112
3113
3114

3115
3116
3117
3118
3119
3120
3121
3116
3117
3118
3119
3120
3121
3122

3123
3124
3125
3126
3127
3128
3129
3130







-
+







	valuePtr = varPtr->value.objPtr;
	if (valuePtr != NULL) {
	    TclDecrRefCount(valuePtr);
	}
	objResultPtr = OBJ_AT_TOS;
	varPtr->value.objPtr = objResultPtr;
#ifndef TCL_COMPILE_DEBUG
	if (*(pc+pcAdjustment) == INST_POP) {
	if (pc[pcAdjustment] == INST_POP) {
	    tosPtr--;
	    NEXT_INST_F((pcAdjustment+1), 0, 0);
	}
#else
	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
#endif
	Tcl_IncrRefCount(objResultPtr);
3166
3167
3168
3169
3170
3171
3172
3173

3174
3175
3176
3177
3178
3179
3180
3175
3176
3177
3178
3179
3180
3181

3182
3183
3184
3185
3186
3187
3188
3189







-
+







	if (part2Ptr == NULL) {
	    TRACE(("\"%.30s\" <- \"%.30s\" =>", O2S(part1Ptr),O2S(valuePtr)));
	} else {
	    TRACE(("\"%.30s(%.30s)\" <- \"%.30s\" => ",
		    O2S(part1Ptr), O2S(part2Ptr), O2S(valuePtr)));
	}
#endif
	varPtr = TclObjLookupVarEx(interp, objPtr,part2Ptr, TCL_LEAVE_ERR_MSG,
	varPtr = TclObjLookupVarEx(interp, objPtr, part2Ptr, TCL_LEAVE_ERR_MSG,
		"set", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
	if (!varPtr) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	cleanup = ((part2Ptr == NULL)? 2 : 3);
	pcAdjustment = 1;
3271
3272
3273
3274
3275
3276
3277
3278

3279
3280
3281
3282
3283
3284
3285
3280
3281
3282
3283
3284
3285
3286

3287
3288
3289
3290
3291
3292
3293
3294







-
+







		part1Ptr, part2Ptr, valuePtr, storeFlags, opnd);
	CACHE_STACK_INFO();
	if (!objResultPtr) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}
#ifndef TCL_COMPILE_DEBUG
	if (*(pc+pcAdjustment) == INST_POP) {
	if (pc[pcAdjustment] == INST_POP) {
	    NEXT_INST_V((pcAdjustment+1), cleanup, 0);
	}
#endif
	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
	NEXT_INST_V(pcAdjustment, cleanup, 1);

    case INST_LAPPEND_LIST:
3367
3368
3369
3370
3371
3372
3373
3374

3375
3376
3377
3378
3379
3380
3381
3376
3377
3378
3379
3380
3381
3382

3383
3384
3385
3386
3387
3388
3389
3390







-
+







	if (Tcl_IsShared(objResultPtr)) {
	    Tcl_Obj *newValue = Tcl_DuplicateObj(objResultPtr);

	    TclDecrRefCount(objResultPtr);
	    varPtr->value.objPtr = objResultPtr = newValue;
	    Tcl_IncrRefCount(newValue);
	}
	if (Tcl_ListObjReplace(interp, objResultPtr, len, 0, objc, objv)
	if (TclListObjAppendElements(interp, objResultPtr, objc, objv)
		!= TCL_OK) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
	NEXT_INST_V(pcAdjustment, cleanup, 1);

3425
3426
3427
3428
3429
3430
3431
3432

3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462

3463
3464
3465
3466
3467
3468
3469
3434
3435
3436
3437
3438
3439
3440

3441
3442
3443
3444
3445
3446
3447
3448
3449

3450
3451

3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468

3469
3470
3471
3472
3473
3474
3475
3476







-
+








-


-

















-
+







	    } else {
		if (Tcl_IsShared(objResultPtr)) {
		    valueToAssign = Tcl_DuplicateObj(objResultPtr);
		    createdNewObj = 1;
		} else {
		    valueToAssign = objResultPtr;
		}
		if (Tcl_ListObjReplace(interp, valueToAssign, len, 0,
		if (TclListObjAppendElements(interp, valueToAssign,
			objc, objv) != TCL_OK) {
		    if (createdNewObj) {
			TclDecrRefCount(valueToAssign);
		    }
		    goto errorInLappendListPtr;
		}
	    }
	    DECACHE_STACK_INFO();
	    Tcl_IncrRefCount(valueToAssign);
	    objResultPtr = TclPtrSetVarIdx(interp, varPtr, arrayPtr, part1Ptr,
		    part2Ptr, valueToAssign, TCL_LEAVE_ERR_MSG, opnd);
	    TclDecrRefCount(valueToAssign);
	    CACHE_STACK_INFO();
	    if (!objResultPtr) {
	    errorInLappendListPtr:
		TRACE_ERROR(interp);
		goto gotError;
	    }
	}
	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
	NEXT_INST_V(pcAdjustment, cleanup, 1);
    }

    /*
     *	   End of INST_STORE and related instructions.
     * -----------------------------------------------------------------
     *	   Start of INST_INCR instructions.
     *
     * WARNING: more 'goto' here than your doctor recommended! The different
     * instructions set the value of some variables and then jump to somme
     * instructions set the value of some variables and then jump to some
     * common execution code.
     */

/*TODO: Consider more untangling here; merge with LOAD and STORE ? */

    {
	Tcl_Obj *incrPtr;
3557
3558
3559
3560
3561
3562
3563
3564

3565
3566
3567
3568
3569
3570
3571

3572
3573
3574
3575
3576
3577
3578
3564
3565
3566
3567
3568
3569
3570

3571
3572
3573
3574
3575
3576
3577

3578
3579
3580
3581
3582
3583
3584
3585







-
+






-
+







	cleanup = 0;
	varPtr = LOCAL(opnd);
	while (TclIsVarLink(varPtr)) {
	    varPtr = varPtr->value.linkPtr;
	}

	if (TclIsVarDirectModifyable(varPtr)) {
	    ClientData ptr;
	    void *ptr;
	    int type;

	    objPtr = varPtr->value.objPtr;
	    if (GetNumberFromObj(NULL, objPtr, &ptr, &type) == TCL_OK) {
		if (type == TCL_NUMBER_INT) {
		    Tcl_WideInt augend = *((const Tcl_WideInt *)ptr);
		    Tcl_WideInt sum = augend + increment;
		    Tcl_WideInt sum = (Tcl_WideInt)((Tcl_WideUInt)augend + (Tcl_WideUInt)increment);

		    /*
		     * Overflow when (augend and sum have different sign) and
		     * (augend and increment have the same sign). This is
		     * encapsulated in the Overflowing macro.
		     */

3597
3598
3599
3600
3601
3602
3603
3604

3605
3606
3607
3608
3609
3610
3611
3604
3605
3606
3607
3608
3609
3610

3611
3612
3613
3614
3615
3616
3617
3618







-
+







			TclNewIntObj(objResultPtr, w + increment);
			Tcl_IncrRefCount(objResultPtr);
			varPtr->value.objPtr = objResultPtr;
		    } else {
			objResultPtr = objPtr;

			/*
			 * We know the sum value is outside the long range;
			 * We know the sum value is outside the Tcl_WideInt range;
			 * use macro form that doesn't range test again.
			 */

			TclSetIntObj(objPtr, w+increment);
		    }
		    goto doneIncr;
		}	/* end if (type == TCL_NUMBER_INT) */
3672
3673
3674
3675
3676
3677
3678
3679

3680
3681
3682
3683
3684
3685
3686
3679
3680
3681
3682
3683
3684
3685

3686
3687
3688
3689
3690
3691
3692
3693







-
+







		TRACE_ERROR(interp);
		goto gotError;
	    }
	}
    doneIncr:
	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
#ifndef TCL_COMPILE_DEBUG
	if (*(pc+pcAdjustment) == INST_POP) {
	if (pc[pcAdjustment] == INST_POP) {
	    NEXT_INST_V((pcAdjustment+1), cleanup, 0);
	}
#endif
	NEXT_INST_V(pcAdjustment, cleanup, 1);
    }

    /*
3759
3760
3761
3762
3763
3764
3765
3766

3767
3768
3769
3770
3771
3772
3773
3766
3767
3768
3769
3770
3771
3772

3773
3774
3775
3776
3777
3778
3779
3780







-
+








    doExistStk:
	varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, 0, "access",
		/*createPart1*/0, /*createPart2*/1, &arrayPtr);
	if (varPtr) {
	    if (ReadTraced(varPtr) || (arrayPtr && ReadTraced(arrayPtr))) {
		DECACHE_STACK_INFO();
		TclObjCallVarTraces(iPtr, arrayPtr, varPtr, part1Ptr,part2Ptr,
		TclObjCallVarTraces(iPtr, arrayPtr, varPtr, part1Ptr, part2Ptr,
			TCL_TRACE_READS, 0, -1);
		CACHE_STACK_INFO();
	    }
	    if (TclIsVarUndefined(varPtr)) {
		TclCleanupVar(varPtr, arrayPtr);
		varPtr = NULL;
	    }
3911
3912
3913
3914
3915
3916
3917







































































3918
3919
3920
3921
3922
3923
3924
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	TRACE_ERROR(interp);
	goto gotError;
    }
    break;

    /*
     *	   End of INST_UNSET instructions.
     * -----------------------------------------------------------------
     *	   Start of INST_CONST instructions.
     */
    {
	const char *msgPart;

    case INST_CONST_IMM:
	opnd = TclGetUInt4AtPtr(pc+1);
	pcAdjustment = 5;
	cleanup = 1;
	part1Ptr = NULL;
	objPtr = OBJ_AT_TOS;
	TRACE(("%u \"%.30s\" => \n", opnd, O2S(objPtr)));
	varPtr = LOCAL(opnd);
	arrayPtr = NULL;
	while (TclIsVarLink(varPtr)) {
	    varPtr = varPtr->value.linkPtr;
	}
	goto doConst;
    case INST_CONST_STK:
	opnd = -1;
	pcAdjustment = 1;
	cleanup = 2;
	part1Ptr = OBJ_UNDER_TOS;
	objPtr = OBJ_AT_TOS;
	TRACE(("\"%.30s\" \"%.30s\" => ", O2S(part1Ptr), O2S(objPtr)));
	varPtr = TclObjLookupVarEx(interp, part1Ptr, NULL, 0, NULL,
		/*createPart1*/1, /*createPart2*/0, &arrayPtr);
    doConst:
	if (TclIsVarConstant(varPtr)) {
	    TRACE_APPEND(("\n"));
	    NEXT_INST_V(pcAdjustment, cleanup, 0);
	}
	if (TclIsVarArray(varPtr)) {
	    msgPart = "variable is array";
	    goto constError;
	} else if (TclIsVarArrayElement(varPtr)) {
	    msgPart = "name refers to an element in an array";
	    goto constError;
	} else if (!TclIsVarUndefined(varPtr)) {
	    msgPart = "variable already exists";
	    goto constError;
	}
	if (TclIsVarDirectModifyable(varPtr)) {
	    varPtr->value.objPtr = objPtr;
	    Tcl_IncrRefCount(objPtr);
	} else {
	    Tcl_Obj *resPtr;

	    DECACHE_STACK_INFO();
	    resPtr = TclPtrSetVarIdx(interp, varPtr, arrayPtr, part1Ptr, NULL,
		    objPtr, TCL_LEAVE_ERR_MSG, opnd);
	    CACHE_STACK_INFO();
	    if (resPtr == NULL) {
		TRACE_ERROR(interp);
		goto gotError;
	    }
	}
	TclSetVarConstant(varPtr);
	TRACE_APPEND(("\n"));
	NEXT_INST_V(pcAdjustment, cleanup, 0);

    constError:
	TclObjVarErrMsg(interp, part1Ptr, NULL, "make constant", msgPart, opnd);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CONST", (char *)NULL);
	TRACE_ERROR(interp);
	goto gotError;
    }

    /*
     *	   End of INST_CONST instructions.
     * -----------------------------------------------------------------
     *	   Start of INST_ARRAY instructions.
     */

    case INST_ARRAY_EXISTS_IMM:
	opnd = TclGetUInt4AtPtr(pc+1);
	pcAdjustment = 5;
3985
3986
3987
3988
3989
3990
3991
3992

3993
3994
3995
3996
3997
3998
3999
4063
4064
4065
4066
4067
4068
4069

4070
4071
4072
4073
4074
4075
4076
4077







-
+







		/*
		 * Either an array element, or a scalar: lose!
		 */

		TclObjVarErrMsg(interp, part1Ptr, NULL, "array set",
			"variable isn't array", opnd);
		DECACHE_STACK_INFO();
		Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", NULL);
		Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", (char *)NULL);
		CACHE_STACK_INFO();
		TRACE_ERROR(interp);
		goto gotError;
	    }
	    TclInitArrayVar(varPtr);
#ifdef TCL_COMPILE_DEBUG
	    TRACE_APPEND(("done\n"));
4134
4135
4136
4137
4138
4139
4140
4141
4142


4143
4144
4145
4146
4147
4148
4149


4150
4151
4152
4153
4154
4155
4156
4212
4213
4214
4215
4216
4217
4218


4219
4220
4221
4222
4223
4224
4225


4226
4227
4228
4229
4230
4231
4232
4233
4234







-
-
+
+





-
-
+
+







    /*
     *	   End of variable linking instructions.
     * -----------------------------------------------------------------
     */

    case INST_JUMP1:
	opnd = TclGetInt1AtPtr(pc+1);
	TRACE(("%d => new pc %u\n", opnd,
		(unsigned)(pc + opnd - codePtr->codeStart)));
	TRACE(("%d => new pc %" TCL_Z_MODIFIER "u\n", opnd,
		(size_t)(pc + opnd - codePtr->codeStart)));
	NEXT_INST_F(opnd, 0, 0);
    break;

    case INST_JUMP4:
	opnd = TclGetInt4AtPtr(pc+1);
	TRACE(("%d => new pc %u\n", opnd,
		(unsigned)(pc + opnd - codePtr->codeStart)));
	TRACE(("%d => new pc %" TCL_Z_MODIFIER "u\n", opnd,
		(size_t)(pc + opnd - codePtr->codeStart)));
	NEXT_INST_F(opnd, 0, 0);

    {
	int jmpOffset[2], b;

	/* TODO: consider rewrite so we don't compute the offset we're not
	 * going to take. */
4184
4185
4186
4187
4188
4189
4190
4191
4192


4193
4194
4195
4196
4197
4198
4199
4200
4201


4202
4203
4204
4205
4206
4207
4208
4262
4263
4264
4265
4266
4267
4268


4269
4270
4271
4272
4273
4274
4275
4276
4277


4278
4279
4280
4281
4282
4283
4284
4285
4286







-
-
+
+







-
-
+
+







	    TRACE_ERROR(interp);
	    goto gotError;
	}

#ifdef TCL_COMPILE_DEBUG
	if (b) {
	    if ((*pc == INST_JUMP_TRUE1) || (*pc == INST_JUMP_TRUE4)) {
		TRACE_APPEND(("%.20s true, new pc %u\n", O2S(valuePtr),
			(unsigned)(pc + jmpOffset[1] - codePtr->codeStart)));
		TRACE_APPEND(("%.20s true, new pc %" TCL_Z_MODIFIER "u\n", O2S(valuePtr),
			(size_t)(pc + jmpOffset[1] - codePtr->codeStart)));
	    } else {
		TRACE_APPEND(("%.20s true\n", O2S(valuePtr)));
	    }
	} else {
	    if ((*pc == INST_JUMP_TRUE1) || (*pc == INST_JUMP_TRUE4)) {
		TRACE_APPEND(("%.20s false\n", O2S(valuePtr)));
	    } else {
		TRACE_APPEND(("%.20s false, new pc %u\n", O2S(valuePtr),
			(unsigned)(pc + jmpOffset[0] - codePtr->codeStart)));
		TRACE_APPEND(("%.20s false, new pc %" TCL_Z_MODIFIER "u\n", O2S(valuePtr),
			(size_t)(pc + jmpOffset[0] - codePtr->codeStart)));
	    }
	}
#endif
	NEXT_INST_F(jmpOffset[b], 1, 0);
    }
    break;

4218
4219
4220
4221
4222
4223
4224
4225
4226


4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241


4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266

4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283

4284
4285
4286
4287
4288
4289
4290
4291
4292
4293

4294
4295
4296
4297
4298
4299
4300
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







-
-
+
+













-
-
+
+
-
-
-
-
-
-
-


-














-
+
















-
+









-
+







	opnd = TclGetInt4AtPtr(pc+1);
	jtPtr = (JumptableInfo *) codePtr->auxDataArrayPtr[opnd].clientData;
	TRACE(("%d \"%.20s\" => ", opnd, O2S(OBJ_AT_TOS)));
	hPtr = Tcl_FindHashEntry(&jtPtr->hashTable, TclGetString(OBJ_AT_TOS));
	if (hPtr != NULL) {
	    int jumpOffset = PTR2INT(Tcl_GetHashValue(hPtr));

	    TRACE_APPEND(("found in table, new pc %u\n",
		    (unsigned)(pc - codePtr->codeStart + jumpOffset)));
	    TRACE_APPEND(("found in table, new pc %" TCL_Z_MODIFIER "u\n",
		    (size_t)(pc - codePtr->codeStart + jumpOffset)));
	    NEXT_INST_F(jumpOffset, 1, 0);
	} else {
	    TRACE_APPEND(("not found in table\n"));
	    NEXT_INST_F(5, 1, 0);
	}
    }
    break;

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

    case INST_NS_CURRENT: {
	Namespace *currNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
    case INST_NS_CURRENT:
	objResultPtr = TclNewNamespaceObj(TclGetCurrentNamespace(interp));

	if (currNsPtr == (Namespace *) TclGetGlobalNamespace(interp)) {
	    TclNewLiteralStringObj(objResultPtr, "::");
	} else {
	    TclNewStringObj(objResultPtr, currNsPtr->fullName,
		    strlen(currNsPtr->fullName));
	}
	TRACE_WITH_OBJ(("=> "), objResultPtr);
	NEXT_INST_F(1, 0, 1);
    }
    break;
    case INST_COROUTINE_NAME: {
	CoroutineData *corPtr = iPtr->execEnvPtr->corPtr;

	TclNewObj(objResultPtr);
	if (corPtr && !(corPtr->cmdPtr->flags & CMD_DYING)) {
	    Tcl_GetCommandFullName(interp, (Tcl_Command) corPtr->cmdPtr,
		    objResultPtr);
	}
	TRACE_WITH_OBJ(("=> "), objResultPtr);
	NEXT_INST_F(1, 0, 1);
    }
    break;
    case INST_INFO_LEVEL_NUM:
	TclNewIntObj(objResultPtr, iPtr->varFramePtr->level);
	TclNewIntObj(objResultPtr, (int)iPtr->varFramePtr->level);
	TRACE_WITH_OBJ(("=> "), objResultPtr);
	NEXT_INST_F(1, 0, 1);
    break;
    case INST_INFO_LEVEL_ARGS: {
	int level;
	CallFrame *framePtr = iPtr->varFramePtr;
	CallFrame *rootFramePtr = iPtr->rootFramePtr;

	TRACE(("\"%.30s\" => ", O2S(OBJ_AT_TOS)));
	if (TclGetIntFromObj(interp, OBJ_AT_TOS, &level) != TCL_OK) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	if (level <= 0) {
	    level += framePtr->level;
	}
	for (; (framePtr->level!=level) && (framePtr!=rootFramePtr) ;
	for (; ((int)framePtr->level!=level) && (framePtr!=rootFramePtr) ;
		framePtr = framePtr->callerVarPtr) {
	    /* Empty loop body */
	}
	if (framePtr == rootFramePtr) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad level \"%s\"", TclGetString(OBJ_AT_TOS)));
	    TRACE_ERROR(interp);
	    DECACHE_STACK_INFO();
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "STACK_LEVEL",
		    TclGetString(OBJ_AT_TOS), NULL);
		    TclGetString(OBJ_AT_TOS), (char *)NULL);
	    CACHE_STACK_INFO();
	    goto gotError;
	}
	objResultPtr = Tcl_NewListObj(framePtr->objc, framePtr->objv);
	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
	NEXT_INST_F(1, 1, 1);
    }
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
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
4436
4437
4438
4439







-
+

















-
+










-
+







	if (TclCheckEmptyString(objResultPtr) == TCL_EMPTYSTRING_YES ) {
	    Tcl_DecrRefCount(objResultPtr);
	    instOriginError:
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "invalid command name \"%s\"", TclGetString(OBJ_AT_TOS)));
	    DECACHE_STACK_INFO();
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND",
		    TclGetString(OBJ_AT_TOS), NULL);
		    TclGetString(OBJ_AT_TOS), (char *)NULL);
	    CACHE_STACK_INFO();
	    TRACE_APPEND(("ERROR: not command\n"));
	    goto gotError;
	}
	TRACE_APPEND(("\"%.30s\"", O2S(OBJ_AT_TOS)));
	NEXT_INST_F(1, 1, 1);
    }

    /*
     * -----------------------------------------------------------------
     *	   Start of TclOO support instructions.
     */

    {
	Object *oPtr;
	CallFrame *framePtr;
	CallContext *contextPtr;
	int skip, newDepth;
	Tcl_Size skip, newDepth;

    case INST_TCLOO_SELF:
	framePtr = iPtr->varFramePtr;
	if (framePtr == NULL ||
		!(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
	    TRACE(("=> ERROR: no TclOO call context\n"));
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "self may only be called from inside a method",
		    -1));
	    DECACHE_STACK_INFO();
	    Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", (char *)NULL);
	    CACHE_STACK_INFO();
	    goto gotError;
	}
	contextPtr = (CallContext *)framePtr->clientData;

	/*
	 * Call out to get the name; it's expensive to compute but cached.
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
4453
4454
4455
4456
4457
4458
4459

4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472

4473
4474
4475
4476
4477
4478
4479
4480

4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495

4496
4497

4498
4499
4500
4501
4502
4503
4504
4505







-
+












-
+







-
+














-
+

-
+







	if (framePtr == NULL ||
		!(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
	    TRACE_APPEND(("ERROR: no TclOO call context\n"));
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "nextto may only be called from inside a method",
		    -1));
	    DECACHE_STACK_INFO();
	    Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", (char *)NULL);
	    CACHE_STACK_INFO();
	    goto gotError;
	}
	contextPtr = (CallContext *)framePtr->clientData;

	oPtr = (Object *) Tcl_GetObjectFromObj(interp, valuePtr);
	if (oPtr == NULL) {
	    TRACE_APPEND(("ERROR: \"%.30s\" not object\n", O2S(valuePtr)));
	    goto gotError;
	} else {
	    Class *classPtr = oPtr->classPtr;
	    struct MInvoke *miPtr;
	    int i;
	    Tcl_Size i;
	    const char *methodType;

	    if (classPtr == NULL) {
		TRACE_APPEND(("ERROR: \"%.30s\" not class\n", O2S(valuePtr)));
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"\"%s\" is not a class", TclGetString(valuePtr)));
		DECACHE_STACK_INFO();
		Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_REQUIRED", NULL);
		Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_REQUIRED", (char *)NULL);
		CACHE_STACK_INFO();
		goto gotError;
	    }

	    for (i=contextPtr->index+1 ; i<contextPtr->callPtr->numChain ; i++) {
		miPtr = contextPtr->callPtr->chain + i;
		if (!miPtr->isFilter &&
			miPtr->mPtr->declaringClassPtr == classPtr) {
		    newDepth = i;
#ifdef TCL_COMPILE_DEBUG
		    if (tclTraceExec >= 2) {
			if (traceInstructions) {
			    strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
			} else {
			    fprintf(stdout, "%d: (%u) invoking ",
			    fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_T_MODIFIER "d) invoking ",
				    iPtr->numLevels,
				    (unsigned)(pc - codePtr->codeStart));
				    (size_t)(pc - codePtr->codeStart));
			}
			for (i = 0;  i < opnd;  i++) {
			    TclPrintObject(stdout, objv[i], 15);
			    fprintf(stdout, " ");
			}
			fprintf(stdout, "\n");
			fflush(stdout);
4445
4446
4447
4448
4449
4450
4451
4452

4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463

4464
4465
4466
4467
4468
4469
4470
4471

4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489

4490
4491
4492
4493
4494
4495
4496
4515
4516
4517
4518
4519
4520
4521

4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532

4533
4534
4535
4536
4537
4538
4539
4540

4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558

4559
4560
4561
4562
4563
4564
4565
4566







-
+










-
+







-
+

















-
+







		methodType = "destructor";
	    } else {
		methodType = "method";
	    }

	    TRACE_APPEND(("ERROR: \"%.30s\" not on reachable chain\n",
		    O2S(valuePtr)));
	    for (i=contextPtr->index ; i>=0 ; i--) {
	    for (i = contextPtr->index ; i != TCL_INDEX_NONE ; i--) {
		miPtr = contextPtr->callPtr->chain + i;
		if (miPtr->isFilter
			|| miPtr->mPtr->declaringClassPtr != classPtr) {
		    continue;
		}
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"%s implementation by \"%s\" not reachable from here",
			methodType, TclGetString(valuePtr)));
		DECACHE_STACK_INFO();
		Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_NOT_REACHABLE",
			NULL);
			(char *)NULL);
		CACHE_STACK_INFO();
		goto gotError;
	    }
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "%s has no non-filter implementation by \"%s\"",
		    methodType, TclGetString(valuePtr)));
	    DECACHE_STACK_INFO();
	    Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_NOT_THERE", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_NOT_THERE", (char *)NULL);
	    CACHE_STACK_INFO();
	    goto gotError;
	}

    case INST_TCLOO_NEXT:
	opnd = TclGetUInt1AtPtr(pc+1);
	objv = &OBJ_AT_DEPTH(opnd - 1);
	framePtr = iPtr->varFramePtr;
	skip = 1;
	TRACE(("%d => ", opnd));
	if (framePtr == NULL ||
		!(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
	    TRACE_APPEND(("ERROR: no TclOO call context\n"));
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "next may only be called from inside a method",
		    -1));
	    DECACHE_STACK_INFO();
	    Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", (char *)NULL);
	    CACHE_STACK_INFO();
	    goto gotError;
	}
	contextPtr = (CallContext *)framePtr->clientData;

	newDepth = contextPtr->index + 1;
	if (newDepth >= contextPtr->callPtr->numChain) {
4511
4512
4513
4514
4515
4516
4517
4518

4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529


4530
4531
4532
4533
4534
4535
4536
4581
4582
4583
4584
4585
4586
4587

4588
4589
4590
4591
4592
4593
4594
4595
4596
4597


4598
4599
4600
4601
4602
4603
4604
4605
4606







-
+









-
-
+
+







		methodType = "method";
	    }

	    TRACE_APPEND(("ERROR: no TclOO next impl\n"));
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "no next %s implementation", methodType));
	    DECACHE_STACK_INFO();
	    Tcl_SetErrorCode(interp, "TCL", "OO", "NOTHING_NEXT", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "OO", "NOTHING_NEXT", (char *)NULL);
	    CACHE_STACK_INFO();
	    goto gotError;
#ifdef TCL_COMPILE_DEBUG
	} else if (tclTraceExec >= 2) {
	    int i;

	    if (traceInstructions) {
		strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
	    } else {
		fprintf(stdout, "%d: (%u) invoking ",
			iPtr->numLevels, (unsigned)(pc - codePtr->codeStart));
		fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_Z_MODIFIER "u) invoking ",
			iPtr->numLevels, (pc - codePtr->codeStart));
	    }
	    for (i = 0;  i < opnd;  i++) {
		TclPrintObject(stdout, objv[i], 15);
		fprintf(stdout, " ");
	    }
	    fprintf(stdout, "\n");
	    fflush(stdout);
4572
4573
4574
4575
4576
4577
4578

4579




4580
4581
4582
4583
4584
4585
4586
4642
4643
4644
4645
4646
4647
4648
4649

4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660







+
-
+
+
+
+







	    oPtr->flags &= ~FILTER_HANDLING;
	}

	{
	    Method *const mPtr =
		    contextPtr->callPtr->chain[newDepth].mPtr;

	    if (mPtr->typePtr->version < TCL_OO_METHOD_VERSION_2) {
	    return mPtr->typePtr->callProc(mPtr->clientData, interp,
		return mPtr->typePtr->callProc(mPtr->clientData, interp,
			(Tcl_ObjectContext) contextPtr, opnd, objv);
	    }
	    return ((Tcl_MethodCallProc2 *)(void *)(mPtr->typePtr->callProc))(mPtr->clientData, interp,
		    (Tcl_ObjectContext) contextPtr, opnd, objv);
	}

    case INST_TCLOO_IS_OBJECT:
	oPtr = (Object *) Tcl_GetObjectFromObj(interp, OBJ_AT_TOS);
	objResultPtr = TCONST(oPtr != NULL ? 1 : 0);
	TRACE_WITH_OBJ(("%.30s => ", O2S(OBJ_AT_TOS)), objResultPtr);
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609

4610
4611
4612
4613
4614
4615

4616
4617
4618
4619
4620
4621
4622

4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643

4644
4645
4646
4647
4648
4649























4650
4651
4652
4653
4654




4655
4656
4657







4658





4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670















4671



4672
4673
4674
4675
4676
4677
4678
4671
4672
4673
4674
4675
4676
4677






4678
4679
4680
4681
4682
4683

4684
4685
4686
4687
4688
4689
4690

4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711

4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750



4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763












4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789







-
-
-
-
-
-
+





-
+






-
+




















-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+
+
+
+
-
-
-
+
+
+
+
+
+
+

+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+







    case INST_TCLOO_NS:
	oPtr = (Object *) Tcl_GetObjectFromObj(interp, OBJ_AT_TOS);
	if (oPtr == NULL) {
	    TRACE(("%.30s => ERROR: not object\n", O2S(OBJ_AT_TOS)));
	    goto gotError;
	}

	/*
	 * TclOO objects *never* have the global namespace as their NS.
	 */

	TclNewStringObj(objResultPtr, oPtr->namespacePtr->fullName,
		strlen(oPtr->namespacePtr->fullName));
	objResultPtr = TclNewNamespaceObj(oPtr->namespacePtr);
	TRACE_WITH_OBJ(("%.30s => ", O2S(OBJ_AT_TOS)), objResultPtr);
	NEXT_INST_F(1, 1, 1);
    }

    /*
     *     End of TclOO support instructions.
     *	   End of TclOO support instructions.
     * -----------------------------------------------------------------
     *	   Start of INST_LIST and related instructions.
     */

    {
	int numIndices, nocase, match, cflags;
	size_t slength, length2, fromIdx, toIdx, index, s1len, s2len;
	Tcl_Size slength, length2, fromIdx, toIdx, index, s1len, s2len;
	const char *s1, *s2;

    case INST_LIST:
	/*
	 * Pop the opnd (objc) top stack elements into a new list obj and then
	 * decrement their ref counts.
	 */

	opnd = TclGetUInt4AtPtr(pc+1);
	objResultPtr = Tcl_NewListObj(opnd, &OBJ_AT_DEPTH(opnd-1));
	TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
	NEXT_INST_V(5, opnd, 1);

    case INST_LIST_LENGTH:
	TRACE(("\"%.30s\" => ", O2S(OBJ_AT_TOS)));
	if (TclListObjLength(interp, OBJ_AT_TOS, &length) != TCL_OK) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	TclNewIntObj(objResultPtr, length);
	TRACE_APPEND(("%d\n", length));
	TRACE_APPEND(("%" TCL_SIZE_MODIFIER "d\n", length));
	NEXT_INST_F(1, 1, 1);

    case INST_LIST_INDEX:	/* lindex with objc == 3 */
	value2Ptr = OBJ_AT_TOS;
	valuePtr = OBJ_UNDER_TOS;
	TRACE(("\"%.30s\" \"%.30s\" => ", O2S(valuePtr), O2S(value2Ptr)));

	/* special case for AbstractList */
	if (TclObjTypeHasProc(valuePtr, indexProc)) {
	    DECACHE_STACK_INFO();
	    length = TclObjTypeLength(valuePtr);
	    if (TclGetIntForIndexM(interp, value2Ptr, length-1, &index)!=TCL_OK) {
		CACHE_STACK_INFO();
		TRACE_ERROR(interp);
		goto gotError;
	    }
	    if (TclObjTypeIndex(interp, valuePtr, index, &objResultPtr)!=TCL_OK) {
		CACHE_STACK_INFO();
		TRACE_ERROR(interp);
		goto gotError;
	    }
	    CACHE_STACK_INFO();
	    if (objResultPtr == NULL) {
		/* Index is out of range, return empty result. */
		TclNewObj(objResultPtr);
	    }
	    Tcl_IncrRefCount(objResultPtr); // reference held here
	    goto lindexDone;
	}

	/*
	 * Extract the desired list element.
	 */

	{
	    Tcl_Size value2Length;
	    Tcl_Obj *indexListPtr = value2Ptr;

	if ((TclListObjGetElements(interp, valuePtr, &objc, &objv) == TCL_OK)
		&& !TclHasIntRep(value2Ptr, &tclListType)) {
	    int code;
	    if ((TclListObjGetElements(interp, valuePtr, &objc, &objv) == TCL_OK)
		    && (!TclHasInternalRep(value2Ptr, &tclListType)
		    || (Tcl_ListObjLength(interp, value2Ptr, &value2Length),
			value2Length == 1
			    ? (indexListPtr = TclListObjGetElement(value2Ptr, 0), 1)
			    : 0))) {
		int code;

		/* increment the refCount of value2Ptr because TclListObjGetElement may
		 * have just extracted it from a list in the condition for this block.
		 */
		Tcl_IncrRefCount(indexListPtr);

	    DECACHE_STACK_INFO();
	    code = TclGetIntForIndexM(interp, value2Ptr, objc-1, &index);
	    CACHE_STACK_INFO();
	    if (code == TCL_OK) {
		TclDecrRefCount(value2Ptr);
		tosPtr--;
		pcAdjustment = 1;
		goto lindexFastPath;
	    }
	    Tcl_ResetResult(interp);
	}

		DECACHE_STACK_INFO();
		code = TclGetIntForIndexM(interp, indexListPtr, objc-1, &index);
		TclDecrRefCount(indexListPtr);
		CACHE_STACK_INFO();
		if (code == TCL_OK) {
		    Tcl_DecrRefCount(value2Ptr);
		    tosPtr--;
		    pcAdjustment = 1;
		    goto lindexFastPath;
		}
		Tcl_ResetResult(interp);
	    }
	}

	DECACHE_STACK_INFO();
	objResultPtr = TclLindexList(interp, valuePtr, value2Ptr);
	CACHE_STACK_INFO();

    lindexDone:
	if (!objResultPtr) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}

	/*
	 * Stash the list element on the stack.
4693
4694
4695
4696
4697
4698
4699

























4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711

4712
4713
4714
4715


4716
4717
4718
4719
4720
4721
4722
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846

4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
+




+
+







	TRACE(("\"%.30s\" %d => ", O2S(valuePtr), opnd));

	/*
	 * Get the contents of the list, making sure that it really is a list
	 * in the process.
	 */

	/* special case for AbstractList */
	if (TclObjTypeHasProc(valuePtr, indexProc)) {
	    length = TclObjTypeLength(valuePtr);

	    /* Decode end-offset index values. */
	    index = TclIndexDecode(opnd, length-1);

	    if (index >= 0 && index < length) {
		/* Compute value @ index */
		DECACHE_STACK_INFO();
		if (TclObjTypeIndex(interp, valuePtr, index, &objResultPtr)!=TCL_OK) {
		    CACHE_STACK_INFO();
		    TRACE_ERROR(interp);
		    goto gotError;
		}
		CACHE_STACK_INFO();
	    } else {
		TclNewObj(objResultPtr);
	    }

	    pcAdjustment = 5;
	    goto lindexFastPath2;
	}

	/* List case */
	if (TclListObjGetElements(interp, valuePtr, &objc, &objv) != TCL_OK) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}

	/* Decode end-offset index values. */

	index = TclIndexDecode(opnd, objc - 1);
	pcAdjustment = 5;

    lindexFastPath:
	if (index < (size_t)objc) {
	if (index >= 0 && index < objc) {
	    objResultPtr = objv[index];
	} else {
	    TclNewObj(objResultPtr);
	}

    lindexFastPath2:

	TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr)));
	NEXT_INST_F(pcAdjustment, 1, 1);

    case INST_LIST_INDEX_MULTI:	/* 'lindex' with multiple index args */
	/*
	 * Determine the count of index args.
4763
4764
4765
4766
4767
4768
4769






4770
4771



4772

4773
4774
4775
4776
4777
4778
4779
4780

4781
4782
4783
4784
4785
4786
4787
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913


4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925

4926
4927
4928
4929
4930
4931
4932
4933







+
+
+
+
+
+
-
-
+
+
+

+







-
+







	valuePtr = POP_OBJECT();
	Tcl_DecrRefCount(valuePtr); /* This one should be done here */

	/*
	 * Compute the new variable value.
	 */

	DECACHE_STACK_INFO();
	if (TclObjTypeHasProc(valuePtr, setElementProc)) {
	    objResultPtr = TclObjTypeSetElement(interp,
		    valuePtr, numIndices,
		    &OBJ_AT_DEPTH(numIndices), OBJ_AT_TOS);
	} else {
	objResultPtr = TclLsetFlat(interp, valuePtr, numIndices,
		&OBJ_AT_DEPTH(numIndices), OBJ_AT_TOS);
	    objResultPtr = TclLsetFlat(interp, valuePtr, numIndices,
		    &OBJ_AT_DEPTH(numIndices), OBJ_AT_TOS);
	}
	if (!objResultPtr) {
	    CACHE_STACK_INFO();
	    TRACE_ERROR(interp);
	    goto gotError;
	}

	/*
	 * Set result.
	 */

	CACHE_STACK_INFO();
	TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr)));
	NEXT_INST_V(5, numIndices+1, -1);

    case INST_LSET_LIST:	/* 'lset' with 4 args */
	/*
	 * Get the old value of variable, and remove the stack ref. This is
	 * safe because the variable still references the object; the ref
4843
4844
4845
4846
4847
4848
4849
4850

4851
4852
4853
4854
4855
4856
4857
4989
4990
4991
4992
4993
4994
4995

4996
4997
4998
4999
5000
5001
5002
5003







-
+








	/*
	 * Skip a lot of work if we're about to throw the result away (common
	 * with uses of [lassign]).
	 */

#ifndef TCL_COMPILE_DEBUG
	if (*(pc+9) == INST_POP) {
	if (pc[9] == INST_POP) {
	    NEXT_INST_F(10, 1, 0);
	}
#endif

	/* Every range of an empty list is an empty list */
	if (objc == 0) {
	    /* avoid return of not canonical list (e. g. spaces in string repr.) */
4869
4870
4871
4872
4873
4874
4875
4876

4877
4878
4879
4880

4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891






4892
4893









4894
4895
4896
4897
4898
4899
4900
4901
4902
4903









4904
4905
4906
4907
4908
4909
4910
4911









4912
4913
4914
4915



4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929




























4930
4931
4932
4933
4934
4935
4936
5015
5016
5017
5018
5019
5020
5021

5022
5023
5024
5025

5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043


5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071








5072
5073
5074
5075
5076
5077
5078
5079
5080
5081



5082
5083
5084
5085













5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120







-
+



-
+











+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+










+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    TclNewObj(objResultPtr);
	    TRACE_APPEND(("\"%.30s\"", O2S(objResultPtr)));
	    NEXT_INST_F(9, 1, 1);
	}
	toIdx = TclIndexDecode(toIdx, objc - 1);
	if (toIdx == TCL_INDEX_NONE) {
	    goto emptyList;
	} else if (toIdx + 1 >= (size_t)objc + 1) {
	} else if (toIdx >= objc) {
	    toIdx = objc - 1;
	}

	assert (toIdx < (size_t)objc);
	assert (toIdx >= 0 && toIdx < objc);
	/*
	assert ( fromIdx != TCL_INDEX_NONE );
	 *
	 * Extra safety for legacy bytecodes:
	 */
	if (fromIdx == TCL_INDEX_NONE) {
	    fromIdx = TCL_INDEX_START;
	}

	fromIdx = TclIndexDecode(fromIdx, objc - 1);

	DECACHE_STACK_INFO();
	if (TclObjTypeHasProc(valuePtr, sliceProc)) {
	    if (TclObjTypeSlice(interp, valuePtr, fromIdx, toIdx, &objResultPtr) != TCL_OK) {
		objResultPtr = NULL;
	    }
	} else {
	objResultPtr = TclListObjRange(valuePtr, fromIdx, toIdx);

	    objResultPtr = TclListObjRange(interp, valuePtr, fromIdx, toIdx);
	}
	if (objResultPtr == NULL) {
	    CACHE_STACK_INFO();
	    TRACE_ERROR(interp);
	    goto gotError;
	}

	CACHE_STACK_INFO();
	TRACE_APPEND(("\"%.30s\"", O2S(objResultPtr)));
	NEXT_INST_F(9, 1, 1);

    case INST_LIST_IN:
    case INST_LIST_NOT_IN:	/* Basic list containment operators. */
	value2Ptr = OBJ_AT_TOS;
	valuePtr = OBJ_UNDER_TOS;

	s1 = TclGetStringFromObj(valuePtr, &s1len);
	TRACE(("\"%.30s\" \"%.30s\" => ", O2S(valuePtr), O2S(value2Ptr)));

	if (TclObjTypeHasProc(value2Ptr, inOperProc) != NULL) {
	    int status = TclObjTypeInOperator(interp, valuePtr, value2Ptr, &match);
	    if (status != TCL_OK) {
		TRACE_ERROR(interp);
		goto gotError;
	    }
	} else {

	if (TclListObjLength(interp, value2Ptr, &length) != TCL_OK) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	match = 0;
	if (length > 0) {
	    int i = 0;
	    Tcl_Obj *o;
	    if (TclListObjLength(interp, value2Ptr, &length) != TCL_OK) {
		TRACE_ERROR(interp);
		goto gotError;
	    }
	    match = 0;
	    if (length > 0) {
		Tcl_Size i = 0;
		Tcl_Obj *o;
		int isAbstractList = TclObjTypeHasProc(value2Ptr, indexProc) != NULL;

	    /*
	     * An empty list doesn't match anything.
	     */
		/*
		 * An empty list doesn't match anything.
		 */

	    do {
		Tcl_ListObjIndex(NULL, value2Ptr, i, &o);
		if (o != NULL) {
		    s2 = TclGetStringFromObj(o, &s2len);
		} else {
		    s2 = "";
		    s2len = 0;
		}
		if (s1len == s2len) {
		    match = (memcmp(s1, s2, s1len) == 0);
		}
		i++;
	    } while (i < length && match == 0);
		do {
		    if (isAbstractList) {
			DECACHE_STACK_INFO();
			if (TclObjTypeIndex(interp, value2Ptr, i, &o) != TCL_OK) {
			    CACHE_STACK_INFO();
			    TRACE_ERROR(interp);
			    goto gotError;
			}
			CACHE_STACK_INFO();
		    } else {
			Tcl_ListObjIndex(NULL, value2Ptr, i, &o);
		    }
		    if (o != NULL) {
			s2 = TclGetStringFromObj(o, &s2len);
		    } else {
			s2 = "";
			s2len = 0;
		    }
		    if (s1len == s2len) {
			match = (memcmp(s1, s2, s1len) == 0);
		    }

		    /* Could be an ephemeral abstract obj */
		    Tcl_BounceRefCount(o);

		    i++;
		} while (i < length && match == 0);
	    }
	}

	if (*pc == INST_LIST_NOT_IN) {
	    match = !match;
	}

	TRACE_APPEND(("%d\n", match));
4962
4963
4964
4965
4966
4967
4968














































































4969
4970
4971
4972
4973





4974
4975
4976
4977
4978
4979
4980
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230





5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+







		TRACE_ERROR(interp);
		goto gotError;
	    }
	    TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr)));
	    NEXT_INST_F(1, 1, 0);
	}

    case INST_LREPLACE4: {
	size_t numToDelete, numNewElems;
	int end_indicator;
	int haveSecondIndex, flags;
	Tcl_Obj *fromIdxObj, *toIdxObj;
	opnd = TclGetInt4AtPtr(pc + 1);
	flags = TclGetInt1AtPtr(pc + 5);

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

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

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

	DECACHE_STACK_INFO();

	if (TclGetIntForIndexM(interp, fromIdxObj, length - end_indicator,
		&fromIdx) != TCL_OK) {
	    CACHE_STACK_INFO();
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	if (fromIdx == TCL_INDEX_NONE) {
	    fromIdx = 0;
	} else if (fromIdx > length) {
	    fromIdx = length;
	}
	numToDelete = 0;
	if (toIdxObj) {
	    if (TclGetIntForIndexM(interp, toIdxObj, length - end_indicator,
		    &toIdx) != TCL_OK) {
		CACHE_STACK_INFO();
		TRACE_ERROR(interp);
		goto gotError;
	    }
	    if (toIdx != TCL_INDEX_NONE) {
		if (toIdx > length) {
		    toIdx = length;
		}
		if (toIdx >= fromIdx) {
		    numToDelete = (size_t)toIdx - (size_t)fromIdx + 1;
		}
	    }
	}

	CACHE_STACK_INFO();

	if (Tcl_IsShared(valuePtr)) {
	    objResultPtr = Tcl_DuplicateObj(valuePtr);
	    if (Tcl_ListObjReplace(interp, objResultPtr, fromIdx, numToDelete,
		    numNewElems, &OBJ_AT_DEPTH(numNewElems - 1)) != TCL_OK) {
		TRACE_ERROR(interp);
		Tcl_DecrRefCount(objResultPtr);
		goto gotError;
	    }
	    TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr)));
	    NEXT_INST_V(6, opnd, 1);
	} else {
	    if (Tcl_ListObjReplace(interp, valuePtr, fromIdx, numToDelete,
		    numNewElems, &OBJ_AT_DEPTH(numNewElems - 1)) != TCL_OK) {
		TRACE_ERROR(interp);
		goto gotError;
	    }
	    TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr)));
	    NEXT_INST_V(6, opnd - 1, 0);
	}
	}

    /*
     *	   End of INST_LIST and related instructions.
     * -----------------------------------------------------------------
     *	   Start of string-related instructions.
     */
	/*
	 *	   End of INST_LIST and related instructions.
	 * -----------------------------------------------------------------
	 *	   Start of string-related instructions.
	 */

    case INST_STR_EQ:
    case INST_STR_NEQ:		/* String (in)equality check */
    case INST_STR_CMP:		/* String compare. */
    case INST_STR_LT:
    case INST_STR_GT:
    case INST_STR_LE:
5047
5048
5049
5050
5051
5052
5053
5054

5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071

5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088

5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099

5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111

5112
5113
5114
5115

5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148

5149
5150
5151
5152
5153
5154

5155
5156
5157
5158
5159
5160
5161
5162

5163
5164
5165
5166
5167
5168
5169

5170
5171

5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219

5220
5221
5222

5223
5224
5225
5226
5227

5228
5229
5230
5231
5232
5233
5234

5235
5236
5237
5238
5239
5240
5241
5242
5243
5244

5245
5246

5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259

5260
5261
5262
5263
5264
5265
5266
5267
5268


5269
5270
5271

5272
5273
5274
5275

5276
5277
5278
5279
5280
5281
5282
5309
5310
5311
5312
5313
5314
5315

5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332

5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349

5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360

5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372

5373
5374
5375
5376

5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393



5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406

5407

5408
5409
5410
5411

5412

5413
5414
5415
5416
5417
5418

5419







5420
5421

5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441









5442

















5443

5444



5445


5446


5447
5448
5449
5450
5451
5452
5453

5454
5455
5456
5457
5458
5459
5460
5461
5462
5463

5464


5465

5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476

5477


5478
5479
5480
5481
5482


5483
5484
5485
5486

5487
5488
5489
5490

5491
5492
5493
5494
5495
5496
5497
5498







-
+
















-
+
















-
+










-
+











-
+



-
+
















-
-
-













-
+
-




-
+
-






-
+
-
-
-
-
-
-
-
+

-
+



















-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
+
-
-
-
+
-
-

-
-
+






-
+









-
+
-
-
+
-











-
+
-
-





-
-
+
+


-
+



-
+







	    slength = Tcl_UtfToUpper(TclGetString(objResultPtr));
	    Tcl_SetObjLength(objResultPtr, slength);
	    TRACE_APPEND(("\"%.20s\"\n", O2S(objResultPtr)));
	    NEXT_INST_F(1, 1, 1);
	} else {
	    slength = Tcl_UtfToUpper(TclGetString(valuePtr));
	    Tcl_SetObjLength(valuePtr, slength);
	    TclFreeIntRep(valuePtr);
	    TclFreeInternalRep(valuePtr);
	    TRACE_APPEND(("\"%.20s\"\n", O2S(valuePtr)));
	    NEXT_INST_F(1, 0, 0);
	}
    case INST_STR_LOWER:
	valuePtr = OBJ_AT_TOS;
	TRACE(("\"%.20s\" => ", O2S(valuePtr)));
	if (Tcl_IsShared(valuePtr)) {
	    s1 = TclGetStringFromObj(valuePtr, &slength);
	    TclNewStringObj(objResultPtr, s1, slength);
	    slength = Tcl_UtfToLower(TclGetString(objResultPtr));
	    Tcl_SetObjLength(objResultPtr, slength);
	    TRACE_APPEND(("\"%.20s\"\n", O2S(objResultPtr)));
	    NEXT_INST_F(1, 1, 1);
	} else {
	    slength = Tcl_UtfToLower(TclGetString(valuePtr));
	    Tcl_SetObjLength(valuePtr, slength);
	    TclFreeIntRep(valuePtr);
	    TclFreeInternalRep(valuePtr);
	    TRACE_APPEND(("\"%.20s\"\n", O2S(valuePtr)));
	    NEXT_INST_F(1, 0, 0);
	}
    case INST_STR_TITLE:
	valuePtr = OBJ_AT_TOS;
	TRACE(("\"%.20s\" => ", O2S(valuePtr)));
	if (Tcl_IsShared(valuePtr)) {
	    s1 = TclGetStringFromObj(valuePtr, &slength);
	    TclNewStringObj(objResultPtr, s1, slength);
	    slength = Tcl_UtfToTitle(TclGetString(objResultPtr));
	    Tcl_SetObjLength(objResultPtr, slength);
	    TRACE_APPEND(("\"%.20s\"\n", O2S(objResultPtr)));
	    NEXT_INST_F(1, 1, 1);
	} else {
	    slength = Tcl_UtfToTitle(TclGetString(valuePtr));
	    Tcl_SetObjLength(valuePtr, slength);
	    TclFreeIntRep(valuePtr);
	    TclFreeInternalRep(valuePtr);
	    TRACE_APPEND(("\"%.20s\"\n", O2S(valuePtr)));
	    NEXT_INST_F(1, 0, 0);
	}

    case INST_STR_INDEX:
	value2Ptr = OBJ_AT_TOS;
	valuePtr = OBJ_UNDER_TOS;
	TRACE(("\"%.20s\" %.20s => ", O2S(valuePtr), O2S(value2Ptr)));

	/*
	 * Get char length to calulate what 'end' means.
	 * Get char length to calculate what 'end' means.
	 */

	slength = Tcl_GetCharLength(valuePtr);
	DECACHE_STACK_INFO();
	if (TclGetIntForIndexM(interp, value2Ptr, slength-1, &index)!=TCL_OK) {
	    CACHE_STACK_INFO();
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	CACHE_STACK_INFO();

	if (index >= slength) {
	if (index < 0 || index >= slength) {
	    TclNewObj(objResultPtr);
	} else if (TclIsPureByteArray(valuePtr)) {
	    objResultPtr = Tcl_NewByteArrayObj(
		    Tcl_GetByteArrayFromObj(valuePtr, NULL)+index, 1);
		    Tcl_GetBytesFromObj(NULL, valuePtr, (Tcl_Size *)NULL)+index, 1);
	} else if (valuePtr->bytes && slength == valuePtr->length) {
	    objResultPtr = Tcl_NewStringObj((const char *)
		    valuePtr->bytes+index, 1);
	} else {
	    char buf[4] = "";
	    int ch = Tcl_GetUniChar(valuePtr, index);

	    /*
	     * This could be: Tcl_NewUnicodeObj((const Tcl_UniChar *)&ch, 1)
	     * but creating the object as a string seems to be faster in
	     * practical use.
	     */
	    if (ch == -1) {
		TclNewObj(objResultPtr);
	    } else {
		slength = Tcl_UniCharToUtf(ch, buf);
		if ((ch >= 0xD800) && (slength < 3)) {
		    slength += Tcl_UniCharToUtf(-1, buf + slength);
		}
		objResultPtr = Tcl_NewStringObj(buf, slength);
	    }
	}

	TRACE_APPEND(("\"%s\"\n", O2S(objResultPtr)));
	NEXT_INST_F(1, 2, 1);

    case INST_STR_RANGE:
	TRACE(("\"%.20s\" %.20s %.20s =>",
		O2S(OBJ_AT_DEPTH(2)), O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS)));
	slength = Tcl_GetCharLength(OBJ_AT_DEPTH(2)) - 1;

	DECACHE_STACK_INFO();
	if (TclGetIntForIndexM(interp, OBJ_UNDER_TOS, slength,
	if (TclGetIntForIndexM(interp, OBJ_UNDER_TOS, slength, &fromIdx) != TCL_OK) {
		    &fromIdx) != TCL_OK) {
	    CACHE_STACK_INFO();
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	if (TclGetIntForIndexM(interp, OBJ_AT_TOS, slength,
	if (TclGetIntForIndexM(interp, OBJ_AT_TOS, slength, &toIdx) != TCL_OK) {
		    &toIdx) != TCL_OK) {
	    CACHE_STACK_INFO();
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	CACHE_STACK_INFO();

	if (fromIdx == TCL_INDEX_NONE) {
	if (toIdx == TCL_INDEX_NONE) {
	    fromIdx = TCL_INDEX_START;
	}
	if (toIdx + 1 >= slength + 1) {
	    toIdx = slength;
	}
	if (toIdx + 1 >= fromIdx + 1) {
	    objResultPtr = Tcl_GetRange(OBJ_AT_DEPTH(2), fromIdx, toIdx);
	    TclNewObj(objResultPtr);
	} else {
	    TclNewObj(objResultPtr);
	    objResultPtr = Tcl_GetRange(OBJ_AT_DEPTH(2), fromIdx, toIdx);
	}
	TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr)));
	NEXT_INST_V(1, 3, 1);

    case INST_STR_RANGE_IMM:
	valuePtr = OBJ_AT_TOS;
	fromIdx = TclGetInt4AtPtr(pc+1);
	toIdx = TclGetInt4AtPtr(pc+5);
	slength = Tcl_GetCharLength(valuePtr);
	TRACE(("\"%.20s\" %d %d => ", O2S(valuePtr), (int)(fromIdx), (int)(toIdx)));

	/* Every range of an empty value is an empty value */
	if (slength == 0) {
	    TRACE_APPEND(("\n"));
	    NEXT_INST_F(9, 0, 0);
	}

	/* Decode index operands. */

	/*
	assert ( toIdx != TCL_INDEX_NONE );
	 *
	 * Extra safety for legacy bytecodes:
	 */
	if (toIdx == TCL_INDEX_NONE) {
	    goto emptyRange;
	}

	toIdx = TclIndexDecode(toIdx, slength - 1);
	if (toIdx == TCL_INDEX_NONE) {
	    goto emptyRange;
	} else if (toIdx >= slength) {
	    toIdx = slength - 1;
	}

	assert ( toIdx != TCL_INDEX_NONE && toIdx < slength );

	/*
	assert ( fromIdx != TCL_INDEX_NONE );
	 *
	 * Extra safety for legacy bytecodes:
	 */
	if (fromIdx == TCL_INDEX_NONE) {
	    fromIdx = TCL_INDEX_START;
	}

	fromIdx = TclIndexDecode(fromIdx, slength - 1);
	if (fromIdx == TCL_INDEX_NONE) {
	if (toIdx == TCL_INDEX_NONE) {
	    fromIdx = TCL_INDEX_START;
	}

	    TclNewObj(objResultPtr);
	if (fromIdx + 1 <= toIdx + 1) {
	    objResultPtr = Tcl_GetRange(valuePtr, fromIdx, toIdx);
	} else {
	emptyRange:
	    TclNewObj(objResultPtr);
	    objResultPtr = Tcl_GetRange(valuePtr, fromIdx, toIdx);
	}
	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
	NEXT_INST_F(9, 1, 1);

    {
	Tcl_UniChar *ustring1, *ustring2, *ustring3, *end, *p;
	size_t length3;
	Tcl_Size length3;
	Tcl_Obj *value3Ptr;

    case INST_STR_REPLACE:
	value3Ptr = POP_OBJECT();
	valuePtr = OBJ_AT_DEPTH(2);
	slength = Tcl_GetCharLength(valuePtr) - 1;
	TRACE(("\"%.20s\" %s %s \"%.20s\" => ", O2S(valuePtr),
		O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), O2S(value3Ptr)));
	DECACHE_STACK_INFO();
	if (TclGetIntForIndexM(interp, OBJ_UNDER_TOS, slength,
	if (TclGetIntForIndexM(interp, OBJ_UNDER_TOS, slength, &fromIdx) != TCL_OK
		    &fromIdx) != TCL_OK
	    || TclGetIntForIndexM(interp, OBJ_AT_TOS, slength,
		|| TclGetIntForIndexM(interp, OBJ_AT_TOS, slength, &toIdx) != TCL_OK) {
		    &toIdx) != TCL_OK) {
	    CACHE_STACK_INFO();
	    TclDecrRefCount(value3Ptr);
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	CACHE_STACK_INFO();
	TclDecrRefCount(OBJ_AT_TOS);
	(void) POP_OBJECT();
	TclDecrRefCount(OBJ_AT_TOS);
	(void) POP_OBJECT();

	if ((toIdx == TCL_INDEX_NONE) ||
	if ((toIdx < 0) || (fromIdx > slength) || (toIdx < fromIdx)) {
		(fromIdx + 1 > slength + 1) ||
		(toIdx + 1 < fromIdx + 1)) {
	    TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr)));
	    TclDecrRefCount(value3Ptr);
	    NEXT_INST_F(1, 0, 0);
	}

	if (fromIdx == TCL_INDEX_NONE) {
	    fromIdx = TCL_INDEX_START;
	if (fromIdx < 0) {
	    fromIdx = 0;
	}

	if (toIdx + 1 > slength + 1) {
	if (toIdx > slength) {
	    toIdx = slength;
	}

	if ((fromIdx == TCL_INDEX_START) && (toIdx == slength)) {
	if ((fromIdx == 0) && (toIdx == slength)) {
	    TclDecrRefCount(OBJ_AT_TOS);
	    OBJ_AT_TOS = value3Ptr;
	    TRACE_APPEND(("\"%.30s\"\n", O2S(value3Ptr)));
	    NEXT_INST_F(1, 0, 0);
	}

	objResultPtr = TclStringReplace(interp, valuePtr, fromIdx,
5300
5301
5302
5303
5304
5305
5306
5307

5308
5309
5310
5311
5312

5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324

5325
5326
5327
5328
5329
5330
5331
5332





5333
5334

5335
5336
5337
5338
5339
5340
5341

5342
5343
5344
5345
5346
5347
5348
5349

5350
5351
5352
5353
5354
5355
5356
5357
5358
5359

5360
5361
5362
5363
5364

5365
5366

5367
5368
5369
5370
5371
5372
5373
5374
5375

5376
5377
5378
5379
5380
5381

5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403


5404
5405
5406
5407


5408
5409
5410

5411
5412

5413
5414
5415


5416
5417
5418
5419
5420
5421
5422
5516
5517
5518
5519
5520
5521
5522

5523
5524
5525
5526
5527

5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539

5540
5541
5542
5543
5544
5545



5546
5547
5548
5549
5550
5551

5552
5553
5554
5555
5556
5557
5558

5559
5560
5561
5562
5563
5564
5565
5566

5567
5568
5569
5570
5571
5572
5573
5574
5575
5576

5577
5578
5579
5580
5581

5582
5583

5584
5585
5586
5587
5588
5589
5590
5591
5592

5593
5594
5595
5596
5597
5598

5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619


5620
5621
5622
5623


5624
5625
5626
5627

5628
5629

5630
5631


5632
5633
5634
5635
5636
5637
5638
5639
5640







-
+




-
+











-
+





-
-
-
+
+
+
+
+

-
+






-
+







-
+









-
+




-
+

-
+








-
+





-
+




















-
-
+
+


-
-
+
+


-
+

-
+

-
-
+
+







	if (value3Ptr == value2Ptr) {
	    objResultPtr = valuePtr;
	    goto doneStringMap;
	} else if (valuePtr == value2Ptr) {
	    objResultPtr = value3Ptr;
	    goto doneStringMap;
	}
	ustring1 = TclGetUnicodeFromObj(valuePtr, &slength);
	ustring1 = Tcl_GetUnicodeFromObj(valuePtr, &slength);
	if (slength == 0) {
	    objResultPtr = valuePtr;
	    goto doneStringMap;
	}
	ustring2 = TclGetUnicodeFromObj(value2Ptr, &length2);
	ustring2 = Tcl_GetUnicodeFromObj(value2Ptr, &length2);
	if (length2 > slength || length2 == 0) {
	    objResultPtr = valuePtr;
	    goto doneStringMap;
	} else if (length2 == slength) {
	    if (memcmp(ustring1, ustring2, sizeof(Tcl_UniChar) * slength)) {
		objResultPtr = valuePtr;
	    } else {
		objResultPtr = value3Ptr;
	    }
	    goto doneStringMap;
	}
	ustring3 = TclGetUnicodeFromObj(value3Ptr, &length3);
	ustring3 = Tcl_GetUnicodeFromObj(value3Ptr, &length3);

	objResultPtr = Tcl_NewUnicodeObj(ustring1, 0);
	p = ustring1;
	end = ustring1 + slength;
	for (; ustring1 < end; ustring1++) {
	    if ((*ustring1 == *ustring2) && (length2==1 ||
		    memcmp(ustring1, ustring2, sizeof(Tcl_UniChar) * length2)
			    == 0)) {
	    if ((*ustring1 == *ustring2) &&
		    /* Fix bug [69218ab7b]: restrict max compare length. */
		    ((end - ustring1) >= length2) && (length2 == 1 ||
			memcmp(ustring1, ustring2,
				sizeof(Tcl_UniChar) * length2) == 0)) {
		if (p != ustring1) {
		    TclAppendUnicodeToObj(objResultPtr, p, ustring1-p);
		    Tcl_AppendUnicodeToObj(objResultPtr, p, ustring1-p);
		    p = ustring1 + length2;
		} else {
		    p += length2;
		}
		ustring1 = p - 1;

		TclAppendUnicodeToObj(objResultPtr, ustring3, length3);
		Tcl_AppendUnicodeToObj(objResultPtr, ustring3, length3);
	    }
	}
	if (p != ustring1) {
	    /*
	     * Put the rest of the unmapped chars onto result.
	     */

	    TclAppendUnicodeToObj(objResultPtr, p, ustring1 - p);
	    Tcl_AppendUnicodeToObj(objResultPtr, p, ustring1 - p);
	}
    doneStringMap:
	TRACE_WITH_OBJ(("%.20s %.20s %.20s => ",
		O2S(value2Ptr), O2S(value3Ptr), O2S(valuePtr)), objResultPtr);
	NEXT_INST_V(1, 3, 1);

    case INST_STR_FIND:
	objResultPtr = TclStringFirst(OBJ_UNDER_TOS, OBJ_AT_TOS, 0);

	TRACE(("%.20s %.20s => %d\n",
	TRACE(("%.20s %.20s => %s\n",
		O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), O2S(objResultPtr)));
	NEXT_INST_F(1, 2, 1);

    case INST_STR_FIND_LAST:
	objResultPtr = TclStringLast(OBJ_UNDER_TOS, OBJ_AT_TOS, INT_MAX - 1);
	objResultPtr = TclStringLast(OBJ_UNDER_TOS, OBJ_AT_TOS, TCL_SIZE_MAX - 1);

	TRACE(("%.20s %.20s => %d\n",
	TRACE(("%.20s %.20s => %s\n",
		O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), O2S(objResultPtr)));
	NEXT_INST_F(1, 2, 1);

    case INST_STR_CLASS:
	opnd = TclGetInt1AtPtr(pc+1);
	valuePtr = OBJ_AT_TOS;
	TRACE(("%s \"%.30s\" => ", tclStringClassTable[opnd].name,
		O2S(valuePtr)));
	ustring1 = TclGetUnicodeFromObj(valuePtr, &slength);
	ustring1 = Tcl_GetUnicodeFromObj(valuePtr, &slength);
	match = 1;
	if (slength > 0) {
	    int ch;
	    end = ustring1 + slength;
	    for (p=ustring1 ; p<end ; ) {
		p += TclUniCharToUCS4(p, &ch);
		ch = *p++;
		if (!tclStringClassTable[opnd].comparator(ch)) {
		    match = 0;
		    break;
		}
	    }
	}
	TRACE_APPEND(("%d\n", match));
	JUMP_PEEPHOLE_F(match, 2, 1);
    }

    case INST_STR_MATCH:
	nocase = TclGetInt1AtPtr(pc+1);
	valuePtr = OBJ_AT_TOS;		/* String */
	value2Ptr = OBJ_UNDER_TOS;	/* Pattern */

	/*
	 * Check that at least one of the objects is Unicode before promoting
	 * both.
	 */

	if (TclHasIntRep(valuePtr, &tclStringType)
		|| TclHasIntRep(value2Ptr, &tclStringType)) {
	if (TclHasInternalRep(valuePtr, &tclStringType)
		|| TclHasInternalRep(value2Ptr, &tclStringType)) {
	    Tcl_UniChar *ustring1, *ustring2;

	    ustring1 = TclGetUnicodeFromObj(valuePtr, &slength);
	    ustring2 = TclGetUnicodeFromObj(value2Ptr, &length2);
	    ustring1 = Tcl_GetUnicodeFromObj(valuePtr, &slength);
	    ustring2 = Tcl_GetUnicodeFromObj(value2Ptr, &length2);
	    match = TclUniCharMatch(ustring1, slength, ustring2, length2,
		    nocase);
	} else if (TclIsPureByteArray(valuePtr) && !nocase) {
	} else if (TclIsPureByteArray(valuePtr) && TclIsPureByteArray(value2Ptr) && !nocase) {
	    unsigned char *bytes1, *bytes2;
	    size_t wlen1 = 0, wlen2 = 0;
	    Tcl_Size wlen1 = 0, wlen2 = 0;

	    bytes1 = TclGetByteArrayFromObj(valuePtr, &wlen1);
	    bytes2 = TclGetByteArrayFromObj(value2Ptr, &wlen2);
	    bytes1 = Tcl_GetBytesFromObj(NULL, valuePtr, &wlen1);
	    bytes2 = Tcl_GetBytesFromObj(NULL, value2Ptr, &wlen2);
	    match = TclByteArrayMatch(bytes1, wlen1, bytes2, wlen2, 0);
	} else {
	    match = Tcl_StringCaseMatch(TclGetString(valuePtr),
		    TclGetString(value2Ptr), nocase);
	}

	/*
5430
5431
5432
5433
5434
5435
5436
5437

5438
5439
5440
5441
5442
5443
5444
5648
5649
5650
5651
5652
5653
5654

5655
5656
5657
5658
5659
5660
5661
5662







-
+







	 * Peep-hole optimisation: if you're about to jump, do jump from here.
	 */

	JUMP_PEEPHOLE_F(match, 2, 2);

    {
	const char *string1, *string2;
	size_t trim1, trim2;
	Tcl_Size trim1, trim2;

    case INST_STR_TRIM_LEFT:
	valuePtr = OBJ_UNDER_TOS;	/* String */
	value2Ptr = OBJ_AT_TOS;		/* TrimSet */
	string2 = TclGetStringFromObj(value2Ptr, &length2);
	string1 = TclGetStringFromObj(valuePtr, &slength);
	trim1 = TclTrimLeft(string1, slength, string2, length2);
5529
5530
5531
5532
5533
5534
5535
5536

5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5747
5748
5749
5750
5751
5752
5753

5754
5755
5756
5757
5758
5759
5760








5761
5762
5763
5764
5765
5766
5767







-
+






-
-
-
-
-
-
-
-







    /*
     *	   End of string-related instructions.
     * -----------------------------------------------------------------
     *	   Start of numeric operator instructions.
     */

    {
	ClientData ptr1, ptr2;
	void *ptr1, *ptr2;
	int type1, type2;
	Tcl_WideInt w1, w2, wResult;

    case INST_NUM_TYPE:
	if (GetNumberFromObj(NULL, OBJ_AT_TOS, &ptr1, &type1) != TCL_OK) {
	    type1 = 0;
	} else if (type1 == TCL_NUMBER_BIG) {
	    /* value is an integer outside the WIDE_MIN to WIDE_MAX range */
	    /* [string is wideinteger] is WIDE_MIN to WIDE_MAX range */
	    Tcl_WideInt w;

	    if (TclGetWideIntFromObj(NULL, OBJ_AT_TOS, &w) == TCL_OK) {
		type1 = TCL_NUMBER_INT;
	    }
	}
	TclNewIntObj(objResultPtr, type1);
	TRACE(("\"%.20s\" => %d\n", O2S(OBJ_AT_TOS), type1));
	NEXT_INST_F(1, 1, 1);

    case INST_EQ:
    case INST_NEQ:
5647
5648
5649
5650
5651
5652
5653
5654

5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665

5666
5667
5668
5669
5670
5671
5672
5857
5858
5859
5860
5861
5862
5863

5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874

5875
5876
5877
5878
5879
5880
5881
5882







-
+










-
+








	if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK)
		|| (type1==TCL_NUMBER_DOUBLE) || (type1==TCL_NUMBER_NAN)) {
	    TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n", O2S(valuePtr),
		    O2S(value2Ptr), (valuePtr->typePtr?
		    valuePtr->typePtr->name : "null")));
	    DECACHE_STACK_INFO();
	    IllegalExprOperandType(interp, pc, valuePtr);
	    IllegalExprOperandType(interp, "left ", pc, valuePtr);
	    CACHE_STACK_INFO();
	    goto gotError;
	}

	if ((GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2) != TCL_OK)
		|| (type2==TCL_NUMBER_DOUBLE) || (type2==TCL_NUMBER_NAN)) {
	    TRACE(("%.20s %.20s => ILLEGAL 2nd TYPE %s\n", O2S(valuePtr),
		    O2S(value2Ptr), (value2Ptr->typePtr?
		    value2Ptr->typePtr->name : "null")));
	    DECACHE_STACK_INFO();
	    IllegalExprOperandType(interp, pc, value2Ptr);
	    IllegalExprOperandType(interp, "right ", pc, value2Ptr);
	    CACHE_STACK_INFO();
	    goto gotError;
	}

	/*
	 * Check for common, simple case.
	 */
5708
5709
5710
5711
5712
5713
5714
5715


5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728

5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742

5743
5744
5745

5746
5747

5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761

5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777

5778
5779
5780
5781
5782
5783
5784
5918
5919
5920
5921
5922
5923
5924

5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938

5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952

5953
5954
5955

5956
5957

5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971

5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987

5988
5989
5990
5991
5992
5993
5994
5995







-
+
+












-
+













-
+


-
+

-
+













-
+















-
+







		     */

		    if ((wResult < 0 || (wResult == 0 &&
			    ((w1 < 0 && w2 > 0) || (w1 > 0 && w2 < 0)))) &&
			    (wResult * w2 != w1)) {
			wResult -= 1;
		    }
		    wResult = w1 - w2*wResult;
		    wResult = (Tcl_WideInt)((Tcl_WideUInt)w1 -
			    (Tcl_WideUInt)w2*(Tcl_WideUInt)wResult);
		    goto wideResultOfArithmetic;
		}
		break;

	    case INST_RSHIFT:
		if (w2 < 0) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "negative shift argument", -1));
#ifdef ERROR_CODE_FOR_EARLY_DETECTED_ARITH_ERROR
		    DECACHE_STACK_INFO();
		    Tcl_SetErrorCode(interp, "ARITH", "DOMAIN",
			    "domain error: argument not in valid range",
			    NULL);
			    (char *)NULL);
		    CACHE_STACK_INFO();
#endif /* ERROR_CODE_FOR_EARLY_DETECTED_ARITH_ERROR */
		    goto gotError;
		} else if (w1 == 0) {
		    TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
		    objResultPtr = TCONST(0);
		    TRACE(("%s\n", O2S(objResultPtr)));
		    NEXT_INST_F(1, 2, 1);
		} else {
		    /*
		     * Quickly force large right shifts to 0 or -1.
		     */

		    if (w2 >= (Tcl_WideInt)(CHAR_BIT*sizeof(long))) {
		    if (w2 >= (Tcl_WideInt)(CHAR_BIT*sizeof(w1))) {
			/*
			 * We assume that INT_MAX is much larger than the
			 * number of bits in a long. This is a pretty safe
			 * number of bits in a Tcl_WideInt. This is a pretty safe
			 * assumption, given that the former is usually around
			 * 4e9 and the latter 32 or 64...
			 * 4e9 and the latter 64...
			 */

			TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
			if (w1 > 0L) {
			    objResultPtr = TCONST(0);
			} else {
			    TclNewIntObj(objResultPtr, -1);
			}
			TRACE(("%s\n", O2S(objResultPtr)));
			NEXT_INST_F(1, 2, 1);
		    }

		    /*
		     * Handle shifts within the native long range.
		     * Handle shifts within the native Tcl_WideInt range.
		     */

		    wResult = w1 >> ((int) w2);
		    goto wideResultOfArithmetic;
		}
		break;

	    case INST_LSHIFT:
		if (w2 < 0) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "negative shift argument", -1));
#ifdef ERROR_CODE_FOR_EARLY_DETECTED_ARITH_ERROR
		    DECACHE_STACK_INFO();
		    Tcl_SetErrorCode(interp, "ARITH", "DOMAIN",
			    "domain error: argument not in valid range",
			    NULL);
			    (char *)NULL);
		    CACHE_STACK_INFO();
#endif /* ERROR_CODE_FOR_EARLY_DETECTED_ARITH_ERROR */
		    goto gotError;
		} else if (w1 == 0) {
		    TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
		    objResultPtr = TCONST(0);
		    TRACE(("%s\n", O2S(objResultPtr)));
5792
5793
5794
5795
5796
5797
5798
5799

5800
5801
5802
5803
5804
5805
5806
5807

5808
5809
5810

5811
5812
5813


5814
5815
5816
5817
5818
5819
5820
6003
6004
6005
6006
6007
6008
6009

6010
6011
6012
6013
6014
6015
6016
6017

6018
6019
6020

6021
6022


6023
6024
6025
6026
6027
6028
6029
6030
6031







-
+







-
+


-
+

-
-
+
+







		     */

		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "integer value too large to represent", -1));
#ifdef ERROR_CODE_FOR_EARLY_DETECTED_ARITH_ERROR
		    DECACHE_STACK_INFO();
		    Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
			    "integer value too large to represent", NULL);
			    "integer value too large to represent", (char *)NULL);
		    CACHE_STACK_INFO();
#endif /* ERROR_CODE_FOR_EARLY_DETECTED_ARITH_ERROR */
		    goto gotError;
		} else {
		    int shift = (int) w2;

		    /*
		     * Handle shifts within the native long range.
		     * Handle shifts within the native Tcl_WideInt range.
		     */

		    if ((size_t) shift < CHAR_BIT*sizeof(long) && (w1 != 0)
		    if (((size_t)shift < CHAR_BIT*sizeof(w1))
			    && !((w1>0 ? w1 : ~w1) &
				-(1L<<(CHAR_BIT*sizeof(long) - 1 - shift)))) {
			wResult = w1 << shift;
				-((Tcl_WideUInt)1<<(CHAR_BIT*sizeof(w1) - 1 - shift)))) {
			wResult = (Tcl_WideUInt)w1 << shift;
			goto wideResultOfArithmetic;
		    }
		}

		/*
		 * Too large; need to use the broken-out function.
		 */
5867
5868
5869
5870
5871
5872
5873
5874

5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895

5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912

5913
5914
5915
5916
5917
5918
5919
5920
5921
5922

5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933

5934
5935
5936
5937
5938
5939
5940
6078
6079
6080
6081
6082
6083
6084

6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105

6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122

6123
6124
6125
6126
6127
6128
6129
6130
6131
6132

6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143

6144
6145
6146
6147
6148
6149
6150
6151







-
+




















-
+
















-
+









-
+










-
+








	if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK)
		|| IsErroringNaNType(type1)) {
	    TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n",
		    O2S(value2Ptr), O2S(valuePtr),
		    (valuePtr->typePtr? valuePtr->typePtr->name: "null")));
	    DECACHE_STACK_INFO();
	    IllegalExprOperandType(interp, pc, valuePtr);
	    IllegalExprOperandType(interp, "left ", pc, valuePtr);
	    CACHE_STACK_INFO();
	    goto gotError;
	}

#ifdef ACCEPT_NAN
	if (type1 == TCL_NUMBER_NAN) {
	    /*
	     * NaN first argument -> result is also NaN.
	     */

	    NEXT_INST_F(1, 1, 0);
	}
#endif

	if ((GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2) != TCL_OK)
		|| IsErroringNaNType(type2)) {
	    TRACE(("%.20s %.20s => ILLEGAL 2nd TYPE %s\n",
		    O2S(value2Ptr), O2S(valuePtr),
		    (value2Ptr->typePtr? value2Ptr->typePtr->name: "null")));
	    DECACHE_STACK_INFO();
	    IllegalExprOperandType(interp, pc, value2Ptr);
	    IllegalExprOperandType(interp, "right ", pc, value2Ptr);
	    CACHE_STACK_INFO();
	    goto gotError;
	}

#ifdef ACCEPT_NAN
	if (type2 == TCL_NUMBER_NAN) {
	    /*
	     * NaN second argument -> result is also NaN.
	     */

	    objResultPtr = value2Ptr;
	    NEXT_INST_F(1, 2, 1);
	}
#endif

	/*
	 * Handle (long,long) arithmetic as best we can without going out to
	 * Handle Tcl_WideInt arithmetic as best we can without going out to
	 * an external function.
	 */

	if ((type1 == TCL_NUMBER_INT) && (type2 == TCL_NUMBER_INT)) {
	    w1 = *((const Tcl_WideInt *)ptr1);
	    w2 = *((const Tcl_WideInt *)ptr2);

	    switch (*pc) {
	    case INST_ADD:
		wResult = w1 + w2;
		wResult = (Tcl_WideInt)((Tcl_WideUInt)w1 + (Tcl_WideUInt)w2);
		/*
		 * Check for overflow.
		 */

		if (Overflowing(w1, w2, wResult)) {
		    goto overflow;
		}
		goto wideResultOfArithmetic;

	    case INST_SUB:
		wResult = w1 - w2;
		wResult = (Tcl_WideInt)((Tcl_WideUInt)w1 - (Tcl_WideUInt)w2);
		/*
		 * Must check for overflow. The macro tests for overflows in
		 * sums by looking at the sign bits. As we have a subtraction
		 * here, we are adding -w2. As -w2 could in turn overflow, we
		 * test with ~w2 instead: it has the opposite sign bit to w2
		 * so it does the job. Note that the only "bad" case (w2==0)
		 * is irrelevant for this macro, as in that case w1 and
6030
6031
6032
6033
6034
6035
6036
6037

6038
6039
6040
6041
6042
6043
6044
6241
6242
6243
6244
6245
6246
6247

6248
6249
6250
6251
6252
6253
6254
6255







-
+








	/* TODO - check claim that taking address of b harms performance */
	/* TODO - consider optimization search for constants */
	if (TclGetBooleanFromObj(NULL, valuePtr, &b) != TCL_OK) {
	    TRACE(("\"%.20s\" => ERROR: illegal type %s\n", O2S(valuePtr),
		    (valuePtr->typePtr? valuePtr->typePtr->name : "null")));
	    DECACHE_STACK_INFO();
	    IllegalExprOperandType(interp, pc, valuePtr);
	    IllegalExprOperandType(interp, "", pc, valuePtr);
	    CACHE_STACK_INFO();
	    goto gotError;
	}
	/* TODO: Consider peephole opt. */
	objResultPtr = TCONST(!b);
	TRACE_WITH_OBJ(("%s => ", O2S(valuePtr)), objResultPtr);
	NEXT_INST_F(1, 1, 1);
6052
6053
6054
6055
6056
6057
6058
6059

6060
6061
6062
6063
6064
6065
6066
6263
6264
6265
6266
6267
6268
6269

6270
6271
6272
6273
6274
6275
6276
6277







-
+







	    /*
	     * ... ~$NonInteger => raise an error.
	     */

	    TRACE_APPEND(("ERROR: illegal type %s\n",
		    (valuePtr->typePtr? valuePtr->typePtr->name : "null")));
	    DECACHE_STACK_INFO();
	    IllegalExprOperandType(interp, pc, valuePtr);
	    IllegalExprOperandType(interp, "", pc, valuePtr);
	    CACHE_STACK_INFO();
	    goto gotError;
	}
	if (type1 == TCL_NUMBER_INT) {
	    w1 = *((const Tcl_WideInt *) ptr1);
	    if (Tcl_IsShared(valuePtr)) {
		TclNewIntObj(objResultPtr, ~w1);
6084
6085
6086
6087
6088
6089
6090
6091

6092
6093
6094
6095
6096
6097
6098
6295
6296
6297
6298
6299
6300
6301

6302
6303
6304
6305
6306
6307
6308
6309







-
+







	valuePtr = OBJ_AT_TOS;
	TRACE(("\"%.20s\" => ", O2S(valuePtr)));
	if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK)
		|| IsErroringNaNType(type1)) {
	    TRACE_APPEND(("ERROR: illegal type %s \n",
		    (valuePtr->typePtr? valuePtr->typePtr->name : "null")));
	    DECACHE_STACK_INFO();
	    IllegalExprOperandType(interp, pc, valuePtr);
	    IllegalExprOperandType(interp, "", pc, valuePtr);
	    CACHE_STACK_INFO();
	    goto gotError;
	}
	switch (type1) {
	case TCL_NUMBER_NAN:
	    /* -NaN => NaN */
	    TRACE_APPEND(("%s\n", O2S(valuePtr)));
6137
6138
6139
6140
6141
6142
6143
6144

6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162

6163
6164
6165
6166
6167
6168
6169
6348
6349
6350
6351
6352
6353
6354

6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372

6373
6374
6375
6376
6377
6378
6379
6380







-
+

















-
+







		/*
		 * ... +$NonNumeric => raise an error.
		 */

		TRACE_APPEND(("ERROR: illegal type %s\n",
			(valuePtr->typePtr? valuePtr->typePtr->name:"null")));
		DECACHE_STACK_INFO();
		IllegalExprOperandType(interp, pc, valuePtr);
		IllegalExprOperandType(interp, "", pc, valuePtr);
		CACHE_STACK_INFO();
		goto gotError;
	    }

	    /* ... TryConvertToNumeric($NonNumeric) is acceptable */
	    TRACE_APPEND(("not numeric\n"));
	    NEXT_INST_F(1, 0, 0);
	}
	if (IsErroringNaNType(type1)) {
	    if (*pc == INST_UPLUS) {
		/*
		 * ... +$NonNumeric => raise an error.
		 */

		TRACE_APPEND(("ERROR: illegal type %s\n",
			(valuePtr->typePtr? valuePtr->typePtr->name:"null")));
		DECACHE_STACK_INFO();
		IllegalExprOperandType(interp, pc, valuePtr);
		IllegalExprOperandType(interp, "", pc, valuePtr);
		CACHE_STACK_INFO();
	    } else {
		/*
		 * Numeric conversion of NaN -> error.
		 */

		TRACE_APPEND(("ERROR: IEEE floating pt error\n"));
6186
6187
6188
6189
6190
6191
6192
6193

6194
6195
6196
6197
6198
6199
6200
6397
6398
6399
6400
6401
6402
6403

6404
6405
6406
6407
6408
6409
6410
6411







-
+







	if (valuePtr->bytes == NULL) {
	    TRACE_APPEND(("numeric, same Tcl_Obj\n"));
	    NEXT_INST_F(1, 0, 0);
	}
	if (Tcl_IsShared(valuePtr)) {
	    /*
	     * Here we do some surgery within the Tcl_Obj internals. We want
	     * to copy the intrep, but not the string, so we temporarily hide
	     * to copy the internalrep, but not the string, so we temporarily hide
	     * the string so we do not copy it.
	     */

	    char *savedString = valuePtr->bytes;

	    valuePtr->bytes = NULL;
	    objResultPtr = Tcl_DuplicateObj(valuePtr);
6211
6212
6213
6214
6215
6216
6217
6218

6219
6220
6221
6222
6223
6224
6225
6422
6423
6424
6425
6426
6427
6428

6429
6430
6431
6432
6433
6434
6435
6436







-
+







    /*
     *	   End of numeric operator instructions.
     * -----------------------------------------------------------------
     */

    case INST_TRY_CVT_TO_BOOLEAN:
	valuePtr = OBJ_AT_TOS;
	if (TclHasIntRep(valuePtr,  &tclBooleanType)) {
	if (TclHasInternalRep(valuePtr,  &tclBooleanType)) {
	    objResultPtr = TCONST(1);
	} else {
	    int res = (TclSetBooleanFromAny(NULL, valuePtr) == TCL_OK);
	    objResultPtr = TCONST(res);
	}
	TRACE_WITH_OBJ(("\"%.30s\" => ", O2S(valuePtr)), objResultPtr);
	NEXT_INST_F(1, 0, 1);
6247
6248
6249
6250
6251
6252
6253
6254

6255
6256
6257


6258
6259
6260
6261
6262
6263
6264
6265
6458
6459
6460
6461
6462
6463
6464

6465



6466
6467

6468
6469
6470
6471
6472
6473
6474







-
+
-
-
-
+
+
-







	TRACE(("=> CONTINUE!\n"));
	goto processExceptionReturn;

    {
	ForeachInfo *infoPtr;
	Tcl_Obj *listPtr, **elements;
	ForeachVarList *varListPtr;
	int numLists, listLen, numVars;
	Tcl_Size numLists, listLen, numVars, listTmpDepth;
	int listTmpDepth;
	size_t iterNum, iterMax, iterTmp;
	int varIndex, valIndex, j;
	Tcl_Size iterNum, iterMax, iterTmp;
	Tcl_Size varIndex, valIndex, i, j;
	long i;

    case INST_FOREACH_START:
	/*
	 * Initialize the data for the looping construct, pushing the
	 * corresponding Tcl_Objs to the stack.
	 */

6274
6275
6276
6277
6278
6279
6280

6281

6282

6283
6284
6285
6286
6287
6288
6289
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492

6493
6494
6495
6496
6497
6498
6499
6500







+

+
-
+








	iterMax = 0;
	listTmpDepth = numLists-1;
	for (i = 0;  i < numLists;  i++) {
	    varListPtr = infoPtr->varLists[i];
	    numVars = varListPtr->numVars;
	    listPtr = OBJ_AT_DEPTH(listTmpDepth);
	    DECACHE_STACK_INFO();
	    if (TclListObjLength(interp, listPtr, &listLen) != TCL_OK) {
		CACHE_STACK_INFO();
		TRACE_APPEND(("ERROR converting list %ld, \"%s\": %s",
		TRACE_APPEND(("ERROR converting list %" TCL_Z_MODIFIER "d, \"%s\": %s",
			i, O2S(listPtr), O2S(Tcl_GetObjResult(interp))));
		goto gotError;
	    }
	    if (Tcl_IsShared(listPtr)) {
		objPtr = TclListObjCopy(NULL, listPtr);
		Tcl_IncrRefCount(objPtr);
		Tcl_DecrRefCount(listPtr);
6321
6322
6323
6324
6325
6326
6327
6328

6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348

6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359

6360
6361







6362







6363
6364
6365
6366
6367
6368


6369















6370
6371
6372
6373
6374
6375
6376
6532
6533
6534
6535
6536
6537
6538

6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581

6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596

6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618







-
+




















+











+


+
+
+
+
+
+
+
-
+
+
+
+
+
+
+






+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	/*
	 * Jump directly to the INST_FOREACH_STEP instruction; the C code just
	 * falls through.
	 */

	pc += 5 - infoPtr->loopCtTemp;

    case INST_FOREACH_STEP:
    case INST_FOREACH_STEP: /* TODO: address abstract list indexing here! */
	/*
	 * "Step" a foreach loop (i.e., begin its next iteration) by assigning
	 * the next value list element to each loop var.
	 */

	tmpPtr = OBJ_AT_TOS;
	infoPtr = (ForeachInfo *)tmpPtr->internalRep.twoPtrValue.ptr1;
	numLists = infoPtr->numLists;
	TRACE(("=> "));

	tmpPtr = OBJ_AT_DEPTH(1);
	iterNum = (size_t)tmpPtr->internalRep.twoPtrValue.ptr1;
	iterMax = (size_t)tmpPtr->internalRep.twoPtrValue.ptr2;

	/*
	 * If some list still has a remaining list element iterate one more
	 * time. Assign to var the next element from its value list.
	 */

	if (iterNum < iterMax) {
	    int status;
	    /*
	     * Set the variables and jump back to run the body
	     */

	    tmpPtr->internalRep.twoPtrValue.ptr1 =(void *)(iterNum + 1);

	    listTmpDepth = numLists + 1;

	    for (i = 0;  i < numLists;  i++) {
		varListPtr = infoPtr->varLists[i];
		numVars = varListPtr->numVars;
		int hasAbstractList;

		listPtr = OBJ_AT_DEPTH(listTmpDepth);
		hasAbstractList = TclObjTypeHasProc(listPtr, indexProc) != 0;
		DECACHE_STACK_INFO();
		if (hasAbstractList) {
		    status = Tcl_ListObjLength(interp, listPtr, &listLen);
		    elements = NULL;
		} else {
		    status = TclListObjGetElements(
		TclListObjGetElements(interp, listPtr, &listLen, &elements);
			interp, listPtr, &listLen, &elements);
		}
		if (status != TCL_OK) {
		    CACHE_STACK_INFO();
		    goto gotError;
		}
		CACHE_STACK_INFO();

		valIndex = (iterNum * numVars);
		for (j = 0;  j < numVars;  j++) {
		    if (valIndex >= listLen) {
			TclNewObj(valuePtr);
		    } else {
			DECACHE_STACK_INFO();
			if (elements) {
			valuePtr = elements[valIndex];
			    valuePtr = elements[valIndex];
			} else {
			    status = Tcl_ListObjIndex(
				interp, listPtr, valIndex, &valuePtr);
			    if (status != TCL_OK) {
				/* Could happen for abstract lists */
				CACHE_STACK_INFO();
				goto gotError;
			    }
			    if (valuePtr == NULL) {
				/* Permitted for Tcl_LOI to return NULL */
				TclNewObj(valuePtr);
			    }
			}
			CACHE_STACK_INFO();
		    }

		    varIndex = varListPtr->varIndexes[j];
		    varPtr = LOCAL(varIndex);
		    while (TclIsVarLink(varPtr)) {
			varPtr = varPtr->value.linkPtr;
		    }
6384
6385
6386
6387
6388
6389
6390
6391

6392
6393
6394
6395
6396
6397
6398
6626
6627
6628
6629
6630
6631
6632

6633
6634
6635
6636
6637
6638
6639
6640







-
+







			    Tcl_IncrRefCount(valuePtr);
			}
		    } else {
			DECACHE_STACK_INFO();
			if (TclPtrSetVarIdx(interp, varPtr, NULL, NULL, NULL,
				valuePtr, TCL_LEAVE_ERR_MSG, varIndex)==NULL){
			    CACHE_STACK_INFO();
			    TRACE_APPEND(("ERROR init. index temp %d: %.30s",
			    TRACE_APPEND(("ERROR init. index temp %" TCL_SIZE_MODIFIER "d: %.30s",
				    varIndex, O2S(Tcl_GetObjResult(interp))));
			    goto gotError;
			}
			CACHE_STACK_INFO();
		    }
		    valIndex++;
		}
6431
6432
6433
6434
6435
6436
6437
6438

6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456




6457
6458
6459
6460
6461
6462
6463
6464
6465
6466

6467
6468
6469
6470
6471
6472
6473
6673
6674
6675
6676
6677
6678
6679

6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694




6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707

6708
6709
6710
6711
6712
6713
6714
6715







-
+














-
-
-
-
+
+
+
+









-
+







	 *   - collecting obj (unshared)
	 * The instruction lappends the result to the collecting obj.
	 */

	tmpPtr = OBJ_AT_DEPTH(1);
	infoPtr = (ForeachInfo *)tmpPtr->internalRep.twoPtrValue.ptr1;
	numLists = infoPtr->numLists;
	TRACE_APPEND(("=> appending to list at depth %d\n", 3 + numLists));
	TRACE_APPEND(("=> appending to list at depth %" TCL_SIZE_MODIFIER "d\n", 3 + numLists));

	objPtr = OBJ_AT_DEPTH(3 + numLists);
	Tcl_ListObjAppendElement(NULL, objPtr, OBJ_AT_TOS);
	NEXT_INST_F(1, 1, 0);
    }
    break;

    case INST_BEGIN_CATCH4:
	/*
	 * Record start of the catch command with exception range index equal
	 * to the operand. Push the current stack depth onto the special catch
	 * stack.
	 */

	*(++catchTop) = CURR_DEPTH;
	TRACE(("%u => catchTop=%d, stackTop=%d\n",
		TclGetUInt4AtPtr(pc+1), (int) (catchTop - initCatchTop - 1),
		(int) CURR_DEPTH));
	*(++catchTop) = (Tcl_Obj *)INT2PTR(CURR_DEPTH);
	TRACE(("%u => catchTop=%" TCL_T_MODIFIER "d, stackTop=%" TCL_T_MODIFIER "d\n",
		TclGetUInt4AtPtr(pc+1), (catchTop - initCatchTop - 1),
		CURR_DEPTH));
	NEXT_INST_F(5, 0, 0);
    break;

    case INST_END_CATCH:
	catchTop--;
	DECACHE_STACK_INFO();
	Tcl_ResetResult(interp);
	CACHE_STACK_INFO();
	result = TCL_OK;
	TRACE(("=> catchTop=%d\n", (int) (catchTop - initCatchTop - 1)));
	TRACE(("=> catchTop=%" TCL_Z_MODIFIER "u\n", (size_t)(catchTop - initCatchTop - 1)));
	NEXT_INST_F(1, 0, 0);
    break;

    case INST_PUSH_RESULT:
	objResultPtr = Tcl_GetObjResult(interp);
	TRACE_WITH_OBJ(("=> "), objResultPtr);

6513
6514
6515
6516
6517
6518
6519
6520


6521
6522
6523
6524
6525
6526


6527
6528
6529

6530
6531
6532
6533
6534
6535

6536
6537
6538
6539
6540
6541
6542
6755
6756
6757
6758
6759
6760
6761

6762
6763
6764
6765
6766
6767
6768

6769
6770
6771
6772

6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787







-
+
+





-
+
+


-
+






+








    /*
     * -----------------------------------------------------------------
     *	   Start of dictionary-related instructions.
     */

    {
	int opnd2, allocateDict, done, i, allocdict;
	int opnd2, allocateDict, done, allocdict;
	Tcl_Size i;
	Tcl_Obj *dictPtr, *statePtr, *keyPtr, *listPtr, *varNamePtr, *keysPtr;
	Tcl_Obj *emptyPtr, **keyPtrPtr;
	Tcl_DictSearch *searchPtr;
	DictUpdateInfo *duiPtr;

    case INST_DICT_VERIFY:
    case INST_DICT_VERIFY: {
	Tcl_Size size;
	dictPtr = OBJ_AT_TOS;
	TRACE(("\"%.30s\" => ", O2S(dictPtr)));
	if (Tcl_DictObjSize(interp, dictPtr, &done) != TCL_OK) {
	if (Tcl_DictObjSize(interp, dictPtr, &size) != TCL_OK) {
	    TRACE_APPEND(("ERROR verifying dictionary nature of \"%.30s\": %s\n",
		    O2S(dictPtr), O2S(Tcl_GetObjResult(interp))));
	    goto gotError;
	}
	TRACE_APPEND(("OK\n"));
	NEXT_INST_F(1, 1, 0);
    }
    break;

    case INST_DICT_EXISTS: {
	int found;

	opnd = TclGetUInt4AtPtr(pc+1);
	TRACE(("%u => ", opnd));
6590
6591
6592
6593
6594
6595
6596
6597

6598
6599
6600
6601
6602
6603
6604
6835
6836
6837
6838
6839
6840
6841

6842
6843
6844
6845
6846
6847
6848
6849







-
+







	}
	if (!objResultPtr) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "key \"%s\" not known in dictionary",
		    TclGetString(OBJ_AT_TOS)));
	    DECACHE_STACK_INFO();
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "DICT",
		    TclGetString(OBJ_AT_TOS), NULL);
		    TclGetString(OBJ_AT_TOS), (char *)NULL);
	    CACHE_STACK_INFO();
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
	NEXT_INST_V(5, opnd+1, 1);
    case INST_DICT_GET_DEF:
6726
6727
6728
6729
6730
6731
6732
6733

6734
6735
6736
6737
6738
6739
6740
6971
6972
6973
6974
6975
6976
6977

6978
6979
6980
6981
6982
6983
6984
6985







-
+







	    TclDecrRefCount(dictPtr);
	    if (objResultPtr == NULL) {
		TRACE_ERROR(interp);
		goto gotError;
	    }
	}
#ifndef TCL_COMPILE_DEBUG
	if (*(pc+9) == INST_POP) {
	if (pc[9] == INST_POP) {
	    NEXT_INST_V(10, cleanup, 0);
	}
#endif
	TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr)));
	NEXT_INST_V(9, cleanup, 1);

    case INST_DICT_APPEND:
6865
6866
6867
6868
6869
6870
6871
6872

6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889

6890
6891
6892
6893
6894
6895
6896
6897
6898
6899

6900
6901
6902
6903

6904
6905
6906
6907

6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921

6922
6923
6924

6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944

6945
6946
6947
6948
6949
6950
6951
7110
7111
7112
7113
7114
7115
7116

7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130

7131
7132

7133
7134
7135
7136
7137
7138
7139
7140
7141
7142

7143
7144
7145
7146

7147
7148
7149
7150

7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164

7165
7166
7167

7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187

7188
7189
7190
7191
7192
7193
7194
7195







-
+













-


-
+









-
+



-
+



-
+













-
+


-
+



















-
+







	    TclDecrRefCount(dictPtr);
	    if (objResultPtr == NULL) {
		TRACE_ERROR(interp);
		goto gotError;
	    }
	}
#ifndef TCL_COMPILE_DEBUG
	if (*(pc+5) == INST_POP) {
	if (pc[5] == INST_POP) {
	    NEXT_INST_F(6, 2, 0);
	}
#endif
	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
	NEXT_INST_F(5, 2, 1);

    case INST_DICT_FIRST:
	opnd = TclGetUInt4AtPtr(pc+1);
	TRACE(("%u => ", opnd));
	dictPtr = POP_OBJECT();
	searchPtr = (Tcl_DictSearch *)Tcl_Alloc(sizeof(Tcl_DictSearch));
	if (Tcl_DictObjFirst(interp, dictPtr, searchPtr, &keyPtr,
		&valuePtr, &done) != TCL_OK) {

	    /*
	     * dictPtr is no longer on the stack, and we're not
	     * moving it into the intrep of an iterator.  We need
	     * moving it into the internalrep of an iterator.  We need
	     * to drop the refcount [Tcl Bug 9b352768e6].
	     */

	    Tcl_DecrRefCount(dictPtr);
	    Tcl_Free(searchPtr);
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	{
	    Tcl_ObjIntRep ir;
	    Tcl_ObjInternalRep ir;
	    TclNewObj(statePtr);
	    ir.twoPtrValue.ptr1 = searchPtr;
	    ir.twoPtrValue.ptr2 = dictPtr;
	    Tcl_StoreIntRep(statePtr, &dictIteratorType, &ir);
	    Tcl_StoreInternalRep(statePtr, &dictIteratorType, &ir);
	}
	varPtr = LOCAL(opnd);
	if (varPtr->value.objPtr) {
	    if (TclHasIntRep(varPtr->value.objPtr, &dictIteratorType)) {
	    if (TclHasInternalRep(varPtr->value.objPtr, &dictIteratorType)) {
		Tcl_Panic("mis-issued dictFirst!");
	    }
	    TclDecrRefCount(varPtr->value.objPtr);
	}
	varPtr->value.objPtr = statePtr;
	Tcl_IncrRefCount(statePtr);
	goto pushDictIteratorResult;

    case INST_DICT_NEXT:
	opnd = TclGetUInt4AtPtr(pc+1);
	TRACE(("%u => ", opnd));
	statePtr = (*LOCAL(opnd)).value.objPtr;
	{
	    const Tcl_ObjIntRep *irPtr;
	    const Tcl_ObjInternalRep *irPtr;

	    if (statePtr &&
		    (irPtr = TclFetchIntRep(statePtr, &dictIteratorType))) {
		    (irPtr = TclFetchInternalRep(statePtr, &dictIteratorType))) {
		searchPtr = (Tcl_DictSearch *)irPtr->twoPtrValue.ptr1;
		Tcl_DictObjNext(searchPtr, &keyPtr, &valuePtr, &done);
	    } else {
		Tcl_Panic("mis-issued dictNext!");
	    }
	}
    pushDictIteratorResult:
	if (done) {
	    TclNewObj(emptyPtr);
	    PUSH_OBJECT(emptyPtr);
	    PUSH_OBJECT(emptyPtr);
	} else {
	    PUSH_OBJECT(valuePtr);
	    PUSH_OBJECT(keyPtr);
	}
	TRACE_APPEND(("\"%.30s\" \"%.30s\" %d\n",
		O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), done));

	/*
	 * The INST_DICT_FIRST and INST_DICT_NEXT instructsions are always
	 * The INST_DICT_FIRST and INST_DICT_NEXT instructions are always
	 * followed by a conditional jump, so we can take advantage of this to
	 * do some peephole optimization (note that we're careful to not close
	 * out someone doing something else).
	 */

	JUMP_PEEPHOLE_F(done, 5, 0);

6972
6973
6974
6975
6976
6977
6978
6979

6980
6981
6982
6983
6984
6985
6986
7216
7217
7218
7219
7220
7221
7222

7223
7224
7225
7226
7227
7228
7229
7230







-
+







	}
	Tcl_IncrRefCount(dictPtr);
	if (TclListObjGetElements(interp, OBJ_AT_TOS, &length,
		&keyPtrPtr) != TCL_OK) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	if ((size_t)length != duiPtr->length) {
	if (length != duiPtr->length) {
	    Tcl_Panic("dictUpdateStart argument length mismatch");
	}
	for (i=0 ; i<length ; i++) {
	    if (Tcl_DictObjGet(interp, dictPtr, keyPtrPtr[i],
		    &valuePtr) != TCL_OK) {
		TRACE_ERROR(interp);
		Tcl_DecrRefCount(dictPtr);
7117
7118
7119
7120
7121
7122
7123
7124

7125
7126
7127
7128
7129
7130
7131
7361
7362
7363
7364
7365
7366
7367

7368
7369
7370
7371
7372
7373
7374
7375







-
+







		TCL_LEAVE_ERR_MSG, "set", 1, 1, &arrayPtr);
	if (varPtr == NULL) {
	    TRACE_ERROR(interp);
	    TclDecrRefCount(keysPtr);
	    goto gotError;
	}
	DECACHE_STACK_INFO();
	result = TclDictWithFinish(interp, varPtr,arrayPtr,varNamePtr,NULL,-1,
	result = TclDictWithFinish(interp, varPtr, arrayPtr, varNamePtr, NULL, -1,
		objc, objv, keysPtr);
	CACHE_STACK_INFO();
	TclDecrRefCount(keysPtr);
	if (result != TCL_OK) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}
7160
7161
7162
7163
7164
7165
7166
7167

7168
7169
7170
7171
7172




7173
7174

7175
7176

7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198






















7199
7200
7201
7202
7203
7204
7205
7404
7405
7406
7407
7408
7409
7410

7411





7412
7413
7414
7415
7416

7417
7418

7419
7420





















7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449







-
+
-
-
-
-
-
+
+
+
+

-
+

-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    break;

    /*
     *	   End of dictionary-related instructions.
     * -----------------------------------------------------------------
     */

    case INST_CLOCK_READ:
    case INST_CLOCK_READ: {	/* Read the wall clock */
	{			/* Read the wall clock */
	    Tcl_WideInt wval;
	    Tcl_Time now;
	    switch(TclGetUInt1AtPtr(pc+1)) {
	    case 0:		/* clicks */
	Tcl_WideInt wval;
	Tcl_Time now;
	switch (TclGetUInt1AtPtr(pc+1)) {
	case 0:			/* clicks */
#ifdef TCL_WIDE_CLICKS
		wval = TclpGetWideClicks();
	    wval = TclpGetWideClicks();
#else
		wval = (Tcl_WideInt) TclpGetClicks();
	    wval = (Tcl_WideInt)TclpGetClicks();
#endif
		break;
	    case 1:		/* microseconds */
		Tcl_GetTime(&now);
		wval = (Tcl_WideInt) now.sec * 1000000 + now.usec;
		break;
	    case 2:		/* milliseconds */
		Tcl_GetTime(&now);
		wval = (Tcl_WideInt) now.sec * 1000 + now.usec / 1000;
		break;
	    case 3:		/* seconds */
		Tcl_GetTime(&now);
		wval = (Tcl_WideInt) now.sec;
		break;
	    default:
		Tcl_Panic("clockRead instruction with unknown clock#");
	    }
	    TclNewIntObj(objResultPtr, wval);
	    TRACE_WITH_OBJ(("=> "), objResultPtr);
	    NEXT_INST_F(2, 0, 1);
	}
	break;
	    break;
	case 1:			/* microseconds */
	    Tcl_GetTime(&now);
	    wval = (Tcl_WideInt)now.sec * 1000000 + now.usec;
	    break;
	case 2:			/* milliseconds */
	    Tcl_GetTime(&now);
	    wval = (Tcl_WideInt)now.sec * 1000 + now.usec / 1000;
	    break;
	case 3:			/* seconds */
	    Tcl_GetTime(&now);
	    wval = (Tcl_WideInt)now.sec;
	    break;
	default:
	    Tcl_Panic("clockRead instruction with unknown clock#");
	    break;
	}
	TclNewIntObj(objResultPtr, wval);
	TRACE_WITH_OBJ(("=> "), objResultPtr);
	NEXT_INST_F(2, 0, 1);
    }
    break;

    default:
	Tcl_Panic("TclNRExecuteByteCode: unrecognized opCode %u", *pc);
    } /* end of switch on opCode */

    /*
     * Block for variables needed to process exception returns.
7256
7257
7258
7259
7260
7261
7262
7263

7264
7265
7266
7267
7268

7269
7270
7271
7272
7273
7274
7275

7276
7277
7278
7279
7280
7281
7282
7500
7501
7502
7503
7504
7505
7506

7507
7508
7509
7510
7511

7512
7513
7514
7515
7516
7517
7518

7519
7520
7521
7522
7523
7524
7525
7526







-
+




-
+






-
+







	    while (cleanup--) {
		valuePtr = POP_OBJECT();
		TclDecrRefCount(valuePtr);
	    }
	    if (result == TCL_BREAK) {
		result = TCL_OK;
		pc = (codePtr->codeStart + rangePtr->breakOffset);
		TRACE_APPEND(("%s, range at %d, new pc %d\n",
		TRACE_APPEND(("%s, range at %" TCL_SIZE_MODIFIER "d, new pc %" TCL_SIZE_MODIFIER "d\n",
			StringForResultCode(result),
			rangePtr->codeOffset, rangePtr->breakOffset));
		NEXT_INST_F(0, 0, 0);
	    }
	    if (rangePtr->continueOffset == -1) {
	    if (rangePtr->continueOffset == TCL_INDEX_NONE) {
		TRACE_APPEND(("%s, loop w/o continue, checking for catch\n",
			StringForResultCode(result)));
		goto checkForCatch;
	    }
	    result = TCL_OK;
	    pc = (codePtr->codeStart + rangePtr->continueOffset);
	    TRACE_APPEND(("%s, range at %d, new pc %d\n",
	    TRACE_APPEND(("%s, range at %" TCL_SIZE_MODIFIER "d, new pc %" TCL_SIZE_MODIFIER "d\n",
		    StringForResultCode(result),
		    rangePtr->codeOffset, rangePtr->continueOffset));
	    NEXT_INST_F(0, 0, 0);
	}
#ifdef TCL_COMPILE_DEBUG
	if (traceInstructions) {
	    objPtr = Tcl_GetObjResult(interp);
7295
7296
7297
7298
7299
7300
7301
7302

7303
7304
7305
7306
7307
7308
7309

7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323

7324
7325
7326
7327
7328
7329
7330
7539
7540
7541
7542
7543
7544
7545

7546
7547
7548
7549
7550
7551
7552

7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564
7565
7566

7567
7568
7569
7570
7571
7572
7573
7574







-
+






-
+













-
+







	 * Division by zero in an expression. Control only reaches this point
	 * by "goto divideByZero".
	 */

    divideByZero:
	Tcl_SetObjResult(interp, Tcl_NewStringObj("divide by zero", -1));
	DECACHE_STACK_INFO();
	Tcl_SetErrorCode(interp, "ARITH", "DIVZERO", "divide by zero", NULL);
	Tcl_SetErrorCode(interp, "ARITH", "DIVZERO", "divide by zero", (char *)NULL);
	CACHE_STACK_INFO();
	goto gotError;

    outOfMemory:
	Tcl_SetObjResult(interp, Tcl_NewStringObj("out of memory", -1));
	DECACHE_STACK_INFO();
	Tcl_SetErrorCode(interp, "ARITH", "OUTOFMEMORY", "out of memory", NULL);
	Tcl_SetErrorCode(interp, "ARITH", "OUTOFMEMORY", "out of memory", (char *)NULL);
	CACHE_STACK_INFO();
	goto gotError;

	/*
	 * Exponentiation of zero by negative number in an expression. Control
	 * only reaches this point by "goto exponOfZero".
	 */

    exponOfZero:
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"exponentiation of zero by negative power", -1));
	DECACHE_STACK_INFO();
	Tcl_SetErrorCode(interp, "ARITH", "DOMAIN",
		"exponentiation of zero by negative power", NULL);
		"exponentiation of zero by negative power", (char *)NULL);
	CACHE_STACK_INFO();

	/*
	 * Almost all error paths feed through here rather than assigning to
	 * result themselves (for a small but consistent saving).
	 */

7341
7342
7343
7344
7345
7346
7347
7348

7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366


7367
7368
7369
7370
7371
7372
7373
7585
7586
7587
7588
7589
7590
7591

7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608


7609
7610
7611
7612
7613
7614
7615
7616
7617







-
+
















-
-
+
+








    checkForCatch:
	if (iPtr->execEnvPtr->rewind) {
	    goto abnormalReturn;
	}
	if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
	    const unsigned char *pcBeg;
	    size_t xxx1length;
	    Tcl_Size xxx1length;

	    bytes = GetSrcInfoForPc(pc, codePtr, &xxx1length, &pcBeg, NULL);
	    DECACHE_STACK_INFO();
	    TclLogCommandInfo(interp, codePtr->source, bytes,
		    bytes ? xxx1length : 0, pcBeg, tosPtr);
	    CACHE_STACK_INFO();
	}
	iPtr->flags &= ~ERR_ALREADY_LOGGED;

	/*
	 * Clear all expansions that may have started after the last
	 * INST_BEGIN_CATCH.
	 */

	while (auxObjList) {
	    if ((catchTop != initCatchTop)
		    && (*catchTop > (ptrdiff_t)
			auxObjList->internalRep.twoPtrValue.ptr2)) {
		    && (PTR2INT(*catchTop) >
			PTR2INT(auxObjList->internalRep.twoPtrValue.ptr2))) {
		break;
	    }
	    POP_TAUX_OBJ();
	}

	/*
	 * We must not catch if the script in progress has been canceled with
7434
7435
7436
7437
7438
7439
7440
7441

7442
7443
7444
7445
7446
7447
7448
7449
7450




7451
7452
7453
7454
7455
7456
7457
7678
7679
7680
7681
7682
7683
7684

7685
7686
7687
7688
7689
7690




7691
7692
7693
7694
7695
7696
7697
7698
7699
7700
7701







-
+





-
-
-
-
+
+
+
+







	 * "exception". It was found either by checkForCatch just above or by
	 * an instruction during break, continue, or error processing. Jump to
	 * its catchOffset after unwinding the operand stack to the depth it
	 * had when starting to execute the range's catch command.
	 */

    processCatch:
	while (CURR_DEPTH > *catchTop) {
	while (CURR_DEPTH > PTR2INT(*catchTop)) {
	    valuePtr = POP_OBJECT();
	    TclDecrRefCount(valuePtr);
	}
#ifdef TCL_COMPILE_DEBUG
	if (traceInstructions) {
	    fprintf(stdout, "  ... found catch at %d, catchTop=%d, "
		    "unwound to %ld, new pc %u\n",
		    rangePtr->codeOffset, (int) (catchTop - initCatchTop - 1),
		    (long) *catchTop, (unsigned) rangePtr->catchOffset);
	    fprintf(stdout, "  ... found catch at %" TCL_SIZE_MODIFIER "d, catchTop=%" TCL_T_MODIFIER "d, "
		    "unwound to %" TCL_T_MODIFIER "d, new pc %" TCL_SIZE_MODIFIER "d\n",
		    rangePtr->codeOffset, (catchTop - initCatchTop - 1),
		    PTR2INT(*catchTop), rangePtr->catchOffset);
	}
#endif
	pc = (codePtr->codeStart + rangePtr->catchOffset);
	NEXT_INST_F(0, 0, 0);	/* Restart the execution loop at pc. */

	/*
	 * end of infinite loop dispatching on instructions.
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489




7490
7491
7492
7493
7494
7495
7496
7723
7724
7725
7726
7727
7728
7729




7730
7731
7732
7733
7734
7735
7736
7737
7738
7739
7740







-
-
-
-
+
+
+
+







	while (tosPtr > initTosPtr) {
	    objPtr = POP_OBJECT();
	    Tcl_DecrRefCount(objPtr);
	}

	if (tosPtr < initTosPtr) {
	    fprintf(stderr,
		    "\nTclNRExecuteByteCode: abnormal return at pc %u: "
		    "stack top %d < entry stack top %d\n",
		    (unsigned)(pc - codePtr->codeStart),
		    (unsigned) CURR_DEPTH, (unsigned) 0);
		    "\nTclNRExecuteByteCode: abnormal return at pc %" TCL_T_MODIFIER "d: "
		    "stack top %" TCL_T_MODIFIER "d < entry stack top %d\n",
		    (pc - codePtr->codeStart),
		    CURR_DEPTH, 0);
	    Tcl_Panic("TclNRExecuteByteCode execution failure: end stack top < start stack top");
	}
	CLANG_ASSERT(bcFramePtr);
    }

    iPtr->cmdFramePtr = bcFramePtr->nextPtr;
    TclReleaseByteCode(codePtr);
7508
7509
7510
7511
7512
7513
7514
7515

7516
7517
7518
7519
7520
7521
7522
7752
7753
7754
7755
7756
7757
7758

7759
7760
7761
7762
7763
7764
7765
7766







-
+








     * case INST_START_CMD:
     */

	instStartCmdFailed:
	{
	    const char *bytes;
	    size_t xxx1length;
	    Tcl_Size xxx1length;

	    xxx1length = 0;

	    if (TclInterpReady(interp) == TCL_ERROR) {
		goto gotError;
	    }

7548
7549
7550
7551
7552
7553
7554
7555

7556
7557
7558
7559
7560
7561
7562
7792
7793
7794
7795
7796
7797
7798

7799
7800
7801
7802
7803
7804
7805
7806







-
+







#undef auxObjList
#undef catchTop
#undef TCONST
#undef esPtr

static int
FinalizeOONext(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    CallContext *contextPtr = (CallContext *)data[1];

    /*
7574
7575
7576
7577
7578
7579
7580
7581

7582
7583
7584
7585
7586
7587
7588
7818
7819
7820
7821
7822
7823
7824

7825
7826
7827
7828
7829
7830
7831
7832







-
+







    contextPtr->skip = PTR2INT(data[3]);
    contextPtr->oPtr->flags &= ~FILTER_HANDLING;
    return result;
}

static int
FinalizeOONextFilter(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    CallContext *contextPtr = (CallContext *)data[1];

    /*
7604
7605
7606
7607
7608
7609
7610
7611
7612




7613
7614
7615
7616
7617
7618
7619
7848
7849
7850
7851
7852
7853
7854


7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865







-
-
+
+
+
+








/*
 * WidePwrSmallExpon --
 *
 * Helper to calculate small powers of integers whose result is wide.
 */
static inline Tcl_WideInt
WidePwrSmallExpon(Tcl_WideInt w1, long exponent) {

WidePwrSmallExpon(
    Tcl_WideInt w1,
    long exponent)
{
    Tcl_WideInt wResult;

    wResult = w1 * w1;		/* b**2 */
    switch (exponent) {
    case 2:
	break;
    case 3:
7720
7721
7722
7723
7724
7725
7726
7727

7728
7729
7730
7731
7732
7733
7734

7735
7736
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747

7748
7749
7750
7751
7752
7753
7754


7755
7756
7757
7758
7759
7760
7761
7966
7967
7968
7969
7970
7971
7972

7973
7974
7975
7976
7977
7978
7979

7980
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992

7993
7994
7995
7996
7997
7998


7999
8000
8001
8002
8003
8004
8005
8006
8007







-
+






-
+












-
+





-
-
+
+







    Tcl_Obj *valuePtr,		/* The first operand on the stack. */
    Tcl_Obj *value2Ptr)		/* The second operand on the stack. */
{
#define WIDE_RESULT(w) \
    if (Tcl_IsShared(valuePtr)) {		\
	return Tcl_NewWideIntObj(w);		\
    } else {					\
	TclSetIntObj(valuePtr, w);		\
	TclSetIntObj(valuePtr, (w));		\
	return NULL;				\
    }
#define BIG_RESULT(b) \
    if (Tcl_IsShared(valuePtr)) {		\
	return Tcl_NewBignumObj(b);		\
    } else {					\
	Tcl_SetBignumObj(valuePtr, b);		\
	Tcl_SetBignumObj(valuePtr, (b));		\
	return NULL;				\
    }
#define DOUBLE_RESULT(d) \
    if (Tcl_IsShared(valuePtr)) {		\
	TclNewDoubleObj(objResultPtr, (d));	\
	return objResultPtr;			\
    } else {					\
	Tcl_SetDoubleObj(valuePtr, (d));	\
	return NULL;				\
    }

    int type1, type2;
    ClientData ptr1, ptr2;
    void *ptr1, *ptr2;
    double d1, d2, dResult;
    Tcl_WideInt w1, w2, wResult;
    mp_int big1, big2, bigResult, bigRemainder;
    Tcl_Obj *objResultPtr;
    int invalid, zero;
    long shift;
	mp_err err;
    int shift;
    mp_err err;

    (void) GetNumberFromObj(NULL, valuePtr, &ptr1, &type1);
    (void) GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2);

    switch (opcode) {
    case INST_MOD:
	/* TODO: Attempts to re-use unshared operands on stack */
7790
7791
7792
7793
7794
7795
7796
7797
7798


7799
7800
7801
7802

7803
7804


7805
7806
7807
7808
7809
7810
7811

7812
7813
7814
7815
7816
7817
7818
8036
8037
8038
8039
8040
8041
8042


8043
8044
8045
8046
8047

8048
8049

8050
8051
8052
8053
8054
8055
8056
8057

8058
8059
8060
8061
8062
8063
8064
8065







-
-
+
+



-
+

-
+
+






-
+







		wQuotient = w1 / w2;

		/*
		 * Force Tcl's integer division rules.
		 * TODO: examine for logic simplification
		 */

		if (((wQuotient < (Tcl_WideInt) 0)
			|| ((wQuotient == (Tcl_WideInt) 0)
		if (((wQuotient < 0)
			|| ((wQuotient == 0)
			&& ((w1 < 0 && w2 > 0)
			|| (w1 > 0 && w2 < 0))))
			&& (wQuotient * w2 != w1)) {
		    wQuotient -= (Tcl_WideInt) 1;
		    wQuotient -= 1;
		}
		wRemainder = w1 - w2*wQuotient;
		wRemainder = (Tcl_WideInt)((Tcl_WideUInt)w1 -
			(Tcl_WideUInt)w2*(Tcl_WideUInt)wQuotient);
		WIDE_RESULT(wRemainder);
	    }

	    Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);

	    /* TODO: internals intrusion */
	    if ((w1 > ((Tcl_WideInt) 0)) ^ !mp_isneg(&big2)) {
	    if ((w1 > ((Tcl_WideInt)0)) ^ !mp_isneg(&big2)) {
		/*
		 * Arguments are opposite sign; remainder is sum.
		 */

		err = mp_init_i64(&big1, w1);
		if (err == MP_OKAY) {
		    err = mp_add(&big2, &big1, &big2);
7829
7830
7831
7832
7833
7834
7835
7836

7837
7838
7839
7840
7841
7842
7843
8076
8077
8078
8079
8080
8081
8082

8083
8084
8085
8086
8087
8088
8089
8090







-
+







	     */

	    mp_clear(&big2);
	    return NULL;
	}
	Tcl_GetBignumFromObj(NULL, valuePtr, &big1);
	Tcl_GetBignumFromObj(NULL, value2Ptr, &big2);
	err = mp_init_multi(&bigResult, &bigRemainder, NULL);
	err = mp_init_multi(&bigResult, &bigRemainder, (void *)NULL);
	if (err == MP_OKAY) {
	    err = mp_div(&big1, &big2, &bigResult, &bigRemainder);
	}
	if ((err == MP_OKAY) && !mp_iszero(&bigRemainder) && (bigRemainder.sign != big2.sign)) {
	    /*
	     * Convert to Tcl's integer division rules.
	     */
7916
7917
7918
7919
7920
7921
7922
7923

7924
7925
7926


7927
7928
7929
7930
7931
7932
7933
8163
8164
8165
8166
8167
8168
8169

8170



8171
8172
8173
8174
8175
8176
8177
8178
8179







-
+
-
-
-
+
+







	    /*
	     * Handle shifts within the native wide range.
	     */

	    if ((type1 == TCL_NUMBER_INT)
		    && ((size_t)shift < CHAR_BIT*sizeof(Tcl_WideInt))) {
		w1 = *((const Tcl_WideInt *)ptr1);
		if (!((w1>0 ? w1 : ~w1)
		if (!((w1 > 0 ? w1 : ~w1) & -(
			& -(((Tcl_WideInt)1)
			<< (CHAR_BIT*sizeof(Tcl_WideInt) - 1 - shift)))) {
		    WIDE_RESULT(w1 << shift);
			((Tcl_WideUInt)1) << (CHAR_BIT*sizeof(Tcl_WideInt) - 1 - shift)))) {
		    WIDE_RESULT((Tcl_WideUInt)w1 << shift);
		}
	    }
	} else {
	    /*
	     * Quickly force large right shifts to 0 or -1.
	     */

8074
8075
8076
8077
8078
8079
8080
8081

8082
8083
8084
8085
8086
8087
8088
8320
8321
8322
8323
8324
8325
8326

8327
8328
8329
8330
8331
8332
8333
8334







-
+







		 * Anything to the first power is itself
		 */

		return NULL;
	    }

	    negativeExponent = (w2 < 0);
	    oddExponent = (int) (w2 & (Tcl_WideInt)1);
	    oddExponent = (int)w2 & 1;
	} else {
	    Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
	    negativeExponent = mp_isneg(&big2);
	    err = mp_mod_2d(&big2, 1, &big2);
	    oddExponent = (err == MP_OKAY) && !mp_iszero(&big2);
	    mp_clear(&big2);
	}
8145
8146
8147
8148
8149
8150
8151
8152

8153
8154
8155
8156
8157
8158
8159
8160
8161
8162
8163
8164
8165
8166
8167
8168
8169
8170
8171
8172


8173
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184


8185
8186
8187
8188
8189
8190
8191
8391
8392
8393
8394
8395
8396
8397

8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414
8415
8416


8417
8418
8419
8420
8421
8422
8423
8424
8425
8426
8427
8428


8429
8430
8431
8432
8433
8434
8435
8436
8437







-
+


















-
-
+
+










-
-
+
+







		WIDE_RESULT(-1);
	}

	/*
	 * We refuse to accept exponent arguments that exceed one mp_digit
	 * which means the max exponent value is 2**28-1 = 0x0FFFFFFF =
	 * 268435455, which fits into a signed 32 bit int which is within the
	 * range of the long int type. This means any numeric Tcl_Obj value
	 * range of the Tcl_WideInt type. This means any numeric Tcl_Obj value
	 * not using TCL_NUMBER_INT type must hold a value larger than we
	 * accept.
	 */

	if (type2 != TCL_NUMBER_INT) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "exponent too large", -1));
	    return GENERAL_ARITHMETIC_ERROR;
	}

	/* From here (up to overflowExpon) w1 and exponent w2 are wide-int's. */
	assert(type1 == TCL_NUMBER_INT && type2 == TCL_NUMBER_INT);

	if (w1 == 2) {
	    /*
	     * Reduce small powers of 2 to shifts.
	     */

	    if ((Tcl_WideUInt) w2 < (Tcl_WideUInt) CHAR_BIT*sizeof(Tcl_WideInt) - 1) {
		WIDE_RESULT(((Tcl_WideInt) 1) << (int)w2);
	    if ((Tcl_WideUInt)w2 < (Tcl_WideUInt)CHAR_BIT*sizeof(Tcl_WideInt) - 1) {
		WIDE_RESULT(((Tcl_WideInt)1) << (int)w2);
	    }
	    goto overflowExpon;
	}
	if (w1 == -2) {
	    int signum = oddExponent ? -1 : 1;

	    /*
	     * Reduce small powers of 2 to shifts.
	     */

	    if ((Tcl_WideUInt) w2 < CHAR_BIT * sizeof(Tcl_WideInt) - 1) {
		WIDE_RESULT(signum * (((Tcl_WideInt) 1) << (int) w2));
	    if ((Tcl_WideUInt)w2 < CHAR_BIT * sizeof(Tcl_WideInt) - 1) {
		WIDE_RESULT(signum * (((Tcl_WideInt)1) << (int) w2));
	    }
	    goto overflowExpon;
	}
	if (w2 - 2 < (long)MaxBase64Size
		&& w1 <=  MaxBase64[w2 - 2]
		&& w1 >= -MaxBase64[w2 - 2]) {
	    /*
8229
8230
8231
8232
8233
8234
8235
8236

8237
8238
8239
8240
8241
8242
8243
8244

8245

8246
8247
8248
8249
8250
8251
8252
8475
8476
8477
8478
8479
8480
8481

8482
8483
8484
8485
8486
8487
8488
8489
8490
8491

8492
8493
8494
8495
8496
8497
8498
8499







-
+








+
-
+







		WIDE_RESULT(wResult);
	    }
	}

    overflowExpon:

	if ((TclGetWideIntFromObj(NULL, value2Ptr, &w2) != TCL_OK)
		|| (value2Ptr->typePtr != &tclIntType)
		|| !TclHasInternalRep(value2Ptr, &tclIntType)
		|| (Tcl_WideUInt)w2 >= (1<<28)) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "exponent too large", -1));
	    return GENERAL_ARITHMETIC_ERROR;
	}
	Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
	err = mp_init(&bigResult);
	if (err == MP_OKAY) {
	    /* Don't use "mp_expt_n" directly here, it doesn't exist in libtommath 1.2 */
	    err = mp_expt_u32(&big1, (unsigned int)w2, &bigResult);
	    err = TclBN_mp_expt_n(&big1, (int)w2, &bigResult);
	}
	if (err != MP_OKAY) {
	    return OUT_OF_MEMORY;
	}
	mp_clear(&big1);
	BIG_RESULT(&bigResult);
    }
8295
8296
8297
8298
8299
8300
8301
8302

8303
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316


8317
8318
8319
8320
8321
8322
8323
8324
8325
8326
8327
8328
8329
8330


8331
8332
8333
8334
8335
8336
8337
8338
8542
8543
8544
8545
8546
8547
8548

8549
8550
8551
8552
8553
8554
8555
8556
8557
8558
8559
8560
8561


8562
8563

8564
8565
8566
8567
8568
8569
8570
8571
8572
8573
8574


8575
8576

8577
8578
8579
8580
8581
8582
8583







-
+












-
-
+
+
-











-
-
+
+
-








	doubleResult:
#ifndef ACCEPT_NAN
	    /*
	     * Check now for IEEE floating-point error.
	     */

	    if (TclIsNaN(dResult)) {
	    if (isnan(dResult)) {
		TclExprFloatError(interp, dResult);
		return GENERAL_ARITHMETIC_ERROR;
	    }
#endif
	    DOUBLE_RESULT(dResult);
	}
	if ((type1 == TCL_NUMBER_INT) && (type2 == TCL_NUMBER_INT)) {
	    w1 = *((const Tcl_WideInt *)ptr1);
	    w2 = *((const Tcl_WideInt *)ptr2);

	    switch (opcode) {
	    case INST_ADD:
		wResult = w1 + w2;
		if ((type1 == TCL_NUMBER_INT) || (type2 == TCL_NUMBER_INT))
		wResult = (Tcl_WideInt)((Tcl_WideUInt)w1 + (Tcl_WideUInt)w2);
		if ((type1 == TCL_NUMBER_INT) || (type2 == TCL_NUMBER_INT)) {
		{
		    /*
		     * Check for overflow.
		     */

		    if (Overflowing(w1, w2, wResult)) {
			goto overflowBasic;
		    }
		}
		break;

	    case INST_SUB:
		wResult = w1 - w2;
		if ((type1 == TCL_NUMBER_INT) || (type2 == TCL_NUMBER_INT))
		wResult = (Tcl_WideInt)((Tcl_WideUInt)w1 - (Tcl_WideUInt)w2);
		if ((type1 == TCL_NUMBER_INT) || (type2 == TCL_NUMBER_INT)) {
		{
		    /*
		     * Must check for overflow. The macro tests for overflows
		     * in sums by looking at the sign bits. As we have a
		     * subtraction here, we are adding -w2. As -w2 could in
		     * turn overflow, we test with ~w2 instead: it has the
		     * opposite sign bit to w2 so it does the job. Note that
		     * the only "bad" case (w2==0) is irrelevant for this
8391
8392
8393
8394
8395
8396
8397
8398
8399


8400
8401
8402

8403
8404
8405

8406
8407
8408

8409
8410
8411
8412
8413
8414
8415
8636
8637
8638
8639
8640
8641
8642


8643
8644
8645
8646

8647
8648
8649

8650
8651
8652

8653
8654
8655
8656
8657
8658
8659
8660







-
-
+
+


-
+


-
+


-
+







	}

    overflowBasic:
	Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
	Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
	err = mp_init(&bigResult);
	if (err == MP_OKAY) {
	switch (opcode) {
	case INST_ADD:
	    switch (opcode) {
	    case INST_ADD:
		err = mp_add(&big1, &big2, &bigResult);
		break;
	case INST_SUB:
	    case INST_SUB:
		err = mp_sub(&big1, &big2, &bigResult);
		break;
	case INST_MULT:
	    case INST_MULT:
		err = mp_mul(&big1, &big2, &bigResult);
		break;
	case INST_DIV:
	    case INST_DIV:
		if (mp_iszero(&big2)) {
		    mp_clear(&big1);
		    mp_clear(&big2);
		    mp_clear(&bigResult);
		    return DIVIDED_BY_ZERO;
		}
		err = mp_init(&bigRemainder);
8442
8443
8444
8445
8446
8447
8448
8449

8450
8451
8452
8453
8454
8455
8456
8687
8688
8689
8690
8691
8692
8693

8694
8695
8696
8697
8698
8699
8700
8701







-
+







}

static Tcl_Obj *
ExecuteExtendedUnaryMathOp(
    int opcode,			/* What operation to perform. */
    Tcl_Obj *valuePtr)		/* The operand on the stack. */
{
    ClientData ptr;
    void *ptr = NULL;
    int type;
    Tcl_WideInt w;
    mp_int big;
    Tcl_Obj *objResultPtr;
    mp_err err = MP_OKAY;

    (void) GetNumberFromObj(NULL, valuePtr, &ptr, &type);
8522
8523
8524
8525
8526
8527
8528
8529

8530
8531
8532
8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544
8545
8546
8547
8548
8549
8550

8551
8552
8553
8554
8555

8556
8557
8558
8559
8560
8561
8562
8767
8768
8769
8770
8771
8772
8773

8774
8775
8776
8777
8778
8779
8780
8781
8782
8783
8784
8785
8786
8787
8788
8789
8790
8791
8792
8793
8794

8795
8796
8797
8798
8799

8800
8801
8802
8803
8804
8805
8806
8807







-
+




















-
+




-
+








int
TclCompareTwoNumbers(
    Tcl_Obj *valuePtr,
    Tcl_Obj *value2Ptr)
{
    int type1 = TCL_NUMBER_NAN, type2 = TCL_NUMBER_NAN, compare;
    ClientData ptr1, ptr2;
    void *ptr1, *ptr2;
    mp_int big1, big2;
    double d1, d2, tmp;
    Tcl_WideInt w1, w2;

    (void) GetNumberFromObj(NULL, valuePtr, &ptr1, &type1);
    (void) GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2);

    switch (type1) {
    case TCL_NUMBER_INT:
	w1 = *((const Tcl_WideInt *)ptr1);
	switch (type2) {
	case TCL_NUMBER_INT:
	    w2 = *((const Tcl_WideInt *)ptr2);
	wideCompare:
	    return (w1 < w2) ? MP_LT : ((w1 > w2) ? MP_GT : MP_EQ);
	case TCL_NUMBER_DOUBLE:
	    d2 = *((const double *)ptr2);
	    d1 = (double) w1;

	    /*
	     * If the double has a fractional part, or if the long can be
	     * If the double has a fractional part, or if the Tcl_WideInt can be
	     * converted to double without loss of precision, then compare as
	     * doubles.
	     */

	    if (DBL_MANT_DIG > CHAR_BIT*sizeof(Tcl_WideInt) || w1 == (Tcl_WideInt) d1
	    if (DBL_MANT_DIG > CHAR_BIT*sizeof(Tcl_WideInt) || w1 == (Tcl_WideInt)d1
		    || modf(d2, &tmp) != 0.0) {
		goto doubleCompare;
	    }

	    /*
	     * Otherwise, to make comparision based on full precision, need to
	     * convert the double to a suitably sized integer.
8571
8572
8573
8574
8575
8576
8577
8578

8579
8580
8581
8582
8583
8584
8585
8816
8817
8818
8819
8820
8821
8822

8823
8824
8825
8826
8827
8828
8829
8830







-
+








	    if (d2 < (double)WIDE_MIN) {
		return MP_GT;
	    }
	    if (d2 > (double)WIDE_MAX) {
		return MP_LT;
	    }
	    w2 = (Tcl_WideInt) d2;
	    w2 = (Tcl_WideInt)d2;
	    goto wideCompare;
	case TCL_NUMBER_BIG:
	    Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
	    if (mp_isneg(&big2)) {
		compare = MP_GT;
	    } else {
		compare = MP_LT;
8596
8597
8598
8599
8600
8601
8602
8603

8604
8605
8606
8607
8608
8609
8610
8611
8612

8613
8614
8615

8616
8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628

8629
8630
8631
8632
8633
8634
8635
8636
8637
8638
8639
8640
8641
8642
8643
8644
8645
8646
8647
8648

8649
8650
8651
8652
8653
8654
8655
8656
8657
8658

8659
8660
8661
8662
8663
8664
8665
8841
8842
8843
8844
8845
8846
8847

8848
8849
8850
8851
8852
8853
8854
8855
8856

8857
8858
8859

8860
8861
8862
8863
8864
8865
8866
8867
8868
8869
8870
8871
8872

8873
8874
8875
8876
8877
8878
8879
8880
8881
8882
8883
8884
8885
8886
8887
8888
8889
8890
8891
8892

8893
8894
8895
8896
8897
8898
8899
8900
8901
8902

8903
8904
8905
8906
8907
8908
8909
8910







-
+








-
+


-
+












-
+



















-
+









-
+







	    d2 = *((const double *)ptr2);
	doubleCompare:
	    return (d1 < d2) ? MP_LT : ((d1 > d2) ? MP_GT : MP_EQ);
	case TCL_NUMBER_INT:
	    w2 = *((const Tcl_WideInt *)ptr2);
	    d2 = (double) w2;
	    if (DBL_MANT_DIG > CHAR_BIT*sizeof(Tcl_WideInt)
		    || w2 == (Tcl_WideInt) d2 || modf(d1, &tmp) != 0.0) {
		    || w2 == (Tcl_WideInt)d2 || modf(d1, &tmp) != 0.0) {
		goto doubleCompare;
	    }
	    if (d1 < (double)WIDE_MIN) {
		return MP_LT;
	    }
	    if (d1 > (double)WIDE_MAX) {
		return MP_GT;
	    }
	    w1 = (Tcl_WideInt) d1;
	    w1 = (Tcl_WideInt)d1;
	    goto wideCompare;
	case TCL_NUMBER_BIG:
	    if (TclIsInfinite(d1)) {
	    if (isinf(d1)) {
		return (d1 > 0.0) ? MP_GT : MP_LT;
	    }
	    Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
	    if ((d1 < (double)WIDE_MAX) && (d1 > (double)WIDE_MIN)) {
		if (mp_isneg(&big2)) {
		    compare = MP_GT;
		} else {
		    compare = MP_LT;
		}
		mp_clear(&big2);
		return compare;
	    }
	    if (DBL_MANT_DIG > CHAR_BIT*sizeof(long)
	    if (DBL_MANT_DIG > CHAR_BIT*sizeof(Tcl_WideInt)
		    && modf(d1, &tmp) != 0.0) {
		d2 = TclBignumToDouble(&big2);
		mp_clear(&big2);
		goto doubleCompare;
	    }
	    Tcl_InitBignumFromDouble(NULL, d1, &big1);
	    goto bigCompare;
	}
    break;

    case TCL_NUMBER_BIG:
	Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
	switch (type2) {
	case TCL_NUMBER_INT:
	    compare = mp_cmp_d(&big1, 0);
	    mp_clear(&big1);
	    return compare;
	case TCL_NUMBER_DOUBLE:
	    d2 = *((const double *)ptr2);
	    if (TclIsInfinite(d2)) {
	    if (isinf(d2)) {
		compare = (d2 > 0.0) ? MP_LT : MP_GT;
		mp_clear(&big1);
		return compare;
	    }
	    if ((d2 < (double)WIDE_MAX) && (d2 > (double)WIDE_MIN)) {
		compare = mp_cmp_d(&big1, 0);
		mp_clear(&big1);
		return compare;
	    }
	    if (DBL_MANT_DIG > CHAR_BIT*sizeof(long)
	    if (DBL_MANT_DIG > CHAR_BIT*sizeof(Tcl_WideInt)
		    && modf(d2, &tmp) != 0.0) {
		d1 = TclBignumToDouble(&big1);
		mp_clear(&big1);
		goto doubleCompare;
	    }
	    Tcl_InitBignumFromDouble(NULL, d2, &big2);
	    goto bigCompare;
8695
8696
8697
8698
8699
8700
8701
8702

8703
8704
8705
8706
8707


8708


8709
8710
8711
8712
8713
8714





8715
8716
8717
8718
8719
8720
8721
8722
8723
8724
8725
8726
8727







8728
8729
8730
8731



8732
8733
8734
8735
8736


8737
8738
8739
8740
8741
8742
8743
8940
8941
8942
8943
8944
8945
8946

8947
8948
8949
8950
8951
8952
8953
8954

8955
8956
8957
8958
8959
8960
8961

8962
8963
8964
8965
8966
8967
8968
8969
8970
8971
8972
8973
8974
8975
8976



8977
8978
8979
8980
8981
8982
8983
8984



8985
8986
8987
8988
8989
8990
8991

8992
8993
8994
8995
8996
8997
8998
8999
9000







-
+





+
+
-
+
+





-
+
+
+
+
+










-
-
-
+
+
+
+
+
+
+

-
-
-
+
+
+




-
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
PrintByteCodeInfo(
    ByteCode *codePtr)	/* The bytecode whose summary is printed to
    ByteCode *codePtr)		/* The bytecode whose summary is printed to
				 * stdout. */
{
    Proc *procPtr = codePtr->procPtr;
    Interp *iPtr = (Interp *) *codePtr->interpHandle;

    fprintf(stdout,
	    "\nExecuting ByteCode 0x%p, refCt %" TCL_Z_MODIFIER
    fprintf(stdout, "\nExecuting ByteCode 0x%p, refCt %" TCL_Z_MODIFIER "u, epoch %" TCL_Z_MODIFIER "u, interp 0x%p (epoch %" TCL_Z_MODIFIER "u)\n",
	    "u, epoch %" TCL_Z_MODIFIER "u, interp 0x%p (epoch %"
	    TCL_Z_MODIFIER "u)\n",
	    codePtr, codePtr->refCount, codePtr->compileEpoch, iPtr,
	    iPtr->compileEpoch);
    fprintf(stdout, "  Source: ");
    TclPrintSource(stdout, codePtr->source, 60);

    fprintf(stdout, "\n  Cmds %d, src %d, inst %u, litObjs %u, aux %d, stkDepth %u, code/src %.2f\n",
    fprintf(stdout,
	    "\n  Cmds %" TCL_Z_MODIFIER "u, src %" TCL_Z_MODIFIER
	    "u, inst %" TCL_Z_MODIFIER "u, litObjs %" TCL_Z_MODIFIER
	    "u, aux %" TCL_Z_MODIFIER "u, stkDepth %" TCL_Z_MODIFIER
	    "u, code/src %.2f\n",
	    codePtr->numCommands, codePtr->numSrcBytes,
	    codePtr->numCodeBytes, codePtr->numLitObjects,
	    codePtr->numAuxDataItems, codePtr->maxStackDepth,
#ifdef TCL_COMPILE_STATS
	    codePtr->numSrcBytes?
		    ((float)codePtr->structureSize)/codePtr->numSrcBytes :
#endif
	    0.0);

#ifdef TCL_COMPILE_STATS
    fprintf(stdout, "  Code %lu = header %lu+inst %d+litObj %lu+exc %lu+aux %lu+cmdMap %d\n",
	    (unsigned long) codePtr->structureSize,
	    (unsigned long) (sizeof(ByteCode)-sizeof(size_t)-sizeof(Tcl_Time)),
    fprintf(stdout,
	    "  Code %" TCL_Z_MODIFIER "u = header %" TCL_Z_MODIFIER
	    "u+inst %" TCL_Z_MODIFIER "u+litObj %" TCL_Z_MODIFIER
	    "u+exc %" TCL_Z_MODIFIER "u+aux %" TCL_Z_MODIFIER
	    "u+cmdMap %" TCL_Z_MODIFIER "u\n",
	    codePtr->structureSize,
	    offsetof(ByteCode, localCachePtr),
	    codePtr->numCodeBytes,
	    (unsigned long) (codePtr->numLitObjects * sizeof(Tcl_Obj *)),
	    (unsigned long) (codePtr->numExceptRanges*sizeof(ExceptionRange)),
	    (unsigned long) (codePtr->numAuxDataItems * sizeof(AuxData)),
	    codePtr->numLitObjects * sizeof(Tcl_Obj *),
	    codePtr->numExceptRanges*sizeof(ExceptionRange),
	    codePtr->numAuxDataItems * sizeof(AuxData),
	    codePtr->numCmdLocBytes);
#endif /* TCL_COMPILE_STATS */
    if (procPtr != NULL) {
	fprintf(stdout,
		"  Proc 0x%p, refCt %" TCL_Z_MODIFIER "u, args %d, compiled locals %d\n",
		"  Proc 0x%p, refCt %" TCL_Z_MODIFIER "u, args %"
		TCL_Z_MODIFIER "u, compiled locals %" TCL_Z_MODIFIER "u\n",
		procPtr, procPtr->refCount, procPtr->numArgs,
		procPtr->numCompiledLocals);
    }
}
#endif /* TCL_COMPILE_DEBUG */

/*
8758
8759
8760
8761
8762
8763
8764
8765

8766
8767
8768
8769

8770
8771
8772
8773
8774
8775

8776
8777
8778


8779
8780
8781
8782
8783

8784
8785
8786
8787
8788
8789
8790



8791
8792
8793

8794
8795

8796
8797
8798

8799
8800
8801
8802
8803
8804
8805
8806

8807
8808
8809
8810
8811
8812
8813
9015
9016
9017
9018
9019
9020
9021

9022
9023
9024
9025

9026
9027
9028
9029
9030
9031

9032
9033


9034
9035
9036
9037
9038
9039

9040
9041
9042
9043
9044



9045
9046
9047
9048
9049

9050


9051
9052
9053

9054
9055
9056
9057
9058
9059
9060
9061

9062
9063
9064
9065
9066
9067
9068
9069







-
+



-
+





-
+

-
-
+
+




-
+




-
-
-
+
+
+


-
+
-
-
+


-
+







-
+







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

#ifdef TCL_COMPILE_DEBUG
static void
ValidatePcAndStackTop(
    ByteCode *codePtr,	/* The bytecode whose summary is printed to
    ByteCode *codePtr,		/* The bytecode whose summary is printed to
				 * stdout. */
    const unsigned char *pc,	/* Points to first byte of a bytecode
				 * instruction. The program counter. */
    int stackTop,		/* Current stack top. Must be between
    size_t stackTop,		/* Current stack top. Must be between
				 * stackLowerBound and stackUpperBound
				 * (inclusive). */
    int checkStack)		/* 0 if the stack depth check should be
				 * skipped. */
{
    int stackUpperBound = codePtr->maxStackDepth;
    size_t stackUpperBound = codePtr->maxStackDepth;
				/* Greatest legal value for stackTop. */
    size_t relativePc = (size_t) (pc - codePtr->codeStart);
    size_t codeStart = (size_t) codePtr->codeStart;
    size_t relativePc = (size_t)(pc - codePtr->codeStart);
    size_t codeStart = (size_t)codePtr->codeStart;
    size_t codeEnd = (size_t)
	    (codePtr->codeStart + codePtr->numCodeBytes);
    unsigned char opCode = *pc;

    if (((size_t) pc < codeStart) || ((size_t) pc > codeEnd)) {
    if ((PTR2UINT(pc) < codeStart) || (PTR2UINT(pc) > codeEnd)) {
	fprintf(stderr, "\nBad instruction pc 0x%p in TclNRExecuteByteCode\n",
		pc);
	Tcl_Panic("TclNRExecuteByteCode execution failure: bad pc");
    }
    if ((unsigned) opCode >= LAST_INST_OPCODE) {
	fprintf(stderr, "\nBad opcode %d at pc %" TCL_Z_MODIFIER "u in TclNRExecuteByteCode\n",
		(unsigned) opCode, relativePc);
    if (opCode >= LAST_INST_OPCODE) {
	fprintf(stderr, "\nBad opcode %u at pc %" TCL_Z_MODIFIER "u in TclNRExecuteByteCode\n",
		opCode, relativePc);
	Tcl_Panic("TclNRExecuteByteCode execution failure: bad opcode");
    }
    if (checkStack &&
    if (checkStack && (stackTop > stackUpperBound)) {
	    ((stackTop < 0) || (stackTop > stackUpperBound))) {
	size_t numChars;
	Tcl_Size numChars;
	const char *cmd = GetSrcInfoForPc(pc, codePtr, &numChars, NULL, NULL);

	fprintf(stderr, "\nBad stack top %d at pc %" TCL_Z_MODIFIER "u in TclNRExecuteByteCode (min 0, max %i)",
	fprintf(stderr, "\nBad stack top %" TCL_Z_MODIFIER "u at pc %" TCL_Z_MODIFIER "u in TclNRExecuteByteCode (min 0, max %" TCL_Z_MODIFIER "u)",
		stackTop, relativePc, stackUpperBound);
	if (cmd != NULL) {
	    Tcl_Obj *message;

	    TclNewLiteralStringObj(message, "\n executing ");
	    Tcl_IncrRefCount(message);
	    Tcl_AppendLimitedToObj(message, cmd, numChars, 100, NULL);
	    fprintf(stderr,"%s\n", TclGetString(message));
	    fprintf(stderr, "%s\n", TclGetString(message));
	    Tcl_DecrRefCount(message);
	} else {
	    fprintf(stderr, "\n");
	}
	Tcl_Panic("TclNRExecuteByteCode execution failure: bad stack top");
    }
}
8831
8832
8833
8834
8835
8836
8837

8838

8839
8840
8841
8842
8843

8844
8845
8846
8847
8848
8849
8850
8851
8852
8853
8854



















8855
8856
8857
8858
8859
8860
8861
8862
8863
8864
8865
8866
8867
8868



8869
8870
8871
8872
8873
8874
8875
9087
9088
9089
9090
9091
9092
9093
9094

9095
9096
9097
9098
9099

9100
9101
9102
9103
9104
9105
9106
9107
9108
9109
9110
9111
9112
9113
9114
9115
9116
9117
9118
9119
9120
9121
9122
9123
9124
9125
9126
9127
9128
9129
9130
9131
9132
9133
9134
9135
9136
9137
9138
9139
9140
9141



9142
9143
9144
9145
9146
9147
9148
9149
9150
9151







+
-
+




-
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
-
-
+
+
+







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

static void
IllegalExprOperandType(
    Tcl_Interp *interp,		/* Interpreter to which error information
				 * pertains. */
    const char *ord,		/* "first ", "second " or "" */
    const unsigned char *pc, /* Points to the instruction being executed
    const unsigned char *pc,	/* Points to the instruction being executed
				 * when the illegal type was found. */
    Tcl_Obj *opndPtr)		/* Points to the operand holding the value
				 * with the illegal type. */
{
    ClientData ptr;
    void *ptr;
    int type;
    const unsigned char opcode = *pc;
    const char *description, *op = "unknown";

    if (opcode == INST_EXPON) {
	op = "**";
    } else if (opcode <= INST_LNOT) {
	op = operatorStrings[opcode - INST_BITOR];
    }

    if (GetNumberFromObj(NULL, opndPtr, &ptr, &type) != TCL_OK) {
	Tcl_Size length;
	if (TclHasInternalRep(opndPtr, &tclDictType)) {
	    Tcl_DictObjSize(NULL, opndPtr, &length);
	    if (length > 0) {
	    listRep:
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"cannot use a list as %soperand of \"%s\"", ord, op));
		Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", "list", (char *)NULL);
		return;
	    }
	}
	Tcl_ObjTypeLengthProc *lengthProc = TclObjTypeHasProc(opndPtr, lengthProc);
	Tcl_Size objcPtr;
	Tcl_Obj **objvPtr;
	if ((lengthProc && lengthProc(opndPtr) > 1)
		|| ((TclMaxListLength(TclGetString(opndPtr), TCL_INDEX_NONE, NULL) > 1)
		&& (Tcl_ListObjGetElements(NULL, opndPtr, &objcPtr, &objvPtr) == TCL_OK))) {
	    goto listRep;
	}
	description = "non-numeric string";
    } else if (type == TCL_NUMBER_NAN) {
	description = "non-numeric floating-point value";
    } else if (type == TCL_NUMBER_DOUBLE) {
	description = "floating-point value";
    } else {
	/* TODO: No caller needs this. Eliminate? */
	description = "(big) integer";
    }

    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "can't use %s \"%s\" as operand of \"%s\"", description,
	    TclGetString(opndPtr), op));
    Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", description, NULL);
	    "cannot use %s \"%s\" as %soperand of \"%s\"", description,
	    TclGetString(opndPtr), ord, op));
    Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", description, (char *)NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetSrcInfoForPc, GetSrcInfoForPc, TclGetSourceFromFrame --
 *
8891
8892
8893
8894
8895
8896
8897
8898

8899
8900
8901
8902

8903
8904
8905
8906


8907
8908

8909
8910

8911
8912
8913
8914
8915
8916

8917
8918
8919
8920
8921
8922
8923
9167
9168
9169
9170
9171
9172
9173

9174
9175
9176
9177

9178
9179
9180


9181
9182
9183

9184
9185

9186
9187
9188
9189
9190
9191

9192
9193
9194
9195
9196
9197
9198
9199







-
+



-
+


-
-
+
+

-
+

-
+





-
+







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

Tcl_Obj *
TclGetSourceFromFrame(
    CmdFrame *cfPtr,
    int objc,
    Tcl_Size objc,
    Tcl_Obj *const objv[])
{
    if (cfPtr == NULL) {
        return Tcl_NewListObj(objc, objv);
	return Tcl_NewListObj(objc, objv);
    }
    if (cfPtr->cmdObj == NULL) {
        if (cfPtr->cmd == NULL) {
	    ByteCode *codePtr = (ByteCode *) cfPtr->data.tebc.codePtr;
	if (cfPtr->cmd == NULL) {
	    ByteCode *codePtr = (ByteCode *)cfPtr->data.tebc.codePtr;

            cfPtr->cmd = GetSrcInfoForPc((unsigned char *)
	    cfPtr->cmd = GetSrcInfoForPc((unsigned char *)
		    cfPtr->data.tebc.pc, codePtr, &cfPtr->len, NULL, NULL);
        }
	}
	if (cfPtr->cmd) {
	    cfPtr->cmdObj = Tcl_NewStringObj(cfPtr->cmd, cfPtr->len);
	} else {
	    cfPtr->cmdObj = Tcl_NewListObj(objc, objv);
	}
        Tcl_IncrRefCount(cfPtr->cmdObj);
	Tcl_IncrRefCount(cfPtr->cmdObj);
    }
    return cfPtr->cmdObj;
}

void
TclGetSrcInfoForPc(
    CmdFrame *cfPtr)
8937
8938
8939
8940
8941
8942
8943
8944
8945


8946
8947
8948
8949
8950
8951
8952
9213
9214
9215
9216
9217
9218
9219


9220
9221
9222
9223
9224
9225
9226
9227
9228







-
-
+
+







	/*
	 * We now have the command. We can get the srcOffset back and from
	 * there find the list of word locations for this command.
	 */

	ExtCmdLoc *eclPtr;
	ECL *locPtr = NULL;
	size_t srcOffset;
	int i;
	Tcl_Size srcOffset;
	Tcl_Size i;
	Interp *iPtr = (Interp *) *codePtr->interpHandle;
	Tcl_HashEntry *hePtr =
		Tcl_FindHashEntry(iPtr->lineBCPtr, codePtr);

	if (!hePtr) {
	    return;
	}
8984
8985
8986
8987
8988
8989
8990
8991

8992
8993
8994
8995
8996
8997

8998
8999
9000
9001
9002


9003
9004
9005
9006
9007
9008
9009





9010
9011
9012

9013
9014
9015
9016
9017
9018
9019
9260
9261
9262
9263
9264
9265
9266

9267
9268
9269
9270
9271
9272

9273
9274
9275
9276


9277
9278
9279
9280





9281
9282
9283
9284
9285
9286
9287

9288
9289
9290
9291
9292
9293
9294
9295







-
+





-
+



-
-
+
+


-
-
-
-
-
+
+
+
+
+


-
+







GetSrcInfoForPc(
    const unsigned char *pc,	/* The program counter value for which to
				 * return the closest command's source info.
				 * This points within a bytecode instruction
				 * in codePtr's code. */
    ByteCode *codePtr,		/* The bytecode sequence in which to look up
				 * the command source for the pc. */
    size_t *lengthPtr,		/* If non-NULL, the location where the length
    Tcl_Size *lengthPtr,	/* If non-NULL, the location where the length
				 * of the command's source should be stored.
				 * If NULL, no length is stored. */
    const unsigned char **pcBeg,/* If non-NULL, the bytecode location
				 * where the current instruction starts.
				 * If NULL; no pointer is stored. */
    int *cmdIdxPtr)		/* If non-NULL, the location where the index
    Tcl_Size *cmdIdxPtr)	/* If non-NULL, the location where the index
				 * of the command containing the pc should
				 * be stored. */
{
    size_t pcOffset = (size_t)(pc - codePtr->codeStart);
    size_t numCmds = codePtr->numCommands;
    Tcl_Size pcOffset = pc - codePtr->codeStart;
    Tcl_Size numCmds = codePtr->numCommands;
    unsigned char *codeDeltaNext, *codeLengthNext;
    unsigned char *srcDeltaNext, *srcLengthNext;
    size_t codeOffset, codeLen, codeEnd, srcOffset, srcLen, delta, i;
    int bestDist = INT_MAX;	/* Distance of pc to best cmd's start pc. */
    int bestSrcOffset = -1;	/* Initialized to avoid compiler warning. */
    int bestSrcLength = -1;	/* Initialized to avoid compiler warning. */
    int bestCmdIdx = -1;
    Tcl_Size codeOffset, codeLen, codeEnd, srcOffset, srcLen, delta, i;
    Tcl_Size bestDist = TCL_SIZE_MAX; /* Distance of pc to best cmd's start pc. */
    Tcl_Size bestSrcOffset = -1; /* Initialized to avoid compiler warning. */
    Tcl_Size bestSrcLength = -1; /* Initialized to avoid compiler warning. */
    Tcl_Size bestCmdIdx = -1;

    /* The pc must point within the bytecode */
    assert (pcOffset < (size_t)codePtr->numCodeBytes);
    assert ((pcOffset >= 0) && (pcOffset < codePtr->numCodeBytes));

    /*
     * Decode the code and source offset and length for each command. The
     * closest enclosing command is the last one whose code started before
     * pcOffset.
     */

9081
9082
9083
9084
9085
9086
9087
9088

9089
9090
9091
9092
9093
9094
9095
9096
9097

9098
9099
9100
9101
9102
9103
9104
9357
9358
9359
9360
9361
9362
9363

9364
9365
9366
9367
9368
9369
9370
9371
9372

9373
9374
9375
9376
9377
9378
9379
9380







-
+








-
+







	const unsigned char *curr, *prev;

	/*
	 * Walk from beginning of command or BC to pc, by complete
	 * instructions. Stop when crossing pc; keep previous.
	 */

	curr = ((bestDist == INT_MAX) ? codePtr->codeStart : pc - bestDist);
	curr = ((bestDist == TCL_SIZE_MAX) ? codePtr->codeStart : pc - bestDist);
	prev = curr;
	while (curr <= pc) {
	    prev = curr;
	    curr += tclInstructionTable[*curr].numBytes;
	}
	*pcBeg = prev;
    }

    if (bestDist == INT_MAX) {
    if (bestDist == TCL_SIZE_MAX) {
	return NULL;
    }

    if (lengthPtr != NULL) {
	*lengthPtr = bestSrcLength;
    }

9146
9147
9148
9149
9150
9151
9152
9153

9154
9155
9156
9157
9158
9159
9160
9422
9423
9424
9425
9426
9427
9428

9429
9430
9431
9432
9433
9434
9435
9436







-
+







				 * closer loop ranges). If TCL_CONTINUE, look
				 * for loop ranges that define a continue
				 * point or a catch range. */
    ByteCode *codePtr)		/* Points to the ByteCode in which to search
				 * for the enclosing ExceptionRange. */
{
    ExceptionRange *rangeArrayPtr;
    int numRanges = codePtr->numExceptRanges;
    size_t numRanges = codePtr->numExceptRanges;
    ExceptionRange *rangePtr;
    size_t pcOffset = pc - codePtr->codeStart;
    size_t start;

    if (numRanges == 0) {
	return NULL;
    }
9173
9174
9175
9176
9177
9178
9179
9180

9181
9182
9183
9184
9185
9186
9187
9449
9450
9451
9452
9453
9454
9455

9456
9457
9458
9459
9460
9461
9462
9463







-
+







		(pcOffset < (start + rangePtr->numCodeBytes))) {
	    if (rangePtr->type == CATCH_EXCEPTION_RANGE) {
		return rangePtr;
	    }
	    if (searchMode == TCL_BREAK) {
		return rangePtr;
	    }
	    if (searchMode == TCL_CONTINUE && rangePtr->continueOffset != -1){
	    if (searchMode == TCL_CONTINUE && rangePtr->continueOffset != TCL_INDEX_NONE){
		return rangePtr;
	    }
	}
    }
    return NULL;
}

9236
9237
9238
9239
9240
9241
9242
9243

9244
9245
9246
9247


9248
9249
9250
9251

9252
9253
9254
9255

9256
9257
9258
9259
9260
9261
9262

9263
9264
9265
9266
9267
9268
9269
9512
9513
9514
9515
9516
9517
9518

9519
9520
9521


9522
9523
9524
9525
9526

9527
9528
9529
9530

9531
9532
9533
9534
9535
9536
9537

9538
9539
9540
9541
9542
9543
9544
9545







-
+


-
-
+
+



-
+



-
+






-
+







TclExprFloatError(
    Tcl_Interp *interp,		/* Where to store error message. */
    double value)		/* Value returned after error; used to
				 * distinguish underflows from overflows. */
{
    const char *s;

    if ((errno == EDOM) || TclIsNaN(value)) {
    if ((errno == EDOM) || isnan(value)) {
	s = "domain error: argument not in valid range";
	Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
	Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", s, NULL);
    } else if ((errno == ERANGE) || TclIsInfinite(value)) {
	Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", s, (char *)NULL);
    } else if ((errno == ERANGE) || isinf(value)) {
	if (value == 0.0) {
	    s = "floating-point value too small to represent";
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
	    Tcl_SetErrorCode(interp, "ARITH", "UNDERFLOW", s, NULL);
	    Tcl_SetErrorCode(interp, "ARITH", "UNDERFLOW", s, (char *)NULL);
	} else {
	    s = "floating-point value too large to represent";
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
	    Tcl_SetErrorCode(interp, "ARITH", "OVERFLOW", s, NULL);
	    Tcl_SetErrorCode(interp, "ARITH", "OVERFLOW", s, (char *)NULL);
	}
    } else {
	Tcl_Obj *objPtr = Tcl_ObjPrintf(
		"unknown floating-point error, errno = %d", errno);

	Tcl_SetErrorCode(interp, "ARITH", "UNKNOWN",
		TclGetString(objPtr), NULL);
		TclGetString(objPtr), (char *)NULL);
	Tcl_SetObjResult(interp, objPtr);
    }
}

#ifdef TCL_COMPILE_STATS
/*
 *----------------------------------------------------------------------
9313
9314
9315
9316
9317
9318
9319
9320

9321
9322
9323
9324
9325
9326
9327
9328
9329
9330
9331
9332
9333
9334
9335




9336
9337
9338
9339
9340
9341
9342
9589
9590
9591
9592
9593
9594
9595

9596
9597
9598
9599
9600
9601
9602
9603
9604
9605
9606
9607
9608
9609


9610
9611
9612
9613
9614
9615
9616
9617
9618
9619
9620







-
+













-
-
+
+
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
EvalStatsCmd(
    ClientData unused,		/* Unused. */
    TCL_UNUSED(void *),		/* Unused. */
    Tcl_Interp *interp,		/* The current interpreter. */
    int objc,			/* The number of arguments. */
    Tcl_Obj *const objv[])	/* The argument strings. */
{
    Interp *iPtr = (Interp *) interp;
    LiteralTable *globalTablePtr = &iPtr->literalTable;
    ByteCodeStats *statsPtr = &iPtr->stats;
    double totalCodeBytes, currentCodeBytes;
    double totalLiteralBytes, currentLiteralBytes;
    double objBytesIfUnshared, strBytesIfUnshared, sharingBytesSaved;
    double strBytesSharedMultX, strBytesSharedOnce;
    double numInstructions, currentHeaderBytes;
    size_t numCurrentByteCodes, numByteCodeLits;
    size_t refCountSum, literalMgmtBytes, sum, decadeHigh, length;
    size_t numSharedMultX, numSharedOnce, minSizeDecade, maxSizeDecade, i;
    size_t refCountSum, literalMgmtBytes, sum, decadeHigh;
    size_t numSharedMultX, numSharedOnce, minSizeDecade, maxSizeDecade;
    Tcl_Size i, length;
    size_t ui;
    char *litTableStats;
    LiteralEntry *entryPtr;
    Tcl_Obj *objPtr;

#define Percent(a,b) ((a) * 100.0 / (b))

    TclNewObj(objPtr);
9355
9356
9357
9358
9359
9360
9361
9362

9363
9364
9365
9366
9367
9368
9369
9633
9634
9635
9636
9637
9638
9639

9640
9641
9642
9643
9644
9645
9646
9647







-
+







	    + (statsPtr->numLiteralsCreated * sizeof(Tcl_Obj))
	    + statsPtr->totalLitStringBytes;
    totalCodeBytes = statsPtr->totalByteCodeBytes + totalLiteralBytes;

    numCurrentByteCodes =
	    statsPtr->numCompilations - statsPtr->numByteCodesFreed;
    currentHeaderBytes = numCurrentByteCodes
	    * (sizeof(ByteCode) - sizeof(size_t) - sizeof(Tcl_Time));
	    * offsetof(ByteCode, localCachePtr);
    literalMgmtBytes = sizeof(LiteralTable)
	    + (iPtr->literalTable.numBuckets * sizeof(LiteralEntry *))
	    + (iPtr->literalTable.numEntries * sizeof(LiteralEntry));
    currentLiteralBytes = literalMgmtBytes
	    + iPtr->literalTable.numEntries * sizeof(Tcl_Obj)
	    + statsPtr->currentLitStringBytes;
    currentCodeBytes = statsPtr->currentByteCodeBytes + currentLiteralBytes;
9464
9465
9466
9467
9468
9469
9470
9471

9472
9473
9474

9475
9476
9477
9478
9479
9480
9481
9742
9743
9744
9745
9746
9747
9748

9749
9750
9751

9752
9753
9754
9755
9756
9757
9758
9759







-
+


-
+







    refCountSum = 0;
    numSharedMultX = 0;
    numSharedOnce = 0;
    objBytesIfUnshared = 0.0;
    strBytesIfUnshared = 0.0;
    strBytesSharedMultX = 0.0;
    strBytesSharedOnce = 0.0;
    for (i = 0;  i < globalTablePtr->numBuckets;  i++) {
    for (ui = 0;  ui < globalTablePtr->numBuckets;  ui++) {
	for (entryPtr = globalTablePtr->buckets[i];  entryPtr != NULL;
		entryPtr = entryPtr->nextPtr) {
	    if (TclHasIntRep(entryPtr->objPtr, &tclByteCodeType)) {
	    if (TclHasInternalRep(entryPtr->objPtr, &tclByteCodeType)) {
		numByteCodeLits++;
	    }
	    (void) TclGetStringFromObj(entryPtr->objPtr, &length);
	    refCountSum += entryPtr->refCount;
	    objBytesIfUnshared += (entryPtr->refCount * sizeof(Tcl_Obj));
	    strBytesIfUnshared += (entryPtr->refCount * (length+1));
	    if (entryPtr->refCount > 1) {
9493
9494
9495
9496
9497
9498
9499
9500

9501
9502
9503
9504
9505
9506
9507
9771
9772
9773
9774
9775
9776
9777

9778
9779
9780
9781
9782
9783
9784
9785







-
+







    Tcl_AppendPrintfToObj(objPtr, "\nTotal objects (all interps)\t%" TCL_Z_MODIFIER "u\n",
	    tclObjsAlloced);
    Tcl_AppendPrintfToObj(objPtr, "Current objects\t\t\t%" TCL_Z_MODIFIER "u\n",
	    (tclObjsAlloced - tclObjsFreed));
    Tcl_AppendPrintfToObj(objPtr, "Total literal objects\t\t%" TCL_Z_MODIFIER "u\n",
	    statsPtr->numLiteralsCreated);

    Tcl_AppendPrintfToObj(objPtr, "\nCurrent literal objects\t\t%" TCL_Z_MODIFIER "u (%0.1f%% of current objects)\n",
    Tcl_AppendPrintfToObj(objPtr, "\nCurrent literal objects\t\t%" TCL_SIZE_MODIFIER "d (%0.1f%% of current objects)\n",
	    globalTablePtr->numEntries,
	    Percent(globalTablePtr->numEntries, tclObjsAlloced-tclObjsFreed));
    Tcl_AppendPrintfToObj(objPtr, "  ByteCode literals\t\t%" TCL_Z_MODIFIER "u (%0.1f%% of current literals)\n",
	    numByteCodeLits,
	    Percent(numByteCodeLits, globalTablePtr->numEntries));
    Tcl_AppendPrintfToObj(objPtr, "  Literals reused > 1x\t\t%" TCL_Z_MODIFIER "u\n",
	    numSharedMultX);
9548
9549
9550
9551
9552
9553
9554
9555

9556
9557
9558
9559

9560
9561
9562
9563

9564
9565
9566
9567

9568
9569
9570
9571

9572
9573
9574
9575
9576
9577
9578
9579
9580
9581
9582
9583
9584
9585
9586
9587
9588
9589
9590
9591
9592




9593
9594
9595
9596
9597
9598
9599
9826
9827
9828
9829
9830
9831
9832

9833
9834
9835
9836

9837
9838
9839
9840

9841
9842
9843
9844

9845
9846
9847
9848

9849
9850
9851
9852
9853
9854
9855
9856
9857
9858
9859
9860
9861
9862
9863
9864
9865
9866




9867
9868
9869
9870
9871
9872
9873
9874
9875
9876
9877







-
+



-
+



-
+



-
+



-
+

















-
-
-
-
+
+
+
+







	    statsPtr->currentByteCodeBytes / numCurrentByteCodes);
    Tcl_AppendPrintfToObj(objPtr, "Header            %12.6g   %8.1f%%   %8.1f\n",
	    currentHeaderBytes,
	    Percent(currentHeaderBytes, statsPtr->currentByteCodeBytes),
	    currentHeaderBytes / numCurrentByteCodes);
    Tcl_AppendPrintfToObj(objPtr, "Instructions      %12.6g   %8.1f%%   %8.1f\n",
	    statsPtr->currentInstBytes,
	    Percent(statsPtr->currentInstBytes,statsPtr->currentByteCodeBytes),
	    Percent(statsPtr->currentInstBytes, statsPtr->currentByteCodeBytes),
	    statsPtr->currentInstBytes / numCurrentByteCodes);
    Tcl_AppendPrintfToObj(objPtr, "Literal ptr array %12.6g   %8.1f%%   %8.1f\n",
	    statsPtr->currentLitBytes,
	    Percent(statsPtr->currentLitBytes,statsPtr->currentByteCodeBytes),
	    Percent(statsPtr->currentLitBytes, statsPtr->currentByteCodeBytes),
	    statsPtr->currentLitBytes / numCurrentByteCodes);
    Tcl_AppendPrintfToObj(objPtr, "Exception table   %12.6g   %8.1f%%   %8.1f\n",
	    statsPtr->currentExceptBytes,
	    Percent(statsPtr->currentExceptBytes,statsPtr->currentByteCodeBytes),
	    Percent(statsPtr->currentExceptBytes, statsPtr->currentByteCodeBytes),
	    statsPtr->currentExceptBytes / numCurrentByteCodes);
    Tcl_AppendPrintfToObj(objPtr, "Auxiliary data    %12.6g   %8.1f%%   %8.1f\n",
	    statsPtr->currentAuxBytes,
	    Percent(statsPtr->currentAuxBytes,statsPtr->currentByteCodeBytes),
	    Percent(statsPtr->currentAuxBytes, statsPtr->currentByteCodeBytes),
	    statsPtr->currentAuxBytes / numCurrentByteCodes);
    Tcl_AppendPrintfToObj(objPtr, "Command map       %12.6g   %8.1f%%   %8.1f\n",
	    statsPtr->currentCmdMapBytes,
	    Percent(statsPtr->currentCmdMapBytes,statsPtr->currentByteCodeBytes),
	    Percent(statsPtr->currentCmdMapBytes, statsPtr->currentByteCodeBytes),
	    statsPtr->currentCmdMapBytes / numCurrentByteCodes);

    /*
     * Detailed literal statistics.
     */

    Tcl_AppendPrintfToObj(objPtr, "\nLiteral string sizes:\n");
    Tcl_AppendPrintfToObj(objPtr, "\t Up to length\t\tPercentage\n");
    maxSizeDecade = 0;
    i = 32;
    while (i-- > 0) {
	if (statsPtr->literalCount[i] > 0) {
	    maxSizeDecade = i;
	    break;
	}
    }
    sum = 0;
    for (i = 0;  i <= maxSizeDecade;  i++) {
	decadeHigh = (1 << (i+1)) - 1;
	sum += statsPtr->literalCount[i];
	Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_Z_MODIFIER "u\t\t%8.0f%%\n",
    for (ui = 0;  ui <= maxSizeDecade;  ui++) {
	decadeHigh = (1 << (ui+1)) - 1;
	sum += statsPtr->literalCount[ui];
	Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_SIZE_MODIFIER "d\t\t%8.0f%%\n",
		decadeHigh, Percent(sum, statsPtr->numLiteralsCreated));
    }

    litTableStats = TclLiteralStats(globalTablePtr);
    Tcl_AppendPrintfToObj(objPtr, "\nCurrent literal table statistics:\n%s\n",
	    litTableStats);
    Tcl_Free(litTableStats);
9607
9608
9609
9610
9611
9612
9613
9614

9615
9616
9617


9618
9619

9620
9621
9622
9623
9624




9625
9626
9627
9628
9629
9630
9631
9632
9633
9634
9635
9636
9637

9638
9639
9640


9641
9642

9643
9644
9645
9646
9647




9648
9649
9650
9651
9652
9653
9654
9655
9656
9657
9658
9659
9660

9661
9662
9663


9664
9665

9666
9667
9668
9669



9670
9671
9672
9673
9674
9675
9676
9885
9886
9887
9888
9889
9890
9891

9892
9893


9894
9895
9896
9897
9898
9899




9900
9901
9902
9903
9904
9905
9906
9907
9908
9909
9910
9911
9912
9913
9914
9915

9916
9917


9918
9919
9920
9921
9922
9923




9924
9925
9926
9927
9928
9929
9930
9931
9932
9933
9934
9935
9936
9937
9938
9939

9940
9941


9942
9943
9944
9945
9946
9947



9948
9949
9950
9951
9952
9953
9954
9955
9956
9957







-
+

-
-
+
+


+

-
-
-
-
+
+
+
+












-
+

-
-
+
+


+

-
-
-
-
+
+
+
+












-
+

-
-
+
+


+

-
-
-
+
+
+







    minSizeDecade = maxSizeDecade = 0;
    for (i = 0;  i < 31;  i++) {
	if (statsPtr->srcCount[i] > 0) {
	    minSizeDecade = i;
	    break;
	}
    }
    for (i = 31;  i >= 0;  i--) {
    for (i = 31;  i != TCL_INDEX_NONE;  i--) {
	if (statsPtr->srcCount[i] > 0) {
	    maxSizeDecade = i;
	    break;
	    break;		/* maxSizeDecade to consume 'i' value
				 * below... */
	}
    }
    maxSizeDecade = i;
    sum = 0;
    for (i = minSizeDecade;  i <= maxSizeDecade;  i++) {
	decadeHigh = (1 << (i+1)) - 1;
	sum += statsPtr->srcCount[i];
	Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_Z_MODIFIER "u\t\t%8.0f%%\n",
    for (ui = minSizeDecade;  ui <= maxSizeDecade;  ui++) {
	decadeHigh = (1 << (ui+1)) - 1;
	sum += statsPtr->srcCount[ui];
	Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_SIZE_MODIFIER "d\t\t%8.0f%%\n",
		decadeHigh, Percent(sum, statsPtr->numCompilations));
    }

    Tcl_AppendPrintfToObj(objPtr, "\nByteCode sizes:\n");
    Tcl_AppendPrintfToObj(objPtr, "\t Up to size\t\tPercentage\n");
    minSizeDecade = maxSizeDecade = 0;
    for (i = 0;  i < 31;  i++) {
	if (statsPtr->byteCodeCount[i] > 0) {
	    minSizeDecade = i;
	    break;
	}
    }
    for (i = 31;  i >= 0;  i--) {
    for (i = 31;  i != TCL_INDEX_NONE;  i--) {
	if (statsPtr->byteCodeCount[i] > 0) {
	    maxSizeDecade = i;
	    break;
	    break;		/* maxSizeDecade to consume 'i' value
				 * below... */
	}
    }
    maxSizeDecade = i;
    sum = 0;
    for (i = minSizeDecade;  i <= maxSizeDecade;  i++) {
	decadeHigh = (1 << (i+1)) - 1;
	sum += statsPtr->byteCodeCount[i];
	Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_Z_MODIFIER "u\t\t%8.0f%%\n",
    for (ui = minSizeDecade;  ui <= maxSizeDecade;  i++) {
	decadeHigh = (1 << (ui+1)) - 1;
	sum += statsPtr->byteCodeCount[ui];
	Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_SIZE_MODIFIER "d\t\t%8.0f%%\n",
		decadeHigh, Percent(sum, statsPtr->numCompilations));
    }

    Tcl_AppendPrintfToObj(objPtr, "\nByteCode longevity (excludes Current ByteCodes):\n");
    Tcl_AppendPrintfToObj(objPtr, "\t       Up to ms\t\tPercentage\n");
    minSizeDecade = maxSizeDecade = 0;
    for (i = 0;  i < 31;  i++) {
	if (statsPtr->lifetimeCount[i] > 0) {
	    minSizeDecade = i;
	    break;
	}
    }
    for (i = 31;  i >= 0;  i--) {
    for (i = 31;  i != TCL_INDEX_NONE;  i--) {
	if (statsPtr->lifetimeCount[i] > 0) {
	    maxSizeDecade = i;
	    break;
	    break;		/* maxSizeDecade to consume 'i' value
				 * below... */
	}
    }
    maxSizeDecade = i;
    sum = 0;
    for (i = minSizeDecade;  i <= maxSizeDecade;  i++) {
	decadeHigh = (1 << (i+1)) - 1;
	sum += statsPtr->lifetimeCount[i];
    for (ui = minSizeDecade;  ui <= maxSizeDecade;  ui++) {
	decadeHigh = (1 << (ui+1)) - 1;
	sum += statsPtr->lifetimeCount[ui];
	Tcl_AppendPrintfToObj(objPtr, "\t%12.3f\t\t%8.0f%%\n",
		decadeHigh/1000.0, Percent(sum, statsPtr->numByteCodesFreed));
    }

    /*
     * Instruction counts.
     */

Changes to generic/tclFCmd.c.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tclFCmd.c
 *
 *	This file implements the generic portion of file manipulation
 *	subcommands of the "file" command.
 *
 * Copyright (c) 1996-1998 Sun Microsystems, Inc.
 * Copyright © 1996-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclFileSystem.h"
43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57







-
+







 *	See the user documentation.
 *
 *---------------------------------------------------------------------------
 */

int
TclFileRenameCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Interp for error reporting or recursive
				 * calls in the case of a tricky rename. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument strings passed to Tcl_FileCmd. */
{
    return FileCopyRename(interp, objc, objv, 0);
}
72
73
74
75
76
77
78
79

80
81
82
83
84
85
86
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86







-
+







 *	See the user documentation.
 *
 *---------------------------------------------------------------------------
 */

int
TclFileCopyCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Used for error reporting or recursive calls
				 * in the case of a tricky copy. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument strings passed to Tcl_FileCmd. */
{
    return FileCopyRename(interp, objc, objv, 1);
}
109
110
111
112
113
114
115

116
117
118
119
120
121
122
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) {
130
131
132
133
134
135
136






137
138
139
140
141
142
143
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.
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
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







-
+





-
+
+



+







+
+
+
+
+
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
TclFileMakeDirsCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Used for error reporting. */
    int objc,			/* Number of arguments */
    Tcl_Obj *const objv[])	/* Argument strings passed to Tcl_FileCmd. */
{
    Tcl_Obj *errfile = NULL;
    int result, i, j, pobjc;
    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;
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
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







-
+







+

















+
+
+
+
+
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
TclFileDeleteCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    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;
421
422
423
424
425
426
427
428

429
430
431
432
433
434
435
445
446
447
448
449
450
451

452
453
454
455
456
457
458
459







-
+







	    result = TCL_ERROR;
	    break;
	}
    }
    if (result != TCL_OK) {
	if (errfile == NULL) {
	    /*
	     * We try to accomodate poor error results from our Tcl_FS calls.
	     * We try to accommodate poor error results from our Tcl_FS calls.
	     */

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "error deleting unknown file: %s",
		    Tcl_PosixError(interp)));
	} else {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
478
479
480
481
482
483
484

485
486
487
488






489
490
491






492
493
494
495
496
497
498
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
866
867
868
869
870
871
872
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
898
899
903
904
905
906
907
908
909

910
911
912

913
914
915
916
917
918
919
920









921
922
923
924
925
926
927







-
+


-
+







-
-
-
-
-
-
-
-
-







 *	None.
 *
 *---------------------------------------------------------------------------
 */

static Tcl_Obj *
FileBasename(
    Tcl_Interp *interp,		/* Interp, for error return. */
    TCL_UNUSED(Tcl_Interp *),	/* Interp, for error return. */
    Tcl_Obj *pathPtr)		/* Path whose basename to extract. */
{
    int objc;
    Tcl_Size objc;
    Tcl_Obj *splitPtr;
    Tcl_Obj *resultPtr = NULL;

    splitPtr = Tcl_FSSplitPath(pathPtr, &objc);
    Tcl_IncrRefCount(splitPtr);

    if (objc != 0) {
	if ((objc == 1) && (*TclGetString(pathPtr) == '~')) {
	    Tcl_DecrRefCount(splitPtr);
	    if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) {
		return NULL;
	    }
	    splitPtr = Tcl_FSSplitPath(pathPtr, &objc);
	    Tcl_IncrRefCount(splitPtr);
	}

	/*
	 * Return the last component, unless it is the only component, and it
	 * is the root of an absolute path.
	 */

	if (objc > 0) {
	    Tcl_ListObjIndex(NULL, splitPtr, objc-1, &resultPtr);
942
943
944
945
946
947
948
949

950
951
952
953
954
955
956
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
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
1024







-
+








-
+

+










+
+
+
+
+
+












-
+







 *	May set file attributes for the file name.
 *
 *----------------------------------------------------------------------
 */

int
TclFileAttrsCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* The interpreter for error reporting. */
    int objc,			/* Number of command line arguments. */
    Tcl_Obj *const objv[])	/* The command line objects. */
{
    int result;
    const char *const *attributeStrings;
    const char **attributeStringsAllocated = NULL;
    Tcl_Obj *objStrings = NULL;
    int numObjStrings = -1;
    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);

    /*
     * Get the set of attribute names from the filesystem.
     */

    attributeStrings = Tcl_FSFileAttrStrings(filePtr, &objStrings);
    if (attributeStrings == NULL) {
	int index;
	Tcl_Size index;
	Tcl_Obj *objPtr;

	if (objStrings == NULL) {
	    if (Tcl_GetErrno() != 0) {
		/*
		 * There was an error, probably that the filePtr is not
		 * accepted by any filesystem
1002
1003
1004
1005
1006
1007
1008
1009

1010
1011
1012
1013
1014
1015
1016
1037
1038
1039
1040
1041
1042
1043

1044
1045
1046
1047
1048
1049
1050
1051







-
+








	Tcl_IncrRefCount(objStrings);

	/*
	 * Use objStrings as a list object.
	 */

	if (Tcl_ListObjLength(interp, objStrings, &numObjStrings) != TCL_OK) {
	if (TclListObjLength(interp, objStrings, &numObjStrings) != TCL_OK) {
	    goto end;
	}
	attributeStringsAllocated = (const char **)
		TclStackAlloc(interp, (1+numObjStrings) * sizeof(char *));
	for (index = 0; index < numObjStrings; index++) {
	    Tcl_ListObjIndex(interp, objStrings, index, &objPtr);
	    attributeStringsAllocated[index] = TclGetString(objPtr);
1076
1077
1078
1079
1080
1081
1082
1083

1084
1085
1086
1087
1088
1089
1090
1111
1112
1113
1114
1115
1116
1117

1118
1119
1120
1121
1122
1123
1124
1125







-
+







	int index;
	Tcl_Obj *objPtr = NULL;

	if (numObjStrings == 0) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad option \"%s\", there are no file attributes in this"
		    " filesystem", TclGetString(objv[0])));
	    Tcl_SetErrorCode(interp, "TCL","OPERATION","FATTR","NONE", NULL);
	    Tcl_SetErrorCode(interp, "TCL","OPERATION","FATTR","NONE", (char *)NULL);
	    goto end;
	}

	if (Tcl_GetIndexFromObj(interp, objv[0], attributeStrings,
		"option", TCL_INDEX_TEMP_TABLE, &index) != TCL_OK) {
	    goto end;
	}
1100
1101
1102
1103
1104
1105
1106
1107

1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
1135
1136
1137
1138
1139
1140
1141

1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154

1155
1156
1157
1158
1159
1160
1161
1162







-
+












-
+








	int i, index;

	if (numObjStrings == 0) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad option \"%s\", there are no file attributes in this"
		    " filesystem", TclGetString(objv[0])));
	    Tcl_SetErrorCode(interp, "TCL","OPERATION","FATTR","NONE", NULL);
	    Tcl_SetErrorCode(interp, "TCL","OPERATION","FATTR","NONE", (char *)NULL);
	    goto end;
	}

	for (i = 0; i < objc ; i += 2) {
	    if (Tcl_GetIndexFromObj(interp, objv[i], attributeStrings,
		    "option", TCL_INDEX_TEMP_TABLE, &index) != TCL_OK) {
		goto end;
	    }
	    if (i + 1 == objc) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"value for \"%s\" missing", TclGetString(objv[i])));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "FATTR",
			"NOVALUE", NULL);
			"NOVALUE", (char *)NULL);
		goto end;
	    }
	    if (Tcl_FSFileAttrsSet(interp, index, filePtr,
		    objv[i + 1]) != TCL_OK) {
		goto end;
	    }
	}
1158
1159
1160
1161
1162
1163
1164
1165

1166
1167
1168
1169
1170
1171

1172
1173
1174
1175
1176
1177
1178
1193
1194
1195
1196
1197
1198
1199

1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214







-
+






+







 *	May create a new link.
 *
 *----------------------------------------------------------------------
 */

int
TclFileLinkCmd(
    TCL_UNUSED(ClientData),
    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;
    }

    /*
1207
1208
1209
1210
1211
1212
1213






1214
1215
1216
1217
1218
1219
1220
1221
1222
1223

1224
1225
1226
1227
1228
1229
1230
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







+
+
+
+
+
+









-
+







	    }
	} 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) {
	    /*
	     * We handle three common error cases specially, and for all other
	     * errors, we use the standard posix error message.
	     * errors, we use the standard Posix error message.
	     */

	    if (errno == EEXIST) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"could not create new link \"%s\": that path already"
			" exists", TclGetString(objv[index])));
		Tcl_PosixError(interp);
1264
1265
1266
1267
1268
1269
1270






1271
1272
1273
1274
1275
1276
1277
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) {
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
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392







-
+





+









+
+
+
+
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclFileReadLinkCmd(
    TCL_UNUSED(ClientData),
    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)));
1360
1361
1362
1363
1364
1365
1366
1367

1368
1369
1370
1371
1372
1373
1374
1415
1416
1417
1418
1419
1420
1421

1422
1423
1424
1425
1426
1427
1428
1429







-
+







 *	to a variable, so reentrancy is a potential issue.
 *
 *---------------------------------------------------------------------------
 */

int
TclFileTemporaryCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *nameVarObj = NULL;	/* Variable to store the name of the temporary
				 * file in. */
    Tcl_Obj *nameObj = NULL;	/* Object that will contain the filename. */
1385
1386
1387
1388
1389
1390
1391
1392

1393
1394
1395
1396
1397
1398
1399
1440
1441
1442
1443
1444
1445
1446

1447
1448
1449
1450
1451
1452
1453
1454







-
+







    }

    if (objc > 1) {
	nameVarObj = objv[1];
	TclNewObj(nameObj);
    }
    if (objc > 2) {
	size_t length;
	Tcl_Size length;
	Tcl_Obj *templateObj = objv[2];
	const char *string = TclGetStringFromObj(templateObj, &length);

	/*
	 * Treat an empty string as if it wasn't there.
	 */

1519
1520
1521
1522
1523
1524
1525
1526

1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544

1545
1546
1547
1548
1549
1550
1551
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







-
+

















-
+







 *	Creates a temporary directory.
 *
 *---------------------------------------------------------------------------
 */

int
TclFileTempDirCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *dirNameObj;	/* Object that will contain the directory
				 * name. */
    Tcl_Obj *baseDirObj = NULL, *nameBaseObj = NULL;
				/* Pieces of template. Each piece is NULL if
				 * it is omitted. The platform temporary file
				 * engine might ignore some pieces. */

    if (objc < 1 || objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?template?");
	return TCL_ERROR;
    }

    if (objc > 1) {
	int length;
	Tcl_Size length;
	Tcl_Obj *templateObj = objv[1];
	const char *string = TclGetStringFromObj(templateObj, &length);
	const int onWindows = (tclPlatform == TCL_PLATFORM_WINDOWS);

	/*
	 * Treat an empty string as if it wasn't there.
	 */
1644
1645
1646
1647
1648
1649
1650
1651
1652












































































1653
1654
1655
1656
1657
1658
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






		"can't create temporary directory: %s",
		Tcl_PosixError(interp)));
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, dirNameObj);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclFileHomeCmd --
 *
 *	This function is invoked to process the "file home" Tcl command.
 *	See the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclFileHomeCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *homeDirObj;

    if (objc != 1 && objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?user?");
	return TCL_ERROR;
    }
    homeDirObj = TclGetHomeDirObj(interp, objc == 1 ? NULL : Tcl_GetString(objv[1]));
    if (homeDirObj == NULL) {
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, homeDirObj);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclFileTildeExpandCmd --
 *
 *	This function is invoked to process the "file tildeexpand" Tcl command.
 *	See the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclFileTildeExpandCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *expandedPathObj;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "path");
	return TCL_ERROR;
    }
    expandedPathObj = TclResolveTildePath(interp, objv[1]);
    if (expandedPathObj == NULL) {
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, expandedPathObj);
    return TCL_OK;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclFileName.c.

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
30
31
32
33
34
35
36
37
38
39








40
41
42
43
44
45
46
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52






-
-
+
+




















-
-









+
+
+
+
+
+
+
+







/*
 * tclFileName.c --
 *
 *	This file contains routines for converting file names betwen native
 *	and network form.
 *
 * Copyright (c) 1995-1998 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright © 1995-1998 Sun Microsystems, Inc.
 * Copyright © 1998-1999 Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclRegexp.h"
#include "tclFileSystem.h" /* For TclGetPathType() */

/*
 * The following variable is set in the TclPlatformInit call to one of:
 * TCL_PLATFORM_UNIX or TCL_PLATFORM_WINDOWS.
 */

TclPlatformType tclPlatform = TCL_PLATFORM_UNIX;

/*
 * Prototypes for local procedures defined in this file:
 */

static const char *	DoTildeSubst(Tcl_Interp *interp,
			    const char *user, Tcl_DString *resultPtr);
static const char *	ExtractWinRoot(const char *path,
			    Tcl_DString *resultPtr, int offset,
			    Tcl_PathType *typePtr);
static int		SkipToChar(char **stringPtr, int match);
static Tcl_Obj *	SplitWinPath(const char *path);
static Tcl_Obj *	SplitUnixPath(const char *path);
static int		DoGlob(Tcl_Interp *interp, Tcl_Obj *resultPtr,
			    const char *separators, Tcl_Obj *pathPtr, int flags,
			    char *pattern, Tcl_GlobTypeData *types);
static int		TclGlob(Tcl_Interp *interp, char *pattern,
			    Tcl_Obj *pathPrefix, int globFlags,
			    Tcl_GlobTypeData *types);

/* Flag values used by TclGlob() */

#define TCL_GLOBMODE_DIR	4
#define TCL_GLOBMODE_TAILS	8

/*
 * When there is no support for getting the block size of a file in a stat()
 * call, use this as a guess. Allow it to be overridden in the platform-
 * specific files.
 */

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
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







-
+

















-
-
-
-
+
+
+
+



-
+







 *
 *	Matches the root portion of a Windows path and appends it to the
 *	specified Tcl_DString.
 *
 * Results:
 *	Returns the position in the path immediately after the root including
 *	any trailing slashes. Appends a cleaned up version of the root to the
 *	Tcl_DString at the specified offest.
 *	Tcl_DString at the specified offset.
 *
 * Side effects:
 *	Modifies the specified Tcl_DString.
 *
 *----------------------------------------------------------------------
 */

static const char *
ExtractWinRoot(
    const char *path,		/* Path to parse. */
    Tcl_DString *resultPtr,	/* Buffer to hold result. */
    int offset,			/* Offset in buffer where result should be
				 * stored. */
    Tcl_PathType *typePtr)	/* Where to store pathType result */
{
    int extended = 0;

    if (   (path[0] == '/' || path[0] == '\\')
	&& (path[1] == '/' || path[1] == '\\')
	&& (path[2] == '?')
	&& (path[3] == '/' || path[3] == '\\')) {
    if (       (path[0] == '/' || path[0] == '\\')
	    && (path[1] == '/' || path[1] == '\\')
	    && (path[2] == '?')
	    && (path[3] == '/' || path[3] == '\\')) {
	extended = 1;
	path = path + 4;
	if (path[0] == 'U' && path[1] == 'N' && path[2] == 'C'
	    && (path[3] == '/' || path[3] == '\\')) {
		&& (path[3] == '/' || path[3] == '\\')) {
	    extended = 2;
	    path = path + 4;
	}
    }

    if (path[0] == '/' || path[0] == '\\') {
	/*
238
239
240
241
242
243
244
245

246
247
248
249
250
251
252
244
245
246
247
248
249
250

251
252
253
254
255
256
257
258







-
+







		    && path[3] >= '1' && path[3] <= '9') {
		/*
		 * May have match for 'com[1-9]:?', which is a serial port.
		 */

		if (path[4] == '\0') {
		    abs = 4;
		} else if (path [4] == ':' && path[5] == '\0') {
		} else if (path[4] == ':' && path[5] == '\0') {
		    abs = 5;
		}

	    } else if ((path[2] == 'n' || path[2] == 'N') && path[3] == '\0') {
		/*
		 * Have match for 'con'.
		 */
260
261
262
263
264
265
266
267

268
269
270
271
272
273
274
266
267
268
269
270
271
272

273
274
275
276
277
278
279
280







-
+







	    if (path[3] >= '1' && path[3] <= '9') {
		/*
		 * May have match for 'lpt[1-9]:?'
		 */

		if (path[4] == '\0') {
		    abs = 4;
		} else if (path [4] == ':' && path[5] == '\0') {
		} else if (path[4] == ':' && path[5] == '\0') {
		    abs = 5;
		}
	    }

	} else if ((path[0] == 'p' || path[0] == 'P')
		&& (path[1] == 'r' || path[1] == 'R')
		&& (path[2] == 'n' || path[2] == 'N')
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
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
467
468
469
470
471
472
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
442
443
444







-
-
-
-
-
-













-
-
+
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+

-
-
-
+
+
+

-
-
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-







 *	Determines whether a given path is relative to the current directory,
 *	relative to the current volume, or absolute, but ONLY FOR THE NATIVE
 *	FILESYSTEM. This function is called from tclIOUtil.c (but needs to be
 *	here due to its dependence on static variables/functions in this
 *	file). The exported function Tcl_FSGetPathType should be used by
 *	extensions.
 *
 *	Note that '~' paths are always considered TCL_PATH_ABSOLUTE, even
 *	though expanding the '~' could lead to any possible path type. This
 *	function should therefore be considered a low-level, string
 *	manipulation function only -- it doesn't actually do any expansion in
 *	making its determination.
 *
 * Results:
 *	Returns one of TCL_PATH_ABSOLUTE, TCL_PATH_RELATIVE, or
 *	TCL_PATH_VOLUME_RELATIVE.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_PathType
TclpGetNativePathType(
    Tcl_Obj *pathPtr,		/* Native path of interest */
    int *driveNameLengthPtr,	/* Returns length of drive, if non-NULL and
				 * path was absolute */
    Tcl_Size *driveNameLengthPtr, /* Returns length of drive, if non-NULL and
				   * path was absolute */
    Tcl_Obj **driveNameRef)
{
    Tcl_PathType type = TCL_PATH_ABSOLUTE;
    const char *path = TclGetString(pathPtr);

    if (path[0] == '~') {
	/*
	 * This case is common to all platforms. Paths that begin with ~ are
	 * absolute.
	 */

	if (driveNameLengthPtr != NULL) {
	    const char *end = path + 1;
	    while ((*end != '\0') && (*end != '/')) {
		end++;
	    }
	    *driveNameLengthPtr = end - path;
	}
    } else {
	switch (tclPlatform) {
	case TCL_PLATFORM_UNIX: {
	    const char *origPath = path;
    switch (tclPlatform) {
    case TCL_PLATFORM_UNIX: {
	const char *origPath = path;

	    /*
	     * Paths that begin with / are absolute.
	     */
	/*
	 * Paths that begin with / are absolute.
	 */

	    if (path[0] == '/') {
		++path;
	if (path[0] == '/') {
	    ++path;
#if defined(__CYGWIN__) || defined(__QNX__)
		/*
		 * Check for "//" network path prefix
		 */
		if ((*path == '/') && path[1] && (path[1] != '/')) {
		    path += 2;
		    while (*path && *path != '/') {
			++path;
		    }
	    /*
	     * Check for "//" network path prefix
	     */
	    if ((*path == '/') && path[1] && (path[1] != '/')) {
		path += 2;
		while (*path && *path != '/') {
		    ++path;
		}
#if defined(__CYGWIN__)
		    /* UNC paths need to be followed by a share name */
		    if (*path++ && (*path && *path != '/')) {
			++path;
			while (*path && *path != '/') {
			    ++path;
			}
	    }
		    } else {
			path = origPath + 1;
		    }
#endif
		}
#endif
		if (driveNameLengthPtr != NULL) {
		    /*
		     * We need this addition in case the QNX or Cygwin code was used.
		     */
	    if (driveNameLengthPtr != NULL) {
		/*
		 * We need this addition in case the "//" code was used.
		 */

		    *driveNameLengthPtr = (path - origPath);
		}
	    } else {
		type = TCL_PATH_RELATIVE;
	    }
	    break;
	}
	case TCL_PLATFORM_WINDOWS: {
	    Tcl_DString ds;
	    const char *rootEnd;
		*driveNameLengthPtr = (path - origPath);
	    }
	} else {
	    type = TCL_PATH_RELATIVE;
	}
	break;
    }
    case TCL_PLATFORM_WINDOWS: {
	Tcl_DString ds;
	const char *rootEnd;

	    Tcl_DStringInit(&ds);
	    rootEnd = ExtractWinRoot(path, &ds, 0, &type);
	    if ((rootEnd != path) && (driveNameLengthPtr != NULL)) {
		*driveNameLengthPtr = rootEnd - path;
		if (driveNameRef != NULL) {
		    *driveNameRef = TclDStringToObj(&ds);
		    Tcl_IncrRefCount(*driveNameRef);
		}
	    }
	    Tcl_DStringFree(&ds);
	    break;
	}
	Tcl_DStringInit(&ds);
	rootEnd = ExtractWinRoot(path, &ds, 0, &type);
	if ((rootEnd != path) && (driveNameLengthPtr != NULL)) {
	    *driveNameLengthPtr = rootEnd - path;
	    if (driveNameRef != NULL) {
		*driveNameRef = Tcl_DStringToObj(&ds);
		Tcl_IncrRefCount(*driveNameRef);
	    }
	}
	Tcl_DStringFree(&ds);
	break;
    }
	}
    }
    return type;
}

/*
 *---------------------------------------------------------------------------
 *
489
490
491
492
493
494
495
496

497
498
499
500
501
502
503
461
462
463
464
465
466
467

468
469
470
471
472
473
474
475







-
+







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

Tcl_Obj *
TclpNativeSplitPath(
    Tcl_Obj *pathPtr,		/* Path to split. */
    int *lenPtr)		/* int to store number of path elements. */
    Tcl_Size *lenPtr)		/* int to store number of path elements. */
{
    Tcl_Obj *resultPtr = NULL;	/* Needed only to prevent gcc warnings. */

    /*
     * Perform platform specific splitting.
     */

512
513
514
515
516
517
518
519

520
521
522
523
524
525
526
484
485
486
487
488
489
490

491
492
493
494
495
496
497
498







-
+







    }

    /*
     * Compute the number of elements in the result.
     */

    if (lenPtr != NULL) {
	Tcl_ListObjLength(NULL, resultPtr, lenPtr);
	TclListObjLength(NULL, resultPtr, lenPtr);
    }
    return resultPtr;
}

/*
 *----------------------------------------------------------------------
 *
542
543
544
545
546
547
548

549
550
551
552

553
554
555
556
557
558
559
560

561
562
563
564
565
566
567
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







+



-
+






-
-
+







 *
 * Side effects:
 *	Allocates memory.
 *
 *----------------------------------------------------------------------
 */

#undef Tcl_SplitPath
void
Tcl_SplitPath(
    const char *path,		/* Pointer to string containing a path. */
    int *argcPtr,		/* Pointer to location to fill in with the
    Tcl_Size *argcPtr,		/* Pointer to location to fill in with the
				 * number of elements in the path. */
    const char ***argvPtr)	/* Pointer to place to store pointer to array
				 * of pointers to path elements. */
{
    Tcl_Obj *resultPtr = NULL;	/* Needed only to prevent gcc warnings. */
    Tcl_Obj *tmpPtr, *eltPtr;
    int i;
    size_t size, len;
    Tcl_Size i, size, len;
    char *p;
    const char *str;

    /*
     * Perform the splitting, using objectified, vfs-aware code.
     */

607
608
609
610
611
612
613
614

615
616
617
618
619
620
621
579
580
581
582
583
584
585

586
587
588
589
590
591
592
593







-
+







     * Now set up the argv pointers.
     */

    p = (char *) &(*argvPtr)[(*argcPtr) + 1];

    for (i = 0; i < *argcPtr; i++) {
	(*argvPtr)[i] = p;
	for (; *(p++)!='\0'; );
	while (*(p++) != '\0');
    }
    (*argvPtr)[i] = NULL;

    /*
     * Free the result ptr given to us by Tcl_FSSplitPath
     */

651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
623
624
625
626
627
628
629

630
631
632
633
634
635
636
637







638






639
640
641
642
643
644
645
646

647

648
649
650
651
652
653
654
655
656
657





658

659
660
661
662
663
664
665







-








-
-
-
-
-
-
-
+
-
-
-
-
-
-








-
+
-










-
-
-
-
-
+
-







     * Deal with the root directory as a special case.
     */

    TclNewObj(result);
    if (*path == '/') {
	Tcl_Obj *rootElt;
	++path;
#if defined(__CYGWIN__) || defined(__QNX__)
	/*
	 * Check for "//" network path prefix
	 */
	if ((*path == '/') && path[1] && (path[1] != '/')) {
	    path += 2;
	    while (*path && *path != '/') {
		++path;
	    }
#if defined(__CYGWIN__)
	    /* UNC paths need to be followed by a share name */
	    if (*path++ && (*path && *path != '/')) {
		++path;
		while (*path && *path != '/') {
		    ++path;
		}
	}
	    } else {
		path = origPath + 1;
	    }
#endif
	}
#endif
	rootElt = Tcl_NewStringObj(origPath, path - origPath);
	Tcl_ListObjAppendElement(NULL, result, rootElt);
	while (*path == '/') {
	    ++path;
	}
    }

    /*
     * Split on slashes. Embedded elements that start with tilde will be
     * Split on slashes.
     * prefixed with "./" so they are not affected by tilde substitution.
     */

    for (;;) {
	elementStart = path;
	while ((*path != '\0') && (*path != '/')) {
	    path++;
	}
	length = path - elementStart;
	if (length > 0) {
	    Tcl_Obj *nextElt;
	    if ((elementStart[0] == '~') && (elementStart != origPath)) {
		TclNewLiteralStringObj(nextElt, "./");
		Tcl_AppendToObj(nextElt, elementStart, length);
	    } else {
		nextElt = Tcl_NewStringObj(elementStart, length);
	    nextElt = Tcl_NewStringObj(elementStart, length);
	    }
	    Tcl_ListObjAppendElement(NULL, result, nextElt);
	}
	if (*path++ == '\0') {
	    break;
	}
    }
    return result;
744
745
746
747
748
749
750
751

752
753
754
755
756

757
758
759
760
761
762
763
764
765
766
767
768
769
770
771



772
773
774
775
776
777
778
697
698
699
700
701
702
703

704
705
706
707
708

709


710
711
712
713
714
715
716
717
718
719



720
721
722
723
724
725
726
727
728
729







-
+




-
+
-
-










-
-
-
+
+
+







    p = ExtractWinRoot(path, &buf, 0, &type);

    /*
     * Terminate the root portion, if we matched something.
     */

    if (p != path) {
	Tcl_ListObjAppendElement(NULL, result, TclDStringToObj(&buf));
	Tcl_ListObjAppendElement(NULL, result, Tcl_DStringToObj(&buf));
    }
    Tcl_DStringFree(&buf);

    /*
     * Split on slashes. Embedded elements that start with tilde or a drive
     * Split on slashes.
     * letter will be prefixed with "./" so they are not affected by tilde
     * substitution.
     */

    do {
	elementStart = p;
	while ((*p != '\0') && (*p != '/') && (*p != '\\')) {
	    p++;
	}
	length = p - elementStart;
	if (length > 0) {
	    Tcl_Obj *nextElt;
	    if ((elementStart != path) && ((elementStart[0] == '~')
		    || (isalpha(UCHAR(elementStart[0]))
			&& elementStart[1] == ':'))) {
	    if ((elementStart != path) &&
		    isalpha(UCHAR(elementStart[0])) &&
		    (elementStart[1] == ':')) {
		TclNewLiteralStringObj(nextElt, "./");
		Tcl_AppendToObj(nextElt, elementStart, length);
	    } else {
		nextElt = Tcl_NewStringObj(elementStart, length);
	    }
	    Tcl_ListObjAppendElement(NULL, result, nextElt);
	}
803
804
805
806
807
808
809
810

811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826

827
828
829
830
831
832
833
754
755
756
757
758
759
760

761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776

777
778
779
780
781
782
783
784







-
+















-
+







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

Tcl_Obj *
Tcl_FSJoinToPath(
    Tcl_Obj *pathPtr,		/* Valid path or NULL. */
    int objc,			/* Number of array elements to join */
    Tcl_Size objc,		/* Number of array elements to join */
    Tcl_Obj *const objv[])	/* Path elements to join. */
{
    if (pathPtr == NULL) {
	return TclJoinPath(objc, objv, 0);
    }
    if (objc == 0) {
	return TclJoinPath(1, &pathPtr, 0);
    }
    if (objc == 1) {
	Tcl_Obj *pair[2];

	pair[0] = pathPtr;
	pair[1] = objv[0];
	return TclJoinPath(2, pair, 0);
    } else {
	int elemc = objc + 1;
	Tcl_Size elemc = objc + 1;
	Tcl_Obj *ret, **elemv = (Tcl_Obj**)Tcl_Alloc(elemc*sizeof(Tcl_Obj *));

	elemv[0] = pathPtr;
	memcpy(elemv+1, objv, objc*sizeof(Tcl_Obj *));
	ret = TclJoinPath(elemc, elemv, 0);
	Tcl_Free(elemv);
	return ret;
852
853
854
855
856
857
858
859

860
861
862
863
864
865
866
867

868
869
870
871
872
873
874
875
876



877
878
879
880
881
882
883
803
804
805
806
807
808
809

810
811
812
813
814
815
816
817

818
819
820
821
822
823
824



825
826
827
828
829
830
831
832
833
834







-
+







-
+






-
-
-
+
+
+








void
TclpNativeJoinPath(
    Tcl_Obj *prefix,
    const char *joining)
{
    int needsSep;
    size_t length;
    Tcl_Size length;
    char *dest;
    const char *p;
    const char *start;

    start = TclGetStringFromObj(prefix, &length);

    /*
     * Remove the ./ from tilde prefixed elements, and drive-letter prefixed
     * Remove the ./ from drive-letter prefixed
     * elements on Windows, unless it is the first component.
     */

    p = joining;

    if (length != 0) {
	if ((p[0] == '.') && (p[1] == '/') && ((p[2] == '~')
		|| (tclPlatform==TCL_PLATFORM_WINDOWS && isalpha(UCHAR(p[2]))
		&& (p[3] == ':')))) {
	if ((p[0] == '.') && (p[1] == '/') &&
		(tclPlatform==TCL_PLATFORM_WINDOWS) && isalpha(UCHAR(p[2]))
		&& (p[3] == ':')) {
	    p += 2;
	}
    }
    if (*p == '\0') {
	return;
    }

893
894
895
896
897
898
899
900

901
902
903
904
905
906
907
844
845
846
847
848
849
850

851
852
853
854
855
856
857
858







-
+







	}
	needsSep = 0;

	/*
	 * Append the element, eliminating duplicate and trailing slashes.
	 */

	Tcl_SetObjLength(prefix, length + (int) strlen(p));
	Tcl_SetObjLength(prefix, length + strlen(p));

	dest = TclGetString(prefix) + length;
	for (; *p != '\0'; p++) {
	    if (*p == '/') {
		while (p[1] == '/') {
		    p++;
		}
972
973
974
975
976
977
978
979

980
981
982
983
984

985
986
987
988
989
990
991
923
924
925
926
927
928
929

930
931
932
933


934
935
936
937
938
939
940
941







-
+



-
-
+







 *	Modifies the Tcl_DString.
 *
 *----------------------------------------------------------------------
 */

char *
Tcl_JoinPath(
    int argc,
    Tcl_Size argc,
    const char *const *argv,
    Tcl_DString *resultPtr)	/* Pointer to previously initialized DString */
{
    int i;
    size_t len;
    Tcl_Size i, len;
    Tcl_Obj *listObj;
    Tcl_Obj *resultObj;
    const char *resultStr;

    /*
     * Build the list of paths.
     */
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
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







-
+
-
-


-
-
-
+
+
+
+


-
-
-
















-
+








/*
 *---------------------------------------------------------------------------
 *
 * Tcl_TranslateFileName --
 *
 *	Converts a file name into a form usable by the native system
 *	interfaces. If the name starts with a tilde, it will produce a name
 *	interfaces.
 *	where the tilde and following characters have been replaced by the
 *	home directory location for the named user.
 *
 * Results:
 *	The return value is a pointer to a string containing the name after
 *	tilde substitution. If there was no tilde substitution, the return
 *	value is a pointer to a copy of the original string. If there was an
 *	The return value is a pointer to a string containing the name.
 *      This may either be the name pointer passed in or space allocated in
 *      bufferPtr. In all cases, if the return value is not NULL, the caller
 *	must call Tcl_DStringFree() to free the space. If there was an
 *	error in processing the name, then an error message is left in the
 *	interp's result (if interp was not NULL) and the return value is NULL.
 *	Space for the return value is allocated in bufferPtr; the caller must
 *	call Tcl_DStringFree() to free the space if the return value was not
 *	NULL.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

char *
Tcl_TranslateFileName(
    Tcl_Interp *interp,		/* Interpreter in which to store error message
				 * (if necessary). */
    const char *name,		/* File name, which may begin with "~" (to
				 * indicate current user's home directory) or
				 * "~<user>" (to indicate any user's home
				 * directory). */
    Tcl_DString *bufferPtr)	/* Uninitialized or free DString filled with
				 * name after tilde substitution. */
				 * name. */
{
    Tcl_Obj *path = Tcl_NewStringObj(name, -1);
    Tcl_Obj *transPtr;

    Tcl_IncrRefCount(path);
    transPtr = Tcl_FSGetTranslatedPath(interp, path);
    if (transPtr == NULL) {
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354

1355
1356
1357
1358
1359
1360
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
1092
1093
1094
1095
1096
1097
1098



























































1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114

1115
1116
1117
1118
1119

1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133

1134
1135
1136
1137
1138
1139
1140
1141
1142


1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163

1164
1165

1166
1167
1168
1169
1170
1171
1172
1173
1174

1175
1176
1177
1178
1179
1180
1181
1182
1183
1184

1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202

1203
1204
1205
1206
1207
1208
1209
1210
1211
1212

1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223

1224
1225
1226
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
















-
+




-
+
+












-
+








-
-
+
+



















-
+

-
+
+
+
+





-
+









-
+

















-
+









-
+










-
+



-
+
















-
+














-
+









-
+








    return p;
}

/*
 *----------------------------------------------------------------------
 *
 * DoTildeSubst --
 *
 *	Given a string following a tilde, this routine returns the
 *	corresponding home directory.
 *
 * Results:
 *	The result is a pointer to a static string containing the home
 *	directory in native format. If there was an error in processing the
 *	substitution, then an error message is left in the interp's result and
 *	the return value is NULL. On success, the results are appended to
 *	resultPtr, and the contents of resultPtr are returned.
 *
 * Side effects:
 *	Information may be left in resultPtr.
 *
 *----------------------------------------------------------------------
 */

static const char *
DoTildeSubst(
    Tcl_Interp *interp,		/* Interpreter in which to store error message
				 * (if necessary). */
    const char *user,		/* Name of user whose home directory should be
				 * substituted, or "" for current user. */
    Tcl_DString *resultPtr)	/* Initialized DString filled with name after
				 * tilde substitution. */
{
    const char *dir;

    if (*user == '\0') {
	Tcl_DString dirString;

	dir = TclGetEnv("HOME", &dirString);
	if (dir == NULL) {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"couldn't find HOME environment "
			"variable to expand path", -1));
		Tcl_SetErrorCode(interp, "TCL", "FILENAME", "NO_HOME", NULL);
	    }
	    return NULL;
	}
	Tcl_JoinPath(1, &dir, resultPtr);
	Tcl_DStringFree(&dirString);
    } else if (TclpGetUserHome(user, resultPtr) == NULL) {
	if (interp) {
	    Tcl_ResetResult(interp);
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "user \"%s\" doesn't exist", user));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "USER", user, NULL);
	}
	return NULL;
    }
    return Tcl_DStringValue(resultPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GlobObjCmd --
 *
 *	This procedure is invoked to process the "glob" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_GlobObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int index, i, globFlags, length, join, dir, result;
    int i, globFlags, join, dir, result;
    Tcl_Size length;
    char *string;
    const char *separators;
    Tcl_Obj *typePtr, *look;
    Tcl_Obj *pathOrDir = NULL;
    Tcl_DString prefix;
    static const char *const options[] = {
	"-directory", "-join", "-nocomplain", "-path", "-tails",
	"-types", "--", NULL
    };
    enum globOptionsEnum {
	GLOB_DIR, GLOB_JOIN, GLOB_NOCOMPLAIN, GLOB_PATH, GLOB_TAILS,
	GLOB_TYPE, GLOB_LAST
    };
    } index;
    enum pathDirOptions {PATH_NONE = -1 , PATH_GENERAL = 0, PATH_DIR = 1};
    Tcl_GlobTypeData *globTypes = NULL;

    globFlags = 0;
    join = 0;
    dir = PATH_NONE;
    typePtr = NULL;
    for (i = 1; i < objc; i++) {
	if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
		&index) != TCL_OK) {
	if (Tcl_GetIndexFromObj(interp, objv[i], options,
		"option", 0, &index) != TCL_OK) {
	    string = TclGetString(objv[i]);
	    if (string[0] == '-') {
		/*
		 * It looks like the command contains an option so signal an
		 * error.
		 */

		return TCL_ERROR;
	    } else {
		/*
		 * This clearly isn't an option; assume it's the first glob
		 * pattern. We must clear the error.
		 */

		Tcl_ResetResult(interp);
		break;
	    }
	}

	switch ((enum globOptionsEnum) index) {
	switch (index) {
	case GLOB_NOCOMPLAIN:			/* -nocomplain */
	    globFlags |= TCL_GLOBMODE_NO_COMPLAIN;
	    /*
	     * Do nothing; This is normal operations in Tcl 9.
	     * Keep accepting as a no-op option to accommodate old scripts.
	     */
	    break;
	case GLOB_DIR:				/* -dir */
	    if (i == (objc-1)) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"missing argument to \"-directory\"", -1));
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (char *)NULL);
		return TCL_ERROR;
	    }
	    if (dir != PATH_NONE) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			dir == PATH_DIR
			    ? "\"-directory\" may only be used once"
			    : "\"-directory\" cannot be used with \"-path\"",
			-1));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "GLOB",
			"BADOPTIONCOMBINATION", NULL);
			"BADOPTIONCOMBINATION", (char *)NULL);
		return TCL_ERROR;
	    }
	    dir = PATH_DIR;
	    globFlags |= TCL_GLOBMODE_DIR;
	    pathOrDir = objv[i+1];
	    i++;
	    break;
	case GLOB_JOIN:				/* -join */
	    join = 1;
	    break;
	case GLOB_TAILS:				/* -tails */
	    globFlags |= TCL_GLOBMODE_TAILS;
	    break;
	case GLOB_PATH:				/* -path */
	    if (i == (objc-1)) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"missing argument to \"-path\"", -1));
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (char *)NULL);
		return TCL_ERROR;
	    }
	    if (dir != PATH_NONE) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			dir == PATH_GENERAL
			    ? "\"-path\" may only be used once"
			    : "\"-path\" cannot be used with \"-dictionary\"",
			-1));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "GLOB",
			"BADOPTIONCOMBINATION", NULL);
			"BADOPTIONCOMBINATION", (char *)NULL);
		return TCL_ERROR;
	    }
	    dir = PATH_GENERAL;
	    pathOrDir = objv[i+1];
	    i++;
	    break;
	case GLOB_TYPE:				/* -types */
	    if (i == (objc-1)) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"missing argument to \"-types\"", -1));
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (char *)NULL);
		return TCL_ERROR;
	    }
	    typePtr = objv[i+1];
	    if (Tcl_ListObjLength(interp, typePtr, &length) != TCL_OK) {
	    if (TclListObjLength(interp, typePtr, &length) != TCL_OK) {
		return TCL_ERROR;
	    }
	    i++;
	    break;
	case GLOB_LAST:				/* -- */
	    i++;
	    goto endOfForLoop;
	}
    }

  endOfForLoop:
    if ((globFlags & TCL_GLOBMODE_TAILS) && (pathOrDir == NULL)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"\"-tails\" must be used with either "
		"\"-directory\" or \"-path\"", -1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "GLOB",
		"BADOPTIONCOMBINATION", NULL);
		"BADOPTIONCOMBINATION", (char *)NULL);
	return TCL_ERROR;
    }

    separators = NULL;
    switch (tclPlatform) {
    case TCL_PLATFORM_UNIX:
	separators = "/";
	break;
    case TCL_PLATFORM_WINDOWS:
	separators = "/\\:";
	break;
    }

    if (dir == PATH_GENERAL) {
	size_t pathlength;
	Tcl_Size pathlength;
	const char *last;
	const char *first = TclGetStringFromObj(pathOrDir,&pathlength);

	/*
	 * Find the last path separator in the path
	 */

	last = first + pathlength;
	for (; last != first; last--) {
	    if (strchr(separators, *(last-1)) != NULL) {
	    if (strchr(separators, last[-1]) != NULL) {
		break;
	    }
	}

	if (last == first + pathlength) {
	    /*
	     * It's really a directory.
1411
1412
1413
1414
1415
1416
1417
1418


1419
1420
1421


1422


1423
1424
1425
1426
1427
1428
1429
1302
1303
1304
1305
1306
1307
1308

1309
1310
1311
1312

1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324







-
+
+


-
+
+

+
+







		Tcl_DStringAppend(&pref, last, first+pathlength-last);
		pathOrDir = Tcl_NewStringObj(first, last-first-1);

		/*
		 * We must ensure that we haven't cut off too much, and turned
		 * a valid path like '/' or 'C:/' into an incorrect path like
		 * '' or 'C:'. The way we do this is to add a separator if
		 * there are none presently in the prefix.
		 * there are none presently in the prefix. Similar treatment
		 * for the zipfs volume.
		 */

		if (strpbrk(TclGetString(pathOrDir), "\\/") == NULL) {
		const char *temp = TclGetString(pathOrDir);
		if (strpbrk(temp, "\\/") == NULL) {
		    Tcl_AppendToObj(pathOrDir, last-1, 1);
		} else if (!strcmp(temp, "//zipfs:")) {
		    Tcl_AppendToObj(pathOrDir, "/", 1);
		}
	    }

	    /*
	     * Need to quote 'prefix'.
	     */

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
1347
1348
1349
1350
1351
1352
1353


1354
1355
1356
1357
1358
1359
1360
1361
1362
1363


1364
1365
1366
1367
1368
1369
1370
1371
1372







-
-
+
+








-
-
+
+







    if (typePtr != NULL) {
	/*
	 * The rest of the possible type arguments (except 'd') are platform
	 * specific. We don't complain when they are used on an incompatible
	 * platform.
	 */

	Tcl_ListObjLength(interp, typePtr, &length);
	if (length <= 0) {
	TclListObjLength(interp, typePtr, &length);
	if (length == 0) {
	    goto skipTypes;
	}
	globTypes = (Tcl_GlobTypeData *)TclStackAlloc(interp, sizeof(Tcl_GlobTypeData));
	globTypes->type = 0;
	globTypes->perm = 0;
	globTypes->macType = NULL;
	globTypes->macCreator = NULL;

	while (--length >= 0) {
	    size_t len;
	while (length-- > 0) {
	    Tcl_Size len;
	    const char *str;

	    Tcl_ListObjIndex(interp, typePtr, length, &look);
	    str = TclGetStringFromObj(look, &len);
	    if (strcmp("readonly", str) == 0) {
		globTypes->perm |= TCL_GLOB_PERM_RONLY;
	    } else if (strcmp("hidden", str) == 0) {
1521
1522
1523
1524
1525
1526
1527
1528

1529
1530

1531
1532
1533
1534
1535
1536
1537
1416
1417
1418
1419
1420
1421
1422

1423
1424

1425
1426
1427
1428
1429
1430
1431
1432







-
+

-
+







		    goto badMacTypesArg;
		}
		globTypes->macType = look;
		Tcl_IncrRefCount(look);

	    } else {
		Tcl_Obj *item;
		int llen;
		Tcl_Size llen;

		if ((Tcl_ListObjLength(NULL, look, &llen) == TCL_OK)
		if ((TclListObjLength(NULL, look, &llen) == TCL_OK)
			&& (llen == 3)) {
		    Tcl_ListObjIndex(interp, look, 0, &item);
		    if (!strcmp("macintosh", TclGetString(item))) {
			Tcl_ListObjIndex(interp, look, 1, &item);
			if (!strcmp("type", TclGetString(item))) {
			    Tcl_ListObjIndex(interp, look, 2, &item);
			    if (globTypes->macType != NULL) {
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
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







-
+









-
+







		 * haven't yet made use of it.
		 */

	    badTypesArg:
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"bad argument to \"-types\": %s",
			TclGetString(look)));
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "BAD", NULL);
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "BAD", (char *)NULL);
		result = TCL_ERROR;
		join = 0;
		goto endOfGlob;

	    badMacTypesArg:
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"only one MacOS type or creator argument"
			" to \"-types\" allowed", -1));
		result = TCL_ERROR;
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "BAD", NULL);
		Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "BAD", (char *)NULL);
		join = 0;
		goto endOfGlob;
	    }
	}
    }

  skipTypes:
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
1524
1525
1526
1527
1528
1529
1530



































1531
1532
1533
1534
1535
1536
1537







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







		    globTypes) != TCL_OK) {
		result = TCL_ERROR;
		goto endOfGlob;
	    }
	}
    }

    if ((globFlags & TCL_GLOBMODE_NO_COMPLAIN) == 0) {
	if (Tcl_ListObjLength(interp, Tcl_GetObjResult(interp),
		&length) != TCL_OK) {
	    /*
	     * This should never happen. Maybe we should be more dramatic.
	     */

	    result = TCL_ERROR;
	    goto endOfGlob;
	}

	if (length == 0) {
	    Tcl_Obj *errorMsg =
		    Tcl_ObjPrintf("no files matched glob pattern%s \"",
			    (join || (objc == 1)) ? "" : "s");

	    if (join) {
		Tcl_AppendToObj(errorMsg, Tcl_DStringValue(&prefix), -1);
	    } else {
		const char *sep = "";

		for (i = 0; i < objc; i++) {
		    Tcl_AppendPrintfToObj(errorMsg, "%s%s",
			    sep, TclGetString(objv[i]));
		    sep = " ";
		}
	    }
	    Tcl_AppendToObj(errorMsg, "\"", -1);
	    Tcl_SetObjResult(interp, errorMsg);
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "GLOB", "NOMATCH",
		    NULL);
	    result = TCL_ERROR;
	}
    }

  endOfGlob:
    if (join || (dir == PATH_GENERAL)) {
	Tcl_DStringFree(&prefix);
    }
    if (pathOrDir != NULL) {
	Tcl_DecrRefCount(pathOrDir);
    }
1688
1689
1690
1691
1692
1693
1694
1695

1696
1697
1698
1699
1700
1701
1702
1703
1548
1549
1550
1551
1552
1553
1554

1555

1556
1557
1558
1559
1560
1561
1562







-
+
-







}

/*
 *----------------------------------------------------------------------
 *
 * TclGlob --
 *
 *	Sets the separator string based on the platform, performs tilde
 *	Sets the separator string based on the platform	and calls DoGlob.
 *	substitution, and calls DoGlob.
 *
 *	The interpreter's result, on entry to this function, must be a valid
 *	Tcl list (e.g. it could be empty), since we will lappend any new
 *	results to that list. If it is not a valid list, this function will
 *	fail to do anything very meaningful.
 *
 *	Note that if globFlags contains 'TCL_GLOBMODE_TAILS' then pathPrefix
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788

1789
1790
1791
1792

1793
1794
1795

1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
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







-
+












-
-
+













-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
+
-
-
-
-
-







 *
 * Side effects:
 *	The 'pattern' is written to.
 *
 *----------------------------------------------------------------------
 */

int
static int
TclGlob(
    Tcl_Interp *interp,		/* Interpreter for returning error message or
				 * appending list of matching file names. */
    char *pattern,		/* Glob pattern to match. Must not refer to a
				 * static string. */
    Tcl_Obj *pathPrefix,	/* Path prefix to glob pattern, if non-null,
				 * which is considered literally. */
    int globFlags,		/* Stores or'ed combination of flags */
    Tcl_GlobTypeData *types)	/* Struct containing acceptable types. May be
				 * NULL. */
{
    const char *separators;
    const char *head;
    char *tail, *start;
    char *tail;
    int result;
    Tcl_Obj *filenamesObj, *savedResultObj;

    separators = NULL;
    switch (tclPlatform) {
    case TCL_PLATFORM_UNIX:
	separators = "/";
	break;
    case TCL_PLATFORM_WINDOWS:
	separators = "/\\:";
	break;
    }

    if (pathPrefix == NULL) {
    if (pathPrefix != NULL) {
	char c;
	Tcl_DString buffer;
	Tcl_DStringInit(&buffer);

	start = pattern;

	/*
	 * Perform tilde substitution, if needed.
	 */

	if (start[0] == '~') {
	    /*
	     * Find the first path separator after the tilde.
	     */

	    for (tail = start; *tail != '\0'; tail++) {
		if (*tail == '\\') {
		    if (strchr(separators, tail[1]) != NULL) {
			break;
		    }
		} else if (strchr(separators, *tail) != NULL) {
		    break;
		}
	    }

	    /*
	     * Determine the home directory for the specified user.
	     */

	    c = *tail;
	    *tail = '\0';
	    head = DoTildeSubst(interp, start+1, &buffer);
	    *tail = c;
	    if (head == NULL) {
		return TCL_ERROR;
	    }
	    if (head != Tcl_DStringValue(&buffer)) {
		Tcl_DStringAppend(&buffer, head, -1);
	    }
	    pathPrefix = TclDStringToObj(&buffer);
	    Tcl_IncrRefCount(pathPrefix);
	Tcl_IncrRefCount(pathPrefix);
	    globFlags |= TCL_GLOBMODE_DIR;
	    if (c != '\0') {
		tail++;
	    }
    }
	    Tcl_DStringFree(&buffer);
	} else {
	    tail = pattern;
    tail = pattern;
	}
    } else {
	Tcl_IncrRefCount(pathPrefix);
	tail = pattern;
    }

    /*
     * Handling empty path prefixes with glob patterns like 'C:' or
     * 'c:////////' is a pain on Windows if we leave it too late, since these
     * aren't really patterns at all! We therefore check the head of the
     * pattern now for such cases, if we don't have an unquoted prefix yet.
     *
1832
1833
1834
1835
1836
1837
1838
1839

1840
1841
1842
1843
1844
1845
1846
1640
1641
1642
1643
1644
1645
1646

1647
1648
1649
1650
1651
1652
1653
1654







-
+







		}
		p++;
	    }
	    tail = p;
	    Tcl_IncrRefCount(pathPrefix);
	} else if (pathPrefix == NULL && (tail[0] == '/'
		|| (tail[0] == '\\' && tail[1] == '\\'))) {
	    int driveNameLen;
	    Tcl_Size driveNameLen;
	    Tcl_Obj *driveName;
	    Tcl_Obj *temp = Tcl_NewStringObj(tail, -1);
	    Tcl_IncrRefCount(temp);

	    switch (TclGetPathType(temp, NULL, &driveNameLen, &driveName)) {
	    case TCL_PATH_VOLUME_RELATIVE: {
		/*
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
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







-
+

-
+










-
+








    /*
     * Finally if we still haven't managed to generate a path prefix, check if
     * the path starts with a current volume.
     */

    if (pathPrefix == NULL) {
	int driveNameLen;
	Tcl_Size driveNameLen;
	Tcl_Obj *driveName;
	if (TclFSNonnativePathType(tail, (int) strlen(tail), NULL,
	if (TclFSNonnativePathType(tail, strlen(tail), NULL,
		&driveNameLen, &driveName) == TCL_PATH_ABSOLUTE) {
	    pathPrefix = driveName;
	    tail += driveNameLen;
	}
    }

    /*
     * To process a [glob] invocation, this function may be called multiple
     * times. Each time, the previously discovered filenames are in the
     * interpreter result. We stash that away here so the result is free for
     * error messsages.
     * error messages.
     */

    savedResultObj = Tcl_GetObjResult(interp);
    Tcl_IncrRefCount(savedResultObj);
    Tcl_ResetResult(interp);
    TclNewObj(filenamesObj);
    Tcl_IncrRefCount(filenamesObj);
1985
1986
1987
1988
1989
1990
1991
1992

1993
1994

1995
1996
1997
1998
1999
2000
2001
1793
1794
1795
1796
1797
1798
1799

1800
1801

1802
1803
1804
1805
1806
1807
1808
1809







-
+

-
+







     * that would add a lot of complexity to the code. This way is a little
     * slower (when the -tails flag is given), but much simpler to code.
     *
     * We do it by rewriting the result list in-place.
     */

    if (globFlags & TCL_GLOBMODE_TAILS) {
	int objc, i;
	Tcl_Size objc, i;
	Tcl_Obj **objv;
	size_t prefixLen;
	Tcl_Size prefixLen;
	const char *pre;

	/*
	 * If this length has never been set, set it here.
	 */

	if (pathPrefix == NULL) {
2013
2014
2015
2016
2017
2018
2019
2020

2021
2022

2023
2024
2025
2026
2027
2028
2029
1821
1822
1823
1824
1825
1826
1827

1828
1829

1830
1831
1832
1833
1834
1835
1836
1837







-
+

-
+








	    if ((tclPlatform != TCL_PLATFORM_WINDOWS) || (prefixLen != 2)
		    || (pre[1] != ':')) {
		prefixLen++;
	    }
	}

	Tcl_ListObjGetElements(NULL, filenamesObj, &objc, &objv);
	TclListObjGetElements(NULL, filenamesObj, &objc, &objv);
	for (i = 0; i< objc; i++) {
	    size_t len;
	    Tcl_Size len;
	    const char *oldStr = TclGetStringFromObj(objv[i], &len);
	    Tcl_Obj *elem;

	    if (len == prefixLen) {
		if ((pattern[0] == '\0')
			|| (strchr(separators, pattern[0]) == NULL)) {
		    TclNewLiteralStringObj(elem, ".");
2154
2155
2156
2157
2158
2159
2160
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
1962
1963
1964
1965
1966
1967
1968

1969
1970
1971
1972
1973
1974
1975
1976
1977
1978

1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997

1998
1999
2000
2001
2002
2003
2004







-
+









-



















-







    Tcl_Obj *pathPtr,		/* Completely expanded prefix. */
    int flags,			/* If non-zero then pathPtr is a directory */
    char *pattern,		/* The pattern to match against. Must not be a
				 * pointer to a static string. */
    Tcl_GlobTypeData *types)	/* List object containing list of acceptable
				 * types. May be NULL. */
{
    int baseLength, quoted, count;
    int baseLength, quoted;
    int result = TCL_OK;
    char *name, *p, *openBrace, *closeBrace, *firstSpecialChar;
    Tcl_Obj *joinedPtr;

    /*
     * Consume any leading directory separators, leaving pattern pointing just
     * past the last initial separator.
     */

    count = 0;
    name = pattern;
    for (; *pattern != '\0'; pattern++) {
	if (*pattern == '\\') {
	    /*
	     * If the first character is escaped, either we have a directory
	     * separator, or we have any other character. In the latter case
	     * the rest is a pattern, and we must break from the loop. This
	     * is particularly important on Windows where '\' is both the
	     * escaping character and a directory separator.
	     */

	    if (strchr(separators, pattern[1]) != NULL) {
		pattern++;
	    } else {
		break;
	    }
	} else if (strchr(separators, *pattern) == NULL) {
	    break;
	}
	count++;
    }

    /*
     * Look for the first matching pair of braces or the first directory
     * separator that is not inside a pair of braces.
     */

2227
2228
2229
2230
2231
2232
2233
2234

2235
2236
2237
2238
2239
2240
2241

2242
2243
2244
2245
2246
2247
2248
2033
2034
2035
2036
2037
2038
2039

2040
2041
2042
2043
2044
2045
2046

2047
2048
2049
2050
2051
2052
2053
2054







-
+






-
+








		closeBrace = p;
		break;
	    }
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "unmatched open-brace in file name", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "GLOB", "BALANCE",
		    NULL);
		    (char *)NULL);
	    return TCL_ERROR;

	} else if (*p == '}') {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "unmatched close-brace in file name", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "GLOB", "BALANCE",
		    NULL);
		    (char *)NULL);
	    return TCL_ERROR;
	}
    }

    /*
     * Substitute the alternate patterns from the braces and recurse.
     */
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
2399
2400
2401
2145
2146
2147
2148
2149
2150
2151

2152
2153
2154

2155
2156
2157
2158
2159







2160
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







-
+


-
+




-
-
-
-
-
-
-



-
+



-
+


-
+









-
+












-
+







	*p = '\0';
	TclNewObj(subdirsPtr);
	Tcl_IncrRefCount(subdirsPtr);
	result = Tcl_FSMatchInDirectory(interp, subdirsPtr, pathPtr,
		pattern, &dirOnly);
	*p = save;
	if (result == TCL_OK) {
	    int subdirc, i, repair = -1;
	    Tcl_Size i, subdirc, repair = -1;
	    Tcl_Obj **subdirv;

	    result = Tcl_ListObjGetElements(interp, subdirsPtr,
	    result = TclListObjGetElements(interp, subdirsPtr,
		    &subdirc, &subdirv);
	    for (i=0; result==TCL_OK && i<subdirc; i++) {
		Tcl_Obj *copy = NULL;

		if (pathPtr == NULL && TclGetString(subdirv[i])[0] == '~') {
		    Tcl_ListObjLength(NULL, matchesObj, &repair);
		    copy = subdirv[i];
		    subdirv[i] = Tcl_NewStringObj("./", 2);
		    Tcl_AppendObjToObj(subdirv[i], copy);
		    Tcl_IncrRefCount(subdirv[i]);
		}
		result = DoGlob(interp, matchesObj, separators, subdirv[i],
			1, p+1, types);
		if (copy) {
		    int end;
		    Tcl_Size end;

		    Tcl_DecrRefCount(subdirv[i]);
		    subdirv[i] = copy;
		    Tcl_ListObjLength(NULL, matchesObj, &end);
		    TclListObjLength(NULL, matchesObj, &end);
		    while (repair < end) {
			const char *bytes;
			size_t numBytes;
			Tcl_Size numBytes;
			Tcl_Obj *fixme, *newObj;

			Tcl_ListObjIndex(NULL, matchesObj, repair, &fixme);
			bytes = TclGetStringFromObj(fixme, &numBytes);
			newObj = Tcl_NewStringObj(bytes+2, numBytes-2);
			Tcl_ListObjReplace(NULL, matchesObj, repair, 1,
				1, &newObj);
			repair++;
		    }
		    repair = -1;
		    repair = TCL_INDEX_NONE;
		}
	    }
	}
	TclDecrRefCount(subdirsPtr);
	return result;
    }

    /*
     * We reach here with no pattern char in current section
     */

    if (*p == '\0') {
	size_t length;
	Tcl_Size length;
	Tcl_DString append;

	/*
	 * This is the code path reached by a command like 'glob foo'.
	 *
	 * There are no more wildcards in the pattern and no more unprocessed
	 * characters in the pattern, so now we can construct the path, and
2440
2441
2442
2443
2444
2445
2446
2447

2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458

2459
2460
2461
2462
2463
2464
2465
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







-
+










-
+







	}

	/*
	 * Common for all platforms.
	 */

	if (pathPtr == NULL) {
	    joinedPtr = TclDStringToObj(&append);
	    joinedPtr = Tcl_DStringToObj(&append);
	} else if (flags) {
	    joinedPtr = TclNewFSPathObj(pathPtr, Tcl_DStringValue(&append),
		    Tcl_DStringLength(&append));
	} else {
	    joinedPtr = Tcl_DuplicateObj(pathPtr);
	    if (strchr(separators, Tcl_DStringValue(&append)[0]) == NULL) {
		/*
		 * The current prefix must end in a separator.
		 */

		size_t len;
		Tcl_Size len;
		const char *joined = TclGetStringFromObj(joinedPtr,&len);

		if ((len > 0) && (strchr(separators, joined[len-1]) == NULL)) {
		    Tcl_AppendToObj(joinedPtr, "/", 1);
		}
	    }
	    Tcl_AppendToObj(joinedPtr, Tcl_DStringValue(&append),
2488
2489
2490
2491
2492
2493
2494
2495

2496
2497
2498
2499
2500
2501
2502
2287
2288
2289
2290
2291
2292
2293

2294
2295
2296
2297
2298
2299
2300
2301







-
+







	     * The current prefix must end in a separator, unless this is a
	     * volume-relative path. In particular globbing in Windows shares,
	     * when not using -dir or -path, e.g. 'glob [file join
	     * //machine/share/subdir *]' requires adding a separator here.
	     * This behaviour is not currently tested for in the test suite.
	     */

	    size_t len;
	    Tcl_Size len;
	    const char *joined = TclGetStringFromObj(joinedPtr,&len);

	    if ((len > 0) && (strchr(separators, joined[len-1]) == NULL)) {
		if (Tcl_FSGetPathType(pathPtr) != TCL_PATH_VOLUME_RELATIVE) {
		    Tcl_AppendToObj(joinedPtr, "/", 1);
		}
	    }
2538
2539
2540
2541
2542
2543
2544
2545
2546


2547
2548
2549
2550
2551
2552
2553
2337
2338
2339
2340
2341
2342
2343


2344
2345
2346
2347
2348
2349
2350
2351
2352







-
-
+
+








/*
 *---------------------------------------------------------------------------
 *
 * Access functions for Tcl_StatBuf --
 *
 *	These functions provide portable read-only access to the portable
 *	fields of the Tcl_StatBuf structure (really a 'struct stat', 'struct
 *	stat64' or something else related). [TIP #316]
 *	fields of the Tcl_StatBuf structure (really a 'struct stat'
 *	or something else related). [TIP #316]
 *
 * Results:
 *	The value from the field being retrieved.
 *
 * Side effects:
 *	None.
 *
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
2398
2399
2400
2401
2402
2403
2404

2405
2406
2407
2408

2409
2410
2411

2412
2413
2414
2415

2416
2417
2418

2419
2420
2421
2422

2423
2424
2425

2426
2427
2428
2429

2430
2431
2432

2433
2434
2435
2436
2437

2438
2439
2440
2441

2442
2443
2444
2445
2446
2447
2448
2449







-
+



-
+


-
+



-
+


-
+



-
+


-
+



-
+


-
+




-
+



-
+







int
Tcl_GetDeviceTypeFromStat(
    const Tcl_StatBuf *statPtr)
{
    return (int) statPtr->st_rdev;
}

Tcl_WideInt
long long
Tcl_GetAccessTimeFromStat(
    const Tcl_StatBuf *statPtr)
{
    return (Tcl_WideInt) statPtr->st_atime;
    return (long long) statPtr->st_atime;
}

Tcl_WideInt
long long
Tcl_GetModificationTimeFromStat(
    const Tcl_StatBuf *statPtr)
{
    return (Tcl_WideInt) statPtr->st_mtime;
    return (long long) statPtr->st_mtime;
}

Tcl_WideInt
long long
Tcl_GetChangeTimeFromStat(
    const Tcl_StatBuf *statPtr)
{
    return (Tcl_WideInt) statPtr->st_ctime;
    return (long long) statPtr->st_ctime;
}

Tcl_WideUInt
unsigned long long
Tcl_GetSizeFromStat(
    const Tcl_StatBuf *statPtr)
{
    return (Tcl_WideUInt) statPtr->st_size;
    return (unsigned long long) statPtr->st_size;
}

Tcl_WideUInt
unsigned long long
Tcl_GetBlocksFromStat(
    const Tcl_StatBuf *statPtr)
{
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
    return (Tcl_WideUInt) statPtr->st_blocks;
    return (unsigned long long) statPtr->st_blocks;
#else
    unsigned blksize = Tcl_GetBlockSizeFromStat(statPtr);

    return ((Tcl_WideUInt) statPtr->st_size + blksize - 1) / blksize;
    return ((unsigned long long) statPtr->st_size + blksize - 1) / blksize;
#endif
}

#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
unsigned
Tcl_GetBlockSizeFromStat(
    const Tcl_StatBuf *statPtr)

Changes to generic/tclFileSystem.h.

1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







/*
 * tclFileSystem.h --
 *
 *	This file contains the common defintions and prototypes for use by
 *	This file contains the common definitions and prototypes for use by
 *	Tcl's filesystem and path handling layers.
 *
 * Copyright (c) 2003 Vince Darley.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */
44
45
46
47
48
49
50
51

52
53
54


55
56
57

58
59
60
61
62
63
64
44
45
46
47
48
49
50

51
52


53
54
55
56

57
58
59
60
61
62
63
64







-
+

-
-
+
+


-
+







/*
 * Private shared functions for use by tclIOUtil.c, tclPathObj.c and
 * tclFileName.c, and any platform-specific filesystem code.
 */

MODULE_SCOPE Tcl_PathType TclFSGetPathType(Tcl_Obj *pathPtr,
			    const Tcl_Filesystem **filesystemPtrPtr,
			    int *driveNameLengthPtr);
			    Tcl_Size *driveNameLengthPtr);
MODULE_SCOPE Tcl_PathType TclFSNonnativePathType(const char *pathPtr,
			    int pathLen, const Tcl_Filesystem **filesystemPtrPtr,
			    int *driveNameLengthPtr, Tcl_Obj **driveNameRef);
			    Tcl_Size pathLen, const Tcl_Filesystem **filesystemPtrPtr,
			    Tcl_Size *driveNameLengthPtr, Tcl_Obj **driveNameRef);
MODULE_SCOPE Tcl_PathType TclGetPathType(Tcl_Obj *pathPtr,
			    const Tcl_Filesystem **filesystemPtrPtr,
			    int *driveNameLengthPtr, Tcl_Obj **driveNameRef);
			    Tcl_Size *driveNameLengthPtr, Tcl_Obj **driveNameRef);
MODULE_SCOPE int	TclFSEpochOk(size_t filesystemEpoch);
MODULE_SCOPE int	TclFSCwdIsNative(void);
MODULE_SCOPE Tcl_Obj *	TclWinVolumeRelativeNormalize(Tcl_Interp *interp,
			    const char *path, Tcl_Obj **useThisCwdPtr);

MODULE_SCOPE Tcl_FSPathInFilesystemProc TclNativePathInFilesystem;
MODULE_SCOPE Tcl_FSCreateInternalRepProc TclNativeCreateNativeRep;

Changes to generic/tclGet.c.

1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16







-
-
+
+







/*
 * tclGet.c --
 *
 *	This file contains functions to convert strings into other forms, like
 *	integers or floating-point numbers or booleans, doing syntax checking
 *	along the way.
 *
 * Copyright (c) 1990-1993 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright © 1990-1993 The Regents of the University of California.
 * Copyright © 1994-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

49
50
51
52
53
54
55
56

57
58
59
60
61
62
63
49
50
51
52
53
54
55

56
57
58
59
60
61
62
63







-
+







    obj.length = strlen(src);
    obj.typePtr = NULL;

    code = Tcl_GetIntFromObj(interp, &obj, intPtr);
    if (obj.refCount > 1) {
	Tcl_Panic("invalid sharing of Tcl_Obj on C stack");
    }
    TclFreeIntRep(&obj);
    TclFreeInternalRep(&obj);
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetDouble --
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
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







-
+












-
+










+
+

-
+



+
-
+





+
+
+










-
+



+
+
+
+
+
+
+
+
+
+
+
+








    obj.length = strlen(src);
    obj.typePtr = NULL;

    code = Tcl_GetDoubleFromObj(interp, &obj, doublePtr);
    if (obj.refCount > 1) {
	Tcl_Panic("invalid sharing of Tcl_Obj on C stack");
    }
    TclFreeIntRep(&obj);
    TclFreeInternalRep(&obj);
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetBoolean --
 *
 *	Given a string, return a 0/1 boolean value corresponding to the
 *	string.
 *
 * Results:
 *	The return value is normally TCL_OK; in this case *boolPtr will be set
 *	The return value is normally TCL_OK; in this case *charPtr will be set
 *	to the 0/1 value equivalent to src. If src is improperly formed then
 *	TCL_ERROR is returned and an error message will be left in the
 *	interp's result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

#undef Tcl_GetBool
#undef Tcl_GetBoolFromObj
int
Tcl_GetBoolean(
Tcl_GetBool(
    Tcl_Interp *interp,		/* Interpreter used for error reporting. */
    const char *src,		/* String containing one of the boolean values
				 * 1, 0, true, false, yes, no, on, off. */
    int flags,
    int *boolPtr)		/* Place to store converted result, which will
    char *charPtr)		/* Place to store converted result, which will
				 * be 0 or 1. */
{
    Tcl_Obj obj;
    int code;

    if ((src == NULL) || (*src == '\0')) {
	return Tcl_GetBoolFromObj(interp, NULL, flags, charPtr);
    }
    obj.refCount = 1;
    obj.bytes = (char *) src;
    obj.length = strlen(src);
    obj.typePtr = NULL;

    code = TclSetBooleanFromAny(interp, &obj);
    if (obj.refCount > 1) {
	Tcl_Panic("invalid sharing of Tcl_Obj on C stack");
    }
    if (code == TCL_OK) {
	*boolPtr = obj.internalRep.wideValue != 0;
	Tcl_GetBoolFromObj(NULL, &obj, flags, charPtr);
    }
    return code;
}

#undef Tcl_GetBoolean
int
Tcl_GetBoolean(
    Tcl_Interp *interp,		/* Interpreter used for error reporting. */
    const char *src,		/* String containing one of the boolean values
				 * 1, 0, true, false, yes, no, on, off. */
    int *intPtr)		/* Place to store converted result, which will
				 * be 0 or 1. */
{
    return Tcl_GetBool(interp, src, (TCL_NULL_OK-2)&(int)sizeof(int), (char *)(void *)intPtr);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclGetDate.y.

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
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
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
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









-
-
+
+
+


















-
-
+
+
+
















-
-
-
-
-
+
+
-
-
+






-
-
+
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-











-
-
-
+
+
+
+
+
+
+
+
+





-
+


-
+













-
+










-
+

-
+

-
-













-
-
-
+
+
+
+


-
+
+
+


+







-
-
+
+

+
+
-
+
+
+












+



-
+


-
+


-
+


-
+


-
+


-
+


-
+
-


+
-
+
-
-

-
+


+
+
+
+
+
+
+
+
+
+
+






-
+
-
-
-
-
+
-
-
-
-
-
-





-




-






+
+
+
+
+
+
+
+
-
+




+
+
+
+



-
+

-
+

-
+



-
+
+
+
+
+



-
+



-
+



+
+
+
+
+
+









-
+
-
-
-
-





-
-
-
-
-




-
+







/*
 * tclGetDate.y --
 *
 *	Contains yacc grammar for parsing date and time strings. The output of
 *	this file should be the file tclDate.c which is used directly in the
 *	Tcl sources. Note that this file is largely obsolete in Tcl 8.5; it is
 *	only used when doing free-form date parsing, an ill-defined process
 *	anyway.
 *
 * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1992-1995 Karl Lehenbauer & Mark Diekhans.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2015 Sergey G. Brester aka sebres.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

%parse-param {DateInfo* info}
%lex-param {DateInfo* info}
%define api.pure
 /* %error-verbose would be nice, but our token names are meaningless */
%locations

%{
/*
 * tclDate.c --
 *
 *	This file is generated from a yacc grammar defined in the file
 *	tclGetDate.y. It should not be edited directly.
 *
 * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1992-1995 Karl Lehenbauer & Mark Diekhans.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2015 Sergey G. Brester aka sebres.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */
#include "tclInt.h"

/*
 * Bison generates several labels that happen to be unused. MS Visual C++
 * doesn't like that, and complains. Tell it to shut up.
 */

#ifdef _MSC_VER
#pragma warning( disable : 4102 )
#endif /* _MSC_VER */

/*
 * Meridian: am, pm, or 24-hour style.
 */

typedef enum _MERIDIAN {
#if 0
#define YYDEBUG 1
    MERam, MERpm, MER24
} MERIDIAN;
#endif

/*
 * yyparse will accept a 'struct DateInfo' as its parameter; that's where the
 * parsed fields will be returned.
 */

typedef struct DateInfo {

#include "tclDate.h"
    Tcl_Obj* messages;		/* Error messages */
    const char* separatrix;	/* String separating messages */

    time_t dateYear;
    time_t dateMonth;
    time_t dateDay;
    int dateHaveDate;

    time_t dateHour;
    time_t dateMinutes;
    time_t dateSeconds;
    MERIDIAN dateMeridian;
    int dateHaveTime;

    time_t dateTimezone;
    int dateDSTmode;
    int dateHaveZone;

    time_t dateRelMonth;
    time_t dateRelDay;
    time_t dateRelSeconds;
    int dateHaveRel;

    time_t dateMonthOrdinal;
    int dateHaveOrdinalMonth;

    time_t dateDayOrdinal;
    time_t dateDayNumber;
    int dateHaveDay;

    const char *dateStart;
    const char *dateInput;
    time_t *dateRelPointer;

    int dateDigitCount;
} DateInfo;

#define YYMALLOC	Tcl_Alloc
#define YYFREE(x)	(Tcl_Free((void*) (x)))

#define yyDSTmode	(info->dateDSTmode)
#define yyDayOrdinal	(info->dateDayOrdinal)
#define yyDayNumber	(info->dateDayNumber)
#define yyMonthOrdinal	(info->dateMonthOrdinal)
#define yyHaveDate	(info->dateHaveDate)
#define yyHaveDay	(info->dateHaveDay)
#define yyHaveOrdinalMonth (info->dateHaveOrdinalMonth)
#define yyHaveRel	(info->dateHaveRel)
#define yyHaveTime	(info->dateHaveTime)
#define yyHaveZone	(info->dateHaveZone)
#define yyTimezone	(info->dateTimezone)
#define yyDay		(info->dateDay)
#define yyMonth		(info->dateMonth)
#define yyYear		(info->dateYear)
#define yyHour		(info->dateHour)
#define yyMinutes	(info->dateMinutes)
#define yySeconds	(info->dateSeconds)
#define yyMeridian	(info->dateMeridian)
#define yyRelMonth	(info->dateRelMonth)
#define yyRelDay	(info->dateRelDay)
#define yyRelSeconds	(info->dateRelSeconds)
#define yyRelPointer	(info->dateRelPointer)
#define yyInput		(info->dateInput)
#define yyDigitCount	(info->dateDigitCount)

#define EPOCH		1970
#define START_OF_TIME	1902
#define END_OF_TIME	2037

/*
 * The offset of tm_year of struct tm returned by localtime, gmtime, etc.
 * Posix requires 1900.
 */

#define TM_YEAR_BASE	1900

#define HOUR(x)		((int) (60 * x))
#define SECSPERDAY	(24L * 60L * 60L)
#define IsLeapYear(x)	((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0))
#define HOUR(x)		((60 * (int)(x)))
#define IsLeapYear(x)	(((x) % 4 == 0) && ((x) % 100 != 0 || (x) % 400 == 0))

#define yyIncrFlags(f)				\
    do {					\
	info->errFlags |= (info->flags & (f));	\
	if (info->errFlags) { YYABORT; }	\
	info->flags |= (f);			\
    } while (0);

/*
 * An entry in the lexical lookup table.
 */

typedef struct _TABLE {
typedef struct {
    const char *name;
    int type;
    time_t value;
    int value;
} TABLE;

/*
 * Daylight-savings mode: on, off, or not yet known.
 */

typedef enum _DSTMODE {
    DSTon, DSToff, DSTmaybe
} DSTMODE;

%}

%union {
    time_t Number;
    Tcl_WideInt Number;
    enum _MERIDIAN Meridian;
}

%{

/*
 * Prototypes of internal functions.
 */

static int		LookupWord(YYSTYPE* yylvalPtr, char *buff);
 static void		TclDateerror(YYLTYPE* location,
static void		TclDateerror(YYLTYPE* location,
				     DateInfo* info, const char *s);
 static int		TclDatelex(YYSTYPE* yylvalPtr, YYLTYPE* location,
static int		TclDatelex(YYSTYPE* yylvalPtr, YYLTYPE* location,
				   DateInfo* info);
static time_t		ToSeconds(time_t Hours, time_t Minutes,
			    time_t Seconds, MERIDIAN Meridian);
MODULE_SCOPE int	yyparse(DateInfo*);

%}

%token	tAGO
%token	tDAY
%token	tDAYZONE
%token	tID
%token	tMERIDIAN
%token	tMONTH
%token	tMONTH_UNIT
%token	tSTARDATE
%token	tSEC_UNIT
%token	tSNUMBER
%token	tUNUMBER
%token	tZONE
%token	tUNUMBER
%token	tZONE
%token	tZONEwO4
%token	tZONEwO2
%token	tEPOCH
%token	tDST
%token	tISOBASE
%token	tISOBAS8
%token	tISOBAS6
%token	tISOBASL
%token	tDAY_UNIT
%token	tNEXT
%token	SP

%type	<Number>	tDAY
%type	<Number>	tDAYZONE
%type	<Number>	tMONTH
%type	<Number>	tMONTH_UNIT
%type	<Number>	tDST
%type	<Number>	tSEC_UNIT
%type	<Number>	tSNUMBER
%type	<Number>	tUNUMBER
%type	<Number>	tUNUMBER
%type	<Number>	INTNUM
%type	<Number>	tZONE
%type	<Number>	tZONEwO4
%type	<Number>	tZONEwO2
%type	<Number>	tISOBASE
%type	<Number>	tISOBAS8
%type	<Number>	tISOBAS6
%type	<Number>	tISOBASL
%type	<Number>	tDAY_UNIT
%type	<Number>	unit
%type	<Number>	sign
%type	<Number>	tNEXT
%type	<Number>	tSTARDATE
%type	<Meridian>	tMERIDIAN
%type	<Meridian>	o_merid

%%

spec	: /* NULL */
	| spec item
	/* | spec SP item */
	;

item	: time {
	    yyHaveTime++;
	    yyIncrFlags(CLF_TIME);
	}
	| zone {
	    yyHaveZone++;
	    yyIncrFlags(CLF_ZONE);
	}
	| date {
	    yyHaveDate++;
	    yyIncrFlags(CLF_HAVEDATE);
	}
	| ordMonth {
	    yyHaveOrdinalMonth++;
	    yyIncrFlags(CLF_ORDINALMONTH);
	}
	| day {
	    yyHaveDay++;
	    yyIncrFlags(CLF_DAYOFWEEK);
	}
	| relspec {
	    yyHaveRel++;
	    info->flags |= CLF_RELCONV;
	}
	| iso {
	    yyHaveTime++;
	    yyIncrFlags(CLF_TIME|CLF_HAVEDATE);
	    yyHaveDate++;
	}
	| trek {
	    yyIncrFlags(CLF_TIME|CLF_HAVEDATE);
	    yyHaveTime++;
	    info->flags |= CLF_RELCONV;
	    yyHaveDate++;
	    yyHaveRel++;
	}
	| number
	| numitem
	;

iextime : tUNUMBER ':' tUNUMBER ':' tUNUMBER {
	    yyHour = $1;
	    yyMinutes = $3;
	    yySeconds = $5;
	}
	| tUNUMBER ':' tUNUMBER {
	    yyHour = $1;
	    yyMinutes = $3;
	    yySeconds = 0;
	}
	;
time	: tUNUMBER tMERIDIAN {
	    yyHour = $1;
	    yyMinutes = 0;
	    yySeconds = 0;
	    yyMeridian = $2;
	}
	| tUNUMBER ':' tUNUMBER o_merid {
	| iextime o_merid {
	    yyHour = $1;
	    yyMinutes = $3;
	    yySeconds = 0;
	    yyMeridian = $4;
	    yyMeridian = $2;
	}
	| tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
	    yyHour = $1;
	    yyMinutes = $3;
	    yySeconds = $5;
	    yyMeridian = $6;
	}
	;

zone	: tZONE tDST {
	    yyTimezone = $1;
	    if (yyTimezone > HOUR( 12)) yyTimezone -= HOUR(100);
	    yyDSTmode = DSTon;
	}
	| tZONE {
	    yyTimezone = $1;
	    if (yyTimezone > HOUR( 12)) yyTimezone -= HOUR(100);
	    yyDSTmode = DSToff;
	}
	| tDAYZONE {
	    yyTimezone = $1;
	    yyDSTmode = DSTon;
	}
	| tZONEwO4 sign INTNUM { /* GMT+0100, GMT-1000, etc. */
	    yyTimezone = $1 - $2*($3 % 100 + ($3 / 100) * 60);
	    yyDSTmode = DSToff;
	}
	| tZONEwO2 sign INTNUM { /* GMT+1, GMT-10, etc. */
	    yyTimezone = $1 - $2*($3 * 60);
	    yyDSTmode = DSToff;
	}
	| sign tUNUMBER {
	| sign INTNUM { /* +0100, -0100 */
	    yyTimezone = -$1*($2 % 100 + ($2 / 100) * 60);
	    yyDSTmode = DSToff;
	}
	;

comma	: ','
	| ',' SP
	;

day	: tDAY {
	    yyDayOrdinal = 1;
	    yyDayNumber = $1;
	    yyDayOfWeek = $1;
	}
	| tDAY ',' {
	| tDAY comma {
	    yyDayOrdinal = 1;
	    yyDayNumber = $1;
	    yyDayOfWeek = $1;
	}
	| tUNUMBER tDAY {
	    yyDayOrdinal = $1;
	    yyDayNumber = $2;
	    yyDayOfWeek = $2;
	}
	| sign SP tUNUMBER tDAY {
	    yyDayOrdinal = $1 * $3;
	    yyDayOfWeek = $4;
	}
	| sign tUNUMBER tDAY {
	    yyDayOrdinal = $1 * $2;
	    yyDayNumber = $3;
	    yyDayOfWeek = $3;
	}
	| tNEXT tDAY {
	    yyDayOrdinal = 2;
	    yyDayNumber = $2;
	    yyDayOfWeek = $2;
	}
	;

iexdate	: tUNUMBER '-' tUNUMBER '-' tUNUMBER {
	    yyMonth = $3;
	    yyDay = $5;
	    yyYear = $1;
	}
	;
date	: tUNUMBER '/' tUNUMBER {
	    yyMonth = $1;
	    yyDay = $3;
	}
	| tUNUMBER '/' tUNUMBER '/' tUNUMBER {
	    yyMonth = $1;
	    yyDay = $3;
	    yyYear = $5;
	}
	| tISOBASE {
	| isodate
	    yyYear = $1 / 10000;
	    yyMonth = ($1 % 10000)/100;
	    yyDay = $1 % 100;
	}
	| tUNUMBER '-' tMONTH '-' tUNUMBER {
	    yyDay = $1;
	    yyMonth = $3;
	    yyYear = $5;
	}
	| tUNUMBER '-' tUNUMBER '-' tUNUMBER {
	    yyMonth = $3;
	    yyDay = $5;
	    yyYear = $1;
	}
	| tMONTH tUNUMBER {
	    yyMonth = $1;
	    yyDay = $2;
	}
	| tMONTH tUNUMBER ',' tUNUMBER {
	| tMONTH tUNUMBER comma tUNUMBER {
	    yyMonth = $1;
	    yyDay = $2;
	    yyYear = $4;
	}
	| tUNUMBER tMONTH {
	    yyMonth = $2;
	    yyDay = $1;
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

442
443
444
445
446
447

448
449
450
451
452
453
454
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
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







-
-
+
+


-
-
+
+



-
+
-
-
-
-
-
+
+
+
+
+
-
-
-

-
+
-



-
-
-

+
+
-
+
-
-
-
-
-
-
-
+
+
+

+
+
+
-
+







+
+
+
+
+
+
+
+
+


-
+









-
+











-
+
+
+
+


-
+





-
+







	    yyMonth = $2;
	    yyDay = $1;
	    yyYear = $3;
	}
	;

ordMonth: tNEXT tMONTH {
	    yyMonthOrdinal = 1;
	    yyMonth = $2;
	    yyMonthOrdinalIncr = 1;
	    yyMonthOrdinal = $2;
	}
	| tNEXT tUNUMBER tMONTH {
	    yyMonthOrdinal = $2;
	    yyMonth = $3;
	    yyMonthOrdinalIncr = $2;
	    yyMonthOrdinal = $3;
	}
	;

iso	: tUNUMBER '-' tUNUMBER '-' tUNUMBER tZONE
isosep	: 'T'|SP
		tUNUMBER ':' tUNUMBER ':' tUNUMBER {
	    if ($6 != HOUR( 7) + HOUR(100)) YYABORT;
	    yyYear = $1;
	    yyMonth = $3;
	    yyDay = $5;
	;
isodate	: tISOBAS8 { /* YYYYMMDD */
	    yyYear = $1 / 10000;
	    yyMonth = ($1 % 10000)/100;
	    yyDay = $1 % 100;
	    yyHour = $7;
	    yyMinutes = $9;
	    yySeconds = $11;
	}
	| tISOBASE tZONE tISOBASE {
	| tISOBAS6 { /* YYMMDD */
	    if ($2 != HOUR( 7) + HOUR(100)) YYABORT;
	    yyYear = $1 / 10000;
	    yyMonth = ($1 % 10000)/100;
	    yyDay = $1 % 100;
	    yyHour = $3 / 10000;
	    yyMinutes = ($3 % 10000)/100;
	    yySeconds = $3 % 100;
	}
	| iexdate
	;
	| tISOBASE tZONE tUNUMBER ':' tUNUMBER ':' tUNUMBER {
isotime	: tISOBAS6 {
	    if ($2 != HOUR( 7) + HOUR(100)) YYABORT;
	    yyYear = $1 / 10000;
	    yyMonth = ($1 % 10000)/100;
	    yyDay = $1 % 100;
	    yyHour = $3;
	    yyMinutes = $5;
	    yySeconds = $7;
	    yyHour = $1 / 10000;
	    yyMinutes = ($1 % 10000)/100;
	    yySeconds = $1 % 100;
	}
	| iextime
	;
iso	: isodate isosep isotime
	| tISOBASE tISOBASE {
	| tISOBASL tISOBAS6 { /* YYYYMMDDhhmmss */
	    yyYear = $1 / 10000;
	    yyMonth = ($1 % 10000)/100;
	    yyDay = $1 % 100;
	    yyHour = $2 / 10000;
	    yyMinutes = ($2 % 10000)/100;
	    yySeconds = $2 % 100;
	}
	| tISOBASL tUNUMBER { /* YYYYMMDDhhmm */
	    if (yyDigitCount != 4) YYABORT; /* normally unreached */
	    yyYear = $1 / 10000;
	    yyMonth = ($1 % 10000)/100;
	    yyDay = $1 % 100;
	    yyHour = $2 / 100;
	    yyMinutes = ($2 % 100);
	    yySeconds = 0;
	}
	;

trek	: tSTARDATE tUNUMBER '.' tUNUMBER {
trek	: tSTARDATE INTNUM '.' tUNUMBER {
	    /*
	     * Offset computed year by -377 so that the returned years will be
	     * in a range accessible with a 32 bit clock seconds value.
	     */

	    yyYear = $2/1000 + 2323 - 377;
	    yyDay  = 1;
	    yyMonth = 1;
	    yyRelDay += (($2%1000)*(365 + IsLeapYear(yyYear)))/1000;
	    yyRelSeconds += $4 * 144 * 60;
	    yyRelSeconds += $4 * (144LL * 60LL);
	}
	;

relspec : relunits tAGO {
	    yyRelSeconds *= -1;
	    yyRelMonth *= -1;
	    yyRelDay *= -1;
	}
	| relunits
	;

relunits : sign tUNUMBER unit {
relunits : sign SP INTNUM unit {
	    *yyRelPointer += $1 * $3 * $4;
	}
	| sign INTNUM unit {
	    *yyRelPointer += $1 * $2 * $3;
	}
	| tUNUMBER unit {
	| INTNUM unit {
	    *yyRelPointer += $1 * $2;
	}
	| tNEXT unit {
	    *yyRelPointer += $2;
	}
	| tNEXT tUNUMBER unit {
	| tNEXT INTNUM unit {
	    *yyRelPointer += $2 * $3;
	}
	| unit {
	    *yyRelPointer += $1;
	}
	;

470
471
472
473
474
475
476
477
478













479
480
481

482
483
484
485
486
487
488
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







-
-
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+







	}
	| tMONTH_UNIT {
	    $$ = $1;
	    yyRelPointer = &yyRelMonth;
	}
	;

number	: tUNUMBER {
	    if (yyHaveTime && yyHaveDate && !yyHaveRel) {
INTNUM	: tUNUMBER {
	    $$ = $1;
	}
	| tISOBAS6 {
	    $$ = $1;
	}
	| tISOBAS8 {
	    $$ = $1;
	}
	;

numitem	: tUNUMBER {
	    if ((info->flags & (CLF_TIME|CLF_HAVEDATE|CLF_RELCONV)) == (CLF_TIME|CLF_HAVEDATE)) {
		yyYear = $1;
	    } else {
		yyHaveTime++;
		yyIncrFlags(CLF_TIME);
		if (yyDigitCount <= 2) {
		    yyHour = $1;
		    yyMinutes = 0;
		} else {
		    yyHour = $1 / 100;
		    yyMinutes = $1 % 100;
		}
515
516
517
518
519
520
521
522

523
524
525
526
527
528
529
492
493
494
495
496
497
498

499
500
501
502
503
504
505
506







-
+







    { "july",		tMONTH,	 7 },
    { "august",		tMONTH,	 8 },
    { "september",	tMONTH,	 9 },
    { "sept",		tMONTH,	 9 },
    { "october",	tMONTH, 10 },
    { "november",	tMONTH, 11 },
    { "december",	tMONTH, 12 },
    { "sunday",		tDAY, 0 },
    { "sunday",		tDAY, 7 },
    { "monday",		tDAY, 1 },
    { "tuesday",	tDAY, 2 },
    { "tues",		tDAY, 2 },
    { "wednesday",	tDAY, 3 },
    { "wednes",		tDAY, 3 },
    { "thursday",	tDAY, 4 },
    { "thur",		tDAY, 4 },
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
536
537
538
539
540
541
542














543
544
545
546
547
548
549







-
-
-
-
-
-
-
-
-
-
-
-
-
-







    { "tomorrow",	tDAY_UNIT,	1 },
    { "yesterday",	tDAY_UNIT,	-1 },
    { "today",		tDAY_UNIT,	0 },
    { "now",		tSEC_UNIT,	0 },
    { "last",		tUNUMBER,	-1 },
    { "this",		tSEC_UNIT,	0 },
    { "next",		tNEXT,		1 },
#if 0
    { "first",		tUNUMBER,	1 },
    { "second",		tUNUMBER,	2 },
    { "third",		tUNUMBER,	3 },
    { "fourth",		tUNUMBER,	4 },
    { "fifth",		tUNUMBER,	5 },
    { "sixth",		tUNUMBER,	6 },
    { "seventh",	tUNUMBER,	7 },
    { "eighth",		tUNUMBER,	8 },
    { "ninth",		tUNUMBER,	9 },
    { "tenth",		tUNUMBER,	10 },
    { "eleventh",	tUNUMBER,	11 },
    { "twelfth",	tUNUMBER,	12 },
#endif
    { "ago",		tAGO,		1 },
    { "epoch",		tEPOCH,		0 },
    { "stardate",	tSTARDATE,	0 },
    { NULL, 0, 0 }
};

/*
614
615
616
617
618
619
620


621
622
623
624
625
626
627
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592







+
+







    { "cdt",	tDAYZONE,  HOUR( 6) },	    /* Central Daylight */
    { "mst",	tZONE,	   HOUR( 7) },	    /* Mountain Standard */
    { "mdt",	tDAYZONE,  HOUR( 7) },	    /* Mountain Daylight */
    { "pst",	tZONE,	   HOUR( 8) },	    /* Pacific Standard */
    { "pdt",	tDAYZONE,  HOUR( 8) },	    /* Pacific Daylight */
    { "yst",	tZONE,	   HOUR( 9) },	    /* Yukon Standard */
    { "ydt",	tDAYZONE,  HOUR( 9) },	    /* Yukon Daylight */
    { "akst",	tZONE,	   HOUR( 9) },	    /* Alaska Standard */
    { "akdt",	tDAYZONE,  HOUR( 9) },	    /* Alaska Daylight */
    { "hst",	tZONE,	   HOUR(10) },	    /* Hawaii Standard */
    { "hdt",	tDAYZONE,  HOUR(10) },	    /* Hawaii Daylight */
    { "cat",	tZONE,	   HOUR(10) },	    /* Central Alaska */
    { "ahst",	tZONE,	   HOUR(10) },	    /* Alaska-Hawaii Standard */
    { "nt",	tZONE,	   HOUR(11) },	    /* Nome */
    { "idlw",	tZONE,	   HOUR(12) },	    /* International Date Line West */
    { "cet",	tZONE,	  -HOUR( 1) },	    /* Central European */
637
638
639
640
641
642
643
644

645
646
647
648
649
650
651
602
603
604
605
606
607
608

609
610
611
612
613
614
615
616







-
+







    { "bt",	tZONE,	  -HOUR( 3) },	    /* Baghdad, USSR Zone 2 */
    { "it",	tZONE,	  -HOUR( 7/2) },    /* Iran */
    { "zp4",	tZONE,	  -HOUR( 4) },	    /* USSR Zone 3 */
    { "zp5",	tZONE,	  -HOUR( 5) },	    /* USSR Zone 4 */
    { "ist",	tZONE,	  -HOUR(11/2) },    /* Indian Standard */
    { "zp6",	tZONE,	  -HOUR( 6) },	    /* USSR Zone 5 */
#if	0
    /* For completeness.  NST is also Newfoundland Stanard, nad SST is
    /* For completeness.  NST is also Newfoundland Standard, and SST is
     * also Swedish Summer. */
    { "nst",	tZONE,	  -HOUR(13/2) },    /* North Sumatra */
    { "sst",	tZONE,	  -HOUR( 7) },	    /* South Sumatra, USSR Zone 6 */
#endif	/* 0 */
    { "wast",	tZONE,	  -HOUR( 7) },	    /* West Australian Standard */
    { "wadt",	tDAYZONE, -HOUR( 7) },	    /* West Australian Daylight */
    { "jt",	tZONE,	  -HOUR(15/2) },    /* Java (3pm in Cronusland!) */
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
707
708
709
710
711
712
713
714
715



716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732

733
734
735
736



737
738
739
740
741
742
743
744
745
746
747

748
749
750

751
752
753
754
755

756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778

779
780
781
782

783
784
785
786
787
788
789
635
636
637
638
639
640
641

























642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709

710
711



712
713
714
715
716



717
718




719
720


721


722


723


724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743

744
745
746
747

748
749
750
751
752
753
754
755







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+












+
+
+
















-
+

-
-
-
+
+
+


-
-
-


-
-
-
-
+

-
-
+
-
-

-
-
+
-
-




















-
+



-
+







};

/*
 * Military timezone table.
 */

static const TABLE MilitaryTable[] = {
    { "a",	tZONE,	-HOUR( 1) + HOUR(100) },
    { "b",	tZONE,	-HOUR( 2) + HOUR(100) },
    { "c",	tZONE,	-HOUR( 3) + HOUR(100) },
    { "d",	tZONE,	-HOUR( 4) + HOUR(100) },
    { "e",	tZONE,	-HOUR( 5) + HOUR(100) },
    { "f",	tZONE,	-HOUR( 6) + HOUR(100) },
    { "g",	tZONE,	-HOUR( 7) + HOUR(100) },
    { "h",	tZONE,	-HOUR( 8) + HOUR(100) },
    { "i",	tZONE,	-HOUR( 9) + HOUR(100) },
    { "k",	tZONE,	-HOUR(10) + HOUR(100) },
    { "l",	tZONE,	-HOUR(11) + HOUR(100) },
    { "m",	tZONE,	-HOUR(12) + HOUR(100) },
    { "n",	tZONE,	HOUR(  1) + HOUR(100) },
    { "o",	tZONE,	HOUR(  2) + HOUR(100) },
    { "p",	tZONE,	HOUR(  3) + HOUR(100) },
    { "q",	tZONE,	HOUR(  4) + HOUR(100) },
    { "r",	tZONE,	HOUR(  5) + HOUR(100) },
    { "s",	tZONE,	HOUR(  6) + HOUR(100) },
    { "t",	tZONE,	HOUR(  7) + HOUR(100) },
    { "u",	tZONE,	HOUR(  8) + HOUR(100) },
    { "v",	tZONE,	HOUR(  9) + HOUR(100) },
    { "w",	tZONE,	HOUR( 10) + HOUR(100) },
    { "x",	tZONE,	HOUR( 11) + HOUR(100) },
    { "y",	tZONE,	HOUR( 12) + HOUR(100) },
    { "z",	tZONE,	HOUR( 0)  + HOUR(100) },
    { "a",	tZONE,	-HOUR( 1) },
    { "b",	tZONE,	-HOUR( 2) },
    { "c",	tZONE,	-HOUR( 3) },
    { "d",	tZONE,	-HOUR( 4) },
    { "e",	tZONE,	-HOUR( 5) },
    { "f",	tZONE,	-HOUR( 6) },
    { "g",	tZONE,	-HOUR( 7) },
    { "h",	tZONE,	-HOUR( 8) },
    { "i",	tZONE,	-HOUR( 9) },
    { "k",	tZONE,	-HOUR(10) },
    { "l",	tZONE,	-HOUR(11) },
    { "m",	tZONE,	-HOUR(12) },
    { "n",	tZONE,	HOUR(  1) },
    { "o",	tZONE,	HOUR(  2) },
    { "p",	tZONE,	HOUR(  3) },
    { "q",	tZONE,	HOUR(  4) },
    { "r",	tZONE,	HOUR(  5) },
    { "s",	tZONE,	HOUR(  6) },
    { "t",	tZONE,	HOUR(  7) },
    { "u",	tZONE,	HOUR(  8) },
    { "v",	tZONE,	HOUR(  9) },
    { "w",	tZONE,	HOUR( 10) },
    { "x",	tZONE,	HOUR( 11) },
    { "y",	tZONE,	HOUR( 12) },
    { "z",	tZONE,	HOUR( 0) },
    { NULL, 0, 0 }
};

static inline const char *
bypassSpaces(
    const char *s)
{
    while (TclIsSpaceProc(*s)) {
	s++;
    }
    return s;
}

/*
 * Dump error messages in the bit bucket.
 */

static void
TclDateerror(
    YYLTYPE* location,
    DateInfo* infoPtr,
    const char *s)
{
    Tcl_Obj* t;
    if (!infoPtr->messages) {
	TclNewObj(infoPtr->messages);
    }
    Tcl_AppendToObj(infoPtr->messages, infoPtr->separatrix, -1);
    Tcl_AppendToObj(infoPtr->messages, s, -1);
    Tcl_AppendToObj(infoPtr->messages, " (characters ", -1);
    TclNewIntObj(t, location->first_column);
    Tcl_IncrRefCount(t);
    Tcl_AppendObjToObj(infoPtr->messages, t);
    Tcl_DecrRefCount(t);
    Tcl_AppendToObj(infoPtr->messages, "-", -1);
    TclNewIntObj(t, location->last_column);
    Tcl_IncrRefCount(t);
    Tcl_AppendObjToObj(infoPtr->messages, t);
    Tcl_DecrRefCount(t);
    Tcl_AppendToObj(infoPtr->messages, ")", -1);
    infoPtr->separatrix = "\n";
}

static time_t
int
ToSeconds(
    time_t Hours,
    time_t Minutes,
    time_t Seconds,
    int Hours,
    int Minutes,
    int Seconds,
    MERIDIAN Meridian)
{
    if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59) {
	return -1;
    }
    switch (Meridian) {
    case MER24:
	if (Hours < 0 || Hours > 23) {
	    return -1;
	}
	return (Hours * 60L + Minutes) * 60L + Seconds;
	return (Hours * 60 + Minutes) * 60 + Seconds;
    case MERam:
	if (Hours < 1 || Hours > 12) {
	    return -1;
	return (((Hours / 24) * 24 + (Hours % 12)) * 60 + Minutes) * 60 + Seconds;
	}
	return ((Hours % 12) * 60L + Minutes) * 60L + Seconds;
    case MERpm:
	if (Hours < 1 || Hours > 12) {
	    return -1;
	return (((Hours / 24) * 24 + (Hours % 12) + 12) * 60 + Minutes) * 60 + Seconds;
	}
	return (((Hours % 12) + 12) * 60L + Minutes) * 60L + Seconds;
    }
    return -1;			/* Should never be reached */
}

static int
LookupWord(
    YYSTYPE* yylvalPtr,
    char *buff)
{
    char *p;
    char *q;
    const TABLE *tp;
    int i, abbrev;

    /*
     * Make it lowercase.
     */

    Tcl_UtfToLower(buff);

    if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
    if (*buff == 'a' && (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0)) {
	yylvalPtr->Meridian = MERam;
	return tMERIDIAN;
    }
    if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
    if (*buff == 'p' && (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0)) {
	yylvalPtr->Meridian = MERpm;
	return tMERIDIAN;
    }

    /*
     * See if we have an abbreviation for a month.
     */
889
890
891
892
893
894
895

896
897
898
899
900
901
902











903

904
905

906
907
908
909
910
911












912
913
914
915
916














917
918
919
920
921
922
923




924
925
926
927
928









929

930
931
932

933
934
935
936
937
938
939































940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
1128
1129
855
856
857
858
859
860
861
862
863
864
865




866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910




911
912
913
914





915
916
917
918
919
920
921
922
923
924
925
926
927

928
929
930
931
932
933
934

935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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







+



-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

+

-
+

-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+

+


-
+






-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



















-
+

-
+
-

-
-
+

-
-
-
-


-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
-
-
-
-
-
-
-
+
-
-

-
-
+

-
-
+

-
+
-

+
-
+
-

-
-
-
-
-
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+


-
-
-
+
+





-
-
-
+
+

+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+









    YYLTYPE* location,
    DateInfo *info)
{
    char c;
    char *p;
    char buff[20];
    int Count;
    const char *tokStart;

    location->first_column = yyInput - info->dateStart;
    for ( ; ; ) {
	while (TclIsSpaceProcM(*yyInput)) {
	    yyInput++;
	}


	if (isspace(UCHAR(*yyInput))) {
	    yyInput = bypassSpaces(yyInput);
	    /* ignore space at end of text and before some words */
	    c = *yyInput;
	    if (c != '\0' && !isalpha(UCHAR(c))) {
		return SP;
	    }
	}
	tokStart = yyInput;

	if (isdigit(UCHAR(c = *yyInput))) { /* INTL: digit */

	    /*
	     * Convert the string into a number; count the number of digits.
	     * Count the number of digits.
	     */

	    Count = 0;
	    for (yylvalPtr->Number = 0;
		    isdigit(UCHAR(c = *yyInput++)); ) {	  /* INTL: digit */
		yylvalPtr->Number = 10 * yylvalPtr->Number + c - '0';
	    p = (char *)yyInput;
	    while (isdigit(UCHAR(*++p))) {};
	    yyDigitCount = p - yyInput;
	    /*
	     * A number with 12 or 14 digits is considered an ISO 8601 date.
	     */
	    if (yyDigitCount == 14 || yyDigitCount == 12) {
		/* long form of ISO 8601 (without separator), either
		 * YYYYMMDDhhmmss or YYYYMMDDhhmm, so reduce to date
		 * (8 chars is isodate) */
		p = (char *)yyInput+8;
		if (TclAtoWIe(&yylvalPtr->Number, yyInput, p, 1) != TCL_OK) {
		Count++;
	    }
	    yyInput--;
	    yyDigitCount = Count;

		    return tID; /* overflow*/
		}
		yyDigitCount = 8;
		yyInput = p;
		location->last_column = yyInput - info->dateStart - 1;
		return tISOBASL;
	    }
	    /*
	     * Convert the string into a number
	     */
	    if (TclAtoWIe(&yylvalPtr->Number, yyInput, p, 1) != TCL_OK) {
		return tID; /* overflow*/
	    }
	    yyInput = p;
	    /*
	     * A number with 6 or more digits is considered an ISO 8601 base.
	     */

	    if (Count >= 6) {
		location->last_column = yyInput - info->dateStart - 1;
		return tISOBASE;
	    location->last_column = yyInput - info->dateStart - 1;
	    if (yyDigitCount >= 6) {
		if (yyDigitCount == 8) {
		    return tISOBAS8;
	    } else {
		location->last_column = yyInput - info->dateStart - 1;
		return tUNUMBER;
	    }
	}
		}
		if (yyDigitCount == 6) {
		    return tISOBAS6;
		}
	    }
	    /* ignore spaces after digits (optional) */
	    yyInput = bypassSpaces(yyInput);
	    return tUNUMBER;
	}
	if (!(c & 0x80) && isalpha(UCHAR(c))) {		  /* INTL: ISO only. */
	    int ret;
	    for (p = buff; isalpha(UCHAR(c = *yyInput++)) /* INTL: ISO only. */
		     || c == '.'; ) {
		if (p < &buff[sizeof buff - 1]) {
		if (p < &buff[sizeof(buff) - 1]) {
		    *p++ = c;
		}
	    }
	    *p = '\0';
	    yyInput--;
	    location->last_column = yyInput - info->dateStart - 1;
	    return LookupWord(yylvalPtr, buff);
	    ret = LookupWord(yylvalPtr, buff);
	    /*
	     * lookahead:
	     *	for spaces to consider word boundaries (for instance
	     *	literal T in isodateTisotimeZ is not a TZ, but Z is UTC);
	     *	for +/- digit, to differentiate between "GMT+1000 day" and "GMT +1000 day";
	     * bypass spaces after token (but ignore by TZ+OFFS), because should
	     * recognize next SP token, if TZ only.
	     */
	    if (ret == tZONE || ret == tDAYZONE) {
		c = *yyInput;
		if (isdigit(UCHAR(c))) { /* literal not a TZ  */
		    yyInput = tokStart;
		    return *yyInput++;
		}
		if ((c == '+' || c == '-') && isdigit(UCHAR(*(yyInput+1)))) {
		    if ( !isdigit(UCHAR(*(yyInput+2)))
		      || !isdigit(UCHAR(*(yyInput+3)))) {
			/* GMT+1, GMT-10, etc. */
			return tZONEwO2;
		    }
		    if ( isdigit(UCHAR(*(yyInput+4)))
		      && !isdigit(UCHAR(*(yyInput+5)))) {
			/* GMT+1000, etc. */
			return tZONEwO4;
		    }
		}
	    }
	    yyInput = bypassSpaces(yyInput);
	    return ret;

	}
	if (c != '(') {
	    location->last_column = yyInput - info->dateStart;
	    return *yyInput++;
	}
	Count = 0;
	do {
	    c = *yyInput++;
	    if (c == '\0') {
		location->last_column = yyInput - info->dateStart - 1;
		return c;
	    } else if (c == '(') {
		Count++;
	    } else if (c == ')') {
		Count--;
	    }
	} while (Count > 0);
    }
}


int
TclClockOldscanObjCmd(
TclClockFreeScan(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Count of paraneters */
    Tcl_Obj *const *objv)	/* Parameters */
    DateInfo *info)		/* Input and result parameters */
{
    Tcl_Obj *result, *resultElement;
    int yr, mo, da;
    DateInfo dateInfo;
    DateInfo* info = &dateInfo;
    int status;

    if (objc != 5) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"stringToParse baseYear baseMonth baseDay" );
	return TCL_ERROR;
    }

    yyInput = TclGetString(objv[1]);
  #if YYDEBUG
    /* enable debugging if compiled with YYDEBUG */
    yydebug = 1;
  #endif

    /*
     * yyInput = stringToParse;
    dateInfo.dateStart = yyInput;

    yyHaveDate = 0;
     *
     * ClockInitDateInfo(info) should be executed to pre-init info;
    if (Tcl_GetIntFromObj(interp, objv[2], &yr) != TCL_OK
	    || Tcl_GetIntFromObj(interp, objv[3], &mo) != TCL_OK
	    || Tcl_GetIntFromObj(interp, objv[4], &da) != TCL_OK) {
	return TCL_ERROR;
    }
    yyYear = yr; yyMonth = mo; yyDay = da;

     */
    yyHaveTime = 0;
    yyHour = 0; yyMinutes = 0; yySeconds = 0; yyMeridian = MER24;

    yyHaveZone = 0;
    yyTimezone = 0; yyDSTmode = DSTmaybe;
    yyDSTmode = DSTmaybe;

    yyHaveOrdinalMonth = 0;
    yyMonthOrdinal = 0;
    info->separatrix = "";

    yyHaveDay = 0;
    info->dateStart = yyInput;
    yyDayOrdinal = 0; yyDayNumber = 0;

    /* ignore spaces at begin */
    yyHaveRel = 0;
    yyInput = bypassSpaces(yyInput);
    yyRelMonth = 0; yyRelDay = 0; yyRelSeconds = 0; yyRelPointer = NULL;

    TclNewObj(dateInfo.messages);
    dateInfo.separatrix = "";
    Tcl_IncrRefCount(dateInfo.messages);

    status = yyparse(&dateInfo);
    /* parse */
    status = yyparse(info);
    if (status == 1) {
	const char *msg = NULL;
	if (info->errFlags & CLF_HAVEDATE) {
	    msg = "more than one date in string";
	} else if (info->errFlags & CLF_TIME) {
	    msg = "more than one time of day in string";
	} else if (info->errFlags & CLF_ZONE) {
	    msg = "more than one time zone in string";
	} else if (info->errFlags & CLF_DAYOFWEEK) {
	    msg = "more than one weekday in string";
	} else if (info->errFlags & CLF_ORDINALMONTH) {
	    msg = "more than one ordinal month in string";
	}
	if (msg) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1));
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", (char *)NULL);
	} else {
	Tcl_SetObjResult(interp, dateInfo.messages);
	Tcl_DecrRefCount(dateInfo.messages);
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", NULL);
	return TCL_ERROR;
	    Tcl_SetObjResult(interp,
		info->messages ? info->messages : Tcl_NewObj());
	    info->messages = NULL;
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", (char *)NULL);
	}
	status = TCL_ERROR;
    } else if (status == 2) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("memory exhausted", -1));
	Tcl_DecrRefCount(dateInfo.messages);
	Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
	return TCL_ERROR;
	Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
	status = TCL_ERROR;
    } else if (status != 0) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("Unknown status returned "
						  "from date parser. Please "
						  "report this error as a "
						  "bug in Tcl.", -1));
	Tcl_DecrRefCount(dateInfo.messages);
	Tcl_SetErrorCode(interp, "TCL", "BUG", NULL);
	return TCL_ERROR;
	Tcl_SetErrorCode(interp, "TCL", "BUG", (char *)NULL);
	status = TCL_ERROR;
    }
    if (info->messages) {
    Tcl_DecrRefCount(dateInfo.messages);

	Tcl_DecrRefCount(info->messages);
    }
    if (yyHaveDate > 1) {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("more than one date in string", -1));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL);
	return TCL_ERROR;
    }
    if (yyHaveTime > 1) {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("more than one time of day in string", -1));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL);
	return TCL_ERROR;
    }
    if (yyHaveZone > 1) {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("more than one time zone in string", -1));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL);
	return TCL_ERROR;
    }
    if (yyHaveDay > 1) {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("more than one weekday in string", -1));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL);
	return TCL_ERROR;
    }
    if (yyHaveOrdinalMonth > 1) {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("more than one ordinal month in string", -1));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL);
	return TCL_ERROR;
    }

    TclNewObj(result);
    TclNewObj(resultElement);
    if (yyHaveDate) {
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyYear));
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyMonth));
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyDay));
    }
    Tcl_ListObjAppendElement(interp, result, resultElement);

    if (yyHaveTime) {
	Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj(
		ToSeconds(yyHour, yyMinutes, yySeconds, (MERIDIAN)yyMeridian)));
    } else {
	Tcl_ListObjAppendElement(interp, result, Tcl_NewObj());
    }

    TclNewObj(resultElement);
    if (yyHaveZone) {
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(-yyTimezone));
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(1 - yyDSTmode));
    }
    Tcl_ListObjAppendElement(interp, result, resultElement);

    TclNewObj(resultElement);
    if (yyHaveRel) {
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyRelMonth));
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyRelDay));
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyRelSeconds));
    }
    Tcl_ListObjAppendElement(interp, result, resultElement);

    TcNewObj(resultElement);
    if (yyHaveDay && !yyHaveDate) {
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyDayOrdinal));
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyDayNumber));
    }
    Tcl_ListObjAppendElement(interp, result, resultElement);

    TclNewObj(resultElement);
    if (yyHaveOrdinalMonth) {
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyMonthOrdinal));
	Tcl_ListObjAppendElement(interp, resultElement,
		Tcl_NewIntObj(yyMonth));
    }
    Tcl_ListObjAppendElement(interp, result, resultElement);

    Tcl_SetObjResult(interp, result);
    return TCL_OK;
    return status;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclHash.c.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * tclHash.c --
 *
 *	Implementation of in-memory hash tables for Tcl and Tcl-based
 *	applications.
 *
 * Copyright (c) 1991-1993 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 * Copyright © 1991-1993 The Regents of the University of California.
 * Copyright © 1994 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

32
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46


47
48
49
50
51
52
53







-
+







-
-








/*
 * Prototypes for the array hash key methods.
 */

static Tcl_HashEntry *	AllocArrayEntry(Tcl_HashTable *tablePtr, void *keyPtr);
static int		CompareArrayKeys(void *keyPtr, Tcl_HashEntry *hPtr);
static TCL_HASH_TYPE	HashArrayKey(Tcl_HashTable *tablePtr, void *keyPtr);
static size_t		HashArrayKey(Tcl_HashTable *tablePtr, void *keyPtr);

/*
 * Prototypes for the string hash key methods.
 */

static Tcl_HashEntry *	AllocStringEntry(Tcl_HashTable *tablePtr,
			    void *keyPtr);
static int		CompareStringKeys(void *keyPtr, Tcl_HashEntry *hPtr);
static TCL_HASH_TYPE	HashStringKey(Tcl_HashTable *tablePtr, void *keyPtr);

/*
 * Function prototypes for static functions in this file:
 */

static Tcl_HashEntry *	BogusFind(Tcl_HashTable *tablePtr, const char *key);
static Tcl_HashEntry *	BogusCreate(Tcl_HashTable *tablePtr, const char *key,
76
77
78
79
80
81
82
83
84


85
86
87
88
89
90
91
74
75
76
77
78
79
80


81
82
83
84
85
86
87
88
89







-
-
+
+







    NULL, /* AllocOneWordKey, */	/* allocEntryProc */
    NULL  /* FreeOneWordKey, */		/* freeEntryProc */
};

const Tcl_HashKeyType tclStringHashKeyType = {
    TCL_HASH_KEY_TYPE_VERSION,		/* version */
    0,					/* flags */
    HashStringKey,			/* hashKeyProc */
    CompareStringKeys,			/* compareKeysProc */
    TclHashStringKey,			/* hashKeyProc */
    TclCompareStringKeys,		/* compareKeysProc */
    AllocStringEntry,			/* allocEntryProc */
    NULL				/* freeEntryProc */
};

/*
 *----------------------------------------------------------------------
 *
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
208
209
210
211
212
213
214

215
216
217
218
219
220
221







-







static Tcl_HashEntry *
FindHashEntry(
    Tcl_HashTable *tablePtr,	/* Table in which to lookup entry. */
    const char *key)		/* Key to use to find matching entry. */
{
    return CreateHashEntry(tablePtr, key, NULL);
}


/*
 *----------------------------------------------------------------------
 *
 * CreateHashEntry --
 *
 *	Given a hash table with string keys, and a string key, find the entry
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
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







-
+









-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	hash = typePtr->hashKeyProc(tablePtr, (void *) key);
	if (typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) {
	    index = RANDOM_INDEX(tablePtr, hash);
	} else {
	    index = hash & tablePtr->mask;
	}
    } else {
	hash = (size_t) key;
	hash = PTR2UINT(key);
	index = RANDOM_INDEX(tablePtr, hash);
    }

    /*
     * Search all of the entries in the appropriate bucket.
     */

    if (typePtr->compareKeysProc) {
	Tcl_CompareHashKeysProc *compareKeysProc = typePtr->compareKeysProc;

	for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
		hPtr = hPtr->nextPtr) {
	    if (hash != hPtr->hash) {
		continue;
	    }
	    /* if keys pointers or values are equal */
	    if ((key == hPtr->key.oneWordValue)
		|| compareKeysProc((void *) key, hPtr)
	    ) {
		if (newPtr) {
		    *newPtr = 0;
		}
		return hPtr;
	if (typePtr->flags & TCL_HASH_KEY_DIRECT_COMPARE) {
	    for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
		    hPtr = hPtr->nextPtr) {
		if (hash != hPtr->hash) {
		    continue;
		}
		/* if keys pointers or values are equal */
		if ((key == hPtr->key.oneWordValue)
		    || compareKeysProc((void *) key, hPtr)) {
		    if (newPtr) {
			*newPtr = 0;
		    }
		    return hPtr;
		}
	    }
	} else { /* no direct compare - compare key addresses only */
	    for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
		    hPtr = hPtr->nextPtr) {
		if (hash != hPtr->hash) {
		    continue;
		}
		/* if needle pointer equals content pointer or values equal */
		if ((key == hPtr->key.string)
			|| compareKeysProc((void *) key, hPtr)) {
		    if (newPtr) {
			*newPtr = 0;
		    }
		    return hPtr;
		}
	    }
	}
    } else {
	for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
		hPtr = hPtr->nextPtr) {
	    if (hash != hPtr->hash) {
		continue;
434
435
436
437
438
439
440
441

442
443
444
445
446
447
448
446
447
448
449
450
451
452

453
454
455
456
457
458
459
460







-
+








void
Tcl_DeleteHashTable(
    Tcl_HashTable *tablePtr)	/* Table to delete. */
{
    Tcl_HashEntry *hPtr, *nextPtr;
    const Tcl_HashKeyType *typePtr;
    size_t i;
    Tcl_Size i;

    if (tablePtr->keyType == TCL_STRING_KEYS) {
	typePtr = &tclStringHashKeyType;
    } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) {
	typePtr = &tclOneWordHashKeyType;
    } else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS
	    || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) {
538
539
540
541
542
543
544
545

546
547
548
549
550
551
552
553
550
551
552
553
554
555
556

557

558
559
560
561
562
563
564







-
+
-







 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_HashEntry *
Tcl_NextHashEntry(
    Tcl_HashSearch *searchPtr)
    Tcl_HashSearch *searchPtr)	/* Place to store information about progress
				/* Place to store information about progress
				 * through the table. Must have been
				 * initialized by calling
				 * Tcl_FirstHashEntry. */
{
    Tcl_HashEntry *hPtr;
    Tcl_HashTable *tablePtr = searchPtr->tablePtr;

583
584
585
586
587
588
589

590

591
592
593
594
595
596
597
594
595
596
597
598
599
600
601

602
603
604
605
606
607
608
609







+
-
+







 */

char *
Tcl_HashStats(
    Tcl_HashTable *tablePtr)	/* Table for which to produce stats. */
{
#define NUM_COUNTERS 10
    Tcl_Size i;
    size_t count[NUM_COUNTERS], overflow, i, j;
    size_t count[NUM_COUNTERS], overflow, j;
    double average, tmp;
    Tcl_HashEntry *hPtr;
    char *result, *p;

    /*
     * Compute a histogram of bucket usage.
     */
618
619
620
621
622
623
624
625

626
627
628
629

630
631
632
633

634
635
636

637
638
639
640
641
642
643
630
631
632
633
634
635
636

637
638
639
640

641
642
643
644

645
646
647

648
649
650
651
652
653
654
655







-
+



-
+



-
+


-
+







    }

    /*
     * Print out the histogram and a few other pieces of information.
     */

    result = (char *)Tcl_Alloc((NUM_COUNTERS * 60) + 300);
    sprintf(result, "%" TCL_Z_MODIFIER "u entries in table, %" TCL_Z_MODIFIER "u buckets\n",
    snprintf(result, 60, "%" TCL_SIZE_MODIFIER "u entries in table, %" TCL_SIZE_MODIFIER "u buckets\n",
	    tablePtr->numEntries, tablePtr->numBuckets);
    p = result + strlen(result);
    for (i = 0; i < NUM_COUNTERS; i++) {
	sprintf(p, "number of buckets with %" TCL_Z_MODIFIER "u entries: %" TCL_Z_MODIFIER "u\n",
	snprintf(p, 60, "number of buckets with %" TCL_SIZE_MODIFIER "u entries: %" TCL_SIZE_MODIFIER "u\n",
		i, count[i]);
	p += strlen(p);
    }
    sprintf(p, "number of buckets with %d or more entries: %" TCL_Z_MODIFIER "u\n",
    snprintf(p, 60, "number of buckets with %d or more entries: %" TCL_SIZE_MODIFIER "u\n",
	    NUM_COUNTERS, overflow);
    p += strlen(p);
    sprintf(p, "average search distance for entry: %.1f", average);
    snprintf(p, 60, "average search distance for entry: %.1f", average);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * AllocArrayEntry --
652
653
654
655
656
657
658
659

660
661
662
663
664
665


666
667
668
669
670
671
672
673
674
675

676
677
678
679
680
681
682
683
684
685
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







-
+

-
-

-
-
+
+

-
-
-





-
+
-
-
-







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

static Tcl_HashEntry *
AllocArrayEntry(
    Tcl_HashTable *tablePtr,	/* Hash table. */
    void *keyPtr)			/* Key to store in the hash table entry. */
    void *keyPtr)		/* Key to store in the hash table entry. */
{
    int *array = (int *) keyPtr;
    int *iPtr1, *iPtr2;
    Tcl_HashEntry *hPtr;
    int count;
    size_t size;
    size_t count = tablePtr->keyType * sizeof(int);
    size_t size = offsetof(Tcl_HashEntry, key) + count;

    count = tablePtr->keyType;

    size = sizeof(Tcl_HashEntry) + (count*sizeof(int)) - sizeof(hPtr->key);
    if (size < sizeof(Tcl_HashEntry)) {
	size = sizeof(Tcl_HashEntry);
    }
    hPtr = (Tcl_HashEntry *)Tcl_Alloc(size);

    for (iPtr1 = array, iPtr2 = hPtr->key.words;
    memcpy(hPtr->key.string, keyPtr, count);
	    count > 0; count--, iPtr1++, iPtr2++) {
	*iPtr2 = *iPtr1;
    }
    Tcl_SetHashValue(hPtr, NULL);

    return hPtr;
}

/*
 *----------------------------------------------------------------------
696
697
698
699
700
701
702
703

704
705
706
707
708

709
710
711
712
713

714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740

741
742
743

744
745
746

747
748
749
750
751
752
753
700
701
702
703
704
705
706

707
708
709



710

711



712






713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732

733
734
735

736
737
738

739
740
741
742
743
744
745
746







-
+


-
-
-
+
-

-
-
-
+
-
-
-
-
-
-




















-
+


-
+


-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
CompareArrayKeys(
    void *keyPtr,			/* New key to compare. */
    void *keyPtr,		/* New key to compare. */
    Tcl_HashEntry *hPtr)	/* Existing key to compare. */
{
    const int *iPtr1 = (const int *)keyPtr;
    const int *iPtr2 = hPtr->key.words;
    Tcl_HashTable *tablePtr = hPtr->tablePtr;
    size_t count = hPtr->tablePtr->keyType * sizeof(int);
    int count;

    for (count = tablePtr->keyType; ; count--, iPtr1++, iPtr2++) {
	if (count == 0) {
	    return 1;
    return !memcmp(keyPtr, hPtr->key.string, count);
	}
	if (*iPtr1 != *iPtr2) {
	    break;
	}
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * HashArrayKey --
 *
 *	Compute a one-word summary of an array, which can be used to generate
 *	a hash index.
 *
 * Results:
 *	The return value is a one-word summary of the information in
 *	string.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static TCL_HASH_TYPE
static size_t
HashArrayKey(
    Tcl_HashTable *tablePtr,	/* Hash table. */
    void *keyPtr)				/* Key from which to compute hash value. */
    void *keyPtr)		/* Key from which to compute hash value. */
{
    const int *array = (const int *) keyPtr;
    TCL_HASH_TYPE result;
    size_t result;
    int count;

    for (result = 0, count = tablePtr->keyType; count > 0;
	    count--, array++) {
	result += *array;
    }
    return result;
768
769
770
771
772
773
774
775

776
777
778
779
780
781
782
783
784
785
786

787
788
789
790
791
792
793
794
795

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811



812
813
814
815
816
817
818
819
820

821
822
823
824
825
826
827
828
829
830
831
832
833
834
835


836
837

838
839
840

841
842
843
844
845
846
847
761
762
763
764
765
766
767

768
769
770
771
772
773
774
775
776
777
778

779
780
781
782
783
784
785
786
787

788
789
790
791
792
793
794
795
796
797
798
799
800
801



802
803
804
805
806
807
808
809
810
811
812

813
814
815
816
817
818
819
820
821
822
823
824
825
826


827
828
829

830
831
832

833
834
835
836
837
838
839
840







-
+










-
+








-
+













-
-
-
+
+
+








-
+













-
-
+
+

-
+


-
+







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

static Tcl_HashEntry *
AllocStringEntry(
    TCL_UNUSED(Tcl_HashTable *),
    void *keyPtr)			/* Key to store in the hash table entry. */
    void *keyPtr)		/* Key to store in the hash table entry. */
{
    const char *string = (const char *) keyPtr;
    Tcl_HashEntry *hPtr;
    size_t size, allocsize;

    allocsize = size = strlen(string) + 1;
    if (size < sizeof(hPtr->key)) {
	allocsize = sizeof(hPtr->key);
    }
    hPtr = (Tcl_HashEntry *)Tcl_Alloc(offsetof(Tcl_HashEntry, key) + allocsize);
    memset(hPtr, 0, sizeof(Tcl_HashEntry) + allocsize - sizeof(hPtr->key));
    memset(hPtr, 0, offsetof(Tcl_HashEntry, key) + allocsize);
    memcpy(hPtr->key.string, string, size);
    Tcl_SetHashValue(hPtr, NULL);
    return hPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * CompareStringKeys --
 * TclCompareStringKeys --
 *
 *	Compares two string keys.
 *
 * Results:
 *	The return value is 0 if they are different and 1 if they are the
 *	same.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
CompareStringKeys(
    void *keyPtr,			/* New key to compare. */
int
TclCompareStringKeys(
    void *keyPtr,		/* New key to compare. */
    Tcl_HashEntry *hPtr)	/* Existing key to compare. */
{
    return !strcmp((char *)keyPtr, hPtr->key.string);
}

/*
 *----------------------------------------------------------------------
 *
 * HashStringKey --
 * TclHashStringKey --
 *
 *	Compute a one-word summary of a text string, which can be used to
 *	generate a hash index.
 *
 * Results:
 *	The return value is a one-word summary of the information in string.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static TCL_HASH_TYPE
HashStringKey(
size_t
TclHashStringKey(
    TCL_UNUSED(Tcl_HashTable *),
    void *keyPtr)			/* Key from which to compute hash value. */
    void *keyPtr)		/* Key from which to compute hash value. */
{
    const char *string = (const char *)keyPtr;
    TCL_HASH_TYPE result;
    size_t result;
    char c;

    /*
     * I tried a zillion different hash functions and asked many other people
     * for advice. Many people had their own favorite functions, all
     * different, but no-one had much idea why they were good ones. I chose
     * the one below (multiply by 9 and add new character) because of the

Changes to generic/tclHistory.c.

1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17








-
-
+
+







/*
 * tclHistory.c --
 *
 *	This module and the Tcl library file history.tcl together implement
 *	Tcl command history. Tcl_RecordAndEval(Obj) can be called to record
 *	commands ("events") before they are executed. Commands defined in
 *	history.tcl may be used to perform history substitutions.
 *
 * Copyright (c) 1990-1993 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright © 1990-1993 The Regents of the University of California.
 * Copyright © 1994-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

199
200
201
202
203
204
205
206

207
208
209
210
211
212
213
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213







-
+







 *	The constant words may be deleted.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteHistoryObjs(
    ClientData clientData,
    void *clientData,
    TCL_UNUSED(Tcl_Interp *))
{
    HistoryObjs *histObjsPtr = (HistoryObjs *)clientData;

    TclDecrRefCount(histObjsPtr->historyObj);
    TclDecrRefCount(histObjsPtr->addObj);
    Tcl_Free(histObjsPtr);

Changes to generic/tclIO.c.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * tclIO.c --
 *
 *	This file provides the generic portions (those that are the same on
 *	all platforms and for all channel types) of Tcl's IO facilities.
 *
 * Copyright (c) 1998-2000 Ajuba Solutions
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1998-2000 Ajuba Solutions
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Contributions from Don Porter, NIST, 2014. (not subject to US copyright)
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38







-
+







 */

typedef struct ChannelHandler {
    Channel *chanPtr;		/* The channel structure for this channel. */
    int mask;			/* Mask of desired events. */
    Tcl_ChannelProc *proc;	/* Procedure to call in the type of
				 * Tcl_CreateChannelHandler. */
    ClientData clientData;	/* Argument to pass to procedure. */
    void *clientData;		/* Argument to pass to procedure. */
    struct ChannelHandler *nextPtr;
				/* Next one in list of registered handlers. */
} ChannelHandler;

/*
 * This structure keeps track of the current ChannelHandler being invoked in
 * the current invocation of Tcl_NotifyChannel. There is a potential
46
47
48
49
50
51
52
53
54



55
56
57


58
59
60
61
62
63
64
46
47
48
49
50
51
52


53
54
55
56


57
58
59
60
61
62
63
64
65







-
-
+
+
+

-
-
+
+







 * nested invocations of Tcl_NotifyChannel and compare the handler being
 * deleted against the NEXT handler to be invoked in that invocation; when it
 * finds such a situation, Tcl_DeleteChannelHandler updates the nextHandlerPtr
 * field of the structure to the next handler.
 */

typedef struct NextChannelHandler {
    ChannelHandler *nextHandlerPtr;	/* The next handler to be invoked in
					 * this invocation. */
    ChannelHandler *nextHandlerPtr;
				/* The next handler to be invoked in
				 * this invocation. */
    struct NextChannelHandler *nestedHandlerPtr;
					/* Next nested invocation of
					 * Tcl_NotifyChannel. */
				/* Next nested invocation of
				 * Tcl_NotifyChannel. */
} NextChannelHandler;

/*
 * The following structure is used by Tcl_GetsObj() to encapsulates the
 * state for a "gets" operation.
 */

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
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







+






-
-
-
+
+
+




















-

-

-

+
+
+










-
-
-
-
+
+
+
+
+






-
+




-
+















+
+
+






-
+

-
+


-
+







-
+

-
-
+
+






-
+














+



-
-
+
+



-
+












-
+



-
+







 * copy.  Note that the data buffer for the copy will be appended to this
 * structure.
 */

typedef struct CopyState {
    struct Channel *readPtr;	/* Pointer to input channel. */
    struct Channel *writePtr;	/* Pointer to output channel. */
    int refCount;		/* Reference counter. */
    int readFlags;		/* Original read channel flags. */
    int writeFlags;		/* Original write channel flags. */
    Tcl_WideInt toRead;		/* Number of bytes to copy, or -1. */
    Tcl_WideInt total;		/* Total bytes transferred (written). */
    Tcl_Interp *interp;		/* Interp that started the copy. */
    Tcl_Obj *cmdPtr;		/* Command to be invoked at completion. */
    int bufSize;		/* Size of appended buffer. */
    char buffer[1];		/* Copy buffer, this must be the last
                                 * field. */
    Tcl_Size bufSize;		/* Size of appended buffer. */
    char buffer[TCLFLEXARRAY];	/* Copy buffer, this must be the last
				 * field. */
} CopyState;

/*
 * All static variables used in this file are collected into a single instance
 * of the following structure. For multi-threaded implementations, there is
 * one instance of this structure for each thread.
 *
 * Notice that different structures with the same name appear in other files.
 * The structure defined below is used in this file only.
 */

typedef struct {
    NextChannelHandler *nestedHandlerPtr;
				/* This variable holds the list of nested
				 * Tcl_NotifyChannel invocations. */
    ChannelState *firstCSPtr;	/* List of all channels currently open,
				 * indexed by ChannelState, as only one
				 * ChannelState exists per set of stacked
				 * channels. */
    Tcl_Channel stdinChannel;	/* Static variable for the stdin channel. */
    int stdinInitialized;
    Tcl_Channel stdoutChannel;	/* Static variable for the stdout channel. */
    int stdoutInitialized;
    Tcl_Channel stderrChannel;	/* Static variable for the stderr channel. */
    int stderrInitialized;
    Tcl_Encoding binaryEncoding;
    int stdinInitialized;
    int stdoutInitialized;
    int stderrInitialized;
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;

/*
 * Structure to record a close callback. One such record exists for
 * each close callback registered for a channel.
 */

typedef struct CloseCallback {
    Tcl_CloseProc *proc;		/* The procedure to call. */
    ClientData clientData;		/* Arbitrary one-word data to pass
					 * to the callback. */
    struct CloseCallback *nextPtr;	/* For chaining close callbacks. */
    Tcl_CloseProc *proc;	/* The procedure to call. */
    void *clientData;		/* Arbitrary one-word data to pass
				 * to the callback. */
    struct CloseCallback *nextPtr;
				/* For chaining close callbacks. */
} CloseCallback;

/*
 * Static functions in this file:
 */

static ChannelBuffer *	AllocChannelBuffer(int length);
static ChannelBuffer *	AllocChannelBuffer(Tcl_Size length);
static void		PreserveChannelBuffer(ChannelBuffer *bufPtr);
static void		ReleaseChannelBuffer(ChannelBuffer *bufPtr);
static int		IsShared(ChannelBuffer *bufPtr);
static void		ChannelFree(Channel *chanPtr);
static void		ChannelTimerProc(ClientData clientData);
static void		ChannelTimerProc(void *clientData);
static int		ChanRead(Channel *chanPtr, char *dst, int dstSize);
static int		CheckChannelErrors(ChannelState *statePtr,
			    int direction);
static int		CheckForDeadChannel(Tcl_Interp *interp,
			    ChannelState *statePtr);
static void		CheckForStdChannelsBeingClosed(Tcl_Channel chan);
static void		CleanupChannelHandlers(Tcl_Interp *interp,
			    Channel *chanPtr);
static int		CloseChannel(Tcl_Interp *interp, Channel *chanPtr,
			    int errorCode);
static int		CloseChannelPart(Tcl_Interp *interp, Channel *chanPtr,
			    int errorCode, int flags);
static int		CloseWrite(Tcl_Interp *interp, Channel *chanPtr);
static void		CommonGetsCleanup(Channel *chanPtr);
static int		CopyData(CopyState *csPtr, int mask);
static void		DeleteTimerHandler(ChannelState *statePtr);
static int		Lossless(ChannelState *inStatePtr,
			    ChannelState *outStatePtr, long long toRead);
static int		MoveBytes(CopyState *csPtr);

static void		MBCallback(CopyState *csPtr, Tcl_Obj *errObj);
static void		MBError(CopyState *csPtr, int mask, int errorCode);
static int		MBRead(CopyState *csPtr);
static int		MBWrite(CopyState *csPtr);
static void		MBEvent(ClientData clientData, int mask);
static void		MBEvent(void *clientData, int mask);

static void		CopyEventProc(ClientData clientData, int mask);
static void		CopyEventProc(void *clientData, int mask);
static void		CreateScriptRecord(Tcl_Interp *interp,
			    Channel *chanPtr, int mask, Tcl_Obj *scriptPtr);
static void		DeleteChannelTable(ClientData clientData,
static void		DeleteChannelTable(void *clientData,
			    Tcl_Interp *interp);
static void		DeleteScriptRecord(Tcl_Interp *interp,
			    Channel *chanPtr, int mask);
static int		DetachChannel(Tcl_Interp *interp, Tcl_Channel chan);
static void		DiscardInputQueued(ChannelState *statePtr,
			    int discardSavedBuffers);
static void		DiscardOutputQueued(ChannelState *chanPtr);
static int		DoRead(Channel *chanPtr, char *dst, size_t bytesToRead,
static Tcl_Size		DoRead(Channel *chanPtr, char *dst, Tcl_Size bytesToRead,
			    int allowShortReads);
static int		DoReadChars(Channel *chan, Tcl_Obj *objPtr, size_t toRead,
			    int appendFlag);
static Tcl_Size		DoReadChars(Channel *chan, Tcl_Obj *objPtr, Tcl_Size toRead,
			    int allowShortReads, int appendFlag);
static int		FilterInputBytes(Channel *chanPtr,
			    GetsState *statePtr);
static int		FlushChannel(Tcl_Interp *interp, Channel *chanPtr,
			    int calledFromAsyncFlush);
static int		TclGetsObjBinary(Tcl_Channel chan, Tcl_Obj *objPtr);
static Tcl_Encoding	GetBinaryEncoding(void);
static Tcl_ExitProc	FreeBinaryEncoding;
static void		FreeBinaryEncoding(void);
static Tcl_HashTable *	GetChannelTable(Tcl_Interp *interp);
static int		GetInput(Channel *chanPtr);
static void		PeekAhead(Channel *chanPtr, char **dstEndPtr,
			    GetsState *gsPtr);
static int		ReadBytes(ChannelState *statePtr, Tcl_Obj *objPtr,
			    int charsLeft);
static int		ReadChars(ChannelState *statePtr, Tcl_Obj *objPtr,
			    int charsLeft, int *factorPtr);
static void		RecycleBuffer(ChannelState *statePtr,
			    ChannelBuffer *bufPtr, int mustDiscard);
static int		StackSetBlockMode(Channel *chanPtr, int mode);
static int		SetBlockMode(Tcl_Interp *interp, Channel *chanPtr,
			    int mode);
static void		StopCopy(CopyState *csPtr);
static void		CopyDecrRefCount(CopyState *csPtr);
static void		TranslateInputEOL(ChannelState *statePtr, char *dst,
			    const char *src, int *dstLenPtr, int *srcLenPtr);
static void		UpdateInterest(Channel *chanPtr);
static int		Write(Channel *chanPtr, const char *src,
			    int srcLen, Tcl_Encoding encoding);
static Tcl_Size		Write(Channel *chanPtr, const char *src,
			    Tcl_Size srcLen, Tcl_Encoding encoding);
static Tcl_Obj *	FixLevelCode(Tcl_Obj *msg);
static void		SpliceChannel(Tcl_Channel chan);
static void		CutChannel(Tcl_Channel chan);
static int              WillRead(Channel *chanPtr);
static int	      WillRead(Channel *chanPtr);

#define WriteChars(chanPtr, src, srcLen) \
			Write(chanPtr, src, srcLen, chanPtr->state->encoding)
#define WriteBytes(chanPtr, src, srcLen) \
			Write(chanPtr, src, srcLen, tclIdentityEncoding)

/*
 * Simplifying helper macros. All may use their argument(s) multiple times.
 * The ANSI C "prototypes" for the macros are listed below, together with a
 * short description of what the macro does.
 *
 * --------------------------------------------------------------------------
 * size_t BytesLeft(ChannelBuffer *bufPtr)
 * Tcl_Size BytesLeft(ChannelBuffer *bufPtr)
 *
 *	Returns the number of bytes of data remaining in the buffer.
 *
 * int SpaceLeft(ChannelBuffer *bufPtr)
 * Tcl_Size SpaceLeft(ChannelBuffer *bufPtr)
 *
 *	Returns the number of bytes of space remaining at the end of the
 *	buffer.
 *
 * int IsBufferReady(ChannelBuffer *bufPtr)
 *
 *	Returns whether a buffer has bytes available within it.
271
272
273
274
275
276
277
278

279
280

281
282
283
284
285
286
287
278
279
280
281
282
283
284

285
286

287
288
289
290
291
292
293
294







-
+

-
+







 * char *RemovePoint(ChannelBuffer *bufPtr)
 *
 *	Returns a pointer to where characters should be removed from the
 *	buffer.
 * --------------------------------------------------------------------------
 */

#define BytesLeft(bufPtr)	((size_t)((bufPtr)->nextAdded - (bufPtr)->nextRemoved))
#define BytesLeft(bufPtr)	((bufPtr)->nextAdded - (bufPtr)->nextRemoved)

#define SpaceLeft(bufPtr)	((size_t)((bufPtr)->bufLength - (bufPtr)->nextAdded))
#define SpaceLeft(bufPtr)	((bufPtr)->bufLength - (bufPtr)->nextAdded)

#define IsBufferReady(bufPtr)	((bufPtr)->nextAdded > (bufPtr)->nextRemoved)

#define IsBufferEmpty(bufPtr)	((bufPtr)->nextAdded == (bufPtr)->nextRemoved)

#define IsBufferFull(bufPtr)	((bufPtr) && (bufPtr)->nextAdded >= (bufPtr)->bufLength)

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
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







-
+




-
-
+
+



-
-
+
+

-
+
+


-
+

-
+



-
+


-
+

-
-
+
+







 * a channel name in the context of an interp.  Saves the lookup
 * result and values needed to check its continued validity.
 */

typedef struct ResolvedChanName {
    ChannelState *statePtr;	/* The saved lookup result */
    Tcl_Interp *interp;		/* The interp in which the lookup was done. */
    size_t epoch;		/* The epoch of the channel when the lookup
    Tcl_Size epoch;		/* The epoch of the channel when the lookup
				 * was done. Use to verify validity. */
    size_t refCount;		/* Share this struct among many Tcl_Obj. */
} ResolvedChanName;

static void		DupChannelIntRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);
static void		FreeChannelIntRep(Tcl_Obj *objPtr);
static void		DupChannelInternalRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);
static void		FreeChannelInternalRep(Tcl_Obj *objPtr);

static const Tcl_ObjType chanObjType = {
    "channel",			/* name for this type */
    FreeChannelIntRep,		/* freeIntRepProc */
    DupChannelIntRep,		/* dupIntRepProc */
    FreeChannelInternalRep,		/* freeIntRepProc */
    DupChannelInternalRep,		/* dupIntRepProc */
    NULL,			/* updateStringProc */
    NULL			/* setFromAnyProc */
    NULL,			/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

#define ChanSetIntRep(objPtr, resPtr)					\
#define ChanSetInternalRep(objPtr, resPtr)					\
    do {								\
	Tcl_ObjIntRep ir;						\
	Tcl_ObjInternalRep ir;						\
	(resPtr)->refCount++;						\
	ir.twoPtrValue.ptr1 = (resPtr);					\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreIntRep((objPtr), &chanObjType, &ir);			\
	Tcl_StoreInternalRep((objPtr), &chanObjType, &ir);			\
    } while (0)

#define ChanGetIntRep(objPtr, resPtr)					\
#define ChanGetInternalRep(objPtr, resPtr)					\
    do {								\
	const Tcl_ObjIntRep *irPtr;					\
	irPtr = TclFetchIntRep((objPtr), &chanObjType);		\
	const Tcl_ObjInternalRep *irPtr;					\
	irPtr = TclFetchInternalRep((objPtr), &chanObjType);		\
	(resPtr) = irPtr ? (ResolvedChanName *)irPtr->twoPtrValue.ptr1 : NULL;		\
    } while (0)

#define BUSY_STATE(st, fl) \
     ((((st)->csPtrR) && ((fl) & TCL_READABLE)) || \
      (((st)->csPtrW) && ((fl) & TCL_WRITABLE)))

388
389
390
391
392
393
394
395
396
397



398
399
400
401
402
403
404
396
397
398
399
400
401
402



403
404
405
406
407
408
409
410
411
412







-
-
-
+
+
+







 * Results:
 *	The return value of the driver inputProc,
 *	  - number of bytes stored at dst, ot
 *	  - -1 on error, with a Posix error code available to the caller by
 *	    calling Tcl_GetErrno().
 *
 * Side effects:
 *	The CHANNEL_BLOCKED and CHANNEL_EOF flags of the channel state are set
 *	as appropriate.  On EOF, the inputEncodingFlags are set to perform
 *	ending operations on decoding.
 *	The CHANNEL_ENCODING_ERROR, CHANNEL_BLOCKED and CHANNEL_EOF flags
 *	of the channel state are set as appropriate.  On EOF, the
 *	inputEncodingFlags are set to perform ending operations on decoding.
 *
 *	TODO - Is this really the right place for that?
 *
 *---------------------------------------------------------------------------
 */
static int
ChanRead(
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
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







-
+




-
+










-
+








    /*
     * Each read op must set the blocked and eof states anew, not let
     * the effect of prior reads leak through.
     */

    if (GotFlag(chanPtr->state, CHANNEL_EOF)) {
        chanPtr->state->inputEncodingFlags |= TCL_ENCODING_START;
	chanPtr->state->inputEncodingFlags |= TCL_ENCODING_START;
    }
    ResetFlag(chanPtr->state, CHANNEL_BLOCKED | CHANNEL_EOF);
    chanPtr->state->inputEncodingFlags &= ~TCL_ENCODING_END;
    if (WillRead(chanPtr) == -1) {
        return -1;
	return -1;
    }

    bytesRead = chanPtr->typePtr->inputProc(chanPtr->instanceData,
	    dst, dstSize, &result);

    /*
     * Stop any flag leakage through stacked channel levels.
     */

    if (GotFlag(chanPtr->state, CHANNEL_EOF)) {
        chanPtr->state->inputEncodingFlags |= TCL_ENCODING_START;
	chanPtr->state->inputEncodingFlags |= TCL_ENCODING_START;
    }
    ResetFlag(chanPtr->state, CHANNEL_BLOCKED | CHANNEL_EOF);
    chanPtr->state->inputEncodingFlags &= ~TCL_ENCODING_END;
    if (bytesRead == -1) {
	if ((result == EWOULDBLOCK) || (result == EAGAIN)) {
	    SetFlag(chanPtr->state, CHANNEL_BLOCKED);
	    result = EAGAIN;
475
476
477
478
479
480
481
482

483
484
485
486
487
488
489
483
484
485
486
487
488
489

490
491
492
493
494
495
496
497







-
+







    /*
     * Note that we prefer the wideSeekProc if that field is available in the
     * type and non-NULL.
     */

    if (Tcl_ChannelWideSeekProc(chanPtr->typePtr) == NULL) {
	*errnoPtr = EINVAL;
	return -1;
	return TCL_INDEX_NONE;
    }

	return Tcl_ChannelWideSeekProc(chanPtr->typePtr)(chanPtr->instanceData,
		offset, mode, errnoPtr);
}

static inline void
574
575
576
577
578
579
580
581
582


583
584
585
586
587
588





589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610



611
612
613


614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630



631
632
633
634
635
636
637





638
639
640
641



642
643
644
645
646
647
648
649
650
651
652
653
654

655
656
657
658
659
660
661
582
583
584
585
586
587
588


589
590
591





592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615



616
617
618
619


620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635



636
637
638
639
640





641
642
643
644
645
646



647
648
649
650
651
652
653
654
655
656
657
658
659
660
661

662
663
664
665
666
667
668
669







-
-
+
+

-
-
-
-
-
+
+
+
+
+



















-
-
-
+
+
+

-
-
+
+














-
-
-
+
+
+


-
-
-
-
-
+
+
+
+
+

-
-
-
+
+
+












-
+







    int doflushnb;

    /*
     * Fetch the pre-TIP#398 compatibility flag.
     */

    {
        const char *s;
        Tcl_DString ds;
	const char *s;
	Tcl_DString ds;

        s = TclGetEnv("TCL_FLUSH_NONBLOCKING_ON_EXIT", &ds);
        doflushnb = ((s != NULL) && strcmp(s, "0"));
        if (s != NULL) {
            Tcl_DStringFree(&ds);
        }
	s = TclGetEnv("TCL_FLUSH_NONBLOCKING_ON_EXIT", &ds);
	doflushnb = ((s != NULL) && strcmp(s, "0"));
	if (s != NULL) {
	    Tcl_DStringFree(&ds);
	}
    }

    /*
     * Walk all channel state structures known to this thread and close
     * corresponding channels.
     */

    while (active) {
	/*
	 * Iterate through the open channel list, and find the first channel
	 * that isn't dead. We start from the head of the list each time,
	 * because the close action on one channel can close others.
	 */

	active = 0;
	for (statePtr = tsdPtr->firstCSPtr;
		statePtr != NULL;
		statePtr = statePtr->nextCSPtr) {
	    chanPtr = statePtr->topChanPtr;
            if (GotFlag(statePtr, CHANNEL_DEAD)) {
                continue;
            }
	    if (GotFlag(statePtr, CHANNEL_DEAD)) {
		continue;
	    }
	    if (!GotFlag(statePtr, CHANNEL_INCLOSE | CHANNEL_CLOSED )
                || GotFlag(statePtr, BG_FLUSH_SCHEDULED)) {
                ResetFlag(statePtr, BG_FLUSH_SCHEDULED);
		    || GotFlag(statePtr, BG_FLUSH_SCHEDULED)) {
		ResetFlag(statePtr, BG_FLUSH_SCHEDULED);
		active = 1;
		break;
	    }
	}

	/*
	 * We've found a live (or bg-closing) channel. Close it.
	 */

	if (active) {
	    TclChannelPreserve((Tcl_Channel)chanPtr);

	    /*
	     * TIP #398: by default, we no longer set the channel back into
             * blocking mode.  To restore the old blocking behavior, the
             * environment variable TCL_FLUSH_NONBLOCKING_ON_EXIT must be set
             * and not be "0".
	     * blocking mode.  To restore the old blocking behavior, the
	     * environment variable TCL_FLUSH_NONBLOCKING_ON_EXIT must be set
	     * and not be "0".
	     */

            if (doflushnb) {
                /*
                 * Set the channel back into blocking mode to ensure that we
                 * wait for all data to flush out.
                 */
	    if (doflushnb) {
		/*
		 * Set the channel back into blocking mode to ensure that we
		 * wait for all data to flush out.
		 */

                (void) Tcl_SetChannelOption(NULL, (Tcl_Channel) chanPtr,
                                            "-blocking", "on");
            }
		(void) Tcl_SetChannelOption(NULL, (Tcl_Channel) chanPtr,
			"-blocking", "on");
	    }

	    if ((chanPtr == (Channel *) tsdPtr->stdinChannel) ||
		    (chanPtr == (Channel *) tsdPtr->stdoutChannel) ||
		    (chanPtr == (Channel *) tsdPtr->stderrChannel)) {
		/*
		 * Decrement the refcount which was earlier artificially
		 * bumped up to keep the channel from being closed.
		 */

		statePtr->refCount--;
	    }

	    if (statePtr->refCount + 1 <= 1) {
	    if (statePtr->refCount <= 0) {
		/*
		 * Close it only if the refcount indicates that the channel is
		 * not referenced from any interpreter. If it is, that
		 * interpreter will close the channel when it gets destroyed.
		 */

		(void) Tcl_CloseEx(NULL, (Tcl_Channel) chanPtr, 0);
683
684
685
686
687
688
689

690
691
692
693
694
695
696
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705







+







		chanPtr->instanceData = NULL;
		SetFlag(statePtr, CHANNEL_DEAD);
	    }
	    TclChannelRelease((Tcl_Channel)chanPtr);
	}
    }

    FreeBinaryEncoding();
    TclpFinalizeSockets();
    TclpFinalizePipes();
}

/*
 *----------------------------------------------------------------------
 *
724
725
726
727
728
729
730




731
732
733
734
735
736
737
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750







+
+
+
+







    case TCL_STDOUT:
	tsdPtr->stdoutInitialized = init;
	tsdPtr->stdoutChannel = channel;
	break;
    case TCL_STDERR:
	tsdPtr->stderrInitialized = init;
	tsdPtr->stderrChannel = channel;
	if (channel) {
	    ENCODING_PROFILE_SET(((Channel *)channel)->state->inputEncodingFlags, TCL_ENCODING_PROFILE_REPLACE);
	    ENCODING_PROFILE_SET(((Channel *)channel)->state->outputEncodingFlags, TCL_ENCODING_PROFILE_REPLACE);
	}
	break;
    }
}

/*
 *----------------------------------------------------------------------
 *
794
795
796
797
798
799
800


801
802
803
804
805
806
807
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822







+
+







	channel = tsdPtr->stdoutChannel;
	break;
    case TCL_STDERR:
	if (!tsdPtr->stderrInitialized) {
	    tsdPtr->stderrInitialized = -1;
	    tsdPtr->stderrChannel = TclpGetDefaultStdChannel(TCL_STDERR);
	    if (tsdPtr->stderrChannel != NULL) {
		ENCODING_PROFILE_SET(((Channel *)tsdPtr->stderrChannel)->state->inputEncodingFlags, TCL_ENCODING_PROFILE_REPLACE);
		ENCODING_PROFILE_SET(((Channel *)tsdPtr->stderrChannel)->state->outputEncodingFlags, TCL_ENCODING_PROFILE_REPLACE);
		tsdPtr->stderrInitialized = 1;
		Tcl_RegisterChannel(NULL, tsdPtr->stderrChannel);
	    }
	}
	channel = tsdPtr->stderrChannel;
	break;
    }
828
829
830
831
832
833
834
835

836
837
838
839
840
841
842
843
844
845
846
847
848
849

850
851
852
853
854
855
856
857







-
+








void
Tcl_CreateCloseHandler(
    Tcl_Channel chan,		/* The channel for which to create the close
				 * callback. */
    Tcl_CloseProc *proc,	/* The callback routine to call when the
				 * channel will be closed. */
    ClientData clientData)	/* Arbitrary data to pass to the close
    void *clientData)	/* Arbitrary data to pass to the close
				 * callback. */
{
    ChannelState *statePtr = ((Channel *) chan)->state;
    CloseCallback *cbPtr;

    cbPtr = (CloseCallback *)Tcl_Alloc(sizeof(CloseCallback));
    cbPtr->proc = proc;
866
867
868
869
870
871
872
873

874
875
876
877
878
879
880
881
882
883
884
885
886
887

888
889
890
891
892
893
894
895







-
+








void
Tcl_DeleteCloseHandler(
    Tcl_Channel chan,		/* The channel for which to cancel the close
				 * callback. */
    Tcl_CloseProc *proc,	/* The procedure for the callback to
				 * remove. */
    ClientData clientData)	/* The callback data for the callback to
    void *clientData)	/* The callback data for the callback to
				 * remove. */
{
    ChannelState *statePtr = ((Channel *) chan)->state;
    CloseCallback *cbPtr, *cbPrevPtr;

    for (cbPtr = statePtr->closeCbPtr, cbPrevPtr = NULL;
	    cbPtr != NULL; cbPtr = cbPtr->nextPtr) {
957
958
959
960
961
962
963
964

965
966
967
968
969
970
971
972

973
974
975
976
977
978
979
972
973
974
975
976
977
978

979
980
981
982
983
984
985
986

987
988
989
990
991
992
993
994







-
+







-
+







 *	an interpreter is deleted, via the AssocData cleanup mechanism.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Deletes the hash table of channels. May close channels. May flush
 *	output on closed channels. Removes any channeEvent handlers that were
 *	output on closed channels. Removes any channelEvent handlers that were
 *	registered in this interpreter.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteChannelTable(
    ClientData clientData,	/* The per-interpreter data structure. */
    void *clientData,	/* The per-interpreter data structure. */
    Tcl_Interp *interp)		/* The interpreter being deleted. */
{
    Tcl_HashTable *hTblPtr;	/* The hash table. */
    Tcl_HashSearch hSearch;	/* Search variable. */
    Tcl_HashEntry *hPtr;	/* Search variable. */
    Channel *chanPtr;		/* Channel being deleted. */
    ChannelState *statePtr;	/* State of Channel being deleted. */
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







-
+







    hTblPtr = (Tcl_HashTable *)clientData;
    for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch); hPtr != NULL;
	    hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch)) {
	chanPtr = (Channel *)Tcl_GetHashValue(hPtr);
	statePtr = chanPtr->state;

	/*
	 * Remove any fileevents registered in this interpreter.
	 * Remove any file events registered in this interpreter.
	 */

	for (sPtr = statePtr->scriptRecordPtr, prevPtr = NULL;
		sPtr != NULL; sPtr = nextPtr) {
	    nextPtr = sPtr->nextPtr;
	    if (sPtr->interp == interp) {
		if (prevPtr == NULL) {
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
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







-
+







-
+







-
+







{
    ChannelState *statePtr = ((Channel *) chan)->state;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (tsdPtr->stdinInitialized == 1
	    && tsdPtr->stdinChannel != NULL
	    && statePtr == ((Channel *)tsdPtr->stdinChannel)->state) {
	if (statePtr->refCount + 1 < 3) {
	if (statePtr->refCount < 2) {
	    statePtr->refCount = 0;
	    tsdPtr->stdinChannel = NULL;
	    return;
	}
    } else if (tsdPtr->stdoutInitialized == 1
	    && tsdPtr->stdoutChannel != NULL
	    && statePtr == ((Channel *)tsdPtr->stdoutChannel)->state) {
	if (statePtr->refCount + 1 < 3) {
	if (statePtr->refCount < 2) {
	    statePtr->refCount = 0;
	    tsdPtr->stdoutChannel = NULL;
	    return;
	}
    } else if (tsdPtr->stderrInitialized == 1
	    && tsdPtr->stderrChannel != NULL
	    && statePtr == ((Channel *)tsdPtr->stderrChannel)->state) {
	if (statePtr->refCount + 1 < 3) {
	if (statePtr->refCount < 2) {
	    statePtr->refCount = 0;
	    tsdPtr->stderrChannel = NULL;
	    return;
	}
    }
}

1217
1218
1219
1220
1221
1222
1223
1224
1225


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


1239
1240
1241
1242
1243
1244
1245
1246
1247







-
-
+
+







    ChannelState *statePtr;	/* State of the real channel. */

    statePtr = ((Channel *) chan)->state->bottomChanPtr->state;

    if (GotFlag(statePtr, CHANNEL_INCLOSE)) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
                    "illegal recursive call to close through close-handler"
                    " of channel", -1));
		    "illegal recursive call to close through close-handler"
		    " of channel", -1));
	}
	return TCL_ERROR;
    }

    if (DetachChannel(interp, chan) != TCL_OK) {
	return TCL_OK;
    }
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







-
+








    CheckForStdChannelsBeingClosed(chan);

    /*
     * If the refCount reached zero, close the actual channel.
     */

    if (statePtr->refCount + 1 <= 1) {
    if (statePtr->refCount <= 0) {
	Tcl_Preserve(statePtr);
	if (!GotFlag(statePtr, BG_FLUSH_SCHEDULED)) {
	    /*
	     * We don't want to re-enter Tcl_CloseEx().
	     */

	    if (!GotFlag(statePtr, CHANNEL_CLOSED)) {
1409
1410
1411
1412
1413
1414
1415
1416

1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430

1431
1432
1433
1434
1435
1436
1437
1438







-
+








Tcl_Channel
Tcl_GetChannel(
    Tcl_Interp *interp,		/* Interpreter in which to find or create the
				 * channel. */
    const char *chanName,	/* The name of the channel. */
    int *modePtr)		/* Where to store the mode in which the
				 * channel was opened? Will contain an ORed
				 * channel was opened? Will contain an OR'ed
				 * combination of TCL_READABLE and
				 * TCL_WRITABLE, if non-NULL. */
{
    Channel *chanPtr;		/* The actual channel. */
    Tcl_HashTable *hTblPtr;	/* Hash table of channels. */
    Tcl_HashEntry *hPtr;	/* Search variable. */
    const char *name;		/* Translated name. */
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
1460
1461
1462
1463
1464
1465
1466


1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480

1481
1482
1483
1484
1485
1486
1487
1488







-
-
+
+












-
+







	}
    }

    hTblPtr = GetChannelTable(interp);
    hPtr = Tcl_FindHashEntry(hTblPtr, name);
    if (hPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "can not find channel named \"%s\"", chanName));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CHANNEL", chanName, NULL);
		"can not find channel named \"%s\"", chanName));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CHANNEL", chanName, (char *)NULL);
	return NULL;
    }

    /*
     * Always return bottom-most channel in the stack. This one lives the
     * longest - other channels may go away unnoticed. The other APIs
     * compensate where necessary to retrieve the topmost channel again.
     */

    chanPtr = (Channel *)Tcl_GetHashValue(hPtr);
    chanPtr = chanPtr->state->bottomChanPtr;
    if (modePtr != NULL) {
	*modePtr = chanPtr->state->flags & (TCL_READABLE|TCL_WRITABLE);
	*modePtr = GotFlag(chanPtr->state, TCL_READABLE|TCL_WRITABLE);
    }

    return (Tcl_Channel) chanPtr;
}

/*
 *---------------------------------------------------------------------------
1492
1493
1494
1495
1496
1497
1498
1499

1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512

1513
1514
1515
1516


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

1535
1536
1537
1538
1539
1540
1541

1542
1543
1544

1545
1546
1547
1548

1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560

1561
1562
1563
1564
1565
1566
1567
1507
1508
1509
1510
1511
1512
1513

1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526

1527
1528
1529


1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548

1549
1550
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







-
+












-
+


-
-
+
+

















-
+





-
-
+
-
-

+



-
+











-
+







int
TclGetChannelFromObj(
    Tcl_Interp *interp,		/* Interpreter in which to find or create the
				 * channel. */
    Tcl_Obj *objPtr,
    Tcl_Channel *channelPtr,
    int *modePtr,		/* Where to store the mode in which the
				 * channel was opened? Will contain an ORed
				 * channel was opened? Will contain an OR'ed
				 * combination of TCL_READABLE and
				 * TCL_WRITABLE, if non-NULL. */
    TCL_UNUSED(int) /*flags*/)
{
    ChannelState *statePtr;
    ResolvedChanName *resPtr = NULL;
    Tcl_Channel chan;

    if (interp == NULL) {
	return TCL_ERROR;
    }

    ChanGetIntRep(objPtr, resPtr);
    ChanGetInternalRep(objPtr, resPtr);
    if (resPtr) {
	/*
 	 * Confirm validity of saved lookup results.
 	 */
	 * Confirm validity of saved lookup results.
	 */

	statePtr = resPtr->statePtr;
	if ((resPtr->interp == interp)		/* Same interp context */
			/* No epoch change in channel since lookup */
		&& (resPtr->epoch == statePtr->epoch)) {
	    /*
	     * Have a valid saved lookup. Jump to end to return it.
	     */

	    goto valid;
	}
    }

    chan = Tcl_GetChannel(interp, TclGetString(objPtr), NULL);

    if (chan == NULL) {
	if (resPtr) {
	    Tcl_StoreIntRep(objPtr, &chanObjType, NULL);
	    Tcl_StoreInternalRep(objPtr, &chanObjType, NULL);
	}
	return TCL_ERROR;
    }

    if (resPtr && resPtr->refCount == 1) {
	/*
         * Re-use the ResolvedCmdName struct.
	/* Re-use the ResolvedCmdName struct */
         */

	Tcl_Release(resPtr->statePtr);

    } else {
	resPtr = (ResolvedChanName *) Tcl_Alloc(sizeof(ResolvedChanName));
	resPtr->refCount = 0;
	ChanSetIntRep(objPtr, resPtr);		/* Overwrites, if needed */
	ChanSetInternalRep(objPtr, resPtr);		/* Overwrites, if needed */
    }
    statePtr = ((Channel *)chan)->state;
    resPtr->statePtr = statePtr;
    Tcl_Preserve(statePtr);
    resPtr->interp = interp;
    resPtr->epoch = statePtr->epoch;

  valid:
    *channelPtr = (Tcl_Channel) statePtr->bottomChanPtr;

    if (modePtr != NULL) {
	*modePtr = statePtr->flags & (TCL_READABLE|TCL_WRITABLE);
	*modePtr = GotFlag(statePtr, TCL_READABLE|TCL_WRITABLE);
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
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
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







-
+










-
-
-
-
-
-
-
+
+
-
-
-
+
-
-







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

Tcl_Channel
Tcl_CreateChannel(
    const Tcl_ChannelType *typePtr, /* The channel type record. */
    const char *chanName,	/* Name of channel to record. */
    ClientData instanceData,	/* Instance specific data. */
    void *instanceData,		/* Instance specific data. */
    int mask)			/* TCL_READABLE & TCL_WRITABLE to indicate if
				 * the channel is readable, writable. */
{
    Channel *chanPtr;		/* The channel structure newly created. */
    ChannelState *statePtr;	/* The stack-level independent state info for
				 * the channel. */
    const char *name;
    char *tmp;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    /*
     * With the change of the Tcl_ChannelType structure to use a version in
     * 8.3.2+, we have to make sure that our assumption that the structure
     * remains a binary compatible size is true.
     *
     * If this assertion fails on some system, then it can be removed only if
     * the user recompiles code with older channel drivers in the new system
    if (typePtr->typeName == NULL) {
	Tcl_Panic("channel does not have a type name");
     * as well.
     */

    }
    assert(sizeof(Tcl_ChannelTypeVersion) == sizeof(Tcl_DriverBlockModeProc *));
    assert(typePtr->typeName != NULL);
    if (Tcl_ChannelVersion(typePtr) != TCL_CHANNEL_VERSION_5) {
	Tcl_Panic("channel type %s must be version TCL_CHANNEL_VERSION_5", typePtr->typeName);
    }
    if (typePtr->close2Proc == NULL) {
	Tcl_Panic("channel type %s must define close2Proc", typePtr->typeName);
    }
    if ((TCL_READABLE & mask) && (NULL == typePtr->inputProc)) {
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
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







-
-
-
+
+
+









+



-
-
-
-
-
-


-

-
-
+
-
















-















+







     * information for the channel.
     */

    if (chanName != NULL) {
	unsigned len = strlen(chanName) + 1;

	/*
         * Make sure we allocate at least 7 bytes, so it fits for "stdout"
         * later.
         */
	 * Make sure we allocate at least 7 bytes, so it fits for "stdout"
	 * later.
	 */

	tmp = (char *)Tcl_Alloc((len < 7) ? 7 : len);
	strcpy(tmp, chanName);
    } else {
	tmp = (char *)Tcl_Alloc(7);
	tmp[0] = '\0';
    }
    statePtr->channelName = tmp;
    statePtr->flags = mask;
    statePtr->maxPerms = mask; /* Save max privileges for close callback */

    /*
     * Set the channel to system default encoding.
     *
     * Note the strange bit of protection taking place here. If the system
     * encoding name is reported back as "binary", something weird is
     * happening. Tcl provides no "binary" encoding, so someone else has
     * provided one. We ignore it so as not to interfere with the "magic"
     * interpretation that Tcl_Channels give to the "-encoding binary" option.
     */

    statePtr->encoding = NULL;
    name = Tcl_GetEncodingName(NULL);
    if (strcmp(name, "binary") != 0) {
	statePtr->encoding = Tcl_GetEncoding(NULL, name);
    statePtr->encoding = Tcl_GetEncoding(NULL, name);
    }
    statePtr->inputEncodingState  = NULL;
    statePtr->inputEncodingFlags  = TCL_ENCODING_START;
    statePtr->outputEncodingState = NULL;
    statePtr->outputEncodingFlags = TCL_ENCODING_START;

    /*
     * Set the channel up initially in AUTO input translation mode to accept
     * "\n", "\r" and "\r\n". Output translation mode is set to a platform
     * specific default value. The eofChar is set to 0 for both input and
     * output, so that Tcl does not look for an in-file EOF indicator (e.g.,
     * ^Z) and does not append an EOF indicator to files.
     */

    statePtr->inputTranslation	= TCL_TRANSLATE_AUTO;
    statePtr->outputTranslation	= TCL_PLATFORM_TRANSLATION;
    statePtr->inEofChar		= 0;
    statePtr->outEofChar	= 0;

    statePtr->unreportedError	= 0;
    statePtr->refCount		= 0;
    statePtr->closeCbPtr	= NULL;
    statePtr->curOutPtr		= NULL;
    statePtr->outQueueHead	= NULL;
    statePtr->outQueueTail	= NULL;
    statePtr->saveInBufPtr	= NULL;
    statePtr->inQueueHead	= NULL;
    statePtr->inQueueTail	= NULL;
    statePtr->chPtr		= NULL;
    statePtr->interestMask	= 0;
    statePtr->scriptRecordPtr	= NULL;
    statePtr->bufSize		= CHANNELBUFFER_DEFAULT_SIZE;
    statePtr->timer		= NULL;
    statePtr->timerChanPtr	= NULL;
    statePtr->csPtrR		= NULL;
    statePtr->csPtrW		= NULL;
    statePtr->outputStage	= NULL;

    /*
     * As we are creating the channel, it is obviously the top for now.
     */
1800
1801
1802
1803
1804
1805
1806
1807

1808
1809
1810
1811
1812
1813
1814
1796
1797
1798
1799
1800
1801
1802

1803
1804
1805
1806
1807
1808
1809
1810







-
+








Tcl_Channel
Tcl_StackChannel(
    Tcl_Interp *interp,		/* The interpreter we are working in */
    const Tcl_ChannelType *typePtr,
				/* The channel type record for the new
				 * channel. */
    ClientData instanceData,	/* Instance specific data for the new
    void *instanceData,		/* Instance specific data for the new
				 * channel. */
    int mask,			/* TCL_READABLE & TCL_WRITABLE to indicate if
				 * the channel is readable, writable. */
    Tcl_Channel prevChan)	/* The channel structure to replace */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    Channel *chanPtr, *prevChanPtr;
1827
1828
1829
1830
1831
1832
1833
1834

1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853

1854
1855
1856
1857
1858
1859
1860
1823
1824
1825
1826
1827
1828
1829

1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848

1849
1850
1851
1852
1853
1854
1855
1856







-
+


















-
+







    while ((statePtr != NULL) && (statePtr->topChanPtr != prevChanPtr)) {
	statePtr = statePtr->nextCSPtr;
    }

    if (statePtr == NULL) {
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "couldn't find state for channel \"%s\"",
		    "couldn't find state for channel \"%s\"",
		    Tcl_GetChannelName(prevChan)));
	}
	return NULL;
    }

    /*
     * Here we check if the given "mask" matches the "flags" of the already
     * existing channel.
     *
     *	  | - | R | W | RW |
     *	--+---+---+---+----+	<=>  0 != (chan->mask & prevChan->mask)
     *	- |   |   |   |    |
     *	R |   | + |   | +  |	The superceding channel is allowed to restrict
     *	W |   |   | + | +  |	the capabilities of the superceded one!
     *	RW|   | + | + | +  |
     *	--+---+---+---+----+
     */

    if ((mask & (statePtr->flags & (TCL_READABLE | TCL_WRITABLE))) == 0) {
    if ((mask & GotFlag(statePtr, TCL_READABLE|TCL_WRITABLE)) == 0) {
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "reading and writing both disallowed for channel \"%s\"",
		    Tcl_GetChannelName(prevChan)));
	}
	return NULL;
    }
1878
1879
1880
1881
1882
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
1874
1875
1876
1877
1878
1879
1880

1881
1882
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







-
+




















-
+







	 * the stacking state of this channel during its operations.
	 */
	if (Tcl_Flush((Tcl_Channel) prevChanPtr) != TCL_OK) {
	    statePtr->csPtrR = csPtrR;
	    statePtr->csPtrW = csPtrW;
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                        "could not flush channel \"%s\"",
			"could not flush channel \"%s\"",
			Tcl_GetChannelName(prevChan)));
	    }
	    return NULL;
	}

	statePtr->csPtrR = csPtrR;
	statePtr->csPtrW = csPtrW;
    }

    /*
     * Discard any input in the buffers. They are not yet read by the user of
     * the channel, so they have to go through the new transformation before
     * reading. As the buffers contain the untransformed form their contents
     * are not only useless but actually distorts our view of the system.
     *
     * To preserve the information without having to read them again and to
     * avoid problems with the location in the channel (seeking might be
     * impossible) we move the buffers from the common state structure into
     * the channel itself. We use the buffers in the channel below the new
     * transformation to hold the data. In the future this allows us to write
     * transformations which pre-read data and push the unused part back when
     * transformations which preread data and push the unused part back when
     * they are going away.
     */

    if (((mask & TCL_READABLE) != 0) && (statePtr->inQueueHead != NULL)) {
	/*
	 * When statePtr->inQueueHead is not NULL, we know
	 * prevChanPtr->inQueueHead must be NULL.
1989
1990
1991
1992
1993
1994
1995
1996

1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015

2016
2017
2018
2019
2020
2021
2022
1985
1986
1987
1988
1989
1990
1991

1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010

2011
2012
2013
2014
2015
2016
2017
2018







-
+


















-
+







    }
}

static void
ChannelFree(
    Channel *chanPtr)
{
    if (!chanPtr->refCount) {
    if (chanPtr->refCount == 0) {
	Tcl_Free(chanPtr);
	return;
    }
    chanPtr->typePtr = NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UnstackChannel --
 *
 *	Unstacks an entry in the hash table for a Tcl_Channel record. This is
 *	the reverse to 'Tcl_StackChannel'.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	If TCL_ERROR is returned, the posix error code will be set with
 *	If TCL_ERROR is returned, the Posix error code will be set with
 *	Tcl_SetErrno. May leave a message in interp result as well.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UnstackChannel(
2031
2032
2033
2034
2035
2036
2037
2038

2039
2040
2041
2042
2043
2044
2045
2027
2028
2029
2030
2031
2032
2033

2034
2035
2036
2037
2038
2039
2040
2041







-
+







     * This operation should occur at the top of a channel stack.
     */

    chanPtr = statePtr->topChanPtr;

    if (chanPtr->downChanPtr != NULL) {
	/*
	 * Instead of manipulating the per-thread / per-interp list/hashtable
	 * Instead of manipulating the per-thread / per-interp list/hash table
	 * of registered channels we wind down the state of the
	 * transformation, and then restore the state of underlying channel
	 * into the old structure.
	 *
	 * TODO: Figure out how to handle the situation where the chan
	 * operations called below by this unstacking operation cause
	 * another unstacking recursively.  In that case the downChanPtr
2073
2074
2075
2076
2077
2078
2079
2080

2081
2082
2083
2084
2085
2086

2087
2088
2089
2090
2091
2092
2093
2069
2070
2071
2072
2073
2074
2075

2076
2077
2078
2079
2080
2081

2082
2083
2084
2085
2086
2087
2088
2089







-
+





-
+







		 * bypass area into the regular interpreter result. Fall back
		 * to the regular message if nothing was found in the
		 * bypasses.
		 */

		if (!TclChanCaughtErrorBypass(interp, chan) && interp) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                            "could not flush channel \"%s\"",
			    "could not flush channel \"%s\"",
			    Tcl_GetChannelName((Tcl_Channel) chanPtr)));
		}
		return TCL_ERROR;
	    }

	    statePtr->csPtrR  = csPtrR;
	    statePtr->csPtrR = csPtrR;
	    statePtr->csPtrW = csPtrW;
	}

	/*
	 * Anything in the input queue and the push-back buffers of the
	 * transformation going away is transformed data, but not yet read. As
	 * unstacking means that the caller does not want to see transformed
2136
2137
2138
2139
2140
2141
2142

2143
2144


2145
2146
2147
2148
2149
2150
2151
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150







+


+
+







	/*
	 * Leave this link intact for closeproc
	 *  chanPtr->downChanPtr = NULL;
	 */

	/*
	 * Close and free the channel driver state.
	 * TIP #220: This is done with maximum privileges (as created).
	 */

	ResetFlag(statePtr, TCL_READABLE|TCL_WRITABLE);
	SetFlag(statePtr, statePtr->maxPerms);
	result = ChanClose(chanPtr, interp);
	ChannelFree(chanPtr);

	UpdateInterest(statePtr->topChanPtr);

	if (result != 0) {
	    Tcl_SetErrno(result);
2161
2162
2163
2164
2165
2166
2167
2168

2169
2170
2171
2172
2173
2174
2175
2160
2161
2162
2163
2164
2165
2166

2167
2168
2169
2170
2171
2172
2173
2174







-
+







	}
    } else {
	/*
	 * This channel does not cover another one. Simply do a close, if
	 * necessary.
	 */

	if (statePtr->refCount + 1 <= 1) {
	if (statePtr->refCount <= 0) {
	    if (Tcl_CloseEx(interp, chan, 0) != TCL_OK) {
		/*
		 * TIP #219, Tcl Channel Reflection API.
		 * "TclChanCaughtErrorBypass" is not required here, it was
		 * done already by "Tcl_Close".
		 */

2256
2257
2258
2259
2260
2261
2262
2263

2264
2265
2266
2267
2268
2269
2270
2255
2256
2257
2258
2259
2260
2261

2262
2263
2264
2265
2266
2267
2268
2269







-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

ClientData
void *
Tcl_GetChannelInstanceData(
    Tcl_Channel chan)		/* Channel for which to return client data. */
{
    Channel *chanPtr = (Channel *) chan;
				/* The actual channel. */

    return chanPtr->instanceData;
2344
2345
2346
2347
2348
2349
2350
2351

2352
2353
2354
2355
2356
2357
2358
2343
2344
2345
2346
2347
2348
2349

2350
2351
2352
2353
2354
2355
2356
2357







-
+







Tcl_GetChannelMode(
    Tcl_Channel chan)		/* The channel for which the mode is being
				 * computed. */
{
    ChannelState *statePtr = ((Channel *) chan)->state;
				/* State of actual channel. */

    return (statePtr->flags & (TCL_READABLE | TCL_WRITABLE));
    return GotFlag(statePtr, TCL_READABLE|TCL_WRITABLE);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetChannelName --
 *
2395
2396
2397
2398
2399
2400
2401
2402

2403
2404
2405

2406
2407
2408
2409
2410
2411
2412



2413
2414
2415
2416
2417
2418
2419
2420
2421
















































2422
2423
2424
2425
2426
2427
2428
2394
2395
2396
2397
2398
2399
2400

2401
2402
2403

2404
2405
2406
2407
2408



2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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







-
+


-
+




-
-
-
+
+
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







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

int
Tcl_GetChannelHandle(
    Tcl_Channel chan,		/* The channel to get file from. */
    int direction,		/* TCL_WRITABLE or TCL_READABLE. */
    ClientData *handlePtr)	/* Where to store handle */
    void **handlePtr)	/* Where to store handle */
{
    Channel *chanPtr;		/* The actual channel. */
    ClientData handle;
    void *handle;
    int result;

    chanPtr = ((Channel *) chan)->state->bottomChanPtr;
    if (!chanPtr->typePtr->getHandleProc) {
        Tcl_SetChannelError(chan, Tcl_ObjPrintf(
                "channel \"%s\" does not support OS handles",
                Tcl_GetChannelName(chan)));
	Tcl_SetChannelError(chan, Tcl_ObjPrintf(
		"channel \"%s\" does not support OS handles",
		Tcl_GetChannelName(chan)));
	return TCL_ERROR;
    }
    result = chanPtr->typePtr->getHandleProc(chanPtr->instanceData, direction,
	    &handle);
    if (handlePtr) {
	*handlePtr = handle;
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_RemoveChannelMode --
 *
 *	Remove either read or write privileges from the channel.
 *
 * Results:
 *	A standard Tcl result code.
 *
 * Side effects:
 *	May change the access mode of the channel.
 *	May leave an error message in the interp.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_RemoveChannelMode(
     Tcl_Interp *interp,	/* The interp for an error message. Allowed to be NULL. */
     Tcl_Channel chan,		/* The channel which is modified. */
     int mode)			/* The access mode to drop from the channel */
{
    const char* emsg;
    ChannelState *statePtr = ((Channel *) chan)->state;
				/* State of actual channel. */

    if ((mode != TCL_READABLE) && (mode != TCL_WRITABLE)) {
	emsg = "Illegal mode value.";
	goto error;
    }
    if (0 == (GotFlag(statePtr, TCL_READABLE|TCL_WRITABLE) & ~mode)) {
	emsg = "Bad mode, would make channel inacessible";
	goto error;
    }

    ResetFlag(statePtr, mode);
    return TCL_OK;

 error:
    if (interp != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"Tcl_RemoveChannelMode error: %s. Channel: \"%s\"",
		emsg, Tcl_GetChannelName((Tcl_Channel) chan)));
    }
    return TCL_ERROR;
}

/*
 *---------------------------------------------------------------------------
 *
 * AllocChannelBuffer --
 *
 *	A channel buffer has BUFFER_PADDING bytes extra at beginning to hold
2442
2443
2444
2445
2446
2447
2448
2449

2450
2451
2452

2453
2454
2455
2456
2457
2458
2459
2489
2490
2491
2492
2493
2494
2495

2496
2497
2498

2499
2500
2501
2502
2503
2504
2505
2506







-
+


-
+







 *	None.
 *
 *---------------------------------------------------------------------------
 */

static ChannelBuffer *
AllocChannelBuffer(
    int length)			/* Desired length of channel buffer. */
    Tcl_Size length)			/* Desired length of channel buffer. */
{
    ChannelBuffer *bufPtr;
    int n;
    Tcl_Size n;

    n = length + CHANNELBUFFER_HEADER_SIZE + BUFFER_PADDING + BUFFER_PADDING;
    bufPtr = (ChannelBuffer *)Tcl_Alloc(n);
    bufPtr->nextAdded	= BUFFER_PADDING;
    bufPtr->nextRemoved	= BUFFER_PADDING;
    bufPtr->bufLength	= length + BUFFER_PADDING;
    bufPtr->nextPtr	= NULL;
2481
2482
2483
2484
2485
2486
2487
2488

2489
2490
2491
2492
2493
2494
2495
2528
2529
2530
2531
2532
2533
2534

2535
2536
2537
2538
2539
2540
2541
2542







-
+







    Tcl_Free(bufPtr);
}

static int
IsShared(
    ChannelBuffer *bufPtr)
{
    return bufPtr->refCount + 1 > 2;
    return bufPtr->refCount > 1;
}

/*
 *----------------------------------------------------------------------
 *
 * RecycleBuffer --
 *
2524
2525
2526
2527
2528
2529
2530
2531
2532


2533
2534
2535

2536
2537
2538
2539
2540
2541
2542
2571
2572
2573
2574
2575
2576
2577


2578
2579
2580
2581

2582
2583
2584
2585
2586
2587
2588
2589







-
-
+
+


-
+








    if (mustDiscard) {
	ReleaseChannelBuffer(bufPtr);
	return;
    }

    /*
     * Only save buffers which have the requested buffersize for the channel.
     * This is to honor dynamic changes of the buffersize made by the user.
     * Only save buffers which have the requested buffer size for the channel.
     * This is to honor dynamic changes of the buffe rsize made by the user.
     */

    if ((bufPtr->bufLength - BUFFER_PADDING) != statePtr->bufSize) {
    if ((bufPtr->bufLength) != statePtr->bufSize + BUFFER_PADDING) {
	ReleaseChannelBuffer(bufPtr);
	return;
    }

    /*
     * Only save buffers for the input queue if the channel is readable.
     */
2638
2639
2640
2641
2642
2643
2644
2645

2646
2647
2648
2649
2650
2651
2652
2685
2686
2687
2688
2689
2690
2691

2692
2693
2694
2695
2696
2697
2698
2699







-
+







    if (!GotFlag(statePtr, CHANNEL_DEAD)) {
	return 0;
    }

    Tcl_SetErrno(EINVAL);
    if (interp) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
                "unable to access channel: invalid channel", -1));
		"unable to access channel: invalid channel", -1));
    }
    return 1;
}

/*
 *----------------------------------------------------------------------
 *
2681
2682
2683
2684
2685
2686
2687

2688
2689
2690
2691

2692
2693
2694
2695
2696
2697
2698
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738

2739
2740
2741
2742
2743
2744
2745
2746







+



-
+







    int written;		/* Amount of output data actually written in
				 * current round. */
    int errorCode = 0;		/* Stores POSIX error codes from channel
				 * driver operations. */
    int wroteSome = 0;		/* Set to one if any data was written to the
				 * driver. */

    int bufExists;
    /*
     * Prevent writing on a dead channel -- a channel that has been closed but
     * not yet deallocated. This can occur if the exit handler for the channel
     * deallocation runs before all channels are deregistered in all
     * deallocation runs before all channels are unregistered in all
     * interpreters.
     */

    if (CheckForDeadChannel(interp, statePtr)) {
	return -1;
    }

2799
2800
2801
2802
2803
2804
2805
2806

2807
2808

2809
2810
2811
2812
2813
2814
2815
2847
2848
2849
2850
2851
2852
2853

2854
2855

2856
2857
2858
2859
2860
2861
2862
2863







-
+

-
+







	    /*
	     * Decide whether to report the error upwards or defer it.
	     */

	    if (calledFromAsyncFlush) {
		/*
		 * TIP #219, Tcl Channel Reflection API.
		 * When defering the error copy a message from the bypass into
		 * When deferring the error copy a message from the bypass into
		 * the unreported area. Or discard it if the new error is to
		 * be ignored in favor of an earlier defered error.
		 * be ignored in favor of an earlier deferred error.
		 */

		Tcl_Obj *msg = statePtr->chanMsg;

		if (statePtr->unreportedError == 0) {
		    statePtr->unreportedError = errorCode;
		    statePtr->unreportedMsg = msg;
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
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







-

+










+
+
+
+
+
+
+
+
+
+
+
-
+

-
-
-
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+







	    }

	    /*
	     * When we get an error we throw away all the output currently
	     * queued.
	     */

	    DiscardOutputQueued(statePtr);
	    ReleaseChannelBuffer(bufPtr);
	    DiscardOutputQueued(statePtr);
	    break;
	} else {
	    /*
	     * TODO: Consider detecting and reacting to short writes on
	     * blocking channels.  Ought not happen.  See iocmd-24.2.
	     */

	    wroteSome = 1;
	}

	bufExists = bufPtr->refCount > 1;
	ReleaseChannelBuffer(bufPtr);
	if (bufExists) {
	    /* There is still a reference to this buffer other than the one
	     * this routine just released, meaning that final cleanup of the
	     * buffer hasn't been ordered by, e.g. by a reflected channel
	     * closing the channel from within one of its handler scripts (not
	     * something one would expecte, but it must be considered).  Normal
	     * operations on the buffer can proceed.
	     */

	bufPtr->nextRemoved += written;
	    bufPtr->nextRemoved += written;

	/*
	 * If this buffer is now empty, recycle it.
	 */
	    /*
	     * If this buffer is now empty, recycle it.
	     */

	if (IsBufferEmpty(bufPtr)) {
	    statePtr->outQueueHead = bufPtr->nextPtr;
	    if (statePtr->outQueueHead == NULL) {
		statePtr->outQueueTail = NULL;
	    }
	    RecycleBuffer(statePtr, bufPtr, 0);
	}
	ReleaseChannelBuffer(bufPtr);
	    if (IsBufferEmpty(bufPtr)) {
		statePtr->outQueueHead = bufPtr->nextPtr;
		if (statePtr->outQueueHead == NULL) {
		    statePtr->outQueueTail = NULL;
		}
		RecycleBuffer(statePtr, bufPtr, 0);
	    }
	}

    }	/* Closes "while". */

    /*
     * If we wrote some data while flushing in the background, we are done.
     * We can't finish the background flush until we run out of data and the
     * channel becomes writable again. This ensures that all of the pending
     * data has been flushed at the system level.
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
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







-
+


















-
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








    /*
     * If the channel is flagged as closed, delete it when the refCount drops
     * to zero, the output queue is empty and there is no output in the
     * current output buffer.
     */

    if (GotFlag(statePtr, CHANNEL_CLOSED) && (statePtr->refCount + 1 <= 1) &&
    if (GotFlag(statePtr, CHANNEL_CLOSED) && (statePtr->refCount <= 0) &&
	    (statePtr->outQueueHead == NULL) &&
	    ((statePtr->curOutPtr == NULL) ||
	    IsBufferEmpty(statePtr->curOutPtr))) {
	errorCode = CloseChannel(interp, chanPtr, errorCode);
	goto done;
    }

    /*
     * If the write-side of the channel is flagged as closed, delete it when
     * the output queue is empty and there is no output in the current output
     * buffer.
     */

    if (GotFlag(statePtr, CHANNEL_CLOSEDWRITE) &&
	    (statePtr->outQueueHead == NULL) &&
	    ((statePtr->curOutPtr == NULL) ||
	    IsBufferEmpty(statePtr->curOutPtr))) {
	errorCode = CloseChannelPart(interp, chanPtr, errorCode,
                TCL_CLOSE_WRITE);
		TCL_CLOSE_WRITE);
	goto done;
    }

  done:
    TclChannelRelease((Tcl_Channel)chanPtr);
    return errorCode;
}

static void
FreeChannelState(
    void *blockPtr)		/* Channel state to free. */
{
    ChannelState *statePtr = (ChannelState *)blockPtr;
    /*
     * Even after close some members can be filled again (in events etc).
     * Test in bug [79474c588] illustrates one leak (on remaining chanMsg).
     * Possible other fields need freeing on some constellations.
     */

    DiscardInputQueued(statePtr, 1);
    if (statePtr->curOutPtr != NULL) {
	ReleaseChannelBuffer(statePtr->curOutPtr);
    }
    DiscardOutputQueued(statePtr);

    DeleteTimerHandler(statePtr);

    if (statePtr->chanMsg) {
	Tcl_DecrRefCount(statePtr->chanMsg);
    }
    if (statePtr->unreportedMsg) {
	Tcl_DecrRefCount(statePtr->unreportedMsg);
    }
    Tcl_Free(statePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * CloseChannel --
 *
 *	Utility procedure to close a channel and free associated resources.
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
3095
3096
3097
3098
3099
3100
3101












3102
3103
3104
3105
3106
3107
3108







-
-
-
-
-
-
-
-
-
-
-
-







     * The caller guarantees that there are no more buffers queued for output.
     */

    if (statePtr->outQueueHead != NULL) {
	Tcl_Panic("TclFlush, closed channel: queued output left");
    }

    /*
     * If the EOF character is set in the channel, append that to the output
     * device.
     */

    if ((statePtr->outEofChar != 0) && GotFlag(statePtr, TCL_WRITABLE)) {
	int dummy;
	char c = (char) statePtr->outEofChar;

	(void) ChanWrite(chanPtr, &c, 1, &dummy);
    }

    /*
     * TIP #219, Tcl Channel Reflection API.
     * Move a leftover error message in the channel bypass into the
     * interpreter bypass. Just clear it if there is no interpreter.
     */

    if (statePtr->chanMsg != NULL) {
3093
3094
3095
3096
3097
3098
3099
3100

3101
3102
3103
3104
3105
3106
3107
3169
3170
3171
3172
3173
3174
3175

3176
3177
3178
3179
3180
3181
3182
3183







-
+







	}
    }

    /*
     * Cancel any outstanding timer.
     */

    Tcl_DeleteTimerHandler(statePtr->timer);
    DeleteTimerHandler(statePtr);

    /*
     * Mark the channel as deleted by clearing the type structure.
     */

    if (chanPtr->downChanPtr != NULL) {
	Channel *downChanPtr = chanPtr->downChanPtr;
3121
3122
3123
3124
3125
3126
3127
3128

3129
3130
3131
3132
3133
3134
3135
3197
3198
3199
3200
3201
3202
3203

3204
3205
3206
3207
3208
3209
3210
3211







-
+







     * There is only the TOP Channel, so we free the remaining pointers we
     * have and then ourselves. Since this is the last of the channels in the
     * stack, make sure to free the ChannelState structure associated with it.
     */

    ChannelFree(chanPtr);

    Tcl_EventuallyFree(statePtr, TCL_DYNAMIC);
    Tcl_EventuallyFree(statePtr, FreeChannelState);

    return errorCode;
}

/*
 *----------------------------------------------------------------------
 *
3145
3146
3147
3148
3149
3150
3151
3152
3153


3154
3155
3156
3157
3158
3159
3160
3221
3222
3223
3224
3225
3226
3227


3228
3229
3230
3231
3232
3233
3234
3235
3236







-
-
+
+







 * Side effects:
 *	Resets the field 'nextCSPtr' of the specified channel state to NULL.
 *
 * NOTE:
 *	The channel to cut out of the list must not be referenced in any
 *	interpreter. This is something this procedure cannot check (despite
 *	the refcount) because the caller usually wants fiddle with the channel
 *	(like transfering it to a different thread) and thus keeps the
 *	refcount artifically high to prevent its destruction.
 *	(like transferring it to a different thread) and thus keeps the
 *	refcount artificially high to prevent its destruction.
 *
 *----------------------------------------------------------------------
 */

static void
CutChannel(
    Tcl_Channel chan)		/* The channel being removed. Must not be
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269



3270
3271
3272
3273
3274
3275
3276
3336
3337
3338
3339
3340
3341
3342



3343
3344
3345
3346
3347
3348
3349
3350
3351
3352







-
-
-
+
+
+







 *
 * Side effects:
 *	Nothing.
 *
 * NOTE:
 *	The channel to splice into the list must not be referenced in any
 *	interpreter. This is something this procedure cannot check (despite
 *	the refcount) because the caller usually wants figgle with the channel
 *	(like transfering it to a different thread) and thus keeps the
 *	refcount artifically high to prevent its destruction.
 *	the refcount) because the caller usually wants fiddle with the channel
 *	(like transferring it to a different thread) and thus keeps the
 *	refcount artificially high to prevent its destruction.
 *
 *----------------------------------------------------------------------
 */

static void
SpliceChannel(
    Tcl_Channel chan)		/* The channel being added. Must not be
3357
3358
3359
3360
3361
3362
3363
3364


3365
3366
3367
3368
3369
3370
3371
3433
3434
3435
3436
3437
3438
3439

3440
3441
3442
3443
3444
3445
3446
3447
3448







-
+
+







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

int
TclClose(
    Tcl_Interp *interp,		/* Interpreter for errors. */
    Tcl_Channel chan)		/* The channel being closed. Must not be
				 * referenced in any interpreter. */
				 * referenced in any interpreter. May be NULL,
				 * in which case this is a no-op. */
{
    CloseCallback *cbPtr;	/* Iterate over close callbacks for this
				 * channel. */
    Channel *chanPtr;		/* The real IO channel. */
    ChannelState *statePtr;	/* State of real IO channel. */
    int result = 0;			/* Of calling FlushChannel. */
    int flushcode;
3389
3390
3391
3392
3393
3394
3395
3396

3397
3398
3399
3400
3401
3402
3403
3404


3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417


3418
3419
3420
3421
3422
3423
3424
3466
3467
3468
3469
3470
3471
3472

3473
3474
3475
3476
3477
3478
3479


3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493

3494
3495
3496
3497
3498
3499
3500
3501
3502







-
+






-
-
+
+












-
+
+







     * This operation should occur at the top of a channel stack.
     */

    chanPtr = (Channel *) chan;
    statePtr = chanPtr->state;
    chanPtr = statePtr->topChanPtr;

    if (statePtr->refCount + 1 > 1) {
    if (statePtr->refCount > 0) {
	Tcl_Panic("called Tcl_Close on channel with refCount > 0");
    }

    if (GotFlag(statePtr, CHANNEL_INCLOSE)) {
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
                    "illegal recursive call to close through close-handler"
                    " of channel", -1));
		    "illegal recursive call to close through close-handler"
		    " of channel", -1));
	}
	return TCL_ERROR;
    }
    SetFlag(statePtr, CHANNEL_INCLOSE);

    /*
     * When the channel has an escape sequence driven encoding such as
     * iso2022, the terminated escape sequence must write to the buffer.
     */

    stickyError = 0;

    if (GotFlag(statePtr, TCL_WRITABLE) && (statePtr->encoding != NULL)
    if (GotFlag(statePtr, TCL_WRITABLE)
	    && (statePtr->encoding != GetBinaryEncoding())
	    && !(statePtr->outputEncodingFlags & TCL_ENCODING_START)) {
	int code = CheckChannelErrors(statePtr, TCL_WRITABLE);

	if (code == 0) {
	    statePtr->outputEncodingFlags |= TCL_ENCODING_END;
	    code = WriteChars(chanPtr, "", 0);
	    statePtr->outputEncodingFlags &= ~TCL_ENCODING_END;
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3519
3520
3521
3522
3523
3524
3525





3526
3527
3528
3529
3530
3531
3532







-
-
-
-
-







	    TclDecrRefCount(statePtr->chanMsg);
	    statePtr->chanMsg = NULL;
	}
    }

    Tcl_ClearChannelHandlers(chan);

    /*
     * Cancel any outstanding timer.
     */
    Tcl_DeleteTimerHandler(statePtr->timer);

    /*
     * Invoke the registered close callbacks and delete their records.
     */

    while (statePtr->closeCbPtr != NULL) {
	cbPtr = statePtr->closeCbPtr;
	statePtr->closeCbPtr = cbPtr->nextPtr;
3500
3501
3502
3503
3504
3505
3506
3507

3508
3509
3510
3511
3512
3513
3514
3573
3574
3575
3576
3577
3578
3579

3580
3581
3582
3583
3584
3585
3586
3587







-
+







	result = EINVAL;
    }

    if (stickyError != 0) {
	Tcl_SetErrno(stickyError);
	if (interp != NULL) {
	    Tcl_SetObjResult(interp,
			     Tcl_NewStringObj(Tcl_PosixError(interp), -1));
		    Tcl_NewStringObj(Tcl_PosixError(interp), -1));
	}
	return TCL_ERROR;
    }

    /*
     * Bug 97069ea11a: set error message if a flush code is set and no error
     * message set up to now.
3600
3601
3602
3603
3604
3605
3606
3607

3608
3609
3610
3611
3612
3613
3614
3615
3616
3617


3618
3619
3620
3621
3622
3623
3624
3625
3626

3627
3628
3629
3630


3631
3632
3633
3634
3635
3636
3637
3673
3674
3675
3676
3677
3678
3679

3680
3681
3682
3683
3684
3685
3686
3687
3688


3689
3690
3691
3692
3693
3694
3695
3696
3697
3698

3699
3700
3701


3702
3703
3704
3705
3706
3707
3708
3709
3710







-
+








-
-
+
+








-
+


-
-
+
+








    /*
     * Check direction against channel mode. It is an error if we try to close
     * a direction not supported by the channel (already closed, or never
     * opened for that direction).
     */

    if (!(statePtr->flags & (TCL_READABLE | TCL_WRITABLE) & flags)) {
    if (!(GotFlag(statePtr, TCL_READABLE|TCL_WRITABLE) & flags)) {
	const char *msg;

	if (flags & TCL_CLOSE_READ) {
	    msg = "read";
	} else {
	    msg = "write";
	}
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "Half-close of %s-side not possible, side not opened or"
                " already closed", msg));
		"Half-close of %s-side not possible, side not opened or"
		" already closed", msg));
	return TCL_ERROR;
    }

    /*
     * A user may try to call half-close from within a channel close handler.
     * That won't do.
     */

    if (statePtr->flags & CHANNEL_INCLOSE) {
    if (GotFlag(statePtr, CHANNEL_INCLOSE)) {
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
                    "illegal recursive call to close through close-handler"
                    " of channel", -1));
		    "illegal recursive call to close through close-handler"
		    " of channel", -1));
	}
	return TCL_ERROR;
    }

    if (flags & TCL_CLOSE_READ) {
	/*
	 * Call the finalization code directly. There are no events to handle,
3672
3673
3674
3675
3676
3677
3678
3679

3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692


3693
3694
3695
3696
3697
3698
3699
3700
3701
3702

3703
3704
3705
3706
3707
3708
3709
3745
3746
3747
3748
3749
3750
3751

3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763


3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774

3775
3776
3777
3778
3779
3780
3781
3782







-
+











-
-
+
+









-
+







 *	A standard Tcl result.
 *
 * Side effects:
 *	Closes the write side of the channel.
 *
 * NOTE:
 *	CloseWrite removes the channel as far as the user is concerned.
 *	However, the ooutput data structures may continue to exist for a while
 *	However, the output data structures may continue to exist for a while
 *	longer if it has a background flush scheduled. The device itself is
 *	eventually closed and the channel structures modified, in
 *	CloseChannelPart, below.
 *
 *----------------------------------------------------------------------
 */

static int
CloseWrite(
    Tcl_Interp *interp,		/* Interpreter for errors. */
    Channel *chanPtr)		/* The channel whose write side is being
                                 * closed. May still be used by some
                                 * interpreter */
				 * closed. May still be used by some
				 * interpreter */
{
    /*
     * Notes: clear-channel-handlers - write side only ? or keep around, just
     * not called.
     *
     * No close callbacks are run - channel is still open (read side)
     */

    ChannelState *statePtr = chanPtr->state;
                                /* State of real IO channel. */
				/* State of real IO channel. */
    int flushcode;
    int result = 0;

    /*
     * The call to FlushChannel will flush any queued output and invoke the
     * close function of the channel driver, or it will set up the channel to
     * be flushed and closed asynchronously.
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3855
3856
3857
3858
3859
3860
3861












3862
3863
3864
3865
3866
3867
3868







-
-
-
-
-
-
-
-
-
-
-
-







	 */

	if (statePtr->outQueueHead != NULL) {
	    Tcl_Panic("ClosechanHalf, closed write-side of channel: "
		    "queued output left");
	}

	/*
	 * If the EOF character is set in the channel, append that to the
	 * output device.
	 */

	if ((statePtr->outEofChar != 0) && GotFlag(statePtr, TCL_WRITABLE)) {
	    int dummy;
	    char c = (char) statePtr->outEofChar;

	    (void) ChanWrite(chanPtr, &c, 1, &dummy);
	}

	/*
	 * TIP #219, Tcl Channel Reflection API.
	 * Move a leftover error message in the channel bypass into the
	 * interpreter bypass. Just clear it if there is no interpreter.
	 */

	if (statePtr->chanMsg != NULL) {
3910
3911
3912
3913
3914
3915
3916
3917

3918
3919
3920
3921
3922
3923
3924
3971
3972
3973
3974
3975
3976
3977

3978
3979
3980
3981
3982
3983
3984
3985







-
+







    statePtr = chanPtr->state;
    chanPtr = statePtr->topChanPtr;

    /*
     * Cancel any outstanding timer.
     */

    Tcl_DeleteTimerHandler(statePtr->timer);
    DeleteTimerHandler(statePtr);

    /*
     * Remove any references to channel handlers for this channel that may be
     * about to be invoked.
     */

    for (nhPtr = tsdPtr->nestedHandlerPtr; nhPtr != NULL;
3939
3940
3941
3942
3943
3944
3945

3946
3947







3948
3949
3950
3951
3952
3953
3954
4000
4001
4002
4003
4004
4005
4006
4007


4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021







+
-
-
+
+
+
+
+
+
+







    }
    statePtr->chPtr = NULL;

    /*
     * Cancel any pending copy operation.
     */

    if (statePtr->csPtrR) {
    StopCopy(statePtr->csPtrR);
    StopCopy(statePtr->csPtrW);
	StopCopy(statePtr->csPtrR);
	statePtr->csPtrR = NULL;
    }
    if (statePtr->csPtrW) {
	StopCopy(statePtr->csPtrW);
	statePtr->csPtrW = NULL;
    }

    /*
     * Must set the interest mask now to 0, otherwise infinite loops will
     * occur if Tcl_DoOneEvent is called before the channel is finally deleted
     * in FlushChannel. This can happen if the channel has a background flush
     * active.
     */
3977
3978
3979
3980
3981
3982
3983
3984
3985


3986
3987
3988
3989
3990
3991
3992
3993
3994

3995
3996
3997
3998

3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012

4013
4014
4015
4016
4017
4018
4019

4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039


4040
4041
4042
4043
4044
4045
4046
4047
4048

4049
4050
4051
4052

4053
4054
4055
4056
4057
4058
4059

4060
4061
4062

4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075

4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096


4097
4098
4099
4100
4101
4102
4103
4104
4105

4106
4107
4108
4109
4110

4111
4112
4113
4114
4115

4116
4117
4118
4119

4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134

4135
4136
4137
4138
4139
4140
4141
4142
4143
4144







4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165


4166
4167
4168
4169
4170
4171
4172
4173
4174

4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186

4187
4188
4189
4190
4191
4192

4193
4194

4195
4196









4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210


4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232


4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244

4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261

4262
4263
4264
4265
4266
4267
4268
4269
4270
4271

4272
4273
4274
4275

4276
4277
4278
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
4044
4045
4046
4047
4048
4049
4050


4051
4052
4053
4054
4055
4056
4057
4058
4059
4060

4061
4062
4063
4064

4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078

4079
4080
4081
4082
4083
4084
4085

4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104


4105
4106
4107
4108
4109
4110
4111
4112
4113
4114

4115
4116
4117
4118

4119
4120
4121
4122
4123
4124
4125

4126
4127
4128

4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141

4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161


4162
4163
4164
4165
4166
4167
4168
4169
4170
4171

4172
4173
4174
4175
4176

4177
4178
4179
4180
4181

4182
4183
4184
4185

4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200

4201
4202
4203
4204
4205
4206
4207
4208
4209


4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235


4236
4237
4238
4239
4240
4241
4242
4243
4244
4245

4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257

4258
4259
4260
4261
4262
4263

4264
4265
4266
4267


4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
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







-
-
+
+








-
+



-
+













-
+






-
+


















-
-
+
+








-
+



-
+






-
+


-
+












-
+



















-
-
+
+








-
+




-
+




-
+



-
+














-
+








-
-
+
+
+
+
+
+
+



















-
-
+
+








-
+











-
+





-
+


+
-
-
+
+
+
+
+
+
+
+
+












-
-
+
+




















-
-
+
+











-
+
















-
+









-
+



-
+





+
-
+
+
+


-
+







-





-
+

-
-
+
+
+







 *	buffer is ready e.g. if it contains a newline and we are in line
 *	buffering mode. Compensates stacking, i.e. will redirect the data from
 *	the specified channel to the topmost channel in a stack.
 *
 *	No encoding conversions are applied to the bytes being read.
 *
 * Results:
 *	The number of bytes written or TCL_IO_FAILURE in case of error. If
 *	TCL_IO_FAILURE, Tcl_GetErrno will return the error code.
 *	The number of bytes written or TCL_INDEX_NONE in case of error. If
 *	TCL_INDEX_NONE, Tcl_GetErrno will return the error code.
 *
 * Side effects:
 *	May buffer up output and may cause output to be produced on the
 *	channel.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
Tcl_Write(
    Tcl_Channel chan,		/* The channel to buffer output for. */
    const char *src,		/* Data to queue in output buffer. */
    size_t srcLen)			/* Length of data in bytes, or -1 for
    Tcl_Size srcLen)			/* Length of data in bytes, or TCL_INDEX_NONE for
				 * strlen(). */
{
    /*
     * Always use the topmost channel of the stack
     */

    Channel *chanPtr;
    ChannelState *statePtr;	/* State info for channel */

    statePtr = ((Channel *) chan)->state;
    chanPtr = statePtr->topChanPtr;

    if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) {
	return TCL_IO_FAILURE;
	return TCL_INDEX_NONE;
    }

    if (srcLen == TCL_INDEX_NONE) {
	srcLen = strlen(src);
    }
    if (WriteBytes(chanPtr, src, srcLen) == -1) {
	return TCL_IO_FAILURE;
	return TCL_INDEX_NONE;
    }
    return srcLen;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_WriteRaw --
 *
 *	Puts a sequence of bytes into an output buffer, may queue the buffer
 *	for output if it gets full, and also remembers whether the current
 *	buffer is ready e.g. if it contains a newline and we are in line
 *	buffering mode. Writes directly to the driver of the channel, does not
 *	compensate for stacking.
 *
 *	No encoding conversions are applied to the bytes being read.
 *
 * Results:
 *	The number of bytes written or TCL_IO_FAILURE in case of error. If
 *	TCL_IO_FAILURE, Tcl_GetErrno will return the error code.
 *	The number of bytes written or TCL_INDEX_NONE in case of error. If
 *	TCL_INDEX_NONE, Tcl_GetErrno will return the error code.
 *
 * Side effects:
 *	May buffer up output and may cause output to be produced on the
 *	channel.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
Tcl_WriteRaw(
    Tcl_Channel chan,		/* The channel to buffer output for. */
    const char *src,		/* Data to queue in output buffer. */
    size_t srcLen)		/* Length of data in bytes, or -1 for
    Tcl_Size srcLen)		/* Length of data in bytes, or TCL_INDEX_NONE for
				 * strlen(). */
{
    Channel *chanPtr = ((Channel *) chan);
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    int errorCode;
    size_t written;
    Tcl_Size written;

    if (CheckChannelErrors(statePtr, TCL_WRITABLE | CHANNEL_RAW_MODE) != 0) {
	return TCL_IO_FAILURE;
	return TCL_INDEX_NONE;
    }

    if (srcLen == TCL_INDEX_NONE) {
	srcLen = strlen(src);
    }

    /*
     * Go immediately to the driver, do all the error handling by ourselves.
     * The code was stolen from 'FlushChannel'.
     */

    written = ChanWrite(chanPtr, src, srcLen, &errorCode);
    if (written == TCL_IO_FAILURE) {
    if (written == TCL_INDEX_NONE) {
	Tcl_SetErrno(errorCode);
    }

    return written;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_WriteChars --
 *
 *	Takes a sequence of UTF-8 characters and converts them for output
 *	using the channel's current encoding, may queue the buffer for output
 *	if it gets full, and also remembers whether the current buffer is
 *	ready e.g. if it contains a newline and we are in line buffering
 *	mode. Compensates stacking, i.e. will redirect the data from the
 *	specified channel to the topmost channel in a stack.
 *
 * Results:
 *	The number of bytes written or TCL_IO_FAILURE in case of error. If
 *	TCL_IO_FAILURE, Tcl_GetErrno will return the error code.
 *	The number of bytes written or TCL_INDEX_NONE in case of error. If
 *	TCL_INDEX_NONE, Tcl_GetErrno will return the error code.
 *
 * Side effects:
 *	May buffer up output and may cause output to be produced on the
 *	channel.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
Tcl_WriteChars(
    Tcl_Channel chan,		/* The channel to buffer output for. */
    const char *src,		/* UTF-8 characters to queue in output
				 * buffer. */
    size_t len)			/* Length of string in bytes, or -1 for
    Tcl_Size len)			/* Length of string in bytes, or TCL_INDEX_NONE for
				 * strlen(). */
{
    Channel *chanPtr = (Channel *) chan;
    ChannelState *statePtr = chanPtr->state;	/* State info for channel */
    int result;
    Tcl_Size result;
    Tcl_Obj *objPtr;

    if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) {
	return TCL_IO_FAILURE;
	return TCL_INDEX_NONE;
    }

    chanPtr = statePtr->topChanPtr;

    if (len == TCL_INDEX_NONE) {
	len = strlen(src);
    }
    if (statePtr->encoding) {
	return WriteChars(chanPtr, src, len);
    }

    /*
     * Inefficient way to convert UTF-8 to byte-array, but the code
     * parallels the way it is done for objects.  Special case for 1-byte
     * (used by eg [puts] for the \n) could be extended to more efficient
     * (used by e.g. [puts] for the \n) could be extended to more efficient
     * translation of the src string.
     */

    if ((len == 1) && (UCHAR(*src) < 0xC0)) {
	return WriteBytes(chanPtr, src, len);
    }

    objPtr = Tcl_NewStringObj(src, len);
    src = (char *) TclGetByteArrayFromObj(objPtr, &len);
    result = WriteBytes(chanPtr, src, len);
    src = (char *) Tcl_GetBytesFromObj(NULL, objPtr, &len);
    if (src == NULL) {
	Tcl_SetErrno(EILSEQ);
	result = TCL_INDEX_NONE;
    } else {
	result = WriteBytes(chanPtr, src, len);
    }
    TclDecrRefCount(objPtr);
    return result;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_WriteObj --
 *
 *	Takes the Tcl object and queues its contents for output. If the
 *	encoding of the channel is NULL, takes the byte-array representation
 *	of the object and queues those bytes for output. Otherwise, takes the
 *	characters in the UTF-8 (string) representation of the object and
 *	converts them for output using the channel's current encoding. May
 *	flush internal buffers to output if one becomes full or is ready for
 *	some other reason, e.g. if it contains a newline and the channel is in
 *	line buffering mode.
 *
 * Results:
 *	The number of bytes written or -1 in case of error. If -1,
 *	Tcl_GetErrno() will return the error code.
 *	The number of bytes written or TCL_INDEX_NONE in case of error. If
 *	TCL_INDEX_NONE, Tcl_GetErrno() will return the error code.
 *
 * Side effects:
 *	May buffer up output and may cause output to be produced on the
 *	channel.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
Tcl_WriteObj(
    Tcl_Channel chan,		/* The channel to buffer output for. */
    Tcl_Obj *objPtr)		/* The object to write. */
{
    /*
     * Always use the topmost channel of the stack
     */

    Channel *chanPtr;
    ChannelState *statePtr;	/* State info for channel */
    const char *src;
    size_t srcLen = 0;
    Tcl_Size srcLen = 0;

    statePtr = ((Channel *) chan)->state;
    chanPtr = statePtr->topChanPtr;

    if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) {
	return TCL_IO_FAILURE;
	return TCL_INDEX_NONE;
    }
    if (statePtr->encoding == NULL) {
	Tcl_Size result;
	src = (char *) TclGetByteArrayFromObj(objPtr, &srcLen);
	return WriteBytes(chanPtr, src, srcLen);

	src = (char *) Tcl_GetBytesFromObj(NULL, objPtr, &srcLen);
	if (src == NULL) {
	    Tcl_SetErrno(EILSEQ);
	    result = TCL_INDEX_NONE;
	} else {
	    result = WriteBytes(chanPtr, src, srcLen);
	}
	return result;
    } else {
	src = TclGetStringFromObj(objPtr, &srcLen);
	return WriteChars(chanPtr, src, srcLen);
    }
}

static void
WillWrite(
    Channel *chanPtr)
{
    int inputBuffered;

    if (((Tcl_ChannelWideSeekProc(chanPtr->typePtr) != NULL)
	    ) && ((inputBuffered = Tcl_InputBuffered((Tcl_Channel) chanPtr)) > 0)){
    if ((Tcl_ChannelWideSeekProc(chanPtr->typePtr) != NULL)
	    && ((inputBuffered = Tcl_InputBuffered((Tcl_Channel) chanPtr)) > 0)){
	int ignore;

	DiscardInputQueued(chanPtr->state, 0);
	ChanSeek(chanPtr, -inputBuffered, SEEK_CUR, &ignore);
    }
}

static int
WillRead(
    Channel *chanPtr)
{
    if (chanPtr->typePtr == NULL) {
	/*
	 * Prevent read attempts on a closed channel.
	 */

	DiscardInputQueued(chanPtr->state, 0);
	Tcl_SetErrno(EINVAL);
	return -1;
    }
    if (((Tcl_ChannelWideSeekProc(chanPtr->typePtr) != NULL)
	    ) && (Tcl_OutputBuffered((Tcl_Channel) chanPtr) > 0)) {
    if ((Tcl_ChannelWideSeekProc(chanPtr->typePtr) != NULL)
	    && (Tcl_OutputBuffered((Tcl_Channel) chanPtr) > 0)) {
	/*
	 * CAVEAT - The assumption here is that FlushChannel() will push out
	 * the bytes of any writes that are in progress.  Since this is a
	 * seekable channel, we assume it is not one that can block and force
	 * bg flushing.  Channels we know that can do that - sockets, pipes -
	 * are not seekable. If the assumption is wrong, more drastic measures
	 * may be required here like temporarily setting the channel into
	 * blocking mode.
	 */

	if (FlushChannel(NULL, chanPtr, 0) != 0) {
	return -1;
	    return -1;
	}
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * Write --
 *
 *	Convert srcLen bytes starting at src according to encoding and write
 *	produced bytes into an output buffer, may queue the buffer for output
 *	if it gets full, and also remembers whether the current buffer is
 *	ready e.g. if it contains a newline and we are in line buffering mode.
 *
 * Results:
 *	The number of bytes written or -1 in case of error. If -1,
 *	The number of bytes written or TCL_INDEX_NONE in case of error. If TCL_INDEX_NONE,
 *	Tcl_GetErrno will return the error code.
 *
 * Side effects:
 *	May buffer up output and may cause output to be produced on the
 *	channel.
 *
 *----------------------------------------------------------------------
 */

static int
static Tcl_Size
Write(
    Channel *chanPtr,		/* The channel to buffer output for. */
    const char *src,		/* UTF-8 string to write. */
    int srcLen,			/* Length of UTF-8 string in bytes. */
    Tcl_Size srcLen,	    /* Length of UTF-8 string in bytes. */
    Tcl_Encoding encoding)
{
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    char *nextNewLine = NULL;
    int endEncoding, needNlFlush = 0;
    int endEncoding, saved = 0, total = 0, flushed = 0, needNlFlush = 0;
    Tcl_Size saved = 0, total = 0, flushed = 0;
    char safe[BUFFER_PADDING];
    int encodingError = 0;

    if (srcLen) {
        WillWrite(chanPtr);
	WillWrite(chanPtr);
    }

    /*
     * Write the terminated escape sequence even if srcLen is 0.
     */

    endEncoding = ((statePtr->outputEncodingFlags & TCL_ENCODING_END) != 0);

    if (GotFlag(statePtr, CHANNEL_LINEBUFFERED)
	    || (statePtr->outputTranslation != TCL_TRANSLATE_LF)) {
	nextNewLine = (char *)memchr(src, '\n', srcLen);
    }

    while (srcLen + saved + endEncoding > 0) {
    while (srcLen + saved + endEncoding > 0 && !encodingError) {
	ChannelBuffer *bufPtr;
	char *dst, safe[BUFFER_PADDING];
	int result, srcRead, dstLen, dstWrote, srcLimit = srcLen;
	char *dst;
	int result, srcRead, dstLen, dstWrote;
	Tcl_Size srcLimit = srcLen;

	if (nextNewLine) {
	    srcLimit = nextNewLine - src;
	}

	/* Get space to write into */
	bufPtr = statePtr->curOutPtr;
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
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
4436
4437
4438
4439
4440
4441







-














+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
-
-
-
+
-
-
-
+







	     * that we need to stick at the beginning of this buffer.
	     */

	    memcpy(InsertPoint(bufPtr), safe, saved);
	    bufPtr->nextAdded += saved;
	    saved = 0;
	}
	PreserveChannelBuffer(bufPtr);
	dst = InsertPoint(bufPtr);
	dstLen = SpaceLeft(bufPtr);

	result = Tcl_UtfToExternal(NULL, encoding, src, srcLimit,
		statePtr->outputEncodingFlags,
		&statePtr->outputEncodingState, dst,
		dstLen + BUFFER_PADDING, &srcRead, &dstWrote, NULL);

	/*
	 * See chan-io-1.[89]. Tcl Bug 506297.
	 */

	statePtr->outputEncodingFlags &= ~TCL_ENCODING_START;

	/*
	 * See io-75.2, TCL bug 6978c01b65.
	 * Check, if an encoding error occured and should be reported to the
	 * script level.
	 * This happens, if a written character may not be represented by the
	 * current output encoding and strict encoding is active.
	 */
	if ((result != TCL_OK) && (srcRead + dstWrote == 0)) {
	    /*
	     * We're reading from invalid/incomplete UTF-8.
	     */


	if ((result == TCL_CONVERT_UNKNOWN || result == TCL_CONVERT_SYNTAX) ||
		/*
		 * We're reading from invalid/incomplete UTF-8.
		 */
		((result != TCL_OK) && (srcRead + dstWrote == 0))) {
	    ReleaseChannelBuffer(bufPtr);
	    if (total == 0) {
		Tcl_SetErrno(EINVAL);
	    encodingError = 1;
		return -1;
	    }
	    break;
	    result = TCL_OK;
	}

	bufPtr->nextAdded += dstWrote;
	src += srcRead;
	srcLen -= srcRead;
	total += dstWrote;
	dst += dstWrote;
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
4436
4437
4438
4439
4440


4441
4442
4443
4444
4445
4446
4447




4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460


4461
4462
4463
4464
4465
4466
4467
4468
4469
4470

4471
4472
4473
4474
4475
4476
4477
4478
4479

4480
4481
4482
4483

4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501


4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513

4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525

4526
4527
4528
4529







4530
4531

4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546

4547
4548
4549
4550
4551
4552
4553
4554
4555

4556
4557


4558
4559
4560
4561
4562
4563
4564
4485
4486
4487
4488
4489
4490
4491

4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502

4503
4504
4505
4506
4507









4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521

4522


4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546


4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557

4558
4559
4560
4561
4562
4563
4564
4565
4566

4567
4568
4569
4570

4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587


4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600

4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612

4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625

4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640

4641
4642
4643
4644
4645
4646
4647
4648
4649

4650
4651

4652
4653
4654
4655
4656
4657
4658
4659
4660







-
+










-





-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+





-

-
-
+
+







+
+
+
+











-
-
+
+









-
+








-
+



-
+
















-
-
+
+











-
+











-
+




+
+
+
+
+
+
+

-
+














-
+








-
+

-
+
+







	     * When translating from UTF-8 to external encoding, we allowed
	     * the translation to produce a character that crossed the end of
	     * the output buffer, so that we would get a completely full
	     * buffer before flushing it. The extra bytes will be moved to the
	     * beginning of the next buffer.
	     */

	    saved = 1 + ~SpaceLeft(bufPtr);
	    saved = -SpaceLeft(bufPtr);
	    memcpy(safe, dst + dstLen, saved);
	    bufPtr->nextAdded = bufPtr->bufLength;
	}

	if ((srcLen + saved == 0) && (result == TCL_OK)) {
	    endEncoding = 0;
	}

	if (IsBufferFull(bufPtr)) {
	    if (FlushChannel(NULL, chanPtr, 0) != 0) {
		ReleaseChannelBuffer(bufPtr);
		return -1;
	    }
	    flushed += statePtr->bufSize;

	    /*
 	     * We just flushed.  So if we have needNlFlush set to record that
 	     * we need to flush because theres a (translated) newline in the
 	     * buffer, that's likely not true any more.  But there is a tricky
 	     * exception.  If we have saved bytes that did not really get
 	     * flushed and those bytes came from a translation of a newline as
 	     * the last thing taken from the src array, then needNlFlush needs
 	     * to remain set to flag that the next buffer still needs a
 	     * newline flush.
 	     */
	     * We just flushed.  So if we have needNlFlush set to record that
	     * we need to flush because there is a (translated) newline in the
	     * buffer, that's likely not true any more.  But there is a tricky
	     * exception.  If we have saved bytes that did not really get
	     * flushed and those bytes came from a translation of a newline as
	     * the last thing taken from the src array, then needNlFlush needs
	     * to remain set to flag that the next buffer still needs a
	     * newline flush.
	     */

	    if (needNlFlush && (saved == 0 || src[-1] != '\n')) {
		needNlFlush = 0;
	    }
	}
	ReleaseChannelBuffer(bufPtr);
    }
    if ((flushed < total) && (GotFlag(statePtr, CHANNEL_UNBUFFERED) ||
	    (needNlFlush && GotFlag(statePtr, CHANNEL_LINEBUFFERED)))) {
    if (((flushed < total) && GotFlag(statePtr, CHANNEL_UNBUFFERED)) ||
	    (needNlFlush && GotFlag(statePtr, CHANNEL_LINEBUFFERED))) {
	if (FlushChannel(NULL, chanPtr, 0) != 0) {
	    return -1;
	}
    }

    UpdateInterest(chanPtr);

    if (encodingError) {
	Tcl_SetErrno(EILSEQ);
	return -1;
    }
    return total;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_Gets --
 *
 *	Reads a complete line of input from the channel into a Tcl_DString.
 *
 * Results:
 *	Length of line read (in characters) or -1 if error, EOF, or blocked.
 *	If -1, use Tcl_GetErrno() to retrieve the POSIX error code for the
 *	Length of line read (in characters) or TCL_INDEX_NONE if error, EOF, or blocked.
 *	If TCL_INDEX_NONE, use Tcl_GetErrno() to retrieve the POSIX error code for the
 *	error or condition that occurred.
 *
 * Side effects:
 *	May flush output on the channel. May cause input to be consumed from
 *	the channel.
 *
 *---------------------------------------------------------------------------
 */

size_t
Tcl_Size
Tcl_Gets(
    Tcl_Channel chan,		/* Channel from which to read. */
    Tcl_DString *lineRead)	/* The line read will be appended to this
				 * DString as UTF-8 characters. The caller
				 * must have initialized it and is responsible
				 * for managing the storage. */
{
    Tcl_Obj *objPtr;
    size_t charsStored;
    Tcl_Size charsStored;

    TclNewObj(objPtr);
    charsStored = Tcl_GetsObj(chan, objPtr);
    if (charsStored + 1 > 1) {
    if (charsStored > 0) {
	TclDStringAppendObj(lineRead, objPtr);
    }
    TclDecrRefCount(objPtr);
    return charsStored;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_GetsObj --
 *
 *	Accumulate input from the input channel until end-of-line or
 *	end-of-file has been seen. Bytes read from the input channel are
 *	converted to UTF-8 using the encoding specified by the channel.
 *
 * Results:
 *	Number of characters accumulated in the object or -1 if error,
 *	blocked, or EOF. If -1, use Tcl_GetErrno() to retrieve the POSIX error
 *	Number of characters accumulated in the object or TCL_INDEX_NONE if error,
 *	blocked, or EOF. If TCL_INDEX_NONE, use Tcl_GetErrno() to retrieve the POSIX error
 *	code for the error or condition that occurred.
 *
 * Side effects:
 *	Consumes input from the channel.
 *
 *	On reading EOF, leave channel pointing at EOF char. On reading EOL,
 *	leave channel pointing after EOL, but don't return EOL in dst buffer.
 *
 *---------------------------------------------------------------------------
 */

size_t
Tcl_Size
Tcl_GetsObj(
    Tcl_Channel chan,		/* Channel from which to read. */
    Tcl_Obj *objPtr)		/* The line read will be appended to this
				 * object as UTF-8 characters. */
{
    GetsState gs;
    Channel *chanPtr = (Channel *) chan;
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    ChannelBuffer *bufPtr;
    int inEofChar, skip, copiedTotal, oldFlags, oldRemoved;
    size_t oldLength;
    Tcl_Size oldLength;
    Tcl_Encoding encoding;
    char *dst, *dstEnd, *eol, *eof;
    Tcl_EncodingState oldState;

    if (GotFlag(statePtr, CHANNEL_ENCODING_ERROR)) {
	UpdateInterest(chanPtr);
	ResetFlag(statePtr, CHANNEL_EOF|CHANNEL_ENCODING_ERROR);
	Tcl_SetErrno(EILSEQ);
	return TCL_INDEX_NONE;
    }

    if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) {
	return TCL_IO_FAILURE;
	return TCL_INDEX_NONE;
    }

    /*
     * If we're sitting ready to read the eofchar, there's no need to
     * do it.
     */

    if (GotFlag(statePtr, CHANNEL_STICKY_EOF)) {
	SetFlag(statePtr, CHANNEL_EOF);
	assert(statePtr->inputEncodingFlags & TCL_ENCODING_END);
	assert(!GotFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR));

	/* TODO: Do we need this? */
	UpdateInterest(chanPtr);
	return TCL_IO_FAILURE;
	return TCL_INDEX_NONE;
    }

    /*
     * A binary version of Tcl_GetsObj. This could also handle encodings that
     * are ascii-7 pure (iso8859, utf-8, ...) with a final encoding conversion
     * done on objPtr.
     */

    if ((statePtr->encoding == NULL)
    if (statePtr->encoding == GetBinaryEncoding()
	    && ((statePtr->inputTranslation == TCL_TRANSLATE_LF)
		    || (statePtr->inputTranslation == TCL_TRANSLATE_CR))) {
		    || (statePtr->inputTranslation == TCL_TRANSLATE_CR))
	    && Tcl_GetBytesFromObj(NULL, objPtr, (Tcl_Size *)NULL) != NULL) {
	return TclGetsObjBinary(chan, objPtr);
    }

    /*
     * This operation should occur at the top of a channel stack.
     */

4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4673
4674
4675
4676
4677
4678
4679









4680
4681
4682
4683
4684
4685
4686







-
-
-
-
-
-
-
-
-







    oldFlags = statePtr->inputEncodingFlags;
    oldState = statePtr->inputEncodingState;
    oldRemoved = BUFFER_PADDING;
    if (bufPtr != NULL) {
	oldRemoved = bufPtr->nextRemoved;
    }

    /*
     * If there is no encoding, use "iso8859-1" -- Tcl_GetsObj() doesn't
     * produce ByteArray objects.
     */

    if (encoding == NULL) {
	encoding = GetBinaryEncoding();
    }

    /*
     * Object used by FilterInputBytes to keep track of how much data has been
     * consumed from the channel buffers.
     */

    gs.objPtr		= objPtr;
    gs.dstPtr		= &dst;
4611
4612
4613
4614
4615
4616
4617






4618
4619
4620
4621
4622
4623
4624
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717







+
+
+
+
+
+







    skip = 0;
    eof = NULL;
    inEofChar = statePtr->inEofChar;

    ResetFlag(statePtr, CHANNEL_BLOCKED);
    while (1) {
	if (dst >= dstEnd) {
	    /*
	     * In case of encoding errors, state gets flag
	     * CHANNEL_ENCODING_ERROR set in the call below. First, the
	     * EOF/EOL condition is checked, as we may have valid data with
	     * EOF/EOL before the encoding error.
	     */
	    if (FilterInputBytes(chanPtr, &gs) != 0) {
		goto restore;
	    }
	    dstEnd = dst + gs.bytesWrote;
	}

	/*
4661
4662
4663
4664
4665
4666
4667
4668

4669
4670
4671
4672
4673

4674
4675
4676
4677
4678
4679
4680
4754
4755
4756
4757
4758
4759
4760

4761
4762
4763
4764
4765

4766
4767
4768
4769
4770
4771
4772
4773







-
+




-
+







	case TCL_TRANSLATE_CRLF:
	    for (eol = dst; eol < dstEnd; eol++) {
		if (*eol == '\r') {
		    eol++;

		    /*
		     * If a CR is at the end of the buffer, then check for a
		     * LF at the begining of the next buffer, unless EOF char
		     * LF at the beginning of the next buffer, unless EOF char
		     * was found already.
		     */

		    if (eol >= dstEnd) {
			size_t offset;
			Tcl_Size offset;

			if (eol != eof) {
			    offset = eol - objPtr->bytes;
			    dst = dstEnd;
			    if (FilterInputBytes(chanPtr, &gs) != 0) {
				goto restore;
			    }
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4787
4788
4789
4790
4791
4792
4793

4794
4795
4796
4797
4798
4799
4800







-







		}
	    }
	    break;
	case TCL_TRANSLATE_AUTO:
	    eol = dst;
	    skip = 1;
	    if (GotFlag(statePtr, INPUT_SAW_CR)) {
		ResetFlag(statePtr, INPUT_SAW_CR);
		if ((eol < dstEnd) && (*eol == '\n')) {
		    /*
		     * Skip the raw bytes that make up the '\n'.
		     */

		    int rawRead;
		    char tmp[TCL_UTF_MAX];
4744
4745
4746
4747
4748
4749
4750

4751
4752

4753
4754
4755
4756
4757
4758
4759
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853







+


+







			    goto gotEOL;
			}
		    }
		    if (*eol == '\n') {
			skip++;
		    }
		    eol--;
		    ResetFlag(statePtr, INPUT_SAW_CR);
		    goto gotEOL;
		} else if (*eol == '\n') {
		    ResetFlag(statePtr, INPUT_SAW_CR);
		    goto gotEOL;
		}
	    }
	}
	if (eof != NULL) {
	    /*
	     * EOF character was seen. On EOF, leave current file position
4774
4775
4776
4777
4778
4779
4780
4781

4782
4783






















4784
4785
4786
4787
4788
4789
4790
4868
4869
4870
4871
4872
4873
4874

4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906







-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







		 * If we didn't append any bytes before encountering EOF,
		 * caller needs to see -1.
		 */

		Tcl_SetObjLength(objPtr, oldLength);
		CommonGetsCleanup(chanPtr);
		copiedTotal = -1;
		ResetFlag(statePtr, CHANNEL_BLOCKED);
		ResetFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR);
		goto done;
	    }
	    goto gotEOL;
	} else if (gs.bytesWrote == 0
		&& GotFlag(statePtr, CHANNEL_ENCODING_ERROR)) {
	    /* Ticket c4eb46a1 Harald Oehlmann 2023-11-12 debugging session.
	     * In non blocking mode we loop indifenitly on a decoding error in
	     * this while-loop.
	     * Removed the following from the upper condition:
	     * "&& !GotFlag(statePtr, CHANNEL_NONBLOCKING)"
	     * In case of an encoding error with leading correct bytes, we pass here
	     * two times, as gs.bytesWrote is not 0 on the first pass. This feels
	     * once to much, as the data is anyway not used.
	     */

	    /* Set eol to the position that caused the encoding error, and then
	     * continue to gotEOL, which stores the data that was decoded
	     * without error to objPtr.  This allows the caller to do something
	     * useful with the data decoded so far, and also results in the
	     * position of the file being the first byte that was not
	     * successfully decoded, allowing further processing at exactly that
	     * point, if desired.
	     */
	    eol = dstEnd;
	    goto gotEOL;
	}
	dst = dstEnd;
    }

    /*
     * Found EOL or EOF, but the output buffer may now contain too many UTF-8
4876
4877
4878
4879
4880
4881
4882
4883

4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899






4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918


4919
4920
4921
4922
4923
4924
4925
4992
4993
4994
4995
4996
4997
4998

4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038


5039
5040
5041
5042
5043
5044
5045
5046
5047







-
+
















+
+
+
+
+
+

















-
-
+
+







    /*
     * Update the notifier state so we don't block while there is still data
     * in the buffers.
     */

  done:
    assert(!GotFlag(statePtr, CHANNEL_EOF)
	    || GotFlag(statePtr, CHANNEL_STICKY_EOF)
	    || GotFlag(statePtr, CHANNEL_STICKY_EOF|CHANNEL_ENCODING_ERROR)
	    || Tcl_InputBuffered((Tcl_Channel)chanPtr) == 0);
    assert(!(GotFlag(statePtr, CHANNEL_EOF|CHANNEL_BLOCKED)
	    == (CHANNEL_EOF|CHANNEL_BLOCKED)));

    /*
     * Regenerate the top channel, in case it was changed due to
     * self-modifying reflected transforms.
     */

    if (chanPtr != statePtr->topChanPtr) {
	TclChannelRelease((Tcl_Channel)chanPtr);
	chanPtr = statePtr->topChanPtr;
	TclChannelPreserve((Tcl_Channel)chanPtr);
    }
    UpdateInterest(chanPtr);
    TclChannelRelease((Tcl_Channel)chanPtr);
    if (GotFlag(statePtr, CHANNEL_ENCODING_ERROR) && gs.bytesWrote == 0) {
	bufPtr->nextRemoved = oldRemoved;
	Tcl_SetErrno(EILSEQ);
	copiedTotal = -1;
    }
    ResetFlag(statePtr, CHANNEL_ENCODING_ERROR);
    return copiedTotal;
}

/*
 *---------------------------------------------------------------------------
 *
 * TclGetsObjBinary --
 *
 *	A variation of Tcl_GetsObj that works directly on the buffers until
 *	end-of-line or end-of-file has been seen. Bytes read from the input
 *	channel return as a ByteArray obj.
 *
 *	WARNING!  The notion of "binary" used here is different from notions
 *	of "binary" used in other places. In particular, this "binary" routine
 *	may be called when an -eofchar is set on the channel.
 *
 * Results:
 *	Number of characters accumulated in the object or -1 if error,
 *	blocked, or EOF. If -1, use Tcl_GetErrno() to retrieve the POSIX error
 *	Number of characters accumulated in the object or TCL_INDEX_NONE if error,
 *	blocked, or EOF. If TCL_INDEX_NONE, use Tcl_GetErrno() to retrieve the POSIX error
 *	code for the error or condition that occurred.
 *
 * Side effects:
 *	Consumes input from the channel.
 *
 *	On reading EOF, leave channel pointing at EOF char. On reading EOL,
 *	leave channel pointing after EOL, but don't return EOL in dst buffer.
4934
4935
4936
4937
4938
4939
4940
4941

4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958

4959




4960
4961
4962
4963
4964
4965
4966
5056
5057
5058
5059
5060
5061
5062

5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081

5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092







-
+

















+
-
+
+
+
+







				 * object as UTF-8 characters. */
{
    Channel *chanPtr = (Channel *) chan;
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    ChannelBuffer *bufPtr;
    int inEofChar, skip, copiedTotal, oldFlags, oldRemoved;
    size_t rawLen, byteLen = 0, oldLength;
    Tcl_Size rawLen, byteLen = 0, oldLength;
    int eolChar;
    unsigned char *dst, *dstEnd, *eol, *eof, *byteArray;

    /*
     * This operation should occur at the top of a channel stack.
     */

    chanPtr = statePtr->topChanPtr;
    TclChannelPreserve((Tcl_Channel)chanPtr);

    bufPtr = statePtr->inQueueHead;

    /*
     * Preserved so we can restore the channel's state in case we don't find a
     * newline in the available input.
     */

    byteArray = Tcl_GetBytesFromObj(NULL, objPtr, &byteLen);
    byteArray = TclGetByteArrayFromObj(objPtr, &byteLen);
    if (byteArray == NULL) {
	Tcl_SetErrno(EILSEQ);
	return -1;
    }
    oldFlags = statePtr->inputEncodingFlags;
    oldRemoved = BUFFER_PADDING;
    oldLength = byteLen;
    if (bufPtr != NULL) {
	oldRemoved = bufPtr->nextRemoved;
    }

5006
5007
5008
5009
5010
5011
5012
5013

5014
5015
5016
5017
5018
5019
5020
5132
5133
5134
5135
5136
5137
5138

5139
5140
5141
5142
5143
5144
5145
5146







-
+







	} else {
	    /*
	     * Incoming CHANNEL_STICKY_EOF is filtered out on entry.  A new
	     * CHANNEL_STICKY_EOF set in this routine leads to return before
	     * coming back here.  When we are not dealing with
	     * CHANNEL_STICKY_EOF, a CHANNEL_EOF implies an empty buffer.
	     * Here the buffer is non-empty so we know we're a non-EOF.
             */
	     */

	    assert(!GotFlag(statePtr, CHANNEL_STICKY_EOF));
	    assert(!GotFlag(statePtr, CHANNEL_EOF));
	}

	dst = (unsigned char *) RemovePoint(bufPtr);
	dstEnd = dst + BytesLeft(bufPtr);
5059
5060
5061
5062
5063
5064
5065
5066

5067
5068
5069
5070
5071
5072
5073
5185
5186
5187
5188
5189
5190
5191

5192
5193
5194
5195
5196
5197
5198
5199







-
+







	}
	if (GotFlag(statePtr, CHANNEL_EOF)) {
	    skip = 0;
	    eol = dstEnd;
	    if ((dst == dstEnd) && (byteLen == oldLength)) {
		/*
		 * If we didn't append any bytes before encountering EOF,
		 * caller needs to see -1.
		 * caller needs to see TCL_INDEX_NONE.
		 */

		byteArray = Tcl_SetByteArrayLength(objPtr, oldLength);
		CommonGetsCleanup(chanPtr);
		copiedTotal = -1;
		ResetFlag(statePtr, CHANNEL_BLOCKED);
		goto done;
5108
5109
5110
5111
5112
5113
5114
5115

5116
5117
5118
5119
5120
5121
5122
5234
5235
5236
5237
5238
5239
5240

5241
5242
5243
5244
5245
5246
5247
5248







-
+







    bufPtr->nextRemoved += rawLen + skip;

    /*
     * Convert the buffer if there was an encoding.
     * XXX - unimplemented.
     */

    if (statePtr->encoding != NULL) {
    if (statePtr->encoding != GetBinaryEncoding()) {
    }

    /*
     * Recycle all the emptied buffers.
     */

    CommonGetsCleanup(chanPtr);
5186
5187
5188
5189
5190
5191
5192
5193

5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205

5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5312
5313
5314
5315
5316
5317
5318

5319

5320
5321
5322
5323
5324
5325
5326
5327
5328
5329

5330
5331
5332
5333
5334
5335

5336
5337
5338
5339
5340
5341
5342







-
+
-










-
+





-







 * Results:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

static void
FreeBinaryEncoding(
FreeBinaryEncoding(void)
    TCL_UNUSED(ClientData))
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (tsdPtr->binaryEncoding != NULL) {
	Tcl_FreeEncoding(tsdPtr->binaryEncoding);
	tsdPtr->binaryEncoding = NULL;
    }
}

static Tcl_Encoding
GetBinaryEncoding()
GetBinaryEncoding(void)
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (tsdPtr->binaryEncoding == NULL) {
	tsdPtr->binaryEncoding = Tcl_GetEncoding(NULL, "iso8859-1");
	Tcl_CreateThreadExitHandler(FreeBinaryEncoding, NULL);
    }
    if (tsdPtr->binaryEncoding == NULL) {
	Tcl_Panic("binary encoding is not available");
    }
    return tsdPtr->binaryEncoding;
}

5303
5304
5305
5306
5307
5308
5309
5310

5311
5312
5313
5314
5315
5316
5317
5427
5428
5429
5430
5431
5432
5433

5434
5435
5436
5437
5438
5439
5440
5441







-
+







    } else {
	/*
	 * Incoming CHANNEL_STICKY_EOF is filtered out on entry.  A new
	 * CHANNEL_STICKY_EOF set in this routine leads to return before
	 * coming back here.  When we are not dealing with CHANNEL_STICKY_EOF,
	 * a CHANNEL_EOF implies an empty buffer.  Here the buffer is
	 * non-empty so we know we're a non-EOF.
         */
	 */

	assert(!GotFlag(statePtr, CHANNEL_STICKY_EOF));
	assert(!GotFlag(statePtr, CHANNEL_EOF));
    }

    /*
     * Convert some of the bytes from the channel buffer to UTF-8. Space in
5342
5343
5344
5345
5346
5347
5348

5349
5350
5351
5352







5353
5354
5355
5356
5357
5358
5359
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491







+




+
+
+
+
+
+
+







	    }
	}
	spaceLeft = length - offset;
	dst = objPtr->bytes + offset;
	*gsPtr->dstPtr = dst;
    }
    gsPtr->state = statePtr->inputEncodingState;

    result = Tcl_ExternalToUtf(NULL, gsPtr->encoding, raw, rawLen,
	    statePtr->inputEncodingFlags | TCL_ENCODING_NO_TERMINATE,
	    &statePtr->inputEncodingState, dst, spaceLeft, &gsPtr->rawRead,
	    &gsPtr->bytesWrote, &gsPtr->charsWrote);

	if (result == TCL_CONVERT_UNKNOWN || result == TCL_CONVERT_SYNTAX) {
	    SetFlag(statePtr, CHANNEL_ENCODING_ERROR);
	    ResetFlag(statePtr, CHANNEL_STICKY_EOF);
	    ResetFlag(statePtr, CHANNEL_EOF);
	    result = TCL_OK;
	}

    /*
     * Make sure that if we go through 'gets', that we reset the
     * TCL_ENCODING_START flag still. [Bug #523988]
     */

    statePtr->inputEncodingFlags &= ~TCL_ENCODING_START;
5538
5539
5540
5541
5542
5543
5544
5545

5546
5547
5548
5549
5550
5551

5552
5553
5554
5555
5556
5557
5558
5670
5671
5672
5673
5674
5675
5676

5677
5678
5679
5680
5681
5682

5683
5684
5685
5686
5687
5688
5689
5690







-
+





-
+







	 * buffer because the caller could change the channel's encoding which
	 * could change the interpretation of whether those bytes really made
	 * up multi-byte characters after all.
	 */

	nextPtr = bufPtr->nextPtr;
	for ( ; nextPtr != NULL; nextPtr = bufPtr->nextPtr) {
	    int extra;
	    Tcl_Size extra;

	    extra = SpaceLeft(bufPtr);
	    if (extra > 0) {
		memcpy(InsertPoint(bufPtr),
			nextPtr->buf + (BUFFER_PADDING - extra),
			(size_t) extra);
			extra);
		bufPtr->nextAdded += extra;
		nextPtr->nextRemoved = BUFFER_PADDING;
	    }
	    bufPtr = nextPtr;
	}
    }
}
5566
5567
5568
5569
5570
5571
5572
5573

5574
5575
5576
5577
5578
5579
5580
5581
5582

5583
5584
5585
5586

5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599

5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618

5619
5620
5621
5622
5623
5624
5625
5626
5627

5628
5629
5630
5631

5632
5633
5634
5635
5636
5637
5638
5639
5640

5641
5642
5643
5644
5645
5646
5647
5698
5699
5700
5701
5702
5703
5704

5705
5706
5707
5708
5709
5710
5711
5712
5713

5714
5715
5716
5717

5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730

5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749

5750
5751
5752
5753
5754
5755
5756
5757
5758

5759
5760
5761
5762

5763
5764
5765
5766
5767
5768
5769
5770
5771

5772
5773
5774
5775
5776
5777
5778
5779







-
+








-
+



-
+












-
+


















-
+








-
+



-
+








-
+







 *	is done on the bytes being read, so the number of bytes consumed from
 *	the channel may not be equal to the number of bytes stored in the
 *	destination buffer.
 *
 *	No encoding conversions are applied to the bytes being read.
 *
 * Results:
 *	The number of bytes read, or -1 on error. Use Tcl_GetErrno() to
 *	The number of bytes read, or TCL_INDEX_NONE on error. Use Tcl_GetErrno() to
 *	retrieve the error code for the error that occurred.
 *
 * Side effects:
 *	May cause input to be buffered.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
Tcl_Read(
    Tcl_Channel chan,		/* The channel from which to read. */
    char *dst,			/* Where to store input read. */
    size_t bytesToRead)		/* Maximum number of bytes to read. */
    Tcl_Size bytesToRead)		/* Maximum number of bytes to read. */
{
    Channel *chanPtr = (Channel *) chan;
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */

    /*
     * This operation should occur at the top of a channel stack.
     */

    chanPtr = statePtr->topChanPtr;

    if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) {
	return TCL_IO_FAILURE;
	return TCL_INDEX_NONE;
    }

    return DoRead(chanPtr, dst, bytesToRead, 0);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ReadRaw --
 *
 *	Reads a given number of bytes from a channel. EOL and EOF translation
 *	is done on the bytes being read, so the number of bytes consumed from
 *	the channel may not be equal to the number of bytes stored in the
 *	destination buffer.
 *
 *	No encoding conversions are applied to the bytes being read.
 *
 * Results:
 *	The number of bytes read, or -1 on error. Use Tcl_GetErrno() to
 *	The number of bytes read, or TCL_INDEX_NONE on error. Use Tcl_GetErrno() to
 *	retrieve the error code for the error that occurred.
 *
 * Side effects:
 *	May cause input to be buffered.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
Tcl_ReadRaw(
    Tcl_Channel chan,		/* The channel from which to read. */
    char *readBuf,		/* Where to store input read. */
    size_t bytesToRead)		/* Maximum number of bytes to read. */
    Tcl_Size bytesToRead)		/* Maximum number of bytes to read. */
{
    Channel *chanPtr = (Channel *) chan;
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    int copied = 0;

    assert(bytesToRead > 0);
    if (CheckChannelErrors(statePtr, TCL_READABLE | CHANNEL_RAW_MODE) != 0) {
	return TCL_IO_FAILURE;
	return TCL_INDEX_NONE;
    }

    /*
     * First read bytes from the push-back buffers.
     */

    while (chanPtr->inQueueHead && bytesToRead > 0) {
5657
5658
5659
5660
5661
5662
5663
5664
5665


5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678

5679
5680
5681
5682
5683
5684
5685
5789
5790
5791
5792
5793
5794
5795


5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809

5810
5811
5812
5813
5814
5815
5816
5817







-
-
+
+












-
+







	memcpy(readBuf, RemovePoint(bufPtr), toCopy);
	bufPtr->nextRemoved += toCopy;
	copied += toCopy;
	readBuf += toCopy;
	bytesToRead -= toCopy;

	/*
         * If the current buffer is empty recycle it.
         */
	 * If the current buffer is empty recycle it.
	 */

	if (IsBufferEmpty(bufPtr)) {
	    chanPtr->inQueueHead = bufPtr->nextPtr;
	    if (chanPtr->inQueueHead == NULL) {
		chanPtr->inQueueTail = NULL;
	    }
	    RecycleBuffer(chanPtr->state, bufPtr, 0);
	}
    }

    /*
     * Go to the driver only if we got nothing from pushback.  Have to do it
     * this way to avoid EOF mis-timings when we consider the ability that EOF
     * this way to avoid EOF mistimings when we consider the ability that EOF
     * may not be a permanent condition in the driver, and in that case we
     * have to synchronize.
     */

    if (copied) {
	return copied;
    }
5703
5704
5705
5706
5707
5708
5709
5710
5711


5712
5713
5714
5715
5716
5717
5718
5835
5836
5837
5838
5839
5840
5841


5842
5843
5844
5845
5846
5847
5848
5849
5850







-
-
+
+







	     */

	    if (!GotFlag(statePtr, CHANNEL_BLOCKED) || copied == 0) {
		copied = -1;
	    }
	} else if (nread > 0) {
	    /*
             * Successful read (short is OK) - add to bytes copied.
             */
	     * Successful read (short is OK) - add to bytes copied.
	     */

	    copied += nread;
	} else {
	    /*
	     * nread == 0.  Driver is at EOF. Let that state filter up.
	     */
	}
5729
5730
5731
5732
5733
5734
5735
5736

5737
5738
5739
5740
5741
5742
5743
5744
5745

5746
5747
5748
5749
5750


5751
5752
5753
5754
5755
5756
5757
5861
5862
5863
5864
5865
5866
5867

5868
5869
5870
5871
5872
5873
5874
5875
5876

5877
5878
5879
5880


5881
5882
5883
5884
5885
5886
5887
5888
5889







-
+








-
+



-
-
+
+







 *	been seen, EOF is seen, or the channel would block. EOL and EOF
 *	translation is done. If reading binary data, the raw bytes are wrapped
 *	in a Tcl byte array object. Otherwise, the raw bytes are converted to
 *	UTF-8 using the channel's current encoding and stored in a Tcl string
 *	object.
 *
 * Results:
 *	The number of characters read, or -1 on error. Use Tcl_GetErrno() to
 *	The number of characters read, or TCL_INDEX_NONE on error. Use Tcl_GetErrno() to
 *	retrieve the error code for the error that occurred.
 *
 * Side effects:
 *	May cause input to be buffered.
 *
 *---------------------------------------------------------------------------
 */

size_t
Tcl_Size
Tcl_ReadChars(
    Tcl_Channel chan,		/* The channel to read. */
    Tcl_Obj *objPtr,		/* Input data is stored in this object. */
    size_t toRead,		/* Maximum number of characters to store, or
				 * -1 to read all available data (up to EOF or
    Tcl_Size toRead,		/* Maximum number of characters to store, or
				 * TCL_INDEX_NONE to read all available data (up to EOF or
				 * when channel blocks). */
    int appendFlag)		/* If non-zero, data read from the channel
				 * will be appended to the object. Otherwise,
				 * the data will replace the existing contents
				 * of the object. */
{
    Channel *chanPtr = (Channel *) chan;
5767
5768
5769
5770
5771
5772
5773
5774

5775
5776
5777

5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792

5793
5794
5795
5796
5797
5798
5799
5800
5801

5802
5803
5804
5805
5806


5807

5808
5809
5810
5811
5812
5813
5814
5815

5816

5817
5818
5819
5820
5821
5822
5823
5824
5825



5826
5827
5828
5829
5830
5831
5832
5833
5834
5835

5836
5837
5838
5839
5840
5841
5842
5843
5844


5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860

5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874

5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
















5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896


5897
5898
5899
5900
5901
5902
5903
5904
5905

5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917













5918
5919
5920
5921
5922
5923
5924
5925


5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941

5942


5943
5944
5945

5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957

5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973

5974
5975
5976

5977












5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997

5998
5999
6000
6001
6002
6003
6004
5899
5900
5901
5902
5903
5904
5905

5906
5907
5908

5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923

5924
5925
5926
5927
5928
5929
5930
5931
5932

5933
5934
5935
5936


5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949

5950
5951
5952
5953
5954
5955




5956
5957
5958










5959









5960
5961

5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975

5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989

5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026


6027
6028
6029
6030
6031
6032
6033
6034
6035
6036

6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068


6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087

6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104

6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120

6121
6122
6123

6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156

6157
6158
6159
6160
6161
6162
6163
6164







-
+


-
+














-
+








-
+



-
-
+
+

+








+
-
+





-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
-














-
+













-
+










+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










-
-
+
+








-
+












+
+
+
+
+
+
+
+
+
+
+
+
+






-
-
+
+
















+
-
+
+



+











-
+















-
+


-
+

+
+
+
+
+
+
+
+
+
+
+
+



















-
+







    if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) {
	/*
	 * Update the notifier state so we don't block while there is still
	 * data in the buffers.
	 */

	UpdateInterest(chanPtr);
	return -1;
	return TCL_INDEX_NONE;
    }

    return DoReadChars(chanPtr, objPtr, toRead, appendFlag);
    return DoReadChars(chanPtr, objPtr, toRead, 0, appendFlag);
}
/*
 *---------------------------------------------------------------------------
 *
 * DoReadChars --
 *
 *	Reads from the channel until the requested number of characters have
 *	been seen, EOF is seen, or the channel would block. EOL and EOF
 *	translation is done. If reading binary data, the raw bytes are wrapped
 *	in a Tcl byte array object. Otherwise, the raw bytes are converted to
 *	UTF-8 using the channel's current encoding and stored in a Tcl string
 *	object.
 *
 * Results:
 *	The number of characters read, or -1 on error. Use Tcl_GetErrno() to
 *	The number of characters read, or TCL_INDEX_NONE on error. Use Tcl_GetErrno() to
 *	retrieve the error code for the error that occurred.
 *
 * Side effects:
 *	May cause input to be buffered.
 *
 *---------------------------------------------------------------------------
 */

static int
static Tcl_Size
DoReadChars(
    Channel *chanPtr,		/* The channel to read. */
    Tcl_Obj *objPtr,		/* Input data is stored in this object. */
    size_t toRead,			/* Maximum number of characters to store, or
				 * -1 to read all available data (up to EOF or
    Tcl_Size toRead,		/* Maximum number of characters to store, or
				 * TCL_INDEX_NONE to read all available data (up to EOF or
				 * when channel blocks). */
    int allowShortReads,	/* Allow half-blocking (pipes,sockets) */
    int appendFlag)		/* If non-zero, data read from the channel
				 * will be appended to the object. Otherwise,
				 * the data will replace the existing contents
				 * of the object. */
{
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    ChannelBuffer *bufPtr;
    Tcl_Size copied;
    int copied, copiedNow, result;
    int result;
    Tcl_Encoding encoding = statePtr->encoding;
    int binaryMode;
#define UTF_EXPANSION_FACTOR	1024
    int factor = UTF_EXPANSION_FACTOR;

    binaryMode = (encoding == NULL)
	    && (statePtr->inputTranslation == TCL_TRANSLATE_LF)
	    && (statePtr->inEofChar == '\0');

    if (GotFlag(statePtr, CHANNEL_ENCODING_ERROR)) {
	ResetFlag(statePtr, CHANNEL_EOF|CHANNEL_ENCODING_ERROR);
	/* TODO: UpdateInterest not needed here? */
    if (appendFlag) {
	if (binaryMode && (NULL == TclGetBytesFromObj(NULL, objPtr, NULL))) {
	    binaryMode = 0;
	}
    } else {
	if (binaryMode) {
	    Tcl_SetByteArrayLength(objPtr, 0);
	} else {
	    Tcl_SetObjLength(objPtr, 0);

	UpdateInterest(chanPtr);
	    /*
	     * We're going to access objPtr->bytes directly, so we must ensure
	     * that this is actually a string object (otherwise it might have
	     * been pure Unicode).
	     *
	     * Probably not needed anymore.
	     */

	    TclGetString(objPtr);
	Tcl_SetErrno(EILSEQ);
	return -1;
	}
    }

    /*
     * Early out when next read will see eofchar.
     *
     * NOTE: See DoRead for argument that it's a bug (one we're keeping) to
     * have this escape before the one for zero-char read request.
     */

    if (GotFlag(statePtr, CHANNEL_STICKY_EOF)) {
	SetFlag(statePtr, CHANNEL_EOF);
	assert(statePtr->inputEncodingFlags & TCL_ENCODING_END);
	assert(!GotFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR));

	/* TODO: We don't need this call? */
	/* TODO: UpdateInterest not needed here? */
	UpdateInterest(chanPtr);
	return 0;
    }

    /*
     * Special handling for zero-char read request.
     */
    if (toRead == 0) {
	if (GotFlag(statePtr, CHANNEL_EOF)) {
	    statePtr->inputEncodingFlags |= TCL_ENCODING_START;
	}
	ResetFlag(statePtr, CHANNEL_BLOCKED|CHANNEL_EOF);
	statePtr->inputEncodingFlags &= ~TCL_ENCODING_END;
	/* TODO: We don't need this call? */
	/* TODO: UpdateInterest not needed here? */
	UpdateInterest(chanPtr);
	return 0;
    }

    /*
     * This operation should occur at the top of a channel stack.
     */

    chanPtr = statePtr->topChanPtr;
    TclChannelPreserve((Tcl_Channel)chanPtr);

    binaryMode = (encoding == GetBinaryEncoding())
	    && (statePtr->inputTranslation == TCL_TRANSLATE_LF)
	    && (statePtr->inEofChar == '\0');

    if (appendFlag) {
	if (binaryMode && (NULL == Tcl_GetBytesFromObj(NULL, objPtr, (Tcl_Size *)NULL))) {
	    binaryMode = 0;
	}
    } else {
	if (binaryMode) {
	    Tcl_SetByteArrayLength(objPtr, 0);
	} else {
	    Tcl_SetObjLength(objPtr, 0);
	}
    }

    /*
     * Must clear the BLOCKED|EOF flags here since we check before reading.
     */

    if (GotFlag(statePtr, CHANNEL_EOF)) {
	statePtr->inputEncodingFlags |= TCL_ENCODING_START;
    }
    ResetFlag(statePtr, CHANNEL_BLOCKED|CHANNEL_EOF);
    statePtr->inputEncodingFlags &= ~TCL_ENCODING_END;
    for (copied = 0; toRead > 0; ) {
	copiedNow = -1;
    for (copied = 0; toRead != 0 ; ) {
	int copiedNow = -1;
	if (statePtr->inQueueHead != NULL) {
	    if (binaryMode) {
		copiedNow = ReadBytes(statePtr, objPtr, toRead);
	    } else {
		copiedNow = ReadChars(statePtr, objPtr, toRead, &factor);
	    }

	    /*
	     * If the current buffer is empty recycle it.
	     * Recycle current buffer if empty.
	     */

	    bufPtr = statePtr->inQueueHead;
	    if (IsBufferEmpty(bufPtr)) {
		ChannelBuffer *nextPtr = bufPtr->nextPtr;

		RecycleBuffer(statePtr, bufPtr, 0);
		statePtr->inQueueHead = nextPtr;
		if (nextPtr == NULL) {
		    statePtr->inQueueTail = NULL;
		}
	    }

	    /*
	     * If CHANNEL_ENCODING_ERROR and CHANNEL_STICKY_EOF are both set,
	     * then CHANNEL_ENCODING_ERROR was caused by data that occurred
	     * after the EOF character was encountered, so it doesn't count as
	     * a real error.
	     */

	    if (GotFlag(statePtr, CHANNEL_ENCODING_ERROR)
		    && !GotFlag(statePtr, CHANNEL_STICKY_EOF)
		    && (!GotFlag(statePtr, CHANNEL_NONBLOCKING))) {
		goto finish;
	    }
	}

	if (copiedNow < 0) {
	    if (GotFlag(statePtr, CHANNEL_EOF)) {
		break;
	    }
	    if (GotFlag(statePtr, CHANNEL_NONBLOCKING|CHANNEL_BLOCKED)
		    == (CHANNEL_NONBLOCKING|CHANNEL_BLOCKED)) {
	    if ((GotFlag(statePtr, CHANNEL_NONBLOCKING) || allowShortReads)
		    && GotFlag(statePtr, CHANNEL_BLOCKED)) {
		break;
	    }
	    result = GetInput(chanPtr);
	    if (chanPtr != statePtr->topChanPtr) {
		TclChannelRelease((Tcl_Channel)chanPtr);
		chanPtr = statePtr->topChanPtr;
		TclChannelPreserve((Tcl_Channel)chanPtr);
	    }
	    if (result != 0) {
		if (!GotFlag(statePtr, CHANNEL_BLOCKED)) {
		    copied = -1;
		}
		break;
	    }
	} else {
	    copied += copiedNow;
	    if (toRead != TCL_INDEX_NONE) {
	    toRead -= copiedNow;
		toRead -= copiedNow; /* Only decr if not reading whole file */
	    }
	}
    }

finish:
    /*
     * Failure to fill a channel buffer may have left channel reporting a
     * "blocked" state, but so long as we fulfilled the request here, the
     * caller does not consider us blocked.
     */

    if (toRead == 0) {
	ResetFlag(statePtr, CHANNEL_BLOCKED);
    }

    /*
     * Regenerate the top channel, in case it was changed due to
     * Regenerate chanPtr in case it was changed due to
     * self-modifying reflected transforms.
     */

    if (chanPtr != statePtr->topChanPtr) {
	TclChannelRelease((Tcl_Channel)chanPtr);
	chanPtr = statePtr->topChanPtr;
	TclChannelPreserve((Tcl_Channel)chanPtr);
    }

    /*
     * Update the notifier state so we don't block while there is still data
     * in the buffers.
     */

    assert(!GotFlag(statePtr, CHANNEL_EOF)
	    || GotFlag(statePtr, CHANNEL_STICKY_EOF)
	    || GotFlag(statePtr, CHANNEL_STICKY_EOF|CHANNEL_ENCODING_ERROR)
	    || Tcl_InputBuffered((Tcl_Channel)chanPtr) == 0);
    assert(!(GotFlag(statePtr, CHANNEL_EOF|CHANNEL_BLOCKED)
            == (CHANNEL_EOF|CHANNEL_BLOCKED)));
	    == (CHANNEL_EOF|CHANNEL_BLOCKED)));
    UpdateInterest(chanPtr);

    /* This must comes after UpdateInterest(), which may set errno */
    if (GotFlag(statePtr, CHANNEL_ENCODING_ERROR)
	    && (!copied || !GotFlag(statePtr, CHANNEL_NONBLOCKING))) {
	/* Channel either is blocking or is nonblocking with no data
	 * succesfully red before the error.  Return an error so that callers
	 * like [read] can also return an error.
	*/
	ResetFlag(statePtr, CHANNEL_EOF|CHANNEL_ENCODING_ERROR);
	Tcl_SetErrno(EILSEQ);
	copied = -1;
    }
    TclChannelRelease((Tcl_Channel)chanPtr);
    return copied;
}

/*
 *---------------------------------------------------------------------------
 *
 * ReadBytes --
 *
 *	Reads from the channel until the requested number of bytes have been
 *	seen, EOF is seen, or the channel would block. Bytes from the channel
 *	are stored in objPtr as a ByteArray object. EOL and EOF translation
 *	are done.
 *
 *	'bytesToRead' can safely be a very large number because space is only
 *	allocated to hold data read from the channel as needed.
 *
 * Results:
 *	The return value is the number of bytes appended to the object, or
 *	-1 to indicate that zero bytes were read due to an EOF.
 *	TCL_INDEX_NONE to indicate that zero bytes were read due to an EOF.
 *
 * Side effects:
 *	The storage of bytes in objPtr can cause (re-)allocation of memory.
 *
 *---------------------------------------------------------------------------
 */

6059
6060
6061
6062
6063
6064
6065
6066

6067
6068
6069
6070
6071
6072

6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083

6084
6085
6086
6087
6088
6089
6090

6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110



6111
6112


6113
6114

6115
6116
6117

6118
6119
6120
6121
6122
6123
6124
6219
6220
6221
6222
6223
6224
6225

6226
6227
6228
6229
6230
6231

6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242

6243

6244
6245
6246
6247
6248

6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272


6273
6274
6275

6276
6277
6278

6279
6280
6281
6282
6283
6284
6285
6286







-
+





-
+










-
+
-





-
+




















+
+
+
-
-
+
+

-
+


-
+







ReadChars(
    ChannelState *statePtr,	/* State of channel to read. */
    Tcl_Obj *objPtr,		/* Input data is appended to this object.
				 * objPtr->length is how much space has been
				 * allocated to hold data, not how many bytes
				 * of data have been stored in the object. */
    int charsToRead,		/* Maximum number of characters to store, or
				 * -1 to get all available characters.
				 * TCL_INDEX_NONE to get all available characters.
				 * Characters are obtained from the first
				 * buffer in the queue -- even if this number
				 * is larger than the number of characters
				 * available in the first buffer, only the
				 * characters from the first buffer are
				 * returned. The execption is when there is
				 * returned. The exception is when there is
				 * not any complete character in the first
				 * buffer.  In that case, a recursive call
				 * effectively obtains chars from the
				 * second buffer. */
    int *factorPtr)		/* On input, contains a guess of how many
				 * bytes need to be allocated to hold the
				 * result of converting N source bytes to
				 * UTF-8. On output, contains another guess
				 * based on the data seen so far. */
{
    Tcl_Encoding encoding = statePtr->encoding? statePtr->encoding
    Tcl_Encoding encoding = statePtr->encoding;
	    : GetBinaryEncoding();
    Tcl_EncodingState savedState = statePtr->inputEncodingState;
    ChannelBuffer *bufPtr = statePtr->inQueueHead;
    int savedIEFlags = statePtr->inputEncodingFlags;
    int savedFlags = statePtr->flags;
    char *dst, *src = RemovePoint(bufPtr);
    size_t numBytes;
    Tcl_Size numBytes;
    int srcLen = BytesLeft(bufPtr);

    /*
     * One src byte can yield at most one character.  So when the number of
     * src bytes we plan to read is less than the limit on character count to
     * be read, clearly we will remain within that limit, and we can use the
     * value of "srcLen" as a tighter limit for sizing receiving buffers.
     */

    int toRead = ((charsToRead<0)||(charsToRead > srcLen)) ? srcLen : charsToRead;

    /*
     * 'factor' is how much we guess that the bytes in the source buffer will
     * expand when converted to UTF-8 chars. This guess comes from analyzing
     * how many characters were produced by the previous pass.
     */

    int factor = *factorPtr;
    int dstLimit = TCL_UTF_MAX - 1 + toRead * factor / UTF_EXPANSION_FACTOR;

    if (dstLimit <= 0) {
	dstLimit = INT_MAX; /* avoid overflow */
    }
    (void) TclGetStringFromObj(objPtr, &numBytes);
    Tcl_AppendToObj(objPtr, NULL, dstLimit);
    (void)TclGetStringFromObj(objPtr, &numBytes);
    TclAppendUtfToUtf(objPtr, NULL, dstLimit);
    if (toRead == srcLen) {
	size_t size;
	Tcl_Size size;

	dst = TclGetStringStorage(objPtr, &size) + numBytes;
	dstLimit = size - numBytes;
	dstLimit = (size - numBytes) > INT_MAX ? INT_MAX : (size - numBytes);
    } else {
	dst = TclGetString(objPtr) + numBytes;
    }

    /*
     * This routine is burdened with satisfying several constraints. It cannot
     * append more than 'charsToRead` chars onto objPtr. This is measured
6159
6160
6161
6162
6163
6164
6165






6166
6167
6168
6169
6170
6171
6172
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340







+
+
+
+
+
+








	assert(bufPtr->nextPtr == NULL || BytesLeft(bufPtr->nextPtr) == 0
		|| (statePtr->inputEncodingFlags & TCL_ENCODING_END) == 0);

	code = Tcl_ExternalToUtf(NULL, encoding, src, srcLen,
		flags, &statePtr->inputEncodingState,
		dst, dstLimit, &srcRead, &dstDecoded, &numChars);

	if (code == TCL_CONVERT_UNKNOWN || code == TCL_CONVERT_SYNTAX
		|| (code == TCL_CONVERT_MULTIBYTE && GotFlag(statePtr, CHANNEL_EOF))) {
	    SetFlag(statePtr, CHANNEL_ENCODING_ERROR);
	    code = TCL_OK;
	}

	/*
	 * Perform the translation transformation in place.  Read no more than
	 * the dstDecoded bytes the encoding transformation actually produced.
	 * Capture the number of bytes written in dstWrote. Capture the number
	 * of bytes actually consumed in dstRead.
	 */
6187
6188
6189
6190
6191
6192
6193
6194

6195
6196
6197
6198
6199

6200
6201
6202
6203
6204
6205
6206
6355
6356
6357
6358
6359
6360
6361

6362
6363
6364
6365
6366

6367
6368
6369
6370
6371
6372
6373
6374







-
+




-
+







		 *    we saw it and stopped translating at that point.
		 *
		 * NOTE the bizarre spec of TranslateInputEOL in this case.
		 * Clearly the eof char had to be read in order to account for
		 * the stopping, but the value of dstRead does not include it.
		 *
		 * Also rather bizarre, our caller can only notice an EOF
		 * condition if we return the value -1 as the number of chars
		 * condition if we return the value TCL_INDEX_NONE as the number of chars
		 * read.  This forces us to perform a 2-call dance where the
		 * first call can read all the chars up to the eof char, and
		 * the second call is solely for consuming the encoded eof
		 * char then pointed at by src so that we can return that
		 * magic -1 value.  This seems really wasteful, especially
		 * magic TCL_INDEX_NONE value.  This seems really wasteful, especially
		 * since the first decoding pass of each call is likely to
		 * decode many bytes beyond that eof char that's all we care
		 * about.
		 */

		if (dstRead == 0) {
		    /*
6295
6296
6297
6298
6299
6300
6301
6302

6303
6304
6305
6306
6307
6308
6309
6463
6464
6465
6466
6467
6468
6469

6470
6471
6472
6473
6474
6475
6476
6477







-
+








		    statePtr->inputEncodingFlags &= ~TCL_ENCODING_START;

		    Tcl_SetObjLength(objPtr, numBytes + 1);
		    return 1;
		}

	    } else if (statePtr->flags & CHANNEL_EOF) {
	    } else if (GotFlag(statePtr, CHANNEL_EOF)) {
		/*
		 * The bare \r is the only char and we will never read a
		 * subsequent char to make the determination.
		 */

		dst[0] = '\r';
		bufPtr->nextRemoved = bufPtr->nextAdded;
6398
6399
6400
6401
6402
6403
6404
6405

6406
6407
6408
6409
6410
6411
6412
6566
6567
6568
6569
6570
6571
6572

6573
6574
6575
6576
6577
6578
6579
6580







-
+







	     *
	     * Note that the BUFFER_PADDING (See AllocChannelBuffer) is used
	     * to prevent exactly this situation. I.e. it should never happen.
	     * Therefore it is ok to panic should it happen despite the
	     * precautions.
	     */

	    if (nextPtr->nextRemoved - srcLen < 0) {
	    if (nextPtr->nextRemoved < srcLen) {
		Tcl_Panic("Buffer Underflow, BUFFER_PADDING not enough");
	    }

	    nextPtr->nextRemoved -= srcLen;
	    memcpy(RemovePoint(nextPtr), src, srcLen);
	    RecycleBuffer(statePtr, bufPtr, 0);
	    statePtr->inQueueHead = nextPtr;
6530
6531
6532
6533
6534
6535
6536
6537
6538




6539
6540
6541
6542
6543


6544
6545
6546
6547
6548
6549
6550


6551
6552
6553


6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569





6570
6571
6572
6573

6574
6575
6576
6577
6578
6579




6580
6581
6582
6583


6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602



6603
6604
6605
6606
6607

6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620

6621
6622
6623
6624
6625
6626
6627
6628

6629
6630
6631
6632

6633
6634
6635
6636
6637
6638
6639
6698
6699
6700
6701
6702
6703
6704


6705
6706
6707
6708
6709
6710
6711
6712

6713
6714
6715
6716
6717
6718
6719
6720

6721
6722
6723
6724

6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740


6741
6742
6743
6744
6745
6746
6747
6748

6749
6750
6751
6752
6753


6754
6755
6756
6757
6758
6759
6760

6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788

6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801

6802
6803
6804
6805
6806
6807
6808
6809

6810
6811
6812
6813

6814
6815
6816
6817
6818
6819
6820
6821







-
-
+
+
+
+




-
+
+






-
+
+


-
+
+














-
-
+
+
+
+
+



-
+




-
-
+
+
+
+



-
+
+



















+
+
+




-
+












-
+







-
+



-
+







	char *dst = dstStart;
	int lesser = (dstLen < srcLen) ? dstLen : srcLen;

	while ((crFound = (const char *)memchr(src, '\r', lesser))) {
	    int numBytes = crFound - src;
	    memmove(dst, src, numBytes);

	    dst += numBytes; dstLen -= numBytes;
	    src += numBytes; srcLen -= numBytes;
	    dst += numBytes;
	    dstLen -= numBytes;
	    src += numBytes;
	    srcLen -= numBytes;
	    if (srcLen == 1) {
		/* valid src bytes end in \r */
		if (eof) {
		    *dst++ = '\r';
		    src++; srcLen--;
		    src++;
		    srcLen--;
		} else {
		    lesser = 0;
		    break;
		}
	    } else if (src[1] == '\n') {
		*dst++ = '\n';
		src += 2; srcLen -= 2;
		src += 2;
		srcLen -= 2;
	    } else {
		*dst++ = '\r';
		src++; srcLen--;
		src++;
		srcLen--;
	    }
	    dstLen--;
	    lesser = (dstLen < srcLen) ? dstLen : srcLen;
	}
	memmove(dst, src, lesser);
	srcLen = src + lesser - srcStart;
	dstLen = dst + lesser - dstStart;
	break;
    }
    case TCL_TRANSLATE_AUTO: {
	const char *crFound, *src = srcStart;
	char *dst = dstStart;
	int lesser;

	if ((statePtr->flags & INPUT_SAW_CR) && srcLen) {
	    if (*src == '\n') { src++; srcLen--; }
	if (GotFlag(statePtr, INPUT_SAW_CR) && srcLen) {
	    if (*src == '\n') {
		src++;
		srcLen--;
	    }
	    ResetFlag(statePtr, INPUT_SAW_CR);
	}
	lesser = (dstLen < srcLen) ? dstLen : srcLen;
	while ((crFound = (const char *)memchr(src, '\r', lesser))) {
	while ((crFound = (const char *) memchr(src, '\r', lesser))) {
	    int numBytes = crFound - src;
	    memmove(dst, src, numBytes);

	    dst[numBytes] = '\n';
	    dst += numBytes + 1; dstLen -= numBytes + 1;
	    src += numBytes + 1; srcLen -= numBytes + 1;
	    dst += numBytes + 1;
	    dstLen -= numBytes + 1;
	    src += numBytes + 1;
	    srcLen -= numBytes + 1;
	    if (srcLen == 0) {
		SetFlag(statePtr, INPUT_SAW_CR);
	    } else if (*src == '\n') {
		src++; srcLen--;
		src++;
		srcLen--;
	    }
	    lesser = (dstLen < srcLen) ? dstLen : srcLen;
	}
	memmove(dst, src, lesser);
	srcLen = src + lesser - srcStart;
	dstLen = dst + lesser - dstStart;
	break;
    }
    default:
	Tcl_Panic("unknown input translation %d", statePtr->inputTranslation);
    }
    *dstLenPtr = dstLen;
    *srcLenPtr = srcLen;

    if (srcStart + srcLen == eof) {
	/*
	 * EOF character was seen in EOL translated range. Leave current file
	 * position pointing at the EOF character, but don't store the EOF
	 * character in the output string.
	 *
	 * If CHANNEL_ENCODING_ERROR is set, it can only be because of data
	 * encountered after the EOF character, so it is nonsense.  Unset it.
	 */

	SetFlag(statePtr, CHANNEL_EOF | CHANNEL_STICKY_EOF);
	statePtr->inputEncodingFlags |= TCL_ENCODING_END;
	ResetFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR);
	ResetFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR|CHANNEL_ENCODING_ERROR);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Ungets --
 *
 *	Causes the supplied string to be added to the input queue of the
 *	channel, at either the head or tail of the queue.
 *
 * Results:
 *	The number of bytes stored in the channel, or TCL_IO_FAILURE on error.
 *	The number of bytes stored in the channel, or TCL_INDEX_NONE on error.
 *
 * Side effects:
 *	Adds input to the input queue of a channel.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
Tcl_Ungets(
    Tcl_Channel chan,		/* The channel for which to add the input. */
    const char *str,		/* The input itself. */
    size_t len,			/* The length of the input. */
    Tcl_Size len,			/* The length of the input. */
    int atEnd)			/* If non-zero, add at end of queue; otherwise
				 * add at head of queue. */
{
    Channel *chanPtr;		/* The real IO channel. */
    ChannelState *statePtr;	/* State of actual channel. */
    ChannelBuffer *bufPtr;	/* Buffer to contain the data. */
    int flags;
6649
6650
6651
6652
6653
6654
6655
6656

6657
6658
6659
6660
6661
6662
6663
6831
6832
6833
6834
6835
6836
6837

6838
6839
6840
6841
6842
6843
6844
6845







-
+








    /*
     * CheckChannelErrors clears too many flag bits in this one case.
     */

    flags = statePtr->flags;
    if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) {
	len = TCL_IO_FAILURE;
	len = TCL_INDEX_NONE;
	goto done;
    }
    statePtr->flags = flags;

    /*
     * Clear the EOF flags, and clear the BLOCKED bit.
     */
6887
6888
6889
6890
6891
6892
6893
6894

6895
6896
6897
6898
6899

6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910

6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923

6924
6925
6926
6927
6928

6929
6930
6931
6932




6933
6934
6935
6936
6937
6938
6939
7069
7070
7071
7072
7073
7074
7075

7076
7077
7078
7079
7080

7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091

7092
7093
7094
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112




7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123







-
+




-
+










-
+













+





+
-
-
-
-
+
+
+
+







	bufPtr = statePtr->saveInBufPtr;
	statePtr->saveInBufPtr = NULL;

	/*
	 * Check the actual buffersize against the requested buffersize.
	 * Saved buffers of the wrong size are squashed. This is done to honor
	 * dynamic changes of the buffersize made by the user.
         *
	 *
	 * TODO: Tests to cover this.
	 */

	if ((bufPtr != NULL)
		&& (bufPtr->bufLength - BUFFER_PADDING != statePtr->bufSize)) {
		&& (bufPtr->bufLength != statePtr->bufSize + BUFFER_PADDING)) {
	    ReleaseChannelBuffer(bufPtr);
	    bufPtr = NULL;
	}

	if (bufPtr == NULL) {
	    bufPtr = AllocChannelBuffer(statePtr->bufSize);
	}
	bufPtr->nextPtr = NULL;

	toRead = SpaceLeft(bufPtr);
	assert(toRead == statePtr->bufSize);
	assert((Tcl_Size)toRead == statePtr->bufSize);

	if (statePtr->inQueueTail == NULL) {
	    statePtr->inQueueHead = bufPtr;
	} else {
	    statePtr->inQueueTail->nextPtr = bufPtr;
	}
	statePtr->inQueueTail = bufPtr;
    } else {
	toRead = SpaceLeft(bufPtr);
    }

    PreserveChannelBuffer(bufPtr);
    nread = ChanRead(chanPtr, InsertPoint(bufPtr), toRead);
    ReleaseChannelBuffer(bufPtr);

    if (nread < 0) {
	result = Tcl_GetErrno();
    } else {
	result = 0;
	if (statePtr->inQueueTail != NULL) {
	bufPtr->nextAdded += nread;
    }

    ReleaseChannelBuffer(bufPtr);
	    statePtr->inQueueTail->nextAdded += nread;
	}
    }

    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Seek --
6947
6948
6949
6950
6951
6952
6953
6954

6955
6956
6957

6958
6959
6960
6961
6962
6963
6964
6965
6966
6967

6968
6969
6970
6971
6972
6973
6974
7131
7132
7133
7134
7135
7136
7137

7138
7139
7140

7141
7142
7143
7144
7145
7146
7147
7148
7149
7150

7151
7152
7153
7154
7155
7156
7157
7158







-
+


-
+









-
+







 *
 * Side effects:
 *	May flush output on the channel. May discard queued input.
 *
 *----------------------------------------------------------------------
 */

Tcl_WideInt
long long
Tcl_Seek(
    Tcl_Channel chan,		/* The channel on which to seek. */
    Tcl_WideInt offset,		/* Offset to seek to. */
    long long offset,		/* Offset to seek to. */
    int mode)			/* Relative to which location to seek? */
{
    Channel *chanPtr = (Channel *) chan;
				/* The real IO channel. */
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    int inputBuffered, outputBuffered;
				/* # bytes held in buffers. */
    int result;			/* Of device driver operations. */
    Tcl_WideInt curPos;		/* Position on the device. */
    long long curPos;		/* Position on the device. */
    int wasAsync;		/* Was the channel nonblocking before the seek
				 * operation? If so, must restore to
				 * non-blocking mode after the seek. */

    if (CheckChannelErrors(statePtr, TCL_WRITABLE | TCL_READABLE) != 0) {
	return -1;
    }
6991
6992
6993
6994
6995
6996
6997
6998

6999
7000
7001
7002
7003
7004
7005
7006
7175
7176
7177
7178
7179
7180
7181

7182

7183
7184
7185
7186
7187
7188
7189







-
+
-







    chanPtr = statePtr->topChanPtr;

    /*
     * Disallow seek on channels whose type does not have a seek procedure
     * defined. This means that the channel does not support seeking.
     */

    if ((Tcl_ChannelWideSeekProc(chanPtr->typePtr) == NULL)
    if (Tcl_ChannelWideSeekProc(chanPtr->typePtr) == NULL) {
    ) {
	Tcl_SetErrno(EINVAL);
	return -1;
    }

    /*
     * Compute how much input and output is buffered. If both input and output
     * is buffered, cannot compute the current position.
7117
7118
7119
7120
7121
7122
7123
7124

7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135

7136
7137
7138
7139
7140
7141
7142
7300
7301
7302
7303
7304
7305
7306

7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317

7318
7319
7320
7321
7322
7323
7324
7325







-
+










-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_WideInt
long long
Tcl_Tell(
    Tcl_Channel chan)		/* The channel to return pos for. */
{
    Channel *chanPtr = (Channel *) chan;
				/* The real IO channel. */
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    int inputBuffered, outputBuffered;
				/* # bytes held in buffers. */
    int result;			/* Of calling device driver. */
    Tcl_WideInt curPos;		/* Position on device. */
    long long curPos;		/* Position on device. */

    if (CheckChannelErrors(statePtr, TCL_WRITABLE | TCL_READABLE) != 0) {
	return -1;
    }

    /*
     * Disallow tell on dead channels -- channels that have been closed but
7156
7157
7158
7159
7160
7161
7162
7163

7164
7165
7166
7167
7168
7169
7170
7171
7339
7340
7341
7342
7343
7344
7345

7346

7347
7348
7349
7350
7351
7352
7353







-
+
-







    chanPtr = statePtr->topChanPtr;

    /*
     * Disallow tell on channels whose type does not have a seek procedure
     * defined. This means that the channel does not support seeking.
     */

    if ((Tcl_ChannelWideSeekProc(chanPtr->typePtr) == NULL)
    if (Tcl_ChannelWideSeekProc(chanPtr->typePtr) == NULL) {
    ) {
	Tcl_SetErrno(EINVAL);
	return -1;
    }

    /*
     * Compute how much input and output is buffered. If both input and output
     * is buffered, cannot compute the current position.
7209
7210
7211
7212
7213
7214
7215
7216

7217
7218
7219
7220
7221
7222
7223
7391
7392
7393
7394
7395
7396
7397

7398
7399
7400
7401
7402
7403
7404
7405







-
+







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

int
Tcl_TruncateChannel(
    Tcl_Channel chan,		/* Channel to truncate. */
    Tcl_WideInt length)		/* Length to truncate it to. */
    long long length)		/* Length to truncate it to. */
{
    Channel *chanPtr = (Channel *) chan;
    Tcl_DriverTruncateProc *truncateProc =
	    Tcl_ChannelTruncateProc(chanPtr->typePtr);
    int result;

    if (truncateProc == NULL) {
7238
7239
7240
7241
7242
7243
7244
7245

7246
7247
7248
7249
7250
7251

7252
7253
7254
7255
7256
7257
7258
7420
7421
7422
7423
7424
7425
7426

7427
7428
7429
7430
7431
7432

7433
7434
7435
7436
7437
7438
7439
7440







-
+





-
+








	Tcl_SetErrno(EINVAL);
	return TCL_ERROR;
    }

    /*
     * Seek first to force a total flush of all pending buffers and ditch any
     * pre-read input data.
     * preread input data.
     */

    WillWrite(chanPtr);

    if (WillRead(chanPtr) == -1) {
        return TCL_ERROR;
	return TCL_ERROR;
    }

    /*
     * We're all flushed to disk now and we also don't have any unfortunate
     * input baggage around either; can truncate with impunity.
     */

7298
7299
7300
7301
7302
7303
7304
7305

7306
7307
7308
7309
7310
7311
7312
7480
7481
7482
7483
7484
7485
7486

7487
7488
7489
7490
7491
7492
7493
7494







-
+








    if (statePtr->unreportedError != 0) {
	Tcl_SetErrno(statePtr->unreportedError);
	statePtr->unreportedError = 0;

	/*
	 * TIP #219, Tcl Channel Reflection API.
	 * Move a defered error message back into the channel bypass.
	 * Move a deferred error message back into the channel bypass.
	 */

	if (statePtr->chanMsg != NULL) {
	    TclDecrRefCount(statePtr->chanMsg);
	}
	statePtr->chanMsg = statePtr->unreportedMsg;
	statePtr->unreportedMsg = NULL;
7323
7324
7325
7326
7327
7328
7329
7330

7331
7332
7333
7334
7335
7336
7337
7505
7506
7507
7508
7509
7510
7511

7512
7513
7514
7515
7516
7517
7518
7519







-
+







	return -1;
    }

    /*
     * Fail if the channel is not opened for desired operation.
     */

    if ((statePtr->flags & direction) == 0) {
    if (GotFlag(statePtr, direction) == 0) {
	Tcl_SetErrno(EACCES);
	return -1;
    }

    /*
     * Fail if the channel is in the middle of a background copy.
     *
7351
7352
7353
7354
7355
7356
7357




























7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377



7378
7379


























7380
7381
7382
7383
7384
7385
7386
7533
7534
7535
7536
7537
7538
7539
7540
7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




















+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TclChanIsBinary --
 *
 *	Returns 1 if the channel is a binary channel, 0 otherwise.
 *
 * Results:
 *	1 or 0, always.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclChanIsBinary(
    Tcl_Channel chan)		/* Does this channel have EOF? */
{
    ChannelState *statePtr = ((Channel *) chan)->state;
				/* State of real channel structure. */

    return ((statePtr->encoding == GetBinaryEncoding()) && !statePtr->inEofChar
	    && (!GotFlag(statePtr, TCL_READABLE) || (statePtr->inputTranslation == TCL_TRANSLATE_LF))
	    && (!GotFlag(statePtr, TCL_WRITABLE) || (statePtr->outputTranslation == TCL_TRANSLATE_LF)));
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Eof --
 *
 *	Returns 1 if the channel is at EOF, 0 otherwise.
 *
 * Results:
 *	1 or 0, always.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_Eof(
    Tcl_Channel chan)		/* Does this channel have EOF? */
{
    ChannelState *statePtr = ((Channel *) chan)->state;
				/* State of real channel structure. */

    if (GotFlag(statePtr, CHANNEL_ENCODING_ERROR)) {
	return 0;
    }
    return GotFlag(statePtr, CHANNEL_EOF) ? 1 : 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TclChannelGetBlockingMode --
 *
 *	Returns 1 if the channel is in blocking mode (default), 0 otherwise.
 *
 * Results:
 *	1 or 0, always.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclChannelGetBlockingMode(
    Tcl_Channel chan)
{
    ChannelState *statePtr = ((Channel *) chan)->state;
				/* State of real channel structure. */

    return GotFlag(statePtr, CHANNEL_NONBLOCKING) ? 0 : 1;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_InputBlocked --
 *
 *	Returns 1 if input is blocked on this channel, 0 otherwise.
7433
7434
7435
7436
7437
7438
7439
7440

7441
7442
7443
7444
7445
7446
7447
7672
7673
7674
7675
7676
7677
7678

7679
7680
7681
7682
7683
7684
7685
7686







-
+








    for (bytesBuffered = 0, bufPtr = statePtr->inQueueHead; bufPtr != NULL;
	    bufPtr = bufPtr->nextPtr) {
	bytesBuffered += BytesLeft(bufPtr);
    }

    /*
     * Don't forget the bytes in the topmost pushback area.
     * Remember the bytes in the topmost pushback area.
     */

    for (bufPtr = statePtr->topChanPtr->inQueueHead; bufPtr != NULL;
	    bufPtr = bufPtr->nextPtr) {
	bytesBuffered += BytesLeft(bufPtr);
    }

7541
7542
7543
7544
7545
7546
7547
7548

7549
7550
7551
7552
7553
7554
7555
7780
7781
7782
7783
7784
7785
7786

7787
7788
7789
7790
7791
7792
7793
7794







-
+







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

void
Tcl_SetChannelBufferSize(
    Tcl_Channel chan,		/* The channel whose buffer size to set. */
    int sz)			/* The size to set. */
    Tcl_Size sz)			/* The size to set. */
{
    ChannelState *statePtr;	/* State of real channel structure. */

    /*
     * Clip the buffer size to force it into the [1,1M] range
     */

7595
7596
7597
7598
7599
7600
7601
7602

7603
7604
7605
7606
7607
7608
7609
7834
7835
7836
7837
7838
7839
7840

7841
7842
7843
7844
7845
7846
7847
7848







-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_Size
Tcl_GetChannelBufferSize(
    Tcl_Channel chan)		/* The channel for which to find the buffer
				 * size. */
{
    ChannelState *statePtr = ((Channel *) chan)->state;
				/* State of real channel structure. */

7623
7624
7625
7626
7627
7628
7629
7630

7631
7632
7633
7634
7635
7636
7637
7862
7863
7864
7865
7866
7867
7868

7869
7870
7871
7872
7873
7874
7875
7876







-
+







 *
 * Results:
 *	TCL_ERROR.
 *
 * Side effects:

 *	An error message is generated in interp's result object to indicate
 *	that a command was invoked with the a bad option. The message has the
 *	that a command was invoked with a bad option. The message has the
 *	form:
 *		bad option "blah": should be one of
 *		<...generic options...>+<...specific options...>
 *	"blah" is the optionName argument and "<specific options>" is a space
 *	separated list of specific option words. The function takes good care
 *	of inserting minus signs before each option, commas after, and an "or"
 *	before the last option.
7645
7646
7647
7648
7649
7650
7651
7652

7653
7654

7655
7656

7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669
7670

7671
7672
7673
7674
7675
7676

7677
7678
7679
7680
7681
7682
7683
7884
7885
7886
7887
7888
7889
7890

7891
7892

7893
7894

7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908

7909
7910
7911
7912
7913
7914

7915
7916
7917
7918
7919
7920
7921
7922







-
+

-
+

-
+













-
+





-
+







    const char *optionName,	/* 'bad option' name */
    const char *optionList)	/* Specific options list to append to the
				 * standard generic options. Can be NULL for
				 * generic options only. */
{
    if (interp != NULL) {
	const char *genericopt =
		"blocking buffering buffersize encoding eofchar translation";
		"blocking buffering buffersize encoding eofchar profile translation";
	const char **argv;
	int argc, i;
	Tcl_Size argc, i;
	Tcl_DString ds;
        Tcl_Obj *errObj;
	Tcl_Obj *errObj;

	Tcl_DStringInit(&ds);
	Tcl_DStringAppend(&ds, genericopt, -1);
	if (optionList && (*optionList)) {
	    TclDStringAppendLiteral(&ds, " ");
	    Tcl_DStringAppend(&ds, optionList, -1);
	}
	if (Tcl_SplitList(interp, Tcl_DStringValue(&ds),
		&argc, &argv) != TCL_OK) {
	    Tcl_Panic("malformed option list in channel driver");
	}
	Tcl_ResetResult(interp);
	errObj = Tcl_ObjPrintf("bad option \"%s\": should be one of ",
                optionName ? optionName : "");
		optionName ? optionName : "");
	argc--;
	for (i = 0; i < argc; i++) {
	    Tcl_AppendPrintfToObj(errObj, "-%s, ", argv[i]);
	}
	Tcl_AppendPrintfToObj(errObj, "or -%s", argv[i]);
        Tcl_SetObjResult(interp, errObj);
	Tcl_SetObjResult(interp, errObj);
	Tcl_DStringFree(&ds);
	Tcl_Free((void *)argv);
    }
    Tcl_SetErrno(EINVAL);
    return TCL_ERROR;
}

7705
7706
7707
7708
7709
7710
7711
7712

7713
7714
7715
7716
7717
7718
7719
7944
7945
7946
7947
7948
7949
7950

7951
7952
7953
7954
7955
7956
7957
7958







-
+







Tcl_GetChannelOption(
    Tcl_Interp *interp,		/* For error reporting - can be NULL. */
    Tcl_Channel chan,		/* Channel on which to get option. */
    const char *optionName,	/* Option to get. */
    Tcl_DString *dsPtr)		/* Where to store value(s). */
{
    size_t len;			/* Length of optionName string. */
    char optionVal[128];	/* Buffer for sprintf. */
    char optionVal[128];	/* Buffer for snprintf. */
    Channel *chanPtr = (Channel *) chan;
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    int flags;

    /*
     * Disallow options on dead channels -- channels that have been closed but
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801


7802
7803
7804
7805
7806
7807

7808
7809
7810
7811

7812
7813

7814
7815

7816
7817

7818
7819
7820


7821
7822
7823


7824
7825

7826
7827
7828
7829
7830



7831
7832
7833


7834
7835





7836
7837
7838
7839
7840


7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
8029
8030
8031
8032
8033
8034
8035





8036
8037

8038
8039
8040
8041
8042
8043
8044
8045
8046

8047


8048
8049

8050


8051



8052
8053



8054
8055


8056





8057
8058
8059



8060
8061


8062
8063
8064
8065
8066





8067
8068





8069
8070
8071
8072
8073
8074
8075







-
-
-
-
-
+
+
-





+



-
+
-
-
+

-
+
-
-
+
-
-
-
+
+
-
-
-
+
+
-
-
+
-
-
-
-
-
+
+
+
-
-
-
+
+
-
-
+
+
+
+
+
-
-
-
-
-
+
+
-
-
-
-
-







	    return TCL_OK;
	}
    }
    if (len == 0 || HaveOpt(2, "-encoding")) {
	if (len == 0) {
	    Tcl_DStringAppendElement(dsPtr, "-encoding");
	}
	if (statePtr->encoding == NULL) {
	    Tcl_DStringAppendElement(dsPtr, "binary");
	} else {
	    Tcl_DStringAppendElement(dsPtr,
		    Tcl_GetEncodingName(statePtr->encoding));
	Tcl_DStringAppendElement(dsPtr,
	    Tcl_GetEncodingName(statePtr->encoding));
	}
	if (len > 0) {
	    return TCL_OK;
	}
    }
    if (len == 0 || HaveOpt(2, "-eofchar")) {
	char buf[4] = "";
	if (len == 0) {
	    Tcl_DStringAppendElement(dsPtr, "-eofchar");
	}
	if (((flags & (TCL_READABLE|TCL_WRITABLE)) ==
	if ((flags & TCL_READABLE) && (statePtr->inEofChar != 0)) {
		(TCL_READABLE|TCL_WRITABLE)) && (len == 0)) {
	    Tcl_DStringStartSublist(dsPtr);
	    snprintf(buf, sizeof(buf), "%c", statePtr->inEofChar);
	}
	if (flags & TCL_READABLE) {
	if (len > 0) {
	    if (statePtr->inEofChar == 0) {
		Tcl_DStringAppendElement(dsPtr, "");
		Tcl_DStringAppend(dsPtr, buf, -1);
	    } else {
		char buf[4];

	    return TCL_OK;
	}
		sprintf(buf, "%c", statePtr->inEofChar);
		Tcl_DStringAppendElement(dsPtr, buf);
	    }
	Tcl_DStringAppendElement(dsPtr, buf);
    }
	}
	if (flags & TCL_WRITABLE) {
    if (len == 0 || HaveOpt(1, "-profile")) {
	    if (statePtr->outEofChar == 0) {
		Tcl_DStringAppendElement(dsPtr, "");
	    } else {
		char buf[4];

	int profile;
	const char *profileName;
	if (len == 0) {
		sprintf(buf, "%c", statePtr->outEofChar);
		Tcl_DStringAppendElement(dsPtr, buf);
	    }
	    Tcl_DStringAppendElement(dsPtr, "-profile");
	}
	}
	if (!(flags & (TCL_READABLE|TCL_WRITABLE))) {
	/* Note currently input and output profiles are same */
	profile = ENCODING_PROFILE_GET(statePtr->inputEncodingFlags);
	profileName = TclEncodingProfileIdToName(interp, profile);
	if (profileName == NULL) {
	    return TCL_ERROR;
	    /*
	     * Not readable or writable (e.g. server socket)
	     */

	    Tcl_DStringAppendElement(dsPtr, "");
	}
	Tcl_DStringAppendElement(dsPtr, profileName);
	}
	if (((flags & (TCL_READABLE|TCL_WRITABLE)) ==
		(TCL_READABLE|TCL_WRITABLE)) && (len == 0)) {
	    Tcl_DStringEndSublist(dsPtr);
	}
	if (len > 0) {
	    return TCL_OK;
	}
    }
    if (len == 0 || HaveOpt(1, "-translation")) {
	if (len == 0) {
	    Tcl_DStringAppendElement(dsPtr, "-translation");
7938
7939
7940
7941
7942
7943
7944
7945
7946


7947
7948
7949
7950
7951
7952
7953
7954
7955
7956


7957
7958
7959
7960
7961
7962
7963
8161
8162
8163
8164
8165
8166
8167


8168
8169
8170
8171
8172
8173
8174
8175
8176
8177


8178
8179
8180
8181
8182
8183
8184
8185
8186







-
-
+
+








-
-
+
+







    const char *newValue)	/* New value for option. */
{
    Channel *chanPtr = (Channel *) chan;
				/* The real IO channel. */
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    size_t len;			/* Length of optionName string. */
    int argc;
    const char **argv;
    Tcl_Size argc;
    const char **argv = NULL;

    /*
     * If the channel is in the middle of a background copy, fail.
     */

    if (statePtr->csPtrR || statePtr->csPtrW) {
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
                    "unable to set channel options: background copy in"
                    " progress", -1));
		    "unable to set channel options: background copy in"
		    " progress", -1));
	}
	return TCL_ERROR;
    }

    /*
     * Disallow options on dead channels -- channels that have been closed but
     * not yet been deallocated. Such channels can be found if the exit
7998
7999
8000
8001
8002
8003
8004
8005
8006
8007
8008




8009
8010
8011
8012



8013








8014

8015
8016
8017
8018
8019
8020

8021
8022
8023








8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036

8037
8038
8039
8040
8041
8042
8043
8044

8045

8046
8047

8048

8049
8050
8051
8052
8053


8054
8055
8056
8057
8058
8059
8060

8061
8062

8063
8064

8065
8066
8067
8068
8069
8070
8071
8072
8073

8074
8075
8076
8077
8078
8079
8080
8081
8082


8083
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102









8103
8104
8105
8106
8107
8108
8109
8221
8222
8223
8224
8225
8226
8227




8228
8229
8230
8231
8232
8233
8234

8235
8236
8237
8238
8239
8240
8241
8242
8243
8244
8245
8246

8247
8248
8249
8250
8251
8252
8253
8254
8255


8256
8257
8258
8259
8260
8261
8262
8263
8264
8265
8266
8267
8268
8269
8270
8271
8272
8273
8274
8275

8276
8277
8278
8279
8280
8281
8282
8283
8284
8285
8286
8287
8288
8289
8290

8291
8292
8293
8294


8295
8296







8297


8298


8299







8300

8301



8302
8303
8304
8305


8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316
8317
8318
8319
8320
8321
8322
8323
8324
8325
8326
8327
8328
8329
8330
8331
8332
8333
8334
8335
8336
8337
8338
8339
8340
8341
8342
8343







-
-
-
-
+
+
+
+



-
+
+
+

+
+
+
+
+
+
+
+
-
+






+

-
-
+
+
+
+
+
+
+
+












-
+








+

+


+
-
+



-
-
+
+
-
-
-
-
-
-
-
+
-
-
+
-
-
+
-
-
-
-
-
-
-

-
+
-
-
-




-
-
+
+




















+
+
+
+
+
+
+
+
+







	    ResetFlag(statePtr, CHANNEL_UNBUFFERED);
	    SetFlag(statePtr, CHANNEL_LINEBUFFERED);
	} else if ((newValue[0] == 'n') &&
		(strncmp(newValue, "none", len) == 0)) {
	    ResetFlag(statePtr, CHANNEL_LINEBUFFERED);
	    SetFlag(statePtr, CHANNEL_UNBUFFERED);
	} else if (interp) {
            Tcl_SetObjResult(interp, Tcl_NewStringObj(
                    "bad value for -buffering: must be one of"
                    " full, line, or none", -1));
            return TCL_ERROR;
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "bad value for -buffering: must be one of"
		    " full, line, or none", -1));
	    return TCL_ERROR;
	}
	return TCL_OK;
    } else if (HaveOpt(7, "-buffersize")) {
	int newBufferSize;
	Tcl_WideInt newBufferSize;
	Tcl_Obj obj;
	int code;

	obj.refCount = 1;
	obj.bytes = (char *)newValue;
	obj.length = strlen(newValue);
	obj.typePtr = NULL;

	code = Tcl_GetWideIntFromObj(interp, &obj, &newBufferSize);
	TclFreeInternalRep(&obj);

	if (Tcl_GetInt(interp, newValue, &newBufferSize) == TCL_ERROR) {
	if (code == TCL_ERROR) {
	    return TCL_ERROR;
	}
	Tcl_SetChannelBufferSize(chan, newBufferSize);
	return TCL_OK;
    } else if (HaveOpt(2, "-encoding")) {
	Tcl_Encoding encoding;
	int profile;

	if ((newValue[0] == '\0') || (strcmp(newValue, "binary") == 0)) {
	    encoding = NULL;
	if ((newValue[0] == '\0') || !strcmp(newValue, "binary")) {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"unknown encoding \"%s\": No longer supported.\n"
			"\tplease use either \"-translation binary\" "
			"or \"-encoding iso8859-1\"", newValue));
	    }
	    return TCL_ERROR;
	} else {
	    encoding = Tcl_GetEncoding(interp, newValue);
	    if (encoding == NULL) {
		return TCL_ERROR;
	    }
	}

	/*
	 * When the channel has an escape sequence driven encoding such as
	 * iso2022, the terminated escape sequence must write to the buffer.
	 */

	if ((statePtr->encoding != NULL)
	if ((statePtr->encoding != GetBinaryEncoding())
		&& !(statePtr->outputEncodingFlags & TCL_ENCODING_START)
		&& (CheckChannelErrors(statePtr, TCL_WRITABLE) == 0)) {
	    statePtr->outputEncodingFlags |= TCL_ENCODING_END;
	    WriteChars(chanPtr, "", 0);
	}
	Tcl_FreeEncoding(statePtr->encoding);
	statePtr->encoding = encoding;
	statePtr->inputEncodingState = NULL;
	profile = ENCODING_PROFILE_GET(statePtr->inputEncodingFlags);
	statePtr->inputEncodingFlags = TCL_ENCODING_START;
	ENCODING_PROFILE_SET(statePtr->inputEncodingFlags, profile);
	statePtr->outputEncodingState = NULL;
	statePtr->outputEncodingFlags = TCL_ENCODING_START;
	ENCODING_PROFILE_SET(statePtr->outputEncodingFlags, profile); /* Same as input */
	ResetFlag(statePtr, CHANNEL_NEED_MORE_DATA);
	ResetFlag(statePtr, CHANNEL_NEED_MORE_DATA|CHANNEL_ENCODING_ERROR);
	UpdateInterest(chanPtr);
	return TCL_OK;
    } else if (HaveOpt(2, "-eofchar")) {
	if (Tcl_SplitList(interp, newValue, &argc, &argv) == TCL_ERROR) {
	    return TCL_ERROR;
	if (!newValue[0] || (!(newValue[0] & 0x80) && (!newValue[1]
#ifndef TCL_NO_DEPRECATED
	}
	if (argc == 0) {
	    statePtr->inEofChar = 0;
	    statePtr->outEofChar = 0;
	} else if (argc == 1 || argc == 2) {
	    int outIndex = (argc - 1);
	    int inValue = (int) argv[0][0];
		|| !strcmp(newValue+1, " {}")
	    int outValue = (int) argv[outIndex][0];

#endif
	    if (inValue & 0x80 || outValue & 0x80) {
		if (interp) {
		))) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
                            "bad value for -eofchar: must be non-NUL ASCII"
                            " character", -1));
		}
		Tcl_Free((void *)argv);
		return TCL_ERROR;
	    }
	    if (GotFlag(statePtr, TCL_READABLE)) {
		statePtr->inEofChar = inValue;
		statePtr->inEofChar = newValue[0];
	    }
	    if (GotFlag(statePtr, TCL_WRITABLE)) {
		statePtr->outEofChar = outValue;
	    }
	} else {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"bad value for -eofchar: should be a list of zero,"
			" one, or two elements", -1));
			"bad value for -eofchar: must be non-NUL ASCII"
			" character", TCL_INDEX_NONE));
	    }
	    Tcl_Free((void *)argv);
	    return TCL_ERROR;
	}
	if (argv != NULL) {
	    Tcl_Free((void *)argv);
	}

	/*
	 * [Bug 930851] Reset EOF and BLOCKED flags. Changing the character
	 * which signals eof can transform a current eof condition into a 'go
	 * ahead'. Ditto for blocked.
	 */

	if (GotFlag(statePtr, CHANNEL_EOF)) {
	    statePtr->inputEncodingFlags |= TCL_ENCODING_START;
	}
	ResetFlag(statePtr, CHANNEL_EOF|CHANNEL_STICKY_EOF|CHANNEL_BLOCKED);
	statePtr->inputEncodingFlags &= ~TCL_ENCODING_END;
	return TCL_OK;
    } else if (HaveOpt(1, "-profile")) {
	int profile;
	if (TclEncodingProfileNameToId(interp, newValue, &profile) != TCL_OK) {
	    return TCL_ERROR;
	}
	ENCODING_PROFILE_SET(statePtr->inputEncodingFlags, profile);
	ENCODING_PROFILE_SET(statePtr->outputEncodingFlags, profile);
	ResetFlag(statePtr, CHANNEL_NEED_MORE_DATA|CHANNEL_ENCODING_ERROR);
	return TCL_OK;
    } else if (HaveOpt(1, "-translation")) {
	const char *readMode, *writeMode;

	if (Tcl_SplitList(interp, newValue, &argc, &argv) == TCL_ERROR) {
	    return TCL_ERROR;
	}

8130
8131
8132
8133
8134
8135
8136
8137

8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
8148
8149
8150

8151
8152
8153
8154
8155
8156
8157
8364
8365
8366
8367
8368
8369
8370

8371
8372
8373
8374
8375
8376
8377
8378
8379
8380
8381
8382
8383

8384
8385
8386
8387
8388
8389
8390
8391







-
+












-
+







		translation = statePtr->inputTranslation;
	    } else if (strcmp(readMode, "auto") == 0) {
		translation = TCL_TRANSLATE_AUTO;
	    } else if (strcmp(readMode, "binary") == 0) {
		translation = TCL_TRANSLATE_LF;
		statePtr->inEofChar = 0;
		Tcl_FreeEncoding(statePtr->encoding);
		statePtr->encoding = NULL;
		statePtr->encoding = Tcl_GetEncoding(NULL, "iso8859-1");
	    } else if (strcmp(readMode, "lf") == 0) {
		translation = TCL_TRANSLATE_LF;
	    } else if (strcmp(readMode, "cr") == 0) {
		translation = TCL_TRANSLATE_CR;
	    } else if (strcmp(readMode, "crlf") == 0) {
		translation = TCL_TRANSLATE_CRLF;
	    } else if (strcmp(readMode, "platform") == 0) {
		translation = TCL_PLATFORM_TRANSLATION;
	    } else {
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "bad value for -translation: must be one of "
                            "auto, binary, cr, lf, crlf, or platform", -1));
			    "auto, binary, cr, lf, crlf, or platform", -1));
		}
		Tcl_Free((void *)argv);
		return TCL_ERROR;
	    }

	    /*
	     * Reset the EOL flags since we need to look at any buffered data
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187

8188
8189
8190
8191
8192
8193
8194
8195
8196
8197
8198
8199
8200

8201
8202
8203
8204
8205
8206
8207
8411
8412
8413
8414
8415
8416
8417

8418
8419

8420
8421
8422
8423
8424
8425
8426
8427
8428
8429
8430
8431
8432

8433
8434
8435
8436
8437
8438
8439
8440







-


-
+












-
+








		if (strcmp(Tcl_ChannelName(chanPtr->typePtr), "tcp") == 0) {
		    statePtr->outputTranslation = TCL_TRANSLATE_CRLF;
		} else {
		    statePtr->outputTranslation = TCL_PLATFORM_TRANSLATION;
		}
	    } else if (strcmp(writeMode, "binary") == 0) {
		statePtr->outEofChar = 0;
		statePtr->outputTranslation = TCL_TRANSLATE_LF;
		Tcl_FreeEncoding(statePtr->encoding);
		statePtr->encoding = NULL;
		statePtr->encoding = Tcl_GetEncoding(NULL, "iso8859-1");
	    } else if (strcmp(writeMode, "lf") == 0) {
		statePtr->outputTranslation = TCL_TRANSLATE_LF;
	    } else if (strcmp(writeMode, "cr") == 0) {
		statePtr->outputTranslation = TCL_TRANSLATE_CR;
	    } else if (strcmp(writeMode, "crlf") == 0) {
		statePtr->outputTranslation = TCL_TRANSLATE_CRLF;
	    } else if (strcmp(writeMode, "platform") == 0) {
		statePtr->outputTranslation = TCL_PLATFORM_TRANSLATION;
	    } else {
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "bad value for -translation: must be one of "
                            "auto, binary, cr, lf, crlf, or platform", -1));
			    "auto, binary, cr, lf, crlf, or platform", -1));
		}
		Tcl_Free((void *)argv);
		return TCL_ERROR;
	    }
	}
	Tcl_Free((void *)argv);
	return TCL_OK;
8516
8517
8518
8519
8520
8521
8522
8523
8524
8525
8526
8527
8528
8529


8530
8531
8532
8533
8534
8535
8536
8537





8538
8539
8540
8541
8542
8543
8544
8749
8750
8751
8752
8753
8754
8755







8756
8757








8758
8759
8760
8761
8762
8763
8764
8765
8766
8767
8768
8769







-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+







	     * events too. This compiles on all platforms, and also passes the
	     * testsuite on all of them.
	     */

	    mask &= ~TCL_EXCEPTION;

	    if (!statePtr->timer) {
		statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
                        ChannelTimerProc, chanPtr);
	    }
	}
    }

    if (!statePtr->timer
		TclChannelPreserve((Tcl_Channel)chanPtr);
		statePtr->timerChanPtr = chanPtr;
	&& mask & TCL_WRITABLE
	&& GotFlag(statePtr, CHANNEL_NONBLOCKING)) {

	statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
	    ChannelTimerProc,chanPtr);
    }


		statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
			ChannelTimerProc, chanPtr);
	    }
	}
    }
    ChanWatch(chanPtr, mask);
}

/*
 *----------------------------------------------------------------------
 *
 * ChannelTimerProc --
8553
8554
8555
8556
8557
8558
8559
8560

8561
8562
8563
8564


8565
8566
8567
8568



8569
8570
8571
8572
8573
8574
8575
8576

8577
8578
8579
8580
8581
8582
8583
8584
8585
8586
8587
8588









8589
8590
8591
8592
8593
8594











8595




8596








8597
8598
8599
8600
8601
8602
8603
8778
8779
8780
8781
8782
8783
8784

8785
8786
8787


8788
8789
8790



8791
8792
8793








8794












8795
8796
8797
8798
8799
8800
8801
8802
8803






8804
8805
8806
8807
8808
8809
8810
8811
8812
8813
8814
8815
8816
8817
8818
8819

8820
8821
8822
8823
8824
8825
8826
8827
8828
8829
8830
8831
8832
8833
8834







-
+


-
-
+
+

-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
-
+
+
+
+
+
+
+
+







 *	May invoke channel handlers.
 *
 *----------------------------------------------------------------------
 */

static void
ChannelTimerProc(
    ClientData clientData)
    void *clientData)
{
    Channel *chanPtr = (Channel *)clientData;
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    /* State info for channel */
    ChannelState *statePtr = chanPtr->state;

    Tcl_Preserve(statePtr);
    statePtr->timer = NULL;
    if (statePtr->interestMask & TCL_WRITABLE
    if (chanPtr->typePtr == NULL) {
	statePtr->timer = NULL;
	TclChannelRelease((Tcl_Channel)statePtr->timerChanPtr);
	&& GotFlag(statePtr, CHANNEL_NONBLOCKING)
	&& !GotFlag(statePtr, BG_FLUSH_SCHEDULED)
	) {
	/*
	 * Restart the timer in case a channel handler reenters the event loop
	 * before UpdateInterest gets called by Tcl_NotifyChannel.
	 */
	statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
	statePtr->timerChanPtr = NULL;
                ChannelTimerProc,chanPtr);
	Tcl_NotifyChannel((Tcl_Channel) chanPtr, TCL_WRITABLE);
    }

    if (!GotFlag(statePtr, CHANNEL_NEED_MORE_DATA)
	    && (statePtr->interestMask & TCL_READABLE)
	    && (statePtr->inQueueHead != NULL)
	    && IsBufferReady(statePtr->inQueueHead)) {
	/*
	 * Restart the timer in case a channel handler reenters the event loop
	 * before UpdateInterest gets called by Tcl_NotifyChannel.
	 */
    } else {
	if (!GotFlag(statePtr, CHANNEL_NEED_MORE_DATA)
		&& (statePtr->interestMask & TCL_READABLE)
		&& (statePtr->inQueueHead != NULL)
		&& IsBufferReady(statePtr->inQueueHead)) {
	    /*
	     * Restart the timer in case a channel handler reenters the event loop
	     * before UpdateInterest gets called by Tcl_NotifyChannel.
	     */

	statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
                ChannelTimerProc,chanPtr);
	Tcl_NotifyChannel((Tcl_Channel) chanPtr, TCL_READABLE);
    } else {
	UpdateInterest(chanPtr);
	    statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
		ChannelTimerProc,chanPtr);
	    Tcl_Preserve(statePtr);
	    Tcl_NotifyChannel((Tcl_Channel) chanPtr, TCL_READABLE);
	    Tcl_Release(statePtr);
	} else {
	    statePtr->timer = NULL;
	    UpdateInterest(chanPtr);
	    TclChannelRelease((Tcl_Channel)statePtr->timerChanPtr);
	    statePtr->timerChanPtr = NULL;
	}
    }
}

static void
DeleteTimerHandler(
    Tcl_Release(statePtr);
    ChannelState *statePtr)
{
    if (statePtr->timer != NULL) {
	Tcl_DeleteTimerHandler(statePtr->timer);
	statePtr->timer = NULL;
	TclChannelRelease((Tcl_Channel)statePtr->timerChanPtr);
	statePtr->timerChanPtr = NULL;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_CreateChannelHandler --
 *
8623
8624
8625
8626
8627
8628
8629
8630

8631
8632
8633
8634
8635
8636
8637
8854
8855
8856
8857
8858
8859
8860

8861
8862
8863
8864
8865
8866
8867
8868







-
+







    int mask,			/* OR'ed combination of TCL_READABLE,
				 * TCL_WRITABLE, and TCL_EXCEPTION: indicates
				 * conditions under which proc should be
				 * called. Use 0 to disable a registered
				 * handler. */
    Tcl_ChannelProc *proc,	/* Procedure to call for each selected
				 * event. */
    ClientData clientData)	/* Arbitrary data to pass to proc. */
    void *clientData)	/* Arbitrary data to pass to proc. */
{
    ChannelHandler *chPtr;
    Channel *chanPtr = (Channel *) chan;
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */

    /*
8654
8655
8656
8657
8658
8659
8660
8661

8662
8663
8664
8665
8666
8667
8668
8885
8886
8887
8888
8889
8890
8891

8892
8893
8894
8895
8896
8897
8898
8899







-
+







	chPtr->chanPtr = chanPtr;
	chPtr->nextPtr = statePtr->chPtr;
	statePtr->chPtr = chPtr;
    }

    /*
     * The remainder of the initialization below is done regardless of whether
     * or not this is a new record or a modification of an old one.
     * this is a new record or a modification of an old one.
     */

    chPtr->mask = mask;

    /*
     * Recompute the interest mask for the channel - this call may actually be
     * disabling an existing handler.
8695
8696
8697
8698
8699
8700
8701
8702

8703
8704
8705
8706
8707
8708
8709
8926
8927
8928
8929
8930
8931
8932

8933
8934
8935
8936
8937
8938
8939
8940







-
+







 */

void
Tcl_DeleteChannelHandler(
    Tcl_Channel chan,		/* The channel for which to remove the
				 * callback. */
    Tcl_ChannelProc *proc,	/* The procedure in the callback to delete. */
    ClientData clientData)	/* The client data in the callback to
    void *clientData)	/* The client data in the callback to
				 * delete. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    ChannelHandler *chPtr, *prevChPtr;
    Channel *chanPtr = (Channel *) chan;
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
8901
8902
8903
8904
8905
8906
8907
8908

8909
8910
8911
8912
8913
8914
8915
9132
9133
9134
9135
9136
9137
9138

9139
9140
9141
9142
9143
9144
9145
9146







-
+







 *	Whatever the script does.
 *
 *----------------------------------------------------------------------
 */

void
TclChannelEventScriptInvoker(
    ClientData clientData,	/* The script+interp record. */
    void *clientData,	/* The script+interp record. */
    TCL_UNUSED(int) /*mask*/)
{
    EventScriptRecord *esPtr = (EventScriptRecord *)clientData;
				/* The event script + interpreter to eval it
				 * in. */
    Channel *chanPtr = esPtr->chanPtr;
				/* The channel for which this handler is
8969
8970
8971
8972
8973
8974
8975
8976

8977
8978
8979
8980
8981
8982
8983
8984
8985
8986
8987
8988
8989
8990
8991
8992

8993
8994
8995
8996
8997
8998
8999
9000
9001
9002
9003
9004
9005
9006
9007
9008

9009
9010
9011
9012
9013
9014
9015
9200
9201
9202
9203
9204
9205
9206

9207
9208
9209
9210
9211
9212
9213
9214
9215
9216
9217
9218
9219
9220
9221
9222

9223
9224
9225
9226
9227
9228
9229
9230
9231
9232
9233
9234
9235
9236
9237
9238

9239
9240
9241
9242
9243
9244
9245
9246







-
+















-
+















-
+







 *	May create a channel handler for the specified channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FileEventObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Interpreter in which the channel for which
				 * to create the handler is found. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Channel *chanPtr;		/* The channel to create the handler for. */
    ChannelState *statePtr;	/* State info for channel */
    Tcl_Channel chan;		/* The opaque type for the channel. */
    const char *chanName;
    int modeIndex;		/* Index of mode argument. */
    int mask;
    static const char *const modeOptions[] = {"readable", "writable", NULL};
    static const int maskArray[] = {TCL_READABLE, TCL_WRITABLE};

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 1, objv, "channelId event ?script?");
	Tcl_WrongNumArgs(interp, 1, objv, "channel event ?script?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[2], modeOptions, "event name", 0,
	    &modeIndex) != TCL_OK) {
	return TCL_ERROR;
    }
    mask = maskArray[modeIndex];

    chanName = TclGetString(objv[1]);
    chan = Tcl_GetChannel(interp, chanName, NULL);
    if (chan == NULL) {
	return TCL_ERROR;
    }
    chanPtr = (Channel *) chan;
    statePtr = chanPtr->state;
    if ((statePtr->flags & mask) == 0) {
    if (GotFlag(statePtr, mask) == 0) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("channel is not %s",
		(mask == TCL_READABLE) ? "readable" : "writable"));
	return TCL_ERROR;
    }

    /*
     * If we are supposed to return the script, do so.
9063
9064
9065
9066
9067
9068
9069
9070

9071
9072
9073
9074
9075
9076
9077
9294
9295
9296
9297
9298
9299
9300

9301
9302
9303
9304
9305
9306
9307
9308







-
+







 *	Calls CopyData for -command invocation.
 *
 *----------------------------------------------------------------------
 */

static void
ZeroTransferTimerProc(
    ClientData clientData)
    void *clientData)
{
    /* calling CopyData with mask==0 still implies immediate invocation of the
     *  -command callback, and completion of the fcopy.
     */
    CopyData((CopyState *)clientData, 0);
}

9097
9098
9099
9100
9101
9102
9103
9104

9105
9106
9107
9108
9109
9110
9111
9112
9113
9114
9115
9116
9117
9118
9119
9120
9121

9122
9123
9124
9125
9126
9127
9128

9129
9130
9131
9132
9133
9134
9135
9328
9329
9330
9331
9332
9333
9334

9335
9336
9337
9338
9339
9340
9341
9342
9343
9344
9345
9346
9347
9348
9349
9350
9351

9352
9353
9354
9355
9356
9357
9358

9359
9360
9361
9362
9363
9364
9365
9366







-
+
















-
+






-
+







 */

int
TclCopyChannel(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Channel inChan,		/* Channel to read from. */
    Tcl_Channel outChan,	/* Channel to write to. */
    Tcl_WideInt toRead,		/* Amount of data to copy, or -1 for all. */
    long long toRead,		/* Amount of data to copy, or -1 for all. */
    Tcl_Obj *cmdPtr)		/* Pointer to script to execute or NULL. */
{
    Channel *inPtr = (Channel *) inChan;
    Channel *outPtr = (Channel *) outChan;
    ChannelState *inStatePtr, *outStatePtr;
    int readFlags, writeFlags;
    CopyState *csPtr;
    int nonBlocking = (cmdPtr) ? CHANNEL_NONBLOCKING : 0;
    int moveBytes;

    inStatePtr = inPtr->state;
    outStatePtr = outPtr->state;

    if (BUSY_STATE(inStatePtr, TCL_READABLE)) {
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "channel \"%s\" is busy", Tcl_GetChannelName(inChan)));
		    "channel \"%s\" is busy", Tcl_GetChannelName(inChan)));
	}
	return TCL_ERROR;
    }
    if (BUSY_STATE(outStatePtr, TCL_WRITABLE)) {
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "channel \"%s\" is busy", Tcl_GetChannelName(outChan)));
		    "channel \"%s\" is busy", Tcl_GetChannelName(outChan)));
	}
	return TCL_ERROR;
    }

    readFlags = inStatePtr->flags;
    writeFlags = outStatePtr->flags;

9154
9155
9156
9157
9158
9159
9160
9161
9162


9163
9164
9165
9166
9167
9168
9169

9170
9171
9172
9173
9174
9175
9176
9177
9178
9179
9180
9181

9182
9183
9184

9185
9186
9187
9188

9189
9190
9191
9192
9193
9194



9195

9196
9197
9198
9199
9200
9201
9202
9203
9204
9205
9206
9207
9208
9209


9210
9211
9212
9213
9214
9215
9216
9385
9386
9387
9388
9389
9390
9391


9392
9393
9394






9395




9396
9397
9398
9399
9400
9401
9402

9403
9404
9405
9406
9407
9408
9409
9410

9411
9412
9413
9414
9415
9416
9417
9418
9419
9420

9421
9422
9423
9424
9425
9426
9427
9428
9429
9430
9431
9432
9433


9434
9435
9436
9437
9438
9439
9440
9441
9442







-
-
+
+

-
-
-
-
-
-
+
-
-
-
-







-
+



+



-
+






+
+
+
-
+












-
-
+
+







	return TCL_ERROR;
    }

    /*
     * Make sure the output side is unbuffered.
     */

    outStatePtr->flags = (outStatePtr->flags & ~CHANNEL_LINEBUFFERED)
	    | CHANNEL_UNBUFFERED;
    ResetFlag(outStatePtr, CHANNEL_LINEBUFFERED);
    SetFlag(outStatePtr, CHANNEL_UNBUFFERED);

    /*
     * Test for conditions where we know we can just move bytes from input
     * channel to output channel with no transformation or even examination
     * of the bytes themselves.
     */

    moveBytes = Lossless(inStatePtr, outStatePtr, toRead);
    moveBytes = inStatePtr->inEofChar == '\0'	/* No eofChar to stop input */
	    && inStatePtr->inputTranslation == TCL_TRANSLATE_LF
	    && outStatePtr->outputTranslation == TCL_TRANSLATE_LF
	    && inStatePtr->encoding == outStatePtr->encoding;

    /*
     * Allocate a new CopyState to maintain info about the current copy in
     * progress. This structure will be deallocated when the copy is
     * completed.
     */

    csPtr = (CopyState *)Tcl_Alloc(sizeof(CopyState) + !moveBytes * inStatePtr->bufSize);
    csPtr = (CopyState *)Tcl_Alloc(offsetof(CopyState, buffer) + 1U + !moveBytes * inStatePtr->bufSize);
    csPtr->bufSize = !moveBytes * inStatePtr->bufSize;
    csPtr->readPtr = inPtr;
    csPtr->writePtr = outPtr;
    csPtr->refCount = 2; /* two references below (inStatePtr, outStatePtr) */
    csPtr->readFlags = readFlags;
    csPtr->writeFlags = writeFlags;
    csPtr->toRead = toRead;
    csPtr->total = (Tcl_WideInt) 0;
    csPtr->total = 0;
    csPtr->interp = interp;
    if (cmdPtr) {
	Tcl_IncrRefCount(cmdPtr);
    }
    csPtr->cmdPtr = cmdPtr;

    TclChannelPreserve(inChan);
    TclChannelPreserve(outChan);

    inStatePtr->csPtrR  = csPtr;
    inStatePtr->csPtrR = csPtr;
    outStatePtr->csPtrW = csPtr;

    if (moveBytes) {
	return MoveBytes(csPtr);
    }

    /*
     * Special handling of -size 0 async transfers, so that the -command is
     * still called asynchronously.
     */

    if ((nonBlocking == CHANNEL_NONBLOCKING) && (toRead == 0)) {
        Tcl_CreateTimerHandler(0, ZeroTransferTimerProc, csPtr);
        return 0;
	Tcl_CreateTimerHandler(0, ZeroTransferTimerProc, csPtr);
	return TCL_OK;
    }

    /*
     * Start copying data between the channels.
     */

    return CopyData(csPtr, 0);
9285
9286
9287
9288
9289
9290
9291
9292

9293
9294
9295
9296
9297
9298
9299
9511
9512
9513
9514
9515
9516
9517

9518
9519
9520
9521
9522
9523
9524
9525







-
+







	Tcl_SetObjResult(csPtr->interp, errObj);
	StopCopy(csPtr);
    }
}

static void
MBEvent(
    ClientData clientData,
    void *clientData,
    int mask)
{
    CopyState *csPtr = (CopyState *) clientData;
    Tcl_Channel inChan = (Tcl_Channel) csPtr->readPtr;
    Tcl_Channel outChan = (Tcl_Channel) csPtr->writePtr;
    ChannelState *inStatePtr = csPtr->readPtr->state;

9364
9365
9366
9367
9368
9369
9370
9371
9372
9373
9374
9375
9376
9377







9378
9379
9380
9381
9382
9383
9384
9590
9591
9592
9593
9594
9595
9596







9597
9598
9599
9600
9601
9602
9603
9604
9605
9606
9607
9608
9609
9610







-
-
-
-
-
-
-
+
+
+
+
+
+
+







	}
	bufPtr = bufPtr->nextPtr;
    }

    if (bufPtr) {
	/* Split the overflowing buffer in two */
	int extra = (int) (inBytes - csPtr->toRead);
        /* Note that going with int for extra assumes that inBytes is not too
         * much over toRead to require a wide itself. If that gets violated
         * then the calculations involving extra must be made wide too.
         *
         * Noted with Win32/MSVC debug build treating the warning (possible of
         * data in __int64 to int conversion) as error.
         */
	/* Note that going with int for extra assumes that inBytes is not too
	 * much over toRead to require a wide itself. If that gets violated
	 * then the calculations involving extra must be made wide too.
	 *
	 * Noted with Win32/MSVC debug build treating the warning (possible of
	 * data in long long to int conversion) as error.
	 */

	bufPtr = AllocChannelBuffer(extra);

	tail->nextAdded -= extra;
	memcpy(InsertPoint(bufPtr), InsertPoint(tail), extra);
	bufPtr->nextAdded += extra;
	bufPtr->nextPtr = tail->nextPtr;
9468
9469
9470
9471
9472
9473
9474
9475
9476



9477

9478
9479

9480
9481


9482
9483
9484
9485
9486
9487
9488
9489
9490
9491
9492
9493
9494
9495
9496
9497
9498

9499
9500
9501
9502

9503
9504
9505
9506
9507

9508
9509
9510
9511
9512
9513
9514
9515
9516




9517
9518
9519
9520
9521




9522
9523
9524
9525
9526
9527
9528
9529
9530
9531
9532
9533
9534
9535

9536
9537
9538
9539


9540
9541
9542
9543
9544
9545

9546
9547

9548
9549

9550
9551
9552




















9553
9554
9555
9556
9557
9558
9559
9560

9561
9562
9563
9564
9565

9566
9567
9568
9569
9570
9571
9572
9573
9574
9575
9576
9577
9578
9579
9580
9581
9582
9583
9584


9585
9586
9587
9588
9589
9590
9591
9592
9593
9594
9595
9596
9597
9598
9599
9600
9601
9602
9603

9604
9605
9606
9607
9608
9609
9610
9611

9612
9613

9614
9615
9616
9617
9618
9619
9620
9621
9622
9623
9624
9625
9626

9627
9628
9629

9630
9631
9632
9633
9634
9635
9636

9637
9638
9639
9640
9641

9642
9643
9644
9645
9646

9647
9648
9649
9650
9651
9652
9653
9654
9655
9656

9657
9658
9659

9660
9661
9662
9663
9664
9665
9666
9694
9695
9696
9697
9698
9699
9700


9701
9702
9703
9704
9705
9706

9707

9708
9709
9710
9711
9712
9713
9714
9715
9716
9717
9718
9719
9720
9721
9722
9723
9724
9725
9726

9727


9728

9729
9730
9731
9732
9733

9734
9735
9736
9737
9738
9739
9740
9741
9742
9743
9744
9745
9746
9747
9748
9749
9750
9751
9752
9753
9754
9755
9756
9757
9758
9759
9760
9761
9762
9763
9764
9765
9766
9767
9768
9769

9770
9771
9772


9773
9774
9775
9776
9777
9778
9779

9780
9781

9782
9783
9784
9785



9786
9787
9788
9789
9790
9791
9792
9793
9794
9795
9796
9797
9798
9799
9800
9801
9802
9803
9804
9805
9806
9807
9808
9809
9810
9811
9812

9813
9814
9815
9816
9817

9818
9819
9820
9821
9822
9823
9824
9825
9826
9827
9828
9829
9830
9831
9832
9833
9834
9835


9836
9837
9838
9839
9840
9841
9842
9843
9844
9845
9846
9847
9848
9849
9850
9851
9852
9853
9854
9855

9856
9857
9858
9859
9860
9861
9862
9863

9864
9865

9866
9867
9868





9869
9870
9871
9872
9873

9874
9875
9876

9877
9878
9879
9880
9881
9882
9883

9884
9885
9886
9887
9888

9889
9890
9891
9892
9893

9894
9895
9896
9897
9898
9899
9900
9901
9902
9903

9904
9905
9906

9907
9908
9909
9910
9911
9912
9913
9914







-
-
+
+
+

+

-
+
-

+
+
















-
+
-
-

-
+




-
+









+
+
+
+





+
+
+
+













-
+


-
-
+
+





-
+

-
+


+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+




-
+

















-
-
+
+


















-
+







-
+

-
+


-
-
-
-
-





-
+


-
+






-
+




-
+




-
+









-
+


-
+







    CopyState *csPtr,		/* State of copy operation. */
    int mask)			/* Current channel event flags. */
{
    Tcl_Interp *interp;
    Tcl_Obj *cmdPtr, *errObj = NULL, *bufObj = NULL, *msg = NULL;
    Tcl_Channel inChan, outChan;
    ChannelState *inStatePtr, *outStatePtr;
    int result = TCL_OK, size;
    size_t sizeb;
    int result = TCL_OK;
    Tcl_Size sizeb;
    Tcl_Size sizePart;
    Tcl_WideInt total;
    Tcl_WideInt size;
    const char *buffer;
    int inBinary, outBinary, sameEncoding;
    int moveBytes;
				/* Encoding control */
    int underflow;		/* Input underflow */

    csPtr->refCount++;		/* avoid freeing during handling */

    inChan	= (Tcl_Channel) csPtr->readPtr;
    outChan	= (Tcl_Channel) csPtr->writePtr;
    inStatePtr	= csPtr->readPtr->state;
    outStatePtr	= csPtr->writePtr->state;
    interp	= csPtr->interp;
    cmdPtr	= csPtr->cmdPtr;

    /*
     * Copy the data the slow way, using the translation mechanism.
     *
     * Note: We have make sure that we use the topmost channel in a stack for
     * the copying. The caller uses Tcl_GetChannel to access it, and thus gets
     * the bottom of the stack.
     */

    inBinary = (inStatePtr->encoding == NULL);
    moveBytes = Lossless(inStatePtr, outStatePtr, csPtr->toRead);
    outBinary = (outStatePtr->encoding == NULL);
    sameEncoding = (inStatePtr->encoding == outStatePtr->encoding);

    if (!(inBinary || sameEncoding)) {
    if (!moveBytes) {
	TclNewObj(bufObj);
	Tcl_IncrRefCount(bufObj);
    }

    while (csPtr->toRead != (Tcl_WideInt) 0) {
    while (csPtr->toRead != 0) {
	/*
	 * Check for unreported background errors.
	 */

	Tcl_GetChannelError(inChan, &msg);
	if ((inStatePtr->unreportedError != 0) || (msg != NULL)) {
	    Tcl_SetErrno(inStatePtr->unreportedError);
	    inStatePtr->unreportedError = 0;
	    goto readError;
	} else if (inStatePtr->flags & CHANNEL_ENCODING_ERROR) {
	    Tcl_SetErrno(EILSEQ);
	    inStatePtr->flags &= ~CHANNEL_ENCODING_ERROR;
	    goto readError;
	}
	Tcl_GetChannelError(outChan, &msg);
	if ((outStatePtr->unreportedError != 0) || (msg != NULL)) {
	    Tcl_SetErrno(outStatePtr->unreportedError);
	    outStatePtr->unreportedError = 0;
	    goto writeError;
	} else if (outStatePtr->flags & CHANNEL_ENCODING_ERROR) {
	    Tcl_SetErrno(EILSEQ);
	    outStatePtr->flags &= ~CHANNEL_ENCODING_ERROR;
	    goto writeError;
	}

	if (cmdPtr && (mask == 0)) {
	    /*
	     * In async mode, we skip reading synchronously and fake an
	     * underflow instead to prime the readable fileevent.
	     */

	    size = 0;
	    underflow = 1;
	} else {
	    /*
	     * Read up to bufSize bytes.
	     * Read up to bufSize characters.
	     */

	    if ((csPtr->toRead == (Tcl_WideInt) -1)
                    || (csPtr->toRead > (Tcl_WideInt) csPtr->bufSize)) {
	    if ((csPtr->toRead == -1)
		    || (csPtr->toRead > (Tcl_WideInt)csPtr->bufSize)) {
		sizeb = csPtr->bufSize;
	    } else {
		sizeb = csPtr->toRead;
	    }

	    if (inBinary || sameEncoding) {
	    if (moveBytes) {
		size = DoRead(inStatePtr->topChanPtr, csPtr->buffer, sizeb,
                              !GotFlag(inStatePtr, CHANNEL_NONBLOCKING));
			      !GotFlag(inStatePtr, CHANNEL_NONBLOCKING));
	    } else {
		size = DoReadChars(inStatePtr->topChanPtr, bufObj, sizeb,
			!GotFlag(inStatePtr, CHANNEL_NONBLOCKING)
			0 /* No append */);
	    }
	    underflow = (size >= 0) && ((size_t)size < sizeb);	/* Input underflow */
			,0 /* No append */);
		/*
		 * In case of a recoverable encoding error, any data before
		 * the error should be written. This data is in the bufObj.
		 * Program flow for this case:
		 * - Check, if there are any remaining bytes to write
		 * - If yes, simulate a successful read to write them out
		 * - Come back here by the outer loop and read again
		 * - Do not enter in the if below, as there are no pending
		 *  writes
		 * - Fail below with a read error
		 */
		if (size < 0 && Tcl_GetErrno() == EILSEQ) {
		    TclGetStringFromObj(bufObj, &sizePart);
		    if (sizePart > 0) {
			size = sizePart;
		    }
		}
	    }
	    underflow = (size >= 0) && (size < sizeb);	/* Input underflow */
	}

	if (size < 0) {
	readError:
	    if (interp) {
		TclNewObj(errObj);
		Tcl_AppendStringsToObj(errObj, "error reading \"",
			Tcl_GetChannelName(inChan), "\": ", NULL);
			Tcl_GetChannelName(inChan), "\": ", (char *)NULL);
		if (msg != NULL) {
		    Tcl_AppendObjToObj(errObj, msg);
		} else {
		    Tcl_AppendStringsToObj(errObj, Tcl_PosixError(interp),
			    NULL);
			    (char *)NULL);
		}
	    }
	    if (msg != NULL) {
		Tcl_DecrRefCount(msg);
	    }
	    break;
	} else if (underflow) {
	    /*
	     * We had an underflow on the read side. If we are at EOF, and not
	     * in the synchronous part of an asynchronous fcopy, then the
	     * copying is done, otherwise set up a channel handler to detect
	     * when the channel becomes readable again.
	     */

	    if ((size == 0) && Tcl_Eof(inChan) && !(cmdPtr && (mask == 0))) {
		break;
	    }
	    if (cmdPtr && (!Tcl_Eof(inChan) || (mask == 0)) &&
                !(mask & TCL_READABLE)) {
	    if (cmdPtr && (!Tcl_Eof(inChan) || (mask == 0))
		    && !(mask & TCL_READABLE)) {
		if (mask & TCL_WRITABLE) {
		    Tcl_DeleteChannelHandler(outChan, CopyEventProc, csPtr);
		}
		Tcl_CreateChannelHandler(inChan, TCL_READABLE, CopyEventProc,
			csPtr);
	    }
	    if (size == 0) {
		if (!GotFlag(inStatePtr, CHANNEL_NONBLOCKING)) {
		    /*
		     * We allowed a short read.  Keep trying.
		     */

		    continue;
		}
		if (bufObj != NULL) {
		    TclDecrRefCount(bufObj);
		    bufObj = NULL;
		}
		return TCL_OK;
		goto done;
	    }
	}

	/*
	 * Now write the buffer out.
	 */

	if (inBinary || sameEncoding) {
	if (moveBytes) {
	    buffer = csPtr->buffer;
	    sizeb = size;
	    sizeb = WriteBytes(outStatePtr->topChanPtr, buffer, size);
	} else {
	    buffer = TclGetStringFromObj(bufObj, &sizeb);
	}

	if (outBinary || sameEncoding) {
	    sizeb = WriteBytes(outStatePtr->topChanPtr, buffer, sizeb);
	} else {
	    sizeb = WriteChars(outStatePtr->topChanPtr, buffer, sizeb);
	}

	/*
	 * [Bug 2895565]. At this point 'size' still contains the number of
	 * bytes or characters which have been read. We keep this to later to
	 * characters which have been read. We keep this to later to
	 * update the totals and toRead information, see marker (UP) below. We
	 * must not overwrite it with 'sizeb', which is the number of written
	 * bytes or characters, and both EOL translation and encoding
	 * characters, and both EOL translation and encoding
	 * conversion may have changed this number unpredictably in relation
	 * to 'size' (It can be smaller or larger, in the latter case able to
	 * drive toRead below -1, causing infinite looping). Completely
	 * unsuitable for updating totals and toRead.
	 */

	if (sizeb == TCL_INDEX_NONE) {
	if (sizeb < 0) {
	writeError:
	    if (interp) {
		TclNewObj(errObj);
		Tcl_AppendStringsToObj(errObj, "error writing \"",
			Tcl_GetChannelName(outChan), "\": ", NULL);
			Tcl_GetChannelName(outChan), "\": ", (char *)NULL);
		if (msg != NULL) {
		    Tcl_AppendObjToObj(errObj, msg);
		} else {
		    Tcl_AppendStringsToObj(errObj, Tcl_PosixError(interp),
			    NULL);
			    (char *)NULL);
		}
	    }
	    if (msg != NULL) {
		Tcl_DecrRefCount(msg);
	    }
	    break;
	}

	/*
	 * Update the current byte count. Do it now so the count is valid
	 * Update the current character count. Do it now so the count is valid
	 * before a return or break takes us out of the loop. The invariant at
	 * the top of the loop should be that csPtr->toRead holds the number
	 * of bytes left to copy.
	 * of characters left to copy.
	 */

	if (csPtr->toRead != -1) {
	    csPtr->toRead -= size;
	}
	csPtr->total += size;

9687
9688
9689
9690
9691
9692
9693
9694

9695
9696
9697
9698
9699
9700
9701
9935
9936
9937
9938
9939
9940
9941

9942
9943
9944
9945
9946
9947
9948
9949







-
+







		Tcl_CreateChannelHandler(outChan, TCL_WRITABLE,
			CopyEventProc, csPtr);
	    }
	    if (bufObj != NULL) {
		TclDecrRefCount(bufObj);
		bufObj = NULL;
	    }
	    return TCL_OK;
	    goto done;
	}

	/*
	 * For background copies, we only do one buffer per invocation so we
	 * don't starve the rest of the system.
	 */

9709
9710
9711
9712
9713
9714
9715
9716

9717
9718
9719
9720
9721
9722
9723
9724
9725
9726
9727


9728
9729
9730
9731
9732
9733
9734
9957
9958
9959
9960
9961
9962
9963

9964
9965
9966
9967
9968
9969
9970
9971
9972
9973


9974
9975
9976
9977
9978
9979
9980
9981
9982







-
+









-
-
+
+







		Tcl_CreateChannelHandler(outChan, TCL_WRITABLE, CopyEventProc,
			csPtr);
	    }
	    if (bufObj != NULL) {
		TclDecrRefCount(bufObj);
		bufObj = NULL;
	    }
	    return TCL_OK;
	    goto done;
	}
    } /* while */

    if (bufObj != NULL) {
	TclDecrRefCount(bufObj);
	bufObj = NULL;
    }

    /*
     * Make the callback or return the number of bytes transferred. The local
     * total is used because StopCopy frees csPtr.
     * Make the callback or return the number of characters transferred. The
     * local total is used because StopCopy frees csPtr.
     */

    total = csPtr->total;
    if (cmdPtr && interp) {
	int code;

	/*
9761
9762
9763
9764
9765
9766
9767



9768
9769
9770
9771
9772
9773
9774
9775
9776
9777
9778
9779
9780
9781
9782
9783
9784


9785
9786
9787
9788

9789
9790
9791
9792

9793
9794
9795
9796
9797
9798
9799
9800

9801
9802
9803
9804

9805
9806
9807
9808
9809
9810
9811
9812
9813
9814
9815
9816
9817
9818
9819
9820
9821





9822
9823
9824
9825
9826
9827
9828
10009
10010
10011
10012
10013
10014
10015
10016
10017
10018
10019
10020
10021
10022
10023
10024
10025
10026
10027
10028
10029
10030
10031
10032
10033


10034
10035
10036
10037
10038

10039
10040
10041
10042

10043
10044
10045
10046
10047
10048
10049
10050

10051
10052
10053
10054

10055
10056
10057
10058
10059
10060
10061
10062
10063
10064
10065
10066
10067
10068
10069
10070
10071
10072
10073
10074
10075
10076
10077
10078
10079
10080
10081
10082
10083
10084







+
+
+















-
-
+
+



-
+



-
+







-
+



-
+

















+
+
+
+
+







		result = TCL_ERROR;
	    } else {
		Tcl_ResetResult(interp);
		Tcl_SetObjResult(interp, Tcl_NewWideIntObj(total));
	    }
	}
    }

  done:
    CopyDecrRefCount(csPtr);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * DoRead --
 *
 *	Stores up to "bytesToRead" bytes in memory pointed to by "dst".
 *	These bytes come from reading the channel "chanPtr" and
 *	performing the configured translations.  No encoding conversions
 *	are applied to the bytes being read.
 *
 * Results:
 *	The number of bytes actually stored (<= bytesToRead),
 * 	or -1 if there is an error in reading the channel.  Use
 * 	Tcl_GetErrno() to retrieve the error code for the error
 *	or TCL_INDEX_NONE if there is an error in reading the channel.  Use
 *	Tcl_GetErrno() to retrieve the error code for the error
 *	that occurred.
 *
 *	The number of bytes stored can be less than the number
 * 	requested when
 *	requested when
 *	  - EOF is reached on the channel; or
 *	  - the channel is non-blocking, and we've read all we can
 *	    without blocking.
 *	  - a channel reading error occurs (and we return -1)
 *	  - a channel reading error occurs (and we return TCL_INDEX_NONE)
 *
 * Side effects:
 *	May cause input to be buffered.
 *
 *----------------------------------------------------------------------
 */

static int
static Tcl_Size
DoRead(
    Channel *chanPtr,		/* The channel from which to read. */
    char *dst,			/* Where to store input read. */
    size_t bytesToRead,		/* Maximum number of bytes to read. */
    Tcl_Size bytesToRead,		/* Maximum number of bytes to read. */
    int allowShortReads)	/* Allow half-blocking (pipes,sockets) */
{
    ChannelState *statePtr = chanPtr->state;
    char *p = dst;

    /*
     * Early out when we know a read will get the eofchar.
     *
     * NOTE: This seems to be a bug.  The special handling for
     * a zero-char read request ought to come first.  As coded
     * the EOF due to eofchar has distinguishing behavior from
     * the EOF due to reported EOF on the underlying device, and
     * that seems undesirable.  However recent history indicates
     * that new inconsistent behavior in a patchlevel has problems
     * too.  Keep on keeping on for now.
     */

    if (GotFlag(statePtr, CHANNEL_ENCODING_ERROR)) {
	UpdateInterest(chanPtr);
	Tcl_SetErrno(EILSEQ);
	return -1;
    }
    if (GotFlag(statePtr, CHANNEL_STICKY_EOF)) {
	SetFlag(statePtr, CHANNEL_EOF);
	assert(statePtr->inputEncodingFlags & TCL_ENCODING_END);
	assert(!GotFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR));

	/* TODO: Don't need this call */
	UpdateInterest(chanPtr);
9855
9856
9857
9858
9859
9860
9861
9862
9863


9864
9865
9866
9867
9868
9869
9870
9871
9872
9873
9874
9875
9876
9877
9878
9879
9880
9881
9882

9883
9884

9885
9886

9887
9888
9889
9890
9891
9892
9893
9894
9895







9896
9897
9898
9899
9900
9901
9902
10111
10112
10113
10114
10115
10116
10117


10118
10119
10120
10121
10122
10123
10124
10125
10126
10127


10128
10129
10130
10131
10132
10133
10134
10135

10136


10137


10138



10139
10140
10141
10142
10143

10144
10145
10146
10147
10148
10149
10150
10151
10152
10153
10154
10155
10156
10157







-
-
+
+








-
-








-
+
-
-
+
-
-
+
-
-
-





-
+
+
+
+
+
+
+







	ChannelBuffer *bufPtr = statePtr->inQueueHead;

	/*
	 * Don't read more data if we have what we need.
	 */

	while (!bufPtr ||			/* We got no buffer!   OR */
		(!IsBufferFull(bufPtr) && 	/* Our buffer has room AND */
		((size_t)BytesLeft(bufPtr) < bytesToRead))) {
		(!IsBufferFull(bufPtr) &&	/* Our buffer has room AND */
		((Tcl_Size) BytesLeft(bufPtr) < bytesToRead))) {
						/* Not enough bytes in it yet
						 * to fill the dst */
	    int code;

	moreData:
	    code = GetInput(chanPtr);
	    bufPtr = statePtr->inQueueHead;

	    assert(bufPtr != NULL);

	    if (GotFlag(statePtr, CHANNEL_EOF|CHANNEL_BLOCKED)) {
		/*
		 * Further reads cannot do any more.
		 */

		break;
	    }

	    if (code) {
	    if (code || !bufPtr) {
		/*
	     * Read error
		/* Read error (or channel dead/closed) */
	     */

		goto readErr;
		UpdateInterest(chanPtr);
		TclChannelRelease((Tcl_Channel)chanPtr);
		return -1;
	    }

	    assert(IsBufferFull(bufPtr));
	}

	assert(bufPtr != NULL);
	if (!bufPtr) {
	  readErr:

	    UpdateInterest(chanPtr);
	    TclChannelRelease((Tcl_Channel)chanPtr);
	    return -1;
	}

	bytesRead = BytesLeft(bufPtr);
	bytesWritten = bytesToRead;

	TranslateInputEOL(statePtr, p, RemovePoint(bufPtr),
		&bytesWritten, &bytesRead);
	bufPtr->nextRemoved += bytesRead;
9912
9913
9914
9915
9916
9917
9918
9919

9920
9921
9922

9923
9924
9925
9926
9927
9928
9929
9930
9931
9932
9933
9934
9935
9936
9937
9938
9939
9940

9941
9942
9943
9944
9945
9946
9947
9948

9949
9950
9951
9952
9953
9954
9955
10167
10168
10169
10170
10171
10172
10173

10174
10175
10176

10177
10178
10179
10180
10181
10182
10183
10184
10185
10186
10187
10188
10189
10190
10191
10192
10193
10194

10195
10196
10197
10198
10199
10200
10201
10202

10203
10204
10205
10206
10207
10208
10209
10210







-
+


-
+

















-
+







-
+







	     */

	    if (bytesToRead == 0) {
		break;
	    }

	    /*
	     * 1) We're @EOF because we saw eof char.
	     * 1) We're @EOF because we saw eof char, or there was an encoding error.
	     */

	    if (GotFlag(statePtr, CHANNEL_STICKY_EOF)) {
	    if (GotFlag(statePtr, CHANNEL_STICKY_EOF|CHANNEL_ENCODING_ERROR)) {
		break;
	    }

	    /*
	     * 2) The buffer holds a \r while in CRLF translation, followed by
	     *    the end of the buffer.
	     */

	    assert(statePtr->inputTranslation == TCL_TRANSLATE_CRLF);
	    assert(RemovePoint(bufPtr)[0] == '\r');
	    assert(BytesLeft(bufPtr) == 1);

	    if (bufPtr->nextPtr == NULL) {
		/*
		 * There's no more buffered data...
		 */

		if (statePtr->flags & CHANNEL_EOF) {
		if (GotFlag(statePtr, CHANNEL_EOF)) {
		    /*
		     * ...and there never will be.
		     */

		    *p++ = '\r';
		    bytesToRead--;
		    bufPtr->nextRemoved++;
		} else if (statePtr->flags & CHANNEL_BLOCKED) {
		} else if (GotFlag(statePtr, CHANNEL_BLOCKED)) {
		    /*
		     * ...and we cannot get more now.
		     */

		    SetFlag(statePtr, CHANNEL_NEED_MORE_DATA);
		    break;
		} else {
9999
10000
10001
10002
10003
10004
10005
10006

10007
10008
10009
10010
10011
10012

10013
10014
10015
10016
10017
10018
10019
10254
10255
10256
10257
10258
10259
10260

10261
10262
10263
10264
10265
10266

10267
10268
10269
10270
10271
10272
10273
10274







-
+





-
+







	}
    }
    if (bytesToRead == 0) {
	ResetFlag(statePtr, CHANNEL_BLOCKED);
    }

    assert(!GotFlag(statePtr, CHANNEL_EOF)
	    || GotFlag(statePtr, CHANNEL_STICKY_EOF)
	    || GotFlag(statePtr, CHANNEL_STICKY_EOF|CHANNEL_ENCODING_ERROR)
	    || Tcl_InputBuffered((Tcl_Channel)chanPtr) == 0);
    assert(!(GotFlag(statePtr, CHANNEL_EOF|CHANNEL_BLOCKED)
	    == (CHANNEL_EOF|CHANNEL_BLOCKED)));
    UpdateInterest(chanPtr);
    TclChannelRelease((Tcl_Channel)chanPtr);
    return (int)(p - dst);
    return (Tcl_Size)(p - dst);
}

/*
 *----------------------------------------------------------------------
 *
 * CopyEventProc --
 *
10028
10029
10030
10031
10032
10033
10034
10035

10036
10037
10038
10039

































10040
10041
10042
10043
10044
10045
10046
10283
10284
10285
10286
10287
10288
10289

10290
10291
10292
10293
10294
10295
10296
10297
10298
10299
10300
10301
10302
10303
10304
10305
10306
10307
10308
10309
10310
10311
10312
10313
10314
10315
10316
10317
10318
10319
10320
10321
10322
10323
10324
10325
10326
10327
10328
10329
10330
10331
10332
10333
10334







-
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
CopyEventProc(
    ClientData clientData,
    void *clientData,
    int mask)
{
    (void) CopyData((CopyState *)clientData, mask);
}

/*
 *----------------------------------------------------------------------
 *
 * Lossless --
 *
 *	Determines whether copying characters between two channel states would
 *	be lossless, i.e. whether one byte corresponds to one character, every
 *	character appears in the Unicode character set, there are no
 *	translations to be performed, and no inline signals to respond to.
 *
 * Result:
 *	True if copying would be lossless.
 *
 *----------------------------------------------------------------------
 */
int
Lossless(
    ChannelState *inStatePtr,
    ChannelState *outStatePtr,
    long long toRead)
{
    return inStatePtr->inEofChar == '\0'	/* No eofChar to stop input */
	&& inStatePtr->inputTranslation == TCL_TRANSLATE_LF
	&& outStatePtr->outputTranslation == TCL_TRANSLATE_LF
	&& ((inStatePtr->encoding == GetBinaryEncoding()
		&& outStatePtr->encoding == GetBinaryEncoding())
	    || (toRead == -1
		&& inStatePtr->encoding == outStatePtr->encoding
		&& ENCODING_PROFILE_GET(inStatePtr->inputEncodingFlags) == TCL_ENCODING_PROFILE_TCL8
		&& ENCODING_PROFILE_GET(outStatePtr->inputEncodingFlags) == TCL_ENCODING_PROFILE_TCL8
	    ));
}

/*
 *----------------------------------------------------------------------
 *
 * StopCopy --
 *
 *	This routine halts a copy that is in progress.
10074
10075
10076
10077
10078
10079
10080
10081

10082
10083
10084
10085
10086
10087

10088
10089
10090
10091
10092
10093
10094


10095
10096
10097
10098
10099
10100
10101
10102
10103

10104



10105
10106





















10107
10108
10109
10110
10111
10112
10113
10362
10363
10364
10365
10366
10367
10368

10369
10370
10371
10372
10373
10374

10375
10376
10377
10378
10379
10380


10381
10382
10383
10384
10385
10386
10387
10388
10389
10390
10391
10392
10393
10394
10395
10396


10397
10398
10399
10400
10401
10402
10403
10404
10405
10406
10407
10408
10409
10410
10411
10412
10413
10414
10415
10416
10417
10418
10419
10420
10421
10422
10423
10424







-
+





-
+





-
-
+
+









+

+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    outStatePtr = csPtr->writePtr->state;

    /*
     * Restore the old blocking mode and output buffering mode.
     */

    nonBlocking = csPtr->readFlags & CHANNEL_NONBLOCKING;
    if (nonBlocking != (inStatePtr->flags & CHANNEL_NONBLOCKING)) {
    if (nonBlocking != GotFlag(inStatePtr, CHANNEL_NONBLOCKING)) {
	SetBlockMode(NULL, csPtr->readPtr,
		nonBlocking ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING);
    }
    if (csPtr->readPtr != csPtr->writePtr) {
	nonBlocking = csPtr->writeFlags & CHANNEL_NONBLOCKING;
	if (nonBlocking != (outStatePtr->flags & CHANNEL_NONBLOCKING)) {
	if (nonBlocking != GotFlag(outStatePtr, CHANNEL_NONBLOCKING)) {
	    SetBlockMode(NULL, csPtr->writePtr,
		    nonBlocking ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING);
	}
    }
    ResetFlag(outStatePtr, CHANNEL_LINEBUFFERED | CHANNEL_UNBUFFERED);
    outStatePtr->flags |=
	    csPtr->writeFlags & (CHANNEL_LINEBUFFERED | CHANNEL_UNBUFFERED);
    SetFlag(outStatePtr,
	    csPtr->writeFlags & (CHANNEL_LINEBUFFERED | CHANNEL_UNBUFFERED));

    if (csPtr->cmdPtr) {
	Tcl_DeleteChannelHandler(inChan, CopyEventProc, csPtr);
	if (inChan != outChan) {
	    Tcl_DeleteChannelHandler(outChan, CopyEventProc, csPtr);
	}
	Tcl_DeleteChannelHandler(inChan, MBEvent, csPtr);
	Tcl_DeleteChannelHandler(outChan, MBEvent, csPtr);
	TclDecrRefCount(csPtr->cmdPtr);
	csPtr->cmdPtr = NULL;
    }

    if (inStatePtr->csPtrR) {
	assert(inStatePtr->csPtrR == csPtr);
    inStatePtr->csPtrR = NULL;
    outStatePtr->csPtrW = NULL;
	inStatePtr->csPtrR = NULL;
	CopyDecrRefCount(csPtr);
    }
    if (outStatePtr->csPtrW) {
	assert(outStatePtr->csPtrW == csPtr);
	outStatePtr->csPtrW = NULL;
	CopyDecrRefCount(csPtr);
    }
}

static void
CopyDecrRefCount(
    CopyState *csPtr)
{
    if (csPtr->refCount-- > 1) {
	return;
    }

    TclChannelRelease((Tcl_Channel)csPtr->readPtr);
    TclChannelRelease((Tcl_Channel)csPtr->writePtr);

    Tcl_Free(csPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * StackSetBlockMode --
10197
10198
10199
10200
10201
10202
10203
10204

10205
10206
10207
10208
10209
10210
10211
10508
10509
10510
10511
10512
10513
10514

10515
10516
10517
10518
10519
10520
10521
10522







-
+







	     * Note that we cannot have a message in the interpreter bypass
	     * area, StackSetBlockMode is restricted to the channel bypass.
	     * We still need the interp as the destination of the move.
	     */

	    if (!TclChanCaughtErrorBypass(interp, (Tcl_Channel) chanPtr)) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                        "error setting blocking mode: %s",
			"error setting blocking mode: %s",
			Tcl_PosixError(interp)));
	    }
	} else {
	    /*
	     * TIP #219.
	     * If we have no interpreter to put a bypass message into we have
	     * to clear it, to prevent its propagation and use in other places
10248
10249
10250
10251
10252
10253
10254
10255

10256
10257
10258
10259
10260
10261
10262
10559
10560
10561
10562
10563
10564
10565

10566
10567
10568
10569
10570
10571
10572
10573







-
+







}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetChannelNamesEx --
 *
 *	Return the names of open channels in the interp filtered filtered
 *	Return the names of open channels in the interp filtered
 *	through a pattern. If pattern is NULL, it returns all the open
 *	channels.
 *
 * Results:
 *	TCL_OK or TCL_ERROR.
 *
 * Side effects:
10402
10403
10404
10405
10406
10407
10408
10409

10410
10411
10412
10413
10414
10415
10416
10713
10714
10715
10716
10717
10718
10719

10720
10721
10722
10723
10724
10725
10726
10727







-
+







int
Tcl_IsChannelShared(
    Tcl_Channel chan)		/* The channel to query */
{
    ChannelState *statePtr = ((Channel *) chan)->state;
				/* State of real channel structure. */

    return ((statePtr->refCount + 1 > 2) ? 1 : 0);
    return ((statePtr->refCount > 1) ? 1 : 0);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_IsChannelExisting --
 *
10472
10473
10474
10475
10476
10477
10478
10479


10480
10481
10482
10483
10484
10485
10486
10783
10784
10785
10786
10787
10788
10789

10790
10791
10792
10793
10794
10795
10796
10797
10798







-
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

const char *
Tcl_ChannelName(
    const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */
    const Tcl_ChannelType *chanTypePtr)
				/* Pointer to channel type. */
{
    return chanTypePtr->typeName;
}

/*
 *----------------------------------------------------------------------
 *
10812
10813
10814
10815
10816
10817
10818
10819
10820
10821
10822

10823
10824
10825
10826
10827






10828
10829
10830
10831
10832
10833
10834
11124
11125
11126
11127
11128
11129
11130




11131

11132
11133
11134
11135
11136
11137
11138
11139
11140
11141
11142
11143
11144
11145
11146
11147
11148







-
-
-
-
+
-




+
+
+
+
+
+








void
Tcl_SetChannelErrorInterp(
    Tcl_Interp *interp,		/* Interp to store the data into. */
    Tcl_Obj *msg)		/* Error message to store. */
{
    Interp *iPtr = (Interp *) interp;

    if (iPtr->chanMsg != NULL) {
	TclDecrRefCount(iPtr->chanMsg);
	iPtr->chanMsg = NULL;
    Tcl_Obj *disposePtr = iPtr->chanMsg;
    }

    if (msg != NULL) {
	iPtr->chanMsg = FixLevelCode(msg);
	Tcl_IncrRefCount(iPtr->chanMsg);
    } else {
	iPtr->chanMsg = NULL;
    }

    if (disposePtr != NULL) {
	TclDecrRefCount(disposePtr);
    }
    return;
}

/*
 *----------------------------------------------------------------------
 *
10847
10848
10849
10850
10851
10852
10853
10854

10855
10856
10857
10858

10859
10860
10861
10862
10863






10864
10865
10866
10867
10868
10869
10870
11161
11162
11163
11164
11165
11166
11167

11168




11169

11170
11171
11172
11173
11174
11175
11176
11177
11178
11179
11180
11181
11182
11183
11184
11185
11186







-
+
-
-
-
-
+
-




+
+
+
+
+
+







 */

void
Tcl_SetChannelError(
    Tcl_Channel chan,		/* Channel to store the data into. */
    Tcl_Obj *msg)		/* Error message to store. */
{
    ChannelState *statePtr = ((Channel *) chan)->state;
    ChannelState *statePtr = ((Channel *)chan)->state;

    if (statePtr->chanMsg != NULL) {
	TclDecrRefCount(statePtr->chanMsg);
	statePtr->chanMsg = NULL;
    Tcl_Obj *disposePtr = statePtr->chanMsg;
    }

    if (msg != NULL) {
	statePtr->chanMsg = FixLevelCode(msg);
	Tcl_IncrRefCount(statePtr->chanMsg);
    } else {
	statePtr->chanMsg = NULL;
    }

    if (disposePtr != NULL) {
	TclDecrRefCount(disposePtr);
    }
    return;
}

/*
 *----------------------------------------------------------------------
 *
10884
10885
10886
10887
10888
10889
10890
10891


10892
10893
10894
10895
10896
10897
10898
10899
10900
10901
10902
10903
10904

10905
10906
10907
10908

10909
10910
10911
10912
10913
10914
10915
11200
11201
11202
11203
11204
11205
11206

11207
11208
11209
11210
11211
11212
11213
11214
11215
11216
11217
11218
11219
11220

11221
11222
11223
11224

11225
11226
11227
11228
11229
11230
11231
11232







-
+
+












-
+



-
+







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

static Tcl_Obj *
FixLevelCode(
    Tcl_Obj *msg)
{
    int explicitResult, numOptions, lc, lcn;
    int explicitResult, numOptions, lcn;
    Tcl_Size lc;
    Tcl_Obj **lv, **lvn;
    int res, i, j, val, lignore, cignore;
    int newlevel = -1, newcode = -1;

    /* ASSERT msg != NULL */

    /*
     * Process the caught message.
     *
     * Syntax = (option value)... ?message?
     *
     * Bad message syntax causes a panic, because the other side uses
     * Tcl_GetReturnOptions and list construction functions to marshall the
     * Tcl_GetReturnOptions and list construction functions to marshal the
     * information. Hence an error means that we've got serious breakage.
     */

    res = Tcl_ListObjGetElements(NULL, msg, &lc, &lv);
    res = TclListObjGetElements(NULL, msg, &lc, &lv);
    if (res != TCL_OK) {
	Tcl_Panic("Tcl_SetChannelError: bad syntax of message");
    }

    explicitResult = (1 == (lc % 2));
    numOptions = lc - explicitResult;

10966
10967
10968
10969
10970
10971
10972
10973
10974


10975
10976
10977
10978
10979
10980
10981
11283
11284
11285
11286
11287
11288
11289


11290
11291
11292
11293
11294
11295
11296
11297
11298







-
-
+
+







    if (newcode >= 0) {
	lcn += 2;
    }

    lvn = (Tcl_Obj **)Tcl_Alloc(lcn * sizeof(Tcl_Obj *));

    /*
     * New level/code information is spliced into the first occurence of
     * -level, -code, further occurences are ignored. The options cannot be
     * New level/code information is spliced into the first occurrence of
     * -level, -code, further occurrences are ignored. The options cannot be
     * not present, we would not come here. Options which are ok are simply
     * copied over.
     */

    lignore = cignore = 0;
    for (i=0, j=0; i<numOptions; i+=2) {
	if (0 == strcmp(TclGetString(lv[i]), "-level")) {
11104
11105
11106
11107
11108
11109
11110
11111

11112
11113
11114
11115
11116
11117
11118
11119
11120
11121
11122
11123
11124
11125
11126
11127

11128
11129
11130
11131
11132
11133
11134
11135

11136
11137

11138
11139
11140
11141
11142
11143

11144
11145
11146
11147
11148
11149
11150
11151
11152
11153
11154
11155
11156
11157

11158
11159
11160
11161
11162

11163
11164
11165
11166
11167
11168
11169
11170
11171
11172
11173
11174
11175
11176
11177
11178
11179
11180
11181
11182
11183

11184
11185
11186
11187
11188
11189
11190
11191
11192
11193
11194
11195

11196
11197
11198
11199
11200
11201
11202
11421
11422
11423
11424
11425
11426
11427

11428
11429
11430
11431
11432
11433
11434
11435
11436
11437
11438
11439
11440
11441
11442
11443

11444
11445
11446
11447
11448
11449
11450
11451

11452
11453

11454
11455
11456
11457
11458
11459

11460
11461
11462
11463
11464
11465
11466
11467
11468
11469
11470
11471
11472
11473

11474
11475
11476
11477
11478

11479
11480
11481
11482
11483
11484
11485
11486
11487
11488
11489
11490
11491
11492
11493
11494
11495
11496
11497
11498

11499
11500
11501
11502
11503
11504
11505
11506
11507
11508
11509
11510
11511
11512
11513
11514
11515
11516
11517
11518
11519
11520







-
+















-
+







-
+

-
+





-
+













-
+




-
+



















-

+












+







{
    return chanTypePtr->truncateProc;
}

/*
 *----------------------------------------------------------------------
 *
 * DupChannelIntRep --
 * DupChannelInternalRep --
 *
 *	Initialize the internal representation of a new Tcl_Obj to a copy of
 *	the internal representation of an existing string object.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	copyPtr's internal rep is set to a copy of srcPtr's internal
 *	representation.
 *
 *----------------------------------------------------------------------
 */

static void
DupChannelIntRep(
DupChannelInternalRep(
    Tcl_Obj *srcPtr,	/* Object with internal rep to copy. Must have
				 * an internal rep of type "Channel". */
    Tcl_Obj *copyPtr)	/* Object with internal rep to set. Must not
				 * currently have an internal rep.*/
{
    ResolvedChanName *resPtr;

    ChanGetIntRep(srcPtr, resPtr);
    ChanGetInternalRep(srcPtr, resPtr);
    assert(resPtr);
    ChanSetIntRep(copyPtr, resPtr);
    ChanSetInternalRep(copyPtr, resPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * FreeChannelIntRep --
 * FreeChannelInternalRep --
 *
 *	Release statePtr storage.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	May cause state to be freed.
 *
 *----------------------------------------------------------------------
 */

static void
FreeChannelIntRep(
FreeChannelInternalRep(
    Tcl_Obj *objPtr)		/* Object with internal rep to free. */
{
    ResolvedChanName *resPtr;

    ChanGetIntRep(objPtr, resPtr);
    ChanGetInternalRep(objPtr, resPtr);
    assert(resPtr);
    if (resPtr->refCount-- > 1) {
	return;
    }
    Tcl_Release(resPtr->statePtr);
    Tcl_Free(resPtr);
}

#if 0
/*
 * For future debugging work, a simple function to print the flags of a
 * channel in semi-readable form.
 */

static int
DumpFlags(
    char *str,
    int flags)
{
    char buf[20];
    int i = 0;
    char buf[24];

#define ChanFlag(chr, bit)      (buf[i++] = ((flags & (bit)) ? (chr) : '_'))

    ChanFlag('r', TCL_READABLE);
    ChanFlag('w', TCL_WRITABLE);
    ChanFlag('n', CHANNEL_NONBLOCKING);
    ChanFlag('l', CHANNEL_LINEBUFFERED);
    ChanFlag('u', CHANNEL_UNBUFFERED);
    ChanFlag('F', BG_FLUSH_SCHEDULED);
    ChanFlag('c', CHANNEL_CLOSED);
    ChanFlag('E', CHANNEL_EOF);
    ChanFlag('S', CHANNEL_STICKY_EOF);
    ChanFlag('U', CHANNEL_ENCODING_ERROR);
    ChanFlag('B', CHANNEL_BLOCKED);
    ChanFlag('/', INPUT_SAW_CR);
    ChanFlag('D', CHANNEL_DEAD);
    ChanFlag('R', CHANNEL_RAW_MODE);
    ChanFlag('x', CHANNEL_INCLOSE);

    buf[i] ='\0';

Changes to generic/tclIO.h.

32
33
34
35
36
37
38
39
40


41
42

43
44

45
46
47
48



49
50
51
52
53
54
55
32
33
34
35
36
37
38


39
40
41

42
43

44
45



46
47
48
49
50
51
52
53
54
55







-
-
+
+

-
+

-
+

-
-
-
+
+
+







/*
 * struct ChannelBuffer:
 *
 * Buffers data being sent to or from a channel.
 */

typedef struct ChannelBuffer {
    size_t refCount;		/* Current uses count */
    int nextAdded;		/* The next position into which a character
    Tcl_Size refCount;		/* Current uses count */
    Tcl_Size nextAdded;		/* The next position into which a character
				 * will be put in the buffer. */
    int nextRemoved;		/* Position of next byte to be removed from
    Tcl_Size nextRemoved;	/* Position of next byte to be removed from
				 * the buffer. */
    int bufLength;		/* How big is the buffer? */
    Tcl_Size bufLength;		/* How big is the buffer? */
    struct ChannelBuffer *nextPtr;
    				/* Next buffer in chain. */
    char buf[TCLFLEXARRAY];		/* Placeholder for real buffer. The real
				 * buffer occuppies this space + bufSize-1
				/* Next buffer in chain. */
    char buf[TCLFLEXARRAY];	/* Placeholder for real buffer. The real
				 * buffer occupies this space + bufSize-1
				 * bytes. This must be the last field in the
				 * structure. */
} ChannelBuffer;

#define CHANNELBUFFER_HEADER_SIZE	offsetof(ChannelBuffer, buf)

/*
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
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







-
+
















-
+















-
+







 * data specific to the channel but which belongs to the generic part of the
 * Tcl channel mechanism, and it points at an instance specific (and type
 * specific) instance data, and at a channel type structure.
 */

typedef struct Channel {
    struct ChannelState *state; /* Split out state information */
    void *instanceData;	/* Instance-specific data provided by creator
    void *instanceData;		/* Instance-specific data provided by creator
				 * of channel. */
    const Tcl_ChannelType *typePtr; /* Pointer to channel type structure. */
    struct Channel *downChanPtr;/* Refers to channel this one was stacked
				 * upon. This reference is NULL for normal
				 * channels. See Tcl_StackChannel. */
    struct Channel *upChanPtr;	/* Refers to the channel above stacked this
				 * one. NULL for the top most channel. */

    /*
     * Intermediate buffers to hold pre-read data for consumption by a newly
     * stacked transformation. See 'Tcl_StackChannel'.
     */

    ChannelBuffer *inQueueHead;	/* Points at first buffer in input queue. */
    ChannelBuffer *inQueueTail;	/* Points at last buffer in input queue. */

    size_t refCount;
    Tcl_Size refCount;
} Channel;

/*
 * struct ChannelState:
 *
 * One of these structures is allocated for each open channel. It contains
 * data specific to the channel but which belongs to the generic part of the
 * Tcl channel mechanism, and it points at an instance specific (and type
 * specific) instance data, and at a channel type structure.
 */

typedef struct ChannelState {
    char *channelName;		/* The name of the channel instance in Tcl
				 * commands. Storage is owned by the generic
				 * IO code, is dynamically allocated. */
    int	flags;			/* ORed combination of the flags defined
    int	flags;			/* OR'ed combination of the flags defined
				 * below. */
    Tcl_Encoding encoding;	/* Encoding to apply when reading or writing
				 * data on this channel. NULL means no
				 * encoding is applied to data. */
    Tcl_EncodingState inputEncodingState;
				/* Current encoding state, used when
				 * converting input data bytes to UTF-8. */
154
155
156
157
158
159
160

161
162



163
164
165
166

167
168
169
170
171
172
173
154
155
156
157
158
159
160
161
162

163
164
165
166
167
168

169
170
171
172
173
174
175
176







+

-
+
+
+



-
+







				/* What translation to apply for end of line
				 * sequences on input? */
    TclEolTranslation outputTranslation;
				/* What translation to use for generating end
				 * of line sequences in output? */
    int inEofChar;		/* If nonzero, use this as a signal of EOF on
				 * input. */
#if TCL_MAJOR_VERSION < 9
    int outEofChar;		/* If nonzero, append this to the channel when
				 * it is closed if it is open for writing. */
				 * it is closed if it is open for writing.
				 * For Tcl 8.x only */
#endif
    int unreportedError;	/* Non-zero if an error report was deferred
				 * because it happened in the background. The
				 * value is the POSIX error code. */
    size_t refCount;		/* How many interpreters hold references to
    Tcl_Size refCount;		/* How many interpreters hold references to
				 * this IO channel? */
    struct CloseCallback *closeCbPtr;
				/* Callbacks registered to be called when the
				 * channel is closed. */
    char *outputStage;		/* Temporary staging buffer used when
				 * translating EOL before converting from
				 * UTF-8 to external form. */
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
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







-
+

+
+
+


















-
+


-
-
+
+



-
+

+
+



-
+





-
+

-
-
-
-







    struct ChannelHandler *chPtr;/* List of channel handlers registered for
				  * this channel. */
    int interestMask;		/* Mask of all events this channel has
				 * handlers for. */
    EventScriptRecord *scriptRecordPtr;
				/* Chain of all scripts registered for event
				 * handlers ("fileevent") on this channel. */
    int bufSize;		/* What size buffers to allocate? */
    Tcl_Size bufSize;		/* What size buffers to allocate? */
    Tcl_TimerToken timer;	/* Handle to wakeup timer for this channel. */
    Channel *timerChanPtr;	/* Needed in order to decrement the refCount of
				 * the right channel when the timer is
				 * deleted. */
    struct CopyState *csPtrR;	/* State of background copy for which channel
				 * is input, or NULL. */
    struct CopyState *csPtrW;	/* State of background copy for which channel
				 * is output, or NULL. */
    Channel *topChanPtr;	/* Refers to topmost channel in a stack. Never
				 * NULL. */
    Channel *bottomChanPtr;	/* Refers to bottommost channel in a stack.
				 * This channel can be relied on to live as
				 * long as the channel state. Never NULL. */
    struct ChannelState *nextCSPtr;
				/* Next in list of channels currently open. */
    Tcl_ThreadId managingThread;/* TIP #10: Id of the thread managing this
				 * stack of channels. */

    /*
     * TIP #219 ... Info for the I/O system ...
     * Error message set by channel drivers, for the propagation of arbitrary
     * Tcl errors. This information, if present (chanMsg not NULL), takes
     * precedence over a posix error code returned by a channel operation.
     * precedence over a Posix error code returned by a channel operation.
     */

    Tcl_Obj* chanMsg;
    Tcl_Obj* unreportedMsg;     /* Non-NULL if an error report was deferred
    Tcl_Obj *chanMsg;
    Tcl_Obj *unreportedMsg;	/* Non-NULL if an error report was deferred
				 * because it happened in the background. The
				 * value is the chanMg, if any. #219's
				 * companion to 'unreportedError'. */
    size_t epoch;		/* Used to test validity of stored channelname
    Tcl_Size epoch;		/* Used to test validity of stored channelname
				 * lookup results. */
    int maxPerms;		/* TIP #220: Max access privileges
				 * the channel was created with. */
} ChannelState;

/*
 * Values for the flags field in Channel. Any ORed combination of the
 * Values for the flags field in Channel. Any OR'ed combination of the
 * following flags can be stored in the field. These flags record various
 * options and state bits about the channel. In addition to the flags below,
 * the channel can also have TCL_READABLE (1<<1) and TCL_WRITABLE (1<<2) set.
 */

#define CHANNEL_NONBLOCKING	(1<<3)	/* Channel is currently in nonblocking
#define CHANNEL_NONBLOCKING	(1<<6)	/* Channel is currently in nonblocking
					 * mode. */
#define CHANNEL_LINEBUFFERED	(1<<4)	/* Output to the channel must be
					 * flushed after every newline. */
#define CHANNEL_UNBUFFERED	(1<<5)	/* Output to the channel must always
					 * be flushed immediately. */
#define BG_FLUSH_SCHEDULED	(1<<7)	/* A background flush of the queued
					 * output buffers has been
					 * scheduled. */
#define CHANNEL_CLOSED		(1<<8)	/* Channel has been closed. No further
					 * Tcl-level IO on the channel is
					 * allowed. */
#define CHANNEL_EOF		(1<<9)	/* EOF occurred on this channel. This
265
266
267
268
269
270
271


272
273
274




275
276
277
278
279
280
281
269
270
271
272
273
274
275
276
277
278
279

280
281
282
283
284
285
286
287
288
289
290







+
+


-
+
+
+
+







					 * flag is set when gets fails to get
					 * a complete line or when read fails
					 * to get a complete character. When
					 * set, file events will not be
					 * delivered for buffered data until
					 * the state of the channel
					 * changes. */
#define CHANNEL_ENCODING_ERROR	(1<<15)	/* set if channel
					 * encountered an encoding error */
#define CHANNEL_RAW_MODE	(1<<16)	/* When set, notes that the Raw API is
					 * being used. */

#define CHANNEL_LINEBUFFERED	(1<<17)	/* Output to the channel must be
					 * flushed after every newline. */
#define CHANNEL_UNBUFFERED	(1<<18)	/* Output to the channel must always
					 * be flushed immediately. */
#define CHANNEL_INCLOSE		(1<<19)	/* Channel is currently being closed.
					 * Its structures are still live and
					 * usable, but it may not be closed
					 * again from within the close
					 * handler. */
#define CHANNEL_CLOSEDWRITE	(1<<21)	/* Channel write side has been closed.
					 * No further Tcl-level write IO on

Changes to generic/tclIOCmd.c.

1
2
3
4
5
6

7
8
9
10
11
12


13
14
15
16
17
18
19
1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21





-
+






+
+







/*
 * tclIOCmd.c --
 *
 *	Contains the definitions of most of the Tcl commands relating to IO.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclIO.h"
#include "tclTomMath.h"

/*
 * Callback structure for accept callback in a TCP server.
 */

typedef struct {
    Tcl_Obj *script;		/* Script to invoke. */
33
34
35
36
37
38
39
40

41
42
43
44
45



46
47

48
49
50
51
52
53
54
35
36
37
38
39
40
41

42
43
44



45
46
47
48

49
50
51
52
53
54
55
56







-
+


-
-
-
+
+
+

-
+







static Tcl_ThreadDataKey dataKey;

/*
 * Static functions for this file:
 */

static Tcl_ExitProc		FinalizeIOCmdTSD;
static Tcl_TcpAcceptProc 	AcceptCallbackProc;
static Tcl_TcpAcceptProc	AcceptCallbackProc;
static Tcl_ObjCmdProc		ChanPendingObjCmd;
static Tcl_ObjCmdProc		ChanTruncateObjCmd;
static void			RegisterTcpServerInterpCleanup(
				    Tcl_Interp *interp,
				    AcceptCallback *acceptCallbackPtr);
static void		RegisterTcpServerInterpCleanup(
			    Tcl_Interp *interp,
			    AcceptCallback *acceptCallbackPtr);
static Tcl_InterpDeleteProc	TcpAcceptCallbacksDeleteProc;
static void		TcpServerCloseProc(ClientData callbackData);
static void		TcpServerCloseProc(void *callbackData);
static void		UnregisterTcpServerInterpCleanupProc(
			    Tcl_Interp *interp,
			    AcceptCallback *acceptCallbackPtr);

/*
 *----------------------------------------------------------------------
 *
63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
65
66
67
68
69
70
71

72
73
74
75
76
77
78
79







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
FinalizeIOCmdTSD(
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (tsdPtr->stdoutObjPtr != NULL) {
	Tcl_DecrRefCount(tsdPtr->stdoutObjPtr);
	tsdPtr->stdoutObjPtr = NULL;
    }
93
94
95
96
97
98
99
100

101
102
103
104
105
106
107
108
109

110
111
112
113
114
115
116
95
96
97
98
99
100
101

102
103
104
105
106
107
108
109
110

111
112
113
114
115
116
117
118







-
+








-
+







 *	Produces output on a channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_PutsObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Channel chan;		/* The channel to puts on. */
    Tcl_Obj *string;		/* String to write. */
    Tcl_Obj *chanObjPtr = NULL;	/* channel object. */
    int newline;		/* Add a newline at end? */
    int result;			/* Result of puts operation. */
    Tcl_Size result;		/* Result of puts operation. */
    int mode;			/* Mode in which channel is opened. */

    switch (objc) {
    case 2:			/* [puts $x] */
	string = objv[1];
	newline = 1;
	break;
132
133
134
135
136
137
138
139

140
141
142
143
144
145
146
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148







-
+







	    chanObjPtr = objv[2];
	    string = objv[3];
	    break;
	}
	/* Fall through */
    default:			/* [puts] or
				 * [puts some bad number of arguments...] */
	Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? ?channelId? string");
	Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? ?channel? string");
	return TCL_ERROR;
    }

    if (chanObjPtr == NULL) {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	if (!tsdPtr->initialized) {
159
160
161
162
163
164
165
166

167
168
169
170
171

172
173
174
175
176
177
178
161
162
163
164
165
166
167

168
169
170
171
172

173
174
175
176
177
178
179
180







-
+




-
+







		"channel \"%s\" wasn't opened for writing",
		TclGetString(chanObjPtr)));
	return TCL_ERROR;
    }

    TclChannelPreserve(chan);
    result = Tcl_WriteObj(chan, string);
    if (result == -1) {
    if (result == TCL_INDEX_NONE) {
	goto error;
    }
    if (newline != 0) {
	result = Tcl_WriteChars(chan, "\n", 1);
	if (result == -1) {
	if (result == TCL_INDEX_NONE) {
	    goto error;
	}
    }
    TclChannelRelease(chan);
    return TCL_OK;

    /*
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
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







-
+









-
+







 *	May cause output to appear on the specified channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FlushObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *chanObjPtr;
    Tcl_Channel chan;		/* The channel to flush on. */
    int mode;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "channelId");
	Tcl_WrongNumArgs(interp, 1, objv, "channel");
	return TCL_ERROR;
    }
    chanObjPtr = objv[1];
    if (TclGetChannelFromObj(interp, chanObjPtr, &chan, &mode, 0) != TCL_OK) {
	return TCL_ERROR;
    }
    if (!(mode & TCL_WRITABLE)) {
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
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







-
+





-
+





-
+
















-
+


















-
+







+
+
-
+







 *	May consume input from channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_GetsObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Channel chan;		/* The channel to read from. */
    int lineLen;		/* Length of line just read. */
    Tcl_Size lineLen;		/* Length of line just read. */
    int mode;			/* Mode in which channel is opened. */
    Tcl_Obj *linePtr, *chanObjPtr;
    int code = TCL_OK;

    if ((objc != 2) && (objc != 3)) {
	Tcl_WrongNumArgs(interp, 1, objv, "channelId ?varName?");
	Tcl_WrongNumArgs(interp, 1, objv, "channel ?varName?");
	return TCL_ERROR;
    }
    chanObjPtr = objv[1];
    if (TclGetChannelFromObj(interp, chanObjPtr, &chan, &mode, 0) != TCL_OK) {
	return TCL_ERROR;
    }
    if (!(mode & TCL_READABLE)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"channel \"%s\" wasn't opened for reading",
		TclGetString(chanObjPtr)));
	return TCL_ERROR;
    }

    TclChannelPreserve(chan);
    TclNewObj(linePtr);
    lineLen = Tcl_GetsObj(chan, linePtr);
    if (lineLen < 0) {
    if (lineLen == TCL_IO_FAILURE) {
	if (!Tcl_Eof(chan) && !Tcl_InputBlocked(chan)) {
	    Tcl_DecrRefCount(linePtr);

	    /*
	     * TIP #219.
	     * Capture error messages put by the driver into the bypass area
	     * and put them into the regular interpreter result. Fall back to
	     * the regular message if nothing was found in the bypass.
	     */

	    if (!TclChanCaughtErrorBypass(interp, chan)) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"error reading \"%s\": %s",
			TclGetString(chanObjPtr), Tcl_PosixError(interp)));
	    }
	    code = TCL_ERROR;
	    goto done;
	}
	lineLen = -1;
	lineLen = TCL_IO_FAILURE;
    }
    if (objc == 3) {
	if (Tcl_ObjSetVar2(interp, objv[2], NULL, linePtr,
		TCL_LEAVE_ERR_MSG) == NULL) {
	    code = TCL_ERROR;
	    goto done;
	}
	Tcl_Obj *lineLenObj;
	TclNewIndexObj(lineLenObj, lineLen);
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(lineLen));
	Tcl_SetObjResult(interp, lineLenObj);
    } else {
	Tcl_SetObjResult(interp, linePtr);
    }
  done:
    TclChannelRelease(chan);
    return code;
}
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
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







-
+






-
-
+
+








-
+







-
+







 *	May consume input from channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ReadObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Channel chan;		/* The channel to read from. */
    int newline, i;		/* Discard newline at end? */
    int toRead;			/* How many bytes to read? */
    int charactersRead;		/* How many characters were read? */
    Tcl_WideInt toRead;			/* How many bytes to read? */
    Tcl_Size charactersRead;		/* How many characters were read? */
    int mode;			/* Mode in which channel is opened. */
    Tcl_Obj *resultPtr, *chanObjPtr;

    if ((objc != 2) && (objc != 3)) {
	Interp *iPtr;

    argerror:
	iPtr = (Interp *) interp;
	Tcl_WrongNumArgs(interp, 1, objv, "channelId ?numChars?");
	Tcl_WrongNumArgs(interp, 1, objv, "channel ?numChars?");

	/*
	 * Do not append directly; that makes ensembles using this command as
	 * a subcommand produce the wrong message.
	 */

	iPtr->flags |= INTERP_ALTERNATE_WRONG_ARGS;
	Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? channelId");
	Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? channel");
	return TCL_ERROR;
    }

    i = 1;
    newline = 0;
    if (strcmp(TclGetString(objv[1]), "-nonewline") == 0) {
	newline = 1;
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
467
468
469
470
471
472
473
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
467
468
469

470
471
472
473
474
475
476
477
478

479
480
481
482
483
484
485







-
+

-
-
-
-
-
+
+
+
+
+




-


-
+
+
+
+
+
+
+
+
+













-
+
+
+









-
+








-








    /*
     * Compute how many bytes to read.
     */

    toRead = -1;
    if (i < objc) {
	if ((TclGetIntFromObj(interp, objv[i], &toRead) != TCL_OK)
	if ((TclGetWideIntFromObj(NULL, objv[i], &toRead) != TCL_OK)
		|| (toRead < 0)) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"expected non-negative integer but got \"%s\"",
			TclGetString(objv[i])));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "NUMBER", NULL);
		return TCL_ERROR;
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "expected non-negative integer but got \"%s\"",
		    TclGetString(objv[i])));
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "NUMBER", (char *)NULL);
	    return TCL_ERROR;
	}
    }

    TclNewObj(resultPtr);
    Tcl_IncrRefCount(resultPtr);
    TclChannelPreserve(chan);
    charactersRead = Tcl_ReadChars(chan, resultPtr, toRead, 0);
    if (charactersRead < 0) {
    if (charactersRead == TCL_IO_FAILURE) {
	Tcl_Obj *returnOptsPtr = NULL;
	if (TclChannelGetBlockingMode(chan)) {
	    returnOptsPtr = Tcl_NewDictObj();
	    Tcl_DictObjPut(NULL, returnOptsPtr, Tcl_NewStringObj("-data", -1),
		    resultPtr);
	} else {
	    Tcl_DecrRefCount(resultPtr);
	}
	/*
	 * TIP #219.
	 * Capture error messages put by the driver into the bypass area and
	 * put them into the regular interpreter result. Fall back to the
	 * regular message if nothing was found in the bypass.
	 */

	if (!TclChanCaughtErrorBypass(interp, chan)) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "error reading \"%s\": %s",
		    TclGetString(chanObjPtr), Tcl_PosixError(interp)));
	}
	TclChannelRelease(chan);
	Tcl_DecrRefCount(resultPtr);
	if (returnOptsPtr) {
	    Tcl_SetReturnOptions(interp, returnOptsPtr);
	}
	return TCL_ERROR;
    }

    /*
     * If requested, remove the last newline in the channel if at EOF.
     */

    if ((charactersRead > 0) && (newline != 0)) {
	const char *result;
	size_t length;
	Tcl_Size length;

	result = TclGetStringFromObj(resultPtr, &length);
	if (result[length - 1] == '\n') {
	    Tcl_SetObjLength(resultPtr, length - 1);
	}
    }
    Tcl_SetObjResult(interp, resultPtr);
    TclChannelRelease(chan);
    Tcl_DecrRefCount(resultPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SeekObjCmd --
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
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







-
+















-
+





-
+







 *	flush queued output.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_SeekObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Channel chan;		/* The channel to tell on. */
    Tcl_WideInt offset;		/* Where to seek? */
    int mode;			/* How to seek? */
    Tcl_WideInt result;		/* Of calling Tcl_Seek. */
    int optionIndex;
    static const char *const originOptions[] = {
	"start", "current", "end", NULL
    };
    static const int modeArray[] = {SEEK_SET, SEEK_CUR, SEEK_END};

    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 1, objv, "channelId offset ?origin?");
	Tcl_WrongNumArgs(interp, 1, objv, "channel offset ?origin?");
	return TCL_ERROR;
    }
    if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
	return TCL_ERROR;
    }
    if (Tcl_GetWideIntFromObj(interp, objv[2], &offset) != TCL_OK) {
    if (TclGetWideIntFromObj(interp, objv[2], &offset) != TCL_OK) {
	return TCL_ERROR;
    }
    mode = SEEK_SET;
    if (objc == 4) {
	if (Tcl_GetIndexFromObj(interp, objv[3], originOptions, "origin", 0,
		&optionIndex) != TCL_OK) {
	    return TCL_ERROR;
558
559
560
561
562
563
564
565

566
567
568
569
570
571
572
573
574
575

576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
570
571
572
573
574
575
576

577
578
579
580
581
582
583
584
585
586

587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607

608
609
610
611
612
613
614







-
+









-
+




















-







 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_TellObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Channel chan;		/* The channel to tell on. */
    Tcl_WideInt newLoc;
    int code;

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

    /*
     * Try to find a channel with the right name and permissions in the IO
     * channel table of this interpreter.
     */

    if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
	return TCL_ERROR;
    }

    TclChannelPreserve(chan);
    newLoc = Tcl_Tell(chan);

    /*
     * TIP #219.
     * Capture error messages put by the driver into the bypass area and put
     * them into the regular interpreter result.
     */


    code  = TclChanCaughtErrorBypass(interp, chan);
    TclChannelRelease(chan);
    if (code) {
	return TCL_ERROR;
    }

620
621
622
623
624
625
626
627

628
629
630
631
632
633
634
635
636
637
638
639

640
641
642
643
644
645
646
631
632
633
634
635
636
637

638
639
640
641
642
643
644
645
646
647
648
649

650
651
652
653
654
655
656
657







-
+











-
+







 *	May discard queued input; may flush queued output.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_CloseObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Channel chan;		/* The channel to close. */
    static const char *const dirOptions[] = {
	"read", "write", NULL
    };
    static const int dirArray[] = {TCL_CLOSE_READ, TCL_CLOSE_WRITE};

    if ((objc != 2) && (objc != 3)) {
	Tcl_WrongNumArgs(interp, 1, objv, "channelId ?direction?");
	Tcl_WrongNumArgs(interp, 1, objv, "channel ?direction?");
	return TCL_ERROR;
    }

    if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
	return TCL_ERROR;
    }

693
694
695
696
697
698
699
700

701
702
703
704
705
706
707
704
705
706
707
708
709
710

711
712
713
714
715
716
717
718







-
+







	 * messages produced by drivers during the closing of a channel,
	 * because the Tcl convention is that such error messages do not have
	 * a terminating newline.
	 */

	Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
	const char *string;
	size_t len;
	Tcl_Size len;

	if (Tcl_IsShared(resultPtr)) {
	    resultPtr = Tcl_DuplicateObj(resultPtr);
	    Tcl_SetObjResult(interp, resultPtr);
	}
	string = TclGetStringFromObj(resultPtr, &len);
	if ((len > 0) && (string[len - 1] == '\n')) {
728
729
730
731
732
733
734
735

736
737
738
739
740
741
742
743
744
745

746
747
748
749
750
751
752
739
740
741
742
743
744
745

746
747
748
749
750
751
752
753
754
755

756
757
758
759
760
761
762
763







-
+









-
+







 *	May modify the behavior of an IO channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FconfigureObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *optionName, *valueName;
    Tcl_Channel chan;		/* The channel to set a mode on. */
    int i;			/* Iterate over arg-value pairs. */

    if ((objc < 2) || (((objc % 2) == 1) && (objc != 3))) {
	Tcl_WrongNumArgs(interp, 1, objv, "channelId ?-option value ...?");
	Tcl_WrongNumArgs(interp, 1, objv, "channel ?-option value ...?");
	return TCL_ERROR;
    }

    if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
	return TCL_ERROR;
    }

803
804
805
806
807
808
809
810

811
812
813
814
815
816
817
818

819
820
821
822
823
824
825
826
827
828








































829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849

850
851
852
853
854
855
856
857
858
859
860

861
862
863
864
865
866
867
814
815
816
817
818
819
820

821
822
823
824
825
826
827
828

829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899

900
901
902
903
904
905
906
907
908
909
910

911
912
913
914
915
916
917
918







-
+







-
+










+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




















-
+










-
+







 *	specified channel has an EOF condition.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_EofObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Channel chan;

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

    if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Tcl_Eof(chan)));
    return TCL_OK;
}

/*
 *---------------------------------------------------------------------------
 *
 * ChanIsBinaryCmd --
 *
 *	This function is invoked to process the Tcl "chan isbinary" command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Sets interp's result to boolean true or false depending on whether the
 *	specified channel is a binary channel.
 *
 *---------------------------------------------------------------------------
 */

static int
ChanIsBinaryCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Channel chan;

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

    if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(TclChanIsBinary(chan)));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ExecObjCmd --
 *
 *	This function is invoked to process the "exec" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ExecObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *resultPtr;
    const char **argv;		/* An array for the string arguments. Stored
				 * on the _Tcl_ stack. */
    const char *string;
    Tcl_Channel chan;
    int argc, background, i, index, keepNewline, result, skip, ignoreStderr;
    size_t length;
    Tcl_Size length;
    static const char *const options[] = {
	"-ignorestderr", "-keepnewline", "--", NULL
    };
    enum execOptionsEnum {
	EXEC_IGNORESTDERR, EXEC_KEEPNEWLINE, EXEC_LAST
    };

930
931
932
933
934
935
936





937
938
939
940
941
942
943
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999







+
+
+
+
+







     */

    TclStackFree(interp, (void *) argv);

    if (chan == NULL) {
	return TCL_ERROR;
    }

    /* Bug [0f1ddc0df7] - encoding errors - use replace profile */
    if (Tcl_SetChannelOption(NULL, chan, "-profile", "replace") != TCL_OK) {
	return TCL_ERROR;
    }

    if (background) {
	/*
	 * Store the list of PIDs from the pipeline in interp's result and
	 * detach the PIDs (instead of waiting for them).
	 */

1002
1003
1004
1005
1006
1007
1008
1009

1010
1011
1012
1013
1014
1015
1016

1017
1018
1019
1020
1021
1022
1023
1024
1025

1026
1027
1028
1029
1030
1031
1032
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







-
+






-
+








-
+







 *	the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Sets interp's result to boolean true or false depending on whether the
 *	preceeding input operation on the channel would have blocked.
 *	preceding input operation on the channel would have blocked.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_FblockedObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Channel chan;
    int mode;

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

    if (TclGetChannelFromObj(interp, objv[1], &chan, &mode, 0) != TCL_OK) {
	return TCL_ERROR;
    }
    if (!(mode & TCL_READABLE)) {
1055
1056
1057
1058
1059
1060
1061
1062

1063
1064
1065
1066
1067
1068
1069
1111
1112
1113
1114
1115
1116
1117

1118
1119
1120
1121
1122
1123
1124
1125







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_OpenObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int pipeline, prot;
    const char *modeString, *what;
    Tcl_Channel chan;
1113
1114
1115
1116
1117
1118
1119
1120


1121
1122
1123
1124
1125
1126
1127

1128
1129
1130
1131
1132
1133

1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148

1149
1150
1151
1152
1153
1154
1155
1169
1170
1171
1172
1173
1174
1175

1176
1177
1178
1179
1180
1181
1182
1183

1184
1185
1186
1187
1188
1189

1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204

1205
1206
1207
1208
1209
1210
1211
1212







-
+
+






-
+





-
+














-
+







    /*
     * Open the file or create a process pipeline.
     */

    if (!pipeline) {
	chan = Tcl_FSOpenFileChannel(interp, objv[1], modeString, prot);
    } else {
	int mode, seekFlag, cmdObjc, binary;
	int mode, modeFlags;
	Tcl_Size cmdObjc;
	const char **cmdArgv;

	if (Tcl_SplitList(interp, what+1, &cmdObjc, &cmdArgv) != TCL_OK) {
	    return TCL_ERROR;
	}

	mode = TclGetOpenModeEx(interp, modeString, &seekFlag, &binary);
	mode = TclGetOpenMode(interp, modeString, &modeFlags);
	if (mode == -1) {
	    chan = NULL;
	} else {
	    int flags = TCL_STDERR | TCL_ENFORCE_MODE;

	    switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) {
	    switch (mode & O_ACCMODE) {
	    case O_RDONLY:
		flags |= TCL_STDOUT;
		break;
	    case O_WRONLY:
		flags |= TCL_STDIN;
		break;
	    case O_RDWR:
		flags |= (TCL_STDIN | TCL_STDOUT);
		break;
	    default:
		Tcl_Panic("Tcl_OpenCmd: invalid mode value");
		break;
	    }
	    chan = Tcl_OpenCommandChannel(interp, cmdObjc, cmdArgv, flags);
	    if (binary && chan) {
	    if ((modeFlags & CHANNEL_RAW_MODE) && chan) {
		Tcl_SetChannelOption(interp, chan, "-translation", "binary");
	    }
	}
	Tcl_Free((void *)cmdArgv);
    }
    if (chan == NULL) {
	return TCL_ERROR;
1178
1179
1180
1181
1182
1183
1184
1185

1186
1187
1188
1189
1190
1191
1192
1235
1236
1237
1238
1239
1240
1241

1242
1243
1244
1245
1246
1247
1248
1249







-
+







 *	subsequently to eval accept scripts.
 *
 *----------------------------------------------------------------------
 */

static void
TcpAcceptCallbacksDeleteProc(
    ClientData clientData,	/* Data which was passed when the assocdata
    void *clientData,	/* Data which was passed when the assocdata
				 * was registered. */
    TCL_UNUSED(Tcl_Interp *))
{
    Tcl_HashTable *hTblPtr = (Tcl_HashTable *)clientData;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch hSearch;

1281
1282
1283
1284
1285
1286
1287
1288

1289
1290
1291
1292
1293
1294
1295
1338
1339
1340
1341
1342
1343
1344

1345
1346
1347
1348
1349
1350
1351
1352







-
+







    Tcl_HashEntry *hPtr;

    hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, "tclTCPAcceptCallbacks", NULL);
    if (hTblPtr == NULL) {
	return;
    }

    hPtr = Tcl_FindHashEntry(hTblPtr, (char *) acceptCallbackPtr);
    hPtr = Tcl_FindHashEntry(hTblPtr, acceptCallbackPtr);
    if (hPtr != NULL) {
	Tcl_DeleteHashEntry(hPtr);
    }
}

/*
 *----------------------------------------------------------------------
1306
1307
1308
1309
1310
1311
1312
1313

1314
1315
1316
1317
1318
1319
1320
1363
1364
1365
1366
1367
1368
1369

1370
1371
1372
1373
1374
1375
1376
1377







-
+







 *	Whatever the script does.
 *
 *----------------------------------------------------------------------
 */

static void
AcceptCallbackProc(
    ClientData callbackData,	/* The data stored when the callback was
    void *callbackData,	/* The data stored when the callback was
				 * created in the call to
				 * Tcl_OpenTcpServer. */
    Tcl_Channel chan,		/* Channel for the newly accepted
				 * connection. */
    char *address,		/* Address of client that was accepted. */
    int port)			/* Port of client that was accepted. */
{
1397
1398
1399
1400
1401
1402
1403
1404

1405
1406
1407
1408
1409
1410
1411
1454
1455
1456
1457
1458
1459
1460

1461
1462
1463
1464
1465
1466
1467
1468







-
+







 *	longer be informed.
 *
 *----------------------------------------------------------------------
 */

static void
TcpServerCloseProc(
    ClientData callbackData)	/* The data passed in the call to
    void *callbackData)	/* The data passed in the call to
				 * Tcl_CreateCloseHandler. */
{
    AcceptCallback *acceptCallbackPtr = (AcceptCallback *)callbackData;
				/* The actual data. */

    if (acceptCallbackPtr->interp != NULL) {
	UnregisterTcpServerInterpCleanupProc(acceptCallbackPtr->interp,
1430
1431
1432
1433
1434
1435
1436
1437

1438
1439
1440
1441
1442
1443
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
1474
1475
1476
1477
1478
1487
1488
1489
1490
1491
1492
1493

1494
1495
1496
1497
1498
1499


1500
1501
1502
1503





1504
1505
1506
1507
1508
1509
1510
1511
1512
1513

1514


1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525

1526
1527
1528
1529
1530
1531
1532
1533







-
+





-
-
+
+


-
-
-
-
-
+
+
+
+
+





-
+
-
-











-
+







 *	Creates a socket based channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_SocketObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static const char *const socketOptions[] = {
	"-async", "-myaddr", "-myport", "-reuseaddr", "-reuseport", "-server",
	NULL
	"-async", "-backlog", "-myaddr", "-myport", "-reuseaddr",
	"-reuseport", "-server", NULL
    };
    enum socketOptionsEnum {
	SKT_ASYNC, SKT_MYADDR, SKT_MYPORT, SKT_REUSEADDR, SKT_REUSEPORT,
	SKT_SERVER
    };
    int optionIndex, a, server = 0, myport = 0, async = 0, reusep = -1,
	reusea = -1;
	SKT_ASYNC, SKT_BACKLOG, SKT_MYADDR, SKT_MYPORT, SKT_REUSEADDR,
	SKT_REUSEPORT, SKT_SERVER
    } optionIndex;
    int a, server = 0, myport = 0, async = 0, reusep = -1,
	reusea = -1, backlog = -1;
    unsigned int flags = 0;
    const char *host, *port, *myaddr = NULL;
    Tcl_Obj *script = NULL;
    Tcl_Channel chan;

    if (TclpHasSockets(interp) != TCL_OK) {
    TclInitSockets();
	return TCL_ERROR;
    }

    for (a = 1; a < objc; a++) {
	const char *arg = TclGetString(objv[a]);

	if (arg[0] != '-') {
	    break;
	}
	if (Tcl_GetIndexFromObj(interp, objv[a], socketOptions, "option",
		TCL_EXACT, &optionIndex) != TCL_OK) {
	    return TCL_ERROR;
	}
	switch ((enum socketOptionsEnum) optionIndex) {
	switch (optionIndex) {
	case SKT_ASYNC:
	    if (server == 1) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"cannot set -async option for server sockets", -1));
		return TCL_ERROR;
	    }
	    async = 1;
1533
1534
1535
1536
1537
1538
1539











1540
1541
1542
1543
1544
1545
1546
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







+
+
+
+
+
+
+
+
+
+
+







		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"no argument given for -reuseport option", -1));
		return TCL_ERROR;
	    }
	    if (Tcl_GetBooleanFromObj(interp, objv[a], &reusep) != TCL_OK) {
		return TCL_ERROR;
	    }
	    break;
	case SKT_BACKLOG:
	    a++;
	    if (a >= objc) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"no argument given for -backlog option", -1));
		return TCL_ERROR;
	    }
	    if (Tcl_GetIntFromObj(interp, objv[a], &backlog) != TCL_OK) {
		return TCL_ERROR;
	    }
	    break;
	default:
	    Tcl_Panic("Tcl_SocketObjCmd: bad option index to SocketOptions");
	}
    }
    if (server) {
	host = myaddr;		/* NULL implies INADDR_ANY */
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
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







-
+


+
-
+
-



-
+

-
-
+
+







	a++;
    } else {
	Interp *iPtr;

    wrongNumArgs:
	iPtr = (Interp *) interp;
	Tcl_WrongNumArgs(interp, 1, objv,
		"?-myaddr addr? ?-myport myport? ?-async? host port");
		"?-async? ?-myaddr addr? ?-myport myport? host port");
	iPtr->flags |= INTERP_ALTERNATE_WRONG_ARGS;
	Tcl_WrongNumArgs(interp, 1, objv,
		"-server command ?-backlog count? ?-myaddr addr? "
		"-server command ?-reuseaddr boolean? ?-reuseport boolean? "
		"?-reuseaddr boolean? ?-reuseport boolean? port");
		"?-myaddr addr? port");
	return TCL_ERROR;
    }

    if (!server && (reusea != -1 || reusep != -1)) {
    if (!server && (reusea != -1 || reusep != -1 || backlog != -1)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"options -reuseaddr and -reuseport are only valid for servers",
		-1));
		"options -backlog, -reuseaddr, and -reuseport are only valid "
		"for servers", -1));
	return TCL_ERROR;
    }

    /*
     * Set the options to their default value if the user didn't override
     * their value.
     */
1610
1611
1612
1613
1614
1615
1616
1617

1618
1619
1620
1621
1622
1623
1624
1676
1677
1678
1679
1680
1681
1682

1683
1684
1685
1686
1687
1688
1689
1690







-
+







    if (server) {
	AcceptCallback *acceptCallbackPtr = (AcceptCallback *)Tcl_Alloc(sizeof(AcceptCallback));

	Tcl_IncrRefCount(script);
	acceptCallbackPtr->script = script;
	acceptCallbackPtr->interp = interp;

	chan = Tcl_OpenTcpServerEx(interp, port, host, flags,
	chan = Tcl_OpenTcpServerEx(interp, port, host, flags, backlog,
		AcceptCallbackProc, acceptCallbackPtr);
	if (chan == NULL) {
	    Tcl_DecrRefCount(script);
	    Tcl_Free(acceptCallbackPtr);
	    return TCL_ERROR;
	}

1672
1673
1674
1675
1676
1677
1678
1679

1680
1681
1682
1683
1684
1685
1686
1738
1739
1740
1741
1742
1743
1744

1745
1746
1747
1748
1749
1750
1751
1752







-
+







 *	handler.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FcopyObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Channel inChan, outChan;
    int mode, i, index;
    Tcl_WideInt toRead;
1723
1724
1725
1726
1727
1728
1729
1730

1731
1732
1733
1734
1735
1736
1737
1789
1790
1791
1792
1793
1794
1795

1796
1797
1798
1799
1800
1801
1802
1803







-
+







    for (i = 3; i < objc; i += 2) {
	if (Tcl_GetIndexFromObj(interp, objv[i], switches, "option", 0,
		&index) != TCL_OK) {
	    return TCL_ERROR;
	}
	switch (index) {
	case FcopySize:
	    if (Tcl_GetWideIntFromObj(interp, objv[i+1], &toRead) != TCL_OK) {
	    if (TclGetWideIntFromObj(interp, objv[i+1], &toRead) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (toRead < 0) {
		/*
		 * Handle all negative sizes like -1, meaning 'copy all'. By
		 * resetting toRead we avoid changes in the core copying
		 * functions (which explicitly check for -1 and crash on any
1767
1768
1769
1770
1771
1772
1773
1774

1775
1776
1777
1778
1779
1780
1781
1782


1783
1784
1785

1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798

1799
1800
1801
1802
1803
1804
1805
1833
1834
1835
1836
1837
1838
1839

1840
1841
1842
1843
1844
1845

1846

1847
1848
1849
1850

1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863

1864
1865
1866
1867
1868
1869
1870
1871







-
+





-

-
+
+


-
+












-
+







 *	"output"), or -1 if the channel wasn't opened for that mode.
 *
 *---------------------------------------------------------------------------
 */

static int
ChanPendingObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Channel chan;
    int index, mode;
    static const char *const options[] = {"input", "output", NULL};
    enum pendingOptionsEnum {PENDING_INPUT, PENDING_OUTPUT};
    enum pendingOptionsEnum {PENDING_INPUT, PENDING_OUTPUT} index;
    int mode;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "mode channelId");
	Tcl_WrongNumArgs(interp, 1, objv, "mode channel");
	return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObj(interp, objv[1], options, "mode", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }

    if (TclGetChannelFromObj(interp, objv[2], &chan, &mode, 0) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum pendingOptionsEnum) index) {
    switch (index) {
    case PENDING_INPUT:
	if (!(mode & TCL_READABLE)) {
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-1));
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tcl_InputBuffered(chan)));
	}
	break;
1829
1830
1831
1832
1833
1834
1835
1836

1837
1838
1839
1840
1841
1842
1843
1844
1845

1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857

1858
1859
1860
1861
1862
1863
1864
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







-
+








-
+











-
+







 *	Truncates a channel (or rather a file underlying a channel).
 *
 *----------------------------------------------------------------------
 */

static int
ChanTruncateObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Channel chan;
    Tcl_WideInt length;

    if ((objc < 2) || (objc > 3)) {
	Tcl_WrongNumArgs(interp, 1, objv, "channelId ?length?");
	Tcl_WrongNumArgs(interp, 1, objv, "channel ?length?");
	return TCL_ERROR;
    }
    if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
	return TCL_ERROR;
    }

    if (objc == 3) {
	/*
	 * User is supplying an explicit length.
	 */

	if (Tcl_GetWideIntFromObj(interp, objv[2], &length) != TCL_OK) {
	if (TclGetWideIntFromObj(interp, objv[2], &length) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (length < 0) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "cannot truncate to negative length of file", -1));
	    return TCL_ERROR;
	}
1902
1903
1904
1905
1906
1907
1908
1909

1910
1911
1912
1913
1914
1915
1916
1968
1969
1970
1971
1972
1973
1974

1975
1976
1977
1978
1979
1980
1981
1982







-
+







 *	anonymous pipe.
 *
 *----------------------------------------------------------------------
 */

static int
ChanPipeObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Channel rchan, wchan;
    const char *channelNames[2];
    Tcl_Obj *resultPtr;
1953
1954
1955
1956
1957
1958
1959
1960

1961
1962
1963
1964
1965
1966
1967
2019
2020
2021
2022
2023
2024
2025

2026
2027
2028
2029
2030
2031
2032
2033







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclChannelNamesCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc < 1 || objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?pattern?");
	return TCL_ERROR;
2003
2004
2005
2006
2007
2008
2009

2010
2011
2012
2013
2014
2015
2016
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083







+







	{"close",	Tcl_CloseObjCmd,	TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
	{"copy",	Tcl_FcopyObjCmd,	NULL, NULL, NULL, 0},
	{"create",	TclChanCreateObjCmd,	TclCompileBasic2ArgCmd, NULL, NULL, 0},		/* TIP #219 */
	{"eof",		Tcl_EofObjCmd,		TclCompileBasic1ArgCmd, NULL, NULL, 0},
	{"event",	Tcl_FileEventObjCmd,	TclCompileBasic2Or3ArgCmd, NULL, NULL, 0},
	{"flush",	Tcl_FlushObjCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 0},
	{"gets",	Tcl_GetsObjCmd,		TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
	{"isbinary",	ChanIsBinaryCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 0},
	{"names",	TclChannelNamesCmd,	TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
	{"pending",	ChanPendingObjCmd,	TclCompileBasic2ArgCmd, NULL, NULL, 0},		/* TIP #287 */
	{"pipe",	ChanPipeObjCmd,		TclCompileBasic0ArgCmd, NULL, NULL, 0},		/* TIP #304 */
	{"pop",		TclChanPopObjCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 0},		/* TIP #230 */
	{"postevent",	TclChanPostEventObjCmd,	TclCompileBasic2ArgCmd, NULL, NULL, 0},	/* TIP #219 */
	{"push",	TclChanPushObjCmd,	TclCompileBasic2ArgCmd, NULL, NULL, 0},		/* TIP #230 */
	{"puts",	Tcl_PutsObjCmd,		NULL, NULL, NULL, 0},
2031
2032
2033
2034
2035
2036
2037
2038

2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2098
2099
2100
2101
2102
2103
2104

2105

2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117







-
+
-












    ensemble = TclMakeEnsemble(interp, "chan", initMap);
    Tcl_GetEnsembleMappingDict(NULL, ensemble, &mapObj);
    for (i=0 ; extras[i] ; i+=2) {
	/*
	 * Can assume that reference counts are all incremented.
	 */

	Tcl_DictObjPut(NULL, mapObj, Tcl_NewStringObj(extras[i], -1),
	TclDictPutString(NULL, mapObj, extras[i], extras[i + 1]);
		Tcl_NewStringObj(extras[i+1], -1));
    }
    Tcl_SetEnsembleMappingDict(interp, ensemble, mapObj);
    return ensemble;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclIOGT.c.

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
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
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

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






-
-
+
+













-
+

-
+

-
+

-
+

-
+


-
+


-
-
-
-
-
-
+
+
+
+
+
+






-
+







/*
 * tclIOGT.c --
 *
 *	Implements a generic transformation exposing the underlying API at the
 *	script level. Contributed by Andreas Kupries.
 *
 * Copyright (c) 2000 Ajuba Solutions
 * Copyright (c) 1999-2000 Andreas Kupries (a.kupries@westend.com)
 * Copyright © 2000 Ajuba Solutions
 * Copyright © 1999-2000 Andreas Kupries (a.kupries@westend.com)
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclIO.h"

/*
 * Forward declarations of internal procedures. First the driver procedures of
 * the transformation.
 */

static int		TransformBlockModeProc(ClientData instanceData,
static int		TransformBlockModeProc(void *instanceData,
			    int mode);
static int		TransformCloseProc(ClientData instanceData,
static int		TransformCloseProc(void *instanceData,
			    Tcl_Interp *interp, int flags);
static int		TransformInputProc(ClientData instanceData, char *buf,
static int		TransformInputProc(void *instanceData, char *buf,
			    int toRead, int *errorCodePtr);
static int		TransformOutputProc(ClientData instanceData,
static int		TransformOutputProc(void *instanceData,
			    const char *buf, int toWrite, int *errorCodePtr);
static int		TransformSetOptionProc(ClientData instanceData,
static int		TransformSetOptionProc(void *instanceData,
			    Tcl_Interp *interp, const char *optionName,
			    const char *value);
static int		TransformGetOptionProc(ClientData instanceData,
static int		TransformGetOptionProc(void *instanceData,
			    Tcl_Interp *interp, const char *optionName,
			    Tcl_DString *dsPtr);
static void		TransformWatchProc(ClientData instanceData, int mask);
static int		TransformGetFileHandleProc(ClientData instanceData,
			    int direction, ClientData *handlePtr);
static int		TransformNotifyProc(ClientData instanceData, int mask);
static Tcl_WideInt	TransformWideSeekProc(ClientData instanceData,
			    Tcl_WideInt offset, int mode, int *errorCodePtr);
static void		TransformWatchProc(void *instanceData, int mask);
static int		TransformGetFileHandleProc(void *instanceData,
			    int direction, void **handlePtr);
static int		TransformNotifyProc(void *instanceData, int mask);
static long long	TransformWideSeekProc(void *instanceData,
			    long long offset, int mode, int *errorCodePtr);

/*
 * Forward declarations of internal procedures. Secondly the procedures for
 * handling and generating fileeevents.
 */

static void		TransformChannelHandlerTimer(ClientData clientData);
static void		TransformChannelHandlerTimer(void *clientData);

/*
 * Forward declarations of internal procedures. Third, helper procedures
 * encapsulating essential tasks.
 */

typedef struct TransformChannelData TransformChannelData;
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
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







-
+










-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+







 */

typedef struct ResultBuffer ResultBuffer;

static inline void	ResultClear(ResultBuffer *r);
static inline void	ResultInit(ResultBuffer *r);
static inline int	ResultEmpty(ResultBuffer *r);
static inline int	ResultCopy(ResultBuffer *r, unsigned char *buf,
static inline size_t	ResultCopy(ResultBuffer *r, unsigned char *buf,
			    size_t toRead);
static inline void	ResultAdd(ResultBuffer *r, unsigned char *buf,
			    size_t toWrite);

/*
 * This structure describes the channel type structure for Tcl-based
 * transformations.
 */

static const Tcl_ChannelType transformChannelType = {
    "transform",		/* Type name. */
    TCL_CHANNEL_VERSION_5,	/* v5 channel */
    NULL,		/* Close proc. */
    TransformInputProc,		/* Input proc. */
    TransformOutputProc,	/* Output proc. */
    NULL,			/* Seek proc. */
    TransformSetOptionProc,	/* Set option proc. */
    TransformGetOptionProc,	/* Get option proc. */
    TransformWatchProc,		/* Initialize notifier. */
    TransformGetFileHandleProc,	/* Get OS handles out of channel. */
    TransformCloseProc,		/* close2proc */
    TransformBlockModeProc,	/* Set blocking/nonblocking mode.*/
    "transform",
    TCL_CHANNEL_VERSION_5,
    NULL,			/* Deprecated. */
    TransformInputProc,
    TransformOutputProc,
    NULL,			/* Deprecated. */
    TransformSetOptionProc,
    TransformGetOptionProc,
    TransformWatchProc,
    TransformGetFileHandleProc,
    TransformCloseProc,
    TransformBlockModeProc,
    NULL,			/* Flush proc. */
    TransformNotifyProc,	/* Handling of events bubbling up. */
    TransformWideSeekProc,	/* Wide seek proc. */
    NULL,			/* Thread action. */
    NULL			/* Truncate. */
    TransformNotifyProc,
    TransformWideSeekProc,
    NULL,			/* Thread action proc. */
    NULL			/* Truncate proc. */
};

/*
 * Possible values for 'flags' field in control structure, see below.
 */

#define CHANNEL_ASYNC (1<<0)	/* Non-blocking mode. */
254
255
256
257
258
259
260
261

262
263
264
265
266
267
268
269

270
271
272
273
274
275
276
254
255
256
257
258
259
260

261
262
263
264
265
266
267
268

269
270
271
272
273
274
275
276







-
+







-
+







    Tcl_Interp *interp,		/* Interpreter for result. */
    Tcl_Channel chan,		/* Channel to transform. */
    Tcl_Obj *cmdObjPtr)		/* Script to use for transform. */
{
    Channel *chanPtr;		/* The actual channel. */
    ChannelState *statePtr;	/* State info for channel. */
    int mode;			/* Read/write mode of the channel. */
    int objc;
    Tcl_Size objc;
    TransformChannelData *dataPtr;
    Tcl_DString ds;

    if (chan == NULL) {
	return TCL_ERROR;
    }

    if (TCL_OK != Tcl_ListObjLength(interp, cmdObjPtr, &objc)) {
    if (TCL_OK != TclListObjLength(interp, cmdObjPtr, &objc)) {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("-command value is not a list", -1));
	return TCL_ERROR;
    }

    chanPtr = (Channel *) chan;
    statePtr = chanPtr->state;
371
372
373
374
375
376
377
378

379
380
381
382
383
384
385
371
372
373
374
375
376
377

378
379
380
381
382
383
384
385







-
+







				 * callback is sent to the underlying channel
				 * or not. */
    int preserve)		/* Flag. If true the procedure will preserve
				 * the result state of all accessed
				 * interpreters. */
{
    Tcl_Obj *resObj;		/* See below, switch (transmit). */
    size_t resLen = 0;
    Tcl_Size resLen = 0;
    unsigned char *resBuf;
    Tcl_InterpState state = NULL;
    int res = TCL_OK;
    Tcl_Obj *command = TclListObjCopy(NULL, dataPtr->command);
    Tcl_Interp *eval = dataPtr->interp;

    Tcl_Preserve(eval);
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
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







-
+
+
+
+
+
+



-
+







-
+







     */

    if (preserve == P_PRESERVE) {
	state = Tcl_SaveInterpState(eval, res);
    }

    Tcl_IncrRefCount(command);
    Tcl_ListObjAppendElement(NULL, command, Tcl_NewStringObj((char *) op, -1));
    res = Tcl_ListObjAppendElement(NULL, command, Tcl_NewStringObj((char *) op, -1));
    if (res != TCL_OK) {
	Tcl_DecrRefCount(command);
	Tcl_Release(eval);
	return res;
    }

    /*
     * Use a byte-array to prevent the misinterpretation of binary data coming
     * through as UTF while at the tcl level.
     * through as Utf while at the tcl level.
     */

    Tcl_ListObjAppendElement(NULL, command, Tcl_NewByteArrayObj(buf, bufLen));

    /*
     * Step 2, execute the command at the global level of the interpreter used
     * to create the transformation. Destroy the command afterward. If an
     * error occured and the current interpreter is defined and not equal to
     * error occurred and the current interpreter is defined and not equal to
     * the interpreter for the callback, then copy the error message into
     * current interpreter. Don't copy if in preservation mode.
     */

    res = Tcl_EvalObjEx(eval, command, TCL_EVAL_GLOBAL);
    Tcl_DecrRefCount(command);
    command = NULL;
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
467
468
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
467
468
469



470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486







-
-
-
-
+
+
+
+
+
+
+






-
-
-
+
+
+
+
+
+



-
-
-
+
+
+
+
+
+
+
+
+
+







	break;

    case TRANSMIT_DOWN:
	if (dataPtr->self == NULL) {
	    break;
	}
	resObj = Tcl_GetObjResult(eval);
	resBuf = TclGetByteArrayFromObj(resObj, &resLen);
	Tcl_WriteRaw(Tcl_GetStackedChannel(dataPtr->self), (char *) resBuf,
		resLen);
	break;
	resBuf = Tcl_GetBytesFromObj(NULL, resObj, &resLen);
	if (resBuf) {
	    Tcl_WriteRaw(Tcl_GetStackedChannel(dataPtr->self),
		    (char *) resBuf, resLen);
	    break;
	}
	goto nonBytes;

    case TRANSMIT_SELF:
	if (dataPtr->self == NULL) {
	    break;
	}
	resObj = Tcl_GetObjResult(eval);
	resBuf = TclGetByteArrayFromObj(resObj, &resLen);
	Tcl_WriteRaw(dataPtr->self, (char *) resBuf, resLen);
	break;
	resBuf = Tcl_GetBytesFromObj(NULL, resObj, &resLen);
	if (resBuf) {
	    Tcl_WriteRaw(dataPtr->self, (char *) resBuf, resLen);
	    break;
	}
	goto nonBytes;

    case TRANSMIT_IBUF:
	resObj = Tcl_GetObjResult(eval);
	resBuf = TclGetByteArrayFromObj(resObj, &resLen);
	ResultAdd(&dataPtr->result, resBuf, resLen);
	break;
	resBuf = Tcl_GetBytesFromObj(NULL, resObj, &resLen);
	if (resBuf) {
	    ResultAdd(&dataPtr->result, resBuf, resLen);
	    break;
	}
	nonBytes:
	Tcl_AppendResult(interp, "chan transform callback received non-bytes",
		(char *)NULL);
	Tcl_Release(eval);
	return TCL_ERROR;

    case TRANSMIT_NUM:
	/*
	 * Interpret result as integer number.
	 */

	resObj = Tcl_GetObjResult(eval);
493
494
495
496
497
498
499
500

501
502
503
504
505
506
507
511
512
513
514
515
516
517

518
519
520
521
522
523
524
525







-
+







 *	0 if successful, errno when failed.
 *
 *----------------------------------------------------------------------
 */

static int
TransformBlockModeProc(
    ClientData instanceData,	/* State of transformation. */
    void *instanceData,	/* State of transformation. */
    int mode)			/* New blocking mode. */
{
    TransformChannelData *dataPtr = (TransformChannelData *)instanceData;

    if (mode == TCL_MODE_NONBLOCKING) {
	dataPtr->flags |= CHANNEL_ASYNC;
    } else {
525
526
527
528
529
530
531
532

533
534
535
536
537
538
539
543
544
545
546
547
548
549

550
551
552
553
554
555
556
557







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TransformCloseProc(
    ClientData instanceData,
    void *instanceData,
    Tcl_Interp *interp,
	int flags)
{
    TransformChannelData *dataPtr = (TransformChannelData *)instanceData;

    if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
	return EINVAL;
556
557
558
559
560
561
562
563

564
565
566
567
568
569
570
574
575
576
577
578
579
580

581
582
583
584
585
586
587
588







-
+







	dataPtr->timer = NULL;
    }

    /*
     * Now flush data waiting in internal buffers to output and input. The
     * input must be done despite the fact that there is no real receiver for
     * it anymore. But the scripts might have sideeffects other parts of the
     * system rely on (f.e. signaling the close to interested parties).
     * system rely on (f.e. signalling the close to interested parties).
     */

    PreserveData(dataPtr);
    if (dataPtr->mode & TCL_WRITABLE) {
	ExecuteCallback(dataPtr, interp, A_FLUSH_WRITE, NULL, 0,
		TRANSMIT_DOWN, P_PRESERVE);
    }
609
610
611
612
613
614
615
616

617
618
619
620
621
622
623
627
628
629
630
631
632
633

634
635
636
637
638
639
640
641







-
+







 *	A transformed buffer.
 *
 *----------------------------------------------------------------------
 */

static int
TransformInputProc(
    ClientData instanceData,
    void *instanceData,
    char *buf,
    int toRead,
    int *errorCodePtr)
{
    TransformChannelData *dataPtr = (TransformChannelData *)instanceData;
    int gotBytes, read, copied;
    Tcl_Channel downChan;
776
777
778
779
780
781
782
783

784
785
786
787
788
789
790
794
795
796
797
798
799
800

801
802
803
804
805
806
807
808







-
+







 *	A transformed buffer.
 *
 *----------------------------------------------------------------------
 */

static int
TransformOutputProc(
    ClientData instanceData,
    void *instanceData,
    const char *buf,
    int toWrite,
    int *errorCodePtr)
{
    TransformChannelData *dataPtr = (TransformChannelData *)instanceData;

    /*
826
827
828
829
830
831
832
833

834
835
836


837
838
839
840
841
842

843
844
845

846
847
848
849
850
851
852
844
845
846
847
848
849
850

851
852


853
854
855
856
857
858
859

860
861
862

863
864
865
866
867
868
869
870







-
+

-
-
+
+





-
+


-
+







 * Result:
 *	-1 if failed, the new position if successful. An output argument
 *	contains the POSIX error code if an error occurred, or zero.
 *
 *----------------------------------------------------------------------
 */

static Tcl_WideInt
static long long
TransformWideSeekProc(
    ClientData instanceData,	/* The channel to manipulate. */
    Tcl_WideInt offset,		/* Size of movement. */
    void *instanceData,		/* The channel to manipulate. */
    long long offset,		/* Size of movement. */
    int mode,			/* How to move. */
    int *errorCodePtr)		/* Location of error flag. */
{
    TransformChannelData *dataPtr = (TransformChannelData *)instanceData;
    Tcl_Channel parent = Tcl_GetStackedChannel(dataPtr->self);
    const Tcl_ChannelType *parentType	= Tcl_GetChannelType(parent);
    const Tcl_ChannelType *parentType = Tcl_GetChannelType(parent);
    Tcl_DriverWideSeekProc *parentWideSeekProc =
	    Tcl_ChannelWideSeekProc(parentType);
    ClientData parentData = Tcl_GetChannelInstanceData(parent);
    void *parentData = Tcl_GetChannelInstanceData(parent);

    if ((offset == 0) && (mode == SEEK_CUR)) {
	/*
	 * This is no seek but a request to tell the caller the current
	 * location. Simply pass the request down.
	 */

883
884
885
886
887
888
889
890

891
892
893
894
895
896
897
901
902
903
904
905
906
907

908
909
910
911
912
913
914
915







-
+







     * If we have a wide seek capability, we should stick with that.
     */

    if (parentWideSeekProc == NULL) {
	*errorCodePtr = EINVAL;
	return -1;
    }
	return parentWideSeekProc(parentData, offset, mode, errorCodePtr);
    return parentWideSeekProc(parentData, offset, mode, errorCodePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TransformSetOptionProc --
 *
906
907
908
909
910
911
912
913

914
915
916
917
918
919
920
924
925
926
927
928
929
930

931
932
933
934
935
936
937
938







-
+







 *	A standard TCL error code.
 *
 *----------------------------------------------------------------------
 */

static int
TransformSetOptionProc(
    ClientData instanceData,
    void *instanceData,
    Tcl_Interp *interp,
    const char *optionName,
    const char *value)
{
    TransformChannelData *dataPtr = (TransformChannelData *)instanceData;
    Tcl_Channel downChan = Tcl_GetStackedChannel(dataPtr->self);
    Tcl_DriverSetOptionProc *setOptionProc;
944
945
946
947
948
949
950
951

952
953
954
955
956
957
958
962
963
964
965
966
967
968

969
970
971
972
973
974
975
976







-
+







 *	A standard TCL error code.
 *
 *----------------------------------------------------------------------
 */

static int
TransformGetOptionProc(
    ClientData instanceData,
    void *instanceData,
    Tcl_Interp *interp,
    const char *optionName,
    Tcl_DString *dsPtr)
{
    TransformChannelData *dataPtr = (TransformChannelData *)instanceData;
    Tcl_Channel downChan = Tcl_GetStackedChannel(dataPtr->self);
    Tcl_DriverGetOptionProc *getOptionProc;
991
992
993
994
995
996
997
998

999
1000
1001
1002
1003
1004
1005

1006
1007
1008
1009
1010
1011
1012
1009
1010
1011
1012
1013
1014
1015

1016
1017
1018
1019
1020
1021
1022

1023
1024
1025
1026
1027
1028
1029
1030







-
+






-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TransformWatchProc(
    ClientData instanceData,	/* Channel to watch. */
    void *instanceData,	/* Channel to watch. */
    int mask)			/* Events of interest. */
{
    TransformChannelData *dataPtr = (TransformChannelData *)instanceData;
    Tcl_Channel downChan;

    /*
     * The caller expressed interest in events occuring for this channel. We
     * The caller expressed interest in events occurring for this channel. We
     * are forwarding the call to the underlying channel now.
     */

    dataPtr->watchMask = mask;

    /*
     * No channel handlers any more. We will be notified automatically about
1069
1070
1071
1072
1073
1074
1075
1076

1077
1078

1079
1080
1081
1082
1083
1084
1085
1087
1088
1089
1090
1091
1092
1093

1094
1095

1096
1097
1098
1099
1100
1101
1102
1103







-
+

-
+







 *	The appropriate Tcl_File or NULL if not present.
 *
 *----------------------------------------------------------------------
 */

static int
TransformGetFileHandleProc(
    ClientData instanceData,	/* Channel to query. */
    void *instanceData,	/* Channel to query. */
    int direction,		/* Direction of interest. */
    ClientData *handlePtr)	/* Place to store the handle into. */
    void **handlePtr)	/* Place to store the handle into. */
{
    TransformChannelData *dataPtr = (TransformChannelData *)instanceData;

    /*
     * Return the handle belonging to parent channel. IOW, pass the request
     * down and the result up.
     */
1103
1104
1105
1106
1107
1108
1109
1110

1111
1112

1113
1114
1115
1116
1117

1118
1119
1120
1121
1122
1123
1124
1121
1122
1123
1124
1125
1126
1127

1128
1129

1130
1131
1132
1133
1134

1135
1136
1137
1138
1139
1140
1141
1142







-
+

-
+




-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TransformNotifyProc(
    ClientData clientData,	/* The state of the notified
    void *clientData,	/* The state of the notified
				 * transformation. */
    int mask)			/* The mask of occuring events. */
    int mask)			/* The mask of occurring events. */
{
    TransformChannelData *dataPtr = (TransformChannelData *)clientData;

    /*
     * An event occured in the underlying channel. This transformation doesn't
     * An event occurred in the underlying channel. This transformation doesn't
     * process such events thus returns the incoming mask unchanged.
     */

    if (dataPtr->timer != NULL) {
	/*
	 * Delete an existing timer. It was not fired, yet we are here, so the
	 * channel below generated such an event and we don't have to. The
1148
1149
1150
1151
1152
1153
1154
1155

1156
1157
1158
1159
1160
1161
1162
1166
1167
1168
1169
1170
1171
1172

1173
1174
1175
1176
1177
1178
1179
1180







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TransformChannelHandlerTimer(
    ClientData clientData)	/* Transformation to query. */
    void *clientData)	/* Transformation to query. */
{
    TransformChannelData *dataPtr = (TransformChannelData *)clientData;

    dataPtr->timer = NULL;
    if (!(dataPtr->watchMask&TCL_READABLE) || ResultEmpty(&dataPtr->result)) {
	/*
	 * The timer fired, but either is there no (more) interest in the
1200
1201
1202
1203
1204
1205
1206
1207

1208
1209
1210
1211
1212
1213
1214
1218
1219
1220
1221
1222
1223
1224

1225
1226
1227
1228
1229
1230
1231
1232







-
+








/*
 *----------------------------------------------------------------------
 *
 * ResultInit --
 *
 *	Initializes the specified buffer structure. The structure will contain
 *	valid information for an emtpy buffer.
 *	valid information for an empty buffer.
 *
 * Side effects:
 *	See above.
 *
 * Result:
 *	None.
 *
1262
1263
1264
1265
1266
1267
1268
1269

1270
1271
1272
1273
1274
1275

1276
1277
1278
1279
1280
1281
1282
1280
1281
1282
1283
1284
1285
1286

1287
1288
1289
1290
1291
1292

1293
1294
1295
1296
1297
1298
1299
1300







-
+





-
+







 *
 * Result:
 *	The number of actually copied bytes, possibly less than 'toRead'.
 *
 *----------------------------------------------------------------------
 */

static inline int
static inline size_t
ResultCopy(
    ResultBuffer *r,		/* The buffer to read from. */
    unsigned char *buf,		/* The buffer to copy into. */
    size_t toRead)		/* Number of requested bytes. */
{
    if (r->used == 0) {
    if (ResultEmpty(r)) {
	/*
	 * Nothing to copy in the case of an empty buffer.
	 */

	return 0;
    } else if (r->used == toRead) {
	/*
1325
1326
1327
1328
1329
1330
1331
1332

1333
1334
1335
1336
1337
1338
1339
1343
1344
1345
1346
1347
1348
1349

1350
1351
1352
1353
1354
1355
1356
1357







-
+








static inline void
ResultAdd(
    ResultBuffer *r,		/* The buffer to extend. */
    unsigned char *buf,		/* The buffer to read from. */
    size_t toWrite)		/* The number of bytes in 'buf'. */
{
    if (r->used + toWrite > r->allocated) {
    if ((r->used + toWrite + 1) > r->allocated) {
	/*
	 * Extension of the internal buffer is required.
	 */

	if (r->allocated == 0) {
	    r->allocated = toWrite + INCREMENT;
	    r->buf = (unsigned char *)Tcl_Alloc(r->allocated);

Changes to generic/tclIORChan.c.

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
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
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
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












-
+




















-
+

-
+

-
+

-
-
+
+

-
+

-
+

-
-
-
+
+
+


-
+


-
-
+
+


-
+
-


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
+

-
+













-
+
-


-
+












-
-
-
-
-
-
-
-
-
-
-







-
+

+
+
-
-
+
+
+
-




-
+







/*
 * tclIORChan.c --
 *
 *	This file contains the implementation of Tcl's generic channel
 *	reflection code, which allows the implementation of Tcl channels in
 *	Tcl code.
 *
 *	Parts of this file are based on code contributed by Jean-Claude
 *	Wippler.
 *
 *	See TIP #219 for the specification of this functionality.
 *
 * Copyright (c) 2004-2005 ActiveState, a divison of Sophos
 * Copyright © 2004-2005 ActiveState, a division of Sophos
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclIO.h"
#include <assert.h>

#ifndef EINVAL
#define EINVAL	9
#endif
#ifndef EOK
#define EOK	0
#endif

/*
 * Signatures of all functions used in the C layer of the reflection.
 */

static int		ReflectClose(ClientData clientData,
static int		ReflectClose(void *clientData,
			    Tcl_Interp *interp, int flags);
static int		ReflectInput(ClientData clientData, char *buf,
static int		ReflectInput(void *clientData, char *buf,
			    int toRead, int *errorCodePtr);
static int		ReflectOutput(ClientData clientData, const char *buf,
static int		ReflectOutput(void *clientData, const char *buf,
			    int toWrite, int *errorCodePtr);
static void		ReflectWatch(ClientData clientData, int mask);
static int		ReflectBlock(ClientData clientData, int mode);
static void		ReflectWatch(void *clientData, int mask);
static int		ReflectBlock(void *clientData, int mode);
#if TCL_THREADS
static void		ReflectThread(ClientData clientData, int action);
static void		ReflectThread(void *clientData, int action);
static int		ReflectEventRun(Tcl_Event *ev, int flags);
static int		ReflectEventDelete(Tcl_Event *ev, ClientData cd);
static int		ReflectEventDelete(Tcl_Event *ev, void *cd);
#endif
static Tcl_WideInt	ReflectSeekWide(ClientData clientData,
			    Tcl_WideInt offset, int mode, int *errorCodePtr);
static int		ReflectGetOption(ClientData clientData,
static long long	 ReflectSeekWide(void *clientData,
			    long long offset, int mode, int *errorCodePtr);
static int		ReflectGetOption(void *clientData,
			    Tcl_Interp *interp, const char *optionName,
			    Tcl_DString *dsPtr);
static int		ReflectSetOption(ClientData clientData,
static int		ReflectSetOption(void *clientData,
			    Tcl_Interp *interp, const char *optionName,
			    const char *newValue);
static void     TimerRunRead(ClientData clientData);
static void     TimerRunWrite(ClientData clientData);
static int		ReflectTruncate(void *clientData,
			    long long length);

/*
 * The C layer channel type/driver definition used by the reflection. This is
 * The C layer channel type/driver definition used by the reflection.
 * a version 3 structure.
 */

static const Tcl_ChannelType tclRChannelType = {
    "tclrchannel",	   /* Type name.				  */
    TCL_CHANNEL_VERSION_5, /* v5 channel */
    NULL,	   /* Close channel, clean instance data	  */
    ReflectInput,	   /* Handle read request			  */
    ReflectOutput,	   /* Handle write request			  */
    NULL,
    ReflectSetOption,	   /* Set options.			NULL'able */
    ReflectGetOption,	   /* Get options.			NULL'able */
    ReflectWatch,	   /* Initialize notifier			  */
    NULL,		   /* Get OS handle from the channel.	NULL'able */
	ReflectClose,	   /* No close2 support.		NULL'able */
    ReflectBlock,	   /* Set blocking/nonblocking.		NULL'able */
    NULL,		   /* Flush channel. Not used by core.	NULL'able */
    NULL,		   /* Handle events.			NULL'able */
    ReflectSeekWide,	   /* Move access point (64 bit).	NULL'able */
static const Tcl_ChannelType reflectedChannelType = {
    "tclrchannel",
    TCL_CHANNEL_VERSION_5,
    NULL,			/* Deprecated */
    ReflectInput,
    ReflectOutput,
    NULL,			/* Deprecated */
    ReflectSetOption,
    ReflectGetOption,
    ReflectWatch,
    NULL,			/* Get OS handle from the channel. */
    ReflectClose,
    ReflectBlock,
    NULL,			/* Flush channel. */
    NULL,			/* Handle bubbled events. */
    ReflectSeekWide,
#if TCL_THREADS
    ReflectThread,         /* thread action, tracking owner */
    ReflectThread,
#else
	NULL,		   /* thread action */
    NULL,			/* Thread action proc */
#endif
    NULL		   /* truncate */
    ReflectTruncate		/* Truncate proc. */
};

/*
 * Instance data for a reflected channel. ===========================
 */

typedef struct {
    Tcl_Channel chan;		/* Back reference to generic channel
				 * structure. */
    Tcl_Interp *interp;		/* Reference to the interpreter containing the
				 * Tcl level part of the channel. NULL here
				 * signals the channel is dead because the
				 * interpreter/thread containing its Tcl
				 * command is gone.
				 * command is gone. */
				 */
#if TCL_THREADS
    Tcl_ThreadId thread;	/* Thread the 'interp' belongs to. == Handler thread */
    Tcl_ThreadId owner;         /* Thread owning the structure.    == Channel thread */
    Tcl_ThreadId owner;		/* Thread owning the structure.    == Channel thread */
#endif
    Tcl_Obj *cmd;		/* Callback command prefix */
    Tcl_Obj *methods;		/* Methods to append to command prefix */
    Tcl_Obj *name;		/* Name of the channel as created */

    int mode;			/* Mask of R/W mode */
    int interest;		/* Mask of events the channel is interested
				 * in. */

    int dead;			/* Boolean signal that some operations
				 * should no longer be attempted. */

    Tcl_TimerToken readTimer;   /*
				   A token for the timer that is scheduled in
				   order to call Tcl_NotifyChannel when the
				   channel is readable
			        */
    Tcl_TimerToken writeTimer;  /*
				   A token for the timer that is scheduled in
				   order to call Tcl_NotifyChannel when the
				   channel is writable
			        */

    /*
     * Note regarding the usage of timers.
     *
     * Most channel implementations need a timer in the C level to ensure that
     * data in buffers is flushed out through the generation of fake file
     * events.
     *
     * See 'rechan', 'memchan', etc.
     * See 'refchan', 'memchan', etc.
     *
     * Here this is _not_ required. Interest in events is posted to the Tcl
     * level via 'watch'. And posting of events is possible from the Tcl level
     * A timer is used here as well in order to ensure at least on pass through
     * the event loop when a channel becomes ready. See issues 67a5eabbd3d1 and
     * as well, via 'chan postevent'. This means that the generation of all
     * events, fake or not, timer based or not, is completely in the hands of
     * the Tcl level. Therefore no timer here.
     * ef28eb1f1516.
     */
} ReflectedChannel;

/*
 * Structure of the table maping from channel handles to reflected
 * Structure of the table mapping from channel handles to reflected
 * channels. Each interpreter which has the handler command for one or more
 * reflected channels records them in such a table, so that 'chan postevent'
 * is able to find them even if the actual channel was moved to a different
 * interpreter and/or thread.
 *
 * The table is reachable via the standard interpreter AssocData, the key is
 * defined below.
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
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







+













+









-
+
+






-
+







    "cget",		/* OPT \/ Together or none */
    "cgetall",		/* OPT /\ of these two     */
    "configure",	/* OPT */
    "finalize",		/*     */
    "initialize",	/*     */
    "read",		/* OPT */
    "seek",		/* OPT */
    "truncate",		/* OPT */
    "watch",		/*     */
    "write",		/* OPT */
    NULL
};
typedef enum {
    METH_BLOCKING,
    METH_CGET,
    METH_CGETALL,
    METH_CONFIGURE,
    METH_FINAL,
    METH_INIT,
    METH_READ,
    METH_SEEK,
    METH_TRUNCATE,
    METH_WATCH,
    METH_WRITE
} MethodName;

#define FLAG(m) (1 << (m))
#define REQUIRED_METHODS \
	(FLAG(METH_INIT) | FLAG(METH_FINAL) | FLAG(METH_WATCH))
#define NULLABLE_METHODS \
	(FLAG(METH_BLOCKING) | FLAG(METH_SEEK) | \
	FLAG(METH_CONFIGURE) | FLAG(METH_CGET) | FLAG(METH_CGETALL))
	FLAG(METH_CONFIGURE) | FLAG(METH_CGET) | \
	FLAG(METH_CGETALL)   | FLAG(METH_TRUNCATE))

#define RANDW \
	(TCL_READABLE | TCL_WRITABLE)

#define IMPLIES(a,b)	((!(a)) || (b))
#define NEGIMPL(a,b)
#define HAS(x,f)	(x & FLAG(f))
#define HAS(x,f)	((x) & FLAG(f))

#if TCL_THREADS
/*
 * Thread specific types and structures.
 *
 * We are here essentially creating a very specific implementation of 'thread
 * send'.
227
228
229
230
231
232
233
234


235
236
237
238
239
240
241
219
220
221
222
223
224
225

226
227
228
229
230
231
232
233
234







-
+
+







    ForwardedInput,
    ForwardedOutput,
    ForwardedSeek,
    ForwardedWatch,
    ForwardedBlock,
    ForwardedSetOpt,
    ForwardedGetOpt,
    ForwardedGetOptAll
    ForwardedGetOptAll,
    ForwardedTruncate
} ForwardedOperation;

/*
 * Event used to forward driver invocations to the thread actually managing
 * the channel. We cannot construct the command to execute and forward that.
 * Because then it will contain a mixture of Tcl_Obj's belonging to both the
 * command handler thread (CT), and the thread managing the channel (MT),
257
258
259
260
261
262
263
264

265
266
267
268
269
270

271
272
273
274
275
276
277
250
251
252
253
254
255
256

257
258
259
260
261
262

263
264
265
266
267
268
269
270







-
+





-
+







 * ForwardParamBase. Where an operation does not need any special types, it
 * has no "subtype" and just uses ForwardParamBase, as listed above.)
 */

struct ForwardParamInput {
    ForwardParamBase base;	/* "Supertype". MUST COME FIRST. */
    char *buf;			/* O: Where to store the read bytes */
    size_t toRead;			/* I: #bytes to read,
    Tcl_Size toRead;		/* I: #bytes to read,
				 * O: #bytes actually read */
};
struct ForwardParamOutput {
    ForwardParamBase base;	/* "Supertype". MUST COME FIRST. */
    const char *buf;		/* I: Where the bytes to write come from */
    int toWrite;		/* I: #bytes to write,
    Tcl_Size toWrite;		/* I: #bytes to write,
				 * O: #bytes actually written */
};
struct ForwardParamSeek {
    ForwardParamBase base;	/* "Supertype". MUST COME FIRST. */
    int seekMode;		/* I: How to seek */
    Tcl_WideInt offset;		/* I: Where to seek,
				 * O: New location */
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
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







+
+
+
+














+







    const char *value;		/* Value to set */
};
struct ForwardParamGetOpt {
    ForwardParamBase base;	/* "Supertype". MUST COME FIRST. */
    const char *name;		/* Name of option to get, maybe NULL */
    Tcl_DString *value;		/* Result */
};
struct ForwardParamTruncate {
    ForwardParamBase base;	/* "Supertype". MUST COME FIRST. */
    Tcl_WideInt length;		/* I: Length of file. */
};

/*
 * Now join all these together in a single union for convenience.
 */

typedef union ForwardParam {
    ForwardParamBase base;
    struct ForwardParamInput input;
    struct ForwardParamOutput output;
    struct ForwardParamSeek seek;
    struct ForwardParamWatch watch;
    struct ForwardParamBlock block;
    struct ForwardParamSetOpt setOpt;
    struct ForwardParamGetOpt getOpt;
    struct ForwardParamTruncate truncate;
} ForwardParam;

/*
 * Forward declaration.
 */

typedef struct ForwardingResult ForwardingResult;
386
387
388
389
390
391
392
393

394
395
396
397
398
399
400
384
385
386
387
388
389
390

391
392
393
394
395
396
397
398







-
+







 * involved in the forwarding exits. It also clean things up so that we don't
 * leak resources when threads go away.
 */

static void		ForwardOpToHandlerThread(ReflectedChannel *rcPtr,
			    ForwardedOperation op, const void *param);
static int		ForwardProc(Tcl_Event *evPtr, int mask);
static void		SrcExitProc(ClientData clientData);
static void		SrcExitProc(void *clientData);

#define FreeReceivedError(p) \
	if ((p)->base.mustFree) {                               \
	    Tcl_Free((p)->base.msgStr);                           \
	}
#define PassReceivedErrorInterp(i,p) \
	if ((i) != NULL) {                                      \
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
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







-
+

















+








static int		EncodeEventMask(Tcl_Interp *interp,
			    const char *objName, Tcl_Obj *obj, int *mask);
static Tcl_Obj *	DecodeEventMask(int mask);
static ReflectedChannel * NewReflectedChannel(Tcl_Interp *interp,
			    Tcl_Obj *cmdpfxObj, int mode, Tcl_Obj *handleObj);
static Tcl_Obj *	NextHandle(void);
static void		FreeReflectedChannel(ReflectedChannel *rcPtr);
static Tcl_FreeProc	FreeReflectedChannel;
static int		InvokeTclMethod(ReflectedChannel *rcPtr,
			    MethodName method, Tcl_Obj *argOneObj,
			    Tcl_Obj *argTwoObj, Tcl_Obj **resultObjPtr);

static ReflectedChannelMap *	GetReflectedChannelMap(Tcl_Interp *interp);
static Tcl_InterpDeleteProc	DeleteReflectedChannelMap;
static int		ErrnoReturn(ReflectedChannel *rcPtr, Tcl_Obj *resObj);
static void		MarkDead(ReflectedChannel *rcPtr);

/*
 * Global constant strings (messages). ==================
 * These string are used directly as bypass errors, thus they have to be valid
 * Tcl lists where the last element is the message itself. Hence the
 * list-quoting to keep the words of the message together. See also [x].
 */

static const char *msg_read_toomuch = "{read delivered more than requested}";
static const char *msg_read_nonbyte = "{read delivered nonbyte result}";
static const char *msg_write_toomuch = "{write wrote more than requested}";
static const char *msg_write_nothing = "{write wrote nothing}";
static const char *msg_seek_beforestart = "{Tried to seek before origin}";
#if TCL_THREADS
static const char *msg_send_originlost = "{Channel thread lost}";
#endif /* TCL_THREADS */
static const char *msg_send_dstlost    = "{Owner lost}";
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
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







-
+












-
+




















-
-
-
+
+
+
+












-
+







 *	Creates a new channel.
 *
 *----------------------------------------------------------------------
 */

int
TclChanCreateObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    ReflectedChannel *rcPtr;	/* Instance data of the new channel */
    Tcl_Obj *rcId;		/* Handle of the new channel */
    int mode;			/* R/W mode of new channel. Has to match
				 * abilities of handler commands */
    Tcl_Obj *cmdObj;		/* Command prefix, list of words */
    Tcl_Obj *cmdNameObj;	/* Command name */
    Tcl_Channel chan;		/* Token for the new channel */
    Tcl_Obj *modeObj;		/* mode in obj form for method call */
    int listc;			/* Result of 'initialize', and of */
    Tcl_Size listc;		/* Result of 'initialize', and of */
    Tcl_Obj **listv;		/* its sublist in the 2nd element */
    int methIndex;		/* Encoded method name */
    int result;			/* Result code for 'initialize' */
    Tcl_Obj *resObj;		/* Result data for 'initialize' */
    int methods;		/* Bitmask for supported methods. */
    Channel *chanPtr;		/* 'chan' resolved to internal struct. */
    Tcl_Obj *err;		/* Error message */
    ReflectedChannelMap *rcmPtr;
				/* Map of reflected channels with handlers in
				 * this interp. */
    Tcl_HashEntry *hPtr;	/* Entry in the above map */
    int isNew;			/* Placeholder. */

    /*
     * Syntax:   chan create MODE CMDPREFIX
     *           [0]  [1]    [2]  [3]
     *
     * Actually: rCreate MODE CMDPREFIX
     *           [0]     [1]  [2]
     */

#define MODE	(1)
#define CMD	(2)
    enum ArgIndices {
	MODE = 1,
	CMD = 2
    };

    /*
     * Number of arguments...
     */

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "mode cmdprefix");
	return TCL_ERROR;
    }

    /*
     * First argument is a list of modes. Allowed entries are "read", "write".
     * Expect at least one list element. Abbreviations are ok.
     * Empty list is uncommon, but allowed. Abbreviations are ok.
     */

    modeObj = objv[MODE];
    if (EncodeEventMask(interp, "mode", objv[MODE], &mode) != TCL_OK) {
	return TCL_ERROR;
    }

565
566
567
568
569
570
571



572
573
574
575
576
577
578
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581







+
+
+








    /*
     * Now create the channel.
     */

    rcId = NextHandle();
    rcPtr = NewReflectedChannel(interp, cmdObj, mode, rcId);
    if (!rcPtr) {
	return TCL_ERROR;
    }

    /*
     * Invoke 'initialize' and validate that the handler is present and ok.
     * Squash the channel if not.
     *
     * Note: The conversion of 'mode' back into a Tcl_Obj ensures that
     * 'initialize' is invoked with canonical mode names, and no
594
595
596
597
598
599
600
601
602
603
604




605
606
607
608
609
610
611
597
598
599
600
601
602
603




604
605
606
607
608
609
610
611
612
613
614







-
-
-
-
+
+
+
+







    /*
     * Verify the result.
     * - List, of method names. Convert to mask.
     *   Check for non-optionals through the mask.
     *   Compare open mode against optional r/w.
     */

    if (Tcl_ListObjGetElements(NULL, resObj, &listc, &listv) != TCL_OK) {
        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "chan handler \"%s initialize\" returned non-list: %s",
                TclGetString(cmdObj), TclGetString(resObj)));
    if (TclListObjGetElements(NULL, resObj, &listc, &listv) != TCL_OK) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"chan handler \"%s initialize\" returned non-list: %s",
		TclGetString(cmdObj), TclGetString(resObj)));
	Tcl_DecrRefCount(resObj);
	goto error;
    }

    methods = 0;
    while (listc > 0) {
	if (Tcl_GetIndexFromObj(interp, listv[listc-1], methodNames,
621
622
623
624
625
626
627
628
629
630



631
632
633
634
635
636
637



638
639
640
641
642
643
644



645
646
647
648
649
650
651



652
653
654
655
656
657
658



659
660
661
662
663
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
707
708
709
710
624
625
626
627
628
629
630



631
632
633
634
635
636
637



638
639
640
641
642
643
644



645
646
647
648
649
650
651



652
653
654
655
656
657
658



659
660
661
662
663
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
707
708

709
710
711
712
713
714
715
716







-
-
-
+
+
+




-
-
-
+
+
+




-
-
-
+
+
+




-
-
-
+
+
+




-
-
-
+
+
+









-
+














-
+














+
+
+





-
+








	methods |= FLAG(methIndex);
	listc--;
    }
    Tcl_DecrRefCount(resObj);

    if ((REQUIRED_METHODS & methods) != REQUIRED_METHODS) {
        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "chan handler \"%s\" does not support all required methods",
                TclGetString(cmdObj)));
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"chan handler \"%s\" does not support all required methods",
		TclGetString(cmdObj)));
	goto error;
    }

    if ((mode & TCL_READABLE) && !HAS(methods, METH_READ)) {
        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "chan handler \"%s\" lacks a \"read\" method",
                TclGetString(cmdObj)));
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"chan handler \"%s\" lacks a \"read\" method",
		TclGetString(cmdObj)));
	goto error;
    }

    if ((mode & TCL_WRITABLE) && !HAS(methods, METH_WRITE)) {
        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "chan handler \"%s\" lacks a \"write\" method",
                TclGetString(cmdObj)));
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"chan handler \"%s\" lacks a \"write\" method",
		TclGetString(cmdObj)));
	goto error;
    }

    if (!IMPLIES(HAS(methods, METH_CGET), HAS(methods, METH_CGETALL))) {
        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "chan handler \"%s\" supports \"cget\" but not \"cgetall\"",
                TclGetString(cmdObj)));
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"chan handler \"%s\" supports \"cget\" but not \"cgetall\"",
		TclGetString(cmdObj)));
	goto error;
    }

    if (!IMPLIES(HAS(methods, METH_CGETALL), HAS(methods, METH_CGET))) {
        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "chan handler \"%s\" supports \"cgetall\" but not \"cget\"",
                TclGetString(cmdObj)));
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"chan handler \"%s\" supports \"cgetall\" but not \"cget\"",
		TclGetString(cmdObj)));
	goto error;
    }

    Tcl_ResetResult(interp);

    /*
     * Everything is fine now.
     */

    chan = Tcl_CreateChannel(&tclRChannelType, TclGetString(rcId), rcPtr,
    chan = Tcl_CreateChannel(&reflectedChannelType, TclGetString(rcId), rcPtr,
	    mode);
    rcPtr->chan = chan;
    TclChannelPreserve(chan);
    chanPtr = (Channel *) chan;

    if ((methods & NULLABLE_METHODS) != NULLABLE_METHODS) {
	/*
	 * Some of the nullable methods are not supported. We clone the
	 * channel type, null the associated C functions, and use the result
	 * as the actual channel type.
	 */

	Tcl_ChannelType *clonePtr = (Tcl_ChannelType *)Tcl_Alloc(sizeof(Tcl_ChannelType));

	memcpy(clonePtr, &tclRChannelType, sizeof(Tcl_ChannelType));
	memcpy(clonePtr, &reflectedChannelType, sizeof(Tcl_ChannelType));

	if (!(methods & FLAG(METH_CONFIGURE))) {
	    clonePtr->setOptionProc = NULL;
	}

	if (!(methods & FLAG(METH_CGET)) && !(methods & FLAG(METH_CGETALL))) {
	    clonePtr->getOptionProc = NULL;
	}
	if (!(methods & FLAG(METH_BLOCKING))) {
	    clonePtr->blockModeProc = NULL;
	}
	if (!(methods & FLAG(METH_SEEK))) {
	    clonePtr->wideSeekProc = NULL;
	}
	if (!(methods & FLAG(METH_TRUNCATE))) {
	    clonePtr->truncateProc = NULL;
	}

	chanPtr->typePtr = clonePtr;
    }

    /*
     * Register the channel in the I/O system, and in our our map for 'chan
     * Register the channel in the I/O system, and in our map for 'chan
     * postevent'.
     */

    Tcl_RegisterChannel(interp, chan);

    rcmPtr = GetReflectedChannelMap(interp);
    hPtr = Tcl_CreateHashEntry(&rcmPtr->map, chanPtr->state->channelName,
721
722
723
724
725
726
727
728

729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
727
728
729
730
731
732
733

734
735
736
737
738
739
740
741
742



743
744
745
746
747
748
749







-
+








-
-
-







#endif

    /*
     * Return handle as result of command.
     */

    Tcl_SetObjResult(interp,
            Tcl_NewStringObj(chanPtr->state->channelName, -1));
	    Tcl_NewStringObj(chanPtr->state->channelName, -1));
    return TCL_OK;

  error:
    Tcl_DecrRefCount(rcPtr->name);
    Tcl_DecrRefCount(rcPtr->methods);
    Tcl_DecrRefCount(rcPtr->cmd);
    Tcl_Free(rcPtr);
    return TCL_ERROR;

#undef MODE
#undef CMD
}

/*
 *----------------------------------------------------------------------
 *
 * TclChanPostEventObjCmd --
 *
781
782
783
784
785
786
787
788

789
790
791
792
793
794
795
796
797
798
799
800

801
802
803
804
805
806
807
808

809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826




827
828
829
830
831
832
833
784
785
786
787
788
789
790

791
792
793
794
795
796
797
798
799
800
801
802

803
804
805
806
807
808
809
810

811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826



827
828
829
830
831
832
833
834
835
836
837







-
+











-
+







-
+















-
-
-
+
+
+
+







    Tcl_NotifyChannel(e->rcPtr->chan, e->events);
    return 1;
}

static int
ReflectEventDelete(
    Tcl_Event *ev,
    ClientData cd)
    void *cd)
{
    /* OWNER thread
     *
     * Invoked by DeleteThreadReflectedChannelMap() and ReflectClose(). The
     * latter ensures that no pending events of this type are run on an
     * invalid channel.
     */

    ReflectEvent *e = (ReflectEvent *) ev;

    if ((ev->proc != ReflectEventRun) || ((cd != NULL) && (cd != e->rcPtr))) {
        return 0;
	return 0;
    }
    return 1;
}
#endif

int
TclChanPostEventObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    /*
     * Ensure -> HANDLER thread
     *
     * Syntax:   chan postevent CHANNEL EVENTSPEC
     *           [0]  [1]       [2]     [3]
     *
     * Actually: rPostevent CHANNEL EVENTSPEC
     *           [0]        [1]     [2]
     *
     * where EVENTSPEC = {read write ...} (Abbreviations allowed as well).
     */

#define CHAN	(1)
#define EVENT	(2)
    enum ArgIndices {
	CHAN = 1,
	EVENT = 2
    };

    const char *chanId;		/* Tcl level channel handle */
    Tcl_Channel chan;		/* Channel associated to the handle */
    const Tcl_ChannelType *chanTypePtr;
				/* Its associated driver structure */
    ReflectedChannel *rcPtr;	/* Associated instance data */
    int events;			/* Mask of events to post */
852
853
854
855
856
857
858
859
860


861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877


878
879
880
881
882
883
884
856
857
858
859
860
861
862


863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879


880
881
882
883
884
885
886
887
888







-
-
+
+















-
-
+
+







    chanId = TclGetString(objv[CHAN]);

    rcmPtr = GetReflectedChannelMap(interp);
    hPtr = Tcl_FindHashEntry(&rcmPtr->map, chanId);

    if (hPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "can not find reflected channel named \"%s\"", chanId));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CHANNEL", chanId, NULL);
		"can not find reflected channel named \"%s\"", chanId));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CHANNEL", chanId, (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Note that the search above subsumes several of the older checks,
     * namely:
     *
     * (1) Does the channel handle refer to a reflected channel?
     * (2) Is the post event issued from the interpreter holding the handler
     *     of the reflected channel?
     *
     * A successful search answers yes to both. Because the map holds only
     * handles of reflected channels, and only of such whose handler is
     * defined in this interpreter.
     *
     * We keep the old checks for both, for paranioa, but abort now instead of
     * throwing errors, as failure now means that our internal datastructures
     * We keep the old checks for both, for paranoia, but abort now instead of
     * throwing errors, as failure now means that our internal data structures
     * have gone seriously haywire.
     */

    chan = (Tcl_Channel)Tcl_GetHashValue(hPtr);
    chanTypePtr = Tcl_GetChannelType(chan);

    /*
904
905
906
907
908
909
910





911
912
913
914
915
916
917
918
919


920
921
922
923
924
925
926
927
928
929
930

931
932
933
934
935
936
937
938
939
940
941
942
943
944

945
946
947
948



949
950
951
952
953
954
955
956
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
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926


927
928
929
930
931
932
933
934
935
936
937
938

939











940
941

942
943



944
945
946
947












948
949
950
951
952
953
954
955
956
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







+
+
+
+
+







-
-
+
+










-
+
-
-
-
-
-
-
-
-
-
-
-


-
+

-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+









-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







     * Second argument is a list of events. Allowed entries are "read",
     * "write". Expect at least one list element. Abbreviations are ok.
     */

    if (EncodeEventMask(interp, "event", objv[EVENT], &events) != TCL_OK) {
	return TCL_ERROR;
    }
    if (events == 0) {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("bad event list: is empty", -1));
	return TCL_ERROR;
    }

    /*
     * Check that the channel is actually interested in the provided events.
     */

    if (events & ~rcPtr->interest) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "tried to post events channel \"%s\" is not interested in",
                chanId));
		"tried to post events channel \"%s\" is not interested in",
		chanId));
	return TCL_ERROR;
    }

    /*
     * We have the channel and the events to post.
     */

#if TCL_THREADS
    if (rcPtr->owner == rcPtr->thread) {
#endif
	if (events & TCL_READABLE) {
	Tcl_NotifyChannel(chan, events);
	    if (rcPtr->readTimer == NULL) {
		rcPtr->readTimer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
			TimerRunRead, rcPtr);
	    }
	}
	if (events & TCL_WRITABLE) {
	    if (rcPtr->writeTimer == NULL) {
		rcPtr->writeTimer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
			TimerRunWrite, rcPtr);
	    }
	}
#if TCL_THREADS
    } else {
        ReflectEvent *ev = (ReflectEvent *)Tcl_Alloc(sizeof(ReflectEvent));
	ReflectEvent *ev = (ReflectEvent *)Tcl_Alloc(sizeof(ReflectEvent));

        ev->header.proc = ReflectEventRun;
        ev->events = events;
        ev->rcPtr = rcPtr;
	ev->header.proc = ReflectEventRun;
	ev->events = events;
	ev->rcPtr = rcPtr;

        /*
         * We are not preserving the structure here. When the channel is
         * closed any pending events are deleted, see ReflectClose(), and
         * ReflectEventDelete(). Trying to preserve and later release when the
         * event is run may generate a situation where the channel structure
         * is deleted but not our structure, crashing in
         * FreeReflectedChannel().
         *
         * Force creation of the RCM, for proper cleanup on thread teardown.
         * The teardown of unprocessed events is currently coupled to the
         * thread reflected channel map
         */
	/*
	 * We are not preserving the structure here. When the channel is
	 * closed any pending events are deleted, see ReflectClose(), and
	 * ReflectEventDelete(). Trying to preserve and later release when the
	 * event is run may generate a situation where the channel structure
	 * is deleted but not our structure, crashing in
	 * FreeReflectedChannel().
	 *
	 * Force creation of the RCM, for proper cleanup on thread teardown.
	 * The teardown of unprocessed events is currently coupled to the
	 * thread reflected channel map
	 */

        (void) GetThreadReflectedChannelMap();
	(void) GetThreadReflectedChannelMap();

        /*
         * XXX Race condition !!
         * XXX The destination thread may not exist anymore already.
         * XXX (Delayed postevent executed after channel got removed).
         * XXX Can we detect this ? (check the validity of the owner threadid ?)
         * XXX Actually, in that case the channel should be dead also !
         */
	/*
	 * XXX Race condition !!
	 * XXX The destination thread may not exist anymore already.
	 * XXX (Delayed postevent executed after channel got removed).
	 * XXX Can we detect this ? (check the validity of the owner threadid ?)
	 * XXX Actually, in that case the channel should be dead also !
	 */

        Tcl_ThreadQueueEvent(rcPtr->owner, (Tcl_Event *) ev, TCL_QUEUE_TAIL);
        Tcl_ThreadAlert(rcPtr->owner);
	Tcl_ThreadQueueEvent(rcPtr->owner, (Tcl_Event *) ev,
		TCL_QUEUE_TAIL|TCL_QUEUE_ALERT_IF_EMPTY);
    }
#endif

    /*
     * Squash interp results left by the event script.
     */

    Tcl_ResetResult(interp);
    return TCL_OK;

#undef CHAN
#undef EVENT
}

static void
TimerRunRead(
    ClientData clientData)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    rcPtr->readTimer = NULL;
    Tcl_NotifyChannel(rcPtr->chan, TCL_READABLE);
}

static void
TimerRunWrite(
    ClientData clientData)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    rcPtr->writeTimer = NULL;
    Tcl_NotifyChannel(rcPtr->chan, TCL_WRITABLE);
}

/*
 * Channel error message marshalling utilities.
 */

static Tcl_Obj *
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
1006
1007
1008
1009
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







-
+


-
+







-
+



-
+







}

static void
UnmarshallErrorResult(
    Tcl_Interp *interp,
    Tcl_Obj *msgObj)
{
    int lc;
    Tcl_Size lc;
    Tcl_Obj **lv;
    int explicitResult;
    int numOptions;
    Tcl_Size numOptions;

    /*
     * Process the caught message.
     *
     * Syntax = (option value)... ?message?
     *
     * Bad syntax causes a panic. This is OK because the other side uses
     * Tcl_GetReturnOptions and list construction functions to marshall the
     * Tcl_GetReturnOptions and list construction functions to marshal the
     * information; if we panic here, something has gone badly wrong already.
     */

    if (Tcl_ListObjGetElements(interp, msgObj, &lc, &lv) != TCL_OK) {
    if (TclListObjGetElements(interp, msgObj, &lc, &lv) != TCL_OK) {
	Tcl_Panic("TclChanCaughtErrorBypass: Bad syntax of caught result");
    }
    if (interp == NULL) {
	return;
    }

    explicitResult = lc & 1;		/* Odd number of values? */
1128
1129
1130
1131
1132
1133
1134
1135

1136
1137
1138

1139
1140
1141
1142
1143
1144
1145
1146
1147
1148

1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169


1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190



1191
1192

1193
1194
1195
1196
1197
1198
1199
1200
1201

1202
1203
1204
1205
1206
1207
1208
1209
1210
1211

1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228



1229
1230

1231
1232
1233
1234
1235
1236
1237
1105
1106
1107
1108
1109
1110
1111

1112
1113
1114

1115
1116
1117
1118
1119
1120
1121
1122
1123
1124

1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144


1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164



1165
1166
1167
1168

1169
1170
1171
1172
1173
1174
1175
1176
1177

1178
1179
1180
1181







1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196



1197
1198
1199
1200

1201
1202
1203
1204
1205
1206
1207
1208







-
+


-
+









-
+



















-
-
+
+


















-
-
-
+
+
+

-
+








-
+



-
-
-
-
-
-
-
+














-
-
-
+
+
+

-
+








/*
 *----------------------------------------------------------------------
 *
 * ReflectClose --
 *
 *	This function is invoked when the channel is closed, to delete the
 *	driver specific instance data.
 *	driver-specific instance data.
 *
 * Results:
 *	A posix error.
 *	A Posix error.
 *
 * Side effects:
 *	Releases memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectClose(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
	int flags)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    int result;			/* Result code for 'close' */
    Tcl_Obj *resObj;		/* Result data for 'close' */
    ReflectedChannelMap *rcmPtr;/* Map of reflected channels with handlers in
				 * this interp */
    Tcl_HashEntry *hPtr;	/* Entry in the above map */
    const Tcl_ChannelType *tctPtr;

    if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
	return EINVAL;
    }

    if (TclInThreadExit()) {
	/*
	 * This call comes from TclFinalizeIOSystem. There are no
	 * interpreters, and therefore we cannot call upon the handler command
	 * anymore. Threading is irrelevant as well. We simply clean up all
	 * our C level data structures and leave the Tcl level to the other
	 * anymore. Threading is irrelevant as well. Simply clean up all
	 * the C level data structures and leave the Tcl level to the other
	 * finalization functions.
	 */

	/*
	 * THREADED => Forward this to the origin thread
	 *
	 * Note: DeleteThreadReflectedChannelMap() is the thread exit handler
	 * for the origin thread. Use this to clean up the structure? Except
	 * if lost?
	 */

#if TCL_THREADS
	if (rcPtr->thread != Tcl_GetCurrentThread()) {
	    ForwardParam p;

	    ForwardOpToHandlerThread(rcPtr, ForwardedClose, &p);
	    result = p.base.code;

            /*
             * Now squash the pending reflection events for this channel.
             */
	    /*
	     * Now squash the pending reflection events for this channel.
	     */

            Tcl_DeleteEvents(ReflectEventDelete, rcPtr);
	    Tcl_DeleteEvents(ReflectEventDelete, rcPtr);

	    if (result != TCL_OK) {
		FreeReceivedError(&p);
	    }
	}
#endif

	tctPtr = ((Channel *)rcPtr->chan)->typePtr;
	if (tctPtr && tctPtr != &tclRChannelType) {
	if (tctPtr && tctPtr != &reflectedChannelType) {
	    Tcl_Free((void *)tctPtr);
	    ((Channel *)rcPtr->chan)->typePtr = NULL;
	}
	if (rcPtr->readTimer != NULL) {
	    Tcl_DeleteTimerHandler(rcPtr->readTimer);
	}
	if (rcPtr->writeTimer != NULL) {
	    Tcl_DeleteTimerHandler(rcPtr->writeTimer);
	}
        Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
	Tcl_EventuallyFree(rcPtr, FreeReflectedChannel);
	return EOK;
    }

    /*
     * Are we in the correct thread?
     */

#if TCL_THREADS
    if (rcPtr->thread != Tcl_GetCurrentThread()) {
	ForwardParam p;

	ForwardOpToHandlerThread(rcPtr, ForwardedClose, &p);
	result = p.base.code;

        /*
         * Now squash the pending reflection events for this channel.
         */
	/*
	 * Now squash the pending reflection events for this channel.
	 */

        Tcl_DeleteEvents(ReflectEventDelete, rcPtr);
	Tcl_DeleteEvents(ReflectEventDelete, rcPtr);

	if (result != TCL_OK) {
	    PassReceivedErrorInterp(interp, &p);
	}
    } else {
#endif
	result = InvokeTclMethod(rcPtr, METH_FINAL, NULL, NULL, &resObj);
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
1240
1241
1242
1243
1244
1245
1246

1247
1248
1249
1250







1251
1252
1253
1254
1255
1256
1257
1258







-
+



-
-
-
-
-
-
-
+







		Tcl_GetChannelName(rcPtr->chan));
	if (hPtr) {
	    Tcl_DeleteHashEntry(hPtr);
	}
    }
#endif
    tctPtr = ((Channel *)rcPtr->chan)->typePtr;
    if (tctPtr && tctPtr != &tclRChannelType) {
    if (tctPtr && tctPtr != &reflectedChannelType) {
	Tcl_Free((void *)tctPtr);
	((Channel *)rcPtr->chan)->typePtr = NULL;
    }
    if (rcPtr->readTimer != NULL) {
	Tcl_DeleteTimerHandler(rcPtr->readTimer);
    }
    if (rcPtr->writeTimer != NULL) {
	Tcl_DeleteTimerHandler(rcPtr->writeTimer);
    }
    Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
    Tcl_EventuallyFree(rcPtr, FreeReflectedChannel);
    return (result == TCL_OK) ? EOK : EINVAL;
}

/*
 *----------------------------------------------------------------------
 *
 * ReflectInput --
1301
1302
1303
1304
1305
1306
1307
1308

1309
1310
1311
1312
1313
1314
1315

1316
1317
1318
1319
1320
1321
1322
1266
1267
1268
1269
1270
1271
1272

1273
1274
1275
1276
1277
1278
1279

1280
1281
1282
1283
1284
1285
1286
1287







-
+






-
+







 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectInput(
    ClientData clientData,
    void *clientData,
    char *buf,
    int toRead,
    int *errorCodePtr)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    Tcl_Obj *toReadObj;
    size_t bytec = 0;		/* Number of returned bytes */
    Tcl_Size bytec = 0;		/* Number of returned bytes */
    unsigned char *bytev;	/* Array of returned bytes */
    Tcl_Obj *resObj;		/* Result data for 'read' */

    /*
     * Are we in the correct thread?
     */

1358
1359
1360
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
1387
1388
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
1354
1355
1356







-
+



-
+


-
+

+
+
+
-
+






-
+







    Tcl_IncrRefCount(toReadObj);

    if (InvokeTclMethod(rcPtr, METH_READ, toReadObj, NULL, &resObj)!=TCL_OK) {
	int code = ErrnoReturn(rcPtr, resObj);

	if (code < 0) {
	    *errorCodePtr = -code;
            goto error;
	    goto error;
	}

	Tcl_SetChannelError(rcPtr->chan, resObj);
        goto invalid;
	goto invalid;
    }

    bytev = TclGetByteArrayFromObj(resObj, &bytec);
    bytev = Tcl_GetBytesFromObj(NULL, resObj, &bytec);

    if (bytev == NULL) {
	SetChannelErrorStr(rcPtr->chan, msg_read_nonbyte);
	goto invalid;
    if ((size_t)toRead < bytec) {
    } else if (toRead < bytec) {
	SetChannelErrorStr(rcPtr->chan, msg_read_toomuch);
	goto invalid;
    }

    *errorCodePtr = EOK;

    if (bytec + 1 > 1) {
    if (bytec > 0) {
	memcpy(buf, bytev, bytec);
    }

 stop:
    Tcl_DecrRefCount(toReadObj);
    Tcl_DecrRefCount(resObj);		/* Remove reference held from invoke */
    Tcl_Release(rcPtr);
1408
1409
1410
1411
1412
1413
1414
1415

1416
1417
1418
1419
1420
1421
1422
1376
1377
1378
1379
1380
1381
1382

1383
1384
1385
1386
1387
1388
1389
1390







-
+







 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectOutput(
    ClientData clientData,
    void *clientData,
    const char *buf,
    int toWrite,
    int *errorCodePtr)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    Tcl_Obj *bufObj;
    Tcl_Obj *resObj;		/* Result data for 'write' */
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448



1449
1450
1451
1452
1453
1454
1455
1407
1408
1409
1410
1411
1412
1413



1414
1415
1416
1417
1418
1419
1420
1421
1422
1423







-
-
-
+
+
+







	    if (p.base.code < 0) {
		/*
		 * No error message, this is an errno signal.
		 */

		*errorCodePtr = -p.base.code;
	    } else {
                PassReceivedError(rcPtr->chan, &p);
                *errorCodePtr = EINVAL;
            }
		PassReceivedError(rcPtr->chan, &p);
		*errorCodePtr = EINVAL;
	    }
	    p.output.toWrite = -1;
	} else {
	    *errorCodePtr = EOK;
	}

	return p.output.toWrite;
    }
1465
1466
1467
1468
1469
1470
1471
1472

1473
1474
1475
1476

1477
1478
1479
1480
1481
1482
1483
1484
1485

1486
1487
1488
1489

1490
1491
1492
1493
1494
1495
1496
1497
1498
1499

1500
1501
1502
1503
1504
1505
1506
1507
1508
1509

1510
1511
1512
1513
1514
1515
1516
1433
1434
1435
1436
1437
1438
1439

1440
1441
1442
1443

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
1474
1475
1476

1477
1478
1479
1480
1481
1482
1483
1484







-
+



-
+








-
+



-
+









-
+









-
+







    Tcl_IncrRefCount(bufObj);

    if (InvokeTclMethod(rcPtr, METH_WRITE, bufObj, NULL, &resObj) != TCL_OK) {
	int code = ErrnoReturn(rcPtr, resObj);

	if (code < 0) {
	    *errorCodePtr = -code;
            goto error;
	    goto error;
	}

	Tcl_SetChannelError(rcPtr->chan, resObj);
        goto invalid;
	goto invalid;
    }

    if (Tcl_InterpDeleted(rcPtr->interp)) {
	/*
	 * The interp was destroyed during InvokeTclMethod().
	 */

	SetChannelErrorStr(rcPtr->chan, msg_send_dstlost);
        goto invalid;
	goto invalid;
    }
    if (Tcl_GetIntFromObj(rcPtr->interp, resObj, &written) != TCL_OK) {
	Tcl_SetChannelError(rcPtr->chan, MarshallError(rcPtr->interp));
        goto invalid;
	goto invalid;
    }

    if ((written == 0) && (toWrite > 0)) {
	/*
	 * The handler claims to have written nothing of what it was given.
	 * That is bad.
	 */

	SetChannelErrorStr(rcPtr->chan, msg_write_nothing);
        goto invalid;
	goto invalid;
    }
    if (toWrite < written) {
	/*
	 * The handler claims to have written more than it was given. That is
	 * bad. Note that the I/O core would crash if we were to return this
	 * information, trying to write -nnn bytes in the next iteration.
	 */

	SetChannelErrorStr(rcPtr->chan, msg_write_toomuch);
        goto invalid;
	goto invalid;
    }

    *errorCodePtr = EOK;
 stop:
    Tcl_DecrRefCount(bufObj);
    Tcl_DecrRefCount(resObj);		/* Remove reference held from invoke */
    Tcl_Release(rcPtr->interp);
1535
1536
1537
1538
1539
1540
1541
1542

1543
1544
1545


1546
1547
1548
1549
1550
1551
1552
1503
1504
1505
1506
1507
1508
1509

1510
1511


1512
1513
1514
1515
1516
1517
1518
1519
1520







-
+

-
-
+
+







 *
 * Side effects:
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static Tcl_WideInt
static long long
ReflectSeekWide(
    ClientData clientData,
    Tcl_WideInt offset,
    void *clientData,
    long long offset,
    int seekMode,
    int *errorCodePtr)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    Tcl_Obj *offObj, *baseObj;
    Tcl_Obj *resObj;		/* Result for 'seek' */
    Tcl_WideInt newLoc;
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
1546
1547
1548
1549
1550
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







-
-
+
+





-
+


-
+

-
+




-
+








    /* ASSERT: rcPtr->method & FLAG(METH_SEEK) */

    Tcl_Preserve(rcPtr);

    TclNewIntObj(offObj, offset);
    baseObj = Tcl_NewStringObj(
            (seekMode == SEEK_SET) ? "start" :
            (seekMode == SEEK_CUR) ? "current" : "end", -1);
	    (seekMode == SEEK_SET) ? "start" :
	    (seekMode == SEEK_CUR) ? "current" : "end", -1);
    Tcl_IncrRefCount(offObj);
    Tcl_IncrRefCount(baseObj);

    if (InvokeTclMethod(rcPtr, METH_SEEK, offObj, baseObj, &resObj)!=TCL_OK) {
	Tcl_SetChannelError(rcPtr->chan, resObj);
        goto invalid;
	goto invalid;
    }

    if (Tcl_GetWideIntFromObj(rcPtr->interp, resObj, &newLoc) != TCL_OK) {
    if (TclGetWideIntFromObj(rcPtr->interp, resObj, &newLoc) != TCL_OK) {
	Tcl_SetChannelError(rcPtr->chan, MarshallError(rcPtr->interp));
        goto invalid;
	goto invalid;
    }

    if (newLoc < 0) {
	SetChannelErrorStr(rcPtr->chan, msg_seek_beforestart);
        goto invalid;
	goto invalid;
    }

    *errorCodePtr = EOK;
 stop:
    Tcl_DecrRefCount(offObj);
    Tcl_DecrRefCount(baseObj);
    Tcl_DecrRefCount(resObj);		/* Remove reference held from invoke */
1630
1631
1632
1633
1634
1635
1636
1637

1638
1639
1640
1641
1642
1643
1644
1598
1599
1600
1601
1602
1603
1604

1605
1606
1607
1608
1609
1610
1611
1612







-
+







 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static void
ReflectWatch(
    ClientData clientData,
    void *clientData,
    int mask)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    Tcl_Obj *maskObj;

    /*
     * We restrict the interest to what the channel can support. IOW there
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
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







-
+









-
+







 *
 * ReflectBlock --
 *
 *	This function is invoked to tell the channel which blocking behaviour
 *	is required of it.
 *
 * Results:
 *	A posix error number.
 *	A Posix error number.
 *
 * Side effects:
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectBlock(
    ClientData clientData,
    void *clientData,
    int nonblocking)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    Tcl_Obj *blockObj;
    int errorNum;		/* EINVAL or EOK (success). */
    Tcl_Obj *resObj;		/* Result data for 'blocking' */

1769
1770
1771
1772
1773
1774
1775
1776

1777
1778
1779
1780
1781
1782
1783
1784


1785
1786
1787


1788
1789
1790


1791
1792
1793
1794
1795
1796
1797
1737
1738
1739
1740
1741
1742
1743

1744
1745
1746
1747
1748
1749
1750


1751
1752
1753


1754
1755
1756


1757
1758
1759
1760
1761
1762
1763
1764
1765







-
+






-
-
+
+

-
-
+
+

-
-
+
+







 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static void
ReflectThread(
    ClientData clientData,
    void *clientData,
    int action)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;

    switch (action) {
    case TCL_CHANNEL_THREAD_INSERT:
        rcPtr->owner = Tcl_GetCurrentThread();
        break;
	rcPtr->owner = Tcl_GetCurrentThread();
	break;
    case TCL_CHANNEL_THREAD_REMOVE:
        rcPtr->owner = NULL;
        break;
	rcPtr->owner = NULL;
	break;
    default:
        Tcl_Panic("Unknown thread action code.");
        break;
	Tcl_Panic("Unknown thread action code.");
	break;
    }
}

#endif
/*
 *----------------------------------------------------------------------
 *
1806
1807
1808
1809
1810
1811
1812
1813

1814
1815
1816
1817
1818
1819
1820
1774
1775
1776
1777
1778
1779
1780

1781
1782
1783
1784
1785
1786
1787
1788







-
+







 *	Arbitrary, as it calls upon a Tcl script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectSetOption(
    ClientData clientData,	/* Channel to query */
    void *clientData,	/* Channel to query */
    Tcl_Interp *interp,		/* Interpreter to leave error messages in */
    const char *optionName,	/* Name of requested option */
    const char *newValue)	/* The new value */
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    Tcl_Obj *optionObj, *valueObj;
    int result;			/* Result code for 'configure' */
1878
1879
1880
1881
1882
1883
1884
1885

1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897

1898

1899
1900
1901
1902
1903
1904
1905
1846
1847
1848
1849
1850
1851
1852

1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866

1867
1868
1869
1870
1871
1872
1873
1874







-
+












+
-
+







 *	Arbitrary, as it calls upon a Tcl script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectGetOption(
    ClientData clientData,	/* Channel to query */
    void *clientData,	/* Channel to query */
    Tcl_Interp *interp,		/* Interpreter to leave error messages in */
    const char *optionName,	/* Name of reuqested option */
    Tcl_DString *dsPtr)		/* String to place the result into */
{
    /*
     * This code is special. It has regular passing of Tcl result, and errors.
     * The bypass functions are not required.
     */

    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    Tcl_Obj *optionObj;
    Tcl_Obj *resObj;		/* Result data for 'configure' */
    Tcl_Size listc;
    int listc, result = TCL_OK;
    int result = TCL_OK;
    Tcl_Obj **listv;
    MethodName method;

    /*
     * Are we in the correct thread?
     */

1941
1942
1943
1944
1945
1946
1947
1948

1949
1950
1951
1952
1953
1954
1955

1956
1957
1958
1959
1960
1961
1962
1963
1964
1965

1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980


1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991

1992
1993

1994
1995

1996
1997
1998
1999
2000
2001
2002

2003
2004
2005
2006
2007
2008
2009

2010
2011
2012
2013
2014
2015
2016
2017



































































2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032




2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053

2054
2055
2056
2057
2058

2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
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
1958
1959

1960
1961

1962
1963

1964
1965
1966
1967
1968
1969
1970

1971
1972
1973
1974
1975
1976
1977

1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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






2095
2096
2097
2098
2099
2100
2101







-
+






-
+









-
+













-
-
+
+










-
+

-
+

-
+






-
+






-
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
-
-
-
+
+
+
+




















-
+




-
+
-
-
-
-
-
-







    } else {
	/*
	 * Retrieve the value of one option.
	 */

	method = METH_CGET;
	optionObj = Tcl_NewStringObj(optionName, -1);
        Tcl_IncrRefCount(optionObj);
	Tcl_IncrRefCount(optionObj);
    }

    Tcl_Preserve(rcPtr);

    if (InvokeTclMethod(rcPtr, method, optionObj, NULL, &resObj)!=TCL_OK) {
	UnmarshallErrorResult(interp, resObj);
        goto error;
	goto error;
    }

    /*
     * The result has to go into the 'dsPtr' for propagation to the caller of
     * the driver.
     */

    if (optionObj != NULL) {
	TclDStringAppendObj(dsPtr, resObj);
        goto ok;
	goto ok;
    }

    /*
     * Extract the list and append each item as element.
     */

    /*
     * NOTE (4): If we extract the string rep we can assume a properly quoted
     * string. Together with a separating space this way of simply appending
     * the whole string rep might be faster. It also doesn't check if the
     * result is a valid list. Nor that the list has an even number elements.
     */

    if (Tcl_ListObjGetElements(interp, resObj, &listc, &listv) != TCL_OK) {
        goto error;
    if (TclListObjGetElements(interp, resObj, &listc, &listv) != TCL_OK) {
	goto error;
    }

    if ((listc % 2) == 1) {
	/*
	 * Odd number of elements is wrong.
	 */

	Tcl_ResetResult(interp);
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"Expected list with even number of "
		"elements, got %d element%s instead", listc,
		"elements, got %" TCL_SIZE_MODIFIER "d element%s instead", listc,
		(listc == 1 ? "" : "s")));
        goto error;
	goto error;
    } else {
	size_t len;
	Tcl_Size len;
	const char *str = TclGetStringFromObj(resObj, &len);

	if (len) {
	    TclDStringAppendLiteral(dsPtr, " ");
	    Tcl_DStringAppend(dsPtr, str, len);
	}
        goto ok;
	goto ok;
    }

 ok:
    result = TCL_OK;
 stop:
    if (optionObj) {
        Tcl_DecrRefCount(optionObj);
	Tcl_DecrRefCount(optionObj);
    }
    Tcl_DecrRefCount(resObj);	/* Remove reference held from invoke */
    Tcl_Release(rcPtr);
    return result;
 error:
    result = TCL_ERROR;
    goto stop;
}

/*
 *----------------------------------------------------------------------
 *
 * ReflectTruncate --
 *
 *	This function is invoked to truncate a channel's file size.
 *
 * Results:
 *	A standard Tcl result code.
 *
 * Side effects:
 *	Arbitrary, as it calls upon a Tcl script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectTruncate(
    void *clientData,	/* Channel to query */
    long long length)		/* Length to truncate to. */
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    Tcl_Obj *lenObj;
    int errorNum;		/* EINVAL or EOK (success). */
    Tcl_Obj *resObj;		/* Result for 'truncate' */

    /*
     * Are we in the correct thread?
     */

#if TCL_THREADS
    if (rcPtr->thread != Tcl_GetCurrentThread()) {
	ForwardParam p;

	p.truncate.length = length;

	ForwardOpToHandlerThread(rcPtr, ForwardedTruncate, &p);

	if (p.base.code != TCL_OK) {
	    PassReceivedError(rcPtr->chan, &p);
	    return EINVAL;
	}

	return EOK;
    }
#endif

    /* ASSERT: rcPtr->method & FLAG(METH_TRUNCATE) */

    Tcl_Preserve(rcPtr);

    lenObj  = Tcl_NewWideIntObj(length);
    Tcl_IncrRefCount(lenObj);

    if (InvokeTclMethod(rcPtr,METH_TRUNCATE,lenObj,NULL,&resObj)!=TCL_OK) {
	Tcl_SetChannelError(rcPtr->chan, resObj);
	errorNum = EINVAL;
    } else {
	errorNum = EOK;
    }

    Tcl_DecrRefCount(lenObj);
    Tcl_DecrRefCount(resObj);		/* Remove reference held from invoke */
    Tcl_Release(rcPtr);
    return errorNum;
}

/*
 * Helpers. =========================================================
 */

/*
 *----------------------------------------------------------------------
 *
 * EncodeEventMask --
 *
 *	This function takes a list of event items and constructs the
 *	equivalent internal bitmask. The list must contain at least one
 *	element. Elements are "read", "write", or any unique abbreviation of
 *	them. Note that the bitmask is not changed if problems are
 *	encountered.
 *	equivalent internal bitmask. The list may be empty but will usually
 *	contain at least one element. Valid elements are "read", "write", or
 *	any unique abbreviation of them. Note that the bitmask is not changed
 *	if problems are encountered.
 *
 * Results:
 *	A standard Tcl error code. A bitmask where TCL_READABLE and/or
 *	TCL_WRITABLE can be set.
 *
 * Side effects:
 *	May shimmer 'obj' to a list representation. May place an error message
 *	into the interp result.
 *
 *----------------------------------------------------------------------
 */

static int
EncodeEventMask(
    Tcl_Interp *interp,
    const char *objName,
    Tcl_Obj *obj,
    int *mask)
{
    int events;			/* Mask of events to post */
    int listc;			/* #elements in eventspec list */
    Tcl_Size listc;			/* #elements in eventspec list */
    Tcl_Obj **listv;		/* Elements of eventspec list */
    int evIndex;		/* Id of event for an element of the eventspec
				 * list. */

    if (Tcl_ListObjGetElements(interp, obj, &listc, &listv) != TCL_OK) {
    if (TclListObjGetElements(interp, obj, &listc, &listv) != TCL_OK) {
	return TCL_ERROR;
    }

    if (listc < 1) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "bad %s list: is empty", objName));
	return TCL_ERROR;
    }

    events = 0;
    while (listc > 0) {
	if (Tcl_GetIndexFromObj(interp, listv[listc-1], eventOptions,
		objName, 0, &evIndex) != TCL_OK) {
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2192
2193
2194
2195
2196
2197
2198


2199
2200
2201
2202
2203
2204

2205
2206
2207
2208
2209
2210
2211







-
-






-







    rcPtr = (ReflectedChannel *)Tcl_Alloc(sizeof(ReflectedChannel));

    /* rcPtr->chan: Assigned by caller. Dummy data here. */

    rcPtr->chan = NULL;
    rcPtr->interp = interp;
    rcPtr->dead = 0;
    rcPtr->readTimer = 0;
    rcPtr->writeTimer = 0;
#if TCL_THREADS
    rcPtr->thread = Tcl_GetCurrentThread();
#endif
    rcPtr->mode = mode;
    rcPtr->interest = 0;		/* Initially no interest registered */

    /* ASSERT: cmdpfxObj is a Tcl List */
    rcPtr->cmd = TclListObjCopy(NULL, cmdpfxObj);
    Tcl_IncrRefCount(rcPtr->cmd);
    rcPtr->methods = Tcl_NewListObj(METH_WRITE + 1, NULL);
    while (mn <= (int)METH_WRITE) {
	Tcl_ListObjAppendElement(NULL, rcPtr->methods,
		Tcl_NewStringObj(methodNames[mn++], -1));
    }
2197
2198
2199
2200
2201
2202
2203
2204

2205
2206
2207
2208
2209
2210
2211
2224
2225
2226
2227
2228
2229
2230

2231
2232
2233
2234
2235
2236
2237
2238







-
+







 *	reflected channel.
 *
 * Results:
 *	A Tcl_Obj containing the string of the new channel handle. The
 *	refcount of the returned object is -- zero --.
 *
 * Side effects:
 *	May allocate memory. Mutex protected critical section locks out other
 *	May allocate memory. Mutex-protected critical section locks out other
 *	threads for a short time.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Obj *
NextHandle(void)
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
2253
2254
2255
2256
2257
2258
2259


2260
2261
2262
2263




2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299

2300
2301
2302
2303
2304
2305
2306
2307







-
-
+
+


-
-
-
-
+
+
+
+
+
+

+



+



+

+
+
+
+
+
+
+
+
+
+









-
+







    resObj = Tcl_ObjPrintf("rc%lu", rcCounter);
    rcCounter++;
    Tcl_MutexUnlock(&rcCounterMutex);

    return resObj;
}

static void
FreeReflectedChannel(
static inline void
CleanRefChannelInstance(
    ReflectedChannel *rcPtr)
{
    Channel *chanPtr = (Channel *) rcPtr->chan;

    TclChannelRelease((Tcl_Channel)chanPtr);
    if (rcPtr->name) {
    if (rcPtr->name) {
	/*
	 * Reset obj-type (channel is deleted or dead anyway) to avoid leakage
	 * by cyclic references (see bug [79474c58800cdf94]).
	 */
	TclFreeInternalRep(rcPtr->name);
	Tcl_DecrRefCount(rcPtr->name);
	rcPtr->name = NULL;
    }
    if (rcPtr->methods) {
	Tcl_DecrRefCount(rcPtr->methods);
	rcPtr->methods = NULL;
    }
    if (rcPtr->cmd) {
	Tcl_DecrRefCount(rcPtr->cmd);
	rcPtr->cmd = NULL;
    }
}
static void
FreeReflectedChannel(
    void *blockPtr)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *) blockPtr;
    Channel *chanPtr = (Channel *) rcPtr->chan;

    TclChannelRelease((Tcl_Channel)chanPtr);
    CleanRefChannelInstance(rcPtr);
    Tcl_Free(rcPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * InvokeTclMethod --
 *
 *	This function is used to invoke the Tcl level of a reflected channel.
 *	It handles all the command assembly, invokation, and generic state and
 *	It handles all the command assembly, invocation, and generic state and
 *	result mgmt. It does *not* handle thread redirection; that is the
 *	responsibility of clients of this function.
 *
 * Results:
 *	Result code and data as returned by the method.
 *
 * Side effects:
2279
2280
2281
2282
2283
2284
2285
2286
2287


2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305




2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
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







-
-
+
+














-
-
-
-
+
+
+
+










-







    MethodName method,
    Tcl_Obj *argOneObj,		/* NULL'able */
    Tcl_Obj *argTwoObj,		/* NULL'able */
    Tcl_Obj **resultObjPtr)	/* NULL'able */
{
    Tcl_Obj *methObj = NULL;	/* Method name in object form */
    Tcl_InterpState sr;		/* State of handler interp */
    int result;			/* Result code of method invokation */
    Tcl_Obj *resObj = NULL;	/* Result of method invokation. */
    int result;			/* Result code of method invocation */
    Tcl_Obj *resObj = NULL;	/* Result of method invocation. */
    Tcl_Obj *cmd;

    if (rcPtr->dead) {
	/*
	 * The channel is marked as dead. Bail out immediately, with an
	 * appropriate error.
	 */

	if (resultObjPtr != NULL) {
	    resObj = Tcl_NewStringObj(msg_dstlost,-1);
	    *resultObjPtr = resObj;
	    Tcl_IncrRefCount(resObj);
	}

        /*
         * Not touching argOneObj, argTwoObj, they have not been used.
         * See the contract as well.
         */
	/*
	 * Not touching argOneObj, argTwoObj, they have not been used.
	 * See the contract as well.
	 */

	return TCL_ERROR;
    }

    /*
     * Insert method into the callback command, after the command prefix,
     * before the channel id.
     */

    cmd = TclListObjCopy(NULL, rcPtr->cmd);

    Tcl_ListObjIndex(NULL, rcPtr->methods, method, &methObj);
    Tcl_ListObjAppendElement(NULL, cmd, methObj);
    Tcl_ListObjAppendElement(NULL, cmd, rcPtr->name);

    /*
     * Append the additional argument containing method specific details
     * behind the channel id. If specified.
2363
2364
2365
2366
2367
2368
2369
2370

2371
2372
2373
2374
2375
2376
2377
2404
2405
2406
2407
2408
2409
2410

2411
2412
2413
2414
2415
2416
2417
2418







-
+







	     * the full state of the result, including additional options.
	     *
	     * This is complex and ugly, and would be completely unnecessary
	     * if we only added support for a TCL_FORBID_EXCEPTIONS flag.
	     */

	    if (result != TCL_ERROR) {
		size_t cmdLen;
		Tcl_Size cmdLen;
		const char *cmdString = TclGetStringFromObj(cmd, &cmdLen);

		Tcl_IncrRefCount(cmd);
		Tcl_ResetResult(rcPtr->interp);
		Tcl_SetObjResult(rcPtr->interp, Tcl_ObjPrintf(
			"chan handler returned bad code: %d", result));
		Tcl_LogCommandInfo(rcPtr->interp, cmdString, cmdString,
2499
2500
2501
2502
2503
2504
2505
2506

2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519

2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536

2537
2538
2539
2540
2541
2542
2543
2540
2541
2542
2543
2544
2545
2546

2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559

2560











2561
2562
2563
2564
2565

2566
2567
2568
2569
2570
2571
2572
2573







-
+












-
+
-
-
-
-
-
-
-
-
-
-
-





-
+







 *	an interpreter is deleted, via the AssocData cleanup mechanism.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Deletes the hash table of channels. May close channels. May flush
 *	output on closed channels. Removes any channeEvent handlers that were
 *	output on closed channels. Removes any channelEvent handlers that were
 *	registered in this interpreter.
 *
 *----------------------------------------------------------------------
 */

static void
MarkDead(
    ReflectedChannel *rcPtr)
{
    if (rcPtr->dead) {
	return;
    }
    if (rcPtr->name) {
    CleanRefChannelInstance(rcPtr);
	Tcl_DecrRefCount(rcPtr->name);
	rcPtr->name = NULL;
    }
    if (rcPtr->methods) {
	Tcl_DecrRefCount(rcPtr->methods);
	rcPtr->methods = NULL;
    }
    if (rcPtr->cmd) {
	Tcl_DecrRefCount(rcPtr->cmd);
	rcPtr->cmd = NULL;
    }
    rcPtr->dead = 1;
}

static void
DeleteReflectedChannelMap(
    ClientData clientData,	/* The per-interpreter data structure. */
    void *clientData,	/* The per-interpreter data structure. */
    Tcl_Interp *interp)		/* The interpreter being deleted. */
{
    ReflectedChannelMap *rcmPtr = (ReflectedChannelMap *)clientData;
				/* The map */
    Tcl_HashSearch hSearch;	 /* Search variable. */
    Tcl_HashEntry *hPtr;	 /* Search variable. */
    ReflectedChannel *rcPtr;
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606





2607
2608
2609
2610
2611
2612
2613
2625
2626
2627
2628
2629
2630
2631





2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643







-
-
-
-
-
+
+
+
+
+








	    continue;
	}

	/*
	 * The receiver for the event exited, before processing the event. We
	 * detach the result now, wake the originator up and signal failure.
         *
         * Attention: Results may have been detached already, by either the
         * receiver, or this thread, as part of other parts in the thread
         * teardown. Such results are ignored. See ticket [b47b176adf] for the
         * identical race condition in Tcl 8.6 IORTrans.
	 *
	 * Attention: Results may have been detached already, by either the
	 * receiver, or this thread, as part of other parts in the thread
	 * teardown. Such results are ignored. See ticket [b47b176adf] for the
	 * identical race condition in Tcl 8.6 IORTrans.
	 */

	evPtr = resultPtr->evPtr;

	/*
	 * Basic crash safety until this routine can get revised [3411310]
	 */
2651
2652
2653
2654
2655
2656
2657


2658
2659
2660
2661
2662
2663
2664
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696







+
+








	    continue;
	}

	MarkDead(rcPtr);
	Tcl_DeleteHashEntry(hPtr);
    }
#else
    (void)interp;
#endif
}

#if TCL_THREADS
/*
 *----------------------------------------------------------------------
 *
2706
2707
2708
2709
2710
2711
2712
2713

2714
2715
2716
2717
2718
2719

2720
2721
2722
2723
2724
2725
2726
2738
2739
2740
2741
2742
2743
2744

2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759







-
+






+







 *	Deletes the hash table of channels.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteThreadReflectedChannelMap(
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    Tcl_HashSearch hSearch;	 /* Search variable. */
    Tcl_HashEntry *hPtr;	 /* Search variable. */
    Tcl_ThreadId self = Tcl_GetCurrentThread();
    ReflectedChannelMap *rcmPtr; /* The map */
    ForwardingResult *resultPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    /*
     * The origin thread for one or more reflected channels is gone.
     * NOTE: If this function is called due to a thread getting killed the
     *       per-interp DeleteReflectedChannelMap is apparently not called.
     */

2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756





2757
2758
2759
2760
2761
2762
2763
2778
2779
2780
2781
2782
2783
2784





2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796







-
-
-
-
-
+
+
+
+
+








	    continue;
	}

	/*
	 * The receiver for the event exited, before processing the event. We
	 * detach the result now, wake the originator up and signal failure.
         *
         * Attention: Results may have been detached already, by either the
         * receiver, or this thread, as part of other parts in the thread
         * teardown. Such results are ignored. See ticket [b47b176adf] for the
         * identical race condition in Tcl 8.6 IORTrans.
	 *
	 * Attention: Results may have been detached already, by either the
	 * receiver, or this thread, as part of other parts in the thread
	 * teardown. Such results are ignored. See ticket [b47b176adf] for the
	 * identical race condition in Tcl 8.6 IORTrans.
	 */

	evPtr = resultPtr->evPtr;

	/*
	 * Basic crash safety until this routine can get revised [3411310]
	 */
2792
2793
2794
2795
2796
2797
2798

2799
2800
2801
2802
2803
2804
2805
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839







+







    /*
     * Get the map of all channels handled by the current thread. This is a
     * ReflectedChannelMap, but on a per-thread basis, not per-interp. Go
     * through the channels, remove all, mark them as dead.
     */

    rcmPtr = GetThreadReflectedChannelMap();
    tsdPtr->rcmPtr = NULL;
    for (hPtr = Tcl_FirstHashEntry(&rcmPtr->map, &hSearch);
	    hPtr != NULL;
	    hPtr = Tcl_FirstHashEntry(&rcmPtr->map, &hSearch)) {
	Tcl_Channel chan = (Tcl_Channel)Tcl_GetHashValue(hPtr);
	ReflectedChannel *rcPtr = (ReflectedChannel *)Tcl_GetChannelInstanceData(chan);

	MarkDead(rcPtr);
2881
2882
2883
2884
2885
2886
2887
2888
2889


2890
2891
2892
2893
2894
2895
2896
2915
2916
2917
2918
2919
2920
2921


2922
2923
2924
2925
2926
2927
2928
2929
2930







-
-
+
+








    Tcl_CreateThreadExitHandler(SrcExitProc, evPtr);

    /*
     * Queue the event and poke the other thread's notifier.
     */

    Tcl_ThreadQueueEvent(dst, (Tcl_Event *) evPtr, TCL_QUEUE_TAIL);
    Tcl_ThreadAlert(dst);
    Tcl_ThreadQueueEvent(dst, (Tcl_Event *) evPtr,
	    TCL_QUEUE_TAIL|TCL_QUEUE_ALERT_IF_EMPTY);

    /*
     * (*) Block until the handler thread has either processed the transfer or
     * rejected it.
     */

    while (resultPtr->result < 0) {
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
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







-
+











-
+







     * Notes regarding access to the referenced data.
     *
     * In principle the data belongs to the originating thread (see
     * evPtr->src), however this thread is currently blocked at (*), i.e.,
     * quiescent. Because of this we can treat the data as belonging to us,
     * without fear of race conditions. I.e. we can read and write as we like.
     *
     * The only thing we cannot be sure of is the resultPtr. This can be be
     * The only thing we cannot be sure of is the resultPtr. This can be
     * NULLed if the originating thread went away while the event is handled
     * here now.
     */

    ForwardingEvent *evPtr = (ForwardingEvent *) evGPtr;
    ForwardingResult *resultPtr = evPtr->resultPtr;
    ReflectedChannel *rcPtr = evPtr->rcPtr;
    Tcl_Interp *interp = rcPtr->interp;
    ForwardParam *paramPtr = evPtr->param;
    Tcl_Obj *resObj = NULL;	/* Interp result of InvokeTclMethod */
    ReflectedChannelMap *rcmPtr;/* Map of reflected channels with handlers in
                                 * this interp. */
				 * this interp. */
    Tcl_HashEntry *hPtr;	/* Entry in the above map */

    /*
     * Ignore the event if no one is waiting for its result anymore.
     */

    if (!resultPtr) {
3000
3001
3002
3003
3004
3005
3006
3007

3008
3009
3010
3011
3012

3013
3014
3015
3016
3017
3018
3019
3034
3035
3036
3037
3038
3039
3040

3041
3042
3043
3044
3045

3046
3047
3048
3049
3050
3051
3052
3053







-
+




-
+







	 * We remove the channel from both interpreter and thread maps before
	 * releasing the memory, to prevent future accesses (like by
	 * 'postevent') from finding and dereferencing a dangling pointer.
	 */

	rcmPtr = GetReflectedChannelMap(interp);
	hPtr = Tcl_FindHashEntry(&rcmPtr->map,
                Tcl_GetChannelName(rcPtr->chan));
		Tcl_GetChannelName(rcPtr->chan));
	Tcl_DeleteHashEntry(hPtr);

	rcmPtr = GetThreadReflectedChannelMap();
	hPtr = Tcl_FindHashEntry(&rcmPtr->map,
                Tcl_GetChannelName(rcPtr->chan));
		Tcl_GetChannelName(rcPtr->chan));
	Tcl_DeleteHashEntry(hPtr);
	MarkDead(rcPtr);
	break;
    }

    case ForwardedInput: {
	Tcl_Obj *toReadObj;
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
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







-
+


-
+

+
+
+
-
+



-
+





-
-
+
+





-
-
+
+

-
+







	    }
	    paramPtr->input.toRead = TCL_IO_FAILURE;
	} else {
	    /*
	     * Process a regular result.
	     */

	    size_t bytec = 0;		/* Number of returned bytes */
	    Tcl_Size bytec = 0;		/* Number of returned bytes */
	    unsigned char *bytev;	/* Array of returned bytes */

	    bytev = TclGetByteArrayFromObj(resObj, &bytec);
	    bytev = Tcl_GetBytesFromObj(NULL, resObj, &bytec);

	    if (bytev == NULL) {
		ForwardSetStaticError(paramPtr, msg_read_nonbyte);
		paramPtr->input.toRead = -1;
	    if (paramPtr->input.toRead < bytec) {
	    } else if (paramPtr->input.toRead < bytec) {
		ForwardSetStaticError(paramPtr, msg_read_toomuch);
		paramPtr->input.toRead = TCL_IO_FAILURE;
	    } else {
		if (bytec + 1 > 1) {
		if (bytec > 0) {
		    memcpy(paramPtr->input.buf, bytev, bytec);
		}
		paramPtr->input.toRead = bytec;
	    }
	}
        Tcl_Release(rcPtr);
        Tcl_DecrRefCount(toReadObj);
	Tcl_Release(rcPtr);
	Tcl_DecrRefCount(toReadObj);
	break;
    }

    case ForwardedOutput: {
	Tcl_Obj *bufObj = Tcl_NewByteArrayObj((unsigned char *)
                paramPtr->output.buf, paramPtr->output.toWrite);
        Tcl_IncrRefCount(bufObj);
		paramPtr->output.buf, paramPtr->output.toWrite);
	Tcl_IncrRefCount(bufObj);

        Tcl_Preserve(rcPtr);
	Tcl_Preserve(rcPtr);
	if (InvokeTclMethod(rcPtr, METH_WRITE, bufObj, NULL, &resObj) != TCL_OK) {
	    int code = ErrnoReturn(rcPtr, resObj);

	    if (code < 0) {
		paramPtr->base.code = code;
	    } else {
		ForwardSetObjError(paramPtr, resObj);
3086
3087
3088
3089
3090
3091
3092
3093
3094


3095
3096
3097
3098
3099
3100
3101
3123
3124
3125
3126
3127
3128
3129


3130
3131
3132
3133
3134
3135
3136
3137
3138







-
-
+
+







	    } else if (written==0 || paramPtr->output.toWrite<written) {
		ForwardSetStaticError(paramPtr, msg_write_toomuch);
		paramPtr->output.toWrite = -1;
	    } else {
		paramPtr->output.toWrite = written;
	    }
	}
        Tcl_Release(rcPtr);
        Tcl_DecrRefCount(bufObj);
	Tcl_Release(rcPtr);
	Tcl_DecrRefCount(bufObj);
	break;
    }

    case ForwardedSeek: {
	Tcl_Obj *offObj;
	Tcl_Obj *baseObj;

3115
3116
3117
3118
3119
3120
3121
3122

3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138



3139
3140
3141
3142
3143
3144

3145
3146

3147
3148
3149
3150

3151
3152
3153
3154
3155
3156
3157
3158


3159
3160

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
3199
3200


3201
3202
3203
3204
3205
3206
3207
3208
3209

3210
3211
3212
3213
3214
3215
3216
3217
3218

3219
3220
3221
3222


3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233


3234
3235
3236
3237
3238

3239
3240
3241
3242
3243
3244
3245
3246
3247

3248













3249
3250
3251
3252
3253
3254
3255
3152
3153
3154
3155
3156
3157
3158

3159
3160
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
3199


3200
3201
3202
3203
3204
3205
3206
3207
3208



3209
3210
3211
3212

3213
3214
3215



3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228


3229
3230
3231
3232
3233
3234
3235


3236
3237
3238
3239
3240
3241
3242
3243
3244
3245

3246
3247
3248
3249
3250
3251
3252
3253
3254

3255
3256
3257


3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268


3269
3270
3271
3272
3273
3274

3275
3276
3277
3278
3279
3280
3281
3282
3283

3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305







-
+













-
-
-
+
+
+





-
+

-
+



-
+






-
-
+
+

-
+


-
-
+
+







-
-
-
+
+
+

-
+


-
-
-
+
+
+










-
-
+
+





-
-
+
+








-
+








-
+


-
-
+
+









-
-
+
+




-
+








-
+

+
+
+
+
+
+
+
+
+
+
+
+
+







	    /*
	     * Process a regular result. If the type is wrong this may change
	     * into an error.
	     */

	    Tcl_WideInt newLoc;

	    if (Tcl_GetWideIntFromObj(interp, resObj, &newLoc) == TCL_OK) {
	    if (TclGetWideIntFromObj(interp, resObj, &newLoc) == TCL_OK) {
		if (newLoc < 0) {
		    ForwardSetStaticError(paramPtr, msg_seek_beforestart);
		    paramPtr->seek.offset = -1;
		} else {
		    paramPtr->seek.offset = newLoc;
		}
	    } else {
		Tcl_DecrRefCount(resObj);
		resObj = MarshallError(interp);
		ForwardSetObjError(paramPtr, resObj);
		paramPtr->seek.offset = -1;
	    }
	}
        Tcl_Release(rcPtr);
        Tcl_DecrRefCount(offObj);
        Tcl_DecrRefCount(baseObj);
	Tcl_Release(rcPtr);
	Tcl_DecrRefCount(offObj);
	Tcl_DecrRefCount(baseObj);
	break;
    }

    case ForwardedWatch: {
	Tcl_Obj *maskObj = DecodeEventMask(paramPtr->watch.mask);
        /* assert maskObj.refCount == 1 */
	/* assert maskObj.refCount == 1 */

        Tcl_Preserve(rcPtr);
	Tcl_Preserve(rcPtr);
	rcPtr->interest = paramPtr->watch.mask;
	(void) InvokeTclMethod(rcPtr, METH_WATCH, maskObj, NULL, NULL);
	Tcl_DecrRefCount(maskObj);
        Tcl_Release(rcPtr);
	Tcl_Release(rcPtr);
	break;
    }

    case ForwardedBlock: {
	Tcl_Obj *blockObj = Tcl_NewBooleanObj(!paramPtr->block.nonblocking);

        Tcl_IncrRefCount(blockObj);
        Tcl_Preserve(rcPtr);
	Tcl_IncrRefCount(blockObj);
	Tcl_Preserve(rcPtr);
	if (InvokeTclMethod(rcPtr, METH_BLOCKING, blockObj, NULL,
                &resObj) != TCL_OK) {
		&resObj) != TCL_OK) {
	    ForwardSetObjError(paramPtr, resObj);
	}
        Tcl_Release(rcPtr);
        Tcl_DecrRefCount(blockObj);
	Tcl_Release(rcPtr);
	Tcl_DecrRefCount(blockObj);
	break;
    }

    case ForwardedSetOpt: {
	Tcl_Obj *optionObj = Tcl_NewStringObj(paramPtr->setOpt.name, -1);
	Tcl_Obj *valueObj  = Tcl_NewStringObj(paramPtr->setOpt.value, -1);

        Tcl_IncrRefCount(optionObj);
        Tcl_IncrRefCount(valueObj);
        Tcl_Preserve(rcPtr);
	Tcl_IncrRefCount(optionObj);
	Tcl_IncrRefCount(valueObj);
	Tcl_Preserve(rcPtr);
	if (InvokeTclMethod(rcPtr, METH_CONFIGURE, optionObj, valueObj,
                &resObj) != TCL_OK) {
		&resObj) != TCL_OK) {
	    ForwardSetObjError(paramPtr, resObj);
	}
        Tcl_Release(rcPtr);
        Tcl_DecrRefCount(optionObj);
        Tcl_DecrRefCount(valueObj);
	Tcl_Release(rcPtr);
	Tcl_DecrRefCount(optionObj);
	Tcl_DecrRefCount(valueObj);
	break;
    }

    case ForwardedGetOpt: {
	/*
	 * Retrieve the value of one option.
	 */

	Tcl_Obj *optionObj = Tcl_NewStringObj(paramPtr->getOpt.name, -1);

        Tcl_IncrRefCount(optionObj);
        Tcl_Preserve(rcPtr);
	Tcl_IncrRefCount(optionObj);
	Tcl_Preserve(rcPtr);
	if (InvokeTclMethod(rcPtr, METH_CGET, optionObj, NULL, &resObj)!=TCL_OK){
	    ForwardSetObjError(paramPtr, resObj);
	} else {
	    TclDStringAppendObj(paramPtr->getOpt.value, resObj);
	}
        Tcl_Release(rcPtr);
        Tcl_DecrRefCount(optionObj);
	Tcl_Release(rcPtr);
	Tcl_DecrRefCount(optionObj);
	break;
    }

    case ForwardedGetOptAll:
	/*
	 * Retrieve all options.
	 */

        Tcl_Preserve(rcPtr);
	Tcl_Preserve(rcPtr);
	if (InvokeTclMethod(rcPtr, METH_CGETALL, NULL, NULL, &resObj) != TCL_OK){
	    ForwardSetObjError(paramPtr, resObj);
	} else {
	    /*
	     * Extract list, validate that it is a list, and #elements. See
	     * NOTE (4) as well.
	     */

	    int listc;
	    Tcl_Size listc;
	    Tcl_Obj **listv;

	    if (Tcl_ListObjGetElements(interp, resObj, &listc,
                    &listv) != TCL_OK) {
	    if (TclListObjGetElements(interp, resObj, &listc,
		    &listv) != TCL_OK) {
		Tcl_DecrRefCount(resObj);
		resObj = MarshallError(interp);
		ForwardSetObjError(paramPtr, resObj);
	    } else if ((listc % 2) == 1) {
		/*
		 * Odd number of elements is wrong. [x].
		 */

		char *buf = (char *)Tcl_Alloc(200);
		sprintf(buf,
			"{Expected list with even number of elements, got %d %s instead}",
		snprintf(buf, 200,
			"{Expected list with even number of elements, got %" TCL_SIZE_MODIFIER "d %s instead}",
			listc, (listc == 1 ? "element" : "elements"));

		ForwardSetDynamicError(paramPtr, buf);
	    } else {
		size_t len;
		Tcl_Size len;
		const char *str = TclGetStringFromObj(resObj, &len);

		if (len) {
		    TclDStringAppendLiteral(paramPtr->getOpt.value, " ");
		    Tcl_DStringAppend(paramPtr->getOpt.value, str, len);
		}
	    }
	}
        Tcl_Release(rcPtr);
	Tcl_Release(rcPtr);
	break;

    case ForwardedTruncate: {
	Tcl_Obj *lenObj = Tcl_NewWideIntObj(paramPtr->truncate.length);

	Tcl_IncrRefCount(lenObj);
	Tcl_Preserve(rcPtr);
	if (InvokeTclMethod(rcPtr,METH_TRUNCATE,lenObj,NULL,&resObj)!=TCL_OK) {
	    ForwardSetObjError(paramPtr, resObj);
	}
	Tcl_Release(rcPtr);
	Tcl_DecrRefCount(lenObj);
	break;
    }

    default:
	/*
	 * Bad operation code.
	 */

	Tcl_Panic("Bad operation code in ForwardProc");
3279
3280
3281
3282
3283
3284
3285
3286

3287
3288
3289
3290
3291
3292
3293
3329
3330
3331
3332
3333
3334
3335

3336
3337
3338
3339
3340
3341
3342
3343







-
+







    }

    return 1;
}

static void
SrcExitProc(
    ClientData clientData)
    void *clientData)
{
    ForwardingEvent *evPtr = (ForwardingEvent *)clientData;
    ForwardingResult *resultPtr;
    ForwardParam *paramPtr;

    /*
     * NOTE (2): Can this handler be called with the originator blocked?
3330
3331
3332
3333
3334
3335
3336
3337

3338
3339
3340
3341
3342
3343
3344
3380
3381
3382
3383
3384
3385
3386

3387
3388
3389
3390
3391
3392
3393
3394







-
+







}

static void
ForwardSetObjError(
    ForwardParam *paramPtr,
    Tcl_Obj *obj)
{
    size_t len;
    Tcl_Size len;
    const char *msgStr = TclGetStringFromObj(obj, &len);

    len++;
    ForwardSetDynamicError(paramPtr, Tcl_Alloc(len));
    memcpy(paramPtr->base.msgStr, msgStr, len);
}
#endif

Changes to generic/tclIORTrans.c.

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
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
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
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












-
+




















-
+

-
+

-
+

-
-
-
-
-
+
+
+
+
+


-
+


-
-
-
+
+
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+










-
+






-
-
-
-
-
-
+
+
+
+
+
+







/*
 * tclIORTrans.c --
 *
 *	This file contains the implementation of Tcl's generic transformation
 *	reflection code, which allows the implementation of Tcl channel
 *	transformations in Tcl code.
 *
 *	Parts of this file are based on code contributed by Jean-Claude
 *	Wippler.
 *
 *	See TIP #230 for the specification of this functionality.
 *
 * Copyright (c) 2007-2008 ActiveState.
 * Copyright © 2007-2008 ActiveState.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclIO.h"
#include <assert.h>

#ifndef EINVAL
#define EINVAL	9
#endif
#ifndef EOK
#define EOK	0
#endif

/*
 * Signatures of all functions used in the C layer of the reflection.
 */

static int		ReflectClose(ClientData clientData,
static int		ReflectClose(void *clientData,
			    Tcl_Interp *interp, int flags);
static int		ReflectInput(ClientData clientData, char *buf,
static int		ReflectInput(void *clientData, char *buf,
			    int toRead, int *errorCodePtr);
static int		ReflectOutput(ClientData clientData, const char *buf,
static int		ReflectOutput(void *clientData, const char *buf,
			    int toWrite, int *errorCodePtr);
static void		ReflectWatch(ClientData clientData, int mask);
static int		ReflectBlock(ClientData clientData, int mode);
static Tcl_WideInt	ReflectSeekWide(ClientData clientData,
			    Tcl_WideInt offset, int mode, int *errorCodePtr);
static int		ReflectGetOption(ClientData clientData,
static void		ReflectWatch(void *clientData, int mask);
static int		ReflectBlock(void *clientData, int mode);
static long long	ReflectSeekWide(void *clientData,
			    long long offset, int mode, int *errorCodePtr);
static int		ReflectGetOption(void *clientData,
			    Tcl_Interp *interp, const char *optionName,
			    Tcl_DString *dsPtr);
static int		ReflectSetOption(ClientData clientData,
static int		ReflectSetOption(void *clientData,
			    Tcl_Interp *interp, const char *optionName,
			    const char *newValue);
static int		ReflectHandle(ClientData clientData, int direction,
			    ClientData *handle);
static int		ReflectNotify(ClientData clientData, int mask);
static int		ReflectHandle(void *clientData, int direction,
			    void **handle);
static int		ReflectNotify(void *clientData, int mask);

/*
 * The C layer channel type/driver definition used by the reflection.
 */

static const Tcl_ChannelType tclRTransformType = {
    "tclrtransform",		/* Type name. */
    TCL_CHANNEL_VERSION_5,	/* v5 channel. */
    NULL,		/* Close channel, clean instance data. */
    ReflectInput,		/* Handle read request. */
    ReflectOutput,		/* Handle write request. */
	NULL,			/* Move location of access point. */
    ReflectSetOption,		/* Set options. */
    ReflectGetOption,		/* Get options. */
    ReflectWatch,		/* Initialize notifier. */
    ReflectHandle,		/* Get OS handle from the channel. */
	ReflectClose,		/* No close2 support. NULL'able. */
    ReflectBlock,		/* Set blocking/nonblocking. */
    NULL,			/* Flush channel. Not used by core.
static const Tcl_ChannelType reflectedTransformType = {
    "tclrtransform",
    TCL_CHANNEL_VERSION_5,
    NULL,			/* Deprecated. */
    ReflectInput,
    ReflectOutput,
    NULL,			/* Deprecated. */
    ReflectSetOption,
    ReflectGetOption,
    ReflectWatch,
    ReflectHandle,
    ReflectClose,
    ReflectBlock,
    NULL,			/* Flush channel. Not used by core. */
				 * NULL'able. */
    ReflectNotify,		/* Handle events. */
    ReflectSeekWide,		/* Move access point (64 bit). */
    NULL,			/* thread action */
    NULL			/* truncate */
    ReflectNotify,
    ReflectSeekWide,
    NULL,			/* Thread action proc. */
    NULL			/* Truncate proc. */
};

/*
 * Structure of the buffer to hold transform results to be consumed by higher
 * layers upon reading from the channel, plus the functions to manage such.
 */

typedef struct {
    unsigned char *buf;		/* Reference to the buffer area. */
    size_t allocated;		/* Allocated size of the buffer area. */
    size_t used;			/* Number of bytes in the buffer,
    size_t used;		/* Number of bytes in the buffer,
				 * <= allocated. */
} ResultBuffer;

#define ResultLength(r) ((r)->used)
/* static int		ResultLength(ResultBuffer *r); */

static void		ResultClear(ResultBuffer *r);
static void		ResultInit(ResultBuffer *r);
static void		ResultAdd(ResultBuffer *r, unsigned char *buf,
			    int toWrite);
static int		ResultCopy(ResultBuffer *r, unsigned char *buf,
			    int toRead);
static inline void	ResultClear(ResultBuffer *r);
static inline void	ResultInit(ResultBuffer *r);
static inline void	ResultAdd(ResultBuffer *r, unsigned char *buf,
			    size_t toWrite);
static inline size_t	ResultCopy(ResultBuffer *r, unsigned char *buf,
			    size_t toRead);

#define RB_INCREMENT (512)

/*
 * Convenience macro to make some casts easier to use.
 */

208
209
210
211
212
213
214
215

216
217
218
219
220
221
222
207
208
209
210
211
212
213

214
215
216
217
218
219
220
221







-
+







#define REQUIRED_METHODS \
	(FLAG(METH_INIT) | FLAG(METH_FINAL))
#define RANDW \
	(TCL_READABLE | TCL_WRITABLE)

#define IMPLIES(a,b)	((!(a)) || (b))
#define NEGIMPL(a,b)
#define HAS(x,f)	(x & FLAG(f))
#define HAS(x,f)	((x) & FLAG(f))

#if TCL_THREADS
/*
 * Thread specific types and structures.
 *
 * We are here essentially creating a very specific implementation of 'thread
 * send'.
260
261
262
263
264
265
266
267

268
269
270
271
272
273
274
259
260
261
262
263
264
265

266
267
268
269
270
271
272
273







-
+







 * has no "subtype" and just uses ForwardParamBase, as listed above.)
 */

struct ForwardParamTransform {
    ForwardParamBase base;	/* "Supertype". MUST COME FIRST. */
    char *buf;			/* I: Bytes to transform,
				 * O: Bytes in transform result */
    size_t size;		/* I: #bytes to transform,
    Tcl_Size size;		/* I: #bytes to transform,
				 * O: #bytes in the transform result */
};
struct ForwardParamLimit {
    ForwardParamBase base;	/* "Supertype". MUST COME FIRST. */
    int max;			/* O: Character read limit */
};

351
352
353
354
355
356
357
358

359
360
361
362
363
364
365
350
351
352
353
354
355
356

357
358
359
360
361
362
363
364







-
+







 * thread involved in the forwarding exits. They also clean things up so that
 * we don't leak resources when threads go away.
 */

static void		ForwardOpToOwnerThread(ReflectedTransform *rtPtr,
			    ForwardedOperation op, const void *param);
static int		ForwardProc(Tcl_Event *evPtr, int mask);
static void		SrcExitProc(ClientData clientData);
static void		SrcExitProc(void *clientData);

#define FreeReceivedError(p) \
	do {								\
	    if ((p)->base.mustFree) {					\
		Tcl_Free((p)->base.msgStr);				\
	    }								\
	} while (0)
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
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







-
+


















-
+






-
+







	    (p)->base.msgStr = (char *) (emsg);				\
	} while (0)

static void		ForwardSetObjError(ForwardParam *p,
			    Tcl_Obj *objPtr);
static ReflectedTransformMap *	GetThreadReflectedTransformMap(void);
static void		DeleteThreadReflectedTransformMap(
			    ClientData clientData);
			    void *clientData);
#endif /* TCL_THREADS */

#define SetChannelErrorStr(c,msgStr) \
	Tcl_SetChannelError((c), Tcl_NewStringObj((msgStr), -1))

static Tcl_Obj *	MarshallError(Tcl_Interp *interp);
static void		UnmarshallErrorResult(Tcl_Interp *interp,
			    Tcl_Obj *msgObj);

/*
 * Static functions for this file:
 */

static Tcl_Obj *	DecodeEventMask(int mask);
static ReflectedTransform * NewReflectedTransform(Tcl_Interp *interp,
			    Tcl_Obj *cmdpfxObj, int mode, Tcl_Obj *handleObj,
			    Tcl_Channel parentChan);
static Tcl_Obj *	NextHandle(void);
static void		FreeReflectedTransform(ReflectedTransform *rtPtr);
static Tcl_FreeProc	FreeReflectedTransform;
static void		FreeReflectedTransformArgs(ReflectedTransform *rtPtr);
static int		InvokeTclMethod(ReflectedTransform *rtPtr,
			    const char *method, Tcl_Obj *argOneObj,
			    Tcl_Obj *argTwoObj, Tcl_Obj **resultObjPtr);

static ReflectedTransformMap *	GetReflectedTransformMap(Tcl_Interp *interp);
static void		DeleteReflectedTransformMap(ClientData clientData,
static void		DeleteReflectedTransformMap(void *clientData,
			    Tcl_Interp *interp);

/*
 * Global constant strings (messages). ==================
 * These string are used directly as bypass errors, thus they have to be valid
 * Tcl lists where the last element is the message itself. Hence the
 * list-quoting to keep the words of the message together. See also [x].
446
447
448
449
450
451
452
453

454
455
456
457
458
459
460
445
446
447
448
449
450
451

452
453
454
455
456
457
458
459







-
+







/*
 * Helper functions encapsulating some of the thread forwarding to make the
 * control flow in callers easier.
 */

static void		TimerKill(ReflectedTransform *rtPtr);
static void		TimerSetup(ReflectedTransform *rtPtr);
static void		TimerRun(ClientData clientData);
static void		TimerRun(void *clientData);
static int		TransformRead(ReflectedTransform *rtPtr,
			    int *errorCodePtr, Tcl_Obj *bufObj);
static int		TransformWrite(ReflectedTransform *rtPtr,
			    int *errorCodePtr, unsigned char *buf,
			    int toWrite);
static int		TransformDrain(ReflectedTransform *rtPtr,
			    int *errorCodePtr);
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
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







-
+















-
+


















-
-
-
+
+
+
+







 *	Creates a new channel.
 *
 *----------------------------------------------------------------------
 */

int
TclChanPushObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    ReflectedTransform *rtPtr;	/* Instance data of the new (transform)
				 * channel. */
    Tcl_Obj *chanObj;		/* Handle of parent channel */
    Tcl_Channel parentChan;	/* Token of parent channel */
    int mode;			/* R/W mode of parent, later the new channel.
				 * Has to match the abilities of the handler
				 * commands */
    Tcl_Obj *cmdObj;		/* Command prefix, list of words */
    Tcl_Obj *cmdNameObj;	/* Command name */
    Tcl_Obj *rtId;		/* Handle of the new transform (channel) */
    Tcl_Obj *modeObj;		/* mode in obj form for method call */
    int listc;			/* Result of 'initialize', and of */
    Tcl_Size listc;		/* Result of 'initialize', and of */
    Tcl_Obj **listv;		/* its sublist in the 2nd element */
    int methIndex;		/* Encoded method name */
    int result;			/* Result code for 'initialize' */
    Tcl_Obj *resObj;		/* Result data for 'initialize' */
    int methods;		/* Bitmask for supported methods. */
    ReflectedTransformMap *rtmPtr;
				/* Map of reflected transforms with handlers
				 * in this interp. */
    Tcl_HashEntry *hPtr;	/* Entry in the above map */
    int isNew;			/* Placeholder. */

    /*
     * Syntax:   chan push CHANNEL CMDPREFIX
     *           [0]  [1]  [2]     [3]
     *
     * Actually: rPush CHANNEL CMDPREFIX
     *           [0]   [1]     [2]
     */

#define CHAN	(1)
#define CMD	(2)
    enum ArgIndices {
	CHAN = 1,
	CMD = 2
    };

    /*
     * Number of arguments...
     */

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "channel cmdprefix");
595
596
597
598
599
600
601
602
603
604
605




606
607
608
609
610
611
612
595
596
597
598
599
600
601




602
603
604
605
606
607
608
609
610
611
612







-
-
-
-
+
+
+
+








    /*
     * Verify the result.
     * - List, of method names. Convert to mask. Check for non-optionals
     *   through the mask. Compare open mode against optional r/w.
     */

    if (Tcl_ListObjGetElements(NULL, resObj, &listc, &listv) != TCL_OK) {
        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "chan handler \"%s initialize\" returned non-list: %s",
                TclGetString(cmdObj), TclGetString(resObj)));
    if (TclListObjGetElements(NULL, resObj, &listc, &listv) != TCL_OK) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"chan handler \"%s initialize\" returned non-list: %s",
		TclGetString(cmdObj), TclGetString(resObj)));
	Tcl_DecrRefCount(resObj);
	goto error;
    }

    methods = 0;
    while (listc > 0) {
	if (Tcl_GetIndexFromObj(interp, listv[listc-1], methodNames,
621
622
623
624
625
626
627
628
629
630



631
632
633
634
635
636
637

638
639
640
641
642
643
644
645
646
647
648
649
650
651
652



653
654
655
656
657
658
659
660
661
662
663



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
621
622
623
624
625
626
627



628
629
630
631
632
633
634
635
636

637
638
639
640
641
642
643
644
645
646
647
648
649



650
651
652
653
654
655
656
657
658
659
660



661
662
663
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







-
-
-
+
+
+






-
+












-
-
-
+
+
+








-
-
-
+
+
+




-
-
-
+
+
+











-
+



-
+








	methods |= FLAG(methIndex);
	listc--;
    }
    Tcl_DecrRefCount(resObj);

    if ((REQUIRED_METHODS & methods) != REQUIRED_METHODS) {
        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "chan handler \"%s\" does not support all required methods",
                TclGetString(cmdObj)));
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"chan handler \"%s\" does not support all required methods",
		TclGetString(cmdObj)));
	goto error;
    }

    /*
     * Mode tell us what the parent channel supports. The methods tell us what
     * the handler supports. We remove the non-supported bits from the mode
     * and check that the channel is not completely inacessible. Afterward the
     * and check that the channel is not completely inaccessible. Afterward the
     * mode tells us which methods are still required, and these methods will
     * also be supported by the handler, by design of the check.
     */

    if (!HAS(methods, METH_READ)) {
	mode &= ~TCL_READABLE;
    }
    if (!HAS(methods, METH_WRITE)) {
	mode &= ~TCL_WRITABLE;
    }

    if (!mode) {
        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "chan handler \"%s\" makes the channel inaccessible",
                TclGetString(cmdObj)));
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"chan handler \"%s\" makes the channel inaccessible",
		TclGetString(cmdObj)));
	goto error;
    }

    /*
     * The mode and support for it is ok, now check the internal constraints.
     */

    if (!IMPLIES(HAS(methods, METH_DRAIN), HAS(methods, METH_READ))) {
        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "chan handler \"%s\" supports \"drain\" but not \"read\"",
                TclGetString(cmdObj)));
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"chan handler \"%s\" supports \"drain\" but not \"read\"",
		TclGetString(cmdObj)));
	goto error;
    }

    if (!IMPLIES(HAS(methods, METH_FLUSH), HAS(methods, METH_WRITE))) {
        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "chan handler \"%s\" supports \"flush\" but not \"write\"",
                TclGetString(cmdObj)));
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"chan handler \"%s\" supports \"flush\" but not \"write\"",
		TclGetString(cmdObj)));
	goto error;
    }

    Tcl_ResetResult(interp);

    /*
     * Everything is fine now.
     */

    rtPtr->methods = methods;
    rtPtr->mode = mode;
    rtPtr->chan = Tcl_StackChannel(interp, &tclRTransformType, rtPtr, mode,
    rtPtr->chan = Tcl_StackChannel(interp, &reflectedTransformType, rtPtr, mode,
	    rtPtr->parent);

    /*
     * Register the transform in our our map for proper handling of deleted
     * Register the transform in our map for proper handling of deleted
     * interpreters and/or threads.
     */

    rtmPtr = GetReflectedTransformMap(interp);
    hPtr = Tcl_CreateHashEntry(&rtmPtr->map, TclGetString(rtId), &isNew);
    if (!isNew && rtPtr != Tcl_GetHashValue(hPtr)) {
	Tcl_Panic("TclChanPushObjCmd: duplicate transformation handle");
709
710
711
712
713
714
715
716

717
718
719
720
721
722
723
724
725
726
727
709
710
711
712
713
714
715

716
717



718
719
720
721
722
723
724







-
+

-
-
-








  error:
    /*
     * We are not going through ReflectClose as we never had a channel
     * structure.
     */

    Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform);
    Tcl_EventuallyFree(rtPtr, FreeReflectedTransform);
    return TCL_ERROR;

#undef CHAN
#undef CMD
}

/*
 *----------------------------------------------------------------------
 *
 * TclChanPopObjCmd --
 *
736
737
738
739
740
741
742
743

744
745
746
747
748
749
750
751
752
753
754
755
756



757
758
759
760
761
762
763
733
734
735
736
737
738
739

740
741
742
743
744
745
746
747
748
749
750
751


752
753
754
755
756
757
758
759
760
761







-
+











-
-
+
+
+







 *	latter implies that arbitrary side effects are possible.
 *
 *----------------------------------------------------------------------
 */

int
TclChanPopObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    /*
     * Syntax:   chan pop CHANNEL
     *           [0]  [1] [2]
     *
     * Actually: rPop CHANNEL
     *           [0]  [1]
     */

#define CHAN	(1)
    enum ArgIndices {
	CHAN = 1
    };

    const char *chanId;		/* Tcl level channel handle */
    Tcl_Channel chan;		/* Channel associated to the handle */
    int mode;			/* Channel r/w mode */

    /*
     * Number of arguments...
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
781
782
783
784
785
786
787


788
789
790
791
792
793
794







-
-







    /*
     * Removing transformations is generic, and not restricted to reflected
     * transformations.
     */

    Tcl_UnstackChannel(interp, chan);
    return TCL_OK;

#undef CHAN
}

/*
 * Channel error message marshalling utilities.
 */

static Tcl_Obj *
816
817
818
819
820
821
822
823

824
825
826

827
828
829
830
831
832
833
834
835
836
837
838

839
840
841
842
843
844
845
812
813
814
815
816
817
818

819
820
821

822
823
824
825
826
827
828
829
830
831
832
833

834
835
836
837
838
839
840
841







-
+


-
+











-
+







}

static void
UnmarshallErrorResult(
    Tcl_Interp *interp,
    Tcl_Obj *msgObj)
{
    int lc;
    Tcl_Size lc;
    Tcl_Obj **lv;
    int explicitResult;
    int numOptions;
    Tcl_Size numOptions;

    /*
     * Process the caught message.
     *
     * Syntax = (option value)... ?message?
     *
     * Bad syntax causes a panic. This is OK because the other side uses
     * Tcl_GetReturnOptions and list construction functions to marshall the
     * information; if we panic here, something has gone badly wrong already.
     */

    if (Tcl_ListObjGetElements(interp, msgObj, &lc, &lv) != TCL_OK) {
    if (TclListObjGetElements(interp, msgObj, &lc, &lv) != TCL_OK) {
	Tcl_Panic("TclChanCaughtErrorBypass: Bad syntax of caught result");
    }
    if (interp == NULL) {
	return;
    }

    explicitResult = lc & 1;		/* Odd number of values? */
862
863
864
865
866
867
868
869

870
871
872
873
874
875
876
877
878
879

880
881
882
883
884
885
886
858
859
860
861
862
863
864

865
866
867
868
869
870
871
872
873
874

875
876
877
878
879
880
881
882







-
+









-
+







 *
 * ReflectClose --
 *
 *	This function is invoked when the channel is closed, to delete the
 *	driver specific instance data.
 *
 * Results:
 *	A posix error.
 *	A Posix error.
 *
 * Side effects:
 *	Releases memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectClose(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int flags)
{
    ReflectedTransform *rtPtr = (ReflectedTransform *)clientData;
    int errorCode, errorCodeSet = 0;
    int result = TCL_OK;	/* Result code for 'close' */
    Tcl_Obj *resObj;		/* Result data for 'close' */
919
920
921
922
923
924
925
926

927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943

944
945
946
947
948
949
950
951
952
953
954
955
956
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
915
916
917
918
919
920
921

922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938

939
940
941
942
943
944
945
946
947
948
949
950
951
952

953
954
955
956
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







-
+
















-
+













-
+



















-
+










-
+








	    if (result != TCL_OK) {
		FreeReceivedError(&p);
	    }
	}
#endif /* TCL_THREADS */

	Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform);
	Tcl_EventuallyFree(rtPtr, FreeReflectedTransform);
	return EOK;
    }

    /*
     * In the reflected channel implementation a cleaned method mask here
     * implies that the channel creation was aborted, and "finalize" must not
     * be called. for transformations however we are not going through here on
     * such an abort, but directly through FreeReflectedTransform. So for us
     * that check is not necessary. We always go through 'finalize'.
     */

    if (HAS(rtPtr->methods, METH_DRAIN) && !rtPtr->readIsDrained) {
	if (!TransformDrain(rtPtr, &errorCode)) {
#if TCL_THREADS
	    if (rtPtr->thread != Tcl_GetCurrentThread()) {
		Tcl_EventuallyFree(rtPtr,
			(Tcl_FreeProc *) FreeReflectedTransform);
			FreeReflectedTransform);
		return errorCode;
	    }
#endif /* TCL_THREADS */
	    errorCodeSet = 1;
	    goto cleanup;
	}
    }

    if (HAS(rtPtr->methods, METH_FLUSH)) {
	if (!TransformFlush(rtPtr, &errorCode, FLUSH_WRITE)) {
#if TCL_THREADS
	    if (rtPtr->thread != Tcl_GetCurrentThread()) {
		Tcl_EventuallyFree(rtPtr,
			(Tcl_FreeProc *) FreeReflectedTransform);
			FreeReflectedTransform);
		return errorCode;
	    }
#endif /* TCL_THREADS */
	    errorCodeSet = 1;
	    goto cleanup;
	}
    }

    /*
     * Are we in the correct thread?
     */

#if TCL_THREADS
    if (rtPtr->thread != Tcl_GetCurrentThread()) {
	ForwardParam p;

	ForwardOpToOwnerThread(rtPtr, ForwardedClose, &p);
	result = p.base.code;

	Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform);
	Tcl_EventuallyFree(rtPtr, FreeReflectedTransform);

	if (result != TCL_OK) {
	    PassReceivedErrorInterp(interp, &p);
	    return EINVAL;
	}
	return EOK;
    }
#endif /* TCL_THREADS */

    /*
     * Do the actual invokation of "finalize" now; we're in the right thread.
     * Do the actual invocation of "finalize" now; we're in the right thread.
     */

    result = InvokeTclMethod(rtPtr, "finalize", NULL, NULL, &resObj);
    if ((result != TCL_OK) && (interp != NULL)) {
	Tcl_SetChannelErrorInterp(interp, resObj);
    }

1029
1030
1031
1032
1033
1034
1035
1036

1037
1038
1039
1040
1041
1042
1043
1025
1026
1027
1028
1029
1030
1031

1032
1033
1034
1035
1036
1037
1038
1039







-
+







	hPtr = Tcl_FindHashEntry(&rtmPtr->map, TclGetString(rtPtr->handle));
	if (hPtr) {
	    Tcl_DeleteHashEntry(hPtr);
	}
#endif /* TCL_THREADS */
    }

    Tcl_EventuallyFree (rtPtr, (Tcl_FreeProc *) FreeReflectedTransform);
    Tcl_EventuallyFree(rtPtr, FreeReflectedTransform);
    return errorCodeSet ? errorCode : ((result == TCL_OK) ? EOK : EINVAL);
}

/*
 *----------------------------------------------------------------------
 *
 * ReflectInput --
1051
1052
1053
1054
1055
1056
1057
1058

1059
1060
1061
1062
1063
1064
1065
1047
1048
1049
1050
1051
1052
1053

1054
1055
1056
1057
1058
1059
1060
1061







-
+







 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectInput(
    ClientData clientData,
    void *clientData,
    char *buf,
    int toRead,
    int *errorCodePtr)
{
    ReflectedTransform *rtPtr = (ReflectedTransform *)clientData;
    int gotBytes, copied, readBytes;
    Tcl_Obj *bufObj;
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1097
1098
1099
1100
1101
1102
1103

1104
1105
1106
1107
1108
1109
1110







-







	    goto stop;
	}

	if (rtPtr->eofPending) {
	    goto stop;
	}


	/*
	 * The buffer is exhausted, but the caller wants even more. We now
	 * have to go to the underlying channel, get more bytes and then
	 * transform them for delivery. We may not get what we want (full EOF
	 * or temporarily out of data).
	 *
	 * Length (rtPtr->result) == 0, toRead > 0 here. Use 'buf'! as target
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1131
1132
1133
1134
1135
1136
1137

1138
1139
1140
1141
1142
1143
1144







-







		}
	    } /* else: 'maxRead < 0' == Accept the current value of toRead */
	}

	if (toRead <= 0) {
	    goto stop;
	}


	readBytes = Tcl_ReadRaw(rtPtr->parent,
		(char *) Tcl_SetByteArrayLength(bufObj, toRead), toRead);
	if (readBytes < 0) {
	    if (Tcl_InputBlocked(rtPtr->parent) && (gotBytes > 0)) {

		/*
1244
1245
1246
1247
1248
1249
1250
1251

1252
1253
1254
1255
1256
1257
1258
1238
1239
1240
1241
1242
1243
1244

1245
1246
1247
1248
1249
1250
1251
1252







-
+







 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectOutput(
    ClientData clientData,
    void *clientData,
    const char *buf,
    int toWrite,
    int *errorCodePtr)
{
    ReflectedTransform *rtPtr = (ReflectedTransform *)clientData;

    /*
1315
1316
1317
1318
1319
1320
1321
1322

1323
1324
1325


1326
1327
1328
1329
1330
1331
1332
1309
1310
1311
1312
1313
1314
1315

1316
1317


1318
1319
1320
1321
1322
1323
1324
1325
1326







-
+

-
-
+
+







 * Side effects:
 *	Allocates memory. Arbitrary, per the parent channel, and the called
 *	scripts.
 *
 *----------------------------------------------------------------------
 */

static Tcl_WideInt
static long long
ReflectSeekWide(
    ClientData clientData,
    Tcl_WideInt offset,
    void *clientData,
    long long offset,
    int seekMode,
    int *errorCodePtr)
{
    ReflectedTransform *rtPtr = (ReflectedTransform *)clientData;
    Channel *parent = (Channel *) rtPtr->parent;
    Tcl_WideInt curPos;		/* Position on the device. */

1373
1374
1375
1376
1377
1378
1379
1380
1381


1382
1383
1384
1385
1386
1387
1388
1367
1368
1369
1370
1371
1372
1373


1374
1375
1376
1377
1378
1379
1380
1381
1382







-
-
+
+







     * non-NULL...
     */

    if (Tcl_ChannelWideSeekProc(parent->typePtr) == NULL) {
	*errorCodePtr = EINVAL;
	curPos = -1;
    } else {
    	curPos = Tcl_ChannelWideSeekProc(parent->typePtr)(parent->instanceData, offset,
    		seekMode, errorCodePtr);
	curPos = Tcl_ChannelWideSeekProc(parent->typePtr)(parent->instanceData, offset,
		seekMode, errorCodePtr);
    }
    if (curPos == -1) {
	Tcl_SetErrno(*errorCodePtr);
    }

    *errorCodePtr = EOK;
    Tcl_Release(rtPtr);
1404
1405
1406
1407
1408
1409
1410
1411

1412
1413
1414
1415
1416
1417
1418
1398
1399
1400
1401
1402
1403
1404

1405
1406
1407
1408
1409
1410
1411
1412







-
+







 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static void
ReflectWatch(
    ClientData clientData,
    void *clientData,
    int mask)
{
    ReflectedTransform *rtPtr = (ReflectedTransform *)clientData;
    Tcl_DriverWatchProc *watchProc;

    watchProc = Tcl_ChannelWatchProc(Tcl_GetChannelType(rtPtr->parent));
    watchProc(Tcl_GetChannelInstanceData(rtPtr->parent), mask);
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
1439
1440
1441
1442
1443
1444
1445

1446
1447
1448
1449
1450
1451
1452
1453
1454
1455

1456
1457
1458
1459
1460
1461
1462
1463







-
+









-
+







 *
 * ReflectBlock --
 *
 *	This function is invoked to tell the channel which blocking behaviour
 *	is required of it.
 *
 * Results:
 *	A posix error number.
 *	A Posix error number.
 *
 * Side effects:
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectBlock(
    ClientData clientData,
    void *clientData,
    int nonblocking)
{
    ReflectedTransform *rtPtr = (ReflectedTransform *)clientData;

    /*
     * Transformations simply record the blocking mode in their C level
     * structure for use by --> ReflectInput. The Tcl level doesn't see this
1488
1489
1490
1491
1492
1493
1494
1495

1496
1497
1498
1499
1500
1501
1502
1482
1483
1484
1485
1486
1487
1488

1489
1490
1491
1492
1493
1494
1495
1496







-
+







 *	Arbitrary, per the parent channel.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectSetOption(
    ClientData clientData,	/* Channel to query */
    void *clientData,		/* Channel to query */
    Tcl_Interp *interp,		/* Interpreter to leave error messages in */
    const char *optionName,	/* Name of requested option */
    const char *newValue)	/* The new value */
{
    ReflectedTransform *rtPtr = (ReflectedTransform *)clientData;

    /*
1530
1531
1532
1533
1534
1535
1536
1537

1538
1539

1540
1541
1542
1543
1544
1545
1546
1524
1525
1526
1527
1528
1529
1530

1531
1532

1533
1534
1535
1536
1537
1538
1539
1540







-
+

-
+







 *	Arbitrary, per the parent channel.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectGetOption(
    ClientData clientData,	/* Channel to query */
    void *clientData,		/* Channel to query */
    Tcl_Interp *interp,		/* Interpreter to leave error messages in */
    const char *optionName,	/* Name of reuqested option */
    const char *optionName,	/* Name of requested option */
    Tcl_DString *dsPtr)		/* String to place the result into */
{
    ReflectedTransform *rtPtr = (ReflectedTransform *)clientData;

    /*
     * Transformations have no options. Thus the call is passed down unchanged
     * to the parent channel for processing. Its results are passed back
1579
1580
1581
1582
1583
1584
1585
1586

1587
1588

1589
1590
1591
1592
1593
1594

1595
1596
1597
1598
1599
1600
1601
1573
1574
1575
1576
1577
1578
1579

1580
1581

1582
1583
1584
1585
1586
1587

1588
1589
1590
1591
1592
1593
1594
1595







-
+

-
+





-
+







 *	Arbitrary, per the parent channel.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectHandle(
    ClientData clientData,
    void *clientData,
    int direction,
    ClientData *handlePtr)
    void **handlePtr)
{
    ReflectedTransform *rtPtr = (ReflectedTransform *)clientData;

    /*
     * Transformations have no handle of their own. As such we simply query
     * the parent channel for it. This way the qery will ripple down through
     * the parent channel for it. This way the query will ripple down through
     * all transformations until reaches the base channel. Which then returns
     * its handle, or fails. The former will then ripple up the stack.
     *
     * This all happens in the thread we are in. As the Tcl level is not
     * involved no forwarding is required.
     */

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
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







-
+





-
+



















-







 *	Arbitrary, per the parent channel.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectNotify(
    ClientData clientData,
    void *clientData,
    int mask)
{
    ReflectedTransform *rtPtr = (ReflectedTransform *)clientData;

    /*
     * An event occured in the underlying channel.
     * An event occurred in the underlying channel.
     *
     * We delete our timer. It was not fired, yet we are here, so the channel
     * below generated such an event and we don't have to. The renewal of the
     * interest after the execution of channel handlers will eventually cause
     * us to recreate the timer (in ReflectWatch).
     */

    TimerKill(rtPtr);

    /*
     * Pass to higher layers.
     */

    return mask;
}

/*
 * Helpers. =========================================================
 */


/*
 *----------------------------------------------------------------------
 *
 * DecodeEventMask --
 *
 *	This function takes an internal bitmask of events and constructs the
1715
1716
1717
1718
1719
1720
1721
1722

1723
1724
1725
1726
1727
1728
1729
1730
1731
1708
1709
1710
1711
1712
1713
1714

1715
1716

1717
1718
1719
1720
1721
1722
1723







-
+

-







    Tcl_Interp *interp,
    Tcl_Obj *cmdpfxObj,
    TCL_UNUSED(int) /*mode*/,
    Tcl_Obj *handleObj,
    Tcl_Channel parentChan)
{
    ReflectedTransform *rtPtr;
    int listc;
    Tcl_Size i, listc;
    Tcl_Obj **listv;
    int i;

    rtPtr = (ReflectedTransform *)Tcl_Alloc(sizeof(ReflectedTransform));

    /* rtPtr->chan: Assigned by caller. Dummy data here. */
    /* rtPtr->methods: Assigned by caller. Dummy data here. */

    rtPtr->chan = NULL;
1753
1754
1755
1756
1757
1758
1759
1760

1761
1762
1763
1764
1765
1766
1767
1745
1746
1747
1748
1749
1750
1751

1752
1753
1754
1755
1756
1757
1758
1759







-
+








    /*
     * Method placeholder.
     */

    /* ASSERT: cmdpfxObj is a Tcl List */

    Tcl_ListObjGetElements(interp, cmdpfxObj, &listc, &listv);
    TclListObjGetElements(interp, cmdpfxObj, &listc, &listv);

    /*
     * See [==] as well.
     * Storage for the command prefix and the additional words required for
     * the invocation of methods in the command handler.
     *
     * listv [0] [listc-1] | [listc]  [listc+1] |
1867
1868
1869
1870
1871
1872
1873
1874

1875

1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891

1892
1893
1894
1895
1896
1897
1898
1859
1860
1861
1862
1863
1864
1865

1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883

1884
1885
1886
1887
1888
1889
1890
1891







-
+

+















-
+







    Tcl_DecrRefCount(rtPtr->argv[n+1]);

    rtPtr->argc = 1;
}

static void
FreeReflectedTransform(
    ReflectedTransform *rtPtr)
    void *blockPtr)
{
    ReflectedTransform *rtPtr = (ReflectedTransform *) blockPtr;
    TimerKill(rtPtr);
    ResultClear(&rtPtr->result);

    FreeReflectedTransformArgs(rtPtr);

    Tcl_Free(rtPtr->argv);
    Tcl_Free(rtPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * InvokeTclMethod --
 *
 *	This function is used to invoke the Tcl level of a reflected channel.
 *	It handles all the command assembly, invokation, and generic state and
 *	It handles all the command assembly, invocation, and generic state and
 *	result mgmt. It does *not* handle thread redirection; that is the
 *	responsibility of clients of this function.
 *
 * Results:
 *	Result code and data as returned by the method.
 *
 * Side effects:
1916
1917
1918
1919
1920
1921
1922
1923
1924


1925
1926
1927
1928
1929
1930
1931
1909
1910
1911
1912
1913
1914
1915


1916
1917
1918
1919
1920
1921
1922
1923
1924







-
-
+
+







    Tcl_Obj *argOneObj,		/* NULL'able */
    Tcl_Obj *argTwoObj,		/* NULL'able */
    Tcl_Obj **resultObjPtr)	/* NULL'able */
{
    int cmdc;			/* #words in constructed command */
    Tcl_Obj *methObj = NULL;	/* Method name in object form */
    Tcl_InterpState sr;		/* State of handler interp */
    int result;			/* Result code of method invokation */
    Tcl_Obj *resObj = NULL;	/* Result of method invokation. */
    int result;			/* Result code of method invocation */
    Tcl_Obj *resObj = NULL;	/* Result of method invocation. */

    if (rtPtr->dead) {
	/*
	 * The transform is marked as dead. Bail out immediately, with an
	 * appropriate error.
	 */

1941
1942
1943
1944
1945
1946
1947
1948

1949
1950
1951
1952
1953
1954
1955
1934
1935
1936
1937
1938
1939
1940

1941
1942
1943
1944
1945
1946
1947
1948







-
+







     * NOTE (5): Decide impl. issue: Cache objects with method names?
     * Requires TSD data as reflections can be created in many different
     * threads.
     * NO: Caching of command resolutions means storage per channel.
     */

    /*
     * Insert method into the pre-allocated area, after the command prefix,
     * Insert method into the preallocated area, after the command prefix,
     * before the channel id.
     */

    methObj = Tcl_NewStringObj(method, -1);
    Tcl_IncrRefCount(methObj);
    rtPtr->argv[rtPtr->argc - 2] = methObj;

1968
1969
1970
1971
1972
1973
1974
1975

1976
1977
1978
1979
1980
1981
1982
1961
1962
1963
1964
1965
1966
1967

1968
1969
1970
1971
1972
1973
1974
1975







-
+







	if (argTwoObj) {
	    rtPtr->argv[cmdc] = argTwoObj;
	    cmdc++;
	}
    }

    /*
     * And run the handler... This is done in auch a manner which leaves any
     * And run the handler... This is done in a manner which leaves any
     * existing state intact.
     */

    sr = Tcl_SaveInterpState(rtPtr->interp, 0 /* Dummy */);
    Tcl_Preserve(rtPtr);
    Tcl_Preserve(rtPtr->interp);
    result = Tcl_EvalObjv(rtPtr->interp, cmdc, rtPtr->argv, TCL_EVAL_GLOBAL);
2001
2002
2003
2004
2005
2006
2007
2008

2009
2010
2011
2012
2013
2014
2015
1994
1995
1996
1997
1998
1999
2000

2001
2002
2003
2004
2005
2006
2007
2008







-
+







	     * the full state of the result, including additional options.
	     *
	     * This is complex and ugly, and would be completely unnecessary
	     * if we only added support for a TCL_FORBID_EXCEPTIONS flag.
	     */
	    if (result != TCL_ERROR) {
		Tcl_Obj *cmd = Tcl_NewListObj(cmdc, rtPtr->argv);
		size_t cmdLen;
		Tcl_Size cmdLen;
		const char *cmdString = TclGetStringFromObj(cmd, &cmdLen);

		Tcl_IncrRefCount(cmd);
		Tcl_ResetResult(rtPtr->interp);
		Tcl_SetObjResult(rtPtr->interp, Tcl_ObjPrintf(
			"chan handler returned bad code: %d", result));
		Tcl_LogCommandInfo(rtPtr->interp, cmdString, cmdString, cmdLen);
2071
2072
2073
2074
2075
2076
2077
2078


2079
2080
2081
2082
2083
2084
2085
2064
2065
2066
2067
2068
2069
2070

2071
2072
2073
2074
2075
2076
2077
2078
2079







-
+
+







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

static ReflectedTransformMap *
GetReflectedTransformMap(
    Tcl_Interp *interp)
{
    ReflectedTransformMap *rtmPtr = (ReflectedTransformMap *)Tcl_GetAssocData(interp, RTMKEY, NULL);
    ReflectedTransformMap *rtmPtr = (ReflectedTransformMap *)
	    Tcl_GetAssocData(interp, RTMKEY, NULL);

    if (rtmPtr == NULL) {
	rtmPtr = (ReflectedTransformMap *)Tcl_Alloc(sizeof(ReflectedTransformMap));
	Tcl_InitHashTable(&rtmPtr->map, TCL_STRING_KEYS);
	Tcl_SetAssocData(interp, RTMKEY,
		(Tcl_InterpDeleteProc *) DeleteReflectedTransformMap, rtmPtr);
    }
2104
2105
2106
2107
2108
2109
2110
2111

2112
2113
2114
2115
2116
2117
2118
2119
2120
2121


2122
2123
2124
2125
2126
2127
2128
2098
2099
2100
2101
2102
2103
2104

2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124







-
+










+
+







 *	registered in this interpreter.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteReflectedTransformMap(
    ClientData clientData,	/* The per-interpreter data structure. */
    void *clientData,		/* The per-interpreter data structure. */
    Tcl_Interp *interp)		/* The interpreter being deleted. */
{
    ReflectedTransformMap *rtmPtr; /* The map */
    Tcl_HashSearch hSearch;	 /* Search variable. */
    Tcl_HashEntry *hPtr;	 /* Search variable. */
    ReflectedTransform *rtPtr;
#if TCL_THREADS
    ForwardingResult *resultPtr;
    ForwardingEvent *evPtr;
    ForwardParam *paramPtr;
#else
    (void)interp;
#endif /* TCL_THREADS */

    /*
     * Delete all entries. The channels may have been closed already, or will
     * be closed later, by the standard IO finalization of an interpreter
     * under destruction. Except for the channels which were moved to a
     * different interpreter and/or thread. They do not exist from the IO
2237
2238
2239
2240
2241
2242
2243
2244


2245
2246
2247
2248
2249
2250
2251
2233
2234
2235
2236
2237
2238
2239

2240
2241
2242
2243
2244
2245
2246
2247
2248







-
+
+








static ReflectedTransformMap *
GetThreadReflectedTransformMap(void)
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (!tsdPtr->rtmPtr) {
	tsdPtr->rtmPtr = (ReflectedTransformMap *)Tcl_Alloc(sizeof(ReflectedTransformMap));
	tsdPtr->rtmPtr = (ReflectedTransformMap *)
		Tcl_Alloc(sizeof(ReflectedTransformMap));
	Tcl_InitHashTable(&tsdPtr->rtmPtr->map, TCL_STRING_KEYS);
	Tcl_CreateThreadExitHandler(DeleteThreadReflectedTransformMap, NULL);
    }

    return tsdPtr->rtmPtr;
}

2265
2266
2267
2268
2269
2270
2271
2272

2273
2274
2275
2276
2277
2278
2279
2262
2263
2264
2265
2266
2267
2268

2269
2270
2271
2272
2273
2274
2275
2276







-
+







 *	Deletes the hash table of channels.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteThreadReflectedTransformMap(
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    Tcl_HashSearch hSearch;	 /* Search variable. */
    Tcl_HashEntry *hPtr;	 /* Search variable. */
    Tcl_ThreadId self = Tcl_GetCurrentThread();
    ReflectedTransformMap *rtmPtr; /* The map */
    ForwardingResult *resultPtr;

2409
2410
2411
2412
2413
2414
2415
2416
2417


2418
2419
2420
2421
2422
2423
2424
2406
2407
2408
2409
2410
2411
2412


2413
2414
2415
2416
2417
2418
2419
2420
2421







-
-
+
+








    Tcl_CreateThreadExitHandler(SrcExitProc, evPtr);

    /*
     * Queue the event and poke the other thread's notifier.
     */

    Tcl_ThreadQueueEvent(dst, (Tcl_Event *) evPtr, TCL_QUEUE_TAIL);
    Tcl_ThreadAlert(dst);
    Tcl_ThreadQueueEvent(dst, (Tcl_Event *) evPtr,
	    TCL_QUEUE_TAIL|TCL_QUEUE_ALERT_IF_EMPTY);

    /*
     * (*) Block until the other thread has either processed the transfer or
     * rejected it.
     */

    while (resultPtr->result < 0) {
2469
2470
2471
2472
2473
2474
2475
2476

2477
2478
2479
2480
2481
2482
2483
2466
2467
2468
2469
2470
2471
2472

2473
2474
2475
2476
2477
2478
2479
2480







-
+







     * Notes regarding access to the referenced data.
     *
     * In principle the data belongs to the originating thread (see
     * evPtr->src), however this thread is currently blocked at (*), i.e.
     * quiescent. Because of this we can treat the data as belonging to us,
     * without fear of race conditions. I.e. we can read and write as we like.
     *
     * The only thing we cannot be sure of is the resultPtr. This can be be
     * The only thing we cannot be sure of is the resultPtr. This can be
     * NULLed if the originating thread went away while the event is handled
     * here now.
     */

    ForwardingEvent *evPtr = (ForwardingEvent *) evGPtr;
    ForwardingResult *resultPtr = evPtr->resultPtr;
    ReflectedTransform *rtPtr = evPtr->rtPtr;
2557
2558
2559
2560
2561
2562
2563
2564

2565
2566
2567
2568

2569
2570
2571
2572
2573
2574
2575
2554
2555
2556
2557
2558
2559
2560

2561
2562
2563
2564

2565
2566
2567
2568
2569
2570
2571
2572







-
+



-
+







	    paramPtr->transform.size = TCL_INDEX_NONE;
	} else {
	    /*
	     * Process a regular return. Contains the transformation result.
	     * Sent it back to the request originator.
	     */

	    size_t bytec = 0;	/* Number of returned bytes */
	    Tcl_Size bytec = 0;	/* Number of returned bytes */
	    unsigned char *bytev;
				/* Array of returned bytes */

	    bytev = TclGetByteArrayFromObj(resObj, &bytec);
	    bytev = Tcl_GetBytesFromObj(NULL, resObj, &bytec);

	    paramPtr->transform.size = bytec;

	    if (bytec > 0) {
		paramPtr->transform.buf = (char *)Tcl_Alloc(bytec);
		memcpy(paramPtr->transform.buf, bytev, bytec);
	    } else {
2591
2592
2593
2594
2595
2596
2597
2598

2599
2600
2601
2602

2603
2604
2605
2606
2607
2608
2609
2588
2589
2590
2591
2592
2593
2594

2595
2596
2597
2598

2599
2600
2601
2602
2603
2604
2605
2606







-
+



-
+







	    paramPtr->transform.size = TCL_INDEX_NONE;
	} else {
	    /*
	     * Process a regular return. Contains the transformation result.
	     * Sent it back to the request originator.
	     */

	    size_t bytec = 0;	/* Number of returned bytes */
	    Tcl_Size bytec = 0;	/* Number of returned bytes */
	    unsigned char *bytev;
				/* Array of returned bytes */

	    bytev = TclGetByteArrayFromObj(resObj, &bytec);
	    bytev = Tcl_GetBytesFromObj(NULL, resObj, &bytec);

	    paramPtr->transform.size = bytec;

	    if (bytec > 0) {
		paramPtr->transform.buf = (char *)Tcl_Alloc(bytec);
		memcpy(paramPtr->transform.buf, bytev, bytec);
	    } else {
2621
2622
2623
2624
2625
2626
2627
2628

2629
2630
2631

2632
2633
2634
2635
2636
2637
2638
2618
2619
2620
2621
2622
2623
2624

2625
2626
2627

2628
2629
2630
2631
2632
2633
2634
2635







-
+


-
+







	    paramPtr->transform.size = TCL_INDEX_NONE;
	} else {
	    /*
	     * Process a regular return. Contains the transformation result.
	     * Sent it back to the request originator.
	     */

	    size_t bytec = 0;	/* Number of returned bytes */
	    Tcl_Size bytec = 0;	/* Number of returned bytes */
	    unsigned char *bytev; /* Array of returned bytes */

	    bytev = TclGetByteArrayFromObj(resObj, &bytec);
	    bytev = Tcl_GetBytesFromObj(NULL, resObj, &bytec);

	    paramPtr->transform.size = bytec;

	    if (bytec > 0) {
		paramPtr->transform.buf = (char *)Tcl_Alloc(bytec);
		memcpy(paramPtr->transform.buf, bytev, bytec);
	    } else {
2647
2648
2649
2650
2651
2652
2653
2654

2655
2656
2657
2658

2659
2660
2661
2662
2663
2664
2665
2644
2645
2646
2647
2648
2649
2650

2651
2652
2653
2654

2655
2656
2657
2658
2659
2660
2661
2662







-
+



-
+







	    paramPtr->transform.size = TCL_INDEX_NONE;
	} else {
	    /*
	     * Process a regular return. Contains the transformation result.
	     * Sent it back to the request originator.
	     */

	    size_t bytec = 0;	/* Number of returned bytes */
	    Tcl_Size bytec = 0;	/* Number of returned bytes */
	    unsigned char *bytev;
				/* Array of returned bytes */

	    bytev = TclGetByteArrayFromObj(resObj, &bytec);
	    bytev = Tcl_GetBytesFromObj(NULL, resObj, &bytec);

	    paramPtr->transform.size = bytec;

	    if (bytec > 0) {
		paramPtr->transform.buf = (char *)Tcl_Alloc(bytec);
		memcpy(paramPtr->transform.buf, bytev, bytec);
	    } else {
2714
2715
2716
2717
2718
2719
2720
2721

2722
2723
2724
2725
2726
2727
2728
2711
2712
2713
2714
2715
2716
2717

2718
2719
2720
2721
2722
2723
2724
2725







-
+







    }

    return 1;
}

static void
SrcExitProc(
    ClientData clientData)
    void *clientData)
{
    ForwardingEvent *evPtr = (ForwardingEvent *)clientData;
    ForwardingResult *resultPtr;
    ForwardParam *paramPtr;

    /*
     * NOTE (2): Can this handler be called with the originator blocked?
2765
2766
2767
2768
2769
2770
2771
2772

2773
2774
2775
2776
2777
2778
2779
2762
2763
2764
2765
2766
2767
2768

2769
2770
2771
2772
2773
2774
2775
2776







-
+







}

static void
ForwardSetObjError(
    ForwardParam *paramPtr,
    Tcl_Obj *obj)
{
    size_t len;
    Tcl_Size len;
    const char *msgStr = TclGetStringFromObj(obj, &len);

    len++;
    ForwardSetDynamicError(paramPtr, Tcl_Alloc(len));
    memcpy(paramPtr->base.msgStr, msgStr, len);
}
#endif /* TCL_THREADS */
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
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







-
+













-
+










-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TimerRun(
    ClientData clientData)
    void *clientData)
{
    ReflectedTransform *rtPtr = (ReflectedTransform *)clientData;

    rtPtr->timer = NULL;
    Tcl_NotifyChannel(rtPtr->chan, TCL_READABLE);
}

/*
 *----------------------------------------------------------------------
 *
 * ResultInit --
 *
 *	Initializes the specified buffer structure. The structure will contain
 *	valid information for an emtpy buffer.
 *	valid information for an empty buffer.
 *
 * Side effects:
 *	See above.
 *
 * Result:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
static inline void
ResultInit(
    ResultBuffer *rPtr)		/* Reference to the structure to
				 * initialize. */
{
    rPtr->used = 0;
    rPtr->allocated = 0;
    rPtr->buf = NULL;
2904
2905
2906
2907
2908
2909
2910
2911

2912
2913
2914
2915
2916
2917
2918
2901
2902
2903
2904
2905
2906
2907

2908
2909
2910
2911
2912
2913
2914
2915







-
+







 *
 * Result:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
static inline void
ResultClear(
    ResultBuffer *rPtr)		/* Reference to the buffer to clear out */
{
    rPtr->used = 0;

    if (!rPtr->allocated) {
	return;
2935
2936
2937
2938
2939
2940
2941
2942

2943
2944
2945
2946

2947
2948
2949
2950
2951
2952
2953
2932
2933
2934
2935
2936
2937
2938

2939
2940
2941
2942

2943
2944
2945
2946
2947
2948
2949
2950







-
+



-
+







 *
 * Result:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
static inline void
ResultAdd(
    ResultBuffer *rPtr,		/* The buffer to extend */
    unsigned char *buf,		/* The buffer to read from */
    int toWrite)		/* The number of bytes in 'buf' */
    size_t toWrite)		/* The number of bytes in 'buf' */
{
    if ((rPtr->used + toWrite + 1) > rPtr->allocated) {
	/*
	 * Extension of the internal buffer is required.
	 * NOTE: Currently linear. Should be doubling to amortize.
	 */

2983
2984
2985
2986
2987
2988
2989
2990

2991
2992
2993
2994

2995
2996
2997
2998
2999
3000
3001
2980
2981
2982
2983
2984
2985
2986

2987
2988
2989
2990

2991
2992
2993
2994
2995
2996
2997
2998







-
+



-
+







 *
 * Result:
 *	The number of actually copied bytes, possibly less than 'toRead'.
 *
 *----------------------------------------------------------------------
 */

static int
static inline size_t
ResultCopy(
    ResultBuffer *rPtr,		/* The buffer to read from */
    unsigned char *buf,		/* The buffer to copy into */
    int toRead)			/* Number of requested bytes */
    size_t toRead)		/* Number of requested bytes */
{
    int copied;

    if (rPtr->used == 0) {
	/*
	 * Nothing to copy in the case of an empty buffer.
	 */
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
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







-
+










-
+







static int
TransformRead(
    ReflectedTransform *rtPtr,
    int *errorCodePtr,
    Tcl_Obj *bufObj)
{
    Tcl_Obj *resObj;
    size_t bytec = 0;		/* Number of returned bytes */
    Tcl_Size bytec = 0;		/* Number of returned bytes */
    unsigned char *bytev;	/* Array of returned bytes */

    /*
     * Are we in the correct thread?
     */

#if TCL_THREADS
    if (rtPtr->thread != Tcl_GetCurrentThread()) {
	ForwardParam p;

	p.transform.buf = (char *) TclGetByteArrayFromObj(bufObj,
	p.transform.buf = (char *) Tcl_GetBytesFromObj(NULL, bufObj,
		&(p.transform.size));

	ForwardOpToOwnerThread(rtPtr, ForwardedInput, &p);

	if (p.base.code != TCL_OK) {
	    PassReceivedError(rtPtr->chan, &p);
	    *errorCodePtr = EINVAL;
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
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







-
+















-
+







    if (InvokeTclMethod(rtPtr, "read", bufObj, NULL, &resObj) != TCL_OK) {
	Tcl_SetChannelError(rtPtr->chan, resObj);
	Tcl_DecrRefCount(resObj);	/* Remove reference held from invoke */
	*errorCodePtr = EINVAL;
	return 0;
    }

    bytev = TclGetByteArrayFromObj(resObj, &bytec);
    bytev = Tcl_GetBytesFromObj(NULL, resObj, &bytec);
    ResultAdd(&rtPtr->result, bytev, bytec);

    Tcl_DecrRefCount(resObj);		/* Remove reference held from invoke */
    return 1;
}

static int
TransformWrite(
    ReflectedTransform *rtPtr,
    int *errorCodePtr,
    unsigned char *buf,
    int toWrite)
{
    Tcl_Obj *bufObj;
    Tcl_Obj *resObj;
    size_t bytec = 0;		/* Number of returned bytes */
    Tcl_Size bytec = 0;		/* Number of returned bytes */
    unsigned char *bytev;	/* Array of returned bytes */
    int res;

    /*
     * Are we in the correct thread?
     */

3141
3142
3143
3144
3145
3146
3147
3148

3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169

3170
3171
3172
3173
3174
3175
3176
3138
3139
3140
3141
3142
3143
3144

3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165

3166
3167
3168
3169
3170
3171
3172
3173







-
+




















-
+







	    Tcl_DecrRefCount(bufObj);
	    Tcl_DecrRefCount(resObj);	/* Remove reference held from invoke */
	    return 0;
	}

	*errorCodePtr = EOK;

	bytev = TclGetByteArrayFromObj(resObj, &bytec);
	bytev = Tcl_GetBytesFromObj(NULL, resObj, &bytec);
	res = Tcl_WriteRaw(rtPtr->parent, (char *) bytev, bytec);

	Tcl_DecrRefCount(bufObj);
	Tcl_DecrRefCount(resObj);	/* Remove reference held from invoke */
    }

    if (res < 0) {
	*errorCodePtr = Tcl_GetErrno();
	return 0;
    }

    return 1;
}

static int
TransformDrain(
    ReflectedTransform *rtPtr,
    int *errorCodePtr)
{
    Tcl_Obj *resObj;
    size_t bytec = 0;		/* Number of returned bytes */
    Tcl_Size bytec = 0;		/* Number of returned bytes */
    unsigned char *bytev;	/* Array of returned bytes */

    /*
     * Are we in the correct thread?
     */

#if TCL_THREADS
3194
3195
3196
3197
3198
3199
3200
3201

3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218

3219
3220
3221
3222
3223
3224
3225
3191
3192
3193
3194
3195
3196
3197

3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214

3215
3216
3217
3218
3219
3220
3221
3222







-
+
















-
+







	if (InvokeTclMethod(rtPtr, "drain", NULL, NULL, &resObj)!=TCL_OK) {
	    Tcl_SetChannelError(rtPtr->chan, resObj);
	    Tcl_DecrRefCount(resObj);	/* Remove reference held from invoke */
	    *errorCodePtr = EINVAL;
	    return 0;
	}

	bytev = TclGetByteArrayFromObj(resObj, &bytec);
	bytev = Tcl_GetBytesFromObj(NULL, resObj, &bytec);
	ResultAdd(&rtPtr->result, bytev, bytec);

	Tcl_DecrRefCount(resObj);	/* Remove reference held from invoke */
    }

    rtPtr->readIsDrained = 1;
    return 1;
}

static int
TransformFlush(
    ReflectedTransform *rtPtr,
    int *errorCodePtr,
    int op)
{
    Tcl_Obj *resObj;
    size_t bytec = 0;		/* Number of returned bytes */
    Tcl_Size bytec = 0;		/* Number of returned bytes */
    unsigned char *bytev;	/* Array of returned bytes */
    int res;

    /*
     * Are we in the correct thread?
     */

3250
3251
3252
3253
3254
3255
3256
3257

3258
3259
3260
3261
3262
3263
3264
3247
3248
3249
3250
3251
3252
3253

3254
3255
3256
3257
3258
3259
3260
3261







-
+







	    Tcl_SetChannelError(rtPtr->chan, resObj);
	    Tcl_DecrRefCount(resObj);	/* Remove reference held from invoke */
	    *errorCodePtr = EINVAL;
	    return 0;
	}

	if (op == FLUSH_WRITE) {
	    bytev = TclGetByteArrayFromObj(resObj, &bytec);
	    bytev = Tcl_GetBytesFromObj(NULL, resObj, &bytec);
	    res = Tcl_WriteRaw(rtPtr->parent, (char *) bytev, bytec);
	} else {
	    res = 0;
	}
	Tcl_DecrRefCount(resObj);	/* Remove reference held from invoke */
    }

Changes to generic/tclIOSock.c.

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
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





-
+














-
+







/*
 * tclIOSock.c --
 *
 *	Common routines used by all socket based channel types.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

#if defined(_WIN32)
/*
 * On Windows, we need to do proper Unicode->UTF-8 conversion.
 */

typedef struct {
    int initialized;
    Tcl_DString errorMsg; /* UTF-8 encoded error-message */
    Tcl_DString errorMsg;	/* UTF-8 encoded error-message */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;

#undef gai_strerror
static const char *
gai_strerror(
    int code)
71
72
73
74
75
76
77
78






79
80
81
82
83
84
85
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85
86
87
88
89
90







-
+
+
+
+
+
+







    const char *native;

    if (Tcl_GetInt(NULL, string, portPtr) != TCL_OK) {
	/*
	 * Don't bother translating 'proto' to native.
	 */

	native = Tcl_UtfToExternalDString(NULL, string, -1, &ds);
	if (Tcl_UtfToExternalDStringEx(interp, NULL, string, -1, 0, &ds,
		NULL) != TCL_OK) {
	    Tcl_DStringFree(&ds);
	    return TCL_ERROR;
	}
	native = Tcl_DStringValue(&ds);
	sp = getservbyname(native, proto);		/* INTL: Native. */
	Tcl_DStringFree(&ds);
	if (sp != NULL) {
	    *portPtr = ntohs((unsigned short) sp->s_port);
	    return TCL_OK;
	}
    }
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
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







-
+



+

+
+
+

-
+



-
+



-
+



-
+







#if !defined(_WIN32) && !defined(__CYGWIN__)
#   define SOCKET int
#endif

int
TclSockMinimumBuffers(
    void *sock,			/* Socket file descriptor */
    int size)			/* Minimum buffer size */
    Tcl_Size size1)		/* Minimum buffer size */
{
    int current;
    socklen_t len;
    int size = size1;

    if (size != size1) {
	return TCL_ERROR;
    }
    len = sizeof(int);
    getsockopt((SOCKET)(size_t) sock, SOL_SOCKET, SO_SNDBUF,
    getsockopt((SOCKET)(size_t)sock, SOL_SOCKET, SO_SNDBUF,
	    (char *) &current, &len);
    if (current < size) {
	len = sizeof(int);
	setsockopt((SOCKET)(size_t) sock, SOL_SOCKET, SO_SNDBUF,
	setsockopt((SOCKET)(size_t)sock, SOL_SOCKET, SO_SNDBUF,
		(char *) &size, len);
    }
    len = sizeof(int);
    getsockopt((SOCKET)(size_t) sock, SOL_SOCKET, SO_RCVBUF,
    getsockopt((SOCKET)(size_t)sock, SOL_SOCKET, SO_RCVBUF,
	    (char *) &current, &len);
    if (current < size) {
	len = sizeof(int);
	setsockopt((SOCKET)(size_t) sock, SOL_SOCKET, SO_RCVBUF,
	setsockopt((SOCKET)(size_t)sock, SOL_SOCKET, SO_RCVBUF,
		(char *) &size, len);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
176
177
178
179
180
181
182
183






184
185
186
187
188
189
190
185
186
187
188
189
190
191

192
193
194
195
196
197
198
199
200
201
202
203
204







-
+
+
+
+
+
+







    struct addrinfo *v6head = NULL, *v6ptr = NULL;
    char *native = NULL, portbuf[TCL_INTEGER_SPACE], *portstring;
    const char *family = NULL;
    Tcl_DString ds;
    int result;

    if (host != NULL) {
	native = Tcl_UtfToExternalDString(NULL, host, -1, &ds);
	if (Tcl_UtfToExternalDStringEx(interp, NULL, host, -1, 0, &ds,
		NULL) != TCL_OK) {
		Tcl_DStringFree(&ds);
	    return 0;
	}
	native = Tcl_DStringValue(&ds);
    }

    /*
     * Workaround for OSX's apparent inability to resolve "localhost", "0"
     * when the loopback device is the only available network interface.
     */

245
246
247
248
249
250
251
252

253
254
255
256
257
258
259
259
260
261
262
263
264
265

266
267
268
269
270
271
272
273







-
+








    if (result != 0) {
	*errorMsgPtr =
#ifdef EAI_SYSTEM	/* Doesn't exist on Windows */
		(result == EAI_SYSTEM) ? Tcl_PosixError(interp) :
#endif /* EAI_SYSTEM */
		gai_strerror(result);
        return 0;
	return 0;
    }

    /*
     * Put IPv4 addresses before IPv6 addresses to maximize backwards
     * compatibility of [fconfigure -sockname] output.
     *
     * There might be more elegant/efficient ways to do this.
309
310
311
312
313
314
315
316

317
318
319
320
321
322


323
324
325
326
327
328
329
330
331
323
324
325
326
327
328
329

330
331
332
333
334


335
336
337
338
339
340
341
342
343
344
345







-
+




-
-
+
+










Tcl_Channel
Tcl_OpenTcpServer(
    Tcl_Interp *interp,
    int port,
    const char *host,
    Tcl_TcpAcceptProc *acceptProc,
    ClientData callbackData)
    void *callbackData)
{
    char portbuf[TCL_INTEGER_SPACE];

    TclFormatInt(portbuf, port);
    return Tcl_OpenTcpServerEx(interp, portbuf, host, TCL_TCPSERVER_REUSEADDR,
	    acceptProc, callbackData);
    return Tcl_OpenTcpServerEx(interp, portbuf, host, -1,
	    TCL_TCPSERVER_REUSEADDR, acceptProc, callbackData);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclIOUtil.c.

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
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
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
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









-
-
-
+
+
+






+


















-
+
















-
+
-



-
+
-
-
+










-
+




-
+







/*
 * tclIOUtil.c --
 *
 *	Provides an interface for managing filesystems in Tcl, and also for
 *	creating a filesystem interface in Tcl arbitrary facilities.  All
 *	filesystem operations are performed via this interface.  Vince Darley
 *	is the primary author.  Other signifiant contributors are Karl
 *	Lehenbauer, Mark Diekhans and Peter da Silva.
 *
 * Copyright (c) 1991-1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 2001-2004 Vincent Darley.
 * Copyright © 1991-1994 The Regents of the University of California.
 * Copyright © 1994-1997 Sun Microsystems, Inc.
 * Copyright © 2001-2004 Vincent Darley.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclIO.h"
#ifdef _WIN32
#   include "tclWinInt.h"
#endif
#include "tclFileSystem.h"

#ifdef TCL_TEMPLOAD_NO_UNLINK
#ifndef NO_FSTATFS
#include <sys/statfs.h>
#endif
#endif

/*
 * struct FilesystemRecord --
 *
 * An item in a linked list of registered filesystems
 */

typedef struct FilesystemRecord {
    ClientData clientData;	/* Client-specific data for the filesystem
    void *clientData;		/* Client-specific data for the filesystem
				 * (can be NULL) */
    const Tcl_Filesystem *fsPtr;/* Pointer to filesystem dispatch table. */
    struct FilesystemRecord *nextPtr;
				/* The next registered filesystem, or NULL to
				 * indicate the end of the list. */
    struct FilesystemRecord *prevPtr;
				/* The previous filesystem, or NULL to indicate
				 * the ned of the list */
} FilesystemRecord;

/*
 */

typedef struct {
    int initialized;
    size_t cwdPathEpoch;	/* Compared with the global cwdPathEpoch to
				 * determine whether cwdPathPtr is stale.
				 * determine whether cwdPathPtr is stale. */
				 */
    size_t filesystemEpoch;
    Tcl_Obj *cwdPathPtr;	/* A private copy of cwdPathPtr. Updated when
				 * the value is accessed  and cwdPathEpoch has
				 * changed.
				 * changed. */
				 */
    ClientData cwdClientData;
    void *cwdClientData;
    FilesystemRecord *filesystemList;
    size_t claims;
} ThreadSpecificData;

/*
 * Forward declarations.
 */

static Tcl_NRPostProc	EvalFileCallback;
static FilesystemRecord*FsGetFirstFilesystem(void);
static void		FsThrExitProc(ClientData cd);
static void		FsThrExitProc(void *cd);
static Tcl_Obj *	FsListMounts(Tcl_Obj *pathPtr, const char *pattern);
static void		FsAddMountsToGlobResult(Tcl_Obj *resultPtr,
			    Tcl_Obj *pathPtr, const char *pattern,
			    Tcl_GlobTypeData *types);
static void		FsUpdateCwd(Tcl_Obj *cwdObj, ClientData clientData);
static void		FsUpdateCwd(Tcl_Obj *cwdObj, void *clientData);
static void		FsRecacheFilesystemList(void);
static void		Claim(void);
static void		Disclaim(void);

static void *		DivertFindSymbol(Tcl_Interp *interp,
			    Tcl_LoadHandle loadHandle, const char *symbol);
static void		DivertUnloadFile(Tcl_LoadHandle loadHandle);
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
99
100
101
102
103
104
105

106
107
108
109
110
111
112







-







 * Functions that support the native filesystem functions listed above.  They
 * are the same for win/unix, and not in tclInt.h because they are and should
 * be used only here.
 */

MODULE_SCOPE const char *const		tclpFileAttrStrings[];
MODULE_SCOPE const TclFileAttrProcs	tclpFileAttrProcs[];


/*
 * These these functions are not static either because routines in the native
 * (win/unix) directories call them or they are actually implemented in those
 * directories. They should be called from outside Tcl's native filesystem
 * routines. If we ever built the native filesystem support into a separate
 * code library, this could actually be enforced.
174
175
176
177
178
179
180
181

182
183
184
185
186
187
188
172
173
174
175
176
177
178

179
180
181
182
183
184
185
186







-
+







    (Tcl_FSGetCwdProc *) TclpGetNativeCwd,
    TclpObjChdir
};

/*
 * An initial record in the linked list for the native filesystem.  Remains at
 * the tail of the list and is never freed.  Currently the native filesystem is
 * hard-coded.  It may make sense to modify this to accomodate unconventional
 * hard-coded.  It may make sense to modify this to accommodate unconventional
 * uses of Tcl that provide no native filesystem.
 */

static FilesystemRecord nativeFilesystemRecord = {
    NULL,
    &tclNativeFilesystem,
    NULL,
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
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







-
+

















-
+










-
+
+








/*
 * A files-system indepent sense of the current directory.
 */

static Tcl_Obj *cwdPathPtr = NULL;
static size_t cwdPathEpoch = 0;	    /* The pathname of the current directory */
static ClientData cwdClientData = NULL;
static void *cwdClientData = NULL;
TCL_DECLARE_MUTEX(cwdMutex)

static Tcl_ThreadDataKey fsDataKey;

/*
 * When a temporary copy of a file is created on the native filesystem in order
 * to load the file, an FsDivertLoad structure is created to track both the
 * actual unloadProc/clientData combination which was used, and the original and
 * modified filenames.  This makes it possible to correctly undo the entire
 * operation in order to unload the library.
 */

typedef struct {
    Tcl_LoadHandle loadHandle;
    Tcl_FSUnloadFileProc *unloadProcPtr;
    Tcl_Obj *divertedFile;
    const Tcl_Filesystem *divertedFilesystem;
    ClientData divertedFileNativeRep;
    void *divertedFileNativeRep;
} FsDivertLoad;

/*
 * Obsolete string-based APIs that should be removed in a future release,
 * perhaps in Tcl 9.
 */

/* Obsolete */
int
Tcl_Stat(
    const char *path,		/* Pathname of file to stat (in current CP). */
    const char *path,		/* Pathname of file to stat (in current system
				 * encoding). */
    struct stat *oldStyleBuf)	/* Filled with results of stat call. */
{
    int ret;
    Tcl_StatBuf buf;
    Tcl_Obj *pathPtr = Tcl_NewStringObj(path,-1);

    Tcl_IncrRefCount(pathPtr);
289
290
291
292
293
294
295
296

297
298
299
300
301
302
303
288
289
290
291
292
293
294

295
296
297
298
299
300
301
302







-
+







	}

#   undef OUT_OF_RANGE
#   undef OUT_OF_URANGE
#endif /* !TCL_WIDE_INT_IS_LONG */

	/*
	 * Copy across all supported fields, with possible type coercions on
	 * Copy across all supported fields, with possible type coercion on
	 * those fields that change between the normal and lf64 versions of
	 * the stat structure (on Solaris at least). This is slow when the
	 * structure sizes coincide, but that's what you get for using an
	 * obsolete interface.
	 */

	oldStyleBuf->st_mode	= buf.st_mode;
324
325
326
327
328
329
330
331
332


333
334
335
336
337
338
339
323
324
325
326
327
328
329


330
331
332
333
334
335
336
337
338







-
-
+
+







    }
    return ret;
}

/* Obsolete */
int
Tcl_Access(
    const char *path,		/* Pathname of file to access (in current CP).
				*/
    const char *path,		/* Pathname of file to access (in current
				 * system encoding). */
    int mode)			/* Permission setting. */
{
    int ret;
    Tcl_Obj *pathPtr = Tcl_NewStringObj(path,-1);

    Tcl_IncrRefCount(pathPtr);
    ret = Tcl_FSAccess(pathPtr,mode);
410
411
412
413
414
415
416
417

418
419
420
421
422
423
424
409
410
411
412
413
414
415

416
417
418
419
420
421
422
423







-
+








/*
 * The basic filesystem implementation.
 */

static void
FsThrExitProc(
    ClientData cd)
    void *cd)
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)cd;
    FilesystemRecord *fsRecPtr = NULL, *tmpFsRecPtr = NULL;

    /*
     * Discard the cwd copy.
     */
446
447
448
449
450
451
452





453
454
455
456
457
458
459
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463







+
+
+
+
+







    tsdPtr->initialized = 0;
}

int
TclFSCwdIsNative(void)
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);

    /* if not yet initialized - ensure we'll once obtain cwd */
    if (!tsdPtr->cwdPathEpoch) {
	Tcl_FSGetCwd(NULL);
    }

    if (tsdPtr->cwdClientData != NULL) {
	return 1;
    } else {
	return 0;
    }
}
517
518
519
520
521
522
523
524

525
526
527
528
529
530
531
521
522
523
524
525
526
527

528
529
530
531
532
533
534
535







-
+







    if (pathPtrPtr == NULL) {
	return (tsdPtr->cwdPathPtr == NULL);
    }

    if (tsdPtr->cwdPathPtr == *pathPtrPtr) {
	return 1;
    } else {
	size_t len1, len2;
	Tcl_Size len1, len2;
	const char *str1, *str2;

	str1 = TclGetStringFromObj(tsdPtr->cwdPathPtr, &len1);
	str2 = TclGetStringFromObj(*pathPtrPtr, &len2);
	if ((len1 == len2) && !memcmp(str1, str2, len1)) {
	    /*
	     * The values are equal but the objects are different.  Cache the
657
658
659
660
661
662
663
664

665
666

667
668
669
670
671
672
673
661
662
663
664
665
666
667

668
669

670
671
672
673
674
675
676
677







-
+

-
+







/*
 * If non-NULL, take posession of clientData and free it later.
 */

static void
FsUpdateCwd(
    Tcl_Obj *cwdObj,
    ClientData clientData)
    void *clientData)
{
    size_t len = 0;
    Tcl_Size len = 0;
    const char *str = NULL;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);

    if (cwdObj != NULL) {
	str = TclGetStringFromObj(cwdObj, &len);
    }

757
758
759
760
761
762
763

764
765
766
767
768
769
770
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775







+







    }

    /*
     * Remove all filesystems, freeing any allocated memory that is no longer
     * needed.
     */

    TclZipfsFinalize();
    fsRecPtr = filesystemList;
    while (fsRecPtr != NULL) {
	FilesystemRecord *tmpFsRecPtr = fsRecPtr->nextPtr;

	/*
	 * The native filesystem is static, so don't free it.
	 */
839
840
841
842
843
844
845
846

847
848
849
850
851
852
853
844
845
846
847
848
849
850

851
852
853
854
855
856
857
858







-
+







 *	registered filesystems.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FSRegister(
    ClientData clientData,	/* Client-specific data for this filesystem. */
    void *clientData,		/* Client-specific data for this filesystem. */
    const Tcl_Filesystem *fsPtr)/* The filesystem record for the new fs. */
{
    FilesystemRecord *newFilesystemPtr;

    if (fsPtr == NULL) {
	return TCL_ERROR;
    }
985
986
987
988
989
990
991
992


993
994
995
996
997
998
999
990
991
992
993
994
995
996

997
998
999
1000
1001
1002
1003
1004
1005







-
+
+







				 * of the correct type. */
    Tcl_GlobTypeData *types)	/* Specifies acceptable types.
				 * May be NULL. The directory flag is
				 * particularly significant. */
{
    const Tcl_Filesystem *fsPtr;
    Tcl_Obj *cwd, *tmpResultPtr, **elemsPtr;
    int resLength, i, ret = -1;
    Tcl_Size resLength, i;
    int ret = -1;

    if (types != NULL && (types->type & TCL_GLOB_TYPE_MOUNT)) {
	/*
	 * Currently external callers may not query mounts, which would be a
	 * valuable future step. This is the only routine that knows about
	 * mounts, so we're being called recursively by ourself. Return no
	 * matches.
1061
1062
1063
1064
1065
1066
1067
1068

1069
1070
1071
1072
1073
1074
1075
1067
1068
1069
1070
1071
1072
1073

1074
1075
1076
1077
1078
1079
1080
1081







-
+







	if (ret == TCL_OK) {
	    FsAddMountsToGlobResult(tmpResultPtr, cwd, pattern, types);

	    /*
	     * resultPtr and tmpResultPtr are guaranteed to be distinct.
	     */

	    ret = Tcl_ListObjGetElements(interp, tmpResultPtr,
	    ret = TclListObjGetElements(interp, tmpResultPtr,
		    &resLength, &elemsPtr);
	    for (i=0 ; ret==TCL_OK && i<resLength ; i++) {
		ret = Tcl_ListObjAppendElement(interp, resultPtr,
			TclFSMakePathRelative(interp, elemsPtr[i], cwd));
	    }
	}
	TclDecrRefCount(tmpResultPtr);
1098
1099
1100
1101
1102
1103
1104
1105

1106
1107
1108

1109
1110
1111
1112
1113
1114
1115
1116

1117
1118
1119

1120
1121
1122
1123
1124

1125
1126
1127
1128
1129
1130
1131
1104
1105
1106
1107
1108
1109
1110

1111

1112

1113
1114
1115
1116
1117
1118
1119
1120

1121
1122
1123

1124
1125
1126
1127
1128

1129
1130
1131
1132
1133
1134
1135
1136







-
+
-

-
+







-
+


-
+




-
+







static void
FsAddMountsToGlobResult(
    Tcl_Obj *resultPtr,		/* The current list of matching pathnames. Must
				 * not be shared. */
    Tcl_Obj *pathPtr,		/* The directory that was searched. */
    const char *pattern,	/* Pattern to match mounts against. */
    Tcl_GlobTypeData *types)	/* Acceptable types.  May be NULL. The
				 * directory flag is particularly significant.
				 * directory flag is particularly significant. */
				 */
{
    int mLength, gLength, i;
    Tcl_Size mLength, gLength, i;
    int dir = (types == NULL || (types->type & TCL_GLOB_TYPE_DIR));
    Tcl_Obj *mounts = FsListMounts(pathPtr, pattern);

    if (mounts == NULL) {
	return;
    }

    if (Tcl_ListObjLength(NULL, mounts, &mLength) != TCL_OK || mLength == 0) {
    if (TclListObjLength(NULL, mounts, &mLength) != TCL_OK || mLength == 0) {
	goto endOfMounts;
    }
    if (Tcl_ListObjLength(NULL, resultPtr, &gLength) != TCL_OK) {
    if (TclListObjLength(NULL, resultPtr, &gLength) != TCL_OK) {
	goto endOfMounts;
    }
    for (i=0 ; i<mLength ; i++) {
	Tcl_Obj *mElt;
	int j;
	Tcl_Size j;
	int found = 0;

	Tcl_ListObjIndex(NULL, mounts, i, &mElt);

	for (j=0 ; j<gLength ; j++) {
	    Tcl_Obj *gElt;

1141
1142
1143
1144
1145
1146
1147
1148

1149
1150
1151
1152
1153
1154
1155
1146
1147
1148
1149
1150
1151
1152

1153
1154
1155
1156
1157
1158
1159
1160







-
+







		    gLength--;
		}
		break;		/* Break out of for loop. */
	    }
	}
	if (!found && dir) {
	    Tcl_Obj *norm;
	    size_t len, mlen;
	    Tcl_Size len, mlen;

	    /*
	     * mElt is normalized and lies inside pathPtr so
	     * add to the result the right representation of mElt,
	     * i.e. the representation relative to pathPtr.
	     */

1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1168
1169
1170
1171
1172
1173
1174

1175
1176
1177
1178
1179
1180
1181







-







		    /*
		     * Deal with the root of the volume.
		     */

		    len--;
		}
		len++;		/* account for '/' in the mElt [Bug 1602539] */


		mElt = TclNewFSPathObj(pathPtr, mount + len, mlen - len);
		Tcl_ListObjAppendElement(NULL, resultPtr, mElt);
	    }
	    /*
	     * Not comparing mounts to mounts, so no need to increment gLength
	     */
1208
1209
1210
1211
1212
1213
1214
1215

1216
1217
1218
1219
1220
1221
1222
1223
1224

1225
1226
1227
1228
1229
1230
1231
1212
1213
1214
1215
1216
1217
1218

1219


1220
1221
1222
1223
1224
1225

1226
1227
1228
1229
1230
1231
1232
1233







-
+
-
-






-
+







 *	(2) An additional mount point is established inside an existing
 *	filesystem (except for the native file system; see note below).
 *
 *	(3) A filesystem changes the list of available volumes (except for the
 *	native file system; see note below).
 *
 *	(4) The mapping from a string representation of a file to a full,
 *	normalized pathname changes. For example, if 'env(HOME)' is modified,
 *	normalized pathname changes.
 *	then any pathname containing '~' maps to a different item, possibly in
 *	a different filesystem.
 *
 *	Tcl has no control over (2) and (3), so each registered filesystem must
 *	call Tcl_FSMountsChnaged in each of those circumstances.
 *
 *	The reason for the exception in 2,3 for the native filesystem is that
 *	the native filesystem claims every file without determining whether
 *	whether the file exists, or even whether the pathname makes sense.
 *	the file exists, or even whether the pathname makes sense.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_FSMountsChanged(
    TCL_UNUSED(const Tcl_Filesystem *) /*fsPtr*/)
1259
1260
1261
1262
1263
1264
1265
1266

1267
1268
1269
1270
1271

1272
1273
1274
1275
1276
1277
1278
1261
1262
1263
1264
1265
1266
1267

1268
1269
1270
1271
1272

1273
1274
1275
1276
1277
1278
1279
1280







-
+




-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

ClientData
void *
Tcl_FSData(
    const Tcl_Filesystem *fsPtr) /* The filesystem to find in the list of
				  *  registered filesystems. */
{
    ClientData retVal = NULL;
    void *retVal = NULL;
    FilesystemRecord *fsRecPtr = FsGetFirstFilesystem();

    /*
     * Find the filesystem in and retrieve its clientData.
     */

    while ((retVal == NULL) && (fsRecPtr != NULL)) {
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
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
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
1354
1355

1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368

1369
1370
1371
1372
1373
1374
1375







-
+




















-
+














-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
+
+
+










-







 *	Stores the resulting pathname in pathPtr and returns the offset of the
 *	last byte processed in pathPtr.
 *
 * Side effects:
 *	None (beyond the memory allocation for the result).
 *
 * Special notes:
 *	If the filesystem-specific normalizePathProcs can re-introduce ../, ./
 *	If the filesystem-specific normalizePathProcs can reintroduce ../, ./
 *	components into the pathname, this function does not return the correct
 *	result. This may be possible with symbolic links on unix.
 *
 *
 *---------------------------------------------------------------------------
 */

int
TclFSNormalizeToUniquePath(
    Tcl_Interp *interp,		/* Used for error messages. */
    Tcl_Obj *pathPtr,		/* An Pathname to normalize in-place.  Must be
				 * unshared. */
    int startAt)		/* Offset the string of pathPtr to start at.
				 * Must either be 0 or offset of a directory
				 * separator at the end of a pathname part that
				 * is already normalized, I.e. not the index of
				 * the byte just after the separator.  */
{
    FilesystemRecord *fsRecPtr, *firstFsRecPtr;

    size_t i;
    Tcl_Size i;
    int isVfsPath = 0;
    const char *path;

    /*
     * Pathnames starting with a UNC prefix and ending with a colon character
     * are reserved for VFS use.  These names can not conflict with real UNC
     * pathnames per https://msdn.microsoft.com/en-us/library/gg465305.aspx and
     * rfc3986's definition of reg-name.
     *
     * We check these first to avoid useless calls to the native filesystem's
     * normalizePathProc.
     */
    path = TclGetStringFromObj(pathPtr, &i);

    if ( (i >= 3) && ( (path[0] == '/' && path[1] == '/')
		    || (path[0] == '\\' && path[1] == '\\') ) ) {
	for ( i = 2; ; i++) {
	    if (path[i] == '\0') break;
	    if (path[i] == path[0]) break;
	}
    if ((i >= 3) && ((path[0] == '/' && path[1] == '/')
	    || (path[0] == '\\' && path[1] == '\\'))) {
	for (i = 2; ; i++) {
	    if (path[i] == '\0') {
		break;
	    }
	    if (path[i] == path[0]) {
		break;
	    }
	}
	--i;
	if (path[i] == ':') isVfsPath = 1;
	if (path[i] == ':') {
	    isVfsPath = 1;
	}
    }

    /*
     * Call the the normalizePathProc routine of each registered filesystem.
     */
    firstFsRecPtr = FsGetFirstFilesystem();

    Claim();

    if (!isVfsPath) {

	/*
	 * Find and call the native filesystem handler first if there is one
	 * because the root of Tcl's filesystem is always a native filesystem
	 * (i.e., '/' on unix is native).
	 */

	for (fsRecPtr=firstFsRecPtr; fsRecPtr!=NULL; fsRecPtr=fsRecPtr->nextPtr) {
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479



1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490


1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512

1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529

1530
1531
1532
1533

1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546

1547
1548
1549

1550
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
1415
1416
1417
1418
1419
1420
1421































1422
1423
1424
1425
1426
1427

1428
1429
1430
1431

1432

1433


1434
1435
1436
1437
1438
1439
1440
1441
1442
1443

1444
1445
1446
1447



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
1478
1479
1480
1481

1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498

1499

1500
1501

1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513


1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-






-
+


+
-
+
-

-
-
+
+








-
+



-
-
-
+
-
-

-
-
+
+
+
-







-
-
-
+
+









-











-
+
















-
+
-


-
+











-
-
+



+











+





+
+
+
+









+
+
+
+
+
+
+
+
+
-
+


+
+
+
-
+


+
+
+
-
+


+
+
+
+
+
+
+
+

-
+

+
+
+


-
-
+
+
+
+


+
+
+







-
+
-




+
+
+







-
+
-

-

+
+
+


+
+
+
-
+

-


-
-
-
+
+
+

-
+
-








-
+














-
+







}

/*
 *---------------------------------------------------------------------------
 *
 * TclGetOpenMode --
 *
 *	Obsolete.  A limited version of TclGetOpenModeEx() which exists only to
 *	satisfy any extensions imprudently using it via Tcl's internal stubs
 *	table.
 *
 * Results:
 *	See TclGetOpenModeEx().
 *
 * Side effects:
 *	See TclGetOpenModeEx().
 *
 *---------------------------------------------------------------------------
 */

int
TclGetOpenMode(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting.  May
				 *  be NULL. */
    const char *modeString,	/* e.g. "r+" or "RDONLY CREAT". */
    int *seekFlagPtr)		/* Sets this to 1 to tell the caller to seek to
				   EOF after opening the file, and
				 * 0 otherwise. */
{
    int binary = 0;
    return TclGetOpenModeEx(interp, modeString, seekFlagPtr, &binary);
}

/*
 *---------------------------------------------------------------------------
 *
 * TclGetOpenModeEx --
 *
 *	Computes a POSIX mode mask for opening a file.
 *
 * Results:
 *	The mode to pass to "open", or -1 if an error occurs.
 *
 * Side effects:
 *	Sets *seekFlagPtr to 1 to tell the caller to
 *	Sets *modeFlagsPtr to 1 to tell the caller to
 *	seek to EOF after opening the file, or to 0 otherwise.
 *
 *	Adds CHANNEL_RAW_MODE to *modeFlagsPtr to tell the caller
 *	Sets *binaryPtr to 1 to tell the caller to configure the channel as a
 *	to configure the channel as a binary channel.
 *	binary channel, or to 0 otherwise.
 *
 *	If there is an error and interp is not NULL, sets interpreter result to
 *	an error message.
 *	If there is an error and interp is not NULL, sets
 *	interpreter result to an error message.
 *
 * Special note:
 *	Based on a prototype implementation contributed by Mark Diekhans.
 *
 *---------------------------------------------------------------------------
 */

int
TclGetOpenModeEx(
TclGetOpenMode(
    Tcl_Interp *interp,		/* Interpreter, possibly NULL, to use for
				 * error reporting. */
    const char *modeString,	/* Mode string, e.g. "r+" or "RDONLY CREAT" */
    int *seekFlagPtr,		/* Sets this to 1 to tell the the caller to seek to
				 * EOF after opening the file, and 0 otherwise. */
    int *binaryPtr)		/* Sets this to 1 to tell the caller to
    int *modeFlagsPtr)
				 * configure the channel for binary
				 * operations after opening the file. */
{
    int mode, modeArgc, c, i, gotRW;
    const char **modeArgv, *flag;
    int mode, c, gotRW;
    Tcl_Size modeArgc, i;
    const char **modeArgv = NULL, *flag;
#define RW_MODES (O_RDONLY|O_WRONLY|O_RDWR)

    /*
     * Check for the simpler fopen-like access modes like "r" which are
     * distinguished from the POSIX access modes by the presence of a
     * lower-case first letter.
     */

    *seekFlagPtr = 0;
    *binaryPtr = 0;
    mode = 0;
    *modeFlagsPtr = 0;
    mode = O_RDONLY;

    /*
     * Guard against wide characters before using byte-oriented routines.
     */

    if (!(modeString[0] & 0x80)
	    && islower(UCHAR(modeString[0]))) { /* INTL: ISO only. */
	switch (modeString[0]) {
	case 'r':
	    mode = O_RDONLY;
	    break;
	case 'w':
	    mode = O_WRONLY|O_CREAT|O_TRUNC;
	    break;
	case 'a':
	    /*
	     * Add O_APPEND for proper automatic seek-to-end-on-write by the
	     * OS. [Bug 680143]
	     */

	    mode = O_WRONLY|O_CREAT|O_APPEND;
	    *seekFlagPtr = 1;
	    *modeFlagsPtr |= 1;
	    break;
	default:
	    goto error;
	}
	i = 1;
	while (i<3 && modeString[i]) {
	    if (modeString[i] == modeString[i-1]) {
		goto error;
	    }
	    switch (modeString[i++]) {
	    case '+':
		/*
		 * Remove O_APPEND so that the seek command works. [Bug
		 * 1773127]
		 */

		mode &= ~(O_RDONLY|O_WRONLY|O_APPEND);
		mode = (mode & ~(O_ACCMODE|O_APPEND)) | O_RDWR;
		mode |= O_RDWR;
		break;
	    case 'b':
		*binaryPtr = 1;
		*modeFlagsPtr |= CHANNEL_RAW_MODE;
		break;
	    default:
		goto error;
	    }
	}
	if (modeString[i] != 0) {
	    goto error;
	}
	return mode;

    error:
	*seekFlagPtr = 0;
	*binaryPtr = 0;
	*modeFlagsPtr = 0;
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "illegal access mode \"%s\"", modeString));
	    Tcl_SetErrorCode(interp, "TCL", "OPENMODE", "INVALID", (char *)NULL);
	}
	return -1;
    }

    /*
     * The access modes are specified as a list of POSIX modes like O_CREAT.
     *
     * Tcl_SplitList must work correctly when interp is NULL.
     */

    if (Tcl_SplitList(interp, modeString, &modeArgc, &modeArgv) != TCL_OK) {
    invAccessMode:
	if (interp != NULL) {
	    Tcl_AddErrorInfo(interp,
		    "\n    while processing open access modes \"");
	    Tcl_AddErrorInfo(interp, modeString);
	    Tcl_AddErrorInfo(interp, "\"");
	    Tcl_SetErrorCode(interp, "TCL", "OPENMODE", "INVALID", (char *)NULL);
	}
	if (modeArgv) {
	    Tcl_Free((void *)modeArgv);
	}
	return -1;
    }

    gotRW = 0;
    for (i = 0; i < modeArgc; i++) {
	flag = modeArgv[i];
	c = flag[0];
	if ((c == 'R') && (strcmp(flag, "RDONLY") == 0)) {
	    if (gotRW) {
	    invRW:
		if (interp != NULL) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
				"invalid access mode \"%s\": modes RDONLY, "
				"RDWR, and WRONLY cannot be combined", flag));
		}
		goto invAccessMode;
	    }
	    mode = (mode & ~RW_MODES) | O_RDONLY;
	    mode = (mode & ~O_ACCMODE) | O_RDONLY;
	    gotRW = 1;
	} else if ((c == 'W') && (strcmp(flag, "WRONLY") == 0)) {
	    if (gotRW) {
		goto invRW;
	    }
	    mode = (mode & ~RW_MODES) | O_WRONLY;
	    mode = (mode & ~O_ACCMODE) | O_WRONLY;
	    gotRW = 1;
	} else if ((c == 'R') && (strcmp(flag, "RDWR") == 0)) {
	    if (gotRW) {
		goto invRW;
	    }
	    mode = (mode & ~RW_MODES) | O_RDWR;
	    mode = (mode & ~O_ACCMODE) | O_RDWR;
	    gotRW = 1;
	} else if ((c == 'A') && (strcmp(flag, "APPEND") == 0)) {
	    if (mode & O_APPEND) {
	    accessFlagRepeated:
		if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"access mode \"%s\" repeated", flag));
		}
	    goto invAccessMode;
	    }
	    mode |= O_APPEND;
	    *seekFlagPtr = 1;
	    *modeFlagsPtr |= 1;
	} else if ((c == 'C') && (strcmp(flag, "CREAT") == 0)) {
	    if (mode & O_CREAT) {
	    goto accessFlagRepeated;
	    }
	    mode |= O_CREAT;
	} else if ((c == 'E') && (strcmp(flag, "EXCL") == 0)) {
	    mode |= O_EXCL;

	    if (mode & O_EXCL) {
		goto accessFlagRepeated;
	    }
	    mode |= O_EXCL;
	} else if ((c == 'N') && (strcmp(flag, "NOCTTY") == 0)) {
#ifdef O_NOCTTY
	    if (mode & O_NOCTTY) {
		goto accessFlagRepeated;
	    }
	    mode |= O_NOCTTY;
#else
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"access mode \"%s\" not supported by this system",
			flag));
	    }
	    Tcl_Free((void *)modeArgv);
	    goto invAccessMode;
	    return -1;
#endif

	} else if ((c == 'N') && (strcmp(flag, "NONBLOCK") == 0)) {
#ifdef O_NONBLOCK
	    if (mode & O_NONBLOCK) {
		goto accessFlagRepeated;
	    }
	    mode |= O_NONBLOCK;
#else
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"access mode \"%s\" not supported by this system",
			flag));
	    }
	    Tcl_Free((void *)modeArgv);
	    goto invAccessMode;
	    return -1;
#endif

	} else if ((c == 'T') && (strcmp(flag, "TRUNC") == 0)) {
	    if (mode & O_TRUNC) {
		goto accessFlagRepeated;
	    }
	    mode |= O_TRUNC;
	} else if ((c == 'B') && (strcmp(flag, "BINARY") == 0)) {
	    if (*modeFlagsPtr & CHANNEL_RAW_MODE) {
		goto accessFlagRepeated;
	    }
	    *binaryPtr = 1;
	    *modeFlagsPtr |= CHANNEL_RAW_MODE;
	} else {

	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"invalid access mode \"%s\": must be RDONLY, WRONLY, "
			"RDWR, APPEND, BINARY, CREAT, EXCL, NOCTTY, NONBLOCK,"
			" or TRUNC", flag));
			"invalid access mode \"%s\": must be APPEND, BINARY, "
			"CREAT, EXCL, NOCTTY, NONBLOCK, RDONLY, RDWR, "
			"TRUNC, or WRONLY", flag));
	    }
	    Tcl_Free((void *)modeArgv);
	    goto invAccessMode;
	    return -1;
	}
    }

    Tcl_Free((void *)modeArgv);

    if (!gotRW) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "access mode must include either RDONLY, WRONLY, or RDWR",
		    "access mode must include either RDONLY, RDWR, or WRONLY",
		    -1));
	}
	return -1;
    }
    return mode;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FSEvalFile, Tcl_FSEvalFileEx, TclNREvalFile --
 *
 *	Reads a file and evaluates it as a script.
 *
 *	Tcl_FSEvalFile is Tcl_FSEvalFileEx without the encoding argument.
 *	Tcl_FSEvalFile is Tcl_FSEvalFileEx without the encodingName argument.
 *
 *	TclNREvalFile is an NRE-enabled version of Tcl_FSEvalFileEx.
 *
 * Results:
 *	A standard Tcl result, which is either the result of executing the
 *	file or an error indicating why the file couldn't be read.
 *
1680
1681
1682
1683
1684
1685
1686
1687

1688
1689
1690


1691
1692
1693
1694
1695
1696
1697
1689
1690
1691
1692
1693
1694
1695

1696
1697


1698
1699
1700
1701
1702
1703
1704
1705
1706







-
+

-
-
+
+







int
Tcl_FSEvalFileEx(
    Tcl_Interp *interp,		/* Interpreter that evaluates the script. */
    Tcl_Obj *pathPtr,		/* Pathname of the file to process.
				 * Tilde-substitution is performed on this
				 * pathname. */
    const char *encodingName)	/* Either the name of an encoding or NULL to
				   use the utf-8 encoding. */
				 * use the utf-8 encoding. */
{
    size_t length;
	int result = TCL_ERROR;
    Tcl_Size length;
    int result = TCL_ERROR;
    Tcl_StatBuf statBuf;
    Tcl_Obj *oldScriptFile;
    Interp *iPtr;
    const char *string;
    Tcl_Channel chan;
    Tcl_Obj *objPtr;

1711
1712
1713
1714
1715
1716
1717
1718
1719


1720
1721
1722

1723
1724
1725
1726
1727
1728
1729
1720
1721
1722
1723
1724
1725
1726


1727
1728
1729
1730

1731
1732
1733
1734
1735
1736
1737
1738







-
-
+
+


-
+







	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"couldn't read file \"%s\": %s",
		TclGetString(pathPtr), Tcl_PosixError(interp)));
	return result;
    }

    /*
     * The eof character is \32 (^Z). This is standard on Windows, and Tcl
     * uses it on every platform to allow for scripted documents. [Bug: 2040]
     * The eof character is \x1A (^Z). Tcl uses it on every platform to allow
     * for scripted documents. [Bug: 2040]
     */

    Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}");
    Tcl_SetChannelOption(interp, chan, "-eofchar", "\x1A");

    /*
     * If the encoding is specified, set the channel to that encoding.
     * Otherwise use utf-8.  If the encoding is unknown report an error.
     */

    if (encodingName == NULL) {
1752
1753
1754
1755
1756
1757
1758
1759
1760


1761
1762
1763
1764
1765
1766
1767
1761
1762
1763
1764
1765
1766
1767


1768
1769
1770
1771
1772
1773
1774
1775
1776







-
-
+
+







    string = TclGetString(objPtr);

    /*
     * If first character is not a BOM, append the remaining characters.
     * Otherwise, replace them. [Bug 3466099]
     */

    if (Tcl_ReadChars(chan, objPtr, -1,
	    memcmp(string, "\xef\xbb\xbf", 3)) == TCL_IO_FAILURE) {
    if (Tcl_ReadChars(chan, objPtr, TCL_INDEX_NONE,
	    memcmp(string, "\xEF\xBB\xBF", 3)) == TCL_IO_FAILURE) {
	Tcl_CloseEx(interp, chan, 0);
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"couldn't read file \"%s\": %s",
		TclGetString(pathPtr), Tcl_PosixError(interp)));
	goto end;
    }

1797
1798
1799
1800
1801
1802
1803
1804

1805
1806
1807
1808
1809

1810
1811
1812
1813
1814
1815
1816
1806
1807
1808
1809
1810
1811
1812

1813
1814
1815
1816
1817

1818
1819
1820
1821
1822
1823
1824
1825







-
+




-
+







	result = TclUpdateReturnInfo(iPtr);
    } else if (result == TCL_ERROR) {
	/*
	 * Record information about where the error occurred.
	 */

	const char *pathString = TclGetStringFromObj(pathPtr, &length);
	unsigned limit = 150;
	int limit = 150;
	int overflow = (length > limit);

	Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
		"\n    (file \"%.*s%s\" line %d)",
		(overflow ? limit : (unsigned)length), pathString,
		(overflow ? limit : (int)length), pathString,
		(overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
    }

  end:
    Tcl_DecrRefCount(objPtr);
    return result;
}
1847
1848
1849
1850
1851
1852
1853
1854
1855


1856
1857
1858

1859
1860
1861
1862
1863
1864
1865
1856
1857
1858
1859
1860
1861
1862


1863
1864
1865
1866

1867
1868
1869
1870
1871
1872
1873
1874







-
-
+
+


-
+







		"couldn't read file \"%s\": %s",
		TclGetString(pathPtr), Tcl_PosixError(interp)));
	return TCL_ERROR;
    }
    TclPkgFileSeen(interp, TclGetString(pathPtr));

    /*
     * The eof character is \32 (^Z). This is standard on Windows, and Tcl
     * uses it on every platform to allow for scripted documents. [Bug: 2040]
     * The eof character is \x1A (^Z). Tcl uses it on every platform to allow
     * for scripted documents. [Bug: 2040]
     */

    Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}");
    Tcl_SetChannelOption(interp, chan, "-eofchar", "\x1A");

    /*
     * If the encoding is specified, set the channel to that encoding.
     * Otherwise use utf-8.  If the encoding is unknown report an error.
     */

    if (encodingName == NULL) {
1889
1890
1891
1892
1893
1894
1895
1896
1897


1898
1899
1900
1901
1902
1903
1904
1898
1899
1900
1901
1902
1903
1904


1905
1906
1907
1908
1909
1910
1911
1912
1913







-
-
+
+







    string = TclGetString(objPtr);

    /*
     * If first character is not a BOM, append the remaining characters.
     * Otherwise, replace them. [Bug 3466099]
     */

    if (Tcl_ReadChars(chan, objPtr, -1,
	    memcmp(string, "\xef\xbb\xbf", 3)) == TCL_IO_FAILURE) {
    if (Tcl_ReadChars(chan, objPtr, TCL_INDEX_NONE,
	    memcmp(string, "\xEF\xBB\xBF", 3)) == TCL_IO_FAILURE) {
	Tcl_CloseEx(interp, chan, 0);
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"couldn't read file \"%s\": %s",
		TclGetString(pathPtr), Tcl_PosixError(interp)));
	Tcl_DecrRefCount(objPtr);
	return TCL_ERROR;
    }
1921
1922
1923
1924
1925
1926
1927
1928

1929
1930
1931
1932
1933
1934
1935
1930
1931
1932
1933
1934
1935
1936

1937
1938
1939
1940
1941
1942
1943
1944







-
+







    TclNRAddCallback(interp, EvalFileCallback, oldScriptFile, pathPtr, objPtr,
	    NULL);
    return TclNREvalObjEx(interp, objPtr, 0, NULL, INT_MIN);
}

static int
EvalFileCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *oldScriptFile = (Tcl_Obj *)data[0];
    Tcl_Obj *pathPtr = (Tcl_Obj *)data[1];
    Tcl_Obj *objPtr = (Tcl_Obj *)data[2];
1948
1949
1950
1951
1952
1953
1954
1955

1956
1957

1958
1959
1960
1961
1962

1963
1964
1965
1966
1967
1968
1969
1957
1958
1959
1960
1961
1962
1963

1964
1965

1966
1967
1968
1969
1970

1971
1972
1973
1974
1975
1976
1977
1978







-
+

-
+




-
+







    if (result == TCL_RETURN) {
	result = TclUpdateReturnInfo(iPtr);
    } else if (result == TCL_ERROR) {
	/*
	 * Record information about where the error occurred.
	 */

	size_t length;
	Tcl_Size length;
	const char *pathString = TclGetStringFromObj(pathPtr, &length);
	const unsigned int limit = 150;
	const int limit = 150;
	int overflow = (length > limit);

	Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
		"\n    (file \"%.*s%s\" line %d)",
		(overflow ? limit : (unsigned int)length), pathString,
		(overflow ? limit : (int)length), pathString,
		(overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
    }

    Tcl_DecrRefCount(objPtr);
    return result;
}

2005
2006
2007
2008
2009
2010
2011
2012

2013
2014
2015
2016
2017
2018
2019
2014
2015
2016
2017
2018
2019
2020

2021
2022
2023
2024
2025
2026
2027
2028







-
+







 *	this is implemented in the C library as a thread-local value , but this
 *	is *really* unsafe to assume!
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Modifies the the Tcl error code value.
 *	Modifies the Tcl error code value.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetErrno(
    int err)			/* The new value. */
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
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
2095
2096







-
+










-
+
-













-
+







    Tcl_Interp *interp)		/* Interpreter to set the errorCode of */
{
    const char *id, *msg;

    msg = Tcl_ErrnoMsg(errno);
    id = Tcl_ErrnoId();
    if (interp) {
	Tcl_SetErrorCode(interp, "POSIX", id, msg, NULL);
	Tcl_SetErrorCode(interp, "POSIX", id, msg, (char *)NULL);
    }
    return msg;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FSStat --
 *	Calls 'statProc' of the filesystem corresponding to pathPtr.
 *
 *	Replaces the standard library routines stat.
 *	Replaces the standard library "stat" routine.
 *
 *
 * Results:
 *	See stat documentation.
 *
 * Side effects:
 *	See stat documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FSStat(
    Tcl_Obj *pathPtr,		/* Pathname of the file to call stat on (in
				 *  current CP). */
				 *  current system encoding). */
    Tcl_StatBuf *buf)		/* A buffer to hold the results of the call to
				 *  stat. */
{
    const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);

    if (fsPtr != NULL && fsPtr->statProc != NULL) {
	return fsPtr->statProc(pathPtr, buf);
2109
2110
2111
2112
2113
2114
2115
2116

2117
2118
2119
2120
2121
2122
2123
2117
2118
2119
2120
2121
2122
2123

2124
2125
2126
2127
2128
2129
2130
2131







-
+







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

int
Tcl_FSLstat(
    Tcl_Obj *pathPtr,		/* Pathname of the file to call stat on (in
				   current CP). */
				 * current system encoding). */
    Tcl_StatBuf *buf)		/* Filled with results of that call to stat. */
{
    const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);

    if (fsPtr != NULL) {
	if (fsPtr->lstatProc != NULL) {
	    return fsPtr->lstatProc(pathPtr, buf);
2146
2147
2148
2149
2150
2151
2152
2153


2154
2155
2156
2157
2158
2159
2160
2154
2155
2156
2157
2158
2159
2160

2161
2162
2163
2164
2165
2166
2167
2168
2169







-
+
+







 *	See access documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FSAccess(
    Tcl_Obj *pathPtr,		/* Pathname of file to access (in current CP). */
    Tcl_Obj *pathPtr,		/* Pathname of file to access (in current
				 * system encoding). */
    int mode)			/* Permission setting. */
{
    const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);

    if (fsPtr != NULL && fsPtr->accessProc != NULL) {
	return fsPtr->accessProc(pathPtr, mode);
    }
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
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
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
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







-
+



-
-
-
-
-
-
-
-
-


-
+






-
+


















-
+









-
+







Tcl_Channel
Tcl_FSOpenFileChannel(
    Tcl_Interp *interp,		/* Interpreter for error reporting, or NULL */
    Tcl_Obj *pathPtr,		/* Pathname of file to open. */
    const char *modeString,	/* A list of POSIX open modes or a string such
				 * as "rw". */
    int permissions)		/* What modes to use if opening the file
				   involves creating it. */
				 * involves creating it. */
{
    const Tcl_Filesystem *fsPtr;
    Tcl_Channel retVal = NULL;


    if (Tcl_FSGetNormalizedPath(interp, pathPtr) == NULL) {
	/*
	 * Return the correct error message.
	 */
	return NULL;
    }

    fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
    if (fsPtr != NULL && fsPtr->openFileChannelProc != NULL) {
	int mode, seekFlag, binary;
	int mode, modeFlags;

	/*
	 * Parse the mode to determine whether to seek at the outset
	 * and/or set the channel into binary mode.
	 */

	mode = TclGetOpenModeEx(interp, modeString, &seekFlag, &binary);
	mode = TclGetOpenMode(interp, modeString, &modeFlags);
	if (mode == -1) {
	    return NULL;
	}

	/*
	 * Open the file.
	 */

	retVal = fsPtr->openFileChannelProc(interp, pathPtr, mode,
		permissions);
	if (retVal == NULL) {
	    return NULL;
	}

	/*
	 * Seek and/or set binary mode as determined above.
	 */

	if (seekFlag && Tcl_Seek(retVal, (Tcl_WideInt) 0, SEEK_END)
	if ((modeFlags & 1) && Tcl_Seek(retVal, (Tcl_WideInt) 0, SEEK_END)
		< (Tcl_WideInt) 0) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"could not seek to end of file while opening \"%s\": %s",
			TclGetString(pathPtr), Tcl_PosixError(interp)));
	    }
	    Tcl_CloseEx(NULL, retVal, 0);
	    return NULL;
	}
	if (binary) {
	if (modeFlags & CHANNEL_RAW_MODE) {
	    Tcl_SetChannelOption(interp, retVal, "-translation", "binary");
	}
	return retVal;
    }

    /*
     * File doesn't belong to any filesystem that can open it.
2279
2280
2281
2282
2283
2284
2285

2286



2287
2288
2289
2290






2291
2292
2293
2294
2295
2296
2297
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290




2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303







+

+
+
+
-
-
-
-
+
+
+
+
+
+







int
Tcl_FSUtime(
    Tcl_Obj *pathPtr,		/* Pathaname of file to call uTimeProc on */
    struct utimbuf *tval)	/* Specifies the access/modification
				 * times to use. Should not be modified. */
{
    const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
    int err;

    if (fsPtr == NULL) {
	err = ENOENT;
    } else {
    if (fsPtr != NULL && fsPtr->utimeProc != NULL) {
	return fsPtr->utimeProc(pathPtr, tval);
    }
    /* TODO: set errno here? Tcl_SetErrno(ENOENT); */
	if (fsPtr->utimeProc != NULL) {
	    return fsPtr->utimeProc(pathPtr, tval);
	}
	err = ENOTSUP;
    }
    Tcl_SetErrno(err);
    return -1;
}

/*
 *----------------------------------------------------------------------
 *
 * NativeFileAttrStrings --
2470
2471
2472
2473
2474
2475
2476
2477

2478
2479
2480

2481
2482
2483
2484
2485
2486
2487
2476
2477
2478
2479
2480
2481
2482

2483
2484
2485

2486
2487
2488
2489
2490
2491
2492
2493







-
+


-
+







	}
	return result;
    } else if (listObj != NULL) {
	/*
	 * It's a non-constant attribute list, so do a literal search.
	 */

	int i, objc;
	Tcl_Size i, objc;
	Tcl_Obj **objv;

	if (Tcl_ListObjGetElements(NULL, listObj, &objc, &objv) != TCL_OK) {
	if (TclListObjGetElements(NULL, listObj, &objc, &objv) != TCL_OK) {
	    TclDecrRefCount(listObj);
	    return TCL_ERROR;
	}
	for (i=0 ; i<objc ; i++) {
	    if (!strcmp(attributeName, TclGetString(objv[i]))) {
		TclDecrRefCount(listObj);
		*indexPtr = i;
2617
2618
2619
2620
2621
2622
2623
2624

2625
2626
2627
2628
2629
2630
2631
2623
2624
2625
2626
2627
2628
2629

2630
2631
2632
2633
2634
2635
2636
2637







-
+







	 * current directory.
	 */

	fsRecPtr = FsGetFirstFilesystem();
	Claim();
	for (; (retVal == NULL) && (fsRecPtr != NULL);
		fsRecPtr = fsRecPtr->nextPtr) {
	    ClientData retCd;
	    void *retCd;
	    TclFSGetCwdProc2 *proc2;

	    if (fsRecPtr->fsPtr->getCwdProc == NULL) {
		continue;
	    }

	    if (fsRecPtr->fsPtr->version == TCL_FILESYSTEM_VERSION_1) {
2643
2644
2645
2646
2647
2648
2649
2650
2651



2652
2653
2654
2655
2656
2657
2658
2649
2650
2651
2652
2653
2654
2655


2656
2657
2658
2659
2660
2661
2662
2663
2664
2665







-
-
+
+
+







		 */

		retVal = fsRecPtr->fsPtr->internalToNormalizedProc(retCd);
		Tcl_IncrRefCount(retVal);
		norm = TclFSNormalizeAbsolutePath(interp,retVal);
		if (norm != NULL) {
		    /*
		     * Assign to global storage the pathname of the current directory
		     * and copy it into thread-local storage as well.
		     * Assign to global storage the pathname of the current
		     * directory and copy it into thread-local storage as
		     * well.
		     *
		     * At system startup multiple threads could in principle
		     * call this function simultaneously, which is a little
		     * peculiar, but should be fine given the mutex locks in
		     * FSUPdateCWD.  Once some value is assigned to the global
		     * variable the 'else' branch below is always taken, which
		     * is simpler.
2717
2718
2719
2720
2721
2722
2723
2724

2725
2726
2727
2728
2729
2730
2731
2724
2725
2726
2727
2728
2729
2730

2731
2732
2733
2734
2735
2736
2737
2738







-
+







	 * if it is out-of-date. This allows an error to be thrown if, for
	 * example, the permissions on the current working directory have
	 * changed.
	 */

	const Tcl_Filesystem *fsPtr =
		Tcl_FSGetFileSystemForPath(tsdPtr->cwdPathPtr);
	ClientData retCd = NULL;
	void *retCd = NULL;
	Tcl_Obj *retVal, *norm;

	if (fsPtr == NULL || fsPtr->getCwdProc == NULL) {
	    /*
	     * There is no corresponding filesystem or the filesystem does not
	     * have a getCwd routine. Just assume current local value is ok.
	     */
2758
2759
2760
2761
2762
2763
2764
2765

2766
2767
2768
2769
2770
2771
2772
2765
2766
2767
2768
2769
2770
2771

2772
2773
2774
2775
2776
2777
2778
2779







-
+








	    retVal = fsPtr->internalToNormalizedProc(retCd);
	    Tcl_IncrRefCount(retVal);
	}

	if (retVal == NULL) {
	    /*
	     * The current directory could not not determined.  Reset the
	     * The current directory could not be determined.  Reset the
	     * current direcory to ensure, for example, that 'pwd' does actually
	     * throw the correct error in Tcl.  This is tested for in the test
	     * suite on unix.
	     */

	    FsUpdateCwd(NULL, NULL);
	    goto cdDidNotChange;
2790
2791
2792
2793
2794
2795
2796
2797

2798
2799
2800
2801
2802
2803
2804
2797
2798
2799
2800
2801
2802
2803

2804
2805
2806
2807
2808
2809
2810
2811







-
+







	     * Determine whether the filesystem's answer is the same as the
	     * cached local value.  Since both 'norm' and 'tsdPtr->cwdPathPtr'
	     * are normalized pathnames, do something more efficient than
	     * calling 'Tcl_FSEqualPaths', and in addition avoid a nasty
	     * infinite loop bug when trying to normalize tsdPtr->cwdPathPtr.
	     */

	    size_t len1, len2;
	    Tcl_Size len1, len2;
	    const char *str1, *str2;

	    str1 = TclGetStringFromObj(tsdPtr->cwdPathPtr, &len1);
	    str2 = TclGetStringFromObj(norm, &len2);
	    if ((len1 == len2) && (strcmp(str1, str2) == 0)) {
		/*
		 * The pathname values are equal so retain the old pathname
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
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







-
-
+
+












-
+







	if (normDirName == NULL) {
	    /* Not really true, but what else to do? */
	    Tcl_SetErrno(ENOENT);
	    return -1;
	}

	if (fsPtr == &tclNativeFilesystem) {
	    ClientData cd;
	    ClientData oldcd = tsdPtr->cwdClientData;
	    void *cd;
	    void *oldcd = tsdPtr->cwdClientData;

	    /*
	     * Assume that the native filesystem has a getCwdProc and that it
	     * is at version 2.
	     */

	    TclFSGetCwdProc2 *proc2 = (TclFSGetCwdProc2 *) fsPtr->getCwdProc;

	    cd = proc2(oldcd);
	    if (cd != oldcd) {
		/*
		 * Call getCwdProc() and store the resulting internal handle to
		 * compare things with it later.  This might might not be
		 * compare things with it later.  This might not be
		 * exactly the same string as that of the fully normalized
		 * pathname.  For example, for the Windows internal handle the
		 * separator is the backslash character.  On Unix it might well
		 * be true that the internal handle is the fully normalized
		 * pathname and one could simply use:
		 *	cd = Tcl_FSGetNativePath(pathPtr);
		 * but this can't be guaranteed in the general case.  In fact,
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
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







-
-
+
+



-
+

















-
-
+
+







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

int
Tcl_FSLoadFile(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Obj *pathPtr,		/* Pathname of the file containing the dynamic shared object.
				 */
    Tcl_Obj *pathPtr,		/* Pathname of the file containing the dynamic
				 * shared object. */
    const char *sym1, const char *sym2,
				/* Names of two functions to find in the
				 * dynamic shared object. */
    Tcl_PackageInitProc **proc1Ptr, Tcl_PackageInitProc **proc2Ptr,
    Tcl_LibraryInitProc **proc1Ptr, Tcl_LibraryInitProc **proc2Ptr,
				/* Places to store pointers to the functions
				 * named by sym1 and sym2. */
    Tcl_LoadHandle *handlePtr,	/* A place to store the token for the loaded
				 * object.  Can be passed to
				 * (*unloadProcPtr)() to unload the file. */
    TCL_UNUSED(Tcl_FSUnloadFileProc **))
{
    const char *symbols[3];
    void *procPtrs[2];
    int res;

    symbols[0] = sym1;
    symbols[1] = sym2;
    symbols[2] = NULL;

    res = Tcl_LoadFile(interp, pathPtr, symbols, 0, procPtrs, handlePtr);
    if (res == TCL_OK) {
	*proc1Ptr = (Tcl_PackageInitProc *) procPtrs[0];
	*proc2Ptr = (Tcl_PackageInitProc *) procPtrs[1];
	*proc1Ptr = (Tcl_LibraryInitProc *) procPtrs[0];
	*proc2Ptr = (Tcl_LibraryInitProc *) procPtrs[1];
    } else {
	*proc1Ptr = *proc2Ptr = NULL;
    }

    return res;
}

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
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







+
+
+
+
+
+
+










-
-
+
+

-
-
+
+

-





-
+







 * denied removal.
 *
 * Doing the unlink is also an issue within docker containers, whose AUFS
 * bungles this as well, see
 *     https://github.com/dotcloud/docker/issues/1911
 *
 */

#ifdef _WIN32
#define getenv(x) _wgetenv(L##x)
#define atoi(x) _wtoi(x)
#else
#define WCHAR char
#endif

static int
skipUnlink(
    Tcl_Obj *shlibFile)
{
    /*
     * Unlinking is not performed in the following cases:
     *
     * 1. The operating system is HPUX.
     *
     * 2.   If the environment variable TCL_TEMPLOAD_NO_UNLINK is present and
     * set to true (an integer > 0)
     * 2. If the environment variable TCL_TEMPLOAD_NO_UNLINK is present and
     *    set to true (an integer > 0)
     *
     * 3. TCL_TEMPLOAD_NO_UNLINK is not true (an integer > 0) and AUFS filesystem can be detected (using statfs, if available).
     *
     * 3. TCL_TEMPLOAD_NO_UNLINK is not true (an integer > 0) and AUFS
     *    filesystem can be detected (using statfs, if available).
     */


#ifdef hpux
    (void)shlibFile;
    return 1;
#else
    char *skipstr = getenv("TCL_TEMPLOAD_NO_UNLINK");
    WCHAR *skipstr = getenv("TCL_TEMPLOAD_NO_UNLINK");

    if (skipstr && (skipstr[0] != '\0')) {
	return atoi(skipstr);
    }

#ifndef TCL_TEMPLOAD_NO_UNLINK
    (void)shlibFile;
3212
3213
3214
3215
3216
3217
3218

3219

3220
3221
3222
3223
3224
3225
3226
3227
3228

3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3225
3226
3227
3228
3229
3230
3231
3232

3233
3234
3235
3236
3237
3238
3239
3240
3241

3242
3243







3244
3245
3246
3247
3248
3249
3250







+
-
+








-
+

-
-
-
-
-
-
-







    /*
     * The platform supports loading a dynamic shared object from memory.
     * Create a sufficiently large buffer, read the file into it, and then load
     * the dynamic shared object from the buffer:
     */

    {
	Tcl_Size ret;
	int ret, size;
	size_t size;
	void *buffer;
	Tcl_StatBuf statBuf;
	Tcl_Channel data;

	ret = Tcl_FSStat(pathPtr, &statBuf);
	if (ret < 0) {
	    goto mustCopyToTempAnyway;
	}
	size = (int) statBuf.st_size;
	size = statBuf.st_size;

	/*
	 * Tcl_Read takes an int:  Determine whether the file size is wide.
	 */

	if (size != (Tcl_WideInt) statBuf.st_size) {
	    goto mustCopyToTempAnyway;
	}
	data = Tcl_FSOpenFileChannel(interp, pathPtr, "rb", 0666);
	if (!data) {
	    goto mustCopyToTempAnyway;
	}
	buffer = TclpLoadMemoryGetBuffer(interp, size);
	if (!buffer) {
	    Tcl_CloseEx(interp, data, 0);
3444
3445
3446
3447
3448
3449
3450
3451

3452
3453
3454
3455
3456
3457
3458
3451
3452
3453
3454
3455
3456
3457

3458
3459
3460
3461
3462
3463
3464
3465







-
+







 *	from the virtual filesystem to a native filesystem.
 *
 *----------------------------------------------------------------------
 */

static void *
DivertFindSymbol(
    Tcl_Interp *interp, 	/* The relevant interpreter. */
    Tcl_Interp *interp,		/* The relevant interpreter. */
    Tcl_LoadHandle loadHandle,	/* A handle to the diverted module. */
    const char *symbol)		/* The name of symbol to resolve. */
{
    FsDivertLoad *tvdlPtr = (FsDivertLoad *) loadHandle->clientData;
    Tcl_LoadHandle originalHandle = tvdlPtr->loadHandle;

    return originalHandle->findSymbolProcPtr(interp, originalHandle, symbol);
3495
3496
3497
3498
3499
3500
3501
3502

3503
3504
3505
3506
3507
3508
3509
3502
3503
3504
3505
3506
3507
3508

3509
3510
3511
3512
3513
3514
3515
3516







-
+








    /*
     * Determine which filesystem contains the temporary copy of the file.
     */

    if (tvdlPtr->divertedFilesystem == NULL) {
	/*
	 * Use the function for the native filsystem, which works works even at
	 * Use the function for the native filsystem, which works even at
	 * this late stage.
	 */

	TclpDeleteFile(tvdlPtr->divertedFileNativeRep);
	NativeFreeInternalRep(tvdlPtr->divertedFileNativeRep);
    } else {
	/*
3558
3559
3560
3561
3562
3563
3564
3565

3566
3567
3568
3569
3570
3571
3572
3565
3566
3567
3568
3569
3570
3571

3572
3573
3574
3575
3576
3577
3578
3579







-
+







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

void *
Tcl_FindSymbol(
    Tcl_Interp *interp,		/* The relevant interpreter. */
    Tcl_LoadHandle loadHandle,	/* A handle for the loaded object. */
    const char *symbol)		/* The name name of the symbol to resolve. */
    const char *symbol)		/* The name of the symbol to resolve. */
{
    return loadHandle->findSymbolProcPtr(interp, loadHandle, symbol);
}

/*
 *----------------------------------------------------------------------
 *
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3598
3599
3600
3601
3602
3603
3604





















































































3605
3606
3607
3608
3609
3610
3611







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	return TCL_ERROR;
    }
    if (handle->unloadFileProcPtr != NULL) {
	handle->unloadFileProcPtr(handle);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclFSUnloadTempFile --
 *
 *	Unloads an object loaded via temporary file from a virtual filesystem
 *	to a native filesystem.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Frees resources for the loaded object and deletes the temporary file.
 *
 *----------------------------------------------------------------------
 */

void
TclFSUnloadTempFile(
    Tcl_LoadHandle loadHandle)	/* A handle for the object, as provided by a
				 *  previous call to Tcl_FSLoadFile(). */
{
    FsDivertLoad *tvdlPtr = (FsDivertLoad *) loadHandle;

    if (tvdlPtr == NULL) {
	/*
	 * tvdlPtr was provided by Tcl_LoadFile so it should not be NULL here.
	 */
	return;
    }

    if (tvdlPtr->unloadProcPtr != NULL) {
	/*
	 * 'unloadProcPtr' must be called first so that the shared library is
	 * actually unloaded by the OS. Otherwise, the following 'delete' may
	 * well fail because the shared library is still in use.
	 */

	tvdlPtr->unloadProcPtr(tvdlPtr->loadHandle);
    }

    if (tvdlPtr->divertedFilesystem == NULL) {
	/*
	 * Call the function for the native fileystem, which works even at this
	 * late stage.
	 */

	TclpDeleteFile(tvdlPtr->divertedFileNativeRep);
	NativeFreeInternalRep(tvdlPtr->divertedFileNativeRep);
    } else {
	/*
	 * Remove the temporary file that was created.  If encodings have
	 * already been freed because the interpreter is exiting this may
	 * crash.
	 */

	if (tvdlPtr->divertedFilesystem->deleteFileProc(tvdlPtr->divertedFile)
		!= TCL_OK) {
	    /*
	     * This may have happened because Tcl is exiting and encodings may
	     * have already been deleted, or something else the filesystem
	     * depends on may be gone.
	     *
	     * TO DO:  Figure out how to delete this file more robustly, or
	     * give the filesystem the information it needs to delete the file
	     * more robustly.  One problem might be that the filesystem cannot
	     * extract the information it needs from the above pathname object
	     * because Tcl's entire filesystem apparatus (the code in this
	     * file) has been finalized and there is no way to get the native
	     * handle of the file.
	     */
	}

	/*
	 * This also decrements the refCount of the Tcl_Filesystem
	 * corresponding to this file. which might case filesystem to be freed
	 * if Tcl is exiting.
	 */

	Tcl_DecrRefCount(tvdlPtr->divertedFile);
    }

    Tcl_Free(tvdlPtr);
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_FSLink --
 *
 *	Creates or inspects a link by calling 'linkProc' of the filesystem
3714
3715
3716
3717
3718
3719
3720
3721
3722

3723
3724
3725
3726
3727
3728
3729







3730
3731
3732
3733
3734
3735
3736
3636
3637
3638
3639
3640
3641
3642


3643

3644
3645
3646
3647


3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661







-
-
+
-




-
-
+
+
+
+
+
+
+







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

Tcl_Obj *
Tcl_FSLink(
    Tcl_Obj *pathPtr,		/* Pathaname of file. */
    Tcl_Obj *toPtr,		/*
				 * NULL or the pathname of a file to link to.
    Tcl_Obj *toPtr,		/* NULL or the pathname of a file to link to. */
				 */
    int linkAction)		/* Action to perform. */
{
    const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);

    if (fsPtr != NULL && fsPtr->linkProc != NULL) {
	return fsPtr->linkProc(pathPtr, toPtr, linkAction);
    if (fsPtr) {
	if (fsPtr->linkProc == NULL) {
	    Tcl_SetErrno(ENOTSUP);
	    return NULL;
	} else {
	    return fsPtr->linkProc(pathPtr, toPtr, linkAction);
	}
    }

    /*
     * If S_IFLNK isn't defined the machine doesn't support symbolic links, so
     * the file can't possibly be a symbolic link. Generate an EINVAL error,
     * which is what happens on machines that do support symbolic links when
     * readlink is called for a file that isn't a symbolic link.
3779
3780
3781
3782
3783
3784
3785

3786
3787
3788
3789





3790
3791
3792
3793
3794
3795
3796
3704
3705
3706
3707
3708
3709
3710
3711




3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723







+
-
-
-
-
+
+
+
+
+







    Claim();
    while (fsRecPtr != NULL) {
	if (fsRecPtr->fsPtr->listVolumesProc != NULL) {
	    Tcl_Obj *thisFsVolumes = fsRecPtr->fsPtr->listVolumesProc();

	    if (thisFsVolumes != NULL) {
		Tcl_ListObjAppendList(NULL, resultPtr, thisFsVolumes);
		/*
		/* The refCount of each list returned by a `listVolumesProc` is
		 * already incremented.  Do not hang onto the list, though.  It
		 * belongs to the filesystem.  Add its contents to * the result
		 * we are building, and then decrement the refCount.  */
		 * The refCount of each list returned by a `listVolumesProc`
		 * is already incremented.  Do not hang onto the list, though.
		 * It belongs to the filesystem.  Add its contents to the
		 * result we are building, and then decrement the refCount.
		 */
		Tcl_DecrRefCount(thisFsVolumes);
	    }
	}
	fsRecPtr = fsRecPtr->nextPtr;
    }
    Disclaim();

3861
3862
3863
3864
3865
3866
3867
3868

3869
3870
3871
3872
3873
3874

3875
3876
3877
3878
3879
3880
3881
3788
3789
3790
3791
3792
3793
3794

3795
3796
3797
3798
3799
3800

3801
3802
3803
3804
3805
3806
3807
3808







-
+





-
+







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

Tcl_Obj *
Tcl_FSSplitPath(
    Tcl_Obj *pathPtr,		/* The pathname to split. */
    int *lenPtr)		/* A place to hold the number of pathname
    Tcl_Size *lenPtr)		/* A place to hold the number of pathname
				 * elements. */
{
    Tcl_Obj *result = NULL;	/* Just to squelch gcc warnings. */
    const Tcl_Filesystem *fsPtr;
    char separator = '/';
    int driveNameLength;
    Tcl_Size driveNameLength;
    const char *p;

    /*
     * Perform platform-specific splitting.
     */

    if (TclFSGetPathType(pathPtr, &fsPtr,
3913
3914
3915
3916
3917
3918
3919
3920

3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933

3934
3935
3936
3937
3938
3939
3940
3941
3840
3841
3842
3843
3844
3845
3846

3847
3848
3849
3850
3851
3852
3853
3854






3855

3856
3857
3858
3859
3860
3861
3862







-
+







-
-
-
-
-
-
+
-








    /*
     * Add the remaining pathname elements to the list.
     */

    for (;;) {
	const char *elementStart = p;
	int length;
	Tcl_Size length;

	while ((*p != '\0') && (*p != separator)) {
	    p++;
	}
	length = p - elementStart;
	if (length > 0) {
	    Tcl_Obj *nextElt;

	    if (elementStart[0] == '~') {
		TclNewLiteralStringObj(nextElt, "./");
		Tcl_AppendToObj(nextElt, elementStart, length);
	    } else {
		nextElt = Tcl_NewStringObj(elementStart, length);
	    nextElt = Tcl_NewStringObj(elementStart, length);
	    }
	    Tcl_ListObjAppendElement(NULL, result, nextElt);
	}
	if (*p++ == '\0') {
	    break;
	}
    }

3964
3965
3966
3967
3968
3969
3970

3971

3972
3973
3974
3975
3976
3977
3978

3979
3980
3981
3982
3983
3984
3985
3885
3886
3887
3888
3889
3890
3891
3892

3893
3894
3895
3896
3897
3898
3899

3900
3901
3902
3903
3904
3905
3906
3907







+
-
+






-
+







Tcl_PathType
TclGetPathType(
    Tcl_Obj *pathPtr,		/* Pathname to determine type of. */
    const Tcl_Filesystem **filesystemPtrPtr,
				/* If not NULL, a place in which to store a
				 * pointer to the filesystem for this pathname
				 * if it is absolute. */
    Tcl_Size *driveNameLengthPtr,
    int *driveNameLengthPtr,	/* If not NULL, a place in which to store the
				/* If not NULL, a place in which to store the
				 * length of the volume name. */
    Tcl_Obj **driveNameRef)	/* If not NULL, for an absolute pathname, a
				 * place to store a pointer to an object with a
				 * refCount of 1, and whose value is the name
				 * of the volume. */
{
    size_t pathLen;
    Tcl_Size pathLen;
    const char *path = TclGetStringFromObj(pathPtr, &pathLen);
    Tcl_PathType type;

    type = TclFSNonnativePathType(path, pathLen, filesystemPtrPtr,
	    driveNameLengthPtr, driveNameRef);

    if (type != TCL_PATH_ABSOLUTE) {
4013
4014
4015
4016
4017
4018
4019
4020

4021
4022
4023
4024

4025
4026


4027
4028
4029

4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045

4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062

4063
4064
4065
4066

4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077

4078
4079
4080
4081

4082
4083
4084
4085
4086
4087

4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108

4109
4110
4111
4112
4113
4114
4115
3935
3936
3937
3938
3939
3940
3941

3942
3943
3944
3945
3946
3947


3948
3949

3950

3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966

3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983

3984
3985
3986
3987

3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998

3999
4000
4001
4002

4003
4004
4005
4006
4007
4008

4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029

4030
4031
4032
4033
4034
4035
4036
4037







-
+




+
-
-
+
+
-

-
+















-
+
















-
+



-
+










-
+



-
+





-
+




















-
+







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

Tcl_PathType
TclFSNonnativePathType(
    const char *path,		/* Pathname to determine the type of. */
    int pathLen,		/* Length of the pathname. */
    Tcl_Size pathLen,		/* Length of the pathname. */
    const Tcl_Filesystem **filesystemPtrPtr,
				/* If not NULL, a  place to store a pointer to
				 * the filesystem for this pathname when it is
				 * an absolute pathname. */
    Tcl_Size *driveNameLengthPtr,
    int *driveNameLengthPtr,	/* If not NULL, a place to store the length of
				 * the volume name if the pathname is absolute.
				/* If not NULL, a place to store the length of
				 * the volume name if the pathname is absolute. */
				 */
    Tcl_Obj **driveNameRef)	/* If not NULL, a place to store a pointer to
				 * an object having its its refCount already
				 * an object having its refCount already
				 * incremented, and contining the name of the
				 * volume if the pathname is absolute. */
{
    FilesystemRecord *fsRecPtr;
    Tcl_PathType type = TCL_PATH_RELATIVE;

    /*
     * Determine whether the given pathname is an absolute pathname on some
     * filesystem other than the native filesystem.
     */

    fsRecPtr = FsGetFirstFilesystem();
    Claim();
    while (fsRecPtr != NULL) {
	/*
	 * Skip the the native filesystem because otherwise some of the tests
	 * Skip the native filesystem because otherwise some of the tests
	 * in the Tcl testsuite might fail because some of the tests
	 * artificially change the current platform (between win, unix) but the
	 * list of volumes obtained by calling fsRecPtr->fsPtr->listVolumesProc
	 * reflects the current (real) platform only. In particular, on Unix
	 * '/' matchs the beginning of certain absolute Windows pathnames
	 * starting '//' and those tests go wrong.
	 *
	 * There is another reason to skip the native filesystem:  Since the
	 * tclFilename.c code has nice fast 'absolute path' checkers, there is
	 * no reason to waste time doing that in this frequently-called
	 * function.  It is better to save the overhead of the native
	 * filesystem continuously returning a list of volumes.
	 */

	if ((fsRecPtr->fsPtr != &tclNativeFilesystem)
		&& (fsRecPtr->fsPtr->listVolumesProc != NULL)) {
	    int numVolumes;
	    Tcl_Size numVolumes;
	    Tcl_Obj *thisFsVolumes = fsRecPtr->fsPtr->listVolumesProc();

	    if (thisFsVolumes != NULL) {
		if (Tcl_ListObjLength(NULL, thisFsVolumes, &numVolumes)
		if (TclListObjLength(NULL, thisFsVolumes, &numVolumes)
			!= TCL_OK) {
		    /*
		     * This is VERY bad; the listVolumesProc didn't return a
		     * valid list. Set numVolumes to -1 to skip the loop below
		     * and just return with the current value of 'type'.
		     *
		     * It would be better to signal an error here, but
		     * Tcl_Panic seems a bit excessive.
		     */

		    numVolumes = -1;
		    numVolumes = TCL_INDEX_NONE;
		}
		while (numVolumes > 0) {
		    Tcl_Obj *vol;
		    size_t len;
		    Tcl_Size len;
		    const char *strVol;

		    numVolumes--;
		    Tcl_ListObjIndex(NULL, thisFsVolumes, numVolumes, &vol);
		    strVol = TclGetStringFromObj(vol,&len);
		    if ((size_t) pathLen < len) {
		    if (pathLen < len) {
			continue;
		    }
		    if (strncmp(strVol, path, len) == 0) {
			type = TCL_PATH_ABSOLUTE;
			if (filesystemPtrPtr != NULL) {
			    *filesystemPtrPtr = fsRecPtr->fsPtr;
			}
			if (driveNameLengthPtr != NULL) {
			    *driveNameLengthPtr = len;
			}
			if (driveNameRef != NULL) {
			    *driveNameRef = vol;
			    Tcl_IncrRefCount(vol);
			}
			break;
		    }
		}
		Tcl_DecrRefCount(thisFsVolumes);
		if (type == TCL_PATH_ABSOLUTE) {
		    /*
		     * No need to to examine additional filesystems.
		     * No need to examine additional filesystems.
		     */

		    break;
		}
	    }
	}
	fsRecPtr = fsRecPtr->nextPtr;
4136
4137
4138
4139
4140
4141
4142
4143

4144
4145
4146
4147
4148
4149
4150
4058
4059
4060
4061
4062
4063
4064

4065
4066
4067
4068
4069
4070
4071
4072







-
+







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

int
Tcl_FSRenameFile(
    Tcl_Obj *srcPathPtr,	/* The pathname of a file or directory to be
				   renamed. */
				 * renamed. */
    Tcl_Obj *destPathPtr)	/* The new pathname for the file. */
{
    int retVal = -1;
    const Tcl_Filesystem *fsPtr, *fsPtr2;

    fsPtr = Tcl_FSGetFileSystemForPath(srcPathPtr);
    fsPtr2 = Tcl_FSGetFileSystemForPath(destPathPtr);
4296
4297
4298
4299
4300
4301
4302

4303



4304
4305
4306
4307






4308
4309
4310
4311
4312
4313
4314
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229




4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242







+

+
+
+
-
-
-
-
+
+
+
+
+
+







 */

int
Tcl_FSDeleteFile(
    Tcl_Obj *pathPtr)		/* Pathname of file to be removed (UTF-8). */
{
    const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
    int err;

    if (fsPtr == NULL) {
	err = ENOENT;
    } else {
    if (fsPtr != NULL && fsPtr->deleteFileProc != NULL) {
	return fsPtr->deleteFileProc(pathPtr);
    }
    Tcl_SetErrno(ENOENT);
	if (fsPtr->deleteFileProc != NULL) {
	    return fsPtr->deleteFileProc(pathPtr);
	}
	err = ENOTSUP;
    }
    Tcl_SetErrno(err);
    return -1;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_FSCreateDirectory --
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
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266




4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
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







+

+
+
+
-
-
-
-
+
+
+
+
+
+








-
+














-
-
+
+
-


-
-
-
-
+
+
+
+







 */

int
Tcl_FSCreateDirectory(
    Tcl_Obj *pathPtr)		/* Pathname of directory to create (UTF-8). */
{
    const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
    int err;

    if (fsPtr == NULL) {
	err = ENOENT;
    } else {
    if (fsPtr != NULL && fsPtr->createDirectoryProc != NULL) {
	return fsPtr->createDirectoryProc(pathPtr);
    }
    Tcl_SetErrno(ENOENT);
	if (fsPtr->createDirectoryProc != NULL) {
	    return fsPtr->createDirectoryProc(pathPtr);
	}
	err = ENOTSUP;
    }
    Tcl_SetErrno(err);
    return -1;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_FSCopyDirectory --
 *
 *	If both pathnames correspond to the the same filesystem, calls
 *	If both pathnames correspond to the same filesystem, calls
 *	'copyDirectoryProc' of that filesystem.
 *
 * Results:
 *	A standard Tcl return code, or -1 if no 'copyDirectoryProc' is found.
 *
 * Side effects:
 *	A directory may be copied. POSIX error 'EXDEV' is set if no
 *	copyDirectoryProc is found.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_FSCopyDirectory(
    Tcl_Obj *srcPathPtr,	/*
				 * The pathname of the directory to be copied.
    Tcl_Obj *srcPathPtr,	/* The pathname of the directory to be
				 * copied. */
				 */
    Tcl_Obj *destPathPtr,	/* The pathname of the target directory. */
    Tcl_Obj **errorPtr)		/* If not NULL, and there is an error, a place
				 *  to store a pointer to a new object, with
				 *  its refCount already incremented, and
				 *  containing the pathname name of file
				 *  causing the error. */
				 * to store a pointer to a new object, with
				 * its refCount already incremented, and
				 * containing the pathname name of file
				 * causing the error. */
{
    int retVal = -1;
    const Tcl_Filesystem *fsPtr, *fsPtr2;

    fsPtr = Tcl_FSGetFileSystemForPath(srcPathPtr);
    fsPtr2 = Tcl_FSGetFileSystemForPath(destPathPtr);

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
4436
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







-
+
-




-
+

-
+
-



-
+


+
+
+
+






-
+







 *	removeDirectoryProc is found.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_FSRemoveDirectory(
    Tcl_Obj *pathPtr,		/* The pathname of the directory to be removed.
    Tcl_Obj *pathPtr,		/* The pathname of the directory to be removed. */
                                 */
    int recursive,		/* If zero, removes only an empty directory.
				 * Otherwise, removes the directory and all its
				 * contents.  */
    Tcl_Obj **errorPtr)		/* If not NULL and an error occurs, stores a
				 * place to store a a pointer to a new
				 * place to store a pointer to a new
				 * object having a refCount of 1 and containing
				 * the name of the file that produced an error.
				 * the name of the file that produced an error. */
				 * */
{
    const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);

    if (fsPtr == NULL || fsPtr->removeDirectoryProc == NULL) {
    if (fsPtr == NULL) {
	Tcl_SetErrno(ENOENT);
	return -1;
    }
    if (fsPtr->removeDirectoryProc == NULL) {
	Tcl_SetErrno(ENOTSUP);
	return -1;
    }

    if (recursive) {
	Tcl_Obj *cwdPtr = Tcl_FSGetCwd(NULL);
	if (cwdPtr != NULL) {
	    const char *cwdStr, *normPathStr;
	    size_t cwdLen, normLen;
	    Tcl_Size cwdLen, normLen;
	    Tcl_Obj *normPath = Tcl_FSGetNormalizedPath(NULL, pathPtr);

	    if (normPath != NULL) {
		normPathStr = TclGetStringFromObj(normPath, &normLen);
		cwdStr = TclGetStringFromObj(cwdPtr, &cwdLen);
		if ((cwdLen >= normLen) && (strncmp(normPathStr, cwdStr,
			normLen) == 0)) {
4510
4511
4512
4513
4514
4515
4516
4517

4518
4519
4520
4521
4522
4523
4524
4445
4446
4447
4448
4449
4450
4451

4452
4453
4454
4455
4456
4457
4458
4459







-
+







    }

    /*
     * Call each of the "pathInFilesystem" functions in succession until the
     * corresponding filesystem is found.
     */
    for (; fsRecPtr!=NULL ; fsRecPtr=fsRecPtr->nextPtr) {
	ClientData clientData = NULL;
	void *clientData = NULL;

	if (fsRecPtr->fsPtr->pathInFilesystemProc == NULL) {
	    continue;
	}

	if (fsRecPtr->fsPtr->pathInFilesystemProc(pathPtr, &clientData)!=-1) {
	    /* This is the filesystem for pathPtr.  Assume the type of pathPtr
4567
4568
4569
4570
4571
4572
4573
4574

4575
4576
4577
4578
4579
4580
4581
4502
4503
4504
4505
4506
4507
4508

4509
4510
4511
4512
4513
4514
4515
4516







-
+







 *	Memory is released.
 *
 *---------------------------------------------------------------------------
 */

static void
NativeFreeInternalRep(
    ClientData clientData)
    void *clientData)
{
    Tcl_Free(clientData);
}

/*
 *---------------------------------------------------------------------------
 *

Added generic/tclIcu.c.








































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tclIcu.c --
 *
 *	tclIcu.c implements various Tcl commands that make use of
 *	the ICU library if present on the system.
 *	(Adapted from tkIcu.c)
 *
 * Copyright © 2021 Jan Nijtmans
 * Copyright © 2024 Ashok P. Nadkarni
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

typedef uint16_t UCharx;
typedef uint32_t UChar32x;

/*
 * Runtime linking of libicu.
 */
typedef enum UBreakIteratorTypex {
    UBRK_CHARACTERX = 0,
    UBRK_WORDX = 1
} UBreakIteratorTypex;

typedef enum UErrorCodex {
    U_STRING_NOT_TERMINATED_WARNING = -124,
    U_AMBIGUOUS_ALIAS_WARNING = -122,
    U_ZERO_ERRORZ = 0, /**< No error, no warning. */
    U_BUFFER_OVERFLOW_ERROR = 15,
} UErrorCodex;

#define U_SUCCESS(x) ((x)<=U_ZERO_ERRORZ)
#define U_FAILURE(x) ((x)>U_ZERO_ERRORZ)

typedef enum {
    UCNV_UNASSIGNED = 0,
    UCNV_ILLEGAL = 1,
    UCNV_IRREGULAR = 2,
    UCNV_RESET = 3,
    UCNV_CLOSE = 4,
    UCNV_CLONE = 5
} UConverterCallbackReasonx;

typedef enum UNormalizationCheckResultx {
  UNORM_NO,
  UNORM_YES,
  UNORM_MAYBE
} UNormalizationCheckResultx;

typedef struct UEnumeration UEnumeration;
typedef struct UCharsetDetector UCharsetDetector;
typedef struct UCharsetMatch UCharsetMatch;
typedef struct UBreakIterator UBreakIterator;
typedef struct UNormalizer2 UNormalizer2;
typedef struct UConverter UConverter;
typedef struct UConverterFromUnicodeArgs UConverterFromUnicodeArgs;
typedef struct UConverterToUnicodeArgs UConverterToUnicodeArgs;
typedef void   (*UConverterFromUCallback)(const void *context,
					  UConverterFromUnicodeArgs *args,
					  const UCharx *codeUnits,
					  int32_t length, UChar32x codePoint,
					  UConverterCallbackReasonx reason,
					  UErrorCodex *pErrorCode);
typedef void   (*UConverterToUCallback)(const void *context,
					UConverterToUnicodeArgs *args,
					const char *codeUnits,
					int32_t length,
					UConverterCallbackReasonx reason,
					UErrorCodex *pErrorCode);
/*
 * Prototypes for ICU functions sorted by category.
 */
typedef void        (*fn_u_cleanup)(void);
typedef const char *(*fn_u_errorName)(UErrorCodex);
typedef UCharx *(*fn_u_strFromUTF32)(UCharx *dest,
				     int32_t destCapacity,
				     int32_t *pDestLength,
				     const UChar32x *src,
				     int32_t srcLength,
				     UErrorCodex *pErrorCode);
typedef UCharx *(*fn_u_strFromUTF32WithSub)(UCharx *dest,
					    int32_t destCapacity,
					    int32_t *pDestLength,
					    const UChar32x *src,
					    int32_t srcLength,
					    UChar32x subchar,
					    int32_t *pNumSubstitutions,
					    UErrorCodex *pErrorCode);
typedef UChar32x *(*fn_u_strToUTF32)(UChar32x *dest,
				     int32_t destCapacity,
				     int32_t *pDestLength,
				     const UCharx *src,
				     int32_t srcLength,
				     UErrorCodex *pErrorCode);
typedef UChar32x *(*fn_u_strToUTF32WithSub)(UChar32x *dest,
					    int32_t destCapacity,
					    int32_t *pDestLength,
					    const UCharx *src,
					    int32_t srcLength,
					    UChar32x subchar,
					    int32_t *pNumSubstitutions,
					    UErrorCodex *pErrorCode);

typedef void        (*fn_ucnv_close)(UConverter *);
typedef uint16_t    (*fn_ucnv_countAliases)(const char *, UErrorCodex *);
typedef int32_t     (*fn_ucnv_countAvailable)(void);
typedef int32_t     (*fn_ucnv_fromUChars)(UConverter *, char *dest,
	int32_t destCapacity, const UCharx *src, int32_t srcLen, UErrorCodex *);
typedef const char *(*fn_ucnv_getAlias)(const char *, uint16_t, UErrorCodex *);
typedef const char *(*fn_ucnv_getAvailableName)(int32_t);
typedef UConverter *(*fn_ucnv_open)(const char *converterName, UErrorCodex *);
typedef void        (*fn_ucnv_setFromUCallBack)(UConverter *,
						UConverterFromUCallback newAction,
						const void *newContext,
						UConverterFromUCallback *oldAction,
						const void **oldContext,
						UErrorCodex *err);
typedef void        (*fn_ucnv_setToUCallBack)(UConverter *,
						UConverterToUCallback newAction,
						const void *newContext,
						UConverterToUCallback *oldAction,
						const void **oldContext,
						UErrorCodex *err);
typedef int32_t     (*fn_ucnv_toUChars)(UConverter *, UCharx *dest,
					int32_t destCapacity, const char *src, int32_t srcLen, UErrorCodex *);
typedef UConverterFromUCallback fn_UCNV_FROM_U_CALLBACK_STOP;
typedef UConverterToUCallback   fn_UCNV_TO_U_CALLBACK_STOP;

typedef UBreakIterator *(*fn_ubrk_open)(
	UBreakIteratorTypex, const char *, const uint16_t *, int32_t,
	UErrorCodex *);
typedef void	(*fn_ubrk_close)(UBreakIterator *);
typedef int32_t	(*fn_ubrk_preceding)(UBreakIterator *, int32_t);
typedef int32_t	(*fn_ubrk_following)(UBreakIterator *, int32_t);
typedef int32_t	(*fn_ubrk_previous)(UBreakIterator *);
typedef int32_t	(*fn_ubrk_next)(UBreakIterator *);
typedef void	(*fn_ubrk_setText)(
	UBreakIterator *, const void *, int32_t, UErrorCodex *);

typedef UCharsetDetector * (*fn_ucsdet_open)(UErrorCodex *status);
typedef void               (*fn_ucsdet_close)(UCharsetDetector *ucsd);
typedef void               (*fn_ucsdet_setText)(UCharsetDetector *ucsd,
	const char *textIn, int32_t len, UErrorCodex *status);
typedef const char *       (*fn_ucsdet_getName)(
	const UCharsetMatch *ucsm, UErrorCodex *status);
typedef UEnumeration *     (*fn_ucsdet_getAllDetectableCharsets)(
	UCharsetDetector *ucsd, UErrorCodex *status);
typedef const UCharsetMatch *  (*fn_ucsdet_detect)(
	UCharsetDetector *ucsd, UErrorCodex *status);
typedef const UCharsetMatch ** (*fn_ucsdet_detectAll)(
	UCharsetDetector *ucsd, int32_t *matchesFound, UErrorCodex *status);

typedef void        (*fn_uenum_close)(UEnumeration *);
typedef int32_t     (*fn_uenum_count)(UEnumeration *, UErrorCodex *);
typedef const char *(*fn_uenum_next)(UEnumeration *, int32_t *, UErrorCodex *);

typedef UNormalizer2 *(*fn_unorm2_getNFCInstance)(UErrorCodex *);
typedef UNormalizer2 *(*fn_unorm2_getNFDInstance)(UErrorCodex *);
typedef UNormalizer2 *(*fn_unorm2_getNFKCInstance)(UErrorCodex *);
typedef UNormalizer2 *(*fn_unorm2_getNFKDInstance)(UErrorCodex *);
typedef int32_t (*fn_unorm2_normalize)(const UNormalizer2 *,
				       const UCharx *,
				       int32_t,
				       UCharx *,
				       int32_t,
				       UErrorCodex *);

#define FIELD(name) fn_ ## name _ ## name

static struct {
    size_t nopen;		/* Total number of references to ALL libraries */
    /*
     * Depending on platform, ICU symbols may be distributed amongst
     * multiple libraries. For current functionality at most 2 needed.
     * Order of library loading is not guaranteed.
     */
    Tcl_LoadHandle      libs[2];

    FIELD(u_cleanup);
    FIELD(u_errorName);
    FIELD(u_strFromUTF32);
    FIELD(u_strFromUTF32WithSub);
    FIELD(u_strToUTF32);
    FIELD(u_strToUTF32WithSub);

    FIELD(ubrk_open);
    FIELD(ubrk_close);
    FIELD(ubrk_preceding);
    FIELD(ubrk_following);
    FIELD(ubrk_previous);
    FIELD(ubrk_next);
    FIELD(ubrk_setText);

    FIELD(ucnv_close);
    FIELD(ucnv_countAliases);
    FIELD(ucnv_countAvailable);
    FIELD(ucnv_fromUChars);
    FIELD(ucnv_getAlias);
    FIELD(ucnv_getAvailableName);
    FIELD(ucnv_open);
    FIELD(ucnv_setFromUCallBack);
    FIELD(ucnv_setToUCallBack);
    FIELD(ucnv_toUChars);
    FIELD(UCNV_FROM_U_CALLBACK_STOP);
    FIELD(UCNV_TO_U_CALLBACK_STOP);

    FIELD(ucsdet_close);
    FIELD(ucsdet_detect);
    FIELD(ucsdet_detectAll);
    FIELD(ucsdet_getAllDetectableCharsets);
    FIELD(ucsdet_getName);
    FIELD(ucsdet_open);
    FIELD(ucsdet_setText);

    FIELD(uenum_close);
    FIELD(uenum_count);
    FIELD(uenum_next);
    FIELD(unorm2_getNFCInstance);
    FIELD(unorm2_getNFDInstance);
    FIELD(unorm2_getNFKCInstance);
    FIELD(unorm2_getNFKDInstance);
    FIELD(unorm2_normalize);
} icu_fns = {
    0,    {NULL, NULL}, /* Reference count, library handles */
    NULL, NULL, NULL, NULL, NULL, NULL,                     /* u_* */
    NULL, NULL, NULL, NULL, NULL, NULL, NULL,               /* ubrk* */
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,   /* ucnv_* .. */
    NULL, NULL, NULL,                                       /* .. ucnv_ */
    NULL, NULL, NULL, NULL, NULL, NULL, NULL,               /* ucsdet* */
    NULL, NULL, NULL,                                       /* uenum_* */
    NULL, NULL, NULL, NULL, NULL,                           /* unorm2_* */
};

#define u_cleanup        icu_fns._u_cleanup
#define u_errorName      icu_fns._u_errorName
#define u_strFromUTF32   icu_fns._u_strFromUTF32
#define u_strFromUTF32WithSub icu_fns._u_strFromUTF32WithSub
#define u_strToUTF32          icu_fns._u_strToUTF32
#define u_strToUTF32WithSub   icu_fns._u_strToUTF32WithSub

#define ubrk_open        icu_fns._ubrk_open
#define ubrk_close       icu_fns._ubrk_close
#define ubrk_preceding   icu_fns._ubrk_preceding
#define ubrk_following   icu_fns._ubrk_following
#define ubrk_previous    icu_fns._ubrk_previous
#define ubrk_next        icu_fns._ubrk_next
#define ubrk_setText     icu_fns._ubrk_setText

#define ucnv_close            icu_fns._ucnv_close
#define ucnv_countAliases     icu_fns._ucnv_countAliases
#define ucnv_countAvailable   icu_fns._ucnv_countAvailable
#define ucnv_fromUChars       icu_fns._ucnv_fromUChars
#define ucnv_getAlias         icu_fns._ucnv_getAlias
#define ucnv_getAvailableName icu_fns._ucnv_getAvailableName
#define ucnv_open             icu_fns._ucnv_open
#define ucnv_setFromUCallBack icu_fns._ucnv_setFromUCallBack
#define ucnv_setToUCallBack   icu_fns._ucnv_setToUCallBack
#define ucnv_toUChars         icu_fns._ucnv_toUChars
#define UCNV_FROM_U_CALLBACK_STOP icu_fns._UCNV_FROM_U_CALLBACK_STOP
#define UCNV_TO_U_CALLBACK_STOP   icu_fns._UCNV_TO_U_CALLBACK_STOP

#define ucsdet_close     icu_fns._ucsdet_close
#define ucsdet_detect    icu_fns._ucsdet_detect
#define ucsdet_detectAll icu_fns._ucsdet_detectAll
#define ucsdet_getAllDetectableCharsets icu_fns._ucsdet_getAllDetectableCharsets
#define ucsdet_getName   icu_fns._ucsdet_getName
#define ucsdet_open      icu_fns._ucsdet_open
#define ucsdet_setText   icu_fns._ucsdet_setText

#define uenum_next       icu_fns._uenum_next
#define uenum_close      icu_fns._uenum_close
#define uenum_count      icu_fns._uenum_count

#define unorm2_getNFCInstance  icu_fns._unorm2_getNFCInstance
#define unorm2_getNFDInstance  icu_fns._unorm2_getNFDInstance
#define unorm2_getNFKCInstance icu_fns._unorm2_getNFKCInstance
#define unorm2_getNFKDInstance icu_fns._unorm2_getNFKDInstance
#define unorm2_normalize       icu_fns._unorm2_normalize

TCL_DECLARE_MUTEX(icu_mutex);

/* Options used by multiple normalization functions */
static const char *normalizationForms[] = {"nfc", "nfd", "nfkc", "nfkd", NULL};
typedef enum { MODE_NFC, MODE_NFD, MODE_NFKC, MODE_NFKD } NormalizationMode;


/* Error handlers. */

static int
FunctionNotAvailableError(
    Tcl_Interp *interp)
{
    if (interp) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"ICU function not available", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "ICU", "UNSUPPORTED_OP", NULL);
    }
    return TCL_ERROR;
}

static int
IcuError(
    Tcl_Interp *interp,
    const char *message,
    UErrorCodex code)
{
    if (interp) {
	const char *codeMessage = NULL;
	if (u_errorName) {
	    codeMessage = u_errorName(code);
	}
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"%s%sICU error (%d): %s",
		message ? message : "",
		message ? ". " : "",
		code,
		codeMessage ? codeMessage : ""));
	Tcl_SetErrorCode(interp, "TCL", "ICU", codeMessage, NULL);
    }
    return TCL_ERROR;
}

/*
 * Detect the likely encoding of the string encoded in the given byte array.
 */
static int
DetectEncoding(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    int all)
{
    Tcl_Size len;
    const char *bytes;
    const UCharsetMatch *match;
    const UCharsetMatch **matches;
    int nmatches;
    int ret;

    // Confirm we have the profile of functions we need.
    if (ucsdet_open == NULL ||
	    ucsdet_setText == NULL ||
	    ucsdet_detect == NULL ||
	    ucsdet_detectAll == NULL ||
	    ucsdet_getName == NULL ||
	    ucsdet_close == NULL) {
	return FunctionNotAvailableError(interp);
    }

    bytes = (char *) Tcl_GetBytesFromObj(interp, objPtr, &len);
    if (bytes == NULL) {
	return TCL_ERROR;
    }
    UErrorCodex status = U_ZERO_ERRORZ;

    UCharsetDetector* csd = ucsdet_open(&status);
    if (U_FAILURE(status)) {
	return IcuError(interp, "Could not open charset detector", status);
    }

    ucsdet_setText(csd, bytes, len, &status);
    if (U_FAILURE(status)) {
	IcuError(interp, "Could not set detection text", status);
	ucsdet_close(csd);
	return TCL_ERROR;
    }

    if (all) {
	matches = ucsdet_detectAll(csd, &nmatches, &status);
    } else {
	match = ucsdet_detect(csd, &status);
	matches = &match;
	nmatches = match ? 1 : 0;
    }

    if (U_FAILURE(status) || nmatches == 0) {
	ret = IcuError(interp, "Could not detect character set", status);
    } else {
	int i;
	Tcl_Obj *resultObj = Tcl_NewListObj(nmatches, NULL);

	for (i = 0; i < nmatches; ++i) {
	    const char *name = ucsdet_getName(matches[i], &status);
	    if (U_FAILURE(status) || name == NULL) {
		name = "unknown";
		status = U_ZERO_ERRORZ; /* Reset on failure */
	    }
	    Tcl_ListObjAppendElement(
		    NULL, resultObj, Tcl_NewStringObj(name, TCL_AUTO_LENGTH));
	}
	Tcl_SetObjResult(interp, resultObj);
	ret = TCL_OK;
    }

    ucsdet_close(csd);
    return ret;
}

static int
DetectableEncodings(
    Tcl_Interp *interp)
{
    // Confirm we have the profile of functions we need.
    if (ucsdet_open == NULL ||
	    ucsdet_getAllDetectableCharsets == NULL ||
	    ucsdet_close == NULL ||
	    uenum_next == NULL ||
	    uenum_count == NULL ||
	    uenum_close == NULL) {
	return FunctionNotAvailableError(interp);
    }
    UErrorCodex status = U_ZERO_ERRORZ;
    UCharsetDetector *csd = ucsdet_open(&status);

    if (U_FAILURE(status)) {
	return IcuError(interp, "Could not open charset detector", status);
    }

    int ret;
    UEnumeration *enumerator = ucsdet_getAllDetectableCharsets(csd, &status);
    if (U_FAILURE(status) || enumerator == NULL) {
	IcuError(interp, "Could not get list of detectable encodings", status);
	ret = TCL_ERROR;
    } else {
	int32_t count = uenum_count(enumerator, &status);

	if (U_FAILURE(status)) {
	    IcuError(interp, "Could not get charset enumerator count", status);
	    ret = TCL_ERROR;
	} else {
	    int i;
	    Tcl_Obj *resultObj = Tcl_NewListObj(0, NULL);

	    for (i = 0; i < count; ++i) {
		const char *name;
		int32_t len;

		name = uenum_next(enumerator, &len, &status);
		if (name == NULL || U_FAILURE(status)) {
		    name = "unknown";
		    len = 7;
		    status = U_ZERO_ERRORZ; /* Reset on error */
		}
		Tcl_ListObjAppendElement(
			NULL, resultObj, Tcl_NewStringObj(name, len));
	    }
	    Tcl_SetObjResult(interp, resultObj);
	    ret = TCL_OK;
	}
	uenum_close(enumerator);
    }

    ucsdet_close(csd);
    return ret;
}

/*
 *------------------------------------------------------------------------
 *
 * IcuObjToUCharDString --
 *
 *    Encodes a Tcl_Obj value in ICU UChars and stores in dsPtr.
 *
 * Results:
 *    Return TCL_OK / TCL_ERROR.
 *
 * Side effects:
 *    *dsPtr should be cleared by caller only if return code is TCL_OK.
 *
 *------------------------------------------------------------------------
 */
static int
IcuObjToUCharDString(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    int strict,
    Tcl_DString *dsPtr)
{
    Tcl_Encoding encoding;

    /*
     * TODO - not the most efficient to get an encoding every time.
     * However, we cannot use Tcl_UtfToChar16DString as that blithely
     * ignores invalid or ill-formed UTF8 strings.
     */
    encoding = Tcl_GetEncoding(interp, "utf-16");
    if (encoding == NULL) {
	return TCL_ERROR;
    }

    int result;
    char *s;
    Tcl_Size len;
    s = Tcl_GetStringFromObj(objPtr, &len);
    result = Tcl_UtfToExternalDStringEx(interp,
					encoding,
					s,
					len,
					strict ? TCL_ENCODING_PROFILE_STRICT
					       : TCL_ENCODING_PROFILE_REPLACE,
					dsPtr,
					NULL);
    if (result != TCL_OK) {
	Tcl_DStringFree(dsPtr); /* Must be done on error */
	/* TCL_CONVER_* errors -> TCL_ERROR */
	result = TCL_ERROR;
    }

    Tcl_FreeEncoding(encoding);
    return result;
}

/*
 *------------------------------------------------------------------------
 *
 * IcuObjFromUCharDString --
 *
 *    Stores a Tcl_Obj value by decoding ICU UChars in dsPtr.
 *
 * Results:
 *    Return Tcl_Obj or NULL on error.
 *
 * Side effects:
 *    None.
 *
 *------------------------------------------------------------------------
 */
static Tcl_Obj *
IcuObjFromUCharDString(
    Tcl_Interp *interp,
    Tcl_DString *dsPtr,
    int strict)
{
    Tcl_Encoding encoding;

    /*
     * TODO - not the most efficient to get an encoding every time.
     * However, we cannot use Tcl_UtfToChar16DString as that blithely
     * ignores invalid or ill-formed UTF8 strings.
     */
    encoding = Tcl_GetEncoding(interp, "utf-16");
    if (encoding == NULL) {
	return NULL;
    }
    Tcl_Obj *objPtr = NULL;
    char *s = Tcl_DStringValue(dsPtr);
    Tcl_Size len = Tcl_DStringLength(dsPtr);
    Tcl_DString dsOut;
    int result;
    result  = Tcl_ExternalToUtfDStringEx(interp,
					encoding,
					s,
					len,
					strict ? TCL_ENCODING_PROFILE_STRICT
					       : TCL_ENCODING_PROFILE_REPLACE,
					&dsOut,
					NULL);

    if (result == TCL_OK) {
	objPtr = Tcl_DStringToObj(&dsOut); /* Clears dsPtr! */
    }

    Tcl_FreeEncoding(encoding);
    return objPtr;
}

/*
 *------------------------------------------------------------------------
 *
 * EncodingDetectObjCmd --
 *
 *	Implements the Tcl command EncodingDetect.
 *	  encdetect - returns names of all detectable encodings
 *	  encdetect BYTES ?-all? - return detected encoding(s)
 *
 * Results:
 *	TCL_OK    - Success.
 *	TCL_ERROR - Error.
 *
 * Side effects:
 *	Interpreter result holds result or error message.
 *
 *------------------------------------------------------------------------
 */
static int
IcuDetectObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc > 3) {
	Tcl_WrongNumArgs(interp, 1 , objv, "?bytes ?-all??");
	return TCL_ERROR;
    }

    if (objc == 1) {
	return DetectableEncodings(interp);
    }

    int all = 0;
    if (objc == 3) {
	if (strcmp("-all", Tcl_GetString(objv[2]))) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "Invalid option %s, must be \"-all\"",
		    Tcl_GetString(objv[2])));
	    return TCL_ERROR;
	}
	all = 1;
    }

    return DetectEncoding(interp, objv[1], all);
}

/*
 *------------------------------------------------------------------------
 *
 * IcuConverterNamesObjCmd --
 *
 *	Sets interp result to list of available ICU converters.
 *
 * Results:
 *	TCL_OK    - Success.
 *	TCL_ERROR - Error.
 *
 * Side effects:
 *	Interpreter result holds list of converter names.
 *
 *------------------------------------------------------------------------
 */
static int
IcuConverterNamesObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{

    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1 , objv, "");
	return TCL_ERROR;
    }
    if (ucnv_countAvailable == NULL || ucnv_getAvailableName == NULL) {
	return FunctionNotAvailableError(interp);
    }

    int32_t count = ucnv_countAvailable();
    if (count <= 0) {
	return TCL_OK;
    }
    Tcl_Obj *resultObj = Tcl_NewListObj(count, NULL);
    int32_t i;

    for (i = 0; i < count; ++i) {
	const char *name = ucnv_getAvailableName(i);
	if (name) {
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    Tcl_NewStringObj(name, TCL_AUTO_LENGTH));
	}
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

/*
 *------------------------------------------------------------------------
 *
 * IcuConverterAliasesObjCmd --
 *
 *	Sets interp result to list of available ICU converters.
 *
 * Results:
 *	TCL_OK    - Success.
 *	TCL_ERROR - Error.
 *
 * Side effects:
 *	Interpreter result holds list of converter names.
 *
 *------------------------------------------------------------------------
 */
static int
IcuConverterAliasesObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1 , objv, "convertername");
	return TCL_ERROR;
    }
    if (ucnv_countAliases == NULL || ucnv_getAlias == NULL) {
	return FunctionNotAvailableError(interp);
    }

    const char *name = Tcl_GetString(objv[1]);
    UErrorCodex status = U_ZERO_ERRORZ;
    uint16_t count = ucnv_countAliases(name, &status);
    if (status != U_AMBIGUOUS_ALIAS_WARNING && U_FAILURE(status)) {
	return IcuError(interp, "Could not get aliases", status);
    }
    if (count <= 0) {
	return TCL_OK;
    }

    Tcl_Obj *resultObj = Tcl_NewListObj(count, NULL);
    uint16_t i;

    for (i = 0; i < count; ++i) {
	status = U_ZERO_ERRORZ; /* Reset in case U_AMBIGUOUS_ALIAS_WARNING */
	const char *aliasName = ucnv_getAlias(name, i, &status);

	if (status != U_AMBIGUOUS_ALIAS_WARNING && U_FAILURE(status)) {
	    status = U_ZERO_ERRORZ; /* Reset error for next iteration */
	    continue;
	}
	if (aliasName) {
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    Tcl_NewStringObj(aliasName, TCL_AUTO_LENGTH));
	}
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

/*
 *------------------------------------------------------------------------
 *
 * IcuConverttoDString --
 *
 *    Converts a string in ICU default encoding to the specified encoding.
 *
 * Results:
 *    TCL_OK / TCL_ERROR
 *
 * Side effects:
 *    On success, encoded string is stored in output dsOutPtr
 *
 *------------------------------------------------------------------------
 */
static int
IcuConverttoDString(
    Tcl_Interp *interp,
    Tcl_DString *dsInPtr,  /* Input UTF16 */
    const char *icuEncName,
    int strict,
    Tcl_DString *dsOutPtr) /* Output encoded string. */
{
    if (ucnv_open == NULL || ucnv_close == NULL ||
	ucnv_fromUChars == NULL || UCNV_FROM_U_CALLBACK_STOP == NULL) {
	return FunctionNotAvailableError(interp);
    }

    UErrorCodex status = U_ZERO_ERRORZ;
    UConverter *ucnvPtr = ucnv_open(icuEncName, &status);
    if (ucnvPtr == NULL) {
	return IcuError(interp, "Could not get encoding converter", status);
    }
    if (strict) {
	ucnv_setFromUCallBack(ucnvPtr, UCNV_FROM_U_CALLBACK_STOP, NULL, NULL, NULL, &status);
	if (U_FAILURE(status)) {
	    /* TODO - use ucnv_getInvalidUChars to retrieve failing chars */
	    ucnv_close(ucnvPtr);
	    return IcuError(interp, "Could not set conversion callback", status);
	}
    }

    UCharx *utf16 = (UCharx *) Tcl_DStringValue(dsInPtr);
    Tcl_Size utf16len = Tcl_DStringLength(dsInPtr) / sizeof(UCharx);
    Tcl_Size dstLen, dstCapacity;
    if (utf16len > INT_MAX) {
	Tcl_SetObjResult( interp,
		Tcl_NewStringObj("Max length supported by ICU exceeded.", TCL_INDEX_NONE));
	return TCL_ERROR;
    }

    dstCapacity = utf16len;
    Tcl_DStringInit(dsOutPtr);
    Tcl_DStringSetLength(dsOutPtr, dstCapacity);
    dstLen = ucnv_fromUChars(ucnvPtr, Tcl_DStringValue(dsOutPtr), dstCapacity,
			     utf16, utf16len, &status);
    if (U_FAILURE(status)) {
	switch (status) {
	case U_STRING_NOT_TERMINATED_WARNING:
	    break; /* We don't care */
	case U_BUFFER_OVERFLOW_ERROR:
	    Tcl_DStringSetLength(dsOutPtr, dstLen);
	    status = U_ZERO_ERRORZ; /* Reset before call */
	    dstLen = ucnv_fromUChars(ucnvPtr, Tcl_DStringValue(dsOutPtr), dstLen,
				     utf16, utf16len, &status);
	    if (U_SUCCESS(status)) {
		break;
	    }
	    /* FALLTHRU */
	default:
	    Tcl_DStringFree(dsOutPtr);
	    ucnv_close(ucnvPtr);
	    return IcuError(interp, "ICU error while encoding", status);
	}
    }
    Tcl_DStringSetLength(dsOutPtr, dstLen);
    ucnv_close(ucnvPtr);
    return TCL_OK;
}

/*
 *------------------------------------------------------------------------
 *
 * IcuBytesToUCharDString --
 *
 *    Converts encoded bytes to ICU UChars in a Tcl_DString
 *
 * Results:
 *    TCL_OK / TCL_ERROR
 *
 * Side effects:
 *    On success, encoded string is stored in output dsOutPtr
 *
 *------------------------------------------------------------------------
 */
static int
IcuBytesToUCharDString(
    Tcl_Interp *interp,
    const unsigned char *bytes,
    Tcl_Size nbytes,
    const char *icuEncName,
    int strict,
    Tcl_DString *dsOutPtr) /* Output UChar string. */
{
    if (ucnv_open == NULL || ucnv_close == NULL ||
	ucnv_toUChars == NULL || UCNV_TO_U_CALLBACK_STOP == NULL) {
	return FunctionNotAvailableError(interp);
    }

    if (nbytes > INT_MAX) {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("Max length supported by ICU exceeded.", TCL_INDEX_NONE));
	return TCL_ERROR;
    }

    UErrorCodex status = U_ZERO_ERRORZ;
    UConverter *ucnvPtr = ucnv_open(icuEncName, &status);
    if (ucnvPtr == NULL) {
	return IcuError(interp, "Could not get encoding converter", status);
    }
    if (strict) {
	ucnv_setToUCallBack(ucnvPtr, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &status);
	if (U_FAILURE(status)) {
	    /* TODO - use ucnv_getInvalidUChars to retrieve failing chars */
	    ucnv_close(ucnvPtr);
	    return IcuError(interp, "Could not set conversion callback", status);
	}
    }

    int dstLen;
    int dstCapacity = (int) nbytes; /* In UChar's  */
    Tcl_DStringInit(dsOutPtr);
    Tcl_DStringSetLength(dsOutPtr, dstCapacity);
    dstLen = ucnv_toUChars(ucnvPtr, (UCharx *)Tcl_DStringValue(dsOutPtr), dstCapacity,
			   (const char *)bytes, nbytes, &status);
    if (U_FAILURE(status)) {
	switch (status) {
	case U_STRING_NOT_TERMINATED_WARNING:
	    break; /* We don't care */
	case U_BUFFER_OVERFLOW_ERROR:
	    dstCapacity = sizeof(UCharx) * dstLen;
	    Tcl_DStringSetLength(dsOutPtr, dstCapacity);
	    status = U_ZERO_ERRORZ; /* Reset before call */
	    dstLen = ucnv_toUChars(ucnvPtr, (UCharx *)Tcl_DStringValue(dsOutPtr), dstCapacity,
				   (const char *)bytes, nbytes, &status);
	    if (U_SUCCESS(status)) {
		break;
	    }
	    /* FALLTHRU */
	default:
	    Tcl_DStringFree(dsOutPtr);
	    ucnv_close(ucnvPtr);
	    return IcuError(interp, "ICU error while decoding", status);
	}
    }
    Tcl_DStringSetLength(dsOutPtr, sizeof(UCharx)*dstLen);
    ucnv_close(ucnvPtr);
    return TCL_OK;
}


/*
 *------------------------------------------------------------------------
 *
 * IcuNormalizeUCharDString --
 *
 *    Normalizes the UTF-16 encoded data
 *
 * Results:
 *    TCL_OK / TCL_ERROR
 *
 * Side effects:
 *    Normalized data is stored in dsOutPtr which should only be
 *    Tcl_DStringFree-ed if return code is TCL_OK.
 *
 *------------------------------------------------------------------------
 */
static int
IcuNormalizeUCharDString(
    Tcl_Interp *interp,
    Tcl_DString *dsInPtr, /* Input UTF16 */
    NormalizationMode mode,
    Tcl_DString *dsOutPtr) /* Output normalized UTF16. */
{
    typedef UNormalizer2 *(*normFn)(UErrorCodex *);
    normFn fn = NULL;

    switch (mode) {
    case MODE_NFC:
	fn = unorm2_getNFCInstance;
	break;
    case MODE_NFD:
	fn = unorm2_getNFDInstance;
	break;
    case MODE_NFKC:
	fn = unorm2_getNFKCInstance;
	break;
    case MODE_NFKD:
	fn = unorm2_getNFKDInstance;
	break;
    }
    if (fn == NULL || unorm2_normalize == NULL) {
	return FunctionNotAvailableError(interp);
    }

    UErrorCodex status = U_ZERO_ERRORZ;
    UNormalizer2 *normalizer = fn(&status);
    if (U_FAILURE(status)) {
	return IcuError(interp, "Could not get ICU normalizer", status);
    }

    UCharx *utf16;
    Tcl_Size utf16len;
    UCharx *normPtr;
    int32_t normLen;

    utf16 = (UCharx *) Tcl_DStringValue(dsInPtr);
    utf16len = Tcl_DStringLength(dsInPtr) / sizeof(UCharx);
    if (utf16len > INT_MAX) {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("Max length supported by ICU exceeded.", TCL_INDEX_NONE));
	return TCL_ERROR;
    }
    Tcl_DStringInit(dsOutPtr);
    Tcl_DStringSetLength(dsOutPtr, utf16len * sizeof(UCharx));
    normPtr = (UCharx *) Tcl_DStringValue(dsOutPtr);

    normLen = unorm2_normalize(
	normalizer, utf16, utf16len, normPtr, utf16len, &status);
    if (U_FAILURE(status)) {
	switch (status) {
	case U_STRING_NOT_TERMINATED_WARNING:
	    /* No problem, don't need it terminated */
	    break;
	case U_BUFFER_OVERFLOW_ERROR:
	    /* Expand buffer */
	    Tcl_DStringSetLength(dsOutPtr, normLen * sizeof(UCharx));
	    normPtr = (UCharx *) Tcl_DStringValue(dsOutPtr);
	    status = U_ZERO_ERRORZ; /* Need to clear error! */
	    normLen = unorm2_normalize(
		normalizer, utf16, utf16len, normPtr, normLen, &status);
	    if (U_SUCCESS(status)) {
		break;
	    }
	    /* FALLTHRU */
	default:
	    Tcl_DStringFree(dsOutPtr);
	    return IcuError(interp, "String normalization failed", status);
	}
    }

    Tcl_DStringSetLength(dsOutPtr, normLen * sizeof(UCharx));
    return TCL_OK;
}

/*
 * Common function for parsing convert options.
 */
static int IcuParseConvertOptions(
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[],
    int *strictPtr,
    Tcl_Obj **failindexVarPtr)
{
    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "?-profile PROFILE? ICUENCNAME STRING");
	return TCL_ERROR;
    }
    objc -= 2; /* truncate fixed arguments */

    /* Use GetIndexFromObj for option parsing so -failindex can be added later */

    static const char *optNames[] = {"-profile", "-failindex", NULL};
    enum { OPT_PROFILE, OPT_FAILINDEX } opt;
    int i;
    int strict = 1;
    for (i = 1; i < objc; ++i) {
	if (Tcl_GetIndexFromObj(
		interp, objv[i], optNames, "option", 0, &opt) != TCL_OK) {
	    return TCL_ERROR;
	}
	++i;
	if (i == objc) {
	    Tcl_SetObjResult(interp,
			     Tcl_ObjPrintf("Missing value for option %s.",
					   Tcl_GetString(objv[i - 1])));
	    return TCL_ERROR;
	}
	const char *s = Tcl_GetString(objv[i]);
	switch (opt) {
	case OPT_PROFILE:
	    if (!strcmp(s, "replace")) {
		strict = 0;
	    } else if (strcmp(s, "strict")) {
		Tcl_SetObjResult(
		    interp,
		    Tcl_ObjPrintf("Invalid value \"%s\" supplied for option"
			 " \"-profile\". Must be \"strict\" or \"replace\".",
			 s));
		return TCL_ERROR;
	    }
	    break;
	case OPT_FAILINDEX:
	    /* TBD */
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("Option -failindex not implemented.", TCL_INDEX_NONE));
	    return TCL_ERROR;
	}
    }
    *strictPtr = strict;
    *failindexVarPtr = NULL;
    return TCL_OK;
}

/*
 *------------------------------------------------------------------------
 *
 * IcuConvertfromObjCmd --
 *
 *    Implements the Tcl command "icu convertfrom"
 *        icu convertfrom ?-profile replace|strict? encoding string
 *
 * Results:
 *    TCL_OK    - Success.
 *    TCL_ERROR - Error.
 *
 * Side effects:
 *    Interpreter result holds result or error message.
 *
 *------------------------------------------------------------------------
 */
static int
IcuConvertfromObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,    /* Current interpreter. */
    int objc,              /* Number of arguments. */
    Tcl_Obj *const objv[]) /* Argument objects. */
{
    int strict;
    Tcl_Obj *failindexVar;

    if (IcuParseConvertOptions(interp, objc, objv, &strict, &failindexVar) != TCL_OK) {
	return TCL_ERROR;
    }

    Tcl_Size nbytes;
    const unsigned char *bytes = Tcl_GetBytesFromObj(interp, objv[objc-1], &nbytes);
    if (bytes == NULL) {
	return TCL_ERROR;
    }

    Tcl_DString ds;
    if (IcuBytesToUCharDString(interp, bytes, nbytes,
	    Tcl_GetString(objv[objc-2]), strict, &ds) != TCL_OK) {
	return TCL_ERROR;
    }
    Tcl_Obj *resultObj = IcuObjFromUCharDString(interp, &ds, strict);
    if (resultObj) {
	Tcl_SetObjResult(interp, resultObj);
	return TCL_OK;
    } else {
	return TCL_ERROR;
    }
}

/*
 *------------------------------------------------------------------------
 *
 * IcuConverttoObjCmd --
 *
 *    Implements the Tcl command "icu convertto"
 *        icu convertto ?-profile replace|strict? encoding string
 *
 * Results:
 *    TCL_OK    - Success.
 *    TCL_ERROR - Error.
 *
 * Side effects:
 *    Interpreter result holds result or error message.
 *
 *------------------------------------------------------------------------
 */
static int
IcuConverttoObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,    /* Current interpreter. */
    int objc,              /* Number of arguments. */
    Tcl_Obj *const objv[]) /* Argument objects. */
{
    int strict;
    Tcl_Obj *failindexVar;

    if (IcuParseConvertOptions(interp, objc, objv, &strict, &failindexVar) != TCL_OK) {
	return TCL_ERROR;
    }

    Tcl_DString dsIn;
    Tcl_DString dsOut;
    if (IcuObjToUCharDString(interp, objv[objc - 1], strict, &dsIn) != TCL_OK ||
	IcuConverttoDString(interp, &dsIn,
	    Tcl_GetString(objv[objc-2]), strict, &dsOut) != TCL_OK) {
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp,
	Tcl_NewByteArrayObj((unsigned char *)Tcl_DStringValue(&dsOut),
			    Tcl_DStringLength(&dsOut)));
    Tcl_DStringFree(&dsOut);
    return TCL_OK;
}

/*
 *------------------------------------------------------------------------
 *
 * IcuNormalizeObjCmd --
 *
 *    Implements the Tcl command "icu normalize"
 *        icu normalize ?-profile replace|strict? ?-mode nfc|nfd|nfkc|nfkd? string
 *
 * Results:
 *    TCL_OK    - Success.
 *    TCL_ERROR - Error.
 *
 * Side effects:
 *    Interpreter result holds result or error message.
 *
 *------------------------------------------------------------------------
 */
static int
IcuNormalizeObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,    /* Current interpreter. */
    int objc,              /* Number of arguments. */
    Tcl_Obj *const objv[]) /* Argument objects. */
{
    static const char *optNames[] = {"-profile", "-mode", NULL};
    enum { OPT_PROFILE, OPT_MODE } opt;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?-profile PROFILE? ?-mode MODE? STRING");
	return TCL_ERROR;
    }

    int i;
    int strict = 1;
    NormalizationMode mode = MODE_NFC;
    for (i = 1; i < objc - 1; ++i) {
	if (Tcl_GetIndexFromObj(
		interp, objv[i], optNames, "option", 0, &opt) != TCL_OK) {
	    return TCL_ERROR;
	}
	++i;
	if (i == (objc-1)) {
	    Tcl_SetObjResult(interp,
			     Tcl_ObjPrintf("Missing value for option %s.",
					   Tcl_GetString(objv[i - 1])));
	    return TCL_ERROR;
	}
	const char *s = Tcl_GetString(objv[i]);
	switch (opt) {
	case OPT_PROFILE:
	    if (!strcmp(s, "replace")) {
		strict = 0;
	    } else if (strcmp(s, "strict")) {
		Tcl_SetObjResult(
		    interp,
		    Tcl_ObjPrintf("Invalid value \"%s\" supplied for option \"-profile\". Must be "
				  "\"strict\" or \"replace\".",
				  s));
		return TCL_ERROR;
	    }
	    break;
	case OPT_MODE:
	    if (Tcl_GetIndexFromObj(interp, objv[i], normalizationForms, "normalization mode", 0, &mode) != TCL_OK) {
		return TCL_ERROR;
	    }
	    break;
	}
    }

    Tcl_DString dsIn;
    Tcl_DString dsNorm;
    if (IcuObjToUCharDString(interp, objv[objc - 1], strict, &dsIn) != TCL_OK ||
	IcuNormalizeUCharDString(interp, &dsIn, mode, &dsNorm) != TCL_OK) {
	return TCL_ERROR;
    }
    Tcl_DStringFree(&dsIn);
    Tcl_Obj *objPtr = IcuObjFromUCharDString(interp, &dsNorm, strict);
    Tcl_DStringFree(&dsNorm);
    if (objPtr) {
	Tcl_SetObjResult(interp, objPtr);
	return TCL_OK;
    }
    else {
	return TCL_ERROR;
    }
}

/*
 *------------------------------------------------------------------------
 *
 * TclIcuCleanup --
 *
 *	Called whenever a command referencing the ICU function table is
 *	deleted. When the reference count drops to zero, the table is released
 *	and the ICU shared libraries are unloaded.
 *
 *------------------------------------------------------------------------
 */
static void
TclIcuCleanup(
    TCL_UNUSED(void *))
{
    Tcl_MutexLock(&icu_mutex);
    if (icu_fns.nopen-- <= 1) {
	int i;
	if (u_cleanup != NULL) {
	    u_cleanup();
	}
	for (i = 0; i < (int)(sizeof(icu_fns.libs) / sizeof(icu_fns.libs[0]));
		++i) {
	    if (icu_fns.libs[i] != NULL) {
		Tcl_FSUnloadFile(NULL, icu_fns.libs[i]);
	    }
	}
	memset(&icu_fns, 0, sizeof(icu_fns));
    }
    Tcl_MutexUnlock(&icu_mutex);
}

/*
 *------------------------------------------------------------------------
 *
 * IcuFindSymbol --
 *
 *	Finds an ICU symbol in a shared library and returns its value.
 *
 *      Caller must be holding icu_mutex lock.
 *
 * Results:
 *	Returns the symbol value or NULL if not found.
 *
 *------------------------------------------------------------------------
 */
static void *
IcuFindSymbol(
    Tcl_LoadHandle loadH, /* Handle to shared library containing symbol */
    const char *name,     /* Name of function */
    const char *suffix    /* Suffix that may be present */
)
{
    /*
     * ICU symbols may have a version suffix depending on how it was built.
     * Rather than try both forms every time, suffixConvention remembers if a
     * suffix is needed (all functions will have it, or none will)
     * 0 - don't know, 1 - have suffix, -1 - no suffix
     */
    static int suffixConvention = 0;
    char symbol[256];
    void *value = NULL;

    /* Note we only update suffixConvention on a positive result */

    strcpy(symbol, name);
    if (suffixConvention <= 0) {
	/* Either don't need suffix or don't know if we do */
	value = Tcl_FindSymbol(NULL, loadH, symbol);
	if (value) {
	    suffixConvention = -1; /* Remember that no suffixes present */
	    return value;
	}
    }
    if (suffixConvention >= 0) {
	/* Either need suffix or don't know if we do */
	strcat(symbol, suffix);
	value = Tcl_FindSymbol(NULL, loadH, symbol);
	if (value) {
	    suffixConvention = 1;
	}
    }
    return value;
}

/*
 *------------------------------------------------------------------------
 *
 * TclIcuInit --
 *
 *	Load the ICU commands into the given interpreter. If the ICU
 *	commands have never previously been loaded, the ICU libraries are
 *	loaded first.
 *
 *------------------------------------------------------------------------
 */
static void
TclIcuInit(
    Tcl_Interp *interp)
{
    Tcl_MutexLock(&icu_mutex);
    char icuversion[4] = "_80"; /* Highest ICU version + 1 */

    /*
     * The initialization below clones the one from Tk. May need revisiting.
     * ICU shared library names as well as function names *may* be versioned.
     * See https://unicode-org.github.io/icu/userguide/icu4c/packaging.html
     * for the gory details.
     */
    if (icu_fns.nopen == 0) {
	int i = 0;
	Tcl_Obj *nameobj;
	static const char *iculibs[] = {
#if defined(_WIN32)
#  define DLLNAME "icu%s%s.dll"
	    "icuuc??.dll", /* Windows, user-provided */
	    NULL,
	    "cygicuuc??.dll", /* When running under Cygwin */
#elif defined(__CYGWIN__)
#  define DLLNAME "cygicu%s%s.dll"
	    "cygicuuc??.dll",
#elif defined(MAC_OSX_TCL)
#  define DLLNAME "libicu%s.%s.dylib"
	    "libicuuc.??.dylib",
#else
#  define DLLNAME "libicu%s.so.%s"
	    "libicuuc.so.??",
#endif
	    NULL
	};

	/* Going back down to ICU version 60 */
	while ((icu_fns.libs[0] == NULL) && (icuversion[1] >= '6')) {
	    if (--icuversion[2] < '0') {
		icuversion[1]--; icuversion[2] = '9';
	    }
#if defined(__CYGWIN__)
	    i = 2;
#else
	    i = 0;
#endif
	    while (iculibs[i] != NULL) {
		Tcl_ResetResult(interp);
		nameobj = Tcl_NewStringObj(iculibs[i], TCL_AUTO_LENGTH);
		char *nameStr = Tcl_GetString(nameobj);
		char *p = strchr(nameStr, '?');

		if (p != NULL) {
		    memcpy(p, icuversion+1, 2);
		}
		Tcl_IncrRefCount(nameobj);
		if (Tcl_LoadFile(interp, nameobj, NULL, 0, NULL,
			&icu_fns.libs[0]) == TCL_OK) {
		    if (p == NULL) {
			icuversion[0] = '\0';
		    }
		    Tcl_DecrRefCount(nameobj);
		    break;
		}
		Tcl_DecrRefCount(nameobj);
		++i;
	    }
	}
	if (icu_fns.libs[0] != NULL) {
	    /* Loaded icuuc, load others with the same version */
	    nameobj = Tcl_ObjPrintf(DLLNAME, "i18n", icuversion+1);
	    Tcl_IncrRefCount(nameobj);
	    /* Ignore errors. Calls to contained functions will fail. */
	    (void) Tcl_LoadFile(interp, nameobj, NULL, 0, NULL, &icu_fns.libs[1]);
	    Tcl_DecrRefCount(nameobj);
	}
#ifdef _WIN32
	/*
	 * On Windows, if no ICU install found, look for the system's
	 * (Win10 1703 or later). There are two cases. Newer systems
	 * have icu.dll containing all functions. Older systems have
	 * icucc.dll and icuin.dll
	 */
	if (icu_fns.libs[0] == NULL) {
	    Tcl_ResetResult(interp);
	    nameobj = Tcl_NewStringObj("icu.dll", TCL_AUTO_LENGTH);
	    Tcl_IncrRefCount(nameobj);
	    if (Tcl_LoadFile(interp, nameobj, NULL, 0, NULL, &icu_fns.libs[0])
		    == TCL_OK) {
		/* Reload same for second set of functions. */
		(void) Tcl_LoadFile(interp, nameobj, NULL, 0, NULL,
			&icu_fns.libs[1]);
		/* Functions do NOT have version suffixes */
		icuversion[0] = '\0';
	    }
	    Tcl_DecrRefCount(nameobj);
	}
	if (icu_fns.libs[0] == NULL) {
	    /* No icu.dll. Try last fallback */
	    Tcl_ResetResult(interp);
	    nameobj = Tcl_NewStringObj("icuuc.dll", TCL_AUTO_LENGTH);
	    Tcl_IncrRefCount(nameobj);
	    if (Tcl_LoadFile(interp, nameobj, NULL, 0, NULL, &icu_fns.libs[0])
		    == TCL_OK) {
		Tcl_DecrRefCount(nameobj);
		nameobj = Tcl_NewStringObj("icuin.dll", TCL_AUTO_LENGTH);
		Tcl_IncrRefCount(nameobj);
		(void) Tcl_LoadFile(interp, nameobj, NULL, 0, NULL,
			&icu_fns.libs[1]);
		/* Functions do NOT have version suffixes */
		icuversion[0] = '\0';
	    }
	    Tcl_DecrRefCount(nameobj);
	}
#endif // _WIN32

	/* Symbol may have version (Windows, FreeBSD), or not (Linux) */

#define ICUUC_SYM(name)                                                   \
    do {                                                                  \
	icu_fns._##name =                                                 \
	    (fn_##name)IcuFindSymbol(icu_fns.libs[0], #name, icuversion); \
    } while (0)

	if (icu_fns.libs[0] != NULL) {
	    ICUUC_SYM(u_cleanup);
	    ICUUC_SYM(u_errorName);
	    ICUUC_SYM(u_strFromUTF32);
	    ICUUC_SYM(u_strFromUTF32WithSub);
	    ICUUC_SYM(u_strToUTF32);
	    ICUUC_SYM(u_strToUTF32WithSub);

	    ICUUC_SYM(ucnv_close);
	    ICUUC_SYM(ucnv_countAliases);
	    ICUUC_SYM(ucnv_countAvailable);
	    ICUUC_SYM(ucnv_fromUChars);
	    ICUUC_SYM(ucnv_getAlias);
	    ICUUC_SYM(ucnv_getAvailableName);
	    ICUUC_SYM(ucnv_open);
	    ICUUC_SYM(ucnv_setFromUCallBack);
	    ICUUC_SYM(ucnv_setToUCallBack);
	    ICUUC_SYM(ucnv_toUChars);
	    ICUUC_SYM(UCNV_FROM_U_CALLBACK_STOP);
	    ICUUC_SYM(UCNV_TO_U_CALLBACK_STOP);

	    ICUUC_SYM(ubrk_open);
	    ICUUC_SYM(ubrk_close);
	    ICUUC_SYM(ubrk_preceding);
	    ICUUC_SYM(ubrk_following);
	    ICUUC_SYM(ubrk_previous);
	    ICUUC_SYM(ubrk_next);
	    ICUUC_SYM(ubrk_setText);

	    ICUUC_SYM(uenum_close);
	    ICUUC_SYM(uenum_count);
	    ICUUC_SYM(uenum_next);

	    ICUUC_SYM(unorm2_getNFCInstance);
	    ICUUC_SYM(unorm2_getNFDInstance);
	    ICUUC_SYM(unorm2_getNFKCInstance);
	    ICUUC_SYM(unorm2_getNFKDInstance);
	    ICUUC_SYM(unorm2_normalize);
#undef ICUUC_SYM
	}

#define ICUIN_SYM(name)                                                   \
    do {                                                                  \
	icu_fns._##name =                                                 \
	    (fn_##name)IcuFindSymbol(icu_fns.libs[1], #name, icuversion); \
    } while (0)

	if (icu_fns.libs[1] != NULL) {
	    ICUIN_SYM(ucsdet_close);
	    ICUIN_SYM(ucsdet_detect);
	    ICUIN_SYM(ucsdet_detectAll);
	    ICUIN_SYM(ucsdet_getName);
	    ICUIN_SYM(ucsdet_getAllDetectableCharsets);
	    ICUIN_SYM(ucsdet_open);
	    ICUIN_SYM(ucsdet_setText);
#undef ICUIN_SYM
	}
    }

    if (icu_fns.libs[0] != NULL) {
	/*
	 * Note refcounts updated BEFORE command definition to protect
	 * against self redefinition.
	 */
	if (icu_fns.libs[1] != NULL) {
	    /* Commands needing both libraries */

	    /* Ref count number of commands */
	    icu_fns.nopen += 3;
	    Tcl_CreateObjCommand(interp,  "::tcl::unsupported::icu::convertto",
				 IcuConverttoObjCmd, 0, TclIcuCleanup);
	    Tcl_CreateObjCommand(interp,  "::tcl::unsupported::icu::convertfrom",
				 IcuConvertfromObjCmd, 0, TclIcuCleanup);
	    Tcl_CreateObjCommand(interp,  "::tcl::unsupported::icu::detect",
		    IcuDetectObjCmd, 0, TclIcuCleanup);
	}

	/* Commands needing only libs[0] (icuuc) */

	/* Ref count number of commands */
	icu_fns.nopen += 3; /* UPDATE AS CMDS ADDED/DELETED BELOW */
	Tcl_CreateObjCommand(interp, "::tcl::unsupported::icu::converters",
		IcuConverterNamesObjCmd, 0, TclIcuCleanup);
	Tcl_CreateObjCommand(interp, "::tcl::unsupported::icu::aliases",
		IcuConverterAliasesObjCmd, 0, TclIcuCleanup);
	Tcl_CreateObjCommand(interp, "::tcl::unsupported::icu::normalize",
		IcuNormalizeObjCmd, 0, TclIcuCleanup);
    }

    Tcl_MutexUnlock(&icu_mutex);
}

/*
 *------------------------------------------------------------------------
 *
 * TclLoadIcuObjCmd --
 *
 *	Loads and initializes ICU
 *
 * Results:
 *	TCL_OK    - Success.
 *	TCL_ERROR - Error.
 *
 * Side effects:
 *	Interpreter result holds result or error message.
 *
 *------------------------------------------------------------------------
 */
int
TclLoadIcuObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1 , objv, "");
	return TCL_ERROR;
    }
    TclIcuInit(interp);
    return TCL_OK;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * coding: utf-8
 * End:
 */

Changes to generic/tclIndexObj.c.

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
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
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



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







-
-
-
+
+
+













-
+



-
+
-
-
-
+
-
-
-
+
-
-








-
+




-
+
+












-
-
+
+











-
+







/*
 * tclIndexObj.c --
 *
 *	This file implements objects of type "index". This object type is used
 *	to lookup a keyword in a table of valid values and cache the index of
 *	the matching entry. Also provides table-based argv/argc processing.
 *
 * Copyright (c) 1990-1994 The Regents of the University of California.
 * Copyright (c) 1997 Sun Microsystems, Inc.
 * Copyright (c) 2006 Sam Bromley.
 * Copyright © 1990-1994 The Regents of the University of California.
 * Copyright © 1997 Sun Microsystems, Inc.
 * Copyright © 2006 Sam Bromley.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

/*
 * Prototypes for functions defined later in this file:
 */

static int		GetIndexFromObjList(Tcl_Interp *interp,
			    Tcl_Obj *objPtr, Tcl_Obj *tableObjPtr,
			    const char *msg, int flags, int *indexPtr);
			    const char *msg, int flags, Tcl_Size *indexPtr);
static void		UpdateStringOfIndex(Tcl_Obj *objPtr);
static void		DupIndex(Tcl_Obj *srcPtr, Tcl_Obj *dupPtr);
static void		FreeIndex(Tcl_Obj *objPtr);
static int		PrefixAllObjCmd(ClientData clientData,
static Tcl_ObjCmdProc PrefixAllObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		PrefixLongestObjCmd(ClientData clientData,
static Tcl_ObjCmdProc PrefixLongestObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		PrefixMatchObjCmd(ClientData clientData,
static Tcl_ObjCmdProc PrefixMatchObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static void		PrintUsage(Tcl_Interp *interp,
			    const Tcl_ArgvInfo *argTable);

/*
 * The structure below defines the index Tcl object type by means of functions
 * that can be invoked by generic object code.
 */

static const Tcl_ObjType indexType = {
const Tcl_ObjType tclIndexType = {
    "index",			/* name */
    FreeIndex,			/* freeIntRepProc */
    DupIndex,			/* dupIntRepProc */
    UpdateStringOfIndex,	/* updateStringProc */
    NULL			/* setFromAnyProc */
    NULL,			/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

/*
 * The definition of the internal representation of the "index" object; The
 * internalRep.twoPtrValue.ptr1 field of an object of "index" type will be a
 * pointer to one of these structures.
 *
 * Keep this structure declaration in sync with tclTestObj.c
 */

typedef struct {
    void *tablePtr;		/* Pointer to the table of strings */
    size_t offset;			/* Offset between table entries */
    size_t index;			/* Selected index into table. */
    Tcl_Size offset;	/* Offset between table entries */
    Tcl_Size index;		/* Selected index into table. */
} IndexRep;

/*
 * The following macros greatly simplify moving through a table...
 */

#define STRING_AT(table, offset) \
	(*((const char *const *)(((char *)(table)) + (offset))))
#define NEXT_ENTRY(table, offset) \
	(&(STRING_AT(table, offset)))
#define EXPAND_OF(indexRep) \
	STRING_AT((indexRep)->tablePtr, (indexRep)->offset*(indexRep)->index)
	(((indexRep)->index != TCL_INDEX_NONE) ? STRING_AT((indexRep)->tablePtr, (indexRep)->offset*(indexRep)->index) : "")

/*
 *----------------------------------------------------------------------
 *
 * GetIndexFromObjList --
 *
 *	This procedure looks up an object's value in a table of strings and
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
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







-
+


+
-
+





-
+


-
+















-
+











-
+
















-
-
-
-
-
+
+
+
+
+
+









+









-
+


-
-
+
+

-
+





-
+

-
-
-
+
+
+
+
+
+
+





-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
+







-
-
+
+


+
+
+







-
+







    Tcl_Interp *interp,		/* Used for error reporting if not NULL. */
    Tcl_Obj *objPtr,		/* Object containing the string to lookup. */
    Tcl_Obj *tableObjPtr,	/* List of strings to compare against the
				 * value of objPtr. */
    const char *msg,		/* Identifying word to use in error
				 * messages. */
    int flags,			/* 0 or TCL_EXACT */
    int *indexPtr)		/* Place to store resulting integer index. */
    Tcl_Size *indexPtr)		/* Place to store resulting index. */
{

    Tcl_Size objc, t;
    int objc, result, t;
    int result;
    Tcl_Obj **objv;
    const char **tablePtr;

    /*
     * Use Tcl_GetIndexFromObjStruct to do the work to avoid duplicating most
     * of the code there. This is a bit ineffiecient but simpler.
     * of the code there. This is a bit inefficient but simpler.
     */

    result = Tcl_ListObjGetElements(interp, tableObjPtr, &objc, &objv);
    result = TclListObjGetElements(interp, tableObjPtr, &objc, &objv);
    if (result != TCL_OK) {
	return result;
    }

    /*
     * Build a string table from the list.
     */

    tablePtr = (const char **)Tcl_Alloc((objc + 1) * sizeof(char *));
    for (t = 0; t < objc; t++) {
	if (objv[t] == objPtr) {
	    /*
	     * An exact match is always chosen, so we can stop here.
	     */

	    Tcl_Free((void *)tablePtr);
	    Tcl_Free(tablePtr);
	    *indexPtr = t;
	    return TCL_OK;
	}

	tablePtr[t] = TclGetString(objv[t]);
    }
    tablePtr[objc] = NULL;

    result = Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr,
	    sizeof(char *), msg, flags | TCL_INDEX_TEMP_TABLE, indexPtr);

    Tcl_Free((void *)tablePtr);
    Tcl_Free(tablePtr);

    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetIndexFromObjStruct --
 *
 *	This function looks up an object's value given a starting string and
 *	an offset for the amount of space between strings. This is useful when
 *	the strings are embedded in some other kind of array.
 *
 * Results:
 *	If the value of objPtr is identical to or a unique abbreviation for
 *	one of the entries in tablePtr, then the return value is TCL_OK and
 *	the index of the matching entry is stored at *indexPtr. If there isn't
 *	a proper match, then TCL_ERROR is returned and an error message is
 *	left in interp's result (unless interp is NULL). The msg argument is
 *	used in the error message; for example, if msg has the value "option"
 *	then the error message will say something like 'bad option "foo": must
 *	the index of the matching entry is stored at *indexPtr
 *	(unless indexPtr is NULL). If there isn't a proper match, then
 *	TCL_ERROR is returned and an error message is left in interp's
 *	result (unless interp is NULL). The msg argument is used in the
 *	error message; for example, if msg has the value "option" then
 *	the error message will say something like 'bad option "foo": must
 *	be ...'
 *
 * Side effects:
 *	The result of the lookup is cached as the internal rep of objPtr, so
 *	that repeated lookups can be done quickly.
 *
 *----------------------------------------------------------------------
 */

#undef Tcl_GetIndexFromObjStruct
int
Tcl_GetIndexFromObjStruct(
    Tcl_Interp *interp,		/* Used for error reporting if not NULL. */
    Tcl_Obj *objPtr,		/* Object containing the string to lookup. */
    const void *tablePtr,	/* The first string in the table. The second
				 * string will be at this address plus the
				 * offset, the third plus the offset again,
				 * etc. The last entry must be NULL and there
				 * must not be duplicate entries. */
    size_t offset,			/* The number of bytes between entries */
    Tcl_Size offset,		/* The number of bytes between entries */
    const char *msg,		/* Identifying word to use in error
				 * messages. */
    int flags,			/* 0 or TCL_EXACT */
    int *indexPtr)		/* Place to store resulting integer index. */
    int flags,			/* 0, TCL_EXACT, TCL_NULL_OK or TCL_INDEX_TEMP_TABLE */
    void *indexPtr)		/* Place to store resulting index. */
{
    int index, idx, numAbbrev;
    Tcl_Size index, idx, numAbbrev;
    const char *key, *p1;
    const char *p2;
    const char *const *entryPtr;
    Tcl_Obj *resultPtr;
    IndexRep *indexRep;
    const Tcl_ObjIntRep *irPtr;
    const Tcl_ObjInternalRep *irPtr;

    /* Protect against invalid values, like -1 or 0. */
    if (offset+1 <= sizeof(char *)) {
	offset = sizeof(char *);
    if (offset < (Tcl_Size)sizeof(char *)) {
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "Invalid %s value %" TCL_SIZE_MODIFIER "d.",
		    "struct offset", offset));
	}
	return TCL_ERROR;
    }
    /*
     * See if there is a valid cached result from a previous lookup.
     */

    if (!(flags & TCL_INDEX_TEMP_TABLE)) {
    irPtr = TclFetchIntRep(objPtr, &indexType);
    if (irPtr) {
	indexRep = (IndexRep *)irPtr->twoPtrValue.ptr1;
	if (indexRep->tablePtr==tablePtr && indexRep->offset==offset) {
	    *indexPtr = indexRep->index;
    if (objPtr && !(flags & TCL_INDEX_TEMP_TABLE)) {
	irPtr = TclFetchInternalRep(objPtr, &tclIndexType);
	if (irPtr) {
	    indexRep = (IndexRep *)irPtr->twoPtrValue.ptr1;
	    if ((indexRep->tablePtr == tablePtr)
		    && (indexRep->offset == offset)
		    && (indexRep->index != TCL_INDEX_NONE)) {
		index = indexRep->index;
	    return TCL_OK;
	}
    }
		goto uncachedDone;
	    }
	}
    }

    /*
     * Lookup the value of the object in the table. Accept unique
     * abbreviations unless TCL_EXACT is set in flags.
     */

    key = TclGetString(objPtr);
    index = -1;
    key = objPtr ? TclGetString(objPtr) : "";
    index = TCL_INDEX_NONE;
    numAbbrev = 0;

    if (!*key && (flags & TCL_NULL_OK)) {
	goto uncachedDone;
    }
    /*
     * Scan the table looking for one of:
     *  - An exact match (always preferred)
     *  - A single abbreviation (allowed depending on flags)
     *  - Several abbreviations (never allowed, but overridden by exact match)
     */

    for (entryPtr = (const char* const*)tablePtr, idx = 0; *entryPtr != NULL;
    for (entryPtr = (const char *const *)tablePtr, idx = 0; *entryPtr != NULL;
	    entryPtr = NEXT_ENTRY(entryPtr, offset), idx++) {
	for (p1 = key, p2 = *entryPtr; *p1 == *p2; p1++, p2++) {
	    if (*p1 == '\0') {
		index = idx;
		goto done;
	    }
	}
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
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
366
367
368
369
370
371
372
373







-
-
+
+



-
+



-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+











-
+





-
+

-
+


-
+


-
+

-
+

-
+




+
+
-
+
+

-
+



+
+
+







  done:
    /*
     * Cache the found representation. Note that we want to avoid allocating a
     * new internal-rep if at all possible since that is potentially a slow
     * operation.
     */

    if (!(flags & TCL_INDEX_TEMP_TABLE)) {
    irPtr = TclFetchIntRep(objPtr, &indexType);
    if (objPtr && (index != TCL_INDEX_NONE) && !(flags & TCL_INDEX_TEMP_TABLE)) {
    irPtr = TclFetchInternalRep(objPtr, &tclIndexType);
    if (irPtr) {
	indexRep = (IndexRep *)irPtr->twoPtrValue.ptr1;
    } else {
	Tcl_ObjIntRep ir;
	Tcl_ObjInternalRep ir;

	indexRep = (IndexRep*)Tcl_Alloc(sizeof(IndexRep));
	ir.twoPtrValue.ptr1 = indexRep;
	Tcl_StoreIntRep(objPtr, &indexType, &ir);
	Tcl_StoreInternalRep(objPtr, &tclIndexType, &ir);
    }
    indexRep->tablePtr = (void *) tablePtr;
    indexRep->offset = offset;
    indexRep->index = index;
    }

  uncachedDone:
    if (indexPtr != NULL) {
	flags &= (30-(int)(sizeof(int)<<1));
	if (flags) {
	    if (flags == sizeof(uint16_t)<<1) {
		*(uint16_t *)indexPtr = index;
		return TCL_OK;
	    } else if (flags == (int)(sizeof(uint8_t)<<1)) {
		*(uint8_t *)indexPtr = index;
		return TCL_OK;
	    } else if (flags == (int)(sizeof(int64_t)<<1)) {
		*(int64_t *)indexPtr = index;
		return TCL_OK;
	    } else if (flags == (int)(sizeof(int32_t)<<1)) {
		*(int32_t *)indexPtr = index;
		return TCL_OK;
	    }
	}
    *indexPtr = index;
	*(int *)indexPtr = index;
    }
    return TCL_OK;

  error:
    if (interp != NULL) {
	/*
	 * Produce a fancy error message.
	 */

	int count = 0;

	TclNewObj(resultPtr);
	entryPtr = (const char* const *)tablePtr;
	entryPtr = (const char *const *)tablePtr;
	while ((*entryPtr != NULL) && !**entryPtr) {
	    entryPtr = NEXT_ENTRY(entryPtr, offset);
	}
	Tcl_AppendStringsToObj(resultPtr,
		(numAbbrev>1 && !(flags & TCL_EXACT) ? "ambiguous " : "bad "),
		msg, " \"", key, NULL);
		msg, " \"", key, (char *)NULL);
	if (*entryPtr == NULL) {
	    Tcl_AppendStringsToObj(resultPtr, "\": no valid options", NULL);
	    Tcl_AppendStringsToObj(resultPtr, "\": no valid options", (char *)NULL);
	} else {
	    Tcl_AppendStringsToObj(resultPtr, "\": must be ",
		    *entryPtr, NULL);
		    *entryPtr, (char *)NULL);
	    entryPtr = NEXT_ENTRY(entryPtr, offset);
	    while (*entryPtr != NULL) {
		if (*NEXT_ENTRY(entryPtr, offset) == NULL) {
		if ((*NEXT_ENTRY(entryPtr, offset) == NULL) && !(flags & TCL_NULL_OK)) {
		    Tcl_AppendStringsToObj(resultPtr, (count > 0 ? "," : ""),
			    " or ", *entryPtr, NULL);
			    " or ", *entryPtr, (char *)NULL);
		} else if (**entryPtr) {
		    Tcl_AppendStringsToObj(resultPtr, ", ", *entryPtr, NULL);
		    Tcl_AppendStringsToObj(resultPtr, ", ", *entryPtr, (char *)NULL);
		    count++;
		}
		entryPtr = NEXT_ENTRY(entryPtr, offset);
	    }
	    if ((flags & TCL_NULL_OK)) {
		Tcl_AppendStringsToObj(resultPtr, ", or \"\"", (char *)NULL);
	}
	    }
	}
	Tcl_SetObjResult(interp, resultPtr);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", msg, key, NULL);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", msg, key, (char *)NULL);
    }
    return TCL_ERROR;
}
/* #define again, needed below */
#define Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags, indexPtr) \
	((Tcl_GetIndexFromObjStruct)((interp), (objPtr), (tablePtr), (offset), (msg), (flags)|(int)(sizeof(*(indexPtr))<<1), (indexPtr)))

/*
 *----------------------------------------------------------------------
 *
 * UpdateStringOfIndex --
 *
 *	This function is called to convert a Tcl object from index internal
350
351
352
353
354
355
356
357

358
359
360
361
362
363
364
382
383
384
385
386
387
388

389
390
391
392
393
394
395
396







-
+







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

static void
UpdateStringOfIndex(
    Tcl_Obj *objPtr)
{
    IndexRep *indexRep = (IndexRep *)TclFetchIntRep(objPtr, &indexType)->twoPtrValue.ptr1;
    IndexRep *indexRep = (IndexRep *)TclFetchInternalRep(objPtr, &tclIndexType)->twoPtrValue.ptr1;
    const char *indexStr = EXPAND_OF(indexRep);

    Tcl_InitStringRep(objPtr, indexStr, strlen(indexStr));
}

/*
 *----------------------------------------------------------------------
379
380
381
382
383
384
385
386

387
388
389

390
391
392
393

394
395
396
397
398
399
400
411
412
413
414
415
416
417

418
419
420

421
422
423
424

425
426
427
428
429
430
431
432







-
+


-
+



-
+







 */

static void
DupIndex(
    Tcl_Obj *srcPtr,
    Tcl_Obj *dupPtr)
{
    Tcl_ObjIntRep ir;
    Tcl_ObjInternalRep ir;
    IndexRep *dupIndexRep = (IndexRep *)Tcl_Alloc(sizeof(IndexRep));

    memcpy(dupIndexRep, TclFetchIntRep(srcPtr, &indexType)->twoPtrValue.ptr1,
    memcpy(dupIndexRep, TclFetchInternalRep(srcPtr, &tclIndexType)->twoPtrValue.ptr1,
	    sizeof(IndexRep));

    ir.twoPtrValue.ptr1 = dupIndexRep;
    Tcl_StoreIntRep(dupPtr, &indexType, &ir);
    Tcl_StoreInternalRep(dupPtr, &tclIndexType, &ir);
}

/*
 *----------------------------------------------------------------------
 *
 * FreeIndex --
 *
410
411
412
413
414
415
416
417

418
419
420
421
422
423
424
442
443
444
445
446
447
448

449
450
451
452
453
454
455
456







-
+







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

static void
FreeIndex(
    Tcl_Obj *objPtr)
{
    Tcl_Free(TclFetchIntRep(objPtr, &indexType)->twoPtrValue.ptr1);
    Tcl_Free(TclFetchInternalRep(objPtr, &tclIndexType)->twoPtrValue.ptr1);
    objPtr->typePtr = NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * TclInitPrefixCmd --
467
468
469
470
471
472
473
474

475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572

573
574
575
576
577
578
579
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
558
559
560
561
562

563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578

579
580
581
582
583
584

585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603

604
605
606
607
608
609
610
611







-
+




-
-
+
+








-
+







-
-
+
+


-
+






-
-
+
+








-
-
+
+



-
+







-
+















-
+





-
+


















-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PrefixMatchObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int flags = 0, result, index;
    int dummyLength, i, errorLength;
    int flags = 0, result;
    Tcl_Size errorLength, i;
    Tcl_Obj *errorPtr = NULL;
    const char *message = "option";
    Tcl_Obj *tablePtr, *objPtr, *resultPtr;
    static const char *const matchOptions[] = {
	"-error", "-exact", "-message", NULL
    };
    enum matchOptionsEnum {
	PRFMATCH_ERROR, PRFMATCH_EXACT, PRFMATCH_MESSAGE
    };
    } index;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "?options? table string");
	return TCL_ERROR;
    }

    for (i = 1; i < (objc - 2); i++) {
	if (Tcl_GetIndexFromObj(interp, objv[i], matchOptions, "option", 0,
		&index) != TCL_OK) {
	if (Tcl_GetIndexFromObjStruct(interp, objv[i], matchOptions,
		sizeof(char *), "option", 0, &index) != TCL_OK) {
	    return TCL_ERROR;
	}
	switch ((enum matchOptionsEnum) index) {
	switch (index) {
	case PRFMATCH_EXACT:
	    flags |= TCL_EXACT;
	    break;
	case PRFMATCH_MESSAGE:
	    if (i > objc-4) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"missing value for -message", -1));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NOARG", NULL);
			"missing value for -message", TCL_INDEX_NONE));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NOARG", (char *)NULL);
		return TCL_ERROR;
	    }
	    i++;
	    message = TclGetString(objv[i]);
	    break;
	case PRFMATCH_ERROR:
	    if (i > objc-4) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"missing value for -error", -1));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NOARG", NULL);
			"missing value for -error", TCL_INDEX_NONE));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NOARG", (char *)NULL);
		return TCL_ERROR;
	    }
	    i++;
	    result = Tcl_ListObjLength(interp, objv[i], &errorLength);
	    result = TclListObjLength(interp, objv[i], &errorLength);
	    if (result != TCL_OK) {
		return TCL_ERROR;
	    }
	    if ((errorLength % 2) != 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"error options must have an even number of elements",
			-1));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "DICTIONARY", NULL);
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "DICTIONARY", (char *)NULL);
		return TCL_ERROR;
	    }
	    errorPtr = objv[i];
	    break;
	}
    }

    tablePtr = objv[objc - 2];
    objPtr = objv[objc - 1];

    /*
     * Check that table is a valid list first, since we want to handle that
     * error case regardless of level.
     */

    result = Tcl_ListObjLength(interp, tablePtr, &dummyLength);
    result = TclListObjLength(interp, tablePtr, &i);
    if (result != TCL_OK) {
	return result;
    }

    result = GetIndexFromObjList(interp, objPtr, tablePtr, message, flags,
	    &index);
	    &i);
    if (result != TCL_OK) {
	if (errorPtr != NULL && errorLength == 0) {
	    Tcl_ResetResult(interp);
	    return TCL_OK;
	} else if (errorPtr == NULL) {
	    return TCL_ERROR;
	}

	if (Tcl_IsShared(errorPtr)) {
	    errorPtr = Tcl_DuplicateObj(errorPtr);
	}
	Tcl_ListObjAppendElement(interp, errorPtr,
		Tcl_NewStringObj("-code", 5));
	Tcl_ListObjAppendElement(interp, errorPtr, Tcl_NewWideIntObj(result));

	return Tcl_SetReturnOptions(interp, errorPtr);
    }

    result = Tcl_ListObjIndex(interp, tablePtr, index, &resultPtr);
    result = Tcl_ListObjIndex(interp, tablePtr, i, &resultPtr);
    if (result != TCL_OK) {
	return result;
    }
    Tcl_SetObjResult(interp, resultPtr);
    return TCL_OK;
}

591
592
593
594
595
596
597
598

599
600
601
602
603
604


605
606
607
608
609
610
611
612
613

614
615
616
617
618
619
620
623
624
625
626
627
628
629

630
631
632
633
634


635
636
637
638
639
640
641
642
643
644

645
646
647
648
649
650
651
652







-
+




-
-
+
+








-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PrefixAllObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int tableObjc, result, t;
    size_t length, elemLength;
    int result;
    Tcl_Size length, elemLength, tableObjc, t;
    const char *string, *elemString;
    Tcl_Obj **tableObjv, *resultPtr;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "table string");
	return TCL_ERROR;
    }

    result = Tcl_ListObjGetElements(interp, objv[1], &tableObjc, &tableObjv);
    result = TclListObjGetElements(interp, objv[1], &tableObjc, &tableObjv);
    if (result != TCL_OK) {
	return result;
    }
    resultPtr = Tcl_NewListObj(0, NULL);
    string = TclGetStringFromObj(objv[2], &length);

    for (t = 0; t < tableObjc; t++) {
649
650
651
652
653
654
655
656

657
658
659
660
661
662


663
664
665
666
667
668
669
670
671

672
673
674
675
676
677
678
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
707
708
709
710







-
+




-
-
+
+








-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PrefixLongestObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int tableObjc, result, t;
    size_t i, length, elemLength, resultLength;
    int result;
    Tcl_Size i, length, elemLength, resultLength, tableObjc, t;
    const char *string, *elemString, *resultString;
    Tcl_Obj **tableObjv;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "table string");
	return TCL_ERROR;
    }

    result = Tcl_ListObjGetElements(interp, objv[1], &tableObjc, &tableObjv);
    result = TclListObjGetElements(interp, objv[1], &tableObjc, &tableObjv);
    if (result != TCL_OK) {
	return result;
    }
    string = TclGetStringFromObj(objv[2], &length);

    resultString = NULL;
    resultLength = 0;
714
715
716
717
718
719
720
721

722
723
724
725
726
727
728
746
747
748
749
750
751
752

753
754
755
756
757
758
759
760







-
+








	    for (i = 0; i < resultLength; i++) {
		if (resultString[i] != elemString[i]) {
		    /*
		     * Adjust in case we stopped in the middle of a UTF char.
		     */

		    resultLength = TclUtfPrev(&resultString[i+1],
		    resultLength = Tcl_UtfPrev(&resultString[i+1],
			    resultString) - resultString;
		    break;
		}
	    }
	}
    }
    if (resultLength > 0) {
770
771
772
773
774
775
776
777

778
779
780
781
782
783
784
785
786

787
788

789
790
791
792
793
794
795

796
797

798
799
800
801
802


803
804
805
806
807
808



809
810
811
812
813
814
815
816
817
818
819

820
821

822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837

838
839
840
841
842
843
844

845
846

847
848
849
850
851
852
853
802
803
804
805
806
807
808

809
810
811
812
813
814
815
816


817
818

819
820
821
822
823
824
825

826
827

828
829
830
831


832
833
834
835
836



837
838
839
840
841









842
843

844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859

860
861
862
863
864
865
866

867
868

869
870
871
872
873
874
875
876







-
+







-
-
+

-
+






-
+

-
+



-
-
+
+



-
-
-
+
+
+


-
-
-
-
-
-
-
-
-
+

-
+















-
+






-
+

-
+







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

void
Tcl_WrongNumArgs(
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments to print from objv. */
    Tcl_Size objc,			/* Number of arguments to print from objv. */
    Tcl_Obj *const objv[],	/* Initial argument objects, which should be
				 * included in the error message. */
    const char *message)	/* Error message to print after the leading
				 * objects in objv. The message may be
				 * NULL. */
{
    Tcl_Obj *objPtr;
    int i;
    size_t len, elemLen;
    Tcl_Size i, len, elemLen;
    char flags;
    Interp *iPtr = (Interp *) interp;
    Interp *iPtr = (Interp *)interp;
    const char *elementStr;

    TclNewObj(objPtr);
    if (iPtr->flags & INTERP_ALTERNATE_WRONG_ARGS) {
	iPtr->flags &= ~INTERP_ALTERNATE_WRONG_ARGS;
	Tcl_AppendObjToObj(objPtr, Tcl_GetObjResult(interp));
	Tcl_AppendToObj(objPtr, " or \"", -1);
	Tcl_AppendToObj(objPtr, " or \"", TCL_INDEX_NONE);
    } else {
	Tcl_AppendToObj(objPtr, "wrong # args: should be \"", -1);
	Tcl_AppendToObj(objPtr, "wrong # args: should be \"", TCL_INDEX_NONE);
    }

    /*
     * Check to see if we are processing an ensemble implementation, and if so
     * rewrite the results in terms of how the ensemble was invoked.
     * If processing an ensemble implementation, rewrite the results in
     * terms of how the ensemble was invoked.
     */

    if (iPtr->ensembleRewrite.sourceObjs != NULL) {
	int toSkip = iPtr->ensembleRewrite.numInsertedObjs;
	int toPrint = iPtr->ensembleRewrite.numRemovedObjs;
	Tcl_Obj *const *origObjv = iPtr->ensembleRewrite.sourceObjs;
	Tcl_Size toSkip = iPtr->ensembleRewrite.numInsertedObjs;
	Tcl_Size toPrint = iPtr->ensembleRewrite.numRemovedObjs;
	Tcl_Obj *const *origObjv = TclEnsembleGetRewriteValues(interp);

	/*
	 * Check for spelling fixes, and substitute the fixed values.
	 */

	if (origObjv[0] == NULL) {
	    origObjv = (Tcl_Obj *const *)origObjv[2];
	}

	/*
	 * We only know how to do rewriting if all the replaced objects are
	 * Only do rewrite the command if all the replaced objects are
	 * actually arguments (in objv) to this function. Otherwise it just
	 * gets too complicated and we'd be better off just giving a slightly
	 * gets too complicated and it's to just give a slightly
	 * confusing error message...
	 */

	if (objc < toSkip) {
	    goto addNormalArgumentsToMessage;
	}

	/*
	 * Strip out the actual arguments that the ensemble inserted.
	 */

	objv += toSkip;
	objc -= toSkip;

	/*
	 * We assume no object is of index type.
	 * Assume no object is of index type.
	 */

	for (i=0 ; i<toPrint ; i++) {
	    /*
	     * Add the element, quoting it if necessary.
	     */
	    const Tcl_ObjIntRep *irPtr;
	    const Tcl_ObjInternalRep *irPtr;

	    if ((irPtr = TclFetchIntRep(origObjv[i], &indexType))) {
	    if ((irPtr = TclFetchInternalRep(origObjv[i], &tclIndexType))) {
		IndexRep *indexRep = (IndexRep *)irPtr->twoPtrValue.ptr1;

		elementStr = EXPAND_OF(indexRep);
		elemLen = strlen(elementStr);
	    } else {
		elementStr = TclGetStringFromObj(origObjv[i], &elemLen);
	    }
866
867
868
869
870
871
872
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
898
899
900
901
902
903
889
890
891
892
893
894
895


896
897
898
899
900
901
902
903
904
905
906
907
908
909

910
911
912
913

914
915

916
917
918

919
920
921
922
923
924
925
926







-
-
+
+












-
+



-
+

-
+


-
+







	    }

	    /*
	     * Add a space if the word is not the last one (which has a
	     * moderately complex condition here).
	     */

	    if (i<toPrint-1 || objc!=0 || message!=NULL) {
		Tcl_AppendStringsToObj(objPtr, " ", NULL);
	    if (i + 1 < toPrint || objc!=0 || message!=NULL) {
		Tcl_AppendStringsToObj(objPtr, " ", (char *)NULL);
	    }
	}
    }

    /*
     * Now add the arguments (other than those rewritten) that the caller took
     * from its calling context.
     */

  addNormalArgumentsToMessage:
    for (i = 0; i < objc; i++) {
	/*
	 * If the object is an index type use the index table which allows for
	 * If the object is an index type, use the index table which allows for
	 * the correct error message even if the subcommand was abbreviated.
	 * Otherwise, just use the string rep.
	 */
	const Tcl_ObjIntRep *irPtr;
	const Tcl_ObjInternalRep *irPtr;

	if ((irPtr = TclFetchIntRep(objv[i], &indexType))) {
	if ((irPtr = TclFetchInternalRep(objv[i], &tclIndexType))) {
	    IndexRep *indexRep = (IndexRep *)irPtr->twoPtrValue.ptr1;

	    Tcl_AppendStringsToObj(objPtr, EXPAND_OF(indexRep), NULL);
	    Tcl_AppendStringsToObj(objPtr, EXPAND_OF(indexRep), (char *)NULL);
	} else {
	    /*
	     * Quote the argument if it contains spaces (Bug 942757).
	     */

	    elementStr = TclGetStringFromObj(objv[i], &elemLen);
	    flags = 0;
916
917
918
919
920
921
922
923
924


925
926
927
928
929
930
931
932
933
934
935

936
937
938


939
940
941
942
943
944
945
939
940
941
942
943
944
945


946
947
948
949
950
951
952
953
954
955
956
957

958
959


960
961
962
963
964
965
966
967
968







-
-
+
+










-
+

-
-
+
+







	}

	/*
	 * Append a space character (" ") if there is more text to follow
	 * (either another element from objv, or the message string).
	 */

	if (i<objc-1 || message!=NULL) {
	    Tcl_AppendStringsToObj(objPtr, " ", NULL);
	if (i + 1 < objc || message!=NULL) {
	    Tcl_AppendStringsToObj(objPtr, " ", (char *)NULL);
	}
    }

    /*
     * Add any trailing message bits and set the resulting string as the
     * interpreter result. Caller is responsible for reporting this as an
     * actual error.
     */

    if (message != NULL) {
	Tcl_AppendStringsToObj(objPtr, message, NULL);
	Tcl_AppendStringsToObj(objPtr, message, (char *)NULL);
    }
    Tcl_AppendStringsToObj(objPtr, "\"", NULL);
    Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL);
    Tcl_AppendStringsToObj(objPtr, "\"", (char *)NULL);
    Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (char *)NULL);
    Tcl_SetObjResult(interp, objPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ParseArgsObjv --
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
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
1024
1025
1026
1027
1028
1029
1030







+





-
+









-
+











-
+

-
+


-
-
+
+
+







 *	Variables may be modified, or procedures may be called. It all depends
 *	on the arguments and their entries in argTable. See the user
 *	documentation for details.
 *
 *----------------------------------------------------------------------
 */

#undef Tcl_ParseArgsObjv
int
Tcl_ParseArgsObjv(
    Tcl_Interp *interp,		/* Place to store error message. */
    const Tcl_ArgvInfo *argTable,
				/* Array of option descriptions. */
    int *objcPtr,		/* Number of arguments in objv. Modified to
    Tcl_Size *objcPtr,		/* Number of arguments in objv. Modified to
				 * hold # args left in objv at end. */
    Tcl_Obj *const *objv,	/* Array of arguments to be parsed. */
    Tcl_Obj ***remObjv)		/* Pointer to array of arguments that were not
				 * processed here. Should be NULL if no return
				 * of arguments is desired. */
{
    Tcl_Obj **leftovers;	/* Array to write back to remObjv on
				 * successful exit. Will include the name of
				 * the command. */
    int nrem;			/* Size of leftovers.*/
    Tcl_Size nrem;		/* Size of leftovers.*/
    const Tcl_ArgvInfo *infoPtr;
				/* Pointer to the current entry in the table
				 * of argument descriptions. */
    const Tcl_ArgvInfo *matchPtr;
				/* Descriptor that matches current argument */
    Tcl_Obj *curArg;		/* Current argument */
    const char *str = NULL;
    char c;		/* Second character of current arg (used for
				 * quick check for matching; use 2nd char.
				 * because first char. will almost always be
				 * '-'). */
    int srcIndex;		/* Location from which to read next argument
    Tcl_Size srcIndex;	/* Location from which to read next argument
				 * from objv. */
    int dstIndex;		/* Used to keep track of current arguments
    Tcl_Size dstIndex;	/* Used to keep track of current arguments
				 * being processed, primarily for error
				 * reporting. */
    int objc;			/* # arguments in objv still to process. */
    size_t length;			/* Number of characters in current argument */
    Tcl_Size objc;		/* # arguments in objv still to process. */
    Tcl_Size length;		/* Number of characters in current argument */
    Tcl_Size gf_ret;		/* Return value from Tcl_ArgvGenFuncProc*/

    if (remObjv != NULL) {
	/*
	 * Then we should copy the name of the command (0th argument). The
	 * upper bound on the number of elements is known, and (undocumented,
	 * but historically true) there should be a NULL argument after the
	 * last result. [Bug 3413857]
1028
1029
1030
1031
1032
1033
1034
1035

1036
1037
1038
1039
1040
1041
1042
1053
1054
1055
1056
1057
1058
1059

1060
1061
1062
1063
1064
1065
1066
1067







-
+







	if (length > 0) {
	    c = str[1];
	} else {
	    c = 0;
	}

	/*
	 * Loop throught the argument descriptors searching for one with the
	 * Loop through the argument descriptors searching for one with the
	 * matching key string. If found, leave a pointer to it in matchPtr.
	 */

	matchPtr = NULL;
	infoPtr = argTable;
	for (; infoPtr != NULL && infoPtr->type != TCL_ARGV_END ; infoPtr++) {
	    if (infoPtr->keyStr == NULL) {
1144
1145
1146
1147
1148
1149
1150






1151
1152
1153
1154

1155
1156

1157



1158
1159
1160
1161
1162
1163
1164
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184

1185
1186

1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198







+
+
+
+
+
+



-
+

-
+

+
+
+







	    if (handlerProc(infoPtr->clientData, argObj, infoPtr->dstPtr)) {
		srcIndex++;
		objc--;
	    }
	    break;
	}
	case TCL_ARGV_GENFUNC: {

	    if (objc > INT_MAX) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"too many (%" TCL_SIZE_MODIFIER "d) arguments for TCL_ARGV_GENFUNC", objc));
		goto error;
	    }
	    Tcl_ArgvGenFuncProc *handlerProc = (Tcl_ArgvGenFuncProc *)
		    infoPtr->srcPtr;

	    objc = handlerProc(infoPtr->clientData, interp, objc,
	    gf_ret = handlerProc(infoPtr->clientData, interp, objc,
		    &objv[srcIndex], infoPtr->dstPtr);
	    if (objc < 0) {
	    if (gf_ret < 0) {
		goto error;
	    } else {
		srcIndex += gf_ret;
		objc -= gf_ret;
	    }
	    break;
	}
	case TCL_ARGV_HELP:
	    PrintUsage(interp, argTable);
	    goto error;
	default:
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
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







-









-
+





-
+








-
+















-
+








-







				/* Array of command-specific argument
				 * descriptions. */
{
    const Tcl_ArgvInfo *infoPtr;
    int width, numSpaces;
#define NUM_SPACES 20
    static const char spaces[] = "                    ";
    char tmp[TCL_DOUBLE_SPACE];
    Tcl_Obj *msg;

    /*
     * First, compute the width of the widest option key, so that we can make
     * everything line up.
     */

    width = 4;
    for (infoPtr = argTable; infoPtr->type != TCL_ARGV_END; infoPtr++) {
	size_t length;
	Tcl_Size length;

	if (infoPtr->keyStr == NULL) {
	    continue;
	}
	length = strlen(infoPtr->keyStr);
	if (length > (size_t)width) {
	if (length > width) {
	    width = length;
	}
    }

    /*
     * Now add the option information, with pretty-printing.
     */

    msg = Tcl_NewStringObj("Command-specific options:", -1);
    msg = Tcl_NewStringObj("Command-specific options:", TCL_INDEX_NONE);
    for (infoPtr = argTable; infoPtr->type != TCL_ARGV_END; infoPtr++) {
	if ((infoPtr->type == TCL_ARGV_HELP) && (infoPtr->keyStr == NULL)) {
	    Tcl_AppendPrintfToObj(msg, "\n%s", infoPtr->helpStr);
	    continue;
	}
	Tcl_AppendPrintfToObj(msg, "\n %s:", infoPtr->keyStr);
	numSpaces = width + 1 - strlen(infoPtr->keyStr);
	while (numSpaces > 0) {
	    if (numSpaces >= NUM_SPACES) {
		Tcl_AppendToObj(msg, spaces, NUM_SPACES);
	    } else {
		Tcl_AppendToObj(msg, spaces, numSpaces);
	    }
	    numSpaces -= NUM_SPACES;
	}
	Tcl_AppendToObj(msg, infoPtr->helpStr, -1);
	Tcl_AppendToObj(msg, infoPtr->helpStr, TCL_INDEX_NONE);
	switch (infoPtr->type) {
	case TCL_ARGV_INT:
	    Tcl_AppendPrintfToObj(msg, "\n\t\tDefault value: %d",
		    *((int *) infoPtr->dstPtr));
	    break;
	case TCL_ARGV_FLOAT:
	    Tcl_AppendPrintfToObj(msg, "\n\t\tDefault value: %g",
		    *((double *) infoPtr->dstPtr));
	    sprintf(tmp, "%g", *((double *) infoPtr->dstPtr));
	    break;
	case TCL_ARGV_STRING: {
	    char *string = *((char **) infoPtr->dstPtr);

	    if (string != NULL) {
		Tcl_AppendPrintfToObj(msg, "\n\t\tDefault value: \"%s\"",
			string);
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
1354

1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397







-
+



-
-
+
+












-
+











    Tcl_Obj *value,
    int *codePtr)		/* Argument objects. */
{
    static const char *const returnCodes[] = {
	"ok", "error", "return", "break", "continue", NULL
    };

    if (!TclHasIntRep(value, &indexType)
    if (!TclHasInternalRep(value, &tclIndexType)
	    && TclGetIntFromObj(NULL, value, codePtr) == TCL_OK) {
	return TCL_OK;
    }
    if (Tcl_GetIndexFromObj(NULL, value, returnCodes, NULL, TCL_EXACT,
	    codePtr) == TCL_OK) {
    if (Tcl_GetIndexFromObjStruct(NULL, value, returnCodes,
	    sizeof(char *), NULL, TCL_EXACT, codePtr) == TCL_OK) {
	return TCL_OK;
    }

    /*
     * Value is not a legal completion code.
     */

    if (interp != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"bad completion code \"%s\": must be"
		" ok, error, return, break, continue, or an integer",
		TclGetString(value)));
	Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_CODE", NULL);
	Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_CODE", (char *)NULL);
    }
    return TCL_ERROR;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclInt.decls.

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
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
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
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
467
468
469

470
471
472
473
474

475
476
477
478

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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
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




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







-
-
-
+
+
+









+






-
-
-
-
-
-
-
-
-
-



-
-
-
-

-
+






-
+

-
-
-
-
-
-

-

-
+














-
-
-
-
-



-
-
-
-



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


-
-
+
+






-
+




-
-
-
-
-
-
-
-
-



-
-
-
-
-
-
-
-
-







-
-
+
+
-
-
-
-



-
-
+
-
-
-
-
-
-
+

-
-
-







-
+


-
+







-
-
-
-
+
+
+
+
-
-
-
+
+
-
+






-
-
-
-
-
-
-
-
-
-
-
-
-
-








-
+
-
-
-
-
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
+



-
-
-
-
-
-
-
-
-
-





-
-
-
-
-









+
-
-
-
+
+
+
-
+

-
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
+

-
-
-
-
-
-
-
-
-
-
-
-
-




-
+


-
+

-




-
-
-
-
-
-
-
-
-
-
-
-
-

-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-









-
-
-
-











-
-
-
-
-
-
-
-
-


-
+







-
+
-
-
-
-
-
-
-
+
+
-

-
-
-











-
-
-
-
-
-
-
-
-
-







-
+

-
-
-
-











-
+


-

-
+


-

-
+

-

-
+


-

-
+


-

-
+














-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-




-
-
-
-
-















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-



-
-
-
-
-
-
-
-







# tclInt.decls --
#
#	This file contains the declarations for all unsupported
#	functions that are exported by the Tcl library.  This file
#	is used to generate the tclIntDecls.h, tclIntPlatDecls.h
#	and tclStubInit.c files
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
# Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2001 Kevin B. Kenny.  All rights reserved.
# Copyright © 2007 Daniel A. Steffen <das@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

library tcl

# Define the unsupported generic interfaces.

interface tclInt
scspec EXTERN

# Declare each of the functions in the unsupported internal Tcl
# interface.  These interfaces are allowed to changed between versions.
# Use at your own risk.  Note that the position of functions should not
# be changed between versions to avoid gratuitous incompatibilities.

# Replaced by Tcl_FSAccess in 8.4:
#declare 0 {
#    int TclAccess(const char *path, int mode)
#}
#declare 1 {
#    int TclAccessDeleteProc(TclAccessProc_ *proc)
#}
#declare 2 {
#    int TclAccessInsertProc(TclAccessProc_ *proc)
#}
declare 3 {
    void TclAllocateFreeObjects(void)
}
# Replaced by TclpChdir in 8.1:
#  declare 4 {
#      int TclChdir(Tcl_Interp *interp, char *dirName)
#  }
declare 5 {
    int TclCleanupChildren(Tcl_Interp *interp, int numPids, Tcl_Pid *pidPtr,
    int TclCleanupChildren(Tcl_Interp *interp, Tcl_Size numPids, Tcl_Pid *pidPtr,
	    Tcl_Channel errorChan)
}
declare 6 {
    void TclCleanupCommand(Command *cmdPtr)
}
declare 7 {
    size_t TclCopyAndCollapse(size_t count, const char *src, char *dst)
    Tcl_Size TclCopyAndCollapse(Tcl_Size count, const char *src, char *dst)
}
# Removed in 9.0:
#declare 8 {
#    int TclCopyChannelOld(Tcl_Interp *interp, Tcl_Channel inChan,
#	    Tcl_Channel outChan, int toRead, Tcl_Obj *cmdPtr)
#}

# TclCreatePipeline unofficially exported for use by BLT.

declare 9 {
    int TclCreatePipeline(Tcl_Interp *interp, int argc, const char **argv,
    Tcl_Size TclCreatePipeline(Tcl_Interp *interp, Tcl_Size argc, const char **argv,
	    Tcl_Pid **pidArrayPtr, TclFile *inPipePtr, TclFile *outPipePtr,
	    TclFile *errFilePtr)
}
declare 10 {
    int TclCreateProc(Tcl_Interp *interp, Namespace *nsPtr,
	    const char *procName,
	    Tcl_Obj *argsPtr, Tcl_Obj *bodyPtr, Proc **procPtrPtr)
}
declare 11 {
    void TclDeleteCompiledLocalVars(Interp *iPtr, CallFrame *framePtr)
}
declare 12 {
    void TclDeleteVars(Interp *iPtr, TclVarHashTable *tablePtr)
}
# Removed in 8.5:
#declare 13 {
#    int TclDoGlob(Tcl_Interp *interp, char *separators,
#	    Tcl_DString *headPtr, char *tail, Tcl_GlobTypeData *types)
#}
declare 14 {
    int TclDumpMemoryInfo(void *clientData, int flags)
}
# Removed in 8.1:
#  declare 15 {
#      void TclExpandParseValue(ParseValue *pvPtr, int needed)
#  }
declare 16 {
    void TclExprFloatError(Tcl_Interp *interp, double value)
}
# Removed in 8.4:
#declare 17 {
#    int TclFileAttrsCmd(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
#}
#declare 18 {
#    int TclFileCopyCmd(Tcl_Interp *interp, int argc, char **argv)
#}
#declare 19 {
#    int TclFileDeleteCmd(Tcl_Interp *interp, int argc, char **argv)
#}
#declare 20 {
#    int TclFileMakeDirsCmd(Tcl_Interp *interp, int argc, char **argv)
#}
#declare 21 {
#    int TclFileRenameCmd(Tcl_Interp *interp, int argc, char **argv)
#}
declare 22 {
    int TclFindElement(Tcl_Interp *interp, const char *listStr,
	    int listLength, const char **elementPtr, const char **nextPtr,
	    size_t *sizePtr, int *bracePtr)
	    Tcl_Size listLength, const char **elementPtr, const char **nextPtr,
	    Tcl_Size *sizePtr, int *bracePtr)
}
declare 23 {
    Proc *TclFindProc(Interp *iPtr, const char *procName)
}
# Replaced with macro (see tclInt.h) in Tcl 8.5.0, restored in 8.5.10
declare 24 {
    size_t TclFormatInt(char *buffer, Tcl_WideInt n)
    Tcl_Size TclFormatInt(char *buffer, Tcl_WideInt n)
}
declare 25 {
    void TclFreePackageInfo(Interp *iPtr)
}
# Removed in 8.1:
#  declare 26 {
#      char *TclGetCwd(Tcl_Interp *interp)
#  }
# Removed in 8.5:
#declare 27 {
#    int TclGetDate(char *p, unsigned long now, long zone,
#	    unsigned long *timePtr)
#}
declare 28 {
    Tcl_Channel TclpGetDefaultStdChannel(int type)
}
# Removed in 8.4b2:
#declare 29 {
#    Tcl_Obj *TclGetElementOfIndexedArray(Tcl_Interp *interp,
#	    int localIndex, Tcl_Obj *elemPtr, int flags)
#}
# Replaced by char *TclGetEnv(const char *name, Tcl_DString *valuePtr) in 8.1:
#  declare 30 {
#      char *TclGetEnv(const char *name)
#  }
declare 31 {
    const char *TclGetExtension(const char *name)
}
declare 32 {
    int TclGetFrame(Tcl_Interp *interp, const char *str,
	    CallFrame **framePtrPtr)
}
# Removed in 8.5:
#declare 33 {
# Removed in 9.0:
#declare 34 {
#    TclCmdProcType TclGetInterpProc(void)
#}
# Removed in 9.0:
#declare 34 {deprecated {Use Tcl_GetIntForIndex}} {
#    int TclGetIntForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr,
#	    int endValue, int *indexPtr)
#}
# Removed in 8.4b2:
#declare 35 {
#declare 37 {
#    Tcl_Obj *TclGetIndexedScalar(Tcl_Interp *interp, int localIndex,
#	    int flags)
#}
# Removed in 8.6a2:
#declare 36 {
#    int TclGetLong(Tcl_Interp *interp, const char *str, long *longPtr)
#    int TclGetLoadedPackages(Tcl_Interp *interp, const char *targetName)
#}
declare 37 {
    int TclGetLoadedPackages(Tcl_Interp *interp, const char *targetName)
}
declare 38 {
    int TclGetNamespaceForQualName(Tcl_Interp *interp, const char *qualName,
	    Namespace *cxtNsPtr, int flags, Namespace **nsPtrPtr,
	    Namespace **altNsPtrPtr, Namespace **actualCxtPtrPtr,
	    const char **simpleNamePtr)
}
declare 39 {
    TclObjCmdProcType TclGetObjInterpProc(void)
    Tcl_ObjCmdProc *TclGetObjInterpProc(void)
}
declare 40 {
    int TclGetOpenMode(Tcl_Interp *interp, const char *str, int *seekFlagPtr)
    int TclGetOpenMode(Tcl_Interp *interp, const char *str, int *modeFlagsPtr)
}
declare 41 {
    Tcl_Command TclGetOriginalCommand(Tcl_Command command)
}
declare 42 {
    const char *TclpGetUserHome(const char *name, Tcl_DString *bufferPtr)
}
# Removed in 8.5a2:
#declare 43 {
#    int TclGlobalInvoke(Tcl_Interp *interp, int argc, const char **argv,
#	    int flags)
declare 43 {
    Tcl_ObjCmdProc2 *TclGetObjInterpProc2(void)
}
# Removed in 9.0:
#}
declare 44 {
    int TclGuessPackageName(const char *fileName, Tcl_DString *bufPtr)
#declare 44 {
#    int TclGuessPackageName(const char *fileName, Tcl_DString *bufPtr)
}
#}
declare 45 {
    int TclHideUnsafeCommands(Tcl_Interp *interp)
}
declare 46 {
    int TclInExit(void)
}
# Removed in 8.4b2:
#declare 47 {
#    Tcl_Obj *TclIncrElementOfIndexedArray(Tcl_Interp *interp,
#	    int localIndex, Tcl_Obj *elemPtr, long incrAmount)
#}
# Removed in 8.4b2:
#declare 48 {
#    Tcl_Obj *TclIncrIndexedScalar(Tcl_Interp *interp, int localIndex,
#	    long incrAmount)
#}
#declare 49 {
#    Tcl_Obj *TclIncrVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
#	    Tcl_Obj *part2Ptr, long incrAmount, int part1NotParsed)
#}
# Removed in 9.0:
#declare 50 {
#    void TclInitCompiledLocals(Tcl_Interp *interp, CallFrame *framePtr,
#	    Namespace *nsPtr)
#}
declare 51 {
    int TclInterpInit(Tcl_Interp *interp)
}
# Removed in 8.5a2:
# Removed in 9.0
#declare 52 {
#    int TclInvoke(Tcl_Interp *interp, int argc, const char **argv,
#	    int flags)
#}
declare 53 {
    int TclInvokeObjectCommand(void *clientData, Tcl_Interp *interp,
	    int argc, const char **argv)
#declare 53 {
#    int TclInvokeObjectCommand(void *clientData, Tcl_Interp *interp,
#	    Tcl_Size argc, const char **argv)
}
declare 54 {
    int TclInvokeStringCommand(void *clientData, Tcl_Interp *interp,
	    int objc, Tcl_Obj *const objv[])
#}
#declare 54 {
#    int TclInvokeStringCommand(void *clientData, Tcl_Interp *interp,
#	    Tcl_Size objc, Tcl_Obj *const objv[])
}
#}
declare 55 {
    Proc *TclIsProc(Command *cmdPtr)
}
# Replaced with TclpLoadFile in 8.1:
#  declare 56 {
#      int TclLoadFile(Tcl_Interp *interp, char *fileName, char *sym1,
#  	    char *sym2, Tcl_PackageInitProc **proc1Ptr,
#  	    Tcl_PackageInitProc **proc2Ptr)
#  }
# Signature changed to take a length in 8.1:
#  declare 57 {
#      int TclLooksLikeInt(char *p)
#  }
declare 58 {
    Var *TclLookupVar(Tcl_Interp *interp, const char *part1, const char *part2,
	    int flags, const char *msg, int createPart1, int createPart2,
	    Var **arrayPtrPtr)
}
# Replaced by Tcl_FSMatchInDirectory in 8.4
#declare 59 {
#    int TclpMatchFiles(Tcl_Interp *interp, char *separators,
#	    Tcl_DString *dirPtr, char *pattern, char *tail)
#}
declare 60 {
    int TclNeedSpace(const char *start, const char *end)
}
declare 61 {
    Tcl_Obj *TclNewProcBodyObj(Proc *procPtr)
}
declare 62 {
    int TclObjCommandComplete(Tcl_Obj *cmdPtr)
}
# Removed in 9.0:
declare 63 {
    int TclObjInterpProc(void *clientData, Tcl_Interp *interp,
	    int objc, Tcl_Obj *const objv[])
#declare 63 {
#    int TclObjInterpProc(void *clientData, Tcl_Interp *interp,
#	    Tcl_Size objc, Tcl_Obj *const objv[])
}
#}
declare 64 {
    int TclObjInvoke(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[],
    int TclObjInvoke(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[],
	    int flags)
}
# Removed in 8.5a2:
#declare 65 {
#    int TclObjInvokeGlobal(Tcl_Interp *interp, int objc,
#	    Tcl_Obj *const objv[], int flags)
#}
#declare 66 {
#    int TclOpenFileChannelDeleteProc(TclOpenFileChannelProc_ *proc)
#}
#declare 67 {
#    int TclOpenFileChannelInsertProc(TclOpenFileChannelProc_ *proc)
#}
# Replaced by Tcl_FSAccess in 8.4:
#declare 68 {
#    int TclpAccess(const char *path, int mode)
#}
declare 69 {
    void *TclpAlloc(size_t size)
    void *TclpAlloc(TCL_HASH_TYPE size)
}
#declare 70 {
#    int TclpCopyFile(const char *source, const char *dest)
#}
#declare 71 {
#    int TclpCopyDirectory(const char *source, const char *dest,
#	    Tcl_DString *errorPtr)
#}
#declare 72 {
#    int TclpCreateDirectory(const char *path)
#}
#declare 73 {
#    int TclpDeleteFile(const char *path)
#}
declare 74 {
    void TclpFree(void *ptr)
}
declare 75 {
    Tcl_WideUInt TclpGetClicks(void)
    unsigned long long TclpGetClicks(void)
}
declare 76 {
    Tcl_WideUInt TclpGetSeconds(void)
    unsigned long long TclpGetSeconds(void)
}

# Removed in 9.0:
#declare 77 {
#    void TclpGetTime(Tcl_Time *time)
#}
# Removed in 8.6:
#declare 78 {
#    int TclpGetTimeZone(unsigned long time)
#}
# Replaced by Tcl_FSListVolumes in 8.4:
#declare 79 {
#    int TclpListVolumes(Tcl_Interp *interp)
#}
# Replaced by Tcl_FSOpenFileChannel in 8.4:
#declare 80 {
#    Tcl_Channel TclpOpenFileChannel(Tcl_Interp *interp, char *fileName,
#	    char *modeString, int permissions)
#}
declare 81 {
    void *TclpRealloc(void *ptr, size_t size)
    void *TclpRealloc(void *ptr, TCL_HASH_TYPE size)
}
#declare 82 {
#    int TclpRemoveDirectory(const char *path, int recursive,
#	    Tcl_DString *errorPtr)
#}
#declare 83 {
#    int TclpRenameFile(const char *source, const char *dest)
#}
# Removed in 8.1:
#  declare 84 {
#      int TclParseBraces(Tcl_Interp *interp, char *str, char **termPtr,
#  	    ParseValue *pvPtr)
#  }
#  declare 85 {
#      int TclParseNestedCmd(Tcl_Interp *interp, char *str, int flags,
#  	    char **termPtr, ParseValue *pvPtr)
#  }
#  declare 86 {
#      int TclParseQuotes(Tcl_Interp *interp, char *str, int termChar,
#  	    int flags, char **termPtr, ParseValue *pvPtr)
#  }
#  declare 87 {
#      void TclPlatformInit(Tcl_Interp *interp)
#  }
# Removed in 9.0:
#declare 88 {
#    char *TclPrecTraceProc(void *clientData, Tcl_Interp *interp,
#	    const char *name1, const char *name2, int flags)
#}
declare 89 {
    int TclPreventAliasLoop(Tcl_Interp *interp, Tcl_Interp *cmdInterp,
	    Tcl_Command cmd)
}
# Removed in 8.1 (only available if compiled with TCL_COMPILE_DEBUG):
#  declare 90 {
#      void TclPrintByteCodeObj(Tcl_Interp *interp, Tcl_Obj *objPtr)
#  }
declare 91 {
    void TclProcCleanupProc(Proc *procPtr)
}
declare 92 {
    int TclProcCompileProc(Tcl_Interp *interp, Proc *procPtr,
	    Tcl_Obj *bodyPtr, Namespace *nsPtr, const char *description,
	    const char *procName)
}
declare 93 {
    void TclProcDeleteProc(void *clientData)
}
# Removed in 8.5:
#declare 94 {
#    int TclProcInterpProc(void *clientData, Tcl_Interp *interp,
#	    int argc, const char **argv)
#}
# Replaced by Tcl_FSStat in 8.4:
#declare 95 {
#    int TclpStat(const char *path, Tcl_StatBuf *buf)
#}
declare 96 {
    int TclRenameCommand(Tcl_Interp *interp, const char *oldName,
            const char *newName)
	    const char *newName)
}
declare 97 {
    void TclResetShadowedCmdRefs(Tcl_Interp *interp, Command *newCmdPtr)
}
declare 98 {
    int TclServiceIdle(void)
}
# Removed in 8.4b2:
# Removed in 9.0:
#declare 99 {
#    Tcl_Obj *TclSetElementOfIndexedArray(Tcl_Interp *interp, int localIndex,
#	    Tcl_Obj *elemPtr, Tcl_Obj *objPtr, int flags)
#}
# Removed in 8.4b2:
#declare 100 {
#    Tcl_Obj *TclSetIndexedScalar(Tcl_Interp *interp, int localIndex,
#declare 101 {
#    const char *TclSetPreInitScript(const char *string)
#	    Tcl_Obj *objPtr, int flags)
#}
declare 101 {
    const char *TclSetPreInitScript(const char *string)
}
declare 102 {
    void TclSetupEnv(Tcl_Interp *interp)
}
declare 103 {
    int TclSockGetPort(Tcl_Interp *interp, const char *str, const char *proto,
	    int *portPtr)
}
# Removed in 9.0:
#declare 104 {
#    int TclSockMinimumBuffersOld(int sock, int size)
#}
# Replaced by Tcl_FSStat in 8.4:
#declare 105 {
#    int TclStat(const char *path, Tcl_StatBuf *buf)
#}
#declare 106 {
#    int TclStatDeleteProc(TclStatProc_ *proc)
#}
#declare 107 {
#    int TclStatInsertProc(TclStatProc_ *proc)
#}
declare 108 {
    void TclTeardownNamespace(Namespace *nsPtr)
}
declare 109 {
    int TclUpdateReturnInfo(Interp *iPtr)
}
declare 110 {
    int TclSockMinimumBuffers(void *sock, int size)
    int TclSockMinimumBuffers(void *sock, Tcl_Size size)
}
# Removed in 8.1:
#  declare 110 {
#      char *TclWordEnd(char *start, char *lastChar, int nested, int *semiPtr)
#  }

# Procedures used in conjunction with Tcl namespaces. They are
# defined here instead of in tcl.decls since they are not stable yet.

declare 111 {
    void Tcl_AddInterpResolvers(Tcl_Interp *interp, const char *name,
	    Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc,
	    Tcl_ResolveCompiledVarProc *compiledVarProc)
}
# Removed in 9.0:
#declare 112 {
#    int Tcl_AppendExportList(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
#    int TclAppendExportList(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
#	    Tcl_Obj *objPtr)
#}
# Removed in 9.0:
#declare 113 {
#    Tcl_Namespace *Tcl_CreateNamespace(Tcl_Interp *interp, const char *name,
#    Tcl_Namespace *TclCreateNamespace(Tcl_Interp *interp, const char *name,
#	    void *clientData, Tcl_NamespaceDeleteProc *deleteProc)
#}
# Removed in 9.0:
#declare 114 {
#    void Tcl_DeleteNamespace(Tcl_Namespace *nsPtr)
#    void TclDeleteNamespace(Tcl_Namespace *nsPtr)
#}
# Removed in 9.0:
#declare 115 {
#    int Tcl_Export(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
#    int TclExport(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
#	    const char *pattern, int resetListFirst)
#}
# Removed in 9.0:
#declare 116 {
#    Tcl_Command Tcl_FindCommand(Tcl_Interp *interp, const char *name,
#    Tcl_Command TclFindCommand(Tcl_Interp *interp, const char *name,
#	    Tcl_Namespace *contextNsPtr, int flags)
#}
# Removed in 9.0:
#declare 117 {
#    Tcl_Namespace *Tcl_FindNamespace(Tcl_Interp *interp, const char *name,
#    Tcl_Namespace *TclFindNamespace(Tcl_Interp *interp, const char *name,
#	    Tcl_Namespace *contextNsPtr, int flags)
#}
declare 118 {
    int Tcl_GetInterpResolvers(Tcl_Interp *interp, const char *name,
	    Tcl_ResolverInfo *resInfo)
}
declare 119 {
    int Tcl_GetNamespaceResolvers(Tcl_Namespace *namespacePtr,
	    Tcl_ResolverInfo *resInfo)
}
declare 120 {
    Tcl_Var Tcl_FindNamespaceVar(Tcl_Interp *interp, const char *name,
	    Tcl_Namespace *contextNsPtr, int flags)
}
# Removed in 9.0:
#declare 121 {
#    int Tcl_ForgetImport(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
#	    const char *pattern)
#}
# Removed in 9.0:
#declare 122 {
#    Tcl_Command Tcl_GetCommandFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr)
#}
# Removed in 9.0:
#declare 123 {
#    void Tcl_GetCommandFullName(Tcl_Interp *interp, Tcl_Command command,
#	    Tcl_Obj *objPtr)
#}
# Removed in 9.0:
#declare 124 {
#    Tcl_Namespace *Tcl_GetCurrentNamespace(Tcl_Interp *interp)
#}
# Removed in 9.0:
#declare 125 {
#    Tcl_Namespace *Tcl_GetGlobalNamespace(Tcl_Interp *interp)
#}
declare 126 {
    void Tcl_GetVariableFullName(Tcl_Interp *interp, Tcl_Var variable,
	    Tcl_Obj *objPtr)
}
# Removed in 9.0:
#declare 127 {
#    int Tcl_Import(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
#	    const char *pattern, int allowOverwrite)
#}
declare 128 {
    void Tcl_PopCallFrame(Tcl_Interp *interp)
}
declare 129 {
    int Tcl_PushCallFrame(Tcl_Interp *interp, Tcl_CallFrame *framePtr,
	    Tcl_Namespace *nsPtr, int isProcCallFrame)
}
declare 130 {
    int Tcl_RemoveInterpResolvers(Tcl_Interp *interp, const char *name)
}
declare 131 {
    void Tcl_SetNamespaceResolvers(Tcl_Namespace *namespacePtr,
	    Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc,
	    Tcl_ResolveCompiledVarProc *compiledVarProc)
}
declare 132 {
    int TclpHasSockets(Tcl_Interp *interp)
}
# Removed in 9.0
#declare 133 {
#    struct tm *TclpGetDate(const time_t *time, int useGMT)
#}
# Removed in 8.5
#declare 134 {
#    size_t TclpStrftime(char *s, size_t maxsize, const char *format,
#	    const struct tm *t, int useGMT)
#}
#declare 135 {
#    int TclpCheckStackSpace(void)
#}

# Added in 8.1:

#declare 137 {
#   int TclpChdir(const char *dirName)
#}
declare 138 {
    const char *TclGetEnv(const char *name, Tcl_DString *valuePtr)
}
#declare 139 {
#    int TclpLoadFile(Tcl_Interp *interp, char *fileName, char *sym1,
#	    char *sym2, Tcl_PackageInitProc **proc1Ptr,
#	    Tcl_PackageInitProc **proc2Ptr, void **clientDataPtr)
#}
#declare 140 {
#    int TclLooksLikeInt(const char *bytes, int length)
#}
# This is used by TclX, but should otherwise be considered private
declare 141 {
    const char *TclpGetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr)
}
declare 142 {
    int TclSetByteCodeFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    CompileHookProc *hookProc, void *clientData)
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620


621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
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







-
-
-




-
-
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







}
declare 148 {
    TclHandle TclHandlePreserve(TclHandle handle)
}
declare 149 {
    void TclHandleRelease(TclHandle handle)
}

# Added for Tcl 8.2

declare 150 {
    int TclRegAbout(Tcl_Interp *interp, Tcl_RegExp re)
}
declare 151 {
    void TclRegExpRangeUniChar(Tcl_RegExp re, size_t index, size_t *startPtr,
	    size_t *endPtr)
    void TclRegExpRangeUniChar(Tcl_RegExp re, Tcl_Size index, Tcl_Size *startPtr,
	    Tcl_Size *endPtr)
}
declare 152 {
    void TclSetLibraryPath(Tcl_Obj *pathPtr)
}
declare 153 {
    Tcl_Obj *TclGetLibraryPath(void)
}

# moved to tclTest.c (static) in 8.3.2/8.4a2
#declare 154 {
#    int TclTestChannelCmd(void *clientData,
#    Tcl_Interp *interp, int argc, char **argv)
#}
#declare 155 {
#    int TclTestChannelEventCmd(void *clientData,
#	     Tcl_Interp *interp, int argc, char **argv)
#}

declare 156 {
    void TclRegError(Tcl_Interp *interp, const char *msg,
	    int status)
}
declare 157 {
    Var *TclVarTraceExists(Tcl_Interp *interp, const char *varName)
}
# REMOVED - use public Tcl_SetStartupScript()
#declare 158 {
#    void TclSetStartupScriptFileName(const char *filename)
#}
# REMOVED - use public Tcl_GetStartupScript()
#declare 159 {
#    const char *TclGetStartupScriptFileName(void)
#}
#declare 160 {
#    int TclpMatchFilesTypes(Tcl_Interp *interp, char *separators,
#	    Tcl_DString *dirPtr, char *pattern, char *tail,
#	    GlobTypeData *types)
#}

# new in 8.3.2/8.4a2
declare 161 {
    int TclChannelTransform(Tcl_Interp *interp, Tcl_Channel chan,
	    Tcl_Obj *cmdObjPtr)
}
declare 162 {
    void TclChannelEventScriptInvoker(void *clientData, int flags)
}
687
688
689
690
691
692
693
694

695
696
697
698
699
700
701
702
703
704
705
706

707
708

709
710
711
712
713


714
715
716
717
718


719
720
721
722
723
724
725
726
727
728


729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
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







-
+


-
-
-
-
-
-
-
-
-
-
+

-
+



-
-
+
+



-
-
+
+




-
-
-

-
-
+
+

-
-
-
-
-
-
-
-
-
-











-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-




-
-
-
-
-







declare 165 {
    void TclpSetInitialEncodings(void)
}

# New function due to TIP #33
declare 166 {
    int TclListObjSetElement(Tcl_Interp *interp, Tcl_Obj *listPtr,
	    int index, Tcl_Obj *valuePtr)
	    Tcl_Size index, Tcl_Obj *valuePtr)
}

# VFS-aware versions of Tcl*StartupScriptFileName (158 and 159 above)
# REMOVED - use public Tcl_SetStartupScript()
#declare 167 {
#    void TclSetStartupScriptPath(Tcl_Obj *pathPtr)
#}
# REMOVED - use public Tcl_GetStartupScript()
#declare 168 {
#    Tcl_Obj *TclGetStartupScriptPath(void)
#}
# variant of Tcl_UtfNCmp that takes n as bytes, not chars
# variant of Tcl_UtfNcmp that takes n as bytes, not chars
declare 169 {
    int TclpUtfNcmp2(const char *s1, const char *s2, size_t n)
    int TclpUtfNcmp2(const void *s1, const void *s2, size_t n)
}
declare 170 {
    int TclCheckInterpTraces(Tcl_Interp *interp, const char *command,
	    size_t numChars, Command *cmdPtr, int result, int traceFlags,
	    int objc, Tcl_Obj *const objv[])
	    Tcl_Size numChars, Command *cmdPtr, int result, int traceFlags,
	    Tcl_Size objc, Tcl_Obj *const objv[])
}
declare 171 {
    int TclCheckExecutionTraces(Tcl_Interp *interp, const char *command,
	    size_t numChars, Command *cmdPtr, int result, int traceFlags,
	    int objc, Tcl_Obj *const objv[])
	    Tcl_Size numChars, Command *cmdPtr, int result, int traceFlags,
	    Tcl_Size objc, Tcl_Obj *const objv[])
}
declare 172 {
    int TclInThreadExit(void)
}

# added for 8.4.2

declare 173 {
    int TclUniCharMatch(const Tcl_UniChar *string, size_t strLen,
	    const Tcl_UniChar *pattern, size_t ptnLen, int flags)
    int TclUniCharMatch(const Tcl_UniChar *string, Tcl_Size strLen,
	    const Tcl_UniChar *pattern, Tcl_Size ptnLen, int flags)
}

# added for 8.4.3

#declare 174 {
#    Tcl_Obj *TclIncrWideVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
#	    Tcl_Obj *part2Ptr, Tcl_WideInt wideIncrAmount, int part1NotParsed)
#}

# Factoring out of trace code

declare 175 {
    int TclCallVarTraces(Interp *iPtr, Var *arrayPtr, Var *varPtr,
	    const char *part1, const char *part2, int flags, int leaveErrMsg)
}
declare 176 {
    void TclCleanupVar(Var *varPtr, Var *arrayPtr)
}
declare 177 {
    void TclVarErrMsg(Tcl_Interp *interp, const char *part1, const char *part2,
	    const char *operation, const char *reason)
}
# TIP 338 made these public - now declared in tcl.h
#declare 178 {
#    void Tcl_SetStartupScript(Tcl_Obj *pathPtr, const char *encodingName)
#}
#declare 179 {
#    Tcl_Obj *Tcl_GetStartupScript(const char **encodingNamePtr)
#}

# REMOVED
# Allocate lists without copying arrays
# declare 180 {
#    Tcl_Obj *TclNewListObjDirect(int objc, Tcl_Obj **objv)
# }
#declare 181 {
#    Tcl_Obj *TclDbNewListObjDirect(int objc, Tcl_Obj **objv,
#	    const char *file, int line)
#}

# Removed in 9.0
#declare 182 {
#     struct tm *TclpLocaltime(const time_t *clock)
#}
# Removed in 9.0
#declare 183 {
#     struct tm *TclpGmtime(const time_t *clock)
#}

# For the new "Thread Storage" subsystem.

### REMOVED on grounds it should never have been exposed. All these
### functions are now either static in tclThreadStorage.c or
### MODULE_SCOPE.
# declare 184 {
#      void TclThreadStorageLockInit(void)
# }
# declare 185 {
#      void TclThreadStorageLock(void)
# }
# declare 186 {
#      void TclThreadStorageUnlock(void)
# }
# declare 187 {
#      void TclThreadStoragePrint(FILE *outFile, int flags)
# }
# declare 188 {
#      Tcl_HashTable *TclThreadStorageGetHashTable(Tcl_ThreadId id)
# }
# declare 189 {
#      Tcl_HashTable *TclThreadStorageInit(Tcl_ThreadId id, void *reserved)
# }
# declare 190 {
#      void TclThreadStorageDataKeyInit(Tcl_ThreadDataKey *keyPtr)
# }
# declare 191 {
#      void *TclThreadStorageDataKeyGet(Tcl_ThreadDataKey *keyPtr)
# }
# declare 192 {
#      void TclThreadStorageDataKeySet(Tcl_ThreadDataKey *keyPtr, void *data)
# }
# declare 193 {
#      void TclFinalizeThreadStorageThread(Tcl_ThreadId id)
# }
# declare 194 {
#      void TclFinalizeThreadStorage(void)
# }
# declare 195 {
#      void TclFinalizeThreadStorageData(Tcl_ThreadDataKey *keyPtr)
# }
# declare 196 {
#      void TclFinalizeThreadStorageDataKey(Tcl_ThreadDataKey *keyPtr)
# }

#
# Added in tcl8.5a5 for compiler/executor experimentation.
# Disabled in Tcl 8.5.1; experiments terminated. :/
#
#declare 197 {
#    int TclCompEvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
#		        const CmdFrame *invoker, int word)
#}
declare 198 {
    int TclObjGetFrame(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    CallFrame **framePtrPtr)
}

#declare 199 {
#    int TclMatchIsTrivial(const char *pattern)
#}

# 200-208 exported for use by the test suite [Bug 1054748]
declare 200 {
    int TclpObjRemoveDirectory(Tcl_Obj *pathPtr, int recursive,
	Tcl_Obj **errorPtr)
}
declare 201 {
    int TclpObjCopyDirectory(Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr,
864
865
866
867
868
869
870
871
872
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
898

899
900
901
902




903


904













905
906
907
908
909
910
911
912

913
914
915
916
917
918
919


920
921
922
923
924
925
926
927
928
929
930
931
932
933
934

935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953

954
955
956
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

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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127

1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142

1143
1144
1145
1146



1147
1148

1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176

1177
1178
1179

1180
1181
1182

1183
1184
1185

1186
1187
1188
1189
1190
1191
1192
1193
1194

1195
1196

1197
1198

1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219

1220
1221
1222
1223
1224
1225
1226
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
451
452
453
454
455
456
457










458
459
460
461
462
463
464
465
466
467

468
469
470
471
472
473
474

475
476
477
478
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
558

559
560
561
562
563
564
565
566
567
568
569

570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586


587
588
589
590
591
592
593
594
595

596
597
598
599
600
601
602
603
604
605
606
607
608
609
610

611
612
613
614
615
616
617
618

619
620
621
622
623

624
625
626
627
628

629
630
631
632
633
634
635
636

637
638
639


640
641
642
643


644









645



646

647
648
649
650
651
652
653
654
655

656
657

658














659




660



661
662
663
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


707
708
709





710
711
712


713
714
715
716
717
718
719
720







-
-
-
-
-
-
-
-
-
-










-
+






-
+




+
+
+
+
-
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+



-
-


-
+





-
-
+
+

-
-
-
-
-
-







-
+


















-
+





-
-
-
-
-
-









-
+



-
+










-
+
















-
-
+
+







-
+














-
+







-
+




-
+




-
+







-
+


-
-
+
+


-
-
+
-
-
-
-
-
-
-
-
-
+
-
-
-

-









-
+

-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-

-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
+
+

-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-

-
+


-
+


-
+
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


-
+
-
-
-
-
-
-
-
-
-
-
-
+



-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-



-
-
-
-
-
+
-
-
+

-
+
-
-
-
-
-
-
-
-
-
-
+
-

-
-
+
+

-
-
-
-
-
+


-
-
+







declare 207 {
    int TclpObjAccess(Tcl_Obj *pathPtr, int mode)
}
declare 208 {
    Tcl_Channel TclpOpenFileChannel(Tcl_Interp *interp,
	    Tcl_Obj *pathPtr, int mode, int permissions)
}
# Made public by TIP 258
#declare 209 {
#    Tcl_Obj *TclGetEncodingSearchPath(void)
#}
#declare 210 {
#    int TclSetEncodingSearchPath(Tcl_Obj *searchPath)
#}
#declare 211 {
#    const char *TclpGetEncodingNameFromEnvironment(Tcl_DString *bufPtr)
#}
declare 212 {
    void TclpFindExecutable(const char *argv0)
}
declare 213 {
    Tcl_Obj *TclGetObjNameOfExecutable(void)
}
declare 214 {
    void TclSetObjNameOfExecutable(Tcl_Obj *name, Tcl_Encoding encoding)
}
declare 215 {
    void *TclStackAlloc(Tcl_Interp *interp, size_t numBytes)
    void *TclStackAlloc(Tcl_Interp *interp, TCL_HASH_TYPE numBytes)
}
declare 216 {
    void TclStackFree(Tcl_Interp *interp, void *freePtr)
}
declare 217 {
    int TclPushStackFrame(Tcl_Interp *interp, Tcl_CallFrame **framePtrPtr,
            Tcl_Namespace *namespacePtr, int isProcCallFrame)
	    Tcl_Namespace *namespacePtr, int isProcCallFrame)
}
declare 218 {
    void TclPopStackFrame(Tcl_Interp *interp)
}
# TIP 431: temporary directory creation function
declare 219 {
    Tcl_Obj *TclpCreateTemporaryDirectory(Tcl_Obj *dirObj,
	    Tcl_Obj *basenameObj)

}

# for use in tclTest.c

# TIP 625: for unit testing - create list objects with span
declare 221 {
    Tcl_Obj *TclListTestObj(size_t length, size_t leadingSpace, size_t endSpace)
}
# TIP 625: for unit testing - check list invariants
declare 222 {
    void TclListObjValidate(Tcl_Interp *interp, Tcl_Obj *listObj)
}
# Bug 7371b6270b
declare 223 {
    void *TclGetCStackPtr(void)
}
declare 224 {
    TclPlatformType *TclGetPlatform(void)
}

#
declare 225 {
    Tcl_Obj *TclTraceDictPath(Tcl_Interp *interp, Tcl_Obj *rootPtr,
	    int keyc, Tcl_Obj *const keyv[], int flags)
	    Tcl_Size keyc, Tcl_Obj *const keyv[], int flags)
}
declare 226 {
    int TclObjBeingDeleted(Tcl_Obj *objPtr)
}
declare 227 {
    void TclSetNsPath(Namespace *nsPtr, size_t pathLength,
            Tcl_Namespace *pathAry[])
    void TclSetNsPath(Namespace *nsPtr, Tcl_Size pathLength,
	    Tcl_Namespace *pathAry[])
}
#  Used to be needed for TclOO-extension; unneeded now that TclOO is in the
#  core and NRE-enabled
#  declare 228 {
#      int TclObjInterpProcCore(Tcl_Interp *interp, Tcl_Obj *procNameObj,
#             int skip, ProcErrorProc *errorProc)
#  }
declare 229 {
    int	TclPtrMakeUpvar(Tcl_Interp *interp, Var *otherP1Ptr,
	    const char *myName, int myFlags, int index)
}
declare 230 {
    Var *TclObjLookupVar(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
	    const char *part2, int flags, const char *msg,
	    const int createPart1, const int createPart2, Var **arrayPtrPtr)
	    int createPart1, int createPart2, Var **arrayPtrPtr)
}
declare 231 {
    int	TclGetNamespaceFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    Tcl_Namespace **nsPtrPtr)
}

# Bits and pieces of TIP#280's guts
declare 232 {
    int TclEvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags,
	    const CmdFrame *invoker, int word)
}
declare 233 {
    void TclGetSrcInfoForPc(CmdFrame *contextPtr)
}

# Exports for VarReform compat: Itcl, XOTcl like to peek into our varTables :(
declare 234 {
    Var *TclVarHashCreateVar(TclVarHashTable *tablePtr, const char *key,
             int *newPtr)
	    int *newPtr)
}
declare 235 {
    void TclInitVarHashTable(TclVarHashTable *tablePtr, Namespace *nsPtr)
}


# TIP 337 made this one public
#declare 236 {
#    void TclBackgroundException(Tcl_Interp *interp, int code)
#}

# TIP #285: Script cancellation support.
declare 237 {
    int TclResetCancellation(Tcl_Interp *interp, int force)
}

# NRE functions for "rogue" extensions to exploit NRE; they will need to
# include NRE.h too.
declare 238 {
    int TclNRInterpProc(void *clientData, Tcl_Interp *interp,
	    int objc, Tcl_Obj *const objv[])
	    Tcl_Size objc, Tcl_Obj *const objv[])
}
declare 239 {
    int TclNRInterpProcCore(Tcl_Interp *interp, Tcl_Obj *procNameObj,
			    int skip, ProcErrorProc *errorProc)
	    Tcl_Size skip, ProcErrorProc *errorProc)
}
declare 240 {
    int TclNRRunCallbacks(Tcl_Interp *interp, int result,
	      struct NRE_callback *rootPtr)
}
declare 241 {
    int TclNREvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags,
	    const CmdFrame *invoker, int word)
}
declare 242 {
    int TclNREvalObjv(Tcl_Interp *interp, int objc,
    int TclNREvalObjv(Tcl_Interp *interp, Tcl_Size objc,
	      Tcl_Obj *const objv[], int flags, Command *cmdPtr)
}

# Tcl_Obj leak detection support.
declare 243 {
    void TclDbDumpActiveObjects(FILE *outFile)
}

# Functions to make things better for itcl
declare 244 {
    Tcl_HashTable *TclGetNamespaceChildTable(Tcl_Namespace *nsPtr)
}
declare 245 {
    Tcl_HashTable *TclGetNamespaceCommandTable(Tcl_Namespace *nsPtr)
}
declare 246 {
    int TclInitRewriteEnsemble(Tcl_Interp *interp, size_t numRemoved,
	    size_t numInserted, Tcl_Obj *const *objv)
    int TclInitRewriteEnsemble(Tcl_Interp *interp, Tcl_Size numRemoved,
	    Tcl_Size numInserted, Tcl_Obj *const *objv)
}
declare 247 {
    void TclResetRewriteEnsemble(Tcl_Interp *interp, int isRootEnsemble)
}

declare 248 {
    int TclCopyChannel(Tcl_Interp *interp, Tcl_Channel inChan,
	    Tcl_Channel outChan, Tcl_WideInt toRead, Tcl_Obj *cmdPtr)
	    Tcl_Channel outChan, long long toRead, Tcl_Obj *cmdPtr)
}

declare 249 {
    char *TclDoubleDigits(double dv, int ndigits, int flags,
			  int *decpt, int *signum, char **endPtr)
}
# TIP #285: Script cancellation support.
declare 250 {
    void TclSetChildCancelFlags(Tcl_Interp *interp, int flags, int force)
}

# Allow extensions for optimization
declare 251 {
    int TclRegisterLiteral(void *envPtr,
	    const char *bytes, size_t length, int flags)
	    const char *bytes, Tcl_Size length, int flags)
}

# Exporting of the internal API to variables.

declare 252 {
    Tcl_Obj *TclPtrGetVar(Tcl_Interp *interp, Tcl_Var varPtr,
	    Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
	    const int flags)
	    int flags)
}
declare 253 {
    Tcl_Obj *TclPtrSetVar(Tcl_Interp *interp, Tcl_Var varPtr,
	    Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
	    Tcl_Obj *newValuePtr, const int flags)
	    Tcl_Obj *newValuePtr, int flags)
}
declare 254 {
    Tcl_Obj *TclPtrIncrObjVar(Tcl_Interp *interp, Tcl_Var varPtr,
	    Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
	    Tcl_Obj *incrPtr, const int flags)
	    Tcl_Obj *incrPtr, int flags)
}
declare 255 {
    int	TclPtrObjMakeUpvar(Tcl_Interp *interp, Tcl_Var otherPtr,
	    Tcl_Obj *myNamePtr, int myFlags)
}
declare 256 {
    int	TclPtrUnsetVar(Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr,
	    Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const int flags)
	    Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags)
}
declare 257 {
    void TclStaticPackage(Tcl_Interp *interp, const char *pkgName,
	    Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc)
    void TclStaticLibrary(Tcl_Interp *interp, const char *prefix,
	    Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc)
}

# TIP 431: temporary directory creation function
declare 258 {
declare 261 {
    Tcl_Obj *TclpCreateTemporaryDirectory(Tcl_Obj *dirObj,
	    Tcl_Obj *basenameObj)
}
# TIP 542
declare 259 {
    void TclAppendUnicodeToObj(Tcl_Obj *objPtr,
	    const Tcl_UniChar *unicode, size_t length)
}

    void TclUnusedStubEntry(void)
declare 260 {
    unsigned char *TclGetBytesFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    size_t *lengthPtr)
}


##############################################################################

# Define the platform specific internal Tcl interface. These functions are
# only available on the designated platform.

interface tclIntPlat

################################
# Windows specific functions
# Platform specific functions

declare 0 win {
declare 1 {
    void TclWinConvertError(int errCode)
}
# Removed in 9.0:
#declare 1 win {
#    void TclWinConvertWSAError(int errCode)
#}
# Removed in 9.0:
#declare 2 win {
#    struct servent *TclWinGetServByName(const char *nm,
#	    const char *proto)
#}
# Removed in 9.0:
#declare 3 win {
#    int TclWinGetSockOpt(SOCKET s, int level, int optname,
    int TclpCloseFile(TclFile file)
#	    char *optval, int *optlen)
#}
declare 4 win {
    void *TclWinGetTclInstance(void)
}
# new for 8.4.20+/8.5.12+ Cygwin only
declare 5 win {
    int TclUnixWaitForFile(int fd, int mask, int timeout)
declare 2 {
    Tcl_Channel TclpCreateCommandChannel(TclFile readFile,
	    TclFile writeFile, TclFile errorFile, size_t numPids, Tcl_Pid *pidPtr)
}
# Removed in 8.1:
#  declare 5 win {
#      HINSTANCE TclWinLoadLibrary(char *name)
#  }
# Removed in 9.0:
#declare 6 win {
#    unsigned short TclWinNToHS(unsigned short ns)
#}
# Removed in 9.0:
#declare 7 win {
#    int TclWinSetSockOpt(SOCKET s, int level, int optname,
#	    const char *optval, int optlen)
#}
declare 8 win {
declare 3 {
    size_t TclpGetPid(Tcl_Pid pid)
}
# Removed in 9.0:
#declare 9 win {
#    int TclWinGetPlatformId(void)
#}
# Removed in 9.0:
#declare 10 win {
#    Tcl_DirEntry *TclpReaddir(TclDIR *dir)
#}
# Removed in 8.3.1 (for Win32s only):
#declare 10 win {
#    int TclWinSynchSpawn(void *args, int type, void **trans, Tcl_Pid *pidPtr)
#}

    int TclpCreatePipe(TclFile *readPipe, TclFile *writePipe)
# Pipe channel functions

declare 11 win {
    void TclGetAndDetachPids(Tcl_Interp *interp, Tcl_Channel chan)
}
declare 4 {
    void *TclWinGetTclInstance(void)
}
declare 12 win {
declare 5 {
    int TclpCloseFile(TclFile file)
}
declare 13 win {
    Tcl_Channel TclpCreateCommandChannel(TclFile readFile,
	    TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr)
}
declare 14 win {
    int TclpCreatePipe(TclFile *readPipe, TclFile *writePipe)
}
declare 15 win {
    int TclpCreateProcess(Tcl_Interp *interp, int argc,
	    const char **argv, TclFile inputFile, TclFile outputFile,
	    TclFile errorFile, Tcl_Pid *pidPtr)
}
# new for 8.4.20+/8.5.12+ Cygwin only
declare 16 win {
    int TclpIsAtty(int fd)
}
# Signature changed in 8.1:
#  declare 16 win {
#      TclFile TclpCreateTempFile(char *contents, Tcl_DString *namePtr)
#  }
#  declare 17 win {
#      char *TclpGetTZName(void)
#  }
# new for 8.5.12+ Cygwin only
declare 17 win {
    int TclUnixCopyFile(const char *src, const char *dst,
    int TclUnixWaitForFile(int fd, int mask, int timeout)
	    const Tcl_StatBuf *statBufPtr, int dontCopyAtts)
}
declare 18 win {
declare 6 {
    TclFile TclpMakeFile(Tcl_Channel channel, int direction)
}
declare 19 win {
declare 7 {
    TclFile TclpOpenFile(const char *fname, int mode)
}
declare 20 win {
declare 8 {
    void TclWinAddProcess(void *hProcess, size_t id)
}
# Removed in 9.0:
#declare 21 win {
#    char *TclpInetNtoa(struct in_addr addr)
#}
# removed permanently for 8.4
#declare 21 win {
#    void TclpAsyncMark(Tcl_AsyncHandler async)
    Tcl_Size TclpGetPid(Tcl_Pid pid)
#}

}
# Added in 8.1:
declare 22 win {
declare 9 {
    TclFile TclpCreateTempFile(const char *contents)
}
# Removed in 8.6:
#declare 23 win {
#    char *TclpGetTZName(int isdst)
#}
declare 24 win {
    char *TclWinNoBackslash(char *path)
}
# replaced by generic TclGetPlatform
#declare 25 win {
#    TclPlatformType *TclWinGetPlatform(void)
#}
# Removed in 9.0:
#declare 26 win {
#    void TclWinSetInterfaces(int wide)
#}

# Added in Tcl 8.3.3 / 8.4

declare 27 win {
declare 11 {
    void TclWinFlushDirtyChannels(void)
}

# Added in 8.4.2

# Removed in 9.0:
#declare 28 win {
#    void TclWinResetInterfaces(void)
#}

################################
# Unix specific functions

# Pipe channel functions

declare 0 unix {
    void TclGetAndDetachPids(Tcl_Interp *interp, Tcl_Channel chan)
}
declare 1 unix {
declare 15 {
    int TclpCloseFile(TclFile file)
}
declare 2 unix {
    Tcl_Channel TclpCreateCommandChannel(TclFile readFile,
	    TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr)
}
declare 3 unix {
    int TclpCreatePipe(TclFile *readPipe, TclFile *writePipe)
}
declare 4 unix {
    int TclpCreateProcess(Tcl_Interp *interp, int argc,
    int TclpCreateProcess(Tcl_Interp *interp, size_t argc,
	    const char **argv, TclFile inputFile, TclFile outputFile,
	    TclFile errorFile, Tcl_Pid *pidPtr)
}
declare 5 unix {
declare 16 {
    int TclUnixWaitForFile_(int fd, int mask, int timeout)
}
declare 6 unix {
    TclFile TclpMakeFile(Tcl_Channel channel, int direction)
}
declare 7 unix {
    TclFile TclpOpenFile(const char *fname, int mode)
}
declare 8 unix {
    int TclUnixWaitForFile(int fd, int mask, int timeout)
}

    int TclpIsAtty(int fd)
# Added in 8.1:

declare 9 unix {
}
declare 17 {
    TclFile TclpCreateTempFile(const char *contents)
}

# Added in 8.4:

# Removed in 9.0:
#declare 10 unix {
#    Tcl_DirEntry *TclpReaddir(TclDIR *dir)
#}
# Removed in 9.0:
#declare 11 unix {
#    struct tm *TclpLocaltime_unix(const time_t *clock)
#}
# Removed in 9.0:
#declare 12 unix {
#    struct tm *TclpGmtime_unix(const time_t *clock)
#}
# Removed in 9.0:
#declare 13 unix {
#    char *TclpInetNtoa(struct in_addr addr)
#}

# Added in 8.5:

declare 14 unix {
    int TclUnixCopyFile(const char *src, const char *dst,
	    const Tcl_StatBuf *statBufPtr, int dontCopyAtts)
}

################################
# Mac OS X specific functions

declare 15 {unix macosx} {
declare 20 {
    int TclMacOSXGetFileAttribute(Tcl_Interp *interp, int objIndex,
	    Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr)
    void TclWinAddProcess(void *hProcess, Tcl_Size id)
}
declare 16 {unix macosx} {
declare 24 {
    int TclMacOSXSetFileAttribute(Tcl_Interp *interp, int objIndex,
	    Tcl_Obj *fileName, Tcl_Obj *attributePtr)
}
declare 17 {unix macosx} {
    int TclMacOSXCopyFileAttributes(const char *src, const char *dst,
	    const Tcl_StatBuf *statBufPtr)
}
declare 18 {unix macosx} {
    int TclMacOSXMatchType(Tcl_Interp *interp, const char *pathName,
	    const char *fileName, Tcl_StatBuf *statBufPtr,
    char *TclWinNoBackslash(char *path)
	    Tcl_GlobTypeData *types)
}
declare 19 {unix macosx} {
    void TclMacOSXNotifierAddRunLoopMode(const void *runLoopMode)
declare 27 {
    void TclWinFlushDirtyChannels(void)
}
declare 22 {unix macosx} {
    TclFile TclpCreateTempFile_(const char *contents)
}

declare 29 {win unix} {
declare 29 {
    int TclWinCPUID(int index, int *regs)
}
# Added in 8.6; core of TclpOpenTemporaryFile
declare 30 {win unix} {
declare 30 {
    int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj, Tcl_Obj *basenameObj,
	    Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj)
}

# Local Variables:
# mode: tcl
# End:

Changes to generic/tclInt.h.

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
62
63
64
65
66
67
68




69





70






71
72
73
74
75
76
77
78







-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
+








#include "tclPort.h"

#include <stdio.h>

#include <ctype.h>
#include <stdarg.h>
#ifdef NO_STDLIB_H
#   include "../compat/stdlib.h"
#else
#   include <stdlib.h>
#include <stdlib.h>
#endif
#ifdef NO_STRING_H
#include "../compat/string.h"
#else
#include <string.h>
#include <stdint.h>
#endif
#if !defined(STDC_HEADERS) && !defined(__STDC__) && !defined(__C99__FUNC__) \
     && !defined(__cplusplus) && !defined(_MSC_VER) && !defined(__ICC)
typedef int ptrdiff_t;
#endif
#include <stddef.h>
#include <string.h>
#include <locale.h>

/*
 * Ensure WORDS_BIGENDIAN is defined correctly:
 * Needs to happen here in addition to configure to work with fat compiles on
 * Darwin (where configure runs only once for multiple architectures).
 */
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
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







-
+
-
-
+
-
-
-
-
+
+
+
-

-
+
-
-
+
-
-
-
-
+
+
+
-




+








/*
 * Macros used to cast between pointers and integers (e.g. when storing an int
 * in ClientData), on 64-bit architectures they avoid gcc warning about "cast
 * to/from pointer from/to integer of different size".
 */

#if !defined(INT2PTR) && !defined(PTR2INT)
#if !defined(INT2PTR)
#   if defined(HAVE_INTPTR_T) || defined(intptr_t)
#	define INT2PTR(p) ((void *)(intptr_t)(p))
#   define INT2PTR(p) ((void *)(ptrdiff_t)(p))
#	define PTR2INT(p) ((intptr_t)(p))
#   else
#	define INT2PTR(p) ((void *)(p))
#	define PTR2INT(p) ((long)(p))
#endif
#if !defined(PTR2INT)
#   define PTR2INT(p) ((ptrdiff_t)(p))
#   endif
#endif
#if !defined(UINT2PTR) && !defined(PTR2UINT)
#if !defined(UINT2PTR)
#   if defined(HAVE_UINTPTR_T) || defined(uintptr_t)
#	define UINT2PTR(p) ((void *)(uintptr_t)(p))
#   define UINT2PTR(p) ((void *)(size_t)(p))
#	define PTR2UINT(p) ((uintptr_t)(p))
#   else
#	define UINT2PTR(p) ((void *)(p))
#	define PTR2UINT(p) ((unsigned long)(p))
#endif
#if !defined(PTR2UINT)
#   define PTR2UINT(p) ((size_t)(p))
#   endif
#endif

#if defined(_WIN32) && defined(_MSC_VER)
#   define vsnprintf _vsnprintf
#   define snprintf _snprintf
#endif

#if !defined(TCL_THREADS)
#   define TCL_THREADS 1
#endif
#if !TCL_THREADS
#   undef TCL_DECLARE_MUTEX
178
179
180
181
182
183
184
185

186
187
188
189
190
191
192
161
162
163
164
165
166
167

168
169
170
171
172
173
174
175







-
+








typedef struct Tcl_ResolvedVarInfo {
    Tcl_ResolveRuntimeVarProc *fetchProc;
    Tcl_ResolveVarDeleteProc *deleteProc;
} Tcl_ResolvedVarInfo;

typedef int (Tcl_ResolveCompiledVarProc)(Tcl_Interp *interp,
	const char *name, int length, Tcl_Namespace *context,
	const char *name, Tcl_Size length, Tcl_Namespace *context,
	Tcl_ResolvedVarInfo **rPtr);

typedef int (Tcl_ResolveVarProc)(Tcl_Interp *interp, const char *name,
	Tcl_Namespace *context, int flags, Tcl_Var *rPtr);

typedef int (Tcl_ResolveCmdProc)(Tcl_Interp *interp, const char *name,
	Tcl_Namespace *context, int flags, Tcl_Command *rPtr);
222
223
224
225
226
227
228
229
230
231
232




233
234
235
236
237






238
239
240
241
242
243
244
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







-
-
-
-
+
+
+
+



-
-
+
+
+
+
+
+







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

typedef struct Tcl_Ensemble Tcl_Ensemble;
typedef struct NamespacePathEntry NamespacePathEntry;

/*
 * Special hashtable for variables: this is just a Tcl_HashTable with an nsPtr
 * field added at the end: in this way variables can find their namespace
 * without having to copy a pointer in their struct: they can access it via
 * their hPtr->tablePtr.
 * Special hashtable for variables:  This is just a Tcl_HashTable with nsPtr
 * and arrayPtr fields added at the end so that variables can find their
 * namespace and possibly containing array without having to copy a pointer in
 * their struct by accessing them via their hPtr->tablePtr.
 */

typedef struct TclVarHashTable {
    Tcl_HashTable table;
    struct Namespace *nsPtr;
    Tcl_HashTable table;	/* "Inherit" from Tcl_HashTable. */
    struct Namespace *nsPtr;	/* The namespace containing the variables. */
#if TCL_MAJOR_VERSION > 8
    struct Var *arrayPtr;	/* The array containing the variables, if they
				 * are variables in an array at all. */
#endif /* TCL_MAJOR_VERSION > 8 */
} TclVarHashTable;

/*
 * This is for itcl - it likes to search our varTables directly :(
 */

#define TclVarHashFindVar(tablePtr, key) \
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
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







-
+
















+

+
+
+
-
+



-
+



-
+




















-
+

-
+

-
+




-
+







typedef struct Namespace {
    char *name;			/* The namespace's simple (unqualified) name.
				 * This contains no ::'s. The name of the
				 * global namespace is "" although "::" is an
				 * synonym. */
    char *fullName;		/* The namespace's fully qualified name. This
				 * starts with ::. */
    void *clientData;	/* An arbitrary value associated with this
    void *clientData;		/* An arbitrary value associated with this
				 * namespace. */
    Tcl_NamespaceDeleteProc *deleteProc;
				/* Procedure invoked when deleting the
				 * namespace to, e.g., free clientData. */
    struct Namespace *parentPtr;/* Points to the namespace that contains this
				 * one. NULL if this is the global
				 * namespace. */
#ifndef BREAK_NAMESPACE_COMPAT
    Tcl_HashTable childTable;	/* Contains any child namespaces. Indexed by
				 * strings; values have type (Namespace *). */
#else
    Tcl_HashTable *childTablePtr;
				/* Contains any child namespaces. Indexed by
				 * strings; values have type (Namespace *). If
				 * NULL, there are no children. */
#endif
#if TCL_MAJOR_VERSION > 8
    size_t nsId;		/* Unique id for the namespace. */
#else
    unsigned long nsId;
#endif
    Tcl_Interp *interp;	/* The interpreter containing this
    Tcl_Interp *interp;		/* The interpreter containing this
				 * namespace. */
    int flags;			/* OR-ed combination of the namespace status
				 * flags NS_DYING and NS_DEAD listed below. */
    size_t activationCount;	/* Number of "activations" or active call
    Tcl_Size activationCount;	/* Number of "activations" or active call
				 * frames for this namespace that are on the
				 * Tcl call stack. The namespace won't be
				 * freed until activationCount becomes zero. */
    size_t refCount;		/* Count of references by namespaceName
    Tcl_Size refCount;		/* Count of references by namespaceName
				 * objects. The namespace can't be freed until
				 * refCount becomes zero. */
    Tcl_HashTable cmdTable;	/* Contains all the commands currently
				 * registered in the namespace. Indexed by
				 * strings; values have type (Command *).
				 * Commands imported by Tcl_Import have
				 * Command structures that point (via an
				 * ImportedCmdRef structure) to the Command
				 * structure in the source namespace's command
				 * table. */
    TclVarHashTable varTable;	/* Contains all the (global) variables
				 * currently in this namespace. Indexed by
				 * strings; values have type (Var *). */
    char **exportArrayPtr;	/* Points to an array of string patterns
				 * specifying which commands are exported. A
				 * pattern may include "string match" style
				 * wildcard characters to specify multiple
				 * commands; however, no namespace qualifiers
				 * are allowed. NULL if no export patterns are
				 * registered. */
    size_t numExportPatterns;	/* Number of export patterns currently
    Tcl_Size numExportPatterns;	/* Number of export patterns currently
				 * registered using "namespace export". */
    size_t maxExportPatterns;	/* Number of export patterns for which space
    Tcl_Size maxExportPatterns;	/* Number of export patterns for which space
				 * is currently allocated. */
    size_t cmdRefEpoch;		/* Incremented if a newly added command
    Tcl_Size cmdRefEpoch;	/* Incremented if a newly added command
				 * shadows a command for which this namespace
				 * has already cached a Command* pointer; this
				 * causes all its cached Command* pointers to
				 * be invalidated. */
    size_t resolverEpoch;	/* Incremented whenever (a) the name
    Tcl_Size resolverEpoch;	/* Incremented whenever (a) the name
				 * resolution rules change for this namespace
				 * or (b) a newly added command shadows a
				 * command that is compiled to bytecodes. This
				 * invalidates all byte codes compiled in the
				 * namespace, causing the code to be
				 * recompiled under the new rules.*/
    Tcl_ResolveCmdProc *cmdResProc;
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
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







-
+










-
+







    Tcl_ResolveCompiledVarProc *compiledVarResProc;
				/* If non-null, this procedure overrides the
				 * usual variable resolution mechanism in Tcl.
				 * This procedure is invoked within
				 * LookupCompiledLocal to resolve variable
				 * references within the namespace at compile
				 * time. */
    size_t exportLookupEpoch;	/* Incremented whenever a command is added to
    Tcl_Size exportLookupEpoch;	/* Incremented whenever a command is added to
				 * a namespace, removed from a namespace or
				 * the exports of a namespace are changed.
				 * Allows TIP#112-driven command lists to be
				 * validated efficiently. */
    Tcl_Ensemble *ensembles;	/* List of structures that contain the details
				 * of the ensembles that are implemented on
				 * top of this namespace. */
    Tcl_Obj *unknownHandlerPtr;	/* A script fragment to be used when command
				 * resolution in this namespace fails. TIP
				 * 181. */
    size_t commandPathLength;	/* The length of the explicit path. */
    Tcl_Size commandPathLength;	/* The length of the explicit path. */
    NamespacePathEntry *commandPathArray;
				/* The explicit path of the namespace as an
				 * array. */
    NamespacePathEntry *commandPathSourceList;
				/* Linked list of path entries that point to
				 * this namespace. */
    Tcl_NamespaceDeleteProc *earlyDeleteProc;
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
442
443
444
445
446
447
448
449
450
451
452
453
454

455
456
457
458
459
460
461
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
442
443
444
445
446

447
448
449
450
451
452
453
454







-
+

-
-
-
+
+
+
+

-
-
+
+
-
-
-
-
-
+
+
+
+
-
-







+
-
+









+
+




+
















-
+







				 * commandPathSourceList field. */
};

/*
 * Flags used to represent the status of a namespace:
 *
 * NS_DYING -	1 means Tcl_DeleteNamespace has been called to delete the
 *		namespace but there are still active call frames on the Tcl
 *		namespace.  There may still be active call frames on the Tcl
 *		stack that refer to the namespace. When the last call frame
 *		referring to it has been popped, it's variables and command
 *		will be destroyed and it will be marked "dead" (NS_DEAD). The
 *		namespace can no longer be looked up by name.
 *		referring to it has been popped, its remaining variables and
 *		commands are destroyed and it is marked "dead" (NS_DEAD).
 * NS_TEARDOWN  -1 means that TclTeardownNamespace has already been called on
 *		this namespace and it should not be called again [Bug 1355942].
 * NS_DEAD -	1 means Tcl_DeleteNamespace has been called to delete the
 *		namespace and no call frames still refer to it. Its variables
 *		and command have already been destroyed. This bit allows the
 *		namespace and no call frames still refer to it. It is no longer
 *		accessible by name. Its variables and commands have already
 *		namespace resolution code to recognize that the namespace is
 *		"deleted". When the last namespaceName object in any byte code
 *		unit that refers to the namespace has been freed (i.e., when
 *		the namespace's refCount is 0), the namespace's storage will
 *		be freed.
 *		been destroyed.  When the last namespaceName object in any byte
 *		code unit that refers to the namespace has been freed (i.e.,
 *		when the namespace's refCount is 0), the namespace's storage
 *		will be freed.
 * NS_KILLED -	1 means that TclTeardownNamespace has already been called on
 *		this namespace and it should not be called again [Bug 1355942]
 * NS_SUPPRESS_COMPILATION -
 *		Marks the commands in this namespace for not being compiled,
 *		forcing them to be looked up every time.
 */

#define NS_DYING	0x01
#define NS_DEAD		0x02
#define NS_TEARDOWN	0x04
#define NS_KILLED	0x04
#define NS_KILLED	0x04 /* Same as NS_TEARDOWN (Deprecated) */
#define NS_SUPPRESS_COMPILATION	0x08

/*
 * Flags passed to TclGetNamespaceForQualName:
 *
 * TCL_GLOBAL_ONLY		- (see tcl.h) Look only in the global ns.
 * TCL_NAMESPACE_ONLY		- (see tcl.h) Look only in the context ns.
 * TCL_CREATE_NS_IF_UNKNOWN	- Create unknown namespaces.
 * TCL_FIND_ONLY_NS		- The name sought is a namespace name.
 * TCL_FIND_IF_NOT_SIMPLE	- Retrieve last namespace even if the rest of
 *				  name is not simple name (contains ::).
 */

#define TCL_CREATE_NS_IF_UNKNOWN	0x800
#define TCL_FIND_ONLY_NS		0x1000
#define TCL_FIND_IF_NOT_SIMPLE		0x2000

/*
 * The client data for an ensemble command. This consists of the table of
 * commands that are actually exported by the namespace, and an epoch counter
 * that, combined with the exportLookupEpoch field of the namespace structure,
 * defines whether the table contains valid data or will need to be recomputed
 * next time the ensemble command is called.
 */

typedef struct EnsembleConfig {
    Namespace *nsPtr;		/* The namespace backing this ensemble up. */
    Tcl_Command token;		/* The token for the command that provides
				 * ensemble support for the namespace, or NULL
				 * if the command has been deleted (or never
				 * existed; the global namespace never has an
				 * ensemble command.) */
    size_t epoch;		/* The epoch at which this ensemble's table of
    Tcl_Size epoch;		/* The epoch at which this ensemble's table of
				 * exported commands is valid. */
    char **subcommandArrayPtr;	/* Array of ensemble subcommand names. At all
				 * consistent points, this will have the same
				 * number of entries as there are entries in
				 * the subcommandTable hash. */
    Tcl_HashTable subcommandTable;
				/* Hash table of ensemble subcommand names,
473
474
475
476
477
478
479
480

481
482
483
484
485
486
487
466
467
468
469
470
471
472

473
474
475
476
477
478
479
480







-
+







    struct EnsembleConfig *next;/* The next ensemble in the linked list of
				 * ensembles associated with a namespace. If
				 * this field points to this ensemble, the
				 * structure has already been unlinked from
				 * all lists, and cannot be found by scanning
				 * the list from the namespace's ensemble
				 * field. */
    int flags;			/* ORed combo of TCL_ENSEMBLE_PREFIX,
    int flags;			/* OR'ed combo of TCL_ENSEMBLE_PREFIX,
				 * ENSEMBLE_DEAD and ENSEMBLE_COMPILE. */

    /* OBJECT FIELDS FOR ENSEMBLE CONFIGURATION */

    Tcl_Obj *subcommandDict;	/* Dictionary providing mapping from
				 * subcommands to their implementing command
				 * prefixes, or NULL if we are to build the
500
501
502
503
504
505
506
507

508
509
510
511

512
513
514
515
516
517
518
493
494
495
496
497
498
499

500
501
502
503

504
505
506
507
508
509
510
511







-
+



-
+







				 * NULL to use the default error-generating
				 * behaviour. The script execution gets all
				 * the arguments to the ensemble command
				 * (including objv[0]) and will have the
				 * results passed directly back to the caller
				 * (including the error code) unless the code
				 * is TCL_CONTINUE in which case the
				 * subcommand will be reparsed by the ensemble
				 * subcommand will be re-parsed by the ensemble
				 * core, presumably because the ensemble
				 * itself has been updated. */
    Tcl_Obj *parameterList;	/* List of ensemble parameter names. */
    int numParameters;		/* Cached number of parameters. This is either
    Tcl_Size numParameters;	/* Cached number of parameters. This is either
				 * 0 (if the parameterList field is NULL) or
				 * the length of the list in the parameterList
				 * field. */
} EnsembleConfig;

/*
 * Various bits for the EnsembleConfig.flags field.
534
535
536
537
538
539
540
541

542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560

561
562
563
564
565
566
567

568
569
570
571
572
573
574
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
558
559

560
561
562
563
564
565
566
567







-
+


















-
+






-
+







 * specific C procedure whenever certain operations are performed on a
 * variable.
 */

typedef struct VarTrace {
    Tcl_VarTraceProc *traceProc;/* Procedure to call when operations given by
				 * flags are performed on variable. */
    void *clientData;	/* Argument to pass to proc. */
    void *clientData;		/* Argument to pass to proc. */
    int flags;			/* What events the trace procedure is
				 * interested in: OR-ed combination of
				 * TCL_TRACE_READS, TCL_TRACE_WRITES,
				 * TCL_TRACE_UNSETS and TCL_TRACE_ARRAY. */
    struct VarTrace *nextPtr;	/* Next in list of traces associated with a
				 * particular variable. */
} VarTrace;

/*
 * The following structure defines a command trace, which is used to invoke a
 * specific C procedure whenever certain operations are performed on a
 * command.
 */

typedef struct CommandTrace {
    Tcl_CommandTraceProc *traceProc;
				/* Procedure to call when operations given by
				 * flags are performed on command. */
    void *clientData;	/* Argument to pass to proc. */
    void *clientData;		/* Argument to pass to proc. */
    int flags;			/* What events the trace procedure is
				 * interested in: OR-ed combination of
				 * TCL_TRACE_RENAME, TCL_TRACE_DELETE. */
    struct CommandTrace *nextPtr;
				/* Next in list of traces associated with a
				 * particular command. */
    size_t refCount;	/* Used to ensure this structure is not
    Tcl_Size refCount;		/* Used to ensure this structure is not
				 * deleted too early. Keeps track of how many
				 * pieces of code have a pointer to this
				 * structure. */
} CommandTrace;

/*
 * When a command trace is active (i.e. its associated procedure is executing)
632
633
634
635
636
637
638
639
640


641
642
643
644
645
646
647
648
649
650
651

652
653
654
655
656
657
658
659
660
661
662

663
664
665
666
667
668
669
670





671
672
673
674
675
676


677
678
679
680

681
682
683
684
685
686
687
625
626
627
628
629
630
631


632
633
634
635
636
637
638
639
640
641
642
643

644
645
646
647
648
649
650
651
652
653
654

655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672


673
674
675
676
677

678
679
680
681
682
683
684
685







-
-
+
+










-
+










-
+








+
+
+
+
+




-
-
+
+



-
+







				 * to in a procedure, or a variable created by
				 * "upvar", this field points to the
				 * referenced variable's Var struct. */
    } value;
} Var;

typedef struct VarInHash {
    Var var;
    size_t refCount;		/* Counts number of active uses of this
    Var var;			/* "Inherit" from Var. */
    Tcl_Size refCount;		/* Counts number of active uses of this
				 * variable: 1 for the entry in the hash
				 * table, 1 for each additional variable whose
				 * linkPtr points here, 1 for each nested
				 * trace active on variable, and 1 if the
				 * variable is a namespace variable. This
				 * record can't be deleted until refCount
				 * becomes 0. */
    Tcl_HashEntry entry;	/* The hash table entry that refers to this
				 * variable. This is used to find the name of
				 * the variable and to delete it from its
				 * hashtable if it is no longer needed. It
				 * hash table if it is no longer needed. It
				 * also holds the variable's name. */
} VarInHash;

/*
 * Flag bits for variables. The first two (VAR_ARRAY and VAR_LINK) are
 * mutually exclusive and give the "type" of the variable. If none is set,
 * this is a scalar variable.
 *
 * VAR_ARRAY -			1 means this is an array variable rather than
 *				a scalar variable or link. The "tablePtr"
 *				field points to the array's hashtable for its
 *				field points to the array's hash table for its
 *				elements.
 * VAR_LINK -			1 means this Var structure contains a pointer
 *				to another Var structure that either has the
 *				real value or is itself another VAR_LINK
 *				pointer. Variables like this come about
 *				through "upvar" and "global" commands, or
 *				through references to variables in enclosing
 *				namespaces.
 * VAR_CONSTANT -		1 means this is a constant "variable", and
 *				cannot be written to by ordinary commands.
 *				Structurally, it's the same as a scalar when
 *				being read, but writes are rejected. Constants
 *				are not supported inside arrays.
 *
 * Flags that indicate the type and status of storage; none is set for
 * compiled local variables (Var structs).
 *
 * VAR_IN_HASHTABLE -		1 means this variable is in a hashtable and
 *				the Var structure is malloced. 0 if it is a
 * VAR_IN_HASHTABLE -		1 means this variable is in a hash table and
 *				the Var structure is malloc'ed. 0 if it is a
 *				local variable that was assigned a slot in a
 *				procedure frame by the compiler so the Var
 *				storage is part of the call frame.
 * VAR_DEAD_HASH		1 means that this var's entry in the hashtable
 * VAR_DEAD_HASH		1 means that this var's entry in the hash table
 *				has already been deleted.
 * VAR_ARRAY_ELEMENT -		1 means that this variable is an array
 *				element, so it is not legal for it to be an
 *				array itself (the VAR_ARRAY flag had better
 *				not be set).
 * VAR_NAMESPACE_VAR -		1 means that this variable was declared as a
 *				namespace variable. This flag ensures it
728
729
730
731
732
733
734

735
736
737
738
739
740
741
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740







+







 * Keep the flag values for VAR_ARGUMENT and VAR_TEMPORARY so that old values
 * in precompiled scripts keep working.
 */

/* Type of value (0 is scalar) */
#define VAR_ARRAY		0x1
#define VAR_LINK		0x2
#define VAR_CONSTANT		0x10000

/* Type of storage (0 is compiled local) */
#define VAR_IN_HASHTABLE	0x4
#define VAR_DEAD_HASH		0x8
#define VAR_ARRAY_ELEMENT	0x1000
#define VAR_NAMESPACE_VAR	0x80	/* KEEP OLD VALUE for Itcl */

762
763
764
765
766
767
768

769
770
771
772
773
774
775

776
777
778
779
780
781
782



783
784
785
786
787

788
789
790
791
792
793
794
761
762
763
764
765
766
767
768
769
770
771
772
773
774

775
776
777
778
779
780
781
782
783
784
785
786
787
788
789

790
791
792
793
794
795
796
797







+






-
+







+
+
+




-
+







/*
 * Macros to ensure that various flag bits are set properly for variables.
 * The ANSI C "prototypes" for these macros are:
 *
 * MODULE_SCOPE void	TclSetVarScalar(Var *varPtr);
 * MODULE_SCOPE void	TclSetVarArray(Var *varPtr);
 * MODULE_SCOPE void	TclSetVarLink(Var *varPtr);
 * MODULE_SCOPE void	TclSetVarConstant(Var *varPtr);
 * MODULE_SCOPE void	TclSetVarArrayElement(Var *varPtr);
 * MODULE_SCOPE void	TclSetVarUndefined(Var *varPtr);
 * MODULE_SCOPE void	TclClearVarUndefined(Var *varPtr);
 */

#define TclSetVarScalar(varPtr) \
    (varPtr)->flags &= ~(VAR_ARRAY|VAR_LINK)
    (varPtr)->flags &= ~(VAR_ARRAY|VAR_LINK|VAR_CONSTANT)

#define TclSetVarArray(varPtr) \
    (varPtr)->flags = ((varPtr)->flags & ~VAR_LINK) | VAR_ARRAY

#define TclSetVarLink(varPtr) \
    (varPtr)->flags = ((varPtr)->flags & ~VAR_ARRAY) | VAR_LINK

#define TclSetVarConstant(varPtr) \
    (varPtr)->flags = ((varPtr)->flags & ~(VAR_ARRAY|VAR_LINK)) | VAR_CONSTANT

#define TclSetVarArrayElement(varPtr) \
    (varPtr)->flags = ((varPtr)->flags & ~VAR_ARRAY) | VAR_ARRAY_ELEMENT

#define TclSetVarUndefined(varPtr) \
    (varPtr)->flags &= ~(VAR_ARRAY|VAR_LINK);\
    (varPtr)->flags &= ~(VAR_ARRAY|VAR_LINK|VAR_CONSTANT);\
    (varPtr)->value.objPtr = NULL

#define TclClearVarUndefined(varPtr)

#define TclSetVarTraceActive(varPtr) \
    (varPtr)->flags |= VAR_TRACE_ACTIVE

812
813
814
815
816
817
818

819
820
821
822
823
824
825
826








827
828
829
830
831
832
833
834
835
836




837
838
839
840
841
842
843
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859







+








+
+
+
+
+
+
+
+










+
+
+
+







    }

/*
 * Macros to read various flag bits of variables.
 * The ANSI C "prototypes" for these macros are:
 *
 * MODULE_SCOPE int	TclIsVarScalar(Var *varPtr);
 * MODULE_SCOPE int	TclIsVarConstant(Var *varPtr);
 * MODULE_SCOPE int	TclIsVarLink(Var *varPtr);
 * MODULE_SCOPE int	TclIsVarArray(Var *varPtr);
 * MODULE_SCOPE int	TclIsVarUndefined(Var *varPtr);
 * MODULE_SCOPE int	TclIsVarArrayElement(Var *varPtr);
 * MODULE_SCOPE int	TclIsVarTemporary(Var *varPtr);
 * MODULE_SCOPE int	TclIsVarArgument(Var *varPtr);
 * MODULE_SCOPE int	TclIsVarResolved(Var *varPtr);
 */

#define TclVarFindHiddenArray(varPtr,arrayPtr)				\
    do {								\
	if ((arrayPtr == NULL) && TclIsVarInHash(varPtr) &&		\
		(TclVarParentArray(varPtr) != NULL)) {			\
	    arrayPtr = TclVarParentArray(varPtr);			\
	}								\
    } while(0)

#define TclIsVarScalar(varPtr) \
    !((varPtr)->flags & (VAR_ARRAY|VAR_LINK))

#define TclIsVarLink(varPtr) \
    ((varPtr)->flags & VAR_LINK)

#define TclIsVarArray(varPtr) \
    ((varPtr)->flags & VAR_ARRAY)

/* Implies scalar as well. */
#define TclIsVarConstant(varPtr) \
    ((varPtr)->flags & VAR_CONSTANT)

#define TclIsVarUndefined(varPtr) \
    ((varPtr)->value.objPtr == NULL)

#define TclIsVarArrayElement(varPtr) \
    ((varPtr)->flags & VAR_ARRAY_ELEMENT)

#define TclIsVarNamespaceVar(varPtr) \
865
866
867
868
869
870
871



872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911


912

913
914
915
916
917
918
919
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906



907
908
909
910
911

912
913
914

915
916
917


918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941

942
943
944
945
946
947
948
949







+
+
+



+
+
+




+
+
+
+
+
+
-
-
-
+
+
+


-
+


-
+


-
-
+
+




















+
+
-
+







    ((varPtr)->flags & VAR_DEAD_HASH)

#define TclGetVarNsPtr(varPtr) \
    (TclIsVarInHash(varPtr) \
	? ((TclVarHashTable *) ((((VarInHash *) (varPtr))->entry.tablePtr)))->nsPtr \
	: NULL)

#define TclVarParentArray(varPtr)					\
    ((TclVarHashTable *) ((VarInHash *) (varPtr))->entry.tablePtr)->arrayPtr

#define VarHashRefCount(varPtr) \
    ((VarInHash *) (varPtr))->refCount

#define VarHashGetKey(varPtr) \
    (((VarInHash *)(varPtr))->entry.key.objPtr)

/*
 * Macros for direct variable access by TEBC.
 */

#define TclIsVarTricky(varPtr,trickyFlags)				\
    (   ((varPtr)->flags & (VAR_ARRAY|VAR_LINK|trickyFlags))		\
	  || (TclIsVarInHash(varPtr)					\
		&& (TclVarParentArray(varPtr) != NULL)			\
		&& (TclVarParentArray(varPtr)->flags & (trickyFlags))))

#define TclIsVarDirectReadable(varPtr) \
    (   !((varPtr)->flags & (VAR_ARRAY|VAR_LINK|VAR_TRACED_READ)) \
    &&  (varPtr)->value.objPtr)
#define TclIsVarDirectReadable(varPtr)					\
    (   (!TclIsVarTricky(varPtr,VAR_TRACED_READ))			\
	&& (varPtr)->value.objPtr)

#define TclIsVarDirectWritable(varPtr) \
    !((varPtr)->flags & (VAR_ARRAY|VAR_LINK|VAR_TRACED_WRITE|VAR_DEAD_HASH))
    (!TclIsVarTricky(varPtr,VAR_TRACED_WRITE|VAR_DEAD_HASH|VAR_CONSTANT))

#define TclIsVarDirectUnsettable(varPtr) \
    !((varPtr)->flags & (VAR_ARRAY|VAR_LINK|VAR_TRACED_READ|VAR_TRACED_WRITE|VAR_TRACED_UNSET|VAR_DEAD_HASH))
    (!TclIsVarTricky(varPtr,VAR_TRACED_READ|VAR_TRACED_WRITE|VAR_TRACED_UNSET|VAR_DEAD_HASH|VAR_CONSTANT))

#define TclIsVarDirectModifyable(varPtr) \
    (   !((varPtr)->flags & (VAR_ARRAY|VAR_LINK|VAR_TRACED_READ|VAR_TRACED_WRITE)) \
    &&  (varPtr)->value.objPtr)
    (   (!TclIsVarTricky(varPtr,VAR_TRACED_READ|VAR_TRACED_WRITE|VAR_CONSTANT))	\
	&&  (varPtr)->value.objPtr)

#define TclIsVarDirectReadable2(varPtr, arrayPtr) \
    (TclIsVarDirectReadable(varPtr) &&\
	(!(arrayPtr) || !((arrayPtr)->flags & VAR_TRACED_READ)))

#define TclIsVarDirectWritable2(varPtr, arrayPtr) \
    (TclIsVarDirectWritable(varPtr) &&\
	(!(arrayPtr) || !((arrayPtr)->flags & VAR_TRACED_WRITE)))

#define TclIsVarDirectModifyable2(varPtr, arrayPtr) \
    (TclIsVarDirectModifyable(varPtr) &&\
	(!(arrayPtr) || !((arrayPtr)->flags & (VAR_TRACED_READ|VAR_TRACED_WRITE))))

/*
 *----------------------------------------------------------------
 * Data structures related to procedures. These are used primarily in
 * tclProc.c, tclCompile.c, and tclExecute.c.
 *----------------------------------------------------------------
 */

#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
#   define TCLFLEXARRAY
#if defined(__GNUC__) && (__GNUC__ > 2)
#elif defined(__GNUC__) && (__GNUC__ > 2)
#   define TCLFLEXARRAY 0
#else
#   define TCLFLEXARRAY 1
#endif

/*
 * Forward declaration to prevent an error when the forward reference to
936
937
938
939
940
941
942
943

944
945

946

947

948
949
950

951
952
953
954
955
956
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
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
1024
1025
1026
1027
1028
1029
1030
1031







-
+

-
+

+
-
+
-
-
-
+










+
+
+
+
+
+
-
+















-
+










-
-
+
+







 */

typedef struct CompiledLocal {
    struct CompiledLocal *nextPtr;
				/* Next compiler-recognized local variable for
				 * this procedure, or NULL if this is the last
				 * local. */
    size_t nameLength;		/* The number of bytes in local variable's name.
    Tcl_Size nameLength;	/* The number of bytes in local variable's name.
				 * Among others used to speed up var lookups. */
    int frameIndex;		/* Index in the array of compiler-assigned
    Tcl_Size frameIndex;	/* Index in the array of compiler-assigned
				 * variables in the procedure call frame. */
#if TCL_MAJOR_VERSION < 9
    int flags;			/* Flag bits for the local variable. Same as
    int flags;
				 * the flags for the Var structure above,
				 * although only VAR_ARGUMENT, VAR_TEMPORARY,
				 * and VAR_RESOLVED make sense. */
#endif
    Tcl_Obj *defValuePtr;	/* Pointer to the default value of an
				 * argument, if any. NULL if not an argument
				 * or, if an argument, no default value. */
    Tcl_ResolvedVarInfo *resolveInfo;
				/* Customized variable resolution info
				 * supplied by the Tcl_ResolveCompiledVarProc
				 * associated with a namespace. Each variable
				 * is marked by a unique tag during
				 * compilation, and that same tag is used to
				 * find the variable at runtime. */
#if TCL_MAJOR_VERSION > 8
    int flags;			/* Flag bits for the local variable. Same as
				 * the flags for the Var structure above,
				 * although only VAR_ARGUMENT, VAR_TEMPORARY,
				 * and VAR_RESOLVED make sense. */
#endif
    char name[TCLFLEXARRAY];		/* Name of the local variable starts here. If
    char name[TCLFLEXARRAY];	/* Name of the local variable starts here. If
				 * the name is NULL, this will just be '\0'.
				 * The actual size of this field will be large
				 * enough to hold the name. MUST BE THE LAST
				 * FIELD IN THE STRUCTURE! */
} CompiledLocal;

/*
 * The structure below defines a command procedure, which consists of a
 * collection of Tcl commands plus information about arguments and other local
 * variables recognized at compile time.
 */

typedef struct Proc {
    struct Interp *iPtr;	/* Interpreter for which this command is
				 * defined. */
    size_t refCount;		/* Reference count: 1 if still present in
    Tcl_Size refCount;		/* Reference count: 1 if still present in
				 * command table plus 1 for each call to the
				 * procedure that is currently active. This
				 * structure can be freed when refCount
				 * becomes zero. */
    struct Command *cmdPtr;	/* Points to the Command structure for this
				 * procedure. This is used to get the
				 * namespace in which to execute the
				 * procedure. */
    Tcl_Obj *bodyPtr;		/* Points to the ByteCode object for
				 * procedure's body command. */
    int numArgs;		/* Number of formal parameters. */
    int numCompiledLocals;	/* Count of local variables recognized by the
    Tcl_Size numArgs;		/* Number of formal parameters. */
    Tcl_Size numCompiledLocals;	/* Count of local variables recognized by the
				 * compiler including arguments and
				 * temporaries. */
    CompiledLocal *firstLocalPtr;
				/* Pointer to first of the procedure's
				 * compiler-allocated local variables, or NULL
				 * if none. The first numArgs entries in this
				 * list describe the procedure's formal
1009
1010
1011
1012
1013
1014
1015
1016

1017



1018

1019

1020
1021
1022
1023
1024
1025
1026
1044
1045
1046
1047
1048
1049
1050

1051
1052
1053
1054
1055
1056
1057

1058
1059
1060
1061
1062
1063
1064
1065







-
+

+
+
+

+
-
+








/*
 * The structure below defines a command trace. This is used to allow Tcl
 * clients to find out whenever a command is about to be executed.
 */

typedef struct Trace {
    int level;			/* Only trace commands at nesting level less
    Tcl_Size level;		/* Only trace commands at nesting level less
				 * than or equal to this. */
#if TCL_MAJOR_VERSION > 8
    Tcl_CmdObjTraceProc2 *proc;	/* Procedure to call to trace command. */
#else
    Tcl_CmdObjTraceProc *proc;	/* Procedure to call to trace command. */
#endif
    void *clientData;	/* Arbitrary value to pass to proc. */
    void *clientData;		/* Arbitrary value to pass to proc. */
    struct Trace *nextPtr;	/* Next in list of traces for this interp. */
    int flags;			/* Flags governing the trace - see
				 * Tcl_CreateObjTrace for details. */
    Tcl_CmdObjTraceDeleteProc *delProc;
				/* Procedure to call when trace is deleted. */
} Trace;

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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213

1214
1215
1216
1217
1218
1219
1220
1221







-
+


-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+







} ActiveInterpTrace;

/*
 * Flag values designating types of execution traces. See tclTrace.c for
 * related flag values.
 *
 * TCL_TRACE_ENTER_EXEC		- triggers enter/enterstep traces.
 * 				- passed to Tcl_CreateObjTrace to set up
 *				- passed to Tcl_CreateObjTrace to set up
 *				  "enterstep" traces.
 * TCL_TRACE_LEAVE_EXEC		- triggers leave/leavestep traces.
 * 				- passed to Tcl_CreateObjTrace to set up
 *				- passed to Tcl_CreateObjTrace to set up
 *				  "leavestep" traces.
 */

#define TCL_TRACE_ENTER_EXEC	1
#define TCL_TRACE_LEAVE_EXEC	2

#if TCL_MAJOR_VERSION > 8
#define TclObjTypeHasProc(objPtr, proc) (((objPtr)->typePtr \
	&& ((offsetof(Tcl_ObjType, proc) < offsetof(Tcl_ObjType, version)) \
	|| (offsetof(Tcl_ObjType, proc) < (objPtr)->typePtr->version))) ? \
	((objPtr)->typePtr)->proc : NULL)

MODULE_SCOPE Tcl_Size TclLengthOne(Tcl_Obj *);

/*
 * Abstract List
 *
 * This structure provides the functions used in List operations to emulate a
 * List for AbstractList types.
 */

static inline Tcl_Size
TclObjTypeLength(
    Tcl_Obj *objPtr)
{
    Tcl_ObjTypeLengthProc *proc = TclObjTypeHasProc(objPtr, lengthProc);
    return proc(objPtr);
}

static inline int
TclObjTypeIndex(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    Tcl_Size index,
    Tcl_Obj **elemObjPtr)
{
    Tcl_ObjTypeIndexProc *proc = TclObjTypeHasProc(objPtr, indexProc);
    return proc(interp, objPtr, index, elemObjPtr);
}

static inline int
TclObjTypeSlice(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    Tcl_Size fromIdx,
    Tcl_Size toIdx,
    Tcl_Obj **newObjPtr)
{
    Tcl_ObjTypeSliceProc *proc = TclObjTypeHasProc(objPtr, sliceProc);
    return proc(interp, objPtr, fromIdx, toIdx, newObjPtr);
}

static inline int
TclObjTypeReverse(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    Tcl_Obj **newObjPtr)
{
    Tcl_ObjTypeReverseProc *proc = TclObjTypeHasProc(objPtr, reverseProc);
    return proc(interp, objPtr, newObjPtr);
}

static inline int
TclObjTypeGetElements(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    Tcl_Size *objCPtr,
    Tcl_Obj ***objVPtr)
{
    Tcl_ObjTypeGetElements *proc = TclObjTypeHasProc(objPtr, getElementsProc);
    return proc(interp, objPtr, objCPtr, objVPtr);
}

static inline Tcl_Obj*
TclObjTypeSetElement(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    Tcl_Size indexCount,
    Tcl_Obj *const indexArray[],
    Tcl_Obj *valueObj)
{
    Tcl_ObjTypeSetElement *proc = TclObjTypeHasProc(objPtr, setElementProc);
    return proc(interp, objPtr, indexCount, indexArray, valueObj);
}

static inline int
TclObjTypeReplace(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    Tcl_Size first,
    Tcl_Size numToDelete,
    Tcl_Size numToInsert,
    Tcl_Obj *const insertObjs[])
{
    Tcl_ObjTypeReplaceProc *proc = TclObjTypeHasProc(objPtr, replaceProc);
    return proc(interp, objPtr, first, numToDelete, numToInsert, insertObjs);
}

static inline int
TclObjTypeInOperator(
    Tcl_Interp *interp,
    Tcl_Obj *valueObj,
    Tcl_Obj *listObj,
    int *boolResult)
{
    Tcl_ObjTypeInOperatorProc *proc = TclObjTypeHasProc(listObj, inOperProc);
    return proc(interp, valueObj, listObj, boolResult);
}
#endif /* TCL_MAJOR_VERSION > 8 */

/*
 * The structure below defines an entry in the assocData hash table which is
 * associated with an interpreter. The entry contains a pointer to a function
 * to call when the interpreter is deleted, and a pointer to a user-defined
 * piece of data.
 */

typedef struct AssocData {
    Tcl_InterpDeleteProc *proc;	/* Proc to call when deleting. */
    void *clientData;	/* Value to pass to proc. */
    void *clientData;		/* Value to pass to proc. */
} AssocData;

/*
 * The structure below defines a call frame. A call frame defines a naming
 * context for a procedure call: its local naming scope (for local variables)
 * and its global naming scope (a namespace, perhaps the global :: namespace).
 * A call frame can also define the naming context for a namespace eval or
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

1116
1117
1118

1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129

1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144


1145
1146
1147
1148
1149

1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160




1161
1162
1163
1164


1165
1166
1167
1168
1169
1170
1171
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







-
-
-
+
+
+


















-
+


-
+
-









-
+













-
-
+
+




-
+








-
-
-
+
+
+
+


-
-
+
+








/*
 * Will be grown to contain: pointers to the varnames (allocated at the end),
 * plus the init values for each variable (suitable to be memcopied on init)
 */

typedef struct LocalCache {
    size_t refCount;
    int numVars;
    Tcl_Obj *varName0;
    Tcl_Size refCount;		/* Reference count. */
    Tcl_Size numVars;		/* Number of variables. */
    Tcl_Obj *varName0;		/* First variable name. */
} LocalCache;

#define localName(framePtr, i) \
    ((&((framePtr)->localCachePtr->varName0))[(i)])

MODULE_SCOPE void	TclFreeLocalCache(Tcl_Interp *interp,
			    LocalCache *localCachePtr);

typedef struct CallFrame {
    Namespace *nsPtr;		/* Points to the namespace used to resolve
				 * commands and global variables. */
    int isProcCallFrame;	/* If 0, the frame was pushed to execute a
				 * namespace command and var references are
				 * treated as references to namespace vars;
				 * varTablePtr and compiledLocals are ignored.
				 * If FRAME_IS_PROC is set, the frame was
				 * pushed to execute a Tcl procedure and may
				 * have local vars. */
    int objc;			/* This and objv below describe the arguments
    Tcl_Size objc;		/* This and objv below describe the arguments
				 * for this procedure call. */
    Tcl_Obj *const *objv;	/* Array of argument objects. */
    struct CallFrame *callerPtr;
    struct CallFrame *callerPtr;/* Value of interp->framePtr when this
				/* Value of interp->framePtr when this
				 * procedure was invoked (i.e. next higher in
				 * stack of all active procedures). */
    struct CallFrame *callerVarPtr;
				/* Value of interp->varFramePtr when this
				 * procedure was invoked (i.e. determines
				 * variable scoping within caller). Same as
				 * callerPtr unless an "uplevel" command or
				 * something equivalent was active in the
				 * caller). */
    int level;			/* Level of this procedure, for "uplevel"
    Tcl_Size level;		/* Level of this procedure, for "uplevel"
				 * purposes (i.e. corresponds to nesting of
				 * callerVarPtr's, not callerPtr's). 1 for
				 * outermost procedure, 0 for top-level. */
    Proc *procPtr;		/* Points to the structure defining the called
				 * procedure. Used to get information such as
				 * the number of compiled local variables
				 * (local variables assigned entries ["slots"]
				 * in the compiledLocals array below). */
    TclVarHashTable *varTablePtr;
				/* Hash table containing local variables not
				 * recognized by the compiler, or created at
				 * execution time through, e.g., upvar.
				 * Initially NULL and created if needed. */
    int numCompiledLocals;	/* Count of local variables recognized by the
				 * compiler including arguments. */
    Tcl_Size numCompiledLocals;	/* Count of local variables recognized
				 * by the compiler including arguments. */
    Var *compiledLocals;	/* Points to the array of local variables
				 * recognized by the compiler. The compiler
				 * emits code that refers to these variables
				 * using an index into this array. */
    void *clientData;	/* Pointer to some context that is used by
    void *clientData;		/* Pointer to some context that is used by
				 * object systems. The meaning of the contents
				 * of this field is defined by the code that
				 * sets it, and it should only ever be set by
				 * the code that is pushing the frame. In that
				 * case, the code that sets it should also
				 * have some means of discovering what the
				 * meaning of the value is, which we do not
				 * specify. */
    LocalCache *localCachePtr;
    Tcl_Obj    *tailcallPtr;
				/* NULL if no tailcall is scheduled */
    LocalCache *localCachePtr;	/* Pointer to the start of the cached variable
				 * names and initialisation data for local
				 * variables. */
    Tcl_Obj *tailcallPtr;	/* NULL if no tailcall is scheduled */
} CallFrame;

#define FRAME_IS_PROC	0x1
#define FRAME_IS_LAMBDA 0x2
#define FRAME_IS_PROC	0x1	/* Frame is a procedure body. */
#define FRAME_IS_LAMBDA 0x2	/* Frame is a lambda term body. */
#define FRAME_IS_METHOD	0x4	/* The frame is a method body, and the frame's
				 * clientData field contains a CallContext
				 * reference. Part of TIP#257. */
#define FRAME_IS_OO_DEFINE 0x8	/* The frame is part of the inside workings of
				 * the [oo::define] command; the clientData
				 * field contains an Object reference that has
				 * been confirmed to refer to a class. Part of
1197
1198
1199
1200
1201
1202
1203
1204
1205


1206
1207
1208
1209
1210
1211
1212
1340
1341
1342
1343
1344
1345
1346


1347
1348
1349
1350
1351
1352
1353
1354
1355







-
-
+
+







    /*
     * General data. Always available.
     */

    int type;			/* Values see below. */
    int level;			/* Number of frames in stack, prevent O(n)
				 * scan of list. */
    int *line;			/* Lines the words of the command start on. */
    int nline;
    Tcl_Size *line;		/* Lines the words of the command start on. */
    Tcl_Size nline;		/* Number of lines in CmdFrame.line. */
    CallFrame *framePtr;	/* Procedure activation record, may be
				 * NULL. */
    struct CmdFrame *nextPtr;	/* Link to calling frame. */
    /*
     * Data needed for Eval vs TEBC
     *
     * EXECUTION CONTEXTS and usage of CmdFrame
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
1385
1386
1387
1388
1389
1390
1391

1392
1393
1394
1395
1396
1397
1398
1399
1400
1401


1402
1403
1404
1405
1406
1407
1408

1409
1410

1411
1412
1413
1414
1415

1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429

1430
1431
1432
1433
1434
1435
1436
1437
1438
1439

1440
1441

1442
1443
1444
1445
1446
1447
1448
1449







-
+









-
-
+
+





-
+

-
+




-
+













-
+









-
+

-
+







	struct {
	    const void *codePtr;/* Byte code currently executed... */
	    const char *pc;	/* ... and instruction pointer. */
	} tebc;
    } data;
    Tcl_Obj *cmdObj;
    const char *cmd;		/* The executed command, if possible... */
    size_t len;			/* ... and its length. */
    Tcl_Size len;		/* ... and its length. */
    const struct CFWordBC *litarg;
				/* Link to set of literal arguments which have
				 * ben pushed on the lineLABCPtr stack by
				 * TclArgumentBCEnter(). These will be removed
				 * by TclArgumentBCRelease. */
} CmdFrame;

typedef struct CFWord {
    CmdFrame *framePtr;		/* CmdFrame to access. */
    int word;			/* Index of the word in the command. */
    size_t refCount;		/* Number of times the word is on the
    Tcl_Size word;		/* Index of the word in the command. */
    Tcl_Size refCount;		/* Number of times the word is on the
				 * stack. */
} CFWord;

typedef struct CFWordBC {
    CmdFrame *framePtr;		/* CmdFrame to access. */
    size_t pc;			/* Instruction pointer of a command in
    Tcl_Size pc;		/* Instruction pointer of a command in
				 * ExtCmdLoc.loc[.] */
    int word;			/* Index of word in
    Tcl_Size word;		/* Index of word in
				 * ExtCmdLoc.loc[cmd]->line[.] */
    struct CFWordBC *prevPtr;	/* Previous entry in stack for same Tcl_Obj. */
    struct CFWordBC *nextPtr;	/* Next entry for same command call. See
				 * CmdFrame litarg field for the list start. */
    Tcl_Obj *obj;		/* Back reference to hashtable key */
    Tcl_Obj *obj;		/* Back reference to hash table key */
} CFWordBC;

/*
 * Structure to record the locations of invisible continuation lines in
 * literal scripts, as character offset from the beginning of the script. Both
 * compiler and direct evaluator use this information to adjust their line
 * counters when tracking through the script, because when it is invoked the
 * continuation line marker as a whole has been removed already, meaning that
 * the \n which was part of it is gone as well, breaking regular line
 * tracking.
 *
 * These structures are allocated and filled by both the function
 * TclSubstTokens() in the file "tclParse.c" and its caller TclEvalEx() in the
 * file "tclBasic.c", and stored in the thread-global hashtable "lineCLPtr" in
 * file "tclBasic.c", and stored in the thread-global hash table "lineCLPtr" in
 * file "tclObj.c". They are used by the functions TclSetByteCodeFromAny() and
 * TclCompileScript(), both found in the file "tclCompile.c". Their memory is
 * released by the function TclFreeObj(), in the file "tclObj.c", and also by
 * the function TclThreadFinalizeObjects(), in the same file.
 */

#define CLL_END		(-1)

typedef struct ContLineLoc {
    int num;			/* Number of entries in loc, not counting the
    Tcl_Size num;		/* Number of entries in loc, not counting the
				 * final -1 marker entry. */
    int loc[TCLFLEXARRAY];/* Table of locations, as character offsets.
    Tcl_Size loc[TCLFLEXARRAY];/* Table of locations, as character offsets.
				 * The table is allocated as part of the
				 * structure, extending behind the nominal end
				 * of the structure. An entry containing the
				 * value -1 is put after the last location, as
				 * end-marker/sentinel. */
} ContLineLoc;

1333
1334
1335
1336
1337
1338
1339
1340

1341
1342
1343

1344
1345
1346
1347

1348
1349
1350
1351
1352
1353
1354
1476
1477
1478
1479
1480
1481
1482

1483
1484
1485

1486
1487
1488
1489

1490
1491
1492
1493
1494
1495
1496
1497







-
+


-
+



-
+







 * procedures (e.g. a lambda) so that their details can be reported correctly
 * by [info frame]. Contains a sub-structure for each extra field.
 */

typedef Tcl_Obj * (GetFrameInfoValueProc)(void *clientData);
typedef struct {
    const char *name;		/* Name of this field. */
    GetFrameInfoValueProc *proc;	/* Function to generate a Tcl_Obj* from the
    GetFrameInfoValueProc *proc;/* Function to generate a Tcl_Obj* from the
				 * clientData, or just use the clientData
				 * directly (after casting) if NULL. */
    void *clientData;	/* Context for above function, or Tcl_Obj* if
    void *clientData;		/* Context for above function, or Tcl_Obj* if
				 * proc field is NULL. */
} ExtraFrameInfoField;
typedef struct {
    size_t length;			/* Length of array. */
    Tcl_Size length;		/* Length of array. */
    ExtraFrameInfoField fields[2];
				/* Really as long as necessary, but this is
				 * long enough for nearly anything. */
} ExtraFrameInfo;

/*
 *----------------------------------------------------------------
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420









1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439




1440
1441
1442
1443
1444
1445
1446
1447





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
1478






1479
1480
1481
1482
1483
1484








1485
1486
1487
1488
1489
1490
1491

1492
1493
1494

1495



1496
1497
1498
1499
1500
1501
1502
1548
1549
1550
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







-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-


-
-












-
+
+
+
+



-
-
-
-
-
+
+
+
+
+

+
+


+
+
+
+
+
+
+
+
+
+
+








-
-
-
-
-
-
-








-
-
-
-
-
+
+
+
+
+
+



-
-
-
+
+
+
+
+
+
+
+






-
+



+
-
+
+
+







/*
 * The type of procedures called by the Tcl bytecode compiler to compile
 * commands. Pointers to these procedures are kept in the Command structure
 * describing each command. The integer value returned by a CompileProc must
 * be one of the following:
 *
 * TCL_OK		Compilation completed normally.
 * TCL_ERROR 		Compilation could not be completed. This can be just a
 * 			judgment by the CompileProc that the command is too
 * 			complex to compile effectively, or it can indicate
 * 			that in the current state of the interp, the command
 * 			would raise an error. The bytecode compiler will not
 * 			do any error reporting at compiler time. Error
 * 			reporting is deferred until the actual runtime,
 * 			because by then changes in the interp state may allow
 * 			the command to be successfully evaluated.
 * TCL_ERROR		Compilation could not be completed. This can be just a
 *			judgment by the CompileProc that the command is too
 *			complex to compile effectively, or it can indicate
 *			that in the current state of the interp, the command
 *			would raise an error. The bytecode compiler will not
 *			do any error reporting at compiler time. Error
 *			reporting is deferred until the actual runtime,
 *			because by then changes in the interp state may allow
 *			the command to be successfully evaluated.
 * TCL_OUT_LINE_COMPILE	A source-compatible alias for TCL_ERROR, kept for the
 * 			sake of old code only.
 */

#define TCL_OUT_LINE_COMPILE	TCL_ERROR

typedef int (CompileProc)(Tcl_Interp *interp, Tcl_Parse *parsePtr,
	struct Command *cmdPtr, struct CompileEnv *compEnvPtr);

/*
 * The type of procedure called from the compilation hook point in
 * SetByteCodeFromAny.
 */

typedef int (CompileHookProc)(Tcl_Interp *interp,
	struct CompileEnv *compEnvPtr, void *clientData);

/*
 * The data structure for a (linked list of) execution stacks.
 * The data structure for a (linked list of) execution stacks. Note that the
 * first word on a particular execution stack is NULL, which is used as a
 * marker to say "go to the previous stack in the list" when unwinding the
 * stack.
 */

typedef struct ExecStack {
    struct ExecStack *prevPtr;
    struct ExecStack *nextPtr;
    Tcl_Obj **markerPtr;
    Tcl_Obj **endPtr;
    Tcl_Obj **tosPtr;
    struct ExecStack *prevPtr;	/* Previous stack in list. */
    struct ExecStack *nextPtr;	/* Next stack in list. */
    Tcl_Obj **markerPtr;	/* The location of the NULL marker. */
    Tcl_Obj **endPtr;		/* Where the stack end is. */
    Tcl_Obj **tosPtr;		/* Where the stack top is. */
    Tcl_Obj *stackWords[TCLFLEXARRAY];
				/* The actual stack space, following this
				 * structure in memory. */
} ExecStack;

/*
 * Saved copies of the stack frame references from the interpreter. Have to be
 * restored into the interpreter to be used.
 */
typedef struct CorContext {
    CallFrame *framePtr;	/* See Interp.framePtr */
    CallFrame *varFramePtr;	/* See Interp.varFramePtr */
    CmdFrame *cmdFramePtr;	/* See Interp.cmdFramePtr */
    Tcl_HashTable *lineLABCPtr;	/* See Interp.lineLABCPtr */
} CorContext;

/*
 * The data structure defining the execution environment for ByteCode's.
 * There is one ExecEnv structure per Tcl interpreter. It holds the evaluation
 * stack that holds command operands and results. The stack grows towards
 * increasing addresses. The member stackPtr points to the stackItems of the
 * currently active execution stack.
 */

typedef struct CorContext {
    struct CallFrame *framePtr;
    struct CallFrame *varFramePtr;
    struct CmdFrame *cmdFramePtr;  /* See Interp.cmdFramePtr */
    Tcl_HashTable *lineLABCPtr;    /* See Interp.lineLABCPtr */
} CorContext;

typedef struct CoroutineData {
    struct Command *cmdPtr;	/* The command handle for the coroutine. */
    struct ExecEnv *eePtr;	/* The special execution environment (stacks,
				 * etc.) for the coroutine. */
    struct ExecEnv *callerEEPtr;/* The execution environment for the caller of
				 * the coroutine, which might be the
				 * interpreter global environment or another
				 * coroutine. */
    CorContext caller;
    CorContext running;
    Tcl_HashTable *lineLABCPtr;    /* See Interp.lineLABCPtr */
    void *stackLevel;
    int auxNumLevels;		/* While the coroutine is running the
    CorContext caller;		/* Caller's saved execution context. */
    CorContext running;		/* This coroutine's saved execution context. */
    Tcl_HashTable *lineLABCPtr;	/* See Interp.lineLABCPtr */
    void *stackLevel;		/* C stack frame reference. Used to try to
				 * ensure we don't overflow that stack. */
    Tcl_Size auxNumLevels;	/* While the coroutine is running the
				 * numLevels of the create/resume command is
				 * stored here; for suspended coroutines it
				 * holds the nesting numLevels at yield. */
    int nargs;                  /* Number of args required for resuming this
				 * coroutine; -2 means "0 or 1" (default), -1
				 * means "any" */
    Tcl_Size nargs;		/* Number of args required for resuming this
				 * coroutine; COROUTINE_ARGUMENTS_SINGLE_OPTIONAL
				 * means "0 or 1" (default),
				 * COROUTINE_ARGUMENTS_ARBITRARY means "any" */
    Tcl_Obj *yieldPtr;		/* The command to yield to.  Stored here in
				 * order to reset splice point in
				 * TclNRCoroutineActivateCallback if the
				 * coroutine is busy. */
} CoroutineData;

typedef struct ExecEnv {
    ExecStack *execStackPtr;	/* Points to the first item in the evaluation
				 * stack on the heap. */
    Tcl_Obj *constants[2];	/* Pointers to constant "0" and "1" objs. */
    struct Tcl_Interp *interp;
    struct Tcl_Interp *interp;	/* Owning interpreter. */
    struct NRE_callback *callbackPtr;
				/* Top callback in NRE's stack. */
    struct CoroutineData *corPtr;
				/* Current coroutine. */
    int rewind;
    int rewind;			/* Set when exception trapping is disabled
				 * because a context is being deleted (e.g.,
				 * the current coroutine has been deleted). */
} ExecEnv;

#define COR_IS_SUSPENDED(corPtr) \
    ((corPtr)->stackLevel == NULL)

/*
 * The definitions for the LiteralTable and LiteralEntry structures. Each
1516
1517
1518
1519
1520
1521
1522
1523

1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541

1542
1543

1544
1545

1546
1547

1548
1549
1550
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
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







-
+

















-
+

-
+

-
+

-
+










-
+


-
+
+







-
+








typedef struct LiteralEntry {
    struct LiteralEntry *nextPtr;
				/* Points to next entry in this hash bucket or
				 * NULL if end of chain. */
    Tcl_Obj *objPtr;		/* Points to Tcl object that holds the
				 * literal's bytes and length. */
    size_t refCount;		/* If in an interpreter's global literal
    Tcl_Size refCount;		/* If in an interpreter's global literal
				 * table, the number of ByteCode structures
				 * that share the literal object; the literal
				 * entry can be freed when refCount drops to
				 * 0. If in a local literal table, TCL_INDEX_NONE. */
    Namespace *nsPtr;		/* Namespace in which this literal is used. We
				 * try to avoid sharing literal non-FQ command
				 * names among different namespaces to reduce
				 * shimmering. */
} LiteralEntry;

typedef struct LiteralTable {
    LiteralEntry **buckets;	/* Pointer to bucket array. Each element
				 * points to first entry in bucket's hash
				 * chain, or NULL. */
    LiteralEntry *staticBuckets[TCL_SMALL_HASH_TABLE];
				/* Bucket array used for small tables to avoid
				 * mallocs and frees. */
    size_t numBuckets;		/* Total number of buckets allocated at
    TCL_HASH_TYPE numBuckets;	/* Total number of buckets allocated at
				 * **buckets. */
    size_t numEntries;		/* Total number of entries present in
    TCL_HASH_TYPE numEntries;	/* Total number of entries present in
				 * table. */
    size_t rebuildSize;		/* Enlarge table when numEntries gets to be
    TCL_HASH_TYPE rebuildSize;	/* Enlarge table when numEntries gets to be
				 * this large. */
    size_t mask;		/* Mask value used in hashing function. */
    TCL_HASH_TYPE mask;		/* Mask value used in hashing function. */
} LiteralTable;

/*
 * The following structure defines for each Tcl interpreter various
 * statistics-related information about the bytecode compiler and
 * interpreter's operation in that interpreter.
 */

#ifdef TCL_COMPILE_STATS
typedef struct ByteCodeStats {
    size_t numExecutions;		/* Number of ByteCodes executed. */
    size_t numExecutions;	/* Number of ByteCodes executed. */
    size_t numCompilations;	/* Number of ByteCodes created. */
    size_t numByteCodesFreed;	/* Number of ByteCodes destroyed. */
    size_t instructionCount[256];	/* Number of times each instruction was
    size_t instructionCount[256];
				/* Number of times each instruction was
				 * executed. */

    double totalSrcBytes;	/* Total source bytes ever compiled. */
    double totalByteCodeBytes;	/* Total bytes for all ByteCodes. */
    double currentSrcBytes;	/* Src bytes for all current ByteCodes. */
    double currentByteCodeBytes;/* Code bytes in all current ByteCodes. */

    size_t srcCount[32];		/* Source size distribution: # of srcs of
    size_t srcCount[32];	/* Source size distribution: # of srcs of
				 * size [2**(n-1)..2**n), n in [0..32). */
    size_t byteCodeCount[32];	/* ByteCode size distribution. */
    size_t lifetimeCount[32];	/* ByteCode lifetime distribution (ms). */

    double currentInstBytes;	/* Instruction bytes-current ByteCodes. */
    double currentLitBytes;	/* Current literal bytes. */
    double currentExceptBytes;	/* Current exception table bytes. */
1592
1593
1594
1595
1596
1597
1598
1599

1600
1601
1602
1603
1604
1605
1606
1750
1751
1752
1753
1754
1755
1756

1757
1758
1759
1760
1761
1762
1763
1764







-
+







 */

typedef struct {
    const char *name;		/* The name of the subcommand. */
    Tcl_ObjCmdProc *proc;	/* The implementation of the subcommand. */
    CompileProc *compileProc;	/* The compiler for the subcommand. */
    Tcl_ObjCmdProc *nreProc;	/* NRE implementation of this command. */
    void *clientData;	/* Any clientData to give the command. */
    void *clientData;		/* Any clientData to give the command. */
    int unsafe;			/* Whether this command is to be hidden by
				 * default in a safe interpreter. */
} EnsembleImplMap;

/*
 *----------------------------------------------------------------
 * Data structures related to commands.
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
1816
1817
1818
1819
1820
1821
1822

1823
1824
1825
1826
1827

1828
1829
1830
1831
1832
1833
1834
1835

1836
1837
1838
1839

1840
1841
1842
1843
1844
1845
1846
1847







-
+




-
+







-
+



-
+







				 * from its Tcl_Command handle. NULL means
				 * that the hash table entry has been removed
				 * already (this can happen if deleteProc
				 * causes the command to be deleted or
				 * recreated). */
    Namespace *nsPtr;		/* Points to the namespace containing this
				 * command. */
    size_t refCount;		/* 1 if in command hashtable plus 1 for each
    Tcl_Size refCount;		/* 1 if in command hashtable plus 1 for each
				 * reference from a CmdName Tcl object
				 * representing a command's name in a ByteCode
				 * instruction sequence. This structure can be
				 * freed when refCount becomes zero. */
    size_t cmdEpoch;		/* Incremented to invalidate any references
    Tcl_Size cmdEpoch;		/* Incremented to invalidate any references
				 * that point to this command when it is
				 * renamed, deleted, hidden, or exposed. */
    CompileProc *compileProc;	/* Procedure called to compile command. NULL
				 * if no compile proc exists for command. */
    Tcl_ObjCmdProc *objProc;	/* Object-based command procedure. */
    void *objClientData;	/* Arbitrary value passed to object proc. */
    Tcl_CmdProc *proc;		/* String-based command procedure. */
    void *clientData;	/* Arbitrary value passed to string proc. */
    void *clientData;		/* Arbitrary value passed to string proc. */
    Tcl_CmdDeleteProc *deleteProc;
				/* Procedure invoked when deleting command to,
				 * e.g., free all client data. */
    void *deleteData;	/* Arbitrary value passed to deleteProc. */
    void *deleteData;		/* Arbitrary value passed to deleteProc. */
    int flags;			/* Miscellaneous bits of information about
				 * command. See below for definitions. */
    ImportRef *importRefPtr;	/* List of each imported Command created in
				 * another namespace when this command is
				 * imported. These imported commands redirect
				 * invocations back to this command. The list
				 * is used to remove all those imported
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727







1728
1729
1730
1731
1732
1733
1734
1735
1872
1873
1874
1875
1876
1877
1878







1879
1880
1881
1882
1883
1884
1885

1886
1887
1888
1889
1890
1891
1892







-
-
-
-
-
-
-
+
+
+
+
+
+
+
-







 * TCL_TRACE_RENAME -		A rename trace is in progress. Further
 *				recursive renames will not be traced.
 * TCL_TRACE_DELETE -		A delete trace is in progress. Further
 *				recursive deletes will not be traced.
 * (these last two flags are defined in tcl.h)
 */

#define CMD_DYING		    0x01
#define CMD_TRACE_ACTIVE	    0x02
#define CMD_HAS_EXEC_TRACES	    0x04
#define CMD_COMPILES_EXPANDED	    0x08
#define CMD_REDEF_IN_PROGRESS	    0x10
#define CMD_VIA_RESOLVER	    0x20
#define CMD_DEAD                    0x40
#define CMD_DYING		0x01
#define CMD_TRACE_ACTIVE	0x02
#define CMD_HAS_EXEC_TRACES	0x04
#define CMD_COMPILES_EXPANDED	0x08
#define CMD_REDEF_IN_PROGRESS	0x10
#define CMD_VIA_RESOLVER	0x20
#define CMD_DEAD		0x40


/*
 *----------------------------------------------------------------
 * Data structures related to name resolution procedures.
 *----------------------------------------------------------------
 */

1821
1822
1823
1824
1825
1826
1827
1828

1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839

1840
1841

1842












1843
1844
1845
1846
1847
1848

1849
1850
1851
1852
1853

1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870






1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1978
1979
1980
1981
1982
1983
1984

1985

1986
1987
1988
1989
1990
1991
1992
1993
1994

1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016

2017
2018
2019
2020
2021

2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120


2121
2122
2123
2124
2125
2126
2127
2128
2129







-
+
-









-
+


+

+
+
+
+
+
+
+
+
+
+
+
+





-
+




-
+

















+
+
+
+
+
+
















-
+





+
+
+





-
+









-
+
-




















+
+
+











-
-
+
+







				/* Pointer to the exported Tcl stub table.  In
				 * ancient pre-8.1 versions of Tcl this was a
				 * pointer to the objResultPtr or a pointer to a
				 * buckets array in a hash table. Deployed stubs
				 * enabled extensions check for a NULL pointer value
				 * and for a TCL_STUBS_MAGIC value to verify they
				 * are not [load]ing into one of those pre-stubs
				 * interps.
				 * interps. */
				 */

    TclHandle handle;		/* Handle used to keep track of when this
				 * interp is deleted. */

    Namespace *globalNsPtr;	/* The interpreter's global namespace. */
    Tcl_HashTable *hiddenCmdTablePtr;
				/* Hash table used by tclBasic.c to keep track
				 * of hidden commands on a per-interp
				 * basis. */
    void *interpInfo;	/* Information used by tclInterp.c to keep
    void *interpInfo;		/* Information used by tclInterp.c to keep
				 * track of parent/child interps on a
				 * per-interp basis. */
#if TCL_MAJOR_VERSION > 8
    void (*optimizer)(void *envPtr);
				/* Reference to the bytecode optimizer, if one
				 * is set. */
#else
    union {
	void (*optimizer)(void *envPtr);
	Tcl_HashTable unused2;	/* No longer used (was mathFuncTable). The
				 * unused space in interp was repurposed for
				 * pluggable bytecode optimizers. The core
				 * contains one optimizer, which can be
				 * selectively overridden by extensions. */
    } extra;
#endif
    /*
     * Information related to procedures and variables. See tclProc.c and
     * tclVar.c for usage.
     */

    int numLevels;		/* Keeps track of how many nested calls to
    Tcl_Size numLevels;		/* Keeps track of how many nested calls to
				 * Tcl_Eval are in progress for this
				 * interpreter. It's used to delay deletion of
				 * the table until all Tcl_Eval invocations
				 * are completed. */
    int maxNestingDepth;	/* If numLevels exceeds this value then Tcl
    Tcl_Size maxNestingDepth;	/* If numLevels exceeds this value then Tcl
				 * assumes that infinite recursion has
				 * occurred and it generates an error. */
    CallFrame *framePtr;	/* Points to top-most in stack of all nested
				 * procedure invocations. */
    CallFrame *varFramePtr;	/* Points to the call frame whose variables
				 * are currently in use (same as framePtr
				 * unless an "uplevel" command is
				 * executing). */
    ActiveVarTrace *activeVarTracePtr;
				/* First in list of active traces for interp,
				 * or NULL if no active traces. */
    int returnCode;		/* [return -code] parameter. */
    CallFrame *rootFramePtr;	/* Global frame pointer for this
				 * interpreter. */
    Namespace *lookupNsPtr;	/* Namespace to use ONLY on the next
				 * TCL_EVAL_INVOKE call to Tcl_EvalObjv. */

#if TCL_MAJOR_VERSION < 9
    char *appendResultDontUse;
    int appendAvlDontUse;
    int appendUsedDontUse;
#endif

    /*
     * Information about packages. Used only in tclPkg.c.
     */

    Tcl_HashTable packageTable;	/* Describes all of the packages loaded in or
				 * available to this interpreter. Keys are
				 * package names, values are (Package *)
				 * pointers. */
    char *packageUnknown;	/* Command to invoke during "package require"
				 * commands for packages that aren't described
				 * in packageTable. Ckalloc'ed, may be
				 * NULL. */
    /*
     * Miscellaneous information:
     */

    size_t cmdCount;		/* Total number of times a command procedure
    Tcl_Size cmdCount;		/* Total number of times a command procedure
				 * has been called for this interpreter. */
    int evalFlags;		/* Flags to control next call to Tcl_Eval.
				 * Normally zero, but may be set before
				 * calling Tcl_Eval. See below for valid
				 * values. */
#if TCL_MAJOR_VERSION < 9
    int unused1;		/* No longer used (was termOffset) */
#endif
    LiteralTable literalTable;	/* Contains LiteralEntry's describing all Tcl
				 * objects holding literals of scripts
				 * compiled by the interpreter. Indexed by the
				 * string representations of literals. Used to
				 * avoid creating duplicate objects. */
    size_t compileEpoch;	/* Holds the current "compilation epoch" for
    Tcl_Size compileEpoch;	/* Holds the current "compilation epoch" for
				 * this interpreter. This is incremented to
				 * invalidate existing ByteCodes when, e.g., a
				 * command with a compile procedure is
				 * redefined. */
    Proc *compiledProcPtr;	/* If a procedure is being compiled, a pointer
				 * to its Proc structure; otherwise, this is
				 * NULL. Set by ObjInterpProc in tclProc.c and
				 * used by tclCompile.c to process local
				 * variables appropriately. */
    ResolverScheme *resolverPtr;
    ResolverScheme *resolverPtr;/* Linked list of name resolution schemes
				/* Linked list of name resolution schemes
				 * added to this interpreter. Schemes are
				 * added and removed by calling
				 * Tcl_AddInterpResolvers and
				 * Tcl_RemoveInterpResolver respectively. */
    Tcl_Obj *scriptFile;	/* NULL means there is no nested source
				 * command active; otherwise this points to
				 * pathPtr of the file being sourced. */
    int flags;			/* Various flag bits. See below. */
    long randSeed;		/* Seed used for rand() function. */
    Trace *tracePtr;		/* List of traces for this interpreter. */
    Tcl_HashTable *assocData;	/* Hash table for associating data with this
				 * interpreter. Cleaned up when this
				 * interpreter is deleted. */
    struct ExecEnv *execEnvPtr;	/* Execution environment for Tcl bytecode
				 * execution. Contains a pointer to the Tcl
				 * evaluation stack. */
    Tcl_Obj *emptyObjPtr;	/* Points to an object holding an empty
				 * string. Returned by Tcl_ObjSetVar2 when
				 * variable traces change a variable in a
				 * gross way. */
#if TCL_MAJOR_VERSION < 9
    char resultSpaceDontUse[TCL_DSTRING_STATIC_SIZE+1];
#endif
    Tcl_Obj *objResultPtr;	/* If the last command returned an object
				 * result, this points to it. Should not be
				 * accessed directly; see comment above. */
    Tcl_ThreadId threadId;	/* ID of thread that owns the interpreter. */

    ActiveCommandTrace *activeCmdTracePtr;
				/* First in list of active command traces for
				 * interp, or NULL if no active traces. */
    ActiveInterpTrace *activeInterpTracePtr;
				/* First in list of active traces for interp,
				 * or NULL if no active traces. */

    int tracesForbiddingInline;	/* Count of traces (in the list headed by
    Tcl_Size tracesForbiddingInline;
				/* Count of traces (in the list headed by
				 * tracePtr) that forbid inline bytecode
				 * compilation. */

    /*
     * Fields used to manage extensible return options (TIP 90).
     */

1965
1966
1967
1968
1969
1970
1971
1972

1973
1974
1975
1976
1977
1978
1979
2145
2146
2147
2148
2149
2150
2151

2152
2153
2154
2155
2156
2157
2158
2159







-
+







				 * set. */
	int granularityTicker;	/* Counter used to determine how often to
				 * check the limits. */
	int exceeded;		/* Which limits have been exceeded, described
				 * as flag values the same as the 'active'
				 * field. */

	size_t cmdCount;		/* Limit for how many commands to execute in
	Tcl_Size cmdCount;	/* Limit for how many commands to execute in
				 * the interpreter. */
	LimitHandler *cmdHandlers;
				/* Handlers to execute when the limit is
				 * reached. */
	int cmdGranularity;	/* Mod factor used to determine how often to
				 * evaluate the limit check. */

2001
2002
2003
2004
2005
2006
2007
2008

2009

2010

2011
2012
2013
2014
2015
2016
2017
2181
2182
2183
2184
2185
2186
2187

2188
2189
2190

2191
2192
2193
2194
2195
2196
2197
2198







-
+

+
-
+








    struct {
	Tcl_Obj *const *sourceObjs;
				/* What arguments were actually input into the
				 * *root* ensemble command? (Nested ensembles
				 * don't rewrite this.) NULL if we're not
				 * processing an ensemble. */
	size_t numRemovedObjs;	/* How many arguments have been stripped off
	Tcl_Size numRemovedObjs;/* How many arguments have been stripped off
				 * because of ensemble processing. */
	Tcl_Size numInsertedObjs;
	size_t numInsertedObjs;	/* How many of the current arguments were
				/* How many of the current arguments were
				 * inserted by an ensemble. */
    } ensembleRewrite;

    /*
     * TIP #219: Global info for the I/O system.
     */

2042
2043
2044
2045
2046
2047
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
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







-
+




















-
+
-







				 * values are "struct CmdFrame*". */
    Tcl_HashTable *lineBCPtr;	/* This table remembers for each ByteCode
				 * object the location information for its
				 * body. It is keyed by the address of the
				 * Proc structure for a procedure. The values
				 * are "struct ExtCmdLoc*". (See
				 * tclCompile.h) */
    Tcl_HashTable *lineLABCPtr;
    Tcl_HashTable *lineLABCPtr;	/* Tcl_Obj* (by exact pointer) -> CFWordBC* */
    Tcl_HashTable *lineLAPtr;	/* This table remembers for each argument of a
				 * command on the execution stack the index of
				 * the argument in the command, and the
				 * location data of the command. It is keyed
				 * by the address of the Tcl_Obj containing
				 * the argument. The values are "struct
				 * CFWord*" (See tclBasic.c). This allows
				 * commands like uplevel, eval, etc. to find
				 * location information for their arguments,
				 * if they are a proper literal argument to an
				 * invoking command. Alt view: An index to the
				 * CmdFrame stack keyed by command argument
				 * holders. */
    ContLineLoc *scriptCLLocPtr;/* This table points to the location data for
				 * invisible continuation lines in the script,
				 * if any. This pointer is set by the function
				 * TclEvalObjEx() in file "tclBasic.c", and
				 * used by function ...() in the same file.
				 * It does for the eval/direct path of script
				 * execution what CompileEnv.clLoc does for
				 * the bytecode compiler.
				 * the bytecode compiler. */
				 */
    /*
     * TIP #268. The currently active selection mode, i.e. the package require
     * preferences.
     */

    int packagePrefer;		/* Current package selection mode. */

2093
2094
2095
2096
2097
2098
2099
2100

2101
2102
2103
2104
2105
2106
2107
2273
2274
2275
2276
2277
2278
2279

2280
2281
2282
2283
2284
2285
2286
2287







-
+







     * Note that these are the same for all interps in the same thread. They
     * just have to be initialised for the thread's parent interp, children
     * inherit the value.
     *
     * They are used by the macros defined below.
     */

    AllocCache *allocCache;
    AllocCache *allocCache;	/* Allocator cache for stack frames. */
    void *pendingObjDataPtr;	/* Pointer to the Cache and PendingObjData
				 * structs for this interp's thread; see
				 * tclObj.c and tclThreadAlloc.c */
    int *asyncReadyPtr;		/* Pointer to the asyncReady indicator for
				 * this interp's thread; see tclAsync.c */
    /*
     * The pointer to the object system root ekeko. c.f. TIP #257.
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137



2138
2139
2140
2141
2142
2143

2144
2145
2146
2147
2148
2149
2150
2308
2309
2310
2311
2312
2313
2314



2315
2316
2317
2318
2319
2320
2321
2322

2323
2324
2325
2326
2327
2328
2329
2330







-
-
-
+
+
+





-
+







    Tcl_Obj *asyncCancelMsg;	/* Error message set by async cancel handler
				 * for the propagation of arbitrary Tcl
				 * errors. This information, if present
				 * (asyncCancelMsg not NULL), takes precedence
				 * over the default error messages returned by
				 * a script cancellation operation. */

	/*
	 * TIP #348 IMPLEMENTATION  -  Substituted error stack
	 */
    /*
     * TIP #348 IMPLEMENTATION  -  Substituted error stack
     */
    Tcl_Obj *errorStack;	/* [info errorstack] value (as a Tcl_Obj). */
    Tcl_Obj *upLiteral;		/* "UP" literal for [info errorstack] */
    Tcl_Obj *callLiteral;	/* "CALL" literal for [info errorstack] */
    Tcl_Obj *innerLiteral;	/* "INNER" literal for [info errorstack] */
    Tcl_Obj *innerContext;	/* cached list for fast reallocation */
    int resetErrorStack;        /* controls cleaning up of ::errorStack */
    int resetErrorStack;	/* controls cleaning up of ::errorStack */

#ifdef TCL_COMPILE_STATS
    /*
     * Statistical information about the bytecode compiler and interpreter's
     * operation. This should be the last field of Interp.
     */

2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173




2174
2175
2176
2177
2178
2179
2180
2343
2344
2345
2346
2347
2348
2349




2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360







-
-
-
-
+
+
+
+







/*
 * Macros for script cancellation support (TIP #285).
 */

#define TclCanceled(iPtr) \
    (((iPtr)->flags & CANCELED) || ((iPtr)->flags & TCL_CANCEL_UNWIND))

#define TclSetCancelFlags(iPtr, cancelFlags)   \
    (iPtr)->flags |= CANCELED;                 \
    if ((cancelFlags) & TCL_CANCEL_UNWIND) {   \
        (iPtr)->flags |= TCL_CANCEL_UNWIND;    \
#define TclSetCancelFlags(iPtr, cancelFlags) \
    (iPtr)->flags |= CANCELED;			\
    if ((cancelFlags) & TCL_CANCEL_UNWIND) {	\
	(iPtr)->flags |= TCL_CANCEL_UNWIND;	\
    }

#define TclUnsetCancelFlags(iPtr) \
    (iPtr)->flags &= (~(CANCELED | TCL_CANCEL_UNWIND))

/*
 * Macros for splicing into and out of doubly linked lists. They assume
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2434
2435
2436
2437
2438
2439
2440




2441
2442
2443
2444
2445
2446
2447







-
-
-
-







 *			Tcl_Canceled and checking if TCL_ERROR is returned.
 *			This is a one-shot flag that is reset immediately upon
 *			being detected; however, if the TCL_CANCEL_UNWIND flag
 *			is set Tcl_Canceled will continue to report that the
 *			script in progress has been canceled thereby allowing
 *			the evaluation stack for the interp to be fully
 *			unwound.
 *
 * WARNING: For the sake of some extensions that have made use of former
 * internal values, do not re-use the flag values 2 (formerly ERR_IN_PROGRESS)
 * or 8 (formerly ERROR_CODE_SET).
 */

#define DELETED				     1
#define ERR_ALREADY_LOGGED		     4
#define INTERP_DEBUG_FRAME		  0x10
#define DONT_COMPILE_CMDS_INLINE	  0x20
#define RAND_SEED_INITIALIZED		  0x40
2298
2299
2300
2301
2302
2303
2304
2305

2306
2307
2308
2309




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
2474
2475
2476
2477
2478
2479
2480

2481
2482



2483
2484
2485
2486
2487
2488


2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506

2507
2508
2509
2510
2511
2512
2513
2514
2515

2516
2517
2518
2519
2520
2521
2522
2523







-
+

-
-
-
+
+
+
+


-
-
+
+






+
+
+
+
+
+
+
+
+
+
-
+
+






+
-
+







#if defined(__APPLE__)
#define TCL_ALLOCALIGN	16
#else
#define TCL_ALLOCALIGN	(2*sizeof(void *))
#endif

/*
 * This macro is used to determine the offset needed to safely allocate any
 * TCL_ALIGN is used to determine the offset needed to safely allocate any
 * data structure in memory. Given a starting offset or size, it "rounds up"
 * or "aligns" the offset to the next 8-byte boundary so that any data
 * structure can be placed at the resulting offset without fear of an
 * alignment error.
 * or "aligns" the offset to the next aligned (typically 8-byte) boundary so
 * that any data structure can be placed at the resulting offset without fear
 * of an alignment error. Note this is clamped to a minimum of 8 for API
 * compatibility.
 *
 * WARNING!! DO NOT USE THIS MACRO TO ALIGN POINTERS: it will produce the
 * wrong result on platforms that allocate addresses that are divisible by 4
 * or 2. Only use it for offsets or sizes.
 * wrong result on platforms that allocate addresses that are divisible by a
 * non-trivial factor of this alignment. Only use it for offsets or sizes.
 *
 * This macro is only used by tclCompile.c in the core (Bug 926445). It
 * however not be made file static, as extensions that touch bytecodes
 * (notably tbcload) require it.
 */

struct TclMaxAlignment {
    char unalign[8];
    union {
	long long maxAlignLongLong;
	double maxAlignDouble;
	void *maxAlignPointer;
    } aligned;
};
#define TCL_ALIGN_BYTES \
	offsetof(struct TclMaxAlignment, aligned)
#define TCL_ALIGN(x) (((int)(x) + 7) & ~7)
#define TCL_ALIGN(x) \
	(((x) + (TCL_ALIGN_BYTES - 1)) & ~(TCL_ALIGN_BYTES - 1))

/*
 * A common panic alert when memory allocation fails.
 */

#define TclOOM(ptr, size) \
    ((size) && ((ptr) || (Tcl_Panic(					\
	((size) && ((ptr)||(Tcl_Panic("unable to alloc %" TCL_Z_MODIFIER "u bytes", (size_t)(size)),1)))
	"unable to alloc %" TCL_Z_MODIFIER "u bytes", (size_t)(size)), 1)))

/*
 * The following enum values are used to specify the runtime platform setting
 * of the tclPlatform variable.
 */

typedef enum {
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







2399













2400
2401










2402



2403
2404
2405












2406












2407
2408




2409

2410
2411




2412

2413
2414
2415
2416































2417


















2418
2419
2420
2421




2422
2423
2424




2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441

2442
2443
2444
2445
2446













2447
2448
2449
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
2489
2490
2491
2492
2493
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







+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-

+

+
-
-
-
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+

+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+

+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+

+
-
-
+
+
+
+

+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+

-
-
+
+
+
+

















+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
-
+
+
+


-
+


-
-
+
+



-
+


-
-
+
+

+
-
-
-
-
+
+
+
+










-
+
-
-
-
+
+







 */

#define	TCL_INVOKE_HIDDEN	(1<<0)
#define TCL_INVOKE_NO_UNKNOWN	(1<<1)
#define TCL_INVOKE_NO_TRACEBACK	(1<<2)

/*
 * ListStore --
 *
 * The structure used as the internal representation of Tcl list objects. This
 * struct is grown (reallocated and copied) as necessary to hold all the
 * list's element pointers. The struct might contain more slots than currently
 * used to hold all element pointers. This is done to make append operations
 * faster.
 */

typedef struct List {
    size_t refCount;
    int maxElemCount;		/* Total number of element array slots. */
    int elemCount;		/* Current number of list elements. */
    int canonicalFlag;		/* Set if the string representation was
				 * derived from the list representation. May
 * A Tcl list's internal representation is defined through three structures.
 *
 * A ListStore struct is a structure that includes a variable size array that
 * serves as storage for a Tcl list. A contiguous sequence of slots in the
 * array, the "in-use" area, holds valid pointers to Tcl_Obj values that
 * belong to one or more Tcl lists. The unused slots before and after these
 * are free slots that may be used to prepend and append without having to
 * reallocate the struct. The ListStore may be shared amongst multiple lists
 * and reference counted.
 *
 * A ListSpan struct defines a sequence of slots within a ListStore. This sequence
 * always lies within the "in-use" area of the ListStore. Like ListStore, the
 * structure may be shared among multiple lists and is reference counted.
 *
 * A ListRep struct holds the internal representation of a Tcl list as stored
 * in a Tcl_Obj. It is composed of a ListStore and a ListSpan that together
 * define the content of the list. The ListSpan specifies the range of slots
 * within the ListStore that hold elements for this list. The ListSpan is
 * optional in which case the list includes all the "in-use" slots of the
 * ListStore.
 *
 */
typedef struct ListStore {
    Tcl_Size firstUsed;		/* Index of first slot in use within slots[] */
    Tcl_Size numUsed;		/* Number of slots in use (starting firstUsed) */
    Tcl_Size numAllocated;	/* Total number of slots[] array slots. */
    size_t refCount;		/* Number of references to this instance. */
    int flags;			/* LISTSTORE_* flags */
    Tcl_Obj *slots[TCLFLEXARRAY];
				/* Variable size array. Grown as needed */
} ListStore;

#define LISTSTORE_CANONICAL 0x1 /* All Tcl_Obj's referencing this
				 * store have their string representation
				 * derived from the list representation */
				 * be ignored if there is no string rep at
				 * all.*/
    Tcl_Obj *elements;		/* First list element; the struct is grown to
				 * accommodate all elements. */
} List;

/* Max number of elements that can be contained in a list */
#define LIST_MAX \
    ((Tcl_Size)(((size_t)TCL_SIZE_MAX - offsetof(ListStore, slots))	\
	(1 + (int)(((size_t)UINT_MAX - sizeof(List))/sizeof(Tcl_Obj *)))
#define LIST_SIZE(numElems) \
	(sizeof(List) + (((numElems) - 1) * sizeof(Tcl_Obj *)))
	    / sizeof(Tcl_Obj *)))
/* Memory size needed for a ListStore to hold numSlots_ elements */
#define LIST_SIZE(numSlots_) \
    ((Tcl_Size)(offsetof(ListStore, slots)				\
	    + ((numSlots_) * sizeof(Tcl_Obj *))))

/*
 * ListSpan --
 * See comments above for ListStore
 */
typedef struct ListSpan {
    Tcl_Size spanStart;		/* Starting index of the span. */
    Tcl_Size spanLength;	/* Number of elements in the span. */
    size_t refCount;		/* Count of references to this span record. */
} ListSpan;
#ifndef LIST_SPAN_THRESHOLD	/* May be set on build line */
#define LIST_SPAN_THRESHOLD 101
#endif
 * Macro used to get the elements of a list object.

/*
 * ListRep --
 * See comments above for ListStore
 */
typedef struct ListRep {
    ListStore *storePtr;	/* element array shared amongst different
				 * lists */
    ListSpan *spanPtr;		/* If not NULL, the span holds the range of
				 * slots within *storePtr that contain this
				 * list elements. */
} ListRep;

/*
 * Macros used to get access list internal representations.
 *
 * Naming conventions:
 * ListRep* - expect a pointer to a valid ListRep
 * ListObj* - expect a pointer to a Tcl_Obj whose internal type is known to
 *            be a list (tclListType). Will crash otherwise.
 * TclListObj* - expect a pointer to a Tcl_Obj whose internal type may or may not
 *            be tclListType. These will convert as needed and return error if
 *            conversion not possible.
 */

/* Returns the starting slot for this listRep in the contained ListStore */
#define ListRepPtr(listPtr) \
    ((List *) (listPtr)->internalRep.twoPtrValue.ptr1)
#define ListRepStart(listRepPtr_) \
    ((listRepPtr_)->spanPtr						\
	? (listRepPtr_)->spanPtr->spanStart				\
	: (listRepPtr_)->storePtr->firstUsed)

/* Returns the number of elements in this listRep */
#define ListRepLength(listRepPtr_) \
    ((listRepPtr_)->spanPtr						\
	? (listRepPtr_)->spanPtr->spanLength				\
	: (listRepPtr_)->storePtr->numUsed)

/* Returns a pointer to the first slot containing this ListRep elements */
#define ListRepElementsBase(listRepPtr_) \
    (&(listRepPtr_)->storePtr->slots[ListRepStart(listRepPtr_)])
#define ListObjGetElements(listPtr, objc, objv) \
    ((objv) = &(ListRepPtr(listPtr)->elements), \
     (objc) = ListRepPtr(listPtr)->elemCount)

/* Stores the number of elements and base address of the element array */
#define ListRepElements(listRepPtr_, objc_, objv_) \
    (((objv_) = ListRepElementsBase(listRepPtr_)),			\
     ((objc_) = ListRepLength(listRepPtr_)))

/* Returns 1/0 whether the ListRep's ListStore is shared. */
#define ListRepIsShared(listRepPtr_) ((listRepPtr_)->storePtr->refCount > 1)

/* Returns a pointer to the ListStore component */
#define ListObjStorePtr(listObj_) \
    ((ListStore *)((listObj_)->internalRep.twoPtrValue.ptr1))

/* Returns a pointer to the ListSpan component */
#define ListObjSpanPtr(listObj_) \
    ((ListSpan *)((listObj_)->internalRep.twoPtrValue.ptr2))

/* Returns the ListRep internal representaton in a Tcl_Obj */
#define ListObjGetRep(listObj_, listRepPtr_) \
    do {								\
	(listRepPtr_)->storePtr = ListObjStorePtr(listObj_);		\
	(listRepPtr_)->spanPtr = ListObjSpanPtr(listObj_);		\
    } while (0)

/* Returns the length of the list */
#define ListObjLength(listPtr, len) \
    ((len) = ListRepPtr(listPtr)->elemCount)
#define ListObjLength(listObj_, len_) \
    ((len_) = ListObjSpanPtr(listObj_)					\
	? ListObjSpanPtr(listObj_)->spanLength				\
	: ListObjStorePtr(listObj_)->numUsed)

/* Returns the starting slot index of this list's elements in the ListStore */
#define ListObjIsCanonical(listPtr) \
    (((listPtr)->bytes == NULL) || ListRepPtr(listPtr)->canonicalFlag)
#define ListObjStart(listObj_) \
    (ListObjSpanPtr(listObj_)						\
	? ListObjSpanPtr(listObj_)->spanStart				\
	: ListObjStorePtr(listObj_)->firstUsed)

/* Stores the element count and base address of this list's elements */
#define TclListObjGetElements(interp, listPtr, objcPtr, objvPtr) \
    (((listPtr)->typePtr == &tclListType) \
	    ? ((ListObjGetElements((listPtr), *(objcPtr), *(objvPtr))), TCL_OK)\
	    : Tcl_ListObjGetElements((interp), (listPtr), (objcPtr), (objvPtr)))
#define ListObjGetElements(listObj_, objc_, objv_) \
    (((objv_) = &ListObjStorePtr(listObj_)->slots[ListObjStart(listObj_)]), \
     (ListObjLength(listObj_, (objc_))))

/*
 * Returns 1/0 whether the internal representation (not the Tcl_Obj itself)
 * is shared.  Note by intent this only checks for sharing of ListStore,
 * not spans.
 */
#define ListObjRepIsShared(listObj_) \
    (ListObjStorePtr(listObj_)->refCount > 1)

/*
 * Certain commands like concat are optimized if an existing string
 * representation of a list object is known to be in canonical format (i.e.
 * generated from the list representation). There are three conditions when
 * this will be the case:
 * (1) No string representation exists which means it will obviously have
 * to be generated from the list representation when needed
 * (2) The ListStore flags is marked canonical. This is done at the time
 * the string representation is generated from the list under certain
 * conditions (see comments in UpdateStringOfList).
 * (3) The list representation does not have a span component. This is
 * because list Tcl_Obj's with spans are always created from existing lists
 * and never from strings (see SetListFromAny) and thus their string
 * representation will always be canonical.
 */
#define ListObjIsCanonical(listObj_) \
    (((listObj_)->bytes == NULL)					\
	|| (ListObjStorePtr(listObj_)->flags & LISTSTORE_CANONICAL)	\
	|| ListObjSpanPtr(listObj_) != NULL)

/*
 * Converts the Tcl_Obj to a list if it isn't one and stores the element
 * count and base address of this list's elements in objcPtr_ and objvPtr_.
 * Return TCL_OK on success or TCL_ERROR if the Tcl_Obj cannot be
 * converted to a list.
 */
#define TclListObjGetElements(interp_, listObj_, objcPtr_, objvPtr_) \
    ((TclHasInternalRep((listObj_), &tclListType))			\
	? ((ListObjGetElements((listObj_), *(objcPtr_), *(objvPtr_))),	\
	    TCL_OK)							\
	: Tcl_ListObjGetElements(					\
	    (interp_), (listObj_), (objcPtr_), (objvPtr_)))

/*
 * Converts the Tcl_Obj to a list if it isn't one and stores the element
 * count in lenPtr_.  Returns TCL_OK on success or TCL_ERROR if the
 * Tcl_Obj cannot be converted to a list.
 */
#define TclListObjLength(interp, listPtr, lenPtr) \
    (((listPtr)->typePtr == &tclListType) \
	    ? ((ListObjLength((listPtr), *(lenPtr))), TCL_OK)\
	    : Tcl_ListObjLength((interp), (listPtr), (lenPtr)))
#define TclListObjLength(interp_, listObj_, lenPtr_) \
    ((TclHasInternalRep((listObj_), &tclListType))			\
	? ((ListObjLength((listObj_), *(lenPtr_))), TCL_OK)		\
	: Tcl_ListObjLength((interp_), (listObj_), (lenPtr_)))

#define TclListObjIsCanonical(listPtr) \
    (((listPtr)->typePtr == &tclListType) ? ListObjIsCanonical((listPtr)) : 0)
#define TclListObjIsCanonical(listObj_) \
    ((TclHasInternalRep((listObj_), &tclListType))			\
	? ListObjIsCanonical((listObj_))				\
	: 0)

/*
 * Modes for collecting (or not) in the implementations of TclNRForeachCmd,
 * TclNRLmapCmd and their compilations.
 */

#define TCL_EACH_KEEP_NONE  0	/* Discard iteration result like [foreach] */
#define TCL_EACH_COLLECT    1	/* Collect iteration result like [lmap] */

/*
 * Macros providing a faster path to booleans and integers:
 * Tcl_GetBooleanFromObj, Tcl_GetLongFromObj, Tcl_GetIntFromObj
 * and Tcl_GetIntForIndex.
 *
 * WARNING: these macros eval their args more than once.
 */

#if TCL_MAJOR_VERSION > 8
#define TclGetBooleanFromObj(interp, objPtr, boolPtr) \
    (((objPtr)->typePtr == &tclIntType \
	    || (objPtr)->typePtr == &tclBooleanType) \
	? (*(boolPtr) = ((objPtr)->internalRep.wideValue!=0), TCL_OK)	\
	: Tcl_GetBooleanFromObj((interp), (objPtr), (boolPtr)))
#define TclGetBooleanFromObj(interp, objPtr, intPtr) \
    ((TclHasInternalRep((objPtr), &tclIntType)				\
	    || TclHasInternalRep((objPtr), &tclBooleanType))		\
	? (*(intPtr) = ((objPtr)->internalRep.wideValue!=0), TCL_OK)	\
	: Tcl_GetBooleanFromObj((interp), (objPtr), (intPtr)))
#else
#define TclGetBooleanFromObj(interp, objPtr, intPtr) \
    ((TclHasInternalRep((objPtr), &tclIntType))				\
	? (*(intPtr) = ((objPtr)->internalRep.wideValue!=0), TCL_OK)	\
	: (TclHasInternalRep((objPtr), &tclBooleanType))		\
	? (*(intPtr) = ((objPtr)->internalRep.longValue!=0), TCL_OK)	\
	: Tcl_GetBooleanFromObj((interp), (objPtr), (intPtr)))
#endif

#ifdef TCL_WIDE_INT_IS_LONG
#define TclGetLongFromObj(interp, objPtr, longPtr) \
    (((objPtr)->typePtr == &tclIntType)	\
	    ? ((*(longPtr) = (objPtr)->internalRep.wideValue), TCL_OK) \
	    : Tcl_GetLongFromObj((interp), (objPtr), (longPtr)))
    ((TclHasInternalRep((objPtr), &tclIntType))				\
	? ((*(longPtr) = (objPtr)->internalRep.wideValue), TCL_OK)	\
	: Tcl_GetLongFromObj((interp), (objPtr), (longPtr)))
#else
#define TclGetLongFromObj(interp, objPtr, longPtr) \
    (((objPtr)->typePtr == &tclIntType \
    ((TclHasInternalRep((objPtr), &tclIntType)				\
	    && (objPtr)->internalRep.wideValue >= (Tcl_WideInt)(LONG_MIN) \
	    && (objPtr)->internalRep.wideValue <= (Tcl_WideInt)(LONG_MAX)) \
	    ? ((*(longPtr) = (long)(objPtr)->internalRep.wideValue), TCL_OK) \
	    : Tcl_GetLongFromObj((interp), (objPtr), (longPtr)))
	? ((*(longPtr) = (long)(objPtr)->internalRep.wideValue), TCL_OK) \
	: Tcl_GetLongFromObj((interp), (objPtr), (longPtr)))
#endif

#define TclGetIntFromObj(interp, objPtr, intPtr) \
    (((objPtr)->typePtr == &tclIntType \
    ((TclHasInternalRep((objPtr), &tclIntType)				\
	    && (objPtr)->internalRep.wideValue >= (Tcl_WideInt)(INT_MIN) \
	    && (objPtr)->internalRep.wideValue <= (Tcl_WideInt)(INT_MAX)) \
	    ? ((*(intPtr) = (int)(objPtr)->internalRep.wideValue), TCL_OK) \
	    : Tcl_GetIntFromObj((interp), (objPtr), (intPtr)))
	? ((*(intPtr) = (int)(objPtr)->internalRep.wideValue), TCL_OK)	\
	: Tcl_GetIntFromObj((interp), (objPtr), (intPtr)))
#define TclGetIntForIndexM(interp, objPtr, endValue, idxPtr) \
    (((TclHasInternalRep((objPtr), &tclIntType))			\
    ((((objPtr)->typePtr == &tclIntType) && ((objPtr)->internalRep.wideValue >= 0) \
	    && ((Tcl_WideUInt)(objPtr)->internalRep.wideValue <= (size_t)(endValue) + 1)) \
	    ? ((*(idxPtr) = (size_t)(objPtr)->internalRep.wideValue), TCL_OK) \
	    : Tcl_GetIntForIndex((interp), (objPtr), (endValue), (idxPtr)))
	    && ((objPtr)->internalRep.wideValue >= 0)			\
	    && ((objPtr)->internalRep.wideValue <= endValue))		\
	? ((*(idxPtr) = (objPtr)->internalRep.wideValue), TCL_OK)	\
	: Tcl_GetIntForIndex((interp), (objPtr), (endValue), (idxPtr)))

/*
 * Macro used to save a function call for common uses of
 * Tcl_GetWideIntFromObj(). The ANSI C "prototype" is:
 *
 * MODULE_SCOPE int TclGetWideIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
 *			Tcl_WideInt *wideIntPtr);
 */

#define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \
    (((objPtr)->typePtr == &tclIntType)					\
    ((TclHasInternalRep((objPtr), &tclIntType))				\
	? (*(wideIntPtr) =						\
		((objPtr)->internalRep.wideValue), TCL_OK) :		\
	Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr)))
	? (*(wideIntPtr) = ((objPtr)->internalRep.wideValue), TCL_OK)	\
	: Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr)))

/*
 * Flag values for TclTraceDictPath().
 *
 * DICT_PATH_READ indicates that all entries on the path must exist but no
 * updates will be needed.
 *
2524
2525
2526
2527
2528
2529
2530
2531


2532
2533
2534
2535
2536
2537
2538
2864
2865
2866
2867
2868
2869
2870

2871
2872
2873
2874
2875
2876
2877
2878
2879







-
+
+







 * more efficiency in 'path' manipulation and usage, and cleaner filesystem
 * code internally.
 */

#define TCL_FILESYSTEM_VERSION_2	((Tcl_FSVersion) 0x2)
typedef void *(TclFSGetCwdProc2)(void *clientData);
typedef int (Tcl_FSLoadFileProc2) (Tcl_Interp *interp, Tcl_Obj *pathPtr,
	Tcl_LoadHandle *handlePtr, Tcl_FSUnloadFileProc **unloadProcPtr, int flags);
	Tcl_LoadHandle *handlePtr, Tcl_FSUnloadFileProc **unloadProcPtr,
	int flags);

/*
 * The following types are used for getting and storing platform-specific file
 * attributes in tclFCmd.c and the various platform-versions of that file.
 * This is done to have as much common code as possible in the file attributes
 * code. For more information about the callbacks, see TclFileAttrsCmd in
 * tclFCmd.c.
2551
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
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
3134
3135
3136
3137
3138
3139
3140



3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152







-
-
-
-
-
-
-
-
-
-


















-
-
-
-
-
-
-
-
-






-
+
+

+
+
+
+
+
+
+
+










-
+

-
+




-
+














-
+


-
+



-
+

-
+


-
+








+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
+
+
+
+


+
+
+
+
+
+
+
















-
-
-
+
+
+

+







/*
 * Opaque handle used in pipeline routines to encapsulate platform-dependent
 * state.
 */

typedef struct TclFile_ *TclFile;

/*
 * The "globParameters" argument of the function TclGlob is an or'ed
 * combination of the following values:
 */

#define TCL_GLOBMODE_NO_COMPLAIN	1
#define TCL_GLOBMODE_JOIN		2
#define TCL_GLOBMODE_DIR		4
#define TCL_GLOBMODE_TAILS		8

typedef enum Tcl_PathPart {
    TCL_PATH_DIRNAME,
    TCL_PATH_TAIL,
    TCL_PATH_EXTENSION,
    TCL_PATH_ROOT
} Tcl_PathPart;

/*
 *----------------------------------------------------------------
 * Data structures related to obsolete filesystem hooks
 *----------------------------------------------------------------
 */

typedef int (TclStatProc_)(const char *path, struct stat *buf);
typedef int (TclAccessProc_)(const char *path, int mode);
typedef Tcl_Channel (TclOpenFileChannelProc_)(Tcl_Interp *interp,
	const char *fileName, const char *modeString, int permissions);

/*
 *----------------------------------------------------------------
 * Data structures related to procedures
 *----------------------------------------------------------------
 */

typedef Tcl_CmdProc *TclCmdProcType;
typedef Tcl_ObjCmdProc *TclObjCmdProcType;

/*
 *----------------------------------------------------------------
 * Data structures for process-global values.
 *----------------------------------------------------------------
 */

typedef void (TclInitProcessGlobalValueProc)(char **valuePtr, size_t *lengthPtr,
typedef void (TclInitProcessGlobalValueProc)(char **valuePtr,
	TCL_HASH_TYPE *lengthPtr,
	Tcl_Encoding *encodingPtr);

#ifdef _WIN32
/* On Windows, all Unicode (except surrogates) are valid. */
#   define TCLFSENCODING tclUtf8Encoding
#else
/* On Non-Windows, use the system encoding for validation checks. */
#   define TCLFSENCODING NULL
#endif

/*
 * A ProcessGlobalValue struct exists for each internal value in Tcl that is
 * to be shared among several threads. Each thread sees a (Tcl_Obj) copy of
 * the value, and the gobal value is kept as a counted string, with epoch and
 * mutex control. Each ProcessGlobalValue struct should be a static variable in
 * some file.
 */

typedef struct ProcessGlobalValue {
    size_t epoch;		/* Epoch counter to detect changes in the
    Tcl_Size epoch;		/* Epoch counter to detect changes in the
				 * global value. */
    size_t numBytes;		/* Length of the global string. */
    TCL_HASH_TYPE numBytes;	/* Length of the global string. */
    char *value;		/* The global string value. */
    Tcl_Encoding encoding;	/* system encoding when global string was
				 * initialized. */
    TclInitProcessGlobalValueProc *proc;
    				/* A procedure to initialize the global string
				/* A procedure to initialize the global string
				 * copy when a "get" request comes in before
				 * any "set" request has been received. */
    Tcl_Mutex mutex;		/* Enforce orderly access from multiple
				 * threads. */
    Tcl_ThreadDataKey key;	/* Key for per-thread data holding the
				 * (Tcl_Obj) copy for each thread. */
} ProcessGlobalValue;

/*
 *----------------------------------------------------------------------
 * Flags for TclParseNumber
 *----------------------------------------------------------------------
 */

#define TCL_PARSE_DECIMAL_ONLY		1
#define TCL_PARSE_DECIMAL_ONLY	1
				/* Leading zero doesn't denote octal or
				 * hex. */
#define TCL_PARSE_OCTAL_ONLY		2
#define TCL_PARSE_OCTAL_ONLY	2
				/* Parse octal even without prefix. */
#define TCL_PARSE_HEXADECIMAL_ONLY	4
				/* Parse hexadecimal even without prefix. */
#define TCL_PARSE_INTEGER_ONLY		8
#define TCL_PARSE_INTEGER_ONLY	8
				/* Disable floating point parsing. */
#define TCL_PARSE_SCAN_PREFIXES		16
#define TCL_PARSE_SCAN_PREFIXES	16
				/* Use [scan] rules dealing with 0?
				 * prefixes. */
#define TCL_PARSE_NO_WHITESPACE		32
#define TCL_PARSE_NO_WHITESPACE	32
				/* Reject leading/trailing whitespace. */
#define TCL_PARSE_BINARY_ONLY	64
				/* Parse binary even without prefix. */
#define TCL_PARSE_NO_UNDERSCORE	128
				/* Reject underscore digit separator */

/*
 *----------------------------------------------------------------------
 * Internal convenience macros for manipulating encoding flags. See
 * TCL_ENCODING_PROFILE_* in tcl.h
 *----------------------------------------------------------------------
 */
 * Type values TclGetNumberFromObj

#define ENCODING_PROFILE_MASK     0xFF000000
#define ENCODING_PROFILE_GET(flags_) \
    ((flags_) & ENCODING_PROFILE_MASK)
#define ENCODING_PROFILE_SET(flags_, profile_) \
    do {								\
	(flags_) &= ~ENCODING_PROFILE_MASK;				\
	(flags_) |= ((profile_) & ENCODING_PROFILE_MASK);		\
    } while (0)

/*
 *----------------------------------------------------------------------
 * Common functions for calculating overallocation. Trivial but allows for
 * experimenting with growth factors without having to change code in
 * multiple places. See TclAttemptAllocElemsEx and similar for usage
 * examples. Best to use those functions. Direct use of TclUpsizeAlloc /
 * TclResizeAlloc is needed in special cases such as when total size of
 * memory block is limited to less than TCL_SIZE_MAX.
 *----------------------------------------------------------------------
 */

static inline Tcl_Size
TclUpsizeAlloc(
    TCL_UNUSED(Tcl_Size),	/* oldSize. For future experiments with
				 * some growth algorithms that use this
				 * information. */
    Tcl_Size needed,
    Tcl_Size limit)
{
    /* assert (oldCapacity < needed <= limit) */
    if (needed < (limit - needed/2)) {
	return needed + needed / 2;
    } else {
	return limit;
    }
}
#define TCL_NUMBER_INT		2
#define TCL_NUMBER_BIG		3
#define TCL_NUMBER_DOUBLE	4
#define TCL_NUMBER_NAN		5

static inline Tcl_Size
TclUpsizeRetry(
    Tcl_Size needed,
    Tcl_Size lastAttempt)
{
    /* assert(needed < lastAttempt); */
    if (needed < lastAttempt - 1) {
	/* (needed+lastAttempt)/2 but that formula may overflow Tcl_Size */
	return needed + (lastAttempt - needed) / 2;
    } else {
	return needed;
    }
}

MODULE_SCOPE void *	TclAllocElemsEx(Tcl_Size elemCount, Tcl_Size elemSize,
			    Tcl_Size leadSize, Tcl_Size *capacityPtr);
MODULE_SCOPE void *	TclReallocElemsEx(void *oldPtr, Tcl_Size elemCount,
			    Tcl_Size elemSize, Tcl_Size leadSize,
			    Tcl_Size *capacityPtr);
MODULE_SCOPE void *	TclAttemptReallocElemsEx(void *oldPtr,
			    Tcl_Size elemCount, Tcl_Size elemSize,
			    Tcl_Size leadSize, Tcl_Size *capacityPtr);

/* Alloc elemCount elements of size elemSize with leadSize header
 * returning actual capacity (in elements) in *capacityPtr. */
static inline void *
TclAttemptAllocElemsEx(
    Tcl_Size elemCount,
    Tcl_Size elemSize,
    Tcl_Size leadSize,
    Tcl_Size *capacityPtr)
{
    return TclAttemptReallocElemsEx(
	    NULL, elemCount, elemSize, leadSize, capacityPtr);
}

/* Alloc numByte bytes, returning actual capacity in *capacityPtr. */
static inline void *
TclAllocEx(
    Tcl_Size numBytes,
    Tcl_Size *capacityPtr)
{
    return TclAllocElemsEx(numBytes, 1, 0, capacityPtr);
}

/* Alloc numByte bytes, returning actual capacity in *capacityPtr. */
static inline void *
TclAttemptAllocEx(
    Tcl_Size numBytes,
    Tcl_Size *capacityPtr)
{
    return TclAttemptAllocElemsEx(numBytes, 1, 0, capacityPtr);
}

/* Realloc numByte bytes, returning actual capacity in *capacityPtr. */
static inline void *
TclReallocEx(
    void *oldPtr,
    Tcl_Size numBytes,
    Tcl_Size *capacityPtr)
{
    return TclReallocElemsEx(oldPtr, numBytes, 1, 0, capacityPtr);
}

/* Realloc numByte bytes, returning actual capacity in *capacityPtr. */
static inline void *
TclAttemptReallocEx(
    void *oldPtr,
    Tcl_Size numBytes,
    Tcl_Size *capacityPtr)
{
    return TclAttemptReallocElemsEx(oldPtr, numBytes, 1, 0, capacityPtr);
}

/*
 *----------------------------------------------------------------
 * Variables shared among Tcl modules but not used by the outside world.
 *----------------------------------------------------------------
 */

MODULE_SCOPE char *tclNativeExecutableName;
MODULE_SCOPE int tclFindExecutableSearchDone;
MODULE_SCOPE char *tclMemDumpFileName;
MODULE_SCOPE TclPlatformType tclPlatform;
MODULE_SCOPE Tcl_NotifierProcs tclNotifierHooks;

/*
 * Declarations related to internal encoding functions.
 */

MODULE_SCOPE Tcl_Encoding tclIdentityEncoding;
MODULE_SCOPE Tcl_Encoding tclUtf8Encoding;
MODULE_SCOPE int	TclEncodingProfileNameToId(Tcl_Interp *interp,
			    const char *profileName,
			    int *profilePtr);
MODULE_SCOPE const char *TclEncodingProfileIdToName(Tcl_Interp *interp,
			    int profileId);
MODULE_SCOPE void	TclGetEncodingProfiles(Tcl_Interp *interp);

/*
 * TIP #233 (Virtualized Time)
 * Data for the time hooks, if any.
 */

MODULE_SCOPE Tcl_GetTimeProc *tclGetTimeProcPtr;
MODULE_SCOPE Tcl_ScaleTimeProc *tclScaleTimeProcPtr;
MODULE_SCOPE void *tclTimeClientData;

/*
 * Variables denoting the Tcl object types defined in the core.
 */

MODULE_SCOPE const Tcl_ObjType tclBignumType;
MODULE_SCOPE const Tcl_ObjType tclBooleanType;
MODULE_SCOPE const Tcl_ObjType tclByteArrayType;
MODULE_SCOPE const Tcl_ObjType tclByteCodeType;
MODULE_SCOPE const Tcl_ObjType tclDoubleType;
MODULE_SCOPE const Tcl_ObjType tclByteCodeType;
MODULE_SCOPE const Tcl_ObjType tclDoubleType;
MODULE_SCOPE const Tcl_ObjType tclExprCodeType;
MODULE_SCOPE const Tcl_ObjType tclIntType;
MODULE_SCOPE const Tcl_ObjType tclIndexType;
MODULE_SCOPE const Tcl_ObjType tclListType;
MODULE_SCOPE const Tcl_ObjType tclDictType;
MODULE_SCOPE const Tcl_ObjType tclProcBodyType;
MODULE_SCOPE const Tcl_ObjType tclStringType;
MODULE_SCOPE const Tcl_ObjType tclEnsembleCmdType;
MODULE_SCOPE const Tcl_ObjType tclRegexpType;
MODULE_SCOPE Tcl_ObjType tclCmdNameType;
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
3216
3217
3218
3219
3220
3221
3222


3223
3224
3225
3226
3227


3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245

3246
3247
3248
3249
3250
3251
3252
3253

3254
3255

3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269

3270

3271


3272
3273

3274



3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285

3286




3287
3288

3289
3290
3291
3292
3293
3294
3295

3296
3297

3298
3299


3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311


3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327


3328
3329
3330

3331
3332
3333
3334

3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347

3348
3349

3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361


3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382

3383

3384
3385
3386
3387
3388
3389
3390
3391
3392
3393







-
-
+
+
+


-
-
+
+
















-
+







-
+

-
+













-
+
-

-
-
+

-
+
-
-
-
+










-
+
-
-
-
-
+

-
+

+
+
+
+

-
+

-
+

-
-
+
+
+




+
+
+


-
-
+
+



+






+



-
-
+
+

-
+



-
+









+
+

-
+

-
+
+
+
+
+
+
+
+
+
+


-
-
+
+









+
+








-

-
+
+
+







MODULE_SCOPE Tcl_ObjCmdProc TclNRCoroutineObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldmObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldToObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclNRInvoke;
MODULE_SCOPE Tcl_NRPostProc TclNRReleaseValues;

MODULE_SCOPE void  TclSetTailcall(Tcl_Interp *interp, Tcl_Obj *tailcallPtr);
MODULE_SCOPE void  TclPushTailcallPoint(Tcl_Interp *interp);
MODULE_SCOPE void	TclSetTailcall(Tcl_Interp *interp,
			    Tcl_Obj *tailcallPtr);
MODULE_SCOPE void	TclPushTailcallPoint(Tcl_Interp *interp);

/* These two can be considered for the public api */
MODULE_SCOPE void  TclMarkTailcall(Tcl_Interp *interp);
MODULE_SCOPE void  TclSkipTailcall(Tcl_Interp *interp);
MODULE_SCOPE void	TclMarkTailcall(Tcl_Interp *interp);
MODULE_SCOPE void	TclSkipTailcall(Tcl_Interp *interp);

/*
 * This structure holds the data for the various iteration callbacks used to
 * NRE the 'for' and 'while' commands. We need a separate structure because we
 * have more than the 4 client data entries we can provide directly thorugh
 * the callback API. It is the 'word' information which puts us over the
 * limit. It is needed because the loop body is argument 4 of 'for' and
 * argument 2 of 'while'. Not providing the correct index confuses the #280
 * code. We TclSmallAlloc/Free this.
 */

typedef struct ForIterData {
    Tcl_Obj *cond;		/* Loop condition expression. */
    Tcl_Obj *body;		/* Loop body. */
    Tcl_Obj *next;		/* Loop step script, NULL for 'while'. */
    const char *msg;		/* Error message part. */
    int word;			/* Index of the body script in the command */
    Tcl_Size word;		/* Index of the body script in the command */
} ForIterData;

/* TIP #357 - Structure doing the bookkeeping of handles for Tcl_LoadFile
 *            and Tcl_FindSymbol. This structure corresponds to an opaque
 *            typedef in tcl.h */

typedef void* TclFindSymbolProc(Tcl_Interp* interp, Tcl_LoadHandle loadHandle,
				const char* symbol);
	const char* symbol);
struct Tcl_LoadHandle_ {
    void *clientData;	/* Client data is the load handle in the
    void *clientData;		/* Client data is the load handle in the
				 * native filesystem if a module was loaded
				 * there, or an opaque pointer to a structure
				 * for further bookkeeping on load-from-VFS
				 * and load-from-memory */
    TclFindSymbolProc* findSymbolProcPtr;
				/* Procedure that resolves symbols in a
				 * loaded module */
    Tcl_FSUnloadFileProc* unloadFileProcPtr;
				/* Procedure that unloads a loaded module */
};

/* Flags for conversion of doubles to digit strings */

#define TCL_DD_E_FORMAT 		0x2
#define TCL_DD_E_FORMAT 0x2	/* Use a fixed-length string of digits,
				/* Use a fixed-length string of digits,
				 * suitable for E format*/
#define TCL_DD_F_FORMAT 		0x3
				/* Use a fixed number of digits after the
#define TCL_DD_F_FORMAT 0x3	/* Use a fixed number of digits after the
				 * decimal point, suitable for F format */
#define TCL_DD_SHORTEST 		0x4
#define TCL_DD_SHORTEST 0x4	/* Use the shortest possible string */
				/* Use the shortest possible string */
#define TCL_DD_NO_QUICK 		0x8
				/* Debug flag: forbid quick FP conversion */
#define TCL_DD_NO_QUICK 0x8	/* Debug flag: forbid quick FP conversion */

#define TCL_DD_CONVERSION_TYPE_MASK	0x3
				/* Mask to isolate the conversion type */

/*
 *----------------------------------------------------------------
 * Procedures shared among Tcl modules but not used by the outside world:
 *----------------------------------------------------------------
 */

MODULE_SCOPE void	TclAppendBytesToByteArray(Tcl_Obj *objPtr,
#if TCL_MAJOR_VERSION > 8
			    const unsigned char *bytes, size_t len);
MODULE_SCOPE int	TclNREvalCmd(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    int flags);
MODULE_SCOPE void	TclAdvanceContinuations(int *line, int **next,
MODULE_SCOPE void	TclAdvanceContinuations(Tcl_Size *line, Tcl_Size **next,
			    int loc);
MODULE_SCOPE void	TclAdvanceLines(int *line, const char *start,
MODULE_SCOPE void	TclAdvanceLines(Tcl_Size *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[], int objc, CmdFrame *cf);
			    Tcl_Obj *objv[], Tcl_Size objc, CmdFrame *cf);
MODULE_SCOPE void	TclArgumentRelease(Tcl_Interp *interp,
			    Tcl_Obj *objv[], int objc);
			    Tcl_Obj *objv[], Tcl_Size objc);
MODULE_SCOPE void	TclArgumentBCEnter(Tcl_Interp *interp,
			    Tcl_Obj *objv[], int objc,
			    void *codePtr, CmdFrame *cfPtr, int cmd, size_t pc);
			    Tcl_Obj *objv[], Tcl_Size objc,
			    void *codePtr, CmdFrame *cfPtr, Tcl_Size cmd,
			    Tcl_Size pc);
MODULE_SCOPE void	TclArgumentBCRelease(Tcl_Interp *interp,
			    CmdFrame *cfPtr);
MODULE_SCOPE void	TclArgumentGet(Tcl_Interp *interp, Tcl_Obj *obj,
			    CmdFrame **cfPtrPtr, int *wordPtr);
MODULE_SCOPE int	TclAsyncNotifier(int sigNumber, Tcl_ThreadId threadId,
			    void *clientData, int *flagPtr, int value);
MODULE_SCOPE void	TclAsyncMarkFromNotifier(void);
MODULE_SCOPE double	TclBignumToDouble(const void *bignum);
MODULE_SCOPE int	TclByteArrayMatch(const unsigned char *string,
			    size_t strLen, const unsigned char *pattern,
			    size_t ptnLen, int flags);
			    Tcl_Size strLen, const unsigned char *pattern,
			    Tcl_Size ptnLen, int flags);
MODULE_SCOPE double	TclCeil(const void *a);
MODULE_SCOPE void	TclChannelPreserve(Tcl_Channel chan);
MODULE_SCOPE void	TclChannelRelease(Tcl_Channel chan);
MODULE_SCOPE int	TclChannelGetBlockingMode(Tcl_Channel chan);
MODULE_SCOPE int	TclCheckArrayTraces(Tcl_Interp *interp, Var *varPtr,
			    Var *arrayPtr, Tcl_Obj *name, int index);
MODULE_SCOPE int	TclCheckEmptyString(Tcl_Obj *objPtr);
MODULE_SCOPE int	TclChanCaughtErrorBypass(Tcl_Interp *interp,
			    Tcl_Channel chan);
MODULE_SCOPE Tcl_ObjCmdProc TclChannelNamesCmd;
MODULE_SCOPE int	TclChanIsBinary(Tcl_Channel chan);
MODULE_SCOPE Tcl_NRPostProc TclClearRootEnsemble;
MODULE_SCOPE int	TclCompareTwoNumbers(Tcl_Obj *valuePtr,
			    Tcl_Obj *value2Ptr);
MODULE_SCOPE ContLineLoc *TclContinuationsEnter(Tcl_Obj *objPtr, int num,
			    int *loc);
MODULE_SCOPE ContLineLoc *TclContinuationsEnter(Tcl_Obj *objPtr, Tcl_Size num,
			    Tcl_Size *loc);
MODULE_SCOPE void	TclContinuationsEnterDerived(Tcl_Obj *objPtr,
			    int start, int *clNext);
			    Tcl_Size start, Tcl_Size *clNext);
MODULE_SCOPE ContLineLoc *TclContinuationsGet(Tcl_Obj *objPtr);
MODULE_SCOPE void	TclContinuationsCopy(Tcl_Obj *objPtr,
			    Tcl_Obj *originObjPtr);
MODULE_SCOPE size_t	TclConvertElement(const char *src, size_t length,
MODULE_SCOPE Tcl_Size	TclConvertElement(const char *src, Tcl_Size length,
			    char *dst, int flags);
MODULE_SCOPE Tcl_Command TclCreateObjCommandInNs(Tcl_Interp *interp,
			    const char *cmdName, Tcl_Namespace *nsPtr,
			    Tcl_ObjCmdProc *proc, void *clientData,
			    Tcl_CmdDeleteProc *deleteProc);
MODULE_SCOPE Tcl_Command TclCreateEnsembleInNs(Tcl_Interp *interp,
			    const char *name, Tcl_Namespace *nameNamespacePtr,
			    Tcl_Namespace *ensembleNamespacePtr, int flags);
MODULE_SCOPE void	TclDeleteNamespaceVars(Namespace *nsPtr);
MODULE_SCOPE void	TclDeleteNamespaceChildren(Namespace *nsPtr);
MODULE_SCOPE Tcl_Size	TclDictGetSize(Tcl_Obj *dictPtr);
MODULE_SCOPE int	TclFindDictElement(Tcl_Interp *interp,
			    const char *dict, int dictLength,
			    const char *dict, Tcl_Size dictLength,
			    const char **elementPtr, const char **nextPtr,
			    size_t *sizePtr, int *literalPtr);
			    Tcl_Size *sizePtr, int *literalPtr);
MODULE_SCOPE Tcl_Obj *	TclDictObjSmartRef(Tcl_Interp *interp, Tcl_Obj *);
MODULE_SCOPE int	TclDictGet(Tcl_Interp *interp, Tcl_Obj *dictPtr,
			    const char *key, Tcl_Obj **valuePtrPtr);
MODULE_SCOPE int	TclDictPut(Tcl_Interp *interp, Tcl_Obj *dictPtr,
			    const char *key, Tcl_Obj *valuePtr);
MODULE_SCOPE int	TclDictPutString(Tcl_Interp *interp, Tcl_Obj *dictPtr,
			    const char *key, const char *value);
MODULE_SCOPE int	TclDictRemove(Tcl_Interp *interp, Tcl_Obj *dictPtr,
			    const char *key);
/* TIP #280 - Modified token based evaluation, with line information. */
MODULE_SCOPE int	TclEvalEx(Tcl_Interp *interp, const char *script,
			    size_t numBytes, int flags, int line,
			    int *clNextOuter, const char *outerScript);
			    Tcl_Size numBytes, int flags, Tcl_Size line,
			    Tcl_Size *clNextOuter, const char *outerScript);
MODULE_SCOPE Tcl_ObjCmdProc TclFileAttrsCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclFileCopyCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclFileDeleteCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclFileLinkCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclFileMakeDirsCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclFileReadLinkCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclFileRenameCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclFileTempDirCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclFileTemporaryCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclFileHomeCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclFileTildeExpandCmd;
MODULE_SCOPE void	TclCreateLateExitHandler(Tcl_ExitProc *proc,
			    void *clientData);
MODULE_SCOPE void	TclDeleteLateExitHandler(Tcl_ExitProc *proc,
			    void *clientData);
MODULE_SCOPE char *	TclDStringAppendObj(Tcl_DString *dsPtr,
			    Tcl_Obj *objPtr);
MODULE_SCOPE char *	TclDStringAppendDString(Tcl_DString *dsPtr,
			    Tcl_DString *toAppendPtr);
MODULE_SCOPE Tcl_Obj *	TclDStringToObj(Tcl_DString *dsPtr);
MODULE_SCOPE Tcl_Obj *const *TclFetchEnsembleRoot(Tcl_Interp *interp,
			    Tcl_Obj *const *objv, int objc, int *objcPtr);
			    Tcl_Obj *const *objv, Tcl_Size objc,
			    Tcl_Size *objcPtr);
MODULE_SCOPE Tcl_Obj *const *TclEnsembleGetRewriteValues(Tcl_Interp *interp);
MODULE_SCOPE Tcl_Namespace *TclEnsureNamespace(Tcl_Interp *interp,
			    Tcl_Namespace *namespacePtr);
MODULE_SCOPE void	TclFinalizeAllocSubsystem(void);
MODULE_SCOPE void	TclFinalizeAsync(void);
MODULE_SCOPE void	TclFinalizeDoubleConversion(void);
MODULE_SCOPE void	TclFinalizeEncodingSubsystem(void);
MODULE_SCOPE void	TclFinalizeEnvironment(void);
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
3134

3135
3136
3137
3138
3139
3140
3141
3142

3143
3144
3145

3146
3147
3148

3149
3150
3151

3152
3153
3154
3155

3156
3157
3158
3159
3160

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
3199
3200
3201
3202
3203

3204
3205

3206
3207
3208
3209
3210
3211
3212
3213
3214


3215
3216
3217
3218
3219

3220
3221
3222


3223
3224
3225

3226
3227
3228
3229
3230
3231
3232
3233

3234
3235
3236



3237
3238
3239
3240
3241
3242
3243
3244
3245
3246


3247
3248
3249
3250
3251
3252
3253
3254

3255
3256
3257

3258
3259
3260

3261
3262
3263
3264
3265

3266
3267
3268

3269
3270
3271

3272
3273
3274
3275

3276
3277
3278

3279
3280
3281

3282
3283

3284
3285
3286

3287
3288
3289


3290
3291
3292

3293
3294
3295

3296
3297
3298
3299
3300
3301

3302
3303
3304
3305
3306
3307
3308
3309
3310
3311


3312
3313

3314
3315
3316

3317
3318
3319

3320
3321
3322
3323

3324
3325
3326

3327
3328
3329

3330
3331
3332

3333
3334
3335

3336
3337
3338

3339
3340
3341

3342
3343
3344

3345
3346
3347

3348
3349
3350
3351

3352
3353
3354

3355
3356
3357

3358
3359
3360

3361
3362
3363

3364
3365
3366

3367
3368
3369

3370
3371
3372

3373
3374
3375

3376
3377
3378

3379
3380
3381
3382

3383
3384
3385


3386
3387
3388

3389
3390
3391


3392
3393
3394

3395
3396
3397

3398
3399
3400

3401
3402
3403

3404
3405
3406

3407
3408
3409

3410
3411
3412

3413
3414
3415

3416
3417
3418

3419
3420
3421

3422
3423
3424

3425
3426
3427

3428
3429
3430

3431
3432
3433

3434
3435
3436

3437
3438
3439
3440

3441
3442
3443

3444
3445
3446

3447
3448
3449

3450
3451
3452
3453

3454
3455
3456

3457
3458
3459

3460
3461
3462

3463
3464
3465

3466
3467
3468

3469
3470
3471

3472
3473
3474

3475
3476
3477

3478
3479
3480

3481
3482
3483

3484
3485
3486

3487
3488
3489

3490
3491
3492

3493
3494
3495
3496

3497
3498
3499

3500
3501
3502

3503
3504
3505

3506
3507

3508
3509
3510

3511
3512
3513

3514
3515
3516

3517
3518
3519

3520
3521
3522

3523
3524
3525

3526
3527
3528

3529
3530
3531

3532
3533
3534

3535
3536
3537

3538
3539
3540

3541
3542
3543
3544
3545
3546
3547
3548
3549
3550

3551
3552
3553

3554
3555
3556

3557
3558
3559

3560
3561
3562

3563
3564
3565

3566
3567
3568

3569
3570
3571

3572
3573
3574

3575
3576
3577


3578
3579
3580

3581
3582
3583

3584
3585
3586

3587
3588
3589

3590
3591
3592

3593
3594
3595

3596
3597
3598

3599
3600
3601

3602
3603
3604

3605
3606
3607

3608
3609
3610

3611
3612
3613

3614
3615
3616

3617
3618
3619

3620
3621
3622

3623
3624
3625

3626
3627
3628

3629
3630
3631

3632
3633
3634

3635
3636
3637

3638
3639
3640

3641
3642
3643

3644
3645
3646

3647
3648
3649

3650
3651
3652

3653
3654
3655

3656
3657
3658

3659
3660
3661

3662
3663
3664

3665
3666
3667

3668
3669
3670

3671
3672
3673

3674
3675
3676

3677
3678
3679

3680
3681
3682

3683
3684
3685

3686
3687
3688

3689
3690
3691

3692
3693
3694

3695
3696
3697

3698
3699
3700

3701
3702
3703

3704
3705
3706

3707
3708
3709

3710
3711
3712

3713
3714
3715

3716
3717
3718

3719
3720
3721

3722
3723
3724

3725
3726
3727

3728
3729
3730

3731
3732
3733

3734
3735
3736

3737
3738
3739

3740
3741
3742

3743
3744
3745

3746
3747
3748

3749
3750
3751

3752
3753
3754

3755
3756
3757

3758
3759
3760

3761
3762
3763

3764
3765
3766

3767
3768
3769

3770
3771
3772

3773
3774
3775

3776
3777
3778

3779
3780
3781

3782
3783
3784

3785
3786
3787

3788
3789
3790

3791
3792
3793

3794
3795
3796

3797
3798
3799

3800
3801
3802

3803
3804
3805

3806
3807
3808

3809
3810
3811

3812
3813
3814

3815
3816
3817

3818
3819
3820

3821
3822
3823

3824
3825
3826

3827
3828
3829

3830
3831
3832

3833
3834
3835

3836
3837
3838

3839
3840
3841

3842
3843
3844

3845
3846
3847

3848
3849
3850

3851
3852
3853

3854
3855
3856

3857
3858
3859

3860
3861
3862

3863
3864
3865

3866
3867
3868

3869
3870
3871
3872

3873
3874
3875
3876


3877
3878

3879
3880
3881

3882
3883
3884

3885
3886
3887

3888
3889
3890

3891
3892
3893

3894
3895
3896

3897
3898
3899

3900
3901
3902

3903
3904
3905

3906
3907
3908

3909
3910
3911

3912
3913
3914

3915
3916
3917

3918
3919
3920

3921
3922
3923

3924
3925
3926

3927
3928
3929

3930
3931
3932

3933
3934
3935

3936
3937
3938

3939
3940
3941

3942
3943
3944

3945
3946
3947

3948
3949
3950

3951
3952
3953

3954
3955
3956

3957
3958
3959

3960
3961
3962

3963
3964
3965

3966
3967
3968

3969
3970
3971

3972
3973
3974

3975
3976
3977

3978
3979
3980

3981
3982
3983

3984
3985
3986

3987
3988
3989

3990
3991
3992

3993
3994
3995

3996
3997
3998

3999
4000
4001

4002
4003
4004
4005

4006
4007
4008
4009
4010
4011
4012
4013
4014

4015
4016
4017

4018
4019

4020
4021

4022
4023

4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041


4042
4043
4044
4045


4046
4047
4048
4049

4050
4051
4052
4053

4054
4055
4056
4057

4058
4059
4060
4061
4062
4063

4064
4065
4066
4067
4068
4069
4070
3411
3412
3413
3414
3415
3416
3417


3418
3419
3420

3421
3422
3423
3424
3425
3426
3427
3428
3429
3430






3431

3432
3433
3434


3435
3436
3437

3438
3439
3440

3441


3442
3443
3444
3445
3446

3447


3448

3449





3450
3451
3452
3453
3454

3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466

3467

3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478

3479
3480
3481


3482
3483
3484
3485
3486
3487


3488
3489
3490
3491
3492

3493
3494
3495
3496

3497
3498
3499
3500
3501

3502
3503
3504
3505
3506
3507
3508
3509

3510
3511
3512
3513
3514

3515


3516
3517

3518
3519


3520
3521
3522
3523
3524
3525
3526

3527
3528
3529
3530
3531
3532

3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560


3561
3562
3563

3564
3565
3566
3567
3568
3569
3570
3571


3572
3573
3574

3575
3576

3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590


3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607

3608
3609

3610
3611
3612
3613

3614
3615
3616
3617
3618
3619
3620
3621

3622
3623
3624

3625
3626
3627

3628
3629
3630

3631




3632
3633
3634
3635
3636

3637
3638

3639
3640
3641

3642
3643
3644








3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662









3663





3664
3665
3666
3667
3668
3669
3670

3671
3672

3673
3674
3675
3676
3677
3678
3679
3680


3681
3682
3683
3684
3685
3686

3687
3688


3689
3690
3691
3692

3693
3694
3695
3696
3697
3698
3699
3700

3701
3702


3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713


3714
3715
3716
3717
3718
3719
3720
3721
3722

3723



3724



3725


3726
3727

3728



3729



3730


3731

3732



3733



3734


3735

3736

3737



3738
3739



3740



3741


3742
3743
3744

3745


3746
3747
3748
3749
3750
3751


3752
3753


3754
3755
3756

3757



3758


3759

3760



3761



3762



3763



3764



3765



3766



3767



3768


3769

3770



3771



3772



3773



3774



3775



3776



3777



3778



3779


3780

3781



3782
3783



3784



3785
3786



3787



3788



3789



3790



3791



3792



3793



3794



3795



3796



3797



3798



3799



3800



3801


3802

3803



3804



3805



3806


3807

3808



3809



3810



3811



3812



3813



3814



3815



3816



3817



3818



3819



3820



3821


3822

3823



3824



3825



3826


3827



3828



3829



3830



3831



3832



3833



3834



3835



3836



3837



3838


3839
3840
3841
3842
3843
3844
3845

3846



3847



3848



3849



3850



3851



3852



3853



3854



3855
3856



3857



3858



3859



3860



3861



3862



3863



3864



3865



3866



3867



3868



3869



3870



3871



3872



3873



3874



3875



3876



3877



3878



3879



3880



3881



3882



3883



3884



3885



3886



3887



3888



3889



3890



3891



3892



3893



3894



3895



3896



3897



3898



3899



3900



3901



3902



3903



3904



3905



3906



3907



3908



3909



3910



3911



3912



3913



3914



3915



3916



3917



3918



3919



3920



3921



3922



3923



3924



3925



3926



3927



3928



3929



3930



3931



3932



3933



3934



3935



3936



3937



3938



3939



3940



3941



3942



3943



3944



3945



3946



3947



3948



3949



3950



3951



3952



3953


3954

3955




3956
3957


3958



3959



3960



3961



3962



3963



3964



3965



3966



3967



3968



3969



3970



3971



3972



3973



3974



3975



3976



3977



3978



3979



3980



3981



3982



3983



3984



3985



3986



3987



3988



3989



3990



3991



3992



3993



3994



3995



3996



3997



3998



3999


4000

4001


4002
4003
4004
4005
4006
4007

4008
4009
4010

4011
4012

4013
4014

4015
4016

4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033


4034
4035
4036
4037


4038
4039
4040
4041
4042

4043
4044
4045
4046

4047
4048
4049
4050

4051
4052
4053
4054
4055
4056

4057
4058
4059
4060
4061
4062
4063
4064







-
-
+


-










-
-
-
-
-
-

-
+


-
-
+
+

-
+


-
+
-
-
+




-
+
-
-
+
-

-
-
-
-
-
+
+
+
+
+
-












-

-
+

+
+
+
+





-
+
+

-
-
+
+

+
+
+
-
-
+
+



-
+



-
+




-
+







-
+




-
+
-
-


-
+

-
-
+
+


+


-
+
+
+
+
+

-
+
+
+
+
+
+
+
+
+

+


+


+
+
+
+
+
+






-
-
+
+

-
+

+





-
-



-
+

-
+













-
-
+
+
+














-
+

-
+



-
+







-
+


-
+


-
+


-
+
-
-
-
-
+




-
+

-
+


-
+


-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

+
+
+





-
-
-
-
-
-
-
-
-
+
-
-
-
-
-







-
+

-
+







-
-
+
+




-
+

-
-
+
+


-
+







-
+

-
-
+
+
+








-
-
+
+







-
+
-
-
-
+
-
-
-
+
-
-


-
+
-
-
-
+
-
-
-
+
-
-

-
+
-
-
-
+
-
-
-
+
-
-
+
-

-
+
-
-
-
+
+
-
-
-
+
-
-
-
+
-
-



-
+
-
-






-
-
+
+
-
-
+


-
+
-
-
-
+
-
-

-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-

-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-

-
+
-
-
-
+
+
-
-
-
+
-
-
-
+
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-

-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-

-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-

-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-







-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-

-
+
-
-
-
-
+
+
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-

-
+
-
-






-
+


-
+

-
+

-
+

-
+
















-
-
+
+


-
-
+
+



-
+



-
+



-
+





-
+







MODULE_SCOPE double	TclFloor(const void *a);
MODULE_SCOPE void	TclFormatNaN(double value, char *buffer);
MODULE_SCOPE int	TclFSFileAttrIndex(Tcl_Obj *pathPtr,
			    const char *attributeName, int *indexPtr);
MODULE_SCOPE Tcl_Command TclNRCreateCommandInNs(Tcl_Interp *interp,
			    const char *cmdName, Tcl_Namespace *nsPtr,
			    Tcl_ObjCmdProc *proc, Tcl_ObjCmdProc *nreProc,
			    void *clientData,
			    Tcl_CmdDeleteProc *deleteProc);
			    void *clientData, Tcl_CmdDeleteProc *deleteProc);
MODULE_SCOPE int	TclNREvalFile(Tcl_Interp *interp, Tcl_Obj *pathPtr,
			    const char *encodingName);
MODULE_SCOPE void	TclFSUnloadTempFile(Tcl_LoadHandle loadHandle);
MODULE_SCOPE int *	TclGetAsyncReadyPtr(void);
MODULE_SCOPE Tcl_Obj *	TclGetBgErrorHandler(Tcl_Interp *interp);
MODULE_SCOPE int	TclGetChannelFromObj(Tcl_Interp *interp,
			    Tcl_Obj *objPtr, Tcl_Channel *chanPtr,
			    int *modePtr, int flags);
MODULE_SCOPE CmdFrame *	TclGetCmdFrameForProcedure(Proc *procPtr);
MODULE_SCOPE int	TclGetCompletionCodeFromObj(Tcl_Interp *interp,
			    Tcl_Obj *value, int *code);
MODULE_SCOPE Proc *	TclGetLambdaFromObj(Tcl_Interp *interp,
			    Tcl_Obj *objPtr, Tcl_Obj **nsObjPtrPtr);
MODULE_SCOPE int	TclGetNumberFromObj(Tcl_Interp *interp,
			    Tcl_Obj *objPtr, void **clientDataPtr,
			    int *typePtr);
MODULE_SCOPE int	TclGetOpenModeEx(Tcl_Interp *interp,
			    const char *modeString, int *seekFlagPtr,
			    int *binaryPtr);
MODULE_SCOPE Tcl_Obj *	TclGetProcessGlobalValue(ProcessGlobalValue *pgvPtr);
MODULE_SCOPE Tcl_Obj *	TclGetSourceFromFrame(CmdFrame *cfPtr, int objc,
MODULE_SCOPE Tcl_Obj *	TclGetSourceFromFrame(CmdFrame *cfPtr, Tcl_Size objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE char *	TclGetStringStorage(Tcl_Obj *objPtr,
			    size_t *sizePtr);
MODULE_SCOPE int	TclGetLoadedPackagesEx(Tcl_Interp *interp,
			    Tcl_Size *sizePtr);
MODULE_SCOPE int	TclGetLoadedLibraries(Tcl_Interp *interp,
				const char *targetName,
				const char *packageName);
				const char *prefix);
MODULE_SCOPE int	TclGetWideBitsFromObj(Tcl_Interp *, Tcl_Obj *,
				Tcl_WideInt *);
MODULE_SCOPE int	TclGlob(Tcl_Interp *interp, char *pattern,
MODULE_SCOPE int	TclCompareStringKeys(void *keyPtr, Tcl_HashEntry *hPtr);
			    Tcl_Obj *unquotedPrefix, int globFlags,
			    Tcl_GlobTypeData *types);
MODULE_SCOPE size_t	TclHashStringKey(Tcl_HashTable *tablePtr, void *keyPtr);
MODULE_SCOPE int	TclIncrObj(Tcl_Interp *interp, Tcl_Obj *valuePtr,
			    Tcl_Obj *incrPtr);
MODULE_SCOPE Tcl_Obj *	TclIncrObjVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
			    Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr, int flags);
MODULE_SCOPE int	TclInfoExistsCmd(void *dummy, Tcl_Interp *interp,
MODULE_SCOPE Tcl_ObjCmdProc TclInfoExistsCmd;
			    int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclInfoCoroutineCmd(void *dummy, Tcl_Interp *interp,
MODULE_SCOPE Tcl_ObjCmdProc TclInfoCoroutineCmd;
			    int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Obj *	TclInfoFrame(Tcl_Interp *interp, CmdFrame *framePtr);
MODULE_SCOPE int	TclInfoGlobalsCmd(void *dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclInfoLocalsCmd(void *dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclInfoVarsCmd(void *dummy, Tcl_Interp *interp,
MODULE_SCOPE Tcl_ObjCmdProc TclInfoGlobalsCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclInfoLocalsCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclInfoVarsCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclInfoConstsCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclInfoConstantCmd;
			    int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE void	TclInitAlloc(void);
MODULE_SCOPE void	TclInitDbCkalloc(void);
MODULE_SCOPE void	TclInitDoubleConversion(void);
MODULE_SCOPE void	TclInitEmbeddedConfigurationInformation(
			    Tcl_Interp *interp);
MODULE_SCOPE void	TclInitEncodingSubsystem(void);
MODULE_SCOPE void	TclInitIOSubsystem(void);
MODULE_SCOPE void	TclInitLimitSupport(Tcl_Interp *interp);
MODULE_SCOPE void	TclInitNamespaceSubsystem(void);
MODULE_SCOPE void	TclInitNotifier(void);
MODULE_SCOPE void	TclInitObjSubsystem(void);
MODULE_SCOPE int	TclInterpReady(Tcl_Interp *interp);
MODULE_SCOPE int	TclIsDigitProc(int byte);
MODULE_SCOPE int	TclIsBareword(int byte);
MODULE_SCOPE Tcl_Obj *	TclJoinPath(int elements, Tcl_Obj * const objv[],
MODULE_SCOPE Tcl_Obj *	TclJoinPath(Tcl_Size elements, Tcl_Obj * const objv[],
			    int forceRelative);
MODULE_SCOPE Tcl_Obj *	TclGetHomeDirObj(Tcl_Interp *interp, const char *user);
MODULE_SCOPE Tcl_Obj *	TclResolveTildePath(Tcl_Interp *interp,
			    Tcl_Obj *pathObj);
MODULE_SCOPE Tcl_Obj *	TclResolveTildePathList(Tcl_Obj *pathsObj);
MODULE_SCOPE int	TclJoinThread(Tcl_ThreadId id, int *result);
MODULE_SCOPE void	TclLimitRemoveAllHandlers(Tcl_Interp *interp);
MODULE_SCOPE Tcl_Obj *	TclLindexList(Tcl_Interp *interp,
			    Tcl_Obj *listPtr, Tcl_Obj *argPtr);
MODULE_SCOPE Tcl_Obj *	TclLindexFlat(Tcl_Interp *interp, Tcl_Obj *listPtr,
			    int indexCount, Tcl_Obj *const indexArray[]);
			    Tcl_Size indexCount, Tcl_Obj *const indexArray[]);
MODULE_SCOPE Tcl_Obj *	TclListObjGetElement(Tcl_Obj *listObj, Tcl_Size index);
/* TIP #280 */
MODULE_SCOPE void	TclListLines(Tcl_Obj *listObj, int line, int n,
			    int *lines, Tcl_Obj *const *elems);
MODULE_SCOPE void	TclListLines(Tcl_Obj *listObj, Tcl_Size line, Tcl_Size n,
			    Tcl_Size *lines, Tcl_Obj *const *elems);
MODULE_SCOPE Tcl_Obj *	TclListObjCopy(Tcl_Interp *interp, Tcl_Obj *listPtr);
MODULE_SCOPE int	TclListObjAppendElements(Tcl_Interp *interp,
			    Tcl_Obj *toObj, Tcl_Size elemCount,
			    Tcl_Obj *const elemObjv[]);
MODULE_SCOPE Tcl_Obj *	TclListObjRange(Tcl_Obj *listPtr, size_t fromIdx,
			    size_t toIdx);
MODULE_SCOPE Tcl_Obj *	TclListObjRange(Tcl_Interp *interp, Tcl_Obj *listPtr,
			    Tcl_Size fromIdx, Tcl_Size toIdx);
MODULE_SCOPE Tcl_Obj *	TclLsetList(Tcl_Interp *interp, Tcl_Obj *listPtr,
			    Tcl_Obj *indexPtr, Tcl_Obj *valuePtr);
MODULE_SCOPE Tcl_Obj *	TclLsetFlat(Tcl_Interp *interp, Tcl_Obj *listPtr,
			    int indexCount, Tcl_Obj *const indexArray[],
			    Tcl_Size indexCount, Tcl_Obj *const indexArray[],
			    Tcl_Obj *valuePtr);
MODULE_SCOPE Tcl_Command TclMakeEnsemble(Tcl_Interp *interp, const char *name,
			    const EnsembleImplMap map[]);
MODULE_SCOPE int	TclMaxListLength(const char *bytes, size_t numBytes,
MODULE_SCOPE Tcl_Size	TclMaxListLength(const char *bytes, Tcl_Size numBytes,
			    const char **endPtr);
MODULE_SCOPE int	TclMergeReturnOptions(Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[], Tcl_Obj **optionsPtrPtr,
			    int *codePtr, int *levelPtr);
MODULE_SCOPE Tcl_Obj *  TclNoErrorStack(Tcl_Interp *interp, Tcl_Obj *options);
MODULE_SCOPE Tcl_Obj *	TclNoErrorStack(Tcl_Interp *interp, Tcl_Obj *options);
MODULE_SCOPE int	TclNokia770Doubles(void);
MODULE_SCOPE void	TclNsDecrRefCount(Namespace *nsPtr);
MODULE_SCOPE int	TclNamespaceDeleted(Namespace *nsPtr);
MODULE_SCOPE void	TclObjVarErrMsg(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
			    Tcl_Obj *part2Ptr, const char *operation,
			    const char *reason, int index);
MODULE_SCOPE int	TclObjInvokeNamespace(Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[],
			    Tcl_Size objc, Tcl_Obj *const objv[],
			    Tcl_Namespace *nsPtr, int flags);
MODULE_SCOPE int	TclObjUnsetVar2(Tcl_Interp *interp,
			    Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags);
MODULE_SCOPE int	TclParseBackslash(const char *src,
			    size_t numBytes, size_t *readPtr, char *dst);
			    Tcl_Size numBytes, Tcl_Size *readPtr, char *dst);
MODULE_SCOPE int	TclParseHex(const char *src, size_t numBytes,
			    int *resultPtr);
MODULE_SCOPE int	TclParseNumber(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    const char *expected, const char *bytes,
			    size_t numBytes, const char **endPtrPtr, int flags);
			    Tcl_Size numBytes, const char **endPtrPtr, int flags);
MODULE_SCOPE void	TclParseInit(Tcl_Interp *interp, const char *string,
			    size_t numBytes, Tcl_Parse *parsePtr);
MODULE_SCOPE size_t	TclParseAllWhiteSpace(const char *src, size_t numBytes);
			    Tcl_Size numBytes, Tcl_Parse *parsePtr);
MODULE_SCOPE Tcl_Size	TclParseAllWhiteSpace(const char *src, Tcl_Size numBytes);
MODULE_SCOPE int	TclProcessReturn(Tcl_Interp *interp,
			    int code, int level, Tcl_Obj *returnOpts);
MODULE_SCOPE void	TclUndoRefCount(Tcl_Obj *objPtr);
MODULE_SCOPE int	TclpObjLstat(Tcl_Obj *pathPtr, Tcl_StatBuf *buf);
MODULE_SCOPE Tcl_Obj *	TclpTempFileName(void);
MODULE_SCOPE Tcl_Obj *  TclpTempFileNameForLibrary(Tcl_Interp *interp, Tcl_Obj* pathPtr);
MODULE_SCOPE Tcl_Obj *	TclpTempFileNameForLibrary(Tcl_Interp *interp,
			    Tcl_Obj* pathPtr);
MODULE_SCOPE Tcl_Obj *	TclNewArithSeriesObj(Tcl_Interp *interp,
			    int useDoubles, Tcl_Obj *startObj, Tcl_Obj *endObj,
			    Tcl_Obj *stepObj, Tcl_Obj *lenObj);
MODULE_SCOPE Tcl_Obj *	TclNewFSPathObj(Tcl_Obj *dirPtr, const char *addStrRep,
			    size_t len);
			    Tcl_Size len);
MODULE_SCOPE Tcl_Obj *	TclNewNamespaceObj(Tcl_Namespace *namespacePtr);
MODULE_SCOPE void	TclpAlertNotifier(void *clientData);
MODULE_SCOPE void *	TclpNotifierData(void);
MODULE_SCOPE void	TclpServiceModeHook(int mode);
MODULE_SCOPE void	TclpSetTimer(const Tcl_Time *timePtr);
MODULE_SCOPE int	TclpWaitForEvent(const Tcl_Time *timePtr);
MODULE_SCOPE void	TclpCreateFileHandler(int fd, int mask,
			    Tcl_FileProc *proc, void *clientData);
MODULE_SCOPE int	TclpDeleteFile(const void *path);
MODULE_SCOPE void	TclpDeleteFileHandler(int fd);
MODULE_SCOPE void	TclpFinalizeCondition(Tcl_Condition *condPtr);
MODULE_SCOPE void	TclpFinalizeMutex(Tcl_Mutex *mutexPtr);
MODULE_SCOPE void	TclpFinalizeNotifier(void *clientData);
MODULE_SCOPE void	TclpFinalizePipes(void);
MODULE_SCOPE void	TclpFinalizeSockets(void);
#ifdef _WIN32
MODULE_SCOPE void	TclInitSockets(void);
#else
#define TclInitSockets() /* do nothing */
#endif
struct addrinfo; /* forward declaration, needed for TclCreateSocketAddress */
MODULE_SCOPE int	TclCreateSocketAddress(Tcl_Interp *interp,
			    struct addrinfo **addrlist,
			    const char *host, int port, int willBind,
			    const char **errorMsgPtr);
MODULE_SCOPE int	TclpThreadCreate(Tcl_ThreadId *idPtr,
			    Tcl_ThreadCreateProc *proc, void *clientData,
			    size_t stackSize, int flags);
MODULE_SCOPE size_t	TclpFindVariable(const char *name, size_t *lengthPtr);
			    TCL_HASH_TYPE stackSize, int flags);
MODULE_SCOPE Tcl_Size	TclpFindVariable(const char *name, Tcl_Size *lengthPtr);
MODULE_SCOPE void	TclpInitLibraryPath(char **valuePtr,
			    size_t *lengthPtr, Tcl_Encoding *encodingPtr);
			    TCL_HASH_TYPE *lengthPtr, Tcl_Encoding *encodingPtr);
MODULE_SCOPE void	TclpInitLock(void);
MODULE_SCOPE void *	TclpInitNotifier(void);
MODULE_SCOPE void	TclpInitPlatform(void);
MODULE_SCOPE void	TclpInitUnlock(void);
MODULE_SCOPE Tcl_Obj *	TclpObjListVolumes(void);
MODULE_SCOPE void	TclpGlobalLock(void);
MODULE_SCOPE void	TclpGlobalUnlock(void);
MODULE_SCOPE int	TclpMatchFiles(Tcl_Interp *interp, char *separators,
			    Tcl_DString *dirPtr, char *pattern, char *tail);
MODULE_SCOPE int	TclpObjNormalizePath(Tcl_Interp *interp,
			    Tcl_Obj *pathPtr, int nextCheckpoint);
MODULE_SCOPE void	TclpNativeJoinPath(Tcl_Obj *prefix, const char *joining);
MODULE_SCOPE Tcl_Obj *	TclpNativeSplitPath(Tcl_Obj *pathPtr, int *lenPtr);
MODULE_SCOPE Tcl_Obj *	TclpNativeSplitPath(Tcl_Obj *pathPtr, Tcl_Size *lenPtr);
MODULE_SCOPE Tcl_PathType TclpGetNativePathType(Tcl_Obj *pathPtr,
			    int *driveNameLengthPtr, Tcl_Obj **driveNameRef);
			    Tcl_Size *driveNameLengthPtr, Tcl_Obj **driveNameRef);
MODULE_SCOPE int	TclCrossFilesystemCopy(Tcl_Interp *interp,
			    Tcl_Obj *source, Tcl_Obj *target);
MODULE_SCOPE int	TclpMatchInDirectory(Tcl_Interp *interp,
			    Tcl_Obj *resultPtr, Tcl_Obj *pathPtr,
			    const char *pattern, Tcl_GlobTypeData *types);
MODULE_SCOPE void	*TclpGetNativeCwd(void *clientData);
MODULE_SCOPE Tcl_FSDupInternalRepProc TclNativeDupInternalRep;
MODULE_SCOPE Tcl_Obj *	TclpObjLink(Tcl_Obj *pathPtr, Tcl_Obj *toPtr,
			    int linkType);
MODULE_SCOPE int	TclpObjChdir(Tcl_Obj *pathPtr);
MODULE_SCOPE Tcl_Channel TclpOpenTemporaryFile(Tcl_Obj *dirObj,
			    Tcl_Obj *basenameObj, Tcl_Obj *extensionObj,
			    Tcl_Obj *resultingNameObj);
MODULE_SCOPE void TclPkgFileSeen(Tcl_Interp *interp, const char *fileName);
MODULE_SCOPE void *TclInitPkgFiles(Tcl_Interp *interp);
MODULE_SCOPE void	TclPkgFileSeen(Tcl_Interp *interp,
			    const char *fileName);
MODULE_SCOPE void *	TclInitPkgFiles(Tcl_Interp *interp);
MODULE_SCOPE Tcl_Obj *	TclPathPart(Tcl_Interp *interp, Tcl_Obj *pathPtr,
			    Tcl_PathPart portion);
MODULE_SCOPE char *	TclpReadlink(const char *fileName,
			    Tcl_DString *linkPtr);
MODULE_SCOPE void	TclpSetVariables(Tcl_Interp *interp);
MODULE_SCOPE void *	TclThreadStorageKeyGet(Tcl_ThreadDataKey *keyPtr);
MODULE_SCOPE void	TclThreadStorageKeySet(Tcl_ThreadDataKey *keyPtr,
			    void *data);
MODULE_SCOPE TCL_NORETURN void TclpThreadExit(int status);
MODULE_SCOPE void	TclRememberCondition(Tcl_Condition *mutex);
MODULE_SCOPE void	TclRememberJoinableThread(Tcl_ThreadId id);
MODULE_SCOPE void	TclRememberMutex(Tcl_Mutex *mutex);
MODULE_SCOPE void	TclRemoveScriptLimitCallbacks(Tcl_Interp *interp);
MODULE_SCOPE int	TclReToGlob(Tcl_Interp *interp, const char *reStr,
			    size_t reStrLen, Tcl_DString *dsPtr, int *flagsPtr,
			    Tcl_Size reStrLen, Tcl_DString *dsPtr, int *flagsPtr,
			    int *quantifiersFoundPtr);
MODULE_SCOPE size_t	TclScanElement(const char *string, size_t length,
MODULE_SCOPE Tcl_Size	TclScanElement(const char *string, Tcl_Size length,
			    char *flagPtr);
MODULE_SCOPE void	TclSetBgErrorHandler(Tcl_Interp *interp,
			    Tcl_Obj *cmdPrefix);
MODULE_SCOPE void	TclSetBignumIntRep(Tcl_Obj *objPtr,
MODULE_SCOPE void	TclSetBignumInternalRep(Tcl_Obj *objPtr,
			    void *bignumValue);
MODULE_SCOPE int	TclSetBooleanFromAny(Tcl_Interp *interp,
			    Tcl_Obj *objPtr);
MODULE_SCOPE void	TclSetCmdNameObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    Command *cmdPtr);
MODULE_SCOPE void	TclSetDuplicateObj(Tcl_Obj *dupPtr, Tcl_Obj *objPtr);
MODULE_SCOPE void	TclSetProcessGlobalValue(ProcessGlobalValue *pgvPtr,
			    Tcl_Obj *newValue, Tcl_Encoding encoding);
			    Tcl_Obj *newValue);
MODULE_SCOPE void	TclSignalExitThread(Tcl_ThreadId id, int result);
MODULE_SCOPE void	TclSpellFix(Tcl_Interp *interp,
			    Tcl_Obj *const *objv, int objc, size_t subIdx,
			    Tcl_Obj *const *objv, Tcl_Size objc, Tcl_Size subIdx,
			    Tcl_Obj *bad, Tcl_Obj *fix);
MODULE_SCOPE void *	TclStackRealloc(Tcl_Interp *interp, void *ptr,
			    size_t numBytes);
			    TCL_HASH_TYPE numBytes);
typedef int (*memCmpFn_t)(const void*, const void*, size_t);
MODULE_SCOPE int	TclStringCmp(Tcl_Obj *value1Ptr, Tcl_Obj *value2Ptr,
			    int checkEq, int nocase, size_t reqlength);
			    int checkEq, int nocase, Tcl_Size reqlength);
MODULE_SCOPE int	TclStringCmpOpts(Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[], int *nocase,
			    int *reqlength);
MODULE_SCOPE int	TclStringMatch(const char *str, size_t strLen,
MODULE_SCOPE int	TclStringMatch(const char *str, Tcl_Size strLen,
			    const char *pattern, int ptnLen, int flags);
MODULE_SCOPE int	TclStringMatchObj(Tcl_Obj *stringObj,
			    Tcl_Obj *patternObj, int flags);
MODULE_SCOPE void	TclSubstCompile(Tcl_Interp *interp, const char *bytes,
			    size_t numBytes, int flags, int line,
			    Tcl_Size numBytes, int flags, Tcl_Size line,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclSubstOptions(Tcl_Interp *interp, int numOpts,
MODULE_SCOPE int	TclSubstOptions(Tcl_Interp *interp, Tcl_Size numOpts,
			    Tcl_Obj *const opts[], int *flagPtr);
MODULE_SCOPE void	TclSubstParse(Tcl_Interp *interp, const char *bytes,
			    size_t numBytes, int flags, Tcl_Parse *parsePtr,
			    Tcl_Size numBytes, int flags, Tcl_Parse *parsePtr,
			    Tcl_InterpState *statePtr);
MODULE_SCOPE int	TclSubstTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr,
			    int count, int *tokensLeftPtr, int line,
			    int *clNextOuter, const char *outerScript);
MODULE_SCOPE size_t	TclTrim(const char *bytes, size_t numBytes,
			    const char *trim, size_t numTrim, size_t *trimRight);
MODULE_SCOPE size_t	TclTrimLeft(const char *bytes, size_t numBytes,
			    const char *trim, size_t numTrim);
MODULE_SCOPE size_t	TclTrimRight(const char *bytes, size_t numBytes,
			    const char *trim, size_t numTrim);
			    Tcl_Size count, int *tokensLeftPtr, Tcl_Size line,
			    Tcl_Size *clNextOuter, const char *outerScript);
MODULE_SCOPE Tcl_Size	TclTrim(const char *bytes, Tcl_Size numBytes,
			    const char *trim, Tcl_Size numTrim,
			    Tcl_Size *trimRight);
MODULE_SCOPE Tcl_Size	TclTrimLeft(const char *bytes, Tcl_Size numBytes,
			    const char *trim, Tcl_Size numTrim);
MODULE_SCOPE Tcl_Size	TclTrimRight(const char *bytes, Tcl_Size numBytes,
			    const char *trim, Tcl_Size numTrim);
MODULE_SCOPE const char*TclGetCommandTypeName(Tcl_Command command);
MODULE_SCOPE int	TclObjInterpProc(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE void	TclRegisterCommandTypeName(
			    Tcl_ObjCmdProc *implementationProc,
			    const char *nameStr);
MODULE_SCOPE int	TclUtfCmp(const char *cs, const char *ct);
MODULE_SCOPE int	TclUtfCasecmp(const char *cs, const char *ct);
MODULE_SCOPE size_t	TclUtfCount(int ch);
#if TCL_UTF_MAX > 3
#   define TclUtfToUCS4 Tcl_UtfToUniChar
#   define TclUniCharToUCS4(src, ptr) (*ptr = *(src),1)
#   define TclUCS4Complete Tcl_UtfCharComplete
#   define TclChar16Complete(src, length) (((unsigned)((unsigned char)*(src) - 0xF0) < 5) \
	    ? ((length) >= 3) : Tcl_UtfCharComplete((src), (length)))
#else
    MODULE_SCOPE int	TclUtfToUCS4(const char *src, int *ucs4Ptr);
MODULE_SCOPE int	TclUtfCount(int ch);
    MODULE_SCOPE int	TclUniCharToUCS4(const Tcl_UniChar *src, int *ucs4Ptr);
#   define TclUCS4Complete(src, length) (((unsigned)((unsigned char)*(src) - 0xF0) < 5) \
	    ? ((length) >= 4) : Tcl_UtfCharComplete((src), (length)))
#   define TclChar16Complete Tcl_UtfCharComplete
#endif
MODULE_SCOPE Tcl_Obj *	TclpNativeToNormalized(void *clientData);
MODULE_SCOPE Tcl_Obj *	TclpFilesystemPathType(Tcl_Obj *pathPtr);
MODULE_SCOPE int	TclpDlopen(Tcl_Interp *interp, Tcl_Obj *pathPtr,
			    Tcl_LoadHandle *loadHandle,
			    Tcl_FSUnloadFileProc **unloadProcPtr, int flags);
MODULE_SCOPE int	TclpUtime(Tcl_Obj *pathPtr, struct utimbuf *tval);
#ifdef TCL_LOAD_FROM_MEMORY
MODULE_SCOPE void *	TclpLoadMemoryGetBuffer(Tcl_Interp *interp, int size);
MODULE_SCOPE void *	TclpLoadMemoryGetBuffer(Tcl_Interp *interp, size_t size);
MODULE_SCOPE int	TclpLoadMemory(Tcl_Interp *interp, void *buffer,
			    int size, int codeSize, Tcl_LoadHandle *loadHandle,
			    size_t size, Tcl_Size codeSize, Tcl_LoadHandle *loadHandle,
			    Tcl_FSUnloadFileProc **unloadProcPtr, int flags);
#endif
MODULE_SCOPE void	TclInitThreadStorage(void);
MODULE_SCOPE void	TclFinalizeThreadDataThread(void);
MODULE_SCOPE void	TclFinalizeThreadStorage(void);

#ifdef TCL_WIDE_CLICKS
MODULE_SCOPE Tcl_WideInt TclpGetWideClicks(void);
MODULE_SCOPE double	TclpWideClicksToNanoseconds(Tcl_WideInt clicks);
MODULE_SCOPE long long	TclpGetWideClicks(void);
MODULE_SCOPE double	TclpWideClicksToNanoseconds(long long clicks);
MODULE_SCOPE double	TclpWideClickInMicrosec(void);
#else
#   ifdef _WIN32
#	define TCL_WIDE_CLICKS 1
MODULE_SCOPE Tcl_WideInt TclpGetWideClicks(void);
MODULE_SCOPE long long	TclpGetWideClicks(void);
MODULE_SCOPE double	TclpWideClickInMicrosec(void);
#	define		TclpWideClicksToNanoseconds(clicks) \
				((double)(clicks) * TclpWideClickInMicrosec() * 1000)
#	define TclpWideClicksToNanoseconds(clicks) \
		((double)(clicks) * TclpWideClickInMicrosec() * 1000)
#   endif
#endif
MODULE_SCOPE Tcl_WideInt TclpGetMicroseconds(void);
MODULE_SCOPE long long	TclpGetMicroseconds(void);

MODULE_SCOPE int	TclZlibInit(Tcl_Interp *interp);
MODULE_SCOPE void *	TclpThreadCreateKey(void);
MODULE_SCOPE void	TclpThreadDeleteKey(void *keyPtr);
MODULE_SCOPE void	TclpThreadSetGlobalTSD(void *tsdKeyPtr, void *ptr);
MODULE_SCOPE void *	TclpThreadGetGlobalTSD(void *tsdKeyPtr);
MODULE_SCOPE void	TclErrorStackResetIf(Tcl_Interp *interp,
			    const char *msg, size_t length);
			    const char *msg, Tcl_Size length);
/* Tip 430 */
MODULE_SCOPE int    TclZipfs_Init(Tcl_Interp *interp);

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.
 */

MODULE_SCOPE int	TclIsSpaceProc(int byte);
#	define TclIsSpaceProcM(byte) \
		(((byte) > 0x20) ? 0 : TclIsSpaceProc(byte))
#define TclIsSpaceProcM(byte) \
    (((byte) > 0x20) ? 0 : TclIsSpaceProc(byte))

/*
 *----------------------------------------------------------------
 * Command procedures in the generic core:
 *----------------------------------------------------------------
 */

MODULE_SCOPE int	Tcl_AfterObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_AfterObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_AppendObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_AppendObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ApplyObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_ApplyObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Command TclInitArrayCmd(Tcl_Interp *interp);
MODULE_SCOPE Tcl_Command TclInitBinaryCmd(Tcl_Interp *interp);
MODULE_SCOPE int	Tcl_BreakObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_BreakObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_CatchObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_CatchObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_CdObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_CdObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Command TclInitChanCmd(Tcl_Interp *interp);
MODULE_SCOPE int	TclChanCreateObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclChanCreateObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclChanPostEventObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclChanPostEventObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclChanPopObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclChanPopObjCmd;
			    Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclChanPushObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclChanPushObjCmd;
			    Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE void	TclClockInit(Tcl_Interp *interp);
MODULE_SCOPE int	TclClockOldscanObjCmd(
MODULE_SCOPE Tcl_ObjCmdProc TclClockOldscanObjCmd;
			    void *clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_CloseObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_CloseObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc Tcl_ConcatObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ConcatObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_ConstObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ContinueObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_ContinueObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_TimerToken TclCreateAbsoluteTimerHandler(
			    Tcl_Time *timePtr, Tcl_TimerProc *proc,
			    void *clientData);
MODULE_SCOPE int	TclDefaultBgErrorHandlerObjCmd(
MODULE_SCOPE Tcl_ObjCmdProc TclDefaultBgErrorHandlerObjCmd;
			    void *clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Command TclInitDictCmd(Tcl_Interp *interp);
MODULE_SCOPE int	TclDictWithFinish(Tcl_Interp *interp, Var *varPtr,
			    Var *arrayPtr, Tcl_Obj *part1Ptr,
			    Tcl_Obj *part2Ptr, int index, int pathc,
			    Tcl_Obj *const pathv[], Tcl_Obj *keysPtr);
MODULE_SCOPE Tcl_Obj *	TclDictWithInit(Tcl_Interp *interp, Tcl_Obj *dictPtr,
			    int pathc, Tcl_Obj *const pathv[]);
MODULE_SCOPE int	Tcl_DisassembleObjCmd(void *clientData,
			    Tcl_Size pathc, Tcl_Obj *const pathv[]);
MODULE_SCOPE Tcl_ObjCmdProc Tcl_DisassembleObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_ObjCmdProc TclLoadIcuObjCmd;

/* Assemble command function */
MODULE_SCOPE int	Tcl_AssembleObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_AssembleObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclNRAssembleObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclNRAssembleObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Command TclInitEncodingCmd(Tcl_Interp *interp);
MODULE_SCOPE int	Tcl_EofObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_EofObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ErrorObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_ErrorObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_EvalObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_EvalObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ExecObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_ExecObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ExitObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_ExitObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ExprObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_ExprObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_FblockedObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_FblockedObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_FconfigureObjCmd(
MODULE_SCOPE Tcl_ObjCmdProc Tcl_FconfigureObjCmd;
			    void *clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_FcopyObjCmd(void *dummy,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_FcopyObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Command TclInitFileCmd(Tcl_Interp *interp);
MODULE_SCOPE int	Tcl_FileEventObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_FileEventObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_FlushObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_FlushObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ForObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_ForObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ForeachObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_ForeachObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_FormatObjCmd(void *dummy,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_FormatObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_GetsObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_GetsObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_GlobalObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_GlobalObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_GlobObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_GlobObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_IfObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_IfObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_IncrObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_IncrObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Command TclInitInfoCmd(Tcl_Interp *interp);
MODULE_SCOPE int	Tcl_InterpObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_InterpObjCmd;
			    Tcl_Interp *interp, int argc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_JoinObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_JoinObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LappendObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LappendObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LassignObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LassignObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LeditObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LindexObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LindexObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LinsertObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LinsertObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LlengthObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LlengthObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_ListObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ListObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LmapObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LmapObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LoadObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LoadObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LpopObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LpopObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LrangeObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LrangeObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LremoveObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LremoveObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LrepeatObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LrepeatObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LreplaceObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LreplaceObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LreverseObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LreverseObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LsearchObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LsearchObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LseqObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LsetObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LsetObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LsortObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LsortObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Command TclInitNamespaceCmd(Tcl_Interp *interp);
MODULE_SCOPE int	TclNamespaceEnsembleCmd(void *dummy,
MODULE_SCOPE Tcl_ObjCmdProc TclNamespaceEnsembleCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_OpenObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_OpenObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_PackageObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_PackageObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_PidObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_PidObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Command TclInitPrefixCmd(Tcl_Interp *interp);
MODULE_SCOPE int	Tcl_PutsObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_PutsObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_PwdObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_PwdObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ReadObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_ReadObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_RegexpObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_RegexpObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_RegsubObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_RegsubObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_RenameObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_RenameObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_RepresentationCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_RepresentationCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ReturnObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_ReturnObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ScanObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_ScanObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_SeekObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_SeekObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_SetObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_SetObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_SplitObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_SplitObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_SocketObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_SocketObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_SourceObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_SourceObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Command TclInitStringCmd(Tcl_Interp *interp);
MODULE_SCOPE int	Tcl_SubstObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_SubstObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_SwitchObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_SwitchObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_TellObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_TellObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ThrowObjCmd(void *dummy, Tcl_Interp *interp,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_ThrowObjCmd;
			    int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_TimeObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_TimeObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_TimeRateObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_TimeRateObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_TraceObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_TraceObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_TryObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_TryObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_UnloadObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_UnloadObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_UnsetObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_UnsetObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_UpdateObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_UpdateObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_UplevelObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_UplevelObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_UpvarObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_UpvarObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_VariableObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_VariableObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_VwaitObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_VwaitObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_WhileObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc Tcl_WhileObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);

/*
 *----------------------------------------------------------------
 * Compilation procedures for commands in the generic core:
 *----------------------------------------------------------------
 */

MODULE_SCOPE int	TclCompileAppendCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileAppendCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileArrayExistsCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileArrayExistsCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileArraySetCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileArraySetCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileArrayUnsetCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileArrayUnsetCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBreakCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileBreakCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileCatchCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileCatchCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileClockClicksCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileClockClicksCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileClockReadingCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileClockReadingCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileConcatCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileConcatCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileContinueCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileConstCmd;
MODULE_SCOPE CompileProc TclCompileContinueCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictAppendCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileDictAppendCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictCreateCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileDictCreateCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictExistsCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileDictExistsCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictForCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileDictForCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictGetCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileDictGetCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictGetWithDefaultCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileDictGetWithDefaultCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictIncrCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileDictIncrCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictLappendCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileDictLappendCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictMapCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileDictMapCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictMergeCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileDictMergeCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictSetCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileDictSetCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictUnsetCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileDictUnsetCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictUpdateCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileDictUpdateCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictWithCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileDictWithCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileEnsemble(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileEnsemble;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileErrorCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileErrorCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileExprCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileExprCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileForCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileForCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileForeachCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileForeachCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileFormatCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileFormatCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileGlobalCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileGlobalCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileIfCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileIfCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileInfoCommandsCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileInfoCommandsCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileInfoCoroutineCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileInfoCoroutineCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileInfoExistsCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileInfoExistsCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileInfoLevelCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileInfoLevelCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileInfoObjectClassCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileInfoObjectClassCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileInfoObjectIsACmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileInfoObjectIsACmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileInfoObjectNamespaceCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileInfoObjectNamespaceCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileIncrCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileIncrCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLappendCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileLappendCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLassignCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileLassignCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLindexCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileLindexCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLinsertCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileLinsertCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileListCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileListCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLlengthCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileLlengthCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLmapCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileLmapCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLrangeCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileLrangeCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLreplaceCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileLreplaceCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLsetCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileLsetCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileNamespaceCodeCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileNamespaceCodeCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileNamespaceCurrentCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileNamespaceCurrentCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileNamespaceOriginCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileNamespaceOriginCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileNamespaceQualifiersCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileNamespaceQualifiersCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileNamespaceTailCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileNamespaceTailCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileNamespaceUpvarCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileNamespaceUpvarCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileNamespaceWhichCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileNamespaceWhichCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileNoOp(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileNoOp;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileObjectNextCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileObjectNextCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileObjectNextToCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileObjectNextToCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileObjectSelfCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileObjectSelfCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileRegexpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileRegexpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileRegsubCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileRegsubCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileReturnCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileReturnCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileSetCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileSetCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringCatCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStringCatCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringCmpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStringCmpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringEqualCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStringEqualCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringFirstCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStringFirstCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringIndexCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStringIndexCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringInsertCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStringInsertCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringIsCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStringIsCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringLastCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStringLastCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringLenCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStringLenCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringMapCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStringMapCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringMatchCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStringMatchCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringRangeCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStringRangeCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringReplaceCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStringReplaceCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringToLowerCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStringToLowerCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringToTitleCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStringToTitleCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringToUpperCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStringToUpperCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringTrimCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStringTrimCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringTrimLCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStringTrimLCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringTrimRCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStringTrimRCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileSubstCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileSubstCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileSwitchCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileSwitchCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileTailcallCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileTailcallCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileThrowCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileThrowCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileTryCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileTryCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileUnsetCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileUnsetCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileUpvarCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileUpvarCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileVariableCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileVariableCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileWhileCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileWhileCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileYieldCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileYieldCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileYieldToCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileYieldToCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasic0ArgCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileBasic0ArgCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasic1ArgCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileBasic1ArgCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasic2ArgCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileBasic2ArgCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasic3ArgCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileBasic3ArgCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasic0Or1ArgCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileBasic0Or1ArgCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasic1Or2ArgCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileBasic1Or2ArgCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasic2Or3ArgCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileBasic2Or3ArgCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasic0To2ArgCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileBasic0To2ArgCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasic1To3ArgCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileBasic1To3ArgCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasicMin0ArgCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileBasicMin0ArgCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasicMin1ArgCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileBasicMin1ArgCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasicMin2ArgCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileBasicMin2ArgCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);

MODULE_SCOPE int	TclInvertOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclInvertOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileInvertOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
MODULE_SCOPE CompileProc TclCompileInvertOpCmd;

			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclNotOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclNotOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileNotOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileNotOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclAddOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclAddOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileAddOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileAddOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclMulOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclMulOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileMulOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileMulOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclAndOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclAndOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileAndOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileAndOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclOrOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclOrOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileOrOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileOrOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclXorOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclXorOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileXorOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileXorOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclPowOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclPowOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompilePowOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompilePowOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclLshiftOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclLshiftOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileLshiftOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileLshiftOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclRshiftOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclRshiftOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileRshiftOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileRshiftOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclModOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclModOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileModOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileModOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclNeqOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclNeqOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileNeqOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileNeqOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclStrneqOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclStrneqOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileStrneqOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStrneqOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclInOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclInOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileInOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileInOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclNiOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclNiOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileNiOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileNiOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclMinusOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclMinusOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileMinusOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileMinusOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclDivOpCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc TclDivOpCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileDivOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileDivOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLessOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileLessOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLeqOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileLeqOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileGreaterOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileGreaterOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileGeqOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileGeqOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileEqOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileEqOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStreqOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStreqOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStrLtOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStrLtOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStrLeOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStrLeOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStrGtOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStrGtOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStrGeOpCmd(Tcl_Interp *interp,
MODULE_SCOPE CompileProc TclCompileStrGeOpCmd;
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);

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

/*
 * Routines that provide the [string] ensemble functionality. Possible
 * candidates for public interface.
 */

MODULE_SCOPE Tcl_Obj *	TclStringCat(Tcl_Interp *interp, int objc,
MODULE_SCOPE Tcl_Obj *	TclStringCat(Tcl_Interp *interp, Tcl_Size objc,
			    Tcl_Obj *const objv[], int flags);
MODULE_SCOPE Tcl_Obj *	TclStringFirst(Tcl_Obj *needle, Tcl_Obj *haystack,
			    size_t start);
			    Tcl_Size start);
MODULE_SCOPE Tcl_Obj *	TclStringLast(Tcl_Obj *needle, Tcl_Obj *haystack,
			    size_t last);
			    Tcl_Size last);
MODULE_SCOPE Tcl_Obj *	TclStringRepeat(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    size_t count, int flags);
			    Tcl_Size count, int flags);
MODULE_SCOPE Tcl_Obj *	TclStringReplace(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    size_t first, size_t count, Tcl_Obj *insertPtr,
			    Tcl_Size first, Tcl_Size count, Tcl_Obj *insertPtr,
			    int flags);
MODULE_SCOPE Tcl_Obj *	TclStringReverse(Tcl_Obj *objPtr, int flags);

/* Flag values for the [string] ensemble functions. */

#define TCL_STRING_MATCH_NOCASE TCL_MATCH_NOCASE /* (1<<0) in tcl.h */
#define TCL_STRING_IN_PLACE (1<<1)

/*
 * Functions defined in generic/tclVar.c and currently exported only for use
 * by the bytecode compiler and engine. Some of these could later be placed in
 * the public interface.
 */

MODULE_SCOPE Var *	TclObjLookupVarEx(Tcl_Interp * interp,
			    Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags,
			    const char *msg, const int createPart1,
			    const int createPart2, Var **arrayPtrPtr);
			    const char *msg, int createPart1,
			    int createPart2, Var **arrayPtrPtr);
MODULE_SCOPE Var *	TclLookupArrayElement(Tcl_Interp *interp,
			    Tcl_Obj *arrayNamePtr, Tcl_Obj *elNamePtr,
			    const int flags, const char *msg,
			    const int createPart1, const int createPart2,
			    int flags, const char *msg,
			    int createPart1, int createPart2,
			    Var *arrayPtr, int index);
MODULE_SCOPE Tcl_Obj *	TclPtrGetVarIdx(Tcl_Interp *interp,
			    Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr,
			    Tcl_Obj *part2Ptr, const int flags, int index);
			    Tcl_Obj *part2Ptr, int flags, int index);
MODULE_SCOPE Tcl_Obj *	TclPtrSetVarIdx(Tcl_Interp *interp,
			    Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr,
			    Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr,
			    const int flags, int index);
			    int flags, int index);
MODULE_SCOPE Tcl_Obj *	TclPtrIncrObjVarIdx(Tcl_Interp *interp,
			    Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr,
			    Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr,
			    const int flags, int index);
			    int flags, int index);
MODULE_SCOPE int	TclPtrObjMakeUpvarIdx(Tcl_Interp *interp,
			    Var *otherPtr, Tcl_Obj *myNamePtr, int myFlags,
			    int index);
MODULE_SCOPE int	TclPtrUnsetVarIdx(Tcl_Interp *interp, Var *varPtr,
			    Var *arrayPtr, Tcl_Obj *part1Ptr,
			    Tcl_Obj *part2Ptr, const int flags,
			    Tcl_Obj *part2Ptr, int flags,
			    int index);
MODULE_SCOPE void	TclInvalidateNsPath(Namespace *nsPtr);
MODULE_SCOPE void	TclFindArrayPtrElements(Var *arrayPtr,
			    Tcl_HashTable *tablePtr);

/*
 * The new extended interface to the variable traces.
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097







4098
4099
4100
4101
4102
4103
4104
4105
4078
4079
4080
4081
4082
4083
4084







4085
4086
4087
4088
4089
4090
4091

4092
4093
4094
4095
4096
4097
4098







-
-
-
-
-
-
-
+
+
+
+
+
+
+
-








MODULE_SCOPE int	TclFullFinalizationRequested(void);

/*
 * TIP #542
 */

MODULE_SCOPE size_t TclUniCharLen(const Tcl_UniChar *uniStr);
MODULE_SCOPE int TclUniCharNcmp(const Tcl_UniChar *ucs,
				const Tcl_UniChar *uct, size_t numChars);
MODULE_SCOPE int TclUniCharNcasecmp(const Tcl_UniChar *ucs,
				const Tcl_UniChar *uct, size_t numChars);
MODULE_SCOPE int TclUniCharCaseMatch(const Tcl_UniChar *uniStr,
				const Tcl_UniChar *uniPattern, int nocase);
MODULE_SCOPE size_t	TclUniCharLen(const Tcl_UniChar *uniStr);
MODULE_SCOPE int	TclUniCharNcmp(const Tcl_UniChar *ucs,
			    const Tcl_UniChar *uct, size_t numChars);
MODULE_SCOPE int	TclUniCharNcasecmp(const Tcl_UniChar *ucs,
			    const Tcl_UniChar *uct, size_t numChars);
MODULE_SCOPE int	TclUniCharCaseMatch(const Tcl_UniChar *uniStr,
			    const Tcl_UniChar *uniPattern, int nocase);


/*
 * Just for the purposes of command-type registration.
 */

MODULE_SCOPE Tcl_ObjCmdProc TclEnsembleImplementationCmd;
MODULE_SCOPE Tcl_ObjCmdProc TclAliasObjCmd;
4129
4130
4131
4132
4133
4134
4135
4136


4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151


4152








4153
4154
4155

































4156
4157
4158
4159
4160
4161
4162
4122
4123
4124
4125
4126
4127
4128

4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143


4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155


4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195







-
+
+













-
-
+
+

+
+
+
+
+
+
+
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







} TclProcessWaitStatus;

MODULE_SCOPE Tcl_Command TclInitProcessCmd(Tcl_Interp *interp);
MODULE_SCOPE void	TclProcessCreated(Tcl_Pid pid);
MODULE_SCOPE TclProcessWaitStatus TclProcessWait(Tcl_Pid pid, int options,
			    int *codePtr, Tcl_Obj **msgObjPtr,
			    Tcl_Obj **errorObjPtr);
MODULE_SCOPE int TclClose(Tcl_Interp *,	Tcl_Channel chan);
MODULE_SCOPE int	TclClose(Tcl_Interp *, Tcl_Channel chan);

/*
 * TIP #508: [array default]
 */

MODULE_SCOPE void	TclInitArrayVar(Var *arrayPtr);
MODULE_SCOPE Tcl_Obj *	TclGetArrayDefault(Var *arrayPtr);

/*
 * Utility routines for encoding index values as integers. Used by both
 * some of the command compilers and by [lsort] and [lsearch].
 */

MODULE_SCOPE int	TclIndexEncode(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    size_t before, size_t after, int *indexPtr);
MODULE_SCOPE size_t	TclIndexDecode(int encoded, size_t endValue);
			    int before, int after, int *indexPtr);
MODULE_SCOPE Tcl_Size	TclIndexDecode(int encoded, Tcl_Size endValue);

/*
 * Error message utility functions
 */
MODULE_SCOPE int	TclCommandWordLimitError(Tcl_Interp *interp,
			    Tcl_Size count);

#endif /* TCL_MAJOR_VERSION > 8 */

/* Constants used in index value encoding routines. */
#define TCL_INDEX_END           ((size_t)-2)
#define TCL_INDEX_START         ((size_t)0)
#define TCL_INDEX_END	((Tcl_Size)-2)
#define TCL_INDEX_START	((Tcl_Size)0)

/*
 *----------------------------------------------------------------------
 *
 * TclScaleTime --
 *
 *	TIP #233 (Virtualized Time): Wrapper around the time virutalisation
 *	rescale function to hide the binding of the clientData.
 *
 *	This is static inline code; it's like a macro, but a function. It's
 *	used because this is a piece of code that ends up in places that are a
 *	bit performance sensitive.
 *
 * Results:
 *	None
 *
 * Side effects:
 *	Updates the time structure (given as an argument) with what the time
 *	should be after virtualisation.
 *
 *----------------------------------------------------------------------
 */

static inline void
TclScaleTime(
    Tcl_Time *timePtr)
{
    if (timePtr != NULL) {
	tclScaleTimeProcPtr(timePtr, tclTimeClientData);
    }
}

/*
 *----------------------------------------------------------------
 * Macros used by the Tcl core to create and release Tcl objects.
 * TclNewObj(objPtr) creates a new object denoting an empty string.
 * TclDecrRefCount(objPtr) decrements the object's reference count, and frees
 * the object if its reference count is zero. These macros are inline versions
4196
4197
4198
4199
4200
4201
4202
4203

4204
4205
4206

4207
4208
4209
4210
4211
4212
4213
4214
4215
4216






4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239













4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256

4257
4258
4259
4260
4261
4262
4263
4229
4230
4231
4232
4233
4234
4235

4236
4237
4238

4239
4240
4241
4242
4243






4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259













4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288

4289
4290
4291
4292
4293
4294
4295
4296







-
+


-
+




-
-
-
-
-
-
+
+
+
+
+
+










-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
















-
+







#  define TclIncrObjsFreed() \
    tclObjsFreed++
#else
#  define TclIncrObjsAllocated()
#  define TclIncrObjsFreed()
#endif /* TCL_COMPILE_STATS */

#  define TclAllocObjStorage(objPtr)		\
#  define TclAllocObjStorage(objPtr) \
	TclAllocObjStorageEx(NULL, (objPtr))

#  define TclFreeObjStorage(objPtr)		\
#  define TclFreeObjStorage(objPtr) \
	TclFreeObjStorageEx(NULL, (objPtr))

#ifndef TCL_MEM_DEBUG
# define TclNewObj(objPtr) \
    TclIncrObjsAllocated(); \
    TclAllocObjStorage(objPtr); \
    (objPtr)->refCount = 0; \
    (objPtr)->bytes    = &tclEmptyString; \
    (objPtr)->length   = 0; \
    (objPtr)->typePtr  = NULL; \
    TclIncrObjsAllocated();						\
    TclAllocObjStorage(objPtr);						\
    (objPtr)->refCount = 0;						\
    (objPtr)->bytes    = &tclEmptyString;				\
    (objPtr)->length   = 0;						\
    (objPtr)->typePtr  = NULL;						\
    TCL_DTRACE_OBJ_CREATE(objPtr)

/*
 * Invalidate the string rep first so we can use the bytes value for our
 * pointer chain, and signal an obj deletion (as opposed to shimmering) with
 * 'length == TCL_INDEX_NONE'.
 * Use empty 'if ; else' to handle use in unbraced outer if/else conditions.
 */

# define TclDecrRefCount(objPtr) \
    if ((objPtr)->refCount-- > 1) ; else { \
	if (!(objPtr)->typePtr || !(objPtr)->typePtr->freeIntRepProc) { \
	    TCL_DTRACE_OBJ_FREE(objPtr); \
	    if ((objPtr)->bytes \
		    && ((objPtr)->bytes != &tclEmptyString)) { \
		Tcl_Free((objPtr)->bytes); \
	    } \
	    (objPtr)->length = TCL_INDEX_NONE; \
	    TclFreeObjStorage(objPtr); \
	    TclIncrObjsFreed(); \
	} else { \
	    TclFreeObj(objPtr); \
	} \
    if ((objPtr)->refCount-- > 1) ; else {				\
	if (!(objPtr)->typePtr || !(objPtr)->typePtr->freeIntRepProc) {	\
	    TCL_DTRACE_OBJ_FREE(objPtr);				\
	    if ((objPtr)->bytes						\
		    && ((objPtr)->bytes != &tclEmptyString)) {		\
		Tcl_Free((objPtr)->bytes);				\
	    }								\
	    (objPtr)->length = TCL_INDEX_NONE;				\
	    TclFreeObjStorage(objPtr);					\
	    TclIncrObjsFreed();						\
	} else {							\
	    TclFreeObj(objPtr);						\
	}								\
    }

#if TCL_THREADS && !defined(USE_THREAD_ALLOC)
#   define USE_THREAD_ALLOC 1
#endif

#if defined(PURIFY)

/*
 * The PURIFY mode is like the regular mode, but instead of doing block
 * Tcl_Obj allocation and keeping a freed list for efficiency, it always
 * allocates and frees a single Tcl_Obj so that tools like Purify can better
 * track memory leaks.
 */

#  define TclAllocObjStorageEx(interp, objPtr) \
	(objPtr) = (Tcl_Obj *) Tcl_Alloc(sizeof(Tcl_Obj))
	(objPtr) = (Tcl_Obj *)Tcl_Alloc(sizeof(Tcl_Obj))

#  define TclFreeObjStorageEx(interp, objPtr) \
	Tcl_Free(objPtr)

#undef USE_THREAD_ALLOC
#undef USE_TCLALLOC
#elif TCL_THREADS && defined(USE_THREAD_ALLOC)
4339
4340
4341
4342
4343
4344
4345
4346
4347


4348
4349
4350


4351
4352
4353
4354
4355
4356
4357
4372
4373
4374
4375
4376
4377
4378


4379
4380
4381


4382
4383
4384
4385
4386
4387
4388
4389
4390







-
-
+
+

-
-
+
+







	(objPtr) = tclFreeObjList;					\
	tclFreeObjList = (Tcl_Obj *)					\
		tclFreeObjList->internalRep.twoPtrValue.ptr1;		\
	Tcl_MutexUnlock(&tclObjMutex);					\
    } while (0)

#  define TclFreeObjStorageEx(interp, objPtr) \
    do {							       \
	Tcl_MutexLock(&tclObjMutex);				       \
    do {								\
	Tcl_MutexLock(&tclObjMutex);					\
	(objPtr)->internalRep.twoPtrValue.ptr1 = (void *) tclFreeObjList; \
	tclFreeObjList = (objPtr);				       \
	Tcl_MutexUnlock(&tclObjMutex);				       \
	tclFreeObjList = (objPtr);					\
	Tcl_MutexUnlock(&tclObjMutex);					\
    } while (0)
#endif

#else /* TCL_MEM_DEBUG */
MODULE_SCOPE void	TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
			    int line);

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
4436
4437
4438
4439
4440

4441
4442

4443
4444

4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459

4460
4461
4462
4463
4464
4465
4466
4467
4468






4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488








4489
4490
4491
4492
4493
4494
4495
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
4436


4437
4438



4439
4440
4441


4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470



















4471

4472


4473


4474







4475
4476
4477
4478
4479
4480
4481

4482
4483
4484
4485






4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503








4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518







-
-
-





-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+

+

-
-



+
+
+

-
-
+
+
-
-
-
+
+

-
-
+
+

+
+
+
+
+
+
+
+
+
+
















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
+
-
-
+
-
-
+
-
-
-
-
-
-
-







-
+



-
-
-
-
-
-
+
+
+
+
+
+












-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+








# define TclNewObj(objPtr) \
    TclDbNewObj(objPtr, __FILE__, __LINE__);

# define TclDecrRefCount(objPtr) \
    Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__)

# define TclNewListObjDirect(objc, objv) \
    TclDbNewListObjDirect(objc, objv, __FILE__, __LINE__)

#undef USE_THREAD_ALLOC
#endif /* TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to set a Tcl_Obj's string representation to a
 * copy of the "len" bytes starting at "bytePtr". This code works even if the
 * byte array contains NULLs as long as the length is correct. Because "len"
 * is referenced multiple times, it should be as simple an expression as
 * possible. The ANSI C "prototype" for this macro is:
 * Macros used by the Tcl core to set a Tcl_Obj's string representation to a
 * copy of the "len" bytes starting at "bytePtr". The value of "len" must
 * not be negative.  When "len" is 0, then it is acceptable to pass
 * "bytePtr" = NULL.  When "len" > 0, "bytePtr" must not be NULL, and it
 * must point to a location from which "len" bytes may be read.  These
 * constraints are not checked here.  The validity of the bytes copied
 * as a value string representation is also not verififed.  This macro
 * must not be called while "objPtr" is being freed or when "objPtr"
 * already has a string representation.  The caller must use
 * this macro properly.  Improper use can lead to dangerous results.
 * Because "len" is referenced multiple times, take care that it is an
 * expression with the same value each use.
 *
 * The ANSI C "prototypes" for these macros are:
 *
 * MODULE_SCOPE void TclInitEmptyStringRep(Tcl_Obj *objPtr);
 * MODULE_SCOPE void TclInitStringRep(Tcl_Obj *objPtr, char *bytePtr, size_t len);
 * MODULE_SCOPE void TclAttemptInitStringRep(Tcl_Obj *objPtr, char *bytePtr, size_t len);
 *
 * This macro should only be called on an unshared objPtr where
 *  objPtr->typePtr->freeIntRepProc == NULL
 *----------------------------------------------------------------
 */

#define TclInitEmptyStringRep(objPtr) \
    ((objPtr)->length = (((objPtr)->bytes = &tclEmptyString), 0))

#define TclInitStringRep(objPtr, bytePtr, len) \
    if ((len) == 0) { \
	(objPtr)->bytes	 = &tclEmptyString; \
    if ((len) == 0) {							\
	TclInitEmptyStringRep(objPtr);					\
	(objPtr)->length = 0; \
    } else { \
	(objPtr)->bytes = (char *)Tcl_Alloc((len) + 1); \
    } else {								\
	(objPtr)->bytes = (char *)Tcl_Alloc((len) + 1U);		\
	memcpy((objPtr)->bytes, (bytePtr) ? (bytePtr) : &tclEmptyString, (len)); \
	(objPtr)->bytes[len] = '\0'; \
	(objPtr)->length = (len); \
	(objPtr)->bytes[len] = '\0';					\
	(objPtr)->length = (len);					\
    }

#define TclAttemptInitStringRep(objPtr, bytePtr, len) \
    ((((len) == 0) ? (							\
	TclInitEmptyStringRep(objPtr)					\
    ) : (								\
	(objPtr)->bytes = (char *)Tcl_AttemptAlloc((len) + 1U),		\
	(objPtr)->length = ((objPtr)->bytes) ?				\
		(memcpy((objPtr)->bytes, (bytePtr) ? (bytePtr) : &tclEmptyString, (len)), \
		(objPtr)->bytes[len] = '\0', (len)) : (-1)		\
    )), (objPtr)->bytes)

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to get the string representation's byte array
 * pointer from a Tcl_Obj. This is an inline version of Tcl_GetString(). The
 * macro's expression result is the string rep's byte pointer which might be
 * NULL. The bytes referenced by this pointer must not be modified by the
 * caller. The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE char *	TclGetString(Tcl_Obj *objPtr);
 *----------------------------------------------------------------
 */

#define TclGetString(objPtr) \
    ((objPtr)->bytes? (objPtr)->bytes : Tcl_GetString(objPtr))

#if 0
   static inline char *TclGetStringFromObj(Tcl_Obj *objPtr, size_t *lenPtr) {
      char *response = Tcl_GetString(objPtr);
      *(lenPtr) = objPtr->length;
      return response;
   }
   static inline Tcl_UniChar *TclGetUnicodeFromObj(Tcl_Obj *objPtr, size_t *lenPtr) {
      Tcl_UniChar *response = Tcl_GetUnicodeFromObj(objPtr, NULL);
      *(lenPtr) = *((size_t *) (objPtr)->internalRep.twoPtrValue.ptr1);
      return response;
   }
   static inline unsigned char *TclGetByteArrayFromObj(Tcl_Obj *objPtr, size_t *lenPtr) {
      unsigned char *response = Tcl_GetByteArrayFromObj(objPtr, NULL);
      if (response) {
          *(lenPtr) = *((size_t *) (objPtr)->internalRep.twoPtrValue.ptr1 + 1);
      }
      return response;
   }
#else
#define TclGetStringFromObj(objPtr, lenPtr) \
    (((objPtr)->bytes \
    ((objPtr)->bytes							\
	    ? NULL : Tcl_GetString((objPtr)), \
	    *(lenPtr) = (objPtr)->length, (objPtr)->bytes))
	    ? (*(lenPtr) = (objPtr)->length, (objPtr)->bytes)		\
#define TclGetUnicodeFromObj(objPtr, lenPtr) \
    (Tcl_GetUnicodeFromObj((objPtr), NULL), \
	    : (Tcl_GetStringFromObj)((objPtr), (lenPtr)))
	    *(lenPtr) = *((size_t *) (objPtr)->internalRep.twoPtrValue.ptr1), \
	    Tcl_GetUnicodeFromObj((objPtr), NULL))
#define TclGetByteArrayFromObj(objPtr, lenPtr) \
    (Tcl_GetByteArrayFromObj((objPtr), NULL) ? \
	(*(lenPtr) = *((size_t *) (objPtr)->internalRep.twoPtrValue.ptr1 + 1), \
	(unsigned char *)(((size_t *) (objPtr)->internalRep.twoPtrValue.ptr1) + 3)) : NULL)
#endif

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to clean out an object's internal
 * representation. Does not actually reset the rep's bytes. The ANSI C
 * "prototype" for this macro is:
 *
 * MODULE_SCOPE void	TclFreeIntRep(Tcl_Obj *objPtr);
 * MODULE_SCOPE void	TclFreeInternalRep(Tcl_Obj *objPtr);
 *----------------------------------------------------------------
 */

#define TclFreeIntRep(objPtr) \
    if ((objPtr)->typePtr != NULL) { \
	if ((objPtr)->typePtr->freeIntRepProc != NULL) { \
	    (objPtr)->typePtr->freeIntRepProc(objPtr); \
	} \
	(objPtr)->typePtr = NULL; \
#define TclFreeInternalRep(objPtr) \
    if ((objPtr)->typePtr != NULL) {					\
	if ((objPtr)->typePtr->freeIntRepProc != NULL) {		\
	    (objPtr)->typePtr->freeIntRepProc(objPtr);			\
	}								\
	(objPtr)->typePtr = NULL;					\
    }

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to clean out an object's string representation.
 * The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE void	TclInvalidateStringRep(Tcl_Obj *objPtr);
 *----------------------------------------------------------------
 */

#define TclInvalidateStringRep(objPtr) \
    do { \
	Tcl_Obj *_isobjPtr = (Tcl_Obj *)(objPtr); \
	if (_isobjPtr->bytes != NULL) { \
	    if (_isobjPtr->bytes != &tclEmptyString) { \
		Tcl_Free((char *)_isobjPtr->bytes); \
	    } \
	    _isobjPtr->bytes = NULL; \
	} \
    do {								\
	Tcl_Obj *_isobjPtr = (Tcl_Obj *)(objPtr);			\
	if (_isobjPtr->bytes != NULL) {					\
	    if (_isobjPtr->bytes != &tclEmptyString) {			\
		Tcl_Free((char *)_isobjPtr->bytes);			\
	    }								\
	    _isobjPtr->bytes = NULL;					\
	}								\
    } while (0)

/*
 * These form part of the native filesystem support. They are needed here
 * because we have a few native filesystem functions (which are the same for
 * win/unix) in this file.
 */
4524
4525
4526
4527
4528
4529
4530
4531
4532


4533
4534
4535
4536
4537
4538
4539
4547
4548
4549
4550
4551
4552
4553


4554
4555
4556
4557
4558
4559
4560
4561
4562







-
-
+
+







 *
 * MODULE_SCOPE void	TclUnpackBignum(Tcl_Obj *objPtr, mp_int bignum);
 *----------------------------------------------------------------
 */

#define TclUnpackBignum(objPtr, bignum) \
    do {								\
	Tcl_Obj *bignumObj = (objPtr);				\
	int bignumPayload =					\
	Tcl_Obj *bignumObj = (objPtr);					\
	int bignumPayload =						\
		PTR2INT(bignumObj->internalRep.twoPtrValue.ptr2);	\
	if (bignumPayload == -1) {					\
	    (bignum) = *((mp_int *) bignumObj->internalRep.twoPtrValue.ptr1); \
	} else {							\
	    (bignum).dp = (mp_digit *)bignumObj->internalRep.twoPtrValue.ptr1;	\
	    (bignum).sign = bignumPayload >> 30;			\
	    (bignum).alloc = (bignumPayload >> 15) & 0x7FFF;		\
4566
4567
4568
4569
4570
4571
4572
4573

4574
4575
4576

4577
4578
4579
4580
4581
4582

4583
4584
4585
4586
4587
4588
4589
4590
4591
4592


4593
4594
4595
4596
4597
4598
4599


4600
4601
4602
4603
4604

4605
4606
4607
4608
4609
4610
4611
4589
4590
4591
4592
4593
4594
4595

4596
4597
4598

4599




4600

4601
4602
4603
4604
4605
4606





4607
4608
4609
4610





4611
4612
4613
4614
4615
4616

4617
4618
4619
4620
4621
4622
4623
4624







-
+


-
+
-
-
-
-

-
+





-
-
-
-
-
+
+


-
-
-
-
-
+
+




-
+







#endif

/* Token growth tuning, default to the general value. */
#ifndef TCL_MIN_TOKEN_GROWTH
#define TCL_MIN_TOKEN_GROWTH TCL_MIN_GROWTH/sizeof(Tcl_Token)
#endif

#define TCL_MAX_TOKENS (int)(UINT_MAX / sizeof(Tcl_Token))
/* TODO - code below does not check for integer overflow */
#define TclGrowTokenArray(tokenPtr, used, available, append, staticPtr)	\
    do {								\
	int _needed = (used) + (append);					\
	Tcl_Size _needed = (used) + (append);				\
	if (_needed > TCL_MAX_TOKENS) {					\
	    Tcl_Panic("max # of tokens for a Tcl parse (%d) exceeded",	\
		    TCL_MAX_TOKENS);					\
	}								\
	if (_needed > (available)) {					\
	    int allocated = 2 * _needed;					\
	    Tcl_Size allocated = 2 * _needed;				\
	    Tcl_Token *oldPtr = (tokenPtr);				\
	    Tcl_Token *newPtr;						\
	    if (oldPtr == (staticPtr)) {				\
		oldPtr = NULL;						\
	    }								\
	    if (allocated > TCL_MAX_TOKENS) {				\
		allocated = TCL_MAX_TOKENS;				\
	    }								\
	    newPtr = (Tcl_Token *) Tcl_AttemptRealloc((char *) oldPtr,	\
		    (allocated * sizeof(Tcl_Token)));	\
	    newPtr = (Tcl_Token *)Tcl_AttemptRealloc((char *) oldPtr,	\
		    allocated * sizeof(Tcl_Token));			\
	    if (newPtr == NULL) {					\
		allocated = _needed + (append) + TCL_MIN_TOKEN_GROWTH;	\
		if (allocated > TCL_MAX_TOKENS) {			\
		    allocated = TCL_MAX_TOKENS;				\
		}							\
		newPtr = (Tcl_Token *) Tcl_Realloc((char *) oldPtr,	\
			(allocated * sizeof(Tcl_Token))); \
		newPtr = (Tcl_Token *)Tcl_Realloc((char *) oldPtr,	\
			allocated * sizeof(Tcl_Token));			\
	    }								\
	    (available) = allocated;					\
	    if (oldPtr == NULL) {					\
		memcpy(newPtr, staticPtr,				\
			((used) * sizeof(Tcl_Token)));		\
			(used) * sizeof(Tcl_Token));			\
	    }								\
	    (tokenPtr) = newPtr;					\
	}								\
    } while (0)

#define TclGrowParseTokenArray(parsePtr, append)			\
    TclGrowTokenArray((parsePtr)->tokenPtr, (parsePtr)->numTokens,	\
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630


4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647



4648
4649
4650
4651
4652
4653
4654
4655
4656
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
4688
4689





4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4633
4634
4635
4636
4637
4638
4639

4640


4641
4642
4643






4644
4645
4646
4647
4648
4649
4650
4651


4652
4653
4654
4655
4656
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
4688
4689
4690
4691

















4692
4693
4694
4695
4696
4697
4698







-

-
-
+
+

-
-
-
-
-
-








-
-
+
+
+



-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+


-
-
-
-
-

















-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







 * string handling. The macro's expression result is 1 for the 1-byte case or
 * the result of Tcl_UtfToUniChar. The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE int	TclUtfToUniChar(const char *string, Tcl_UniChar *ch);
 *----------------------------------------------------------------
 */

#if TCL_UTF_MAX > 3
#define TclUtfToUniChar(str, chPtr) \
	(((UCHAR(*(str))) < 0x80) ?		\
	    ((*(chPtr) = UCHAR(*(str))), 1)	\
	(((UCHAR(*(str))) < 0x80) ?					\
	    ((*(chPtr) = UCHAR(*(str))), 1)				\
	    : Tcl_UtfToUniChar(str, chPtr))
#else
#define TclUtfToUniChar(str, chPtr) \
	((((unsigned char) *(str)) < 0x80) ?		\
	    ((*(chPtr) = (unsigned char) *(str)), 1)	\
	    : Tcl_UtfToChar16(str, chPtr))
#endif

/*
 *----------------------------------------------------------------
 * Macro counterpart of the Tcl_NumUtfChars() function. To be used in speed-
 * -sensitive points where it pays to avoid a function call in the common case
 * of counting along a string of all one-byte characters.  The ANSI C
 * "prototype" for this macro is:
 *
 * MODULE_SCOPE void	TclNumUtfChars(int numChars, const char *bytes,
 *				size_t numBytes);
 * MODULE_SCOPE void	TclNumUtfCharsM(Tcl_Size numChars, const char *bytes,
 *				Tcl_Size numBytes);
 * numBytes must be >= 0
 *----------------------------------------------------------------
 */

#define TclNumUtfChars(numChars, bytes, numBytes) \
    do { \
	size_t _count, _i = (numBytes); \
	unsigned char *_str = (unsigned char *) (bytes); \
	while (_i && (*_str < 0xC0)) { _i--; _str++; } \
	_count = (numBytes) - _i; \
	if (_i) { \
	    _count += Tcl_NumUtfChars((bytes) + _count, _i); \
	} \
	(numChars) = _count; \
#define TclNumUtfCharsM(numChars, bytes, numBytes) \
    do {								\
	Tcl_Size _count, _i = (numBytes);				\
	unsigned char *_str = (unsigned char *) (bytes);		\
	while (_i > 0 && (*_str < 0xC0)) { _i--; _str++; }		\
	_count = (numBytes) - _i;					\
	if (_i) {							\
	    _count += Tcl_NumUtfChars((bytes) + _count, _i);		\
	}								\
	(numChars) = _count;						\
    } while (0);

#define TclUtfPrev(src, start) \
	(((src) < (start) + 2) ? (start) : \
	((unsigned char) *((src) - 1)) < 0x80 ? (src) - 1 : \
	Tcl_UtfPrev(src, start))

/*
 *----------------------------------------------------------------
 * Macro that encapsulates the logic that determines when it is safe to
 * interpret a string as a byte array directly. In summary, the object must be
 * a byte array and must not have a string representation (as the operations
 * that it is used in are defined on strings, not byte arrays). Theoretically
 * it is possible to also be efficient in the case where the object's bytes
 * field is filled by generation from the byte array (c.f. list canonicality)
 * but we don't do that at the moment since this is purely about efficiency.
 * The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE int	TclIsPureByteArray(Tcl_Obj *objPtr);
 *----------------------------------------------------------------
 */

MODULE_SCOPE int	TclIsPureByteArray(Tcl_Obj *objPtr);
#define TclIsPureDict(objPtr) \
	(((objPtr)->bytes==NULL) && ((objPtr)->typePtr==&tclDictType))
#define TclHasIntRep(objPtr, type) \
	((objPtr)->typePtr == (type))
#define TclFetchIntRep(objPtr, type) \
	(TclHasIntRep((objPtr), (type)) ? &((objPtr)->internalRep) : NULL)
    (((objPtr)->bytes == NULL) && TclHasInternalRep((objPtr), &tclDictType))
#define TclHasInternalRep(objPtr, type) \
    ((objPtr)->typePtr == (type))
#define TclFetchInternalRep(objPtr, type) \
    (TclHasInternalRep((objPtr), (type)) ? &(objPtr)->internalRep : NULL)


/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to compare Unicode strings. On big-endian
 * systems we can use the more efficient memcmp, but this would not be
 * lexically correct on little-endian systems. The ANSI C "prototype" for
 * this macro is:
 *
 * MODULE_SCOPE int	TclUniCharNcmp(const Tcl_UniChar *cs,
 *			    const Tcl_UniChar *ct, unsigned long n);
 *----------------------------------------------------------------
 */

#ifdef WORDS_BIGENDIAN
#   define TclUniCharNcmp(cs,ct,n) memcmp((cs),(ct),(n)*sizeof(Tcl_UniChar))
#endif /* WORDS_BIGENDIAN */

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to increment a namespace's export epoch
 * counter. The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE void	TclInvalidateNsCmdLookup(Namespace *nsPtr);
4726
4727
4728
4729
4730
4731
4732
4733

4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749






4750
4751
4752
4753
4754
4755
4756
4711
4712
4713
4714
4715
4716
4717

4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729





4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742







-
+











-
-
-
-
-
+
+
+
+
+
+







 *----------------------------------------------------------------------
 *
 * Core procedure added to libtommath for bignum manipulation.
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE Tcl_PackageInitProc TclTommath_Init;
MODULE_SCOPE Tcl_LibraryInitProc TclTommath_Init;

/*
 *----------------------------------------------------------------------
 *
 * External (platform specific) initialization routine, these declarations
 * explicitly don't use EXTERN since this code does not get compiled into the
 * library:
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE Tcl_PackageInitProc TclplatformtestInit;
MODULE_SCOPE Tcl_PackageInitProc TclObjTest_Init;
MODULE_SCOPE Tcl_PackageInitProc TclThread_Init;
MODULE_SCOPE Tcl_PackageInitProc Procbodytest_Init;
MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
MODULE_SCOPE Tcl_LibraryInitProc TclplatformtestInit;
MODULE_SCOPE Tcl_LibraryInitProc TclObjTest_Init;
MODULE_SCOPE Tcl_LibraryInitProc TclThread_Init;
MODULE_SCOPE Tcl_LibraryInitProc Procbodytest_Init;
MODULE_SCOPE Tcl_LibraryInitProc Procbodytest_SafeInit;
MODULE_SCOPE Tcl_LibraryInitProc Tcl_ABSListTest_Init;

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to check whether a pattern has any characters
 * special to [string match]. The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE int	TclMatchIsTrivial(const char *pattern);
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780





4781
4782
4783
4784
4785
4786
4787
4788





4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799

4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814








4815
4816
4817
4818


4819
4820
4821
4822
4823
4824
4825
4826
















4827



4828
4829
4830
4831
4832
4833
4834
4835
4836
4837








4838
4839
4840
4841
4842
4843
4844
4845
4846
4847







4848
4849
4850
4851
4852
4853















4854
4855

4856
4857
4858
4859
4860
4861
4862
4755
4756
4757
4758
4759
4760
4761





4762
4763
4764
4765
4766
4767
4768
4769





4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784

4785
4786
4787
4788
4789
4790
4791
4792








4793
4794
4795
4796
4797
4798
4799
4800
4801
4802


4803
4804








4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826








4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837







4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866

4867
4868
4869
4870
4871
4872
4873
4874







-
-
-
-
-
+
+
+
+
+



-
-
-
-
-
+
+
+
+
+










-
+







-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+


-
-
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+


-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+



-
-
-
-
-
-
-
+
+
+
+
+
+
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+







 *
 * MODULE_SCOPE void	TclSetIntObj(Tcl_Obj *objPtr, Tcl_WideInt w);
 * MODULE_SCOPE void	TclSetDoubleObj(Tcl_Obj *objPtr, double d);
 *----------------------------------------------------------------
 */

#define TclSetIntObj(objPtr, i) \
    do {						\
	Tcl_ObjIntRep ir;				\
	ir.wideValue = (Tcl_WideInt) i;			\
	TclInvalidateStringRep(objPtr);			\
	Tcl_StoreIntRep(objPtr, &tclIntType, &ir);	\
    do {							\
	Tcl_ObjInternalRep ir;					\
	ir.wideValue = (Tcl_WideInt) i;				\
	TclInvalidateStringRep(objPtr);				\
	Tcl_StoreInternalRep(objPtr, &tclIntType, &ir);		\
    } while (0)

#define TclSetDoubleObj(objPtr, d) \
    do {						\
	Tcl_ObjIntRep ir;				\
	ir.doubleValue = (double) d;			\
	TclInvalidateStringRep(objPtr);			\
	Tcl_StoreIntRep(objPtr, &tclDoubleType, &ir);	\
    do {							\
	Tcl_ObjInternalRep ir;					\
	ir.doubleValue = (double) d;				\
	TclInvalidateStringRep(objPtr);				\
	Tcl_StoreInternalRep(objPtr, &tclDoubleType, &ir);	\
    } while (0)

/*
 *----------------------------------------------------------------
 * Macros used by the Tcl core to create and initialise objects of standard
 * types, avoiding the corresponding function calls in time critical parts of
 * the core. The ANSI C "prototypes" for these macros are:
 *
 * MODULE_SCOPE void	TclNewIntObj(Tcl_Obj *objPtr, Tcl_WideInt w);
 * MODULE_SCOPE void	TclNewDoubleObj(Tcl_Obj *objPtr, double d);
 * MODULE_SCOPE void	TclNewStringObj(Tcl_Obj *objPtr, const char *s, size_t len);
 * MODULE_SCOPE void	TclNewStringObj(Tcl_Obj *objPtr, const char *s, Tcl_Size len);
 * MODULE_SCOPE void	TclNewLiteralStringObj(Tcl_Obj*objPtr, const char *sLiteral);
 *
 *----------------------------------------------------------------
 */

#ifndef TCL_MEM_DEBUG
#define TclNewIntObj(objPtr, w) \
    do {						\
	TclIncrObjsAllocated();				\
	TclAllocObjStorage(objPtr);			\
	(objPtr)->refCount = 0;				\
	(objPtr)->bytes = NULL;				\
	(objPtr)->internalRep.wideValue = (Tcl_WideInt)(w);	\
	(objPtr)->typePtr = &tclIntType;		\
	TCL_DTRACE_OBJ_CREATE(objPtr);			\
    do {								\
	TclIncrObjsAllocated();						\
	TclAllocObjStorage(objPtr);					\
	(objPtr)->refCount = 0;						\
	(objPtr)->bytes = NULL;						\
	(objPtr)->internalRep.wideValue = (Tcl_WideInt)(w);		\
	(objPtr)->typePtr = &tclIntType;				\
	TCL_DTRACE_OBJ_CREATE(objPtr);					\
    } while (0)

#define TclNewIndexObj(objPtr, w) \
    do {						\
#define TclNewUIntObj(objPtr, uw) \
    do {								\
	size_t _w = (w);		\
	TclIncrObjsAllocated();				\
	TclAllocObjStorage(objPtr);			\
	(objPtr)->refCount = 0;				\
	(objPtr)->bytes = NULL;				\
	(objPtr)->internalRep.wideValue = ((_w) == TCL_INDEX_NONE) ? -1 : (Tcl_WideInt)(_w); \
	(objPtr)->typePtr = &tclIntType;		\
	TCL_DTRACE_OBJ_CREATE(objPtr);			\
	TclIncrObjsAllocated();						\
	TclAllocObjStorage(objPtr);					\
	(objPtr)->refCount = 0;						\
	(objPtr)->bytes = NULL;						\
	Tcl_WideUInt uw_ = (uw);					\
	if (uw_ > WIDE_MAX) {						\
	    mp_int bignumValue_;					\
	    if (mp_init_u64(&bignumValue_, uw_) != MP_OKAY) {		\
		Tcl_Panic("%s: memory overflow", "TclNewUIntObj");	\
	    }								\
	    TclSetBignumInternalRep((objPtr), &bignumValue_);		\
	} else {							\
	    (objPtr)->internalRep.wideValue = (Tcl_WideInt)(uw_);	\
	    (objPtr)->typePtr = &tclIntType;				\
	}								\
	TCL_DTRACE_OBJ_CREATE(objPtr);					\
    } while (0)

#define TclNewIndexObj(objPtr, w) \
    TclNewIntObj(objPtr, w)

#define TclNewDoubleObj(objPtr, d) \
    do {							\
	TclIncrObjsAllocated();					\
	TclAllocObjStorage(objPtr);				\
	(objPtr)->refCount = 0;					\
	(objPtr)->bytes = NULL;					\
	(objPtr)->internalRep.doubleValue = (double)(d);	\
	(objPtr)->typePtr = &tclDoubleType;			\
	TCL_DTRACE_OBJ_CREATE(objPtr);				\
    do {								\
	TclIncrObjsAllocated();						\
	TclAllocObjStorage(objPtr);					\
	(objPtr)->refCount = 0;						\
	(objPtr)->bytes = NULL;						\
	(objPtr)->internalRep.doubleValue = (double)(d);		\
	(objPtr)->typePtr = &tclDoubleType;				\
	TCL_DTRACE_OBJ_CREATE(objPtr);					\
    } while (0)

#define TclNewStringObj(objPtr, s, len) \
    do {							\
	TclIncrObjsAllocated();					\
	TclAllocObjStorage(objPtr);				\
	(objPtr)->refCount = 0;					\
	TclInitStringRep((objPtr), (s), (len));			\
	(objPtr)->typePtr = NULL;				\
	TCL_DTRACE_OBJ_CREATE(objPtr);				\
    do {								\
	TclIncrObjsAllocated();						\
	TclAllocObjStorage(objPtr);					\
	(objPtr)->refCount = 0;						\
	TclInitStringRep((objPtr), (s), (len));				\
	(objPtr)->typePtr = NULL;					\
	TCL_DTRACE_OBJ_CREATE(objPtr);					\
    } while (0)

#else /* TCL_MEM_DEBUG */
#define TclNewIntObj(objPtr, w) \
    (objPtr) = Tcl_NewWideIntObj(w)

#define TclNewUIntObj(objPtr, uw) \
    do {								\
	Tcl_WideUInt uw_ = (uw);					\
	if (uw_ > WIDE_MAX) {						\
	    mp_int bignumValue_;					\
	    if (mp_init_u64(&bignumValue_, uw_) == MP_OKAY) {		\
		(objPtr) = Tcl_NewBignumObj(&bignumValue_);		\
	    } else {							\
		(objPtr) = NULL;					\
	    }								\
	} else {							\
	    (objPtr) = Tcl_NewWideIntObj(uw_);				\
	}								\
    } while (0)

#define TclNewIndexObj(objPtr, w) \
    (objPtr) = ((w) == TCL_INDEX_NONE) ? Tcl_NewWideIntObj(-1) : Tcl_NewWideIntObj(w)
    TclNewIntObj(objPtr, w)

#define TclNewDoubleObj(objPtr, d) \
    (objPtr) = Tcl_NewDoubleObj(d)

#define TclNewStringObj(objPtr, s, len) \
    (objPtr) = Tcl_NewStringObj((s), (len))
#endif /* TCL_MEM_DEBUG */
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929

4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947








4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963


4964
4965

4966
4967
4968
4969
4970
4971
4972
4891
4892
4893
4894
4895
4896
4897


























4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914

4915
4916
4917
4918
4919
4920
4921

4922
4923
4924








4925
4926
4927
4928
4929
4930
4931
4932
4933

4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946

4947
4948
4949

4950
4951
4952
4953
4954
4955
4956
4957







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

















-
+






-



-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-













-
+
+

-
+







 */

#define TclDStringAppendLiteral(dsPtr, sLiteral) \
    Tcl_DStringAppend((dsPtr), (sLiteral), sizeof(sLiteral "") - 1)
#define TclDStringClear(dsPtr) \
    Tcl_DStringSetLength((dsPtr), 0)

/*
 *----------------------------------------------------------------
 * Macros used by the Tcl core to test for some special double values.
 * The ANSI C "prototypes" for these macros are:
 *
 * MODULE_SCOPE int	TclIsInfinite(double d);
 * MODULE_SCOPE int	TclIsNaN(double d);
 */

#ifdef _MSC_VER
#    define TclIsInfinite(d)	(!(_finite((d))))
#    define TclIsNaN(d)		(_isnan((d)))
#else
#    define TclIsInfinite(d)	((d) > DBL_MAX || (d) < -DBL_MAX)
#    ifdef NO_ISNAN
#	 define TclIsNaN(d)	((d) != (d))
#    else
#	 define TclIsNaN(d)	(isnan(d))
#    endif
#endif

/* Workaround for platforms missing offsetof(), e.g. VC++ 6.0 */
#ifndef offsetof
#   define offsetof(type, field) ((size_t) ((char *) &((type *) 0)->field))
#endif

/*
 *----------------------------------------------------------------
 * Inline version of Tcl_GetCurrentNamespace and Tcl_GetGlobalNamespace.
 */

#define TclGetCurrentNamespace(interp) \
    (Tcl_Namespace *) ((Interp *)(interp))->varFramePtr->nsPtr

#define TclGetGlobalNamespace(interp) \
    (Tcl_Namespace *) ((Interp *)(interp))->globalNsPtr

/*
 *----------------------------------------------------------------
 * Inline version of TclCleanupCommand; still need the function as it is in
 * the internal stubs, but the core can use the macro instead.
 */

#define TclCleanupCommandMacro(cmdPtr)		\
#define TclCleanupCommandMacro(cmdPtr) \
    do {					\
	if ((cmdPtr)->refCount-- <= 1) {	\
	    Tcl_Free(cmdPtr);			\
	}					\
    } while (0)


/*
 * inside this routine crement refCount first incase cmdPtr is replacing itself
 */
#define TclRoutineAssign(location, cmdPtr)	    \
    do {					    \
	(cmdPtr)->refCount++;			    \
	if ((location) != NULL			    \
	    && (location--) <= 1) {		    \
	    Tcl_Free(((location)));		    \
	}					    \
	(location) = (cmdPtr);			    \
#define TclRoutineAssign(location, cmdPtr) \
    do {								\
	(cmdPtr)->refCount++;						\
	if ((location) != NULL						\
		&& (location--) <= 1) {					\
	    Tcl_Free(((location)));					\
	}								\
	(location) = (cmdPtr);						\
    } while (0)


#define TclRoutineHasName(cmdPtr) \
    ((cmdPtr)->hPtr != NULL)

/*
 *----------------------------------------------------------------
 * Inline versions of Tcl_LimitReady() and Tcl_LimitExceeded to limit number
 * of calls out of the critical path. Note that this code isn't particularly
 * readable; the non-inline version (in tclInterp.c) is much easier to
 * understand. Note also that these macros takes different args (iPtr->limit)
 * to the non-inline version.
 */

#define TclLimitExceeded(limit) ((limit).exceeded != 0)
#define TclLimitExceeded(limit) \
    ((limit).exceeded != 0)

#define TclLimitReady(limit)						\
#define TclLimitReady(limit) \
    (((limit).active == 0) ? 0 :					\
    (++(limit).granularityTicker,					\
    ((((limit).active & TCL_LIMIT_COMMANDS) &&				\
	    (((limit).cmdGranularity == 1) ||				\
	    ((limit).granularityTicker % (limit).cmdGranularity == 0)))	\
	    ? 1 :							\
    (((limit).active & TCL_LIMIT_TIME) &&				\
5008
5009
5010
5011
5012
5013
5014
5015

5016
5017
5018
5019
5020

5021
5022
5023
5024
5025
5026
5027
5028
5029
5030

5031
5032
5033
5034
5035

5036
5037
5038
5039
5040
5041
5042
4993
4994
4995
4996
4997
4998
4999

5000
5001
5002
5003
5004

5005
5006
5007
5008
5009
5010
5011
5012
5013
5014

5015
5016
5017
5018
5019

5020
5021
5022
5023
5024
5025
5026
5027







-
+




-
+









-
+




-
+







#ifndef TCL_MEM_DEBUG
#define TclSmallAllocEx(interp, nbytes, memPtr) \
    do {								\
	Tcl_Obj *_objPtr;						\
	TCL_CT_ASSERT((nbytes)<=sizeof(Tcl_Obj));			\
	TclIncrObjsAllocated();						\
	TclAllocObjStorageEx((interp), (_objPtr));			\
	*(void **)&memPtr = (void *) (_objPtr);					\
	*(void **)&(memPtr) = (void *) (_objPtr);			\
    } while (0)

#define TclSmallFreeEx(interp, memPtr) \
    do {								\
	TclFreeObjStorageEx((interp), (Tcl_Obj *)memPtr);		\
	TclFreeObjStorageEx((interp), (Tcl_Obj *)(memPtr));		\
	TclIncrObjsFreed();						\
    } while (0)

#else    /* TCL_MEM_DEBUG */
#define TclSmallAllocEx(interp, nbytes, memPtr) \
    do {								\
	Tcl_Obj *_objPtr;						\
	TCL_CT_ASSERT((nbytes)<=sizeof(Tcl_Obj));			\
	TclNewObj(_objPtr);						\
	*(void **)&memPtr = (void *) _objPtr;					\
	*(void **)&(memPtr) = (void *)_objPtr;				\
    } while (0)

#define TclSmallFreeEx(interp, memPtr) \
    do {								\
	Tcl_Obj *_objPtr = (Tcl_Obj *) memPtr;				\
	Tcl_Obj *_objPtr = (Tcl_Obj *)(memPtr);				\
	_objPtr->bytes = NULL;						\
	_objPtr->typePtr = NULL;					\
	_objPtr->refCount = 1;						\
	TclDecrRefCount(_objPtr);					\
    } while (0)
#endif   /* TCL_MEM_DEBUG */

5076
5077
5078
5079
5080
5081
5082

5083

5084
5085
5086
5087
5088
5089
5090
5061
5062
5063
5064
5065
5066
5067
5068

5069
5070
5071
5072
5073
5074
5075
5076







+
-
+








typedef struct NRE_callback {
    Tcl_NRPostProc *procPtr;
    void *data[4];
    struct NRE_callback *nextPtr;
} NRE_callback;

#define TOP_CB(iPtr) \
#define TOP_CB(iPtr) (((Interp *)(iPtr))->execEnvPtr->callbackPtr)
    (((Interp *)(iPtr))->execEnvPtr->callbackPtr)

/*
 * Inline version of Tcl_NRAddCallback.
 */

#define TclNRAddCallback(interp,postProcPtr,data0,data1,data2,data3) \
    do {								\
5101
5102
5103
5104
5105
5106
5107
5108

5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124



5125
5126




























5127
5128

5129
5130
5131
5132
5133
5134
5135
5087
5088
5089
5090
5091
5092
5093

5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107



5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141

5142
5143
5144
5145
5146
5147
5148
5149







-
+













-
-
-
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+








#if NRE_USE_SMALL_ALLOC
#define TCLNR_ALLOC(interp, ptr) \
    TclSmallAllocEx(interp, sizeof(NRE_callback), (ptr))
#define TCLNR_FREE(interp, ptr)  TclSmallFreeEx((interp), (ptr))
#else
#define TCLNR_ALLOC(interp, ptr) \
    (ptr = (Tcl_Alloc(sizeof(NRE_callback))))
    ((ptr) = Tcl_Alloc(sizeof(NRE_callback)))
#define TCLNR_FREE(interp, ptr)  Tcl_Free(ptr)
#endif

#if NRE_ENABLE_ASSERTS
#define NRE_ASSERT(expr) assert((expr))
#else
#define NRE_ASSERT(expr)
#endif

#include "tclIntDecls.h"
#include "tclIntPlatDecls.h"

#if !defined(USE_TCL_STUBS) && !defined(TCL_MEM_DEBUG)
#define Tcl_AttemptAlloc        TclpAlloc
#define Tcl_AttemptRealloc      TclpRealloc
#define Tcl_Free                TclpFree
#define Tcl_AttemptAlloc	TclpAlloc
#define Tcl_AttemptRealloc	TclpRealloc
#define Tcl_Free		TclpFree
#endif

/*
 * Special hack for macOS, where the static linker (technically the 'ar'
 * command) hates empty object files, and accepts no flags to make it shut up.
 *
 * These symbols are otherwise completely useless.
 *
 * They can't be written to or written through. They can't be seen by any
 * other code. They use a separate attribute (supported by all macOS
 * compilers, which are derivatives of clang or gcc) to stop the compilation
 * from moaning. They will be excluded during the final linking stage.
 *
 * Other platforms get nothing at all. That's good.
 */

#ifdef MAC_OSX_TCL
#define TCL_MAC_EMPTY_FILE(name) \
    static __attribute__((used)) const void *const TclUnusedFile_ ## name = NULL;
#else
#define TCL_MAC_EMPTY_FILE(name)
#endif /* MAC_OSX_TCL */

/*
 * Other externals.
 */

MODULE_SCOPE size_t TclEnvEpoch;	/* Epoch of the tcl environment
					 * (if changed with tcl-env). */

#endif /* _TCLINT */


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

Changes to generic/tclIntDecls.h.

46
47
48
49
50
51
52
53
54



55
56
57
58

59
60
61
62

63
64
65
66
67
68
69
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







-
-
+
+
+



-
+



-
+







/* Slot 0 is reserved */
/* Slot 1 is reserved */
/* Slot 2 is reserved */
/* 3 */
EXTERN void		TclAllocateFreeObjects(void);
/* Slot 4 is reserved */
/* 5 */
EXTERN int		TclCleanupChildren(Tcl_Interp *interp, int numPids,
				Tcl_Pid *pidPtr, Tcl_Channel errorChan);
EXTERN int		TclCleanupChildren(Tcl_Interp *interp,
				Tcl_Size numPids, Tcl_Pid *pidPtr,
				Tcl_Channel errorChan);
/* 6 */
EXTERN void		TclCleanupCommand(Command *cmdPtr);
/* 7 */
EXTERN size_t		TclCopyAndCollapse(size_t count, const char *src,
EXTERN Tcl_Size		TclCopyAndCollapse(Tcl_Size count, const char *src,
				char *dst);
/* Slot 8 is reserved */
/* 9 */
EXTERN int		TclCreatePipeline(Tcl_Interp *interp, int argc,
EXTERN Tcl_Size		TclCreatePipeline(Tcl_Interp *interp, Tcl_Size argc,
				const char **argv, Tcl_Pid **pidArrayPtr,
				TclFile *inPipePtr, TclFile *outPipePtr,
				TclFile *errFilePtr);
/* 10 */
EXTERN int		TclCreateProc(Tcl_Interp *interp, Namespace *nsPtr,
				const char *procName, Tcl_Obj *argsPtr,
				Tcl_Obj *bodyPtr, Proc **procPtrPtr);
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
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







-
+

-
+




-
+

















-
+
-
-








-
+


-
+





-
-
-
+
+
-
+











-
+
-
-
-
-
+
-
-
-
















-
+
-
-
-

-
+






-
+







-
+

-
+





-
+







/* Slot 17 is reserved */
/* Slot 18 is reserved */
/* Slot 19 is reserved */
/* Slot 20 is reserved */
/* Slot 21 is reserved */
/* 22 */
EXTERN int		TclFindElement(Tcl_Interp *interp,
				const char *listStr, int listLength,
				const char *listStr, Tcl_Size listLength,
				const char **elementPtr,
				const char **nextPtr, size_t *sizePtr,
				const char **nextPtr, Tcl_Size *sizePtr,
				int *bracePtr);
/* 23 */
EXTERN Proc *		TclFindProc(Interp *iPtr, const char *procName);
/* 24 */
EXTERN size_t		TclFormatInt(char *buffer, Tcl_WideInt n);
EXTERN Tcl_Size		TclFormatInt(char *buffer, Tcl_WideInt n);
/* 25 */
EXTERN void		TclFreePackageInfo(Interp *iPtr);
/* Slot 26 is reserved */
/* Slot 27 is reserved */
/* 28 */
EXTERN Tcl_Channel	TclpGetDefaultStdChannel(int type);
/* Slot 29 is reserved */
/* Slot 30 is reserved */
/* 31 */
EXTERN const char *	TclGetExtension(const char *name);
/* 32 */
EXTERN int		TclGetFrame(Tcl_Interp *interp, const char *str,
				CallFrame **framePtrPtr);
/* Slot 33 is reserved */
/* Slot 34 is reserved */
/* Slot 35 is reserved */
/* Slot 36 is reserved */
/* 37 */
/* Slot 37 is reserved */
EXTERN int		TclGetLoadedPackages(Tcl_Interp *interp,
				const char *targetName);
/* 38 */
EXTERN int		TclGetNamespaceForQualName(Tcl_Interp *interp,
				const char *qualName, Namespace *cxtNsPtr,
				int flags, Namespace **nsPtrPtr,
				Namespace **altNsPtrPtr,
				Namespace **actualCxtPtrPtr,
				const char **simpleNamePtr);
/* 39 */
EXTERN TclObjCmdProcType TclGetObjInterpProc(void);
EXTERN Tcl_ObjCmdProc *	 TclGetObjInterpProc(void);
/* 40 */
EXTERN int		TclGetOpenMode(Tcl_Interp *interp, const char *str,
				int *seekFlagPtr);
				int *modeFlagsPtr);
/* 41 */
EXTERN Tcl_Command	TclGetOriginalCommand(Tcl_Command command);
/* 42 */
EXTERN const char *	TclpGetUserHome(const char *name,
				Tcl_DString *bufferPtr);
/* Slot 43 is reserved */
/* 44 */
EXTERN int		TclGuessPackageName(const char *fileName,
/* 43 */
EXTERN Tcl_ObjCmdProc2 * TclGetObjInterpProc2(void);
				Tcl_DString *bufPtr);
/* Slot 44 is reserved */
/* 45 */
EXTERN int		TclHideUnsafeCommands(Tcl_Interp *interp);
/* 46 */
EXTERN int		TclInExit(void);
/* Slot 47 is reserved */
/* Slot 48 is reserved */
/* Slot 49 is reserved */
/* Slot 50 is reserved */
/* 51 */
EXTERN int		TclInterpInit(Tcl_Interp *interp);
/* Slot 52 is reserved */
/* 53 */
/* Slot 53 is reserved */
EXTERN int		TclInvokeObjectCommand(void *clientData,
				Tcl_Interp *interp, int argc,
				const char **argv);
/* 54 */
/* Slot 54 is reserved */
EXTERN int		TclInvokeStringCommand(void *clientData,
				Tcl_Interp *interp, int objc,
				Tcl_Obj *const objv[]);
/* 55 */
EXTERN Proc *		TclIsProc(Command *cmdPtr);
/* Slot 56 is reserved */
/* Slot 57 is reserved */
/* 58 */
EXTERN Var *		TclLookupVar(Tcl_Interp *interp, const char *part1,
				const char *part2, int flags,
				const char *msg, int createPart1,
				int createPart2, Var **arrayPtrPtr);
/* Slot 59 is reserved */
/* 60 */
EXTERN int		TclNeedSpace(const char *start, const char *end);
/* 61 */
EXTERN Tcl_Obj *	TclNewProcBodyObj(Proc *procPtr);
/* 62 */
EXTERN int		TclObjCommandComplete(Tcl_Obj *cmdPtr);
/* 63 */
/* Slot 63 is reserved */
EXTERN int		TclObjInterpProc(void *clientData,
				Tcl_Interp *interp, int objc,
				Tcl_Obj *const objv[]);
/* 64 */
EXTERN int		TclObjInvoke(Tcl_Interp *interp, int objc,
EXTERN int		TclObjInvoke(Tcl_Interp *interp, Tcl_Size objc,
				Tcl_Obj *const objv[], int flags);
/* Slot 65 is reserved */
/* Slot 66 is reserved */
/* Slot 67 is reserved */
/* Slot 68 is reserved */
/* 69 */
EXTERN void *		TclpAlloc(size_t size);
EXTERN void *		TclpAlloc(TCL_HASH_TYPE size);
/* Slot 70 is reserved */
/* Slot 71 is reserved */
/* Slot 72 is reserved */
/* Slot 73 is reserved */
/* 74 */
EXTERN void		TclpFree(void *ptr);
/* 75 */
EXTERN Tcl_WideUInt	TclpGetClicks(void);
EXTERN unsigned long long TclpGetClicks(void);
/* 76 */
EXTERN Tcl_WideUInt	TclpGetSeconds(void);
EXTERN unsigned long long TclpGetSeconds(void);
/* Slot 77 is reserved */
/* Slot 78 is reserved */
/* Slot 79 is reserved */
/* Slot 80 is reserved */
/* 81 */
EXTERN void *		TclpRealloc(void *ptr, size_t size);
EXTERN void *		TclpRealloc(void *ptr, TCL_HASH_TYPE size);
/* Slot 82 is reserved */
/* Slot 83 is reserved */
/* Slot 84 is reserved */
/* Slot 85 is reserved */
/* Slot 86 is reserved */
/* Slot 87 is reserved */
/* Slot 88 is reserved */
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
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







-
+
-














-
+







/* 97 */
EXTERN void		TclResetShadowedCmdRefs(Tcl_Interp *interp,
				Command *newCmdPtr);
/* 98 */
EXTERN int		TclServiceIdle(void);
/* Slot 99 is reserved */
/* Slot 100 is reserved */
/* 101 */
/* Slot 101 is reserved */
EXTERN const char *	TclSetPreInitScript(const char *string);
/* 102 */
EXTERN void		TclSetupEnv(Tcl_Interp *interp);
/* 103 */
EXTERN int		TclSockGetPort(Tcl_Interp *interp, const char *str,
				const char *proto, int *portPtr);
/* Slot 104 is reserved */
/* Slot 105 is reserved */
/* Slot 106 is reserved */
/* Slot 107 is reserved */
/* 108 */
EXTERN void		TclTeardownNamespace(Namespace *nsPtr);
/* 109 */
EXTERN int		TclUpdateReturnInfo(Interp *iPtr);
/* 110 */
EXTERN int		TclSockMinimumBuffers(void *sock, int size);
EXTERN int		TclSockMinimumBuffers(void *sock, Tcl_Size size);
/* 111 */
EXTERN void		Tcl_AddInterpResolvers(Tcl_Interp *interp,
				const char *name,
				Tcl_ResolveCmdProc *cmdProc,
				Tcl_ResolveVarProc *varProc,
				Tcl_ResolveCompiledVarProc *compiledVarProc);
/* Slot 112 is reserved */
291
292
293
294
295
296
297
298

299
300
301
302
303
304
305
306
279
280
281
282
283
284
285

286

287
288
289
290
291
292
293







-
+
-







				const char *name);
/* 131 */
EXTERN void		Tcl_SetNamespaceResolvers(
				Tcl_Namespace *namespacePtr,
				Tcl_ResolveCmdProc *cmdProc,
				Tcl_ResolveVarProc *varProc,
				Tcl_ResolveCompiledVarProc *compiledVarProc);
/* 132 */
/* Slot 132 is reserved */
EXTERN int		TclpHasSockets(Tcl_Interp *interp);
/* Slot 133 is reserved */
/* Slot 134 is reserved */
/* Slot 135 is reserved */
/* Slot 136 is reserved */
/* Slot 137 is reserved */
/* 138 */
EXTERN const char *	TclGetEnv(const char *name, Tcl_DString *valuePtr);
327
328
329
330
331
332
333
334
335
336



337
338

339
340
341
342
343
344
345
346
314
315
316
317
318
319
320



321
322
323


324

325
326
327
328
329
330
331







-
-
-
+
+
+
-
-
+
-







/* 148 */
EXTERN TclHandle	TclHandlePreserve(TclHandle handle);
/* 149 */
EXTERN void		TclHandleRelease(TclHandle handle);
/* 150 */
EXTERN int		TclRegAbout(Tcl_Interp *interp, Tcl_RegExp re);
/* 151 */
EXTERN void		TclRegExpRangeUniChar(Tcl_RegExp re, size_t index,
				size_t *startPtr, size_t *endPtr);
/* 152 */
EXTERN void		TclRegExpRangeUniChar(Tcl_RegExp re, Tcl_Size index,
				Tcl_Size *startPtr, Tcl_Size *endPtr);
/* Slot 152 is reserved */
EXTERN void		TclSetLibraryPath(Tcl_Obj *pathPtr);
/* 153 */
/* Slot 153 is reserved */
EXTERN Tcl_Obj *	TclGetLibraryPath(void);
/* Slot 154 is reserved */
/* Slot 155 is reserved */
/* 156 */
EXTERN void		TclRegError(Tcl_Interp *interp, const char *msg,
				int status);
/* 157 */
EXTERN Var *		TclVarTraceExists(Tcl_Interp *interp,
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
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







-
+




-
+



-
+

-
+


-
+

-
+




-
-
+
+







EXTERN const void *	TclGetInstructionTable(void);
/* 164 */
EXTERN void		TclExpandCodeArray(void *envPtr);
/* 165 */
EXTERN void		TclpSetInitialEncodings(void);
/* 166 */
EXTERN int		TclListObjSetElement(Tcl_Interp *interp,
				Tcl_Obj *listPtr, int index,
				Tcl_Obj *listPtr, Tcl_Size index,
				Tcl_Obj *valuePtr);
/* Slot 167 is reserved */
/* Slot 168 is reserved */
/* 169 */
EXTERN int		TclpUtfNcmp2(const char *s1, const char *s2,
EXTERN int		TclpUtfNcmp2(const void *s1, const void *s2,
				size_t n);
/* 170 */
EXTERN int		TclCheckInterpTraces(Tcl_Interp *interp,
				const char *command, size_t numChars,
				const char *command, Tcl_Size numChars,
				Command *cmdPtr, int result, int traceFlags,
				int objc, Tcl_Obj *const objv[]);
				Tcl_Size objc, Tcl_Obj *const objv[]);
/* 171 */
EXTERN int		TclCheckExecutionTraces(Tcl_Interp *interp,
				const char *command, size_t numChars,
				const char *command, Tcl_Size numChars,
				Command *cmdPtr, int result, int traceFlags,
				int objc, Tcl_Obj *const objv[]);
				Tcl_Size objc, Tcl_Obj *const objv[]);
/* 172 */
EXTERN int		TclInThreadExit(void);
/* 173 */
EXTERN int		TclUniCharMatch(const Tcl_UniChar *string,
				size_t strLen, const Tcl_UniChar *pattern,
				size_t ptnLen, int flags);
				Tcl_Size strLen, const Tcl_UniChar *pattern,
				Tcl_Size ptnLen, int flags);
/* Slot 174 is reserved */
/* 175 */
EXTERN int		TclCallVarTraces(Interp *iPtr, Var *arrayPtr,
				Var *varPtr, const char *part1,
				const char *part2, int flags,
				int leaveErrMsg);
/* 176 */
451
452
453
454
455
456
457
458


459
460
461
462
463
464
465
466
467
468



469
470
471
472








473
474
475
476
477

478
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

558
559
560
561
562

563
564
565
566
567

568
569
570
571
572
573
574
575

576
577
578
579
580
581
582
583
584
585









586
587
588
589
590
591
592
593
594
595
596
597
598
599
600

601
602

603
604

605
606
607
608
609
610
611
612
613
614
615
616
617

618
619

620
621
622
623
624
625
626
627
628
629
630
631
632

633
634
635


636
637

638

639
640
641
642
643
644
645
646
647
648
649


650
651
652
653
654
655
656
657
658
659


660
661
662
663
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
707
708
709
710
711
712
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
467
468
469

470
471
472
473
474

475
476
477
478
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
558

559
560
561
562
563
564
565
566

567
568









569
570
571
572
573
574
575
576
577




578
579
580
581
582
583
584
585
586
587

588
589

590
591

592
593
594
595
596
597
598
599
600
601
602
603
604

605
606

607
608
609
610
611
612
613
614
615
616
617
618
619

620
621


622
623
624
625
626

627

628
629
630
631
632
633
634
635


636
637
638
639
640
641
642
643
644
645


646
647
648
649
650
651

652
653
654
655
656
657


658
659
660
661
662
663

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







-
+
+









-
+
+
+

-
-
-
+
+
+
+
+
+
+
+




-
+




-
+








-
+
-
-
+



















-
+


-
+








-
+










-
+







-
+








-
+



-
+




-
+




-
+







-
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-










-
+

-
+

-
+












-
+

-
+












-
+

-
-
+
+


+
-
+
-








-
-
+
+








-
-
+
+




-
+





-
-
+
+




-
+



















-
+








-
+







EXTERN void		TclpFindExecutable(const char *argv0);
/* 213 */
EXTERN Tcl_Obj *	TclGetObjNameOfExecutable(void);
/* 214 */
EXTERN void		TclSetObjNameOfExecutable(Tcl_Obj *name,
				Tcl_Encoding encoding);
/* 215 */
EXTERN void *		TclStackAlloc(Tcl_Interp *interp, size_t numBytes);
EXTERN void *		TclStackAlloc(Tcl_Interp *interp,
				TCL_HASH_TYPE numBytes);
/* 216 */
EXTERN void		TclStackFree(Tcl_Interp *interp, void *freePtr);
/* 217 */
EXTERN int		TclPushStackFrame(Tcl_Interp *interp,
				Tcl_CallFrame **framePtrPtr,
				Tcl_Namespace *namespacePtr,
				int isProcCallFrame);
/* 218 */
EXTERN void		TclPopStackFrame(Tcl_Interp *interp);
/* Slot 219 is reserved */
/* 219 */
EXTERN Tcl_Obj *	TclpCreateTemporaryDirectory(Tcl_Obj *dirObj,
				Tcl_Obj *basenameObj);
/* Slot 220 is reserved */
/* Slot 221 is reserved */
/* Slot 222 is reserved */
/* Slot 223 is reserved */
/* 221 */
EXTERN Tcl_Obj *	TclListTestObj(size_t length, size_t leadingSpace,
				size_t endSpace);
/* 222 */
EXTERN void		TclListObjValidate(Tcl_Interp *interp,
				Tcl_Obj *listObj);
/* 223 */
EXTERN void *		TclGetCStackPtr(void);
/* 224 */
EXTERN TclPlatformType * TclGetPlatform(void);
/* 225 */
EXTERN Tcl_Obj *	TclTraceDictPath(Tcl_Interp *interp,
				Tcl_Obj *rootPtr, int keyc,
				Tcl_Obj *rootPtr, Tcl_Size keyc,
				Tcl_Obj *const keyv[], int flags);
/* 226 */
EXTERN int		TclObjBeingDeleted(Tcl_Obj *objPtr);
/* 227 */
EXTERN void		TclSetNsPath(Namespace *nsPtr, size_t pathLength,
EXTERN void		TclSetNsPath(Namespace *nsPtr, Tcl_Size pathLength,
				Tcl_Namespace *pathAry[]);
/* Slot 228 is reserved */
/* 229 */
EXTERN int		TclPtrMakeUpvar(Tcl_Interp *interp, Var *otherP1Ptr,
				const char *myName, int myFlags, int index);
/* 230 */
EXTERN Var *		TclObjLookupVar(Tcl_Interp *interp,
				Tcl_Obj *part1Ptr, const char *part2,
				int flags, const char *msg,
				int flags, const char *msg, int createPart1,
				const int createPart1, const int createPart2,
				Var **arrayPtrPtr);
				int createPart2, Var **arrayPtrPtr);
/* 231 */
EXTERN int		TclGetNamespaceFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, Tcl_Namespace **nsPtrPtr);
/* 232 */
EXTERN int		TclEvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr,
				int flags, const CmdFrame *invoker, int word);
/* 233 */
EXTERN void		TclGetSrcInfoForPc(CmdFrame *contextPtr);
/* 234 */
EXTERN Var *		TclVarHashCreateVar(TclVarHashTable *tablePtr,
				const char *key, int *newPtr);
/* 235 */
EXTERN void		TclInitVarHashTable(TclVarHashTable *tablePtr,
				Namespace *nsPtr);
/* Slot 236 is reserved */
/* 237 */
EXTERN int		TclResetCancellation(Tcl_Interp *interp, int force);
/* 238 */
EXTERN int		TclNRInterpProc(void *clientData, Tcl_Interp *interp,
				int objc, Tcl_Obj *const objv[]);
				Tcl_Size objc, Tcl_Obj *const objv[]);
/* 239 */
EXTERN int		TclNRInterpProcCore(Tcl_Interp *interp,
				Tcl_Obj *procNameObj, int skip,
				Tcl_Obj *procNameObj, Tcl_Size skip,
				ProcErrorProc *errorProc);
/* 240 */
EXTERN int		TclNRRunCallbacks(Tcl_Interp *interp, int result,
				struct NRE_callback *rootPtr);
/* 241 */
EXTERN int		TclNREvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr,
				int flags, const CmdFrame *invoker, int word);
/* 242 */
EXTERN int		TclNREvalObjv(Tcl_Interp *interp, int objc,
EXTERN int		TclNREvalObjv(Tcl_Interp *interp, Tcl_Size objc,
				Tcl_Obj *const objv[], int flags,
				Command *cmdPtr);
/* 243 */
EXTERN void		TclDbDumpActiveObjects(FILE *outFile);
/* 244 */
EXTERN Tcl_HashTable *	TclGetNamespaceChildTable(Tcl_Namespace *nsPtr);
/* 245 */
EXTERN Tcl_HashTable *	TclGetNamespaceCommandTable(Tcl_Namespace *nsPtr);
/* 246 */
EXTERN int		TclInitRewriteEnsemble(Tcl_Interp *interp,
				size_t numRemoved, size_t numInserted,
				Tcl_Size numRemoved, Tcl_Size numInserted,
				Tcl_Obj *const *objv);
/* 247 */
EXTERN void		TclResetRewriteEnsemble(Tcl_Interp *interp,
				int isRootEnsemble);
/* 248 */
EXTERN int		TclCopyChannel(Tcl_Interp *interp,
				Tcl_Channel inChan, Tcl_Channel outChan,
				Tcl_WideInt toRead, Tcl_Obj *cmdPtr);
				long long toRead, Tcl_Obj *cmdPtr);
/* 249 */
EXTERN char *		TclDoubleDigits(double dv, int ndigits, int flags,
				int *decpt, int *signum, char **endPtr);
/* 250 */
EXTERN void		TclSetChildCancelFlags(Tcl_Interp *interp, int flags,
				int force);
/* 251 */
EXTERN int		TclRegisterLiteral(void *envPtr, const char *bytes,
				size_t length, int flags);
				Tcl_Size length, int flags);
/* 252 */
EXTERN Tcl_Obj *	TclPtrGetVar(Tcl_Interp *interp, Tcl_Var varPtr,
				Tcl_Var arrayPtr, Tcl_Obj *part1Ptr,
				Tcl_Obj *part2Ptr, const int flags);
				Tcl_Obj *part2Ptr, int flags);
/* 253 */
EXTERN Tcl_Obj *	TclPtrSetVar(Tcl_Interp *interp, Tcl_Var varPtr,
				Tcl_Var arrayPtr, Tcl_Obj *part1Ptr,
				Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr,
				const int flags);
				int flags);
/* 254 */
EXTERN Tcl_Obj *	TclPtrIncrObjVar(Tcl_Interp *interp, Tcl_Var varPtr,
				Tcl_Var arrayPtr, Tcl_Obj *part1Ptr,
				Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr,
				const int flags);
				int flags);
/* 255 */
EXTERN int		TclPtrObjMakeUpvar(Tcl_Interp *interp,
				Tcl_Var otherPtr, Tcl_Obj *myNamePtr,
				int myFlags);
/* 256 */
EXTERN int		TclPtrUnsetVar(Tcl_Interp *interp, Tcl_Var varPtr,
				Tcl_Var arrayPtr, Tcl_Obj *part1Ptr,
				Tcl_Obj *part2Ptr, const int flags);
				Tcl_Obj *part2Ptr, int flags);
/* 257 */
EXTERN void		TclStaticPackage(Tcl_Interp *interp,
				const char *pkgName,
				Tcl_PackageInitProc *initProc,
				Tcl_PackageInitProc *safeInitProc);
/* 258 */
EXTERN Tcl_Obj *	TclpCreateTemporaryDirectory(Tcl_Obj *dirObj,
				Tcl_Obj *basenameObj);
/* 259 */
EXTERN void		TclAppendUnicodeToObj(Tcl_Obj *objPtr,
EXTERN void		TclStaticLibrary(Tcl_Interp *interp,
				const char *prefix,
				Tcl_LibraryInitProc *initProc,
				Tcl_LibraryInitProc *safeInitProc);
/* Slot 258 is reserved */
/* Slot 259 is reserved */
/* Slot 260 is reserved */
/* 261 */
EXTERN void		TclUnusedStubEntry(void);
				const Tcl_UniChar *unicode, size_t length);
/* 260 */
EXTERN unsigned char *	TclGetBytesFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, size_t *lengthPtr);

typedef struct TclIntStubs {
    int magic;
    void *hooks;

    void (*reserved0)(void);
    void (*reserved1)(void);
    void (*reserved2)(void);
    void (*tclAllocateFreeObjects) (void); /* 3 */
    void (*reserved4)(void);
    int (*tclCleanupChildren) (Tcl_Interp *interp, int numPids, Tcl_Pid *pidPtr, Tcl_Channel errorChan); /* 5 */
    int (*tclCleanupChildren) (Tcl_Interp *interp, Tcl_Size numPids, Tcl_Pid *pidPtr, Tcl_Channel errorChan); /* 5 */
    void (*tclCleanupCommand) (Command *cmdPtr); /* 6 */
    size_t (*tclCopyAndCollapse) (size_t count, const char *src, char *dst); /* 7 */
    Tcl_Size (*tclCopyAndCollapse) (Tcl_Size count, const char *src, char *dst); /* 7 */
    void (*reserved8)(void);
    int (*tclCreatePipeline) (Tcl_Interp *interp, int argc, const char **argv, Tcl_Pid **pidArrayPtr, TclFile *inPipePtr, TclFile *outPipePtr, TclFile *errFilePtr); /* 9 */
    Tcl_Size (*tclCreatePipeline) (Tcl_Interp *interp, Tcl_Size argc, const char **argv, Tcl_Pid **pidArrayPtr, TclFile *inPipePtr, TclFile *outPipePtr, TclFile *errFilePtr); /* 9 */
    int (*tclCreateProc) (Tcl_Interp *interp, Namespace *nsPtr, const char *procName, Tcl_Obj *argsPtr, Tcl_Obj *bodyPtr, Proc **procPtrPtr); /* 10 */
    void (*tclDeleteCompiledLocalVars) (Interp *iPtr, CallFrame *framePtr); /* 11 */
    void (*tclDeleteVars) (Interp *iPtr, TclVarHashTable *tablePtr); /* 12 */
    void (*reserved13)(void);
    int (*tclDumpMemoryInfo) (void *clientData, int flags); /* 14 */
    void (*reserved15)(void);
    void (*tclExprFloatError) (Tcl_Interp *interp, double value); /* 16 */
    void (*reserved17)(void);
    void (*reserved18)(void);
    void (*reserved19)(void);
    void (*reserved20)(void);
    void (*reserved21)(void);
    int (*tclFindElement) (Tcl_Interp *interp, const char *listStr, int listLength, const char **elementPtr, const char **nextPtr, size_t *sizePtr, int *bracePtr); /* 22 */
    int (*tclFindElement) (Tcl_Interp *interp, const char *listStr, Tcl_Size listLength, const char **elementPtr, const char **nextPtr, Tcl_Size *sizePtr, int *bracePtr); /* 22 */
    Proc * (*tclFindProc) (Interp *iPtr, const char *procName); /* 23 */
    size_t (*tclFormatInt) (char *buffer, Tcl_WideInt n); /* 24 */
    Tcl_Size (*tclFormatInt) (char *buffer, Tcl_WideInt n); /* 24 */
    void (*tclFreePackageInfo) (Interp *iPtr); /* 25 */
    void (*reserved26)(void);
    void (*reserved27)(void);
    Tcl_Channel (*tclpGetDefaultStdChannel) (int type); /* 28 */
    void (*reserved29)(void);
    void (*reserved30)(void);
    const char * (*tclGetExtension) (const char *name); /* 31 */
    int (*tclGetFrame) (Tcl_Interp *interp, const char *str, CallFrame **framePtrPtr); /* 32 */
    void (*reserved33)(void);
    void (*reserved34)(void);
    void (*reserved35)(void);
    void (*reserved36)(void);
    int (*tclGetLoadedPackages) (Tcl_Interp *interp, const char *targetName); /* 37 */
    void (*reserved37)(void);
    int (*tclGetNamespaceForQualName) (Tcl_Interp *interp, const char *qualName, Namespace *cxtNsPtr, int flags, Namespace **nsPtrPtr, Namespace **altNsPtrPtr, Namespace **actualCxtPtrPtr, const char **simpleNamePtr); /* 38 */
    TclObjCmdProcType (*tclGetObjInterpProc) (void); /* 39 */
    int (*tclGetOpenMode) (Tcl_Interp *interp, const char *str, int *seekFlagPtr); /* 40 */
    Tcl_ObjCmdProc * (*tclGetObjInterpProc) (void); /* 39 */
    int (*tclGetOpenMode) (Tcl_Interp *interp, const char *str, int *modeFlagsPtr); /* 40 */
    Tcl_Command (*tclGetOriginalCommand) (Tcl_Command command); /* 41 */
    const char * (*tclpGetUserHome) (const char *name, Tcl_DString *bufferPtr); /* 42 */
    Tcl_ObjCmdProc2 * (*tclGetObjInterpProc2) (void); /* 43 */
    void (*reserved43)(void);
    void (*reserved44)(void);
    int (*tclGuessPackageName) (const char *fileName, Tcl_DString *bufPtr); /* 44 */
    int (*tclHideUnsafeCommands) (Tcl_Interp *interp); /* 45 */
    int (*tclInExit) (void); /* 46 */
    void (*reserved47)(void);
    void (*reserved48)(void);
    void (*reserved49)(void);
    void (*reserved50)(void);
    int (*tclInterpInit) (Tcl_Interp *interp); /* 51 */
    void (*reserved52)(void);
    int (*tclInvokeObjectCommand) (void *clientData, Tcl_Interp *interp, int argc, const char **argv); /* 53 */
    int (*tclInvokeStringCommand) (void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 54 */
    void (*reserved53)(void);
    void (*reserved54)(void);
    Proc * (*tclIsProc) (Command *cmdPtr); /* 55 */
    void (*reserved56)(void);
    void (*reserved57)(void);
    Var * (*tclLookupVar) (Tcl_Interp *interp, const char *part1, const char *part2, int flags, const char *msg, int createPart1, int createPart2, Var **arrayPtrPtr); /* 58 */
    void (*reserved59)(void);
    int (*tclNeedSpace) (const char *start, const char *end); /* 60 */
    Tcl_Obj * (*tclNewProcBodyObj) (Proc *procPtr); /* 61 */
    int (*tclObjCommandComplete) (Tcl_Obj *cmdPtr); /* 62 */
    int (*tclObjInterpProc) (void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 63 */
    int (*tclObjInvoke) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* 64 */
    void (*reserved63)(void);
    int (*tclObjInvoke) (Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], int flags); /* 64 */
    void (*reserved65)(void);
    void (*reserved66)(void);
    void (*reserved67)(void);
    void (*reserved68)(void);
    void * (*tclpAlloc) (size_t size); /* 69 */
    void * (*tclpAlloc) (TCL_HASH_TYPE size); /* 69 */
    void (*reserved70)(void);
    void (*reserved71)(void);
    void (*reserved72)(void);
    void (*reserved73)(void);
    void (*tclpFree) (void *ptr); /* 74 */
    Tcl_WideUInt (*tclpGetClicks) (void); /* 75 */
    Tcl_WideUInt (*tclpGetSeconds) (void); /* 76 */
    unsigned long long (*tclpGetClicks) (void); /* 75 */
    unsigned long long (*tclpGetSeconds) (void); /* 76 */
    void (*reserved77)(void);
    void (*reserved78)(void);
    void (*reserved79)(void);
    void (*reserved80)(void);
    void * (*tclpRealloc) (void *ptr, size_t size); /* 81 */
    void * (*tclpRealloc) (void *ptr, TCL_HASH_TYPE size); /* 81 */
    void (*reserved82)(void);
    void (*reserved83)(void);
    void (*reserved84)(void);
    void (*reserved85)(void);
    void (*reserved86)(void);
    void (*reserved87)(void);
    void (*reserved88)(void);
    int (*tclPreventAliasLoop) (Tcl_Interp *interp, Tcl_Interp *cmdInterp, Tcl_Command cmd); /* 89 */
    void (*reserved90)(void);
    void (*tclProcCleanupProc) (Proc *procPtr); /* 91 */
    int (*tclProcCompileProc) (Tcl_Interp *interp, Proc *procPtr, Tcl_Obj *bodyPtr, Namespace *nsPtr, const char *description, const char *procName); /* 92 */
    void (*tclProcDeleteProc) (void *clientData); /* 93 */
    void (*reserved94)(void);
    void (*reserved95)(void);
    int (*tclRenameCommand) (Tcl_Interp *interp, const char *oldName, const char *newName); /* 96 */
    void (*tclResetShadowedCmdRefs) (Tcl_Interp *interp, Command *newCmdPtr); /* 97 */
    int (*tclServiceIdle) (void); /* 98 */
    void (*reserved99)(void);
    void (*reserved100)(void);
    const char * (*tclSetPreInitScript) (const char *string); /* 101 */
    void (*reserved101)(void);
    void (*tclSetupEnv) (Tcl_Interp *interp); /* 102 */
    int (*tclSockGetPort) (Tcl_Interp *interp, const char *str, const char *proto, int *portPtr); /* 103 */
    void (*reserved104)(void);
    void (*reserved105)(void);
    void (*reserved106)(void);
    void (*reserved107)(void);
    void (*tclTeardownNamespace) (Namespace *nsPtr); /* 108 */
    int (*tclUpdateReturnInfo) (Interp *iPtr); /* 109 */
    int (*tclSockMinimumBuffers) (void *sock, int size); /* 110 */
    int (*tclSockMinimumBuffers) (void *sock, Tcl_Size size); /* 110 */
    void (*tcl_AddInterpResolvers) (Tcl_Interp *interp, const char *name, Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc, Tcl_ResolveCompiledVarProc *compiledVarProc); /* 111 */
    void (*reserved112)(void);
    void (*reserved113)(void);
    void (*reserved114)(void);
    void (*reserved115)(void);
    void (*reserved116)(void);
    void (*reserved117)(void);
720
721
722
723
724
725
726
727

728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748



749
750
751
752
753
754
755
756
757
758
759
760
761

762
763
764
765
766



767
768

769
770
771
772
773
774
775
708
709
710
711
712
713
714

715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733



734
735
736
737
738
739
740
741
742
743
744
745
746
747
748

749
750
751



752
753
754
755

756
757
758
759
760
761
762
763







-
+


















-
-
-
+
+
+












-
+


-
-
-
+
+
+

-
+







    void (*reserved125)(void);
    void (*tcl_GetVariableFullName) (Tcl_Interp *interp, Tcl_Var variable, Tcl_Obj *objPtr); /* 126 */
    void (*reserved127)(void);
    void (*tcl_PopCallFrame) (Tcl_Interp *interp); /* 128 */
    int (*tcl_PushCallFrame) (Tcl_Interp *interp, Tcl_CallFrame *framePtr, Tcl_Namespace *nsPtr, int isProcCallFrame); /* 129 */
    int (*tcl_RemoveInterpResolvers) (Tcl_Interp *interp, const char *name); /* 130 */
    void (*tcl_SetNamespaceResolvers) (Tcl_Namespace *namespacePtr, Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc, Tcl_ResolveCompiledVarProc *compiledVarProc); /* 131 */
    int (*tclpHasSockets) (Tcl_Interp *interp); /* 132 */
    void (*reserved132)(void);
    void (*reserved133)(void);
    void (*reserved134)(void);
    void (*reserved135)(void);
    void (*reserved136)(void);
    void (*reserved137)(void);
    const char * (*tclGetEnv) (const char *name, Tcl_DString *valuePtr); /* 138 */
    void (*reserved139)(void);
    void (*reserved140)(void);
    const char * (*tclpGetCwd) (Tcl_Interp *interp, Tcl_DString *cwdPtr); /* 141 */
    int (*tclSetByteCodeFromAny) (Tcl_Interp *interp, Tcl_Obj *objPtr, CompileHookProc *hookProc, void *clientData); /* 142 */
    int (*tclAddLiteralObj) (struct CompileEnv *envPtr, Tcl_Obj *objPtr, LiteralEntry **litPtrPtr); /* 143 */
    void (*tclHideLiteral) (Tcl_Interp *interp, struct CompileEnv *envPtr, int index); /* 144 */
    const struct AuxDataType * (*tclGetAuxDataType) (const char *typeName); /* 145 */
    TclHandle (*tclHandleCreate) (void *ptr); /* 146 */
    void (*tclHandleFree) (TclHandle handle); /* 147 */
    TclHandle (*tclHandlePreserve) (TclHandle handle); /* 148 */
    void (*tclHandleRelease) (TclHandle handle); /* 149 */
    int (*tclRegAbout) (Tcl_Interp *interp, Tcl_RegExp re); /* 150 */
    void (*tclRegExpRangeUniChar) (Tcl_RegExp re, size_t index, size_t *startPtr, size_t *endPtr); /* 151 */
    void (*tclSetLibraryPath) (Tcl_Obj *pathPtr); /* 152 */
    Tcl_Obj * (*tclGetLibraryPath) (void); /* 153 */
    void (*tclRegExpRangeUniChar) (Tcl_RegExp re, Tcl_Size index, Tcl_Size *startPtr, Tcl_Size *endPtr); /* 151 */
    void (*reserved152)(void);
    void (*reserved153)(void);
    void (*reserved154)(void);
    void (*reserved155)(void);
    void (*tclRegError) (Tcl_Interp *interp, const char *msg, int status); /* 156 */
    Var * (*tclVarTraceExists) (Tcl_Interp *interp, const char *varName); /* 157 */
    void (*reserved158)(void);
    void (*reserved159)(void);
    void (*reserved160)(void);
    int (*tclChannelTransform) (Tcl_Interp *interp, Tcl_Channel chan, Tcl_Obj *cmdObjPtr); /* 161 */
    void (*tclChannelEventScriptInvoker) (void *clientData, int flags); /* 162 */
    const void * (*tclGetInstructionTable) (void); /* 163 */
    void (*tclExpandCodeArray) (void *envPtr); /* 164 */
    void (*tclpSetInitialEncodings) (void); /* 165 */
    int (*tclListObjSetElement) (Tcl_Interp *interp, Tcl_Obj *listPtr, int index, Tcl_Obj *valuePtr); /* 166 */
    int (*tclListObjSetElement) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size index, Tcl_Obj *valuePtr); /* 166 */
    void (*reserved167)(void);
    void (*reserved168)(void);
    int (*tclpUtfNcmp2) (const char *s1, const char *s2, size_t n); /* 169 */
    int (*tclCheckInterpTraces) (Tcl_Interp *interp, const char *command, size_t numChars, Command *cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *const objv[]); /* 170 */
    int (*tclCheckExecutionTraces) (Tcl_Interp *interp, const char *command, size_t numChars, Command *cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *const objv[]); /* 171 */
    int (*tclpUtfNcmp2) (const void *s1, const void *s2, size_t n); /* 169 */
    int (*tclCheckInterpTraces) (Tcl_Interp *interp, const char *command, Tcl_Size numChars, Command *cmdPtr, int result, int traceFlags, Tcl_Size objc, Tcl_Obj *const objv[]); /* 170 */
    int (*tclCheckExecutionTraces) (Tcl_Interp *interp, const char *command, Tcl_Size numChars, Command *cmdPtr, int result, int traceFlags, Tcl_Size objc, Tcl_Obj *const objv[]); /* 171 */
    int (*tclInThreadExit) (void); /* 172 */
    int (*tclUniCharMatch) (const Tcl_UniChar *string, size_t strLen, const Tcl_UniChar *pattern, size_t ptnLen, int flags); /* 173 */
    int (*tclUniCharMatch) (const Tcl_UniChar *string, Tcl_Size strLen, const Tcl_UniChar *pattern, Tcl_Size ptnLen, int flags); /* 173 */
    void (*reserved174)(void);
    int (*tclCallVarTraces) (Interp *iPtr, Var *arrayPtr, Var *varPtr, const char *part1, const char *part2, int flags, int leaveErrMsg); /* 175 */
    void (*tclCleanupVar) (Var *varPtr, Var *arrayPtr); /* 176 */
    void (*tclVarErrMsg) (Tcl_Interp *interp, const char *part1, const char *part2, const char *operation, const char *reason); /* 177 */
    void (*reserved178)(void);
    void (*reserved179)(void);
    void (*reserved180)(void);
803
804
805
806
807
808
809
810

811
812
813
814

815
816
817
818



819
820

821
822

823
824
825

826
827
828
829
830
831
832
833
834


835
836
837

838
839
840
841

842
843

844
845
846
847
848
849




850
851
852
853
854
855






856
857
858
859
860
861
862
791
792
793
794
795
796
797

798
799
800
801

802
803



804
805
806
807

808
809

810
811
812

813
814
815
816
817
818
819
820


821
822
823
824

825
826
827
828

829
830

831
832
833




834
835
836
837
838





839
840
841
842
843
844
845
846
847
848
849
850
851







-
+



-
+

-
-
-
+
+
+

-
+

-
+


-
+







-
-
+
+


-
+



-
+

-
+


-
-
-
-
+
+
+
+

-
-
-
-
-
+
+
+
+
+
+







    Tcl_Channel (*tclpOpenFileChannel) (Tcl_Interp *interp, Tcl_Obj *pathPtr, int mode, int permissions); /* 208 */
    void (*reserved209)(void);
    void (*reserved210)(void);
    void (*reserved211)(void);
    void (*tclpFindExecutable) (const char *argv0); /* 212 */
    Tcl_Obj * (*tclGetObjNameOfExecutable) (void); /* 213 */
    void (*tclSetObjNameOfExecutable) (Tcl_Obj *name, Tcl_Encoding encoding); /* 214 */
    void * (*tclStackAlloc) (Tcl_Interp *interp, size_t numBytes); /* 215 */
    void * (*tclStackAlloc) (Tcl_Interp *interp, TCL_HASH_TYPE numBytes); /* 215 */
    void (*tclStackFree) (Tcl_Interp *interp, void *freePtr); /* 216 */
    int (*tclPushStackFrame) (Tcl_Interp *interp, Tcl_CallFrame **framePtrPtr, Tcl_Namespace *namespacePtr, int isProcCallFrame); /* 217 */
    void (*tclPopStackFrame) (Tcl_Interp *interp); /* 218 */
    void (*reserved219)(void);
    Tcl_Obj * (*tclpCreateTemporaryDirectory) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj); /* 219 */
    void (*reserved220)(void);
    void (*reserved221)(void);
    void (*reserved222)(void);
    void (*reserved223)(void);
    Tcl_Obj * (*tclListTestObj) (size_t length, size_t leadingSpace, size_t endSpace); /* 221 */
    void (*tclListObjValidate) (Tcl_Interp *interp, Tcl_Obj *listObj); /* 222 */
    void * (*tclGetCStackPtr) (void); /* 223 */
    TclPlatformType * (*tclGetPlatform) (void); /* 224 */
    Tcl_Obj * (*tclTraceDictPath) (Tcl_Interp *interp, Tcl_Obj *rootPtr, int keyc, Tcl_Obj *const keyv[], int flags); /* 225 */
    Tcl_Obj * (*tclTraceDictPath) (Tcl_Interp *interp, Tcl_Obj *rootPtr, Tcl_Size keyc, Tcl_Obj *const keyv[], int flags); /* 225 */
    int (*tclObjBeingDeleted) (Tcl_Obj *objPtr); /* 226 */
    void (*tclSetNsPath) (Namespace *nsPtr, size_t pathLength, Tcl_Namespace *pathAry[]); /* 227 */
    void (*tclSetNsPath) (Namespace *nsPtr, Tcl_Size pathLength, Tcl_Namespace *pathAry[]); /* 227 */
    void (*reserved228)(void);
    int (*tclPtrMakeUpvar) (Tcl_Interp *interp, Var *otherP1Ptr, const char *myName, int myFlags, int index); /* 229 */
    Var * (*tclObjLookupVar) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, const char *part2, int flags, const char *msg, const int createPart1, const int createPart2, Var **arrayPtrPtr); /* 230 */
    Var * (*tclObjLookupVar) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, const char *part2, int flags, const char *msg, int createPart1, int createPart2, Var **arrayPtrPtr); /* 230 */
    int (*tclGetNamespaceFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Namespace **nsPtrPtr); /* 231 */
    int (*tclEvalObjEx) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags, const CmdFrame *invoker, int word); /* 232 */
    void (*tclGetSrcInfoForPc) (CmdFrame *contextPtr); /* 233 */
    Var * (*tclVarHashCreateVar) (TclVarHashTable *tablePtr, const char *key, int *newPtr); /* 234 */
    void (*tclInitVarHashTable) (TclVarHashTable *tablePtr, Namespace *nsPtr); /* 235 */
    void (*reserved236)(void);
    int (*tclResetCancellation) (Tcl_Interp *interp, int force); /* 237 */
    int (*tclNRInterpProc) (void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 238 */
    int (*tclNRInterpProcCore) (Tcl_Interp *interp, Tcl_Obj *procNameObj, int skip, ProcErrorProc *errorProc); /* 239 */
    int (*tclNRInterpProc) (void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); /* 238 */
    int (*tclNRInterpProcCore) (Tcl_Interp *interp, Tcl_Obj *procNameObj, Tcl_Size skip, ProcErrorProc *errorProc); /* 239 */
    int (*tclNRRunCallbacks) (Tcl_Interp *interp, int result, struct NRE_callback *rootPtr); /* 240 */
    int (*tclNREvalObjEx) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags, const CmdFrame *invoker, int word); /* 241 */
    int (*tclNREvalObjv) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags, Command *cmdPtr); /* 242 */
    int (*tclNREvalObjv) (Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], int flags, Command *cmdPtr); /* 242 */
    void (*tclDbDumpActiveObjects) (FILE *outFile); /* 243 */
    Tcl_HashTable * (*tclGetNamespaceChildTable) (Tcl_Namespace *nsPtr); /* 244 */
    Tcl_HashTable * (*tclGetNamespaceCommandTable) (Tcl_Namespace *nsPtr); /* 245 */
    int (*tclInitRewriteEnsemble) (Tcl_Interp *interp, size_t numRemoved, size_t numInserted, Tcl_Obj *const *objv); /* 246 */
    int (*tclInitRewriteEnsemble) (Tcl_Interp *interp, Tcl_Size numRemoved, Tcl_Size numInserted, Tcl_Obj *const *objv); /* 246 */
    void (*tclResetRewriteEnsemble) (Tcl_Interp *interp, int isRootEnsemble); /* 247 */
    int (*tclCopyChannel) (Tcl_Interp *interp, Tcl_Channel inChan, Tcl_Channel outChan, Tcl_WideInt toRead, Tcl_Obj *cmdPtr); /* 248 */
    int (*tclCopyChannel) (Tcl_Interp *interp, Tcl_Channel inChan, Tcl_Channel outChan, long long toRead, Tcl_Obj *cmdPtr); /* 248 */
    char * (*tclDoubleDigits) (double dv, int ndigits, int flags, int *decpt, int *signum, char **endPtr); /* 249 */
    void (*tclSetChildCancelFlags) (Tcl_Interp *interp, int flags, int force); /* 250 */
    int (*tclRegisterLiteral) (void *envPtr, const char *bytes, size_t length, int flags); /* 251 */
    Tcl_Obj * (*tclPtrGetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const int flags); /* 252 */
    Tcl_Obj * (*tclPtrSetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, const int flags); /* 253 */
    Tcl_Obj * (*tclPtrIncrObjVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr, const int flags); /* 254 */
    int (*tclRegisterLiteral) (void *envPtr, const char *bytes, Tcl_Size length, int flags); /* 251 */
    Tcl_Obj * (*tclPtrGetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags); /* 252 */
    Tcl_Obj * (*tclPtrSetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags); /* 253 */
    Tcl_Obj * (*tclPtrIncrObjVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr, int flags); /* 254 */
    int (*tclPtrObjMakeUpvar) (Tcl_Interp *interp, Tcl_Var otherPtr, Tcl_Obj *myNamePtr, int myFlags); /* 255 */
    int (*tclPtrUnsetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const int flags); /* 256 */
    void (*tclStaticPackage) (Tcl_Interp *interp, const char *pkgName, Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc); /* 257 */
    Tcl_Obj * (*tclpCreateTemporaryDirectory) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj); /* 258 */
    void (*tclAppendUnicodeToObj) (Tcl_Obj *objPtr, const Tcl_UniChar *unicode, size_t length); /* 259 */
    unsigned char * (*tclGetBytesFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, size_t *lengthPtr); /* 260 */
    int (*tclPtrUnsetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags); /* 256 */
    void (*tclStaticLibrary) (Tcl_Interp *interp, const char *prefix, Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc); /* 257 */
    void (*reserved258)(void);
    void (*reserved259)(void);
    void (*reserved260)(void);
    void (*tclUnusedStubEntry) (void); /* 261 */
} TclIntStubs;

extern const TclIntStubs *tclIntStubsPtr;

#ifdef __cplusplus
}
#endif
917
918
919
920
921
922
923
924

925
926
927
928
929
930
931
932
933
934
935
936
937
938



939
940
941
942
943
944
945
946
947
948
949
950
951


952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967

968
969
970
971
972
973
974
975
906
907
908
909
910
911
912

913

914
915
916
917
918
919
920
921
922
923



924
925
926
927
928
929
930
931
932
933
934
935
936
937


938
939


940
941
942
943
944
945
946
947
948
949
950
951
952

953

954
955
956
957
958
959
960







-
+
-










-
-
-
+
+
+











-
-
+
+
-
-













-
+
-







	(tclIntStubsPtr->tclGetExtension) /* 31 */
#define TclGetFrame \
	(tclIntStubsPtr->tclGetFrame) /* 32 */
/* Slot 33 is reserved */
/* Slot 34 is reserved */
/* Slot 35 is reserved */
/* Slot 36 is reserved */
#define TclGetLoadedPackages \
/* Slot 37 is reserved */
	(tclIntStubsPtr->tclGetLoadedPackages) /* 37 */
#define TclGetNamespaceForQualName \
	(tclIntStubsPtr->tclGetNamespaceForQualName) /* 38 */
#define TclGetObjInterpProc \
	(tclIntStubsPtr->tclGetObjInterpProc) /* 39 */
#define TclGetOpenMode \
	(tclIntStubsPtr->tclGetOpenMode) /* 40 */
#define TclGetOriginalCommand \
	(tclIntStubsPtr->tclGetOriginalCommand) /* 41 */
#define TclpGetUserHome \
	(tclIntStubsPtr->tclpGetUserHome) /* 42 */
/* Slot 43 is reserved */
#define TclGuessPackageName \
	(tclIntStubsPtr->tclGuessPackageName) /* 44 */
#define TclGetObjInterpProc2 \
	(tclIntStubsPtr->tclGetObjInterpProc2) /* 43 */
/* Slot 44 is reserved */
#define TclHideUnsafeCommands \
	(tclIntStubsPtr->tclHideUnsafeCommands) /* 45 */
#define TclInExit \
	(tclIntStubsPtr->tclInExit) /* 46 */
/* Slot 47 is reserved */
/* Slot 48 is reserved */
/* Slot 49 is reserved */
/* Slot 50 is reserved */
#define TclInterpInit \
	(tclIntStubsPtr->tclInterpInit) /* 51 */
/* Slot 52 is reserved */
#define TclInvokeObjectCommand \
	(tclIntStubsPtr->tclInvokeObjectCommand) /* 53 */
/* Slot 53 is reserved */
/* Slot 54 is reserved */
#define TclInvokeStringCommand \
	(tclIntStubsPtr->tclInvokeStringCommand) /* 54 */
#define TclIsProc \
	(tclIntStubsPtr->tclIsProc) /* 55 */
/* Slot 56 is reserved */
/* Slot 57 is reserved */
#define TclLookupVar \
	(tclIntStubsPtr->tclLookupVar) /* 58 */
/* Slot 59 is reserved */
#define TclNeedSpace \
	(tclIntStubsPtr->tclNeedSpace) /* 60 */
#define TclNewProcBodyObj \
	(tclIntStubsPtr->tclNewProcBodyObj) /* 61 */
#define TclObjCommandComplete \
	(tclIntStubsPtr->tclObjCommandComplete) /* 62 */
#define TclObjInterpProc \
/* Slot 63 is reserved */
	(tclIntStubsPtr->tclObjInterpProc) /* 63 */
#define TclObjInvoke \
	(tclIntStubsPtr->tclObjInvoke) /* 64 */
/* Slot 65 is reserved */
/* Slot 66 is reserved */
/* Slot 67 is reserved */
/* Slot 68 is reserved */
#define TclpAlloc \
1012
1013
1014
1015
1016
1017
1018
1019
1020

1021
1022
1023
1024
1025
1026
1027
997
998
999
1000
1001
1002
1003


1004
1005
1006
1007
1008
1009
1010
1011







-
-
+







	(tclIntStubsPtr->tclRenameCommand) /* 96 */
#define TclResetShadowedCmdRefs \
	(tclIntStubsPtr->tclResetShadowedCmdRefs) /* 97 */
#define TclServiceIdle \
	(tclIntStubsPtr->tclServiceIdle) /* 98 */
/* Slot 99 is reserved */
/* Slot 100 is reserved */
#define TclSetPreInitScript \
	(tclIntStubsPtr->tclSetPreInitScript) /* 101 */
/* Slot 101 is reserved */
#define TclSetupEnv \
	(tclIntStubsPtr->tclSetupEnv) /* 102 */
#define TclSockGetPort \
	(tclIntStubsPtr->tclSockGetPort) /* 103 */
/* Slot 104 is reserved */
/* Slot 105 is reserved */
/* Slot 106 is reserved */
1058
1059
1060
1061
1062
1063
1064
1065
1066

1067
1068
1069
1070
1071
1072
1073
1042
1043
1044
1045
1046
1047
1048


1049
1050
1051
1052
1053
1054
1055
1056







-
-
+







	(tclIntStubsPtr->tcl_PopCallFrame) /* 128 */
#define Tcl_PushCallFrame \
	(tclIntStubsPtr->tcl_PushCallFrame) /* 129 */
#define Tcl_RemoveInterpResolvers \
	(tclIntStubsPtr->tcl_RemoveInterpResolvers) /* 130 */
#define Tcl_SetNamespaceResolvers \
	(tclIntStubsPtr->tcl_SetNamespaceResolvers) /* 131 */
#define TclpHasSockets \
	(tclIntStubsPtr->tclpHasSockets) /* 132 */
/* Slot 132 is reserved */
/* Slot 133 is reserved */
/* Slot 134 is reserved */
/* Slot 135 is reserved */
/* Slot 136 is reserved */
/* Slot 137 is reserved */
#define TclGetEnv \
	(tclIntStubsPtr->tclGetEnv) /* 138 */
1091
1092
1093
1094
1095
1096
1097
1098
1099

1100
1101

1102
1103
1104
1105
1106
1107
1108
1074
1075
1076
1077
1078
1079
1080


1081


1082
1083
1084
1085
1086
1087
1088
1089







-
-
+
-
-
+







	(tclIntStubsPtr->tclHandlePreserve) /* 148 */
#define TclHandleRelease \
	(tclIntStubsPtr->tclHandleRelease) /* 149 */
#define TclRegAbout \
	(tclIntStubsPtr->tclRegAbout) /* 150 */
#define TclRegExpRangeUniChar \
	(tclIntStubsPtr->tclRegExpRangeUniChar) /* 151 */
#define TclSetLibraryPath \
	(tclIntStubsPtr->tclSetLibraryPath) /* 152 */
/* Slot 152 is reserved */
#define TclGetLibraryPath \
	(tclIntStubsPtr->tclGetLibraryPath) /* 153 */
/* Slot 153 is reserved */
/* Slot 154 is reserved */
/* Slot 155 is reserved */
#define TclRegError \
	(tclIntStubsPtr->tclRegError) /* 156 */
#define TclVarTraceExists \
	(tclIntStubsPtr->tclVarTraceExists) /* 157 */
/* Slot 158 is reserved */
1193
1194
1195
1196
1197
1198
1199

1200

1201

1202
1203
1204





1205
1206
1207
1208
1209
1210
1211
1174
1175
1176
1177
1178
1179
1180
1181

1182
1183
1184



1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196







+
-
+

+
-
-
-
+
+
+
+
+







	(tclIntStubsPtr->tclStackAlloc) /* 215 */
#define TclStackFree \
	(tclIntStubsPtr->tclStackFree) /* 216 */
#define TclPushStackFrame \
	(tclIntStubsPtr->tclPushStackFrame) /* 217 */
#define TclPopStackFrame \
	(tclIntStubsPtr->tclPopStackFrame) /* 218 */
#define TclpCreateTemporaryDirectory \
/* Slot 219 is reserved */
	(tclIntStubsPtr->tclpCreateTemporaryDirectory) /* 219 */
/* Slot 220 is reserved */
#define TclListTestObj \
/* Slot 221 is reserved */
/* Slot 222 is reserved */
/* Slot 223 is reserved */
	(tclIntStubsPtr->tclListTestObj) /* 221 */
#define TclListObjValidate \
	(tclIntStubsPtr->tclListObjValidate) /* 222 */
#define TclGetCStackPtr \
	(tclIntStubsPtr->tclGetCStackPtr) /* 223 */
#define TclGetPlatform \
	(tclIntStubsPtr->tclGetPlatform) /* 224 */
#define TclTraceDictPath \
	(tclIntStubsPtr->tclTraceDictPath) /* 225 */
#define TclObjBeingDeleted \
	(tclIntStubsPtr->tclObjBeingDeleted) /* 226 */
#define TclSetNsPath \
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
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







-
-
+
+
-
-
+
-
-
-
-
+
+
+
+






-
-
-
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





	(tclIntStubsPtr->tclPtrSetVar) /* 253 */
#define TclPtrIncrObjVar \
	(tclIntStubsPtr->tclPtrIncrObjVar) /* 254 */
#define TclPtrObjMakeUpvar \
	(tclIntStubsPtr->tclPtrObjMakeUpvar) /* 255 */
#define TclPtrUnsetVar \
	(tclIntStubsPtr->tclPtrUnsetVar) /* 256 */
#define TclStaticPackage \
	(tclIntStubsPtr->tclStaticPackage) /* 257 */
#define TclStaticLibrary \
	(tclIntStubsPtr->tclStaticLibrary) /* 257 */
#define TclpCreateTemporaryDirectory \
	(tclIntStubsPtr->tclpCreateTemporaryDirectory) /* 258 */
/* Slot 258 is reserved */
#define TclAppendUnicodeToObj \
	(tclIntStubsPtr->tclAppendUnicodeToObj) /* 259 */
#define TclGetBytesFromObj \
	(tclIntStubsPtr->tclGetBytesFromObj) /* 260 */
/* Slot 259 is reserved */
/* Slot 260 is reserved */
#define TclUnusedStubEntry \
	(tclIntStubsPtr->tclUnusedStubEntry) /* 261 */

#endif /* defined(USE_TCL_STUBS) */

/* !END!: Do not edit above this line. */

#if defined(USE_TCL_STUBS)
#undef Tcl_StaticPackage
#define Tcl_StaticPackage \
	(tclIntStubsPtr->tclStaticPackage)
#undef Tcl_StaticLibrary
#define Tcl_StaticLibrary \
	(tclIntStubsPtr->tclStaticLibrary)
#endif /* defined(USE_TCL_STUBS) */

#if (TCL_MAJOR_VERSION < 9) && defined(USE_TCL_STUBS)
#undef TclpGetClicks
#define TclpGetClicks() \
		((unsigned long)tclIntStubsPtr->tclpGetClicks())
#undef TclpGetSeconds
#define TclpGetSeconds() \
		((unsigned long)tclIntStubsPtr->tclpGetSeconds())
#undef TclGetObjInterpProc2
#define TclGetObjInterpProc2 TclGetObjInterpProc
#endif

#undef TclUnusedStubEntry
#define TclObjInterpProc TclGetObjInterpProc()
#define TclObjInterpProc2 TclGetObjInterpProc2()

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#endif /* _TCLINTDECLS */

Changes to generic/tclIntPlatDecls.h.

26
27
28
29
30
31
32
33

34
35
36
37
38
39
40
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40







-
+








/*
 * WARNING: This file is automatically generated by the tools/genStubs.tcl
 * script.  Any modifications to the function declarations below should be made
 * in the generic/tclInt.decls script.
 */

/* !BEGIN!: Do not edit below this line. */
#if TCL_MAJOR_VERSION < 9

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Exported function declarations:
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
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







-
+
-








-
+
+







/* 3 */
EXTERN int		TclpCreatePipe(TclFile *readPipe, TclFile *writePipe);
/* 4 */
EXTERN int		TclpCreateProcess(Tcl_Interp *interp, int argc,
				const char **argv, TclFile inputFile,
				TclFile outputFile, TclFile errorFile,
				Tcl_Pid *pidPtr);
/* 5 */
/* Slot 5 is reserved */
EXTERN int		TclUnixWaitForFile_(int fd, int mask, int timeout);
/* 6 */
EXTERN TclFile		TclpMakeFile(Tcl_Channel channel, int direction);
/* 7 */
EXTERN TclFile		TclpOpenFile(const char *fname, int mode);
/* 8 */
EXTERN int		TclUnixWaitForFile(int fd, int mask, int timeout);
/* 9 */
EXTERN TclFile		TclpCreateTempFile(const char *contents);
/* Slot 10 is reserved */
/* 10 */
EXTERN Tcl_DirEntry *	TclpReaddir(TclDIR *dir);
/* Slot 11 is reserved */
/* Slot 12 is reserved */
/* Slot 13 is reserved */
/* 14 */
EXTERN int		TclUnixCopyFile(const char *src, const char *dst,
				const Tcl_StatBuf *statBufPtr,
				int dontCopyAtts);
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
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







-
+
-














-
+
-










-
+







				Tcl_StatBuf *statBufPtr,
				Tcl_GlobTypeData *types);
/* 19 */
EXTERN void		TclMacOSXNotifierAddRunLoopMode(
				const void *runLoopMode);
/* Slot 20 is reserved */
/* Slot 21 is reserved */
/* 22 */
/* Slot 22 is reserved */
EXTERN TclFile		TclpCreateTempFile_(const char *contents);
/* Slot 23 is reserved */
/* Slot 24 is reserved */
/* Slot 25 is reserved */
/* Slot 26 is reserved */
/* Slot 27 is reserved */
/* Slot 28 is reserved */
/* 29 */
EXTERN int		TclWinCPUID(int index, int *regs);
/* 30 */
EXTERN int		TclUnixOpenTemporaryFile(Tcl_Obj *dirObj,
				Tcl_Obj *basenameObj, Tcl_Obj *extensionObj,
				Tcl_Obj *resultingNameObj);
#endif /* UNIX */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
/* 0 */
/* Slot 0 is reserved */
EXTERN void		TclWinConvertError(int errCode);
/* Slot 1 is reserved */
/* Slot 2 is reserved */
/* Slot 3 is reserved */
/* 4 */
EXTERN void *		TclWinGetTclInstance(void);
/* 5 */
EXTERN int		TclUnixWaitForFile(int fd, int mask, int timeout);
/* Slot 6 is reserved */
/* Slot 7 is reserved */
/* 8 */
EXTERN size_t		TclpGetPid(Tcl_Pid pid);
EXTERN Tcl_Size		TclpGetPid(Tcl_Pid pid);
/* Slot 9 is reserved */
/* Slot 10 is reserved */
/* 11 */
EXTERN void		TclGetAndDetachPids(Tcl_Interp *interp,
				Tcl_Channel chan);
/* 12 */
EXTERN int		TclpCloseFile(TclFile file);
151
152
153
154
155
156
157
158

159
160
161
162
163
164
165
149
150
151
152
153
154
155

156
157
158
159
160
161
162
163







-
+







				const Tcl_StatBuf *statBufPtr,
				int dontCopyAtts);
/* 18 */
EXTERN TclFile		TclpMakeFile(Tcl_Channel channel, int direction);
/* 19 */
EXTERN TclFile		TclpOpenFile(const char *fname, int mode);
/* 20 */
EXTERN void		TclWinAddProcess(void *hProcess, size_t id);
EXTERN void		TclWinAddProcess(void *hProcess, Tcl_Size id);
/* Slot 21 is reserved */
/* 22 */
EXTERN TclFile		TclpCreateTempFile(const char *contents);
/* Slot 23 is reserved */
/* 24 */
EXTERN char *		TclWinNoBackslash(char *path);
/* Slot 25 is reserved */
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
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







-
+
-








-
-
+
+
-







/* 3 */
EXTERN int		TclpCreatePipe(TclFile *readPipe, TclFile *writePipe);
/* 4 */
EXTERN int		TclpCreateProcess(Tcl_Interp *interp, int argc,
				const char **argv, TclFile inputFile,
				TclFile outputFile, TclFile errorFile,
				Tcl_Pid *pidPtr);
/* 5 */
/* Slot 5 is reserved */
EXTERN int		TclUnixWaitForFile_(int fd, int mask, int timeout);
/* 6 */
EXTERN TclFile		TclpMakeFile(Tcl_Channel channel, int direction);
/* 7 */
EXTERN TclFile		TclpOpenFile(const char *fname, int mode);
/* 8 */
EXTERN int		TclUnixWaitForFile(int fd, int mask, int timeout);
/* 9 */
EXTERN TclFile		TclpCreateTempFile(const char *contents);
/* Slot 10 is reserved */
/* Slot 11 is reserved */
/* 10 */
EXTERN Tcl_DirEntry *	TclpReaddir(TclDIR *dir);
/* Slot 12 is reserved */
/* Slot 13 is reserved */
/* 14 */
EXTERN int		TclUnixCopyFile(const char *src, const char *dst,
				const Tcl_StatBuf *statBufPtr,
				int dontCopyAtts);
/* 15 */
EXTERN int		TclMacOSXGetFileAttribute(Tcl_Interp *interp,
227
228
229
230
231
232
233
234

235
236
237
238
239
240
241
242
223
224
225
226
227
228
229

230

231
232
233
234
235
236
237







-
+
-







				Tcl_StatBuf *statBufPtr,
				Tcl_GlobTypeData *types);
/* 19 */
EXTERN void		TclMacOSXNotifierAddRunLoopMode(
				const void *runLoopMode);
/* Slot 20 is reserved */
/* Slot 21 is reserved */
/* 22 */
/* Slot 22 is reserved */
EXTERN TclFile		TclpCreateTempFile_(const char *contents);
/* Slot 23 is reserved */
/* Slot 24 is reserved */
/* Slot 25 is reserved */
/* Slot 26 is reserved */
/* Slot 27 is reserved */
/* Slot 28 is reserved */
/* 29 */
258
259
260
261
262
263
264
265

266
267
268
269
270
271
272
253
254
255
256
257
258
259

260
261
262
263
264
265
266
267







-
+







    int (*tclpCreatePipe) (TclFile *readPipe, TclFile *writePipe); /* 3 */
    int (*tclpCreateProcess) (Tcl_Interp *interp, int argc, const char **argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid *pidPtr); /* 4 */
    int (*tclUnixWaitForFile_) (int fd, int mask, int timeout); /* 5 */
    TclFile (*tclpMakeFile) (Tcl_Channel channel, int direction); /* 6 */
    TclFile (*tclpOpenFile) (const char *fname, int mode); /* 7 */
    int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 8 */
    TclFile (*tclpCreateTempFile) (const char *contents); /* 9 */
    void (*reserved10)(void);
    Tcl_DirEntry * (*tclpReaddir) (TclDIR *dir); /* 10 */
    void (*reserved11)(void);
    void (*reserved12)(void);
    void (*reserved13)(void);
    int (*tclUnixCopyFile) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 14 */
    int (*tclMacOSXGetFileAttribute) (Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr); /* 15 */
    int (*tclMacOSXSetFileAttribute) (Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj *attributePtr); /* 16 */
    int (*tclMacOSXCopyFileAttributes) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr); /* 17 */
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
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







-
+







-
+

-
+









-
+







    void (*reserved26)(void);
    void (*reserved27)(void);
    void (*reserved28)(void);
    int (*tclWinCPUID) (int index, int *regs); /* 29 */
    int (*tclUnixOpenTemporaryFile) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); /* 30 */
#endif /* UNIX */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
    void (*tclWinConvertError) (int errCode); /* 0 */
    void (*reserved0)(void);
    void (*reserved1)(void);
    void (*reserved2)(void);
    void (*reserved3)(void);
    void * (*tclWinGetTclInstance) (void); /* 4 */
    int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 5 */
    void (*reserved6)(void);
    void (*reserved7)(void);
    size_t (*tclpGetPid) (Tcl_Pid pid); /* 8 */
    Tcl_Size (*tclpGetPid) (Tcl_Pid pid); /* 8 */
    void (*reserved9)(void);
    void (*reserved10)(void);
    void *(*tclpReaddir) (void *dir); /* 10 */
    void (*tclGetAndDetachPids) (Tcl_Interp *interp, Tcl_Channel chan); /* 11 */
    int (*tclpCloseFile) (TclFile file); /* 12 */
    Tcl_Channel (*tclpCreateCommandChannel) (TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr); /* 13 */
    int (*tclpCreatePipe) (TclFile *readPipe, TclFile *writePipe); /* 14 */
    int (*tclpCreateProcess) (Tcl_Interp *interp, int argc, const char **argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid *pidPtr); /* 15 */
    int (*tclpIsAtty) (int fd); /* 16 */
    int (*tclUnixCopyFile) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 17 */
    TclFile (*tclpMakeFile) (Tcl_Channel channel, int direction); /* 18 */
    TclFile (*tclpOpenFile) (const char *fname, int mode); /* 19 */
    void (*tclWinAddProcess) (void *hProcess, size_t id); /* 20 */
    void (*tclWinAddProcess) (void *hProcess, Tcl_Size id); /* 20 */
    void (*reserved21)(void);
    TclFile (*tclpCreateTempFile) (const char *contents); /* 22 */
    void (*reserved23)(void);
    char * (*tclWinNoBackslash) (char *path); /* 24 */
    void (*reserved25)(void);
    void (*reserved26)(void);
    void (*tclWinFlushDirtyChannels) (void); /* 27 */
324
325
326
327
328
329
330
331

332
333
334
335
336
337
338
319
320
321
322
323
324
325

326
327
328
329
330
331
332
333







-
+







    int (*tclpCreatePipe) (TclFile *readPipe, TclFile *writePipe); /* 3 */
    int (*tclpCreateProcess) (Tcl_Interp *interp, int argc, const char **argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid *pidPtr); /* 4 */
    int (*tclUnixWaitForFile_) (int fd, int mask, int timeout); /* 5 */
    TclFile (*tclpMakeFile) (Tcl_Channel channel, int direction); /* 6 */
    TclFile (*tclpOpenFile) (const char *fname, int mode); /* 7 */
    int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 8 */
    TclFile (*tclpCreateTempFile) (const char *contents); /* 9 */
    void (*reserved10)(void);
    Tcl_DirEntry * (*tclpReaddir) (TclDIR *dir); /* 10 */
    void (*reserved11)(void);
    void (*reserved12)(void);
    void (*reserved13)(void);
    int (*tclUnixCopyFile) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 14 */
    int (*tclMacOSXGetFileAttribute) (Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr); /* 15 */
    int (*tclMacOSXSetFileAttribute) (Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj *attributePtr); /* 16 */
    int (*tclMacOSXCopyFileAttributes) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr); /* 17 */
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
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







-
+
-








-
+
+

















-
+
-












-
+
-







	(tclIntPlatStubsPtr->tclpCloseFile) /* 1 */
#define TclpCreateCommandChannel \
	(tclIntPlatStubsPtr->tclpCreateCommandChannel) /* 2 */
#define TclpCreatePipe \
	(tclIntPlatStubsPtr->tclpCreatePipe) /* 3 */
#define TclpCreateProcess \
	(tclIntPlatStubsPtr->tclpCreateProcess) /* 4 */
#define TclUnixWaitForFile_ \
/* Slot 5 is reserved */
	(tclIntPlatStubsPtr->tclUnixWaitForFile_) /* 5 */
#define TclpMakeFile \
	(tclIntPlatStubsPtr->tclpMakeFile) /* 6 */
#define TclpOpenFile \
	(tclIntPlatStubsPtr->tclpOpenFile) /* 7 */
#define TclUnixWaitForFile \
	(tclIntPlatStubsPtr->tclUnixWaitForFile) /* 8 */
#define TclpCreateTempFile \
	(tclIntPlatStubsPtr->tclpCreateTempFile) /* 9 */
/* Slot 10 is reserved */
#define TclpReaddir \
	(tclIntPlatStubsPtr->tclpReaddir) /* 10 */
/* Slot 11 is reserved */
/* Slot 12 is reserved */
/* Slot 13 is reserved */
#define TclUnixCopyFile \
	(tclIntPlatStubsPtr->tclUnixCopyFile) /* 14 */
#define TclMacOSXGetFileAttribute \
	(tclIntPlatStubsPtr->tclMacOSXGetFileAttribute) /* 15 */
#define TclMacOSXSetFileAttribute \
	(tclIntPlatStubsPtr->tclMacOSXSetFileAttribute) /* 16 */
#define TclMacOSXCopyFileAttributes \
	(tclIntPlatStubsPtr->tclMacOSXCopyFileAttributes) /* 17 */
#define TclMacOSXMatchType \
	(tclIntPlatStubsPtr->tclMacOSXMatchType) /* 18 */
#define TclMacOSXNotifierAddRunLoopMode \
	(tclIntPlatStubsPtr->tclMacOSXNotifierAddRunLoopMode) /* 19 */
/* Slot 20 is reserved */
/* Slot 21 is reserved */
#define TclpCreateTempFile_ \
/* Slot 22 is reserved */
	(tclIntPlatStubsPtr->tclpCreateTempFile_) /* 22 */
/* Slot 23 is reserved */
/* Slot 24 is reserved */
/* Slot 25 is reserved */
/* Slot 26 is reserved */
/* Slot 27 is reserved */
/* Slot 28 is reserved */
#define TclWinCPUID \
	(tclIntPlatStubsPtr->tclWinCPUID) /* 29 */
#define TclUnixOpenTemporaryFile \
	(tclIntPlatStubsPtr->tclUnixOpenTemporaryFile) /* 30 */
#endif /* UNIX */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
#define TclWinConvertError \
/* Slot 0 is reserved */
	(tclIntPlatStubsPtr->tclWinConvertError) /* 0 */
/* Slot 1 is reserved */
/* Slot 2 is reserved */
/* Slot 3 is reserved */
#define TclWinGetTclInstance \
	(tclIntPlatStubsPtr->tclWinGetTclInstance) /* 4 */
#define TclUnixWaitForFile \
	(tclIntPlatStubsPtr->tclUnixWaitForFile) /* 5 */
475
476
477
478
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
468
469
470
471
472
473
474

475

476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720

721
722
723
724
725
726
727
728
729
730
731
732
733
734
735

736
737
738
739







-
+
-








-
+
+

















-
+
-














+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+



-

-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+



	(tclIntPlatStubsPtr->tclpCloseFile) /* 1 */
#define TclpCreateCommandChannel \
	(tclIntPlatStubsPtr->tclpCreateCommandChannel) /* 2 */
#define TclpCreatePipe \
	(tclIntPlatStubsPtr->tclpCreatePipe) /* 3 */
#define TclpCreateProcess \
	(tclIntPlatStubsPtr->tclpCreateProcess) /* 4 */
#define TclUnixWaitForFile_ \
/* Slot 5 is reserved */
	(tclIntPlatStubsPtr->tclUnixWaitForFile_) /* 5 */
#define TclpMakeFile \
	(tclIntPlatStubsPtr->tclpMakeFile) /* 6 */
#define TclpOpenFile \
	(tclIntPlatStubsPtr->tclpOpenFile) /* 7 */
#define TclUnixWaitForFile \
	(tclIntPlatStubsPtr->tclUnixWaitForFile) /* 8 */
#define TclpCreateTempFile \
	(tclIntPlatStubsPtr->tclpCreateTempFile) /* 9 */
/* Slot 10 is reserved */
#define TclpReaddir \
	(tclIntPlatStubsPtr->tclpReaddir) /* 10 */
/* Slot 11 is reserved */
/* Slot 12 is reserved */
/* Slot 13 is reserved */
#define TclUnixCopyFile \
	(tclIntPlatStubsPtr->tclUnixCopyFile) /* 14 */
#define TclMacOSXGetFileAttribute \
	(tclIntPlatStubsPtr->tclMacOSXGetFileAttribute) /* 15 */
#define TclMacOSXSetFileAttribute \
	(tclIntPlatStubsPtr->tclMacOSXSetFileAttribute) /* 16 */
#define TclMacOSXCopyFileAttributes \
	(tclIntPlatStubsPtr->tclMacOSXCopyFileAttributes) /* 17 */
#define TclMacOSXMatchType \
	(tclIntPlatStubsPtr->tclMacOSXMatchType) /* 18 */
#define TclMacOSXNotifierAddRunLoopMode \
	(tclIntPlatStubsPtr->tclMacOSXNotifierAddRunLoopMode) /* 19 */
/* Slot 20 is reserved */
/* Slot 21 is reserved */
#define TclpCreateTempFile_ \
/* Slot 22 is reserved */
	(tclIntPlatStubsPtr->tclpCreateTempFile_) /* 22 */
/* Slot 23 is reserved */
/* Slot 24 is reserved */
/* Slot 25 is reserved */
/* Slot 26 is reserved */
/* Slot 27 is reserved */
/* Slot 28 is reserved */
#define TclWinCPUID \
	(tclIntPlatStubsPtr->tclWinCPUID) /* 29 */
#define TclUnixOpenTemporaryFile \
	(tclIntPlatStubsPtr->tclUnixOpenTemporaryFile) /* 30 */
#endif /* MACOSX */

#endif /* defined(USE_TCL_STUBS) */

#else /* TCL_MAJOR_VERSION > 8 */
/* !BEGIN!: Do not edit below this line. */

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Exported function declarations:
 */

/* Slot 0 is reserved */
/* 1 */
EXTERN int		TclpCloseFile(TclFile file);
/* 2 */
EXTERN Tcl_Channel	TclpCreateCommandChannel(TclFile readFile,
				TclFile writeFile, TclFile errorFile,
				size_t numPids, Tcl_Pid *pidPtr);
/* 3 */
EXTERN int		TclpCreatePipe(TclFile *readPipe, TclFile *writePipe);
/* 4 */
EXTERN void *		TclWinGetTclInstance(void);
/* 5 */
EXTERN int		TclUnixWaitForFile(int fd, int mask, int timeout);
/* 6 */
EXTERN TclFile		TclpMakeFile(Tcl_Channel channel, int direction);
/* 7 */
EXTERN TclFile		TclpOpenFile(const char *fname, int mode);
/* 8 */
EXTERN Tcl_Size		TclpGetPid(Tcl_Pid pid);
/* 9 */
EXTERN TclFile		TclpCreateTempFile(const char *contents);
/* Slot 10 is reserved */
/* 11 */
EXTERN void		TclGetAndDetachPids(Tcl_Interp *interp,
				Tcl_Channel chan);
/* Slot 12 is reserved */
/* Slot 13 is reserved */
/* Slot 14 is reserved */
/* 15 */
EXTERN int		TclpCreateProcess(Tcl_Interp *interp, size_t argc,
				const char **argv, TclFile inputFile,
				TclFile outputFile, TclFile errorFile,
				Tcl_Pid *pidPtr);
/* 16 */
EXTERN int		TclpIsAtty(int fd);
/* 17 */
EXTERN int		TclUnixCopyFile(const char *src, const char *dst,
				const Tcl_StatBuf *statBufPtr,
				int dontCopyAtts);
/* Slot 18 is reserved */
/* Slot 19 is reserved */
/* 20 */
EXTERN void		TclWinAddProcess(void *hProcess, Tcl_Size id);
/* Slot 21 is reserved */
/* Slot 22 is reserved */
/* Slot 23 is reserved */
/* 24 */
EXTERN char *		TclWinNoBackslash(char *path);
/* Slot 25 is reserved */
/* Slot 26 is reserved */
/* 27 */
EXTERN void		TclWinFlushDirtyChannels(void);
/* Slot 28 is reserved */
/* 29 */
EXTERN int		TclWinCPUID(int index, int *regs);
/* 30 */
EXTERN int		TclUnixOpenTemporaryFile(Tcl_Obj *dirObj,
				Tcl_Obj *basenameObj, Tcl_Obj *extensionObj,
				Tcl_Obj *resultingNameObj);

typedef struct TclIntPlatStubs {
    int magic;
    void *hooks;

    void (*reserved0)(void);
    int (*tclpCloseFile) (TclFile file); /* 1 */
    Tcl_Channel (*tclpCreateCommandChannel) (TclFile readFile, TclFile writeFile, TclFile errorFile, size_t numPids, Tcl_Pid *pidPtr); /* 2 */
    int (*tclpCreatePipe) (TclFile *readPipe, TclFile *writePipe); /* 3 */
    void * (*tclWinGetTclInstance) (void); /* 4 */
    int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 5 */
    TclFile (*tclpMakeFile) (Tcl_Channel channel, int direction); /* 6 */
    TclFile (*tclpOpenFile) (const char *fname, int mode); /* 7 */
    Tcl_Size (*tclpGetPid) (Tcl_Pid pid); /* 8 */
    TclFile (*tclpCreateTempFile) (const char *contents); /* 9 */
    void (*reserved10)(void);
    void (*tclGetAndDetachPids) (Tcl_Interp *interp, Tcl_Channel chan); /* 11 */
    void (*reserved12)(void);
    void (*reserved13)(void);
    void (*reserved14)(void);
    int (*tclpCreateProcess) (Tcl_Interp *interp, size_t argc, const char **argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid *pidPtr); /* 15 */
    int (*tclpIsAtty) (int fd); /* 16 */
    int (*tclUnixCopyFile) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 17 */
    void (*reserved18)(void);
    void (*reserved19)(void);
    void (*tclWinAddProcess) (void *hProcess, Tcl_Size id); /* 20 */
    void (*reserved21)(void);
    void (*reserved22)(void);
    void (*reserved23)(void);
    char * (*tclWinNoBackslash) (char *path); /* 24 */
    void (*reserved25)(void);
    void (*reserved26)(void);
    void (*tclWinFlushDirtyChannels) (void); /* 27 */
    void (*reserved28)(void);
    int (*tclWinCPUID) (int index, int *regs); /* 29 */
    int (*tclUnixOpenTemporaryFile) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); /* 30 */
} TclIntPlatStubs;

extern const TclIntPlatStubs *tclIntPlatStubsPtr;

#ifdef __cplusplus
}
#endif

#if defined(USE_TCL_STUBS)

/*
 * Inline function declarations:
 */

/* Slot 0 is reserved */
#define TclpCloseFile \
	(tclIntPlatStubsPtr->tclpCloseFile) /* 1 */
#define TclpCreateCommandChannel \
	(tclIntPlatStubsPtr->tclpCreateCommandChannel) /* 2 */
#define TclpCreatePipe \
	(tclIntPlatStubsPtr->tclpCreatePipe) /* 3 */
#define TclWinGetTclInstance \
	(tclIntPlatStubsPtr->tclWinGetTclInstance) /* 4 */
#define TclUnixWaitForFile \
	(tclIntPlatStubsPtr->tclUnixWaitForFile) /* 5 */
#define TclpMakeFile \
	(tclIntPlatStubsPtr->tclpMakeFile) /* 6 */
#define TclpOpenFile \
	(tclIntPlatStubsPtr->tclpOpenFile) /* 7 */
#define TclpGetPid \
	(tclIntPlatStubsPtr->tclpGetPid) /* 8 */
#define TclpCreateTempFile \
	(tclIntPlatStubsPtr->tclpCreateTempFile) /* 9 */
/* Slot 10 is reserved */
#define TclGetAndDetachPids \
	(tclIntPlatStubsPtr->tclGetAndDetachPids) /* 11 */
/* Slot 12 is reserved */
/* Slot 13 is reserved */
/* Slot 14 is reserved */
#define TclpCreateProcess \
	(tclIntPlatStubsPtr->tclpCreateProcess) /* 15 */
#define TclpIsAtty \
	(tclIntPlatStubsPtr->tclpIsAtty) /* 16 */
#define TclUnixCopyFile \
	(tclIntPlatStubsPtr->tclUnixCopyFile) /* 17 */
/* Slot 18 is reserved */
/* Slot 19 is reserved */
#define TclWinAddProcess \
	(tclIntPlatStubsPtr->tclWinAddProcess) /* 20 */
/* Slot 21 is reserved */
/* Slot 22 is reserved */
/* Slot 23 is reserved */
#define TclWinNoBackslash \
	(tclIntPlatStubsPtr->tclWinNoBackslash) /* 24 */
/* Slot 25 is reserved */
/* Slot 26 is reserved */
#define TclWinFlushDirtyChannels \
	(tclIntPlatStubsPtr->tclWinFlushDirtyChannels) /* 27 */
/* Slot 28 is reserved */
#define TclWinCPUID \
	(tclIntPlatStubsPtr->tclWinCPUID) /* 29 */
#define TclUnixOpenTemporaryFile \
	(tclIntPlatStubsPtr->tclUnixOpenTemporaryFile) /* 30 */

#endif /* defined(USE_TCL_STUBS) */

/* !END!: Do not edit above this line. */
#endif /* TCL_MAJOR_VERSION */

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT
#define TclWinConvertWSAError TclWinConvertError

#undef TclpCreateTempFile_
#undef TclUnixWaitForFile_
#ifndef MAC_OSX_TCL /* not accessable on Win32/UNIX */
#ifdef MAC_OSX_TCL /* not accessible on Win32/UNIX */
MODULE_SCOPE int TclMacOSXGetFileAttribute(Tcl_Interp *interp,
	int objIndex, Tcl_Obj *fileName,
	Tcl_Obj **attributePtrPtr);
/* 16 */
MODULE_SCOPE int TclMacOSXSetFileAttribute(Tcl_Interp *interp,
	int objIndex, Tcl_Obj *fileName,
	Tcl_Obj *attributePtr);
/* 17 */
MODULE_SCOPE int TclMacOSXCopyFileAttributes(const char *src,
	const char *dst,
	const Tcl_StatBuf *statBufPtr);
/* 18 */
MODULE_SCOPE int TclMacOSXMatchType(Tcl_Interp *interp,
	const char *pathName, const char *fileName,
	Tcl_StatBuf *statBufPtr,
	Tcl_GlobTypeData *types);
#else
#undef TclMacOSXGetFileAttribute /* 15 */
#undef TclMacOSXSetFileAttribute /* 16 */
#undef TclMacOSXCopyFileAttributes /* 17 */
#undef TclMacOSXMatchType /* 18 */
#undef TclMacOSXNotifierAddRunLoopMode /* 19 */
#endif

#if !defined(_WIN32)
#if defined(_WIN32)
#   if !defined(TCL_NO_DEPRECATED)
#	define TclWinConvertError Tcl_WinConvertError
#	define TclWinConvertWSAError Tcl_WinConvertError
#	define TclWinNToHS ntohs
#	define TclpInetNtoa inet_ntoa
#	define TclWinGetServByName getservbyname
#	define TclWinGetSockOpt getsockopt
#	define TclWinSetSockOpt setsockopt
#	define TclWinGetPlatformId() (2) /* VER_PLATFORM_WIN32_NT */
#	define TclWinResetInterfaces() /* nop */
#	define TclWinSetInterfaces(dummy) /* nop */
#   endif /* TCL_NO_DEPRECATED */
#else
#   undef TclpGetPid
#   define TclpGetPid(pid) ((size_t)(pid))
#   define TclpGetPid(pid) ((Tcl_Size)(pid))
#endif

#endif /* _TCLINTPLATDECLS */

Changes to generic/tclInterp.c.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * tclInterp.c --
 *
 *	This file implements the "interp" command which allows creation and
 *	manipulation of Tcl interpreters from within Tcl scripts.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 2004 Donal K. Fellows
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2004 Donal K. Fellows
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
47
48
49
50
51
52
53

54
55
56
57
58
59
60
61
62

63
64
65
66
67
68
69
70







-
+








-
+







				 * This is used by alias deletion to remove
				 * the alias from the child interpreter alias
				 * table. */
    struct Target *targetPtr;	/* Entry for target command in parent. This is
				 * used in the parent interpreter to map back
				 * from the target command to aliases
				 * redirecting to it. */
    int objc;			/* Count of Tcl_Obj in the prefix of the
    Tcl_Size objc;		/* Count of Tcl_Obj in the prefix of the
				 * target command to be invoked in the target
				 * interpreter. Additional arguments specified
				 * when calling the alias in the child interp
				 * will be appended to the prefix before the
				 * command is invoked. */
    Tcl_Obj *objPtr;		/* The first actual prefix object - the target
				 * command name; this has to be at the end of
				 * the structure, which will be extended to
				 * accomodate the remaining objects in the
				 * accommodate the remaining objects in the
				 * prefix. */
} Alias;

/*
 *
 * Child:
 *
133
134
135
136
137
138
139




140
141
142
143
144
145
146
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150







+
+
+
+







    Target *targetsPtr;		/* The head of a doubly-linked list of all the
				 * target records which denote aliases from
				 * children or sibling interpreters that direct
				 * to commands in this interpreter. This list
				 * is used to remove dangling pointers from
				 * the child (or sibling) interpreters when
				 * this interpreter is deleted. */
    Tcl_Size idIssuer;		/* Used to issue a sequence of names for
				 * "unnamed" child interpreters. We keep a
				 * count here to avoid having to scan over IDs
				 * for interpreters that we've already used. */
} Parent;

/*
 * The following structure keeps track of all the Parent and Child information
 * on a per-interp basis.
 */

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
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







-
+









+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-

-
+
+
+
+
+







-
+






-
-
+
+

-
+

-
+

-
+





-
+

-
+

-
+


-
+





-
+




-
+


-
-
+
+

-
-
+
+




-
+

-
+
+


-
+





-




-
+














-
+




-
+







 * TIP#143 limit handler internal representation.
 */

struct LimitHandler {
    int flags;			/* The state of this particular handler. */
    Tcl_LimitHandlerProc *handlerProc;
				/* The handler callback. */
    ClientData clientData;	/* Opaque argument to the handler callback. */
    void *clientData;		/* Opaque argument to the handler callback. */
    Tcl_LimitHandlerDeleteProc *deleteProc;
				/* How to delete the clientData. */
    LimitHandler *prevPtr;	/* Previous item in linked list of
				 * handlers. */
    LimitHandler *nextPtr;	/* Next item in linked list of handlers. */
};

/*
 * Values for the LimitHandler flags field.
 */
enum LimitHandlerFlags {
 *      LIMIT_HANDLER_ACTIVE - Whether the handler is currently being
 *              processed; handlers are never to be entered reentrantly.
 *      LIMIT_HANDLER_DELETED - Whether the handler has been deleted. This
 *              should not normally be observed because when a handler is
 *              deleted it is also spliced out of the list of handlers, but
 *              even so we will be careful.
 */

    LIMIT_HANDLER_ACTIVE = 1,	/* The handler is currently being processed;
				 * handlers are never to be reentered. */
    LIMIT_HANDLER_DELETED = 2	/* The handler has been deleted. This should
				 * not normally be observed because when a
				 * handler is deleted it is also spliced out of
				 * the list of handlers, but even so we will be
				 * careful.*/
};
#define LIMIT_HANDLER_ACTIVE    0x01
#define LIMIT_HANDLER_DELETED   0x02


/*
 * Macro to make looking up child and parent info more convenient.
 */
#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, int objc,
			    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;
static Tcl_ObjCmdProc	AliasNRCmd;
static Tcl_CmdDeleteProc AliasObjCmdDeleteProc;
static Tcl_Interp *	GetInterp(Tcl_Interp *interp, Tcl_Obj *pathPtr);
static Tcl_Interp *	GetInterp2(Tcl_Interp *interp, int objc,
static Tcl_Interp *	GetInterp2(Tcl_Interp *interp, Tcl_Size objc,
			    Tcl_Obj *const objv[]);
static Tcl_InterpDeleteProc	InterpInfoDeleteProc;
static Tcl_InterpDeleteProc InterpInfoDeleteProc;
static int		ChildBgerror(Tcl_Interp *interp,
			    Tcl_Interp *childInterp, int objc,
			    Tcl_Interp *childInterp, Tcl_Size objc,
			    Tcl_Obj *const objv[]);
static Tcl_Interp *	ChildCreate(Tcl_Interp *interp, Tcl_Obj *pathPtr,
			    int safe);
static int		ChildDebugCmd(Tcl_Interp *interp,
			    Tcl_Interp *childInterp,
			    int objc, Tcl_Obj *const objv[]);
			    Tcl_Size objc, Tcl_Obj *const objv[]);
static int		ChildEval(Tcl_Interp *interp, Tcl_Interp *childInterp,
			    int objc, Tcl_Obj *const objv[]);
			    Tcl_Size objc, Tcl_Obj *const objv[]);
static int		ChildExpose(Tcl_Interp *interp,
			    Tcl_Interp *childInterp, int objc,
			    Tcl_Interp *childInterp, Tcl_Size objc,
			    Tcl_Obj *const objv[]);
static int		ChildHide(Tcl_Interp *interp, Tcl_Interp *childInterp,
			    int objc, Tcl_Obj *const objv[]);
			    Tcl_Size objc, Tcl_Obj *const objv[]);
static int		ChildHidden(Tcl_Interp *interp,
			    Tcl_Interp *childInterp);
static int		ChildInvokeHidden(Tcl_Interp *interp,
			    Tcl_Interp *childInterp,
			    const char *namespaceName,
			    int objc, Tcl_Obj *const objv[]);
			    Tcl_Size objc, Tcl_Obj *const objv[]);
static int		ChildMarkTrusted(Tcl_Interp *interp,
			    Tcl_Interp *childInterp);
static Tcl_CmdDeleteProc	ChildObjCmdDeleteProc;
static int		ChildRecursionLimit(Tcl_Interp *interp,
			    Tcl_Interp *childInterp, int objc,
			    Tcl_Interp *childInterp, Tcl_Size objc,
			    Tcl_Obj *const objv[]);
static int		ChildCommandLimitCmd(Tcl_Interp *interp,
			    Tcl_Interp *childInterp, int consumedObjc,
			    int objc, Tcl_Obj *const objv[]);
			    Tcl_Interp *childInterp, Tcl_Size consumedObjc,
			    Tcl_Size objc, Tcl_Obj *const objv[]);
static int		ChildTimeLimitCmd(Tcl_Interp *interp,
			    Tcl_Interp *childInterp, int consumedObjc,
			    int objc, Tcl_Obj *const objv[]);
			    Tcl_Interp *childInterp, Tcl_Size consumedObjc,
			    Tcl_Size objc, Tcl_Obj *const objv[]);
static void		InheritLimitsFromParent(Tcl_Interp *childInterp,
			    Tcl_Interp *parentInterp);
static void		SetScriptLimitCallback(Tcl_Interp *interp, int type,
			    Tcl_Interp *targetInterp, Tcl_Obj *scriptObj);
static void		CallScriptLimitCallback(ClientData clientData,
static void		CallScriptLimitCallback(void *clientData,
			    Tcl_Interp *interp);
static void		DeleteScriptLimitCallback(ClientData clientData);
static void		DeleteScriptLimitCallback(void *clientData);
static void		MakeSafe(Tcl_Interp *interp);
static void		RunLimitHandlers(LimitHandler *handlerPtr,
			    Tcl_Interp *interp);
static void		TimeLimitCallback(ClientData clientData);
static void		TimeLimitCallback(void *clientData);

/* NRE enabling */
static Tcl_NRPostProc	NRPostInvokeHidden;
static Tcl_ObjCmdProc	NRInterpCmd;
static Tcl_ObjCmdProc	NRChildCmd;


/*
 *----------------------------------------------------------------------
 *
 * TclSetPreInitScript --
 * Tcl_SetPreInitScript --
 *
 *	This routine is used to change the value of the internal variable,
 *	tclPreInitScript.
 *
 * Results:
 *	Returns the current value of tclPreInitScript.
 *
 * Side effects:
 *	Changes the way Tcl_Init() routine behaves.
 *
 *----------------------------------------------------------------------
 */

const char *
TclSetPreInitScript(
Tcl_SetPreInitScript(
    const char *string)		/* Pointer to a script. */
{
    const char *prevString = tclPreInitScript;
    tclPreInitScript = string;
    return(prevString);
    return prevString;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Init --
 *
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
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







-
-
-
-
-




+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+





-
+
+







 *
 * Side effects:
 *	Depends on what's in the init.tcl script.
 *
 *----------------------------------------------------------------------
 */

typedef struct PkgName {
    struct PkgName *nextPtr;	/* Next in list of package names being initialized. */
    char name[4];
} PkgName;

int
Tcl_Init(
    Tcl_Interp *interp)		/* Interpreter to initialize. */
{
    /*
     * Splice for putting the "tcl" package in the list of packages while the
     * pre-init and init scripts are running. The real version of this struct
     * is in tclPkg.c.
     */
    typedef struct PkgName {
	struct PkgName *nextPtr;/* Next in list of package names being
				 * initialized. */
	char name[4];		/* Enough space for "tcl". The *real* version
				 * of this structure uses a flex array. */
    } PkgName;

    PkgName pkgName = {NULL, "Tcl"};
    PkgName **names = (PkgName **)TclInitPkgFiles(interp);
    PkgName pkgName = {NULL, "tcl"};
    PkgName **names = (PkgName **) TclInitPkgFiles(interp);
    int result = TCL_ERROR;

    pkgName.nextPtr = *names;
    *names = &pkgName;
    if (tclPreInitScript != NULL) {
	if (Tcl_EvalEx(interp, tclPreInitScript, -1, 0) == TCL_ERROR) {
	if (Tcl_EvalEx(interp, tclPreInitScript, TCL_INDEX_NONE,
		0 /*flags*/) == TCL_ERROR) {
	    goto end;
	}
    }

    /*
     * In order to find init.tcl during initialization, the following script
     * is invoked by Tcl_Init(). It looks in several different directories:
397
398
399
400
401
402
403

404
405
406
407
408
409
410
411
412
413
414
415
416
413
414
415
416
417
418
419
420
421
422
423
424
425

426
427
428
429
430
431
432







+





-







"	if {[info exists env(TCL_LIBRARY)] && ($env(TCL_LIBRARY) ne {})} {\n"
"	    lappend scripts {set env(TCL_LIBRARY)}\n"
"	    lappend scripts {\n"
"if {[regexp ^tcl(.*)$ [file tail $env(TCL_LIBRARY)] -> tail] == 0} continue\n"
"if {$tail eq [info tclversion]} continue\n"
"file join [file dirname $env(TCL_LIBRARY)] tcl[info tclversion]}\n"
"	}\n"
"	lappend scripts {::tcl::zipfs::tcl_library_init}\n"
"	if {[info exists tclDefaultLibrary]} {\n"
"	    lappend scripts {set tclDefaultLibrary}\n"
"	} else {\n"
"	    lappend scripts {::tcl::pkgconfig get scriptdir,runtime}\n"
"	}\n"
"	lappend scripts {::tcl::zipfs::tcl_library_init}\n"
"	lappend scripts {\n"
"set parentDir [file dirname [file dirname [info nameofexecutable]]]\n"
"set grandParentDir [file dirname $parentDir]\n"
"file join $parentDir lib tcl[info tclversion]} \\\n"
"	{file join $grandParentDir lib tcl[info tclversion]} \\\n"
"	{file join $parentDir library} \\\n"
"	{file join $grandParentDir library} \\\n"
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
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
467


468
469
470
471
472
473
474
475
476







-
-
+










+


-
+






-
-
+
+







"		lappend scripts [list lindex \\$tcl_libPath $i]\n"
"	    }\n"
"	}\n"
"    }\n"
"    set dirs {}\n"
"    set errors {}\n"
"    foreach script $scripts {\n"
"	lappend dirs [eval $script]\n"
"	set tcl_library [lindex $dirs end]\n"
"	if {[set tcl_library [eval $script]] eq \"\"} continue\n"
"	set tclfile [file join $tcl_library init.tcl]\n"
"	if {[file exists $tclfile]} {\n"
"	    if {[catch {uplevel #0 [list source $tclfile]} msg opts]} {\n"
"		append errors \"$tclfile: $msg\n\"\n"
"		append errors \"[dict get $opts -errorinfo]\n\"\n"
"		continue\n"
"	    }\n"
"	    unset -nocomplain tclDefaultLibrary\n"
"	    return\n"
"	}\n"
"	lappend dirs $tcl_library\n"
"    }\n"
"    unset -nocomplain tclDefaultLibrary\n"
"    set msg \"Can't find a usable init.tcl in the following directories: \n\"\n"
"    set msg \"Cannot find a usable init.tcl in the following directories: \n\"\n"
"    append msg \"    $dirs\n\n\"\n"
"    append msg \"$errors\n\n\"\n"
"    append msg \"This probably means that Tcl wasn't installed properly.\n\"\n"
"    error $msg\n"
"  }\n"
"}\n"
"tclInit", -1, 0);

"tclInit", TCL_INDEX_NONE, 0);
    TclpSetInitialEncodings();
end:
    *names = (*names)->nextPtr;
    return result;
}

/*
 *---------------------------------------------------------------------------
478
479
480
481
482
483
484
485

486
487
488
489
490

491
492
493
494
495
496
497
494
495
496
497
498
499
500

501
502
503
504
505
506
507
508
509
510
511
512
513
514







-
+





+







TclInterpInit(
    Tcl_Interp *interp)		/* Interpreter to initialize. */
{
    InterpInfo *interpInfoPtr;
    Parent *parentPtr;
    Child *childPtr;

    interpInfoPtr = (InterpInfo *)Tcl_Alloc(sizeof(InterpInfo));
    interpInfoPtr = (InterpInfo *) Tcl_Alloc(sizeof(InterpInfo));
    ((Interp *) interp)->interpInfo = interpInfoPtr;

    parentPtr = &interpInfoPtr->parent;
    Tcl_InitHashTable(&parentPtr->childTable, TCL_STRING_KEYS);
    parentPtr->targetsPtr = NULL;
    parentPtr->idIssuer = 0;

    childPtr = &interpInfoPtr->child;
    childPtr->parentInterp	= NULL;
    childPtr->childEntryPtr	= NULL;
    childPtr->childInterp	= interp;
    childPtr->interpCmd		= NULL;
    Tcl_InitHashTable(&childPtr->aliasTable, TCL_STRING_KEYS);
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
558
559
560
539
540
541
542
543
544
545

546
547
548
549
550


551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576







-
+




-
-


















+








static void
InterpInfoDeleteProc(
    TCL_UNUSED(void *),
    Tcl_Interp *interp)		/* Interp being deleted. All commands for
				 * child interps should already be deleted. */
{
    InterpInfo *interpInfoPtr;
    InterpInfo *interpInfoPtr = INTERP_INFO(interp);
    Child *childPtr;
    Parent *parentPtr;
    Target *targetPtr;

    interpInfoPtr = (InterpInfo *) ((Interp *) interp)->interpInfo;

    /*
     * There shouldn't be any commands left.
     */

    parentPtr = &interpInfoPtr->parent;
    if (parentPtr->childTable.numEntries != 0) {
	Tcl_Panic("InterpInfoDeleteProc: still exist commands");
    }
    Tcl_DeleteHashTable(&parentPtr->childTable);

    /*
     * Tell any interps that have aliases to this interp that they should
     * delete those aliases. If the other interp was already dead, it would
     * have removed the target record already.
     */

    for (targetPtr = parentPtr->targetsPtr; targetPtr != NULL; ) {
	Target *tmpPtr = targetPtr->nextPtr;

	Tcl_DeleteCommandFromToken(targetPtr->childInterp,
		targetPtr->childCmd);
	targetPtr = tmpPtr;
    }

    childPtr = &interpInfoPtr->child;
    if (childPtr->interpCmd != NULL) {
597
598
599
600
601
602
603
604
605
606
607




608
609
610
611
612
613
614
615
616
617



618
619
620
621
622
623
624
625
626
627
613
614
615
616
617
618
619




620
621
622
623
624
625
626
627
628
629
630



631
632
633
634
635

636
637
638
639
640
641
642







-
-
-
-
+
+
+
+







-
-
-
+
+
+


-







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_InterpObjCmd(
    ClientData clientData,
    Tcl_Interp *interp,			/* Current interpreter. */
    int objc,				/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument objects. */
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, NRInterpCmd, clientData, objc, objv);
}

static int
NRInterpCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,			/* Current interpreter. */
    int objc,				/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument objects. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Interp *childInterp;
    int index;
    static const char *const options[] = {
	"alias",	"aliases",	"bgerror",	"cancel",
	"children",	"create",	"debug",	"delete",
	"eval",		"exists",	"expose",	"hide",
	"hidden",	"issafe",	"invokehidden",
	"limit",	"marktrusted",	"recursionlimit",
	"share",
645
646
647
648
649
650
651
652


653
654
655
656
657
658
659


660
661
662
663
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
707
708
709
710
711
712
713

714
715
716
717
718
719
720
721

722
723
724
725
726
727
728
729

730
731
732
733

734
735
736
737
738
739
740
660
661
662
663
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
707

708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729

730
731
732
733
734
735
736


737

738
739
740
741
742
743

744
745
746
747

748
749
750
751
752
753
754
755







-
+
+





-
-
+
+





-
+




-
+
-
-
-




















+
-
+
+
+
+


















-
+






-
-
+
-






-
+



-
+







	OPT_EVAL,	OPT_EXISTS,	OPT_EXPOSE,	OPT_HIDE,
	OPT_HIDDEN,	OPT_ISSAFE,	OPT_INVOKEHID,
	OPT_LIMIT,	OPT_MARKTRUSTED, OPT_RECLIMIT, OPT_SHARE,
#ifndef TCL_NO_DEPRECATED
	OPT_SLAVES,
#endif
	OPT_TARGET,	OPT_TRANSFER
    };
    } index;
    Tcl_Size i;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "cmd ?arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(NULL, objv[1], options,
	    "option", 0, &index) != TCL_OK) {
    if (Tcl_GetIndexFromObj(NULL, objv[1], options, NULL, 0,
	    &index) != TCL_OK) {
	/* Don't report the "slaves" option as possibility */
	Tcl_GetIndexFromObj(interp, objv[1], optionsNoSlaves,
		"option", 0, &index);
	return TCL_ERROR;
    }
    switch ((enum interpOptionEnum)index) {
    switch (index) {
    case OPT_ALIAS: {
	Tcl_Interp *parentInterp;

	if (objc < 4) {
	aliasArgs:
	    goto aliasArgs;
	    Tcl_WrongNumArgs(interp, 2, objv,
		    "childPath childCmd ?parentPath parentCmd? ?arg ...?");
	    return TCL_ERROR;
	}
	childInterp = GetInterp(interp, objv[2]);
	if (childInterp == NULL) {
	    return TCL_ERROR;
	}
	if (objc == 4) {
	    return AliasDescribe(interp, childInterp, objv[3]);
	}
	if ((objc == 5) && (TclGetString(objv[4])[0] == '\0')) {
	    return AliasDelete(interp, childInterp, objv[3]);
	}
	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);
	}

	goto aliasArgs;
    aliasArgs:
	Tcl_WrongNumArgs(interp, 2, objv,
		"childPath childCmd ?parentPath parentCmd? ?arg ...?");
	return TCL_ERROR;
    }
    case OPT_ALIASES:
	childInterp = GetInterp2(interp, objc, objv);
	if (childInterp == NULL) {
	    return TCL_ERROR;
	}
	return AliasList(interp, childInterp);
    case OPT_BGERROR:
	if (objc != 3 && objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "path ?cmdPrefix?");
	    return TCL_ERROR;
	}
	childInterp = GetInterp(interp, objv[2]);
	if (childInterp == NULL) {
	    return TCL_ERROR;
	}
	return ChildBgerror(interp, childInterp, objc - 3, objv + 3);
    case OPT_CANCEL: {
	int i, flags;
	int flags = 0;
	Tcl_Obj *resultObjPtr;
	static const char *const cancelOptions[] = {
	    "-unwind",	"--",	NULL
	};
	enum optionCancelEnum {
	    OPT_UNWIND,	OPT_LAST
	};

	} idx;
	flags = 0;

	for (i = 2; i < objc; i++) {
	    if (TclGetString(objv[i])[0] != '-') {
		break;
	    }
	    if (Tcl_GetIndexFromObj(interp, objv[i], cancelOptions, "option",
		    0, &index) != TCL_OK) {
		    0, &idx) != TCL_OK) {
		return TCL_ERROR;
	    }

	    switch ((enum optionCancelEnum) index) {
	    switch (idx) {
	    case OPT_UNWIND:
		/*
		 * The evaluation stack in the target interp is to be unwound.
		 */

		flags |= TCL_CANCEL_UNWIND;
		break;
778
779
780
781
782
783
784
785

786
787
788
789
790
791
792
793

794
795
796
797
798
799
800
801
802
803
804
805
806

807
808
809

810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825



826
827
828
829
830
831
832
833
834
835
836
837




838
839
840
841
842
843
844
845

846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878

879
880
881

882
883
884
885
886
887
888
793
794
795
796
797
798
799

800
801
802
803
804
805
806
807

808
809
810
811
812
813
814
815
816
817
818
819
820

821
822
823

824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850





851
852
853
854



855
856
857


858

859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899







-
+







-
+












-
+


-
+
















+
+
+







-
-
-
-
-
+
+
+
+
-
-
-



-
-
+
-




















-










-
+


-
+







	} else {
	    resultObjPtr = NULL;
	}

	return Tcl_CancelEval(childInterp, resultObjPtr, 0, flags);
    }
    case OPT_CREATE: {
	int i, last, safe;
	int last, safe;
	Tcl_Obj *childPtr;
	char buf[16 + TCL_INTEGER_SPACE];
	static const char *const createOptions[] = {
	    "-safe",	"--", NULL
	};
	enum option {
	    OPT_SAFE,	OPT_LAST
	};
	} idx;

	safe = Tcl_IsSafe(interp);

	/*
	 * Weird historical rules: "-safe" is accepted at the end, too.
	 */

	childPtr = NULL;
	last = 0;
	for (i = 2; i < objc; i++) {
	    if ((last == 0) && (TclGetString(objv[i])[0] == '-')) {
		if (Tcl_GetIndexFromObj(interp, objv[i], createOptions,
			"option", 0, &index) != TCL_OK) {
			"option", 0, &idx) != TCL_OK) {
		    return TCL_ERROR;
		}
		if (index == OPT_SAFE) {
		if (idx == OPT_SAFE) {
		    safe = 1;
		    continue;
		}
		i++;
		last = 1;
	    }
	    if (childPtr != NULL) {
		Tcl_WrongNumArgs(interp, 2, objv, "?-safe? ?--? ?path?");
		return TCL_ERROR;
	    }
	    if (i < objc) {
		childPtr = objv[i];
	    }
	}
	buf[0] = '\0';
	if (childPtr == NULL) {
	    Parent *parentInfo = &INTERP_INFO(interp)->parent;
	    Tcl_CmdInfo cmdInfo;

	    /*
	     * Create an anonymous interpreter -- we choose its name and the
	     * name of the command. We check that the command name that we use
	     * for the interpreter does not collide with an existing command
	     * in the parent interpreter.
	     */

	    for (i = 0; ; i++) {
		Tcl_CmdInfo cmdInfo;

		sprintf(buf, "interp%d", i);
		if (Tcl_GetCommandInfo(interp, buf, &cmdInfo) == 0) {
	    do {
		snprintf(buf, sizeof(buf), "interp%" TCL_SIZE_MODIFIER "d",
			parentInfo->idIssuer++);
	    } while (Tcl_GetCommandInfo(interp, buf, &cmdInfo));
		    break;
		}
	    }
	    childPtr = Tcl_NewStringObj(buf, -1);
	}
	if (ChildCreate(interp, childPtr, safe) == NULL) {
	    if (buf[0] != '\0') {
		Tcl_DecrRefCount(childPtr);
	    Tcl_BounceRefCount(childPtr);
	    }
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, childPtr);
	return TCL_OK;
    }
    case OPT_DEBUG:		/* TIP #378 */
	/*
	 * Currently only -frame supported, otherwise ?-option ?value??
	 */

	if (objc < 3 || objc > 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "path ?-frame ?bool??");
	    return TCL_ERROR;
	}
	childInterp = GetInterp(interp, objv[2]);
	if (childInterp == NULL) {
	    return TCL_ERROR;
	}
	return ChildDebugCmd(interp, childInterp, objc - 3, objv + 3);
    case OPT_DELETE: {
	int i;
	InterpInfo *iiPtr;

	for (i = 2; i < objc; i++) {
	    childInterp = GetInterp(interp, objv[i]);
	    if (childInterp == NULL) {
		return TCL_ERROR;
	    } else if (childInterp == interp) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"cannot delete the current interpreter", -1));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
			"DELETESELF", NULL);
			"DELETESELF", (char *)NULL);
		return TCL_ERROR;
	    }
	    iiPtr = (InterpInfo *) ((Interp *) childInterp)->interpInfo;
	    iiPtr = INTERP_INFO(childInterp);
	    Tcl_DeleteCommandFromToken(iiPtr->child.parentInterp,
		    iiPtr->child.interpCmd);
	}
	return TCL_OK;
    }
    case OPT_EVAL:
	if (objc < 4) {
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952

953
954
955
956
957
958
959
960

961
962
963

964
965

966
967
968
969
970
971
972
949
950
951
952
953
954
955

956
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







-






-
+







-
+


-
+

-
+







	childInterp = GetInterp2(interp, objc, objv);
	if (childInterp == NULL) {
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Tcl_IsSafe(childInterp)));
	return TCL_OK;
    case OPT_INVOKEHID: {
	int i;
	const char *namespaceName;
	static const char *const hiddenOptions[] = {
	    "-global",	"-namespace",	"--", NULL
	};
	enum hiddenOption {
	    OPT_GLOBAL,	OPT_NAMESPACE,	OPT_LAST
	};
	} idx;

	namespaceName = NULL;
	for (i = 3; i < objc; i++) {
	    if (TclGetString(objv[i])[0] != '-') {
		break;
	    }
	    if (Tcl_GetIndexFromObj(interp, objv[i], hiddenOptions, "option",
		    0, &index) != TCL_OK) {
		    0, &idx) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (index == OPT_GLOBAL) {
	    if (idx == OPT_GLOBAL) {
		namespaceName = "::";
	    } else if (index == OPT_NAMESPACE) {
	    } else if (idx == OPT_NAMESPACE) {
		if (++i == objc) { /* There must be more arguments. */
		    break;
		} else {
		    namespaceName = TclGetString(objv[i]);
		}
	    } else {
		i++;
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
1024
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
1024
1025
1026
1027
1028

1029
1030
1031
1032
1033
1034
1035







-
-
+














-
+




+
+
+


-







    }
    case OPT_LIMIT: {
	static const char *const limitTypes[] = {
	    "commands", "time", NULL
	};
	enum LimitTypes {
	    LIMIT_TYPE_COMMANDS, LIMIT_TYPE_TIME
	};
	int limitType;
	} limitType;

	if (objc < 4) {
	    Tcl_WrongNumArgs(interp, 2, objv,
		    "path limitType ?-option value ...?");
	    return TCL_ERROR;
	}
	childInterp = GetInterp(interp, objv[2]);
	if (childInterp == NULL) {
	    return TCL_ERROR;
	}
	if (Tcl_GetIndexFromObj(interp, objv[3], limitTypes, "limit type", 0,
		&limitType) != TCL_OK) {
	    return TCL_ERROR;
	}
	switch ((enum LimitTypes) limitType) {
	switch (limitType) {
	case LIMIT_TYPE_COMMANDS:
	    return ChildCommandLimitCmd(interp, childInterp, 4, objc,objv);
	case LIMIT_TYPE_TIME:
	    return ChildTimeLimitCmd(interp, childInterp, 4, objc, objv);
	default:
	    Tcl_Panic("unreachable");
	    return TCL_ERROR;
	}
    }
    break;
    case OPT_MARKTRUSTED:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "path");
	    return TCL_ERROR;
	}
	childInterp = GetInterp(interp, objv[2]);
	if (childInterp == NULL) {
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
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







-
+



-
+












-
+







	Tcl_HashSearch hashSearch;
	char *string;

	childInterp = GetInterp2(interp, objc, objv);
	if (childInterp == NULL) {
	    return TCL_ERROR;
	}
	iiPtr = (InterpInfo *) ((Interp *) childInterp)->interpInfo;
	iiPtr = INTERP_INFO(childInterp);
	TclNewObj(resultPtr);
	hPtr = Tcl_FirstHashEntry(&iiPtr->parent.childTable, &hashSearch);
	for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&hashSearch)) {
	    string = (char *)Tcl_GetHashKey(&iiPtr->parent.childTable, hPtr);
	    string = (char *) Tcl_GetHashKey(&iiPtr->parent.childTable, hPtr);
	    Tcl_ListObjAppendElement(NULL, resultPtr,
		    Tcl_NewStringObj(string, -1));
	}
	Tcl_SetObjResult(interp, resultPtr);
	return TCL_OK;
    }
    case OPT_TRANSFER:
    case OPT_SHARE: {
	Tcl_Interp *parentInterp;	/* The parent of the child. */
	Tcl_Channel chan;

	if (objc != 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "srcPath channelId destPath");
	    Tcl_WrongNumArgs(interp, 2, objv, "srcPath channel destPath");
	    return TCL_ERROR;
	}
	parentInterp = GetInterp(interp, objv[2]);
	if (parentInterp == NULL) {
	    return TCL_ERROR;
	}
	chan = Tcl_GetChannel(parentInterp, TclGetString(objv[3]), NULL);
1110
1111
1112
1113
1114
1115
1116
1117

1118
1119
1120
1121
1122
1123
1124

1125
1126
1127

1128
1129
1130
1131
1132
1133

1134
1135
1136
1137



1138
1139
1140
1141
1142
1143
1144
1145
1146
1121
1122
1123
1124
1125
1126
1127

1128
1129
1130
1131
1132
1133
1134

1135
1136
1137

1138
1139
1140
1141
1142
1143

1144
1145
1146
1147
1148
1149
1150
1151
1152

1153
1154
1155
1156
1157
1158
1159







-
+






-
+


-
+





-
+




+
+
+

-







	childInterp = GetInterp(interp, objv[2]);
	if (childInterp == NULL) {
	    return TCL_ERROR;
	}

	aliasName = TclGetString(objv[3]);

	iiPtr = (InterpInfo *) ((Interp *) childInterp)->interpInfo;
	iiPtr = INTERP_INFO(childInterp);
	hPtr = Tcl_FindHashEntry(&iiPtr->child.aliasTable, aliasName);
	if (hPtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "alias \"%s\" in path \"%s\" not found",
		    aliasName, TclGetString(objv[2])));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS", aliasName,
		    NULL);
		    (char *)NULL);
	    return TCL_ERROR;
	}
	aliasPtr = (Alias *)Tcl_GetHashValue(hPtr);
	aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
	if (Tcl_GetInterpPath(interp, aliasPtr->targetInterp) != TCL_OK) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "target interpreter for alias \"%s\" in path \"%s\" is "
		    "not my descendant", aliasName, TclGetString(objv[2])));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
		    "TARGETSHROUDED", NULL);
		    "TARGETSHROUDED", (char *)NULL);
	    return TCL_ERROR;
	}
	return TCL_OK;
    }
    default:
	Tcl_Panic("unreachable");
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *---------------------------------------------------------------------------
 *
 * GetInterp2 --
 *
1160
1161
1162
1163
1164
1165
1166
1167

1168
1169
1170
1171
1172
1173
1174
1173
1174
1175
1176
1177
1178
1179

1180
1181
1182
1183
1184
1185
1186
1187







-
+







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

static Tcl_Interp *
GetInterp2(
    Tcl_Interp *interp,		/* Default interp if no interp was specified
				 * on the command line. */
    int objc,			/* Number of arguments. */
    Tcl_Size objc,		/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    if (objc == 2) {
	return interp;
    } else if (objc == 3) {
	return GetInterp(interp, objv[2]);
    } else {
1195
1196
1197
1198
1199
1200
1201
1202

1203
1204
1205
1206
1207

1208
1209
1210

1211
1212
1213
1214
1215
1216
1217
1208
1209
1210
1211
1212
1213
1214

1215
1216
1217
1218
1219

1220
1221
1222

1223
1224
1225
1226
1227
1228
1229
1230







-
+




-
+


-
+








int
Tcl_CreateAlias(
    Tcl_Interp *childInterp,	/* Interpreter for source command. */
    const char *childCmd,	/* Command to install in child. */
    Tcl_Interp *targetInterp,	/* Interpreter for target command. */
    const char *targetCmd,	/* Name of target command. */
    int argc,			/* How many additional arguments? */
    Tcl_Size argc,		/* How many additional arguments? */
    const char *const *argv)	/* These are the additional args. */
{
    Tcl_Obj *childObjPtr, *targetObjPtr;
    Tcl_Obj **objv;
    int i;
    Tcl_Size i;
    int result;

    objv = (Tcl_Obj **)TclStackAlloc(childInterp, sizeof(Tcl_Obj *) * argc);
    objv = (Tcl_Obj **) TclStackAlloc(childInterp, sizeof(Tcl_Obj *) * argc);
    for (i = 0; i < argc; i++) {
	objv[i] = Tcl_NewStringObj(argv[i], -1);
	Tcl_IncrRefCount(objv[i]);
    }

    childObjPtr = Tcl_NewStringObj(childCmd, -1);
    Tcl_IncrRefCount(childObjPtr);
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
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







-
+


















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








int
Tcl_CreateAliasObj(
    Tcl_Interp *childInterp,	/* Interpreter for source command. */
    const char *childCmd,	/* Command to install in child. */
    Tcl_Interp *targetInterp,	/* Interpreter for target command. */
    const char *targetCmd,	/* Name of target command. */
    int objc,			/* How many additional arguments? */
    Tcl_Size objc,		/* How many additional arguments? */
    Tcl_Obj *const objv[])	/* Argument vector. */
{
    Tcl_Obj *childObjPtr, *targetObjPtr;
    int result;

    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;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetAlias --
 *
 *	Gets information about an alias.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_GetAlias(
    Tcl_Interp *interp,		/* Interp to start search from. */
    const char *aliasName,	/* Name of alias to find. */
    Tcl_Interp **targetInterpPtr,
				/* (Return) target interpreter. */
    const char **targetNamePtr,	/* (Return) name of target command. */
    int *argcPtr,		/* (Return) count of addnl args. */
    const char ***argvPtr)	/* (Return) additional arguments. */
{
    InterpInfo *iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo;
    Tcl_HashEntry *hPtr;
    Alias *aliasPtr;
    int i, objc;
    Tcl_Obj **objv;

    hPtr = Tcl_FindHashEntry(&iiPtr->child.aliasTable, aliasName);
    if (hPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"alias \"%s\" not found", aliasName));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS", aliasName, NULL);
	return TCL_ERROR;
    }
    aliasPtr = (Alias *)Tcl_GetHashValue(hPtr);
    objc = aliasPtr->objc;
    objv = &aliasPtr->objPtr;

    if (targetInterpPtr != NULL) {
	*targetInterpPtr = aliasPtr->targetInterp;
    }
    if (targetNamePtr != NULL) {
	*targetNamePtr = TclGetString(objv[0]);
    }
    if (argcPtr != NULL) {
	*argcPtr = objc - 1;
    }
    if (argvPtr != NULL) {
	*argvPtr = (const char **)
		Tcl_Alloc(sizeof(const char *) * (objc - 1));
	for (i = 1; i < objc; i++) {
	    (*argvPtr)[i - 1] = TclGetString(objv[i]);
	}
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetAliasObj --
 *
 *	Object version: Gets information about an alias.
1354
1355
1356
1357
1358
1359
1360
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


1387
1388
1389
1390
1391
1392
1393
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







-
-
+
+


-
+


-
+






-
+
+


-
+






-
-
+
+








int
Tcl_GetAliasObj(
    Tcl_Interp *interp,		/* Interp to start search from. */
    const char *aliasName,	/* Name of alias to find. */
    Tcl_Interp **targetInterpPtr,
				/* (Return) target interpreter. */
    const char **targetNamePtr,	/* (Return) name of target command. */
    int *objcPtr,		/* (Return) count of addnl args. */
    const char **targetCmdPtr,	/* (Return) name of target command. */
    Tcl_Size *objcPtr,		/* (Return) count of addnl args. */
    Tcl_Obj ***objvPtr)		/* (Return) additional args. */
{
    InterpInfo *iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo;
    InterpInfo *iiPtr = INTERP_INFO(interp);
    Tcl_HashEntry *hPtr;
    Alias *aliasPtr;
    int objc;
    Tcl_Size objc;
    Tcl_Obj **objv;

    hPtr = Tcl_FindHashEntry(&iiPtr->child.aliasTable, aliasName);
    if (hPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"alias \"%s\" not found", aliasName));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS", aliasName, NULL);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS", aliasName,
		(char *)NULL);
	return TCL_ERROR;
    }
    aliasPtr = (Alias *)Tcl_GetHashValue(hPtr);
    aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
    objc = aliasPtr->objc;
    objv = &aliasPtr->objPtr;

    if (targetInterpPtr != NULL) {
	*targetInterpPtr = aliasPtr->targetInterp;
    }
    if (targetNamePtr != NULL) {
	*targetNamePtr = TclGetString(objv[0]);
    if (targetCmdPtr != NULL) {
	*targetCmdPtr = TclGetString(objv[0]);
    }
    if (objcPtr != NULL) {
	*objcPtr = objc - 1;
    }
    if (objvPtr != NULL) {
	*objvPtr = objv + 1;
    }
1440
1441
1442
1443
1444
1445
1446
1447

1448
1449
1450
1451
1452
1453
1454
1392
1393
1394
1395
1396
1397
1398

1399
1400
1401
1402
1403
1404
1405
1406







-
+








    /*
     * OK, we are dealing with an alias, so traverse the chain of aliases. If
     * we encounter the alias we are defining (or renaming to) any in the
     * chain then we have a loop.
     */

    aliasPtr = (Alias *)cmdPtr->objClientData;
    aliasPtr = (Alias *) cmdPtr->objClientData;
    nextAliasPtr = aliasPtr;
    while (1) {
	Tcl_Obj *cmdNamePtr;

	/*
	 * If the target of the next alias in the chain is the same as the
	 * source alias, we have a loop.
1475
1476
1477
1478
1479
1480
1481
1482

1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496

1497
1498
1499
1500
1501
1502
1503
1427
1428
1429
1430
1431
1432
1433

1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447

1448
1449
1450
1451
1452
1453
1454
1455







-
+













-
+







	}
	aliasCmdPtr = (Command *) aliasCmd;
	if (aliasCmdPtr == cmdPtr) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "cannot define or rename alias \"%s\": would create a loop",
		    Tcl_GetCommandName(cmdInterp, cmd)));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
		    "ALIASLOOP", NULL);
		    "ALIASLOOP", (char *)NULL);
	    return TCL_ERROR;
	}

	/*
	 * Otherwise, follow the chain one step further. See if the target
	 * command is an alias - if so, follow the loop to its target command.
	 * Otherwise we do not have a loop.
	 */

	if (aliasCmdPtr->objProc != TclAliasObjCmd
		&& aliasCmdPtr->objProc != TclLocalAliasObjCmd) {
	    return TCL_OK;
	}
	nextAliasPtr = (Alias *)aliasCmdPtr->objClientData;
	nextAliasPtr = (Alias *) aliasCmdPtr->objClientData;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * AliasCreate --
1518
1519
1520
1521
1522
1523
1524
1525
1526


1527
1528
1529
1530
1531
1532
1533
1534
1535


1536
1537

1538
1539
1540
1541
1542
1543
1544
1545
1546


1547
1548
1549
1550
1551
1552
1553
1470
1471
1472
1473
1474
1475
1476


1477
1478
1479
1480
1481
1482
1483
1484
1485
1486

1487
1488
1489

1490
1491
1492
1493
1494
1495
1496
1497


1498
1499
1500
1501
1502
1503
1504
1505
1506







-
-
+
+








-
+
+

-
+







-
-
+
+







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 *targetNamePtr,	/* Name of target cmd. */
    int objc,			/* Additional arguments to store */
    Tcl_Obj *targetCmdPtr,	/* Name of target cmd. */
    Tcl_Size objc,		/* Additional arguments to store */
    Tcl_Obj *const objv[])	/* with alias. */
{
    Alias *aliasPtr;
    Tcl_HashEntry *hPtr;
    Target *targetPtr;
    Child *childPtr;
    Parent *parentPtr;
    Tcl_Obj **prefv;
    int isNew, i;
    int isNew;
    Tcl_Size i;

    aliasPtr = (Alias *)Tcl_Alloc(sizeof(Alias) + objc * sizeof(Tcl_Obj *));
    aliasPtr = (Alias *) Tcl_Alloc(sizeof(Alias) + objc * sizeof(Tcl_Obj *));
    aliasPtr->token = namePtr;
    Tcl_IncrRefCount(aliasPtr->token);
    aliasPtr->targetInterp = parentInterp;

    aliasPtr->objc = objc + 1;
    prefv = &aliasPtr->objPtr;

    *prefv = targetNamePtr;
    Tcl_IncrRefCount(targetNamePtr);
    *prefv = targetCmdPtr;
    Tcl_IncrRefCount(targetCmdPtr);
    for (i = 0; i < objc; i++) {
	*(++prefv) = objv[i];
	Tcl_IncrRefCount(objv[i]);
    }

    Tcl_Preserve(childInterp);
    Tcl_Preserve(parentInterp);
1570
1571
1572
1573
1574
1575
1576
1577

1578
1579
1580
1581
1582
1583
1584
1523
1524
1525
1526
1527
1528
1529

1530
1531
1532
1533
1534
1535
1536
1537







-
+







	 * careful to wipe out its client data first, so the command doesn't
	 * try to delete itself.
	 */

	Command *cmdPtr;

	Tcl_DecrRefCount(aliasPtr->token);
	Tcl_DecrRefCount(targetNamePtr);
	Tcl_DecrRefCount(targetCmdPtr);
	for (i = 0; i < objc; i++) {
	    Tcl_DecrRefCount(objv[i]);
	}

	cmdPtr = (Command *) aliasPtr->childCmd;
	cmdPtr->clientData = NULL;
	cmdPtr->deleteProc = NULL;
1596
1597
1598
1599
1600
1601
1602
1603

1604
1605
1606
1607
1608
1609
1610
1549
1550
1551
1552
1553
1554
1555

1556
1557
1558
1559
1560
1561
1562
1563







-
+







	return TCL_ERROR;
    }

    /*
     * Make an entry in the alias table. If it already exists, retry.
     */

    childPtr = &((InterpInfo *) ((Interp *) childInterp)->interpInfo)->child;
    childPtr = &INTERP_INFO(childInterp)->child;
    while (1) {
	Tcl_Obj *newToken;
	const char *string;

	string = TclGetString(aliasPtr->token);
	hPtr = Tcl_CreateHashEntry(&childPtr->aliasTable, string, &isNew);
	if (isNew != 0) {
1638
1639
1640
1641
1642
1643
1644
1645

1646
1647
1648
1649

1650
1651
1652
1653
1654
1655
1656
1591
1592
1593
1594
1595
1596
1597

1598
1599
1600
1601

1602
1603
1604
1605
1606
1607
1608
1609







-
+



-
+







     * because the alias may be pointing at a renamed alias, as in:
     *
     * interp alias {} foo {} bar		# Create an alias "foo"
     * rename foo zop				# Now rename the alias
     * interp alias {} foo {} zop		# Now recreate "foo"...
     */

    targetPtr = (Target *)Tcl_Alloc(sizeof(Target));
    targetPtr = (Target *) Tcl_Alloc(sizeof(Target));
    targetPtr->childCmd = aliasPtr->childCmd;
    targetPtr->childInterp = childInterp;

    parentPtr = &((InterpInfo*) ((Interp*) parentInterp)->interpInfo)->parent;
    parentPtr = &INTERP_INFO(parentInterp)->parent;
    targetPtr->nextPtr = parentPtr->targetsPtr;
    targetPtr->prevPtr = NULL;
    if (parentPtr->targetsPtr != NULL) {
	parentPtr->targetsPtr->prevPtr = targetPtr;
    }
    parentPtr->targetsPtr = targetPtr;
    aliasPtr->targetPtr = targetPtr;
1690
1691
1692
1693
1694
1695
1696
1697

1698
1699
1700
1701
1702
1703

1704
1705
1706

1707
1708
1709
1710
1711
1712
1713
1643
1644
1645
1646
1647
1648
1649

1650
1651
1652
1653
1654
1655

1656
1657
1658

1659
1660
1661
1662
1663
1664
1665
1666







-
+





-
+


-
+








    /*
     * If the alias has been renamed in the child, the parent can still use
     * the original name (with which it was created) to find the alias to
     * delete it.
     */

    childPtr = &((InterpInfo *) ((Interp *) childInterp)->interpInfo)->child;
    childPtr = &INTERP_INFO(childInterp)->child;
    hPtr = Tcl_FindHashEntry(&childPtr->aliasTable, TclGetString(namePtr));
    if (hPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"alias \"%s\" not found", TclGetString(namePtr)));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS",
		TclGetString(namePtr), NULL);
		TclGetString(namePtr), (char *)NULL);
	return TCL_ERROR;
    }
    aliasPtr = (Alias *)Tcl_GetHashValue(hPtr);
    aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
    Tcl_DeleteCommandFromToken(childInterp, aliasPtr->childCmd);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
1739
1740
1741
1742
1743
1744
1745
1746

1747
1748
1749
1750
1751

1752
1753
1754
1755
1756
1757
1758
1692
1693
1694
1695
1696
1697
1698

1699
1700
1701
1702
1703

1704
1705
1706
1707
1708
1709
1710
1711







-
+




-
+








    /*
     * If the alias has been renamed in the child, the parent can still use
     * the original name (with which it was created) to find the alias to
     * describe it.
     */

    childPtr = &((InterpInfo *) ((Interp *) childInterp)->interpInfo)->child;
    childPtr = &INTERP_INFO(childInterp)->child;
    hPtr = Tcl_FindHashEntry(&childPtr->aliasTable, TclGetString(namePtr));
    if (hPtr == NULL) {
	return TCL_OK;
    }
    aliasPtr = (Alias *)Tcl_GetHashValue(hPtr);
    aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
    prefixPtr = Tcl_NewListObj(aliasPtr->objc, &aliasPtr->objPtr);
    Tcl_SetObjResult(interp, prefixPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
1778
1779
1780
1781
1782
1783
1784
1785

1786
1787
1788
1789

1790
1791
1792
1793
1794
1795
1796
1731
1732
1733
1734
1735
1736
1737

1738
1739
1740
1741

1742
1743
1744
1745
1746
1747
1748
1749







-
+



-
+







    Tcl_HashEntry *entryPtr;
    Tcl_HashSearch hashSearch;
    Tcl_Obj *resultPtr;
    Alias *aliasPtr;
    Child *childPtr;

    TclNewObj(resultPtr);
    childPtr = &((InterpInfo *) ((Interp *) childInterp)->interpInfo)->child;
    childPtr = &INTERP_INFO(childInterp)->child;

    entryPtr = Tcl_FirstHashEntry(&childPtr->aliasTable, &hashSearch);
    for ( ; entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&hashSearch)) {
	aliasPtr = (Alias *)Tcl_GetHashValue(entryPtr);
	aliasPtr = (Alias *) Tcl_GetHashValue(entryPtr);
	Tcl_ListObjAppendElement(NULL, resultPtr, aliasPtr->token);
    }
    Tcl_SetObjResult(interp, resultPtr);
    return TCL_OK;
}

/*
1818
1819
1820
1821
1822
1823
1824
1825

1826
1827
1828
1829
1830
1831


1832
1833
1834

1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845

1846

1847
1848
1849
1850







1851
1852
1853


1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873

1874
1875
1876
1877
1878
1879

1880
1881


1882
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
1771
1772
1773
1774
1775
1776
1777

1778
1779
1780
1781
1782


1783
1784
1785
1786

1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801




1802
1803
1804
1805
1806
1807
1808
1809


1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830

1831
1832
1833
1834
1835
1836

1837
1838

1839
1840
1841
1842

1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855

1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872

1873
1874
1875
1876
1877
1878
1879
1880







-
+




-
-
+
+


-
+











+

+
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+



















-
+





-
+

-
+
+


-













-
+
















-
+







 *	forwarded.
 *
 *----------------------------------------------------------------------
 */

static int
AliasNRCmd(
    ClientData clientData,	/* Alias record. */
    void *clientData,		/* Alias record. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument vector. */
{
    Alias *aliasPtr = (Alias *)clientData;
    int prefc, cmdc, i;
    Alias *aliasPtr = (Alias *) clientData;
    Tcl_Size prefc, cmdc, i;
    Tcl_Obj **prefv, **cmdv;
    Tcl_Obj *listPtr;
    List *listRep;
    ListRep listRep;
    int flags = TCL_EVAL_INVOKE;

    /*
     * Append the arguments to the command prefix and invoke the command in
     * the target interp's global namespace.
     */

    prefc = aliasPtr->objc;
    prefv = &aliasPtr->objPtr;
    cmdc = prefc + objc - 1;

    /* TODO - encapsulate this into tclListObj.c */
    listPtr = Tcl_NewListObj(cmdc, NULL);
    ListObjGetRep(listPtr, &listRep);
    listRep = ListRepPtr(listPtr);
    listRep->elemCount = cmdc;
    cmdv = &listRep->elements;

    cmdv = ListRepElementsBase(&listRep);
    listRep.storePtr->numUsed = cmdc;
    if (listRep.spanPtr) {
	listRep.spanPtr->spanStart = listRep.storePtr->firstUsed;
	listRep.spanPtr->spanLength = listRep.storePtr->numUsed;
    }

    prefv = &aliasPtr->objPtr;
    memcpy(cmdv, prefv, (prefc * sizeof(Tcl_Obj *)));
    memcpy(cmdv+prefc, objv+1, ((objc-1) * sizeof(Tcl_Obj *)));
    memcpy(cmdv, prefv, prefc * sizeof(Tcl_Obj *));
    memcpy(cmdv+prefc, objv+1, (objc-1) * sizeof(Tcl_Obj *));

    for (i=0; i<cmdc; i++) {
	Tcl_IncrRefCount(cmdv[i]);
    }

    /*
     * Use the ensemble rewriting machinery to ensure correct error messages:
     * only the source command should show, not the full target prefix.
     */

    if (TclInitRewriteEnsemble(interp, 1, prefc, objv)) {
	TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
    }
    TclSkipTailcall(interp);
    return Tcl_NREvalObj(interp, listPtr, flags);
}

int
TclAliasObjCmd(
    ClientData clientData,	/* Alias record. */
    void *clientData,		/* Alias record. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument vector. */
{
#define ALIAS_CMDV_PREALLOC 10
    Alias *aliasPtr = (Alias *)clientData;
    Alias *aliasPtr = (Alias *) clientData;
    Tcl_Interp *targetInterp = aliasPtr->targetInterp;
    int result, prefc, cmdc, i;
    int result;
    Tcl_Size prefc, cmdc, i;
    Tcl_Obj **prefv, **cmdv;
    Tcl_Obj *cmdArr[ALIAS_CMDV_PREALLOC];
    Interp *tPtr = (Interp *) targetInterp;
    int isRootEnsemble;

    /*
     * Append the arguments to the command prefix and invoke the command in
     * the target interp's global namespace.
     */

    prefc = aliasPtr->objc;
    prefv = &aliasPtr->objPtr;
    cmdc = prefc + objc - 1;
    if (cmdc <= ALIAS_CMDV_PREALLOC) {
	cmdv = cmdArr;
    } else {
	cmdv = (Tcl_Obj **)TclStackAlloc(interp, cmdc * sizeof(Tcl_Obj *));
	cmdv = (Tcl_Obj **) TclStackAlloc(interp, cmdc * sizeof(Tcl_Obj *));
    }

    memcpy(cmdv, prefv, prefc * sizeof(Tcl_Obj *));
    memcpy(cmdv+prefc, objv+1, (objc-1) * sizeof(Tcl_Obj *));

    Tcl_ResetResult(targetInterp);

    for (i=0; i<cmdc; i++) {
	Tcl_IncrRefCount(cmdv[i]);
    }

    /*
     * Use the ensemble rewriting machinery to ensure correct error messages:
     * only the source command should show, not the full target prefix.
     */

    isRootEnsemble = TclInitRewriteEnsemble((Tcl_Interp *)tPtr, 1, prefc, objv);
    isRootEnsemble = TclInitRewriteEnsemble(targetInterp, 1, prefc, objv);

    /*
     * Protect the target interpreter if it isn't the same as the source
     * interpreter so that we can continue to work with it after the target
     * command completes.
     */

1931
1932
1933
1934
1935
1936
1937
1938

1939
1940
1941
1942
1943
1944
1945
1889
1890
1891
1892
1893
1894
1895

1896
1897
1898
1899
1900
1901
1902
1903







-
+







    result = Tcl_EvalObjv(targetInterp, cmdc, cmdv, TCL_EVAL_INVOKE);

    /*
     * Clean up the ensemble rewrite info if we set it in the first place.
     */

    if (isRootEnsemble) {
	TclResetRewriteEnsemble((Tcl_Interp *)tPtr, 1);
	TclResetRewriteEnsemble(targetInterp, 1);
    }

    /*
     * If it was a cross-interpreter alias, we need to transfer the result
     * back to the source interpreter and release the lock we previously set
     * on the target interpreter.
     */
1957
1958
1959
1960
1961
1962
1963
1964

1965
1966
1967
1968
1969
1970
1971



1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988

1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003

2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016

2017
2018
2019
2020
2021
2022
2023
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
1958
1959
1960

1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973

1974
1975
1976
1977
1978
1979
1980
1981







-
+





-
-
+
+
+


-













-
+














-
+












-
+







    }
    return result;
#undef ALIAS_CMDV_PREALLOC
}

int
TclLocalAliasObjCmd(
    ClientData clientData,	/* Alias record. */
    void *clientData,		/* Alias record. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument vector. */
{
#define ALIAS_CMDV_PREALLOC 10
    Alias *aliasPtr = (Alias *)clientData;
    int result, prefc, cmdc, i;
    Alias *aliasPtr = (Alias *) clientData;
    int result;
    Tcl_Size prefc, cmdc, i;
    Tcl_Obj **prefv, **cmdv;
    Tcl_Obj *cmdArr[ALIAS_CMDV_PREALLOC];
    Interp *iPtr = (Interp *) interp;
    int isRootEnsemble;

    /*
     * Append the arguments to the command prefix and invoke the command in
     * the global namespace.
     */

    prefc = aliasPtr->objc;
    prefv = &aliasPtr->objPtr;
    cmdc = prefc + objc - 1;
    if (cmdc <= ALIAS_CMDV_PREALLOC) {
	cmdv = cmdArr;
    } else {
	cmdv = (Tcl_Obj **)TclStackAlloc(interp, cmdc * sizeof(Tcl_Obj *));
	cmdv = (Tcl_Obj **) TclStackAlloc(interp, cmdc * sizeof(Tcl_Obj *));
    }

    memcpy(cmdv, prefv, prefc * sizeof(Tcl_Obj *));
    memcpy(cmdv+prefc, objv+1, (objc-1) * sizeof(Tcl_Obj *));

    for (i=0; i<cmdc; i++) {
	Tcl_IncrRefCount(cmdv[i]);
    }

    /*
     * Use the ensemble rewriting machinery to ensure correct error messages:
     * only the source command should show, not the full target prefix.
     */

    isRootEnsemble = TclInitRewriteEnsemble((Tcl_Interp *)iPtr, 1, prefc, objv);
    isRootEnsemble = TclInitRewriteEnsemble(interp, 1, prefc, objv);

    /*
     * Execute the target command in the target interpreter.
     */

    result = Tcl_EvalObjv(interp, cmdc, cmdv, TCL_EVAL_INVOKE);

    /*
     * Clean up the ensemble rewrite info if we set it in the first place.
     */

    if (isRootEnsemble) {
	TclResetRewriteEnsemble((Tcl_Interp *)iPtr, 1);
	TclResetRewriteEnsemble(interp, 1);
    }

    for (i=0; i<cmdc; i++) {
	Tcl_DecrRefCount(cmdv[i]);
    }
    if (cmdv != cmdArr) {
	TclStackFree(interp, cmdv);
2042
2043
2044
2045
2046
2047
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
2000
2001
2002
2003
2004
2005
2006

2007
2008

2009
2010

2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028


2029
2030
2031
2032
2033
2034
2035
2036







-
+

-
+

-
+

















-
-
+







 *	interpreter.
 *
 *----------------------------------------------------------------------
 */

static void
AliasObjCmdDeleteProc(
    ClientData clientData)	/* The alias record for this alias. */
    void *clientData)		/* The alias record for this alias. */
{
    Alias *aliasPtr = (Alias *)clientData;
    Alias *aliasPtr = (Alias *) clientData;
    Target *targetPtr;
    int i;
    Tcl_Size i;
    Tcl_Obj **objv;

    Tcl_DecrRefCount(aliasPtr->token);
    objv = &aliasPtr->objPtr;
    for (i = 0; i < aliasPtr->objc; i++) {
	Tcl_DecrRefCount(objv[i]);
    }
    Tcl_DeleteHashEntry(aliasPtr->aliasEntryPtr);

    /*
     * Splice the target record out of the target interpreter's parent list.
     */

    targetPtr = aliasPtr->targetPtr;
    if (targetPtr->prevPtr != NULL) {
	targetPtr->prevPtr->nextPtr = targetPtr->nextPtr;
    } else {
	Parent *parentPtr = &((InterpInfo *) ((Interp *)
		aliasPtr->targetInterp)->interpInfo)->parent;
	Parent *parentPtr = &INTERP_INFO(aliasPtr->targetInterp)->parent;

	parentPtr->targetsPtr = targetPtr->nextPtr;
    }
    if (targetPtr->nextPtr != NULL) {
	targetPtr->nextPtr->prevPtr = targetPtr->prevPtr;
    }

2172
2173
2174
2175
2176
2177
2178
2179

2180
2181
2182
2183
2184
2185
2186
2129
2130
2131
2132
2133
2134
2135

2136
2137
2138
2139
2140
2141
2142
2143







-
+







    Tcl_Interp *interp)		/* Get the parent of this interpreter. */
{
    Child *childPtr;		/* Child record of this interpreter. */

    if (interp == NULL) {
	return NULL;
    }
    childPtr = &((InterpInfo *) ((Interp *) interp)->interpInfo)->child;
    childPtr = &INTERP_INFO(interp)->child;
    return childPtr->parentInterp;
}

/*
 *----------------------------------------------------------------------
 *
 * TclSetChildCancelFlags --
2216
2217
2218
2219
2220
2221
2222
2223

2224
2225
2226
2227

2228
2229
2230
2231
2232
2233
2234
2173
2174
2175
2176
2177
2178
2179

2180
2181
2182
2183

2184
2185
2186
2187
2188
2189
2190
2191







-
+



-
+








    if (interp == NULL) {
	return;
    }

    flags &= (CANCELED | TCL_CANCEL_UNWIND);

    parentPtr = &((InterpInfo *) ((Interp *) interp)->interpInfo)->parent;
    parentPtr = &INTERP_INFO(interp)->parent;

    hPtr = Tcl_FirstHashEntry(&parentPtr->childTable, &hashSearch);
    for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&hashSearch)) {
	childPtr = (Child *)Tcl_GetHashValue(hPtr);
	childPtr = (Child *) Tcl_GetHashValue(hPtr);
	iPtr = (Interp *) childPtr->childInterp;

	if (iPtr == NULL) {
	    continue;
	}

	if (flags == 0) {
2268
2269
2270
2271
2272
2273
2274
2275

2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288


2289
2290
2291
2292
2293



2294
2295
2296
2297
2298
2299
2300
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







-
+











-
-
+
+



-
-
+
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_GetInterpPath(
    Tcl_Interp *interp,	/* Interpreter to start search from. */
    Tcl_Interp *interp,		/* Interpreter to start search from. */
    Tcl_Interp *targetInterp)	/* Interpreter to find. */
{
    InterpInfo *iiPtr;

    if (targetInterp == interp) {
	Tcl_SetObjResult(interp, Tcl_NewObj());
	return TCL_OK;
    }
    if (targetInterp == NULL) {
	return TCL_ERROR;
    }
    iiPtr = (InterpInfo *) ((Interp *) targetInterp)->interpInfo;
    if (Tcl_GetInterpPath(interp, iiPtr->child.parentInterp) != TCL_OK){
    iiPtr = INTERP_INFO(targetInterp);
    if (Tcl_GetInterpPath(interp, iiPtr->child.parentInterp) != TCL_OK) {
	return TCL_ERROR;
    }
    Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp),
	    Tcl_NewStringObj((const char *)Tcl_GetHashKey(&iiPtr->parent.childTable,
		    iiPtr->child.childEntryPtr), -1));
	    Tcl_NewStringObj((const char *)
		    Tcl_GetHashKey(&iiPtr->parent.childTable,
			    iiPtr->child.childEntryPtr), -1));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * GetInterp --
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
2274
2275
2276
2277
2278
2279
2280

2281
2282
2283
2284
2285
2286
2287
2288
2289
2290

2291
2292
2293
2294
2295
2296
2297

2298
2299
2300
2301
2302
2303
2304
2305
2306
2307

2308
2309
2310
2311
2312
2313
2314
2315







-
+









-
+






-
+









-
+







    Tcl_Interp *interp,		/* Interp. to start search from. */
    Tcl_Obj *pathPtr)		/* List object containing name of interp. to
				 * be found. */
{
    Tcl_HashEntry *hPtr;	/* Search element. */
    Child *childPtr;		/* Interim child record. */
    Tcl_Obj **objv;
    int objc, i;
    Tcl_Size objc, i;
    Tcl_Interp *searchInterp;	/* Interim storage for interp. to find. */
    InterpInfo *parentInfoPtr;

    if (TclListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) {
	return NULL;
    }

    searchInterp = interp;
    for (i = 0; i < objc; i++) {
	parentInfoPtr = (InterpInfo *) ((Interp *) searchInterp)->interpInfo;
	parentInfoPtr = INTERP_INFO(searchInterp);
	hPtr = Tcl_FindHashEntry(&parentInfoPtr->parent.childTable,
		TclGetString(objv[i]));
	if (hPtr == NULL) {
	    searchInterp = NULL;
	    break;
	}
	childPtr = (Child *)Tcl_GetHashValue(hPtr);
	childPtr = (Child *) Tcl_GetHashValue(hPtr);
	searchInterp = childPtr->childInterp;
	if (searchInterp == NULL) {
	    break;
	}
    }
    if (searchInterp == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"could not find interpreter \"%s\"", TclGetString(pathPtr)));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INTERP",
		TclGetString(pathPtr), NULL);
		TclGetString(pathPtr), (char *)NULL);
    }
    return searchInterp;
}

/*
 *----------------------------------------------------------------------
 *
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
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







-
+



-
+






-
+







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

static int
ChildBgerror(
    Tcl_Interp *interp,		/* Interp for error return. */
    Tcl_Interp *childInterp,	/* Interp in which limit is set/queried. */
    int objc,			/* Set or Query. */
    Tcl_Size objc,		/* Set or Query. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    if (objc) {
	int length;
	Tcl_Size length;

	if (TCL_ERROR == TclListObjLength(NULL, objv[0], &length)
		|| (length < 1)) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "cmdPrefix must be list of length >= 1", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
		    "BGERRORFORMAT", NULL);
		    "BGERRORFORMAT", (char *)NULL);
	    return TCL_ERROR;
	}
	TclSetBgErrorHandler(childInterp, objv[0]);
    }
    Tcl_SetObjResult(interp, TclGetBgErrorHandler(childInterp));
    return TCL_OK;
}
2420
2421
2422
2423
2424
2425
2426
2427


2428
2429
2430

2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2378
2379
2380
2381
2382
2383
2384

2385
2386
2387
2388

2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409

2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420

2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438

2439


2440
2441
2442
2443
2444
2445
2446







-
+
+


-
+




















-
+










-
+

















-
+
-
-







    int safe)			/* Should we make it "safe"? */
{
    Tcl_Interp *parentInterp, *childInterp;
    Child *childPtr;
    InterpInfo *parentInfoPtr;
    Tcl_HashEntry *hPtr;
    const char *path;
    int isNew, objc;
    int isNew;
    Tcl_Size objc;
    Tcl_Obj **objv;

    if (Tcl_ListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) {
    if (TclListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) {
	return NULL;
    }
    if (objc < 2) {
	parentInterp = interp;
	path = TclGetString(pathPtr);
    } else {
	Tcl_Obj *objPtr;

	objPtr = Tcl_NewListObj(objc - 1, objv);
	parentInterp = GetInterp(interp, objPtr);
	Tcl_DecrRefCount(objPtr);
	if (parentInterp == NULL) {
	    return NULL;
	}
	path = TclGetString(objv[objc - 1]);
    }
    if (safe == 0) {
	safe = Tcl_IsSafe(parentInterp);
    }

    parentInfoPtr = (InterpInfo *) ((Interp *) parentInterp)->interpInfo;
    parentInfoPtr = INTERP_INFO(parentInterp);
    hPtr = Tcl_CreateHashEntry(&parentInfoPtr->parent.childTable, path,
	    &isNew);
    if (isNew == 0) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"interpreter named \"%s\" already exists, cannot create",
		path));
	return NULL;
    }

    childInterp = Tcl_CreateInterp();
    childPtr = &((InterpInfo *) ((Interp *) childInterp)->interpInfo)->child;
    childPtr = &INTERP_INFO(childInterp)->child;
    childPtr->parentInterp = parentInterp;
    childPtr->childEntryPtr = hPtr;
    childPtr->childInterp = childInterp;
    childPtr->interpCmd = Tcl_NRCreateCommand(parentInterp, path,
	    TclChildObjCmd, NRChildCmd, childInterp, ChildObjCmdDeleteProc);
    Tcl_InitHashTable(&childPtr->aliasTable, TCL_STRING_KEYS);
    Tcl_SetHashValue(hPtr, childPtr);
    Tcl_SetVar2(childInterp, "tcl_interactive", NULL, "0", TCL_GLOBAL_ONLY);

    /*
     * Inherit the recursion limit.
     */

    ((Interp *) childInterp)->maxNestingDepth =
	    ((Interp *) parentInterp)->maxNestingDepth;

    if (safe) {
	if (Tcl_MakeSafe(childInterp) == TCL_ERROR) {
	MakeSafe(childInterp);
	    goto error;
	}
    } else {
	if (Tcl_Init(childInterp) == TCL_ERROR) {
	    goto error;
	}

	/*
	 * This will create the "memory" command in child interpreters if we
2544
2545
2546
2547
2548
2549
2550
2551

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
2501
2502
2503
2504
2505
2506
2507

2508
2509
2510
2511
2512
2513
2514
2515
2516
2517

2518
2519
2520
2521
2522

2523

2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534

2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549

2550
2551
2552
2553
2554
2555
2556
2557







-
+









-
+




-
+
-











-
+














-
+







 *	See user documentation for details.
 *
 *----------------------------------------------------------------------
 */

int
TclChildObjCmd(
    ClientData clientData,	/* Child interpreter. */
    void *clientData,		/* Child interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, NRChildCmd, clientData, objc, objv);
}

static int
NRChildCmd(
    ClientData clientData,	/* Child interpreter. */
    void *clientData,		/* Child interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Interp *childInterp = (Tcl_Interp *)clientData;
    Tcl_Interp *childInterp = (Tcl_Interp *) clientData;
    int index;
    static const char *const options[] = {
	"alias",	"aliases",	"bgerror",	"debug",
	"eval",		"expose",	"hide",		"hidden",
	"issafe",	"invokehidden",	"limit",	"marktrusted",
	"recursionlimit", NULL
    };
    enum childCmdOptionsEnum {
	OPT_ALIAS,	OPT_ALIASES,	OPT_BGERROR,	OPT_DEBUG,
	OPT_EVAL,	OPT_EXPOSE,	OPT_HIDE,	OPT_HIDDEN,
	OPT_ISSAFE,	OPT_INVOKEHIDDEN, OPT_LIMIT,	OPT_MARKTRUSTED,
	OPT_RECLIMIT
    };
    } index;

    if (childInterp == NULL) {
	Tcl_Panic("TclChildObjCmd: interpreter has been deleted");
    }

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "cmd ?arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum childCmdOptionsEnum) index) {
    switch (index) {
    case OPT_ALIAS:
	if (objc > 2) {
	    if (objc == 3) {
		return AliasDescribe(interp, childInterp, objv[2]);
	    }
	    if (TclGetString(objv[3])[0] == '\0') {
		if (objc == 4) {
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
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







-
+






-
+







-
+


-
+

-
+


-
-

+



















-
-
+









-
+







	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Tcl_IsSafe(childInterp)));
	return TCL_OK;
    case OPT_INVOKEHIDDEN: {
	int i;
	Tcl_Size i;
	const char *namespaceName;
	static const char *const hiddenOptions[] = {
	    "-global",	"-namespace",	"--", NULL
	};
	enum hiddenOption {
	    OPT_GLOBAL,	OPT_NAMESPACE,	OPT_LAST
	};
	} idx;

	namespaceName = NULL;
	for (i = 2; i < objc; i++) {
	    if (TclGetString(objv[i])[0] != '-') {
		break;
	    }
	    if (Tcl_GetIndexFromObj(interp, objv[i], hiddenOptions, "option",
		    0, &index) != TCL_OK) {
		    0, &idx) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (index == OPT_GLOBAL) {
	    if (idx == OPT_GLOBAL) {
		namespaceName = "::";
	    } else if (index == OPT_NAMESPACE) {
	    } else if (idx == OPT_NAMESPACE) {
		if (++i == objc) { /* There must be more arguments. */
		    break;
		} else {
		    namespaceName = TclGetString(objv[i]);
		}
		namespaceName = TclGetString(objv[i]);
	    } else {
		i++;
		break;
	    }
	}
	if (objc - i < 1) {
	    Tcl_WrongNumArgs(interp, 2, objv,
		    "?-namespace ns? ?-global? ?--? cmd ?arg ..?");
	    return TCL_ERROR;
	}
	return ChildInvokeHidden(interp, childInterp, namespaceName,
		objc - i, objv + i);
    }
    case OPT_LIMIT: {
	static const char *const limitTypes[] = {
	    "commands", "time", NULL
	};
	enum LimitTypes {
	    LIMIT_TYPE_COMMANDS, LIMIT_TYPE_TIME
	};
	int limitType;
	} limitType;

	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "limitType ?-option value ...?");
	    return TCL_ERROR;
	}
	if (Tcl_GetIndexFromObj(interp, objv[2], limitTypes, "limit type", 0,
		&limitType) != TCL_OK) {
	    return TCL_ERROR;
	}
	switch ((enum LimitTypes) limitType) {
	switch (limitType) {
	case LIMIT_TYPE_COMMANDS:
	    return ChildCommandLimitCmd(interp, childInterp, 3, objc,objv);
	case LIMIT_TYPE_TIME:
	    return ChildTimeLimitCmd(interp, childInterp, 3, objc, objv);
	}
    }
    break;
2760
2761
2762
2763
2764
2765
2766
2767

2768
2769
2770

2771
2772
2773

2774
2775
2776
2777
2778
2779
2780
2714
2715
2716
2717
2718
2719
2720

2721
2722
2723

2724
2725
2726

2727
2728
2729
2730
2731
2732
2733
2734







-
+


-
+


-
+







 *	the child interpreter.
 *
 *----------------------------------------------------------------------
 */

static void
ChildObjCmdDeleteProc(
    ClientData clientData)	/* The ChildRecord for the command. */
    void *clientData)		/* The ChildRecord for the command. */
{
    Child *childPtr;		/* Interim storage for Child record. */
    Tcl_Interp *childInterp = (Tcl_Interp *)clientData;
    Tcl_Interp *childInterp = (Tcl_Interp *) clientData;
				/* And for a child interp. */

    childPtr = &((InterpInfo *) ((Interp *) childInterp)->interpInfo)->child;
    childPtr = &INTERP_INFO(childInterp)->child;

    /*
     * Unlink the child from its parent interpreter.
     */

    Tcl_DeleteHashEntry(childPtr->childEntryPtr);

2808
2809
2810
2811
2812
2813
2814
2815

2816
2817
2818
2819
2820
2821
2822
2762
2763
2764
2765
2766
2767
2768

2769
2770
2771
2772
2773
2774
2775
2776







-
+







 */

static int
ChildDebugCmd(
    Tcl_Interp *interp,		/* Interp for error return. */
    Tcl_Interp *childInterp,	/* The child interpreter in which command
				 * will be evaluated. */
    int objc,			/* Number of arguments. */
    Tcl_Size objc,		/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static const char *const debugTypes[] = {
	"-frame", NULL
    };
    enum DebugTypes {
	DEBUG_TYPE_FRAME
2879
2880
2881
2882
2883
2884
2885
2886

2887
2888
2889
2890
2891
2892
2893
2833
2834
2835
2836
2837
2838
2839

2840
2841
2842
2843
2844
2845
2846
2847







-
+







 */

static int
ChildEval(
    Tcl_Interp *interp,		/* Interp for error return. */
    Tcl_Interp *childInterp,	/* The child interpreter in which command
				 * will be evaluated. */
    int objc,			/* Number of arguments. */
    Tcl_Size objc,		/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int result;

    /*
     * TIP #285: If necessary, reset the cancellation flags for the child
     * interpreter now; otherwise, canceling a script in a parent interpreter
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
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







-
+









-
+







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

static int
ChildExpose(
    Tcl_Interp *interp,		/* Interp for error return. */
    Tcl_Interp *childInterp,	/* Interp in which command will be exposed. */
    int objc,			/* Number of arguments. */
    Tcl_Size objc,		/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    const char *name;

    if (Tcl_IsSafe(interp)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"permission denied: safe interpreter cannot expose commands",
		-1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "UNSAFE",
		NULL);
		(char *)NULL);
	return TCL_ERROR;
    }

    name = TclGetString(objv[(objc == 1) ? 0 : 1]);
    if (Tcl_ExposeCommand(childInterp, TclGetString(objv[0]),
	    name) != TCL_OK) {
	Tcl_TransferResult(childInterp, TCL_ERROR, interp);
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
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







-
+



-
+






-
+


-
+






-
+







-
+







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

static int
ChildRecursionLimit(
    Tcl_Interp *interp,		/* Interp for error return. */
    Tcl_Interp *childInterp,	/* Interp in which limit is set/queried. */
    int objc,			/* Set or Query. */
    Tcl_Size objc,		/* Set or Query. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    Interp *iPtr;
    int limit;
    Tcl_WideInt limit;

    if (objc) {
	if (Tcl_IsSafe(interp)) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj("permission denied: "
		    "safe interpreters cannot change recursion limit", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "UNSAFE",
		    NULL);
		    (char *)NULL);
	    return TCL_ERROR;
	}
	if (TclGetIntFromObj(interp, objv[0], &limit) == TCL_ERROR) {
	if (TclGetWideIntFromObj(interp, objv[0], &limit) == TCL_ERROR) {
	    return TCL_ERROR;
	}
	if (limit <= 0) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "recursion limit must be > 0", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "BADLIMIT",
		    NULL);
		    (char *)NULL);
	    return TCL_ERROR;
	}
	Tcl_SetRecursionLimit(childInterp, limit);
	iPtr = (Interp *) childInterp;
	if (interp == childInterp && iPtr->numLevels > limit) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "falling back due to new recursion limit", -1));
	    Tcl_SetErrorCode(interp, "TCL", "RECURSION", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "RECURSION", (char *)NULL);
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, objv[0]);
	return TCL_OK;
    } else {
	limit = Tcl_SetRecursionLimit(childInterp, 0);
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(limit));
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
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







-
+









-
+







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

static int
ChildHide(
    Tcl_Interp *interp,		/* Interp for error return. */
    Tcl_Interp *childInterp,	/* Interp in which command will be exposed. */
    int objc,			/* Number of arguments. */
    Tcl_Size objc,		/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    const char *name;

    if (Tcl_IsSafe(interp)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"permission denied: safe interpreter cannot hide commands",
		-1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "UNSAFE",
		NULL);
		(char *)NULL);
	return TCL_ERROR;
    }

    name = TclGetString(objv[(objc == 1) ? 0 : 1]);
    if (Tcl_HideCommand(childInterp, TclGetString(objv[0]), name) != TCL_OK) {
	Tcl_TransferResult(childInterp, TCL_ERROR, interp);
	return TCL_ERROR;
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
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







-
-
-
-
+
+
+
+








-
+
+







 */

static int
ChildHidden(
    Tcl_Interp *interp,		/* Interp for data return. */
    Tcl_Interp *childInterp)	/* Interp whose hidden commands to query. */
{
    Tcl_Obj *listObjPtr;		/* Local object pointer. */
    Tcl_HashTable *hTblPtr;		/* For local searches. */
    Tcl_HashEntry *hPtr;		/* For local searches. */
    Tcl_HashSearch hSearch;		/* For local searches. */
    Tcl_Obj *listObjPtr;	/* Local object pointer. */
    Tcl_HashTable *hTblPtr;	/* For local searches. */
    Tcl_HashEntry *hPtr;	/* For local searches. */
    Tcl_HashSearch hSearch;	/* For local searches. */

    TclNewObj(listObjPtr);
    hTblPtr = ((Interp *) childInterp)->hiddenCmdTablePtr;
    if (hTblPtr != NULL) {
	for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
		hPtr != NULL;
		hPtr = Tcl_NextHashEntry(&hSearch)) {
	    Tcl_ListObjAppendElement(NULL, listObjPtr,
		    Tcl_NewStringObj((const char *)Tcl_GetHashKey(hTblPtr, hPtr), -1));
		    Tcl_NewStringObj((const char *)
			    Tcl_GetHashKey(hTblPtr, hPtr), -1));
	}
    }
    Tcl_SetObjResult(interp, listObjPtr);
    return TCL_OK;
}

/*
3133
3134
3135
3136
3137
3138
3139
3140

3141
3142
3143
3144
3145
3146
3147
3148
3149
3150

3151
3152
3153
3154
3155
3156
3157
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







-
+









-
+








static int
ChildInvokeHidden(
    Tcl_Interp *interp,		/* Interp for error return. */
    Tcl_Interp *childInterp,	/* The child interpreter in which command will
				 * be invoked. */
    const char *namespaceName,	/* The namespace to use, if any. */
    int objc,			/* Number of arguments. */
    Tcl_Size objc,		/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int result;

    if (Tcl_IsSafe(interp)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"not allowed to invoke hidden commands from safe interpreter",
		-1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "UNSAFE",
		NULL);
		(char *)NULL);
	return TCL_ERROR;
    }

    Tcl_Preserve(childInterp);
    Tcl_AllowExceptions(childInterp);

    if (namespaceName == NULL) {
3177
3178
3179
3180
3181
3182
3183
3184

3185
3186
3187
3188
3189


3190
3191
3192
3193
3194
3195
3196
3132
3133
3134
3135
3136
3137
3138

3139
3140
3141
3142


3143
3144
3145
3146
3147
3148
3149
3150
3151







-
+



-
-
+
+








    Tcl_Release(childInterp);
    return result;
}

static int
NRPostInvokeHidden(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Interp *childInterp = (Tcl_Interp *)data[0];
    NRE_callback *rootPtr = (NRE_callback *)data[1];
    Tcl_Interp *childInterp = (Tcl_Interp *) data[0];
    NRE_callback *rootPtr = (NRE_callback *) data[1];

    if (interp != childInterp) {
	result = TclNRRunCallbacks(childInterp, result, rootPtr);
	Tcl_TransferResult(childInterp, result, interp);
    }
    Tcl_Release(childInterp);
    return result;
3220
3221
3222
3223
3224
3225
3226
3227

3228
3229
3230
3231
3232
3233
3234
3175
3176
3177
3178
3179
3180
3181

3182
3183
3184
3185
3186
3187
3188
3189







-
+







				 * trusted. */
{
    if (Tcl_IsSafe(interp)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"permission denied: safe interpreter cannot mark trusted",
		-1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "UNSAFE",
		NULL);
		(char *)NULL);
	return TCL_ERROR;
    }
    ((Interp *) childInterp)->flags &= ~SAFE_INTERP;
    return TCL_OK;
}

/*
3258
3259
3260
3261
3262
3263
3264
3265

3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282


3283
3284
3285
3286
3287

3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300


3301
3302
3303
3304
3305
3306
3307
3213
3214
3215
3216
3217
3218
3219

3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235


3236
3237
3238
3239
3240
3241

3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254

3255
3256
3257
3258
3259
3260
3261
3262
3263







-
+















-
-
+
+




-
+












-
+
+







    }
    return (iPtr->flags & SAFE_INTERP) ? 1 : 0;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_MakeSafe --
 * MakeSafe --
 *
 *	Makes its argument interpreter contain only functionality that is
 *	defined to be part of Safe Tcl. Unsafe commands are hidden, the env
 *	array is unset, and the standard channels are removed.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Hides commands in its argument interpreter, and removes settings and
 *	channels.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_MakeSafe(
void
MakeSafe(
    Tcl_Interp *interp)		/* Interpreter to be made safe. */
{
    Tcl_Channel chan;		/* Channel to remove from safe interpreter. */
    Interp *iPtr = (Interp *) interp;
    Tcl_Interp *parent = ((InterpInfo*) iPtr->interpInfo)->child.parentInterp;
    Tcl_Interp *parent = INTERP_INFO(iPtr)->child.parentInterp;

    TclHideUnsafeCommands(interp);

    if (parent != NULL) {
	/*
	 * Alias these function implementations in the child to those in the
	 * parent; the overall implementations are safe, but they're normally
	 * defined by init.tcl which is not sourced by safe interpreters.
	 * Assume these functions all work. [Bug 2895741]
	 */

	(void) Tcl_EvalEx(interp,
		"namespace eval ::tcl {namespace eval mathfunc {}}", -1, 0);
		"namespace eval ::tcl {namespace eval mathfunc {}}",
		TCL_INDEX_NONE, 0);
    }

    iPtr->flags |= SAFE_INTERP;

    /*
     * Unsetting variables : (which should not have been set in the first
     * place, but...)
3319
3320
3321
3322
3323
3324
3325
3326

3327
3328
3329
3330
3331
3332
3333
3275
3276
3277
3278
3279
3280
3281

3282
3283
3284
3285
3286
3287
3288
3289







-
+








    Tcl_UnsetVar2(interp, "tcl_platform", "os", TCL_GLOBAL_ONLY);
    Tcl_UnsetVar2(interp, "tcl_platform", "osVersion", TCL_GLOBAL_ONLY);
    Tcl_UnsetVar2(interp, "tcl_platform", "machine", TCL_GLOBAL_ONLY);
    Tcl_UnsetVar2(interp, "tcl_platform", "user", TCL_GLOBAL_ONLY);

    /*
     * Unset path informations variables (the only one remaining is [info
     * Unset path information variables (the only one remaining is [info
     * nameofexecutable])
     */

    Tcl_UnsetVar2(interp, "tclDefaultLibrary", NULL, TCL_GLOBAL_ONLY);
    Tcl_UnsetVar2(interp, "tcl_library", NULL, TCL_GLOBAL_ONLY);
    Tcl_UnsetVar2(interp, "tcl_pkgPath", NULL, TCL_GLOBAL_ONLY);

3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3305
3306
3307
3308
3309
3310
3311


3312
3313
3314
3315
3316
3317
3318







-
-







    if (chan != NULL) {
	Tcl_UnregisterChannel(interp, chan);
    }
    chan = Tcl_GetStdChannel(TCL_STDERR);
    if (chan != NULL) {
	Tcl_UnregisterChannel(interp, chan);
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_LimitExceeded --
 *
3474
3475
3476
3477
3478
3479
3480
3481

3482
3483
3484
3485
3486
3487
3488
3428
3429
3430
3431
3432
3433
3434

3435
3436
3437
3438
3439
3440
3441
3442







-
+







	Tcl_Preserve(interp);
	RunLimitHandlers(iPtr->limit.cmdHandlers, interp);
	if (iPtr->limit.cmdCount >= iPtr->cmdCount) {
	    iPtr->limit.exceeded &= ~TCL_LIMIT_COMMANDS;
	} else if (iPtr->limit.exceeded & TCL_LIMIT_COMMANDS) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "command count limit exceeded", -1));
	    Tcl_SetErrorCode(interp, "TCL", "LIMIT", "COMMANDS", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "LIMIT", "COMMANDS", (char *)NULL);
	    Tcl_Release(interp);
	    return TCL_ERROR;
	}
	Tcl_Release(interp);
    }

    if ((iPtr->limit.active & TCL_LIMIT_TIME) &&
3500
3501
3502
3503
3504
3505
3506
3507

3508
3509
3510
3511
3512
3513
3514
3454
3455
3456
3457
3458
3459
3460

3461
3462
3463
3464
3465
3466
3467
3468







-
+







	    if (iPtr->limit.time.sec > now.sec ||
		    (iPtr->limit.time.sec == now.sec &&
		    iPtr->limit.time.usec >= now.usec)) {
		iPtr->limit.exceeded &= ~TCL_LIMIT_TIME;
	    } else if (iPtr->limit.exceeded & TCL_LIMIT_TIME) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"time limit exceeded", -1));
		Tcl_SetErrorCode(interp, "TCL", "LIMIT", "TIME", NULL);
		Tcl_SetErrorCode(interp, "TCL", "LIMIT", "TIME", (char *)NULL);
		Tcl_Release(interp);
		return TCL_ERROR;
	    }
	    Tcl_Release(interp);
	}
    }

3602
3603
3604
3605
3606
3607
3608
3609

3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620


3621
3622
3623
3624
3625
3626
3627

3628
3629
3630
3631
3632
3633
3634
3556
3557
3558
3559
3560
3561
3562

3563
3564
3565
3566
3567
3568
3569
3570
3571
3572


3573
3574
3575
3576
3577
3578
3579
3580

3581
3582
3583
3584
3585
3586
3587
3588







-
+









-
-
+
+






-
+







 */

void
Tcl_LimitAddHandler(
    Tcl_Interp *interp,
    int type,
    Tcl_LimitHandlerProc *handlerProc,
    ClientData clientData,
    void *clientData,
    Tcl_LimitHandlerDeleteProc *deleteProc)
{
    Interp *iPtr = (Interp *) interp;
    LimitHandler *handlerPtr;

    /*
     * Convert everything into a real deletion callback.
     */

    if (deleteProc == (Tcl_LimitHandlerDeleteProc *) TCL_DYNAMIC) {
	deleteProc = (Tcl_LimitHandlerDeleteProc *) TclpFree;
    if (deleteProc == TCL_DYNAMIC) {
	deleteProc = TclpFree;
    }

    /*
     * Allocate a handler record.
     */

    handlerPtr = (LimitHandler *)Tcl_Alloc(sizeof(LimitHandler));
    handlerPtr = (LimitHandler *) Tcl_Alloc(sizeof(LimitHandler));
    handlerPtr->flags = 0;
    handlerPtr->handlerProc = handlerProc;
    handlerPtr->clientData = clientData;
    handlerPtr->deleteProc = deleteProc;
    handlerPtr->prevPtr = NULL;

    /*
3676
3677
3678
3679
3680
3681
3682
3683

3684
3685
3686
3687
3688
3689
3690
3630
3631
3632
3633
3634
3635
3636

3637
3638
3639
3640
3641
3642
3643
3644







-
+







 */

void
Tcl_LimitRemoveHandler(
    Tcl_Interp *interp,
    int type,
    Tcl_LimitHandlerProc *handlerProc,
    ClientData clientData)
    void *clientData)
{
    Interp *iPtr = (Interp *) interp;
    LimitHandler *handlerPtr;

    switch (type) {
    case TCL_LIMIT_COMMANDS:
	handlerPtr = iPtr->limit.cmdHandlers;
3979
3980
3981
3982
3983
3984
3985
3986

3987
3988
3989
3990
3991
3992
3993
3933
3934
3935
3936
3937
3938
3939

3940
3941
3942
3943
3944
3945
3946
3947







-
+







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

void
Tcl_LimitSetCommands(
    Tcl_Interp *interp,
    int commandLimit)
    Tcl_Size commandLimit)
{
    Interp *iPtr = (Interp *) interp;

    iPtr->limit.cmdCount = commandLimit;
    iPtr->limit.exceeded &= ~TCL_LIMIT_COMMANDS;
}

4075
4076
4077
4078
4079
4080
4081
4082

4083
4084
4085


4086
4087
4088
4089
4090
4091
4092
4029
4030
4031
4032
4033
4034
4035

4036
4037


4038
4039
4040
4041
4042
4043
4044
4045
4046







-
+

-
-
+
+







 *	commands. May make callbacks into other interpreters.
 *
 *----------------------------------------------------------------------
 */

static void
TimeLimitCallback(
    ClientData clientData)
    void *clientData)
{
    Tcl_Interp *interp = (Tcl_Interp *)clientData;
    Interp *iPtr = (Interp *)clientData;
    Tcl_Interp *interp = (Tcl_Interp *) clientData;
    Interp *iPtr = (Interp *) clientData;
    int code;

    Tcl_Preserve(interp);
    iPtr->limit.timeEvent = NULL;

    /*
     * Must reset the granularity ticker here to force an immediate full
4219
4220
4221
4222
4223
4224
4225
4226

4227
4228

4229
4230
4231
4232
4233
4234
4235
4173
4174
4175
4176
4177
4178
4179

4180
4181

4182
4183
4184
4185
4186
4187
4188
4189







-
+

-
+







 *	is removed.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteScriptLimitCallback(
    ClientData clientData)
    void *clientData)
{
    ScriptLimitCallback *limitCBPtr = (ScriptLimitCallback *)clientData;
    ScriptLimitCallback *limitCBPtr = (ScriptLimitCallback *) clientData;

    Tcl_DecrRefCount(limitCBPtr->scriptObj);
    if (limitCBPtr->entryPtr != NULL) {
	Tcl_DeleteHashEntry(limitCBPtr->entryPtr);
    }
    Tcl_Free(limitCBPtr);
}
4250
4251
4252
4253
4254
4255
4256
4257

4258
4259
4260

4261
4262
4263
4264
4265
4266
4267
4204
4205
4206
4207
4208
4209
4210

4211
4212
4213

4214
4215
4216
4217
4218
4219
4220
4221







-
+


-
+







 *	errors.
 *
 *----------------------------------------------------------------------
 */

static void
CallScriptLimitCallback(
    ClientData clientData,
    void *clientData,
    TCL_UNUSED(Tcl_Interp *))
{
    ScriptLimitCallback *limitCBPtr = (ScriptLimitCallback *)clientData;
    ScriptLimitCallback *limitCBPtr = (ScriptLimitCallback *) clientData;
    int code;

    if (Tcl_InterpDeleted(limitCBPtr->interp)) {
	return;
    }
    Tcl_Preserve(limitCBPtr->interp);
    code = Tcl_EvalObjEx(limitCBPtr->interp, limitCBPtr->scriptObj,
4283
4284
4285
4286
4287
4288
4289
4290

4291
4292
4293
4294
4295
4296
4297
4237
4238
4239
4240
4241
4242
4243

4244
4245
4246
4247
4248
4249
4250
4251







-
+







 *	interpreter through this mechanism (though as many interpreters may be
 *	limited as the programmer chooses overall).
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	A limit callback implemented as an invokation of a Tcl script in
 *	A limit callback implemented as an invocation of a Tcl script in
 *	another interpreter is either installed or removed.
 *
 *----------------------------------------------------------------------
 */

static void
SetScriptLimitCallback(
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
4264
4265
4266
4267
4268
4269
4270

4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281

4282
4283
4284
4285
4286
4287

4288
4289
4290
4291
4292
4293
4294
4295
4296







-
+










-
+





-
+
+







	Tcl_Panic("installing limit callback to the limited interpreter");
    }

    key.interp = targetInterp;
    key.type = type;

    if (scriptObj == NULL) {
	hashPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key);
	hashPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, &key);
	if (hashPtr != NULL) {
	    Tcl_LimitRemoveHandler(targetInterp, type, CallScriptLimitCallback,
		    Tcl_GetHashValue(hashPtr));
	}
	return;
    }

    hashPtr = Tcl_CreateHashEntry(&iPtr->limit.callbacks, &key,
	    &isNew);
    if (!isNew) {
	limitCBPtr = (ScriptLimitCallback *)Tcl_GetHashValue(hashPtr);
	limitCBPtr = (ScriptLimitCallback *) Tcl_GetHashValue(hashPtr);
	limitCBPtr->entryPtr = NULL;
	Tcl_LimitRemoveHandler(targetInterp, type, CallScriptLimitCallback,
		limitCBPtr);
    }

    limitCBPtr = (ScriptLimitCallback *)Tcl_Alloc(sizeof(ScriptLimitCallback));
    limitCBPtr = (ScriptLimitCallback *)
	    Tcl_Alloc(sizeof(ScriptLimitCallback));
    limitCBPtr->interp = interp;
    limitCBPtr->scriptObj = scriptObj;
    limitCBPtr->entryPtr = hashPtr;
    limitCBPtr->type = type;
    Tcl_IncrRefCount(scriptObj);

    Tcl_LimitAddHandler(targetInterp, type, CallScriptLimitCallback,
4412
4413
4414
4415
4416
4417
4418
4419

4420
4421
4422
4423
4424
4425
4426
4367
4368
4369
4370
4371
4372
4373

4374
4375
4376
4377
4378
4379
4380
4381







-
+







    iPtr->limit.cmdHandlers = NULL;
    iPtr->limit.cmdGranularity = 1;
    memset(&iPtr->limit.time, 0, sizeof(Tcl_Time));
    iPtr->limit.timeHandlers = NULL;
    iPtr->limit.timeEvent = NULL;
    iPtr->limit.timeGranularity = 10;
    Tcl_InitHashTable(&iPtr->limit.callbacks,
	    sizeof(ScriptLimitCallbackKey)/sizeof(int));
	    sizeof(ScriptLimitCallbackKey) / sizeof(int));
}

/*
 *----------------------------------------------------------------------
 *
 * InheritLimitsFromParent --
 *
4478
4479
4480
4481
4482
4483
4484
4485
4486


4487
4488
4489
4490
4491
4492
4493
4494

4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511


4512
4513
4514
4515
4516
4517
4518
4519
4520
4521

4522
4523

4524
4525
4526

4527
4528
4529
4530
4531
4532
4533
4534
4535

4536
4537
4538
4539


4540
4541
4542
4543
4544


4545
4546
4547
4548
4549

4550
4551
4552
4553
4554
4555
4556
4557
4558
4559

4560
4561
4562
4563

4564
4565

4566
4567
4568
4569
4570
4571
4572
4433
4434
4435
4436
4437
4438
4439


4440
4441
4442
4443
4444
4445
4446
4447
4448

4449
4450

4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464

4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475

4476
4477

4478
4479


4480
4481
4482
4483
4484
4485
4486
4487
4488

4489

4490


4491
4492

4493
4494


4495
4496
4497
4498
4499
4500

4501

4502
4503
4504
4505
4506
4507
4508
4509

4510
4511
4512
4513

4514
4515

4516
4517
4518
4519
4520
4521
4522
4523







-
-
+
+







-
+

-














-
+
+









-
+

-
+

-
-
+








-
+
-

-
-
+
+
-


-
-
+
+




-
+
-








-
+



-
+

-
+







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

static int
ChildCommandLimitCmd(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Interp *childInterp,	/* Interpreter being adjusted. */
    int consumedObjc,		/* Number of args already parsed. */
    int objc,			/* Total number of arguments. */
    Tcl_Size consumedObjc,	/* Number of args already parsed. */
    Tcl_Size objc,		/* Total number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static const char *const options[] = {
	"-command", "-granularity", "-value", NULL
    };
    enum Options {
	OPT_CMD, OPT_GRAN, OPT_VAL
    };
    } index;
    Interp *iPtr = (Interp *) interp;
    int index;
    ScriptLimitCallbackKey key;
    ScriptLimitCallback *limitCBPtr;
    Tcl_HashEntry *hPtr;

    /*
     * First, ensure that we are not reading or writing the calling
     * interpreter's limits; it may only manipulate its children. Note that
     * the low level API enforces this with Tcl_Panic, which we want to
     * avoid. [Bug 3398794]
     */

    if (interp == childInterp) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"limits on current interpreter inaccessible", -1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "SELF", NULL);
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "SELF",
		(char *)NULL);
	return TCL_ERROR;
    }

    if (objc == consumedObjc) {
	Tcl_Obj *dictPtr;

	TclNewObj(dictPtr);
	key.interp = childInterp;
	key.type = TCL_LIMIT_COMMANDS;
	hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key);
	hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, &key);
	if (hPtr != NULL) {
	    limitCBPtr = (ScriptLimitCallback *)Tcl_GetHashValue(hPtr);
	    limitCBPtr = (ScriptLimitCallback *) Tcl_GetHashValue(hPtr);
	    if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
		Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[0], -1),
			limitCBPtr->scriptObj);
		TclDictPut(NULL, dictPtr, options[0], limitCBPtr->scriptObj);
	    } else {
		goto putEmptyCommandInDict;
	    }
	} else {
	    Tcl_Obj *empty;

	putEmptyCommandInDict:
	    TclNewObj(empty);
	    Tcl_DictObjPut(NULL, dictPtr,
	    TclDictPut(NULL, dictPtr, options[0], empty);
		    Tcl_NewStringObj(options[0], -1), empty);
	}
	Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[1], -1),
		Tcl_NewWideIntObj(Tcl_LimitGetGranularity(childInterp,
	TclDictPut(NULL, dictPtr, options[1], Tcl_NewWideIntObj(
		Tcl_LimitGetGranularity(childInterp, TCL_LIMIT_COMMANDS)));
		TCL_LIMIT_COMMANDS)));

	if (Tcl_LimitTypeEnabled(childInterp, TCL_LIMIT_COMMANDS)) {
	    Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[2], -1),
		    Tcl_NewWideIntObj(Tcl_LimitGetCommands(childInterp)));
	    TclDictPut(NULL, dictPtr, options[2], Tcl_NewWideIntObj(
		    Tcl_LimitGetCommands(childInterp)));
	} else {
	    Tcl_Obj *empty;

	    TclNewObj(empty);
	    Tcl_DictObjPut(NULL, dictPtr,
	    TclDictPut(NULL, dictPtr, options[2], empty);
		    Tcl_NewStringObj(options[2], -1), empty);
	}
	Tcl_SetObjResult(interp, dictPtr);
	return TCL_OK;
    } else if (objc == consumedObjc+1) {
	if (Tcl_GetIndexFromObj(interp, objv[consumedObjc], options, "option",
		0, &index) != TCL_OK) {
	    return TCL_ERROR;
	}
	switch ((enum Options) index) {
	switch (index) {
	case OPT_CMD:
	    key.interp = childInterp;
	    key.type = TCL_LIMIT_COMMANDS;
	    hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key);
	    hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, &key);
	    if (hPtr != NULL) {
		limitCBPtr = (ScriptLimitCallback *)Tcl_GetHashValue(hPtr);
		limitCBPtr = (ScriptLimitCallback *) Tcl_GetHashValue(hPtr);
		if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
		    Tcl_SetObjResult(interp, limitCBPtr->scriptObj);
		}
	    }
	    break;
	case OPT_GRAN:
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
4580
4581
4582
4583
4584
4585
4586
4587
4588

4589
4590
4591
4592
4593
4594
4595
4596
4597

4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611

4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628

4629
4630
4631
4632
4633
4634
4635
4531
4532
4533
4534
4535
4536
4537


4538
4539
4540
4541
4542
4543
4544
4545
4546

4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560

4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577

4578
4579
4580
4581
4582
4583
4584
4585







-
-
+








-
+













-
+
















-
+







	    break;
	}
	return TCL_OK;
    } else if ((objc-consumedObjc) & 1 /* isOdd(objc-consumedObjc) */) {
	Tcl_WrongNumArgs(interp, consumedObjc, objv, "?-option value ...?");
	return TCL_ERROR;
    } else {
	int i;
	size_t scriptLen = 0, limitLen = 0;
	Tcl_Size i, scriptLen = 0, limitLen = 0;
	Tcl_Obj *scriptObj = NULL, *granObj = NULL, *limitObj = NULL;
	int gran = 0, limit = 0;

	for (i=consumedObjc ; i<objc ; i+=2) {
	    if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
		    &index) != TCL_OK) {
		return TCL_ERROR;
	    }
	    switch ((enum Options) index) {
	    switch (index) {
	    case OPT_CMD:
		scriptObj = objv[i+1];
		(void) TclGetStringFromObj(scriptObj, &scriptLen);
		break;
	    case OPT_GRAN:
		granObj = objv[i+1];
		if (TclGetIntFromObj(interp, objv[i+1], &gran) != TCL_OK) {
		    return TCL_ERROR;
		}
		if (gran < 1) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "granularity must be at least 1", -1));
		    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
			    "BADVALUE", NULL);
			    "BADVALUE", (char *)NULL);
		    return TCL_ERROR;
		}
		break;
	    case OPT_VAL:
		limitObj = objv[i+1];
		(void) TclGetStringFromObj(objv[i+1], &limitLen);
		if (limitLen == 0) {
		    break;
		}
		if (TclGetIntFromObj(interp, objv[i+1], &limit) != TCL_OK) {
		    return TCL_ERROR;
		}
		if (limit < 0) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "command limit value must be at least 0", -1));
		    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
			    "BADVALUE", NULL);
			    "BADVALUE", (char *)NULL);
		    return TCL_ERROR;
		}
		break;
	    }
	}
	if (scriptObj != NULL) {
	    SetScriptLimitCallback(interp, TCL_LIMIT_COMMANDS, childInterp,
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676





4677
4678
4679
4680
4681
4682
4683

4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700


4701
4702
4703
4704
4705
4706
4707
4708
4709
4710

4711
4712

4713
4714
4715

4716
4717
4718
4719
4720
4721
4722
4723

4724
4725
4726
4727


4728
4729
4730
4731
4732
4733
4734
4735
4736



4737
4738
4739
4740
4741
4742

4743
4744

4745
4746
4747
4748
4749
4750
4751
4752
4753
4754

4755
4756
4757
4758

4759
4760

4761
4762
4763
4764
4765
4766
4767
4615
4616
4617
4618
4619
4620
4621





4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632

4633
4634

4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648

4649
4650
4651
4652
4653
4654
4655
4656
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
4688

4689


4690

4691
4692
4693
4694
4695
4696
4697
4698

4699
4700
4701
4702

4703
4704

4705
4706
4707
4708
4709
4710
4711
4712







-
-
-
-
-
+
+
+
+
+






-
+

-














-
+
+









-
+

-
+

-
-
+







-
+
-

-
-
+
+
-





-
-
-
+
+
+





-
+
-
-
+
-








-
+



-
+

-
+







 *	Depends on the arguments.
 *
 *----------------------------------------------------------------------
 */

static int
ChildTimeLimitCmd(
    Tcl_Interp *interp,			/* Current interpreter. */
    Tcl_Interp *childInterp,		/* Interpreter being adjusted. */
    int consumedObjc,			/* Number of args already parsed. */
    int objc,				/* Total number of arguments. */
    Tcl_Obj *const objv[])		/* Argument objects. */
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Interp *childInterp,	/* Interpreter being adjusted. */
    Tcl_Size consumedObjc,	/* Number of args already parsed. */
    Tcl_Size objc,		/* Total number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static const char *const options[] = {
	"-command", "-granularity", "-milliseconds", "-seconds", NULL
    };
    enum Options {
	OPT_CMD, OPT_GRAN, OPT_MILLI, OPT_SEC
    };
    } index;
    Interp *iPtr = (Interp *) interp;
    int index;
    ScriptLimitCallbackKey key;
    ScriptLimitCallback *limitCBPtr;
    Tcl_HashEntry *hPtr;

    /*
     * First, ensure that we are not reading or writing the calling
     * interpreter's limits; it may only manipulate its children. Note that
     * the low level API enforces this with Tcl_Panic, which we want to
     * avoid. [Bug 3398794]
     */

    if (interp == childInterp) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"limits on current interpreter inaccessible", -1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "SELF", NULL);
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "SELF",
		(char *)NULL);
	return TCL_ERROR;
    }

    if (objc == consumedObjc) {
	Tcl_Obj *dictPtr;

	TclNewObj(dictPtr);
	key.interp = childInterp;
	key.type = TCL_LIMIT_TIME;
	hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key);
	hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, &key);
	if (hPtr != NULL) {
	    limitCBPtr = (ScriptLimitCallback *)Tcl_GetHashValue(hPtr);
	    limitCBPtr = (ScriptLimitCallback *) Tcl_GetHashValue(hPtr);
	    if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
		Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[0], -1),
			limitCBPtr->scriptObj);
		TclDictPut(NULL, dictPtr, options[0], limitCBPtr->scriptObj);
	    } else {
		goto putEmptyCommandInDict;
	    }
	} else {
	    Tcl_Obj *empty;
	putEmptyCommandInDict:
	    TclNewObj(empty);
	    Tcl_DictObjPut(NULL, dictPtr,
	    TclDictPut(NULL, dictPtr, options[0], empty);
		    Tcl_NewStringObj(options[0], -1), empty);
	}
	Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[1], -1),
		Tcl_NewWideIntObj(Tcl_LimitGetGranularity(childInterp,
	TclDictPut(NULL, dictPtr, options[1], Tcl_NewWideIntObj(
		Tcl_LimitGetGranularity(childInterp, TCL_LIMIT_TIME)));
		TCL_LIMIT_TIME)));

	if (Tcl_LimitTypeEnabled(childInterp, TCL_LIMIT_TIME)) {
	    Tcl_Time limitMoment;

	    Tcl_LimitGetTime(childInterp, &limitMoment);
	    Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[2], -1),
		    Tcl_NewWideIntObj(limitMoment.usec/1000));
	    Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[3], -1),
	    TclDictPut(NULL, dictPtr, options[2],
		    Tcl_NewWideIntObj(limitMoment.usec / 1000));
	    TclDictPut(NULL, dictPtr, options[3],
		    Tcl_NewWideIntObj(limitMoment.sec));
	} else {
	    Tcl_Obj *empty;

	    TclNewObj(empty);
	    Tcl_DictObjPut(NULL, dictPtr,
	    TclDictPut(NULL, dictPtr, options[2], empty);
		    Tcl_NewStringObj(options[2], -1), empty);
	    Tcl_DictObjPut(NULL, dictPtr,
	    TclDictPut(NULL, dictPtr, options[3], empty);
		    Tcl_NewStringObj(options[3], -1), empty);
	}
	Tcl_SetObjResult(interp, dictPtr);
	return TCL_OK;
    } else if (objc == consumedObjc+1) {
	if (Tcl_GetIndexFromObj(interp, objv[consumedObjc], options, "option",
		0, &index) != TCL_OK) {
	    return TCL_ERROR;
	}
	switch ((enum Options) index) {
	switch (index) {
	case OPT_CMD:
	    key.interp = childInterp;
	    key.type = TCL_LIMIT_TIME;
	    hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key);
	    hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, &key);
	    if (hPtr != NULL) {
		limitCBPtr = (ScriptLimitCallback *)Tcl_GetHashValue(hPtr);
		limitCBPtr = (ScriptLimitCallback *) Tcl_GetHashValue(hPtr);
		if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
		    Tcl_SetObjResult(interp, limitCBPtr->scriptObj);
		}
	    }
	    break;
	case OPT_GRAN:
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
4786
4787
4788
4789
4790
4791
4792
4793
4794

4795
4796
4797
4798
4799

4800
4801
4802
4803
4804
4805
4806
4807

4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821

4822
4823
4824
4825
4826
4827
4828
4829
4830
4831

4832
4833
4834
4835
4836

4837
4838

4839
4840
4841

4842
4843
4844
4845
4846
4847
4848
4849

4850
4851
4852
4853
4854

4855
4856

4857
4858
4859

4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875

4876
4877
4878
4879
4880
4881
4882
4883

4884
4885
4886
4887
4888
4889
4890
4731
4732
4733
4734
4735
4736
4737


4738
4739
4740
4741
4742

4743
4744
4745
4746
4747
4748
4749
4750

4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764

4765
4766
4767
4768
4769
4770
4771
4772
4773
4774

4775
4776
4777
4778
4779

4780
4781

4782
4783
4784

4785
4786
4787
4788
4789
4790
4791
4792

4793
4794
4795
4796
4797

4798
4799

4800
4801
4802

4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818

4819
4820
4821
4822
4823
4824
4825
4826

4827
4828
4829
4830
4831
4832
4833
4834







-
-
+




-
+







-
+













-
+









-
+




-
+

-
+


-
+







-
+




-
+

-
+


-
+















-
+







-
+







	    break;
	}
	return TCL_OK;
    } else if ((objc-consumedObjc) & 1 /* isOdd(objc-consumedObjc) */) {
	Tcl_WrongNumArgs(interp, consumedObjc, objv, "?-option value ...?");
	return TCL_ERROR;
    } else {
	int i;
	size_t scriptLen = 0, milliLen = 0, secLen = 0;
	Tcl_Size i, scriptLen = 0, milliLen = 0, secLen = 0;
	Tcl_Obj *scriptObj = NULL, *granObj = NULL;
	Tcl_Obj *milliObj = NULL, *secObj = NULL;
	int gran = 0;
	Tcl_Time limitMoment;
	int tmp;
	Tcl_WideInt tmp;

	Tcl_LimitGetTime(childInterp, &limitMoment);
	for (i=consumedObjc ; i<objc ; i+=2) {
	    if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
		    &index) != TCL_OK) {
		return TCL_ERROR;
	    }
	    switch ((enum Options) index) {
	    switch (index) {
	    case OPT_CMD:
		scriptObj = objv[i+1];
		(void) TclGetStringFromObj(objv[i+1], &scriptLen);
		break;
	    case OPT_GRAN:
		granObj = objv[i+1];
		if (TclGetIntFromObj(interp, objv[i+1], &gran) != TCL_OK) {
		    return TCL_ERROR;
		}
		if (gran < 1) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "granularity must be at least 1", -1));
		    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
			    "BADVALUE", NULL);
			    "BADVALUE", (char *)NULL);
		    return TCL_ERROR;
		}
		break;
	    case OPT_MILLI:
		milliObj = objv[i+1];
		(void) TclGetStringFromObj(objv[i+1], &milliLen);
		if (milliLen == 0) {
		    break;
		}
		if (TclGetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
		if (TclGetWideIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
		    return TCL_ERROR;
		}
		if (tmp < 0) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "milliseconds must be at least 0", -1));
			    "milliseconds must be non-negative", -1));
		    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
			    "BADVALUE", NULL);
			    "BADVALUE", (char *)NULL);
		    return TCL_ERROR;
		}
		limitMoment.usec = ((long) tmp)*1000;
		limitMoment.usec = tmp*1000;
		break;
	    case OPT_SEC:
		secObj = objv[i+1];
		(void) TclGetStringFromObj(objv[i+1], &secLen);
		if (secLen == 0) {
		    break;
		}
		if (TclGetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
		if (TclGetWideIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
		    return TCL_ERROR;
		}
		if (tmp < 0) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "seconds must be at least 0", -1));
			    "seconds must be non-negative", -1));
		    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
			    "BADVALUE", NULL);
			    "BADVALUE", (char *)NULL);
		    return TCL_ERROR;
		}
		limitMoment.sec = tmp;
		limitMoment.sec = (long long) tmp;
		break;
	    }
	}
	if (milliObj != NULL || secObj != NULL) {
	    if (milliObj != NULL) {
		/*
		 * Setting -milliseconds but clearing -seconds, or resetting
		 * -milliseconds but not resetting -seconds? Bad voodoo!
		 */

		if (secObj != NULL && secLen == 0 && milliLen > 0) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "may only set -milliseconds if -seconds is not "
			    "also being reset", -1));
		    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
			    "BADUSAGE", NULL);
			    "BADUSAGE", (char *)NULL);
		    return TCL_ERROR;
		}
		if (milliLen == 0 && (secObj == NULL || secLen > 0)) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "may only reset -milliseconds if -seconds is "
			    "also being reset", -1));
		    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
			    "BADUSAGE", NULL);
			    "BADUSAGE", (char *)NULL);
		    return TCL_ERROR;
		}
	    }

	    if (milliLen > 0 || secLen > 0) {
		/*
		 * Force usec to be in range [0..1000000), possibly

Changes to generic/tclLink.c.

1
2
3
4
5
6
7
8
9
10
11
12




13
14
15
16
17
18
19
1
2
3
4
5
6
7
8




9
10
11
12
13
14
15
16
17
18
19








-
-
-
-
+
+
+
+







/*
 * tclLink.c --
 *
 *	This file implements linked variables (a C variable that is tied to a
 *	Tcl variable). The idea of linked variables was first suggested by
 *	Andreas Stolcke and this implementation is based heavily on a
 *	prototype implementation provided by him.
 *
 * Copyright (c) 1993 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 2008 Rene Zaumseil
 * Copyright (c) 2019 Donal K. Fellows
 * Copyright © 1993 The Regents of the University of California.
 * Copyright © 1994-1997 Sun Microsystems, Inc.
 * Copyright © 2008 Rene Zaumseil
 * Copyright © 2019 Donal K. Fellows
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclTomMath.h"
29
30
31
32
33
34
35
36

37
38
39

40
41
42
43
44
45
46
29
30
31
32
33
34
35

36
37
38

39
40
41
42
43
44
45
46







-
+


-
+







    Tcl_Interp *interp;		/* Interpreter containing Tcl variable. */
    Namespace *nsPtr;		/* Namespace containing Tcl variable */
    Tcl_Obj *varName;		/* Name of variable (must be global). This is
				 * needed during trace callbacks, since the
				 * actual variable may be aliased at that time
				 * via upvar. */
    void *addr;			/* Location of C variable. */
    size_t bytes;		/* Size of C variable array. This is 0 when
    Tcl_Size bytes;		/* Size of C variable array. This is 0 when
				 * single variables, and >0 used for array
				 * variables. */
    size_t numElems;	/* Number of elements in C variable array.
    Tcl_Size numElems;	/* Number of elements in C variable array.
				 * Zero for single variables. */
    int type;			/* Type of link (TCL_LINK_INT, etc.). */
    union {
	char c;
	unsigned char uc;
	int i;
	unsigned int ui;
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
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







-
+













-
+




-
+
+







#define LINK_ALLOC_ADDR		4
#define LINK_ALLOC_LAST		8

/*
 * Forward references to functions defined later in this file:
 */

static char *		LinkTraceProc(ClientData clientData,Tcl_Interp *interp,
static char *		LinkTraceProc(void *clientData,Tcl_Interp *interp,
			    const char *name1, const char *name2, int flags);
static Tcl_Obj *	ObjValue(Link *linkPtr);
static void		LinkFree(Link *linkPtr);
static int		GetInvalidIntFromObj(Tcl_Obj *objPtr, int *intPtr);
static int		GetInvalidDoubleFromObj(Tcl_Obj *objPtr,
			    double *doublePtr);
static int		SetInvalidRealFromAny(Tcl_Interp *interp,
			    Tcl_Obj *objPtr);

/*
 * A marker type used to flag weirdnesses so we can pass them around right.
 */

static Tcl_ObjType invalidRealType = {
static const Tcl_ObjType invalidRealType = {
    "invalidReal",			/* name */
    NULL,				/* freeIntRepProc */
    NULL,				/* dupIntRepProc */
    NULL,				/* updateStringProc */
    NULL				/* setFromAnyProc */
    NULL,				/* setFromAnyProc */
    TCL_OBJTYPE_V1(TclLengthOne)
};

/*
 * Convenience macro for accessing the value of the C variable pointed to by a
 * link. Note that this macro produces something that may be regarded as an
 * lvalue or rvalue; it may be assigned to as well as read. Also note that
 * this macro assumes the name of the variable being accessed (linkPtr); this
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
175
176
177
178
179
180
181








182
183
184
185
186
187
188







-
-
-
-
-
-
-
-







    linkPtr = (Link *)Tcl_Alloc(sizeof(Link));
    linkPtr->interp = interp;
    linkPtr->nsPtr = NULL;
    linkPtr->varName = Tcl_NewStringObj(varName, -1);
    Tcl_IncrRefCount(linkPtr->varName);
    linkPtr->addr = addr;
    linkPtr->type = type & ~TCL_LINK_READ_ONLY;
#if !defined(TCL_NO_DEPRECATED) && (defined(TCL_WIDE_INT_IS_LONG) \
	|| defined(_WIN32) || defined(__CYGWIN__))
    if (linkPtr->type == 11 /* legacy TCL_LINK_LONG */) {
	linkPtr->type = TCL_LINK_LONG;
    } else if (linkPtr->type == 12 /* legacy TCL_LINK_ULONG */) {
	linkPtr->type = TCL_LINK_ULONG;
    }
#endif
    if (type & TCL_LINK_READ_ONLY) {
	linkPtr->flags = LINK_READ_ONLY;
    } else {
	linkPtr->flags = 0;
    }
    linkPtr->bytes = 0;
    linkPtr->numElems = 0;
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
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







-
+















-
-
-
-
-
-
-
-







    const char *varName,	/* Name of a global variable in interp. */
    void *addr,			/* Address of a C variable to be linked to
				 * varName. If NULL then the necessary space
				 * will be allocated and returned as the
				 * interpreter result. */
    int type,			/* Type of C variable: TCL_LINK_INT, etc. Also
				 * may have TCL_LINK_READ_ONLY OR'ed in. */
    size_t size)			/* Size of C variable array, >1 if array */
    Tcl_Size size)		/* Size of C variable array, >1 if array */
{
    Tcl_Obj *objPtr;
    Link *linkPtr;
    Namespace *dummy;
    const char *name;
    int code;

    if (size < 1) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"wrong array size given", -1));
	return TCL_ERROR;
    }

    linkPtr = (Link *)Tcl_Alloc(sizeof(Link));
    linkPtr->type = type & ~TCL_LINK_READ_ONLY;
#if !defined(TCL_NO_DEPRECATED) && (defined(TCL_WIDE_INT_IS_LONG) \
	|| defined(_WIN32) || defined(__CYGWIN__))
    if (linkPtr->type == 11 /* legacy TCL_LINK_LONG */) {
	linkPtr->type = TCL_LINK_LONG;
    } else if (linkPtr->type == 12 /* legacy TCL_LINK_ULONG */) {
	linkPtr->type = TCL_LINK_ULONG;
    }
#endif
    linkPtr->numElems = size;
    if (type & TCL_LINK_READ_ONLY) {
	linkPtr->flags = LINK_READ_ONLY;
    } else {
	linkPtr->flags = 0;
    }

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
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







-
-
-
-
-
-
-
-










-
+







	break;
    case TCL_LINK_USHORT:
	linkPtr->bytes = size * sizeof(unsigned short);
	break;
    case TCL_LINK_UINT:
	linkPtr->bytes = size * sizeof(unsigned int);
	break;
#if !defined(TCL_WIDE_INT_IS_LONG) && !defined(_WIN32) && !defined(__CYGWIN__)
    case TCL_LINK_LONG:
	linkPtr->bytes = size * sizeof(long);
	break;
    case TCL_LINK_ULONG:
	linkPtr->bytes = size * sizeof(unsigned long);
	break;
#endif
    case TCL_LINK_FLOAT:
	linkPtr->bytes = size * sizeof(float);
	break;
    case TCL_LINK_STRING:
	linkPtr->bytes = size * sizeof(char);
	size = 1;		/* This is a variable length string, no need
				 * to check last value. */

	/*
	 * If no address is given create one and use as address the
         * not needed linkPtr->lastValue
	 * not needed linkPtr->lastValue
	 */

	if (addr == NULL) {
	    linkPtr->lastValue.aryPtr = Tcl_Alloc(linkPtr->bytes);
	    linkPtr->flags |= LINK_ALLOC_LAST;
	    addr = (char *) &linkPtr->lastValue.cPtr;
	}
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
558
559
560
561
562
563
564
565
566

567
568

569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591

592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609

610
611
612
613
614
615
616
617
618

619
620

621
622
623
624
625
626
627
628
629
630
631
632
633
634
635



636
637
638
639
640
641
642
643
644
645
646
647


648
649
650
651
652
653
654
655
656
657
658
659

660
661
662
663
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
707
708
709

710
711
712
713
714
715
716
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
558
559
560
561
562
563
564
565
566
567
568


569
570
571
572
573
574
575
576
577
578
579
580
581


582
583
584
585
586
587
588
589
590
591
592
593
594

595
596
597
598
599
600
601
602
603
604
605




606
607
608
609
610
611
612
613
614
615
616

617
618
619


620
621
622
623
624
625
626
627
628
629
630
631




632
633
634
635
636
637
638
639
640
641
642
643
644

645
646
647
648
649
650
651
652







-
+















-
+
-
-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-












-
+

















-
+








-
+

-
+













-
-
+
+
+










-
-
+
+











-
+










-
-
-
-
+
+
+
+







-
+


-
-
+
+










-
-
-
-
+
+
+
+









-
+







}

static inline int
GetWide(
    Tcl_Obj *objPtr,
    Tcl_WideInt *widePtr)
{
    if (Tcl_GetWideIntFromObj(NULL, objPtr, widePtr) != TCL_OK) {
    if (TclGetWideIntFromObj(NULL, objPtr, widePtr) != TCL_OK) {
	int intValue;

	if (GetInvalidIntFromObj(objPtr, &intValue) != TCL_OK) {
	    return 1;
	}
	*widePtr = intValue;
    }
    return 0;
}

static inline int
GetUWide(
    Tcl_Obj *objPtr,
    Tcl_WideUInt *uwidePtr)
{
    Tcl_WideInt *widePtr = (Tcl_WideInt *) uwidePtr;
    if (Tcl_GetWideUIntFromObj(NULL, objPtr, uwidePtr) != TCL_OK) {
    ClientData clientData;
    int type, intValue;
	int intValue;

    if (TclGetNumberFromObj(NULL, objPtr, &clientData, &type) == TCL_OK) {
	if (type == TCL_NUMBER_INT) {
	    *widePtr = *((const Tcl_WideInt *) clientData);
	    return (*widePtr < 0);
	} else if (type == TCL_NUMBER_BIG) {
	    mp_int *numPtr = (mp_int *)clientData;
	    Tcl_WideUInt value = 0;
	    union {
		Tcl_WideUInt value;
		unsigned char bytes[sizeof(Tcl_WideUInt)];
	    } scratch;
	    size_t numBytes;
	    unsigned char *bytes = scratch.bytes;

	if (GetInvalidIntFromObj(objPtr, &intValue) != TCL_OK) {
	    if (numPtr->sign || (MP_OKAY != mp_to_ubin(numPtr,
		    bytes, sizeof(Tcl_WideUInt), &numBytes))) {
		/*
		 * If the sign bit is set (a negative value) or if the value
		 * can't possibly fit in the bits of an unsigned wide, there's
		 * no point in doing further conversion.
		 */
		return 1;
	    }
	    return 1;
	}
#ifdef WORDS_BIGENDIAN
	    while (numBytes-- > 0) {
		value = (value << CHAR_BIT) | *bytes++;
	    }
#else /* !WORDS_BIGENDIAN */
	    /*
	     * Little-endian can read the value directly.
	     */
	    value = scratch.value;
#endif /* WORDS_BIGENDIAN */
	    *uwidePtr = value;
	*uwidePtr = intValue;
	    return 0;
	}
    }
    }

    /*
     * Evil edge case fallback.
     */

    if (GetInvalidIntFromObj(objPtr, &intValue) != TCL_OK) {
	return 1;
    }
    *uwidePtr = intValue;
    return 0;
}

static inline int
GetDouble(
    Tcl_Obj *objPtr,
    double *dblPtr)
{
    if (Tcl_GetDoubleFromObj(NULL, objPtr, dblPtr) == TCL_OK) {
	return 0;
    } else {
#ifdef ACCEPT_NAN
	Tcl_ObjIntRep *irPtr = TclFetchIntRep(objPtr, &tclDoubleType);
	Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objPtr, &tclDoubleType);

	if (irPtr != NULL) {
	    *dblPtr = irPtr->doubleValue;
	    return 0;
	}
#endif /* ACCEPT_NAN */
	return GetInvalidDoubleFromObj(objPtr, dblPtr) != TCL_OK;
    }
}

static inline int
EqualDouble(
    double a,
    double b)
{
    return (a == b)
#ifdef ACCEPT_NAN
	|| (TclIsNaN(a) && TclIsNaN(b))
	|| (isnan(a) && isnan(b))
#endif /* ACCEPT_NAN */
	;
}

static inline int
IsSpecial(
    double a)
{
    return TclIsInfinite(a)
    return isinf(a)
#ifdef ACCEPT_NAN
	|| TclIsNaN(a)
	|| isnan(a)
#endif /* ACCEPT_NAN */
	;
}

/*
 * Mark an object as holding a weird double.
 */

static int
SetInvalidRealFromAny(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Obj *objPtr)
{
    size_t length;
    const char *str, *endPtr;
    const char *str;
    const char *endPtr;
    Tcl_Size length;

    str = TclGetStringFromObj(objPtr, &length);
    if ((length == 1) && (str[0] == '.')) {
	objPtr->typePtr = &invalidRealType;
	objPtr->internalRep.doubleValue = 0.0;
	return TCL_OK;
    }
    if (TclParseNumber(NULL, objPtr, NULL, str, length, &endPtr,
	    TCL_PARSE_DECIMAL_ONLY) == TCL_OK) {
	/*
	 * If number is followed by [eE][+-]?, then it is an invalid double,
	 * but it could be the start of a valid double.
	 * If number is followed by [eE][+-]?, then it is an invalid
	 * double, but it could be the start of a valid double.
	 */

	if (*endPtr == 'e' || *endPtr == 'E') {
	    ++endPtr;
	    if (*endPtr == '+' || *endPtr == '-') {
		++endPtr;
	    }
	    if (*endPtr == 0) {
		double doubleValue = 0.0;

		Tcl_GetDoubleFromObj(NULL, objPtr, &doubleValue);
		TclFreeIntRep(objPtr);
		TclFreeInternalRep(objPtr);
		objPtr->typePtr = &invalidRealType;
		objPtr->internalRep.doubleValue = doubleValue;
		return TCL_OK;
	    }
	}
    }
    return TCL_ERROR;
}

/*
 * This function checks for integer representations, which are valid when
 * linking with C variables, but which are invalid in other contexts in Tcl.
 * Handled are "+", "-", "", "0x", "0b", "0d" and "0o" (upper- and
 * lower-case).  See bug [39f6304c2e].
 * This function checks for integer representations, which are valid
 * when linking with C variables, but which are invalid in other
 * contexts in Tcl. Handled are "+", "-", "", "0x", "0b", "0d" and "0o"
 * (upperand lowercase). See bug [39f6304c2e].
 */

static int
GetInvalidIntFromObj(
    Tcl_Obj *objPtr,
    int *intPtr)
{
    size_t length;
    Tcl_Size length;
    const char *str = TclGetStringFromObj(objPtr, &length);

    if ((length == 0) ||
	    ((length == 2) && (str[0] == '0') && strchr("xXbBoOdD", str[1]))) {
    if ((length == 0) || ((length == 2) && (str[0] == '0')
	    && strchr("xXbBoOdD", str[1]))) {
	*intPtr = 0;
	return TCL_OK;
    } else if ((length == 1) && strchr("+-", str[0])) {
	*intPtr = (str[0] == '+');
	return TCL_OK;
    }
    return TCL_ERROR;
}

/*
 * This function checks for double representations, which are valid when
 * linking with C variables, but which are invalid in other contexts in Tcl.
 * Handled are "+", "-", "", ".", "0x", "0b" and "0o" (upper- and lower-case)
 * and sequences like "1e-". See bug [39f6304c2e].
 * This function checks for double representations, which are valid
 * when linking with C variables, but which are invalid in other
 * contexts in Tcl. Handled are "+", "-", "", ".", "0x", "0b" and "0o"
 * (upper- and lowercase) and sequences like "1e-". See bug [39f6304c2e].
 */

static int
GetInvalidDoubleFromObj(
    Tcl_Obj *objPtr,
    double *doublePtr)
{
    int intValue;

    if (TclHasIntRep(objPtr, &invalidRealType)) {
    if (TclHasInternalRep(objPtr, &invalidRealType)) {
	goto gotdouble;
    }
    if (GetInvalidIntFromObj(objPtr, &intValue) == TCL_OK) {
	*doublePtr = (double) intValue;
	return TCL_OK;
    }
    if (SetInvalidRealFromAny(NULL, objPtr) == TCL_OK) {
740
741
742
743
744
745
746
747

748
749
750
751
752
753
754
755
756
757
758

759
760
761
762
763
764
765
766

767
768
769
770
771
772
773
774
775
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
707
708
709
710







-
+










-
+







-
+

-







 *	modification.
 *
 *----------------------------------------------------------------------
 */

static char *
LinkTraceProc(
    ClientData clientData,	/* Contains information about the link. */
    void *clientData,	/* Contains information about the link. */
    Tcl_Interp *interp,		/* Interpreter containing Tcl variable. */
    TCL_UNUSED(const char *) /*name1*/,
    TCL_UNUSED(const char *) /*name2*/,
				/* Links can only be made to global variables,
				 * so we can find them with need to resolve
				 * caller-supplied name in caller context. */
    int flags)			/* Miscellaneous additional information. */
{
    Link *linkPtr = (Link *)clientData;
    int changed;
    size_t valueLength = 0;
    Tcl_Size valueLength = 0;
    const char *value;
    char **pp;
    Tcl_Obj *valueObj;
    int valueInt;
    Tcl_WideInt valueWide;
    Tcl_WideUInt valueUWide;
    double valueDouble;
    int objc;
    Tcl_Size objc, i;
    Tcl_Obj **objv;
    int i;

    /*
     * If the variable is being unset, then just re-create it (with a trace)
     * unless the whole interpreter is going away.
     */

    if (flags & TCL_TRACE_UNSETS) {
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
771
772
773
774
775
776
777








778
779
780
781
782
783
784







-
-
-
-
-
-
-
-







		break;
	    case TCL_LINK_USHORT:
		changed = (LinkedVar(unsigned short) != linkPtr->lastValue.us);
		break;
	    case TCL_LINK_UINT:
		changed = (LinkedVar(unsigned int) != linkPtr->lastValue.ui);
		break;
#if !defined(TCL_WIDE_INT_IS_LONG) && !defined(_WIN32) && !defined(__CYGWIN__)
	    case TCL_LINK_LONG:
		changed = (LinkedVar(long) != linkPtr->lastValue.l);
		break;
	    case TCL_LINK_ULONG:
		changed = (LinkedVar(unsigned long) != linkPtr->lastValue.ul);
		break;
#endif
	    case TCL_LINK_FLOAT:
		changed = !EqualDouble(LinkedVar(float), linkPtr->lastValue.f);
		break;
	    case TCL_LINK_STRING:
	    case TCL_LINK_CHARS:
	    case TCL_LINK_BINARY:
		changed = 1;
867
868
869
870
871
872
873
874

875
876
877
878
879
880
881
794
795
796
797
798
799
800

801
802
803
804
805
806
807
808







-
+







	}
	return NULL;
    }

    /*
     * For writes, first make sure that the variable is writable. Then convert
     * the Tcl value to C if possible. If the variable isn't writable or can't
     * be converted, then restore the varaible's old value and return an
     * be converted, then restore the variable's old value and return an
     * error. Another tricky thing: we have to save and restore the interp's
     * result, since the variable access could occur when the result has been
     * partially set.
     */

    if (linkPtr->flags & LINK_READ_ONLY) {
	Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
916
917
918
919
920
921
922
923
924




925
926
927
928
929
930
931
843
844
845
846
847
848
849


850
851
852
853
854
855
856
857
858
859
860







-
-
+
+
+
+







	} else {
	    linkPtr->lastValue.c = '\0';
	    LinkedVar(char) = linkPtr->lastValue.c;
	}
	return NULL;

    case TCL_LINK_BINARY:
	value = (char *) TclGetByteArrayFromObj(valueObj, &valueLength);
	if (valueLength != linkPtr->bytes) {
	value = (char *) Tcl_GetBytesFromObj(NULL, valueObj, &valueLength);
	if (value == NULL) {
	    return (char *) "invalid binary value";
	} else if (valueLength != linkPtr->bytes) {
	    return (char *) "wrong size of binary value";
	}
	if (linkPtr->flags & LINK_ALLOC_LAST) {
	    memcpy(linkPtr->lastValue.aryPtr, value, valueLength);
	    memcpy(linkPtr->addr, value, valueLength);
	} else {
	    linkPtr->lastValue.uc = (unsigned char) *value;
943
944
945
946
947
948
949
950
951


952
953
954
955
956
957
958
959

960
961
962
963
964
965

966
967
968
969
970
971
972
872
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
898
899
900
901







-
-
+
+







-
+





-
+







    ((value) >= (lowerLimit) && (value) <= (upperLimit))

    /*
     * If we're working with an array of numbers, extract the Tcl list.
     */

    if (linkPtr->flags & LINK_ALLOC_LAST) {
	if (Tcl_ListObjGetElements(NULL, (valueObj), &objc, &objv) == TCL_ERROR
		|| (size_t)objc != linkPtr->numElems) {
	if (TclListObjGetElements(NULL, (valueObj), &objc, &objv) == TCL_ERROR
		|| objc != linkPtr->numElems) {
	    return (char *) "wrong dimension";
	}
    }

    switch (linkPtr->type) {
    case TCL_LINK_INT:
	if (linkPtr->flags & LINK_ALLOC_LAST) {
	    for (i=0; i < objc; i++) {
	    for (i = 0; i < objc; i++) {
		int *varPtr = &linkPtr->lastValue.iPtr[i];

		if (GetInt(objv[i], varPtr)) {
		    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			    ObjValue(linkPtr), TCL_GLOBAL_ONLY);
	            return (char *) "variable array must have integer values";
		    return (char *) "variable array must have integer values";
		}
	    }
	} else {
	    int *varPtr = &linkPtr->lastValue.i;

	    if (GetInt(valueObj, varPtr)) {
		Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
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
1116
1117
1118
1119
1120

1121
1122
1123

1124
1125
1126
1127
1128
1129
1130

1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144

1145
1146
1147

1148
1149
1150
1151
1152
1153
1154

1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218

1219
1220
1221
1222
1223
1224
1225
1226
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
955
956
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
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
1116
1117

1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
1128
1129
1130

1131
1132
1133
1134
1135
1136
1137
1138







-
+


















-
+


-
+


















-
+









-
+
















-
+


















-
+


-
+






-
+













-
+


-
+






-
+








-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-






-
+



















-
+


-
+









-
+







	if (linkPtr->flags & LINK_ALLOC_LAST) {
	    for (i=0; i < objc; i++) {
		int *varPtr = &linkPtr->lastValue.iPtr[i];

		if (Tcl_GetBooleanFromObj(NULL, objv[i], varPtr) != TCL_OK) {
		    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			    ObjValue(linkPtr), TCL_GLOBAL_ONLY);
	            return (char *) "variable array must have boolean value";
		    return (char *) "variable array must have boolean value";
		}
	    }
	} else {
	    int *varPtr = &linkPtr->lastValue.i;

	    if (Tcl_GetBooleanFromObj(NULL, valueObj, varPtr) != TCL_OK) {
		Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			ObjValue(linkPtr), TCL_GLOBAL_ONLY);
		return (char *) "variable must have boolean value";
	    }
	    LinkedVar(int) = *varPtr;
	}
	break;

    case TCL_LINK_CHAR:
	if (linkPtr->flags & LINK_ALLOC_LAST) {
	    for (i=0; i < objc; i++) {
		if (GetInt(objv[i], &valueInt)
		        || !InRange(SCHAR_MIN, valueInt, SCHAR_MAX)) {
			|| !InRange(SCHAR_MIN, valueInt, SCHAR_MAX)) {
		    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			    ObjValue(linkPtr), TCL_GLOBAL_ONLY);
	            return (char *) "variable array must have char value";
		    return (char *) "variable array must have char value";
		}
		linkPtr->lastValue.cPtr[i] = (char) valueInt;
	    }
	} else {
	    if (GetInt(valueObj, &valueInt)
		    || !InRange(SCHAR_MIN, valueInt, SCHAR_MAX)) {
		Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			ObjValue(linkPtr), TCL_GLOBAL_ONLY);
		return (char *) "variable must have char value";
	    }
	    LinkedVar(char) = linkPtr->lastValue.c = (char) valueInt;
	}
	break;

    case TCL_LINK_UCHAR:
	if (linkPtr->flags & LINK_ALLOC_LAST) {
	    for (i=0; i < objc; i++) {
		if (GetInt(objv[i], &valueInt)
		        || !InRange(0, valueInt, UCHAR_MAX)) {
			|| !InRange(0, valueInt, (int)UCHAR_MAX)) {
		    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			    ObjValue(linkPtr), TCL_GLOBAL_ONLY);
		    return (char *)
			    "variable array must have unsigned char value";
		}
		linkPtr->lastValue.ucPtr[i] = (unsigned char) valueInt;
	    }
	} else {
	    if (GetInt(valueObj, &valueInt)
		    || !InRange(0, valueInt, UCHAR_MAX)) {
		    || !InRange(0, valueInt, (int)UCHAR_MAX)) {
		Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			ObjValue(linkPtr), TCL_GLOBAL_ONLY);
		return (char *) "variable must have unsigned char value";
	    }
	    LinkedVar(unsigned char) = linkPtr->lastValue.uc =
		    (unsigned char) valueInt;
	}
	break;

    case TCL_LINK_SHORT:
	if (linkPtr->flags & LINK_ALLOC_LAST) {
	    for (i=0; i < objc; i++) {
		if (GetInt(objv[i], &valueInt)
			|| !InRange(SHRT_MIN, valueInt, SHRT_MAX)) {
		    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			    ObjValue(linkPtr), TCL_GLOBAL_ONLY);
	            return (char *) "variable array must have short value";
		    return (char *) "variable array must have short value";
		}
		linkPtr->lastValue.sPtr[i] = (short) valueInt;
	    }
	} else {
	    if (GetInt(valueObj, &valueInt)
		    || !InRange(SHRT_MIN, valueInt, SHRT_MAX)) {
		Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			ObjValue(linkPtr), TCL_GLOBAL_ONLY);
		return (char *) "variable must have short value";
	    }
	    LinkedVar(short) = linkPtr->lastValue.s = (short) valueInt;
	}
	break;

    case TCL_LINK_USHORT:
	if (linkPtr->flags & LINK_ALLOC_LAST) {
	    for (i=0; i < objc; i++) {
		if (GetInt(objv[i], &valueInt)
		        || !InRange(0, valueInt, USHRT_MAX)) {
			|| !InRange(0, valueInt, (int)USHRT_MAX)) {
		    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			    ObjValue(linkPtr), TCL_GLOBAL_ONLY);
	            return (char *)
		    return (char *)
			"variable array must have unsigned short value";
		}
		linkPtr->lastValue.usPtr[i] = (unsigned short) valueInt;
	    }
	} else {
	    if (GetInt(valueObj, &valueInt)
		    || !InRange(0, valueInt, USHRT_MAX)) {
		    || !InRange(0, valueInt, (int)USHRT_MAX)) {
		Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			ObjValue(linkPtr), TCL_GLOBAL_ONLY);
		return (char *) "variable must have unsigned short value";
	    }
	    LinkedVar(unsigned short) = linkPtr->lastValue.us =
		    (unsigned short) valueInt;
	}
	break;

    case TCL_LINK_UINT:
	if (linkPtr->flags & LINK_ALLOC_LAST) {
	    for (i=0; i < objc; i++) {
		if (GetWide(objv[i], &valueWide)
			|| !InRange(0, valueWide, UINT_MAX)) {
			|| !InRange(0, valueWide, (Tcl_WideInt)UINT_MAX)) {
		    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			    ObjValue(linkPtr), TCL_GLOBAL_ONLY);
	            return (char *)
		    return (char *)
			    "variable array must have unsigned int value";
		}
		linkPtr->lastValue.uiPtr[i] = (unsigned int) valueWide;
	    }
	} else {
	    if (GetWide(valueObj, &valueWide)
		    || !InRange(0, valueWide, UINT_MAX)) {
		    || !InRange(0, valueWide, (Tcl_WideInt)UINT_MAX)) {
		Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			ObjValue(linkPtr), TCL_GLOBAL_ONLY);
		return (char *) "variable must have unsigned int value";
	    }
	    LinkedVar(unsigned int) = linkPtr->lastValue.ui =
		    (unsigned int) valueWide;
	}
	break;

#if !defined(TCL_WIDE_INT_IS_LONG) && !defined(_WIN32) && !defined(__CYGWIN__)
    case TCL_LINK_LONG:
	if (linkPtr->flags & LINK_ALLOC_LAST) {
	    for (i=0; i < objc; i++) {
		if (GetWide(objv[i], &valueWide)
			|| !InRange(LONG_MIN, valueWide, LONG_MAX)) {
		    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			    ObjValue(linkPtr), TCL_GLOBAL_ONLY);
	            return (char *) "variable array must have long value";
		}
		linkPtr->lastValue.lPtr[i] = (long) valueWide;
	    }
	} else {
	    if (GetWide(valueObj, &valueWide)
		    || !InRange(LONG_MIN, valueWide, LONG_MAX)) {
		Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			ObjValue(linkPtr), TCL_GLOBAL_ONLY);
		return (char *) "variable must have long value";
	    }
	    LinkedVar(long) = linkPtr->lastValue.l = (long) valueWide;
	}
	break;

    case TCL_LINK_ULONG:
	if (linkPtr->flags & LINK_ALLOC_LAST) {
	    for (i=0; i < objc; i++) {
		if (GetUWide(objv[i], &valueUWide)
			|| (valueUWide > ULONG_MAX)) {
		    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			    ObjValue(linkPtr), TCL_GLOBAL_ONLY);
	            return (char *)
			    "variable array must have unsigned long value";
		}
		linkPtr->lastValue.ulPtr[i] = (unsigned long) valueUWide;
	    }
	} else {
	    if (GetUWide(valueObj, &valueUWide)
		    || (valueUWide > ULONG_MAX)) {
		Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			ObjValue(linkPtr), TCL_GLOBAL_ONLY);
		return (char *) "variable must have unsigned long value";
	    }
	    LinkedVar(unsigned long) = linkPtr->lastValue.ul =
		    (unsigned long) valueUWide;
	}
	break;
#endif

    case TCL_LINK_WIDE_UINT:
	if (linkPtr->flags & LINK_ALLOC_LAST) {
	    for (i=0; i < objc; i++) {
		if (GetUWide(objv[i], &valueUWide)) {
		    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			    ObjValue(linkPtr), TCL_GLOBAL_ONLY);
	            return (char *)
		    return (char *)
			    "variable array must have unsigned wide int value";
		}
		linkPtr->lastValue.uwPtr[i] = valueUWide;
	    }
	} else {
	    if (GetUWide(valueObj, &valueUWide)) {
		Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			ObjValue(linkPtr), TCL_GLOBAL_ONLY);
		return (char *) "variable must have unsigned wide int value";
	    }
	    LinkedVar(Tcl_WideUInt) = linkPtr->lastValue.uw = valueUWide;
	}
	break;

    case TCL_LINK_FLOAT:
	if (linkPtr->flags & LINK_ALLOC_LAST) {
	    for (i=0; i < objc; i++) {
		if (GetDouble(objv[i], &valueDouble)
			&& !InRange(FLT_MIN, fabs(valueDouble), FLT_MAX)
		        && !IsSpecial(valueDouble)) {
			&& !IsSpecial(valueDouble)) {
		    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			    ObjValue(linkPtr), TCL_GLOBAL_ONLY);
	            return (char *) "variable array must have float value";
		    return (char *)"variable array must have float value";
		}
		linkPtr->lastValue.fPtr[i] = (float) valueDouble;
	    }
	} else {
	    if (GetDouble(valueObj, &valueDouble)
		    && !InRange(FLT_MIN, fabs(valueDouble), FLT_MAX)
		    && !IsSpecial(valueDouble)) {
		Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			ObjValue(linkPtr), TCL_GLOBAL_ONLY);
		return (char *) "variable must have float value";
		return (char *)"variable must have float value";
	    }
	    LinkedVar(float) = linkPtr->lastValue.f = (float) valueDouble;
	}
	break;

    default:
	return (char *) "internal error: bad linked variable type";
1284
1285
1286
1287
1288
1289
1290
1291

1292
1293
1294
1295
1296
1297
1298
1164
1165
1166
1167
1168
1169
1170

1171
1172
1173
1174
1175
1176
1177
1178







-
+








static Tcl_Obj *
ObjValue(
    Link *linkPtr)		/* Structure describing linked variable. */
{
    char *p;
    Tcl_Obj *resultObj, **objv;
    size_t i;
    Tcl_Size i;

    switch (linkPtr->type) {
    case TCL_LINK_INT:
	if (linkPtr->flags & LINK_ALLOC_LAST) {
	    memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
	    objv = (Tcl_Obj **)Tcl_Alloc(linkPtr->numElems * sizeof(Tcl_Obj *));
	    for (i=0; i < linkPtr->numElems; i++) {
1318
1319
1320
1321
1322
1323
1324
1325

1326
1327
1328
1329
1330
1331
1332
1198
1199
1200
1201
1202
1203
1204

1205
1206
1207
1208
1209
1210
1211
1212







-
+







	linkPtr->lastValue.w = LinkedVar(Tcl_WideInt);
	return Tcl_NewWideIntObj(linkPtr->lastValue.w);
    case TCL_LINK_DOUBLE:
	if (linkPtr->flags & LINK_ALLOC_LAST) {
	    memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
	    objv = (Tcl_Obj **)Tcl_Alloc(linkPtr->numElems * sizeof(Tcl_Obj *));
	    for (i=0; i < linkPtr->numElems; i++) {
		objv[i] = Tcl_NewDoubleObj(linkPtr->lastValue.dPtr[i]);
		TclNewDoubleObj(objv[i], linkPtr->lastValue.dPtr[i]);
	    }
	    resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
	    Tcl_Free(objv);
	    return resultObj;
	}
	linkPtr->lastValue.d = LinkedVar(double);
	return Tcl_NewDoubleObj(linkPtr->lastValue.d);
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444

1445
1446
1447
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-





-
+







-
+




-
-
+






+
-
+
+
+







	    }
	    resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
	    Tcl_Free(objv);
	    return resultObj;
	}
	linkPtr->lastValue.ui = LinkedVar(unsigned int);
	return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.ui);
#if !defined(TCL_WIDE_INT_IS_LONG) && !defined(_WIN32) && !defined(__CYGWIN__)
    case TCL_LINK_LONG:
	if (linkPtr->flags & LINK_ALLOC_LAST) {
	    memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
	    objv = (Tcl_Obj **)Tcl_Alloc(linkPtr->numElems * sizeof(Tcl_Obj *));
	    for (i=0; i < linkPtr->numElems; i++) {
		TclNewIntObj(objv[i], linkPtr->lastValue.lPtr[i]);
	    }
	    resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
	    Tcl_Free(objv);
	    return resultObj;
	}
	linkPtr->lastValue.l = LinkedVar(long);
	return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.l);
    case TCL_LINK_ULONG:
	if (linkPtr->flags & LINK_ALLOC_LAST) {
	    memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
	    objv = (Tcl_Obj **)Tcl_Alloc(linkPtr->numElems * sizeof(Tcl_Obj *));
	    for (i=0; i < linkPtr->numElems; i++) {
		TclNewIntObj(objv[i], linkPtr->lastValue.ulPtr[i]);
	    }
	    resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
	    Tcl_Free(objv);
	    return resultObj;
	}
	linkPtr->lastValue.ul = LinkedVar(unsigned long);
	return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.ul);
#endif
    case TCL_LINK_FLOAT:
	if (linkPtr->flags & LINK_ALLOC_LAST) {
	    memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
	    objv = (Tcl_Obj **)Tcl_Alloc(linkPtr->numElems * sizeof(Tcl_Obj *));
	    for (i=0; i < linkPtr->numElems; i++) {
		objv[i] = Tcl_NewDoubleObj(linkPtr->lastValue.fPtr[i]);
		TclNewDoubleObj(objv[i], linkPtr->lastValue.fPtr[i]);
	    }
	    resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
	    Tcl_Free(objv);
	    return resultObj;
	}
	linkPtr->lastValue.f = LinkedVar(float);
	return Tcl_NewDoubleObj(linkPtr->lastValue.f);
    case TCL_LINK_WIDE_UINT:
    case TCL_LINK_WIDE_UINT: {
	if (linkPtr->flags & LINK_ALLOC_LAST) {
	    memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
	    objv = (Tcl_Obj **)Tcl_Alloc(linkPtr->numElems * sizeof(Tcl_Obj *));
	    for (i=0; i < linkPtr->numElems; i++) {
		TclNewIntObj(objv[i], (Tcl_WideInt)
			linkPtr->lastValue.uwPtr[i]);
		TclNewUIntObj(objv[i], linkPtr->lastValue.uwPtr[i]);
	    }
	    resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
	    Tcl_Free(objv);
	    return resultObj;
	}
	linkPtr->lastValue.uw = LinkedVar(Tcl_WideUInt);
	Tcl_Obj *uwObj;
	return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.uw);
	TclNewUIntObj(uwObj, linkPtr->lastValue.uw);
	return uwObj;
	}

    case TCL_LINK_STRING:
	p = LinkedVar(char *);
	if (p == NULL) {
	    TclNewLiteralStringObj(resultObj, "NULL");
	    return resultObj;
	}

Changes to generic/tclListObj.c.

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
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
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
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
467
468
469







470
471
472


473
474
475

476
477
478
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
558
559
560
561
562
563
564
565


566
567

568
569

570
571
572
573

574
575
576

577
578

579
580

581
582
583
584




585
586
587
588
589
590
591
592
593
594


595
596

597
598
599

600
601
602
603
604
605
606
607

608
609
610
611
612
613
614
615


616































































































































































617
618
619
620
621
622
623
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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715

716
717


718
719



720
721
722
723

724
725
726



727
728
729
730
731

732



733
734
735
736
737




738
739
740
741

742
743


744
745



746
747
748

749


750




751
752
753

754
755
756
757
758
759
760
761
762
763
764
765




766
767
768
769
770
771
772
773
774
775
776




777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797




798






799
800
801
802
803

804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837



838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933



934
935
936


937
938
939
940

941
942

943
944

945


946



947
948

949
950
951
952
953
954
955
956
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
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

1116
1117
1118
1119
1120




1121
1122
1123
1124
1125

1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145

1146
1147
1148
1149
1150
1151
1152


1153
1154
1155

1156
1157
1158

1159
1160
1161




1162


1163



1164




1165
1166
1167
1168
1169
1170
1171

1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354

1355
1356
1357

1358

1359



1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899





-
-
-
+





+

-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+
-
-
-
-
-
-







-
+
+



+
+
+
+
+
+
+

+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+

-
-
+
+
-
-
-
+
+

+
-
+
+

-
-
-
+
+
+
+

-
+
-
-
-
+
+



-
-
-
-
+
+
+

-
+

-
-
+
+
-
-
-



-
+
-
-

-
-
-
-
+
+
+
-




+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+





-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
-
-
-
-
-
+
+
+
+

-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
-
+
+

-
-
+
+
+

-
+

-
+

-
+
-
-

-
-
-
+

-

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







+
-
+
-
+
+

-
+
+

+
-
-
-
-
+
+
+
+

-
+
-
-
-
+
+









-
+









-
+


-
-
+
+

-
+


-
+


-
-
-
-
+
-
-
+
-
-
-

-
-
-
+






-
+

+
+
+
-
-
-
-
+
+
+
+

-
+
+
+
+
+
+
+
+
+
+
+
+








-
+






-
-
+
+

-
+


-
+


-
-
-
-
+
-
-
+
-
-
-

-
-
-
-
+






-
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
-
+
+
+
+
+
+
+
+
+
+
+
+
+



-



-
+


-
-




-
-
-
-
-
-
-



-
+
+



+
+
-
-
+
+

+
+









-
-
-
+
+
+

-
-
-
-
-
+
+
+
+
+
-

-
-
+
+
-







-
+


-
+
-

-
-
-
+
+
+
+
+




-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
+




+
+










+
-
-
-
+
+
+

-
-
+
-
-
+

+
-
-
+
+
-
-

-
-
-
+
-
-
+
-
-
-
-
+
+
-

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+

-
-
+
-
-
-
-
-
+
-
-
-
+
-
-
+
-
-
-
-
+
+
+







-
-
+
+
-

-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
+
-
-
+
+




+



-
+

-
+




-
+

-
-
+
+
-
-
-
-
-
+
+
-
-
-
-
-
+
+
-
-
-
-
-
-
-
+
-








-
+
+

-
+
-
-
+
-
-
-
-
+
-
-
-
+

-
+
-
-
+
-
-
-
-
+
+
+
+
-



-



-
-
+
+

-
+


-
+



-
-
-
-
-
+








+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







/*
 * tclListObj.c --
 *
 *	This file contains functions that implement the Tcl list object type.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998 by Scriptics Corporation.
 * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
 * Copyright © 2022 Ashok P. Nadkarni.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include <assert.h>
#include "tclInt.h"
#include <assert.h>
#include "tclTomMath.h"

/*
 * TODO - memmove is fast. Measure at what size we should prefer memmove
 * (for unshared objects only) in lieu of range operations. On the other
 * hand, more cache dirtied?
 */

/*
 * Macros for validation and bug checking.
 */

/*
 * Control whether asserts are enabled. Always enable in debug builds. In non-debug
 * builds, can be set with cdebug="-DENABLE_LIST_ASSERTS" on the nmake command line.
 */
#ifdef ENABLE_LIST_ASSERTS
# ifdef NDEBUG
#  undef NDEBUG /* Activate assert() macro */
# endif
#else
# ifndef NDEBUG
#  define ENABLE_LIST_ASSERTS /* Always activate list asserts in debug mode */
# endif
#endif

#ifdef ENABLE_LIST_ASSERTS

#define LIST_ASSERT(cond_) assert(cond_)
/*
 * LIST_INDEX_ASSERT is to catch errors with negative indices and counts
 * being passed AFTER validation. On Tcl9 length types are unsigned hence
 * the checks against LIST_MAX. On Tcl8 length types are signed hence the
 * also checks against 0.
 */
#define LIST_INDEX_ASSERT(idxarg_)                                 \
    do {                                                           \
	Tcl_Size idx_ = (idxarg_); /* To guard against ++ etc. */ \
	LIST_ASSERT(idx_ >= 0 && idx_ < LIST_MAX);                 \
    } while (0)
/* Ditto for counts except upper limit is different */
#define LIST_COUNT_ASSERT(countarg_)                                   \
    do {                                                               \
	Tcl_Size count_ = (countarg_); /* To guard against ++ etc. */ \
	LIST_ASSERT(count_ >= 0 && count_ <= LIST_MAX);                \
    } while (0)

#else

#define LIST_ASSERT(cond_) ((void) 0)
#define LIST_INDEX_ASSERT(idx_) ((void) 0)
#define LIST_COUNT_ASSERT(count_) ((void) 0)

#endif

/* Checks for when caller should have already converted to internal list type */
#define LIST_ASSERT_TYPE(listObj_) \
    LIST_ASSERT(TclHasInternalRep((listObj_), &tclListType))

/*
 * If ENABLE_LIST_INVARIANTS is enabled (-DENABLE_LIST_INVARIANTS from the
 * command line), the entire list internal representation is checked for
 * inconsistencies. This has a non-trivial cost so has to be separately
 * enabled and not part of assertions checking. However, the test suite does
 * invoke ListRepValidate directly even without ENABLE_LIST_INVARIANTS.
 */
#ifdef ENABLE_LIST_INVARIANTS
#define LISTREP_CHECK(listRepPtr_) ListRepValidate(listRepPtr_, __FILE__, __LINE__)
#else
#define LISTREP_CHECK(listRepPtr_) (void) 0
#endif

/*
 * Flags used for controlling behavior of allocation of list
 * internal representations.
 *
 * If the LISTREP_PANIC_ON_FAIL bit is set, the function will panic if
 * list is too large or memory cannot be allocated. Without the flag
 * a NULL pointer is returned.
 *
 * The LISTREP_SPACE_FAVOR_NONE, LISTREP_SPACE_FAVOR_FRONT,
 * LISTREP_SPACE_FAVOR_BACK, LISTREP_SPACE_ONLY_BACK flags are used to
 * control additional space when allocating.
 * - If none of these flags is present, the exact space requested is
 *   allocated, nothing more.
 * - Otherwise, if only LISTREP_FAVOR_FRONT is present, extra space is
 *   allocated with more towards the front.
 * - Conversely, if only LISTREP_FAVOR_BACK is present extra space is allocated
 *   with more to the back.
 * - If both flags are present (LISTREP_SPACE_FAVOR_NONE), the extra space
 *   is equally apportioned.
 * - Finally if LISTREP_SPACE_ONLY_BACK is present, ALL extra space is at
 *   the back.
 */
#define LISTREP_PANIC_ON_FAIL         0x00000001
#define LISTREP_SPACE_FAVOR_FRONT     0x00000002
#define LISTREP_SPACE_FAVOR_BACK      0x00000004
#define LISTREP_SPACE_ONLY_BACK       0x00000008
#define LISTREP_SPACE_FAVOR_NONE \
    (LISTREP_SPACE_FAVOR_FRONT | LISTREP_SPACE_FAVOR_BACK)
#define LISTREP_SPACE_FLAGS                               \
    (LISTREP_SPACE_FAVOR_FRONT | LISTREP_SPACE_FAVOR_BACK \
     | LISTREP_SPACE_ONLY_BACK)

/*
 * Prototypes for functions defined later in this file:
 * Prototypes for non-inline static functions defined later in this file:
 */

static List *		AttemptNewList(Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static List *		NewListIntRep(int objc, Tcl_Obj *const objv[], int p);
static void		DupListInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
static void		FreeListInternalRep(Tcl_Obj *listPtr);
static int		SetListFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
static void		UpdateStringOfList(Tcl_Obj *listPtr);
static int	MemoryAllocationError(Tcl_Interp *, size_t size);
static int	ListLimitExceededError(Tcl_Interp *);
static ListStore *ListStoreNew(Tcl_Size objc, Tcl_Obj *const objv[], int flags);
static int	ListRepInit(Tcl_Size objc, Tcl_Obj *const objv[], int flags, ListRep *);
static int	ListRepInitAttempt(Tcl_Interp *,
		    Tcl_Size objc,
		    Tcl_Obj *const objv[],
		    ListRep *);
static void	ListRepClone(ListRep *fromRepPtr, ListRep *toRepPtr, int flags);
static void	ListRepUnsharedFreeUnreferenced(const ListRep *repPtr);
static int	TclListObjGetRep(Tcl_Interp *, Tcl_Obj *listPtr, ListRep *repPtr);
static void	ListRepRange(ListRep *srcRepPtr,
		    Tcl_Size rangeStart,
		    Tcl_Size rangeEnd,
		    int preserveSrcRep,
		    ListRep *rangeRepPtr);
static ListStore *ListStoreReallocate(ListStore *storePtr, Tcl_Size numSlots);
static void	ListRepValidate(const ListRep *repPtr, const char *file,
		    int lineNum);
static void	DupListInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
static void	FreeListInternalRep(Tcl_Obj *listPtr);
static int	SetListFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
static void	UpdateStringOfList(Tcl_Obj *listPtr);
static Tcl_Size ListLength(Tcl_Obj *listPtr);

/*
 * The structure below defines the list Tcl object type by means of functions
 * that can be invoked by generic object code.
 *
 * The internal representation of a list object is a two-pointer
 * The internal representation of a list object is ListRep defined in tcl.h.
 * representation. The first pointer designates a List structure that contains
 * an array of pointers to the element objects, together with integers that
 * represent the current element count and the allocated size of the array.
 * The second pointer is normally NULL; during execution of functions in this
 * file that operate on nested sublists, it is occasionally used as working
 * storage to avoid an auxiliary stack.
 */

const Tcl_ObjType tclListType = {
    "list",			/* name */
    FreeListInternalRep,	/* freeIntRepProc */
    DupListInternalRep,		/* dupIntRepProc */
    UpdateStringOfList,		/* updateStringProc */
    SetListFromAny		/* setFromAnyProc */
    SetListFromAny,		/* setFromAnyProc */
    TCL_OBJTYPE_V1(ListLength)
};

/* Macros to manipulate the List internal rep */
#define ListRepIncrRefs(repPtr_) \
    do {					\
	(repPtr_)->storePtr->refCount++;	\
	if ((repPtr_)->spanPtr) {		\
	    (repPtr_)->spanPtr->refCount++;	\
	}					\
    } while (0)

/* Returns number of free unused slots at the back of the ListRep's ListStore */
#define ListRepNumFreeTail(repPtr_) \
    ((repPtr_)->storePtr->numAllocated \
     - ((repPtr_)->storePtr->firstUsed + (repPtr_)->storePtr->numUsed))
#define ListSetIntRep(objPtr, listRepPtr)				\
    do {								\
	Tcl_ObjIntRep ir;						\
	ir.twoPtrValue.ptr1 = (listRepPtr);				\
	ir.twoPtrValue.ptr2 = NULL;					\
	(listRepPtr)->refCount++;					\
	Tcl_StoreIntRep((objPtr), &tclListType, &ir);			\
    } while (0)

#define ListGetIntRep(objPtr, listRepPtr)				\
    do {								\
	const Tcl_ObjIntRep *irPtr;					\
	irPtr = TclFetchIntRep((objPtr), &tclListType);		\
	(listRepPtr) = irPtr ? (List *)irPtr->twoPtrValue.ptr1 : NULL;		\
    } while (0)

#define ListResetIntRep(objPtr, listRepPtr) \
    TclFetchIntRep((objPtr), &tclListType)->twoPtrValue.ptr1 = (listRepPtr)

/* Returns number of free unused slots at the front of the ListRep's ListStore */
#define ListRepNumFreeHead(repPtr_) ((repPtr_)->storePtr->firstUsed)

/* Returns a pointer to the slot corresponding to list index listIdx_ */
#define ListRepSlotPtr(repPtr_, listIdx_) \
    (&(repPtr_)->storePtr->slots[ListRepStart(repPtr_) + (listIdx_)])

/*
 * Macros to replace the internal representation in a Tcl_Obj. There are
 * subtle differences in each so make sure to use the right one to avoid
 * memory leaks, access to freed memory and the like.
 *
 * ListObjStompRep - assumes the Tcl_Obj internal representation can be
 * overwritten AND that the passed ListRep already has reference counts that
 * include the reference from the Tcl_Obj. Basically just copies the pointers
 * and sets the internal Tcl_Obj type to list
 *
 * ListObjOverwriteRep - like ListObjOverwriteRep but additionally
 * increments reference counts on the passed ListRep. Generally used when
 * the string representation of the Tcl_Obj is not to be modified.
 *
 * ListObjReplaceRepAndInvalidate - Like ListObjOverwriteRep but additionally
 * assumes the Tcl_Obj internal rep is valid (and possibly even same as
 * passed ListRep) and frees it first. Additionally invalidates the string
 * representation. Generally used when modifying a Tcl_Obj value.
 */
#define ListObjStompRep(objPtr_, repPtr_)                              \
    do {                                                               \
	(objPtr_)->internalRep.twoPtrValue.ptr1 = (repPtr_)->storePtr; \
	(objPtr_)->internalRep.twoPtrValue.ptr2 = (repPtr_)->spanPtr;  \
	(objPtr_)->typePtr = &tclListType;                             \
    } while (0)

#define ListObjOverwriteRep(objPtr_, repPtr_) \
    do {                                      \
	ListRepIncrRefs(repPtr_);             \
	ListObjStompRep(objPtr_, repPtr_);    \
    } while (0)

#define ListObjReplaceRepAndInvalidate(objPtr_, repPtr_)           \
    do {                                                           \
	/* Note order important, don't use ListObjOverwriteRep! */ \
	ListRepIncrRefs(repPtr_);                                  \
	TclFreeInternalRep(objPtr_);                               \
	TclInvalidateStringRep(objPtr_);                           \
	ListObjStompRep(objPtr_, repPtr_);                         \
    } while (0)

/*
 *------------------------------------------------------------------------
 *
 * ListSpanNew --
 *
 *    Allocates and initializes memory for a new ListSpan. The reference
 *    count on the returned struct is 0.
 *
 * Results:
 *    Non-NULL pointer to the allocated ListSpan.
 *
 * Side effects:
 *    The function will panic on memory allocation failure.
 *
 *------------------------------------------------------------------------
 */
static inline ListSpan *
ListSpanNew(
    Tcl_Size firstSlot, /* Starting slot index of the span */
    Tcl_Size numSlots)  /* Number of slots covered by the span */
{
    ListSpan *spanPtr = (ListSpan *) Tcl_Alloc(sizeof(*spanPtr));
    spanPtr->refCount = 0;
    spanPtr->spanStart = firstSlot;
    spanPtr->spanLength = numSlots;
    return spanPtr;
}

/*
 *------------------------------------------------------------------------
 *
 * ListSpanDecrRefs --
 *
 *   Decrements the reference count on a span, freeing the memory if
 *   it drops to zero or less.
 *
 * Results:
 *   None.
 *
 * Side effects:
 *   The memory may be freed.
 *
 *------------------------------------------------------------------------
 */
static inline void
ListSpanDecrRefs(
    ListSpan *spanPtr)
{
    if (spanPtr->refCount <= 1) {
	Tcl_Free(spanPtr);
    } else {
	spanPtr->refCount -= 1;
    }
}

/*
 *------------------------------------------------------------------------
 *
 * ListSpanMerited --
 *
 *    Creation of a new list may sometimes be done as a span on existing
 *    storage instead of allocating new. The tradeoff is that if the
 *    original list is released, the new span-based list may hold on to
 *    more memory than desired. This function implements heuristics for
 *    deciding which option is better.
 *
 * Results:
 *    Returns non-0 if a span-based list is likely to be more optimal
 *    and 0 if not.
 *
 * Side effects:
 *    None.
 *
 *------------------------------------------------------------------------
 */
static inline int
ListSpanMerited(
    Tcl_Size length,                 /* Length of the proposed span */
    Tcl_Size usedStorageLength,      /* Number of slots currently in used */
    Tcl_Size allocatedStorageLength) /* Length of the currently allocation */
{
    /*
     * Possible optimizations for future consideration
     * - heuristic LIST_SPAN_THRESHOLD
     * - currently, information about the sharing (ref count) of existing
     * storage is not passed. Perhaps it should be. For example if the
     * existing storage has a "large" ref count, then it might make sense
     * to do even a small span.
     */

    if (length < LIST_SPAN_THRESHOLD) {
	return 0;/* No span for small lists */
    }
    if (length < (allocatedStorageLength / 2 - allocatedStorageLength / 8)) {
	return 0; /* No span if less than 3/8 of allocation */
    }
    if (length < usedStorageLength / 2) {
	return 0; /* No span if less than half current storage */
    }

    return 1;
}

/*
 *------------------------------------------------------------------------
 *
 * ListRepFreeUnreferenced --
 *
 *    Inline wrapper for ListRepUnsharedFreeUnreferenced that does quick checks
 *    before calling it.
 *
 *    IMPORTANT: this function must not be called on an internal
 *    representation of a Tcl_Obj that is itself shared.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    See comments for ListRepUnsharedFreeUnreferenced.
 *
 *------------------------------------------------------------------------
 */
static inline void
ListRepFreeUnreferenced(
    const ListRep *repPtr)
{
    if (! ListRepIsShared(repPtr) && repPtr->spanPtr) {
	/* T:listrep-1.5.1 */
	ListRepUnsharedFreeUnreferenced(repPtr);
    }
}

/*
 *------------------------------------------------------------------------
 *
 * ObjArrayIncrRefs --
 *
 *    Increments the reference counts for Tcl_Obj's in a subarray.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    As above.
 *
 *------------------------------------------------------------------------
 */
static inline void
ObjArrayIncrRefs(
    Tcl_Obj * const *objv,  /* Pointer to the array */
    Tcl_Size startIdx,     /* Starting index of subarray within objv */
    Tcl_Size count)        /* Number of elements in the subarray */
{
    Tcl_Obj *const *end;
    LIST_INDEX_ASSERT(startIdx);
    LIST_COUNT_ASSERT(count);
    objv += startIdx;
    end = objv + count;
    while (objv < end) {
	Tcl_IncrRefCount(*objv);
	++objv;
    }
}

/*
 *------------------------------------------------------------------------
 *
 * ObjArrayDecrRefs --
 *
 *    Decrements the reference counts for Tcl_Obj's in a subarray.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    As above.
 *
 *------------------------------------------------------------------------
 */
static inline void
ObjArrayDecrRefs(
    Tcl_Obj * const *objv, /* Pointer to the array */
    Tcl_Size startIdx,    /* Starting index of subarray within objv */
    Tcl_Size count)       /* Number of elements in the subarray */
{
    Tcl_Obj * const *end;
    LIST_INDEX_ASSERT(startIdx);
    LIST_COUNT_ASSERT(count);
    objv += startIdx;
    end = objv + count;
    while (objv < end) {
	Tcl_DecrRefCount(*objv);
	++objv;
    }
}

/*
 *------------------------------------------------------------------------
 *
 * ObjArrayCopy --
 *
 *    Copies an array of Tcl_Obj* pointers.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Reference counts on copied Tcl_Obj's are incremented.
 *
 *------------------------------------------------------------------------
 */
static inline void
ObjArrayCopy(
    Tcl_Obj **to,          /* Destination */
    Tcl_Size count,       /* Number of pointers to copy */
    Tcl_Obj *const from[]) /* Source array of Tcl_Obj* */
{
    Tcl_Obj **end;
    LIST_COUNT_ASSERT(count);
    end = to + count;
    /* TODO - would memmove followed by separate IncrRef loop be faster? */
    while (to < end) {
	Tcl_IncrRefCount(*from);
	*to++ = *from++;
    }
}

/*
 *------------------------------------------------------------------------
 *
 * MemoryAllocationError --
 *
 *    Generates a memory allocation failure error.
 *
 * Results:
 *    Always TCL_ERROR.
 *
 * Side effects:
 *    Error message and code are stored in the interpreter if not NULL.
 *
 *------------------------------------------------------------------------
 */
static int
MemoryAllocationError(
    Tcl_Interp *interp, /* Interpreter for error message. May be NULL */
    size_t size)        /* Size of attempted allocation that failed */
{
    if (interp != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"list construction failed: unable to alloc %" TCL_Z_MODIFIER
		"u bytes",
		size));
	Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
    }
    return TCL_ERROR;
}

/*
 *------------------------------------------------------------------------
 *
 * ListLimitExceeded --
 *
 *    Generates an error for exceeding maximum list size.
 *
 * Results:
 *    Always TCL_ERROR.
 *
 * Side effects:
 *    Error message and code are stored in the interpreter if not NULL.
 *
 *------------------------------------------------------------------------
 */
static int
ListLimitExceededError(
    Tcl_Interp *interp)
{
    if (interp != NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"max length of a Tcl list exceeded", -1));
	Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
    }
    return TCL_ERROR;
}

/*
 *------------------------------------------------------------------------
 *
 * ListRepUnsharedShiftDown --
 *
 *    Shifts the "in-use" contents in the ListStore for a ListRep down
 *    by the given number of slots. The ListStore must be unshared and
 *    the free space at the front of the storage area must be big enough.
 *    It is the caller's responsibility to check.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    The contents of the ListRep's ListStore area are shifted down in the
 *    storage area. The ListRep's ListSpan is updated accordingly.
 *
 *------------------------------------------------------------------------
 */
static inline void
ListRepUnsharedShiftDown(
    ListRep *repPtr,
    Tcl_Size shiftCount)
{
    ListStore *storePtr;

    LISTREP_CHECK(repPtr);
    LIST_ASSERT(!ListRepIsShared(repPtr));

    storePtr = repPtr->storePtr;
#ifndef TCL_MIN_ELEMENT_GROWTH
#define TCL_MIN_ELEMENT_GROWTH TCL_MIN_GROWTH/sizeof(Tcl_Obj *)

    LIST_COUNT_ASSERT(shiftCount);
    LIST_ASSERT(storePtr->firstUsed >= shiftCount);

    memmove(&storePtr->slots[storePtr->firstUsed - shiftCount],
	    &storePtr->slots[storePtr->firstUsed],
	    storePtr->numUsed * sizeof(Tcl_Obj *));
    storePtr->firstUsed -= shiftCount;
    if (repPtr->spanPtr) {
	repPtr->spanPtr->spanStart -= shiftCount;
	LIST_ASSERT(repPtr->spanPtr->spanLength == storePtr->numUsed);
    } else {
	/*
	 * If there was no span, firstUsed must have been 0 (Invariant)
	 * AND shiftCount must have been 0 (<= firstUsed on call)
	 * In other words, this would have been a no-op
	 */

	LIST_ASSERT(storePtr->firstUsed == 0);
	LIST_ASSERT(shiftCount == 0);
    }

    LISTREP_CHECK(repPtr);
}

/*
 *------------------------------------------------------------------------
 *
 * ListRepUnsharedShiftUp --
 *
 *    Shifts the "in-use" contents in the ListStore for a ListRep up
 *    by the given number of slots. The ListStore must be unshared and
 *    the free space at the back of the storage area must be big enough.
 *    It is the caller's responsibility to check.
 *    TODO - this function is not currently used.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    The contents of the ListRep's ListStore area are shifted up in the
 *    storage area. The ListRep's ListSpan is updated accordingly.
 *
 *------------------------------------------------------------------------
 */
#if 0
static inline void
ListRepUnsharedShiftUp(
    ListRep *repPtr,
    Tcl_Size shiftCount)
{
    ListStore *storePtr;

    LISTREP_CHECK(repPtr);
    LIST_ASSERT(!ListRepIsShared(repPtr));
    LIST_COUNT_ASSERT(shiftCount);

    storePtr = repPtr->storePtr;
    LIST_ASSERT((storePtr->firstUsed + storePtr->numUsed + shiftCount)
		<= storePtr->numAllocated);

    memmove(&storePtr->slots[storePtr->firstUsed + shiftCount],
	    &storePtr->slots[storePtr->firstUsed],
	    storePtr->numUsed * sizeof(Tcl_Obj *));
    storePtr->firstUsed += shiftCount;
    if (repPtr->spanPtr) {
	repPtr->spanPtr->spanStart += shiftCount;
    } else {
	/* No span means entire original list is span */
	/* Should have been zero before shift - Invariant TBD */
	LIST_ASSERT(storePtr->firstUsed == shiftCount);
	repPtr->spanPtr = ListSpanNew(shiftCount, storePtr->numUsed);
    }

    LISTREP_CHECK(repPtr);
}
#endif

/*
 *------------------------------------------------------------------------
 *
 * ListRepValidate --
 *
 *	Checks all invariants for a ListRep and panics on failure.
 *	Note this is independent of NDEBUG, assert etc.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Panics if any invariant is not met.
 *
 *------------------------------------------------------------------------
 */
static void
ListRepValidate(
    const ListRep *repPtr,
    const char *file,
    int lineNum)
{
    ListStore *storePtr = repPtr->storePtr;
    const char *condition;

    (void)storePtr; /* To stop gcc from whining about unused vars */

#define INVARIANT(cond_)        \
    do {                        \
	if (!(cond_)) {         \
	    condition = #cond_; \
	    goto failure;       \
	}                       \
    } while (0)

    /* Separate each condition so line number gives exact reason for failure */
    INVARIANT(storePtr != NULL);
    INVARIANT(storePtr->numAllocated >= 0);
    INVARIANT(storePtr->numAllocated <= LIST_MAX);
    INVARIANT(storePtr->firstUsed >= 0);
    INVARIANT(storePtr->firstUsed < storePtr->numAllocated);
    INVARIANT(storePtr->numUsed >= 0);
    INVARIANT(storePtr->numUsed <= storePtr->numAllocated);
    INVARIANT(storePtr->firstUsed <= (storePtr->numAllocated - storePtr->numUsed));

    if (! ListRepIsShared(repPtr)) {
	/*
	 * If this is the only reference and there is no span, then store
	 * occupancy must begin at 0
	 */
	INVARIANT(repPtr->spanPtr || repPtr->storePtr->firstUsed == 0);
    }

    INVARIANT(ListRepStart(repPtr) >= storePtr->firstUsed);
    INVARIANT(ListRepLength(repPtr) <= storePtr->numUsed);
    INVARIANT(ListRepStart(repPtr) <= (storePtr->firstUsed + storePtr->numUsed - ListRepLength(repPtr)));

#undef INVARIANT

    return;

failure:
    Tcl_Panic("List internal failure in %s line %d. Condition: %s",
	      file,
	      lineNum,
	      condition);
}

/*
 *------------------------------------------------------------------------
 *
 * TclListObjValidate --
 *
 *    Wrapper around ListRepValidate. Primarily used from test suite.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Will panic if internal structure is not consistent or if object
 *    cannot be converted to a list object.
 *
 *------------------------------------------------------------------------
 */
void
TclListObjValidate(
    Tcl_Interp *interp,
    Tcl_Obj *listObj)
{
    ListRep listRep;
    if (TclListObjGetRep(interp, listObj, &listRep) != TCL_OK) {
	Tcl_Panic("Object passed to TclListObjValidate cannot be converted to "
		  "a list object.");
    }
    ListRepValidate(&listRep, __FILE__, __LINE__);
}

/*
 *----------------------------------------------------------------------
 *
 * NewListIntRep --
 * ListStoreNew --
 *
 *	Creates a 'List' structure with space for 'objc' elements.  'objc' must
 *	be > 0.  If 'objv' is not NULL, The list is initialized with first
 *	Allocates a new ListStore with space for at least objc elements. objc
 *	must be > 0.  If objv!=NULL, initializes with the first objc values
 *	'objc' values in that array.  Otherwise the list is initialized to have
 *	0 elements, with space to add 'objc' more.  Flag value 'p' indicates
 *	how to behave on failure.
 *	in that array.  If objv==NULL, initalize 0 elements, with space
 *	to add objc more.
 *
 *      Normally the function allocates the exact space requested unless
 * Value
 *      the flags arguments has any LISTREP_SPACE_*
 *      bits set. See the comments for those #defines.
 *
 *	A new 'List' structure with refCount 0. If some failure
 *	prevents this NULL is returned if 'p' is 0 , and 'Tcl_Panic'
 *	is called if it is not.
 * Results:
 *      On success, a pointer to the allocated ListStore is returned.
 *      On allocation failure, panics if LISTREP_PANIC_ON_FAIL is set in
 *      flags; otherwise returns NULL.
 *
 * Effect
 * Side effects:
 *
 *	The refCount of each value in 'objv' is incremented as it is added
 *	to the list.
 *	The ref counts of the elements in objv are incremented on success
 *	since the returned ListStore references them.
 *
 *----------------------------------------------------------------------
 */

static List *
NewListIntRep(
    int objc,
static ListStore *
ListStoreNew(
    Tcl_Size objc,
    Tcl_Obj *const objv[],
    int p)
    int flags)
{
    List *listRepPtr;

    ListStore *storePtr;
    Tcl_Size capacity;
    if (objc <= 0) {
	Tcl_Panic("NewListIntRep: expects postive element count");
    }

    /*
     * First check to see if we'd overflow and try to allocate an object
     * larger than our memory allocator allows. Note that this is actually a
     * larger than our memory allocator allows.
     * fairly small value when you're on a serious 64-bit machine, but that
     * requires API changes to fix. See [Bug 219196] for a discussion.
     */

    if ((size_t)objc > LIST_MAX) {
	if (p) {
	    Tcl_Panic("max length of a Tcl list (%d elements) exceeded",
    if (objc > LIST_MAX) {
	if (flags & LISTREP_PANIC_ON_FAIL) {
	    Tcl_Panic("max length of a Tcl list exceeded");
		    LIST_MAX);
	}
	return NULL;
    }

    storePtr = NULL;
    if (flags & LISTREP_SPACE_FLAGS) {
	/* Caller requests extra space front, back or both */
	storePtr = (ListStore *)TclAttemptAllocElemsEx(
	    objc, sizeof(Tcl_Obj *), offsetof(ListStore, slots), &capacity);
    } else {
	/* Exact allocation */
	capacity = objc;
    listRepPtr = (List *)Tcl_AttemptAlloc(LIST_SIZE(objc));
    if (listRepPtr == NULL) {
	if (p) {
	    Tcl_Panic("list creation failed: unable to alloc %" TCL_Z_MODIFIER "u bytes",
	storePtr = (ListStore *)Tcl_AttemptAlloc(LIST_SIZE(capacity));
    }
    if (storePtr == NULL) {
	if (flags & LISTREP_PANIC_ON_FAIL) {
	    Tcl_Panic("list creation failed: unable to alloc %" TCL_SIZE_MODIFIER
		    "d bytes",
		    LIST_SIZE(objc));
	}
	return NULL;
    }

    listRepPtr->canonicalFlag = 0;
    listRepPtr->refCount = 0;
    listRepPtr->maxElemCount = objc;

    storePtr->refCount = 0;
    storePtr->flags = 0;
    storePtr->numAllocated = capacity;
    if (capacity == objc) {
	storePtr->firstUsed = 0;
    } else {
	Tcl_Size extra = capacity - objc;
	int spaceFlags = flags & LISTREP_SPACE_FLAGS;
	if (spaceFlags == LISTREP_SPACE_ONLY_BACK) {
	    storePtr->firstUsed = 0;
	} else if (spaceFlags == LISTREP_SPACE_FAVOR_FRONT) {
	    /* Leave more space in the front */
	    storePtr->firstUsed =
		extra - (extra / 4); /* NOT same as 3*extra/4 */
	} else if (spaceFlags == LISTREP_SPACE_FAVOR_BACK) {
	    /* Leave more space in the back */
	    storePtr->firstUsed = extra / 4;
	} else {
	    /* Apportion equally */
	    storePtr->firstUsed = extra / 2;
	}
    if (objv) {
	Tcl_Obj **elemPtrs;
	int i;

    }
	listRepPtr->elemCount = objc;
	elemPtrs = &listRepPtr->elements;
	for (i = 0;  i < objc;  i++) {
	    elemPtrs[i] = objv[i];
	    Tcl_IncrRefCount(elemPtrs[i]);
	}

    if (objv) {
	storePtr->numUsed = objc;
	ObjArrayCopy(&storePtr->slots[storePtr->firstUsed], objc, objv);
    } else {
	listRepPtr->elemCount = 0;
	storePtr->numUsed = 0;
    }

    return storePtr;
}

/*
 *------------------------------------------------------------------------
 *
 * ListStoreReallocate --
 *
 *    Reallocates the memory for a ListStore allocating extra for
 *    possible future growth.
 *
 * Results:
 *    Pointer to the ListStore which may be the same as storePtr or pointer
 *    to a new block of memory. On reallocation failure, NULL is returned.
 *
 *
 * Side effects:
 *    The memory pointed to by storePtr is freed if it a new block has to
 *    be returned.
 *
 *
 *------------------------------------------------------------------------
 */
static ListStore *
ListStoreReallocate(
    ListStore *storePtr,
    Tcl_Size needed)
{
    Tcl_Size capacity;

    if (needed > LIST_MAX) {
    return listRepPtr;
}

	return NULL;
    }
    storePtr = (ListStore *) TclAttemptReallocElemsEx(storePtr,
	    needed, sizeof(Tcl_Obj *), offsetof(ListStore, slots), &capacity);
    /* Only the capacity has changed, fix it in the header */
    if (storePtr) {
	storePtr->numAllocated = capacity;
    }
    return storePtr;
}

/*
 *----------------------------------------------------------------------
 *
 * ListRepInit --
 *
 *      Initializes a ListRep to hold a list internal representation
 *      with space for objc elements.
 *
 *      objc must be > 0. If objv!=NULL, initializes with the first objc
 *      values in that array. If objv==NULL, initalize list internal rep to
 *      have 0 elements, with space to add objc more.
 *
 *	Normally the function allocates the exact space requested unless
 *	the flags arguments has one of the LISTREP_SPACE_* bits set.
 *	See the comments for those #defines.
 *
 *      The reference counts of the ListStore and ListSpan (if present)
 *	pointed to by the initialized repPtr are set to zero.
 *	Caller has to manage them as necessary.
 *
 * Results:
 *      On success, TCL_OK is returned with *listRepPtr initialized.
 *      On failure, panics if LISTREP_PANIC_ON_FAIL is set in flags; otherwise
 *	returns TCL_ERROR with *listRepPtr fields set to NULL.
 *
 * Side effects:
 *	The ref counts of the elements in objv are incremented since the
 *	resulting list now refers to them.
 *
 *----------------------------------------------------------------------
 */
static int
ListRepInit(
    Tcl_Size objc,
    Tcl_Obj *const objv[],
    int flags,
    ListRep *repPtr)
{
    ListStore *storePtr;
 *  AttemptNewList --
 *
 *	Like NewListIntRep, but additionally sets an error message on failure.

    storePtr = ListStoreNew(objc, objv, flags);
    if (storePtr) {
	repPtr->storePtr = storePtr;
	if (storePtr->firstUsed == 0) {
	    repPtr->spanPtr = NULL;
	} else {
	    repPtr->spanPtr =
		ListSpanNew(storePtr->firstUsed, storePtr->numUsed);
	}
	return TCL_OK;
    }
    /*
     * Initialize to keep gcc happy at the call site. Else it complains
     * about possibly uninitialized use.
     */
    repPtr->storePtr = NULL;
    repPtr->spanPtr = NULL;
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * ListRepInitAttempt --
 *
 *	Creates a list internal rep with space for objc elements. See
 *	ListRepInit for requirements for parameters (in particular objc must
 *	be > 0). This function only adds error messages to the interpreter if
 *	not NULL.
 *
 *      The reference counts of the ListStore and ListSpan (if present)
 *	pointed to by the initialized repPtr are set to zero.
 *	Caller has to manage them as necessary.
 *
 * Results:
 *      On success, TCL_OK is returned with *listRepPtr initialized.
 *	On allocation failure, returnes TCL_ERROR with an error message
 *	in the interpreter if non-NULL.
 *
 * Side effects:
 *	The ref counts of the elements in objv are incremented since the
 *	resulting list now refers to them.
 *
 *----------------------------------------------------------------------
 */

static List *
AttemptNewList(
static int
ListRepInitAttempt(
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
    Tcl_Size objc,
    Tcl_Obj *const objv[],
    ListRep *repPtr)
{
    List *listRepPtr = NewListIntRep(objc, objv, 0);
    int result = ListRepInit(objc, objv, 0, repPtr);

    if (interp != NULL && listRepPtr == NULL) {
    if (result != TCL_OK && interp != NULL) {
	if (objc > LIST_MAX) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    ListLimitExceededError(interp);
		    "max length of a Tcl list (%d elements) exceeded",
		    LIST_MAX));
	} else {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "list creation failed: unable to alloc %" TCL_Z_MODIFIER "u bytes",
		    LIST_SIZE(objc)));
	    MemoryAllocationError(interp, LIST_SIZE(objc));
	}
	Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
    }
    return result;
}

/*
 *------------------------------------------------------------------------
 *
 * ListRepClone --
 *
 *    Does a deep clone of an existing ListRep.
 *
 *    Normally the function allocates the exact space needed unless
 *    the flags arguments has one of the LISTREP_SPACE_* bits set.
 *    See the comments for those #defines.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    The toRepPtr location is initialized with the ListStore and ListSpan
 *    (if needed) containing a copy of the list elements in fromRepPtr.
 *    The function will panic if memory cannot be allocated.
 *
 *------------------------------------------------------------------------
 */
static void
ListRepClone(
    ListRep *fromRepPtr,
    ListRep *toRepPtr,
    int flags)
{
    Tcl_Obj **fromObjs;
    Tcl_Size numFrom;

    ListRepElements(fromRepPtr, numFrom, fromObjs);
    ListRepInit(numFrom, fromObjs, flags | LISTREP_PANIC_ON_FAIL, toRepPtr);
}

/*
 *------------------------------------------------------------------------
 *
 * ListRepUnsharedFreeUnreferenced --
 *
 *    Frees any Tcl_Obj's from the "in-use" area of the ListStore for a
 *    ListRep that are not actually references from any lists.
 *
 *    IMPORTANT: this function must not be called on a shared internal
 *    representation or the internal representation of a shared Tcl_Obj.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    The firstUsed and numUsed fields of the ListStore are updated to
 *    reflect the new "in-use" extent.
 *
 *------------------------------------------------------------------------
 */
static void
ListRepUnsharedFreeUnreferenced(
    const ListRep *repPtr)
{
    Tcl_Size count;
    ListStore *storePtr;
    ListSpan *spanPtr;

    LIST_ASSERT(!ListRepIsShared(repPtr));
    LISTREP_CHECK(repPtr);

    storePtr = repPtr->storePtr;
    spanPtr = repPtr->spanPtr;
    if (spanPtr == NULL) {
	LIST_ASSERT(storePtr->firstUsed == 0); /* Invariant TBD */
    return listRepPtr;
	return;
    }

    /* Collect garbage at front */
    count = spanPtr->spanStart - storePtr->firstUsed;
    LIST_COUNT_ASSERT(count);
    if (count > 0) {
	/* T:listrep-1.5.1,6.{1:8} */
	ObjArrayDecrRefs(storePtr->slots, storePtr->firstUsed, count);
	storePtr->firstUsed = spanPtr->spanStart;
	LIST_ASSERT(storePtr->numUsed >= count);
	storePtr->numUsed -= count;
    }

    /* Collect garbage at back */
    count = (storePtr->firstUsed + storePtr->numUsed)
	  - (spanPtr->spanStart + spanPtr->spanLength);
    LIST_COUNT_ASSERT(count);
    if (count > 0) {
	/* T:listrep-6.{1:8} */
	ObjArrayDecrRefs(
	    storePtr->slots, spanPtr->spanStart + spanPtr->spanLength, count);
	LIST_ASSERT(storePtr->numUsed >= count);
	storePtr->numUsed -= count;
    }

    LIST_ASSERT(ListRepStart(repPtr) == storePtr->firstUsed);
    LIST_ASSERT(ListRepLength(repPtr) == storePtr->numUsed);
    LISTREP_CHECK(repPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_NewListObj --
 *
 *	This function is normally called when not debugging: i.e., when
 *	Creates a new list object and adds values to it. When TCL_MEM_DEBUG is
 *	TCL_MEM_DEBUG is not defined. It creates a new list object from an
 *	defined, 'Tcl_DbNewListObj' is called instead.
 *	(objc,objv) array: that is, each of the objc elements of the array
 *	referenced by objv is inserted as an element into a new Tcl object.
 *
 * Value
 *	When TCL_MEM_DEBUG is defined, this function just returns the result
 *	of calling the debugging version Tcl_DbNewListObj.
 *
 * Results:
 *	A new list 'Tcl_Obj' to which is appended values from 'objv', or if
 *	'objc' is less than or equal to zero, a list 'Tcl_Obj' having no
 *	elements.  The string representation of the new 'Tcl_Obj' is set to
 *	NULL.  The refCount of the list is 0.
 *	A new list object is returned that is initialized from the object
 *	pointers in objv. If objc is less than or equal to zero, an empty
 *	object is returned. The new object's string representation is left
 *	NULL. The resulting new list object has ref count 0.
 *
 * Effect
 * Side effects:
 *
 *	The refCount of each elements in 'objv' is incremented as it is added
 *	to the list.
 *	The ref counts of the elements in objv are incremented since the
 *	resulting list now refers to them.
 *
 *----------------------------------------------------------------------
 */

#ifdef TCL_MEM_DEBUG
#undef Tcl_NewListObj

Tcl_Obj *
Tcl_NewListObj(
    int objc,			/* Count of objects referenced by objv. */
    Tcl_Size objc,		/* Count of objects referenced by objv. */
    Tcl_Obj *const objv[])	/* An array of pointers to Tcl objects. */
{
    return Tcl_DbNewListObj(objc, objv, "unknown", 0);
}

#else /* if not TCL_MEM_DEBUG */

Tcl_Obj *
Tcl_NewListObj(
    int objc,			/* Count of objects referenced by objv. */
    Tcl_Size objc,		/* Count of objects referenced by objv. */
    Tcl_Obj *const objv[])	/* An array of pointers to Tcl objects. */
{
    List *listRepPtr;
    Tcl_Obj *listPtr;
    ListRep listRep;
    Tcl_Obj *listObj;

    TclNewObj(listPtr);
    TclNewObj(listObj);

    if (objc <= 0) {
	return listPtr;
	return listObj;
    }

    /*
     * Create the internal rep.
     */

    ListRepInit(objc, objv, LISTREP_PANIC_ON_FAIL, &listRep);
    listRepPtr = NewListIntRep(objc, objv, 1);

    ListObjReplaceRepAndInvalidate(listObj, &listRep);
    /*
     * Now create the object.
     */

    TclInvalidateStringRep(listPtr);
    ListSetIntRep(listPtr, listRepPtr);
    return listPtr;
    return listObj;
}
#endif /* if TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------------
 *
 *  Tcl_DbNewListObj --
 * Tcl_DbNewListObj --
 *
 *	This function is normally called when debugging: i.e., when
 *	TCL_MEM_DEBUG is defined. It creates new list objects. It is the same
 *	as the Tcl_NewListObj function above except that it calls
 *	Like 'Tcl_NewListObj', but it calls Tcl_DbCkalloc directly with the
 *	file name and line number from its caller.  This simplifies debugging
 *	since the [memory active] command will report the correct file
 *	name and line number when reporting objects that haven't been freed.
 *	Tcl_DbCkalloc directly with the file name and line number from its
 *	caller. This simplifies debugging since then the [memory active]
 *	command will report the correct file name and line number when
 *	reporting objects that haven't been freed.
 *
 *	When TCL_MEM_DEBUG is not defined, 'Tcl_NewListObj' is called instead.
 *	When TCL_MEM_DEBUG is not defined, this function just returns the
 *	result of calling Tcl_NewListObj.
 *
 * Results:
 *	A new list object is returned that is initialized from the object
 *	pointers in objv. If objc is less than or equal to zero, an empty
 *	object is returned. The new object's string representation is left
 *	NULL. The new list object has ref count 0.
 *
 * Side effects:
 *	The ref counts of the elements in objv are incremented since the
 *	resulting list now refers to them.
 *
 *----------------------------------------------------------------------
 */

#ifdef TCL_MEM_DEBUG

Tcl_Obj *
Tcl_DbNewListObj(
    int objc,			/* Count of objects referenced by objv. */
    Tcl_Size objc,		/* Count of objects referenced by objv. */
    Tcl_Obj *const objv[],	/* An array of pointers to Tcl objects. */
    const char *file,		/* The name of the source file calling this
				 * function; used for debugging. */
    int line)			/* Line number in the source file; used for
				 * debugging. */
{
    Tcl_Obj *listPtr;
    List *listRepPtr;
    Tcl_Obj *listObj;
    ListRep listRep;

    TclDbNewObj(listPtr, file, line);
    TclDbNewObj(listObj, file, line);

    if (objc <= 0) {
	return listPtr;
	return listObj;
    }

    /*
     * Create the internal rep.
     */

    ListRepInit(objc, objv, LISTREP_PANIC_ON_FAIL, &listRep);
    listRepPtr = NewListIntRep(objc, objv, 1);

    ListObjReplaceRepAndInvalidate(listObj, &listRep);
    /*
     * Now create the object.
     */

    TclInvalidateStringRep(listPtr);
    ListSetIntRep(listPtr, listRepPtr);

    return listPtr;
    return listObj;
}

#else /* if not TCL_MEM_DEBUG */

Tcl_Obj *
Tcl_DbNewListObj(
    int objc,			/* Count of objects referenced by objv. */
    Tcl_Size objc,		/* Count of objects referenced by objv. */
    Tcl_Obj *const objv[],	/* An array of pointers to Tcl objects. */
    TCL_UNUSED(const char *) /*file*/,
    TCL_UNUSED(int) /*line*/)
{
    return Tcl_NewListObj(objc, objv);
}
#endif /* TCL_MEM_DEBUG */

/*
 *------------------------------------------------------------------------
 *
 * TclNewListObj2 --
 *
 *    Create a new Tcl_Obj list comprising of the concatenation of two
 *    Tcl_Obj* arrays.
 *    TODO - currently this function is not used within tclListObj but
 *    need to see if it would be useful in other files that preallocate
 *    lists and then append.
 *
 * Results:
 *    Non-NULL pointer to the allocate Tcl_Obj.
 *
 * Side effects:
 *    None.
 *
 *------------------------------------------------------------------------
 */
Tcl_Obj *
TclNewListObj2(
    Tcl_Size objc1,		/* Count of objects referenced by objv1. */
    Tcl_Obj *const objv1[],	/* First array of pointers to Tcl objects. */
    Tcl_Size objc2,		/* Count of objects referenced by objv2. */
    Tcl_Obj *const objv2[])	/* Second array of pointers to Tcl objects. */
{
    Tcl_Obj *listObj;
    ListStore *storePtr;
    Tcl_Size objc = objc1 + objc2;

    listObj = Tcl_NewListObj(objc, NULL);
    if (objc == 0) {
	return listObj; /* An empty object */
    }
    LIST_ASSERT_TYPE(listObj);

    storePtr = ListObjStorePtr(listObj);

    LIST_ASSERT(ListObjSpanPtr(listObj) == NULL);
    LIST_ASSERT(storePtr->firstUsed == 0);
    LIST_ASSERT(storePtr->numUsed == 0);
    LIST_ASSERT(storePtr->numAllocated >= objc);

    if (objc1) {
	ObjArrayCopy(storePtr->slots, objc1, objv1);
    }
    if (objc2) {
	ObjArrayCopy(&storePtr->slots[objc1], objc2, objv2);
    }
    storePtr->numUsed = objc;
    return listObj;
}

/*
 *----------------------------------------------------------------------
 *
 * TclListObjGetRep --
 *
 *	This function returns a copy of the ListRep stored
 *	as the internal representation of an object. The reference
 *	counts of the (ListStore, ListSpan) contained in the representation
 *	are NOT incremented.
 *
 * Results:
 *	The return value is normally TCL_OK; in this case *listRepP
 *	is set to a copy of the descriptor stored as the internal
 *	representation of the Tcl_Obj containing a list. if listPtr does not
 *	refer to a list object and the object can not be converted to one,
 *	TCL_ERROR is returned and an error message will be left in the
 *	interpreter's result if interp is not NULL.
 *
 * Side effects:
 *	The possible conversion of the object referenced by listPtr
 *	to a list object. *repPtr is initialized to the internal rep
 *      if result is TCL_OK, or set to NULL on error.
 *----------------------------------------------------------------------
 */

static int
TclListObjGetRep(
    Tcl_Interp *interp, /* Used to report errors if not NULL. */
    Tcl_Obj *listObj,   /* List object for which an element array is
			 * to be returned. */
    ListRep *repPtr)	/* Location to store descriptor */
{
    if (!TclHasInternalRep(listObj, &tclListType)) {
	int result;
	result = SetListFromAny(interp, listObj);
	if (result != TCL_OK) {
	    /* Init to keep gcc happy wrt uninitialized fields at call site */
	    repPtr->storePtr = NULL;
	    repPtr->spanPtr = NULL;
	    return result;
	}
    }
    ListObjGetRep(listObj, repPtr);
    LISTREP_CHECK(repPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetListObj --
 *
 *	Like 'Tcl_NewListObj', but operates on an existing 'Tcl_Obj'instead of
 *	creating a new one.
 *	Modify an object to be a list containing each of the objc elements of
 *	the object array referenced by objv.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The object is made a list object and is initialized from the object
 *	pointers in objv. If objc is less than or equal to zero, an empty
 *	object is returned. The new object's string representation is left
 *	NULL. The ref counts of the elements in objv are incremented since the
 *	list now refers to them. The object's old string and internal
 *	representations are freed and its type is set NULL.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetListObj(
    Tcl_Obj *objPtr,		/* Object whose internal rep to init. */
    int objc,			/* Count of objects referenced by objv. */
    Tcl_Size objc,		/* Count of objects referenced by objv. */
    Tcl_Obj *const objv[])	/* An array of pointers to Tcl objects. */
{
    List *listRepPtr;

    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_SetListObj");
    }

    /*
     * Free any old string rep and any internal rep for the old type.
     */

    TclFreeIntRep(objPtr);
    TclInvalidateStringRep(objPtr);

    /*
     * Set the object's type to "list" and initialize the internal rep.
     * However, if there are no elements to put in the list, just give the
     * object an empty string rep and a NULL type.
     * object an empty string rep and a NULL type. NOTE ListRepInit must
     * not be called with objc == 0!
     */

    if (objc > 0) {
	ListRep listRep;
	/* TODO - perhaps ask for extra space? */
	listRepPtr = NewListIntRep(objc, objv, 1);
	ListSetIntRep(objPtr, listRepPtr);
	ListRepInit(objc, objv, LISTREP_PANIC_ON_FAIL, &listRep);
	ListObjReplaceRepAndInvalidate(objPtr, &listRep);
    } else {
	TclFreeInternalRep(objPtr);
	TclInvalidateStringRep(objPtr);
	Tcl_InitStringRep(objPtr, NULL, 0);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclListObjCopy --
 *
 *	Creates a new 'Tcl_Obj' which is a pure copy of a list value. This
 *	provides for the C level a counterpart of the [lrange $list 0 end]
 *	command, while using internals details to be as efficient as possible.
 *	Makes a "pure list" copy of a list value. This provides for the C
 *	level a counterpart of the [lrange $list 0 end] command, while using
 *	internals details to be as efficient as possible.
 *
 * Value
 *
 *	The address of the new 'Tcl_Obj' which shares its internal
 *	representation with 'listPtr', and whose refCount is 0.  If 'listPtr'
 *	is not actually a list, the value is NULL, and an error message is left
 * Results:
 *	Normally returns a pointer to a new Tcl_Obj, that contains the same
 *	list value as *listPtr does. The returned Tcl_Obj has a refCount of
 *	zero. If *listPtr does not hold a list, NULL is returned, and if
 *	interp is non-NULL, an error message is recorded there.
 *	in 'interp' if it is not NULL.
 *
 * Effect
 *
 * Side effects:
 *	None.
 *	'listPtr' is converted to a list if it isn't one already.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TclListObjCopy(
    Tcl_Interp *interp,		/* Used to report errors if not NULL. */
    Tcl_Obj *listPtr)		/* List object for which an element array is
    Tcl_Obj *listObj)		/* List object for which an element array is
				 * to be returned. */
{
    Tcl_Obj *copyPtr;
    Tcl_Obj *copyObj;
    List *listRepPtr;

    ListGetIntRep(listPtr, listRepPtr);
    if (NULL == listRepPtr) {
	if (SetListFromAny(interp, listPtr) != TCL_OK) {
    if (!TclHasInternalRep(listObj, &tclListType)) {
	if (TclObjTypeHasProc(listObj, lengthProc)) {
	    return Tcl_DuplicateObj(listObj);
	}
	if (SetListFromAny(interp, listObj) != TCL_OK) {
	    return NULL;
	}
    }

    TclNewObj(copyPtr);
    TclInvalidateStringRep(copyPtr);
    DupListInternalRep(listPtr, copyPtr);
    return copyPtr;
    TclNewObj(copyObj);
    TclInvalidateStringRep(copyObj);
    DupListInternalRep(listObj, copyObj);
    return copyObj;
}

/*
 *------------------------------------------------------------------------
 *
 * ListRepRange --
 *
 *	Initializes a ListRep as a range within the passed ListRep.
 *	The range limits are clamped to the list boundaries.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *      The ListStore and ListSpan referenced by in the returned ListRep
 *      may or may not be the same as those passed in. For example, the
 *      ListStore may differ because the range is small enough that a new
 *      ListStore is more memory-optimal. The ListSpan may differ because
 *      it is NULL or shared. Regardless, reference counts on the returned
 *      values are not incremented. Generally, ListObjReplaceRepAndInvalidate
 *      may be used to store the new ListRep back into an object or a
 *      ListRepIncrRefs followed by ListRepDecrRefs to free in case of errors.
 *	Any other use should be carefully reconsidered.
 *      TODO WARNING:- this is an awkward interface and easy for caller
 *      to get wrong. Mostly due to refcount combinations. Perhaps passing
 *      in the source listObj instead of source listRep might simplify.
 *
 *------------------------------------------------------------------------
 */
static void
ListRepRange(
    ListRep *srcRepPtr,		/* Contains source of the range */
    Tcl_Size rangeStart,	/* Index of first element to include */
    Tcl_Size rangeEnd,		/* Index of last element to include */
    int preserveSrcRep,		/* If true, srcRepPtr contents must not be
				 * modified (generally because a shared Tcl_Obj
				 * references it) */
    ListRep *rangeRepPtr)	/* Output. Must NOT be == srcRepPtr */
{
    Tcl_Obj **srcElems;
    Tcl_Size numSrcElems = ListRepLength(srcRepPtr);
    Tcl_Size rangeLen;
    Tcl_Size numAfterRangeEnd;

    LISTREP_CHECK(srcRepPtr);

    /* Take the opportunity to garbage collect */
    /* TODO - we probably do not need the preserveSrcRep here unlike later */
    if (!preserveSrcRep) {
	/* T:listrep-1.{4,5,8,9},2.{4:7},3.{15:18},4.{7,8} */
	ListRepFreeUnreferenced(srcRepPtr);
    } /* else T:listrep-2.{4.2,4.3,5.2,5.3,6.2,7.2,8.1} */

    if (rangeStart < 0) {
	rangeStart = 0;
    }
    if (rangeEnd >= numSrcElems) {
	rangeEnd = numSrcElems - 1;
    }
    if (rangeStart > rangeEnd) {
	/* Empty list of capacity 1. */
	ListRepInit(1, NULL, LISTREP_PANIC_ON_FAIL, rangeRepPtr);
	return;
    }

    rangeLen = rangeEnd - rangeStart + 1;

    /*
     * We can create a range one of four ways:
     *  (0) Range encapsulates entire list
     *  (1) Special case: deleting in-place from end of an unshared object
     *  (2) Use a ListSpan referencing the current ListStore
     *  (3) Creating a new ListStore
     *  (4) Removing all elements outside the range in the current ListStore
     * Option (4) may only be done if caller has not disallowed it AND
     * the ListStore is not shared.
     *
     * The choice depends on heuristics related to speed and memory.
     * TODO - heuristics below need to be measured and tuned.
     *
     * Note: Even if nothing below cause any changes, we still want the
     * string-canonizing effect of [lrange 0 end] so the Tcl_Obj should not
     * be returned as is even if the range encompasses the whole list.
     */
    if (rangeStart == 0 && rangeEnd == (numSrcElems-1)) {
	/* Option 0 - entire list. This may be used to canonicalize */
	/* T:listrep-1.10.1,2.8.1 */
	*rangeRepPtr = *srcRepPtr; /* Not ref counts not incremented */
    } else if (rangeStart == 0 && (!preserveSrcRep)
	    && (!ListRepIsShared(srcRepPtr) && srcRepPtr->spanPtr == NULL)) {
	/* Option 1 - Special case unshared, exclude end elements, no span  */
	LIST_ASSERT(srcRepPtr->storePtr->firstUsed == 0); /* If no span */
	ListRepElements(srcRepPtr, numSrcElems, srcElems);
	numAfterRangeEnd = numSrcElems - (rangeEnd + 1);
	/* Assert: Because numSrcElems > rangeEnd earlier */
	if (numAfterRangeEnd != 0) {
	    /* T:listrep-1.{8,9} */
	    ObjArrayDecrRefs(srcElems, rangeEnd + 1, numAfterRangeEnd);
	}
	/* srcRepPtr->storePtr->firstUsed,numAllocated unchanged */
	srcRepPtr->storePtr->numUsed = rangeLen;
	srcRepPtr->storePtr->flags = 0;
	rangeRepPtr->storePtr = srcRepPtr->storePtr; /* Note no incr ref */
	rangeRepPtr->spanPtr = NULL;
    } else if (ListSpanMerited(rangeLen, srcRepPtr->storePtr->numUsed,
	    srcRepPtr->storePtr->numAllocated)) {
	/* Option 2 - because span would be most efficient */
	Tcl_Size spanStart = ListRepStart(srcRepPtr) + rangeStart;
	if (!preserveSrcRep && srcRepPtr->spanPtr
		&& srcRepPtr->spanPtr->refCount <= 1) {
	    /* If span is not shared reuse it */
	    /* T:listrep-2.7.3,3.{16,18} */
	    srcRepPtr->spanPtr->spanStart = spanStart;
	    srcRepPtr->spanPtr->spanLength = rangeLen;
	    *rangeRepPtr = *srcRepPtr;
	} else {
	    /* Span not present or is shared. */
	    /* T:listrep-1.5,2.{5,7},4.{7,8} */
	    rangeRepPtr->storePtr = srcRepPtr->storePtr;
	    rangeRepPtr->spanPtr = ListSpanNew(spanStart, rangeLen);
	}
	/*
	 * We have potentially created a new internal representation that
	 * references the same storage as srcRep but not yet incremented its
	 * reference count. So do NOT call freezombies if preserveSrcRep
	 * is mandated.
	 */
	if (!preserveSrcRep) {
	    /* T:listrep-1.{5.1,5.2,5.4},2.{5,7},3.{16,18},4.{7,8} */
	    ListRepFreeUnreferenced(rangeRepPtr);
	}
    } else if (preserveSrcRep || ListRepIsShared(srcRepPtr)) {
	/* Option 3 - span or modification in place not allowed/desired */
	/* T:listrep-2.{4,6} */
	ListRepElements(srcRepPtr, numSrcElems, srcElems);
	/* TODO - allocate extra space? */
	ListRepInit(rangeLen, &srcElems[rangeStart], LISTREP_PANIC_ON_FAIL,
		rangeRepPtr);
    } else {
	/*
	 * Option 4 - modify in place. Note that because of the invariant
	 * that spanless list stores must start at 0, we have to move
	 * everything to the front.
	 * TODO - perhaps if a span already exists, no need to move to front?
	 * or maybe no need to move all the way to the front?
	 * TODO - if range is small relative to allocation, allocate new?
	 */

	/* Asserts follow from call to ListRepFreeUnreferenced earlier */
	LIST_ASSERT(!preserveSrcRep);
	LIST_ASSERT(!ListRepIsShared(srcRepPtr));
	LIST_ASSERT(ListRepStart(srcRepPtr) == srcRepPtr->storePtr->firstUsed);
	LIST_ASSERT(ListRepLength(srcRepPtr) == srcRepPtr->storePtr->numUsed);

	ListRepElements(srcRepPtr, numSrcElems, srcElems);

	/* Free leading elements outside range */
	if (rangeStart != 0) {
	    /* T:listrep-1.4,3.15 */
	    ObjArrayDecrRefs(srcElems, 0, rangeStart);
	}
	/* Ditto for trailing */
	numAfterRangeEnd = numSrcElems - (rangeEnd + 1);
	/* Assert: Because numSrcElems > rangeEnd earlier */
	if (numAfterRangeEnd != 0) {
	    /* T:listrep-3.17 */
	    ObjArrayDecrRefs(srcElems, rangeEnd + 1, numAfterRangeEnd);
	}
	memmove(&srcRepPtr->storePtr->slots[0],
		&srcRepPtr->storePtr
		     ->slots[srcRepPtr->storePtr->firstUsed + rangeStart],
		rangeLen * sizeof(Tcl_Obj *));
	srcRepPtr->storePtr->firstUsed = 0;
	srcRepPtr->storePtr->numUsed = rangeLen;
	srcRepPtr->storePtr->flags = 0;
	if (srcRepPtr->spanPtr) {
	    /* In case the source has a span, update it for consistency */
	    /* T:listrep-3.{15,17} */
	    srcRepPtr->spanPtr->spanStart = srcRepPtr->storePtr->firstUsed;
	    srcRepPtr->spanPtr->spanLength = srcRepPtr->storePtr->numUsed;
	}
	rangeRepPtr->storePtr = srcRepPtr->storePtr;
	rangeRepPtr->spanPtr = NULL;
    }

    /* TODO - call freezombies here if !preserveSrcRep? */

    /* Note ref counts intentionally not incremented */
    LISTREP_CHECK(rangeRepPtr);
    return;
}

/*
 *----------------------------------------------------------------------
 *
 * TclListObjRange --
 *
 *	Makes a slice of a list value.
 *      *listPtr must be known to be a valid list.
 *      *listObj must be known to be a valid list.
 *
 * Results:
 *	Returns a pointer to the sliced list.
 *      This may be a new object or the same object if not shared.
 *	Returns NULL if passed listObj was not a list and could not be
 *	converted to one.
 *
 * Side effects:
 *	The possible conversion of the object referenced by listPtr
 *	to a list object.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TclListObjRange(
    Tcl_Interp *interp,		/* May be NULL. Used for error messages */
    Tcl_Obj *listPtr,		/* List object to take a range from. */
    size_t fromIdx,		/* Index of first element to include. */
    size_t toIdx)			/* Index of last element to include. */
    Tcl_Obj *listObj,		/* List object to take a range from. */
    Tcl_Size rangeStart,	/* Index of first element to include. */
    Tcl_Size rangeEnd)		/* Index of last element to include. */
{
    Tcl_Obj **elemPtrs;
    int listLen;
    ListRep listRep;
    size_t i, newLen;
    List *listRepPtr;
    ListRep resultRep;

    int isShared;
    TclListObjGetElements(NULL, listPtr, &listLen, &elemPtrs);

    if (TclListObjGetRep(interp, listObj, &listRep) != TCL_OK) {
	return NULL;
    if (fromIdx == TCL_INDEX_NONE) {
	fromIdx = 0;
    }
    if (toIdx + 1 >= (size_t)listLen + 1) {
	toIdx = listLen-1;
    }

    if (fromIdx + 1 > toIdx + 1) {
	Tcl_Obj *obj;
    isShared = Tcl_IsShared(listObj);
	TclNewObj(obj);
	return obj;
    }


    ListRepRange(&listRep, rangeStart, rangeEnd, isShared, &resultRep);
    newLen = toIdx - fromIdx + 1;

    if (Tcl_IsShared(listPtr) ||
	    ((ListRepPtr(listPtr)->refCount > 1))) {
	return Tcl_NewListObj(newLen, &elemPtrs[fromIdx]);
    }

    /*
     * In-place is possible.
    if (isShared) {
	/* T:listrep-1.10.1,2.{4.2,4.3,5.2,5.3,6.2,7.2,8.1} */
	TclNewObj(listObj);
    } /* T:listrep-1.{4.3,5.1,5.2} */
    ListObjReplaceRepAndInvalidate(listObj, &resultRep);
    return listObj;
}

/*
 *----------------------------------------------------------------------
     */

 *
    /*
     * Even if nothing below cause any changes, we still want the
     * string-canonizing effect of [lrange 0 end].
     */

    TclInvalidateStringRep(listPtr);

 * TclListObjGetElement --
 *
 *	Returns a single element from the array of the elements in a list
 *	object, without doing any bounds checking.  Caller must ensure
 *	that ObjPtr of type 'tclListType' and that index is valid for the
 *	list.
 *
    /*
     * Delete elements that should not be included.
     */
 *----------------------------------------------------------------------
 */

    for (i = 0; i < fromIdx; i++) {
	TclDecrRefCount(elemPtrs[i]);
Tcl_Obj *
    }
    for (i = toIdx + 1; i < (size_t)listLen; i++) {
	TclDecrRefCount(elemPtrs[i]);
    }

TclListObjGetElement(
    if (fromIdx > 0) {
	memmove(elemPtrs, &elemPtrs[fromIdx],
		(size_t) newLen * sizeof(Tcl_Obj*));
    Tcl_Obj *objPtr,		/* List object for which an element array is
    }

				 * to be returned. */
    listRepPtr = ListRepPtr(listPtr);
    listRepPtr->elemCount = newLen;

    return listPtr;
    Tcl_Size index)
{
    return ListObjStorePtr(objPtr)->slots[ListObjStart(objPtr) + index];
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjGetElements --
 *
 *	Retreive the elements in a list 'Tcl_Obj'.
 *
 *	This function returns an (objc,objv) array of the elements in a list
 *	object.
 * Value
 *
 *	TCL_OK
 *
 *	    A count of list elements is stored, 'objcPtr', And a pointer to the
 *	    array of elements in the list is stored in 'objvPtr'.
 * Results:
 *	The return value is normally TCL_OK; in this case *objcPtr is set to
 *	the count of list elements and *objvPtr is set to a pointer to an
 *	array of (*objcPtr) pointers to each list element. If listPtr does not
 *	refer to a list object and the object can not be converted to one,
 *	TCL_ERROR is returned and an error message will be left in the
 *	interpreter's result if interp is not NULL.
 *
 *	    The elements accessible via 'objvPtr' should be treated as readonly
 *	    and the refCount for each object is _not_ incremented; the caller
 *	    must do that if it holds on to a reference. Furthermore, the
 *	    pointer and length returned by this function may change as soon as
 *	    any function is called on the list object. Be careful about
 *	    retaining the pointer in a local data structure.
 *	The objects referenced by the returned array should be treated as
 *	readonly and their ref counts are _not_ incremented; the caller must
 *	do that if it holds on to a reference. Furthermore, the pointer and
 *	length returned by this function may change as soon as any function is
 *	called on the list object; be careful about retaining the pointer in a
 *	local data structure.
 *
 *	TCL_ERROR
 *
 *	    'listPtr' is not a valid list. An error message is left in the
 *	    interpreter's result if 'interp' is not NULL.
 *
 * Effect
 * Side effects:
 *
 *	'listPtr' is converted to a list object if it isn't one already.
 *	The possible conversion of the object referenced by listPtr
 *	to a list object.
 *
 *----------------------------------------------------------------------
 */

#undef Tcl_ListObjGetElements
int
Tcl_ListObjGetElements(
    Tcl_Interp *interp,		/* Used to report errors if not NULL. */
    Tcl_Obj *listPtr,	/* List object for which an element array is
    Tcl_Obj *objPtr,		/* List object for which an element array is
				 * to be returned. */
    int *objcPtr,		/* Where to store the count of objects
    Tcl_Size *objcPtr,		/* Where to store the count of objects
				 * referenced by objv. */
    Tcl_Obj ***objvPtr)		/* Where to store the pointer to an array of
				 * pointers to the list's objects. */
{
    List *listRepPtr;
    ListRep listRep;

    ListGetIntRep(listPtr, listRepPtr);

    if (TclObjTypeHasProc(objPtr, getElementsProc)) {
	return TclObjTypeGetElements(interp, objPtr, objcPtr, objvPtr);
    if (listRepPtr == NULL) {
	int result;
	size_t length;

	(void) TclGetStringFromObj(listPtr, &length);
    }
    if (TclListObjGetRep(interp, objPtr, &listRep) != TCL_OK) {
	if (length == 0) {
	    *objcPtr = 0;
	    *objvPtr = NULL;
	    return TCL_OK;
	}
	return TCL_ERROR;
    }
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
	ListGetIntRep(listPtr, listRepPtr);
    }
    *objcPtr = listRepPtr->elemCount;
    ListRepElements(&listRep, *objcPtr, *objvPtr);
    *objvPtr = &listRepPtr->elements;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjAppendList --
 *
 *	Appends the elements of elemListPtr to those of listPtr.
 *	This function appends the elements in the list fromObj
 *	to toObj. toObj must not be shared else the function will panic.
 *
 * Value
 * Results:
 *
 *	TCL_OK
 *	The return value is normally TCL_OK. If fromObj or toObj do not
 *
 *	    Success.
 *
 *	TCL_ERROR
 *	refer to list values, TCL_ERROR is returned and an error message is
 *
 *	    'listPtr' or 'elemListPtr' are not valid lists.  An error
 *	    message is left in the interpreter's result if 'interp' is not NULL.
 *	left in the interpreter's result if interp is not NULL.
 *
 * Effect
 * Side effects:
 *
 *	The reference count of each element of 'elemListPtr' as it is added to
 *	The reference counts of the elements in fromObj are incremented
 *	'listPtr'. 'listPtr' and 'elemListPtr' are converted to 'tclListType'
 *	if they are not already. Appending the new elements may cause the
 *	array of element pointers in 'listObj' to grow.  If any objects are
 *	appended to 'listPtr'. Any preexisting string representation of
 *	since the list now refers to them. toObj and fromObj are
 *	converted, if necessary, to list objects. Also, appending the new
 *	elements may cause toObj's array of element pointers to grow.
 *	toObj's old string representation, if any, is invalidated.
 *	'listPtr' is invalidated.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ListObjAppendList(
    Tcl_Interp *interp,		/* Used to report errors if not NULL. */
    Tcl_Obj *listPtr,	/* List object to append elements to. */
    Tcl_Obj *elemListPtr)	/* List obj with elements to append. */
    Tcl_Obj *toObj,		/* List object to append elements to. */
    Tcl_Obj *fromObj)		/* List obj with elements to append. */
{
    int objc;
    Tcl_Size objc;
    Tcl_Obj **objv;

    if (Tcl_IsShared(listPtr)) {
    if (Tcl_IsShared(toObj)) {
	Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendList");
    }

    /*
     * Pull the elements to append from elemListPtr.
     */

    if (TCL_OK != TclListObjGetElements(interp, elemListPtr, &objc, &objv)) {
    if (TclListObjGetElements(interp, fromObj, &objc, &objv) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Insert the new elements starting after the lists's last element.
     * Delete zero existing elements.
     */

    return TclListObjAppendElements(interp, toObj, objc, objv);
}
    return Tcl_ListObjReplace(interp, listPtr, LIST_MAX, 0, objc, objv);

/*
 *------------------------------------------------------------------------
 *
 * TclListObjAppendElements --
 *
 *      Appends multiple elements to a Tcl_Obj list object. If
 *      the passed Tcl_Obj is not a list object, it will be converted to one
 *      and an error raised if the conversion fails.
 *
 *	The Tcl_Obj must not be shared though the internal representation
 *	may be.
 *
 * Results:
 *	On success, TCL_OK is returned with the specified elements appended.
 *	On failure, TCL_ERROR is returned with an error message in the
 *	interpreter if not NULL.
 *
 * Side effects:
 *    None.
 *
 *------------------------------------------------------------------------
 */
 int
 TclListObjAppendElements (
    Tcl_Interp *interp,		/* Used to report errors if not NULL. */
    Tcl_Obj *toObj,		/* List object to append */
    Tcl_Size elemCount,		/* Number of elements in elemObjs[] */
    Tcl_Obj * const elemObjv[])	/* Objects to append to toObj's list. */
{
    ListRep listRep;
    Tcl_Obj **toObjv;
    Tcl_Size toLen;
    Tcl_Size finalLen;

    if (Tcl_IsShared(toObj)) {
	Tcl_Panic("%s called with shared object", "TclListObjAppendElements");
    }

    if (TclListObjGetRep(interp, toObj, &listRep) != TCL_OK) {
	/* Cannot be converted to a list */
	return TCL_ERROR;
    }

    if (elemCount <= 0) {
	/*
	 * Note that when elemCount <= 0, this routine is logically a
	 * no-op, removing and adding no elements to the list. However, by removing
	 * the string representation, we get the important side effect that the
	 * resulting listPtr is a list in canonical form. This is important.
	 * Resist any temptation to optimize this case further. See bug [e38dce74e2].
	 */
	if (!ListObjIsCanonical(toObj)) {
	    TclInvalidateStringRep(toObj);
	}
	/* Nothing to do. Note AFTER check for list above */
	return TCL_OK;
    }

    ListRepElements(&listRep, toLen, toObjv);
    if (elemCount > LIST_MAX || toLen > (LIST_MAX - elemCount)) {
	return ListLimitExceededError(interp);
    }

    finalLen = toLen + elemCount;
    if (!ListRepIsShared(&listRep)) {
	/*
	 * Reuse storage if possible. Even if too small, realloc-ing instead
	 * of creating a new ListStore will save us on manipulating Tcl_Obj
	 * reference counts on the elements which is a substantial cost
	 * if the list is not small.
	 */
	Tcl_Size numTailFree;

	ListRepFreeUnreferenced(&listRep); /* Collect garbage before checking room */

	LIST_ASSERT(ListRepStart(&listRep) == listRep.storePtr->firstUsed);
	LIST_ASSERT(ListRepLength(&listRep) == listRep.storePtr->numUsed);
	LIST_ASSERT(toLen == listRep.storePtr->numUsed);

	if (finalLen > listRep.storePtr->numAllocated) {
	    /* T:listrep-1.{2,11},3.6 */
	    ListStore *newStorePtr = ListStoreReallocate(
		    listRep.storePtr, finalLen);
	    if (newStorePtr == NULL) {
		return MemoryAllocationError(interp, LIST_SIZE(finalLen));
	    }
	    LIST_ASSERT(newStorePtr->numAllocated >= finalLen);
	    listRep.storePtr = newStorePtr;
	    /*
	     * WARNING: at this point the Tcl_Obj internal rep potentially
	     * points to freed storage if the reallocation returned a
	     * different location. Overwrite it to bring it back in sync.
	     */
	    ListObjStompRep(toObj, &listRep);
	} /* else T:listrep-3.{4,5} */
	LIST_ASSERT(listRep.storePtr->numAllocated >= finalLen);
	/* Current store big enough */
	numTailFree = ListRepNumFreeTail(&listRep);
	LIST_ASSERT((numTailFree + listRep.storePtr->firstUsed)
		    >= elemCount); /* Total free */
	if (numTailFree < elemCount) {
	    /* Not enough room at back. Move some to front */
	    /* T:listrep-3.5 */
	    Tcl_Size shiftCount = elemCount - numTailFree;
	    /* Divide remaining space between front and back */
	    shiftCount += (listRep.storePtr->numAllocated - finalLen) / 2;
	    LIST_ASSERT(shiftCount <= listRep.storePtr->firstUsed);
	    if (shiftCount) {
		/* T:listrep-3.5 */
		ListRepUnsharedShiftDown(&listRep, shiftCount);
	    }
	} /* else T:listrep-3.{4,6} */
	ObjArrayCopy(
		&listRep.storePtr->slots[
			ListRepStart(&listRep) + ListRepLength(&listRep)],
		elemCount, elemObjv);
	listRep.storePtr->numUsed = finalLen;
	if (listRep.spanPtr) {
	    /* T:listrep-3.{4,5,6} */
	    LIST_ASSERT(listRep.spanPtr->spanStart
			== listRep.storePtr->firstUsed);
	    listRep.spanPtr->spanLength = finalLen;
	} /* else T:listrep-3.6.3 */
	LIST_ASSERT(ListRepStart(&listRep) == listRep.storePtr->firstUsed);
	LIST_ASSERT(ListRepLength(&listRep) == finalLen);
	LISTREP_CHECK(&listRep);

	ListObjReplaceRepAndInvalidate(toObj, &listRep);
	return TCL_OK;
    }

    /*
     * Have to make a new list rep, either shared or no room in old one.
     * If the old list did not have a span (all elements at front), do
     * not leave space in the front either, assuming all appends and no
     * prepends.
     */
    if (ListRepInit(finalLen, NULL,
	    listRep.spanPtr ? LISTREP_SPACE_FAVOR_BACK : LISTREP_SPACE_ONLY_BACK,
	    &listRep) != TCL_OK) {
	return MemoryAllocationError(interp, finalLen);
    }
    LIST_ASSERT(listRep.storePtr->numAllocated >= finalLen);

    if (toLen) {
	/* T:listrep-2.{2,9},4.5 */
	ObjArrayCopy(ListRepSlotPtr(&listRep, 0), toLen, toObjv);
    }
    ObjArrayCopy(ListRepSlotPtr(&listRep, toLen), elemCount, elemObjv);
    listRep.storePtr->numUsed = finalLen;
    if (listRep.spanPtr) {
	/* T:listrep-4.5 */
	LIST_ASSERT(listRep.spanPtr->spanStart == listRep.storePtr->firstUsed);
	listRep.spanPtr->spanLength = finalLen;
    }
    LISTREP_CHECK(&listRep);
    ListObjReplaceRepAndInvalidate(toObj, &listRep);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjAppendElement --
 *
635
636
637
638
639
640
641
642

643
644
645
646
647
648
649
650
651
652
653


654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749

750
751
752
753
754
755
756
757
758

759
760
761
762
763
764
765
766
767
768

769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804


805
806

807
808

809
810
811
812
813
814
815
816

817
818
819


820
821

822
823

824
825
826
827
828
829
830
831
832


833
834
835
836

837
838
839
840

841
842
843
844
845
846
847
848
849
850










851
852
853
854





855
856
857

858
859
860
861
862
863
864
865
866
867
868



869
870

871
872

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
898
899
900
901
902
903
904
905
906
907
908
909













910




911
912




913
914
915
916
917
918
919
920




921
922
923
924



925
926
927



928
929
930
931
932
933
934




935


936

937
938
939


940
941

942
943
944

945
946

947
948
949



950
951
952
953
954
955
956
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


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
1116










1117
1118
1119
1120


















1121



1122

1123
1124
1125





1126
1127
1128






1129
1130
1131
1132
1133














1134
1135

1136
1137


1138
1139
1140
1141
1142
1143
1144

















1145
1146

1147




1148
1149
1150



1151
1152
1153











1154
1155

1156

1157
1158
1159
1160
1161
1162
1163










1164
1165

1166

1167



1168

1169
1170
1171
1172












1173

1174







1175

1176
1177
1178
1179












1180
1181

1182
1183





1184
1185
1186
1187














1188
1189
1190
1191








1192
1193
1194
1195
1196



1197
1198
1199
1200
1201
1202
1203
1204



















1205
1206
1207
1208
1209
1210
1211
1212
1213

1214
1215
1216
1217
1218




1219
1220
1221


1222
1223
1224
1225






1226
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
1354
1355
1356
1357



1358
1359
1360

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
1387




1388
1389


1390
1391
1392






1393
1394
1395
1396
1397
1398
1399
1400
1401
1402



1403
1404

1405
1406
1407


1408
1409
1410
1411
1412
1413
1414
1415
1416
1417

1418
1419

1420
1421










1422
1423
1424
1425
1426





1427
1428
1429
1430
1431
1432
1433






1434
1435
1436
1437











1438
1439
1440
1441



1442
1443
1444
1445
1446









1447
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
1478
1479

1480
1481
1482
1483
1484







1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500


1501
1502
1503

1504
1505
1506
1507
1508






1509
1510
1511
1512
1513

1514
1515
1516
1517
1518


1519
1520

1521
1522
1523
1524
1525
1526

1527
1528
1529
1530

1531
1532
1533
1534

1535
1536
1537
1538
1539
1540
1541

1542
1543







1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763

1764
1765
1766


1767
1768



1769
1770
1771
1772
1773
1774
1775

1776
1777
1778

1779
1780
1781
1782
1783
1784
1785
1786

1787
1788
1789
1790
1791
1792
1793
1794
1795
1796


1797
1798
1799
1800

1801
1802
1803
1804

1805
1806
1807

1808
1809

1810
1811
1812
1813
1814


1815
1816
1817
1818
1819
1820
1821


1822

1823

1824
1825


1826
1827

1828
1829
1830
1831
1832
1833
1834
1835
1836
1837

1838
1839
1840
1841
1842
1843
1844
1845



1846
1847
1848
1849
1850
1851
1852
1853
1854
1855


1856
1857
1858


1859
1860

1861
1862
1863
1864
1865
1866
1867

1868
1869
1870
1871
1872

1873
1874
1875
1876
1877
1878

1879
1880
1881
1882
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
1958

1959

1960
1961

1962
1963

1964
1965

1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976

1977
1978
1979
1980
1981
1982
1983
1984
1985
1986

1987
1988
1989


1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000

2001
2002


2003
2004
2005




2006

2007
2008


2009
2010
2011

2012
2013
2014
2015
2016
2017
2018
2019


























2020
2021

2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032

2033

2034
2035
2036
2037



2038

2039
2040


2041
2042
2043
2044
2045
2046

2047
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
2095
2096
2097
2098
2099
2100
2101
2102

2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116

2117
2118
2119
2120
2121


2122
2123
2124
2125

2126
2127
2128
2129


2130
2131

2132
2133
2134
2135
2136













2137



2138

2139
2140
2141
2142

2143
2144
2145
2146

2147
2148
2149
2150
2151

2152
2153
2154
2155
2156
2157
2158

2159
2160
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
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


1958
1959
1960
1961

1962
1963
1964


1965
1966
1967
1968


1969




1970
1971









1972
1973
1974
1975
1976
1977
1978
1979
1980
1981




1982
1983
1984
1985
1986
1987
1988

1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999

2000
2001
2002
2003

2004


2005



2006
2007
2008
2009

2010



2011
2012

2013
2014
2015
2016
2017
2018
2019



2020
2021
2022
2023

2024
2025
2026



2027
2028
2029













2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047


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
2095
2096
2097
2098

2099



2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110

2111
2112
2113
2114




2115





2116
2117
2118



2119




2120
2121
2122
2123
2124



2125








2126



2127
2128
2129


2130
2131
2132






2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155

2156





2157
2158
2159
2160
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




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
2273
2274
2275
2276
2277
2278
2279
2280




2281
2282
2283
2284
2285
2286
2287
2288


2289












2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399


2400


2401
2402







2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419

2420
2421

2422
2423
2424
2425
2426


2427
2428
2429



2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441

2442
2443
2444







2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497


2498


2499
2500
2501
2502
2503




2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517




2518
2519
2520
2521
2522
2523
2524
2525

2526



2527
2528
2529

2530






2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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
3134
3135


3136
3137
3138
3139
3140



3141
3142
3143
3144

3145
3146









3147
3148

3149
3150
3151
3152

3153
3154


3155
3156
3157
3158
3159
3160
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




3199





3200
3201
3202
3203

3204
3205
3206

3207
3208






3209
3210




3211






3212

3213
3214
3215
3216
3217
3218
3219
3220
3221


3222
3223
3224

3225
3226
3227
3228
3229
3230
3231
3232
3233

3234
3235

3236
3237

3238
3239







3240
3241
3242
3243
3244




3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256

3257
3258
3259

3260
3261
3262
3263

3264
3265
3266
3267

3268
3269


3270
3271
3272


3273
3274


3275

3276
3277
3278
3279
3280
3281
3282

3283
3284

3285


3286


3287

3288
3289

3290


3291


3292
3293
3294
3295

3296
3297
3298
3299
3300

3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311

3312
3313
3314

3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328


3329
3330
3331
3332

3333
3334
3335
3336
3337
3338


3339
3340

3341

3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377

3378

3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389

3390

3391
3392

3393
3394
3395
3396
3397


3398
3399

3400
3401
3402
3403

3404
3405
3406
3407
3408
3409

3410
3411
3412

3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424

3425




3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436

3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453

3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468

3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479

3480
3481

3482
3483
3484
3485


3486
3487
3488
3489
3490

3491
3492



3493
3494
3495

3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518

3519

3520


3521

3522
3523

3524
3525
3526
3527


3528

3529
3530
3531
3532


3533


3534
3535

3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549

3550
3551
3552
3553
3554
3555
3556
3557
3558
3559

3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627







-
+





-



-
-
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







-
-
+
+

-
+
-
-
+
-






-
+
-
-
-
+
+

-
+
-
-
+



-



-
-
+
+


-
-
+
-
-
-
-
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+


-
+










-
+
+
+

-
+
-
-
+
-
-
-
+
+
+
+
-

-
-
-
+
+
-




+


-
-
-
+
+
+

-
+

+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
-
-
+
+
+
+







-
+
+
+
+

-
-
-
+
+
+
-
-
-
+
+
+

-
-
-
-
-
-
+
+
+
+

+
+
-
+
-
-
-
+
+

-
+
-
-
-
+
-
-
+
-
-
-
+
+
+



-



-
-
-
-
-
+
+
+
+
+
-

-
-
-
+
+
+
+
+
+
+
+
+
+

-
+



-
-
-
-
+
-
-
-
-
-
+
+
+
-
-
-

-
-
-
-
+
+
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
+
-
-
-



-
-
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
-
+
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
-
-
-
+
+
+
-
-
+

+
+
+
+
+
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+

+
+
+
+
-
+
-
-
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
-
+
-
-
-
+
+
+
+
+

-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-

+
-
+
+
+
+

-
-
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
+

+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
+
-
+

+
+
+

+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+

+
+
+
+
+
+
+
-
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
-

-
-
-
+
+
+
-

-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
+

-
-
-
-
+
+
+
+

-
-
+
+
-
-

-
+
+
+
+
+
+



-



-
-
+
+

-
-
+

-
+
+




+
-
+

-
-
+
+
-
-
+



-
-
+














-
+


-
-
+
+
+

-
-
+

-
+
-
-
-
-
-
+
-

-
+





-
+

-
-
+
+

-
+
+
+
+

-
-
-
+
+

+
+
+
+
-
-
+
+

-


-



-
-
+
+



-
+
+

+
+
+
-
-
-
-
+
+
+
+
+
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+

+
+
+
-
+

-



-
+






-
-
-
+
+
+



+
-
+
+

+

-
+
+

+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+



-
-
+
+
+
+

-
+
+

-
-
+
+
+
+
+
+



-



-
-
-
+
+
+

-
+

-
-
+
+

-







-
+
-
-
+
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+

-
-
-
-
+
+
+
+
+
+
+
+
+










-
-
-
+
+
+
+

-
-
-
-
+
+
+
+
+
-
-
-
+
-
-
-
+

-
-
-
+
+
+

-
-
-
-
+
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-


-



-
-
+
+


-
+

-
-
-
-
+
+
+
+
+
+




-
+



-
-
+
+

-
+





-
+



-
+



-
+






-
+
-

+
+
+
+
+
+
+







-
+






-
-
+
+










-
-
+
+


-
+




+
+
+
+
+
+
+
+
-
-
+
+



-
-
+
+
-







-
-
-
+
+
+



-
-
-
+
+
+

-
+

-
-
+
+





-
-
-
-
+
+
+
+


-
-
+
+

-
+

-
-
-
+
+
+



-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+


-
-
-
+
+






-
-
+
+
+

-
-
-
+
+
+
-

-
-
-
-
-
+
+
-
-

-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
-
-
-
-
+
+
+
+








-
-
+
+





-
+





-
-
-
-
-
+
+
+
+
+
+
+

+
-
-
+
+

-
-
+
+







-
+

-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
+
+
+
-
-
+
+
+

+
-
-
-
+
+
+
+
-
+

-
-
-
-
-
-
-
-
-


-




-
+

-
-
+
+


+
+
+
-
-
-
-

-
-
+
-

-
+



-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
+
-
-
-
-
+

-
-
+
-
-
+
-


-
-
+
+
-





-
+
+

+

+
-
-
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-

-
-
-
-
-
+
+


-
+
+

-
+

-
-
-
-
-
-
+

-
-
-
-
+
-
-
-
-
-
-
+
-









-
-
+
+

-
+
+

+





-


-
+

-
+

-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+








-
+


-
+
+

+
-
+



-


-
-
+
+

-
-
+
+
-
-
+
-







-
+

-
+
-
-
+
-
-
+
-
+

-
+
-
-
+
-
-
+



-





-

+









-
+


-
+
+











+
-
-
+
+


-
+
+
+
+

+
-
-
+
+
-

-
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
-










+
-
+
-


-
+
+
+

+
-
-
+
+
-




-
+





-
+


-
+











-
+
-
-
-
-










+
-
+

+
+







+
+
+
+
+
+
-
+
+
+
+
+










-
+










-


-
+



-
-
+
+



-
+

-
-
-
+
+

-
+





+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
-
+
-

-
-
+
-


-
+



-
-
+
-




-
-
+
-
-


-




+
+
+







-
+









-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *	    converted to one. An error message will be left in the
 *	    interpreter's result if interp is not NULL.
 *
 * Effect
 *
 *	If 'listPtr' is not already of type 'tclListType', it is converted.
 *	The 'refCount' of 'objPtr' is incremented as it is added to 'listPtr'.
 *	Appending the new element may cause the the array of element pointers
 *	Appending the new element may cause the array of element pointers
 *	in 'listObj' to grow.  Any preexisting string representation of
 *	'listPtr' is invalidated.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ListObjAppendElement(
    Tcl_Interp *interp,		/* Used to report errors if not NULL. */
    Tcl_Obj *listPtr,		/* List object to append objPtr to. */
    Tcl_Obj *objPtr)		/* Object to append to listPtr's list. */
    Tcl_Obj *toObj,		/* List object to append elemObj to. */
    Tcl_Obj *elemObj)		/* Object to append to toObj's list. */
{
    List *listRepPtr, *newPtr = NULL;
    int numElems, numRequired, needGrow, isShared, attempt;

    if (Tcl_IsShared(listPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendElement");
    }

    ListGetIntRep(listPtr, listRepPtr);
    if (listRepPtr == NULL) {
	int result;
	size_t length;

	(void) TclGetStringFromObj(listPtr, &length);
	if (length == 0) {
	    Tcl_SetListObj(listPtr, 1, &objPtr);
	    return TCL_OK;
	}
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
	ListGetIntRep(listPtr, listRepPtr);
    }

    numElems = listRepPtr->elemCount;
    numRequired = numElems + 1 ;
    needGrow = (numRequired > listRepPtr->maxElemCount);
    isShared = (listRepPtr->refCount > 1);

    if (numRequired > LIST_MAX) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "max length of a Tcl list (%d elements) exceeded",
		    LIST_MAX));
	    Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
	}
	return TCL_ERROR;
    }

    if (needGrow && !isShared) {
	/*
    /*
	 * Need to grow + unshared intrep => try to realloc
	 */

     * TODO - compare perf with 8.6 to see if worth optimizing single
	attempt = 2 * numRequired;
	if (attempt <= LIST_MAX) {
	    newPtr = (List *)Tcl_AttemptRealloc(listRepPtr, LIST_SIZE(attempt));
	}
	if (newPtr == NULL) {
	    attempt = numRequired + 1 + TCL_MIN_ELEMENT_GROWTH;
	    if (attempt > LIST_MAX) {
		attempt = LIST_MAX;
	    }
	    newPtr = (List *)Tcl_AttemptRealloc(listRepPtr, LIST_SIZE(attempt));
	}
	if (newPtr == NULL) {
	    attempt = numRequired;
	    newPtr = (List *)Tcl_AttemptRealloc(listRepPtr, LIST_SIZE(attempt));
	}
	if (newPtr) {
	    listRepPtr = newPtr;
	    listRepPtr->maxElemCount = attempt;
	    needGrow = 0;
	}
    }
    if (isShared || needGrow) {
	Tcl_Obj **dst, **src = &listRepPtr->elements;

	/*
	 * Either we have a shared intrep and we must copy to write, or we
	 * need to grow and realloc attempts failed.  Attempt intrep copy.
	 */

	attempt = 2 * numRequired;
	newPtr = AttemptNewList(NULL, attempt, NULL);
	if (newPtr == NULL) {
	    attempt = numRequired + 1 + TCL_MIN_ELEMENT_GROWTH;
	    if (attempt > LIST_MAX) {
		attempt = LIST_MAX;
	    }
	    newPtr = AttemptNewList(NULL, attempt, NULL);
	}
	if (newPtr == NULL) {
	    attempt = numRequired;
	    newPtr = AttemptNewList(interp, attempt, NULL);
	}
	if (newPtr == NULL) {
	    /*
	     * All growth attempts failed; throw the error.
	     */

	    return TCL_ERROR;
	}

	dst = &newPtr->elements;
     * element case
	newPtr->refCount++;
	newPtr->canonicalFlag = listRepPtr->canonicalFlag;
	newPtr->elemCount = listRepPtr->elemCount;

	if (isShared) {
	    /*
	     * The original intrep must remain undisturbed.  Copy into the new
	     * one and bump refcounts
	     */
     */
	    while (numElems--) {
		*dst = *src++;
		Tcl_IncrRefCount(*dst++);
	    }
	    listRepPtr->refCount--;
	} else {
	    /*
	     * Old intrep to be freed, re-use refCounts.
	     */

    return TclListObjAppendElements(interp, toObj, 1, &elemObj);
	    memcpy(dst, src, numElems * sizeof(Tcl_Obj *));
	    Tcl_Free(listRepPtr);
	}
	listRepPtr = newPtr;
    }
    ListResetIntRep(listPtr, listRepPtr);
    listRepPtr->refCount++;
    TclFreeIntRep(listPtr);
    ListSetIntRep(listPtr, listRepPtr);
    listRepPtr->refCount--;

    /*
     * Add objPtr to the end of listPtr's array of element pointers. Increment
     * the ref count for the (now shared) objPtr.
     */

    *(&listRepPtr->elements + listRepPtr->elemCount) = objPtr;
    Tcl_IncrRefCount(objPtr);
    listRepPtr->elemCount++;

    /*
     * Invalidate any old string representation since the list's internal
     * representation has changed.
     */

    TclInvalidateStringRep(listPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjIndex --
 *
 * 	Retrieve a pointer to the element of 'listPtr' at 'index'.  The index
 * 	of the first element is 0.
 *	Retrieve a pointer to the element of 'listPtr' at 'index'.  The index
 *	of the first element is 0.
 *
 * Value
 * Returns:
 *
 * 	TCL_OK
 *	TCL_OK
 *
 *	    A pointer to the element at 'index' is stored in 'objPtrPtr'.  If
 *	    'index' is out of range, NULL is stored in 'objPtrPtr'.  This
 *	    object should be treated as readonly and its 'refCount' is _not_
 *	    incremented. The caller must do that if it holds on to the
 *	    reference.
 *
 * 	TCL_ERROR
 *	TCL_ERROR
 *
 * 	    'listPtr' is not a valid list. An an error message is left in the
 * 	    interpreter's result if 'interp' is not NULL.
 *	    'listPtr' is not a valid list. An error message is left in the
 *	    interpreter's result if 'interp' is not NULL.
 *
 *  Effect
 * Effect:
 *
 * 	If 'listPtr' is not already of type 'tclListType', it is converted.
 *	If 'listPtr' is not already of type 'tclListType', it is converted.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ListObjIndex(
    Tcl_Interp *interp,		/* Used to report errors if not NULL. */
    Tcl_Obj *listPtr,	/* List object to index into. */
    int index,		/* Index of element to return. */
    Tcl_Obj *listObj,		/* List object to index into. */
    Tcl_Size index,		/* Index of element to return. */
    Tcl_Obj **objPtrPtr)	/* The resulting Tcl_Obj* is stored here. */
{
    List *listRepPtr;

    Tcl_Obj **elemObjs;
    ListGetIntRep(listPtr, listRepPtr);
    if (listRepPtr == NULL) {
	int result;
	size_t length;
    Tcl_Size numElems;

	(void) TclGetStringFromObj(listPtr, &length);
	if (length == 0) {
	    *objPtrPtr = NULL;
	    return TCL_OK;
	}
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    /* Empty string => empty list. Avoid unnecessary shimmering */
    if (listObj->bytes == &tclEmptyString) {
	*objPtrPtr = NULL;
	return TCL_OK;
    }

    int hasAbstractList = TclObjTypeHasProc(listObj,indexProc) != 0;
    if (hasAbstractList) {
	return TclObjTypeIndex(interp, listObj, index, objPtrPtr);
    }
	ListGetIntRep(listPtr, listRepPtr);
    }

    if ((index < 0) || (index >= listRepPtr->elemCount)) {

    if (TclListObjGetElements(interp, listObj, &numElems, &elemObjs) != TCL_OK) {
	return TCL_ERROR;
    }
    if ((index < 0) || (index >= numElems)) {
	*objPtrPtr = NULL;
    } else {
	*objPtrPtr = (&listRepPtr->elements)[index];
	*objPtrPtr = elemObjs[index];
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjLength --
 *
 * 	Retrieve the number of elements in a list.
 *	This function returns the number of elements in a list object. If the
 *	object is not already a list object, an attempt will be made to
 *	convert it to one.
 *
 * Value
 * Results:
 *
 *	TCL_OK
 *	The return value is normally TCL_OK; in this case *lenPtr will be set
 *
 *	    A count of list elements is stored at the address provided by
 *	    'intPtr'. If 'listPtr' is not already of type 'tclListPtr', it is
 *	to the integer count of list elements. If listPtr does not refer to a
 *	list object and the object can not be converted to one, TCL_ERROR is
 *	returned and an error message will be left in the interpreter's result
 *	if interp is not NULL.
 *	    converted.
 *
 *	TCL_ERROR
 *
 *	    'listPtr' is not a valid list.  An error message will be left in
 * Side effects:
 *	The possible conversion of the argument object to a list object.
 *	    the interpreter's result if 'interp' is not NULL.
 *
 *----------------------------------------------------------------------
 */

#undef Tcl_ListObjLength
int
Tcl_ListObjLength(
    Tcl_Interp *interp,		/* Used to report errors if not NULL. */
    Tcl_Obj *listPtr,	/* List object whose #elements to return. */
    int *intPtr)	/* The resulting int is stored here. */
    Tcl_Interp *interp,	/* Used to report errors if not NULL. */
    Tcl_Obj *listObj,	/* List object whose #elements to return. */
    Tcl_Size *lenPtr)	/* The resulting length is stored here. */
{
    List *listRepPtr;
    ListRep listRep;

    /* Empty string => empty list. Avoid unnecessary shimmering */
    ListGetIntRep(listPtr, listRepPtr);
    if (listRepPtr == NULL) {
	int result;
    if (listObj->bytes == &tclEmptyString) {
	*lenPtr = 0;
	return TCL_OK;
	size_t length;

	(void) TclGetStringFromObj(listPtr, &length);
	if (length == 0) {
	    *intPtr = 0;
	    return TCL_OK;
	}
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
	ListGetIntRep(listPtr, listRepPtr);
    }
    }

    if (TclObjTypeHasProc(listObj, lengthProc)) {
	*lenPtr = TclObjTypeLength(listObj);
	return TCL_OK;
    }

    if (TclListObjGetRep(interp, listObj, &listRep) != TCL_OK) {
	return TCL_ERROR;
    }
    *lenPtr = ListRepLength(&listRep);
    return TCL_OK;
}

static Tcl_Size
ListLength(
    Tcl_Obj *listPtr)
{
    *intPtr = listRepPtr->elemCount;
    return TCL_OK;
    ListRep listRep;
    ListObjGetRep(listPtr, &listRep);

    return ListRepLength(&listRep);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjReplace --
 *
 *	Replace values in a list.
 *	This function replaces zero or more elements of the list referenced by
 *	listObj with the objects from an (objc,objv) array. The objc elements
 *	of the array referenced by objv replace the count elements in listPtr
 *	starting at first.
 *
 *	If 'first' is zero or negative, it refers to the first element. If
 *	'first' outside the range of elements in the list, no elements are
 *	deleted.
 *	If the argument first is zero or negative, it refers to the first
 *	element. If first is greater than or equal to the number of elements
 *	in the list, then no elements are deleted; the new elements are
 *
 *	If 'count' is zero or negative no elements are deleted, and any new
 *	elements are inserted at the beginning of the list.
 *	appended to the list. Count gives the number of elements to replace.
 *	If count is zero or negative then no elements are deleted; the new
 *	elements are simply inserted before first.
 *
 * Value
 *
 *	TCL_OK
 *
 *	    The first 'objc' values of 'objv' replaced 'count' elements in 'listPtr'
 *	    starting at 'first'.  If 'objc' 0, no new elements are added.
 *	The argument objv refers to an array of objc pointers to the new
 *	elements to be added to listPtr in place of those that were deleted.
 *	If objv is NULL, no new elements are added. If listPtr is not a list
 *	object, an attempt will be made to convert it to one.
 *
 * Results:
 *	The return value is normally TCL_OK. If listPtr does not refer to a
 *	TCL_ERROR
 *	list object and can not be converted to one, TCL_ERROR is returned and
 *
 *	    'listPtr' is not a valid list.   An error message is left in the
 *	    interpreter's result if 'interp' is not NULL.
 *	an error message will be left in the interpreter's result if interp is
 *	not NULL.
 *
 * Effect
 * Side effects:
 *
 *	If 'listPtr' is not of type 'tclListType', it is converted if possible.
 *
 *	The ref counts of the objc elements in objv are incremented since the
 *	The 'refCount' of each element appended to the list is incremented.
 *	Similarly, the 'refCount' for each replaced element is decremented.
 *	resulting list now refers to them. Similarly, the ref counts for
 *
 *	If 'listPtr' is modified, any previous string representation is
 *	invalidated.
 *	replaced objects are decremented. listObj is converted, if necessary,
 *	to a list object. listObj's old string representation, if any, is
 *	freed.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ListObjReplace(
    Tcl_Interp *interp,		/* Used for error reporting if not NULL. */
    Tcl_Obj *listPtr,		/* List object whose elements to replace. */
    int first,			/* Index of first element to replace. */
    int count,			/* Number of elements to replace. */
    int objc,			/* Number of objects to insert. */
    Tcl_Obj *const objv[])	/* An array of objc pointers to Tcl objects to
    Tcl_Obj *listObj,		/* List object whose elements to replace. */
    Tcl_Size first,		/* Index of first element to replace. */
    Tcl_Size numToDelete,	/* Number of elements to replace. */
    Tcl_Size numToInsert,	/* Number of objects to insert. */
    Tcl_Obj *const insertObjs[])/* Tcl objects to insert */
				 * insert. */
{
    List *listRepPtr;
    Tcl_Obj **elemPtrs;
    int needGrow, numElems, numRequired, numAfterLast, start, i, j, isShared;
    ListRep listRep;
    Tcl_Size origListLen;
    Tcl_Size lenChange;
    Tcl_Size leadSegmentLen;
    Tcl_Size tailSegmentLen;
    Tcl_Size numFreeSlots;
    Tcl_Size leadShift;
    Tcl_Size tailShift;
    Tcl_Obj **listObjs;
    int favor;

    if (Tcl_IsShared(listPtr)) {
    if (Tcl_IsShared(listObj)) {
	Tcl_Panic("%s called with shared object", "Tcl_ListObjReplace");
    }

    ListGetIntRep(listPtr, listRepPtr);
    if (listRepPtr == NULL) {
	size_t length;

    if (TclObjTypeHasProc(listObj, replaceProc)) {
	(void) TclGetStringFromObj(listPtr, &length);
	if (length == 0) {
	    if (objc == 0) {
		return TCL_OK;
	    }
	return TclObjTypeReplace(interp, listObj, first,
		numToDelete, numToInsert, insertObjs);
    }
	    Tcl_SetListObj(listPtr, objc, NULL);
	} else {
	    int result = SetListFromAny(interp, listPtr);

	    if (result != TCL_OK) {
		return result;
	    }
	}
    if (TclListObjGetRep(interp, listObj, &listRep) != TCL_OK) {
	/* Cannot be converted to a list */
	return TCL_ERROR;
    }

	ListGetIntRep(listPtr, listRepPtr);
    }

    /* Make limits sane */
    /*
     * Note that when count == 0 and objc == 0, this routine is logically a
     * no-op, removing and adding no elements to the list. However, by flowing
     * through this routine anyway, we get the important side effect that the
     * resulting listPtr is a list in canoncial form. This is important.
     * Resist any temptation to optimize this case.
     */

    origListLen = ListRepLength(&listRep);
    elemPtrs = &listRepPtr->elements;
    numElems = listRepPtr->elemCount;

    if (first < 0) {
	first = 0;
    }
    if (first >= numElems) {
	first = numElems;	/* So we'll insert after last element. */
    if (first > origListLen) {
	first = origListLen;	/* So we'll insert after last element. */
    }
    if (count < 0) {
	count = 0;
    } else if (first > INT_MAX - count /* Handle integer overflow */
	    || numElems < first+count) {

	count = numElems - first;
    if (numToDelete < 0) {
	numToDelete = 0;
    } else if (first > LIST_MAX - numToDelete /* Handle integer overflow */
	     || origListLen < first + numToDelete) {
	numToDelete = origListLen - first;
    }

    if (numToInsert > LIST_MAX - (origListLen - numToDelete)) {
	return ListLimitExceededError(interp);
    }

    if ((first+numToDelete) >= origListLen) {
	/* Operating at back of list. Favor leaving space at back */
	favor = LISTREP_SPACE_FAVOR_BACK;
    } else if (first == 0) {
	/* Operating on front of list. Favor leaving space in front */
	favor = LISTREP_SPACE_FAVOR_FRONT;
    } else {
	/* Operating on middle of list. */
	favor = LISTREP_SPACE_FAVOR_NONE;
    }

    /*

     * There are a number of special cases to consider from an optimization
    if (objc > LIST_MAX - (numElems - count)) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "max length of a Tcl list (%d elements) exceeded",
		    LIST_MAX));
     * point of view.
     * (1) Pure deletes (numToInsert==0) from the front or back can be treated
     * as a range op irrespective of whether the ListStore is shared or not
     * (2) Pure inserts (numToDelete == 0)
     *   (2a) Pure inserts at the back can be treated as appends
	}
	return TCL_ERROR;
    }
     *   (2b) Pure inserts from the *front* can be optimized under certain
     *   conditions by inserting before first ListStore slot in use if there
     *   is room, again irrespective of sharing
     * (3) If the ListStore is shared OR there is insufficient free space
     * OR existing allocation is too large compared to new size, create
     * a new ListStore
     * (4) Unshared ListStore with sufficient free space. Delete, shift and
     * insert within the ListStore.
     */

    isShared = (listRepPtr->refCount > 1);
    numRequired = numElems - count + objc; /* Known <= LIST_MAX */
    needGrow = numRequired > listRepPtr->maxElemCount;

    /* Note: do not do TclInvalidateStringRep as yet in case there are errors */
    for (i = 0;  i < objc;  i++) {
	Tcl_IncrRefCount(objv[i]);
    }

    if (needGrow && !isShared) {
	/* Try to use realloc */
	List *newPtr = NULL;
	int attempt = 2 * numRequired;
	if (attempt <= LIST_MAX) {
	    newPtr = (List *)Tcl_AttemptRealloc(listRepPtr, LIST_SIZE(attempt));

    /* Check Case (1) - Treat pure deletes from front or back as range ops */
    if (numToInsert == 0) {
	if (numToDelete == 0) {
	    /*
	     * Should force canonical even for no-op. Remember Tcl_Obj unshared
	     * so OK to invalidate string rep
	     */
	    /* T:listrep-1.10,2.8 */
	    TclInvalidateStringRep(listObj);
	    return TCL_OK;
	}
	if (first == 0) {
	    /* Delete from front, so return tail. */
	    /* T:listrep-1.{4,5},2.{4,5},3.{15,16},4.7 */
	    ListRep tailRep;
	    ListRepRange(&listRep, numToDelete, origListLen-1, 0, &tailRep);
	    ListObjReplaceRepAndInvalidate(listObj, &tailRep);
	    return TCL_OK;
	} else if ((first+numToDelete) >= origListLen) {
	    /* Delete from tail, so return head */
	    /* T:listrep-1.{8,9},2.{6,7},3.{17,18},4.8 */
	    ListRep headRep;
	    ListRepRange(&listRep, 0, first-1, 0, &headRep);
	    ListObjReplaceRepAndInvalidate(listObj, &headRep);
	    return TCL_OK;
	}
	/* Deletion from middle. Fall through to general case */
    }

    /* Garbage collect before checking the pure insert optimization */
    ListRepFreeUnreferenced(&listRep);

    /*
     * Check Case (2) - pure inserts under certain conditions:
     */
    if (numToDelete == 0) {
	/* Case (2a) - Append to list. */
	if (first == origListLen) {
	    /* T:listrep-1.11,2.9,3.{5,6},2.2.1 */
	    return TclListObjAppendElements(
		interp, listObj, numToInsert, insertObjs);
	}
	if (newPtr == NULL) {
	    attempt = numRequired + 1 + TCL_MIN_ELEMENT_GROWTH;
	    if (attempt > LIST_MAX) {
		attempt = LIST_MAX;
	    }
	    newPtr = (List *)Tcl_AttemptRealloc(listRepPtr, LIST_SIZE(attempt));

	/*
	 * Case (2b) - pure inserts at front under some circumstances
	 * (i) Insertion must be at head of list
	 * (ii) The list's span must be at head of the in-use slots in the store
	 * (iii) There must be unused room at front of the store
	}
	if (newPtr == NULL) {
	    attempt = numRequired;
	    newPtr = (List *)Tcl_AttemptRealloc(listRepPtr, LIST_SIZE(attempt));
	 * NOTE THIS IS TRUE EVEN IF THE ListStore IS SHARED as it will not
	 * affect the other Tcl_Obj's referencing this ListStore.
	 */
	if (first == 0 &&						 /* (i) */
		ListRepStart(&listRep) == listRep.storePtr->firstUsed && /* (ii) */
	}
	if (newPtr) {
	    listRepPtr = newPtr;
	    ListResetIntRep(listPtr, listRepPtr);
	    elemPtrs = &listRepPtr->elements;
	    listRepPtr->maxElemCount = attempt;
	    needGrow = numRequired > listRepPtr->maxElemCount;
		numToInsert <= listRep.storePtr->firstUsed) {		 /* (iii) */
	    Tcl_Size newLen;
	    LIST_ASSERT(numToInsert); /* Else would have returned above */
	    listRep.storePtr->firstUsed -= numToInsert;
	    ObjArrayCopy(&listRep.storePtr->slots[listRep.storePtr->firstUsed],
		    numToInsert, insertObjs);
	    listRep.storePtr->numUsed += numToInsert;
	    newLen = listRep.spanPtr->spanLength + numToInsert;
	}
    }
    if (!needGrow && !isShared) {
	int shift;

	    if (listRep.spanPtr && listRep.spanPtr->refCount <= 1) {
		/* An unshared span record, re-use it */
		/* T:listrep-3.1 */
		listRep.spanPtr->spanStart = listRep.storePtr->firstUsed;
		listRep.spanPtr->spanLength = newLen;
	    } else {
		/* Need a new span record */
		if (listRep.storePtr->firstUsed == 0) {
		    listRep.spanPtr = NULL;
		} else {
		    /* T:listrep-4.3 */
		    listRep.spanPtr =
			ListSpanNew(listRep.storePtr->firstUsed, newLen);
		}
	/*
	 * Can use the current List struct. First "delete" count elements
	 * starting at first.
	 */

	    }
	for (j = first;  j < first + count;  j++) {
	    Tcl_Obj *victimPtr = elemPtrs[j];

	    ListObjReplaceRepAndInvalidate(listObj, &listRep);
	    return TCL_OK;
	}
	    TclDecrRefCount(victimPtr);
	}
    }

    /* Just for readability of the code */
    lenChange = numToInsert - numToDelete;
    leadSegmentLen = first;
    tailSegmentLen = origListLen - (first + numToDelete);
    numFreeSlots = listRep.storePtr->numAllocated - listRep.storePtr->numUsed;

	/*
    /*
	 * Shift the elements after the last one removed to their new
	 * locations.
	 */

	start = first + count;
	numAfterLast = numElems - start;
     * Before further processing, if unshared, try and reallocate to avoid
     * new allocation below. This avoids expensive ref count manipulation
     * later by not having to go through the ListRepInit and
     * ListObjReplaceAndInvalidate below.
     * TODO - we could be smarter about the reallocate. Use of realloc
     * means all new free space is at the back. Instead, the realloc could
     * be an explicit alloc and memmove which would let us redistribute
     * free space.
     */
    if (numFreeSlots < lenChange && !ListRepIsShared(&listRep)) {
	/* T:listrep-1.{1,3,14,18,21},3.{3,10,11,14,27,32,41} */
	ListStore *newStorePtr =
	    ListStoreReallocate(listRep.storePtr, origListLen + lenChange);
	if (newStorePtr == NULL) {
	    return MemoryAllocationError(interp,
		    LIST_SIZE(origListLen + lenChange));
	}
	listRep.storePtr = newStorePtr;
	numFreeSlots =
	shift = objc - count;	/* numNewElems - numDeleted */
	if ((numAfterLast > 0) && (shift != 0)) {
	    Tcl_Obj **src = elemPtrs + start;

	    listRep.storePtr->numAllocated - listRep.storePtr->numUsed;
	/*
	 * WARNING: at this point the Tcl_Obj internal rep potentially
	 * points to freed storage if the reallocation returned a
	 * different location. Overwrite it to bring it back in sync.
	 */
	ListObjStompRep(listObj, &listRep);
    }
	    memmove(src+shift, src, numAfterLast * sizeof(Tcl_Obj*));
	}

    } else {
	/*
	 * Cannot use the current List struct; it is shared, too small, or
	 * both. Allocate a new struct and insert elements into it.
	 */

	List *oldListRepPtr = listRepPtr;
	Tcl_Obj **oldPtrs = elemPtrs;
	int newMax;

	if (needGrow) {
	    newMax = 2 * numRequired;
    /*
     * Case (3) a new ListStore is required
     * (a) The passed-in ListStore is shared
     * (b) There is not enough free space in the unshared passed-in ListStore
     * (c) The new unshared size is much "smaller" (TODO) than the allocated space
     * TODO - for unshared case ONLY, consider a "move" based implementation
     */
    if (ListRepIsShared(&listRep) ||				/* 3a */
	    numFreeSlots < lenChange ||				/* 3b */
	    (origListLen + lenChange) <
		    (listRep.storePtr->numAllocated / 4)) {	/* 3c */
	ListRep newRep;
	Tcl_Obj **toObjs;
	listObjs = &listRep.storePtr->slots[ListRepStart(&listRep)];
	ListRepInit(origListLen + lenChange, NULL,
		LISTREP_PANIC_ON_FAIL | favor, &newRep);
	toObjs = ListRepSlotPtr(&newRep, 0);
	if (leadSegmentLen > 0) {
	    /* T:listrep-2.{2,3,13:18},4.{6,9,13:18} */
	    ObjArrayCopy(toObjs, leadSegmentLen, listObjs);
	}
	if (numToInsert > 0) {
	    /* T:listrep-2.{1,2,3,10:18},4.{1,2,4,6,10:18} */
	    ObjArrayCopy(&toObjs[leadSegmentLen], numToInsert,
		    insertObjs);
	}
	if (tailSegmentLen > 0) {
	    /* T:listrep-2.{1,2,3,10:15},4.{1,2,4,6,9:12,16:18} */
	    ObjArrayCopy(&toObjs[leadSegmentLen + numToInsert],
	} else {
	    newMax = listRepPtr->maxElemCount;
		    tailSegmentLen, &listObjs[leadSegmentLen+numToDelete]);
	}
	newRep.storePtr->numUsed = origListLen + lenChange;
	if (newRep.spanPtr) {
	    /* T:listrep-2.{1,2,3,10:18},4.{1,2,4,6,9:18} */
	    newRep.spanPtr->spanLength = newRep.storePtr->numUsed;

	}
	listRepPtr = AttemptNewList(NULL, newMax, NULL);
	if (listRepPtr == NULL) {
	LISTREP_CHECK(&newRep);
	ListObjReplaceRepAndInvalidate(listObj, &newRep);
	    unsigned int limit = LIST_MAX - numRequired;
	    unsigned int extra = numRequired - numElems
		    + TCL_MIN_ELEMENT_GROWTH;
	    int growth = (int) ((extra > limit) ? limit : extra);
	return TCL_OK;
    }

    /*
     * Case (4) - unshared ListStore with sufficient room.
     * After deleting elements, there will be a corresponding gap. If this
     * gap does not match number of insertions, either the lead segment,
     * or the tail segment, or both will have to be moved.
     * The general strategy is to move the fewest number of elements. If
     *
     * TODO - what about appends to unshared ? Is below sufficiently optimal?
     */

	    listRepPtr = AttemptNewList(NULL, numRequired + growth, NULL);
	    if (listRepPtr == NULL) {
		listRepPtr = AttemptNewList(interp, numRequired, NULL);
		if (listRepPtr == NULL) {
		    for (i = 0;  i < objc;  i++) {
			/* See bug 3598580 */
			Tcl_DecrRefCount(objv[i]);
		    }
    /* Following must hold for unshared listreps after ListRepFreeUnreferenced above */
    LIST_ASSERT(origListLen == listRep.storePtr->numUsed);
    LIST_ASSERT(origListLen == ListRepLength(&listRep));
    LIST_ASSERT(ListRepStart(&listRep) == listRep.storePtr->firstUsed);

    LIST_ASSERT((numToDelete + numToInsert) > 0);

    /* Base of slot array holding the list elements */
    listObjs = &listRep.storePtr->slots[ListRepStart(&listRep)];

		    return TCL_ERROR;
		}
	    }
	}
    /*
     * Free up elements to be deleted. Before that, increment the ref counts
     * for objects to be inserted in case there is overlap. T:listobj-11.1
     */
    if (numToInsert) {
	/* T:listrep-1.{1,3,12:21},3.{2,3,7:14,23:41} */
	ObjArrayIncrRefs(insertObjs, 0, numToInsert);
    }
    if (numToDelete) {
	/* T:listrep-1.{6,7,12:21},3.{19:41} */
	ObjArrayDecrRefs(listObjs, first, numToDelete);
    }

    /*
     * TODO - below the moves are optimized but this may result in needing a
     * span allocation. Perhaps for small lists, it may be more efficient to
     * just move everything up front and save on allocating a span.
     */

    /*
     * Calculate shifts if necessary to accommodate insertions.
     * NOTE: all indices are relative to listObjs which is not necessarily the
	ListResetIntRep(listPtr, listRepPtr);
     * start of the ListStore storage area.
	listRepPtr->refCount++;

	elemPtrs = &listRepPtr->elements;
     *
     * leadShift - how much to shift the lead segment
     * tailShift - how much to shift the tail segment
     * insertTarget - index where to insert.
     */

	if (isShared) {
	    /*
    if (lenChange == 0) {
	/* T:listrep-1.{12,15,19},3.{23,28,33}. Exact fit */
	leadShift = 0;
	tailShift = 0;
    } else if (lenChange < 0) {
	/*
	     * The old struct will remain in place; need new refCounts for the
	     * new List struct references. Copy over only the surviving
	     * elements.
	     */

	 * More deletions than insertions. The gap after deletions is large
	 * enough for insertions. Move a segment depending on size.
	 */
	if (leadSegmentLen > tailSegmentLen) {
	    /* Tail segment smaller. Insert after lead, move tail down */
	    /* T:listrep-1.{7,17,20},3.{21,2229,35} */
	    leadShift = 0;
	    tailShift = lenChange;
	} else {
	    /* Lead segment smaller. Insert before tail, move lead up */
	    /* T:listrep-1.{6,13,16},3.{19,20,24,34} */
	    leadShift = -lenChange;
	    tailShift = 0;
	}
	    for (i=0; i < first; i++) {
		elemPtrs[i] = oldPtrs[i];
    } else {
		Tcl_IncrRefCount(elemPtrs[i]);
	    }
	LIST_ASSERT(lenChange > 0); /* Reminder */

	    for (i = first + count, j = first + objc;
		    j < numRequired; i++, j++) {
		elemPtrs[j] = oldPtrs[i];
		Tcl_IncrRefCount(elemPtrs[j]);
	    }

	    oldListRepPtr->refCount--;
	/*
	 * We need to make room for the insertions. Again we have multiple
	 * possibilities. We may be able to get by just shifting one segment
	 * or need to shift both. In the former case, favor shifting the
	 * smaller segment.
	 */
	Tcl_Size leadSpace = ListRepNumFreeHead(&listRep);
	Tcl_Size tailSpace = ListRepNumFreeTail(&listRep);
	Tcl_Size finalFreeSpace = leadSpace + tailSpace - lenChange;

	LIST_ASSERT((leadSpace + tailSpace) >= lenChange);
	if (leadSpace >= lenChange
		&& (leadSegmentLen < tailSegmentLen || tailSpace < lenChange)) {
	    /* Move only lead to the front to make more room */
	    /* T:listrep-3.25,36,38, */
	    leadShift = -lenChange;
	    tailShift = 0;
	} else {
	    /*
	     * Redistribute the remaining free space between the front and
	     * The old struct will be removed; use its inherited refCounts.
	     * back if either there is no tail space left or if the
	     * entire list is the head anyways. This is an important
	     * optimization for further operations like further asymmetric
	     * insertions.
	     */

	    if (first > 0) {
	    if (finalFreeSpace > 1 && (tailSpace == 0 || tailSegmentLen == 0)) {
		Tcl_Size postShiftLeadSpace = leadSpace - lenChange;
		if (postShiftLeadSpace > (finalFreeSpace/2)) {
		memcpy(elemPtrs, oldPtrs, first * sizeof(Tcl_Obj *));
	    }

		    Tcl_Size extraShift = postShiftLeadSpace - (finalFreeSpace / 2);
		    leadShift -= extraShift;
		    tailShift = -extraShift; /* Move tail to the front as well */
		}
	    } /* else T:listrep-3.{7,12,25,38} */
	    LIST_ASSERT(leadShift >= 0 || leadSpace >= -leadShift);
	} else if (tailSpace >= lenChange) {
	    /* Move only tail segment to the back to make more room. */
	    /* T:listrep-3.{8,10,11,14,26,27,30,32,37,39,41} */
	    leadShift = 0;
	    tailShift = lenChange;
	    /*
	     * "Delete" count elements starting at first.
	     * See comments above. This is analogous.
	     */
	    if (finalFreeSpace > 1 && (leadSpace == 0 || leadSegmentLen == 0)) {

	    for (j = first;  j < first + count;  j++) {
		Tcl_Obj *victimPtr = oldPtrs[j];

		TclDecrRefCount(victimPtr);
	    }

		Tcl_Size postShiftTailSpace = tailSpace - lenChange;
		if (postShiftTailSpace > (finalFreeSpace/2)) {
		    /* T:listrep-1.{1,3,14,18,21},3.{2,3,26,27} */
		    Tcl_Size extraShift = postShiftTailSpace - (finalFreeSpace / 2);
		    tailShift += extraShift;
		    leadShift = extraShift; /* Move head to the back as well */
		}
	    }
	    LIST_ASSERT(tailShift <= tailSpace);
	} else {
	    /*
	     * Copy the elements after the last one removed, shifted to their
	     * Both lead and tail need to be shifted to make room.
	     * new locations.
	     * Divide remaining free space equally between front and back.
	     */
	    /* T:listrep-3.{9,13,31,40} */
	    LIST_ASSERT(leadSpace < lenChange);
	    LIST_ASSERT(tailSpace < lenChange);

	    /*
	    start = first + count;
	    numAfterLast = numElems - start;
	    if (numAfterLast > 0) {
		memcpy(elemPtrs + first + objc, oldPtrs + start,
	     * leadShift = leadSpace - (finalFreeSpace/2)
	     * Thus leadShift <= leadSpace
	     * Also,
	     * = leadSpace - (leadSpace + tailSpace - lenChange)/2
	     * = leadSpace/2 - tailSpace/2 + lenChange/2
	     * >= 0 because lenChange > tailSpace
	     */
	    leadShift = leadSpace - (finalFreeSpace / 2);
	    tailShift = lenChange - leadShift;
	    if (tailShift > tailSpace) {
		/* Account for integer division errors */
		leadShift += 1;
			(size_t) numAfterLast * sizeof(Tcl_Obj *));
		tailShift -= 1;
	    }
	    /*
	     * Following must be true because otherwise one of the previous
	     * if clauses would have been taken.
	     */
	    LIST_ASSERT(leadShift > 0 && leadShift < lenChange);
	    LIST_ASSERT(tailShift > 0 && tailShift < lenChange);
	    leadShift = -leadShift; /* Lead is actually shifted downward */

	}
	    Tcl_Free(oldListRepPtr);
	}
    }

    }

    /* Careful about order of moves! */
    if (leadShift > 0) {
	/* Will happen when we have to make room at bottom */
	if (tailShift != 0 && tailSegmentLen != 0) {
	    /* T:listrep-1.{1,3,14,18},3.{2,3,26,27} */
	    Tcl_Size tailStart = leadSegmentLen + numToDelete;
	    memmove(&listObjs[tailStart + tailShift],
		    &listObjs[tailStart],
		    tailSegmentLen * sizeof(Tcl_Obj *));
	}
    /*
     * Insert the new elements into elemPtrs before "first".
	if (leadSegmentLen != 0) {
     */

	    /* T:listrep-1.{3,6,16,18,21},3.{19,20,34} */
	    memmove(&listObjs[leadShift],
		    &listObjs[0],
		    leadSegmentLen * sizeof(Tcl_Obj *));
	}
    for (i=0,j=first ; i<objc ; i++,j++) {
	elemPtrs[j] = objv[i];
    }

    } else {
	if (leadShift != 0 && leadSegmentLen != 0) {
	    /* T:listrep-3.{7,9,12,13,31,36,38,40} */
	    memmove(&listObjs[leadShift],
		    &listObjs[0],
		    leadSegmentLen * sizeof(Tcl_Obj *));
	}
	if (tailShift != 0 && tailSegmentLen != 0) {
	    /* T:listrep-1.{7,17},3.{8:11,13,14,21,22,35,37,39:41} */
	    Tcl_Size tailStart = leadSegmentLen + numToDelete;
	    memmove(&listObjs[tailStart + tailShift],
		    &listObjs[tailStart],
		    tailSegmentLen * sizeof(Tcl_Obj *));
	}
    /*
     * Update the count of elements.
     */

    }
    if (numToInsert) {
	/* Do NOT use ObjArrayCopy here since we have already incr'ed ref counts */
	/* T:listrep-1.{1,3,12:21},3.{2,3,7:14,23:41} */
	memmove(&listObjs[leadSegmentLen + leadShift],
		insertObjs,
		numToInsert * sizeof(Tcl_Obj *));
    }
    listRepPtr->elemCount = numRequired;

    /*
     * Invalidate and free any old representations that may not agree
     * with the revised list's internal representation.
    listRep.storePtr->firstUsed += leadShift;
    listRep.storePtr->numUsed = origListLen + lenChange;
    listRep.storePtr->flags = 0;
     */

    listRepPtr->refCount++;
    TclFreeIntRep(listPtr);
    ListSetIntRep(listPtr, listRepPtr);
    listRepPtr->refCount--;

    TclInvalidateStringRep(listPtr);
    if (listRep.spanPtr && listRep.spanPtr->refCount <= 1) {
	/* An unshared span record, re-use it, even if not required */
	/* T:listrep-3.{2,3,7:14},3.{19:41} */
	listRep.spanPtr->spanStart = listRep.storePtr->firstUsed;
	listRep.spanPtr->spanLength = listRep.storePtr->numUsed;
    } else {
	/* Need a new span record */
	if (listRep.storePtr->firstUsed == 0) {
	    /* T:listrep-1.{7,12,15,17,19,20} */
	    listRep.spanPtr = NULL;
	} else {
	    /* T:listrep-1.{1,3,6.1,13,14,16,18,21} */
	    listRep.spanPtr = ListSpanNew(listRep.storePtr->firstUsed,
		    listRep.storePtr->numUsed);
	}
    }

    LISTREP_CHECK(&listRep);
    ListObjReplaceRepAndInvalidate(listObj, &listRep);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclLindexList --
 *
 *	Implements the 'lindex' command when objc==3.
 *	This procedure handles the 'lindex' command when objc==3.
 *
 *	Implemented entirely as a wrapper around 'TclLindexFlat'. Reconfigures
 *	the argument format into required form while taking care to manage
 *	shimmering so as to tend to keep the most useful intreps
 *	and/or avoid the most expensive conversions.
 * Results:
 *	Returns a pointer to the object extracted, or NULL if an error
 *	occurred. The returned object already includes one reference count for
 *	the pointer returned.
 *
 * Value
 *
 * Side effects:
 *	None.
 *	A pointer to the specified element, with its 'refCount' incremented, or
 *	NULL if an error occurred.
 *
 * Notes
 * Notes:
 *	This procedure is implemented entirely as a wrapper around
 *	TclLindexFlat. All it does is reconfigure the argument format into the
 *	form required by TclLindexFlat, while taking care to manage shimmering
 *	in such a way that we tend to keep the most useful internalreps and/or
 *	avoid the most expensive conversions.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TclLindexList(
    Tcl_Interp *interp,		/* Tcl interpreter. */
    Tcl_Obj *listPtr,		/* List being unpacked. */
    Tcl_Obj *argPtr)		/* Index or index list. */
    Tcl_Obj *listObj,		/* List being unpacked. */
    Tcl_Obj *argObj)		/* Index or index list. */
{

    size_t index;			/* Index into the list. */
    Tcl_Size index;		/* Index into the list. */
    Tcl_Obj *indexListCopy;
    List *listRepPtr;
    Tcl_Obj **indexObjs;
    Tcl_Size numIndexObjs;

    /*
     * Determine whether argPtr designates a list or a single index. We have
     * to be careful about the order of the checks to avoid repeated
     * shimmering; if internal rep is already a list do not shimmer it.
     * shimmering; see TIP#22 and TIP#33 for the details.
     * see TIP#22 and TIP#33 for the details.
     */

    ListGetIntRep(argPtr, listRepPtr);
    if (!TclHasInternalRep(argObj, &tclListType)
	    && TclGetIntForIndexM(NULL, argObj, TCL_SIZE_MAX - 1,
    if ((listRepPtr == NULL)
	    && TclGetIntForIndexM(NULL , argPtr, (size_t)WIDE_MAX - 1, &index) == TCL_OK) {
		    &index) == TCL_OK) {
	/*
	 * argPtr designates a single index.
	 */

	return TclLindexFlat(interp, listPtr, 1, &argPtr);
	return TclLindexFlat(interp, listObj, 1, &argObj);
    }

    /*
     * Here we make a private copy of the index list argument to avoid any
     * shimmering issues that might invalidate the indices array below while
     * we are still using it. This is probably unnecessary. It does not appear
     * that any damaging shimmering is possible, and no test has been devised
     * to show any error when this private copy is not made. But it's cheap,
     * and it offers some future-proofing insurance in case the TclLindexFlat
     * implementation changes in some unexpected way, or some new form of
     * trace or callback permits things to happen that the current
     * implementation does not.
     */

    indexListCopy = TclListObjCopy(NULL, argPtr);
    indexListCopy = TclListObjCopy(NULL, argObj);
    if (indexListCopy == NULL) {
	/*
	 * argPtr designates something that is neither an index nor a
	 * well-formed list. Report the error via TclLindexFlat.
	 * The argument is neither an index nor a well-formed list.
	 * Report the error via TclLindexFlat.
	 * TODO - This is as original code. why not directly return an error?
	 */

	return TclLindexFlat(interp, listPtr, 1, &argPtr);
	return TclLindexFlat(interp, listObj, 1, &argObj);
    }

    TclListObjGetElements(interp, indexListCopy, &numIndexObjs, &indexObjs);
    ListGetIntRep(indexListCopy, listRepPtr);

    assert(listRepPtr != NULL);

    listPtr = TclLindexFlat(interp, listPtr, listRepPtr->elemCount,
    listObj = TclLindexFlat(interp, listObj, numIndexObjs, indexObjs);
		&listRepPtr->elements);
    Tcl_DecrRefCount(indexListCopy);
    return listPtr;
    return listObj;
}

/*
 *----------------------------------------------------------------------
 *
 *  TclLindexFlat --
 * TclLindexFlat --
 *
 * 	The core of the 'lindex' command, with all index
 * 	arguments presented as a flat list.
 *	This procedure is the core of the 'lindex' command, with all index
 *	arguments presented as a flat list.
 *
 *  Value
 * Results:
 *	Returns a pointer to the object extracted, or NULL if an error
 *	occurred. The returned object already includes one reference count for
 *	the pointer returned.
 *
 *	A pointer to the object extracted, with its 'refCount' incremented,  or
 *	NULL if an error occurred.  Thus, the calling code will usually do
 *	something like:
 * Side effects:
 *	None.
 *
 * Notes:
 *	The reference count of the returned object includes one reference
 *	corresponding to the pointer returned. Thus, the calling code will
 *	usually do something like:
 * 		Tcl_SetObjResult(interp, result);
 * 		Tcl_DecrRefCount(result);
 *		Tcl_SetObjResult(interp, result);
 *		Tcl_DecrRefCount(result);
 *
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TclLindexFlat(
    Tcl_Interp *interp,		/* Tcl interpreter. */
    Tcl_Obj *listPtr,		/* Tcl object representing the list. */
    int indexCount,		/* Count of indices. */
    Tcl_Obj *listObj,		/* Tcl object representing the list. */
    Tcl_Size indexCount,	/* Count of indices. */
    Tcl_Obj *const indexArray[])/* Array of pointers to Tcl objects that
				 * represent the indices in the list. */
{
    int i;
    int status;
    Tcl_Size i;

    /* Handle AbstractList as special case */
    if (TclObjTypeHasProc(listObj,indexProc)) {
	Tcl_Size listLen = TclObjTypeLength(listObj);
    Tcl_IncrRefCount(listPtr);

    for (i=0 ; i<indexCount && listPtr ; i++) {
	size_t index;
	Tcl_Size index;
	Tcl_Obj *elemObj = listObj; /* for lindex without indices return list */
	for (i=0 ; i<indexCount && listObj ; i++) {
	    if (TclGetIntForIndexM(interp, indexArray[i], /*endValue*/ listLen-1,
		    &index) == TCL_OK) {
	int listLen = 0;
	Tcl_Obj **elemPtrs = NULL, *sublistCopy;

		// TODO: ???
	    }
	/*
	 * Here we make a private copy of the current sublist, so we avoid any
	 * shimmering issues that might invalidate the elemPtr array below
	 * while we are still using it. See test lindex-8.4.
	 */

	sublistCopy = TclListObjCopy(interp, listPtr);
	Tcl_DecrRefCount(listPtr);
	listPtr = NULL;

	if (sublistCopy == NULL) {
	    if (i==0) {
		if (TclObjTypeIndex(interp, listObj, index, &elemObj) != TCL_OK) {
		    return NULL;
		}
	    } else if (index > 0) {
		// TODO: support nested lists
		Tcl_Obj *e2Obj = TclLindexFlat(interp, elemObj, 1, &indexArray[i]);
		Tcl_DecrRefCount(elemObj);
		elemObj = e2Obj;
	    }
	}
	Tcl_IncrRefCount(elemObj);
	return elemObj;
    }

	    /*
	     * The sublist is not a list at all => error.
	     */
    Tcl_IncrRefCount(listObj);

    for (i=0 ; i<indexCount && listObj ; i++) {
	Tcl_Size index, listLen = 0;
	Tcl_Obj **elemPtrs = NULL;

	status = Tcl_ListObjLength(interp, listObj, &listLen);
	if (status != TCL_OK) {
	    Tcl_DecrRefCount(listObj);
	    break;
	    return NULL;
	}
	TclListObjGetElements(NULL, sublistCopy, &listLen, &elemPtrs);

	if (TclGetIntForIndexM(interp, indexArray[i], /*endValue*/ listLen-1,
		&index) == TCL_OK) {
	    if (index >= (size_t)listLen) {
	    if (index < 0 || index >= listLen) {
		/*
		 * Index is out of range. Break out of loop with empty result.
		 * First check remaining indices for validity
		 */

		while (++i < indexCount) {
		    if (TclGetIntForIndexM(interp, indexArray[i], (size_t)WIDE_MAX - 1, &index)
			!= TCL_OK) {
			Tcl_DecrRefCount(sublistCopy);
		    if (TclGetIntForIndexM(interp, indexArray[i],
			    TCL_SIZE_MAX - 1, &index) != TCL_OK) {
			Tcl_DecrRefCount(listObj);
			return NULL;
		    }
		}
		Tcl_DecrRefCount(listObj);
		TclNewObj(listPtr);
		TclNewObj(listObj);
		Tcl_IncrRefCount(listObj);
	    } else {
		Tcl_Obj *itemObj;
		/*
		 * Extract the pointer to the appropriate element.
		 * Must set the internal rep again because it may have been
		 * changed by TclGetIntForIndexM. See test lindex-8.4.
		 */
		if (!TclHasInternalRep(listObj, &tclListType)) {
		    status = SetListFromAny(interp, listObj);
		    if (status != TCL_OK) {
			/* The list is not a list at all => error.  */
			Tcl_DecrRefCount(listObj);
			return NULL;

		    }
		listPtr = elemPtrs[index];
	    }
	    Tcl_IncrRefCount(listPtr);
	}
	Tcl_DecrRefCount(sublistCopy);
    }

    return listPtr;
		}

		ListObjGetElements(listObj, listLen, elemPtrs);
		/* increment this reference count first before decrementing
		 * just in case they are the same Tcl_Obj
		 */
		itemObj = elemPtrs[index];
		Tcl_IncrRefCount(itemObj);
		Tcl_DecrRefCount(listObj);
		/* Extract the pointer to the appropriate element. */
		listObj = itemObj;
	    }
	} else {
	    Tcl_DecrRefCount(listObj);
	    listObj = NULL;
	}
    }
    return listObj;
}

/*
 *----------------------------------------------------------------------
 *
 * TclLsetList --
 *
 *	The core of [lset] when objc == 4. Objv[2] may be either a
 *	Core of the 'lset' command when objc == 4. Objv[2] may be either a
 *	scalar index or a list of indices.
 *      It also handles 'lpop' when given a NULL value.
 *
 *	Implemented entirely as a wrapper around 'TclLindexFlat', as described
 *	for 'TclLindexList'.
 * Results:
 *	Returns the new value of the list variable, or NULL if there was an
 *	error. The returned object includes one reference count for the
 *	pointer returned.
 *
 * Value
 * Side effects:
 *	None.
 *
 *	The new list, with the 'refCount' of 'valuPtr' incremented, or NULL if
 *	there was an error.
 * Notes:
 *	This procedure is implemented entirely as a wrapper around
 *	TclLsetFlat. All it does is reconfigure the argument format into the
 *	form required by TclLsetFlat, while taking care to manage shimmering
 *	in such a way that we tend to keep the most useful internalreps and/or
 *	avoid the most expensive conversions.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TclLsetList(
    Tcl_Interp *interp,		/* Tcl interpreter. */
    Tcl_Obj *listPtr,		/* Pointer to the list being modified. */
    Tcl_Obj *indexArgPtr,	/* Index or index-list arg to 'lset'. */
    Tcl_Obj *valuePtr)		/* Value arg to 'lset' or NULL to 'lpop'. */
    Tcl_Obj *listObj,		/* Pointer to the list being modified. */
    Tcl_Obj *indexArgObj,	/* Index or index-list arg to 'lset'. */
    Tcl_Obj *valueObj)		/* Value arg to 'lset' or NULL to 'lpop'. */
{
    int indexCount = 0;		/* Number of indices in the index list. */
    Tcl_Size indexCount = 0;   /* Number of indices in the index list. */
    Tcl_Obj **indices = NULL;	/* Vector of indices in the index list. */
    Tcl_Obj *retValuePtr;	/* Pointer to the list to be returned. */
    size_t index;			/* Current index in the list - discarded. */
    Tcl_Obj *retValueObj;	/* Pointer to the list to be returned. */
    Tcl_Size index;            /* Current index in the list - discarded. */
    Tcl_Obj *indexListCopy;
    List *listRepPtr;

    /*
     * Determine whether the index arg designates a list or a single index.
     * We have to be careful about the order of the checks to avoid repeated
     * shimmering; see TIP #22 and #23 for details.
     */

    ListGetIntRep(indexArgPtr, listRepPtr);
    if (!TclHasInternalRep(indexArgObj, &tclListType)
    if (listRepPtr == NULL
	    && TclGetIntForIndexM(NULL, indexArgPtr, (size_t)WIDE_MAX - 1, &index) == TCL_OK) {
	    && TclGetIntForIndexM(NULL, indexArgObj, TCL_SIZE_MAX - 1, &index)
	/*
	 * indexArgPtr designates a single index.
		== TCL_OK) {
	if (TclObjTypeHasProc(listObj, setElementProc)) {
	    indices = &indexArgObj;
	    retValueObj = TclObjTypeSetElement(
		    interp, listObj, 1, indices, valueObj);
	    if (retValueObj) {
		Tcl_IncrRefCount(retValueObj);
	    }
	} else {
	    /* indexArgPtr designates a single index. */
	 */

	return TclLsetFlat(interp, listPtr, 1, &indexArgPtr, valuePtr);

    }
	    /* T:listrep-1.{2.1,12.1,15.1,19.1},2.{2.3,9.3,10.1,13.1,16.1}, 3.{4,5,6}.3 */
	    retValueObj = TclLsetFlat(interp, listObj, 1, &indexArgObj, valueObj);
	}

    } else {

    indexListCopy = TclListObjCopy(NULL, indexArgPtr);
    if (indexListCopy == NULL) {
	/*
	 * indexArgPtr designates something that is neither an index nor a
	 * well formed list. Report the error via TclLsetFlat.
	 */
	indexListCopy = TclListObjCopy(NULL,indexArgObj);
	if (!indexListCopy) {
	    /*
	     * indexArgPtr designates something that is neither an index nor a
	     * well formed list. Report the error via TclLsetFlat.
	     */

	return TclLsetFlat(interp, listPtr, 1, &indexArgPtr, valuePtr);
    }
    TclListObjGetElements(NULL, indexArgPtr, &indexCount, &indices);
	    retValueObj = TclLsetFlat(interp, listObj, 1, &indexArgObj, valueObj);
	} else {
	    if (TCL_OK != TclListObjGetElements(
		    interp, indexListCopy, &indexCount, &indices)) {
		Tcl_DecrRefCount(indexListCopy);
		/*
		 * indexArgPtr designates something that is neither an index nor a
		 * well formed list. Report the error via TclLsetFlat.
		 */
		retValueObj = TclLsetFlat(interp, listObj, 1, &indexArgObj, valueObj);
	    } else {

    /*
     * Let TclLsetFlat handle the actual lset'ting.
     */
		/*
		 * Let TclLsetFlat perform the actual lset operation.
		 */

    retValuePtr = TclLsetFlat(interp, listPtr, indexCount, indices, valuePtr);

    Tcl_DecrRefCount(indexListCopy);
    return retValuePtr;
		retValueObj = TclLsetFlat(interp, listObj, indexCount, indices, valueObj);
		if (indexListCopy) {
		    Tcl_DecrRefCount(indexListCopy);
		}
	    }
	}
    }
    assert (retValueObj==NULL || retValueObj->typePtr || retValueObj->bytes);
    return retValueObj;
}

/*
 *----------------------------------------------------------------------
 *
 * TclLsetFlat --
 *
 *	Core engine of the 'lset' command.
 *      It also handles 'lpop' when given a NULL value.
 *
 * Value
 *
 *	The resulting list
 * Results:
 *	Returns the new value of the list variable, or NULL if an error
 *	occurred. The returned object includes one reference count for the
 *	pointer returned.
 *
 *	    The 'refCount' of 'valuePtr' is incremented.  If 'listPtr' was not
 *	    duplicated, its 'refCount' is incremented.  The reference count of
 *	    an unduplicated object is therefore 2 (one for the returned pointer
 *	    and one for the variable that holds it).  The reference count of a
 * Side effects:
 *	On entry, the reference count of the variable value does not reflect
 *	any references held on the stack. The first action of this function is
 *	to determine whether the object is shared, and to duplicate it if it
 *	is. The reference count of the duplicate is incremented. At this
 *	    duplicate object is 1, reflecting that result is the only active
 *	    reference. The caller is expected to store the result in the
 *	    variable and decrement its reference count. (INST_STORE_* does
 *	point, the reference count will be 1 for either case, so that the
 *	    exactly this.)
 *
 *	NULL
 *	object will appear to be unshared.
 *
 *	    An error occurred.  If 'listPtr' was duplicated, the reference
 *	    count on the duplicate is decremented so that it is 0, causing any
 *	    memory allocated by this function to be freed.
 *	If an error occurs, and the object has been duplicated, the reference
 *	count on the duplicate is decremented so that it is now 0: this
 *	dismisses any memory that was allocated by this function.
 *
 *
 * Effect
 *
 *	On entry, the reference count of 'listPtr' does not reflect any
 *	If no error occurs, the reference count of the original object is
 *	references held on the stack. The first action of this function is to
 *	determine whether 'listPtr' is shared and to create a duplicate
 *	unshared copy if it is.  The reference count of the duplicate is
 *	incremented. At this point, the reference count is 1 in either case so
 *	that the object is considered unshared.
 *	incremented if the object has not been duplicated, and nothing is done
 *	to a reference count of the duplicate. Now the reference count of an
 *	unduplicated object is 2 (the returned pointer, plus the one stored in
 *	the variable). The reference count of a duplicate object is 1,
 *	reflecting that the returned pointer is the only active reference. The
 *	caller is expected to store the returned value back in the variable
 *	and decrement its reference count. (INST_STORE_* does exactly this.)
 *
 *	The unshared list is altered directly to produce the result.
 *	'TclLsetFlat' maintains a linked list of 'Tcl_Obj' values whose string
 *	representations must be spoilt by threading via 'ptr2' of the
 *	two-pointer internal representation. On entry to 'TclLsetFlat', the
 *	values of 'ptr2' are immaterial; on exit, the 'ptr2' field of any
 *	Tcl_Obj that has been modified is set to NULL.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TclLsetFlat(
    Tcl_Interp *interp,		/* Tcl interpreter. */
    Tcl_Obj *listPtr,		/* Pointer to the list being modified. */
    int indexCount,		/* Number of index args. */
    Tcl_Obj *listObj,		/* Pointer to the list being modified. */
    Tcl_Size indexCount,	/* Number of index args. */
    Tcl_Obj *const indexArray[],
				/* Index args. */
    Tcl_Obj *valuePtr)		/* Value arg to 'lset' or NULL to 'lpop'. */
    Tcl_Obj *valueObj)		/* Value arg to 'lset' or NULL to 'lpop'. */
{
    size_t index;
    int result, len;
    Tcl_Obj *subListPtr, *retValuePtr, *chainPtr;
    Tcl_ObjIntRep *irPtr;
    Tcl_Size index, len;
    int result;
    Tcl_Obj *subListObj, *retValueObj;
    Tcl_Obj *pendingInvalidates[10];
    Tcl_Obj **pendingInvalidatesPtr = pendingInvalidates;
    Tcl_Size numPendingInvalidates = 0;

    /*
     * If there are no indices, simply return the new value.  (Without
     * indices, [lset] is a synonym for [set].
     * [lpop] does not use this but protect for NULL valuePtr just in case.
     * [lpop] does not use this but protect for NULL valueObj just in case.
     */

    if (indexCount == 0) {
	if (valuePtr != NULL) {
	    Tcl_IncrRefCount(valuePtr);
	if (valueObj != NULL) {
	    Tcl_IncrRefCount(valueObj);
	}
	return valuePtr;
	return valueObj;
    }

    /*
     * If the list is shared, make a copy we can modify (copy-on-write).  We
     * use Tcl_DuplicateObj() instead of TclListObjCopy() for a few reasons:
     * 1) we have not yet confirmed listPtr is actually a list; 2) We make a
     * 1) we have not yet confirmed listObj is actually a list; 2) We make a
     * verbatim copy of any existing string rep, and when we combine that with
     * the delayed invalidation of string reps of modified Tcl_Obj's
     * implemented below, the outcome is that any error condition that causes
     * this routine to return NULL, will leave the string rep of listPtr and
     * this routine to return NULL, will leave the string rep of listObj and
     * all elements to be unchanged.
     */

    subListPtr = Tcl_IsShared(listPtr) ? Tcl_DuplicateObj(listPtr) : listPtr;
    subListObj = Tcl_IsShared(listObj) ? Tcl_DuplicateObj(listObj) : listObj;

    /*
     * Anchor the linked list of Tcl_Obj's whose string reps must be
     * invalidated if the operation succeeds.
     */

    retValuePtr = subListPtr;
    retValueObj = subListObj;
    chainPtr = NULL;
    result = TCL_OK;

    /* Allocate if static array for pending invalidations is too small */
    if (indexCount > (Tcl_Size) (sizeof(pendingInvalidates) /
	    sizeof(pendingInvalidates[0]))) {
	pendingInvalidatesPtr =
	    (Tcl_Obj **) Tcl_Alloc(indexCount * sizeof(*pendingInvalidatesPtr));
    }

    /*
     * Loop through all the index arguments, and for each one dive into the
     * appropriate sublist.
     */

    do {
	int elemCount;
	Tcl_Size elemCount;
	Tcl_Obj *parentList, **elemPtrs;

	/*
	 * Check for the possible error conditions...
	 */

	if (TclListObjGetElements(interp, subListPtr, &elemCount, &elemPtrs)
		!= TCL_OK) {
	if (TclListObjGetElements(interp, subListObj,
		&elemCount, &elemPtrs) != TCL_OK) {
	    /* ...the sublist we're indexing into isn't a list at all. */
	    result = TCL_ERROR;
	    break;
	}

	/*
	 * WARNING: the macro TclGetIntForIndexM is not safe for
	 * post-increments, avoid '*indexArray++' here.
	 */

	if (TclGetIntForIndexM(interp, *indexArray, elemCount - 1, &index)
		!= TCL_OK)  {
	if (TclGetIntForIndexM(interp, *indexArray, elemCount - 1,
		&index) != TCL_OK) {
	    /* ...the index we're trying to use isn't an index at all. */
	    result = TCL_ERROR;
	    indexArray++;
	    indexArray++; /* Why bother with this increment? TBD */
	    break;
	}
	indexArray++;

	/*
	 * Special case 0-length lists. The Tcl indexing function treat
	 * will return any value beyond length as TCL_SIZE_MAX for this
	 * case.
	 */
	if ((index == TCL_SIZE_MAX) && (elemCount == 0)) {
	    index = 0;
	}
	if (index > (size_t)elemCount
		|| (valuePtr == NULL && index >= (size_t)elemCount)) {
	if (index < 0 || index > elemCount
		|| (valueObj == NULL && index >= elemCount)) {
	    /* ...the index points outside the sublist. */
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"index \"%s\" out of range", Tcl_GetString(indexArray[-1])));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX"
			"index \"%s\" out of range", TclGetString(indexArray[-1])));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", "OUTOFRANGE", (char *)NULL);
			"OUTOFRANGE", NULL);
	    }
	    result = TCL_ERROR;
	    break;
	}

	/*
	 * No error conditions.  As long as we're not yet on the last index,
	 * determine the next sublist for the next pass through the loop, and
	 * take steps to make sure it is an unshared copy, as we intend to
	 * modify it.
	 * determine the next sublist for the next pass through the loop,
	 * and take steps to make sure it is an unshared copy, as we intend
	 * to modify it.
	 */

	if (--indexCount) {
	    parentList = subListPtr;
	    if (index == (size_t)elemCount) {
		TclNewObj(subListPtr);
	    parentList = subListObj;
	    if (index == elemCount) {
		TclNewObj(subListObj);
	    } else {
		subListPtr = elemPtrs[index];
		subListObj = elemPtrs[index];
	    }
	    if (Tcl_IsShared(subListPtr)) {
		subListPtr = Tcl_DuplicateObj(subListPtr);
	    if (Tcl_IsShared(subListObj)) {
		subListObj = Tcl_DuplicateObj(subListObj);
	    }

	    /*
	     * Replace the original elemPtr[index] in parentList with a copy
	     * we know to be unshared.  This call will also deal with the
	     * situation where parentList shares its intrep with other
	     * Tcl_Obj's.  Dealing with the shared intrep case can cause
	     * subListPtr to become shared again, so detect that case and make
	     * and store another copy.
	     * situation where parentList shares its internalrep with other
	     * Tcl_Obj's.  Dealing with the shared internalrep case can
	     * cause subListObj to become shared again, so detect that case
	     * and make and store another copy.
	     */

	    if (index == (size_t)elemCount) {
		Tcl_ListObjAppendElement(NULL, parentList, subListPtr);
	    if (index == elemCount) {
		Tcl_ListObjAppendElement(NULL, parentList, subListObj);
	    } else {
		TclListObjSetElement(NULL, parentList, index, subListPtr);
		TclListObjSetElement(NULL, parentList, index, subListObj);
	    }
	    if (Tcl_IsShared(subListPtr)) {
		subListPtr = Tcl_DuplicateObj(subListPtr);
		TclListObjSetElement(NULL, parentList, index, subListPtr);
	    if (Tcl_IsShared(subListObj)) {
		subListObj = Tcl_DuplicateObj(subListObj);
		TclListObjSetElement(NULL, parentList, index, subListObj);
	    }

	    /*
	     * The TclListObjSetElement() calls do not spoil the string rep of
	     * parentList, and that's fine for now, since all we've done so
	     * far is replace a list element with an unshared copy.  The list
	     * value remains the same, so the string rep. is still valid, and
	     * unchanged, which is good because if this whole routine returns
	     * NULL, we'd like to leave no change to the value of the lset
	     * variable.  Later on, when we set valuePtr in its proper place,
	     * then all containing lists will have their values changed, and
	     * will need their string reps spoiled.  We maintain a list of all
	     * those Tcl_Obj's (via a little intrep surgery) so we can spoil
	     * them at that time.
	     * The TclListObjSetElement() calls do not spoil the string rep
	     * of parentList, and that's fine for now, since all we've done
	     * so far is replace a list element with an unshared copy.  The
	     * list value remains the same, so the string rep. is still
	     * valid, and unchanged, which is good because if this whole
	     * routine returns NULL, we'd like to leave no change to the
	     * value of the lset variable.  Later on, when we set valueObj
	     * in its proper place, then all containing lists will have
	     * their values changed, and will need their string reps
	     * spoiled.  We maintain a list of all those Tcl_Obj's
	     * pendingInvalidatesPtr[] so we can spoil them at that time.
	     */

	    irPtr = TclFetchIntRep(parentList, &tclListType);
	    irPtr->twoPtrValue.ptr2 = chainPtr;
	    chainPtr = parentList;
	    pendingInvalidatesPtr[numPendingInvalidates] = parentList;
	    ++numPendingInvalidates;
	}
    } while (indexCount > 0);

    /*
     * Either we've detected and error condition, and exited the loop with
     * result == TCL_ERROR, or we've successfully reached the last index, and
     * we're ready to store valuePtr.  In either case, we need to clean up our
     * string spoiling list of Tcl_Obj's.
     * we're ready to store valueObj. On success, we need to invalidate
     * the string representations of intermediate lists whose contained
     * list element would have changed.
     */

    while (chainPtr) {
	Tcl_Obj *objPtr = chainPtr;
    if (result == TCL_OK) {
	while (numPendingInvalidates > 0) {
	    Tcl_Obj *objPtr;
	List *listRepPtr;

	/*
	 * Clear away our intrep surgery mess.
	 */

	irPtr = TclFetchIntRep(objPtr, &tclListType);
	    --numPendingInvalidates;
	    objPtr = pendingInvalidatesPtr[numPendingInvalidates];
	listRepPtr = (List *)irPtr->twoPtrValue.ptr1;
	chainPtr = (Tcl_Obj *)irPtr->twoPtrValue.ptr2;

	if (result == TCL_OK) {
	    if (result == TCL_OK) {

	    /*
	     * We're going to store valuePtr, so spoil string reps of all
	     * containing lists.
	     */

		/*
		 * We're going to store valueObj, so spoil string reps of all
		 * containing lists.
		 * TODO - historically, the storing of the internal rep was done
		 * because the ptr2 field of the internal rep was used to chain
		 * objects whose string rep needed to be invalidated. Now this
		 * is no longer the case, so replacing of the internal rep
		 * should not be needed. The TclInvalidateStringRep should
		 * suffice. Formulate a test case before changing.
		 */
		ListRep objInternalRep;
		TclListObjGetRep(NULL, objPtr, &objInternalRep);
		ListObjReplaceRepAndInvalidate(objPtr, &objInternalRep);
	    }
	    listRepPtr->refCount++;
	    TclFreeIntRep(objPtr);
	    ListSetIntRep(objPtr, listRepPtr);
	    listRepPtr->refCount--;

	}
	    TclInvalidateStringRep(objPtr);
	} else {
	    irPtr->twoPtrValue.ptr2 = NULL;
	}
    }

    if (pendingInvalidatesPtr != pendingInvalidates) {
	Tcl_Free(pendingInvalidatesPtr);
    }

    if (result != TCL_OK) {
	/*
	 * Error return; message is already in interp. Clean up any excess
	 * memory.
	 */

	if (retValuePtr != listPtr) {
	    Tcl_DecrRefCount(retValuePtr);
	if (retValueObj != listObj) {
	    Tcl_DecrRefCount(retValueObj);
	}
	return NULL;
    }

    /*
     * Store valuePtr in proper sublist and return. The -1 is to avoid a
     * Store valueObj in proper sublist and return. The -1 is to avoid a
     * compiler warning (not a problem because we checked that we have a
     * proper list - or something convertible to one - above).
     */

    len = -1;
    TclListObjLength(NULL, subListPtr, &len);
    if (valuePtr == NULL) {
	Tcl_ListObjReplace(NULL, subListPtr, index, 1, 0, NULL);
    } else if (index == (size_t)len) {
	Tcl_ListObjAppendElement(NULL, subListPtr, valuePtr);
    TclListObjLength(NULL, subListObj, &len);
    if (valueObj == NULL) {
	/* T:listrep-1.{4.2,5.4,6.1,7.1,8.3},2.{4,5}.4 */
	Tcl_ListObjReplace(NULL, subListObj, index, 1, 0, NULL);
    } else if (index == len) {
	/* T:listrep-1.2.1,2.{2.3,9.3},3.{4,5,6}.3 */
	Tcl_ListObjAppendElement(NULL, subListObj, valueObj);
    } else {
	/* T:listrep-1.{12.1,15.1,19.1},2.{10,13,16}.1 */
	TclListObjSetElement(NULL, subListPtr, index, valuePtr);
	TclInvalidateStringRep(subListPtr);
	TclListObjSetElement(NULL, subListObj, index, valueObj);
	TclInvalidateStringRep(subListObj);
    }
    Tcl_IncrRefCount(retValuePtr);
    return retValuePtr;
    Tcl_IncrRefCount(retValueObj);
    return retValueObj;
}

/*
 *----------------------------------------------------------------------
 *
 * TclListObjSetElement --
 *
 *	Set a single element of a list to a specified value.
 *	Set a single element of a list to a specified value
 *
 *	It is the caller's responsibility to invalidate the string
 *	representation of the 'listPtr'.
 *
 * Value
 * Results:
 *
 * 	TCL_OK
 *	The return value is normally TCL_OK. If listObj does not refer to a
 *
 *	    Success.
 *
 *	TCL_ERROR
 *
 *	    'listPtr' does not refer to a list object and cannot be converted
 *	    to one.  An error message will be left in the interpreter result if
 *	    interp is not NULL.
 *	list object and cannot be converted to one, TCL_ERROR is returned and
 *	an error message will be left in the interpreter result if interp is
 *	not NULL. Similarly, if index designates an element outside the range
 *
 *	TCL_ERROR
 *	[0..listLength-1], where listLength is the count of elements in the
 *	list object designated by listObj, TCL_ERROR is returned and an error
 *	message is left in the interpreter result.
 *
 * Side effects:
 *	    An index designates an element outside the range [0..listLength-1],
 *	    where 'listLength' is the count of elements in the list object
 *	    designated by 'listPtr'.  An error message is left in the
 *	Tcl_Panic if listObj designates a shared object. Otherwise, attempts
 *	to convert it to a list with a non-shared internal rep. Decrements the
 *	ref count of the object at the specified index within the list,
 *	replaces with the object designated by valueObj, and increments the
 *	    interpreter result.
 *	ref count of the replacement object.
 *
 * Effect
 *
 *	If 'listPtr' designates a shared object, 'Tcl_Panic' is called.  If
 *	'listPtr' is not already of type 'tclListType', it is converted and the
 *	internal representation is unshared. The 'refCount' of the element at
 *	'index' is decremented and replaced in the list with the 'valuePtr',
 *	whose 'refCount' in turn is incremented.
 *
 *
 *----------------------------------------------------------------------
 */

int
TclListObjSetElement(
    Tcl_Interp *interp,		/* Tcl interpreter; used for error reporting
				 * if not NULL. */
    Tcl_Obj *listPtr,		/* List object in which element should be
    Tcl_Obj *listObj,		/* List object in which element should be
				 * stored. */
    int index,			/* Index of element to store. */
    Tcl_Obj *valuePtr)		/* Tcl object to store in the designated list
    Tcl_Size index,		/* Index of element to store. */
    Tcl_Obj *valueObj)		/* Tcl object to store in the designated list
				 * element. */
{
    ListRep listRep;
    Tcl_Obj **elemPtrs;         /* Pointers to elements of the list. */
    Tcl_Size elemCount;		/* Number of elements in the list. */
    List *listRepPtr;		/* Internal representation of the list being
				 * modified. */
    Tcl_Obj **elemPtrs;		/* Pointers to elements of the list. */
    int elemCount;		/* Number of elements in the list. */

    /*
     * Ensure that the listPtr parameter designates an unshared list.
    /* Ensure that the listObj parameter designates an unshared list. */
     */

    if (Tcl_IsShared(listPtr)) {
    if (Tcl_IsShared(listObj)) {
	Tcl_Panic("%s called with shared object", "TclListObjSetElement");
    }

    ListGetIntRep(listPtr, listRepPtr);
    if (listRepPtr == NULL) {
	int result;
	size_t length;

    if (TclListObjGetRep(interp, listObj, &listRep) != TCL_OK) {
	(void) TclGetStringFromObj(listPtr, &length);
	if (length == 0) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"index \"%d\" out of range", index));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX",
			"OUTOFRANGE", NULL);
	    }
	    return TCL_ERROR;
	}
	return TCL_ERROR;
    }
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}

	ListGetIntRep(listPtr, listRepPtr);
    }

    elemCount = listRepPtr->elemCount;
    elemCount = ListRepLength(&listRep);

    /*
     * Ensure that the index is in bounds.
    /* Ensure that the index is in bounds. */
     */

    if ((index < 0) || (index >= elemCount)) {
    if (index<0 || index>=elemCount) {
	if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"index \"%d\" out of range", index));
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX",
			"index \"%" TCL_SIZE_MODIFIER "d\" out of range", index));
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", "OUTOFRANGE", (char *)NULL);
		    "OUTOFRANGE", NULL);
	}
	return TCL_ERROR;
    }

    /*
     * If the internal rep is shared, replace it with an unshared copy.
     * Note - garbage collect this only AFTER checking indices above.
     * Do not want to modify listrep and then not store it back in listObj.
     */
    ListRepFreeUnreferenced(&listRep);

    /* Replace a shared internal rep with an unshared copy */
    if (listRepPtr->refCount > 1) {
	Tcl_Obj **dst, **src = &listRepPtr->elements;
    if (listRep.storePtr->refCount > 1) {
	ListRep newInternalRep;
	List *newPtr = AttemptNewList(NULL, listRepPtr->maxElemCount, NULL);

	/* T:listrep-2.{10,13,16}.1 */
	if (newPtr == NULL) {
	    newPtr = AttemptNewList(interp, elemCount, NULL);
	    if (newPtr == NULL) {
		return TCL_ERROR;
	    }
	}
	newPtr->refCount++;
	newPtr->elemCount = elemCount;
	newPtr->canonicalFlag = listRepPtr->canonicalFlag;

	/* TODO - leave extra space? */
	dst = &newPtr->elements;
	while (elemCount--) {
	    *dst = *src++;
	    Tcl_IncrRefCount(*dst++);
	}

	listRepPtr->refCount--;

	ListRepClone(&listRep, &newInternalRep, LISTREP_PANIC_ON_FAIL);
	listRep = newInternalRep;
    } /* else T:listrep-1.{12.1,15.1,19.1} */
	listRepPtr = newPtr;
	ListResetIntRep(listPtr, listRepPtr);
    }
    elemPtrs = &listRepPtr->elements;

    /*
     * Add a reference to the new list element.
     */

    Tcl_IncrRefCount(valuePtr);
    /* Retrieve element array AFTER potential cloning above */
    ListRepElements(&listRep, elemCount, elemPtrs);

    /*
     * Remove a reference from the old list element.
     * Add a reference to the new list element and remove from old before
     * replacing it. Order is important!
     */

    Tcl_IncrRefCount(valueObj);
    Tcl_DecrRefCount(elemPtrs[index]);

    /*
     * Stash the new object in the list.
     */

    elemPtrs[index] = valuePtr;
    elemPtrs[index] = valueObj;

    /*
     * Invalidate outdated intreps.
     */

    /* Internal rep may be cloned so replace */
    ListGetIntRep(listPtr, listRepPtr);
    listRepPtr->refCount++;
    TclFreeIntRep(listPtr);
    ListSetIntRep(listPtr, listRepPtr);
    listRepPtr->refCount--;

    ListObjReplaceRepAndInvalidate(listObj, &listRep);
    TclInvalidateStringRep(listPtr);

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * FreeListInternalRep --
 *
 *	Deallocate the storage associated with the internal representation of a
 *	a list object.
 *	Deallocate the storage associated with a list object's internal
 *	representation.
 *
 * Effect
 * Results:
 *	None.
 *
 * Side effects:
 *	Frees listPtr's List* internal representation, if no longer shared.
 *	May decrement the ref counts of element objects, which may free them.
 *
 *----------------------------------------------------------------------
 */

static void
FreeListInternalRep(
    Tcl_Obj *listPtr)		/* List object with internal rep to free. */
    Tcl_Obj *listObj)		/* List object with internal rep to free. */
{
    List *listRepPtr;
    ListRep listRep;

    ListGetIntRep(listPtr, listRepPtr);
    assert(listRepPtr != NULL);

    if (listRepPtr->refCount-- <= 1) {
	Tcl_Obj **elemPtrs = &listRepPtr->elements;
	int i, numElems = listRepPtr->elemCount;

    ListObjGetRep(listObj, &listRep);
    if (listRep.storePtr->refCount-- <= 1) {
	ObjArrayDecrRefs(
	    listRep.storePtr->slots,
	    listRep.storePtr->firstUsed, listRep.storePtr->numUsed);
	for (i = 0;  i < numElems;  i++) {
	    Tcl_DecrRefCount(elemPtrs[i]);
	}
	Tcl_Free(listRepPtr);
	Tcl_Free(listRep.storePtr);
    }
    if (listRep.spanPtr) {
	ListSpanDecrRefs(listRep.spanPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * DupListInternalRep --
 *
 *	Initialize the internal representation of a list 'Tcl_Obj' to share the
 *	Initialize the internal representation of a list Tcl_Obj to share the
 *	internal representation of an existing list object.
 *
 * Effect
 * Results:
 *	None.
 *
 * Side effects:
 *	The 'refCount' of the List internal rep is incremented.
 *	The reference count of the List internal rep is incremented.
 *
 *----------------------------------------------------------------------
 */

static void
DupListInternalRep(
    Tcl_Obj *srcPtr,		/* Object with internal rep to copy. */
    Tcl_Obj *copyPtr)		/* Object with internal rep to set. */
    Tcl_Obj *srcObj,		/* Object with internal rep to copy. */
    Tcl_Obj *copyObj)		/* Object with internal rep to set. */
{
    List *listRepPtr;

    ListRep listRep;
    ListObjGetRep(srcObj, &listRep);
    ListGetIntRep(srcPtr, listRepPtr);
    assert(listRepPtr != NULL);
    ListObjOverwriteRep(copyObj, &listRep);
    ListSetIntRep(copyPtr, listRepPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * SetListFromAny --
 *
 *	Convert any object to a list.
 *	Attempt to generate a list internal form for the Tcl object "objPtr".
 *
 * Value
 * Results:
 *
 *    TCL_OK
 *	The return value is TCL_OK or TCL_ERROR. If an error occurs during
 *
 *	Success.  The internal representation of 'objPtr' is set, and the type
 *	conversion, an error message is left in the interpreter's result
 *	of 'objPtr' is 'tclListType'.
 *	unless "interp" is NULL.
 *
 *    TCL_ERROR
 * Side effects:
 *
 *	An error occured during conversion. An error message is left in the
 *	If no error occurs, a list is stored as "objPtr"s internal
 *	interpreter's result if 'interp' is not NULL.
 *
 *	representation.
 *
 *----------------------------------------------------------------------
 */

static int
SetListFromAny(
    Tcl_Interp *interp,		/* Used for error reporting if not NULL. */
    Tcl_Obj *objPtr)		/* The object to convert. */
{
    List *listRepPtr;
    Tcl_Obj **elemPtrs;
    ListRep listRep;

    /*
     * Dictionaries are a special case; they have a string representation such
     * that *all* valid dictionaries are valid lists. Hence we can convert
     * more directly. Only do this when there's no existing string rep; if
     * there is, it is the string rep that's authoritative (because it could
     * describe duplicate keys).
     */

    if (!TclHasStringRep(objPtr) && TclHasIntRep(objPtr, &tclDictType)) {
    if (!TclHasStringRep(objPtr) && TclHasInternalRep(objPtr, &tclDictType)) {
	Tcl_Obj *keyPtr, *valuePtr;
	Tcl_DictSearch search;
	int done, size;
	int done;
	Tcl_Size size;

	/*
	 * Create the new list representation. Note that we do not need to do
	 * anything with the string representation as the transformation (and
	 * the reverse back to a dictionary) are both order-preserving. Also
	 * note that since we know we've got a valid dictionary (by
	 * representation) we also know that fetching the size of the
	 * dictionary or iterating over it will not fail.
	 */

	Tcl_DictObjSize(NULL, objPtr, &size);
	/* TODO - leave space in front and/or back? */
	listRepPtr = AttemptNewList(interp, size > 0 ? 2*size : 1, NULL);
	if (!listRepPtr) {
	if (ListRepInitAttempt(interp, size > 0 ? 2 * size : 1, NULL,
		&listRep) != TCL_OK) {
	    return TCL_ERROR;
	}
	listRepPtr->elemCount = 2 * size;

	LIST_ASSERT(listRep.spanPtr == NULL); /* Guard against future changes */
	LIST_ASSERT(listRep.storePtr->firstUsed == 0);
	LIST_ASSERT((listRep.storePtr->flags & LISTSTORE_CANONICAL) == 0);

	listRep.storePtr->numUsed = 2 * size;
	/*
	 * Populate the list representation.

	/* Populate the list representation. */
	 */

	elemPtrs = &listRepPtr->elements;
	elemPtrs = listRep.storePtr->slots;
	Tcl_DictObjFirst(NULL, objPtr, &search, &keyPtr, &valuePtr, &done);
	while (!done) {
	    *elemPtrs++ = keyPtr;
	    *elemPtrs++ = valuePtr;
	    Tcl_IncrRefCount(keyPtr);
	    Tcl_IncrRefCount(valuePtr);
	    Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done);
	}
    } else if (TclObjTypeHasProc(objPtr,indexProc)) {
	Tcl_Size elemCount, i;

	elemCount = TclObjTypeLength(objPtr);

	if (ListRepInitAttempt(interp, elemCount, NULL, &listRep) != TCL_OK) {
	    return TCL_ERROR;
	}

	LIST_ASSERT(listRep.spanPtr == NULL); /* Guard against future changes */
	LIST_ASSERT(listRep.storePtr->firstUsed == 0);

	elemPtrs = listRep.storePtr->slots;

	/* Each iteration, store a list element */
	for (i = 0; i < elemCount; i++) {
	    if (TclObjTypeIndex(interp, objPtr, i, elemPtrs) != TCL_OK) {
		return TCL_ERROR;
	    }
	    Tcl_IncrRefCount(*elemPtrs++);/* Since list now holds ref to it. */
	}

	LIST_ASSERT((Tcl_Size)(elemPtrs - listRep.storePtr->slots) == elemCount);

	listRep.storePtr->numUsed = elemCount;

    } else {
	int estCount;
	Tcl_Size estCount, length;
	size_t length;
	const char *limit, *nextElem = TclGetStringFromObj(objPtr, &length);

	/*
	 * Allocate enough space to hold a (Tcl_Obj *) for each
	 * (possible) list element.
	 */

	estCount = TclMaxListLength(nextElem, length, &limit);
	estCount += (estCount == 0);	/* Smallest list struct holds 1
					 * element. */
	/* TODO - allocate additional space? */
	listRepPtr = AttemptNewList(interp, estCount, NULL);
	if (ListRepInitAttempt(interp, estCount, NULL, &listRep) != TCL_OK) {
	if (listRepPtr == NULL) {
	    return TCL_ERROR;
	}
	elemPtrs = &listRepPtr->elements;

	LIST_ASSERT(listRep.spanPtr == NULL); /* Guard against future changes */
	LIST_ASSERT(listRep.storePtr->firstUsed == 0);

	elemPtrs = listRep.storePtr->slots;
	/*
	 * Each iteration, parse and store a list element.

	/* Each iteration, parse and store a list element. */
	 */

	while (nextElem < limit) {
	    const char *elemStart;
	    char *check;
	    size_t elemSize;
	    Tcl_Size elemSize;
	    int literal;

	    if (TCL_OK != TclFindElement(interp, nextElem, limit - nextElem,
		    &elemStart, &nextElem, &elemSize, &literal)) {
	    fail:
		while (--elemPtrs >= &listRepPtr->elements) {
		while (--elemPtrs >= listRep.storePtr->slots) {
		    Tcl_DecrRefCount(*elemPtrs);
		}
		Tcl_Free(listRepPtr);
		Tcl_Free(listRep.storePtr);
		return TCL_ERROR;
	    }
	    if (elemStart == limit) {
		break;
	    }

	    TclNewObj(*elemPtrs);
	    TclInvalidateStringRep(*elemPtrs);
	    check = Tcl_InitStringRep(*elemPtrs, literal ? elemStart : NULL,
		    elemSize);
	    if (elemSize && check == NULL) {
		if (interp) {
		MemoryAllocationError(interp, elemSize);
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "cannot construct list, out of memory", -1));
		    Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
		}
		goto fail;
	    }
	    if (!literal) {
		Tcl_InitStringRep(*elemPtrs, NULL,
			TclCopyAndCollapse(elemSize, elemStart, check));
	    }

	    Tcl_IncrRefCount(*elemPtrs++);/* Since list now holds ref to it. */
	}

	listRep.storePtr->numUsed =
 	listRepPtr->elemCount = elemPtrs - &listRepPtr->elements;
	    elemPtrs - listRep.storePtr->slots;
    }

    LISTREP_CHECK(&listRep);

    /*
     * Store the new internalRep. We do this as late
     * as possible to allow the conversion code, in particular
     * Tcl_GetStringFromObj, to use the old internalRep.
     */

    /*
     * Note old string representation NOT to be invalidated.
     * So do NOT use ListObjReplaceRepAndInvalidate. InternalRep to be freed AFTER
     * IncrRefs so do not use ListObjOverwriteRep
     */
    ListRepIncrRefs(&listRep);
    ListSetIntRep(objPtr, listRepPtr);
    TclFreeInternalRep(objPtr);
    objPtr->internalRep.twoPtrValue.ptr1 = listRep.storePtr;
    objPtr->internalRep.twoPtrValue.ptr2 = listRep.spanPtr;
    objPtr->typePtr = &tclListType;

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * UpdateStringOfList --
 *
 *	Update the string representation for a list object.
 *
 *	Any previously-exising string representation is not invalidated, so
 *	Any previously-existing string representation is not invalidated, so
 *	storage is lost if this has not been taken care of.
 *
 * Effect
 *
 *	The string representation of 'listPtr' is set to the resulting string.
 *	This string will be empty if the list has no elements. It is assumed
 *	that the list internal representation is not NULL.
 *
 *----------------------------------------------------------------------
 */

static void
UpdateStringOfList(
    Tcl_Obj *listPtr)		/* List object with string rep to update. */
    Tcl_Obj *listObj)		/* List object with string rep to update. */
{
#   define LOCAL_SIZE 64
    char localFlags[LOCAL_SIZE], *flagPtr = NULL;
    int numElems, i;
    size_t length, bytesNeeded = 0;
    Tcl_Size numElems, i, length;
    size_t bytesNeeded = 0;
    const char *elem, *start;
    char *dst;
    Tcl_Obj **elemPtrs;
    List *listRepPtr;
    ListRep listRep;

    ListGetIntRep(listPtr, listRepPtr);

    assert(listRepPtr != NULL);
    ListObjGetRep(listObj, &listRep);
    LISTREP_CHECK(&listRep);

    numElems = listRepPtr->elemCount;
    ListRepElements(&listRep, numElems, elemPtrs);

    /*
     * Mark the list as being canonical; although it will now have a string
     * rep, it is one we derived through proper "canonical" quoting and so
     * it's known to be free from nasties relating to [concat] and [eval].
     * However, we only do this if
     *
     * (a) the store is not shared as a shared store may be referenced by
     * multiple lists with different string reps. (see [a366c6efee]), AND
     *
     * (b) list does not have a span. Consider a list generated from a
     * string and then this function called for a spanned list generated
     * from the original list. We cannot mark the list store as canonical as
     * that would also make the originating list canonical, which it may not
     * be. On the other hand, the spanned list itself is always canonical
     * (never generated from a string) so it does not have to be explicitly
     * marked as such. The ListObjIsCanonical macro takes this into account.
     * See the comments there.
     */
    if (listRep.storePtr->refCount < 2 && listRep.spanPtr == NULL) {
	LIST_ASSERT(listRep.storePtr->firstUsed == 0);/* Invariant */
	listRep.storePtr->flags |= LISTSTORE_CANONICAL;

    }
    listRepPtr->canonicalFlag = 1;

    /*
     * Handle empty list case first, so rest of the routine is simpler.
    /* Handle empty list case first, so rest of the routine is simpler. */
     */

    if (numElems == 0) {
	Tcl_InitStringRep(listPtr, NULL, 0);
	Tcl_InitStringRep(listObj, NULL, 0);
	return;
    }

    /*
     * Pass 1: estimate space, gather flags.
    /* Pass 1: estimate space, gather flags. */
     */

    if (numElems <= LOCAL_SIZE) {
	flagPtr = localFlags;
    } else {
	/*
	 * We know numElems <= LIST_MAX, so this is safe.
	/* We know numElems <= LIST_MAX, so this is safe. */
	 */

	flagPtr = (char *)Tcl_Alloc(numElems);
    }
    elemPtrs = &listRepPtr->elements;
    for (i = 0; i < numElems; i++) {
	flagPtr[i] = (i ? TCL_DONT_QUOTE_HASH : 0);
	elem = TclGetStringFromObj(elemPtrs[i], &length);
	bytesNeeded += TclScanElement(elem, length, flagPtr+i);
	if (bytesNeeded > SIZE_MAX - numElems) {
	    Tcl_Panic("max size for a Tcl value (%" TCL_Z_MODIFIER "u bytes) exceeded", SIZE_MAX);
	}
    }
    bytesNeeded += numElems - 1;

    /*
     * Pass 2: copy into string rep buffer.
     */

    start = dst = Tcl_InitStringRep(listPtr, NULL, bytesNeeded);
    start = dst = Tcl_InitStringRep(listObj, NULL, bytesNeeded);
    TclOOM(dst, bytesNeeded);
    for (i = 0; i < numElems; i++) {
	flagPtr[i] |= (i ? TCL_DONT_QUOTE_HASH : 0);
	elem = TclGetStringFromObj(elemPtrs[i], &length);
	dst += TclConvertElement(elem, length, dst, flagPtr[i]);
	*dst++ = ' ';
    }

    /* Set the string length to what was actually written, the safe choice */
    (void) Tcl_InitStringRep(listPtr, NULL, dst - 1 - start);
    (void) Tcl_InitStringRep(listObj, NULL, dst - 1 - start);

    if (flagPtr != localFlags) {
	Tcl_Free(flagPtr);
    }
}

/*
 *------------------------------------------------------------------------
 *
 * TclListTestObj --
 *
 *    Returns a list object with a specific internal rep and content.
 *    Used specifically for testing so span can be controlled explicitly.
 *
 * Results:
 *    Pointer to the Tcl_Obj containing the list.
 *
 * Side effects:
 *    None.
 *
 *------------------------------------------------------------------------
 */
Tcl_Obj *
TclListTestObj(
    size_t length,
    size_t leadingSpace,
    size_t endSpace)
{
    ListRep listRep;
    size_t capacity;
    Tcl_Obj *listObj;

    TclNewObj(listObj);

    /* Only a test object so ignoring overflow checks */
    capacity = length + leadingSpace + endSpace;
    if (capacity == 0) {
	return listObj;
    }
    if (capacity > LIST_MAX) {
	return NULL;
    }

    ListRepInit(capacity, NULL, LISTREP_PANIC_ON_FAIL, &listRep);

    ListStore *storePtr = listRep.storePtr;
    size_t i;
    for (i = 0; i < length; ++i) {
	TclNewUIntObj(storePtr->slots[i + leadingSpace], i);
	Tcl_IncrRefCount(storePtr->slots[i + leadingSpace]);
    }
    storePtr->firstUsed = leadingSpace;
    storePtr->numUsed = length;
    if (leadingSpace != 0) {
	listRep.spanPtr = ListSpanNew(leadingSpace, length);
    }
    ListObjReplaceRepAndInvalidate(listObj, &listRep);
    return listObj;
}

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

Changes to generic/tclLiteral.c.

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
30
31

32
33
34
35
36
37
38
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
30

31
32
33
34
35
36
37
38









-
-
+
+



















-
+







/*
 * tclLiteral.c --
 *
 *	Implementation of the global and ByteCode-local literal tables used to
 *	manage the Tcl objects created for literal values during compilation
 *	of Tcl scripts. This implementation borrows heavily from the more
 *	general hashtable implementation of Tcl hash tables that appears in
 *	tclHash.c.
 *
 * Copyright (c) 1997-1998 Sun Microsystems, Inc.
 * Copyright (c) 2004 by Kevin B. Kenny.  All rights reserved.
 * Copyright © 1997-1998 Sun Microsystems, Inc.
 * Copyright © 2004 Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclCompile.h"

/*
 * When there are this many entries per bucket, on average, rebuild a
 * literal's hash table to make it larger.
 */

#define REBUILD_MULTIPLIER	3

/*
 * Function prototypes for static functions in this file:
 */

static int		AddLocalLiteralEntry(CompileEnv *envPtr,
static size_t		AddLocalLiteralEntry(CompileEnv *envPtr,
			    Tcl_Obj *objPtr, int localHash);
static void		ExpandLocalLiteralArray(CompileEnv *envPtr);
static size_t		HashString(const char *string, size_t length);
#ifdef TCL_COMPILE_DEBUG
static LiteralEntry *	LookupLiteralEntry(Tcl_Interp *interp,
			    Tcl_Obj *objPtr);
#endif
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
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







-
-
-
+
+
+














-
+














-
+







 */

Tcl_Obj *
TclCreateLiteral(
    Interp *iPtr,
    const char *bytes,	/* The start of the string. Note that this is
				 * not a NUL-terminated string. */
    size_t length,		/* Number of bytes in the string. */
    size_t hash,		/* The string's hash. If -1, it will be
				 * computed here. */
    Tcl_Size length,	/* Number of bytes in the string. */
    size_t hash, /* The string's hash. If the value is
					 * TCL_INDEX_NONE, it will be computed here. */
    int *newPtr,
    Namespace *nsPtr,
    int flags,
    LiteralEntry **globalPtrPtr)
{
    LiteralTable *globalTablePtr = &iPtr->literalTable;
    LiteralEntry *globalPtr;
    size_t globalHash;
    Tcl_Obj *objPtr;

    /*
     * Is it in the interpreter's global literal table?
     */

    if (hash == TCL_INDEX_NONE) {
    if (hash == (size_t) TCL_INDEX_NONE) {
	hash = HashString(bytes, length);
    }
    globalHash = (hash & globalTablePtr->mask);
    for (globalPtr=globalTablePtr->buckets[globalHash] ; globalPtr!=NULL;
	    globalPtr = globalPtr->nextPtr) {
	objPtr = globalPtr->objPtr;
	if (globalPtr->nsPtr == nsPtr) {
	    /*
	     * Literals should always have UTF-8 representations... but this
	     * is not guaranteed so we need to be careful anyway.
	     *
	     * https://stackoverflow.com/q/54337750/301832
	     */

	    size_t objLength;
	    Tcl_Size objLength;
	    const char *objBytes = TclGetStringFromObj(objPtr, &objLength);

	    if ((objLength == length) && ((length == 0)
		    || ((objBytes[0] == bytes[0])
		    && (memcmp(objBytes, bytes, length) == 0)))) {
		/*
		 * A literal was found: return it
347
348
349
350
351
352
353
354

355
356
357

358
359
360
361
362
363
364
347
348
349
350
351
352
353

354
355
356

357
358
359
360
361
362
363
364







-
+


-
+







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

Tcl_Obj *
TclFetchLiteral(
    CompileEnv *envPtr,		/* Points to the CompileEnv from which to
				 * fetch the registered literal value. */
    size_t index)		/* Index of the desired literal, as returned
    Tcl_Size index)		/* Index of the desired literal, as returned
				 * by prior call to TclRegisterLiteral() */
{
    if (index >= (size_t) envPtr->literalArrayNext) {
    if (index >= envPtr->literalArrayNext) {
	return NULL;
    }
    return envPtr->literalArrayPtr[index].objPtr;
}

/*
 *----------------------------------------------------------------------
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
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







-
+






-
+





-
+











-
+







 *	is set directly from string, otherwise the string is freed. Typically,
 *	a caller sets LITERAL_ON_HEAP if "string" is an already heap-allocated
 *	buffer holding the result of backslash substitutions.
 *
 *----------------------------------------------------------------------
 */

int
int /* Do NOT change this type. Should not be wider than TclEmitPush operand*/
TclRegisterLiteral(
    void *ePtr,		/* Points to the CompileEnv in whose object
				 * array an object is found or created. */
    const char *bytes,	/* Points to string for which to find or
				 * create an object in CompileEnv's object
				 * array. */
    size_t length,			/* Number of bytes in the string. If -1, the
    Tcl_Size length,			/* Number of bytes in the string. If -1, the
				 * string consists of all bytes up to the
				 * first null character. */
    int flags)			/* If LITERAL_ON_HEAP then the caller already
				 * malloc'd bytes and ownership is passed to
				 * this function. If LITERAL_CMD_NAME then
				 * the literal should not be shared accross
				 * the literal should not be shared across
				 * namespaces. */
{
    CompileEnv *envPtr = (CompileEnv *)ePtr;
    Interp *iPtr = envPtr->iPtr;
    LiteralTable *localTablePtr = &envPtr->localLitTable;
    LiteralEntry *globalPtr, *localPtr;
    Tcl_Obj *objPtr;
    size_t hash, localHash, objIndex;
    int isNew;
    Namespace *nsPtr;

    if (length == TCL_INDEX_NONE) {
    if (length < 0) {
	length = (bytes ? strlen(bytes) : 0);
    }
    hash = HashString(bytes, length);

    /*
     * Is the literal already in the CompileEnv's local literal array? If so,
     * just return its index.
433
434
435
436
437
438
439



440
441
442
443
444
445
446

447
448
449
450
451
452
453
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448

449
450
451
452
453
454
455
456







+
+
+






-
+







		Tcl_Free((void *)bytes);
	    }
	    objIndex = (localPtr - envPtr->literalArrayPtr);
#ifdef TCL_COMPILE_DEBUG
	    TclVerifyLocalLiteralTable(envPtr);
#endif /*TCL_COMPILE_DEBUG*/

	    if (objIndex > INT_MAX) {
		Tcl_Panic("Literal table index too large. Cannot be handled by TclEmitPush");
	    }
	    return objIndex;
	}
    }

    /*
     * The literal is new to this CompileEnv. If it is a command name, avoid
     * sharing it accross namespaces, and try not to share it with non-cmd
     * sharing it across namespaces, and try not to share it with non-cmd
     * literals. Note that FQ command names can be shared, so that we register
     * the namespace as the interp's global NS.
     */

    if ((flags & LITERAL_CMD_NAME)) {
	if ((length >= 2) && (bytes[0] == ':') && (bytes[1] == ':')) {
	    nsPtr = iPtr->globalNsPtr;
471
472
473
474
475
476
477




478
479
480
481
482
483
484
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491







+
+
+
+







    if (globalPtr != NULL && (globalPtr->refCount + 1 < 2)) {
	Tcl_Panic("%s: global literal \"%.*s\" had bad refCount %" TCL_Z_MODIFIER "u",
		"TclRegisterLiteral", (length>60? 60 : (int)length), bytes,
		globalPtr->refCount);
    }
    TclVerifyLocalLiteralTable(envPtr);
#endif /*TCL_COMPILE_DEBUG*/
    if (objIndex > INT_MAX) {
	Tcl_Panic(
	    "Literal table index too large. Cannot be handled by TclEmitPush");
    }
    return objIndex;
}

#ifdef TCL_COMPILE_DEBUG
/*
 *----------------------------------------------------------------------
 *
549
550
551
552
553
554
555
556


557
558
559
560
561
562
563
556
557
558
559
560
561
562

563
564
565
566
567
568
569
570
571







-
+
+







    CompileEnv *envPtr,/* Points to CompileEnv whose literal array
				 * contains the entry being hidden. */
    int index)			/* The index of the entry in the literal
				 * array. */
{
    LiteralEntry **nextPtrPtr, *entryPtr, *lPtr;
    LiteralTable *localTablePtr = &envPtr->localLitTable;
    size_t localHash, length;
    size_t localHash;
    Tcl_Size length;
    const char *bytes;
    Tcl_Obj *newObjPtr;

    lPtr = &envPtr->literalArrayPtr[index];

    /*
     * To avoid unwanted sharing we need to copy the object and remove it from
613
614
615
616
617
618
619
620

621
622
623
624
625
626




627
628
629
630
631
632
633
621
622
623
624
625
626
627

628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645







-
+






+
+
+
+







				 * the object is to be inserted. */
    Tcl_Obj *objPtr,		/* The object to insert into the array. */
    LiteralEntry **litPtrPtr)	/* The location where the pointer to the new
				 * literal entry should be stored. May be
				 * NULL. */
{
    LiteralEntry *lPtr;
    int objIndex;
    size_t objIndex;

    if (envPtr->literalArrayNext >= envPtr->literalArrayEnd) {
	ExpandLocalLiteralArray(envPtr);
    }
    objIndex = envPtr->literalArrayNext;
    envPtr->literalArrayNext++;
    if (objIndex > INT_MAX) {
	Tcl_Panic(
	    "Literal table index too large. Cannot be handled by TclEmitPush");
    }

    lPtr = &envPtr->literalArrayPtr[objIndex];
    lPtr->objPtr = objPtr;
    Tcl_IncrRefCount(objPtr);
    lPtr->refCount = TCL_INDEX_NONE;	/* i.e., unused */
    lPtr->nextPtr = NULL;

652
653
654
655
656
657
658
659

660
661
662
663
664
665
666
667
668

669
670
671
672
673
674
675
664
665
666
667
668
669
670

671
672
673
674
675
676
677
678
679

680
681
682
683
684
685
686
687







-
+








-
+







 * Side effects:
 *	Expands the literal array if necessary. May rebuild the hash bucket
 *	array of the CompileEnv's literal array if it becomes too large.
 *
 *----------------------------------------------------------------------
 */

static int
static size_t
AddLocalLiteralEntry(
    CompileEnv *envPtr,/* Points to CompileEnv in whose literal array
				 * the object is to be inserted. */
    Tcl_Obj *objPtr,		/* The literal to add to the CompileEnv. */
    int localHash)		/* Hash value for the literal's string. */
{
    LiteralTable *localTablePtr = &envPtr->localLitTable;
    LiteralEntry *localPtr;
    int objIndex;
    size_t objIndex;

    objIndex = TclAddLiteralObj(envPtr, objPtr, &localPtr);

    /*
     * Add the literal to the local table.
     */

822
823
824
825
826
827
828
829


830
831
832
833
834
835
836
834
835
836
837
838
839
840

841
842
843
844
845
846
847
848
849







-
+
+







				 * previously created by a call to
				 * TclRegisterLiteral. */
{
    Interp *iPtr = (Interp *) interp;
    LiteralTable *globalTablePtr;
    LiteralEntry *entryPtr, *prevPtr;
    const char *bytes;
    size_t length, index;
    size_t index;
    Tcl_Size length;

    if (iPtr == NULL) {
	goto done;
    }

    globalTablePtr = &iPtr->literalTable;
    bytes = TclGetStringFromObj(objPtr, &length);
965
966
967
968
969
970
971
972


973
974
975
976
977
978
979
978
979
980
981
982
983
984

985
986
987
988
989
990
991
992
993







-
+
+







				/* Local or global table to enlarge. */
{
    LiteralEntry **oldBuckets;
    LiteralEntry **oldChainPtr, **newChainPtr;
    LiteralEntry *entryPtr;
    LiteralEntry **bucketPtr;
    const char *bytes;
    size_t oldSize, count, index, length;
    size_t oldSize, count, index;
    Tcl_Size length;

    oldSize = tablePtr->numBuckets;
    oldBuckets = tablePtr->buckets;

    /*
     * Allocate and initialize the new bucket array, and set up hashing
     * constants for new array size.
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
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







-
+















-
+


-
-
+
+







 *	TclSetCmdNameObj()).
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Resets the internal representation of the CmdName Tcl_Obj
 *	using TclFreeIntRep().
 *	using TclFreeInternalRep().
 *
 *----------------------------------------------------------------------
 */

void
TclInvalidateCmdLiteral(
    Tcl_Interp *interp,		/* Interpreter for which to invalidate a
				 * command literal. */
    const char *name,		/* Points to the start of the cmd literal
				 * name. */
    Namespace *nsPtr)		/* The namespace for which to lookup and
				 * invalidate a cmd literal. */
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *literalObjPtr = TclCreateLiteral(iPtr, name,
	    strlen(name), -1, NULL, nsPtr, 0, NULL);
	    strlen(name), TCL_INDEX_NONE, NULL, nsPtr, 0, NULL);

    if (literalObjPtr != NULL) {
	if (TclHasIntRep(literalObjPtr, &tclCmdNameType)) {
	    TclFreeIntRep(literalObjPtr);
	if (TclHasInternalRep(literalObjPtr, &tclCmdNameType)) {
	    TclFreeInternalRep(literalObjPtr);
	}
	/* Balance the refcount effects of TclCreateLiteral() above */
	Tcl_IncrRefCount(literalObjPtr);
	TclReleaseLiteral(interp, literalObjPtr);
    }
}

1124
1125
1126
1127
1128
1129
1130
1131

1132
1133
1134
1135

1136
1137
1138
1139

1140
1141
1142

1143
1144
1145
1146
1147
1148
1149
1138
1139
1140
1141
1142
1143
1144

1145
1146
1147
1148

1149
1150
1151
1152

1153
1154
1155

1156
1157
1158
1159
1160
1161
1162
1163







-
+



-
+



-
+


-
+







    }

    /*
     * Print out the histogram and a few other pieces of information.
     */

    result = (char *)Tcl_Alloc(NUM_COUNTERS*60 + 300);
    sprintf(result, "%" TCL_Z_MODIFIER "u entries in table, %" TCL_Z_MODIFIER "u buckets\n",
    snprintf(result, 60, "%" TCL_Z_MODIFIER "u entries in table, %" TCL_Z_MODIFIER "u buckets\n",
	    tablePtr->numEntries, tablePtr->numBuckets);
    p = result + strlen(result);
    for (i=0 ; i<NUM_COUNTERS ; i++) {
	sprintf(p, "number of buckets with %" TCL_Z_MODIFIER "u entries: %" TCL_Z_MODIFIER "u\n",
	snprintf(p, 60, "number of buckets with %" TCL_Z_MODIFIER "u entries: %" TCL_Z_MODIFIER "u\n",
		i, count[i]);
	p += strlen(p);
    }
    sprintf(p, "number of buckets with %d or more entries: %" TCL_Z_MODIFIER "u\n",
    snprintf(p, 60, "number of buckets with %d or more entries: %" TCL_Z_MODIFIER "u\n",
	    NUM_COUNTERS, overflow);
    p += strlen(p);
    sprintf(p, "average search distance for entry: %.1f", average);
    snprintf(p, 60, "average search distance for entry: %.1f", average);
    return result;
}
#endif /*TCL_COMPILE_STATS*/

#ifdef TCL_COMPILE_DEBUG
/*
 *----------------------------------------------------------------------

Changes to generic/tclLoad.c.

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
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
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
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






-
+








-
+

-
-
+
+
-
-


-
-
-
+
+
+

-
+
-
-





-
+

-
+

-
+

-
+

-
+

-
-
+
+

-
-
-
+
+
+

-
-
+
+

-
+

-
-
+
+


-
+



-
+



-
-
+
+


-
+


-
+



-
+


-
-
-
-
-
+
+
+
+
+

-
+





-
-
+
+
+
+
+
+
+
+
+
+
+
+
+







/*
 * tclLoad.c --
 *
 *	This file provides the generic portion (those that are the same on all
 *	platforms) of Tcl's dynamic loading facilities.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

/*
 * The following structure describes a package that has been loaded either
 * The following structure describes a library that has been loaded either
 * dynamically (with the "load" command) or statically (as indicated by a call
 * to TclGetLoadedPackages). All such packages are linked together into a
 * single list for the process. Packages are never unloaded, until the
 * to Tcl_StaticLibrary). All such libraries are linked together into a
 * single list for the process.
 * application exits, when TclFinalizeLoad is called, and these structures are
 * freed.
 */

typedef struct LoadedPackage {
    char *fileName;		/* Name of the file from which the package was
				 * loaded. An empty string means the package
typedef struct LoadedLibrary {
    char *fileName;		/* Name of the file from which the library was
				 * loaded. An empty string means the library
				 * is loaded statically. Malloc-ed. */
    char *packageName;		/* Name of package prefix for the package,
    char *prefix;		/* Prefix for the library.
				 * properly capitalized (first letter UC,
				 * others LC), no "_", as in "Net".
				 * Malloc-ed. */
    Tcl_LoadHandle loadHandle;	/* Token for the loaded file which should be
				 * passed to (*unLoadProcPtr)() when the file
				 * is no longer needed. If fileName is NULL,
				 * then this field is irrelevant. */
    Tcl_PackageInitProc *initProc;
    Tcl_LibraryInitProc *initProc;
				/* Initialization function to call to
				 * incorporate this package into a trusted
				 * incorporate this library into a trusted
				 * interpreter. */
    Tcl_PackageInitProc *safeInitProc;
    Tcl_LibraryInitProc *safeInitProc;
				/* Initialization function to call to
				 * incorporate this package into a safe
				 * incorporate this library into a safe
				 * interpreter (one that will execute
				 * untrusted scripts). NULL means the package
				 * untrusted scripts). NULL means the library
				 * can't be used in unsafe interpreters. */
    Tcl_PackageUnloadProc *unloadProc;
				/* Finalisation function to unload a package
    Tcl_LibraryUnloadProc *unloadProc;
				/* Finalization function to unload a library
				 * from a trusted interpreter. NULL means that
				 * the package cannot be unloaded. */
    Tcl_PackageUnloadProc *safeUnloadProc;
				/* Finalisation function to unload a package
				 * the library cannot be unloaded. */
    Tcl_LibraryUnloadProc *safeUnloadProc;
				/* Finalization function to unload a library
				 * from a safe interpreter. NULL means that
				 * the package cannot be unloaded. */
    int interpRefCount;		/* How many times the package has been loaded
				 * the library cannot be unloaded. */
    int interpRefCount;		/* How many times the library has been loaded
				 * in trusted interpreters. */
    int safeInterpRefCount;	/* How many times the package has been loaded
    int safeInterpRefCount;	/* How many times the library has been loaded
				 * in safe interpreters. */
    struct LoadedPackage *nextPtr;
				/* Next in list of all packages loaded into
    struct LoadedLibrary *nextPtr;
				/* Next in list of all libraries loaded into
				 * this application process. NULL means end of
				 * list. */
} LoadedPackage;
} LoadedLibrary;

/*
 * TCL_THREADS
 * There is a global list of packages that is anchored at firstPackagePtr.
 * There is a global list of libraries that is anchored at firstLibraryPtr.
 * Access to this list is governed by a mutex.
 */

static LoadedPackage *firstPackagePtr = NULL;
				/* First in list of all packages loaded into
static LoadedLibrary *firstLibraryPtr = NULL;
				/* First in list of all libraries loaded into
				 * this process. */

TCL_DECLARE_MUTEX(packageMutex)
TCL_DECLARE_MUTEX(libraryMutex)

/*
 * The following structure represents a particular package that has been
 * The following structure represents a particular library that has been
 * incorporated into a particular interpreter (by calling its initialization
 * function). There is a list of these structures for each interpreter, with
 * an AssocData value (key "load") for the interpreter that points to the
 * first package (if any).
 * first library (if any).
 */

typedef struct InterpPackage {
    LoadedPackage *pkgPtr;	/* Points to detailed information about
				 * package. */
    struct InterpPackage *nextPtr;
				/* Next package in this interpreter, or NULL
typedef struct InterpLibrary {
    LoadedLibrary *libraryPtr;	/* Points to detailed information about
				 * library. */
    struct InterpLibrary *nextPtr;
				/* Next library in this interpreter, or NULL
				 * for end of list. */
} InterpPackage;
} InterpLibrary;

/*
 * Prototypes for functions that are private to this file:
 */

static void		LoadCleanupProc(ClientData clientData,
			    Tcl_Interp *interp);
static void	LoadCleanupProc(void *clientData,
		    Tcl_Interp *interp);
static int	IsStatic(LoadedLibrary *libraryPtr);
static int	UnloadLibrary(Tcl_Interp *interp, Tcl_Interp *target,
		    LoadedLibrary *library, int keepLibrary,
		    const char *fullFileName, int interpExiting);

static int
IsStatic(
    LoadedLibrary *libraryPtr)
{
    return (libraryPtr->fileName[0] == '\0');
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_LoadObjCmd --
 *
 *	This function is invoked to process the "load" Tcl command. See the
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





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
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
467
468
469
470
471
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
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
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
467
468

469
470
471
472

473
474
475
476
477
478
479
480







-
-
+
+

-
+


-
-
+
+



-
+


-
+



-
+










-
+

-
+






-
+
+







-
+






-
+

-
-
-
+
+
+


-
+

-
+

-
+





-
+














-
-
+
+




-
+


-
+


-
-
+
+


-
-
+
+

-
+
-
-

-
+





-
+

-
-
+
+



-
+



-
+



-
-
+
+

-
+

-
+



-
-
-
+
+
+



-
-
+
+



-
-
+
+

-
+






-
+


-
+




-
+

-
+





-
+


-
-
+
+

+
-
+
+





-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+

+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+

-
-
+
+
+
+



-
+


-
+

-
+

-
+

-
+



-
+






-
+


-
+





-
+


-
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+


-
+


-
+


-
-
+
+

-
-
-
-
+
+
+
+










-
+




-
+

-
-
+
+

-
+



-
+

-
+

-
-
+
+

-
+



-
+







Tcl_LoadObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Interp *target;
    LoadedPackage *pkgPtr, *defaultPtr;
    Tcl_DString pkgName, tmp, initName, safeInitName;
    LoadedLibrary *libraryPtr, *defaultPtr;
    Tcl_DString pfx, tmp, initName, safeInitName;
    Tcl_DString unloadName, safeUnloadName;
    InterpPackage *ipFirstPtr, *ipPtr;
    InterpLibrary *ipFirstPtr, *ipPtr;
    int code, namesMatch, filesMatch, offset;
    const char *symbols[2];
    Tcl_PackageInitProc *initProc;
    const char *p, *fullFileName, *packageName;
    Tcl_LibraryInitProc *initProc;
    const char *p, *fullFileName, *prefix;
    Tcl_LoadHandle loadHandle;
    Tcl_UniChar ch = 0;
    size_t len;
    int index, flags = 0;
    int flags = 0;
    Tcl_Obj *const *savedobjv = objv;
    static const char *const options[] = {
	"-global",		"-lazy",		"--",	NULL
	"-global",	"-lazy",	"--",	NULL
    };
    enum loadOptionsEnum {
	LOAD_GLOBAL,	LOAD_LAZY,	LOAD_LAST
    };
    } index;

    while (objc > 2) {
	if (TclGetString(objv[1])[0] != '-') {
	    break;
	}
	if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0,
		&index) != TCL_OK) {
	    return TCL_ERROR;
	}
	++objv; --objc;
	if (LOAD_GLOBAL == (enum loadOptionsEnum) index) {
	if (LOAD_GLOBAL == index) {
	    flags |= TCL_LOAD_GLOBAL;
	} else if (LOAD_LAZY == (enum loadOptionsEnum) index) {
	} else if (LOAD_LAZY == index) {
	    flags |= TCL_LOAD_LAZY;
	} else {
		break;
	}
    }
    if ((objc < 2) || (objc > 4)) {
	Tcl_WrongNumArgs(interp, 1, savedobjv, "?-global? ?-lazy? ?--? fileName ?packageName? ?interp?");
	Tcl_WrongNumArgs(interp, 1, savedobjv,
		"?-global? ?-lazy? ?--? fileName ?prefix? ?interp?");
	return TCL_ERROR;
    }
    if (Tcl_FSConvertToPathType(interp, objv[1]) != TCL_OK) {
	return TCL_ERROR;
    }
    fullFileName = TclGetString(objv[1]);

    Tcl_DStringInit(&pkgName);
    Tcl_DStringInit(&pfx);
    Tcl_DStringInit(&initName);
    Tcl_DStringInit(&safeInitName);
    Tcl_DStringInit(&unloadName);
    Tcl_DStringInit(&safeUnloadName);
    Tcl_DStringInit(&tmp);

    packageName = NULL;
    prefix = NULL;
    if (objc >= 3) {
	packageName = TclGetString(objv[2]);
	if (packageName[0] == '\0') {
	    packageName = NULL;
	prefix = TclGetString(objv[2]);
	if (prefix[0] == '\0') {
	    prefix = NULL;
	}
    }
    if ((fullFileName[0] == 0) && (packageName == NULL)) {
    if ((fullFileName[0] == 0) && (prefix == NULL)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"must specify either file name or package name", -1));
		"must specify either file name or prefix", -1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "NOLIBRARY",
		NULL);
		(char *)NULL);
	code = TCL_ERROR;
	goto done;
    }

    /*
     * Figure out which interpreter we're going to load the package into.
     * Figure out which interpreter we're going to load the library into.
     */

    target = interp;
    if (objc == 4) {
	const char *childIntName = TclGetString(objv[3]);

	target = Tcl_GetChild(interp, childIntName);
	if (target == NULL) {
	    code = TCL_ERROR;
	    goto done;
	}
    }

    /*
     * Scan through the packages that are currently loaded to see if the
     * package we want is already loaded. We'll use a loaded package if it
     * Scan through the libraries that are currently loaded to see if the
     * library we want is already loaded. We'll use a loaded library if it
     * meets any of the following conditions:
     *  - Its name and file match the once we're looking for.
     *  - Its file matches, and we weren't given a name.
     *  - Its name matches, the file name was specified as empty, and there is
     *	  only no statically loaded package with the same name.
     *	  only no statically loaded library with the same prefix.
     */

    Tcl_MutexLock(&packageMutex);
    Tcl_MutexLock(&libraryMutex);

    defaultPtr = NULL;
    for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) {
	if (packageName == NULL) {
    for (libraryPtr = firstLibraryPtr; libraryPtr != NULL; libraryPtr = libraryPtr->nextPtr) {
	if (prefix == NULL) {
	    namesMatch = 0;
	} else {
	    TclDStringClear(&pkgName);
	    Tcl_DStringAppend(&pkgName, packageName, -1);
	    TclDStringClear(&pfx);
	    Tcl_DStringAppend(&pfx, prefix, -1);
	    TclDStringClear(&tmp);
	    Tcl_DStringAppend(&tmp, pkgPtr->packageName, -1);
	    Tcl_DStringAppend(&tmp, libraryPtr->prefix, -1);
	    Tcl_UtfToLower(Tcl_DStringValue(&pkgName));
	    Tcl_UtfToLower(Tcl_DStringValue(&tmp));
	    if (strcmp(Tcl_DStringValue(&tmp),
		    Tcl_DStringValue(&pkgName)) == 0) {
		    Tcl_DStringValue(&pfx)) == 0) {
		namesMatch = 1;
	    } else {
		namesMatch = 0;
	    }
	}
	TclDStringClear(&pkgName);
	TclDStringClear(&pfx);

	filesMatch = (strcmp(pkgPtr->fileName, fullFileName) == 0);
	if (filesMatch && (namesMatch || (packageName == NULL))) {
	filesMatch = (strcmp(libraryPtr->fileName, fullFileName) == 0);
	if (filesMatch && (namesMatch || (prefix == NULL))) {
	    break;
	}
	if (namesMatch && (fullFileName[0] == 0)) {
	    defaultPtr = pkgPtr;
	    defaultPtr = libraryPtr;
	}
	if (filesMatch && !namesMatch && (fullFileName[0] != 0)) {
	    /*
	     * Can't have two different packages loaded from the same file.
	     * Can't have two different libraries loaded from the same file.
	     */

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "file \"%s\" is already loaded for package \"%s\"",
		    fullFileName, pkgPtr->packageName));
		    "file \"%s\" is already loaded for prefix \"%s\"",
		    fullFileName, libraryPtr->prefix));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD",
		    "SPLITPERSONALITY", NULL);
		    "SPLITPERSONALITY", (char *)NULL);
	    code = TCL_ERROR;
	    Tcl_MutexUnlock(&packageMutex);
	    Tcl_MutexUnlock(&libraryMutex);
	    goto done;
	}
    }
    Tcl_MutexUnlock(&packageMutex);
    if (pkgPtr == NULL) {
	pkgPtr = defaultPtr;
    Tcl_MutexUnlock(&libraryMutex);
    if (libraryPtr == NULL) {
	libraryPtr = defaultPtr;
    }

    /*
     * Scan through the list of packages already loaded in the target
     * interpreter. If the package we want is already loaded there, then
     * Scan through the list of libraries already loaded in the target
     * interpreter. If the library we want is already loaded there, then
     * there's nothing for us to do.
     */

    if (pkgPtr != NULL) {
	ipFirstPtr = (InterpPackage *)Tcl_GetAssocData(target, "tclLoad", NULL);
    if (libraryPtr != NULL) {
	ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
	for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
	    if (ipPtr->pkgPtr == pkgPtr) {
	    if (ipPtr->libraryPtr == libraryPtr) {
		code = TCL_OK;
		goto done;
	    }
	}
    }

    if (pkgPtr == NULL) {
    if (libraryPtr == NULL) {
	/*
	 * The desired file isn't currently loaded, so load it. It's an error
	 * if the desired package is a static one.
	 * if the desired library is a static one.
	 */

	if (fullFileName[0] == 0) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "package \"%s\" isn't loaded statically", packageName));
		    "no library with prefix \"%s\" is loaded statically", prefix));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "NOTSTATIC",
		    NULL);
		    (char *)NULL);
	    code = TCL_ERROR;
	    goto done;
	}

	/*
	 * Figure out the module name if it wasn't provided explicitly.
	 * Figure out the prefix if it wasn't provided explicitly.
	 */

	if (packageName != NULL) {
	    Tcl_DStringAppend(&pkgName, packageName, -1);
	if (prefix != NULL) {
	    Tcl_DStringAppend(&pfx, prefix, -1);
	} else {
	    Tcl_Obj *splitPtr, *pkgGuessPtr;
	    int retc;
	    Tcl_Size pElements;
	    const char *pkgGuess;

	    /*
	     * Threading note - this call used to be protected by a mutex.
	     */

	    retc = TclGuessPackageName(fullFileName, &pkgName);
	    if (!retc) {
		Tcl_Obj *splitPtr, *pkgGuessPtr;
		int pElements;
		const char *pkgGuess;

		/*
		 * The platform-specific code couldn't figure out the module
		 * name. Make a guess by taking the last element of the file
		 * name, stripping off any leading "lib", and then using all
		 * of the alphabetic and underline characters that follow
		 * that.
		 */
	    /*
	     * The platform-specific code couldn't figure out the prefix.
	     * Make a guess by taking the last element of the file
	     * name, stripping off any leading "lib" and/or "tcl9", and
	     * then using all of the alphabetic and underline characters
	     * that follow that.
	     */

		splitPtr = Tcl_FSSplitPath(objv[1], &pElements);
		Tcl_ListObjIndex(NULL, splitPtr, pElements -1, &pkgGuessPtr);
		pkgGuess = TclGetString(pkgGuessPtr);
		if ((pkgGuess[0] == 'l') && (pkgGuess[1] == 'i')
			&& (pkgGuess[2] == 'b')) {
		    pkgGuess += 3;
		}
	    splitPtr = Tcl_FSSplitPath(objv[1], &pElements);
	    Tcl_ListObjIndex(NULL, splitPtr, pElements -1, &pkgGuessPtr);
	    pkgGuess = TclGetString(pkgGuessPtr);
	    if ((pkgGuess[0] == 'l') && (pkgGuess[1] == 'i')
		    && (pkgGuess[2] == 'b')) {
		pkgGuess += 3;
	    }
#ifdef __CYGWIN__
		if ((pkgGuess[0] == 'c') && (pkgGuess[1] == 'y')
			&& (pkgGuess[2] == 'g')) {
		    pkgGuess += 3;
		}
	    else if ((pkgGuess[0] == 'c') && (pkgGuess[1] == 'y')
		    && (pkgGuess[2] == 'g')) {
		pkgGuess += 3;
	    }
#endif /* __CYGWIN__ */
	    if (((pkgGuess[0] == 't')
#ifdef MAC_OSX_TCL
		    || (pkgGuess[0] == 'T')
#endif
		    ) && (pkgGuess[1] == 'c')
		    && (pkgGuess[2] == 'l') && (pkgGuess[3] == '9')) {
		pkgGuess += 4;
	    }
		for (p = pkgGuess; *p != 0; p += offset) {
		    offset = TclUtfToUniChar(p, &ch);
	    for (p = pkgGuess; *p != 0; p += offset) {
		offset = TclUtfToUniChar(p, &ch);
		    if ((ch > 0x100)
			    || !(isalpha(UCHAR(ch)) /* INTL: ISO only */
				    || (UCHAR(ch) == '_'))) {
			break;
		    }
		}
		if (p == pkgGuess) {
		    Tcl_DecrRefCount(splitPtr);
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "couldn't figure out package name for %s",
			    fullFileName));
		    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD",
			    "WHATPACKAGE", NULL);
		    code = TCL_ERROR;
		    goto done;
		}
		Tcl_DStringAppend(&pkgName, pkgGuess, p - pkgGuess);
		Tcl_DecrRefCount(splitPtr);
	    }
		if (!Tcl_UniCharIsWordChar(UCHAR(ch))
			|| Tcl_UniCharIsDigit(UCHAR(ch))) {
		    break;
		}
	    }
	    if (p == pkgGuess) {
		Tcl_DecrRefCount(splitPtr);
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"cannot figure out prefix for %s",
			fullFileName));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD",
			"WHATLIBRARY", (char *)NULL);
		code = TCL_ERROR;
		goto done;
	    }
	    Tcl_DStringAppend(&pfx, pkgGuess, p - pkgGuess);
	    Tcl_DecrRefCount(splitPtr);

	}

	/*
	 * Fix the capitalization in the package name so that the first
	 * character is in caps (or title case) but the others are all
	 * lower-case.
	 */
	    /*
	     * Fix the capitalization in the prefix so that the first
	     * character is in caps (or title case) but the others are all
	     * lower-case.
	     */

	Tcl_DStringSetLength(&pkgName,
		Tcl_UtfToTitle(Tcl_DStringValue(&pkgName)));
	    Tcl_DStringSetLength(&pfx,
		    Tcl_UtfToTitle(Tcl_DStringValue(&pfx)));

	}

	/*
	 * Compute the names of the two initialization functions, based on the
	 * package name.
	 * prefix.
	 */

	TclDStringAppendDString(&initName, &pkgName);
	TclDStringAppendDString(&initName, &pfx);
	TclDStringAppendLiteral(&initName, "_Init");
	TclDStringAppendDString(&safeInitName, &pkgName);
	TclDStringAppendDString(&safeInitName, &pfx);
	TclDStringAppendLiteral(&safeInitName, "_SafeInit");
	TclDStringAppendDString(&unloadName, &pkgName);
	TclDStringAppendDString(&unloadName, &pfx);
	TclDStringAppendLiteral(&unloadName, "_Unload");
	TclDStringAppendDString(&safeUnloadName, &pkgName);
	TclDStringAppendDString(&safeUnloadName, &pfx);
	TclDStringAppendLiteral(&safeUnloadName, "_SafeUnload");

	/*
	 * Call platform-specific code to load the package and find the two
	 * Call platform-specific code to load the library and find the two
	 * initialization functions.
	 */

	symbols[0] = Tcl_DStringValue(&initName);
	symbols[1] = NULL;

	Tcl_MutexLock(&packageMutex);
	Tcl_MutexLock(&libraryMutex);
	code = Tcl_LoadFile(interp, objv[1], symbols, flags, &initProc,
		&loadHandle);
	Tcl_MutexUnlock(&packageMutex);
	Tcl_MutexUnlock(&libraryMutex);
	if (code != TCL_OK) {
	    goto done;
	}

	/*
	 * Create a new record to describe this package.
	 * Create a new record to describe this library.
	 */

	pkgPtr = (LoadedPackage *)Tcl_Alloc(sizeof(LoadedPackage));
	libraryPtr = (LoadedLibrary *)Tcl_Alloc(sizeof(LoadedLibrary));
	len = strlen(fullFileName) + 1;
	pkgPtr->fileName	   = (char *)Tcl_Alloc(len);
	memcpy(pkgPtr->fileName, fullFileName, len);
	len = Tcl_DStringLength(&pkgName) + 1;
	pkgPtr->packageName	   = (char *)Tcl_Alloc(len);
	memcpy(pkgPtr->packageName, Tcl_DStringValue(&pkgName), len);
	pkgPtr->loadHandle	   = loadHandle;
	pkgPtr->initProc	   = initProc;
	pkgPtr->safeInitProc	   = (Tcl_PackageInitProc *)
	libraryPtr->fileName	   = (char *)Tcl_Alloc(len);
	memcpy(libraryPtr->fileName, fullFileName, len);
	len = Tcl_DStringLength(&pfx) + 1;
	libraryPtr->prefix	   = (char *)Tcl_Alloc(len);
	memcpy(libraryPtr->prefix, Tcl_DStringValue(&pfx), len);
	libraryPtr->loadHandle	   = loadHandle;
	libraryPtr->initProc	   = initProc;
	libraryPtr->safeInitProc	   = (Tcl_LibraryInitProc *)
		Tcl_FindSymbol(interp, loadHandle,
			Tcl_DStringValue(&safeInitName));
	pkgPtr->unloadProc	   = (Tcl_PackageUnloadProc *)
	libraryPtr->unloadProc	   = (Tcl_LibraryUnloadProc *)
		Tcl_FindSymbol(interp, loadHandle,
			Tcl_DStringValue(&unloadName));
	pkgPtr->safeUnloadProc	   = (Tcl_PackageUnloadProc *)
	libraryPtr->safeUnloadProc	   = (Tcl_LibraryUnloadProc *)
		Tcl_FindSymbol(interp, loadHandle,
			Tcl_DStringValue(&safeUnloadName));
	pkgPtr->interpRefCount	   = 0;
	pkgPtr->safeInterpRefCount = 0;
	libraryPtr->interpRefCount	   = 0;
	libraryPtr->safeInterpRefCount = 0;

	Tcl_MutexLock(&packageMutex);
	pkgPtr->nextPtr		   = firstPackagePtr;
	firstPackagePtr		   = pkgPtr;
	Tcl_MutexUnlock(&packageMutex);
	Tcl_MutexLock(&libraryMutex);
	libraryPtr->nextPtr		   = firstLibraryPtr;
	firstLibraryPtr		   = libraryPtr;
	Tcl_MutexUnlock(&libraryMutex);

	/*
	 * The Tcl_FindSymbol calls may have left a spurious error message in
	 * the interpreter result.
	 */

	Tcl_ResetResult(interp);
    }

    /*
     * Invoke the package's initialization function (either the normal one or
     * Invoke the library's initialization function (either the normal one or
     * the safe one, depending on whether or not the interpreter is safe).
     */

    if (Tcl_IsSafe(target)) {
	if (pkgPtr->safeInitProc == NULL) {
	if (libraryPtr->safeInitProc == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't use package in a safe interpreter: no"
		    " %s_SafeInit procedure", pkgPtr->packageName));
		    "cannot use library in a safe interpreter: no"
		    " %s_SafeInit procedure", libraryPtr->prefix));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "UNSAFE",
		    NULL);
		    (char *)NULL);
	    code = TCL_ERROR;
	    goto done;
	}
	code = pkgPtr->safeInitProc(target);
	code = libraryPtr->safeInitProc(target);
    } else {
	if (pkgPtr->initProc == NULL) {
	if (libraryPtr->initProc == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't attach package to interpreter: no %s_Init procedure",
		    pkgPtr->packageName));
		    "cannot attach library to interpreter: no %s_Init procedure",
		    libraryPtr->prefix));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "ENTRYPOINT",
		    NULL);
		    (char *)NULL);
	    code = TCL_ERROR;
	    goto done;
	}
	code = pkgPtr->initProc(target);
	code = libraryPtr->initProc(target);
    }

    /*
     * Test for whether the initialization failed. If so, transfer the error
     * from the target interpreter to the originating one.
     */

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
558
559
560
561
562

563
564
565
566
567
568
569
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


558
559



560
561

562

563
564
565
566
567
568

569
570
571
572
573
574
575
576







-
+





-
+

-
+

-
+

-
+


-
-
+
+


-
-
-
+
+
+




-
+













-
+



















-
-
+
+
-
-
-
+
+
-

-
+





-
+







	    iPtr->legacyFreeProc = (void (*) (void))-1;
	}
	Tcl_TransferResult(target, code, interp);
	goto done;
    }

    /*
     * Record the fact that the package has been loaded in the target
     * Record the fact that the library has been loaded in the target
     * interpreter.
     *
     * Update the proper reference count.
     */

    Tcl_MutexLock(&packageMutex);
    Tcl_MutexLock(&libraryMutex);
    if (Tcl_IsSafe(target)) {
	pkgPtr->safeInterpRefCount++;
	libraryPtr->safeInterpRefCount++;
    } else {
	pkgPtr->interpRefCount++;
	libraryPtr->interpRefCount++;
    }
    Tcl_MutexUnlock(&packageMutex);
    Tcl_MutexUnlock(&libraryMutex);

    /*
     * Refetch ipFirstPtr: loading the package may have introduced additional
     * static packages at the head of the linked list!
     * Refetch ipFirstPtr: loading the library may have introduced additional
     * static libraries at the head of the linked list!
     */

    ipFirstPtr = (InterpPackage *)Tcl_GetAssocData(target, "tclLoad", NULL);
    ipPtr = (InterpPackage *)Tcl_Alloc(sizeof(InterpPackage));
    ipPtr->pkgPtr = pkgPtr;
    ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
    ipPtr = (InterpLibrary *)Tcl_Alloc(sizeof(InterpLibrary));
    ipPtr->libraryPtr = libraryPtr;
    ipPtr->nextPtr = ipFirstPtr;
    Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, ipPtr);

  done:
    Tcl_DStringFree(&pkgName);
    Tcl_DStringFree(&pfx);
    Tcl_DStringFree(&initName);
    Tcl_DStringFree(&safeInitName);
    Tcl_DStringFree(&unloadName);
    Tcl_DStringFree(&safeUnloadName);
    Tcl_DStringFree(&tmp);
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UnloadObjCmd --
 *
 *	This function is invoked to process the "unload" Tcl command. See the
 *	Implements the "unload" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UnloadObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Interp *target;		/* Which interpreter to unload from. */
    LoadedPackage *pkgPtr, *defaultPtr;
    Tcl_DString pkgName, tmp;
    LoadedLibrary *libraryPtr;
    Tcl_DString pfx, tmp;
    Tcl_PackageUnloadProc *unloadProc;
    InterpPackage *ipFirstPtr, *ipPtr;
    int i, index, code, complain = 1, keepLibrary = 0;
    InterpLibrary *ipFirstPtr, *ipPtr;
    int i, code, complain = 1, keepLibrary = 0;
    int trustedRefCount = -1, safeRefCount = -1;
    const char *fullFileName = "";
    const char *packageName;
    const char *prefix;
    static const char *const options[] = {
	"-nocomplain", "-keeplibrary", "--", NULL
    };
    enum unloadOptionsEnum {
	UNLOAD_NOCOMPLAIN, UNLOAD_KEEPLIB, UNLOAD_LAST
    };
    } index;

    for (i = 1; i < objc; i++) {
	if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
		&index) != TCL_OK) {
	    fullFileName = TclGetString(objv[i]);
	    if (fullFileName[0] == '-') {
		/*
578
579
580
581
582
583
584
585

586
587
588
589
590
591
592
593
594
595
596
597
598
599
600

601
602
603
604
605
606
607
608

609
610
611

612
613
614
615



616
617
618

619
620

621
622

623
624
625
626
627
628

629
630
631
632
633
634
635
636
637
638
639
640
641
642
643


644
645
646
647
648




649
650
651

652
653
654

655
656
657

658
659
660
661


662
663

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
707
708

709
710
711
712
713
714
715


716
717
718
719
720
721


722
723

724
725
726
727
728
729
730
731

732
733
734
735
736
737
738

739
740
741
742












743
744
745







746
747
748










749
750
751
752
753
754







755
756
757
758
759


























760
761
762
763
764
765
766
767
768
769
770












771
772
773
774

775
776
777
778
779
780
781
782



783
784
785
786
787
788






789
790
791
792
793
794





795
796
797
798
799
800







801
802
803
804
805
806


807
808





























809
810
811

812
813

814
815
816
817
818
819
820


821
822
823

824
825
826
827
828
829
830


831
832
833
834
835



836
837
838
839


840
841
842
843
844
845
846
847
848
849
850
851
852
853
854



855
856
857
858
859
860
861



862
863
864
865
866




867
868
869
870
871
872
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



898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925

926
927

928
929
930
931
932
933
934

935
936
937
938
939
940
941
942


943
944
945
946

947
948
949

950
951
952


953
954

955
956

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
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
1116

1117
1118
1119
1120
1121
1122
1123
1124



1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136

1137
1138
1139
1140
1141
1142
1143
1144

1145
1146
1147
1148
1149
1150
1151

1152
1153

1154
1155


1156
1157
1158





1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171

1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185

1186
1187
1188
1189

1190
1191
1192
1193
1194
1195
1196



1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207


1208
1209
1210
1211
1212
1213



1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
585
586
587
588
589
590
591

592
593
594
595
596
597
598
599
600
601
602
603
604
605
606

607
608
609
610
611
612
613
614

615
616
617

618
619



620
621
622
623
624

625
626

627
628

629
630
631
632
633
634

635
636
637
638
639
640
641
642
643
644
645
646
647
648


649
650
651




652
653
654
655
656
657

658
659


660
661
662

663
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
707
708

709
710
711
712
713
714


715
716
717
718
719
720


721
722
723

724
725
726
727
728
729
730
731

732
733
734
735
736
737
738

739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755



756
757
758
759
760
761
762



763
764
765
766
767
768
769
770
771
772






773
774
775
776
777
778
779





780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806










807
808
809
810
811
812
813
814
815
816
817
818
819
820
821

822
823
824
825
826
827
828
829
830
831
832
833






834
835
836
837
838
839
840





841
842
843
844
845
846





847
848
849
850
851
852
853
854
855
856
857
858
859
860
861


862
863
864
865
866
867
868
869
870
871
872
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
898
899
900


901
902
903
904

905
906
907
908
909
910


911
912
913
914



915
916
917
918
919


920
921
922
923
924
925
926
927
928
929
930
931
932
933



934
935
936
937
938
939
940



941
942
943
944




945
946
947
948
949
950
951
952
953






















954




955
956
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
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





1116
1117
1118
1119
1120
1121
1122
1123

1124
1125
1126
1127
1128
1129
1130
1131
1132

1133
1134
1135

1136
1137

1138
1139
1140
1141

1142
1143


1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156

1157
1158
1159
1160
1161
1162



1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176

1177
1178
1179
1180
1181
1182
1183
1184

1185
1186
1187
1188
1189
1190
1191

1192
1193

1194
1195

1196
1197
1198


1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215

1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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







-
+














-
+







-
+


-
+

-
-
-
+
+
+


-
+

-
+

-
+





-
+













-
-
+
+

-
-
-
-
+
+
+
+


-
+

-
-
+


-
+


-
-
+
+

-
+
-
-

-
+





-
+

-
-
+
+

-
-
-





-
+


-
+



-
-
+
+

-
+



-
+







-
+





-
-
+
+




-
-
+
+

-
+







-
+






-
+




+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+



-
+








+
+
+
-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+
+
+






+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+

-
+





-
-
+
+


-
+





-
-
+
+


-
-
-
+
+
+


-
-
+
+












-
-
-
+
+
+




-
-
-
+
+
+

-
-
-
-
+
+
+
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
+
+















-
-
-
-
-
-






-
+

-
+






-
+






-
-
+
+



-
+
-
-
-
+

-
-
+
+

-
+

-
+


-
-
+
+


-
+



-
-
-
-
-
+
+
+
+
+



-
+


-
+



-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+



-
+

-
+





-
+



-
-
+
+








-
+









-
+








-
+
-
-
-
-
-
-
-
-
-
-
-
-






-
-
+
+
-


-
-
+
+




-
-
-
-
-
+
+
+
+
+



-
+








-
+


-
+

-
+



-
+

-
-
+
+











-
+





-
-
-
+
+
+











-
+







-
+






-
+

-
+

-
+
+

-
-
+
+
+
+
+












-
+













-
+



-
+




-
-
-
+
+
+









-
-
+
+



-
-
-
+
+
+










		 * must clear the error.
		 */

		Tcl_ResetResult(interp);
		break;
	    }
	}
	switch ((enum unloadOptionsEnum)index) {
	switch (index) {
	case UNLOAD_NOCOMPLAIN:		/* -nocomplain */
	    complain = 0;
	    break;
	case UNLOAD_KEEPLIB:		/* -keeplibrary */
	    keepLibrary = 1;
	    break;
	case UNLOAD_LAST:		/* -- */
	    i++;
	    goto endOfForLoop;
	}
    }
  endOfForLoop:
    if ((objc-i < 1) || (objc-i > 3)) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"?-switch ...? fileName ?packageName? ?interp?");
		"?-switch ...? fileName ?prefix? ?interp?");
	return TCL_ERROR;
    }
    if (Tcl_FSConvertToPathType(interp, objv[i]) != TCL_OK) {
	return TCL_ERROR;
    }

    fullFileName = TclGetString(objv[i]);
    Tcl_DStringInit(&pkgName);
    Tcl_DStringInit(&pfx);
    Tcl_DStringInit(&tmp);

    packageName = NULL;
    prefix = NULL;
    if (objc - i >= 2) {
	packageName = TclGetString(objv[i+1]);
	if (packageName[0] == '\0') {
	    packageName = NULL;
	prefix = TclGetString(objv[i+1]);
	if (prefix[0] == '\0') {
	    prefix = NULL;
	}
    }
    if ((fullFileName[0] == 0) && (packageName == NULL)) {
    if ((fullFileName[0] == 0) && (prefix == NULL)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"must specify either file name or package name", -1));
		"must specify either file name or prefix", -1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "NOLIBRARY",
		NULL);
		(char *)NULL);
	code = TCL_ERROR;
	goto done;
    }

    /*
     * Figure out which interpreter we're going to load the package into.
     * Figure out which interpreter we're going to load the library into.
     */

    target = interp;
    if (objc - i == 3) {
	const char *childIntName = TclGetString(objv[i + 2]);

	target = Tcl_GetChild(interp, childIntName);
	if (target == NULL) {
	    return TCL_ERROR;
	}
    }

    /*
     * Scan through the packages that are currently loaded to see if the
     * package we want is already loaded. We'll use a loaded package if it
     * Scan through the libraries that are currently loaded to see if the
     * library we want is already loaded. We'll use a loaded library if it
     * meets any of the following conditions:
     *  - Its name and file match the once we're looking for.
     *  - Its file matches, and we weren't given a name.
     *  - Its name matches, the file name was specified as empty, and there is
     *	  only no statically loaded package with the same name.
     *  - Its prefix and file match the once we're looking for.
     *  - Its file matches, and we weren't given a prefix.
     *  - Its prefix matches, the file name was specified as empty, and there is
     *	  no statically loaded library with the same prefix.
     */

    Tcl_MutexLock(&packageMutex);
    Tcl_MutexLock(&libraryMutex);

    defaultPtr = NULL;
    for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) {
    for (libraryPtr = firstLibraryPtr; libraryPtr != NULL; libraryPtr = libraryPtr->nextPtr) {
	int namesMatch, filesMatch;

	if (packageName == NULL) {
	if (prefix == NULL) {
	    namesMatch = 0;
	} else {
	    TclDStringClear(&pkgName);
	    Tcl_DStringAppend(&pkgName, packageName, -1);
	    TclDStringClear(&pfx);
	    Tcl_DStringAppend(&pfx, prefix, -1);
	    TclDStringClear(&tmp);
	    Tcl_DStringAppend(&tmp, pkgPtr->packageName, -1);
	    Tcl_DStringAppend(&tmp, libraryPtr->prefix, -1);
	    Tcl_UtfToLower(Tcl_DStringValue(&pkgName));
	    Tcl_UtfToLower(Tcl_DStringValue(&tmp));
	    if (strcmp(Tcl_DStringValue(&tmp),
		    Tcl_DStringValue(&pkgName)) == 0) {
		    Tcl_DStringValue(&pfx)) == 0) {
		namesMatch = 1;
	    } else {
		namesMatch = 0;
	    }
	}
	TclDStringClear(&pkgName);
	TclDStringClear(&pfx);

	filesMatch = (strcmp(pkgPtr->fileName, fullFileName) == 0);
	if (filesMatch && (namesMatch || (packageName == NULL))) {
	filesMatch = (strcmp(libraryPtr->fileName, fullFileName) == 0);
	if (filesMatch && (namesMatch || (prefix == NULL))) {
	    break;
	}
	if (namesMatch && (fullFileName[0] == 0)) {
	    defaultPtr = pkgPtr;
	}
	if (filesMatch && !namesMatch && (fullFileName[0] != 0)) {
	    break;
	}
    }
    Tcl_MutexUnlock(&packageMutex);
    Tcl_MutexUnlock(&libraryMutex);
    if (fullFileName[0] == 0) {
	/*
	 * It's an error to try unload a static package.
	 * It's an error to try unload a static library.
	 */

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"package \"%s\" is loaded statically and cannot be unloaded",
		packageName));
		"library with prefix \"%s\" is loaded statically and cannot be unloaded",
		prefix));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "STATIC",
		NULL);
		(char *)NULL);
	code = TCL_ERROR;
	goto done;
    }
    if (pkgPtr == NULL) {
    if (libraryPtr == NULL) {
	/*
	 * The DLL pointed by the provided filename has never been loaded.
	 */

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"file \"%s\" has never been loaded", fullFileName));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "NEVERLOADED",
		NULL);
		(char *)NULL);
	code = TCL_ERROR;
	goto done;
    }

    /*
     * Scan through the list of packages already loaded in the target
     * interpreter. If the package we want is already loaded there, then we
     * Scan through the list of libraries already loaded in the target
     * interpreter. If the library we want is already loaded there, then we
     * should proceed with unloading.
     */

    code = TCL_ERROR;
    if (pkgPtr != NULL) {
	ipFirstPtr = (InterpPackage *)Tcl_GetAssocData(target, "tclLoad", NULL);
    if (libraryPtr != NULL) {
	ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
	for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
	    if (ipPtr->pkgPtr == pkgPtr) {
	    if (ipPtr->libraryPtr == libraryPtr) {
		code = TCL_OK;
		break;
	    }
	}
    }
    if (code != TCL_OK) {
	/*
	 * The package has not been loaded in this interpreter.
	 * The library has not been loaded in this interpreter.
	 */

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"file \"%s\" has never been loaded in this interpreter",
		fullFileName));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "NEVERLOADED",
		NULL);
		(char *)NULL);
	code = TCL_ERROR;
	goto done;
    }

    code = UnloadLibrary(interp, target, libraryPtr, keepLibrary, fullFileName, 0);

  done:
    Tcl_DStringFree(&pfx);
    Tcl_DStringFree(&tmp);
    if (!complain && (code != TCL_OK)) {
	code = TCL_OK;
	Tcl_ResetResult(interp);
    }
    return code;
}

    /*
     * Ensure that the DLL can be unloaded. If it is a trusted interpreter,
     * pkgPtr->unloadProc must not be NULL for the DLL to be unloadable. If
/*
 *----------------------------------------------------------------------
 *
 * UnloadLibrary --
 *
 *	Unloads a library from an interpreter, and also from the process if it
 *	is unloadable, i.e. if it provides an "unload" function.
     * the interpreter is a safe one, pkgPtr->safeUnloadProc must be non-NULL.
     */

 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See description.
 *
 *----------------------------------------------------------------------
 */
static int
    if (Tcl_IsSafe(target)) {
	if (pkgPtr->safeUnloadProc == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "file \"%s\" cannot be unloaded under a safe interpreter",
		    fullFileName));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "CANNOT",
UnloadLibrary(
    Tcl_Interp *interp,
    Tcl_Interp *target,
    LoadedLibrary *libraryPtr,
    int keepLibrary,
    const char *fullFileName,
    int interpExiting)
		    NULL);
	    code = TCL_ERROR;
	    goto done;
	}
	unloadProc = pkgPtr->safeUnloadProc;
{
    int code;
    InterpLibrary *ipFirstPtr, *ipPtr;
    LoadedLibrary *iterLibraryPtr;
    int trustedRefCount = -1, safeRefCount = -1;
    Tcl_LibraryUnloadProc *unloadProc = NULL;

    /*
     * Ensure that the DLL can be unloaded. If it is a trusted interpreter,
     * libraryPtr->unloadProc must not be NULL for the DLL to be unloadable. If
     * the interpreter is a safe one, libraryPtr->safeUnloadProc must be non-NULL.
     */

    if (Tcl_IsSafe(target)) {
	if (libraryPtr->safeUnloadProc == NULL) {
	    if (!interpExiting) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"file \"%s\" cannot be unloaded under a safe interpreter",
			fullFileName));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "CANNOT",
			(char *)NULL);
		code = TCL_ERROR;
		goto done;
	    }
	}
	unloadProc = libraryPtr->safeUnloadProc;
    } else {
	if (pkgPtr->unloadProc == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "file \"%s\" cannot be unloaded under a trusted interpreter",
		    fullFileName));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "CANNOT",
		    NULL);
	    code = TCL_ERROR;
	    goto done;
	}
	unloadProc = pkgPtr->unloadProc;
	if (libraryPtr->unloadProc == NULL) {
	    if (!interpExiting) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"file \"%s\" cannot be unloaded under a trusted interpreter",
			fullFileName));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "CANNOT",
			(char *)NULL);
		code = TCL_ERROR;
		goto done;
	    }
	}
	unloadProc = libraryPtr->unloadProc;
    }

    /*
     * We are ready to unload the package. First, evaluate the unload
     * We are ready to unload the library. First, evaluate the unload
     * function. If this fails, we cannot proceed with unload. Also, we must
     * specify the proper flag to pass to the unload callback.
     * TCL_UNLOAD_DETACH_FROM_INTERPRETER is defined when the callback should
     * only remove itself from the interpreter; the library will be unloaded
     * in a future call of unload. In case the library will be unloaded just
     * after the callback returns, TCL_UNLOAD_DETACH_FROM_PROCESS is passed.
     */

    if (unloadProc == NULL) {
	code = TCL_OK;
    } else {
    code = TCL_UNLOAD_DETACH_FROM_INTERPRETER;
    if (!keepLibrary) {
	Tcl_MutexLock(&packageMutex);
	trustedRefCount = pkgPtr->interpRefCount;
	safeRefCount = pkgPtr->safeInterpRefCount;
	Tcl_MutexUnlock(&packageMutex);
	code = TCL_UNLOAD_DETACH_FROM_INTERPRETER;
	if (!keepLibrary) {
	    Tcl_MutexLock(&libraryMutex);
	    trustedRefCount = libraryPtr->interpRefCount;
	    safeRefCount = libraryPtr->safeInterpRefCount;
	    Tcl_MutexUnlock(&libraryMutex);

	if (Tcl_IsSafe(target)) {
	    safeRefCount--;
	} else {
	    trustedRefCount--;
	}
	    if (Tcl_IsSafe(target)) {
		safeRefCount--;
	    } else {
		trustedRefCount--;
	    }

	if (safeRefCount <= 0 && trustedRefCount <= 0) {
	    code = TCL_UNLOAD_DETACH_FROM_PROCESS;
	}
    }
    code = unloadProc(target, code);
	    if (safeRefCount <= 0 && trustedRefCount <= 0) {
		code = TCL_UNLOAD_DETACH_FROM_PROCESS;
	    }
	}
	code = unloadProc(target, code);
    }

    if (code != TCL_OK) {
	Tcl_TransferResult(target, code, interp);
	goto done;
    }

    /*
     * Remove this library from the interpreter's library cache.
     */
     * The unload function executed fine. Examine the reference count to see
     * if we unload the DLL.

    if (!interpExiting) {
	ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
	if (ipFirstPtr) {
	    ipPtr = ipFirstPtr;
	    if (ipPtr->libraryPtr == libraryPtr) {
		ipFirstPtr = ipFirstPtr->nextPtr;
	    } else {
		InterpLibrary *ipPrevPtr;

		for (ipPrevPtr = ipPtr; ipPtr != NULL;
			ipPrevPtr = ipPtr, ipPtr = ipPtr->nextPtr) {
		    if (ipPtr->libraryPtr == libraryPtr) {
			ipPrevPtr->nextPtr = ipPtr->nextPtr;
			break;
		    }
		}
	    }
	    Tcl_Free(ipPtr);
	    Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, ipFirstPtr);
	}
    }

    if (IsStatic(libraryPtr)) {
	goto done;
    }

    /*
     * The unload function was called succesfully.
     */

    Tcl_MutexLock(&packageMutex);
    Tcl_MutexLock(&libraryMutex);
    if (Tcl_IsSafe(target)) {
	pkgPtr->safeInterpRefCount--;
	libraryPtr->safeInterpRefCount--;

	/*
	 * Do not let counter get negative.
	 */

	if (pkgPtr->safeInterpRefCount < 0) {
	    pkgPtr->safeInterpRefCount = 0;
	if (libraryPtr->safeInterpRefCount < 0) {
	    libraryPtr->safeInterpRefCount = 0;
	}
    } else {
	pkgPtr->interpRefCount--;
	libraryPtr->interpRefCount--;

	/*
	 * Do not let counter get negative.
	 */

	if (pkgPtr->interpRefCount < 0) {
	    pkgPtr->interpRefCount = 0;
	if (libraryPtr->interpRefCount < 0) {
	    libraryPtr->interpRefCount = 0;
	}
    }
    trustedRefCount = pkgPtr->interpRefCount;
    safeRefCount = pkgPtr->safeInterpRefCount;
    Tcl_MutexUnlock(&packageMutex);
    trustedRefCount = libraryPtr->interpRefCount;
    safeRefCount = libraryPtr->safeInterpRefCount;
    Tcl_MutexUnlock(&libraryMutex);

    code = TCL_OK;
    if (pkgPtr->safeInterpRefCount <= 0 && pkgPtr->interpRefCount <= 0
	    && !keepLibrary) {
    if (libraryPtr->safeInterpRefCount <= 0 && libraryPtr->interpRefCount <= 0
	    && (unloadProc != NULL) && !keepLibrary) {
	/*
	 * Unload the shared library from the application memory...
	 */

#if defined(TCL_UNLOAD_DLLS) || defined(_WIN32)
	/*
	 * Some Unix dlls are poorly behaved - registering things like atexit
	 * calls that can't be unregistered. If you unload such dlls, you get
	 * a core on exit because it wants to call a function in the dll after
	 * it's been unloaded.
	 */

	if (pkgPtr->fileName[0] != '\0') {
	    Tcl_MutexLock(&packageMutex);
	    if (Tcl_FSUnloadFile(interp, pkgPtr->loadHandle) == TCL_OK) {
	if (!IsStatic(libraryPtr)) {
	    Tcl_MutexLock(&libraryMutex);
	    if (Tcl_FSUnloadFile(interp, libraryPtr->loadHandle) == TCL_OK) {
		/*
		 * Remove this library from the loaded library cache.
		 */

		defaultPtr = pkgPtr;
		if (defaultPtr == firstPackagePtr) {
		    firstPackagePtr = pkgPtr->nextPtr;
		iterLibraryPtr = libraryPtr;
		if (iterLibraryPtr == firstLibraryPtr) {
		    firstLibraryPtr = libraryPtr->nextPtr;
		} else {
		    for (pkgPtr = firstPackagePtr; pkgPtr != NULL;
			    pkgPtr = pkgPtr->nextPtr) {
			if (pkgPtr->nextPtr == defaultPtr) {
			    pkgPtr->nextPtr = defaultPtr->nextPtr;
		    for (libraryPtr = firstLibraryPtr; libraryPtr != NULL;
			    libraryPtr = libraryPtr->nextPtr) {
			if (libraryPtr->nextPtr == iterLibraryPtr) {
			    libraryPtr->nextPtr = iterLibraryPtr->nextPtr;
			    break;
			}
		    }
		}

		/*
		 * Remove this library from the interpreter's library cache.
		 */

		ipFirstPtr = (InterpPackage *)Tcl_GetAssocData(target, "tclLoad", NULL);
		ipPtr = ipFirstPtr;
		if (ipPtr->pkgPtr == defaultPtr) {
		    ipFirstPtr = ipFirstPtr->nextPtr;
		} else {
		    InterpPackage *ipPrevPtr;

		    for (ipPrevPtr = ipPtr; ipPtr != NULL;
			    ipPrevPtr = ipPtr, ipPtr = ipPtr->nextPtr) {
			if (ipPtr->pkgPtr == defaultPtr) {
			    ipPrevPtr->nextPtr = ipPtr->nextPtr;
			    break;
			}
		    }
		}
		Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc,
			ipFirstPtr);
		Tcl_Free(defaultPtr->fileName);
		Tcl_Free(iterLibraryPtr->fileName);
		Tcl_Free(defaultPtr->packageName);
		Tcl_Free(defaultPtr);
		Tcl_Free(ipPtr);
		Tcl_MutexUnlock(&packageMutex);
		Tcl_Free(iterLibraryPtr->prefix);
		Tcl_Free(iterLibraryPtr);
		Tcl_MutexUnlock(&libraryMutex);
	    } else {
		code = TCL_ERROR;
	    }
	}
#else
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"file \"%s\" cannot be unloaded: unloading disabled",
		fullFileName));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "DISABLED",
		NULL);
	code = TCL_ERROR;
#endif
    }

  done:
    Tcl_DStringFree(&pkgName);
    Tcl_DStringFree(&tmp);
    if (!complain && (code != TCL_OK)) {
	code = TCL_OK;
	Tcl_ResetResult(interp);
    }
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_StaticPackage --
 * Tcl_StaticLibrary --
 *
 *	This function is invoked to indicate that a particular package has
 *	This function is invoked to indicate that a particular library has
 *	been linked statically with an application.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Once this function completes, the package becomes loadable via the
 *	Once this function completes, the library becomes loadable via the
 *	"load" command with an empty file name.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_StaticPackage(
    Tcl_Interp *interp,		/* If not NULL, it means that the package has
Tcl_StaticLibrary(
    Tcl_Interp *interp,		/* If not NULL, it means that the library has
				 * already been loaded into the given
				 * interpreter by calling the appropriate init
				 * proc. */
    const char *pkgName,	/* Name of package (must be properly
    const char *prefix,	/* Prefix. */
				 * capitalized: first letter upper case,
				 * others lower case). */
    Tcl_PackageInitProc *initProc,
    Tcl_LibraryInitProc *initProc,
				/* Function to call to incorporate this
				 * package into a trusted interpreter. */
    Tcl_PackageInitProc *safeInitProc)
				 * library into a trusted interpreter. */
    Tcl_LibraryInitProc *safeInitProc)
				/* Function to call to incorporate this
				 * package into a safe interpreter (one that
				 * library into a safe interpreter (one that
				 * will execute untrusted scripts). NULL means
				 * the package can't be used in safe
				 * the library can't be used in safe
				 * interpreters. */
{
    LoadedPackage *pkgPtr;
    InterpPackage *ipPtr, *ipFirstPtr;
    LoadedLibrary *libraryPtr;
    InterpLibrary *ipPtr, *ipFirstPtr;

    /*
     * Check to see if someone else has already reported this package as
     * Check to see if someone else has already reported this library as
     * statically loaded in the process.
     */

    Tcl_MutexLock(&packageMutex);
    for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) {
	if ((pkgPtr->initProc == initProc)
		&& (pkgPtr->safeInitProc == safeInitProc)
		&& (strcmp(pkgPtr->packageName, pkgName) == 0)) {
    Tcl_MutexLock(&libraryMutex);
    for (libraryPtr = firstLibraryPtr; libraryPtr != NULL; libraryPtr = libraryPtr->nextPtr) {
	if ((libraryPtr->initProc == initProc)
		&& (libraryPtr->safeInitProc == safeInitProc)
		&& (strcmp(libraryPtr->prefix, prefix) == 0)) {
	    break;
	}
    }
    Tcl_MutexUnlock(&packageMutex);
    Tcl_MutexUnlock(&libraryMutex);

    /*
     * If the package is not yet recorded as being loaded statically, add it
     * If the library is not yet recorded as being loaded statically, add it
     * to the list now.
     */

    if (pkgPtr == NULL) {
	pkgPtr = (LoadedPackage *)Tcl_Alloc(sizeof(LoadedPackage));
	pkgPtr->fileName	= (char *)Tcl_Alloc(1);
	pkgPtr->fileName[0]	= 0;
	pkgPtr->packageName	= (char *)Tcl_Alloc(strlen(pkgName) + 1);
	strcpy(pkgPtr->packageName, pkgName);
	pkgPtr->loadHandle	= NULL;
	pkgPtr->initProc	= initProc;
	pkgPtr->safeInitProc	= safeInitProc;
	Tcl_MutexLock(&packageMutex);
	pkgPtr->nextPtr		= firstPackagePtr;
	firstPackagePtr		= pkgPtr;
	Tcl_MutexUnlock(&packageMutex);
    if (libraryPtr == NULL) {
	libraryPtr = (LoadedLibrary *)Tcl_Alloc(sizeof(LoadedLibrary));
	libraryPtr->fileName	= (char *)Tcl_Alloc(1);
	libraryPtr->fileName[0]	= 0;
	libraryPtr->prefix	= (char *)Tcl_Alloc(strlen(prefix) + 1);
	strcpy(libraryPtr->prefix, prefix);
	libraryPtr->loadHandle	= NULL;
	libraryPtr->initProc	= initProc;
	libraryPtr->safeInitProc	= safeInitProc;
	libraryPtr->unloadProc = NULL;
	libraryPtr->safeUnloadProc = NULL;
	Tcl_MutexLock(&libraryMutex);
	libraryPtr->nextPtr		= firstLibraryPtr;
	firstLibraryPtr		= libraryPtr;
	Tcl_MutexUnlock(&libraryMutex);
    }

    if (interp != NULL) {

	/*
	 * If we're loading the package into an interpreter, determine whether
	 * If we're loading the library into an interpreter, determine whether
	 * it's already loaded.
	 */

	ipFirstPtr = (InterpPackage *)Tcl_GetAssocData(interp, "tclLoad", NULL);
	ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(interp, "tclLoad", NULL);
	for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
	    if (ipPtr->pkgPtr == pkgPtr) {
	    if (ipPtr->libraryPtr == libraryPtr) {
		return;
	    }
	}

	/*
	 * Package isn't loaded in the current interp yet. Mark it as now being
	 * Library isn't loaded in the current interp yet. Mark it as now being
	 * loaded.
	 */

	ipPtr = (InterpPackage *)Tcl_Alloc(sizeof(InterpPackage));
	ipPtr->pkgPtr = pkgPtr;
	ipPtr = (InterpLibrary *)Tcl_Alloc(sizeof(InterpLibrary));
	ipPtr->libraryPtr = libraryPtr;
	ipPtr->nextPtr = ipFirstPtr;
	Tcl_SetAssocData(interp, "tclLoad", LoadCleanupProc, ipPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetLoadedPackages, TclGetLoadedPackagesEx --
 * TclGetLoadedLibraries --
 *
 *	This function returns information about all of the files that are
 *	loaded (either in a particular interpreter, or for all interpreters).
 *
 * Results:
 *	The return value is a standard Tcl completion code. If successful, a
 *	list of lists is placed in the interp's result. Each sublist
 *	corresponds to one loaded file; its first element is the name of the
 *	file (or an empty string for something that's statically loaded) and
 *	the second element is the name of the package in that file.
 *	the second element is the prefix of the library in that file.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclGetLoadedPackages(
TclGetLoadedLibraries(
    Tcl_Interp *interp,		/* Interpreter in which to return information
				 * or error message. */
    const char *targetName)	/* Name of target interpreter or NULL. If
				 * NULL, return info about all interps;
				 * otherwise, just return info about this
				 * interpreter. */
{
    return TclGetLoadedPackagesEx(interp, targetName, NULL);
}

int
TclGetLoadedPackagesEx(
    Tcl_Interp *interp,		/* Interpreter in which to return information
				 * or error message. */
    const char *targetName,	/* Name of target interpreter or NULL. If
				 * NULL, return info about all interps;
				 * otherwise, just return info about this
				 * interpreter. */
    const char *packageName)	/* Package name or NULL. If NULL, return info
				 * for all packages.
    const char *prefix)		/* Prefix or NULL. If NULL, return info
				 * for all prefixes. */
				 */
{
    Tcl_Interp *target;
    LoadedPackage *pkgPtr;
    InterpPackage *ipPtr;
    LoadedLibrary *libraryPtr;
    InterpLibrary *ipPtr;
    Tcl_Obj *resultObj, *pkgDesc[2];

    if (targetName == NULL) {
	TclNewObj(resultObj);
	Tcl_MutexLock(&packageMutex);
	for (pkgPtr = firstPackagePtr; pkgPtr != NULL;
		pkgPtr = pkgPtr->nextPtr) {
	    pkgDesc[0] = Tcl_NewStringObj(pkgPtr->fileName, -1);
	    pkgDesc[1] = Tcl_NewStringObj(pkgPtr->packageName, -1);
	Tcl_MutexLock(&libraryMutex);
	for (libraryPtr = firstLibraryPtr; libraryPtr != NULL;
		libraryPtr = libraryPtr->nextPtr) {
	    pkgDesc[0] = Tcl_NewStringObj(libraryPtr->fileName, -1);
	    pkgDesc[1] = Tcl_NewStringObj(libraryPtr->prefix, -1);
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    Tcl_NewListObj(2, pkgDesc));
	}
	Tcl_MutexUnlock(&packageMutex);
	Tcl_MutexUnlock(&libraryMutex);
	Tcl_SetObjResult(interp, resultObj);
	return TCL_OK;
    }

    target = Tcl_GetChild(interp, targetName);
    if (target == NULL) {
	return TCL_ERROR;
    }
    ipPtr = (InterpPackage *)Tcl_GetAssocData(target, "tclLoad", NULL);
    ipPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);

    /*
     * Return information about all of the available packages.
     * Return information about all of the available libraries.
     */
    if (packageName) {
    if (prefix) {
	resultObj = NULL;

	for (; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
	    pkgPtr = ipPtr->pkgPtr;
	    libraryPtr = ipPtr->libraryPtr;

	    if (!strcmp(packageName, pkgPtr->packageName)) {
		resultObj = Tcl_NewStringObj(pkgPtr->fileName, -1);
	    if (!strcmp(prefix, libraryPtr->prefix)) {
		resultObj = Tcl_NewStringObj(libraryPtr->fileName, -1);
		break;
	    }
	}

	if (resultObj) {
	    Tcl_SetObjResult(interp, resultObj);
	}
	return TCL_OK;
    }

    /*
     * Return information about only the packages that are loaded in a given
     * Return information about only the libraries that are loaded in a given
     * interpreter.
     */

    TclNewObj(resultObj);
    for (; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
	pkgPtr = ipPtr->pkgPtr;
	pkgDesc[0] = Tcl_NewStringObj(pkgPtr->fileName, -1);
	pkgDesc[1] = Tcl_NewStringObj(pkgPtr->packageName, -1);
	libraryPtr = ipPtr->libraryPtr;
	pkgDesc[0] = Tcl_NewStringObj(libraryPtr->fileName, -1);
	pkgDesc[1] = Tcl_NewStringObj(libraryPtr->prefix, -1);
	Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewListObj(2, pkgDesc));
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * LoadCleanupProc --
 *
 *	This function is called to delete all of the InterpPackage structures
 *	This function is called to delete all of the InterpLibrary structures
 *	for an interpreter when the interpreter is deleted. It gets invoked
 *	via the Tcl AssocData mechanism.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Storage for all of the InterpPackage functions for interp get deleted.
 *	Storage for all of the InterpLibrary functions for interp get deleted.
 *
 *----------------------------------------------------------------------
 */

static void
LoadCleanupProc(
    ClientData clientData,	/* Pointer to first InterpPackage structure
    void *clientData,		/* Pointer to first InterpLibrary structure
				 * for interp. */
    TCL_UNUSED(Tcl_Interp *))
    Tcl_Interp *interp)
{
    InterpPackage *ipPtr, *nextPtr;
    InterpLibrary *ipPtr = (InterpLibrary *)clientData, *nextPtr;
    LoadedLibrary *libraryPtr;

    ipPtr = (InterpPackage *)clientData;
    while (ipPtr != NULL) {
    while (ipPtr) {
	libraryPtr = ipPtr->libraryPtr;
	UnloadLibrary(interp, interp, libraryPtr, 0, "", 1);
	/* UnloadLibrary doesn't free it by interp delete, so do it here and
	 * repeat for next. */
	nextPtr = ipPtr->nextPtr;
	Tcl_Free(ipPtr);
	ipPtr = nextPtr;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclFinalizeLoad --
 *
 *	This function is invoked just before the application exits. It frees
 *	all of the LoadedPackage structures.
 *	all of the LoadedLibrary structures.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Memory is freed.
 *
 *----------------------------------------------------------------------
 */

void
TclFinalizeLoad(void)
{
    LoadedPackage *pkgPtr;
    LoadedLibrary *libraryPtr;

    /*
     * No synchronization here because there should just be one thread alive
     * at this point. Logically, packageMutex should be grabbed at this point,
     * at this point. Logically, libraryMutex should be grabbed at this point,
     * but the Mutexes get finalized before the call to this routine. The only
     * subsystem left alive at this point is the memory allocator.
     */

    while (firstPackagePtr != NULL) {
	pkgPtr = firstPackagePtr;
	firstPackagePtr = pkgPtr->nextPtr;
    while (firstLibraryPtr != NULL) {
	libraryPtr = firstLibraryPtr;
	firstLibraryPtr = libraryPtr->nextPtr;

#if defined(TCL_UNLOAD_DLLS) || defined(_WIN32)
	/*
	 * Some Unix dlls are poorly behaved - registering things like atexit
	 * calls that can't be unregistered. If you unload such dlls, you get
	 * a core on exit because it wants to call a function in the dll after
	 * it has been unloaded.
	 */

	if (pkgPtr->fileName[0] != '\0') {
	    Tcl_FSUnloadFile(NULL, pkgPtr->loadHandle);
	if (!IsStatic(libraryPtr)) {
	    Tcl_FSUnloadFile(NULL, libraryPtr->loadHandle);
	}
#endif

	Tcl_Free(pkgPtr->fileName);
	Tcl_Free(pkgPtr->packageName);
	Tcl_Free(pkgPtr);
	Tcl_Free(libraryPtr->fileName);
	Tcl_Free(libraryPtr->prefix);
	Tcl_Free(libraryPtr);
    }
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclLoadNone.c.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tclLoadNone.c --
 *
 *	This procedure provides a version of the TclpDlopen for use in
 *	systems that don't support dynamic loading; it just returns an error.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-











-
-
+
+







-
-
-
-
-
+
+
+
+
+
-
-
+
-







    if (interp) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"dynamic loading is not currently available on this system",
		-1));
    }
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TclGuessPackageName --
 *
 *	If the "load" command is invoked without providing a package name,
 *	this procedure is invoked to try to figure it out.
 *
 * Results:
 *	Always returns 0 to indicate that we couldn't figure out a package
 *	name; generic code will then try to guess the package from the file
 *	name. A return value of 1 would have meant that we figured out the
 *	package name and put it in bufPtr.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclGuessPackageName(
    const char *fileName,	/* Name of file containing package (already
				 * translated to local form if needed). */
    Tcl_DString *bufPtr)	/* Initialized empty dstring. Append package
				 * name to this if possible. */
{
    return 0;
}

/*
 * These functions are fallbacks if we somehow determine that the platform can
 * do loading from memory but the user wishes to disable it. They just report
 * (gracefully) that they fail.
 */

#ifdef TCL_LOAD_FROM_MEMORY

MODULE_SCOPE void *
TclpLoadMemoryGetBuffer(
    Tcl_Interp *interp,		/* Dummy: unused by this implementation */
    int size)			/* Dummy: unused by this implementation */
    TCL_UNUSED(Tcl_Interp *),
    TCL_UNUSED(size_t))
{
    return NULL;
}

MODULE_SCOPE int
TclpLoadMemory(
    Tcl_Interp *interp,		/* Used for error reporting. */
    void *buffer,		/* Dummy: unused by this implementation */
    int size,			/* Dummy: unused by this implementation */
    int codeSize,		/* Dummy: unused by this implementation */
    Tcl_LoadHandle *loadHandle,	/* Dummy: unused by this implementation */
    Tcl_FSUnloadFileProc **unloadProcPtr,
    TCL_UNUSED(void *),
    TCL_UNUSED(size_t),
    TCL_UNUSED(Tcl_Size),
    TCL_UNUSED(Tcl_LoadHandle *),
    TCL_UNUSED(Tcl_FSUnloadFileProc **),
				/* Dummy: unused by this implementation */
    int flags)
    TCL_UNUSED(int))
				/* Dummy: unused by this implementation */
{
    if (interp) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("dynamic loading from memory "
		"is not available on this system", -1));
    }
    return TCL_ERROR;
}

Changes to generic/tclMain.c.

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
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
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
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










-
-
-
+
+
+

















-
+
+














-
+









-
+

-
+








-
-
-
-
-







/*
 * tclMain.c --
 *
 *	Main program for Tcl shells and other Tcl-based applications.
 *	This file contains a generic main program for Tcl shells and other
 *	Tcl-based applications. It can be used as-is for many applications,
 *	just by supplying a different appInitProc function for each specific
 *	application. Or, it can be used as a template for creating new main
 *	programs for Tcl applications.
 *
 * Copyright (c) 1988-1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 2000 Ajuba Solutions.
 * Copyright © 1988-1994 The Regents of the University of California.
 * Copyright © 1994-1997 Sun Microsystems, Inc.
 * Copyright © 2000 Ajuba Solutions.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

/*
 * On Windows, this file needs to be compiled twice, once with UNICODE and
 * _UNICODE defined. This way both Tcl_Main and Tcl_MainExW can be
 * implemented, sharing the same source code.
 */

#include "tclInt.h"

/*
 * The default prompt used when the user has not overridden it.
 */

#define DEFAULT_PRIMARY_PROMPT	"% "
static const char DEFAULT_PRIMARY_PROMPT[] = "% ";
static const char ENCODING_ERROR[] = "\n\t(encoding error in stderr)";

/*
 * This file can be compiled on Windows in UNICODE mode, as well as on all
 * other platforms using the native encoding. This is done by using the normal
 * Windows functions like _tcscmp, but on platforms which don't have <tchar.h>
 * we have to translate that to strcmp here.
 */

#ifndef _WIN32
#   define TCHAR char
#   define TEXT(arg) arg
#   define _tcscmp strcmp
#endif

static Tcl_Obj *
static inline Tcl_Obj *
NewNativeObj(
    TCHAR *string)
{
    Tcl_DString ds;

#ifdef UNICODE
    Tcl_DStringInit(&ds);
    Tcl_WCharToUtfDString(string, -1, &ds);
#else
    Tcl_ExternalToUtfDString(NULL, (char *)string, -1, &ds);
    (void)Tcl_ExternalToUtfDString(NULL, (char *)string, -1, &ds);
#endif
    return TclDStringToObj(&ds);
    return Tcl_DStringToObj(&ds);
}

/*
 * Declarations for various library functions and variables (don't want to
 * include tclPort.h here, because people might copy this file out of the Tcl
 * source directory to make their own modified versions).
 */

#if defined _MSC_VER && _MSC_VER < 1900
/* isatty is always defined on MSVC 14.0, but not necessarily as CRTIMPORT. */
extern CRTIMPORT int	isatty(int fd);
#endif

/*
 * The thread-local variables for this file's functions.
 */

typedef struct {
    Tcl_Obj *path;		/* The filename of the script for *_Main()
				 * routines to [source] as a startup script,
111
112
113
114
115
116
117
118
119


120
121
122
123
124
125
126
107
108
109
110
111
112
113


114
115
116
117
118
119
120
121
122







-
-
+
+








/*
 * Forward declarations for functions defined later in this file.
 */

MODULE_SCOPE Tcl_MainLoopProc *TclGetMainLoop(void);
static void		Prompt(Tcl_Interp *interp, InteractiveState *isPtr);
static void		StdinProc(ClientData clientData, int mask);
static void		FreeMainInterp(ClientData clientData);
static void		StdinProc(void *clientData, int mask);
static void		FreeMainInterp(void *clientData);

#if !defined(_WIN32) || defined(UNICODE) && !defined(TCL_ASCII_MAIN)
static Tcl_ThreadDataKey dataKey;

/*
 *----------------------------------------------------------------------
 *
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
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







-
+


-
+

-
-
+
+
+


+
+
+




-
-
-




-
+
-
-
-







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

void
Tcl_SetStartupScript(
    Tcl_Obj *path,		/* Filesystem path of startup script file */
    const char *encoding)	/* Encoding of the data in that file */
    const char *encodingName)	/* Encoding of the data in that file */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    Tcl_Obj *newEncoding = NULL;
    Tcl_Obj *encodingObj = NULL;

    if (encoding != NULL) {
	newEncoding = Tcl_NewStringObj(encoding, -1);
    if (encodingName != NULL) {
	encodingObj = Tcl_NewStringObj(encodingName, -1);
	Tcl_IncrRefCount(encodingObj);
    }

    if (path != NULL) {
	Tcl_IncrRefCount(path);
    }
    if (tsdPtr->path != NULL) {
	Tcl_DecrRefCount(tsdPtr->path);
    }
    tsdPtr->path = path;
    if (tsdPtr->path != NULL) {
	Tcl_IncrRefCount(tsdPtr->path);
    }

    if (tsdPtr->encoding != NULL) {
	Tcl_DecrRefCount(tsdPtr->encoding);
    }
    tsdPtr->encoding = newEncoding;
    tsdPtr->encoding = encodingObj;
    if (tsdPtr->encoding != NULL) {
	Tcl_IncrRefCount(tsdPtr->encoding);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetStartupScript --
 *
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
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







-
-
+
+

-
+











-
+
+







				 * (const char *) that points to the
				 * registered encoding name for the startup
				 * script. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (encodingPtr != NULL) {
	if (tsdPtr->encoding == NULL) {
	    *encodingPtr = NULL;
	if (tsdPtr->encoding != NULL) {
	    *encodingPtr = Tcl_GetString(tsdPtr->encoding);
	} else {
	    *encodingPtr = TclGetString(tsdPtr->encoding);
	    *encodingPtr = NULL;
	}
    }
    return tsdPtr->path;
}

/*----------------------------------------------------------------------
 *
 * Tcl_SourceRCFile --
 *
 *	This function is typically invoked by Tcl_Main of Tk_Main function to
 *	source an application specific rc file into the interpreter at startup
 *	time.
 *	time. If the filename cannot be translated (e.g. it referred to a bogus
 *	user or there was no HOME environment variable). Just do nothing.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Depends on what's in the rc script.
 *
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
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







-
+
-
-
-
-
-
-










-
+
+
+







    fileName = Tcl_GetVar2(interp, "tcl_rcFileName", NULL, TCL_GLOBAL_ONLY);
    if (fileName != NULL) {
	Tcl_Channel c;
	const char *fullName;

	Tcl_DStringInit(&temp);
	fullName = Tcl_TranslateFileName(interp, fileName, &temp);
	if (fullName == NULL) {
	if (fullName != NULL) {
	    /*
	     * Couldn't translate the file name (e.g. it referred to a bogus
	     * user or there was no HOME environment variable). Just do
	     * nothing.
	     */
	} else {
	    /*
	     * Test for the existence of the rc file before trying to read it.
	     */

	    c = Tcl_OpenFileChannel(NULL, fullName, "r", 0);
	    if (c != NULL) {
		Tcl_CloseEx(NULL, c, 0);
		if (Tcl_EvalFile(interp, fullName) != TCL_OK) {
		    chan = Tcl_GetStdChannel(TCL_STDERR);
		    if (chan) {
			Tcl_WriteObj(chan, Tcl_GetObjResult(interp));
			if (Tcl_WriteObj(chan, Tcl_GetObjResult(interp)) < 0) {
			    Tcl_WriteChars(chan, ENCODING_ERROR, -1);
			}
			Tcl_WriteChars(chan, "\n", 1);
		    }
		}
	    }
	}
	Tcl_DStringFree(&temp);
    }
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
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







-
+







+








+
+
+
+
-
+
+







 *	interpreted.
 *
 *----------------------------------------------------------------------
 */

TCL_NORETURN void
Tcl_MainEx(
    int argc,			/* Number of arguments. */
    Tcl_Size argc,			/* Number of arguments. */
    TCHAR **argv,		/* Array of argument strings. */
    Tcl_AppInitProc *appInitProc,
				/* Application-specific initialization
				 * function to call after most initialization
				 * but before starting to execute commands. */
    Tcl_Interp *interp)
{
    Tcl_Size i=0;		/* argv[i] index */
    Tcl_Obj *path, *resultPtr, *argvPtr, *appName;
    const char *encodingName = NULL;
    int code, exitCode = 0;
    Tcl_MainLoopProc *mainLoopProc;
    Tcl_Channel chan;
    InteractiveState is;

    TclpSetInitialEncodings();
    if (argc > 0) {
	--argc;			/* consume argv[0] */
	++i;
    }
    TclpFindExecutable((const char *)argv[0]);
    TclpFindExecutable((const char *)argv[0]);	/* nb: this could be NULL
						 * w/ (eg) an empty argv supplied to execve() */

    Tcl_InitMemory(interp);

    is.interp = interp;
    is.prompt = PROMPT_START;
    TclNewObj(is.commandPtr);

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

366
367
368
369
370
371
372
373
374
375
376
377



378
379
380
381
382
383
384
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
366
367
368
369
370
371
372
373
374

375
376
377
378
379
380
381
382
383
384







+
-
+



-
+


-
-
+
+


-
+




-
+
+
+


-
+


-
-





-
+









-
+











-
+
+
+







	/*
	 * Check whether first 3 args (argv[1] - argv[3]) look like
	 *  -encoding ENCODING FILENAME
	 * or like
	 *  FILENAME
	 */

	/* mind argc is being adjusted as we proceed */
	if ((argc > 3) && (0 == _tcscmp(TEXT("-encoding"), argv[1]))
	if ((argc >= 3) && (0 == _tcscmp(TEXT("-encoding"), argv[1]))
		&& ('-' != argv[3][0])) {
	    Tcl_Obj *value = NewNativeObj(argv[2]);
	    Tcl_SetStartupScript(NewNativeObj(argv[3]),
		    TclGetString(value));
		    Tcl_GetString(value));
	    Tcl_DecrRefCount(value);
	    argc -= 3;
	    argv += 3;
	} else if ((argc > 1) && ('-' != argv[1][0])) {
	    i += 3;
	} else if ((argc >= 1) && ('-' != argv[1][0])) {
	    Tcl_SetStartupScript(NewNativeObj(argv[1]), NULL);
	    argc--;
	    argv++;
	    i++;
	}
    }

    path = Tcl_GetStartupScript(&encodingName);
    if (path == NULL) {
    if (path != NULL) {
	appName = path;
    } else if (argv[0]) {
	appName = NewNativeObj(argv[0]);
    } else {
	appName = path;
	appName = Tcl_NewStringObj("tclsh", -1);
    }
    Tcl_SetVar2Ex(interp, "argv0", NULL, appName, TCL_GLOBAL_ONLY);
    argc--;
    argv++;

    Tcl_SetVar2Ex(interp, "argc", NULL, Tcl_NewWideIntObj(argc), TCL_GLOBAL_ONLY);

    argvPtr = Tcl_NewListObj(0, NULL);
    while (argc--) {
	Tcl_ListObjAppendElement(NULL, argvPtr, NewNativeObj(*argv++));
	Tcl_ListObjAppendElement(NULL, argvPtr, NewNativeObj(argv[i++]));
    }
    Tcl_SetVar2Ex(interp, "argv", NULL, argvPtr, TCL_GLOBAL_ONLY);

    /*
     * Set the "tcl_interactive" variable.
     */

    is.tty = isatty(0);
    Tcl_SetVar2Ex(interp, "tcl_interactive", NULL,
	    Tcl_NewWideIntObj(!path && is.tty), TCL_GLOBAL_ONLY);
	    Tcl_NewBooleanObj(!path && is.tty), TCL_GLOBAL_ONLY);

    /*
     * Invoke application-specific initialization.
     */

    Tcl_Preserve(interp);
    if (appInitProc(interp) != TCL_OK) {
	chan = Tcl_GetStdChannel(TCL_STDERR);
	if (chan) {
	    Tcl_WriteChars(chan,
		    "application-specific initialization failed: ", -1);
	    Tcl_WriteObj(chan, Tcl_GetObjResult(interp));
	    if (Tcl_WriteObj(chan, Tcl_GetObjResult(interp)) < 0) {
		Tcl_WriteChars(chan, ENCODING_ERROR, -1);
	    }
	    Tcl_WriteChars(chan, "\n", 1);
	}
    }
    if (Tcl_InterpDeleted(interp)) {
	goto done;
    }
    if (Tcl_LimitExceeded(interp)) {
402
403
404
405
406
407
408
409

410
411
412
413

414
415
416
417



418
419
420
421
422
423
424
402
403
404
405
406
407
408

409
410



411


412

413
414
415
416
417
418
419
420
421
422







-
+

-
-
-
+
-
-

-
+
+
+







    if (path != NULL) {
	Tcl_ResetResult(interp);
	code = Tcl_FSEvalFileEx(interp, path, encodingName);
	if (code != TCL_OK) {
	    chan = Tcl_GetStdChannel(TCL_STDERR);
	    if (chan) {
		Tcl_Obj *options = Tcl_GetReturnOptions(interp, code);
		Tcl_Obj *keyPtr, *valuePtr;
		Tcl_Obj *valuePtr = NULL;

		TclNewLiteralStringObj(keyPtr, "-errorinfo");
		Tcl_IncrRefCount(keyPtr);
		Tcl_DictObjGet(NULL, options, keyPtr, &valuePtr);
		TclDictGet(NULL, options, "-errorinfo", &valuePtr);
		Tcl_DecrRefCount(keyPtr);

		if (valuePtr) {
		    Tcl_WriteObj(chan, valuePtr);
		    if (Tcl_WriteObj(chan, valuePtr) < 0) {
			Tcl_WriteChars(chan, ENCODING_ERROR, -1);
		    }
		}
		Tcl_WriteChars(chan, "\n", 1);
		Tcl_DecrRefCount(options);
	    }
	    exitCode = 1;
	}
	goto done;
447
448
449
450
451
452
453
454

455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475

476
477
478
479
480
481
482
445
446
447
448
449
450
451

452
453
454
455
456
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_LinkVar(interp, "tcl_interactive", &is.tty, TCL_LINK_BOOLEAN);
    is.input = Tcl_GetStdChannel(TCL_STDIN);
    while ((is.input != NULL) && !Tcl_InterpDeleted(interp)) {
	mainLoopProc = TclGetMainLoop();
	if (mainLoopProc == NULL) {
	    size_t length;
	    Tcl_Size length;

	    if (is.tty) {
		Prompt(interp, &is);
		if (Tcl_InterpDeleted(interp)) {
		    break;
		}
		if (Tcl_LimitExceeded(interp)) {
		    break;
		}
		is.input = Tcl_GetStdChannel(TCL_STDIN);
		if (is.input == NULL) {
		    break;
		}
	    }
	    if (Tcl_IsShared(is.commandPtr)) {
		Tcl_DecrRefCount(is.commandPtr);
		is.commandPtr = Tcl_DuplicateObj(is.commandPtr);
		Tcl_IncrRefCount(is.commandPtr);
	    }
	    length = Tcl_GetsObj(is.input, is.commandPtr);
	    if (length == TCL_INDEX_NONE) {
	    if (length < 0) {
		if (Tcl_InputBlocked(is.input)) {
		    /*
		     * This can only happen if stdin has been set to
		     * non-blocking. In that case cycle back and try again.
		     * This sets up a tight polling loop (since we have no
		     * event loop running). If this causes bad CPU hogging, we
		     * might try toggling the blocking on stdin instead.
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
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







-
+










-
+
+
+





-
+


-
+
+
+







	    is.prompt = PROMPT_START;

	    /*
	     * The final newline is syntactically redundant, and causes some
	     * error messages troubles deeper in, so lop it back off.
	     */

	    (void)TclGetStringFromObj(is.commandPtr, &length);
	    (void)Tcl_GetStringFromObj(is.commandPtr, &length);
	    Tcl_SetObjLength(is.commandPtr, --length);
	    code = Tcl_RecordAndEvalObj(interp, is.commandPtr,
		    TCL_EVAL_GLOBAL);
	    is.input = Tcl_GetStdChannel(TCL_STDIN);
	    Tcl_DecrRefCount(is.commandPtr);
	    TclNewObj(is.commandPtr);
	    Tcl_IncrRefCount(is.commandPtr);
	    if (code != TCL_OK) {
		chan = Tcl_GetStdChannel(TCL_STDERR);
		if (chan) {
		    Tcl_WriteObj(chan, Tcl_GetObjResult(interp));
			if (Tcl_WriteObj(chan, Tcl_GetObjResult(interp)) < 0) {
			    Tcl_WriteChars(chan, ENCODING_ERROR, -1);
			}
		    Tcl_WriteChars(chan, "\n", 1);
		}
	    } else if (is.tty) {
		resultPtr = Tcl_GetObjResult(interp);
		Tcl_IncrRefCount(resultPtr);
		(void)TclGetStringFromObj(resultPtr, &length);
		(void)Tcl_GetStringFromObj(resultPtr, &length);
		chan = Tcl_GetStdChannel(TCL_STDOUT);
		if ((length > 0) && chan) {
		    Tcl_WriteObj(chan, resultPtr);
		    if (Tcl_WriteObj(chan, resultPtr) < 0) {
			Tcl_WriteChars(chan, ENCODING_ERROR, -1);
		    }
		    Tcl_WriteChars(chan, "\n", 1);
		}
		Tcl_DecrRefCount(resultPtr);
	    }
	} else {	/* (mainLoopProc != NULL) */
	    /*
	     * If a main loop has been defined while running interactively, we
729
730
731
732
733
734
735
736

737
738
739
740

741
742
743
744
745
746
747
748
749
750
751
752

753
754
755
756
757
758
759
731
732
733
734
735
736
737

738
739
740
741

742
743
744
745
746
747
748
749
750
751
752
753

754
755
756
757
758
759
760
761







-
+



-
+











-
+







 *	Could be almost arbitrary, depending on the command that's typed.
 *
 *----------------------------------------------------------------------
 */

static void
StdinProc(
    ClientData clientData,	/* The state of interactive cmd line */
    void *clientData,	/* The state of interactive cmd line */
    TCL_UNUSED(int) /*mask*/)
{
    int code;
    size_t length;
    Tcl_Size length;
    InteractiveState *isPtr = (InteractiveState *)clientData;
    Tcl_Channel chan = isPtr->input;
    Tcl_Obj *commandPtr = isPtr->commandPtr;
    Tcl_Interp *interp = isPtr->interp;

    if (Tcl_IsShared(commandPtr)) {
	Tcl_DecrRefCount(commandPtr);
	commandPtr = Tcl_DuplicateObj(commandPtr);
	Tcl_IncrRefCount(commandPtr);
    }
    length = Tcl_GetsObj(chan, commandPtr);
    if (length == TCL_INDEX_NONE) {
    if (length < 0) {
	if (Tcl_InputBlocked(chan)) {
	    return;
	}
	if (isPtr->tty) {
	    /*
	     * Would be better to find a way to exit the mainLoop? Or perhaps
	     * evaluate [exit]? Leaving as is for now due to compatibility
773
774
775
776
777
778
779
780

781
782
783
784
785
786
787
775
776
777
778
779
780
781

782
783
784
785
786
787
788
789







-
+







    }
    Tcl_AppendToObj(commandPtr, "\n", 1);
    if (!TclObjCommandComplete(commandPtr)) {
	isPtr->prompt = PROMPT_CONTINUE;
	goto prompt;
    }
    isPtr->prompt = PROMPT_START;
    (void)TclGetStringFromObj(commandPtr, &length);
    (void)Tcl_GetStringFromObj(commandPtr, &length);
    Tcl_SetObjLength(commandPtr, --length);

    /*
     * Disable the stdin channel handler while evaluating the command;
     * otherwise if the command re-enters the event loop we might process
     * commands from stdin before the current command is finished. Among other
     * things, this will trash the text of the command being evaluated.
797
798
799
800
801
802
803
804



805
806
807
808
809
810
811
812

813
814



815
816
817
818
819
820
821
799
800
801
802
803
804
805

806
807
808
809
810
811
812
813
814
815

816
817

818
819
820
821
822
823
824
825
826
827







-
+
+
+







-
+

-
+
+
+







    if (chan != NULL) {
	Tcl_CreateChannelHandler(chan, TCL_READABLE, StdinProc, isPtr);
    }
    if (code != TCL_OK) {
	chan = Tcl_GetStdChannel(TCL_STDERR);

	if (chan != NULL) {
	    Tcl_WriteObj(chan, Tcl_GetObjResult(interp));
	    if (Tcl_WriteObj(chan, Tcl_GetObjResult(interp)) < 0) {
		Tcl_WriteChars(chan, ENCODING_ERROR, -1);
	    }
	    Tcl_WriteChars(chan, "\n", 1);
	}
    } else if (isPtr->tty) {
	Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
	chan = Tcl_GetStdChannel(TCL_STDOUT);

	Tcl_IncrRefCount(resultPtr);
	(void)TclGetStringFromObj(resultPtr, &length);
	(void)Tcl_GetStringFromObj(resultPtr, &length);
	if ((length > 0) && (chan != NULL)) {
	    Tcl_WriteObj(chan, resultPtr);
	    if (Tcl_WriteObj(chan, resultPtr) < 0) {
		Tcl_WriteChars(chan, ENCODING_ERROR, -1);
	    }
	    Tcl_WriteChars(chan, "\n", 1);
	}
	Tcl_DecrRefCount(resultPtr);
    }

    /*
     * If a tty stdin is still around, output a prompt.
868
869
870
871
872
873
874
875

876
877
878
879
880
881
882
883
884
885



886
887
888
889
890
891
892
874
875
876
877
878
879
880

881
882
883
884
885
886
887
888
889
890

891
892
893
894
895
896
897
898
899
900







-
+









-
+
+
+







    }
    if (promptCmdPtr == NULL) {
    defaultPrompt:
	if (isPtr->prompt == PROMPT_START) {
	    chan = Tcl_GetStdChannel(TCL_STDOUT);
	    if (chan != NULL) {
		Tcl_WriteChars(chan, DEFAULT_PRIMARY_PROMPT,
			strlen(DEFAULT_PRIMARY_PROMPT));
			sizeof(DEFAULT_PRIMARY_PROMPT) - 1);
	    }
	}
    } else {
	code = Tcl_EvalObjEx(interp, promptCmdPtr, TCL_EVAL_GLOBAL);
	if (code != TCL_OK) {
	    Tcl_AddErrorInfo(interp,
		    "\n    (script that generates prompt)");
	    chan = Tcl_GetStdChannel(TCL_STDERR);
	    if (chan != NULL) {
		Tcl_WriteObj(chan, Tcl_GetObjResult(interp));
		if (Tcl_WriteObj(chan, Tcl_GetObjResult(interp)) < 0) {
		    Tcl_WriteChars(chan, ENCODING_ERROR, -1);
		}
		Tcl_WriteChars(chan, "\n", 1);
	    }
	    goto defaultPrompt;
	}
    }

    chan = Tcl_GetStdChannel(TCL_STDOUT);
905
906
907
908
909
910
911
912

913
914
915
916
917
918
919
913
914
915
916
917
918
919

920
921
922
923
924
925
926
927







-
+







 *	startup script storage at exit.
 *
 *----------------------------------------------------------------------
 */

static void
FreeMainInterp(
    ClientData clientData)
    void *clientData)
{
    Tcl_Interp *interp = (Tcl_Interp *)clientData;

    /*if (TclInExit()) return;*/

    if (!Tcl_InterpDeleted(interp)) {
	Tcl_DeleteInterp(interp);

Changes to generic/tclNamesp.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14





15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9





10
11
12
13
14
15
16
17
18
19
20
21









-
-
-
-
-
+
+
+
+
+







/*
 * tclNamesp.c --
 *
 *	Contains support for namespaces, which provide a separate context of
 *	commands and global variables. The global :: namespace is the
 *	traditional Tcl "global" scope. Other namespaces are created as
 *	children of the global namespace. These other namespaces contain
 *	special-purpose commands and variables for packages.
 *
 * Copyright (c) 1993-1997 Lucent Technologies.
 * Copyright (c) 1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright (c) 2002-2005 Donal K. Fellows.
 * Copyright (c) 2006 Neil Madden.
 * Copyright © 1993-1997 Lucent Technologies.
 * Copyright © 1997 Sun Microsystems, Inc.
 * Copyright © 1998-1999 Scriptics Corporation.
 * Copyright © 2002-2005 Donal K. Fellows.
 * Copyright © 2006 Neil Madden.
 * Contributions from Don Porter, NIST, 2007. (not subject to US copyright)
 *
 * Originally implemented by
 *   Michael J. McLennan
 *   Bell Labs Innovations for Lucent Technologies
 *   mmclennan@lucent.com
 *
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
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







-
+




-
-
+
+
+

-
+

-
+


-
+





-
-
+
+
+







				 * becomes zero. */
} ResolvedNsName;

/*
 * Declarations for functions local to this file:
 */

static void		DeleteImportedCmd(ClientData clientData);
static void		DeleteImportedCmd(void *clientData);
static int		DoImport(Tcl_Interp *interp,
			    Namespace *nsPtr, Tcl_HashEntry *hPtr,
			    const char *cmdName, const char *pattern,
			    Namespace *importNsPtr, int allowOverwrite);
static void		DupNsNameInternalRep(Tcl_Obj *objPtr,Tcl_Obj *copyPtr);
static char *		ErrorCodeRead(ClientData clientData,Tcl_Interp *interp,
static void		DupNsNameInternalRep(Tcl_Obj *objPtr,
			    Tcl_Obj *copyPtr);
static char *		ErrorCodeRead(void *clientData, Tcl_Interp *interp,
			    const char *name1, const char *name2, int flags);
static char *		ErrorInfoRead(ClientData clientData,Tcl_Interp *interp,
static char *		ErrorInfoRead(void *clientData, Tcl_Interp *interp,
			    const char *name1, const char *name2, int flags);
static char *		EstablishErrorCodeTraces(ClientData clientData,
static char *		EstablishErrorCodeTraces(void *clientData,
			    Tcl_Interp *interp, const char *name1,
			    const char *name2, int flags);
static char *		EstablishErrorInfoTraces(ClientData clientData,
static char *		EstablishErrorInfoTraces(void *clientData,
			    Tcl_Interp *interp, const char *name1,
			    const char *name2, int flags);
static void		FreeNsNameInternalRep(Tcl_Obj *objPtr);
static int		GetNamespaceFromObj(Tcl_Interp *interp,
			    Tcl_Obj *objPtr, Tcl_Namespace **nsPtrPtr);
static int		InvokeImportedNRCmd(ClientData clientData,
			    Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]);
static int		InvokeImportedNRCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static Tcl_ObjCmdProc	NamespaceChildrenCmd;
static Tcl_ObjCmdProc	NamespaceCodeCmd;
static Tcl_ObjCmdProc	NamespaceCurrentCmd;
static Tcl_ObjCmdProc	NamespaceDeleteCmd;
static Tcl_ObjCmdProc	NamespaceEvalCmd;
static Tcl_ObjCmdProc	NRNamespaceEvalCmd;
static Tcl_ObjCmdProc	NamespaceExistsCmd;
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
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







-
+
+


-
+

-
+



-
+


-
+

-
-
-
+
+
+







 */

static const Tcl_ObjType nsNameType = {
    "nsName",			/* the type's name */
    FreeNsNameInternalRep,	/* freeIntRepProc */
    DupNsNameInternalRep,	/* dupIntRepProc */
    NULL,			/* updateStringProc */
    SetNsNameFromAny		/* setFromAnyProc */
    SetNsNameFromAny,		/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

#define NsNameSetIntRep(objPtr, nnPtr)					\
#define NsNameSetInternalRep(objPtr, nnPtr) \
    do {								\
	Tcl_ObjIntRep ir;						\
	Tcl_ObjInternalRep ir;						\
	(nnPtr)->refCount++;						\
	ir.twoPtrValue.ptr1 = (nnPtr);					\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreIntRep((objPtr), &nsNameType, &ir);			\
	Tcl_StoreInternalRep((objPtr), &nsNameType, &ir);		\
    } while (0)

#define NsNameGetIntRep(objPtr, nnPtr)					\
#define NsNameGetInternalRep(objPtr, nnPtr) \
    do {								\
	const Tcl_ObjIntRep *irPtr;					\
	irPtr = TclFetchIntRep((objPtr), &nsNameType);			\
	(nnPtr) = irPtr ? (ResolvedNsName *)irPtr->twoPtrValue.ptr1 : NULL;		\
	const Tcl_ObjInternalRep *irPtr;				\
	irPtr = TclFetchInternalRep((objPtr), &nsNameType);		\
	(nnPtr) = irPtr ? (ResolvedNsName *) irPtr->twoPtrValue.ptr1 : NULL; \
    } while (0)

/*
 * Array of values describing how to implement each standard subcommand of the
 * "namespace" command.
 */

172
173
174
175
176
177
178





















































































































179
180
181
182
183
184
185
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    {"qualifiers", NamespaceQualifiersCmd, TclCompileNamespaceQualifiersCmd, NULL, NULL, 0},
    {"tail",	   NamespaceTailCmd,	TclCompileNamespaceTailCmd, NULL, NULL, 0},
    {"unknown",	   NamespaceUnknownCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
    {"upvar",	   NamespaceUpvarCmd,	TclCompileNamespaceUpvarCmd, NULL, NULL, 0},
    {"which",	   NamespaceWhichCmd,	TclCompileNamespaceWhichCmd, NULL, NULL, 0},
    {NULL, NULL, NULL, NULL, NULL, 0}
};

/*
 *----------------------------------------------------------------------
 *
 * CreateChildEntry --
 *
 *	Create a child namespace hash table entry.
 *
 * Results:
 *	Handle to hash table entry for a child namespace with the given name.
 *	Caller should handle filling in the namespace value.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
static inline Tcl_HashEntry *
CreateChildEntry(
    Namespace *nsPtr,		/* Parent namespace. */
    const char *name,		/* Simple name to look for. */
    int *isNewPtr)		/* Pointer to var with whether this is new. */
{
#ifndef BREAK_NAMESPACE_COMPAT
    return Tcl_CreateHashEntry(&nsPtr->childTable, name, isNewPtr);
#else
    if )nsPtr->childTablePtr == NULL) {
	nsPtr->childTablePtr = (Tcl_HashTable *)
		Tcl_Alloc(sizeof(Tcl_HashTable));
	Tcl_InitHashTable(nsPtr->childTablePtr, TCL_STRING_KEYS);
    }
    return Tcl_CreateHashEntry(nsPtr->childTablePtr, name, isNewPtr);
#endif
}

/*
 *----------------------------------------------------------------------
 *
 * FindChildEntry --
 *
 *	Look up a child namespace hash table entry.
 *
 * Results:
 *	Handle to hash table entry if a child namespace with the given name
 *	exists, otherwise NULL.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
static inline Tcl_HashEntry *
FindChildEntry(
    Namespace *nsPtr,		/* Parent namespace. */
    const char *name)		/* Simple name to look for. */
{
#ifndef BREAK_NAMESPACE_COMPAT
    return Tcl_FindHashEntry(&nsPtr->childTable, name);
#else
    return nsPtr->childTablePtr ?
	    Tcl_FindHashEntry(nsPtr->childTablePtr, name) : NULL;
#endif
}

/*
 *----------------------------------------------------------------------
 *
 * FirstChildEntry --
 *
 *	Start an iteration through the collection of child namespaces.
 *
 * Results:
 *	Handle to hash table entry if a child namespace exists, otherwise NULL.
 *
 * Side effects:
 *	Updates the search handle.
 *
 *----------------------------------------------------------------------
 */
static inline Tcl_HashEntry *
FirstChildEntry(
    Namespace *nsPtr,		/* Parent namespace. */
    Tcl_HashSearch *searchPtr)	/* Iteration handle reference. */
{
#ifndef BREAK_NAMESPACE_COMPAT
    return Tcl_FirstHashEntry(&nsPtr->childTable, searchPtr);
#else
    return nsPtr->childTablePtr ?
	    Tcl_FirstHashEntry(nsPtr->childTablePtr, searchPtr) : NULL;
#endif
}

/*
 *----------------------------------------------------------------------
 *
 * NumChildEntries --
 *
 *	Get the count of child namespaces.
 *
 * Results:
 *	Number of child entries.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
static inline Tcl_Size
NumChildEntries(
    Namespace *nsPtr)
{
#ifndef BREAK_NAMESPACE_COMPAT
    return nsPtr->childTable.numEntries;
#else
    return nsPtr->childTablePtr ? nsPtr->childTablePtr->numEntries : 0;
#endif
}

/*
 *----------------------------------------------------------------------
 *
 * TclInitNamespaceSubsystem --
 *
 *	This function is called to initialize all the structures that are used
216
217
218
219
220
221
222
223

224
225
226
227
228
229
230
336
337
338
339
340
341
342

343
344
345
346
347
348
349
350







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Namespace *
Tcl_GetCurrentNamespace(
    Tcl_Interp *interp)/* Interpreter whose current namespace is
    Tcl_Interp *interp)		/* Interpreter whose current namespace is
				 * being queried. */
{
    return TclGetCurrentNamespace(interp);
}

/*
 *----------------------------------------------------------------------
240
241
242
243
244
245
246
247

248
249
250
251
252
253
254
360
361
362
363
364
365
366

367
368
369
370
371
372
373
374







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Namespace *
Tcl_GetGlobalNamespace(
    Tcl_Interp *interp)/* Interpreter whose global namespace should
    Tcl_Interp *interp)		/* Interpreter whose global namespace should
				 * be returned. */
{
    return TclGetGlobalNamespace(interp);
}

/*
 *----------------------------------------------------------------------
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
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







-
+



















-
+







    if (namespacePtr == NULL) {
	nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
    } else {
	nsPtr = (Namespace *) namespacePtr;

	/*
	 * TODO: Examine whether it would be better to guard based on NS_DYING
	 * or NS_KILLED. It appears that these are not tested because they can
	 * or NS_TEARDOWN. It appears that these are not tested because they can
	 * be set in a global interp that has been [namespace delete]d, but
	 * which never really completely goes away because of lingering global
	 * things like ::errorInfo and [::unknown] and hidden commands.
	 * Review of those designs might permit stricter checking here.
	 */

	if (nsPtr->flags & NS_DEAD) {
	    Tcl_Panic("Trying to push call frame for dead namespace");
	}
    }

    nsPtr->activationCount++;
    framePtr->nsPtr = nsPtr;
    framePtr->isProcCallFrame = isProcCallFrame;
    framePtr->objc = 0;
    framePtr->objv = NULL;
    framePtr->callerPtr = iPtr->framePtr;
    framePtr->callerVarPtr = iPtr->varFramePtr;
    if (iPtr->varFramePtr != NULL) {
	framePtr->level = (iPtr->varFramePtr->level + 1);
	framePtr->level = iPtr->varFramePtr->level + 1U;
    } else {
	framePtr->level = 0;
    }
    framePtr->procPtr = NULL;		/* no called procedure */
    framePtr->varTablePtr = NULL;	/* and no local variables */
    framePtr->numCompiledLocals = 0;
    framePtr->compiledLocals = NULL;
405
406
407
408
409
410
411
412

413
414
415
416
417
418


419
420
421
422
423
424
425
525
526
527
528
529
530
531

532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547







-
+






+
+







    /*
     * Decrement the namespace's count of active call frames. If the namespace
     * is "dying" and there are no more active call frames, call
     * Tcl_DeleteNamespace to destroy it.
     */

    nsPtr = framePtr->nsPtr;
    if ((--nsPtr->activationCount <= (unsigned)(nsPtr == iPtr->globalNsPtr))
    if ((--nsPtr->activationCount <= (nsPtr == iPtr->globalNsPtr))
	    && (nsPtr->flags & NS_DYING)) {
	Tcl_DeleteNamespace((Tcl_Namespace *) nsPtr);
    }
    framePtr->nsPtr = NULL;

    if (framePtr->tailcallPtr) {
	/* Reusing the existing reference count from framePtr->tailcallPtr, so
	 * no need to Tcl_IncrRefCount(framePtr->tailcallPtr)*/
	TclSetTailcall(interp, framePtr->tailcallPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
454
455
456
457
458
459
460
461

462
463
464
465
466
467
468
576
577
578
579
580
581
582

583
584
585
586
587
588
589
590







-
+







				 * If new variables are created, they will be
				 * created in the frame. If 0, the frame is
				 * for a "namespace eval" or "namespace
				 * inscope" command and var references are
				 * treated as references to namespace
				 * variables. */
{
    *framePtrPtr = (Tcl_CallFrame *)TclStackAlloc(interp, sizeof(CallFrame));
    *framePtrPtr = (Tcl_CallFrame *) TclStackAlloc(interp, sizeof(CallFrame));
    return Tcl_PushCallFrame(interp, *framePtrPtr, namespacePtr,
	    isProcCallFrame);
}

void
TclPopStackFrame(
    Tcl_Interp *interp)		/* Interpreter with call frame to pop. */
488
489
490
491
492
493
494
495

496
497
498
499
500
501
502
610
611
612
613
614
615
616

617
618
619
620
621
622
623
624







-
+







 *	Read and unset traces are established on ::errorCode.
 *
 *----------------------------------------------------------------------
 */

static char *
EstablishErrorCodeTraces(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    TCL_UNUSED(const char *) /*name1*/,
    TCL_UNUSED(const char *) /*name2*/,
    TCL_UNUSED(int) /*flags*/)
{
    Tcl_TraceVar2(interp, "errorCode", NULL, TCL_GLOBAL_ONLY|TCL_TRACE_READS,
	    ErrorCodeRead, NULL);
520
521
522
523
524
525
526
527

528
529
530
531
532
533
534
642
643
644
645
646
647
648

649
650
651
652
653
654
655
656







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static char *
ErrorCodeRead(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    TCL_UNUSED(const char *) /*name1*/,
    TCL_UNUSED(const char *) /*name2*/,
    TCL_UNUSED(int) /*flags*/)
{
    Interp *iPtr = (Interp *) interp;

562
563
564
565
566
567
568
569

570
571
572
573
574
575
576
684
685
686
687
688
689
690

691
692
693
694
695
696
697
698







-
+







 *	Read and unset traces are established on ::errorInfo.
 *
 *----------------------------------------------------------------------
 */

static char *
EstablishErrorInfoTraces(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    TCL_UNUSED(const char *) /*name1*/,
    TCL_UNUSED(const char *) /*name2*/,
    TCL_UNUSED(int) /*flags*/)
{
    Tcl_TraceVar2(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY|TCL_TRACE_READS,
	    ErrorInfoRead, NULL);
594
595
596
597
598
599
600
601

602
603
604
605
606
607
608
716
717
718
719
720
721
722

723
724
725
726
727
728
729
730







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static char *
ErrorInfoRead(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    TCL_UNUSED(const char *) /*name1*/,
    TCL_UNUSED(const char *) /*name2*/,
    TCL_UNUSED(int) /*flags*/)
{
    Interp *iPtr = (Interp *) interp;

646
647
648
649
650
651
652
653

654
655
656
657
658
659
660
768
769
770
771
772
773
774

775
776
777
778
779
780
781
782







-
+







Tcl_CreateNamespace(
    Tcl_Interp *interp,		/* Interpreter in which a new namespace is
				 * being created. Also used for error
				 * reporting. */
    const char *name,		/* Name for the new namespace. May be a
				 * qualified name with names of ancestor
				 * namespaces separated by "::"s. */
    ClientData clientData,	/* One-word value to store with namespace. */
    void *clientData,		/* One-word value to store with namespace. */
    Tcl_NamespaceDeleteProc *deleteProc)
				/* Function called to delete client data when
				 * the namespace is deleted. NULL if no
				 * function should be called. */
{
    Interp *iPtr = (Interp *) interp;
    Namespace *nsPtr, *ancestorPtr;
708
709
710
711
712
713
714
715

716
717

718
719
720
721
722
723
724
830
831
832
833
834
835
836

837
838

839
840
841
842
843
844
845
846







-
+

-
+







     * If we've ended up with an empty string now, we're attempting to create
     * the global namespace despite the global namespace existing. That's
     * naughty!
     */

    if (*name == '\0') {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("can't create namespace"
                " \"\": only global namespace can have empty name", -1));
		" \"\": only global namespace can have empty name", -1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NAMESPACE",
		"CREATEGLOBAL", NULL);
		"CREATEGLOBAL", (char *)NULL);
	Tcl_DStringFree(&tmpBuffer);
	return NULL;
    }

    /*
     * Find the parent for the new namespace.
     */
738
739
740
741
742
743
744
745
746
747
748
749
750

751
752
753
754
755
756

757
758
759
760
761
762
763
764
765
766
767

768
769

770
771
772
773
774
775
776
860
861
862
863
864
865
866






867


868
869
870

871
872
873
874
875
876
877
878
879
880
881

882
883

884
885
886
887
888
889
890
891







-
-
-
-
-
-
+
-
-



-
+










-
+

-
+







    }

    /*
     * Check for a bad namespace name and make sure that the name does not
     * already exist in the parent namespace.
     */

    if (
#ifndef BREAK_NAMESPACE_COMPAT
	Tcl_FindHashEntry(&parentPtr->childTable, simpleName) != NULL
#else
	parentPtr->childTablePtr != NULL &&
	Tcl_FindHashEntry(parentPtr->childTablePtr, simpleName) != NULL
    if (FindChildEntry(parentPtr, simpleName) != NULL) {
#endif
    ) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't create namespace \"%s\": already exists", name));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NAMESPACE",
		"CREATEEXISTING", NULL);
		"CREATEEXISTING", (char *)NULL);
	Tcl_DStringFree(&tmpBuffer);
	return NULL;
    }

    /*
     * Create the new namespace and root it in its parent. Increment the count
     * of namespaces created.
     */

  doCreate:
    nsPtr = (Namespace *)Tcl_Alloc(sizeof(Namespace));
    nsPtr = (Namespace *) Tcl_Alloc(sizeof(Namespace));
    nameLen = strlen(simpleName) + 1;
    nsPtr->name = (char *)Tcl_Alloc(nameLen);
    nsPtr->name = (char *) Tcl_Alloc(nameLen);
    memcpy(nsPtr->name, simpleName, nameLen);
    nsPtr->fullName = NULL;		/* Set below. */
    nsPtr->clientData = clientData;
    nsPtr->deleteProc = deleteProc;
    nsPtr->parentPtr = parentPtr;
#ifndef BREAK_NAMESPACE_COMPAT
    Tcl_InitHashTable(&nsPtr->childTable, TCL_STRING_KEYS);
797
798
799
800
801
802
803
804
805
806

807
808
809
810
811
812
813
912
913
914
915
916
917
918



919
920
921
922
923
924
925
926







-
-
-
+







    nsPtr->unknownHandlerPtr = NULL;
    nsPtr->commandPathLength = 0;
    nsPtr->commandPathArray = NULL;
    nsPtr->commandPathSourceList = NULL;
    nsPtr->earlyDeleteProc = NULL;

    if (parentPtr != NULL) {
	entryPtr = Tcl_CreateHashEntry(
		TclGetNamespaceChildTable((Tcl_Namespace *) parentPtr),
		simpleName, &newEntry);
	entryPtr = CreateChildEntry(parentPtr, simpleName, &newEntry);
	Tcl_SetHashValue(entryPtr, nsPtr);
    } else {
	/*
	 * In the global namespace create traces to maintain the ::errorInfo
	 * and ::errorCode variables.
	 */

850
851
852
853
854
855
856
857

858
859
860
861
862
863
864
963
964
965
966
967
968
969

970
971
972
973
974
975
976
977







-
+







	    namePtr = buffPtr;
	    buffPtr = tempPtr;
	}
    }

    name = Tcl_DStringValue(namePtr);
    nameLen = Tcl_DStringLength(namePtr);
    nsPtr->fullName = (char *)Tcl_Alloc(nameLen + 1);
    nsPtr->fullName = (char *) Tcl_Alloc(nameLen + 1);
    memcpy(nsPtr->fullName, name, nameLen + 1);

    Tcl_DStringFree(&buffer1);
    Tcl_DStringFree(&buffer2);
    Tcl_DStringFree(&tmpBuffer);

    /*
898
899
900
901
902
903
904
905
906


907
908
909
910
911
912
913
914
1011
1012
1013
1014
1015
1016
1017


1018
1019

1020
1021
1022
1023
1024
1025
1026







-
-
+
+
-







 */

void
Tcl_DeleteNamespace(
    Tcl_Namespace *namespacePtr)/* Points to the namespace to delete. */
{
    Namespace *nsPtr = (Namespace *) namespacePtr;
    Interp *iPtr = (Interp *) nsPtr->interp;
    Namespace *globalNsPtr = (Namespace *)
    Tcl_Interp *interp = nsPtr->interp;
    Namespace *globalNsPtr = (Namespace *) TclGetGlobalNamespace(interp);
	    TclGetGlobalNamespace((Tcl_Interp *) iPtr);
    Tcl_HashEntry *entryPtr;
    Tcl_HashSearch search;
    Command *cmdPtr;

    /*
     * Ensure that this namespace doesn't get deallocated in the meantime.
     */
942
943
944
945
946
947
948
949

950
951

952
953
954
955
956
957
958
959
1054
1055
1056
1057
1058
1059
1060

1061
1062

1063

1064
1065
1066
1067
1068
1069
1070







-
+

-
+
-







     *
     * NOTE: we could avoid traversing the ns's command list by keeping a
     * separate list of coros.
     */

    for (entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
	    entryPtr != NULL;) {
	cmdPtr = (Command *)Tcl_GetHashValue(entryPtr);
	cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
	if (cmdPtr->nreProc == TclNRInterpCoroutine) {
	    Tcl_DeleteCommandFromToken((Tcl_Interp *) iPtr,
	    Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
		    (Tcl_Command) cmdPtr);
	    entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
	} else {
	    entryPtr = Tcl_NextHashEntry(&search);
	}
    }

    /*
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
1024
1025

1026
1027
1028
1029

1030
1031
1032
1033
1034
1035
1036
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
1116

1117
1118
1119



1120
1121
1122
1123
1124
1125

1126
1127
1128
1129

1130
1131
1132
1133
1134

1135
1136
1137
1138

1139
1140
1141
1142
1143
1144
1145
1146







-
+














-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+


-
-
-
+





-
+



-
+




-
+



-
+








	/*
	 * Splice out and link to indicate that we've already been killed.
	 */

	nsPtr->ensembles = (Tcl_Ensemble *) ensemblePtr->next;
	ensemblePtr->next = ensemblePtr;
	Tcl_DeleteCommandFromToken(nsPtr->interp, ensemblePtr->token);
	Tcl_DeleteCommandFromToken(interp, ensemblePtr->token);
    }

    /*
     * If the namespace has a registered unknown handler (TIP 181), then free
     * it here.
     */

    if (nsPtr->unknownHandlerPtr != NULL) {
	Tcl_DecrRefCount(nsPtr->unknownHandlerPtr);
	nsPtr->unknownHandlerPtr = NULL;
    }

    /*
     * If the namespace is on the call frame stack, it is marked as "dying"
     * (NS_DYING is OR'd into its flags): the namespace can't be looked up by
     * name but its commands and variables are still usable by those active
     * call frames. When all active call frames referring to the namespace
     * have been popped from the Tcl stack, Tcl_PopCallFrame will call this
     * function again to delete everything in the namespace. If no nsName
     * objects refer to the namespace (i.e., if its refCount is zero), its
     * commands and variables are deleted and the storage for its namespace
     * structure is freed. Otherwise, if its refCount is nonzero, the
     * namespace's commands and variables are deleted but the structure isn't
     * freed. Instead, NS_DEAD is OR'd into the structure's flags to allow the
     * namespace resolution code to recognize that the namespace is "deleted".
     * The structure's storage is freed by FreeNsNameInternalRep when its
     * refCount reaches 0.
     * (NS_DYING is OR'd into its flags):  Contents of the namespace are
     * still available and visible until the namespace is later marked as
     * NS_DEAD, and its commands and variables are still usable by any
     * active call frames referring to th namespace. When all active call
     * frames referring to the namespace have been popped from the Tcl
     * stack, Tcl_PopCallFrame calls Tcl_DeleteNamespace again. If no
     * nsName objects refer to the namespace (i.e., if its refCount is
     * zero), its commands and variables are deleted and the storage for
     * its namespace structure is freed.  Otherwise, if its refCount is
     * nonzero, the namespace's commands and variables are deleted but the
     * structure isn't freed. Instead, NS_DEAD is OR'd into the structure's
     * flags to allow the namespace resolution code to recognize that the
     * namespace is "deleted".  The structure's storage is freed by
     * FreeNsNameInternalRep when its refCount reaches 0.
     */

    if (nsPtr->activationCount > (unsigned)(nsPtr == globalNsPtr)) {
    if (nsPtr->activationCount > (nsPtr == globalNsPtr)) {
	nsPtr->flags |= NS_DYING;
	if (nsPtr->parentPtr != NULL) {
	    entryPtr = Tcl_FindHashEntry(
		    TclGetNamespaceChildTable((Tcl_Namespace *)
			    nsPtr->parentPtr), nsPtr->name);
	    entryPtr = FindChildEntry(nsPtr->parentPtr, nsPtr->name);
	    if (entryPtr != NULL) {
		Tcl_DeleteHashEntry(entryPtr);
	    }
	}
	nsPtr->parentPtr = NULL;
    } else if (!(nsPtr->flags & NS_KILLED)) {
    } else if (!(nsPtr->flags & NS_TEARDOWN)) {
	/*
	 * Delete the namespace and everything in it. If this is the global
	 * namespace, then clear it but don't free its storage unless the
	 * interpreter is being torn down. Set the NS_KILLED flag to avoid
	 * interpreter is being torn down. Set the NS_TEARDOWN flag to avoid
	 * recursive calls here - if the namespace is really in the process of
	 * being deleted, ignore any second call.
	 */

	nsPtr->flags |= (NS_DYING|NS_KILLED);
	nsPtr->flags |= NS_DYING | NS_TEARDOWN;

	TclTeardownNamespace(nsPtr);

	if ((nsPtr != globalNsPtr) || (iPtr->flags & DELETED)) {
	if ((nsPtr != globalNsPtr) || (((Interp *) interp)->flags & DELETED)) {
	    /*
	     * If this is the global namespace, then it may have residual
	     * "errorInfo" and "errorCode" variables for errors that occurred
	     * while it was being torn down. Try to clear the variable list
	     * one last time.
	     */

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
1158
1159
1160
1161
1162
1163
1164


1165
1166
1167
1168
1169
1170
1171
1172

1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240







-
-
+
+






-
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








	    nsPtr ->flags |= NS_DEAD;
	} else {
	    /*
	     * Restore the ::errorInfo and ::errorCode traces.
	     */

	    EstablishErrorInfoTraces(NULL, nsPtr->interp, NULL, NULL, 0);
	    EstablishErrorCodeTraces(NULL, nsPtr->interp, NULL, NULL, 0);
	    EstablishErrorInfoTraces(NULL, interp, NULL, NULL, 0);
	    EstablishErrorCodeTraces(NULL, interp, NULL, NULL, 0);

	    /*
	     * We didn't really kill it, so remove the KILLED marks, so it can
	     * get killed later, avoiding mem leaks.
	     */

	    nsPtr->flags &= ~(NS_DYING|NS_KILLED);
	    nsPtr->flags &= ~(NS_DYING|NS_TEARDOWN);
	}
    }
    TclNsDecrRefCount(nsPtr);
}

int
TclNamespaceDeleted(
    Namespace *nsPtr)
{
    return (nsPtr->flags & NS_DYING) ? 1 : 0;
}

void
TclDeleteNamespaceChildren(
    Namespace *nsPtr)		/* Namespace whose children to delete */
{
    Tcl_Interp *interp = nsPtr->interp;
    Tcl_HashEntry *entryPtr;
    size_t i;
    int unchecked;
    Tcl_HashSearch search;

    /*
     * Delete all the child namespaces.
     *
     * BE CAREFUL: When each child is deleted, it divorces itself from its
     * parent.  The hash table can't be properly traversed if its elements are
     * being deleted.  Because of traces (and the desire to avoid the
     * quadratic problems of just using Tcl_FirstHashEntry over and over, [Bug
     * f97d4ee020]) copy to a temporary array and then delete all those
     * namespaces.
     *
     * Important: leave the hash table itself still live.
     */

    unchecked = (NumChildEntries(nsPtr) > 0);
    while (NumChildEntries(nsPtr) > 0 && unchecked) {
	size_t length = NumChildEntries(nsPtr);
	Namespace **children = (Namespace **)
		TclStackAlloc(interp, sizeof(Namespace *) * length);

	i = 0;
	for (entryPtr = FirstChildEntry(nsPtr, &search);
		entryPtr != NULL;
		entryPtr = Tcl_NextHashEntry(&search)) {
	    children[i] = (Namespace *) Tcl_GetHashValue(entryPtr);
	    children[i]->refCount++;
	    i++;
	}
	unchecked = 0;
	for (i = 0 ; i < length ; i++) {
	    if (!(children[i]->flags & NS_DYING)) {
		unchecked = 1;
		Tcl_DeleteNamespace((Tcl_Namespace *) children[i]);
		TclNsDecrRefCount(children[i]);
	    }
	}
	TclStackFree(interp, children);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclTeardownNamespace --
 *
 *	Used internally to dismantle and unlink a namespace when it is
1093
1094
1095
1096
1097
1098
1099
1100

1101
1102
1103

1104
1105
1106

1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128


1129
1130
1131
1132
1133
1134
1135

1136
1137
1138
1139
1140

1141
1142
1143
1144

1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156

1157
1158
1159
1160
1161
1162
1163
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







-
+


-
+


-
+




















-
-
+
+






-
+




-
+
-


-
+









-
-
-
+







 *	Deletes all commands, variables and namespaces in this namespace.
 *
 *----------------------------------------------------------------------
 */

void
TclTeardownNamespace(
    Namespace *nsPtr)	/* Points to the namespace to be dismantled
    Namespace *nsPtr)		/* Points to the namespace to be dismantled
				 * and unlinked from its parent. */
{
    Interp *iPtr = (Interp *) nsPtr->interp;
    Tcl_Interp *interp = nsPtr->interp;
    Tcl_HashEntry *entryPtr;
    Tcl_HashSearch search;
    size_t i;
    Tcl_Size i;

    /*
     * Start by destroying the namespace's variable table, since variables
     * might trigger traces. Variable table should be cleared but not freed!
     * TclDeleteNamespaceVars frees it, so we reinitialize it afterwards.
     */

    TclDeleteNamespaceVars(nsPtr);
    TclInitVarHashTable(&nsPtr->varTable, nsPtr);

    /*
     * Delete all commands in this namespace. Be careful when traversing the
     * hash table: when each command is deleted, it removes itself from the
     * command table. Because of traces (and the desire to avoid the quadratic
     * problems of just using Tcl_FirstHashEntry over and over, [Bug
     * f97d4ee020]) we copy to a temporary array and then delete all those
     * commands.
     */

    while (nsPtr->cmdTable.numEntries > 0) {
	size_t length = nsPtr->cmdTable.numEntries;
	Command **cmds = (Command **)TclStackAlloc((Tcl_Interp *) iPtr,
	Tcl_Size length = nsPtr->cmdTable.numEntries;
	Command **cmds = (Command **)TclStackAlloc(interp,
		sizeof(Command *) * length);

	i = 0;
	for (entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
		entryPtr != NULL;
		entryPtr = Tcl_NextHashEntry(&search)) {
	    cmds[i] = (Command *)Tcl_GetHashValue(entryPtr);
	    cmds[i] = (Command *) Tcl_GetHashValue(entryPtr);
	    cmds[i]->refCount++;
	    i++;
	}
	for (i = 0 ; i < length ; i++) {
	    Tcl_DeleteCommandFromToken((Tcl_Interp *) iPtr,
	    Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmds[i]);
		    (Tcl_Command) cmds[i]);
	    TclCleanupCommandMacro(cmds[i]);
	}
	TclStackFree((Tcl_Interp *) iPtr, cmds);
	TclStackFree(interp, cmds);
    }
    Tcl_DeleteHashTable(&nsPtr->cmdTable);
    Tcl_InitHashTable(&nsPtr->cmdTable, TCL_STRING_KEYS);

    /*
     * Remove the namespace from its parent's child hashtable.
     */

    if (nsPtr->parentPtr != NULL) {
	entryPtr = Tcl_FindHashEntry(
		TclGetNamespaceChildTable((Tcl_Namespace *)
			nsPtr->parentPtr), nsPtr->name);
	entryPtr = FindChildEntry(nsPtr->parentPtr, nsPtr->name);
	if (entryPtr != NULL) {
	    Tcl_DeleteHashEntry(entryPtr);
	}
    }
    nsPtr->parentPtr = NULL;

    /*
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192

1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1333
1334
1335
1336
1337
1338
1339









1340















































1341
1342
1343
1344
1345
1346
1347







-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	    }
	    nsPathPtr->nsPtr = NULL;
	    nsPathPtr = nsPathPtr->nextPtr;
	} while (nsPathPtr != NULL);
	nsPtr->commandPathSourceList = NULL;
    }

    /*
     * Delete all the child namespaces.
     *
     * BE CAREFUL: When each child is deleted, it will divorce itself from its
     * parent. You can't traverse a hash table properly if its elements are
     * being deleted.  Because of traces (and the desire to avoid the
     * quadratic problems of just using Tcl_FirstHashEntry over and over, [Bug
     * f97d4ee020]) we copy to a temporary array and then delete all those
     * namespaces.
    TclDeleteNamespaceChildren(nsPtr);
     *
     * Important: leave the hash table itself still live.
     */

#ifndef BREAK_NAMESPACE_COMPAT
    while (nsPtr->childTable.numEntries > 0) {
	size_t length = nsPtr->childTable.numEntries;
	Namespace **children = (Namespace **)TclStackAlloc((Tcl_Interp *) iPtr,
		sizeof(Namespace *) * length);

	i = 0;
	for (entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
		entryPtr != NULL;
		entryPtr = Tcl_NextHashEntry(&search)) {
	    children[i] = (Namespace *)Tcl_GetHashValue(entryPtr);
	    children[i]->refCount++;
	    i++;
	}
	for (i = 0 ; i < length ; i++) {
	    Tcl_DeleteNamespace((Tcl_Namespace *) children[i]);
	    TclNsDecrRefCount(children[i]);
	}
	TclStackFree((Tcl_Interp *) iPtr, children);
    }
#else
    if (nsPtr->childTablePtr != NULL) {
	while (nsPtr->childTablePtr->numEntries > 0) {
	    size_t length = nsPtr->childTablePtr->numEntries;
	    Namespace **children = (Namespace **)TclStackAlloc((Tcl_Interp *) iPtr,
		    sizeof(Namespace *) * length);

	    i = 0;
	    for (entryPtr = Tcl_FirstHashEntry(nsPtr->childTablePtr, &search);
		    entryPtr != NULL;
		    entryPtr = Tcl_NextHashEntry(&search)) {
		children[i] = Tcl_GetHashValue(entryPtr);
		children[i]->refCount++;
		i++;
	    }
	    for (i = 0 ; i < length ; i++) {
		Tcl_DeleteNamespace((Tcl_Namespace *) children[i]);
		TclNsDecrRefCount(children[i]);
	    }
	    TclStackFree((Tcl_Interp *) iPtr, children);
	}
    }
#endif

    /*
     * Free the namespace's export pattern array.
     */

    if (nsPtr->exportArrayPtr != NULL) {
	for (i = 0;  i < nsPtr->numExportPatterns;  i++) {
1286
1287
1288
1289
1290
1291
1292
1293

1294
1295
1296
1297
1298
1299
1300
1387
1388
1389
1390
1391
1392
1393

1394
1395
1396
1397
1398
1399
1400
1401







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
NamespaceFree(
    Namespace *nsPtr)	/* Points to the namespace to free. */
    Namespace *nsPtr)		/* Points to the namespace to free. */
{
    /*
     * Most of the namespace's contents are freed when the namespace is
     * deleted by Tcl_DeleteNamespace. All that remains is to free its names
     * (for error messages), and the structure itself.
     */

1365
1366
1367
1368
1369
1370
1371
1372

1373
1374
1375
1376
1377
1378
1379
1466
1467
1468
1469
1470
1471
1472

1473
1474
1475
1476
1477
1478
1479
1480







-
+







				 * list before appending. */
{
#define INIT_EXPORT_PATTERNS 5
    Namespace *nsPtr, *exportNsPtr, *dummyPtr;
    Namespace *currNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
    const char *simplePattern;
    char *patternCpy;
    size_t neededElems, len, i;
    Tcl_Size neededElems, len, i;

    /*
     * If the specified namespace is NULL, use the current namespace.
     */

    if (namespacePtr == NULL) {
	nsPtr = (Namespace *) currNsPtr;
1404
1405
1406
1407
1408
1409
1410
1411
1412


1413
1414
1415
1416
1417
1418
1419
1505
1506
1507
1508
1509
1510
1511


1512
1513
1514
1515
1516
1517
1518
1519
1520







-
-
+
+







     */

    TclGetNamespaceForQualName(interp, pattern, nsPtr, TCL_NAMESPACE_ONLY,
	    &exportNsPtr, &dummyPtr, &dummyPtr, &simplePattern);

    if ((exportNsPtr != nsPtr) || (strcmp(pattern, simplePattern) != 0)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("invalid export pattern"
                " \"%s\": pattern can't specify a namespace", pattern));
	Tcl_SetErrorCode(interp, "TCL", "EXPORT", "INVALID", NULL);
		" \"%s\": pattern can't specify a namespace", pattern));
	Tcl_SetErrorCode(interp, "TCL", "EXPORT", "INVALID", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Make sure that we don't already have the pattern in the array
     */

1434
1435
1436
1437
1438
1439
1440
1441

1442
1443
1444
1445
1446
1447
1448
1449
1450

1451
1452
1453
1454
1455
1456
1457
1535
1536
1537
1538
1539
1540
1541

1542
1543
1544
1545
1546
1547
1548
1549
1550

1551
1552
1553
1554
1555
1556
1557
1558







-
+








-
+







     * pattern.
     */

    neededElems = nsPtr->numExportPatterns + 1;
    if (neededElems > nsPtr->maxExportPatterns) {
	nsPtr->maxExportPatterns = nsPtr->maxExportPatterns ?
		2 * nsPtr->maxExportPatterns : INIT_EXPORT_PATTERNS;
	nsPtr->exportArrayPtr = (char **)Tcl_Realloc(nsPtr->exportArrayPtr,
	nsPtr->exportArrayPtr = (char **) Tcl_Realloc(nsPtr->exportArrayPtr,
		sizeof(char *) * nsPtr->maxExportPatterns);
    }

    /*
     * Add the pattern to the namespace's array of export patterns.
     */

    len = strlen(pattern);
    patternCpy = (char *)Tcl_Alloc(len + 1);
    patternCpy = (char *) Tcl_Alloc(len + 1);
    memcpy(patternCpy, pattern, len + 1);

    nsPtr->exportArrayPtr[nsPtr->numExportPatterns] = patternCpy;
    nsPtr->numExportPatterns++;

    /*
     * The list of commands actually exported from the namespace might have
1484
1485
1486
1487
1488
1489
1490
1491


1492
1493
1494
1495
1496
1497
1498
1499

1500
1501
1502
1503
1504
1505
1506
1585
1586
1587
1588
1589
1590
1591

1592
1593
1594
1595
1596
1597
1598
1599
1600

1601
1602
1603
1604
1605
1606
1607
1608







-
+
+







-
+







 *	object.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_AppendExportList(
    Tcl_Interp *interp,		/* Interpreter used for error reporting. */
    Tcl_Interp *interp,		/* Interpreter used for global NS and error
				 * reporting. */
    Tcl_Namespace *namespacePtr,/* Points to the namespace whose export
				 * pattern list is appended onto objPtr. NULL
				 * for the current namespace. */
    Tcl_Obj *objPtr)		/* Points to the Tcl object onto which the
				 * export pattern list is appended. */
{
    Namespace *nsPtr;
    size_t i;
    Tcl_Size i;
    int result;

    /*
     * If the specified namespace is NULL, use the current namespace.
     */

    if (namespacePtr == NULL) {
1585
1586
1587
1588
1589
1590
1591
1592

1593
1594
1595
1596
1597
1598
1599
1687
1688
1689
1690
1691
1692
1693

1694
1695
1696
1697
1698
1699
1700
1701







-
+







     * imported commands in autoloaded libraries and loads them in. That way,
     * they will be found when we try to create links below.
     *
     * Note that we don't just call Tcl_EvalObjv() directly because we do not
     * want absence of the command to be a failure case.
     */

    if (Tcl_FindCommand(interp,"auto_import",NULL,TCL_GLOBAL_ONLY) != NULL) {
    if (Tcl_FindCommand(interp, "auto_import", NULL, TCL_GLOBAL_ONLY) != NULL) {
	Tcl_Obj *objv[2];
	int result;

	TclNewLiteralStringObj(objv[0], "auto_import");
	objv[1] = Tcl_NewStringObj(pattern, -1);

	Tcl_IncrRefCount(objv[0]);
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
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
1749







-
+







-
-
+
+






-
-
+
+


-
-
-
+
+
+







    /*
     * From the pattern, find the namespace from which we are importing and
     * get the simple pattern (no namespace qualifiers or ::'s) at the end.
     */

    if (strlen(pattern) == 0) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("empty import pattern",-1));
	Tcl_SetErrorCode(interp, "TCL", "IMPORT", "EMPTY", NULL);
	Tcl_SetErrorCode(interp, "TCL", "IMPORT", "EMPTY", (char *)NULL);
	return TCL_ERROR;
    }
    TclGetNamespaceForQualName(interp, pattern, nsPtr, TCL_NAMESPACE_ONLY,
	    &importNsPtr, &dummyPtr, &dummyPtr, &simplePattern);

    if (importNsPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "unknown namespace in import pattern \"%s\"", pattern));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", pattern, NULL);
		"unknown namespace in import pattern \"%s\"", pattern));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", pattern, (char *)NULL);
	return TCL_ERROR;
    }
    if (importNsPtr == nsPtr) {
	if (pattern == simplePattern) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "no namespace specified in import pattern \"%s\"",
                    pattern));
	    Tcl_SetErrorCode(interp, "TCL", "IMPORT", "ORIGIN", NULL);
		    pattern));
	    Tcl_SetErrorCode(interp, "TCL", "IMPORT", "ORIGIN", (char *)NULL);
	} else {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "import pattern \"%s\" tries to import from namespace"
                    " \"%s\" into itself", pattern, importNsPtr->name));
	    Tcl_SetErrorCode(interp, "TCL", "IMPORT", "SELF", NULL);
		    "import pattern \"%s\" tries to import from namespace"
		    " \"%s\" into itself", pattern, importNsPtr->name));
	    Tcl_SetErrorCode(interp, "TCL", "IMPORT", "SELF", (char *)NULL);
	}
	return TCL_ERROR;
    }

    /*
     * Scan through the command table in the source namespace and look for
     * exported commands that match the string pattern. Create an "imported
1655
1656
1657
1658
1659
1660
1661
1662

1663
1664
1665
1666
1667
1668
1669
1757
1758
1759
1760
1761
1762
1763

1764
1765
1766
1767
1768
1769
1770
1771







-
+







	    return TCL_OK;
	}
	return DoImport(interp, nsPtr, hPtr, simplePattern, pattern,
		importNsPtr, allowOverwrite);
    }
    for (hPtr = Tcl_FirstHashEntry(&importNsPtr->cmdTable, &search);
	    (hPtr != NULL); hPtr = Tcl_NextHashEntry(&search)) {
	char *cmdName = (char *)Tcl_GetHashKey(&importNsPtr->cmdTable, hPtr);
	char *cmdName = (char *) Tcl_GetHashKey(&importNsPtr->cmdTable, hPtr);

	if (Tcl_StringMatch(cmdName, simplePattern) &&
		DoImport(interp, nsPtr, hPtr, cmdName, pattern, importNsPtr,
		allowOverwrite) == TCL_ERROR) {
	    return TCL_ERROR;
	}
    }
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
1797
1798
1799
1800
1801
1802
1803

1804
1805
1806
1807
1808
1809
1810
1811
1812

1813

1814
1815
1816
1817
1818
1819
1820







-
+








-
+
-







    Namespace *nsPtr,
    Tcl_HashEntry *hPtr,
    const char *cmdName,
    const char *pattern,
    Namespace *importNsPtr,
    int allowOverwrite)
{
    size_t i = 0, exported = 0;
    Tcl_Size i = 0, exported = 0;
    Tcl_HashEntry *found;

    /*
     * The command cmdName in the source namespace matches the pattern. Check
     * whether it was exported. If it wasn't, we ignore it.
     */

    while (!exported && (i < importNsPtr->numExportPatterns)) {
	exported |= Tcl_StringMatch(cmdName,
	exported |= Tcl_StringMatch(cmdName, importNsPtr->exportArrayPtr[i++]);
		importNsPtr->exportArrayPtr[i++]);
    }
    if (!exported) {
	return TCL_OK;
    }

    /*
     * Unless there is a name clash, create an imported command in the current
1742
1743
1744
1745
1746
1747
1748
1749

1750
1751

1752
1753
1754
1755

1756
1757
1758
1759
1760
1761



1762
1763

1764
1765
1766
1767
1768
1769

1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785

1786
1787
1788
1789
1790

1791
1792
1793


1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805


1806
1807
1808
1809
1810
1811
1812
1843
1844
1845
1846
1847
1848
1849

1850
1851

1852
1853
1854
1855

1856
1857
1858
1859



1860
1861
1862
1863

1864
1865
1866
1867
1868
1869

1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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







-
+

-
+



-
+



-
-
-
+
+
+

-
+





-
+















-
+




-
+


-
+
+










-
-
+
+







	Tcl_DStringAppend(&ds, cmdName, -1);

	/*
	 * Check whether creating the new imported command in the current
	 * namespace would create a cycle of imported command references.
	 */

	cmdPtr = (Command *)Tcl_GetHashValue(hPtr);
	cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
	if (found != NULL && cmdPtr->deleteProc == DeleteImportedCmd) {
	    Command *overwrite = (Command *)Tcl_GetHashValue(found);
	    Command *overwrite = (Command *) Tcl_GetHashValue(found);
	    Command *linkCmd = cmdPtr;

	    while (linkCmd->deleteProc == DeleteImportedCmd) {
		dataPtr = (ImportedCmdData *)linkCmd->objClientData;
		dataPtr = (ImportedCmdData *) linkCmd->objClientData;
		linkCmd = dataPtr->realCmdPtr;
		if (overwrite == linkCmd) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                            "import pattern \"%s\" would create a loop"
                            " containing command \"%s\"",
                            pattern, Tcl_DStringValue(&ds)));
			    "import pattern \"%s\" would create a loop"
			    " containing command \"%s\"",
			    pattern, Tcl_DStringValue(&ds)));
		    Tcl_DStringFree(&ds);
		    Tcl_SetErrorCode(interp, "TCL", "IMPORT", "LOOP", NULL);
		    Tcl_SetErrorCode(interp, "TCL", "IMPORT", "LOOP", (char *)NULL);
		    return TCL_ERROR;
		}
	    }
	}

	dataPtr = (ImportedCmdData *)Tcl_Alloc(sizeof(ImportedCmdData));
	dataPtr = (ImportedCmdData *) Tcl_Alloc(sizeof(ImportedCmdData));
	importedCmd = Tcl_NRCreateCommand(interp, Tcl_DStringValue(&ds),
		TclInvokeImportedCmd, InvokeImportedNRCmd, dataPtr,
		DeleteImportedCmd);
	dataPtr->realCmdPtr = cmdPtr;
	/* corresponding decrement is in DeleteImportedCmd */
	cmdPtr->refCount++;
	dataPtr->selfPtr = (Command *) importedCmd;
	dataPtr->selfPtr->compileProc = cmdPtr->compileProc;
	Tcl_DStringFree(&ds);

	/*
	 * Create an ImportRef structure describing this new import command
	 * and add it to the import ref list in the "real" command.
	 */

	refPtr = (ImportRef *)Tcl_Alloc(sizeof(ImportRef));
	refPtr = (ImportRef *) Tcl_Alloc(sizeof(ImportRef));
	refPtr->importedCmdPtr = (Command *) importedCmd;
	refPtr->nextPtr = cmdPtr->importRefPtr;
	cmdPtr->importRefPtr = refPtr;
    } else {
	Command *overwrite = (Command *)Tcl_GetHashValue(found);
	Command *overwrite = (Command *) Tcl_GetHashValue(found);

	if (overwrite->deleteProc == DeleteImportedCmd) {
	    ImportedCmdData *dataPtr = (ImportedCmdData *)overwrite->objClientData;
	    ImportedCmdData *dataPtr = (ImportedCmdData *)
		    overwrite->objClientData;

	    if (dataPtr->realCmdPtr == Tcl_GetHashValue(hPtr)) {
		/*
		 * Repeated import of same command is acceptable.
		 */

		return TCL_OK;
	    }
	}
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "can't import command \"%s\": already exists", cmdName));
	Tcl_SetErrorCode(interp, "TCL", "IMPORT", "OVERWRITE", NULL);
		"can't import command \"%s\": already exists", cmdName));
	Tcl_SetErrorCode(interp, "TCL", "IMPORT", "OVERWRITE", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
1868
1869
1870
1871
1872
1873
1874
1875

1876
1877
1878
1879
1880
1881
1882
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
1970
1971
1972
1973
1974
1975
1976

1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988

1989
1990
1991
1992
1993
1994
1995
1996
1997
1998

1999
2000
2001
2002
2003

2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018

2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031

2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044

2045
2046
2047
2048
2049
2050
2051
2052







-
+











-
+









-
+




-
+














-
+












-
+
+











-
+







    TclGetNamespaceForQualName(interp, pattern, nsPtr, TCL_NAMESPACE_ONLY,
	    &sourceNsPtr, &dummyPtr, &dummyPtr, &simplePattern);

    if (sourceNsPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"unknown namespace in namespace forget pattern \"%s\"",
		pattern));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", pattern, NULL);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", pattern, (char *)NULL);
	return TCL_ERROR;
    }

    if (strcmp(pattern, simplePattern) == 0) {
	/*
	 * The pattern is simple. Delete any imported commands that match it.
	 */

	if (TclMatchIsTrivial(simplePattern)) {
	    hPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, simplePattern);
	    if (hPtr != NULL) {
		Command *cmdPtr = (Command *)Tcl_GetHashValue(hPtr);
		Command *cmdPtr = (Command *) Tcl_GetHashValue(hPtr);

		if (cmdPtr && (cmdPtr->deleteProc == DeleteImportedCmd)) {
		    Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
		}
	    }
	    return TCL_OK;
	}
	for (hPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
		(hPtr != NULL); hPtr = Tcl_NextHashEntry(&search)) {
	    Command *cmdPtr = (Command *)Tcl_GetHashValue(hPtr);
	    Command *cmdPtr = (Command *) Tcl_GetHashValue(hPtr);

	    if (cmdPtr->deleteProc != DeleteImportedCmd) {
		continue;
	    }
	    cmdName = (char *)Tcl_GetHashKey(&nsPtr->cmdTable, hPtr);
	    cmdName = (char *) Tcl_GetHashKey(&nsPtr->cmdTable, hPtr);
	    if (Tcl_StringMatch(cmdName, simplePattern)) {
		Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
	    }
	}
	return TCL_OK;
    }

    /*
     * The pattern was namespace-qualified.
     */

    for (hPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search); (hPtr != NULL);
	    hPtr = Tcl_NextHashEntry(&search)) {
	Tcl_CmdInfo info;
	Tcl_Command token = (Tcl_Command)Tcl_GetHashValue(hPtr);
	Tcl_Command token = (Tcl_Command) Tcl_GetHashValue(hPtr);
	Tcl_Command origin = TclGetOriginalCommand(token);

	if (Tcl_GetCommandInfoFromToken(origin, &info) == 0) {
	    continue;			/* Not an imported command. */
	}
	if (info.namespacePtr != (Tcl_Namespace *) sourceNsPtr) {
	    /*
	     * Original not in namespace we're matching. Check the first link
	     * in the import chain.
	     */

	    Command *cmdPtr = (Command *) token;
	    ImportedCmdData *dataPtr = (ImportedCmdData *)cmdPtr->objClientData;
	    ImportedCmdData *dataPtr = (ImportedCmdData *)
		    cmdPtr->objClientData;
	    Tcl_Command firstToken = (Tcl_Command) dataPtr->realCmdPtr;

	    if (firstToken == origin) {
		continue;
	    }
	    Tcl_GetCommandInfoFromToken(firstToken, &info);
	    if (info.namespacePtr != (Tcl_Namespace *) sourceNsPtr) {
		continue;
	    }
	    origin = firstToken;
	}
	if (Tcl_StringMatch(Tcl_GetCommandName(NULL, origin), simplePattern)){
	if (Tcl_StringMatch(Tcl_GetCommandName(NULL, origin), simplePattern)) {
	    Tcl_DeleteCommandFromToken(interp, token);
	}
    }
    return TCL_OK;
}

/*
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985

1986
1987
1988
1989
1990
1991
1992
2074
2075
2076
2077
2078
2079
2080

2081
2082
2083
2084
2085
2086

2087
2088
2089
2090
2091
2092
2093
2094







-






-
+








Tcl_Command
TclGetOriginalCommand(
    Tcl_Command command)	/* The imported command for which the original
				 * command should be returned. */
{
    Command *cmdPtr = (Command *) command;
    ImportedCmdData *dataPtr;

    if (cmdPtr->deleteProc != DeleteImportedCmd) {
	return NULL;
    }

    while (cmdPtr->deleteProc == DeleteImportedCmd) {
	dataPtr = (ImportedCmdData *)cmdPtr->objClientData;
	ImportedCmdData *dataPtr = (ImportedCmdData *) cmdPtr->objClientData;
	cmdPtr = dataPtr->realCmdPtr;
    }
    return (Tcl_Command) cmdPtr;
}

/*
 *----------------------------------------------------------------------
2005
2006
2007
2008
2009
2010
2011
2012

2013
2014
2015
2016
2017
2018

2019
2020
2021
2022
2023
2024
2025
2026
2027

2028
2029
2030
2031
2032
2033
2034
2107
2108
2109
2110
2111
2112
2113

2114
2115
2116
2117
2118
2119

2120
2121
2122
2123
2124
2125
2126
2127
2128

2129
2130
2131
2132
2133
2134
2135
2136







-
+





-
+








-
+







 *	wrong, the result object is set to an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InvokeImportedNRCmd(
    ClientData clientData,	/* Points to the imported command's
    void *clientData,		/* Points to the imported command's
				 * ImportedCmdData structure. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    ImportedCmdData *dataPtr = (ImportedCmdData *)clientData;
    ImportedCmdData *dataPtr = (ImportedCmdData *) clientData;
    Command *realCmdPtr = dataPtr->realCmdPtr;

    TclSkipTailcall(interp);
    return TclNREvalObjv(interp, objc, objv, TCL_EVAL_NOERR, realCmdPtr);
}

int
TclInvokeImportedCmd(
    ClientData clientData,	/* Points to the imported command's
    void *clientData,		/* Points to the imported command's
				 * ImportedCmdData structure. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    return Tcl_NRCallObjProc(interp, InvokeImportedNRCmd, clientData,
	    objc, objv);
2053
2054
2055
2056
2057
2058
2059
2060

2061
2062
2063

2064
2065
2066
2067
2068
2069
2070
2155
2156
2157
2158
2159
2160
2161

2162
2163
2164

2165
2166
2167
2168
2169
2170
2171
2172







-
+


-
+







 *	Removes the imported command from the real command's import list.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteImportedCmd(
    ClientData clientData)	/* Points to the imported command's
    void *clientData)		/* Points to the imported command's
				 * ImportedCmdData structure. */
{
    ImportedCmdData *dataPtr = (ImportedCmdData *)clientData;
    ImportedCmdData *dataPtr = (ImportedCmdData *) clientData;
    Command *realCmdPtr = dataPtr->realCmdPtr;
    Command *selfPtr = dataPtr->selfPtr;
    ImportRef *refPtr, *prevPtr;

    prevPtr = NULL;
    for (refPtr = realCmdPtr->importRefPtr; refPtr != NULL;
	    refPtr = refPtr->nextPtr) {
2122
2123
2124
2125
2126
2127
2128
2129

2130
2131
2132
2133
2134
2135
2136
2224
2225
2226
2227
2228
2229
2230

2231
2232
2233
2234
2235
2236
2237
2238







-
+







 *	is set NULL. If both TCL_GLOBAL_ONLY and TCL_NAMESPACE_ONLY are
 *	specified, TCL_GLOBAL_ONLY is ignored and the search starts from the
 *	namespace specified by cxtNsPtr.
 *
 *	If "flags" contains TCL_CREATE_NS_IF_UNKNOWN, all namespace components
 *	of the qualified name that cannot be found are automatically created
 *	within their specified parent. This makes sure that functions like
 *	Tcl_CreateCommand always succeed. There is no alternate search path,
 *	Tcl_CreateObjCommand always succeed. There is no alternate search path,
 *	so *altNsPtrPtr is set NULL.
 *
 *	If "flags" contains TCL_FIND_ONLY_NS, the qualified name is treated as
 *	a reference to a namespace, and the entire qualified name is followed.
 *	If the name is relative, the namespace is looked up only in the
 *	current namespace. A pointer to the namespace is stored in *nsPtrPtr
 *	and NULL is stored in *simpleNamePtr. Otherwise, if TCL_FIND_ONLY_NS
2203
2204
2205
2206
2207
2208
2209
2210

2211
2212
2213
2214
2215
2216
2217
2305
2306
2307
2308
2309
2310
2311

2312
2313
2314
2315
2316
2317
2318
2319







-
+







				 * NULL. */
    const char **simpleNamePtr) /* Address where function stores the simple
				 * name at end of the qualName, or NULL if
				 * qualName is "::" or the flag
				 * TCL_FIND_ONLY_NS was specified. */
{
    Interp *iPtr = (Interp *) interp;
    Namespace *nsPtr = cxtNsPtr;
    Namespace *nsPtr = cxtNsPtr, *lastNsPtr = NULL, *lastAltNsPtr = NULL;
    Namespace *altNsPtr;
    Namespace *globalNsPtr = iPtr->globalNsPtr;
    const char *start, *end;
    const char *nsName;
    Tcl_HashEntry *entryPtr;
    Tcl_DString buffer;
    int len;
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238



2239
2240
2241
2242

2243
2244
2245
2246
2247
2248
2249
2331
2332
2333
2334
2335
2336
2337



2338
2339
2340
2341
2342
2343

2344
2345
2346
2347
2348
2349
2350
2351







-
-
-
+
+
+



-
+







	nsPtr = globalNsPtr;
    } else if (nsPtr == NULL) {
	nsPtr = iPtr->varFramePtr->nsPtr;
    }

    start = qualName;			/* Points to start of qualifying
					 * namespace. */
    if ((*qualName == ':') && (*(qualName+1) == ':')) {
	start = qualName+2;		/* Skip over the initial :: */
	while (*start == ':') {
    if ((qualName[0] == ':') && (qualName[1] == ':')) {
	start = qualName + 2;		/* Skip over the initial :: */
	while (start[0] == ':') {
	    start++;			/* Skip over a subsequent : */
	}
	nsPtr = globalNsPtr;
	if (*start == '\0') {		/* qualName is just two or more
	if (start[0] == '\0') {		/* qualName is just two or more
					 * ":"s. */
	    *nsPtrPtr = globalNsPtr;
	    *altNsPtrPtr = NULL;
	    *actualCxtPtrPtr = globalNsPtr;
	    *simpleNamePtr = start;	/* Points to empty string. */
	    return TCL_OK;
	}
2275
2276
2277
2278
2279
2280
2281
2282

2283
2284
2285
2286
2287
2288
2289
2290
2291
2292

2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306

2307
2308
2309
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
2390

2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401

2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419

2420
2421
2422
2423
2424
2425
2426
2377
2378
2379
2380
2381
2382
2383

2384
2385
2386
2387
2388
2389
2390
2391
2392
2393

2394
2395
2396
2397
2398
2399
2400
2401
2402
2403


2404


2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424

2425
2426
2427
2428





2429




2430

2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446


2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497

2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524







-
+









-
+









-
-

-
-
+



















-
+



-
-
-
-
-
+
-
-
-
-

-
+













+
+
-
-
+
+
+
+









-
-
-
-
-
-
-
+
-
-

-
+

+
+









+
+
+
+
+
+
-
-
+
+
+
+
+

-
-
+










-
+


















+







	 * the end of the qualified name (i.e., a name ending in "\0"). Set
	 * len to the number of characters, starting from start, in the name;
	 * set end to point after the "::"s or at the "\0".
	 */

	len = 0;
	for (end = start;  *end != '\0';  end++) {
	    if ((*end == ':') && (*(end+1) == ':')) {
	    if ((end[0] == ':') && (end[1] == ':')) {
		end += 2;		/* Skip over the initial :: */
		while (*end == ':') {
		    end++;		/* Skip over the subsequent : */
		}
		break;			/* Exit for loop; end is after ::'s */
	    }
	    len++;
	}

	if (*end=='\0' && !(end-start>=2 && *(end-1)==':' && *(end-2)==':')) {
	if (end[0]=='\0' && !(end-start>=2 && end[-1]==':' && end[-2]==':')) {
	    /*
	     * qualName ended with a simple name at start. If TCL_FIND_ONLY_NS
	     * was specified, look this up as a namespace. Otherwise, start is
	     * the name of a cmd or var and we are done.
	     */

	    if (flags & TCL_FIND_ONLY_NS) {
		nsName = start;
	    } else {
		*nsPtrPtr = nsPtr;
		*altNsPtrPtr = altNsPtr;
		*simpleNamePtr = start;
		Tcl_DStringFree(&buffer);
		return TCL_OK;
		goto done;
	    }
	} else {
	    /*
	     * start points to the beginning of a namespace qualifier ending
	     * in "::". end points to the start of a name in that namespace
	     * that might be empty. Copy the namespace qualifier to a buffer
	     * so it can be null terminated. We can't modify the incoming
	     * qualName since it may be a string constant.
	     */

	    TclDStringClear(&buffer);
	    Tcl_DStringAppend(&buffer, start, len);
	    nsName = Tcl_DStringValue(&buffer);
	}

	/*
	 * Look up the namespace qualifier nsName in the current namespace
	 * context. If it isn't found but TCL_CREATE_NS_IF_UNKNOWN is set,
	 * create that qualifying namespace. This is needed for functions like
	 * Tcl_CreateCommand that cannot fail.
	 * Tcl_CreateObjCommand that cannot fail.
	 */

	if (nsPtr != NULL) {
#ifndef BREAK_NAMESPACE_COMPAT
	    entryPtr = Tcl_FindHashEntry(&nsPtr->childTable, nsName);
#else
	    if (nsPtr->childTablePtr == NULL) {
		entryPtr = NULL;
	    entryPtr = FindChildEntry(nsPtr, nsName);
	    } else {
		entryPtr = Tcl_FindHashEntry(nsPtr->childTablePtr, nsName);
	    }
#endif
	    if (entryPtr != NULL) {
		nsPtr = (Namespace *)Tcl_GetHashValue(entryPtr);
		nsPtr = (Namespace *) Tcl_GetHashValue(entryPtr);
	    } else if (flags & TCL_CREATE_NS_IF_UNKNOWN) {
		Tcl_CallFrame *framePtr;

		(void) TclPushStackFrame(interp, &framePtr,
			(Tcl_Namespace *) nsPtr, /*isProcCallFrame*/ 0);

		nsPtr = (Namespace *)
			Tcl_CreateNamespace(interp, nsName, NULL, NULL);
		TclPopStackFrame(interp);

		if (nsPtr == NULL) {
		    Tcl_Panic("Could not create namespace '%s'", nsName);
		}
	    } else {
		/*
	    } else {			/* Namespace not found and was not
					 * created. */
		 * Namespace not found and was not created.
		 * Remember last found namespace for TCL_FIND_IF_NOT_SIMPLE.
		 */
		lastNsPtr = nsPtr;
		nsPtr = NULL;
	    }
	}

	/*
	 * Look up the namespace qualifier in the alternate search path too.
	 */

	if (altNsPtr != NULL) {
#ifndef BREAK_NAMESPACE_COMPAT
	    entryPtr = Tcl_FindHashEntry(&altNsPtr->childTable, nsName);
#else
	    if (altNsPtr->childTablePtr != NULL) {
		entryPtr = Tcl_FindHashEntry(altNsPtr->childTablePtr, nsName);
	    } else {
		entryPtr = NULL;
	    entryPtr = FindChildEntry(altNsPtr, nsName);
	    }
#endif
	    if (entryPtr != NULL) {
		altNsPtr = (Namespace *)Tcl_GetHashValue(entryPtr);
		altNsPtr = (Namespace *) Tcl_GetHashValue(entryPtr);
	    } else {
		/* Remember last found in alternate path */
		lastAltNsPtr = altNsPtr;
		altNsPtr = NULL;
	    }
	}

	/*
	 * If both search paths have failed, return NULL results.
	 */

	if ((nsPtr == NULL) && (altNsPtr == NULL)) {
	    if (flags & TCL_FIND_IF_NOT_SIMPLE) {
		/*
		 * return last found NS, regardless simple name or not,
		 * e. g. ::A::B::C::D -> ::A::B and C::D, if namespace C
		 * cannot be found in ::A::B
		 */
	    *nsPtrPtr = NULL;
	    *altNsPtrPtr = NULL;
		nsPtr = lastNsPtr;
		altNsPtr = lastAltNsPtr;
		*simpleNamePtr = start;
		goto done;
	    }
	    *simpleNamePtr = NULL;
	    Tcl_DStringFree(&buffer);
	    return TCL_OK;
	    goto done;
	}

	start = end;
    }

    /*
     * We ignore trailing "::"s in a namespace name, but in a command or
     * variable name, trailing "::"s refer to the cmd or var named {}.
     */

    if ((flags & TCL_FIND_ONLY_NS) || (end>start && *(end-1)!=':')) {
    if ((flags & TCL_FIND_ONLY_NS) || (end>start && end[-1]!=':')) {
	*simpleNamePtr = NULL;		/* Found namespace name. */
    } else {
	*simpleNamePtr = end;		/* Found cmd/var: points to empty
					 * string. */
    }

    /*
     * As a special case, if we are looking for a namespace and qualName is ""
     * and the current active namespace (nsPtr) is not the global namespace,
     * return NULL (no namespace was found). This is because namespaces can
     * not have empty names except for the global namespace.
     */

    if ((flags & TCL_FIND_ONLY_NS) && (*qualName == '\0')
	    && (nsPtr != globalNsPtr)) {
	nsPtr = NULL;
    }

done:
    *nsPtrPtr = nsPtr;
    *altNsPtrPtr = altNsPtr;
    Tcl_DStringFree(&buffer);
    return TCL_OK;
}

/*
2480
2481
2482
2483
2484
2485
2486
2487

2488
2489
2490
2491
2492
2493
2494
2578
2579
2580
2581
2582
2583
2584

2585
2586
2587
2588
2589
2590
2591
2592







-
+







				 * (current namespace if contextNsPtr is
				 * NULL), then in global namespace. */
    Tcl_Namespace *contextNsPtr,/* Ignored if TCL_GLOBAL_ONLY flag is set or
				 * if the name starts with "::". Otherwise,
				 * points to namespace in which to resolve
				 * name; if NULL, look up name in the current
				 * namespace. */
    int flags)		/* Flags controlling namespace lookup: an OR'd
    int flags)			/* Flags controlling namespace lookup: an OR'd
				 * combination of TCL_GLOBAL_ONLY and
				 * TCL_LEAVE_ERR_MSG flags. */
{
    Namespace *nsPtr, *dummy1Ptr, *dummy2Ptr;
    const char *dummy;

    /*
2502
2503
2504
2505
2506
2507
2508
2509
2510


2511
2512
2513
2514
2515
2516
2517
2600
2601
2602
2603
2604
2605
2606


2607
2608
2609
2610
2611
2612
2613
2614
2615







-
-
+
+








    if (nsPtr != NULL) {
	return (Tcl_Namespace *) nsPtr;
    }

    if (flags & TCL_LEAVE_ERR_MSG) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "unknown namespace \"%s\"", name));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", name, NULL);
		"unknown namespace \"%s\"", name));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", name, (char *)NULL);
    }
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
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
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







-
+














-
+







-
+


-
+








-
+








-
+


-
+














-
+


-
+







		result = resPtr->cmdResProc(interp, name,
			(Tcl_Namespace *) cxtNsPtr, flags, &cmd);
	    }
	    resPtr = resPtr->nextPtr;
	}

	if (result == TCL_OK) {
	    ((Command *)cmd)->flags |= CMD_VIA_RESOLVER;
	    ((Command *) cmd)->flags |= CMD_VIA_RESOLVER;
	    return cmd;

	} else if (result != TCL_CONTINUE) {
	    return NULL;
	}
    }

    /*
     * Find the namespace(s) that contain the command.
     */

    cmdPtr = NULL;
    if (cxtNsPtr->commandPathLength!=0 && strncmp(name, "::", 2)
	    && !(flags & TCL_NAMESPACE_ONLY)) {
	size_t i;
	Tcl_Size i;
	Namespace *pathNsPtr, *realNsPtr, *dummyNsPtr;

	(void) TclGetNamespaceForQualName(interp, name, cxtNsPtr,
		TCL_NAMESPACE_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr,
		&simpleName);
	if ((realNsPtr != NULL) && (simpleName != NULL)) {
	    if ((cxtNsPtr == realNsPtr)
		    || !(realNsPtr->flags & NS_DYING)) {
		    || !(realNsPtr->flags & NS_DEAD)) {
		entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
		if (entryPtr != NULL) {
		    cmdPtr = (Command *)Tcl_GetHashValue(entryPtr);
		    cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
		}
	    }
	}

	/*
	 * Next, check along the path.
	 */

	for (i=0 ; i<cxtNsPtr->commandPathLength && cmdPtr==NULL ; i++) {
	for (i=0 ; (cmdPtr == NULL) && i<cxtNsPtr->commandPathLength ; i++) {
	    pathNsPtr = cxtNsPtr->commandPathArray[i].nsPtr;
	    if (pathNsPtr == NULL) {
		continue;
	    }
	    (void) TclGetNamespaceForQualName(interp, name, pathNsPtr,
		    TCL_NAMESPACE_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr,
		    &simpleName);
	    if ((realNsPtr != NULL) && (simpleName != NULL)
		    && !(realNsPtr->flags & NS_DYING)) {
		    && !(realNsPtr->flags & NS_DEAD)) {
		entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
		if (entryPtr != NULL) {
		    cmdPtr = (Command *)Tcl_GetHashValue(entryPtr);
		    cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
		}
	    }
	}

	/*
	 * If we've still not found the command, look in the global namespace
	 * as a last resort.
	 */

	if (cmdPtr == NULL) {
	    (void) TclGetNamespaceForQualName(interp, name, NULL,
		    TCL_GLOBAL_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr,
		    &simpleName);
	    if ((realNsPtr != NULL) && (simpleName != NULL)
		    && !(realNsPtr->flags & NS_DYING)) {
		    && !(realNsPtr->flags & NS_DEAD)) {
		entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
		if (entryPtr != NULL) {
		    cmdPtr = (Command *)Tcl_GetHashValue(entryPtr);
		    cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
		}
	    }
	}
    } else {
	Namespace *nsPtr[2];
	int search;

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
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







-
+






-
+





-
-
+
+







	 */

	for (search = 0;  (search < 2) && (cmdPtr == NULL);  search++) {
	    if ((nsPtr[search] != NULL) && (simpleName != NULL)) {
		entryPtr = Tcl_FindHashEntry(&nsPtr[search]->cmdTable,
			simpleName);
		if (entryPtr != NULL) {
		    cmdPtr = (Command *)Tcl_GetHashValue(entryPtr);
		    cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
		}
	    }
	}
    }

    if (cmdPtr != NULL) {
	cmdPtr->flags  &= ~CMD_VIA_RESOLVER;
	cmdPtr->flags &= ~CMD_VIA_RESOLVER;
	return (Tcl_Command) cmdPtr;
    }

    if (flags & TCL_LEAVE_ERR_MSG) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "unknown command \"%s\"", name));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", name, NULL);
		"unknown command \"%s\"", name));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", name, (char *)NULL);
    }
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
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
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







-
+



















+
-
+
















-
-
-
+
-
-
-
-
-
-
-
-

-
+







    Tcl_HashEntry *hPtr;
    Namespace *nsPtr;
    Namespace *trailNsPtr, *shadowNsPtr;
    Namespace *globalNsPtr = (Namespace *) TclGetGlobalNamespace(interp);
    int found, i;
    int trailFront = -1;
    int trailSize = 5;		/* Formerly NUM_TRAIL_ELEMS. */
    Namespace **trailPtr = (Namespace **)TclStackAlloc(interp,
    Namespace **trailPtr = (Namespace **) TclStackAlloc(interp,
	    trailSize * sizeof(Namespace *));

    /*
     * Start at the namespace containing the new command, and work up through
     * the list of parents. Stop just before the global namespace, since the
     * global namespace can't "shadow" its own entries.
     *
     * The namespace "trail" list we build consists of the names of each
     * namespace that encloses the new command, in order from outermost to
     * innermost: for example, "a" then "b". Each iteration of this loop
     * eventually extends the trail upwards by one namespace, nsPtr. We use
     * this trail list to see if nsPtr (e.g. "a" in 2. above) could have
     * now-invalid cached command references. This will happen if nsPtr
     * (e.g. "a") contains a sequence of child namespaces (e.g. "b") such that
     * there is a identically-named sequence of child namespaces starting from
     * :: (e.g. "::b") whose tail namespace contains a command also named
     * cmdName.
     */

    cmdName = (char *)
    cmdName = (char *)Tcl_GetHashKey(newCmdPtr->hPtr->tablePtr, newCmdPtr->hPtr);
	    Tcl_GetHashKey(newCmdPtr->hPtr->tablePtr, newCmdPtr->hPtr);
    for (nsPtr=newCmdPtr->nsPtr ; (nsPtr!=NULL) && (nsPtr!=globalNsPtr) ;
	    nsPtr=nsPtr->parentPtr) {
	/*
	 * Find the maximal sequence of child namespaces contained in nsPtr
	 * such that there is a identically-named sequence of child namespaces
	 * starting from ::. shadowNsPtr will be the tail of this sequence, or
	 * the deepest namespace under :: that might contain a command now
	 * shadowed by cmdName. We check below if shadowNsPtr actually
	 * contains a command cmdName.
	 */

	found = 1;
	shadowNsPtr = globalNsPtr;

	for (i = trailFront;  i >= 0;  i--) {
	    trailNsPtr = trailPtr[i];
#ifndef BREAK_NAMESPACE_COMPAT
	    hPtr = Tcl_FindHashEntry(&shadowNsPtr->childTable,
		    trailNsPtr->name);
	    hPtr = FindChildEntry(shadowNsPtr, trailNsPtr->name);
#else
	    if (shadowNsPtr->childTablePtr != NULL) {
		hPtr = Tcl_FindHashEntry(shadowNsPtr->childTablePtr,
			trailNsPtr->name);
	    } else {
		hPtr = NULL;
	    }
#endif
	    if (hPtr != NULL) {
		shadowNsPtr = (Namespace *)Tcl_GetHashValue(hPtr);
		shadowNsPtr = (Namespace *) Tcl_GetHashValue(hPtr);
	    } else {
		found = 0;
		break;
	    }
	}

	/*
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
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







-
+














-
-
+
+
+







		/*
		 * If the shadowed command was compiled to bytecodes, we
		 * invalidate all the bytecodes in nsPtr, to force a new
		 * compilation. We use the resolverEpoch to signal the need
		 * for a fresh compilation of every bytecode.
		 */

		if (((Command *)Tcl_GetHashValue(hPtr))->compileProc != NULL){
		if (((Command *) Tcl_GetHashValue(hPtr))->compileProc != NULL) {
		    nsPtr->resolverEpoch++;
		}
	    }
	}

	/*
	 * Insert nsPtr at the front of the trail list: i.e., at the end of
	 * the trailPtr array.
	 */

	trailFront++;
	if (trailFront == trailSize) {
	    int newSize = 2 * trailSize;

	    trailPtr = (Namespace **)TclStackRealloc(interp, trailPtr,
		    newSize * sizeof(Namespace *));
	    trailPtr = (Namespace **)
		    TclStackRealloc(interp, trailPtr,
			    newSize * sizeof(Namespace *));
	    trailSize = newSize;
	}
	trailPtr[trailFront] = nsPtr;
    }
    TclStackFree(interp, trailPtr);
}

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
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







-
+














-
+
















-
+


-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	     */

	    NamespaceCurrentCmd(NULL, interp, 1, NULL);
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "namespace \"%s\" not found in \"%s\"", name,
		    Tcl_GetStringResult(interp)));
	}
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", name, NULL);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", name, (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

static int
GetNamespaceFromObj(
    Tcl_Interp *interp,		/* The current interpreter. */
    Tcl_Obj *objPtr,		/* The object to be resolved as the name of a
				 * namespace. */
    Tcl_Namespace **nsPtrPtr)	/* Result namespace pointer goes here. */
{
    ResolvedNsName *resNamePtr;

    NsNameGetIntRep(objPtr, resNamePtr);
    NsNameGetInternalRep(objPtr, resNamePtr);
    if (resNamePtr) {
	Namespace *nsPtr, *refNsPtr;

	/*
	 * Check that the ResolvedNsName is still valid; avoid letting the ref
	 * cross interps.
	 */

	nsPtr = resNamePtr->nsPtr;
	refNsPtr = resNamePtr->refNsPtr;
	if (!(nsPtr->flags & NS_DYING) && (interp == nsPtr->interp)
		&& (!refNsPtr || (refNsPtr ==
		(Namespace *) TclGetCurrentNamespace(interp)))) {
	    *nsPtrPtr = (Tcl_Namespace *) nsPtr;
	    return TCL_OK;
	}
	Tcl_StoreIntRep(objPtr, &nsNameType, NULL);
	Tcl_StoreInternalRep(objPtr, &nsNameType, NULL);
    }
    if (SetNsNameFromAny(interp, objPtr) == TCL_OK) {
	NsNameGetIntRep(objPtr, resNamePtr);
	NsNameGetInternalRep(objPtr, resNamePtr);
	assert(resNamePtr != NULL);
	*nsPtrPtr = (Tcl_Namespace *) resNamePtr->nsPtr;
	return TCL_OK;
    }
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TclNewNamespaceObj --
 *
 *	Gets an object that contains a reference to a given namespace.
 *
 *	Note that this gets the name of the namespace immediately; this means
 *	that the name is guaranteed to persist even if the namespace is
 *	deleted. (This is checked by test namespace-7.1.)
 *
 * Results:
 *	Returns a newly-allocated Tcl_Obj.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
Tcl_Obj *
TclNewNamespaceObj(
    Tcl_Namespace *namespacePtr)
{
    Namespace *nsPtr = (Namespace *) namespacePtr;
    Tcl_Size len;
    Tcl_Obj *objPtr;

    /*
     * If NS_DEAD set, we have no name any more; the fullName field may have
     * been deallocated.
     */
    assert(!(nsPtr->flags & NS_DEAD));

    /*
     * Need to get the name pro-actively; the name must persist after the
     * namespace is deleted. This is the easiest way.
     */

    len = strlen(nsPtr->fullName);
    TclNewStringObj(objPtr, nsPtr->fullName, len);

    /*
     * But we know exactly which namespace this resolves to. Remember that
     * unless things are already being taken apart.
     */

    if (!(nsPtr->flags & (NS_DYING | NS_TEARDOWN))) {
	ResolvedNsName *resNamePtr = (ResolvedNsName *)
		Tcl_Alloc(sizeof(ResolvedNsName));

	resNamePtr->nsPtr = nsPtr;
	resNamePtr->refNsPtr = NULL;
	resNamePtr->refCount = 0;
	nsPtr->refCount++;
	NsNameSetInternalRep(objPtr, resNamePtr);
    }
    return objPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TclInitNamespaceCmd --
 *
 *	This function is called to create the "namespace" Tcl command. See the
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
3126
3127
3128
3129
3130
3131
3132

3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144

3145
3146
3147
3148
3149
3150
3151
3152
3153

3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170

3171
3172
3173
3174
3175
3176
3177
3178







-
+











-
+








-
+
















-
+







 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceChildrenCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Namespace *namespacePtr;
    Namespace *nsPtr, *childNsPtr;
    Namespace *globalNsPtr = (Namespace *) TclGetGlobalNamespace(interp);
    const char *pattern = NULL;
    Tcl_DString buffer;
    Tcl_HashEntry *entryPtr;
    Tcl_HashSearch search;
    Tcl_Obj *listPtr, *elemPtr;
    Tcl_Obj *listPtr;

    /*
     * Get a pointer to the specified namespace, or the current namespace.
     */

    if (objc == 1) {
	nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
    } else if ((objc == 2) || (objc == 3)) {
	if (TclGetNamespaceFromObj(interp, objv[1], &namespacePtr) != TCL_OK){
	if (TclGetNamespaceFromObj(interp, objv[1], &namespacePtr) != TCL_OK) {
	    return TCL_ERROR;
	}
	nsPtr = (Namespace *) namespacePtr;
    } else {
	Tcl_WrongNumArgs(interp, 1, objv, "?name? ?pattern?");
	return TCL_ERROR;
    }

    /*
     * Get the glob-style pattern, if any, used to narrow the search.
     */

    Tcl_DStringInit(&buffer);
    if (objc == 3) {
	const char *name = TclGetString(objv[2]);

	if ((*name == ':') && (*(name+1) == ':')) {
	if ((name[0] == ':') && (name[1] == ':')) {
	    pattern = name;
	} else {
	    Tcl_DStringAppend(&buffer, nsPtr->fullName, -1);
	    if (nsPtr != globalNsPtr) {
		TclDStringAppendLiteral(&buffer, "::");
	    }
	    Tcl_DStringAppend(&buffer, name, -1);
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
3188
3189
3190
3191
3192
3193
3194






3195



3196
3197
3198
3199
3200


3201






3202

3203
3204
3205


3206
3207
3208
3209
3210
3211
3212
3213
3214







-
-
-
-
-
-
+
-
-
-
+




-
-
+
-
-
-
-
-
-

-
+


-
-
+
+







    listPtr = Tcl_NewListObj(0, NULL);
    if ((pattern != NULL) && TclMatchIsTrivial(pattern)) {
	size_t length = strlen(nsPtr->fullName);

	if (strncmp(pattern, nsPtr->fullName, length) != 0) {
	    goto searchDone;
	}
	if (
#ifndef BREAK_NAMESPACE_COMPAT
	    Tcl_FindHashEntry(&nsPtr->childTable, pattern+length) != NULL
#else
	    nsPtr->childTablePtr != NULL &&
	    Tcl_FindHashEntry(nsPtr->childTablePtr, pattern+length) != NULL
	if (FindChildEntry(nsPtr, pattern+length) != NULL) {
#endif
	) {
	    Tcl_ListObjAppendElement(interp, listPtr,
	    Tcl_ListObjAppendElement(NULL, listPtr,
		    Tcl_NewStringObj(pattern, -1));
	}
	goto searchDone;
    }
#ifndef BREAK_NAMESPACE_COMPAT
    entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
    entryPtr = FirstChildEntry(nsPtr, &search);
#else
    if (nsPtr->childTablePtr == NULL) {
	goto searchDone;
    }
    entryPtr = Tcl_FirstHashEntry(nsPtr->childTablePtr, &search);
#endif
    while (entryPtr != NULL) {
	childNsPtr = (Namespace *)Tcl_GetHashValue(entryPtr);
	childNsPtr = (Namespace *) Tcl_GetHashValue(entryPtr);
	if ((pattern == NULL)
		|| Tcl_StringMatch(childNsPtr->fullName, pattern)) {
	    elemPtr = Tcl_NewStringObj(childNsPtr->fullName, -1);
	    Tcl_ListObjAppendElement(interp, listPtr, elemPtr);
	    Tcl_ListObjAppendElement(NULL, listPtr,
		    TclNewNamespaceObj((Tcl_Namespace *) childNsPtr));
	}
	entryPtr = Tcl_NextHashEntry(&search);
    }

  searchDone:
    Tcl_SetObjResult(interp, listPtr);
    Tcl_DStringFree(&buffer);
3106
3107
3108
3109
3110
3111
3112
3113

3114
3115
3116
3117
3118
3119
3120
3121

3122
3123
3124
3125
3126
3127
3128
3241
3242
3243
3244
3245
3246
3247

3248
3249
3250
3251
3252

3253
3254

3255
3256
3257
3258
3259
3260
3261
3262







-
+




-


-
+







 *	result in the interpreter's result object.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceCodeCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Namespace *currNsPtr;
    Tcl_Obj *listPtr, *objPtr;
    const char *arg;
    size_t length;
    Tcl_Size length;

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

    /*
3146
3147
3148
3149
3150
3151
3152
3153

3154
3155
3156
3157
3158
3159

3160
3161
3162
3163
3164
3165





3166
3167
3168
3169
3170
3171
3172
3280
3281
3282
3283
3284
3285
3286

3287


3288



3289






3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301







-
+
-
-

-
-
-
+
-
-
-
-
-
-
+
+
+
+
+







     * argument "arg". By constructing a list, we ensure that scoped commands
     * are interpreted properly when they are executed later, by the
     * "namespace inscope" command.
     */

    TclNewObj(listPtr);
    TclNewLiteralStringObj(objPtr, "::namespace");
    Tcl_ListObjAppendElement(interp, listPtr, objPtr);
    Tcl_ListObjAppendElement(NULL, listPtr, objPtr);
    TclNewLiteralStringObj(objPtr, "inscope");
    Tcl_ListObjAppendElement(interp, listPtr, objPtr);

    currNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
    if (currNsPtr == (Namespace *) TclGetGlobalNamespace(interp)) {
	TclNewLiteralStringObj(objPtr, "::");
    TclNewLiteralStringObj(objPtr, "inscope");
    } else {
	objPtr = Tcl_NewStringObj(currNsPtr->fullName, -1);
    }
    Tcl_ListObjAppendElement(interp, listPtr, objPtr);

    Tcl_ListObjAppendElement(interp, listPtr, objv[1]);
    Tcl_ListObjAppendElement(NULL, listPtr, objPtr);

    Tcl_ListObjAppendElement(NULL, listPtr,
	    TclNewNamespaceObj(TclGetCurrentNamespace(interp)));
    Tcl_ListObjAppendElement(NULL, listPtr, objv[1]);

    Tcl_SetObjResult(interp, listPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
3187
3188
3189
3190
3191
3192
3193
3194

3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212


3213
3214
3215
3216
3217

3218
3219

3220
3221
3222
3223
3224
3225
3226
3227
3316
3317
3318
3319
3320
3321
3322

3323
3324
3325
3326
3327


3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343



3344


3345

3346
3347
3348
3349
3350
3351
3352







-
+




-
-












+
+


-
-
-
+
-
-
+
-







 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceCurrentCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Namespace *currNsPtr;

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

    /*
     * The "real" name of the global namespace ("::") is the null string, but
     * we return "::" for it as a convenience to programmers. Note that "" and
     * "::" are treated as synonyms by the namespace code so that it is still
     * easy to do things like:
     *
     *    namespace [namespace current]::bar { ... }
     *
     * This behavior is encoded into TclNewNamespaceObj().
     */

    currNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
    if (currNsPtr == (Namespace *) TclGetGlobalNamespace(interp)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("::", 2));
    Tcl_SetObjResult(interp,
    } else {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(currNsPtr->fullName, -1));
	    TclNewNamespaceObj(TclGetCurrentNamespace(interp)));
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * NamespaceDeleteCmd --
3250
3251
3252
3253
3254
3255
3256
3257

3258
3259
3260
3261
3262
3263
3264
3375
3376
3377
3378
3379
3380
3381

3382
3383
3384
3385
3386
3387
3388
3389







-
+







 *	function returns an error message in the interpreter's result object.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceDeleteCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Namespace *namespacePtr;
    const char *name;
    int i;
3274
3275
3276
3277
3278
3279
3280
3281

3282
3283

3284
3285
3286

3287
3288
3289
3290
3291
3292
3293
3399
3400
3401
3402
3403
3404
3405

3406
3407

3408
3409
3410

3411
3412
3413
3414
3415
3416
3417
3418







-
+

-
+


-
+







     * command line are valid, and report any errors.
     */

    for (i = 1;  i < objc;  i++) {
	name = TclGetString(objv[i]);
	namespacePtr = Tcl_FindNamespace(interp, name, NULL, /*flags*/ 0);
	if ((namespacePtr == NULL)
		|| (((Namespace *) namespacePtr)->flags & NS_KILLED)) {
		|| (((Namespace *) namespacePtr)->flags & NS_TEARDOWN)) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "unknown namespace \"%s\" in namespace delete command",
		    "unknown namespace \"%s\" in namespace delete command",
		    TclGetString(objv[i])));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE",
		    TclGetString(objv[i]), NULL);
		    TclGetString(objv[i]), (char *)NULL);
	    return TCL_ERROR;
	}
    }

    /*
     * Okay, now delete each namespace.
     */
3327
3328
3329
3330
3331
3332
3333
3334

3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345

3346
3347
3348
3349
3350
3351
3352
3452
3453
3454
3455
3456
3457
3458

3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469

3470
3471
3472
3473
3474
3475
3476
3477







-
+










-
+







 *	result.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceEvalCmd(
    ClientData clientData,	/* Arbitrary value passed to cmd. */
    void *clientData,		/* Arbitrary value passed to cmd. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, NRNamespaceEvalCmd, clientData, objc,
	    objv);
}

static int
NRNamespaceEvalCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    CmdFrame *invoker;
    int word;
3420
3421
3422
3423
3424
3425
3426
3427

3428
3429
3430
3431

3432
3433
3434
3435
3436
3437

3438
3439
3440
3441
3442
3443
3444
3545
3546
3547
3548
3549
3550
3551

3552
3553
3554
3555

3556
3557
3558
3559
3560
3561

3562
3563
3564
3565
3566
3567
3568
3569







-
+



-
+





-
+







    TclNRAddCallback(interp, NsEval_Callback, namespacePtr, "eval",
	    NULL, NULL);
    return TclNREvalObjEx(interp, objPtr, 0, invoker, word);
}

static int
NsEval_Callback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Namespace *namespacePtr = (Tcl_Namespace *)data[0];
    Tcl_Namespace *namespacePtr = (Tcl_Namespace *) data[0];

    if (result == TCL_ERROR) {
	size_t length = strlen(namespacePtr->fullName);
	unsigned limit = 200;
	int overflow = (length > limit);
	char *cmd = (char *)data[1];
	char *cmd = (char *) data[1];

	Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
		"\n    (in namespace %s \"%.*s%s\" script line %d)",
		cmd,
		(overflow ? limit : (unsigned)length), namespacePtr->fullName,
		(overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
    }
3470
3471
3472
3473
3474
3475
3476
3477

3478
3479
3480
3481
3482
3483
3484
3595
3596
3597
3598
3599
3600
3601

3602
3603
3604
3605
3606
3607
3608
3609







-
+







 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceExistsCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Namespace *namespacePtr;

    if (objc != 2) {
3525
3526
3527
3528
3529
3530
3531
3532

3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553

3554
3555
3556
3557
3558
3559
3560
3650
3651
3652
3653
3654
3655
3656

3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677

3678
3679
3680
3681
3682
3683
3684
3685







-
+




















-
+







 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceExportCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int firstArg, i;

    if (objc < 1) {
	Tcl_WrongNumArgs(interp, 1, objv, "?-clear? ?pattern pattern...?");
	return TCL_ERROR;
    }

    /*
     * If no pattern arguments are given, and "-clear" isn't specified, return
     * the namespace's current export pattern list.
     */

    if (objc == 1) {
	Tcl_Obj *listPtr;

	TclNewObj(listPtr);
	(void)Tcl_AppendExportList(interp, NULL, listPtr);
	(void) Tcl_AppendExportList(interp, NULL, listPtr);
	Tcl_SetObjResult(interp, listPtr);
	return TCL_OK;
    }

    /*
     * Process the optional "-clear" argument.
     */
3607
3608
3609
3610
3611
3612
3613
3614

3615
3616
3617
3618
3619
3620
3621
3732
3733
3734
3735
3736
3737
3738

3739
3740
3741
3742
3743
3744
3745
3746







-
+







 *	interpreter's result object.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceForgetCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *pattern;
    int i, result;

3672
3673
3674
3675
3676
3677
3678
3679

3680
3681
3682
3683
3684
3685
3686
3797
3798
3799
3800
3801
3802
3803

3804
3805
3806
3807
3808
3809
3810
3811







-
+







 *	result object.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceImportCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int allowOverwrite = 0;
    const char *string, *pattern;
    int i, result;
3712
3713
3714
3715
3716
3717
3718
3719

3720
3721
3722
3723

3724
3725
3726
3727
3728
3729
3730
3837
3838
3839
3840
3841
3842
3843

3844
3845
3846
3847

3848
3849
3850
3851
3852
3853
3854
3855







-
+



-
+







	Tcl_HashSearch search;
	Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
	Tcl_Obj *listPtr;

	TclNewObj(listPtr);
	for (hPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
		hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
	    Command *cmdPtr = (Command *)Tcl_GetHashValue(hPtr);
	    Command *cmdPtr = (Command *) Tcl_GetHashValue(hPtr);

	    if (cmdPtr->deleteProc == DeleteImportedCmd) {
		Tcl_ListObjAppendElement(NULL, listPtr, Tcl_NewStringObj(
			(char *)Tcl_GetHashKey(&nsPtr->cmdTable, hPtr) ,-1));
			(char *) Tcl_GetHashKey(&nsPtr->cmdTable, hPtr), -1));
	    }
	}
	Tcl_SetObjResult(interp, listPtr);
	return TCL_OK;
    }

    /*
3776
3777
3778
3779
3780
3781
3782
3783

3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794

3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3901
3902
3903
3904
3905
3906
3907

3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918

3919
3920
3921
3922
3923
3924
3925

3926
3927
3928
3929
3930
3931
3932







-
+










-
+






-







 *	Returns a result in the Tcl interpreter's result object.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceInscopeCmd(
    ClientData clientData,	/* Arbitrary value passed to cmd. */
    void *clientData,		/* Arbitrary value passed to cmd. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, NRNamespaceInscopeCmd, clientData, objc,
	    objv);
}

static int
NRNamespaceInscopeCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Namespace *namespacePtr;
    CallFrame *framePtr, **framePtrPtr;
    int i;
    Tcl_Obj *cmdObjPtr;

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

3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850

3851
3852

3853
3854
3855
3856
3857
3858
3859
3956
3957
3958
3959
3960
3961
3962

3963








3964

3965
3966

3967
3968
3969
3970
3971
3972
3973
3974







-

-
-
-
-
-
-
-
-

-
+

-
+







     * of extra arguments to form the command to evaluate.
     */

    if (objc == 3) {
	cmdObjPtr = objv[2];
    } else {
	Tcl_Obj *concatObjv[2];
	Tcl_Obj *listPtr;

	listPtr = Tcl_NewListObj(0, NULL);
	for (i = 3;  i < objc;  i++) {
	    if (Tcl_ListObjAppendElement(interp, listPtr, objv[i]) != TCL_OK){
		Tcl_DecrRefCount(listPtr);	/* Free unneeded obj. */
		return TCL_ERROR;
	    }
	}

	concatObjv[0] = objv[2];
	concatObjv[1] = listPtr;
	concatObjv[1] = Tcl_NewListObj(objc - 3, objv + 3);
	cmdObjPtr = Tcl_ConcatObj(2, concatObjv);
	Tcl_DecrRefCount(listPtr);    /* We're done with the list object. */
	Tcl_DecrRefCount(concatObjv[1]); /* We're done with the list object. */
    }

    TclNRAddCallback(interp, NsEval_Callback, namespacePtr, "inscope",
	    NULL, NULL);
    return TclNREvalObjEx(interp, cmdObjPtr, 0, NULL, 0);
}

3884
3885
3886
3887
3888
3889
3890
3891

3892
3893
3894
3895
3896
3897
3898
3999
4000
4001
4002
4003
4004
4005

4006
4007
4008
4009
4010
4011
4012
4013







-
+







 *	interpreter's result object.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceOriginCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Command cmd, origCmd;
    Tcl_Obj *resultPtr;

3907
3908
3909
3910
3911
3912
3913
3914

3915
3916

3917
3918
3919
3920
3921
3922
3923
3924
3925
3926








3927
3928
3929
3930
3931
3932
3933
4022
4023
4024
4025
4026
4027
4028

4029
4030

4031





4032
4033
4034


4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049







-
+

-
+
-
-
-
-
-



-
-
+
+
+
+
+
+
+
+







    }
    origCmd = TclGetOriginalCommand(cmd);
    if (origCmd == NULL) {
	origCmd = cmd;
    }
    TclNewObj(resultPtr);
    Tcl_GetCommandFullName(interp, origCmd, resultPtr);
    if (TclCheckEmptyString(resultPtr) == TCL_EMPTYSTRING_YES ) {
    if (TclCheckEmptyString(resultPtr) == TCL_EMPTYSTRING_YES) {
	Tcl_DecrRefCount(resultPtr);
	namespaceOriginError:
	goto namespaceOriginError;
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "invalid command name \"%s\"", TclGetString(objv[1])));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND",
		TclGetString(objv[1]), NULL);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, resultPtr);
    return TCL_OK;
}


  namespaceOriginError:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "invalid command name \"%s\"", TclGetString(objv[1])));
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND",
	    TclGetString(objv[1]), (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * NamespaceParentCmd --
 *
 *	Invoked to implement the "namespace parent" command that returns the
3944
3945
3946
3947
3948
3949
3950
3951

3952
3953
3954
3955
3956
3957
3958
4060
4061
4062
4063
4064
4065
4066

4067
4068
4069
4070
4071
4072
4073
4074







-
+







 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceParentCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Namespace *nsPtr;

    if (objc == 1) {
3967
3968
3969
3970
3971
3972
3973
3974

3975
3976
3977
3978
3979
3980
3981
3982
4083
4084
4085
4086
4087
4088
4089

4090

4091
4092
4093
4094
4095
4096
4097







-
+
-







    }

    /*
     * Report the parent of the specified namespace.
     */

    if (nsPtr->parentPtr != NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
	Tcl_SetObjResult(interp, TclNewNamespaceObj(nsPtr->parentPtr));
		nsPtr->parentPtr->fullName, -1));
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
4002
4003
4004
4005
4006
4007
4008
4009

4010
4011
4012
4013
4014
4015
4016


4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036


4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052


4053
4054

4055
4056
4057
4058
4059
4060
4061
4117
4118
4119
4120
4121
4122
4123

4124
4125
4126
4127
4128
4129


4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149


4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165


4166
4167
4168

4169
4170
4171
4172
4173
4174
4175
4176







-
+





-
-
+
+


















-
-
+
+














-
-
+
+

-
+







 *	names that depend on the namespace for resolution).
 *
 *----------------------------------------------------------------------
 */

static int
NamespacePathCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
    size_t i;
    int nsObjc, result = TCL_ERROR;
    Tcl_Size nsObjc, i;
    int result = TCL_ERROR;
    Tcl_Obj **nsObjv;
    Tcl_Namespace **namespaceList = NULL;

    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?pathList?");
	return TCL_ERROR;
    }

    /*
     * If no path is given, return the current path.
     */

    if (objc == 1) {
	Tcl_Obj *resultObj;

	TclNewObj(resultObj);
	for (i=0 ; i<nsPtr->commandPathLength ; i++) {
	    if (nsPtr->commandPathArray[i].nsPtr != NULL) {
		Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(
			nsPtr->commandPathArray[i].nsPtr->fullName, -1));
		Tcl_ListObjAppendElement(NULL, resultObj, TclNewNamespaceObj(
			(Tcl_Namespace *) nsPtr->commandPathArray[i].nsPtr));
	    }
	}
	Tcl_SetObjResult(interp, resultObj);
	return TCL_OK;
    }

    /*
     * There is a path given, so parse it into an array of namespace pointers.
     */

    if (TclListObjGetElements(interp, objv[1], &nsObjc, &nsObjv) != TCL_OK) {
	goto badNamespace;
    }
    if (nsObjc != 0) {
	namespaceList = (Tcl_Namespace **)TclStackAlloc(interp,
		sizeof(Tcl_Namespace *) * nsObjc);
	namespaceList = (Tcl_Namespace **)
		TclStackAlloc(interp, sizeof(Tcl_Namespace *) * nsObjc);

	for (i=0 ; i<(size_t)nsObjc ; i++) {
	for (i = 0; i < nsObjc; i++) {
	    if (TclGetNamespaceFromObj(interp, nsObjv[i],
		    &namespaceList[i]) != TCL_OK) {
		goto badNamespace;
	    }
	}
    }

4092
4093
4094
4095
4096
4097
4098
4099

4100
4101
4102
4103
4104
4105



4106
4107
4108
4109
4110
4111
4112
4207
4208
4209
4210
4211
4212
4213

4214
4215
4216
4217



4218
4219
4220
4221
4222
4223
4224
4225
4226
4227







-
+



-
-
-
+
+
+







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

void
TclSetNsPath(
    Namespace *nsPtr,		/* Namespace whose path is to be set. */
    size_t pathLength,		/* Length of pathAry. */
    Tcl_Size pathLength,	/* Length of pathAry. */
    Tcl_Namespace *pathAry[])	/* Array of namespaces that are the path. */
{
    if (pathLength != 0) {
	NamespacePathEntry *tmpPathArray =
		(NamespacePathEntry *)Tcl_Alloc(sizeof(NamespacePathEntry) * pathLength);
	size_t i;
	NamespacePathEntry *tmpPathArray = (NamespacePathEntry *)
		Tcl_Alloc(sizeof(NamespacePathEntry) * pathLength);
	Tcl_Size i;

	for (i=0 ; i<pathLength ; i++) {
	    tmpPathArray[i].nsPtr = (Namespace *) pathAry[i];
	    tmpPathArray[i].creatorNsPtr = nsPtr;
	    tmpPathArray[i].prevPtr = NULL;
	    tmpPathArray[i].nextPtr =
		    tmpPathArray[i].nsPtr->commandPathSourceList;
4149
4150
4151
4152
4153
4154
4155
4156

4157
4158
4159
4160
4161
4162
4163
4264
4265
4266
4267
4268
4269
4270

4271
4272
4273
4274
4275
4276
4277
4278







-
+







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

static void
UnlinkNsPath(
    Namespace *nsPtr)
{
    size_t i;
    Tcl_Size i;
    for (i=0 ; i<nsPtr->commandPathLength ; i++) {
	NamespacePathEntry *nsPathPtr = &nsPtr->commandPathArray[i];

	if (nsPathPtr->prevPtr != NULL) {
	    nsPathPtr->prevPtr->nextPtr = nsPathPtr->nextPtr;
	}
	if (nsPathPtr->nextPtr != NULL) {
4182
4183
4184
4185
4186
4187
4188
4189

4190
4191
4192
4193
4194
4195
4196
4297
4298
4299
4300
4301
4302
4303

4304
4305
4306
4307
4308
4309
4310
4311







-
+







 *
 * Results:
 *	nothing
 *
 * Side effects:
 *	Increments the command reference epoch in each namespace whose path
 *	includes the given namespace. This causes any cached resolved names
 *	whose root cacheing context starts at that namespace to be recomputed
 *	whose root caching context starts at that namespace to be recomputed
 *	the next time they are used.
 *
 *----------------------------------------------------------------------
 */

void
TclInvalidateNsPath(
4229
4230
4231
4232
4233
4234
4235
4236

4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255

4256
4257
4258
4259

4260
4261
4262


4263
4264
4265
4266
4267
4268
4269
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







-
+


















-
+



-
+

-
-
+
+







 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceQualifiersCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *name, *p;
    size_t length;

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

    /*
     * Find the end of the string, then work backward and find the start of
     * the last "::" qualifier.
     */

    name = TclGetString(objv[1]);
    for (p = name;  *p != '\0';  p++) {
    for (p = name;  p[0] != '\0';  p++) {
	/* empty body */
    }
    while (--p >= name) {
	if ((*p == ':') && (p > name) && (*(p-1) == ':')) {
	if ((p[0] == ':') && (p > name) && (p[-1] == ':')) {
	    p -= 2;			/* Back up over the :: */
	    while ((p >= name) && (*p == ':')) {
		p--;			/* Back up over the preceeding : */
	    while ((p >= name) && (p[0] == ':')) {
		p--;			/* Back up over the preceding : */
	    }
	    break;
	}
    }

    if (p >= name) {
	length = p-name+1;
4297
4298
4299
4300
4301
4302
4303
4304

4305
4306
4307
4308
4309
4310
4311
4412
4413
4414
4415
4416
4417
4418

4419
4420
4421
4422
4423
4424
4425
4426







-
+







 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceUnknownCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Namespace *currNsPtr;
    Tcl_Obj *resultPtr;
    int rc;
4400
4401
4402
4403
4404
4405
4406
4407

4408
4409
4410
4411
4412
4413
4414
4515
4516
4517
4518
4519
4520
4521

4522
4523
4524
4525
4526
4527
4528
4529







-
+







int
Tcl_SetNamespaceUnknownHandler(
    Tcl_Interp *interp,		/* Interpreter in which the namespace
				 * exists. */
    Tcl_Namespace *nsPtr,	/* Namespace which is being updated. */
    Tcl_Obj *handlerPtr)	/* The new handler, or NULL to reset. */
{
    int lstlen = 0;
    Tcl_Size lstlen = 0;
    Namespace *currNsPtr = (Namespace *) nsPtr;

    /*
     * Ensure that we check for errors *first* before we change anything.
     */

    if (handlerPtr != NULL) {
4484
4485
4486
4487
4488
4489
4490
4491

4492
4493
4494
4495
4496
4497
4498
4599
4600
4601
4602
4603
4604
4605

4606
4607
4608
4609
4610
4611
4612
4613







-
+







 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceTailCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *name, *p;

    if (objc != 2) {
4506
4507
4508
4509
4510
4511
4512
4513

4514
4515
4516
4517
4518
4519
4520
4621
4622
4623
4624
4625
4626
4627

4628
4629
4630
4631
4632
4633
4634
4635







-
+







     */

    name = TclGetString(objv[1]);
    for (p = name;  *p != '\0';  p++) {
	/* empty body */
    }
    while (--p > name) {
	if ((*p == ':') && (*(p-1) == ':')) {
	if ((p[0] == ':') && (p[-1] == ':')) {
	    p++;			/* Just after the last "::" */
	    break;
	}
    }

    if (p >= name) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(p, -1));
4534
4535
4536
4537
4538
4539
4540
4541

4542
4543
4544
4545
4546
4547
4548
4549

4550
4551
4552
4553
4554
4555
4556
4649
4650
4651
4652
4653
4654
4655

4656
4657
4658
4659
4660
4661
4662
4663

4664
4665
4666
4667
4668
4669
4670
4671







-
+







-
+







 *	    namespace upvar ns otherVar myVar ?otherVar myVar ...?
 *
 * Results:
 *	Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
 *
 * Side effects:
 *	Creates new variables in the current scope, linked to the
 *	corresponding variables in the stipulated nmamespace. If anything goes
 *	corresponding variables in the stipulated namespace. If anything goes
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceUpvarCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Namespace *nsPtr, *savedNsPtr;
    Var *otherPtr, *arrayPtr;
4616
4617
4618
4619
4620
4621
4622
4623

4624
4625
4626
4627
4628
4629
4630
4731
4732
4733
4734
4735
4736
4737

4738
4739
4740
4741
4742
4743
4744
4745







-
+







 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceWhichCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static const char *const opts[] = {
	"-command", "-variable", NULL
    };
4692
4693
4694
4695
4696
4697
4698
4699

4700
4701
4702
4703
4704

4705
4706
4707
4708
4709
4710
4711
4807
4808
4809
4810
4811
4812
4813

4814
4815
4816
4817
4818

4819
4820
4821
4822
4823
4824
4825
4826







-
+




-
+







 *	the namespace, it's structure will be freed.
 *
 *----------------------------------------------------------------------
 */

static void
FreeNsNameInternalRep(
    Tcl_Obj *objPtr)	/* nsName object with internal representation
    Tcl_Obj *objPtr)		/* nsName object with internal representation
				 * to free. */
{
    ResolvedNsName *resNamePtr;

    NsNameGetIntRep(objPtr, resNamePtr);
    NsNameGetInternalRep(objPtr, resNamePtr);
    assert(resNamePtr != NULL);

    /*
     * Decrement the reference count of the namespace. If there are no more
     * references, free it up.
     */

4739
4740
4741
4742
4743
4744
4745
4746

4747
4748
4749
4750

4751
4752

4753
4754
4755
4756
4757
4758
4759
4854
4855
4856
4857
4858
4859
4860

4861
4862
4863
4864

4865
4866

4867
4868
4869
4870
4871
4872
4873
4874







-
+



-
+

-
+







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

static void
DupNsNameInternalRep(
    Tcl_Obj *srcPtr,		/* Object with internal rep to copy. */
    Tcl_Obj *copyPtr)	/* Object with internal rep to set. */
    Tcl_Obj *copyPtr)		/* Object with internal rep to set. */
{
    ResolvedNsName *resNamePtr;

    NsNameGetIntRep(srcPtr, resNamePtr);
    NsNameGetInternalRep(srcPtr, resNamePtr);
    assert(resNamePtr != NULL);
    NsNameSetIntRep(copyPtr, resNamePtr);
    NsNameSetInternalRep(copyPtr, resNamePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * SetNsNameFromAny --
 *
4775
4776
4777
4778
4779
4780
4781
4782

4783
4784
4785
4786
4787
4788
4789
4890
4891
4892
4893
4894
4895
4896

4897
4898
4899
4900
4901
4902
4903
4904







-
+







 */

static int
SetNsNameFromAny(
    Tcl_Interp *interp,		/* Points to the namespace in which to resolve
				 * name. Also used for error reporting if not
				 * NULL. */
    Tcl_Obj *objPtr)	/* The object to convert. */
    Tcl_Obj *objPtr)		/* The object to convert. */
{
    const char *dummy;
    Namespace *nsPtr, *dummy1Ptr, *dummy2Ptr;
    ResolvedNsName *resNamePtr;
    const char *name;

    if (interp == NULL) {
4800
4801
4802
4803
4804
4805
4806
4807

4808
4809
4810
4811
4812
4813
4814
4815

4816
4817
4818
4819
4820
4821
4822
4915
4916
4917
4918
4919
4920
4921

4922
4923
4924
4925
4926
4927
4928
4929

4930
4931
4932
4933
4934
4935
4936
4937







-
+







-
+








    /*
     * If we found a namespace, then create a new ResolvedNsName structure
     * that holds a reference to it.
     */

    nsPtr->refCount++;
    resNamePtr = (ResolvedNsName *)Tcl_Alloc(sizeof(ResolvedNsName));
    resNamePtr = (ResolvedNsName *) Tcl_Alloc(sizeof(ResolvedNsName));
    resNamePtr->nsPtr = nsPtr;
    if ((name[0] == ':') && (name[1] == ':')) {
	resNamePtr->refNsPtr = NULL;
    } else {
	resNamePtr->refNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
    }
    resNamePtr->refCount = 0;
    NsNameSetIntRep(objPtr, resNamePtr);
    NsNameSetInternalRep(objPtr, resNamePtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetNamespaceCommandTable --
4860
4861
4862
4863
4864
4865
4866
4867


4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880


4881
4882
4883

4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904


4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917


4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935

4936
4937
4938

4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954

4955
4956

4957
4958
4959
4960
4961
4962
4963
4975
4976
4977
4978
4979
4980
4981

4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994


4995
4996
4997
4998

4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018


5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031


5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050

5051
5052
5053

5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069

5070


5071
5072
5073
5074
5075
5076
5077
5078







-
+
+











-
-
+
+


-
+



















-
-
+
+











-
-
+
+

















-
+


-
+















-
+
-
-
+







    Tcl_Namespace *nsPtr)
{
    Namespace *nPtr = (Namespace *) nsPtr;
#ifndef BREAK_NAMESPACE_COMPAT
    return &nPtr->childTable;
#else
    if (nPtr->childTablePtr == NULL) {
	nPtr->childTablePtr = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));
	nPtr->childTablePtr = (Tcl_HashTable *)
		Tcl_Alloc(sizeof(Tcl_HashTable));
	Tcl_InitHashTable(nPtr->childTablePtr, TCL_STRING_KEYS);
    }
    return nPtr->childTablePtr;
#endif
}

/*
 *----------------------------------------------------------------------
 *
 * TclLogCommandInfo --
 *
 *	This function is invoked after an error occurs in an interpreter. It
 *	adds information to iPtr->errorInfo/errorStack fields to describe the
 *	Invoked after an error occurs in an interpreter.
 *	Adds information to iPtr->errorInfo/errorStack fields to describe the
 *	command that was being executed when the error occurred. When pc and
 *	tosPtr are non-NULL, conveying a bytecode execution "inner context",
 *	and the offending instruction is suitable, that inner context is
 *	and the offending instruction is suitable, and that inner context is
 *	recorded in errorStack.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Information about the command is added to errorInfo/errorStack and the
 *	line number stored internally in the interpreter is set.
 *
 *----------------------------------------------------------------------
 */

void
TclLogCommandInfo(
    Tcl_Interp *interp,		/* Interpreter in which to log information. */
    const char *script,		/* First character in script containing
				 * command (must be <= command). */
    const char *command,	/* First character in command that generated
				 * the error. */
    size_t length,			/* Number of bytes in command (-1 means
				 * use all bytes up to first null byte). */
    Tcl_Size length,		/* Number of bytes in command (< 0 means use
				 * all bytes up to first null byte). */
    const unsigned char *pc,    /* Current pc of bytecode execution context */
    Tcl_Obj **tosPtr)		/* Current stack of bytecode execution
				 * context */
{
    const char *p;
    Interp *iPtr = (Interp *) interp;
    int overflow, limit = 150;
    Var *varPtr, *arrayPtr;

    if (iPtr->flags & ERR_ALREADY_LOGGED) {
	/*
	 * Someone else has already logged error information for this command;
	 * we shouldn't add anything more.
	 * Someone else has already logged error information for this command.
	 * Don't add anything more.
	 */

	return;
    }

    if (command != NULL) {
	/*
	 * Compute the line number where the error occurred.
	 */

	iPtr->errorLine = 1;
	for (p = script; p != command; p++) {
	    if (*p == '\n') {
		iPtr->errorLine++;
	    }
	}

	if (length == TCL_INDEX_NONE) {
	if (length < 0) {
	    length = strlen(command);
	}
	overflow = (length > (size_t)limit);
	overflow = (length > limit);
	Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
		"\n    %s\n\"%.*s%s\"", ((iPtr->errorInfo == NULL)
		? "while executing" : "invoked from within"),
		(overflow ? limit : (int)length), command,
		(overflow ? "..." : "")));

	varPtr = TclObjLookupVarEx(interp, iPtr->eiVar, NULL, TCL_GLOBAL_ONLY,
		NULL, 0, 0, &arrayPtr);
	if ((varPtr == NULL) || !TclIsVarTraced(varPtr)) {
	    /*
	     * Should not happen.
	     */

	    return;
	} else {
	    Tcl_HashEntry *hPtr
	    Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&iPtr->varTraces, varPtr);
		    = Tcl_FindHashEntry(&iPtr->varTraces, (char *) varPtr);
	    VarTrace *tracePtr = (VarTrace *)Tcl_GetHashValue(hPtr);
	    VarTrace *tracePtr = (VarTrace *) Tcl_GetHashValue(hPtr);

	    if (tracePtr->traceProc != EstablishErrorInfoTraces) {
		/*
		 * The most recent trace set on ::errorInfo is not the one the
		 * core itself puts on last. This means some other code is
		 * tracing the variable, and the additional trace(s) might be
		 * write traces that expect the timing of writes to
4981
4982
4983
4984
4985
4986
4987
4988

4989
4990
4991

4992
4993
4994

4995
4996
4997
4998
4999
5000
5001
5096
5097
5098
5099
5100
5101
5102

5103
5104
5105

5106
5107
5108

5109
5110
5111
5112
5113
5114
5115
5116







-
+


-
+


-
+








	newObj = Tcl_DuplicateObj(iPtr->errorStack);
	Tcl_DecrRefCount(iPtr->errorStack);
	Tcl_IncrRefCount(newObj);
	iPtr->errorStack = newObj;
    }
    if (iPtr->resetErrorStack) {
	int len;
	Tcl_Size len;

	iPtr->resetErrorStack = 0;
	Tcl_ListObjLength(interp, iPtr->errorStack, &len);
	TclListObjLength(interp, iPtr->errorStack, &len);

	/*
	 * Reset while keeping the list intrep as much as possible.
	 * Reset while keeping the list internalrep as much as possible.
	 */

	Tcl_ListObjReplace(interp, iPtr->errorStack, 0, len, 0, NULL);
	if (pc != NULL) {
	    Tcl_Obj *innerContext;

	    innerContext = TclGetInnerContext(interp, pc, tosPtr);
5019
5020
5021
5022
5023
5024
5025
5026

5027
5028
5029
5030
5031
5032
5033
5134
5135
5136
5137
5138
5139
5140

5141
5142
5143
5144
5145
5146
5147
5148







-
+







    } else if (iPtr->varFramePtr != iPtr->framePtr) {
	/*
	 * uplevel case, [lappend errorstack UP $relativelevel]
	 */

	Tcl_ListObjAppendElement(NULL, iPtr->errorStack, iPtr->upLiteral);
	Tcl_ListObjAppendElement(NULL, iPtr->errorStack, Tcl_NewWideIntObj(
		iPtr->framePtr->level - iPtr->varFramePtr->level));
		(int)(iPtr->framePtr->level - iPtr->varFramePtr->level)));
    } else if (iPtr->framePtr != iPtr->rootFramePtr) {
	/*
	 * normal case, [lappend errorstack CALL [info level 0]]
	 */

	Tcl_ListObjAppendElement(NULL, iPtr->errorStack, iPtr->callLiteral);
	Tcl_ListObjAppendElement(NULL, iPtr->errorStack, Tcl_NewListObj(
5053
5054
5055
5056
5057
5058
5059
5060

5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073

5074
5075
5076

5077
5078
5079

5080
5081
5082
5083
5084
5085
5086
5168
5169
5170
5171
5172
5173
5174

5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187

5188
5189
5190

5191
5192
5193

5194
5195
5196
5197
5198
5199
5200
5201







-
+












-
+


-
+


-
+







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

void
TclErrorStackResetIf(
    Tcl_Interp *interp,
    const char *msg,
    size_t length)
    Tcl_Size length)
{
    Interp *iPtr = (Interp *) interp;

    if (Tcl_IsShared(iPtr->errorStack)) {
	Tcl_Obj *newObj;

	newObj = Tcl_DuplicateObj(iPtr->errorStack);
	Tcl_DecrRefCount(iPtr->errorStack);
	Tcl_IncrRefCount(newObj);
	iPtr->errorStack = newObj;
    }
    if (iPtr->resetErrorStack) {
	int len;
	Tcl_Size len;

	iPtr->resetErrorStack = 0;
	Tcl_ListObjLength(interp, iPtr->errorStack, &len);
	TclListObjLength(interp, iPtr->errorStack, &len);

	/*
	 * Reset while keeping the list intrep as much as possible.
	 * Reset while keeping the list internalrep as much as possible.
	 */

	Tcl_ListObjReplace(interp, iPtr->errorStack, 0, len, 0, NULL);
	Tcl_ListObjAppendElement(NULL, iPtr->errorStack, iPtr->innerLiteral);
	Tcl_ListObjAppendElement(NULL, iPtr->errorStack,
		Tcl_NewStringObj(msg, length));
    }
5108
5109
5110
5111
5112
5113
5114
5115

5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5223
5224
5225
5226
5227
5228
5229

5230
5231
5232
5233
5234

5235
5236
5237
5238
5239
5240
5241
5242
5243







-
+




-









void
Tcl_LogCommandInfo(
    Tcl_Interp *interp,		/* Interpreter in which to log information. */
    const char *script,		/* First character in script containing
				 * command (must be <= command). */
    const char *command,	/* First character in command that generated
				 * the error. */
    size_t length)		/* Number of bytes in command (-1 means use
    Tcl_Size length)		/* Number of bytes in command (-1 means use
				 * all bytes up to first null byte). */
{
    TclLogCommandInfo(interp, script, command, length, NULL, NULL);
}

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

Changes to generic/tclNotify.c.

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
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
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
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
45









-
-
-
+
+
+
+








-
+



-
+











-
+







/*
 * tclNotify.c --
 *
 *	This file implements the generic portion of the Tcl notifier. The
 *	notifier is lowest-level part of the event system. It manages an event
 *	queue that holds Tcl_Event structures. The platform specific portion
 *	of the notifier is defined in the tcl*Notify.c files in each platform
 *	directory.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998 by Scriptics Corporation.
 * Copyright (c) 2003 by Kevin B. Kenny.  All rights reserved.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1998 Scriptics Corporation.
 * Copyright © 2003 Kevin B. Kenny.  All rights reserved.
 * Copyright © 2021 Donal K. Fellows
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

/*
 * Module-scope struct of notifier hooks that are checked in the default
 * Notifier hooks that are checked in the public wrappers for the default
 * notifier functions (for overriding via Tcl_SetNotifier).
 */

Tcl_NotifierProcs tclNotifierHooks = {
static Tcl_NotifierProcs tclNotifierHooks = {
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};

/*
 * For each event source (created with Tcl_CreateEventSource) there is a
 * structure of the following type:
 */

typedef struct EventSource {
    Tcl_EventSetupProc *setupProc;
    Tcl_EventCheckProc *checkProc;
    ClientData clientData;
    void *clientData;
    struct EventSource *nextPtr;
} EventSource;

/*
 * The following structure keeps track of the state of the notifier on a
 * per-thread basis. The first three elements keep track of the event queue.
 * In addition to the first (next to be serviced) and last events in the
66
67
68
69
70
71
72
73

74
75
76
77
78
79
80
67
68
69
70
71
72
73

74
75
76
77
78
79
80
81







-
+







				 * elapsed time for the next block. */
    int inTraversal;		/* 1 if Tcl_SetMaxBlockTime is being called
				 * during an event source traversal. */
    EventSource *firstEventSourcePtr;
				/* Pointer to first event source in list of
				 * event sources for this thread. */
    Tcl_ThreadId threadId;	/* Thread that owns this notifier instance. */
    ClientData clientData;	/* Opaque handle for platform specific
    void *clientData;	/* Opaque handle for platform specific
				 * notifier. */
    int initialized;		/* 1 if notifier has been initialized. */
    struct ThreadSpecificData *nextPtr;
				/* Next notifier in global list of notifiers.
				 * Access is controlled by the listLock global
				 * mutex. */
} ThreadSpecificData;
90
91
92
93
94
95
96
97
98


99
100
101
102
103
104
105
91
92
93
94
95
96
97


98
99
100
101
102
103
104
105
106







-
-
+
+







static ThreadSpecificData *firstNotifierPtr = NULL;
TCL_DECLARE_MUTEX(listLock)

/*
 * Declarations for routines used only in this file.
 */

static void		QueueEvent(ThreadSpecificData *tsdPtr,
			    Tcl_Event *evPtr, Tcl_QueuePosition position);
static int		QueueEvent(ThreadSpecificData *tsdPtr,
			    Tcl_Event *evPtr, int position);

/*
 *----------------------------------------------------------------------
 *
 * TclInitNotifier --
 *
 *	Initialize the thread local data structures for the notifier
170
171
172
173
174
175
176
177

178
179
180
181
182
183
184
171
172
173
174
175
176
177

178
179
180
181
182
183
184
185







-
+







TclFinalizeNotifier(void)
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    ThreadSpecificData **prevPtrPtr;
    Tcl_Event *evPtr, *hold;

    if (!tsdPtr->initialized) {
	return;		/* Notifier not initialized for the current thread */
	return; /* Notifier not initialized for the current thread */
    }

    Tcl_MutexLock(&(tsdPtr->queueMutex));
    for (evPtr = tsdPtr->firstEventPtr; evPtr != NULL; ) {
	hold = evPtr;
	evPtr = evPtr->nextPtr;
	Tcl_Free(hold);
220
221
222
223
224
225
226
227

228
229
































230
231
232
233
234
235
236
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







-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *	notifier functions.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetNotifier(
    Tcl_NotifierProcs *notifierProcPtr)
    const Tcl_NotifierProcs *notifierProcPtr)
{
    tclNotifierHooks = *notifierProcPtr;

    /*
     * Don't allow hooks to refer to the hook point functions; avoids infinite
     * loop.
     */

    if (tclNotifierHooks.setTimerProc == Tcl_SetTimer) {
	tclNotifierHooks.setTimerProc = NULL;
    }
    if (tclNotifierHooks.waitForEventProc == Tcl_WaitForEvent) {
	tclNotifierHooks.waitForEventProc = NULL;
    }
    if (tclNotifierHooks.initNotifierProc == Tcl_InitNotifier) {
	tclNotifierHooks.initNotifierProc = NULL;
    }
    if (tclNotifierHooks.finalizeNotifierProc == Tcl_FinalizeNotifier) {
	tclNotifierHooks.finalizeNotifierProc = NULL;
    }
    if (tclNotifierHooks.alertNotifierProc == Tcl_AlertNotifier) {
	tclNotifierHooks.alertNotifierProc = NULL;
    }
    if (tclNotifierHooks.serviceModeHookProc == Tcl_ServiceModeHook) {
	tclNotifierHooks.serviceModeHookProc = NULL;
    }
#ifndef _WIN32
    if (tclNotifierHooks.createFileHandlerProc == Tcl_CreateFileHandler) {
	tclNotifierHooks.createFileHandlerProc = NULL;
    }
    if (tclNotifierHooks.deleteFileHandlerProc == Tcl_DeleteFileHandler) {
	tclNotifierHooks.deleteFileHandlerProc = NULL;
    }
#endif /* !_WIN32 */
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_CreateEventSource --
 *
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
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







-
+
















-
+







 *
 *	CheckProc is called after select or whatever operation was actually
 *	used to wait. It figures out whether anything interesting actually
 *	happened (e.g. by calling Tcl_AsyncReady), and then calls
 *	Tcl_QueueEvent to queue any events that are ready.
 *
 *	Each of these functions is passed two arguments, e.g.
 *		(*checkProc)(ClientData clientData, int flags));
 *		(*checkProc)(void *clientData, int flags));
 *	ClientData is the same as the clientData argument here, and flags is a
 *	combination of things like TCL_FILE_EVENTS that indicates what events
 *	are of interest: setupProc and checkProc use flags to figure out
 *	whether their events are relevant or not.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_CreateEventSource(
    Tcl_EventSetupProc *setupProc,
				/* Function to invoke to figure out what to
				 * wait for. */
    Tcl_EventCheckProc *checkProc,
				/* Function to call after waiting to see what
				 * happened. */
    ClientData clientData)	/* One-word argument to pass to setupProc and
    void *clientData)	/* One-word argument to pass to setupProc and
				 * checkProc. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    EventSource *sourcePtr = (EventSource *)Tcl_Alloc(sizeof(EventSource));

    sourcePtr->setupProc = setupProc;
    sourcePtr->checkProc = checkProc;
307
308
309
310
311
312
313
314

315
316
317
318
319
320
321
340
341
342
343
344
345
346

347
348
349
350
351
352
353
354







-
+







Tcl_DeleteEventSource(
    Tcl_EventSetupProc *setupProc,
				/* Function to invoke to figure out what to
				 * wait for. */
    Tcl_EventCheckProc *checkProc,
				/* Function to call after waiting to see what
				 * happened. */
    ClientData clientData)	/* One-word argument to pass to setupProc and
    void *clientData)	/* One-word argument to pass to setupProc and
				 * checkProc. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    EventSource *sourcePtr, *prevPtr;

    for (sourcePtr = tsdPtr->firstEventSourcePtr, prevPtr = NULL;
	    sourcePtr != NULL;
354
355
356
357
358
359
360
361
362


363
364
365
366
367
368
369
387
388
389
390
391
392
393


394
395
396
397
398
399
400
401
402







-
-
+
+







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. */
    Tcl_QueuePosition position)	/* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD,
				 * TCL_QUEUE_MARK. */
    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);

    QueueEvent(tsdPtr, evPtr, position);
}

/*
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

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

467
468
469
470
471
472
473
474
475
476

477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494

495
496
497
498
499
500
501
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
467
468

469
470
471
472
473
474
475
476

477
478
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







-
-
+
+


















-
+
+
+



















+
-
+







-
+








-
-
+
+


+
+
+
-
+











-
+









-
+


















+







Tcl_ThreadQueueEvent(
    Tcl_ThreadId threadId,	/* Identifier for thread to use. */
    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. */
    Tcl_QueuePosition position)	/* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD,
				 * TCL_QUEUE_MARK. */
    int position) /* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, TCL_QUEUE_MARK,
				 * possibly combined with TCL_QUEUE_ALERT_IF_EMPTY. */
{
    ThreadSpecificData *tsdPtr;

    /*
     * Find the notifier associated with the specified thread.
     */

    Tcl_MutexLock(&listLock);
    for (tsdPtr = firstNotifierPtr; tsdPtr && tsdPtr->threadId != threadId;
	    tsdPtr = tsdPtr->nextPtr) {
	/* Empty loop body. */
    }

    /*
     * Queue the event if there was a notifier associated with the thread.
     */

    if (tsdPtr) {
	QueueEvent(tsdPtr, evPtr, position);
	if (QueueEvent(tsdPtr, evPtr, position)) {
	    Tcl_AlertNotifier(tsdPtr->clientData);
	}
    } else {
	Tcl_Free(evPtr);
    }
    Tcl_MutexUnlock(&listLock);
}

/*
 *----------------------------------------------------------------------
 *
 * QueueEvent --
 *
 *	Insert an event into the specified thread's event queue at one of
 *	three positions: the head, the tail, or before a floating marker.
 *	Events inserted before the marker will be processed in first-in-
 *	first-out order, but before any events inserted at the tail of the
 *	queue. Events inserted at the head of the queue will be processed in
 *	last-in-first-out order.
 *
 * Results:
 *	For TCL_QUEUE_ALERT_IF_EMPTY the empty state before the
 *	None.
 *	operation is returned.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
static int
QueueEvent(
    ThreadSpecificData *tsdPtr,	/* Handle to thread local data that indicates
				 * which event queue to use. */
    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. */
    Tcl_QueuePosition position)	/* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD,
				 * TCL_QUEUE_MARK. */
    int position) /* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, TCL_QUEUE_MARK,
				 * possibly combined with TCL_QUEUE_ALERT_IF_EMPTY */
{
    Tcl_MutexLock(&(tsdPtr->queueMutex));
    if (tsdPtr->firstEventPtr != NULL) {
	position &= ~TCL_QUEUE_ALERT_IF_EMPTY;
    }
    if (position == TCL_QUEUE_TAIL) {
    if ((position & 3) == TCL_QUEUE_TAIL) {
	/*
	 * Append the event on the end of the queue.
	 */

	evPtr->nextPtr = NULL;
	if (tsdPtr->firstEventPtr == NULL) {
	    tsdPtr->firstEventPtr = evPtr;
	} else {
	    tsdPtr->lastEventPtr->nextPtr = evPtr;
	}
	tsdPtr->lastEventPtr = evPtr;
    } else if (position == TCL_QUEUE_HEAD) {
    } else if ((position & 3) == TCL_QUEUE_HEAD) {
	/*
	 * Push the event on the head of the queue.
	 */

	evPtr->nextPtr = tsdPtr->firstEventPtr;
	if (tsdPtr->firstEventPtr == NULL) {
	    tsdPtr->lastEventPtr = evPtr;
	}
	tsdPtr->firstEventPtr = evPtr;
    } else if (position == TCL_QUEUE_MARK) {
    } else if ((position & 3) == TCL_QUEUE_MARK) {
	/*
	 * Insert the event after the current marker event and advance the
	 * marker to the new event.
	 */

	if (tsdPtr->markerEventPtr == NULL) {
	    evPtr->nextPtr = tsdPtr->firstEventPtr;
	    tsdPtr->firstEventPtr = evPtr;
	} else {
	    evPtr->nextPtr = tsdPtr->markerEventPtr->nextPtr;
	    tsdPtr->markerEventPtr->nextPtr = evPtr;
	}
	tsdPtr->markerEventPtr = evPtr;
	if (evPtr->nextPtr == NULL) {
	    tsdPtr->lastEventPtr = evPtr;
	}
    }
    Tcl_MutexUnlock(&(tsdPtr->queueMutex));
    return position & TCL_QUEUE_ALERT_IF_EMPTY;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DeleteEvents --
 *
512
513
514
515
516
517
518
519

520
521
522
523
524
525
526
552
553
554
555
556
557
558

559
560
561
562
563
564
565
566







-
+







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

void
Tcl_DeleteEvents(
    Tcl_EventDeleteProc *proc,	/* The function to call. */
    ClientData clientData)	/* The type-specific data. */
    void *clientData)	/* The type-specific data. */
{
    Tcl_Event *evPtr;		/* Pointer to the event being examined */
    Tcl_Event *prevPtr;		/* Pointer to evPtr's predecessor, or NULL if
				 * evPtr designates the first event in the
				 * queue for the thread. */
    Tcl_Event *hold;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
790
791
792
793
794
795
796
797

798
799
800
801
802
803
804
830
831
832
833
834
835
836

837
838
839
840
841
842
843
844







-
+







 *	May reduce the length of the next sleep in the tsdPtr->
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetMaxBlockTime(
    const Tcl_Time *timePtr)		/* Specifies a maximum elapsed time for the
    const Tcl_Time *timePtr)	/* Specifies a maximum elapsed time for the
				 * next blocking operation in the event
				 * tsdPtr-> */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (!tsdPtr->blockTimeSet || (timePtr->sec < tsdPtr->blockTime.sec)
	    || ((timePtr->sec == tsdPtr->blockTime.sec)
983
984
985
986
987
988
989
990
991
992
993
994
995






996
997
998
999
1000
1001
1002
1023
1024
1025
1026
1027
1028
1029






1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042







-
-
-
-
-
-
+
+
+
+
+
+







	    }
	}
	if (flags & TCL_DONT_WAIT) {
	    break;
	}

	/*
	 * If Tcl_WaitForEvent has returned 1, indicating that one system
	 * event has been dispatched (and thus that some Tcl code might have
	 * been indirectly executed), we break out of the loop. We do this to
	 * give VwaitCmd for instance a chance to check if that system event
	 * had the side effect of changing the variable (so the vwait can
	 * return and unwind properly).
	 * If Tcl_WaitForEvent has returned 1, indicating that one system event
	 * has been dispatched (and thus that some Tcl code might have been
	 * indirectly executed), we break out of the loop in order, e.g.  to
	 * give vwait a chance to determine whether that system event had the
	 * side effect of changing the variable (so the vwait can return and
	 * unwind properly).
	 *
	 * NB: We will process idle events if any first, because otherwise we
	 *     might never do the idle events if the notifier always gets
	 *     system events.
	 */

	if (result) {
1036
1037
1038
1039
1040
1041
1042
1043

1044
1045
1046
1047
1048
1049
1050
1076
1077
1078
1079
1080
1081
1082

1083
1084
1085
1086
1087
1088
1089
1090







-
+







    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (tsdPtr->serviceMode == TCL_SERVICE_NONE) {
	return result;
    }

    /*
     * We need to turn off event servicing like we to in Tcl_DoOneEvent, to
     * We need to turn off event servicing like we do in Tcl_DoOneEvent, to
     * avoid recursive calls.
     */

    tsdPtr->serviceMode = TCL_SERVICE_NONE;

    /*
     * Check async handlers first.
1128
1129
1130
1131
1132
1133
1134






























































































































































































































































1135
1136
1137
1138
1139
1140
1141
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    Tcl_AlertNotifier(tsdPtr->clientData);
	    break;
	}
    }
    Tcl_MutexUnlock(&listLock);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_InitNotifier --
 *
 *	Initializes the platform specific notifier state. Forwards to the
 *	platform implementation when the hook is not enabled.
 *
 * Results:
 *	Returns a handle to the notifier state for this thread..
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void *
Tcl_InitNotifier(void)
{
    if (tclNotifierHooks.initNotifierProc) {
	return tclNotifierHooks.initNotifierProc();
    } else {
	return TclpInitNotifier();
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FinalizeNotifier --
 *
 *	This function is called to cleanup the notifier state before a thread
 *	is terminated. Forwards to the platform implementation when the hook
 *	is not enabled.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	If no finalizeNotifierProc notifier hook exists, TclpFinalizeNotifier
 *	is called.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_FinalizeNotifier(
    void *clientData)
{
    if (tclNotifierHooks.finalizeNotifierProc) {
	tclNotifierHooks.finalizeNotifierProc(clientData);
    } else {
	TclpFinalizeNotifier(clientData);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AlertNotifier --
 *
 *	Wake up the specified notifier from any thread. This routine is called
 *	by the platform independent notifier code whenever the Tcl_ThreadAlert
 *	routine is called. This routine is guaranteed not to be called by Tcl
 *	on a given notifier after Tcl_FinalizeNotifier is called for that
 *	notifier.  This routine is typically called from a thread other than
 *	the notifier's thread.  Forwards to the platform implementation when
 *	the hook is not enabled.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	See the platform-specific implementations.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_AlertNotifier(
    void *clientData)	/* Pointer to thread data. */
{
    if (tclNotifierHooks.alertNotifierProc) {
	tclNotifierHooks.alertNotifierProc(clientData);
    } else {
	TclpAlertNotifier(clientData);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ServiceModeHook --
 *
 *	This function is invoked whenever the service mode changes.  Forwards
 *	to the platform implementation when the hook is not enabled.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	See the platform-specific implementations.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_ServiceModeHook(
    int mode)			/* Either TCL_SERVICE_ALL, or
				 * TCL_SERVICE_NONE. */
{
    if (tclNotifierHooks.serviceModeHookProc) {
	tclNotifierHooks.serviceModeHookProc(mode);
    } else {
	TclpServiceModeHook(mode);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetTimer --
 *
 *	This function sets the current notifier timer value.  Forwards to the
 *	platform implementation when the hook is not enabled.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	See the platform-specific implementations.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetTimer(
    const Tcl_Time *timePtr)		/* Timeout value, may be NULL. */
{
    if (tclNotifierHooks.setTimerProc) {
	tclNotifierHooks.setTimerProc(timePtr);
    } else {
	TclpSetTimer(timePtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_WaitForEvent --
 *
 *	This function is called by Tcl_DoOneEvent to wait for new events on
 *	the notifier's message queue.  If the block time is 0, then
 *	Tcl_WaitForEvent just polls without blocking.  Forwards to the
 *	platform implementation when the hook is not enabled.
 *
 * Results:
 *	Returns -1 if the wait would block forever, 1 if an out-of-loop source
 *	was processed (see platform-specific notes) and otherwise returns 0.
 *
 * Side effects:
 *	Queues file events that are detected by the notifier.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_WaitForEvent(
    const Tcl_Time *timePtr)		/* Maximum block time, or NULL. */
{
    if (tclNotifierHooks.waitForEventProc) {
	return tclNotifierHooks.waitForEventProc(timePtr);
    } else {
	return TclpWaitForEvent(timePtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_CreateFileHandler --
 *
 *	This function registers a file descriptor handler with the notifier.
 *	Forwards to the platform implementation when the hook is not enabled.
 *
 *	This function is not defined on Windows. The OS API there is too
 *	different.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Creates a new file handler structure.
 *
 *----------------------------------------------------------------------
 */

#ifndef _WIN32
void
Tcl_CreateFileHandler(
    int fd,			/* Handle of stream to watch. */
    int mask,			/* OR'ed combination of TCL_READABLE,
				 * TCL_WRITABLE, and TCL_EXCEPTION: indicates
				 * conditions under which proc should be
				 * called. */
    Tcl_FileProc *proc,		/* Function to call for each selected
				 * event. */
    void *clientData)	/* Arbitrary data to pass to proc. */
{
    if (tclNotifierHooks.createFileHandlerProc) {
	tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData);
    } else {
	TclpCreateFileHandler(fd, mask, proc, clientData);
    }
}
#endif /* !_WIN32 */

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DeleteFileHandler --
 *
 *	Cancel a previously-arranged callback arrangement for a file
 *	descriptor.  Forwards to the platform implementation when the hook is
 *	not enabled.
 *
 *	This function is not defined on Windows. The OS API there is too
 *	different.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	If a callback was previously registered on the file descriptor, remove
 *	it.
 *
 *----------------------------------------------------------------------
 */

#ifndef _WIN32
void
Tcl_DeleteFileHandler(
    int fd)			/* Stream id for which to remove callback
				 * function. */
{
    if (tclNotifierHooks.deleteFileHandlerProc) {
	tclNotifierHooks.deleteFileHandlerProc(fd);
    } else {
	TclpDeleteFileHandler(fd);
    }
}
#endif /* !_WIN32 */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclOO.c.

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
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





-
-
+
+












-
+







/*
 * tclOO.c --
 *
 *	This file contains the object-system core (NB: not Tcl_Obj, but ::oo)
 *
 * Copyright (c) 2005-2012 by Donal K. Fellows
 * Copyright (c) 2017 by Nathan Coulter
 * Copyright © 2005-2019 Donal K. Fellows
 * Copyright © 2017 Nathan Coulter
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

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

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

static const struct {
    const char *name;
    Tcl_ObjCmdProc *objProc;
    int flag;
} defineCmds[] = {
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
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







-
-
-
+








-
-
+
+

-
-
+
+


-
+


-
+


-
+


-
+







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		DeletedDefineNamespace(ClientData clientData);
static void		DeletedObjdefNamespace(ClientData clientData);
static void		DeletedHelpersNamespace(ClientData clientData);
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(ClientData clientData);
static void		ObjectNamespaceDeleted(ClientData clientData);
static void		MyDeleted(void *clientData);
static void		ObjectNamespaceDeleted(void *clientData);
static Tcl_CommandTraceProc	ObjectRenamedTrace;
static inline void	RemoveClass(Class **list, int num, int idx);
static inline void	RemoveObject(Object **list, int num, int idx);
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(ClientData clientData,
static int		PublicNRObjectCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
static int		PrivateNRObjectCmd(ClientData clientData,
static int		PrivateNRObjectCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
static int		MyClassNRObjCmd(ClientData clientData,
static int		MyClassNRObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
static void		MyClassDeleted(ClientData clientData);
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.
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
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







+
+
+

















-
+
+

+
+







    DCM("varname", 0,	TclOO_Object_VarName),
    {NULL, 0, {0, NULL, NULL, NULL, NULL}}
}, clsMethods[] = {
    DCM("create", 1,	TclOO_Class_Create),
    DCM("new", 1,	TclOO_Class_New),
    DCM("createWithNamespace", 0, TclOO_Class_CreateNs),
    {NULL, 0, {0, NULL, NULL, NULL, NULL}}
}, cfgMethods[] = {
    DCM("configure", 1, TclOO_Configurable_Configure),
    {NULL, 0, {0, NULL, NULL, NULL, NULL}}
};

/*
 * And for the oo::class constructor...
 */

static const Tcl_MethodType classConstructor = {
    TCL_OO_METHOD_VERSION_CURRENT,
    "oo::class constructor",
    TclOO_Class_Constructor, NULL, NULL
};

/*
 * Scripted parts of TclOO. First, the main script (cannot be outside this
 * file).
 */

static const char *initScript =
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.
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
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







-
-
+
+

-
+








-
-
+
+

-
+







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

static inline void
RemoveClass(
    Class **list,
    int num,
    int idx)
    size_t num,
    size_t idx)
{
    for (; idx < num - 1; idx++) {
    for (; idx + 1 < num; idx++) {
	list[idx] = list[idx + 1];
    }
    list[idx] = NULL;
}

static inline void
RemoveObject(
    Object **list,
    int num,
    int idx)
    size_t num,
    size_t idx)
{
    for (; idx < num - 1; idx++) {
    for (; idx + 1 < num; idx++) {
	list[idx] = list[idx + 1];
    }
    list[idx] = NULL;
}

/*
 * ----------------------------------------------------------------------
249
250
251
252
253
254
255
256

257
258
259

260
261





262
263
264
265
266
267
268
253
254
255
256
257
258
259

260
261
262
263
264


265
266
267
268
269
270
271
272
273
274
275
276







-
+



+
-
-
+
+
+
+
+







    }

    /*
     * Run our initialization script and, if that works, declare the package
     * to be fully provided.
     */

    if (Tcl_EvalEx(interp, initScript, -1, 0) != TCL_OK) {
    if (Tcl_EvalEx(interp, initScript, TCL_INDEX_NONE, 0) != TCL_OK) {
	return TCL_ERROR;
    }

#ifndef TCL_NO_DEPRECATED
    return Tcl_PkgProvideEx(interp, "TclOO", TCLOO_PATCHLEVEL,
	    (void *) &tclOOStubs);
    Tcl_PkgProvideEx(interp, "TclOO", TCLOO_PATCHLEVEL,
	    &tclOOStubs);
#endif
    return Tcl_PkgProvideEx(interp, "tcl::oo", TCLOO_PATCHLEVEL,
	    &tclOOStubs);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOGetFoundation --
 *
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
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
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
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
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
467
468
469
470
471
472
473
474
475

476
477
478
479
480
481
482
483







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














-
-
-
+
+
+
+

-
-
-
+












-
+
-
-
+
-


+


+





+
+





+
+
-
+
+


-
-
+
+
+





-

-
-
+
-

-


-
-
+
-

-














-
-
+
-
-
-
+
-








-
+

+
-
+







-
-
+
+
-
-
-
+
+
-
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+










+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+







{
    return GetFoundation(interp);
}

/*
 * ----------------------------------------------------------------------
 *
 * CreateCmdInNS --
 *
 *	Create a command in a namespace. Supports setting various
 *	implementation functions, but not a deletion callback or a clientData;
 *	it's suitable for use-cases in this file, no more.
 *
 * ----------------------------------------------------------------------
 */
static inline void
CreateCmdInNS(
    Tcl_Interp *interp,
    Tcl_Namespace *namespacePtr,
    const char *name,
    Tcl_ObjCmdProc *cmdProc,
    Tcl_ObjCmdProc *nreProc,
    CompileProc *compileProc)
{
    Command *cmdPtr;

    if (cmdProc == NULL && nreProc == NULL) {
	Tcl_Panic("must supply at least one implementation function");
    }
    cmdPtr = (Command *) TclCreateObjCommandInNs(interp, name,
	    namespacePtr, cmdProc, NULL, NULL);
    cmdPtr->nreProc = nreProc;
    cmdPtr->compileProc = compileProc;
}

/*
 * ----------------------------------------------------------------------
 *
 * InitFoundation --
 *
 *	Set up the core of the OO core class system. This is a structure
 *	holding references to the magical bits that need to be known about in
 *	other places, plus the oo::object and oo::class classes.
 *
 * ----------------------------------------------------------------------
 */

static int
InitFoundation(
    Tcl_Interp *interp)
{
    static Tcl_ThreadDataKey tsdKey;
    ThreadLocalData *tsdPtr =
	    (ThreadLocalData *)Tcl_GetThreadData(&tsdKey, sizeof(ThreadLocalData));
    Foundation *fPtr = (Foundation *)Tcl_Alloc(sizeof(Foundation));
    ThreadLocalData *tsdPtr = (ThreadLocalData *)
	    Tcl_GetThreadData(&tsdKey, sizeof(ThreadLocalData));
    Foundation *fPtr = (Foundation *) Tcl_Alloc(sizeof(Foundation));
    Tcl_Namespace *define, *objdef;
    Tcl_Obj *namePtr;
    Tcl_DString buffer;
    Command *cmdPtr;
    int i;
    size_t i;

    /*
     * Initialize the structure that holds the OO system core. This is
     * attached to the interpreter via an assocData entry; not very efficient,
     * but the best we can do without hacking the core more.
     */

    memset(fPtr, 0, sizeof(Foundation));
    ((Interp *) interp)->objectFoundation = fPtr;
    fPtr->interp = interp;
    fPtr->ooNs = Tcl_CreateNamespace(interp, "::oo", fPtr, NULL);
    Tcl_Export(interp, fPtr->ooNs, "[a-z]*", 1);
    fPtr->defineNs = Tcl_CreateNamespace(interp, "::oo::define", fPtr,
    define = Tcl_CreateNamespace(interp, "::oo::define", fPtr, NULL);
	    DeletedDefineNamespace);
    fPtr->objdefNs = Tcl_CreateNamespace(interp, "::oo::objdefine", fPtr,
    objdef = Tcl_CreateNamespace(interp, "::oo::objdefine", fPtr, NULL);
	    DeletedObjdefNamespace);
    fPtr->helpersNs = Tcl_CreateNamespace(interp, "::oo::Helpers", fPtr,
	    DeletedHelpersNamespace);
    Tcl_CreateNamespace(interp, "::oo::configuresupport", NULL, NULL);
    fPtr->epoch = 1;
    fPtr->tsdPtr = tsdPtr;

    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);
    Tcl_CreateObjCommand(interp, "::oo::UnknownDefinition",

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

    /*
     * Create the subcommands in the oo::define and oo::objdefine spaces.
     */

    Tcl_DStringInit(&buffer);
    for (i = 0 ; defineCmds[i].name ; i++) {
	TclDStringAppendLiteral(&buffer, "::oo::define::");
	Tcl_DStringAppend(&buffer, defineCmds[i].name, -1);
	TclCreateObjCommandInNs(interp, defineCmds[i].name, define,
	Tcl_CreateObjCommand(interp, Tcl_DStringValue(&buffer),
		defineCmds[i].objProc, INT2PTR(defineCmds[i].flag), NULL);
	Tcl_DStringFree(&buffer);
    }
    for (i = 0 ; objdefCmds[i].name ; i++) {
	TclDStringAppendLiteral(&buffer, "::oo::objdefine::");
	Tcl_DStringAppend(&buffer, objdefCmds[i].name, -1);
	TclCreateObjCommandInNs(interp, objdefCmds[i].name, objdef,
	Tcl_CreateObjCommand(interp, Tcl_DStringValue(&buffer),
		objdefCmds[i].objProc, INT2PTR(objdefCmds[i].flag), NULL);
	Tcl_DStringFree(&buffer);
    }

    Tcl_CallWhenDeleted(interp, KillFoundation, NULL);

    /*
     * Create the special objects at the core of the object system.
     */

    InitClassSystemRoots(interp, fPtr);

    /*
     * Basic method declarations for the core classes.
     */

    for (i = 0 ; objMethods[i].name ; i++) {
	TclOONewBasicMethod(interp, fPtr->objectCls, &objMethods[i]);
    TclOODefineBasicMethods(fPtr->objectCls, objMethods);
    }
    for (i = 0 ; clsMethods[i].name ; i++) {
	TclOONewBasicMethod(interp, fPtr->classCls, &clsMethods[i]);
    TclOODefineBasicMethods(fPtr->classCls, clsMethods);
    }

    /*
     * Finish setting up the class of classes by marking the 'new' method as
     * private; classes, unlike general objects, must have explicit names. We
     * also need to create the constructor for classes.
     */

    TclNewLiteralStringObj(namePtr, "new");
    Tcl_NewInstanceMethod(interp, (Tcl_Object) fPtr->classCls->thisPtr,
    TclNewInstanceMethod(interp, (Tcl_Object) fPtr->classCls->thisPtr,
	    namePtr /* keeps ref */, 0 /* private */, NULL, NULL);
    Tcl_BounceRefCount(namePtr);
    fPtr->classCls->constructorPtr = (Method *) Tcl_NewMethod(interp,
    fPtr->classCls->constructorPtr = (Method *) TclNewMethod(
	    (Tcl_Class) fPtr->classCls, NULL, 0, &classConstructor, NULL);

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

    cmdPtr = (Command *) Tcl_NRCreateCommand(interp, "::oo::Helpers::next",
	    NULL, TclOONextObjCmd, NULL, NULL);
    CreateCmdInNS(interp, fPtr->helpersNs, "next",
	    NULL, TclOONextObjCmd, TclCompileObjectNextCmd);
    cmdPtr->compileProc = TclCompileObjectNextCmd;
    cmdPtr = (Command *) Tcl_NRCreateCommand(interp, "::oo::Helpers::nextto",
	    NULL, TclOONextToObjCmd, NULL, NULL);
    CreateCmdInNS(interp, fPtr->helpersNs, "nextto",
	    NULL, TclOONextToObjCmd, TclCompileObjectNextToCmd);
    cmdPtr->compileProc = TclCompileObjectNextToCmd;
    cmdPtr = (Command *) Tcl_CreateObjCommand(interp, "::oo::Helpers::self",
	    TclOOSelfObjCmd, NULL, NULL);
    cmdPtr->compileProc = TclCompileObjectSelfCmd;
    Tcl_CreateObjCommand(interp, "::oo::define", TclOODefineObjCmd, NULL,
    CreateCmdInNS(interp, fPtr->helpersNs, "self",
	    TclOOSelfObjCmd, NULL, TclCompileObjectSelfCmd);

    CreateCmdInNS(interp, fPtr->ooNs, "define", TclOODefineObjCmd, NULL, NULL);
	    NULL);
    Tcl_CreateObjCommand(interp, "::oo::objdefine", TclOOObjDefObjCmd, NULL,
	    NULL);
    Tcl_CreateObjCommand(interp, "::oo::copy", TclOOCopyObjectCmd, NULL,NULL);
    CreateCmdInNS(interp, fPtr->ooNs, "objdefine", TclOOObjDefObjCmd, NULL, NULL);
    CreateCmdInNS(interp, fPtr->ooNs, "copy", TclOOCopyObjectCmd, NULL, NULL);

    TclOOInitInfo(interp);

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

    if (TclOODefineSlots(fPtr) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Make the configurable class and install its standard defined method.
     */

    Tcl_Object cfgCls = Tcl_NewObjectInstance(interp,
	    (Tcl_Class) fPtr->classCls, "::oo::configuresupport::configurable",
	    NULL, TCL_INDEX_NONE, NULL, 0);
    TclOODefineBasicMethods(((Object *) cfgCls)->classPtr, cfgMethods);

    /*
     * Don't have handles to these namespaces, so use Tcl_CreateObjCommand.
     */

    Tcl_CreateObjCommand(interp,
	    "::oo::configuresupport::configurableobject::property",
	    TclOODefinePropertyCmd, (void *) 1, NULL);
    Tcl_CreateObjCommand(interp,
	    "::oo::configuresupport::configurableclass::property",
	    TclOODefinePropertyCmd, (void *) 0, NULL);

    /*
     * Evaluate the remaining definitions, which are a compiled-in Tcl script.
     */

    return Tcl_EvalEx(interp, tclOOSetupScript, -1, 0);
    return Tcl_EvalEx(interp, tclOOSetupScript, TCL_INDEX_NONE, 0);
}

/*
 * ----------------------------------------------------------------------
 *
 * InitClassSystemRoots --
 *
445
446
447
448
449
450
451

452
453
454
455


456
457
458
459
460
461
462
496
497
498
499
500
501
502
503
504
505


506
507
508
509
510
511
512
513
514







+


-
-
+
+







    Object fakeObject;
    Tcl_Obj *defNsName;

    /* Stand up a phony class for bootstrapping. */
    fPtr->objectCls = &fakeCls;
    /* referenced in TclOOAllocClass to increment the refCount. */
    fakeCls.thisPtr = &fakeObject;
    fakeObject.refCount = 0;	// Do not increment an uninitialized value.

    fPtr->objectCls = TclOOAllocClass(interp,
	    AllocObject(interp, "object", (Namespace *)fPtr->ooNs, NULL));
    /* Corresponding TclOODecrRefCount in KillFoudation */
	    AllocObject(interp, "object", (Namespace *) fPtr->ooNs, NULL));
    // Corresponding TclOODecrRefCount in KillFoundation
    AddRef(fPtr->objectCls->thisPtr);

    /*
     * This is why it is unnecessary in this routine to replace the
     * incremented reference count of fPtr->objectCls that was swallowed by
     * fakeObject.
     */
472
473
474
475
476
477
478
479
480


481
482
483
484
485
486
487
524
525
526
527
528
529
530


531
532
533
534
535
536
537
538
539







-
-
+
+







    fPtr->objectCls->thisPtr->flags |= ROOT_OBJECT;
    fPtr->objectCls->flags |= ROOT_OBJECT;
    TclNewLiteralStringObj(defNsName, "::oo::objdefine");
    fPtr->objectCls->objDefinitionNs = defNsName;
    Tcl_IncrRefCount(defNsName);

    fPtr->classCls = TclOOAllocClass(interp,
	    AllocObject(interp, "class", (Namespace *)fPtr->ooNs, NULL));
    /* Corresponding TclOODecrRefCount in KillFoudation */
	    AllocObject(interp, "class", (Namespace *) fPtr->ooNs, NULL));
    // Corresponding TclOODecrRefCount in KillFoundation
    AddRef(fPtr->classCls->thisPtr);

    /*
     * Increment reference counts for each reference because these
     * relationships can be dynamically changed.
     *
     * Corresponding TclOODecrRefCount for all incremented refcounts is in
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571


572
573
574
575
576
577
578
579


580
581
582
583






584
585
586
587
588
589
590
591
592
593
594
595
596
597




598
599
600
601
602
603
604
566
567
568
569
570
571
572

573
574

575
576
577
578
579
580
581


















582

583
584

585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603


604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650







-
+

-
+






-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
+

-
+


















-
-
+
+








+
+




+
+
+
+
+
+














+
+
+
+







     * Everything else is careful to prohibit looping.
     */
}

/*
 * ----------------------------------------------------------------------
 *
 * DeletedDefineNamespace, DeletedObjdefNamespace, DeletedHelpersNamespace --
 * DeletedHelpersNamespace --
 *
 *	Simple helpers used to clear fields of the foundation when they no
 *	Simple helper used to clear fields of the foundation when they no
 *	longer hold useful information.
 *
 * ----------------------------------------------------------------------
 */

static void
DeletedDefineNamespace(
    ClientData clientData)
{
    Foundation *fPtr = (Foundation *)clientData;

    fPtr->defineNs = NULL;
}

static void
DeletedObjdefNamespace(
    ClientData clientData)
{
    Foundation *fPtr = (Foundation *)clientData;

    fPtr->objdefNs = NULL;
}

static void
DeletedHelpersNamespace(
    ClientData clientData)
    void *clientData)
{
    Foundation *fPtr = (Foundation *)clientData;
    Foundation *fPtr = (Foundation *) clientData;

    fPtr->helpersNs = NULL;
}

/*
 * ----------------------------------------------------------------------
 *
 * KillFoundation --
 *
 *	Delete those parts of the OO core that are not deleted automatically
 *	when the objects and classes themselves are destroyed.
 *
 * ----------------------------------------------------------------------
 */

static void
KillFoundation(
    TCL_UNUSED(void *),
    Tcl_Interp *interp)	/* The interpreter containing the OO system
			 * foundation. */
    Tcl_Interp *interp)		/* The interpreter containing the OO system
				 * foundation. */
{
    Foundation *fPtr = GetFoundation(interp);

    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.
     */

    ((Interp *) interp)->objectFoundation = NULL;
}

/*
 * ----------------------------------------------------------------------
 *
 * AllocObject --
 *
 *	Allocate an object of basic type. Does not splice the object into its
 *	class's instance list.  The caller must set the classPtr on the object
 *	to either a class or NULL, call TclOOAddToInstances to add the object
 *	to the class's instance list, and if the object itself is a class, use
 *	call TclOOAddToSubclasses() to add it to the right class's list of
 *	subclasses.
 *
 * Returns:
 *	Pointer to the object structure created, or NULL if a specific
 *	namespace was asked for but couldn't be created.
 *
 * ----------------------------------------------------------------------
 */

static Object *
AllocObject(
    Tcl_Interp *interp,		/* Interpreter within which to create the
				 * object. */
616
617
618
619
620
621
622
623

624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642










643
644
645
646
647
648
649

650

651
652
653
654
655
656
657
662
663
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
707
708
709







-
+
















-
-
-
+
+
+
+
+
+
+
+
+
+
-
-





+
-
+







{
    Foundation *fPtr = GetFoundation(interp);
    Object *oPtr;
    Command *cmdPtr;
    CommandTrace *tracePtr;
    size_t creationEpoch;

    oPtr = (Object *)Tcl_Alloc(sizeof(Object));
    oPtr = (Object *) Tcl_Alloc(sizeof(Object));
    memset(oPtr, 0, sizeof(Object));

    /*
     * Every object has a namespace; make one. Note that this also normally
     * computes the creation epoch value for the object, a sequence number
     * that is unique to the object (and which allows us to manage method
     * caching without comparing pointers).
     *
     * When creating a namespace, we first check to see if the caller
     * specified the name for the namespace. If not, we generate namespace
     * names using the epoch until such time as a new namespace is actually
     * created.
     */

    if (nsNameStr != NULL) {
	oPtr->namespacePtr = Tcl_CreateNamespace(interp, nsNameStr, oPtr, NULL);
	if (oPtr->namespacePtr != NULL) {
	    creationEpoch = ++fPtr->tsdPtr->nsCount;
	    goto configNamespace;
	if (oPtr->namespacePtr == NULL) {
	    /*
	     * Couldn't make the specific namespace. Report as an error.
	     * [Bug 154f0982f2]
	     */
	    Tcl_Free(oPtr);
	    return NULL;
	}
	creationEpoch = ++fPtr->tsdPtr->nsCount;
	goto configNamespace;
	}
	Tcl_ResetResult(interp);
    }

    while (1) {
	char objName[10 + TCL_INTEGER_SPACE];

	snprintf(objName, sizeof(objName), "::oo::Obj%" TCL_Z_MODIFIER "u",
	sprintf(objName, "::oo::Obj%" TCL_Z_MODIFIER "u", ++fPtr->tsdPtr->nsCount);
		++fPtr->tsdPtr->nsCount);
	oPtr->namespacePtr = Tcl_CreateNamespace(interp, objName, oPtr, NULL);
	if (oPtr->namespacePtr != NULL) {
	    creationEpoch = fPtr->tsdPtr->nsCount;
	    break;
	}

	/*
712
713
714
715
716
717
718
719

720
721
722
723
724
725

726
727
728
729
730
731
732
733
734


735
736
737
738
739
740
741
742
743
744
745

746
747
748
749
750
751
752
764
765
766
767
768
769
770

771
772
773
774
775
776

777
778
779
780
781
782
783
784
785

786
787
788
789
790
791
792
793
794
795
796
797

798
799
800
801
802
803
804
805







-
+





-
+








-
+
+










-
+







     * Finally, create the object commands and initialize the trace on the
     * public command (so that the object structures are deleted when the
     * command is deleted).
     */

    if (!nameStr) {
	nameStr = oPtr->namespacePtr->name;
	nsPtr = (Namespace *)oPtr->namespacePtr;
	nsPtr = (Namespace *) oPtr->namespacePtr;
	if (nsPtr->parentPtr != NULL) {
	    nsPtr = nsPtr->parentPtr;
	}
    }
    oPtr->command = TclCreateObjCommandInNs(interp, nameStr,
	(Tcl_Namespace *)nsPtr, TclOOPublicObjectCmd, oPtr, NULL);
	(Tcl_Namespace *) nsPtr, TclOOPublicObjectCmd, oPtr, NULL);

    /*
     * Add the NRE command and trace directly. While this breaks a number of
     * abstractions, it is faster and we're inside Tcl here so we're allowed.
     */

    cmdPtr = (Command *) oPtr->command;
    cmdPtr->nreProc = PublicNRObjectCmd;
    cmdPtr->tracePtr = tracePtr = (CommandTrace *)Tcl_Alloc(sizeof(CommandTrace));
    cmdPtr->tracePtr = tracePtr = (CommandTrace *)
	    Tcl_Alloc(sizeof(CommandTrace));
    tracePtr->traceProc = ObjectRenamedTrace;
    tracePtr->clientData = oPtr;
    tracePtr->flags = TCL_TRACE_RENAME|TCL_TRACE_DELETE;
    tracePtr->nextPtr = NULL;
    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);
	    MyClassDeleted);
    return oPtr;
}

/*
 * ----------------------------------------------------------------------
 *
 * SquelchCachedName --
778
779
780
781
782
783
784
785

786
787
788

789
790
791
792
793
794
795

796
797

798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816

817
818
819
820
821
822

823
824
825
826
827
828
829
831
832
833
834
835
836
837

838
839
840

841
842
843
844
845
846
847

848
849

850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868

869
870
871
872
873
874

875
876
877
878
879
880
881
882







-
+


-
+






-
+

-
+


















-
+





-
+







 *	of those commands when the object itself is deleted.
 *
 * ----------------------------------------------------------------------
 */

static void
MyDeleted(
    ClientData clientData)	/* Reference to the object whose [my] has been
    void *clientData)		/* Reference to the object whose [my] has been
				 * squelched. */
{
    Object *oPtr = (Object *)clientData;
    Object *oPtr = (Object *) clientData;

    oPtr->myCommand = NULL;
}

static void
MyClassDeleted(
    ClientData clientData)
    void *clientData)
{
    Object *oPtr = (Object *)clientData;
    Object *oPtr = (Object *) clientData;
    oPtr->myclassCommand = NULL;
}

/*
 * ----------------------------------------------------------------------
 *
 * ObjectRenamedTrace --
 *
 *	This callback is triggered when the object is deleted by any
 *	mechanism. It runs the destructors and arranges for the actual cleanup
 *	of the object's namespace, which in turn triggers cleansing of the
 *	object data structures.
 *
 * ----------------------------------------------------------------------
 */

static void
ObjectRenamedTrace(
    ClientData clientData,	/* The object being deleted. */
    void *clientData,		/* The object being deleted. */
    TCL_UNUSED(Tcl_Interp *),
    TCL_UNUSED(const char *) /*oldName*/,
    TCL_UNUSED(const char *) /*newName*/,
    int flags)			/* Why was the object deleted? */
{
    Object *oPtr = (Object *)clientData;
    Object *oPtr = (Object *) clientData;

    /*
     * If this is a rename and not a delete of the object, we just flush the
     * cache of the object name.
     */

    if (flags & TCL_TRACE_RENAME) {
949
950
951
952
953
954
955
956

957
958
959
960
961
962
963
1002
1003
1004
1005
1006
1007
1008

1009
1010
1011
1012
1013
1014
1015
1016







-
+








void
TclOOReleaseClassContents(
    Tcl_Interp *interp,		/* The interpreter containing the class. */
    Object *oPtr)		/* The object representing the class. */
{
    FOREACH_HASH_DECLS;
    int i;
    Tcl_Size i;
    Class *clsPtr = oPtr->classPtr, *tmpClsPtr;
    Method *mPtr;
    Foundation *fPtr = oPtr->fPtr;
    Tcl_Obj *variableObj;
    PrivateVariableMapping *privateVariable;

    /*
1006
1007
1008
1009
1010
1011
1012






1013
1014
1015
1016
1017
1018
1019
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078







+
+
+
+
+
+







	    TclOODeleteChain(callPtr);
	}
	Tcl_DeleteHashTable(clsPtr->classChainCache);
	Tcl_Free(clsPtr->classChainCache);
	clsPtr->classChainCache = NULL;
    }

    /*
     * Squelch the property lists.
     */

    TclOOReleasePropertyStorage(&clsPtr->properties);

    /*
     * Squelch our filter list.
     */

    if (clsPtr->filters.num) {
	Tcl_Obj *filterObj;

1027
1028
1029
1030
1031
1032
1033
1034

1035
1036
1037
1038
1039
1040
1041
1086
1087
1088
1089
1090
1091
1092

1093
1094
1095
1096
1097
1098
1099
1100







-
+








    /*
     * Squelch our metadata.
     */

    if (clsPtr->metadataPtr != NULL) {
	Tcl_ObjectMetadataType *metadataTypePtr;
	ClientData value;
	void *value;

	FOREACH_HASH(metadataTypePtr, value, clsPtr->metadataPtr) {
	    metadataTypePtr->deleteProc(value);
	}
	Tcl_DeleteHashTable(clsPtr->metadataPtr);
	Tcl_Free(clsPtr->metadataPtr);
	clsPtr->metadataPtr = NULL;
1099
1100
1101
1102
1103
1104
1105
1106

1107
1108
1109

1110
1111
1112
1113
1114
1115
1116
1117


1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130

1131
1132
1133
1134
1135
1136
1137
1158
1159
1160
1161
1162
1163
1164

1165
1166
1167

1168
1169
1170
1171
1172
1173
1174


1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188

1189
1190
1191
1192
1193
1194
1195
1196







-
+


-
+






-
-
+
+












-
+







 *	(interpreter teardown is complex!)
 *
 * ----------------------------------------------------------------------
 */

static void
ObjectNamespaceDeleted(
    ClientData clientData)	/* Pointer to the class whose namespace is
    void *clientData)		/* Pointer to the class whose namespace is
				 * being deleted. */
{
    Object *oPtr = (Object *)clientData;
    Object *oPtr = (Object *) clientData;
    Foundation *fPtr = oPtr->fPtr;
    FOREACH_HASH_DECLS;
    Class *mixinPtr;
    Method *mPtr;
    Tcl_Obj *filterObj, *variableObj;
    PrivateVariableMapping *privateVariable;
    Tcl_Interp *interp = oPtr->fPtr->interp;
    int i;
    Tcl_Interp *interp = fPtr->interp;
    Tcl_Size i;

    if (Destructing(oPtr)) {
	/*
	 * TODO:  Can ObjectNamespaceDeleted ever be called twice?  If not,
	 * this guard could be removed.
	 */

	return;
    }

    /*
     * One rule for the teardown routines is that if an object is in the
     * process of being deleted, nothing else may modify its bookeeping
     * process of being deleted, nothing else may modify its bookkeeping
     * records.  This is the flag that
     */

    oPtr->flags |= OBJECT_DESTRUCTING;

    /*
     * Let the dominoes fall!
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159



1160
1161
1162
1163
1164
1165
1166
1206
1207
1208
1209
1210
1211
1212


1213
1214

1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225







-
-


-

+
+
+







     * in that case when the destructor is partially deleted before the uses
     * of it have gone. [Bug 2949397]
     */

    if (!Tcl_InterpDeleted(interp) && !(oPtr->flags & DESTRUCTOR_CALLED)) {
	CallContext *contextPtr =
		TclOOGetCallContext(oPtr, NULL, DESTRUCTOR, NULL, NULL, NULL);
	int result;
	Tcl_InterpState state;

	oPtr->flags |= DESTRUCTOR_CALLED;

	if (contextPtr != NULL) {
	    int result;
	    Tcl_InterpState state;

	    contextPtr->callPtr->flags |= DESTRUCTOR;
	    contextPtr->skip = 0;
	    state = Tcl_SaveInterpState(interp, TCL_OK);
	    result = Tcl_NRCallObjProc(interp, TclOOInvokeContext,
		    contextPtr, 0, NULL);
	    if (result != TCL_OK) {
		Tcl_BackgroundException(interp, result);
1176
1177
1178
1179
1180
1181
1182
1183

1184
1185
1186
1187
1188
1189
1190
1191

1192
1193
1194
1195

1196
1197
1198

1199
1200
1201
1202
1203
1204
1205
1206

1207
1208
1209
1210
1211
1212
1213
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







-
+







-
+



-
+


-
+







-
+







     * 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 the namespace,
	 * go ahead and clean up the namespace,
	 */
    } else {
	/*
	 * The namespace must have been deleted directly.  Delete the command
	 * as well.
	 */

	Tcl_DeleteCommandFromToken(oPtr->fPtr->interp, oPtr->command);
	Tcl_DeleteCommandFromToken(interp, oPtr->command);
    }

    if (oPtr->myclassCommand) {
	Tcl_DeleteCommandFromToken(oPtr->fPtr->interp, oPtr->myclassCommand);
	Tcl_DeleteCommandFromToken(interp, oPtr->myclassCommand);
    }
    if (oPtr->myCommand) {
	Tcl_DeleteCommandFromToken(oPtr->fPtr->interp, oPtr->myCommand);
	Tcl_DeleteCommandFromToken(interp, oPtr->myCommand);
    }

    /*
     * Splice the object out of its context. After this, we must *not* call
     * methods on the object.
     */

    /* TODO: Should this be protected with a !IsRoot() condition? */
    // TODO: Should this be protected with a !IsRoot() condition?
    TclOORemoveFromInstances(oPtr, oPtr->selfCls);

    if (oPtr->mixins.num > 0) {
	FOREACH(mixinPtr, oPtr->mixins) {
	    TclOORemoveFromInstances(oPtr, mixinPtr);
	    TclOODecrRefCount(mixinPtr->thisPtr);
	}
1250
1251
1252
1253
1254
1255
1256
1257

1258
1259
1260
1261
1262
1263
1264
1265
1266






1267
1268
1269
1270
1271
1272
1273
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







-
+









+
+
+
+
+
+







	TclOODeleteChainCache(oPtr->chainCache);
    }

    SquelchCachedName(oPtr);

    if (oPtr->metadataPtr != NULL) {
	Tcl_ObjectMetadataType *metadataTypePtr;
	ClientData value;
	void *value;

	FOREACH_HASH(metadataTypePtr, value, oPtr->metadataPtr) {
	    metadataTypePtr->deleteProc(value);
	}
	Tcl_DeleteHashTable(oPtr->metadataPtr);
	Tcl_Free(oPtr->metadataPtr);
	oPtr->metadataPtr = NULL;
    }

    /*
     * Squelch the property lists.
     */

    TclOOReleasePropertyStorage(&oPtr->properties);

    /*
     * Because an object can be a class that is an instance of itself, the
     * class object's class structure should only be cleaned after most of
     * the cleanup on the object is done.
     *
     * The class of objects needs some special care; if it is deleted (and
     * we're not killing the whole interpreter) we force the delete of the
1285
1286
1287
1288
1289
1290
1291
1292

1293
1294
1295
1296
1297
1298
1299
1350
1351
1352
1353
1354
1355
1356

1357
1358
1359
1360
1361
1362
1363
1364







-
+







	TclOOReleaseClassContents(interp, oPtr);
    }

    /*
     * Delete the object structure itself.
     */

    TclNsDecrRefCount((Namespace *)oPtr->namespacePtr);
    TclNsDecrRefCount((Namespace *) oPtr->namespacePtr);
    oPtr->namespacePtr = NULL;
    TclOODecrRefCount(oPtr->selfCls->thisPtr);
    oPtr->selfCls = NULL;
    TclOODecrRefCount(oPtr);
    return;
}

1330
1331
1332
1333
1334
1335
1336

1337



1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357

1358

1359
1360
1361
1362
1363
1364
1365
1395
1396
1397
1398
1399
1400
1401
1402

1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426

1427
1428
1429
1430
1431
1432
1433
1434







+
-
+
+
+




















+
-
+







 * TclOOObjectDestroyed --
 *
 *	Returns TCL_OK if an object is entirely deleted, i.e. the destruction
 *	sequence has completed.
 *
 * ----------------------------------------------------------------------
 */
int
int TclOOObjectDestroyed(Object *oPtr) {
TclOOObjectDestroyed(
    Object *oPtr)
{
    return (oPtr->namespacePtr == NULL);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOORemoveFromInstances --
 *
 *	Utility function to remove an object from the list of instances within
 *	a class.
 *
 * ----------------------------------------------------------------------
 */

int
TclOORemoveFromInstances(
    Object *oPtr,		/* The instance to remove. */
    Class *clsPtr)		/* The class (possibly) containing the
				 * reference to the instance. */
{
    Tcl_Size i;
    int i, res = 0;
    int res = 0;
    Object *instPtr;

    FOREACH(instPtr, clsPtr->instances) {
	if (oPtr == instPtr) {
	    RemoveItem(Object, clsPtr->instances, i);
	    TclOODecrRefCount(oPtr);
	    res++;
1386
1387
1388
1389
1390
1391
1392
1393


1394
1395
1396



1397
1398
1399
1400
1401
1402
1403
1455
1456
1457
1458
1459
1460
1461

1462
1463
1464


1465
1466
1467
1468
1469
1470
1471
1472
1473
1474







-
+
+

-
-
+
+
+







    Class *clsPtr)		/* The class to add the instance to. It is
				 * assumed that the class is not already
				 * present as an instance in the class. */
{
    if (clsPtr->instances.num >= clsPtr->instances.size) {
	clsPtr->instances.size += ALLOC_CHUNK;
	if (clsPtr->instances.size == ALLOC_CHUNK) {
	    clsPtr->instances.list = (Object **)Tcl_Alloc(sizeof(Object *) * ALLOC_CHUNK);
	    clsPtr->instances.list = (Object **)
		    Tcl_Alloc(sizeof(Object *) * ALLOC_CHUNK);
	} else {
	    clsPtr->instances.list = (Object **)Tcl_Realloc(clsPtr->instances.list,
		    sizeof(Object *) * clsPtr->instances.size);
	    clsPtr->instances.list = (Object **)
		    Tcl_Realloc(clsPtr->instances.list,
			    sizeof(Object *) * clsPtr->instances.size);
	}
    }
    clsPtr->instances.list[clsPtr->instances.num++] = oPtr;
    AddRef(oPtr);
}

/*
1413
1414
1415
1416
1417
1418
1419

1420

1421
1422
1423
1424
1425
1426
1427
1484
1485
1486
1487
1488
1489
1490
1491

1492
1493
1494
1495
1496
1497
1498
1499







+
-
+








int
TclOORemoveFromMixins(
    Class *mixinPtr,		/* The mixin to remove. */
    Object *oPtr)		/* The object (possibly) containing the
				 * reference to the mixin. */
{
    Tcl_Size i;
    int i, res = 0;
    int res = 0;
    Class *mixPtr;

    FOREACH(mixPtr, oPtr->mixins) {
	if (mixinPtr == mixPtr) {
	    RemoveItem(Class, oPtr->mixins, i);
	    TclOODecrRefCount(mixPtr->thisPtr);
	    res++;
1448
1449
1450
1451
1452
1453
1454

1455

1456
1457
1458
1459
1460
1461
1462
1520
1521
1522
1523
1524
1525
1526
1527

1528
1529
1530
1531
1532
1533
1534
1535







+
-
+








int
TclOORemoveFromSubclasses(
    Class *subPtr,		/* The subclass to remove. */
    Class *superPtr)		/* The superclass to possibly remove the
				 * subclass reference from. */
{
    Tcl_Size i;
    int i, res = 0;
    int res = 0;
    Class *subclsPtr;

    FOREACH(subclsPtr, superPtr->subclasses) {
	if (subPtr == subclsPtr) {
	    RemoveItem(Class, superPtr->subclasses, i);
	    TclOODecrRefCount(subPtr->thisPtr);
	    res++;
1485
1486
1487
1488
1489
1490
1491
1492


1493
1494
1495



1496
1497
1498
1499
1500
1501
1502
1558
1559
1560
1561
1562
1563
1564

1565
1566
1567


1568
1569
1570
1571
1572
1573
1574
1575
1576
1577







-
+
+

-
-
+
+
+







{
    if (Destructing(superPtr->thisPtr)) {
	return;
    }
    if (superPtr->subclasses.num >= superPtr->subclasses.size) {
	superPtr->subclasses.size += ALLOC_CHUNK;
	if (superPtr->subclasses.size == ALLOC_CHUNK) {
	    superPtr->subclasses.list = (Class **)Tcl_Alloc(sizeof(Class *) * ALLOC_CHUNK);
	    superPtr->subclasses.list = (Class **)
		    Tcl_Alloc(sizeof(Class *) * ALLOC_CHUNK);
	} else {
	    superPtr->subclasses.list = (Class **)Tcl_Realloc(superPtr->subclasses.list,
		    sizeof(Class *) * superPtr->subclasses.size);
	    superPtr->subclasses.list = (Class **)
		    Tcl_Realloc(superPtr->subclasses.list,
			    sizeof(Class *) * superPtr->subclasses.size);
	}
    }
    superPtr->subclasses.list[superPtr->subclasses.num++] = subPtr;
    AddRef(subPtr->thisPtr);
}

/*
1512
1513
1514
1515
1516
1517
1518

1519

1520
1521
1522
1523
1524
1525
1526
1587
1588
1589
1590
1591
1592
1593
1594

1595
1596
1597
1598
1599
1600
1601
1602







+
-
+








int
TclOORemoveFromMixinSubs(
    Class *subPtr,		/* The subclass to remove. */
    Class *superPtr)		/* The superclass to possibly remove the
				 * subclass reference from. */
{
    Tcl_Size i;
    int i, res = 0;
    int res = 0;
    Class *subclsPtr;

    FOREACH(subclsPtr, superPtr->mixinSubs) {
	if (subPtr == subclsPtr) {
	    RemoveItem(Class, superPtr->mixinSubs, i);
	    TclOODecrRefCount(subPtr->thisPtr);
	    res++;
1550
1551
1552
1553
1554
1555
1556
1557


1558
1559
1560



1561
1562
1563
1564
1565
1566
1567
1626
1627
1628
1629
1630
1631
1632

1633
1634
1635


1636
1637
1638
1639
1640
1641
1642
1643
1644
1645







-
+
+

-
-
+
+
+







{
    if (Destructing(superPtr->thisPtr)) {
	return;
    }
    if (superPtr->mixinSubs.num >= superPtr->mixinSubs.size) {
	superPtr->mixinSubs.size += ALLOC_CHUNK;
	if (superPtr->mixinSubs.size == ALLOC_CHUNK) {
	    superPtr->mixinSubs.list = (Class **)Tcl_Alloc(sizeof(Class *) * ALLOC_CHUNK);
	    superPtr->mixinSubs.list = (Class **)
		    Tcl_Alloc(sizeof(Class *) * ALLOC_CHUNK);
	} else {
	    superPtr->mixinSubs.list = (Class **)Tcl_Realloc(superPtr->mixinSubs.list,
		    sizeof(Class *) * superPtr->mixinSubs.size);
	    superPtr->mixinSubs.list = (Class **)
		    Tcl_Realloc(superPtr->mixinSubs.list,
			    sizeof(Class *) * superPtr->mixinSubs.size);
	}
    }
    superPtr->mixinSubs.list[superPtr->mixinSubs.num++] = subPtr;
    AddRef(subPtr->thisPtr);
}

/*
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
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







-
+
















-
+







TclOOAllocClass(
    Tcl_Interp *interp,		/* Interpreter within which to allocate the
				 * class. */
    Object *useThisObj)		/* Object that is to act as the class
				 * representation. */
{
    Foundation *fPtr = GetFoundation(interp);
    Class *clsPtr = (Class *)Tcl_Alloc(sizeof(Class));
    Class *clsPtr = (Class *) Tcl_Alloc(sizeof(Class));

    memset(clsPtr, 0, sizeof(Class));
    clsPtr->thisPtr = useThisObj;

    /*
     * Configure the namespace path for the class's object.
     */

    InitClassPath(interp, clsPtr);

    /*
     * Classes are subclasses of oo::object, i.e. the objects they create are
     * objects.
     */

    clsPtr->superclasses.num = 1;
    clsPtr->superclasses.list = (Class **)Tcl_Alloc(sizeof(Class *));
    clsPtr->superclasses.list = (Class **) Tcl_Alloc(sizeof(Class *));
    clsPtr->superclasses.list[0] = fPtr->objectCls;
    AddRef(fPtr->objectCls->thisPtr);

    /*
     * Finish connecting the class structure to the object structure.
     */

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
1730
1731
1732
1733
1734
1735
1736

1737
1738
1739

1740
1741
1742
1743
1744

1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756

1757
1758
1759
1760
1761
1762
1763
1764







-
+


-
+




-
+











-
+







    Tcl_Interp *interp,		/* Interpreter context. */
    Tcl_Class cls,		/* Class to create an instance of. */
    const char *nameStr,	/* Name of object to create, or NULL to ask
				 * the code to pick its own unique name. */
    const char *nsNameStr,	/* Name of namespace to create inside object,
				 * or NULL to ask the code to pick its own
				 * unique name. */
    int objc,			/* Number of arguments. Negative value means
    Tcl_Size objc,		/* Number of arguments. Negative value means
				 * do not call constructor. */
    Tcl_Obj *const *objv,	/* Argument list. */
    int skip)			/* Number of arguments to _not_ pass to the
    Tcl_Size skip)		/* Number of arguments to _not_ pass to the
				 * constructor. */
{
    Class *classPtr = (Class *) cls;
    Object *oPtr;
    ClientData clientData[4];
    void *clientData[4];

    oPtr = TclNewObjectInstanceCommon(interp, classPtr, nameStr, nsNameStr);
    if (oPtr == NULL) {
	return NULL;
    }

    /*
     * Run constructors, except when objc < 0, which is a special flag case
     * used for object cloning only.
     */

    if (objc >= 0) {
    if (objc != TCL_INDEX_NONE) {
	CallContext *contextPtr =
		TclOOGetCallContext(oPtr, NULL, CONSTRUCTOR, NULL, NULL, NULL);

	if (contextPtr != NULL) {
	    int isRoot, result;
	    Tcl_InterpState state;

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
1749
1750
1751
1752
1753
1798
1799
1800
1801
1802
1803
1804

1805
1806
1807

1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823

1824
1825
1826
1827
1828
1829
1830
1831







-
+


-
+















-
+







    Tcl_Interp *interp,		/* Interpreter context. */
    Tcl_Class cls,		/* Class to create an instance of. */
    const char *nameStr,	/* Name of object to create, or NULL to ask
				 * the code to pick its own unique name. */
    const char *nsNameStr,	/* Name of namespace to create inside object,
				 * or NULL to ask the code to pick its own
				 * unique name. */
    int objc,			/* Number of arguments. Negative value means
    Tcl_Size objc,		/* Number of arguments. Negative value means
				 * do not call constructor. */
    Tcl_Obj *const *objv,	/* Argument list. */
    int skip,			/* Number of arguments to _not_ pass to the
    Tcl_Size skip,		/* Number of arguments to _not_ pass to the
				 * constructor. */
    Tcl_Object *objectPtr)	/* Place to write the object reference upon
				 * successful allocation. */
{
    Class *classPtr = (Class *) cls;
    CallContext *contextPtr;
    Tcl_InterpState state;
    Object *oPtr;

    oPtr = TclNewObjectInstanceCommon(interp, classPtr, nameStr, nsNameStr);
    if (oPtr == NULL) {
	return TCL_ERROR;
    }

    /*
     * Run constructors, except when objc < 0 (a special flag case used for
     * Run constructors, except when objc == TCL_INDEX_NONE (a special flag case used for
     * object cloning only). If there aren't any constructors, we do nothing.
     */

    if (objc < 0) {
	*objectPtr = (Tcl_Object) oPtr;
	return TCL_OK;
    }
1802
1803
1804
1805
1806
1807
1808
1809

1810
1811
1812
1813
1814
1815
1816
1817
1818



1819
1820
1821
1822
1823
1824
1825
1880
1881
1882
1883
1884
1885
1886

1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906







-
+









+
+
+







	 */

	hPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, simpleName);
	if (hPtr) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't create object \"%s\": command already exists with"
		    " that name", nameStr));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "OVERWRITE_OBJECT", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "OO", "OVERWRITE_OBJECT", (char *)NULL);
	    return NULL;
	}
    }

    /*
     * Create the object.
     */

    oPtr = AllocObject(interp, simpleName, nsPtr, nsNameStr);
    if (oPtr == NULL) {
	return NULL;
    }
    oPtr->selfCls = classPtr;
    AddRef(classPtr->thisPtr);
    TclOOAddToInstances(oPtr, classPtr);

    /*
     * Check to see if we're really creating a class. If so, allocate the
     * class structure as well.
1839
1840
1841
1842
1843
1844
1845
1846

1847
1848
1849
1850
1851
1852
1853




1854
1855
1856
1857
1858
1859
1860
1861
1862
1863


1864
1865
1866
1867
1868
1869
1870
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







-
+



-
-
-
-
+
+
+
+








-
-
+
+







	oPtr->classPtr = NULL;
    }
    return oPtr;
}

static int
FinalizeAlloc(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    CallContext *contextPtr = (CallContext *)data[0];
    Object *oPtr = (Object *)data[1];
    Tcl_InterpState state = (Tcl_InterpState)data[2];
    Tcl_Object *objectPtr = (Tcl_Object *)data[3];
    CallContext *contextPtr = (CallContext *) data[0];
    Object *oPtr = (Object *) data[1];
    Tcl_InterpState state = (Tcl_InterpState) data[2];
    Tcl_Object *objectPtr = (Tcl_Object *) data[3];

    /*
     * Ensure an error if the object was deleted in the constructor. Don't
     * want to lose errors by accident. [Bug 2903011]
     */

    if (result != TCL_ERROR && Destructing(oPtr)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"object deleted in constructor", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "STILLBORN", NULL);
		"object deleted in constructor", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "STILLBORN", (char *)NULL);
	result = TCL_ERROR;
    }
    if (result != TCL_OK) {
	Tcl_DiscardInterpState(state);

	/*
	 * Take care to not delete a deleted object; that would be bad. [Bug
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
1998
1999
2000
2001
2002
2003
2004
2005

2006
2007
2008
2009
2010
2011
2012
2013


2014
2015
2016
2017
2018
2019
2020
2021
2022
2023


2024
2025
2026
2027
2028
2029
2030
2031
2032







+
-
+







-
-
+
+








-
-
+
+







    Object *oPtr = (Object *) sourceObject, *o2Ptr;
    FOREACH_HASH_DECLS;
    Method *mPtr;
    Class *mixinPtr;
    CallContext *contextPtr;
    Tcl_Obj *keyPtr, *filterObj, *variableObj, *args[3];
    PrivateVariableMapping *privateVariable;
    Tcl_Size i;
    int i, result;
    int result;

    /*
     * Sanity check.
     */

    if (IsRootClass(oPtr)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"may not clone the class of classes", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "CLONING_CLASS", NULL);
		"may not clone the class of classes", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "CLONING_CLASS", (char *)NULL);
	return NULL;
    }

    /*
     * Build the instance. Note that this does not run any constructors.
     */

    o2Ptr = (Object *) Tcl_NewObjectInstance(interp,
	    (Tcl_Class) oPtr->selfCls, targetName, targetNamespaceName, -1,
	    NULL, -1);
	    (Tcl_Class) oPtr->selfCls, targetName, targetNamespaceName,
	    TCL_INDEX_NONE, NULL, 0);
    if (o2Ptr == NULL) {
	return NULL;
    }

    /*
     * Copy the object-local methods to the new object.
     */
2021
2022
2023
2024
2025
2026
2027
2028

2029
2030
2031
2032
2033
2034
2035
2103
2104
2105
2106
2107
2108
2109

2110
2111
2112
2113
2114
2115
2116
2117







-
+








    /*
     * Copy the object's metadata.
     */

    if (oPtr->metadataPtr != NULL) {
	Tcl_ObjectMetadataType *metadataTypePtr;
	ClientData value, duplicate;
	void *value, *duplicate;

	FOREACH_HASH(metadataTypePtr, value, oPtr->metadataPtr) {
	    if (metadataTypePtr->cloneProc == NULL) {
		duplicate = value;
	    } else {
		if (metadataTypePtr->cloneProc(interp, value,
			&duplicate) != TCL_OK) {
2066
2067
2068
2069
2070
2071
2072
2073
2074



2075
2076
2077


2078
2079
2080
2081
2082
2083
2084
2148
2149
2150
2151
2152
2153
2154


2155
2156
2157
2158


2159
2160
2161
2162
2163
2164
2165
2166
2167







-
-
+
+
+

-
-
+
+







	 */

	FOREACH(superPtr, cls2Ptr->superclasses) {
	    TclOORemoveFromSubclasses(cls2Ptr, superPtr);
	    TclOODecrRefCount(superPtr->thisPtr);
	}
	if (cls2Ptr->superclasses.num) {
	    cls2Ptr->superclasses.list = (Class **)Tcl_Realloc(cls2Ptr->superclasses.list,
		    sizeof(Class *) * clsPtr->superclasses.num);
	    cls2Ptr->superclasses.list = (Class **)
		    Tcl_Realloc(cls2Ptr->superclasses.list,
			    sizeof(Class *) * clsPtr->superclasses.num);
	} else {
	    cls2Ptr->superclasses.list =
		    (Class **)Tcl_Alloc(sizeof(Class *) * clsPtr->superclasses.num);
	    cls2Ptr->superclasses.list = (Class **)
		    Tcl_Alloc(sizeof(Class *) * clsPtr->superclasses.num);
	}
	memcpy(cls2Ptr->superclasses.list, clsPtr->superclasses.list,
		sizeof(Class *) * clsPtr->superclasses.num);
	cls2Ptr->superclasses.num = clsPtr->superclasses.num;
	FOREACH(superPtr, cls2Ptr->superclasses) {
	    TclOOAddToSubclasses(cls2Ptr, superPtr);

2166
2167
2168
2169
2170
2171
2172
2173

2174
2175
2176
2177
2178
2179
2180
2249
2250
2251
2252
2253
2254
2255

2256
2257
2258
2259
2260
2261
2262
2263







-
+








	/*
	 * Duplicate the class's metadata.
	 */

	if (clsPtr->metadataPtr != NULL) {
	    Tcl_ObjectMetadataType *metadataTypePtr;
	    ClientData value, duplicate;
	    void *value, *duplicate;

	    FOREACH_HASH(metadataTypePtr, value, clsPtr->metadataPtr) {
		if (metadataTypePtr->cloneProc == NULL) {
		    duplicate = value;
		} else {
		    if (metadataTypePtr->cloneProc(interp, value,
			    &duplicate) != TCL_OK) {
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
2273
2274

2275
2276
2277
2278
2279
2280

2281
2282
2283
2284

2285
2286
2287
2288
2289
2290
2291
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







-
+


-
+





-
+


-
+
















-
+


-
+





-
+



-
+







CloneObjectMethod(
    Tcl_Interp *interp,
    Object *oPtr,
    Method *mPtr,
    Tcl_Obj *namePtr)
{
    if (mPtr->typePtr == NULL) {
	Tcl_NewInstanceMethod(interp, (Tcl_Object) oPtr, namePtr,
	TclNewInstanceMethod(interp, (Tcl_Object) oPtr, namePtr,
		mPtr->flags & PUBLIC_METHOD, NULL, NULL);
    } else if (mPtr->typePtr->cloneProc) {
	ClientData newClientData;
	void *newClientData;

	if (mPtr->typePtr->cloneProc(interp, mPtr->clientData,
		&newClientData) != TCL_OK) {
	    return TCL_ERROR;
	}
	Tcl_NewInstanceMethod(interp, (Tcl_Object) oPtr, namePtr,
	TclNewInstanceMethod(interp, (Tcl_Object) oPtr, namePtr,
		mPtr->flags & PUBLIC_METHOD, mPtr->typePtr, newClientData);
    } else {
	Tcl_NewInstanceMethod(interp, (Tcl_Object) oPtr, namePtr,
	TclNewInstanceMethod(interp, (Tcl_Object) oPtr, namePtr,
		mPtr->flags & PUBLIC_METHOD, mPtr->typePtr, mPtr->clientData);
    }
    return TCL_OK;
}

static int
CloneClassMethod(
    Tcl_Interp *interp,
    Class *clsPtr,
    Method *mPtr,
    Tcl_Obj *namePtr,
    Method **m2PtrPtr)
{
    Method *m2Ptr;

    if (mPtr->typePtr == NULL) {
	m2Ptr = (Method *) Tcl_NewMethod(interp, (Tcl_Class) clsPtr,
	m2Ptr = (Method *) TclNewMethod((Tcl_Class) clsPtr,
		namePtr, mPtr->flags & PUBLIC_METHOD, NULL, NULL);
    } else if (mPtr->typePtr->cloneProc) {
	ClientData newClientData;
	void *newClientData;

	if (mPtr->typePtr->cloneProc(interp, mPtr->clientData,
		&newClientData) != TCL_OK) {
	    return TCL_ERROR;
	}
	m2Ptr = (Method *) Tcl_NewMethod(interp, (Tcl_Class) clsPtr,
	m2Ptr = (Method *) TclNewMethod((Tcl_Class) clsPtr,
		namePtr, mPtr->flags & PUBLIC_METHOD, mPtr->typePtr,
		newClientData);
    } else {
	m2Ptr = (Method *) Tcl_NewMethod(interp, (Tcl_Class) clsPtr,
	m2Ptr = (Method *) TclNewMethod((Tcl_Class) clsPtr,
		namePtr, mPtr->flags & PUBLIC_METHOD, mPtr->typePtr,
		mPtr->clientData);
    }
    if (m2PtrPtr != NULL) {
	*m2PtrPtr = m2Ptr;
    }
    return TCL_OK;
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
2390
2391
2392
2393

2394
2395
2396
2397
2398
2399
2400

2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421

2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437

2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2396
2397
2398
2399
2400
2401
2402

2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423

2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439

2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504

2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520

2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534

2535
2536
2537
2538
2539
2540
2541
2542
2543

2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556

2557
2558
2559
2560
2561
2562
2563
2564







-
+




















-
+















-
+













-
+
+








-
+












-
+






-
+




















-
+















-
+













-
+








-
+












-
+







 *	attached (replacing the previous value, which is deleted if present)
 *	otherwise. This means it is impossible to attach a NULL value for any
 *	metadata type.
 *
 * ----------------------------------------------------------------------
 */

ClientData
void *
Tcl_ClassGetMetadata(
    Tcl_Class clazz,
    const Tcl_ObjectMetadataType *typePtr)
{
    Class *clsPtr = (Class *) clazz;
    Tcl_HashEntry *hPtr;

    /*
     * If there's no metadata store attached, the type in question has
     * definitely not been attached either!
     */

    if (clsPtr->metadataPtr == NULL) {
	return NULL;
    }

    /*
     * There is a metadata store, so look in it for the given type.
     */

    hPtr = Tcl_FindHashEntry(clsPtr->metadataPtr, (char *) typePtr);
    hPtr = Tcl_FindHashEntry(clsPtr->metadataPtr, typePtr);

    /*
     * Return the metadata value if we found it, otherwise NULL.
     */

    if (hPtr == NULL) {
	return NULL;
    }
    return Tcl_GetHashValue(hPtr);
}

void
Tcl_ClassSetMetadata(
    Tcl_Class clazz,
    const Tcl_ObjectMetadataType *typePtr,
    ClientData metadata)
    void *metadata)
{
    Class *clsPtr = (Class *) clazz;
    Tcl_HashEntry *hPtr;
    int isNew;

    /*
     * Attach the metadata store if not done already.
     */

    if (clsPtr->metadataPtr == NULL) {
	if (metadata == NULL) {
	    return;
	}
	clsPtr->metadataPtr = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));
	clsPtr->metadataPtr = (Tcl_HashTable *)
		Tcl_Alloc(sizeof(Tcl_HashTable));
	Tcl_InitHashTable(clsPtr->metadataPtr, TCL_ONE_WORD_KEYS);
    }

    /*
     * If the metadata is NULL, we're deleting the metadata for the type.
     */

    if (metadata == NULL) {
	hPtr = Tcl_FindHashEntry(clsPtr->metadataPtr, (char *) typePtr);
	hPtr = Tcl_FindHashEntry(clsPtr->metadataPtr, typePtr);
	if (hPtr != NULL) {
	    typePtr->deleteProc(Tcl_GetHashValue(hPtr));
	    Tcl_DeleteHashEntry(hPtr);
	}
	return;
    }

    /*
     * Otherwise we're attaching the metadata. Note that if there was already
     * some metadata attached of this type, we delete that first.
     */

    hPtr = Tcl_CreateHashEntry(clsPtr->metadataPtr, (char *) typePtr, &isNew);
    hPtr = Tcl_CreateHashEntry(clsPtr->metadataPtr, typePtr, &isNew);
    if (!isNew) {
	typePtr->deleteProc(Tcl_GetHashValue(hPtr));
    }
    Tcl_SetHashValue(hPtr, metadata);
}

ClientData
void *
Tcl_ObjectGetMetadata(
    Tcl_Object object,
    const Tcl_ObjectMetadataType *typePtr)
{
    Object *oPtr = (Object *) object;
    Tcl_HashEntry *hPtr;

    /*
     * If there's no metadata store attached, the type in question has
     * definitely not been attached either!
     */

    if (oPtr->metadataPtr == NULL) {
	return NULL;
    }

    /*
     * There is a metadata store, so look in it for the given type.
     */

    hPtr = Tcl_FindHashEntry(oPtr->metadataPtr, (char *) typePtr);
    hPtr = Tcl_FindHashEntry(oPtr->metadataPtr, typePtr);

    /*
     * Return the metadata value if we found it, otherwise NULL.
     */

    if (hPtr == NULL) {
	return NULL;
    }
    return Tcl_GetHashValue(hPtr);
}

void
Tcl_ObjectSetMetadata(
    Tcl_Object object,
    const Tcl_ObjectMetadataType *typePtr,
    ClientData metadata)
    void *metadata)
{
    Object *oPtr = (Object *) object;
    Tcl_HashEntry *hPtr;
    int isNew;

    /*
     * Attach the metadata store if not done already.
     */

    if (oPtr->metadataPtr == NULL) {
	if (metadata == NULL) {
	    return;
	}
	oPtr->metadataPtr = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));
	oPtr->metadataPtr = (Tcl_HashTable *) Tcl_Alloc(sizeof(Tcl_HashTable));
	Tcl_InitHashTable(oPtr->metadataPtr, TCL_ONE_WORD_KEYS);
    }

    /*
     * If the metadata is NULL, we're deleting the metadata for the type.
     */

    if (metadata == NULL) {
	hPtr = Tcl_FindHashEntry(oPtr->metadataPtr, (char *) typePtr);
	hPtr = Tcl_FindHashEntry(oPtr->metadataPtr, typePtr);
	if (hPtr != NULL) {
	    typePtr->deleteProc(Tcl_GetHashValue(hPtr));
	    Tcl_DeleteHashEntry(hPtr);
	}
	return;
    }

    /*
     * Otherwise we're attaching the metadata. Note that if there was already
     * some metadata attached of this type, we delete that first.
     */

    hPtr = Tcl_CreateHashEntry(oPtr->metadataPtr, (char *) typePtr, &isNew);
    hPtr = Tcl_CreateHashEntry(oPtr->metadataPtr, typePtr, &isNew);
    if (!isNew) {
	typePtr->deleteProc(Tcl_GetHashValue(hPtr));
    }
    Tcl_SetHashValue(hPtr, metadata);
}

/*
2488
2489
2490
2491
2492
2493
2494
2495

2496
2497
2498
2499
2500

2501
2502
2503
2504
2505

2506
2507
2508
2509
2510
2511


2512
2513
2514
2515
2516

2517
2518
2519
2520
2521

2522
2523
2524
2525
2526

2527
2528
2529
2530
2531

2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547

2548
2549
2550
2551
2552
2553
2554
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







-
+




-
+




-
+




-
-
+
+




-
+




-
+




-
+




-
+















-
+







 *	function. Note that the core is function is NRE-aware.
 *
 * ----------------------------------------------------------------------
 */

int
TclOOPublicObjectCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    return Tcl_NRCallObjProc(interp, PublicNRObjectCmd, clientData,objc,objv);
    return Tcl_NRCallObjProc(interp, PublicNRObjectCmd, clientData, objc, objv);
}

static int
PublicNRObjectCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    return TclOOObjectCmdCore((Object *)clientData, interp, objc, objv, PUBLIC_METHOD,
	    NULL);
    return TclOOObjectCmdCore((Object *) clientData, interp, objc, objv,
	    PUBLIC_METHOD, NULL);
}

int
TclOOPrivateObjectCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    return Tcl_NRCallObjProc(interp, PrivateNRObjectCmd,clientData,objc,objv);
    return Tcl_NRCallObjProc(interp, PrivateNRObjectCmd, clientData, objc, objv);
}

static int
PrivateNRObjectCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    return TclOOObjectCmdCore((Object *)clientData, interp, objc, objv, 0, NULL);
    return TclOOObjectCmdCore((Object *) clientData, interp, objc, objv, 0, NULL);
}

int
TclOOInvokeObject(
    Tcl_Interp *interp,		/* Interpreter for commands, variables,
				 * results, error reporting, etc. */
    Tcl_Object object,		/* The object to invoke. */
    Tcl_Class startCls,		/* Where in the class chain to start the
				 * invoke from, or NULL to traverse the whole
				 * chain including filters. */
    int publicPrivate,		/* Whether this is an invoke from a public
				 * context (PUBLIC_METHOD), a private context
				 * (PRIVATE_METHOD), or a *really* private
				 * context (any other value; conventionally
				 * 0). */
    int objc,			/* Number of arguments. */
    Tcl_Size objc,		/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Array of argument objects. It is assumed
				 * that the name of the method to invoke will
				 * be at index 1. */
{
    switch (publicPrivate) {
    case PUBLIC_METHOD:
	return TclOOObjectCmdCore((Object *) object, interp, objc, objv,
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
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







-
+









-
+




-
+







 *	Special trap door to allow an object to delegate simply to its class.
 *
 * ----------------------------------------------------------------------
 */

int
TclOOMyClassObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    return Tcl_NRCallObjProc(interp, MyClassNRObjCmd, clientData, objc, objv);
}

static int
MyClassNRObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *)clientData;
    Object *oPtr = (Object *) clientData;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "methodName ?arg ...?");
	return TCL_ERROR;
    }
    return TclOOObjectCmdCore(oPtr->selfCls->thisPtr, interp, objc, objv, 0,
	    NULL);
2611
2612
2613
2614
2615
2616
2617
2618

2619
2620
2621
2622
2623
2624
2625
2695
2696
2697
2698
2699
2700
2701

2702
2703
2704
2705
2706
2707
2708
2709







-
+







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

int
TclOOObjectCmdCore(
    Object *oPtr,		/* The object being invoked. */
    Tcl_Interp *interp,		/* The interpreter containing the object. */
    int objc,			/* How many arguments are being passed in. */
    Tcl_Size objc,		/* How many arguments are being passed in. */
    Tcl_Obj *const *objv,	/* The array of arguments. */
    int flags,			/* Whether this is an invocation through the
				 * public or the private command interface. */
    Class *startCls)		/* Where to start in the call chain, or NULL
				 * if we are to start at the front with
				 * filters and the object's methods (which is
				 * the normal case). */
2644
2645
2646
2647
2648
2649
2650
2651

2652
2653
2654
2655
2656
2657
2658
2728
2729
2730
2731
2732
2733
2734

2735
2736
2737
2738
2739
2740
2741
2742







-
+








    /*
     * Determine if we're in a context that can see the extra, private methods
     * in this class.
     */

    if (framePtr->isProcCallFrame & FRAME_IS_METHOD) {
	CallContext *callerContextPtr = (CallContext *)framePtr->clientData;
	CallContext *callerContextPtr = (CallContext *) framePtr->clientData;
	Method *callerMethodPtr =
		callerContextPtr->callPtr->chain[callerContextPtr->index].mPtr;

	if (callerMethodPtr->declaringObjectPtr) {
	    callerObjPtr = callerMethodPtr->declaringObjectPtr;
	}
	if (callerMethodPtr->declaringClassPtr) {
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
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







-
+
















-
+












-
-
+










-
+

-
+
















-
+








-
+







		callerClsPtr, methodNamePtr);
	TclDecrRefCount(mappedMethodName);
	if (contextPtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "impossible to invoke method \"%s\": no defined method or"
		    " unknown method", TclGetString(methodNamePtr)));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD_MAPPED",
		    TclGetString(methodNamePtr), NULL);
		    TclGetString(methodNamePtr), (char *)NULL);
	    return TCL_ERROR;
	}
    } else {
	/*
	 * Get the call chain.
	 */

    noMapping:
	contextPtr = TclOOGetCallContext(oPtr, methodNamePtr,
		flags | (oPtr->flags & FILTER_HANDLING), callerObjPtr,
		callerClsPtr, NULL);
	if (contextPtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "impossible to invoke method \"%s\": no defined method or"
		    " unknown method", TclGetString(methodNamePtr)));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
		    TclGetString(methodNamePtr), NULL);
		    TclGetString(methodNamePtr), (char *)NULL);
	    return TCL_ERROR;
	}
    }

    /*
     * Check to see if we need to apply magical tricks to start part way
     * through the call chain.
     */

    if (startCls != NULL) {
	for (; contextPtr->index < contextPtr->callPtr->numChain;
		contextPtr->index++) {
	    struct MInvoke *miPtr =
		    &contextPtr->callPtr->chain[contextPtr->index];
	    MInvoke *miPtr = &contextPtr->callPtr->chain[contextPtr->index];

	    if (miPtr->isFilter) {
		continue;
	    }
	    if (miPtr->mPtr->declaringClassPtr == startCls) {
		break;
	    }
	}
	if (contextPtr->index >= contextPtr->callPtr->numChain) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "no valid method implementation", -1));
		    "no valid method implementation", TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
		    TclGetString(methodNamePtr), NULL);
		    TclGetString(methodNamePtr), (char *)NULL);
	    TclOODeleteContext(contextPtr);
	    return TCL_ERROR;
	}
    }

    /*
     * Invoke the call chain, locking the object structure against deletion
     * for the duration.
     */

    TclNRAddCallback(interp, FinalizeObjectCall, contextPtr, NULL,NULL,NULL);
    return TclOOInvokeContext(contextPtr, interp, objc, objv);
}

static int
FinalizeObjectCall(
    ClientData data[],
    void *data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    /*
     * Dispose of the call chain, which drops the lock on the object's
     * structure.
     */

    TclOODeleteContext((CallContext *)data[0]);
    TclOODeleteContext((CallContext *) data[0]);
    return result;
}

/*
 * ----------------------------------------------------------------------
 *
 * Tcl_ObjectContextInvokeNext, TclNRObjectContextInvokeNext, FinalizeNext --
2783
2784
2785
2786
2787
2788
2789
2790

2791
2792

2793
2794
2795
2796


2797
2798
2799
2800
2801
2802
2803
2866
2867
2868
2869
2870
2871
2872

2873
2874

2875
2876
2877


2878
2879
2880
2881
2882
2883
2884
2885
2886







-
+

-
+


-
-
+
+







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

int
Tcl_ObjectContextInvokeNext(
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Size objc,
    Tcl_Obj *const *objv,
    int skip)
    Tcl_Size skip)
{
    CallContext *contextPtr = (CallContext *) context;
    int savedIndex = contextPtr->index;
    int savedSkip = contextPtr->skip;
    size_t savedIndex = contextPtr->index;
    size_t savedSkip = contextPtr->skip;
    int result;

    if (contextPtr->index + 1 >= contextPtr->callPtr->numChain) {
	/*
	 * We're at the end of the chain; generate an error message unless the
	 * interpreter is being torn down, in which case we might be getting
	 * here because of methods/destructors doing a [next] (or equivalent)
2816
2817
2818
2819
2820
2821
2822
2823

2824
2825
2826
2827
2828
2829
2830
2899
2900
2901
2902
2903
2904
2905

2906
2907
2908
2909
2910
2911
2912
2913







-
+







	    methodType = "destructor";
	} else {
	    methodType = "method";
	}

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"no next %s implementation", methodType));
	Tcl_SetErrorCode(interp, "TCL", "OO", "NOTHING_NEXT", NULL);
	Tcl_SetErrorCode(interp, "TCL", "OO", "NOTHING_NEXT", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Advance to the next method implementation in the chain in the method
     * call context while we process the body. However, need to adjust the
     * argument-skip control because we're guaranteed to have a single prefix
2855
2856
2857
2858
2859
2860
2861
2862

2863
2864

2865
2866
2867
2868
2869
2870
2871
2938
2939
2940
2941
2942
2943
2944

2945
2946

2947
2948
2949
2950
2951
2952
2953
2954







-
+

-
+







    return result;
}

int
TclNRObjectContextInvokeNext(
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Size objc,
    Tcl_Obj *const *objv,
    int skip)
    Tcl_Size skip)
{
    CallContext *contextPtr = (CallContext *) context;

    if (contextPtr->index + 1 >= contextPtr->callPtr->numChain) {
	/*
	 * We're at the end of the chain; generate an error message unless the
	 * interpreter is being torn down, in which case we might be getting
2885
2886
2887
2888
2889
2890
2891
2892

2893
2894
2895
2896
2897
2898
2899
2968
2969
2970
2971
2972
2973
2974

2975
2976
2977
2978
2979
2980
2981
2982







-
+







	    methodType = "destructor";
	} else {
	    methodType = "method";
	}

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"no next %s implementation", methodType));
	Tcl_SetErrorCode(interp, "TCL", "OO", "NOTHING_NEXT", NULL);
	Tcl_SetErrorCode(interp, "TCL", "OO", "NOTHING_NEXT", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Advance to the next method implementation in the chain in the method
     * call context while we process the body. However, need to adjust the
     * argument-skip control because we're guaranteed to have a single prefix
2913
2914
2915
2916
2917
2918
2919
2920

2921
2922
2923
2924

2925
2926
2927
2928
2929
2930
2931
2996
2997
2998
2999
3000
3001
3002

3003
3004
3005
3006

3007
3008
3009
3010
3011
3012
3013
3014







-
+



-
+







     */

    return TclOOInvokeContext(contextPtr, interp, objc, objv);
}

static int
FinalizeNext(
    ClientData data[],
    void *data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    CallContext *contextPtr = (CallContext *)data[0];
    CallContext *contextPtr = (CallContext *) data[0];

    /*
     * Restore the call chain context index as we've finished the inner invoke
     * and want to operate in the outer context again.
     */

    contextPtr->index = PTR2INT(data[1]);
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
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







-
+





-
+



















-
+







    }
    if (cmdPtr->objProc != TclOOPublicObjectCmd) {
	cmdPtr = (Command *) TclGetOriginalCommand((Tcl_Command) cmdPtr);
	if (cmdPtr == NULL || cmdPtr->objProc != TclOOPublicObjectCmd) {
	    goto notAnObject;
	}
    }
    return (Tcl_Object)cmdPtr->objClientData;
    return (Tcl_Object) cmdPtr->objClientData;

  notAnObject:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "%s does not refer to an object", TclGetString(objPtr)));
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "OBJECT", TclGetString(objPtr),
	    NULL);
	    (char *)NULL);
    return NULL;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOIsReachable --
 *
 *	Utility function that tests whether a class is a subclass (whether
 *	directly or indirectly) of another class.
 *
 * ----------------------------------------------------------------------
 */

int
TclOOIsReachable(
    Class *targetPtr,
    Class *startPtr)
{
    int i;
    Tcl_Size i;
    Class *superPtr;

  tailRecurse:
    if (startPtr == targetPtr) {
	return 1;
    }
    if (startPtr->superclasses.num == 1 && startPtr->mixins.num == 0) {
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
3134
3135
3136
3137
3138
3139




















3140
3141
3142
3143
3144
3145
3146
3147
3157
3158
3159
3160
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

3199
3200
3201
3202
3203
3204
3205

3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250







-
+


-
+



-
+






-
+






-
+






-
+






-
+






-
+
















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








    return contextPtr->callPtr->chain[contextPtr->index].isFilter;
}

Tcl_Object
Tcl_ObjectContextObject(
    Tcl_ObjectContext context)
{
    return (Tcl_Object) ((CallContext *)context)->oPtr;
    return (Tcl_Object) ((CallContext *) context)->oPtr;
}

int
Tcl_Size
Tcl_ObjectContextSkippedArgs(
    Tcl_ObjectContext context)
{
    return ((CallContext *)context)->skip;
    return ((CallContext *) context)->skip;
}

Tcl_Namespace *
Tcl_GetObjectNamespace(
    Tcl_Object object)
{
    return ((Object *)object)->namespacePtr;
    return ((Object *) object)->namespacePtr;
}

Tcl_Command
Tcl_GetObjectCommand(
    Tcl_Object object)
{
    return ((Object *)object)->command;
    return ((Object *) object)->command;
}

Tcl_Class
Tcl_GetObjectAsClass(
    Tcl_Object object)
{
    return (Tcl_Class) ((Object *)object)->classPtr;
    return (Tcl_Class) ((Object *) object)->classPtr;
}

int
Tcl_ObjectDeleted(
    Tcl_Object object)
{
    return ((Object *)object)->command == NULL;
    return ((Object *) object)->command == NULL;
}

Tcl_Object
Tcl_GetClassAsObject(
    Tcl_Class clazz)
{
    return (Tcl_Object) ((Class *)clazz)->thisPtr;
    return (Tcl_Object) ((Class *) clazz)->thisPtr;
}

Tcl_ObjectMapMethodNameProc *
Tcl_ObjectGetMethodNameMapper(
    Tcl_Object object)
{
    return ((Object *) object)->mapMethodNameProc;
}

void
Tcl_ObjectSetMethodNameMapper(
    Tcl_Object object,
    Tcl_ObjectMapMethodNameProc *mapMethodNameProc)
{
    ((Object *) object)->mapMethodNameProc = mapMethodNameProc;
}

Tcl_Class
Tcl_GetClassOfObject(
    Tcl_Object object)
{
    return (Tcl_Class) ((Object *) object)->selfCls;
}

Tcl_Obj *
Tcl_GetObjectClassName(
    Tcl_Interp *interp,
    Tcl_Object object)
{
    Tcl_Object classObj = (Tcl_Object) (((Object *) object)->selfCls)->thisPtr;

    if (classObj == NULL) {
	return NULL;
    }
    return Tcl_GetObjectName(interp, classObj);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclOO.decls.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







# tclOO.decls --
#
#	This file contains the declarations for all supported public functions
#	that are exported by the TclOO package that is embedded within the Tcl
#	library via the stubs table.  This file is used to generate the
#	tclOODecls.h, tclOOIntDecls.h and tclOOStubInit.c files.
#
# Copyright (c) 2008-2013 by Donal K. Fellows.
# Copyright © 2008-2013 Donal K. Fellows.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

library tclOO

######################################################################
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
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







-
-
+
+














-
+



















-
-
+
+







declare 12 {
    Tcl_Method Tcl_NewMethod(Tcl_Interp *interp, Tcl_Class cls,
	    Tcl_Obj *nameObj, int flags, const Tcl_MethodType *typePtr,
	    void *clientData)
}
declare 13 {
    Tcl_Object Tcl_NewObjectInstance(Tcl_Interp *interp, Tcl_Class cls,
	    const char *nameStr, const char *nsNameStr, int objc,
	    Tcl_Obj *const *objv, int skip)
	    const char *nameStr, const char *nsNameStr, Tcl_Size objc,
	    Tcl_Obj *const *objv, Tcl_Size skip)
}
declare 14 {
    int Tcl_ObjectDeleted(Tcl_Object object)
}
declare 15 {
    int Tcl_ObjectContextIsFiltering(Tcl_ObjectContext context)
}
declare 16 {
    Tcl_Method Tcl_ObjectContextMethod(Tcl_ObjectContext context)
}
declare 17 {
    Tcl_Object Tcl_ObjectContextObject(Tcl_ObjectContext context)
}
declare 18 {
    int Tcl_ObjectContextSkippedArgs(Tcl_ObjectContext context)
    Tcl_Size Tcl_ObjectContextSkippedArgs(Tcl_ObjectContext context)
}
declare 19 {
    void *Tcl_ClassGetMetadata(Tcl_Class clazz,
	    const Tcl_ObjectMetadataType *typePtr)
}
declare 20 {
    void Tcl_ClassSetMetadata(Tcl_Class clazz,
	    const Tcl_ObjectMetadataType *typePtr, void *metadata)
}
declare 21 {
    void *Tcl_ObjectGetMetadata(Tcl_Object object,
	    const Tcl_ObjectMetadataType *typePtr)
}
declare 22 {
    void Tcl_ObjectSetMetadata(Tcl_Object object,
	    const Tcl_ObjectMetadataType *typePtr, void *metadata)
}
declare 23 {
    int Tcl_ObjectContextInvokeNext(Tcl_Interp *interp,
	    Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv,
	    int skip)
	    Tcl_ObjectContext context, Tcl_Size objc, Tcl_Obj *const *objv,
	    Tcl_Size skip)
}
declare 24 {
    Tcl_ObjectMapMethodNameProc *Tcl_ObjectGetMethodNameMapper(
	    Tcl_Object object)
}
declare 25 {
    void Tcl_ObjectSetMethodNameMapper(Tcl_Object object,
125
126
127
128
129
130
131




















132
133
134
135
136
137
138
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







}
declare 28 {
    Tcl_Obj *Tcl_GetObjectName(Tcl_Interp *interp, Tcl_Object object)
}
declare 29 {
    int Tcl_MethodIsPrivate(Tcl_Method method)
}
declare 30 {
    Tcl_Class Tcl_GetClassOfObject(Tcl_Object object)
}
declare 31 {
    Tcl_Obj *Tcl_GetObjectClassName(Tcl_Interp *interp, Tcl_Object object)
}
declare 32 {
    int Tcl_MethodIsType2(Tcl_Method method, const Tcl_MethodType2 *typePtr,
	    void **clientDataPtr)
}
declare 33 {
    Tcl_Method Tcl_NewInstanceMethod2(Tcl_Interp *interp, Tcl_Object object,
	    Tcl_Obj *nameObj, int flags, const Tcl_MethodType2 *typePtr,
	    void *clientData)
}
declare 34 {
    Tcl_Method Tcl_NewMethod2(Tcl_Interp *interp, Tcl_Class cls,
	    Tcl_Obj *nameObj, int flags, const Tcl_MethodType2 *typePtr,
	    void *clientData)
}

######################################################################
# Private API, exposed to support advanced OO systems that plug in on top of
# TclOO; not intended for general use and does not have any commitment to
# long-term support.
#

160
161
162
163
164
165
166
167

168
169
170
171
172
173
174
180
181
182
183
184
185
186

187
188
189
190
191
192
193
194







-
+







}
declare 4 {
    Method *TclOONewProcMethod(Tcl_Interp *interp, Class *clsPtr,
	    int flags, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj,
	    ProcedureMethod **pmPtrPtr)
}
declare 5 {
    int TclOOObjectCmdCore(Object *oPtr, Tcl_Interp *interp, int objc,
    int TclOOObjectCmdCore(Object *oPtr, Tcl_Interp *interp, Tcl_Size objc,
	    Tcl_Obj *const *objv, int publicOnly, Class *startCls)
}
declare 6 {
    int TclOOIsReachable(Class *targetPtr, Class *startPtr)
}
declare 7 {
    Method *TclOONewForwardMethod(Tcl_Interp *interp, Class *clsPtr,
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
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







-
+



-
+




-
+


-
+




-
+







	    TclOO_PreCallProc *preCallPtr, TclOO_PostCallProc *postCallPtr,
	    ProcErrorProc *errProc, void *clientData, Tcl_Obj *nameObj,
	    Tcl_Obj *argsObj, Tcl_Obj *bodyObj, int flags,
	    void **internalTokenPtr)
}
declare 11 {
    int TclOOInvokeObject(Tcl_Interp *interp, Tcl_Object object,
	    Tcl_Class startCls, int publicPrivate, int objc,
	    Tcl_Class startCls, int publicPrivate, Tcl_Size objc,
	    Tcl_Obj *const *objv)
}
declare 12 {
    void TclOOObjectSetFilters(Object *oPtr, int numFilters,
    void TclOOObjectSetFilters(Object *oPtr, Tcl_Size numFilters,
	    Tcl_Obj *const *filters)
}
declare 13 {
    void TclOOClassSetFilters(Tcl_Interp *interp, Class *classPtr,
	    int numFilters, Tcl_Obj *const *filters)
	    Tcl_Size numFilters, Tcl_Obj *const *filters)
}
declare 14 {
    void TclOOObjectSetMixins(Object *oPtr, int numMixins,
    void TclOOObjectSetMixins(Object *oPtr, Tcl_Size numMixins,
	    Class *const *mixins)
}
declare 15 {
    void TclOOClassSetMixins(Tcl_Interp *interp, Class *classPtr,
	    int numMixins, Class *const *mixins)
	    Tcl_Size numMixins, Class *const *mixins)
}

return

# Local Variables:
# mode: tcl
# End:

Changes to generic/tclOO.h.

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
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







-
-
+
+














-
+







 *
 * tests/oo.test
 * tests/ooNext2.test
 * unix/tclooConfig.sh
 * win/tclooConfig.sh
 */

#define TCLOO_VERSION "1.2.0"
#define TCLOO_PATCHLEVEL TCLOO_VERSION
#define TCLOO_VERSION "1.3"
#define TCLOO_PATCHLEVEL TCLOO_VERSION ".0"

#include "tcl.h"

/*
 * For C++ compilers, use extern "C"
 */

#ifdef __cplusplus
extern "C" {
#endif

extern const char *TclOOInitializeStubs(
	Tcl_Interp *, const char *version);
#define Tcl_OOInitStubs(interp) \
    TclOOInitializeStubs((interp), TCLOO_VERSION)
    TclOOInitializeStubs((interp), TCLOO_PATCHLEVEL)
#ifndef USE_TCL_STUBS
#   define TclOOInitializeStubs(interp, version) (TCLOO_PATCHLEVEL)
#endif

/*
 * These are opaque types.
 */
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
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







+
+
+
+
+
+













-
+

-
+














+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
-
+
+
+
+
+





-
-
-
-
+
+
+
+
+







-
+


















+
+
+
-
+







 * Public datatypes for callbacks and structures used in the TIP#257 (OO)
 * implementation. These are used to implement custom types of method calls
 * and to allow the attachment of arbitrary data to objects and classes.
 */

typedef int (Tcl_MethodCallProc)(void *clientData, Tcl_Interp *interp,
	Tcl_ObjectContext objectContext, int objc, Tcl_Obj *const *objv);
#if TCL_MAJOR_VERSION > 8
typedef int (Tcl_MethodCallProc2)(void *clientData, Tcl_Interp *interp,
	Tcl_ObjectContext objectContext, Tcl_Size objc, Tcl_Obj *const *objv);
#else
#define Tcl_MethodCallProc2 Tcl_MethodCallProc
#endif
typedef void (Tcl_MethodDeleteProc)(void *clientData);
typedef int (Tcl_CloneProc)(Tcl_Interp *interp, void *oldClientData,
	void **newClientData);
typedef void (Tcl_ObjectMetadataDeleteProc)(void *clientData);
typedef int (Tcl_ObjectMapMethodNameProc)(Tcl_Interp *interp,
	Tcl_Object object, Tcl_Class *startClsPtr, Tcl_Obj *methodNameObj);

/*
 * The type of a method implementation. This describes how to call the method
 * implementation, how to delete it (when the object or class is deleted) and
 * how to create a clone of it (when the object or class is copied).
 */

typedef struct {
typedef struct Tcl_MethodType {
    int version;		/* Structure version field. Always to be equal
				 * to TCL_OO_METHOD_VERSION_CURRENT in
				 * to TCL_OO_METHOD_VERSION_(1|CURRENT) in
				 * declarations. */
    const char *name;		/* Name of this type of method, mostly for
				 * debugging purposes. */
    Tcl_MethodCallProc *callProc;
				/* How to invoke this method. */
    Tcl_MethodDeleteProc *deleteProc;
				/* How to delete this method's type-specific
				 * data, or NULL if the type-specific data
				 * does not need deleting. */
    Tcl_CloneProc *cloneProc;	/* How to copy this method's type-specific
				 * data, or NULL if the type-specific data can
				 * be copied directly. */
} Tcl_MethodType;

#if TCL_MAJOR_VERSION > 8
typedef struct Tcl_MethodType2 {
    int version;		/* Structure version field. Always to be equal
				 * to TCL_OO_METHOD_VERSION_2 in
				 * declarations. */
    const char *name;		/* Name of this type of method, mostly for
				 * debugging purposes. */
    Tcl_MethodCallProc2 *callProc;
				/* How to invoke this method. */
    Tcl_MethodDeleteProc *deleteProc;
				/* How to delete this method's type-specific
				 * data, or NULL if the type-specific data
				 * does not need deleting. */
    Tcl_CloneProc *cloneProc;	/* How to copy this method's type-specific
				 * data, or NULL if the type-specific data can
				 * be copied directly. */
} Tcl_MethodType2;
#else
#define Tcl_MethodType2 Tcl_MethodType
#endif

/*
 * The correct value for the version field of the Tcl_MethodType structure.
 * This allows new versions of the structure to be introduced without breaking
 * binary compatibility.
 */

#define TCL_OO_METHOD_VERSION_CURRENT 1
enum TclOOMethodVersion {
    TCL_OO_METHOD_VERSION_1 = 1,
    TCL_OO_METHOD_VERSION_2 = 2
};
#define TCL_OO_METHOD_VERSION_CURRENT TCL_OO_METHOD_VERSION_1

/*
 * Visibility constants for the flags parameter to Tcl_NewMethod and
 * Tcl_NewInstanceMethod.
 */

#define TCL_OO_METHOD_PUBLIC		1
#define TCL_OO_METHOD_UNEXPORTED	0
#define TCL_OO_METHOD_PRIVATE		0x20
enum TclOOMethodVisibilityFlags {
    TCL_OO_METHOD_PUBLIC = 1,
    TCL_OO_METHOD_UNEXPORTED = 0,
    TCL_OO_METHOD_PRIVATE = 0x20
};

/*
 * The type of some object (or class) metadata. This describes how to delete
 * the metadata (when the object or class is deleted) and how to create a
 * clone of it (when the object or class is copied).
 */

typedef struct {
typedef struct Tcl_ObjectMetadataType {
    int version;		/* Structure version field. Always to be equal
				 * to TCL_OO_METADATA_VERSION_CURRENT in
				 * declarations. */
    const char *name;
    Tcl_ObjectMetadataDeleteProc *deleteProc;
				/* How to delete the metadata. This must not
				 * be NULL. */
    Tcl_CloneProc *cloneProc;	/* How to copy the metadata, or NULL if the
				 * type-specific data can be copied
				 * directly. */
} Tcl_ObjectMetadataType;

/*
 * The correct value for the version field of the Tcl_ObjectMetadataType
 * structure. This allows new versions of the structure to be introduced
 * without breaking binary compatibility.
 */

enum TclOOMetadataVersion {
    TCL_OO_METADATA_VERSION_1 = 1
};
#define TCL_OO_METADATA_VERSION_CURRENT 1
#define TCL_OO_METADATA_VERSION_CURRENT TCL_OO_METADATA_VERSION_1

/*
 * Include all the public API, generated from tclOO.decls.
 */

#include "tclOODecls.h"

Changes to generic/tclOOBasic.c.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
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






-
+










+







/*
 * tclOOBasic.c --
 *
 *	This file contains implementations of the "simple" commands and
 *	methods from the object-system core.
 *
 * Copyright (c) 2005-2013 by Donal K. Fellows
 * Copyright © 2005-2013 Donal K. Fellows
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#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;
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
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







-
+



-
+




















-
+








-
-
+
+
+


-
-





+
+
+


+
-
+
-

-
-
+
+
+
+
+
+
+
+
+
+





-
+


-
+







{
    TclNRAddCallback(interp, FinalizeConstruction, NULL, NULL, NULL, NULL);
    return (Tcl_Object *) &(TOP_CB(interp)->data[0]);
}

static int
FinalizeConstruction(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Object *oPtr = (Object *)data[0];
    Object *oPtr = (Object *) data[0];

    if (result != TCL_OK) {
	return result;
    }
    Tcl_SetObjResult(interp, TclOOObjectName(interp, oPtr));
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOO_Class_Constructor --
 *
 *	Implementation for oo::class constructor.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Class_Constructor(
    TCL_UNUSED(ClientData),
    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;

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

    /*
     * 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",
    nameObj = Tcl_NewStringObj(oPtr->namespacePtr->fullName, -1);
	    oPtr->namespacePtr->fullName);
    Tcl_AppendToObj(nameObj, ":: oo ::delegate", -1);
    Tcl_NewObjectInstance(interp, (Tcl_Class) oPtr->fPtr->classCls,
	    TclGetString(nameObj), NULL, -1, NULL, -1);
    Tcl_DecrRefCount(nameObj);
	    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 **)Tcl_Alloc(3 * sizeof(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];
    invoke[2] = objv[objc - 1];

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

    Tcl_IncrRefCount(invoke[0]);
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
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







-
+



-
-
+
+






-
+







-
+



















-
+








-
+











-
+







-
+




-
+



-
-
+
+







     */

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

static int
DecrRefsPostClassConstructor(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj **invoke = (Tcl_Obj **)data[0];
    Object *oPtr = (Object *)data[1];
    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] = Tcl_NewStringObj("::oo::MixinClassDelegates", -1);
    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]);
    Tcl_Free(invoke);
    TclStackFree(interp, invoke);
    if (code != TCL_OK) {
	Tcl_DiscardInterpState(saved);
	return code;
    }
    return Tcl_RestoreInterpState(interp, saved);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOO_Class_Create --
 *
 *	Implementation for oo::class->create method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Class_Create(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Interpreter in which to create the object;
				 * also used for error reporting. */
    Tcl_ObjectContext context,	/* The object/call context. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* The actual arguments. */
{
    Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
    const char *objName;
    size_t len;
    Tcl_Size len;

    /*
     * Sanity check; should not be possible to invoke this method on a
     * non-class.
     */

    if (oPtr->classPtr == NULL) {
	Tcl_Obj *cmdnameObj = TclOOObjectName(interp, oPtr);

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"object \"%s\" is not a class", TclGetString(cmdnameObj)));
	Tcl_SetErrorCode(interp, "TCL", "OO", "INSTANTIATE_NONCLASS", NULL);
	Tcl_SetErrorCode(interp, "TCL", "OO", "INSTANTIATE_NONCLASS", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Check we have the right number of (sensible) arguments.
     */

    if (objc - Tcl_ObjectContextSkippedArgs(context) < 1) {
    if (objc < 1 + Tcl_ObjectContextSkippedArgs(context)) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"objectName ?arg ...?");
	return TCL_ERROR;
    }
    objName = TclGetStringFromObj(
    objName = Tcl_GetStringFromObj(
	    objv[Tcl_ObjectContextSkippedArgs(context)], &len);
    if (len == 0) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"object name must not be empty", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "EMPTY_NAME", NULL);
		"object name must not be empty", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "EMPTY_NAME", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Make the object and return its name.
     */

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
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







-
+








-
+











-
+







-
+




-
+



-
-
+
+


-
-
+
+


-
-
+
+









-
+















-
+


















-
+







 *	Implementation for oo::class->createWithNamespace method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Class_CreateNs(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Interpreter in which to create the object;
				 * also used for error reporting. */
    Tcl_ObjectContext context,	/* The object/call context. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* The actual arguments. */
{
    Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
    const char *objName, *nsName;
    size_t len;
    Tcl_Size len;

    /*
     * Sanity check; should not be possible to invoke this method on a
     * non-class.
     */

    if (oPtr->classPtr == NULL) {
	Tcl_Obj *cmdnameObj = TclOOObjectName(interp, oPtr);

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"object \"%s\" is not a class", TclGetString(cmdnameObj)));
	Tcl_SetErrorCode(interp, "TCL", "OO", "INSTANTIATE_NONCLASS", NULL);
	Tcl_SetErrorCode(interp, "TCL", "OO", "INSTANTIATE_NONCLASS", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Check we have the right number of (sensible) arguments.
     */

    if (objc - Tcl_ObjectContextSkippedArgs(context) < 2) {
    if (objc + 1 < Tcl_ObjectContextSkippedArgs(context) + 3) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"objectName namespaceName ?arg ...?");
	return TCL_ERROR;
    }
    objName = TclGetStringFromObj(
    objName = Tcl_GetStringFromObj(
	    objv[Tcl_ObjectContextSkippedArgs(context)], &len);
    if (len == 0) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"object name must not be empty", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "EMPTY_NAME", NULL);
		"object name must not be empty", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "EMPTY_NAME", (char *)NULL);
	return TCL_ERROR;
    }
    nsName = TclGetStringFromObj(
	    objv[Tcl_ObjectContextSkippedArgs(context)+1], &len);
    nsName = Tcl_GetStringFromObj(
	    objv[Tcl_ObjectContextSkippedArgs(context) + 1], &len);
    if (len == 0) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"namespace name must not be empty", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "EMPTY_NAME", NULL);
		"namespace name must not be empty", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "EMPTY_NAME", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Make the object and return its name.
     */

    return TclNRNewObjectInstance(interp, (Tcl_Class) oPtr->classPtr,
	    objName, nsName, objc, objv,
	    Tcl_ObjectContextSkippedArgs(context)+2,
	    Tcl_ObjectContextSkippedArgs(context) + 2,
	    AddConstructionFinalizer(interp));
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOO_Class_New --
 *
 *	Implementation for oo::class->new method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Class_New(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Interpreter in which to create the object;
				 * also used for error reporting. */
    Tcl_ObjectContext context,	/* The object/call context. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* The actual arguments. */
{
    Object *oPtr = (Object *) Tcl_ObjectContextObject(context);

    /*
     * Sanity check; should not be possible to invoke this method on a
     * non-class.
     */

    if (oPtr->classPtr == NULL) {
	Tcl_Obj *cmdnameObj = TclOOObjectName(interp, oPtr);

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"object \"%s\" is not a class", TclGetString(cmdnameObj)));
	Tcl_SetErrorCode(interp, "TCL", "OO", "INSTANTIATE_NONCLASS", NULL);
	Tcl_SetErrorCode(interp, "TCL", "OO", "INSTANTIATE_NONCLASS", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Make the object and return its name.
     */

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
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







-
+









-
+







 *	Implementation for oo::object->destroy method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Object_Destroy(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Interpreter in which to create the object;
				 * also used for error reporting. */
    Tcl_ObjectContext context,	/* The object/call context. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* The actual arguments. */
{
    Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
    CallContext *contextPtr;

    if (objc != Tcl_ObjectContextSkippedArgs(context)) {
    if (objc != (int) Tcl_ObjectContextSkippedArgs(context)) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		NULL);
	return TCL_ERROR;
    }
    if (!(oPtr->flags & DESTRUCTOR_CALLED)) {
	oPtr->flags |= DESTRUCTOR_CALLED;
	contextPtr = TclOOGetCallContext(oPtr, NULL, DESTRUCTOR, NULL, NULL,
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
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
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481

482
483
484
485
486

487
488
489
490
491
492
493
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
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
467
468
469
470
471
472
473

474
475
476
477
478
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







-
+



-
+




















-
+








-
+




-
+










-
+
+
















-
+


















-
+




-
+







	Tcl_DeleteCommandFromToken(interp, oPtr->command);
    }
    return TCL_OK;
}

static int
AfterNRDestructor(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    CallContext *contextPtr = (CallContext *)data[0];
    CallContext *contextPtr = (CallContext *) data[0];

    if (contextPtr->oPtr->command) {
	Tcl_DeleteCommandFromToken(interp, contextPtr->oPtr->command);
    }
    TclOODeleteContext(contextPtr);
    return result;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOO_Object_Eval --
 *
 *	Implementation for oo::object->eval method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Object_Eval(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Interpreter in which to create the object;
				 * also used for error reporting. */
    Tcl_ObjectContext context,	/* The object/call context. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* The actual arguments. */
{
    CallContext *contextPtr = (CallContext *) context;
    Tcl_Object object = Tcl_ObjectContextObject(context);
    const int skip = Tcl_ObjectContextSkippedArgs(context);
    size_t skip = Tcl_ObjectContextSkippedArgs(context);
    CallFrame *framePtr, **framePtrPtr = &framePtr;
    Tcl_Obj *scriptPtr;
    CmdFrame *invoker;

    if (objc-1 < skip) {
    if ((size_t) objc < skip + 1) {
	Tcl_WrongNumArgs(interp, skip, objv, "arg ?arg ...?");
	return TCL_ERROR;
    }

    /*
     * Make the object's namespace the current namespace and evaluate the
     * command(s).
     */

    (void) TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr,
	    Tcl_GetObjectNamespace(object), 0);
	    Tcl_GetObjectNamespace(object), FRAME_IS_METHOD);
    framePtr->clientData = context;
    framePtr->objc = objc;
    framePtr->objv = objv;	/* Reference counts do not need to be
				 * incremented here. */

    if (!(contextPtr->callPtr->flags & PUBLIC_METHOD)) {
	object = NULL;		/* Now just for error mesage printing. */
    }

    /*
     * Work out what script we are actually going to evaluate.
     *
     * When there's more than one argument, we concatenate them together with
     * spaces between, then evaluate the result. Tcl_EvalObjEx will delete the
     * object when it decrements its refcount after eval'ing it.
     */

    if (objc != skip+1) {
    if ((size_t) objc != skip+1) {
	scriptPtr = Tcl_ConcatObj(objc-skip, objv+skip);
	invoker = NULL;
    } else {
	scriptPtr = objv[skip];
	invoker = ((Interp *) interp)->cmdFramePtr;
    }

    /*
     * Evaluate the script now, with FinalizeEval to do the processing after
     * the script completes.
     */

    TclNRAddCallback(interp, FinalizeEval, object, NULL, NULL, NULL);
    return TclNREvalObjEx(interp, scriptPtr, 0, invoker, skip);
}

static int
FinalizeEval(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    if (result == TCL_ERROR) {
	Object *oPtr = (Object *)data[0];
	Object *oPtr = (Object *) data[0];
	const char *namePtr;

	if (oPtr) {
	    namePtr = TclGetString(TclOOObjectName(interp, oPtr));
	} else {
	    namePtr = "my";
	}
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
558
559
560
561
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
558
559
560
561
562
563
564
565
566

567
568
569
570
571
572
573
574







-
+











+
-
+









-
+










-
+







 *	just creates a suitable error message.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Object_Unknown(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Interpreter in which to create the object;
				 * also used for error reporting. */
    Tcl_ObjectContext context,	/* The object/call context. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* The actual arguments. */
{
    CallContext *contextPtr = (CallContext *) context;
    Object *callerObj = NULL;
    Class *callerCls = NULL;
    Object *oPtr = contextPtr->oPtr;
    const char **methodNames;
    int numMethodNames, i;
    int numMethodNames, i, skip = Tcl_ObjectContextSkippedArgs(context);
    size_t skip = Tcl_ObjectContextSkippedArgs(context);
    CallFrame *framePtr = ((Interp *) interp)->varFramePtr;
    Tcl_Obj *errorMsg;

    /*
     * If no method name, generate an error asking for a method name. (Only by
     * overriding *this* method can an object handle the absence of a method
     * name without an error).
     */

    if (objc < skip+1) {
    if ((size_t) objc < skip + 1) {
	Tcl_WrongNumArgs(interp, skip, objv, "method ?arg ...?");
	return TCL_ERROR;
    }

    /*
     * Determine if the calling context should know about extra private
     * methods, and if so, which.
     */

    if (framePtr->isProcCallFrame & FRAME_IS_METHOD) {
	CallContext *callerContext = (CallContext *)framePtr->clientData;
	CallContext *callerContext = (CallContext *) framePtr->clientData;
	Method *mPtr = callerContext->callPtr->chain[
		    callerContext->index].mPtr;

	if (mPtr->declaringObjectPtr) {
	    if (oPtr == mPtr->declaringObjectPtr) {
		callerObj = mPtr->declaringObjectPtr;
	    }
585
586
587
588
589
590
591
592

593
594
595
596
597
598
599
600

601
602

603
604
605

606
607
608


609
610
611

612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627

628
629
630
631
632
633
634
635
636
637

638
639

640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655

656
657
658
659
660
661
662
663
664
665
666
667
668

669
670
671
672
673
674
675
598
599
600
601
602
603
604

605
606
607
608
609
610
611
612

613
614

615
616
617

618
619


620
621
622
623

624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639

640
641
642
643
644
645
646
647
648
649

650
651

652
653
654
655
656
657
658
659
660
661
662
663
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







-
+







-
+

-
+


-
+

-
-
+
+


-
+















-
+









-
+

-
+















-
+












-
+







	    piece = "visible methods";
	} else {
	    piece = "methods";
	}
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"object \"%s\" has no %s", TclGetString(tmpBuf), piece));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
		TclGetString(objv[skip]), NULL);
		TclGetString(objv[skip]), (char *)NULL);
	return TCL_ERROR;
    }

    errorMsg = Tcl_ObjPrintf("unknown method \"%s\": must be ",
	    TclGetString(objv[skip]));
    for (i=0 ; i<numMethodNames-1 ; i++) {
	if (i) {
	    Tcl_AppendToObj(errorMsg, ", ", -1);
	    Tcl_AppendToObj(errorMsg, ", ", TCL_AUTO_LENGTH);
	}
	Tcl_AppendToObj(errorMsg, methodNames[i], -1);
	Tcl_AppendToObj(errorMsg, methodNames[i], TCL_AUTO_LENGTH);
    }
    if (i) {
	Tcl_AppendToObj(errorMsg, " or ", -1);
	Tcl_AppendToObj(errorMsg, " or ", TCL_AUTO_LENGTH);
    }
    Tcl_AppendToObj(errorMsg, methodNames[i], -1);
    Tcl_Free((void *)methodNames);
    Tcl_AppendToObj(errorMsg, methodNames[i], TCL_AUTO_LENGTH);
    Tcl_Free((void *) methodNames);
    Tcl_SetObjResult(interp, errorMsg);
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
	    TclGetString(objv[skip]), NULL);
	    TclGetString(objv[skip]), (char *)NULL);
    return TCL_ERROR;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOO_Object_LinkVar --
 *
 *	Implementation of oo::object->variable method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Object_LinkVar(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Interpreter in which to create the object;
				 * also used for error reporting. */
    Tcl_ObjectContext context,	/* The object/call context. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* The actual arguments. */
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Object object = Tcl_ObjectContextObject(context);
    Namespace *savedNsPtr;
    int i;
    Tcl_Size i;

    if (objc-Tcl_ObjectContextSkippedArgs(context) < 0) {
    if (objc < Tcl_ObjectContextSkippedArgs(context)) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"?varName ...?");
	return TCL_ERROR;
    }

    /*
     * A sanity check. Shouldn't ever happen. (This is all that remains of a
     * more complex check inherited from [global] after we have applied the
     * fix for [Bug 2903811]; note that the fix involved *removing* code.)
     */

    if (iPtr->varFramePtr == NULL) {
	return TCL_OK;
    }

    for (i=Tcl_ObjectContextSkippedArgs(context) ; i<objc ; i++) {
    for (i = Tcl_ObjectContextSkippedArgs(context) ; i < objc ; i++) {
	Var *varPtr, *aryPtr;
	const char *varName = TclGetString(objv[i]);

	/*
	 * The variable name must not contain a '::' since that's illegal in
	 * local names.
	 */

	if (strstr(varName, "::") != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "variable name \"%s\" illegal: must not contain namespace"
		    " separator", varName));
	    Tcl_SetErrorCode(interp, "TCL", "UPVAR", "INVERTED", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "UPVAR", "INVERTED", (char *)NULL);
	    return TCL_ERROR;
	}

	/*
	 * Switch to the object's namespace for the duration of this call.
	 * Like this, the variable is looked up in the namespace of the
	 * object, and not in the namespace of the caller. Otherwise this
690
691
692
693
694
695
696
697

698
699
700
701
702
703
704
703
704
705
706
707
708
709

710
711
712
713
714
715
716
717







-
+







	    /*
	     * Variable cannot be an element in an array. If aryPtr is not
	     * NULL, it is an element, so throw up an error and return.
	     */

	    TclVarErrMsg(interp, varName, NULL, "define",
		    "name refers to an element in an array");
	    Tcl_SetErrorCode(interp, "TCL", "UPVAR", "LOCAL_ELEMENT", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "UPVAR", "LOCAL_ELEMENT", (char *)NULL);
	    return TCL_ERROR;
	}

	/*
	 * Arrange for the lifetime of the variable to be correctly managed.
	 * This is copied out of Tcl_VariableObjCmd...
	 */
713
714
715
716
717
718
719
720

721
722

723



724
725
726

727
728

729
730

731
732
733
734






735
736
737
738
739

740
741
742
743

744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759

760
761
762


763
764
765
766
767
768
769
770
771
772
773
774
775
776


777
778
779
780

781
782
783
784
785
786



787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808



809
810
811
812
813
814
815
816
817
818



819
820
821
822



823
824
825







































826
827













828
829
830
831
832
833
834

835
836

837
838
839
840
841
842

843
844

845
846
847

848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867

868
869
870
871
872
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
898
899
900
901
902
903

904
905
906
907
908
909
910
911
912

913
914
915
916
917
918
919
920
921
922
923
924
925
926

927
928
929

930
931
932
933
934
935
936
937
938
939
940
941
942
943

944
945
946
947

948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122


1123
1124
1125

1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138

1139
1140
1141
1142
1143
1144
1145
1146
1147
1148


1149
1150
1151


1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165

1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182

1183
1184

1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197

1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216


1217
1218
1219
1220
1221

1222
1223

1224
1225
1226
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
726
727
728
729
730
731
732

733
734

735
736
737
738
739
740
741

742


743


744




745
746
747
748
749
750
751




752




753




754
755
756
757
758
759
760
761
762
763
764

765
766


767
768
769
770
771
772
773
774
775
776
777
778
779
780


781
782
783
784
785

786
787
788
789



790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811



812
813
814
815
816
817
818
819
820
821



822
823
824
825
826


827
828
829
830


831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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

898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917

918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936

937
938
939

940
941
942
943
944
945
946
947
948
949
950
951
952
953

954
955
956
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
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

1116
1117
1118
1119

1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136

1137
1138
1139
1140
1141


1142
1143
1144
1145
1146
1147
1148
1149


1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170


1171
1172
1173
1174

1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187

1188
1189
1190
1191
1192
1193
1194
1195
1196


1197
1198
1199
1200

1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215

1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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







-
+

-
+

+
+
+


-
+
-
-
+
-
-
+
-
-
-
-
+
+
+
+
+
+

-
-
-
-
+
-
-
-
-
+
-
-
-
-











-
+

-
-
+
+












-
-
+
+



-
+



-
-
-
+
+
+



















-
-
-
+
+
+







-
-
-
+
+
+


-
-
+
+
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+







+

-
+
-
-
-
-
-
-
+
-
-
+
-

-
+



















-
+


















-
+


-
+













-
+








-
+













-
+


-
+













-
+



-
+










-
+









-
+



















-
-
+
+






-
+






-
+





-
+




-
+

-
+

-
+

















-
+











-
+




-












-
+



-
+
















-
+




-
-
+
+






-
-
+
+



















-
-
+
+


-
+












-
+








-
-
+
+


-
+
+













-
+
















-
+

-
+












-
+

















-
-
+
+




-
+

-
+


















-
+









-
+




















-
+








-
+







    }
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOO_Object_VarName --
 * TclOOLookupObjectVar --
 *
 *	Implementation of the oo::object->varname method.
 *	Look up a variable in an object. Tricky because of private variables.
 *
 * Returns:
 *	Handle to the variable if it can be found, or NULL if there's an error.
 *
 * ----------------------------------------------------------------------
 */

Tcl_Var
int
TclOO_Object_VarName(
TclOOLookupObjectVar(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Interpreter in which to create the object;
    Tcl_Interp *interp,
				 * also used for error reporting. */
    Tcl_ObjectContext context,	/* The object/call context. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* The actual arguments. */
    Tcl_Object object,		/* Object we're looking up within. */
    Tcl_Obj *varName,		/* User-visible name we're looking up. */
    Tcl_Var *aryPtr)		/* Where to write the handle to the array
				 * containing the element; if not an element,
				 * then the variable this points to is set to
				 * NULL. */
{
    Var *varPtr, *aryVar;
    Tcl_Obj *varNamePtr, *argPtr;
    CallFrame *framePtr = ((Interp *) interp)->varFramePtr;
    const char *arg;
    const char *arg = TclGetString(varName);

    if (Tcl_ObjectContextSkippedArgs(context)+1 != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"varName");
    Tcl_Obj *varNamePtr;
	return TCL_ERROR;
    }
    argPtr = objv[objc-1];
    arg = TclGetString(argPtr);

    /*
     * Convert the variable name to fully-qualified form if it wasn't already.
     * This has to be done prior to lookup because we can run into problems
     * with resolvers otherwise. [Bug 3603695]
     *
     * We still need to do the lookup; the variable could be linked to another
     * variable and we want the target's name.
     */

    if (arg[0] == ':' && arg[1] == ':') {
	varNamePtr = argPtr;
	varNamePtr = varName;
    } else {
	Tcl_Namespace *namespacePtr =
		Tcl_GetObjectNamespace(Tcl_ObjectContextObject(context));
	Tcl_Namespace *namespacePtr = Tcl_GetObjectNamespace(object);
	CallFrame *framePtr = ((Interp *) interp)->varFramePtr;

	/*
	 * Private method handling. [TIP 500]
	 *
	 * If we're in a context that can see some private methods of an
	 * object, we may need to precede a variable name with its prefix.
	 * This is a little tricky as we need to check through the inheritance
	 * hierarchy when the method was declared by a class to see if the
	 * current object is an instance of that class.
	 */

	if (framePtr->isProcCallFrame & FRAME_IS_METHOD) {
	    Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
	    CallContext *callerContext = (CallContext *)framePtr->clientData;
	    Object *oPtr = (Object *) object;
	    CallContext *callerContext = (CallContext *) framePtr->clientData;
	    Method *mPtr = callerContext->callPtr->chain[
		    callerContext->index].mPtr;
	    PrivateVariableMapping *pvPtr;
	    int i;
	    Tcl_Size i;

	    if (mPtr->declaringObjectPtr == oPtr) {
		FOREACH_STRUCT(pvPtr, oPtr->privateVariables) {
		    if (!strcmp(TclGetString(pvPtr->variableObj),
			    TclGetString(argPtr))) {
			argPtr = pvPtr->fullNameObj;
		    if (!TclStringCmp(pvPtr->variableObj, varName, 1, 0,
			    TCL_INDEX_NONE)) {
			varName = pvPtr->fullNameObj;
			break;
		    }
		}
	    } else if (mPtr->declaringClassPtr &&
		    mPtr->declaringClassPtr->privateVariables.num) {
		Class *clsPtr = mPtr->declaringClassPtr;
		int isInstance = TclOOIsReachable(clsPtr, oPtr->selfCls);
		Class *mixinCls;

		if (!isInstance) {
		    FOREACH(mixinCls, oPtr->mixins) {
			if (TclOOIsReachable(clsPtr, mixinCls)) {
			    isInstance = 1;
			    break;
			}
		    }
		}
		if (isInstance) {
		    FOREACH_STRUCT(pvPtr, clsPtr->privateVariables) {
			if (!strcmp(TclGetString(pvPtr->variableObj),
				TclGetString(argPtr))) {
			    argPtr = pvPtr->fullNameObj;
			if (!TclStringCmp(pvPtr->variableObj, varName, 1, 0,
				TCL_INDEX_NONE)) {
			    varName = pvPtr->fullNameObj;
			    break;
			}
		    }
		}
	    }
	}

	varNamePtr = Tcl_NewStringObj(namespacePtr->fullName, -1);
	Tcl_AppendToObj(varNamePtr, "::", 2);
	Tcl_AppendObjToObj(varNamePtr, argPtr);
	// The namespace isn't the global one; necessarily true for any object!
	varNamePtr = Tcl_ObjPrintf("%s::%s",
		namespacePtr->fullName, TclGetString(varName));
    }
    Tcl_IncrRefCount(varNamePtr);
    varPtr = TclObjLookupVar(interp, varNamePtr, NULL,
	    TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG, "refer to", 1, 1, &aryVar);
    Tcl_Var var = (Tcl_Var) TclObjLookupVar(interp, varNamePtr, NULL,
	    TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG, "refer to", 1, 1,
	    (Var **) aryPtr);
    Tcl_DecrRefCount(varNamePtr);
    if (varPtr == NULL) {
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", arg, NULL);
    if (var == NULL) {
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", arg, (void *) NULL);
    } else if (*aryPtr == NULL && TclIsVarArrayElement((Var *) var)) {
	/*
	 * If the varPtr points to an element of an array but we don't already
	 * have the array, find it now. Note that this can't be easily
	 * backported; the arrayPtr field is new in Tcl 9.0. [Bug 2da1cb0c80]
	 */
	*aryPtr = (Tcl_Var) TclVarParentArray(var);
    }

    return var;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOO_Object_VarName --
 *
 *	Implementation of the oo::object->varname method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Object_VarName(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Interpreter in which to create the object;
				 * also used for error reporting. */
    Tcl_ObjectContext context,	/* The object/call context. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* The actual arguments. */
{
    Tcl_Var varPtr, aryVar;
    Tcl_Obj *varNamePtr;

    if ((int) Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"varName");
	return TCL_ERROR;
    }

    varPtr = TclOOLookupObjectVar(interp, Tcl_ObjectContextObject(context),
	    objv[objc - 1], &aryVar);
    if (varPtr == NULL) {
	return TCL_ERROR;
    }

    /*
     * The variable reference must not disappear too soon. [Bug 74b6110204]
     */
    if (!TclIsVarArrayElement((Var *) varPtr)) {
	TclSetVarNamespaceVar((Var *) varPtr);
    }

    /*
     * Now that we've pinned down what variable we're really talking about
     * (including traversing variable links), convert back to a name.
     */

    TclNewObj(varNamePtr);

    if (aryVar != NULL) {
	Tcl_GetVariableFullName(interp, (Tcl_Var) aryVar, varNamePtr);
	Tcl_GetVariableFullName(interp, aryVar, varNamePtr);

	/*
	 * WARNING! This code pokes inside the implementation of hash tables!
	 */

	Tcl_AppendToObj(varNamePtr, "(", -1);
	Tcl_AppendPrintfToObj(varNamePtr, "(%s)", Tcl_GetString(
	Tcl_AppendObjToObj(varNamePtr, ((VarInHash *)
		varPtr)->entry.key.objPtr);
		VarHashGetKey(varPtr)));
	Tcl_AppendToObj(varNamePtr, ")", -1);
    } else {
	Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr, varNamePtr);
	Tcl_GetVariableFullName(interp, varPtr, varNamePtr);
    }
    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.
 *
 * ----------------------------------------------------------------------
 */

int
TclOONextObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Interp *iPtr = (Interp *) interp;
    CallFrame *framePtr = iPtr->varFramePtr;
    Tcl_ObjectContext context;

    /*
     * 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])));
	Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL);
	Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", (char *)NULL);
	return TCL_ERROR;
    }
    context = (Tcl_ObjectContext)framePtr->clientData;
    context = (Tcl_ObjectContext) framePtr->clientData;

    /*
     * Invoke the (advanced) method call context in the caller context. Note
     * that this is like [uplevel 1] and not [eval].
     */

    TclNRAddCallback(interp, NextRestoreFrame, framePtr, NULL,NULL,NULL);
    iPtr->varFramePtr = framePtr->callerVarPtr;
    return TclNRObjectContextInvokeNext(interp, context, objc, objv, 1);
}

int
TclOONextToObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Interp *iPtr = (Interp *) interp;
    CallFrame *framePtr = iPtr->varFramePtr;
    Class *classPtr;
    CallContext *contextPtr;
    int i;
    Tcl_Size i;
    Tcl_Object object;
    const char *methodType;

    /*
     * 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])));
	Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL);
	Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", (char *)NULL);
	return TCL_ERROR;
    }
    contextPtr = (CallContext *)framePtr->clientData;
    contextPtr = (CallContext *) framePtr->clientData;

    /*
     * Sanity check the arguments; we need the first one to refer to a class.
     */

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "class ?arg...?");
	return TCL_ERROR;
    }
    object = Tcl_GetObjectFromObj(interp, objv[1]);
    if (object == NULL) {
	return TCL_ERROR;
    }
    classPtr = ((Object *)object)->classPtr;
    classPtr = ((Object *) object)->classPtr;
    if (classPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"\"%s\" is not a class", TclGetString(objv[1])));
	Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_REQUIRED", NULL);
	Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_REQUIRED", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Search for an implementation of a method associated with the current
     * call on the call chain past the point where we currently are. Do not
     * allow jumping backwards!
     */

    for (i=contextPtr->index+1 ; i<contextPtr->callPtr->numChain ; i++) {
	struct MInvoke *miPtr = contextPtr->callPtr->chain + i;
	MInvoke *miPtr = &contextPtr->callPtr->chain[i];

	if (!miPtr->isFilter && miPtr->mPtr->declaringClassPtr == classPtr) {
	    /*
	     * Invoke the (advanced) method call context in the caller
	     * context. Note that this is like [uplevel 1] and not [eval].
	     */

	    TclNRAddCallback(interp, NextRestoreFrame, framePtr,
		    contextPtr, INT2PTR(contextPtr->index), NULL);
	    contextPtr->index = i-1;
	    contextPtr->index = i - 1;
	    iPtr->varFramePtr = framePtr->callerVarPtr;
	    return TclNRObjectContextInvokeNext(interp,
		    (Tcl_ObjectContext) contextPtr, objc, objv, 2);
	}
    }

    /*
     * Generate an appropriate error message, depending on whether the value
     * is on the chain but unreachable, or not on the chain at all.
     */

    if (contextPtr->callPtr->flags & CONSTRUCTOR) {
	methodType = "constructor";
    } else if (contextPtr->callPtr->flags & DESTRUCTOR) {
	methodType = "destructor";
    } else {
	methodType = "method";
    }

    for (i=contextPtr->index ; i>=0 ; i--) {
	struct MInvoke *miPtr = contextPtr->callPtr->chain + i;
    for (i=contextPtr->index ; i != TCL_INDEX_NONE ; i--) {
	MInvoke *miPtr = &contextPtr->callPtr->chain[i];

	if (!miPtr->isFilter && miPtr->mPtr->declaringClassPtr == classPtr) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "%s implementation by \"%s\" not reachable from here",
		    methodType, TclGetString(objv[1])));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_NOT_REACHABLE",
		    NULL);
		    (char *)NULL);
	    return TCL_ERROR;
	}
    }
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "%s has no non-filter implementation by \"%s\"",
	    methodType, TclGetString(objv[1])));
    Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_NOT_THERE", NULL);
    Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_NOT_THERE", (char *)NULL);
    return TCL_ERROR;
}

static int
NextRestoreFrame(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    CallContext *contextPtr = (CallContext *)data[1];
    CallContext *contextPtr = (CallContext *) data[1];

    iPtr->varFramePtr = (CallFrame *)data[0];
    iPtr->varFramePtr = (CallFrame *) data[0];
    if (contextPtr != NULL) {
	contextPtr->index = PTR2INT(data[2]);
	contextPtr->index = PTR2UINT(data[2]);
    }
    return result;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOSelfObjCmd --
 *
 *	Implementation of the [self] command, which provides introspection of
 *	the call context.
 *
 * ----------------------------------------------------------------------
 */

int
TclOOSelfObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    static const char *const subcmds[] = {
	"call", "caller", "class", "filter", "method", "namespace", "next",
	"object", "target", NULL
    };
    enum SelfCmds {
	SELF_CALL, SELF_CALLER, SELF_CLASS, SELF_FILTER, SELF_METHOD, SELF_NS,
	SELF_NEXT, SELF_OBJECT, SELF_TARGET
    };
    } index;
    Interp *iPtr = (Interp *) interp;
    CallFrame *framePtr = iPtr->varFramePtr;
    CallContext *contextPtr;
    Tcl_Obj *result[3];
    int index;

#define CurrentlyInvoked(contextPtr) \
    ((contextPtr)->callPtr->chain[(contextPtr)->index])

    /*
     * Start with sanity checks on the calling context and the method 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])));
	Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL);
	Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", (char *)NULL);
	return TCL_ERROR;
    }

    contextPtr = (CallContext*)framePtr->clientData;
    contextPtr = (CallContext *) framePtr->clientData;

    /*
     * Now we do "conventional" argument parsing for a while. Note that no
     * subcommand takes arguments.
     */

    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "subcommand");
	return TCL_ERROR;
    } else if (objc == 1) {
	index = SELF_OBJECT;
    } else if (Tcl_GetIndexFromObj(interp, objv[1], subcmds, "subcommand", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum SelfCmds) index) {
    switch (index) {
    case SELF_OBJECT:
	Tcl_SetObjResult(interp, TclOOObjectName(interp, contextPtr->oPtr));
	return TCL_OK;
    case SELF_NS:
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		contextPtr->oPtr->namespacePtr->fullName,-1));
	Tcl_SetObjResult(interp,
		TclNewNamespaceObj(contextPtr->oPtr->namespacePtr));
	return TCL_OK;
    case SELF_CLASS: {
	Class *clsPtr = CurrentlyInvoked(contextPtr).mPtr->declaringClassPtr;

	if (clsPtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "method not defined by a class", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "UNMATCHED_CONTEXT", NULL);
		    "method not defined by a class", TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "UNMATCHED_CONTEXT", (char *)NULL);
	    return TCL_ERROR;
	}

	Tcl_SetObjResult(interp, TclOOObjectName(interp, clsPtr->thisPtr));
	return TCL_OK;
    }
    case SELF_METHOD:
	if (contextPtr->callPtr->flags & CONSTRUCTOR) {
	    Tcl_SetObjResult(interp, contextPtr->oPtr->fPtr->constructorName);
	} else if (contextPtr->callPtr->flags & DESTRUCTOR) {
	    Tcl_SetObjResult(interp, contextPtr->oPtr->fPtr->destructorName);
	} else {
	    Tcl_SetObjResult(interp,
		    CurrentlyInvoked(contextPtr).mPtr->namePtr);
	}
	return TCL_OK;
    case SELF_FILTER:
	if (!CurrentlyInvoked(contextPtr).isFilter) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "not inside a filtering context", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "UNMATCHED_CONTEXT", NULL);
		    "not inside a filtering context", TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "UNMATCHED_CONTEXT", (char *)NULL);
	    return TCL_ERROR;
	} else {
	    struct MInvoke *miPtr = &CurrentlyInvoked(contextPtr);
	    MInvoke *miPtr = &CurrentlyInvoked(contextPtr);
	    Object *oPtr;
	    const char *type;

	    if (miPtr->filterDeclarer != NULL) {
		oPtr = miPtr->filterDeclarer->thisPtr;
		type = "class";
	    } else {
		oPtr = contextPtr->oPtr;
		type = "object";
	    }

	    result[0] = TclOOObjectName(interp, oPtr);
	    result[1] = Tcl_NewStringObj(type, -1);
	    result[1] = Tcl_NewStringObj(type, TCL_AUTO_LENGTH);
	    result[2] = miPtr->mPtr->namePtr;
	    Tcl_SetObjResult(interp, Tcl_NewListObj(3, result));
	    return TCL_OK;
	}
    case SELF_CALLER:
	if ((framePtr->callerVarPtr == NULL) ||
		!(framePtr->callerVarPtr->isProcCallFrame & FRAME_IS_METHOD)){
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "caller is not an object", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL);
		    "caller is not an object", TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", (char *)NULL);
	    return TCL_ERROR;
	} else {
	    CallContext *callerPtr = (CallContext *)framePtr->callerVarPtr->clientData;
	    CallContext *callerPtr = (CallContext *)
		    framePtr->callerVarPtr->clientData;
	    Method *mPtr = callerPtr->callPtr->chain[callerPtr->index].mPtr;
	    Object *declarerPtr;

	    if (mPtr->declaringClassPtr != NULL) {
		declarerPtr = mPtr->declaringClassPtr->thisPtr;
	    } else if (mPtr->declaringObjectPtr != NULL) {
		declarerPtr = mPtr->declaringObjectPtr;
	    } else {
		/*
		 * This should be unreachable code.
		 */

		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"method without declarer!", -1));
			"method without declarer!", TCL_AUTO_LENGTH));
		return TCL_ERROR;
	    }

	    result[0] = TclOOObjectName(interp, declarerPtr);
	    result[1] = TclOOObjectName(interp, callerPtr->oPtr);
	    if (callerPtr->callPtr->flags & CONSTRUCTOR) {
		result[2] = declarerPtr->fPtr->constructorName;
	    } else if (callerPtr->callPtr->flags & DESTRUCTOR) {
		result[2] = declarerPtr->fPtr->destructorName;
	    } else {
		result[2] = mPtr->namePtr;
	    }
	    Tcl_SetObjResult(interp, Tcl_NewListObj(3, result));
	    return TCL_OK;
	}
    case SELF_NEXT:
	if (contextPtr->index < contextPtr->callPtr->numChain-1) {
	if (contextPtr->index < contextPtr->callPtr->numChain - 1) {
	    Method *mPtr =
		    contextPtr->callPtr->chain[contextPtr->index+1].mPtr;
		    contextPtr->callPtr->chain[contextPtr->index + 1].mPtr;
	    Object *declarerPtr;

	    if (mPtr->declaringClassPtr != NULL) {
		declarerPtr = mPtr->declaringClassPtr->thisPtr;
	    } else if (mPtr->declaringObjectPtr != NULL) {
		declarerPtr = mPtr->declaringObjectPtr;
	    } else {
		/*
		 * This should be unreachable code.
		 */

		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"method without declarer!", -1));
			"method without declarer!", TCL_AUTO_LENGTH));
		return TCL_ERROR;
	    }

	    result[0] = TclOOObjectName(interp, declarerPtr);
	    if (contextPtr->callPtr->flags & CONSTRUCTOR) {
		result[1] = declarerPtr->fPtr->constructorName;
	    } else if (contextPtr->callPtr->flags & DESTRUCTOR) {
		result[1] = declarerPtr->fPtr->destructorName;
	    } else {
		result[1] = mPtr->namePtr;
	    }
	    Tcl_SetObjResult(interp, Tcl_NewListObj(2, result));
	}
	return TCL_OK;
    case SELF_TARGET:
	if (!CurrentlyInvoked(contextPtr).isFilter) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "not inside a filtering context", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "UNMATCHED_CONTEXT", NULL);
		    "not inside a filtering context", TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "UNMATCHED_CONTEXT", (char *)NULL);
	    return TCL_ERROR;
	} else {
	    Method *mPtr;
	    Object *declarerPtr;
	    int i;
	    Tcl_Size i;

	    for (i=contextPtr->index ; i<contextPtr->callPtr->numChain ; i++){
	    for (i=contextPtr->index ; i<contextPtr->callPtr->numChain ; i++) {
		if (!contextPtr->callPtr->chain[i].isFilter) {
		    break;
		}
	    }
	    if (i == contextPtr->callPtr->numChain) {
		Tcl_Panic("filtering call chain without terminal non-filter");
	    }
	    mPtr = contextPtr->callPtr->chain[i].mPtr;
	    if (mPtr->declaringClassPtr != NULL) {
		declarerPtr = mPtr->declaringClassPtr->thisPtr;
	    } else if (mPtr->declaringObjectPtr != NULL) {
		declarerPtr = mPtr->declaringObjectPtr;
	    } else {
		/*
		 * This should be unreachable code.
		 */

		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"method without declarer!", -1));
			"method without declarer!", TCL_AUTO_LENGTH));
		return TCL_ERROR;
	    }
	    result[0] = TclOOObjectName(interp, declarerPtr);
	    result[1] = mPtr->namePtr;
	    Tcl_SetObjResult(interp, Tcl_NewListObj(2, result));
	    return TCL_OK;
	}
    case SELF_CALL:
	result[0] = TclOORenderCallChain(interp, contextPtr->callPtr);
	TclNewIntObj(result[1], contextPtr->index);
	TclNewIndexObj(result[1], contextPtr->index);
	Tcl_SetObjResult(interp, Tcl_NewListObj(2, result));
	return TCL_OK;
    }
    return TCL_ERROR;
}

/*
 * ----------------------------------------------------------------------
 *
 * CopyObjectCmd --
 *
 *	Implementation of the [oo::copy] command, which clones an object (but
 *	not its namespace). Note that no constructors are called during this
 *	process.
 *
 * ----------------------------------------------------------------------
 */

int
TclOOCopyObjectCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Object oPtr, o2Ptr;

    if (objc < 2 || objc > 4) {
	Tcl_WrongNumArgs(interp, 1, objv,
			 "sourceName ?targetName? ?targetNamespace?");
		"sourceName ?targetName? ?targetNamespace?");
	return TCL_ERROR;
    }

    oPtr = Tcl_GetObjectFromObj(interp, objv[1]);
    if (oPtr == NULL) {
	return TCL_ERROR;
    }

Changes to generic/tclOOCall.c.

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
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
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
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




-
+
+

-
+













-
-
+
+

-
-
+

-
+




-
+






-
+




-
+








-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+







/*
 * tclOOCall.c --
 *
 *	This file contains the method call chain management code for the
 *	object-system core.
 *	object-system core. It also contains everything else that does
 *	inheritance hierarchy traversal.
 *
 * Copyright (c) 2005-2012 by Donal K. Fellows
 * Copyright © 2005-2019 Donal K. Fellows
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "tclInt.h"
#include "tclOOInt.h"
#include <assert.h>

/*
 * Structure containing a CallContext and any other values needed only during
 * the construction of the CallContext.
 * Structure containing a CallChain and any other values needed only during
 * the construction of the CallChain.
 */

struct ChainBuilder {
typedef struct ChainBuilder {
    CallChain *callChainPtr;	/* The call chain being built. */
    int filterLength;		/* Number of entries in the call chain that
    size_t filterLength;	/* Number of entries in the call chain that
				 * are due to processing filters and not the
				 * main call chain. */
    Object *oPtr;		/* The object that we are building the chain
				 * for. */
};
} ChainBuilder;

/*
 * Structures used for traversing the class hierarchy to find out where
 * definitions are supposed to be done.
 */

typedef struct {
typedef struct DefineEntry {
    Class *definerCls;
    Tcl_Obj *namespaceName;
} DefineEntry;

typedef struct {
typedef struct DefineChain {
    DefineEntry *list;
    int num;
    int size;
} DefineChain;

/*
 * Extra flags used for call chain management.
 */

#define DEFINITE_PROTECTED 0x100000
#define DEFINITE_PUBLIC    0x200000
#define KNOWN_STATE	   (DEFINITE_PROTECTED | DEFINITE_PUBLIC)
#define SPECIAL		   (CONSTRUCTOR | DESTRUCTOR | FORCE_UNKNOWN)
#define BUILDING_MIXINS	   0x400000
#define TRAVERSED_MIXIN	   0x800000
#define OBJECT_MIXIN	   0x1000000
enum CallChainFlags {
    DEFINITE_PROTECTED = 0x100000,
    DEFINITE_PUBLIC = 0x200000,
    KNOWN_STATE = (DEFINITE_PROTECTED | DEFINITE_PUBLIC),
    SPECIAL = (CONSTRUCTOR | DESTRUCTOR | FORCE_UNKNOWN),
    BUILDING_MIXINS = 0x400000,
    TRAVERSED_MIXIN = 0x800000,
    OBJECT_MIXIN = 0x1000000,
    DEFINE_FOR_CLASS = 0x2000000
};

#define MIXIN_CONSISTENT(flags) \
    (((flags) & OBJECT_MIXIN) ||					\
	!((flags) & BUILDING_MIXINS) == !((flags) & TRAVERSED_MIXIN))

/*
 * Note that the flag bit PRIVATE_METHOD has a confusing name; it's just for
 * Itcl's special type of private.
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
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







+
+
+
+
+
+
+
+





-
+

-
+






-
+




-
+







-
+





-
+




-
+














-
+












-
+
+

-







#define WANT_UNEXPORTED(flags)			\
    (((flags) & (PRIVATE_METHOD | TRUE_PRIVATE_METHOD)) == 0)
#define WANT_ITCLPRIVATE(flags)			\
    (((flags) & PRIVATE_METHOD) != 0)
#define WANT_PRIVATE(flags)			\
    (((flags) & TRUE_PRIVATE_METHOD) != 0)

/*
 * Name the bits used in the names table values.
 */
enum NameTableValues {
    IN_LIST = 1,		/* Seen an implementation. */
    NO_IMPLEMENTATION = 2	/* Seen, but not implemented yet. */
};

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

static void		AddClassFiltersToCallContext(Object *const oPtr,
			    Class *clsPtr, struct ChainBuilder *const cbPtr,
			    Class *clsPtr, ChainBuilder *const cbPtr,
			    Tcl_HashTable *const doneFilters, int flags);
static void		AddClassMethodNames(Class *clsPtr, const int flags,
static void		AddClassMethodNames(Class *clsPtr, int flags,
			    Tcl_HashTable *const namesPtr,
			    Tcl_HashTable *const examinedClassesPtr);
static inline void	AddDefinitionNamespaceToChain(Class *const definerCls,
			    Tcl_Obj *const namespaceName,
			    DefineChain *const definePtr, int flags);
static inline void	AddMethodToCallChain(Method *const mPtr,
			    struct ChainBuilder *const cbPtr,
			    ChainBuilder *const cbPtr,
			    Tcl_HashTable *const doneFilters,
			    Class *const filterDecl, int flags);
static inline int	AddInstancePrivateToCallContext(Object *const oPtr,
			    Tcl_Obj *const methodNameObj,
			    struct ChainBuilder *const cbPtr, int flags);
			    ChainBuilder *const cbPtr, int flags);
static inline void	AddStandardMethodName(int flags, Tcl_Obj *namePtr,
			    Method *mPtr, Tcl_HashTable *namesPtr);
static inline void	AddPrivateMethodNames(Tcl_HashTable *methodsTablePtr,
			    Tcl_HashTable *namesPtr);
static inline int	AddSimpleChainToCallContext(Object *const oPtr,
			    Class *const contextCls,
			    Tcl_Obj *const methodNameObj,
			    struct ChainBuilder *const cbPtr,
			    ChainBuilder *const cbPtr,
			    Tcl_HashTable *const doneFilters, int flags,
			    Class *const filterDecl);
static int		AddPrivatesFromClassChainToCallContext(Class *classPtr,
			    Class *const contextCls,
			    Tcl_Obj *const methodNameObj,
			    struct ChainBuilder *const cbPtr,
			    ChainBuilder *const cbPtr,
			    Tcl_HashTable *const doneFilters, int flags,
			    Class *const filterDecl);
static int		AddSimpleClassChainToCallContext(Class *classPtr,
			    Tcl_Obj *const methodNameObj,
			    struct ChainBuilder *const cbPtr,
			    ChainBuilder *const cbPtr,
			    Tcl_HashTable *const doneFilters, int flags,
			    Class *const filterDecl);
static void		AddSimpleClassDefineNamespaces(Class *classPtr,
			    DefineChain *const definePtr, int flags);
static inline void	AddSimpleDefineNamespaces(Object *const oPtr,
			    DefineChain *const definePtr, int flags);
static int		CmpStr(const void *ptr1, const void *ptr2);
static void		DupMethodNameRep(Tcl_Obj *srcPtr, Tcl_Obj *dstPtr);
static Tcl_NRPostProc	FinalizeMethodRefs;
static void		FreeMethodNameRep(Tcl_Obj *objPtr);
static inline int	IsStillValid(CallChain *callPtr, Object *oPtr,
			    int flags, int reuseMask);
static Tcl_NRPostProc	ResetFilterFlags;
static Tcl_NRPostProc	SetFilterFlags;
static int		SortMethodNames(Tcl_HashTable *namesPtr, int flags,
static size_t		SortMethodNames(Tcl_HashTable *namesPtr, int flags,
			    const char ***stringsPtr);
static inline void	StashCallChain(Tcl_Obj *objPtr, CallChain *callPtr);

/*
 * Object type used to manage type caches attached to method names.
 */

static const Tcl_ObjType methodNameType = {
    "TclOO method name",
    FreeMethodNameRep,
    DupMethodNameRep,
    NULL,
    NULL
    NULL,
    TCL_OBJTYPE_V0
};


/*
 * ----------------------------------------------------------------------
 *
 * TclOODeleteContext --
 *
 *	Destroys a method call-chain context, which should not be in use.
243
244
245
246
247
248
249
250

251
252
253
254
255

256
257
258
259
260
261
262
254
255
256
257
258
259
260

261
262
263
264
265

266
267
268
269
270
271
272
273







-
+




-
+







 */

static inline void
StashCallChain(
    Tcl_Obj *objPtr,
    CallChain *callPtr)
{
    Tcl_ObjIntRep ir;
    Tcl_ObjInternalRep ir;

    callPtr->refCount++;
    TclGetString(objPtr);
    ir.twoPtrValue.ptr1 = callPtr;
    Tcl_StoreIntRep(objPtr, &methodNameType, &ir);
    Tcl_StoreInternalRep(objPtr, &methodNameType, &ir);
}

void
TclOOStashContext(
    Tcl_Obj *objPtr,
    CallContext *contextPtr)
{
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
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







-
-
+
+






-
-
+
+

















-
+







-
+











-
+







 */

static void
DupMethodNameRep(
    Tcl_Obj *srcPtr,
    Tcl_Obj *dstPtr)
{
    StashCallChain(dstPtr,
	    (CallChain *)TclFetchIntRep(srcPtr, &methodNameType)->twoPtrValue.ptr1);
    StashCallChain(dstPtr, (CallChain *)
	    TclFetchInternalRep(srcPtr, &methodNameType)->twoPtrValue.ptr1);
}

static void
FreeMethodNameRep(
    Tcl_Obj *objPtr)
{
    TclOODeleteChain(
	    (CallChain *)TclFetchIntRep(objPtr, &methodNameType)->twoPtrValue.ptr1);
    TclOODeleteChain((CallChain *)
	    TclFetchInternalRep(objPtr, &methodNameType)->twoPtrValue.ptr1);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOInvokeContext --
 *
 *	Invokes a single step along a method call-chain context. Note that the
 *	invocation of a step along the chain can cause further steps along the
 *	chain to be invoked. Note that this function is written to be as light
 *	in stack usage as possible.
 *
 * ----------------------------------------------------------------------
 */

int
TclOOInvokeContext(
    ClientData clientData,	/* The method call context. */
    void *clientData,		/* The method call context. */
    Tcl_Interp *interp,		/* Interpreter for error reporting, and many
				 * other sorts of context handling (e.g.,
				 * commands, variables) depending on method
				 * implementation. */
    int objc,			/* The number of arguments. */
    Tcl_Obj *const objv[])	/* The arguments as actually seen. */
{
    CallContext *const contextPtr = (CallContext *)clientData;
    CallContext *const contextPtr = (CallContext *) clientData;
    Method *const mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr;
    const int isFilter =
	    contextPtr->callPtr->chain[contextPtr->index].isFilter;

    /*
     * If this is the first step along the chain, we preserve the method
     * entries in the chain so that they do not get deleted out from under our
     * feet.
     */

    if (contextPtr->index == 0) {
	int i;
	Tcl_Size i;

	for (i = 0 ; i < contextPtr->callPtr->numChain ; i++) {
	    AddRef(contextPtr->callPtr->chain[i].mPtr);
	}

	/*
	 * Ensure that the method name itself is part of the arguments when
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
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







+
-
+
+
+
+





-
+



-
+







-
+



-
+







-
+



-
-
+
+







	contextPtr->oPtr->flags &= ~FILTER_HANDLING;
    }

    /*
     * Run the method implementation.
     */

    if (mPtr->typePtr->version < TCL_OO_METHOD_VERSION_2) {
    return mPtr->typePtr->callProc(mPtr->clientData, interp,
	return (mPtr->typePtr->callProc)(mPtr->clientData, interp,
		(Tcl_ObjectContext) contextPtr, objc, objv);
    }
    return (mPtr->type2Ptr->callProc)(mPtr->clientData, interp,
	    (Tcl_ObjectContext) contextPtr, objc, objv);
}

static int
SetFilterFlags(
    ClientData data[],
    void *data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    CallContext *contextPtr = (CallContext *)data[0];
    CallContext *contextPtr = (CallContext *) data[0];

    contextPtr->oPtr->flags |= FILTER_HANDLING;
    return result;
}

static int
ResetFilterFlags(
    ClientData data[],
    void *data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    CallContext *contextPtr = (CallContext *)data[0];
    CallContext *contextPtr = (CallContext *) data[0];

    contextPtr->oPtr->flags &= ~FILTER_HANDLING;
    return result;
}

static int
FinalizeMethodRefs(
    ClientData data[],
    void *data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    CallContext *contextPtr = (CallContext *)data[0];
    int i;
    CallContext *contextPtr = (CallContext *) data[0];
    Tcl_Size i;

    for (i = 0 ; i < contextPtr->callPtr->numChain ; i++) {
	TclOODelMethodRef(contextPtr->callPtr->chain[i].mPtr);
    }
    return result;
}

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
467
468
456
457
458
459
460
461
462

463
464
465
466
467
468
469
470






471
472
473
474
475
476
477







-
+







-
-
-
-
-
-







    Tcl_HashTable names;	/* Tcl_Obj* method name to "wanted in list"
				 * mapping. */
    Tcl_HashTable examinedClasses;
				/* Used to track what classes have been looked
				 * at. Is set-like in nature and keyed by
				 * pointer to class. */
    FOREACH_HASH_DECLS;
    int i, numStrings;
    Tcl_Size i, numStrings;
    Class *mixinPtr;
    Tcl_Obj *namePtr;
    Method *mPtr;

    Tcl_InitObjHashTable(&names);
    Tcl_InitHashTable(&examinedClasses, TCL_ONE_WORD_KEYS);

    /*
     * Name the bits used in the names table values.
     */
#define IN_LIST 1
#define NO_IMPLEMENTATION 2

    /*
     * Process method names due to the object.
     */

    if (oPtr->methodsPtr) {
	FOREACH_HASH(namePtr, mPtr, oPtr->methodsPtr) {
	    if (IS_PRIVATE(mPtr)) {
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
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







-
+













-
+








    Tcl_DeleteHashTable(&examinedClasses);
    numStrings = SortMethodNames(&names, flags, stringsPtr);
    Tcl_DeleteHashTable(&names);
    return numStrings;
}

int
size_t
TclOOGetSortedClassMethodList(
    Class *clsPtr,		/* The class to get the method names for. */
    int flags,			/* Whether we just want the public method
				 * names. */
    const char ***stringsPtr)	/* Where to write a pointer to the array of
				 * strings to. */
{
    Tcl_HashTable names;	/* Tcl_Obj* method name to "wanted in list"
				 * mapping. */
    Tcl_HashTable examinedClasses;
				/* Used to track what classes have been looked
				 * at. Is set-like in nature and keyed by
				 * pointer to class. */
    int numStrings;
    size_t numStrings;

    Tcl_InitObjHashTable(&names);
    Tcl_InitHashTable(&examinedClasses, TCL_ONE_WORD_KEYS);

    /*
     * Process method names from the class hierarchy and the mixin hierarchy.
     */
576
577
578
579
580
581
582
583

584
585
586
587
588
589
590
585
586
587
588
589
590
591

592
593
594
595
596
597
598
599







-
+







 *
 * Returns:
 *	The length of the sorted list.
 *
 * ----------------------------------------------------------------------
 */

static int
static size_t
SortMethodNames(
    Tcl_HashTable *namesPtr,	/* The table of names; unsorted, but contains
				 * whether the names are wanted and under what
				 * circumstances. */
    int flags,			/* Whether we are looking for unexported
				 * methods. Full private methods are handled
				 * on insertion to the table. */
609
610
611
612
613
614
615
616

617
618
619
620
621
622
623
618
619
620
621
622
623
624

625
626
627
628
629
630
631
632







-
+








    /*
     * We need to build the list of methods to sort. We will be using qsort()
     * for this, because it is very unlikely that the list will be heavily
     * sorted when it is long enough to matter.
     */

    strings = (const char **)Tcl_Alloc(sizeof(char *) * namesPtr->numEntries);
    strings = (const char **) Tcl_Alloc(sizeof(char *) * namesPtr->numEntries);
    FOREACH_HASH(namePtr, isWanted, namesPtr) {
	if (!WANT_PUBLIC(flags) || (PTR2INT(isWanted) & IN_LIST)) {
	    if (PTR2INT(isWanted) & NO_IMPLEMENTATION) {
		continue;
	    }
	    strings[i++] = TclGetString(namePtr);
	}
631
632
633
634
635
636
637
638

639
640
641
642
643
644
645
640
641
642
643
644
645
646

647
648
649
650
651
652
653
654







-
+








    if (i > 0) {
	if (i > 1) {
	    qsort((void *) strings, i, sizeof(char *), CmpStr);
	}
	*stringsPtr = strings;
    } else {
	Tcl_Free((void *)strings);
	Tcl_Free((void *) strings);
	*stringsPtr = NULL;
    }
    return i;
}

/*
 * Comparator for SortMethodNames
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
707
708
709
710
711
712
713

714
715
716
717
718
719
720
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721

722
723
724
725
726
727
728
729







-
+














-
+






-
+
















-
+







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

static void
AddClassMethodNames(
    Class *clsPtr,		/* Class to get method names from. */
    const int flags,		/* Whether we are interested in just the
    int flags,			/* Whether we are interested in just the
				 * public method names. */
    Tcl_HashTable *const namesPtr,
				/* Reference to the hash table to put the
				 * information in. The hash table maps the
				 * Tcl_Obj * method name to an integral value
				 * describing whether the method is wanted.
				 * This ensures that public/private override
				 * semantics are handled correctly. */
    Tcl_HashTable *const examinedClassesPtr)
				/* Hash table that tracks what classes have
				 * already been looked at. The keys are the
				 * pointers to the classes, and the values are
				 * immaterial. */
{
    int i;
    Tcl_Size i;

    /*
     * If we've already started looking at this class, stop working on it now
     * to prevent repeated work.
     */

    if (Tcl_FindHashEntry(examinedClassesPtr, (char *) clsPtr)) {
    if (Tcl_FindHashEntry(examinedClassesPtr, clsPtr)) {
	return;
    }

    /*
     * Scope all declarations so that the compiler can stand a good chance of
     * making the recursive step highly efficient. We also hand-implement the
     * tail-recursive case using a while loop; C compilers typically cannot do
     * tail-recursion optimization usefully.
     */

    while (1) {
	FOREACH_HASH_DECLS;
	Tcl_Obj *namePtr;
	Method *mPtr;
	int isNew;

	(void) Tcl_CreateHashEntry(examinedClassesPtr, (char *) clsPtr,
	(void) Tcl_CreateHashEntry(examinedClassesPtr, clsPtr,
		&isNew);
	if (!isNew) {
	    break;
	}

	if (clsPtr->mixins.num != 0) {
	    Class *mixinPtr;
765
766
767
768
769
770
771
772

773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788

789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828

829
830
831
832
833
834
835
836

837
838

839
840
841
842
843
844
845
774
775
776
777
778
779
780

781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796

797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813



814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832


833
834
835
836
837
838
839
840

841
842

843
844
845
846
847
848
849
850







-
+















-
+
















-
-
-



















-
-
+







-
+

-
+







    Method *mPtr;
    Tcl_Obj *namePtr;

    FOREACH_HASH(namePtr, mPtr, methodsTablePtr) {
	if (IS_PRIVATE(mPtr)) {
	    int isNew;

	    hPtr = Tcl_CreateHashEntry(namesPtr, (char *) namePtr, &isNew);
	    hPtr = Tcl_CreateHashEntry(namesPtr, namePtr, &isNew);
	    Tcl_SetHashValue(hPtr, INT2PTR(IN_LIST));
	}
    }
}

static inline void
AddStandardMethodName(
    int flags,
    Tcl_Obj *namePtr,
    Method *mPtr,
    Tcl_HashTable *namesPtr)
{
    if (!IS_PRIVATE(mPtr)) {
	int isNew;
	Tcl_HashEntry *hPtr =
		Tcl_CreateHashEntry(namesPtr, (char *) namePtr, &isNew);
		Tcl_CreateHashEntry(namesPtr, namePtr, &isNew);

	if (isNew) {
	    int isWanted = (!WANT_PUBLIC(flags) || IS_PUBLIC(mPtr))
		    ? IN_LIST : 0;

	    isWanted |= (mPtr->typePtr == NULL ? NO_IMPLEMENTATION : 0);
	    Tcl_SetHashValue(hPtr, INT2PTR(isWanted));
	} else if ((PTR2INT(Tcl_GetHashValue(hPtr)) & NO_IMPLEMENTATION)
		&& mPtr->typePtr != NULL) {
	    int isWanted = PTR2INT(Tcl_GetHashValue(hPtr));

	    isWanted &= ~NO_IMPLEMENTATION;
	    Tcl_SetHashValue(hPtr, INT2PTR(isWanted));
	}
    }
}

#undef IN_LIST
#undef NO_IMPLEMENTATION

/*
 * ----------------------------------------------------------------------
 *
 * AddInstancePrivateToCallContext --
 *
 *	Add private methods from the instance. Called when the calling Tcl
 *	context is a TclOO method declared by an object that is the same as
 *	the current object. Returns true iff a private method was actually
 *	found and added to the call chain (as this suppresses caching).
 *
 * ----------------------------------------------------------------------
 */

static inline int
AddInstancePrivateToCallContext(
    Object *const oPtr,		/* Object to add call chain entries for. */
    Tcl_Obj *const methodName,	/* Name of method to add the call chain
				 * entries for. */
    struct ChainBuilder *const cbPtr,
				/* Where to add the call chain entries. */
    ChainBuilder *const cbPtr,	/* Where to add the call chain entries. */
    int flags)			/* What sort of call chain are we building. */
{
    Tcl_HashEntry *hPtr;
    Method *mPtr;
    int donePrivate = 0;

    if (oPtr->methodsPtr) {
	hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) methodName);
	hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, methodName);
	if (hPtr != NULL) {
	    mPtr = (Method *)Tcl_GetHashValue(hPtr);
	    mPtr = (Method *) Tcl_GetHashValue(hPtr);
	    if (IS_PRIVATE(mPtr)) {
		AddMethodToCallChain(mPtr, cbPtr, NULL, NULL, flags);
		donePrivate = 1;
	    }
	}
    }
    return donePrivate;
863
864
865
866
867
868
869
870
871

872
873
874
875
876
877
878
879

880

881
882
883
884
885

886
887
888

889
890
891
892
893
894
895
868
869
870
871
872
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
898
899
900







-
-
+








+
-
+




-
+


-
+







    Object *const oPtr,		/* Object to add call chain entries for. */
    Class *const contextCls,	/* Context class; the currently considered
				 * class is equal to this, private methods may
				 * also be added. [TIP 500] */
    Tcl_Obj *const methodNameObj,
				/* Name of method to add the call chain
				 * entries for. */
    struct ChainBuilder *const cbPtr,
				/* Where to add the call chain entries. */
    ChainBuilder *const cbPtr,	/* Where to add the call chain entries. */
    Tcl_HashTable *const doneFilters,
				/* Where to record what call chain entries
				 * have been processed. */
    int flags,			/* What sort of call chain are we building. */
    Class *const filterDecl)	/* The class that declared the filter. If
				 * NULL, either the filter was declared by the
				 * object or this isn't a filter. */
{
    Tcl_Size i;
    int i, foundPrivate = 0, blockedUnexported = 0;
    int foundPrivate = 0, blockedUnexported = 0;
    Tcl_HashEntry *hPtr;
    Method *mPtr;

    if (!(flags & (KNOWN_STATE | SPECIAL)) && oPtr->methodsPtr) {
	hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) methodNameObj);
	hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, methodNameObj);

	if (hPtr != NULL) {
	    mPtr = (Method *)Tcl_GetHashValue(hPtr);
	    mPtr = (Method *) Tcl_GetHashValue(hPtr);
	    if (!IS_PRIVATE(mPtr)) {
		if (WANT_PUBLIC(flags)) {
		    if (!IS_PUBLIC(mPtr)) {
			blockedUnexported = 1;
		    } else {
			flags |= DEFINITE_PUBLIC;
		    }
909
910
911
912
913
914
915
916

917
918

919
920
921
922
923
924



925
926
927
928
929
930
931
914
915
916
917
918
919
920

921
922

923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939







-
+

-
+






+
+
+







			doneFilters, flags|TRAVERSED_MIXIN, filterDecl);
	    }
	    foundPrivate |= AddSimpleClassChainToCallContext(mixinPtr,
		    methodNameObj, cbPtr, doneFilters,
		    flags | TRAVERSED_MIXIN, filterDecl);
	}
	if (oPtr->methodsPtr && !blockedUnexported) {
	    hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *)methodNameObj);
	    hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, methodNameObj);
	    if (hPtr != NULL) {
		mPtr = (Method *)Tcl_GetHashValue(hPtr);
		mPtr = (Method *) Tcl_GetHashValue(hPtr);
		if (!IS_PRIVATE(mPtr)) {
		    AddMethodToCallChain(mPtr, cbPtr, doneFilters, filterDecl,
			    flags);
		}
	    }
	}
    }
    if (!oPtr->selfCls) {
	return foundPrivate;
    }
    if (contextCls) {
	foundPrivate |= AddPrivatesFromClassChainToCallContext(oPtr->selfCls,
		contextCls, methodNameObj, cbPtr, doneFilters, flags,
		filterDecl);
    }
    if (!blockedUnexported) {
946
947
948
949
950
951
952
953
954

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972

973
974
975
976
977
978
979
954
955
956
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







-
-
+

















-
+







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

static inline void
AddMethodToCallChain(
    Method *const mPtr,		/* Actual method implementation to add to call
				 * chain (or NULL, a no-op). */
    struct ChainBuilder *const cbPtr,
				/* The call chain to add the method
    ChainBuilder *const cbPtr,	/* The call chain to add the method
				 * implementation to. */
    Tcl_HashTable *const doneFilters,
				/* Where to record what filters have been
				 * processed. If NULL, not processing filters.
				 * Note that this function does not update
				 * this hashtable. */
    Class *const filterDecl,	/* The class that declared the filter. If
				 * NULL, either the filter was declared by the
				 * object or this isn't a filter. */
    int flags)			/* Used to check if we're mixin-consistent
				 * only. Mixin-consistent means that either
				 * we're looking to add things from a mixin
				 * and we have passed a mixin, or we're not
				 * looking to add things from a mixin and have
				 * not passed a mixin. */
{
    CallChain *callPtr = cbPtr->callChainPtr;
    int i;
    Tcl_Size i;

    /*
     * Return if this is just an entry used to record whether this is a public
     * method. If so, there's nothing real to call and so nothing to add to
     * the call chain.
     *
     * This is also where we enforce mixin-consistency.
1032
1033
1034
1035
1036
1037
1038
1039
1040


1041
1042

1043
1044
1045


1046
1047
1048
1049
1050
1051
1052
1039
1040
1041
1042
1043
1044
1045


1046
1047
1048

1049
1050


1051
1052
1053
1054
1055
1056
1057
1058
1059







-
-
+
+

-
+

-
-
+
+







    /*
     * Need to really add the method. This is made a bit more complex by the
     * fact that we are using some "static" space initially, and only start
     * realloc-ing if the chain gets long.
     */

    if (callPtr->numChain == CALL_CHAIN_STATIC_SIZE) {
	callPtr->chain =
		(struct MInvoke *)Tcl_Alloc(sizeof(struct MInvoke) * (callPtr->numChain + 1));
	callPtr->chain = (MInvoke *)
		Tcl_Alloc(sizeof(MInvoke) * (callPtr->numChain + 1));
	memcpy(callPtr->chain, callPtr->staticChain,
		sizeof(struct MInvoke) * callPtr->numChain);
		sizeof(MInvoke) * callPtr->numChain);
    } else if (callPtr->numChain > CALL_CHAIN_STATIC_SIZE) {
	callPtr->chain = (struct MInvoke *)Tcl_Realloc(callPtr->chain,
		sizeof(struct MInvoke) * (callPtr->numChain + 1));
	callPtr->chain = (MInvoke *) Tcl_Realloc(callPtr->chain,
		sizeof(MInvoke) * (callPtr->numChain + 1));
    }
    callPtr->chain[i].mPtr = mPtr;
    callPtr->chain[i].isFilter = (doneFilters != NULL);
    callPtr->chain[i].filterDeclarer = filterDecl;
    callPtr->numChain++;
}

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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141







+
+
+
+
+
+
+



-
+


+
-
-
-
+
+
+
+
+
+
+
+















-
+














+
+
+
+
+
+
+








static inline void
InitCallChain(
    CallChain *callPtr,
    Object *oPtr,
    int flags)
{
    /*
     * Note that it's possible to end up with a NULL oPtr->selfCls here if
     * there is a call into stereotypical object after it has finished running
     * its destructor phase. Such things can't be cached for a long time so the
     * epoch can be bogus. [Bug 7842f33a5c]
     */

    callPtr->flags = flags &
	    (PUBLIC_METHOD | PRIVATE_METHOD | SPECIAL | FILTER_HANDLING);
    if (oPtr->flags & USE_CLASS_CACHE) {
	oPtr = oPtr->selfCls->thisPtr;
	oPtr = (oPtr->selfCls ? oPtr->selfCls->thisPtr : NULL);
	callPtr->flags |= USE_CLASS_CACHE;
    }
    if (oPtr) {
    callPtr->epoch = oPtr->fPtr->epoch;
    callPtr->objectCreationEpoch = oPtr->creationEpoch;
    callPtr->objectEpoch = oPtr->epoch;
	callPtr->epoch = oPtr->fPtr->epoch;
	callPtr->objectCreationEpoch = oPtr->creationEpoch;
	callPtr->objectEpoch = oPtr->epoch;
    } else {
	callPtr->epoch = 0;
	callPtr->objectCreationEpoch = 0;
	callPtr->objectEpoch = 0;
    }
    callPtr->refCount = 1;
    callPtr->numChain = 0;
    callPtr->chain = callPtr->staticChain;
}

/*
 * ----------------------------------------------------------------------
 *
 * IsStillValid --
 *
 *	Calculates whether the given call chain can be used for executing a
 *	method for the given object. The condition on a chain from a cached
 *	location being reusable is:
 *	- Refers to the same object (same creation epoch), and
 *	- Still across the same class structure (same global epoch), and
 *	- Still across the same object strucutre (same local epoch), and
 *	- Still across the same object structure (same local epoch), and
 *	- No public/private/filter magic leakage (same flags, modulo the fact
 *	  that a public chain will satisfy a non-public call).
 *
 * ----------------------------------------------------------------------
 */

static inline int
IsStillValid(
    CallChain *callPtr,
    Object *oPtr,
    int flags,
    int mask)
{
    if ((oPtr->flags & USE_CLASS_CACHE)) {
	/*
	 * If the object is in a weird state (due to stereotype tricks) then
	 * just declare the cache invalid. [Bug 7842f33a5c]
	 */
	if (!oPtr->selfCls) {
	    return 0;
	}
	oPtr = oPtr->selfCls->thisPtr;
	flags |= USE_CLASS_CACHE;
    }
    return ((callPtr->objectCreationEpoch == oPtr->creationEpoch)
	    && (callPtr->epoch == oPtr->fPtr->epoch)
	    && (callPtr->objectEpoch == oPtr->epoch)
	    && ((callPtr->flags & mask) == (flags & mask)));
1144
1145
1146
1147
1148
1149
1150
1151
1152



1153
1154
1155
1156
1157
1158
1159
1171
1172
1173
1174
1175
1176
1177


1178
1179
1180
1181
1182
1183
1184
1185
1186
1187







-
-
+
+
+







				 * also be added. [TIP 500] */
    Tcl_Obj *cacheInThisObj)	/* What object to cache in, or NULL if it is
				 * to be in the same object as the
				 * methodNameObj. */
{
    CallContext *contextPtr;
    CallChain *callPtr;
    struct ChainBuilder cb;
    int i, count, doFilters, donePrivate = 0;
    ChainBuilder cb;
    Tcl_Size i, count;
    int doFilters, donePrivate = 0;
    Tcl_HashEntry *hPtr;
    Tcl_HashTable doneFilters;

    if (cacheInThisObj == NULL) {
	cacheInThisObj = methodNameObj;
    }
    if (flags&(SPECIAL|FILTER_HANDLING) || (oPtr->flags&FILTER_HANDLING)) {
1185
1186
1187
1188
1189
1190
1191
1192

1193
1194
1195
1196


1197
1198
1199
1200
1201

1202
1203








1204
1205


1206
1207

1208
1209
1210
1211
1212
1213
1214

1215
1216
1217
1218
1219
1220
1221

1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233

1234
1235
1236
1237
1238
1239
1240
1213
1214
1215
1216
1217
1218
1219

1220
1221
1222


1223
1224
1225
1226
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







-
+


-
-
+
+




-
+


+
+
+
+
+
+
+
+
-
-
+
+

-
+






-
+






-
+











-
+







	/*
	 * Check if we can get the chain out of the Tcl_Obj method name or out
	 * of the cache. This is made a bit more complex by the fact that
	 * there are multiple different layers of cache (in the Tcl_Obj, in
	 * the object, and in the class).
	 */

	const Tcl_ObjIntRep *irPtr;
	const Tcl_ObjInternalRep *irPtr;
	const int reuseMask = (WANT_PUBLIC(flags) ? ~0 : ~PUBLIC_METHOD);

	if ((irPtr = TclFetchIntRep(cacheInThisObj, &methodNameType))) {
	    callPtr = (CallChain *)irPtr->twoPtrValue.ptr1;
	if ((irPtr = TclFetchInternalRep(cacheInThisObj, &methodNameType))) {
	    callPtr = (CallChain *) irPtr->twoPtrValue.ptr1;
	    if (IsStillValid(callPtr, oPtr, flags, reuseMask)) {
		callPtr->refCount++;
		goto returnContext;
	    }
	    Tcl_StoreIntRep(cacheInThisObj, &methodNameType, NULL);
	    Tcl_StoreInternalRep(cacheInThisObj, &methodNameType, NULL);
	}

	/*
	 * Note that it's possible to end up with a NULL oPtr->selfCls here if
	 * there is a call into stereotypical object after it has finished
	 * running its destructor phase. It's quite a tangle, but at that
	 * point, we simply can't get stereotypes from the cache.
	 * [Bug 7842f33a5c]
	 */

	if (oPtr->flags & USE_CLASS_CACHE) {
	    if (oPtr->selfCls->classChainCache != NULL) {
	if (oPtr->flags & USE_CLASS_CACHE && oPtr->selfCls) {
	    if (oPtr->selfCls->classChainCache) {
		hPtr = Tcl_FindHashEntry(oPtr->selfCls->classChainCache,
			(char *) methodNameObj);
			methodNameObj);
	    } else {
		hPtr = NULL;
	    }
	} else {
	    if (oPtr->chainCache != NULL) {
		hPtr = Tcl_FindHashEntry(oPtr->chainCache,
			(char *) methodNameObj);
			methodNameObj);
	    } else {
		hPtr = NULL;
	    }
	}

	if (hPtr != NULL && Tcl_GetHashValue(hPtr) != NULL) {
	    callPtr = (CallChain *)Tcl_GetHashValue(hPtr);
	    callPtr = (CallChain *) Tcl_GetHashValue(hPtr);
	    if (IsStillValid(callPtr, oPtr, flags, reuseMask)) {
		callPtr->refCount++;
		goto returnContext;
	    }
	    Tcl_SetHashValue(hPtr, NULL);
	    TclOODeleteChain(callPtr);
	}

	doFilters = 1;
    }

    callPtr = (CallChain *)Tcl_Alloc(sizeof(CallChain));
    callPtr = (CallChain *) Tcl_Alloc(sizeof(CallChain));
    InitCallChain(callPtr, oPtr, flags);

    cb.callChainPtr = callPtr;
    cb.filterLength = 0;
    cb.oPtr = oPtr;

    /*
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
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371

1372

1373
1374
1375
1376
1377
1378
1379
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
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410

1411
1412
1413
1414
1415
1416
1417
1418







+


-
-
+
+




-
+


-
+
+




-
+




















+
-
+







	callPtr->epoch = 0;
	if (count == callPtr->numChain) {
	    TclOODeleteChain(callPtr);
	    return NULL;
	}
    } else if (doFilters && !donePrivate) {
	if (hPtr == NULL) {
	    int isNew;
	    if (oPtr->flags & USE_CLASS_CACHE) {
		if (oPtr->selfCls->classChainCache == NULL) {
		    oPtr->selfCls->classChainCache =
			    (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));
		    oPtr->selfCls->classChainCache = (Tcl_HashTable *)
			    Tcl_Alloc(sizeof(Tcl_HashTable));

		    Tcl_InitObjHashTable(oPtr->selfCls->classChainCache);
		}
		hPtr = Tcl_CreateHashEntry(oPtr->selfCls->classChainCache,
			(char *) methodNameObj, &i);
			methodNameObj, &isNew);
	    } else {
		if (oPtr->chainCache == NULL) {
		    oPtr->chainCache = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));
		    oPtr->chainCache = (Tcl_HashTable *)
			    Tcl_Alloc(sizeof(Tcl_HashTable));

		    Tcl_InitObjHashTable(oPtr->chainCache);
		}
		hPtr = Tcl_CreateHashEntry(oPtr->chainCache,
			(char *) methodNameObj, &i);
			methodNameObj, &isNew);
	    }
	}
	callPtr->refCount++;
	Tcl_SetHashValue(hPtr, callPtr);
	StashCallChain(cacheInThisObj, callPtr);
    } else if (flags & CONSTRUCTOR) {
	if (oPtr->selfCls->constructorChainPtr) {
	    TclOODeleteChain(oPtr->selfCls->constructorChainPtr);
	}
	oPtr->selfCls->constructorChainPtr = callPtr;
	callPtr->refCount++;
    } else if ((flags & DESTRUCTOR) && oPtr->mixins.num == 0) {
	if (oPtr->selfCls->destructorChainPtr) {
	    TclOODeleteChain(oPtr->selfCls->destructorChainPtr);
	}
	oPtr->selfCls->destructorChainPtr = callPtr;
	callPtr->refCount++;
    }

  returnContext:
    contextPtr = (CallContext *)
    contextPtr = (CallContext *)TclStackAlloc(oPtr->fPtr->interp, sizeof(CallContext));
	    TclStackAlloc(oPtr->fPtr->interp, sizeof(CallContext));
    contextPtr->oPtr = oPtr;

    /*
     * Corresponding TclOODecrRefCount() in TclOODeleteContext
     */

    AddRef(oPtr);
1403
1404
1405
1406
1407
1408
1409
1410
1411


1412
1413
1414
1415











1416
1417
1418
1419
1420
1421
1422
1442
1443
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







-
-
+
+




+
+
+
+
+
+
+
+
+
+
+







				 * destructor chain. */
    int flags)			/* What sort of context are we looking for.
				 * Only the bits PUBLIC_METHOD, CONSTRUCTOR,
				 * PRIVATE_METHOD, DESTRUCTOR and
				 * FILTER_HANDLING are useful. */
{
    CallChain *callPtr;
    struct ChainBuilder cb;
    int i, count;
    ChainBuilder cb;
    Tcl_Size count;
    Foundation *fPtr = clsPtr->thisPtr->fPtr;
    Tcl_HashEntry *hPtr;
    Tcl_HashTable doneFilters;
    Object obj;

    /*
     * Note that it's possible to end up with a NULL clsPtr here if there is
     * a call into stereotypical object after it has finished running its
     * destructor phase. It's quite a tangle, but at that point, we simply
     * can't get stereotypes. [Bug 7842f33a5c]
     */

    if (clsPtr == NULL) {
	return NULL;
    }

    /*
     * Synthesize a temporary stereotypical object so that we can use existing
     * machinery to produce the stereotypical call chain.
     */

    memset(&obj, 0, sizeof(Object));
1430
1431
1432
1433
1434
1435
1436
1437

1438
1439
1440
1441

1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453

1454
1455
1456
1457
1458
1459
1460
1480
1481
1482
1483
1484
1485
1486

1487
1488
1489
1490

1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502

1503
1504
1505
1506
1507
1508
1509
1510







-
+



-
+











-
+







     * the cache. This is made a bit more complex by the fact that there are
     * multiple different layers of cache (in the Tcl_Obj, in the object, and
     * in the class).
     */

    if (clsPtr->classChainCache != NULL) {
	hPtr = Tcl_FindHashEntry(clsPtr->classChainCache,
		(char *) methodNameObj);
		methodNameObj);
	if (hPtr != NULL && Tcl_GetHashValue(hPtr) != NULL) {
	    const int reuseMask = (WANT_PUBLIC(flags) ? ~0 : ~PUBLIC_METHOD);

	    callPtr = (CallChain *)Tcl_GetHashValue(hPtr);
	    callPtr = (CallChain *) Tcl_GetHashValue(hPtr);
	    if (IsStillValid(callPtr, &obj, flags, reuseMask)) {
		callPtr->refCount++;
		return callPtr;
	    }
	    Tcl_SetHashValue(hPtr, NULL);
	    TclOODeleteChain(callPtr);
	}
    } else {
	hPtr = NULL;
    }

    callPtr = (CallChain *)Tcl_Alloc(sizeof(CallChain));
    callPtr = (CallChain *) Tcl_Alloc(sizeof(CallChain));
    memset(callPtr, 0, sizeof(CallChain));
    callPtr->flags = flags & (PUBLIC_METHOD|PRIVATE_METHOD|FILTER_HANDLING);
    callPtr->epoch = fPtr->epoch;
    callPtr->objectCreationEpoch = fPtr->tsdPtr->nsCount;
    callPtr->objectEpoch = clsPtr->thisPtr->epoch;
    callPtr->refCount = 1;
    callPtr->chain = callPtr->staticChain;
1484
1485
1486
1487
1488
1489
1490
1491

1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506

1507
1508


1509
1510
1511
1512

1513
1514
1515
1516
1517
1518
1519
1534
1535
1536
1537
1538
1539
1540

1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558

1559
1560
1561
1562
1563

1564
1565
1566
1567
1568
1569
1570
1571







-
+















+

-
+
+



-
+







	    flags|BUILDING_MIXINS, NULL);
    AddSimpleChainToCallContext(&obj, NULL, methodNameObj, &cb, NULL, flags,
	    NULL);

    /*
     * Check to see if the method has no implementation. If so, we probably
     * need to add in a call to the unknown method. Otherwise, set up the
     * cacheing of the method implementation (if relevant).
     * caching of the method implementation (if relevant).
     */

    if (count == callPtr->numChain) {
	AddSimpleChainToCallContext(&obj, NULL, fPtr->unknownMethodNameObj,
		&cb, NULL, BUILDING_MIXINS, NULL);
	AddSimpleChainToCallContext(&obj, NULL, fPtr->unknownMethodNameObj,
		&cb, NULL, 0, NULL);
	callPtr->flags |= OO_UNKNOWN_METHOD;
	callPtr->epoch = 0;
	if (count == callPtr->numChain) {
	    TclOODeleteChain(callPtr);
	    return NULL;
	}
    } else {
	if (hPtr == NULL) {
	    int isNew;
	    if (clsPtr->classChainCache == NULL) {
		clsPtr->classChainCache = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));
		clsPtr->classChainCache = (Tcl_HashTable *)
			Tcl_Alloc(sizeof(Tcl_HashTable));
		Tcl_InitObjHashTable(clsPtr->classChainCache);
	    }
	    hPtr = Tcl_CreateHashEntry(clsPtr->classChainCache,
		    (char *) methodNameObj, &i);
		    methodNameObj, &isNew);
	}
	callPtr->refCount++;
	Tcl_SetHashValue(hPtr, callPtr);
	StashCallChain(methodNameObj, callPtr);
    }
    return callPtr;
}
1529
1530
1531
1532
1533
1534
1535
1536
1537

1538
1539
1540
1541
1542
1543
1544

1545

1546
1547
1548
1549
1550
1551
1552
1581
1582
1583
1584
1585
1586
1587


1588
1589
1590
1591
1592
1593
1594
1595
1596

1597
1598
1599
1600
1601
1602
1603
1604







-
-
+







+
-
+







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

static void
AddClassFiltersToCallContext(
    Object *const oPtr,		/* Object that the filters operate on. */
    Class *clsPtr,		/* Class to get the filters from. */
    struct ChainBuilder *const cbPtr,
				/* Context to fill with call chain entries. */
    ChainBuilder *const cbPtr,	/* Context to fill with call chain entries. */
    Tcl_HashTable *const doneFilters,
				/* Where to record what filters have been
				 * processed. Keys are objects, values are
				 * ignored. */
    int flags)			/* Whether we've gone along a mixin link
				 * yet. */
{
    Tcl_Size i;
    int i, clearedFlags =
    int clearedFlags =
	    flags & ~(TRAVERSED_MIXIN|OBJECT_MIXIN|BUILDING_MIXINS);
    Class *superPtr, *mixinPtr;
    Tcl_Obj *filterObj;

  tailRecurse:
    if (clsPtr == NULL) {
	return;
1568
1569
1570
1571
1572
1573
1574
1575

1576
1577
1578
1579
1580
1581
1582
1583
1620
1621
1622
1623
1624
1625
1626

1627

1628
1629
1630
1631
1632
1633
1634







-
+
-







     * override how filters work to extend their behaviour.
     */

    if (MIXIN_CONSISTENT(flags)) {
	FOREACH(filterObj, clsPtr->filters) {
	    int isNew;

	    (void) Tcl_CreateHashEntry(doneFilters, (char *) filterObj,
	    (void) Tcl_CreateHashEntry(doneFilters, filterObj, &isNew);
		    &isNew);
	    if (isNew) {
		AddSimpleChainToCallContext(oPtr, NULL, filterObj, cbPtr,
			doneFilters, clearedFlags|BUILDING_MIXINS, clsPtr);
		AddSimpleChainToCallContext(oPtr, NULL, filterObj, cbPtr,
			doneFilters, clearedFlags, clsPtr);
	    }
	}
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
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







-
-
+








-
+








+
+
+
+



+
+
+













-
+







AddPrivatesFromClassChainToCallContext(
    Class *classPtr,		/* Class to add the call chain entries for. */
    Class *const contextCls,	/* Context class; the currently considered
				 * class is equal to this, private methods may
				 * also be added. */
    Tcl_Obj *const methodName,	/* Name of method to add the call chain
				 * entries for. */
    struct ChainBuilder *const cbPtr,
				/* Where to add the call chain entries. */
    ChainBuilder *const cbPtr,	/* Where to add the call chain entries. */
    Tcl_HashTable *const doneFilters,
				/* Where to record what call chain entries
				 * have been processed. */
    int flags,			/* What sort of call chain are we building. */
    Class *const filterDecl)	/* The class that declared the filter. If
				 * NULL, either the filter was declared by the
				 * object or this isn't a filter. */
{
    int i;
    Tcl_Size i;
    Class *superPtr;

    /*
     * We hard-code the tail-recursive form. It's by far the most common case
     * *and* it is much more gentle on the stack.
     *
     * Note that mixins must be processed before the main class hierarchy.
     * [Bug 1998221]
     *
     * Note also that it's possible to end up with a null classPtr here if
     * there is a call into stereotypical object after it has finished running
     * its destructor phase. [Bug 7842f33a5c]
     */

  tailRecurse:
    if (classPtr == NULL) {
	return 0;
    }
    FOREACH(superPtr, classPtr->mixins) {
	if (AddPrivatesFromClassChainToCallContext(superPtr, contextCls,
		methodName, cbPtr, doneFilters, flags|TRAVERSED_MIXIN,
		filterDecl)) {
	    return 1;
	}
    }

    if (classPtr == contextCls) {
	Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&classPtr->classMethods,
		methodName);

	if (hPtr != NULL) {
	    Method *mPtr = (Method *)Tcl_GetHashValue(hPtr);
	    Method *mPtr = (Method *) Tcl_GetHashValue(hPtr);

	    if (IS_PRIVATE(mPtr)) {
		AddMethodToCallChain(mPtr, cbPtr, doneFilters, filterDecl,
			flags);
		return 1;
	    }
	}
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758


1759
1760
1761
1762
1763
1764
1765
1766
1767
1768

1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797

1798
1799
1800
1801
1802
1803

1804
1805
1806
1807
1808
1809
1810
1811







-
-
+








+
-
+











+
+
+














-
+





-
+








static int
AddSimpleClassChainToCallContext(
    Class *classPtr,		/* Class to add the call chain entries for. */
    Tcl_Obj *const methodNameObj,
				/* Name of method to add the call chain
				 * entries for. */
    struct ChainBuilder *const cbPtr,
				/* Where to add the call chain entries. */
    ChainBuilder *const cbPtr,	/* Where to add the call chain entries. */
    Tcl_HashTable *const doneFilters,
				/* Where to record what call chain entries
				 * have been processed. */
    int flags,			/* What sort of call chain are we building. */
    Class *const filterDecl)	/* The class that declared the filter. If
				 * NULL, either the filter was declared by the
				 * object or this isn't a filter. */
{
    Tcl_Size i;
    int i, privateDanger = 0;
    int privateDanger = 0;
    Class *superPtr;

    /*
     * We hard-code the tail-recursive form. It's by far the most common case
     * *and* it is much more gentle on the stack.
     *
     * Note that mixins must be processed before the main class hierarchy.
     * [Bug 1998221]
     */

  tailRecurse:
    if (classPtr == NULL) {
	return privateDanger;
    }
    FOREACH(superPtr, classPtr->mixins) {
	privateDanger |= AddSimpleClassChainToCallContext(superPtr,
		methodNameObj, cbPtr, doneFilters, flags | TRAVERSED_MIXIN,
		filterDecl);
    }

    if (flags & CONSTRUCTOR) {
	AddMethodToCallChain(classPtr->constructorPtr, cbPtr, doneFilters,
		filterDecl, flags);
    } else if (flags & DESTRUCTOR) {
	AddMethodToCallChain(classPtr->destructorPtr, cbPtr, doneFilters,
		filterDecl, flags);
    } else {
	Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&classPtr->classMethods,
		(char *) methodNameObj);
		methodNameObj);

	if (classPtr->flags & HAS_PRIVATE_METHODS) {
	    privateDanger |= 1;
	}
	if (hPtr != NULL) {
	    Method *mPtr = (Method *)Tcl_GetHashValue(hPtr);
	    Method *mPtr = (Method *) Tcl_GetHashValue(hPtr);

	    if (!IS_PRIVATE(mPtr)) {
		if (!(flags & KNOWN_STATE)) {
		    if (flags & PUBLIC_METHOD) {
			if (!IS_PUBLIC(mPtr)) {
			    return privateDanger;
			}
1790
1791
1792
1793
1794
1795
1796
1797

1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823

1824

1825
1826

1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841


1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854




1855
1856
1857
1858
1859
1860
1861
1850
1851
1852
1853
1854
1855
1856

1857
1858
1859
1860
1861
1862
1863

1864

1865

1866

1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880

1881
1882

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







-
+






-

-

-

-













+
-
+

-
+














-
+
+









-
-
-
-
+
+
+
+







TclOORenderCallChain(
    Tcl_Interp *interp,
    CallChain *callPtr)
{
    Tcl_Obj *filterLiteral, *methodLiteral, *objectLiteral, *privateLiteral;
    Tcl_Obj *resultObj, *descObjs[4], **objv;
    Foundation *fPtr = TclOOGetFoundation(interp);
    int i;
    Tcl_Size i;

    /*
     * Allocate the literals (potentially) used in our description.
     */

    TclNewLiteralStringObj(filterLiteral, "filter");
    Tcl_IncrRefCount(filterLiteral);
    TclNewLiteralStringObj(methodLiteral, "method");
    Tcl_IncrRefCount(methodLiteral);
    TclNewLiteralStringObj(objectLiteral, "object");
    Tcl_IncrRefCount(objectLiteral);
    TclNewLiteralStringObj(privateLiteral, "private");
    Tcl_IncrRefCount(privateLiteral);

    /*
     * Do the actual construction of the descriptions. They consist of a list
     * of triples that describe the details of how a method is understood. For
     * each triple, the first word is the type of invocation ("method" is
     * normal, "unknown" is special because it adds the method name as an
     * extra argument when handled by some method types, and "filter" is
     * special because it's a filter method). The second word is the name of
     * the method in question (which differs for "unknown" and "filter" types)
     * and the third word is the full name of the class that declares the
     * method (or "object" if it is declared on the instance).
     */

    objv = (Tcl_Obj **)
    objv = (Tcl_Obj **)TclStackAlloc(interp, callPtr->numChain * sizeof(Tcl_Obj *));
	    TclStackAlloc(interp, callPtr->numChain * sizeof(Tcl_Obj *));
    for (i = 0 ; i < callPtr->numChain ; i++) {
	struct MInvoke *miPtr = &callPtr->chain[i];
	MInvoke *miPtr = &callPtr->chain[i];

	descObjs[0] =
	    miPtr->isFilter ? filterLiteral :
	    callPtr->flags & OO_UNKNOWN_METHOD ? fPtr->unknownMethodNameObj :
	    IS_PRIVATE(miPtr->mPtr) ? privateLiteral :
		    methodLiteral;
	descObjs[1] =
	    callPtr->flags & CONSTRUCTOR ? fPtr->constructorName :
	    callPtr->flags & DESTRUCTOR ? fPtr->destructorName :
		    miPtr->mPtr->namePtr;
	descObjs[2] = miPtr->mPtr->declaringClassPtr
		? Tcl_GetObjectName(interp,
			(Tcl_Object) miPtr->mPtr->declaringClassPtr->thisPtr)
		: objectLiteral;
	descObjs[3] = Tcl_NewStringObj(miPtr->mPtr->typePtr->name, -1);
	descObjs[3] = Tcl_NewStringObj(miPtr->mPtr->typePtr->name,
		TCL_AUTO_LENGTH);

	objv[i] = Tcl_NewListObj(4, descObjs);
    }

    /*
     * Drop the local references to the literals; if they're actually used,
     * they'll live on the description itself.
     */

    Tcl_DecrRefCount(filterLiteral);
    Tcl_DecrRefCount(methodLiteral);
    Tcl_DecrRefCount(objectLiteral);
    Tcl_DecrRefCount(privateLiteral);
    Tcl_BounceRefCount(filterLiteral);
    Tcl_BounceRefCount(methodLiteral);
    Tcl_BounceRefCount(objectLiteral);
    Tcl_BounceRefCount(privateLiteral);

    /*
     * Finish building the description and return it.
     */

    resultObj = Tcl_NewListObj(callPtr->numChain, objv);
    TclStackFree(interp, objv);
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
1951
1952
1953
1954
1955
1956
1957

1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968


1969
1970
1971
1972
1973
1974
1975
1976
1977







-
+










-
-
+
+







				 * [oo::define], otherwise, we are going to
				 * use this for [oo::objdefine]. */
{
    DefineChain define;
    DefineEntry staticSpace[DEFINE_CHAIN_STATIC_SIZE];
    DefineEntry *entryPtr;
    Tcl_Namespace *nsPtr = NULL;
    int i;
    int i, flags = (forClass ? DEFINE_FOR_CLASS : 0);

    define.list = staticSpace;
    define.num = 0;
    define.size = DEFINE_CHAIN_STATIC_SIZE;

    /*
     * Add the actual define locations. We have to do this twice to handle
     * class mixins right.
     */

    AddSimpleDefineNamespaces(oPtr, &define, forClass | BUILDING_MIXINS);
    AddSimpleDefineNamespaces(oPtr, &define, forClass);
    AddSimpleDefineNamespaces(oPtr, &define, flags | BUILDING_MIXINS);
    AddSimpleDefineNamespaces(oPtr, &define, flags);

    /*
     * Go through the list until we find a namespace whose name we can
     * resolve.
     */

    FOREACH_STRUCT(entryPtr, define) {
1946
1947
1948
1949
1950
1951
1952
1953

1954
1955
1956
1957
1958
1959
1960
2004
2005
2006
2007
2008
2009
2010

2011
2012
2013
2014
2015
2016
2017
2018







-
+







    Object *const oPtr,		/* Object to add define chain entries for. */
    DefineChain *const definePtr,
				/* Where to add the define chain entries. */
    int flags)			/* What sort of define chain are we
				 * building. */
{
    Class *mixinPtr;
    int i;
    Tcl_Size i;

    FOREACH(mixinPtr, oPtr->mixins) {
	AddSimpleClassDefineNamespaces(mixinPtr, definePtr,
		flags | TRAVERSED_MIXIN);
    }

    AddSimpleClassDefineNamespaces(oPtr->selfCls, definePtr, flags);
1975
1976
1977
1978
1979
1980
1981
1982

1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996

1997
1998
1999
2000
2001
2002
2003
2033
2034
2035
2036
2037
2038
2039

2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053

2054
2055
2056
2057
2058
2059
2060
2061







-
+













-
+







AddSimpleClassDefineNamespaces(
    Class *classPtr,		/* Class to add the define chain entries for. */
    DefineChain *const definePtr,
				/* Where to add the define chain entries. */
    int flags)			/* What sort of define chain are we
				 * building. */
{
    int i;
    Tcl_Size i;
    Class *superPtr;

    /*
     * We hard-code the tail-recursive form. It's by far the most common case
     * *and* it is much more gentle on the stack.
     */

  tailRecurse:
    FOREACH(superPtr, classPtr->mixins) {
	AddSimpleClassDefineNamespaces(superPtr, definePtr,
		flags | TRAVERSED_MIXIN);
    }

    if (flags & ~(TRAVERSED_MIXIN | BUILDING_MIXINS)) {
    if (flags & DEFINE_FOR_CLASS) {
	AddDefinitionNamespaceToChain(classPtr, classPtr->clsDefinitionNs,
		definePtr, flags);
    } else {
	AddDefinitionNamespaceToChain(classPtr, classPtr->objDefinitionNs,
		definePtr, flags);
    }

2023
2024
2025
2026
2027
2028
2029
2030
2031



2032
2033
2034
2035
2036
2037
2038
2081
2082
2083
2084
2085
2086
2087


2088
2089
2090
2091
2092
2093
2094
2095
2096
2097







-
-
+
+
+







 *	reallocating the space for the chain if necessary.
 *
 * ----------------------------------------------------------------------
 */

static inline void
AddDefinitionNamespaceToChain(
    Class *const definerCls,		/* What class defines this entry. */
    Tcl_Obj *const namespaceName,	/* The name for this entry (or NULL, a
    Class *const definerCls,	/* What class defines this entry. */
    Tcl_Obj *const namespaceName,
				/* The name for this entry (or NULL, a
				 * no-op). */
    DefineChain *const definePtr,
				/* The define chain to add the method
				 * implementation to. */
    int flags)			/* Used to check if we're mixin-consistent
				 * only. Mixin-consistent means that either
				 * we're looking to add things from a mixin
2084
2085
2086
2087
2088
2089
2090
2091
2092


2093
2094
2095
2096

2097
2098
2099
2100
2101
2102
2103
2143
2144
2145
2146
2147
2148
2149


2150
2151
2152
2153
2154

2155
2156
2157
2158
2159
2160
2161
2162







-
-
+
+



-
+







     */

    if (definePtr->num == definePtr->size) {
	definePtr->size *= 2;
	if (definePtr->num == DEFINE_CHAIN_STATIC_SIZE) {
	    DefineEntry *staticList = definePtr->list;

	    definePtr->list =
		    (DefineEntry *)Tcl_Alloc(sizeof(DefineEntry) * definePtr->size);
	    definePtr->list = (DefineEntry *)
		    Tcl_Alloc(sizeof(DefineEntry) * definePtr->size);
	    memcpy(definePtr->list, staticList,
		    sizeof(DefineEntry) * definePtr->num);
	} else {
	    definePtr->list = (DefineEntry *)Tcl_Realloc(definePtr->list,
	    definePtr->list = (DefineEntry *) Tcl_Realloc(definePtr->list,
		    sizeof(DefineEntry) * definePtr->size);
	}
    }
    definePtr->list[i].definerCls = definerCls;
    definePtr->list[i].namespaceName = namespaceName;
    definePtr->num++;
}

Changes to generic/tclOODecls.h.

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
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







-
-
+
+










-
+

















-
-
+
+

















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







TCLAPI Tcl_Method	Tcl_NewMethod(Tcl_Interp *interp, Tcl_Class cls,
				Tcl_Obj *nameObj, int flags,
				const Tcl_MethodType *typePtr,
				void *clientData);
/* 13 */
TCLAPI Tcl_Object	Tcl_NewObjectInstance(Tcl_Interp *interp,
				Tcl_Class cls, const char *nameStr,
				const char *nsNameStr, int objc,
				Tcl_Obj *const *objv, int skip);
				const char *nsNameStr, Tcl_Size objc,
				Tcl_Obj *const *objv, Tcl_Size skip);
/* 14 */
TCLAPI int		Tcl_ObjectDeleted(Tcl_Object object);
/* 15 */
TCLAPI int		Tcl_ObjectContextIsFiltering(
				Tcl_ObjectContext context);
/* 16 */
TCLAPI Tcl_Method	Tcl_ObjectContextMethod(Tcl_ObjectContext context);
/* 17 */
TCLAPI Tcl_Object	Tcl_ObjectContextObject(Tcl_ObjectContext context);
/* 18 */
TCLAPI int		Tcl_ObjectContextSkippedArgs(
TCLAPI Tcl_Size		Tcl_ObjectContextSkippedArgs(
				Tcl_ObjectContext context);
/* 19 */
TCLAPI void *		Tcl_ClassGetMetadata(Tcl_Class clazz,
				const Tcl_ObjectMetadataType *typePtr);
/* 20 */
TCLAPI void		Tcl_ClassSetMetadata(Tcl_Class clazz,
				const Tcl_ObjectMetadataType *typePtr,
				void *metadata);
/* 21 */
TCLAPI void *		Tcl_ObjectGetMetadata(Tcl_Object object,
				const Tcl_ObjectMetadataType *typePtr);
/* 22 */
TCLAPI void		Tcl_ObjectSetMetadata(Tcl_Object object,
				const Tcl_ObjectMetadataType *typePtr,
				void *metadata);
/* 23 */
TCLAPI int		Tcl_ObjectContextInvokeNext(Tcl_Interp *interp,
				Tcl_ObjectContext context, int objc,
				Tcl_Obj *const *objv, int skip);
				Tcl_ObjectContext context, Tcl_Size objc,
				Tcl_Obj *const *objv, Tcl_Size skip);
/* 24 */
TCLAPI Tcl_ObjectMapMethodNameProc * Tcl_ObjectGetMethodNameMapper(
				Tcl_Object object);
/* 25 */
TCLAPI void		Tcl_ObjectSetMethodNameMapper(Tcl_Object object,
				Tcl_ObjectMapMethodNameProc *mapMethodNameProc);
/* 26 */
TCLAPI void		Tcl_ClassSetConstructor(Tcl_Interp *interp,
				Tcl_Class clazz, Tcl_Method method);
/* 27 */
TCLAPI void		Tcl_ClassSetDestructor(Tcl_Interp *interp,
				Tcl_Class clazz, Tcl_Method method);
/* 28 */
TCLAPI Tcl_Obj *	Tcl_GetObjectName(Tcl_Interp *interp,
				Tcl_Object object);
/* 29 */
TCLAPI int		Tcl_MethodIsPrivate(Tcl_Method method);
/* 30 */
TCLAPI Tcl_Class	Tcl_GetClassOfObject(Tcl_Object object);
/* 31 */
TCLAPI Tcl_Obj *	Tcl_GetObjectClassName(Tcl_Interp *interp,
				Tcl_Object object);
/* 32 */
TCLAPI int		Tcl_MethodIsType2(Tcl_Method method,
				const Tcl_MethodType2 *typePtr,
				void **clientDataPtr);
/* 33 */
TCLAPI Tcl_Method	Tcl_NewInstanceMethod2(Tcl_Interp *interp,
				Tcl_Object object, Tcl_Obj *nameObj,
				int flags, const Tcl_MethodType2 *typePtr,
				void *clientData);
/* 34 */
TCLAPI Tcl_Method	Tcl_NewMethod2(Tcl_Interp *interp, Tcl_Class cls,
				Tcl_Obj *nameObj, int flags,
				const Tcl_MethodType2 *typePtr,
				void *clientData);

typedef struct {
    const struct TclOOIntStubs *tclOOIntStubs;
} TclOOStubHooks;

typedef struct TclOOStubs {
    int magic;
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
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







-
+




-
+




-
+






+
+
+
+
+







    Tcl_Class (*tcl_MethodDeclarerClass) (Tcl_Method method); /* 6 */
    Tcl_Object (*tcl_MethodDeclarerObject) (Tcl_Method method); /* 7 */
    int (*tcl_MethodIsPublic) (Tcl_Method method); /* 8 */
    int (*tcl_MethodIsType) (Tcl_Method method, const Tcl_MethodType *typePtr, void **clientDataPtr); /* 9 */
    Tcl_Obj * (*tcl_MethodName) (Tcl_Method method); /* 10 */
    Tcl_Method (*tcl_NewInstanceMethod) (Tcl_Interp *interp, Tcl_Object object, Tcl_Obj *nameObj, int flags, const Tcl_MethodType *typePtr, void *clientData); /* 11 */
    Tcl_Method (*tcl_NewMethod) (Tcl_Interp *interp, Tcl_Class cls, Tcl_Obj *nameObj, int flags, const Tcl_MethodType *typePtr, void *clientData); /* 12 */
    Tcl_Object (*tcl_NewObjectInstance) (Tcl_Interp *interp, Tcl_Class cls, const char *nameStr, const char *nsNameStr, int objc, Tcl_Obj *const *objv, int skip); /* 13 */
    Tcl_Object (*tcl_NewObjectInstance) (Tcl_Interp *interp, Tcl_Class cls, const char *nameStr, const char *nsNameStr, Tcl_Size objc, Tcl_Obj *const *objv, Tcl_Size skip); /* 13 */
    int (*tcl_ObjectDeleted) (Tcl_Object object); /* 14 */
    int (*tcl_ObjectContextIsFiltering) (Tcl_ObjectContext context); /* 15 */
    Tcl_Method (*tcl_ObjectContextMethod) (Tcl_ObjectContext context); /* 16 */
    Tcl_Object (*tcl_ObjectContextObject) (Tcl_ObjectContext context); /* 17 */
    int (*tcl_ObjectContextSkippedArgs) (Tcl_ObjectContext context); /* 18 */
    Tcl_Size (*tcl_ObjectContextSkippedArgs) (Tcl_ObjectContext context); /* 18 */
    void * (*tcl_ClassGetMetadata) (Tcl_Class clazz, const Tcl_ObjectMetadataType *typePtr); /* 19 */
    void (*tcl_ClassSetMetadata) (Tcl_Class clazz, const Tcl_ObjectMetadataType *typePtr, void *metadata); /* 20 */
    void * (*tcl_ObjectGetMetadata) (Tcl_Object object, const Tcl_ObjectMetadataType *typePtr); /* 21 */
    void (*tcl_ObjectSetMetadata) (Tcl_Object object, const Tcl_ObjectMetadataType *typePtr, void *metadata); /* 22 */
    int (*tcl_ObjectContextInvokeNext) (Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv, int skip); /* 23 */
    int (*tcl_ObjectContextInvokeNext) (Tcl_Interp *interp, Tcl_ObjectContext context, Tcl_Size objc, Tcl_Obj *const *objv, Tcl_Size skip); /* 23 */
    Tcl_ObjectMapMethodNameProc * (*tcl_ObjectGetMethodNameMapper) (Tcl_Object object); /* 24 */
    void (*tcl_ObjectSetMethodNameMapper) (Tcl_Object object, Tcl_ObjectMapMethodNameProc *mapMethodNameProc); /* 25 */
    void (*tcl_ClassSetConstructor) (Tcl_Interp *interp, Tcl_Class clazz, Tcl_Method method); /* 26 */
    void (*tcl_ClassSetDestructor) (Tcl_Interp *interp, Tcl_Class clazz, Tcl_Method method); /* 27 */
    Tcl_Obj * (*tcl_GetObjectName) (Tcl_Interp *interp, Tcl_Object object); /* 28 */
    int (*tcl_MethodIsPrivate) (Tcl_Method method); /* 29 */
    Tcl_Class (*tcl_GetClassOfObject) (Tcl_Object object); /* 30 */
    Tcl_Obj * (*tcl_GetObjectClassName) (Tcl_Interp *interp, Tcl_Object object); /* 31 */
    int (*tcl_MethodIsType2) (Tcl_Method method, const Tcl_MethodType2 *typePtr, void **clientDataPtr); /* 32 */
    Tcl_Method (*tcl_NewInstanceMethod2) (Tcl_Interp *interp, Tcl_Object object, Tcl_Obj *nameObj, int flags, const Tcl_MethodType2 *typePtr, void *clientData); /* 33 */
    Tcl_Method (*tcl_NewMethod2) (Tcl_Interp *interp, Tcl_Class cls, Tcl_Obj *nameObj, int flags, const Tcl_MethodType2 *typePtr, void *clientData); /* 34 */
} TclOOStubs;

extern const TclOOStubs *tclOOStubsPtr;

#ifdef __cplusplus
}
#endif
227
228
229
230
231
232
233










234
235
236
237
238










239
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







+
+
+
+
+
+
+
+
+
+





+
+
+
+
+
+
+
+
+
+

	(tclOOStubsPtr->tcl_ClassSetConstructor) /* 26 */
#define Tcl_ClassSetDestructor \
	(tclOOStubsPtr->tcl_ClassSetDestructor) /* 27 */
#define Tcl_GetObjectName \
	(tclOOStubsPtr->tcl_GetObjectName) /* 28 */
#define Tcl_MethodIsPrivate \
	(tclOOStubsPtr->tcl_MethodIsPrivate) /* 29 */
#define Tcl_GetClassOfObject \
	(tclOOStubsPtr->tcl_GetClassOfObject) /* 30 */
#define Tcl_GetObjectClassName \
	(tclOOStubsPtr->tcl_GetObjectClassName) /* 31 */
#define Tcl_MethodIsType2 \
	(tclOOStubsPtr->tcl_MethodIsType2) /* 32 */
#define Tcl_NewInstanceMethod2 \
	(tclOOStubsPtr->tcl_NewInstanceMethod2) /* 33 */
#define Tcl_NewMethod2 \
	(tclOOStubsPtr->tcl_NewMethod2) /* 34 */

#endif /* defined(USE_TCLOO_STUBS) */

/* !END!: Do not edit above this line. */

#if TCL_MAJOR_VERSION < 9
    /* TIP #630 for 8.7 */
#   undef Tcl_MethodIsType2
#   define Tcl_MethodIsType2 Tcl_MethodIsType
#   undef Tcl_NewInstanceMethod2
#   define Tcl_NewInstanceMethod2 Tcl_NewInstanceMethod
#   undef Tcl_NewMethod2
#   define Tcl_NewMethod2 Tcl_NewMethod
#endif

#endif /* _TCLOODECLS */

Changes to generic/tclOODefineCmds.c.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tclOODefineCmds.c --
 *
 *	This file contains the implementation of the ::oo::define command,
 *	part of the object-system core (NB: not Tcl_Obj, but ::oo).
 *
 * Copyright (c) 2006-2013 by Donal K. Fellows
 * Copyright © 2006-2019 Donal K. Fellows
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
28
29
30
31
32
33
34
35
36

37
38
39
40
41

42
43
44
45
46
47
48
28
29
30
31
32
33
34


35
36
37
38
39

40
41
42
43
44
45
46
47







-
-
+




-
+







 */

#define OBJNAME_LENGTH_IN_ERRORINFO_LIMIT 30

/*
 * Some things that make it easier to declare a slot.
 */

struct DeclaredSlot {
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},				\
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
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







+


















-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


+
+
+
+
+
+
+
+
+
-
+


-
+


-
+


-
+


-
+


-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+







-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







#define PUBLIC_PATTERN		"[a-z]*"

/*
 * Forward declarations.
 */

static inline void	BumpGlobalEpoch(Tcl_Interp *interp, Class *classPtr);
static inline void	BumpInstanceEpoch(Object *oPtr);
static Tcl_Command	FindCommand(Tcl_Interp *interp, Tcl_Obj *stringObj,
			    Tcl_Namespace *const namespacePtr);
static inline void	GenerateErrorInfo(Tcl_Interp *interp, Object *oPtr,
			    Tcl_Obj *savedNameObj, const char *typeOfSubject);
static inline int	MagicDefinitionInvoke(Tcl_Interp *interp,
			    Tcl_Namespace *nsPtr, int cmdIndex,
			    int objc, Tcl_Obj *const *objv);
static inline Class *	GetClassInOuterContext(Tcl_Interp *interp,
			    Tcl_Obj *className, const char *errMsg);
static inline Tcl_Namespace *GetNamespaceInOuterContext(Tcl_Interp *interp,
			    Tcl_Obj *namespaceName);
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		ClassFilterGet(ClientData clientData,
static int		ClassFilter_Get(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassFilterSet(ClientData clientData,
static int		ClassFilter_Set(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassMixinGet(ClientData clientData,
static int		ClassMixin_Get(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassMixinSet(ClientData clientData,
static int		ClassMixin_Set(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassSuperGet(ClientData clientData,
static int		ClassSuper_Get(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassSuperSet(ClientData clientData,
static int		ClassSuper_Set(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassVarsGet(ClientData clientData,
static int		ClassVars_Get(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassVarsSet(ClientData clientData,
static int		ClassVars_Set(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjFilter_Get(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjFilter_Set(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjMixin_Get(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjFilterGet(ClientData clientData,
static int		ObjMixin_Set(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjFilterSet(ClientData clientData,
static int		ObjVars_Get(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjMixinGet(ClientData clientData,
static int		ObjVars_Set(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjMixinSet(ClientData clientData,
static int		Configurable_ClassReadableProps_Get(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjVarsGet(ClientData clientData,
static int		Configurable_ClassReadableProps_Set(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjVarsSet(ClientData clientData,
static int		Configurable_ClassWritableProps_Get(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		Configurable_ClassWritableProps_Set(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		Configurable_ObjectReadableProps_Get(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		Configurable_ObjectReadableProps_Set(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		Configurable_ObjectWritableProps_Get(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		Configurable_ObjectWritableProps_Set(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ResolveClass(ClientData clientData,
static int		ResolveClass(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);

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

static const struct DeclaredSlot slots[] = {
    SLOT("define::filter",      ClassFilterGet, ClassFilterSet, NULL),
    SLOT("define::mixin",       ClassMixinGet,  ClassMixinSet, ResolveClass),
    SLOT("define::superclass",  ClassSuperGet,  ClassSuperSet, ResolveClass),
    SLOT("define::variable",    ClassVarsGet,   ClassVarsSet, NULL),
    SLOT("objdefine::filter",   ObjFilterGet,   ObjFilterSet, NULL),
    SLOT("objdefine::mixin",    ObjMixinGet,    ObjMixinSet, ResolveClass),
    SLOT("objdefine::variable", ObjVarsGet,     ObjVarsSet, NULL),
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().
 */
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+






-
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	 * invalidate any call chains. Note that we still bump our object's
	 * epoch if it has any mixins; the relation between a class and its
	 * representative object is special. But it won't hurt.
	 */

	if (classPtr->thisPtr->mixins.num > 0) {
	    classPtr->thisPtr->epoch++;

	    /*
	     * Invalidate the property caches directly.
	     */

	    if (classPtr->properties.allReadableCache) {
		Tcl_DecrRefCount(classPtr->properties.allReadableCache);
		classPtr->properties.allReadableCache = NULL;
	    }
	    if (classPtr->properties.allWritableCache) {
		Tcl_DecrRefCount(classPtr->properties.allWritableCache);
		classPtr->properties.allWritableCache = NULL;
	    }
	}
	return;
    }

    /*
     * Either there's no class (?!) or we're reconfiguring something that is
     * in use. Force regeneration of call chains.
     * in use. Force regeneration of call chains and properties.
     */

    TclOOGetFoundation(interp)->epoch++;
}

/*
 * ----------------------------------------------------------------------
 *
 * BumpInstanceEpoch --
 *
 *	Advances the epoch and clears the property cache of an object. The
 *	equivalent for classes is BumpGlobalEpoch(), as classes have a more
 *	complex set of relationships to other entities.
 *
 * ----------------------------------------------------------------------
 */

static inline void
BumpInstanceEpoch(
    Object *oPtr)
{
    oPtr->epoch++;
    if (oPtr->properties.allReadableCache) {
	Tcl_DecrRefCount(oPtr->properties.allReadableCache);
	oPtr->properties.allReadableCache = NULL;
    }
    if (oPtr->properties.allWritableCache) {
	Tcl_DecrRefCount(oPtr->properties.allWritableCache);
	oPtr->properties.allWritableCache = NULL;
    }
}

/*
 * ----------------------------------------------------------------------
 *
 * RecomputeClassCacheFlag --
 *
 *	Determine whether the object is prototypical of its class, and hence
245
246
247
248
249
250
251
252

253
254
255

256
257
258
259
260
261
262
321
322
323
324
325
326
327

328
329
330

331
332
333
334
335
336
337
338







-
+


-
+







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

void
TclOOObjectSetFilters(
    Object *oPtr,
    int numFilters,
    Tcl_Size numFilters,
    Tcl_Obj *const *filters)
{
    int i;
    Tcl_Size i;

    if (oPtr->filters.num) {
	Tcl_Obj *filterObj;

	FOREACH(filterObj, oPtr->filters) {
	    Tcl_DecrRefCount(filterObj);
	}
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
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







-
+


-
+

-
+









-
+
















-
+


-
+







	RecomputeClassCacheFlag(oPtr);
    } else {
	/*
	 * We've got a list of filters, so we're creating filters.
	 */

	Tcl_Obj **filtersList;
	int size = sizeof(Tcl_Obj *) * numFilters;	/* should be size_t */
	size_t size = sizeof(Tcl_Obj *) * numFilters;

	if (oPtr->filters.num == 0) {
	    filtersList = (Tcl_Obj **)Tcl_Alloc(size);
	    filtersList = (Tcl_Obj **) Tcl_Alloc(size);
	} else {
	    filtersList = (Tcl_Obj **)Tcl_Realloc(oPtr->filters.list, size);
	    filtersList = (Tcl_Obj **) Tcl_Realloc(oPtr->filters.list, size);
	}
	for (i = 0 ; i < numFilters ; i++) {
	    filtersList[i] = filters[i];
	    Tcl_IncrRefCount(filters[i]);
	}
	oPtr->filters.list = filtersList;
	oPtr->filters.num = numFilters;
	oPtr->flags &= ~USE_CLASS_CACHE;
    }
    oPtr->epoch++;		/* Only this object can be affected. */
    BumpInstanceEpoch(oPtr);	// Only this object can be affected.
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOClassSetFilters --
 *
 *	Install a list of filter method names into a class.
 *
 * ----------------------------------------------------------------------
 */

void
TclOOClassSetFilters(
    Tcl_Interp *interp,
    Class *classPtr,
    int numFilters,
    Tcl_Size numFilters,
    Tcl_Obj *const *filters)
{
    int i;
    Tcl_Size i;

    if (classPtr->filters.num) {
	Tcl_Obj *filterObj;

	FOREACH(filterObj, classPtr->filters) {
	    Tcl_DecrRefCount(filterObj);
	}
332
333
334
335
336
337
338
339

340
341
342

343
344


345
346
347
348
349
350
351
408
409
410
411
412
413
414

415
416
417

418
419

420
421
422
423
424
425
426
427
428







-
+


-
+

-
+
+







	classPtr->filters.num = 0;
    } else {
	/*
	 * We've got a list of filters, so we're creating filters.
	 */

	Tcl_Obj **filtersList;
	int size = sizeof(Tcl_Obj *) * numFilters;	/* should be size_t */
	size_t size = sizeof(Tcl_Obj *) * numFilters;

	if (classPtr->filters.num == 0) {
	    filtersList = (Tcl_Obj **)Tcl_Alloc(size);
	    filtersList = (Tcl_Obj **) Tcl_Alloc(size);
	} else {
	    filtersList = (Tcl_Obj **)Tcl_Realloc(classPtr->filters.list, size);
	    filtersList = (Tcl_Obj **)
		    Tcl_Realloc(classPtr->filters.list, size);
	}
	for (i = 0 ; i < numFilters ; i++) {
	    filtersList[i] = filters[i];
	    Tcl_IncrRefCount(filters[i]);
	}
	classPtr->filters.list = filtersList;
	classPtr->filters.num = numFilters;
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
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
444
445
446
447
448
449
450

451
452
453
454

455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474

475
476
477

478
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







-
+



-
+



















-
+


-
+
+
















-
+
















-
+



-
+
















-
-
+
+
+

-
+
+







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

void
TclOOObjectSetMixins(
    Object *oPtr,
    int numMixins,
    Tcl_Size numMixins,
    Class *const *mixins)
{
    Class *mixinPtr;
    int i;
    Tcl_Size i;

    if (numMixins == 0) {
	if (oPtr->mixins.num != 0) {
	    FOREACH(mixinPtr, oPtr->mixins) {
		TclOORemoveFromInstances(oPtr, mixinPtr);
		TclOODecrRefCount(mixinPtr->thisPtr);
	    }
	    Tcl_Free(oPtr->mixins.list);
	    oPtr->mixins.num = 0;
	}
	RecomputeClassCacheFlag(oPtr);
    } else {
	if (oPtr->mixins.num != 0) {
	    FOREACH(mixinPtr, oPtr->mixins) {
		if (mixinPtr && mixinPtr != oPtr->selfCls) {
		    TclOORemoveFromInstances(oPtr, mixinPtr);
		}
		TclOODecrRefCount(mixinPtr->thisPtr);
	    }
	    oPtr->mixins.list = (Class **)Tcl_Realloc(oPtr->mixins.list,
	    oPtr->mixins.list = (Class **) Tcl_Realloc(oPtr->mixins.list,
		    sizeof(Class *) * numMixins);
	} else {
	    oPtr->mixins.list = (Class **)Tcl_Alloc(sizeof(Class *) * numMixins);
	    oPtr->mixins.list = (Class **)
		    Tcl_Alloc(sizeof(Class *) * numMixins);
	    oPtr->flags &= ~USE_CLASS_CACHE;
	}
	oPtr->mixins.num = numMixins;
	memcpy(oPtr->mixins.list, mixins, sizeof(Class *) * numMixins);
	FOREACH(mixinPtr, oPtr->mixins) {
	    if (mixinPtr != oPtr->selfCls) {
		TclOOAddToInstances(oPtr, mixinPtr);

		/*
		 * For the new copy created by memcpy().
		 */

		AddRef(mixinPtr->thisPtr);
	    }
	}
    }
    oPtr->epoch++;
    BumpInstanceEpoch(oPtr);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOClassSetMixins --
 *
 *	Install a list of mixin classes into a class.
 *
 * ----------------------------------------------------------------------
 */

void
TclOOClassSetMixins(
    Tcl_Interp *interp,
    Class *classPtr,
    int numMixins,
    Tcl_Size numMixins,
    Class *const *mixins)
{
    Class *mixinPtr;
    int i;
    Tcl_Size i;

    if (numMixins == 0) {
	if (classPtr->mixins.num != 0) {
	    FOREACH(mixinPtr, classPtr->mixins) {
		TclOORemoveFromMixinSubs(classPtr, mixinPtr);
		TclOODecrRefCount(mixinPtr->thisPtr);
	    }
	    Tcl_Free(classPtr->mixins.list);
	    classPtr->mixins.num = 0;
	}
    } else {
	if (classPtr->mixins.num != 0) {
	    FOREACH(mixinPtr, classPtr->mixins) {
		TclOORemoveFromMixinSubs(classPtr, mixinPtr);
		TclOODecrRefCount(mixinPtr->thisPtr);
	    }
	    classPtr->mixins.list = (Class **)Tcl_Realloc(classPtr->mixins.list,
		    sizeof(Class *) * numMixins);
	    classPtr->mixins.list = (Class **)
		    Tcl_Realloc(classPtr->mixins.list,
			    sizeof(Class *) * numMixins);
	} else {
	    classPtr->mixins.list = (Class **)Tcl_Alloc(sizeof(Class *) * numMixins);
	    classPtr->mixins.list = (Class **)
		    Tcl_Alloc(sizeof(Class *) * numMixins);
	}
	classPtr->mixins.num = numMixins;
	memcpy(classPtr->mixins.list, mixins, sizeof(Class *) * numMixins);
	FOREACH(mixinPtr, classPtr->mixins) {
	    TclOOAddToMixinSubs(classPtr, mixinPtr);

	    /*
478
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



558
559


560
561
562
563
564
565
566
558
559
560
561
562
563
564
565
566
567
568

569
570
571
572
573

574
575
576
577
578
579
580
581
582
583
584
585
586
587

588
589

590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611

612
613
614
615
616
617
618
619
620

621
622
623
624
625
626

627
628
629
630
631
632
633
634
635
636
637
638
639
640


641
642
643
644

645
646
647
648
649
650
651
652
653







+



-
+



+
-
+












+
-
+

-
+




















+
-
+








-
+




+
-
+













-
-
+
+
+

-
+
+







 *
 * InstallStandardVariableMapping, InstallPrivateVariableMapping --
 *
 *	Helpers for installing standard and private variable maps.
 *
 * ----------------------------------------------------------------------
 */

static inline void
InstallStandardVariableMapping(
    VariableNameList *vnlPtr,
    int varc,
    Tcl_Size varc,
    Tcl_Obj *const *varv)
{
    Tcl_Obj *variableObj;
    Tcl_Size i, n;
    int i, n, created;
    int created;
    Tcl_HashTable uniqueTable;

    for (i=0 ; i<varc ; i++) {
	Tcl_IncrRefCount(varv[i]);
    }
    FOREACH(variableObj, *vnlPtr) {
	Tcl_DecrRefCount(variableObj);
    }
    if (i != varc) {
	if (varc == 0) {
	    Tcl_Free(vnlPtr->list);
	} else if (i) {
	    vnlPtr->list = (Tcl_Obj **)
	    vnlPtr->list = (Tcl_Obj **)Tcl_Realloc(vnlPtr->list, sizeof(Tcl_Obj *) * varc);
		    Tcl_Realloc(vnlPtr->list, sizeof(Tcl_Obj *) * varc);
	} else {
	    vnlPtr->list = (Tcl_Obj **)Tcl_Alloc(sizeof(Tcl_Obj *) * varc);
	    vnlPtr->list = (Tcl_Obj **) Tcl_Alloc(sizeof(Tcl_Obj *) * varc);
	}
    }
    vnlPtr->num = 0;
    if (varc > 0) {
	Tcl_InitObjHashTable(&uniqueTable);
	for (i=n=0 ; i<varc ; i++) {
	    Tcl_CreateHashEntry(&uniqueTable, varv[i], &created);
	    if (created) {
		vnlPtr->list[n++] = varv[i];
	    } else {
		Tcl_DecrRefCount(varv[i]);
	    }
	}
	vnlPtr->num = n;

	/*
	 * Shouldn't be necessary, but maintain num/list invariant.
	 */

	if (n != varc) {
	    vnlPtr->list = (Tcl_Obj **)
	    vnlPtr->list = (Tcl_Obj **)Tcl_Realloc(vnlPtr->list, sizeof(Tcl_Obj *) * n);
		    Tcl_Realloc(vnlPtr->list, sizeof(Tcl_Obj *) * n);
	}
	Tcl_DeleteHashTable(&uniqueTable);
    }
}

static inline void
InstallPrivateVariableMapping(
    PrivateVariableList *pvlPtr,
    int varc,
    Tcl_Size varc,
    Tcl_Obj *const *varv,
    int creationEpoch)
{
    PrivateVariableMapping *privatePtr;
    Tcl_Size i, n;
    int i, n, created;
    int created;
    Tcl_HashTable uniqueTable;

    for (i=0 ; i<varc ; i++) {
	Tcl_IncrRefCount(varv[i]);
    }
    FOREACH_STRUCT(privatePtr, *pvlPtr) {
	Tcl_DecrRefCount(privatePtr->variableObj);
	Tcl_DecrRefCount(privatePtr->fullNameObj);
    }
    if (i != varc) {
	if (varc == 0) {
	    Tcl_Free(pvlPtr->list);
	} else if (i) {
	    pvlPtr->list = (PrivateVariableMapping *)Tcl_Realloc(pvlPtr->list,
		    sizeof(PrivateVariableMapping) * varc);
	    pvlPtr->list = (PrivateVariableMapping *)
		    Tcl_Realloc(pvlPtr->list,
			    sizeof(PrivateVariableMapping) * varc);
	} else {
	    pvlPtr->list = (PrivateVariableMapping *)Tcl_Alloc(sizeof(PrivateVariableMapping) * varc);
	    pvlPtr->list = (PrivateVariableMapping *)
		    Tcl_Alloc(sizeof(PrivateVariableMapping) * varc);
	}
    }

    pvlPtr->num = 0;
    if (varc > 0) {
	Tcl_InitObjHashTable(&uniqueTable);
	for (i=n=0 ; i<varc ; i++) {
579
580
581
582
583
584
585
586

587
588
589
590
591
592
593
666
667
668
669
670
671
672

673
674
675
676
677
678
679
680







-
+







	pvlPtr->num = n;

	/*
	 * Shouldn't be necessary, but maintain num/list invariant.
	 */

	if (n != varc) {
	    pvlPtr->list = (PrivateVariableMapping *)Tcl_Realloc(pvlPtr->list,
	    pvlPtr->list = (PrivateVariableMapping *) Tcl_Realloc(pvlPtr->list,
		    sizeof(PrivateVariableMapping) * n);
	}
	Tcl_DeleteHashTable(&uniqueTable);
    }
}

/*
614
615
616
617
618
619
620
621

622
623
624

625
626
627
628
629

630
631
632
633
634
635


636
637
638
639
640
641
642

643
644
645
646
647

648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667

668
669
670
671
672
673
674
701
702
703
704
705
706
707

708
709
710

711
712
713
714
715

716
717
718
719
720


721
722
723
724
725
726
727
728

729
730
731
732
733

734

735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752

753
754
755
756
757
758
759
760







-
+


-
+




-
+




-
-
+
+






-
+




-
+
-


















-
+








    if (!useClass) {
	if (!oPtr->methodsPtr) {
	noSuchMethod:
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "method %s does not exist", TclGetString(fromPtr)));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
		    TclGetString(fromPtr), NULL);
		    TclGetString(fromPtr), (char *)NULL);
	    return TCL_ERROR;
	}
	hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) fromPtr);
	hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, fromPtr);
	if (hPtr == NULL) {
	    goto noSuchMethod;
	}
	if (toPtr) {
	    newHPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, (char *) toPtr,
	    newHPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, toPtr,
		    &isNew);
	    if (hPtr == newHPtr) {
	    renameToSelf:
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"cannot rename method to itself", -1));
		Tcl_SetErrorCode(interp, "TCL", "OO", "RENAME_TO_SELF", NULL);
			"cannot rename method to itself", TCL_AUTO_LENGTH));
		Tcl_SetErrorCode(interp, "TCL", "OO", "RENAME_TO_SELF", (char *)NULL);
		return TCL_ERROR;
	    } else if (!isNew) {
	    renameToExisting:
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"method called %s already exists",
			TclGetString(toPtr)));
		Tcl_SetErrorCode(interp, "TCL", "OO", "RENAME_OVER", NULL);
		Tcl_SetErrorCode(interp, "TCL", "OO", "RENAME_OVER", (char *)NULL);
		return TCL_ERROR;
	    }
	}
    } else {
	hPtr = Tcl_FindHashEntry(&oPtr->classPtr->classMethods,
	hPtr = Tcl_FindHashEntry(&oPtr->classPtr->classMethods, fromPtr);
		(char *) fromPtr);
	if (hPtr == NULL) {
	    goto noSuchMethod;
	}
	if (toPtr) {
	    newHPtr = Tcl_CreateHashEntry(&oPtr->classPtr->classMethods,
		    (char *) toPtr, &isNew);
	    if (hPtr == newHPtr) {
		goto renameToSelf;
	    } else if (!isNew) {
		goto renameToExisting;
	    }
	}
    }

    /*
     * Complete the splicing by changing the method's name.
     */

    mPtr = (Method *)Tcl_GetHashValue(hPtr);
    mPtr = (Method *) Tcl_GetHashValue(hPtr);
    if (toPtr) {
	Tcl_IncrRefCount(toPtr);
	Tcl_DecrRefCount(mPtr->namePtr);
	mPtr->namePtr = toPtr;
	Tcl_SetHashValue(newHPtr, mPtr);
    } else {
	if (!useClass) {
691
692
693
694
695
696
697
698

699
700
701
702
703
704

705
706
707


708
709
710
711
712


713
714
715
716
717
718
719
720
721
722
723

724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745

746
747
748
749
750
751
752
753
754
755
756
757
758
759

760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780

781
782
783
784
785
786
787
777
778
779
780
781
782
783

784
785
786
787
788
789

790



791
792
793
794
795


796
797
798
799
800
801
802
803
804
805
806
807

808



809
810
811
812
813
814

815
816
817
818
819
820
821
822
823
824
825

826
827
828
829
830
831
832
833
834
835
836
837
838
839

840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860

861
862
863
864
865
866
867
868







-
+





-
+
-
-
-
+
+



-
-
+
+










-
+
-
-
-






-











-
+













-
+




















-
+







 *	prefix of.
 *
 * ----------------------------------------------------------------------
 */

int
TclOOUnknownDefinition(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Namespace *nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
    Tcl_HashSearch search;
    FOREACH_HASH_DECLS;
    Tcl_HashEntry *hPtr;
    size_t soughtLen;
    const char *soughtStr, *matchedStr = NULL;
    Tcl_Size soughtLen;
    const char *soughtStr, *nameStr, *matchedStr = NULL;

    if (objc < 2) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"bad call of unknown handler", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_UNKNOWN", NULL);
		"bad call of unknown handler", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_UNKNOWN", (char *)NULL);
	return TCL_ERROR;
    }
    if (TclOOGetDefineCmdContext(interp) == NULL) {
	return TCL_ERROR;
    }

    soughtStr = TclGetStringFromObj(objv[1], &soughtLen);
    if (soughtLen == 0) {
	goto noMatch;
    }
    hPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
    FOREACH_HASH_KEY(nameStr, &nsPtr->cmdTable) {
    while (hPtr != NULL) {
	const char *nameStr = (const char *)Tcl_GetHashKey(&nsPtr->cmdTable, hPtr);

	if (strncmp(soughtStr, nameStr, soughtLen) == 0) {
	    if (matchedStr != NULL) {
		goto noMatch;
	    }
	    matchedStr = nameStr;
	}
	hPtr = Tcl_NextHashEntry(&search);
    }

    if (matchedStr != NULL) {
	/*
	 * Got one match, and only one match!
	 */

	Tcl_Obj **newObjv = (Tcl_Obj **)
		TclStackAlloc(interp, sizeof(Tcl_Obj*) * (objc - 1));
	int result;

	newObjv[0] = Tcl_NewStringObj(matchedStr, -1);
	newObjv[0] = Tcl_NewStringObj(matchedStr, TCL_AUTO_LENGTH);
	Tcl_IncrRefCount(newObjv[0]);
	if (objc > 2) {
	    memcpy(newObjv + 1, objv + 2, sizeof(Tcl_Obj *) * (objc - 2));
	}
	result = Tcl_EvalObjv(interp, objc - 1, newObjv, 0);
	Tcl_DecrRefCount(newObjv[0]);
	TclStackFree(interp, newObjv);
	return result;
    }

  noMatch:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "invalid command name \"%s\"", soughtStr));
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", soughtStr, NULL);
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", soughtStr, (char *)NULL);
    return TCL_ERROR;
}

/*
 * ----------------------------------------------------------------------
 *
 * FindCommand --
 *
 *	Specialized version of Tcl_FindCommand that handles command prefixes
 *	and disallows namespace magic.
 *
 * ----------------------------------------------------------------------
 */

static Tcl_Command
FindCommand(
    Tcl_Interp *interp,
    Tcl_Obj *stringObj,
    Tcl_Namespace *const namespacePtr)
{
    size_t length;
    Tcl_Size length;
    const char *nameStr, *string = TclGetStringFromObj(stringObj, &length);
    Namespace *const nsPtr = (Namespace *) namespacePtr;
    FOREACH_HASH_DECLS;
    Tcl_Command cmd, cmd2;

    /*
     * If someone is playing games, we stop playing right now.
841
842
843
844
845
846
847
848
849


850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869

870
871
872
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
898


899
900
901
902

















903
904
905
906
907
908
909
922
923
924
925
926
927
928


929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949

950
951
952
953
954
955
956
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







-
-
+
+



















-
+



















-
-
+
+
+


-
+



-
-
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    int objc,
    Tcl_Obj *const objv[])
{
    CallFrame *framePtr, **framePtrPtr = &framePtr;

    if (namespacePtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"no definition namespace available", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
		"no definition namespace available", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * framePtrPtr is needed to satisfy GCC 3.3's strict aliasing rules.
     */

    (void) TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr,
	    namespacePtr, FRAME_IS_OO_DEFINE);
    framePtr->clientData = oPtr;
    framePtr->objc = objc;
    framePtr->objv = objv;	/* Reference counts do not need to be
				 * incremented here. */
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOGetDefineCmdContext --
 * TclOOGetDefineCmdContext, TclOOGetClassDefineCmdContext --
 *
 *	Extracts the magic token from the current stack frame, or returns NULL
 *	(and leaves an error message) otherwise.
 *
 * ----------------------------------------------------------------------
 */

Tcl_Object
TclOOGetDefineCmdContext(
    Tcl_Interp *interp)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Object object;

    if ((iPtr->varFramePtr == NULL)
	    || (iPtr->varFramePtr->isProcCallFrame != FRAME_IS_OO_DEFINE
	    && iPtr->varFramePtr->isProcCallFrame != PRIVATE_FRAME)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"this command may only be called from within the context of"
		" an ::oo::define or ::oo::objdefine command", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
		" an ::oo::define or ::oo::objdefine command",
		TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	return NULL;
    }
    object = (Tcl_Object)iPtr->varFramePtr->clientData;
    object = (Tcl_Object) iPtr->varFramePtr->clientData;
    if (Tcl_ObjectDeleted(object)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"this command cannot be called when the object has been"
		" deleted", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
		" deleted", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	return NULL;
    }
    return object;
}

Class *
TclOOGetClassDefineCmdContext(
    Tcl_Interp *interp)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    if (oPtr == NULL) {
	return NULL;
    }
    if (!oPtr->classPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
	return NULL;
    }
    return oPtr->classPtr;
}

/*
 * ----------------------------------------------------------------------
 *
 * GetClassInOuterContext, GetNamespaceInOuterContext --
 *
 *	Wrappers round Tcl_GetObjectFromObj and TclGetNamespaceFromObj to
933
934
935
936
937
938
939
940

941
942

943
944
945
946
947
948
949
1032
1033
1034
1035
1036
1037
1038

1039
1040

1041
1042
1043
1044
1045
1046
1047
1048







-
+

-
+







    }
    oPtr = (Object *) Tcl_GetObjectFromObj(interp, className);
    iPtr->varFramePtr = savedFramePtr;
    if (oPtr == NULL) {
	return NULL;
    }
    if (oPtr->classPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, -1));
	Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS",
		TclGetString(className), NULL);
		TclGetString(className), (char *)NULL);
	return NULL;
    }
    return oPtr->classPtr;
}

static inline Tcl_Namespace *
GetNamespaceInOuterContext(
992
993
994
995
996
997
998
999

1000
1001
1002
1003

1004
1005
1006
1007
1008

1009
1010
1011
1012
1013
1014
1015
1091
1092
1093
1094
1095
1096
1097

1098
1099
1100
1101

1102
1103
1104
1105
1106

1107
1108
1109
1110
1111
1112
1113
1114







-
+



-
+




-
+







				 * current name (post-execution) has to be
				 * used. This matters, because the object
				 * could have been renamed... */
    const char *typeOfSubject)	/* Part of the message, saying whether it was
				 * an object, class or class-as-object that
				 * was being configured. */
{
    size_t length;
    Tcl_Size length;
    Tcl_Obj *realNameObj = Tcl_ObjectDeleted((Tcl_Object) oPtr)
	    ? savedNameObj : TclOOObjectName(interp, oPtr);
    const char *objName = TclGetStringFromObj(realNameObj, &length);
    unsigned limit = OBJNAME_LENGTH_IN_ERRORINFO_LIMIT;
    int limit = OBJNAME_LENGTH_IN_ERRORINFO_LIMIT;
    int overflow = (length > limit);

    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
	    "\n    (in definition script for %s \"%.*s%s\" line %d)",
	    typeOfSubject, (overflow ? limit : (unsigned)length), objName,
	    typeOfSubject, (overflow ? limit : (int) length), objName,
	    (overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
}

/*
 * ----------------------------------------------------------------------
 *
 * MagicDefinitionInvoke --
1028
1029
1030
1031
1032
1033
1034
1035


1036
1037
1038
1039
1040
1041
1042
1127
1128
1129
1130
1131
1132
1133

1134
1135
1136
1137
1138
1139
1140
1141
1142







-
+
+







    Tcl_Namespace *nsPtr,
    int cmdIndex,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *objPtr, *obj2Ptr, **objs;
    Tcl_Command cmd;
    int isRoot, dummy, result, offset = cmdIndex + 1;
    int isRoot, result, offset = cmdIndex + 1;
    Tcl_Size dummy;

    /*
     * More than one argument: fire them through the ensemble processing
     * engine so that everything appears to be good and proper in error
     * messages. Note that we cannot just concatenate and send through
     * Tcl_EvalObjEx, as that doesn't do ensemble processing, and we cannot go
     * through Tcl_EvalObjv without the extra work to pre-find the command, as
1059
1060
1061
1062
1063
1064
1065
1066

1067
1068

1069
1070
1071
1072
1073
1074
1075
1159
1160
1161
1162
1163
1164
1165

1166
1167

1168
1169
1170
1171
1172
1173
1174
1175







-
+

-
+







	 */

	Tcl_AppendObjToObj(obj2Ptr, objv[cmdIndex]);
    } else {
	Tcl_GetCommandFullName(interp, cmd, obj2Ptr);
    }
    Tcl_ListObjAppendElement(NULL, objPtr, obj2Ptr);
    /* TODO: overflow? */
    // TODO: overflow?
    Tcl_ListObjReplace(NULL, objPtr, 1, 0, objc - offset, objv + offset);
    Tcl_ListObjGetElements(NULL, objPtr, &dummy, &objs);
    TclListObjGetElements(NULL, objPtr, &dummy, &objs);

    result = Tcl_EvalObjv(interp, objc - cmdIndex, objs, TCL_EVAL_INVOKE);
    if (isRoot) {
	TclResetRewriteEnsemble(interp, 1);
    }
    Tcl_DecrRefCount(objPtr);

1088
1089
1090
1091
1092
1093
1094
1095

1096
1097
1098
1099
1100
1101
1102
1188
1189
1190
1191
1192
1193
1194

1195
1196
1197
1198
1199
1200
1201
1202







-
+







 *	messages are clearer.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Namespace *nsPtr;
    Object *oPtr;
    int result;
1110
1111
1112
1113
1114
1115
1116
1117

1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137

1138
1139
1140
1141
1142
1143
1144
1210
1211
1212
1213
1214
1215
1216

1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236

1237
1238
1239
1240
1241
1242
1243
1244







-
+



















-
+







    if (oPtr == NULL) {
	return TCL_ERROR;
    }
    if (oPtr->classPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"%s does not refer to a class", TclGetString(objv[1])));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS",
		TclGetString(objv[1]), NULL);
		TclGetString(objv[1]), (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Make the oo::define namespace the current namespace and evaluate the
     * command(s).
     */

    nsPtr = TclOOGetDefineContextNamespace(interp, oPtr, 1);
    if (InitDefineContext(interp, nsPtr, oPtr, objc, objv) != TCL_OK) {
	return TCL_ERROR;
    }

    AddRef(oPtr);
    if (objc == 3) {
	Tcl_Obj *objNameObj = TclOOObjectName(interp, oPtr);

	Tcl_IncrRefCount(objNameObj);
	result = TclEvalObjEx(interp, objv[2], 0,
		((Interp *)interp)->cmdFramePtr, 2);
		((Interp *) interp)->cmdFramePtr, 2);
	if (result == TCL_ERROR) {
	    GenerateErrorInfo(interp, oPtr, objNameObj, "class");
	}
	TclDecrRefCount(objNameObj);
    } else {
	result = MagicDefinitionInvoke(interp, nsPtr, 2, objc, objv);
    }
1164
1165
1166
1167
1168
1169
1170
1171

1172
1173
1174
1175
1176
1177
1178
1264
1265
1266
1267
1268
1269
1270

1271
1272
1273
1274
1275
1276
1277
1278







-
+







 *	messages are clearer.
 *
 * ----------------------------------------------------------------------
 */

int
TclOOObjDefObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Namespace *nsPtr;
    Object *oPtr;
    int result;
1199
1200
1201
1202
1203
1204
1205
1206

1207
1208
1209
1210
1211
1212
1213
1299
1300
1301
1302
1303
1304
1305

1306
1307
1308
1309
1310
1311
1312
1313







-
+








    AddRef(oPtr);
    if (objc == 3) {
	Tcl_Obj *objNameObj = TclOOObjectName(interp, oPtr);

	Tcl_IncrRefCount(objNameObj);
	result = TclEvalObjEx(interp, objv[2], 0,
		((Interp *)interp)->cmdFramePtr, 2);
		((Interp *) interp)->cmdFramePtr, 2);
	if (result == TCL_ERROR) {
	    GenerateErrorInfo(interp, oPtr, objNameObj, "object");
	}
	TclDecrRefCount(objNameObj);
    } else {
	result = MagicDefinitionInvoke(interp, nsPtr, 2, objc, objv);
    }
1233
1234
1235
1236
1237
1238
1239
1240

1241
1242
1243
1244
1245
1246
1247
1333
1334
1335
1336
1337
1338
1339

1340
1341
1342
1343
1344
1345
1346
1347







-
+







 *	dispatch so that error messages are clearer.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineSelfObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Namespace *nsPtr;
    Object *oPtr;
    int result, isPrivate;
1273
1274
1275
1276
1277
1278
1279
1280

1281
1282
1283
1284
1285
1286
1287
1373
1374
1375
1376
1377
1378
1379

1380
1381
1382
1383
1384
1385
1386
1387







-
+








    AddRef(oPtr);
    if (objc == 2) {
	Tcl_Obj *objNameObj = TclOOObjectName(interp, oPtr);

	Tcl_IncrRefCount(objNameObj);
	result = TclEvalObjEx(interp, objv[1], 0,
		((Interp *)interp)->cmdFramePtr, 1);
		((Interp *) interp)->cmdFramePtr, 1);
	if (result == TCL_ERROR) {
	    GenerateErrorInfo(interp, oPtr, objNameObj, "class object");
	}
	TclDecrRefCount(objNameObj);
    } else {
	result = MagicDefinitionInvoke(interp, nsPtr, 1, objc, objv);
    }
1304
1305
1306
1307
1308
1309
1310
1311

1312
1313
1314
1315
1316
1317
1318
1404
1405
1406
1407
1408
1409
1410

1411
1412
1413
1414
1415
1416
1417
1418







-
+







 *	command.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineObjSelfObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr;

    if (objc != 1) {
1338
1339
1340
1341
1342
1343
1344
1345

1346
1347
1348
1349
1350
1351
1352
1438
1439
1440
1441
1442
1443
1444

1445
1446
1447
1448
1449
1450
1451
1452







-
+







 *	and "oo::objdefine" commands.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefinePrivateObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int isInstancePrivate = (clientData != NULL);
				/* Just so that we can generate the correct
				 * error message depending on the context of
1411
1412
1413
1414
1415
1416
1417
1418

1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439



1440
1441
1442
1443
1444
1445



1446
1447
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
1511
1512
1513
1514
1515
1516
1517

1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537


1538
1539
1540
1541
1542
1543
1544


1545
1546
1547
1548
1549
1550
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







-
+



















-
-
+
+
+




-
-
+
+
+


















-
-
+
+
+







 *	command.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineClassObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr;
    Class *clsPtr;
    Foundation *fPtr = TclOOGetFoundation(interp);
    int wasClass, willBeClass;

    /*
     * Parse the context to get the object to operate on.
     */

    oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    if (oPtr == NULL) {
	return TCL_ERROR;
    }
    if (oPtr->flags & ROOT_OBJECT) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"may not modify the class of the root object class", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
		"may not modify the class of the root object class",
		TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	return TCL_ERROR;
    }
    if (oPtr->flags & ROOT_CLASS) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"may not modify the class of the class of classes", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
		"may not modify the class of the class of classes",
		TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Parse the argument to get the class to set the object's class to.
     */

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "className");
	return TCL_ERROR;
    }
    clsPtr = GetClassInOuterContext(interp, objv[1],
	    "the class of an object must be a class");
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }
    if (oPtr == clsPtr->thisPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"may not change classes into an instance of themselves", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
		"may not change classes into an instance of themselves",
		TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Set the object's class.
     */

1501
1502
1503
1504
1505
1506
1507
1508

1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527

1528
1529
1530
1531
1532
1533

1534
1535

1536


1537

1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553

1554
1555
1556
1557
1558
1559
1560
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







-
+


















-
+




-
-
+

-
+

+
+
-
+




-
-
-
-
-
-
-
-
-
-
-
-
+







	} else if (!wasClass && willBeClass) {
	    TclOOAllocClass(interp, oPtr);
	}

	if (oPtr->classPtr != NULL) {
	    BumpGlobalEpoch(interp, oPtr->classPtr);
	} else {
	    oPtr->epoch++;
	    BumpInstanceEpoch(oPtr);
	}
    }
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOODefineConstructorObjCmd --
 *
 *	Implementation of the "constructor" subcommand of the "oo::define"
 *	command.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineConstructorObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr;
    Class *clsPtr;
    Class *clsPtr = TclOOGetClassDefineCmdContext(interp);
    Tcl_Method method;
    size_t bodyLength;
    Tcl_Size bodyLength;

    if (clsPtr == NULL) {
	return TCL_ERROR;
    if (objc != 3) {
    } else if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "arguments body");
	return TCL_ERROR;
    }

    /*
     * Extract and validate the context, which is the class that we wish to
     * modify.
     */

    oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    if (oPtr == NULL) {
	return TCL_ERROR;
    }
    clsPtr = oPtr->classPtr;

    (void)TclGetStringFromObj(objv[2], &bodyLength);
    (void) TclGetStringFromObj(objv[2], &bodyLength);
    if (bodyLength > 0) {
	/*
	 * Create the method structure.
	 */

	method = (Tcl_Method) TclOONewProcMethod(interp, clsPtr,
		PUBLIC_METHOD, NULL, objv[1], objv[2], NULL);
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
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







-
+










-
+



-
-
+

-
-
-
-
-
-
-
-
+


-
-
+
+







 *	"oo::define" command.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineDefnNsObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    static const char *kindList[] = {
	"-class",
	"-instance",
	NULL
    };
    int kind = 0;
    Object *oPtr;
    Class *clsPtr = TclOOGetClassDefineCmdContext(interp);
    Tcl_Namespace *nsPtr;
    Tcl_Obj *nsNamePtr, **storagePtr;

    oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    if (oPtr == NULL) {
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }
    if (!oPtr->classPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
	return TCL_ERROR;
    }
    if (oPtr->flags & (ROOT_OBJECT | ROOT_CLASS)) {
    } else if (clsPtr->thisPtr->flags & (ROOT_OBJECT | ROOT_CLASS)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"may not modify the definition namespace of the root classes",
		-1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
		TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Parse the arguments and work out what the user wants to do.
     */

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
1726
1727
1728
1729
1730
1731
1732

1733
1734
1735
1736
1737
1738
1739
1740
1741

1742
1743

1744
1745
1746
1747
1748
1749
1750
1751







-
+








-
+

-
+







    if (!TclGetString(objv[objc - 1])[0]) {
	nsNamePtr = NULL;
    } else {
	nsPtr = GetNamespaceInOuterContext(interp, objv[objc - 1]);
	if (nsPtr == NULL) {
	    return TCL_ERROR;
	}
	nsNamePtr = Tcl_NewStringObj(nsPtr->fullName, -1);
	nsNamePtr = TclNewNamespaceObj(nsPtr);
	Tcl_IncrRefCount(nsNamePtr);
    }

    /*
     * Update the correct field of the class definition.
     */

    if (kind) {
	storagePtr = &oPtr->classPtr->objDefinitionNs;
	storagePtr = &clsPtr->objDefinitionNs;
    } else {
	storagePtr = &oPtr->classPtr->clsDefinitionNs;
	storagePtr = &clsPtr->clsDefinitionNs;
    }
    if (*storagePtr != NULL) {
	Tcl_DecrRefCount(*storagePtr);
    }
    *storagePtr = nsNamePtr;
    return TCL_OK;
}
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

1749
1750
1751
1752
1753
1754
1755
1756

1757
1758
1759

1760
1761
1762
1763
1764
1765
1766
1759
1760
1761
1762
1763
1764
1765

1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785


1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802

1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822

1823
1824
1825
1826
1827


1828

1829
1830
1831
1832
1833

1834
1835
1836
1837
1838




1839



1840
1841
1842
1843
1844
1845
1846
1847







-
+



















-
-
+
+















-
+



















-
+




-
-

-
+
+

+
+
-
+




-
-
-
-
+
-
-
-
+







 *	and "oo::objdefine" commands.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineDeleteMethodObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int isInstanceDeleteMethod = (clientData != NULL);
    Object *oPtr;
    int i;

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

    oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    if (oPtr == NULL) {
	return TCL_ERROR;
    }
    if (!isInstanceDeleteMethod && !oPtr->classPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
		"attempt to misuse API", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	return TCL_ERROR;
    }

    for (i = 1; i < objc; i++) {
	/*
	 * Delete the method structure from the appropriate hash table.
	 */

	if (RenameDeleteMethod(interp, oPtr, !isInstanceDeleteMethod,
		objv[i], NULL) != TCL_OK) {
	    return TCL_ERROR;
	}
    }

    if (isInstanceDeleteMethod) {
	oPtr->epoch++;
	BumpInstanceEpoch(oPtr);
    } else {
	BumpGlobalEpoch(interp, oPtr->classPtr);
    }
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOODefineDestructorObjCmd --
 *
 *	Implementation of the "destructor" subcommand of the "oo::define"
 *	command.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineDestructorObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr;
    Class *clsPtr;
    Tcl_Method method;
    size_t bodyLength;
    Tcl_Size bodyLength;
    Class *clsPtr = TclOOGetClassDefineCmdContext(interp);

    if (clsPtr == NULL) {
	return TCL_ERROR;
    if (objc != 2) {
    } else if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "body");
	return TCL_ERROR;
    }

    oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    if (oPtr == NULL) {
	return TCL_ERROR;
    }

    clsPtr = oPtr->classPtr;

    (void)TclGetStringFromObj(objv[1], &bodyLength);
    (void) TclGetStringFromObj(objv[1], &bodyLength);
    if (bodyLength > 0) {
	/*
	 * Create the method structure.
	 */

	method = (Tcl_Method) TclOONewProcMethod(interp, clsPtr,
		PUBLIC_METHOD, NULL, NULL, objv[1], NULL);
1796
1797
1798
1799
1800
1801
1802
1803

1804
1805
1806
1807
1808
1809
1810
1877
1878
1879
1880
1881
1882
1883

1884
1885
1886
1887
1888
1889
1890
1891







-
+







 *	"oo::objdefine" commands.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineExportObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int isInstanceExport = (clientData != NULL);
    Object *oPtr;
    Method *mPtr;
1820
1821
1822
1823
1824
1825
1826
1827
1828


1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844


1845
1846
1847
1848

1849
1850
1851

1852
1853
1854
1855
1856

1857
1858
1859
1860
1861
1862
1863

1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878

1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899

1900
1901
1902
1903
1904
1905
1906
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
1958
1959

1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980

1981
1982
1983
1984
1985
1986
1987
1988







-
-
+
+















-
+
+



-
+


-
+




-
+






-
+














-
+




















-
+







    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", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
		"attempt to misuse API", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	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));
		oPtr->methodsPtr = (Tcl_HashTable *)
			Tcl_Alloc(sizeof(Tcl_HashTable));
		Tcl_InitObjHashTable(oPtr->methodsPtr);
		oPtr->flags &= ~USE_CLASS_CACHE;
	    }
	    hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, (char *)objv[i],
	    hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, objv[i],
		    &isNew);
	} else {
	    hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, (char *)objv[i],
	    hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, objv[i],
		    &isNew);
	}

	if (isNew) {
	    mPtr = (Method *)Tcl_Alloc(sizeof(Method));
	    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);
	    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.
     */

    if (changed) {
	if (isInstanceExport) {
	    oPtr->epoch++;
	    BumpInstanceEpoch(oPtr);
	} else {
	    BumpGlobalEpoch(interp, clsPtr);
	}
    }
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOODefineForwardObjCmd --
 *
 *	Implementation of the "forward" subcommand of the "oo::define" and
 *	"oo::objdefine" commands.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineForwardObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int isInstanceForward = (clientData != NULL);
    Object *oPtr;
    Method *mPtr;
1914
1915
1916
1917
1918
1919
1920
1921
1922


1923
1924
1925
1926
1927
1928
1929
1996
1997
1998
1999
2000
2001
2002


2003
2004
2005
2006
2007
2008
2009
2010
2011







-
-
+
+








    oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    if (oPtr == NULL) {
	return TCL_ERROR;
    }
    if (!isInstanceForward && !oPtr->classPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
		"attempt to misuse API", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	return TCL_ERROR;
    }
    isPublic = Tcl_StringMatch(TclGetString(objv[1]), PUBLIC_PATTERN)
	    ? PUBLIC_METHOD : 0;
    if (IsPrivateDefine(interp)) {
	isPublic = TRUE_PRIVATE_METHOD;
    }
1956
1957
1958
1959
1960
1961
1962
1963

1964
1965
1966
1967
1968
1969
1970
2038
2039
2040
2041
2042
2043
2044

2045
2046
2047
2048
2049
2050
2051
2052







-
+







 *	"oo::objdefine" commands.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineMethodObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    /*
     * Table of export modes for methods and their corresponding enum.
     */
1992
1993
1994
1995
1996
1997
1998
1999
2000


2001
2002
2003
2004
2005

2006
2007
2008
2009
2010
2011
2012
2074
2075
2076
2077
2078
2079
2080


2081
2082
2083
2084
2085
2086

2087
2088
2089
2090
2091
2092
2093
2094







-
-
+
+




-
+








    oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    if (oPtr == NULL) {
	return TCL_ERROR;
    }
    if (!isInstanceMethod && !oPtr->classPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
		"attempt to misuse API", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	return TCL_ERROR;
    }
    if (objc == 5) {
	if (Tcl_GetIndexFromObj(interp, objv[2], exportModes, "export flag",
		0, (int *) &exportMode) != TCL_OK) {
		0, &exportMode) != TCL_OK) {
	    return TCL_ERROR;
	}
	switch (exportMode) {
	case MODE_EXPORT:
	    isPublic = PUBLIC_METHOD;
	    break;
	case MODE_PRIVATE:
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
2095
2096

2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116

2117
2118
2119
2120
2121
2122
2123
2134
2135
2136
2137
2138
2139
2140

2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159


2160
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







-
+


















-
-
+
+
















-
+



















-
+







 *	and "oo::objdefine" commands.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineRenameMethodObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int isInstanceRenameMethod = (clientData != NULL);
    Object *oPtr;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "oldName newName");
	return TCL_ERROR;
    }

    oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    if (oPtr == NULL) {
	return TCL_ERROR;
    }
    if (!isInstanceRenameMethod && !oPtr->classPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
		"attempt to misuse API", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Delete the method entry from the appropriate hash table, and transfer
     * the thing it points to to its new entry. To do this, we first need to
     * get the entries from the appropriate hash tables (this can generate a
     * range of errors...)
     */

    if (RenameDeleteMethod(interp, oPtr, !isInstanceRenameMethod,
	    objv[1], objv[2]) != TCL_OK) {
	return TCL_ERROR;
    }

    if (isInstanceRenameMethod) {
	oPtr->epoch++;
	BumpInstanceEpoch(oPtr);
    } else {
	BumpGlobalEpoch(interp, oPtr->classPtr);
    }
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOODefineUnexportObjCmd --
 *
 *	Implementation of the "unexport" subcommand of the "oo::define" and
 *	"oo::objdefine" commands.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineUnexportObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int isInstanceUnexport = (clientData != NULL);
    Object *oPtr;
    Method *mPtr;
2133
2134
2135
2136
2137
2138
2139
2140
2141


2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157


2158
2159
2160
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
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

2273
2274
2275
2276
2277
2278
2279
2280







-
-
+
+















-
+
+



-
+


-
+




-
+






-
+













-
+







    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", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
		"attempt to misuse API", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	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));
		oPtr->methodsPtr = (Tcl_HashTable *)
			Tcl_Alloc(sizeof(Tcl_HashTable));
		Tcl_InitObjHashTable(oPtr->methodsPtr);
		oPtr->flags &= ~USE_CLASS_CACHE;
	    }
	    hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, (char *)objv[i],
	    hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, objv[i],
		    &isNew);
	} else {
	    hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, (char *)objv[i],
	    hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, objv[i],
		    &isNew);
	}

	if (isNew) {
	    mPtr = (Method *)Tcl_Alloc(sizeof(Method));
	    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);
	    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.
     */

    if (changed) {
	if (isInstanceUnexport) {
	    oPtr->epoch++;
	    BumpInstanceEpoch(oPtr);
	} else {
	    BumpGlobalEpoch(interp, clsPtr);
	}
    }
    return TCL_OK;
}

2261
2262
2263
2264
2265
2266
2267
2268
2269
2270




2271

2272
2273



2274

2275
2276
2277
2278
2279
2280
2281




2282
2283
2284



2285
2286
2287
2288
2289

2290
2291

2292
2293
2294

2295
2296
2297
2298
2299
2300



2301
2302
2303
2304
2305
2306
2307

2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397


2398
2399
2400
2401
2402
2403

2404
2405
2406

2407


2408

2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420

2421
2422
2423

2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434


2435
2436
2437
2438
2439
2440
2441


2442
2443






2444


2445

2446
2447
2448
2449
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
2489
2490
2491
2492
2493

2494
2495
2496
2497
2498
2499
2500
2501
2502
2503


2504
2505
2506
2507
2508
2509

2510
2511
2512

2513


2514

2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526

2527
2528
2529

2530
2531
2532
2533
2534
2535
2536
2537
2538
2539


2540
2541
2542
2543
2544
2545
2546



2547
2548
2549


2550

2551
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
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
2399
2400
2401
2402
2403


2404
2405
2406
2407
2408
2409
2410

2411
2412

2413
2414
2415
2416

2417
2418
2419
2420
2421








2422

2423

2424
2425
2426
2427
2428
2429
2430
2431


2432
2433
2434
2435
2436
2437
2438


2439
2440
2441
2442
2443
2444

2445
2446
2447
2448
2449
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
2489
2490
2491








2492

2493

2494
2495
2496
2497
2498
2499
2500
2501
2502
2503


2504
2505
2506
2507
2508
2509
2510


2511
2512
2513

2514
2515
2516
2517
2518
2519
2520
2521
2522

2523
2524
2525
2526
2527
2528
2529








2530

2531
2532
2533

2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551

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







-
-
-
+
+
+
+
-
+


+
+
+
-
+
-



-
-
-
+
+
+
+

-
-
+
+
+




-
+

-
+


-
+



-
-
-
+
+
+






-
+








-
-
+
+





-
+

-
+

+
+
-
+




-
-
-
-
-
-
-
-
+
-

-
+







-
-
+
+





-
-
+
+


+
+
-
+






-
-
-
-
-
-
-
-
+




-
+






-
+








-
-
+
+





-
+


-
+

+
+
-
+




-
-
-
-
-
-
-
-
+
-

-
+









-
-
+
+





-
-
+
+

-
+
+
+
+
+
+

+
+
-
+






-
-
-
-
-
-
-
-
+
-



-
+
+








+
+
+
+
+
+
+
+
-
+

-
-
+
+




-
+
+




+







-
+








-
-
+
+





-
+


-
+

+
+
-
+




-
-
-
-
-
-
-
-
+
-

-
+








-
-
+
+





-
-
+
+
+



+
+
-
+






-
+
-
-
-
-
-
-
-
+

-
-
+
+
+

-
+


















-
-
-
+
+
+

-
+














-
-
+
+



-
+

-
-
+
+
+







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

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

    if (object == NULL) {
	return TCL_ERROR;
    }
    slotCls = ((Object *) Tcl_NewObjectInstance(fPtr->interp, (Tcl_Class)
    slotCls = ((Object *) object)->classPtr;
	    fPtr->classCls, "::oo::Slot", NULL, -1, NULL, 0))->classPtr;
    if (slotCls == NULL) {
	return TCL_ERROR;
    }
    Tcl_IncrRefCount(getName);
    Tcl_IncrRefCount(setName);
    Tcl_IncrRefCount(resolveName);

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

	if (slotObject == NULL) {
	    continue;
	}
	Tcl_NewInstanceMethod(fPtr->interp, slotObject, getName, 0,
	TclNewInstanceMethod(interp, slotObject, getName, 0,
		&slotInfoPtr->getterType, NULL);
	Tcl_NewInstanceMethod(fPtr->interp, slotObject, setName, 0,
	TclNewInstanceMethod(interp, slotObject, setName, 0,
		&slotInfoPtr->setterType, NULL);
	if (slotInfoPtr->resolverType.callProc) {
	    Tcl_NewInstanceMethod(fPtr->interp, slotObject, resolveName, 0,
	    TclNewInstanceMethod(interp, slotObject, resolveName, 0,
		    &slotInfoPtr->resolverType, NULL);
	}
    }
    Tcl_DecrRefCount(getName);
    Tcl_DecrRefCount(setName);
    Tcl_DecrRefCount(resolveName);
    Tcl_BounceRefCount(getName);
    Tcl_BounceRefCount(setName);
    Tcl_BounceRefCount(resolveName);
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * ClassFilterGet, ClassFilterSet --
 * ClassFilter_Get, ClassFilter_Set --
 *
 *	Implementation of the "filter" slot accessors of the "oo::define"
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ClassFilterGet(
    TCL_UNUSED(ClientData),
ClassFilter_Get(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Class *clsPtr = TclOOGetClassDefineCmdContext(interp);
    Tcl_Obj *resultObj, *filterObj;
    int i;
    Tcl_Size i;

    if (clsPtr == NULL) {
	return TCL_ERROR;
    if (Tcl_ObjectContextSkippedArgs(context) != objc) {
    } else if (Tcl_ObjectContextSkippedArgs(context) != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		NULL);
	return TCL_ERROR;
    }
    if (oPtr == NULL) {
	return TCL_ERROR;
    } else if (!oPtr->classPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
	return TCL_ERROR;
    }


    TclNewObj(resultObj);
    FOREACH(filterObj, oPtr->classPtr->filters) {
    FOREACH(filterObj, clsPtr->filters) {
	Tcl_ListObjAppendElement(NULL, resultObj, filterObj);
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ClassFilterSet(
    TCL_UNUSED(ClientData),
ClassFilter_Set(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    int filterc;
    Class *clsPtr = TclOOGetClassDefineCmdContext(interp);
    Tcl_Size filterc;
    Tcl_Obj **filterv;

    if (clsPtr == NULL) {
	return TCL_ERROR;
    if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
    } else if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"filterList");
	return TCL_ERROR;
    }
    objv += Tcl_ObjectContextSkippedArgs(context);

    if (oPtr == NULL) {
	return TCL_ERROR;
    } else if (!oPtr->classPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
	return TCL_ERROR;
    } else if (Tcl_ListObjGetElements(interp, objv[0], &filterc,
    if (TclListObjGetElements(interp, objv[0], &filterc,
	    &filterv) != TCL_OK) {
	return TCL_ERROR;
    }

    TclOOClassSetFilters(interp, oPtr->classPtr, filterc, filterv);
    TclOOClassSetFilters(interp, clsPtr, filterc, filterv);
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * ClassMixinGet, ClassMixinSet --
 * ClassMixin_Get, ClassMixin_Set --
 *
 *	Implementation of the "mixin" slot accessors of the "oo::define"
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ClassMixinGet(
    TCL_UNUSED(ClientData),
ClassMixin_Get(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Class *clsPtr = TclOOGetClassDefineCmdContext(interp);
    Tcl_Obj *resultObj;
    Class *mixinPtr;
    int i;
    Tcl_Size i;

    if (clsPtr == NULL) {
	return TCL_ERROR;
    if (Tcl_ObjectContextSkippedArgs(context) != objc) {
    } else if (Tcl_ObjectContextSkippedArgs(context) != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		NULL);
	return TCL_ERROR;
    }
    if (oPtr == NULL) {
	return TCL_ERROR;
    } else if (!oPtr->classPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
	return TCL_ERROR;
    }


    TclNewObj(resultObj);
    FOREACH(mixinPtr, oPtr->classPtr->mixins) {
    FOREACH(mixinPtr, clsPtr->mixins) {
	Tcl_ListObjAppendElement(NULL, resultObj,
		TclOOObjectName(interp, mixinPtr->thisPtr));
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;

}

static int
ClassMixinSet(
    TCL_UNUSED(ClientData),
ClassMixin_Set(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    int mixinc, i;
    Class *clsPtr = TclOOGetClassDefineCmdContext(interp);
    Tcl_Size mixinc, i;
    Tcl_Obj **mixinv;
    Class **mixins;
    Class **mixins;		/* The references to the classes to actually
				 * install. */
    Tcl_HashTable uniqueCheck;	/* Note that this hash table is just used as a
				 * set of class references; it has no payload
				 * values and keys are always pointers. */
    int isNew;

    if (clsPtr == NULL) {
	return TCL_ERROR;
    if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
    } else if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"mixinList");
	return TCL_ERROR;
    }
    objv += Tcl_ObjectContextSkippedArgs(context);

    if (oPtr == NULL) {
	return TCL_ERROR;
    } else if (!oPtr->classPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
	return TCL_ERROR;
    } else if (Tcl_ListObjGetElements(interp, objv[0], &mixinc,
    if (TclListObjGetElements(interp, objv[0], &mixinc, &mixinv) != TCL_OK) {
	    &mixinv) != TCL_OK) {
	return TCL_ERROR;
    }

    mixins = (Class **)TclStackAlloc(interp, sizeof(Class *) * mixinc);
    mixins = (Class **) TclStackAlloc(interp, sizeof(Class *) * mixinc);
    Tcl_InitHashTable(&uniqueCheck, TCL_ONE_WORD_KEYS);

    for (i = 0; i < mixinc; i++) {
	mixins[i] = GetClassInOuterContext(interp, mixinv[i],
		"may only mix in classes");
	if (mixins[i] == NULL) {
	    i--;
	    goto freeAndError;
	}
	(void) Tcl_CreateHashEntry(&uniqueCheck, (void *) mixins[i], &isNew);
	if (!isNew) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "class should only be a direct mixin once",
		    TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "REPETITIOUS", (char *)NULL);
	    goto freeAndError;
	}
	if (TclOOIsReachable(oPtr->classPtr, mixins[i])) {
	if (TclOOIsReachable(clsPtr, mixins[i])) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "may not mix a class into itself", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "SELF_MIXIN", NULL);
		    "may not mix a class into itself", TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "SELF_MIXIN", (char *)NULL);
	    goto freeAndError;
	}
    }

    TclOOClassSetMixins(interp, oPtr->classPtr, mixinc, mixins);
    TclOOClassSetMixins(interp, clsPtr, mixinc, mixins);
    Tcl_DeleteHashTable(&uniqueCheck);
    TclStackFree(interp, mixins);
    return TCL_OK;

  freeAndError:
    Tcl_DeleteHashTable(&uniqueCheck);
    TclStackFree(interp, mixins);
    return TCL_ERROR;
}

/*
 * ----------------------------------------------------------------------
 *
 * ClassSuperGet, ClassSuperSet --
 * ClassSuper_Get, ClassSuper_Set --
 *
 *	Implementation of the "superclass" slot accessors of the "oo::define"
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ClassSuperGet(
    TCL_UNUSED(ClientData),
ClassSuper_Get(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Class *clsPtr = TclOOGetClassDefineCmdContext(interp);
    Tcl_Obj *resultObj;
    Class *superPtr;
    int i;
    Tcl_Size i;

    if (clsPtr == NULL) {
	return TCL_ERROR;
    if (Tcl_ObjectContextSkippedArgs(context) != objc) {
    } else if (Tcl_ObjectContextSkippedArgs(context) != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		NULL);
	return TCL_ERROR;
    }
    if (oPtr == NULL) {
	return TCL_ERROR;
    } else if (!oPtr->classPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
	return TCL_ERROR;
    }


    TclNewObj(resultObj);
    FOREACH(superPtr, oPtr->classPtr->superclasses) {
    FOREACH(superPtr, clsPtr->superclasses) {
	Tcl_ListObjAppendElement(NULL, resultObj,
		TclOOObjectName(interp, superPtr->thisPtr));
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ClassSuperSet(
    TCL_UNUSED(ClientData),
ClassSuper_Set(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    int superc, i, j;
    Class *clsPtr = TclOOGetClassDefineCmdContext(interp);
    Tcl_Size superc, j;
    Tcl_Size i;
    Tcl_Obj **superv;
    Class **superclasses, *superPtr;

    if (clsPtr == NULL) {
	return TCL_ERROR;
    if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
    } else if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"superclassList");
	return TCL_ERROR;
    }
    objv += Tcl_ObjectContextSkippedArgs(context);

    if (oPtr == NULL) {
    Foundation *fPtr = clsPtr->thisPtr->fPtr;
	return TCL_ERROR;
    } else if (!oPtr->classPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
	return TCL_ERROR;
    } else if (oPtr == oPtr->fPtr->objectCls->thisPtr) {
    if (clsPtr == fPtr->objectCls) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"may not modify the superclass of the root object", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
		"may not modify the superclass of the root object",
		TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	return TCL_ERROR;
    } else if (Tcl_ListObjGetElements(interp, objv[0], &superc,
    } else if (TclListObjGetElements(interp, objv[0], &superc,
	    &superv) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Allocate some working space.
     */

    superclasses = (Class **) Tcl_Alloc(sizeof(Class *) * superc);

    /*
     * Parse the arguments to get the class to use as superclasses.
     *
     * Note that zero classes is special, as it is equivalent to just the
     * class of objects. [Bug 9d61624b3d]
     */

    if (superc == 0) {
	superclasses = (Class **)Tcl_Realloc(superclasses, sizeof(Class *));
	if (TclOOIsReachable(oPtr->fPtr->classCls, oPtr->classPtr)) {
	    superclasses[0] = oPtr->fPtr->classCls;
	superclasses = (Class **) Tcl_Realloc(superclasses, sizeof(Class *));
	if (TclOOIsReachable(fPtr->classCls, clsPtr)) {
	    superclasses[0] = fPtr->classCls;
	} else {
	    superclasses[0] = oPtr->fPtr->objectCls;
	    superclasses[0] = fPtr->objectCls;
	}
	superc = 1;
	AddRef(superclasses[0]->thisPtr);
    } else {
	for (i = 0; i < superc; i++) {
	    superclasses[i] = GetClassInOuterContext(interp, superv[i],
		    "only a class can be a superclass");
	    if (superclasses[i] == NULL) {
		goto failedAfterAlloc;
	    }
	    for (j = 0; j < i; j++) {
		if (superclasses[j] == superclasses[i]) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "class should only be a direct superclass once",
			    -1));
		    Tcl_SetErrorCode(interp, "TCL", "OO", "REPETITIOUS",NULL);
			    TCL_AUTO_LENGTH));
		    Tcl_SetErrorCode(interp, "TCL", "OO", "REPETITIOUS",(char *)NULL);
		    goto failedAfterAlloc;
		}
	    }
	    if (TclOOIsReachable(oPtr->classPtr, superclasses[i])) {
	    if (TclOOIsReachable(clsPtr, superclasses[i])) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"attempt to form circular dependency graph", -1));
		Tcl_SetErrorCode(interp, "TCL", "OO", "CIRCULARITY", NULL);
			"attempt to form circular dependency graph",
			TCL_AUTO_LENGTH));
		Tcl_SetErrorCode(interp, "TCL", "OO", "CIRCULARITY", (char *)NULL);
	    failedAfterAlloc:
		for (; i-- > 0 ;) {
		    TclOODecrRefCount(superclasses[i]->thisPtr);
		}
		Tcl_Free(superclasses);
		return TCL_ERROR;
	    }
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
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







-
-
-
+
+
+


-
+

-
-
-
-
+
+
+
+

-
+







-
+








-
-
+
+





-
+

-
+

+
+
-
+




-
-
-
-
-
-
-
-





-
+





-
+








-
-
+
+





-
-
+
+
+

-

+
+
-
+






-
-
-
-
-
-
-
-
+
-










-
+






-
+





-
-
+
+

-
+







-
+








-
-
+
+







-
+


















-
-
+
+






-
+










-
+
-










-
+








-
-
+
+








-
+







    /*
     * Install the list of superclasses into the class. Note that this also
     * involves splicing the class out of the superclasses' subclass list that
     * it used to be a member of and splicing it into the new superclasses'
     * subclass list.
     */

    if (oPtr->classPtr->superclasses.num != 0) {
	FOREACH(superPtr, oPtr->classPtr->superclasses) {
	    TclOORemoveFromSubclasses(oPtr->classPtr, superPtr);
    if (clsPtr->superclasses.num != 0) {
	FOREACH(superPtr, clsPtr->superclasses) {
	    TclOORemoveFromSubclasses(clsPtr, superPtr);
	    TclOODecrRefCount(superPtr->thisPtr);
	}
	Tcl_Free(oPtr->classPtr->superclasses.list);
	Tcl_Free(clsPtr->superclasses.list);
    }
    oPtr->classPtr->superclasses.list = superclasses;
    oPtr->classPtr->superclasses.num = superc;
    FOREACH(superPtr, oPtr->classPtr->superclasses) {
	TclOOAddToSubclasses(oPtr->classPtr, superPtr);
    clsPtr->superclasses.list = superclasses;
    clsPtr->superclasses.num = superc;
    FOREACH(superPtr, clsPtr->superclasses) {
	TclOOAddToSubclasses(clsPtr, superPtr);
    }
    BumpGlobalEpoch(interp, oPtr->classPtr);
    BumpGlobalEpoch(interp, clsPtr);

    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * ClassVarsGet, ClassVarsSet --
 * ClassVars_Get, ClassVars_Set --
 *
 *	Implementation of the "variable" slot accessors of the "oo::define"
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ClassVarsGet(
    TCL_UNUSED(ClientData),
ClassVars_Get(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Class *clsPtr = TclOOGetClassDefineCmdContext(interp);
    Tcl_Obj *resultObj;
    int i;
    Tcl_Size i;

    if (clsPtr == NULL) {
	return TCL_ERROR;
    if (Tcl_ObjectContextSkippedArgs(context) != objc) {
    } else if (Tcl_ObjectContextSkippedArgs(context) != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		NULL);
	return TCL_ERROR;
    }
    if (oPtr == NULL) {
	return TCL_ERROR;
    } else if (!oPtr->classPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
	return TCL_ERROR;
    }

    TclNewObj(resultObj);
    if (IsPrivateDefine(interp)) {
	PrivateVariableMapping *privatePtr;

	FOREACH_STRUCT(privatePtr, oPtr->classPtr->privateVariables) {
	FOREACH_STRUCT(privatePtr, clsPtr->privateVariables) {
	    Tcl_ListObjAppendElement(NULL, resultObj, privatePtr->variableObj);
	}
    } else {
	Tcl_Obj *variableObj;

	FOREACH(variableObj, oPtr->classPtr->variables) {
	FOREACH(variableObj, clsPtr->variables) {
	    Tcl_ListObjAppendElement(NULL, resultObj, variableObj);
	}
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ClassVarsSet(
    TCL_UNUSED(ClientData),
ClassVars_Set(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    int varc;
    Class *clsPtr = TclOOGetClassDefineCmdContext(interp);
    Tcl_Size i;
    Tcl_Size varc;
    Tcl_Obj **varv;
    int i;

    if (clsPtr == NULL) {
	return TCL_ERROR;
    if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
    } else if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"filterList");
	return TCL_ERROR;
    }
    objv += Tcl_ObjectContextSkippedArgs(context);

    if (oPtr == NULL) {
	return TCL_ERROR;
    } else if (!oPtr->classPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
	return TCL_ERROR;
    } else if (Tcl_ListObjGetElements(interp, objv[0], &varc,
    if (TclListObjGetElements(interp, objv[0], &varc, &varv) != TCL_OK) {
	    &varv) != TCL_OK) {
	return TCL_ERROR;
    }

    for (i = 0; i < varc; i++) {
	const char *varName = TclGetString(varv[i]);

	if (strstr(varName, "::") != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "invalid declared variable name \"%s\": must not %s",
		    varName, "contain namespace separators"));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", (char *)NULL);
	    return TCL_ERROR;
	}
	if (Tcl_StringMatch(varName, "*(*)")) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "invalid declared variable name \"%s\": must not %s",
		    varName, "refer to an array element"));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", (char *)NULL);
	    return TCL_ERROR;
	}
    }

    if (IsPrivateDefine(interp)) {
	InstallPrivateVariableMapping(&oPtr->classPtr->privateVariables,
		varc, varv, oPtr->classPtr->thisPtr->creationEpoch);
	InstallPrivateVariableMapping(&clsPtr->privateVariables,
		varc, varv, clsPtr->thisPtr->creationEpoch);
    } else {
	InstallStandardVariableMapping(&oPtr->classPtr->variables, varc, varv);
	InstallStandardVariableMapping(&clsPtr->variables, varc, varv);
    }
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * ObjectFilterGet, ObjectFilterSet --
 * ObjFilter_Get, ObjFilter_Set --
 *
 *	Implementation of the "filter" slot accessors of the "oo::objdefine"
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ObjFilterGet(
    TCL_UNUSED(ClientData),
ObjFilter_Get(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Obj *resultObj, *filterObj;
    int i;
    Tcl_Size i;

    if (Tcl_ObjectContextSkippedArgs(context) != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		NULL);
	return TCL_ERROR;
    } else if (oPtr == NULL) {
	return TCL_ERROR;
    }

    TclNewObj(resultObj);
    FOREACH(filterObj, oPtr->filters) {
	Tcl_ListObjAppendElement(NULL, resultObj, filterObj);
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ObjFilterSet(
    TCL_UNUSED(ClientData),
ObjFilter_Set(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    int filterc;
    Tcl_Size filterc;
    Tcl_Obj **filterv;

    if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"filterList");
	return TCL_ERROR;
    } else if (oPtr == NULL) {
	return TCL_ERROR;
    }
    objv += Tcl_ObjectContextSkippedArgs(context);
    if (Tcl_ListObjGetElements(interp, objv[0], &filterc,
    if (TclListObjGetElements(interp, objv[0], &filterc, &filterv) != TCL_OK) {
	    &filterv) != TCL_OK) {
	return TCL_ERROR;
    }

    TclOOObjectSetFilters(oPtr, filterc, filterv);
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * ObjectMixinGet, ObjectMixinSet --
 * ObjMixin_Get, ObjMixin_Set --
 *
 *	Implementation of the "mixin" slot accessors of the "oo::objdefine"
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ObjMixinGet(
    TCL_UNUSED(ClientData),
ObjMixin_Get(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Obj *resultObj;
    Class *mixinPtr;
    int i;
    Tcl_Size i;

    if (Tcl_ObjectContextSkippedArgs(context) != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		NULL);
	return TCL_ERROR;
    } else if (oPtr == NULL) {
	return TCL_ERROR;
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
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







-
-
+
+






-
+

-
-
+
+
+
+
+
+









-
+
-



-
+
+





+
+
+
+
-
-
+
+
+
+
+





+

+
+
+
+
+





-
+








-
-
+
+







-
+







	}
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ObjMixinSet(
    TCL_UNUSED(ClientData),
ObjMixin_Set(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    int mixinc;
    Tcl_Size mixinc, i;
    Tcl_Obj **mixinv;
    Class **mixins;
    int i;
    Class **mixins;		/* The references to the classes to actually
				 * install. */
    Tcl_HashTable uniqueCheck;	/* Note that this hash table is just used as a
				 * set of class references; it has no payload
				 * values and keys are always pointers. */
    int isNew;

    if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"mixinList");
	return TCL_ERROR;
    } else if (oPtr == NULL) {
	return TCL_ERROR;
    }
    objv += Tcl_ObjectContextSkippedArgs(context);
    if (Tcl_ListObjGetElements(interp, objv[0], &mixinc,
    if (TclListObjGetElements(interp, objv[0], &mixinc, &mixinv) != TCL_OK) {
	    &mixinv) != TCL_OK) {
	return TCL_ERROR;
    }

    mixins = (Class **)TclStackAlloc(interp, sizeof(Class *) * mixinc);
    mixins = (Class **) TclStackAlloc(interp, sizeof(Class *) * mixinc);
    Tcl_InitHashTable(&uniqueCheck, TCL_ONE_WORD_KEYS);

    for (i = 0; i < mixinc; i++) {
	mixins[i] = GetClassInOuterContext(interp, mixinv[i],
		"may only mix in classes");
	if (mixins[i] == NULL) {
	    goto freeAndError;
	}
	(void) Tcl_CreateHashEntry(&uniqueCheck, (void *) mixins[i], &isNew);
	if (!isNew) {
	    TclStackFree(interp, mixins);
	    return TCL_ERROR;
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "class should only be a direct mixin once",
		    TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "REPETITIOUS", (char *)NULL);
	    goto freeAndError;
	}
    }

    TclOOObjectSetMixins(oPtr, mixinc, mixins);
    TclStackFree(interp, mixins);
    Tcl_DeleteHashTable(&uniqueCheck);
    return TCL_OK;

  freeAndError:
    TclStackFree(interp, mixins);
    Tcl_DeleteHashTable(&uniqueCheck);
    return TCL_ERROR;
}

/*
 * ----------------------------------------------------------------------
 *
 * ObjectVarsGet, ObjectVarsSet --
 * ObjVars_Get, ObjVars_Set --
 *
 *	Implementation of the "variable" slot accessors of the "oo::objdefine"
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ObjVarsGet(
    TCL_UNUSED(ClientData),
ObjVars_Get(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Obj *resultObj;
    int i;
    Tcl_Size i;

    if (Tcl_ObjectContextSkippedArgs(context) != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		NULL);
	return TCL_ERROR;
    } else if (oPtr == NULL) {
	return TCL_ERROR;
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
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







-
-
+
+






-
+










-
+
-










-
+






-
+







	}
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ObjVarsSet(
    TCL_UNUSED(ClientData),
ObjVars_Set(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    int varc, i;
    Tcl_Size varc, i;
    Tcl_Obj **varv;

    if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"variableList");
	return TCL_ERROR;
    } else if (oPtr == NULL) {
	return TCL_ERROR;
    }
    objv += Tcl_ObjectContextSkippedArgs(context);
    if (Tcl_ListObjGetElements(interp, objv[0], &varc,
    if (TclListObjGetElements(interp, objv[0], &varc, &varv) != TCL_OK) {
	    &varv) != TCL_OK) {
	return TCL_ERROR;
    }

    for (i = 0; i < varc; i++) {
	const char *varName = TclGetString(varv[i]);

	if (strstr(varName, "::") != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "invalid declared variable name \"%s\": must not %s",
		    varName, "contain namespace separators"));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", (char *)NULL);
	    return TCL_ERROR;
	}
	if (Tcl_StringMatch(varName, "*(*)")) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "invalid declared variable name \"%s\": must not %s",
		    varName, "refer to an array element"));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", (char *)NULL);
	    return TCL_ERROR;
	}
    }

    if (IsPrivateDefine(interp)) {
	InstallPrivateVariableMapping(&oPtr->privateVariables, varc, varv,
		oPtr->creationEpoch);
3035
3036
3037
3038
3039
3040
3041
3042

3043
3044
3045
3046
3047
3048
3049
3112
3113
3114
3115
3116
3117
3118

3119
3120
3121
3122
3123
3124
3125
3126







-
+







 *	names to their fully-qualified names if possible.
 *
 * ----------------------------------------------------------------------
 */

static int
ResolveClass(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    int idx = Tcl_ObjectContextSkippedArgs(context);
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
3073
3074
3075
3076
3077
3078
3079
























































































































































































































































































































































3080
3081
3082
3083
3084
3085
3086
3087
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
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
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








	Tcl_SetObjResult(interp, objv[idx]);
    } else {
	Tcl_SetObjResult(interp, TclOOObjectName(interp, clsPtr->thisPtr));
    }

    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * Configurable_ClassReadableProps_Get, Configurable_ClassReadableProps_Set,
 * Configurable_ObjectReadableProps_Get, Configurable_ObjectReadableProps_Set --
 *
 *	Implementations of the "readableproperties" slot accessors for classes
 *	and instances.
 *
 * ----------------------------------------------------------------------
 */

static int
Configurable_ClassReadableProps_Get(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Class *clsPtr = TclOOGetClassDefineCmdContext(interp);

    if (clsPtr == NULL) {
	return TCL_ERROR;
    } else if (Tcl_ObjectContextSkippedArgs(context) != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		NULL);
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, TclOOGetPropertyList(&clsPtr->properties.readable));
    return TCL_OK;
}

static int
Configurable_ClassReadableProps_Set(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Class *clsPtr = TclOOGetClassDefineCmdContext(interp);
    Tcl_Size varc;
    Tcl_Obj **varv;

    if (clsPtr == NULL) {
	return TCL_ERROR;
    } else if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"filterList");
	return TCL_ERROR;
    }
    objv += Tcl_ObjectContextSkippedArgs(context);

    if (TclListObjGetElements(interp, objv[0], &varc, &varv) != TCL_OK) {
	return TCL_ERROR;
    }

    TclOOInstallReadableProperties(&clsPtr->properties, varc, varv);
    BumpGlobalEpoch(interp, clsPtr);
    return TCL_OK;
}

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

    if (oPtr == NULL) {
	return TCL_ERROR;
    } else if (Tcl_ObjectContextSkippedArgs(context) != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		NULL);
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, TclOOGetPropertyList(&oPtr->properties.readable));
    return TCL_OK;
}

static int
Configurable_ObjectReadableProps_Set(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Size varc;
    Tcl_Obj **varv;

    if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"filterList");
	return TCL_ERROR;
    }
    objv += Tcl_ObjectContextSkippedArgs(context);

    if (oPtr == NULL) {
	return TCL_ERROR;
    } else if (TclListObjGetElements(interp, objv[0], &varc,
	    &varv) != TCL_OK) {
	return TCL_ERROR;
    }

    TclOOInstallReadableProperties(&oPtr->properties, varc, varv);
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * Configurable_ClassWritableProps_Get, Configurable_ClassWritableProps_Set,
 * Configurable_ObjectWritableProps_Get, Configurable_ObjectWritableProps_Set --
 *
 *	Implementations of the "writableproperties" slot accessors for classes
 *	and instances.
 *
 * ----------------------------------------------------------------------
 */

static int
Configurable_ClassWritableProps_Get(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Class *clsPtr = TclOOGetClassDefineCmdContext(interp);

    if (clsPtr == NULL) {
	return TCL_ERROR;
    } else if (Tcl_ObjectContextSkippedArgs(context) != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		NULL);
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, TclOOGetPropertyList(&clsPtr->properties.writable));
    return TCL_OK;
}

static int
Configurable_ClassWritableProps_Set(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Class *clsPtr = TclOOGetClassDefineCmdContext(interp);
    Tcl_Size varc;
    Tcl_Obj **varv;

    if (clsPtr == NULL) {
	return TCL_ERROR;
    } else if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"propertyList");
	return TCL_ERROR;
    }
    objv += Tcl_ObjectContextSkippedArgs(context);

    if (TclListObjGetElements(interp, objv[0], &varc, &varv) != TCL_OK) {
	return TCL_ERROR;
    }

    TclOOInstallWritableProperties(&clsPtr->properties, varc, varv);
    BumpGlobalEpoch(interp, clsPtr);
    return TCL_OK;
}

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

    if (oPtr == NULL) {
	return TCL_ERROR;
    } else if (Tcl_ObjectContextSkippedArgs(context) != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		NULL);
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, TclOOGetPropertyList(&oPtr->properties.writable));
    return TCL_OK;
}

static int
Configurable_ObjectWritableProps_Set(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Size varc;
    Tcl_Obj **varv;

    if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"propertyList");
	return TCL_ERROR;
    }
    objv += Tcl_ObjectContextSkippedArgs(context);

    if (oPtr == NULL) {
	return TCL_ERROR;
    } else if (TclListObjGetElements(interp, objv[0], &varc,
	    &varv) != TCL_OK) {
	return TCL_ERROR;
    }

    TclOOInstallWritableProperties(&oPtr->properties, varc, varv);
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOORegisterProperty, TclOORegisterInstanceProperty --
 *
 *	Helpers to add or remove a name from the property slots of a class or
 *	instance.
 *
 * BuildPropertyList --
 *
 *	Helper for the helpers. Scans a property list and does the filtering
 *	or adding of the property to add or remove
 *
 * ----------------------------------------------------------------------
 */

static int
BuildPropertyList(
    PropertyList *propsList,	/* Property list to scan. */
    Tcl_Obj *propName,		/* Property to add/remove. */
    int addingProp,		/* True if we're adding, false if removing. */
    Tcl_Obj *listObj)		/* The list of property names we're building */
{
    int present = 0, changed = 0, i;
    Tcl_Obj *other;

    Tcl_SetListObj(listObj, 0, NULL);
    FOREACH(other, *propsList) {
	if (!TclStringCmp(propName, other, 1, 0, TCL_INDEX_NONE)) {
	    present = 1;
	    if (!addingProp) {
		changed = 1;
		continue;
	    }
	}
	Tcl_ListObjAppendElement(NULL, listObj, other);
    }
    if (!present && addingProp) {
	Tcl_ListObjAppendElement(NULL, listObj, propName);
	changed = 1;
    }
    return changed;
}

void
TclOORegisterInstanceProperty(
    Object *oPtr,		/* Object that owns the property slots. */
    Tcl_Obj *propName,		/* Property to add/remove. Must include the
				 * hyphen if one is desired; this is the value
				 * that is actually placed in the slot. */
    int registerReader,		/* True if we're adding the property name to
				 * the readable property slot. False if we're
				 * removing the property name from the slot. */
    int registerWriter)		/* True if we're adding the property name to
				 * the writable property slot. False if we're
				 * removing the property name from the slot. */
{
    Tcl_Obj *listObj = Tcl_NewObj();	/* Working buffer. */
    Tcl_Obj **objv;
    Tcl_Size count;

    if (BuildPropertyList(&oPtr->properties.readable, propName, registerReader,
	    listObj)) {
	TclListObjGetElements(NULL, listObj, &count, &objv);
	TclOOInstallReadableProperties(&oPtr->properties, count, objv);
    }

    if (BuildPropertyList(&oPtr->properties.writable, propName, registerWriter,
	    listObj)) {
	TclListObjGetElements(NULL, listObj, &count, &objv);
	TclOOInstallWritableProperties(&oPtr->properties, count, objv);
    }
    Tcl_BounceRefCount(listObj);
}

void
TclOORegisterProperty(
    Class *clsPtr,		/* Class that owns the property slots. */
    Tcl_Obj *propName,		/* Property to add/remove. Must include the
				 * hyphen if one is desired; this is the value
				 * that is actually placed in the slot. */
    int registerReader,		/* True if we're adding the property name to
				 * the readable property slot. False if we're
				 * removing the property name from the slot. */
    int registerWriter)		/* True if we're adding the property name to
				 * the writable property slot. False if we're
				 * removing the property name from the slot. */
{
    Tcl_Obj *listObj = Tcl_NewObj();	/* Working buffer. */
    Tcl_Obj **objv;
    Tcl_Size count;
    int changed = 0;

    if (BuildPropertyList(&clsPtr->properties.readable, propName,
	    registerReader, listObj)) {
	TclListObjGetElements(NULL, listObj, &count, &objv);
	TclOOInstallReadableProperties(&clsPtr->properties, count, objv);
	changed = 1;
    }

    if (BuildPropertyList(&clsPtr->properties.writable, propName,
	    registerWriter, listObj)) {
	TclListObjGetElements(NULL, listObj, &count, &objv);
	TclOOInstallWritableProperties(&clsPtr->properties, count, objv);
	changed = 1;
    }
    Tcl_BounceRefCount(listObj);
    if (changed) {
	BumpGlobalEpoch(clsPtr->thisPtr->fPtr->interp, clsPtr);
    }
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclOOInfo.c.

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
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






-
+











-







/*
 * tclOODefineCmds.c --
 *
 *	This file contains the implementation of the ::oo-related [info]
 *	subcommands.
 *
 * Copyright (c) 2006-2011 by Donal K. Fellows
 * Copyright © 2006-2019 Donal K. Fellows
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

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

static inline Class *	GetClassFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr);
static Tcl_ObjCmdProc InfoObjectCallCmd;
static Tcl_ObjCmdProc InfoObjectClassCmd;
static Tcl_ObjCmdProc InfoObjectDefnCmd;
static Tcl_ObjCmdProc InfoObjectFiltersCmd;
static Tcl_ObjCmdProc InfoObjectForwardCmd;
static Tcl_ObjCmdProc InfoObjectIdCmd;
static Tcl_ObjCmdProc InfoObjectIsACmd;
57
58
59
60
61
62
63

64
65
66
67
68
69
70
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70







+







    {"filters",	   InfoObjectFiltersCmd,    TclCompileBasic1ArgCmd, NULL, NULL, 0},
    {"forward",	   InfoObjectForwardCmd,    TclCompileBasic2ArgCmd, NULL, NULL, 0},
    {"isa",	   InfoObjectIsACmd,	    TclCompileInfoObjectIsACmd, NULL, NULL, 0},
    {"methods",	   InfoObjectMethodsCmd,    TclCompileBasicMin1ArgCmd, NULL, NULL, 0},
    {"methodtype", InfoObjectMethodTypeCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
    {"mixins",	   InfoObjectMixinsCmd,	    TclCompileBasic1ArgCmd, NULL, NULL, 0},
    {"namespace",  InfoObjectNsCmd,	    TclCompileInfoObjectNamespaceCmd, NULL, NULL, 0},
    {"properties", TclOOInfoObjectPropCmd,  TclCompileBasicMin1ArgCmd, NULL, NULL, 0},
    {"variables",  InfoObjectVariablesCmd,  TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
    {"vars",	   InfoObjectVarsCmd,	    TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
    {NULL, NULL, NULL, NULL, NULL, 0}
};

/*
 * List of commands that are used to implement the [info class] subcommands.
78
79
80
81
82
83
84

85
86
87
88
89

















90
91
92
93
94
95
96
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







+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    {"destructor",   InfoClassDestrCmd,		TclCompileBasic1ArgCmd, NULL, NULL, 0},
    {"filters",	     InfoClassFiltersCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 0},
    {"forward",	     InfoClassForwardCmd,	TclCompileBasic2ArgCmd, NULL, NULL, 0},
    {"instances",    InfoClassInstancesCmd,	TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
    {"methods",	     InfoClassMethodsCmd,	TclCompileBasicMin1ArgCmd, NULL, NULL, 0},
    {"methodtype",   InfoClassMethodTypeCmd,	TclCompileBasic2ArgCmd, NULL, NULL, 0},
    {"mixins",	     InfoClassMixinsCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 0},
    {"properties",   TclOOInfoClassPropCmd,	TclCompileBasicMin1ArgCmd, NULL, NULL, 0},
    {"subclasses",   InfoClassSubsCmd,		TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
    {"superclasses", InfoClassSupersCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 0},
    {"variables",    InfoClassVariablesCmd,	TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
    {NULL, NULL, NULL, NULL, NULL, 0}
};

/*
 * ----------------------------------------------------------------------
 *
 * LocalVarName --
 *
 *	Get the name of a local variable (especially a method argument) as a
 *	Tcl value.
 *
 * ----------------------------------------------------------------------
 */
static inline Tcl_Obj *
LocalVarName(
    CompiledLocal *localPtr)
{
    return Tcl_NewStringObj(localPtr->name, TCL_AUTO_LENGTH);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOInitInfo --
 *
 *	Adjusts the Tcl core [info] command to contain subcommands ("object"
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
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







-
-
+
-
-
+







-
+







-
-
+
+












-
+







    /*
     * Install into the [info] ensemble.
     */

    infoCmd = Tcl_FindCommand(interp, "info", NULL, TCL_GLOBAL_ONLY);
    if (infoCmd) {
	Tcl_GetEnsembleMappingDict(NULL, infoCmd, &mapDict);
	Tcl_DictObjPut(NULL, mapDict, Tcl_NewStringObj("object", -1),
		Tcl_NewStringObj("::oo::InfoObject", -1));
	TclDictPutString(NULL, mapDict, "object", "::oo::InfoObject");
	Tcl_DictObjPut(NULL, mapDict, Tcl_NewStringObj("class", -1),
		Tcl_NewStringObj("::oo::InfoClass", -1));
	TclDictPutString(NULL, mapDict, "class", "::oo::InfoClass");
	Tcl_SetEnsembleMappingDict(interp, infoCmd, mapDict);
    }
}

/*
 * ----------------------------------------------------------------------
 *
 * GetClassFromObj --
 * TclOOGetClassFromObj --
 *
 *	How to correctly get a class from a Tcl_Obj. Just a wrapper round
 *	Tcl_GetObjectFromObj, but this is an idiom that was used heavily.
 *
 * ----------------------------------------------------------------------
 */

static inline Class *
GetClassFromObj(
Class *
TclOOGetClassFromObj(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr)
{
    Object *oPtr = (Object *) Tcl_GetObjectFromObj(interp, objPtr);

    if (oPtr == NULL) {
	return NULL;
    }
    if (oPtr->classPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"\"%s\" is not a class", TclGetString(objPtr)));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS",
		TclGetString(objPtr), NULL);
		TclGetString(objPtr), (char *)NULL);
	return NULL;
    }
    return oPtr->classPtr;
}

/*
 * ----------------------------------------------------------------------
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
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







-
+

-
+









-
+



-
+








    if (objc == 2) {
	Tcl_SetObjResult(interp,
		TclOOObjectName(interp, oPtr->selfCls->thisPtr));
	return TCL_OK;
    } else {
	Class *mixinPtr, *o2clsPtr;
	int i;
	Tcl_Size i;

	o2clsPtr = GetClassFromObj(interp, objv[2]);
	o2clsPtr = TclOOGetClassFromObj(interp, objv[2]);
	if (o2clsPtr == NULL) {
	    return TCL_ERROR;
	}

	FOREACH(mixinPtr, oPtr->mixins) {
	    if (!mixinPtr) {
		continue;
	    }
	    if (TclOOIsReachable(o2clsPtr, mixinPtr)) {
		Tcl_SetObjResult(interp, Tcl_NewWideIntObj(1));
		Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
		return TCL_OK;
	    }
	}
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
		TclOOIsReachable(o2clsPtr, oPtr->selfCls)));
	return TCL_OK;
    }
}

/*
 * ----------------------------------------------------------------------
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
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







-
+

-
+
-
-
-
-
-

-
+

-
-
-
-
-
+


+
+
+
+







-
+
-






-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



















-
+







    if (oPtr == NULL) {
	return TCL_ERROR;
    }

    if (!oPtr->methodsPtr) {
	goto unknownMethod;
    }
    hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) objv[2]);
    hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, objv[2]);
    if (hPtr == NULL) {
    unknownMethod:
	goto unknownMethod;
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"unknown method \"%s\"", TclGetString(objv[2])));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
		TclGetString(objv[2]), NULL);
	return TCL_ERROR;
    }
    procPtr = TclOOGetProcFromMethod((Method *)Tcl_GetHashValue(hPtr));
    procPtr = TclOOGetProcFromMethod((Method *) Tcl_GetHashValue(hPtr));
    if (procPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"definition not available for this kind of method", -1));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
		TclGetString(objv[2]), NULL);
	return TCL_ERROR;
	goto wrongType;
    }

    /*
     * We now have the method to describe the definition of.
     */

    TclNewObj(resultObjs[0]);
    for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL;
	    localPtr=localPtr->nextPtr) {
	if (TclIsVarArgument(localPtr)) {
	    Tcl_Obj *argObj;

	    TclNewObj(argObj);
	    Tcl_ListObjAppendElement(NULL, argObj,
	    Tcl_ListObjAppendElement(NULL, argObj, LocalVarName(localPtr));
		    Tcl_NewStringObj(localPtr->name, -1));
	    if (localPtr->defValuePtr != NULL) {
		Tcl_ListObjAppendElement(NULL, argObj, localPtr->defValuePtr);
	    }
	    Tcl_ListObjAppendElement(NULL, resultObjs[0], argObj);
	}
    }
    resultObjs[1] = TclOOGetMethodBody((Method *)Tcl_GetHashValue(hPtr));
    resultObjs[1] = TclOOGetMethodBody((Method *) Tcl_GetHashValue(hPtr));
    Tcl_SetObjResult(interp, Tcl_NewListObj(2, resultObjs));
    return TCL_OK;

    /*
     * Errors...
     */

  unknownMethod:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "unknown method \"%s\"", TclGetString(objv[2])));
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
	    TclGetString(objv[2]), (char *)NULL);
    return TCL_ERROR;

  wrongType:
    Tcl_SetObjResult(interp, Tcl_NewStringObj(
	    "definition not available for this kind of method",
	    TCL_AUTO_LENGTH));
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
	    TclGetString(objv[2]), (char *)NULL);
    return TCL_ERROR;
}

/*
 * ----------------------------------------------------------------------
 *
 * InfoObjectFiltersCmd --
 *
 *	Implements [info object filters $objName]
 *
 * ----------------------------------------------------------------------
 */

static int
InfoObjectFiltersCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    int i;
    Tcl_Size i;
    Tcl_Obj *filterObj, *resultObj;
    Object *oPtr;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "objName");
	return TCL_ERROR;
    }
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
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







-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-







    if (oPtr == NULL) {
	return TCL_ERROR;
    }

    if (!oPtr->methodsPtr) {
	goto unknownMethod;
    }
    hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) objv[2]);
    hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, objv[2]);
    if (hPtr == NULL) {
	goto unknownMethod;
    }
    prefixObj = TclOOGetFwdFromMethod((Method *) Tcl_GetHashValue(hPtr));
    if (prefixObj == NULL) {
	goto wrongType;
    }

    /*
     * Describe the valid forward method.
     */

    Tcl_SetObjResult(interp, prefixObj);
    return TCL_OK;

    /*
     * Errors...
     */

    unknownMethod:
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"unknown method \"%s\"", TclGetString(objv[2])));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
		TclGetString(objv[2]), NULL);
	return TCL_ERROR;
    }
  unknownMethod:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "unknown method \"%s\"", TclGetString(objv[2])));
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
	    TclGetString(objv[2]), (char *)NULL);
    return TCL_ERROR;

    prefixObj = TclOOGetFwdFromMethod((Method *)Tcl_GetHashValue(hPtr));
    if (prefixObj == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"prefix argument list not available for this kind of method",
		-1));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
		TclGetString(objv[2]), NULL);
	return TCL_ERROR;
  wrongType:
    Tcl_SetObjResult(interp, Tcl_NewStringObj(
	    "prefix argument list not available for this kind of method",
	    TCL_AUTO_LENGTH));
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
	    TclGetString(objv[2]), (char *)NULL);
    return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, prefixObj);
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * InfoObjectIsACmd --
 *
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
446
447
448
449
450
451
452

453
454

455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471

472
473
474
475
476
477
478
479







-
+

-
+
+















-
+







    Tcl_Obj *const objv[])
{
    static const char *const categories[] = {
	"class", "metaclass", "mixin", "object", "typeof", NULL
    };
    enum IsACats {
	IsClass, IsMetaclass, IsMixin, IsObject, IsType
    };
    } idx;
    Object *oPtr, *o2Ptr;
    int idx, i, result = 0;
    int result = 0;
    Tcl_Size i;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "category objName ?arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], categories, "category", 0,
	    &idx) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Now we know what test we are doing, we can check we've got the right
     * number of arguments.
     */

    switch ((enum IsACats) idx) {
    switch (idx) {
    case IsObject:
    case IsClass:
    case IsMetaclass:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "objName");
	    return TCL_ERROR;
	}
450
451
452
453
454
455
456
457

458
459
460
461
462
463
464
493
494
495
496
497
498
499

500
501
502
503
504
505
506
507







-
+







     */

    oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[2]);
    if (oPtr == NULL) {
	goto failPrecondition;
    }

    switch ((enum IsACats) idx) {
    switch (idx) {
    case IsObject:
	result = 1;
	break;
    case IsClass:
	result = (oPtr->classPtr != NULL);
	break;
    case IsMetaclass:
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
558
559
560

561
562
563
564
565
566
567
568
569
570
571
572
573
574
575

576
577
578
579
580
581
582
583
584
585
586

587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603




604
605
606
607
608
609
610
611
612

613
614
615

616
617






618
619
620










621
622
623
624
625
626
627
561
562
563
564
565
566
567





568
569
570
571
572

573
574
575
576
577
578

579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600

601
602
603
604
605
606
607

608
609
610
611
612
613
614
615
616
617
618
619
620
621
622

623
624
625
626
627
628
629
630
631
632
633

634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663

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







-
-
-
-
-





-
+





-
+
+

+
+
+
+
+
+
+
+
+










-
+






-
+














-
+










-
+

















+
+
+
+








-
+


-
+


+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+







static int
InfoObjectMethodsCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Object *oPtr;
    int flag = PUBLIC_METHOD, recurse = 0, scope = -1;
    FOREACH_HASH_DECLS;
    Tcl_Obj *namePtr, *resultObj;
    Method *mPtr;
    static const char *const options[] = {
	"-all", "-localprivate", "-private", "-scope", NULL
    };
    enum Options {
	OPT_ALL, OPT_LOCALPRIVATE, OPT_PRIVATE, OPT_SCOPE
    };
    } idx;
    static const char *const scopes[] = {
	"private", "public", "unexported"
    };
    enum Scopes {
	SCOPE_PRIVATE, SCOPE_PUBLIC, SCOPE_UNEXPORTED,
	SCOPE_LOCALPRIVATE
	SCOPE_LOCALPRIVATE,
	SCOPE_DEFAULT = -1
    };
    Object *oPtr;
    int flag = PUBLIC_METHOD, recurse = 0, scope = SCOPE_DEFAULT;
    FOREACH_HASH_DECLS;
    Tcl_Obj *namePtr, *resultObj;
    Method *mPtr;

    /*
     * Parse arguments.
     */

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "objName ?-option value ...?");
	return TCL_ERROR;
    }
    oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]);
    if (oPtr == NULL) {
	return TCL_ERROR;
    }
    if (objc != 2) {
	int i, idx;
	int i;

	for (i=2 ; i<objc ; i++) {
	    if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
		    &idx) != TCL_OK) {
		return TCL_ERROR;
	    }
	    switch ((enum Options) idx) {
	    switch (idx) {
	    case OPT_ALL:
		recurse = 1;
		break;
	    case OPT_LOCALPRIVATE:
		flag = PRIVATE_METHOD;
		break;
	    case OPT_PRIVATE:
		flag = 0;
		break;
	    case OPT_SCOPE:
		if (++i >= objc) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "missing option for -scope"));
		    Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING",
			    NULL);
			    (char *)NULL);
		    return TCL_ERROR;
		}
		if (Tcl_GetIndexFromObj(interp, objv[i], scopes, "scope", 0,
			&scope) != TCL_OK) {
		    return TCL_ERROR;
		}
		break;
	    }
	}
    }
    if (scope != -1) {
    if (scope != SCOPE_DEFAULT) {
	recurse = 0;
	switch (scope) {
	case SCOPE_PRIVATE:
	    flag = TRUE_PRIVATE_METHOD;
	    break;
	case SCOPE_PUBLIC:
	    flag = PUBLIC_METHOD;
	    break;
	case SCOPE_LOCALPRIVATE:
	    flag = PRIVATE_METHOD;
	    break;
	case SCOPE_UNEXPORTED:
	    flag = 0;
	    break;
	}
    }

    /*
     * List matching methods.
     */

    TclNewObj(resultObj);
    if (recurse) {
	const char **names;
	int i, numNames = TclOOGetSortedMethodList(oPtr, NULL, NULL, flag,
		&names);

	for (i=0 ; i<numNames ; i++) {
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    Tcl_NewStringObj(names[i], -1));
		    Tcl_NewStringObj(names[i], TCL_AUTO_LENGTH));
	}
	if (numNames > 0) {
	    Tcl_Free((void *)names);
	    Tcl_Free((void *) names);
	}
    } else if (oPtr->methodsPtr) {
	if (scope == SCOPE_DEFAULT) {
	    /*
	     * Handle legacy-mode matching. [Bug 36e5517a6850]
	     */
	    int scopeFilter = flag | TRUE_PRIVATE_METHOD;

	FOREACH_HASH(namePtr, mPtr, oPtr->methodsPtr) {
	    if (mPtr->typePtr && (mPtr->flags & SCOPE_FLAGS) == flag) {
		Tcl_ListObjAppendElement(NULL, resultObj, namePtr);
	    FOREACH_HASH(namePtr, mPtr, oPtr->methodsPtr) {
		if (mPtr->typePtr && (mPtr->flags & scopeFilter) == flag) {
		    Tcl_ListObjAppendElement(NULL, resultObj, namePtr);
		}
	    }
	} else {
	    FOREACH_HASH(namePtr, mPtr, oPtr->methodsPtr) {
		if (mPtr->typePtr && (mPtr->flags & SCOPE_FLAGS) == flag) {
		    Tcl_ListObjAppendElement(NULL, resultObj, namePtr);
		}
	    }
	}
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

655
656
657
658
659
660
661
662

663
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
720
721
722
723
724
725
726

727
728

729





730

731
732
733
734
735
736
737
738
739
740

741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757







-
+

-
+
-
-
-
-
-

-
+









-
+
+

+
+
+
+
+
+
+







    if (oPtr == NULL) {
	return TCL_ERROR;
    }

    if (!oPtr->methodsPtr) {
	goto unknownMethod;
    }
    hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) objv[2]);
    hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, objv[2]);
    if (hPtr == NULL) {
    unknownMethod:
	goto unknownMethod;
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"unknown method \"%s\"", TclGetString(objv[2])));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
		TclGetString(objv[2]), NULL);
	return TCL_ERROR;
    }
    mPtr = (Method *)Tcl_GetHashValue(hPtr);
    mPtr = (Method *) Tcl_GetHashValue(hPtr);
    if (mPtr->typePtr == NULL) {
	/*
	 * Special entry for visibility control: pretend the method doesnt
	 * exist.
	 */

	goto unknownMethod;
    }

    Tcl_SetObjResult(interp, Tcl_NewStringObj(mPtr->typePtr->name, -1));
    Tcl_SetObjResult(interp,
	    Tcl_NewStringObj(mPtr->typePtr->name, TCL_AUTO_LENGTH));
    return TCL_OK;

  unknownMethod:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "unknown method \"%s\"", TclGetString(objv[2])));
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
	    TclGetString(objv[2]), (char *)NULL);
    return TCL_ERROR;
}

/*
 * ----------------------------------------------------------------------
 *
 * InfoObjectMixinsCmd --
 *
698
699
700
701
702
703
704
705

706
707
708
709
710
711
712
766
767
768
769
770
771
772

773
774
775
776
777
778
779
780







-
+







    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Class *mixinPtr;
    Object *oPtr;
    Tcl_Obj *resultObj;
    int i;
    Tcl_Size i;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "objName");
	return TCL_ERROR;
    }
    oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]);
    if (oPtr == NULL) {
781
782
783
784
785
786
787
788

789
790
791
792
793
794
795
796
849
850
851
852
853
854
855

856

857
858
859
860
861
862
863







-
+
-







	return TCL_ERROR;
    }
    oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]);
    if (oPtr == NULL) {
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp,
    Tcl_SetObjResult(interp, TclNewNamespaceObj(oPtr->namespacePtr));
	    Tcl_NewStringObj(oPtr->namespacePtr->fullName, -1));
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * InfoObjectVariablesCmd --
805
806
807
808
809
810
811

812

813
814
815
816
817
818
819




820
821
822
823
824
825
826
872
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
898







+
-
+







+
+
+
+







    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Object *oPtr;
    Tcl_Obj *resultObj;
    Tcl_Size i;
    int i, isPrivate = 0;
    int isPrivate = 0;

    if (objc != 2 && objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "objName ?-private?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (strcmp("-private", TclGetString(objv[2])) != 0) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "option \"%s\" is not exactly \"-private\"",
		    TclGetString(objv[2])));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_ARG");
	    return TCL_ERROR;
	}
	isPrivate = 1;
    }
    oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]);
    if (oPtr == NULL) {
	return TCL_ERROR;
927
928
929
930
931
932
933
934

935
936
937
938
939
940
941
942
943
944
945



946
947
948
949
950
951
952
953
954
955
956

957
958
959
960
961
962
963
964
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
1024
1025
1026
1027
1028

1029

1030
1031
1032
1033
1034
1035
1036







-
+









-
-
+
+
+










-
+
-







    Tcl_Obj *resultObjs[2];
    Class *clsPtr;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "className");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    clsPtr = TclOOGetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }
    if (clsPtr->constructorPtr == NULL) {
	return TCL_OK;
    }
    procPtr = TclOOGetProcFromMethod(clsPtr->constructorPtr);
    if (procPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"definition not available for this kind of method", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "METHOD_TYPE", NULL);
		"definition not available for this kind of method",
		TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "METHOD_TYPE", (char *)NULL);
	return TCL_ERROR;
    }

    TclNewObj(resultObjs[0]);
    for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL;
	    localPtr=localPtr->nextPtr) {
	if (TclIsVarArgument(localPtr)) {
	    Tcl_Obj *argObj;

	    TclNewObj(argObj);
	    Tcl_ListObjAppendElement(NULL, argObj,
	    Tcl_ListObjAppendElement(NULL, argObj, LocalVarName(localPtr));
		    Tcl_NewStringObj(localPtr->name, -1));
	    if (localPtr->defValuePtr != NULL) {
		Tcl_ListObjAppendElement(NULL, argObj, localPtr->defValuePtr);
	    }
	    Tcl_ListObjAppendElement(NULL, resultObjs[0], argObj);
	}
    }
    resultObjs[1] = TclOOGetMethodBody(clsPtr->constructorPtr);
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
1024

1025
1026
1027
1028
1029
1030
1031
1032

1033
1034
1035
1036
1037
1038
1039
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







-
+



-
+




-
+


-
+


-
+
+

-
+










-
+
-






-
+







    Tcl_Obj *resultObjs[2];
    Class *clsPtr;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "className methodName");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    clsPtr = TclOOGetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }
    hPtr = Tcl_FindHashEntry(&clsPtr->classMethods, (char *) objv[2]);
    hPtr = Tcl_FindHashEntry(&clsPtr->classMethods, objv[2]);
    if (hPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"unknown method \"%s\"", TclGetString(objv[2])));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
		TclGetString(objv[2]), NULL);
		TclGetString(objv[2]), (char *)NULL);
	return TCL_ERROR;
    }
    procPtr = TclOOGetProcFromMethod((Method *)Tcl_GetHashValue(hPtr));
    procPtr = TclOOGetProcFromMethod((Method *) Tcl_GetHashValue(hPtr));
    if (procPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"definition not available for this kind of method", -1));
		"definition not available for this kind of method",
		TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
		TclGetString(objv[2]), NULL);
		TclGetString(objv[2]), (char *)NULL);
	return TCL_ERROR;
    }

    TclNewObj(resultObjs[0]);
    for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL;
	    localPtr=localPtr->nextPtr) {
	if (TclIsVarArgument(localPtr)) {
	    Tcl_Obj *argObj;

	    TclNewObj(argObj);
	    Tcl_ListObjAppendElement(NULL, argObj,
	    Tcl_ListObjAppendElement(NULL, argObj, LocalVarName(localPtr));
		    Tcl_NewStringObj(localPtr->name, -1));
	    if (localPtr->defValuePtr != NULL) {
		Tcl_ListObjAppendElement(NULL, argObj, localPtr->defValuePtr);
	    }
	    Tcl_ListObjAppendElement(NULL, resultObjs[0], argObj);
	}
    }
    resultObjs[1] = TclOOGetMethodBody((Method *)Tcl_GetHashValue(hPtr));
    resultObjs[1] = TclOOGetMethodBody((Method *) Tcl_GetHashValue(hPtr));
    Tcl_SetObjResult(interp, Tcl_NewListObj(2, resultObjs));
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
1060
1061
1062
1063
1064
1065
1066
1067

1068
1069
1070
1071
1072
1073
1074
1132
1133
1134
1135
1136
1137
1138

1139
1140
1141
1142
1143
1144
1145
1146







-
+







    Tcl_Obj *nsNamePtr;
    Class *clsPtr;

    if (objc != 2 && objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "className ?kind?");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    clsPtr = TclOOGetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }
    if (objc == 3 && Tcl_GetIndexFromObj(interp, objv[2], kindList, "kind", 0,
	    &kind) != TCL_OK) {
	return TCL_ERROR;
    }
1104
1105
1106
1107
1108
1109
1110
1111

1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123



1124
1125
1126
1127
1128
1129
1130
1176
1177
1178
1179
1180
1181
1182

1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193


1194
1195
1196
1197
1198
1199
1200
1201
1202
1203







-
+










-
-
+
+
+







    Proc *procPtr;
    Class *clsPtr;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "className");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    clsPtr = TclOOGetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }

    if (clsPtr->destructorPtr == NULL) {
	return TCL_OK;
    }
    procPtr = TclOOGetProcFromMethod(clsPtr->destructorPtr);
    if (procPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"definition not available for this kind of method", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "METHOD_TYPE", NULL);
		"definition not available for this kind of method",
		TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "METHOD_TYPE", (char *)NULL);
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, TclOOGetMethodBody(clsPtr->destructorPtr));
    return TCL_OK;
}

1141
1142
1143
1144
1145
1146
1147
1148

1149
1150
1151
1152
1153
1154
1155
1156

1157
1158
1159
1160
1161
1162
1163
1214
1215
1216
1217
1218
1219
1220

1221
1222
1223
1224
1225
1226
1227
1228

1229
1230
1231
1232
1233
1234
1235
1236







-
+







-
+







static int
InfoClassFiltersCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    int i;
    Tcl_Size i;
    Tcl_Obj *filterObj, *resultObj;
    Class *clsPtr;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "className");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    clsPtr = TclOOGetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }

    TclNewObj(resultObj);
    FOREACH(filterObj, clsPtr->filters) {
	Tcl_ListObjAppendElement(NULL, resultObj, filterObj);
1187
1188
1189
1190
1191
1192
1193
1194

1195
1196
1197
1198

1199
1200
1201
1202
1203

1204
1205
1206

1207
1208
1209
1210

1211
1212

1213
1214
1215
1216
1217
1218
1219
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







-
+



-
+




-
+


-
+



-
+

-
+







    Tcl_Obj *prefixObj;
    Class *clsPtr;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "className methodName");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    clsPtr = TclOOGetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }
    hPtr = Tcl_FindHashEntry(&clsPtr->classMethods, (char *) objv[2]);
    hPtr = Tcl_FindHashEntry(&clsPtr->classMethods, objv[2]);
    if (hPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"unknown method \"%s\"", TclGetString(objv[2])));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
		TclGetString(objv[2]), NULL);
		TclGetString(objv[2]), (char *)NULL);
	return TCL_ERROR;
    }
    prefixObj = TclOOGetFwdFromMethod((Method *)Tcl_GetHashValue(hPtr));
    prefixObj = TclOOGetFwdFromMethod((Method *) Tcl_GetHashValue(hPtr));
    if (prefixObj == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"prefix argument list not available for this kind of method",
		-1));
		TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
		TclGetString(objv[2]), NULL);
		TclGetString(objv[2]), (char *)NULL);
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, prefixObj);
    return TCL_OK;
}

1232
1233
1234
1235
1236
1237
1238
1239

1240
1241
1242
1243
1244
1245
1246
1247

1248
1249
1250
1251
1252
1253
1254
1305
1306
1307
1308
1309
1310
1311

1312
1313
1314
1315
1316
1317
1318
1319

1320
1321
1322
1323
1324
1325
1326
1327







-
+







-
+







    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Object *oPtr;
    Class *clsPtr;
    int i;
    Tcl_Size i;
    const char *pattern = NULL;
    Tcl_Obj *resultObj;

    if (objc != 2 && objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "className ?pattern?");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    clsPtr = TclOOGetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }
    if (objc == 3) {
	pattern = TclGetString(objv[2]);
    }

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
1354
1355
1356
1357
1358
1359
1360
1361
1362

1363
1364
1365
1366

1367
1368
1369

1370
1371
1372
1373






1374
1375
1376










1377
1378
1379
1380
1381
1382
1383
1351
1352
1353
1354
1355
1356
1357




1358
1359
1360
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
1387
1388
1389
1390
1391

1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406

1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417

1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435

1436
1437
1438
1439

1440
1441
1442

1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453



1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470







-
-
-
-





-
+




-
+
+

+
+
+
+





-
+




-
+






-
+














-
+










-
+

















-
+



-
+


-
+




+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+







static int
InfoClassMethodsCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    int flag = PUBLIC_METHOD, recurse = 0, scope = -1;
    Tcl_Obj *namePtr, *resultObj;
    Method *mPtr;
    Class *clsPtr;
    static const char *const options[] = {
	"-all", "-localprivate", "-private", "-scope", NULL
    };
    enum Options {
	OPT_ALL, OPT_LOCALPRIVATE, OPT_PRIVATE, OPT_SCOPE
    };
    } idx;
    static const char *const scopes[] = {
	"private", "public", "unexported"
    };
    enum Scopes {
	SCOPE_PRIVATE, SCOPE_PUBLIC, SCOPE_UNEXPORTED
	SCOPE_PRIVATE, SCOPE_PUBLIC, SCOPE_UNEXPORTED,
	SCOPE_DEFAULT = -1
    };
    int flag = PUBLIC_METHOD, recurse = 0, scope = SCOPE_DEFAULT;
    Tcl_Obj *namePtr, *resultObj;
    Method *mPtr;
    Class *clsPtr;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "className ?-option value ...?");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    clsPtr = TclOOGetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }
    if (objc != 2) {
	int i, idx;
	int i;

	for (i=2 ; i<objc ; i++) {
	    if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
		    &idx) != TCL_OK) {
		return TCL_ERROR;
	    }
	    switch ((enum Options) idx) {
	    switch (idx) {
	    case OPT_ALL:
		recurse = 1;
		break;
	    case OPT_LOCALPRIVATE:
		flag = PRIVATE_METHOD;
		break;
	    case OPT_PRIVATE:
		flag = 0;
		break;
	    case OPT_SCOPE:
		if (++i >= objc) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "missing option for -scope"));
		    Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING",
			    NULL);
			    (char *)NULL);
		    return TCL_ERROR;
		}
		if (Tcl_GetIndexFromObj(interp, objv[i], scopes, "scope", 0,
			&scope) != TCL_OK) {
		    return TCL_ERROR;
		}
		break;
	    }
	}
    }
    if (scope != -1) {
    if (scope != SCOPE_DEFAULT) {
	recurse = 0;
	switch (scope) {
	case SCOPE_PRIVATE:
	    flag = TRUE_PRIVATE_METHOD;
	    break;
	case SCOPE_PUBLIC:
	    flag = PUBLIC_METHOD;
	    break;
	case SCOPE_UNEXPORTED:
	    flag = 0;
	    break;
	}
    }

    TclNewObj(resultObj);
    if (recurse) {
	const char **names;
	int i, numNames = TclOOGetSortedClassMethodList(clsPtr, flag, &names);
	Tcl_Size i, numNames = TclOOGetSortedClassMethodList(clsPtr, flag, &names);

	for (i=0 ; i<numNames ; i++) {
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    Tcl_NewStringObj(names[i], -1));
		    Tcl_NewStringObj(names[i], TCL_AUTO_LENGTH));
	}
	if (numNames > 0) {
	    Tcl_Free((void *)names);
	    Tcl_Free((void *) names);
	}
    } else {
	FOREACH_HASH_DECLS;

	if (scope == SCOPE_DEFAULT) {
	    /*
	     * Handle legacy-mode matching. [Bug 36e5517a6850]
	     */
	    int scopeFilter = flag | TRUE_PRIVATE_METHOD;

	FOREACH_HASH(namePtr, mPtr, &clsPtr->classMethods) {
	    if (mPtr->typePtr && (mPtr->flags & SCOPE_FLAGS) == flag) {
		Tcl_ListObjAppendElement(NULL, resultObj, namePtr);
	    FOREACH_HASH(namePtr, mPtr, &clsPtr->classMethods) {
		if (mPtr->typePtr && (mPtr->flags & scopeFilter) == flag) {
		    Tcl_ListObjAppendElement(NULL, resultObj, namePtr);
		}
	    }
	} else {
	    FOREACH_HASH(namePtr, mPtr, &clsPtr->classMethods) {
		if (mPtr->typePtr && (mPtr->flags & SCOPE_FLAGS) == flag) {
		    Tcl_ListObjAppendElement(NULL, resultObj, namePtr);
		}
	    }
	}
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

1402
1403
1404
1405
1406
1407
1408
1409

1410
1411
1412
1413
1414

1415
1416

1417
1418
1419
1420
1421
1422
1423

1424
1425
1426
1427
1428
1429
1430
1431
1432


1433







1434
1435
1436
1437
1438
1439
1440
1489
1490
1491
1492
1493
1494
1495

1496
1497
1498
1499
1500

1501
1502

1503





1504

1505
1506
1507
1508
1509
1510
1511
1512
1513

1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530







-
+




-
+

-
+
-
-
-
-
-

-
+








-
+
+

+
+
+
+
+
+
+







    Method *mPtr;
    Class *clsPtr;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "className methodName");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    clsPtr = TclOOGetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }

    hPtr = Tcl_FindHashEntry(&clsPtr->classMethods, (char *) objv[2]);
    hPtr = Tcl_FindHashEntry(&clsPtr->classMethods, objv[2]);
    if (hPtr == NULL) {
    unknownMethod:
	goto unknownMethod;
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"unknown method \"%s\"", TclGetString(objv[2])));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
		TclGetString(objv[2]), NULL);
	return TCL_ERROR;
    }
    mPtr = (Method *)Tcl_GetHashValue(hPtr);
    mPtr = (Method *) Tcl_GetHashValue(hPtr);
    if (mPtr->typePtr == NULL) {
	/*
	 * Special entry for visibility control: pretend the method doesnt
	 * exist.
	 */

	goto unknownMethod;
    }
    Tcl_SetObjResult(interp, Tcl_NewStringObj(mPtr->typePtr->name, -1));
    Tcl_SetObjResult(interp,
	    Tcl_NewStringObj(mPtr->typePtr->name, TCL_AUTO_LENGTH));
    return TCL_OK;

  unknownMethod:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "unknown method \"%s\"", TclGetString(objv[2])));
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
	    TclGetString(objv[2]), (char *)NULL);
    return TCL_ERROR;
}

/*
 * ----------------------------------------------------------------------
 *
 * InfoClassMixinsCmd --
 *
1448
1449
1450
1451
1452
1453
1454
1455

1456
1457
1458
1459
1460
1461

1462
1463
1464
1465
1466
1467
1468
1538
1539
1540
1541
1542
1543
1544

1545
1546
1547
1548
1549
1550

1551
1552
1553
1554
1555
1556
1557
1558







-
+





-
+







    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Class *clsPtr, *mixinPtr;
    Tcl_Obj *resultObj;
    int i;
    Tcl_Size i;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "className");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    clsPtr = TclOOGetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }

    TclNewObj(resultObj);
    FOREACH(mixinPtr, clsPtr->mixins) {
	if (!mixinPtr) {
1490
1491
1492
1493
1494
1495
1496
1497

1498
1499
1500
1501
1502
1503
1504

1505
1506
1507
1508
1509
1510
1511
1580
1581
1582
1583
1584
1585
1586

1587
1588
1589
1590
1591
1592
1593

1594
1595
1596
1597
1598
1599
1600
1601







-
+






-
+







    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Class *clsPtr, *subclassPtr;
    Tcl_Obj *resultObj;
    int i;
    Tcl_Size i;
    const char *pattern = NULL;

    if (objc != 2 && objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "className ?pattern?");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    clsPtr = TclOOGetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }
    if (objc == 3) {
	pattern = TclGetString(objv[2]);
    }

1545
1546
1547
1548
1549
1550
1551
1552

1553
1554
1555
1556
1557
1558

1559
1560
1561
1562
1563
1564
1565
1635
1636
1637
1638
1639
1640
1641

1642
1643
1644
1645
1646
1647

1648
1649
1650
1651
1652
1653
1654
1655







-
+





-
+







    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Class *clsPtr, *superPtr;
    Tcl_Obj *resultObj;
    int i;
    Tcl_Size i;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "className");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    clsPtr = TclOOGetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }

    TclNewObj(resultObj);
    FOREACH(superPtr, clsPtr->superclasses) {
	Tcl_ListObjAppendElement(NULL, resultObj,
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
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







+
-
+







+
+
+
+




-
+







    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Class *clsPtr;
    Tcl_Obj *resultObj;
    Tcl_Size i;
    int i, isPrivate = 0;
    int isPrivate = 0;

    if (objc != 2 && objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "className ?-private?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	if (strcmp("-private", TclGetString(objv[2])) != 0) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "option \"%s\" is not exactly \"-private\"",
		    TclGetString(objv[2])));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_ARG");
	    return TCL_ERROR;
	}
	isPrivate = 1;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    clsPtr = TclOOGetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }

    TclNewObj(resultObj);
    if (isPrivate) {
	PrivateVariableMapping *privatePtr;
1656
1657
1658
1659
1660
1661
1662
1663


1664
1665
1666
1667
1668
1669
1670
1751
1752
1753
1754
1755
1756
1757

1758
1759
1760
1761
1762
1763
1764
1765
1766







-
+
+







     * Get the call context and render its call chain.
     */

    contextPtr = TclOOGetCallContext(oPtr, objv[2], PUBLIC_METHOD, NULL, NULL,
	    NULL);
    if (contextPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"cannot construct any call chain", -1));
		"cannot construct any call chain", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_CALL_CHAIN");
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp,
	    TclOORenderCallChain(interp, contextPtr->callPtr));
    TclOODeleteContext(contextPtr);
    return TCL_OK;
}
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
1785
1786
1787
1788
1789
1790
1791

1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803

1804
1805
1806
1807
1808
1809
1810
1811
1812







-
+











-
+
+







    Class *clsPtr;
    CallChain *callPtr;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "className methodName");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    clsPtr = TclOOGetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }

    /*
     * Get an render the stereotypical call chain.
     */

    callPtr = TclOOGetStereotypeCallChain(clsPtr, objv[2], PUBLIC_METHOD);
    if (callPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"cannot construct any call chain", -1));
		"cannot construct any call chain", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_CALL_CHAIN");
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, TclOORenderCallChain(interp, callPtr));
    TclOODeleteChain(callPtr);
    return TCL_OK;
}


Changes to generic/tclOOInt.h.

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
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







-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+






-
-
-
-
+
+
+
+
+

-
-
-
+
+
+
+
+
+

-
-
+

-
-
+




-
+
















-
-
+

-
+




-
+













+
+
+
-
+
+
+
+
+
+
+
+

+
+
+
-
+




+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
+
-




-
-
+



-
+






-
+
-



-
+














-
+

-
+





+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
-
+
+
-
-
-
+





-
+


-
-
+
-
-
-
-
-
-
+
+
+
+
+



-
-
+
+

-
+



















+
-
+
+
+

+
-
-
-
-
+
+
+
+
-
-
+


-
+



-
+



-
+



-
+

+
+
+
+
-
+



-
-
-
-
+






-
+



-
-
+

-
-
+


-
-
+


-
-
+

-
-
+

-
-
+















-
-
+
+







#define Object	TclOOObject
#endif /* __OBJC__ */

/*
 * Forward declarations.
 */

struct CallChain;
struct Class;
struct Foundation;
struct Object;
typedef struct CallChain CallChain;
typedef struct CallContext CallContext;
typedef struct Class Class;
typedef struct DeclaredClassMethod DeclaredClassMethod;
typedef struct ForwardMethod ForwardMethod;
typedef struct Foundation Foundation;
typedef struct Method Method;
typedef struct MInvoke MInvoke;
typedef struct Object Object;
typedef struct PrivateVariableMapping PrivateVariableMapping;
typedef struct ProcedureMethod ProcedureMethod;
typedef struct PropertyStorage PropertyStorage;

/*
 * The data that needs to be stored per method. This record is used to collect
 * information about all sorts of methods, including forwards, constructors
 * and destructors.
 */

typedef struct Method {
    const Tcl_MethodType *typePtr;
				/* The type of method. If NULL, this is a
struct Method {
    union {
	const Tcl_MethodType *typePtr;
	const Tcl_MethodType2 *type2Ptr;
    };				/* The type of method. If NULL, this is a
				 * special flag record which is just used for
				 * the setting of the flags field. */
    size_t refCount;
    void *clientData;	/* Type-specific data. */
				 * the setting of the flags field. Note that
				 * this is a union of two pointer types that
				 * have the same layout at least as far as the
				 * internal version field. */
    Tcl_Size refCount;
    void *clientData;		/* Type-specific data. */
    Tcl_Obj *namePtr;		/* Name of the method. */
    struct Object *declaringObjectPtr;
				/* The object that declares this method, or
    Object *declaringObjectPtr;	/* The object that declares this method, or
				 * NULL if it was declared by a class. */
    struct Class *declaringClassPtr;
				/* The class that declares this method, or
    Class *declaringClassPtr;	/* The class that declares this method, or
				 * NULL if it was declared directly on an
				 * object. */
    int flags;			/* Assorted flags. Includes whether this
				 * method is public/exported or not. */
} Method;
};

/*
 * Pre- and post-call callbacks, to allow procedure-like methods to be fine
 * tuned in their behaviour.
 */

typedef int (TclOO_PreCallProc)(void *clientData, Tcl_Interp *interp,
	Tcl_ObjectContext context, Tcl_CallFrame *framePtr, int *isFinished);
typedef int (TclOO_PostCallProc)(void *clientData, Tcl_Interp *interp,
	Tcl_ObjectContext context, Tcl_Namespace *namespacePtr, int result);
typedef void (TclOO_PmCDDeleteProc)(void *clientData);
typedef void *(TclOO_PmCDCloneProc)(void *clientData);

/*
 * Procedure-like methods have the following extra information.
 */

typedef struct ProcedureMethod {
struct ProcedureMethod {
    int version;		/* Version of this structure. Currently must
				 * be 0. */
				 * be TCLOO_PROCEDURE_METHOD_VERSION_1. */
    Proc *procPtr;		/* Core of the implementation of the method;
				 * includes the argument definition and the
				 * body bytecodes. */
    int flags;			/* Flags to control features. */
    size_t refCount;
    Tcl_Size refCount;
    void *clientData;
    TclOO_PmCDDeleteProc *deleteClientdataProc;
    TclOO_PmCDCloneProc *cloneClientdataProc;
    ProcErrorProc *errProc;	/* Replacement error handler. */
    TclOO_PreCallProc *preCallProc;
				/* Callback to allow for additional setup
				 * before the method executes. */
    TclOO_PostCallProc *postCallProc;
				/* Callback to allow for additional cleanup
				 * after the method executes. */
    GetFrameInfoValueProc *gfivProc;
				/* Callback to allow for fine tuning of how
				 * the method reports itself. */
    Command cmd;		/* Space used to connect to [info frame] */
    ExtraFrameInfo efi;		/* Space used to store data for [info frame] */
    Tcl_Interp *interp;		/* Interpreter in which to compute the name of
} ProcedureMethod;
				 * the method. */
    Tcl_Method method;		/* Method to compute the name of. */
    int callSiteFlags;		/* Flags from the call chain. Only interested
				 * in whether this is a constructor or
				 * destructor, which we can't know until then
				 * for messy reasons. Other flags are variable
				 * but not used. */
};

enum ProcedureMethodVersion {
    TCLOO_PROCEDURE_METHOD_VERSION_1 = 0
};
#define TCLOO_PROCEDURE_METHOD_VERSION 0
#define TCLOO_PROCEDURE_METHOD_VERSION TCLOO_PROCEDURE_METHOD_VERSION_1

/*
 * Flags for use in a ProcedureMethod.
 *
 */
enum ProceudreMethodFlags {
 * When the USE_DECLARER_NS flag is set, the method will use the namespace of
 * the object or class that declared it (or the clone of it, if it was from
 * such that the implementation of the method came to the particular use)
 * instead of the namespace of the object on which the method was invoked.
 * This flag must be distinct from all others that are associated with
 * methods.
    USE_DECLARER_NS = 0x80	/* When set, the method will use the namespace
				 * of the object or class that declared it (or
				 * the clone of it, if it was from such that
				 * the implementation of the method came to the
				 * particular use) instead of the namespace of
				 * the object on which the method was invoked.
				 * This flag must be distinct from all others
				 * that are associated with methods. */
 */

};
#define USE_DECLARER_NS		0x80

/*
 * Forwarded methods have the following extra information.
 */

typedef struct ForwardMethod {
struct ForwardMethod {
    Tcl_Obj *prefixObj;		/* The list of values to use to replace the
				 * object and method name with. Will be a
				 * non-empty list. */
} ForwardMethod;
};

/*
 * Structure used in private variable mappings. Describes the mapping of a
 * single variable from the user's local name to the system's storage name.
 * [TIP #500]
 */

struct PrivateVariableMapping {
typedef struct {
    Tcl_Obj *variableObj;	/* Name used within methods. This is the part
				 * that is properly under user control. */
    Tcl_Obj *fullNameObj;	/* Name used at the instance namespace level. */
} PrivateVariableMapping;
};

/*
 * Helper definitions that declare a "list" array. The two varieties are
 * either optimized for simplicity (in the case that the whole array is
 * typically assigned at once) or efficiency (in the case that the array is
 * expected to be expanded over time). These lists are designed to be iterated
 * over with the help of the FOREACH macro (see later in this file).
 *
 * The "num" field always counts the number of listType_t elements used in the
 * "list" field. When a "size" field exists, it describes how many elements
 * are present in the list; when absent, exactly "num" elements are present.
 */

#define LIST_STATIC(listType_t) \
    struct { int num; listType_t *list; }
    struct { Tcl_Size num; listType_t *list; }
#define LIST_DYNAMIC(listType_t) \
    struct { int num, size; listType_t *list; }
    struct { Tcl_Size num, size; listType_t *list; }

/*
 * These types are needed in function arguments.
 */

typedef LIST_STATIC(Class *) ClassList;
typedef LIST_DYNAMIC(Class *) VarClassList;
typedef LIST_STATIC(Tcl_Obj *) FilterList;
typedef LIST_DYNAMIC(Object *) ObjectList;
typedef LIST_STATIC(Tcl_Obj *) VariableNameList;
typedef LIST_STATIC(PrivateVariableMapping) PrivateVariableList;
typedef LIST_STATIC(Tcl_Obj *) PropertyList;

/*
 * This type is used in various places. It holds the parts of an object or
 * class relating to property information.
 */
struct PropertyStorage {
    PropertyList readable;	/* The readable properties slot. */
    PropertyList writable;	/* The writable properties slot. */
    Tcl_Obj *allReadableCache;	/* The cache of all readable properties
				 * exposed by this object or class (in its
				 * stereotypical instancs). Contains a sorted
				 * unique list if not NULL. */
    Tcl_Obj *allWritableCache;	/* The cache of all writable properties
				 * exposed by this object or class (in its
				 * stereotypical instances). Contains a sorted
				 * unique list if not NULL. */
    int epoch;			/* The epoch that the caches are valid for. */
};

/*
 * Now, the definition of what an object actually is.
 */

typedef struct Object {
    struct Foundation *fPtr;	/* The basis for the object system. Putting
struct Object {
    Foundation *fPtr;		/* The basis for the object system, which is
				 * this here allows the avoidance of quite a
				 * lot of hash lookups on the critical path
				 * for object invocation and creation. */
				 * conceptually part of the interpreter. */
    Tcl_Namespace *namespacePtr;/* This object's namespace. */
    Tcl_Command command;	/* Reference to this object's public
				 * command. */
    Tcl_Command myCommand;	/* Reference to this object's internal
				 * command. */
    struct Class *selfCls;	/* This object's class. */
    Class *selfCls;		/* This object's class. */
    Tcl_HashTable *methodsPtr;	/* Object-local Tcl_Obj (method name) to
				 * Method* mapping. */
    LIST_STATIC(struct Class *) mixins;
				/* Classes mixed into this object. */
    ClassList mixins;		/* Classes mixed into this object. */
    LIST_STATIC(Tcl_Obj *) filters;
				/* List of filter names. */
    struct Class *classPtr;	/* This is non-NULL for all classes, and NULL
				 *  for everything else. It points to the class
				 *  structure. */
    size_t refCount;		/* Number of strong references to this object.
    FilterList filters;		/* List of filter names. */
    Class *classPtr;		/* This is non-NULL for all classes, and NULL
				 * for everything else. It points to the class
				 * structure. */
    Tcl_Size refCount;		/* Number of strong references to this object.
				 * Note that there may be many more weak
				 * references; this mechanism exists to
				 * avoid Tcl_Preserve. */
    int flags;
    size_t creationEpoch;		/* Unique value to make comparisons of objects
    int flags;			/* See ObjectFlags. */
    Tcl_Size creationEpoch;	/* Unique value to make comparisons of objects
				 * easier. */
    size_t epoch;			/* Per-object epoch, incremented when the way
    Tcl_Size epoch;		/* Per-object epoch, incremented when the way
				 * an object should resolve call chains is
				 * changed. */
    Tcl_HashTable *metadataPtr;	/* Mapping from pointers to metadata type to
				 * the void *values that are the values
				 * of each piece of attached metadata. This
				 * field starts out as NULL and is only
				 * allocated if metadata is attached. */
    Tcl_Obj *cachedNameObj;	/* Cache of the name of the object. */
    Tcl_HashTable *chainCache;	/* Place to keep unused contexts. This table
				 * is indexed by method name as Tcl_Obj. */
    Tcl_ObjectMapMethodNameProc *mapMethodNameProc;
				/* Function to allow remapping of method
				 * names. For itcl-ng. */
    VariableNameList variables;
    PrivateVariableList privateVariables;
				/* 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
} Object;
				 * properties that this object *claims* to
				 * support. */
};

enum ObjectFlags {
#define OBJECT_DESTRUCTING	1	/* Indicates that an object is being or has
								 *  been destroyed  */
#define DESTRUCTOR_CALLED 2	/* Indicates that evaluation of destructor script for the
							   object has began */
    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 */
#define OO_UNUSED_4	4	/* No longer used.  */
#define ROOT_OBJECT 0x1000	/* Flag to say that this object is the root of
    ROOT_OBJECT = 0x1000,	/* Flag to say that this object is the root of
				 * the class hierarchy and should be treated
				 * specially during teardown. */
#define FILTER_HANDLING 0x2000	/* Flag set when the object is processing a
    FILTER_HANDLING = 0x2000,	/* Flag set when the object is processing a
				 * filter; when set, filters are *not*
				 * processed on the object, preventing nasty
				 * recursive filtering problems. */
#define USE_CLASS_CACHE 0x4000	/* Flag set to say that the object is a pure
    USE_CLASS_CACHE = 0x4000,	/* Flag set to say that the object is a pure
				 * instance of the class, and has had nothing
				 * added that changes the dispatch chain (i.e.
				 * no methods, mixins, or filters. */
#define ROOT_CLASS 0x8000	/* Flag to say that this object is the root
    ROOT_CLASS = 0x8000,	/* Flag to say that this object is the root
				 * class of classes, and should be treated
				 * specially during teardown (and in a few
				 * other spots). */
#define FORCE_UNKNOWN 0x10000	/* States that we are *really* looking up the
    FORCE_UNKNOWN = 0x10000,	/* States that we are *really* looking up the
				 * unknown method handler at that point. */
    DONT_DELETE = 0x20000,	/* Inhibit deletion of this object. Used
				 * during fundamental object type mutation to
				 * make sure that the object actually survives
				 * to the end of the operation. */
#define HAS_PRIVATE_METHODS 0x20000
    HAS_PRIVATE_METHODS = 0x40000
				/* Object/class has (or had) private methods,
				 * and so shouldn't be cached so
				 * aggressively. */
#define DONT_DELETE 0x40000	/* Inhibit deletion of this object. Used
				 * during fundamental object type mutation to
				 * make sure that the object actually survives
				 * to the end of the operation. */
};

/*
 * And the definition of a class. Note that every class also has an associated
 * object, through which it is manipulated.
 */

typedef struct Class {
struct Class {
    Object *thisPtr;		/* Reference to the object associated with
				 * this class. */
    int flags;			/* Assorted flags. */
    LIST_STATIC(struct Class *) superclasses;
				/* List of superclasses, used for generation
    ClassList superclasses;	/* List of superclasses, used for generation
				 * of method call chains. */
    LIST_DYNAMIC(struct Class *) subclasses;
				/* List of subclasses, used to ensure deletion
    VarClassList subclasses;	/* List of subclasses, used to ensure deletion
				 * of dependent entities happens properly when
				 * the class itself is deleted. */
    LIST_DYNAMIC(Object *) instances;
				/* List of instances, used to ensure deletion
    ObjectList instances;	/* List of instances, used to ensure deletion
				 * of dependent entities happens properly when
				 * the class itself is deleted. */
    LIST_STATIC(Tcl_Obj *) filters;
				/* List of filter names, used for generation
    FilterList filters;		/* List of filter names, used for generation
				 * of method call chains. */
    LIST_STATIC(struct Class *) mixins;
				/* List of mixin classes, used for generation
    ClassList mixins;		/* List of mixin classes, used for generation
				 * of method call chains. */
    LIST_DYNAMIC(struct Class *) mixinSubs;
				/* List of classes that this class is mixed
    VarClassList mixinSubs;	/* List of classes that this class is mixed
				 * into, used to ensure deletion of dependent
				 * entities happens properly when the class
				 * itself is deleted. */
    Tcl_HashTable classMethods;	/* Hash table of all methods. Hash maps from
				 * the (Tcl_Obj*) method name to the (Method*)
				 * method record. */
    Method *constructorPtr;	/* Method record of the class constructor (if
				 * any). */
    Method *destructorPtr;	/* Method record of the class destructor (if
				 * any). */
    Tcl_HashTable *metadataPtr;	/* Mapping from pointers to metadata type to
				 * the void *values that are the values
				 * of each piece of attached metadata. This
				 * field starts out as NULL and is only
				 * allocated if metadata is attached. */
    struct CallChain *constructorChainPtr;
    struct CallChain *destructorChainPtr;
    CallChain *constructorChainPtr;
    CallChain *destructorChainPtr;
    Tcl_HashTable *classChainCache;
				/* Places where call chains are stored. For
				 * constructors, the class chain is always
				 * used. For destructors and ordinary methods,
				 * the class chain is only used when the
				 * object doesn't override with its own mixins
				 * (and filters and method implementations for
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
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

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
467
468

469
470
471

472
473
474

475
476
477

478
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

558
559
560

561
562
563

564
565

566
567
568
569
570
571
572
573
574
575
576











577
578
579
580


581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598



599
600
601
602
603
604
605
606
607

608
609
610
611
612
613
614
615
616



617
618
619
620



621
622
623
624
625
626
627
628
629
630
631
632
633
634


635













636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652

653
654
655
656
657
658

659
660
661
662
663
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
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



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
467
468
469



470
471
472
473



474
475
476


477
478
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
558
559
560


561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591

592
593
594
595
596
597
598
599
600
601
602
603
604
605



606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654

655
656
657
658
659
660

661
662
663
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







+
+
+
-
+


-
-
-
-
+
+

-

-
+







+
+
+
+
+
+
-
-
+
+



-
-
-
-
-
-
-
-



-
+













+
+
+
-
+


-
-
-
-
+
+

-


+
+
+
+








+
+
+
-
-
+
+


-
+

-
+


-
-
-
+
+
+


-
-
+
+

+
+
+
+
+
+
-
+

-
+

-
+




-
+




-
-
-
+
+
+

-
-
-
+
+
+
-
-
+


+





-
+
-



-
+







-
-
+
+
-
-
-
+
-
-
-
+
-
-
-
+
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
+
-
-
-
+
-
-
-
-
-
-
+
-
-
-
+
-
-
-
+
+
-
-
+





-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
+











+
+
+
+
+
+
+
+
+
+
+


-
-
+
+


















+
+
+








-
+









+
+
+

-
-
-
+
+
+














+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
















-
+





-
+




-
-
+
+



-
+




-
-
+
+





-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+







				 * class in when those instances are defined
				 * as instances. If NULL, use the value from
				 * the class hierarchy. It's an error at
				 * [oo::objdefine]/[self] call time if this
				 * namespace is defined but doesn't exist; we
				 * also check at setting time but don't check
				 * between times. */
    PropertyStorage properties;	/* Information relating to the lists of
				 * properties that this class *claims* to
				 * support. */
} Class;
};

/*
 * The foundation of the object system within an interpreter contains
 * references to the key classes and namespaces, together with a few other
 * useful bits and pieces. Probably ought to eventually go in the Interp
 * structure itself.
 * Master epoch counter for making unique IDs for objects that can be compared
 * cheaply.
 */

typedef struct ThreadLocalData {
    size_t nsCount;		/* Epoch counter is used for keeping
    Tcl_Size nsCount;		/* Epoch counter is used for keeping
				 * the values used in Tcl_Obj internal
				 * representations sane. Must be thread-local
				 * because Tcl_Objs can cross interpreter
				 * boundaries within a thread (objects don't
				 * generally cross threads). */
} ThreadLocalData;

/*
 * The foundation of the object system within an interpreter contains
 * references to the key classes and namespaces, together with a few other
 * useful bits and pieces. Probably ought to eventually go in the Interp
 * structure itself.
 */
typedef struct Foundation {
    Tcl_Interp *interp;
struct Foundation {
    Tcl_Interp *interp;		/* The interpreter this is attached to. */
    Class *objectCls;		/* The root of the object system. */
    Class *classCls;		/* The class of all classes. */
    Tcl_Namespace *ooNs;	/* ::oo namespace. */
    Tcl_Namespace *defineNs;	/* Namespace containing special commands for
				 * manipulating objects and classes. The
				 * "oo::define" command acts as a special kind
				 * of ensemble for this namespace. */
    Tcl_Namespace *objdefNs;	/* Namespace containing special commands for
				 * manipulating objects and classes. The
				 * "oo::objdefine" command acts as a special
				 * kind of ensemble for this namespace. */
    Tcl_Namespace *helpersNs;	/* Namespace containing the commands that are
				 * only valid when executing inside a
				 * procedural method. */
    size_t epoch;			/* Used to invalidate method chains when the
    Tcl_Size epoch;		/* Used to invalidate method chains when the
				 * class structure changes. */
    ThreadLocalData *tsdPtr;	/* Counter so we can allocate a unique
				 * namespace to each object. */
    Tcl_Obj *unknownMethodNameObj;
				/* Shared object containing the name of the
				 * unknown method handler method. */
    Tcl_Obj *constructorName;	/* Shared object containing the "name" of a
				 * 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. */
} Foundation;
};

/*
 * A call context structure is built when a method is called. It contains the
 * chain of method implementations that are to be invoked by a particular
 * call, and the process of calling walks the chain, with the [next] command
 * proceeding to the next entry in the chain.
 * The number of MInvoke records in the CallChain before we allocate
 * separately.
 */

#define CALL_CHAIN_STATIC_SIZE 4

/*
 * Information relating to the invocation of a particular method implementation
 * in a call chain.
 */
struct MInvoke {
    Method *mPtr;		/* Reference to the method implementation
				 * record. */
    int isFilter;		/* Whether this is a filter invocation. */
    Class *filterDeclarer;	/* What class decided to add the filter; if
				 * NULL, it was added by the object. */
};

/*
 * The cacheable part of a call context.
 */
typedef struct CallChain {
    size_t objectCreationEpoch;	/* The object's creation epoch. Note that the
struct CallChain {
    Tcl_Size objectCreationEpoch;/* The object's creation epoch. Note that the
				 * object reference is not stored in the call
				 * chain; it is in the call context. */
    size_t objectEpoch;		/* Local (object structure) epoch counter
    Tcl_Size objectEpoch;	/* Local (object structure) epoch counter
				 * snapshot. */
    size_t epoch;			/* Global (class structure) epoch counter
    Tcl_Size epoch;		/* Global (class structure) epoch counter
				 * snapshot. */
    int flags;			/* Assorted flags, see below. */
    size_t refCount;		/* Reference count. */
    int numChain;		/* Size of the call chain. */
    struct MInvoke *chain;	/* Array of call chain entries. May point to
    Tcl_Size refCount;		/* Reference count. */
    Tcl_Size numChain;		/* Size of the call chain. */
    MInvoke *chain;		/* Array of call chain entries. May point to
				 * staticChain if the number of entries is
				 * small. */
    struct MInvoke staticChain[CALL_CHAIN_STATIC_SIZE];
} CallChain;
    MInvoke staticChain[CALL_CHAIN_STATIC_SIZE];
};

/*
 * A call context structure is built when a method is called. It contains the
 * chain of method implementations that are to be invoked by a particular
 * call, and the process of calling walks the chain, with the [next] command
 * proceeding to the next entry in the chain.
 */
typedef struct CallContext {
struct CallContext {
    Object *oPtr;		/* The object associated with this call. */
    int index;			/* Index into the call chain of the currently
    Tcl_Size index;		/* Index into the call chain of the currently
				 * executing method implementation. */
    int skip;			/* Current number of arguments to skip; can
    Tcl_Size skip;		/* Current number of arguments to skip; can
				 * vary depending on whether it is a direct
				 * method call or a continuation via the
				 * [next] command. */
    CallChain *callPtr;		/* The actual call chain. */
} CallContext;
};

/*
 * Bits for the 'flags' field of the call chain.
 */

#define PUBLIC_METHOD     0x01	/* This is a public (exported) method. */
#define PRIVATE_METHOD    0x02	/* This is a private (class's direct instances
enum TclOOCallChainFlags {
    PUBLIC_METHOD = 0x01,	/* This is a public (exported) method. */
    PRIVATE_METHOD = 0x02,	/* This is a private (class's direct instances
				 * only) method. Supports itcl. */
#define OO_UNKNOWN_METHOD 0x04	/* This is an unknown method. */
#define CONSTRUCTOR	  0x08	/* This is a constructor. */
#define DESTRUCTOR	  0x10	/* This is a destructor. */
    OO_UNKNOWN_METHOD = 0x04,	/* This is an unknown method. */
    CONSTRUCTOR = 0x08,		/* This is a constructor. */
    DESTRUCTOR = 0x10,		/* This is a destructor. */
#define TRUE_PRIVATE_METHOD 0x20
				/* This is a private method only accessible
    TRUE_PRIVATE_METHOD = 0x20	/* This is a private method only accessible
				 * from other methods defined on this class
				 * or instance. [TIP #500] */
};
#define SCOPE_FLAGS (PUBLIC_METHOD | PRIVATE_METHOD | TRUE_PRIVATE_METHOD)

/*
 * Structure containing definition information about basic class methods.
 */

struct DeclaredClassMethod {
typedef struct {
    const char *name;		/* Name of the method in question. */
    int isPublic;		/* Whether the method is public by default. */
    Tcl_MethodType definition;	/* How to call the method. */
} DeclaredClassMethod;
};

/*
 *----------------------------------------------------------------
 * Commands relating to OO support.
 *----------------------------------------------------------------
 */

MODULE_SCOPE int	TclOOInit(Tcl_Interp *interp);
MODULE_SCOPE int	TclOODefineObjCmd(void *clientData,
MODULE_SCOPE int		TclOOInit(Tcl_Interp *interp);
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOOObjDefObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclOOObjDefObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineConstructorObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineConstructorObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineDeleteMethodObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineDefnNsObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineDeleteMethodObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineDestructorObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineDestructorObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineExportObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineExportObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineForwardObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineForwardObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineMethodObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineMethodObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineRenameMethodObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineRenameMethodObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineUnexportObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineUnexportObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineClassObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineSelfObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineObjSelfObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOOUnknownDefinition(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOOCopyObjectCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOONextObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOONextToObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineUnexportObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineClassObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineClassObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineSelfObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineSelfObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineObjSelfObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineObjSelfObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefinePrivateObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefinePrivateObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOOUnknownDefinition(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefinePropertyCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOOUnknownDefinition;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOOCopyObjectCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclOOCopyObjectCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineDefnNsObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOONextObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclOONextObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOONextToObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclOONextToObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOOSelfObjCmd(void *clientData,
MODULE_SCOPE Tcl_ObjCmdProc	TclOOSelfObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOOInfoObjectPropCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE Tcl_ObjCmdProc	TclOOInfoClassPropCmd;

/*
 * Method implementations (in tclOOBasic.c).
 */

MODULE_SCOPE int	TclOO_Class_Constructor(void *clientData,
MODULE_SCOPE Tcl_MethodCallProc	TclOO_Class_Constructor;
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOO_Class_Create(void *clientData,
MODULE_SCOPE Tcl_MethodCallProc	TclOO_Class_Create;
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOO_Class_CreateNs(void *clientData,
MODULE_SCOPE Tcl_MethodCallProc	TclOO_Class_CreateNs;
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOO_Class_New(void *clientData,
MODULE_SCOPE Tcl_MethodCallProc	TclOO_Class_New;
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOO_Object_Destroy(void *clientData,
MODULE_SCOPE Tcl_MethodCallProc	TclOO_Object_Destroy;
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOO_Object_Eval(void *clientData,
MODULE_SCOPE Tcl_MethodCallProc	TclOO_Object_Eval;
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOO_Object_LinkVar(void *clientData,
MODULE_SCOPE Tcl_MethodCallProc	TclOO_Object_LinkVar;
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOO_Object_Unknown(void *clientData,
MODULE_SCOPE Tcl_MethodCallProc	TclOO_Object_Unknown;
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOO_Object_VarName(void *clientData,
MODULE_SCOPE Tcl_MethodCallProc	TclOO_Object_VarName;
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
MODULE_SCOPE Tcl_MethodCallProc TclOO_Configurable_Configure;

/*
 * Private definitions, some of which perhaps ought to be exposed properly or
 * maybe just put in the internal stubs table.
 */

MODULE_SCOPE void	TclOOAddToInstances(Object *oPtr, Class *clsPtr);
MODULE_SCOPE void	TclOOAddToMixinSubs(Class *subPtr, Class *mixinPtr);
MODULE_SCOPE void	TclOOAddToSubclasses(Class *subPtr, Class *superPtr);
MODULE_SCOPE Class *	TclOOAllocClass(Tcl_Interp *interp,
			    Object *useThisObj);
MODULE_SCOPE int	TclMethodIsType(Tcl_Method method,
			    const Tcl_MethodType *typePtr,
			    void **clientDataPtr);
MODULE_SCOPE Tcl_Method TclNewInstanceMethod(Tcl_Interp *interp,
			    Tcl_Object object, Tcl_Obj *nameObj,
			    int flags, const Tcl_MethodType *typePtr,
			    void *clientData);
MODULE_SCOPE Tcl_Method TclNewMethod(Tcl_Class cls,
			    Tcl_Obj *nameObj, int flags,
			    const Tcl_MethodType *typePtr,
			    void *clientData);
MODULE_SCOPE int	TclNRNewObjectInstance(Tcl_Interp *interp,
			    Tcl_Class cls, const char *nameStr,
			    const char *nsNameStr, int objc,
			    Tcl_Obj *const *objv, int skip,
			    const char *nsNameStr, Tcl_Size objc,
			    Tcl_Obj *const *objv, Tcl_Size skip,
			    Tcl_Object *objectPtr);
MODULE_SCOPE Object *	TclNewObjectInstanceCommon(Tcl_Interp *interp,
			    Class *classPtr,
			    const char *nameStr,
			    const char *nsNameStr);
MODULE_SCOPE int	TclOODecrRefCount(Object *oPtr);
MODULE_SCOPE int	TclOOObjectDestroyed(Object *oPtr);
MODULE_SCOPE int	TclOODefineSlots(Foundation *fPtr);
MODULE_SCOPE void	TclOODeleteChain(CallChain *callPtr);
MODULE_SCOPE void	TclOODeleteChainCache(Tcl_HashTable *tablePtr);
MODULE_SCOPE void	TclOODeleteContext(CallContext *contextPtr);
MODULE_SCOPE void	TclOODeleteDescendants(Tcl_Interp *interp,
			    Object *oPtr);
MODULE_SCOPE void	TclOODelMethodRef(Method *method);
MODULE_SCOPE CallContext *TclOOGetCallContext(Object *oPtr,
			    Tcl_Obj *methodNameObj, int flags,
			    Object *contextObjPtr, Class *contextClsPtr,
			    Tcl_Obj *cacheInThisObj);
MODULE_SCOPE Class *	TclOOGetClassDefineCmdContext(Tcl_Interp *interp);
MODULE_SCOPE Class *	TclOOGetClassFromObj(Tcl_Interp *interp,
			    Tcl_Obj *objPtr);
MODULE_SCOPE Tcl_Namespace *TclOOGetDefineContextNamespace(
			    Tcl_Interp *interp, Object *oPtr, int forClass);
MODULE_SCOPE CallChain *TclOOGetStereotypeCallChain(Class *clsPtr,
			    Tcl_Obj *methodNameObj, int flags);
MODULE_SCOPE Foundation	*TclOOGetFoundation(Tcl_Interp *interp);
MODULE_SCOPE Tcl_Obj *	TclOOGetFwdFromMethod(Method *mPtr);
MODULE_SCOPE Proc *	TclOOGetProcFromMethod(Method *mPtr);
MODULE_SCOPE Tcl_Obj *	TclOOGetMethodBody(Method *mPtr);
MODULE_SCOPE int	TclOOGetSortedClassMethodList(Class *clsPtr,
MODULE_SCOPE size_t	TclOOGetSortedClassMethodList(Class *clsPtr,
			    int flags, const char ***stringsPtr);
MODULE_SCOPE int	TclOOGetSortedMethodList(Object *oPtr,
			    Object *contextObj, Class *contextCls, int flags,
			    const char ***stringsPtr);
MODULE_SCOPE int	TclOOInit(Tcl_Interp *interp);
MODULE_SCOPE void	TclOOInitInfo(Tcl_Interp *interp);
MODULE_SCOPE int	TclOOInvokeContext(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Var	TclOOLookupObjectVar(Tcl_Interp *interp,
			    Tcl_Object object, Tcl_Obj *varName,
			    Tcl_Var *aryPtr);
MODULE_SCOPE int	TclNRObjectContextInvokeNext(Tcl_Interp *interp,
			    Tcl_ObjectContext context, int objc,
			    Tcl_Obj *const *objv, int skip);
MODULE_SCOPE void	TclOONewBasicMethod(Tcl_Interp *interp, Class *clsPtr,
			    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,
			    Class *superPtr);
MODULE_SCOPE Tcl_Obj *	TclOORenderCallChain(Tcl_Interp *interp,
			    CallChain *callPtr);
MODULE_SCOPE void	TclOOStashContext(Tcl_Obj *objPtr,
			    CallContext *contextPtr);
MODULE_SCOPE Tcl_Obj *	TclOOGetAllObjectProperties(Object *oPtr,
			    int writable);
MODULE_SCOPE void	TclOOSetupVariableResolver(Tcl_Namespace *nsPtr);
MODULE_SCOPE Tcl_Obj *	TclOOGetPropertyList(PropertyList *propList);
MODULE_SCOPE void	TclOOReleasePropertyStorage(PropertyStorage *propsPtr);
MODULE_SCOPE void	TclOOInstallReadableProperties(PropertyStorage *props,
			    Tcl_Size objc, Tcl_Obj *const objv[]);
MODULE_SCOPE void	TclOOInstallWritableProperties(PropertyStorage *props,
			    Tcl_Size objc, Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclOOInstallStdPropertyImpls(void *useInstance,
			    Tcl_Interp *interp, Tcl_Obj *propName,
			    int readable, int writable);
MODULE_SCOPE void	TclOORegisterProperty(Class *clsPtr,
			    Tcl_Obj *propName, int mayRead, int mayWrite);
MODULE_SCOPE void	TclOORegisterInstanceProperty(Object *oPtr,
			    Tcl_Obj *propName, int mayRead, int mayWrite);

/*
 * Include all the private API, generated from tclOO.decls.
 */

#include "tclOOIntDecls.h"

/*
 * Alternatives to Tcl_Preserve/Tcl_EventuallyFree/Tcl_Release.
 */

#define AddRef(ptr) ((ptr)->refCount++)

/*
 * A convenience macro for iterating through the lists used in the internal
 * memory management of objects.
 * REQUIRES DECLARATION: int i;
 * REQUIRES DECLARATION: Tcl_Size i;
 */

#define FOREACH(var,ary) \
    for(i=0 ; i<(ary).num; i++) if ((ary).list[i] == NULL) { \
	continue; \
    } else if (var = (ary).list[i], 1)
    } else if ((var) = (ary).list[i], 1)

/*
 * A variation where the array is an array of structs. There's no issue with
 * possible NULLs; every element of the array will be iterated over and the
 * varable set to a pointer to each of those elements in turn.
 * REQUIRES DECLARATION: int i;
 * variable set to a pointer to each of those elements in turn.
 * REQUIRES DECLARATION: Tcl_Size i; See [96551aca55] for more FOREACH_STRUCT details.
 */

#define FOREACH_STRUCT(var,ary) \
    for(i=0 ; var=&((ary).list[i]), i<(ary).num; i++)
    if (i=0, (ary).num>0) for(; var=&((ary).list[i]), i<(ary).num; i++)

/*
 * Convenience macros for iterating through hash tables. FOREACH_HASH_DECLS
 * sets up the declarations needed for the main macro, FOREACH_HASH, which
 * does the actual iteration. FOREACH_HASH_VALUE is a restricted version that
 * only iterates over values.
 * does the actual iteration. FOREACH_HASH_KEY and FOREACH_HASH_VALUE are
 * restricted versions that only iterate over keys or values respectively.
 * REQUIRES DECLARATION: FOREACH_HASH_DECLS;
 */

#define FOREACH_HASH_DECLS \
    Tcl_HashEntry *hPtr;Tcl_HashSearch search
#define FOREACH_HASH(key,val,tablePtr) \
    for(hPtr=Tcl_FirstHashEntry((tablePtr),&search); hPtr!=NULL ? \
	    (*(void **)&(key)=Tcl_GetHashKey((tablePtr),hPtr),\
	    *(void **)&(val)=Tcl_GetHashValue(hPtr),1):0; hPtr=Tcl_NextHashEntry(&search))
#define FOREACH_HASH_VALUE(val,tablePtr) \
    for(hPtr=Tcl_FirstHashEntry((tablePtr),&search); hPtr!=NULL ? \
	    (*(void **)&(val)=Tcl_GetHashValue(hPtr),1):0;hPtr=Tcl_NextHashEntry(&search))
#define FOREACH_HASH(key, val, tablePtr) \
    for(hPtr = Tcl_FirstHashEntry((tablePtr), &search); hPtr != NULL ? \
	    (*(void **)&(key) = Tcl_GetHashKey((tablePtr), hPtr), \
	    *(void **)&(val) = Tcl_GetHashValue(hPtr), 1) : 0; \
	    hPtr = Tcl_NextHashEntry(&search))
#define FOREACH_HASH_KEY(key, tablePtr) \
    for(hPtr = Tcl_FirstHashEntry((tablePtr), &search); hPtr != NULL ? \
	    (*(void **)&(key) = Tcl_GetHashKey((tablePtr), hPtr), 1) : 0; \
	    hPtr = Tcl_NextHashEntry(&search))
#define FOREACH_HASH_VALUE(val, tablePtr) \
    for(hPtr = Tcl_FirstHashEntry((tablePtr), &search); hPtr != NULL ? \
	    (*(void **)&(val) = Tcl_GetHashValue(hPtr), 1) : 0; \
	    hPtr = Tcl_NextHashEntry(&search))

/*
 * Convenience macro for duplicating a list. Needs no external declaration,
 * but all arguments are used multiple times and so must have no side effects.
 */

#undef DUPLICATE /* prevent possible conflict with definition in WINAPI nb30.h */

Changes to generic/tclOOIntDecls.h.

38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
38
39
40
41
42
43
44

45
46
47
48
49
50
51
52







-
+







/* 4 */
TCLAPI Method *		TclOONewProcMethod(Tcl_Interp *interp, Class *clsPtr,
				int flags, Tcl_Obj *nameObj,
				Tcl_Obj *argsObj, Tcl_Obj *bodyObj,
				ProcedureMethod **pmPtrPtr);
/* 5 */
TCLAPI int		TclOOObjectCmdCore(Object *oPtr, Tcl_Interp *interp,
				int objc, Tcl_Obj *const *objv,
				Tcl_Size objc, Tcl_Obj *const *objv,
				int publicOnly, Class *startCls);
/* 6 */
TCLAPI int		TclOOIsReachable(Class *targetPtr, Class *startPtr);
/* 7 */
TCLAPI Method *		TclOONewForwardMethod(Tcl_Interp *interp,
				Class *clsPtr, int isPublic,
				Tcl_Obj *nameObj, Tcl_Obj *prefixObj);
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
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







-
+


-
-
+
+


-
+


-
-
+
+


-
+











-
+





-
-
-
-
-
+
+
+
+
+







				ProcErrorProc *errProc, void *clientData,
				Tcl_Obj *nameObj, Tcl_Obj *argsObj,
				Tcl_Obj *bodyObj, int flags,
				void **internalTokenPtr);
/* 11 */
TCLAPI int		TclOOInvokeObject(Tcl_Interp *interp,
				Tcl_Object object, Tcl_Class startCls,
				int publicPrivate, int objc,
				int publicPrivate, Tcl_Size objc,
				Tcl_Obj *const *objv);
/* 12 */
TCLAPI void		TclOOObjectSetFilters(Object *oPtr, int numFilters,
				Tcl_Obj *const *filters);
TCLAPI void		TclOOObjectSetFilters(Object *oPtr,
				Tcl_Size numFilters, Tcl_Obj *const *filters);
/* 13 */
TCLAPI void		TclOOClassSetFilters(Tcl_Interp *interp,
				Class *classPtr, int numFilters,
				Class *classPtr, Tcl_Size numFilters,
				Tcl_Obj *const *filters);
/* 14 */
TCLAPI void		TclOOObjectSetMixins(Object *oPtr, int numMixins,
				Class *const *mixins);
TCLAPI void		TclOOObjectSetMixins(Object *oPtr,
				Tcl_Size numMixins, Class *const *mixins);
/* 15 */
TCLAPI void		TclOOClassSetMixins(Tcl_Interp *interp,
				Class *classPtr, int numMixins,
				Class *classPtr, Tcl_Size numMixins,
				Class *const *mixins);

typedef struct TclOOIntStubs {
    int magic;
    void *hooks;

    Tcl_Object (*tclOOGetDefineCmdContext) (Tcl_Interp *interp); /* 0 */
    Tcl_Method (*tclOOMakeProcInstanceMethod) (Tcl_Interp *interp, Object *oPtr, int flags, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, const Tcl_MethodType *typePtr, void *clientData, Proc **procPtrPtr); /* 1 */
    Tcl_Method (*tclOOMakeProcMethod) (Tcl_Interp *interp, Class *clsPtr, int flags, Tcl_Obj *nameObj, const char *namePtr, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, const Tcl_MethodType *typePtr, void *clientData, Proc **procPtrPtr); /* 2 */
    Method * (*tclOONewProcInstanceMethod) (Tcl_Interp *interp, Object *oPtr, int flags, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, ProcedureMethod **pmPtrPtr); /* 3 */
    Method * (*tclOONewProcMethod) (Tcl_Interp *interp, Class *clsPtr, int flags, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, ProcedureMethod **pmPtrPtr); /* 4 */
    int (*tclOOObjectCmdCore) (Object *oPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv, int publicOnly, Class *startCls); /* 5 */
    int (*tclOOObjectCmdCore) (Object *oPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const *objv, int publicOnly, Class *startCls); /* 5 */
    int (*tclOOIsReachable) (Class *targetPtr, Class *startPtr); /* 6 */
    Method * (*tclOONewForwardMethod) (Tcl_Interp *interp, Class *clsPtr, int isPublic, Tcl_Obj *nameObj, Tcl_Obj *prefixObj); /* 7 */
    Method * (*tclOONewForwardInstanceMethod) (Tcl_Interp *interp, Object *oPtr, int isPublic, Tcl_Obj *nameObj, Tcl_Obj *prefixObj); /* 8 */
    Tcl_Method (*tclOONewProcInstanceMethodEx) (Tcl_Interp *interp, Tcl_Object oPtr, TclOO_PreCallProc *preCallPtr, TclOO_PostCallProc *postCallPtr, ProcErrorProc *errProc, void *clientData, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, int flags, void **internalTokenPtr); /* 9 */
    Tcl_Method (*tclOONewProcMethodEx) (Tcl_Interp *interp, Tcl_Class clsPtr, TclOO_PreCallProc *preCallPtr, TclOO_PostCallProc *postCallPtr, ProcErrorProc *errProc, void *clientData, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, int flags, void **internalTokenPtr); /* 10 */
    int (*tclOOInvokeObject) (Tcl_Interp *interp, Tcl_Object object, Tcl_Class startCls, int publicPrivate, int objc, Tcl_Obj *const *objv); /* 11 */
    void (*tclOOObjectSetFilters) (Object *oPtr, int numFilters, Tcl_Obj *const *filters); /* 12 */
    void (*tclOOClassSetFilters) (Tcl_Interp *interp, Class *classPtr, int numFilters, Tcl_Obj *const *filters); /* 13 */
    void (*tclOOObjectSetMixins) (Object *oPtr, int numMixins, Class *const *mixins); /* 14 */
    void (*tclOOClassSetMixins) (Tcl_Interp *interp, Class *classPtr, int numMixins, Class *const *mixins); /* 15 */
    int (*tclOOInvokeObject) (Tcl_Interp *interp, Tcl_Object object, Tcl_Class startCls, int publicPrivate, Tcl_Size objc, Tcl_Obj *const *objv); /* 11 */
    void (*tclOOObjectSetFilters) (Object *oPtr, Tcl_Size numFilters, Tcl_Obj *const *filters); /* 12 */
    void (*tclOOClassSetFilters) (Tcl_Interp *interp, Class *classPtr, Tcl_Size numFilters, Tcl_Obj *const *filters); /* 13 */
    void (*tclOOObjectSetMixins) (Object *oPtr, Tcl_Size numMixins, Class *const *mixins); /* 14 */
    void (*tclOOClassSetMixins) (Tcl_Interp *interp, Class *classPtr, Tcl_Size numMixins, Class *const *mixins); /* 15 */
} TclOOIntStubs;

extern const TclOOIntStubs *tclOOIntStubsPtr;

#ifdef __cplusplus
}
#endif

Changes to generic/tclOOMethod.c.

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
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
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


30
31
32
33
34
35
36

37
38
39
40
41
42
43
44





-
+












-
-
-
-
-
-
-
-
-
-
-





-
+



-
+
-
-
-
-
+
-
-







-
+







/*
 * tclOOMethod.c --
 *
 *	This file contains code to create and manage methods.
 *
 * Copyright (c) 2005-2011 by Donal K. Fellows
 * Copyright © 2005-2011 Donal K. Fellows
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

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

/*
 * Structure used to help delay computing names of objects or classes for
 * [info frame] until needed, making invokation faster in the normal case.
 */

struct PNI {
    Tcl_Interp *interp;		/* Interpreter in which to compute the name of
				 * a method. */
    Tcl_Method method;		/* Method to compute the name of. */
};

/*
 * Structure used to contain all the information needed about a call frame
 * used in a procedure-like method.
 */

typedef struct {
typedef struct PMFrameData {
    CallFrame *framePtr;	/* Reference to the call frame itself (it's
				 * actually allocated on the Tcl stack). */
    ProcErrorProc *errProc;	/* The error handler for the body. */
    Tcl_Obj *nameObj;		/* The "name" of the command. */
    Tcl_Obj *nameObj;		/* The "name" of the command. Only used for a
    Command cmd;		/* The command structure. Mostly bogus. */
    ExtraFrameInfo efi;		/* Extra information used for [info frame]. */
    Command *oldCmdPtr;		/* Saved cmdPtr so that we can be safe after a
				 * recursive call returns. */
				 * few moments, so not reference. */
    struct PNI pni;		/* Specialist information used in the efi
				 * field for this type of call. */
} PMFrameData;

/*
 * Structure used to pass information about variable resolution to the
 * on-the-ground resolvers used when working with resolved compiled variables.
 */

typedef struct {
typedef struct OOResVarInfo {
    Tcl_ResolvedVarInfo info;	/* "Type" information so that the compiled
				 * variable can be linked to the namespace
				 * variable at the right time. */
    Tcl_Obj *variableObj;	/* The name of the variable. */
    Tcl_Var cachedObjectVar;	/* TODO: When to flush this cache? Can class
				 * variables be cached? */
} OOResVarInfo;
79
80
81
82
83
84
85

86
87
88
89
90
91
92
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77







+







static void		DeleteProcedureMethodRecord(ProcedureMethod *pmPtr);
static void		DeleteProcedureMethod(void *clientData);
static int		CloneProcedureMethod(Tcl_Interp *interp,
			    void *clientData, void **newClientData);
static ProcErrorProc	MethodErrorHandler;
static ProcErrorProc	ConstructorErrorHandler;
static ProcErrorProc	DestructorErrorHandler;
static Tcl_Obj *	RenderMethodName(void *clientData);
static Tcl_Obj *	RenderDeclarerName(void *clientData);
static int		InvokeForwardMethod(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static void		DeleteForwardMethod(void *clientData);
static int		CloneForwardMethod(Tcl_Interp *interp,
			    void *clientData, void **newClientData);
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+












-
+




















-
+





-
+



-
+

-
+





-
+







 * Helper macros (derived from things private to tclVar.c)
 */

#define TclVarTable(contextNs) \
    ((Tcl_HashTable *) (&((Namespace *) (contextNs))->varTable))
#define TclVarHashGetValue(hPtr) \
    ((Tcl_Var) ((char *)hPtr - offsetof(VarInHash, entry)))

static inline ProcedureMethod *
AllocProcedureMethodRecord(
    int flags)
{
    ProcedureMethod *pmPtr = (ProcedureMethod *)
	    Tcl_Alloc(sizeof(ProcedureMethod));
    memset(pmPtr, 0, sizeof(ProcedureMethod));
    pmPtr->version = TCLOO_PROCEDURE_METHOD_VERSION;
    pmPtr->flags = flags & USE_DECLARER_NS;
    pmPtr->refCount = 1;
    pmPtr->cmd.clientData = &pmPtr->efi;
    return pmPtr;
}

/*
 * ----------------------------------------------------------------------
 *
 * Tcl_NewInstanceMethod --
 *
 *	Attach a method to an object instance.
 *
 * ----------------------------------------------------------------------
 */

Tcl_Method
Tcl_NewInstanceMethod(
TclNewInstanceMethod(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Object object,		/* The object that has the method attached to
				 * it. */
    Tcl_Obj *nameObj,		/* The name of the method. May be NULL; if so,
				 * up to caller to manage storage (e.g., when
				 * it is a constructor or destructor). */
    int flags,			/* Whether this is a public method. */
    const Tcl_MethodType *typePtr,
				/* The type of method this is, which defines
				 * how to invoke, delete and clone the
				 * method. */
    void *clientData)		/* Some data associated with the particular
				 * method to be created. */
{
    Object *oPtr = (Object *) object;
    Method *mPtr;
    Tcl_HashEntry *hPtr;
    int isNew;

    if (nameObj == NULL) {
	mPtr = (Method *)Tcl_Alloc(sizeof(Method));
	mPtr = (Method *) Tcl_Alloc(sizeof(Method));
	mPtr->namePtr = NULL;
	mPtr->refCount = 1;
	goto populate;
    }
    if (!oPtr->methodsPtr) {
	oPtr->methodsPtr = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));
	oPtr->methodsPtr = (Tcl_HashTable *) Tcl_Alloc(sizeof(Tcl_HashTable));
	Tcl_InitObjHashTable(oPtr->methodsPtr);
	oPtr->flags &= ~USE_CLASS_CACHE;
    }
    hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, (char *) nameObj, &isNew);
    hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, nameObj, &isNew);
    if (isNew) {
	mPtr = (Method *)Tcl_Alloc(sizeof(Method));
	mPtr = (Method *) Tcl_Alloc(sizeof(Method));
	mPtr->namePtr = nameObj;
	mPtr->refCount = 1;
	Tcl_IncrRefCount(nameObj);
	Tcl_SetHashValue(hPtr, mPtr);
    } else {
	mPtr = (Method *)Tcl_GetHashValue(hPtr);
	mPtr = (Method *) Tcl_GetHashValue(hPtr);
	if (mPtr->typePtr != NULL && mPtr->typePtr->deleteProc != NULL) {
	    mPtr->typePtr->deleteProc(mPtr->clientData);
	}
    }

  populate:
    mPtr->typePtr = typePtr;
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












-
+
-


















-
+




-
+

-
+





-
+







	if (flags & TRUE_PRIVATE_METHOD) {
	    oPtr->flags |= HAS_PRIVATE_METHODS;
	}
    }
    oPtr->epoch++;
    return (Tcl_Method) mPtr;
}
Tcl_Method
Tcl_NewInstanceMethod(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Object object,		/* The object that has the method attached to
				 * it. */
    Tcl_Obj *nameObj,		/* The name of the method. May be NULL; if so,
				 * up to caller to manage storage (e.g., when
				 * it is a constructor or destructor). */
    int flags,			/* Whether this is a public method. */
    const Tcl_MethodType *typePtr,
				/* The type of method this is, which defines
				 * how to invoke, delete and clone the
				 * method. */
    void *clientData)		/* Some data associated with the particular
				 * method to be created. */
{
    if (typePtr->version > TCL_OO_METHOD_VERSION_1) {
	Tcl_Panic("%s: Wrong version in typePtr->version, should be %s",
		"Tcl_NewInstanceMethod", "TCL_OO_METHOD_VERSION_1");
    }
    return TclNewInstanceMethod(NULL, object, nameObj, flags, typePtr,
	    clientData);
}
Tcl_Method
Tcl_NewInstanceMethod2(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Object object,		/* The object that has the method attached to
				 * it. */
    Tcl_Obj *nameObj,		/* The name of the method. May be NULL; if so,
				 * up to caller to manage storage (e.g., when
				 * it is a constructor or destructor). */
    int flags,			/* Whether this is a public method. */
    const Tcl_MethodType2 *typePtr,
				/* The type of method this is, which defines
				 * how to invoke, delete and clone the
				 * method. */
    void *clientData)		/* Some data associated with the particular
				 * method to be created. */
{
    if (typePtr->version < TCL_OO_METHOD_VERSION_2) {
	Tcl_Panic("%s: Wrong version in typePtr->version, should be %s",
		"Tcl_NewInstanceMethod2", "TCL_OO_METHOD_VERSION_2");
    }
    return TclNewInstanceMethod(NULL, object, nameObj, flags,
	    (const Tcl_MethodType *) typePtr, clientData);
}

/*
 * ----------------------------------------------------------------------
 *
 * Tcl_NewMethod --
 *
 *	Attach a method to a class.
 *
 * ----------------------------------------------------------------------
 */

Tcl_Method
Tcl_NewMethod(
TclNewMethod(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Class cls,		/* The class to attach the method to. */
    Tcl_Obj *nameObj,		/* The name of the object. May be NULL (e.g.,
				 * for constructors or destructors); if so, up
				 * to caller to manage storage. */
    int flags,			/* Whether this is a public method. */
    const Tcl_MethodType *typePtr,
				/* The type of method this is, which defines
				 * how to invoke, delete and clone the
				 * method. */
    void *clientData)		/* Some data associated with the particular
				 * method to be created. */
{
    Class *clsPtr = (Class *) cls;
    Method *mPtr;
    Tcl_HashEntry *hPtr;
    int isNew;

    if (nameObj == NULL) {
	mPtr = (Method *)Tcl_Alloc(sizeof(Method));
	mPtr = (Method *) Tcl_Alloc(sizeof(Method));
	mPtr->namePtr = NULL;
	mPtr->refCount = 1;
	goto populate;
    }
    hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, (char *)nameObj,&isNew);
    hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, nameObj, &isNew);
    if (isNew) {
	mPtr = (Method *)Tcl_Alloc(sizeof(Method));
	mPtr = (Method *) Tcl_Alloc(sizeof(Method));
	mPtr->refCount = 1;
	mPtr->namePtr = nameObj;
	Tcl_IncrRefCount(nameObj);
	Tcl_SetHashValue(hPtr, mPtr);
    } else {
	mPtr = (Method *)Tcl_GetHashValue(hPtr);
	mPtr = (Method *) Tcl_GetHashValue(hPtr);
	if (mPtr->typePtr != NULL && mPtr->typePtr->deleteProc != NULL) {
	    mPtr->typePtr->deleteProc(mPtr->clientData);
	}
    }

  populate:
    clsPtr->thisPtr->fPtr->epoch++;
251
252
253
254
255
256
257













































258
259
260
261
262
263
264
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	if (flags & TRUE_PRIVATE_METHOD) {
	    clsPtr->flags |= HAS_PRIVATE_METHODS;
	}
    }

    return (Tcl_Method) mPtr;
}

Tcl_Method
Tcl_NewMethod(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Class cls,		/* The class to attach the method to. */
    Tcl_Obj *nameObj,		/* The name of the object. May be NULL (e.g.,
				 * for constructors or destructors); if so, up
				 * to caller to manage storage. */
    int flags,			/* Whether this is a public method. */
    const Tcl_MethodType *typePtr,
				/* The type of method this is, which defines
				 * how to invoke, delete and clone the
				 * method. */
    void *clientData)		/* Some data associated with the particular
				 * method to be created. */
{
    if (typePtr->version > TCL_OO_METHOD_VERSION_1) {
	Tcl_Panic("%s: Wrong version in typePtr->version, should be %s",
		"Tcl_NewMethod", "TCL_OO_METHOD_VERSION_1");
    }
    return TclNewMethod(cls, nameObj, flags, typePtr, clientData);
}

Tcl_Method
Tcl_NewMethod2(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Class cls,		/* The class to attach the method to. */
    Tcl_Obj *nameObj,		/* The name of the object. May be NULL (e.g.,
				 * for constructors or destructors); if so, up
				 * to caller to manage storage. */
    int flags,			/* Whether this is a public method. */
    const Tcl_MethodType2 *typePtr,
				/* The type of method this is, which defines
				 * how to invoke, delete and clone the
				 * method. */
    void *clientData)		/* Some data associated with the particular
				 * method to be created. */
{
    if (typePtr->version < TCL_OO_METHOD_VERSION_2) {
	Tcl_Panic("%s: Wrong version in typePtr->version, should be %s",
		"Tcl_NewMethod2", "TCL_OO_METHOD_VERSION_2");
    }
    return TclNewMethod(cls, nameObj, flags,
	    (const Tcl_MethodType *) typePtr, clientData);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOODelMethodRef --
 *
 *	How to delete a method.
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
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







-
+








-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+
+







	Tcl_Free(mPtr);
    }
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOONewBasicMethod --
 * TclOODefineBasicMethods --
 *
 *	Helper that makes it cleaner to create very simple methods during
 *	basic system initialization. Not suitable for general use.
 *
 * ----------------------------------------------------------------------
 */

void
TclOONewBasicMethod(
TclOODefineBasicMethods(
    Tcl_Interp *interp,
    Class *clsPtr,		/* Class to attach the method to. */
    const DeclaredClassMethod *dcm)
				/* Name of the method, whether it is public,
				 * and the function to implement it. */
{
    Tcl_Obj *namePtr = Tcl_NewStringObj(dcm->name, -1);
    Class *clsPtr,		/* Class to attach the methods to. */
    const DeclaredClassMethod *dcmAry)
				/* Static table of method definitions. */
{
    int i;

    for (i = 0 ; dcmAry[i].name ; i++) {
	Tcl_Obj *namePtr = Tcl_NewStringObj(dcmAry[i].name, TCL_AUTO_LENGTH);

    Tcl_IncrRefCount(namePtr);
    Tcl_NewMethod(interp, (Tcl_Class) clsPtr, namePtr,
	    (dcm->isPublic ? PUBLIC_METHOD : 0), &dcm->definition, NULL);
    Tcl_DecrRefCount(namePtr);
	TclNewMethod((Tcl_Class) clsPtr, namePtr,
		(dcmAry[i].isPublic ? PUBLIC_METHOD : 0),
		&dcmAry[i].definition, NULL);
	Tcl_BounceRefCount(namePtr);
    }
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOONewProcInstanceMethod --
 *
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
422
423
424
425
426
427
428

429
430
431
432

433
434
435






436
437
438
439
440
441
442
443







-
+



-
+


-
-
-
-
-
-
+







    Tcl_Obj *bodyObj,		/* The body of the method, which must not be
				 * NULL. */
    ProcedureMethod **pmPtrPtr)	/* Place to write pointer to procedure method
				 * structure to allow for deeper tuning of the
				 * structure's contents. NULL if caller is not
				 * interested. */
{
    int argsLen;
    Tcl_Size argsLen;
    ProcedureMethod *pmPtr;
    Tcl_Method method;

    if (Tcl_ListObjLength(interp, argsObj, &argsLen) != TCL_OK) {
    if (TclListObjLength(interp, argsObj, &argsLen) != TCL_OK) {
	return NULL;
    }
    pmPtr = (ProcedureMethod *)Tcl_Alloc(sizeof(ProcedureMethod));
    memset(pmPtr, 0, sizeof(ProcedureMethod));
    pmPtr->version = TCLOO_PROCEDURE_METHOD_VERSION;
    pmPtr->flags = flags & USE_DECLARER_NS;
    pmPtr->refCount = 1;

    pmPtr = AllocProcedureMethodRecord(flags);
    method = TclOOMakeProcInstanceMethod(interp, oPtr, flags, nameObj,
	    argsObj, bodyObj, &procMethodType, pmPtr, &pmPtr->procPtr);
    if (method == NULL) {
	Tcl_Free(pmPtr);
    } else if (pmPtrPtr != NULL) {
	*pmPtrPtr = pmPtr;
    }
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
469
470
471
472
473
474
475

476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597







-
+





-
+



-
+





-
-
-
-
-
-
+



-
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    Tcl_Obj *bodyObj,		/* The body of the method, which must not be
				 * NULL. */
    ProcedureMethod **pmPtrPtr)	/* Place to write pointer to procedure method
				 * structure to allow for deeper tuning of the
				 * structure's contents. NULL if caller is not
				 * interested. */
{
    int argsLen;		/* -1 => delete argsObj before exit */
    Tcl_Size argsLen;		/* TCL_INDEX_NONE => delete argsObj before exit */
    ProcedureMethod *pmPtr;
    const char *procName;
    Tcl_Method method;

    if (argsObj == NULL) {
	argsLen = -1;
	argsLen = TCL_INDEX_NONE;
	TclNewObj(argsObj);
	Tcl_IncrRefCount(argsObj);
	procName = "<destructor>";
    } else if (Tcl_ListObjLength(interp, argsObj, &argsLen) != TCL_OK) {
    } else if (TclListObjLength(interp, argsObj, &argsLen) != TCL_OK) {
	return NULL;
    } else {
	procName = (nameObj==NULL ? "<constructor>" : TclGetString(nameObj));
    }

    pmPtr = (ProcedureMethod *)Tcl_Alloc(sizeof(ProcedureMethod));
    memset(pmPtr, 0, sizeof(ProcedureMethod));
    pmPtr->version = TCLOO_PROCEDURE_METHOD_VERSION;
    pmPtr->flags = flags & USE_DECLARER_NS;
    pmPtr->refCount = 1;

    pmPtr = AllocProcedureMethodRecord(flags);
    method = TclOOMakeProcMethod(interp, clsPtr, flags, nameObj, procName,
	    argsObj, bodyObj, &procMethodType, pmPtr, &pmPtr->procPtr);

    if (argsLen == -1) {
    if (argsLen == TCL_INDEX_NONE) {
	Tcl_DecrRefCount(argsObj);
    }
    if (method == NULL) {
	Tcl_Free(pmPtr);
    } else if (pmPtrPtr != NULL) {
	*pmPtrPtr = pmPtr;
    }

    return (Method *) method;
}

/*
 * ----------------------------------------------------------------------
 *
 * InitCmdFrame --
 *
 *	Set up a CmdFrame to record the source location for a procedure
 *	method. Assumes that the body is the last argument to the command
 *	creating the method, a good assumption because putting the body
 *	elsewhere is ugly.
 *
 * ----------------------------------------------------------------------
 */
static inline void
InitCmdFrame(
    Interp *iPtr,		/* Where source locations are recorded. */
    Proc *procPtr)		/* Guts of the method being made. */
{
    if (iPtr->cmdFramePtr) {
	CmdFrame context = *iPtr->cmdFramePtr;

	if (context.type == TCL_LOCATION_BC) {
	    /*
	     * Retrieve source information from the bytecode, if possible. If
	     * the information is retrieved successfully, context.type will be
	     * TCL_LOCATION_SOURCE and the reference held by
	     * context.data.eval.path will be counted.
	     */

	    TclGetSrcInfoForPc(&context);
	} else if (context.type == TCL_LOCATION_SOURCE) {
	    /*
	     * The copy into 'context' up above has created another reference
	     * to 'context.data.eval.path'; account for it.
	     */

	    Tcl_IncrRefCount(context.data.eval.path);
	}

	if (context.type == TCL_LOCATION_SOURCE) {
	    /*
	     * We can account for source location within a proc only if the
	     * proc body was not created by substitution. This is where we
	     * assume that the body is the last argument; the index of the body
	     * is NOT a fixed count of arguments in because of the alternate
	     * form of [oo::define]/[oo::objdefine].
	     * (FIXME: check that this is sane and correct!)
	     */

	    if (context.line && context.nline > 1
		    && (context.line[context.nline - 1] >= 0)) {
		int isNew;
		CmdFrame *cfPtr = (CmdFrame *) Tcl_Alloc(sizeof(CmdFrame));
		Tcl_HashEntry *hPtr;

		cfPtr->level = -1;
		cfPtr->type = context.type;
		cfPtr->line = (Tcl_Size *) Tcl_Alloc(sizeof(Tcl_Size));
		cfPtr->line[0] = context.line[context.nline - 1];
		cfPtr->nline = 1;
		cfPtr->framePtr = NULL;
		cfPtr->nextPtr = NULL;

		cfPtr->data.eval.path = context.data.eval.path;
		Tcl_IncrRefCount(cfPtr->data.eval.path);

		cfPtr->cmd = NULL;
		cfPtr->len = 0;

		hPtr = Tcl_CreateHashEntry(iPtr->linePBodyPtr,
			procPtr, &isNew);
		Tcl_SetHashValue(hPtr, cfPtr);
	    }

	    /*
	     * 'context' is going out of scope; account for the reference that
	     * it's holding to the path name.
	     */

	    Tcl_DecrRefCount(context.data.eval.path);
	    context.data.eval.path = NULL;
	}
    }}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOMakeProcInstanceMethod --
 *
 *	The guts of the code to make a procedure-like method for an object.
 *	Split apart so that it is easier for other extensions to reuse (in
446
447
448
449
450
451
452
453

454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471

472
473
474
475
476
477
478
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
610
611
612
613
614
615
616

617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632



633







634





















































635
636
637
638
639
640
641
642







-
+















-
-
-
+
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+







				 * NULL. */
    Tcl_Obj *argsObj,		/* The formal argument list for the method,
				 * which _must not_ be NULL. */
    Tcl_Obj *bodyObj,		/* The body of the method, which _must not_ be
				 * NULL. */
    const Tcl_MethodType *typePtr,
				/* The type of the method to create. */
    void *clientData,	/* The per-method type-specific data. */
    void *clientData,		/* The per-method type-specific data. */
    Proc **procPtrPtr)		/* A pointer to the variable in which to write
				 * the procedure record reference. Presumably
				 * inside the structure indicated by the
				 * pointer in clientData. */
{
    Interp *iPtr = (Interp *) interp;
    Proc *procPtr;

    if (TclCreateProc(interp, NULL, TclGetString(nameObj), argsObj, bodyObj,
	    procPtrPtr) != TCL_OK) {
	return NULL;
    }
    procPtr = *procPtrPtr;
    procPtr->cmdPtr = NULL;

    if (iPtr->cmdFramePtr) {
	CmdFrame context = *iPtr->cmdFramePtr;

    InitCmdFrame(iPtr, procPtr);
	if (context.type == TCL_LOCATION_BC) {
	    /*
	     * Retrieve source information from the bytecode, if possible. If
	     * the information is retrieved successfully, context.type will be
	     * TCL_LOCATION_SOURCE and the reference held by
	     * context.data.eval.path will be counted.
	     */

	    TclGetSrcInfoForPc(&context);
	} else if (context.type == TCL_LOCATION_SOURCE) {
	    /*
	     * The copy into 'context' up above has created another reference
	     * to 'context.data.eval.path'; account for it.
	     */

	    Tcl_IncrRefCount(context.data.eval.path);
	}

	if (context.type == TCL_LOCATION_SOURCE) {
	    /*
	     * We can account for source location within a proc only if the
	     * proc body was not created by substitution.
	     * (FIXME: check that this is sane and correct!)
	     */

	    if (context.line
		    && (context.nline >= 4) && (context.line[3] >= 0)) {
		int isNew;
		CmdFrame *cfPtr = (CmdFrame *)Tcl_Alloc(sizeof(CmdFrame));
		Tcl_HashEntry *hPtr;

		cfPtr->level = -1;
		cfPtr->type = context.type;
		cfPtr->line = (int *)Tcl_Alloc(sizeof(int));
		cfPtr->line[0] = context.line[3];
		cfPtr->nline = 1;
		cfPtr->framePtr = NULL;
		cfPtr->nextPtr = NULL;

		cfPtr->data.eval.path = context.data.eval.path;
		Tcl_IncrRefCount(cfPtr->data.eval.path);

		cfPtr->cmd = NULL;
		cfPtr->len = 0;

		hPtr = Tcl_CreateHashEntry(iPtr->linePBodyPtr,
			(char *) procPtr, &isNew);
		Tcl_SetHashValue(hPtr, cfPtr);
	    }

	    /*
	     * 'context' is going out of scope; account for the reference that
	     * it's holding to the path name.
	     */

	    Tcl_DecrRefCount(context.data.eval.path);
	    context.data.eval.path = NULL;
	}
    }

    return Tcl_NewInstanceMethod(interp, (Tcl_Object) oPtr, nameObj, flags,
    return TclNewInstanceMethod(interp, (Tcl_Object) oPtr, nameObj, flags,
	    typePtr, clientData);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOMakeProcMethod --
559
560
561
562
563
564
565
566

567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584

585
586
587
588
589
590
591
592
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645

646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661

662
663
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
662
663
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
707
708

709
710
711
712
713
714
715
716
717
718
719


720
721

722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760

761
762
763
764
765
766
767
768







-
+















-
-
-
+
-
-
-
-
-
-
-

-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-














-
+





-
+










-
-
+
+
-



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+







				 * _must not_ be NULL. */
    Tcl_Obj *argsObj,		/* The formal argument list for the method,
				 * which _must not_ be NULL. */
    Tcl_Obj *bodyObj,		/* The body of the method, which _must not_ be
				 * NULL. */
    const Tcl_MethodType *typePtr,
				/* The type of the method to create. */
    void *clientData,	/* The per-method type-specific data. */
    void *clientData,		/* The per-method type-specific data. */
    Proc **procPtrPtr)		/* A pointer to the variable in which to write
				 * the procedure record reference. Presumably
				 * inside the structure indicated by the
				 * pointer in clientData. */
{
    Interp *iPtr = (Interp *) interp;
    Proc *procPtr;

    if (TclCreateProc(interp, NULL, namePtr, argsObj, bodyObj,
	    procPtrPtr) != TCL_OK) {
	return NULL;
    }
    procPtr = *procPtrPtr;
    procPtr->cmdPtr = NULL;

    if (iPtr->cmdFramePtr) {
	CmdFrame context = *iPtr->cmdFramePtr;

    InitCmdFrame(iPtr, procPtr);
	if (context.type == TCL_LOCATION_BC) {
	    /*
	     * Retrieve source information from the bytecode, if possible. If
	     * the information is retrieved successfully, context.type will be
	     * TCL_LOCATION_SOURCE and the reference held by
	     * context.data.eval.path will be counted.
	     */

	    TclGetSrcInfoForPc(&context);
	} else if (context.type == TCL_LOCATION_SOURCE) {
	    /*
	     * The copy into 'context' up above has created another reference
	     * to 'context.data.eval.path'; account for it.
	     */

    return TclNewMethod(
	    Tcl_IncrRefCount(context.data.eval.path);
	}

	if (context.type == TCL_LOCATION_SOURCE) {
	    /*
	     * We can account for source location within a proc only if the
	     * proc body was not created by substitution.
	     * (FIXME: check that this is sane and correct!)
	     */

	    if (context.line
		    && (context.nline >= 4) && (context.line[3] >= 0)) {
		int isNew;
		CmdFrame *cfPtr = (CmdFrame *)Tcl_Alloc(sizeof(CmdFrame));
		Tcl_HashEntry *hPtr;

		cfPtr->level = -1;
		cfPtr->type = context.type;
		cfPtr->line = (int *)Tcl_Alloc(sizeof(int));
		cfPtr->line[0] = context.line[3];
		cfPtr->nline = 1;
		cfPtr->framePtr = NULL;
		cfPtr->nextPtr = NULL;

		cfPtr->data.eval.path = context.data.eval.path;
		Tcl_IncrRefCount(cfPtr->data.eval.path);

		cfPtr->cmd = NULL;
		cfPtr->len = 0;

		hPtr = Tcl_CreateHashEntry(iPtr->linePBodyPtr,
			(char *) procPtr, &isNew);
		Tcl_SetHashValue(hPtr, cfPtr);
	    }

	    /*
	     * 'context' is going out of scope; account for the reference that
	     * it's holding to the path name.
	     */

	    Tcl_DecrRefCount(context.data.eval.path);
	    context.data.eval.path = NULL;
	}
    }

    return Tcl_NewMethod(interp, (Tcl_Class) clsPtr, nameObj, flags, typePtr,
	    (Tcl_Class) clsPtr, nameObj, flags, typePtr, clientData);
	    clientData);
}

/*
 * ----------------------------------------------------------------------
 *
 * InvokeProcedureMethod, PushMethodCallFrame --
 *
 *	How to invoke a procedure-like method.
 *
 * ----------------------------------------------------------------------
 */

static int
InvokeProcedureMethod(
    void *clientData,	/* Pointer to some per-method context. */
    void *clientData,		/* Pointer to some per-method context. */
    Tcl_Interp *interp,
    Tcl_ObjectContext context,	/* The method calling context. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments as actually seen. */
{
    ProcedureMethod *pmPtr = (ProcedureMethod *)clientData;
    ProcedureMethod *pmPtr = (ProcedureMethod *) clientData;
    int result;
    PMFrameData *fdPtr;		/* Important data that has to have a lifetime
				 * matched by this function (or rather, by the
				 * call frame's lifetime). */

    /*
     * If the object namespace (or interpreter) were deleted, we just skip to
     * the next thing in the chain.
     */

    if (TclOOObjectDestroyed(((CallContext *)context)->oPtr) ||
	Tcl_InterpDeleted(interp)
    if (TclOOObjectDestroyed(((CallContext *) context)->oPtr)
	    || Tcl_InterpDeleted(interp)) {
    ) {
	return TclNRObjectContextInvokeNext(interp, context, objc, objv,
		Tcl_ObjectContextSkippedArgs(context));
    }

    /*
     * Finishes filling out the extra frame info so that [info frame] works if
     * that is not already set up.
     */

    if (pmPtr->efi.length == 0) {
	Tcl_Method method = Tcl_ObjectContextMethod(context);

	pmPtr->efi.length = 2;
	pmPtr->efi.fields[0].name = "method";
	pmPtr->efi.fields[0].proc = RenderMethodName;
	pmPtr->efi.fields[0].clientData = pmPtr;
	pmPtr->callSiteFlags = ((CallContext *)
		context)->callPtr->flags & (CONSTRUCTOR | DESTRUCTOR);
	pmPtr->interp = interp;
	pmPtr->method = method;
	if (pmPtr->gfivProc != NULL) {
	    pmPtr->efi.fields[1].name = "";
	    pmPtr->efi.fields[1].proc = pmPtr->gfivProc;
	    pmPtr->efi.fields[1].clientData = pmPtr;
	} else {
	    if (Tcl_MethodDeclarerObject(method) != NULL) {
		pmPtr->efi.fields[1].name = "object";
	    } else {
		pmPtr->efi.fields[1].name = "class";
	    }
	    pmPtr->efi.fields[1].proc = RenderDeclarerName;
	    pmPtr->efi.fields[1].clientData = pmPtr;
	}
    }

    /*
     * Allocate the special frame data.
     */

    fdPtr = (PMFrameData *)TclStackAlloc(interp, sizeof(PMFrameData));
    fdPtr = (PMFrameData *) TclStackAlloc(interp, sizeof(PMFrameData));

    /*
     * Create a call frame for this method.
     */

    result = PushMethodCallFrame(interp, (CallContext *) context, pmPtr,
	    objc, objv, fdPtr);
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
779
780
781
782
783
784
785







786
787
788
789
790
791
792







-
-
-
-
-
-
-








    if (pmPtr->preCallProc != NULL) {
	int isFinished;

	result = pmPtr->preCallProc(pmPtr->clientData, interp, context,
		(Tcl_CallFrame *) fdPtr->framePtr, &isFinished);
	if (isFinished || result != TCL_OK) {
	    /*
	     * Restore the old cmdPtr so that a subsequent use of [info frame]
	     * won't crash on us. [Bug 3001438]
	     */

	    pmPtr->procPtr->cmdPtr = fdPtr->oldCmdPtr;

	    Tcl_PopCallFrame(interp);
	    TclStackFree(interp, fdPtr->framePtr);
	    if (pmPtr->refCount-- <= 1) {
		DeleteProcedureMethodRecord(pmPtr);
	    }
	    TclStackFree(interp, fdPtr);
	    return result;
739
740
741
742
743
744
745
746
747
748



749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
804
805
806
807
808
809
810



811
812
813
814
815
816
817
818
819
820
821
822
823
824
825







826
827
828
829
830
831
832







-
-
-
+
+
+












-
-
-
-
-
-
-








static int
FinalizePMCall(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    ProcedureMethod *pmPtr = (ProcedureMethod *)data[0];
    Tcl_ObjectContext context = (Tcl_ObjectContext)data[1];
    PMFrameData *fdPtr = (PMFrameData *)data[2];
    ProcedureMethod *pmPtr = (ProcedureMethod *) data[0];
    Tcl_ObjectContext context = (Tcl_ObjectContext) data[1];
    PMFrameData *fdPtr = (PMFrameData *) data[2];

    /*
     * Give the post-call callback a chance to do some cleanup. Note that at
     * this point the call frame itself is invalid; it's already been popped.
     */

    if (pmPtr->postCallProc) {
	result = pmPtr->postCallProc(pmPtr->clientData, interp, context,
		Tcl_GetObjectNamespace(Tcl_ObjectContextObject(context)),
		result);
    }

    /*
     * Restore the old cmdPtr so that a subsequent use of [info frame] won't
     * crash on us. [Bug 3001438]
     */

    pmPtr->procPtr->cmdPtr = fdPtr->oldCmdPtr;

    /*
     * Scrap the special frame data now that we're done with it. Note that we
     * are inlining DeleteProcedureMethod() here; this location is highly
     * sensitive when it comes to performance!
     */

    if (pmPtr->refCount-- <= 1) {
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827

828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846

847
848

849
850
851
852
853
854
855
856
857
858
859
860
861

862

863
864
865
866
867


868
869

870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
845
846
847
848
849
850
851

852
853
854
855
856
857
858
859

860
861
862

863
864
865
866
867

868
869
870
871
872
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
898
899

900
901
902
903
904

905
906
907

908
909
910
911
912

913
914
915
916
917
918
919
920
921
922
923


























924









925
926
927
928
929
930
931







-








-



-





-












-
-
+










-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-






+
-
+




-
+
+

-
+




-
+










-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-







    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv,	/* Array of arguments. */
    PMFrameData *fdPtr)		/* Place to store information about the call
				 * frame. */
{
    Namespace *nsPtr = (Namespace *) contextPtr->oPtr->namespacePtr;
    int result;
    const char *namePtr;
    CallFrame **framePtrPtr = &fdPtr->framePtr;
    ByteCode *codePtr;

    /*
     * Compute basic information on the basis of the type of method it is.
     */

    if (contextPtr->callPtr->flags & CONSTRUCTOR) {
	namePtr = "<constructor>";
	fdPtr->nameObj = contextPtr->oPtr->fPtr->constructorName;
	fdPtr->errProc = ConstructorErrorHandler;
    } else if (contextPtr->callPtr->flags & DESTRUCTOR) {
	namePtr = "<destructor>";
	fdPtr->nameObj = contextPtr->oPtr->fPtr->destructorName;
	fdPtr->errProc = DestructorErrorHandler;
    } else {
	fdPtr->nameObj = Tcl_MethodName(
		Tcl_ObjectContextMethod((Tcl_ObjectContext) contextPtr));
	namePtr = TclGetString(fdPtr->nameObj);
	fdPtr->errProc = MethodErrorHandler;
    }
    if (pmPtr->errProc != NULL) {
	fdPtr->errProc = pmPtr->errProc;
    }

    /*
     * Magic to enable things like [incr Tcl], which wants methods to run in
     * their class's namespace.
     */

    if (pmPtr->flags & USE_DECLARER_NS) {
	Method *mPtr =
		contextPtr->callPtr->chain[contextPtr->index].mPtr;
	Method *mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr;

	if (mPtr->declaringClassPtr != NULL) {
	    nsPtr = (Namespace *)
		    mPtr->declaringClassPtr->thisPtr->namespacePtr;
	} else {
	    nsPtr = (Namespace *) mPtr->declaringObjectPtr->namespacePtr;
	}
    }

    /*
     * Save the old cmdPtr so that when this recursive call returns, we can
     * restore it. To do otherwise causes crashes in [info frame] after we
     * return from a recursive call. [Bug 3001438]
     */

    fdPtr->oldCmdPtr = pmPtr->procPtr->cmdPtr;

    /*
     * Compile the body. This operation may fail.
     * Compile the body.
     */

     *
    fdPtr->efi.length = 2;
    memset(&fdPtr->cmd, 0, sizeof(Command));
    fdPtr->cmd.nsPtr = nsPtr;
    fdPtr->cmd.clientData = &fdPtr->efi;
    pmPtr->procPtr->cmdPtr = &fdPtr->cmd;

    /*
     * [Bug 2037727] Always call TclProcCompileProc so that we check not only
     * that we have bytecode, but also that it remains valid. Note that we set
     * the namespace of the code here directly; this is a hack, but the
     * alternative is *so* slow...
     */

    pmPtr->procPtr->cmdPtr = &pmPtr->cmd;
    ByteCodeGetIntRep(pmPtr->procPtr->bodyPtr, &tclByteCodeType, codePtr);
    ByteCodeGetInternalRep(pmPtr->procPtr->bodyPtr, &tclByteCodeType, codePtr);
    if (codePtr) {
	codePtr->nsPtr = nsPtr;
    }
    result = TclProcCompileProc(interp, pmPtr->procPtr,
	    pmPtr->procPtr->bodyPtr, nsPtr, "body of method", namePtr);
	    pmPtr->procPtr->bodyPtr, nsPtr, "body of method",
	    TclGetString(fdPtr->nameObj));
    if (result != TCL_OK) {
	goto failureReturn;
	return result;
    }

    /*
     * Make the stack frame and fill it out with information about this call.
     * This operation may fail.
     * This operation doesn't ever actually fail.
     */

    (void) TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr,
	    (Tcl_Namespace *) nsPtr, FRAME_IS_PROC|FRAME_IS_METHOD);

    fdPtr->framePtr->clientData = contextPtr;
    fdPtr->framePtr->objc = objc;
    fdPtr->framePtr->objv = objv;
    fdPtr->framePtr->procPtr = pmPtr->procPtr;

    /*
     * Finish filling out the extra frame info so that [info frame] works.
     */

    fdPtr->efi.fields[0].name = "method";
    fdPtr->efi.fields[0].proc = NULL;
    fdPtr->efi.fields[0].clientData = fdPtr->nameObj;
    if (pmPtr->gfivProc != NULL) {
	fdPtr->efi.fields[1].name = "";
	fdPtr->efi.fields[1].proc = pmPtr->gfivProc;
	fdPtr->efi.fields[1].clientData = pmPtr;
    } else {
	Tcl_Method method =
		Tcl_ObjectContextMethod((Tcl_ObjectContext) contextPtr);

	if (Tcl_MethodDeclarerObject(method) != NULL) {
	    fdPtr->efi.fields[1].name = "object";
	} else {
	    fdPtr->efi.fields[1].name = "class";
	}
	fdPtr->efi.fields[1].proc = RenderDeclarerName;
	fdPtr->efi.fields[1].clientData = &fdPtr->pni;
	fdPtr->pni.interp = interp;
	fdPtr->pni.method = method;
    }

    return TCL_OK;

    /*
     * Restore the old cmdPtr so that a subsequent use of [info frame] won't
     * crash on us. [Bug 3001438]
     */

  failureReturn:
    pmPtr->procPtr->cmdPtr = fdPtr->oldCmdPtr;
    return result;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOSetupVariableResolver, etc. --
 *
948
949
950
951
952
953
954
955

956
957
958
959
960
961
962
952
953
954
955
956
957
958

959
960
961
962
963
964
965
966







-
+







}

static int
ProcedureMethodVarResolver(
    Tcl_Interp *interp,
    const char *varName,
    Tcl_Namespace *contextNs,
    TCL_UNUSED(int) /*flags*/,	/* Ignoring variable access flags (???) */
    TCL_UNUSED(int) /*flags*/,	// Ignoring variable access flags (???)
    Tcl_Var *varPtr)
{
    int result;
    Tcl_ResolvedVarInfo *rPtr = NULL;

    result = ProcedureMethodCompiledVarResolver(interp, varName,
	    strlen(varName), contextNs, &rPtr);
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
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
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

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







-
-
+
+











-
+
















-
+




-
+








-
+







-
+







-
+














-
+







    OOResVarInfo *infoPtr = (OOResVarInfo *) rPtr;
    Interp *iPtr = (Interp *) interp;
    CallFrame *framePtr = iPtr->varFramePtr;
    CallContext *contextPtr;
    Tcl_Obj *variableObj;
    PrivateVariableMapping *privateVar;
    Tcl_HashEntry *hPtr;
    int i, isNew, cacheIt;
    size_t varLen, len;
    int isNew, cacheIt;
    Tcl_Size i, varLen, len;
    const char *match, *varName;

    /*
     * Check that the variable is being requested in a context that is also a
     * method call; if not (i.e. we're evaluating in the object's namespace or
     * in a procedure of that namespace) then we do nothing.
     */

    if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
	return NULL;
    }
    contextPtr = (CallContext *)framePtr->clientData;
    contextPtr = (CallContext *) framePtr->clientData;

    /*
     * If we've done the work before (in a comparable context) then reuse that
     * rather than performing resolution ourselves.
     */

    if (infoPtr->cachedObjectVar) {
	return infoPtr->cachedObjectVar;
    }

    /*
     * Check if the variable is one we want to resolve at all (i.e. whether it
     * is in the list provided by the user). If not, we mustn't do anything
     * either.
     */

    varName = TclGetStringFromObj(infoPtr->variableObj, &varLen);
    varName = Tcl_GetStringFromObj(infoPtr->variableObj, &varLen);
    if (contextPtr->callPtr->chain[contextPtr->index]
	    .mPtr->declaringClassPtr != NULL) {
	FOREACH_STRUCT(privateVar, contextPtr->callPtr->chain[contextPtr->index]
		.mPtr->declaringClassPtr->privateVariables) {
	    match = TclGetStringFromObj(privateVar->variableObj, &len);
	    match = Tcl_GetStringFromObj(privateVar->variableObj, &len);
	    if ((len == varLen) && !memcmp(match, varName, len)) {
		variableObj = privateVar->fullNameObj;
		cacheIt = 0;
		goto gotMatch;
	    }
	}
	FOREACH(variableObj, contextPtr->callPtr->chain[contextPtr->index]
		.mPtr->declaringClassPtr->variables) {
	    match = TclGetStringFromObj(variableObj, &len);
	    match = Tcl_GetStringFromObj(variableObj, &len);
	    if ((len == varLen) && !memcmp(match, varName, len)) {
		cacheIt = 0;
		goto gotMatch;
	    }
	}
    } else {
	FOREACH_STRUCT(privateVar, contextPtr->oPtr->privateVariables) {
	    match = TclGetStringFromObj(privateVar->variableObj, &len);
	    match = Tcl_GetStringFromObj(privateVar->variableObj, &len);
	    if ((len == varLen) && !memcmp(match, varName, len)) {
		variableObj = privateVar->fullNameObj;
		cacheIt = 1;
		goto gotMatch;
	    }
	}
	FOREACH(variableObj, contextPtr->oPtr->variables) {
	    match = TclGetStringFromObj(variableObj, &len);
	    match = Tcl_GetStringFromObj(variableObj, &len);
	    if ((len == varLen) && !memcmp(match, varName, len)) {
		cacheIt = 1;
		goto gotMatch;
	    }
	}
    }
    return NULL;

    /*
     * It is a variable we want to resolve, so resolve it.
     */

  gotMatch:
    hPtr = Tcl_CreateHashEntry(TclVarTable(contextPtr->oPtr->namespacePtr),
	    (char *) variableObj, &isNew);
	    variableObj, &isNew);
    if (isNew) {
	TclSetVarNamespaceVar((Var *) TclVarHashGetValue(hPtr));
    }
    if (cacheIt) {
	infoPtr->cachedObjectVar = TclVarHashGetValue(hPtr);

	/*
1098
1099
1100
1101
1102
1103
1104
1105

1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123

1124
1125
1126
1127
1128
1129
1130
1131
1132


























1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151


1152
1153
1154

1155
1156

1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174

1175
1176
1177
1178
1179
1180
1181
1182
1183
1184

1185
1186
1187



1188
1189
1190

1191
































1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204

1205
1206
1207
1208


1209
1210
1211
1212
1213

1214
1215
1216

1217
1218


1219
1220
1221
1222

1223
1224
1225
1226
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
1102
1103
1104
1105
1106
1107
1108

1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126

1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179


1180
1181
1182
1183

1184
1185

1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203

1204
1205
1206
1207
1208
1209
1210
1211
1212
1213

1214
1215


1216
1217
1218
1219
1220

1221
1222
1223
1224
1225
1226
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







-
+

















-
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

















-
-
+
+


-
+

-
+

















-
+









-
+

-
-
+
+
+


-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












-
+


-
-
+
+
-



-
+


-
+

-
+
+



-
+












-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    Tcl_Free(infoPtr);
}

static int
ProcedureMethodCompiledVarResolver(
    TCL_UNUSED(Tcl_Interp *),
    const char *varName,
    int length,
    Tcl_Size length,
    TCL_UNUSED(Tcl_Namespace *),
    Tcl_ResolvedVarInfo **rPtrPtr)
{
    OOResVarInfo *infoPtr;
    Tcl_Obj *variableObj = Tcl_NewStringObj(varName, length);

    /*
     * Do not create resolvers for cases that contain namespace separators or
     * which look like array accesses. Both will lead us astray.
     */

    if (strstr(TclGetString(variableObj), "::") != NULL ||
	    Tcl_StringMatch(TclGetString(variableObj), "*(*)")) {
	Tcl_DecrRefCount(variableObj);
	return TCL_CONTINUE;
    }

    infoPtr = (OOResVarInfo *)Tcl_Alloc(sizeof(OOResVarInfo));
    infoPtr = (OOResVarInfo *) Tcl_Alloc(sizeof(OOResVarInfo));
    infoPtr->info.fetchProc = ProcedureMethodCompiledVarConnect;
    infoPtr->info.deleteProc = ProcedureMethodCompiledVarDelete;
    infoPtr->cachedObjectVar = NULL;
    infoPtr->variableObj = variableObj;
    Tcl_IncrRefCount(variableObj);
    *rPtrPtr = &infoPtr->info;
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * RenderMethodName --
 *
 *	Returns the name of the declared method. Used for producing information
 *	for [info frame].
 *
 * ----------------------------------------------------------------------
 */

static Tcl_Obj *
RenderMethodName(
    void *clientData)
{
    ProcedureMethod *pmPtr = (ProcedureMethod *) clientData;

    if (pmPtr->callSiteFlags & CONSTRUCTOR) {
	return TclOOGetFoundation(pmPtr->interp)->constructorName;
    } else if (pmPtr->callSiteFlags & DESTRUCTOR) {
	return TclOOGetFoundation(pmPtr->interp)->destructorName;
    } else {
	return Tcl_MethodName(pmPtr->method);
    }
}

/*
 * ----------------------------------------------------------------------
 *
 * RenderDeclarerName --
 *
 *	Returns the name of the entity (object or class) which declared a
 *	method. Used for producing information for [info frame] in such a way
 *	that the expensive part of this (generating the object or class name
 *	itself) isn't done until it is needed.
 *
 * ----------------------------------------------------------------------
 */

static Tcl_Obj *
RenderDeclarerName(
    void *clientData)
{
    struct PNI *pni = (struct PNI *)clientData;
    Tcl_Object object = Tcl_MethodDeclarerObject(pni->method);
    ProcedureMethod *pmPtr = (ProcedureMethod *) clientData;
    Tcl_Object object = Tcl_MethodDeclarerObject(pmPtr->method);

    if (object == NULL) {
	object = Tcl_GetClassAsObject(Tcl_MethodDeclarerClass(pni->method));
	object = Tcl_GetClassAsObject(Tcl_MethodDeclarerClass(pmPtr->method));
    }
    return TclOOObjectName(pni->interp, (Object *) object);
    return TclOOObjectName(pmPtr->interp, (Object *) object);
}

/*
 * ----------------------------------------------------------------------
 *
 * MethodErrorHandler, ConstructorErrorHandler, DestructorErrorHandler --
 *
 *	How to fill in the stack trace correctly upon error in various forms
 *	of procedure-like methods. LIMIT is how long the inserted strings in
 *	the error traces should get before being converted to have ellipses,
 *	and ELLIPSIFY is a macro to do the conversion (with the help of a
 *	%.*s%s format field). Note that ELLIPSIFY is only safe for use in
 *	suitable formatting contexts.
 *
 * ----------------------------------------------------------------------
 */

/* TODO: Check whether Tcl_AppendLimitedToObj() can work here. */
// TODO: Check whether Tcl_AppendLimitedToObj() can work here.

#define LIMIT 60
#define ELLIPSIFY(str,len) \
	((len) > LIMIT ? LIMIT : (int)(len)), (str), ((len) > LIMIT ? "..." : "")

static void
MethodErrorHandler(
    Tcl_Interp *interp,
    TCL_UNUSED(Tcl_Obj *) /*methodNameObj*/)
	/* We pull the method name out of context instead of from argument */
	// We pull the method name out of context instead of from argument
{
    size_t nameLen, objectNameLen;
    CallContext *contextPtr = (CallContext *)((Interp *) interp)->varFramePtr->clientData;
    Tcl_Size nameLen, objectNameLen;
    CallContext *contextPtr = (CallContext *)
	    ((Interp *) interp)->varFramePtr->clientData;
    Method *mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr;
    const char *objectName, *kindName, *methodName =
	    TclGetStringFromObj(mPtr->namePtr, &nameLen);
	    Tcl_GetStringFromObj(mPtr->namePtr, &nameLen);
    Object *declarerPtr;

    if (mPtr->declaringObjectPtr != NULL) {
	declarerPtr = mPtr->declaringObjectPtr;
	kindName = "object";
    } else {
	if (mPtr->declaringClassPtr == NULL) {
	    Tcl_Panic("method not declared in class or object");
	}
	declarerPtr = mPtr->declaringClassPtr->thisPtr;
	kindName = "class";
    }

    objectName = Tcl_GetStringFromObj(TclOOObjectName(interp, declarerPtr),
	    &objectNameLen);
    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
	    "\n    (%s \"%.*s%s\" method \"%.*s%s\" line %d)",
	    kindName, ELLIPSIFY(objectName, objectNameLen),
	    ELLIPSIFY(methodName, nameLen), Tcl_GetErrorLine(interp)));
}

static void
ConstructorErrorHandler(
    Tcl_Interp *interp,
    TCL_UNUSED(Tcl_Obj *) /*methodNameObj*/)
	// Ignore. We know it is the constructor.
{
    CallContext *contextPtr = (CallContext *)
	    ((Interp *) interp)->varFramePtr->clientData;
    Method *mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr;
    Object *declarerPtr;
    const char *objectName, *kindName;
    Tcl_Size objectNameLen;

    if (mPtr->declaringObjectPtr != NULL) {
	declarerPtr = mPtr->declaringObjectPtr;
	kindName = "object";
    } else {
	if (mPtr->declaringClassPtr == NULL) {
	    Tcl_Panic("method not declared in class or object");
	}
	declarerPtr = mPtr->declaringClassPtr->thisPtr;
	kindName = "class";
    }

    objectName = TclGetStringFromObj(TclOOObjectName(interp, declarerPtr),
    objectName = Tcl_GetStringFromObj(TclOOObjectName(interp, declarerPtr),
	    &objectNameLen);
    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
	    "\n    (%s \"%.*s%s\" method \"%.*s%s\" line %d)",
	    kindName, ELLIPSIFY(objectName, objectNameLen),
	    "\n    (%s \"%.*s%s\" constructor line %d)", kindName,
	    ELLIPSIFY(objectName, objectNameLen), Tcl_GetErrorLine(interp)));
	    ELLIPSIFY(methodName, nameLen), Tcl_GetErrorLine(interp)));
}

static void
ConstructorErrorHandler(
DestructorErrorHandler(
    Tcl_Interp *interp,
    TCL_UNUSED(Tcl_Obj *) /*methodNameObj*/)
		/* Ignore. We know it is the constructor. */
	// Ignore. We know it is the destructor.
{
    CallContext *contextPtr = (CallContext *)((Interp *) interp)->varFramePtr->clientData;
    CallContext *contextPtr = (CallContext *)
	    ((Interp *) interp)->varFramePtr->clientData;
    Method *mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr;
    Object *declarerPtr;
    const char *objectName, *kindName;
    size_t objectNameLen;
    Tcl_Size objectNameLen;

    if (mPtr->declaringObjectPtr != NULL) {
	declarerPtr = mPtr->declaringObjectPtr;
	kindName = "object";
    } else {
	if (mPtr->declaringClassPtr == NULL) {
	    Tcl_Panic("method not declared in class or object");
	}
	declarerPtr = mPtr->declaringClassPtr->thisPtr;
	kindName = "class";
    }

    objectName = TclGetStringFromObj(TclOOObjectName(interp, declarerPtr),
    objectName = Tcl_GetStringFromObj(TclOOObjectName(interp, declarerPtr),
	    &objectNameLen);
    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
	    "\n    (%s \"%.*s%s\" constructor line %d)", kindName,
	    ELLIPSIFY(objectName, objectNameLen), Tcl_GetErrorLine(interp)));
}

static void
DestructorErrorHandler(
    Tcl_Interp *interp,
    TCL_UNUSED(Tcl_Obj *) /*methodNameObj*/)
		/* Ignore. We know it is the destructor. */
{
    CallContext *contextPtr = (CallContext *)((Interp *) interp)->varFramePtr->clientData;
    Method *mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr;
    Object *declarerPtr;
    const char *objectName, *kindName;
    size_t objectNameLen;

    if (mPtr->declaringObjectPtr != NULL) {
	declarerPtr = mPtr->declaringObjectPtr;
	kindName = "object";
    } else {
	if (mPtr->declaringClassPtr == NULL) {
	    Tcl_Panic("method not declared in class or object");
	}
	declarerPtr = mPtr->declaringClassPtr->thisPtr;
	kindName = "class";
    }

    objectName = TclGetStringFromObj(TclOOObjectName(interp, declarerPtr),
	    &objectNameLen);
    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
	    "\n    (%s \"%.*s%s\" destructor line %d)", kindName,
	    ELLIPSIFY(objectName, objectNameLen), Tcl_GetErrorLine(interp)));
}

/*
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
1354
1355
1356
1357
1358
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
1354
1355
1356
1357
1358
1359

1360
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
1387
1388
1389
1390
1391
1392
1393







-
+












-
+
















-
+














-
+






-
+


+
+







    Tcl_Free(pmPtr);
}

static void
DeleteProcedureMethod(
    void *clientData)
{
    ProcedureMethod *pmPtr = (ProcedureMethod *)clientData;
    ProcedureMethod *pmPtr = (ProcedureMethod *) clientData;

    if (pmPtr->refCount-- <= 1) {
	DeleteProcedureMethodRecord(pmPtr);
    }
}

static int
CloneProcedureMethod(
    Tcl_Interp *interp,
    void *clientData,
    void **newClientData)
{
    ProcedureMethod *pmPtr = (ProcedureMethod *)clientData;
    ProcedureMethod *pmPtr = (ProcedureMethod *) clientData;
    ProcedureMethod *pm2Ptr;
    Tcl_Obj *bodyObj, *argsObj;
    CompiledLocal *localPtr;

    /*
     * Copy the argument list.
     */

    TclNewObj(argsObj);
    for (localPtr=pmPtr->procPtr->firstLocalPtr; localPtr!=NULL;
	    localPtr=localPtr->nextPtr) {
	if (TclIsVarArgument(localPtr)) {
	    Tcl_Obj *argObj;

	    TclNewObj(argObj);
	    Tcl_ListObjAppendElement(NULL, argObj,
		    Tcl_NewStringObj(localPtr->name, -1));
		    Tcl_NewStringObj(localPtr->name, TCL_AUTO_LENGTH));
	    if (localPtr->defValuePtr != NULL) {
		Tcl_ListObjAppendElement(NULL, argObj, localPtr->defValuePtr);
	    }
	    Tcl_ListObjAppendElement(NULL, argsObj, argObj);
	}
    }

    /*
     * Must strip the internal representation in order to ensure that any
     * bound references to instance variables are removed. [Bug 3609693]
     */

    bodyObj = Tcl_DuplicateObj(pmPtr->procPtr->bodyPtr);
    TclGetString(bodyObj);
    Tcl_StoreIntRep(pmPtr->procPtr->bodyPtr, &tclByteCodeType, NULL);
    Tcl_StoreInternalRep(pmPtr->procPtr->bodyPtr, &tclByteCodeType, NULL);

    /*
     * Create the actual copy of the method record, manufacturing a new proc
     * record.
     */

    pm2Ptr = (ProcedureMethod *)Tcl_Alloc(sizeof(ProcedureMethod));
    pm2Ptr = (ProcedureMethod *) Tcl_Alloc(sizeof(ProcedureMethod));
    memcpy(pm2Ptr, pmPtr, sizeof(ProcedureMethod));
    pm2Ptr->refCount = 1;
    pm2Ptr->cmd.clientData = &pm2Ptr->efi;
    pm2Ptr->efi.length = 0;	/* Trigger a reinit of this. */
    Tcl_IncrRefCount(argsObj);
    Tcl_IncrRefCount(bodyObj);
    if (TclCreateProc(interp, NULL, "", argsObj, bodyObj,
	    &pm2Ptr->procPtr) != TCL_OK) {
	Tcl_DecrRefCount(argsObj);
	Tcl_DecrRefCount(bodyObj);
	Tcl_Free(pm2Ptr);
1383
1384
1385
1386
1387
1388
1389
1390

1391
1392
1393

1394
1395
1396
1397
1398
1399


1400
1401
1402
1403

1404
1405
1406

1407
1408
1409
1410
1411
1412
1413
1418
1419
1420
1421
1422
1423
1424

1425
1426
1427

1428
1429
1430
1431
1432


1433
1434
1435
1436
1437

1438
1439
1440

1441
1442
1443
1444
1445
1446
1447
1448







-
+


-
+




-
-
+
+



-
+


-
+







    Tcl_Interp *interp,		/* Interpreter for error reporting. */
    Object *oPtr,		/* The object to attach the method to. */
    int flags,			/* Whether the method is public or not. */
    Tcl_Obj *nameObj,		/* The name of the method. */
    Tcl_Obj *prefixObj)		/* List of arguments that form the command
				 * prefix to forward to. */
{
    int prefixLen;
    Tcl_Size prefixLen;
    ForwardMethod *fmPtr;

    if (Tcl_ListObjLength(interp, prefixObj, &prefixLen) != TCL_OK) {
    if (TclListObjLength(interp, prefixObj, &prefixLen) != TCL_OK) {
	return NULL;
    }
    if (prefixLen < 1) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"method forward prefix must be non-empty", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_FORWARD", NULL);
		"method forward prefix must be non-empty", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_FORWARD", (char *)NULL);
	return NULL;
    }

    fmPtr = (ForwardMethod *)Tcl_Alloc(sizeof(ForwardMethod));
    fmPtr = (ForwardMethod *) Tcl_Alloc(sizeof(ForwardMethod));
    fmPtr->prefixObj = prefixObj;
    Tcl_IncrRefCount(prefixObj);
    return (Method *) Tcl_NewInstanceMethod(interp, (Tcl_Object) oPtr,
    return (Method *) TclNewInstanceMethod(interp, (Tcl_Object) oPtr,
	    nameObj, flags, &fwdMethodType, fmPtr);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOONewForwardMethod --
1422
1423
1424
1425
1426
1427
1428
1429

1430
1431
1432

1433
1434
1435
1436
1437
1438


1439
1440
1441
1442

1443
1444
1445

1446
1447
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
1478
1479
1480

1481
1482
1483
1484
1485
1486
1487
1488
1489
1490


1491
1492
1493
1494
1495
1496
1497
1498
1499
1500

1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520

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


1534
1535
1536
1537
1538
1539
1540
1457
1458
1459
1460
1461
1462
1463

1464
1465
1466

1467
1468
1469
1470
1471


1472
1473
1474
1475
1476

1477
1478
1479

1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496

1497
1498
1499
1500
1501
1502
1503

1504
1505

1506
1507
1508
1509
1510
1511
1512
1513
1514
1515

1516
1517
1518
1519
1520
1521
1522
1523
1524


1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535

1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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







-
+


-
+




-
-
+
+



-
+


-
+
















-
+






-
+

-
+
+








-
+








-
-
+
+









-
+



















-
+











-
-
+
+







    Tcl_Interp *interp,		/* Interpreter for error reporting. */
    Class *clsPtr,		/* The class to attach the method to. */
    int flags,			/* Whether the method is public or not. */
    Tcl_Obj *nameObj,		/* The name of the method. */
    Tcl_Obj *prefixObj)		/* List of arguments that form the command
				 * prefix to forward to. */
{
    int prefixLen;
    Tcl_Size prefixLen;
    ForwardMethod *fmPtr;

    if (Tcl_ListObjLength(interp, prefixObj, &prefixLen) != TCL_OK) {
    if (TclListObjLength(interp, prefixObj, &prefixLen) != TCL_OK) {
	return NULL;
    }
    if (prefixLen < 1) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"method forward prefix must be non-empty", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_FORWARD", NULL);
		"method forward prefix must be non-empty", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_FORWARD", (char *)NULL);
	return NULL;
    }

    fmPtr = (ForwardMethod *)Tcl_Alloc(sizeof(ForwardMethod));
    fmPtr = (ForwardMethod *) Tcl_Alloc(sizeof(ForwardMethod));
    fmPtr->prefixObj = prefixObj;
    Tcl_IncrRefCount(prefixObj);
    return (Method *) Tcl_NewMethod(interp, (Tcl_Class) clsPtr, nameObj,
    return (Method *) TclNewMethod((Tcl_Class) clsPtr, nameObj,
	    flags, &fwdMethodType, fmPtr);
}

/*
 * ----------------------------------------------------------------------
 *
 * InvokeForwardMethod --
 *
 *	How to invoke a forwarded method. Works by doing some ensemble-like
 *	command rearranging and then invokes some other Tcl command.
 *
 * ----------------------------------------------------------------------
 */

static int
InvokeForwardMethod(
    void *clientData,	/* Pointer to some per-method context. */
    void *clientData,		/* Pointer to some per-method context. */
    Tcl_Interp *interp,
    Tcl_ObjectContext context,	/* The method calling context. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments as actually seen. */
{
    CallContext *contextPtr = (CallContext *) context;
    ForwardMethod *fmPtr = (ForwardMethod *)clientData;
    ForwardMethod *fmPtr = (ForwardMethod *) clientData;
    Tcl_Obj **argObjs, **prefixObjs;
    int numPrefixes, len, skip = contextPtr->skip;
    Tcl_Size numPrefixes, skip = contextPtr->skip;
    int len;

    /*
     * Build the real list of arguments to use. Note that we know that the
     * prefixObj field of the ForwardMethod structure holds a reference to a
     * non-empty list, so there's a whole class of failures ("not a list") we
     * can ignore here.
     */

    Tcl_ListObjGetElements(NULL, fmPtr->prefixObj, &numPrefixes, &prefixObjs);
    TclListObjGetElements(NULL, fmPtr->prefixObj, &numPrefixes, &prefixObjs);
    argObjs = InitEnsembleRewrite(interp, objc, objv, skip,
	    numPrefixes, prefixObjs, &len);
    Tcl_NRAddCallback(interp, FinalizeForwardCall, argObjs, NULL, NULL, NULL);
    /*
     * NOTE: The combination of direct set of iPtr->lookupNsPtr and the use
     * of the TCL_EVAL_NOERR flag results in an evaluation configuration
     * very much like TCL_EVAL_INVOKE.
     */
    ((Interp *)interp)->lookupNsPtr
	    = (Namespace *) contextPtr->oPtr->namespacePtr;
    ((Interp *) interp)->lookupNsPtr = (Namespace *)
	    contextPtr->oPtr->namespacePtr;
    return TclNREvalObjv(interp, len, argObjs, TCL_EVAL_NOERR, NULL);
}

static int
FinalizeForwardCall(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj **argObjs = (Tcl_Obj **)data[0];
    Tcl_Obj **argObjs = (Tcl_Obj **) data[0];

    TclStackFree(interp, argObjs);
    return result;
}

/*
 * ----------------------------------------------------------------------
 *
 * DeleteForwardMethod, CloneForwardMethod --
 *
 *	How to delete and clone forwarded methods.
 *
 * ----------------------------------------------------------------------
 */

static void
DeleteForwardMethod(
    void *clientData)
{
    ForwardMethod *fmPtr = (ForwardMethod *)clientData;
    ForwardMethod *fmPtr = (ForwardMethod *) clientData;

    Tcl_DecrRefCount(fmPtr->prefixObj);
    Tcl_Free(fmPtr);
}

static int
CloneForwardMethod(
    TCL_UNUSED(Tcl_Interp *),
    void *clientData,
    void **newClientData)
{
    ForwardMethod *fmPtr = (ForwardMethod *)clientData;
    ForwardMethod *fm2Ptr = (ForwardMethod *)Tcl_Alloc(sizeof(ForwardMethod));
    ForwardMethod *fmPtr = (ForwardMethod *) clientData;
    ForwardMethod *fm2Ptr = (ForwardMethod *) Tcl_Alloc(sizeof(ForwardMethod));

    fm2Ptr->prefixObj = fmPtr->prefixObj;
    Tcl_IncrRefCount(fm2Ptr->prefixObj);
    *newClientData = fm2Ptr;
    return TCL_OK;
}

1550
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
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







-
+











-
+












-
+







 */

Proc *
TclOOGetProcFromMethod(
    Method *mPtr)
{
    if (mPtr->typePtr == &procMethodType) {
	ProcedureMethod *pmPtr = (ProcedureMethod *)mPtr->clientData;
	ProcedureMethod *pmPtr = (ProcedureMethod *) mPtr->clientData;

	return pmPtr->procPtr;
    }
    return NULL;
}

Tcl_Obj *
TclOOGetMethodBody(
    Method *mPtr)
{
    if (mPtr->typePtr == &procMethodType) {
	ProcedureMethod *pmPtr = (ProcedureMethod *)mPtr->clientData;
	ProcedureMethod *pmPtr = (ProcedureMethod *) mPtr->clientData;

	(void) TclGetString(pmPtr->procPtr->bodyPtr);
	return pmPtr->procPtr->bodyPtr;
    }
    return NULL;
}

Tcl_Obj *
TclOOGetFwdFromMethod(
    Method *mPtr)
{
    if (mPtr->typePtr == &fwdMethodType) {
	ForwardMethod *fwPtr = (ForwardMethod *)mPtr->clientData;
	ForwardMethod *fwPtr = (ForwardMethod *) mPtr->clientData;

	return fwPtr->prefixObj;
    }
    return NULL;
}

/*
1616
1617
1618
1619
1620
1621
1622
1623
1624



1625
1626
1627
1628
1629
1630
1631
1652
1653
1654
1655
1656
1657
1658


1659
1660
1661
1662
1663
1664
1665
1666
1667
1668







-
-
+
+
+







    Tcl_Obj *const *objv,	/* The real arguments. */
    int toRewrite,		/* Number of real arguments to replace. */
    int rewriteLength,		/* Number of arguments to insert instead. */
    Tcl_Obj *const *rewriteObjs,/* Arguments to insert instead. */
    int *lengthPtr)		/* Where to write the resulting length of the
				 * array of rewritten arguments. */
{
    unsigned len = rewriteLength + objc - toRewrite;
    Tcl_Obj **argObjs = (Tcl_Obj **)TclStackAlloc(interp, sizeof(Tcl_Obj *) * len);
    size_t len = rewriteLength + objc - toRewrite;
    Tcl_Obj **argObjs = (Tcl_Obj **)
	    TclStackAlloc(interp, sizeof(Tcl_Obj *) * len);

    memcpy(argObjs, rewriteObjs, rewriteLength * sizeof(Tcl_Obj *));
    memcpy(argObjs + rewriteLength, objv + toRewrite,
	    sizeof(Tcl_Obj *) * (objc - toRewrite));

    /*
     * Now plumb this into the core ensemble rewrite logging system so that
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
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774

1775
1776
1777
1778
1779
1780
1781

1782
1783
1784
1785
1786
1787
1788
1789







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









+
+
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+






-
+








Tcl_Obj *
Tcl_MethodName(
    Tcl_Method method)
{
    return ((Method *) method)->namePtr;
}

int
TclMethodIsType(
    Tcl_Method method,
    const Tcl_MethodType *typePtr,
    void **clientDataPtr)
{
    Method *mPtr = (Method *) method;

    if (mPtr->typePtr == typePtr) {
	if (clientDataPtr != NULL) {
	    *clientDataPtr = mPtr->clientData;
	}
	return 1;
    }
    return 0;
}

int
Tcl_MethodIsType(
    Tcl_Method method,
    const Tcl_MethodType *typePtr,
    void **clientDataPtr)
{
    Method *mPtr = (Method *) method;

    if (typePtr->version > TCL_OO_METHOD_VERSION_1) {
	Tcl_Panic("%s: Wrong version in typePtr->version, should be %s",
		"Tcl_MethodIsType", "TCL_OO_METHOD_VERSION_1");
    }
    if (mPtr->typePtr == typePtr) {
	if (clientDataPtr != NULL) {
	    *clientDataPtr = mPtr->clientData;
	}
	return 1;
    }
    return 0;
}

int
Tcl_MethodIsType2(
    Tcl_Method method,
    const Tcl_MethodType2 *typePtr,
    void **clientDataPtr)
{
    Method *mPtr = (Method *) method;

    if (typePtr->version < TCL_OO_METHOD_VERSION_2) {
	Tcl_Panic("%s: Wrong version in typePtr->version, should be %s",
		"Tcl_MethodIsType2", "TCL_OO_METHOD_VERSION_2");
    }
    if (mPtr->typePtr == (const Tcl_MethodType *) typePtr) {
	if (clientDataPtr != NULL) {
	    *clientDataPtr = mPtr->clientData;
	}
	return 1;
    }
    return 0;
}

int
Tcl_MethodIsPublic(
    Tcl_Method method)
{
    return (((Method *)method)->flags & PUBLIC_METHOD) ? 1 : 0;
    return (((Method *) method)->flags & PUBLIC_METHOD) ? 1 : 0;
}

int
Tcl_MethodIsPrivate(
    Tcl_Method method)
{
    return (((Method *)method)->flags & TRUE_PRIVATE_METHOD) ? 1 : 0;
    return (((Method *) method)->flags & TRUE_PRIVATE_METHOD) ? 1 : 0;
}

/*
 * Extended method construction for itcl-ng.
 */

Tcl_Method

Added generic/tclOOProp.c.









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tclOOProp.c --
 *
 *	This file contains implementations of the configurable property
 *	mecnanisms.
 *
 * Copyright © 2023-2024 Donal K. Fellows
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclOOInt.h"

/* Short-term cache for GetPropertyName(). */
typedef struct GPNCache {
    Tcl_Obj *listPtr;		/* Holds references to names. */
    char *names[TCLFLEXARRAY];	/* NULL-terminated table of names. */
} GPNCache;

enum GPNFlags {
    GPN_WRITABLE = 1,		/* Are we looking for a writable property? */
    GPN_FALLING_BACK = 2	/* Are we doing a recursive call to determine
				 * if the property is of the other type? */
};

/*
 * Shared bits for [property] declarations.
 */
enum PropOpt {
    PROP_ALL, PROP_READABLE, PROP_WRITABLE
};
static const char *const propOptNames[] = {
    "-all", "-readable", "-writable",
    NULL
};

/*
 * Forward declarations.
 */

static int		Configurable_Getter(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		Configurable_Setter(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static void		DetailsDeleter(void *clientData);
static int		DetailsCloner(Tcl_Interp *, void *oldClientData,
			    void **newClientData);
static void		ImplementObjectProperty(Tcl_Object targetObject,
			    Tcl_Obj *propNamePtr, int installGetter,
			    int installSetter);
static void		ImplementClassProperty(Tcl_Class targetObject,
			    Tcl_Obj *propNamePtr, int installGetter,
			    int installSetter);

/*
 * Method descriptors
 */

static const Tcl_MethodType GetterType = {
    TCL_OO_METHOD_VERSION_1,
    "PropertyGetter",
    Configurable_Getter,
    DetailsDeleter,
    DetailsCloner
};

static const Tcl_MethodType SetterType = {
    TCL_OO_METHOD_VERSION_1,
    "PropertySetter",
    Configurable_Setter,
    DetailsDeleter,
    DetailsCloner
};

/*
 * ----------------------------------------------------------------------
 *
 * TclOO_Configurable_Configure --
 *
 *	Implementation of the oo::configurable->configure method.
 *
 * ----------------------------------------------------------------------
 */

/*
 * Ugly thunks to read and write a property by calling the right method in
 * the right way. Note that we MUST be correct in holding references to Tcl_Obj
 * values, as this is potentially a call into user code.
 */
static inline int
ReadProperty(
    Tcl_Interp *interp,
    Object *oPtr,
    const char *propName)
{
    Tcl_Obj *args[] = {
	oPtr->fPtr->myName,
	Tcl_ObjPrintf("<ReadProp%s>", propName)
    };
    int code;

    Tcl_IncrRefCount(args[0]);
    Tcl_IncrRefCount(args[1]);
    code = TclOOPrivateObjectCmd(oPtr, interp, 2, args);
    Tcl_DecrRefCount(args[0]);
    Tcl_DecrRefCount(args[1]);
    switch (code) {
    case TCL_BREAK:
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"property getter for %s did a break", propName));
	return TCL_ERROR;
    case TCL_CONTINUE:
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"property getter for %s did a continue", propName));
	return TCL_ERROR;
    default:
	return code;
    }
}

static inline int
WriteProperty(
    Tcl_Interp *interp,
    Object *oPtr,
    const char *propName,
    Tcl_Obj *valueObj)
{
    Tcl_Obj *args[] = {
	oPtr->fPtr->myName,
	Tcl_ObjPrintf("<WriteProp%s>", propName),
	valueObj
    };
    int code;

    Tcl_IncrRefCount(args[0]);
    Tcl_IncrRefCount(args[1]);
    Tcl_IncrRefCount(args[2]);
    code = TclOOPrivateObjectCmd(oPtr, interp, 3, args);
    Tcl_DecrRefCount(args[0]);
    Tcl_DecrRefCount(args[1]);
    Tcl_DecrRefCount(args[2]);
    switch (code) {
    case TCL_BREAK:
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"property setter for %s did a break", propName));
	return TCL_ERROR;
    case TCL_CONTINUE:
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"property setter for %s did a continue", propName));
	return TCL_ERROR;
    default:
	return code;
    }
}

/* Look up a property full name. */
static Tcl_Obj *
GetPropertyName(
    Tcl_Interp *interp,		/* Context and error reporting. */
    Object *oPtr,		/* Object to get property name from. */
    int flags,			/* Are we looking for a writable property?
				 * Can we do a fallback message?
				 * See GPNFlags for possible values */
    Tcl_Obj *namePtr,		/* The name supplied by the user. */
    GPNCache **cachePtr)	/* Where to cache the table, if the caller
				 * wants that. The contents are to be freed
				 * with Tcl_Free if the cache is used. */
{
    Tcl_Size objc, index, i;
    Tcl_Obj *listPtr = TclOOGetAllObjectProperties(
	    oPtr, flags & GPN_WRITABLE);
    Tcl_Obj **objv;
    GPNCache *tablePtr;

    (void) Tcl_ListObjGetElements(NULL, listPtr, &objc, &objv);
    if (cachePtr && *cachePtr) {
	tablePtr = *cachePtr;
    } else {
	tablePtr = (GPNCache *) TclStackAlloc(interp,
		offsetof(GPNCache, names) + sizeof(char *) * (objc + 1));

	for (i = 0; i < objc; i++) {
	    tablePtr->names[i] = TclGetString(objv[i]);
	}
	tablePtr->names[objc] = NULL;
	if (cachePtr) {
	    /*
	     * Have a cache, but nothing in it so far.
	     *
	     * We cache the list here so it doesn't vanish from under our
	     * feet if a property implementation does something crazy like
	     * changing the set of properties. The type of copy this does
	     * means that the copy holds the references to the names in the
	     * table.
	     */
	    tablePtr->listPtr = TclListObjCopy(NULL, listPtr);
	    Tcl_IncrRefCount(tablePtr->listPtr);
	    *cachePtr = tablePtr;
	} else {
	    tablePtr->listPtr = NULL;
	}
    }
    int result = Tcl_GetIndexFromObjStruct(interp, namePtr, tablePtr->names,
	    sizeof(char *), "property", TCL_INDEX_TEMP_TABLE, &index);
    if (result == TCL_ERROR && !(flags & GPN_FALLING_BACK)) {
	/*
	 * If property can be accessed the other way, use a special message.
	 * We use a recursive call to look this up.
	 */

	Tcl_InterpState foo = Tcl_SaveInterpState(interp, result);
	Tcl_Obj *otherName = GetPropertyName(interp, oPtr,
		flags ^ (GPN_WRITABLE | GPN_FALLING_BACK), namePtr, NULL);
	result = Tcl_RestoreInterpState(interp, foo);
	if (otherName != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "property \"%s\" is %s only",
		    TclGetString(otherName),
		    (flags & GPN_WRITABLE) ? "read" : "write"));
	}
    }
    if (!cachePtr) {
	TclStackFree(interp, tablePtr);
    }
    if (result != TCL_OK) {
	return NULL;
    }
    return objv[index];
}

/* Release the cache made by GetPropertyName(). */
static inline void
ReleasePropertyNameCache(
    Tcl_Interp *interp,
    GPNCache **cachePtr)
{
    if (*cachePtr) {
	GPNCache *tablePtr = *cachePtr;
	if (tablePtr->listPtr) {
	    Tcl_DecrRefCount(tablePtr->listPtr);
	}
	TclStackFree(interp, tablePtr);
	*cachePtr = NULL;
    }
}

int
TclOO_Configurable_Configure(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Interpreter used for the result, error
				 * reporting, etc. */
    Tcl_ObjectContext context,	/* The object/call context. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* The actual arguments. */
{
    Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
    Tcl_Size skip = Tcl_ObjectContextSkippedArgs(context);
    Tcl_Obj *namePtr;
    Tcl_Size i, namec;
    int code = TCL_OK;

    objc -= skip;
    if ((objc & 1) && (objc != 1)) {
	/*
	 * Bad (odd > 1) number of arguments.
	 */

	Tcl_WrongNumArgs(interp, skip, objv, "?-option value ...?");
	return TCL_ERROR;
    }

    objv += skip;
    if (objc == 0) {
	/*
	 * Read all properties.
	 */

	Tcl_Obj *listPtr = TclOOGetAllObjectProperties(oPtr, 0);
	Tcl_Obj *resultPtr = Tcl_NewObj(), **namev;

	Tcl_IncrRefCount(listPtr);
	ListObjGetElements(listPtr, namec, namev);

	for (i = 0; i < namec; ) {
	    code = ReadProperty(interp, oPtr, TclGetString(namev[i]));
	    if (code != TCL_OK) {
		Tcl_DecrRefCount(resultPtr);
		break;
	    }
	    Tcl_DictObjPut(NULL, resultPtr, namev[i],
		    Tcl_GetObjResult(interp));
	    if (++i >= namec) {
		Tcl_SetObjResult(interp, resultPtr);
		break;
	    }
	    Tcl_SetObjResult(interp, Tcl_NewObj());
	}
	Tcl_DecrRefCount(listPtr);
	return code;
    } else if (objc == 1) {
	/*
	 * Read a single named property.
	 */

	namePtr = GetPropertyName(interp, oPtr, 0, objv[0], NULL);
	if (namePtr == NULL) {
	    return TCL_ERROR;
	}
	return ReadProperty(interp, oPtr, TclGetString(namePtr));
    } else if (objc == 2) {
	/*
	 * Special case for writing to one property. Saves fiddling with the
	 * cache in this common case.
	 */

	namePtr = GetPropertyName(interp, oPtr, GPN_WRITABLE, objv[0], NULL);
	if (namePtr == NULL) {
	    return TCL_ERROR;
	}
	code = WriteProperty(interp, oPtr, TclGetString(namePtr), objv[1]);
	if (code == TCL_OK) {
	    Tcl_ResetResult(interp);
	}
	return code;
    } else {
	/*
	 * Write properties. Slightly tricky because we want to cache the
	 * table of property names.
	 */
	GPNCache *cache = NULL;

	code = TCL_OK;
	for (i = 0; i < objc; i += 2) {
	    namePtr = GetPropertyName(interp, oPtr, GPN_WRITABLE, objv[i],
		    &cache);
	    if (namePtr == NULL) {
		code = TCL_ERROR;
		break;
	    }
	    code = WriteProperty(interp, oPtr, TclGetString(namePtr),
		    objv[i + 1]);
	    if (code != TCL_OK) {
		break;
	    }
	}
	if (code == TCL_OK) {
	    Tcl_ResetResult(interp);
	}
	ReleasePropertyNameCache(interp, &cache);
	return code;
    }
}

/*
 * ----------------------------------------------------------------------
 *
 * Configurable_Getter, Configurable_Setter --
 *
 *	Standard property implementation. The clientData is a simple Tcl_Obj*
 *	that contains the name of the property.
 *
 * ----------------------------------------------------------------------
 */

static int
Configurable_Getter(
    void *clientData,		/* Which property to read. Actually a Tcl_Obj*
				 * reference that is the name of the variable
				 * in the cpntext object. */
    Tcl_Interp *interp,		/* Interpreter used for the result, error
				 * reporting, etc. */
    Tcl_ObjectContext context,	/* The object/call context. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* The actual arguments. */
{
    Tcl_Obj *propNamePtr = (Tcl_Obj *) clientData;
    Tcl_Var varPtr, aryVar;
    Tcl_Obj *valuePtr;

    if ((int) Tcl_ObjectContextSkippedArgs(context) != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context),
		objv, NULL);
	return TCL_ERROR;
    }

    varPtr = TclOOLookupObjectVar(interp, Tcl_ObjectContextObject(context),
	    propNamePtr, &aryVar);
    if (varPtr == NULL) {
	return TCL_ERROR;
    }

    valuePtr = TclPtrGetVar(interp, varPtr, aryVar, propNamePtr, NULL,
	    TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG);
    if (valuePtr == NULL) {
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, valuePtr);
    return TCL_OK;
}

static int
Configurable_Setter(
    void *clientData,		/* Which property to write. Actually a Tcl_Obj*
				 * reference that is the name of the variable
				 * in the cpntext object. */
    Tcl_Interp *interp,		/* Interpreter used for the result, error
				 * reporting, etc. */
    Tcl_ObjectContext context,	/* The object/call context. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* The actual arguments. */
{
    Tcl_Obj *propNamePtr = (Tcl_Obj *) clientData;
    Tcl_Var varPtr, aryVar;

    if ((int) Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context),
		objv, "value");
	return TCL_ERROR;
    }

    varPtr = TclOOLookupObjectVar(interp, Tcl_ObjectContextObject(context),
	    propNamePtr, &aryVar);
    if (varPtr == NULL) {
	return TCL_ERROR;
    }

    if (TclPtrSetVar(interp, varPtr, aryVar, propNamePtr, NULL,
	    objv[objc - 1], TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG) == NULL) {
	return TCL_ERROR;
    }
    return TCL_OK;
}

// Simple support functions
static void
DetailsDeleter(
    void *clientData)
{
    // Just drop the reference count
    Tcl_Obj *propNamePtr = (Tcl_Obj *) clientData;
    Tcl_DecrRefCount(propNamePtr);
}

static int
DetailsCloner(
    TCL_UNUSED(Tcl_Interp *),
    void *oldClientData,
    void **newClientData)
{
    // Just add another reference to this name; easy!
    Tcl_Obj *propNamePtr = (Tcl_Obj *) oldClientData;
    Tcl_IncrRefCount(propNamePtr);
    *newClientData = propNamePtr;
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * ImplementObjectProperty, ImplementClassProperty --
 *
 *	Installs a basic property implementation for a property, either on
 *	an instance or on a class. It's up to the code that calls these
 *	to ensure that the property name is syntactically valid.
 *
 * ----------------------------------------------------------------------
 */

void
ImplementObjectProperty(
    Tcl_Object targetObject,	/* What to install into. */
    Tcl_Obj *propNamePtr,	/* Property name. */
    int installGetter,		/* Whether to install a standard getter. */
    int installSetter)		/* Whether to install a standard setter. */
{
    const char *propName = TclGetString(propNamePtr);

    while (propName[0] == '-') {
	propName++;
    }
    if (installGetter) {
	Tcl_Obj *methodName = Tcl_ObjPrintf("<ReadProp-%s>", propName);
	Tcl_IncrRefCount(propNamePtr); // Paired with DetailsDeleter
	TclNewInstanceMethod(
		NULL, targetObject, methodName, 0, &GetterType, propNamePtr);
	Tcl_BounceRefCount(methodName);
    }
    if (installSetter) {
	Tcl_Obj *methodName = Tcl_ObjPrintf("<WriteProp-%s>", propName);
	Tcl_IncrRefCount(propNamePtr); // Paired with DetailsDeleter
	TclNewInstanceMethod(
		NULL, targetObject, methodName, 0, &SetterType, propNamePtr);
	Tcl_BounceRefCount(methodName);
    }
}

void
ImplementClassProperty(
    Tcl_Class targetClass,	/* What to install into. */
    Tcl_Obj *propNamePtr,	/* Property name. */
    int installGetter,		/* Whether to install a standard getter. */
    int installSetter)		/* Whether to install a standard setter. */
{
    const char *propName = TclGetString(propNamePtr);

    while (propName[0] == '-') {
	propName++;
    }
    if (installGetter) {
	Tcl_Obj *methodName = Tcl_ObjPrintf("<ReadProp-%s>", propName);
	Tcl_IncrRefCount(propNamePtr); // Paired with DetailsDeleter
	TclNewMethod(targetClass, methodName, 0, &GetterType, propNamePtr);
	Tcl_BounceRefCount(methodName);
    }
    if (installSetter) {
	Tcl_Obj *methodName = Tcl_ObjPrintf("<WriteProp-%s>", propName);
	Tcl_IncrRefCount(propNamePtr); // Paired with DetailsDeleter
	TclNewMethod(targetClass, methodName, 0, &SetterType, propNamePtr);
	Tcl_BounceRefCount(methodName);
    }
}

/*
 * ----------------------------------------------------------------------
 *
 * FindClassProps --
 *
 *	Discover the properties known to a class and its superclasses.
 *	The property names become the keys in the accumulator hash table
 *	(which is used as a set).
 *
 * ----------------------------------------------------------------------
 */

static void
FindClassProps(
    Class *clsPtr,		/* The object to inspect. Must exist. */
    int writable,		/* Whether we're after the readable or writable
				 * property set. */
    Tcl_HashTable *accumulator)	/* Where to gather the names. */
{
    int i, dummy;
    Tcl_Obj *propName;
    Class *mixin, *sup;

  tailRecurse:
    if (writable) {
	FOREACH(propName, clsPtr->properties.writable) {
	    Tcl_CreateHashEntry(accumulator, (void *) propName, &dummy);
	}
    } else {
	FOREACH(propName, clsPtr->properties.readable) {
	    Tcl_CreateHashEntry(accumulator, (void *) propName, &dummy);
	}
    }
    if (clsPtr->thisPtr->flags & ROOT_OBJECT) {
	/*
	 * We do *not* traverse upwards from the root!
	 */
	return;
    }
    FOREACH(mixin, clsPtr->mixins) {
	FindClassProps(mixin, writable, accumulator);
    }
    if (clsPtr->superclasses.num == 1) {
	clsPtr = clsPtr->superclasses.list[0];
	goto tailRecurse;
    }
    FOREACH(sup, clsPtr->superclasses) {
	FindClassProps(sup, writable, accumulator);
    }
}

/*
 * ----------------------------------------------------------------------
 *
 * FindObjectProps --
 *
 *	Discover the properties known to an object and all its classes.
 *	The property names become the keys in the accumulator hash table
 *	(which is used as a set).
 *
 * ----------------------------------------------------------------------
 */

static void
FindObjectProps(
    Object *oPtr,		/* The object to inspect. Must exist. */
    int writable,		/* Whether we're after the readable or writable
				 * property set. */
    Tcl_HashTable *accumulator)	/* Where to gather the names. */
{
    int i, dummy;
    Tcl_Obj *propName;
    Class *mixin;

    if (writable) {
	FOREACH(propName, oPtr->properties.writable) {
	    Tcl_CreateHashEntry(accumulator, (void *) propName, &dummy);
	}
    } else {
	FOREACH(propName, oPtr->properties.readable) {
	    Tcl_CreateHashEntry(accumulator, (void *) propName, &dummy);
	}
    }
    FOREACH(mixin, oPtr->mixins) {
	FindClassProps(mixin, writable, accumulator);
    }
    FindClassProps(oPtr->selfCls, writable, accumulator);
}

/*
 * ----------------------------------------------------------------------
 *
 * GetAllClassProperties --
 *
 *	Get the list of all properties known to a class, including to its
 *	superclasses. Manages a cache so this operation is usually cheap.
 *	The order of properties in the resulting list is undefined.
 *
 * ----------------------------------------------------------------------
 */

static Tcl_Obj *
GetAllClassProperties(
    Class *clsPtr,		/* The class to inspect. Must exist. */
    int writable,		/* Whether to get writable properties. If
				 * false, readable properties will be returned
				 * instead. */
    int *allocated)		/* Address of variable to set to true if a
				 * Tcl_Obj was allocated and may be safely
				 * modified by the caller. */
{
    Tcl_HashTable hashTable;
    FOREACH_HASH_DECLS;
    Tcl_Obj *propName, *result;

    /*
     * Look in the cache.
     */

    if (clsPtr->properties.epoch == clsPtr->thisPtr->fPtr->epoch) {
	if (writable) {
	    if (clsPtr->properties.allWritableCache) {
		*allocated = 0;
		return clsPtr->properties.allWritableCache;
	    }
	} else {
	    if (clsPtr->properties.allReadableCache) {
		*allocated = 0;
		return clsPtr->properties.allReadableCache;
	    }
	}
    }

    /*
     * Gather the information. Unsorted! (Caller will sort.)
     */

    *allocated = 1;
    Tcl_InitObjHashTable(&hashTable);
    FindClassProps(clsPtr, writable, &hashTable);
    TclNewObj(result);
    FOREACH_HASH_KEY(propName, &hashTable) {
	Tcl_ListObjAppendElement(NULL, result, propName);
    }
    Tcl_DeleteHashTable(&hashTable);

    /*
     * Cache the information. Also purges the cache.
     */

    if (clsPtr->properties.epoch != clsPtr->thisPtr->fPtr->epoch) {
	if (clsPtr->properties.allWritableCache) {
	    Tcl_DecrRefCount(clsPtr->properties.allWritableCache);
	    clsPtr->properties.allWritableCache = NULL;
	}
	if (clsPtr->properties.allReadableCache) {
	    Tcl_DecrRefCount(clsPtr->properties.allReadableCache);
	    clsPtr->properties.allReadableCache = NULL;
	}
    }
    clsPtr->properties.epoch = clsPtr->thisPtr->fPtr->epoch;
    if (writable) {
	clsPtr->properties.allWritableCache = result;
    } else {
	clsPtr->properties.allReadableCache = result;
    }
    Tcl_IncrRefCount(result);
    return result;
}

/*
 * ----------------------------------------------------------------------
 *
 * SortPropList --
 *	Sort a list of names of properties. Simple support function. Assumes
 *	that the list Tcl_Obj is unshared and doesn't have a string
 *	representation.
 *
 * ----------------------------------------------------------------------
 */

static int
PropNameCompare(
    const void *a,
    const void *b)
{
    Tcl_Obj *first = *(Tcl_Obj **) a;
    Tcl_Obj *second = *(Tcl_Obj **) b;

    return TclStringCmp(first, second, 0, 0, TCL_INDEX_NONE);
}

static inline void
SortPropList(
    Tcl_Obj *list)
{
    Tcl_Size ec;
    Tcl_Obj **ev;

    if (Tcl_IsShared(list)) {
	Tcl_Panic("shared property list cannot be sorted");
    }
    Tcl_ListObjGetElements(NULL, list, &ec, &ev);
    TclInvalidateStringRep(list);
    qsort(ev, ec, sizeof(Tcl_Obj *), PropNameCompare);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOGetAllObjectProperties --
 *
 *	Get the sorted list of all properties known to an object, including to
 *	its classes. Manages a cache so this operation is usually cheap.
 *
 * ----------------------------------------------------------------------
 */

Tcl_Obj *
TclOOGetAllObjectProperties(
    Object *oPtr,		/* The object to inspect. Must exist. */
    int writable)		/* Whether to get writable properties. If
				 * false, readable properties will be returned
				 * instead. */
{
    Tcl_HashTable hashTable;
    FOREACH_HASH_DECLS;
    Tcl_Obj *propName, *result;

    /*
     * Look in the cache.
     */

    if (oPtr->properties.epoch == oPtr->fPtr->epoch) {
	if (writable) {
	    if (oPtr->properties.allWritableCache) {
		return oPtr->properties.allWritableCache;
	    }
	} else {
	    if (oPtr->properties.allReadableCache) {
		return oPtr->properties.allReadableCache;
	    }
	}
    }

    /*
     * Gather the information. Unsorted! (Caller will sort.)
     */

    Tcl_InitObjHashTable(&hashTable);
    FindObjectProps(oPtr, writable, &hashTable);
    TclNewObj(result);
    FOREACH_HASH_KEY(propName, &hashTable) {
	Tcl_ListObjAppendElement(NULL, result, propName);
    }
    Tcl_DeleteHashTable(&hashTable);
    SortPropList(result);

    /*
     * Cache the information.
     */

    if (oPtr->properties.epoch != oPtr->fPtr->epoch) {
	if (oPtr->properties.allWritableCache) {
	    Tcl_DecrRefCount(oPtr->properties.allWritableCache);
	    oPtr->properties.allWritableCache = NULL;
	}
	if (oPtr->properties.allReadableCache) {
	    Tcl_DecrRefCount(oPtr->properties.allReadableCache);
	    oPtr->properties.allReadableCache = NULL;
	}
    }
    oPtr->properties.epoch = oPtr->fPtr->epoch;
    if (writable) {
	oPtr->properties.allWritableCache = result;
    } else {
	oPtr->properties.allReadableCache = result;
    }
    Tcl_IncrRefCount(result);
    return result;
}

/*
 * ----------------------------------------------------------------------
 *
 * SetPropertyList --
 *
 *	Helper for writing a property list (which is actually a set).
 *
 * ----------------------------------------------------------------------
 */
static inline void
SetPropertyList(
    PropertyList *propList,	/* The property list to write. Replaces the
				 * property list's contents. */
    Tcl_Size objc,		/* Number of property names. */
    Tcl_Obj *const objv[])	/* Property names. */
{
    Tcl_Size i, n;
    Tcl_Obj *propObj;
    int created;
    Tcl_HashTable uniqueTable;

    for (i=0 ; i<objc ; i++) {
	Tcl_IncrRefCount(objv[i]);
    }
    FOREACH(propObj, *propList) {
	Tcl_DecrRefCount(propObj);
    }
    if (i != objc) {
	if (objc == 0) {
	    Tcl_Free(propList->list);
	} else if (i) {
	    propList->list = (Tcl_Obj **)
		    Tcl_Realloc(propList->list, sizeof(Tcl_Obj *) * objc);
	} else {
	    propList->list = (Tcl_Obj **)
		    Tcl_Alloc(sizeof(Tcl_Obj *) * objc);
	}
    }
    propList->num = 0;
    if (objc > 0) {
	Tcl_InitObjHashTable(&uniqueTable);
	for (i=n=0 ; i<objc ; i++) {
	    Tcl_CreateHashEntry(&uniqueTable, objv[i], &created);
	    if (created) {
		propList->list[n++] = objv[i];
	    } else {
		Tcl_DecrRefCount(objv[i]);
	    }
	}
	propList->num = n;

	/*
	 * Shouldn't be necessary, but maintain num/list invariant.
	 */

	if (n != objc) {
	    propList->list = (Tcl_Obj **)
		    Tcl_Realloc(propList->list, sizeof(Tcl_Obj *) * n);
	}
	Tcl_DeleteHashTable(&uniqueTable);
    }
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOInstallReadableProperties --
 *
 *	Helper for writing the readable property list (which is actually a set)
 *	that includes flushing the name cache.
 *
 * ----------------------------------------------------------------------
 */
void
TclOOInstallReadableProperties(
    PropertyStorage *props,	/* Which property list to install into. */
    Tcl_Size objc,		/* Number of property names. */
    Tcl_Obj *const objv[])	/* Property names. */
{
    if (props->allReadableCache) {
	Tcl_DecrRefCount(props->allReadableCache);
	props->allReadableCache = NULL;
    }

    SetPropertyList(&props->readable, objc, objv);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOInstallWritableProperties --
 *
 *	Helper for writing the writable property list (which is actually a set)
 *	that includes flushing the name cache.
 *
 * ----------------------------------------------------------------------
 */
void
TclOOInstallWritableProperties(
    PropertyStorage *props,	/* Which property list to install into. */
    Tcl_Size objc,		/* Number of property names. */
    Tcl_Obj *const objv[])	/* Property names. */
{
    if (props->allWritableCache) {
	Tcl_DecrRefCount(props->allWritableCache);
	props->allWritableCache = NULL;
    }

    SetPropertyList(&props->writable, objc, objv);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOGetPropertyList --
 *
 *	Helper for reading a property list.
 *
 * ----------------------------------------------------------------------
 */
Tcl_Obj *
TclOOGetPropertyList(
    PropertyList *propList)	/* The property list to read. */
{
    Tcl_Obj *resultObj, *propNameObj;
    Tcl_Size i;

    TclNewObj(resultObj);
    FOREACH(propNameObj, *propList) {
	Tcl_ListObjAppendElement(NULL, resultObj, propNameObj);
    }
    return resultObj;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOInstallStdPropertyImpls --
 *
 *	Validates a (dashless) property name, and installs implementation
 *	methods if asked to do so (readable and writable flags).
 *
 * ----------------------------------------------------------------------
 */
int
TclOOInstallStdPropertyImpls(
    void *useInstance,
    Tcl_Interp *interp,
    Tcl_Obj *propName,
    int readable,
    int writable)
{
    const char *name, *reason;
    Tcl_Size len;
    char flag = TCL_DONT_QUOTE_HASH;

    /*
     * Validate the property name. Note that just calling TclScanElement() is
     * cheaper than actually formatting a list and comparing the string
     * version of that with the original, as TclScanElement() is one of the
     * core parts of doing that; this skips a whole load of irrelevant memory
     * allocations!
     */

    name = Tcl_GetStringFromObj(propName, &len);
    if (Tcl_StringMatch(name, "-*")) {
	reason = "must not begin with -";
	goto badProp;
    }
    if (TclScanElement(name, len, &flag) != len) {
	reason = "must be a simple word";
	goto badProp;
    }
    if (Tcl_StringMatch(name, "*::*")) {
	reason = "must not contain namespace separators";
	goto badProp;
    }
    if (Tcl_StringMatch(name, "*[()]*")) {
	reason = "must not contain parentheses";
	goto badProp;
    }

    /*
     * Install the implementations... if asked to do so.
     */

    if (useInstance) {
	Tcl_Object object = TclOOGetDefineCmdContext(interp);
	if (!object) {
	    return TCL_ERROR;
	}
	ImplementObjectProperty(object, propName, readable, writable);
    } else {
	Tcl_Class cls = (Tcl_Class) TclOOGetClassDefineCmdContext(interp);
	if (!cls) {
	    return TCL_ERROR;
	}
	ImplementClassProperty(cls, propName, readable, writable);
    }
    return TCL_OK;

  badProp:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "bad property name \"%s\": %s", name, reason));
    Tcl_SetErrorCode(interp, "TCL", "OO", "PROPERTY_FORMAT", NULL);
    return TCL_ERROR;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOODefinePropertyCmd --
 *
 *	Implementation of the "property" definition for classes and instances
 *	governed by the [oo::configurable] metaclass.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefinePropertyCmd(
    void *useInstance,		/* NULL for class, non-NULL for object. */
    Tcl_Interp *interp,		/* For error reporting and lookup. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    int i;
    const char *const options[] = {
	"-get", "-kind", "-set", NULL
    };
    enum Options {
	OPT_GET, OPT_KIND, OPT_SET
    };
    const char *const kinds[] = {
	"readable", "readwrite", "writable", NULL
    };
    enum Kinds {
	KIND_RO, KIND_RW, KIND_WO
    };
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);

    if (oPtr == NULL) {
	return TCL_ERROR;
    }
    if (!useInstance && !oPtr->classPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	return TCL_ERROR;
    }

    for (i = 1; i < objc; i++) {
	Tcl_Obj *propObj = objv[i], *nextObj, *argObj, *hyphenated;
	Tcl_Obj *getterScript = NULL, *setterScript = NULL;

	/*
	 * Parse the extra options for the property.
	 */

	int kind = KIND_RW;
	while (i + 1 < objc) {
	    int option;

	    nextObj = objv[i + 1];
	    if (TclGetString(nextObj)[0] != '-') {
		break;
	    }
	    if (Tcl_GetIndexFromObj(interp, nextObj, options, "option", 0,
		    &option) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (i + 2 >= objc) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"missing %s to go with %s option",
			(option == OPT_KIND ? "kind value" : "body"),
			options[option]));
		Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL);
		return TCL_ERROR;
	    }
	    argObj = objv[i + 2];
	    i += 2;
	    switch (option) {
	    case OPT_GET:
		getterScript = argObj;
		break;
	    case OPT_SET:
		setterScript = argObj;
		break;
	    case OPT_KIND:
		if (Tcl_GetIndexFromObj(interp, argObj, kinds, "kind", 0,
			&kind) != TCL_OK) {
		    return TCL_ERROR;
		}
		break;
	    }
	}

	/*
	 * Install the property. Note that TclOOInstallStdPropertyImpls
	 * validates the property name as well.
	 */

	if (TclOOInstallStdPropertyImpls(useInstance, interp, propObj,
		kind != KIND_WO && getterScript == NULL,
		kind != KIND_RO && setterScript == NULL) != TCL_OK) {
	    return TCL_ERROR;
	}

	hyphenated = Tcl_ObjPrintf("-%s", TclGetString(propObj));
	if (useInstance) {
	    TclOORegisterInstanceProperty(oPtr, hyphenated,
		    kind != KIND_WO, kind != KIND_RO);
	} else {
	    TclOORegisterProperty(oPtr->classPtr, hyphenated,
		    kind != KIND_WO, kind != KIND_RO);
	}
	Tcl_BounceRefCount(hyphenated);

	/*
	 * Create property implementation methods by using the right
	 * back-end API, but only if the user has given us the bodies of the
	 * methods we'll make.
	 */

	if (getterScript != NULL) {
	    Tcl_Obj *getterName = Tcl_ObjPrintf("<ReadProp-%s>",
		    TclGetString(propObj));
	    Tcl_Obj *argsPtr = Tcl_NewObj();
	    Method *mPtr;

	    Tcl_IncrRefCount(getterScript);
	    if (useInstance) {
		mPtr = TclOONewProcInstanceMethod(interp, oPtr, 0,
			getterName, argsPtr, getterScript, NULL);
	    } else {
		mPtr = TclOONewProcMethod(interp, oPtr->classPtr, 0,
			getterName, argsPtr, getterScript, NULL);
	    }
	    Tcl_BounceRefCount(getterName);
	    Tcl_BounceRefCount(argsPtr);
	    Tcl_DecrRefCount(getterScript);
	    if (mPtr == NULL) {
		return TCL_ERROR;
	    }
	}
	if (setterScript != NULL) {
	    Tcl_Obj *setterName = Tcl_ObjPrintf("<WriteProp-%s>",
		    TclGetString(propObj));
	    Tcl_Obj *argsPtr;
	    Method *mPtr;

	    TclNewLiteralStringObj(argsPtr, "value");
	    Tcl_IncrRefCount(setterScript);
	    if (useInstance) {
		mPtr = TclOONewProcInstanceMethod(interp, oPtr, 0,
			setterName, argsPtr, setterScript, NULL);
	    } else {
		mPtr = TclOONewProcMethod(interp, oPtr->classPtr, 0,
			setterName, argsPtr, setterScript, NULL);
	    }
	    Tcl_BounceRefCount(setterName);
	    Tcl_BounceRefCount(argsPtr);
	    Tcl_DecrRefCount(setterScript);
	    if (mPtr == NULL) {
		return TCL_ERROR;
	    }
	}
    }
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOInfoClassPropCmd, TclOOInfoObjectPropCmd --
 *
 *	Implements [info class properties $clsName ?$option...?] and
 *	[info object properties $objName ?$option...?]
 *
 * ----------------------------------------------------------------------
 */

int
TclOOInfoClassPropCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Class *clsPtr;
    int i, idx, all = 0, writable = 0, allocated = 0;
    Tcl_Obj *result;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "className ?options...?");
	return TCL_ERROR;
    }
    clsPtr = TclOOGetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }
    for (i = 2; i < objc; i++) {
	if (Tcl_GetIndexFromObj(interp, objv[i], propOptNames, "option", 0,
		&idx) != TCL_OK) {
	    return TCL_ERROR;
	}
	switch (idx) {
	case PROP_ALL:
	    all = 1;
	    break;
	case PROP_READABLE:
	    writable = 0;
	    break;
	case PROP_WRITABLE:
	    writable = 1;
	    break;
	}
    }

    /*
     * Get the properties.
     */

    if (all) {
	result = GetAllClassProperties(clsPtr, writable, &allocated);
	if (allocated) {
	    SortPropList(result);
	}
    } else {
	if (writable) {
	    result = TclOOGetPropertyList(&clsPtr->properties.writable);
	} else {
	    result = TclOOGetPropertyList(&clsPtr->properties.readable);
	}
	SortPropList(result);
    }
    Tcl_SetObjResult(interp, result);
    return TCL_OK;
}

int
TclOOInfoObjectPropCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Object *oPtr;
    int i, idx, all = 0, writable = 0;
    Tcl_Obj *result;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "objName ?options...?");
	return TCL_ERROR;
    }
    oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]);
    if (oPtr == NULL) {
	return TCL_ERROR;
    }
    for (i = 2; i < objc; i++) {
	if (Tcl_GetIndexFromObj(interp, objv[i], propOptNames, "option", 0,
		&idx) != TCL_OK) {
	    return TCL_ERROR;
	}
	switch (idx) {
	case PROP_ALL:
	    all = 1;
	    break;
	case PROP_READABLE:
	    writable = 0;
	    break;
	case PROP_WRITABLE:
	    writable = 1;
	    break;
	}
    }

    /*
     * Get the properties.
     */

    if (all) {
	result = TclOOGetAllObjectProperties(oPtr, writable);
    } else {
	if (writable) {
	    result = TclOOGetPropertyList(&oPtr->properties.writable);
	} else {
	    result = TclOOGetPropertyList(&oPtr->properties.readable);
	}
	SortPropList(result);
    }
    Tcl_SetObjResult(interp, result);
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOReleasePropertyStorage --
 *
 *	Delete the memory associated with a class or object's properties.
 *
 * ----------------------------------------------------------------------
 */

static inline void
ReleasePropertyList(
    PropertyList *propList)
{
    Tcl_Obj *propertyObj;
    Tcl_Size i;

    FOREACH(propertyObj, *propList) {
	Tcl_DecrRefCount(propertyObj);
    }
    Tcl_Free(propList->list);
    propList->list = NULL;
    propList->num = 0;
}

void
TclOOReleasePropertyStorage(
    PropertyStorage *propsPtr)
{
    if (propsPtr->allReadableCache) {
	Tcl_DecrRefCount(propsPtr->allReadableCache);
    }
    if (propsPtr->allWritableCache) {
	Tcl_DecrRefCount(propsPtr->allWritableCache);
    }
    if (propsPtr->readable.num) {
	ReleasePropertyList(&propsPtr->readable);
    }
    if (propsPtr->writable.num) {
	ReleasePropertyList(&propsPtr->writable);
    }
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclOOScript.h.

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
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







-
+









-
+








#ifndef TCL_OO_SCRIPT_H
#define TCL_OO_SCRIPT_H

/*
 * The scripted part of the definitions of TclOO.
 *
 * Compiled from generic/tclOOScript.tcl by tools/makeHeader.tcl, which
 * Compiled from tools/tclOOScript.tcl by tools/makeHeader.tcl, which
 * 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\t::namespace path {}\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"
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74







-
+







"\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 {TCLOO CMDLINK FORMAT} \\\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"
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
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







-
+

-
+















-
+








-
+















-
-
+
+

-
-
+
+

-
+


-
+




-
+





+
+
+
+
+
+
+
+
+
+
+
-
-
+
+





-
+








-
+








-
-
+




-
+







"\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 -append $d\n"
"\t\t\tdefine $delegate ::oo::define::superclass -appendifnew $d\n"
"\t\t}\n"
"\t\tobjdefine $class ::oo::objdefine::mixin -append $delegate\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 {}} {body {}}} {\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 $body\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 {} {\n"
"\t\t\treturn -code error -errorcode {TCLOO ABSTRACT_SLOT} \"unimplemented\"\n"
"\t\tmethod Get -unexport {} {\n"
"\t\t\treturn -code error -errorcode {TCL OO ABSTRACT_SLOT} \"unimplemented\"\n"
"\t\t}\n"
"\t\tmethod Set list {\n"
"\t\t\treturn -code error -errorcode {TCLOO ABSTRACT_SLOT} \"unimplemented\"\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 list {\n"
"\t\tmethod Resolve -unexport list {\n"
"\t\t\treturn $list\n"
"\t\t}\n"
"\t\tmethod -set args {\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 args {\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 {} {tailcall my Set {}}\n"
"\t\tmethod -prepend args {\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 args {\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 {args} {\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\texport -set -append -clear -prepend -remove\n"
"\t\tunexport unknown destroy\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> {originObject} {\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"
"\t\t\t\t} else {\n"
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
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







-
+












-
+


-
-
+
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













"\t\t\t\t\tarray set vNew [array get vOrigin]\n"
"\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> {originObject} {\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 {TCLOO SINGLETON} \\\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> {originObject} {\n"
"\t\t\t\t\t\t::return -code error -errorcode {TCLOO SINGLETON} \\\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:
 */

Changes to generic/tclOOStubInit.c.

70
71
72
73
74
75
76





77
78
79
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84







+
+
+
+
+



    Tcl_ObjectContextInvokeNext, /* 23 */
    Tcl_ObjectGetMethodNameMapper, /* 24 */
    Tcl_ObjectSetMethodNameMapper, /* 25 */
    Tcl_ClassSetConstructor, /* 26 */
    Tcl_ClassSetDestructor, /* 27 */
    Tcl_GetObjectName, /* 28 */
    Tcl_MethodIsPrivate, /* 29 */
    Tcl_GetClassOfObject, /* 30 */
    Tcl_GetObjectClassName, /* 31 */
    Tcl_MethodIsType2, /* 32 */
    Tcl_NewInstanceMethod2, /* 33 */
    Tcl_NewMethod2, /* 34 */
};

/* !END!: Do not edit above this line. */

Changes to generic/tclOOStubLib.c.

31
32
33
34
35
36
37
38

39
40
41
42
43
44




45


46
47
48
49
50
51
52
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







-
+






+
+
+
+
-
+
+








MODULE_SCOPE const char *
TclOOInitializeStubs(
    Tcl_Interp *interp,
    const char *version)
{
    int exact = 0;
    const char *packageName = "TclOO";
    const char *packageName = "tcl::oo";
    const char *errMsg = NULL;
    TclOOStubs *stubsPtr = NULL;
    const char *actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp,
	    packageName, version, exact, &stubsPtr);

    if (actualVersion == NULL) {
	packageName = "TclOO";
	actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp,
		packageName, version, exact, &stubsPtr);
	if (actualVersion == NULL) {
	return NULL;
	    return NULL;
	}
    }
    if (stubsPtr == NULL) {
	errMsg = "missing stub table pointer";
    } else {
	tclOOStubsPtr = stubsPtr;
	if (stubsPtr->hooks) {
	    tclOOIntStubsPtr = stubsPtr->hooks->tclOOIntStubs;

Changes to generic/tclObj.c.

1
2
3
4
5
6
7
8
9
10
11





12
13
14
15
16
17
18
1
2
3
4
5
6





7
8
9
10
11
12
13
14
15
16
17
18






-
-
-
-
-
+
+
+
+
+







/*
 * tclObj.c --
 *
 *	This file contains Tcl object-related functions that are used by many
 *	Tcl commands.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1999 by Scriptics Corporation.
 * Copyright (c) 2001 by ActiveState Corporation.
 * Copyright (c) 2005 by Kevin B. Kenny.  All rights reserved.
 * Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1999 Scriptics Corporation.
 * Copyright © 2001 ActiveState Corporation.
 * Copyright © 2005 Kevin B. Kenny.  All rights reserved.
 * Copyright © 2007 Daniel A. Steffen <das@users.sourceforge.net>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclTomMath.h"
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
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







-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+


-
-
+
+





-
+













-
+






-
+







 *
 * Notice that different structures with the same name appear in other files.
 * The structure defined below is used in this file only.
 */

typedef struct {
    Tcl_HashTable *lineCLPtr;   /* This table remembers for each Tcl_Obj
                                 * generated by a call to the function
                                 * TclSubstTokens() from a literal text
                                 * where bs+nl sequences occured in it, if
                                 * any. I.e. this table keeps track of
                                 * invisible and stripped continuation lines.
                                 * Its keys are Tcl_Obj pointers, the values
                                 * are ContLineLoc pointers. See the file
                                 * tclCompile.h for the definition of this
                                 * structure, and for references to all
                                 * related places in the core. */
				 * generated by a call to the function
				 * TclSubstTokens() from a literal text
				 * where bs+nl sequences occurred in it, if
				 * any. I.e. this table keeps track of
				 * invisible and stripped continuation lines.
				 * Its keys are Tcl_Obj pointers, the values
				 * are ContLineLoc pointers. See the file
				 * tclCompile.h for the definition of this
				 * structure, and for references to all
				 * related places in the core. */
#if TCL_THREADS && defined(TCL_MEM_DEBUG)
    Tcl_HashTable *objThreadMap;/* Thread local table that is used to check
                                 * that a Tcl_Obj was not allocated by some
                                 * other thread. */
				 * that a Tcl_Obj was not allocated by some
				 * other thread. */
#endif /* TCL_MEM_DEBUG && TCL_THREADS */
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;

static void             TclThreadFinalizeContLines(ClientData clientData);
static void             TclThreadFinalizeContLines(void *clientData);
static ThreadSpecificData *TclGetContLineTable(void);

/*
 * Nested Tcl_Obj deletion management support
 *
 * All context references used in the object freeing code are pointers to this
 * structure; every thread will have its own structure instance. The purpose
 * of this structure is to allow deeply nested collections of Tcl_Objs to be
 * freed without taking a vast depth of C stack (which could cause all sorts
 * of breakage.)
 */

typedef struct PendingObjData {
    int deletionCount;		/* Count of the number of invokations of
    int deletionCount;		/* Count of the number of invocations of
				 * TclFreeObj() are on the stack (at least
				 * conceptually; many are actually expanded
				 * macros). */
    Tcl_Obj *deletionStack;	/* Stack of objects that have had TclFreeObj()
				 * invoked upon them but which can't be
				 * deleted yet because they are in a nested
				 * invokation of TclFreeObj(). By postponing
				 * invocation of TclFreeObj(). By postponing
				 * this way, we limit the maximum overall C
				 * stack depth when deleting a complex object.
				 * The down-side is that we alter the overall
				 * behaviour by altering the order in which
				 * objects are deleted, and we change the
				 * order in which the string rep and the
				 * internal rep of an object are deleted. Note
174
175
176
177
178
179
180
181

182
183
184
185
186
187
188


189
190
191
192
193
194
195
174
175
176
177
178
179
180

181
182
183
184
185
186


187
188
189
190
191
192
193
194
195







-
+





-
-
+
+








/*
 * Macros to pack/unpack a bignum's fields in a Tcl_Obj internal rep
 */

#define PACK_BIGNUM(bignum, objPtr) \
    if ((bignum).used > 0x7FFF) {                                   \
	mp_int *temp = (mp_int *)Tcl_Alloc(sizeof(mp_int));               \
	mp_int *temp = (mp_int *)Tcl_Alloc(sizeof(mp_int));             \
	*temp = bignum;                                                 \
	(objPtr)->internalRep.twoPtrValue.ptr1 = temp;                  \
	(objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(-1);           \
    } else if (((bignum).alloc <= 0x7FFF) || (mp_shrink(&(bignum))) == MP_OKAY) { \
	(objPtr)->internalRep.twoPtrValue.ptr1 = (bignum).dp;           \
	(objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR( ((bignum).sign << 30) \
		| ((bignum).alloc << 15) | ((bignum).used));            \
	(objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(((bignum).sign << 30) \
		| ((bignum).alloc << 15) | ((bignum).used));                \
    }

/*
 * Prototypes for functions defined later in this file:
 */

static int		ParseBoolean(Tcl_Obj *objPtr);
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
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







-
+




-
+
+

-
+




-
+
+






-
+
+






-
+
+








-
+







/*
 * The structures below defines the Tcl object types defined in this file by
 * means of functions that can be invoked by generic object code. See also
 * tclStringObj.c, tclListObj.c, tclByteCode.c for other type manager
 * implementations.
 */

const Tcl_ObjType tclBooleanType = {
const Tcl_ObjType tclBooleanType= {
    "boolean",			/* name */
    NULL,			/* freeIntRepProc */
    NULL,			/* dupIntRepProc */
    NULL,			/* updateStringProc */
    TclSetBooleanFromAny		/* setFromAnyProc */
    TclSetBooleanFromAny,	/* setFromAnyProc */
    TCL_OBJTYPE_V1(TclLengthOne)
};
const Tcl_ObjType tclDoubleType = {
const Tcl_ObjType tclDoubleType= {
    "double",			/* name */
    NULL,			/* freeIntRepProc */
    NULL,			/* dupIntRepProc */
    UpdateStringOfDouble,	/* updateStringProc */
    SetDoubleFromAny		/* setFromAnyProc */
    SetDoubleFromAny,		/* setFromAnyProc */
    TCL_OBJTYPE_V1(TclLengthOne)
};
const Tcl_ObjType tclIntType = {
    "int",			/* name */
    NULL,			/* freeIntRepProc */
    NULL,			/* dupIntRepProc */
    UpdateStringOfInt,		/* updateStringProc */
    SetIntFromAny		/* setFromAnyProc */
    SetIntFromAny,		/* setFromAnyProc */
    TCL_OBJTYPE_V1(TclLengthOne)
};
const Tcl_ObjType tclBignumType = {
    "bignum",			/* name */
    FreeBignum,			/* freeIntRepProc */
    DupBignum,			/* dupIntRepProc */
    UpdateStringOfBignum,	/* updateStringProc */
    NULL			/* setFromAnyProc */
    NULL,			/* setFromAnyProc */
    TCL_OBJTYPE_V1(TclLengthOne)
};

/*
 * The structure below defines the Tcl obj hash key type.
 */

const Tcl_HashKeyType tclObjHashKeyType = {
    TCL_HASH_KEY_TYPE_VERSION,	/* version */
    0,				/* flags */
    TCL_HASH_KEY_DIRECT_COMPARE,/* allows compare keys by pointers */
    TclHashObjKey,		/* hashKeyProc */
    TclCompareObjKeys,		/* compareKeysProc */
    AllocObjEntry,		/* allocEntryProc */
    TclFreeObjEntry		/* freeEntryProc */
};

/*
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
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







-
+
+




















-
+




-
+











+
+
+
+
+
+
+
+
+
+
+







 */

Tcl_ObjType tclCmdNameType = {
    "cmdName",			/* name */
    FreeCmdNameInternalRep,	/* freeIntRepProc */
    DupCmdNameInternalRep,	/* dupIntRepProc */
    NULL,			/* updateStringProc */
    SetCmdNameFromAny		/* setFromAnyProc */
    SetCmdNameFromAny,		/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

/*
 * Structure containing a cached pointer to a command that is the result of
 * resolving the command's name in some namespace. It is the internal
 * representation for a cmdName object. It contains the pointer along with
 * some information that is used to check the pointer's validity.
 */

typedef struct ResolvedCmdName {
    Command *cmdPtr;		/* A cached Command pointer. */
    Namespace *refNsPtr;	/* Points to the namespace containing the
				 * reference (not the namespace that contains
				 * the referenced command). NULL if the name
				 * is fully qualified.*/
    size_t refNsId;		/* refNsPtr's unique namespace id. Used to
				 * verify that refNsPtr is still valid (e.g.,
				 * it's possible that the cmd's containing
				 * namespace was deleted and a new one created
				 * at the same address). */
    size_t refNsCmdEpoch;	/* Value of the referencing namespace's
    Tcl_Size refNsCmdEpoch;	/* Value of the referencing namespace's
				 * cmdRefEpoch when the pointer was cached.
				 * Before using the cached pointer, we check
				 * if the namespace's epoch was incremented;
				 * if so, this cached pointer is invalid. */
    size_t cmdEpoch;		/* Value of the command's cmdEpoch when this
    Tcl_Size cmdEpoch;		/* Value of the command's cmdEpoch when this
				 * pointer was cached. Before using the cached
				 * pointer, we check if the cmd's epoch was
				 * incremented; if so, the cmd was renamed,
				 * deleted, hidden, or exposed, and so the
				 * pointer is invalid. */
    size_t refCount;		/* Reference count: 1 for each cmdName object
				 * that has a pointer to this ResolvedCmdName
				 * structure as its internal rep. This
				 * structure can be freed when refCount
				 * becomes zero. */
} ResolvedCmdName;

#ifdef TCL_MEM_DEBUG
/*
 * Filler matches the value used for filling freed memory in tclCkalloc.
 * On 32-bit systems, the ref counts do not cross 0x7fffffff. On 64-bit
 * implementations, ref counts will never reach this value (unless explicitly
 * incremented without actual references!)
 */
#define FREEDREFCOUNTFILLER \
    (Tcl_Size)(sizeof(objPtr->refCount) == 4 ? 0xe8e8e8e8 : 0xe8e8e8e8e8e8e8e8)
#endif

/*
 *-------------------------------------------------------------------------
 *
 * TclInitObjectSubsystem --
 *
 *	This function is invoked to perform once-only initialization of the
356
357
358
359
360
361
362
363
364
365
366
367
368






369
370
371

372
373
374
375
376
377
378
372
373
374
375
376
377
378






379
380
381
382
383
384

385

386
387
388
389
390
391
392
393







-
-
-
-
-
-
+
+
+
+
+
+
-

-
+







TclInitObjSubsystem(void)
{
    Tcl_MutexLock(&tableMutex);
    typeTableInitialized = 1;
    Tcl_InitHashTable(&typeTable, TCL_STRING_KEYS);
    Tcl_MutexUnlock(&tableMutex);

    Tcl_RegisterObjType(&tclByteArrayType);
    Tcl_RegisterObjType(&tclDoubleType);
    Tcl_RegisterObjType(&tclStringType);
    Tcl_RegisterObjType(&tclListType);
    Tcl_RegisterObjType(&tclDictType);
    Tcl_RegisterObjType(&tclByteCodeType);
    Tcl_RegisterObjType(&tclByteCodeType);
    Tcl_RegisterObjType(&tclCmdNameType);
    Tcl_RegisterObjType(&tclDictType);
    Tcl_RegisterObjType(&tclDoubleType);
    Tcl_RegisterObjType(&tclListType);
    Tcl_RegisterObjType(&tclProcBodyType);
    Tcl_RegisterObjType(&tclCmdNameType);
    Tcl_RegisterObjType(&tclRegexpType);
    Tcl_RegisterObjType(&tclProcBodyType);
    Tcl_RegisterObjType(&tclStringType);

#ifdef TCL_COMPILE_STATS
    Tcl_MutexLock(&tclObjMutex);
    tclObjsAlloced = 0;
    tclObjsFreed = 0;
    {
	int i;
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
558
559
560
561
562
563
564

565
566
567
568
569
570
571
537
538
539
540
541
542
543


544
545
546
547
548
549
550

551
552
553
554
555
556
557
558
559
560
561
562

563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578

579
580
581
582
583
584
585
586







-
-
+
+





-
+











-
+















-
+







 * TIP #280
 *----------------------------------------------------------------------
 */

ContLineLoc *
TclContinuationsEnter(
    Tcl_Obj *objPtr,
    int num,
    int *loc)
    Tcl_Size num,
    Tcl_Size *loc)
{
    int newEntry;
    ThreadSpecificData *tsdPtr = TclGetContLineTable();
    Tcl_HashEntry *hPtr =
	    Tcl_CreateHashEntry(tsdPtr->lineCLPtr, objPtr, &newEntry);
    ContLineLoc *clLocPtr = (ContLineLoc *)Tcl_Alloc(offsetof(ContLineLoc, loc) + (num + 1) *sizeof(int));
    ContLineLoc *clLocPtr = (ContLineLoc *)Tcl_Alloc(offsetof(ContLineLoc, loc) + (num + 1U) *sizeof(Tcl_Size));

    if (!newEntry) {
	/*
	 * We're entering ContLineLoc data for the same value more than one
	 * time. Taking care not to leak the old entry.
	 *
	 * This can happen when literals in a proc body are shared. See for
	 * example test info-30.19 where the action (code) for all branches of
	 * the switch command is identical, mapping them all to the same
	 * literal. An interesting result of this is that the number and
	 * locations (offset) of invisible continuation lines in the literal
	 * are the same for all occurences.
	 * are the same for all occurrences.
	 *
	 * Note that while reusing the existing entry is possible it requires
	 * the same actions as for a new entry because we have to copy the
	 * incoming num/loc data even so. Because we are called from
	 * TclContinuationsEnterDerived for this case, which modified the
	 * stored locations (Rebased to the proper relative offset). Just
	 * returning the stored entry would rebase them a second time, or
	 * more, hosing the data. It is easier to simply replace, as we are
	 * doing.
	 */

	Tcl_Free(Tcl_GetHashValue(hPtr));
    }

    clLocPtr->num = num;
    memcpy(&clLocPtr->loc, loc, num*sizeof(int));
    memcpy(&clLocPtr->loc, loc, num*sizeof(Tcl_Size));
    clLocPtr->loc[num] = CLL_END;       /* Sentinel */
    Tcl_SetHashValue(hPtr, clLocPtr);

    return clLocPtr;
}

/*
586
587
588
589
590
591
592
593
594


595
596
597
598



599
600
601
602
603
604
605
601
602
603
604
605
606
607


608
609
610



611
612
613
614
615
616
617
618
619
620







-
-
+
+

-
-
-
+
+
+







 * TIP #280
 *----------------------------------------------------------------------
 */

void
TclContinuationsEnterDerived(
    Tcl_Obj *objPtr,
    int start,
    int *clNext)
    Tcl_Size start,
    Tcl_Size *clNext)
{
    size_t length;
    int end, num;
    int *wordCLLast = clNext;
    Tcl_Size length;
    Tcl_Size end, num;
    Tcl_Size *wordCLLast = clNext;

    /*
     * We have to handle invisible continuations lines here as well, despite
     * the code we have in TclSubstTokens (TST) for that. Why ?  Nesting. If
     * our script is the sole argument to an 'eval' command, for example, the
     * scriptCLLocPtr we are using was generated by a previous call to TST,
     * and while the words we have here may contain continuation lines they
634
635
636
637
638
639
640
641

642
643
644
645
646
647
648
649
650
651
652
653
654
655

656
657
658
659
660
661
662
663







-
+








    /*
     * And generate the table from the slice, if it was not empty.
     */

    num = wordCLLast - clNext;
    if (num) {
	int i;
	Tcl_Size i;
	ContLineLoc *clLocPtr = TclContinuationsEnter(objPtr, num, clNext);

	/*
	 * Re-base the locations.
	 */

	for (i=0 ; i<num ; i++) {
684
685
686
687
688
689
690
691

692
693
694
695
696
697
698
699
700
701
702
703
704
705

706
707
708
709
710
711
712
713







-
+







void
TclContinuationsCopy(
    Tcl_Obj *objPtr,
    Tcl_Obj *originObjPtr)
{
    ThreadSpecificData *tsdPtr = TclGetContLineTable();
    Tcl_HashEntry *hPtr =
            Tcl_FindHashEntry(tsdPtr->lineCLPtr, originObjPtr);
	    Tcl_FindHashEntry(tsdPtr->lineCLPtr, originObjPtr);

    if (hPtr) {
	ContLineLoc *clLocPtr = (ContLineLoc *)Tcl_GetHashValue(hPtr);

	TclContinuationsEnter(objPtr, clLocPtr->num, clLocPtr->loc);
    }
}
718
719
720
721
722
723
724
725

726
727
728

729
730
731
732
733
734
735
733
734
735
736
737
738
739

740
741
742

743
744
745
746
747
748
749
750







-
+


-
+








ContLineLoc *
TclContinuationsGet(
    Tcl_Obj *objPtr)
{
    ThreadSpecificData *tsdPtr = TclGetContLineTable();
    Tcl_HashEntry *hPtr =
            Tcl_FindHashEntry(tsdPtr->lineCLPtr, objPtr);
	    Tcl_FindHashEntry(tsdPtr->lineCLPtr, objPtr);

    if (!hPtr) {
        return NULL;
	return NULL;
    }
    return (ContLineLoc *)Tcl_GetHashValue(hPtr);
}

/*
 *----------------------------------------------------------------------
 *
746
747
748
749
750
751
752
753

754
755
756
757
758
759
760
761
762
763
764
765
766
767

768
769
770
771
772
773
774
775







-
+







 *
 * TIP #280
 *----------------------------------------------------------------------
 */

static void
TclThreadFinalizeContLines(
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    /*
     * Release the hashtable tracking invisible continuation lines.
     */

    ThreadSpecificData *tsdPtr = TclGetContLineTable();
    Tcl_HashEntry *hPtr;
832
833
834
835
836
837
838
839

840
841
842
843
844
845
846
847
848
849
850
851
852
853

854
855
856
857
858
859
860
861







-
+







    Tcl_Interp *interp,		/* Interpreter used for error reporting. */
    Tcl_Obj *objPtr)		/* Points to the Tcl object onto which the
				 * name of each registered type is appended as
				 * a list element. */
{
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    int numElems;
    Tcl_Size numElems;

    /*
     * Get the test for a valid list out of the way first.
     */

    if (TclListObjLength(interp, objPtr, &numElems) != TCL_OK) {
	return TCL_ERROR;
930
931
932
933
934
935
936
937

938
939
940
941
942
943
944
945
946
947
948
949
950
951

952
953
954
955
956
957
958
959







-
+







     * representation.
     */

    if (typePtr->setFromAnyProc == NULL) {
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't convert value to type %s", typePtr->name));
	    Tcl_SetErrorCode(interp, "TCL", "API_ABUSE", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "API_ABUSE", (char *)NULL);
	}
	return TCL_ERROR;
    }

    return typePtr->setFromAnyProc(interp, objPtr);
}

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







-
+







    Tcl_HashEntry *hPtr;
    Tcl_HashTable *tablePtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    tablePtr = tsdPtr->objThreadMap;

    if (tablePtr != NULL) {
	fprintf(outFile, "total objects: %" TCL_Z_MODIFIER "u\n", tablePtr->numEntries);
	fprintf(outFile, "total objects: %" TCL_SIZE_MODIFIER "d\n", tablePtr->numEntries);
	for (hPtr = Tcl_FirstHashEntry(tablePtr, &hSearch); hPtr != NULL;
		hPtr = Tcl_NextHashEntry(&hSearch)) {
	    ObjData *objData = (ObjData *)Tcl_GetHashValue(hPtr);

	    if (objData != NULL) {
		fprintf(outFile,
			"key = 0x%p, objPtr = 0x%p, file = %s, line = %d\n",
1000
1001
1002
1003
1004
1005
1006
1007

1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021

1022
1023
1024
1025
1026
1027
1028
1029







-
+







/*
 *----------------------------------------------------------------------
 *
 * TclDbInitNewObj --
 *
 *	Called via the TclNewObj or TclDbNewObj macros when TCL_MEM_DEBUG is
 *	enabled. This function will initialize the members of a Tcl_Obj
 *	struct. Initilization would be done inline via the TclNewObj macro
 *	struct. Initialization would be done inline via the TclNewObj macro
 *	when compiling without TCL_MEM_DEBUG.
 *
 * Results:
 *	The Tcl_Obj struct members are initialized.
 *
 * Side effects:
 *	None.
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







-
+







    const char *file,	/* The name of the source file calling this
				 * function; used for debugging. */
    int line)		/* Line number in the source file; used for
				 * debugging. */
{
    objPtr->refCount = 0;
    objPtr->typePtr = NULL;
    TclInitStringRep(objPtr, NULL, 0);
    TclInitEmptyStringRep(objPtr);

#if TCL_THREADS
    /*
     * Add entry to a thread local map used to check if a Tcl_Obj was
     * allocated by the currently executing thread.
     */

1164
1165
1166
1167
1168
1169
1170


1171

1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187

1188
1189
1190
1191
1192
1193
1194
1195







+
+
-
+







#else /* if not TCL_MEM_DEBUG */

Tcl_Obj *
Tcl_DbNewObj(
    TCL_UNUSED(const char *) /*file*/,
    TCL_UNUSED(int) /*line*/)
{
    Tcl_Obj *objPtr;
    TclNewObj(objPtr);
    return Tcl_NewObj();
    return objPtr;
}
#endif /* TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------------
 *
 * TclAllocateFreeObjects --
1274
1275
1276
1277
1278
1279
1280
1281

1282
1283
1284
1285
1286
1287
1288
1291
1292
1293
1294
1295
1296
1297

1298
1299
1300
1301
1302
1303
1304
1305







-
+







	Tcl_HashEntry *hPtr;
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	tablePtr = tsdPtr->objThreadMap;
	if (!tablePtr) {
	    Tcl_Panic("TclFreeObj: object table not initialized");
	}
	hPtr = Tcl_FindHashEntry(tablePtr, (char *) objPtr);
	hPtr = Tcl_FindHashEntry(tablePtr, objPtr);
	if (hPtr) {
	    /*
	     * As the Tcl_Obj is going to be deleted we remove the entry.
	     */

	    ObjData *objData = (ObjData *)Tcl_GetHashValue(hPtr);

1297
1298
1299
1300
1301
1302
1303
1304

1305
1306
1307
1308
1309
1310
1311
1314
1315
1316
1317
1318
1319
1320

1321
1322
1323
1324
1325
1326
1327
1328







-
+








    /*
     * Check for a double free of the same value.  This is slightly tricky
     * because it is customary to free a Tcl_Obj when its refcount falls
     * either from 1 to 0, or from 0 to -1.  Falling from -1 to -2, though,
     * and so on, is always a sign of a botch in the caller.
     */
    if (objPtr->refCount == (size_t)-2) {
    if (objPtr->refCount < -1) {
	Tcl_Panic("Reference count for %p was negative", objPtr);
    }
    /*
     * Now, in case we just approved drop from 1 to 0 as acceptable, make
     * sure we do not accept a second free when falling from 0 to -1.
     * Skip that possibility so any double free will trigger the panic.
     */
1336
1337
1338
1339
1340
1341
1342
1343

1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359

1360
1361
1362
1363
1364
1365

1366
1367
1368

1369
1370
1371
1372
1373
1374
1375
1353
1354
1355
1356
1357
1358
1359

1360
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
1387
1388
1389
1390
1391
1392







-
+















-
+





-
+


-
+







	TclIncrObjsFreed();
	ObjDeletionLock(context);
	while (ObjOnStack(context)) {
	    Tcl_Obj *objToFree;

	    PopObjToDelete(context, objToFree);
	    TCL_DTRACE_OBJ_FREE(objToFree);
	    TclFreeIntRep(objToFree);
	    TclFreeInternalRep(objToFree);

	    Tcl_MutexLock(&tclObjMutex);
	    Tcl_Free(objToFree);
	    Tcl_MutexUnlock(&tclObjMutex);
	    TclIncrObjsFreed();
	}
	ObjDeletionUnlock(context);
    }

    /*
     * We cannot use TclGetContinuationTable() here, because that may
     * re-initialize the thread-data for calls coming after the finalization.
     * We have to access it using the low-level call and then check for
     * validity. This function can be called after TclFinalizeThreadData() has
     * already killed the thread-global data structures. Performing
     * TCL_TSD_INIT will leave us with an un-initialized memory block upon
     * TCL_TSD_INIT will leave us with an uninitialized memory block upon
     * which we crash (if we where to access the uninitialized hashtable).
     */

    {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
        Tcl_HashEntry *hPtr;
	Tcl_HashEntry *hPtr;

	if (tsdPtr->lineCLPtr) {
            hPtr = Tcl_FindHashEntry(tsdPtr->lineCLPtr, objPtr);
	    hPtr = Tcl_FindHashEntry(tsdPtr->lineCLPtr, objPtr);
	    if (hPtr) {
		Tcl_Free(Tcl_GetHashValue(hPtr));
		Tcl_DeleteHashEntry(hPtr);
	    }
	}
    }
}
1443
1444
1445
1446
1447
1448
1449
1450

1451
1452
1453
1454
1455
1456

1457
1458
1459

1460
1461
1462
1463
1464
1465
1466
1460
1461
1462
1463
1464
1465
1466

1467
1468
1469
1470
1471
1472

1473
1474
1475

1476
1477
1478
1479
1480
1481
1482
1483







-
+





-
+


-
+








    /*
     * We cannot use TclGetContinuationTable() here, because that may
     * re-initialize the thread-data for calls coming after the finalization.
     * We have to access it using the low-level call and then check for
     * validity. This function can be called after TclFinalizeThreadData() has
     * already killed the thread-global data structures. Performing
     * TCL_TSD_INIT will leave us with an un-initialized memory block upon
     * TCL_TSD_INIT will leave us with an uninitialized memory block upon
     * which we crash (if we where to access the uninitialized hashtable).
     */

    {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
        Tcl_HashEntry *hPtr;
	Tcl_HashEntry *hPtr;

	if (tsdPtr->lineCLPtr) {
            hPtr = Tcl_FindHashEntry(tsdPtr->lineCLPtr, objPtr);
	    hPtr = Tcl_FindHashEntry(tsdPtr->lineCLPtr, objPtr);
	    if (hPtr) {
		Tcl_Free(Tcl_GetHashValue(hPtr));
		Tcl_DeleteHashEntry(hPtr);
	    }
	}
    }
}
1555
1556
1557
1558
1559
1560
1561
1562

1563
1564
1565
1566
1567
1568
1569
1572
1573
1574
1575
1576
1577
1578

1579
1580
1581
1582
1583
1584
1585
1586







-
+







    Tcl_Obj *dupPtr,
    Tcl_Obj *objPtr)
{
    if (Tcl_IsShared(dupPtr)) {
	Tcl_Panic("%s called with shared object", "TclSetDuplicateObj");
    }
    TclInvalidateStringRep(dupPtr);
    TclFreeIntRep(dupPtr);
    TclFreeInternalRep(dupPtr);
    SetDuplicateObj(dupPtr, objPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetString --
1580
1581
1582
1583
1584
1585
1586

1587
1588
1589
1590
1591
1592
1593
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611







+







 * Side effects:
 *	May call the object's updateStringProc to update the string
 *	representation from the internal representation.
 *
 *----------------------------------------------------------------------
 */

#undef Tcl_GetString
char *
Tcl_GetString(
    Tcl_Obj *objPtr)	/* Object whose string rep byte pointer should
				 * be returned. */
{
    if (objPtr->bytes == NULL) {
	/*
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
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







-
+



















+
+

-
+


-
+







    }
    return objPtr->bytes;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetStringFromObj --
 * Tcl_GetStringFromObj/TclGetStringFromObj --
 *
 *	Returns the string representation's byte array pointer and length for
 *	an object.
 *
 * Results:
 *	Returns a pointer to the string representation of objPtr. If lengthPtr
 *	isn't NULL, the length of the string representation is stored at
 *	*lengthPtr. The byte array referenced by the returned pointer must not
 *	be modified by the caller. Furthermore, the caller must copy the bytes
 *	if they need to retain them since the object's string rep can change
 *	as a result of other operations.
 *
 * Side effects:
 *	May call the object's updateStringProc to update the string
 *	representation from the internal representation.
 *
 *----------------------------------------------------------------------
 */

#if !defined(TCL_NO_DEPRECATED)
#undef TclGetStringFromObj
char *
Tcl_GetStringFromObj(
TclGetStringFromObj(
    Tcl_Obj *objPtr,	/* Object whose string rep byte pointer should
				 * be returned. */
    int *lengthPtr)	/* If non-NULL, the location where the string
    void *lengthPtr)	/* If non-NULL, the location where the string
				 * rep's byte array length should * be stored.
				 * If NULL, no length is stored. */
{
    if (objPtr->bytes == NULL) {
	/*
	 * Note we do not check for objPtr->typePtr == NULL.  An invariant
	 * of a properly maintained Tcl_Obj is that at least  one of
1670
1671
1672
1673
1674
1675
1676
1677














































1678
1679
1680
1681
1682
1683
1684
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
1749







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







		|| objPtr->bytes[objPtr->length] != '\0') {
	    Tcl_Panic("UpdateStringProc for type '%s' "
		    "failed to create a valid string rep",
		    objPtr->typePtr->name);
	}
    }
    if (lengthPtr != NULL) {
	*lengthPtr = (objPtr->length < INT_MAX)? objPtr->length: INT_MAX;
	if (objPtr->length > INT_MAX) {
	    Tcl_Panic("Tcl_GetStringFromObj with 'int' lengthPtr"
		    " cannot handle such long strings. Please use 'Tcl_Size'");
	}
	*(int *)lengthPtr = (int)objPtr->length;
    }
    return objPtr->bytes;
}
#endif /* !defined(TCL_NO_DEPRECATED) */

#undef Tcl_GetStringFromObj
char *
Tcl_GetStringFromObj(
    Tcl_Obj *objPtr,	/* Object whose string rep byte pointer should
				 * be returned. */
    Tcl_Size *lengthPtr)	/* If non-NULL, the location where the string
				 * rep's byte array length should * be stored.
				 * If NULL, no length is stored. */
{
    if (objPtr->bytes == NULL) {
	/*
	 * Note we do not check for objPtr->typePtr == NULL.  An invariant
	 * of a properly maintained Tcl_Obj is that at least  one of
	 * objPtr->bytes and objPtr->typePtr must not be NULL.  If broken
	 * extensions fail to maintain that invariant, we can crash here.
	 */

	if (objPtr->typePtr->updateStringProc == NULL) {
	    /*
	     * Those Tcl_ObjTypes which choose not to define an
	     * updateStringProc must be written in such a way that
	     * (objPtr->bytes) never becomes NULL.
	     */
	    Tcl_Panic("UpdateStringProc should not be invoked for type %s",
		    objPtr->typePtr->name);
	}
	objPtr->typePtr->updateStringProc(objPtr);
	if (objPtr->bytes == NULL
		|| objPtr->bytes[objPtr->length] != '\0') {
	    Tcl_Panic("UpdateStringProc for type '%s' "
		    "failed to create a valid string rep",
		    objPtr->typePtr->name);
	}
    }
    if (lengthPtr != NULL) {
	*lengthPtr = objPtr->length;
    }
    return objPtr->bytes;
}

/*
 *----------------------------------------------------------------------
 *
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738





1739
1740

1741
1742
1743


1744
1745
1746



1747





1748

1749
1750





1751




1752
1753
1754
1755
1756









1757
1758

1759
1760
1761
1762
1763
1764
1765
1792
1793
1794
1795
1796
1797
1798

1799



1800
1801
1802
1803
1804
1805

1806



1807
1808



1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819


1820
1821
1822
1823
1824
1825
1826
1827
1828
1829





1830
1831
1832
1833
1834
1835
1836
1837
1838


1839
1840
1841
1842
1843
1844
1845
1846







-

-
-
-
+
+
+
+
+

-
+
-
-
-
+
+
-
-
-
+
+
+

+
+
+
+
+

+
-
-
+
+
+
+
+

+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+







Tcl_InitStringRep(
    Tcl_Obj *objPtr,	/* Object whose string rep is to be set */
    const char *bytes,
    size_t numBytes)
{
    assert(objPtr->bytes == NULL || bytes == NULL);

    /* Allocate */
    if (objPtr->bytes == NULL) {
	/* Allocate only as empty - extend later if bytes copied */
	objPtr->length = 0;
	if (numBytes) {
	/* Start with no string rep */
	if (numBytes == 0) {
	    TclInitEmptyStringRep(objPtr);
	    return objPtr->bytes;
	} else {
	    objPtr->bytes = (char *)Tcl_AttemptAlloc(numBytes + 1);
	    if (objPtr->bytes == NULL) {
	    if (objPtr->bytes) {
		return NULL;
	    }
	    if (bytes) {
		objPtr->length = numBytes;
		if (bytes) {
		/* Copy */
		memcpy(objPtr->bytes, bytes, numBytes);
		objPtr->length = numBytes;
		    memcpy(objPtr->bytes, bytes, numBytes);
		}
		objPtr->bytes[objPtr->length] = '\0';
	    }
	}
    } else if (objPtr->bytes == &tclEmptyString) {
	/* Start with empty string rep (not allocated) */
	if (numBytes == 0) {
	    return objPtr->bytes;
	} else {
	    objPtr->bytes = (char *)Tcl_AttemptAlloc(numBytes + 1);
	    TclInitStringRep(objPtr, NULL, 0);
	}
	    if (objPtr->bytes) {
		objPtr->length = numBytes;
		objPtr->bytes[objPtr->length] = '\0';
	    }
	}
    } else {
	/* Start with non-empty string rep (allocated) */
	if (numBytes == 0) {
	    Tcl_Free(objPtr->bytes);
	    TclInitEmptyStringRep(objPtr);
	/* objPtr->bytes != NULL bytes == NULL - Truncate */
	objPtr->bytes = (char *)Tcl_Realloc(objPtr->bytes, numBytes + 1);
	objPtr->length = numBytes;
    }

	    return objPtr->bytes;
	} else {
	    objPtr->bytes = (char *)Tcl_AttemptRealloc(objPtr->bytes,
		    numBytes + 1);
	    if (objPtr->bytes) {
		objPtr->length = numBytes;
		objPtr->bytes[objPtr->length] = '\0';
	    }
	}
    /* Terminate */
    objPtr->bytes[objPtr->length] = '\0';
    }

    return objPtr->bytes;
}

/*
 *----------------------------------------------------------------------
 *
1804
1805
1806
1807
1808
1809
1810
1811

1812
1813
1814


1815
1816
1817

1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831

1832
1833
1834

1835
1836
1837


1838
1839

1840
1841

1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852

1853
1854
1855
1856
1857
1858

1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869


1870
1871
1872
1873

1874
1875
1876
1877
1878
1879

1880
1881
1882
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
1958
1959
1960
1961
1962
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
1958
1959

1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974

1975
1976
1977

1978
1979
1980
1981
1982
1983

1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994

1995
1996
1997
1998
1999
2000
2001

2002
2003
2004
2005

2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023


2024
2025

2026
2027

2028
2029
2030

2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041



2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103







-
+

-
-
+
+


-
+













-
+


-
+

-
-
+
+

-
+

-
+










-
+





-
+









-
-
+
+



-
+





-
+














-
+


-
+





-
+










-
+




+

-
+


+
-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
-
+

-
+


-
+










-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
+



+
+
+
+
+
+
+
+
+
+







{
    return TclHasStringRep(objPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_StoreIntRep --
 * Tcl_StoreInternalRep --
 *
 *	This function is called to set the object's internal
 *	representation to match a particular type.
 *	Called to set the object's internal representation to match a
 *	particular type.
 *
 *	It is the caller's responsibility to guarantee that
 *	the value of the submitted IntRep is in agreement with
 *	the value of the submitted internalrep is in agreement with
 *	the value of any existing string rep.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Calls the freeIntRepProc of the current Tcl_ObjType, if any.
 *	Sets the internalRep and typePtr fields to the submitted values.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_StoreIntRep(
Tcl_StoreInternalRep(
    Tcl_Obj *objPtr,		/* Object whose internal rep should be set. */
    const Tcl_ObjType *typePtr,	/* New type for the object */
    const Tcl_ObjIntRep *irPtr)	/* New IntRep for the object */
    const Tcl_ObjInternalRep *irPtr)	/* New internalrep for the object */
{
    /* Clear out any existing IntRep ( "shimmer" ) */
    TclFreeIntRep(objPtr);
    /* Clear out any existing internalrep ( "shimmer" ) */
    TclFreeInternalRep(objPtr);

    /* When irPtr == NULL, just leave objPtr with no IntRep for typePtr */
    /* When irPtr == NULL, just leave objPtr with no internalrep for typePtr */
    if (irPtr) {
	/* Copy the new IntRep into place */
	/* Copy the new internalrep into place */
	objPtr->internalRep = *irPtr;

	/* Set the type to match */
	objPtr->typePtr = typePtr;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FetchIntRep --
 * Tcl_FetchInternalRep --
 *
 *	This function is called to retrieve the object's internal
 *	representation matching a requested type, if any.
 *
 * Results:
 *	A read-only pointer to the associated Tcl_ObjIntRep, or
 *	A read-only pointer to the associated Tcl_ObjInternalRep, or
 *	NULL if no such internal representation exists.
 *
 * Side effects:
 *	Calls the freeIntRepProc of the current Tcl_ObjType, if any.
 *	Sets the internalRep and typePtr fields to the submitted values.
 *
 *----------------------------------------------------------------------
 */

Tcl_ObjIntRep *
Tcl_FetchIntRep(
Tcl_ObjInternalRep *
Tcl_FetchInternalRep(
    Tcl_Obj *objPtr,		/* Object to fetch from. */
    const Tcl_ObjType *typePtr)	/* Requested type */
{
    return TclFetchIntRep(objPtr, typePtr);
    return TclFetchInternalRep(objPtr, typePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FreeIntRep --
 * Tcl_FreeInternalRep --
 *
 *	This function is called to free an object's internal representation.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Calls the freeIntRepProc of the current Tcl_ObjType, if any.
 *	Sets typePtr field to NULL.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_FreeIntRep(
Tcl_FreeInternalRep(
    Tcl_Obj *objPtr)	/* Object whose internal rep should be freed. */
{
    TclFreeIntRep(objPtr);
    TclFreeInternalRep(objPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetBooleanFromObj --
 * Tcl_GetBoolFromObj, Tcl_GetBooleanFromObj --
 *
 *	Attempt to return a boolean from the Tcl object "objPtr". This
 *	includes conversion from any of Tcl's numeric types.
 *
 * Results:
 *	The return value is a standard Tcl object result. If an error occurs
 *	during conversion, an error message is left in the interpreter's
 *	result unless "interp" is NULL.
 *
 * Side effects:
 *	The intrep of *objPtr may be changed.
 *	The internalrep of *objPtr may be changed.
 *
 *----------------------------------------------------------------------
 */

#undef Tcl_GetBoolFromObj
int
Tcl_GetBooleanFromObj(
Tcl_GetBoolFromObj(
    Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
    Tcl_Obj *objPtr,	/* The object from which to get boolean. */
    int flags,
    int *boolPtr)	/* Place to store resulting boolean. */
    char *charPtr)	/* Place to store resulting boolean. */
{
    int result;
    Tcl_Size length;

    if ((flags & TCL_NULL_OK) && (objPtr == NULL || Tcl_GetString(objPtr)[0] == '\0')) {
	result = -1;
	goto boolEnd;
    } else if (objPtr == NULL) {
	if (interp) {
	    TclNewObj(objPtr);
	    TclParseNumber(interp, objPtr, (flags & TCL_NULL_OK)
		    ? "boolean value or \"\"" : "boolean value", NULL, TCL_INDEX_NONE, NULL, 0);
	    Tcl_DecrRefCount(objPtr);
	}
	return TCL_ERROR;
    }
    do {
	if (objPtr->typePtr == &tclIntType || objPtr->typePtr == &tclBooleanType) {
	    *boolPtr = (objPtr->internalRep.wideValue != 0);
	if (TclHasInternalRep(objPtr, &tclIntType) || TclHasInternalRep(objPtr, &tclBooleanType)) {
	    result = (objPtr->internalRep.wideValue != 0);
	    return TCL_OK;
	    goto boolEnd;
	}
	if (objPtr->typePtr == &tclDoubleType) {
	if (TclHasInternalRep(objPtr, &tclDoubleType)) {
	    /*
	     * Caution: Don't be tempted to check directly for the "double"
	     * Tcl_ObjType and then compare the intrep to 0.0. This isn't
	     * Tcl_ObjType and then compare the internalrep to 0.0. This isn't
	     * reliable because a "double" Tcl_ObjType can hold the NaN value.
	     * Use the API Tcl_GetDoubleFromObj, which does the checking and
	     * sets the proper error message for us.
	     */

	    double d;

	    if (Tcl_GetDoubleFromObj(interp, objPtr, &d) != TCL_OK) {
		return TCL_ERROR;
	    }
	    *boolPtr = (d != 0.0);
	    return TCL_OK;
	}
	    result = (d != 0.0);
	    goto boolEnd;
	}
	if (TclHasInternalRep(objPtr, &tclBignumType)) {
	    result = 1;
	boolEnd:
	    if (charPtr != NULL) {
		flags &= (TCL_NULL_OK-2);
		if (flags) {
		    if (flags == (int)sizeof(int)) {
			*(int *)charPtr = result;
			return TCL_OK;
		    } else if (flags == (int)sizeof(short)) {
			*(short *)charPtr = result;
			return TCL_OK;
		    } else {
			Tcl_Panic("Wrong bool var for %s", "Tcl_GetBoolFromObj");
		    }
	if (objPtr->typePtr == &tclBignumType) {
	    *boolPtr = 1;
		}
		*charPtr = result;
	    }
	    return TCL_OK;
	}
	/* Handle dict separately, because it doesn't have a lengthProc */
	if (TclHasInternalRep(objPtr, &tclDictType)) {
	    Tcl_DictObjSize(NULL, objPtr, &length);
	    if (length > 0) {
	    listRep:
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf("expected boolean value%s but got a list",
			    (flags & TCL_NULL_OK) ? " or \"\"" : ""));
		}
		return TCL_ERROR;
	    }
	}
	Tcl_ObjTypeLengthProc *lengthProc = TclObjTypeHasProc(objPtr, lengthProc);
	if (lengthProc && lengthProc(objPtr) != 1) {
	    goto listRep;
	}
    } while ((ParseBoolean(objPtr) == TCL_OK) || (TCL_OK ==
	    TclParseNumber(interp, objPtr, "boolean value", NULL,-1,NULL,0)));
	    TclParseNumber(interp, objPtr, (flags & TCL_NULL_OK)
		    ? "boolean value or \"\"" : "boolean value", NULL,-1,NULL,0)));
    return TCL_ERROR;
}

#undef Tcl_GetBooleanFromObj
int
Tcl_GetBooleanFromObj(
    Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
    Tcl_Obj *objPtr,	/* The object from which to get boolean. */
    int *intPtr)	/* Place to store resulting boolean. */
{
    return Tcl_GetBoolFromObj(interp, objPtr, (TCL_NULL_OK-2)&(int)sizeof(int), (char *)(void *)intPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TclSetBooleanFromAny --
 *
 *	Attempt to generate a boolean internal form for the Tcl object
 *	"objPtr".
1981
1982
1983
1984
1985
1986
1987
1988

1989
1990
1991
1992
1993
1994
1995

1996
1997
1998
1999

2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011


2012
2013
2014
2015
2016
2017
2018

2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030


2031
2032

2033
2034
2035


2036
2037
2038
2039
2040
2041
2042
2122
2123
2124
2125
2126
2127
2128

2129
2130
2131
2132
2133
2134
2135

2136
2137
2138
2139

2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150


2151
2152
2153
2154
2155
2156
2157
2158

2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169


2170
2171
2172

2173
2174


2175
2176
2177
2178
2179
2180
2181
2182
2183







-
+






-
+



-
+










-
-
+
+






-
+










-
-
+
+

-
+

-
-
+
+







    /*
     * For some "pure" numeric Tcl_ObjTypes (no string rep), we can determine
     * whether a boolean conversion is possible without generating the string
     * rep.
     */

    if (objPtr->bytes == NULL) {
	if (objPtr->typePtr == &tclIntType) {
	if (TclHasInternalRep(objPtr, &tclIntType)) {
	    if ((Tcl_WideUInt)objPtr->internalRep.wideValue < 2) {
		return TCL_OK;
	    }
	    goto badBoolean;
	}

	if (objPtr->typePtr == &tclBignumType) {
	if (TclHasInternalRep(objPtr, &tclBignumType)) {
	    goto badBoolean;
	}

	if (objPtr->typePtr == &tclDoubleType) {
	if (TclHasInternalRep(objPtr, &tclDoubleType)) {
	    goto badBoolean;
	}
    }

    if (ParseBoolean(objPtr) == TCL_OK) {
	return TCL_OK;
    }

  badBoolean:
    if (interp != NULL) {
	size_t length;
	const char *str = TclGetStringFromObj(objPtr, &length);
	Tcl_Size length;
	const char *str = Tcl_GetStringFromObj(objPtr, &length);
	Tcl_Obj *msg;

	TclNewLiteralStringObj(msg, "expected boolean value but got \"");
	Tcl_AppendLimitedToObj(msg, str, length, 50, "");
	Tcl_AppendToObj(msg, "\"", -1);
	Tcl_SetObjResult(interp, msg);
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "BOOLEAN", NULL);
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "BOOLEAN", (char *)NULL);
    }
    return TCL_ERROR;
}

static int
ParseBoolean(
    Tcl_Obj *objPtr)	/* The object to parse/convert. */
{
    int newBool;
    char lowerCase[6];
    size_t i, length;
    const char *str = TclGetStringFromObj(objPtr, &length);
    Tcl_Size i, length;
    const char *str = Tcl_GetStringFromObj(objPtr, &length);

    if ((length == 0) || (length > 5)) {
    if ((length < 1) || (length > 5)) {
	/*
         * Longest valid boolean string rep. is "false".
         */
	 * Longest valid boolean string rep. is "false".
	 */

	return TCL_ERROR;
    }

    switch (str[0]) {
    case '0':
	if (length == 1) {
2121
2122
2123
2124
2125
2126
2127
2128

2129
2130
2131
2132
2133
2134

2135
2136
2137
2138
2139
2140
2141
2262
2263
2264
2265
2266
2267
2268

2269
2270
2271
2272
2273
2274

2275
2276
2277
2278
2279
2280
2281
2282







-
+





-
+







    /*
     * Free the old internalRep before setting the new one. We do this as late
     * as possible to allow the conversion code, in particular
     * Tcl_GetStringFromObj, to use that old internalRep.
     */

  goodBoolean:
    TclFreeIntRep(objPtr);
    TclFreeInternalRep(objPtr);
    objPtr->internalRep.wideValue = newBool;
    objPtr->typePtr = &tclBooleanType;
    return TCL_OK;

  numericBoolean:
    TclFreeIntRep(objPtr);
    TclFreeInternalRep(objPtr);
    objPtr->internalRep.wideValue = newBool;
    objPtr->typePtr = &tclIntType;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
2293
2294
2295
2296
2297
2298
2299

2300
2301
2302


2303
2304
2305
2306
2307


2308
2309
2310
2311
2312
2313
2314

2315
2316
2317
2318

2319
2320
2321
2322
2323
















2324
2325
2326
2327
2328
2329
2330
2434
2435
2436
2437
2438
2439
2440
2441
2442


2443
2444
2445
2446
2447


2448
2449
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







+

-
-
+
+



-
-
+
+






-
+



-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








int
Tcl_GetDoubleFromObj(
    Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
    Tcl_Obj *objPtr,	/* The object from which to get a double. */
    double *dblPtr)	/* Place to store resulting double. */
{
    Tcl_Size length;
    do {
	if (objPtr->typePtr == &tclDoubleType) {
	    if (TclIsNaN(objPtr->internalRep.doubleValue)) {
	if (TclHasInternalRep(objPtr, &tclDoubleType)) {
	    if (isnan(objPtr->internalRep.doubleValue)) {
		if (interp != NULL) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "floating point value is Not a Number", -1));
                    Tcl_SetErrorCode(interp, "TCL", "VALUE", "DOUBLE", "NAN",
                            NULL);
		    Tcl_SetErrorCode(interp, "TCL", "VALUE", "DOUBLE", "NAN",
			    (char *)NULL);
		}
		return TCL_ERROR;
	    }
	    *dblPtr = (double) objPtr->internalRep.doubleValue;
	    return TCL_OK;
	}
	if (objPtr->typePtr == &tclIntType) {
	if (TclHasInternalRep(objPtr, &tclIntType)) {
	    *dblPtr = (double) objPtr->internalRep.wideValue;
	    return TCL_OK;
	}
	if (objPtr->typePtr == &tclBignumType) {
	if (TclHasInternalRep(objPtr, &tclBignumType)) {
	    mp_int big;

	    TclUnpackBignum(objPtr, big);
	    *dblPtr = TclBignumToDouble(&big);
	    return TCL_OK;
	}
	/* Handle dict separately, because it doesn't have a lengthProc */
	if (TclHasInternalRep(objPtr, &tclDictType)) {
	    Tcl_DictObjSize(NULL, objPtr, &length);
	    if (length > 0) {
	    listRep:
		if (interp) {
		    Tcl_SetObjResult(interp,
			    Tcl_NewStringObj("expected floating-point number but got a list", TCL_INDEX_NONE));
		}
		return TCL_ERROR;
	    }
	}
	Tcl_ObjTypeLengthProc *lengthProc = TclObjTypeHasProc(objPtr, lengthProc);
	if (lengthProc && lengthProc(objPtr) != 1) {
	    goto listRep;
	}
    } while (SetDoubleFromAny(interp, objPtr) == TCL_OK);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
2377
2378
2379
2380
2381
2382
2383
2384

2385
2386
2387
2388
2389
2390
2391
2535
2536
2537
2538
2539
2540
2541

2542
2543
2544
2545
2546
2547
2548
2549







-
+








static void
UpdateStringOfDouble(
    Tcl_Obj *objPtr)	/* Double obj with string rep to update. */
{
    char *dst = Tcl_InitStringRep(objPtr, NULL, TCL_DOUBLE_SPACE);

    TclOOM(dst, (size_t)TCL_DOUBLE_SPACE + 1);
    TclOOM(dst, TCL_DOUBLE_SPACE + 1);

    Tcl_PrintDouble(NULL, objPtr->internalRep.doubleValue, dst);
    (void) Tcl_InitStringRep(objPtr, NULL, strlen(dst));
}

/*
 *----------------------------------------------------------------------
2429
2430
2431
2432
2433
2434
2435
2436

2437
2438

2439
2440
2441
2442
2443
2444
2445
2587
2588
2589
2590
2591
2592
2593

2594
2595

2596
2597
2598
2599
2600
2601
2602
2603







-
+

-
+








    if (TclGetLongFromObj(interp, objPtr, &l) != TCL_OK) {
	return TCL_ERROR;
    }
    if ((ULONG_MAX > UINT_MAX) && ((l > UINT_MAX) || (l < INT_MIN))) {
	if (interp != NULL) {
	    const char *s =
		    "integer value too large to represent as non-long integer";
		    "integer value too large to represent";
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
	    Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL);
	    Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *)NULL);
	}
	return TCL_ERROR;
    }
    *intPtr = (int) l;
    return TCL_OK;
#endif
}
2462
2463
2464
2465
2466
2467
2468
2469

2470
2471
2472
2473
2474
2475
2476
2620
2621
2622
2623
2624
2625
2626

2627
2628
2629
2630
2631
2632
2633
2634







-
+








static int
SetIntFromAny(
    Tcl_Interp *interp,		/* Tcl interpreter */
    Tcl_Obj *objPtr)		/* Pointer to the object to convert */
{
    Tcl_WideInt w;
    return Tcl_GetWideIntFromObj(interp, objPtr, &w);
    return TclGetWideIntFromObj(interp, objPtr, &w);
}

/*
 *----------------------------------------------------------------------
 *
 * UpdateStringOfInt --
 *
2490
2491
2492
2493
2494
2495
2496
2497

2498
2499
2500
2501
2502
2503
2504
2648
2649
2650
2651
2652
2653
2654

2655
2656
2657
2658
2659
2660
2661
2662







-
+








static void
UpdateStringOfInt(
    Tcl_Obj *objPtr)	/* Int object whose string rep to update. */
{
    char *dst = Tcl_InitStringRep( objPtr, NULL, TCL_INTEGER_SPACE);

    TclOOM(dst, (size_t)TCL_INTEGER_SPACE + 1);
    TclOOM(dst, TCL_INTEGER_SPACE + 1);
    (void) Tcl_InitStringRep(objPtr, NULL,
	    TclFormatInt(dst, objPtr->internalRep.wideValue));
}

/*
 *----------------------------------------------------------------------
 *
2522
2523
2524
2525
2526
2527
2528

2529
2530
2531

2532
2533
2534
2535
2536

2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549

2550
2551
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
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







+


-
+




-
+












-
+





-
+

-
-
-
-
+
+
+
+



-
+




















-
+




-
+













-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








int
Tcl_GetLongFromObj(
    Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
    Tcl_Obj *objPtr,	/* The object from which to get a long. */
    long *longPtr)	/* Place to store resulting long. */
{
    Tcl_Size length;
    do {
#ifdef TCL_WIDE_INT_IS_LONG
	if (objPtr->typePtr == &tclIntType) {
	if (TclHasInternalRep(objPtr, &tclIntType)) {
	    *longPtr = objPtr->internalRep.wideValue;
	    return TCL_OK;
	}
#else
	if (objPtr->typePtr == &tclIntType) {
	if (TclHasInternalRep(objPtr, &tclIntType)) {
	    /*
	     * We return any integer in the range LONG_MIN to ULONG_MAX
	     * converted to a long, ignoring overflow. The rule preserves
	     * existing semantics for conversion of integers on input, but
	     * avoids inadvertent demotion of wide integers to 32-bit ones in
	     * the internal rep.
	     */

	    Tcl_WideInt w = objPtr->internalRep.wideValue;

	    if (w >= (Tcl_WideInt)(LONG_MIN)
		    && w <= (Tcl_WideInt)(ULONG_MAX)) {
		*longPtr = (long) w;
		*longPtr = (long)w;
		return TCL_OK;
	    }
	    goto tooLarge;
	}
#endif
	if (objPtr->typePtr == &tclDoubleType) {
	if (TclHasInternalRep(objPtr, &tclDoubleType)) {
	    if (interp != NULL) {
                Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                        "expected integer but got \"%s\"",
                        TclGetString(objPtr)));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", NULL);
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"expected integer but got \"%s\"",
			TclGetString(objPtr)));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", (char *)NULL);
	    }
	    return TCL_ERROR;
	}
	if (objPtr->typePtr == &tclBignumType) {
	if (TclHasInternalRep(objPtr, &tclBignumType)) {
	    /*
	     * Must check for those bignum values that can fit in a long, even
	     * when auto-narrowing is enabled. Only those values in the signed
	     * long range get auto-narrowed to tclIntType, while all the
	     * values in the unsigned long range will fit in a long.
	     */

		{
	    mp_int big;
	    unsigned long scratch, value = 0;
	    unsigned char *bytes = (unsigned char *) &scratch;
	    size_t numBytes;

	    TclUnpackBignum(objPtr, big);
	    if (mp_to_ubin(&big, bytes, sizeof(long), &numBytes) == MP_OKAY) {
		while (numBytes-- > 0) {
			value = (value << CHAR_BIT) | *bytes++;
		}
		if (big.sign) {
		    if (value <= 1 + (unsigned long)LONG_MAX) {
			*longPtr = - (long) value;
			*longPtr = (long)(-value);
			return TCL_OK;
		    }
		} else {
		    if (value <= (unsigned long)ULONG_MAX) {
			*longPtr = (long) value;
			*longPtr = (long)value;
			return TCL_OK;
		    }
		}
	    }
	    }
#ifndef TCL_WIDE_INT_IS_LONG
	tooLarge:
#endif
	    if (interp != NULL) {
		const char *s = "integer value too large to represent";
		Tcl_Obj *msg = Tcl_NewStringObj(s, -1);

		Tcl_SetObjResult(interp, msg);
		Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL);
		Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *)NULL);
	    }
	    return TCL_ERROR;
	}
	/* Handle dict separately, because it doesn't have a lengthProc */
	if (TclHasInternalRep(objPtr, &tclDictType)) {
	    Tcl_DictObjSize(NULL, objPtr, &length);
	    if (length > 0) {
	    listRep:
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj("expected integer but got a list", -1));
		}
		return TCL_ERROR;
	    }
	}
	Tcl_ObjTypeLengthProc *lengthProc = TclObjTypeHasProc(objPtr, lengthProc);
	if (lengthProc && lengthProc(objPtr) != 1) {
	    goto listRep;
	}
    } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL,
	    TCL_PARSE_INTEGER_ONLY)==TCL_OK);
    return TCL_ERROR;
}

/*
2659
2660
2661
2662
2663
2664
2665



























2666
2667
2668
2669
2670
2671
2672
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








    TclNewObj(objPtr);
    TclSetIntObj(objPtr, wideValue);
    return objPtr;
}
#endif /* if TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------------
 *
 * Tcl_NewWideUIntObj --
 *
 * Results:
 *	The newly created object is returned. This object will have an invalid
 *	string representation. The returned object has ref count 0.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
Tcl_NewWideUIntObj(
    Tcl_WideUInt uwideValue)
				/* Wide integer used to initialize the new
				 * object. */
{
    Tcl_Obj *objPtr;

    TclNewUIntObj(objPtr, uwideValue);
    return objPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DbNewWideIntObj --
 *
 *	If a client is compiled with TCL_MEM_DEBUG defined, calls to
 *	Tcl_NewWideIntObj to create new wide integer end up calling the
2755
2756
2757
2758
2759
2760
2761








































2762
2763
2764
2765
2766
2767
2768
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







{
    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_SetWideIntObj");
    }

    TclSetIntObj(objPtr, wideValue);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetWideUIntObj --
 *
 *	Modify an object to be a wide integer object or a bignum object
 *	and to have the specified unsigned wide integer value.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The object's old string rep, if any, is freed. Also, any old internal
 *	rep is freed.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetWideUIntObj(
    Tcl_Obj *objPtr,	/* Object w. internal rep to init. */
    Tcl_WideUInt uwideValue)
				/* Wide integer used to initialize the
				 * object's value. */
{
    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_SetWideUIntObj");
    }

    if (uwideValue > WIDE_MAX) {
	mp_int bignumValue;
	if (mp_init_u64(&bignumValue, uwideValue) != MP_OKAY) {
	    Tcl_Panic("%s: memory overflow", "Tcl_SetWideUIntObj");
	}
	TclSetBignumInternalRep(objPtr, &bignumValue);
    } {
	TclSetIntObj(objPtr, (Tcl_WideInt)uwideValue);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetWideIntFromObj --
 *
 *	Attempt to return a wide integer from the Tcl object "objPtr". If the
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
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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
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







+

-
+



-
+

-
-
-
-
+
+
+
+



-
+


















-
+




-
+









-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+







int
Tcl_GetWideIntFromObj(
    Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
    Tcl_Obj *objPtr,	/* Object from which to get a wide int. */
    Tcl_WideInt *wideIntPtr)
				/* Place to store resulting long. */
{
    Tcl_Size length;
    do {
	if (objPtr->typePtr == &tclIntType) {
	if (TclHasInternalRep(objPtr, &tclIntType)) {
	    *wideIntPtr = objPtr->internalRep.wideValue;
	    return TCL_OK;
	}
	if (objPtr->typePtr == &tclDoubleType) {
	if (TclHasInternalRep(objPtr, &tclDoubleType)) {
	    if (interp != NULL) {
                Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                        "expected integer but got \"%s\"",
                        TclGetString(objPtr)));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", NULL);
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"expected integer but got \"%s\"",
			TclGetString(objPtr)));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", (char *)NULL);
	    }
	    return TCL_ERROR;
	}
	if (objPtr->typePtr == &tclBignumType) {
	if (TclHasInternalRep(objPtr, &tclBignumType)) {
	    /*
	     * Must check for those bignum values that can fit in a
	     * Tcl_WideInt, even when auto-narrowing is enabled.
	     */

	    mp_int big;
	    Tcl_WideUInt value = 0;
	    size_t numBytes;
	    Tcl_WideInt scratch;
	    unsigned char *bytes = (unsigned char *) &scratch;

	    TclUnpackBignum(objPtr, big);
	    if (mp_to_ubin(&big, bytes, sizeof(Tcl_WideInt), &numBytes) == MP_OKAY) {
		while (numBytes-- > 0) {
		    value = (value << CHAR_BIT) | *bytes++;
		}
		if (big.sign) {
		    if (value <= 1 + ~(Tcl_WideUInt)WIDE_MIN) {
			*wideIntPtr = - (Tcl_WideInt) value;
			*wideIntPtr = (Tcl_WideInt)(-value);
			return TCL_OK;
		    }
		} else {
		    if (value <= (Tcl_WideUInt)WIDE_MAX) {
			*wideIntPtr = (Tcl_WideInt) value;
			*wideIntPtr = (Tcl_WideInt)value;
			return TCL_OK;
		    }
		}
	    }
	    if (interp != NULL) {
		const char *s = "integer value too large to represent";
		Tcl_Obj *msg = Tcl_NewStringObj(s, -1);

		Tcl_SetObjResult(interp, msg);
		Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL);
		Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *)NULL);
	    }
	    return TCL_ERROR;
	}
	/* Handle dict separately, because it doesn't have a lengthProc */
	if (TclHasInternalRep(objPtr, &tclDictType)) {
	    Tcl_DictObjSize(NULL, objPtr, &length);
	    if (length > 0) {
	    listRep:
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj("expected integer but got a list", -1));
		}
		return TCL_ERROR;
	    }
	}
	Tcl_ObjTypeLengthProc *lengthProc = TclObjTypeHasProc(objPtr, lengthProc);
	if (lengthProc && lengthProc(objPtr) != 1) {
	    goto listRep;
	}
    } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL,
	    TCL_PARSE_INTEGER_ONLY)==TCL_OK);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetWideUIntFromObj --
 *
 *	Attempt to return a unsigned wide integer from the Tcl object "objPtr". If the
 *	object is not already a wide int object or a bignum object, an attempt will
 *	be made to convert it to one.
 *
 * Results:
 *	The return value is a standard Tcl object result. If an error occurs
 *	during conversion, an error message is left in the interpreter's
 *	result unless "interp" is NULL.
 *
 * Side effects:
 *	If the object is not already an int object, the conversion will free
 *	any old internal representation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_GetWideUIntFromObj(
    Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
    Tcl_Obj *objPtr,	/* Object from which to get a wide int. */
    Tcl_WideUInt *wideUIntPtr)
				/* Place to store resulting long. */
{
    do {
	if (TclHasInternalRep(objPtr, &tclIntType)) {
	    if (objPtr->internalRep.wideValue < 0) {
	wideUIntOutOfRange:
		if (interp != NULL) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "expected unsigned integer but got \"%s\"",
			    TclGetString(objPtr)));
		    Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", (char *)NULL);
		}
		return TCL_ERROR;
	    }
	    *wideUIntPtr = (Tcl_WideUInt)objPtr->internalRep.wideValue;
	    return TCL_OK;
	}
	if (TclHasInternalRep(objPtr, &tclDoubleType)) {
	    goto wideUIntOutOfRange;
	}
	if (TclHasInternalRep(objPtr, &tclBignumType)) {
	    /*
	     * Must check for those bignum values that can fit in a
	     * Tcl_WideUInt, even when auto-narrowing is enabled.
	     */

	    mp_int big;
	    Tcl_WideUInt value = 0;
	    size_t numBytes;
	    Tcl_WideUInt scratch;
	    unsigned char *bytes = (unsigned char *) &scratch;

	    TclUnpackBignum(objPtr, big);
	    if (big.sign == MP_NEG) {
		goto wideUIntOutOfRange;
	    }
	    if (mp_to_ubin(&big, bytes, sizeof(Tcl_WideUInt), &numBytes) == MP_OKAY) {
		while (numBytes-- > 0) {
		    value = (value << CHAR_BIT) | *bytes++;
		}
		*wideUIntPtr = (Tcl_WideUInt)value;
		return TCL_OK;
	    }

	    if (interp != NULL) {
		const char *s = "integer value too large to represent";
		Tcl_Obj *msg = Tcl_NewStringObj(s, -1);

		Tcl_SetObjResult(interp, msg);
		Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *)NULL);
	    }
	    return TCL_ERROR;
	}
    } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL,
	    TCL_PARSE_INTEGER_ONLY)==TCL_OK);
    return TCL_ERROR;
}


/*
 *----------------------------------------------------------------------
 *
 * TclGetWideBitsFromObj --
 *
 *	Attempt to return a wide integer from the Tcl object "objPtr". If the
 *	object is not already a int, double or bignum, an attempt will be made
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
3211
3212
3213
3214
3215
3216
3217

3218
3219
3220
3221

3222
3223




3224
3225
3226
3227
3228
3229
3230

3231
3232
3233
3234
3235
3236
3237
3238







-
+



-
+

-
-
-
-
+
+
+
+



-
+







int
TclGetWideBitsFromObj(
    Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
    Tcl_Obj *objPtr,            /* Object from which to get a wide int. */
    Tcl_WideInt *wideIntPtr)    /* Place to store resulting wide integer. */
{
    do {
	if (objPtr->typePtr == &tclIntType) {
	if (TclHasInternalRep(objPtr, &tclIntType)) {
	    *wideIntPtr = objPtr->internalRep.wideValue;
	    return TCL_OK;
	}
	if (objPtr->typePtr == &tclDoubleType) {
	if (TclHasInternalRep(objPtr, &tclDoubleType)) {
	    if (interp != NULL) {
                Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                        "expected integer but got \"%s\"",
                        TclGetString(objPtr)));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", NULL);
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"expected integer but got \"%s\"",
			TclGetString(objPtr)));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", (char *)NULL);
	    }
	    return TCL_ERROR;
	}
	if (objPtr->typePtr == &tclBignumType) {
	if (TclHasInternalRep(objPtr, &tclBignumType)) {
	    mp_int big;
	    mp_err err;

	    Tcl_WideUInt value = 0, scratch;
	    size_t numBytes;
	    unsigned char *bytes = (unsigned char *) &scratch;

2910
2911
2912
2913
2914
2915
2916


































2917
2918
2919
2920
2921
2922
2923
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    mp_clear(&big);
	    return TCL_OK;
	}
    } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL,
	    TCL_PARSE_INTEGER_ONLY)==TCL_OK);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetSizeIntFromObj --
 *
 *	Attempt to return a Tcl_Size from the Tcl object "objPtr".
 *
 * Results:
 *  TCL_OK - the converted Tcl_Size value is stored in *sizePtr
 *  TCL_ERROR - the error message is stored in interp
 *
 * Side effects:
 *	The function may free up any existing internal representation.
 *
 *----------------------------------------------------------------------
 */
int
Tcl_GetSizeIntFromObj(
    Tcl_Interp *interp, /* Used for error reporting if not NULL. */
    Tcl_Obj *objPtr,	/* The object from which to get a int. */
    Tcl_Size *sizePtr)  /* Place to store resulting int. */
{
    if (sizeof(Tcl_Size) == sizeof(int)) {
	return TclGetIntFromObj(interp, objPtr, (int *)sizePtr);
    } else {
	Tcl_WideInt wide;
	if (TclGetWideIntFromObj(interp, objPtr, &wide) != TCL_OK) {
	    return TCL_ERROR;
	}
	*sizePtr = (Tcl_Size)wide;
	return TCL_OK;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * FreeBignum --
 *
 *	This function frees the internal rep of a bignum.
2949
2950
2951
2952
2953
2954
2955
2956

2957
2958
2959
2960
2961
2962
2963
3324
3325
3326
3327
3328
3329
3330

3331
3332
3333
3334
3335
3336
3337
3338







-
+







 *
 *	This function duplicates the internal rep of a bignum.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The destination object receies a copy of the source object
 *	The destination object receives a copy of the source object
 *
 *----------------------------------------------------------------------
 */

static void
DupBignum(
    Tcl_Obj *srcPtr,
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036

3037
3038
3039
3040
3041
3042
3043
3396
3397
3398
3399
3400
3401
3402

3403
3404
3405
3406
3407
3408
3409

3410
3411
3412
3413
3414
3415
3416
3417







-







-
+








    stringVal = Tcl_InitStringRep(objPtr, NULL, size - 1);

    TclOOM(stringVal, size);
    if (MP_OKAY != mp_to_radix(&bignumVal, stringVal, size, NULL, 10)) {
	Tcl_Panic("conversion failure in UpdateStringOfBignum");
    }
    (void) Tcl_InitStringRep(objPtr, NULL, size - 1);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_NewBignumObj --
 *
 *	Creates an initializes a bignum object.
 *	Creates and initializes a bignum object.
 *
 * Results:
 *	Returns the newly created object.
 *
 * Side effects:
 *	The bignum value is cleared, since ownership has transferred to Tcl.
 *
3133
3134
3135
3136
3137
3138
3139
3140

3141
3142
3143
3144
3145
3146
3147
3148
3149
3150

3151
3152
3153
3154
3155
3156
3157
3158
3159
3160

3161
3162
3163
3164
3165

3166
3167
3168
3169
3170
3171
3172

3173
3174
3175
3176
3177




3178
3179
3180
3181
3182
3183
3184
3507
3508
3509
3510
3511
3512
3513

3514
3515
3516
3517
3518
3519
3520
3521
3522
3523

3524
3525
3526
3527
3528
3529
3530
3531
3532
3533

3534
3535
3536
3537
3538

3539
3540
3541
3542
3543
3544
3545

3546
3547




3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558







-
+









-
+









-
+




-
+






-
+

-
-
-
-
+
+
+
+







GetBignumFromObj(
    Tcl_Interp *interp,		/* Tcl interpreter for error reporting */
    Tcl_Obj *objPtr,		/* Object to read */
    int copy,			/* Whether to copy the returned bignum value */
    mp_int *bignumValue)	/* Returned bignum value. */
{
    do {
	if (objPtr->typePtr == &tclBignumType) {
	if (TclHasInternalRep(objPtr, &tclBignumType)) {
	    if (copy || Tcl_IsShared(objPtr)) {
		mp_int temp;

		TclUnpackBignum(objPtr, temp);
		if (mp_init_copy(bignumValue, &temp) != MP_OKAY) {
		    return TCL_ERROR;
		}
	    } else {
		TclUnpackBignum(objPtr, *bignumValue);
		/* Optimized TclFreeIntRep */
		/* Optimized TclFreeInternalRep */
		objPtr->internalRep.twoPtrValue.ptr1 = NULL;
		objPtr->internalRep.twoPtrValue.ptr2 = NULL;
		objPtr->typePtr = NULL;
		/*
		 * TODO: If objPtr has a string rep, this leaves
		 * it undisturbed.  Not clear that's proper. Pure
		 * bignum values are converted to empty string.
		 */
		if (objPtr->bytes == NULL) {
		    TclInitStringRep(objPtr, NULL, 0);
		    TclInitEmptyStringRep(objPtr);
		}
	    }
	    return TCL_OK;
	}
	if (objPtr->typePtr == &tclIntType) {
	if (TclHasInternalRep(objPtr, &tclIntType)) {
	    if (mp_init_i64(bignumValue,
		    objPtr->internalRep.wideValue) != MP_OKAY) {
		return TCL_ERROR;
	    }
	    return TCL_OK;
	}
	if (objPtr->typePtr == &tclDoubleType) {
	if (TclHasInternalRep(objPtr, &tclDoubleType)) {
	    if (interp != NULL) {
                Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                        "expected integer but got \"%s\"",
                        TclGetString(objPtr)));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", NULL);
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"expected integer but got \"%s\"",
			TclGetString(objPtr)));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", (char *)NULL);
	    }
	    return TCL_ERROR;
	}
    } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL,
	    TCL_PARSE_INTEGER_ONLY)==TCL_OK);
    return TCL_ERROR;
}
3226
3227
3228
3229
3230
3231
3232
3233

3234
3235
3236
3237
3238
3239
3240
3600
3601
3602
3603
3604
3605
3606

3607
3608
3609
3610
3611
3612
3613
3614







-
+







 *	the object if necessary.
 *
 * Results:
 *	Returns TCL_OK if the conversion is successful, TCL_ERROR otherwise.
 *
 * Side effects:
 *	A copy of bignum is stored in *bignumValue, which is expected to be
 *	uninitialized or cleared. If conversion fails, an the 'interp'
 *	uninitialized or cleared. If conversion fails and the 'interp'
 *	argument is not NULL, an error message is stored in the interpreter
 *	result.
 *
 *	It is expected that the caller will NOT have invoked mp_init on the
 *	bignum value before passing it in. Tcl will initialize the mp_int as
 *	it sets the value. The value is transferred from the internals of
 *	objPtr to the caller, passing responsibility of the caller to call
3289
3290
3291
3292
3293
3294
3295
3296

3297
3298
3299
3300
3301
3302
3303
3304
3305


3306
3307
3308
3309
3310
3311

3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327

3328
3329
3330
3331
3332
3333
3334
3663
3664
3665
3666
3667
3668
3669

3670
3671
3672
3673
3674
3675
3676
3677


3678
3679
3680
3681
3682
3683
3684

3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700

3701
3702
3703
3704
3705
3706
3707
3708







-
+







-
-
+
+





-
+















-
+







    while (numBytes-- > 0) {
	value = (value << CHAR_BIT) | *bytes++;
    }
    if (value > ((Tcl_WideUInt)WIDE_MAX + bignumValue->sign)) {
	goto tooLargeForWide;
    }
    if (bignumValue->sign) {
	TclSetIntObj(objPtr, -(Tcl_WideInt)value);
	TclSetIntObj(objPtr, (Tcl_WideInt)(-value));
    } else {
	TclSetIntObj(objPtr, (Tcl_WideInt)value);
    }
    mp_clear(bignumValue);
    return;
  tooLargeForWide:
    TclInvalidateStringRep(objPtr);
    TclFreeIntRep(objPtr);
    TclSetBignumIntRep(objPtr, bignumValue);
    TclFreeInternalRep(objPtr);
    TclSetBignumInternalRep(objPtr, bignumValue);
}

/*
 *----------------------------------------------------------------------
 *
 * TclSetBignumIntRep --
 * TclSetBignumInternalRep --
 *
 *	Install a bignum into the internal representation of an object.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Object internal representation is updated and object type is set. The
 *	bignum value is cleared, since ownership has transferred to the
 *	object.
 *
 *----------------------------------------------------------------------
 */

void
TclSetBignumIntRep(
TclSetBignumInternalRep(
    Tcl_Obj *objPtr,
    void *big)
{
    mp_int *bignumValue = (mp_int *)big;
    objPtr->typePtr = &tclBignumType;
    PACK_BIGNUM(*bignumValue, objPtr);

3343
3344
3345
3346
3347
3348
3349
3350

3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368

3369
3370
3371

3372
3373

3374
3375
3376


3377
3378
3379
3380
3381
3382
3383
3384

3385
3386
3387
3388
3389

3390
3391
3392
3393
3394
3395
3396
3397
3398















3399
3400
3401
3402




































3403
3404
3405
3406
3407
3408
3409
3717
3718
3719
3720
3721
3722
3723

3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741

3742
3743
3744

3745
3746
3747
3748
3749


3750
3751
3752
3753
3754
3755
3756
3757
3758

3759
3760
3761
3762
3763

3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835







-
+

















-
+


-
+


+

-
-
+
+







-
+




-
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    bignumValue->alloc = bignumValue->used = 0;
    bignumValue->sign = MP_NEG;
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetNumberFromObj --
 * Tcl_GetNumberFromObj --
 *
 *      Extracts a number (of any possible numeric type) from an object.
 *
 * Results:
 *      Whether the extraction worked. The type is stored in the variable
 *      referred to by the typePtr argument, and a pointer to the
 *      representation is stored in the variable referred to by the
 *      clientDataPtr.
 *
 * Side effects:
 *      Can allocate thread-specific data for handling the copy-out space for
 *      bignums; this space is shared within a thread.
 *
 *----------------------------------------------------------------------
 */

int
TclGetNumberFromObj(
Tcl_GetNumberFromObj(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    ClientData *clientDataPtr,
    void **clientDataPtr,
    int *typePtr)
{
    Tcl_Size length;
    do {
	if (objPtr->typePtr == &tclDoubleType) {
	    if (TclIsNaN(objPtr->internalRep.doubleValue)) {
	if (TclHasInternalRep(objPtr, &tclDoubleType)) {
	    if (isnan(objPtr->internalRep.doubleValue)) {
		*typePtr = TCL_NUMBER_NAN;
	    } else {
		*typePtr = TCL_NUMBER_DOUBLE;
	    }
	    *clientDataPtr = &objPtr->internalRep.doubleValue;
	    return TCL_OK;
	}
	if (objPtr->typePtr == &tclIntType) {
	if (TclHasInternalRep(objPtr, &tclIntType)) {
	    *typePtr = TCL_NUMBER_INT;
	    *clientDataPtr = &objPtr->internalRep.wideValue;
	    return TCL_OK;
	}
	if (objPtr->typePtr == &tclBignumType) {
	if (TclHasInternalRep(objPtr, &tclBignumType)) {
	    static Tcl_ThreadDataKey bignumKey;
	    mp_int *bigPtr = (mp_int *)Tcl_GetThreadData(&bignumKey,
		    sizeof(mp_int));

	    TclUnpackBignum(objPtr, *bigPtr);
	    *typePtr = TCL_NUMBER_BIG;
	    *clientDataPtr = bigPtr;
	    return TCL_OK;
	}
	/* Handle dict separately, because it doesn't have a lengthProc */
	if (TclHasInternalRep(objPtr, &tclDictType)) {
	    Tcl_DictObjSize(NULL, objPtr, &length);
	    if (length > 0) {
	    listRep:
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj("expected number but got a list", -1));
		}
		return TCL_ERROR;
	    }
	}
	Tcl_ObjTypeLengthProc *lengthProc = TclObjTypeHasProc(objPtr, lengthProc);
	if (lengthProc && lengthProc(objPtr) != 1) {
	    goto listRep;
	}
    } while (TCL_OK ==
	    TclParseNumber(interp, objPtr, "number", NULL, -1, NULL, 0));
    return TCL_ERROR;
}

int
Tcl_GetNumber(
    Tcl_Interp *interp,
    const char *bytes,
    Tcl_Size numBytes,
    void **clientDataPtr,
    int *typePtr)
{
    static Tcl_ThreadDataKey numberCacheKey;
    Tcl_Obj *objPtr = (Tcl_Obj *)Tcl_GetThreadData(&numberCacheKey,
	    sizeof(Tcl_Obj));

    Tcl_FreeInternalRep(objPtr);

    if (bytes == NULL) {
	bytes = &tclEmptyString;
	numBytes = 0;
    }
    if (numBytes < 0) {
	numBytes = strlen(bytes);
    }
    if (numBytes > INT_MAX) {
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "max size for a Tcl value (%d bytes) exceeded", INT_MAX));
	    Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
	}
	return TCL_ERROR;
    }

    objPtr->bytes = (char *) bytes;
    objPtr->length = numBytes;

    return Tcl_GetNumberFromObj(interp, objPtr, clientDataPtr, typePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_IncrRefCount --
 *
 *	Increments the reference count of the object.
3426
3427
3428
3429
3430
3431
3432
3433

3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446






















3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466

3467
3468
3469
3470
3471
3472
3473
3852
3853
3854
3855
3856
3857
3858

3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913

3914
3915
3916
3917
3918
3919
3920
3921







-
+













+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



















-
+







 *----------------------------------------------------------------------
 *
 * Tcl_DecrRefCount --
 *
 *	Decrements the reference count of the object.
 *
 * Results:
 *	None.
 *	The storage for objPtr may be freed.
 *
 *----------------------------------------------------------------------
 */

#undef Tcl_DecrRefCount
void
Tcl_DecrRefCount(
    Tcl_Obj *objPtr)	/* The object we are releasing a reference to. */
{
    if (objPtr->refCount-- <= 1) {
	TclFreeObj(objPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclUndoRefCount --
 *
 *	Decrement the refCount of objPtr without causing it to be freed if it
 *	drops from 1 to 0.  This allows a function increment a refCount but
 *	then decrement it and still be able to pass return it to a caller,
 *	possibly with a refCount of 0.  The caller must have previously
 *	incremented the refCount.
 *
 *----------------------------------------------------------------------
 */
void
TclUndoRefCount(
    Tcl_Obj *objPtr)	/* The object we are releasing a reference to. */
{
    if (objPtr->refCount > 0) {
	--objPtr->refCount;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_IsShared --
 *
 *	Tests if the object has a ref count greater than one.
 *
 * Results:
 *	Boolean value that is the result of the test.
 *
 *----------------------------------------------------------------------
 */

#undef Tcl_IsShared
int
Tcl_IsShared(
    Tcl_Obj *objPtr)	/* The object to test for being shared. */
{
    return ((objPtr)->refCount + 1 > 2);
    return ((objPtr)->refCount > 1);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DbIncrRefCount --
 *
3493
3494
3495
3496
3497
3498
3499
3500

3501
3502
3503
3504
3505
3506
3507
3941
3942
3943
3944
3945
3946
3947

3948
3949
3950
3951
3952
3953
3954
3955







-
+







    Tcl_Obj *objPtr,	/* The object we are registering a reference
				 * to. */
    const char *file,		/* The name of the source file calling this
				 * function; used for debugging. */
    int line)			/* Line number in the source file; used for
				 * debugging. */
{
    if (objPtr->refCount == 0x61616161) {
    if (objPtr->refCount == FREEDREFCOUNTFILLER) {
	fprintf(stderr, "file = %s, line = %d\n", file, line);
	fflush(stderr);
	Tcl_Panic("incrementing refCount of previously disposed object");
    }

#if TCL_THREADS
    /*
3517
3518
3519
3520
3521
3522
3523
3524

3525
3526
3527
3528
3529
3530
3531
3965
3966
3967
3968
3969
3970
3971

3972
3973
3974
3975
3976
3977
3978
3979







-
+








	if (!tablePtr) {
	    Tcl_Panic("object table not initialized");
	}
	hPtr = Tcl_FindHashEntry(tablePtr, objPtr);
	if (!hPtr) {
	    Tcl_Panic("Trying to %s of Tcl_Obj allocated in another thread",
                    "incr ref count");
		    "incr ref count");
	}
    }
# endif /* TCL_THREADS */
    ++(objPtr)->refCount;
}
#else /* !TCL_MEM_DEBUG */
void
3566
3567
3568
3569
3570
3571
3572
3573

3574
3575
3576
3577
3578
3579
3580
4014
4015
4016
4017
4018
4019
4020

4021
4022
4023
4024
4025
4026
4027
4028







-
+







    Tcl_Obj *objPtr,	/* The object we are releasing a reference
				 * to. */
    const char *file,		/* The name of the source file calling this
				 * function; used for debugging. */
    int line)			/* Line number in the source file; used for
				 * debugging. */
{
    if (objPtr->refCount == 0x61616161) {
    if (objPtr->refCount == FREEDREFCOUNTFILLER) {
	fprintf(stderr, "file = %s, line = %d\n", file, line);
	fflush(stderr);
	Tcl_Panic("decrementing refCount of previously disposed object");
    }

#if TCL_THREADS
    /*
3590
3591
3592
3593
3594
3595
3596
3597

3598
3599
3600
3601
3602
3603
3604
4038
4039
4040
4041
4042
4043
4044

4045
4046
4047
4048
4049
4050
4051
4052







-
+








	if (!tablePtr) {
	    Tcl_Panic("object table not initialized");
	}
	hPtr = Tcl_FindHashEntry(tablePtr, objPtr);
	if (!hPtr) {
	    Tcl_Panic("Trying to %s of Tcl_Obj allocated in another thread",
                    "decr ref count");
		    "decr ref count");
	}
    }
# endif /* TCL_THREADS */

    if (objPtr->refCount-- <= 1) {
	TclFreeObj(objPtr);
    }
3648
3649
3650
3651
3652
3653
3654
3655

3656
3657
3658
3659
3660
3661
3662
4096
4097
4098
4099
4100
4101
4102

4103
4104
4105
4106
4107
4108
4109
4110







-
+







				 * debugging. */
#else
    TCL_UNUSED(const char *) /*file*/,
    TCL_UNUSED(int) /*line*/)
#endif
{
#ifdef TCL_MEM_DEBUG
    if (objPtr->refCount == 0x61616161) {
    if (objPtr->refCount == FREEDREFCOUNTFILLER) {
	fprintf(stderr, "file = %s, line = %d\n", file, line);
	fflush(stderr);
	Tcl_Panic("checking whether previously disposed object is shared");
    }

#if TCL_THREADS
    /*
3672
3673
3674
3675
3676
3677
3678
3679

3680
3681
3682
3683
3684
3685
3686
4120
4121
4122
4123
4124
4125
4126

4127
4128
4129
4130
4131
4132
4133
4134







-
+








	if (!tablePtr) {
	    Tcl_Panic("object table not initialized");
	}
	hPtr = Tcl_FindHashEntry(tablePtr, objPtr);
	if (!hPtr) {
	    Tcl_Panic("Trying to %s of Tcl_Obj allocated in another thread",
                    "check shared status");
		    "check shared status");
	}
    }
# endif /* TCL_THREADS */
#endif /* TCL_MEM_DEBUG */

#ifdef TCL_COMPILE_STATS
    Tcl_MutexLock(&tclObjMutex);
3783
3784
3785
3786
3787
3788
3789
3790



3791
3792
3793
3794
3795
3796
3797
4231
4232
4233
4234
4235
4236
4237

4238
4239
4240
4241
4242
4243
4244
4245
4246
4247







-
+
+
+







    const char *p1, *p2;
    size_t l1, l2;

    /*
     * If the object pointers are the same then they match.
     * OPT: this comparison was moved to the caller

       if (objPtr1 == objPtr2) return 1;
       if (objPtr1 == objPtr2) {
	   return 1;
       }
    */

    /*
     * Don't use Tcl_GetStringFromObj as it would prevent l1 and l2 being
     * in a register.
     */

3858
3859
3860
3861
3862
3863
3864
3865

3866
3867
3868
3869
3870

3871

3872
3873

3874
3875
3876
3877
3878
3879
3880
4308
4309
4310
4311
4312
4313
4314

4315
4316
4317
4318
4319
4320
4321

4322


4323
4324
4325
4326
4327
4328
4329
4330







-
+





+
-
+
-
-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

TCL_HASH_TYPE
size_t
TclHashObjKey(
    TCL_UNUSED(Tcl_HashTable *),
    void *keyPtr)		/* Key from which to compute hash value. */
{
    Tcl_Obj *objPtr = (Tcl_Obj *)keyPtr;
    Tcl_Size length;
    const char *string = TclGetString(objPtr);
    const char *string = Tcl_GetStringFromObj(objPtr, &length);
    size_t length = objPtr->length;
    TCL_HASH_TYPE result = 0;
    size_t result = 0;

    /*
     * I tried a zillion different hash functions and asked many other people
     * for advice. Many people had their own favorite functions, all
     * different, but no-one had much idea why they were good ones. I chose
     * the one below (multiply by 9 and add new character) because of the
     * following reasons:
3902
3903
3904
3905
3906
3907
3908
3909

3910
3911
3912
3913
3914
3915
3916
4352
4353
4354
4355
4356
4357
4358

4359
4360
4361
4362
4363
4364
4365
4366







-
+







     *
     * See also HashStringKey in tclHash.c.
     * See also HashString in tclLiteral.c.
     *
     * See [tcl-Feature Request #2958832]
     */

    if (length) {
    if (length > 0) {
	result = UCHAR(*string);
	while (--length) {
	    result += (result << 3) + UCHAR(*++string);
	}
    }
    return result;
}
3962
3963
3964
3965
3966
3967
3968
3969
3970


3971
3972
3973
3974
3975
3976





3977
3978
3979
3980
3981
3982
3983
3984







3985
3986
3987
3988
3989
3990
3991
3992
3993
3994

3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012

4013
4014
4015
4016
4017
4018
4019
4412
4413
4414
4415
4416
4417
4418


4419
4420
4421





4422
4423
4424
4425
4426
4427







4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443

4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461

4462
4463
4464
4465
4466
4467
4468
4469







-
-
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+









-
+

















-
+







     * is not deleted.
     *
     * If any check fails, then force another conversion to the command type,
     * to discard the old rep and create a new one.
     */

    resPtr = (ResolvedCmdName *)objPtr->internalRep.twoPtrValue.ptr1;
    if (objPtr->typePtr == &tclCmdNameType) {
        Command *cmdPtr = resPtr->cmdPtr;
    if (TclHasInternalRep(objPtr, &tclCmdNameType)) {
	Command *cmdPtr = resPtr->cmdPtr;

        if ((cmdPtr->cmdEpoch == resPtr->cmdEpoch)
                && (interp == cmdPtr->nsPtr->interp)
                && !(cmdPtr->nsPtr->flags & NS_DYING)) {
            Namespace *refNsPtr = (Namespace *)
                    TclGetCurrentNamespace(interp);
	if ((cmdPtr->cmdEpoch == resPtr->cmdEpoch)
		&& (interp == cmdPtr->nsPtr->interp)
		&& !(cmdPtr->nsPtr->flags & NS_DYING)) {
	    Namespace *refNsPtr = (Namespace *)
		    TclGetCurrentNamespace(interp);

            if ((resPtr->refNsPtr == NULL)
                || ((refNsPtr == resPtr->refNsPtr)
                    && (resPtr->refNsId == refNsPtr->nsId)
                    && (resPtr->refNsCmdEpoch == refNsPtr->cmdRefEpoch))) {
                return (Tcl_Command) cmdPtr;
            }
        }
	    if ((resPtr->refNsPtr == NULL)
		    || ((refNsPtr == resPtr->refNsPtr)
		    && (resPtr->refNsId == refNsPtr->nsId)
		    && (resPtr->refNsCmdEpoch == refNsPtr->cmdRefEpoch))) {
		return (Tcl_Command) cmdPtr;
	    }
	}
    }

    /*
     * OK, must create a new internal representation (or fail) as any cache we
     * had is invalid one way or another.
     */

    /* See [07d13d99b0a9] why we cannot call SetCmdNameFromAny() directly here. */
    if (tclCmdNameType.setFromAnyProc(interp, objPtr) != TCL_OK) {
        return NULL;
	return NULL;
    }
    resPtr = (ResolvedCmdName *)objPtr->internalRep.twoPtrValue.ptr1;
    return (Tcl_Command) (resPtr ? resPtr->cmdPtr : NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * TclSetCmdNameObj --
 *
 *	Modify an object to be an CmdName object that refers to the argument
 *	Command structure.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The object's old internal rep is freed. It's string rep is not
 *	The object's old internal rep is freed. Its string rep is not
 *	changed. The refcount in the Command structure is incremented to keep
 *	it from being freed if the command is later deleted until
 *	TclNRExecuteByteCode has a chance to recognize that it was deleted.
 *
 *----------------------------------------------------------------------
 */

4058
4059
4060
4061
4062
4063
4064
4065

4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084

4085
4086
4087
4088
4089
4090
4091
4508
4509
4510
4511
4512
4513
4514

4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533

4534
4535
4536
4537
4538
4539
4540
4541







-
+


















-
+








	fillPtr->refNsPtr = currNsPtr;
	fillPtr->refNsId = currNsPtr->nsId;
	fillPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
    }

    if (resPtr == NULL) {
	TclFreeIntRep(objPtr);
	TclFreeInternalRep(objPtr);

	objPtr->internalRep.twoPtrValue.ptr1 = fillPtr;
	objPtr->internalRep.twoPtrValue.ptr2 = NULL;
	objPtr->typePtr = &tclCmdNameType;
    }
}

void
TclSetCmdNameObj(
    Tcl_Interp *interp,		/* Points to interpreter containing command
				 * that should be cached in objPtr. */
    Tcl_Obj *objPtr,	/* Points to Tcl object to be changed to a
				 * CmdName object. */
    Command *cmdPtr)		/* Points to Command structure that the
				 * CmdName object should refer to. */
{
    ResolvedCmdName *resPtr;

    if (objPtr->typePtr == &tclCmdNameType) {
    if (TclHasInternalRep(objPtr, &tclCmdNameType)) {
	resPtr = (ResolvedCmdName *)objPtr->internalRep.twoPtrValue.ptr1;
	if (resPtr != NULL && resPtr->cmdPtr == cmdPtr) {
	    return;
	}
    }

    SetCmdNameObj(interp, objPtr, cmdPtr, NULL);
4224
4225
4226
4227
4228
4229
4230
4231

4232
4233
4234
4235
4236
4237
4238
4674
4675
4676
4677
4678
4679
4680

4681
4682
4683
4684
4685
4686
4687
4688







-
+







     */

    if (cmdPtr == NULL || !TclRoutineHasName(cmdPtr)) {
	return TCL_ERROR;
    }

    resPtr = (ResolvedCmdName *)objPtr->internalRep.twoPtrValue.ptr1;
    if ((objPtr->typePtr == &tclCmdNameType) && (resPtr->refCount == 1)) {
    if (TclHasInternalRep(objPtr, &tclCmdNameType) && (resPtr->refCount == 1)) {
	/*
	 * Re-use existing ResolvedCmdName struct when possible.
	 * Cleanup the old fields that need it.
	 */

	Command *oldCmdPtr = resPtr->cmdPtr;

4261
4262
4263
4264
4265
4266
4267
4268

4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
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
4711
4712
4713
4714
4715
4716
4717

4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735

4736
4737
4738
4739
4740
4741

4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752

4753
4754

4755
4756
4757
4758
4759
4760
4761
4762







-
+

















-
+





-
+










-
+

-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_RepresentationCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *descObj;

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

    /*
     * Value is a bignum with a refcount of 14, object pointer at 0x12345678,
     * internal representation 0x45671234:0x98765432, string representation
     * "1872361827361287"
     */

    descObj = Tcl_ObjPrintf("value is a %s with a refcount of %" TCL_Z_MODIFIER "u,"
    descObj = Tcl_ObjPrintf("value is a %s with a refcount of %" TCL_SIZE_MODIFIER "d,"
	    " object pointer at %p",
	    objv[1]->typePtr ? objv[1]->typePtr->name : "pure string",
	    objv[1]->refCount, objv[1]);

    if (objv[1]->typePtr) {
	if (objv[1]->typePtr == &tclDoubleType) {
	if (TclHasInternalRep(objv[1], &tclDoubleType)) {
	    Tcl_AppendPrintfToObj(descObj, ", internal representation %g",
		    objv[1]->internalRep.doubleValue);
	} else {
	    Tcl_AppendPrintfToObj(descObj, ", internal representation %p:%p",
		    (void *) objv[1]->internalRep.twoPtrValue.ptr1,
		    (void *) objv[1]->internalRep.twoPtrValue.ptr2);
	}
    }

    if (objv[1]->bytes) {
        Tcl_AppendToObj(descObj, ", string representation \"", -1);
	Tcl_AppendToObj(descObj, ", string representation \"", -1);
	Tcl_AppendLimitedToObj(descObj, objv[1]->bytes, objv[1]->length,
                16, "...");
		16, "...");
	Tcl_AppendToObj(descObj, "\"", -1);
    } else {
	Tcl_AppendToObj(descObj, ", no string representation", -1);
    }

    Tcl_SetObjResult(interp, descObj);
    return TCL_OK;

Changes to generic/tclOptimize.c.

1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * tclOptimize.c --
 *
 *	This file contains the bytecode optimizer.
 *
 * Copyright (c) 2013 by Donal Fellows.
 * Copyright © 2013 Donal Fellows.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclCompile.h"
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38







-
+







static void		TrimUnreachable(CompileEnv *envPtr);

/*
 * Helper macros.
 */

#define DefineTargetAddress(tablePtr, address) \
    ((void) Tcl_CreateHashEntry((tablePtr), (void *) (address), &isNew))
    ((void) Tcl_CreateHashEntry((tablePtr), (address), &isNew))
#define IsTargetAddress(tablePtr, address) \
    (Tcl_FindHashEntry((tablePtr), (void *) (address)) != NULL)
#define AddrLength(address) \
    (tclInstructionTable[*(unsigned char *)(address)].numBytes)
#define InstLength(instruction) \
    (tclInstructionTable[UCHAR(instruction)].numBytes)

50
51
52
53
54
55
56
57


58
59
60
61
62
63
64
50
51
52
53
54
55
56

57
58
59
60
61
62
63
64
65







-
+
+








static void
LocateTargetAddresses(
    CompileEnv *envPtr,
    Tcl_HashTable *tablePtr)
{
    unsigned char *currentInstPtr, *targetInstPtr;
    int isNew, i;
    int isNew;
    Tcl_Size i;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch hSearch;

    Tcl_InitHashTable(tablePtr, TCL_ONE_WORD_KEYS);

    /*
     * The starts of commands represent target addresses.
129
130
131
132
133
134
135
136

137
138
139
140
141
142
143
130
131
132
133
134
135
136

137
138
139
140
141
142
143
144







-
+








	if (rangePtr->type == CATCH_EXCEPTION_RANGE) {
	    targetInstPtr = envPtr->codeStart + rangePtr->catchOffset;
	    DefineTargetAddress(tablePtr, targetInstPtr);
	} else {
	    targetInstPtr = envPtr->codeStart + rangePtr->breakOffset;
	    DefineTargetAddress(tablePtr, targetInstPtr);
	    if (rangePtr->continueOffset >= 0) {
	    if (rangePtr->continueOffset != TCL_INDEX_NONE) {
		targetInstPtr = envPtr->codeStart + rangePtr->continueOffset;
		DefineTargetAddress(tablePtr, targetInstPtr);
	    }
	}
    }
}

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
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







-
+








-
+








-
+














-
+












-
+



-
+



-
+



-
+







    LocateTargetAddresses(envPtr, &targets);
    for (currentInstPtr = envPtr->codeStart ;
	    currentInstPtr < envPtr->codeNext ; currentInstPtr += size) {
	int blank = 0, i, nextInst;

	size = AddrLength(currentInstPtr);
	while ((currentInstPtr + size < envPtr->codeNext)
		&& *(currentInstPtr+size) == INST_NOP) {
		&& currentInstPtr[size] == INST_NOP) {
	    if (IsTargetAddress(&targets, currentInstPtr + size)) {
		break;
	    }
	    size += InstLength(INST_NOP);
	}
	if (IsTargetAddress(&targets, currentInstPtr + size)) {
	    continue;
	}
	nextInst = *(currentInstPtr + size);
	nextInst = currentInstPtr[size];
	switch (*currentInstPtr) {
	case INST_PUSH1:
	    if (nextInst == INST_POP) {
		blank = size + InstLength(nextInst);
	    } else if (nextInst == INST_STR_CONCAT1
		    && TclGetUInt1AtPtr(currentInstPtr + size + 1) == 2) {
		Tcl_Obj *litPtr = TclFetchLiteral(envPtr,
			TclGetUInt1AtPtr(currentInstPtr + 1));
		size_t numBytes;
		Tcl_Size numBytes;

		(void) TclGetStringFromObj(litPtr, &numBytes);
		if (numBytes == 0) {
		    blank = size + InstLength(nextInst);
		}
	    }
	    break;
	case INST_PUSH4:
	    if (nextInst == INST_POP) {
		blank = size + 1;
	    } else if (nextInst == INST_STR_CONCAT1
		    && TclGetUInt1AtPtr(currentInstPtr + size + 1) == 2) {
		Tcl_Obj *litPtr = TclFetchLiteral(envPtr,
			TclGetUInt4AtPtr(currentInstPtr + 1));
		size_t numBytes;
		Tcl_Size numBytes;

		(void) TclGetStringFromObj(litPtr, &numBytes);
		if (numBytes == 0) {
		    blank = size + InstLength(nextInst);
		}
	    }
	    break;

	case INST_LNOT:
	    switch (nextInst) {
	    case INST_JUMP_TRUE1:
		blank = size;
		*(currentInstPtr + size) = INST_JUMP_FALSE1;
		currentInstPtr[size] = INST_JUMP_FALSE1;
		break;
	    case INST_JUMP_FALSE1:
		blank = size;
		*(currentInstPtr + size) = INST_JUMP_TRUE1;
		currentInstPtr[size] = INST_JUMP_TRUE1;
		break;
	    case INST_JUMP_TRUE4:
		blank = size;
		*(currentInstPtr + size) = INST_JUMP_FALSE4;
		currentInstPtr[size] = INST_JUMP_FALSE4;
		break;
	    case INST_JUMP_FALSE4:
		blank = size;
		*(currentInstPtr + size) = INST_JUMP_TRUE4;
		currentInstPtr[size] = INST_JUMP_TRUE4;
		break;
	    }
	    break;

	case INST_TRY_CVT_TO_NUMERIC:
	    switch (nextInst) {
	    case INST_JUMP_TRUE1:
313
314
315
316
317
318
319
320

321
322
323
324
325
326
327
314
315
316
317
318
319
320

321
322
323
324
325
326
327
328







-
+







		break;
	    }
	    break;
	}

	if (blank > 0) {
	    for (i=0 ; i<blank ; i++) {
		*(currentInstPtr + i) = INST_NOP;
		currentInstPtr[i] = INST_NOP;
	    }
	    size = blank;
	}
    }
    Tcl_DeleteHashTable(&targets);
}

361
362
363
364
365
366
367
368

369
370
371
372
373
374
375
362
363
364
365
366
367
368

369
370
371
372
373
374
375
376







-
+







		}
		Tcl_CreateHashEntry(&jumps, INT2PTR(offset), &isNew);
		if (!isNew) {
		    offset = TclGetInt1AtPtr(currentInstPtr + 1);
		    break;
		}
		offset += delta;
		switch (*(currentInstPtr + offset)) {
		switch (currentInstPtr[offset]) {
		case INST_NOP:
		    delta = InstLength(INST_NOP);
		    continue;
		case INST_JUMP1:
		    delta = TclGetInt1AtPtr(currentInstPtr + offset + 1);
		    continue;
		case INST_JUMP4:
389
390
391
392
393
394
395
396

397
398
399
400
401
402
403
390
391
392
393
394
395
396

397
398
399
400
401
402
403
404







-
+







	    Tcl_CreateHashEntry(&jumps, INT2PTR(0), &isNew);
	    for (offset = TclGetInt4AtPtr(currentInstPtr + 1); offset!=0 ;) {
		Tcl_CreateHashEntry(&jumps, INT2PTR(offset), &isNew);
		if (!isNew) {
		    offset = TclGetInt4AtPtr(currentInstPtr + 1);
		    break;
		}
		switch (*(currentInstPtr + offset)) {
		switch (currentInstPtr[offset]) {
		case INST_NOP:
		    offset += InstLength(INST_NOP);
		    continue;
		case INST_JUMP1:
		    offset += TclGetInt1AtPtr(currentInstPtr + offset + 1);
		    continue;
		case INST_JUMP4:

Changes to generic/tclPanic.c.

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
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
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
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







-
-
-
+
+
+















-
+

















-
+

-
+


-
+



















-
+




-
+








-







/*
 * tclPanic.c --
 *
 *	Source code for the "Tcl_Panic" library procedure for Tcl; individual
 *	applications will probably call Tcl_SetPanicProc() to set an
 *	application-specific panic procedure.
 *
 * Copyright (c) 1988-1993 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright © 1988-1993 The Regents of the University of California.
 * Copyright © 1994 Sun Microsystems, Inc.
 * Copyright © 1998-1999 Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#if defined(_WIN32) || defined(__CYGWIN__)
    MODULE_SCOPE void tclWinDebugPanic(const char *format, ...);
#endif

/*
 * The panicProc variable contains a pointer to an application specific panic
 * procedure.
 */

static TCL_NORETURN1 Tcl_PanicProc *panicProc = NULL;
static Tcl_PanicProc *panicProc = NULL;

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetPanicProc --
 *
 *	Replace the default panic behavior with the specified function.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Sets the panicProc variable.
 *
 *----------------------------------------------------------------------
 */

void
const char *
Tcl_SetPanicProc(
    TCL_NORETURN1 Tcl_PanicProc *proc)
    Tcl_PanicProc *proc)
{
    panicProc = proc;
    Tcl_InitSubsystems();
    return Tcl_InitSubsystems();
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Panic --
 *
 *	Print an error message and kill the process.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The process dies, entering the debugger if possible.
 *
 *----------------------------------------------------------------------
 */

/*
 * The following comment is here so that Coverity's static analizer knows that
 * The following comment is here so that Coverity's static analyzer knows that
 * a Tcl_Panic() call can never return and avoids lots of false positives.
 */

/* coverity[+kill] */
void
TCL_NORETURN void
Tcl_Panic(
    const char *format,
    ...)
{
    va_list argList;
    char *arg1, *arg2, *arg3;	/* Additional arguments (variable in number)
				 * to pass to fprintf. */
    char *arg4, *arg5, *arg6, *arg7, *arg8;


    va_start(argList, format);
    arg1 = va_arg(argList, char *);
    arg2 = va_arg(argList, char *);
    arg3 = va_arg(argList, char *);
    arg4 = va_arg(argList, char *);
    arg5 = va_arg(argList, char *);
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
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







+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
+

-
+

-









    tclWinDebugPanic(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
#else
	fprintf(stderr, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
		arg8);
	fprintf(stderr, "\n");
	fflush(stderr);
#endif
    }
#   if defined(__GNUC__)
	__builtin_trap();
#   elif defined(_WIN64)
	__debugbreak();
#   elif defined(_MSC_VER) && defined (_M_IX86)
	_asm {int 3}
#   elif defined(_WIN32)
	DebugBreak();
#   endif
#if defined(__GNUC__)
    __builtin_trap();
#elif defined(_WIN64)
    __debugbreak();
#elif defined(_MSC_VER) && defined (_M_IX86)
    _asm {int 3}
#elif defined(_WIN32)
    DebugBreak();
#endif
#if defined(_WIN32)
	ExitProcess(1);
    ExitProcess(1);
#else
	abort();
    abort();
#endif
    }
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclParse.c.

1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16







-
-
+
+







/*
 * tclParse.c --
 *
 *	This file contains functions that parse Tcl scripts. They do so in a
 *	general-purpose fashion that can be used for many different purposes,
 *	including compilation, direct execution, code analysis, etc.
 *
 * Copyright (c) 1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 Ajuba Solutions.
 * Copyright © 1997 Sun Microsystems, Inc.
 * Copyright © 1998-2000 Ajuba Solutions.
 * Contributions from Don Porter, NIST, 2002. (not subject to US copyright)
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
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
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







+





-
+















-
+







 * TYPE_SPACE -		The character is a whitespace character other than
 *			newline.
 * TYPE_COMMAND_END -	Character is newline or semicolon.
 * TYPE_SUBS -		Character begins a substitution or has other special
 *			meaning in ParseTokens: backslash, dollar sign, or
 *			open bracket.
 * TYPE_QUOTE -		Character is a double quote.
 * TYPE_OPEN_PAREN -	Character is a left parenthesis.
 * TYPE_CLOSE_PAREN -	Character is a right parenthesis.
 * TYPE_CLOSE_BRACK -	Character is a right square bracket.
 * TYPE_BRACE -		Character is a curly brace (either left or right).
 */

const char tclCharTypeTable[] = {
const unsigned char tclCharTypeTable[] = {

    /*
     * Positive character values, from 0-127:
     */

    TYPE_SUBS,        TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
    TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
    TYPE_NORMAL,      TYPE_SPACE,       TYPE_COMMAND_END, TYPE_SPACE,
    TYPE_SPACE,       TYPE_SPACE,       TYPE_NORMAL,      TYPE_NORMAL,
    TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
    TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
    TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
    TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
    TYPE_SPACE,       TYPE_NORMAL,      TYPE_QUOTE,       TYPE_NORMAL,
    TYPE_SUBS,        TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
    TYPE_NORMAL,      TYPE_CLOSE_PAREN, TYPE_NORMAL,      TYPE_NORMAL,
    TYPE_OPEN_PAREN,  TYPE_CLOSE_PAREN, TYPE_NORMAL,      TYPE_NORMAL,
    TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
    TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
    TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
    TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_COMMAND_END,
    TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
    TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
    TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
115
116
117
118
119
120
121
122
123


124
125

126
127

128
129

130
131

132
133
134
135
136
137
138
116
117
118
119
120
121
122


123
124
125

126
127

128
129

130
131

132
133
134
135
136
137
138
139







-
-
+
+

-
+

-
+

-
+

-
+







    TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
};

/*
 * Prototypes for local functions defined in this file:
 */

static int	CommandComplete(const char *script, size_t numBytes);
static size_t		ParseComment(const char *src, size_t numBytes,
static int		CommandComplete(const char *script, Tcl_Size numBytes);
static Tcl_Size		ParseComment(const char *src, Tcl_Size numBytes,
			    Tcl_Parse *parsePtr);
static int		ParseTokens(const char *src, size_t numBytes, int mask,
static int		ParseTokens(const char *src, Tcl_Size numBytes, int mask,
			    int flags, Tcl_Parse *parsePtr);
static size_t		ParseWhiteSpace(const char *src, size_t numBytes,
static Tcl_Size		ParseWhiteSpace(const char *src, Tcl_Size numBytes,
			    int *incompletePtr, char *typePtr);
static size_t		ParseAllWhiteSpace(const char *src, size_t numBytes,
static Tcl_Size		ParseAllWhiteSpace(const char *src, Tcl_Size numBytes,
			    int *incompletePtr);
static int		ParseHex(const char *src, size_t numBytes,
static int		ParseHex(const char *src, Tcl_Size numBytes,
			    int *resultPtr);

/*
 *----------------------------------------------------------------------
 *
 * TclParseInit --
 *
147
148
149
150
151
152
153
154

155
156
157
158
159
160
161
148
149
150
151
152
153
154

155
156
157
158
159
160
161
162







-
+







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

void
TclParseInit(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting */
    const char *start,		/* Start of string to be parsed. */
    size_t numBytes,		/* Total number of bytes in string. If -1,
    Tcl_Size numBytes,		/* Total number of bytes in string. If -1,
				 * the script consists of all bytes up to the
				 * first null character. */
    Tcl_Parse *parsePtr)	/* Points to struct to initialize */
{
    parsePtr->numWords = 0;
    parsePtr->tokenPtr = parsePtr->staticTokens;
    parsePtr->numTokens = 0;
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
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







-
+















-
+




-
+

-
+








int
Tcl_ParseCommand(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting; if
				 * NULL, then no error message is provided. */
    const char *start,		/* First character of string containing one or
				 * more Tcl commands. */
    size_t numBytes,		/* Total number of bytes in string. If -1,
    Tcl_Size numBytes,		/* Total number of bytes in string. If -1,
				 * the script consists of all bytes up to the
				 * first null character. */
    int nested,			/* Non-zero means this is a nested command:
				 * close bracket should be considered a
				 * command terminator. If zero, then close
				 * bracket has no special meaning. */
    Tcl_Parse *parsePtr)
				/* Structure to fill in with information about
				 * the parsed command; any previous
				 * information in the structure is ignored. */
{
    const char *src;		/* Points to current character in the
				 * command. */
    char type;			/* Result returned by CHAR_TYPE(*src). */
    Tcl_Token *tokenPtr;	/* Pointer to token being filled in. */
    int wordIndex;		/* Index of word token for current word. */
    Tcl_Size wordIndex;		/* Index of word token for current word. */
    int terminators;		/* CHAR_TYPE bits that indicate the end of a
				 * command. */
    const char *termPtr;	/* Set by Tcl_ParseBraces/QuotedString to
				 * point to char after terminating one. */
    size_t scanned;
    Tcl_Size scanned;

    if (numBytes == TCL_INDEX_NONE && start) {
    if (numBytes < 0 && start) {
	numBytes = strlen(start);
    }
    TclParseInit(interp, start, numBytes, parsePtr);
    if ((start == NULL) && (numBytes != 0)) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "can't parse a NULL pointer", -1));
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
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







-
+

















-
+







	    if (Tcl_ParseQuotedString(interp, src, numBytes, parsePtr, 1,
		    &termPtr) != TCL_OK) {
		goto error;
	    }
	    src = termPtr;
	    numBytes = parsePtr->end - src;
	} else if (*src == '{') {
	    int expIdx = wordIndex + 1;
	    Tcl_Size expIdx = wordIndex + 1;
	    Tcl_Token *expPtr;

	    if (Tcl_ParseBraces(interp, src, numBytes, parsePtr, 1,
		    &termPtr) != TCL_OK) {
		goto error;
	    }
	    src = termPtr;
	    numBytes = parsePtr->end - src;

	    /*
	     * Check whether the braces contained the word expansion prefix
	     * {*}
	     */

	    expPtr = &parsePtr->tokenPtr[expIdx];
	    if ((0 == expandWord)
		    /* Haven't seen prefix already */
		    && (1 == parsePtr->numTokens - expIdx)
		    && (expIdx + 1 == parsePtr->numTokens)
		    /* Only one token */
		    && (((1 == expPtr->size)
			    /* Same length as prefix */
			    && (expPtr->start[0] == '*')))
			    /* Is the prefix */
		    && (numBytes > 0) && (0 == ParseWhiteSpace(termPtr,
			    numBytes, &parsePtr->incomplete, &type))
377
378
379
380
381
382
383
384

385
386
387
388
389
390
391
378
379
380
381
382
383
384

385
386
387
388
389
390
391
392







-
+







	 * case of a word consisting of a single range of literal text.
	 */

	tokenPtr = &parsePtr->tokenPtr[wordIndex];
	tokenPtr->size = src - tokenPtr->start;
	tokenPtr->numComponents = parsePtr->numTokens - (wordIndex + 1);
	if (expandWord) {
	    size_t i;
	    Tcl_Size i;
	    int isLiteral = 1;

	    /*
	     * When a command includes a word that is an expanded literal; for
	     * example, {*}{1 2 3}, the parser performs that expansion
	     * immediately, generating several TCL_TOKEN_SIMPLE_WORDs instead
	     * of a single TCL_TOKEN_EXPAND_WORD that the Tcl_ParseCommand()
402
403
404
405
406
407
408

409

410
411
412
413
414
415
416
403
404
405
406
407
408
409
410

411
412
413
414
415
416
417
418







+
-
+







		if (tokenPtr[i].type != TCL_TOKEN_TEXT) {
		    isLiteral = 0;
		    break;
		}
	    }

	    if (isLiteral) {
		Tcl_Size elemCount = 0;
		int elemCount = 0, code = TCL_OK, literal = 1;
		int code = TCL_OK, literal = 1;
		const char *nextElem, *listEnd, *elemStart;

		/*
		 * The word to be expanded is a literal, so determine the
		 * boundaries of the literal string to be treated as a list
		 * and expanded. That literal string starts at
		 * tokenPtr[1].start, and includes all bytes up to, but not
424
425
426
427
428
429
430
431

432
433
434
435
436
437
438
426
427
428
429
430
431
432

433
434
435
436
437
438
439
440







-
+








		/*
		 * Step through the literal string, parsing and counting list
		 * elements.
		 */

		while (nextElem < listEnd) {
		    size_t size;
		    Tcl_Size size;

		    code = TclFindElement(NULL, nextElem, listEnd - nextElem,
			    &elemStart, &nextElem, &size, &literal);
		    if ((code != TCL_OK) || !literal) {
			break;
		    }
		    if (elemStart < listEnd) {
466
467
468
469
470
471
472
473

474
475
476
477
478
479
480
468
469
470
471
472
473
474

475
476
477
478
479
480
481
482







-
+







		} else {
		    /*
		     * Recalculate the number of Tcl_Tokens needed to store
		     * tokens representing the expanded list.
		     */

		    const char *listStart;
		    int growthNeeded = wordIndex + 2*elemCount
		    Tcl_Size growthNeeded = wordIndex + 2*elemCount
			    - parsePtr->numTokens;

		    parsePtr->numWords += elemCount - 1;
		    if (growthNeeded > 0) {
			TclGrowParseTokenArray(parsePtr, growthNeeded);
			tokenPtr = &parsePtr->tokenPtr[wordIndex];
		    }
616
617
618
619
620
621
622
623

624
625
626

627
628
629
630
631
632
633
618
619
620
621
622
623
624

625
626
627

628
629
630
631
632
633
634
635







-
+


-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static size_t
static Tcl_Size
ParseWhiteSpace(
    const char *src,		/* First character to parse. */
    size_t numBytes,		/* Max number of bytes to scan. */
    Tcl_Size numBytes,		/* Max number of bytes to scan. */
    int *incompletePtr,		/* Set this boolean memory to true if parsing
				 * indicates an incomplete command. */
    char *typePtr)		/* Points to location to store character type
				 * of character that ends run of whitespace */
{
    char type = TYPE_NORMAL;
    const char *p = src;
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
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
707







-
+


-
+






-
+







-
+


-
+







 *
 * Results:
 *	Returns the number of bytes recognized as white space.
 *
 *----------------------------------------------------------------------
 */

static size_t
static Tcl_Size
ParseAllWhiteSpace(
    const char *src,		/* First character to parse. */
    size_t numBytes,		/* Max number of byes to scan */
    Tcl_Size numBytes,		/* Max number of byes to scan */
    int *incompletePtr)		/* Set true if parse is incomplete. */
{
    char type;
    const char *p = src;

    do {
	size_t scanned = ParseWhiteSpace(p, numBytes, incompletePtr, &type);
	Tcl_Size scanned = ParseWhiteSpace(p, numBytes, incompletePtr, &type);

	p += scanned;
	numBytes -= scanned;
    } while (numBytes && (*p == '\n') && (p++, --numBytes));
    return (p-src);
}

size_t
Tcl_Size
TclParseAllWhiteSpace(
    const char *src,		/* First character to parse. */
    size_t numBytes)		/* Max number of byes to scan */
    Tcl_Size numBytes)		/* Max number of byes to scan */
{
    int dummy;
    return ParseAllWhiteSpace(src, numBytes, &dummy);
}

/*
 *----------------------------------------------------------------------
722
723
724
725
726
727
728
729

730
731
732
733
734
735
736
724
725
726
727
728
729
730

731
732
733
734
735
736
737
738







-
+







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

int
ParseHex(
    const char *src,		/* First character to parse. */
    size_t numBytes,		/* Max number of byes to scan */
    Tcl_Size numBytes,		/* Max number of byes to scan */
    int *resultPtr)		/* Points to storage provided by caller where
				 * the character resulting from the
				 * conversion is to be written. */
{
    int result = 0;
    const char *p = src;

776
777
778
779
780
781
782
783

784
785
786


787
788
789
790
791
792
793

794
795

796
797
798
799
800
801
802
778
779
780
781
782
783
784

785
786


787
788
789
790
791
792
793
794

795
796

797
798
799
800
801
802
803
804







-
+

-
-
+
+






-
+

-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclParseBackslash(
    const char *src,		/* Points to the backslash character of a a
    const char *src,		/* Points to the backslash character of a
				 * backslash sequence. */
    size_t numBytes,		/* Max number of bytes to scan. */
    size_t *readPtr,		/* NULL, or points to storage where the number
    Tcl_Size numBytes,		/* Max number of bytes to scan. */
    Tcl_Size *readPtr,		/* NULL, or points to storage where the number
				 * of bytes scanned should be written. */
    char *dst)			/* NULL, or points to buffer where the UTF-8
				 * encoding of the backslash sequence is to be
				 * written. At most 4 bytes will be written there. */
{
    const char *p = src+1;
    Tcl_UniChar unichar = 0;
    int unichar;
    int result;
    size_t count;
    Tcl_Size count;
    char buf[4] = "";

    if (numBytes == 0) {
	if (readPtr != NULL) {
	    *readPtr = 0;
	}
	return 0;
865
866
867
868
869
870
871
872
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
898
899
900
867
868
869
870
871
872
873










874
875
876
877
878
879
880
881
882



883
884
885
886
887
888
889







-
-
-
-
-
-
-
-
-
-









-
-
-







    case 'u':
	count += ParseHex(p+1, (numBytes > 5) ? 4 : numBytes-2, &result);
	if (count == 2) {
	    /*
	     * No hexdigits -> This is just "u".
	     */
	    result = 'u';
	} else if (((result & 0xFC00) == 0xD800) && (count == 6)
		    && (p[5] == '\\') && (p[6] == 'u') && (numBytes >= 10)) {
	    /* If high surrogate is immediately followed by a low surrogate
	     * escape, combine them into one character. */
	    int low;
	    int count2 = ParseHex(p+7, 4, &low);
	    if ((count2 == 4) && ((low & 0xFC00) == 0xDC00)) {
		result = ((result & 0x3FF)<<10 | (low & 0x3FF)) + 0x10000;
		count += count2 + 2;
	    }
	}
	break;
    case 'U':
	count += ParseHex(p+1, (numBytes > 9) ? 8 : numBytes-2, &result);
	if (count == 2) {
	    /*
	     * No hexdigits -> This is just "U".
	     */
	    result = 'U';
	} else if ((result | 0x7FF) == 0xDFFF) {
	    /* Upper or lower surrogate, not allowed in this syntax. */
	    result = 0xFFFD;
	}
	break;
    case '\n':
	count--;
	do {
	    p++;
	    count++;
935
936
937
938
939
940
941
942

943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
924
925
926
927
928
929
930

931
932
933
934
935
936
937
938
939
940
941
942
943
944
945




946
947
948
949
950
951
952







-
+














-
-
-
-







	 * special, we shouldn't break up a correct utf-8 character. [Bug
	 * #217987] test subst-3.2
	 */

	if (Tcl_UtfCharComplete(p, numBytes - 1)) {
	    count = TclUtfToUniChar(p, &unichar) + 1;	/* +1 for '\' */
	} else {
	    char utfBytes[4];
	    char utfBytes[8];

	    memcpy(utfBytes, p, numBytes - 1);
	    utfBytes[numBytes - 1] = '\0';
	    count = TclUtfToUniChar(utfBytes, &unichar) + 1;
	}
	result = unichar;
	break;
    }

  done:
    if (readPtr != NULL) {
	*readPtr = count;
    }
    count = Tcl_UniCharToUtf(result, dst);
    if ((result >= 0xD800) && (count < 3)) {
	/* Special case for handling high surrogates. */
	count += Tcl_UniCharToUtf(-1, dst + count);
    }
    return count;
}

/*
 *----------------------------------------------------------------------
 *
 * ParseComment --
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
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







-
+


-
+








-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static size_t
static Tcl_Size
ParseComment(
    const char *src,		/* First character to parse. */
    size_t numBytes,		/* Max number of bytes to scan. */
    Tcl_Size numBytes,		/* Max number of bytes to scan. */
    Tcl_Parse *parsePtr)	/* Information about parse in progress.
				 * Updated if parsing indicates an incomplete
				 * command. */
{
    const char *p = src;
    int incomplete = parsePtr->incomplete;

    while (numBytes) {
	size_t scanned = ParseAllWhiteSpace(p, numBytes, &incomplete);
	Tcl_Size scanned = ParseAllWhiteSpace(p, numBytes, &incomplete);
	p += scanned;
	numBytes -= scanned;

	if ((numBytes == 0) || (*p != '#')) {
	    break;
	}
	if (parsePtr->commentStart == NULL) {
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
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







-
-
+
+













-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
ParseTokens(
    const char *src,	/* First character to parse. */
    size_t numBytes,		/* Max number of bytes to scan. */
    const char *src,		/* First character to parse. */
    Tcl_Size numBytes,		/* Max number of bytes to scan. */
    int mask,			/* Specifies when to stop parsing. The parse
				 * stops at the first unquoted character whose
				 * CHAR_TYPE contains any of the bits in
				 * mask. */
    int flags,			/* OR-ed bits indicating what substitutions to
				 * perform: TCL_SUBST_COMMANDS,
				 * TCL_SUBST_VARIABLES, and
				 * TCL_SUBST_BACKSLASHES */
    Tcl_Parse *parsePtr)	/* Information about parse in progress.
				 * Updated with additional tokens and
				 * termination information. */
{
    char type;
    int originalTokens;
    Tcl_Size originalTokens;
    int noSubstCmds = !(flags & TCL_SUBST_COMMANDS);
    int noSubstVars = !(flags & TCL_SUBST_VARIABLES);
    int noSubstBS = !(flags & TCL_SUBST_BACKSLASHES);
    Tcl_Token *tokenPtr;

    /*
     * Each iteration through the following loop adds one token of type
1099
1100
1101
1102
1103
1104
1105
1106

1107
1108
1109
1110
1111
1112
1113
1084
1085
1086
1087
1088
1089
1090

1091
1092
1093
1094
1095
1096
1097
1098







-
+







		    && !(CHAR_TYPE(*src) & (mask | TYPE_SUBS))) {
		/* empty loop */
	    }
	    tokenPtr->type = TCL_TOKEN_TEXT;
	    tokenPtr->size = src - tokenPtr->start;
	    parsePtr->numTokens++;
	} else if (*src == '$') {
	    int varToken;
	    Tcl_Size varToken;

	    if (noSubstVars) {
		tokenPtr->type = TCL_TOKEN_TEXT;
		tokenPtr->size = 1;
		parsePtr->numTokens++;
		src++;
		numBytes--;
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
1354
1355
1356
1357
1358
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







-
+














-
+








int
Tcl_ParseVarName(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting; if
				 * NULL, then no error message is provided. */
    const char *start,		/* Start of variable substitution string.
				 * First character must be "$". */
    size_t numBytes,		/* Total number of bytes in string. If -1,
    Tcl_Size numBytes,		/* Total number of bytes in string. If -1,
				 * the string consists of all bytes up to the
				 * first null character. */
    Tcl_Parse *parsePtr,	/* Structure to fill in with information about
				 * the variable name. */
    int append)			/* Non-zero means append tokens to existing
				 * information in parsePtr; zero means ignore
				 * existing tokens in parsePtr and
				 * reinitialize it. */
{
    Tcl_Token *tokenPtr;
    const char *src;
    int varIndex;
    unsigned array;

    if (numBytes == TCL_INDEX_NONE && start) {
    if (numBytes < 0 && start) {
	numBytes = strlen(start);
    }
    if (!append) {
	TclParseInit(interp, start, numBytes, parsePtr);
    }
    if ((numBytes == 0) || (start == NULL)) {
	return TCL_ERROR;
1393
1394
1395
1396
1397
1398
1399

1400
1401
1402
1403
1404
1405

1406











1407
1408

1409
1410
1411
1412
1413
1414
1415
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392

1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413







+






+
-
+
+
+
+
+
+
+
+
+
+
+


+







     *	  parentheses is the array element name.
     * 3. The $ sign is followed by something that isn't a letter, digit, or
     *	  underscore: in this case, there is no variable name and the token is
     *	  just "$".
     */

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

	ch = *src;
	while (numBytes && (*src != '}')) {
	while (numBytes && (braceCount>0 || ch != '}')) {
	    switch (ch) {
	    case '{': braceCount++; break;
	    case '}': braceCount--; break;
	    case '\\':
		/* if 2 or more left, consume 2, else consume
		 * just the \ and let it run into the end */
		if (numBytes > 1) {
		   src++; numBytes--;
		}
	    }
	    numBytes--;
	    src++;
	    ch= *src;
	}
	if (numBytes == 0) {
	    if (parsePtr->interp != NULL) {
		Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj(
			"missing close-brace for variable name", -1));
	    }
	    parsePtr->errorType = TCL_PARSE_MISSING_VAR_BRACE;
1457
1458
1459
1460
1461
1462
1463
1464

1465
1466
1467
1468

1469
1470
1471
1472
1473
1474
1475








1476
1477
1478
1479
1480
1481
1482
1455
1456
1457
1458
1459
1460
1461

1462
1463
1464
1465

1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488







-
+



-
+







+
+
+
+
+
+
+
+







	if (array) {
	    /*
	     * This is a reference to an array element. Call ParseTokens
	     * recursively to parse the element name, since it could contain
	     * any number of substitutions.
	     */

	    if (TCL_OK != ParseTokens(src+1, numBytes-1, TYPE_CLOSE_PAREN,
	    if (TCL_OK != ParseTokens(src+1, numBytes-1, TYPE_BAD_ARRAY_INDEX,
		    TCL_SUBST_ALL, parsePtr)) {
		goto error;
	    }
	    if ((parsePtr->term == src+numBytes) || (*parsePtr->term != ')')){
	    if (parsePtr->term == src+numBytes){
		if (parsePtr->interp != NULL) {
		    Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj(
			    "missing )", -1));
		}
		parsePtr->errorType = TCL_PARSE_MISSING_PAREN;
		parsePtr->term = src;
		parsePtr->incomplete = 1;
		goto error;
	    } else if ((*parsePtr->term != ')')){
		if (parsePtr->interp != NULL) {
		    Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj(
			    "invalid character in array index", -1));
		}
		parsePtr->errorType = TCL_PARSE_SYNTAX;
		parsePtr->term = src;
		goto error;
	    }
	    src = parsePtr->term + 1;
	}
    }
    tokenPtr = &parsePtr->tokenPtr[varIndex];
    tokenPtr->size = src - tokenPtr->start;
1521
1522
1523
1524
1525
1526
1527
1528

1529
1530
1531
1532
1533
1534
1535
1536
1537
1538

1539
1540
1541
1542
1543
1544
1545
1527
1528
1529
1530
1531
1532
1533

1534
1535
1536
1537
1538
1539
1540
1541
1542
1543

1544
1545
1546
1547
1548
1549
1550
1551







-
+









-
+







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

const char *
Tcl_ParseVar(
    Tcl_Interp *interp,		/* Context for looking up variable. */
    const char *start,	/* Start of variable substitution. First
    const char *start,		/* Start of variable substitution. First
				 * character must be "$". */
    const char **termPtr)	/* If non-NULL, points to word to fill in with
				 * character just after last one in the
				 * variable specifier. */
{
    Tcl_Obj *objPtr;
    int code;
    Tcl_Parse *parsePtr = (Tcl_Parse *)TclStackAlloc(interp, sizeof(Tcl_Parse));

    if (Tcl_ParseVarName(interp, start, -1, parsePtr, 0) != TCL_OK) {
    if (Tcl_ParseVarName(interp, start, TCL_INDEX_NONE, parsePtr, 0) != TCL_OK) {
	TclStackFree(interp, parsePtr);
	return NULL;
    }

    if (termPtr != NULL) {
	*termPtr = start + parsePtr->tokenPtr->size;
    }
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
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







-
+
















-
+
-

-
+








int
Tcl_ParseBraces(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting; if
				 * NULL, then no error message is provided. */
    const char *start,		/* Start of string enclosed in braces. The
				 * first character must be {'. */
    size_t numBytes,		/* Total number of bytes in string. If -1,
    Tcl_Size numBytes,		/* Total number of bytes in string. If -1,
				 * the string consists of all bytes up to the
				 * first null character. */
    Tcl_Parse *parsePtr,
				/* Structure to fill in with information about
				 * the string. */
    int append,			/* Non-zero means append tokens to existing
				 * information in parsePtr; zero means ignore
				 * existing tokens in parsePtr and
				 * reinitialize it. */
    const char **termPtr)	/* If non-NULL, points to word in which to
				 * store a pointer to the character just after
				 * the terminating '}' if the parse was
				 * successful. */
{
    Tcl_Token *tokenPtr;
    const char *src;
    int startIndex, level;
    Tcl_Size length, startIndex, level;
    size_t length;

    if (numBytes == TCL_INDEX_NONE && start) {
    if (numBytes < 0 && start) {
	numBytes = strlen(start);
    }
    if (!append) {
	TclParseInit(interp, start, numBytes, parsePtr);
    }
    if ((numBytes == 0) || (start == NULL)) {
	return TCL_ERROR;
1808
1809
1810
1811
1812
1813
1814
1815

1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830

1831
1832
1833
1834
1835
1836
1837
1813
1814
1815
1816
1817
1818
1819

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

1835
1836
1837
1838
1839
1840
1841
1842







-
+














-
+








int
Tcl_ParseQuotedString(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting; if
				 * NULL, then no error message is provided. */
    const char *start,		/* Start of the quoted string. The first
				 * character must be '"'. */
    size_t numBytes,		/* Total number of bytes in string. If -1,
    Tcl_Size numBytes,		/* Total number of bytes in string. If -1,
				 * the string consists of all bytes up to the
				 * first null character. */
    Tcl_Parse *parsePtr,
				/* Structure to fill in with information about
				 * the string. */
    int append,			/* Non-zero means append tokens to existing
				 * information in parsePtr; zero means ignore
				 * existing tokens in parsePtr and
				 * reinitialize it. */
    const char **termPtr)	/* If non-NULL, points to word in which to
				 * store a pointer to the character just after
				 * the quoted string's terminating close-quote
				 * if the parse succeeds. */
{
    if (numBytes == TCL_INDEX_NONE && start) {
    if (numBytes < 0 && start) {
	numBytes = strlen(start);
    }
    if (!append) {
	TclParseInit(interp, start, numBytes, parsePtr);
    }
    if ((numBytes == 0) || (start == NULL)) {
	return TCL_ERROR;
1889
1890
1891
1892
1893
1894
1895
1896

1897
1898
1899
1900
1901

1902
1903
1904
1905
1906
1907
1908
1894
1895
1896
1897
1898
1899
1900

1901
1902
1903
1904
1905

1906
1907
1908
1909
1910
1911
1912
1913







-
+




-
+







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

void
TclSubstParse(
    Tcl_Interp *interp,
    const char *bytes,
    size_t numBytes,
    Tcl_Size numBytes,
    int flags,
    Tcl_Parse *parsePtr,
    Tcl_InterpState *statePtr)
{
    size_t length = numBytes;
    Tcl_Size length = numBytes;
    const char *p = bytes;

    TclParseInit(interp, p, length, parsePtr);

    /*
     * First parse the string rep of objPtr, as if it were enclosed as a
     * "-quoted word in a normal Tcl command. Honor flags that selectively
2088
2089
2090
2091
2092
2093
2094
2095

2096
2097
2098
2099
2100
2101


2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123



2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140



2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158

2159
2160
2161
2162
2163
2164
2165
2093
2094
2095
2096
2097
2098
2099

2100
2101
2102
2103
2104


2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126


2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143



2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163

2164
2165
2166
2167
2168
2169
2170
2171







-
+




-
-
+
+




















-
-
+
+
+














-
-
-
+
+
+

















-
+







int
TclSubstTokens(
    Tcl_Interp *interp,		/* Interpreter in which to lookup variables,
				 * execute nested commands, and report
				 * errors. */
    Tcl_Token *tokenPtr,	/* Pointer to first in an array of tokens to
				 * evaluate and concatenate. */
    int count,			/* Number of tokens to consider at tokenPtr.
    Tcl_Size count,		/* Number of tokens to consider at tokenPtr.
				 * Must be at least 1. */
    int *tokensLeftPtr,		/* If not NULL, points to memory where an
				 * integer representing the number of tokens
				 * left to be substituted will be written */
    int line,			/* The line the script starts on. */
    int *clNextOuter,		/* Information about an outer context for */
    Tcl_Size line,		/* The line the script starts on. */
    Tcl_Size *clNextOuter,	/* Information about an outer context for */
    const char *outerScript)	/* continuation line data. This is set by
				 * EvalEx() to properly handle [...]-nested
				 * commands. The 'outerScript' refers to the
				 * most-outer script containing the embedded
				 * command, which is refered to by 'script'.
				 * The 'clNextOuter' refers to the current
				 * entry in the table of continuation lines in
				 * this "main script", and the character
				 * offsets are relative to the 'outerScript'
				 * as well.
				 *
				 * If outerScript == script, then this call is
				 * for words in the outer-most script or
				 * command. See Tcl_EvalEx and TclEvalObjEx
				 * for the places generating arguments for
				 * which this is true. */
{
    Tcl_Obj *result;
    int code = TCL_OK;
#define NUM_STATIC_POS 20
    int isLiteral, maxNumCL, numCL, i, adjust;
    int *clPosition = NULL;
    int isLiteral;
    Tcl_Size i, maxNumCL, numCL, adjust;
    Tcl_Size *clPosition = NULL;
    Interp *iPtr = (Interp *) interp;
    int inFile = iPtr->evalFlags & TCL_EVAL_FILE;

    /*
     * Each pass through this loop will substitute one token, and its
     * components, if any. The only thing tricky here is that we go to some
     * effort to pass Tcl_Obj's through untouched, to avoid string copying and
     * Tcl_Obj creation if possible, to aid performance and limit shimmering.
     *
     * Further optimization opportunities might be to check for the equivalent
     * of Tcl_SetObjResult(interp, Tcl_GetObjResult(interp)) and omit them.
     */

    /*
     * For the handling of continuation lines in literals we first check if
     * this is actually a literal. For if not we can forego the additional
     * processing. Otherwise we pre-allocate a small table to store the
     * For the handling of continuation lines in literals, first check if
     * this is actually a literal. If not then forego the additional
     * processing. Otherwise preallocate a small table to store the
     * locations of all continuation lines we find in this literal, if any.
     * The table is extended if needed.
     */

    numCL = 0;
    maxNumCL = 0;
    isLiteral = 1;
    for (i=0 ; i < count; i++) {
	if ((tokenPtr[i].type != TCL_TOKEN_TEXT)
		&& (tokenPtr[i].type != TCL_TOKEN_BS)) {
	    isLiteral = 0;
	    break;
	}
    }

    if (isLiteral) {
	maxNumCL = NUM_STATIC_POS;
	clPosition = (int *)Tcl_Alloc(maxNumCL * sizeof(int));
	clPosition = (Tcl_Size *)Tcl_Alloc(maxNumCL * sizeof(Tcl_Size));
    }

    adjust = 0;
    result = NULL;
    for (; count>0 && code==TCL_OK ; count--, tokenPtr++) {
	Tcl_Obj *appendObj = NULL;
	const char *append = NULL;
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
2222
2223
2224
2225
2226
2227

2228
2229
2230
2231
2232
2233
2234
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
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232

2233
2234
2235
2236
2237
2238
2239
2240







-
+









-
-
+
+

















-
+







	     * everything, just the number of lines we have to add as
	     * correction.
	     */

	    if ((appendByteLength == 1) && (utfCharBytes[0] == ' ')
		    && (tokenPtr->start[1] == '\n')) {
		if (isLiteral) {
		    size_t clPos;
		    Tcl_Size clPos;

		    if (result == 0) {
			clPos = 0;
		    } else {
			(void)TclGetStringFromObj(result, &clPos);
		    }

		    if (numCL >= maxNumCL) {
			maxNumCL *= 2;
			clPosition = (int *)Tcl_Realloc(clPosition,
				maxNumCL * sizeof(int));
			clPosition = (Tcl_Size *)Tcl_Realloc(clPosition,
				maxNumCL * sizeof(Tcl_Size));
		    }
		    clPosition[numCL] = clPos;
		    numCL++;
		}
		adjust++;
	    }
	    break;

	case TCL_TOKEN_COMMAND: {
	    /* TIP #280: Transfer line information to nested command */
	    iPtr->numLevels++;
	    code = TclInterpReady(interp);
	    if (code == TCL_OK) {
		/*
		 * Test cases: info-30.{6,8,9}
		 */

		int theline;
		Tcl_Size theline;

		TclAdvanceContinuations(&line, &clNextOuter,
			tokenPtr->start - outerScript);
		theline = line + adjust;
		code = TclEvalEx(interp, tokenPtr->start+1, tokenPtr->size-2,
			0, theline, clNextOuter, outerScript);

2397
2398
2399
2400
2401
2402
2403
2404

2405
2406
2407
2408
2409
2410
2411
2403
2404
2405
2406
2407
2408
2409

2410
2411
2412
2413
2414
2415
2416
2417







-
+







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

static int
CommandComplete(
    const char *script,		/* Script to check. */
    size_t numBytes)		/* Number of bytes in script. */
    Tcl_Size numBytes)		/* Number of bytes in script. */
{
    Tcl_Parse parse;
    const char *p, *end;
    int result;

    p = script;
    end = p + numBytes;
2445
2446
2447
2448
2449
2450
2451
2452

2453
2454
2455
2456
2457
2458
2459
2451
2452
2453
2454
2455
2456
2457

2458
2459
2460
2461
2462
2463
2464
2465







-
+







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

int
Tcl_CommandComplete(
    const char *script)		/* Script to check. */
{
    return CommandComplete(script, (int) strlen(script));
    return CommandComplete(script, strlen(script));
}

/*
 *----------------------------------------------------------------------
 *
 * TclObjCommandComplete --
 *
2471
2472
2473
2474
2475
2476
2477
2478

2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2477
2478
2479
2480
2481
2482
2483

2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496







-
+












 */

int
TclObjCommandComplete(
    Tcl_Obj *objPtr)		/* Points to object holding script to
				 * check. */
{
    size_t length;
    Tcl_Size length;
    const char *script = TclGetStringFromObj(objPtr, &length);

    return CommandComplete(script, length);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclParse.h.

1
2

3
4
5

6
7
8
9
10
11
12
13












14
15
16
17

1

2
3
4
5
6








7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

22

-
+



+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+



-
+
/*
 * Minimal set of shared macro definitions and declarations so that multiple
 * Minimal set of shared flag definitions and declarations so that multiple
 * source files can make use of the parsing table in tclParse.c
 */

enum ParseTypeFlags {
#define TYPE_NORMAL		0
#define TYPE_SPACE		0x1
#define TYPE_COMMAND_END	0x2
#define TYPE_SUBS		0x4
#define TYPE_QUOTE		0x8
#define TYPE_CLOSE_PAREN	0x10
#define TYPE_CLOSE_BRACK	0x20
#define TYPE_BRACE		0x40
    TYPE_NORMAL = 0,
    TYPE_SPACE = 0x1,
    TYPE_COMMAND_END = 0x2,
    TYPE_SUBS = 0x4,
    TYPE_QUOTE = 0x8,
    TYPE_CLOSE_PAREN = 0x10,
    TYPE_CLOSE_BRACK = 0x20,
    TYPE_BRACE = 0x40,
    TYPE_OPEN_PAREN = 0x80,
    TYPE_BAD_ARRAY_INDEX = (
	TYPE_OPEN_PAREN | TYPE_CLOSE_PAREN | TYPE_QUOTE | TYPE_BRACE)
};

#define CHAR_TYPE(c) tclCharTypeTable[(unsigned char)(c)]

MODULE_SCOPE const char tclCharTypeTable[];
MODULE_SCOPE const unsigned char tclCharTypeTable[];

Changes to generic/tclPathObj.c.

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
30
31
32



33
34
35
36
37
38
39
40
41
42
43
44






45
46
47
48
49
50
51
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
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







-
+



















-
+




+
+
+







-
-
-
-
-
+
+
+
+
+
+







/*
 * tclPathObj.c --
 *
 *	This file contains the implementation of Tcl's "path" object type used
 *	to represent and manipulate a general (virtual) filesystem entity in
 *	an efficient manner.
 *
 * Copyright (c) 2003 Vince Darley.
 * Copyright © 2003 Vince Darley.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclFileSystem.h"
#include <assert.h>

/*
 * Prototypes for functions defined later in this file.
 */

static Tcl_Obj *	AppendPath(Tcl_Obj *head, Tcl_Obj *tail);
static void		DupFsPathInternalRep(Tcl_Obj *srcPtr,
			    Tcl_Obj *copyPtr);
static void		FreeFsPathInternalRep(Tcl_Obj *pathPtr);
static void		UpdateStringOfFsPath(Tcl_Obj *pathPtr);
static int		SetFsPathFromAny(Tcl_Interp *interp, Tcl_Obj *pathPtr);
static size_t	FindSplitPos(const char *path, int separator);
static Tcl_Size		FindSplitPos(const char *path, int separator);
static int		IsSeparatorOrNull(int ch);
static Tcl_Obj *	GetExtension(Tcl_Obj *pathPtr);
static int		MakePathFromNormalized(Tcl_Interp *interp,
			    Tcl_Obj *pathPtr);
static int		MakeTildeRelativePath(Tcl_Interp *interp,
			    const char *user, const char *subPath,
			    Tcl_DString *dsPtr);

/*
 * Define the 'path' object type, which Tcl uses to represent file paths
 * internally.
 */

static const Tcl_ObjType fsPathType = {
    "path",				/* name */
    FreeFsPathInternalRep,		/* freeIntRepProc */
    DupFsPathInternalRep,		/* dupIntRepProc */
    UpdateStringOfFsPath,		/* updateStringProc */
    SetFsPathFromAny			/* setFromAnyProc */
    "path",			/* name */
    FreeFsPathInternalRep,	/* freeIntRepProc */
    DupFsPathInternalRep,	/* dupIntRepProc */
    UpdateStringOfFsPath,	/* updateStringProc */
    SetFsPathFromAny,		/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

/*
 * struct FsPath --
 *
 * Internal representation of a Tcl_Obj of fsPathType
 */
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
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







-
+




















-
+


-
+


-
+







				 *  or ~user components.  Otherwise it is a
				 *  path, possibly absolute, to normalize
				 *  relative to cwdPtr. */
    Tcl_Obj *cwdPtr;		/*  If NULL, either translatedPtr exists or
				 *  normPathPtr exists and is absolute. */
    int flags;			/* Flags to describe interpretation - see
				 * below. */
    ClientData nativePathPtr;	/* Native representation of this path, which
    void *nativePathPtr;	/* Native representation of this path, which
				 * is filesystem dependent. */
    size_t filesystemEpoch;	/* Used to ensure the path representation was
				 * generated during the correct filesystem
				 * epoch. The epoch changes when
				 * filesystem-mounts are changed. */
    const Tcl_Filesystem *fsPtr;/* The Tcl_Filesystem that claims this path */
} FsPath;

/*
 * Flag values for FsPath->flags.
 */

#define TCLPATH_APPENDED 1
#define TCLPATH_NEEDNORM 4

/*
 * Define some macros to give us convenient access to path-object specific
 * fields.
 */

#define PATHOBJ(pathPtr) ((FsPath *) (TclFetchIntRep((pathPtr), &fsPathType)->twoPtrValue.ptr1))
#define PATHOBJ(pathPtr) ((FsPath *) (TclFetchInternalRep((pathPtr), &fsPathType)->twoPtrValue.ptr1))
#define SETPATHOBJ(pathPtr,fsPathPtr) \
	do {							\
		Tcl_ObjIntRep ir;				\
		Tcl_ObjInternalRep ir;				\
		ir.twoPtrValue.ptr1 = (void *) (fsPathPtr);	\
		ir.twoPtrValue.ptr2 = NULL;			\
		Tcl_StoreIntRep((pathPtr), &fsPathType, &ir);	\
		Tcl_StoreInternalRep((pathPtr), &fsPathType, &ir);	\
	} while (0)
#define PATHFLAGS(pathPtr) (PATHOBJ(pathPtr)->flags)

/*
 *---------------------------------------------------------------------------
 *
 * TclFSNormalizeAbsolutePath --
136
137
138
139
140
141
142

143
144







145

146
147
148
149
150
151
152
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







+


+
+
+
+
+
+
+
-
+







    Tcl_Obj *pathPtr)		/* Absolute path to normalize */
{
    const char *dirSep, *oldDirSep;
    int first = 1;		/* Set to zero once we've passed the first
				 * directory separator - we can't use '..' to
				 * remove the volume in a path. */
    Tcl_Obj *retVal = NULL;
    int zipVolumeLen;
    dirSep = TclGetString(pathPtr);

    zipVolumeLen = TclIsZipfsPath(dirSep);
    if (zipVolumeLen) {
	/*
	 * NOTE: file normalization for zipfs is very specific to
	 * format of zipfs volume being of the form //xxx:/
	 */
	dirSep += zipVolumeLen-1; /* Start parse after : */
    if (tclPlatform == TCL_PLATFORM_WINDOWS) {
    } else if (tclPlatform == TCL_PLATFORM_WINDOWS) {
	if (   (dirSep[0] == '/' || dirSep[0] == '\\')
	    && (dirSep[1] == '/' || dirSep[1] == '\\')
	    && (dirSep[2] == '?')
	    && (dirSep[3] == '/' || dirSep[3] == '\\')) {
	    /* NT extended path */
	    dirSep += 4;

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
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







-
+



















-
+

















+
+
+
-
+

-
-
-
-
-
+
+
+
+
+
+










-
+
-







		oldDirSep = dirSep;
	    }
	again:
	    if (IsSeparatorOrNull(dirSep[2])) {
		/*
		 * Need to skip '.' in the path.
		 */
		size_t curLen;
		Tcl_Size curLen;

		if (retVal == NULL) {
		    const char *path = TclGetString(pathPtr);
		    retVal = Tcl_NewStringObj(path, dirSep - path);
		    Tcl_IncrRefCount(retVal);
		}
		(void)TclGetStringFromObj(retVal, &curLen);
		if (curLen == 0) {
		    Tcl_AppendToObj(retVal, dirSep, 1);
		}
		dirSep += 2;
		oldDirSep = dirSep;
		if (dirSep[0] != 0 && dirSep[1] == '.') {
		    goto again;
		}
		continue;
	    }
	    if (dirSep[2] == '.' && IsSeparatorOrNull(dirSep[3])) {
		Tcl_Obj *linkObj;
		size_t curLen;
		Tcl_Size curLen;
		char *linkStr;

		/*
		 * Have '..' so need to skip previous directory.
		 */

		if (retVal == NULL) {
		    const char *path = TclGetString(pathPtr);

		    retVal = Tcl_NewStringObj(path, dirSep - path);
		    Tcl_IncrRefCount(retVal);
		}
		(void)TclGetStringFromObj(retVal, &curLen);
		if (curLen == 0) {
		    Tcl_AppendToObj(retVal, dirSep, 1);
		}
		if (!first || (tclPlatform == TCL_PLATFORM_UNIX)) {
		    if (zipVolumeLen) {
			linkObj = NULL;
		    } else {
		    linkObj = Tcl_FSLink(retVal, NULL, 0);
			linkObj = Tcl_FSLink(retVal, NULL, 0);

		    /* Safety check in case driver caused sharing */
		    if (Tcl_IsShared(retVal)) {
			TclDecrRefCount(retVal);
			retVal = Tcl_DuplicateObj(retVal);
			Tcl_IncrRefCount(retVal);
			/* Safety check in case driver caused sharing */
			if (Tcl_IsShared(retVal)) {
			    TclDecrRefCount(retVal);
			    retVal = Tcl_DuplicateObj(retVal);
			    Tcl_IncrRefCount(retVal);
			}
		    }

		    if (linkObj != NULL) {
			/*
			 * Got a link. Need to check if the link is relative
			 * or absolute, for those platforms where relative
			 * links exist.
			 */

			if (tclPlatform != TCL_PLATFORM_WINDOWS
				&& Tcl_FSGetPathType(linkObj)
				&& Tcl_FSGetPathType(linkObj) == TCL_PATH_RELATIVE) {
					== TCL_PATH_RELATIVE) {
			    /*
			     * We need to follow this link which is relative
			     * to retVal's directory. This means concatenating
			     * the link onto the directory of the path so far.
			     */

			    const char *path =
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
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







-
+














-
+
+


+
-
+







			    linkStr = TclGetStringFromObj(retVal, &curLen);

			    /*
			     * Convert to forward-slashes on windows.
			     */

			    if (tclPlatform == TCL_PLATFORM_WINDOWS) {
				size_t i;
				Tcl_Size i;

				for (i = 0; i < curLen; i++) {
				    if (linkStr[i] == '\\') {
					linkStr[i] = '/';
				    }
				}
			    }
			}
		    } else {
			linkStr = TclGetStringFromObj(retVal, &curLen);
		    }

		    /*
		     * Either way, we now remove the last path element (but
		     * not the first character of the path).
		     * not the first character of the path). In the case of
		     * zipfs, make sure not to go beyond the zipfs volume.
		     */

		    int minLen = zipVolumeLen ? zipVolumeLen - 1 : 0;
		    while (curLen-- > 0) {
		    while (--curLen >= minLen) {
			if (IsSeparatorOrNull(linkStr[curLen])) {
			    if (curLen) {
				Tcl_SetObjLength(retVal, curLen);
			    } else {
				Tcl_SetObjLength(retVal, 1);
			    }
			    break;
377
378
379
380
381
382
383

384
385
386
387



388



389
390







391
392
393
394
395
396
397
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







+

-
-
-
+
+
+

+
+
+
-
-
+
+
+
+
+
+
+







	    retVal = Tcl_DuplicateObj(pathPtr);
	    Tcl_IncrRefCount(retVal);
	}
    }

    /*
     * Ensure a windows drive like C:/ has a trailing separator.
     * Likewise for zipfs volumes.
     */

    if (tclPlatform == TCL_PLATFORM_WINDOWS) {
	size_t len;
    if (zipVolumeLen || (tclPlatform == TCL_PLATFORM_WINDOWS)) {
	int needTrailingSlash = 0;
	Tcl_Size len;
	const char *path = TclGetStringFromObj(retVal, &len);
	if (zipVolumeLen) {
	    if (len == (zipVolumeLen - 1)) {
		needTrailingSlash = 1;

	if (len == 2 && path[0] != 0 && path[1] == ':') {
	    }
	} else {
	    if (len == 2 && path[0] != 0 && path[1] == ':') {
		needTrailingSlash = 1;
	    }
	}
	if (needTrailingSlash) {
	    if (Tcl_IsShared(retVal)) {
		TclDecrRefCount(retVal);
		retVal = Tcl_DuplicateObj(retVal);
		Tcl_IncrRefCount(retVal);
	    }
	    Tcl_AppendToObj(retVal, "/", 1);
	}
472
473
474
475
476
477
478
479

480
481
482
483
484
485
486
498
499
500
501
502
503
504

505
506
507
508
509
510
511
512







-
+







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

Tcl_PathType
TclFSGetPathType(
    Tcl_Obj *pathPtr,
    const Tcl_Filesystem **filesystemPtrPtr,
    int *driveNameLengthPtr)
    Tcl_Size *driveNameLengthPtr)
{
    FsPath *fsPathPtr;

    if (Tcl_FSConvertToPathType(NULL, pathPtr) != TCL_OK) {
	return TclGetPathType(pathPtr, filesystemPtrPtr, driveNameLengthPtr,
		NULL);
    }
536
537
538
539
540
541
542
543

544
545
546
547

548
549
550
551
552
553
554
555
556
557
558
559
560
561

562
563
564
565
566
567
568
562
563
564
565
566
567
568

569
570
571
572

573
574
575
576
577
578
579
580
581
582
583
584
585
586

587
588
589
590
591
592
593
594







-
+



-
+













-
+







 *	None.
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclPathPart(
    Tcl_Interp *interp,		/* Used for error reporting */
    TCL_UNUSED(Tcl_Interp *),	/* Used for error reporting */
    Tcl_Obj *pathPtr,		/* Path to take dirname of */
    Tcl_PathPart portion)	/* Requested portion of name */
{
    if (TclHasIntRep(pathPtr, &fsPathType)) {
    if (TclHasInternalRep(pathPtr, &fsPathType)) {
	FsPath *fsPathPtr = PATHOBJ(pathPtr);

	if (PATHFLAGS(pathPtr) != 0) {
	    switch (portion) {
	    case TCL_PATH_DIRNAME: {
		/*
		 * Check if the joined-on bit has any directory delimiters in
		 * it. If so, the 'dirname' would be a joining of the main
		 * part with the dirname of the joined-on bit. We could handle
		 * that special case here, but we don't, and instead just use
		 * the standardPath code.
		 */

		size_t numBytes;
		Tcl_Size numBytes;
		const char *rest = TclGetStringFromObj(fsPathPtr->normPathPtr, &numBytes);

		if (strchr(rest, '/') != NULL) {
		    goto standardPath;
		}
		/*
		 * If the joined-on bit is empty, then [file dirname] is
591
592
593
594
595
596
597
598

599
600
601
602
603
604
605
617
618
619
620
621
622
623

624
625
626
627
628
629
630
631







-
+







		/*
		 * Check if the joined-on bit has any directory delimiters in
		 * it. If so, the 'tail' would be only the part following the
		 * last delimiter. We could handle that special case here, but
		 * we don't, and instead just use the standardPath code.
		 */

		size_t numBytes;
		Tcl_Size numBytes;
		const char *rest = TclGetStringFromObj(fsPathPtr->normPathPtr, &numBytes);

		if (strchr(rest, '/') != NULL) {
		    goto standardPath;
		}
		/*
		 * If the joined-on bit is empty, then [file tail] is
619
620
621
622
623
624
625
626

627
628
629
630
631
632
633
645
646
647
648
649
650
651

652
653
654
655
656
657
658
659







-
+







		Tcl_IncrRefCount(fsPathPtr->normPathPtr);
		return fsPathPtr->normPathPtr;
	    }
	    case TCL_PATH_EXTENSION:
		return GetExtension(fsPathPtr->normPathPtr);
	    case TCL_PATH_ROOT: {
		const char *fileName, *extension;
		size_t length;
		Tcl_Size length;

		fileName = TclGetStringFromObj(fsPathPtr->normPathPtr,
			&length);
		extension = TclGetExtension(fileName);
		if (extension == NULL) {
		    /*
		     * There is no extension so the root is the same as the
662
663
664
665
666
667
668
669

670
671
672
673
674
675
676
677

678
679
680
681
682
683
684
688
689
690
691
692
693
694

695
696
697
698
699
700
701
702

703
704
705
706
707
708
709
710







-
+







-
+







	    /* Relative path */
	    goto standardPath;
	} else {
	    /* Absolute path */
	    goto standardPath;
	}
    } else {
	int splitElements;
	Tcl_Size splitElements;
	Tcl_Obj *splitPtr, *resultPtr;

    standardPath:
	resultPtr = NULL;
	if (portion == TCL_PATH_EXTENSION) {
	    return GetExtension(pathPtr);
	} else if (portion == TCL_PATH_ROOT) {
	    size_t length;
	    Tcl_Size length;
	    const char *fileName, *extension;

	    fileName = TclGetStringFromObj(pathPtr, &length);
	    extension = TclGetExtension(fileName);
	    if (extension == NULL) {
		Tcl_IncrRefCount(pathPtr);
		return pathPtr;
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
721
722
723
724
725
726
727


728








729
730
731
732
733
734
735







-
-

-
-
-
-
-
-
-
-







	 * Tcl_FSSplitPath in the handling of home directories;
	 * Tcl_FSSplitPath preserves the "~",  but this code computes the
	 * actual full path name, if we had just a single component.
	 */

	splitPtr = Tcl_FSSplitPath(pathPtr, &splitElements);
	Tcl_IncrRefCount(splitPtr);
	if (splitElements == 1  &&  TclGetString(pathPtr)[0] == '~') {
	    Tcl_Obj *norm;

	    TclDecrRefCount(splitPtr);
	    norm = Tcl_FSGetNormalizedPath(interp, pathPtr);
	    if (norm == NULL) {
		return NULL;
	    }
	    splitPtr = Tcl_FSSplitPath(norm, &splitElements);
	    Tcl_IncrRefCount(splitPtr);
	}
	if (portion == TCL_PATH_TAIL) {
	    /*
	     * Return the last component, unless it is the only component, and
	     * it is the root of an absolute path.
	     */

	    if ((splitElements > 0) && ((splitElements > 1) ||
800
801
802
803
804
805
806
807

808
809
810

811
812
813

814
815
816
817
818

819
820
821
822
823
824
825

826
827
828

829
830
831

832
833
834
835
836

837

838
839
840
841
842
843
844

845
846
847
848
849
850
851
816
817
818
819
820
821
822

823
824
825

826
827
828

829
830
831
832
833

834
835
836
837
838
839
840

841
842
843

844
845
846

847
848
849


850
851

852
853
854
855
856
857
858

859
860
861
862
863
864
865
866







-
+


-
+


-
+




-
+






-
+


-
+


-
+


-
-

+
-
+






-
+







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

Tcl_Obj *
Tcl_FSJoinPath(
    Tcl_Obj *listObj,		/* Path elements to join, may have a zero
				 * reference count. */
    int elements)		/* Number of elements to use (-1 = all) */
    Tcl_Size elements)		/* Number of elements to use (-1 = all) */
{
    Tcl_Obj *res;
    int objc;
    Tcl_Size objc;
    Tcl_Obj **objv;

    if (Tcl_ListObjLength(NULL, listObj, &objc) != TCL_OK) {
    if (TclListObjLength(NULL, listObj, &objc) != TCL_OK) {
	return NULL;
    }

    elements = ((elements >= 0) && (elements <= objc)) ? elements : objc;
    Tcl_ListObjGetElements(NULL, listObj, &objc, &objv);
    TclListObjGetElements(NULL, listObj, &objc, &objv);
    res = TclJoinPath(elements, objv, 0);
    return res;
}

Tcl_Obj *
TclJoinPath(
    int elements,		/* Number of elements to use (-1 = all) */
    Tcl_Size elements,		/* Number of elements to use */
    Tcl_Obj * const objv[],	/* Path elements to join */
    int forceRelative)		/* If non-zero, assume all more paths are
				 * relative (e. g. simple normalization) */
				 * relative (e.g. simple normalization) */
{
    Tcl_Obj *res = NULL;
    int i;
    Tcl_Size i;
    const Tcl_Filesystem *fsPtr = NULL;

    assert ( elements >= 0 );

    if (elements == 0) {
	TclNewObj(res);
	return Tcl_NewObj();
	return res;
    }

    assert ( elements > 0 );

    if (elements == 2) {
	Tcl_Obj *elt = objv[0];
	Tcl_ObjIntRep *eltIr = TclFetchIntRep(elt, &fsPathType);
	Tcl_ObjInternalRep *eltIr = TclFetchInternalRep(elt, &fsPathType);

	/*
	 * This is a special case where we can be much more efficient, where
	 * we are joining a single relative path onto an object that is
	 * already of path type. The 'TclNewFSPathObj' call below creates an
	 * object which can be normalized more efficiently. Currently we only
	 * use the special case when we have exactly two elements, but we
862
863
864
865
866
867
868
869

870
871
872
873
874
875
876
877
878
879
880
881
882
883

884
885
886
887
888
889
890
877
878
879
880
881
882
883

884
885
886
887
888
889
890
891
892
893
894
895
896
897

898
899
900
901
902
903
904
905







-
+













-
+







	    Tcl_PathType type;

	    /* if forceRelative - second path is relative */
	    type = forceRelative ? TCL_PATH_RELATIVE :
		    TclGetPathType(tailObj, NULL, NULL, NULL);
	    if (type == TCL_PATH_RELATIVE) {
		const char *str;
		size_t len;
		Tcl_Size len;

		str = TclGetStringFromObj(tailObj, &len);
		if (len == 0) {
		    /*
		     * This happens if we try to handle the root volume '/'.
		     * There's no need to return a special path object, when
		     * the base itself is just fine!
		     */

		    return elt;
		}

		/*
		 * If it doesn't begin with '.' and is a unix path or it a
		 * If it doesn't begin with '.' and is a Unix path or it a
		 * windows path without backslashes, then we can be very
		 * efficient here. (In fact even a windows path with
		 * backslashes can be joined efficiently, but the path object
		 * would not have forward slashes only, and this would
		 * therefore contradict our 'file join' documentation).
		 */

929
930
931
932
933
934
935
936
937


938
939
940
941
942
943
944
944
945
946
947
948
949
950


951
952
953
954
955
956
957
958
959







-
-
+
+







	    }
	}
    }

    assert ( res == NULL );

    for (i = 0; i < elements; i++) {
	int driveNameLength;
	size_t strEltLen, length;
	Tcl_Size driveNameLength;
	Tcl_Size strEltLen, length;
	Tcl_PathType type;
	char *strElt, *ptr;
	Tcl_Obj *driveName = NULL;
	Tcl_Obj *elt = objv[i];

	strElt = TclGetStringFromObj(elt, &strEltLen);
	driveNameLength = 0;
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1050
1051
1052
1053
1054
1055
1056










1057
1058
1059
1060
1061
1062
1063







-
-
-
-
-
-
-
-
-
-








    noQuickReturn:
	if (res == NULL) {
	    TclNewObj(res);
	}
	ptr = TclGetStringFromObj(res, &length);

	/*
	 * Strip off any './' before a tilde, unless this is the beginning of
	 * the path.
	 */

	if (length > 0 && strEltLen > 0 && (strElt[0] == '.') &&
		(strElt[1] == '/') && (strElt[2] == '~')) {
	    strElt += 2;
	}

	/*
	 * A NULL value for fsPtr at this stage basically means we're trying
	 * to join a relative path onto something which is also relative (or
	 * empty). There's nothing particularly wrong with that.
	 */

	if (*strElt == '\0') {
1144
1145
1146
1147
1148
1149
1150
1151

1152
1153
1154
1155
1156
1157

1158
1159
1160
1161
1162
1163
1164
1149
1150
1151
1152
1153
1154
1155

1156
1157
1158
1159
1160
1161

1162
1163
1164
1165
1166
1167
1168
1169







-
+





-
+







     * converting this object to FsPath type for the first time, we don't need
     * to worry whether the 'cwd' has changed. On the other hand, if this
     * object is already of FsPath type, and is a relative path, we do have to
     * worry about the cwd. If the cwd has changed, we must recompute the
     * path.
     */

    if (TclHasIntRep(pathPtr, &fsPathType)) {
    if (TclHasInternalRep(pathPtr, &fsPathType)) {
	if (TclFSEpochOk(PATHOBJ(pathPtr)->filesystemEpoch)) {
	    return TCL_OK;
	}

	TclGetString(pathPtr);
	Tcl_StoreIntRep(pathPtr, &fsPathType, NULL);
	Tcl_StoreInternalRep(pathPtr, &fsPathType, NULL);
    }

    return SetFsPathFromAny(interp, pathPtr);
}

/*
 * Helper function for normalization.
1182
1183
1184
1185
1186
1187
1188
1189

1190
1191
1192
1193
1194
1195
1196
1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1201







-
+








/*
 * Helper function for SetFsPathFromAny. Returns position of first directory
 * delimiter in the path. If no separator is found, then returns the position
 * of the end of the string.
 */

static size_t
static Tcl_Size
FindSplitPos(
    const char *path,
    int separator)
{
    int count = 0;
    switch (tclPlatform) {
    case TCL_PLATFORM_UNIX:
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
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







-
+






+
+
+
-
+















-
-
-
-
-
-
-







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

Tcl_Obj *
TclNewFSPathObj(
    Tcl_Obj *dirPtr,
    const char *addStrRep,
    size_t len)
    Tcl_Size len)
{
    FsPath *fsPathPtr;
    Tcl_Obj *pathPtr;
    const char *p;
    int state = 0, count = 0;

    /*
     * This comment is kept from the days of tilde expansion because
     * it is illustrative of a more general problem.
    /* [Bug 2806250] - this is only a partial solution of the problem.
     * [Bug 2806250] - this is only a partial solution of the problem.
     * The PATHFLAGS != 0 representation assumes in many places that
     * the "tail" part stored in the normPathPtr field is itself a
     * relative path.  Strings that begin with "~" are not relative paths,
     * so we must prevent their storage in the normPathPtr field.
     *
     * More generally we ought to be testing "addStrRep" for any value
     * that is not a relative path, but in an unconstrained VFS world
     * that could be just about anything, and testing could be expensive.
     * Since this routine plays a big role in [glob], anything that slows
     * it down would be unwelcome.  For now, continue the risk of further
     * bugs when some Tcl_Filesystem uses otherwise relative path strings
     * as absolute path strings.  Sensible Tcl_Filesystems will avoid
     * that by mounting on path prefixes like foo:// which cannot be the
     * name of a file or directory read from a native [glob] operation.
     */
    if (addStrRep[0] == '~') {
	Tcl_Obj *tail = Tcl_NewStringObj(addStrRep, len);

	pathPtr = AppendPath(dirPtr, tail);
	Tcl_DecrRefCount(tail);
	return pathPtr;
    }

    TclNewObj(pathPtr);
    fsPathPtr = (FsPath *)Tcl_Alloc(sizeof(FsPath));

    /*
     * Set up the path.
     */
1293
1294
1295
1296
1297
1298
1299
1300

1301
1302
1303
1304
1305
1306
1307
1294
1295
1296
1297
1298
1299
1300

1301
1302
1303
1304
1305
1306
1307
1308







-
+








    /*
     * Look for path components made up of only "."
     * This is overly conservative analysis to keep simple. It may mark some
     * things as needing more aggressive normalization that don't actually
     * need it. No harm done.
     */
    for (p = addStrRep; len+1 > 1; p++, len--) {
    for (p = addStrRep; len > 0; p++, len--) {
	switch (state) {
	case 0:		/* So far only "." since last dirsep or start */
	    switch (*p) {
	    case '.':
		count = 1;
		break;
	    case '/':
1337
1338
1339
1340
1341
1342
1343
1344

1345
1346
1347
1348
1349
1350
1351

1352
1353
1354
1355
1356
1357
1358
1338
1339
1340
1341
1342
1343
1344

1345
1346
1347
1348
1349
1350
1351

1352
1353
1354
1355
1356
1357
1358
1359







-
+






-
+







static Tcl_Obj *
AppendPath(
    Tcl_Obj *head,
    Tcl_Obj *tail)
{
    const char *bytes;
    Tcl_Obj *copy = Tcl_DuplicateObj(head);
    size_t length;
    Tcl_Size length;

    /*
     * This is likely buggy when dealing with virtual filesystem drivers
     * that use some character other than "/" as a path separator.  I know
     * of no evidence that such a foolish thing exists.  This solution was
     * chosen so that "JoinPath" operations that pass through either path
     * intrep produce the same results; that is, bugward compatibility.  If
     * internalrep produce the same results; that is, bugward compatibility.  If
     * we need to fix that bug here, it needs fixing in TclJoinPath() too.
     */
    bytes = TclGetStringFromObj(tail, &length);
    if (length == 0) {
	Tcl_AppendToObj(copy, "/", 1);
    } else {
	TclpNativeJoinPath(copy, bytes);
1384
1385
1386
1387
1388
1389
1390
1391

1392
1393

1394
1395
1396
1397
1398
1399
1400
1385
1386
1387
1388
1389
1390
1391

1392
1393

1394
1395
1396
1397
1398
1399
1400
1401







-
+

-
+








Tcl_Obj *
TclFSMakePathRelative(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Obj *pathPtr,		/* The path we have. */
    Tcl_Obj *cwdPtr)		/* Make it relative to this. */
{
    size_t cwdLen, len;
    Tcl_Size cwdLen, len;
    const char *tempStr;
    Tcl_ObjIntRep *irPtr = TclFetchIntRep(pathPtr, &fsPathType);
    Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(pathPtr, &fsPathType);

    if (irPtr) {
	FsPath *fsPathPtr = PATHOBJ(pathPtr);

	if (PATHFLAGS(pathPtr) != 0 && fsPathPtr->cwdPtr == cwdPtr) {
	    return fsPathPtr->normPathPtr;
	}
1456
1457
1458
1459
1460
1461
1462
1463

1464
1465
1466
1467
1468
1469
1470
1457
1458
1459
1460
1461
1462
1463

1464
1465
1466
1467
1468
1469
1470
1471







-
+







static int
MakePathFromNormalized(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Obj *pathPtr)		/* The object to convert. */
{
    FsPath *fsPathPtr;

    if (TclHasIntRep(pathPtr, &fsPathType)) {
    if (TclHasInternalRep(pathPtr, &fsPathType)) {
	return TCL_OK;
    }

    fsPathPtr = (FsPath *)Tcl_Alloc(sizeof(FsPath));

    /*
     * It's a pure normalized absolute path.
1509
1510
1511
1512
1513
1514
1515
1516

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

1535
1536
1537
1538
1539
1540
1541
1510
1511
1512
1513
1514
1515
1516

1517
1518
1519
1520

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

1534
1535
1536
1537
1538
1539
1540
1541







-
+



-













-
+







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

Tcl_Obj *
Tcl_FSNewNativePath(
    const Tcl_Filesystem *fromFilesystem,
    ClientData clientData)
    void *clientData)
{
    Tcl_Obj *pathPtr = NULL;
    FsPath *fsPathPtr;


    if (fromFilesystem->internalToNormalizedProc != NULL) {
	pathPtr = (*fromFilesystem->internalToNormalizedProc)(clientData);
    }
    if (pathPtr == NULL) {
	return NULL;
    }

    /*
     * Free old representation; shouldn't normally be any, but best to be
     * safe.
     */

    Tcl_StoreIntRep(pathPtr, &fsPathType, NULL);
    Tcl_StoreInternalRep(pathPtr, &fsPathType, NULL);
    fsPathPtr = (FsPath *)Tcl_Alloc(sizeof(FsPath));

    fsPathPtr->translatedPathPtr = NULL;

    Tcl_IncrRefCount(fsPathPtr->normPathPtr = Tcl_DuplicateObj(pathPtr));
    fsPathPtr->cwdPtr = NULL;
    fsPathPtr->nativePathPtr = clientData;
1593
1594
1595
1596
1597
1598
1599
1600

1601
1602
1603
1604
1605
1606
1607
1608
1609

1610
1611
1612
1613
1614
1615
1616
1593
1594
1595
1596
1597
1598
1599

1600
1601
1602
1603
1604
1605
1606
1607
1608

1609
1610
1611
1612
1613
1614
1615
1616







-
+








-
+







	     * (cwdPtr) and a tail (normPathPtr), and if we join the
	     * translated version of cwdPtr to normPathPtr, we'll get the
	     * translated result we need, and can store it for future use.
	     */

	    Tcl_Obj *translatedCwdPtr = Tcl_FSGetTranslatedPath(interp,
		    srcFsPathPtr->cwdPtr);
	    Tcl_ObjIntRep *translatedCwdIrPtr;
	    Tcl_ObjInternalRep *translatedCwdIrPtr;

	    if (translatedCwdPtr == NULL) {
		return NULL;
	    }

	    retObj = Tcl_FSJoinToPath(translatedCwdPtr, 1,
		    &srcFsPathPtr->normPathPtr);
	    Tcl_IncrRefCount(srcFsPathPtr->translatedPathPtr = retObj);
	    translatedCwdIrPtr = TclFetchIntRep(translatedCwdPtr, &fsPathType);
	    translatedCwdIrPtr = TclFetchInternalRep(translatedCwdPtr, &fsPathType);
	    if (translatedCwdIrPtr) {
		srcFsPathPtr->filesystemEpoch
			= PATHOBJ(translatedCwdPtr)->filesystemEpoch;
	    } else {
		srcFsPathPtr->filesystemEpoch = 0;
	    }
	    Tcl_DecrRefCount(translatedCwdPtr);
1652
1653
1654
1655
1656
1657
1658
1659

1660
1661
1662
1663
1664
1665
1666
1652
1653
1654
1655
1656
1657
1658

1659
1660
1661
1662
1663
1664
1665
1666







-
+







Tcl_FSGetTranslatedStringPath(
    Tcl_Interp *interp,
    Tcl_Obj *pathPtr)
{
    Tcl_Obj *transPtr = Tcl_FSGetTranslatedPath(interp, pathPtr);

    if (transPtr != NULL) {
	size_t len;
	Tcl_Size len;
	const char *orig = TclGetStringFromObj(transPtr, &len);
	char *result = (char *)Tcl_Alloc(len+1);

	memcpy(result, orig, len+1);
	TclDecrRefCount(transPtr);
	return result;
    }
1702
1703
1704
1705
1706
1707
1708
1709

1710
1711
1712
1713
1714
1715
1716
1702
1703
1704
1705
1706
1707
1708

1709
1710
1711
1712
1713
1714
1715
1716







-
+







    if (PATHFLAGS(pathPtr) != 0) {
	/*
	 * This is a special path object which is the result of something like
	 * 'file join'
	 */

	Tcl_Obj *dir, *copy;
	size_t tailLen, cwdLen;
	Tcl_Size tailLen, cwdLen;
	int pathType;

	pathType = Tcl_FSGetPathType(fsPathPtr->cwdPtr);
	dir = Tcl_FSGetNormalizedPath(interp, fsPathPtr->cwdPtr);
	if (dir == NULL) {
	    return NULL;
	}
1798
1799
1800
1801
1802
1803
1804
1805

1806
1807
1808
1809
1810
1811

1812
1813
1814
1815
1816
1817
1818
1798
1799
1800
1801
1802
1803
1804

1805
1806
1807
1808
1809
1810

1811
1812
1813
1814
1815
1816
1817
1818







-
+





-
+







    /*
     * Ensure cwd hasn't changed.
     */

    if (fsPathPtr->cwdPtr != NULL) {
	if (!TclFSCwdPointerEquals(&fsPathPtr->cwdPtr)) {
	    TclGetString(pathPtr);
	    Tcl_StoreIntRep(pathPtr, &fsPathType, NULL);
	    Tcl_StoreInternalRep(pathPtr, &fsPathType, NULL);
	    if (SetFsPathFromAny(interp, pathPtr) != TCL_OK) {
		return NULL;
	    }
	    fsPathPtr = PATHOBJ(pathPtr);
	} else if (fsPathPtr->normPathPtr == NULL) {
	    size_t cwdLen;
	    Tcl_Size cwdLen;
	    Tcl_Obj *copy;

	    copy = AppendPath(fsPathPtr->cwdPtr, pathPtr);

	    (void) TclGetStringFromObj(fsPathPtr->cwdPtr, &cwdLen);
	    cwdLen += (TclGetString(copy)[cwdLen] == '/');

1947
1948
1949
1950
1951
1952
1953
1954

1955
1956
1957
1958
1959
1960
1961
1947
1948
1949
1950
1951
1952
1953

1954
1955
1956
1957
1958
1959
1960
1961







-
+







 *
 *	Tcl_FSCreateInternalRepProc if needed to produce the native
 *	handle, which is then stored in the internal representation of pathPtr.
 *
 *---------------------------------------------------------------------------
 */

ClientData
void *
Tcl_FSGetInternalRep(
    Tcl_Obj *pathPtr,
    const Tcl_Filesystem *fsPtr)
{
    FsPath *srcFsPathPtr;

    if (Tcl_FSConvertToPathType(NULL, pathPtr) != TCL_OK) {
2044
2045
2046
2047
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
2044
2045
2046
2047
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







-
+













-
+







int
TclFSEnsureEpochOk(
    Tcl_Obj *pathPtr,
    const Tcl_Filesystem **fsPtrPtr)
{
    FsPath *srcFsPathPtr;

    if (!TclHasIntRep(pathPtr, &fsPathType)) {
    if (!TclHasInternalRep(pathPtr, &fsPathType)) {
	return TCL_OK;
    }

    srcFsPathPtr = PATHOBJ(pathPtr);

    if (!TclFSEpochOk(srcFsPathPtr->filesystemEpoch)) {
	/*
	 * The filesystem has changed in some way since the internal
	 * representation for this object was calculated. Discard the stale
	 * representation and recalculate it.
	 */

	TclGetString(pathPtr);
	Tcl_StoreIntRep(pathPtr, &fsPathType, NULL);
	Tcl_StoreInternalRep(pathPtr, &fsPathType, NULL);
	if (SetFsPathFromAny(NULL, pathPtr) != TCL_OK) {
	    return TCL_ERROR;
	}
	srcFsPathPtr = PATHOBJ(pathPtr);
    }

    if (srcFsPathPtr->fsPtr != NULL) {
2094
2095
2096
2097
2098
2099
2100
2101

2102
2103
2104
2105
2106
2107
2108
2109

2110
2111
2112
2113
2114
2115
2116
2094
2095
2096
2097
2098
2099
2100

2101
2102
2103
2104
2105
2106
2107
2108

2109
2110
2111
2112
2113
2114
2115
2116







-
+







-
+







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

void
TclFSSetPathDetails(
    Tcl_Obj *pathPtr,
    const Tcl_Filesystem *fsPtr,
    ClientData clientData)
    void *clientData)
{
    FsPath *srcFsPathPtr;

    /*
     * Make sure pathPtr is of the correct type.
     */

    if (!TclHasIntRep(pathPtr, &fsPathType)) {
    if (!TclHasInternalRep(pathPtr, &fsPathType)) {
	if (SetFsPathFromAny(NULL, pathPtr) != TCL_OK) {
	    return;
	}
    }

    srcFsPathPtr = PATHOBJ(pathPtr);
    srcFsPathPtr->fsPtr = fsPtr;
2137
2138
2139
2140
2141
2142
2143
2144

2145
2146
2147
2148
2149
2150
2151
2137
2138
2139
2140
2141
2142
2143

2144
2145
2146
2147
2148
2149
2150
2151







-
+








int
Tcl_FSEqualPaths(
    Tcl_Obj *firstPtr,
    Tcl_Obj *secondPtr)
{
    const char *firstStr, *secondStr;
    size_t firstLen, secondLen;
    Tcl_Size firstLen, secondLen;
    int tempErrno;

    if (firstPtr == secondPtr) {
	return 1;
    }

    if (firstPtr == NULL || secondPtr == NULL) {
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
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
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







-
-
-
-











-
+


-
+


-

-
+

















-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-









+
+
-
-
+
+

-
+







 *---------------------------------------------------------------------------
 *
 * SetFsPathFromAny --
 *
 *	Attempt to convert the internal representation of pathPtr to
 *	fsPathType.
 *
 *	A tilde ("~") character at the beginnig of the filename indicates the
 *	current user's home directory, and "~<user>" indicates a particular
 *	user's directory.
 *
 * Results:
 *	Standard Tcl error code.
 *
 * Side effects:
 *	The old representation may be freed, and new memory allocated.
 *
 *---------------------------------------------------------------------------
 */

static int
SetFsPathFromAny(
    Tcl_Interp *interp,		/* Used for error reporting if not NULL. */
    TCL_UNUSED(Tcl_Interp *),	/* Used for error reporting if not NULL. */
    Tcl_Obj *pathPtr)		/* The object to convert. */
{
    size_t len;
    Tcl_Size len;
    FsPath *fsPathPtr;
    Tcl_Obj *transPtr;
    const char *name;

    if (TclHasIntRep(pathPtr, &fsPathType)) {
    if (TclHasInternalRep(pathPtr, &fsPathType)) {
	return TCL_OK;
    }

    /*
     * First step is to translate the filename. This is similar to
     * Tcl_TranslateFilename, but shouldn't convert everything to windows
     * backslashes on that platform. The current implementation of this piece
     * is a slightly optimised version of the various Tilde/Split/Join stuff
     * to avoid multiple split/join operations.
     *
     * We remove any trailing directory separator.
     *
     * However, the split/join routines are quite complex, and one has to make
     * sure not to break anything on Unix or Win (fCmd.test, fileName.test and
     * cmdAH.test exercise most of the code).
     */

    name = TclGetStringFromObj(pathPtr, &len);
    TclGetStringFromObj(pathPtr, &len); /* TODO: Is this needed? */

    /*
     * Handle tilde substitutions, if needed.
     */

    if (len && name[0] == '~') {
	Tcl_DString temp;
	size_t split;
	char separator = '/';

	/*
	 * We have multiple cases '~/foo/bar...', '~user/foo/bar...', etc.
	 * split becomes value 1 for '~/...' as well as for '~'.
	 */
	split = FindSplitPos(name, separator);

	/*
	 * Do some tilde substitution.
	 */

	if (split == 1) {
	    /*
	     * We have just '~' (or '~/...')
	     */

	    const char *dir;
	    Tcl_DString dirString;

	    dir = TclGetEnv("HOME", &dirString);
	    if (dir == NULL) {
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "couldn't find HOME environment variable to"
			    " expand path", -1));
		    Tcl_SetErrorCode(interp, "TCL", "VALUE", "PATH",
			    "HOMELESS", NULL);
		}
		return TCL_ERROR;
	    }
	    Tcl_DStringInit(&temp);
	    Tcl_JoinPath(1, &dir, &temp);
	    Tcl_DStringFree(&dirString);
	} else {
	    /*
	     * There is a '~user'
	     */

	    const char *expandedUser;
	    Tcl_DString userName;

	    Tcl_DStringInit(&userName);
	    Tcl_DStringAppend(&userName, name+1, split-1);
	    expandedUser = Tcl_DStringValue(&userName);

	    Tcl_DStringInit(&temp);
	    if (TclpGetUserHome(expandedUser, &temp) == NULL) {
		if (interp != NULL) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "user \"%s\" doesn't exist", expandedUser));
		    Tcl_SetErrorCode(interp, "TCL", "VALUE", "PATH", "NOUSER",
			    NULL);
		}
		Tcl_DStringFree(&userName);
		Tcl_DStringFree(&temp);
		return TCL_ERROR;
	    }
	    Tcl_DStringFree(&userName);
	}

	transPtr = TclDStringToObj(&temp);

	if (split != len) {
	    /*
	     * Join up the tilde substitution with the rest.
	     */

	    if (name[split+1] == separator) {
		/*
		 * Somewhat tricky case like ~//foo/bar. Make use of
		 * Split/Join machinery to get it right. Assumes all paths
		 * beginning with ~ are part of the native filesystem.
		 */

		int objc;
		Tcl_Obj **objv;
		Tcl_Obj *parts = TclpNativeSplitPath(pathPtr, NULL);

		Tcl_ListObjGetElements(NULL, parts, &objc, &objv);

		/*
		 * Skip '~'. It's replaced by its expansion.
		 */

		objc--; objv++;
		while (objc--) {
		    TclpNativeJoinPath(transPtr, TclGetString(*objv));
		    objv++;
		}
		TclDecrRefCount(parts);
	    } else {
		Tcl_Obj *pair[2];

		pair[0] = transPtr;
		pair[1] = Tcl_NewStringObj(name+split+1, -1);
		transPtr = TclJoinPath(2, pair, 1);
		if (transPtr != pair[0]) {
		    Tcl_DecrRefCount(pair[0]);
		}
		if (transPtr != pair[1]) {
		    Tcl_DecrRefCount(pair[1]);
		}
	    }
	}
    } else {
	transPtr = TclJoinPath(1, &pathPtr, 1);
    transPtr = TclJoinPath(1, &pathPtr, 1);
    }

    /*
     * Now we have a translated filename in 'transPtr'. This will have forward
     * slashes on Windows, and will not contain any ~user sequences.
     */

    fsPathPtr = (FsPath *)Tcl_Alloc(sizeof(FsPath));

    if (transPtr == pathPtr) {
	(void) Tcl_GetString(pathPtr);
	TclFreeInternalRep(pathPtr);
        transPtr = Tcl_DuplicateObj(pathPtr);
        fsPathPtr->filesystemEpoch = 0;
	transPtr = Tcl_DuplicateObj(pathPtr);
	fsPathPtr->filesystemEpoch = 0;
    } else {
        fsPathPtr->filesystemEpoch = TclFSEpoch();
	fsPathPtr->filesystemEpoch = TclFSEpoch();
    }
    Tcl_IncrRefCount(transPtr);
    fsPathPtr->translatedPathPtr = transPtr;
    fsPathPtr->normPathPtr = NULL;
    fsPathPtr->cwdPtr = NULL;
    fsPathPtr->nativePathPtr = NULL;
    fsPathPtr->fsPtr = NULL;
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
2489
2490
2491
2492
2493
2494
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







-
+


-
+



+
-
-
-
-
+
+
+
+
+
+
+
+








-
+







 *	Memory may be allocated.
 *
 *---------------------------------------------------------------------------
 */

static void
UpdateStringOfFsPath(
    Tcl_Obj *pathPtr)	/* path obj with string rep to update. */
    Tcl_Obj *pathPtr)		/* path obj with string rep to update. */
{
    FsPath *fsPathPtr = PATHOBJ(pathPtr);
    size_t cwdLen;
    Tcl_Size cwdLen;
    Tcl_Obj *copy;

    if (PATHFLAGS(pathPtr) == 0 || fsPathPtr->cwdPtr == NULL) {
	if (fsPathPtr->translatedPathPtr == NULL) {
	Tcl_Panic("Called UpdateStringOfFsPath with invalid object");
    }

    copy = AppendPath(fsPathPtr->cwdPtr, fsPathPtr->normPathPtr);
	    Tcl_Panic("Called UpdateStringOfFsPath with invalid object");
	} else {
	    copy = Tcl_DuplicateObj(fsPathPtr->translatedPathPtr);
	}
    } else {
	    copy = AppendPath(fsPathPtr->cwdPtr, fsPathPtr->normPathPtr);
    }

    if (Tcl_IsShared(copy)) {
	copy = Tcl_DuplicateObj(copy);
    }

    Tcl_IncrRefCount(copy);
    /* Steal copy's string rep */
    pathPtr->bytes = TclGetStringFromObj(copy, &cwdLen);
    pathPtr->length = cwdLen;
    TclInitStringRep(copy, NULL, 0);
    TclInitEmptyStringRep(copy);
    TclDecrRefCount(copy);
}

/*
 *---------------------------------------------------------------------------
 *
 * TclNativePathInFilesystem --
2508
2509
2510
2511
2512
2513
2514
2515

2516
2517
2518
2519
2520
2521
2522
2523
2524

2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543

2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560



























































































































































































































































































2561
2562
2563
2564
2565
2566
2567
2568
2395
2396
2397
2398
2399
2400
2401

2402
2403
2404
2405
2406
2407
2408
2409
2410

2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429

2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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







-
+








-
+


















-
+

















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








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

int
TclNativePathInFilesystem(
    Tcl_Obj *pathPtr,
    TCL_UNUSED(ClientData *))
    TCL_UNUSED(void **))
{
    /*
     * A special case is required to handle the empty path "". This is a valid
     * path (i.e. the user should be able to do 'file exists ""' without
     * throwing an error), but equally the path doesn't exist. Those are the
     * semantics of Tcl (at present anyway), so we have to abide by them here.
     */

    if (TclHasIntRep(pathPtr, &fsPathType)) {
    if (TclHasInternalRep(pathPtr, &fsPathType)) {
	if (pathPtr->bytes != NULL && pathPtr->bytes[0] == '\0') {
	    /*
	     * We reject the empty path "".
	     */

	    return -1;
	}

	/*
	 * Otherwise there is no way this path can be empty.
	 */
    } else {
	/*
	 * It is somewhat unusual to reach this code path without the object
	 * being of fsPathType. However, we do our best to deal with the
	 * situation.
	 */

	size_t len;
	Tcl_Size len;

	(void) TclGetStringFromObj(pathPtr, &len);
	if (len == 0) {
	    /*
	     * We reject the empty path "".
	     */

	    return -1;
	}
    }

    /*
     * Path is of correct type, or is of non-zero length, so we accept it.
     */

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * MakeTildeRelativePath --
 *
 *      Returns a path relative to the home directory of a user.
 *      Note there is a difference between not specifying a user and
 *	explicitly specifying the current user. This mimics Tcl8's tilde
 *	expansion.
 *
 *	The subPath argument is joined to the expanded home directory
 *	as in Tcl_JoinPath. This means if it is not relative, it will
 *	returned as the result with the home directory only checked
 *	for user name validity.
 *
 * Results:
 *	Returns TCL_OK on success with home directory path in *dsPtr
 *	and TCL_ERROR on failure with error message in interp if non-NULL.
 *
 *----------------------------------------------------------------------
 */
int
MakeTildeRelativePath(
    Tcl_Interp *interp,		/* May be NULL. Only used for error messages */
    const char *user,		/* User name. NULL -> current user */
    const char *subPath,	/* Rest of path. May be NULL */
    Tcl_DString *dsPtr)		/* Output. Is initialized by the function. Must
				 * be freed on success */
{
    const char *dir;
    Tcl_DString dirString;

    Tcl_DStringInit(dsPtr);
    Tcl_DStringInit(&dirString);

    if (user == NULL || user[0] == 0) {
	/* No user name specified -> current user */

	dir = TclGetEnv("HOME", &dirString);
	if (dir == NULL) {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"couldn't find HOME environment variable to expand path",
			-1));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "PATH",
			"HOMELESS", (char *)NULL);
	    }
	    return TCL_ERROR;
	}
    } else {
	/* User name specified - ~user */
	dir = TclpGetUserHome(user, &dirString);
	if (dir == NULL) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"user \"%s\" doesn't exist", user));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "PATH", "NOUSER",
			(char *)NULL);
	    }
	    return TCL_ERROR;
	}
    }
    if (subPath) {
	const char *parts[2];
	parts[0] = dir;
	parts[1] = subPath;
	Tcl_JoinPath(2, parts, dsPtr);
    } else {
	Tcl_JoinPath(1, &dir, dsPtr);
    }

    Tcl_DStringFree(&dirString);

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetHomeDirObj --
 *
 *	Wrapper around MakeTildeRelativePath. See that function.
 *
 * Results:
 *      Returns a Tcl_Obj containing the home directory of a user
 *	or NULL on failure with error message in interp if non-NULL.
 *
 *----------------------------------------------------------------------
 */
Tcl_Obj *
TclGetHomeDirObj(
    Tcl_Interp *interp,		/* May be NULL. Only used for error messages */
    const char *user)		/* User name. NULL -> current user */
{
    Tcl_DString dirString;

    if (MakeTildeRelativePath(interp, user, NULL, &dirString) != TCL_OK) {
	return NULL;
    }
    return Tcl_DStringToObj(&dirString);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FSTildeExpand --
 *
 *	Copies the path passed in to the output Tcl_DString dsPtr,
 *	resolving leading ~ and ~user components in the path if present.
 *      An error is returned if such a component IS present AND cannot
 *      be resolved.
 *
 *	The output dsPtr must be cleared by caller on success.
 *
 * Results:
 *      TCL_OK - path did not contain leading ~ or it was successful resolved
 *      TCL_ERROR - ~ component could not be resolved.
 *
 *----------------------------------------------------------------------
 */
int Tcl_FSTildeExpand(
    Tcl_Interp *interp,	/* May be NULL. Only used for error messages */
    const char *path,	/* Path to resolve tilde */
    Tcl_DString *dsPtr) /* Output DString for resolved path. */

{
    Tcl_Size split;
    int result;

    assert(path);
    assert(dsPtr);

    Tcl_DStringInit(dsPtr);
    if (path[0] != '~') {
	Tcl_DStringAppend(dsPtr, path, -1);
	return TCL_OK;
    }

    /*
     * We have multiple cases '~', '~user', '~/foo/bar...', '~user/foo...'
     * FindSplitPos returns 1 for '~/...' as well as for '~'. Note on
     * Windows FindSplitPos implicitly checks for '\' as separator
     * in addition to what is passed.
     */
    split = FindSplitPos(path, '/');

    if (split == 1) {
	/* No user name specified '~' or '~/...' -> current user */
	result = MakeTildeRelativePath(interp, NULL, path[1] ? 2 + path : NULL, dsPtr);
    } else {
	/* User name specified - ~user, ~user/... */
	const char *user;
	Tcl_DString dsUser;

	Tcl_DStringInit(&dsUser);
	Tcl_DStringAppend(&dsUser, path+1, split-1);
	user = Tcl_DStringValue(&dsUser);

	/* path[split] is / for ~user/... or \0 for ~user */
	result = MakeTildeRelativePath(interp, user,
		  path[split] ? &path[split + 1] : NULL, dsPtr);
	Tcl_DStringFree(&dsUser);
    }
    if (result != TCL_OK) {
	/* Do not rely on caller to free in case of errors */
	Tcl_DStringFree(dsPtr);
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TclResolveTildePath --
 *
 *	If the passed path is begins with a tilde, does tilde resolution
 *	and returns a Tcl_Obj containing the resolved path. If the tilde
 *	component cannot be resolved, returns NULL. If the path does not
 *	begin with a tilde, returns as is.
 *
 * Results:
 *      Returns a Tcl_Obj with resolved path. This may be a new Tcl_Obj
 *	with ref count 0 or that pathObj that was passed in without its
 *	ref count modified.
 *      Returns NULL if the path begins with a ~ that cannot be resolved
 *	and stores an error message in interp if non-NULL.
 *
 *----------------------------------------------------------------------
 */
Tcl_Obj *
TclResolveTildePath(
    Tcl_Interp *interp,		/* May be NULL. Only used for error messages */
    Tcl_Obj *pathObj)
{
    const char *path;
    Tcl_Size len;
    Tcl_DString resolvedPath;

    path = TclGetStringFromObj(pathObj, &len);
    /* Optimize to skip unnecessary calls below */
    if (path[0] != '~') {
	return pathObj;
    }

    if (Tcl_FSTildeExpand(interp, path, &resolvedPath) != TCL_OK) {
	return NULL;
    }

    return Tcl_DStringToObj(&resolvedPath);
}

/*
 *----------------------------------------------------------------------
 *
 * TclResolveTildePathList --
 *
 *	Given a Tcl_Obj that is a list of paths, returns a Tcl_Obj containing
 *	the paths with any ~-prefixed paths resolved.
 *
 *	Empty strings and ~-prefixed paths that cannot be resolved are
 *      removed from the returned list.
 *
 *      The trailing components of the path are returned verbatim. No
 *	processing is done on them. Moreover, no assumptions should be
 *	made about the separators in the returned path. They may be /
 *	or native. Appropriate path manipulations functions should be
 *	used by caller if desired.
 *
 * Results:
 *	Returns a Tcl_Obj with resolved paths. This may be a new Tcl_Obj with
 *	reference count 0 or the original passed-in Tcl_Obj if no paths needed
 *	resolution. A NULL is returned if the passed in value is not a list
 *	or was NULL.
 *
 *----------------------------------------------------------------------
 */
Tcl_Obj *
TclResolveTildePathList(
    Tcl_Obj *pathsObj)
{
    Tcl_Obj **objv;
    Tcl_Size objc;
    Tcl_Size i;
    Tcl_Obj *resolvedPaths;
    const char *path;

    if (pathsObj == NULL) {
	return NULL;
    }
    if (Tcl_ListObjGetElements(NULL, pathsObj, &objc, &objv) != TCL_OK) {
	return NULL; /* Not a list */
    }

    /*
     * Figure out if any paths need resolving to avoid unnecessary allocations.
     */
    for (i = 0; i < objc; ++i) {
	path = Tcl_GetString(objv[i]);
	if (path[0] == '~') {
	    break; /* At least one path needs resolution */
	}
    }
    if (i == objc) {
	return pathsObj; /* No paths needed to be resolved */
    }

    resolvedPaths = Tcl_NewListObj(objc, NULL);
    for (i = 0; i < objc; ++i) {
	Tcl_Obj *resolvedPath;
	path = Tcl_GetString(objv[i]);
	if (path[0] == 0) {
	    continue; /* Skip empty strings */
	}
	resolvedPath = TclResolveTildePath(NULL, objv[i]);
	if (resolvedPath) {
	    /* Paths that cannot be resolved are skipped */
	    Tcl_ListObjAppendElement(NULL, resolvedPaths, resolvedPath);
	}
    }

    return resolvedPaths;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclPipe.c.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tclPipe.c --
 *
 *	This file contains the generic portion of the command channel driver
 *	as well as various utility routines used in managing subprocesses.
 *
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 * Copyright © 1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

107
108
109
110
111
112
113
114

115
116
117
118
119
120
121
107
108
109
110
111
112
113

114
115
116
117
118
119
120
121







-
+







		Tcl_SetObjResult(interp, msg);
	    } else {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"channel \"%s\" wasn't opened for %s",
			Tcl_GetChannelName(chan),
			((writing) ? "writing" : "reading")));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC",
			"BADCHAN", NULL);
			"BADCHAN", (char *)NULL);
	    }
	    return NULL;
	}
	*releasePtr = 1;
	if (writing) {
	    /*
	     * Be sure to flush output to the file, so that anything written
151
152
153
154
155
156
157
158

159
160
161
162
163
164
165
151
152
153
154
155
156
157

158
159
160
161
162
163
164
165







-
+







	*closePtr = 1;
    }
    return file;

  badLastArg:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "can't specify \"%s\" as last word in command", arg));
    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "SYNTAX", NULL);
    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "SYNTAX", (char *)NULL);
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DetachPids --
175
176
177
178
179
180
181
182

183
184
185
186
187

188
189
190
191
192
193
194
175
176
177
178
179
180
181

182
183
184
185
186

187
188
189
190
191
192
193
194







-
+




-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_DetachPids(
    int numPids,		/* Number of pids to detach: gives size of
    Tcl_Size numPids,		/* Number of pids to detach: gives size of
				 * array pointed to by pidPtr. */
    Tcl_Pid *pidPtr)		/* Array of pids to detach. */
{
    Detached *detPtr;
    int i;
    Tcl_Size i;

    Tcl_MutexLock(&pipeMutex);
    for (i = 0; i < numPids; i++) {
	detPtr = (Detached *)Tcl_Alloc(sizeof(Detached));
	detPtr->pid = pidPtr[i];
	detPtr->nextPtr = detList;
	detList = detPtr;
265
266
267
268
269
270
271
272

273
274
275
276
277
278
279

280
281

282
283
284
285
286
287
288
265
266
267
268
269
270
271

272
273
274
275
276
277
278

279
280

281
282
283
284
285
286
287
288







-
+






-
+

-
+







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

int
TclCleanupChildren(
    Tcl_Interp *interp,		/* Used for error messages. */
    int numPids,		/* Number of entries in pidPtr array. */
    Tcl_Size numPids,		/* Number of entries in pidPtr array. */
    Tcl_Pid *pidPtr,		/* Array of process ids of children. */
    Tcl_Channel errorChan)	/* Channel for file containing stderr output
				 * from pipeline. NULL means there isn't any
				 * stderr output. */
{
    int result = TCL_OK;
    int i, abnormalExit, anyErrorInfo;
    int code, abnormalExit, anyErrorInfo;
    TclProcessWaitStatus waitStatus;
    int code;
    Tcl_Size i;
    Tcl_Obj *msg, *error;

    abnormalExit = 0;
    for (i = 0; i < numPids; i++) {
	waitStatus = TclProcessWait(pidPtr[i], 0, &code, &msg, &error);
	if (waitStatus == TCL_PROCESS_ERROR) {
	    result = TCL_ERROR;
331
332
333
334
335
336
337
338

339
340
341
342
343
344
345
331
332
333
334
335
336
337

338
339
340
341
342
343
344
345







-
+








	if (interp != NULL) {
	    int count;
	    Tcl_Obj *objPtr;

	    Tcl_Seek(errorChan, 0, SEEK_SET);
	    TclNewObj(objPtr);
	    count = Tcl_ReadChars(errorChan, objPtr, -1, 0);
	    count = Tcl_ReadChars(errorChan, objPtr, TCL_INDEX_NONE, 0);
	    if (count == -1) {
		result = TCL_ERROR;
		Tcl_DecrRefCount(objPtr);
		Tcl_ResetResult(interp);
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"error reading stderr output file: %s",
			Tcl_PosixError(interp)));
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
442
443
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
442
443







-
+
















-
+


-
+
















-
+















-
+

-
+







 *	Given an argc/argv array, instantiate a pipeline of processes as
 *	described by the argv.
 *
 *	This function is unofficially exported for use by BLT.
 *
 * Results:
 *	The return value is a count of the number of new processes created, or
 *	-1 if an error occurred while creating the pipeline. *pidArrayPtr is
 *	TCL_INDEX_NONE if an error occurred while creating the pipeline. *pidArrayPtr is
 *	filled in with the address of a dynamically allocated array giving the
 *	ids of all of the processes. It is up to the caller to free this array
 *	when it isn't needed anymore. If inPipePtr is non-NULL, *inPipePtr is
 *	filled in with the file id for the input pipe for the pipeline (if
 *	any): the caller must eventually close this file. If outPipePtr isn't
 *	NULL, then *outPipePtr is filled in with the file id for the output
 *	pipe from the pipeline: the caller must close this file. If errFilePtr
 *	isn't NULL, then *errFilePtr is filled with a file id that may be used
 *	to read error output after the pipeline completes.
 *
 * Side effects:
 *	Processes and pipes are created.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_Size
TclCreatePipeline(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting. */
    int argc,			/* Number of entries in argv. */
    Tcl_Size argc,		/* Number of entries in argv. */
    const char **argv,		/* Array of strings describing commands in
				 * pipeline plus I/O redirection with <, <<,
				 * >, etc. Argv[argc] must be NULL. */
    Tcl_Pid **pidArrayPtr,	/* Word at *pidArrayPtr gets filled in with
				 * address of array of pids for processes in
				 * pipeline (first pid is first process in
				 * pipeline). */
    TclFile *inPipePtr,		/* If non-NULL, input to the pipeline comes
				 * from a pipe (unless overridden by
				 * redirection in the command). The file id
				 * with which to write to this pipe is stored
				 * at *inPipePtr. NULL means command specified
				 * its own input source. */
    TclFile *outPipePtr,	/* If non-NULL, output to the pipeline goes to
				 * a pipe, unless overridden by redirection in
				 * the command. The file id with which to read
				 * frome this pipe is stored at *outPipePtr.
				 * from this pipe is stored at *outPipePtr.
				 * NULL means command specified its own output
				 * sink. */
    TclFile *errFilePtr)	/* If non-NULL, all stderr output from the
				 * pipeline will go to a temporary file
				 * created here, and a descriptor to read the
				 * file will be left at *errFilePtr. The file
				 * will be removed already, so closing this
				 * descriptor will be the end of the file. If
				 * this is NULL, then all stderr output goes
				 * to our stderr. If the pipeline specifies
				 * redirection then the file will still be
				 * created but it will never get any data. */
{
    Tcl_Pid *pidPtr = NULL;	/* Points to malloc-ed array holding all the
				 * pids of child processes. */
    int numPids;		/* Actual number of processes that exist at
    Tcl_Size numPids;		/* Actual number of processes that exist at
				 * *pidPtr right now. */
    int cmdCount;		/* Count of number of distinct commands found
    Tcl_Size cmdCount;		/* Count of number of distinct commands found
				 * in argc/argv. */
    const char *inputLiteral = NULL;
				/* If non-null, then this points to a string
				 * containing input data (specified via <<) to
				 * be piped to the first process in the
				 * pipeline. */
    TclFile inputFile = NULL;	/* If != NULL, gives file to use as input for
456
457
458
459
460
461
462
463


464
465
466
467
468
469
470
456
457
458
459
460
461
462

463
464
465
466
467
468
469
470
471







-
+
+







				 * commands in pipeline. NULL means use
				 * stderr. */
    int errorClose = 0;		/* If non-zero, then errorFile should be
				 * closed when cleaning up. */
    int errorRelease = 0;
    const char *p;
    const char *nextArg;
    int skip, lastBar, lastArg, i, j, atOK, flags, needCmd, errorToOutput = 0;
    int skip, atOK, flags, needCmd, errorToOutput = 0;
    Tcl_Size i, j, lastArg, lastBar;
    Tcl_DString execBuffer;
    TclFile pipeIn;
    TclFile curInFile, curOutFile, curErrFile;
    Tcl_Channel channel;

    if (inPipePtr != NULL) {
	*inPipePtr = NULL;
485
486
487
488
489
490
491
492

493
494
495
496
497
498
499
486
487
488
489
490
491
492

493
494
495
496
497
498
499
500







-
+








    /*
     * First, scan through all the arguments to figure out the structure of
     * the pipeline. Process all of the input and output redirection arguments
     * and remove them from the argument list in the pipeline. Count the
     * number of distinct processes (it's the number of "|" arguments plus
     * one) but don't remove the "|" arguments because they'll be used in the
     * second pass to seperate the individual child processes. Cannot start
     * second pass to separate the individual child processes. Cannot start
     * the child processes in this pass because the redirection symbols may
     * appear anywhere in the command line - e.g., the '<' that specifies the
     * input to the entire pipe may appear at the very end of the argument
     * list.
     */

    lastBar = -1;
509
510
511
512
513
514
515
516

517
518
519
520
521
522
523
510
511
512
513
514
515
516

517
518
519
520
521
522
523
524







-
+







		p++;
	    }
	    if (*p == '\0') {
		if ((i == (lastBar + 1)) || (i == (argc - 1))) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "illegal use of | or |& in command", -1));
		    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC",
			    "PIPESYNTAX", NULL);
			    "PIPESYNTAX", (char *)NULL);
		    goto error;
		}
	    }
	    lastBar = i;
	    cmdCount++;
	    needCmd = 1;
	    break;
538
539
540
541
542
543
544
545

546
547
548
549
550
551
552
539
540
541
542
543
544
545

546
547
548
549
550
551
552
553







-
+







		if (*inputLiteral == '\0') {
		    inputLiteral = ((i + 1) == argc) ? NULL : argv[i + 1];
		    if (inputLiteral == NULL) {
			Tcl_SetObjResult(interp, Tcl_ObjPrintf(
				"can't specify \"%s\" as last word in command",
				argv[i]));
			Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC",
				"PIPESYNTAX", NULL);
				"PIPESYNTAX", (char *)NULL);
			goto error;
		    }
		    skip = 2;
		}
	    } else {
		nextArg = ((i + 1) == argc) ? NULL : argv[i + 1];
		inputLiteral = NULL;
655
656
657
658
659
660
661
662

663
664
665
666
667
668
669
656
657
658
659
660
661
662

663
664
665
666
667
668
669
670







-
+







		 */

		if (i != argc-1) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "must specify \"%s\" as last word in command",
			    argv[i]));
		    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC",
			    "PIPESYNTAX", NULL);
			    "PIPESYNTAX", (char *)NULL);
		    goto error;
		}
		errorFile = outputFile;
		errorToOutput = 2;
		skip = 1;
	    } else {
		nextArg = ((i + 1) == argc) ? NULL : argv[i + 1];
697
698
699
700
701
702
703
704

705
706
707
708
709
710
711
698
699
700
701
702
703
704

705
706
707
708
709
710
711
712







-
+







	/*
	 * We had a bar followed only by redirections.
	 */

	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"illegal use of | or |& in command", -1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "PIPESYNTAX",
		NULL);
		(char *)NULL);
	goto error;
    }

    if (inputFile == NULL) {
	if (inputLiteral != NULL) {
	    /*
	     * The input for the first process is immediate data coming from
970
971
972
973
974
975
976
977

978
979
980
981
982
983
984
971
972
973
974
975
976
977

978
979
980
981
982
983
984
985







-
+







    }
    if ((errFilePtr != NULL) && (*errFilePtr != NULL)) {
	TclpCloseFile(*errFilePtr);
	*errFilePtr = NULL;
    }
    if (pidPtr != NULL) {
	for (i = 0; i < numPids; i++) {
	    if (pidPtr[i] != (Tcl_Pid) -1) {
	    if (pidPtr[i] != (Tcl_Pid)-1) {
		Tcl_DetachPids(1, &pidPtr[i]);
	    }
	}
	Tcl_Free(pidPtr);
    }
    numPids = -1;
    goto cleanup;
1016
1017
1018
1019
1020
1021
1022
1023

1024
1025
1026
1027
1028
1029
1030
1031


1032
1033
1034
1035
1036
1037
1038
1017
1018
1019
1020
1021
1022
1023

1024
1025
1026
1027
1028
1029
1030


1031
1032
1033
1034
1035
1036
1037
1038
1039







-
+






-
-
+
+







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

Tcl_Channel
Tcl_OpenCommandChannel(
    Tcl_Interp *interp,		/* Interpreter for error reporting. Can NOT be
				 * NULL. */
    int argc,			/* How many arguments. */
    Tcl_Size argc,		/* How many arguments. */
    const char **argv,		/* Array of arguments for command pipe. */
    int flags)			/* Or'ed combination of TCL_STDIN, TCL_STDOUT,
				 * TCL_STDERR, and TCL_ENFORCE_MODE. */
{
    TclFile *inPipePtr, *outPipePtr, *errFilePtr;
    TclFile inPipe, outPipe, errFile;
    int numPids;
    Tcl_Pid *pidPtr;
    Tcl_Size numPids;
    Tcl_Pid *pidPtr = NULL;
    Tcl_Channel channel;

    inPipe = outPipe = errFile = NULL;

    inPipePtr = (flags & TCL_STDIN) ? &inPipe : NULL;
    outPipePtr = (flags & TCL_STDOUT) ? &outPipe : NULL;
    errFilePtr = (flags & TCL_STDERR) ? &errFile : NULL;
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
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







-
+







-
+










-
+





-
+








    if (flags & TCL_ENFORCE_MODE) {
	if ((flags & TCL_STDOUT) && (outPipe == NULL)) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "can't read output from command:"
		    " standard output was redirected", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC",
		    "BADREDIRECT", NULL);
		    "BADREDIRECT", (char *)NULL);
	    goto error;
	}
	if ((flags & TCL_STDIN) && (inPipe == NULL)) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "can't write input to command:"
		    " standard input was redirected", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC",
		    "BADREDIRECT", NULL);
		    "BADREDIRECT", (char *)NULL);
	    goto error;
	}
    }

    channel = TclpCreateCommandChannel(outPipe, inPipe, errFile,
	    numPids, pidPtr);

    if (channel == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"pipe for command could not be created", -1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "NOPIPE", NULL);
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "NOPIPE", (char *)NULL);
	goto error;
    }
    return channel;

  error:
    if (numPids > 0) {
    if (pidPtr) {
	Tcl_DetachPids(numPids, pidPtr);
	Tcl_Free(pidPtr);
    }
    if (inPipe != NULL) {
	TclpCloseFile(inPipe);
    }
    if (outPipe != NULL) {

Changes to generic/tclPkg.c.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * tclPkg.c --
 *
 *	This file implements package and version control for Tcl via the
 *	"package" command and a few C APIs.
 *
 * Copyright (c) 1996 Sun Microsystems, Inc.
 * Copyright (c) 2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>
 * Copyright © 1996 Sun Microsystems, Inc.
 * Copyright © 2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * TIP #268.
 * Heavily rewritten to handle the extend version numbers, and extended
 * package requirements.
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
36
37
38
39
40
41
42

43
44
45
46
47
48
49
50







-
+







    struct PkgAvail *nextPtr;	/* Next in list of available versions of the
				 * same package. */
} PkgAvail;

typedef struct PkgName {
    struct PkgName *nextPtr;	/* Next in list of package names being
				 * initialized. */
    char name[1];
    char name[TCLFLEXARRAY];
} PkgName;

typedef struct PkgFiles {
    PkgName *names;		/* Package names being initialized. Must be
				 * first field. */
    Tcl_HashTable table;	/* Table which contains files for each
				 * package. */
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107









108
109
110
111
112
113
114
92
93
94
95
96
97
98









99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114







-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+







static int		SomeRequirementSatisfied(char *havei, int reqc,
			    Tcl_Obj *const reqv[]);
static void		AddRequirementsToResult(Tcl_Interp *interp, int reqc,
			    Tcl_Obj *const reqv[]);
static void		AddRequirementsToDString(Tcl_DString *dstring,
			    int reqc, Tcl_Obj *const reqv[]);
static Package *	FindPackage(Tcl_Interp *interp, const char *name);
static int		PkgRequireCore(ClientData data[], Tcl_Interp *interp, int result);
static int		PkgRequireCoreFinal(ClientData data[], Tcl_Interp *interp, int result);
static int		PkgRequireCoreCleanup(ClientData data[], Tcl_Interp *interp, int result);
static int		PkgRequireCoreStep1(ClientData data[], Tcl_Interp *interp, int result);
static int		PkgRequireCoreStep2(ClientData data[], Tcl_Interp *interp, int result);
static int		TclNRPkgRequireProc(ClientData clientData, Tcl_Interp *interp, int reqc, Tcl_Obj *const reqv[]);
static int		SelectPackage(ClientData data[], Tcl_Interp *interp, int result);
static int		SelectPackageFinal(ClientData data[], Tcl_Interp *interp, int result);
static int		TclNRPackageObjCmdCleanup(ClientData data[], Tcl_Interp *interp, int result);
static int		PkgRequireCore(void *data[], Tcl_Interp *interp, int result);
static int		PkgRequireCoreFinal(void *data[], Tcl_Interp *interp, int result);
static int		PkgRequireCoreCleanup(void *data[], Tcl_Interp *interp, int result);
static int		PkgRequireCoreStep1(void *data[], Tcl_Interp *interp, int result);
static int		PkgRequireCoreStep2(void *data[], Tcl_Interp *interp, int result);
static int		TclNRPkgRequireProc(void *clientData, Tcl_Interp *interp, int reqc, Tcl_Obj *const reqv[]);
static int		SelectPackage(void *data[], Tcl_Interp *interp, int result);
static int		SelectPackageFinal(void *data[], Tcl_Interp *interp, int result);
static int		TclNRPackageObjCmdCleanup(void *data[], Tcl_Interp *interp, int result);

/*
 * Helper macros.
 */

#define DupBlock(v,s,len) \
    ((v) = (char *)Tcl_Alloc(len), memcpy((v),(s),(len)))
188
189
190
191
192
193
194
195

196
197
198
199
200
201
202
188
189
190
191
192
193
194

195
196
197
198
199
200
201
202







-
+







	    pkgPtr->clientData = clientData;
	}
	return TCL_OK;
    }
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "conflicting versions provided for package \"%s\": %s, then %s",
	    name, Tcl_GetString(pkgPtr->version), version));
    Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "VERSIONCONFLICT", NULL);
    Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "VERSIONCONFLICT", (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_PkgRequire / Tcl_PkgRequireEx / Tcl_PkgRequireProc --
221
222
223
224
225
226
227
228

229
230
231
232
233
234
235
221
222
223
224
225
226
227

228
229
230
231
232
233
234
235







-
+







 *	invoked to provide the package.
 *
 *----------------------------------------------------------------------
 */

static void
PkgFilesCleanupProc(
    ClientData clientData,
    void *clientData,
    TCL_UNUSED(Tcl_Interp *))
{
    PkgFiles *pkgFiles = (PkgFiles *) clientData;
    Tcl_HashSearch search;
    Tcl_HashEntry *entry;

    while (pkgFiles->names) {
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
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
467
468
469
470
471
472
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
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
467
468
469
470
471
472







-
+









-
+









-
+



-
+












-
+















-
+














-
+




-
+







	 * reliably, so be very careful about adding any other calls here
	 * without checking how they behave when initialization is incomplete.
	 */

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"Cannot load package \"%s\" in standalone executable:"
		" This package is not compiled with stub support", name));
	Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNSTUBBED", NULL);
	Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNSTUBBED", (char *)NULL);
	return NULL;
    }

    /*
     * Translate between old and new API, and defer to the new function.
     */

    if (version == NULL) {
	if (Tcl_PkgRequireProc(interp, name, 0, NULL, clientDataPtr) == TCL_OK) {
	    result = Tcl_GetString(Tcl_GetObjResult(interp));
	    result = Tcl_GetStringResult(interp);
	    Tcl_ResetResult(interp);
	}
    } else {
	if (exact && TCL_OK
		!= CheckVersionAndConvert(interp, version, NULL, NULL)) {
	    return NULL;
	}
	ov = Tcl_NewStringObj(version, -1);
	if (exact) {
	    Tcl_AppendStringsToObj(ov, "-", version, NULL);
	    Tcl_AppendStringsToObj(ov, "-", version, (char *)NULL);
	}
	Tcl_IncrRefCount(ov);
	if (Tcl_PkgRequireProc(interp, name, 1, &ov, clientDataPtr) == TCL_OK) {
	    result = Tcl_GetString(Tcl_GetObjResult(interp));
	    result = Tcl_GetStringResult(interp);
	    Tcl_ResetResult(interp);
	}
	TclDecrRefCount(ov);
    }
    return result;
}

int
Tcl_PkgRequireProc(
    Tcl_Interp *interp,		/* Interpreter in which package is now
				 * available. */
    const char *name,		/* Name of desired package. */
    int reqc,			/* Requirements constraining the desired
    Tcl_Size reqc,		/* Requirements constraining the desired
				 * version. */
    Tcl_Obj *const reqv[],	/* 0 means to use the latest version
				 * available. */
    void *clientDataPtr)
{
    RequireProcArgs args;

    args.name = name;
    args.clientDataPtr = clientDataPtr;
    return Tcl_NRCallObjProc(interp,
	    TclNRPkgRequireProc, (void *) &args, reqc, reqv);
}

static int
TclNRPkgRequireProc(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int reqc,
    Tcl_Obj *const reqv[])
{
    RequireProcArgs *args = (RequireProcArgs *)clientData;

    Tcl_NRAddCallback(interp,
	    PkgRequireCore, (void *) args->name, INT2PTR(reqc), (void *) reqv,
	    args->clientDataPtr);
    return TCL_OK;
}

static int
PkgRequireCore(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int))
{
    const char *name = (const char *)data[0];
    int reqc = PTR2INT(data[1]);
    int reqc = (int)PTR2INT(data[1]);
    Tcl_Obj **reqv = (Tcl_Obj **)data[2];
    int code = CheckAllRequirements(interp, reqc, reqv);
    Require *reqPtr;

    if (code != TCL_OK) {
	return code;
    }
484
485
486
487
488
489
490
491

492
493
494
495
496
497
498

499
500
501
502
503
504
505
484
485
486
487
488
489
490

491
492
493
494
495
496
497

498
499
500
501
502
503
504
505







-
+






-
+







		PkgRequireCoreFinal, reqPtr, INT2PTR(reqc), reqv, NULL);
    }
    return TCL_OK;
}

static int
PkgRequireCoreStep1(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int))
{
    Tcl_DString command;
    char *script;
    Require *reqPtr = (Require *)data[0];
    int reqc = PTR2INT(data[1]);
    int reqc = (int)PTR2INT(data[1]);
    Tcl_Obj **const reqv = (Tcl_Obj **)data[2];
    const char *name = reqPtr->name /* Name of desired package. */;

    /*
     * If we've got the package in the DB already, go on to actually loading
     * it.
     */
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
558
559
560
561
562

563
564
565
566
567
568
569
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

558
559
560
561
562
563
564
565







-
+
-
-
-
-





-
+




-
+






-
+







    Tcl_DStringInit(&command);
    Tcl_DStringAppend(&command, script, -1);
    Tcl_DStringAppendElement(&command, name);
    AddRequirementsToDString(&command, reqc, reqv);

    Tcl_NRAddCallback(interp,
	    PkgRequireCoreStep2, reqPtr, INT2PTR(reqc), (void *) reqv, NULL);
    Tcl_NREvalObj(interp,
    Tcl_NREvalObj(interp, Tcl_DStringToObj(&command), TCL_EVAL_GLOBAL);
	    Tcl_NewStringObj(Tcl_DStringValue(&command),
		    Tcl_DStringLength(&command)),
	    TCL_EVAL_GLOBAL);
    Tcl_DStringFree(&command);
    return TCL_OK;
}

static int
PkgRequireCoreStep2(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Require *reqPtr = (Require *)data[0];
    int reqc = PTR2INT(data[1]);
    int reqc = (int)PTR2INT(data[1]);
    Tcl_Obj **const reqv = (Tcl_Obj **)data[2];
    const char *name = reqPtr->name; /* Name of desired package. */

    if ((result != TCL_OK) && (result != TCL_ERROR)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"bad return code: %d", result));
	Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL);
	Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", (char *)NULL);
	result = TCL_ERROR;
    }
    if (result == TCL_ERROR) {
	Tcl_AddErrorInfo(interp,
		"\n    (\"package unknown\" script)");
	return result;
    }
578
579
580
581
582
583
584
585

586
587
588
589
590

591
592
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620

621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637

638
639
640
641
642
643
644
645
646
647

648
649
650
651
652
653
654
655
656

657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673

674
675
676
677
678
679
680
574
575
576
577
578
579
580

581
582
583
584
585

586
587
588
589
590
591
592
593
594

595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615

616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632

633
634
635
636
637
638
639
640
641
642

643
644
645
646
647
648
649
650
651

652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668

669
670
671
672
673
674
675
676







-
+




-
+








-
+




















-
+
















-
+









-
+








-
+
















-
+







	    SelectPackage, reqPtr, INT2PTR(reqc), reqv,
	    (void *)PkgRequireCoreFinal);
    return TCL_OK;
}

static int
PkgRequireCoreFinal(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int))
{
    Require *reqPtr = (Require *)data[0];
    int reqc = PTR2INT(data[1]), satisfies;
    int reqc = (int)PTR2INT(data[1]), satisfies;
    Tcl_Obj **const reqv = (Tcl_Obj **)data[2];
    char *pkgVersionI;
    void *clientDataPtr = reqPtr->clientDataPtr;
    const char *name = reqPtr->name; /* Name of desired package. */

    if (reqPtr->pkgPtr->version == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't find package %s", name));
	Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNFOUND", NULL);
	Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNFOUND", (char *)NULL);
	AddRequirementsToResult(interp, reqc, reqv);
	return TCL_ERROR;
    }

    /*
     * Ensure that the provided version meets the current requirements.
     */

    if (reqc != 0) {
	CheckVersionAndConvert(interp, Tcl_GetString(reqPtr->pkgPtr->version),
		&pkgVersionI, NULL);
	satisfies = SomeRequirementSatisfied(pkgVersionI, reqc, reqv);

	Tcl_Free(pkgVersionI);

	if (!satisfies) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "version conflict for package \"%s\": have %s, need",
		    name, Tcl_GetString(reqPtr->pkgPtr->version)));
	    Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "VERSIONCONFLICT",
		    NULL);
		    (char *)NULL);
	    AddRequirementsToResult(interp, reqc, reqv);
	    return TCL_ERROR;
	}
    }

    if (clientDataPtr) {
	const void **ptr = (const void **) clientDataPtr;

	*ptr = reqPtr->pkgPtr->clientData;
    }
    Tcl_SetObjResult(interp, reqPtr->pkgPtr->version);
    return TCL_OK;
}

static int
PkgRequireCoreCleanup(
    ClientData data[],
    void *data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    Tcl_Free(data[0]);
    return result;
}

static int
SelectPackage(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int))
{
    PkgAvail *availPtr, *bestPtr, *bestStablePtr;
    char *availVersion, *bestVersion, *bestStableVersion;
				/* Internal rep. of versions */
    int availStable, satisfies;
    Require *reqPtr = (Require *)data[0];
    int reqc = PTR2INT(data[1]);
    int reqc = (int)PTR2INT(data[1]);
    Tcl_Obj **const reqv = (Tcl_Obj **)data[2];
    const char *name = reqPtr->name;
    Package *pkgPtr = reqPtr->pkgPtr;
    Interp *iPtr = (Interp *) interp;

    /*
     * Check whether we're already attempting to load some version of this
     * package (circular dependency detection).
     */

    if (pkgPtr->clientData != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"circular package dependency:"
		" attempt to provide %s %s requires %s",
		name, (char *) pkgPtr->clientData, name));
	AddRequirementsToResult(interp, reqc, reqv);
	Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "CIRCULARITY", NULL);
	Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "CIRCULARITY", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * The package isn't yet present. Search the list of available versions
     * and invoke the script for the best available version. We are actually
     * locating the best, and the best stable version. One of them is then
824
825
826
827
828
829
830
831

832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850

851
852
853
854
855

856
857
858
859
860
861
862
820
821
822
823
824
825
826

827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845

846
847
848
849
850

851
852
853
854
855
856
857
858







-
+


















-
+




-
+








	pkgFiles = (PkgFiles *)TclInitPkgFiles(interp);

	/*
	 * Push "ifneeded" package name in "tclPkgFiles" assocdata.
	 */

	pkgName = (PkgName *)Tcl_Alloc(sizeof(PkgName) + strlen(name));
	pkgName = (PkgName *)Tcl_Alloc(offsetof(PkgName, name) + 1 + strlen(name));
	pkgName->nextPtr = pkgFiles->names;
	strcpy(pkgName->name, name);
	pkgFiles->names = pkgName;
	if (bestPtr->pkgIndex) {
	    TclPkgFileSeen(interp, bestPtr->pkgIndex);
	}
	reqPtr->versionToProvide = versionToProvide;
	Tcl_NRAddCallback(interp,
		SelectPackageFinal, reqPtr, INT2PTR(reqc), (void *)reqv,
		data[3]);
	Tcl_NREvalObj(interp, Tcl_NewStringObj(bestPtr->script, -1),
		TCL_EVAL_GLOBAL);
    }
    return TCL_OK;
}

static int
SelectPackageFinal(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Require *reqPtr = (Require *)data[0];
    int reqc = PTR2INT(data[1]);
    int reqc = (int)PTR2INT(data[1]);
    Tcl_Obj **const reqv = (Tcl_Obj **)data[2];
    const char *name = reqPtr->name;
    char *versionToProvide = reqPtr->versionToProvide;

    /*
     * Pop the "ifneeded" package name from "tclPkgFiles" assocdata
     */
872
873
874
875
876
877
878
879

880
881
882
883
884
885
886
868
869
870
871
872
873
874

875
876
877
878
879
880
881
882







-
+







	if (reqPtr->pkgPtr->version == NULL) {
	    result = TCL_ERROR;
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "attempt to provide package %s %s failed:"
		    " no version of package %s provided",
		    name, versionToProvide, name));
	    Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNPROVIDED",
		    NULL);
		    (char *)NULL);
	} else {
	    char *pvi, *vi;

	    if (TCL_OK != CheckVersionAndConvert(interp,
		    Tcl_GetString(reqPtr->pkgPtr->version), &pvi, NULL)) {
		result = TCL_ERROR;
	    } else if (CheckVersionAndConvert(interp,
896
897
898
899
900
901
902
903

904
905
906
907
908
909
910
911
912
913
914
915

916
917
918
919
920
921
922
892
893
894
895
896
897
898

899
900
901
902
903
904
905
906
907
908
909
910

911
912
913
914
915
916
917
918







-
+











-
+







		    result = TCL_ERROR;
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "attempt to provide package %s %s failed:"
			    " package %s %s provided instead",
			    name, versionToProvide,
			    name, Tcl_GetString(reqPtr->pkgPtr->version)));
		    Tcl_SetErrorCode(interp, "TCL", "PACKAGE",
			    "WRONGPROVIDE", NULL);
			    "WRONGPROVIDE", (char *)NULL);
		}
	    }
	}
    } else if (result != TCL_ERROR) {
	Tcl_Obj *codePtr;

	TclNewIntObj(codePtr, result);
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"attempt to provide package %s %s failed:"
		" bad return code: %s",
		name, versionToProvide, TclGetString(codePtr)));
	Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL);
	Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", (char *)NULL);
	TclDecrRefCount(codePtr);
	result = TCL_ERROR;
    }

    if (result == TCL_ERROR) {
	Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
		"\n    (\"package ifneeded %s %s\" script)",
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
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







-
+












-
+







	     */

	    const char *foundVersion = Tcl_PkgRequireEx(interp, name, version,
		    exact, clientDataPtr);

	    if (foundVersion == NULL) {
		Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PACKAGE", name,
			NULL);
			(char *)NULL);
	    }
	    return foundVersion;
	}
    }

    if (version != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"package %s %s is not present", name, version));
    } else {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"package %s is not present", name));
    }
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PACKAGE", name, NULL);
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PACKAGE", name, (char *)NULL);
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_PackageObjCmd --
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
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







-
+









-
+













-
+

-
+
+



















-
+







 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */
int
Tcl_PackageObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, TclNRPackageObjCmd, clientData, objc, objv);
}

int
TclNRPackageObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static const char *const pkgOptions[] = {
	"files",  "forget",  "ifneeded", "names",   "prefer",
	"present", "provide", "require",  "unknown", "vcompare",
	"versions", "vsatisfies", NULL
    };
    enum pkgOptionsEnum {
	PKG_FILES,  PKG_FORGET,  PKG_IFNEEDED, PKG_NAMES,   PKG_PREFER,
	PKG_PRESENT, PKG_PROVIDE, PKG_REQUIRE,  PKG_UNKNOWN, PKG_VCOMPARE,
	PKG_VERSIONS, PKG_VSATISFIES
    };
    } optionIndex;
    Interp *iPtr = (Interp *) interp;
    int optionIndex, exact, i, newobjc, satisfies;
    int exact, satisfies;
    Tcl_Size i, newobjc;
    PkgAvail *availPtr, *prevPtr;
    Package *pkgPtr;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    Tcl_HashTable *tablePtr;
    const char *version;
    const char *argv2, *argv3, *argv4;
    char *iva = NULL, *ivb = NULL;
    Tcl_Obj *objvListPtr, **newObjvPtr;

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

    if (Tcl_GetIndexFromObj(interp, objv[1], pkgOptions, "option", 0,
	    &optionIndex) != TCL_OK) {
	return TCL_ERROR;
    }
    switch ((enum pkgOptionsEnum) optionIndex) {
    switch (optionIndex) {
    case PKG_FILES: {
	PkgFiles *pkgFiles;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "package");
	    return TCL_ERROR;
	}
1155
1156
1157
1158
1159
1160
1161
1162

1163
1164
1165
1166
1167
1168
1169
1152
1153
1154
1155
1156
1157
1158

1159
1160
1161
1162
1163
1164
1165
1166







-
+







		Tcl_Free(availPtr);
	    }
	    Tcl_Free(pkgPtr);
	}
	break;
    }
    case PKG_IFNEEDED: {
	size_t length;
	Tcl_Size length;
	int res;
	char *argv3i, *avi;

	if ((objc != 4) && (objc != 5)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "package version ?script?");
	    return TCL_ERROR;
	}
1349
1350
1351
1352
1353
1354
1355
1356

1357
1358
1359
1360
1361
1362
1363
1364

1365
1366
1367
1368
1369
1370
1371
1346
1347
1348
1349
1350
1351
1352

1353
1354
1355
1356
1357
1358
1359
1360

1361
1362
1363
1364
1365
1366
1367
1368







-
+







-
+







	    }

	    /*
	     * Create a new-style requirement for the exact version.
	     */

	    ov = Tcl_NewStringObj(version, -1);
	    Tcl_AppendStringsToObj(ov, "-", version, NULL);
	    Tcl_AppendStringsToObj(ov, "-", version, (char *)NULL);
	    version = NULL;
	    argv3 = TclGetString(objv[3]);
	    Tcl_IncrRefCount(objv[3]);

	    objvListPtr = Tcl_NewListObj(0, NULL);
	    Tcl_IncrRefCount(objvListPtr);
	    Tcl_ListObjAppendElement(interp, objvListPtr, ov);
	    Tcl_ListObjGetElements(interp, objvListPtr, &newobjc, &newObjvPtr);
	    TclListObjGetElements(interp, objvListPtr, &newobjc, &newObjvPtr);

	    Tcl_NRAddCallback(interp,
		    TclNRPackageObjCmdCleanup, objv[3], objvListPtr, NULL,NULL);
	    Tcl_NRAddCallback(interp,
		    PkgRequireCore, (void *) argv3, INT2PTR(newobjc),
		    newObjvPtr, NULL);
	    return TCL_OK;
1384
1385
1386
1387
1388
1389
1390
1391

1392
1393
1394
1395
1396
1397
1398
1399
1400
1401

1402
1403
1404
1405
1406
1407
1408
1381
1382
1383
1384
1385
1386
1387

1388
1389
1390
1391
1392
1393
1394
1395
1396
1397

1398
1399
1400
1401
1402
1403
1404
1405







-
+









-
+







		 * Tcl_Obj structures may have come from another interpreter,
		 * so duplicate them.
		 */

		Tcl_ListObjAppendElement(interp, objvListPtr,
			Tcl_DuplicateObj(newobjv[i]));
	    }
	    Tcl_ListObjGetElements(interp, objvListPtr, &newobjc, &newObjvPtr);
	    TclListObjGetElements(interp, objvListPtr, &newobjc, &newObjvPtr);
	    Tcl_NRAddCallback(interp,
		    TclNRPackageObjCmdCleanup, objv[2], objvListPtr, NULL,NULL);
	    Tcl_NRAddCallback(interp,
		    PkgRequireCore, (void *) argv2, INT2PTR(newobjc),
		    newObjvPtr, NULL);
	    return TCL_OK;
	}
	break;
    case PKG_UNKNOWN: {
	size_t length;
	Tcl_Size length;

	if (objc == 2) {
	    if (iPtr->packageUnknown != NULL) {
		Tcl_SetObjResult(interp,
			Tcl_NewStringObj(iPtr->packageUnknown, -1));
	    }
	} else if (objc == 3) {
1534
1535
1536
1537
1538
1539
1540
1541

1542
1543
1544
1545
1546
1547
1548
1531
1532
1533
1534
1535
1536
1537

1538
1539
1540
1541
1542
1543
1544
1545







-
+







	Tcl_Panic("Tcl_PackageObjCmd: bad option index to pkgOptions");
    }
    return TCL_OK;
}

static int
TclNRPackageObjCmdCleanup(
    ClientData data[],
    void *data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    TclDecrRefCount((Tcl_Obj *) data[0]);
    TclDecrRefCount((Tcl_Obj *) data[1]);
    return result;
}
1669
1670
1671
1672
1673
1674
1675
1676

1677
1678
1679
1680
1681
1682
1683
1666
1667
1668
1669
1670
1671
1672

1673
1674
1675
1676
1677
1678
1679
1680







-
+







    int *stable)		/* Flag: Version is (un)stable. */
{
    const char *p = string;
    char prevChar;
    int hasunstable = 0;
    /*
     * 4* assuming that each char is a separator (a,b become ' -x ').
     * 4+ to have spce for an additional -2 at the end
     * 4+ to have space for an additional -2 at the end
     */
    char *ibuf = (char *)Tcl_Alloc(4 + 4*strlen(string));
    char *ip = ibuf;

    /*
     * Basic rules
     * (1) First character has to be a digit.
1694
1695
1696
1697
1698
1699
1700
1701

1702
1703
1704
1705
1706
1707
1708
1691
1692
1693
1694
1695
1696
1697

1698
1699
1700
1701
1702
1703
1704
1705







-
+








    if (!isdigit(UCHAR(*p))) {				/* INTL: digit */
	goto error;
    }

    *ip++ = *p;

    for (prevChar = *p, p++; *p != 0; p++) {
    for (prevChar = *p, p++; (*p != 0) && (*p != '+'); p++) {
	if (!isdigit(UCHAR(*p)) &&			/* INTL: digit */
		((*p!='.' && *p!='a' && *p!='b') ||
		((hasunstable && (*p=='a' || *p=='b')) ||
		((prevChar=='a' || prevChar=='b' || prevChar=='.')
			&& (*p=='.')) ||
		((*p=='a' || *p=='b' || *p=='.') && prevChar=='.')))) {
	    goto error;
1751
1752
1753
1754
1755
1756
1757
1758

1759
1760
1761
1762
1763
1764
1765
1748
1749
1750
1751
1752
1753
1754

1755
1756
1757
1758
1759
1760
1761
1762







-
+







	return TCL_OK;
    }

  error:
    Tcl_Free(ibuf);
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "expected version number but got \"%s\"", string));
    Tcl_SetErrorCode(interp, "TCL", "VALUE", "VERSION", NULL);
    Tcl_SetErrorCode(interp, "TCL", "VALUE", "VERSION", (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * CompareVersions --
1780
1781
1782
1783
1784
1785
1786
1787

1788
1789
1790
1791
1792
1793
1794
1777
1778
1779
1780
1781
1782
1783

1784
1785
1786
1787
1788
1789
1790
1791







-
+








static int
CompareVersions(
    char *v1, char *v2,		/* Versions strings, of form 2.1.3 (any number
				 * of version numbers). */
    int *isMajorPtr)		/* If non-null, the word pointed to is filled
				 * in with a 0/1 value. 1 means that the
				 * difference occured in the first element. */
				 * difference occurred in the first element. */
{
    int thisIsMajor, res, flip;
    char *s1, *e1, *s2, *e2, o1, o2;

    /*
     * Each iteration of the following loop processes one number from each
     * string, terminated by a " " (space). If those numbers don't match then
1998
1999
2000
2001
2002
2003
2004
2005

2006
2007
2008

2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021

2022
2023
2024
2025
2026
2027
2028
1995
1996
1997
1998
1999
2000
2001

2002
2003
2004

2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017

2018
2019
2020
2021
2022
2023
2024
2025







-
+


-
+












-
+







     * Syntax of requirement = version
     *			     = version-version
     *			     = version-
     */

    char *dash = NULL, *buf;

    dash = (char *)strchr(string, '-');
    dash = strchr(string, '+') ? NULL : (char *)strchr(string, '-');
    if (dash == NULL) {
	/*
	 * No dash found, has to be a simple version.
	 * '+' found or no dash found: has to be a simple version.
	 */

	return CheckVersionAndConvert(interp, string, NULL, NULL);
    }

    if (strchr(dash+1, '-') != NULL) {
	/*
	 * More dashes found after the first. This is wrong.
	 */

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"expected versionMin-versionMax but got \"%s\"", string));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "VERSIONRANGE", NULL);
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "VERSIONRANGE", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Exactly one dash is present. Copy the string, split at the location of
     * dash and check that both parts are versions. Note that the max part can
     * be empty. Also note that the string allocated with strdup() must be
2067
2068
2069
2070
2071
2072
2073
2074

2075
2076
2077
2078
2079
2080
2081
2064
2065
2066
2067
2068
2069
2070

2071
2072
2073
2074
2075
2076
2077
2078







-
+







    int reqc,			/* Requirements constraining the desired
				 * version. */
    Tcl_Obj *const reqv[])	/* 0 means to use the latest version
				 * available. */
{
    Tcl_Obj *result = Tcl_GetObjResult(interp);
    int i;
    size_t length;
    Tcl_Size length;

    for (i = 0; i < reqc; i++) {
	const char *v = TclGetStringFromObj(reqv[i], &length);

	if ((length & 0x1) && (v[length/2] == '-')
		&& (strncmp(v, v+((length+1)/2), length/2) == 0)) {
	    Tcl_AppendPrintfToObj(result, " exactly %s", v+((length+1)/2));
2234
2235
2236
2237
2238
2239
2240
2241

2242
2243
2244
2245
2246
2247
2248
2231
2232
2233
2234
2235
2236
2237

2238
2239
2240
2241
2242
2243
2244
2245







-
+







	Tcl_Free(min);
	Tcl_Free(buf);
	return satisfied;
    }

    /*
     * We have both min and max, and generate their internal reps. When
     * identical we compare as is, otherwise we pad with 'a0' to ove the range
     * identical we compare as is, otherwise we pad with 'a0' to over the range
     * a bit.
     */

    CheckVersionAndConvert(NULL, buf, &min, NULL);
    CheckVersionAndConvert(NULL, dash, &max, NULL);

    if (CompareVersions(min, max, NULL) == 0) {

Changes to generic/tclPkgConfig.c.

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
30
31
32
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
30
31
32




-
+

-
+

















-
+







/*
 * tclPkgConfig.c --
 *
 *	This file contains the configuration information to embed into the tcl
 *	binary library.
 *	library.
 *
 * Copyright (c) 2002 Andreas Kupries <andreas_kupries@users.sourceforge.net>
 * Copyright © 2002 Andreas Kupries <andreas_kupries@users.sourceforge.net>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

/* Note, the definitions in this module are influenced by the following C
 * preprocessor macros:
 *
 * OSCMa  = shortcut for "old style configuration macro activates"
 * NSCMdt = shortcut for "new style configuration macro declares that"
 *
 * - TCL_THREADS		OSCMa compilation as threaded core.
 * - TCL_MEM_DEBUG		OSCMa memory debugging.
 * - TCL_COMPILE_DEBUG		OSCMa debugging of bytecode compiler.
 * - TCL_COMPILE_STATS		OSCMa bytecode compiler statistics.
 *
 * - TCL_CFG_DO64BIT		NSCMdt tcl is compiled for a 64bit system.
 * - NDEBUG		NSCMdt tcl is compiled with symbol info off.
 * - NDEBUG			NSCMdt tcl is compiled with symbol info off.
 * - TCL_CFG_OPTIMIZED		NSCMdt tcl is compiled with cc optimizations on
 * - TCL_CFG_PROFILED		NSCMdt tcl is compiled with profiling info.
 *
 * - CFG_RUNTIME_*		Paths to various stuff at runtime.
 * - CFG_INSTALL_*		Paths to various stuff at installation time.
 *
 * - TCL_CFGVAL_ENCODING	string containing the encoding used for the
105
106
107
108
109
110
111

112
113

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

114
115
116
117
118
119
120
121







+

-
+







    /* Runtime paths to various stuff */

    {"libdir,runtime",		CFG_RUNTIME_LIBDIR},
    {"bindir,runtime",		CFG_RUNTIME_BINDIR},
    {"scriptdir,runtime",	CFG_RUNTIME_SCRDIR},
    {"includedir,runtime",	CFG_RUNTIME_INCDIR},
    {"docdir,runtime",		CFG_RUNTIME_DOCDIR},
#if !defined(STATIC_BUILD)
    {"dllfile,runtime",		CFG_RUNTIME_DLLFILE},
    {"zipfile,runtime",		CFG_RUNTIME_ZIPFILE},
#endif

    /* Installation paths to various stuff */

    {"libdir,install",		CFG_INSTALL_LIBDIR},
    {"bindir,install",		CFG_INSTALL_BINDIR},
    {"scriptdir,install",	CFG_INSTALL_SCRDIR},
    {"includedir,install",	CFG_INSTALL_INCDIR},

Changes to generic/tclPlatDecls.h.

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
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







+
+
+
+
+
+
+
-
+
+









+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+

-
+
+
+
+
+





-

-
-
+
+
+














-



+
+
+
-
+




+
+









+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+




+



	typedef wchar_t TCHAR;
#   else
	typedef char TCHAR;
#   endif
#   define _TCHAR_DEFINED
#endif

#ifndef MODULE_SCOPE
#   ifdef __cplusplus
#	define MODULE_SCOPE extern "C"
#   else
#	define MODULE_SCOPE extern
#   endif
#endif
/* !BEGIN!: Do not edit below this line. */

#if TCL_MAJOR_VERSION < 9

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Exported function declarations:
 */

#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
/* 0 */
EXTERN TCHAR *		Tcl_WinUtfToTChar(const char *str, int len,
				Tcl_DString *dsPtr);
/* 1 */
EXTERN char *		Tcl_WinTCharToUtf(const TCHAR *str, int len,
				Tcl_DString *dsPtr);
/* Slot 2 is reserved */
/* 3 */
EXTERN void		Tcl_WinConvertError(unsigned errCode);
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
/* 0 */
EXTERN int		Tcl_MacOSXOpenBundleResources(Tcl_Interp *interp,
				const char *bundleName, int hasResourceFile,
				Tcl_Size maxPathLen, char *libraryPath);
/* 1 */
EXTERN int		Tcl_MacOSXOpenVersionedBundleResources(
				Tcl_Interp *interp, const char *bundleName,
				const char *bundleVersion,
				int hasResourceFile, Tcl_Size maxPathLen,
				char *libraryPath);
/* 2 */
EXTERN void		Tcl_MacOSXNotifierAddRunLoopMode(
				const void *runLoopMode);
#endif /* MACOSX */

typedef struct TclPlatStubs {
    int magic;
    void *hooks;

#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
    TCHAR * (*tcl_WinUtfToTChar) (const char *str, int len, Tcl_DString *dsPtr); /* 0 */
    char * (*tcl_WinTCharToUtf) (const TCHAR *str, int len, Tcl_DString *dsPtr); /* 1 */
    void (*reserved2)(void);
    void (*tcl_WinConvertError) (unsigned errCode); /* 3 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    int (*tcl_MacOSXOpenBundleResources) (Tcl_Interp *interp, const char *bundleName, int hasResourceFile, Tcl_Size maxPathLen, char *libraryPath); /* 0 */
    int (*tcl_MacOSXOpenVersionedBundleResources) (Tcl_Interp *interp, const char *bundleName, const char *bundleVersion, int hasResourceFile, Tcl_Size maxPathLen, char *libraryPath); /* 1 */
    void (*tcl_MacOSXNotifierAddRunLoopMode) (const void *runLoopMode); /* 2 */
#endif /* MACOSX */
} TclPlatStubs;

extern const TclPlatStubs *tclPlatStubsPtr;

#ifdef __cplusplus
}
#endif

#if defined(USE_TCL_STUBS)

/*
 * Inline function declarations:
 */

#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
#define Tcl_WinUtfToTChar \
	(tclPlatStubsPtr->tcl_WinUtfToTChar) /* 0 */
#define Tcl_WinTCharToUtf \
	(tclPlatStubsPtr->tcl_WinTCharToUtf) /* 1 */
/* Slot 2 is reserved */
#define Tcl_WinConvertError \
	(tclPlatStubsPtr->tcl_WinConvertError) /* 3 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
#define Tcl_MacOSXOpenBundleResources \
	(tclPlatStubsPtr->tcl_MacOSXOpenBundleResources) /* 0 */
#define Tcl_MacOSXOpenVersionedBundleResources \
	(tclPlatStubsPtr->tcl_MacOSXOpenVersionedBundleResources) /* 1 */
#define Tcl_MacOSXNotifierAddRunLoopMode \
	(tclPlatStubsPtr->tcl_MacOSXNotifierAddRunLoopMode) /* 2 */
#endif /* MACOSX */

#endif /* defined(USE_TCL_STUBS) */

#else /* TCL_MAJOR_VERSION > 8 */

/* !BEGIN!: Do not edit below this line. */

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Exported function declarations:
 */

/* Slot 0 is reserved */
/* 1 */
EXTERN int		Tcl_MacOSXOpenVersionedBundleResources(
				Tcl_Interp *interp, const char *bundleName,
				const char *bundleVersion,
				int hasResourceFile, size_t maxPathLen,
				int hasResourceFile, Tcl_Size maxPathLen,
				char *libraryPath);
#endif /* MACOSX */
/* 2 */
EXTERN void		Tcl_MacOSXNotifierAddRunLoopMode(
				const void *runLoopMode);
/* 3 */
EXTERN void		Tcl_WinConvertError(unsigned errCode);

typedef struct TclPlatStubs {
    int magic;
    void *hooks;

#ifdef MAC_OSX_TCL /* MACOSX */
    void (*reserved0)(void);
    int (*tcl_MacOSXOpenVersionedBundleResources) (Tcl_Interp *interp, const char *bundleName, const char *bundleVersion, int hasResourceFile, size_t maxPathLen, char *libraryPath); /* 1 */
#endif /* MACOSX */
    int (*tcl_MacOSXOpenVersionedBundleResources) (Tcl_Interp *interp, const char *bundleName, const char *bundleVersion, int hasResourceFile, Tcl_Size maxPathLen, char *libraryPath); /* 1 */
    void (*tcl_MacOSXNotifierAddRunLoopMode) (const void *runLoopMode); /* 2 */
    void (*tcl_WinConvertError) (unsigned errCode); /* 3 */
} TclPlatStubs;

extern const TclPlatStubs *tclPlatStubsPtr;

#ifdef __cplusplus
}
#endif

#if defined(USE_TCL_STUBS)

/*
 * Inline function declarations:
 */

#ifdef MAC_OSX_TCL /* MACOSX */
/* Slot 0 is reserved */
#define Tcl_MacOSXOpenVersionedBundleResources \
	(tclPlatStubsPtr->tcl_MacOSXOpenVersionedBundleResources) /* 1 */
#define Tcl_MacOSXNotifierAddRunLoopMode \
	(tclPlatStubsPtr->tcl_MacOSXNotifierAddRunLoopMode) /* 2 */
#define Tcl_WinConvertError \
#endif /* MACOSX */
	(tclPlatStubsPtr->tcl_WinConvertError) /* 3 */

#endif /* defined(USE_TCL_STUBS) */

/* !END!: Do not edit above this line. */

#endif /* TCL_MAJOR_VERSION */

#ifdef MAC_OSX_TCL /* MACOSX */
#undef Tcl_MacOSXOpenBundleResources
#define Tcl_MacOSXOpenBundleResources(a,b,c,d,e) Tcl_MacOSXOpenVersionedBundleResources(a,b,NULL,c,d,e)
#endif

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#ifdef _WIN32
#   undef Tcl_CreateFileHandler
#   undef Tcl_DeleteFileHandler
#   undef Tcl_GetOpenFile
#endif
#ifndef MAC_OSX_TCL
#   undef Tcl_MacOSXOpenVersionedBundleResources
#   undef Tcl_MacOSXNotifierAddRunLoopMode
#endif

#if defined(USE_TCL_STUBS) && defined(_WIN32) && !defined(TCL_NO_DEPRECATED)
#if defined(USE_TCL_STUBS) && (defined(_WIN32) || defined(__CYGWIN__))\
	&& (defined(TCL_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8)
#undef Tcl_WinUtfToTChar
#undef Tcl_WinTCharToUtf
#ifdef _WIN32
#define Tcl_WinUtfToTChar(string, len, dsPtr) (Tcl_DStringInit(dsPtr), \
		(TCHAR *)Tcl_UtfToChar16DString((string), (len), (dsPtr)))
#define Tcl_WinTCharToUtf(string, len, dsPtr) (Tcl_DStringInit(dsPtr), \
		(char *)Tcl_Char16ToUtfDString((const unsigned short *)(string), ((((len) + 2) >> 1) - 1), (dsPtr)))
#endif
#endif

#endif /* _TCLPLATDECLS */

Changes to generic/tclPosixStr.c.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * tclPosixStr.c --
 *
 *	This file contains procedures that generate strings corresponding to
 *	various POSIX-related codes, such as errno and signals.
 *
 * Copyright (c) 1991-1994 The Regents of the University of California.
 * Copyright (c) 1994-1996 Sun Microsystems, Inc.
 * Copyright © 1991-1994 The Regents of the University of California.
 * Copyright © 1994-1996 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

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
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







+
+
+












-
-
-


















+
+
+
+
+
+







#endif
#ifdef EALIGN
    case EALIGN: return "EALIGN";
#endif
#if defined(EALREADY) && (!defined(EBUSY) || (EALREADY != EBUSY))
    case EALREADY: return "EALREADY";
#endif
#ifdef EBADCAT
    case EBADCAT: return "EBADCAT";
#endif
#ifdef EBADE
    case EBADE: return "EBADE";
#endif
#ifdef EBADF
    case EBADF: return "EBADF";
#endif
#ifdef EBADFD
    case EBADFD: return "EBADFD";
#endif
#ifdef EBADMSG
    case EBADMSG: return "EBADMSG";
#endif
#ifdef ECANCELED
    case ECANCELED: return "ECANCELED";
#endif
#ifdef EBADR
    case EBADR: return "EBADR";
#endif
#ifdef EBADRPC
    case EBADRPC: return "EBADRPC";
#endif
#ifdef EBADRQC
    case EBADRQC: return "EBADRQC";
#endif
#ifdef EBADSLT
    case EBADSLT: return "EBADSLT";
#endif
#ifdef EBFONT
    case EBFONT: return "EBFONT";
#endif
#ifdef EBUSY
    case EBUSY: return "EBUSY";
#endif
#ifdef ECANCELED
    case ECANCELED: return "ECANCELED";
#endif
#ifdef ECASECLASH
    case ECASECLASH: return "ECASECLASH";
#endif
#ifdef ECHILD
    case ECHILD: return "ECHILD";
#endif
#ifdef ECHRNG
    case ECHRNG: return "ECHRNG";
#endif
#ifdef ECOMM
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
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







+
+
+






+
+
+












+
+
+
+
+
+


















-
+


-
-
-












+
+
+







#endif
#ifdef EDUPPKG
    case EDUPPKG: return "EDUPPKG";
#endif
#ifdef EEXIST
    case EEXIST: return "EEXIST";
#endif
#ifdef EFAIL
    case EFAIL: return "EFAIL";
#endif
#ifdef EFAULT
    case EFAULT: return "EFAULT";
#endif
#ifdef EFBIG
    case EFBIG: return "EFBIG";
#endif
#ifdef EFTYPE
    case EFTYPE: return "EFTYPE";
#endif
#ifdef EHOSTDOWN
    case EHOSTDOWN: return "EHOSTDOWN";
#endif
#ifdef EHOSTUNREACH
    case EHOSTUNREACH: return "EHOSTUNREACH";
#endif
#if defined(EIDRM) && (!defined(EINPROGRESS) || (EIDRM != EINPROGRESS))
    case EIDRM: return "EIDRM";
#endif
#ifdef EINIT
    case EINIT: return "EINIT";
#endif
#ifdef EILSEQ
    case EILSEQ: return "EILSEQ";
#endif
#ifdef EINPROG
    case EINPROG: return "EINPROG";
#endif
#ifdef EINPROGRESS
    case EINPROGRESS: return "EINPROGRESS";
#endif
#ifdef EINTR
    case EINTR: return "EINTR";
#endif
#ifdef EINVAL
    case EINVAL: return "EINVAL";
#endif
#ifdef EIO
    case EIO: return "EIO";
#endif
#ifdef EISCONN
    case EISCONN: return "EISCONN";
#endif
#ifdef EISDIR
    case EISDIR: return "EISDIR";
#endif
#ifdef EISNAME
#ifdef EISNAM
    case EISNAM: return "EISNAM";
#endif
#ifdef ELBIN
    case ELBIN: return "ELBIN";
#endif
#ifdef EL2HLT
    case EL2HLT: return "EL2HLT";
#endif
#ifdef EL2NSYNC
    case EL2NSYNC: return "EL2NSYNC";
#endif
#ifdef EL3HLT
    case EL3HLT: return "EL3HLT";
#endif
#ifdef EL3RST
    case EL3RST: return "EL3RST";
#endif
#ifdef ELBIN
    case ELBIN: return "ELBIN";
#endif
#ifdef ELIBACC
    case ELIBACC: return "ELIBACC";
#endif
#ifdef ELIBBAD
    case ELIBBAD: return "ELIBBAD";
#endif
#ifdef ELIBEXEC
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
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







+
+
+


















-
-
-












+
+
+







#endif
#ifdef ELNRNG
    case ELNRNG: return "ELNRNG";
#endif
#if defined(ELOOP) && (!defined(ENOENT) || (ELOOP != ENOENT))
    case ELOOP: return "ELOOP";
#endif
#ifdef EMEDIUMTYPE
    case EMEDIUMTYPE: return "EMEDIUMTYPE";
#endif
#ifdef EMFILE
    case EMFILE: return "EMFILE";
#endif
#ifdef EMLINK
    case EMLINK: return "EMLINK";
#endif
#ifdef EMSGSIZE
    case EMSGSIZE: return "EMSGSIZE";
#endif
#ifdef EMULTIHOP
    case EMULTIHOP: return "EMULTIHOP";
#endif
#ifdef ENAMETOOLONG
    case ENAMETOOLONG: return "ENAMETOOLONG";
#endif
#ifdef ENAVAIL
    case ENAVAIL: return "ENAVAIL";
#endif
#ifdef ENET
    case ENET: return "ENET";
#endif
#ifdef ENETDOWN
    case ENETDOWN: return "ENETDOWN";
#endif
#ifdef ENETRESET
    case ENETRESET: return "ENETRESET";
#endif
#ifdef ENETUNREACH
    case ENETUNREACH: return "ENETUNREACH";
#endif
#ifdef ENFILE
    case ENFILE: return "ENFILE";
#endif
#ifdef ENMFILE
    case ENMFILE: return "ENMFILE";
#endif
#ifdef ENOANO
    case ENOANO: return "ENOANO";
#endif
#if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR))
    case ENOBUFS: return "ENOBUFS";
#endif
#ifdef ENOCSI
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
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







+
+
+












+
+
+







#endif
#ifdef ENOLINK
    case ENOLINK: return "ENOLINK";
#endif
#ifdef ENOMEM
    case ENOMEM: return "ENOMEM";
#endif
#ifdef ENOMEDIUM
    case ENOMEDIUM: return "ENOMEDIUM";
#endif
#ifdef ENOMSG
    case ENOMSG: return "ENOMSG";
#endif
#ifdef ENONET
    case ENONET: return "ENONET";
#endif
#ifdef ENOPKG
    case ENOPKG: return "ENOPKG";
#endif
#ifdef ENOPROTOOPT
    case ENOPROTOOPT: return "ENOPROTOOPT";
#endif
#ifdef ENOSHARE
    case ENOSHARE: return "ENOSHARE";
#endif
#ifdef ENOSPC
    case ENOSPC: return "ENOSPC";
#endif
#if defined(ENOSR) && (!defined(ENAMETOOLONG) || (ENAMETOOLONG != ENOSR))
    case ENOSR: return "ENOSR";
#endif
#if defined(ENOSTR) && (!defined(ENOTTY) || (ENOTTY != ENOSTR))
331
332
333
334
335
336
337



338
339
340
341
342
343
344
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374







+
+
+







#endif
#ifdef ENOTTY
    case ENOTTY: return "ENOTTY";
#endif
#ifdef ENOTUNIQ
    case ENOTUNIQ: return "ENOTUNIQ";
#endif
#ifdef ENWAIT
    case ENWAIT: return "ENWAIT";
#endif
#ifdef ENXIO
    case ENXIO: return "ENXIO";
#endif
#if defined(EOPNOTSUPP) &&  (!defined(ENOTSUP) || (ENOTSUP != EOPNOTSUPP))
    case EOPNOTSUPP: return "EOPNOTSUPP";
#endif
#ifdef EOTHER
397
398
399
400
401
402
403



404
405
406
407
408
409
410
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443







+
+
+







#endif
#ifdef EREMOTEIO
    case EREMOTEIO: return "EREMOTEIO";
#endif
#ifdef EREMOTERELEASE
    case EREMOTERELEASE: return "EREMOTERELEASE";
#endif
#ifdef ERESTART
    case ERESTART: return "ERESTART";
#endif
#ifdef EROFS
    case EROFS: return "EROFS";
#endif
#ifdef ERPCMISMATCH
    case ERPCMISMATCH: return "ERPCMISMATCH";
#endif
#ifdef ERREMOTE
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
558

559
560
561
562
563
564
565
545
546
547
548
549
550
551

552
553
554
555
556
557
558
559
560

561
562
563

564
565
566
567
568
569

570
571



572

573
574
575
576
577
578

579
580
581
582
583
584
585
586
587

588
589
590
591
592
593
594
595
596

597
598
599
600
601
602
603
604







-
+




+
+
+

-
+


-
+





-
+

-
-
-

-
+





-
+








-
+

+
+
+
+
+
+

-
+







#ifdef EAFNOSUPPORT
    case EAFNOSUPPORT: return "address family not supported by protocol";
#endif
#ifdef EAGAIN
    case EAGAIN: return "resource temporarily unavailable";
#endif
#ifdef EALIGN
    case EALIGN: return "EALIGN";
    case EALIGN: return "alignment error";
#endif
#if defined(EALREADY) && (!defined(EBUSY) || (EALREADY != EBUSY))
    case EALREADY: return "operation already in progress";
#endif
#ifdef EBADCAT
    case EBADCAT: return "bad message catalogue format";
#endif
#ifdef EBADE
    case EBADE: return "bad exchange descriptor";
    case EBADE: return "invalid exchange";
#endif
#ifdef EBADF
    case EBADF: return "bad file number";
    case EBADF: return "bad file descriptor";
#endif
#ifdef EBADFD
    case EBADFD: return "file descriptor in bad state";
#endif
#ifdef EBADMSG
    case EBADMSG: return "not a data message";
    case EBADMSG: return "bad message";
#endif
#ifdef ECANCELED
    case ECANCELED: return "operation canceled";
#endif
#ifdef EBADR
    case EBADR: return "bad request descriptor";
    case EBADR: return "invalid request descriptor";
#endif
#ifdef EBADRPC
    case EBADRPC: return "RPC structure is bad";
#endif
#ifdef EBADRQC
    case EBADRQC: return "bad request code";
    case EBADRQC: return "invalid request code";
#endif
#ifdef EBADSLT
    case EBADSLT: return "invalid slot";
#endif
#ifdef EBFONT
    case EBFONT: return "bad font file format";
#endif
#ifdef EBUSY
    case EBUSY: return "file busy";
    case EBUSY: return "device or resource busy";
#endif
#ifdef ECANCELED
    case ECANCELED: return "operation canceled";
#endif
#ifdef ECASECLASH
    case ECASECLASH: return "filename exists with different case";
#endif
#ifdef ECHILD
    case ECHILD: return "no children";
    case ECHILD: return "no child processes";
#endif
#ifdef ECHRNG
    case ECHRNG: return "channel number out of range";
#endif
#ifdef ECOMM
    case ECOMM: return "communication error on send";
#endif
581
582
583
584
585
586
587
588

589
590
591
592
593
594
595
596
597
598
599
600

601



602
603

604
605
606
607



608
609
610
611
612

613
614
615
616
617
618
619






620
621
622
623
624
625
626
627
628
629
630

631
632
633

634
635
636

637
638
639


640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655



656
657

658
659
660
661
662
663
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
707
708
709

710



711
712

713
714
715
716
717
718
719
620
621
622
623
624
625
626

627
628
629
630
631
632
633
634
635
636
637
638

639
640
641
642
643
644

645
646
647
648
649
650
651
652
653
654
655
656

657
658
659
660
661
662
663
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
707

708
709
710
711
712
713
714
715
716
717

718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749



750
751
752
753
754
755
756
757
758
759

760
761
762
763
764
765

766
767
768
769
770
771
772
773







-
+











-
+

+
+
+

-
+




+
+
+




-
+







+
+
+
+
+
+










-
+


-
+


-
+

-
-
+
+
-
-
-













+
+
+

-
+









-
+










+
+
+


















-
-
-










-
+

+
+
+

-
+







#ifdef EDESTADDRREQ
    case EDESTADDRREQ: return "destination address required";
#endif
#ifdef EDIRTY
    case EDIRTY: return "mounting a dirty fs w/o force";
#endif
#ifdef EDOM
    case EDOM: return "math argument out of range";
    case EDOM: return "numerical argument out of domain";
#endif
#ifdef EDOTDOT
    case EDOTDOT: return "cross mount point";
#endif
#ifdef EDQUOT
    case EDQUOT: return "disk quota exceeded";
#endif
#ifdef EDUPPKG
    case EDUPPKG: return "duplicate package name";
#endif
#ifdef EEXIST
    case EEXIST: return "file already exists";
    case EEXIST: return "file exists";
#endif
#ifdef EFAIL
    case EFAIL: return "cannot start operation";
#endif
#ifdef EFAULT
    case EFAULT: return "bad address in system call argument";
    case EFAULT: return "bad address";
#endif
#ifdef EFBIG
    case EFBIG: return "file too large";
#endif
#ifdef EFTYPE
    case EFTYPE: return "inappropriate file type or format";
#endif
#ifdef EHOSTDOWN
    case EHOSTDOWN: return "host is down";
#endif
#ifdef EHOSTUNREACH
    case EHOSTUNREACH: return "host is unreachable";
    case EHOSTUNREACH: return "no route to host";
#endif
#if defined(EIDRM) && (!defined(EINPROGRESS) || (EIDRM != EINPROGRESS))
    case EIDRM: return "identifier removed";
#endif
#ifdef EINIT
    case EINIT: return "initialization error";
#endif
#ifdef EILSEQ
    case EILSEQ: return "invalid or incomplete multibyte or wide character";
#endif
#ifdef EINPROG
    case EINPROG: return "asynchronous operation in progress";
#endif
#ifdef EINPROGRESS
    case EINPROGRESS: return "operation now in progress";
#endif
#ifdef EINTR
    case EINTR: return "interrupted system call";
#endif
#ifdef EINVAL
    case EINVAL: return "invalid argument";
#endif
#ifdef EIO
    case EIO: return "I/O error";
    case EIO: return "input/output error";
#endif
#ifdef EISCONN
    case EISCONN: return "socket is already connected";
    case EISCONN: return "transport endpoint is already connected";
#endif
#ifdef EISDIR
    case EISDIR: return "illegal operation on a directory";
    case EISDIR: return "is a directory";
#endif
#ifdef EISNAME
    case EISNAM: return "is a name file";
#ifdef EISNAM
    case EISNAM: return "is a named type file";
#endif
#ifdef ELBIN
    case ELBIN: return "ELBIN";
#endif
#ifdef EL2HLT
    case EL2HLT: return "level 2 halted";
#endif
#ifdef EL2NSYNC
    case EL2NSYNC: return "level 2 not synchronized";
#endif
#ifdef EL3HLT
    case EL3HLT: return "level 3 halted";
#endif
#ifdef EL3RST
    case EL3RST: return "level 3 reset";
#endif
#ifdef ELBIN
    case ELBIN: return "inode is remote";
#endif
#ifdef ELIBACC
    case ELIBACC: return "cannot access a needed shared library";
    case ELIBACC: return "can not access a needed shared library";
#endif
#ifdef ELIBBAD
    case ELIBBAD: return "accessing a corrupted shared library";
#endif
#ifdef ELIBEXEC
    case ELIBEXEC: return "cannot exec a shared library directly";
#endif
#if defined(ELIBMAX) && (!defined(ECANCELED) || (ELIBMAX != ECANCELED))
    case ELIBMAX: return
	    "attempting to link in more shared libraries than system limit";
	    "attempting to link in too many shared libraries";
#endif
#ifdef ELIBSCN
    case ELIBSCN: return ".lib section in a.out corrupted";
#endif
#ifdef ELNRNG
    case ELNRNG: return "link number out of range";
#endif
#if defined(ELOOP) && (!defined(ENOENT) || (ELOOP != ENOENT))
    case ELOOP: return "too many levels of symbolic links";
#endif
#ifdef EMEDIUMTYPE
    case EMEDIUMTYPE: return "wrong medium type";
#endif
#ifdef EMFILE
    case EMFILE: return "too many open files";
#endif
#ifdef EMLINK
    case EMLINK: return "too many links";
#endif
#ifdef EMSGSIZE
    case EMSGSIZE: return "message too long";
#endif
#ifdef EMULTIHOP
    case EMULTIHOP: return "multihop attempted";
#endif
#ifdef ENAMETOOLONG
    case ENAMETOOLONG: return "file name too long";
#endif
#ifdef ENAVAIL
    case ENAVAIL: return "not available";
#endif
#ifdef ENET
    case ENET: return "ENET";
#endif
#ifdef ENETDOWN
    case ENETDOWN: return "network is down";
#endif
#ifdef ENETRESET
    case ENETRESET: return "network dropped connection on reset";
#endif
#ifdef ENETUNREACH
    case ENETUNREACH: return "network is unreachable";
#endif
#ifdef ENFILE
    case ENFILE: return "file table overflow";
    case ENFILE: return "too many open files in system";
#endif
#ifdef ENMFILE
    case ENMFILE: return "no more files";
#endif
#ifdef ENOANO
    case ENOANO: return "anode table overflow";
    case ENOANO: return "no anode";
#endif
#if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR))
    case ENOBUFS: return "no buffer space available";
#endif
#ifdef ENOCSI
    case ENOCSI: return "no CSI structure available";
#endif
732
733
734
735
736
737
738
739




740
741
742
743
744
745
746
747
748
749
750
751




752
753
754
755
756
757

758
759
760

761
762
763
764
765
766
767
768
769
770
771
772

773
774
775
776
777
778
779
780
781
782
783
784
785



786
787
788
789
790
791
792
793

794
795
796
797



798
799
800
801
802
803
804
805
806
807
808

809
810
811
812
813
814

815
816
817
818
819
820
821
786
787
788
789
790
791
792

793
794
795
796
797
798
799
800
801
802
803
804
805
806
807

808
809
810
811
812
813
814
815
816

817
818
819

820
821
822
823
824
825
826
827
828
829
830
831

832



833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852

853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870

871
872
873
874
875
876

877
878
879
880
881
882
883
884







-
+
+
+
+











-
+
+
+
+





-
+


-
+











-
+
-
-
-










+
+
+







-
+




+
+
+










-
+





-
+







#ifdef ENOLCK
    case ENOLCK: return "no locks available";
#endif
#ifdef ENOLINK
    case ENOLINK: return "link has been severed";
#endif
#ifdef ENOMEM
    case ENOMEM: return "not enough memory";
    case ENOMEM: return "cannot allocate memory";
#endif
#ifdef ENOMEDIUM
    case ENOMEDIUM: return "no medium found";
#endif
#ifdef ENOMSG
    case ENOMSG: return "no message of desired type";
#endif
#ifdef ENONET
    case ENONET: return "machine is not on the network";
#endif
#ifdef ENOPKG
    case ENOPKG: return "package not installed";
#endif
#ifdef ENOPROTOOPT
    case ENOPROTOOPT: return "bad protocol option";
    case ENOPROTOOPT: return "protocol not available";
#endif
#ifdef ENOSHARE
    case ENOSHARE: return "no such host or network path";
#endif
#ifdef ENOSPC
    case ENOSPC: return "no space left on device";
#endif
#if defined(ENOSR) && (!defined(ENAMETOOLONG) || (ENAMETOOLONG != ENOSR))
    case ENOSR: return "out of stream resources";
    case ENOSR: return "out of streams resources";
#endif
#if defined(ENOSTR) && (!defined(ENOTTY) || (ENOTTY != ENOSTR))
    case ENOSTR: return "not a stream device";
    case ENOSTR: return "device not a stream";
#endif
#ifdef ENOSYM
    case ENOSYM: return "unresolved symbol name";
#endif
#ifdef ENOSYS
    case ENOSYS: return "function not implemented";
#endif
#ifdef ENOTBLK
    case ENOTBLK: return "block device required";
#endif
#ifdef ENOTCONN
    case ENOTCONN: return "socket is not connected";
    case ENOTCONN: return "transport endpoint is not connected";
#endif
#ifdef ENOTRECOVERABLE
    case ENOTRECOVERABLE: return "state not recoverable";
#endif
#ifdef ENOTDIR
    case ENOTDIR: return "not a directory";
#endif
#if defined(ENOTEMPTY) && (!defined(EEXIST) || (ENOTEMPTY != EEXIST))
    case ENOTEMPTY: return "directory not empty";
#endif
#ifdef ENOTNAM
    case ENOTNAM: return "not a name file";
#endif
#ifdef ENOTRECOVERABLE
    case ENOTRECOVERABLE: return "state not recoverable";
#endif
#ifdef ENOTSOCK
    case ENOTSOCK: return "socket operation on non-socket";
#endif
#ifdef ENOTSUP
    case ENOTSUP: return "operation not supported";
#endif
#ifdef ENOTTY
    case ENOTTY: return "inappropriate device for ioctl";
    case ENOTTY: return "inappropriate ioctl for device";
#endif
#ifdef ENOTUNIQ
    case ENOTUNIQ: return "name not unique on network";
#endif
#ifdef ENWAIT
    case ENWAIT: return "No waiting processes";
#endif
#ifdef ENXIO
    case ENXIO: return "no such device or address";
#endif
#if defined(EOPNOTSUPP) &&  (!defined(ENOTSUP) || (ENOTSUP != EOPNOTSUPP))
    case EOPNOTSUPP: return "operation not supported on socket";
#endif
#ifdef EOTHER
    case EOTHER: return "other error";
#endif
#if defined(EOVERFLOW) && (!defined(EFBIG) || (EOVERFLOW != EFBIG)) && (!defined(EINVAL) || (EOVERFLOW != EINVAL))
    case EOVERFLOW: return "file too big";
    case EOVERFLOW: return "value too large for defined data type";
#endif
#ifdef EOWNERDEAD
    case EOWNERDEAD: return "owner died";
#endif
#ifdef EPERM
    case EPERM: return "not owner";
    case EPERM: return "operation not permitted";
#endif
#if defined(EPFNOSUPPORT) && (!defined(ENOLCK) || (ENOLCK != EPFNOSUPPORT))
    case EPFNOSUPPORT: return "protocol family not supported";
#endif
#ifdef EPIPE
    case EPIPE: return "broken pipe";
#endif
837
838
839
840
841
842
843
844

845
846
847

848
849
850
851
852
853
854
855
856

857
858
859

860
861
862




863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904

905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922

923
924
925

926
927
928
929
930
931
932
900
901
902
903
904
905
906

907
908
909

910
911
912
913
914
915
916
917
918

919
920
921

922
923
924

925
926
927
928
929
930
931
932
933
934
935
936
937
938
939

940
941
942
943
944
945

946
947
948
949
950
951
952
953
954

955
956
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







-
+


-
+








-
+


-
+


-
+
+
+
+











-
+





-
+








-
+

+
+
+

-
+











-
+

















-
+


-
+







#ifdef EPROTONOSUPPORT
    case EPROTONOSUPPORT: return "protocol not supported";
#endif
#ifdef EPROTOTYPE
    case EPROTOTYPE: return "protocol wrong type for socket";
#endif
#ifdef ERANGE
    case ERANGE: return "math result unrepresentable";
    case ERANGE: return "numerical result out of range";
#endif
#if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED))
    case EREFUSED: return "EREFUSED";
    case EREFUSED: return "connection refused";
#endif
#ifdef EREMCHG
    case EREMCHG: return "remote address changed";
#endif
#ifdef EREMDEV
    case EREMDEV: return "remote device";
#endif
#ifdef EREMOTE
    case EREMOTE: return "pathname hit remote file system";
    case EREMOTE: return "object is remote";
#endif
#ifdef EREMOTEIO
    case EREMOTEIO: return "remote i/o error";
    case EREMOTEIO: return "remote I/O error";
#endif
#ifdef EREMOTERELEASE
    case EREMOTERELEASE: return "EREMOTERELEASE";
    case EREMOTERELEASE: return "remote peer released connection";
#endif
#ifdef ERESTART
    case ERESTART: return "interrupted system call should be restarted";
#endif
#ifdef EROFS
    case EROFS: return "read-only file system";
#endif
#ifdef ERPCMISMATCH
    case ERPCMISMATCH: return "RPC version is wrong";
#endif
#ifdef ERREMOTE
    case ERREMOTE: return "object is remote";
#endif
#ifdef ESHUTDOWN
    case ESHUTDOWN: return "cannot send after socket shutdown";
    case ESHUTDOWN: return "cannot send after transport endpoint shutdown";
#endif
#ifdef ESOCKTNOSUPPORT
    case ESOCKTNOSUPPORT: return "socket type not supported";
#endif
#ifdef ESPIPE
    case ESPIPE: return "invalid seek";
    case ESPIPE: return "illegal seek";
#endif
#ifdef ESRCH
    case ESRCH: return "no such process";
#endif
#ifdef ESRMNT
    case ESRMNT: return "srmount error";
#endif
#ifdef ESTALE
    case ESTALE: return "stale remote file handle";
    case ESTALE: return "stale file handle";
#endif
#ifdef ESTRPIPE
    case ESTRPIPE: return "streams pipe error";
#endif
#ifdef ESUCCESS
    case ESUCCESS: return "Error 0";
    case ESUCCESS: return "success";
#endif
#if defined(ETIME) && (!defined(ELOOP) || (ETIME != ELOOP))
    case ETIME: return "timer expired";
#endif
#if defined(ETIMEDOUT) && (!defined(ENOSTR) || (ETIMEDOUT != ENOSTR))
    case ETIMEDOUT: return "connection timed out";
#endif
#ifdef ETOOMANYREFS
    case ETOOMANYREFS: return "too many references: cannot splice";
#endif
#ifdef ETXTBSY
    case ETXTBSY: return "text file or pseudo-device busy";
    case ETXTBSY: return "text file busy";
#endif
#ifdef EUCLEAN
    case EUCLEAN: return "structure needs cleaning";
#endif
#ifdef EUNATCH
    case EUNATCH: return "protocol driver not attached";
#endif
#ifdef EUSERS
    case EUSERS: return "too many users";
#endif
#ifdef EVERSION
    case EVERSION: return "version mismatch";
#endif
#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
    case EWOULDBLOCK: return "operation would block";
#endif
#ifdef EXDEV
    case EXDEV: return "cross-domain link";
    case EXDEV: return "invalid cross-device link";
#endif
#ifdef EXFULL
    case EXFULL: return "message tables full";
    case EXFULL: return "exchange full";
#endif
    default:
#ifdef NO_STRERROR
	return "unknown POSIX error";
#else
	return strerror(err);
#endif

Changes to generic/tclPreserve.c.

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
30
31
32
33
34
35
36
37
38
39


40
41
42

43
44
45
46
47
48
49
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
30
31
32
33
34
35
36
37
38

39
40
41
42

43
44
45
46
47
48
49
50







-
-
+
+














-
+














-
+
+


-
+







/*
 * tclPreserve.c --
 *
 *	This file contains a collection of functions that are used to make
 *	sure that widget records and other data structures aren't reallocated
 *	when there are nested functions that depend on their existence.
 *
 * Copyright (c) 1991-1994 The Regents of the University of California.
 * Copyright (c) 1994-1998 Sun Microsystems, Inc.
 * Copyright © 1991-1994 The Regents of the University of California.
 * Copyright © 1994-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

/*
 * The following data structure is used to keep track of all the Tcl_Preserve
 * calls that are still in effect. It grows as needed to accommodate any
 * number of calls in effect.
 */

typedef struct {
    ClientData clientData;	/* Address of preserved block. */
    void *clientData;		/* Address of preserved block. */
    size_t refCount;		/* Number of Tcl_Preserve calls in effect for
				 * block. */
    int mustFree;		/* Non-zero means Tcl_EventuallyFree was
				 * called while a Tcl_Preserve call was in
				 * effect, so the structure must be freed when
				 * refCount becomes zero. */
    Tcl_FreeProc *freeProc;	/* Function to call to free. */
} Reference;

/*
 * Global data structures used to hold the list of preserved data references.
 * These variables are protected by "preserveMutex".
 */

static Reference *refArray = NULL;	/* First in array of references. */
static Reference *refArray = NULL;
				/* First in array of references. */
static size_t spaceAvl = 0;	/* Total number of structures available at
				 * *firstRefPtr. */
static size_t inUse = 0;		/* Count of structures currently in use in
static size_t inUse = 0;	/* Count of structures currently in use in
				 * refArray. */
TCL_DECLARE_MUTEX(preserveMutex)/* To protect the above statics */

#define INITIAL_SIZE	2	/* Initial number of reference slots to make */

/*
 * The following data structure is used to keep track of whether an arbitrary
113
114
115
116
117
118
119
120

121
122
123
124
125
126
127
114
115
116
117
118
119
120

121
122
123
124
125
126
127
128







-
+







 *	until at least the matching call to Tcl_Release.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_Preserve(
    ClientData clientData)	/* Pointer to malloc'ed block of memory. */
    void *clientData)		/* Pointer to malloc'ed block of memory. */
{
    Reference *refPtr;
    size_t i;

    /*
     * See if there is already a reference for this pointer. If so, just
     * increment its reference count.
176
177
178
179
180
181
182
183

184
185
186
187
188
189
190
177
178
179
180
181
182
183

184
185
186
187
188
189
190
191







-
+







 *	call to Tcl_Preserve is still in effect, the block of memory is freed.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_Release(
    ClientData clientData)	/* Pointer to malloc'ed block of memory. */
    void *clientData)		/* Pointer to malloc'ed block of memory. */
{
    Reference *refPtr;
    size_t i;

    Tcl_MutexLock(&preserveMutex);
    for (i=0, refPtr=refArray ; i<inUse ; i++, refPtr++) {
	int mustFree;
255
256
257
258
259
260
261
262

263
264
265
266
267
268
269
256
257
258
259
260
261
262

263
264
265
266
267
268
269
270







-
+







 *	Ptr may be released by calling free().
 *
 *----------------------------------------------------------------------
 */

void
Tcl_EventuallyFree(
    ClientData clientData,	/* Pointer to malloc'ed block of memory. */
    void *clientData,		/* Pointer to malloc'ed block of memory. */
    Tcl_FreeProc *freeProc)	/* Function to actually do free. */
{
    Reference *refPtr;
    size_t i;

    /*
     * See if there is a reference for this pointer. If so, set its "mustFree"
288
289
290
291
292
293
294
295

296
297
298
299
300
301
302
289
290
291
292
293
294
295

296
297
298
299
300
301
302
303







-
+







    /*
     * No reference for this block.  Free it now.
     */

    if (freeProc == TCL_DYNAMIC) {
	Tcl_Free(clientData);
    } else {
	freeProc((char *)clientData);
	freeProc(clientData);
    }
}

/*
 *---------------------------------------------------------------------------
 *
 * TclHandleCreate --

Changes to generic/tclProc.c.

1
2
3
4
5
6
7
8
9
10




11
12
13
14
15
16
17
1
2
3
4
5
6




7
8
9
10
11
12
13
14
15
16
17






-
-
-
-
+
+
+
+







/*
 * tclProc.c --
 *
 *	This file contains routines that implement Tcl procedures, including
 *	the "proc" and "uplevel" commands.
 *
 * Copyright (c) 1987-1993 The Regents of the University of California.
 * Copyright (c) 1994-1998 Sun Microsystems, Inc.
 * Copyright (c) 2004-2006 Miguel Sofer
 * Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
 * Copyright © 1987-1993 The Regents of the University of California.
 * Copyright © 1994-1998 Sun Microsystems, Inc.
 * Copyright © 2004-2006 Miguel Sofer
 * Copyright © 2007 Daniel A. Steffen <das@users.sourceforge.net>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclCompile.h"
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
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







+












-
+

+


-
+

-
+



-
+


-
+

-
-
-
+
+
+



-
+








-
+
+
+
+
+
















-
+
+


-
+

-
+



-
+


-
+

-
-
-
-
+
+
+
+

-


















+


-
+

-
+







static void		MakeLambdaError(Tcl_Interp *interp,
			    Tcl_Obj *procNameObj);
static int		SetLambdaFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);

static Tcl_NRPostProc ApplyNR2;
static Tcl_NRPostProc InterpProcNR2;
static Tcl_NRPostProc Uplevel_Callback;
static Tcl_ObjCmdProc NRInterpProc;

/*
 * The ProcBodyObjType type
 */

const Tcl_ObjType tclProcBodyType = {
    "procbody",			/* name for this type */
    ProcBodyFree,		/* FreeInternalRep function */
    ProcBodyDup,		/* DupInternalRep function */
    NULL,			/* UpdateString function; Tcl_GetString and
				 * Tcl_GetStringFromObj should panic
				 * instead. */
    NULL			/* SetFromAny function; Tcl_ConvertToType
    NULL,			/* SetFromAny function; Tcl_ConvertToType
				 * should panic instead. */
    TCL_OBJTYPE_V0
};

#define ProcSetIntRep(objPtr, procPtr)					\
#define ProcSetInternalRep(objPtr, procPtr) \
    do {								\
	Tcl_ObjIntRep ir;						\
	Tcl_ObjInternalRep ir;						\
	(procPtr)->refCount++;						\
	ir.twoPtrValue.ptr1 = (procPtr);				\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreIntRep((objPtr), &tclProcBodyType, &ir);		\
	Tcl_StoreInternalRep((objPtr), &tclProcBodyType, &ir);		\
    } while (0)

#define ProcGetIntRep(objPtr, procPtr)					\
#define ProcGetInternalRep(objPtr, procPtr) \
    do {								\
	const Tcl_ObjIntRep *irPtr;					\
	irPtr = TclFetchIntRep((objPtr), &tclProcBodyType);		\
	(procPtr) = irPtr ? (Proc *)irPtr->twoPtrValue.ptr1 : NULL;		\
	const Tcl_ObjInternalRep *irPtr;				\
	irPtr = TclFetchInternalRep((objPtr), &tclProcBodyType);	\
	(procPtr) = irPtr ? (Proc *)irPtr->twoPtrValue.ptr1 : NULL;	\
    } while (0)

/*
 * The [upvar]/[uplevel] level reference type. Uses the longValue field
 * The [upvar]/[uplevel] level reference type. Uses the wideValue field
 * to remember the integer value of a parsed #<integer> format.
 *
 * Uses the default behaviour throughout, and never disposes of the string
 * rep; it's just a cache type.
 */

static const Tcl_ObjType levelReferenceType = {
    "levelReference",
    NULL, NULL, NULL, NULL
    NULL,
    NULL,
    NULL,
    NULL,
    TCL_OBJTYPE_V1(TclLengthOne)
};

/*
 * The type of lambdas. Note that every lambda will *always* have a string
 * representation.
 *
 * Internally, ptr1 is a pointer to a Proc instance that is not bound to a
 * command name, and ptr2 is a pointer to the namespace that the Proc instance
 * will execute within. IF YOU CHANGE THIS, CHECK IN tclDisassemble.c TOO.
 */

static const Tcl_ObjType lambdaType = {
    "lambdaExpr",		/* name */
    FreeLambdaInternalRep,	/* freeIntRepProc */
    DupLambdaInternalRep,	/* dupIntRepProc */
    NULL,			/* updateStringProc */
    SetLambdaFromAny		/* setFromAnyProc */
    SetLambdaFromAny,		/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

#define LambdaSetIntRep(objPtr, procPtr, nsObjPtr)			\
#define LambdaSetInternalRep(objPtr, procPtr, nsObjPtr) \
    do {								\
	Tcl_ObjIntRep ir;						\
	Tcl_ObjInternalRep ir;						\
	ir.twoPtrValue.ptr1 = (procPtr);				\
	ir.twoPtrValue.ptr2 = (nsObjPtr);				\
	Tcl_IncrRefCount((nsObjPtr));					\
	Tcl_StoreIntRep((objPtr), &lambdaType, &ir);			\
	Tcl_StoreInternalRep((objPtr), &lambdaType, &ir);		\
    } while (0)

#define LambdaGetIntRep(objPtr, procPtr, nsObjPtr)			\
#define LambdaGetInternalRep(objPtr, procPtr, nsObjPtr) \
    do {								\
	const Tcl_ObjIntRep *irPtr;					\
	irPtr = TclFetchIntRep((objPtr), &lambdaType);			\
	(procPtr) = irPtr ? (Proc *)irPtr->twoPtrValue.ptr1 : NULL;		\
	(nsObjPtr) = irPtr ? (Tcl_Obj *)irPtr->twoPtrValue.ptr2 : NULL;		\
	const Tcl_ObjInternalRep *irPtr;				\
	irPtr = TclFetchInternalRep((objPtr), &lambdaType);		\
	(procPtr) = irPtr ? (Proc *)irPtr->twoPtrValue.ptr1 : NULL;	\
	(nsObjPtr) = irPtr ? (Tcl_Obj *)irPtr->twoPtrValue.ptr2 : NULL;	\
    } while (0)


/*
 *----------------------------------------------------------------------
 *
 * Tcl_ProcObjCmd --
 *
 *	This object-based function is invoked to process the "proc" Tcl
 *	command. See the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result value.
 *
 * Side effects:
 *	A new procedure gets created.
 *
 *----------------------------------------------------------------------
 */

#undef TclObjInterpProc
int
Tcl_ProcObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Size objc,		/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    Proc *procPtr;
    const char *procName;
    const char *simpleName, *procArgs, *procBody;
    Namespace *nsPtr, *altNsPtr, *cxtNsPtr;
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
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







-
+






-
+
















-
+







    TclGetNamespaceForQualName(interp, procName, NULL, 0,
	    &nsPtr, &altNsPtr, &cxtNsPtr, &simpleName);

    if (nsPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't create procedure \"%s\": unknown namespace",
		procName));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", NULL);
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", (char *)NULL);
	return TCL_ERROR;
    }
    if (simpleName == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't create procedure \"%s\": bad procedure name",
		procName));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", NULL);
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Create the data structure to represent the procedure.
     */

    if (TclCreateProc(interp, /*ignored nsPtr*/ NULL, simpleName, objv[2],
	    objv[3], &procPtr) != TCL_OK) {
	Tcl_AddErrorInfo(interp, "\n    (creating proc \"");
	Tcl_AddErrorInfo(interp, simpleName);
	Tcl_AddErrorInfo(interp, "\")");
	return TCL_ERROR;
    }

    cmd = TclNRCreateCommandInNs(interp, simpleName, (Tcl_Namespace *) nsPtr,
	TclObjInterpProc, TclNRInterpProc, procPtr, TclProcDeleteProc);
	TclObjInterpProc, NRInterpProc, procPtr, TclProcDeleteProc);

    /*
     * Now initialize the new procedure's cmdPtr field. This will be used
     * later when the procedure is called to determine what namespace the
     * procedure will run in. This will be different than the current
     * namespace if the proc was renamed into a different namespace.
     */
261
262
263
264
265
266
267
268

269
270
271
272
273
274
275
268
269
270
271
272
273
274

275
276
277
278
279
280
281
282







-
+







		    && (contextPtr->nline >= 4) && (contextPtr->line[3] >= 0)) {
		int isNew;
		Tcl_HashEntry *hePtr;
		CmdFrame *cfPtr = (CmdFrame *)Tcl_Alloc(sizeof(CmdFrame));

		cfPtr->level = -1;
		cfPtr->type = contextPtr->type;
		cfPtr->line = (int *)Tcl_Alloc(sizeof(int));
		cfPtr->line = (Tcl_Size *)Tcl_Alloc(sizeof(Tcl_Size));
		cfPtr->line[0] = contextPtr->line[3];
		cfPtr->nline = 1;
		cfPtr->framePtr = NULL;
		cfPtr->nextPtr = NULL;

		cfPtr->data.eval.path = contextPtr->data.eval.path;
		Tcl_IncrRefCount(cfPtr->data.eval.path);
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
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







-
+










-
+







     *	   seem to make a lot of sense to verify the number of arguments we
     *	   are about to ignore ...
     *	 - could be enhanced to handle also non-empty bodies that contain only
     *	   comments; however, parsing the body will slow down the compilation
     *	   of all procs whose argument list is just _args_
     */

    if (objv[3]->typePtr == &tclProcBodyType) {
    if (TclHasInternalRep(objv[3], &tclProcBodyType)) {
	goto done;
    }

    procArgs = TclGetString(objv[2]);

    while (*procArgs == ' ') {
	procArgs++;
    }

    if ((procArgs[0] == 'a') && (strncmp(procArgs, "args", 4) == 0)) {
	size_t numBytes;
	Tcl_Size numBytes;

	procArgs +=4;
	while (*procArgs != '\0') {
	    if (*procArgs != ' ') {
		goto done;
	    }
	    procArgs++;
400
401
402
403
404
405
406
407

408
409
410

411
412

413
414
415
416
417
418
419
407
408
409
410
411
412
413

414
415
416

417
418

419
420
421
422
423
424
425
426







-
+


-
+

-
+







    Tcl_Obj *argsPtr,		/* Description of arguments. */
    Tcl_Obj *bodyPtr,		/* Command body. */
    Proc **procPtrPtr)		/* Returns: pointer to proc data. */
{
    Interp *iPtr = (Interp *) interp;

    Proc *procPtr = NULL;
    int i, result, numArgs;
    Tcl_Size i, numArgs;
    CompiledLocal *localPtr = NULL;
    Tcl_Obj **argArray;
    int precompiled = 0;
    int precompiled = 0, result;

    ProcGetIntRep(bodyPtr, procPtr);
    ProcGetInternalRep(bodyPtr, procPtr);
    if (procPtr != NULL) {
	/*
	 * Because the body is a TclProProcBody, the actual body is already
	 * compiled, and it is not shared with anyone else, so it's OK not to
	 * unshare it (as a matter of fact, it is bad to unshare it, because
	 * there may be no source code).
	 *
440
441
442
443
444
445
446
447

448
449
450
451
452
453
454
447
448
449
450
451
452
453

454
455
456
457
458
459
460
461







-
+







	 * have a different number of arguments, even if their bodies are
	 * identical. Note that we don't use Tcl_DuplicateObj since we would
	 * not want any bytecode internal representation.
	 */

	if (Tcl_IsShared(bodyPtr)) {
	    const char *bytes;
	    size_t length;
	    Tcl_Size length;
	    Tcl_Obj *sharedBodyPtr = bodyPtr;

	    bytes = TclGetStringFromObj(bodyPtr, &length);
	    bodyPtr = Tcl_NewStringObj(bytes, length);

	    /*
	     * TIP #280.
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
558
559

560
561

562
563
564
565
566

567
568
569
570
571
572
573
574
575
576
577
578
579

580
581
582
583
584
585
586
587
588
589
590
591

592
593
594

595
596
597
598
599
600
601
602
603

604
605
606
607
608

609
610
611
612
613
614
615
616
617

618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

637
638
639
640
641
642
643
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
558
559
560
561

562
563
564

565
566

567
568
569
570
571

572
573
574
575
576
577
578
579
580
581
582
583
584

585
586
587
588
589
590
591
592
593
594
595
596

597
598
599

600
601
602
603
604
605
606
607
608

609
610
611
612
613

614

615
616
617
618
619
620
621

622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640

641
642
643
644
645
646
647
648







-
+







-
-
+
+


-
+










-
+
-






-
+











-
+


-
+



-
+


















-
+


-
+

-
+




-
+












-
+











-
+


-
+








-
+




-
+
-







-
+


















-
+







    /*
     * Break up the argument list into argument specifiers, then process each
     * argument specifier. If the body is precompiled, processing is limited
     * to checking that the parsed argument is consistent with the one stored
     * in the Proc.
     */

    result = Tcl_ListObjGetElements(interp , argsPtr ,&numArgs ,&argArray);
    result = TclListObjGetElements(interp, argsPtr, &numArgs, &argArray);
    if (result != TCL_OK) {
	goto procError;
    }

    if (precompiled) {
	if (numArgs > procPtr->numArgs) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "procedure \"%s\": arg list contains %d entries, "
		    "precompiled header expects %d", procName, numArgs,
		    "procedure \"%s\": arg list contains %" TCL_SIZE_MODIFIER "d entries, "
		    "precompiled header expects %" TCL_SIZE_MODIFIER "d", procName, numArgs,
		    procPtr->numArgs));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
		    "BYTECODELIES", NULL);
		    "BYTECODELIES", (char *)NULL);
	    goto procError;
	}
	localPtr = procPtr->firstLocalPtr;
    } else {
	procPtr->numArgs = numArgs;
	procPtr->numCompiledLocals = numArgs;
    }

    for (i = 0; i < numArgs; i++) {
	const char *argname, *argnamei, *argnamelast;
	int fieldCount;
	Tcl_Size fieldCount, nameLength;
	size_t nameLength;
	Tcl_Obj **fieldValues;

	/*
	 * Now divide the specifier up into name and default.
	 */

	result = Tcl_ListObjGetElements(interp, argArray[i], &fieldCount,
	result = TclListObjGetElements(interp, argArray[i], &fieldCount,
		&fieldValues);
	if (result != TCL_OK) {
	    goto procError;
	}
	if (fieldCount > 2) {
	    Tcl_Obj *errorObj = Tcl_NewStringObj(
		"too many fields in argument specifier \"", -1);
	    Tcl_AppendObjToObj(errorObj, argArray[i]);
	    Tcl_AppendToObj(errorObj, "\"", -1);
	    Tcl_SetObjResult(interp, errorObj);
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
		    "FORMALARGUMENTFORMAT", NULL);
		    "FORMALARGUMENTFORMAT", (char *)NULL);
	    goto procError;
	}
	if ((fieldCount == 0) || (fieldValues[0]->length == 0)) {
	if ((fieldCount == 0) || (Tcl_GetCharLength(fieldValues[0]) == 0)) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "argument with no name", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
		    "FORMALARGUMENTFORMAT", NULL);
		    "FORMALARGUMENTFORMAT", (char *)NULL);
	    goto procError;
	}

	argname = TclGetStringFromObj(fieldValues[0], &nameLength);

	/*
	 * Check that the formal parameter name is a scalar.
	 */

	argnamei = argname;
	argnamelast = (nameLength > 0) ? (argname + nameLength - 1) : argname;
	while (argnamei < argnamelast) {
	    if (*argnamei == '(') {
		if (*argnamelast == ')') { /* We have an array element. */
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "formal parameter \"%s\" is an array element",
			    TclGetString(fieldValues[0])));
		    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
			    "FORMALARGUMENTFORMAT", NULL);
			    "FORMALARGUMENTFORMAT", (char *)NULL);
		    goto procError;
		}
	    } else if (*argnamei == ':' && *(argnamei+1) == ':') {
	    } else if (argnamei[0] == ':' && argnamei[1] == ':') {
		Tcl_Obj *errorObj = Tcl_NewStringObj(
		    "formal parameter \"", -1);
			"formal parameter \"", -1);
		Tcl_AppendObjToObj(errorObj, fieldValues[0]);
		Tcl_AppendToObj(errorObj, "\" is not a simple name", -1);
		Tcl_SetObjResult(interp, errorObj);
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
			"FORMALARGUMENTFORMAT", NULL);
			"FORMALARGUMENTFORMAT", (char *)NULL);
		goto procError;
	    }
	    argnamei++;
	}

	if (precompiled) {
	    /*
	     * Compare the parsed argument with the stored one. Note that the
	     * only flag value that makes sense at this point is VAR_ARGUMENT
	     * (its value was kept the same as pre VarReform to simplify
	     * tbcload's processing of older byetcodes).
	     *
	     * The only other flag vlaue that is important to retrieve from
	     * The only other flag value that is important to retrieve from
	     * precompiled procs is VAR_TEMPORARY (also unchanged). It is
	     * needed later when retrieving the variable names.
	     */

	    if ((localPtr->nameLength != nameLength)
		    || (memcmp(localPtr->name, argname, nameLength) != 0)
		    || (localPtr->frameIndex != i)
		    || !(localPtr->flags & VAR_ARGUMENT)
		    || (localPtr->defValuePtr == NULL && fieldCount == 2)
		    || (localPtr->defValuePtr != NULL && fieldCount != 2)) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"procedure \"%s\": formal parameter %d is "
			"procedure \"%s\": formal parameter %" TCL_SIZE_MODIFIER "d is "
			"inconsistent with precompiled body", procName, i));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
			"BYTECODELIES", NULL);
			"BYTECODELIES", (char *)NULL);
		goto procError;
	    }

	    /*
	     * Compare the default value if any.
	     */

	    if (localPtr->defValuePtr != NULL) {
		size_t tmpLength, valueLength;
		Tcl_Size tmpLength, valueLength;
		const char *tmpPtr = TclGetStringFromObj(localPtr->defValuePtr, &tmpLength);
		const char *value = TclGetStringFromObj(fieldValues[1], &valueLength);

		if ((valueLength != tmpLength)
		     || memcmp(value, tmpPtr, tmpLength) != 0
			|| memcmp(value, tmpPtr, tmpLength) != 0) {
		) {
		    Tcl_Obj *errorObj = Tcl_ObjPrintf(
			    "procedure \"%s\": formal parameter \"", procName);
		    Tcl_AppendObjToObj(errorObj, fieldValues[0]);
		    Tcl_AppendToObj(errorObj, "\" has "
			"default value inconsistent with precompiled body", -1);
		    Tcl_SetObjResult(interp, errorObj);
		    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
			    "BYTECODELIES", NULL);
			    "BYTECODELIES", (char *)NULL);
		    goto procError;
		}
	    }
	    if ((i == numArgs - 1)
		    && (localPtr->nameLength == 4)
		    && (localPtr->name[0] == 'a')
		    && (strcmp(localPtr->name, "args") == 0)) {
		localPtr->flags |= VAR_IS_ARGS;
	    }

	    localPtr = localPtr->nextPtr;
	} else {
	    /*
	     * Allocate an entry in the runtime procedure frame's array of
	     * local variables for the argument.
	     */

	    localPtr = (CompiledLocal *)Tcl_Alloc(
		    offsetof(CompiledLocal, name) + fieldValues[0]->length + 1);
		    offsetof(CompiledLocal, name) + 1U + fieldValues[0]->length);
	    if (procPtr->firstLocalPtr == NULL) {
		procPtr->firstLocalPtr = procPtr->lastLocalPtr = localPtr;
	    } else {
		procPtr->lastLocalPtr->nextPtr = localPtr;
		procPtr->lastLocalPtr = localPtr;
	    }
	    localPtr->nextPtr = NULL;
720
721
722
723
724
725
726
727

728
729
730
731
732
733
734
725
726
727
728
729
730
731

732
733
734
735
736
737
738
739







-
+







	int result;
	Tcl_Obj obj;

	obj.bytes = (char *) name;
	obj.length = strlen(name);
	obj.typePtr = NULL;
	result = TclObjGetFrame(interp, &obj, framePtrPtr);
	TclFreeIntRep(&obj);
	TclFreeInternalRep(&obj);
	return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TclObjGetFrame --
758
759
760
761
762
763
764
765

766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784

785
786
787
788
789
790
791

792
793
794
795
796
797
798
799
800
801

802
803
804

805
806
807
808
809
810
811
763
764
765
766
767
768
769

770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788

789
790
791
792
793
794
795

796
797
798
799
800
801
802
803
804
805

806
807
808

809
810
811
812
813
814
815
816







-
+


















-
+






-
+









-
+


-
+







    Tcl_Interp *interp,		/* Interpreter in which to find frame. */
    Tcl_Obj *objPtr,		/* Object describing frame. */
    CallFrame **framePtrPtr)	/* Store pointer to frame here (or NULL if
				 * global frame indicated). */
{
    Interp *iPtr = (Interp *) interp;
    int curLevel, level, result;
    const Tcl_ObjIntRep *irPtr;
    const Tcl_ObjInternalRep *irPtr;
    const char *name = NULL;
    Tcl_WideInt w;

    /*
     * Parse object to figure out which level number to go to.
     */

    result = 0;
    curLevel = iPtr->varFramePtr->level;

    /*
     * Check for integer first, since that has potential to spare us
     * a generation of a stringrep.
     */

    if (objPtr == NULL) {
	/* Do nothing */
    } else if (TCL_OK == Tcl_GetIntFromObj(NULL, objPtr, &level)) {
	Tcl_GetWideIntFromObj(NULL, objPtr, &w);
	TclGetWideIntFromObj(NULL, objPtr, &w);
	if (w < 0 || w > INT_MAX || curLevel > w + INT_MAX) {
	    result = -1;
	} else {
	    level = curLevel - level;
	    result = 1;
	}
    } else if ((irPtr = TclFetchIntRep(objPtr, &levelReferenceType))) {
    } else if ((irPtr = TclFetchInternalRep(objPtr, &levelReferenceType))) {
	level = irPtr->wideValue;
	result = 1;
    } else {
	name = TclGetString(objPtr);
	if (name[0] == '#') {
	    if (TCL_OK == Tcl_GetInt(NULL, name+1, &level)) {
		if (level < 0 || (level > 0 && name[1] == '-')) {
		    result = -1;
		} else {
		    Tcl_ObjIntRep ir;
		    Tcl_ObjInternalRep ir;

		    ir.wideValue = level;
		    Tcl_StoreIntRep(objPtr, &levelReferenceType, &ir);
		    Tcl_StoreInternalRep(objPtr, &levelReferenceType, &ir);
		    result = 1;
		}
	    } else {
		result = -1;
	    }
	} else if (TclGetWideBitsFromObj(NULL, objPtr, &w) == TCL_OK) {
	    /*
826
827
828
829
830
831
832
833

834
835
836
837
838
839
840
841
842
843
844
845

846
847
848
849
850
851
852
831
832
833
834
835
836
837

838
839
840
841
842
843
844
845
846
847
848
849

850
851
852
853
854
855
856
857







-
+











-
+







	    }
	    level = curLevel - 1;
	}
	if (level >= 0) {
	    CallFrame *framePtr;
	    for (framePtr = iPtr->varFramePtr; framePtr != NULL;
		    framePtr = framePtr->callerVarPtr) {
		if (framePtr->level == level) {
		if ((int)framePtr->level == level) {
		    *framePtrPtr = framePtr;
		    return result;
		}
	    }
	}
    }
badLevel:
    if (name == NULL) {
	name = objPtr ? TclGetString(objPtr) : "1" ;
    }
    Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad level \"%s\"", name));
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LEVEL", name, NULL);
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LEVEL", name, (char *)NULL);
    return -1;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UplevelObjCmd --
861
862
863
864
865
866
867
868

869
870
871
872
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
898
899

900
901
902
903
904
905
906
866
867
868
869
870
871
872

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
898
899
900
901
902
903

904
905
906
907
908
909
910
911







-
+




















-
+









-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Uplevel_Callback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    CallFrame *savedVarFramePtr = (CallFrame *)data[0];

    if (result == TCL_ERROR) {
	Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
		"\n    (\"uplevel\" body line %d)", Tcl_GetErrorLine(interp)));
    }

    /*
     * Restore the variable frame, and return.
     */

    ((Interp *)interp)->varFramePtr = savedVarFramePtr;
    return result;
}

int
Tcl_UplevelObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, TclNRUplevelObjCmd, clientData, objc, objv);
}

int
TclNRUplevelObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{

    Interp *iPtr = (Interp *) interp;
    CmdFrame *invoker = NULL;
915
916
917
918
919
920
921
922
923



924
925
926
927
928
929
930
920
921
922
923
924
925
926


927
928
929
930
931
932
933
934
935
936







-
-
+
+
+







    *    is only one argument.  This requires a TIP since currently a single
    *    argument is interpreted as a level indicator if possible.
    */
    uplevelSyntax:
	Tcl_WrongNumArgs(interp, 1, objv, "?level? command ?arg ...?");
	return TCL_ERROR;
    } else if (!TclHasStringRep(objv[1]) && objc == 2) {
	int status ,llength;
	status = Tcl_ListObjLength(interp, objv[1], &llength);
	int status;
	Tcl_Size llength;
	status = TclListObjLength(interp, objv[1], &llength);
	if (status == TCL_OK && llength > 1) {
	    /* the first argument can't interpreted as a level. Avoid
	     * generating a string representation of the script. */
	    result = TclGetFrame(interp, "1", &framePtr);
	    if (result == -1) {
		return TCL_ERROR;
	    }
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
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







-
+



















-
+







-
+
+







static int
ProcWrongNumArgs(
    Tcl_Interp *interp,
    int skip)
{
    CallFrame *framePtr = ((Interp *)interp)->varFramePtr;
    Proc *procPtr = framePtr->procPtr;
    int localCt = procPtr->numCompiledLocals, numArgs, i;
    Tcl_Size localCt = procPtr->numCompiledLocals, numArgs, i;
    Tcl_Obj **desiredObjs;
    const char *final = NULL;

    /*
     * Build up desired argument list for Tcl_WrongNumArgs
     */

    numArgs = framePtr->procPtr->numArgs;
    desiredObjs = (Tcl_Obj **)TclStackAlloc(interp,
	    sizeof(Tcl_Obj *) * (numArgs+1));

    if (framePtr->isProcCallFrame & FRAME_IS_LAMBDA) {
	desiredObjs[0] = Tcl_NewStringObj("lambdaExpr", -1);
    } else {
	desiredObjs[0] = framePtr->objv[skip-1];
    }
    Tcl_IncrRefCount(desiredObjs[0]);

    if (localCt > 0) {
	Var *defPtr = (Var *) (&framePtr->localCachePtr->varName0 + localCt);
	Var *defPtr = (Var *)(&framePtr->localCachePtr->varName0 + localCt);

	for (i=1 ; i<=numArgs ; i++, defPtr++) {
	    Tcl_Obj *argObj;
	    Tcl_Obj *namePtr = localName(framePtr, i-1);

	    if (defPtr->value.objPtr != NULL) {
		TclNewObj(argObj);
		Tcl_AppendStringsToObj(argObj, "?", TclGetString(namePtr), "?", NULL);
		Tcl_AppendStringsToObj(argObj, "?", TclGetString(namePtr), "?",
			(char *)NULL);
	    } else if (defPtr->flags & VAR_IS_ARGS) {
		numArgs--;
		final = "?arg ...?";
		break;
	    } else {
		argObj = namePtr;
		Tcl_IncrRefCount(namePtr);
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
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







-
+



















-
-
+
+







-
+



















-
+







}

void
TclFreeLocalCache(
    Tcl_Interp *interp,
    LocalCache *localCachePtr)
{
    int i;
    Tcl_Size i;
    Tcl_Obj **namePtrPtr = &localCachePtr->varName0;

    for (i = 0; i < localCachePtr->numVars; i++, namePtrPtr++) {
	Tcl_Obj *objPtr = *namePtrPtr;

	if (objPtr) {
	    /* TclReleaseLiteral calls Tcl_DecrRefCount for us */
	    TclReleaseLiteral(interp, objPtr);
	}
    }
    Tcl_Free(localCachePtr);
}

static void
InitLocalCache(
    Proc *procPtr)
{
    Interp *iPtr = procPtr->iPtr;
    ByteCode *codePtr;
    int localCt = procPtr->numCompiledLocals;
    int numArgs = procPtr->numArgs, i = 0;
    Tcl_Size localCt = procPtr->numCompiledLocals;
    Tcl_Size numArgs = procPtr->numArgs, i = 0;

    Tcl_Obj **namePtr;
    Var *varPtr;
    LocalCache *localCachePtr;
    CompiledLocal *localPtr;
    int isNew;

    ByteCodeGetIntRep(procPtr->bodyPtr, &tclByteCodeType, codePtr);
    ByteCodeGetInternalRep(procPtr->bodyPtr, &tclByteCodeType, codePtr);

    /*
     * Cache the names and initial values of local variables; store the
     * cache in both the framePtr for this execution and in the codePtr
     * for future calls.
     */

    localCachePtr = (LocalCache *)Tcl_Alloc(offsetof(LocalCache, varName0)
	    + localCt * sizeof(Tcl_Obj *)
	    + numArgs * sizeof(Var));

    namePtr = &localCachePtr->varName0;
    varPtr = (Var *) (namePtr + localCt);
    localPtr = procPtr->firstLocalPtr;
    while (localPtr) {
	if (TclIsVarTemporary(localPtr)) {
	    *namePtr = NULL;
	} else {
	    *namePtr = TclCreateLiteral(iPtr, localPtr->name,
		    localPtr->nameLength, /* hash */ -1,
		    localPtr->nameLength, /* hash */ TCL_INDEX_NONE,
		    &isNew, /* nsPtr */ NULL, 0, NULL);
	    Tcl_IncrRefCount(*namePtr);
	}

	if (i < numArgs) {
	    varPtr->flags = (localPtr->flags & VAR_IS_ARGS);
	    varPtr->value.objPtr = localPtr->defValuePtr;
1332
1333
1334
1335
1336
1337
1338
1339

1340
1341
1342
1343
1344
1345
1346
1347
1348

1349
1350
1351

1352
1353
1354
1355
1356
1357
1358
1339
1340
1341
1342
1343
1344
1345

1346
1347
1348
1349
1350
1351
1352
1353
1354

1355
1356
1357

1358
1359
1360
1361
1362
1363
1364
1365







-
+








-
+


-
+







 *	are being referenced at runtime.
 *
 *----------------------------------------------------------------------
 */

static int
InitArgsAndLocals(
    Tcl_Interp *interp,/* Interpreter in which procedure was
    Tcl_Interp *interp,		/* Interpreter in which procedure was
				 * invoked. */
    int skip)			/* Number of initial arguments to be skipped,
				 * i.e., words in the "command name". */
{
    CallFrame *framePtr = ((Interp *)interp)->varFramePtr;
    Proc *procPtr = framePtr->procPtr;
    ByteCode *codePtr;
    Var *varPtr, *defPtr;
    int localCt = procPtr->numCompiledLocals, numArgs, argCt, i, imax;
    Tcl_Size localCt = procPtr->numCompiledLocals, numArgs, argCt, i, imax;
    Tcl_Obj *const *argObjs;

    ByteCodeGetIntRep(procPtr->bodyPtr, &tclByteCodeType, codePtr);
    ByteCodeGetInternalRep(procPtr->bodyPtr, &tclByteCodeType, codePtr);

    /*
     * Make sure that the local cache of variable names and initial values has
     * been initialised properly .
     */

    if (localCt) {
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396

1397
1398
1399
1400
1401
1402
1403
1389
1390
1391
1392
1393
1394
1395

1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410







-







+







     * entries in both the Proc structure's local variable list and the call
     * frame's local variable array.
     */

    numArgs = procPtr->numArgs;
    argCt = framePtr->objc - skip;	/* Set it to the number of args to the
					 * procedure. */
    argObjs = framePtr->objv + skip;
    if (numArgs == 0) {
	if (argCt) {
	    goto incorrectArgs;
	} else {
	    goto correctArgs;
	}
    }
    argObjs = framePtr->objv + skip;
    imax = ((argCt < numArgs-1) ? argCt : numArgs-1);
    for (i = 0; i < imax; i++, varPtr++, defPtr ? defPtr++ : defPtr) {
	/*
	 * "Normal" arguments; last formal is special, depends on it being
	 * 'args'.
	 */

1426
1427
1428
1429
1430
1431
1432
1433

1434
1435
1436
1437
1438
1439
1440
1433
1434
1435
1436
1437
1438
1439

1440
1441
1442
1443
1444
1445
1446
1447







-
+







    /*
     * When we get here, the last formal argument remains to be defined:
     * defPtr and varPtr point to the last argument to be initialized.
     */

    varPtr->flags = 0;
    if (defPtr && defPtr->flags & VAR_IS_ARGS) {
	Tcl_Obj *listPtr = Tcl_NewListObj(argCt-i, argObjs+i);
	Tcl_Obj *listPtr = Tcl_NewListObj((argCt>i)? argCt-i : 0, argObjs+i);

	varPtr->value.objPtr = listPtr;
	Tcl_IncrRefCount(listPtr);	/* Local var is a reference. */
    } else if (argCt == numArgs) {
	Tcl_Obj *objPtr = argObjs[i];

	varPtr->value.objPtr = objPtr;
1496
1497
1498
1499
1500
1501
1502
1503

1504
1505

1506
1507

1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527

1528
1529
1530
1531
1532
1533
1534
1535
1536
1537

1538
1539
1540
1541
1542
1543


1544
1545
1546
1547
1548
1549
1550
1503
1504
1505
1506
1507
1508
1509

1510
1511

1512
1513

1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533

1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550

1551
1552
1553
1554
1555
1556
1557
1558
1559







-
+

-
+

-
+



















-
+










+





-
+
+







 *	to be popped by the caller.
 *
 *----------------------------------------------------------------------
 */

int
TclPushProcCallFrame(
    ClientData clientData,	/* Record describing procedure to be
    void *clientData,		/* Record describing procedure to be
				 * interpreted. */
    Tcl_Interp *interp,/* Interpreter in which procedure was
    Tcl_Interp *interp,		/* Interpreter in which procedure was
				 * invoked. */
    int objc,			/* Count of number of arguments to this
    Tcl_Size objc,		/* Count of number of arguments to this
				 * procedure. */
    Tcl_Obj *const objv[],	/* Argument value objects. */
    int isLambda)		/* 1 if this is a call by ApplyObjCmd: it
				 * needs special rules for error msg */
{
    Proc *procPtr = (Proc *)clientData;
    Namespace *nsPtr = procPtr->cmdPtr->nsPtr;
    CallFrame *framePtr, **framePtrPtr;
    int result;
    ByteCode *codePtr;

    /*
     * If necessary (i.e. if we haven't got a suitable compilation already
     * cached) compile the procedure's body. The compiler will allocate frame
     * slots for the procedure's non-argument local variables. Note that
     * compiling the body might increase procPtr->numCompiledLocals if new
     * local variables are found while compiling.
     */

    ByteCodeGetIntRep(procPtr->bodyPtr, &tclByteCodeType, codePtr);
    ByteCodeGetInternalRep(procPtr->bodyPtr, &tclByteCodeType, codePtr);
    if (codePtr != NULL) {
	Interp *iPtr = (Interp *) interp;

	/*
	 * When we've got bytecode, this is the check for validity. That is,
	 * the bytecode must be for the right interpreter (no cross-leaks!),
	 * the code must be from the current epoch (so subcommand compilation
	 * is up-to-date), the namespace must match (so variable handling
	 * is right) and the resolverEpoch must match (so that new shadowed
	 * commands and/or resolver changes are considered).
	 * Ensure the ByteCode's procPtr is the same (or it's precompiled).
	 */

	if (((Interp *) *codePtr->interpHandle != iPtr)
		|| (codePtr->compileEpoch != iPtr->compileEpoch)
		|| (codePtr->nsPtr != nsPtr)
		|| (codePtr->nsEpoch != nsPtr->resolverEpoch)) {
		|| (codePtr->nsEpoch != nsPtr->resolverEpoch)
		|| ((codePtr->procPtr != procPtr) && procPtr->bodyPtr->bytes)) {
	    goto doCompilation;
	}
    } else {
    doCompilation:
	result = TclProcCompileProc(interp, procPtr, procPtr->bodyPtr, nsPtr,
		(isLambda ? "body of lambda term" : "body of proc"),
		TclGetString(objv[isLambda]));
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
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







-
+

-
+









-
+




-
+

-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *	Depends on the commands in the procedure.
 *
 *----------------------------------------------------------------------
 */

int
TclObjInterpProc(
    ClientData clientData,	/* Record describing procedure to be
    void *clientData,		/* Record describing procedure to be
				 * interpreted. */
    Tcl_Interp *interp,/* Interpreter in which procedure was
    Tcl_Interp *interp,		/* Interpreter in which procedure was
				 * invoked. */
    int objc,			/* Count of number of arguments to this
				 * procedure. */
    Tcl_Obj *const objv[])	/* Argument value objects. */
{
    /*
     * Not used much in the core; external interface for iTcl
     */

    return Tcl_NRCallObjProc(interp, TclNRInterpProc, clientData, objc, objv);
    return Tcl_NRCallObjProc(interp, NRInterpProc, clientData, objc, objv);
}

int
TclNRInterpProc(
    ClientData clientData,	/* Record describing procedure to be
    void *clientData,		/* Record describing procedure to be
				 * interpreted. */
    Tcl_Interp *interp,/* Interpreter in which procedure was
    Tcl_Interp *interp,		/* Interpreter in which procedure was
				 * invoked. */
    Tcl_Size objc,		/* Count of number of arguments to this
				 * procedure. */
    Tcl_Obj *const objv[])	/* Argument value objects. */
{
    int result = TclPushProcCallFrame(clientData, interp, objc, objv,
	    /*isLambda*/ 0);

    if (result != TCL_OK) {
	return TCL_ERROR;
    }
    return TclNRInterpProcCore(interp, objv[0], 1, &MakeProcError);
}

static int
NRInterpProc(
    void *clientData,		/* Record describing procedure to be
				 * interpreted. */
    Tcl_Interp *interp,		/* Interpreter in which procedure was
				 * invoked. */
    int objc,			/* Count of number of arguments to this
				 * procedure. */
    Tcl_Obj *const objv[])	/* Argument value objects. */
{
    int result = TclPushProcCallFrame(clientData, interp, objc, objv,
	    /*isLambda*/ 0);

    if (result != TCL_OK) {
	return TCL_ERROR;
    }
    return TclNRInterpProcCore(interp, objv[0], 1, &MakeProcError);
}

static int
ObjInterpProc2(
    void *clientData,		/* Record describing procedure to be
				 * interpreted. */
    Tcl_Interp *interp,		/* Interpreter in which procedure was
				 * invoked. */
    Tcl_Size objc,		/* Count of number of arguments to this
				 * procedure. */
    Tcl_Obj *const objv[])	/* Argument value objects. */
{
    /*
     * Not used much in the core; external interface for iTcl
     */

    return Tcl_NRCallObjProc2(interp, TclNRInterpProc, clientData, objc, objv);
}

/*
 *----------------------------------------------------------------------
 *
 * TclNRInterpProcCore --
 *
 *	When a Tcl procedure, lambda term or anything else that works like a
1642
1643
1644
1645
1646
1647
1648
1649

1650
1651
1652

1653
1654
1655
1656
1657
1658
1659
1687
1688
1689
1690
1691
1692
1693

1694
1695
1696

1697
1698
1699
1700
1701
1702
1703
1704







-
+


-
+







 *	Nearly anything; depends on the commands in the procedure body.
 *
 *----------------------------------------------------------------------
 */

int
TclNRInterpProcCore(
    Tcl_Interp *interp,/* Interpreter in which procedure was
    Tcl_Interp *interp,		/* Interpreter in which procedure was
				 * invoked. */
    Tcl_Obj *procNameObj,	/* Procedure name for error reporting. */
    int skip,			/* Number of initial arguments to be skipped,
    Tcl_Size skip,		/* Number of initial arguments to be skipped,
				 * i.e., words in the "command name". */
    ProcErrorProc *errorProc)	/* How to convert results from the script into
				 * results of the overall procedure. */
{
    Interp *iPtr = (Interp *) interp;
    Proc *procPtr = iPtr->varFramePtr->procPtr;
    int result;
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
1749
1750
1751
1752
1753
1754
1755
1756
1757

1758
1759
1760
1761
1762
1763
1764
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
1749
1750
1751
1752

1753
1754
1755
1756
1757
1758
1759

1760
1761
1762
1763
1764
1765
1766
1767

1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781

1782
1783
1784
1785
1786
1787
1788
1789
1790

1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801

1802
1803
1804
1805
1806
1807
1808
1809







-
+

















-
+

-
+











-
+






-
+







-
+













-
+








-
+










-
+







	TclStackFree(interp, freePtr);	/* Free CallFrame. */
	return TCL_ERROR;
    }

#if defined(TCL_COMPILE_DEBUG)
    if (tclTraceExec >= 1) {
	CallFrame *framePtr = iPtr->varFramePtr;
	int i;
	Tcl_Size i;

	if (framePtr->isProcCallFrame & FRAME_IS_LAMBDA) {
	    fprintf(stdout, "Calling lambda ");
	} else {
	    fprintf(stdout, "Calling proc ");
	}
	for (i = 0; i < framePtr->objc; i++) {
	    TclPrintObject(stdout, framePtr->objv[i], 15);
	    fprintf(stdout, " ");
	}
	fprintf(stdout, "\n");
	fflush(stdout);
    }
#endif /*TCL_COMPILE_DEBUG*/

#ifdef USE_DTRACE
    if (TCL_DTRACE_PROC_ARGS_ENABLED()) {
	int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;
	Tcl_Size l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;
	const char *a[10];
	int i;
	Tcl_Size i;

	for (i = 0 ; i < 10 ; i++) {
	    a[i] = (l < iPtr->varFramePtr->objc ?
		    TclGetString(iPtr->varFramePtr->objv[l]) : NULL);
	    l++;
	}
	TCL_DTRACE_PROC_ARGS(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7],
		a[8], a[9]);
    }
    if (TCL_DTRACE_PROC_INFO_ENABLED() && iPtr->cmdFramePtr) {
	Tcl_Obj *info = TclInfoFrame(interp, iPtr->cmdFramePtr);
	const char *a[6]; int i[2];
	const char *a[6]; Tcl_Size i[2];

	TclDTraceInfo(info, a, i);
	TCL_DTRACE_PROC_INFO(a[0], a[1], a[2], a[3], i[0], i[1], a[4], a[5]);
	TclDecrRefCount(info);
    }
    if (TCL_DTRACE_PROC_ENTRY_ENABLED()) {
	int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;
	Tcl_Size l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;

	TCL_DTRACE_PROC_ENTRY(l < iPtr->varFramePtr->objc ?
		TclGetString(iPtr->varFramePtr->objv[l]) : NULL,
		iPtr->varFramePtr->objc - l - 1,
		(Tcl_Obj **)(iPtr->varFramePtr->objv + l + 1));
    }
    if (TCL_DTRACE_PROC_ENTRY_ENABLED()) {
	int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;
	Tcl_Size l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;

	TCL_DTRACE_PROC_ENTRY(l < iPtr->varFramePtr->objc ?
		TclGetString(iPtr->varFramePtr->objv[l]) : NULL,
		iPtr->varFramePtr->objc - l - 1,
		(Tcl_Obj **)(iPtr->varFramePtr->objv + l + 1));
    }
#endif /* USE_DTRACE */

    /*
     * Invoke the commands in the procedure's body.
     */

    procPtr->refCount++;
    ByteCodeGetIntRep(procPtr->bodyPtr, &tclByteCodeType, codePtr);
    ByteCodeGetInternalRep(procPtr->bodyPtr, &tclByteCodeType, codePtr);

    TclNRAddCallback(interp, InterpProcNR2, procNameObj, errorProc,
	    NULL, NULL);
    return TclNRExecuteByteCode(interp, codePtr);
}

static int
InterpProcNR2(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    Proc *procPtr = iPtr->varFramePtr->procPtr;
    CallFrame *freePtr;
    Tcl_Obj *procNameObj = (Tcl_Obj *)data[0];
    ProcErrorProc *errorProc = (ProcErrorProc *)data[1];

    if (TCL_DTRACE_PROC_RETURN_ENABLED()) {
	int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;
	Tcl_Size l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;

	TCL_DTRACE_PROC_RETURN(l < iPtr->varFramePtr->objc ?
		TclGetString(iPtr->varFramePtr->objv[l]) : NULL, result);
    }
    if (procPtr->refCount-- <= 1) {
	TclProcCleanupProc(procPtr);
    }
1773
1774
1775
1776
1777
1778
1779
1780

1781
1782
1783
1784
1785
1786
1787
1818
1819
1820
1821
1822
1823
1824

1825
1826
1827
1828
1829
1830
1831
1832







-
+








    if (result != TCL_OK) {
	goto process;
    }

    done:
    if (TCL_DTRACE_PROC_RESULT_ENABLED()) {
	int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;
	Tcl_Size l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;
	Tcl_Obj *r = Tcl_GetObjResult(interp);

	TCL_DTRACE_PROC_RESULT(l < iPtr->varFramePtr->objc ?
		TclGetString(iPtr->varFramePtr->objv[l]) : NULL, result,
		TclGetString(r), r);
    }

1812
1813
1814
1815
1816
1817
1818
1819

1820
1821
1822
1823
1824
1825
1826
1857
1858
1859
1860
1861
1862
1863

1864
1865
1866
1867
1868
1869
1870
1871







-
+







	 * It's an error to get to this point from a 'break' or 'continue', so
	 * transform to an error now.
	 */

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"invoked \"%s\" outside of a loop",
		((result == TCL_BREAK) ? "break" : "continue")));
	Tcl_SetErrorCode(interp, "TCL", "RESULT", "UNEXPECTED", NULL);
	Tcl_SetErrorCode(interp, "TCL", "RESULT", "UNEXPECTED", (char *)NULL);
	result = TCL_ERROR;

	/* FALLTHRU */

    case TCL_ERROR:
	/*
	 * Now it _must_ be an error, so we need to log it as such. This means
1864
1865
1866
1867
1868
1869
1870
1871

1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882

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
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971


1972
1973
1974
1975
1976
1977
1978
1979
1980







-
+











+








-
+
+








-
+





-
+


















-
-
+
+







    const char *description,	/* string describing this body of code. */
    const char *procName)	/* Name of this procedure. */
{
    Interp *iPtr = (Interp *) interp;
    Tcl_CallFrame *framePtr;
    ByteCode *codePtr;

    ByteCodeGetIntRep(bodyPtr, &tclByteCodeType, codePtr);
    ByteCodeGetInternalRep(bodyPtr, &tclByteCodeType, codePtr);

    /*
     * If necessary, compile the procedure's body. The compiler will allocate
     * frame slots for the procedure's non-argument local variables. If the
     * ByteCode already exists, make sure it hasn't been invalidated by
     * someone redefining a core command (this might make the compiled code
     * wrong). Also, if the code was compiled in/for a different interpreter,
     * we recompile it. Note that compiling the body might increase
     * procPtr->numCompiledLocals if new local variables are found while
     * compiling.
     *
     * Ensure the ByteCode's procPtr is the same (or it is pure precompiled).
     * Precompiled procedure bodies, however, are immutable and therefore they
     * are not recompiled, even if things have changed.
     */

    if (codePtr != NULL) {
	if (((Interp *) *codePtr->interpHandle == iPtr)
		&& (codePtr->compileEpoch == iPtr->compileEpoch)
		&& (codePtr->nsPtr == nsPtr)
		&& (codePtr->nsEpoch == nsPtr->resolverEpoch)) {
		&& (codePtr->nsEpoch == nsPtr->resolverEpoch)
		&& ((codePtr->procPtr == procPtr) || !bodyPtr->bytes)) {
	    return TCL_OK;
	}

	if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
	    if ((Interp *) *codePtr->interpHandle != iPtr) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"a precompiled script jumped interps", -1));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
			"CROSSINTERPBYTECODE", NULL);
			"CROSSINTERPBYTECODE", (char *)NULL);
		return TCL_ERROR;
	    }
	    codePtr->compileEpoch = iPtr->compileEpoch;
	    codePtr->nsPtr = nsPtr;
	} else {
	    Tcl_StoreIntRep(bodyPtr, &tclByteCodeType, NULL);
	    Tcl_StoreInternalRep(bodyPtr, &tclByteCodeType, NULL);
	    codePtr = NULL;
	}
    }

    if (codePtr == NULL) {
	Tcl_HashEntry *hePtr;

#ifdef TCL_COMPILE_DEBUG
	if (tclTraceCompile >= 1) {
	    /*
	     * Display a line summarizing the top level command we are about
	     * to compile.
	     */

	    Tcl_Obj *message;

	    TclNewLiteralStringObj(message, "Compiling ");
	    Tcl_IncrRefCount(message);
	    Tcl_AppendStringsToObj(message, description, " \"", NULL);
	    Tcl_AppendLimitedToObj(message, procName, -1, 50, NULL);
	    Tcl_AppendStringsToObj(message, description, " \"", (char *)NULL);
	    Tcl_AppendLimitedToObj(message, procName, TCL_INDEX_NONE, 50, NULL);
	    fprintf(stdout, "%s\"\n", TclGetString(message));
	    Tcl_DecrRefCount(message);
	}
#else
    (void)description;
    (void)procName;
#endif
1980
1981
1982
1983
1984
1985
1986
1987

1988
1989
1990
1991
1992
1993
1994
2027
2028
2029
2030
2031
2032
2033

2034
2035
2036
2037
2038
2039
2040
2041







-
+







		/* isProcCallFrame */ 0);

	/*
	 * TIP #280: We get the invoking context from the cmdFrame which
	 * was saved by 'Tcl_ProcObjCmd' (using linePBodyPtr).
	 */

	hePtr = Tcl_FindHashEntry(iPtr->linePBodyPtr, (char *) procPtr);
	hePtr = Tcl_FindHashEntry(iPtr->linePBodyPtr, procPtr);

	/*
	 * Constructed saved frame has body as word 0. See Tcl_ProcObjCmd.
	 */

	iPtr->invokeWord = 0;
	iPtr->invokeCmdFramePtr = hePtr ? (CmdFrame *)Tcl_GetHashValue(hePtr) : NULL;
2028
2029
2030
2031
2032
2033
2034
2035
2036


2037
2038
2039

2040
2041
2042

2043
2044
2045
2046
2047
2048
2049
2075
2076
2077
2078
2079
2080
2081


2082
2083
2084
2085

2086
2087
2088

2089
2090
2091
2092
2093
2094
2095
2096







-
-
+
+


-
+


-
+







static void
MakeProcError(
    Tcl_Interp *interp,		/* The interpreter in which the procedure was
				 * called. */
    Tcl_Obj *procNameObj)	/* Name of the procedure. Used for error
				 * messages and trace information. */
{
    unsigned int overflow, limit = 60;
    size_t nameLen;
    int overflow, limit = 60;
    Tcl_Size nameLen;
    const char *procName = TclGetStringFromObj(procNameObj, &nameLen);

    overflow = (nameLen > limit);
    overflow = (nameLen > (Tcl_Size)limit);
    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
	    "\n    (procedure \"%.*s%s\" line %d)",
	    (int)(overflow ? limit :nameLen), procName,
	    (overflow ? limit : (int)nameLen), procName,
	    (overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
}

/*
 *----------------------------------------------------------------------
 *
 * TclProcDeleteProc --
2061
2062
2063
2064
2065
2066
2067
2068

2069
2070
2071
2072
2073
2074
2075
2108
2109
2110
2111
2112
2113
2114

2115
2116
2117
2118
2119
2120
2121
2122







-
+







 *	procedure completes.
 *
 *----------------------------------------------------------------------
 */

void
TclProcDeleteProc(
    ClientData clientData)	/* Procedure to be deleted. */
    void *clientData)		/* Procedure to be deleted. */
{
    Proc *procPtr = (Proc *)clientData;

    if (procPtr->refCount-- <= 1) {
	TclProcCleanupProc(procPtr);
    }
}
2089
2090
2091
2092
2093
2094
2095
2096

2097
2098
2099
2100
2101
2102
2103
2104
2105
2106







2107
2108
2109
2110
2111
2112
2113
2136
2137
2138
2139
2140
2141
2142

2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167







-
+










+
+
+
+
+
+
+







 *	Memory gets freed.
 *
 *----------------------------------------------------------------------
 */

void
TclProcCleanupProc(
    Proc *procPtr)	/* Procedure to be deleted. */
    Proc *procPtr)		/* Procedure to be deleted. */
{
    CompiledLocal *localPtr;
    Tcl_Obj *bodyPtr = procPtr->bodyPtr;
    Tcl_Obj *defPtr;
    Tcl_ResolvedVarInfo *resVarInfo;
    Tcl_HashEntry *hePtr = NULL;
    CmdFrame *cfPtr = NULL;
    Interp *iPtr = procPtr->iPtr;

    if (bodyPtr != NULL) {
	/* procPtr is stored in body's ByteCode, so ensure to reset it. */
	ByteCode *codePtr;

	ByteCodeGetInternalRep(bodyPtr, &tclByteCodeType, codePtr);
	if (codePtr != NULL && codePtr->procPtr == procPtr) {
	    codePtr->procPtr = NULL;
	}
	Tcl_DecrRefCount(bodyPtr);
    }
    for (localPtr = procPtr->firstLocalPtr; localPtr != NULL; ) {
	CompiledLocal *nextPtr = localPtr->nextPtr;

	resVarInfo = localPtr->resolveInfo;
	if (resVarInfo) {
2133
2134
2135
2136
2137
2138
2139
2140

2141
2142
2143
2144
2145
2146
2147
2187
2188
2189
2190
2191
2192
2193

2194
2195
2196
2197
2198
2199
2200
2201







-
+







     * procbody structures created by tbcload.
     */

    if (iPtr == NULL) {
	return;
    }

    hePtr = Tcl_FindHashEntry(iPtr->linePBodyPtr, (char *) procPtr);
    hePtr = Tcl_FindHashEntry(iPtr->linePBodyPtr, procPtr);
    if (!hePtr) {
	return;
    }

    cfPtr = (CmdFrame *)Tcl_GetHashValue(hePtr);

    if (cfPtr) {
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
2257
2258
2259
2260
2261
2262
2263

2264
2265




2266
2267
2268
2269
2270
2271

2272
2273
2274
2275
2276
2277
2278
2279
2280

2281
2282
2283

2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297







-
+

-
-
-
-
+
+
+
+


-
+
+







-
+


-
+
+
+
+
+
+
+







    }
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetObjInterpProc --
 * TclGetObjInterpProc/TclGetObjInterpProc2 --
 *
 *	Returns a pointer to the TclObjInterpProc function; this is different
 *	from the value obtained from the TclObjInterpProc reference on systems
 *	like Windows where import and export versions of a function exported
 *	by a DLL exist.
 *	Returns a pointer to the TclObjInterpProc/ObjInterpProc2 functions;
 *	this is different from the value obtained from the TclObjInterpProc
 *	reference on systems like Windows where import and export versions
 *	of a function exported by a DLL exist.
 *
 * Results:
 *	Returns the internal address of the TclObjInterpProc function.
 *	Returns the internal address of the TclObjInterpProc/ObjInterpProc2
 *	functions.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

TclObjCmdProcType
Tcl_ObjCmdProc *
TclGetObjInterpProc(void)
{
    return (TclObjCmdProcType) TclObjInterpProc;
    return TclObjInterpProc;
}

Tcl_ObjCmdProc2 *
TclGetObjInterpProc2(void)
{
    return ObjInterpProc2;
}

/*
 *----------------------------------------------------------------------
 *
 * TclNewProcBodyObj --
 *
2257
2258
2259
2260
2261
2262
2263
2264

2265
2266
2267
2268
2269
2270
2271
2318
2319
2320
2321
2322
2323
2324

2325
2326
2327
2328
2329
2330
2331
2332







-
+








    if (!procPtr) {
	return NULL;
    }

    TclNewObj(objPtr);
    if (objPtr) {
	ProcSetIntRep(objPtr, procPtr);
	ProcSetInternalRep(objPtr, procPtr);
    }

    return objPtr;
}

/*
 *----------------------------------------------------------------------
2286
2287
2288
2289
2290
2291
2292
2293

2294
2295

2296
2297
2298
2299
2300
2301
2302
2347
2348
2349
2350
2351
2352
2353

2354
2355

2356
2357
2358
2359
2360
2361
2362
2363







-
+

-
+








static void
ProcBodyDup(
    Tcl_Obj *srcPtr,		/* Object to copy. */
    Tcl_Obj *dupPtr)		/* Target object for the duplication. */
{
    Proc *procPtr;
    ProcGetIntRep(srcPtr, procPtr);
    ProcGetInternalRep(srcPtr, procPtr);

    ProcSetIntRep(dupPtr, procPtr);
    ProcSetInternalRep(dupPtr, procPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * ProcBodyFree --
 *
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
2390
2391
2392
2393
2394
2395
2396
2397








2398
2399
2400
2401
2402
2403

2404
2405
2406
2407
2408
2409
2410
2377
2378
2379
2380
2381
2382
2383

2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397

2398
2399
2400
2401
2402
2403
2404
2405
2406
2407

2408
2409
2410
2411
2412

2413
2414
2415
2416
2417

2418
2419
2420
2421
2422

2423
2424
2425
2426
2427
2428

2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440

2441
2442
2443
2444
2445

2446
2447
2448
2449
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







-
+













-
+









-
+




-
+




-
+




-
+





-
+











-
+




-
+
+












+
+
+
+
+
+
+
+





-
+








static void
ProcBodyFree(
    Tcl_Obj *objPtr)		/* The object to clean up. */
{
    Proc *procPtr;

    ProcGetIntRep(objPtr, procPtr);
    ProcGetInternalRep(objPtr, procPtr);

    if (procPtr->refCount-- <= 1) {
	TclProcCleanupProc(procPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * DupLambdaInternalRep, FreeLambdaInternalRep, SetLambdaFromAny --
 *
 *	How to manage the internal representations of lambda term objects.
 *	Syntactically they look like a two- or three-element list, where the
 *	first element is the formal arguments, the second is the the body, and
 *	first element is the formal arguments, the second is the body, and
 *	the (optional) third is the namespace to execute the lambda term
 *	within (the global namespace is assumed if it is absent).
 *
 *----------------------------------------------------------------------
 */

static void
DupLambdaInternalRep(
    Tcl_Obj *srcPtr,		/* Object with internal rep to copy. */
    Tcl_Obj *copyPtr)	/* Object with internal rep to set. */
    Tcl_Obj *copyPtr)		/* Object with internal rep to set. */
{
    Proc *procPtr;
    Tcl_Obj *nsObjPtr;

    LambdaGetIntRep(srcPtr, procPtr, nsObjPtr);
    LambdaGetInternalRep(srcPtr, procPtr, nsObjPtr);
    assert(procPtr != NULL);

    procPtr->refCount++;

    LambdaSetIntRep(copyPtr, procPtr, nsObjPtr);
    LambdaSetInternalRep(copyPtr, procPtr, nsObjPtr);
}

static void
FreeLambdaInternalRep(
    Tcl_Obj *objPtr)	/* CmdName object with internal representation
    Tcl_Obj *objPtr)		/* CmdName object with internal representation
				 * to free. */
{
    Proc *procPtr;
    Tcl_Obj *nsObjPtr;

    LambdaGetIntRep(objPtr, procPtr, nsObjPtr);
    LambdaGetInternalRep(objPtr, procPtr, nsObjPtr);
    assert(procPtr != NULL);

    if (procPtr->refCount-- <= 1) {
	TclProcCleanupProc(procPtr);
    }
    TclDecrRefCount(nsObjPtr);
}

static int
SetLambdaFromAny(
    Tcl_Interp *interp,		/* Used for error reporting if not NULL. */
    Tcl_Obj *objPtr)	/* The object to convert. */
    Tcl_Obj *objPtr)		/* The object to convert. */
{
    Interp *iPtr = (Interp *) interp;
    const char *name;
    Tcl_Obj *argsPtr, *bodyPtr, *nsObjPtr, **objv;
    int isNew, objc, result;
    int isNew, result;
    Tcl_Size objc;
    CmdFrame *cfPtr = NULL;
    Proc *procPtr;

    if (interp == NULL) {
	return TCL_ERROR;
    }

    /*
     * Convert objPtr to list type first; if it cannot be converted, or if its
     * length is not 2, then it cannot be converted to lambdaType.
     */

    result = TclListObjLength(NULL, objPtr, &objc);
    if ((result != TCL_OK) || ((objc != 2) && (objc != 3))) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't interpret \"%s\" as a lambda expression",
		Tcl_GetString(objPtr)));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "LAMBDA", (char *)NULL);
	return TCL_ERROR;
    }
    result = TclListObjGetElements(NULL, objPtr, &objc, &objv);
    if ((result != TCL_OK) || ((objc != 2) && (objc != 3))) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't interpret \"%s\" as a lambda expression",
		TclGetString(objPtr)));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "LAMBDA", NULL);
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "LAMBDA", (char *)NULL);
	return TCL_ERROR;
    }

    argsPtr = objv[0];
    bodyPtr = objv[1];

    /*
2474
2475
2476
2477
2478
2479
2480
2481

2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493

2494
2495
2496
2497
2498
2499
2500
2544
2545
2546
2547
2548
2549
2550

2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562

2563
2564
2565
2566
2567
2568
2569
2570







-
+











-
+







	    /*
	     * We can record source location within a lambda only if the body
	     * was not created by substitution.
	     */

	    if (contextPtr->line
		    && (contextPtr->nline >= 2) && (contextPtr->line[1] >= 0)) {
		int buf[2];
		Tcl_Size buf[2];

		/*
		 * Move from approximation (line of list cmd word) to actual
		 * location (line of 2nd list element).
		 */

		cfPtr = (CmdFrame *)Tcl_Alloc(sizeof(CmdFrame));
		TclListLines(objPtr, contextPtr->line[1], 2, buf, NULL);

		cfPtr->level = -1;
		cfPtr->type = contextPtr->type;
		cfPtr->line = (int *)Tcl_Alloc(sizeof(int));
		cfPtr->line = (Tcl_Size *)Tcl_Alloc(sizeof(Tcl_Size));
		cfPtr->line[0] = buf[1];
		cfPtr->nline = 1;
		cfPtr->framePtr = NULL;
		cfPtr->nextPtr = NULL;

		cfPtr->data.eval.path = contextPtr->data.eval.path;
		Tcl_IncrRefCount(cfPtr->data.eval.path);
2521
2522
2523
2524
2525
2526
2527
2528

2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542

2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555

2556
2557
2558
2559
2560
2561

2562
2563
2564
2565
2566
2567
2568
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







-
+













-
+












-
+





-
+







     */

    if (objc == 2) {
	TclNewLiteralStringObj(nsObjPtr, "::");
    } else {
	const char *nsName = TclGetString(objv[2]);

	if ((*nsName != ':') || (*(nsName+1) != ':')) {
	if ((nsName[0] != ':') || (nsName[1] != ':')) {
	    TclNewLiteralStringObj(nsObjPtr, "::");
	    Tcl_AppendObjToObj(nsObjPtr, objv[2]);
	} else {
	    nsObjPtr = objv[2];
	}
    }

    /*
     * Free the list internalrep of objPtr - this will free argsPtr, but
     * bodyPtr retains a reference from the Proc structure. Then finish the
     * conversion to lambdaType.
     */

    LambdaSetIntRep(objPtr, procPtr, nsObjPtr);
    LambdaSetInternalRep(objPtr, procPtr, nsObjPtr);
    return TCL_OK;
}

Proc *
TclGetLambdaFromObj(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    Tcl_Obj **nsObjPtrPtr)
{
    Proc *procPtr;
    Tcl_Obj *nsObjPtr;

    LambdaGetIntRep(objPtr, procPtr, nsObjPtr);
    LambdaGetInternalRep(objPtr, procPtr, nsObjPtr);

    if (procPtr == NULL) {
	if (SetLambdaFromAny(interp, objPtr) != TCL_OK) {
	    return NULL;
	}
	LambdaGetIntRep(objPtr, procPtr, nsObjPtr);
	LambdaGetInternalRep(objPtr, procPtr, nsObjPtr);
    }

    assert(procPtr != NULL);
    if (procPtr->iPtr != (Interp *)interp) {
	return NULL;
    }

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
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







-
+









-
+







 *	Depends on the content of the lambda term (i.e., objv[1]).
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ApplyObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, TclNRApplyObjCmd, clientData, objc, objv);
}

int
TclNRApplyObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Proc *procPtr = NULL;
    Tcl_Obj *lambdaPtr, *nsObjPtr;
    int result;
2664
2665
2666
2667
2668
2669
2670
2671

2672
2673
2674
2675
2676
2677
2678
2734
2735
2736
2737
2738
2739
2740

2741
2742
2743
2744
2745
2746
2747
2748







-
+







	result = TclNRInterpProcCore(interp, objv[1], 2, &MakeLambdaError);
    }
    return result;
}

static int
ApplyNR2(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    ApplyExtraData *extraPtr = (ApplyExtraData *)data[0];

    TclStackFree(interp, extraPtr);
    return result;
2699
2700
2701
2702
2703
2704
2705
2706
2707


2708
2709
2710

2711
2712
2713

2714
2715
2716
2717
2718
2719
2720
2769
2770
2771
2772
2773
2774
2775


2776
2777
2778
2779

2780
2781
2782

2783
2784
2785
2786
2787
2788
2789
2790







-
-
+
+


-
+


-
+







static void
MakeLambdaError(
    Tcl_Interp *interp,		/* The interpreter in which the procedure was
				 * called. */
    Tcl_Obj *procNameObj)	/* Name of the procedure. Used for error
				 * messages and trace information. */
{
    unsigned int overflow, limit = 60;
    size_t nameLen;
    int overflow, limit = 60;
    Tcl_Size nameLen;
    const char *procName = TclGetStringFromObj(procNameObj, &nameLen);

    overflow = (nameLen > limit);
    overflow = (nameLen > (Tcl_Size)limit);
    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
	    "\n    (lambda term \"%.*s%s\" line %d)",
	    (int)(overflow ? limit : nameLen), procName,
	    (overflow ? limit : (int)nameLen), procName,
	    (overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetCmdFrameForProcedure --

Changes to generic/tclProcess.c.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tclProcess.c --
 *
 *	This file implements the "tcl::process" ensemble for subprocess
 *	management as defined by TIP #462.
 *
 * Copyright (c) 2017 Frederic Bonnet.
 * Copyright © 2017 Frederic Bonnet.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

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
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







-
+



+










-
+


-
+



-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-








typedef struct ProcessInfo {
    Tcl_Pid pid;		/* Process id. */
    int resolvedPid;		/* Resolved process id. */
    int purge;			/* Purge eventualy. */
    TclProcessWaitStatus status;/* Process status. */
    int code;			/* Error code, exit status or signal
				   number. */
				 * number. */
    Tcl_Obj *msg;		/* Error message. */
    Tcl_Obj *error;		/* Error code. */
} ProcessInfo;

static Tcl_HashTable infoTablePerPid;
static Tcl_HashTable infoTablePerResolvedPid;
static int infoTablesInitialized = 0;	/* 0 means not yet initialized. */
TCL_DECLARE_MUTEX(infoTablesMutex)

 /*
 * Prototypes for functions defined later in this file:
 */

static void		InitProcessInfo(ProcessInfo *info, Tcl_Pid pid,
			    int resolvedPid);
			    Tcl_Size resolvedPid);
static void		FreeProcessInfo(ProcessInfo *info);
static int		RefreshProcessInfo(ProcessInfo *info, int options);
static TclProcessWaitStatus WaitProcessStatus(Tcl_Pid pid, size_t resolvedPid,
static TclProcessWaitStatus WaitProcessStatus(Tcl_Pid pid, Tcl_Size resolvedPid,
			    int options, int *codePtr, Tcl_Obj **msgPtr,
			    Tcl_Obj **errorObjPtr);
static Tcl_Obj *	BuildProcessStatusObj(ProcessInfo *info);
static int		ProcessListObjCmd(ClientData clientData,
static Tcl_ObjCmdProc ProcessListObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		ProcessStatusObjCmd(ClientData clientData,
static Tcl_ObjCmdProc ProcessStatusObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		ProcessPurgeObjCmd(ClientData clientData,
static Tcl_ObjCmdProc ProcessPurgeObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		ProcessAutopurgeObjCmd(ClientData clientData,
static Tcl_ObjCmdProc ProcessAutopurgeObjCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);

/*
 *----------------------------------------------------------------------
 *
 * InitProcessInfo --
 *
 *	Initializes the ProcessInfo structure.
80
81
82
83
84
85
86
87

88
89
90
91
92
93
94
73
74
75
76
77
78
79

80
81
82
83
84
85
86
87







-
+







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

void
InitProcessInfo(
    ProcessInfo *info,		/* Structure to initialize. */
    Tcl_Pid pid,		/* Process id. */
    int resolvedPid)		/* Resolved process id. */
    Tcl_Size resolvedPid)	/* Resolved process id. */
{
    info->pid = pid;
    info->resolvedPid = resolvedPid;
    info->purge = 0;
    info->status = TCL_PROCESS_UNCHANGED;
    info->code = 0;
    info->msg = NULL;
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
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







-
+
-








+
-
-
+
+
+
+
+







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

int
RefreshProcessInfo(
    ProcessInfo *info,		/* Structure to refresh. */
    int options			/* Options passed to WaitProcessStatus. */
    int options)		/* Options passed to WaitProcessStatus. */
)
{
    if (info->status == TCL_PROCESS_UNCHANGED) {
	/*
	 * Refresh & store status.
	 */

	info->status = WaitProcessStatus(info->pid, info->resolvedPid,
		options, &info->code, &info->msg, &info->error);
	if (info->msg) {
	if (info->msg) Tcl_IncrRefCount(info->msg);
	if (info->error) Tcl_IncrRefCount(info->error);
	    Tcl_IncrRefCount(info->msg);
	}
	if (info->error) {
	    Tcl_IncrRefCount(info->error);
	}
	return (info->status != TCL_PROCESS_UNCHANGED);
    } else {
	/*
	 * No change.
	 */

	return 0;
189
190
191
192
193
194
195
196

197
198
199
200
201
202
203

204
205
206
207
208
209
210
211
185
186
187
188
189
190
191

192
193
194
195
196
197
198

199

200
201
202
203
204
205
206







-
+






-
+
-







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

TclProcessWaitStatus
WaitProcessStatus(
    Tcl_Pid pid,		/* Process id. */
    size_t resolvedPid,		/* Resolved process id. */
    Tcl_Size resolvedPid,	/* Resolved process id. */
    int options,		/* Options passed to Tcl_WaitPid. */
    int *codePtr,		/* If non-NULL, will receive either:
				 *  - 0 for normal exit.
				 *  - errno in case of error.
				 *  - non-zero exit code for abormal exit.
				 *  - signal number if killed or suspended.
				 *  - Tcl_WaitPid status in all other cases.
				 *  - Tcl_WaitPid status in all other cases. */
				 */
    Tcl_Obj **msgObjPtr,	/* If non-NULL, will receive error message. */
    Tcl_Obj **errorObjPtr)	/* If non-NULL, will receive error code. */
{
    int waitStatus;
    Tcl_Obj *errorStrings[5];
    const char *msg;

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
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







-
-
-
+
+
+
+
+
+
+








+
-
+
+





-
-
+
+
+
+
+
+







+
-
-
+
+
+
















+
-
-
-
+
+
+
+
+
















+
-
-
-
+
+
+
+
+















-
-
-
+
+
+
+
+
+
+











-







	     * This changeup in message suggested by Mark Diekhans to
	     * remind people that ECHILD errors can occur on some
	     * systems if SIGCHLD isn't in its default state.
	     */

	    msg = "child process lost (is SIGCHLD ignored or trapped?)";
	}
	if (codePtr) *codePtr = errno;
	if (msgObjPtr) *msgObjPtr = Tcl_ObjPrintf(
		"error waiting for process to exit: %s", msg);
	if (codePtr) {
	    *codePtr = errno;
	}
	if (msgObjPtr) {
	    *msgObjPtr = Tcl_ObjPrintf(
		    "error waiting for process to exit: %s", msg);
	}
	if (errorObjPtr) {
	    errorStrings[0] = Tcl_NewStringObj("POSIX", -1);
	    errorStrings[1] = Tcl_NewStringObj(Tcl_ErrnoId(), -1);
	    errorStrings[2] = Tcl_NewStringObj(msg, -1);
	    *errorObjPtr = Tcl_NewListObj(3, errorStrings);
	}
	return TCL_PROCESS_ERROR;
    } else if (WIFEXITED(waitStatus)) {
	if (codePtr) {
	if (codePtr) *codePtr = WEXITSTATUS(waitStatus);
	    *codePtr = WEXITSTATUS(waitStatus);
	}
	if (!WEXITSTATUS(waitStatus)) {
	    /*
	     * Normal exit.
	     */

	    if (msgObjPtr) *msgObjPtr = NULL;
	    if (errorObjPtr) *errorObjPtr = NULL;
	    if (msgObjPtr) {
		*msgObjPtr = NULL;
	    }
	    if (errorObjPtr) {
		*errorObjPtr = NULL;
	    }
	} else {
	    /*
	     * CHILDSTATUS pid code
	     *
	     * Child exited with a non-zero exit status.
	     */

	    if (msgObjPtr) {
	    if (msgObjPtr) *msgObjPtr = Tcl_NewStringObj(
		    "child process exited abnormally", -1);
		*msgObjPtr = Tcl_NewStringObj(
			"child process exited abnormally", -1);
	    }
	    if (errorObjPtr) {
		errorStrings[0] = Tcl_NewStringObj("CHILDSTATUS", -1);
		TclNewIntObj(errorStrings[1], resolvedPid);
		TclNewIntObj(errorStrings[2], WEXITSTATUS(waitStatus));
		*errorObjPtr = Tcl_NewListObj(3, errorStrings);
	    }
	}
	return TCL_PROCESS_EXITED;
    } else if (WIFSIGNALED(waitStatus)) {
	/*
	 * CHILDKILLED pid sigName msg
	 *
	 * Child killed because of a signal.
	 */

	msg = Tcl_SignalMsg(WTERMSIG(waitStatus));
	if (codePtr) {
	if (codePtr) *codePtr = WTERMSIG(waitStatus);
	if (msgObjPtr) *msgObjPtr = Tcl_ObjPrintf(
		"child killed: %s", msg);
	    *codePtr = WTERMSIG(waitStatus);
	}
	if (msgObjPtr) {
	    *msgObjPtr = Tcl_ObjPrintf("child killed: %s", msg);
	}
	if (errorObjPtr) {
	    errorStrings[0] = Tcl_NewStringObj("CHILDKILLED", -1);
	    TclNewIntObj(errorStrings[1], resolvedPid);
	    errorStrings[2] = Tcl_NewStringObj(Tcl_SignalId(WTERMSIG(waitStatus)), -1);
	    errorStrings[3] = Tcl_NewStringObj(msg, -1);
	    *errorObjPtr = Tcl_NewListObj(4, errorStrings);
	}
	return TCL_PROCESS_SIGNALED;
    } else if (WIFSTOPPED(waitStatus)) {
	/*
	 * CHILDSUSP pid sigName msg
	 *
	 * Child suspended because of a signal.
	 */

	msg = Tcl_SignalMsg(WSTOPSIG(waitStatus));
	if (codePtr) {
	if (codePtr) *codePtr = WSTOPSIG(waitStatus);
	if (msgObjPtr) *msgObjPtr = Tcl_ObjPrintf(
		"child suspended: %s", msg);
	    *codePtr = WSTOPSIG(waitStatus);
	}
	if (msgObjPtr) {
	    *msgObjPtr = Tcl_ObjPrintf("child suspended: %s", msg);
	}
	if (errorObjPtr) {
	    errorStrings[0] = Tcl_NewStringObj("CHILDSUSP", -1);
	    TclNewIntObj(errorStrings[1], resolvedPid);
	    errorStrings[2] = Tcl_NewStringObj(Tcl_SignalId(WSTOPSIG(waitStatus)), -1);
	    errorStrings[3] = Tcl_NewStringObj(msg, -1);
	    *errorObjPtr = Tcl_NewListObj(4, errorStrings);
	}
	return TCL_PROCESS_STOPPED;
    } else {
	/*
	 * TCL OPERATION EXEC ODDWAITRESULT
	 *
	 * Child wait status didn't make sense.
	 */

	if (codePtr) *codePtr = waitStatus;
	if (msgObjPtr) *msgObjPtr = Tcl_NewStringObj(
		"child wait status didn't make sense\n", -1);
	if (codePtr) {
	    *codePtr = waitStatus;
	}
	if (msgObjPtr) {
	    *msgObjPtr = Tcl_NewStringObj(
		    "child wait status didn't make sense\n", -1);
	}
	if (errorObjPtr) {
	    errorStrings[0] = Tcl_NewStringObj("TCL", -1);
	    errorStrings[1] = Tcl_NewStringObj("OPERATION", -1);
	    errorStrings[2] = Tcl_NewStringObj("EXEC", -1);
	    errorStrings[3] = Tcl_NewStringObj("ODDWAITRESULT", -1);
	    TclNewIntObj(errorStrings[4], resolvedPid);
	    *errorObjPtr = Tcl_NewListObj(5, errorStrings);
	}
	return TCL_PROCESS_UNKNOWN_STATUS;
    }
}


/*
 *----------------------------------------------------------------------
 *
 * BuildProcessStatusObj --
 *
 *	Build a list object with process status. The first element is always
398
399
400
401
402
403
404
405

406
407
408
409
410
411
412
414
415
416
417
418
419
420

421
422
423
424
425
426
427
428







-
+







 *	Access to the internal structures is protected by infoTablesMutex.
 *
 *----------------------------------------------------------------------
 */

static int
ProcessListObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *list;
    Tcl_HashEntry *entry;
    Tcl_HashSearch search;
449
450
451
452
453
454
455
456

457
458
459
460
461
462

463
464
465
466

467
468
469
470
471
472
473
474
475
476
477

478
479
480
481
482
483
484
485
486
487
488

489
490
491
492
493
494
495
465
466
467
468
469
470
471

472
473
474
475
476
477

478
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







-
+





-
+



-
+


-







-
+










-
+







 *	Calls RefreshProcessInfo, which can block if -wait switch is given.
 *
 *----------------------------------------------------------------------
 */

static int
ProcessStatusObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *dict;
    int index, options = WNOHANG;
    int options = WNOHANG;
    Tcl_HashEntry *entry;
    Tcl_HashSearch search;
    ProcessInfo *info;
    int numPids;
    Tcl_Size i, numPids;
    Tcl_Obj **pidObjs;
    int result;
    int i;
    int pid;
    Tcl_Obj *const *savedobjv = objv;
    static const char *const switches[] = {
	"-wait", "--", NULL
    };
    enum switchesEnum {
	STATUS_WAIT, STATUS_LAST
    };
    } index;

    while (objc > 1) {
	if (TclGetString(objv[1])[0] != '-') {
	    break;
	}
	if (Tcl_GetIndexFromObj(interp, objv[1], switches, "switches", 0,
		&index) != TCL_OK) {
	    return TCL_ERROR;
	}
	++objv; --objc;
	if (STATUS_WAIT == (enum switchesEnum) index) {
	if (STATUS_WAIT == index) {
	    options = 0;
	} else {
	    break;
	}
    }

    if (objc != 1 && objc != 2) {
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
534
535
536
537
538
539
540

541
542
543
544
545
546
547
548
549
550

551
552
553
554
555
556
557
558







-
+









-
+







		Tcl_DeleteHashEntry(entry);
		FreeProcessInfo(info);
	    } else {
		/*
		 * Add to result.
		 */

		Tcl_DictObjPut(interp, dict, Tcl_NewWideIntObj(info->resolvedPid),
		Tcl_DictObjPut(NULL, dict, Tcl_NewIntObj(info->resolvedPid),
			BuildProcessStatusObj(info));
	    }
	}
	Tcl_MutexUnlock(&infoTablesMutex);
    } else {
	/*
	 * Only return statuses of provided processes.
	 */

	result = Tcl_ListObjGetElements(interp, objv[1], &numPids, &pidObjs);
	result = TclListObjGetElements(interp, objv[1], &numPids, &pidObjs);
	if (result != TCL_OK) {
	    return result;
	}
	dict = Tcl_NewDictObj();
	Tcl_MutexLock(&infoTablesMutex);
	for (i = 0; i < numPids; i++) {
	    result = Tcl_GetIntFromObj(interp, pidObjs[i], &pid);
569
570
571
572
573
574
575
576

577
578
579
580
581
582
583
584
585
586
587
588
589
590

591
592
593
594
595
596
597
598







-
+







		Tcl_DeleteHashEntry(entry);
		FreeProcessInfo(info);
	    } else {
		/*
		 * Add to result.
		 */

		Tcl_DictObjPut(interp, dict, Tcl_NewWideIntObj(info->resolvedPid),
		Tcl_DictObjPut(NULL, dict, Tcl_NewIntObj(info->resolvedPid),
			BuildProcessStatusObj(info));
	    }
	}
	Tcl_MutexUnlock(&infoTablesMutex);
    }
    Tcl_SetObjResult(interp, dict);
    return TCL_OK;
597
598
599
600
601
602
603
604

605
606
607
608
609
610
611
612

613
614

615
616
617
618
619
620
621
622
623
612
613
614
615
616
617
618

619
620
621
622
623
624
625
626

627
628

629


630
631
632
633
634
635
636







-
+







-
+

-
+
-
-







 *	Frees all ProcessInfo structures with their purge flag set.
 *
 *----------------------------------------------------------------------
 */

static int
ProcessPurgeObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_HashEntry *entry;
    Tcl_HashSearch search;
    ProcessInfo *info;
    int numPids;
    Tcl_Size i, numPids;
    Tcl_Obj **pidObjs;
    int result;
    int result, pid;
    int i;
    int pid;

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

    /*
644
645
646
647
648
649
650
651

652
653
654
655
656
657
658
657
658
659
660
661
662
663

664
665
666
667
668
669
670
671







-
+







	}
	Tcl_MutexUnlock(&infoTablesMutex);
    } else {
	/*
	 * Purge only provided processes.
	 */

	result = Tcl_ListObjGetElements(interp, objv[1], &numPids, &pidObjs);
	result = TclListObjGetElements(interp, objv[1], &numPids, &pidObjs);
	if (result != TCL_OK) {
	    return result;
	}
	Tcl_MutexLock(&infoTablesMutex);
	for (i = 0; i < numPids; i++) {
	    result = Tcl_GetIntFromObj(interp, pidObjs[i], &pid);
	    if (result != TCL_OK) {
697
698
699
700
701
702
703
704

705
706
707
708
709
710
711
710
711
712
713
714
715
716

717
718
719
720
721
722
723
724







-
+







 *	Alters detached process handling by Tcl_ReapDetachedProcs().
 *
 *----------------------------------------------------------------------
 */

static int
ProcessAutopurgeObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{

    if (objc != 1 && objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?flag?");
796
797
798
799
800
801
802
803

804
805
806
807
808
809
810
809
810
811
812
813
814
815

816
817
818
819
820
821
822
823







-
+







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

void
TclProcessCreated(
    Tcl_Pid pid)		/* Process id. */
{
    size_t resolvedPid;
    Tcl_Size resolvedPid;
    Tcl_HashEntry *entry, *entry2;
    int isNew;
    ProcessInfo *info;

    /*
     * Get resolved pid first.
     */
822
823
824
825
826
827
828

829


830
831
832
833
834
835
836
835
836
837
838
839
840
841
842

843
844
845
846
847
848
849
850
851







+
-
+
+







	/*
	 * Pid was reused, free old info and reuse structure.
	 */

	info = (ProcessInfo *) Tcl_GetHashValue(entry);
	entry2 = Tcl_FindHashEntry(&infoTablePerResolvedPid,
		INT2PTR(resolvedPid));
	if (entry2) {
	if (entry2) Tcl_DeleteHashEntry(entry2);
	    Tcl_DeleteHashEntry(entry2);
	}
	FreeProcessInfo(info);
    }

    /*
     * Allocate and initialize info structure.
     */

871
872
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
898
899
900
901
902







903
904
905
906
907
908
909
910
911
912
913

914
915
916
917
918
919
920
921
922
923

924
925
926
927
928
929
930
931
932
933
934
935
936















937
938
939
940
941
942
943
886
887
888
889
890
891
892

893

894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913



914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929

930
931
932
933
934
935
936
937
938
939

940
941
942
943
944
945
946
947
948
949





950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971







-
+
-




















-
-
-
+
+
+
+
+
+
+









-

+








-

+








-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    Tcl_Pid pid,		/* Process id. */
    int options,		/* Options passed to WaitProcessStatus. */
    int *codePtr,		/* If non-NULL, will receive either:
				 *  - 0 for normal exit.
				 *  - errno in case of error.
				 *  - non-zero exit code for abormal exit.
				 *  - signal number if killed or suspended.
				 *  - Tcl_WaitPid status in all other cases.
				 *  - Tcl_WaitPid status in all other cases. */
				 */
    Tcl_Obj **msgObjPtr,	/* If non-NULL, will receive error message. */
    Tcl_Obj **errorObjPtr)	/* If non-NULL, will receive error code. */
{
    Tcl_HashEntry *entry;
    ProcessInfo *info;
    TclProcessWaitStatus result;

    /*
     * First search for pid in table.
     */

    Tcl_MutexLock(&infoTablesMutex);
    entry = Tcl_FindHashEntry(&infoTablePerPid, pid);
    if (!entry) {
	/*
	 * Unknown process, just call WaitProcessStatus and return.
	 */

	result = WaitProcessStatus(pid, TclpGetPid(pid), options, codePtr,
		msgObjPtr, errorObjPtr);
	if (msgObjPtr && *msgObjPtr) Tcl_IncrRefCount(*msgObjPtr);
	if (errorObjPtr && *errorObjPtr) Tcl_IncrRefCount(*errorObjPtr);
    Tcl_MutexUnlock(&infoTablesMutex);
	if (msgObjPtr && *msgObjPtr) {
	    Tcl_IncrRefCount(*msgObjPtr);
	}
	if (errorObjPtr && *errorObjPtr) {
	    Tcl_IncrRefCount(*errorObjPtr);
	}
	Tcl_MutexUnlock(&infoTablesMutex);
	return result;
    }

    info = (ProcessInfo *) Tcl_GetHashValue(entry);
    if (info->purge) {
	/*
	 * Process has completed but TclProcessWait has already been called,
	 * so report no change.
	 */
    Tcl_MutexUnlock(&infoTablesMutex);

	Tcl_MutexUnlock(&infoTablesMutex);
	return TCL_PROCESS_UNCHANGED;
    }

    RefreshProcessInfo(info, options);
    if (info->status == TCL_PROCESS_UNCHANGED) {
	/*
	 * No change, stop there.
	 */
    Tcl_MutexUnlock(&infoTablesMutex);

	Tcl_MutexUnlock(&infoTablesMutex);
	return TCL_PROCESS_UNCHANGED;
    }

    /*
     * Set return values.
     */

    result = info->status;
    if (codePtr) *codePtr = info->code;
    if (msgObjPtr) *msgObjPtr = info->msg;
    if (errorObjPtr) *errorObjPtr = info->error;
    if (msgObjPtr && *msgObjPtr) Tcl_IncrRefCount(*msgObjPtr);
    if (errorObjPtr && *errorObjPtr) Tcl_IncrRefCount(*errorObjPtr);
    if (codePtr) {
	*codePtr = info->code;
    }
    if (msgObjPtr) {
	*msgObjPtr = info->msg;
    }
    if (errorObjPtr) {
	*errorObjPtr = info->error;
    }
    if (msgObjPtr && *msgObjPtr) {
	Tcl_IncrRefCount(*msgObjPtr);
    }
    if (errorObjPtr && *errorObjPtr) {
	Tcl_IncrRefCount(*errorObjPtr);
    }

    if (autopurge) {
	/*
	 * Purge now.
	 */

	Tcl_DeleteHashEntry(entry);
952
953
954
955
956
957
958








980
981
982
983
984
985
986
987
988
989
990
991
992
993
994







+
+
+
+
+
+
+
+
	 */

	info->purge = 1;
    }
    Tcl_MutexUnlock(&infoTablesMutex);
    return result;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclRegexp.c.

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

30
31
32
33
34
35
36
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

30
31
32
33
34
35
36
37






-
-
+
+







+













-
+







/*
 * tclRegexp.c --
 *
 *	This file contains the public interfaces to the Tcl regular expression
 *	mechanism.
 *
 * Copyright (c) 1998 by Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright © 1998 Sun Microsystems, Inc.
 * Copyright © 1998-1999 Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclRegexp.h"
#include "tclTomMath.h"
#include <assert.h>

/*
 *----------------------------------------------------------------------
 * The routines in this file use Henry Spencer's regular expression package
 * contained in the following additional source files:
 *
 *	regc_color.c	regc_cvec.c	regc_lex.c
 *	regc_nfa.c	regcomp.c	regcustom.h
 *	rege_dfa.c	regerror.c	regerrs.h
 *	regex.h		regexec.c	regfree.c
 *	regfronts.c	regguts.h
 *
 * Copyright (c) 1998 Henry Spencer.  All rights reserved.
 * Copyright © 1998 Henry Spencer.  All rights reserved.
 *
 * Development of this software was funded, in part, by Cray Research Inc.,
 * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
 * Corporation, none of whom are responsible for the results. The author
 * thanks all of them.
 *
 * Redistribution and use in source and binary forms -- with or without
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
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







-
+













-
-
-
-
-
+
+
+
+
+
+


-
+

-
+



-
+


-
+

-
-
-
+
+
+

-







 * Declarations for functions used only in this file.
 */

static TclRegexp *	CompileRegexp(Tcl_Interp *interp, const char *pattern,
			    size_t length, int flags);
static void		DupRegexpInternalRep(Tcl_Obj *srcPtr,
			    Tcl_Obj *copyPtr);
static void		FinalizeRegexp(ClientData clientData);
static void		FinalizeRegexp(void *clientData);
static void		FreeRegexp(TclRegexp *regexpPtr);
static void		FreeRegexpInternalRep(Tcl_Obj *objPtr);
static int		RegExpExecUniChar(Tcl_Interp *interp, Tcl_RegExp re,
			    const Tcl_UniChar *uniString, size_t numChars,
			    size_t nmatches, int flags);
static int		SetRegexpFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);

/*
 * The regular expression Tcl object type. This serves as a cache of the
 * compiled form of the regular expression.
 */

const Tcl_ObjType tclRegexpType = {
    "regexp",				/* name */
    FreeRegexpInternalRep,		/* freeIntRepProc */
    DupRegexpInternalRep,		/* dupIntRepProc */
    NULL,				/* updateStringProc */
    SetRegexpFromAny			/* setFromAnyProc */
    "regexp",			/* name */
    FreeRegexpInternalRep,	/* freeIntRepProc */
    DupRegexpInternalRep,	/* dupIntRepProc */
    NULL,			/* updateStringProc */
    SetRegexpFromAny,		/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

#define RegexpSetIntRep(objPtr, rePtr)					\
#define RegexpSetInternalRep(objPtr, rePtr) \
    do {								\
	Tcl_ObjIntRep ir;						\
	Tcl_ObjInternalRep ir;						\
	(rePtr)->refCount++;						\
	ir.twoPtrValue.ptr1 = (rePtr);					\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreIntRep((objPtr), &tclRegexpType, &ir);			\
	Tcl_StoreInternalRep((objPtr), &tclRegexpType, &ir);		\
    } while (0)

#define RegexpGetIntRep(objPtr, rePtr)					\
#define RegexpGetInternalRep(objPtr, rePtr) \
    do {								\
	const Tcl_ObjIntRep *irPtr;					\
	irPtr = TclFetchIntRep((objPtr), &tclRegexpType);		\
	(rePtr) = irPtr ? (TclRegexp *)irPtr->twoPtrValue.ptr1 : NULL;		\
	const Tcl_ObjInternalRep *irPtr;				\
	irPtr = TclFetchInternalRep((objPtr), &tclRegexpType);		\
	(rePtr) = irPtr ? (TclRegexp *)irPtr->twoPtrValue.ptr1 : NULL;	\
    } while (0)


/*
 *----------------------------------------------------------------------
 *
 * Tcl_RegExpCompile --
 *
 *	Compile a regular expression into a form suitable for fast matching.
151
152
153
154
155
156
157
158

159
160
161
162
163
164
165
152
153
154
155
156
157
158

159
160
161
162
163
164
165
166







-
+







Tcl_RegExp
Tcl_RegExpCompile(
    Tcl_Interp *interp,		/* For use in error reporting and to access
				 * the interp regexp cache. */
    const char *pattern)	/* String for which to produce compiled
				 * regular expression. */
{
    return (Tcl_RegExp) CompileRegexp(interp, pattern, (int) strlen(pattern),
    return (Tcl_RegExp) CompileRegexp(interp, pattern, strlen(pattern),
	    REG_ADVANCED);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_RegExpExec --
215
216
217
218
219
220
221
222

223
224
225


226
227
228
229
230
231
232
216
217
218
219
220
221
222

223
224


225
226
227
228
229
230
231
232
233







-
+

-
-
+
+







    regexp->objPtr = NULL;

    /*
     * Convert the string to Unicode and perform the match.
     */

    Tcl_DStringInit(&ds);
    ustr = Tcl_UtfToUniCharDString(text, -1, &ds);
    ustr = Tcl_UtfToUniCharDString(text, TCL_INDEX_NONE, &ds);
    numChars = Tcl_DStringLength(&ds) / sizeof(Tcl_UniChar);
    result = RegExpExecUniChar(interp, re, ustr, numChars, -1 /* nmatches */,
	    flags);
    result = RegExpExecUniChar(interp, re, ustr, numChars,
	    TCL_INDEX_NONE /* nmatches */, flags);
    Tcl_DStringFree(&ds);

    return result;
}

/*
 *---------------------------------------------------------------------------
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
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







-
+










-
+

-
+







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

void
Tcl_RegExpRange(
    Tcl_RegExp re,		/* Compiled regular expression that has been
				 * passed to Tcl_RegExpExec. */
    size_t index,			/* 0 means give the range of the entire match,
    Tcl_Size index,		/* 0 means give the range of the entire match,
				 * > 0 means give the range of a matching
				 * subrange. */
    const char **startPtr,	/* Store address of first character in
				 * (sub-)range here. */
    const char **endPtr)	/* Store address of character just after last
				 * in (sub-)range here. */
{
    TclRegexp *regexpPtr = (TclRegexp *) re;
    const char *string;

    if (index > regexpPtr->re.re_nsub) {
    if (index < 0 || (size_t) index > regexpPtr->re.re_nsub) {
	*startPtr = *endPtr = NULL;
    } else if (regexpPtr->matches[index].rm_so == TCL_INDEX_NONE) {
    } else if (regexpPtr->matches[index].rm_so == (size_t) -1) {
	*startPtr = *endPtr = NULL;
    } else {
	if (regexpPtr->objPtr) {
	    string = TclGetString(regexpPtr->objPtr);
	} else {
	    string = regexpPtr->string;
	}
300
301
302
303
304
305
306
307

308
309
310
311
312
313
314
301
302
303
304
305
306
307

308
309
310
311
312
313
314
315







-
+







static int
RegExpExecUniChar(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting. */
    Tcl_RegExp re,		/* Compiled regular expression; returned by a
				 * previous call to Tcl_GetRegExpFromObj */
    const Tcl_UniChar *wString,	/* String against which to match re. */
    size_t numChars,		/* Length of Tcl_UniChar string. */
    size_t nm,		/* How many subexpression matches (counting
    size_t nm,			/* How many subexpression matches (counting
				 * the whole match as subexpression 0) are of
				 * interest. -1 means "don't know". */
    int flags)			/* Regular expression flags. */
{
    int status;
    TclRegexp *regexpPtr = (TclRegexp *) re;
    size_t last = regexpPtr->re.re_nsub + 1;
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
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







-
+

-
+

-
+

-
+




-
+


-
-
-
+
+
+







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

void
TclRegExpRangeUniChar(
    Tcl_RegExp re,		/* Compiled regular expression that has been
				 * passed to Tcl_RegExpExec. */
    size_t index,			/* 0 means give the range of the entire match,
    Tcl_Size index,		/* 0 means give the range of the entire match,
				 * > 0 means give the range of a matching
				 * subrange, TCL_INDEX_NONE means the range of the
				 * subrange, -1 means the range of the
				 * rm_extend field. */
    size_t *startPtr,		/* Store address of first character in
    Tcl_Size *startPtr,		/* Store address of first character in
				 * (sub-)range here. */
    size_t *endPtr)		/* Store address of character just after last
    Tcl_Size *endPtr)		/* Store address of character just after last
				 * in (sub-)range here. */
{
    TclRegexp *regexpPtr = (TclRegexp *) re;

    if ((regexpPtr->flags&REG_EXPECT) && (index == TCL_INDEX_NONE)) {
    if ((regexpPtr->flags&REG_EXPECT) && (index == -1)) {
	*startPtr = regexpPtr->details.rm_extend.rm_so;
	*endPtr = regexpPtr->details.rm_extend.rm_eo;
    } else if (index + 1 > regexpPtr->re.re_nsub + 1) {
	*startPtr = TCL_INDEX_NONE;
	*endPtr = TCL_INDEX_NONE;
    } else if (index < 0 || (size_t) index > regexpPtr->re.re_nsub + 1) {
	*startPtr = -1;
	*endPtr = -1;
    } else {
	*startPtr = regexpPtr->matches[index].rm_so;
	*endPtr = regexpPtr->matches[index].rm_eo;
    }
}

/*
437
438
439
440
441
442
443
444

445
446

447
448
449
450
451
452
453

454
455
456
457
458
459
460
438
439
440
441
442
443
444

445
446

447
448
449
450
451
452
453

454
455
456
457
458
459
460
461







-
+

-
+






-
+







int
Tcl_RegExpExecObj(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting. */
    Tcl_RegExp re,		/* Compiled regular expression; must have been
				 * returned by previous call to
				 * Tcl_GetRegExpFromObj. */
    Tcl_Obj *textObj,		/* Text against which to match re. */
    size_t offset,			/* Character index that marks where matching
    Tcl_Size offset,		/* Character index that marks where matching
				 * should begin. */
    size_t nmatches,		/* How many subexpression matches (counting
    Tcl_Size nmatches,		/* How many subexpression matches (counting
				 * the whole match as subexpression 0) are of
				 * interest. -1 means all of them. */
    int flags)			/* Regular expression execution flags. */
{
    TclRegexp *regexpPtr = (TclRegexp *) re;
    Tcl_UniChar *udata;
    size_t length;
    Tcl_Size length;
    int reflags = regexpPtr->flags;
#define TCL_REG_GLOBOK_FLAGS \
	(TCL_REG_ADVANCED | TCL_REG_NOSUB | TCL_REG_NOCASE)

    /*
     * Take advantage of the equivalent glob pattern, if one exists.
     * This is possible based only on the right mix of incoming flags (0)
477
478
479
480
481
482
483
484

485
486
487
488
489
490
491
478
479
480
481
482
483
484

485
486
487
488
489
490
491
492







-
+







    /*
     * Save the target object so we can extract strings from it later.
     */

    regexpPtr->string = NULL;
    regexpPtr->objPtr = textObj;

    udata = TclGetUnicodeFromObj(textObj, &length);
    udata = Tcl_GetUnicodeFromObj(textObj, &length);

    if (offset > length) {
	offset = length;
    }
    udata += offset;
    length -= offset;

523
524
525
526
527
528
529
530
531


532
533
534
535
536
537
538
524
525
526
527
528
529
530


531
532
533
534
535
536
537
538
539







-
-
+
+







     * For performance reasons, first try compiling the RE without support for
     * subexpressions. On failure, try again without TCL_REG_NOSUB in case the
     * RE has backreferences in it. Closely related to [Bug 1366683]. If this
     * still fails, an error message will be left in the interpreter.
     */

    if (!(re = Tcl_GetRegExpFromObj(interp, patternObj,
	    TCL_REG_ADVANCED | TCL_REG_NOSUB))
     && !(re = Tcl_GetRegExpFromObj(interp, patternObj, TCL_REG_ADVANCED))) {
	    TCL_REG_ADVANCED | TCL_REG_NOSUB)) &&
	    !(re = Tcl_GetRegExpFromObj(interp, patternObj, TCL_REG_ADVANCED))) {
	return -1;
    }
    return Tcl_RegExpExecObj(interp, re, textObj, 0 /* offset */,
	    0 /* nmatches */, 0 /* flags */);
}

/*
589
590
591
592
593
594
595
596

597
598
599
600

601
602
603
604
605
606
607
608
609
610

611
612
613
614
615
616
617
590
591
592
593
594
595
596

597
598
599
600

601
602
603
604
605
606
607
608
609
610

611
612
613
614
615
616
617
618







-
+



-
+









-
+







				 * the interp regexp cache. */
    Tcl_Obj *objPtr,		/* Object whose string rep contains regular
				 * expression pattern. Internal rep will be
				 * changed to compiled form of this regular
				 * expression. */
    int flags)			/* Regular expression compilation flags. */
{
    size_t length;
    Tcl_Size length;
    TclRegexp *regexpPtr;
    const char *pattern;

    RegexpGetIntRep(objPtr, regexpPtr);
    RegexpGetInternalRep(objPtr, regexpPtr);

    if ((regexpPtr == NULL) || (regexpPtr->flags != flags)) {
	pattern = TclGetStringFromObj(objPtr, &length);

	regexpPtr = CompileRegexp(interp, pattern, length, flags);
	if (regexpPtr == NULL) {
	    return NULL;
	}

	RegexpSetIntRep(objPtr, regexpPtr);
	RegexpSetInternalRep(objPtr, regexpPtr);
    }
    return (Tcl_RegExp) regexpPtr;
}

/*
 *----------------------------------------------------------------------
 *
724
725
726
727
728
729
730
731

732
733

734
735
736
737
738
739
740
725
726
727
728
729
730
731

732
733

734
735
736
737
738
739
740
741







-
+

-
+







    const char *p;

    Tcl_ResetResult(interp);
    n = TclReError(status, buf, sizeof(buf));
    p = (n > sizeof(buf)) ? "..." : "";
    Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s%s%s", msg, buf, p));

    sprintf(cbuf, "%d", status);
    snprintf(cbuf, sizeof(cbuf), "%d", status);
    (void) TclReError(REG_ITOA, cbuf, sizeof(cbuf));
    Tcl_SetErrorCode(interp, "REGEXP", cbuf, buf, NULL);
    Tcl_SetErrorCode(interp, "REGEXP", cbuf, buf, (char *)NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * FreeRegexpInternalRep --
 *
752
753
754
755
756
757
758
759

760
761
762
763
764
765
766
753
754
755
756
757
758
759

760
761
762
763
764
765
766
767







-
+








static void
FreeRegexpInternalRep(
    Tcl_Obj *objPtr)		/* Regexp object with internal rep to free. */
{
    TclRegexp *regexpRepPtr;

    RegexpGetIntRep(objPtr, regexpRepPtr);
    RegexpGetInternalRep(objPtr, regexpRepPtr);

    assert(regexpRepPtr != NULL);

    /*
     * If this is the last reference to the regexp, free it.
     */

789
790
791
792
793
794
795
796

797
798
799
800

801
802
803
804
805
806
807
790
791
792
793
794
795
796

797
798
799
800

801
802
803
804
805
806
807
808







-
+



-
+







static void
DupRegexpInternalRep(
    Tcl_Obj *srcPtr,		/* Object with internal rep to copy. */
    Tcl_Obj *copyPtr)		/* Object with internal rep to set. */
{
    TclRegexp *regexpPtr;

    RegexpGetIntRep(srcPtr, regexpPtr);
    RegexpGetInternalRep(srcPtr, regexpPtr);

    assert(regexpPtr != NULL);

    RegexpSetIntRep(copyPtr, regexpPtr);
    RegexpSetInternalRep(copyPtr, regexpPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * SetRegexpFromAny --
 *
853
854
855
856
857
858
859
860

861
862
863
864
865
866
867
854
855
856
857
858
859
860

861
862
863
864
865
866
867
868







-
+







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

static TclRegexp *
CompileRegexp(
    Tcl_Interp *interp,		/* Used for error reporting if not NULL. */
    const char *string,		/* The regexp to compile (UTF-8). */
    size_t length,			/* The length of the string in bytes. */
    size_t length,		/* The length of the string in bytes. */
    int flags)			/* Compilation flags. */
{
    TclRegexp *regexpPtr;
    const Tcl_UniChar *uniString;
    int numChars, status, i, exact;
    Tcl_DString stringBuf;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
914
915
916
917
918
919
920
921
922


923
924
925
926
927
928
929
915
916
917
918
919
920
921


922
923
924
925
926
927
928
929
930







-
-
+
+







    /*
     * This is a new expression, so compile it and add it to the cache.
     */

    regexpPtr = (TclRegexp*)Tcl_Alloc(sizeof(TclRegexp));
    regexpPtr->objPtr = NULL;
    regexpPtr->string = NULL;
    regexpPtr->details.rm_extend.rm_so = -1;
    regexpPtr->details.rm_extend.rm_eo = -1;
    regexpPtr->details.rm_extend.rm_so = TCL_INDEX_NONE;
    regexpPtr->details.rm_extend.rm_eo = TCL_INDEX_NONE;

    /*
     * Get the up-to-date string representation and map to unicode.
     */

    Tcl_DStringInit(&stringBuf);
    uniString = Tcl_UtfToUniCharDString(string, length, &stringBuf);
941
942
943
944
945
946
947
948

949
950
951
952
953
954
955
956
957
958
959
960
961

962
963
964
965
966
967
968
942
943
944
945
946
947
948

949
950
951
952
953
954
955
956
957
958
959
960
961

962
963
964
965
966
967
968
969







-
+












-
+







	/*
	 * Clean up and report errors in the interpreter, if possible.
	 */

	Tcl_Free(regexpPtr);
	if (interp) {
	    TclRegError(interp,
		    "couldn't compile regular expression pattern: ", status);
		    "cannot compile regular expression pattern: ", status);
	}
	return NULL;
    }

    /*
     * Convert RE to a glob pattern equivalent, if any, and cache it.  If this
     * is not possible, then globObjPtr will be NULL.  This is used by
     * Tcl_RegExpExecObj to optionally do a fast match (avoids RE engine).
     */

    if (TclReToGlob(NULL, string, length, &stringBuf, &exact,
	    NULL) == TCL_OK) {
	regexpPtr->globObjPtr = TclDStringToObj(&stringBuf);
	regexpPtr->globObjPtr = Tcl_DStringToObj(&stringBuf);
	Tcl_IncrRefCount(regexpPtr->globObjPtr);
    } else {
	regexpPtr->globObjPtr = NULL;
    }

    /*
     * Allocate enough space for all of the subexpressions, plus one extra for
1048
1049
1050
1051
1052
1053
1054
1055

1056
1057
1058
1059
1060
1061
1062
1049
1050
1051
1052
1053
1054
1055

1056
1057
1058
1059
1060
1061
1062
1063







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
FinalizeRegexp(
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    int i;
    TclRegexp *regexpPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    for (i = 0; (i < NUM_REGEXPS) && (tsdPtr->patterns[i] != NULL); i++) {
	regexpPtr = tsdPtr->regexps[i];

Changes to generic/tclRegexp.h.

33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47







-
+







    Tcl_Obj *globObjPtr;	/* Glob pattern rep of RE or NULL if none. */
    regmatch_t *matches;	/* Array of indices into the Tcl_UniChar
				 * representation of the last string matched
				 * with this regexp to indicate the location
				 * of subexpressions. */
    rm_detail_t details;	/* Detailed information on match (currently
				 * used only for REG_EXPECT). */
    size_t refCount;		/* Count of number of references to this
    Tcl_Size refCount;		/* Count of number of references to this
				 * compiled regexp. */
} TclRegexp;

#endif /* _TCLREGEXP */

/*
 * Local Variables:

Changes to generic/tclResolve.c.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







/*
 * tclResolve.c --
 *
 *	Contains hooks for customized command/variable name resolution
 *	schemes. These hooks allow extensions like [incr Tcl] to add their own
 *	name resolution rules to the Tcl language. Rules can be applied to a
 *	particular namespace, to the interpreter as a whole, or both.
 *
 * Copyright (c) 1998 Lucent Technologies, Inc.
 * Copyright © 1998 Lucent Technologies, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

Changes to generic/tclResult.c.

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
30
31
32
33
34
35
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
30
31
32
33
34
35
36





-
+






+















-
+







/*
 * tclResult.c --
 *
 *	This file contains code to manage the interpreter result.
 *
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 * Copyright © 1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include <assert.h>

/*
 * Indices of the standard return options dictionary keys.
 */

enum returnKeys {
    KEY_CODE,	KEY_ERRORCODE,	KEY_ERRORINFO,	KEY_ERRORLINE,
    KEY_LEVEL,	KEY_OPTIONS,	KEY_ERRORSTACK,	KEY_LAST
};

/*
 * Function prototypes for local functions in this file:
 */

static Tcl_Obj **	GetKeys(void);
static void		ReleaseKeys(ClientData clientData);
static void		ReleaseKeys(void *clientData);
static void		ResetObjResult(Interp *iPtr);

/*
 * This structure is used to take a snapshot of the interpreter state in
 * Tcl_SaveInterpState. You can snapshot the state, execute a command, and
 * then back up to the result or the error that was previously in progress.
 */
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
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







-
-
+





-
+
-
-
-
+
+
+






-
+
-
-
+
-



-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
+
-







    Tcl_Free(statePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetObjResult --
 *
 *	Arrange for objPtr to be an interpreter's result value.
 *	Makes objPtr the interpreter's result value.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	interp->objResultPtr is left pointing to the object referenced by
 *	Stores objPtr interp->objResultPtr, increments its reference count, and
 *	objPtr. The object's reference count is incremented since there is now
 *	a new reference to it. The reference count for any old objResultPtr
 *	value is decremented. Also, the string result is reset.
 *	decrements the reference count of any existing interp->objResultPtr.
 *
 *	The string result is reset.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetObjResult(
    Tcl_Interp *interp,		/* Interpreter with which to associate the
    Tcl_Interp *interp,		/* Interpreter to set the result for. */
				 * return object value. */
    Tcl_Obj *objPtr)	/* Tcl object to be returned. If NULL, the obj
    Tcl_Obj *objPtr)		/* The value to set as the result. */
				 * result is made an empty string object. */
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *oldObjResult = iPtr->objResultPtr;

    iPtr->objResultPtr = objPtr;
    Tcl_IncrRefCount(objPtr);	/* since interp result is a reference */

    if (objPtr == oldObjResult) {
	/* This should be impossible */
	assert(objPtr->refCount != 0);
	return;
    } else {
	iPtr->objResultPtr = objPtr;
	Tcl_IncrRefCount(objPtr);
	TclDecrRefCount(oldObjResult);
    /*
     * We wait until the end to release the old object result, in case we are
     * setting the result to itself.
     */

    }
    TclDecrRefCount(oldObjResult);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetObjResult --
 *
353
354
355
356
357
358
359
360

361
362
363
364
365
366
367
350
351
352
353
354
355
356

357
358
359
360
361
362
363
364







-
+







    const char *element)	/* String to convert to list element and add
				 * to result. */
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *elementPtr = Tcl_NewStringObj(element, -1);
    Tcl_Obj *listPtr = Tcl_NewListObj(1, &elementPtr);
    const char *bytes;
    size_t length;
    Tcl_Size length;

    if (Tcl_IsShared(iPtr->objResultPtr)) {
	Tcl_SetObjResult(interp, Tcl_DuplicateObj(iPtr->objResultPtr));
    }
    bytes = TclGetStringFromObj(iPtr->objResultPtr, &length);
    if (TclNeedSpace(bytes, bytes + length)) {
	Tcl_AppendToObj(iPtr->objResultPtr, " ", 1);
387
388
389
390
391
392
393
394

395
396
397
398
399
400
401
384
385
386
387
388
389
390

391
392
393
394
395
396
397
398







-
+







 *	It also clears any error information for the interpreter.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_ResetResult(
    Tcl_Interp *interp)/* Interpreter for which to clear result. */
    Tcl_Interp *interp)		/* Interpreter for which to clear result. */
{
    Interp *iPtr = (Interp *) interp;

    ResetObjResult(iPtr);
    if (iPtr->errorCode) {
	/* Legacy support */
	if (iPtr->flags & ERR_LEGACY_COPY) {
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
467
468
469
470
471
472
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
467
468
469







-
+

















-
+







 *	the interpreter.
 *
 *----------------------------------------------------------------------
 */

static void
ResetObjResult(
    Interp *iPtr)	/* Points to the interpreter whose result
    Interp *iPtr)		/* Points to the interpreter whose result
				 * object should be reset. */
{
    Tcl_Obj *objResultPtr = iPtr->objResultPtr;

    if (Tcl_IsShared(objResultPtr)) {
	TclDecrRefCount(objResultPtr);
	TclNewObj(objResultPtr);
	Tcl_IncrRefCount(objResultPtr);
	iPtr->objResultPtr = objResultPtr;
    } else {
	if (objResultPtr->bytes != &tclEmptyString) {
	    if (objResultPtr->bytes) {
		Tcl_Free(objResultPtr->bytes);
	    }
	    objResultPtr->bytes = &tclEmptyString;
	    objResultPtr->length = 0;
	}
	TclFreeIntRep(objResultPtr);
	TclFreeInternalRep(objResultPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetErrorCode --
494
495
496
497
498
499
500
501

502
503
504
505
506
507
508
491
492
493
494
495
496
497

498
499
500
501
502
503
504
505







-
+








    /*
     * Scan through the arguments one at a time, appending them to the
     * errorCode field as list elements.
     */

    va_start(argList, interp);
    errorObj = Tcl_NewObj();
    TclNewObj(errorObj);

    /*
     * Scan through the arguments one at a time, appending them to the
     * errorCode field as list elements.
     */

    while (1) {
655
656
657
658
659
660
661
662

663
664
665
666
667
668
669
652
653
654
655
656
657
658

659
660
661
662
663
664
665
666







-
+







 *	Frees memory.
 *
 *----------------------------------------------------------------------
 */

static void
ReleaseKeys(
    ClientData clientData)
    void *clientData)
{
    Tcl_Obj **keys = (Tcl_Obj **)clientData;
    int i;

    for (i = KEY_CODE; i < KEY_LAST; i++) {
	Tcl_DecrRefCount(keys[i]);
	keys[i] = NULL;
715
716
717
718
719
720
721
722

723
724

725
726

727
728
729
730
731
732
733
734

735
736
737


738
739
740


741
742
743
744
745
746





747
748
749
750
751




752
753
754
755
756
757
758






759
760
761
762



763
764
765
766



767
768

769
770
771
772

773
774
775
776

777
778
779
780
781
782
783
712
713
714
715
716
717
718

719
720

721
722

723
724
725
726
727
728
729
730

731
732


733
734
735


736
737
738





739
740
741
742
743
744




745
746
747
748
749






750
751
752
753
754
755
756



757
758
759
760



761
762
763
764

765
766
767
768

769
770
771
772

773
774
775
776
777
778
779
780







-
+

-
+

-
+







-
+

-
-
+
+

-
-
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
+
+
+

-
-
-
+
+
+

-
+



-
+



-
+








    if (code == TCL_ERROR) {
	if (iPtr->errorInfo) {
	    Tcl_DecrRefCount(iPtr->errorInfo);
	    iPtr->errorInfo = NULL;
	}
	Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORINFO],
                &valuePtr);
		&valuePtr);
	if (valuePtr != NULL) {
	    size_t length;
	    Tcl_Size length;

	    (void) TclGetStringFromObj(valuePtr, &length);
	    (void)TclGetStringFromObj(valuePtr, &length);
	    if (length) {
		iPtr->errorInfo = valuePtr;
		Tcl_IncrRefCount(iPtr->errorInfo);
		iPtr->flags |= ERR_ALREADY_LOGGED;
	    }
	}
	Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORSTACK],
                &valuePtr);
		&valuePtr);
	if (valuePtr != NULL) {
            int len, valueObjc;
            Tcl_Obj **valueObjv;
	    Tcl_Size len, valueObjc;
	    Tcl_Obj **valueObjv;

            if (Tcl_IsShared(iPtr->errorStack)) {
                Tcl_Obj *newObj;
	    if (Tcl_IsShared(iPtr->errorStack)) {
		Tcl_Obj *newObj;

                newObj = Tcl_DuplicateObj(iPtr->errorStack);
                Tcl_DecrRefCount(iPtr->errorStack);
                Tcl_IncrRefCount(newObj);
                iPtr->errorStack = newObj;
            }
		newObj = Tcl_DuplicateObj(iPtr->errorStack);
		Tcl_DecrRefCount(iPtr->errorStack);
		Tcl_IncrRefCount(newObj);
		iPtr->errorStack = newObj;
	    }

            /*
             * List extraction done after duplication to avoid moving the rug
             * if someone does [return -errorstack [info errorstack]]
             */
	    /*
	     * List extraction done after duplication to avoid moving the rug
	     * if someone does [return -errorstack [info errorstack]]
	     */

            if (Tcl_ListObjGetElements(interp, valuePtr, &valueObjc,
                    &valueObjv) == TCL_ERROR) {
                return TCL_ERROR;
            }
            iPtr->resetErrorStack = 0;
            Tcl_ListObjLength(interp, iPtr->errorStack, &len);
	    if (TclListObjGetElements(interp, valuePtr, &valueObjc,
		    &valueObjv) == TCL_ERROR) {
		return TCL_ERROR;
	    }
	    iPtr->resetErrorStack = 0;
	    TclListObjLength(interp, iPtr->errorStack, &len);

            /*
             * Reset while keeping the list intrep as much as possible.
             */
	    /*
	     * Reset while keeping the list internalrep as much as possible.
	     */

            Tcl_ListObjReplace(interp, iPtr->errorStack, 0, len, valueObjc,
                    valueObjv);
 	}
	    Tcl_ListObjReplace(interp, iPtr->errorStack, 0, len, valueObjc,
		    valueObjv);
	}
	Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORCODE],
                &valuePtr);
		&valuePtr);
	if (valuePtr != NULL) {
	    Tcl_SetObjErrorCode(interp, valuePtr);
	} else {
	    Tcl_SetErrorCode(interp, "NONE", NULL);
	    Tcl_SetErrorCode(interp, "NONE", (char *)NULL);
	}

	Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORLINE],
                &valuePtr);
		&valuePtr);
	if (valuePtr != NULL) {
	    TclGetIntFromObj(NULL, valuePtr, &iPtr->errorLine);
	}
    }
    if (level != 0) {
	iPtr->returnLevel = level;
	iPtr->returnCode = code;
842
843
844
845
846
847
848
849
850


851
852

853
854
855
856
857
858
859
839
840
841
842
843
844
845


846
847
848

849
850
851
852
853
854
855
856







-
-
+
+

-
+







	    if (TCL_ERROR == Tcl_DictObjFirst(NULL, dict, &search,
		    &keyPtr, &valuePtr, &done)) {
		/*
		 * Value is not a legal dictionary.
		 */

		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                        "bad %s value: expected dictionary but got \"%s\"",
                        compare, TclGetString(objv[1])));
			"bad %s value: expected dictionary but got \"%s\"",
			compare, TclGetString(objv[1])));
		Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_OPTIONS",
			NULL);
			(char *)NULL);
		goto error;
	    }

	    while (!done) {
		Tcl_DictObjPut(NULL, returnOpts, keyPtr, valuePtr);
		Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done);
	    }
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
898
899
900
901



902
903
904
905
906
907
908
909
910
911
912
913

914
915

916
917
918
919
920
921
922


923
924

925
926
927
928
929
930
931
932
933
934
935

936
937

938
939
940
941
942
943
944


945
946

947
948
949
950
951
952




953
954
955

956
957
958

959
960

961
962
963
964
965
966
967
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909

910
911

912
913
914
915
916
917


918
919
920

921
922
923
924
925
926
927
928
929
930
931

932
933

934
935
936
937
938
939


940
941
942

943
944
945




946
947
948
949
950
951

952
953
954

955
956

957
958
959
960
961
962
963
964







-
+


















-
-
-
+
+
+











-
+

-
+





-
-
+
+

-
+










-
+

-
+





-
-
+
+

-
+


-
-
-
-
+
+
+
+


-
+


-
+

-
+







    /*
     * Check for bogus -code value.
     */

    Tcl_DictObjGet(NULL, returnOpts, keys[KEY_CODE], &valuePtr);
    if (valuePtr != NULL) {
	if (TclGetCompletionCodeFromObj(interp, valuePtr,
                &code) == TCL_ERROR) {
		&code) == TCL_ERROR) {
	    goto error;
	}
	Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_CODE]);
    }

    /*
     * Check for bogus -level value.
     */

    Tcl_DictObjGet(NULL, returnOpts, keys[KEY_LEVEL], &valuePtr);
    if (valuePtr != NULL) {
	if ((TCL_ERROR == TclGetIntFromObj(NULL, valuePtr, &level))
		|| (level < 0)) {
	    /*
	     * Value is not a legal level.
	     */

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "bad -level value: expected non-negative integer but got"
                    " \"%s\"", TclGetString(valuePtr)));
	    Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_LEVEL", NULL);
		    "bad -level value: expected non-negative integer but got"
		    " \"%s\"", TclGetString(valuePtr)));
	    Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_LEVEL", (char *)NULL);
	    goto error;
	}
	Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_LEVEL]);
    }

    /*
     * Check for bogus -errorcode value.
     */

    Tcl_DictObjGet(NULL, returnOpts, keys[KEY_ERRORCODE], &valuePtr);
    if (valuePtr != NULL) {
	int length;
	Tcl_Size length;

	if (TCL_ERROR == Tcl_ListObjLength(NULL, valuePtr, &length )) {
	if (TCL_ERROR == TclListObjLength(NULL, valuePtr, &length )) {
	    /*
	     * Value is not a list, which is illegal for -errorcode.
	     */

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "bad -errorcode value: expected a list but got \"%s\"",
                    TclGetString(valuePtr)));
		    "bad -errorcode value: expected a list but got \"%s\"",
		    TclGetString(valuePtr)));
	    Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_ERRORCODE",
		    NULL);
		    (char *)NULL);
	    goto error;
	}
    }

    /*
     * Check for bogus -errorstack value.
     */

    Tcl_DictObjGet(NULL, returnOpts, keys[KEY_ERRORSTACK], &valuePtr);
    if (valuePtr != NULL) {
	int length;
	Tcl_Size length;

	if (TCL_ERROR == Tcl_ListObjLength(NULL, valuePtr, &length )) {
	if (TCL_ERROR == TclListObjLength(NULL, valuePtr, &length)) {
	    /*
	     * Value is not a list, which is illegal for -errorstack.
	     */

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "bad -errorstack value: expected a list but got \"%s\"",
                    TclGetString(valuePtr)));
		    "bad -errorstack value: expected a list but got \"%s\"",
		    TclGetString(valuePtr)));
	    Tcl_SetErrorCode(interp, "TCL", "RESULT", "NONLIST_ERRORSTACK",
                    NULL);
		    (char *)NULL);
	    goto error;
	}
        if (length % 2) {
            /*
             * Errorstack must always be an even-sized list
             */
	if (length % 2) {
	    /*
	     * Errorstack must always be an even-sized list
	     */

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "forbidden odd-sized list for -errorstack: \"%s\"",
		    "forbidden odd-sized list for -errorstack: \"%s\"",
		    TclGetString(valuePtr)));
	    Tcl_SetErrorCode(interp, "TCL", "RESULT",
                    "ODDSIZEDLIST_ERRORSTACK", NULL);
		    "ODDSIZEDLIST_ERRORSTACK", (char *)NULL);
	    goto error;
        }
	}
    }

    /*
     * Convert [return -code return -level X] to [return -code ok -level X+1]
     */

    if (code == TCL_RETURN) {
1033
1034
1035
1036
1037
1038
1039
1040

1041
1042
1043
1044
1045
1046
1047
1030
1031
1032
1033
1034
1035
1036

1037
1038
1039
1040
1041
1042
1043
1044







-
+







		Tcl_NewWideIntObj(result));
	Tcl_DictObjPut(NULL, options, keys[KEY_LEVEL],
		Tcl_NewWideIntObj(0));
    }

    if (result == TCL_ERROR) {
	Tcl_AddErrorInfo(interp, "");
        Tcl_DictObjPut(NULL, options, keys[KEY_ERRORSTACK], iPtr->errorStack);
	Tcl_DictObjPut(NULL, options, keys[KEY_ERRORSTACK], iPtr->errorStack);
    }
    if (iPtr->errorCode) {
	Tcl_DictObjPut(NULL, options, keys[KEY_ERRORCODE], iPtr->errorCode);
    }
    if (iPtr->errorInfo) {
	Tcl_DictObjPut(NULL, options, keys[KEY_ERRORINFO], iPtr->errorInfo);
	Tcl_DictObjPut(NULL, options, keys[KEY_ERRORLINE],
1096
1097
1098
1099
1100
1101
1102

1103

1104
1105
1106
1107
1108
1109
1110
1111


1112
1113
1114
1115
1116
1117
1118
1093
1094
1095
1096
1097
1098
1099
1100

1101
1102
1103
1104
1105
1106
1107


1108
1109
1110
1111
1112
1113
1114
1115
1116







+
-
+






-
-
+
+







 */

int
Tcl_SetReturnOptions(
    Tcl_Interp *interp,
    Tcl_Obj *options)
{
    Tcl_Size objc;
    int objc, level, code;
    int level, code;
    Tcl_Obj **objv, *mergedOpts;

    Tcl_IncrRefCount(options);
    if (TCL_ERROR == TclListObjGetElements(interp, options, &objc, &objv)
	    || (objc % 2)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "expected dict but got \"%s\"", TclGetString(options)));
	Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_OPTIONS", NULL);
		"expected dict but got \"%s\"", TclGetString(options)));
	Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_OPTIONS", (char *)NULL);
	code = TCL_ERROR;
    } else if (TCL_ERROR == TclMergeReturnOptions(interp, objc, objv,
	    &mergedOpts, &code, &level)) {
	code = TCL_ERROR;
    } else {
	code = TclProcessReturn(interp, code, level, mergedOpts);
    }

Changes to generic/tclScan.c.

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
30
31
32
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
30
31
32
33
34





-
+







+




-
-
-
-
-
+
+
+
+
+

-
-
+
+
+







/*
 * tclScan.c --
 *
 *	This file contains the implementation of the "scan" command.
 *
 * Copyright (c) 1998 by Scriptics Corporation.
 * Copyright © 1998 Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclTomMath.h"
#include <assert.h>

/*
 * Flag values used by Tcl_ScanObjCmd.
 */

#define SCAN_NOSKIP	0x1		/* Don't skip blanks. */
#define SCAN_SUPPRESS	0x2		/* Suppress assignment. */
#define SCAN_UNSIGNED	0x4		/* Read an unsigned value. */
#define SCAN_WIDTH	0x8		/* A width value was supplied. */
enum ScanFlags {
    SCAN_NOSKIP = 0x1,		/* Don't skip blanks. */
    SCAN_SUPPRESS = 0x2,	/* Suppress assignment. */
    SCAN_UNSIGNED = 0x4,	/* Read an unsigned value. */
    SCAN_WIDTH = 0x8,		/* A width value was supplied. */

#define SCAN_LONGER	0x400		/* Asked for a wide value. */
#define SCAN_BIG	0x800		/* Asked for a bignum value. */
    SCAN_LONGER = 0x400,	/* Asked for a wide value. */
    SCAN_BIG = 0x800		/* Asked for a bignum value. */
};

/*
 * The following structure contains the information associated with a
 * character set.
 */

typedef struct {
254
255
256
257
258
259
260
261

262
263
264
265
266
267
268
256
257
258
259
260
261
262

263
264
265
266
267
268
269
270







-
+







    Tcl_Interp *interp,		/* Current interpreter. */
    const char *format,		/* The format string. */
    int numVars,		/* The number of variables passed to the scan
				 * command. */
    int *totalSubs)		/* The number of variables that will be
				 * required. */
{
    int gotXpg, gotSequential, value, i, flags;
    int gotXpg, gotSequential, i, flags;
    char *end;
    Tcl_UniChar ch = 0;
    int objIndex, xpgSize, nspace = numVars;
    int *nassign = (int *)TclStackAlloc(interp, nspace * sizeof(int));
    Tcl_Obj *errorMsg;		/* Place to build an error messages. Note that
				 * these are messy operations because we do
				 * not want to use the formatting engine;
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
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
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
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
442
443







+
-
+









+
+
+
+
-
-
+
+





-
-
+
+

-
+











-
+









+
+
+
-
+
+
+
+
+
+
+
+
+
+
+









+
+
+
+
+
+
+
+
+
+
+








-
+
+




















-
+













-
+







	if ((ch < 0x80) && isdigit(UCHAR(ch))) {	/* INTL: "C" locale. */
	    /*
	     * Check for an XPG3-style %n$ specification. Note: there must
	     * not be a mixture of XPG3 specs and non-XPG3 specs in the same
	     * format string.
	     */

	    /* assert(value is >= 0) because of the isdigit() check above */
	    value = strtoul(format-1, &end, 10);	/* INTL: "C" locale. */
	    unsigned long long ull = strtoull(format-1, &end, 10);	/* INTL: "C" locale. */
	    if (*end != '$') {
		goto notXpg;
	    }
	    format = end+1;
	    format += TclUtfToUniChar(format, &ch);
	    gotXpg = 1;
	    if (gotSequential) {
		goto mixedXPG;
	    }
	    /* >=INT_MAX because 9.0 does not support more than INT_MAX-1 args */
	    if (ull == 0 || ull >= INT_MAX) {
		goto badIndex;
	    }
	    objIndex = value - 1;
	    if ((objIndex < 0) || (numVars && (objIndex >= numVars))) {
	    objIndex = (int) ull - 1;
	    if (numVars && (objIndex >= numVars)) {
		goto badIndex;
	    } else if (numVars == 0) {
		/*
		 * In the case where no vars are specified, the user can
		 * specify %9999$ legally, so we have to consider special
		 * rules for growing the assign array. 'value' is guaranteed
		 * to be > 0.
		 * rules for growing the assign array. 'ull' is guaranteed
		 * to be > 0 and < INT_MAX as per checks above.
		 */
		xpgSize = (xpgSize > value) ? xpgSize : value;
		xpgSize = (xpgSize > (int)ull) ? xpgSize : (int)ull;
	    }
	    goto xpgCheckDone;
	}

    notXpg:
	gotSequential = 1;
	if (gotXpg) {
	mixedXPG:
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "cannot mix \"%\" and \"%n$\" conversion specifiers",
		    -1));
	    Tcl_SetErrorCode(interp, "TCL", "FORMAT", "MIXEDSPECTYPES", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "FORMAT", "MIXEDSPECTYPES", (char *)NULL);
	    goto error;
	}

    xpgCheckDone:
	/*
	 * Parse any width specifier.
	 */

	if ((ch < 0x80) && isdigit(UCHAR(ch))) {	/* INTL: "C" locale. */
	    /* Note ull >= 0 because of isdigit check above */
	    unsigned long long ull;
	    ull = strtoull(
	    value = strtoul(format-1, (char **) &format, 10);	/* INTL: "C" locale. */
		    format - 1, (char **)&format, 10);	/* INTL: "C" locale. */
	    /* Note >=, not >, to leave room for a nul */
	    if (ull >= TCL_SIZE_MAX) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"specified field width %" TCL_LL_MODIFIER
			"u exceeds limit %" TCL_SIZE_MODIFIER "d.",
			ull, (Tcl_Size)TCL_SIZE_MAX-1));
		Tcl_SetErrorCode(
			interp, "TCL", "FORMAT", "WIDTHLIMIT", (char *)NULL);
		goto error;
	    }
	    flags |= SCAN_WIDTH;
	    format += TclUtfToUniChar(format, &ch);
	}

	/*
	 * Handle any size specifier.
	 */

	switch (ch) {
	case 'z':
	case 't':
	    if (sizeof(void *) > sizeof(int)) {
		flags |= SCAN_LONGER;
	    }
	    format += TclUtfToUniChar(format, &ch);
	    break;
	case 'L':
	    flags |= SCAN_BIG;
	    format += TclUtfToUniChar(format, &ch);
	    break;
	case 'l':
	    if (*format == 'l') {
		flags |= SCAN_BIG;
		format += 1;
		format += TclUtfToUniChar(format, &ch);
		break;
	    }
	    /* FALLTHRU */
	case 'L':
	case 'j':
	case 'q':
	    flags |= SCAN_LONGER;
	    /* FALLTHRU */
	case 'h':
	    format += TclUtfToUniChar(format, &ch);
	}

	if (!(flags & SCAN_SUPPRESS) && numVars && (objIndex >= numVars)) {
	    goto badIndex;
	}

	/*
	 * Handle the various field types.
	 */

	switch (ch) {
	case 'c':
	    if (flags & SCAN_WIDTH) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"field width may not be specified in %c conversion",
			-1));
		Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADWIDTH", NULL);
		Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADWIDTH", (char *)NULL);
		goto error;
	    }
	    /* FALLTHRU */
	case 'n':
	case 's':
	    if (flags & (SCAN_LONGER|SCAN_BIG)) {
	    invalidFieldSize:
		buf[Tcl_UniCharToUtf(ch, buf)] = '\0';
		errorMsg = Tcl_NewStringObj(
			"field size modifier may not be specified in %", -1);
		Tcl_AppendToObj(errorMsg, buf, -1);
		Tcl_AppendToObj(errorMsg, " conversion", -1);
		Tcl_SetObjResult(interp, errorMsg);
		Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADSIZE", NULL);
		Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADSIZE", (char *)NULL);
		goto error;
	    }
	    /*
	     * Fall through!
	     */
	case 'd':
	case 'e':
449
450
451
452
453
454
455
456

457
458
459
460
461
462
463
464
465

466
467
468
469
470
471
472
473
474
475
476

477
478
479
480
481
482
483
484

485
486
487
488
489
490
491
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







-
+








-
+










-
+







-
+







		}
		format += TclUtfToUniChar(format, &ch);
	    }
	    break;
	badSet:
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "unmatched [ in format string", -1));
	    Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BRACKET", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BRACKET", (char *)NULL);
	    goto error;
	default:
	    buf[Tcl_UniCharToUtf(ch, buf)] = '\0';
	    errorMsg = Tcl_NewStringObj(
		    "bad scan conversion character \"", -1);
	    Tcl_AppendToObj(errorMsg, buf, -1);
	    Tcl_AppendToObj(errorMsg, "\"", -1);
	    Tcl_SetObjResult(interp, errorMsg);
	    Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADTYPE", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADTYPE", (char *)NULL);
	    goto error;
	}
	if (!(flags & SCAN_SUPPRESS)) {
	    if (objIndex >= nspace) {
		/*
		 * Expand the nassign buffer. If we are using XPG specifiers,
		 * make sure that we grow to a large enough size. xpgSize is
		 * guaranteed to be at least one larger than objIndex.
		 */

		value = nspace;
		int nspaceOrig = nspace;
		if (xpgSize) {
		    nspace = xpgSize;
		} else {
		    nspace += 16;	/* formerly STATIC_LIST_SIZE */
		}
		nassign = (int *)TclStackRealloc(interp, nassign,
			nspace * sizeof(int));
		for (i = value; i < nspace; i++) {
		for (i = nspaceOrig; i < nspace; i++) {
		    nassign[i] = 0;
		}
	    }
	    nassign[objIndex]++;
	    objIndex++;
	}
    }
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
537
538
539
540
541
542
543

544
545
546
547
548
549
550
551
552
553
554

555
556
557
558
559
560
561
562
563
564
565
566

567
568
569
570
571

572
573
574
575
576
577
578
579







-
+










-
+











-
+




-
+







	*totalSubs = numVars;
    }
    for (i = 0; i < numVars; i++) {
	if (nassign[i] > 1) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "variable is assigned by multiple \"%n$\" conversion specifiers",
		    -1));
	    Tcl_SetErrorCode(interp, "TCL", "FORMAT", "POLYASSIGNED", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "FORMAT", "POLYASSIGNED", (char *)NULL);
	    goto error;
	} else if (!xpgSize && (nassign[i] == 0)) {
	    /*
	     * If the space is empty, and xpgSize is 0 (means XPG wasn't used,
	     * and/or numVars != 0), then too many vars were given
	     */

	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "variable is not assigned by any conversion specifiers",
		    -1));
	    Tcl_SetErrorCode(interp, "TCL", "FORMAT", "UNASSIGNED", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "FORMAT", "UNASSIGNED", (char *)NULL);
	    goto error;
	}
    }

    TclStackFree(interp, nassign);
    return TCL_OK;

  badIndex:
    if (gotXpg) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"\"%n$\" argument index out of range", -1));
	Tcl_SetErrorCode(interp, "TCL", "FORMAT", "INDEXRANGE", NULL);
	Tcl_SetErrorCode(interp, "TCL", "FORMAT", "INDEXRANGE", (char *)NULL);
    } else {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"different numbers of variable names and field specifiers",
		-1));
	Tcl_SetErrorCode(interp, "TCL", "FORMAT", "FIELDVARMISMATCH", NULL);
	Tcl_SetErrorCode(interp, "TCL", "FORMAT", "FIELDVARMISMATCH", (char *)NULL);
    }

  error:
    TclStackFree(interp, nassign);
    return TCL_ERROR;
}

560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
575

576
577
578


579
580
581
582
583
584
585
592
593
594
595
596
597
598

599
600
601
602
603
604
605
606

607
608
609

610
611
612
613
614
615
616
617
618







-
+







-
+


-
+
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ScanObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *format;
    int numVars, nconversions, totalVars = -1;
    int objIndex, offset, i, result, code;
    long value;
    int value;
    const char *string, *end, *baseString;
    char op = 0;
    int width, underflow = 0;
    int underflow = 0;
    Tcl_Size width;
    Tcl_WideInt wideValue;
    Tcl_UniChar ch = 0, sch = 0;
    Tcl_Obj **objs = NULL, *objPtr = NULL;
    int flags;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv,
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
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720

721
722
723
724
725
726
727
728
729
730







+













+
-
+
+
+







	 */

	if (ch == '*') {
	    flags |= SCAN_SUPPRESS;
	    format += TclUtfToUniChar(format, &ch);
	} else if ((ch < 0x80) && isdigit(UCHAR(ch))) {	/* INTL: "C" locale. */
	    char *formatEnd;
	    /* Note currently XPG3 range limited to INT_MAX to match type of objc */
	    value = strtoul(format-1, &formatEnd, 10);/* INTL: "C" locale. */
	    if (*formatEnd == '$') {
		format = formatEnd+1;
		format += TclUtfToUniChar(format, &ch);
		objIndex = (int) value - 1;
	    }
	}

	/*
	 * Parse any width specifier.
	 */

	if ((ch < 0x80) && isdigit(UCHAR(ch))) {	/* INTL: "C" locale. */
	    unsigned long long ull;
	    width = (int) strtoul(format-1, (char **) &format, 10);/* INTL: "C" locale. */
	    ull  = strtoull(format-1, (char **) &format, 10); /* INTL: "C" locale. */
	    assert(ull <= TCL_SIZE_MAX); /* Else ValidateFormat should've error'ed */
	    width = (Tcl_Size)ull;
	    format += TclUtfToUniChar(format, &ch);
	} else {
	    width = 0;
	}

	/*
	 * Handle any size specifier.
872
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
898
899

900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918

919
920
921


922
923
924
925
926
927
928
929

930
931
932
933
934
935
936
909
910
911
912
913
914
915

916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935

936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954

955

956
957
958
959
960
961
962
963
964
965
966

967
968
969
970
971
972
973
974







-
+



















-
+


















-
+
-


+
+







-
+







	    break;
	}
	case 'c':
	    /*
	     * Scan a single Unicode character.
	     */

	    offset = TclUtfToUCS4(string, &i);
	    offset = TclUtfToUniChar(string, &i);
	    string += offset;
	    if (!(flags & SCAN_SUPPRESS)) {
		TclNewIntObj(objPtr, i);
		Tcl_IncrRefCount(objPtr);
		CLANG_ASSERT(objs);
		objs[objIndex++] = objPtr;
	    }
	    break;

	case 'i':
	    /*
	     * Scan an unsigned or signed integer.
	     */
	    TclNewIntObj(objPtr, 0);
	    Tcl_IncrRefCount(objPtr);
	    if (width == 0) {
		width = ~0;
	    }
	    if (TCL_OK != TclParseNumber(NULL, objPtr, NULL, string, width,
		&end, TCL_PARSE_INTEGER_ONLY | TCL_PARSE_NO_UNDERSCORE | parseFlag)) {
		    &end, TCL_PARSE_INTEGER_ONLY | TCL_PARSE_NO_UNDERSCORE | parseFlag)) {
		Tcl_DecrRefCount(objPtr);
		if (width < 0) {
		    if (*end == '\0') {
			underflow = 1;
		    }
		} else {
		    if (end == string + width) {
			underflow = 1;
		    }
		}
		goto done;
	    }
	    string = end;
	    if (flags & SCAN_SUPPRESS) {
		Tcl_DecrRefCount(objPtr);
		break;
	    }
	    if (flags & SCAN_LONGER) {
		if (Tcl_GetWideIntFromObj(NULL, objPtr, &wideValue) != TCL_OK) {
		if (TclGetWideIntFromObj(NULL, objPtr, &wideValue) != TCL_OK) {
		    wideValue = WIDE_MAX;
		    if (TclGetString(objPtr)[0] == '-') {
			wideValue = WIDE_MIN;
		    } else {
			wideValue = WIDE_MAX;
		    }
		}
		if ((flags & SCAN_UNSIGNED) && (wideValue < 0)) {
		    mp_int big;
		    if (mp_init_u64(&big, (Tcl_WideUInt)wideValue) != MP_OKAY) {
			Tcl_SetObjResult(interp, Tcl_NewStringObj(
				"insufficient memory to create bignum", -1));
			Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
			Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
			return TCL_ERROR;
		    } else {
			Tcl_SetBignumObj(objPtr, &big);
		    }
		} else {
		    TclSetIntObj(objPtr, wideValue);
		}
950
951
952
953
954
955
956
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
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
1024
1025
1026
1027
1028
1029
1030
1031
1032

1033
1034
1035
1036
1037
1038
1039
1040







-
+




-
+

-
+

-
+








-
+



















-
+







			if (objs != NULL) {
			    Tcl_Free(objs);
			}
			Tcl_DecrRefCount(objPtr);
			Tcl_SetObjResult(interp, Tcl_NewStringObj(
				"unsigned bignum scans are invalid", -1));
			Tcl_SetErrorCode(interp, "TCL", "FORMAT",
				"BADUNSIGNED",NULL);
				"BADUNSIGNED", (char *)NULL);
			return TCL_ERROR;
		    }
		}
	    } else {
		if (TclGetLongFromObj(NULL, objPtr, &value) != TCL_OK) {
		if (TclGetIntFromObj(NULL, objPtr, &value) != TCL_OK) {
		    if (TclGetString(objPtr)[0] == '-') {
			value = LONG_MIN;
			value = INT_MIN;
		    } else {
			value = LONG_MAX;
			value = INT_MAX;
		    }
		}
		if ((flags & SCAN_UNSIGNED) && (value < 0)) {
#ifdef TCL_WIDE_INT_IS_LONG
		    mp_int big;
		    if (mp_init_u64(&big, (unsigned long)value) != MP_OKAY) {
			Tcl_SetObjResult(interp, Tcl_NewStringObj(
				"insufficient memory to create bignum", -1));
			Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
			Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
			return TCL_ERROR;
		    } else {
			Tcl_SetBignumObj(objPtr, &big);
		    }
#else
		    Tcl_SetWideIntObj(objPtr, (unsigned long)value);
#endif
		} else {
		    TclSetIntObj(objPtr, value);
		}
	    }
	    objs[objIndex++] = objPtr;
	    break;

	case 'f':
	    /*
	     * Scan a floating point number
	     */

	    objPtr = Tcl_NewDoubleObj(0.0);
	    TclNewDoubleObj(objPtr, 0.0);
	    Tcl_IncrRefCount(objPtr);
	    if (width == 0) {
		width = ~0;
	    }
	    if (TCL_OK != TclParseNumber(NULL, objPtr, NULL, string, width,
		    &end, TCL_PARSE_DECIMAL_ONLY | TCL_PARSE_NO_WHITESPACE | TCL_PARSE_NO_UNDERSCORE)) {
		Tcl_DecrRefCount(objPtr);
1013
1014
1015
1016
1017
1018
1019
1020
1021


1022
1023
1024
1025
1026
1027
1028
1051
1052
1053
1054
1055
1056
1057


1058
1059
1060
1061
1062
1063
1064
1065
1066







-
-
+
+







	    } else if (flags & SCAN_SUPPRESS) {
		Tcl_DecrRefCount(objPtr);
		string = end;
	    } else {
		double dvalue;
		if (Tcl_GetDoubleFromObj(NULL, objPtr, &dvalue) != TCL_OK) {
#ifdef ACCEPT_NAN
		    const Tcl_ObjIntRep *irPtr
			    = TclFetchIntRep(objPtr, &tclDoubleType);
		    const Tcl_ObjInternalRep *irPtr
			    = TclFetchInternalRep(objPtr, &tclDoubleType);
		    if (irPtr) {
			dvalue = irPtr->doubleValue;
		    } else
#endif
		    {
			Tcl_DecrRefCount(objPtr);
			goto done;
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
1116
1117
1118
1119
1120
1121
1122


1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143

1144
1145
1146
1147
1148
1149
1150
1151







+
+

-
+

-
+

-
+






+
+
-
-
+
+

+
+
+
+
+
+
+
+
+
+








-
+







		code = TCL_ERROR;
	    }
	    Tcl_DecrRefCount(objs[i]);
	}
    } else {
	/*
	 * Here no vars were specified, we want a list returned (inline scan)
	 * We create an empty Tcl_Obj to fill missing values rather than
	 * allocating a new Tcl_Obj every time. See test scan-bigdata-XX.
	 */

	Tcl_Obj *emptyObj = NULL;
	TclNewObj(objPtr);
	for (i = 0; i < totalVars; i++) {
	for (i = 0; code == TCL_OK && i < totalVars; i++) {
	    if (objs[i] != NULL) {
		Tcl_ListObjAppendElement(NULL, objPtr, objs[i]);
		code = Tcl_ListObjAppendElement(interp, objPtr, objs[i]);
		Tcl_DecrRefCount(objs[i]);
	    } else {
		/*
		 * More %-specifiers than matching chars, so we just spit out
		 * empty strings for these.
		 */
		if (!emptyObj) {
		    TclNewObj(emptyObj);

		Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewObj());
		}
		code = Tcl_ListObjAppendElement(interp, objPtr, emptyObj);
	    }
	}
	if (code != TCL_OK) {
	    /* If error'ed out, free up remaining. i contains last index freed */
	    while (++i < totalVars) {
		if (objs[i] != NULL) {
		    Tcl_DecrRefCount(objs[i]);
		}
	    }
	    Tcl_DecrRefCount(objPtr);
	    objPtr = NULL;
	}
    }
    if (objs != NULL) {
	Tcl_Free(objs);
    }
    if (code == TCL_OK) {
	if (underflow && (nconversions == 0)) {
	    if (numVars) {
		TclNewIndexObj(objPtr, TCL_INDEX_NONE);
		TclNewIntObj(objPtr, -1);
	    } else {
		if (objPtr) {
		    Tcl_SetListObj(objPtr, 0, NULL);
		} else {
		    TclNewObj(objPtr);
		}
	    }

Added generic/tclStrIdxTree.c.














































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tclStrIdxTree.c --
 *
 *	Contains the routines for managing string index tries in Tcl.
 *
 *	This code is back-ported from the tclSE engine, by Serg G. Brester.
 *
 * Copyright (c) 2016 by Sergey G. Brester aka sebres. All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * -----------------------------------------------------------------------
 *
 * String index tries are prepaired structures used for fast greedy search of the string
 * (index) by unique string prefix as key.
 *
 * Index tree build for two lists together can be explained in the following datagram
 *
 * Lists:
 *
 *	{Januar Februar Maerz April Mai Juni Juli August September Oktober November Dezember}
 *	{Jnr Fbr Mrz Apr Mai Jni Jli Agt Spt Okt Nvb Dzb}
 *
 * Index-Tree:
 *
 *	j		 0	 *	...
 *	 anuar		 1	 *
 *	 u		 0	 *	a		 0
 *	  ni		 6	 *	 pril		 4
 *	  li		 7	 *	 ugust		 8
 *	 n		 0	 *	 gt		 8
 *	  r		 1	 *	s		 9
 *	  i		 6	 *	 eptember	 9
 *	 li		 7	 *	 pt		 9
 *	f		 2	 *	oktober		10
 *	 ebruar		 2	 *	n		11
 *	 br		 2	 *	 ovember	11
 *	m		 0	 *	 vb		11
 *	 a		 0	 *	d		12
 *	  erz		 3	 *	 ezember	12
 *	  i		 5	 *	 zb		12
 *	 rz		 3	 *
 *	...
 *
 * Thereby value 0 shows pure group items (corresponding ambigous matches).
 * But the group may have a value if it contains only same values
 * (see for example group "f" above).
 *
 * StrIdxTree's are very fast, so:
 *    build of above-mentioned tree takes about 10 microseconds.
 *    search of string index in this tree takes fewer as 0.1 microseconds.
 *
 */

#include "tclInt.h"
#include "tclStrIdxTree.h"

static void		StrIdxTreeObj_DupIntRepProc(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
static void		StrIdxTreeObj_FreeIntRepProc(Tcl_Obj *objPtr);
static void		StrIdxTreeObj_UpdateStringProc(Tcl_Obj *objPtr);

static const Tcl_ObjType StrIdxTreeObjType = {
    "str-idx-tree",			/* name */
    StrIdxTreeObj_FreeIntRepProc,	/* freeIntRepProc */
    StrIdxTreeObj_DupIntRepProc,	/* dupIntRepProc */
    StrIdxTreeObj_UpdateStringProc,	/* updateStringProc */
    NULL,				/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

/*
 *----------------------------------------------------------------------
 *
 * TclStrIdxTreeSearch --
 *
 *	Find largest part of string "start" in indexed tree (case sensitive).
 *
 *	Also used for building of string index tree.
 *
 * Results:
 *	Return position of UTF character in start after last equal character
 *	and found item (with parent).
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
const char *
TclStrIdxTreeSearch(
    TclStrIdxTree **foundParent,/* Return value of found sub tree (used for tree build) */
    TclStrIdx **foundItem,	/* Return value of found item */
    TclStrIdxTree *tree,	/* Index tree will be browsed */
    const char *start,		/* UTF string to find in tree */
    const char *end)		/* End of string */
{
    TclStrIdxTree *parent = tree, *prevParent = tree;
    TclStrIdx  *item = tree->firstPtr, *prevItem = NULL;
    const char *s = start, *f, *cin, *cinf, *prevf = NULL;
    Tcl_Size offs = 0;

    if (item == NULL) {
	goto done;
    }

    /* search in tree */
    do {
	cinf = cin = TclGetString(item->key) + offs;
	f = TclUtfFindEqualNCInLwr(s, end, cin, cin + item->length - offs, &cinf);
	/* if something was found */
	if (f > s) {
	    /* if whole string was found */
	    if (f >= end) {
		start = f;
		goto done;
	    }

	    /* set new offset and shift start string */
	    offs += cinf - cin;
	    s = f;

	    /* if match item, go deeper as long as possible */
	    if (offs >= item->length && item->childTree.firstPtr) {
		/* save previuosly found item (if not ambigous) for
		 * possible fallback (few greedy match) */
		if (item->value != NULL) {
		    prevf = f;
		    prevItem = item;
		    prevParent = parent;
		}
		parent = &item->childTree;
		item = item->childTree.firstPtr;
		continue;
	    }

	    /* no children - return this item and current chars found */
	    start = f;
	    goto done;
	}

	item = item->nextPtr;
    } while (item != NULL);

    /* fallback (few greedy match) not ambigous (has a value) */
    if (prevItem != NULL) {
	item = prevItem;
	parent = prevParent;
	start = prevf;
    }

  done:
    if (foundParent) {
	*foundParent = parent;
    }
    if (foundItem) {
	*foundItem = item;
    }
    return start;
}

void
TclStrIdxTreeFree(
    TclStrIdx *tree)
{
    while (tree != NULL) {
	TclStrIdx *t = tree;

	Tcl_DecrRefCount(tree->key);
	if (tree->childTree.firstPtr != NULL) {
	    TclStrIdxTreeFree(tree->childTree.firstPtr);
	}
	tree = tree->nextPtr;
	Tcl_Free(t);
    }
}

/*
 * Several bidirectional list primitives
 */

static inline void
TclStrIdxTreeInsertBranch(
    TclStrIdxTree *parent,
    TclStrIdx *item,
    TclStrIdx *child)
{
    if (parent->firstPtr == child) {
	parent->firstPtr = item;
    }
    if (parent->lastPtr == child) {
	parent->lastPtr = item;
    }
    if ((item->nextPtr = child->nextPtr) != NULL) {
	item->nextPtr->prevPtr = item;
	child->nextPtr = NULL;
    }
    if ((item->prevPtr = child->prevPtr) != NULL) {
	item->prevPtr->nextPtr = item;
	child->prevPtr = NULL;
    }
    item->childTree.firstPtr = child;
    item->childTree.lastPtr = child;
}

static inline void
TclStrIdxTreeAppend(
    TclStrIdxTree *parent,
    TclStrIdx *item)
{
    if (parent->lastPtr != NULL) {
	parent->lastPtr->nextPtr = item;
    }
    item->prevPtr = parent->lastPtr;
    item->nextPtr = NULL;
    parent->lastPtr = item;
    if (parent->firstPtr == NULL) {
	parent->firstPtr = item;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclStrIdxTreeBuildFromList --
 *
 *	Build or extend string indexed tree from tcl list. If the values not
 *	given the values of built list are indices starts with 1. Value of 0
 *	is thereby reserved to the ambigous values.
 *
 *	Important: by multiple lists, optimal tree can be created only if list
 *	with larger strings used firstly.
 *
 * Results:
 *	Returns a standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
int
TclStrIdxTreeBuildFromList(
    TclStrIdxTree *idxTree,
    Tcl_Size lstc,
    Tcl_Obj **lstv,
    void **values)
{
    Tcl_Obj **lwrv;
    Tcl_Size i;
    int ret = TCL_ERROR;
    void *val;
    const char *s, *e, *f;
    TclStrIdx *item;

    /* create lowercase reflection of the list keys */

    lwrv = (Tcl_Obj **) Tcl_AttemptAlloc(sizeof(Tcl_Obj*) * lstc);
    if (lwrv == NULL) {
	return TCL_ERROR;
    }
    for (i = 0; i < lstc; i++) {
	lwrv[i] = Tcl_DuplicateObj(lstv[i]);
	Tcl_IncrRefCount(lwrv[i]);
	lwrv[i]->length = Tcl_UtfToLower(TclGetString(lwrv[i]));
    }

    /* build index tree of the list keys */
    for (i = 0; i < lstc; i++) {
	TclStrIdxTree *foundParent = idxTree;

	e = s = TclGetString(lwrv[i]);
	e += lwrv[i]->length;
	val = values ? values[i] : INT2PTR(i+1);

	/* ignore empty keys (impossible to index it) */
	if (lwrv[i]->length == 0) {
	    continue;
	}

	item = NULL;
	if (idxTree->firstPtr != NULL) {
	    TclStrIdx *foundItem;

	    f = TclStrIdxTreeSearch(&foundParent, &foundItem, idxTree, s, e);
	    /* if common prefix was found */
	    if (f > s) {
		/* ignore element if fulfilled or ambigous */
		if (f == e) {
		    continue;
		}

		/* if shortest key was found with the same value,
		 * just replace its current key with longest key */
		if (foundItem->value == val
			&& foundItem->length <= lwrv[i]->length
			&& foundItem->length <= (f - s) // only if found item is covered in full
			&& foundItem->childTree.firstPtr == NULL) {
		    TclSetObjRef(foundItem->key, lwrv[i]);
		    foundItem->length = lwrv[i]->length;
		    continue;
		}

		/* split tree (e. g. j->(jan,jun) + jul == j->(jan,ju->(jun,jul)) )
		 * but don't split by fulfilled child of found item ( ii->iii->iiii ) */
		if (foundItem->length != (f - s)) {
		    /* first split found item (insert one between parent and found + new one) */
		    item = (TclStrIdx *) Tcl_AttemptAlloc(sizeof(TclStrIdx));
		    if (item == NULL) {
			goto done;
		    }
		    TclInitObjRef(item->key, foundItem->key);
		    item->length = f - s;

		    /* set value or mark as ambigous if not the same value of both */
		    item->value = (foundItem->value == val) ? val : NULL;

		    /* insert group item between foundParent and foundItem */
		    TclStrIdxTreeInsertBranch(foundParent, item, foundItem);
		    foundParent = &item->childTree;
		} else {
		    /* the new item should be added as child of found item */
		    foundParent = &foundItem->childTree;
		}
	    }
	}

	/* append item at end of found parent */
	item = (TclStrIdx *) Tcl_AttemptAlloc(sizeof(TclStrIdx));
	if (item == NULL) {
	    goto done;
	}
	item->childTree.lastPtr = item->childTree.firstPtr = NULL;
	TclInitObjRef(item->key, lwrv[i]);
	item->length = lwrv[i]->length;
	item->value = val;
	TclStrIdxTreeAppend(foundParent, item);
    }

    ret = TCL_OK;
  done:
    if (lwrv != NULL) {
	for (i = 0; i < lstc; i++) {
	    Tcl_DecrRefCount(lwrv[i]);
	}
	Tcl_Free(lwrv);
    }
    if (ret != TCL_OK) {
	if (idxTree->firstPtr != NULL) {
	    TclStrIdxTreeFree(idxTree->firstPtr);
	}
    }
    return ret;
}

/* Is a Tcl_Obj (of right type) holding a smart pointer link? */
static inline int
IsLink(
    Tcl_Obj *objPtr)
{
    Tcl_ObjInternalRep *irPtr = &objPtr->internalRep;
    return irPtr->twoPtrValue.ptr1 && !irPtr->twoPtrValue.ptr2;
}

/* Follow links (smart pointers) if present. */
static inline Tcl_Obj *
FollowPossibleLink(
    Tcl_Obj *objPtr)
{
    if (IsLink(objPtr)) {
	objPtr = (Tcl_Obj *) objPtr->internalRep.twoPtrValue.ptr1;
    }
    /* assert(!IsLink(objPtr)); */
    return objPtr;
}

Tcl_Obj *
TclStrIdxTreeNewObj(void)
{
    Tcl_Obj *objPtr = Tcl_NewObj();
    TclStrIdxTree *tree = (TclStrIdxTree *) &objPtr->internalRep.twoPtrValue;

    /*
     * This assert states that we can safely directly have a tree node as the
     * internal representation of a Tcl_Obj instead of needing to hang it
     * off the back with an extra alloc.
     */
    TCL_CT_ASSERT(sizeof(TclStrIdxTree) <= sizeof(Tcl_ObjInternalRep));

    tree->firstPtr = NULL;
    tree->lastPtr = NULL;
    objPtr->typePtr = &StrIdxTreeObjType;
    /* return tree root in internal representation */
    return objPtr;
}

static void
StrIdxTreeObj_DupIntRepProc(
    Tcl_Obj *srcPtr,
    Tcl_Obj *copyPtr)
{
    /* follow links (smart pointers) */
    srcPtr = FollowPossibleLink(srcPtr);

    /* create smart pointer to it (ptr1 != NULL, ptr2 = NULL) */
    TclInitObjRef(*((Tcl_Obj **) &copyPtr->internalRep.twoPtrValue.ptr1),
	    srcPtr);
    copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
    copyPtr->typePtr = &StrIdxTreeObjType;
}

static void
StrIdxTreeObj_FreeIntRepProc(
    Tcl_Obj *objPtr)
{
    /* follow links (smart pointers) */
    if (IsLink(objPtr)) {
	/* is a link */
	TclUnsetObjRef(*((Tcl_Obj **) &objPtr->internalRep.twoPtrValue.ptr1));
    } else {
	/* is a tree */
	TclStrIdxTree *tree = (TclStrIdxTree *) &objPtr->internalRep.twoPtrValue;

	if (tree->firstPtr != NULL) {
	    TclStrIdxTreeFree(tree->firstPtr);
	}
	tree->firstPtr = NULL;
	tree->lastPtr = NULL;
    }
    objPtr->typePtr = NULL;
}

static void
StrIdxTreeObj_UpdateStringProc(
    Tcl_Obj *objPtr)
{
    /* currently only dummy empty string possible */
    objPtr->length = 0;
    objPtr->bytes = &tclEmptyString;
}

TclStrIdxTree *
TclStrIdxTreeGetFromObj(
    Tcl_Obj *objPtr)
{
    if (objPtr->typePtr != &StrIdxTreeObjType) {
	return NULL;
    }

    /* follow links (smart pointers) */
    objPtr = FollowPossibleLink(objPtr);

    /* return tree root in internal representation */
    return (TclStrIdxTree *) &objPtr->internalRep.twoPtrValue;
}

/*
 * Several debug primitives
 */
#ifdef TEST_STR_IDX_TREE
/* currently unused, debug resp. test purposes only */

static void
TclStrIdxTreePrint(
    Tcl_Interp *interp,
    TclStrIdx  *tree,
    int offs)
{
    Tcl_Obj *obj[2];
    const char *s;

    TclInitObjRef(obj[0], Tcl_NewStringObj("::puts", TCL_AUTO_LENGTH));
    while (tree != NULL) {
	s = TclGetString(tree->key) + offs;
	TclInitObjRef(obj[1], Tcl_ObjPrintf("%*s%.*s\t:%d",
		offs, "", tree->length - offs, s, tree->value));
	Tcl_PutsObjCmd(NULL, interp, 2, obj);
	TclUnsetObjRef(obj[1]);
	if (tree->childTree.firstPtr != NULL) {
	    TclStrIdxTreePrint(interp, tree->childTree.firstPtr, tree->length);
	}
	tree = tree->nextPtr;
    }
    TclUnsetObjRef(obj[0]);
}

int
TclStrIdxTreeTestObjCmd(
    void *clientData, Tcl_Interp *interp,
    int objc, Tcl_Obj *const objv[])
{
    const char *cs, *cin, *ret;
    static const char *const options[] = {
	"findequal", "index", "puts-index", NULL
    };
    enum optionInd {
	O_FINDEQUAL, O_INDEX,  O_PUTS_INDEX
    };
    int optionIndex;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], options,
	    "option", 0, &optionIndex) != TCL_OK) {
	Tcl_SetErrorCode(interp, "CLOCK", "badOption",
		TclGetString(objv[1]), (char *)NULL);
	return TCL_ERROR;
    }

    switch (optionIndex) {
    case O_FINDEQUAL:
	if (objc < 4) {
	    Tcl_WrongNumArgs(interp, 1, objv, "");
	    return TCL_ERROR;
	}
	cs = TclGetString(objv[2]);
	cin = TclGetString(objv[3]);
	ret = TclUtfFindEqual(
		cs, cs + objv[1]->length, cin, cin + objv[2]->length);
	Tcl_SetObjResult(interp, Tcl_NewIntObj(ret - cs));
	break;

    case O_INDEX:
    case O_PUTS_INDEX: {
	Tcl_Obj **lstv;
	Tcl_Size i, lstc;
	TclStrIdxTree idxTree = {NULL, NULL};

	i = 1;
	while (++i < objc) {
	    if (TclListObjGetElements(interp, objv[i],
		    &lstc, &lstv) != TCL_OK) {
		return TCL_ERROR;
	    }
	    TclStrIdxTreeBuildFromList(&idxTree, lstc, lstv, NULL);
	}
	if (optionIndex == O_PUTS_INDEX) {
	    TclStrIdxTreePrint(interp, idxTree.firstPtr, 0);
	}
	TclStrIdxTreeFree(idxTree.firstPtr);
	break;
    }
    }

    return TCL_OK;
}
#endif

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Added generic/tclStrIdxTree.h.






























































































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tclStrIdxTree.h --
 *
 *	Declarations of string index tries and other primitives currently
 *  back-ported from tclSE.
 *
 * Copyright (c) 2016 Serg G. Brester (aka sebres)
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _TCLSTRIDXTREE_H
#define _TCLSTRIDXTREE_H

#include "tclInt.h"

/*
 * Main structures declarations of index tree and entry
 */

typedef struct TclStrIdx TclStrIdx;

/*
 * Top level structure of the tree, or first two fields of the interior
 * structure.
 *
 * Note that this is EXACTLY two pointers so it is the same size as the
 * twoPtrValue of a Tcl_ObjInternalRep. This is how the top level structure
 * of the tree is always allocated. (This type constraint is asserted in
 * TclStrIdxTreeNewObj() so it's guaranteed.)
 *
 * Also note that if firstPtr is not NULL, lastPtr must also be not NULL.
 * The case where firstPtr is not NULL and lastPtr is NULL is special (a
 * smart pointer to one of these) and is not actually a valid instance of
 * this structure.
 */
typedef struct TclStrIdxTree {
    TclStrIdx *firstPtr;
    TclStrIdx *lastPtr;
} TclStrIdxTree;

/*
 * An interior node of the tree. Always directly allocated.
 */
struct TclStrIdx {
    TclStrIdxTree childTree;
    TclStrIdx *nextPtr;
    TclStrIdx *prevPtr;
    Tcl_Obj *key;
    Tcl_Size length;
    void *value;
};

/*
 *----------------------------------------------------------------------
 *
 * TclUtfFindEqual, TclUtfFindEqualNC --
 *
 *	Find largest part of string cs in string cin (case sensitive and not).
 *
 * Results:
 *	Return position of UTF character in cs after last equal character.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static inline const char *
TclUtfFindEqual(
    const char *cs,		/* UTF string to find in cin. */
    const char *cse,		/* End of cs */
    const char *cin,		/* UTF string will be browsed. */
    const char *cine)		/* End of cin */
{
    const char *ret = cs;
    Tcl_UniChar ch1, ch2;

    do {
	cs += TclUtfToUniChar(cs, &ch1);
	cin += TclUtfToUniChar(cin, &ch2);
	if (ch1 != ch2) {
	    break;
	}
    } while ((ret = cs) < cse && cin < cine);
    return ret;
}

static inline const char *
TclUtfFindEqualNC(
    const char *cs,		/* UTF string to find in cin. */
    const char *cse,		/* End of cs */
    const char *cin,		/* UTF string will be browsed. */
    const char *cine,		/* End of cin */
    const char **cinfnd)	/* Return position in cin */
{
    const char *ret = cs;
    Tcl_UniChar ch1, ch2;

    do {
	cs += TclUtfToUniChar(cs, &ch1);
	cin += TclUtfToUniChar(cin, &ch2);
	if (ch1 != ch2) {
	    ch1 = Tcl_UniCharToLower(ch1);
	    ch2 = Tcl_UniCharToLower(ch2);
	    if (ch1 != ch2) {
		break;
	    }
	}
	*cinfnd = cin;
    } while ((ret = cs) < cse && cin < cine);
    return ret;
}

static inline const char *
TclUtfFindEqualNCInLwr(
    const char *cs,		/* UTF string (in anycase) to find in cin. */
    const char *cse,		/* End of cs */
    const char *cin,		/* UTF string (in lowercase) will be browsed. */
    const char *cine,		/* End of cin */
    const char **cinfnd)	/* Return position in cin */
{
    const char *ret = cs;
    Tcl_UniChar ch1, ch2;

    do {
	cs += TclUtfToUniChar(cs, &ch1);
	cin += TclUtfToUniChar(cin, &ch2);
	if (ch1 != ch2) {
	    ch1 = Tcl_UniCharToLower(ch1);
	    if (ch1 != ch2) {
		break;
	    }
	}
	*cinfnd = cin;
    } while ((ret = cs) < cse && cin < cine);
    return ret;
}

/*
 * Primitives to safe set, reset and free references.
 */

#define TclUnsetObjRef(obj) \
    do {								\
	if (obj != NULL) {						\
	    Tcl_DecrRefCount(obj);					\
	    obj = NULL;							\
	}								\
    } while (0)
#define TclInitObjRef(obj, val) \
    do {								\
	obj = (val);							\
	if (obj) {							\
	    Tcl_IncrRefCount(obj);					\
	}								\
    } while (0)
#define TclSetObjRef(obj, val) \
    do {								\
	Tcl_Obj *nval = (val);						\
	if (obj != nval) {						\
	    Tcl_Obj *prev = obj;					\
	    TclInitObjRef(obj, nval);					\
	    if (prev != NULL) {						\
		Tcl_DecrRefCount(prev);					\
	    }								\
	}								\
    } while (0)

/*
 * Prototypes of module functions.
 */

MODULE_SCOPE const char*TclStrIdxTreeSearch(TclStrIdxTree **foundParent,
			    TclStrIdx **foundItem, TclStrIdxTree *tree,
			    const char *start, const char *end);
MODULE_SCOPE int	TclStrIdxTreeBuildFromList(TclStrIdxTree *idxTree,
			    Tcl_Size lstc, Tcl_Obj **lstv, void **values);
MODULE_SCOPE Tcl_Obj *	TclStrIdxTreeNewObj(void);
MODULE_SCOPE TclStrIdxTree*TclStrIdxTreeGetFromObj(Tcl_Obj *objPtr);

#ifdef TEST_STR_IDX_TREE
/* currently unused, debug resp. test purposes only */
MODULE_SCOPE Tcl_ObjCmdProc TclStrIdxTreeTestObjCmd;
#endif

#endif /* _TCLSTRIDXTREE_H */

Changes to generic/tclStrToD.c.

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
30
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
30
31
32
33
34









-
+













+
+
+
+







/*
 * tclStrToD.c --
 *
 *	This file contains a collection of procedures for managing conversions
 *	to/from floating-point in Tcl. They include TclParseNumber, which
 *	parses numbers from strings; TclDoubleDigits, which formats numbers
 *	into strings of digits, and procedures for interconversion among
 *	'double' and 'mp_int' types.
 *
 * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved.
 * Copyright © 2005 Kevin B. Kenny. All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclTomMath.h"
#include <float.h>
#include <math.h>

#ifdef _WIN32
#define copysign _copysign
#endif

#ifndef PRIx64
#   define PRIx64 TCL_LL_MODIFIER "x"
#endif

/*
 * This code supports (at least hypothetically), IBM, Cray, VAX and IEEE-754
 * floating point; of these, only IEEE-754 can represent NaN. IEEE-754 can be
 * uniquely determined by radix and by the widths of significand and exponent.
 */

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
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







-
-
+


-
-
-
-
-
+
+
+
+
+

-
+
+


-
+





-
-
-
+
+
+
+

-
+


+
+




-
+
-
-
+
-
-
-
-
-
+
+







/*
 * gcc on x86 needs access to rounding controls, because of a questionable
 * feature where it retains intermediate results as IEEE 'long double' values
 * somewhat unpredictably. It is tempting to include fpu_control.h, but that
 * file exists only on Linux; it is missing on Cygwin and MinGW. Most gcc-isms
 * and ix86-isms are factored out here.
 */

#if defined(__GNUC__)
# if defined(__GNUC__)
typedef unsigned int	fpu_control_t __attribute__ ((__mode__ (__HI__)));

#define _FPU_GETCW(cw)	__asm__ __volatile__ ("fnstcw %0" : "=m" (*&cw))
#define _FPU_SETCW(cw)	__asm__ __volatile__ ("fldcw %0" : : "m" (*&cw))
#   define FPU_IEEE_ROUNDING	0x027F
#   define ADJUST_FPU_CONTROL_WORD
#define TCL_IEEE_DOUBLE_ROUNDING \
#  define _FPU_GETCW(cw)	__asm__ __volatile__ ("fnstcw %0" : "=m" (*&cw))
#  define _FPU_SETCW(cw)	__asm__ __volatile__ ("fldcw %0" : : "m" (*&cw))
#  define FPU_IEEE_ROUNDING	0x027F
#  define ADJUST_FPU_CONTROL_WORD
#  define TCL_IEEE_DOUBLE_ROUNDING_DECL \
    fpu_control_t roundTo53Bits = FPU_IEEE_ROUNDING;	\
    fpu_control_t oldRoundingMode;			\
    fpu_control_t oldRoundingMode;
#  define TCL_IEEE_DOUBLE_ROUNDING \
    _FPU_GETCW(oldRoundingMode);			\
    _FPU_SETCW(roundTo53Bits)
#define TCL_DEFAULT_DOUBLE_ROUNDING \
#  define TCL_DEFAULT_DOUBLE_ROUNDING \
    _FPU_SETCW(oldRoundingMode)

/*
 * Sun ProC needs sunmath for rounding control on x86 like gcc above.
 */
#elif defined(__sun)
#include <sunmath.h>
#define TCL_IEEE_DOUBLE_ROUNDING \
# elif defined(__sun)
#  include <sunmath.h>
#  define TCL_IEEE_DOUBLE_ROUNDING_DECL
#  define TCL_IEEE_DOUBLE_ROUNDING \
    ieee_flags("set","precision","double",NULL)
#define TCL_DEFAULT_DOUBLE_ROUNDING \
#  define TCL_DEFAULT_DOUBLE_ROUNDING \
    ieee_flags("clear","precision",NULL,NULL)

# endif
#endif
/*
 * Other platforms are assumed to always operate in full IEEE mode, so we make
 * the macros to go in and out of that mode do nothing.
 */

#ifndef TCL_IEEE_DOUBLE_ROUNDING /* !__i386 || (!__GNUC__ && !__sun) */
#else /* !__GNUC__ && !__sun */
#define TCL_IEEE_DOUBLE_ROUNDING	((void) 0)
#  define TCL_IEEE_DOUBLE_ROUNDING_DECL
#define TCL_DEFAULT_DOUBLE_ROUNDING	((void) 0)
#endif
#else /* !__i386 */
#define TCL_IEEE_DOUBLE_ROUNDING	((void) 0)
#define TCL_DEFAULT_DOUBLE_ROUNDING	((void) 0)
#  define TCL_IEEE_DOUBLE_ROUNDING	((void) 0)
#  define TCL_DEFAULT_DOUBLE_ROUNDING	((void) 0)
#endif

/*
 * MIPS floating-point units need special settings in control registers to use
 * gradual underflow as we expect.  This fix is for the MIPSpro compiler.
 */

117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
120
121
122
123
124
125
126

127
128
129
130
131
132
133
134







-
+







#define TWO_OVER_3LOG10 0.28952965460216784
#define LOG10_3HALVES_PLUS_FUDGE 0.1760912590558

/*
 * Definitions of the parts of an IEEE754-format floating point number.
 */

#define SIGN_BIT 	0x80000000
#define SIGN_BIT	0x80000000
				/* Mask for the sign bit in the first word of
				 * a double. */
#define EXP_MASK	0x7FF00000
				/* Mask for the exponent field in the first
				 * word of a double. */
#define EXP_SHIFT	20	/* Shift count to make the exponent an
				 * integer. */
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-
-
+
+







static const int log2pow5[27] = {
    01,  3,  5,  7, 10, 12, 14, 17, 19, 21,
    24, 26, 28, 31, 33, 35, 38, 40, 42, 45,
    47, 49, 52, 54, 56, 59, 61
};
#define N_LOG2POW5 27

static const Tcl_WideUInt wuipow5[27] = {
    (Tcl_WideUInt) 1,		/* 5**0 */
    (Tcl_WideUInt) 5,
    (Tcl_WideUInt) 25,
    (Tcl_WideUInt) 125,
    (Tcl_WideUInt) 625,
    (Tcl_WideUInt) 3125,	/* 5**5 */
    (Tcl_WideUInt) 3125*5,
    (Tcl_WideUInt) 3125*25,
    (Tcl_WideUInt) 3125*125,
    (Tcl_WideUInt) 3125*625,
    (Tcl_WideUInt) 3125*3125,	/* 5**10 */
    (Tcl_WideUInt) 3125*3125*5,
    (Tcl_WideUInt) 3125*3125*25,
    (Tcl_WideUInt) 3125*3125*125,
    (Tcl_WideUInt) 3125*3125*625,
    (Tcl_WideUInt) 3125*3125*3125, /* 5**15 */
    (Tcl_WideUInt) 3125*3125*3125*5,
    (Tcl_WideUInt) 3125*3125*3125*25,
    (Tcl_WideUInt) 3125*3125*3125*125,
    (Tcl_WideUInt) 3125*3125*3125*625,
    (Tcl_WideUInt) 3125*3125*3125*3125,	/* 5**20 */
    (Tcl_WideUInt) 3125*3125*3125*3125*5,
    (Tcl_WideUInt) 3125*3125*3125*3125*25,
    (Tcl_WideUInt) 3125*3125*3125*3125*125,
    (Tcl_WideUInt) 3125*3125*3125*3125*625,
    (Tcl_WideUInt) 3125*3125*3125*3125*3125,  /* 5**25 */
    (Tcl_WideUInt) 3125*3125*3125*3125*3125*5 /* 5**26 */
static const Tcl_WideUInt wuipow5[] = {
    (Tcl_WideUInt) 1U,		/* 5**0 */
    (Tcl_WideUInt) 5U,
    (Tcl_WideUInt) 25U,
    (Tcl_WideUInt) 125U,
    (Tcl_WideUInt) 625U,
    (Tcl_WideUInt) 3125U,	/* 5**5 */
    (Tcl_WideUInt) 3125U*5U,
    (Tcl_WideUInt) 3125U*25U,
    (Tcl_WideUInt) 3125U*125U,
    (Tcl_WideUInt) 3125U*625U,
    (Tcl_WideUInt) 3125U*3125U,	/* 5**10 */
    (Tcl_WideUInt) 3125U*3125U*5U,
    (Tcl_WideUInt) 3125U*3125U*25U,
    (Tcl_WideUInt) 3125U*3125U*125U,
    (Tcl_WideUInt) 3125U*3125U*625U,
    (Tcl_WideUInt) 3125U*3125U*3125U, /* 5**15 */
    (Tcl_WideUInt) 3125U*3125U*3125U*5U,
    (Tcl_WideUInt) 3125U*3125U*3125U*25U,
    (Tcl_WideUInt) 3125U*3125U*3125U*125U,
    (Tcl_WideUInt) 3125U*3125U*3125U*625U,
    (Tcl_WideUInt) 3125U*3125U*3125U*3125U,	/* 5**20 */
    (Tcl_WideUInt) 3125U*3125U*3125U*3125U*5U,
    (Tcl_WideUInt) 3125U*3125U*3125U*3125U*25U,
    (Tcl_WideUInt) 3125U*3125U*3125U*3125U*125U,
    (Tcl_WideUInt) 3125U*3125U*3125U*3125U*625U,
    (Tcl_WideUInt) 3125U*3125U*3125U*3125U*3125U,  /* 5**25 */
    (Tcl_WideUInt) 3125U*3125U*3125U*3125U*3125U*5U,
    (Tcl_WideUInt) 3125U*3125U*3125U*3125U*3125U*25U /* 5**27 */
};

/*
 * Static functions defined in this file.
 */

static int		AccumulateDecimalDigit(unsigned, int,
			    Tcl_WideUInt *, mp_int *, int);
static double		MakeHighPrecisionDouble(int signum,
			    mp_int *significand, int nSigDigs, long exponent);
static double		MakeLowPrecisionDouble(int signum,
			    Tcl_WideUInt significand, int nSigDigs,
			    long exponent);
#ifdef IEEE_FLOATING_POINT
static double		MakeNaN(int signum, Tcl_WideUInt tag);
#endif
static double		RefineApproximation(double approx,
			    mp_int *exactSignificand, int exponent);
static mp_err	MulPow5(mp_int *, unsigned, mp_int *) MP_WUR;
static int 		NormalizeRightward(Tcl_WideUInt *);
static mp_err		MulPow5(mp_int *, unsigned, mp_int *) MP_WUR;
static int		NormalizeRightward(Tcl_WideUInt *);
static int		RequiredPrecision(Tcl_WideUInt);
static void		DoubleToExpAndSig(double, Tcl_WideUInt *, int *,
			    int *);
static void		TakeAbsoluteValue(Double *, int *);
static char *		FormatInfAndNaN(Double *, int *, char **);
static char *		FormatZero(int *, char **);
static int		ApproximateLog10(Tcl_WideUInt, int, int);
377
378
379
380
381
382
383
384
385
386



387
388
389
390
391
392
393
381
382
383
384
385
386
387



388
389
390
391
392
393
394
395
396
397







-
-
-
+
+
+







 *	number in a format recognized by Tcl.
 *
 *	The arguments bytes, numBytes, and objPtr are the inputs which
 *	determine the string to be parsed. If bytes is non-NULL, it points to
 *	the first byte to be scanned. If bytes is NULL, then objPtr must be
 *	non-NULL, and the string representation of objPtr will be scanned
 *	(generated first, if necessary). The numBytes argument determines the
 *	number of bytes to be scanned. If numBytes is negative, the first NUL
 *	byte encountered will terminate the scan. If numBytes is non-negative,
 *	then no more than numBytes bytes will be scanned.
 *	number of bytes to be scanned. If numBytes is TCL_INDEX_NONE, the first NUL
 *	byte encountered will terminate the scan. Otherwise,
 *	no more than numBytes bytes will be scanned.
 *
 *	The argument flags is an input that controls the numeric formats
 *	recognized by the parser. The flag bits are:
 *
 *	- TCL_PARSE_INTEGER_ONLY:	accept only integer values; reject
 *		strings that denote floating point values (or accept only the
 *		leading portion of them that are integer values).
475
476
477
478
479
480
481
482

483
484
485
486
487
488
489
479
480
481
482
483
484
485

486
487
488
489
490
491
492
493







-
+







    Tcl_Interp *interp,		/* Used for error reporting. May be NULL. */
    Tcl_Obj *objPtr,		/* Object to receive the internal rep. */
    const char *expected,	/* Description of the type of number the
				 * caller expects to be able to parse
				 * ("integer", "boolean value", etc.). */
    const char *bytes,		/* Pointer to the start of the string to
				 * scan. */
    size_t numBytes,		/* Maximum number of bytes to scan, see
    Tcl_Size numBytes,		/* Maximum number of bytes to scan, see
				 * above. */
    const char **endPtrPtr,	/* Place to store pointer to the character
				 * that terminated the scan. */
    int flags)			/* Flags governing the parse. */
{
    enum State {
	INITIAL, SIGNUM, ZERO, ZERO_X,
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571

















































































572
573
574
575
576
577
578
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660







-
+


-
+






-
-

-
-
+








-
+



-
-
+
+
















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







				 * point in the parse. */
    int numDigitsAfterDp = 0;	/* Number of digits scanned after the decimal
				 * point. */
    int exponentSignum = 0;	/* Signum of the exponent of a floating point
				 * number. */
    long exponent = 0;		/* Exponent of a floating point number. */
    const char *p;		/* Pointer to next character to scan. */
    size_t len;			/* Number of characters remaining after p. */
    Tcl_Size len;		/* Number of characters remaining after p. */
    const char *acceptPoint;	/* Pointer to position after last character in
				 * an acceptable number. */
    size_t acceptLen;		/* Number of characters following that
    Tcl_Size acceptLen;		/* Number of characters following that
				 * point. */
    int status = TCL_OK;	/* Status to return to caller. */
    char d = 0;			/* Last hexadecimal digit scanned; initialized
				 * to avoid a compiler warning. */
    int shift = 0;		/* Amount to shift when accumulating binary */
    mp_err err = MP_OKAY;
    int under = 0;              /* Flag trailing '_' as error if true once
				 * number is accepted. */

#define ALL_BITS	((Tcl_WideUInt)-1)
#define MOST_BITS	(ALL_BITS >> 1)
#define MOST_BITS	(UWIDE_MAX >> 1)

    /*
     * Initialize bytes to start of the object's string rep if the caller
     * didn't pass anything else.
     */

    if (bytes == NULL) {
	if (interp == NULL && endPtrPtr == NULL) {
	    if (TclHasIntRep(objPtr, &tclDictType)) {
	    if (TclHasInternalRep(objPtr, &tclDictType)) {
		/* A dict can never be a (single) number */
		return TCL_ERROR;
	    }
	    if (TclHasIntRep(objPtr, &tclListType)) {
		int length;
	    if (TclHasInternalRep(objPtr, &tclListType)) {
		Tcl_Size length;
		/* A list can only be a (single) number if its length == 1 */
		TclListObjLength(NULL, objPtr, &length);
		if (length != 1) {
		    return TCL_ERROR;
		}
	    }
	}
	bytes = TclGetString(objPtr);
    }

    p = bytes;
    len = numBytes;
    acceptPoint = p;
    acceptLen = len;
    while (1) {
	char c = len ? *p : '\0';

	/*
	 * Filter out Numeric Whitespace. Expects:
	 *
	 *   ::digit:: '_' ::digit::
	 *
	 * Verify current '_' is ok, then move on to next character,
	 * otherwise follow through on to error.
	 */
	if (c == '_' && !(flags & TCL_PARSE_NO_UNDERSCORE)) {
	    const char *before, *after;

	    if (p==bytes) {
		/* Not allowed at beginning  */
		goto endgame;
	    }
	    /*
	     * span multiple numeric whitespace
	     *              V
	     *   example: 5___6
	     */
	    for (before = (p - 1);
		 (before && *before == '_');
		 before = (before > p ? (before - 1) : NULL));
	    for (after = (p + 1);
		 (after && *after && *after == '_');
		 after = (*after && *after == '_') ? (after + 1) : NULL);

	    switch (state) {
	    case ZERO_B:
	    case BINARY:
		if ((before && (*before != '0' && *before != '1')) ||
			(after && (*after != '0' && *after != '1'))) {
		    /* Not a valid digit */
		    goto endgame;
		}
		break;
	    case ZERO_O:
	    case OCTAL:
		if (((before && (*before < '0' || '7' < *before))) ||
			((after && (*after  < '0' || '7' < *after)))) {
		    goto endgame;
		}
		break;
	    case FRACTION:
	    case ZERO:
	    case ZERO_D:
	    case DECIMAL:
	    case LEADING_RADIX_POINT:
	    case EXPONENT_START:
	    case EXPONENT_SIGNUM:
	    case EXPONENT:
		if ((!before || isdigit(UCHAR(*before))) &&
			(!after || isdigit(UCHAR(*after)))) {
		    break;
		}
		if (after && *after=='(') {
		    /* could be function */
		    goto continue_num;
		}
		goto endgame;
	    case ZERO_X:
	    case HEXADECIMAL:
		if ( (!before || isxdigit(UCHAR(*before))) &&
			(!after || isxdigit(UCHAR(*after)))) {
		    break;
		}
		goto endgame;
	    default:
		/*
		 * Not whitespace, but could be legal for other reasons.
		 * Continue number processing for current character.
		 */
		goto continue_num;
	    }

	    /* Valid whitespace found, move on to the next character */
	    goto next;
	}

    continue_num:
	switch (state) {

	case INITIAL:
	    /*
	     * Initial state. Acceptable characters are +, -, digits, period,
	     * I, N, and whitespace.
	     */
640
641
642
643
644
645
646
647

648
649
650
651
652
653
654
655
656
657
658
659
660

661
662
663
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
707
708
709
710
711
712
713
714
715
716



717
718
719
720
721
722
723

724
725
726
727
728
729








730
731



732
733
734
735
736
737
738
722
723
724
725
726
727
728

729
730
731
732
733
734
735
736
737
738
739
740
741

742
743
744
745
746
747
748
749
750
751



752
753
754
755



756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775

776
777
778

779
780
781
782
783
784
785
786
787



788
789
790
791
792
793
794
795
796

797
798
799
800
801
802
803
804
805
806
807
808
809
810
811


812
813
814
815
816
817
818
819
820
821







-
+












-
+









-
-
-




-
-
-




















-



-









-
-
-
+
+
+






-
+






+
+
+
+
+
+
+
+
-
-
+
+
+







	     * OCTAL state differ only in whether they recognize 'X' and 'b'.
	     */

	    acceptState = state;
	    acceptPoint = p;
	    acceptLen = len;
	    if (c == 'x' || c == 'X') {
		if (flags & (TCL_PARSE_OCTAL_ONLY|TCL_PARSE_BINARY_ONLY) || under) {
		if (flags & (TCL_PARSE_OCTAL_ONLY|TCL_PARSE_BINARY_ONLY)) {
		    goto endgame;
		}
		state = ZERO_X;
		break;
	    }
	    if (flags & TCL_PARSE_HEXADECIMAL_ONLY) {
		goto zerox;
	    }
	    if (flags & TCL_PARSE_SCAN_PREFIXES) {
		goto zeroo;
	    }
	    if (c == 'b' || c == 'B') {
		if ((flags & TCL_PARSE_OCTAL_ONLY) || under) {
		if ((flags & TCL_PARSE_OCTAL_ONLY)) {
		    goto endgame;
		}
		state = ZERO_B;
		break;
	    }
	    if (flags & TCL_PARSE_BINARY_ONLY) {
		goto zerob;
	    }
	    if (c == 'o' || c == 'O') {
		if (under) {
		    goto endgame;
		}
		state = ZERO_O;
		break;
	    }
	    if (c == 'd' || c == 'D') {
		if (under) {
		    goto endgame;
		}
		state = ZERO_D;
		break;
	    }
	    goto decimal;

	case OCTAL:
	    /*
	     * Scanned an optional + or -, followed by a string of octal
	     * digits. Acceptable inputs are more digits, period, or E. If 8
	     * or 9 is encountered, commit to floating point.
	     */

	    acceptState = state;
	    acceptPoint = p;
	    acceptLen = len;
	    /* FALLTHROUGH */
	case ZERO_O:
	zeroo:
	    if (c == '0') {
		numTrailZeros++;
		under = 0;
		state = OCTAL;
		break;
	    } else if (c >= '1' && c <= '7') {
		under = 0;
		if (objPtr != NULL) {
		    shift = 3 * (numTrailZeros + 1);
		    significandOverflow = AccumulateDecimalDigit(
			    (unsigned)(c-'0'), numTrailZeros,
			    &significandWide, &significandBig,
			    significandOverflow);

		    if (!octalSignificandOverflow) {
			/*
			 * Shifting by more bits than are in the value being
			 * shifted is at least de facto nonportable. Check for
			 * too large shifts first.
			 * Shifting by as many or more bits than are in the
			 * value being shifted is undefined behavior. Check
			 * for too large shifts first.
			 */

			if ((octalSignificandWide != 0)
				&& (((size_t)shift >=
					CHAR_BIT*sizeof(Tcl_WideUInt))
				|| (octalSignificandWide >
					((Tcl_WideUInt)-1 >> shift)))) {
					(UWIDE_MAX >> shift)))) {
			    octalSignificandOverflow = 1;
			    err = mp_init_u64(&octalSignificandBig,
				    octalSignificandWide);
			}
		    }
		    if (!octalSignificandOverflow) {
			/*
			 * When the significand is 0, it is possible for the
			 * amount to be shifted to equal or exceed the width
			 * of the significand. Do not shift when the
			 * significand is 0 to avoid undefined behavior.
			 */

			if (octalSignificandWide != 0) {
			octalSignificandWide =
				(octalSignificandWide << shift) + (c - '0');
			    octalSignificandWide <<= shift;
			}
			octalSignificandWide += c - '0';
		    } else {
			if (err == MP_OKAY) {
			    err = mp_mul_2d(&octalSignificandBig, shift,
				    &octalSignificandBig);
			}
			if (err == MP_OKAY) {
			    err = mp_add_d(&octalSignificandBig, (mp_digit)(c - '0'),
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802



803
804
805
806
807

808
809
810
811
812
813










814

815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833

834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854



855
856
857
858
859

860
861
862
863
864
865










866

867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
830
831
832
833
834
835
836




837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855

856
857
858

859
860

861
862

863




864
865
866
867
868
869
870



871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913

914
915
916
917
918

919
920




921
922
923
924
925
926
927



928
929
930
931
932
933
934

935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951

952
953
954
955
956
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







-
-
-
-



















-



-


-


-

-
-
-
-







-
-
-
+
+
+




-
+






+
+
+
+
+
+
+
+
+
+
-
+


















-
+




-


-
-
-
-







-
-
-
+
+
+




-
+






+
+
+
+
+
+
+
+
+
+
-
+
















-


-
-
-
-
-


-
















-











-


-
-
-
-



-



-







		    numSigDigs += numTrailZeros+1;
		} else {
		    numSigDigs = 1;
		}
		numTrailZeros = 0;
		state = OCTAL;
		break;
            } else if (c == '_' && !(flags & TCL_PARSE_NO_UNDERSCORE)) {
                /* Ignore numeric "white space" */
                under = 1;
                break;
	    }
	    goto endgame;

	    /*
	     * Scanned 0x. If state is HEXADECIMAL, scanned at least one
	     * character following the 0x. The only acceptable inputs are
	     * hexadecimal digits.
	     */

	case HEXADECIMAL:
	    acceptState = state;
	    acceptPoint = p;
	    acceptLen = len;
	    /* FALLTHROUGH */

	case ZERO_X:
	zerox:
	    if (c == '0') {
		numTrailZeros++;
		under = 0;
		state = HEXADECIMAL;
		break;
	    } else if (isdigit(UCHAR(c))) {
		under = 0;
		d = (c-'0');
	    } else if (c >= 'A' && c <= 'F') {
		under = 0;
		d = (c-'A'+10);
	    } else if (c >= 'a' && c <= 'f') {
		under = 0;
		d = (c-'a'+10);
            } else if (c == '_' && !(flags & TCL_PARSE_NO_UNDERSCORE)) {
                /* Ignore numeric "white space" */
                under = 1;
                break;
	    } else {
		goto endgame;
	    }
	    if (objPtr != NULL) {
		shift = 4 * (numTrailZeros + 1);
		if (!significandOverflow) {
		    /*
		     * Shifting by more bits than are in the value being
		     * shifted is at least de facto nonportable. Check for too
		     * large shifts first.
		     * Shifting by as many or more bits than are in the
		     * value being shifted is undefined behavior. Check
		     * for too large shifts first.
		     */

		    if (significandWide != 0 &&
			    ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
			    significandWide > ((Tcl_WideUInt)-1 >> shift))) {
			    significandWide > (UWIDE_MAX >> shift))) {
			significandOverflow = 1;
			err = mp_init_u64(&significandBig,
				significandWide);
		    }
		}
		if (!significandOverflow) {
		    /*
		     * When the significand is 0, it is possible for the
		     * amount to be shifted to equal or exceed the width
		     * of the significand. Do not shift when the
		     * significand is 0 to avoid undefined behavior.
		     */

		    if (significandWide != 0) {
			significandWide <<= shift;
		    }
		    significandWide = (significandWide << shift) + d;
		    significandWide += d;
		} else if (err == MP_OKAY) {
		    err = mp_mul_2d(&significandBig, shift, &significandBig);
		    if (err == MP_OKAY) {
			err = mp_add_d(&significandBig, (mp_digit) d, &significandBig);
		    }
		}
	    }
	    if (err != MP_OKAY) {
		return TCL_ERROR;
	    }
	    numTrailZeros = 0;
	    state = HEXADECIMAL;
	    break;

	case BINARY:
	    acceptState = state;
	    acceptPoint = p;
	    acceptLen = len;
		/* FALLTHRU */
	    /* FALLTHRU */
	case ZERO_B:
	zerob:
	    if (c == '0') {
		numTrailZeros++;
		under = 0;
		state = BINARY;
		break;
            } else if (c == '_' && !(flags & TCL_PARSE_NO_UNDERSCORE)) {
                /* Ignore numeric "white space" */
                under = 1;
                break;
	    } else if (c != '1') {
		goto endgame;
	    }
	    if (objPtr != NULL) {
		shift = numTrailZeros + 1;
		if (!significandOverflow) {
		    /*
		     * Shifting by more bits than are in the value being
		     * shifted is at least de facto nonportable. Check for too
		     * large shifts first.
		     * Shifting by as many or more bits than are in the
		     * value being shifted is undefined behavior. Check
		     * for too large shifts first.
		     */

		    if (significandWide != 0 &&
			    ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
			    significandWide > ((Tcl_WideUInt)-1 >> shift))) {
			    significandWide > (UWIDE_MAX >> shift))) {
			significandOverflow = 1;
			err = mp_init_u64(&significandBig,
				significandWide);
		    }
		}
		if (!significandOverflow) {
		    /*
		     * When the significand is 0, it is possible for the
		     * amount to be shifted to equal or exceed the width
		     * of the significand. Do not shift when the
		     * significand is 0 to avoid undefined behavior.
		     */

		    if (significandWide != 0) {
			significandWide <<= shift;
		    }
		    significandWide = (significandWide << shift) + 1;
		    significandWide += 1;
		} else if (err == MP_OKAY) {
		    err = mp_mul_2d(&significandBig, shift, &significandBig);
		    if (err == MP_OKAY) {
			err = mp_add_d(&significandBig, (mp_digit) 1, &significandBig);
		    }
		}
	    }
	    if (err != MP_OKAY) {
		return TCL_ERROR;
	    }
	    numTrailZeros = 0;
	    state = BINARY;
	    break;

	case ZERO_D:
	    if (c == '0') {
		under = 0;
		numTrailZeros++;
	    } else if ( ! isdigit(UCHAR(c))) {
                if (c == '_' && !(flags & TCL_PARSE_NO_UNDERSCORE)) {
                    /* Ignore numeric "white space" */
                    under = 1;
                    break;
                }
		goto endgame;
	    }
	    under = 0;
	    state = DECIMAL;
	    flags |= TCL_PARSE_INTEGER_ONLY;
	    /* FALLTHROUGH */

	case DECIMAL:
	    /*
	     * Scanned an optional + or - followed by a string of decimal
	     * digits.
	     */

	decimal:
	    acceptState = state;
	    acceptPoint = p;
	    acceptLen = len;
	    if (c == '0') {
		numTrailZeros++;
		under = 0;
		state = DECIMAL;
		break;
	    } else if (isdigit(UCHAR(c))) {
		if (objPtr != NULL) {
		    significandOverflow = AccumulateDecimalDigit(
			    (unsigned)(c - '0'), numTrailZeros,
			    &significandWide, &significandBig,
			    significandOverflow);
		}
		numSigDigs += numTrailZeros+1;
		numTrailZeros = 0;
		under = 0;
		state = DECIMAL;
		break;
            } else if (c == '_' && !(flags & TCL_PARSE_NO_UNDERSCORE)) {
                /* Ignore numeric "white space" */
                under = 1;
                break;
	    } else if (flags & TCL_PARSE_INTEGER_ONLY) {
		goto endgame;
	    } else if (c == '.') {
		under = 0;
		state = FRACTION;
		break;
	    } else if (c == 'E' || c == 'e') {
		under = 0;
		state = EXPONENT_START;
		break;
	    }
	    goto endgame;

	    /*
	     * Found a decimal point. If no digits have yet been scanned, E is
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178

1179

1180
1181
1182
1183
1184
1185
1186
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
1116

1117
1118
1119
1120
1121
1122
1123
1124

1125
1126
1127
1128
1129
1130
1131

1132
1133
1134
1135
1136
1137

1138
1139
1140
1141
1142
1143

1144
1145
1146
1147
1148
1149

1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160

1161
1162
1163
1164
1165
1166

1167
1168
1169
1170
1171
1172
1173
1174
1175

1176
1177
1178
1179
1180
1181
1182
1183
1184
1185

1186
1187
1188
1189
1190
1191

1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205

1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217

1218

1219
1220
1221
1222
1223
1224
1225
1226







-
















-


-
-
-
-











-




-













-


-
-
-
-


















-


-
-
-
-










-






-








-







-






-






-






-











-






-









-










-






-














-












-
+
-
+







	    }
	    /* FALLTHROUGH */

	case LEADING_RADIX_POINT:
	    if (c == '0') {
		numDigitsAfterDp++;
		numTrailZeros++;
		under = 0;
		state = FRACTION;
		break;
	    } else if (isdigit(UCHAR(c))) {
		numDigitsAfterDp++;
		if (objPtr != NULL) {
		    significandOverflow = AccumulateDecimalDigit(
			    (unsigned)(c-'0'), numTrailZeros,
			    &significandWide, &significandBig,
			    significandOverflow);
		}
		if (numSigDigs != 0) {
		    numSigDigs += numTrailZeros+1;
		} else {
		    numSigDigs = 1;
		}
		numTrailZeros = 0;
		under = 0;
		state = FRACTION;
		break;
            } else if (c == '_' && !(flags & TCL_PARSE_NO_UNDERSCORE)) {
                /* Ignore numeric "white space" */
                under = 1;
                break;
	    }
	    goto endgame;

	case EXPONENT_START:
	    /*
	     * Scanned the E at the start of an exponent. Make sure a legal
	     * character follows before using the C library strtol routine,
	     * which allows whitespace.
	     */

	    if (c == '+') {
		under = 0;
		state = EXPONENT_SIGNUM;
		break;
	    } else if (c == '-') {
		exponentSignum = 1;
		under = 0;
		state = EXPONENT_SIGNUM;
		break;
	    }
	    /* FALLTHROUGH */

	case EXPONENT_SIGNUM:
	    /*
	     * Found the E at the start of the exponent, followed by a sign
	     * character.
	     */

	    if (isdigit(UCHAR(c))) {
		exponent = c - '0';
		under = 0;
		state = EXPONENT;
		break;
            } else if (c == '_' && !(flags & TCL_PARSE_NO_UNDERSCORE)) {
                /* Ignore numeric "white space" */
                under = 1;
                break;
	    }
	    goto endgame;

	case EXPONENT:
	    /*
	     * Found an exponent with at least one digit. Accumulate it,
	     * making sure to hard-pin it to LONG_MAX on overflow.
	     */

	    acceptState = state;
	    acceptPoint = p;
	    acceptLen = len;
	    if (isdigit(UCHAR(c))) {
		if (exponent < (LONG_MAX - 9) / 10) {
		    exponent = 10 * exponent + (c - '0');
		} else {
		    exponent = LONG_MAX;
		}
		under = 0;
		state = EXPONENT;
		break;
            } else if (c == '_' && !(flags & TCL_PARSE_NO_UNDERSCORE)) {
                /* Ignore numeric "white space" */
                under = 1;
                break;
	    }
	    goto endgame;

	    /*
	     * Parse out INFINITY by simply spelling it out. INF is accepted
	     * as an abbreviation; other prefices are not.
	     */

	case sI:
	    if (c == 'n' || c == 'N') {
		under = 0;
		state = sIN;
		break;
	    }
	    goto endgame;
	case sIN:
	    if (c == 'f' || c == 'F') {
		under = 0;
		state = sINF;
		break;
	    }
	    goto endgame;
	case sINF:
	    acceptState = state;
	    acceptPoint = p;
	    acceptLen = len;
            under = 0;
	    if (c == 'i' || c == 'I') {
		state = sINFI;
		break;
	    }
	    goto endgame;
	case sINFI:
	    if (c == 'n' || c == 'N') {
		under = 0;
		state = sINFIN;
		break;
	    }
	    goto endgame;
	case sINFIN:
	    if (c == 'i' || c == 'I') {
		under = 0;
		state = sINFINI;
		break;
	    }
	    goto endgame;
	case sINFINI:
	    if (c == 't' || c == 'T') {
		under = 0;
		state = sINFINIT;
		break;
	    }
	    goto endgame;
	case sINFINIT:
	    if (c == 'y' || c == 'Y') {
		under = 0;
		state = sINFINITY;
		break;
	    }
	    goto endgame;

	    /*
	     * Parse NaN's.
	     */
#ifdef IEEE_FLOATING_POINT
	case sN:
	    if (c == 'a' || c == 'A') {
		under = 0;
		state = sNA;
		break;
	    }
	    goto endgame;
	case sNA:
	    if (c == 'n' || c == 'N') {
		under = 0;
		state = sNAN;
		break;
	    }
	    goto endgame;
	case sNAN:
	    acceptState = state;
	    acceptPoint = p;
	    acceptLen = len;
	    if (c == '(') {
		under = 0;
		state = sNANPAREN;
		break;
	    }
	    goto endgame;

	    /*
	     * Parse NaN(hexdigits)
	     */
	case sNANHEX:
	    if (c == ')') {
		under = 0;
		state = sNANFINISH;
		break;
	    }
	    /* FALLTHROUGH */
	case sNANPAREN:
	    if (TclIsSpaceProcM(c)) {
		under = 0;
		break;
	    }
	    if (numSigDigs < 13) {
		if (c >= '0' && c <= '9') {
		    d = c - '0';
		} else if (c >= 'a' && c <= 'f') {
		    d = 10 + c - 'a';
		} else if (c >= 'A' && c <= 'F') {
		    d = 10 + c - 'A';
		} else {
		    goto endgame;
		}
		numSigDigs++;
		significandWide = (significandWide << 4) + d;
		under = 0;
		state = sNANHEX;
		break;
	    }
	    goto endgame;
	case sNANFINISH:
#endif

	case sINFINITY:
	    acceptState = state;
	    acceptPoint = p;
	    acceptLen = len;
	    goto endgame;

	}
	}
    next:
	p++;
	len--;
    }

  endgame:
    if (acceptState == INITIAL) {
	/*
1194
1195
1196
1197
1198
1199
1200
1201
1202


1203
1204
1205
1206
1207
1208
1209
1234
1235
1236
1237
1238
1239
1240


1241
1242
1243
1244
1245
1246
1247
1248
1249







-
-
+
+







    } else {
	/*
	 * Back up to the last accepting state in the lexer.
	 * If the last char seen is the numeric whitespace character '_',
	 * backup to that.
	 */

	p = under ? acceptPoint-1 : acceptPoint;
	len = under ? acceptLen-1 : acceptLen;
	p = acceptPoint;
	len = acceptLen;

	if (!(flags & TCL_PARSE_NO_WHITESPACE)) {
	    /*
	     * Accept trailing whitespace.
	     */

	    while (len != 0 && TclIsSpaceProcM(*p)) {
1221
1222
1223
1224
1225
1226
1227
1228

1229
1230
1231
1232
1233
1234
1235
1261
1262
1263
1264
1265
1266
1267

1268
1269
1270
1271
1272
1273
1274
1275







-
+







    }

    /*
     * Generate and store the appropriate internal rep.
     */

    if (status == TCL_OK && objPtr != NULL) {
	TclFreeIntRep(objPtr);
	TclFreeInternalRep(objPtr);
	switch (acceptState) {
	case SIGNUM:
	case ZERO_X:
	case ZERO_O:
	case ZERO_B:
	case ZERO_D:
	case LEADING_RADIX_POINT:
1255
1256
1257
1258
1259
1260
1261







1262


1263
1264
1265
1266
1267
1268
1269
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308

1309
1310
1311
1312
1313
1314
1315
1316
1317







+
+
+
+
+
+
+
-
+
+







		    ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
		    significandWide > (MOST_BITS + signum) >> shift)) {
		significandOverflow = 1;
		err = mp_init_u64(&significandBig, significandWide);
	    }
	    if (shift) {
		if (!significandOverflow) {
		    /*
		     * When the significand is 0, it is possible for the
		     * amount to be shifted to equal or exceed the width
		     * of the significand. Do not shift when the
		     * significand is 0 to avoid undefined behavior.
		     */
		    if (significandWide != 0) {
		    significandWide <<= shift;
			significandWide <<= shift;
		    }
		} else if (err == MP_OKAY) {
		    err = mp_mul_2d(&significandBig, shift, &significandBig);
		}
	    }
	    if (err != MP_OKAY) {
		return TCL_ERROR;
	    }
1279
1280
1281
1282
1283
1284
1285







1286


1287
1288
1289
1290
1291
1292
1293
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340

1341
1342
1343
1344
1345
1346
1347
1348
1349







+
+
+
+
+
+
+
-
+
+







		    ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
		    significandWide > (MOST_BITS + signum) >> shift)) {
		significandOverflow = 1;
		err = mp_init_u64(&significandBig, significandWide);
	    }
	    if (shift) {
		if (!significandOverflow) {
		    /*
		     * When the significand is 0, it is possible for the
		     * amount to be shifted to equal or exceed the width
		     * of the significand. Do not shift when the
		     * significand is 0 to avoid undefined behavior.
		     */
		    if (significandWide != 0) {
		    significandWide <<= shift;
			significandWide <<= shift;
		    }
		} else if (err == MP_OKAY) {
		    err = mp_mul_2d(&significandBig, shift, &significandBig);
		}
	    }
	    if (err != MP_OKAY) {
		return TCL_ERROR;
	    }
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
1360
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
1387
1388
1389

1390
1391
1392

1393
1394
1395
1396
1397
1398
1399
1400

1401
1402
1403
1404
1405
1406
1407
1408







+
+
+
+
+
+
+
-
+
+














-
+


-
+







-
+







		    octalSignificandWide > (MOST_BITS + signum) >> shift)) {
		octalSignificandOverflow = 1;
		err = mp_init_u64(&octalSignificandBig,
			octalSignificandWide);
	    }
	    if (shift) {
		if (!octalSignificandOverflow) {
		    /*
		     * When the significand is 0, it is possible for the
		     * amount to be shifted to equal or exceed the width
		     * of the significand. Do not shift when the
		     * significand is 0 to avoid undefined behavior.
		     */
		    if (octalSignificandWide != 0) {
		    octalSignificandWide <<= shift;
			octalSignificandWide <<= shift;
		    }
		} else if (err == MP_OKAY) {
		    err = mp_mul_2d(&octalSignificandBig, shift,
			    &octalSignificandBig);
		}
	    }
	    if (!octalSignificandOverflow) {
		if ((err == MP_OKAY) && (octalSignificandWide > (MOST_BITS + signum))) {
		    err = mp_init_u64(&octalSignificandBig,
			    octalSignificandWide);
		    octalSignificandOverflow = 1;
		} else {
		    objPtr->typePtr = &tclIntType;
		    if (signum) {
			objPtr->internalRep.wideValue =
				- (Tcl_WideInt) octalSignificandWide;
				(Tcl_WideInt)(-octalSignificandWide);
		    } else {
			objPtr->internalRep.wideValue =
				(Tcl_WideInt) octalSignificandWide;
				(Tcl_WideInt)octalSignificandWide;
		    }
		}
	    }
	    if ((err == MP_OKAY) && octalSignificandOverflow) {
		if (signum) {
		    err = mp_neg(&octalSignificandBig, &octalSignificandBig);
		}
		TclSetBignumIntRep(objPtr, &octalSignificandBig);
		TclSetBignumInternalRep(objPtr, &octalSignificandBig);
	    }
	    if (err != MP_OKAY) {
		return TCL_ERROR;
	    }
	    break;

	case ZERO:
1355
1356
1357
1358
1359
1360
1361
1362

1363
1364
1365

1366
1367
1368
1369
1370
1371
1372
1373

1374
1375
1376
1377
1378
1379
1380
1419
1420
1421
1422
1423
1424
1425

1426
1427
1428

1429
1430
1431
1432
1433
1434
1435
1436

1437
1438
1439
1440
1441
1442
1443
1444







-
+


-
+







-
+







		    err = mp_init_u64(&significandBig,
			    significandWide);
		    significandOverflow = 1;
		} else {
		    objPtr->typePtr = &tclIntType;
		    if (signum) {
			objPtr->internalRep.wideValue =
				- (Tcl_WideInt) significandWide;
				(Tcl_WideInt)(-significandWide);
		    } else {
			objPtr->internalRep.wideValue =
				(Tcl_WideInt) significandWide;
				(Tcl_WideInt)significandWide;
		    }
		}
	    }
	    if ((err == MP_OKAY) && significandOverflow) {
		if (signum) {
		    err = mp_neg(&significandBig, &significandBig);
		}
		TclSetBignumIntRep(objPtr, &significandBig);
		TclSetBignumInternalRep(objPtr, &significandBig);
	    }
	    if (err != MP_OKAY) {
		return TCL_ERROR;
	    }
	    break;

	case FRACTION:
1457
1458
1459
1460
1461
1462
1463
1464

1465
1466
1467
1468











1469
1470

1471
1472
1473
1474
1475
1476
1477
1521
1522
1523
1524
1525
1526
1527

1528
1529



1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541

1542
1543
1544
1545
1546
1547
1548
1549







-
+

-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
+








    /*
     * Format an error message when an invalid number is encountered.
     */

    if (status != TCL_OK) {
	if (interp != NULL) {
	    Tcl_Obj *msg = Tcl_ObjPrintf("expected %s but got \"",
	    Tcl_Obj *msg = Tcl_ObjPrintf("expected %s but got ",
		    expected);

	    Tcl_AppendLimitedToObj(msg, bytes, numBytes, 50, "");
	    Tcl_AppendToObj(msg, "\"", -1);
	    Tcl_Size argc;
	    const char **argv;
	    if ((TclMaxListLength(bytes, TCL_INDEX_NONE, NULL) > 1)
		    && Tcl_SplitList(NULL, bytes, &argc, &argv) == TCL_OK) {
		Tcl_Free(argv);
		Tcl_AppendToObj(msg, "a list", -1);
	    } else {
		Tcl_AppendToObj(msg, "\"", -1);
		Tcl_AppendLimitedToObj(msg, bytes, numBytes, 50, "");
		Tcl_AppendToObj(msg, "\"", -1);
	    }
	    Tcl_SetObjResult(interp, msg);
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "NUMBER", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "NUMBER", (char *)NULL);
	}
    }

    /*
     * Free memory.
     */

1526
1527
1528
1529
1530
1531
1532
1533

1534
1535
1536
1537
1538
1539
1540
1598
1599
1600
1601
1602
1603
1604

1605
1606
1607
1608
1609
1610
1611
1612







-
+







	    /*
	     * There's no need to multiply if the multiplicand is zero.
	     */

	    *wideRepPtr = digit;
	    return 0;
	} else if (numZeros >= maxpow10_wide
		|| w > ((Tcl_WideUInt)-1-digit)/pow10_wide[numZeros+1]) {
		|| w > (UWIDE_MAX-digit)/pow10_wide[numZeros+1]) {
	    /*
	     * Wide multiplication will overflow.  Expand the number to a
	     * bignum and fall through into the bignum case.
	     */

	    if (mp_init_u64(bignumRepPtr, w) != MP_OKAY) {
		return 0;
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
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







+
-
+







-
+
+

-
+
-


-
+
+

-



+
+
+
+
+
+
+







static double
MakeLowPrecisionDouble(
    int signum,			/* 1 if the number is negative, 0 otherwise */
    Tcl_WideUInt significand,	/* Significand of the number */
    int numSigDigs,		/* Number of digits in the significand */
    long exponent)		/* Power of ten */
{
    TCL_IEEE_DOUBLE_ROUNDING_DECL
    double retval;		/* Value of the number. */

    mp_int significandBig;	/* Significand expressed as a bignum. */

    /*
     * With gcc on x86, the floating point rounding mode is double-extended.
     * This causes the result of double-precision calculations to be rounded
     * twice: once to the precision of double-extended and then again to the
     * precision of double. Double-rounding introduces gratuitous errors of 1
     * ulp, so we need to change rounding mode to 53-bits.
     * ulp, so we need to change rounding mode to 53-bits. We also make
     * 'retval' volatile, so that it doesn't get promoted to a register.
     */

    volatile double retval;	/* Value of the number. */
    TCL_IEEE_DOUBLE_ROUNDING;

    /*
     * Test for the easy cases.
     * Test for zero significand, which requires explicit construction
     * of -0.0. (Unary minus returns a positive zero.)
     */

    if (significand == 0) {
	return copysign(0.0, -signum);
    }

    /*
     * Set the FP control word for 53 bits, WARNING: It must be reset
     * before returning.
     */
    TCL_IEEE_DOUBLE_ROUNDING;

    if (numSigDigs <= QUICK_MAX) {
	if (exponent >= 0) {
	    if (exponent <= mmaxpow) {
		/*
		 * The significand is an exact integer, and so is
		 * 10**exponent. The product will be correct to within 1/2 ulp
		 * without special handling.
1681
1682
1683
1684
1685
1686
1687
1688

1689
1690
1691
1692
1693
1694
1695
1761
1762
1763
1764
1765
1766
1767

1768
1769
1770
1771
1772
1773
1774
1775







-
+







			((Tcl_WideInt)significand / pow10vals[-exponent]);
		goto returnValue;
	    }
	}
    }

    /*
     * All the easy cases have failed. Promote ths significand to bignum and
     * All the easy cases have failed. Promote the significand to bignum and
     * call MakeHighPrecisionDouble to do it the hard way.
     */

    if (mp_init_u64(&significandBig, significand) != MP_OKAY) {
	return 0.0;
    }
    retval = MakeHighPrecisionDouble(0, &significandBig, numSigDigs,
1735
1736
1737
1738
1739
1740
1741

1742

1743
1744
1745
1746
1747
1748
1749
1750



1751
1752

1753
1754
1755
1756
1757


1758
1759
1760
1761
1762











1763
1764
1765
1766
1767
1768
1769
1815
1816
1817
1818
1819
1820
1821
1822

1823
1824
1825
1826
1827
1828
1829
1830

1831
1832
1833
1834

1835

1836
1837


1838
1839
1840

1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861







+
-
+







-
+
+
+

-
+
-


-
-
+
+

-



+
+
+
+
+
+
+
+
+
+
+







static double
MakeHighPrecisionDouble(
    int signum,			/* 1=negative, 0=nonnegative */
    mp_int *significand,	/* Exact significand of the number */
    int numSigDigs,		/* Number of significant digits */
    long exponent)		/* Power of 10 by which to multiply */
{
    TCL_IEEE_DOUBLE_ROUNDING_DECL
    double retval;

    int machexp = 0;		/* Machine exponent of a power of 10. */

    /*
     * With gcc on x86, the floating point rounding mode is double-extended.
     * This causes the result of double-precision calculations to be rounded
     * twice: once to the precision of double-extended and then again to the
     * precision of double. Double-rounding introduces gratuitous errors of 1
     * ulp, so we need to change rounding mode to 53-bits.
     * ulp, so we need to change rounding mode to 53-bits. We also make
     * 'retval' volatile to make sure that it doesn't get promoted to a
     * register.
     */

    volatile double retval;
    TCL_IEEE_DOUBLE_ROUNDING;

    /*
     * Quick checks for zero, and over/underflow. Be careful to avoid
     * integer overflow when calculating with 'exponent'.
     * A zero significand requires explicit construction of -0.0.
     * (Unary minus returns positive zero.)
     */

    if (mp_iszero(significand)) {
	return copysign(0.0, -signum);
    }

    /*
     * Set the 53-bit rounding mode. WARNING: It must be reset before
     * returning.
     */
    TCL_IEEE_DOUBLE_ROUNDING;

    /*
     * Make quick checks for over/underflow. Be careful to avoid
     * integer overflow when calculating with 'exponent'.
     */
    if (exponent >= 0 && exponent-1 > maxDigits-numSigDigs) {
	retval = HUGE_VAL;
	goto returnValue;
    } else if (exponent < 0 && numSigDigs+exponent < minDigits+1) {
	retval = 0.0;
	goto returnValue;
    }
1971
1972
1973
1974
1975
1976
1977
1978

1979
1980
1981
1982
1983
1984
1985
2063
2064
2065
2066
2067
2068
2069

2070
2071
2072
2073
2074
2075
2076
2077







-
+







	    return approxResult;
	}
    }

    /*
     * Compute twoMd as 2*M*d, where d is the exact value.
     * This is done by multiplying by 5**(M5+exponent) and then multiplying
     * by 2**(M5+exponent+1), which is, of couse, a left shift.
     * by 2**(M5+exponent+1), which is, of course, a left shift.
     */

    if (mp_init_copy(&twoMd, exactSignificand) != MP_OKAY) {
	mp_clear(&twoMv);
	return approxResult;
    }
    for (i = 0; (i <= 8); ++i) {
2058
2059
2060
2061
2062
2063
2064
2065

2066
2067
2068
2069
2070
2071
2072
2150
2151
2152
2153
2154
2155
2156

2157
2158
2159
2160
2161
2162
2163
2164







-
+








    /*
     * If we're in the 'round to even' case, and the significand is already
     * even, we're done. Return the approximate result.
     */
    if (roundToEven) {
	rteSignificand = frexp(approxResult, &rteExponent);
	rteSigWide = (Tcl_WideInt) ldexp(rteSignificand, FP_PRECISION);
	rteSigWide = (Tcl_WideInt)ldexp(rteSignificand, FP_PRECISION);
	if ((rteSigWide & 1) == 0) {
	    mp_clear(&twoMd);
	    mp_clear(&twoMv);
	    return approxResult;
	}
    }

2121
2122
2123
2124
2125
2126
2127
2128

2129
2130
2131
2132
2133
2134
2135
2213
2214
2215
2216
2217
2218
2219

2220
2221
2222
2223
2224
2225
2226
2227







-
+







 *	Stores base*5**n in result.
 *
 *----------------------------------------------------------------------
 */

static inline mp_err
MulPow5(
    mp_int *base, 		/* Number to multiply. */
    mp_int *base,		/* Number to multiply. */
    unsigned n,			/* Power of 5 to multiply by. */
    mp_int *result)		/* Place to store the result. */
{
    mp_int *p = base;
    int n13 = n / 13;
    int r = n % 13;
    mp_err err = MP_OKAY;
2200
2201
2202
2203
2204
2205
2206
2207

2208
2209
2210
2211
2212
2213
2214
2292
2293
2294
2295
2296
2297
2298

2299
2300
2301
2302
2303
2304
2305
2306







-
+







}

/*
 *----------------------------------------------------------------------
 *
 * RequiredPrecision --
 *
 *	Determines the number of bits needed to hold an intger.
 *	Determines the number of bits needed to hold an integer.
 *
 * Results:
 *	Returns the position of the most significant bit (0 - 63).  Returns 0
 *	if the number is zero.
 *
 *----------------------------------------------------------------------
 */
2564
2565
2566
2567
2568
2569
2570
2571

2572
2573
2574
2575
2576
2577
2578
2656
2657
2658
2659
2660
2661
2662

2663
2664
2665
2666
2667
2668
2669
2670







-
+







 *	one too high.
 *
 *----------------------------------------------------------------------
 */

static inline void
SetPrecisionLimits(
    int flags,		/* Type of conversion: TCL_DD_SHORTEST,
    int flags,			/* Type of conversion: TCL_DD_SHORTEST,
				 * TCL_DD_E_FMT, TCL_DD_F_FMT. */
    int k,			/* Floor(log10(number to convert)) */
    int *ndigitsPtr,		/* IN/OUT: Number of digits requested (will be
				 *         adjusted if needed). */
    int *iPtr,			/* OUT: Maximum number of digits to return. */
    int *iLimPtr,		/* OUT: Number of digits of significance if
				 *      the bignum method is used.*/
2618
2619
2620
2621
2622
2623
2624
2625

2626
2627
2628
2629
2630
2631
2632
2710
2711
2712
2713
2714
2715
2716

2717
2718
2719
2720
2721
2722
2723
2724







-
+







 *	"1" and moves the decimal point (*kPtr) one place to the right.
 *
 *----------------------------------------------------------------------
 */

static inline char *
BumpUp(
    char *s,		    	/* Cursor pointing one past the end of the
    char *s,			/* Cursor pointing one past the end of the
				 * string. */
    char *retval,		/* Start of the string of digits. */
    int *kPtr)			/* Position of the decimal point. */
{
    while (*--s == '9') {
	if (s == retval) {
	    ++(*kPtr);
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
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







-
+
















-
+








    if (k_check && d < 1. && ilim > 0) {
	if (ilim1 < 0) {
	    return NULL;
	}
	ilim = ilim1;
	--k;
	d *= 10.0;
	d = d * 10.0;
	++ieps;
    }

    /*
     * Compute estimated roundoff error.
     */

    eps.d = ieps * d + 7.;
    eps.w.word0 -= (FP_PRECISION-1) << EXP_SHIFT;

    /*
     * Handle the peculiar case where the result has no significant digits.
     */

    retval = (char *)Tcl_Alloc(len + 1);
    if (ilim == 0) {
	d -= 5.;
	d = d - 5.;
	if (d > eps.d) {
	    *retval = '1';
	    *decpt = k;
	    return retval;
	} else if (d < -eps.d) {
	    *decpt = k;
	    return retval;
3086
3087
3088
3089
3090
3091
3092
3093

3094
3095
3096
3097
3098
3099
3100
3178
3179
3180
3181
3182
3183
3184

3185
3186
3187
3188
3189
3190
3191
3192







-
+







	if (digit > 10) {
	    Tcl_Panic("wrong digit!");
	}
	b = b % S;

	/*
	 * Does the current digit put us on the low side of the exact value
	 * but within within roundoff of being exact?
	 * but within roundoff of being exact?
	 */

	if (b < mplus || (b == mplus
		&& (dPtr->w.word1 & 1) == 0)) {
	    /*
	     * Make sure we shouldn't be rounding *up* instead, in case the
	     * next number above is closer.
3345
3346
3347
3348
3349
3350
3351
3352


3353
3354
3355
3356
3357
3358
3359
3437
3438
3439
3440
3441
3442
3443

3444
3445
3446
3447
3448
3449
3450
3451
3452







-
+
+








    /*
     * Compare B and S-m - which is the same as comparing B+m and S - which we
     * do by computing b+m and doing a bitwhack compare against
     * 2**(MP_DIGIT_BIT*sd)
     */

    if ((mp_add(b, m, temp) != MP_OKAY) || (temp->used <= sd)) {	/* Too few digits to be > s */
    if ((mp_add(b, m, temp) != MP_OKAY) || (temp->used <= sd)) {
	/* Too few digits to be > s */
	return 0;
    }
    if (temp->used > sd+1 || temp->dp[sd] > 1) {
				/* >= 2s */
	return 1;
    }
    for (i = sd-1; i >= 0; --i) {
3483
3484
3485
3486
3487
3488
3489
3490

3491
3492
3493
3494
3495
3496
3497
3576
3577
3578
3579
3580
3581
3582

3583
3584
3585
3586
3587
3588
3589
3590







-
+







		Tcl_Panic("wrong digit!");
	    }
	    --b.used; mp_clamp(&b);
	}

	/*
	 * Does the current digit put us on the low side of the exact value
	 * but within within roundoff of being exact?
	 * but within roundoff of being exact?
	 */

	r1 = mp_cmp_mag(&b, (m2plus > m2minus)? &mplus : &mminus);
	if (r1 == MP_LT || (r1 == MP_EQ
		&& (dPtr->w.word1 & 1) == 0)) {
	    /*
	     * Make sure we shouldn't be rounding *up* instead, in case the
3564
3565
3566
3567
3568
3569
3570
3571

3572
3573
3574
3575
3576
3577
3578
3657
3658
3659
3660
3661
3662
3663

3664
3665
3666
3667
3668
3669
3670
3671







-
+







     * Endgame - store the location of the decimal point and the end of the
     * string.
     */

    if (m2plus > m2minus) {
	mp_clear(&mplus);
    }
    mp_clear_multi(&b, &mminus, &temp, NULL);
    mp_clear_multi(&b, &mminus, &temp, (void *)NULL);
    *s = '\0';
    *decpt = k;
    if (endPtr) {
	*endPtr = s;
    }
    return (err == MP_OKAY) ? retval : NULL;
}
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736



3737
3738
3739
3740
3741
3742
3743
3814
3815
3816
3817
3818
3819
3820


3821
3822
3823
3824



3825
3826
3827
3828
3829
3830
3831
3832
3833
3834







-
-




-
-
-
+
+
+







				 * produced the last digit. */
    mp_int *S,			/* Denominator. */
    int isodd)			/* Flag == 1 if the last digit is odd. */
{
    int r = mp_cmp_mag(twor, S);

    switch (r) {
    case MP_LT:
	return 0;
    case MP_EQ:
	return isodd;
    case MP_GT:
	return 1;
    }
    Tcl_Panic("in ShouldBankerRoundUp, trichotomy fails!");
    return 0;
    default:
	return 0;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ShouldBankerRoundUpToNext --
 *
3766
3767
3768
3769
3770
3771
3772
3773

3774
3775
3776
3777
3778
3779
3780
3781
3782



3783
3784
3785
3786
3787
3788
3789
3857
3858
3859
3860
3861
3862
3863

3864


3865
3866
3867
3868



3869
3870
3871
3872
3873
3874
3875
3876
3877
3878







-
+
-
-




-
-
-
+
+
+







     */

    if ((mp_init(&temp) != MP_OKAY) || (mp_add(b, m, &temp) != MP_OKAY)) {
	return 0;
    }
    r = mp_cmp_mag(&temp, S);
    mp_clear(&temp);
    switch(r) {
    switch (r) {
    case MP_LT:
	return 0;
    case MP_EQ:
	return isodd;
    case MP_GT:
	return 1;
    }
    Tcl_Panic("in ShouldBankerRoundUpToNext, trichotomy fails!");
    return 0;
    default:
	return 0;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ShorteningBignumConversion --
 *
4005
4006
4007
4008
4009
4010
4011
4012

4013
4014
4015
4016
4017
4018
4019
4094
4095
4096
4097
4098
4099
4100

4101
4102
4103
4104
4105
4106
4107
4108







-
+







     * Endgame - store the location of the decimal point and the end of the
     * string.
     */

    if (m2plus > m2minus) {
	mp_clear(&mplus);
    }
    mp_clear_multi(&b, &mminus, &dig, &S, NULL);
    mp_clear_multi(&b, &mminus, &dig, &S, (void *)NULL);
    *s = '\0';
    *decpt = k;
    if (endPtr) {
	*endPtr = s;
    }
    return retval;
}
4069
4070
4071
4072
4073
4074
4075
4076

4077
4078
4079
4080
4081
4082
4083
4158
4159
4160
4161
4162
4163
4164

4165
4166
4167
4168
4169
4170
4171
4172







-
+







    }
    if (mp_init_u64(&b, bw) != MP_OKAY) {
	mp_clear(&dig);
	return NULL;
    }
    err = mp_mul_2d(&b, b2, &b);
    if (err == MP_OKAY) {
 	err = mp_init_set(&S, 1);
	err = mp_init_set(&S, 1);
    }
    if (err == MP_OKAY) {
	err = MulPow5(&S, s5, &S);
	if (err == MP_OKAY) {
	    err = mp_mul_2d(&S, s2, &S);
	}
    }
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4234
4235
4236
4237
4238
4239
4240

4241
4242
4243
4244
4245
4246
4247







-







	     * less - unless we're working in F format - because we know that
	     * three groups of digits will always suffice for %#.17e, the
	     * longest format that doesn't introduce empty precision.
	     *
	     * Extract the next group of digits.
	     */


	    if ((err != MP_OKAY) || (mp_div(&b, &S, &dig, &b) != MP_OKAY) || (dig.used > 1)) {
		Tcl_Panic("wrong digit!");
	    }
	    digit = dig.dp[0];
	    for (j = g-1; j >= 0; --j) {
		int t = itens[j];

4180
4181
4182
4183
4184
4185
4186
4187

4188
4189
4190
4191
4192
4193
4194
4268
4269
4270
4271
4272
4273
4274

4275
4276
4277
4278
4279
4280
4281
4282







-
+







    ++s;

    /*
     * Endgame - store the location of the decimal point and the end of the
     * string.
     */

    mp_clear_multi(&b, &S, &dig, NULL);
    mp_clear_multi(&b, &S, &dig, (void *)NULL);
    *s = '\0';
    *decpt = k;
    if (endPtr) {
	*endPtr = s;
    }
    return retval;
}
4407
4408
4409
4410
4411
4412
4413
4414

4415
4416
4417
4418
4419
4420
4421
4495
4496
4497
4498
4499
4500
4501

4502
4503
4504
4505
4506
4507
4508
4509







-
+







	m2plus = m2minus;
	if (!denorm && bw == 1) {
	    ++b2;
	    ++s2;
	    ++m2plus;
	}

	if (s5+1 < N_LOG2POW5 && s2+1 + log2pow5[s5+1] <= 64) {
	if (s5+1 < N_LOG2POW5 && s2+1 + log2pow5[s5+1] < 64) {
	    /*
	     * If 10*2**s2*5**s5 == 2**(s2+1)+5**(s5+1) fits in a 64-bit word,
	     * then all our intermediate calculations can be done using exact
	     * 64-bit arithmetic with no need for expensive multiprecision
	     * operations. (This will be true for all numbers in the range
	     * [1.0e-3 .. 1.0e+24]).
	     */
4464
4465
4466
4467
4468
4469
4470
4471

4472
4473
4474
4475
4476
4477
4478
4552
4553
4554
4555
4556
4557
4558

4559
4560
4561
4562
4563
4564
4565
4566







-
+








	if (b2 >= s2 && s2 > 0) {
	    b2 -= s2; s2 = 0;
	} else if (s2 >= b2 && b2 > 0) {
	    s2 -= b2; b2 = 0;
	}

	if (s5+1 < N_LOG2POW5 && s2+1 + log2pow5[s5+1] <= 64) {
	if (s5+1 < N_LOG2POW5 && s2+1 + log2pow5[s5+1] < 64) {
	    /*
	     * If 10*2**s2*5**s5 == 2**(s2+1)+5**(s5+1) fits in a 64-bit word,
	     * then all our intermediate calculations can be done using exact
	     * 64-bit arithmetic with no need for expensive multiprecision
	     * operations.
	     */

4705
4706
4707
4708
4709
4710
4711
4712

4713
4714
4715
4716
4717

4718
4719
4720
4721
4722
4723
4724
4725
4726
4727

4728
4729
4730
4731
4732

4733
4734
4735
4736
4737
4738
4739
4793
4794
4795
4796
4797
4798
4799

4800
4801
4802
4803
4804

4805
4806
4807
4808
4809
4810
4811
4812
4813
4814

4815
4816
4817
4818
4819

4820
4821
4822
4823
4824
4825
4826
4827







-
+




-
+









-
+




-
+







    mp_err err;
    mp_int *b = (mp_int *)big;

    /*
     * Infinite values can't convert to bignum.
     */

    if (TclIsInfinite(d)) {
    if (isinf(d)) {
	if (interp != NULL) {
	    const char *s = "integer value too large to represent";

	    Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
	    Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL);
	    Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *)NULL);
	}
	return TCL_ERROR;
    }

    fract = frexp(d, &expt);
    if (expt <= 0) {
	err = mp_init(b);
	mp_zero(b);
    } else {
	Tcl_WideInt w = (Tcl_WideInt) ldexp(fract, mantBits);
	Tcl_WideInt w = (Tcl_WideInt)ldexp(fract, mantBits);
	int shift = expt - mantBits;

	err = mp_init_i64(b, w);
	if (err != MP_OKAY) {
		/* just skip */
	    /* just skip */
	} else if (shift < 0) {
	    err = mp_div_2d(b, -shift, b, NULL);
	} else if (shift > 0) {
	    err = mp_mul_2d(b, shift, b);
	}
    }
    if (err != MP_OKAY) {
4755
4756
4757
4758
4759
4760
4761
4762

4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4843
4844
4845
4846
4847
4848
4849

4850
4851
4852
4853
4854
4855
4856

4857
4858
4859
4860
4861
4862
4863







-
+






-







 *	too large to convert.
 *
 *----------------------------------------------------------------------
 */

double
TclBignumToDouble(
    const void *big)			/* Integer to convert. */
    const void *big)		/* Integer to convert. */
{
    mp_int b;
    int bits, shift, i, lsb;
    double r;
    mp_err err;
    const mp_int *a = (const mp_int *)big;


    /*
     * We need a 'mantBits'-bit significand.  Determine what shift will
     * give us that.
     */

    bits = mp_count_bits(a);
4877
4878
4879
4880
4881
4882
4883
4884

4885
4886
4887
4888
4889
4890
4891
4964
4965
4966
4967
4968
4969
4970

4971
4972
4973
4974
4975
4976
4977
4978







-
+







 *	Returns the floating point number.
 *
 *----------------------------------------------------------------------
 */

double
TclCeil(
    const void *big)			/* Integer to convert. */
    const void *big)		/* Integer to convert. */
{
    double r = 0.0;
    mp_int b;
    mp_err err;
    const mp_int *a = (const mp_int *)big;

    err = mp_init(&b);
4943
4944
4945
4946
4947
4948
4949
4950

4951
4952
4953
4954
4955
4956
4957
5030
5031
5032
5033
5034
5035
5036

5037
5038
5039
5040
5041
5042
5043
5044







-
+







 *	Returns the floating point value.
 *
 *----------------------------------------------------------------------
 */

double
TclFloor(
    const void *big)			/* Integer to convert. */
    const void *big)		/* Integer to convert. */
{
    double r = 0.0;
    mp_int b;
    mp_err err;
    const mp_int *a = (const mp_int *)big;

    err = mp_init(&b);
5179
5180
5181
5182
5183
5184
5185
5186

5187
5188
5189
5190
5191
5192
5193
5194


5195
5196
5197
5198
5199
5200

5201
5202

5203
5204
5205
5206
5207
5208
5209
5266
5267
5268
5269
5270
5271
5272

5273
5274
5275
5276
5277
5278
5279


5280
5281
5282
5283
5284
5285
5286

5287
5288

5289
5290
5291
5292
5293
5294
5295
5296







-
+






-
-
+
+





-
+

-
+







{
#ifndef IEEE_FLOATING_POINT
    strcpy(buffer, "NaN");
    return;
#else
    union {
	double dv;
	Tcl_WideUInt iv;
	uint64_t iv;
    } bitwhack;

    bitwhack.dv = value;
    if (n770_fp) {
	bitwhack.iv = Nokia770Twiddle(bitwhack.iv);
    }
    if (bitwhack.iv & ((Tcl_WideUInt) 1 << 63)) {
	bitwhack.iv &= ~ ((Tcl_WideUInt) 1 << 63);
    if (bitwhack.iv & (UINT64_C(1) << 63)) {
	bitwhack.iv &= ~ (UINT64_C(1) << 63);
	*buffer++ = '-';
    }
    *buffer++ = 'N';
    *buffer++ = 'a';
    *buffer++ = 'N';
    bitwhack.iv &= (((Tcl_WideUInt) 1) << 51) - 1;
    bitwhack.iv &= ((UINT64_C(1)) << 51) - 1;
    if (bitwhack.iv != 0) {
	sprintf(buffer, "(%" TCL_LL_MODIFIER "x)", bitwhack.iv);
	snprintf(buffer, TCL_DOUBLE_SPACE, "(%" PRIx64 ")", bitwhack.iv);
    } else {
	*buffer = '\0';
    }
#endif /* IEEE_FLOATING_POINT */
}

/*

Changes to generic/tclStringObj.c.

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
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
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
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




-
-
-
+
+
+

-
-
-
+
+
+
-
-
-
+
+

-
-
+
+


-
-
+
+



-
-
+



-
-
+
+








-
-
+







-
+

-
+

-
+

-
+


-
-
+
+

-
-
+
+


-
-
+
+


-
-
+
+

+
+
+











-
+
+







/*
 * tclStringObj.c --
 *
 *	This file contains functions that implement string operations on Tcl
 *	objects. Some string operations work with UTF strings and others
 *	require Unicode format. Functions that require knowledge of the width
 *	of each character, such as indexing, operate on Unicode data.
 *	objects. Some string operations work with UTF-8 encoding forms.
 *	Functions that require knowledge of the width of each character,
 *	such as indexing, operate on fixed width encoding forms such as UTF-32.
 *
 *	A Unicode string is an internationalized string. Conceptually, a
 *	Unicode string is an array of 16-bit quantities organized as a
 *	sequence of properly formed UTF-8 characters. There is a one-to-one
 *	Conceptually, a string is a sequence of Unicode code points. Internally
 *	it may be stored in an encoding form such as a modified version of
 *	UTF-8 or UTF-32.
 *	map between Unicode and UTF characters. Because Unicode characters
 *	have a fixed width, operations such as indexing operate on Unicode
 *	data. The String object is optimized for the case where each UTF char
 *
 *	The String object is optimized for the case where each UTF char
 *	in a string is only one byte. In this case, we store the value of
 *	numChars, but we don't store the Unicode data (unless Tcl_GetUnicode
 *	is explicitly called).
 *	numChars, but we don't store the fixed form encoding (unless
 *	Tcl_GetUnicode is explicitly called).
 *
 *	The String object type stores one or both formats. The default
 *	behavior is to store UTF. Once Unicode is calculated by a function, it
 *	is stored in the internal rep for future access (without an additional
 *	behavior is to store UTF-8. Once UTF-16/UTF32 is calculated, it is
 *	stored in the internal rep for future access (without an additional
 *	O(n) cost).
 *
 *	To allow many appends to be done to an object without constantly
 *	reallocating the space for the string or Unicode representation, we
 *	allocate double the space for the string or Unicode and use the
 *	reallocating space, we allocate double the space and use the
 *	internal representation to keep track of how much space is used vs.
 *	allocated.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1999 by Scriptics Corporation.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1999 Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclTomMath.h"
#include "tclStringRep.h"

#include "assert.h"
#include <assert.h>
/*
 * Prototypes for functions defined later in this file:
 */

static void		AppendPrintfToObjVA(Tcl_Obj *objPtr,
			    const char *format, va_list argList);
static void		AppendUnicodeToUnicodeRep(Tcl_Obj *objPtr,
			    const Tcl_UniChar *unicode, size_t appendNumChars);
			    const Tcl_UniChar *unicode, Tcl_Size appendNumChars);
static void		AppendUnicodeToUtfRep(Tcl_Obj *objPtr,
			    const Tcl_UniChar *unicode, size_t numChars);
			    const Tcl_UniChar *unicode, Tcl_Size numChars);
static void		AppendUtfToUnicodeRep(Tcl_Obj *objPtr,
			    const char *bytes, size_t numBytes);
			    const char *bytes, Tcl_Size numBytes);
static void		AppendUtfToUtfRep(Tcl_Obj *objPtr,
			    const char *bytes, size_t numBytes);
			    const char *bytes, Tcl_Size numBytes);
static void		DupStringInternalRep(Tcl_Obj *objPtr,
			    Tcl_Obj *copyPtr);
static size_t		ExtendStringRepWithUnicode(Tcl_Obj *objPtr,
			    const Tcl_UniChar *unicode, size_t numChars);
static Tcl_Size		ExtendStringRepWithUnicode(Tcl_Obj *objPtr,
			    const Tcl_UniChar *unicode, Tcl_Size numChars);
static void		ExtendUnicodeRepWithString(Tcl_Obj *objPtr,
			    const char *bytes, size_t numBytes,
			    size_t numAppendChars);
			    const char *bytes, Tcl_Size numBytes,
			    Tcl_Size numAppendChars);
static void		FillUnicodeRep(Tcl_Obj *objPtr);
static void		FreeStringInternalRep(Tcl_Obj *objPtr);
static void		GrowStringBuffer(Tcl_Obj *objPtr, size_t needed, int flag);
static void		GrowUnicodeBuffer(Tcl_Obj *objPtr, size_t needed);
static void		GrowStringBuffer(Tcl_Obj *objPtr, Tcl_Size needed, int flag);
static void		GrowUnicodeBuffer(Tcl_Obj *objPtr, Tcl_Size needed);
static int		SetStringFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
static void		SetUnicodeObj(Tcl_Obj *objPtr,
			    const Tcl_UniChar *unicode, size_t numChars);
static size_t		UnicodeLength(const Tcl_UniChar *unicode);
			    const Tcl_UniChar *unicode, Tcl_Size numChars);
static Tcl_Size		UnicodeLength(const Tcl_UniChar *unicode);
static void		UpdateStringOfString(Tcl_Obj *objPtr);

#define ISCONTINUATION(bytes) (\
	((bytes)[0] & 0xC0) == 0x80)

/*
 * The structure below defines the string Tcl object type by means of
 * functions that can be invoked by generic object code.
 */

const Tcl_ObjType tclStringType = {
    "string",			/* name */
    FreeStringInternalRep,	/* freeIntRepPro */
    DupStringInternalRep,	/* dupIntRepProc */
    UpdateStringOfString,	/* updateStringProc */
    SetStringFromAny		/* setFromAnyProc */
    SetStringFromAny,		/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

/*
 * TCL STRING GROWTH ALGORITHM
 *
 * When growing strings (during an append, for example), the following growth
 * algorithm is used:
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
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







-
-
+
+


-
-
+
+





-
-
+
+
+
+
+




-
-
-
-
-
+
-
-
-
-
-
+
+
+
+
+
-
-
-
+
-
-
+
+
-
-
-
+
-
-
-
-
+
-
-
-
+

-
+





-
+


-
-
+
+



-
-
+
+

-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
+
+
+
-
-

-
+
+

-
-
+
+
-

-
-
+




















-
+













-
+

-
+









-
+





-
+







#ifndef TCL_MIN_UNICHAR_GROWTH
#define TCL_MIN_UNICHAR_GROWTH	TCL_MIN_GROWTH/sizeof(Tcl_UniChar)
#endif

static void
GrowStringBuffer(
    Tcl_Obj *objPtr,
    size_t needed,
    int flag)
    Tcl_Size needed,		/* Not including terminating nul */
    int flag)			/* If 0, try to overallocate */
{
    /*
     * Pre-conditions:
     *	objPtr->typePtr == &tclStringType
     * Preconditions:
     *	TclHasInternalRep(objPtr, &tclStringType)
     *	needed > stringPtr->allocated
     *	flag || objPtr->bytes != NULL
     */

    String *stringPtr = GET_STRING(objPtr);
    char *ptr = NULL;
    size_t attempt;
    char *ptr;
    Tcl_Size capacity;

    assert(needed <= TCL_SIZE_MAX - 1);
    needed += 1; /* Include terminating nul */

    if (objPtr->bytes == &tclEmptyString) {
	objPtr->bytes = NULL;
    }
    if (flag == 0 || stringPtr->allocated > 0) {
	attempt = 2 * needed;
	ptr = (char *)Tcl_AttemptRealloc(objPtr->bytes, attempt + 1);
	if (ptr == NULL) {
	    /*
    /*
	     * Take care computing the amount of modest growth to avoid
	     * overflow into invalid argument values for attempt.
	     */

	    size_t limit = INT_MAX - needed;
     * In code below, note 'capacity' and 'needed' include terminating nul,
     * while stringPtr->allocated does not.
     */
    if (flag == 0 || stringPtr->allocated > 0) {
	ptr = (char *)TclReallocEx(objPtr->bytes, needed, &capacity);
	    size_t extra = needed - objPtr->length + TCL_MIN_GROWTH;
	    size_t growth = (extra > limit) ? limit : extra;

    } else {
	    attempt = needed + growth;
	    ptr = (char *)Tcl_AttemptRealloc(objPtr->bytes, attempt + 1);
	/* Allocate exact size */
	ptr = (char *)Tcl_Realloc(objPtr->bytes, needed);
	}
    }
    if (ptr == NULL) {
	capacity = needed;
	/*
	 * First allocation - just big enough; or last chance fallback.
	 */

    }
	attempt = needed;
	ptr = (char *)Tcl_Realloc(objPtr->bytes, attempt + 1);
    }

    objPtr->bytes = ptr;
    stringPtr->allocated = attempt;
    stringPtr->allocated = capacity - 1; /* Does not include slot for end nul */
}

static void
GrowUnicodeBuffer(
    Tcl_Obj *objPtr,
    size_t needed)
    Tcl_Size needed)
{
    /*
     * Pre-conditions:
     *	objPtr->typePtr == &tclStringType
     * Preconditions:
     *	TclHasInternalRep(objPtr, &tclStringType)
     *	needed > stringPtr->maxChars
     */

    String *ptr = NULL, *stringPtr = GET_STRING(objPtr);
    size_t attempt;
    String *stringPtr = GET_STRING(objPtr);
    Tcl_Size maxChars;

    if (stringPtr->maxChars > 0) {
	/*
	 * Subsequent appends - apply the growth algorithm.
	 */

	attempt = 2 * needed;
    /* Note STRING_MAXCHARS already takes into account space for nul */
    if (needed > STRING_MAXCHARS) {
	ptr = stringAttemptRealloc(stringPtr, attempt);
	if (ptr == NULL) {
	    /*
	     * Take care computing the amount of modest growth to avoid
	     * overflow into invalid argument values for attempt.
	     */

	    size_t extra = needed - stringPtr->numChars
	Tcl_Panic("max size for a Tcl unicode rep (%" TCL_Z_MODIFIER "d bytes) exceeded",
		  STRING_MAXCHARS);
    }
    if (stringPtr->maxChars > 0) {
		    + TCL_MIN_UNICHAR_GROWTH;

	    attempt = needed + extra;
	/* Expansion - try allocating extra space */
	stringPtr = (String *) TclReallocElemsEx(stringPtr,
		needed + 1, /* +1 for nul */
	    ptr = stringAttemptRealloc(stringPtr, attempt);
	}
		sizeof(Tcl_UniChar), offsetof(String, unicode), &maxChars);
	maxChars -= 1; /* End nul not included */
    } else {
    }
    if (ptr == NULL) {
	/*
	 * First allocation - just big enough; or last chance fallback.
	 * First allocation - just big enough. Note needed does
	 * not include terminating nul but STRING_SIZE does
	 */

	attempt = needed;
	stringPtr = (String *)Tcl_Realloc(stringPtr, STRING_SIZE(needed));
	maxChars = needed;
	ptr = stringRealloc(stringPtr, attempt);
    }
    stringPtr = ptr;
    stringPtr->maxChars = attempt;
    stringPtr->maxChars = maxChars;
    SET_STRING(objPtr, stringPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_NewStringObj --
 *
 *	This function is normally called when not debugging: i.e., when
 *	TCL_MEM_DEBUG is not defined. It creates a new string object and
 *	initializes it from the byte pointer and length arguments.
 *
 *	When TCL_MEM_DEBUG is defined, this function just returns the result
 *	of calling the debugging version Tcl_DbNewStringObj.
 *
 * Results:
 *	A newly created string object is returned that has ref count zero.
 *
 * Side effects:
 *	The new object's internal string representation will be set to a copy
 *	of the length bytes starting at "bytes". If "length" is negative, use
 *	of the length bytes starting at "bytes". If "length" is TCL_INDEX_NONE, use
 *	bytes up to the first NUL byte; i.e., assume "bytes" points to a
 *	C-style NUL-terminated string. The object's type is set to NULL. An
 *	extra NUL is added to the end of the new object's byte array.
 *
 *----------------------------------------------------------------------
 */

#ifdef TCL_MEM_DEBUG
#undef Tcl_NewStringObj
Tcl_Obj *
Tcl_NewStringObj(
    const char *bytes,		/* Points to the first of the length bytes
				 * used to initialize the new object. */
    size_t length)			/* The number of bytes to copy from "bytes"
    Tcl_Size length)		/* The number of bytes to copy from "bytes"
				 * when initializing the new object. If
				 * negative, use bytes up to the first NUL
				 * 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. */
    size_t length)		/* The number of bytes to copy from "bytes"
    Tcl_Size length)		/* The number of bytes to copy from "bytes"
				 * when initializing the new object. If -1,
				 * use bytes up to the first NUL byte. */
{
    Tcl_Obj *objPtr;

    if (length == TCL_INDEX_NONE) {
    if (length < 0) {
	length = (bytes? strlen(bytes) : 0);
    }
    TclNewStringObj(objPtr, bytes, length);
    return objPtr;
}
#endif /* TCL_MEM_DEBUG */

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
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







-
+












-
+







 *	result of calling Tcl_NewStringObj.
 *
 * Results:
 *	A newly created string object is returned that has ref count zero.
 *
 * Side effects:
 *	The new object's internal string representation will be set to a copy
 *	of the length bytes starting at "bytes". If "length" is negative, use
 *	of the length bytes starting at "bytes". If "length" is TCL_INDEX_NONE, use
 *	bytes up to the first NUL byte; i.e., assume "bytes" points to a
 *	C-style NUL-terminated string. The object's type is set to NULL. An
 *	extra NUL is added to the end of the new object's byte array.
 *
 *----------------------------------------------------------------------
 */

#ifdef TCL_MEM_DEBUG
Tcl_Obj *
Tcl_DbNewStringObj(
    const char *bytes,		/* Points to the first of the length bytes
				 * used to initialize the new object. */
    size_t length,		/* The number of bytes to copy from "bytes"
    Tcl_Size length,		/* The number of bytes to copy from "bytes"
				 * when initializing the new object. If -1,
				 * use bytes up to the first NUL byte. */
    const char *file,		/* The name of the source file calling this
				 * function; used for debugging. */
    int line)			/* Line number in the source file; used for
				 * debugging. */
{
325
326
327
328
329
330
331
332

333
334
335
336
337
338
339
306
307
308
309
310
311
312

313
314
315
316
317
318
319
320







-
+







    return objPtr;
}
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
Tcl_DbNewStringObj(
    const char *bytes,		/* Points to the first of the length bytes
				 * used to initialize the new object. */
    size_t length,		/* The number of bytes to copy from "bytes"
    Tcl_Size length,		/* The number of bytes to copy from "bytes"
				 * when initializing the new object. If -1,
				 * use bytes up to the first NUL byte. */
    TCL_UNUSED(const char *) /*file*/,
    TCL_UNUSED(int) /*line*/)
{
    return Tcl_NewStringObj(bytes, length);
}
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
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







-
+

















-
+








-
+





-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







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

Tcl_Obj *
Tcl_NewUnicodeObj(
    const Tcl_UniChar *unicode,	/* The unicode string used to initialize the
				 * new object. */
    size_t numChars)		/* Number of characters in the unicode
    Tcl_Size numChars)		/* Number of characters in the unicode
				 * string. */
{
    Tcl_Obj *objPtr;

    TclNewObj(objPtr);
    SetUnicodeObj(objPtr, unicode, numChars);
    return objPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetCharLength --
 *
 *	Get the length of the Unicode string from the Tcl object.
 *
 * Results:
 *	Pointer to unicode string representing the unicode object.
 *	Pointer to Unicode string representing the Unicode object.
 *
 * Side effects:
 *	Frees old internal rep. Allocates memory for new "String" internal
 *	rep.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
Tcl_GetCharLength(
    Tcl_Obj *objPtr)		/* The String object to get the num chars
				 * of. */
{
    String *stringPtr;
    size_t numChars = 0;
    Tcl_Size numChars = 0;

    /*
     * Quick, no-shimmer return for short string reps.
     */

    if ((objPtr->bytes) && (objPtr->length < 2)) {
	/* 0 bytes -> 0 chars; 1 byte -> 1 char */
	return objPtr->length;
    }

    /*
     * Optimize the case where we're really dealing with a bytearray 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" bytearray, because the
     * machinery behind that test is using a proper bytearray ObjType.  We
     * could also compute length of an improper bytearray without shimmering
     * but there's no value in that. We *want* to shimmer an improper bytearray
     * because improper bytearrays have worthless internal reps.
     */

    if (TclIsPureByteArray(objPtr)) {
	(void) Tcl_GetBytesFromObj(NULL, objPtr, &numChars);
	return numChars;
    }

    /*
     * OK, need to work with the object as a string.
     */

    SetStringFromAny(NULL, objPtr);
    stringPtr = GET_STRING(objPtr);
    numChars = stringPtr->numChars;

    /*
     * If numChars is unknown, compute it.
     */

    if (numChars < 0) {
	TclNumUtfCharsM(numChars, objPtr->bytes, objPtr->length);
	stringPtr->numChars = numChars;
    }
    return numChars;
}

Tcl_Size
TclGetCharLength(
    Tcl_Obj *objPtr)		/* The String object to get the num chars
				 * of. */
{
    Tcl_Size numChars = 0;

    /*
     * Quick, no-shimmer return for short string reps.
     */

    if ((objPtr->bytes) && (objPtr->length < 2)) {
	/* 0 bytes -> 0 chars; 1 byte -> 1 char */
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
467
468
469





470
471

472
473
474
475
476
477
478
446
447
448
449
450
451
452




453




454


455


456




457




458
459
460

461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481

482
483
484
485
486
487
488
489
490
491
492
493

494
495
496
497
498
499
500
501







-
-
-
-
+
-
-
-
-
+
-
-
+
-
-
+
-
-
-
-
+
-
-
-
-
+


-
+




















-
+





+
+
+
+
+

-
+







     * machinery behind that test is using a proper bytearray ObjType.  We
     * could also compute length of an improper bytearray without shimmering
     * but there's no value in that. We *want* to shimmer an improper bytearray
     * because improper bytearrays have worthless internal reps.
     */

    if (TclIsPureByteArray(objPtr)) {
	(void) TclGetByteArrayFromObj(objPtr, &numChars);
	return numChars;
    }

	(void) Tcl_GetBytesFromObj(NULL, objPtr, &numChars);
    /*
     * OK, need to work with the object as a string.
     */

    } else {
    SetStringFromAny(NULL, objPtr);
    stringPtr = GET_STRING(objPtr);
	TclGetString(objPtr);
    numChars = stringPtr->numChars;

	numChars = TclNumUtfChars(objPtr->bytes, objPtr->length);
    /*
     * If numChars is unknown, compute it.
     */

    }
    if (numChars == TCL_INDEX_NONE) {
	TclNumUtfChars(numChars, objPtr->bytes, objPtr->length);
	stringPtr->numChars = numChars;
    }

    return numChars;
}


/*
 *----------------------------------------------------------------------
 *
 * TclCheckEmptyString --
 *
 *	Determine whether the string value of an object is or would be the
 *	empty string, without generating a string representation.
 *
 * Results:
 *	Returns 1 if empty, 0 if not, and -1 if unknown.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
int
TclCheckEmptyString(
    Tcl_Obj *objPtr)
{
    int length = -1;
    Tcl_Size length = TCL_INDEX_NONE;

    if (objPtr->bytes == &tclEmptyString) {
	return TCL_EMPTYSTRING_YES;
    }

    if (TclIsPureByteArray(objPtr)
	    && Tcl_GetCharLength(objPtr) == 0) {
	return TCL_EMPTYSTRING_YES;
    }

    if (TclListObjIsCanonical(objPtr)) {
	Tcl_ListObjLength(NULL, objPtr, &length);
	TclListObjLength(NULL, objPtr, &length);
	return length == 0;
    }

    if (TclIsPureDict(objPtr)) {
	Tcl_DictObjSize(NULL, objPtr, &length);
	return length == 0;
    }
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
558










559
560
561
562
563
564
565
566
567
568
569

























570
571
572
573
574
575
576

577
578
579
580
581
582
583
584
585
586
587
588
589
590
591


592





























593
594
595
596

597
598
599
600
601
602
603
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
558
559
560
561
562
563
564
565
566
567

568
569
570
571
572
573

574
575
576
577
578
579
580
581
582
583
584
585





586
587
588
589
590
591
592
593
594
595











596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626

627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677

678
679
680
681
682
683
684
685







-
+




+
+
+
+

-
+




-
-
+
+




















-
+

+
+
+

-
+









+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+















+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+







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

int
Tcl_GetUniChar(
    Tcl_Obj *objPtr,		/* The object to get the Unicode charater
				 * from. */
    size_t index)		/* Get the index'th Unicode character. */
    Tcl_Size index)		/* Get the index'th Unicode character. */
{
    String *stringPtr;
    int ch;

    if (index < 0) {
	return -1;
    }

    /*
     * Optimize the case where we're really dealing with a bytearray object
     * Optimize the case where we're really dealing with a ByteArray object
     * we don't need to convert to a string to perform the indexing operation.
     */

    if (TclIsPureByteArray(objPtr)) {
	size_t length = 0;
	unsigned char *bytes = TclGetByteArrayFromObj(objPtr, &length);
	Tcl_Size length = 0;
	unsigned char *bytes = Tcl_GetBytesFromObj(NULL, objPtr, &length);
	if (index >= length) {
		return -1;
	}

	return bytes[index];
    }

    /*
     * OK, need to work with the object as a string.
     */

    SetStringFromAny(NULL, objPtr);
    stringPtr = GET_STRING(objPtr);

    if (stringPtr->hasUnicode == 0) {
	/*
	 * If numChars is unknown, compute it.
	 */

	if (stringPtr->numChars == TCL_INDEX_NONE) {
	    TclNumUtfChars(stringPtr->numChars, objPtr->bytes, objPtr->length);
	    TclNumUtfCharsM(stringPtr->numChars, objPtr->bytes, objPtr->length);
	}
	if (index >= stringPtr->numChars) {
	    return -1;
	}
	if (stringPtr->numChars == objPtr->length) {
	    return (Tcl_UniChar) objPtr->bytes[index];
	    return (unsigned char) objPtr->bytes[index];
	}
	FillUnicodeRep(objPtr);
	stringPtr = GET_STRING(objPtr);
    }

    if (index >= stringPtr->numChars) {
	return -1;
    }
    ch = stringPtr->unicode[index];
    return ch;
}
#if TCL_UTF_MAX <= 3
    /* See: bug [11ae2be95dac9417] */
    if ((ch & 0xF800) == 0xD800) {
	if (ch & 0x400) {
	    if ((index > 0)

int
TclGetUniChar(
    Tcl_Obj *objPtr,		/* The object to get the Unicode character
				 * from. */
    Tcl_Size index)		/* Get the index'th Unicode character. */
{
    int ch = 0;

    if (index < 0) {
		    && ((stringPtr->unicode[index-1] & 0xFC00) == 0xD800)) {
		ch = -1; /* low surrogate preceded by high surrogate */
	    }
	} else if ((++index < stringPtr->numChars)
		&& ((stringPtr->unicode[index] & 0xFC00) == 0xDC00)) {
	    /* high surrogate followed by low surrogate */
	    ch = (((ch & 0x3FF) << 10) |
			(stringPtr->unicode[index] & 0x3FF)) + 0x10000;
	}
    }
#endif
	return -1;
    }

    /*
     * Optimize the ByteArray case: no need to convert to a string to
     * perform the indexing operation.
     */

    if (TclIsPureByteArray(objPtr)) {
	Tcl_Size length = 0;
	unsigned char *bytes = Tcl_GetBytesFromObj(NULL, objPtr, &length);
	if (index >= length) {
	    return -1;
	}

	return bytes[index];
    }

    Tcl_Size numChars = TclNumUtfChars(objPtr->bytes, objPtr->length);

    if (index >= numChars) {
	return -1;
    }
    const char *begin = TclUtfAtIndex(objPtr->bytes, index);
    TclUtfToUniChar(begin, &ch);
    return ch;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetUnicodeFromObj --
 * Tcl_GetUnicodeFromObj/TclGetUnicodeFromObj --
 *
 *	Get the Unicode form of the String object with length. If the object
 *	is not already a String object, it will be converted to one. If the
 *	String object does not have a Unicode rep, then one is create from the
 *	UTF string format.
 *
 * Results:
 *	Returns a pointer to the object's internal Unicode string.
 *
 * Side effects:
 *	Converts the object to have the String internal rep.
 *
 *----------------------------------------------------------------------
 */

#undef Tcl_GetUnicodeFromObj
#if !defined(TCL_NO_DEPRECATED)
Tcl_UniChar *
TclGetUnicodeFromObj(
    Tcl_Obj *objPtr,		/* The object to find the Unicode string
				 * for. */
    void *lengthPtr)		/* If non-NULL, the location where the string
				 * rep's Tcl_UniChar length should be stored. If
				 * NULL, no length is stored. */
{
    String *stringPtr;

    SetStringFromAny(NULL, objPtr);
    stringPtr = GET_STRING(objPtr);

    if (stringPtr->hasUnicode == 0) {
	FillUnicodeRep(objPtr);
	stringPtr = GET_STRING(objPtr);
    }

    if (lengthPtr != NULL) {
	if (stringPtr->numChars > INT_MAX) {
	    Tcl_Panic("Tcl_GetUnicodeFromObj with 'int' lengthPtr"
		    " cannot handle such long strings. Please use 'Tcl_Size'");
	}
	*(int *)lengthPtr = (int)stringPtr->numChars;
    }
    return stringPtr->unicode;
}
#endif /* !defined(TCL_NO_DEPRECATED) */

Tcl_UniChar *
Tcl_GetUnicodeFromObj(
    Tcl_Obj *objPtr,		/* The object to find the unicode string
				 * for. */
    int *lengthPtr)		/* If non-NULL, the location where the string
    Tcl_Size *lengthPtr)	/* If non-NULL, the location where the string
				 * rep's unichar length should be stored. If
				 * NULL, no length is stored. */
{
    String *stringPtr;

    SetStringFromAny(NULL, objPtr);
    stringPtr = GET_STRING(objPtr);
616
617
618
619
620
621
622
623
624



625
626
627
628
629
630
631
632
633
634
635
636
637
638
639


640
641
642
643

644
645
646


647
648
649
650
651
652
653
654
655
656
657
658

659
660

661
662
663

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


707
708



709
710
711
712
713
714
715
716
717
718
719
720






































721
722
723







724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739

740
741
742
743
744
745
746
747
748
749
750
751
752

753
754
755
756
757
758
759
760
761
762
763
764

765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783

784
785
786
787
788
789
790
791
792
793
794





795
796


797
798
799
800
801
802
803
804
805

806
807
808
809
810




811
812
813
814
815
816
817
698
699
700
701
702
703
704


705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720


721
722
723
724
725

726
727


728
729



730
731
732
733
734
735
736
737

738
739

740
741
742
743
744

745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762

763
764
765

766
767
768
769
770

771
772

773
774
775
776
777
778
779
780
781
782
783
784
785
786


787
788
789
790
791
792
793












794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832


833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854

855
856
857
858
859
860
861
862
863
864
865
866
867

868
869
870
871
872
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
898

899

900
901
902
903
904





905
906
907
908
909


910
911
912
913
914
915
916
917
918
919

920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936







-
-
+
+
+













-
-
+
+



-
+

-
-
+
+
-
-
-








-
+

-
+



+
-
+

















-
+


-
+



+
-
+

-
+













-
-
+
+


+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+
+
+
+
+















-
+












-
+











-
+


















-
+
-





-
-
-
-
-
+
+
+
+
+
-
-
+
+








-
+





+
+
+
+







/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetRange --
 *
 *	Create a Tcl Object that contains the chars between first and last of
 *	the object indicated by "objPtr". If the object is not already a
 *	String object, convert it to one. The first and last indices are
 *	assumed to be in the appropriate range.
 *	String object, convert it to one.  If first is TCL_INDEX_NONE, the
 *	returned string start at the beginning of objPtr.  If last is
 *	TCL_INDEX_NONE, the returned string ends at the end of objPtr.
 *
 * Results:
 *	Returns a new Tcl Object of the String type.
 *
 * Side effects:
 *	Changes the internal rep of "objPtr" to the String type.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
Tcl_GetRange(
    Tcl_Obj *objPtr,		/* The Tcl object to find the range of. */
    size_t first,			/* First index of the range. */
    size_t last)			/* Last index of the range. */
    Tcl_Size first,		/* First index of the range. */
    Tcl_Size last)		/* Last index of the range. */
{
    Tcl_Obj *newObjPtr;		/* The Tcl object to find the range of. */
    String *stringPtr;
    size_t length = 0;
    Tcl_Size length = 0;

    if (first == TCL_INDEX_NONE) {
	first = TCL_INDEX_START;
    if (first < 0) {
	first = 0;
    }
    if (last + 2 <= first + 1) {
	return Tcl_NewObj();
    }

    /*
     * Optimize the case where we're really dealing with a bytearray object
     * we don't need to convert to a string to perform the substring operation.
     */

    if (TclIsPureByteArray(objPtr)) {
	unsigned char *bytes = TclGetByteArrayFromObj(objPtr, &length);
	unsigned char *bytes = Tcl_GetBytesFromObj(NULL, objPtr, &length);

	if (last >= length) {
	if (last < 0 || last >= length) {
	    last = length - 1;
	}
	if (last < first) {
	    TclNewObj(newObjPtr);
	    return Tcl_NewObj();
	    return newObjPtr;
	}
	return Tcl_NewByteArrayObj(bytes + first, last - first + 1);
    }

    /*
     * OK, need to work with the object as a string.
     */

    SetStringFromAny(NULL, objPtr);
    stringPtr = GET_STRING(objPtr);

    if (stringPtr->hasUnicode == 0) {
	/*
	 * If numChars is unknown, compute it.
	 */

	if (stringPtr->numChars == TCL_INDEX_NONE) {
	    TclNumUtfChars(stringPtr->numChars, objPtr->bytes, objPtr->length);
	    TclNumUtfCharsM(stringPtr->numChars, objPtr->bytes, objPtr->length);
	}
	if (stringPtr->numChars == objPtr->length) {
	    if (last >= stringPtr->numChars) {
	    if (last < 0 || last >= stringPtr->numChars) {
		last = stringPtr->numChars - 1;
	    }
	    if (last < first) {
		TclNewObj(newObjPtr);
		return Tcl_NewObj();
		return newObjPtr;
	    }
	    newObjPtr = Tcl_NewStringObj(objPtr->bytes + first, last-first+1);
	    newObjPtr = Tcl_NewStringObj(objPtr->bytes + first, last - first + 1);

	    /*
	     * Since we know the char length of the result, store it.
	     */

	    SetStringFromAny(NULL, newObjPtr);
	    stringPtr = GET_STRING(newObjPtr);
	    stringPtr->numChars = newObjPtr->length;
	    return newObjPtr;
	}
	FillUnicodeRep(objPtr);
	stringPtr = GET_STRING(objPtr);
    }
    if (last > stringPtr->numChars) {
	last = stringPtr->numChars;
    if (last < 0 || last >= stringPtr->numChars) {
	last = stringPtr->numChars - 1;
    }
    if (last < first) {
	TclNewObj(newObjPtr);
	return newObjPtr;
    }
	return Tcl_NewObj();
    }
#if TCL_UTF_MAX <= 3
    /* See: bug [11ae2be95dac9417] */
    if ((first + 1 > 1) && ((stringPtr->unicode[first] & 0xFC00) == 0xDC00)
	    && ((stringPtr->unicode[first-1] & 0xFC00) == 0xD800)) {
	++first;
    }
    if ((last + 2 < stringPtr->numChars + 1)
	    && ((stringPtr->unicode[last+1] & 0xFC00) == 0xDC00)
	    && ((stringPtr->unicode[last] & 0xFC00) == 0xD800)) {
	++last;
    return Tcl_NewUnicodeObj(stringPtr->unicode + first, last - first + 1);
}

Tcl_Obj *
TclGetRange(
    Tcl_Obj *objPtr,		/* The Tcl object to find the range of. */
    Tcl_Size first,		/* First index of the range. */
    Tcl_Size last)		/* Last index of the range. */
{
    Tcl_Obj *newObjPtr;		/* The Tcl object to find the range of. */
    Tcl_Size length = 0;

    if (first < 0) {
	first = TCL_INDEX_START;
    }

    /*
     * Optimize the case where we're really dealing with a bytearray object
     * we don't need to convert to a string to perform the substring operation.
     */

    if (TclIsPureByteArray(objPtr)) {
	unsigned char *bytes = Tcl_GetBytesFromObj(NULL, objPtr, &length);

	if (last < 0 || last >= length) {
	    last = length - 1;
	}
	if (last < first) {
	    TclNewObj(newObjPtr);
	    return newObjPtr;
	}
	return Tcl_NewByteArrayObj(bytes + first, last - first + 1);
    }

    Tcl_Size numChars = TclNumUtfChars(objPtr->bytes, objPtr->length);

    if (last < 0 || last >= numChars) {
	last = numChars - 1;
    }
#endif
    return Tcl_NewUnicodeObj(stringPtr->unicode + first, last - first + 1);
    if (last < first) {
	TclNewObj(newObjPtr);
	return newObjPtr;
    }
    const char *begin = TclUtfAtIndex(objPtr->bytes, first);
    const char *end = TclUtfAtIndex(objPtr->bytes, last + 1);
    return Tcl_NewStringObj(begin, end - begin);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetStringObj --
 *
 *	Modify an object to hold a string that is a copy of the bytes
 *	indicated by the byte pointer and length arguments.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The object's string representation will be set to a copy of the
 *	"length" bytes starting at "bytes". If "length" is negative, use bytes
 *	"length" bytes starting at "bytes". If "length" is TCL_INDEX_NONE, use bytes
 *	up to the first NUL byte; i.e., assume "bytes" points to a C-style
 *	NUL-terminated string. The object's old string and internal
 *	representations are freed and the object's type is set NULL.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetStringObj(
    Tcl_Obj *objPtr,		/* Object whose internal rep to init. */
    const char *bytes,		/* Points to the first of the length bytes
				 * used to initialize the object. */
    size_t length)		/* The number of bytes to copy from "bytes"
    Tcl_Size length)		/* The number of bytes to copy from "bytes"
				 * when initializing the object. If -1,
				 * use bytes up to the first NUL byte.*/
{
    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_SetStringObj");
    }

    /*
     * Set the type to NULL and free any internal rep for the old type.
     */

    TclFreeIntRep(objPtr);
    TclFreeInternalRep(objPtr);

    /*
     * Free any old string rep, then set the string rep to a copy of the
     * length bytes starting at "bytes".
     */

    TclInvalidateStringRep(objPtr);
    if (length == TCL_INDEX_NONE) {
	length = (bytes? strlen(bytes) : 0);
    }
    TclInitStringRep(objPtr, bytes, length);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetObjLength --
 *
 *	This function changes the length of the string representation of an
 *	Changes the length of the string representation of objPtr.
 *	object.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	If the size of objPtr's string representation is greater than length,
 *	then it is reduced to length and a new terminating null byte is stored
 *	in the strength. If the length of the string representation is greater
 *	than length, the storage space is reallocated to the given length; a
 *	null byte is stored at the end, but other bytes past the end of the
 *	If the size of objPtr's string representation is greater than length, a
 *	new terminating null byte is stored in objPtr->bytes at length, and
 *	bytes at positions past length have no meaning.  If the length of the
 *	string representation is greater than length, the storage space is
 *	reallocated to length+1.
 *	original string representation are undefined. The object's internal
 *	representation is changed to "expendable string".
 *
 *	The object's internal representation is changed to &tclStringType.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetObjLength(
    Tcl_Obj *objPtr,		/* Pointer to object. This object must not
				 * currently be shared. */
    size_t length)		/* Number of bytes desired for string
    Tcl_Size length)		/* Number of bytes desired for string
				 * representation of object, not including
				 * terminating null byte. */
{
    String *stringPtr;

    if (length < 0) {
	Tcl_Panic("Tcl_SetObjLength: length requested is negative: "
		"%" TCL_SIZE_MODIFIER "d (integer overflow?)", length);
    }
    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_SetObjLength");
    }

    if (objPtr->bytes && objPtr->length == length) {
	return;
    }
835
836
837
838
839
840
841
842

843
844
845
846
847
848
849
850
851
852
853
854
855

856
857
858
859
860
861
862
954
955
956
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







-
+












-
+







	    stringPtr->allocated = length;
	}

	objPtr->length = length;
	objPtr->bytes[length] = 0;

	/*
	 * Invalidate the unicode data.
	 * Invalidate the Unicode data.
	 */

	stringPtr->numChars = TCL_INDEX_NONE;
	stringPtr->hasUnicode = 0;
    } else {
	if (length > stringPtr->maxChars) {
	    stringPtr = stringRealloc(stringPtr, length);
	    SET_STRING(objPtr, stringPtr);
	    stringPtr->maxChars = length;
	}

	/*
	 * Mark the new end of the unicode string
	 * Mark the new end of the Unicode string
	 */

	stringPtr->numChars = length;
	stringPtr->unicode[length] = 0;
	stringPtr->hasUnicode = 1;

	/*
889
890
891
892
893
894
895
896

897
898
899
900





901
902
903
904
905
906
907
1008
1009
1010
1011
1012
1013
1014

1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031







-
+




+
+
+
+
+







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

int
Tcl_AttemptSetObjLength(
    Tcl_Obj *objPtr,		/* Pointer to object. This object must not
				 * currently be shared. */
    size_t length)		/* Number of bytes desired for string
    Tcl_Size length)		/* Number of bytes desired for string
				 * representation of object, not including
				 * terminating null byte. */
{
    String *stringPtr;

    if (length < 0) {
	/* Negative lengths => most likely integer overflow */
	return 0;
    }

    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_AttemptSetObjLength");
    }
    if (objPtr->bytes && objPtr->length == length) {
	return 1;
    }
917
918
919
920
921
922
923
924

925
926

927
928
929
930
931
932
933
934
935
936
937
938
939

940
941
942
943
944
945
946

947
948
949
950
951
952
953
954
955
956
957
958
959

960
961
962
963
964
965
966
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







-
+

-
+












-
+






-
+












-
+







	    /*
	     * Need to enlarge the buffer.
	     */

	    char *newBytes;

	    if (objPtr->bytes == &tclEmptyString) {
		newBytes = (char *)Tcl_AttemptAlloc(length + 1);
		newBytes = (char *)Tcl_AttemptAlloc(length + 1U);
	    } else {
		newBytes = (char *)Tcl_AttemptRealloc(objPtr->bytes, length + 1);
		newBytes = (char *)Tcl_AttemptRealloc(objPtr->bytes, length + 1U);
	    }
	    if (newBytes == NULL) {
		return 0;
	    }
	    objPtr->bytes = newBytes;
	    stringPtr->allocated = length;
	}

	objPtr->length = length;
	objPtr->bytes[length] = 0;

	/*
	 * Invalidate the unicode data.
	 * Invalidate the Unicode data.
	 */

	stringPtr->numChars = TCL_INDEX_NONE;
	stringPtr->hasUnicode = 0;
    } else {
	/*
	 * Changing length of pure unicode string.
	 * Changing length of pure Unicode string.
	 */

	if (length > stringPtr->maxChars) {
	    stringPtr = stringAttemptRealloc(stringPtr, length);
	    if (stringPtr == NULL) {
		return 0;
	    }
	    SET_STRING(objPtr, stringPtr);
	    stringPtr->maxChars = length;
	}

	/*
	 * Mark the new end of the unicode string.
	 * Mark the new end of the Unicode string.
	 */

	stringPtr->unicode[length] = 0;
	stringPtr->numChars = length;
	stringPtr->hasUnicode = 1;

	/*
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
1024

1025
1026
1027
1028
1029

1030
1031
1032
1033
1034
1035
1036
1110
1111
1112
1113
1114
1115
1116

1117
1118

1119
1120
1121
1122
1123
1124

1125
1126
1127
1128

1129
1130
1131
1132

1133
1134
1135
1136

1137
1138
1139
1140
1141
1142
1143
1144
1145
1146

1147
1148

1149
1150
1151
1152
1153

1154
1155
1156
1157
1158
1159
1160
1161







-
+

-
+





-
+



-
+



-
+


+
-
+









-
+

-
+




-
+







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

void
Tcl_SetUnicodeObj(
    Tcl_Obj *objPtr,		/* The object to set the string of. */
    const Tcl_UniChar *unicode,	/* The unicode string used to initialize the
    const Tcl_UniChar *unicode,	/* The Unicode string used to initialize the
				 * object. */
    size_t numChars)		/* Number of characters in the unicode
    Tcl_Size numChars)		/* Number of characters in the Unicode
				 * string. */
{
    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_SetUnicodeObj");
    }
    TclFreeIntRep(objPtr);
    TclFreeInternalRep(objPtr);
    SetUnicodeObj(objPtr, unicode, numChars);
}

static size_t
static Tcl_Size
UnicodeLength(
    const Tcl_UniChar *unicode)
{
    size_t numChars = 0;
    Tcl_Size numChars = 0;

    if (unicode) {
	/* TODO - is this overflow check really necessary? */
	while ((numChars != TCL_INDEX_NONE) && (unicode[numChars] != 0)) {
	while ((numChars >= 0) && (unicode[numChars] != 0)) {
	    numChars++;
	}
    }
    return numChars;
}

static void
SetUnicodeObj(
    Tcl_Obj *objPtr,		/* The object to set the string of. */
    const Tcl_UniChar *unicode,	/* The unicode string used to initialize the
    const Tcl_UniChar *unicode,	/* The Unicode string used to initialize the
				 * object. */
    size_t numChars)		/* Number of characters in the unicode
    Tcl_Size numChars)		/* Number of characters in the Unicode
				 * string. */
{
    String *stringPtr;

    if (numChars == TCL_INDEX_NONE) {
    if (numChars < 0) {
	numChars = UnicodeLength(unicode);
    }

    /*
     * Allocate enough space for the String structure + Unicode string.
     */

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
1116
1117
1118
1119
1120
1121
1122
1123






1124

1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135

1136
1137
1138
1139
1140
1141
1142
1192
1193
1194
1195
1196
1197
1198

1199
1200
1201

1202
1203
1204
1205
1206
1207
1208


1209
1210
1211

1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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







-
+


-
+






-
-
+
+

-
+

















-
+


-
+















+
+
+
+
+
+
-
+










-
+







 */

void
Tcl_AppendLimitedToObj(
    Tcl_Obj *objPtr,		/* Points to the object to append to. */
    const char *bytes,		/* Points to the bytes to append to the
				 * object. */
    size_t length,		/* The number of bytes available to be
    Tcl_Size length,		/* The number of bytes available to be
				 * appended from "bytes". If -1, then
				 * all bytes up to a NUL byte are available. */
    size_t limit,		/* The maximum number of bytes to append to
    Tcl_Size limit,		/* The maximum number of bytes to append to
				 * the object. */
    const char *ellipsis)	/* Ellipsis marker string, appended to the
				 * object to indicate not all available bytes
				 * at "bytes" were appended. */
{
    String *stringPtr;
    size_t toCopy = 0;
    size_t eLen = 0;
    Tcl_Size toCopy = 0;
    Tcl_Size eLen = 0;

    if (length == TCL_INDEX_NONE) {
    if (length < 0) {
	length = (bytes ? strlen(bytes) : 0);
    }
    if (length == 0) {
	return;
    }
    if (limit <= 0) {
	return;
    }

    if (length <= limit) {
	toCopy = length;
    } else {
	if (ellipsis == NULL) {
	    ellipsis = "...";
	}
	eLen = strlen(ellipsis);
	while (eLen > limit) {
	    eLen = TclUtfPrev(ellipsis+eLen, ellipsis) - ellipsis;
	    eLen = Tcl_UtfPrev(ellipsis+eLen, ellipsis) - ellipsis;
	}

	toCopy = TclUtfPrev(bytes+limit+1-eLen, bytes) - bytes;
	toCopy = Tcl_UtfPrev(bytes+limit+1-eLen, bytes) - bytes;
    }

    /*
     * If objPtr has a valid Unicode rep, then append the Unicode conversion
     * of "bytes" to the objPtr's Unicode rep, otherwise append "bytes" to
     * objPtr's string rep.
     */

    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_AppendLimitedToObj");
    }

    SetStringFromAny(NULL, objPtr);
    stringPtr = GET_STRING(objPtr);

    /* If appended string starts with a continuation byte or a lower surrogate,
     * force objPtr to unicode representation. See [7f1162a867] */
    if (bytes && ISCONTINUATION(bytes)) {
	Tcl_GetUnicode(objPtr);
	stringPtr = GET_STRING(objPtr);
    }
    if (stringPtr->hasUnicode && (stringPtr->numChars+1) > 1) {
    if (stringPtr->hasUnicode && (stringPtr->numChars > 0)) {
	AppendUtfToUnicodeRep(objPtr, bytes, toCopy);
    } else {
	AppendUtfToUtfRep(objPtr, bytes, toCopy);
    }

    if (length <= limit) {
	return;
    }

    stringPtr = GET_STRING(objPtr);
    if (stringPtr->hasUnicode && (stringPtr->numChars+1) > 1) {
    if (stringPtr->hasUnicode && (stringPtr->numChars > 0)) {
	AppendUtfToUnicodeRep(objPtr, ellipsis, eLen);
    } else {
	AppendUtfToUtfRep(objPtr, ellipsis, eLen);
    }
}

/*
1157
1158
1159
1160
1161
1162
1163
1164
1165


1166
1167
1168

1169
1170
1171
1172
1173
1174

1175
1176
1177

1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189

1190
1191

1192
1193


1194
1195
1196
1197
1198

1199
1200
1201
1202
1203
1204
1205
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







-
-
+
+


-
+





-
+


-
+











-
+

-
+

-
+
+




-
+







 */

void
Tcl_AppendToObj(
    Tcl_Obj *objPtr,		/* Points to the object to append to. */
    const char *bytes,		/* Points to the bytes to append to the
				 * object. */
    size_t length)		/* The number of bytes to append from "bytes".
				 * If -1, then append all bytes up to NUL
    Tcl_Size length)		/* The number of bytes to append from "bytes".
				 * If TCL_INDEX_NONE, then append all bytes up to NUL
				 * byte. */
{
    Tcl_AppendLimitedToObj(objPtr, bytes, length, TCL_INDEX_NONE, NULL);
    Tcl_AppendLimitedToObj(objPtr, bytes, length, TCL_SIZE_MAX, NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * TclAppendUnicodeToObj --
 * Tcl_AppendUnicodeToObj --
 *
 *	This function appends a Unicode string to an object in the most
 *	efficient manner possible. Length must be >= 0.
 *	efficient manner possible.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Invalidates the string rep and creates a new Unicode string.
 *
 *----------------------------------------------------------------------
 */

void
TclAppendUnicodeToObj(
Tcl_AppendUnicodeToObj(
    Tcl_Obj *objPtr,		/* Points to the object to append to. */
    const Tcl_UniChar *unicode,	/* The unicode string to append to the
    const Tcl_UniChar *unicode,	/* The Unicode string to append to the
				 * object. */
    size_t length)		/* Number of chars in "unicode". */
    Tcl_Size length)		/* Number of chars in Unicode. Negative
				 * lengths means nul terminated */
{
    String *stringPtr;

    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "TclAppendUnicodeToObj");
	Tcl_Panic("%s called with shared object", "Tcl_AppendUnicodeToObj");
    }

    if (length == 0) {
	return;
    }

    SetStringFromAny(NULL, objPtr);
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

1354
1355
1356
1357
1358
1359
1360
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
1387

1388
1389
1390

1391
1392

1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403

1404
1405
1406
1407
1408
1409
1410
1411
1412
1413

1414
1415
1416

1417
1418
1419
1420
1421
1422
1423

1424
1425
1426
1427
1428
1429
1430

1431
1432
1433
1434


1435
1436
1437
1438
1439
1440
1441
1372
1373
1374
1375
1376
1377
1378


1379
1380
1381
1382


1383
1384




1385
1386
1387
1388
1389
1390
1391
1392
1393


1394
1395


1396


1397
1398


1399

1400
1401

1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417

1418
1419


1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440

1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489

1490
1491
1492
1493
1494
1495
1496
1497

1498
1499
1500
1501
1502
1503
1504
1505
1506
1507


1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523

1524
1525
1526

1527
1528

1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539

1540
1541
1542
1543
1544
1545
1546
1547
1548
1549

1550
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







-
-
+
+


-
-
+
+
-
-
-
-
+
+
+
+



+
+
-
-
+
+
-
-
+
-
-
+

-
-

-
+

-
+















-
+

-
-
+
+



















-
+










+
+
+
+
+
+
+










-
+

-
+


















-
+







-
+









-
-
+
+














-
+


-
+

-
+










-
+









-
+


-
+






-
+






-
+


-
-
+
+








void
Tcl_AppendObjToObj(
    Tcl_Obj *objPtr,		/* Points to the object to append to. */
    Tcl_Obj *appendObjPtr)	/* Object to append. */
{
    String *stringPtr;
    size_t length = 0, numChars;
    size_t appendNumChars = TCL_INDEX_NONE;
    Tcl_Size length = 0, numChars;
    Tcl_Size appendNumChars = TCL_INDEX_NONE;
    const char *bytes;

    /*
     * Special case: second object is standard-empty is fast case. We know
    if (TclCheckEmptyString(appendObjPtr) == TCL_EMPTYSTRING_YES) {
	return;
     * that appending nothing to anything leaves that starting anything...
     */

    if (appendObjPtr->bytes == &tclEmptyString) {
    }

    if (TclCheckEmptyString(objPtr) == TCL_EMPTYSTRING_YES) {
	TclSetDuplicateObj(objPtr, appendObjPtr);
	return;
    }

    if (TclIsPureByteArray(appendObjPtr)
	    && (TclIsPureByteArray(objPtr) || objPtr->bytes == &tclEmptyString)) {
    /*
     * Handle append of one bytearray object to another as a special case.
	/*
	 * Both bytearray objects are pure, so the second internal bytearray value
     * Note that we only do this when the objects are pure so that the
     * bytearray faithfully represent the true value; Otherwise appending the
	 * can be appended to the first, with no need to modify the "bytes" field.
     * byte arrays together could lose information;
     */
	 */

    if ((TclIsPureByteArray(objPtr) || objPtr->bytes == &tclEmptyString)
	    && TclIsPureByteArray(appendObjPtr)) {
	/*
	 * You might expect the code here to be
	 * One might expect the code here to be
	 *
	 *  bytes = TclGetByteArrayFromObj(appendObjPtr, &length);
	 *  bytes = Tcl_GetBytesFromObj(NULL, appendObjPtr, &length);
	 *  TclAppendBytesToByteArray(objPtr, bytes, length);
	 *
	 * and essentially all of the time that would be fine. However, it
	 * would run into trouble in the case where objPtr and appendObjPtr
	 * point to the same thing. That may never be a good idea. It seems to
	 * violate Copy On Write, and we don't have any tests for the
	 * situation, since making any Tcl commands that call
	 * Tcl_AppendObjToObj() do that appears impossible (They honor Copy On
	 * Write!). For the sake of extensions that go off into that realm,
	 * though, here's a more complex approach that can handle all the
	 * cases.
	 *
	 * First, get the lengths.
	 */

	size_t lengthSrc = 0;
	Tcl_Size lengthSrc = 0;

	(void) TclGetByteArrayFromObj(objPtr, &length);
	(void) TclGetByteArrayFromObj(appendObjPtr, &lengthSrc);
	(void) Tcl_GetBytesFromObj(NULL, objPtr, &length);
	(void) Tcl_GetBytesFromObj(NULL, appendObjPtr, &lengthSrc);

	/*
	 * Grow buffer enough for the append.
	 */

	TclAppendBytesToByteArray(objPtr, NULL, lengthSrc);

	/*
	 * Reset objPtr back to the original value.
	 */

	Tcl_SetByteArrayLength(objPtr, length);

	/*
	 * Now do the append knowing that buffer growth cannot cause any
	 * trouble.
	 */

	TclAppendBytesToByteArray(objPtr,
		Tcl_GetByteArrayFromObj(appendObjPtr, NULL), lengthSrc);
		Tcl_GetBytesFromObj(NULL, appendObjPtr, (Tcl_Size *) NULL), lengthSrc);
	return;
    }

    /*
     * Must append as strings.
     */

    SetStringFromAny(NULL, objPtr);
    stringPtr = GET_STRING(objPtr);

    /* If appended string starts with a continuation byte or a lower surrogate,
     * force objPtr to unicode representation. See [7f1162a867]
     * This fixes append-3.4, append-3.7 and utf-1.18 testcases. */
    if (ISCONTINUATION(TclGetString(appendObjPtr))) {
	Tcl_GetUnicode(objPtr);
	stringPtr = GET_STRING(objPtr);
    }
    /*
     * If objPtr has a valid Unicode rep, then get a Unicode string from
     * appendObjPtr and append it.
     */

    if (stringPtr->hasUnicode) {
	/*
	 * If appendObjPtr is not of the "String" type, don't convert it.
	 */

	if (TclHasIntRep(appendObjPtr, &tclStringType)) {
	if (TclHasInternalRep(appendObjPtr, &tclStringType)) {
	    Tcl_UniChar *unicode =
		    TclGetUnicodeFromObj(appendObjPtr, &numChars);
		    Tcl_GetUnicodeFromObj(appendObjPtr, &numChars);

	    AppendUnicodeToUnicodeRep(objPtr, unicode, numChars);
	} else {
	    bytes = TclGetStringFromObj(appendObjPtr, &length);
	    AppendUtfToUnicodeRep(objPtr, bytes, length);
	}
	return;
    }

    /*
     * Append to objPtr's UTF string rep. If we know the number of characters
     * in both objects before appending, then set the combined number of
     * characters in the final (appended-to) object.
     */

    bytes = TclGetStringFromObj(appendObjPtr, &length);

    numChars = stringPtr->numChars;
    if ((numChars != TCL_INDEX_NONE) && TclHasIntRep(appendObjPtr, &tclStringType)) {
    if ((numChars >= 0) && TclHasInternalRep(appendObjPtr, &tclStringType)) {
	String *appendStringPtr = GET_STRING(appendObjPtr);

	appendNumChars = appendStringPtr->numChars;
    }

    AppendUtfToUtfRep(objPtr, bytes, length);

    if ((numChars != TCL_INDEX_NONE) && (appendNumChars != TCL_INDEX_NONE)) {
    if ((numChars >= 0) && (appendNumChars >= 0)) {
	stringPtr->numChars = numChars + appendNumChars;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * AppendUnicodeToUnicodeRep --
 *
 *	This function appends the contents of "unicode" to the Unicode rep of
 *	"objPtr". objPtr must already have a valid Unicode rep.
 *	Appends the contents of unicode to the Unicode rep of
 *	objPtr, which must already have a valid Unicode rep.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	objPtr's internal rep is reallocated.
 *
 *----------------------------------------------------------------------
 */

static void
AppendUnicodeToUnicodeRep(
    Tcl_Obj *objPtr,		/* Points to the object to append to. */
    const Tcl_UniChar *unicode,	/* String to append. */
    size_t appendNumChars)		/* Number of chars of "unicode" to append. */
    Tcl_Size appendNumChars)	/* Number of chars of "unicode" to append. */
{
    String *stringPtr;
    size_t numChars;
    Tcl_Size numChars;

    if (appendNumChars == TCL_INDEX_NONE) {
    if (appendNumChars < 0) {
	appendNumChars = UnicodeLength(unicode);
    }
    if (appendNumChars == 0) {
	return;
    }

    SetStringFromAny(NULL, objPtr);
    stringPtr = GET_STRING(objPtr);

    /*
     * If not enough space has been allocated for the unicode rep, reallocate
     * If not enough space has been allocated for the Unicode rep, reallocate
     * the internal rep object with additional space. First try to double the
     * required allocation; if that fails, try a more modest increase. See the
     * "TCL STRING GROWTH ALGORITHM" comment at the top of this file for an
     * explanation of this growth algorithm.
     */

    numChars = stringPtr->numChars + appendNumChars;

    if (numChars > stringPtr->maxChars) {
	size_t index = TCL_INDEX_NONE;
	Tcl_Size offset = -1;

	/*
	 * Protect against case where unicode points into the existing
	 * Protect against case where Unicode points into the existing
	 * stringPtr->unicode array. Force it to follow any relocations due to
	 * the reallocs below.
	 */

	if (unicode && unicode >= stringPtr->unicode
		&& unicode <= stringPtr->unicode + stringPtr->maxChars) {
	    index = unicode - stringPtr->unicode;
	    offset = unicode - stringPtr->unicode;
	}

	GrowUnicodeBuffer(objPtr, numChars);
	stringPtr = GET_STRING(objPtr);

	/*
	 * Relocate unicode if needed; see above.
	 * Relocate Unicode if needed; see above.
	 */

	if (index != TCL_INDEX_NONE) {
	    unicode = stringPtr->unicode + index;
	if (offset >= 0) {
	    unicode = stringPtr->unicode + offset;
	}
    }

    /*
     * Copy the new string onto the end of the old string, then add the
     * trailing null.
     */
1468
1469
1470
1471
1472
1473
1474
1475

1476
1477
1478
1479
1480
1481
1482
1605
1606
1607
1608
1609
1610
1611

1612
1613
1614
1615
1616
1617
1618
1619







-
+







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

static void
AppendUnicodeToUtfRep(
    Tcl_Obj *objPtr,		/* Points to the object to append to. */
    const Tcl_UniChar *unicode,	/* String to convert to UTF. */
    size_t numChars)		/* Number of chars of "unicode" to convert. */
    Tcl_Size numChars)		/* Number of chars of Unicode to convert. */
{
    String *stringPtr = GET_STRING(objPtr);

    numChars = ExtendStringRepWithUnicode(objPtr, unicode, numChars);

    if (stringPtr->numChars != TCL_INDEX_NONE) {
	stringPtr->numChars += numChars;
1492
1493
1494
1495
1496
1497
1498
1499

1500
1501
1502
1503
1504
1505
1506
1507
1508

1509
1510
1511
1512
1513
1514
1515
1629
1630
1631
1632
1633
1634
1635

1636
1637
1638
1639
1640
1641
1642
1643
1644

1645
1646
1647
1648
1649
1650
1651
1652







-
+








-
+







 *	the Unicode to the Unicode rep of "objPtr". objPtr must already have a
 *	valid Unicode rep. numBytes must be non-negative.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	objPtr's internal rep is reallocated.
 *	objPtr's internal rep is reallocated and string rep is cleaned.
 *
 *----------------------------------------------------------------------
 */

static void
AppendUtfToUnicodeRep(
    Tcl_Obj *objPtr,		/* Points to the object to append to. */
    const char *bytes,		/* String to convert to Unicode. */
    size_t numBytes)		/* Number of bytes of "bytes" to convert. */
    Tcl_Size numBytes)		/* Number of bytes of "bytes" to convert. */
{
    String *stringPtr;

    if (numBytes == 0) {
	return;
    }

1528
1529
1530
1531
1532
1533
1534
1535

1536
1537
1538
1539
1540
1541
1542
1543
1544

1545
1546
1547

1548
1549
1550
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
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787







-
+








-
+


-
+














+
+
+




-
+







-
-
+
+














-
+








-
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *	rep of "objPtr". objPtr must already have a valid String rep.
 *	numBytes must be non-negative.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	objPtr's internal rep is reallocated.
 *	objPtr's string rep is reallocated (by TCL STRING GROWTH ALGORITHM).
 *
 *----------------------------------------------------------------------
 */

static void
AppendUtfToUtfRep(
    Tcl_Obj *objPtr,		/* Points to the object to append to. */
    const char *bytes,		/* String to append. */
    size_t numBytes)		/* Number of bytes of "bytes" to append. */
    Tcl_Size numBytes)		/* Number of bytes of "bytes" to append. */
{
    String *stringPtr;
    size_t newLength, oldLength;
    Tcl_Size newLength, oldLength;

    if (numBytes == 0) {
	return;
    }

    /*
     * Copy the new string onto the end of the old string, then add the
     * trailing null.
     */

    if (objPtr->bytes == NULL) {
	objPtr->length = 0;
    }
    oldLength = objPtr->length;
    if (numBytes > TCL_SIZE_MAX - oldLength) {
	Tcl_Panic("max size for a Tcl value (%" TCL_SIZE_MODIFIER "d bytes) exceeded", TCL_SIZE_MAX);
    }
    newLength = numBytes + oldLength;

    stringPtr = GET_STRING(objPtr);
    if (newLength > stringPtr->allocated) {
	size_t offset = TCL_INDEX_NONE;
	Tcl_Size offset = -1;

	/*
	 * Protect against case where unicode points into the existing
	 * stringPtr->unicode array. Force it to follow any relocations due to
	 * the reallocs below.
	 */

	if (bytes && bytes >= objPtr->bytes
		&& bytes <= objPtr->bytes + objPtr->length) {
	if (bytes && objPtr->bytes && (bytes >= objPtr->bytes)
		&& (bytes <= objPtr->bytes + objPtr->length)) {
	    offset = bytes - objPtr->bytes;
	}

	/*
	 * TODO: consider passing flag=1: no overalloc on first append. This
	 * would make test stringObj-8.1 fail.
	 */

	GrowStringBuffer(objPtr, newLength, 0);

	/*
	 * Relocate bytes if needed; see above.
	 */

	if (offset != TCL_INDEX_NONE) {
	if (offset >= 0) {
	    bytes = objPtr->bytes + offset;
	}
    }

    /*
     * Invalidate the unicode data.
     */

    stringPtr->numChars = TCL_INDEX_NONE;
    stringPtr->numChars = -1;
    stringPtr->hasUnicode = 0;

    if (bytes) {
	memmove(objPtr->bytes + oldLength, bytes, numBytes);
    }
    objPtr->bytes[newLength] = 0;
    objPtr->length = newLength;
}

/*
 *----------------------------------------------------------------------
 *
 * TclAppendUtfToUtf --
 *
 *	This function appends "numBytes" bytes of "bytes" to the UTF string
 *	rep of "objPtr" (objPtr's internal rep converted to string on demand).
 *	numBytes must be non-negative.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	objPtr's string rep is reallocated (by TCL STRING GROWTH ALGORITHM).
 *
 *----------------------------------------------------------------------
 */

void
TclAppendUtfToUtf(
    Tcl_Obj *objPtr,		/* Points to the object to append to. */
    const char *bytes,		/* String to append (or NULL to enlarge buffer). */
    Tcl_Size numBytes)		/* Number of bytes of "bytes" to append. */
{
    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "TclAppendUtfToUtf");
    }

    SetStringFromAny(NULL, objPtr);

    AppendUtfToUtfRep(objPtr, bytes, numBytes);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AppendStringsToObj --
 *
 *	This function appends one or more null-terminated strings to an
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
1841
1842
1843
1844
1845
1846
1847

1848
1849
1850
1851


1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866

1867
1868
1869
1870
1871
1872
1873
1874
1875


1876
1877
1878



1879
1880
1881
1882
1883
1884
1885
1886
1887







-
+



-
-
+
+













-
+








-
-
+
+

-
-
-
+
+







 */

int
Tcl_AppendFormatToObj(
    Tcl_Interp *interp,
    Tcl_Obj *appendObj,
    const char *format,
    int objc,
    Tcl_Size objc,
    Tcl_Obj *const objv[])
{
    const char *span = format, *msg, *errCode;
    int objIndex = 0, gotXpg = 0, gotSequential = 0;
    size_t originalLength, limit, numBytes = 0;
    int gotXpg = 0, gotSequential = 0;
    Tcl_Size objIndex = 0, originalLength, limit, numBytes = 0;
    Tcl_UniChar ch = 0;
    static const char *mixedXPG =
	    "cannot mix \"%\" and \"%n$\" conversion specifiers";
    static const char *const badIndex[2] = {
	"not enough arguments for all format specifiers",
	"\"%n$\" argument index out of range"
    };
    static const char *overflow = "max size for a Tcl value exceeded";

    if (Tcl_IsShared(appendObj)) {
	Tcl_Panic("%s called with shared object", "Tcl_AppendFormatToObj");
    }
    (void)TclGetStringFromObj(appendObj, &originalLength);
    limit = (size_t)INT_MAX - originalLength;
    limit = TCL_SIZE_MAX - originalLength;

    /*
     * Format string is NUL-terminated.
     */

    while (*format != '\0') {
	char *end;
	int gotMinus = 0, gotHash = 0, gotZero = 0, gotSpace = 0, gotPlus = 0;
	int width, gotPrecision, precision, sawFlag, useShort = 0, useBig = 0;
#ifndef TCL_WIDE_INT_IS_LONG
	int gotPrecision, sawFlag, useShort = 0, useBig = 0;
	Tcl_WideInt width, precision;
	int useWide = 0;
#endif
	int newXpg, numChars, allocSegment = 0, segmentLimit;
	size_t segmentNumBytes;
	int newXpg, allocSegment = 0;
	Tcl_Size numChars, segmentLimit, segmentNumBytes;
	Tcl_Obj *segment;
	int step = TclUtfToUniChar(format, &ch);

	format += step;
	if (ch != '%') {
	    numBytes += step;
	    continue;
1808
1809
1810
1811
1812
1813
1814


1815
1816



1817
1818
1819
1820

1821
1822
1823
1824
1825
1826
1827
1828
1829

1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840

1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856


1857








1858
1859
1860
1861
1862
1863
1864
1865
1866

1867
1868
1869
1870
1871
1872
1873
1980
1981
1982
1983
1984
1985
1986
1987
1988


1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004

2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015

2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034

2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050

2051
2052
2053
2054
2055
2056
2057
2058







+
+
-
-
+
+
+




+








-
+










-
+
















+
+
-
+
+
+
+
+
+
+
+








-
+








	/*
	 * Step 3. Minimum field width.
	 */

	width = 0;
	if (isdigit(UCHAR(ch))) {
	    /* Note ull will be >= 0 because of isdigit check above */
	    unsigned long long ull;
	    width = strtoul(format, &end, 10);
	    if (width < 0) {
	    ull = strtoull(format, &end, 10);
	    /* Comparison is >=, not >, to leave room for nul */
	    if (ull >= WIDE_MAX) {
		msg = overflow;
		errCode = "OVERFLOW";
		goto errorMsg;
	    }
	    width = (Tcl_WideInt)ull;
	    format = end;
	    step = TclUtfToUniChar(format, &ch);
	} else if (ch == '*') {
	    if (objIndex >= objc - 1) {
		msg = badIndex[gotXpg];
		errCode = gotXpg ? "INDEXRANGE" : "FIELDVARMISMATCH";
		goto errorMsg;
	    }
	    if (TclGetIntFromObj(interp, objv[objIndex], &width) != TCL_OK) {
	    if (TclGetWideIntFromObj(interp, objv[objIndex], &width) != TCL_OK) {
		goto error;
	    }
	    if (width < 0) {
		width = -width;
		gotMinus = 1;
	    }
	    objIndex++;
	    format += step;
	    step = TclUtfToUniChar(format, &ch);
	}
	if (width > (int) limit) {
	if (width > limit) {
	    msg = overflow;
	    errCode = "OVERFLOW";
	    goto errorMsg;
	}

	/*
	 * Step 4. Precision.
	 */

	gotPrecision = precision = 0;
	if (ch == '.') {
	    gotPrecision = 1;
	    format += step;
	    step = TclUtfToUniChar(format, &ch);
	}
	if (isdigit(UCHAR(ch))) {
	    /* Note ull will be >= 0 because of isdigit check above */
	    unsigned long long ull;
	    precision = strtoul(format, &end, 10);
	    ull = strtoull(format, &end, 10);
	    /* Comparison is >=, not >, to leave room for nul */
	    if (ull >= WIDE_MAX) {
		msg = overflow;
		errCode = "OVERFLOW";
		goto errorMsg;
	    }
	    precision = (Tcl_WideInt)ull;
	    format = end;
	    step = TclUtfToUniChar(format, &ch);
	} else if (ch == '*') {
	    if (objIndex >= objc - 1) {
		msg = badIndex[gotXpg];
		errCode = gotXpg ? "INDEXRANGE" : "FIELDVARMISMATCH";
		goto errorMsg;
	    }
	    if (TclGetIntFromObj(interp, objv[objIndex], &precision)
	    if (TclGetWideIntFromObj(interp, objv[objIndex], &precision)
		    != TCL_OK) {
		goto error;
	    }

	    /*
	     * TODO: Check this truncation logic.
	     */
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
2076
2077
2078
2079
2080
2081
2082

2083
2084

2085
2086
2087
2088
2089

2090

2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101


2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115







-


-





-

-







+
+
+
+
-
-
+
+
+
+
+
+
+







	} else if (ch == 'l') {
	    format += step;
	    step = TclUtfToUniChar(format, &ch);
	    if (ch == 'l') {
		useBig = 1;
		format += step;
		step = TclUtfToUniChar(format, &ch);
#ifndef TCL_WIDE_INT_IS_LONG
	    } else {
		useWide = 1;
#endif
	    }
	} else if (ch == 'I') {
	    if ((format[1] == '6') && (format[2] == '4')) {
		format += (step + 2);
		step = TclUtfToUniChar(format, &ch);
#ifndef TCL_WIDE_INT_IS_LONG
		useWide = 1;
#endif
	    } else if ((format[1] == '3') && (format[2] == '2')) {
		format += (step + 2);
		step = TclUtfToUniChar(format, &ch);
	    } else {
		format += step;
		step = TclUtfToUniChar(format, &ch);
	    }
	} else if ((ch == 'q') || (ch == 'j')) {
	    format += step;
	    step = TclUtfToUniChar(format, &ch);
	    useWide = 1;
	} else if ((ch == 't') || (ch == 'z') || (ch == 'q') || (ch == 'j')
		|| (ch == 'L')) {
	} else if ((ch == 't') || (ch == 'z')) {
	    format += step;
	    step = TclUtfToUniChar(format, &ch);
	    if (sizeof(void *) > sizeof(int)) {
		useWide = 1;
	    }
	} else if (ch == 'L') {
	    format += step;
	    step = TclUtfToUniChar(format, &ch);
	    useBig = 1;
	}

	format += step;
	span = format;
1938
1939
1940
1941
1942
1943
1944



1945


1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960


1961
1962
1963

1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980

1981
1982
1983


1984
1985
1986

1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997



1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014

2015
2016



2017
2018
2019
2020

2021
2022
2023
2024
2025



2026
2027
2028




2029
2030
2031
2032
2033



2034
2035
2036




2037
2038
2039
2040
2041

2042
2043
2044
2045
2046
2047
2048
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137

2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152


2153
2154


2155
2156
2157
2158
2159
2160
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
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







+
+
+
-
+
+













-
-
+
+
-
-

+
















-
+


-
+
+

-
-
+


-







-
+
+
+










-





-
+
-
-
+
+
+



-
+




-
+
+
+

-
-
+
+
+
+




-
+
+
+

-
-
+
+
+
+




-
+







	    msg = "format string ended in middle of field specifier";
	    errCode = "INCOMPLETE";
	    goto errorMsg;
	case 's':
	    if (gotPrecision) {
		numChars = Tcl_GetCharLength(segment);
		if (precision < numChars) {
		    if (precision < 1) {
			TclNewObj(segment);
		    } else {
		    segment = Tcl_GetRange(segment, 0, precision - 1);
			segment = Tcl_GetRange(segment, 0, precision - 1);
		    }
		    numChars = precision;
		    Tcl_IncrRefCount(segment);
		    allocSegment = 1;
		}
	    }
	    break;
	case 'c': {
	    char buf[4] = "";
	    int code, length;

	    if (TclGetIntFromObj(interp, segment, &code) != TCL_OK) {
		goto error;
	    }
	    length = Tcl_UniCharToUtf(code, buf);
	    if ((code >= 0xD800) && (length < 3)) {
	    if ((unsigned)code > 0x10FFFF) {
		code = 0xFFFD;
		/* Special case for handling high surrogates. */
		length += Tcl_UniCharToUtf(-1, buf + length);
	    }
	    length = Tcl_UniCharToUtf(code, buf);
	    segment = Tcl_NewStringObj(buf, length);
	    Tcl_IncrRefCount(segment);
	    allocSegment = 1;
	    break;
	}

	case 'u':
	    /* FALLTHRU */
	case 'd':
	case 'o':
	case 'p':
	case 'x':
	case 'X':
	case 'b': {
	    short s = 0;	/* Silence compiler warning; only defined and
				 * used when useShort is true. */
	    long l;
	    int l;
	    Tcl_WideInt w;
	    mp_int big;
	    int toAppend, isNegative = 0;
	    int isNegative = 0;
	    Tcl_Size toAppend;

#ifndef TCL_WIDE_INT_IS_LONG
	    if (ch == 'p') {
	    if ((ch == 'p') && (sizeof(void *) > sizeof(int))) {
		useWide = 1;
	    }
#endif
	    if (useBig) {
		int cmpResult;
		if (Tcl_GetBignumFromObj(interp, segment, &big) != TCL_OK) {
		    goto error;
		}
		cmpResult = mp_cmp_d(&big, 0);
		isNegative = (cmpResult == MP_LT);
		if (cmpResult == MP_EQ) gotHash = 0;
		if (cmpResult == MP_EQ) {
		    gotHash = 0;
		}
		if (ch == 'u') {
		    if (isNegative) {
			mp_clear(&big);
			msg = "unsigned bignum format is invalid";
			errCode = "BADUNSIGNED";
			goto errorMsg;
		    } else {
			ch = 'd';
		    }
		}
#ifndef TCL_WIDE_INT_IS_LONG
	    } else if (useWide) {
		if (TclGetWideBitsFromObj(interp, segment, &w) != TCL_OK) {
		    goto error;
		}
		isNegative = (w < (Tcl_WideInt) 0);
		if (w == (Tcl_WideInt) 0) gotHash = 0;
		if (w == (Tcl_WideInt) 0) {
#endif
	    } else if (TclGetLongFromObj(NULL, segment, &l) != TCL_OK) {
		    gotHash = 0;
		}
	    } else if (TclGetIntFromObj(NULL, segment, &l) != TCL_OK) {
		if (TclGetWideBitsFromObj(interp, segment, &w) != TCL_OK) {
		    goto error;
		} else {
		    l = (long) w;
		    l = (int) w;
		}
		if (useShort) {
		    s = (short) l;
		    isNegative = (s < (short) 0);
		    if (s == (short) 0) gotHash = 0;
		    if (s == (short) 0) {
			gotHash = 0;
		    }
		} else {
		    isNegative = (l < (long) 0);
		    if (l == (long) 0) gotHash = 0;
		    isNegative = (l < (int) 0);
		    if (l == (int) 0) {
			gotHash = 0;
		    }
		}
	    } else if (useShort) {
		s = (short) l;
		isNegative = (s < (short) 0);
		if (s == (short) 0) gotHash = 0;
		if (s == (short) 0) {
		    gotHash = 0;
		}
	    } else {
		isNegative = (l < (long) 0);
		if (l == (long) 0) gotHash = 0;
		isNegative = (l < (int) 0);
		if (l == (int) 0) {
		    gotHash = 0;
		}
	    }

	    TclNewObj(segment);
	    allocSegment = 1;
	    segmentLimit = INT_MAX;
	    segmentLimit = TCL_SIZE_MAX;
	    Tcl_IncrRefCount(segment);

	    if ((isNegative || gotPlus || gotSpace) && (useBig || ch=='d')) {
		Tcl_AppendToObj(segment,
			(isNegative ? "-" : gotPlus ? "+" : " "), 1);
		segmentLimit -= 1;
	    }
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
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276

2277
2278
2279
2280
2281
2282

2283
2284

2285
2286
2287
2288
2289
2290
2291







+
+
+
+





-
+





-


-







		    Tcl_AppendToObj(segment, "0x", 2);
		    segmentLimit -= 2;
		    break;
		case 'b':
		    Tcl_AppendToObj(segment, "0b", 2);
		    segmentLimit -= 2;
		    break;
		case 'd':
		    Tcl_AppendToObj(segment, "0d", 2);
		    segmentLimit -= 2;
		    break;
		}
	    }

	    switch (ch) {
	    case 'd': {
		size_t length;
		Tcl_Size length;
		Tcl_Obj *pure;
		const char *bytes;

		if (useShort) {
		    TclNewIntObj(pure, s);
#ifndef TCL_WIDE_INT_IS_LONG
		} else if (useWide) {
		    TclNewIntObj(pure, w);
#endif
		} else if (useBig) {
		    pure = Tcl_NewBignumObj(&big);
		} else {
		    TclNewIntObj(pure, l);
		}
		Tcl_IncrRefCount(pure);
		bytes = TclGetStringFromObj(pure, &length);
2099
2100
2101
2102
2103
2104
2105
2106

2107
2108
2109

2110
2111
2112
2113
2114
2115
2116
2117

2118
2119
2120

2121
2122
2123
2124
2125
2126
2127
2303
2304
2305
2306
2307
2308
2309

2310
2311
2312

2313
2314
2315
2316
2317
2318
2319
2320

2321
2322
2323

2324
2325
2326
2327
2328
2329
2330
2331







-
+


-
+







-
+


-
+







		/*
		 * Canonical decimal string reps for integers are composed
		 * entirely of one-byte encoded characters, so "length" is the
		 * number of chars.
		 */

		if (gotPrecision) {
		    if (length < (size_t)precision) {
		    if (length < precision) {
			segmentLimit -= precision - length;
		    }
		    while (length < (size_t)precision) {
		    while (length < precision) {
			Tcl_AppendToObj(segment, "0", 1);
			length++;
		    }
		    gotZero = 0;
		}
		if (gotZero) {
		    length += Tcl_GetCharLength(segment);
		    if (length < (size_t)width) {
		    if (length < width) {
			segmentLimit -= width - length;
		    }
		    while (length < (size_t)width) {
		    while (length < width) {
			Tcl_AppendToObj(segment, "0", 1);
			length++;
		    }
		}
		if (toAppend > segmentLimit) {
		    msg = overflow;
		    errCode = "OVERFLOW";
2137
2138
2139
2140
2141
2142
2143
2144

2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409

2410
2411
2412
2413
2414
2415
2416
2417







-
+




















-








-
















-
+
















-
+







	    case 'p':
	    case 'x':
	    case 'X':
	    case 'b': {
		Tcl_WideUInt bits = 0;
		Tcl_WideInt numDigits = 0;
		int numBits = 4, base = 16, index = 0, shift = 0;
		size_t length;
		Tcl_Size length;
		Tcl_Obj *pure;
		char *bytes;

		if (ch == 'u') {
		    base = 10;
		} else if (ch == 'o') {
		    base = 8;
		    numBits = 3;
		} else if (ch == 'b') {
		    base = 2;
		    numBits = 1;
		}
		if (useShort) {
		    unsigned short us = (unsigned short) s;

		    bits = (Tcl_WideUInt) us;
		    while (us) {
			numDigits++;
			us /= base;
		    }
#ifndef TCL_WIDE_INT_IS_LONG
		} else if (useWide) {
		    Tcl_WideUInt uw = (Tcl_WideUInt) w;

		    bits = uw;
		    while (uw) {
			numDigits++;
			uw /= base;
		    }
#endif
		} else if (useBig && !mp_iszero(&big)) {
		    int leftover = (big.used * MP_DIGIT_BIT) % numBits;
		    mp_digit mask = (~(mp_digit)0) << (MP_DIGIT_BIT-leftover);

		    numDigits = 1 +
			    (((Tcl_WideInt) big.used * MP_DIGIT_BIT) / numBits);
		    while ((mask & big.dp[big.used-1]) == 0) {
			numDigits--;
			mask >>= numBits;
		    }
		    if (numDigits > INT_MAX) {
			msg = overflow;
			errCode = "OVERFLOW";
			goto errorMsg;
		    }
		} else if (!useBig) {
		    unsigned long ul = (unsigned long) l;
		    unsigned ul = (unsigned) l;

		    bits = (Tcl_WideUInt) ul;
		    while (ul) {
			numDigits++;
			ul /= base;
		    }
		}

		/*
		 * Need to be sure zero becomes "0", not "".
		 */

		if (numDigits == 0) {
		    numDigits = 1;
		}
		TclNewObj(pure);
		Tcl_SetObjLength(pure, numDigits);
		Tcl_SetObjLength(pure, (Tcl_Size)numDigits);
		bytes = TclGetString(pure);
		toAppend = length = numDigits;
		while (numDigits--) {
		    int digitOffset;

		    if (useBig && !mp_iszero(&big)) {
			if (index < big.used && (size_t) shift <
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
2433
2434
2435
2436
2437
2438
2439

2440
2441
2442

2443
2444
2445
2446
2447
2448
2449
2450

2451
2452
2453

2454
2455
2456
2457
2458
2459
2460
2461







-
+


-
+







-
+


-
+







		    }
		    bits /= base;
		}
		if (useBig) {
		    mp_clear(&big);
		}
		if (gotPrecision) {
		    if (length < (size_t)precision) {
		    if (length < precision) {
			segmentLimit -= precision - length;
		    }
		    while (length < (size_t)precision) {
		    while (length < precision) {
			Tcl_AppendToObj(segment, "0", 1);
			length++;
		    }
		    gotZero = 0;
		}
		if (gotZero) {
		    length += Tcl_GetCharLength(segment);
		    if (length < (size_t)width) {
		    if (length < width) {
			segmentLimit -= width - length;
		    }
		    while (length < (size_t)width) {
		    while (length < width) {
			Tcl_AppendToObj(segment, "0", 1);
			length++;
		    }
		}
		if (toAppend > segmentLimit) {
		    msg = overflow;
		    errCode = "OVERFLOW";
2298
2299
2300
2301
2302
2303
2304
2305

2306
2307
2308
2309
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
2500
2501
2502
2503
2504
2505
2506

2507
2508
2509
2510
2511
2512
2513


2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540

2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552

2553
2554
2555
2556
2557
2558
2559
2560
2561
2562

2563
2564
2565
2566
2567
2568
2569
2570







-
+






-
-
+
+

















+
+
+





-
+
+
+
+








-
+
+
+







-
+







	    if (gotSpace) {
		*p++ = ' ';
	    }
	    if (gotPlus) {
		*p++ = '+';
	    }
	    if (width) {
		p += sprintf(p, "%d", width);
		p += snprintf(p, TCL_INTEGER_SPACE, "%" TCL_LL_MODIFIER "d", width);
		if (width > length) {
		    length = width;
		}
	    }
	    if (gotPrecision) {
		*p++ = '.';
		p += sprintf(p, "%d", precision);
		if (precision > INT_MAX - length) {
		p += snprintf(p, TCL_INTEGER_SPACE, "%" TCL_LL_MODIFIER "d", precision);
		if (precision > TCL_SIZE_MAX - length) {
		    msg = overflow;
		    errCode = "OVERFLOW";
		    goto errorMsg;
		}
		length += precision;
	    }

	    /*
	     * Don't pass length modifiers!
	     */

	    *p++ = (char) ch;
	    *p = '\0';

	    TclNewObj(segment);
	    allocSegment = 1;
	    if (!Tcl_AttemptSetObjLength(segment, length)) {
		if (allocSegment) {
		    Tcl_DecrRefCount(segment);
		}
		msg = overflow;
		errCode = "OVERFLOW";
		goto errorMsg;
	    }
	    bytes = TclGetString(segment);
	    if (!Tcl_AttemptSetObjLength(segment, sprintf(bytes, spec, d))) {
	    if (!Tcl_AttemptSetObjLength(segment, snprintf(bytes, segment->length, spec, d))) {
		if (allocSegment) {
		    Tcl_DecrRefCount(segment);
		}
		msg = overflow;
		errCode = "OVERFLOW";
		goto errorMsg;
	    }
	    if (ch == 'A') {
		char *q = TclGetString(segment) + 1;
		*q = 'x';
		q = strchr(q, 'P');
		if (q) *q = 'p';
		if (q) {
		    *q = 'p';
		}
	    }
	    break;
	}
	default:
	    if (interp != NULL) {
		Tcl_SetObjResult(interp,
			Tcl_ObjPrintf("bad field specifier \"%c\"", ch));
		Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADTYPE", NULL);
		Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADTYPE", (char *)NULL);
	    }
	    goto error;
	}

	if (width>0 && numChars<0) {
	    numChars = Tcl_GetCharLength(segment);
	}
2406
2407
2408
2409
2410
2411
2412
2413

2414
2415
2416
2417
2418
2419
2420
2616
2617
2618
2619
2620
2621
2622

2623
2624
2625
2626
2627
2628
2629
2630







-
+







    }

    return TCL_OK;

  errorMsg:
    if (interp != NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1));
	Tcl_SetErrorCode(interp, "TCL", "FORMAT", errCode, NULL);
	Tcl_SetErrorCode(interp, "TCL", "FORMAT", errCode, (char *)NULL);
    }
  error:
    Tcl_SetObjLength(appendObj, originalLength);
    return TCL_ERROR;
}

/*
2431
2432
2433
2434
2435
2436
2437
2438

2439
2440
2441
2442
2443
2444
2445
2641
2642
2643
2644
2645
2646
2647

2648
2649
2650
2651
2652
2653
2654
2655







-
+







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

Tcl_Obj *
Tcl_Format(
    Tcl_Interp *interp,
    const char *format,
    int objc,
    Tcl_Size objc,
    Tcl_Obj *const objv[])
{
    int result;
    Tcl_Obj *objPtr;

    TclNewObj(objPtr);
    result = Tcl_AppendFormatToObj(interp, objPtr, format, objc, objv);
2457
2458
2459
2460
2461
2462
2463


























2464
2465
2466
2467
2468
2469
2470
2471


2472
2473
2474
2475
2476
2477
2478
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+
+







 *
 * Results:
 *
 * Side effects:
 *
 *---------------------------------------------------------------------------
 */

static Tcl_Obj *
NewLongObj(
    char c,
    long value)
{
    if ((value < 0) && strchr("puoxX", c)) {
	Tcl_Obj *obj;
	TclNewUIntObj(obj, (unsigned long)value);
	return obj;
    }
    return Tcl_NewWideIntObj((long)value);
}

static Tcl_Obj *
NewWideIntObj(
    char c,
    Tcl_WideInt value)
{
    if ((value < 0) && strchr("puoxX", c)) {
	Tcl_Obj *obj;
	TclNewUIntObj(obj, (Tcl_WideUInt)value);
	return obj;
    }
    return Tcl_NewWideIntObj(value);
}

static void
AppendPrintfToObjVA(
    Tcl_Obj *objPtr,
    const char *format,
    va_list argList)
{
    int code, objc;
    int code;
    Tcl_Size objc;
    Tcl_Obj **objv, *list;
    const char *p;

    TclNewObj(list);
    p = format;
    Tcl_IncrRefCount(list);
    while (*p != '\0') {
2508
2509
2510
2511
2512
2513
2514
2515

2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530





2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543

2544
2545
2546
2547

2548
2549
2550
2551

2552
2553
2554
2555
2556
2557
2558
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







-
+















+
+
+
+
+





-






-
+



-
+



-
+








		/*
		 * Within that buffer, we trim both ends if needed so that we
		 * copy only whole characters, and avoid copying any partial
		 * multi-byte characters.
		 */

		q = TclUtfPrev(end, bytes);
		q = Tcl_UtfPrev(end, bytes);
		if (!Tcl_UtfCharComplete(q, (end - q))) {
		    end = q;
		}

		q = bytes + 4;
		while ((bytes < end) && (bytes < q)
			&& ((*bytes & 0xC0) == 0x80)) {
		    bytes++;
		}

		Tcl_ListObjAppendElement(NULL, list,
			Tcl_NewStringObj(bytes , (end - bytes)));

		break;
	    }
	    case 'p':
		if (sizeof(size_t) == sizeof(Tcl_WideInt)) {
		    size = 2;
		}
		/* FALLTHRU */
	    case 'c':
	    case 'i':
	    case 'u':
	    case 'd':
	    case 'o':
	    case 'p':
	    case 'x':
	    case 'X':
		seekingConversion = 0;
		switch (size) {
		case -1:
		case 0:
		    Tcl_ListObjAppendElement(NULL, list, Tcl_NewWideIntObj(
		    Tcl_ListObjAppendElement(NULL, list, Tcl_NewIntObj(
			    va_arg(argList, int)));
		    break;
		case 1:
		    Tcl_ListObjAppendElement(NULL, list, Tcl_NewWideIntObj(
		    Tcl_ListObjAppendElement(NULL, list, NewLongObj(*p,
			    va_arg(argList, long)));
		    break;
		case 2:
		    Tcl_ListObjAppendElement(NULL, list, Tcl_NewWideIntObj(
		    Tcl_ListObjAppendElement(NULL, list, NewWideIntObj(*p,
			    va_arg(argList, Tcl_WideInt)));
		    break;
		case 3:
		    Tcl_ListObjAppendElement(NULL, list, Tcl_NewBignumObj(
			    va_arg(argList, mp_int *)));
		    break;
		}
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
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







-
+



-
+
















-
-
+
+


-
+








-
+




+
-
+
+

-
+
-




-
-
+
+



-
+









-
+
+


-
+
+



+







+
-
+


-
-
+
+
+









+







-
+













+
-
+



-
+

-
+








-
+









-
+


+
-
+


-
+

-
+







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

char *
TclGetStringStorage(
    Tcl_Obj *objPtr,
    size_t *sizePtr)
    Tcl_Size *sizePtr)
{
    String *stringPtr;

    if (!TclHasIntRep(objPtr, &tclStringType) || objPtr->bytes == NULL) {
    if (!TclHasInternalRep(objPtr, &tclStringType) || objPtr->bytes == NULL) {
	return TclGetStringFromObj(objPtr, sizePtr);
    }

    stringPtr = GET_STRING(objPtr);
    *sizePtr = stringPtr->allocated;
    return objPtr->bytes;
}

/*
 *---------------------------------------------------------------------------
 *
 * TclStringRepeat --
 *
 *	Performs the [string repeat] function.
 *
 * Results:
 * 	A (Tcl_Obj *) pointing to the result value, or NULL in case of an
 * 	error.
 *	A (Tcl_Obj *) pointing to the result value, or NULL in case of an
 *	error.
 *
 * Side effects:
 * 	On error, when interp is not NULL, error information is left in it.
 *	On error, when interp is not NULL, error information is left in it.
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclStringRepeat(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    size_t count,
    Tcl_Size count,
    int flags)
{
    Tcl_Obj *objResultPtr;
    int inPlace = flags & TCL_STRING_IN_PLACE;
    Tcl_Size length = 0;
    size_t length = 0, unichar = 0, done = 1;
    int unichar = 0;
    Tcl_Size done = 1;
    int binary = TclIsPureByteArray(objPtr);

    Tcl_Size maxCount;
    /* assert (count >= 2) */

    /*
     * Analyze to determine what representation result should be.
     * GOALS:	Avoid shimmering & string rep generation.
     * 		Produce pure bytearray when possible.
     * 		Error on overflow.
     *		Produce pure bytearray when possible.
     *		Error on overflow.
     */

    if (!binary) {
	if (TclHasIntRep(objPtr, &tclStringType)) {
	if (TclHasInternalRep(objPtr, &tclStringType)) {
	    String *stringPtr = GET_STRING(objPtr);
	    if (stringPtr->hasUnicode) {
		unichar = 1;
	    }
	}
    }

    if (binary) {
	/* Result will be pure byte array. Pre-size it */
	(void)TclGetByteArrayFromObj(objPtr, &length);
	(void)Tcl_GetBytesFromObj(NULL, objPtr, &length);
	maxCount = TCL_SIZE_MAX;
    } else if (unichar) {
	/* Result will be pure Tcl_UniChar array. Pre-size it. */
	(void)TclGetUnicodeFromObj(objPtr, &length);
	(void)Tcl_GetUnicodeFromObj(objPtr, &length);
	maxCount = TCL_SIZE_MAX/sizeof(Tcl_UniChar);
    } else {
	/* Result will be concat of string reps. Pre-size it. */
	(void)TclGetStringFromObj(objPtr, &length);
	maxCount = TCL_SIZE_MAX;
    }

    if (length == 0) {
	/* Any repeats of empty is empty. */
	return objPtr;
    }

    /* maxCount includes space for null */
    if (count > INT_MAX/length) {
    if (count > (maxCount-1)) {
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "max size for a Tcl value (%d bytes) exceeded", INT_MAX));
	    Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
		    "max size for a Tcl value (%" TCL_SIZE_MODIFIER
		    "d bytes) exceeded", TCL_SIZE_MAX));
	    Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
	}
	return NULL;
    }

    if (binary) {
	/* Efficiently produce a pure byte array result */
	objResultPtr = (!inPlace || Tcl_IsShared(objPtr)) ?
		Tcl_DuplicateObj(objPtr) : objPtr;

	/* Allocate count*length space */
	Tcl_SetByteArrayLength(objResultPtr, count*length); /* PANIC? */
	Tcl_SetByteArrayLength(objResultPtr, length);
	while (count - done > done) {
	    Tcl_AppendObjToObj(objResultPtr, objResultPtr);
	    done *= 2;
	}
	TclAppendBytesToByteArray(objResultPtr,
		Tcl_GetByteArrayFromObj(objResultPtr, NULL),
		Tcl_GetBytesFromObj(NULL, objResultPtr, (Tcl_Size *) NULL),
		(count - done) * length);
    } else if (unichar) {
	/*
	 * Efficiently produce a pure Tcl_UniChar array result.
	 */

	if (!inPlace || Tcl_IsShared(objPtr)) {
	    objResultPtr = Tcl_NewUnicodeObj(Tcl_GetUnicode(objPtr), length);
	} else {
	    TclInvalidateStringRep(objPtr);
	    objResultPtr = objPtr;
	}

	/* TODO - overflow check */
        if (0 == Tcl_AttemptSetObjLength(objResultPtr, count*length)) {
	if (0 == Tcl_AttemptSetObjLength(objResultPtr, count*length)) {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"string size overflow: unable to alloc %"
			TCL_Z_MODIFIER "u bytes",
			TCL_SIZE_MODIFIER "d bytes",
			STRING_SIZE(count*length)));
		Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
		Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
	    }
	    return NULL;
	}
	Tcl_SetObjLength(objResultPtr, length);
	while (count - done > done) {
	    Tcl_AppendObjToObj(objResultPtr, objResultPtr);
	    done *= 2;
	}
	TclAppendUnicodeToObj(objResultPtr, Tcl_GetUnicode(objResultPtr),
	Tcl_AppendUnicodeToObj(objResultPtr, Tcl_GetUnicode(objResultPtr),
		(count - done) * length);
    } else {
	/*
	 * Efficiently concatenate string reps.
	 */

	if (!inPlace || Tcl_IsShared(objPtr)) {
	    objResultPtr = Tcl_NewStringObj(TclGetString(objPtr), length);
	} else {
	    TclFreeIntRep(objPtr);
	    TclFreeInternalRep(objPtr);
	    objResultPtr = objPtr;
	}
	/* TODO - overflow check */
        if (0 == Tcl_AttemptSetObjLength(objResultPtr, count*length)) {
	if (0 == Tcl_AttemptSetObjLength(objResultPtr, count*length)) {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"string size overflow: unable to alloc %" TCL_Z_MODIFIER "u bytes",
			"string size overflow: unable to alloc %" TCL_SIZE_MODIFIER "d bytes",
			count*length));
		Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
		Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
	    }
	    return NULL;
	}
	Tcl_SetObjLength(objResultPtr, length);
	while (count - done > done) {
	    Tcl_AppendObjToObj(objResultPtr, objResultPtr);
	    done *= 2;
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
3128
3129
3130
3131
3132
3133
3134


3135
3136
3137
3138

3139
3140
3141
3142
3143
3144
3145
3146

3147
3148
3149
3150
3151






3152
3153
3154
3155
3156
3157
3158







3159
3160
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
3199

3200

3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215

3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228

3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242

3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253

3254
3255

3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280



3281
3282

3283
3284
3285
3286
3287

3288
3289
3290
3291
3292


3293
3294
3295


3296
3297
3298
3299
3300
3301

3302


3303
3304
3305
3306
3307
3308
3309







-
-
+
+


-
+







-
+




-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-




-
-
+
+
















-
-
+
+
+
+





-

-
+














-
+












-
+





+
+
+





-
+










-
+

-
+




+
+
+

















-
-
-


-
+
+



-
+




-
-
+
+

-
-
+
+




-
+
-
-







 *---------------------------------------------------------------------------
 *
 * TclStringCat --
 *
 *	Performs the [string cat] function.
 *
 * Results:
 * 	A (Tcl_Obj *) pointing to the result value, or NULL in case of an
 * 	error.
 *	A (Tcl_Obj *) pointing to the result value, or NULL in case of an
 *	error.
 *
 * Side effects:
 * 	On error, when interp is not NULL, error information is left in it.
 *	On error, when interp is not NULL, error information is left in it.
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclStringCat(
    Tcl_Interp *interp,
    int objc,
    Tcl_Size objc,
    Tcl_Obj * const objv[],
    int flags)
{
    Tcl_Obj *objResultPtr, * const *ov;
    int oc, binary = 1;
	size_t length = 0;
    int allowUniChar = 1, requestUniChar = 0;
    int first = objc - 1;	/* Index of first value possibly not empty */
    int last = 0;		/* Index of last value possibly not empty */
    int inPlace = flags & TCL_STRING_IN_PLACE;
    int binary = 1;
    Tcl_Size oc, length = 0;
    int allowUniChar = 1, requestUniChar = 0, forceUniChar = 0;
    Tcl_Size first = objc - 1;	/* Index of first value possibly not empty */
    Tcl_Size last = 0;		/* Index of last value possibly not empty */
    int inPlace = (flags & TCL_STRING_IN_PLACE) && !Tcl_IsShared(*objv);

    /* assert ( objc >= 0 ) */

    if (objc <= 1) {
	/* Only one or no objects; return first or empty */
	return objc ? objv[0] : Tcl_NewObj();
    }

    if (objc <= 1) {
	if (objc != 1) {
	    /* Negative (shouldn't be) no objects; return empty */
	    Tcl_Obj *obj;
	    TclNewObj(obj);
	    return obj;
	}
	/* One object; return first */
	return objv[0];
    }
    /* assert ( objc >= 2 ) */

    /*
     * Analyze to determine what representation result should be.
     * GOALS:	Avoid shimmering & string rep generation.
     * 		Produce pure bytearray when possible.
     * 		Error on overflow.
     *		Produce pure bytearray when possible.
     *		Error on overflow.
     */

    ov = objv, oc = objc;
    do {
	Tcl_Obj *objPtr = *ov++;

	if (TclIsPureByteArray(objPtr)) {
	    allowUniChar = 0;
	} else if (objPtr->bytes) {
	    /* Value has a string rep. */
	    if (objPtr->length) {
		/*
		 * Non-empty string rep. Not a pure bytearray, so we won't
		 * create a pure bytearray.
		 */

	 	binary = 0;
		if ((objPtr->typePtr) && (objPtr->typePtr != &tclStringType)) {
		binary = 0;
		if (ov > objv+1 && ISCONTINUATION(TclGetString(objPtr))) {
		    forceUniChar = 1;
		} else if ((objPtr->typePtr) && !TclHasInternalRep(objPtr, &tclStringType)) {
		    /* Prevent shimmer of non-string types. */
		    allowUniChar = 0;
		}
	    }
	} else {
	    /* assert (objPtr->typePtr != NULL) -- stork! */
	    binary = 0;
	    if (TclHasIntRep(objPtr, &tclStringType)) {
	    if (TclHasInternalRep(objPtr, &tclStringType)) {
		/* Have a pure Unicode value; ask to preserve it */
		requestUniChar = 1;
	    } else {
		/* Have another type; prevent shimmer */
		allowUniChar = 0;
	    }
	}
    } while (--oc && (binary || allowUniChar));

    if (binary) {
	/*
	 * Result will be pure byte array. Pre-size it
	 */

	size_t numBytes = 0;
	Tcl_Size numBytes = 0;
	ov = objv;
	oc = objc;
	do {
	    Tcl_Obj *objPtr = *ov++;

	    /*
	     * Every argument is either a bytearray with a ("pure")
	     * value we know we can safely use, or it is an empty string.
	     * We don't need to count bytes for the empty strings.
	     */

	    if (TclIsPureByteArray(objPtr)) {
		(void)TclGetByteArrayFromObj(objPtr, &numBytes); /* PANIC? */
		(void)Tcl_GetBytesFromObj(NULL, objPtr, &numBytes); /* PANIC? */

		if (numBytes) {
		    last = objc - oc;
		    if (length == 0) {
			first = last;
		    }
		    if (length > (TCL_SIZE_MAX-numBytes)) {
			goto overflow;
		    }
		    length += numBytes;
		}
	    }
	} while (--oc);
    } else if (allowUniChar && requestUniChar) {
    } else if ((allowUniChar && requestUniChar) || forceUniChar) {
	/*
	 * Result will be pure Tcl_UniChar array. Pre-size it.
	 */

	ov = objv;
	oc = objc;
	do {
	    Tcl_Obj *objPtr = *ov++;

	    if ((objPtr->bytes == NULL) || (objPtr->length)) {
		size_t numChars;
		Tcl_Size numChars;

		(void)TclGetUnicodeFromObj(objPtr, &numChars); /* PANIC? */
		(void)Tcl_GetUnicodeFromObj(objPtr, &numChars); /* PANIC? */
		if (numChars) {
		    last = objc - oc;
		    if (length == 0) {
			first = last;
		    }
		    if (length > (Tcl_Size) ((TCL_SIZE_MAX/sizeof(Tcl_UniChar))-numChars)) {
			goto overflow;
		    }
		    length += numChars;
		}
	    }
	} while (--oc);
    } else {
	/* Result will be concat of string reps. Pre-size it. */
	ov = objv; oc = objc;
	do {
	    Tcl_Obj *pendingPtr = NULL;

	    /*
	     * Loop until a possibly non-empty value is reached.
	     * Keep string rep generation pending when possible.
	     */

	    do {
		/* assert ( pendingPtr == NULL ) */
		/* assert ( length == 0 ) */

		Tcl_Obj *objPtr = *ov++;

		if (objPtr->bytes == NULL) {
		if (objPtr->bytes == NULL
			&& TclCheckEmptyString(objPtr) != TCL_EMPTYSTRING_YES) {
		    /* No string rep; Take the chance we can avoid making it */
		    pendingPtr = objPtr;
		} else {
		    (void)TclGetStringFromObj(objPtr, &length); /* PANIC? */
		    (void) TclGetStringFromObj(objPtr, &length); /* PANIC? */
		}
	    } while (--oc && (length == 0) && (pendingPtr == NULL));

	    /*
 	     * Either we found a possibly non-empty value, and we remember
 	     * this index as the first and last such value so far seen,
	     * Either we found a possibly non-empty value, and we remember
	     * this index as the first and last such value so far seen,
	     * or (oc == 0) and all values are known empty,
 	     * so first = last = objc - 1 signals the right quick return.
 	     */
	     * so first = last = objc - 1 signals the right quick return.
	     */

	    first = last = objc - oc - 1;

	    if (oc && (length == 0)) {
		size_t numBytes;
		Tcl_Size numBytes;

		/* assert ( pendingPtr != NULL ) */

		/*
		 * There's a pending value followed by more values.  Loop over
		 * remaining values generating strings until a non-empty value
		 * is found, or the pending value gets its string generated.
		 */

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
3134


3135
3136
3137
3138
3139

3140
3141
3142
3143
3144


3145
3146
3147
3148
3149

3150
3151
3152
3153
3154

3155
3156
3157

3158
3159
3160
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
3199
3200
3201
3202
3203

3204
3205

3206
3207
3208
3209
3210
3211
3212

3213
3214
3215
3216
3217
3218
3219

3220
3221

3222
3223
3224
3225
3226
3227
3228
3229
3230
3231

3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247



3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267















































































































3268
3269
3270
3271
3272
3273
3274


3275
3276

3277
3278

3279
3280
3281
3282
3283

3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297


3298
3299
3300


3301
3302
3303
3304
3305




3306
3307
3308
3309
3310
3311



3312
3313
3314
3315
3316
3317
3318


3319
3320
3321
3322
3323
3324
3325
3326

3327
3328
3329
3330
3331
3332
3333
3334



3335
3336

3337
3338
3339
3340
3341
3342
3343
3344
3345

3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360

3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376

3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394


3395
3396
3397
3398

3399
3400
3401
3402
3403




3404
3405

3406
3407
3408


3409
3410
3411
3412
3413
3414
3415
3416

3417
3418
3419
3420
3421
3422
3423
3318
3319
3320
3321
3322
3323
3324

3325
3326
3327
3328
3329
3330
3331
3332

3333
3334
3335


3336
3337
3338
3339

3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366


3367
3368
3369
3370

3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386


3387
3388
3389
3390
3391
3392

3393
3394
3395
3396


3397
3398
3399
3400
3401
3402

3403
3404
3405
3406
3407

3408
3409
3410

3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424

3425
3426
3427

3428
3429
3430
3431
3432
3433
3434
3435
3436
3437


3438
3439
3440
3441
3442
3443
3444
3445
3446
3447


3448
3449
3450
3451
3452
3453
3454
3455
3456

3457
3458

3459
3460
3461
3462
3463
3464


3465
3466
3467
3468
3469
3470
3471

3472
3473

3474
3475
3476
3477
3478
3479
3480
3481
3482
3483

3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498


3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638

3639
3640
3641

3642
3643

3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662


3663
3664
3665


3666
3667
3668




3669
3670
3671
3672
3673
3674
3675



3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694

3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707

3708
3709
3710
3711
3712
3713
3714
3715
3716

3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731

3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747

3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764


3765
3766
3767
3768
3769

3770

3771
3772
3773
3774
3775
3776
3777
3778
3779

3780
3781


3782
3783
3784
3785
3786
3787
3788
3789
3790

3791
3792
3793
3794
3795
3796
3797
3798







-
+







-
+


-
-




-
+















+










-
-
+
+


-
+















-
-
+
+




-
+



-
-
+
+




-
+




-
+


-
+













-
+


-
+









-
-
+
+








-
-
+
+







-
+

-
+





-
-
+






-
+

-
+









-
+














-
-
+
+
+




















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+
+

-
+

-
+





+












-
-
+
+

-
-
+
+

-
-
-
-
+
+
+
+



-
-
-
+
+
+







+
+







-
+








+
+
+

-
+








-
+














-
+















-
+
















-
-
+
+



-
+
-




+
+
+
+

-
+

-
-
+
+







-
+







		if (oc || numBytes) {
		    (void)TclGetStringFromObj(pendingPtr, &length);
		}
		if (length == 0) {
		    if (numBytes) {
			first = last;
		    }
		} else if (numBytes + length > (size_t)INT_MAX) {
		} else if (numBytes > (TCL_SIZE_MAX - length)) {
		    goto overflow;
		}
		length += numBytes;
	    }
	} while (oc && (length == 0));

	while (oc) {
	    size_t numBytes;
	    Tcl_Size numBytes;
	    Tcl_Obj *objPtr = *ov++;

	    /* assert ( length > 0 && pendingPtr == NULL )  */

	    TclGetString(objPtr); /* PANIC? */
	    numBytes = objPtr->length;
	    if (numBytes) {
		last = objc - oc;
		if (numBytes + length > (size_t)INT_MAX) {
		if (numBytes > (TCL_SIZE_MAX - length)) {
		    goto overflow;
		}
		length += numBytes;
	    }
	    --oc;
	}
    }

    if (last <= first /*|| length == 0 */) {
	/* Only one non-empty value or zero length; return first */
	/* NOTE: (length == 0) implies (last <= first) */
	return objv[first];
    }

    objv += first; objc = (last - first + 1);
    inPlace = (flags & TCL_STRING_IN_PLACE) && !Tcl_IsShared(*objv);

    if (binary) {
	/* Efficiently produce a pure byte array result */
	unsigned char *dst;

	/*
	 * Broken interface! Byte array value routines offer no way to handle
	 * failure to allocate enough space. Following stanza may panic.
	 */

	if (inPlace && !Tcl_IsShared(*objv)) {
	    size_t start = 0;
	if (inPlace) {
	    Tcl_Size start = 0;

	    objResultPtr = *objv++; objc--;
	    (void)TclGetByteArrayFromObj(objResultPtr, &start);
	    (void)Tcl_GetBytesFromObj(NULL, objResultPtr, &start);
	    dst = Tcl_SetByteArrayLength(objResultPtr, length) + start;
	} else {
	    objResultPtr = Tcl_NewByteArrayObj(NULL, length);
	    dst = Tcl_SetByteArrayLength(objResultPtr, length);
	}
	while (objc--) {
	    Tcl_Obj *objPtr = *objv++;

	    /*
	     * Every argument is either a bytearray with a ("pure")
	     * value we know we can safely use, or it is an empty string.
	     * We don't need to copy bytes from the empty strings.
	     */

	    if (TclIsPureByteArray(objPtr)) {
		size_t more = 0;
		unsigned char *src = TclGetByteArrayFromObj(objPtr, &more);
		Tcl_Size more = 0;
		unsigned char *src = Tcl_GetBytesFromObj(NULL, objPtr, &more);
		memcpy(dst, src, more);
		dst += more;
	    }
	}
    } else if (allowUniChar && requestUniChar) {
    } else if ((allowUniChar && requestUniChar) || forceUniChar) {
	/* Efficiently produce a pure Tcl_UniChar array result */
	Tcl_UniChar *dst;

	if (inPlace && !Tcl_IsShared(*objv)) {
	    size_t start;
	if (inPlace) {
	    Tcl_Size start;

	    objResultPtr = *objv++; objc--;

	    /* Ugly interface! Force resize of the unicode array. */
	    (void)TclGetUnicodeFromObj(objResultPtr, &start);
	    (void)Tcl_GetUnicodeFromObj(objResultPtr, &start);
	    Tcl_InvalidateStringRep(objResultPtr);
	    if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) {
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    	"concatenation failed: unable to alloc %"
			"concatenation failed: unable to alloc %"
			TCL_Z_MODIFIER "u bytes",
			STRING_SIZE(length)));
		    Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
		    Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
		}
		return NULL;
	    }
	    dst = Tcl_GetUnicode(objResultPtr) + start;
	} else {
	    Tcl_UniChar ch = 0;

	    /* Ugly interface! No scheme to init array size. */
	    objResultPtr = Tcl_NewUnicodeObj(&ch, 0);	/* PANIC? */
	    if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) {
		Tcl_DecrRefCount(objResultPtr);
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    	"concatenation failed: unable to alloc %"
			"concatenation failed: unable to alloc %"
			TCL_Z_MODIFIER "u bytes",
			STRING_SIZE(length)));
		    Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
		    Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
		}
		return NULL;
	    }
	    dst = Tcl_GetUnicode(objResultPtr);
	}
	while (objc--) {
	    Tcl_Obj *objPtr = *objv++;

	    if ((objPtr->bytes == NULL) || (objPtr->length)) {
		size_t more;
		Tcl_UniChar *src = TclGetUnicodeFromObj(objPtr, &more);
		Tcl_Size more;
		Tcl_UniChar *src = Tcl_GetUnicodeFromObj(objPtr, &more);
		memcpy(dst, src, more * sizeof(Tcl_UniChar));
		dst += more;
	    }
	}
    } else {
	/* Efficiently concatenate string reps */
	char *dst;

	if (inPlace && !Tcl_IsShared(*objv)) {
	    size_t start;
	if (inPlace) {
	    Tcl_Size start;

	    objResultPtr = *objv++; objc--;

	    (void)TclGetStringFromObj(objResultPtr, &start);
	    if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) {
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    	"concatenation failed: unable to alloc %" TCL_Z_MODIFIER "u bytes",
			"concatenation failed: unable to alloc %" TCL_SIZE_MODIFIER "d bytes",
			length));
		    Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
		    Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
		}
		return NULL;
	    }
	    dst = TclGetString(objResultPtr) + start;

	    /* assert ( length > start ) */
	    TclFreeIntRep(objResultPtr);
	    TclFreeInternalRep(objResultPtr);
	} else {
	    TclNewObj(objResultPtr);	/* PANIC? */
	    if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) {
		Tcl_DecrRefCount(objResultPtr);
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    	"concatenation failed: unable to alloc %" TCL_Z_MODIFIER "u bytes",
			"concatenation failed: unable to alloc %" TCL_SIZE_MODIFIER "d bytes",
			length));
		    Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
		    Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
		}
		return NULL;
	    }
	    dst = TclGetString(objResultPtr);
	}
	while (objc--) {
	    Tcl_Obj *objPtr = *objv++;

	    if ((objPtr->bytes == NULL) || (objPtr->length)) {
		size_t more;
		Tcl_Size more;
		char *src = TclGetStringFromObj(objPtr, &more);

		memcpy(dst, src, more);
		dst += more;
	    }
	}
	/* Must NUL-terminate! */
	*dst = '\0';
    }
    return objResultPtr;

  overflow:
    if (interp) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "max size for a Tcl value (%d bytes) exceeded", INT_MAX));
	Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
		"max size for a Tcl value (%" TCL_SIZE_MODIFIER
		"d bytes) exceeded", TCL_SIZE_MAX));
	Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
    }
    return NULL;
}

/*
 *---------------------------------------------------------------------------
 *
 * TclStringCmp --
 *	Compare two Tcl_Obj values as strings.
 *
 * Results:
 *	Like memcmp, return -1, 0, or 1.
 *
 * Side effects:
 *	String representations may be generated.  Internal representation may
 *	be changed.
 *
 *---------------------------------------------------------------------------
 */

static int
UniCharNcasememcmp(
    const void *ucsPtr,		/* Unicode string to compare to uct. */
    const void *uctPtr,		/* Unicode string ucs is compared to. */
    size_t numChars)		/* Number of Unichars to compare. */
{
    const Tcl_UniChar *ucs = (const Tcl_UniChar *)ucsPtr;
    const Tcl_UniChar *uct = (const Tcl_UniChar *)uctPtr;
    for ( ; numChars != 0; numChars--, ucs++, uct++) {
	if (*ucs != *uct) {
	    Tcl_UniChar lcs = Tcl_UniCharToLower(*ucs);
	    Tcl_UniChar lct = Tcl_UniCharToLower(*uct);

	    if (lcs != lct) {
		return (lcs - lct);
	    }
	}
    }
    return 0;
}

static int
UtfNmemcmp(
    const void *csPtr,		/* UTF string to compare to ct. */
    const void *ctPtr,		/* UTF string cs is compared to. */
    size_t numChars)		/* Number of UTF chars to compare. */
{
    Tcl_UniChar ch1 = 0, ch2 = 0;
    const char *cs = (const char *)csPtr;
    const char *ct = (const char *)ctPtr;

    /*
     * Cannot use 'memcmp(cs, ct, n);' as byte representation of \u0000 (the
     * pair of bytes 0xC0,0x80) is larger than byte representation of \u0001
     * (the byte 0x01.)
     */

    while (numChars-- > 0) {
	/*
	 * n must be interpreted as chars, not bytes. This should be called
	 * only when both strings are of at least n chars long (no need for \0
	 * check)
	 */

	cs += TclUtfToUniChar(cs, &ch1);
	ct += TclUtfToUniChar(ct, &ch2);
	if (ch1 != ch2) {
	    return (ch1 - ch2);
	}
    }
    return 0;
}

static int
UtfNcasememcmp(
    const void *csPtr,		/* UTF string to compare to ct. */
    const void *ctPtr,		/* UTF string cs is compared to. */
    size_t numChars)		/* Number of UTF chars to compare. */
{
    Tcl_UniChar ch1 = 0, ch2 = 0;
    const char *cs = (const char *)csPtr;
    const char *ct = (const char *)ctPtr;

    while (numChars-- > 0) {
	/*
	 * n must be interpreted as chars, not bytes.
	 * This should be called only when both strings are of
	 * at least n chars long (no need for \0 check)
	 */
	cs += TclUtfToUniChar(cs, &ch1);
	ct += TclUtfToUniChar(ct, &ch2);
	if (ch1 != ch2) {
	    ch1 = Tcl_UniCharToLower(ch1);
	    ch2 = Tcl_UniCharToLower(ch2);
	    if (ch1 != ch2) {
		return (ch1 - ch2);
	    }
	}
    }
    return 0;
}

static int
UniCharNmemcmp(
    const void *ucsPtr,		/* Unicode string to compare to uct. */
    const void *uctPtr,		/* Unicode string ucs is compared to. */
    size_t numChars)		/* Number of unichars to compare. */
{
    const Tcl_UniChar *ucs = (const Tcl_UniChar *)ucsPtr;
    const Tcl_UniChar *uct = (const Tcl_UniChar *)uctPtr;
#if defined(WORDS_BIGENDIAN)
    /*
     * We are definitely on a big-endian machine; memcmp() is safe
     */

    return memcmp(ucs, uct, numChars*sizeof(Tcl_UniChar));

#else /* !WORDS_BIGENDIAN */
    /*
     * We can't simply call memcmp() because that is not lexically correct.
     */

    for ( ; numChars != 0; ucs++, uct++, numChars--) {
	if (*ucs != *uct) {
	    return (*ucs - *uct);
	}
    }
    return 0;
#endif /* WORDS_BIGENDIAN */
}

int
TclStringCmp(
    Tcl_Obj *value1Ptr,
    Tcl_Obj *value2Ptr,
    int checkEq,		/* comparison is only for equality */
    int nocase,			/* comparison is not case sensitive */
    size_t reqlength)		/* requested length */
    Tcl_Size reqlength)		/* requested length in characters;
				 * TCL_INDEX_NONE to compare whole strings */
{
    char *s1, *s2;
    const char *s1, *s2;
    int empty, match;
    size_t length, s1len = 0, s2len = 0;
    Tcl_Size length, s1len = 0, s2len = 0;
    memCmpFn_t memCmpFn;

    if ((reqlength == 0) || (value1Ptr == value2Ptr)) {
	/*
	 * Always match at 0 chars of if it is the same obj.
	 * Note: as documented reqlength negative means it is ignored
	 */
	match = 0;
    } else {
	if (!nocase && TclIsPureByteArray(value1Ptr)
		&& TclIsPureByteArray(value2Ptr)) {
	    /*
	     * Use binary versions of comparisons since that won't cause undue
	     * type conversions and it is much faster. Only do this if we're
	     * case-sensitive (which is all that really makes sense with byte
	     * arrays anyway, and we have no memcasecmp() for some reason... :^)
	     */

	    s1 = (char *) TclGetByteArrayFromObj(value1Ptr, &s1len);
	    s2 = (char *) TclGetByteArrayFromObj(value2Ptr, &s2len);
	    s1 = (char *) Tcl_GetBytesFromObj(NULL, value1Ptr, &s1len);
	    s2 = (char *) Tcl_GetBytesFromObj(NULL, value2Ptr, &s2len);
	    memCmpFn = memcmp;
	} else if (TclHasIntRep(value1Ptr, &tclStringType)
		&& TclHasIntRep(value2Ptr, &tclStringType)) {
	} else if (TclHasInternalRep(value1Ptr, &tclStringType)
		&& TclHasInternalRep(value2Ptr, &tclStringType)) {
	    /*
	     * Do a unicode-specific comparison if both of the args are of
	     * String type. If the char length == byte length, we can do a
	     * memcmp. In benchmark testing this proved the most efficient
	     * check between the unicode and string comparison operations.
	     * Do a Unicode-specific comparison if both of the args are of String
	     * type. If the char length == byte length, we can do a memcmp. In
	     * benchmark testing this proved the most efficient check between the
	     * Unicode and string comparison operations.
	     */

	    if (nocase) {
		s1 = (char *) TclGetUnicodeFromObj(value1Ptr, &s1len);
		s2 = (char *) TclGetUnicodeFromObj(value2Ptr, &s2len);
		memCmpFn = (memCmpFn_t)TclUniCharNcasecmp;
		s1 = (char *) Tcl_GetUnicodeFromObj(value1Ptr, &s1len);
		s2 = (char *) Tcl_GetUnicodeFromObj(value2Ptr, &s2len);
		memCmpFn = UniCharNcasememcmp;
	    } else {
		s1len = Tcl_GetCharLength(value1Ptr);
		s2len = Tcl_GetCharLength(value2Ptr);
		if ((s1len == value1Ptr->length)
			&& (value1Ptr->bytes != NULL)
			&& (s2len == value2Ptr->length)
			&& (value2Ptr->bytes != NULL)) {
			/* each byte represents one character so s1l3n, s2l3n,
			 * and reqlength are in both bytes and characters */
		    s1 = value1Ptr->bytes;
		    s2 = value2Ptr->bytes;
		    memCmpFn = memcmp;
		} else {
		    s1 = (char *) Tcl_GetUnicode(value1Ptr);
		    s2 = (char *) Tcl_GetUnicode(value2Ptr);
		    if (
#ifdef WORDS_BIGENDIAN
#if defined(WORDS_BIGENDIAN)
			    1
#else
			    checkEq
#endif
			    ) {
			memCmpFn = memcmp;
			s1len *= sizeof(Tcl_UniChar);
			s2len *= sizeof(Tcl_UniChar);
			if (reqlength > 0) {
			    reqlength *= sizeof(Tcl_UniChar);
			}
		    } else {
			memCmpFn = (memCmpFn_t) TclUniCharNcmp;
			memCmpFn = UniCharNmemcmp;
		    }
		}
	    }
	} else {
	    empty = TclCheckEmptyString(value1Ptr);
	    if (empty > 0) {
		switch (TclCheckEmptyString(value2Ptr)) {
		case -1:
		    s1 = 0;
		    s1 = "";
		    s1len = 0;
		    s2 = TclGetStringFromObj(value2Ptr, &s2len);
		    break;
		case 0:
		    match = -1;
		    goto matchdone;
		case 1:
		default: /* avoid warn: `s2` may be used uninitialized */
		    match = 0;
		    goto matchdone;
		}
	    } else if (TclCheckEmptyString(value2Ptr) > 0) {
		switch (empty) {
		case -1:
		    s2 = 0;
		    s2 = "";
		    s2len = 0;
		    s1 = TclGetStringFromObj(value1Ptr, &s1len);
		    break;
		case 0:
		    match = 1;
		    goto matchdone;
		case 1:
		default: /* avoid warn: `s1` may be used uninitialized */
		    match = 0;
		    goto matchdone;
		}
	    } else {
		s1 = TclGetStringFromObj(value1Ptr, &s1len);
		s2 = TclGetStringFromObj(value2Ptr, &s2len);
	    }
	    if (!nocase && checkEq) {
	    if (!nocase && checkEq && reqlength < 0) {
		/*
		 * When we have equal-length we can check only for
		 * (in)equality. We can use memcmp in all (n)eq cases because
		 * we don't need to worry about lexical LE/BE variance.
		 */

		memCmpFn = memcmp;
	    } else {
		/*
		 * As a catch-all we will work with UTF-8. We cannot use
		 * memcmp() as that is unsafe with any string containing NUL
		 * (\xC0\x80 in Tcl's utf rep). We can use the more efficient
		 * TclpUtfNcmp2 if we are case-sensitive and no specific
		 * length was requested.
		 */

		if ((reqlength == TCL_INDEX_NONE) && !nocase) {
		    memCmpFn = (memCmpFn_t) TclpUtfNcmp2;
		if ((reqlength < 0) && !nocase) {
		    memCmpFn = TclpUtfNcmp2;
		} else {
		    s1len = Tcl_NumUtfChars(s1, s1len);
		    s2len = Tcl_NumUtfChars(s2, s2len);
		    memCmpFn = (memCmpFn_t)
		    memCmpFn = nocase ? UtfNcasememcmp : UtfNmemcmp;
			    (nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp);
		}
	    }
	}

	/* At this point s1len, s2len, and reqlength should by now have been
	 * adjusted so that they are all in the units expected by the selected
	 * comparison function.
	 */
	length = (s1len < s2len) ? s1len : s2len;
	if (reqlength == TCL_INDEX_NONE) {
	if (reqlength < 0) {
	    /*
	     * The requested length is negative, so we ignore it by setting it
	     * to length + 1 so we correct the match var.
	     * The requested length is negative, so ignore it by setting it
	     * to length + 1 to correct the match var.
	     */

	    reqlength = length + 1;
	} else if (reqlength > 0 && reqlength < length) {
	    length = reqlength;
	}

	if (checkEq && (s1len != s2len)) {
	if (checkEq && reqlength < 0 && (s1len != s2len)) {
	    match = 1;		/* This will be reversed below. */
	} else {
	    /*
	     * The comparison function should compare up to the minimum byte
	     * length only.
	     */

3450
3451
3452
3453
3454
3455
3456
3457

3458
3459
3460


3461
3462
3463
3464

3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476

3477
3478
3479

3480
3481
3482
3483
3484
3485
3486
3825
3826
3827
3828
3829
3830
3831

3832
3833


3834
3835
3836
3837
3838

3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850

3851
3852
3853

3854
3855
3856
3857
3858
3859
3860
3861







-
+

-
-
+
+



-
+











-
+


-
+







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

Tcl_Obj *
TclStringFirst(
    Tcl_Obj *needle,
    Tcl_Obj *haystack,
    size_t start)
    Tcl_Size start)
{
    size_t lh = 0, ln = Tcl_GetCharLength(needle);
    size_t value = TCL_INDEX_NONE;
    Tcl_Size lh = 0, ln = Tcl_GetCharLength(needle);
    Tcl_Size value = -1;
    Tcl_UniChar *checkStr, *endStr, *uh, *un;
    Tcl_Obj *obj;

    if (start == TCL_INDEX_NONE) {
    if (start < 0) {
	start = 0;
    }
    if (ln == 0) {
	/* We don't find empty substrings.  Bizarre!
	 * Whenever this routine is turned into a proper substring
	 * finder, change to `return start` after limits imposed. */
	goto firstEnd;
    }

    if (TclIsPureByteArray(needle) && TclIsPureByteArray(haystack)) {
	unsigned char *end, *check, *bh;
	unsigned char *bn = TclGetByteArrayFromObj(needle, &ln);
	unsigned char *bn = Tcl_GetBytesFromObj(NULL, needle, &ln);

	/* Find bytes in bytes */
	bh = TclGetByteArrayFromObj(haystack, &lh);
	bh = Tcl_GetBytesFromObj(NULL, haystack, &lh);
	if ((lh < ln) || (start > lh - ln)) {
	    /* Don't start the loop if there cannot be a valid answer */
	    goto firstEnd;
	}
	end = bh + lh;

	check = bh + start;
3515
3516
3517
3518
3519
3520
3521
3522
3523


3524
3525
3526
3527
3528
3529
3530
3890
3891
3892
3893
3894
3895
3896


3897
3898
3899
3900
3901
3902
3903
3904
3905







-
-
+
+







     * code pathway, or if it does we want that to be for some values
     * we explicitly decline to support.  Getting there will involve
     * locking down in practice more firmly just what encodings produce
     * what supported results for the objPtr->bytes values.  For now,
     * do only the well-defined Tcl_UniChar array search.
     */

    un = TclGetUnicodeFromObj(needle, &ln);
    uh = TclGetUnicodeFromObj(haystack, &lh);
    un = Tcl_GetUnicodeFromObj(needle, &ln);
    uh = Tcl_GetUnicodeFromObj(haystack, &lh);
    if ((lh < ln) || (start > lh - ln)) {
	/* Don't start the loop if there cannot be a valid answer */
	goto firstEnd;
    }
    endStr = uh + lh;

    for (checkStr = uh + start; checkStr + ln <= endStr; checkStr++) {
3557
3558
3559
3560
3561
3562
3563
3564

3565
3566
3567


3568
3569
3570
3571
3572
3573

3574
3575
3576


3577
3578
3579
3580
3581
3582
3583


3584
3585

3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606


3607
3608

3609
3610
3611
3612
3613
3614
3615
3932
3933
3934
3935
3936
3937
3938

3939
3940


3941
3942
3943
3944
3945
3946
3947

3948
3949


3950
3951
3952
3953
3954
3955
3956


3957
3958
3959

3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979


3980
3981
3982

3983
3984
3985
3986
3987
3988
3989
3990







-
+

-
-
+
+





-
+

-
-
+
+





-
-
+
+

-
+



















-
-
+
+

-
+







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

Tcl_Obj *
TclStringLast(
    Tcl_Obj *needle,
    Tcl_Obj *haystack,
    size_t last)
    Tcl_Size last)
{
    size_t lh = 0, ln = Tcl_GetCharLength(needle);
    size_t value = TCL_INDEX_NONE;
    Tcl_Size lh = 0, ln = Tcl_GetCharLength(needle);
    Tcl_Size value = -1;
    Tcl_UniChar *checkStr, *uh, *un;
    Tcl_Obj *obj;

    if (ln == 0) {
	/*
	 * 	We don't find empty substrings.  Bizarre!
	 *	We don't find empty substrings.  Bizarre!
	 *
	 * 	TODO: When we one day make this a true substring
	 * 	finder, change this to "return last", after limitation.
	 *	TODO: When we one day make this a true substring
	 *	finder, change this to "return last", after limitation.
	 */
	goto lastEnd;
    }

    if (TclIsPureByteArray(needle) && TclIsPureByteArray(haystack)) {
	unsigned char *check, *bh = TclGetByteArrayFromObj(haystack, &lh);
	unsigned char *bn = TclGetByteArrayFromObj(needle, &ln);
	unsigned char *check, *bh = Tcl_GetBytesFromObj(NULL, haystack, &lh);
	unsigned char *bn = Tcl_GetBytesFromObj(NULL, needle, &ln);

	if (last + 1 >= lh + 1) {
	if (last >= lh) {
	    last = lh - 1;
	}
	if (last + 1 < ln) {
	    /* Don't start the loop if there cannot be a valid answer */
	    goto lastEnd;
	}
	check = bh + last + 1 - ln;

	while (check >= bh) {
	    if ((*check == bn[0])
		    && (0 == memcmp(check+1, bn+1, ln-1))) {
		value = (check - bh);
		goto lastEnd;
	    }
	    check--;
	}
	goto lastEnd;
    }

    uh = TclGetUnicodeFromObj(haystack, &lh);
    un = TclGetUnicodeFromObj(needle, &ln);
    uh = Tcl_GetUnicodeFromObj(haystack, &lh);
    un = Tcl_GetUnicodeFromObj(needle, &ln);

    if (last + 1 >= lh + 1) {
    if (last >= lh) {
	last = lh - 1;
    }
    if (last + 1 < ln) {
	/* Don't start the loop if there cannot be a valid answer */
	goto lastEnd;
    }
    checkStr = uh + last + 1 - ln;
3644
3645
3646
3647
3648
3649
3650
3651

3652
3653
3654
3655
3656
3657
3658
4019
4020
4021
4022
4023
4024
4025

4026
4027
4028
4029
4030
4031
4032
4033







-
+







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

static void
ReverseBytes(
    unsigned char *to,		/* Copy bytes into here... */
    unsigned char *from,	/* ...from here... */
    size_t count)		/* Until this many are copied, */
    Tcl_Size count)		/* Until this many are copied, */
				/* reversing as you go. */
{
    unsigned char *src = from + count;

    if (to == from) {
	/* Reversing in place */
	while (--src > to) {
3674
3675
3676
3677
3678
3679
3680
3681
3682


3683
3684
3685
3686
3687

3688
3689
3690
3691
3692
3693
3694
3695

3696
3697
3698
3699

3700

3701
3702
3703


3704
3705
3706
3707
3708

3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727


3728
3729
3730
3731
3732
3733
3734
3735
3736

3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747


3748
3749
3750
3751
3752
3753
3754
3755
3756

3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
4049
4050
4051
4052
4053
4054
4055


4056
4057
4058
4059
4060
4061

4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072



4073
4074
4075
4076


4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101


4102
4103
4104
4105
4106
4107
4108
4109
4110
4111

4112
4113
4114
4115
4116
4117
4118
4119
4120
4121


4122
4123
4124
4125
4126
4127
4128
4129
4130
4131

4132
4133
4134
4135
4136
4137
4138

4139
4140
4141

4142
4143
4144
4145
4146
4147
4148







-
-
+
+




-
+








+

-
-
-
+

+

-
-
+
+





+

















-
-
+
+








-
+









-
-
+
+








-
+






-



-







    int flags)
{
    String *stringPtr;
    Tcl_UniChar ch = 0;
    int inPlace = flags & TCL_STRING_IN_PLACE;

    if (TclIsPureByteArray(objPtr)) {
	size_t numBytes = 0;
	unsigned char *from = TclGetByteArrayFromObj(objPtr, &numBytes);
	Tcl_Size numBytes = 0;
	unsigned char *from = Tcl_GetBytesFromObj(NULL, objPtr, &numBytes);

	if (!inPlace || Tcl_IsShared(objPtr)) {
	    objPtr = Tcl_NewByteArrayObj(NULL, numBytes);
	}
	ReverseBytes(Tcl_GetByteArrayFromObj(objPtr, NULL), from, numBytes);
	ReverseBytes(Tcl_GetBytesFromObj(NULL, objPtr, (Tcl_Size *)NULL), from, numBytes);
	return objPtr;
    }

    SetStringFromAny(NULL, objPtr);
    stringPtr = GET_STRING(objPtr);

    if (stringPtr->hasUnicode) {
	Tcl_UniChar *from = Tcl_GetUnicode(objPtr);
	stringPtr = GET_STRING(objPtr);
	Tcl_UniChar *src = from + stringPtr->numChars;

	if (!inPlace || Tcl_IsShared(objPtr)) {
	    Tcl_UniChar *to;
	Tcl_UniChar *to;

	if (!inPlace || Tcl_IsShared(objPtr)) {
	    /*
	     * Create a non-empty, pure unicode value, so we can coax
	     * Tcl_SetObjLength into growing the unicode rep buffer.
	     * Create a non-empty, pure Unicode value, so we can coax
	     * Tcl_SetObjLength into growing the Unicode rep buffer.
	     */

	    objPtr = Tcl_NewUnicodeObj(&ch, 1);
	    Tcl_SetObjLength(objPtr, stringPtr->numChars);
	    to = Tcl_GetUnicode(objPtr);
	    stringPtr = GET_STRING(objPtr);
	    while (--src >= from) {
		*to++ = *src;
	    }
	} else {
	    /*
	     * Reversing in place.
	     */

	    while (--src > from) {
		ch = *src;
		*src = *from;
		*from++ = ch;
	    }
	}
    }

    if (objPtr->bytes) {
	size_t numChars = stringPtr->numChars;
	size_t numBytes = objPtr->length;
	Tcl_Size numChars = stringPtr->numChars;
	Tcl_Size numBytes = objPtr->length;
	char *to, *from = objPtr->bytes;

	if (!inPlace || Tcl_IsShared(objPtr)) {
	    TclNewObj(objPtr);
	    Tcl_SetObjLength(objPtr, numBytes);
	}
	to = objPtr->bytes;

	if ((numChars == TCL_INDEX_NONE) || (numChars < numBytes)) {
	if (numChars < numBytes) {
	    /*
	     * Either numChars == -1 and we don't know how many chars are
	     * represented by objPtr->bytes and we need Pass 1 just in case,
	     * or numChars >= 0 and we know we have fewer chars than bytes, so
	     * we know there's a multibyte character needing Pass 1.
	     *
	     * Pass 1. Reverse the bytes of each multi-byte character.
	     */

	    size_t charCount = 0;
	    size_t bytesLeft = numBytes;
	    Tcl_Size bytesLeft = numBytes;
	    int chw;

	    while (bytesLeft) {
		/*
		 * NOTE: We know that the from buffer is NUL-terminated. It's
		 * part of the contract for objPtr->bytes values. Thus, we can
		 * skip calling Tcl_UtfCharComplete() here.
		 */

		size_t bytesInChar = TclUtfToUniChar(from, &ch);
		int bytesInChar = TclUtfToUniChar(from, &chw);

		ReverseBytes((unsigned char *)to, (unsigned char *)from,
			bytesInChar);
		to += bytesInChar;
		from += bytesInChar;
		bytesLeft -= bytesInChar;
		charCount++;
	    }

	    from = to = objPtr->bytes;
	    stringPtr->numChars = charCount;
	}
	/* Pass 2. Reverse all the bytes. */
	ReverseBytes((unsigned char *)to, (unsigned char *)from, numBytes);
    }

    return objPtr;
}
3799
3800
3801
3802
3803
3804
3805
3806
3807


3808
3809
3810
3811
3812
3813
3814
3815

3816
3817
3818
3819
3820



3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832


3833
3834
3835
3836
3837
3838
3839
4173
4174
4175
4176
4177
4178
4179


4180
4181
4182
4183
4184
4185
4186
4187
4188

4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207


4208
4209
4210
4211
4212
4213
4214
4215
4216







-
-
+
+







-
+





+
+
+










-
-
+
+







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

Tcl_Obj *
TclStringReplace(
    Tcl_Interp *interp,		/* For error reporting, may be NULL */
    Tcl_Obj *objPtr,		/* String to act upon */
    size_t first,		/* First index to replace */
    size_t count,		/* How many chars to replace */
    Tcl_Size first,		/* First index to replace */
    Tcl_Size count,		/* How many chars to replace */
    Tcl_Obj *insertPtr,		/* Replacement string, may be NULL */
    int flags)			/* TCL_STRING_IN_PLACE => attempt in-place */
{
    int inPlace = flags & TCL_STRING_IN_PLACE;
    Tcl_Obj *result;

    /* Replace nothing with nothing */
    if ((insertPtr == NULL) && (count == 0)) {
    if ((insertPtr == NULL) && (count <= 0)) {
	if (inPlace) {
	    return objPtr;
	} else {
	    return Tcl_DuplicateObj(objPtr);
	}
    }
    if (first < 0) {
	first = 0;
    }

    /*
     * The caller very likely had to call Tcl_GetCharLength() or similar
     * to be able to process index values.  This means it is likely that
     * objPtr is either a proper "bytearray" or a "string" or else it has
     * a known and short string rep.
     */

    if (TclIsPureByteArray(objPtr)) {
	size_t numBytes = 0;
	unsigned char *bytes = TclGetByteArrayFromObj(objPtr, &numBytes);
	Tcl_Size numBytes = 0;
	unsigned char *bytes = Tcl_GetBytesFromObj(NULL, objPtr, &numBytes);

	if (insertPtr == NULL) {
	    /* Replace something with nothing. */

	    assert ( first <= numBytes ) ;
	    assert ( count <= numBytes ) ;
	    assert ( first + count <= numBytes ) ;
3847
3848
3849
3850
3851
3852
3853
3854

3855
3856

3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869

3870
3871
3872
3873
3874



3875
3876
3877
3878
3879
3880
3881
4224
4225
4226
4227
4228
4229
4230

4231
4232

4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245

4246
4247
4248



4249
4250
4251
4252
4253
4254
4255
4256
4257
4258







-
+

-
+












-
+


-
-
-
+
+
+








	/* Replace everything */
	if ((first == 0) && (count == numBytes)) {
	    return insertPtr;
	}

	if (TclIsPureByteArray(insertPtr)) {
	    size_t newBytes = 0;
	    Tcl_Size newBytes = 0;
	    unsigned char *iBytes
		    = TclGetByteArrayFromObj(insertPtr, &newBytes);
		    = Tcl_GetBytesFromObj(NULL, insertPtr, &newBytes);

	    if (count == newBytes && inPlace && !Tcl_IsShared(objPtr)) {
		/*
		 * Removal count and replacement count are equal.
		 * Other conditions permit. Do in-place splice.
		 */

		memcpy(bytes + first, iBytes, count);
		Tcl_InvalidateStringRep(objPtr);
		return objPtr;
	    }

	    if ((size_t)newBytes > INT_MAX - (numBytes - count)) {
	    if (newBytes > (TCL_SIZE_MAX - (numBytes - count))) {
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "max size for a Tcl value (%d bytes) exceeded",
			    INT_MAX));
		    Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
			    "max size for a Tcl value (%" TCL_SIZE_MODIFIER "d bytes) exceeded",
			    TCL_SIZE_MAX));
		    Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
		}
		return NULL;
	    }
	    result = Tcl_NewByteArrayObj(NULL, numBytes - count + newBytes);
								/* PANIC? */
	    Tcl_SetByteArrayLength(result, 0);
	    TclAppendBytesToByteArray(result, bytes, first);
3892
3893
3894
3895
3896
3897
3898
3899
3900


3901
3902
3903
3904
3905
3906
3907
3908
3909


3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923

3924
3925
3926
3927
3928
3929
3930
4269
4270
4271
4272
4273
4274
4275


4276
4277
4278
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







-
-
+
+







-
-
+
+













-
+







     * TODO: Figure out how not to generate a Tcl_UniChar array rep
     * when it can be determined objPtr->bytes points to a string of
     * all single-byte characters so we can index it directly.
     */

    /* The traditional implementation... */
    {
	size_t numChars;
	Tcl_UniChar *ustring = TclGetUnicodeFromObj(objPtr, &numChars);
	Tcl_Size numChars;
	Tcl_UniChar *ustring = Tcl_GetUnicodeFromObj(objPtr, &numChars);

	/* TODO: Is there an in-place option worth pursuing here? */

	result = Tcl_NewUnicodeObj(ustring, first);
	if (insertPtr) {
	    Tcl_AppendObjToObj(result, insertPtr);
	}
	if (first + count < (size_t)numChars) {
	    TclAppendUnicodeToObj(result, ustring + first + count,
	if ((first + count) < numChars) {
	    Tcl_AppendUnicodeToObj(result, ustring + first + count,
		    numChars - first - count);
	}

	return result;
    }
}

/*
 *---------------------------------------------------------------------------
 *
 * FillUnicodeRep --
 *
 *	Populate the Unicode internal rep with the Unicode form of its string
 *	rep. The object must alread have a "String" internal rep.
 *	rep. The object must already have a "String" internal rep.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Reallocates the String internal rep.
 *
3942
3943
3944
3945
3946
3947
3948
3949
3950


3951
3952
3953

3954
3955
3956
3957
3958
3959
3960

3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975


3976
3977





3978
3979
3980
3981
3982
3983
3984
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







-
-
+
+


-
+






-
+














-
+
+

-
+
+
+
+
+







	    stringPtr->numChars);
}

static void
ExtendUnicodeRepWithString(
    Tcl_Obj *objPtr,
    const char *bytes,
    size_t numBytes,
    size_t numAppendChars)
    Tcl_Size numBytes,
    Tcl_Size numAppendChars)
{
    String *stringPtr = GET_STRING(objPtr);
    size_t needed, numOrigChars = 0;
    Tcl_Size needed, numOrigChars = 0;
    Tcl_UniChar *dst, unichar = 0;

    if (stringPtr->hasUnicode) {
	numOrigChars = stringPtr->numChars;
    }
    if (numAppendChars == TCL_INDEX_NONE) {
	TclNumUtfChars(numAppendChars, bytes, numBytes);
	TclNumUtfCharsM(numAppendChars, bytes, numBytes);
    }
    needed = numOrigChars + numAppendChars;

    if (needed > stringPtr->maxChars) {
	GrowUnicodeBuffer(objPtr, needed);
	stringPtr = GET_STRING(objPtr);
    }

    stringPtr->hasUnicode = 1;
    if (bytes) {
	stringPtr->numChars = needed;
    } else {
	numAppendChars = 0;
    }
    for (dst=stringPtr->unicode + numOrigChars; numAppendChars-- > 0; dst++) {
    dst = stringPtr->unicode + numOrigChars;
    if (numAppendChars-- > 0) {
	bytes += TclUtfToUniChar(bytes, &unichar);
	*dst = unichar;
	*dst++ = unichar;
	while (numAppendChars-- > 0) {
	    bytes += TclUtfToUniChar(bytes, &unichar);
	    *dst++ = unichar;
	}
    }
    *dst = 0;
}

/*
 *----------------------------------------------------------------------
 *
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4391
4392
4393
4394
4395
4396
4397

4398
4399
4400
4401
4402
4403
4404







-








    if (srcStringPtr->numChars == TCL_INDEX_NONE) {
	/*
	 * The String struct in the source value holds zero useful data. Don't
	 * bother copying it. Don't even bother allocating space in which to
	 * copy it. Just let the copy be untyped.
	 */

	return;
    }

    if (srcStringPtr->hasUnicode) {
	int copyMaxChars;

	if (srcStringPtr->maxChars / 2 >= srcStringPtr->numChars) {
4061
4062
4063
4064
4065
4066
4067
4068
4069


4070
4071
4072
4073
4074
4075
4076
4077
4078
4079

4080
4081
4082
4083
4084
4085
4086
4087

4088
4089
4090

4091
4092
4093
4094
4095
4096
4097
4442
4443
4444
4445
4446
4447
4448


4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459

4460
4461
4462
4463
4464
4465
4466
4467

4468
4469
4470

4471
4472
4473
4474
4475
4476
4477
4478







-
-
+
+









-
+







-
+


-
+







 *
 *	Create an internal representation of type "String" for an object.
 *
 * Results:
 *	This operation always succeeds and returns TCL_OK.
 *
 * Side effects:
 *	Any old internal reputation for objPtr is freed and the internal
 *	representation is set to "String".
 *	Any old internal representation for objPtr is freed and the internal
 *	representation is set to &tclStringType.
 *
 *----------------------------------------------------------------------
 */

static int
SetStringFromAny(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Obj *objPtr)		/* The object to convert. */
{
    if (!TclHasIntRep(objPtr, &tclStringType)) {
    if (!TclHasInternalRep(objPtr, &tclStringType)) {
	String *stringPtr = stringAlloc(0);

	/*
	 * Convert whatever we have into an untyped value. Just A String.
	 */

	(void) TclGetString(objPtr);
	TclFreeIntRep(objPtr);
	TclFreeInternalRep(objPtr);

	/*
	 * Create a basic String intrep that just points to the UTF-8 string
	 * Create a basic String internalrep that just points to the UTF-8 string
	 * already in place at objPtr->bytes.
	 */

	stringPtr->numChars = -1;
	stringPtr->allocated = objPtr->length;
	stringPtr->maxChars = 0;
	stringPtr->hasUnicode = 0;
4109
4110
4111
4112
4113
4114
4115
4116

4117
4118
4119
4120
4121
4122
4123
4490
4491
4492
4493
4494
4495
4496

4497
4498
4499
4500
4501
4502
4503
4504







-
+







 *	Update the string representation for an object whose internal
 *	representation is "String".
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The object's string may be set by converting its Unicode represention
 *	The object's string may be set by converting its Unicode representation
 *	to UTF format.
 *
 *----------------------------------------------------------------------
 */

static void
UpdateStringOfString(
4132
4133
4134
4135
4136
4137
4138
4139

4140
4141
4142
4143
4144
4145
4146

4147
4148
4149
4150

4151
4152
4153

4154
4155
4156

4157
4158
4159
4160

4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177

4178
4179
4180
4181
4182


4183
4184



4185
4186
4187
4188
4189
4190
4191
4513
4514
4515
4516
4517
4518
4519

4520
4521
4522
4523
4524
4525
4526

4527
4528
4529
4530

4531
4532
4533

4534
4535
4536

4537
4538
4539
4540

4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557

4558
4559
4560
4561
4562

4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576







-
+






-
+



-
+


-
+


-
+



-
+
















-
+




-
+
+


+
+
+







     * memory pointed to by that NULL pointer is clearly bogus, and
     * needs a reset.
     */

    stringPtr->allocated = 0;

    if (stringPtr->numChars == 0) {
	TclInitStringRep(objPtr, NULL, 0);
	TclInitEmptyStringRep(objPtr);
    } else {
	(void) ExtendStringRepWithUnicode(objPtr, stringPtr->unicode,
		stringPtr->numChars);
    }
}

static size_t
static Tcl_Size
ExtendStringRepWithUnicode(
    Tcl_Obj *objPtr,
    const Tcl_UniChar *unicode,
    size_t numChars)
    Tcl_Size numChars)
{
    /*
     * Pre-condition: this is the "string" Tcl_ObjType.
     * Precondition: this is the "string" Tcl_ObjType.
     */

    size_t i, origLength, size = 0;
    Tcl_Size i, origLength, size = 0;
    char *dst;
    String *stringPtr = GET_STRING(objPtr);

    if (numChars == TCL_INDEX_NONE) {
    if (numChars < 0) {
	numChars = UnicodeLength(unicode);
    }

    if (numChars == 0) {
	return 0;
    }

    if (objPtr->bytes == NULL) {
	objPtr->length = 0;
    }
    size = origLength = objPtr->length;

    /*
     * Quick cheap check in case we have more than enough room.
     */

    if (numChars <= (INT_MAX - size)/TCL_UTF_MAX
    if (numChars <= (TCL_SIZE_MAX - size)/TCL_UTF_MAX
	    && stringPtr->allocated >= size + numChars * TCL_UTF_MAX) {
	goto copyBytes;
    }

    for (i = 0; i < numChars; i++) {
    for (i = 0; i < numChars && size >= 0; i++) {
	/* TODO - overflow check! I don't think check below at end suffices */
	size += TclUtfCount(unicode[i]);
    }
    if (size < 0) {
	Tcl_Panic("max size for a Tcl value (%" TCL_SIZE_MODIFIER "d bytes) exceeded", TCL_SIZE_MAX);
    }

    /*
     * Grow space if needed.
     */

    if (size > stringPtr->allocated) {
	GrowStringBuffer(objPtr, size, 1);

Changes to generic/tclStringRep.h.

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
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
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
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



-
-
+
+

-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-











-



-
-
+
+

-
+
-
-
-
-
-



-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+


+
+
+
+

-
+







/*
 * tclStringRep.h --
 *
 *	This file contains the definition of the Unicode string internal
 *	representation and macros to access it.
 *  This file contains the definition of internal representations of a string
 *  and macros to access it.
 *
 *	A Unicode string is an internationalized string. Conceptually, a
 *  Conceptually, a string is a sequence of Unicode code points. Internally
 *	Unicode string is an array of 16-bit quantities organized as a
 *	sequence of properly formed UTF-8 characters. There is a one-to-one
 *	map between Unicode and UTF characters. Because Unicode characters
 *	have a fixed width, operations such as indexing operate on Unicode
 *	data. The String object is optimized for the case where each UTF char
 *	in a string is only one byte. In this case, we store the value of
 *	numChars, but we don't store the Unicode data (unless Tcl_GetUnicode
 *	is explicitly called).
 *
 *	The String object type stores one or both formats. The default
 *	behavior is to store UTF. Once Unicode is calculated by a function, it
 *	is stored in the internal rep for future access (without an additional
 *  it may be stored in an encoding form such as a modified version of UTF-8
 *	O(n) cost).
 *
 *  or UTF-32.
 *	To allow many appends to be done to an object without constantly
 *	reallocating the space for the string or Unicode representation, we
 *	allocate double the space for the string or Unicode and use the
 *	internal representation to keep track of how much space is used vs.
 *	allocated.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1999 by Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef _TCLSTRINGREP
#define _TCLSTRINGREP


/*
 * The following structure is the internal rep for a String object. It keeps
 * track of how much memory has been used and how much has been allocated for
 * the Unicode and UTF string to enable growing and shrinking of the UTF and
 * Unicode reps of the String object with fewer mallocs. To optimize string
 * the various representations to enable growing and shrinking of
 * the String object with fewer mallocs. To optimize string
 * length and indexing operations, this structure also stores the number of
 * characters (same of UTF and Unicode!) once that value has been computed.
 * code points (independent of encoding form) once that value has been computed.
 *
 * Under normal configurations, what Tcl calls "Unicode" is actually UTF-16
 * restricted to the Basic Multilingual Plane (i.e. U+00000 to U+0FFFF). This
 * can be officially modified by altering the definition of Tcl_UniChar in
 * tcl.h, but do not do that unless you are sure what you're doing!
 */

typedef struct {
    size_t numChars;		/* The number of chars in the string. -1 means
				 * this value has not been calculated. Any other
				 * means that there is a valid Unicode rep, or
				 * that the number of UTF bytes == the number
				 * of chars. */
    size_t allocated;		/* The amount of space actually allocated for
				 * the UTF string (minus 1 byte for the
				 * termination char). */
    size_t maxChars;		/* Max number of chars that can fit in the
				 * space allocated for the unicode array. */
    Tcl_Size numChars;		/* The number of chars in the string.
				 * TCL_INDEX_NONE means this value has not been
				 * calculated. Any other means that there is a valid
				 * Unicode rep, or that the number of UTF bytes ==
				 * the number of chars. */
    Tcl_Size allocated;		/* The amount of space allocated for
				 * the UTF-8 string. Does not include nul
				 * terminator so actual allocation is
				 * (allocated+1). */
    Tcl_Size maxChars;		/* Max number of chars that can fit in the
				 * space allocated for the Unicode array. */
    int hasUnicode;		/* Boolean determining whether the string has
				 * a Unicode representation. */
    Tcl_UniChar unicode[TCLFLEXARRAY];	/* The array of Unicode chars. The actual size
				 * of this field depends on the 'maxChars'
				 * field above. */
				 * a Tcl_UniChar representation. */
    Tcl_UniChar unicode[TCLFLEXARRAY];	/* The array of Tcl_UniChar units.
				 * The actual size of this field depends on
				 * the maxChars field above. */
} String;

/* Limit on string lengths. The -1 because limit does not include the nul */
#define STRING_MAXCHARS \
    ((Tcl_Size)((TCL_SIZE_MAX - offsetof(String, unicode))/sizeof(Tcl_UniChar) - 1))
/* Memory needed to hold a string of length numChars - including NUL */
#define STRING_SIZE(numChars) \
    (offsetof(String, unicode) + ((numChars + 1) * sizeof(Tcl_UniChar)))
    (offsetof(String, unicode) + sizeof(Tcl_UniChar) + ((numChars) * sizeof(Tcl_UniChar)))
#define stringAttemptAlloc(numChars) \
    (String *) Tcl_AttemptAlloc(STRING_SIZE(numChars))
#define stringAlloc(numChars) \
    (String *) Tcl_Alloc(STRING_SIZE(numChars))
#define stringRealloc(ptr, numChars) \
    (String *) Tcl_Realloc((ptr), STRING_SIZE(numChars))
#define stringAttemptRealloc(ptr, numChars) \

Added generic/tclStubCall.c.






















































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tclStubCall.c --
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#ifndef _WIN32
#   include <dlfcn.h>
#else
#   define dlopen(a,b) (void *)LoadLibraryW(JOIN(L,a))
#   define dlsym(a,b) (void *)GetProcAddress((HMODULE)(a),b)
#   define dlerror() ""
#endif

MODULE_SCOPE void *tclStubsHandle;

/*
 *----------------------------------------------------------------------
 *
 * TclStubCall --
 *
 *	Load the Tcl core dynamically, version "9.0" (or higher, in future versions).
 *
 * Results:
 *	Returns a function from the Tcl dynamic library or a function
 *	returning NULL if that function cannot be found. See PROCNAME table.
 *
 *	The functions Tcl_MainEx and Tcl_MainExW never return.
 *	Tcl_GetMemoryInfo and Tcl_StaticLibrary return (void),
 *	Tcl_SetExitProc returns its previous exitProc and
 *	Tcl_SetPreInitScript returns the previous script. This means that
 *	those 6 functions cannot be used to initialize the stub-table,
 *	only the first 4 functions in the table can do that.
 *
 *----------------------------------------------------------------------
 */

/* Table containing which function will be returned, depending on the "arg" */
static const char PROCNAME[][24] = {
    "_Tcl_SetPanicProc", /* Default, whenever "arg" <= 0 or "arg" > 9 */
    "_Tcl_InitSubsystems", /* "arg" == (void *)1 */
    "_Tcl_FindExecutable", /* "arg" == (void *)2 */
    "_TclZipfs_AppHook", /* "arg" == (void *)3 */
    "_Tcl_MainExW", /* "arg" == (void *)4 */
    "_Tcl_MainEx", /* "arg" == (void *)5 */
    "_Tcl_StaticLibrary", /* "arg" == (void *)6 */
    "_Tcl_SetExitProc", /* "arg" == (void *)7 */
    "_Tcl_GetMemoryInfo", /* "arg" == (void *)8 */
    "_Tcl_SetPreInitScript" /* "arg" == (void *)9 */
};

MODULE_SCOPE const void *nullVersionProc(void) {
	return NULL;
}

static const char CANNOTCALL[] = "Cannot call %s from stubbed extension\n";
static const char CANNOTFIND[] = "Cannot find %s: %s\n";

MODULE_SCOPE void *
TclStubCall(void *arg)
{
    static void *stubFn[] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
    size_t index = PTR2UINT(arg);

    if (index >= sizeof(PROCNAME)/sizeof(PROCNAME[0])) {
	/* Any other value means Tcl_SetPanicProc() with non-null panicProc */
	index = 0;
    }
    if (tclStubsHandle == INT2PTR(-1)) {
	if ((index == 0) && (arg != NULL)) {
	    ((Tcl_PanicProc *)arg)(CANNOTCALL, PROCNAME[index] + 1);
	} else {
	    fprintf(stderr, CANNOTCALL, PROCNAME[index] + 1);
	    abort();
	}
    }
    if (!stubFn[index]) {
	if (!tclStubsHandle) {
	    tclStubsHandle = dlopen(CFG_RUNTIME_DLLFILE, RTLD_NOW|RTLD_LOCAL);
	    if (!tclStubsHandle) {
#if defined(_WIN32)
		tclStubsHandle = dlopen(CFG_RUNTIME_BINDIR "\\" CFG_RUNTIME_DLLFILE, RTLD_NOW|RTLD_LOCAL);
#elif defined(__CYGWIN__)
		tclStubsHandle = dlopen(CFG_RUNTIME_BINDIR "/" CFG_RUNTIME_DLLFILE, RTLD_NOW|RTLD_LOCAL);
#else
		tclStubsHandle = dlopen(CFG_RUNTIME_LIBDIR "/" CFG_RUNTIME_DLLFILE, RTLD_NOW|RTLD_LOCAL);
#endif
	    }
	    if (!tclStubsHandle) {
		if ((index == 0) && (arg != NULL)) {
		    ((Tcl_PanicProc *)arg)(CANNOTFIND, CFG_RUNTIME_DLLFILE, dlerror());
		} else {
		    fprintf(stderr, CANNOTFIND, CFG_RUNTIME_DLLFILE, dlerror());
		    abort();
		}
	    }
	}
	stubFn[index] = dlsym(tclStubsHandle, PROCNAME[index] + 1);
	if (!stubFn[index]) {
	    stubFn[index] = dlsym(tclStubsHandle, PROCNAME[index]);
	    if (!stubFn[index]) {
		stubFn[index] = (void *)nullVersionProc;
	    }
	}
    }
    return stubFn[index];
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclStubInit.c.

1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * tclStubInit.c --
 *
 *	This file contains the initializers for the Tcl stub vectors.
 *
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright © 1998-1999 Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tommath_private.h"
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
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
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







+
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
-

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-


















-
-
+
+
+













+



+
-
+


-
-
-
+
+
+

-
+




-
-

+
-
-
-
-
-
+
+
+
+
+
+
+
+







+








-
+
















-
+







-
+


-
+








+




-
-
+
+



-
+





-
+




-
-
+
+



-
+





-
+
-
-
-
-
-
-
-
-
-


-
+
+
+
+
+
+
+



















+
+
+
+
+
+
+
+
+
+
+







#undef Tcl_FindExecutable
#undef Tcl_SetExitProc
#undef Tcl_SetPanicProc
#undef TclpGetPid
#undef TclSockMinimumBuffers
#undef Tcl_SetIntObj
#undef Tcl_SetLongObj
#undef Tcl_ListObjGetElements
#undef TclpInetNtoa
#undef TclWinGetServByName
#undef TclWinGetSockOpt
#undef TclWinSetSockOpt
#undef TclWinNToHS
#undef TclStaticPackage
#undef Tcl_ListObjLength
#undef Tcl_DictObjSize
#undef Tcl_SplitList
#undef Tcl_SplitPath
#undef Tcl_FSSplitPath
#undef Tcl_ParseArgsObjv
#undef TclStaticLibrary
#undef Tcl_BackgroundError
#define TclStaticPackage Tcl_StaticPackage
#undef Tcl_UniCharToUtfDString
#undef Tcl_UtfToUniCharDString
#undef Tcl_UtfToUniChar

#define TclStaticLibrary Tcl_StaticLibrary
#undef TclObjInterpProc
#if !defined(_WIN32) && !defined(__CYGWIN__)
# undef Tcl_WinConvertError
# define Tcl_WinConvertError 0
#endif
#undef TclGetStringFromObj
#if defined(TCL_NO_DEPRECATED)
#if TCL_UTF_MAX <= 3
static void uniCodePanic() {
    Tcl_Panic("This extension uses a deprecated function, not available now: Tcl is compiled with -DTCL_UTF_MAX==%d", TCL_UTF_MAX);
}
#   define Tcl_GetUnicode (int *(*)(Tcl_Obj *))(void *)uniCodePanic
#   define Tcl_GetUnicodeFromObj (Tcl_UniChar *(*)(Tcl_Obj *, int *))(void *)uniCodePanic
#   define Tcl_NewUnicodeObj (Tcl_Obj *(*)(const Tcl_UniChar *, size_t))(void *)uniCodePanic
# define TclGetStringFromObj 0
# define TclGetBytesFromObj 0
# define TclGetUnicodeFromObj 0
#   define Tcl_SetUnicodeObj (void(*)(Tcl_Obj *, const Tcl_UniChar *, size_t))(void *)uniCodePanic
#endif
#undef Tcl_Close
#define Tcl_Close 0
#undef Tcl_GetByteArrayFromObj
#define Tcl_GetByteArrayFromObj 0
#define TclUnusedStubEntry 0
#define TclUtfCharComplete Tcl_UtfCharComplete
#define TclUtfNext Tcl_UtfNext
#define TclUtfPrev Tcl_UtfPrev
#undef TclListObjGetElements
#undef TclListObjLength

#if defined(TCL_NO_DEPRECATED)
# define TclListObjGetElements 0
# define TclListObjLength 0
# define TclDictObjSize 0
# define TclSplitList 0
# define TclSplitPath 0
# define TclFSSplitPath 0
# define TclParseArgsObjv 0
# define TclGetAliasObj 0
#else /* !defined(TCL_NO_DEPRECATED) */
int TclListObjGetElements(Tcl_Interp *interp, Tcl_Obj *listPtr,
    void *objcPtr, Tcl_Obj ***objvPtr) {
    Tcl_Size n = TCL_INDEX_NONE;
    int result = Tcl_ListObjGetElements(interp, listPtr, &n, objvPtr);
    if (objcPtr) {
	if ((sizeof(int) != sizeof(Tcl_Size)) && (result == TCL_OK) && (n > INT_MAX)) {
	    if (interp) {
		Tcl_AppendResult(interp, "List too large to be processed", (char *)NULL);
	    }
	    return TCL_ERROR;
	}
	*(int *)objcPtr = (int)n;
    }
    return result;
}
int TclListObjLength(Tcl_Interp *interp, Tcl_Obj *listPtr,
    void *lengthPtr) {
    Tcl_Size n = TCL_INDEX_NONE;
    int result = Tcl_ListObjLength(interp, listPtr, &n);
    if (lengthPtr) {
	if ((sizeof(int) != sizeof(Tcl_Size)) && (result == TCL_OK) && (n > INT_MAX)) {
	    if (interp) {
		Tcl_AppendResult(interp, "List too large to be processed", (char *)NULL);
	    }
	    return TCL_ERROR;
	}
	*(int *)lengthPtr = (int)n;
    }
    return result;
}
int TclDictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr,
    void *sizePtr) {
    Tcl_Size n = TCL_INDEX_NONE;
    int result = Tcl_DictObjSize(interp, dictPtr, &n);
    if (sizePtr) {
	if ((sizeof(int) != sizeof(Tcl_Size)) && (result == TCL_OK) && (n > INT_MAX)) {
	    if (interp) {
		Tcl_AppendResult(interp, "Dict too large to be processed", (char *)NULL);
	    }
	    return TCL_ERROR;
	}
	*(int *)sizePtr = (int)n;
    }
    return result;
}
int TclSplitList(Tcl_Interp *interp, const char *listStr, void *argcPtr,
	const char ***argvPtr) {
    Tcl_Size n = TCL_INDEX_NONE;
    int result = Tcl_SplitList(interp, listStr, &n, argvPtr);
    if (argcPtr) {
	if ((sizeof(int) != sizeof(Tcl_Size)) && (result == TCL_OK) && (n > INT_MAX)) {
	    if (interp) {
		Tcl_AppendResult(interp, "List too large to be processed", (char *)NULL);
	    }
	    Tcl_Free((void *)*argvPtr);
	    return TCL_ERROR;
	}
	*(int *)argcPtr = (int)n;
    }
    return result;
}
void TclSplitPath(const char *path, void *argcPtr, const char ***argvPtr) {
    Tcl_Size n = TCL_INDEX_NONE;
    Tcl_SplitPath(path, &n, argvPtr);
    if (argcPtr) {
	if ((sizeof(int) != sizeof(Tcl_Size)) && (n > INT_MAX)) {
	    n = TCL_INDEX_NONE; /* No other way to return an error-situation */
	    Tcl_Free((void *)*argvPtr);
	    *argvPtr = NULL;
	}
	*(int *)argcPtr = (int)n;
    }
}
Tcl_Obj *TclFSSplitPath(Tcl_Obj *pathPtr, void *lenPtr) {
    Tcl_Size n = TCL_INDEX_NONE;
    Tcl_Obj *result = Tcl_FSSplitPath(pathPtr, &n);
    if (lenPtr) {
	if ((sizeof(int) != sizeof(Tcl_Size)) && result && (n > INT_MAX)) {
	    Tcl_DecrRefCount(result);
	    return NULL;
	}
	*(int *)lenPtr = (int)n;
    }
    return result;
}
int TclParseArgsObjv(Tcl_Interp *interp,
	const Tcl_ArgvInfo *argTable, void *objcPtr, Tcl_Obj *const *objv,
	Tcl_Obj ***remObjv) {
    Tcl_Size n = (*(int *)objcPtr < 0) ? TCL_INDEX_NONE: (Tcl_Size)*(int *)objcPtr ;
    int result = Tcl_ParseArgsObjv(interp, argTable, &n, objv, remObjv);
    *(int *)objcPtr = (int)n;
    return result;
}
int TclGetAliasObj(Tcl_Interp *interp, const char *childCmd,
	Tcl_Interp **targetInterpPtr, const char **targetCmdPtr,
	int *objcPtr, Tcl_Obj ***objv) {
    Tcl_Size n = TCL_INDEX_NONE;
    int result = Tcl_GetAliasObj(interp, childCmd, targetInterpPtr, targetCmdPtr, &n, objv);
    if (objcPtr) {
	if ((sizeof(int) != sizeof(Tcl_Size)) && (result == TCL_OK) && (n > INT_MAX)) {
	    if (interp) {
		Tcl_AppendResult(interp, "List too large to be processed", NULL);
	    }
	    return TCL_ERROR;
	}
	*objcPtr = (int)n;
    }
    return result;
}
#endif /* !defined(TCL_NO_DEPRECATED) */

#define TclBN_mp_add mp_add
#define TclBN_mp_add_d mp_add_d
#define TclBN_mp_and mp_and
#define TclBN_mp_clamp mp_clamp
#define TclBN_mp_clear mp_clear
#define TclBN_mp_clear_multi mp_clear_multi
#define TclBN_mp_cmp mp_cmp
#define TclBN_mp_cmp_d mp_cmp_d
#define TclBN_mp_cmp_mag mp_cmp_mag
#define TclBN_mp_cnt_lsb mp_cnt_lsb
#define TclBN_mp_copy mp_copy
#define TclBN_mp_count_bits mp_count_bits
#define TclBN_mp_div mp_div
#define TclBN_mp_div_d mp_div_d
#define TclBN_mp_div_2 mp_div_2
#define TclBN_mp_div_2d mp_div_2d
#define TclBN_mp_exch mp_exch
#define TclBN_mp_expt_u32 mp_expt_u32
#define TclBN_mp_get_mag_u64 mp_get_mag_u64
#define TclBN_mp_grow mp_grow
#define TclBN_mp_init mp_init
#define TclBN_mp_init_copy mp_init_copy
#define TclBN_mp_init_multi mp_init_multi
#define TclBN_mp_init_set mp_init_set
#define TclBN_mp_init_size mp_init_size
#define TclBN_mp_init_i64 mp_init_i64
#define TclBN_mp_init_u64 mp_init_u64
#define TclBN_mp_lshd mp_lshd
#define TclBN_mp_mod mp_mod
#define TclBN_mp_mod_2d mp_mod_2d
#define TclBN_mp_mul mp_mul
#define TclBN_mp_mul_d mp_mul_d
#define TclBN_mp_mul_2 mp_mul_2
#define TclBN_mp_mul_2d mp_mul_2d
#define TclBN_mp_neg mp_neg
#define TclBN_mp_or mp_or
#define TclBN_mp_radix_size mp_radix_size
#define TclBN_mp_reverse mp_reverse
#define TclBN_mp_pack mp_pack
#define TclBN_mp_pack_count mp_pack_count
#define TclBN_mp_radix_size mp_radix_size
#define TclBN_mp_read_radix mp_read_radix
#define TclBN_mp_rshd mp_rshd
#define TclBN_mp_set_i64 mp_set_i64
#define TclBN_mp_set_u64 mp_set_u64
#define TclBN_mp_shrink mp_shrink
#define TclBN_mp_sqr mp_sqr
#define TclBN_mp_sqrt mp_sqrt
#define TclBN_mp_sub mp_sub
#define TclBN_mp_sub_d mp_sub_d
#define TclBN_mp_signed_rsh mp_signed_rsh
#define TclBN_mp_to_radix mp_to_radix
#define TclBN_mp_to_ubin mp_to_ubin
#define TclBN_mp_ubin_size mp_ubin_size
#define TclBN_mp_unpack mp_unpack
#define TclBN_mp_xor mp_xor
#define TclBN_mp_zero mp_zero
#define TclBN_s_mp_add s_mp_add
#define TclBN_mp_balance_mul s_mp_balance_mul
#define TclBN_s_mp_balance_mul mp_balance_mul
#define TclBN_mp_div_3 s_mp_div_3
#define TclBN_mp_karatsuba_mul s_mp_karatsuba_mul
#define TclBN_mp_karatsuba_sqr s_mp_karatsuba_sqr
#define TclBN_s_mp_mul_digs s_mp_mul_digs
#define TclBN_s_mp_mul_digs_fast s_mp_mul_digs_fast
#define TclBN_s_mp_reverse s_mp_reverse
#define TclBN_mp_mul_digs s_mp_mul_digs
#define TclBN_mp_mul_digs_fast s_mp_mul_digs_fast
#define TclBN_mp_reverse s_mp_reverse
#define TclBN_s_mp_sqr s_mp_sqr
#define TclBN_s_mp_sqr_fast s_mp_sqr_fast
#define TclBN_mp_sqr_fast s_mp_sqr_fast
#define TclBN_s_mp_sub s_mp_sub
#define TclBN_mp_toom_mul s_mp_toom_mul
#define TclBN_mp_toom_sqr s_mp_toom_sqr

#define TclpCreateTempFile_ TclpCreateTempFile
#define TclUnixWaitForFile_ TclUnixWaitForFile
#ifndef MAC_OSX_TCL /* On UNIX, fill with other stub entries */
#   define Tcl_MacOSXOpenVersionedBundleResources 0
#define TclMacOSXGetFileAttribute (int (*)(Tcl_Interp *, int, Tcl_Obj *, Tcl_Obj **))(void *)TclpCreateProcess
#define TclMacOSXSetFileAttribute (int (*)(Tcl_Interp *, int, Tcl_Obj *, Tcl_Obj *))(void *)isatty
#define TclMacOSXCopyFileAttributes (int (*)(const char *, const char *, const Tcl_StatBuf *))(void *)TclUnixCopyFile
#define TclMacOSXMatchType (int (*)(Tcl_Interp *, const char *, const char *, Tcl_StatBuf *, Tcl_GlobTypeData *))(void *)TclpMakeFile
#define TclMacOSXNotifierAddRunLoopMode (void (*)(const void *))(void *)TclpOpenFile
#   define Tcl_MacOSXNotifierAddRunLoopMode 0
#endif
#ifdef _WIN32
#   define Tcl_CreateFileHandler 0
#   define Tcl_DeleteFileHandler 0
#   define Tcl_GetOpenFile 0
#else
#   define TclpIsAtty isatty
#endif

#ifdef _WIN32
#   define TclUnixWaitForFile 0
#   define TclUnixCopyFile 0
#   define TclUnixOpenTemporaryFile 0
#   define TclpReaddir 0
#   undef TclpIsAtty
#   define TclpIsAtty 0
#elif defined(__CYGWIN__)
#   define TclpIsAtty isatty
static void
doNothing(void)
{
    /* dummy implementation, no need to do anything */
}
#   define TclWinAddProcess (void (*) (void *, size_t)) doNothing
#   define TclWinAddProcess (void (*) (void *, Tcl_Size)) doNothing
#   define TclWinFlushDirtyChannels doNothing

#define TclWinNoBackslash winNoBackslash
static char *
TclWinNoBackslash(char *path)
{
    char *p;

    for (p = path; *p != '\0'; p++) {
	if (*p == '\\') {
	    *p = '/';
	}
    }
    return path;
}

void *TclWinGetTclInstance()
void *TclWinGetTclInstance(void)
{
    void *hInstance = NULL;
    GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
	    (const wchar_t *)&TclWinNoBackslash, &hInstance);
    return hInstance;
}

size_t
Tcl_Size
TclpGetPid(Tcl_Pid pid)
{
    return (size_t)pid;
    return (Tcl_Size)PTR2INT(pid);
}

#if defined(TCL_WIDE_INT_IS_LONG)
/* On Cygwin64, long is 64-bit while on Win64 long is 32-bit. Therefore
 * we have to make sure that all stub entries on Cygwin64 follow the Win64
 * signature. Tcl 9 must find a better solution, but that cannot be done
 * without introducing a binary incompatibility.
 */
#define Tcl_GetLongFromObj (int(*)(Tcl_Interp*,Tcl_Obj*,long*))(void *)Tcl_GetIntFromObj
static int exprInt(Tcl_Interp *interp, const char *expr, int *ptr){
    long longValue;
    int result = Tcl_ExprLong(interp, expr, &longValue);
    if (result == TCL_OK) {
	    if ((longValue >= (long)(INT_MIN))
		    && (longValue <= (long)(UINT_MAX))) {
	if ((longValue >= (long)(INT_MIN))
		&& (longValue <= (long)(UINT_MAX))) {
	    *ptr = (int)longValue;
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "integer value too large to represent as non-long integer", -1));
		    "integer value too large to represent", -1));
	    result = TCL_ERROR;
	}
    }
    return result;
}
#define Tcl_ExprLong (int(*)(Tcl_Interp*,const char*,long*))exprInt
#define Tcl_ExprLong (int(*)(Tcl_Interp*,const char*,long*))(void *)exprInt
static int exprIntObj(Tcl_Interp *interp, Tcl_Obj*expr, int *ptr){
    long longValue;
    int result = Tcl_ExprLongObj(interp, expr, &longValue);
    if (result == TCL_OK) {
	    if ((longValue >= (long)(INT_MIN))
		    && (longValue <= (long)(UINT_MAX))) {
	if ((longValue >= (long)(INT_MIN))
		&& (longValue <= (long)(UINT_MAX))) {
	    *ptr = (int)longValue;
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "integer value too large to represent as non-long integer", -1));
		    "integer value too large to represent", -1));
	    result = TCL_ERROR;
	}
    }
    return result;
}
#define Tcl_ExprLongObj (int(*)(Tcl_Interp*,Tcl_Obj*,long*))exprIntObj
#define Tcl_ExprLongObj (int(*)(Tcl_Interp*,Tcl_Obj*,long*))(void *)exprIntObj
static int utfNcmp(const char *s1, const char *s2, unsigned int n){
   return Tcl_UtfNcmp(s1, s2, (unsigned long)n);
}
#define Tcl_UtfNcmp (int(*)(const char*,const char*,unsigned long))(void *)utfNcmp
static int utfNcasecmp(const char *s1, const char *s2, unsigned int n){
   return Tcl_UtfNcasecmp(s1, s2, (unsigned long)n);
}
#define Tcl_UtfNcasecmp (int(*)(const char*,const char*,unsigned long))(void *)utfNcasecmp

#endif /* TCL_WIDE_INT_IS_LONG */

#endif /* __CYGWIN__ */
#else /* __CYGWIN__ */
#   define TclWinGetTclInstance 0
#   define TclpGetPid 0
#   define TclWinFlushDirtyChannels 0
#   define TclWinNoBackslash 0
#   define TclWinAddProcess 0
#endif

/*
 * WARNING: The contents of this file is automatically generated by the
 * tools/genStubs.tcl script. Any modifications to the function declarations
 * below should be made in the generic/tcl.decls script.
 */

MODULE_SCOPE const TclStubs tclStubs;
MODULE_SCOPE const TclTomMathStubs tclTomMathStubs;

#ifdef __GNUC__
/*
 * The rest of this file shouldn't warn about deprecated functions; they're
 * there because we intend them to be so and know that this file is OK to
 * touch those fields.
 */
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif

#ifdef TCL_WITH_EXTERNAL_TOMMATH
/* If Tcl is linked with an external libtommath 1.2.x, then mp_expt_n doesn't
 * exist (since that was introduced in libtommath 1.3.0. Provide it here.) */
mp_err MP_WUR TclBN_mp_expt_n(const mp_int *a, int b, mp_int *c) {
   if ((unsigned)b > MP_MIN(MP_DIGIT_MAX, INT_MAX)) {
      return MP_VAL;
   }
    return mp_expt_u32(a, (uint32_t)b, c);;
}
#endif /* TCL_WITH_EXTERNAL_TOMMATH */

/* !BEGIN!: Do not edit below this line. */

static const TclIntStubs tclIntStubs = {
    TCL_STUB_MAGIC,
    0,
    0, /* 0 */
    0, /* 1 */
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
448
449
450
451
452
453
454

455
456
457
458
459
460


461
462
463
464
465
466
467
468
469
470


471
472
473
474
475
476
477
478
479
480

481
482
483
484
485
486
487
488







-
+





-
-
+
+








-
-
+
+








-
+







    0, /* 30 */
    TclGetExtension, /* 31 */
    TclGetFrame, /* 32 */
    0, /* 33 */
    0, /* 34 */
    0, /* 35 */
    0, /* 36 */
    TclGetLoadedPackages, /* 37 */
    0, /* 37 */
    TclGetNamespaceForQualName, /* 38 */
    TclGetObjInterpProc, /* 39 */
    TclGetOpenMode, /* 40 */
    TclGetOriginalCommand, /* 41 */
    TclpGetUserHome, /* 42 */
    0, /* 43 */
    TclGuessPackageName, /* 44 */
    TclGetObjInterpProc2, /* 43 */
    0, /* 44 */
    TclHideUnsafeCommands, /* 45 */
    TclInExit, /* 46 */
    0, /* 47 */
    0, /* 48 */
    0, /* 49 */
    0, /* 50 */
    TclInterpInit, /* 51 */
    0, /* 52 */
    TclInvokeObjectCommand, /* 53 */
    TclInvokeStringCommand, /* 54 */
    0, /* 53 */
    0, /* 54 */
    TclIsProc, /* 55 */
    0, /* 56 */
    0, /* 57 */
    TclLookupVar, /* 58 */
    0, /* 59 */
    TclNeedSpace, /* 60 */
    TclNewProcBodyObj, /* 61 */
    TclObjCommandComplete, /* 62 */
    TclObjInterpProc, /* 63 */
    0, /* 63 */
    TclObjInvoke, /* 64 */
    0, /* 65 */
    0, /* 66 */
    0, /* 67 */
    0, /* 68 */
    TclpAlloc, /* 69 */
    0, /* 70 */
368
369
370
371
372
373
374
375

376
377
378
379
380
381
382
512
513
514
515
516
517
518

519
520
521
522
523
524
525
526







-
+







    0, /* 94 */
    0, /* 95 */
    TclRenameCommand, /* 96 */
    TclResetShadowedCmdRefs, /* 97 */
    TclServiceIdle, /* 98 */
    0, /* 99 */
    0, /* 100 */
    TclSetPreInitScript, /* 101 */
    0, /* 101 */
    TclSetupEnv, /* 102 */
    TclSockGetPort, /* 103 */
    0, /* 104 */
    0, /* 105 */
    0, /* 106 */
    0, /* 107 */
    TclTeardownNamespace, /* 108 */
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
543
544
545
546
547
548
549

550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569


570
571
572
573
574
575
576
577
578







-
+



















-
-
+
+







    0, /* 125 */
    Tcl_GetVariableFullName, /* 126 */
    0, /* 127 */
    Tcl_PopCallFrame, /* 128 */
    Tcl_PushCallFrame, /* 129 */
    Tcl_RemoveInterpResolvers, /* 130 */
    Tcl_SetNamespaceResolvers, /* 131 */
    TclpHasSockets, /* 132 */
    0, /* 132 */
    0, /* 133 */
    0, /* 134 */
    0, /* 135 */
    0, /* 136 */
    0, /* 137 */
    TclGetEnv, /* 138 */
    0, /* 139 */
    0, /* 140 */
    TclpGetCwd, /* 141 */
    TclSetByteCodeFromAny, /* 142 */
    TclAddLiteralObj, /* 143 */
    TclHideLiteral, /* 144 */
    TclGetAuxDataType, /* 145 */
    TclHandleCreate, /* 146 */
    TclHandleFree, /* 147 */
    TclHandlePreserve, /* 148 */
    TclHandleRelease, /* 149 */
    TclRegAbout, /* 150 */
    TclRegExpRangeUniChar, /* 151 */
    TclSetLibraryPath, /* 152 */
    TclGetLibraryPath, /* 153 */
    0, /* 152 */
    0, /* 153 */
    0, /* 154 */
    0, /* 155 */
    TclRegError, /* 156 */
    TclVarTraceExists, /* 157 */
    0, /* 158 */
    0, /* 159 */
    0, /* 160 */
486
487
488
489
490
491
492
493

494
495
496
497



498
499
500
501
502
503
504
630
631
632
633
634
635
636

637
638



639
640
641
642
643
644
645
646
647
648







-
+

-
-
-
+
+
+







    TclpFindExecutable, /* 212 */
    TclGetObjNameOfExecutable, /* 213 */
    TclSetObjNameOfExecutable, /* 214 */
    TclStackAlloc, /* 215 */
    TclStackFree, /* 216 */
    TclPushStackFrame, /* 217 */
    TclPopStackFrame, /* 218 */
    0, /* 219 */
    TclpCreateTemporaryDirectory, /* 219 */
    0, /* 220 */
    0, /* 221 */
    0, /* 222 */
    0, /* 223 */
    TclListTestObj, /* 221 */
    TclListObjValidate, /* 222 */
    TclGetCStackPtr, /* 223 */
    TclGetPlatform, /* 224 */
    TclTraceDictPath, /* 225 */
    TclObjBeingDeleted, /* 226 */
    TclSetNsPath, /* 227 */
    0, /* 228 */
    TclPtrMakeUpvar, /* 229 */
    TclObjLookupVar, /* 230 */
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
558
559
560
561

562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593


594
595
596

597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646

647

648
649
650
651
652
653
654
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

707
708
709
710
711
712
713
714
715


































716
717
718
719
720

721
722
723

724
725
726
727
728
729
730
731







-
-
-
-
+
+
+
+
+





-
-
+



-
-
+
+


-
+


-
+


-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-



-
-
+
+


-
+








-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-





-


+
-
+







    TclSetChildCancelFlags, /* 250 */
    TclRegisterLiteral, /* 251 */
    TclPtrGetVar, /* 252 */
    TclPtrSetVar, /* 253 */
    TclPtrIncrObjVar, /* 254 */
    TclPtrObjMakeUpvar, /* 255 */
    TclPtrUnsetVar, /* 256 */
    TclStaticPackage, /* 257 */
    TclpCreateTemporaryDirectory, /* 258 */
    TclAppendUnicodeToObj, /* 259 */
    TclGetBytesFromObj, /* 260 */
    TclStaticLibrary, /* 257 */
    0, /* 258 */
    0, /* 259 */
    0, /* 260 */
    TclUnusedStubEntry, /* 261 */
};

static const TclIntPlatStubs tclIntPlatStubs = {
    TCL_STUB_MAGIC,
    0,
#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
    TclGetAndDetachPids, /* 0 */
    0, /* 0 */
    TclpCloseFile, /* 1 */
    TclpCreateCommandChannel, /* 2 */
    TclpCreatePipe, /* 3 */
    TclpCreateProcess, /* 4 */
    TclUnixWaitForFile_, /* 5 */
    TclWinGetTclInstance, /* 4 */
    TclUnixWaitForFile, /* 5 */
    TclpMakeFile, /* 6 */
    TclpOpenFile, /* 7 */
    TclUnixWaitForFile, /* 8 */
    TclpGetPid, /* 8 */
    TclpCreateTempFile, /* 9 */
    0, /* 10 */
    0, /* 11 */
    TclGetAndDetachPids, /* 11 */
    0, /* 12 */
    0, /* 13 */
    TclUnixCopyFile, /* 14 */
    TclMacOSXGetFileAttribute, /* 15 */
    TclMacOSXSetFileAttribute, /* 16 */
    TclMacOSXCopyFileAttributes, /* 17 */
    TclMacOSXMatchType, /* 18 */
    TclMacOSXNotifierAddRunLoopMode, /* 19 */
    0, /* 20 */
    0, /* 14 */
    0, /* 21 */
    TclpCreateTempFile_, /* 22 */
    0, /* 23 */
    0, /* 24 */
    0, /* 25 */
    0, /* 26 */
    0, /* 27 */
    0, /* 28 */
    TclWinCPUID, /* 29 */
    TclUnixOpenTemporaryFile, /* 30 */
#endif /* UNIX */
#if defined(_WIN32) || defined(__CYGWIN__) /* WIN */
    TclWinConvertError, /* 0 */
    0, /* 1 */
    0, /* 2 */
    0, /* 3 */
    TclWinGetTclInstance, /* 4 */
    TclUnixWaitForFile, /* 5 */
    0, /* 6 */
    0, /* 7 */
    TclpGetPid, /* 8 */
    0, /* 9 */
    0, /* 10 */
    TclGetAndDetachPids, /* 11 */
    TclpCloseFile, /* 12 */
    TclpCreateCommandChannel, /* 13 */
    TclpCreatePipe, /* 14 */
    TclpCreateProcess, /* 15 */
    TclpIsAtty, /* 16 */
    TclUnixCopyFile, /* 17 */
    TclpMakeFile, /* 18 */
    TclpOpenFile, /* 19 */
    0, /* 18 */
    0, /* 19 */
    TclWinAddProcess, /* 20 */
    0, /* 21 */
    TclpCreateTempFile, /* 22 */
    0, /* 22 */
    0, /* 23 */
    TclWinNoBackslash, /* 24 */
    0, /* 25 */
    0, /* 26 */
    TclWinFlushDirtyChannels, /* 27 */
    0, /* 28 */
    TclWinCPUID, /* 29 */
    TclUnixOpenTemporaryFile, /* 30 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    TclGetAndDetachPids, /* 0 */
    TclpCloseFile, /* 1 */
    TclpCreateCommandChannel, /* 2 */
    TclpCreatePipe, /* 3 */
    TclpCreateProcess, /* 4 */
    TclUnixWaitForFile_, /* 5 */
    TclpMakeFile, /* 6 */
    TclpOpenFile, /* 7 */
    TclUnixWaitForFile, /* 8 */
    TclpCreateTempFile, /* 9 */
    0, /* 10 */
    0, /* 11 */
    0, /* 12 */
    0, /* 13 */
    TclUnixCopyFile, /* 14 */
    TclMacOSXGetFileAttribute, /* 15 */
    TclMacOSXSetFileAttribute, /* 16 */
    TclMacOSXCopyFileAttributes, /* 17 */
    TclMacOSXMatchType, /* 18 */
    TclMacOSXNotifierAddRunLoopMode, /* 19 */
    0, /* 20 */
    0, /* 21 */
    TclpCreateTempFile_, /* 22 */
    0, /* 23 */
    0, /* 24 */
    0, /* 25 */
    0, /* 26 */
    0, /* 27 */
    0, /* 28 */
    TclWinCPUID, /* 29 */
    TclUnixOpenTemporaryFile, /* 30 */
#endif /* MACOSX */
};

static const TclPlatStubs tclPlatStubs = {
    TCL_STUB_MAGIC,
    0,
#ifdef MAC_OSX_TCL /* MACOSX */
    0, /* 0 */
    Tcl_MacOSXOpenVersionedBundleResources, /* 1 */
    Tcl_MacOSXNotifierAddRunLoopMode, /* 2 */
#endif /* MACOSX */
    Tcl_WinConvertError, /* 3 */
};

const TclTomMathStubs tclTomMathStubs = {
    TCL_STUB_MAGIC,
    0,
    TclBN_epoch, /* 0 */
    TclBN_revision, /* 1 */
665
666
667
668
669
670
671
672

673
674
675
676
677
678
679
742
743
744
745
746
747
748

749
750
751
752
753
754
755
756







-
+







    TclBN_mp_count_bits, /* 12 */
    TclBN_mp_div, /* 13 */
    TclBN_mp_div_d, /* 14 */
    TclBN_mp_div_2, /* 15 */
    TclBN_mp_div_2d, /* 16 */
    0, /* 17 */
    TclBN_mp_exch, /* 18 */
    TclBN_mp_expt_u32, /* 19 */
    TclBN_mp_expt_n, /* 19 */
    TclBN_mp_grow, /* 20 */
    TclBN_mp_init, /* 21 */
    TclBN_mp_init_copy, /* 22 */
    TclBN_mp_init_multi, /* 23 */
    TclBN_mp_init_set, /* 24 */
    TclBN_mp_init_size, /* 25 */
    TclBN_mp_lshd, /* 26 */
717
718
719
720
721
722
723
724
725


726
727
728
729
730

731
732
733
734
735
736
737
794
795
796
797
798
799
800


801
802
803
804
805
806

807
808
809
810
811
812
813
814







-
-
+
+




-
+







    0, /* 64 */
    TclBN_mp_init_i64, /* 65 */
    TclBN_mp_init_u64, /* 66 */
    0, /* 67 */
    TclBN_mp_set_u64, /* 68 */
    TclBN_mp_get_mag_u64, /* 69 */
    TclBN_mp_set_i64, /* 70 */
    0, /* 71 */
    0, /* 72 */
    TclBN_mp_unpack, /* 71 */
    TclBN_mp_pack, /* 72 */
    0, /* 73 */
    0, /* 74 */
    0, /* 75 */
    TclBN_mp_signed_rsh, /* 76 */
    0, /* 77 */
    TclBN_mp_pack_count, /* 77 */
    TclBN_mp_to_ubin, /* 78 */
    0, /* 79 */
    TclBN_mp_to_radix, /* 80 */
};

static const TclStubHooks tclStubHooks = {
    &tclPlatStubs,
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
824
825
826
827
828
829
830

831








832







833
834
835
836
837
838
839







-

-
-
-
-
-
-
-
-

-
-
-
-
-
-
-







    Tcl_Panic, /* 2 */
    Tcl_Alloc, /* 3 */
    Tcl_Free, /* 4 */
    Tcl_Realloc, /* 5 */
    Tcl_DbCkalloc, /* 6 */
    Tcl_DbCkfree, /* 7 */
    Tcl_DbCkrealloc, /* 8 */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
    Tcl_CreateFileHandler, /* 9 */
#endif /* UNIX */
#if defined(_WIN32) /* WIN */
    0, /* 9 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    Tcl_CreateFileHandler, /* 9 */
#endif /* MACOSX */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
    Tcl_DeleteFileHandler, /* 10 */
#endif /* UNIX */
#if defined(_WIN32) /* WIN */
    0, /* 10 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    Tcl_DeleteFileHandler, /* 10 */
#endif /* MACOSX */
    Tcl_SetTimer, /* 11 */
    Tcl_Sleep, /* 12 */
    Tcl_WaitForEvent, /* 13 */
    Tcl_AppendAllObjTypes, /* 14 */
    Tcl_AppendStringsToObj, /* 15 */
    Tcl_AppendToObj, /* 16 */
    Tcl_ConcatObj, /* 17 */
795
796
797
798
799
800
801
802

803
804
805
806

807
808

809
810
811
812
813
814
815
856
857
858
859
860
861
862

863
864
865
866

867
868

869
870
871
872
873
874
875
876







-
+



-
+

-
+







    Tcl_GetDouble, /* 34 */
    Tcl_GetDoubleFromObj, /* 35 */
    0, /* 36 */
    Tcl_GetInt, /* 37 */
    Tcl_GetIntFromObj, /* 38 */
    Tcl_GetLongFromObj, /* 39 */
    Tcl_GetObjType, /* 40 */
    Tcl_GetStringFromObj, /* 41 */
    TclGetStringFromObj, /* 41 */
    Tcl_InvalidateStringRep, /* 42 */
    Tcl_ListObjAppendList, /* 43 */
    Tcl_ListObjAppendElement, /* 44 */
    Tcl_ListObjGetElements, /* 45 */
    TclListObjGetElements, /* 45 */
    Tcl_ListObjIndex, /* 46 */
    Tcl_ListObjLength, /* 47 */
    TclListObjLength, /* 47 */
    Tcl_ListObjReplace, /* 48 */
    0, /* 49 */
    Tcl_NewByteArrayObj, /* 50 */
    Tcl_NewDoubleObj, /* 51 */
    0, /* 52 */
    Tcl_NewListObj, /* 53 */
    0, /* 54 */
835
836
837
838
839
840
841
842

843
844
845
846
847
848
849
896
897
898
899
900
901
902

903
904
905
906
907
908
909
910







-
+







    Tcl_AsyncMark, /* 74 */
    Tcl_AsyncReady, /* 75 */
    0, /* 76 */
    0, /* 77 */
    Tcl_BadChannelOption, /* 78 */
    Tcl_CallWhenDeleted, /* 79 */
    Tcl_CancelIdleCall, /* 80 */
    0, /* 81 */
    Tcl_Close, /* 81 */
    Tcl_CommandComplete, /* 82 */
    Tcl_Concat, /* 83 */
    Tcl_ConvertElement, /* 84 */
    Tcl_ConvertCountedElement, /* 85 */
    Tcl_CreateAlias, /* 86 */
    Tcl_CreateAliasObj, /* 87 */
    Tcl_CreateChannel, /* 88 */
902
903
904
905
906
907
908
909
910


911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
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







-
-
+
+

















-

-
-
-
-
-
-
-







    Tcl_ExprObj, /* 141 */
    Tcl_ExprString, /* 142 */
    Tcl_Finalize, /* 143 */
    0, /* 144 */
    Tcl_FirstHashEntry, /* 145 */
    Tcl_Flush, /* 146 */
    0, /* 147 */
    Tcl_GetAlias, /* 148 */
    Tcl_GetAliasObj, /* 149 */
    0, /* 148 */
    TclGetAliasObj, /* 149 */
    Tcl_GetAssocData, /* 150 */
    Tcl_GetChannel, /* 151 */
    Tcl_GetChannelBufferSize, /* 152 */
    Tcl_GetChannelHandle, /* 153 */
    Tcl_GetChannelInstanceData, /* 154 */
    Tcl_GetChannelMode, /* 155 */
    Tcl_GetChannelName, /* 156 */
    Tcl_GetChannelOption, /* 157 */
    Tcl_GetChannelType, /* 158 */
    Tcl_GetCommandInfo, /* 159 */
    Tcl_GetCommandName, /* 160 */
    Tcl_GetErrno, /* 161 */
    Tcl_GetHostName, /* 162 */
    Tcl_GetInterpPath, /* 163 */
    Tcl_GetParent, /* 164 */
    Tcl_GetNameOfExecutable, /* 165 */
    Tcl_GetObjResult, /* 166 */
#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */
    Tcl_GetOpenFile, /* 167 */
#endif /* UNIX */
#if defined(_WIN32) /* WIN */
    0, /* 167 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
    Tcl_GetOpenFile, /* 167 */
#endif /* MACOSX */
    Tcl_GetPathType, /* 168 */
    Tcl_Gets, /* 169 */
    Tcl_GetsObj, /* 170 */
    Tcl_GetServiceMode, /* 171 */
    Tcl_GetChild, /* 172 */
    Tcl_GetStdChannel, /* 173 */
    0, /* 174 */
952
953
954
955
956
957
958
959

960
961
962
963
964
965
966
1005
1006
1007
1008
1009
1010
1011

1012
1013
1014
1015
1016
1017
1018
1019







-
+







    Tcl_InputBuffered, /* 183 */
    Tcl_InterpDeleted, /* 184 */
    Tcl_IsSafe, /* 185 */
    Tcl_JoinPath, /* 186 */
    Tcl_LinkVar, /* 187 */
    0, /* 188 */
    Tcl_MakeFileChannel, /* 189 */
    Tcl_MakeSafe, /* 190 */
    0, /* 190 */
    Tcl_MakeTcpClientChannel, /* 191 */
    Tcl_Merge, /* 192 */
    Tcl_NextHashEntry, /* 193 */
    Tcl_NotifyChannel, /* 194 */
    Tcl_ObjGetVar2, /* 195 */
    Tcl_ObjSetVar2, /* 196 */
    Tcl_OpenCommandChannel, /* 197 */
1004
1005
1006
1007
1008
1009
1010
1011
1012


1013
1014
1015
1016
1017
1018
1019
1057
1058
1059
1060
1061
1062
1063


1064
1065
1066
1067
1068
1069
1070
1071
1072







-
-
+
+







    Tcl_SetObjResult, /* 235 */
    Tcl_SetStdChannel, /* 236 */
    0, /* 237 */
    Tcl_SetVar2, /* 238 */
    Tcl_SignalId, /* 239 */
    Tcl_SignalMsg, /* 240 */
    Tcl_SourceRCFile, /* 241 */
    Tcl_SplitList, /* 242 */
    Tcl_SplitPath, /* 243 */
    TclSplitList, /* 242 */
    TclSplitPath, /* 243 */
    0, /* 244 */
    0, /* 245 */
    0, /* 246 */
    0, /* 247 */
    Tcl_TraceVar2, /* 248 */
    Tcl_TranslateFileName, /* 249 */
    Tcl_Ungets, /* 250 */
1047
1048
1049
1050
1051
1052
1053
1054

1055
1056
1057
1058
1059
1060
1061
1100
1101
1102
1103
1104
1105
1106

1107
1108
1109
1110
1111
1112
1113
1114







-
+







    0, /* 278 */
    Tcl_GetVersion, /* 279 */
    Tcl_InitMemory, /* 280 */
    Tcl_StackChannel, /* 281 */
    Tcl_UnstackChannel, /* 282 */
    Tcl_GetStackedChannel, /* 283 */
    Tcl_SetMainLoop, /* 284 */
    0, /* 285 */
    Tcl_GetAliasObj, /* 285 */
    Tcl_AppendObjToObj, /* 286 */
    Tcl_CreateEncoding, /* 287 */
    Tcl_CreateThreadExitHandler, /* 288 */
    Tcl_DeleteThreadExitHandler, /* 289 */
    0, /* 290 */
    Tcl_EvalEx, /* 291 */
    Tcl_EvalObjv, /* 292 */
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
1116
1117
1118
1119
1120
1121

1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139


1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150


1151
1152
1153


1154
1155
1156
1157
1158
1159
1160
1127
1128
1129
1130
1131
1132
1133

1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146


1147
1148
1149
1150
1151


1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173

1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190


1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201


1202
1203
1204


1205
1206
1207
1208
1209
1210
1211
1212
1213







-
+












-
-
+
+



-
-
+
+




















-
+
















-
-
+
+









-
-
+
+

-
-
+
+







    Tcl_GetThreadData, /* 305 */
    Tcl_GetVar2Ex, /* 306 */
    Tcl_InitNotifier, /* 307 */
    Tcl_MutexLock, /* 308 */
    Tcl_MutexUnlock, /* 309 */
    Tcl_ConditionNotify, /* 310 */
    Tcl_ConditionWait, /* 311 */
    Tcl_NumUtfChars, /* 312 */
    TclNumUtfChars, /* 312 */
    Tcl_ReadChars, /* 313 */
    0, /* 314 */
    0, /* 315 */
    Tcl_SetSystemEncoding, /* 316 */
    Tcl_SetVar2Ex, /* 317 */
    Tcl_ThreadAlert, /* 318 */
    Tcl_ThreadQueueEvent, /* 319 */
    Tcl_UniCharAtIndex, /* 320 */
    Tcl_UniCharToLower, /* 321 */
    Tcl_UniCharToTitle, /* 322 */
    Tcl_UniCharToUpper, /* 323 */
    Tcl_UniCharToUtf, /* 324 */
    Tcl_UtfAtIndex, /* 325 */
    Tcl_UtfCharComplete, /* 326 */
    TclUtfAtIndex, /* 325 */
    TclUtfCharComplete, /* 326 */
    Tcl_UtfBackslash, /* 327 */
    Tcl_UtfFindFirst, /* 328 */
    Tcl_UtfFindLast, /* 329 */
    Tcl_UtfNext, /* 330 */
    Tcl_UtfPrev, /* 331 */
    TclUtfNext, /* 330 */
    TclUtfPrev, /* 331 */
    Tcl_UtfToExternal, /* 332 */
    Tcl_UtfToExternalDString, /* 333 */
    Tcl_UtfToLower, /* 334 */
    Tcl_UtfToTitle, /* 335 */
    Tcl_UtfToChar16, /* 336 */
    Tcl_UtfToUpper, /* 337 */
    Tcl_WriteChars, /* 338 */
    Tcl_WriteObj, /* 339 */
    Tcl_GetString, /* 340 */
    0, /* 341 */
    0, /* 342 */
    Tcl_AlertNotifier, /* 343 */
    Tcl_ServiceModeHook, /* 344 */
    Tcl_UniCharIsAlnum, /* 345 */
    Tcl_UniCharIsAlpha, /* 346 */
    Tcl_UniCharIsDigit, /* 347 */
    Tcl_UniCharIsLower, /* 348 */
    Tcl_UniCharIsSpace, /* 349 */
    Tcl_UniCharIsUpper, /* 350 */
    Tcl_UniCharIsWordChar, /* 351 */
    0, /* 352 */
    Tcl_Char16Len, /* 352 */
    0, /* 353 */
    Tcl_Char16ToUtfDString, /* 354 */
    Tcl_UtfToChar16DString, /* 355 */
    Tcl_GetRegExpFromObj, /* 356 */
    0, /* 357 */
    Tcl_FreeParse, /* 358 */
    Tcl_LogCommandInfo, /* 359 */
    Tcl_ParseBraces, /* 360 */
    Tcl_ParseCommand, /* 361 */
    Tcl_ParseExpr, /* 362 */
    Tcl_ParseQuotedString, /* 363 */
    Tcl_ParseVarName, /* 364 */
    Tcl_GetCwd, /* 365 */
    Tcl_Chdir, /* 366 */
    Tcl_Access, /* 367 */
    Tcl_Stat, /* 368 */
    Tcl_UtfNcmp, /* 369 */
    Tcl_UtfNcasecmp, /* 370 */
    TclUtfNcmp, /* 369 */
    TclUtfNcasecmp, /* 370 */
    Tcl_StringCaseMatch, /* 371 */
    Tcl_UniCharIsControl, /* 372 */
    Tcl_UniCharIsGraph, /* 373 */
    Tcl_UniCharIsPrint, /* 374 */
    Tcl_UniCharIsPunct, /* 375 */
    Tcl_RegExpExecObj, /* 376 */
    Tcl_RegExpGetInfo, /* 377 */
    Tcl_NewUnicodeObj, /* 378 */
    Tcl_SetUnicodeObj, /* 379 */
    Tcl_GetCharLength, /* 380 */
    Tcl_GetUniChar, /* 381 */
    TclGetCharLength, /* 380 */
    TclGetUniChar, /* 381 */
    0, /* 382 */
    Tcl_GetRange, /* 383 */
    0, /* 384 */
    TclGetRange, /* 383 */
    Tcl_AppendUnicodeToObj, /* 384 */
    Tcl_RegExpMatchObj, /* 385 */
    Tcl_SetNotifier, /* 386 */
    Tcl_GetAllocMutex, /* 387 */
    Tcl_GetChannelNames, /* 388 */
    Tcl_GetChannelNamesEx, /* 389 */
    Tcl_ProcObjCmd, /* 390 */
    Tcl_ConditionFinalize, /* 391 */
1196
1197
1198
1199
1200
1201
1202
1203

1204
1205
1206
1207
1208
1209
1210
1249
1250
1251
1252
1253
1254
1255

1256
1257
1258
1259
1260
1261
1262
1263







-
+







    Tcl_UntraceCommand, /* 427 */
    Tcl_AttemptAlloc, /* 428 */
    Tcl_AttemptDbCkalloc, /* 429 */
    Tcl_AttemptRealloc, /* 430 */
    Tcl_AttemptDbCkrealloc, /* 431 */
    Tcl_AttemptSetObjLength, /* 432 */
    Tcl_GetChannelThread, /* 433 */
    Tcl_GetUnicodeFromObj, /* 434 */
    TclGetUnicodeFromObj, /* 434 */
    0, /* 435 */
    0, /* 436 */
    Tcl_SubstObj, /* 437 */
    Tcl_DetachChannel, /* 438 */
    Tcl_IsStandardChannel, /* 439 */
    Tcl_FSCopyFile, /* 440 */
    Tcl_FSCopyDirectory, /* 441 */
1223
1224
1225
1226
1227
1228
1229
1230

1231
1232
1233
1234
1235
1236
1237
1276
1277
1278
1279
1280
1281
1282

1283
1284
1285
1286
1287
1288
1289
1290







-
+







    Tcl_FSStat, /* 454 */
    Tcl_FSAccess, /* 455 */
    Tcl_FSOpenFileChannel, /* 456 */
    Tcl_FSGetCwd, /* 457 */
    Tcl_FSChdir, /* 458 */
    Tcl_FSConvertToPathType, /* 459 */
    Tcl_FSJoinPath, /* 460 */
    Tcl_FSSplitPath, /* 461 */
    TclFSSplitPath, /* 461 */
    Tcl_FSEqualPaths, /* 462 */
    Tcl_FSGetNormalizedPath, /* 463 */
    Tcl_FSJoinToPath, /* 464 */
    Tcl_FSGetInternalRep, /* 465 */
    Tcl_FSGetTranslatedPath, /* 466 */
    Tcl_FSEvalFile, /* 467 */
    Tcl_FSNewNativePath, /* 468 */
1259
1260
1261
1262
1263
1264
1265
1266

1267
1268
1269
1270
1271
1272
1273
1312
1313
1314
1315
1316
1317
1318

1319
1320
1321
1322
1323
1324
1325
1326







-
+







    Tcl_AllocStatBuf, /* 490 */
    Tcl_Seek, /* 491 */
    Tcl_Tell, /* 492 */
    Tcl_ChannelWideSeekProc, /* 493 */
    Tcl_DictObjPut, /* 494 */
    Tcl_DictObjGet, /* 495 */
    Tcl_DictObjRemove, /* 496 */
    Tcl_DictObjSize, /* 497 */
    TclDictObjSize, /* 497 */
    Tcl_DictObjFirst, /* 498 */
    Tcl_DictObjNext, /* 499 */
    Tcl_DictObjDone, /* 500 */
    Tcl_DictObjPutKeyList, /* 501 */
    Tcl_DictObjRemoveKeyList, /* 502 */
    Tcl_NewDictObj, /* 503 */
    Tcl_DbNewDictObj, /* 504 */
1366
1367
1368
1369
1370
1371
1372
1373

1374
1375
1376
1377
1378
1379
1380
1419
1420
1421
1422
1423
1424
1425

1426
1427
1428
1429
1430
1431
1432
1433







-
+







    Tcl_GetModificationTimeFromStat, /* 597 */
    Tcl_GetChangeTimeFromStat, /* 598 */
    Tcl_GetSizeFromStat, /* 599 */
    Tcl_GetBlocksFromStat, /* 600 */
    Tcl_GetBlockSizeFromStat, /* 601 */
    Tcl_SetEnsembleParameterList, /* 602 */
    Tcl_GetEnsembleParameterList, /* 603 */
    Tcl_ParseArgsObjv, /* 604 */
    TclParseArgsObjv, /* 604 */
    Tcl_GetErrorLine, /* 605 */
    Tcl_SetErrorLine, /* 606 */
    Tcl_TransferResult, /* 607 */
    Tcl_InterpActive, /* 608 */
    Tcl_BackgroundException, /* 609 */
    Tcl_ZlibDeflate, /* 610 */
    Tcl_ZlibInflate, /* 611 */
1398
1399
1400
1401
1402
1403
1404
1405

1406
1407
1408


1409
1410
1411
1412
1413
1414
1415
1416
1417










































1418
1419
1420
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515







-
+

-
-
+
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



    Tcl_FSUnloadFile, /* 629 */
    Tcl_ZlibStreamSetCompressionDictionary, /* 630 */
    Tcl_OpenTcpServerEx, /* 631 */
    TclZipfs_Mount, /* 632 */
    TclZipfs_Unmount, /* 633 */
    TclZipfs_TclLibrary, /* 634 */
    TclZipfs_MountBuffer, /* 635 */
    Tcl_FreeIntRep, /* 636 */
    Tcl_FreeInternalRep, /* 636 */
    Tcl_InitStringRep, /* 637 */
    Tcl_FetchIntRep, /* 638 */
    Tcl_StoreIntRep, /* 639 */
    Tcl_FetchInternalRep, /* 638 */
    Tcl_StoreInternalRep, /* 639 */
    Tcl_HasStringRep, /* 640 */
    Tcl_IncrRefCount, /* 641 */
    Tcl_DecrRefCount, /* 642 */
    Tcl_IsShared, /* 643 */
    Tcl_LinkArray, /* 644 */
    Tcl_GetIntForIndex, /* 645 */
    Tcl_UtfToUniChar, /* 646 */
    Tcl_UniCharToUtfDString, /* 647 */
    Tcl_UtfToUniCharDString, /* 648 */
    TclGetBytesFromObj, /* 649 */
    Tcl_GetBytesFromObj, /* 650 */
    Tcl_GetStringFromObj, /* 651 */
    Tcl_GetUnicodeFromObj, /* 652 */
    Tcl_GetSizeIntFromObj, /* 653 */
    Tcl_UtfCharComplete, /* 654 */
    Tcl_UtfNext, /* 655 */
    Tcl_UtfPrev, /* 656 */
    Tcl_FSTildeExpand, /* 657 */
    Tcl_ExternalToUtfDStringEx, /* 658 */
    Tcl_UtfToExternalDStringEx, /* 659 */
    Tcl_AsyncMarkFromSignal, /* 660 */
    Tcl_ListObjGetElements, /* 661 */
    Tcl_ListObjLength, /* 662 */
    Tcl_DictObjSize, /* 663 */
    Tcl_SplitList, /* 664 */
    Tcl_SplitPath, /* 665 */
    Tcl_FSSplitPath, /* 666 */
    Tcl_ParseArgsObjv, /* 667 */
    Tcl_UniCharLen, /* 668 */
    Tcl_NumUtfChars, /* 669 */
    Tcl_GetCharLength, /* 670 */
    Tcl_UtfAtIndex, /* 671 */
    Tcl_GetRange, /* 672 */
    Tcl_GetUniChar, /* 673 */
    Tcl_GetBool, /* 674 */
    Tcl_GetBoolFromObj, /* 675 */
    Tcl_CreateObjCommand2, /* 676 */
    Tcl_CreateObjTrace2, /* 677 */
    Tcl_NRCreateCommand2, /* 678 */
    Tcl_NRCallObjProc2, /* 679 */
    Tcl_GetNumberFromObj, /* 680 */
    Tcl_GetNumber, /* 681 */
    Tcl_RemoveChannelMode, /* 682 */
    Tcl_GetEncodingNulLength, /* 683 */
    Tcl_GetWideUIntFromObj, /* 684 */
    Tcl_DStringToObj, /* 685 */
    Tcl_UtfNcmp, /* 686 */
    Tcl_UtfNcasecmp, /* 687 */
    Tcl_NewWideUIntObj, /* 688 */
    Tcl_SetWideUIntObj, /* 689 */
    TclUnusedStubEntry, /* 690 */
};

/* !END!: Do not edit above this line. */

Changes to generic/tclStubLib.c.

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
30
31
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
30
31
32
33






-
-
+
+











+





+







/*
 * tclStubLib.c --
 *
 *	Stub object that will be statically linked into extensions that want
 *	to access Tcl.
 *
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright (c) 1998 Paul Duffin.
 * Copyright © 1998-1999 Scriptics Corporation.
 * Copyright © 1998 Paul Duffin.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

MODULE_SCOPE const TclStubs *tclStubsPtr;
MODULE_SCOPE const TclPlatStubs *tclPlatStubsPtr;
MODULE_SCOPE const TclIntStubs *tclIntStubsPtr;
MODULE_SCOPE const TclIntPlatStubs *tclIntPlatStubsPtr;
MODULE_SCOPE void *tclStubsHandle;

const TclStubs *tclStubsPtr = NULL;
const TclPlatStubs *tclPlatStubsPtr = NULL;
const TclIntStubs *tclIntStubsPtr = NULL;
const TclIntPlatStubs *tclIntPlatStubsPtr = NULL;
void *tclStubsHandle = NULL;

/*
 * Use our own ISDIGIT to avoid linking to libc on windows
 */

#define ISDIGIT(c) (((unsigned)((c)-'0')) <= 9)

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
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







-
+

-
+

+

+
+












-
+



















-
+



-
+








+
+
+







MODULE_SCOPE const char *
Tcl_InitStubs(
    Tcl_Interp *interp,
    const char *version,
    int exact,
    int magic)
{
    Interp *iPtr = (Interp *) interp;
    Interp *iPtr = (Interp *)interp;
    const char *actualVersion = NULL;
    ClientData pkgData = NULL;
    void *pkgData = NULL;
    const TclStubs *stubsPtr = iPtr->stubTable;
    const char *tclName = (((exact&0xFF00) >= 0x900) ? "tcl" : "Tcl");

#undef TCL_STUB_MAGIC /* We need the TCL_STUB_MAGIC from Tcl 8.x here */
#define TCL_STUB_MAGIC		((int) 0xFCA3BACF)
    /*
     * We can't optimize this check by caching tclStubsPtr because that
     * prevents apps from being able to load/unload Tcl dynamically multiple
     * times. [Bug 615304]
     */

    if (!stubsPtr || (stubsPtr->magic != (((exact&0xFF00) >= 0x900) ? magic : TCL_STUB_MAGIC))) {
	iPtr->legacyResult = "interpreter uses an incompatible stubs mechanism";
	iPtr->legacyFreeProc = 0; /* TCL_STATIC */
	return NULL;
    }

    actualVersion = stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 0, &pkgData);
    actualVersion = stubsPtr->tcl_PkgRequireEx(interp, tclName, version, 0, &pkgData);
    if (actualVersion == NULL) {
	return NULL;
    }
    if (exact&1) {
	const char *p = version;
	int count = 0;

	while (*p) {
	    count += !ISDIGIT(*p++);
	}
	if (count == 1) {
	    const char *q = actualVersion;

	    p = version;
	    while (*p && (*p == *q)) {
		p++; q++;
	    }
	    if (*p || ISDIGIT(*q)) {
		/* Construct error message */
		stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL);
		stubsPtr->tcl_PkgRequireEx(interp, tclName, version, 1, NULL);
		return NULL;
	    }
	} else {
	    actualVersion = stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL);
	    actualVersion = stubsPtr->tcl_PkgRequireEx(interp, tclName, version, 1, NULL);
	    if (actualVersion == NULL) {
		return NULL;
	    }
	}
    }
    if (((exact&0xFF00) < 0x900)) {
	/* We are running Tcl 8.x */
	stubsPtr = (TclStubs *)pkgData;
    }
    if (tclStubsHandle == NULL) {
	tclStubsHandle = INT2PTR(-1);
    }
    tclStubsPtr = stubsPtr;

    if (stubsPtr->hooks) {
	tclPlatStubsPtr = stubsPtr->hooks->tclPlatStubs;
	tclIntStubsPtr = stubsPtr->hooks->tclIntStubs;
	tclIntPlatStubsPtr = stubsPtr->hooks->tclIntPlatStubs;

Added generic/tclStubLibTbl.c.





































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tclStubLibTbl.c --
 *
 *	Stub object that will be statically linked into extensions that want
 *	to access Tcl.
 *
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright (c) 1998 Paul Duffin.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

MODULE_SCOPE void *tclStubsHandle;

/*
 *----------------------------------------------------------------------
 *
 * TclInitStubTable --
 *
 *	Initialize the stub table, using the structure pointed at
 *	by the "version" argument.
 *
 * Results:
 *	Outputs the value of the "version" argument.
 *
 * Side effects:
 *	Sets the stub table pointers.
 *
 *----------------------------------------------------------------------
 */
MODULE_SCOPE const char *
TclInitStubTable(
    const char *version)	/* points to the version field of a
				 * structure variable. */
{
    if (version) {
	if (tclStubsHandle == NULL) {
	    /* This can only happen with -DBUILD_STATIC, so simulate
	     * that the loading of Tcl succeeded, although we didn't
	     * actually load it dynamically */
	    tclStubsHandle = (void *)1;
	}
	tclStubsPtr = ((const TclStubs **) version)[-1];

	if (tclStubsPtr->hooks) {
	    tclPlatStubsPtr = tclStubsPtr->hooks->tclPlatStubs;
	    tclIntStubsPtr = tclStubsPtr->hooks->tclIntStubs;
	    tclIntPlatStubsPtr = tclStubsPtr->hooks->tclIntPlatStubs;
	} else {
	    tclPlatStubsPtr = NULL;
	    tclIntStubsPtr = NULL;
	    tclIntPlatStubsPtr = NULL;
	}
    }

    return version;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclTest.c.

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
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
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
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








-
-
-
-
+
+
+
+





+
+




+

-
-
-
-
-












+
+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







/*
 * tclTest.c --
 *
 *	This file contains C command functions for a bunch of additional Tcl
 *	commands that are used for testing out Tcl's C interfaces. These
 *	commands are not normally included in Tcl applications; they're only
 *	used for testing.
 *
 * Copyright (c) 1993-1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 Ajuba Solutions.
 * Copyright (c) 2003 by Kevin B. Kenny.  All rights reserved.
 * Copyright © 1993-1994 The Regents of the University of California.
 * Copyright © 1994-1997 Sun Microsystems, Inc.
 * Copyright © 1998-2000 Ajuba Solutions.
 * Copyright © 2003 Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#define TCL_8_API
#undef BUILD_tcl
#undef STATIC_BUILD
#ifndef USE_TCL_STUBS
#   define USE_TCL_STUBS
#endif
#define TCLBOOLWARNING(boolPtr) /* needed here because we compile with -Wc++-compat */
#include "tclInt.h"
#ifdef TCL_WITH_EXTERNAL_TOMMATH
#   include "tommath.h"
#else
#   include "tclTomMath.h"
#endif
#include "tclOO.h"
#include <math.h>

/*
 * Required for Testregexp*Cmd
 */
#include "tclRegexp.h"

/*
 * Required for the TestChannelCmd and TestChannelEventCmd
 */
#include "tclIO.h"

#include "tclUuid.h"

/*
 * Declare external functions used in Windows tests.
 */
DLLEXPORT int		Tcltest_Init(Tcl_Interp *interp);
DLLEXPORT int		Tcltest_SafeInit(Tcl_Interp *interp);

/*
 * Dynamic string shared by TestdcallCmd and DelCallbackProc; used to collect
 * the results of the various deletion callbacks.
 */

static Tcl_DString delString;
static Tcl_Interp *delInterp;

/*
 * One of the following structures exists for each command created by the
 * "testcmdtoken" command.
 */

typedef struct TestCommandTokenRef {
    int id;			/* Identifier for this reference. */
    Tcl_Command token;		/* Tcl's token for the command. */
    const char *value;
    struct TestCommandTokenRef *nextPtr;
				/* Next in list of references. */
} TestCommandTokenRef;

static TestCommandTokenRef *firstCommandTokenRef = NULL;
static int nextCommandTokenRefId = 1;

/*
 * One of the following structures exists for each asynchronous handler
 * created by the "testasync" command".
 */

typedef struct TestAsyncHandler {
    int id;			/* Identifier for this handler. */
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







-
+
-







 * Start of the socket driver state structure to acces field testFlags
 */

typedef struct TcpState TcpState;

struct TcpState {
    Tcl_Channel channel;	/* Channel associated with this socket. */
    int testFlags;              /* bit field for tests. Is set by testsocket
    int flags;			/* ORed combination of various bitfields. */
                                 * test procedure */
};

TCL_DECLARE_MUTEX(asyncTestMutex)

static TestAsyncHandler *firstHandler = NULL;

/*
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
129
130
131
132
133
134
135







136
137
138
139
140
141
142







-
-
-
-
-
-
-








typedef struct {
    Tcl_Interp *interp;
    char *toUtfCmd;
    char *fromUtfCmd;
} TclEncoding;

/*
 * The counter below is used to determine if the TestsaveresultFree routine
 * was called for a result.
 */

static int freeCount;

/*
 * Boolean flag used by the "testsetmainloop" and "testexitmainloop" commands.
 */

static int exitMainLoop = 0;

/*
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
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







-

-






-
+
-
-
-
-
-
+
-
-
-
-
-
+
+


-
+














-
+




-
+
-
-
-


-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
+
+

-
+

-
-
+
+


-
-
-
-
-
+
+
+
+
+

-
-
+
+

+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+


-
+
-
-
-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-








/*
 * Forward declarations for procedures defined later in this file:
 */

static int		AsyncHandlerProc(void *clientData,
			    Tcl_Interp *interp, int code);
#if TCL_THREADS
static Tcl_ThreadCreateType AsyncThreadProc(void *);
#endif
static void		CleanupTestSetassocdataTests(
			    void *clientData, Tcl_Interp *interp);
static void		CmdDelProc1(void *clientData);
static void		CmdDelProc2(void *clientData);
static Tcl_CmdProc	CmdProc1;
static Tcl_CmdProc	CmdProc2;
static void		CmdTraceDeleteProc(
static Tcl_CmdObjTraceProc	CmdTraceDeleteProc;
			    void *clientData, Tcl_Interp *interp,
			    int level, char *command, Tcl_CmdProc *cmdProc,
			    void *cmdClientData, int argc,
			    const char *argv[]);
static void		CmdTraceProc(void *clientData,
static Tcl_CmdObjTraceProc	CmdTraceProc;
			    Tcl_Interp *interp, int level, char *command,
			    Tcl_CmdProc *cmdProc, void *cmdClientData,
			    int argc, const char *argv[]);
static Tcl_CmdProc	CreatedCommandProc;
static Tcl_CmdProc	CreatedCommandProc2;
static Tcl_ObjCmdProc	CreatedCommandProc;
static Tcl_ObjCmdProc	CreatedCommandProc2;
static void		DelCallbackProc(void *clientData,
			    Tcl_Interp *interp);
static Tcl_CmdProc	DelCmdProc;
static Tcl_ObjCmdProc	DelCmdProc;
static void		DelDeleteProc(void *clientData);
static void		EncodingFreeProc(void *clientData);
static int		EncodingToUtfProc(void *clientData,
			    const char *src, int srcLen, int flags,
			    Tcl_EncodingState *statePtr, char *dst,
			    int dstLen, int *srcReadPtr, int *dstWrotePtr,
			    int *dstCharsPtr);
static int		EncodingFromUtfProc(void *clientData,
			    const char *src, int srcLen, int flags,
			    Tcl_EncodingState *statePtr, char *dst,
			    int dstLen, int *srcReadPtr, int *dstWrotePtr,
			    int *dstCharsPtr);
static void		ExitProcEven(void *clientData);
static void		ExitProcOdd(void *clientData);
static Tcl_ObjCmdProc	GetTimesObjCmd;
static Tcl_ObjCmdProc	GetTimesCmd;
static Tcl_ResolveCompiledVarProc	InterpCompiledVarResolver;
static void		MainLoop(void);
static Tcl_CmdProc	NoopCmd;
static Tcl_ObjCmdProc	NoopObjCmd;
static int		ObjTraceProc(void *clientData,
static Tcl_CmdObjTraceProc TraceProc;
			    Tcl_Interp *interp, int level, const char *command,
			    Tcl_Command commandToken, int objc,
			    Tcl_Obj *const objv[]);
static void		ObjTraceDeleteProc(void *clientData);
static void		PrintParse(Tcl_Interp *interp, Tcl_Parse *parsePtr);
static void		SpecialFree(void *blockPtr);
static Tcl_FreeProc	SpecialFree;
static int		StaticInitProc(Tcl_Interp *interp);
static Tcl_CmdProc	TestasyncCmd;
static Tcl_ObjCmdProc	TestbumpinterpepochObjCmd;
static Tcl_ObjCmdProc	TestbytestringObjCmd;
static Tcl_ObjCmdProc	TestsetbytearraylengthObjCmd;
static Tcl_ObjCmdProc	TestpurebytesobjObjCmd;
static Tcl_ObjCmdProc	TeststringbytesObjCmd;
static Tcl_CmdProc	TestcmdinfoCmd;
static Tcl_CmdProc	TestcmdtokenCmd;
static Tcl_CmdProc	TestcmdtraceCmd;
static Tcl_CmdProc	TestconcatobjCmd;
static Tcl_CmdProc	TestcreatecommandCmd;
static Tcl_CmdProc	TestdcallCmd;
static Tcl_CmdProc	TestdelCmd;
static Tcl_CmdProc	TestdelassocdataCmd;
static Tcl_ObjCmdProc	TestdoubledigitsObjCmd;
static Tcl_CmdProc	TestdstringCmd;
static Tcl_ObjCmdProc	TestencodingObjCmd;
static Tcl_ObjCmdProc	TestevalexObjCmd;
static Tcl_ObjCmdProc	TestevalobjvObjCmd;
static Tcl_ObjCmdProc	TesteventObjCmd;
static Tcl_ObjCmdProc	TestasyncCmd;
static Tcl_ObjCmdProc	TestbumpinterpepochCmd;
static Tcl_ObjCmdProc	TestbytestringCmd;
static Tcl_ObjCmdProc	TestsetbytearraylengthCmd;
static Tcl_ObjCmdProc	TestpurebytesobjCmd;
static Tcl_ObjCmdProc	TeststringbytesCmd;
static Tcl_ObjCmdProc2	Testcmdobj2Cmd;
static Tcl_ObjCmdProc	TestcmdinfoCmd;
static Tcl_ObjCmdProc	TestcmdtokenCmd;
static Tcl_ObjCmdProc	TestcmdtraceCmd;
static Tcl_ObjCmdProc	TestconcatobjCmd;
static Tcl_ObjCmdProc	TestcreatecommandCmd;
static Tcl_ObjCmdProc	TestdcallCmd;
static Tcl_ObjCmdProc	TestdelCmd;
static Tcl_ObjCmdProc	TestdelassocdataCmd;
static Tcl_ObjCmdProc	TestdoubledigitsCmd;
static Tcl_ObjCmdProc	TestdstringCmd;
static Tcl_ObjCmdProc	TestencodingCmd;
static Tcl_ObjCmdProc	TestevalexCmd;
static Tcl_ObjCmdProc	TestevalobjvCmd;
static Tcl_ObjCmdProc	TesteventCmd;
static int		TesteventProc(Tcl_Event *event, int flags);
static int		TesteventDeleteProc(Tcl_Event *event,
			    void *clientData);
static Tcl_CmdProc	TestexithandlerCmd;
static Tcl_CmdProc	TestexprlongCmd;
static Tcl_ObjCmdProc	TestexithandlerCmd;
static Tcl_ObjCmdProc	TestexprlongCmd;
static Tcl_ObjCmdProc	TestexprlongobjCmd;
static Tcl_CmdProc	TestexprdoubleCmd;
static Tcl_ObjCmdProc	TestexprdoubleCmd;
static Tcl_ObjCmdProc	TestexprdoubleobjCmd;
static Tcl_ObjCmdProc	TestexprparserObjCmd;
static Tcl_CmdProc	TestexprstringCmd;
static Tcl_ObjCmdProc	TestexprparserCmd;
static Tcl_ObjCmdProc	TestexprstringCmd;
static Tcl_ObjCmdProc	TestfileCmd;
static Tcl_ObjCmdProc	TestfilelinkCmd;
static Tcl_CmdProc	TestfeventCmd;
static Tcl_CmdProc	TestgetassocdataCmd;
static Tcl_CmdProc	TestgetintCmd;
static Tcl_CmdProc	TestlongsizeCmd;
static Tcl_CmdProc	TestgetplatformCmd;
static Tcl_ObjCmdProc	TestfeventCmd;
static Tcl_ObjCmdProc	TestgetassocdataCmd;
static Tcl_ObjCmdProc	TestgetintCmd;
static Tcl_ObjCmdProc	TestlongsizeCmd;
static Tcl_ObjCmdProc	TestgetplatformCmd;
static Tcl_ObjCmdProc	TestgetvarfullnameCmd;
static Tcl_CmdProc	TestinterpdeleteCmd;
static Tcl_CmdProc	TestlinkCmd;
static Tcl_ObjCmdProc	TestinterpdeleteCmd;
static Tcl_ObjCmdProc	TestlinkCmd;
static Tcl_ObjCmdProc	TestlinkarrayCmd;
static Tcl_ObjCmdProc	TestlistrepCmd;
static Tcl_ObjCmdProc	TestlocaleCmd;
static Tcl_CmdProc	TestmainthreadCmd;
static Tcl_CmdProc	TestsetmainloopCmd;
static Tcl_CmdProc	TestexitmainloopCmd;
static Tcl_CmdProc	TestpanicCmd;
static Tcl_ObjCmdProc	TestmainthreadCmd;
static Tcl_ObjCmdProc	TestsetmainloopCmd;
static Tcl_ObjCmdProc	TestexitmainloopCmd;
static Tcl_ObjCmdProc	TestpanicCmd;
static Tcl_ObjCmdProc	TestparseargsCmd;
static Tcl_ObjCmdProc	TestparserObjCmd;
static Tcl_ObjCmdProc	TestparsevarObjCmd;
static Tcl_ObjCmdProc	TestparsevarnameObjCmd;
static Tcl_ObjCmdProc	TestpreferstableObjCmd;
static Tcl_ObjCmdProc	TestprintObjCmd;
static Tcl_ObjCmdProc	TestregexpObjCmd;
static Tcl_ObjCmdProc	TestreturnObjCmd;
static Tcl_ObjCmdProc	TestparserCmd;
static Tcl_ObjCmdProc	TestparsevarCmd;
static Tcl_ObjCmdProc	TestparsevarnameCmd;
static Tcl_ObjCmdProc	TestpreferstableCmd;
static Tcl_ObjCmdProc	TestprintCmd;
static Tcl_ObjCmdProc	TestregexpCmd;
static Tcl_ObjCmdProc	TestreturnCmd;
static void		TestregexpXflags(const char *string,
			    size_t length, int *cflagsPtr, int *eflagsPtr);
static Tcl_ObjCmdProc	TestsaveresultCmd;
static Tcl_ObjCmdProc	TestsetassocdataCmd;
static void		TestsaveresultFree(void *blockPtr);
static Tcl_CmdProc	TestsetassocdataCmd;
static Tcl_CmdProc	TestsetCmd;
static Tcl_CmdProc	Testset2Cmd;
static Tcl_CmdProc	TestseterrorcodeCmd;
static Tcl_ObjCmdProc	TestsetCmd;
static Tcl_ObjCmdProc	Testset2Cmd;
static Tcl_ObjCmdProc	TestseterrorcodeCmd;
static Tcl_ObjCmdProc	TestsetobjerrorcodeCmd;
static Tcl_CmdProc	TestsetplatformCmd;
static Tcl_CmdProc	TeststaticpkgCmd;
static Tcl_CmdProc	TesttranslatefilenameCmd;
static Tcl_CmdProc	TestupvarCmd;
static Tcl_ObjCmdProc	TestWrongNumArgsObjCmd;
static Tcl_ObjCmdProc	TestGetIndexFromObjStructObjCmd;
static Tcl_CmdProc	TestChannelCmd;
static Tcl_CmdProc	TestChannelEventCmd;
static Tcl_CmdProc	TestSocketCmd;
static Tcl_ObjCmdProc	TestFilesystemObjCmd;
static Tcl_ObjCmdProc	TestSimpleFilesystemObjCmd;
static Tcl_ObjCmdProc	TestsetplatformCmd;
static Tcl_ObjCmdProc	TestSizeCmd;
static Tcl_ObjCmdProc	TeststaticlibraryCmd;
static Tcl_ObjCmdProc	TesttranslatefilenameCmd;
static Tcl_ObjCmdProc	TestfstildeexpandCmd;
static Tcl_ObjCmdProc	TestupvarCmd;
static Tcl_ObjCmdProc2	TestWrongNumArgsCmd;
static Tcl_ObjCmdProc	TestGetIndexFromObjStructCmd;
static Tcl_ObjCmdProc	TestChannelCmd;
static Tcl_ObjCmdProc	TestChannelEventCmd;
static Tcl_ObjCmdProc	TestSocketCmd;
static Tcl_ObjCmdProc	TestFilesystemCmd;
static Tcl_ObjCmdProc	TestSimpleFilesystemCmd;
static void		TestReport(const char *cmd, Tcl_Obj *arg1,
			    Tcl_Obj *arg2);
static Tcl_ObjCmdProc	TestgetencpathObjCmd;
static Tcl_ObjCmdProc	TestsetencpathObjCmd;
static Tcl_Obj *	TestReportGetNativePath(Tcl_Obj *pathPtr);
static Tcl_FSStatProc TestReportStat;
static Tcl_FSAccessProc TestReportAccess;
static Tcl_FSOpenFileChannelProc TestReportOpenFileChannel;
static Tcl_FSMatchInDirectoryProc TestReportMatchInDirectory;
static Tcl_FSChdirProc TestReportChdir;
static Tcl_FSLstatProc TestReportLstat;
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
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







-
+










+



-
+
+




-
+


+







static Tcl_FSFileAttrsGetProc TestReportFileAttrsGet;
static Tcl_FSFileAttrsSetProc TestReportFileAttrsSet;
static Tcl_FSUtimeProc TestReportUtime;
static Tcl_FSNormalizePathProc TestReportNormalizePath;
static Tcl_FSPathInFilesystemProc TestReportInFilesystem;
static Tcl_FSFreeInternalRepProc TestReportFreeInternalRep;
static Tcl_FSDupInternalRepProc TestReportDupInternalRep;
static Tcl_CmdProc TestServiceModeCmd;
static Tcl_ObjCmdProc	TestServiceModeCmd;
static Tcl_FSStatProc SimpleStat;
static Tcl_FSAccessProc SimpleAccess;
static Tcl_FSOpenFileChannelProc SimpleOpenFileChannel;
static Tcl_FSListVolumesProc SimpleListVolumes;
static Tcl_FSPathInFilesystemProc SimplePathInFilesystem;
static Tcl_Obj *	SimpleRedirect(Tcl_Obj *pathPtr);
static Tcl_FSMatchInDirectoryProc SimpleMatchInDirectory;
static Tcl_ObjCmdProc	TestUtfNextCmd;
static Tcl_ObjCmdProc	TestUtfPrevCmd;
static Tcl_ObjCmdProc	TestNumUtfCharsCmd;
static Tcl_ObjCmdProc	TestGetUniCharCmd;
static Tcl_ObjCmdProc	TestFindFirstCmd;
static Tcl_ObjCmdProc	TestFindLastCmd;
static Tcl_ObjCmdProc	TestHashSystemHashCmd;

static Tcl_ObjCmdProc	TestGetIntForIndexCmd;
static Tcl_ObjCmdProc	TestLutilCmd;
static Tcl_NRPostProc	NREUnwind_callback;
static Tcl_ObjCmdProc	TestNREUnwind;
static Tcl_ObjCmdProc	TestNRELevels;
static Tcl_ObjCmdProc	TestInterpResolverCmd;
#if defined(HAVE_CPUID) || defined(_WIN32)
#if defined(HAVE_CPUID) && !defined(MAC_OSX_TCL)
static Tcl_ObjCmdProc	TestcpuidCmd;
#endif
static Tcl_ObjCmdProc	TestApplyLambdaCmd;

static const Tcl_Filesystem testReportingFilesystem = {
    "reporting",
    sizeof(Tcl_Filesystem),
    TCL_FILESYSTEM_VERSION_1,
    TestReportInFilesystem, /* path in */
    TestReportDupInternalRep,
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
467
468
469
470
471

472
473
474
475
476
477
478





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
558

559
560

561
562

563
564

565
566

567
568

569
570

571
572

573
574
575
576

577
578

579
580

581
582

583
584

585
586

587
588
589
590
591
592
593
594
595


596
597
598
599


600

601

602

603
604

605
606

607


608
609


610
611

612
613

614
615

616
617
618
619
620
621
622
623
624
625

626
627

628
629
630
631
632
633
634
635
636
637
638
639
640




641
642
643
644
645
646
647
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
467
468
469
470
471
472
473
474
475
476
477
478
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

558
559

560
561
562


563
564
565


566
567
568

569
570

571
572
573
574

575
576

577
578

579
580

581
582



583
584
585
586

587
588
589

590
591

592
593

594
595

596
597

598
599

600
601

602
603
604
605

606
607
608
609

610
611

612
613

614
615
616
617
618
619
620
621

622
623

624
625

626
627

628
629
630
631

632
633

634
635
636
637
638

639
640

641
642

643
644

645
646

647
648

649
650

651
652

653
654



655
656

657
658

659
660

661
662

663
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
707
708
709
710

711
712

713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+

+
-
+





-
+


-
-
-
-
-



-
-
-
+
+
+
+
+
+
+
+
+
+
+
+







-
+


-
-
-
-
-
+
+
+
+
+

-
+

-
+


-
-
+
+

-
-
+
+

-
+

-
+

+
+
-
+

-
+

-
+

-
+

-
-
-
+
+
+

-
+


-
+

-
+

-
+

-
+

-
+

-
+

-
+



-
+



-
+

-
+

-
+







-
+

-
+

-
+

-
+



-
+

-
+

+


-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
-
-
+

-
+

-
+

-
+

-
+

-
+









+
+




+
+
-
+

+
-
+

-
+

-
+

+
+
-
-
+
+

-
+

-
+

-
+









-
+

-
+













+
+
+
+







 *	the interp's result if an error occurs.
 *
 * Side effects:
 *	Depends on the startup script.
 *
 *----------------------------------------------------------------------
 */

#ifndef STRINGIFY
#  define STRINGIFY(x) STRINGIFY1(x)
#  define STRINGIFY1(x) #x
#endif

static const char version[] = TCL_PATCH_LEVEL "+" STRINGIFY(TCL_VERSION_UUID)
#if defined(__clang__) && defined(__clang_major__)
	    ".clang-" STRINGIFY(__clang_major__)
#if __clang_minor__ < 10
	    "0"
#endif
	    STRINGIFY(__clang_minor__)
#endif
#ifdef TCL_COMPILE_DEBUG
	    ".compiledebug"
#endif
#ifdef TCL_COMPILE_STATS
	    ".compilestats"
#endif
#if defined(__cplusplus) && !defined(__OBJC__)
	    ".cplusplus"
#endif
#ifndef NDEBUG
	    ".debug"
#endif
#if !defined(__clang__) && !defined(__INTEL_COMPILER) && defined(__GNUC__)
	    ".gcc-" STRINGIFY(__GNUC__)
#if __GNUC_MINOR__ < 10
	    "0"
#endif
	    STRINGIFY(__GNUC_MINOR__)
#endif
#ifdef __INTEL_COMPILER
	    ".icc-" STRINGIFY(__INTEL_COMPILER)
#endif
#if (defined(_WIN32) && !defined(_WIN64)) || (ULONG_MAX == 0xffffffffUL)
	    ".ilp32"
#endif
#ifdef TCL_MEM_DEBUG
	    ".memdebug"
#endif
#if defined(_MSC_VER)
	    ".msvc-" STRINGIFY(_MSC_VER)
#endif
#ifdef USE_NMAKE
	    ".nmake"
#endif
#if !TCL_THREADS
	    ".no-thread"
#endif
#ifndef TCL_CFG_OPTIMIZED
	    ".no-optimize"
#endif
#ifdef __OBJC__
	    ".objective-c"
#if defined(__cplusplus)
	    "plusplus"
#endif
#endif
#ifdef TCL_CFG_PROFILED
	    ".profile"
#endif
#ifdef PURIFY
	    ".purify"
#endif
#ifdef STATIC_BUILD
	    ".static"
#endif
#if TCL_UTF_MAX < 4
	    ".utf-16"
#endif
;

int
Tcltest_Init(
    Tcl_Interp *interp)		/* Interpreter for application. */
{
    Tcl_CmdInfo info;
    Tcl_Obj **objv, *objPtr;
    Tcl_Size objc;
    int objc, index;
    int index;
    static const char *const specialOptions[] = {
	"-appinitprocerror", "-appinitprocdeleteinterp",
	"-appinitprocclosestderr", "-appinitprocsetrcfile", NULL
    };

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
    if (Tcl_InitStubs(interp, "8.7-", 0) == NULL) {
	return TCL_ERROR;
    }
#ifndef TCL_WITH_EXTERNAL_TOMMATH
    if (Tcl_TomMath_InitStubs(interp, "8.5-") == NULL) {
	return TCL_ERROR;
    }
#endif
    if (Tcl_OOInitStubs(interp) == NULL) {
	return TCL_ERROR;
    }
    /* TIP #268: Full patchlevel instead of just major.minor */

    if (Tcl_PkgProvideEx(interp, "Tcltest", TCL_PATCH_LEVEL, NULL) == TCL_ERROR) {

    if (Tcl_GetCommandInfo(interp, "::tcl::build-info", &info)) {
#if TCL_MAJOR_VERSION > 8
	if (info.isNativeObjectProc == 2) {
	    Tcl_CreateObjCommand2(interp, "::tcl::test::build-info",
		    info.objProc2, (void *)version, NULL);
    } else
#endif
	Tcl_CreateObjCommand(interp, "::tcl::test::build-info",
		info.objProc, (void *)version, NULL);
    }
    if (Tcl_PkgProvideEx(interp, "tcl::test", TCL_PATCH_LEVEL, NULL) == TCL_ERROR) {
	return TCL_ERROR;
    }

    /*
     * Create additional commands and math functions for testing Tcl.
     */

    Tcl_CreateObjCommand(interp, "gettimes", GetTimesObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "gettimes", GetTimesCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "noop", NoopCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "noop", NoopObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testpurebytesobj", TestpurebytesobjObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testsetbytearraylength", TestsetbytearraylengthObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testbytestring", TestbytestringObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "teststringbytes", TeststringbytesObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testwrongnumargs", TestWrongNumArgsObjCmd,
    Tcl_CreateObjCommand(interp, "testpurebytesobj", TestpurebytesobjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testsetbytearraylength", TestsetbytearraylengthCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testbytestring", TestbytestringCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "teststringbytes", TeststringbytesCmd, NULL, NULL);
    Tcl_CreateObjCommand2(interp, "testwrongnumargs", TestWrongNumArgsCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testfilesystem", TestFilesystemObjCmd,
    Tcl_CreateObjCommand(interp, "testfilesystem", TestFilesystemCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testsimplefilesystem", TestSimpleFilesystemObjCmd,
    Tcl_CreateObjCommand(interp, "testsimplefilesystem", TestSimpleFilesystemCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testgetindexfromobjstruct",
	    TestGetIndexFromObjStructObjCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testasync", TestasyncCmd, NULL, NULL);
	    TestGetIndexFromObjStructCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testasync", TestasyncCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testbumpinterpepoch",
	    TestbumpinterpepochObjCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testchannel", TestChannelCmd,
	    TestbumpinterpepochCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testchannel", TestChannelCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testchannelevent", TestChannelEventCmd,
    Tcl_CreateObjCommand(interp, "testchannelevent", TestChannelEventCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testcmdtoken", TestcmdtokenCmd, NULL,
    Tcl_CreateObjCommand(interp, "testcmdtoken", TestcmdtokenCmd, NULL,
	    NULL);
    Tcl_CreateObjCommand2(interp, "testcmdobj2", Testcmdobj2Cmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testcmdinfo", TestcmdinfoCmd, NULL,
    Tcl_CreateObjCommand(interp, "testcmdinfo", TestcmdinfoCmd, NULL,
	    NULL);
    Tcl_CreateCommand(interp, "testcmdtrace", TestcmdtraceCmd,
    Tcl_CreateObjCommand(interp, "testcmdtrace", TestcmdtraceCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testconcatobj", TestconcatobjCmd,
    Tcl_CreateObjCommand(interp, "testconcatobj", TestconcatobjCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testcreatecommand", TestcreatecommandCmd,
    Tcl_CreateObjCommand(interp, "testcreatecommand", TestcreatecommandCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testdcall", TestdcallCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testdel", TestdelCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testdelassocdata", TestdelassocdataCmd,
    Tcl_CreateObjCommand(interp, "testdcall", TestdcallCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testdel", TestdelCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testdelassocdata", TestdelassocdataCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testdoubledigits", TestdoubledigitsObjCmd,
    Tcl_CreateObjCommand(interp, "testdoubledigits", TestdoubledigitsCmd,
			 NULL, NULL);
    Tcl_DStringInit(&dstring);
    Tcl_CreateCommand(interp, "testdstring", TestdstringCmd, NULL,
    Tcl_CreateObjCommand(interp, "testdstring", TestdstringCmd, NULL,
	    NULL);
    Tcl_CreateObjCommand(interp, "testencoding", TestencodingObjCmd, NULL,
    Tcl_CreateObjCommand(interp, "testencoding", TestencodingCmd, NULL,
	    NULL);
    Tcl_CreateObjCommand(interp, "testevalex", TestevalexObjCmd,
    Tcl_CreateObjCommand(interp, "testevalex", TestevalexCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testevalobjv", TestevalobjvObjCmd,
    Tcl_CreateObjCommand(interp, "testevalobjv", TestevalobjvCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testevent", TesteventObjCmd,
    Tcl_CreateObjCommand(interp, "testevent", TesteventCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testexithandler", TestexithandlerCmd,
    Tcl_CreateObjCommand(interp, "testexithandler", TestexithandlerCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testexprlong", TestexprlongCmd,
    Tcl_CreateObjCommand(interp, "testexprlong", TestexprlongCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testexprlongobj", TestexprlongobjCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testexprdouble", TestexprdoubleCmd,
    Tcl_CreateObjCommand(interp, "testexprdouble", TestexprdoubleCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testexprdoubleobj", TestexprdoubleobjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testexprparser", TestexprparserObjCmd,
    Tcl_CreateObjCommand(interp, "testexprparser", TestexprparserCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testexprstring", TestexprstringCmd,
    Tcl_CreateObjCommand(interp, "testexprstring", TestexprstringCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testfevent", TestfeventCmd, NULL,
    Tcl_CreateObjCommand(interp, "testfevent", TestfeventCmd, NULL,
	    NULL);
    Tcl_CreateObjCommand(interp, "testfilelink", TestfilelinkCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testfile", TestfileCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testhashsystemhash",
	    TestHashSystemHashCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testgetassocdata", TestgetassocdataCmd,
    Tcl_CreateObjCommand(interp, "testgetassocdata", TestgetassocdataCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testgetint", TestgetintCmd,
    Tcl_CreateObjCommand(interp, "testgetint", TestgetintCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testlongsize", TestlongsizeCmd,
    Tcl_CreateObjCommand(interp, "testlongsize", TestlongsizeCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testgetplatform", TestgetplatformCmd,
    Tcl_CreateObjCommand(interp, "testgetplatform", TestgetplatformCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testgetvarfullname",
	    TestgetvarfullnameCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testinterpdelete", TestinterpdeleteCmd,
    Tcl_CreateObjCommand(interp, "testinterpdelete", TestinterpdeleteCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testlink", TestlinkCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testlink", TestlinkCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testlinkarray", TestlinkarrayCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testlistrep", TestlistrepCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testlocale", TestlocaleCmd, NULL,
	    NULL);
    Tcl_CreateCommand(interp, "testpanic", TestpanicCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testpanic", TestpanicCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testparseargs", TestparseargsCmd,NULL,NULL);
    Tcl_CreateObjCommand(interp, "testparser", TestparserObjCmd,
    Tcl_CreateObjCommand(interp, "testparser", TestparserCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testparsevar", TestparsevarObjCmd,
    Tcl_CreateObjCommand(interp, "testparsevar", TestparsevarCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testparsevarname", TestparsevarnameObjCmd,
    Tcl_CreateObjCommand(interp, "testparsevarname", TestparsevarnameCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testpreferstable", TestpreferstableObjCmd,
    Tcl_CreateObjCommand(interp, "testpreferstable", TestpreferstableCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testprint", TestprintObjCmd,
    Tcl_CreateObjCommand(interp, "testprint", TestprintCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testregexp", TestregexpObjCmd,
    Tcl_CreateObjCommand(interp, "testregexp", TestregexpCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testreturn", TestreturnObjCmd,
    Tcl_CreateObjCommand(interp, "testreturn", TestreturnCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testsaveresult", TestsaveresultCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testservicemode", TestServiceModeCmd,
    Tcl_CreateObjCommand(interp, "testservicemode", TestServiceModeCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testsetassocdata", TestsetassocdataCmd,
    Tcl_CreateObjCommand(interp, "testsetassocdata", TestsetassocdataCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testsetnoerr", TestsetCmd,
    Tcl_CreateObjCommand(interp, "testsetnoerr", TestsetCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testseterr", TestsetCmd,
    Tcl_CreateObjCommand(interp, "testseterr", TestsetCmd,
	    INT2PTR(TCL_LEAVE_ERR_MSG), NULL);
    Tcl_CreateCommand(interp, "testset2", Testset2Cmd,
    Tcl_CreateObjCommand(interp, "testset2", Testset2Cmd,
	    INT2PTR(TCL_LEAVE_ERR_MSG), NULL);
    Tcl_CreateCommand(interp, "testseterrorcode", TestseterrorcodeCmd,
    Tcl_CreateObjCommand(interp, "testseterrorcode", TestseterrorcodeCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testsetobjerrorcode",
	    TestsetobjerrorcodeCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testutfnext",
	    TestUtfNextCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testutfprev",
	    TestUtfPrevCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testnumutfchars",
	    TestNumUtfCharsCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testgetunichar",
	    TestGetUniCharCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testfindfirst",
	    TestFindFirstCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testfindlast",
	    TestFindLastCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testgetintforindex",
	    TestGetIntForIndexCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testsetplatform", TestsetplatformCmd,
    Tcl_CreateObjCommand(interp, "testsetplatform", TestsetplatformCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testsize", TestSizeCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testsocket", TestSocketCmd,
    Tcl_CreateObjCommand(interp, "testsocket", TestSocketCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "teststaticpkg", TeststaticpkgCmd,
    Tcl_CreateObjCommand(interp, "teststaticlibrary", TeststaticlibraryCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testtranslatefilename",
    Tcl_CreateObjCommand(interp, "testtranslatefilename",
	    TesttranslatefilenameCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testfstildeexpand",
	    TestfstildeexpandCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testupvar", TestupvarCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testmainthread", TestmainthreadCmd, NULL,
    Tcl_CreateObjCommand(interp, "testupvar", TestupvarCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testmainthread", TestmainthreadCmd, NULL,
	    NULL);
    Tcl_CreateCommand(interp, "testsetmainloop", TestsetmainloopCmd,
    Tcl_CreateObjCommand(interp, "testsetmainloop", TestsetmainloopCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testexitmainloop", TestexitmainloopCmd,
    Tcl_CreateObjCommand(interp, "testexitmainloop", TestexitmainloopCmd,
	    NULL, NULL);
#if defined(HAVE_CPUID) || defined(_WIN32)
#if defined(HAVE_CPUID) && !defined(MAC_OSX_TCL)
    Tcl_CreateObjCommand(interp, "testcpuid", TestcpuidCmd,
	    NULL, NULL);
#endif
    Tcl_CreateObjCommand(interp, "testnreunwind", TestNREUnwind,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testnrelevels", TestNRELevels,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testinterpresolver", TestInterpResolverCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testgetencpath", TestgetencpathObjCmd,
    Tcl_CreateObjCommand(interp, "testapplylambda", TestApplyLambdaCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testsetencpath", TestsetencpathObjCmd,
    Tcl_CreateObjCommand(interp, "testlutil", TestLutilCmd,
	    NULL, NULL);

    if (TclObjTest_Init(interp) != TCL_OK) {
	return TCL_ERROR;
    }
    if (Procbodytest_Init(interp) != TCL_OK) {
	return TCL_ERROR;
    }
#if TCL_THREADS
    if (TclThread_Init(interp) != TCL_OK) {
	return TCL_ERROR;
    }
#endif

    if (Tcl_ABSListTest_Init(interp) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Check for special options used in ../tests/main.test
     */

    objPtr = Tcl_GetVar2Ex(interp, "argv", NULL, TCL_GLOBAL_ONLY);
    if (objPtr != NULL) {
659
660
661
662
663
664
665
666

667
668
669
670
671
672
673
749
750
751
752
753
754
755

756
757
758
759
760
761
762
763







-
+







	    case 2: {
		int mode;
		Tcl_UnregisterChannel(interp,
			Tcl_GetChannel(interp, "stderr", &mode));
		return TCL_ERROR;
	    }
	    case 3:
		if (objc-1) {
		if (objc > 1) {
		    Tcl_SetVar2Ex(interp, "tcl_rcFileName", NULL, objv[1],
			    TCL_GLOBAL_ONLY);
		}
		return TCL_ERROR;
	    }
	}
    }
698
699
700
701
702
703
704


705














706
707
708
709
710
711
712
788
789
790
791
792
793
794
795
796

797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817







+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+







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

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

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
    if (Tcl_InitStubs(interp, "8.7-", 0) == NULL) {
	return TCL_ERROR;
    }
    if (Tcl_GetCommandInfo(interp, "::tcl::build-info", &info)) {
#if TCL_MAJOR_VERSION > 8
	if (info.isNativeObjectProc == 2) {
	    Tcl_CreateObjCommand2(interp, "::tcl::test::build-info",
		    info.objProc2, (void *)version, NULL);
    } else
#endif
	Tcl_CreateObjCommand(interp, "::tcl::test::build-info",
		info.objProc, (void *)version, NULL);
    }
    if (Tcl_PkgProvideEx(interp, "tcl::test", TCL_PATCH_LEVEL, NULL) == TCL_ERROR) {
	return TCL_ERROR;
    }
    return Procbodytest_SafeInit(interp);
}

/*
 *----------------------------------------------------------------------
725
726
727
728
729
730
731
732
733


734
735
736
737
738
739

740
741

742
743
744
745


746
747
748
749
750
751



752
753
754

755
756
757
758
759
760
761
762





763
764
765
766
767
768
769
770

771
772
773

774
775
776

777
778
779

780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797



798
799
800
801


802
803
804
805
806
807
808
809
810
811
812

813
814
815
816
817


818
819
820

821
822
823

824
825
826
827
828
829
830
831

832
833
834
835
836
837
838

839
840
841


842
843
844
845
846
847
848
849
850
851
852
853
854
855
856

857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872




873
874
875
876
877
878


879
880
881
882
883
884
885
886
887
888

889
890
891
892
893
894
895
830
831
832
833
834
835
836


837
838
839
840
841
842
843

844
845

846
847
848


849
850
851
852
853



854
855
856
857
858

859

860
861





862
863
864
865
866
867
868
869
870
871
872
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
898



899
900
901
902
903


904
905
906
907
908
909
910
911
912
913
914
915

916
917
918



919
920
921
922

923
924
925

926
927
928
929
930
931
932
933

934
935
936
937
938
939
940

941
942


943
944
945






946
947
948
949
950
951
952

953
954
955
956
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







-
-
+
+





-
+

-
+


-
-
+
+



-
-
-
+
+
+


-
+
-


-
-
-
-
-
+
+
+
+
+







-
+


-
+


-
+


-
+















-
-
-
+
+
+


-
-
+
+










-
+


-
-
-
+
+


-
+


-
+







-
+






-
+

-
-
+
+

-
-
-
-
-
-







-
+












-
-
-
-
+
+
+
+




-
-
+
+









-
+







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

static int
TestasyncCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,			/* Current interpreter. */
    int argc,				/* Number of arguments. */
    const char **argv)			/* Argument strings. */
    int objc,				/* Number of arguments. */
    Tcl_Obj *const *objv)		/* Arguments. */
{
    TestAsyncHandler *asyncPtr, *prevPtr;
    int id, code;
    static int nextId = 1;

    if (argc < 2) {
    if (objc < 2) {
	wrongNumArgs:
	Tcl_AppendResult(interp, "wrong # args", NULL);
	Tcl_WrongNumArgs(interp, 1, objv, "");
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	if (argc != 3) {
    if (strcmp(Tcl_GetString(objv[1]), "create") == 0) {
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	asyncPtr = (TestAsyncHandler *)Tcl_Alloc(sizeof(TestAsyncHandler));
	asyncPtr->command = (char *)Tcl_Alloc(strlen(argv[2]) + 1);
	strcpy(asyncPtr->command, argv[2]);
        Tcl_MutexLock(&asyncTestMutex);
	asyncPtr->command = (char *)Tcl_Alloc(strlen(Tcl_GetString(objv[2])) + 1);
	strcpy(asyncPtr->command, Tcl_GetString(objv[2]));
	Tcl_MutexLock(&asyncTestMutex);
	asyncPtr->id = nextId;
	nextId++;
	asyncPtr->handler = Tcl_AsyncCreate(AsyncHandlerProc,
	asyncPtr->handler = Tcl_AsyncCreate(AsyncHandlerProc, INT2PTR(asyncPtr->id));
                                            INT2PTR(asyncPtr->id));
	asyncPtr->nextPtr = firstHandler;
	firstHandler = asyncPtr;
        Tcl_MutexUnlock(&asyncTestMutex);
	Tcl_SetObjResult(interp, Tcl_NewIntObj(asyncPtr->id));
    } else if (strcmp(argv[1], "delete") == 0) {
	if (argc == 2) {
            Tcl_MutexLock(&asyncTestMutex);
	Tcl_MutexUnlock(&asyncTestMutex);
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(asyncPtr->id));
    } else if (strcmp(Tcl_GetString(objv[1]), "delete") == 0) {
	if (objc == 2) {
	    Tcl_MutexLock(&asyncTestMutex);
	    while (firstHandler != NULL) {
		asyncPtr = firstHandler;
		firstHandler = asyncPtr->nextPtr;
		Tcl_AsyncDelete(asyncPtr->handler);
		Tcl_Free(asyncPtr->command);
		Tcl_Free(asyncPtr);
	    }
            Tcl_MutexUnlock(&asyncTestMutex);
	    Tcl_MutexUnlock(&asyncTestMutex);
	    return TCL_OK;
	}
	if (argc != 3) {
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	if (Tcl_GetInt(interp, argv[2], &id) != TCL_OK) {
	if (Tcl_GetIntFromObj(interp, objv[2], &id) != TCL_OK) {
	    return TCL_ERROR;
	}
        Tcl_MutexLock(&asyncTestMutex);
	Tcl_MutexLock(&asyncTestMutex);
	for (prevPtr = NULL, asyncPtr = firstHandler; asyncPtr != NULL;
		prevPtr = asyncPtr, asyncPtr = asyncPtr->nextPtr) {
	    if (asyncPtr->id != id) {
		continue;
	    }
	    if (prevPtr == NULL) {
		firstHandler = asyncPtr->nextPtr;
	    } else {
		prevPtr->nextPtr = asyncPtr->nextPtr;
	    }
	    Tcl_AsyncDelete(asyncPtr->handler);
	    Tcl_Free(asyncPtr->command);
	    Tcl_Free(asyncPtr);
	    break;
	}
        Tcl_MutexUnlock(&asyncTestMutex);
    } else if (strcmp(argv[1], "mark") == 0) {
	if (argc != 5) {
	Tcl_MutexUnlock(&asyncTestMutex);
    } else if (strcmp(Tcl_GetString(objv[1]), "mark") == 0) {
	if (objc != 5) {
	    goto wrongNumArgs;
	}
	if ((Tcl_GetInt(interp, argv[2], &id) != TCL_OK)
		|| (Tcl_GetInt(interp, argv[4], &code) != TCL_OK)) {
	if ((Tcl_GetIntFromObj(interp, objv[2], &id) != TCL_OK)
		|| (Tcl_GetIntFromObj(interp, objv[4], &code) != TCL_OK)) {
	    return TCL_ERROR;
	}
	Tcl_MutexLock(&asyncTestMutex);
	for (asyncPtr = firstHandler; asyncPtr != NULL;
		asyncPtr = asyncPtr->nextPtr) {
	    if (asyncPtr->id == id) {
		Tcl_AsyncMark(asyncPtr->handler);
		break;
	    }
	}
	Tcl_SetObjResult(interp, Tcl_NewStringObj(argv[3], -1));
	Tcl_SetObjResult(interp, objv[3]);
	Tcl_MutexUnlock(&asyncTestMutex);
	return code;
#if TCL_THREADS
    } else if (strcmp(argv[1], "marklater") == 0) {
	if (argc != 3) {
    } else if (strcmp(Tcl_GetString(objv[1]), "marklater") == 0) {
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	if (Tcl_GetInt(interp, argv[2], &id) != TCL_OK) {
	if (Tcl_GetIntFromObj(interp, objv[2], &id) != TCL_OK) {
	    return TCL_ERROR;
	}
        Tcl_MutexLock(&asyncTestMutex);
	Tcl_MutexLock(&asyncTestMutex);
	for (asyncPtr = firstHandler; asyncPtr != NULL;
		asyncPtr = asyncPtr->nextPtr) {
	    if (asyncPtr->id == id) {
		Tcl_ThreadId threadID;
		if (Tcl_CreateThread(&threadID, AsyncThreadProc,
			INT2PTR(id), TCL_THREAD_STACK_DEFAULT,
			TCL_THREAD_NOFLAGS) != TCL_OK) {
		    Tcl_AppendResult(interp, "can't create thread", NULL);
		    Tcl_AppendResult(interp, "cannot create thread", (char *)NULL);
		    Tcl_MutexUnlock(&asyncTestMutex);
		    return TCL_ERROR;
		}
		break;
	    }
	}
        Tcl_MutexUnlock(&asyncTestMutex);
	Tcl_MutexUnlock(&asyncTestMutex);
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[1],
		"\": must be create, delete, int, mark, or marklater", NULL);
	Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
		"\": must be create, delete, int, mark, or marklater", (char *)NULL);
	return TCL_ERROR;
#else /* !TCL_THREADS */
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[1],
		"\": must be create, delete, int, or mark", NULL);
	return TCL_ERROR;
#endif
    }
    return TCL_OK;
}

static int
AsyncHandlerProc(
    void *clientData,	/* If of TestAsyncHandler structure.
                                 * in global list. */
				 * in global list. */
    Tcl_Interp *interp,		/* Interpreter in which command was
				 * executed, or NULL. */
    int code)			/* Current return code from command. */
{
    TestAsyncHandler *asyncPtr;
    int id = PTR2INT(clientData);
    const char *listArgv[4];
    char *cmd;
    char string[TCL_INTEGER_SPACE];

    Tcl_MutexLock(&asyncTestMutex);
    for (asyncPtr = firstHandler; asyncPtr != NULL;
            asyncPtr = asyncPtr->nextPtr) {
        if (asyncPtr->id == id) {
            break;
        }
	    asyncPtr = asyncPtr->nextPtr) {
	if (asyncPtr->id == id) {
	    break;
	}
    }
    Tcl_MutexUnlock(&asyncTestMutex);

    if (!asyncPtr) {
        /* Woops - this one was deleted between the AsyncMark and now */
        return TCL_OK;
	/* Woops - this one was deleted between the AsyncMark and now */
	return TCL_OK;
    }

    TclFormatInt(string, code);
    listArgv[0] = asyncPtr->command;
    listArgv[1] = Tcl_GetStringResult(interp);
    listArgv[2] = string;
    listArgv[3] = NULL;
    cmd = Tcl_Merge(3, listArgv);
    if (interp != NULL) {
	code = Tcl_EvalEx(interp, cmd, -1, 0);
	code = Tcl_EvalEx(interp, cmd, TCL_INDEX_NONE, 0);
    } else {
	/*
	 * this should not happen, but by definition of how async handlers are
	 * invoked, it's possible.  Better error checking is needed here.
	 */
    }
    Tcl_Free(cmd);
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931





932
933
934
935
936
937
938
939
940

941
942
943
944
945
946
947
948
949
950
951
952
953
954
955


































956
957
958
959
960
961
962
1005
1006
1007
1008
1009
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







-











-
-
-
-
-
+
+
+
+
+





-


-
+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *
 * Side effects:
 *	Invokes Tcl_AsyncMark on the handler
 *
 *----------------------------------------------------------------------
 */

#if TCL_THREADS
static Tcl_ThreadCreateType
AsyncThreadProc(
    void *clientData)	/* Parameter is the id of a
				 * TestAsyncHandler, defined above. */
{
    TestAsyncHandler *asyncPtr;
    int id = PTR2INT(clientData);

    Tcl_Sleep(1);
    Tcl_MutexLock(&asyncTestMutex);
    for (asyncPtr = firstHandler; asyncPtr != NULL;
         asyncPtr = asyncPtr->nextPtr) {
        if (asyncPtr->id == id) {
            Tcl_AsyncMark(asyncPtr->handler);
            break;
        }
	asyncPtr = asyncPtr->nextPtr) {
	if (asyncPtr->id == id) {
	    Tcl_AsyncMark(asyncPtr->handler);
	    break;
	}
    }
    Tcl_MutexUnlock(&asyncTestMutex);
    Tcl_ExitThread(TCL_OK);
    TCL_THREAD_CREATE_RETURN;
}
#endif

static int
TestbumpinterpepochObjCmd(
TestbumpinterpepochCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *)interp;

    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, "");
	return TCL_ERROR;
    }
    iPtr->compileEpoch++;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Testcmdobj2 --
 *
 *	Mock up to test the Tcl_CreateObjCommand2 functionality
 *
 * Results:
 *	Standard Tcl result.
 *
 * Side effects:
 *	Sets interpreter result to number of arguments, first arg, last arg.
 *
 *----------------------------------------------------------------------
 */

static int
Testcmdobj2Cmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Size objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *resultObj;
    resultObj = Tcl_NewListObj(0, NULL);
    Tcl_ListObjAppendElement(interp, resultObj, Tcl_NewWideIntObj(objc));
    if (objc > 1) {
	Tcl_ListObjAppendElement(interp, resultObj, objv[1]);
	Tcl_ListObjAppendElement(interp, resultObj, objv[objc-1]);
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestcmdinfoCmd --
 *
 *	This procedure implements the "testcmdinfo" command.  It is used to
 *	test Tcl_GetCommandInfo, Tcl_SetCommandInfo, and command creation and
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
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
1100
1101
1102
1103
1104
1105
1106


1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120


1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136






1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155

1156
1157
1158

1159
1160
1161



1162
1163
1164
1165
1166
1167
1168

1169
1170
1171

1172
1173

1174
1175
1176
1177

1178
1179
1180

1181
1182

1183
1184



1185
1186
1187
1188
1189
1190
1191
1192

1193
1194
1195
1196

1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207


1208
1209
1210

1211
1212


1213
1214
1215



1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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







-
-
+
+

+
+
+
+
+
+
+

+
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+

-
+

+
-
-
-
+
+
+




-
+


-
+

-
+



-
+


-
+

-
+

-
-
-
+
+
+
+
+
+
+

-
+
+
+

-
+
+






+
+
+
-
-
+
+

-
+

-
-
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+










-
+










-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+








-
+







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

static int
TestcmdinfoCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])      /* Argument objects. */
{
    static const char *const subcmds[] = {
	   "call", "call2", "create", "delete", "get", "modify", NULL
    };
    enum options {
	CMDINFO_CALL, CMDINFO_CALL2, CMDINFO_CREATE,
	CMDINFO_DELETE, CMDINFO_GET, CMDINFO_MODIFY
    } idx;
    Tcl_CmdInfo info;
    Tcl_Obj **cmdObjv;
    Tcl_Size cmdObjc;

    if (argc != 3) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "command arg");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], subcmds, "option", 0,
	    &idx) != TCL_OK) {
	return TCL_ERROR;
    }
    switch (idx) {
    case CMDINFO_CALL:
    case CMDINFO_CALL2:
	if (Tcl_ListObjGetElements(interp, objv[2], &cmdObjc, &cmdObjv) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (cmdObjc == 0) {
	    Tcl_AppendResult(interp, "No command name given", NULL);
		" option cmdName\"", NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	Tcl_CreateCommand(interp, argv[2], CmdProc1, (void *) "original",
		CmdDelProc1);
	    return TCL_ERROR;
	}
	if (Tcl_GetCommandInfo(interp, Tcl_GetString(cmdObjv[0]), &info) == 0) {
	    return TCL_ERROR;
	}
	if (idx == CMDINFO_CALL) {
	    /*
	     * Note when calling through the old 32-bit API, it is the caller's
	     * responsibility to check that number of arguments is <= INT_MAX.
	     * We do not do that here just so we can test what happens if the
	     * caller mistakenly passes more arguments.
	     */
	    return info.objProc(info.objClientData, interp, cmdObjc, cmdObjv);
	} else {
	    return info.objProc2(info.objClientData2, interp, cmdObjc, cmdObjv);
	}
    case CMDINFO_CREATE:
	Tcl_CreateCommand(interp, Tcl_GetString(objv[2]), CmdProc1,
		(void *)"original", CmdDelProc1);
    } else if (strcmp(argv[1], "delete") == 0) {
	break;
    case CMDINFO_DELETE:
	Tcl_DStringInit(&delString);
	Tcl_DeleteCommand(interp, argv[2]);
	Tcl_DeleteCommand(interp, Tcl_GetString(objv[2]));
	Tcl_DStringResult(interp, &delString);
	break;
    } else if (strcmp(argv[1], "get") == 0) {
	if (Tcl_GetCommandInfo(interp, argv[2], &info) ==0) {
	    Tcl_AppendResult(interp, "??", NULL);
    case CMDINFO_GET:
	if (Tcl_GetCommandInfo(interp, Tcl_GetString(objv[2]), &info) ==0) {
	    Tcl_AppendResult(interp, "??", (char *)NULL);
	    return TCL_OK;
	}
	if (info.proc == CmdProc1) {
	    Tcl_AppendResult(interp, "CmdProc1", " ",
		    (char *) info.clientData, NULL);
		    (char *)info.clientData, (char *)NULL);
	} else if (info.proc == CmdProc2) {
	    Tcl_AppendResult(interp, "CmdProc2", " ",
		    (char *) info.clientData, NULL);
		    (char *)info.clientData, (char *)NULL);
	} else {
	    Tcl_AppendResult(interp, "unknown", NULL);
	    Tcl_AppendResult(interp, "unknown", (char *)NULL);
	}
	if (info.deleteProc == CmdDelProc1) {
	    Tcl_AppendResult(interp, " CmdDelProc1", " ",
		    (char *) info.deleteData, NULL);
		    (char *)info.deleteData, (char *)NULL);
	} else if (info.deleteProc == CmdDelProc2) {
	    Tcl_AppendResult(interp, " CmdDelProc2", " ",
		    (char *) info.deleteData, NULL);
		    (char *)info.deleteData, (char *)NULL);
	} else {
	    Tcl_AppendResult(interp, " unknown", NULL);
	    Tcl_AppendResult(interp, " unknown", (char *)NULL);
	}
	Tcl_AppendResult(interp, " ", info.namespacePtr->fullName, NULL);
	if (info.isNativeObjectProc) {
	    Tcl_AppendResult(interp, " nativeObjectProc", NULL);
	Tcl_AppendResult(interp, " ", info.namespacePtr->fullName, (char *)NULL);
	if (info.isNativeObjectProc == 0) {
	    Tcl_AppendResult(interp, " stringProc", (char *)NULL);
	} else if (info.isNativeObjectProc == 1) {
	    Tcl_AppendResult(interp, " nativeObjectProc", (char *)NULL);
	} else if (info.isNativeObjectProc == 2) {
	    Tcl_AppendResult(interp, " nativeObjectProc2", (char *)NULL);
	} else {
	    Tcl_AppendResult(interp, " stringProc", NULL);
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf("Invalid isNativeObjectProc value %d",
		    info.isNativeObjectProc));
	    return TCL_ERROR;
	}
    } else if (strcmp(argv[1], "modify") == 0) {
	break;
    case CMDINFO_MODIFY:
	info.proc = CmdProc2;
	info.clientData = (void *) "new_command_data";
	info.objProc = NULL;
	info.objClientData = NULL;
	info.deleteProc = CmdDelProc2;
	info.deleteData = (void *) "new_delete_data";
	info.namespacePtr = NULL;
	info.objProc2 = NULL;
	info.objClientData2 = NULL;
	if (Tcl_SetCommandInfo(interp, argv[2], &info) == 0) {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
	if (Tcl_SetCommandInfo(interp, Tcl_GetString(objv[2]), &info) == 0) {
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(0));
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(1));
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(1));
	}
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[1],
	break;
    }

		"\": must be create, delete, get, or modify", NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

static int
CmdProc0(
    void *clientData,	/* String to return. */
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*objc*/,
    TCL_UNUSED(Tcl_Obj *const *) /*objv*/)
{
    TestCommandTokenRef *refPtr = (TestCommandTokenRef *) clientData;
    Tcl_AppendResult(interp, "CmdProc1 ", refPtr->value, (char *)NULL);
    return TCL_OK;
}

static int
CmdProc1(
    void *clientData,	/* String to return. */
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*argc*/,
    TCL_UNUSED(const char **) /*argv*/)
{
    Tcl_AppendResult(interp, "CmdProc1 ", (char *) clientData, NULL);
    Tcl_AppendResult(interp, "CmdProc1 ", (char *)clientData, (char *)NULL);
    return TCL_OK;
}

static int
CmdProc2(
    void *clientData,	/* String to return. */
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*argc*/,
    TCL_UNUSED(const char **) /*argv*/)
{
    Tcl_AppendResult(interp, "CmdProc2 ", (char *) clientData, NULL);
    Tcl_AppendResult(interp, "CmdProc2 ", (char *)clientData, (char *)NULL);
    return TCL_OK;
}

static void
CmdDelProc0(
    void *clientData)	/* String to save. */
{
    TestCommandTokenRef *thisRefPtr, *prevRefPtr = NULL;
    TestCommandTokenRef *refPtr = (TestCommandTokenRef *) clientData;
    int id = refPtr->id;
    for (thisRefPtr = firstCommandTokenRef; refPtr != NULL;
	thisRefPtr = thisRefPtr->nextPtr) {
	if (thisRefPtr->id == id) {
	    if (prevRefPtr != NULL) {
		prevRefPtr->nextPtr = thisRefPtr->nextPtr;
	    } else {
		firstCommandTokenRef = thisRefPtr->nextPtr;
	    }
	    break;
	}
	prevRefPtr = thisRefPtr;
    }
    Tcl_Free(refPtr);
}

static void
CmdDelProc1(
    void *clientData)	/* String to save. */
{
    Tcl_DStringInit(&delString);
    Tcl_DStringAppend(&delString, "CmdDelProc1 ", -1);
    Tcl_DStringAppend(&delString, (char *) clientData, -1);
    Tcl_DStringAppend(&delString, (char *)clientData, -1);
}

static void
CmdDelProc2(
    void *clientData)	/* String to save. */
{
    Tcl_DStringInit(&delString);
    Tcl_DStringAppend(&delString, "CmdDelProc2 ", -1);
    Tcl_DStringAppend(&delString, (char *) clientData, -1);
    Tcl_DStringAppend(&delString, (char *)clientData, -1);
}

/*
 *----------------------------------------------------------------------
 *
 * TestcmdtokenCmd --
 *
1098
1099
1100
1101
1102
1103
1104
1105
1106


1107
1108
1109


1110
1111
1112
1113


1114
1115
1116
1117
1118
1119






1120
1121
1122
1123
1124

1125
1126
1127
1128
1129
1130

1131
1132
1133
1134



1135
1136
1137
1138






























1139
1140
1141
1142






1143
1144
1145
1146
1147
1148
1149
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
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366




1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379







-
-
+
+

-
-
+
+


-
-
+
+
-


-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
+
+
+
-
-
-

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+







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

static int
TestcmdtokenCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    Tcl_Command token;
    int *l;
    TestCommandTokenRef *refPtr;
    int id;
    char buf[30];

    if (argc != 3) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "option arg");
		" option arg\"", NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	token = Tcl_CreateCommand(interp, argv[2], CmdProc1,
		(void *) "original", NULL);
    if (strcmp(Tcl_GetString(objv[1]), "create") == 0) {
	refPtr = (TestCommandTokenRef *)Tcl_Alloc(sizeof(TestCommandTokenRef));
	refPtr->token = Tcl_CreateObjCommand(interp, Tcl_GetString(objv[2]), CmdProc0,
		refPtr, CmdDelProc0);
	refPtr->id = nextCommandTokenRefId;
	refPtr->value = "original";
	sprintf(buf, "%p", (void *)token);
	Tcl_AppendResult(interp, buf, NULL);
    } else if (strcmp(argv[1], "name") == 0) {
	Tcl_Obj *objPtr;

	nextCommandTokenRefId++;
	if (sscanf(argv[2], "%p", &l) != 1) {
	    Tcl_AppendResult(interp, "bad command token \"", argv[2],
		    "\"", NULL);
	    return TCL_ERROR;
	}

	refPtr->nextPtr = firstCommandTokenRef;
	objPtr = Tcl_NewObj();
	Tcl_GetCommandFullName(interp, (Tcl_Command) l, objPtr);

	Tcl_AppendElement(interp,
	firstCommandTokenRef = refPtr;
	snprintf(buf, sizeof(buf), "%d", refPtr->id);
	Tcl_AppendResult(interp, buf, (char *)NULL);
		Tcl_GetCommandName(interp, (Tcl_Command) l));
	Tcl_AppendElement(interp, Tcl_GetString(objPtr));
	Tcl_DecrRefCount(objPtr);
    } else {
	if (sscanf(Tcl_GetString(objv[2]), "%d", &id) != 1) {
	    Tcl_AppendResult(interp, "bad command token \"", Tcl_GetString(objv[2]),
		    "\"", (char *)NULL);
	    return TCL_ERROR;
	}

	for (refPtr = firstCommandTokenRef; refPtr != NULL;
		refPtr = refPtr->nextPtr) {
	    if (refPtr->id == id) {
		break;
	    }
	}

	if (refPtr == NULL) {
	    Tcl_AppendResult(interp, "bad command token \"", Tcl_GetString(objv[2]),
		    "\"", (char *)NULL);
	    return TCL_ERROR;
	}

	if (strcmp(Tcl_GetString(objv[1]), "name") == 0) {
	    Tcl_Obj *objPtr;

	    objPtr = Tcl_NewObj();
	    Tcl_GetCommandFullName(interp, refPtr->token, objPtr);

	    Tcl_AppendElement(interp,
		    Tcl_GetCommandName(interp, refPtr->token));
	    Tcl_AppendElement(interp, Tcl_GetString(objPtr));
	    Tcl_DecrRefCount(objPtr);
	} else {
	Tcl_AppendResult(interp, "bad option \"", argv[1],
		"\": must be create or name", NULL);
	return TCL_ERROR;
    }
	    Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
		    "\": must be create, name, or free", (char *)NULL);
	    return TCL_ERROR;
	}
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestcmdtraceCmd --
1161
1162
1163
1164
1165
1166
1167
1168
1169


1170
1171
1172
1173
1174
1175


1176
1177
1178
1179
1180

1181
1182
1183


1184
1185
1186

1187
1188
1189
1190

1191
1192
1193
1194
1195
1196
1197
1198
1199
1200



1201
1202
1203
1204
1205



1206
1207
1208

1209
1210
1211
1212

1213
1214
1215
1216
1217
1218
1219
1220
1221

1222
1223

1224
1225
1226

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
1391
1392
1393
1394
1395
1396
1397


1398
1399
1400
1401
1402
1403


1404
1405

1406
1407
1408

1409
1410


1411
1412
1413
1414

1415
1416
1417
1418

1419
1420
1421
1422
1423
1424
1425
1426



1427
1428
1429
1430
1431



1432
1433
1434
1435
1436

1437
1438
1439
1440

1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481

1482
1483
1484
1485
1486
1487
1488

1489
1490




1491
1492
1493
1494
1495
1496
1497
1498
1499
1500


1501
1502
1503
1504
1505
1506
1507

1508
1509
1510
1511
1512


1513
1514



1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528

1529
1530
1531
1532
1533
1534
1535
1536







-
-
+
+




-
-
+
+
-



-
+

-
-
+
+


-
+



-
+







-
-
-
+
+
+


-
-
-
+
+
+


-
+



-
+








-
+

-
+


-
+




-
+



-
-
-
+
+
+


-
+





-
-
+
+





-
+






-
+

-
-
-
-
+
+
+







-
-
+
+


+


-
+




-
-
+
+
-
-
-
+
+








+



-
+







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

static int
TestcmdtraceCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Argument strings. */
{
    Tcl_DString buffer;
    int result;

    if (argc != 3) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "option script");
		" option script\"", NULL);
	return TCL_ERROR;
    }

    if (strcmp(argv[1], "tracetest") == 0) {
    if (strcmp(Tcl_GetString(objv[1]), "tracetest") == 0) {
	Tcl_DStringInit(&buffer);
	cmdTrace = Tcl_CreateTrace(interp, 50000, CmdTraceProc, &buffer);
	result = Tcl_EvalEx(interp, argv[2], -1, 0);
	cmdTrace = Tcl_CreateObjTrace(interp, 50000, 0, CmdTraceProc, &buffer, NULL);
	result = Tcl_EvalEx(interp, Tcl_GetString(objv[2]), TCL_INDEX_NONE, 0);
	if (result == TCL_OK) {
	    Tcl_ResetResult(interp);
	    Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), NULL);
	    Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), (char *)NULL);
	}
	Tcl_DeleteTrace(interp, cmdTrace);
	Tcl_DStringFree(&buffer);
    } else if (strcmp(argv[1], "deletetest") == 0) {
    } else if (strcmp(Tcl_GetString(objv[1]), "deletetest") == 0) {
	/*
	 * Create a command trace then eval a script to check whether it is
	 * called. Note that this trace procedure removes itself as a further
	 * check of the robustness of the trace proc calling code in
	 * TclNRExecuteByteCode.
	 */

	cmdTrace = Tcl_CreateTrace(interp, 50000, CmdTraceDeleteProc, NULL);
	Tcl_EvalEx(interp, argv[2], -1, 0);
    } else if (strcmp(argv[1], "leveltest") == 0) {
	cmdTrace = Tcl_CreateObjTrace(interp, 50000, 0, CmdTraceDeleteProc, NULL, NULL);
	Tcl_EvalEx(interp, Tcl_GetString(objv[2]), TCL_INDEX_NONE, 0);
    } else if (strcmp(Tcl_GetString(objv[1]), "leveltest") == 0) {
	Interp *iPtr = (Interp *) interp;
	Tcl_DStringInit(&buffer);
	cmdTrace = Tcl_CreateTrace(interp, iPtr->numLevels + 4, CmdTraceProc,
		&buffer);
	result = Tcl_EvalEx(interp, argv[2], -1, 0);
	cmdTrace = Tcl_CreateObjTrace(interp, iPtr->numLevels + 4, 0, CmdTraceProc,
		&buffer, NULL);
	result = Tcl_EvalEx(interp, Tcl_GetString(objv[2]), TCL_INDEX_NONE, 0);
	if (result == TCL_OK) {
	    Tcl_ResetResult(interp);
	    Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), NULL);
	    Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), (char *)NULL);
	}
	Tcl_DeleteTrace(interp, cmdTrace);
	Tcl_DStringFree(&buffer);
    } else if (strcmp(argv[1], "resulttest") == 0) {
    } else if (strcmp(Tcl_GetString(objv[1]), "resulttest") == 0) {
	/* Create an object-based trace, then eval a script. This is used
	 * to test return codes other than TCL_OK from the trace engine.
	 */

	static int deleteCalled;

	deleteCalled = 0;
	cmdTrace = Tcl_CreateObjTrace(interp, 50000,
		TCL_ALLOW_INLINE_COMPILATION, ObjTraceProc,
		TCL_ALLOW_INLINE_COMPILATION, TraceProc,
		&deleteCalled, ObjTraceDeleteProc);
	result = Tcl_EvalEx(interp, argv[2], -1, 0);
	result = Tcl_EvalEx(interp, Tcl_GetString(objv[2]), TCL_INDEX_NONE, 0);
	Tcl_DeleteTrace(interp, cmdTrace);
	if (!deleteCalled) {
	    Tcl_AppendResult(interp, "Delete wasn't called", NULL);
	    Tcl_AppendResult(interp, "Delete wasn't called", (char *)NULL);
	    return TCL_ERROR;
	} else {
	    return result;
	}
    } else if (strcmp(argv[1], "doubletest") == 0) {
    } else if (strcmp(Tcl_GetString(objv[1]), "doubletest") == 0) {
	Tcl_Trace t1, t2;

	Tcl_DStringInit(&buffer);
	t1 = Tcl_CreateTrace(interp, 1, CmdTraceProc, &buffer);
	t2 = Tcl_CreateTrace(interp, 50000, CmdTraceProc, &buffer);
	result = Tcl_EvalEx(interp, argv[2], -1, 0);
	t1 = Tcl_CreateObjTrace(interp, 1, 0, CmdTraceProc, &buffer, NULL);
	t2 = Tcl_CreateObjTrace(interp, 50000, 0, CmdTraceProc, &buffer, NULL);
	result = Tcl_EvalEx(interp, Tcl_GetString(objv[2]), TCL_INDEX_NONE, 0);
	if (result == TCL_OK) {
	    Tcl_ResetResult(interp);
	    Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), NULL);
	    Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), (char *)NULL);
	}
	Tcl_DeleteTrace(interp, t2);
	Tcl_DeleteTrace(interp, t1);
	Tcl_DStringFree(&buffer);
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[1],
		"\": must be tracetest, deletetest, doubletest or resulttest", NULL);
	Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
		"\": must be tracetest, deletetest, doubletest or resulttest", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

static void
static int
CmdTraceProc(
    void *clientData,	/* Pointer to buffer in which the
				 * command and arguments are appended.
				 * Accumulates test result. */
    TCL_UNUSED(Tcl_Interp *),
    TCL_UNUSED(int) /*level*/,
    char *command,		/* The command being traced (after
    const char *command,		/* The command being traced (after
				 * substitutions). */
    TCL_UNUSED(Tcl_CmdProc *) /*cmdProc*/,
    TCL_UNUSED(void *),
    int argc,			/* Number of arguments. */
    const char *argv[])		/* Argument strings. */
    TCL_UNUSED(Tcl_Command) /*cmdProc*/,
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    Tcl_DString *bufPtr = (Tcl_DString *) clientData;
    int i;

    Tcl_DStringAppendElement(bufPtr, command);

    Tcl_DStringStartSublist(bufPtr);
    for (i = 0;  i < argc;  i++) {
	Tcl_DStringAppendElement(bufPtr, argv[i]);
    for (i = 0;  i < objc;  i++) {
	Tcl_DStringAppendElement(bufPtr, Tcl_GetString(objv[i]));
    }
    Tcl_DStringEndSublist(bufPtr);
    return TCL_OK;
}

static void
static int
CmdTraceDeleteProc(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*level*/,
    TCL_UNUSED(char *) /*command*/,
    TCL_UNUSED(Tcl_CmdProc *),
    TCL_UNUSED(const char *) /*command*/,
    TCL_UNUSED(Tcl_Command),
    TCL_UNUSED(void *),
    TCL_UNUSED(int) /*argc*/,
    TCL_UNUSED(const char **) /*argv*/)
    TCL_UNUSED(int) /*objc*/,
    TCL_UNUSED(Tcl_Obj *const *) /*objv*/)
{
    /*
     * Remove ourselves to test whether calling Tcl_DeleteTrace within a trace
     * callback causes the for loop in TclNRExecuteByteCode that calls traces to
     * reference freed memory.
     */

    Tcl_DeleteTrace(interp, cmdTrace);
    return TCL_OK;
}

static int
ObjTraceProc(
TraceProc(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Tcl interpreter */
    TCL_UNUSED(int) /*level*/,
    const char *command,
    TCL_UNUSED(Tcl_Command),
    TCL_UNUSED(int) /*objc*/,
    Tcl_Obj *const objv[])	/* Argument objects. */
1353
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391


1392
1393
1394
1395
1396
1397
1398
1399
1400

1401
1402
1403
1404

1405
1406
1407
1408
1409
1410
1411
1412
1413


1414
1415
1416
1417
1418
1419
1420
1421

1422
1423
1424
1425

1426
1427
1428
1429
1430
1431
1432
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







-
-
+
+

-
-
+
+
-


-
-
+
+

-
+

-
-
+
+

-
+


-
-
+
+









-
-
+
+








-
+



-
+







-
-
+
+







-
+



-
+







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

static int
TestcreatecommandCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option");
		" option\"", NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	Tcl_CreateCommand(interp, "test_ns_basic::createdcommand",
    if (strcmp(Tcl_GetString(objv[1]), "create") == 0) {
	Tcl_CreateObjCommand(interp, "test_ns_basic::createdcommand",
		CreatedCommandProc, NULL, NULL);
    } else if (strcmp(argv[1], "delete") == 0) {
    } else if (strcmp(Tcl_GetString(objv[1]), "delete") == 0) {
	Tcl_DeleteCommand(interp, "test_ns_basic::createdcommand");
    } else if (strcmp(argv[1], "create2") == 0) {
	Tcl_CreateCommand(interp, "value:at:",
    } else if (strcmp(Tcl_GetString(objv[1]), "create2") == 0) {
	Tcl_CreateObjCommand(interp, "value:at:",
		CreatedCommandProc2, NULL, NULL);
    } else if (strcmp(argv[1], "delete2") == 0) {
    } else if (strcmp(Tcl_GetString(objv[1]), "delete2") == 0) {
	Tcl_DeleteCommand(interp, "value:at:");
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[1],
		"\": must be create, delete, create2, or delete2", NULL);
	Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
		"\": must be create, delete, create2, or delete2", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

static int
CreatedCommandProc(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*argc*/,
    TCL_UNUSED(const char **) /*argv*/)
    TCL_UNUSED(int) /*objc*/,
    TCL_UNUSED(Tcl_Obj *const *) /*objv*/)
{
    Tcl_CmdInfo info;
    int found;

    found = Tcl_GetCommandInfo(interp, "test_ns_basic::createdcommand",
	    &info);
    if (!found) {
	Tcl_AppendResult(interp, "CreatedCommandProc could not get command info for test_ns_basic::createdcommand",
		NULL);
		(char *)NULL);
	return TCL_ERROR;
    }
    Tcl_AppendResult(interp, "CreatedCommandProc in ",
	    info.namespacePtr->fullName, NULL);
	    info.namespacePtr->fullName, (char *)NULL);
    return TCL_OK;
}

static int
CreatedCommandProc2(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*argc*/,
    TCL_UNUSED(const char **) /*argv*/)
    TCL_UNUSED(int) /*objc*/,
    TCL_UNUSED(Tcl_Obj *const *) /*objv*/)
{
    Tcl_CmdInfo info;
    int found;

    found = Tcl_GetCommandInfo(interp, "value:at:", &info);
    if (!found) {
	Tcl_AppendResult(interp, "CreatedCommandProc2 could not get command info for test_ns_basic::createdcommand",
		NULL);
		(char *)NULL);
	return TCL_ERROR;
    }
    Tcl_AppendResult(interp, "CreatedCommandProc2 in ",
	    info.namespacePtr->fullName, NULL);
	    info.namespacePtr->fullName, (char *)NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestdcallCmd --
1443
1444
1445
1446
1447
1448
1449
1450
1451


1452
1453


1454
1455
1456
1457
1458


1459
1460
1461
1462
1463
1464
1465
1671
1672
1673
1674
1675
1676
1677


1678
1679
1680

1681
1682
1683
1684
1685


1686
1687
1688
1689
1690
1691
1692
1693
1694







-
-
+
+

-
+
+



-
-
+
+







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

static int
TestdcallCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    int i, id;
    int i;
    int id;

    delInterp = Tcl_CreateInterp();
    Tcl_DStringInit(&delString);
    for (i = 1; i < argc; i++) {
	if (Tcl_GetInt(interp, argv[i], &id) != TCL_OK) {
    for (i = 1; i < objc; i++) {
	if (Tcl_GetIntFromObj(interp, objv[i], &id) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (id < 0) {
	    Tcl_DontCallWhenDeleted(delInterp, DelCallbackProc,
		    INT2PTR(-id));
	} else {
	    Tcl_CallWhenDeleted(delInterp, DelCallbackProc,
1507
1508
1509
1510
1511
1512
1513
1514
1515


1516
1517
1518
1519
1520
1521


1522
1523
1524
1525

1526
1527
1528
1529
1530
1531
1532
1533


1534
1535

1536
1537
1538
1539
1540
1541
1542
1543
1544
1545


1546
1547
1548
1549

1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561

1562
1563
1564
1565
1566
1567
1568
1736
1737
1738
1739
1740
1741
1742


1743
1744
1745
1746
1747
1748


1749
1750
1751
1752
1753

1754
1755
1756
1757
1758
1759
1760


1761
1762
1763

1764
1765
1766
1767
1768
1769
1770
1771
1772


1773
1774
1775
1776
1777

1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789

1790
1791
1792
1793
1794
1795
1796
1797







-
-
+
+




-
-
+
+



-
+






-
-
+
+

-
+








-
-
+
+



-
+











-
+







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

static int
TestdelCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    DelCmd *dPtr;
    Tcl_Interp *child;

    if (argc != 4) {
	Tcl_AppendResult(interp, "wrong # args", NULL);
    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "interp name delcmdname");
	return TCL_ERROR;
    }

    child = Tcl_GetChild(interp, argv[1]);
    child = Tcl_GetChild(interp, Tcl_GetString(objv[1]));
    if (child == NULL) {
	return TCL_ERROR;
    }

    dPtr = (DelCmd *)Tcl_Alloc(sizeof(DelCmd));
    dPtr->interp = interp;
    dPtr->deleteCmd = (char *)Tcl_Alloc(strlen(argv[3]) + 1);
    strcpy(dPtr->deleteCmd, argv[3]);
    dPtr->deleteCmd = (char *)Tcl_Alloc(strlen(Tcl_GetString(objv[3])) + 1);
    strcpy(dPtr->deleteCmd, Tcl_GetString(objv[3]));

    Tcl_CreateCommand(child, argv[2], DelCmdProc, dPtr,
    Tcl_CreateObjCommand(child, Tcl_GetString(objv[2]), DelCmdProc, dPtr,
	    DelDeleteProc);
    return TCL_OK;
}

static int
DelCmdProc(
    void *clientData,	/* String result to return. */
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*argc*/,
    TCL_UNUSED(const char **) /*argv*/)
    TCL_UNUSED(int) /*objv*/,
    TCL_UNUSED(Tcl_Obj *const *) /*objv*/)
{
    DelCmd *dPtr = (DelCmd *) clientData;

    Tcl_AppendResult(interp, dPtr->deleteCmd, NULL);
    Tcl_AppendResult(interp, dPtr->deleteCmd, (char *)NULL);
    Tcl_Free(dPtr->deleteCmd);
    Tcl_Free(dPtr);
    return TCL_OK;
}

static void
DelDeleteProc(
    void *clientData)	/* String command to evaluate. */
{
    DelCmd *dPtr = (DelCmd *)clientData;

    Tcl_EvalEx(dPtr->interp, dPtr->deleteCmd, -1, 0);
    Tcl_EvalEx(dPtr->interp, dPtr->deleteCmd, TCL_INDEX_NONE, 0);
    Tcl_ResetResult(dPtr->interp);
    Tcl_Free(dPtr->deleteCmd);
    Tcl_Free(dPtr);
}

/*
 *----------------------------------------------------------------------
1582
1583
1584
1585
1586
1587
1588
1589
1590


1591
1592

1593
1594

1595
1596
1597

1598
1599
1600
1601
1602
1603
1604
1811
1812
1813
1814
1815
1816
1817


1818
1819
1820

1821


1822
1823
1824

1825
1826
1827
1828
1829
1830
1831
1832







-
-
+
+

-
+
-
-
+


-
+







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

static int
TestdelassocdataCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    if (argc != 2) {
    if (objc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" data_key\"", NULL);
	Tcl_WrongNumArgs(interp, 1, objv, "data_key");
	return TCL_ERROR;
    }
    Tcl_DeleteAssocData(interp, argv[1]);
    Tcl_DeleteAssocData(interp, Tcl_GetString(objv[1]));
    return TCL_OK;
}

/*
 *-----------------------------------------------------------------------------
 *
 * TestdoubledigitsCmd --
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
1844
1845
1846
1847
1848
1849
1850

1851
1852
1853
1854
1855
1856

1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875


1876
1877
1878
1879
1880
1881
1882
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







-
+





-
+


















-
-
+
+










-
-
+
+





-
-
-
+
+
+















-
+







 *	type - One of 'shortest', 'e', 'f'
 *	shorten - Indicates that the 'shorten' flag should be passed in.
 *
 *-----------------------------------------------------------------------------
 */

static int
TestdoubledigitsObjCmd(
TestdoubledigitsCmd(
    TCL_UNUSED(void *),
    Tcl_Interp* interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj* const objv[])	/* Parameter vector */
{
    static const char* options[] = {
    static const char *options[] = {
	"shortest",
	"e",
	"f",
	NULL
    };
    static const int types[] = {
	TCL_DD_SHORTEST,
	TCL_DD_E_FORMAT,
	TCL_DD_F_FORMAT
    };

    const Tcl_ObjType* doubleType;
    double d;
    int status;
    int ndigits;
    int type;
    int decpt;
    int signum;
    char* str;
    char* endPtr;
    char *str;
    char *endPtr;
    Tcl_Obj* strObj;
    Tcl_Obj* retval;

    if (objc < 4 || objc > 5) {
	Tcl_WrongNumArgs(interp, 1, objv, "fpval ndigits type ?shorten?");
	return TCL_ERROR;
    }
    status = Tcl_GetDoubleFromObj(interp, objv[1], &d);
    if (status != TCL_OK) {
	doubleType = Tcl_GetObjType("double");
	if (Tcl_FetchIntRep(objv[1], doubleType)
	    && TclIsNaN(objv[1]->internalRep.doubleValue)) {
	if (Tcl_FetchInternalRep(objv[1], doubleType)
	    && isnan(objv[1]->internalRep.doubleValue)) {
	    status = TCL_OK;
	    memcpy(&d, &(objv[1]->internalRep.doubleValue), sizeof(double));
	}
    }
    if (status != TCL_OK
	|| Tcl_GetIntFromObj(interp, objv[2], &ndigits) != TCL_OK
	|| Tcl_GetIndexFromObj(interp, objv[3], options, "conversion type",
			       TCL_EXACT, &type) != TCL_OK) {
	    || Tcl_GetIntFromObj(interp, objv[2], &ndigits) != TCL_OK
	    || Tcl_GetIndexFromObj(interp, objv[3], options, "conversion type",
		    TCL_EXACT, &type) != TCL_OK) {
	fprintf(stderr, "bad value? %g\n", d);
	return TCL_ERROR;
    }
    type = types[type];
    if (objc > 4) {
	if (strcmp(Tcl_GetString(objv[4]), "shorten")) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj("bad flag", -1));
	    return TCL_ERROR;
	}
	type |= TCL_DD_SHORTEST;
    }
    str = TclDoubleDigits(d, ndigits, type, &decpt, &signum, &endPtr);
    strObj = Tcl_NewStringObj(str, endPtr-str);
    Tcl_Free(str);
    retval = Tcl_NewListObj(1, &strObj);
    Tcl_ListObjAppendElement(NULL, retval, Tcl_NewIntObj(decpt));
    Tcl_ListObjAppendElement(NULL, retval, Tcl_NewWideIntObj(decpt));
    strObj = Tcl_NewStringObj(signum ? "-" : "+", 1);
    Tcl_ListObjAppendElement(NULL, retval, strObj);
    Tcl_SetObjResult(interp, retval);
    return TCL_OK;
}

/*
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
1749
1750
1751
1752


1753
1754
1755
1756
1757
1758
1759





1760
1761
1762
1763

1764
1765
1766
1767
1768

1769
1770

1771
1772
1773
1774

1775
1776

1777
1778
1779
1780
1781



1782
1783
1784
1785
1786







1787
1788
1789

1790
1791
1792
1793
1794


1795
1796
1797
1798
1799
1800
1801



1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812

1813



1814
1815
1816
























































































































































































































1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836

1837
1838
1839
1840
1841
1842
1843

1844
1845
1846
1847

1848
1849
1850
1851







1852
1853
1854
1855
1856
1857
1858

1859
1860
1861
1862

1863
1864
1865

1866
1867
1868
1869
1870
1871
1872
1934
1935
1936
1937
1938
1939
1940


1941
1942
1943
1944
1945

1946
1947

1948
1949
1950


1951
1952
1953
1954

1955
1956
1957



1958
1959
1960
1961
1962



1963
1964
1965
1966
1967
1968


1969
1970
1971
1972
1973


1974
1975
1976
1977
1978


1979
1980
1981
1982





1983
1984
1985
1986
1987
1988
1989
1990

1991
1992
1993
1994
1995

1996
1997

1998
1999
2000
2001

2002
2003

2004
2005
2006



2007
2008
2009
2010
2011
2012


2013
2014
2015
2016
2017
2018
2019
2020
2021

2022
2023
2024
2025


2026
2027
2028
2029
2030
2031



2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288

2289
2290
2291
2292
2293
2294
2295

2296
2297
2298
2299

2300
2301
2302


2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315

2316
2317
2318
2319
2320
2321
2322
2323

2324
2325
2326
2327
2328
2329
2330
2331







-
-
+
+



-
+

-
+


-
-
+
+


-
+


-
-
-
+
+
+


-
-
-
+
+
+



-
-
+
+



-
-
+
+



-
-
+
+


-
-
-
-
-
+
+
+
+
+



-
+




-
+

-
+



-
+

-
+


-
-
-
+
+
+



-
-
+
+
+
+
+
+
+


-
+



-
-
+
+




-
-
-
+
+
+











+

+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



















-
+






-
+



-
+


-
-
+
+
+
+
+
+
+






-
+




+


-
+







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

static int
TestdstringCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    int count;

    if (argc < 2) {
    if (objc < 2) {
	wrongNumArgs:
	Tcl_AppendResult(interp, "wrong # args", NULL);
	Tcl_WrongNumArgs(interp, 1, objv, "option ?args?");
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "append") == 0) {
	if (argc != 4) {
    if (strcmp(Tcl_GetString(objv[1]), "append") == 0) {
	if (objc != 4) {
	    goto wrongNumArgs;
	}
	if (Tcl_GetInt(interp, argv[3], &count) != TCL_OK) {
	if (Tcl_GetIntFromObj(interp, objv[3], &count) != TCL_OK) {
	    return TCL_ERROR;
	}
	Tcl_DStringAppend(&dstring, argv[2], count);
    } else if (strcmp(argv[1], "element") == 0) {
	if (argc != 3) {
	Tcl_DStringAppend(&dstring, Tcl_GetString(objv[2]), count);
    } else if (strcmp(Tcl_GetString(objv[1]), "element") == 0) {
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	Tcl_DStringAppendElement(&dstring, argv[2]);
    } else if (strcmp(argv[1], "end") == 0) {
	if (argc != 2) {
	Tcl_DStringAppendElement(&dstring, Tcl_GetString(objv[2]));
    } else if (strcmp(Tcl_GetString(objv[1]), "end") == 0) {
	if (objc != 2) {
	    goto wrongNumArgs;
	}
	Tcl_DStringEndSublist(&dstring);
    } else if (strcmp(argv[1], "free") == 0) {
	if (argc != 2) {
    } else if (strcmp(Tcl_GetString(objv[1]), "free") == 0) {
	if (objc != 2) {
	    goto wrongNumArgs;
	}
	Tcl_DStringFree(&dstring);
    } else if (strcmp(argv[1], "get") == 0) {
	if (argc != 2) {
    } else if (strcmp(Tcl_GetString(objv[1]), "get") == 0) {
	if (objc != 2) {
	    goto wrongNumArgs;
	}
	Tcl_SetResult(interp, Tcl_DStringValue(&dstring), TCL_VOLATILE);
    } else if (strcmp(argv[1], "gresult") == 0) {
	if (argc != 3) {
    } else if (strcmp(Tcl_GetString(objv[1]), "gresult") == 0) {
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	if (strcmp(argv[2], "staticsmall") == 0) {
	    Tcl_AppendResult(interp, "short", NULL);
	} else if (strcmp(argv[2], "staticlarge") == 0) {
	    Tcl_AppendResult(interp, "first0 first1 first2 first3 first4 first5 first6 first7 first8 first9\nsecond0 second1 second2 second3 second4 second5 second6 second7 second8 second9\nthird0 third1 third2 third3 third4 third5 third6 third7 third8 third9\nfourth0 fourth1 fourth2 fourth3 fourth4 fourth5 fourth6 fourth7 fourth8 fourth9\nfifth0 fifth1 fifth2 fifth3 fifth4 fifth5 fifth6 fifth7 fifth8 fifth9\nsixth0 sixth1 sixth2 sixth3 sixth4 sixth5 sixth6 sixth7 sixth8 sixth9\nseventh0 seventh1 seventh2 seventh3 seventh4 seventh5 seventh6 seventh7 seventh8 seventh9\n", NULL);
	} else if (strcmp(argv[2], "free") == 0) {
	if (strcmp(Tcl_GetString(objv[2]), "staticsmall") == 0) {
	    Tcl_AppendResult(interp, "short", (char *)NULL);
	} else if (strcmp(Tcl_GetString(objv[2]), "staticlarge") == 0) {
	    Tcl_AppendResult(interp, "first0 first1 first2 first3 first4 first5 first6 first7 first8 first9\nsecond0 second1 second2 second3 second4 second5 second6 second7 second8 second9\nthird0 third1 third2 third3 third4 third5 third6 third7 third8 third9\nfourth0 fourth1 fourth2 fourth3 fourth4 fourth5 fourth6 fourth7 fourth8 fourth9\nfifth0 fifth1 fifth2 fifth3 fifth4 fifth5 fifth6 fifth7 fifth8 fifth9\nsixth0 sixth1 sixth2 sixth3 sixth4 sixth5 sixth6 sixth7 sixth8 sixth9\nseventh0 seventh1 seventh2 seventh3 seventh4 seventh5 seventh6 seventh7 seventh8 seventh9\n", (char *)NULL);
	} else if (strcmp(Tcl_GetString(objv[2]), "free") == 0) {
	    char *s = (char *)Tcl_Alloc(100);
	    strcpy(s, "This is a malloc-ed string");
	    Tcl_SetResult(interp, s, TCL_DYNAMIC);
	} else if (strcmp(argv[2], "special") == 0) {
	} else if (strcmp(Tcl_GetString(objv[2]), "special") == 0) {
	    char *s = (char *)Tcl_Alloc(100) + 16;
	    strcpy(s, "This is a specially-allocated string");
	    Tcl_SetResult(interp, s, SpecialFree);
	} else {
	    Tcl_AppendResult(interp, "bad gresult option \"", argv[2],
	    Tcl_AppendResult(interp, "bad gresult option \"", Tcl_GetString(objv[2]),
		    "\": must be staticsmall, staticlarge, free, or special",
		    NULL);
		    (char *)NULL);
	    return TCL_ERROR;
	}
	Tcl_DStringGetResult(interp, &dstring);
    } else if (strcmp(argv[1], "length") == 0) {
    } else if (strcmp(Tcl_GetString(objv[1]), "length") == 0) {

	if (argc != 2) {
	if (objc != 2) {
	    goto wrongNumArgs;
	}
	Tcl_SetObjResult(interp, Tcl_NewIntObj(Tcl_DStringLength(&dstring)));
    } else if (strcmp(argv[1], "result") == 0) {
	if (argc != 2) {
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tcl_DStringLength(&dstring)));
    } else if (strcmp(Tcl_GetString(objv[1]), "result") == 0) {
	if (objc != 2) {
	    goto wrongNumArgs;
	}
	Tcl_DStringResult(interp, &dstring);
    } else if (strcmp(argv[1], "trunc") == 0) {
	if (argc != 3) {
    } else if (strcmp(Tcl_GetString(objv[1]), "toobj") == 0) {
	if (objc != 2) {
	    goto wrongNumArgs;
	}
	Tcl_SetObjResult(interp, Tcl_DStringToObj(&dstring));
    } else if (strcmp(Tcl_GetString(objv[1]), "trunc") == 0) {
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	if (Tcl_GetInt(interp, argv[2], &count) != TCL_OK) {
	if (Tcl_GetIntFromObj(interp, objv[2], &count) != TCL_OK) {
	    return TCL_ERROR;
	}
	Tcl_DStringSetLength(&dstring, count);
    } else if (strcmp(argv[1], "start") == 0) {
	if (argc != 2) {
    } else if (strcmp(Tcl_GetString(objv[1]), "start") == 0) {
	if (objc != 2) {
	    goto wrongNumArgs;
	}
	Tcl_DStringStartSublist(&dstring);
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[1],
		"\": must be append, element, end, free, get, length, "
		"result, trunc, or start", NULL);
	Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
		"\": must be append, element, end, free, get, gresult, length, "
		"result, start, toobj, or trunc", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 * The procedure below is used as a special freeProc to test how well
 * Tcl_DStringGetResult handles freeProc's other than free.
 */

static void SpecialFree(
#if TCL_MAJOR_VERSION > 8
    void *blockPtr			/* Block to free. */
#else
    char *blockPtr			/* Block to free. */
#endif
) {
    Tcl_Free(((char *)blockPtr) - 16);
}

/*
 *------------------------------------------------------------------------
 *
 * UtfTransformFn --
 *
 *    Implements a direct call into Tcl_UtfToExternal and Tcl_ExternalToUtf
 *    as otherwise there is no script level command that directly exercises
 *    these functions (i/o command cannot test all combinations)
 *    The arguments at the script level are roughly those of the above
 *    functions:
 *	encodingname srcbytes flags state dstlen ?srcreadvar? ?dstwrotevar? ?dstcharsvar?
 *
 * Results:
 *    TCL_OK or TCL_ERROR. This indicates any errors running the test, NOT the
 *    result of Tcl_UtfToExternal or Tcl_ExternalToUtf.
 *
 * Side effects:
 *
 *    The result in the interpreter is a list of the return code from the
 *    Tcl_UtfToExternal/Tcl_ExternalToUtf functions, the encoding state, and
 *    an encoded binary string of length dstLen. Note the string is the
 *    entire output buffer, not just the part containing the decoded
 *    portion. This allows for additional checks at test script level.
 *
 *    If any of the srcreadvar, dstwrotevar and dstcharsvar are specified and
 *    not empty, they are treated as names of variables where the *srcRead,
 *    *dstWrote and *dstChars output from the functions are stored.
 *
 *    The function also checks internally whether nuls are correctly
 *    appended as requested but the TCL_ENCODING_NO_TERMINATE flag
 *    and that no buffer overflows occur.
 *------------------------------------------------------------------------
 */
typedef int
UtfTransformFn(Tcl_Interp *interp, Tcl_Encoding encoding, const char *src,
	Tcl_Size srcLen, int flags, Tcl_EncodingState *statePtr, char *dst,
	Tcl_Size dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr);

static int UtfExtWrapper(
    Tcl_Interp *interp, UtfTransformFn *transformer, int objc, Tcl_Obj *const objv[])
{
    Tcl_Encoding encoding;
    Tcl_EncodingState encState, *encStatePtr;
    Tcl_Size srcLen, bufLen;
    const unsigned char *bytes;
    unsigned char *bufPtr;
    int srcRead, dstLen, dstWrote, dstChars;
    Tcl_Obj *srcReadVar, *dstWroteVar, *dstCharsVar;
    int result;
    int flags;
    Tcl_Obj **flagObjs;
    Tcl_Size nflags;
    static const struct {
	const char *flagKey;
	int flag;
    } flagMap[] = {
	{"start", TCL_ENCODING_START},
	{"end", TCL_ENCODING_END},
	{"noterminate", TCL_ENCODING_NO_TERMINATE},
	{"charlimit", TCL_ENCODING_CHAR_LIMIT},
	{"tcl8", TCL_ENCODING_PROFILE_TCL8},
	{"strict", TCL_ENCODING_PROFILE_STRICT},
	{"replace", TCL_ENCODING_PROFILE_REPLACE},
	{NULL, 0}
    };
    Tcl_Size i;
    Tcl_WideInt wide;

    if (objc < 7 || objc > 10) {
	Tcl_WrongNumArgs(interp, 2, objv,
		"encoding srcbytes flags state dstlen ?srcreadvar? ?dstwrotevar? ?dstcharsvar?");
	return TCL_ERROR;
    }
    if (Tcl_GetEncodingFromObj(interp, objv[2], &encoding) != TCL_OK) {
	return TCL_ERROR;
    }

    /* Flags may be specified as list of integers and keywords */
    flags = 0;
    if (Tcl_ListObjGetElements(interp, objv[4], &nflags, &flagObjs) != TCL_OK) {
	return TCL_ERROR;
    }

    for (i = 0; i < nflags; ++i) {
	int flag;
	if (Tcl_GetIntFromObj(NULL, flagObjs[i], &flag) == TCL_OK) {
	    flags |= flag;
	} else {
	    int idx;
	    if (Tcl_GetIndexFromObjStruct(interp, flagObjs[i], flagMap, sizeof(flagMap[0]),
		    "flag", 0, &idx) != TCL_OK) {
		return TCL_ERROR;
	    }
	    flags |= flagMap[idx].flag;
	}
    }

    /* Assumes state is integer if not "" */
    if (Tcl_GetWideIntFromObj(interp, objv[5], &wide) == TCL_OK) {
	encState = (Tcl_EncodingState)(size_t)wide;
	encStatePtr = &encState;
    } else if (Tcl_GetCharLength(objv[5]) == 0) {
	encStatePtr = NULL;
    } else {
	return TCL_ERROR;
    }

    if (Tcl_GetIntFromObj(interp, objv[6], &dstLen) != TCL_OK) {
	return TCL_ERROR;
    }
    srcReadVar = NULL;
    dstWroteVar = NULL;
    dstCharsVar = NULL;
    if (objc > 7) {
	/* Has caller requested srcRead? */
	if (Tcl_GetCharLength(objv[7])) {
	    srcReadVar = objv[7];
	}
	if (objc > 8) {
	    /* Ditto for dstWrote */
	    if (Tcl_GetCharLength(objv[8])) {
		dstWroteVar = objv[8];
	    }
	    if (objc > 9) {
		if (Tcl_GetCharLength(objv[9])) {
		    dstCharsVar = objv[9];
		}
	    }
	}
    }
    if (flags & TCL_ENCODING_CHAR_LIMIT) {
	/* Caller should have specified the dest char limit */
	Tcl_Obj *valueObj;
	if (dstCharsVar == NULL ||
	    (valueObj = Tcl_ObjGetVar2(interp, dstCharsVar, NULL, 0)) == NULL
	) {
	    Tcl_SetResult(interp,
			 "dstCharsVar must be specified with integer value if "
			 "TCL_ENCODING_CHAR_LIMIT set in flags.", TCL_STATIC);
	    return TCL_ERROR;
	}
	if (Tcl_GetIntFromObj(interp, valueObj, &dstChars) != TCL_OK) {
	    return TCL_ERROR;
	}
    } else {
	dstChars = 0; /* Only used for output */
    }

    bufLen = dstLen + 4; /* 4 -> overflow detection */
    bufPtr = (unsigned char *) Tcl_Alloc(bufLen);
    memset(bufPtr, 0xFF, dstLen); /* Need to check nul terminator */
    memmove(bufPtr + dstLen, "\xAB\xCD\xEF\xAB", 4);   /* overflow detection */
    bytes = Tcl_GetByteArrayFromObj(objv[3], &srcLen); /* Last! to avoid shimmering */
    result = (*transformer)(interp, encoding, (const char *)bytes, srcLen, flags,
	    encStatePtr, (char *)bufPtr, dstLen,
	    srcReadVar ? &srcRead : NULL,
	    &dstWrote,
	    dstCharsVar ? &dstChars : NULL);
    if (memcmp(bufPtr + bufLen - 4, "\xAB\xCD\xEF\xAB", 4)) {
	Tcl_SetObjResult(interp,
			 Tcl_ObjPrintf("%s wrote past output buffer",
				       transformer == Tcl_ExternalToUtf ?
				       "Tcl_ExternalToUtf" : "Tcl_UtfToExternal"));
	result = TCL_ERROR;
    } else if (result != TCL_ERROR) {
	Tcl_Obj *resultObjs[3];
	switch (result) {
	case TCL_OK:
	    resultObjs[0] = Tcl_NewStringObj("ok", TCL_INDEX_NONE);
	    break;
	case TCL_CONVERT_MULTIBYTE:
	    resultObjs[0] = Tcl_NewStringObj("multibyte", TCL_INDEX_NONE);
	    break;
	case TCL_CONVERT_SYNTAX:
	    resultObjs[0] = Tcl_NewStringObj("syntax", TCL_INDEX_NONE);
	    break;
	case TCL_CONVERT_UNKNOWN:
	    resultObjs[0] = Tcl_NewStringObj("unknown", TCL_INDEX_NONE);
	    break;
	case TCL_CONVERT_NOSPACE:
	    resultObjs[0] = Tcl_NewStringObj("nospace", TCL_INDEX_NONE);
	    break;
	default:
	    resultObjs[0] = Tcl_NewIntObj(result);
	    break;
	}
	result = TCL_OK;
	resultObjs[1] =
	    encStatePtr ? Tcl_NewWideIntObj((Tcl_WideInt)(size_t)encState) : Tcl_NewObj();
	resultObjs[2] = Tcl_NewByteArrayObj(bufPtr, dstLen);
	if (srcReadVar) {
	    if (Tcl_ObjSetVar2(interp, srcReadVar, NULL, Tcl_NewIntObj(srcRead),
		    TCL_LEAVE_ERR_MSG) == NULL) {
		result = TCL_ERROR;
	    }
	}
	if (dstWroteVar) {
	    if (Tcl_ObjSetVar2(interp, dstWroteVar, NULL, Tcl_NewIntObj(dstWrote),
		    TCL_LEAVE_ERR_MSG) == NULL) {
		result = TCL_ERROR;
	    }
	}
	if (dstCharsVar) {
	    if (Tcl_ObjSetVar2(interp, dstCharsVar, NULL, Tcl_NewIntObj(dstChars),
		    TCL_LEAVE_ERR_MSG) == NULL) {
		result = TCL_ERROR;
	    }
	}
	Tcl_SetObjResult(interp, Tcl_NewListObj(3, resultObjs));
    }

    Tcl_Free(bufPtr);
    Tcl_FreeEncoding(encoding); /* Free returned reference */
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TestencodingCmd --
 *
 *	This procedure implements the "testencoding" command.  It is used
 *	to test the encoding package.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Load encodings.
 *
 *----------------------------------------------------------------------
 */

static int
TestencodingObjCmd(
TestencodingCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Encoding encoding;
    int index, length;
    Tcl_Size length;
    const char *string;
    TclEncoding *encodingPtr;
    static const char *const optionStrings[] = {
	"create",	"delete",	NULL
	"create", "delete", "nullength", "Tcl_ExternalToUtf", "Tcl_UtfToExternal", NULL
    };
    enum options {
	ENC_CREATE,	ENC_DELETE
    };
	ENC_CREATE, ENC_DELETE, ENC_NULLENGTH, ENC_EXTTOUTF, ENC_UTFTOEXT
    } index;

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

    if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum options) index) {
    switch (index) {
    case ENC_CREATE: {
	Tcl_EncodingType type;

	if (objc != 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name toutfcmd fromutfcmd");
	    return TCL_ERROR;
	}
	encodingPtr = (TclEncoding*)Tcl_Alloc(sizeof(TclEncoding));
	encodingPtr = (TclEncoding *)Tcl_Alloc(sizeof(TclEncoding));
	encodingPtr->interp = interp;

	string = Tcl_GetStringFromObj(objv[3], &length);
	encodingPtr->toUtfCmd = (char *)Tcl_Alloc(length + 1);
	memcpy(encodingPtr->toUtfCmd, string, length + 1);

	string = Tcl_GetStringFromObj(objv[4], &length);
1890
1891
1892
1893
1894
1895
1896
1897

1898



















1899
1900
1901
1902
1903
1904
1905
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







-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    return TCL_ERROR;
	}
	if (TCL_OK != Tcl_GetEncodingFromObj(interp, objv[2], &encoding)) {
	    return TCL_ERROR;
	}
	Tcl_FreeEncoding(encoding);	/* Free returned reference */
	Tcl_FreeEncoding(encoding);	/* Free to match CREATE */
	TclFreeIntRep(objv[2]);		/* Free the cached ref */
	TclFreeInternalRep(objv[2]);		/* Free the cached ref */
	break;

    case ENC_NULLENGTH:
	if (objc > 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?encoding?");
	    return TCL_ERROR;
	}
	encoding =
	    Tcl_GetEncoding(interp, objc == 2 ? NULL : Tcl_GetString(objv[2]));
	if (encoding == NULL) {
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp,
		Tcl_NewIntObj(Tcl_GetEncodingNulLength(encoding)));
	Tcl_FreeEncoding(encoding);
	break;
    case ENC_EXTTOUTF:
	return UtfExtWrapper(interp,Tcl_ExternalToUtf,objc,objv);
    case ENC_UTFTOEXT:
	return UtfExtWrapper(interp,Tcl_UtfToExternal,objc,objv);
    }
    return TCL_OK;
}

static int
EncodingToUtfProc(
    void *clientData,	/* TclEncoding structure. */
1913
1914
1915
1916
1917
1918
1919
1920

1921
1922
1923
1924
1925
1926
1927
2391
2392
2393
2394
2395
2396
2397

2398
2399
2400
2401
2402
2403
2404
2405







-
+







    int *dstWrotePtr,		/* Filled with number of bytes stored. */
    int *dstCharsPtr)		/* Filled with number of chars stored. */
{
    int len;
    TclEncoding *encodingPtr;

    encodingPtr = (TclEncoding *) clientData;
    Tcl_EvalEx(encodingPtr->interp, encodingPtr->toUtfCmd, -1, TCL_EVAL_GLOBAL);
    Tcl_EvalEx(encodingPtr->interp, encodingPtr->toUtfCmd, TCL_INDEX_NONE, TCL_EVAL_GLOBAL);

    len = strlen(Tcl_GetStringResult(encodingPtr->interp));
    if (len > dstLen) {
	len = dstLen;
    }
    memcpy(dst, Tcl_GetStringResult(encodingPtr->interp), len);
    Tcl_ResetResult(encodingPtr->interp);
1945
1946
1947
1948
1949
1950
1951
1952

1953
1954
1955
1956
1957
1958
1959
2423
2424
2425
2426
2427
2428
2429

2430
2431
2432
2433
2434
2435
2436
2437







-
+







    int *dstWrotePtr,		/* Filled with number of bytes stored. */
    int *dstCharsPtr)		/* Filled with number of chars stored. */
{
    int len;
    TclEncoding *encodingPtr;

    encodingPtr = (TclEncoding *) clientData;
    Tcl_EvalEx(encodingPtr->interp, encodingPtr->fromUtfCmd, -1, TCL_EVAL_GLOBAL);
    Tcl_EvalEx(encodingPtr->interp, encodingPtr->fromUtfCmd, TCL_INDEX_NONE, TCL_EVAL_GLOBAL);

    len = strlen(Tcl_GetStringResult(encodingPtr->interp));
    if (len > dstLen) {
	len = dstLen;
    }
    memcpy(dst, Tcl_GetStringResult(encodingPtr->interp), len);
    Tcl_ResetResult(encodingPtr->interp);
1974
1975
1976
1977
1978
1979
1980
1981

1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996

1997
1998
1999
2000
2001
2002


2003
2004
2005
2006
2007
2008
2009
2010

2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026

2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041

2042
2043
2044
2045
2046
2047
2048
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

2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504

2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519

2520
2521
2522
2523
2524
2525
2526
2527







-
+














-
+





-
+
+







-
+















-
+














-
+







    Tcl_Free(encodingPtr->fromUtfCmd);
    Tcl_Free(encodingPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TestevalexObjCmd --
 * TestevalexCmd --
 *
 *	This procedure implements the "testevalex" command.  It is
 *	used to test Tcl_EvalEx.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestevalexObjCmd(
TestevalexCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int length, flags;
    int flags;
    Tcl_Size length;
    const char *script;

    flags = 0;
    if (objc == 3) {
	const char *global = Tcl_GetString(objv[2]);
	if (strcmp(global, "global") != 0) {
	    Tcl_AppendResult(interp, "bad value \"", global,
		    "\": must be global", NULL);
		    "\": must be global", (char *)NULL);
	    return TCL_ERROR;
	}
	flags = TCL_EVAL_GLOBAL;
    } else if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "script ?global?");
	return TCL_ERROR;
    }

    script = Tcl_GetStringFromObj(objv[1], &length);
    return Tcl_EvalEx(interp, script, length, flags);
}

/*
 *----------------------------------------------------------------------
 *
 * TestevalobjvObjCmd --
 * TestevalobjvCmd --
 *
 *	This procedure implements the "testevalobjv" command.  It is
 *	used to test Tcl_EvalObjv.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestevalobjvObjCmd(
TestevalobjvCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int evalGlobal;

2056
2057
2058
2059
2060
2061
2062
2063

2064
2065
2066
2067
2068
2069
2070
2535
2536
2537
2538
2539
2540
2541

2542
2543
2544
2545
2546
2547
2548
2549







-
+







    return Tcl_EvalObjv(interp, objc-2, objv+2,
	    (evalGlobal) ? TCL_EVAL_GLOBAL : 0);
}

/*
 *----------------------------------------------------------------------
 *
 * TesteventObjCmd --
 * TesteventCmd --
 *
 *	This procedure implements a 'testevent' command.  The command
 *	is used to test event queue management.
 *
 * The command takes two forms:
 *	- testevent queue name position script
 *		Queues an event at the given position in the queue, and
2083
2084
2085
2086
2087
2088
2089
2090

2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104

2105
2106
2107
2108
2109
2110
2111
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







-
+













-
+







 * Side effects:
 *	Manipulates the event queue as directed.
 *
 *----------------------------------------------------------------------
 */

static int
TesteventObjCmd(
TesteventCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const objv[])	/* Parameter vector */
{
    static const char *const subcommands[] = { /* Possible subcommands */
	"queue", "delete", NULL
    };
    int subCmdIndex;		/* Index of the chosen subcommand */
    static const char *const positions[] = { /* Possible queue positions */
	"head", "tail", "mark", NULL
    };
    int posIndex;		/* Index of the chosen position */
    static const Tcl_QueuePosition posNum[] = {
    static const int posNum[] = {
				/* Interpretation of the chosen position */
	TCL_QUEUE_HEAD,
	TCL_QUEUE_TAIL,
	TCL_QUEUE_MARK
    };
    TestEvent *ev;		/* Event to be queued */

2232
2233
2234
2235
2236
2237
2238
2239

2240
2241
2242
2243
2244
2245
2246
2711
2712
2713
2714
2715
2716
2717

2718
2719
2720
2721
2722
2723
2724
2725







-
+







    Tcl_Obj *targetName;	/* Name of the event(s) to delete */
    const char *targetNameStr;

    if (event->proc != TesteventProc) {
	return 0;
    }
    targetName = (Tcl_Obj *) clientData;
    targetNameStr = (char *) Tcl_GetString(targetName);
    targetNameStr = (char *)Tcl_GetString(targetName);
    ev = (TestEvent *) event;
    evNameStr = Tcl_GetString(ev->tag);
    if (strcmp(evNameStr, targetNameStr) == 0) {
	Tcl_DecrRefCount(ev->tag);
	Tcl_DecrRefCount(ev->command);
	return 1;
    } else {
2265
2266
2267
2268
2269
2270
2271
2272
2273


2274
2275
2276
2277

2278
2279

2280
2281
2282

2283
2284
2285

2286
2287
2288

2289
2290
2291
2292
2293


2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306

2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320

2321
2322
2323
2324
2325
2326
2327
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







-
-
+
+



-
+
-
-
+


-
+


-
+


-
+



-
-
+
+












-
+













-
+







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

static int
TestexithandlerCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    int value;

    if (argc != 3) {
    if (objc != 3) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" create|delete value\"", NULL);
	Tcl_WrongNumArgs(interp, 1, objv, "create|delete value");
	return TCL_ERROR;
    }
    if (Tcl_GetInt(interp, argv[2], &value) != TCL_OK) {
    if (Tcl_GetIntFromObj(interp, objv[2], &value) != TCL_OK) {
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
    if (strcmp(Tcl_GetString(objv[1]), "create") == 0) {
	Tcl_CreateExitHandler((value & 1) ? ExitProcOdd : ExitProcEven,
		INT2PTR(value));
    } else if (strcmp(argv[1], "delete") == 0) {
    } else if (strcmp(Tcl_GetString(objv[1]), "delete") == 0) {
	Tcl_DeleteExitHandler((value & 1) ? ExitProcOdd : ExitProcEven,
		INT2PTR(value));
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[1],
		"\": must be create or delete", NULL);
	Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
		"\": must be create or delete", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

static void
ExitProcOdd(
    void *clientData)	/* Integer value to print. */
{
    char buf[16 + TCL_INTEGER_SPACE];
    int len;

    sprintf(buf, "odd %d\n", (int)PTR2INT(clientData));
    snprintf(buf, sizeof(buf), "odd %d\n", (int)PTR2INT(clientData));
    len = strlen(buf);
    if (len != (int) write(1, buf, len)) {
	Tcl_Panic("ExitProcOdd: unable to write to stdout");
    }
}

static void
ExitProcEven(
    void *clientData)	/* Integer value to print. */
{
    char buf[16 + TCL_INTEGER_SPACE];
    int len;

    sprintf(buf, "even %d\n", (int)PTR2INT(clientData));
    snprintf(buf, sizeof(buf), "even %d\n", (int)PTR2INT(clientData));
    len = strlen(buf);
    if (len != (int) write(1, buf, len)) {
	Tcl_Panic("ExitProcEven: unable to write to stdout");
    }
}

/*
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
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







-
-
+
+





-
+
-
-
+


-
-
+
+



-
-
+
+







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

static int
TestexprlongCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    long exprResult;
    char buf[4 + TCL_INTEGER_SPACE];
    int result;

    if (argc != 2) {
    if (objc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" expression\"", NULL);
	Tcl_WrongNumArgs(interp, 1, objv, "expression");
	return TCL_ERROR;
    }
    Tcl_AppendResult(interp, "This is a result", NULL);
    result = Tcl_ExprLong(interp, argv[1], &exprResult);
    Tcl_AppendResult(interp, "This is a result", (char *)NULL);
    result = Tcl_ExprLong(interp, Tcl_GetString(objv[1]), &exprResult);
    if (result != TCL_OK) {
	return result;
    }
    sprintf(buf, ": %ld", exprResult);
    Tcl_AppendResult(interp, buf, NULL);
    snprintf(buf, sizeof(buf), ": %ld", exprResult);
    Tcl_AppendResult(interp, buf, (char *)NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestexprlongobjCmd --
2395
2396
2397
2398
2399
2400
2401
2402

2403
2404
2405
2406
2407
2408


2409
2410
2411
2412
2413
2414
2415
2872
2873
2874
2875
2876
2877
2878

2879
2880
2881
2882
2883


2884
2885
2886
2887
2888
2889
2890
2891
2892







-
+




-
-
+
+







    char buf[4 + TCL_INTEGER_SPACE];
    int result;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "expression");
	return TCL_ERROR;
    }
    Tcl_AppendResult(interp, "This is a result", NULL);
    Tcl_AppendResult(interp, "This is a result", (char *)NULL);
    result = Tcl_ExprLongObj(interp, objv[1], &exprResult);
    if (result != TCL_OK) {
	return result;
    }
    sprintf(buf, ": %ld", exprResult);
    Tcl_AppendResult(interp, buf, NULL);
    snprintf(buf, sizeof(buf), ": %ld", exprResult);
    Tcl_AppendResult(interp, buf, (char *)NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestexprdoubleCmd --
2426
2427
2428
2429
2430
2431
2432
2433
2434


2435
2436
2437
2438
2439
2440

2441
2442

2443
2444
2445
2446


2447
2448
2449
2450
2451
2452

2453
2454
2455
2456
2457
2458
2459
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







-
-
+
+





-
+
-
-
+


-
-
+
+





-
+







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

static int
TestexprdoubleCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    double exprResult;
    char buf[4 + TCL_DOUBLE_SPACE];
    int result;

    if (argc != 2) {
    if (objc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" expression\"", NULL);
	Tcl_WrongNumArgs(interp, 1, objv, "expression");
	return TCL_ERROR;
    }
    Tcl_AppendResult(interp, "This is a result", NULL);
    result = Tcl_ExprDouble(interp, argv[1], &exprResult);
    Tcl_AppendResult(interp, "This is a result", (char *)NULL);
    result = Tcl_ExprDouble(interp, Tcl_GetString(objv[1]), &exprResult);
    if (result != TCL_OK) {
	return result;
    }
    strcpy(buf, ": ");
    Tcl_PrintDouble(interp, exprResult, buf+2);
    Tcl_AppendResult(interp, buf, NULL);
    Tcl_AppendResult(interp, buf, (char *)NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestexprdoubleobjCmd --
2481
2482
2483
2484
2485
2486
2487
2488

2489
2490
2491
2492
2493
2494
2495

2496
2497
2498
2499
2500
2501
2502
2957
2958
2959
2960
2961
2962
2963

2964
2965
2966
2967
2968
2969
2970

2971
2972
2973
2974
2975
2976
2977
2978







-
+






-
+







    char buf[4 + TCL_DOUBLE_SPACE];
    int result;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "expression");
	return TCL_ERROR;
    }
    Tcl_AppendResult(interp, "This is a result", NULL);
    Tcl_AppendResult(interp, "This is a result", (char *)NULL);
    result = Tcl_ExprDoubleObj(interp, objv[1], &exprResult);
    if (result != TCL_OK) {
	return result;
    }
    strcpy(buf, ": ");
    Tcl_PrintDouble(interp, exprResult, buf+2);
    Tcl_AppendResult(interp, buf, NULL);
    Tcl_AppendResult(interp, buf, (char *)NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestexprstringCmd --
2512
2513
2514
2515
2516
2517
2518
2519
2520


2521
2522

2523
2524

2525
2526
2527

2528
2529
2530
2531
2532
2533
2534
2988
2989
2990
2991
2992
2993
2994


2995
2996
2997

2998


2999
3000
3001

3002
3003
3004
3005
3006
3007
3008
3009







-
-
+
+

-
+
-
-
+


-
+







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

static int
TestexprstringCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)		/* Argument strings. */
{
    if (argc != 2) {
    if (objc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" expression\"", NULL);
	Tcl_WrongNumArgs(interp, 1, objv, "expression");
	return TCL_ERROR;
    }
    return Tcl_ExprString(interp, argv[1]);
    return Tcl_ExprString(interp, Tcl_GetString(objv[1]));
}

/*
 *----------------------------------------------------------------------
 *
 * TestfilelinkCmd --
 *
2566
2567
2568
2569
2570
2571
2572
2573

2574
2575
2576
2577
2578
2579
2580
2581
2582

2583
2584
2585
2586
2587
2588
2589
3041
3042
3043
3044
3045
3046
3047

3048
3049
3050
3051
3052
3053
3054
3055
3056

3057
3058
3059
3060
3061
3062
3063
3064







-
+








-
+







	/* Create link from source to target */
	contents = Tcl_FSLink(objv[1], objv[2],
		TCL_CREATE_SYMBOLIC_LINK|TCL_CREATE_HARD_LINK);
	if (contents == NULL) {
	    Tcl_AppendResult(interp, "could not create link from \"",
		    Tcl_GetString(objv[1]), "\" to \"",
		    Tcl_GetString(objv[2]), "\": ",
		    Tcl_PosixError(interp), NULL);
		    Tcl_PosixError(interp), (char *)NULL);
	    return TCL_ERROR;
	}
    } else {
	/* Read link */
	contents = Tcl_FSLink(objv[1], NULL, 0);
	if (contents == NULL) {
	    Tcl_AppendResult(interp, "could not read link \"",
		    Tcl_GetString(objv[1]), "\": ",
		    Tcl_PosixError(interp), NULL);
		    Tcl_PosixError(interp), (char *)NULL);
	    return TCL_ERROR;
	}
    }
    Tcl_SetObjResult(interp, contents);
    if (objc == 2) {
	/*
	 * If we are creating a link, this will actually just
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
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
3134
3135
3136
3137


3138
3139

3140
3141
3142

3143
3144
3145
3146
3147
3148
3149
3150







-
-
+
+



-
+
-
-
+


-
+

-
+










-
+














-
-
+
+






-
-
+
+
-



-
+







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

static int
TestgetassocdataCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    char *res;

    if (argc != 2) {
    if (objc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" data_key\"", NULL);
	Tcl_WrongNumArgs(interp, 1, objv, "data_key");
	return TCL_ERROR;
    }
    res = (char *) Tcl_GetAssocData(interp, argv[1], NULL);
    res = (char *)Tcl_GetAssocData(interp, Tcl_GetString(objv[1]), NULL);
    if (res != NULL) {
	Tcl_AppendResult(interp, res, NULL);
	Tcl_AppendResult(interp, res, (char *)NULL);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestgetplatformCmd --
 *
 *	This procedure implements the "testgetplatform" command. It is
 *	used to retrievel the value of the tclPlatform global variable.
 *	used to retrieve the value of the tclPlatform global variable.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestgetplatformCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    static const char *const platformStrings[] = { "unix", "mac", "windows" };
    TclPlatformType *platform;

    platform = TclGetPlatform();

    if (argc != 1) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, "");
		NULL);
	return TCL_ERROR;
    }

    Tcl_AppendResult(interp, platformStrings[*platform], NULL);
    Tcl_AppendResult(interp, platformStrings[*platform], (char *)NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestinterpdeleteCmd --
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
3162
3163
3164
3165
3166
3167
3168


3169
3170
3171
3172
3173


3174
3175

3176
3177

3178
3179
3180
3181
3182
3183
3184
3185







-
-
+
+



-
-
+
+
-


-
+







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

static int
TestinterpdeleteCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    Tcl_Interp *childToDelete;

    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "path");
		" path\"", NULL);
	return TCL_ERROR;
    }
    childToDelete = Tcl_GetChild(interp, argv[1]);
    childToDelete = Tcl_GetChild(interp, Tcl_GetString(objv[1]));
    if (childToDelete == NULL) {
	return TCL_ERROR;
    }
    Tcl_DeleteInterp(childToDelete);
    return TCL_OK;
}

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
3201
3202
3203
3204
3205
3206
3207


3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229

3230



3231
3232
3233
3234


3235
3236




3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257

3258
3259
3260

3261
3262
3263
3264
3265

3266
3267
3268

3269
3270
3271
3272
3273

3274
3275
3276

3277
3278
3279
3280
3281

3282
3283
3284

3285
3286
3287
3288
3289

3290
3291
3292

3293
3294

3295
3296
3297

3298
3299
3300

3301
3302
3303
3304
3305

3306
3307
3308

3309
3310
3311
3312
3313

3314
3315
3316

3317
3318
3319
3320
3321

3322
3323
3324

3325
3326
3327
3328
3329

3330
3331
3332

3333
3334
3335
3336
3337

3338
3339
3340

3341
3342
3343
3344
3345

3346
3347
3348

3349
3350
3351
3352
3353

3354
3355
3356

3357
3358
3359
3360
3361

3362
3363
3364

3365
3366
3367
3368
3369
3370

3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386

3387
3388
3389
3390
3391
3392
3393
3394







-
-
+
+




















-
+
-
-
-
+
+


-
-
+
+
-
-
-
-
+
+



















-
+


-
+




-
+


-
+




-
+


-
+




-
+


-
+




-
+


-
+

-
+


-
+


-
+




-
+


-
+




-
+


-
+




-
+


-
+




-
+


-
+




-
+


-
+




-
+


-
+




-
+


-
+




-
+


-
+





-
+















-
+







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

static int
TestlinkCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    static int intVar = 43;
    static int boolVar = 4;
    static double realVar = 1.23;
    static Tcl_WideInt wideVar = 79;
    static char *stringVar = NULL;
    static char charVar = '@';
    static unsigned char ucharVar = 130;
    static short shortVar = 3000;
    static unsigned short ushortVar = 60000;
    static unsigned int uintVar = 0xBEEFFEED;
    static long longVar = 123456789L;
    static unsigned long ulongVar = 3456789012UL;
    static float floatVar = 4.5;
    static Tcl_WideUInt uwideVar = 123;
    static int created = 0;
    char buffer[2*TCL_DOUBLE_SPACE];
    int writable, flag;
    Tcl_Obj *tmp;

    if (argc < 2) {
    if (objc < 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" option ?arg arg arg arg arg arg arg arg arg arg arg arg"
		" arg arg?\"", NULL);
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg arg arg arg arg arg arg arg arg arg arg"
		" arg arg?");
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	if (argc != 16) {
    if (strcmp(Tcl_GetString(objv[1]), "create") == 0) {
	if (objc != 16) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		argv[0], " ", argv[1],
		" intRO realRO boolRO stringRO wideRO charRO ucharRO shortRO"
		" ushortRO uintRO longRO ulongRO floatRO uwideRO\"", NULL);
		Tcl_WrongNumArgs(interp, 2, objv, "intRO realRO boolRO stringRO wideRO charRO ucharRO shortRO"
			" ushortRO uintRO longRO ulongRO floatRO uwideRO");
	    return TCL_ERROR;
	}
	if (created) {
	    Tcl_UnlinkVar(interp, "int");
	    Tcl_UnlinkVar(interp, "real");
	    Tcl_UnlinkVar(interp, "bool");
	    Tcl_UnlinkVar(interp, "string");
	    Tcl_UnlinkVar(interp, "wide");
	    Tcl_UnlinkVar(interp, "char");
	    Tcl_UnlinkVar(interp, "uchar");
	    Tcl_UnlinkVar(interp, "short");
	    Tcl_UnlinkVar(interp, "ushort");
	    Tcl_UnlinkVar(interp, "uint");
	    Tcl_UnlinkVar(interp, "long");
	    Tcl_UnlinkVar(interp, "ulong");
	    Tcl_UnlinkVar(interp, "float");
	    Tcl_UnlinkVar(interp, "uwide");
	}
	created = 1;
	if (Tcl_GetBoolean(interp, argv[2], &writable) != TCL_OK) {
	if (Tcl_GetBooleanFromObj(interp, objv[2], &writable) != TCL_OK) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
	flag = writable ? 0 : TCL_LINK_READ_ONLY;
	if (Tcl_LinkVar(interp, "int", &intVar,
		TCL_LINK_INT | flag) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBoolean(interp, argv[3], &writable) != TCL_OK) {
	if (Tcl_GetBooleanFromObj(interp, objv[3], &writable) != TCL_OK) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
	flag = writable ? 0 : TCL_LINK_READ_ONLY;
	if (Tcl_LinkVar(interp, "real", &realVar,
		TCL_LINK_DOUBLE | flag) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBoolean(interp, argv[4], &writable) != TCL_OK) {
	if (Tcl_GetBooleanFromObj(interp, objv[4], &writable) != TCL_OK) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
	flag = writable ? 0 : TCL_LINK_READ_ONLY;
	if (Tcl_LinkVar(interp, "bool", &boolVar,
		TCL_LINK_BOOLEAN | flag) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBoolean(interp, argv[5], &writable) != TCL_OK) {
	if (Tcl_GetBooleanFromObj(interp, objv[5], &writable) != TCL_OK) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
	flag = writable ? 0 : TCL_LINK_READ_ONLY;
	if (Tcl_LinkVar(interp, "string", &stringVar,
		TCL_LINK_STRING | flag) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBoolean(interp, argv[6], &writable) != TCL_OK) {
	if (Tcl_GetBooleanFromObj(interp, objv[6], &writable) != TCL_OK) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
	flag = writable ? 0 : TCL_LINK_READ_ONLY;
	if (Tcl_LinkVar(interp, "wide", &wideVar,
			TCL_LINK_WIDE_INT | flag) != TCL_OK) {
		TCL_LINK_WIDE_INT | flag) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBoolean(interp, argv[7], &writable) != TCL_OK) {
	if (Tcl_GetBooleanFromObj(interp, objv[7], &writable) != TCL_OK) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
	flag = writable ? 0 : TCL_LINK_READ_ONLY;
	if (Tcl_LinkVar(interp, "char", &charVar,
		TCL_LINK_CHAR | flag) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBoolean(interp, argv[8], &writable) != TCL_OK) {
	if (Tcl_GetBooleanFromObj(interp, objv[8], &writable) != TCL_OK) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
	flag = writable ? 0 : TCL_LINK_READ_ONLY;
	if (Tcl_LinkVar(interp, "uchar", &ucharVar,
		TCL_LINK_UCHAR | flag) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBoolean(interp, argv[9], &writable) != TCL_OK) {
	if (Tcl_GetBooleanFromObj(interp, objv[9], &writable) != TCL_OK) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
	flag = writable ? 0 : TCL_LINK_READ_ONLY;
	if (Tcl_LinkVar(interp, "short", &shortVar,
		TCL_LINK_SHORT | flag) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBoolean(interp, argv[10], &writable) != TCL_OK) {
	if (Tcl_GetBooleanFromObj(interp, objv[10], &writable) != TCL_OK) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
	flag = writable ? 0 : TCL_LINK_READ_ONLY;
	if (Tcl_LinkVar(interp, "ushort", &ushortVar,
		TCL_LINK_USHORT | flag) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBoolean(interp, argv[11], &writable) != TCL_OK) {
	if (Tcl_GetBooleanFromObj(interp, objv[11], &writable) != TCL_OK) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
	flag = writable ? 0 : TCL_LINK_READ_ONLY;
	if (Tcl_LinkVar(interp, "uint", &uintVar,
		TCL_LINK_UINT | flag) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBoolean(interp, argv[12], &writable) != TCL_OK) {
	if (Tcl_GetBooleanFromObj(interp, objv[12], &writable) != TCL_OK) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
	flag = writable ? 0 : TCL_LINK_READ_ONLY;
	if (Tcl_LinkVar(interp, "long", &longVar,
		TCL_LINK_LONG | flag) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBoolean(interp, argv[13], &writable) != TCL_OK) {
	if (Tcl_GetBooleanFromObj(interp, objv[13], &writable) != TCL_OK) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
	flag = writable ? 0 : TCL_LINK_READ_ONLY;
	if (Tcl_LinkVar(interp, "ulong", &ulongVar,
		TCL_LINK_ULONG | flag) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBoolean(interp, argv[14], &writable) != TCL_OK) {
	if (Tcl_GetBooleanFromObj(interp, objv[14], &writable) != TCL_OK) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
	flag = writable ? 0 : TCL_LINK_READ_ONLY;
	if (Tcl_LinkVar(interp, "float", &floatVar,
		TCL_LINK_FLOAT | flag) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBoolean(interp, argv[15], &writable) != TCL_OK) {
	if (Tcl_GetBooleanFromObj(interp, objv[15], &writable) != TCL_OK) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
	flag = writable ? 0 : TCL_LINK_READ_ONLY;
	if (Tcl_LinkVar(interp, "uwide", &uwideVar,
		TCL_LINK_WIDE_UINT | flag) != TCL_OK) {
	    return TCL_ERROR;
	}

    } else if (strcmp(argv[1], "delete") == 0) {
    } else if (strcmp(Tcl_GetString(objv[1]), "delete") == 0) {
	Tcl_UnlinkVar(interp, "int");
	Tcl_UnlinkVar(interp, "real");
	Tcl_UnlinkVar(interp, "bool");
	Tcl_UnlinkVar(interp, "string");
	Tcl_UnlinkVar(interp, "wide");
	Tcl_UnlinkVar(interp, "char");
	Tcl_UnlinkVar(interp, "uchar");
	Tcl_UnlinkVar(interp, "short");
	Tcl_UnlinkVar(interp, "ushort");
	Tcl_UnlinkVar(interp, "uint");
	Tcl_UnlinkVar(interp, "long");
	Tcl_UnlinkVar(interp, "ulong");
	Tcl_UnlinkVar(interp, "float");
	Tcl_UnlinkVar(interp, "uwide");
	created = 0;
    } else if (strcmp(argv[1], "get") == 0) {
    } else if (strcmp(Tcl_GetString(objv[1]), "get") == 0) {
	TclFormatInt(buffer, intVar);
	Tcl_AppendElement(interp, buffer);
	Tcl_PrintDouble(NULL, realVar, buffer);
	Tcl_AppendElement(interp, buffer);
	TclFormatInt(buffer, boolVar);
	Tcl_AppendElement(interp, buffer);
	Tcl_AppendElement(interp, (stringVar == NULL) ? "-" : stringVar);
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
3134
3135
3136


3137
3138
3139
3140
3141
3142
3143


3144
3145
3146
3147
3148
3149
3150


3151
3152
3153
3154
3155
3156

3157
3158

3159
3160
3161
3162
3163
3164

3165
3166

3167
3168
3169
3170
3171
3172

3173
3174
3175
3176
3177


3178
3179
3180
3181
3182
3183
3184
3407
3408
3409
3410
3411
3412
3413

3414
3415
3416
3417
3418

3419
3420
3421

3422
3423
3424

3425



3426
3427

3428
3429
3430


3431
3432
3433
3434
3435
3436
3437
3438
3439
3440


3441
3442
3443
3444
3445

3446





3447
3448
3449

3450
3451
3452


3453
3454
3455
3456


3457
3458
3459
3460
3461
3462
3463
3464


3465
3466
3467
3468
3469
3470


3471
3472
3473
3474
3475
3476


3477
3478
3479
3480
3481
3482


3483
3484
3485
3486
3487
3488


3489
3490
3491
3492
3493
3494


3495
3496
3497
3498
3499
3500


3501
3502
3503
3504
3505
3506

3507
3508

3509
3510
3511
3512
3513

3514
3515

3516
3517
3518
3519
3520
3521

3522
3523

3524
3525
3526

3527



3528
3529

3530
3531
3532


3533
3534
3535
3536
3537
3538


3539
3540
3541
3542
3543
3544


3545
3546
3547
3548
3549
3550

3551
3552
3553
3554

3555
3556
3557


3558
3559
3560
3561
3562


3563
3564
3565
3566
3567
3568
3569
3570
3571


3572
3573
3574
3575
3576
3577
3578


3579
3580
3581
3582
3583
3584
3585


3586
3587
3588
3589
3590
3591
3592


3593
3594
3595
3596
3597
3598
3599


3600
3601
3602
3603
3604
3605
3606


3607
3608
3609
3610
3611
3612
3613


3614
3615
3616
3617
3618
3619
3620

3621
3622

3623
3624
3625
3626
3627
3628

3629
3630

3631
3632
3633
3634
3635
3636

3637
3638
3639
3640


3641
3642
3643
3644
3645
3646
3647
3648
3649







-
+




-
+


-
+


-
+
-
-
-
+

-
+


-
-
+
+
+
+
+
+
+



-
-
+
+



-
+
-
-
-
-
-



-
+


-
-
+
+


-
-
+
+






-
-
+
+




-
-
+
+




-
-
+
+




-
-
+
+




-
-
+
+




-
-
+
+




-
-
+
+




-
+

-
+




-
+

-
+





-
+

-
+


-
+
-
-
-
+

-
+


-
-
+
+




-
-
+
+




-
-
+
+




-
+



-
+


-
-
+
+



-
-
+
+







-
-
+
+





-
-
+
+





-
-
+
+





-
-
+
+





-
-
+
+





-
-
+
+





-
-
+
+





-
+

-
+





-
+

-
+





-
+



-
-
+
+







	TclFormatInt(buffer, (int) ushortVar);
	Tcl_AppendElement(interp, buffer);
	TclFormatInt(buffer, (int) uintVar);
	Tcl_AppendElement(interp, buffer);
	tmp = Tcl_NewWideIntObj(longVar);
	Tcl_AppendElement(interp, Tcl_GetString(tmp));
	Tcl_DecrRefCount(tmp);
	tmp = Tcl_NewWideIntObj((long)ulongVar);
	tmp = Tcl_NewWideUIntObj(ulongVar);
	Tcl_AppendElement(interp, Tcl_GetString(tmp));
	Tcl_DecrRefCount(tmp);
	Tcl_PrintDouble(NULL, (double)floatVar, buffer);
	Tcl_AppendElement(interp, buffer);
	tmp = Tcl_NewWideIntObj((Tcl_WideInt)uwideVar);
	tmp = Tcl_NewWideUIntObj(uwideVar);
	Tcl_AppendElement(interp, Tcl_GetString(tmp));
	Tcl_DecrRefCount(tmp);
    } else if (strcmp(argv[1], "set") == 0) {
    } else if (strcmp(Tcl_GetString(objv[1]), "set") == 0) {
	int v;

	if (argc != 16) {
	if (objc != 16) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " ", argv[1],
		    " intValue realValue boolValue stringValue wideValue"
	    Tcl_WrongNumArgs(interp, 2, objv, "intValue realValue boolValue stringValue wideValue"
		    " charValue ucharValue shortValue ushortValue uintValue"
		    " longValue ulongValue floatValue uwideValue\"", NULL);
		    " longValue ulongValue floatValue uwideValue");
	    return TCL_ERROR;
	}
	if (argv[2][0] != 0) {
	    if (Tcl_GetInt(interp, argv[2], &intVar) != TCL_OK) {
	if (Tcl_GetString(objv[2])[0] != 0) {
	    if (Tcl_GetIntFromObj(interp, objv[2], &intVar) != TCL_OK) {
		return TCL_ERROR;
	    }
	}
	if (Tcl_GetString(objv[3])[0] != 0) {
	    if (Tcl_GetDoubleFromObj(interp, objv[3], &realVar) != TCL_OK) {
		return TCL_ERROR;
	    }
	}
	if (argv[3][0] != 0) {
	    if (Tcl_GetDouble(interp, argv[3], &realVar) != TCL_OK) {
	if (Tcl_GetString(objv[4])[0] != 0) {
	    if (Tcl_GetBooleanFromObj(interp, objv[4], &boolVar) != TCL_OK) {
		return TCL_ERROR;
	    }
	}
	if (argv[4][0] != 0) {
	if (Tcl_GetString(objv[5])[0] != 0) {
	    if (Tcl_GetInt(interp, argv[4], &boolVar) != TCL_OK) {
		return TCL_ERROR;
	    }
	}
	if (argv[5][0] != 0) {
	    if (stringVar != NULL) {
		Tcl_Free(stringVar);
	    }
	    if (strcmp(argv[5], "-") == 0) {
	    if (strcmp(Tcl_GetString(objv[5]), "-") == 0) {
		stringVar = NULL;
	    } else {
		stringVar = (char *)Tcl_Alloc(strlen(argv[5]) + 1);
		strcpy(stringVar, argv[5]);
		stringVar = (char *)Tcl_Alloc(strlen(Tcl_GetString(objv[5])) + 1);
		strcpy(stringVar, Tcl_GetString(objv[5]));
	    }
	}
	if (argv[6][0] != 0) {
	    tmp = Tcl_NewStringObj(argv[6], -1);
	if (Tcl_GetString(objv[6])[0] != 0) {
	    tmp = Tcl_NewStringObj(Tcl_GetString(objv[6]), -1);
	    if (Tcl_GetWideIntFromObj(interp, tmp, &wideVar) != TCL_OK) {
		Tcl_DecrRefCount(tmp);
		return TCL_ERROR;
	    }
	    Tcl_DecrRefCount(tmp);
	}
	if (argv[7][0]) {
	    if (Tcl_GetInt(interp, argv[7], &v) != TCL_OK) {
	if (Tcl_GetString(objv[7])[0]) {
	    if (Tcl_GetIntFromObj(interp, objv[7], &v) != TCL_OK) {
		return TCL_ERROR;
	    }
	    charVar = (char) v;
	}
	if (argv[8][0]) {
	    if (Tcl_GetInt(interp, argv[8], &v) != TCL_OK) {
	if (Tcl_GetString(objv[8])[0]) {
	    if (Tcl_GetIntFromObj(interp, objv[8], &v) != TCL_OK) {
		return TCL_ERROR;
	    }
	    ucharVar = (unsigned char) v;
	}
	if (argv[9][0]) {
	    if (Tcl_GetInt(interp, argv[9], &v) != TCL_OK) {
	if (Tcl_GetString(objv[9])[0]) {
	    if (Tcl_GetIntFromObj(interp, objv[9], &v) != TCL_OK) {
		return TCL_ERROR;
	    }
	    shortVar = (short) v;
	}
	if (argv[10][0]) {
	    if (Tcl_GetInt(interp, argv[10], &v) != TCL_OK) {
	if (Tcl_GetString(objv[10])[0]) {
	    if (Tcl_GetIntFromObj(interp, objv[10], &v) != TCL_OK) {
		return TCL_ERROR;
	    }
	    ushortVar = (unsigned short) v;
	}
	if (argv[11][0]) {
	    if (Tcl_GetInt(interp, argv[11], &v) != TCL_OK) {
	if (Tcl_GetString(objv[11])[0]) {
	    if (Tcl_GetIntFromObj(interp, objv[11], &v) != TCL_OK) {
		return TCL_ERROR;
	    }
	    uintVar = (unsigned int) v;
	}
	if (argv[12][0]) {
	    if (Tcl_GetInt(interp, argv[12], &v) != TCL_OK) {
	if (Tcl_GetString(objv[12])[0]) {
	    if (Tcl_GetIntFromObj(interp, objv[12], &v) != TCL_OK) {
		return TCL_ERROR;
	    }
	    longVar = (long) v;
	}
	if (argv[13][0]) {
	    if (Tcl_GetInt(interp, argv[13], &v) != TCL_OK) {
	if (Tcl_GetString(objv[13])[0]) {
	    if (Tcl_GetIntFromObj(interp, objv[13], &v) != TCL_OK) {
		return TCL_ERROR;
	    }
	    ulongVar = (unsigned long) v;
	}
	if (argv[14][0]) {
	if (Tcl_GetString(objv[14])[0]) {
	    double d;
	    if (Tcl_GetDouble(interp, argv[14], &d) != TCL_OK) {
	    if (Tcl_GetDoubleFromObj(interp, objv[14], &d) != TCL_OK) {
		return TCL_ERROR;
	    }
	    floatVar = (float) d;
	}
	if (argv[15][0]) {
	if (Tcl_GetString(objv[15])[0]) {
	    Tcl_WideInt w;
	    tmp = Tcl_NewStringObj(argv[15], -1);
	    tmp = Tcl_NewStringObj(Tcl_GetString(objv[15]), -1);
	    if (Tcl_GetWideIntFromObj(interp, tmp, &w) != TCL_OK) {
		Tcl_DecrRefCount(tmp);
		return TCL_ERROR;
	    }
	    Tcl_DecrRefCount(tmp);
	    uwideVar = (Tcl_WideUInt) w;
	    uwideVar = (Tcl_WideUInt)w;
	}
    } else if (strcmp(argv[1], "update") == 0) {
    } else if (strcmp(Tcl_GetString(objv[1]), "update") == 0) {
	int v;

	if (argc != 16) {
	if (objc != 16) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " ", argv[1],
		    " intValue realValue boolValue stringValue wideValue"
	    Tcl_WrongNumArgs(interp, 2, objv, "intValue realValue boolValue stringValue wideValue"
		    " charValue ucharValue shortValue ushortValue uintValue"
		    " longValue ulongValue floatValue uwideValue\"", NULL);
		    " longValue ulongValue floatValue uwideValue");
	    return TCL_ERROR;
	}
	if (argv[2][0] != 0) {
	    if (Tcl_GetInt(interp, argv[2], &intVar) != TCL_OK) {
	if (Tcl_GetString(objv[2])[0] != 0) {
	    if (Tcl_GetIntFromObj(interp, objv[2], &intVar) != TCL_OK) {
		return TCL_ERROR;
	    }
	    Tcl_UpdateLinkedVar(interp, "int");
	}
	if (argv[3][0] != 0) {
	    if (Tcl_GetDouble(interp, argv[3], &realVar) != TCL_OK) {
	if (Tcl_GetString(objv[3])[0] != 0) {
	    if (Tcl_GetDoubleFromObj(interp, objv[3], &realVar) != TCL_OK) {
		return TCL_ERROR;
	    }
	    Tcl_UpdateLinkedVar(interp, "real");
	}
	if (argv[4][0] != 0) {
	    if (Tcl_GetInt(interp, argv[4], &boolVar) != TCL_OK) {
	if (Tcl_GetString(objv[4])[0] != 0) {
	    if (Tcl_GetIntFromObj(interp, objv[4], &boolVar) != TCL_OK) {
		return TCL_ERROR;
	    }
	    Tcl_UpdateLinkedVar(interp, "bool");
	}
	if (argv[5][0] != 0) {
	if (Tcl_GetString(objv[5])[0] != 0) {
	    if (stringVar != NULL) {
		Tcl_Free(stringVar);
	    }
	    if (strcmp(argv[5], "-") == 0) {
	    if (strcmp(Tcl_GetString(objv[5]), "-") == 0) {
		stringVar = NULL;
	    } else {
		stringVar = (char *)Tcl_Alloc(strlen(argv[5]) + 1);
		strcpy(stringVar, argv[5]);
		stringVar = (char *)Tcl_Alloc(strlen(Tcl_GetString(objv[5])) + 1);
		strcpy(stringVar, Tcl_GetString(objv[5]));
	    }
	    Tcl_UpdateLinkedVar(interp, "string");
	}
	if (argv[6][0] != 0) {
	    tmp = Tcl_NewStringObj(argv[6], -1);
	if (Tcl_GetString(objv[6])[0] != 0) {
	    tmp = Tcl_NewStringObj(Tcl_GetString(objv[6]), -1);
	    if (Tcl_GetWideIntFromObj(interp, tmp, &wideVar) != TCL_OK) {
		Tcl_DecrRefCount(tmp);
		return TCL_ERROR;
	    }
	    Tcl_DecrRefCount(tmp);
	    Tcl_UpdateLinkedVar(interp, "wide");
	}
	if (argv[7][0]) {
	    if (Tcl_GetInt(interp, argv[7], &v) != TCL_OK) {
	if (Tcl_GetString(objv[7])[0]) {
	    if (Tcl_GetIntFromObj(interp, objv[7], &v) != TCL_OK) {
		return TCL_ERROR;
	    }
	    charVar = (char) v;
	    Tcl_UpdateLinkedVar(interp, "char");
	}
	if (argv[8][0]) {
	    if (Tcl_GetInt(interp, argv[8], &v) != TCL_OK) {
	if (Tcl_GetString(objv[8])[0]) {
	    if (Tcl_GetIntFromObj(interp, objv[8], &v) != TCL_OK) {
		return TCL_ERROR;
	    }
	    ucharVar = (unsigned char) v;
	    Tcl_UpdateLinkedVar(interp, "uchar");
	}
	if (argv[9][0]) {
	    if (Tcl_GetInt(interp, argv[9], &v) != TCL_OK) {
	if (Tcl_GetString(objv[9])[0]) {
	    if (Tcl_GetIntFromObj(interp, objv[9], &v) != TCL_OK) {
		return TCL_ERROR;
	    }
	    shortVar = (short) v;
	    Tcl_UpdateLinkedVar(interp, "short");
	}
	if (argv[10][0]) {
	    if (Tcl_GetInt(interp, argv[10], &v) != TCL_OK) {
	if (Tcl_GetString(objv[10])[0]) {
	    if (Tcl_GetIntFromObj(interp, objv[10], &v) != TCL_OK) {
		return TCL_ERROR;
	    }
	    ushortVar = (unsigned short) v;
	    Tcl_UpdateLinkedVar(interp, "ushort");
	}
	if (argv[11][0]) {
	    if (Tcl_GetInt(interp, argv[11], &v) != TCL_OK) {
	if (Tcl_GetString(objv[11])[0]) {
	    if (Tcl_GetIntFromObj(interp, objv[11], &v) != TCL_OK) {
		return TCL_ERROR;
	    }
	    uintVar = (unsigned int) v;
	    Tcl_UpdateLinkedVar(interp, "uint");
	}
	if (argv[12][0]) {
	    if (Tcl_GetInt(interp, argv[12], &v) != TCL_OK) {
	if (Tcl_GetString(objv[12])[0]) {
	    if (Tcl_GetIntFromObj(interp, objv[12], &v) != TCL_OK) {
		return TCL_ERROR;
	    }
	    longVar = (long) v;
	    Tcl_UpdateLinkedVar(interp, "long");
	}
	if (argv[13][0]) {
	    if (Tcl_GetInt(interp, argv[13], &v) != TCL_OK) {
	if (Tcl_GetString(objv[13])[0]) {
	    if (Tcl_GetIntFromObj(interp, objv[13], &v) != TCL_OK) {
		return TCL_ERROR;
	    }
	    ulongVar = (unsigned long) v;
	    Tcl_UpdateLinkedVar(interp, "ulong");
	}
	if (argv[14][0]) {
	if (Tcl_GetString(objv[14])[0]) {
	    double d;
	    if (Tcl_GetDouble(interp, argv[14], &d) != TCL_OK) {
	    if (Tcl_GetDoubleFromObj(interp, objv[14], &d) != TCL_OK) {
		return TCL_ERROR;
	    }
	    floatVar = (float) d;
	    Tcl_UpdateLinkedVar(interp, "float");
	}
	if (argv[15][0]) {
	if (Tcl_GetString(objv[15])[0]) {
	    Tcl_WideInt w;
	    tmp = Tcl_NewStringObj(argv[15], -1);
	    tmp = Tcl_NewStringObj(Tcl_GetString(objv[15]), -1);
	    if (Tcl_GetWideIntFromObj(interp, tmp, &w) != TCL_OK) {
		Tcl_DecrRefCount(tmp);
		return TCL_ERROR;
	    }
	    Tcl_DecrRefCount(tmp);
	    uwideVar = (Tcl_WideUInt) w;
	    uwideVar = (Tcl_WideUInt)w;
	    Tcl_UpdateLinkedVar(interp, "uwide");
	}
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[1],
		"\": should be create, delete, get, set, or update", NULL);
	Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
		"\": should be create, delete, get, set, or update", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
3196
3197
3198
3199
3200
3201
3202
3203
3204


3205
3206
3207
3208

3209
3210

3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223


3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235

3236
3237
3238
3239
3240
3241
3242
3661
3662
3663
3664
3665
3666
3667


3668
3669
3670
3671
3672

3673
3674

3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687

3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700

3701
3702
3703
3704
3705
3706
3707
3708







-
-
+
+



-
+

-
+












-
+
+











-
+







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

static int
TestlinkarrayCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,         /* Current interpreter. */
    int objc,                   /* Number of arguments. */
    Tcl_Interp *interp,	 /* Current interpreter. */
    int objc,		   /* Number of arguments. */
    Tcl_Obj *const objv[])      /* Argument objects. */
{
    static const char *LinkOption[] = {
        "update", "remove", "create", NULL
	"update", "remove", "create", NULL
    };
    enum LinkOptionEnum { LINK_UPDATE, LINK_REMOVE, LINK_CREATE };
    enum LinkOptionEnum { LINK_UPDATE, LINK_REMOVE, LINK_CREATE } optionIndex;
    static const char *LinkType[] = {
	"char", "uchar", "short", "ushort", "int", "uint", "long", "ulong",
	"wide", "uwide", "float", "double", "string", "char*", "binary", NULL
    };
    /* all values after TCL_LINK_CHARS_ARRAY are used as arrays (see below) */
    static int LinkTypes[] = {
	TCL_LINK_CHAR, TCL_LINK_UCHAR,
	TCL_LINK_SHORT, TCL_LINK_USHORT, TCL_LINK_INT, TCL_LINK_UINT,
	TCL_LINK_LONG, TCL_LINK_ULONG, TCL_LINK_WIDE_INT, TCL_LINK_WIDE_UINT,
	TCL_LINK_FLOAT, TCL_LINK_DOUBLE, TCL_LINK_STRING, TCL_LINK_CHARS,
	TCL_LINK_BINARY
    };
    int optionIndex, typeIndex, readonly, i, size, length;
    int typeIndex, readonly, size;
    Tcl_Size i, length;
    char *name, *arg;
    Tcl_WideInt addr;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option args");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], LinkOption, "option", 0,
	    &optionIndex) != TCL_OK) {
	return TCL_ERROR;
    }
    switch ((enum LinkOptionEnum) optionIndex) {
    switch (optionIndex) {
    case LINK_UPDATE:
	for (i=2; i<objc; i++) {
	    Tcl_UpdateLinkedVar(interp, Tcl_GetString(objv[i]));
	}
	return TCL_OK;
    case LINK_REMOVE:
	for (i=2; i<objc; i++) {
3262
3263
3264
3265
3266
3267
3268
3269

3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284

3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299


























































































































































3300
3301
3302
3303
3304
3305
3306
3728
3729
3730
3731
3732
3733
3734

3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749

3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926







-
+














-
+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    if (arg[1] != 'r') {
		goto wrongArgs;
	    }
	    readonly = TCL_LINK_READ_ONLY;
	    i++;
	}
	if (Tcl_GetIndexFromObj(interp, objv[i++], LinkType, "type", 0,
 		&typeIndex) != TCL_OK) {
		&typeIndex) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_GetIntFromObj(interp, objv[i++], &size) == TCL_ERROR) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong size value", -1));
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[i++]);

	/*
	 * If no address is given request one in the underlying function
	 */

	if (i < objc) {
	    if (Tcl_GetWideIntFromObj(interp, objv[i], &addr) == TCL_ERROR) {
 		Tcl_SetObjResult(interp, Tcl_NewStringObj(
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"wrong address value", -1));
		return TCL_ERROR;
	    }
	} else {
	    addr = 0;
	}
	return Tcl_LinkArray(interp, name, INT2PTR(addr),
		LinkTypes[typeIndex] | readonly, size);
    }
    return TCL_OK;

  wrongArgs:
    Tcl_WrongNumArgs(interp, 2, objv, "?-readonly? type size name ?address?");
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TestlistrepCmd --
 *
 *      This function is invoked to generate a list object with a specific
 *	internal representation.
 *
 * Results:
 *      A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestlistrepCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,         /* Current interpreter. */
    int objc,                   /* Number of arguments. */
    Tcl_Obj *const objv[])      /* Argument objects. */
{
    /* Subcommands supported by this command */
    static const char *const subcommands[] = {
	"new",
	"describe",
	"config",
	"validate",
	NULL
    };
    enum {
	LISTREP_NEW,
	LISTREP_DESCRIBE,
	LISTREP_CONFIG,
	LISTREP_VALIDATE
    } cmdIndex;
    Tcl_Obj *resultObj = NULL;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "command ?arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(
	    interp, objv[1], subcommands, "command", 0, &cmdIndex)
	!= TCL_OK) {
	return TCL_ERROR;
    }
    switch (cmdIndex) {
    case LISTREP_NEW:
	if (objc < 3 || objc > 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "length ?leadSpace endSpace?");
	    return TCL_ERROR;
	} else {
	    Tcl_WideUInt length;
	    Tcl_WideUInt leadSpace = 0;
	    Tcl_WideUInt endSpace = 0;
	    if (Tcl_GetWideUIntFromObj(interp, objv[2], &length) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (objc > 3) {
		if (Tcl_GetWideUIntFromObj(interp, objv[3], &leadSpace) != TCL_OK) {
		    return TCL_ERROR;
		}
		if (objc > 4) {
		    if (Tcl_GetWideUIntFromObj(interp, objv[4], &endSpace)
			!= TCL_OK) {
			return TCL_ERROR;
		    }
		}
	    }
	    resultObj = TclListTestObj(length, leadSpace, endSpace);
	    if (resultObj == NULL) {
		Tcl_AppendResult(interp, "List capacity exceeded", (char *)NULL);
		return TCL_ERROR;
	    }
	}
	break;

    case LISTREP_DESCRIBE:
#define APPEND_FIELD(targetObj_, structPtr_, fld_)                        \
    do {                                                                  \
	Tcl_ListObjAppendElement(                                         \
	    interp, (targetObj_), Tcl_NewStringObj(#fld_, -1));           \
	Tcl_ListObjAppendElement(                                         \
	    interp, (targetObj_), Tcl_NewWideIntObj((structPtr_)->fld_)); \
    } while (0)
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "object");
	    return TCL_ERROR;
	} else {
	    Tcl_Obj **objs;
	    Tcl_Size nobjs;
	    ListRep listRep;
	    Tcl_Obj *listRepObjs[4];

	    /* Force list representation */
	    if (Tcl_ListObjGetElements(interp, objv[2], &nobjs, &objs) != TCL_OK) {
		return TCL_ERROR;
	    }
	    ListObjGetRep(objv[2], &listRep);
	    listRepObjs[0] = Tcl_NewStringObj("store", -1);
	    listRepObjs[1] = Tcl_NewListObj(12, NULL);
	    Tcl_ListObjAppendElement(interp, listRepObjs[1],
		    Tcl_NewStringObj("memoryAddress", -1));
	    Tcl_ListObjAppendElement(interp, listRepObjs[1],
		    Tcl_ObjPrintf("%p", listRep.storePtr));
	    APPEND_FIELD(listRepObjs[1], listRep.storePtr, firstUsed);
	    APPEND_FIELD(listRepObjs[1], listRep.storePtr, numUsed);
	    APPEND_FIELD(listRepObjs[1], listRep.storePtr, numAllocated);
	    APPEND_FIELD(listRepObjs[1], listRep.storePtr, refCount);
	    APPEND_FIELD(listRepObjs[1], listRep.storePtr, flags);
	    if (listRep.spanPtr) {
		listRepObjs[2] = Tcl_NewStringObj("span", -1);
		listRepObjs[3] = Tcl_NewListObj(8, NULL);
		Tcl_ListObjAppendElement(interp, listRepObjs[3],
			Tcl_NewStringObj("memoryAddress", -1));
		Tcl_ListObjAppendElement(interp, listRepObjs[3],
			Tcl_ObjPrintf("%p", listRep.spanPtr));
		APPEND_FIELD(listRepObjs[3], listRep.spanPtr, spanStart);
		APPEND_FIELD(listRepObjs[3], listRep.spanPtr, spanLength);
		APPEND_FIELD(listRepObjs[3], listRep.spanPtr, refCount);
	    }
	    resultObj = Tcl_NewListObj(listRep.spanPtr ? 4 : 2, listRepObjs);
	}
#undef APPEND_FIELD
	break;

    case LISTREP_CONFIG:
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, "object");
	    return TCL_ERROR;
	}
	resultObj = Tcl_NewListObj(2, NULL);
	Tcl_ListObjAppendElement(
	    NULL, resultObj, Tcl_NewStringObj("LIST_SPAN_THRESHOLD", -1));
	Tcl_ListObjAppendElement(
	    NULL, resultObj, Tcl_NewWideIntObj(LIST_SPAN_THRESHOLD));
	break;

    case LISTREP_VALIDATE:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "object");
	    return TCL_ERROR;
	}
	TclListObjValidate(interp, objv[2]); /* Panics if invalid */
	resultObj = Tcl_NewObj();
	break;
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestlocaleCmd --
 *
 *	This procedure implements the "testlocale" command.  It is used
3383
3384
3385
3386
3387
3388
3389
3390

3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405

3406
3407
3408
3409
3410
3411

3412

3413
3414
3415
3416
3417
3418
3419
4003
4004
4005
4006
4007
4008
4009

4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024

4025
4026
4027
4028
4029
4030
4031
4032

4033
4034
4035
4036
4037
4038
4039
4040







-
+














-
+






+
-
+







{
    Tcl_Free(clientData);
}

/*
 *----------------------------------------------------------------------
 *
 * TestparserObjCmd --
 * TestparserCmd --
 *
 *	This procedure implements the "testparser" command.  It is
 *	used for testing the new Tcl script parser in Tcl 8.1.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestparserObjCmd(
TestparserCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    const char *script;
    Tcl_Size dummy;
    int length, dummy;
    int length;
    Tcl_Parse parse;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "script length");
	return TCL_ERROR;
    }
    script = Tcl_GetStringFromObj(objv[1], &dummy);
3439
3440
3441
3442
3443
3444
3445
3446

3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461

3462
3463
3464
3465
3466
3467

3468

3469
3470
3471
3472
3473
3474
3475
4060
4061
4062
4063
4064
4065
4066

4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081

4082
4083
4084
4085
4086
4087
4088
4089

4090
4091
4092
4093
4094
4095
4096
4097







-
+














-
+






+
-
+







    Tcl_FreeParse(&parse);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestexprparserObjCmd --
 * TestexprparserCmd --
 *
 *	This procedure implements the "testexprparser" command.  It is
 *	used for testing the new Tcl expression parser in Tcl 8.1.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestexprparserObjCmd(
TestexprparserCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    const char *script;
    Tcl_Size dummy;
    int length, dummy;
    int length;
    Tcl_Parse parse;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "expr length");
	return TCL_ERROR;
    }
    script = Tcl_GetStringFromObj(objv[1], &dummy);
3523
3524
3525
3526
3527
3528
3529
3530

3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543

3544
3545
3546
3547
3548
3549
3550
4145
4146
4147
4148
4149
4150
4151

4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164

4165
4166
4167
4168
4169
4170
4171
4172







-
+












-
+







    Tcl_Interp *interp,		/* Interpreter whose result is to be set to
				 * the contents of a parse structure. */
    Tcl_Parse *parsePtr)	/* Parse structure to print out. */
{
    Tcl_Obj *objPtr;
    const char *typeString;
    Tcl_Token *tokenPtr;
    int i;
    Tcl_Size i;

    objPtr = Tcl_GetObjResult(interp);
    if (parsePtr->commentSize > 0) {
	Tcl_ListObjAppendElement(NULL, objPtr,
		Tcl_NewStringObj(parsePtr->commentStart,
			parsePtr->commentSize));
    } else {
	Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewStringObj("-", 1));
    }
    Tcl_ListObjAppendElement(NULL, objPtr,
	    Tcl_NewStringObj(parsePtr->commandStart, parsePtr->commandSize));
    Tcl_ListObjAppendElement(NULL, objPtr,
	    Tcl_NewIntObj(parsePtr->numWords));
	    Tcl_NewWideIntObj(parsePtr->numWords));
    for (i = 0; i < parsePtr->numTokens; i++) {
	tokenPtr = &parsePtr->tokenPtr[i];
	switch (tokenPtr->type) {
	case TCL_TOKEN_EXPAND_WORD:
	    typeString = "expand";
	    break;
	case TCL_TOKEN_WORD:
3576
3577
3578
3579
3580
3581
3582
3583

3584
3585

3586
3587

3588
3589
3590
3591
3592
3593

3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608

3609
3610
3611
3612
3613
3614
3615
4198
4199
4200
4201
4202
4203
4204

4205
4206
4207
4208
4209

4210
4211
4212
4213
4214
4215

4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230

4231
4232
4233
4234
4235
4236
4237
4238







-
+


+

-
+





-
+














-
+







	    break;
	}
	Tcl_ListObjAppendElement(NULL, objPtr,
		Tcl_NewStringObj(typeString, -1));
	Tcl_ListObjAppendElement(NULL, objPtr,
		Tcl_NewStringObj(tokenPtr->start, tokenPtr->size));
	Tcl_ListObjAppendElement(NULL, objPtr,
		Tcl_NewIntObj(tokenPtr->numComponents));
		Tcl_NewWideIntObj(tokenPtr->numComponents));
    }
    Tcl_ListObjAppendElement(NULL, objPtr,
	    parsePtr->commandStart ?
	    Tcl_NewStringObj(parsePtr->commandStart + parsePtr->commandSize,
	    -1));
	    TCL_INDEX_NONE) : Tcl_NewObj());
}

/*
 *----------------------------------------------------------------------
 *
 * TestparsevarObjCmd --
 * TestparsevarCmd --
 *
 *	This procedure implements the "testparsevar" command.  It is
 *	used for testing Tcl_ParseVar.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestparsevarObjCmd(
TestparsevarCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    const char *value, *name, *termPtr;

3627
3628
3629
3630
3631
3632
3633
3634

3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649

3650
3651
3652
3653
3654
3655
3656


3657
3658
3659
3660
3661
3662
3663
4250
4251
4252
4253
4254
4255
4256

4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271

4272
4273
4274
4275
4276
4277
4278

4279
4280
4281
4282
4283
4284
4285
4286
4287







-
+














-
+






-
+
+







    Tcl_AppendElement(interp, termPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestparsevarnameObjCmd --
 * TestparsevarnameCmd --
 *
 *	This procedure implements the "testparsevarname" command.  It is
 *	used for testing the new Tcl script parser in Tcl 8.1.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestparsevarnameObjCmd(
TestparsevarnameCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    const char *script;
    int append, length, dummy;
    int length, append;
    Tcl_Size dummy;
    Tcl_Parse parse;

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "script length append");
	return TCL_ERROR;
    }
    script = Tcl_GetStringFromObj(objv[1], &dummy);
3689
3690
3691
3692
3693
3694
3695
3696

3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712

3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727

3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742

3743
3744
3745
3746
3747
3748
3749

3750
3751

3752

3753
3754
3755
3756

3757
3758

3759

3760
3761
3762
3763
3764
3765
3766

3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783

3784
3785
3786
3787
3788
3789
3790


3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807

3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827

3828
3829
3830
3831
3832
3833
3834
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
4436
4437
4438
4439
4440
4441

4442
4443
4444
4445
4446
4447
4448
4449
4450

4451
4452
4453
4454
4455
4456
4457
4458







-
+















-
+














-
+














-
+







+

-
+

+


-
-
+
-

+
-
+






-
+
















-
+





-
-
+
+
















-
+









-









-
+







    Tcl_FreeParse(&parse);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestpreferstableObjCmd --
 * TestpreferstableCmd --
 *
 *	This procedure implements the "testpreferstable" command.  It is
 *	used for being able to test the "package" command even when the
 *  environment variable TCL_PKG_PREFER_LATEST is set in your environment.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestpreferstableObjCmd(
TestpreferstableCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*objc*/,
    TCL_UNUSED(Tcl_Obj *const *) /*objv*/)
{
    Interp *iPtr = (Interp *) interp;

    iPtr->packagePrefer = PKG_PREFER_STABLE;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestprintObjCmd --
 * TestprintCmd --
 *
 *	This procedure implements the "testprint" command.  It is
 *	used for being able to test the Tcl_ObjPrintf() function.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestprintObjCmd(
TestprintCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    Tcl_WideInt argv1 = 0;
    size_t argv2;
    long argv3;

    if (objc < 2 || objc > 3) {
    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "format wideint");
	return TCL_OK;
    }

    if (objc > 1) {
	Tcl_GetWideIntFromObj(interp, objv[2], &argv1);
    Tcl_GetWideIntFromObj(interp, objv[2], &argv1);
    }
    argv2 = (size_t)argv1;
    argv3 = (long)argv1;
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(Tcl_GetString(objv[1]), argv1, argv2, argv2));
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(Tcl_GetString(objv[1]), argv1, argv2, argv3, argv3));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestregexpObjCmd --
 * TestregexpCmd --
 *
 *	This procedure implements the "testregexp" command. It is used to give
 *	a direct interface for regexp flags. It's identical to
 *	Tcl_RegexpObjCmd except for the -xflags option, and the consequences
 *	thereof (including the REG_EXPECT kludge).
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
TestregexpObjCmd(
TestregexpCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int i, indices, stringLength, match, about;
    size_t ii;
    int indices, match, about;
    Tcl_Size stringLength, i, ii;
    int hasxflags, cflags, eflags;
    Tcl_RegExp regExpr;
    const char *string;
    Tcl_Obj *objPtr;
    Tcl_RegExpInfo info;
    static const char *const options[] = {
	"-indices",	"-nocase",	"-about",	"-expanded",
	"-line",	"-linestop",	"-lineanchor",
	"-xflags",
	"--",		NULL
    };
    enum optionsEnum {
	REGEXP_INDICES, REGEXP_NOCASE,	REGEXP_ABOUT,	REGEXP_EXPANDED,
	REGEXP_MULTI,	REGEXP_NOCROSS,	REGEXP_NEWL,
	REGEXP_XFLAGS,
	REGEXP_LAST
    };
    } index;

    indices = 0;
    about = 0;
    cflags = REG_ADVANCED;
    eflags = 0;
    hasxflags = 0;

    for (i = 1; i < objc; i++) {
	const char *name;
	int index;

	name = Tcl_GetString(objv[i]);
	if (name[0] != '-') {
	    break;
	}
	if (Tcl_GetIndexFromObj(interp, objv[i], options, "switch", TCL_EXACT,
		&index) != TCL_OK) {
	    return TCL_ERROR;
	}
	switch ((enum optionsEnum) index) {
	switch (index) {
	case REGEXP_INDICES:
	    indices = 1;
	    break;
	case REGEXP_NOCASE:
	    cflags |= REG_ICASE;
	    break;
	case REGEXP_ABOUT:
3852
3853
3854
3855
3856
3857
3858
3859

3860
3861
3862
3863
3864
3865
3866
4476
4477
4478
4479
4480
4481
4482

4483
4484
4485
4486
4487
4488
4489
4490







-
+







	case REGEXP_LAST:
	    i++;
	    goto endOfForLoop;
	}
    }

  endOfForLoop:
    if (objc - i < hasxflags + 2 - about) {
    if (objc + about < hasxflags + 2 + i) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"?-switch ...? exp string ?matchVar? ?subMatchVar ...?");
	return TCL_ERROR;
    }
    objc -= i;
    objv += i;

3892
3893
3894
3895
3896
3897
3898
3899

3900
3901
3902
3903

3904
3905
3906
3907
3908


3909
3910
3911
3912

3913
3914
3915
3916
3917
3918
3919
3920
3921
3922

3923
3924
3925
3926

3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943

3944
3945
3946
3947

3948
3949
3950
3951
3952
3953
3954
4516
4517
4518
4519
4520
4521
4522

4523
4524
4525
4526

4527
4528
4529
4530


4531
4532
4533
4534
4535

4536
4537
4538
4539
4540
4541
4542
4543
4544
4545

4546
4547
4548
4549

4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566

4567
4568
4569
4570

4571
4572
4573
4574
4575
4576
4577
4578







-
+



-
+



-
-
+
+



-
+









-
+



-
+
















-
+



-
+







    }
    if (match == 0) {
	/*
	 * Set the interpreter's object result to an integer object w/
	 * value 0.
	 */

	Tcl_SetIntObj(Tcl_GetObjResult(interp), 0);
	Tcl_SetWideIntObj(Tcl_GetObjResult(interp), 0);
	if (objc > 2 && (cflags&REG_EXPECT) && indices) {
	    const char *varName;
	    const char *value;
	    size_t start, end;
	    Tcl_Size start, end;
	    char resinfo[TCL_INTEGER_SPACE * 2];

	    varName = Tcl_GetString(objv[2]);
	    TclRegExpRangeUniChar(regExpr, -1, &start, &end);
	    sprintf(resinfo, "%d %d", (int)start, (int)(end-1));
	    TclRegExpRangeUniChar(regExpr, TCL_INDEX_NONE, &start, &end);
	    snprintf(resinfo, sizeof(resinfo), "%" TCL_Z_MODIFIER "d %" TCL_Z_MODIFIER "d", start, end-1);
	    value = Tcl_SetVar2(interp, varName, NULL, resinfo, 0);
	    if (value == NULL) {
		Tcl_AppendResult(interp, "couldn't set variable \"",
			varName, "\"", NULL);
			varName, "\"", (char *)NULL);
		return TCL_ERROR;
	    }
	} else if (cflags & TCL_REG_CANMATCH) {
	    const char *varName;
	    const char *value;
	    char resinfo[TCL_INTEGER_SPACE * 2];

	    Tcl_RegExpGetInfo(regExpr, &info);
	    varName = Tcl_GetString(objv[2]);
	    sprintf(resinfo, "%d", (int)info.extendStart);
	    snprintf(resinfo, sizeof(resinfo), "%" TCL_Z_MODIFIER "d", info.extendStart);
	    value = Tcl_SetVar2(interp, varName, NULL, resinfo, 0);
	    if (value == NULL) {
		Tcl_AppendResult(interp, "couldn't set variable \"",
			varName, "\"", NULL);
			varName, "\"", (char *)NULL);
		return TCL_ERROR;
	    }
	}
	return TCL_OK;
    }

    /*
     * If additional variable names have been specified, return
     * index information in those variables.
     */

    objc -= 2;
    objv += 2;

    Tcl_RegExpGetInfo(regExpr, &info);
    for (i = 0; i < objc; i++) {
	size_t start, end;
	Tcl_Size start, end;
	Tcl_Obj *newPtr, *varPtr, *valuePtr;

	varPtr = objv[i];
	ii = ((cflags&REG_EXPECT) && i == objc-1) ? TCL_INDEX_NONE : (size_t)i;
	ii = ((cflags&REG_EXPECT) && i == objc-1) ? TCL_INDEX_NONE : i;
	if (indices) {
	    Tcl_Obj *objs[2];

	    if (ii == TCL_INDEX_NONE) {
		TclRegExpRangeUniChar(regExpr, ii, &start, &end);
	    } else if (ii > info.nsubs) {
		start = TCL_INDEX_NONE;
3963
3964
3965
3966
3967
3968
3969
3970
3971


3972
3973
3974
3975
3976
3977
3978

3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995

3996
3997
3998
3999
4000
4001
4002
4587
4588
4589
4590
4591
4592
4593


4594
4595
4596
4597
4598
4599
4600
4601

4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618

4619
4620
4621
4622
4623
4624
4625
4626







-
-
+
+






-
+
















-
+







	     * instead of the first character after the match.
	     */

	    if (end != TCL_INDEX_NONE) {
		end--;
	    }

	    objs[0] = Tcl_NewIntObj(start);
	    objs[1] = Tcl_NewIntObj(end);
	    objs[0] = Tcl_NewWideIntObj(start);
	    objs[1] = Tcl_NewWideIntObj(end);

	    newPtr = Tcl_NewListObj(2, objs);
	} else {
	    if (ii == TCL_INDEX_NONE) {
		TclRegExpRangeUniChar(regExpr, ii, &start, &end);
		newPtr = Tcl_GetRange(objPtr, start, end);
	    } else if (ii > info.nsubs) {
	    } else if (ii > info.nsubs || info.matches[ii].end <= 0) {
		newPtr = Tcl_NewObj();
	    } else {
		newPtr = Tcl_GetRange(objPtr, info.matches[ii].start,
			info.matches[ii].end - 1);
	    }
	}
	valuePtr = Tcl_ObjSetVar2(interp, varPtr, NULL, newPtr, TCL_LEAVE_ERR_MSG);
	if (valuePtr == NULL) {
	    return TCL_ERROR;
	}
    }

    /*
     * Set the interpreter's object result to an integer object w/ value 1.
     */

    Tcl_SetIntObj(Tcl_GetObjResult(interp), 1);
    Tcl_SetWideIntObj(Tcl_GetObjResult(interp), 1);
    return TCL_OK;
}

/*
 *---------------------------------------------------------------------------
 *
 * TestregexpXflags --
4083
4084
4085
4086
4087
4088
4089
4090

4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108

4109
4110
4111
4112
4113
4114
4115
4707
4708
4709
4710
4711
4712
4713

4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731

4732
4733
4734
4735
4736
4737
4738
4739







-
+

















-
+







    *cflagsPtr = cflags;
    *eflagsPtr = eflags;
}

/*
 *----------------------------------------------------------------------
 *
 * TestreturnObjCmd --
 * TestreturnCmd --
 *
 *	This procedure implements the "testreturn" command. It is
 *	used to verify that a
 *		return TCL_RETURN;
 *	has same behavior as
 *		return Tcl_SetReturnOptions(interp, Tcl_NewObj());
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
TestreturnObjCmd(
TestreturnCmd(
    TCL_UNUSED(void *),
    TCL_UNUSED(Tcl_Interp *),
    TCL_UNUSED(int) /*objc*/,
    TCL_UNUSED(Tcl_Obj *const *) /*objv*/)
{
    return TCL_RETURN;
}
4132
4133
4134
4135
4136
4137
4138
4139
4140


4141
4142
4143
4144
4145

4146
4147

4148
4149
4150
4151
4152


4153
4154
4155
4156
4157
4158
4159

4160
4161
4162
4163
4164

4165
4166
4167
4168
4169
4170
4171
4756
4757
4758
4759
4760
4761
4762


4763
4764
4765
4766
4767
4768

4769


4770
4771
4772
4773


4774
4775
4776
4777
4778
4779
4780
4781

4782
4783
4784
4785
4786

4787
4788
4789
4790
4791
4792
4793
4794







-
-
+
+




-
+
-
-
+



-
-
+
+






-
+




-
+







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

static int
TestsetassocdataCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    char *buf, *oldData;
    Tcl_InterpDeleteProc *procPtr;

    if (argc != 3) {
    if (objc != 3) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" data_key data_item\"", NULL);
	Tcl_WrongNumArgs(interp, 1, objv, "data_key data_item");
	return TCL_ERROR;
    }

    buf = (char *)Tcl_Alloc(strlen(argv[2]) + 1);
    strcpy(buf, argv[2]);
    buf = (char *)Tcl_Alloc(strlen(Tcl_GetString(objv[2])) + 1);
    strcpy(buf, Tcl_GetString(objv[2]));

    /*
     * If we previously associated a malloced value with the variable,
     * free it before associating a new value.
     */

    oldData = (char *) Tcl_GetAssocData(interp, argv[1], &procPtr);
    oldData = (char *)Tcl_GetAssocData(interp, Tcl_GetString(objv[1]), &procPtr);
    if ((oldData != NULL) && (procPtr == CleanupTestSetassocdataTests)) {
	Tcl_Free(oldData);
    }

    Tcl_SetAssocData(interp, argv[1], CleanupTestSetassocdataTests,	buf);
    Tcl_SetAssocData(interp, Tcl_GetString(objv[1]), CleanupTestSetassocdataTests, buf);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestsetplatformCmd --
4183
4184
4185
4186
4187
4188
4189
4190
4191


4192
4193

4194
4195
4196
4197
4198

4199
4200

4201
4202
4203
4204
4205


4206
4207

4208
4209
4210
4211

4212
4213
4214
4215





















4216
4217
4218
4219
4220

4221
4222
4223


4224
4225
4226
4227
4228
4229

4230
4231
4232
4233
4234
4235
4236

4237
4238
4239
4240


4241
4242
4243
4244

4245
4246

4247
4248
4249

4250
4251
4252

4253
4254
4255

4256
4257
4258
4259
4260
4261
4262
4806
4807
4808
4809
4810
4811
4812


4813
4814
4815

4816
4817
4818
4819
4820

4821


4822
4823
4824
4825


4826
4827
4828

4829
4830
4831
4832

4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862

4863
4864


4865
4866
4867
4868
4869
4870
4871

4872
4873
4874
4875
4876
4877
4878

4879
4880
4881


4882
4883
4884
4885
4886

4887


4888
4889
4890

4891
4892
4893

4894
4895
4896

4897
4898
4899
4900
4901
4902
4903
4904







-
-
+
+

-
+




-
+
-
-
+



-
-
+
+

-
+



-
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+

-
-
+
+





-
+






-
+


-
-
+
+



-
+
-
-
+


-
+


-
+


-
+







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

static int
TestsetplatformCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    size_t length;
    Tcl_Size length;
    TclPlatformType *platform;

    platform = TclGetPlatform();

    if (argc != 2) {
    if (objc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" platform\"", NULL);
	Tcl_WrongNumArgs(interp, 1, objv, "platform");
	return TCL_ERROR;
    }

    length = strlen(argv[1]);
    if (strncmp(argv[1], "unix", length) == 0) {
    const char *argv1 = Tcl_GetStringFromObj(objv[1], &length);
    if (strncmp(argv1, "unix", length) == 0) {
	*platform = TCL_PLATFORM_UNIX;
    } else if (strncmp(argv[1], "windows", length) == 0) {
    } else if (strncmp(argv1, "windows", length) == 0) {
	*platform = TCL_PLATFORM_WINDOWS;
    } else {
	Tcl_AppendResult(interp, "unsupported platform: should be one of "
		"unix, or windows", NULL);
		"unix, or windows", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

static int
TestSizeCmd(
    TCL_UNUSED(void *),	/* Unused */
    Tcl_Interp* interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const * objv)	/* Parameter vector */
{
    if (objc != 2) {
	goto syntax;
    }
    if (strcmp(Tcl_GetString(objv[1]), "st_mtime") == 0) {
	Tcl_StatBuf *statPtr;
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sizeof(statPtr->st_mtime)));
	return TCL_OK;
    }

syntax:
    Tcl_WrongNumArgs(interp, 1, objv, "st_mtime");
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TeststaticpkgCmd --
 * TeststaticlibraryCmd --
 *
 *	This procedure implements the "teststaticpkg" command.
 *	It is used to test the procedure Tcl_StaticPackage.
 *	This procedure implements the "teststaticlibrary" command.
 *	It is used to test the procedure Tcl_StaticLibrary.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	When the packge given by argv[1] is loaded into an interpeter,
 *	When the package given by objv[1] is loaded into an interpreter,
 *	variable "x" in that interpreter is set to "loaded".
 *
 *----------------------------------------------------------------------
 */

static int
TeststaticpkgCmd(
TeststaticlibraryCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Argument strings. */
{
    int safe, loaded;

    if (argc != 4) {
    if (objc != 4) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"",
		argv[0], " pkgName safe loaded\"", NULL);
	Tcl_WrongNumArgs(interp, 1, objv, "prefix safe loaded");
	return TCL_ERROR;
    }
    if (Tcl_GetInt(interp, argv[2], &safe) != TCL_OK) {
    if (Tcl_GetBooleanFromObj(interp, objv[2], &safe) != TCL_OK) {
	return TCL_ERROR;
    }
    if (Tcl_GetInt(interp, argv[3], &loaded) != TCL_OK) {
    if (Tcl_GetBooleanFromObj(interp, objv[3], &loaded) != TCL_OK) {
	return TCL_ERROR;
    }
    Tcl_StaticPackage((loaded) ? interp : NULL, argv[1],
    Tcl_StaticLibrary((loaded) ? interp : NULL, Tcl_GetString(objv[1]),
	    StaticInitProc, (safe) ? StaticInitProc : NULL);
    return TCL_OK;
}

static int
StaticInitProc(
    Tcl_Interp *interp)		/* Interpreter in which package is supposedly
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
4925
4926
4927
4928
4929
4930
4931


4932
4933
4934
4935
4936
4937


4938
4939

4940
4941

4942
4943
4944
4945

4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995







-
-
+
+




-
-
+
+
-


-
+



-
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







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

static int
TesttranslatefilenameCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    Tcl_DString buffer;
    const char *result;

    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"",
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "path");
		argv[0], " path\"", NULL);
	return TCL_ERROR;
    }
    result = Tcl_TranslateFileName(interp, argv[1], &buffer);
    result = Tcl_TranslateFileName(interp, Tcl_GetString(objv[1]), &buffer);
    if (result == NULL) {
	return TCL_ERROR;
    }
    Tcl_AppendResult(interp, result, NULL);
    Tcl_AppendResult(interp, result, (char *)NULL);
    Tcl_DStringFree(&buffer);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestfstildeexpandCmd --
 *
 *	This procedure implements the "testfstildeexpand" command.
 *	It is used to test the Tcl_FSTildeExpand command. It differs
 *      from the script level "file tildeexpand" tests because of a
 *	slightly different code path.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestfstildeexpandCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    Tcl_DString buffer;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "PATH");
	return TCL_ERROR;
    }
    if (Tcl_FSTildeExpand(interp, Tcl_GetString(objv[1]), &buffer) != TCL_OK) {
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_DStringToObj(&buffer));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestupvarCmd --
 *
 *	This procedure implements the "testupvar" command.  It is used
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
5004
5005
5006
5007
5008
5009
5010


5011
5012
5013
5014
5015

5016


5017
5018
5019
5020


5021
5022
5023

5024
5025
5026

5027
5028

5029
5030

5031
5032
5033


5034
5035
5036
5037
5038
5039
5040
5041
5042







-
-
+
+



-
+
-
-
+



-
-
+
+

-
+


-
+

-
+

-
+


-
-
+
+







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

static int
TestupvarCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    int flags = 0;

    if ((argc != 5) && (argc != 6)) {
    if ((objc != 5) && (objc != 6)) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"",
		argv[0], " level name ?name2? dest global\"", NULL);
	Tcl_WrongNumArgs(interp, 1, objv, "level name ?name2? dest global");
	return TCL_ERROR;
    }

    if (argc == 5) {
	if (strcmp(argv[4], "global") == 0) {
    if (objc == 5) {
	if (strcmp(Tcl_GetString(objv[4]), "global") == 0) {
	    flags = TCL_GLOBAL_ONLY;
	} else if (strcmp(argv[4], "namespace") == 0) {
	} else if (strcmp(Tcl_GetString(objv[4]), "namespace") == 0) {
	    flags = TCL_NAMESPACE_ONLY;
	}
	return Tcl_UpVar2(interp, argv[1], argv[2], NULL, argv[3], flags);
	return Tcl_UpVar2(interp, Tcl_GetString(objv[1]), Tcl_GetString(objv[2]), NULL, Tcl_GetString(objv[3]), flags);
    } else {
	if (strcmp(argv[5], "global") == 0) {
	if (strcmp(Tcl_GetString(objv[5]), "global") == 0) {
	    flags = TCL_GLOBAL_ONLY;
	} else if (strcmp(argv[5], "namespace") == 0) {
	} else if (strcmp(Tcl_GetString(objv[5]), "namespace") == 0) {
	    flags = TCL_NAMESPACE_ONLY;
	}
	return Tcl_UpVar2(interp, argv[1], argv[2],
		(argv[3][0] == 0) ? NULL : argv[3], argv[4],
	return Tcl_UpVar2(interp, Tcl_GetString(objv[1]), Tcl_GetString(objv[2]),
		(Tcl_GetString(objv[3])[0] == 0) ? NULL : Tcl_GetString(objv[3]), Tcl_GetString(objv[4]),
		flags);
    }
}

/*
 *----------------------------------------------------------------------
 *
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
5055
5056
5057
5058
5059
5060
5061


5062
5063
5064


5065
5066
5067
5068

5069
5070

5071
5072
5073

5074
5075
5076

5077
5078
5079

5080
5081
5082

5083
5084
5085


5086
5087
5088
5089
5090
5091
5092
5093
5094







-
-
+
+

-
-
+
+


-
+

-
+


-
+


-
+


-
+


-
+


-
-
+
+







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

static int
TestseterrorcodeCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    if (argc > 6) {
	Tcl_AppendResult(interp, "too many args", NULL);
    if (objc > 6) {
	Tcl_AppendResult(interp, "too many args", (char *)NULL);
	return TCL_ERROR;
    }
    switch (argc) {
    switch (objc) {
    case 1:
	Tcl_SetErrorCode(interp, "NONE", NULL);
	Tcl_SetErrorCode(interp, "NONE", (char *)NULL);
	break;
    case 2:
	Tcl_SetErrorCode(interp, argv[1], NULL);
	Tcl_SetErrorCode(interp, Tcl_GetString(objv[1]), (char *)NULL);
	break;
    case 3:
	Tcl_SetErrorCode(interp, argv[1], argv[2], NULL);
	Tcl_SetErrorCode(interp, Tcl_GetString(objv[1]), Tcl_GetString(objv[2]), (char *)NULL);
	break;
    case 4:
	Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], NULL);
	Tcl_SetErrorCode(interp, Tcl_GetString(objv[1]), Tcl_GetString(objv[2]), Tcl_GetString(objv[3]), (char *)NULL);
	break;
    case 5:
	Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], argv[4], NULL);
	Tcl_SetErrorCode(interp, Tcl_GetString(objv[1]), Tcl_GetString(objv[2]), Tcl_GetString(objv[3]), Tcl_GetString(objv[4]), (char *)NULL);
	break;
    case 6:
	Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], argv[4],
		argv[5], NULL);
	Tcl_SetErrorCode(interp, Tcl_GetString(objv[1]), Tcl_GetString(objv[2]), Tcl_GetString(objv[3]), Tcl_GetString(objv[4]),
		Tcl_GetString(objv[5]), (char *)NULL);
    }
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
4456
4457
4458
4459
4460
4461
4462
4463
4464


4465
4466
4467
4468
4469
4470

4471
4472

4473
4474
4475
4476


4477
4478

4479
4480
4481
4482

4483
4484
4485
4486
4487
4488

4489
4490
4491

4492
4493
4494
4495
4496
4497

4498
4499
4500
4501
4502

4503
4504

4505
4506
4507
4508
4509
4510
4511
5135
5136
5137
5138
5139
5140
5141


5142
5143
5144
5145
5146
5147
5148

5149


5150
5151
5152


5153
5154


5155
5156
5157
5158

5159
5160
5161
5162
5163
5164

5165
5166
5167

5168
5169
5170
5171
5172
5173

5174
5175
5176
5177
5178

5179
5180

5181
5182
5183
5184
5185
5186
5187
5188







-
-
+
+





-
+
-
-
+


-
-
+
+
-
-
+



-
+





-
+


-
+





-
+




-
+

-
+







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

static int
TestfeventCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    static Tcl_Interp *interp2 = NULL;
    int code;
    Tcl_Channel chan;

    if (argc < 2) {
    if (objc < 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" option ?arg ...?", NULL);
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "cmd") == 0) {
	if (argc != 3) {
    if (strcmp(Tcl_GetString(objv[1]), "cmd") == 0) {
	if (objc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " cmd script", NULL);
	    Tcl_WrongNumArgs(interp, 2, objv, "script");
	    return TCL_ERROR;
	}
	if (interp2 != NULL) {
	    code = Tcl_EvalEx(interp2, argv[2], -1, TCL_EVAL_GLOBAL);
	    code = Tcl_EvalEx(interp2, Tcl_GetString(objv[2]), TCL_INDEX_NONE, TCL_EVAL_GLOBAL);
	    Tcl_SetObjResult(interp, Tcl_GetObjResult(interp2));
	    return code;
	} else {
	    Tcl_AppendResult(interp,
		    "called \"testfevent code\" before \"testfevent create\"",
		    NULL);
		    (char *)NULL);
	    return TCL_ERROR;
	}
    } else if (strcmp(argv[1], "create") == 0) {
    } else if (strcmp(Tcl_GetString(objv[1]), "create") == 0) {
	if (interp2 != NULL) {
	    Tcl_DeleteInterp(interp2);
	}
	interp2 = Tcl_CreateInterp();
	return Tcl_Init(interp2);
    } else if (strcmp(argv[1], "delete") == 0) {
    } else if (strcmp(Tcl_GetString(objv[1]), "delete") == 0) {
	if (interp2 != NULL) {
	    Tcl_DeleteInterp(interp2);
	}
	interp2 = NULL;
    } else if (strcmp(argv[1], "share") == 0) {
    } else if (strcmp(Tcl_GetString(objv[1]), "share") == 0) {
	if (interp2 != NULL) {
	    chan = Tcl_GetChannel(interp, argv[2], NULL);
	    chan = Tcl_GetChannel(interp, Tcl_GetString(objv[2]), NULL);
	    if (chan == (Tcl_Channel) NULL) {
		return TCL_ERROR;
	    }
	    Tcl_RegisterChannel(interp2, chan);
	}
    }

4528
4529
4530
4531
4532
4533
4534
4535
4536


4537
4538
4539
4540
4541
4542
4543
4544
4545



4546
4547
4548
4549
4550
4551
4552
4553
4554
4555


4556
4557

4558
4559

4560
4561

4562
4563
4564
4565
4566
4567

4568
4569
4570
4571
4572

4573
4574
4575
4576
4577


4578
4579
4580
4581
4582

4583
4584
4585

4586
4587

4588
4589

4590
4591

4592
4593

4594
4595

4596
4597
4598
4599
4600
4601
4602
4603
4604

4605
4606
4607
4608

4609
4610
4611
4612
4613
4614
4615
5205
5206
5207
5208
5209
5210
5211


5212
5213
5214
5215
5216
5217
5218
5219



5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230


5231
5232
5233

5234
5235
5236
5237
5238

5239
5240
5241
5242
5243
5244

5245
5246
5247
5248
5249

5250
5251
5252
5253


5254
5255
5256
5257
5258
5259

5260
5261
5262

5263
5264

5265
5266

5267
5268

5269
5270

5271
5272

5273
5274
5275
5276
5277
5278
5279
5280
5281

5282
5283
5284
5285

5286
5287
5288
5289
5290
5291
5292
5293







-
-
+
+






-
-
-
+
+
+








-
-
+
+

-
+


+

-
+





-
+




-
+



-
-
+
+




-
+


-
+

-
+

-
+

-
+

-
+

-
+








-
+



-
+







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

static int
TestpanicCmd(
    TCL_UNUSED(void *),
    TCL_UNUSED(Tcl_Interp *),
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    /*
     *  Put the arguments into a var args structure
     *  Append all of the arguments together separated by spaces
     */

    char *argString = Tcl_Merge(argc-1, argv+1);
    Tcl_Panic("%s", argString);
    Tcl_Free(argString);
    Tcl_Obj *list = Tcl_NewListObj(objc-1, objv+1);
    Tcl_Panic("%s", Tcl_GetString(list));
    Tcl_DecrRefCount(list);

    return TCL_OK;
}

static int
TestfileCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    Tcl_Obj *const argv[])	/* The argument objects. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* The argument objects. */
{
    int force, i, j, result;
    int force, i, result;
    Tcl_Obj *error = NULL;
    const char *subcmd;
    int j;

    if (argc < 3) {
    if (objc < 3) {
	return TCL_ERROR;
    }

    force = 0;
    i = 2;
    if (strcmp(Tcl_GetString(argv[2]), "-force") == 0) {
    if (strcmp(Tcl_GetString(objv[2]), "-force") == 0) {
	force = 1;
	i = 3;
    }

    if (argc - i > 2) {
    if (objc - i > 2) {
	return TCL_ERROR;
    }

    for (j = i; j < argc; j++) {
	if (Tcl_FSGetNormalizedPath(interp, argv[j]) == NULL) {
    for (j = i; j < objc; j++) {
	if (Tcl_FSGetNormalizedPath(interp, objv[j]) == NULL) {
	    return TCL_ERROR;
	}
    }

    subcmd = Tcl_GetString(argv[1]);
    subcmd = Tcl_GetString(objv[1]);

    if (strcmp(subcmd, "mv") == 0) {
	result = TclpObjRenameFile(argv[i], argv[i + 1]);
	result = TclpObjRenameFile(objv[i], objv[i + 1]);
    } else if (strcmp(subcmd, "cp") == 0) {
	result = TclpObjCopyFile(argv[i], argv[i + 1]);
	result = TclpObjCopyFile(objv[i], objv[i + 1]);
    } else if (strcmp(subcmd, "rm") == 0) {
	result = TclpObjDeleteFile(argv[i]);
	result = TclpObjDeleteFile(objv[i]);
    } else if (strcmp(subcmd, "mkdir") == 0) {
	result = TclpObjCreateDirectory(argv[i]);
	result = TclpObjCreateDirectory(objv[i]);
    } else if (strcmp(subcmd, "cpdir") == 0) {
	result = TclpObjCopyDirectory(argv[i], argv[i + 1], &error);
	result = TclpObjCopyDirectory(objv[i], objv[i + 1], &error);
    } else if (strcmp(subcmd, "rmdir") == 0) {
	result = TclpObjRemoveDirectory(argv[i], force, &error);
	result = TclpObjRemoveDirectory(objv[i], force, &error);
    } else {
	result = TCL_ERROR;
	goto end;
    }

    if (result != TCL_OK) {
	if (error != NULL) {
	    if (Tcl_GetString(error)[0] != '\0') {
		Tcl_AppendResult(interp, Tcl_GetString(error), " ", NULL);
		Tcl_AppendResult(interp, Tcl_GetString(error), " ", (char *)NULL);
	    }
	    Tcl_DecrRefCount(error);
	}
	Tcl_AppendResult(interp, Tcl_ErrnoId(), NULL);
	Tcl_AppendResult(interp, Tcl_ErrnoId(), (char *)NULL);
    }

  end:
    return result;
}

/*
4684
4685
4686
4687
4688
4689
4690
4691

4692
4693
4694
4695

4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707

4708
4709
4710
4711
4712
4713
4714
5362
5363
5364
5365
5366
5367
5368

5369
5370
5371
5372

5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384

5385
5386
5387
5388
5389
5390
5391
5392







-
+



-
+











-
+







    Tcl_GetVariableFullName(interp, variable, Tcl_GetObjResult(interp));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * GetTimesObjCmd --
 * GetTimesCmd --
 *
 *	This procedure implements the "gettimes" command.  It is used for
 *	computing the time needed for various basic operations such as reading
 *	variables, allocating memory, sprintf, converting variables, etc.
 *	variables, allocating memory, snprintf, converting variables, etc.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Allocates and frees memory, sets a variable "a" in the interpreter.
 *
 *----------------------------------------------------------------------
 */

static int
GetTimesObjCmd(
GetTimesCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* The current interpreter. */
    TCL_UNUSED(int) /*cobjc*/,
    TCL_UNUSED(Tcl_Obj *const *) /*cobjv*/)
{
    Interp *iPtr = (Interp *) interp;
    int i, n;
4769
4770
4771
4772
4773
4774
4775
4776

4777
4778
4779
4780
4781
4782
4783
4784

4785
4786
4787
4788
4789
4790
4791
5447
5448
5449
5450
5451
5452
5453

5454
5455
5456
5457
5458
5459
5460
5461

5462
5463
5464
5465
5466
5467
5468
5469







-
+







-
+







    }
    Tcl_GetTime(&stop);
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
    fprintf(stderr, "   %.3f usec per Tcl_DecrRefCount\n", timePer/5000);
    Tcl_Free(objv);

    /* TclGetString 100000 times */
    fprintf(stderr, "TclGetStringFromObj of \"12345\" 100000 times\n");
    fprintf(stderr, "Tcl_GetStringFromObj of \"12345\" 100000 times\n");
    objPtr = Tcl_NewStringObj("12345", -1);
    Tcl_GetTime(&start);
    for (i = 0;  i < 100000;  i++) {
	(void) TclGetString(objPtr);
    }
    Tcl_GetTime(&stop);
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
    fprintf(stderr, "   %.3f usec per TclGetStringFromObj of \"12345\"\n",
    fprintf(stderr, "   %.3f usec per Tcl_GetStringFromObj of \"12345\"\n",
	    timePer/100000);

    /* Tcl_GetIntFromObj 100000 times */
    fprintf(stderr, "Tcl_GetIntFromObj of \"12345\" 100000 times\n");
    Tcl_GetTime(&start);
    for (i = 0;  i < 100000;  i++) {
	if (Tcl_GetIntFromObj(interp, objPtr, &n) != TCL_OK) {
4807
4808
4809
4810
4811
4812
4813
4814
4815


4816
4817
4818

4819
4820
4821
4822

4823
4824
4825
4826
4827
4828
4829
5485
5486
5487
5488
5489
5490
5491


5492
5493
5494
5495

5496
5497
5498
5499

5500
5501
5502
5503
5504
5505
5506
5507







-
-
+
+


-
+



-
+







	}
    }
    Tcl_GetTime(&stop);
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
    fprintf(stderr, "   %.3f usec per Tcl_GetInt of \"12345\"\n",
	    timePer/100000);

    /* sprintf 100000 times */
    fprintf(stderr, "sprintf of 12345 100000 times\n");
    /* snprintf 100000 times */
    fprintf(stderr, "snprintf of 12345 100000 times\n");
    Tcl_GetTime(&start);
    for (i = 0;  i < 100000;  i++) {
	sprintf(newString, "%d", 12345);
	snprintf(newString, sizeof(newString), "%d", 12345);
    }
    Tcl_GetTime(&stop);
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
    fprintf(stderr, "   %.3f usec per sprintf of 12345\n",
    fprintf(stderr, "   %.3f usec per snprintf of 12345\n",
	    timePer/100000);

    /* hashtable lookup 100000 times */
    fprintf(stderr, "hashtable lookup of \"gettimes\" 100000 times\n");
    Tcl_GetTime(&start);
    for (i = 0;  i < 100000;  i++) {
	(void) Tcl_FindHashEntry(&iPtr->globalNsPtr->cmdTable, "gettimes");
4918
4919
4920
4921
4922
4923
4924
4925

4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938

4939
4940
4941
4942
4943
4944

4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959

4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978

4979
4980
4981
4982
4983
4984
4985
5596
5597
5598
5599
5600
5601
5602

5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615

5616
5617
5618
5619
5620
5621

5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636

5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655

5656
5657
5658
5659
5660
5661
5662
5663







-
+












-
+





-
+














-
+


















-
+







{
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TeststringbytesObjCmd --
 * TeststringbytesCmd --
 *	Returns bytearray value of the bytes in argument string rep
 *
 * Results:
 *	Returns the TCL_OK result code.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TeststringbytesObjCmd(
TeststringbytesCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    int n;
    Tcl_Size n;
    const unsigned char *p;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "value");
	return TCL_ERROR;
    }
    p = (const unsigned char *)Tcl_GetStringFromObj(objv[1], &n);
    Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(p, n));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestpurebytesobjObjCmd --
 * TestpurebytesobjCmd --
 *
 *	This object-based procedure constructs a pure bytes object
 *	without type and with internal representation containing NULL's.
 *
 *	If no argument supplied it returns empty object with tclEmptyStringRep,
 *	otherwise it returns this as pure bytes object with bytes value equal
 *	string.
 *
 * Results:
 *	Returns the TCL_OK result code.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestpurebytesobjObjCmd(
TestpurebytesobjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    Tcl_Obj *objPtr;

5003
5004
5005
5006
5007
5008
5009
5010

5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025

5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040

5041
5042


5043
5044
5045
5046







5047
5048
5049
5050
5051
5052
5053
5054

5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069

5070
5071
5072
5073
5074




5075




5076
5077
5078
5079
5080
5081
5082
5083

5084
5085
5086





5087

5088
5089
5090
5091
5092
5093
5094
5681
5682
5683
5684
5685
5686
5687

5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702

5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719


5720
5721


5722

5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736

5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751

5752
5753
5754
5755
5756
5757
5758
5759
5760
5761

5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772

5773
5774
5775
5776
5777
5778
5779
5780
5781

5782
5783
5784
5785
5786
5787
5788
5789







-
+














-
+















+
-
-
+
+
-
-

-
+
+
+
+
+
+
+







-
+














-
+





+
+
+
+
-
+
+
+
+







-
+



+
+
+
+
+
-
+







    Tcl_SetObjResult(interp, objPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestsetbytearraylengthObjCmd --
 * TestsetbytearraylengthCmd --
 *
 *	Testing command 'testsetbytearraylength` used to test the public
 *	interface routine Tcl_SetByteArrayLength().
 *
 * Results:
 *	Returns the TCL_OK result code.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestsetbytearraylengthObjCmd(
TestsetbytearraylengthCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    int n;
    Tcl_Obj *obj = NULL;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "value length");
	return TCL_ERROR;
    }
    if (TCL_OK != Tcl_GetIntFromObj(interp, objv[2], &n)) {
	return TCL_ERROR;
    }
    obj = objv[1];
    if (Tcl_IsShared(objv[1])) {
	obj = Tcl_DuplicateObj(objv[1]);
    if (Tcl_IsShared(obj)) {
	obj = Tcl_DuplicateObj(obj);
    } else {
	obj = objv[1];
    }
    Tcl_SetByteArrayLength(obj, n);
    if (Tcl_SetByteArrayLength(obj, n) == NULL) {
	if (obj != objv[1]) {
	    Tcl_DecrRefCount(obj);
	}
	Tcl_AppendResult(interp, "expected bytes", (char *)NULL);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, obj);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestbytestringObjCmd --
 * TestbytestringCmd --
 *
 *	This object-based procedure constructs a string which can
 *	possibly contain invalid UTF-8 bytes.
 *
 * Results:
 *	Returns the TCL_OK result code.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestbytestringObjCmd(
TestbytestringCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    struct {
#if !defined(TCL_NO_DEPRECATED)
	int n; /* On purpose, not Tcl_Size, in order to demonstrate what happens */
#else
    size_t n = 0;
	Tcl_Size n;
#endif
	int m; /* This variable should not be overwritten */
    } x = {0, 1};
    const char *p;

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

    p = (const char *)TclGetBytesFromObj(interp, objv[1], &n);
    p = (const char *)Tcl_GetBytesFromObj(interp, objv[1], &x.n);
    if (p == NULL) {
	return TCL_ERROR;
    }

    if (x.m != 1) {
	Tcl_AppendResult(interp, "Tcl_GetBytesFromObj() overwrites variable", (char *)NULL);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewStringObj(p, n));
    Tcl_SetObjResult(interp, Tcl_NewStringObj(p, x.n));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestsetCmd --
5105
5106
5107
5108
5109
5110
5111
5112
5113


5114
5115
5116
5117
5118
5119
5120



5121
5122
5123
5124
5125
5126
5127
5128



5129
5130
5131
5132
5133
5134
5135
5136

5137
5138
5139
5140
5141
5142
5143
5144
5145


5146
5147
5148
5149
5150
5151
5152



5153
5154
5155
5156
5157
5158
5159
5160



5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212

5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5800
5801
5802
5803
5804
5805
5806


5807
5808
5809
5810
5811
5812



5813
5814
5815
5816
5817
5818
5819
5820



5821
5822
5823
5824
5825
5826
5827
5828
5829


5830
5831
5832
5833
5834
5835
5836
5837


5838
5839
5840
5841
5842
5843



5844
5845
5846
5847
5848
5849
5850
5851



5852
5853
5854
5855
5856
5857
5858
5859
5860














































5861
5862
5863



















































































5864
5865
5866
5867
5868
5869
5870







-
-
+
+




-
-
-
+
+
+





-
-
-
+
+
+






-
-
+







-
-
+
+




-
-
-
+
+
+





-
-
-
+
+
+






-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







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

static int
TestsetCmd(
    void *data,		/* Additional flags for Get/SetVar2. */
    Tcl_Interp *interp,/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    int flags = PTR2INT(data);
    const char *value;

    if (argc == 2) {
	Tcl_AppendResult(interp, "before get", NULL);
	value = Tcl_GetVar2(interp, argv[1], NULL, flags);
    if (objc == 2) {
	Tcl_AppendResult(interp, "before get", (char *)NULL);
	value = Tcl_GetVar2(interp, Tcl_GetString(objv[1]), NULL, flags);
	if (value == NULL) {
	    return TCL_ERROR;
	}
	Tcl_AppendElement(interp, value);
	return TCL_OK;
    } else if (argc == 3) {
	Tcl_AppendResult(interp, "before set", NULL);
	value = Tcl_SetVar2(interp, argv[1], NULL, argv[2], flags);
    } else if (objc == 3) {
	Tcl_AppendResult(interp, "before set", (char *)NULL);
	value = Tcl_SetVar2(interp, Tcl_GetString(objv[1]), NULL, Tcl_GetString(objv[2]), flags);
	if (value == NULL) {
	    return TCL_ERROR;
	}
	Tcl_AppendElement(interp, value);
	return TCL_OK;
    } else {
	Tcl_AppendResult(interp, "wrong # args: should be \"",
		argv[0], " varName ?newValue?\"", NULL);
	Tcl_WrongNumArgs(interp, 1, objv, "varName ?newValue?");
	return TCL_ERROR;
    }
}
static int
Testset2Cmd(
    void *data,		/* Additional flags for Get/SetVar2. */
    Tcl_Interp *interp,/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Argument strings. */
{
    int flags = PTR2INT(data);
    const char *value;

    if (argc == 3) {
	Tcl_AppendResult(interp, "before get", NULL);
	value = Tcl_GetVar2(interp, argv[1], argv[2], flags);
    if (objc == 3) {
	Tcl_AppendResult(interp, "before get", (char *)NULL);
	value = Tcl_GetVar2(interp, Tcl_GetString(objv[1]), Tcl_GetString(objv[2]), flags);
	if (value == NULL) {
	    return TCL_ERROR;
	}
	Tcl_AppendElement(interp, value);
	return TCL_OK;
    } else if (argc == 4) {
	Tcl_AppendResult(interp, "before set", NULL);
	value = Tcl_SetVar2(interp, argv[1], argv[2], argv[3], flags);
    } else if (objc == 4) {
	Tcl_AppendResult(interp, "before set", (char *)NULL);
	value = Tcl_SetVar2(interp, Tcl_GetString(objv[1]), Tcl_GetString(objv[2]), Tcl_GetString(objv[3]), flags);
	if (value == NULL) {
	    return TCL_ERROR;
	}
	Tcl_AppendElement(interp, value);
	return TCL_OK;
    } else {
	Tcl_AppendResult(interp, "wrong # args: should be \"",
		argv[0], " varName elemName ?newValue?\"", NULL);
	return TCL_ERROR;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TestsaveresultCmd --
 *
 *	Implements the "testsaveresult" cmd that is used when testing the
 *	Tcl_SaveResult, Tcl_RestoreResult, and Tcl_DiscardResult interfaces.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestsaveresultCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    int discard, result, index;
    Tcl_SavedResult state;
    Tcl_Obj *objPtr;
    static const char *const optionStrings[] = {
	"append", "dynamic", "free", "object", "small", NULL
    };
    enum options {
	RESULT_APPEND, RESULT_DYNAMIC, RESULT_FREE, RESULT_OBJECT, RESULT_SMALL
    };

    /*
     * Parse arguments
     */

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "type script discard");
	Tcl_WrongNumArgs(interp, 1, objv, "varName elemName ?newValue??");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }
    if (Tcl_GetBooleanFromObj(interp, objv[3], &discard) != TCL_OK) {
	return TCL_ERROR;
    }

    freeCount = 0;
    objPtr = NULL;		/* Lint. */
    switch ((enum options) index) {
    case RESULT_SMALL:
	Tcl_AppendResult(interp, "small result", NULL);
	break;
    case RESULT_APPEND:
	Tcl_AppendResult(interp, "append result", NULL);
	break;
    case RESULT_FREE: {
	char *buf = (char *)Tcl_Alloc(200);

	strcpy(buf, "free result");
	Tcl_SetResult(interp, buf, TCL_DYNAMIC);
	break;
    }
    case RESULT_DYNAMIC:
	Tcl_SetResult(interp, (char *)"dynamic result", TestsaveresultFree);
	break;
    case RESULT_OBJECT:
	objPtr = Tcl_NewStringObj("object result", -1);
	Tcl_SetObjResult(interp, objPtr);
	break;
    }

    Tcl_SaveResult(interp, &state);

    if (((enum options) index) == RESULT_OBJECT) {
	result = Tcl_EvalObjEx(interp, objv[2], 0);
    } else {
	result = Tcl_EvalEx(interp, Tcl_GetString(objv[2]), -1, 0);
    }

    if (discard) {
	Tcl_DiscardResult(&state);
    } else {
	Tcl_RestoreResult(interp, &state);
	result = TCL_OK;
    }

    switch ((enum options) index) {
    case RESULT_DYNAMIC:
	Tcl_AppendElement(interp, freeCount ? "freed" : "leak");
	break;
    case RESULT_OBJECT:
	Tcl_AppendElement(interp, Tcl_GetObjResult(interp) == objPtr
		? "same" : "different");
	break;
    default:
	break;
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TestsaveresultFree --
 *
 *	Special purpose freeProc used by TestsaveresultCmd.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Increments the freeCount.
 *
 *----------------------------------------------------------------------
 */

static void
TestsaveresultFree(
    TCL_UNUSED(void *))
{
    freeCount++;
}

/*
 *----------------------------------------------------------------------
 *
 * TestmainthreadCmd  --
 *
5314
5315
5316
5317
5318
5319
5320
5321
5322


5323
5324

5325
5326
5327
5328
5329
5330

5331
5332
5333
5334
5335
5336
5337
5880
5881
5882
5883
5884
5885
5886


5887
5888
5889

5890
5891
5892
5893
5894
5895

5896
5897
5898
5899
5900
5901
5902
5903







-
-
+
+

-
+





-
+







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

static int
TestmainthreadCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,/* Current interpreter. */
    int argc,			/* Number of arguments. */
    TCL_UNUSED(const char **) /*argv*/)
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)
{
    if (argc == 1) {
    if (objc == 1) {
	Tcl_Obj *idObj = Tcl_NewWideIntObj((Tcl_WideInt)(size_t)Tcl_GetCurrentThread());

	Tcl_SetObjResult(interp, idObj);
	return TCL_OK;
    } else {
	Tcl_AppendResult(interp, "wrong # args", NULL);
	Tcl_WrongNumArgs(interp, 1, objv, "");
	return TCL_ERROR;
    }
}

/*
 *----------------------------------------------------------------------
 *
5375
5376
5377
5378
5379
5380
5381
5382
5383


5384
5385
5386
5387
5388
5389
5390
5941
5942
5943
5944
5945
5946
5947


5948
5949
5950
5951
5952
5953
5954
5955
5956







-
-
+
+







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

static int
TestsetmainloopCmd(
    TCL_UNUSED(void *),
    TCL_UNUSED(Tcl_Interp *),
    TCL_UNUSED(int) /*argc*/,
    TCL_UNUSED(const char **) /*argv*/)
    TCL_UNUSED(int) /*objc*/,
    TCL_UNUSED(Tcl_Obj *const *) /*objv*/)
{
    exitMainLoop = 0;
    Tcl_SetMainLoop(MainLoop);
    return TCL_OK;
}

/*
5404
5405
5406
5407
5408
5409
5410
5411
5412


5413
5414
5415
5416
5417
5418
5419
5970
5971
5972
5973
5974
5975
5976


5977
5978
5979
5980
5981
5982
5983
5984
5985







-
-
+
+







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

static int
TestexitmainloopCmd(
    TCL_UNUSED(void *),
    TCL_UNUSED(Tcl_Interp *),
    TCL_UNUSED(int) /*argc*/,
    TCL_UNUSED(const char **) /*argv*/)
    TCL_UNUSED(int) /*objc*/,
    TCL_UNUSED(Tcl_Obj *const *) /*objv*/)
{
    exitMainLoop = 1;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
5432
5433
5434
5435
5436
5437
5438
5439
5440


5441
5442
5443
5444
5445
5446
5447
5448
5449

5450
5451

5452
5453
5454

5455
5456

5457
5458
5459

5460
5461
5462
5463
5464

5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477

5478
5479
5480
5481
5482
5483
5484
5485
5486

5487
5488
5489
5490
5491

5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502

5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515

5516
5517
5518
5519
5520
5521
5522
5998
5999
6000
6001
6002
6003
6004


6005
6006
6007
6008
6009
6010
6011
6012
6013
6014

6015
6016

6017
6018
6019

6020


6021
6022
6023

6024

6025
6026
6027

6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040

6041
6042
6043
6044
6045
6046
6047
6048
6049

6050
6051
6052
6053
6054

6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065

6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078

6079
6080
6081
6082
6083
6084
6085
6086







-
-
+
+








-
+

-
+


-
+
-
-
+


-
+
-



-
+












-
+








-
+




-
+










-
+












-
+







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

static int
TestChannelCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Interpreter for result. */
    int argc,			/* Count of additional args. */
    const char **argv)		/* Additional arg strings. */
    int objc,			/* Count of additional args. */
    Tcl_Obj *const *objv)	/* Additional args. */
{
    const char *cmdName;	/* Sub command. */
    Tcl_HashTable *hTblPtr;	/* Hash table of channels. */
    Tcl_HashSearch hSearch;	/* Search variable. */
    Tcl_HashEntry *hPtr;	/* Search variable. */
    Channel *chanPtr;		/* The actual channel. */
    ChannelState *statePtr;	/* state info for channel */
    Tcl_Channel chan;		/* The opaque type. */
    size_t len;			/* Length of subcommand string. */
    Tcl_Size len;			/* Length of subcommand string. */
    int IOQueued;		/* How much IO is queued inside channel? */
    char buf[TCL_INTEGER_SPACE];/* For sprintf. */
    char buf[TCL_INTEGER_SPACE];/* For snprintf. */
    int mode;			/* rw mode of the channel */

    if (argc < 2) {
    if (objc < 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" subcommand ?additional args..?\"", NULL);
	Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?additional args..?");
	return TCL_ERROR;
    }
    cmdName = argv[1];
    cmdName = Tcl_GetStringFromObj(objv[1], &len);
    len = strlen(cmdName);

    chanPtr = NULL;

    if (argc > 2) {
    if (objc > 2) {
	if ((cmdName[0] == 's') && (strncmp(cmdName, "splice", len) == 0)) {
	    /* For splice access the pool of detached channels.
	     * Locate channel, remove from the list.
	     */

	    TestChannel **nextPtrPtr, *curPtr;

	    chan = (Tcl_Channel) NULL;
	    for (nextPtrPtr = &firstDetached, curPtr = firstDetached;
		 curPtr != NULL;
		 nextPtrPtr = &(curPtr->nextPtr), curPtr = curPtr->nextPtr) {

		if (strcmp(argv[2], Tcl_GetChannelName(curPtr->chan)) == 0) {
		if (strcmp(Tcl_GetString(objv[2]), Tcl_GetChannelName(curPtr->chan)) == 0) {
		    *nextPtrPtr = curPtr->nextPtr;
		    curPtr->nextPtr = NULL;
		    chan = curPtr->chan;
		    Tcl_Free(curPtr);
		    break;
		}
	    }
	} else {
	    chan = Tcl_GetChannel(interp, argv[2], &mode);
	    chan = Tcl_GetChannel(interp, Tcl_GetString(objv[2]), &mode);
	}
	if (chan == (Tcl_Channel) NULL) {
	    return TCL_ERROR;
	}
	chanPtr		= (Channel *) chan;
	chanPtr		= (Channel *)chan;
	statePtr	= chanPtr->state;
	chanPtr		= statePtr->topChanPtr;
	chan		= (Tcl_Channel) chanPtr;
    } else {
	statePtr	= NULL;
	chan		= NULL;
    }

    if ((cmdName[0] == 's') && (strncmp(cmdName, "setchannelerror", len) == 0)) {

	Tcl_Obj *msg = Tcl_NewStringObj(argv[3],-1);
	Tcl_Obj *msg = objv[3];

	Tcl_IncrRefCount(msg);
	Tcl_SetChannelError(chan, msg);
	Tcl_DecrRefCount(msg);

	Tcl_GetChannelError(chan, &msg);
	Tcl_SetObjResult(interp, msg);
	Tcl_DecrRefCount(msg);
	return TCL_OK;
    }
    if ((cmdName[0] == 's') && (strncmp(cmdName, "setchannelerrorinterp", len) == 0)) {

	Tcl_Obj *msg = Tcl_NewStringObj(argv[3],-1);
	Tcl_Obj *msg = objv[3];

	Tcl_IncrRefCount(msg);
	Tcl_SetChannelErrorInterp(interp, msg);
	Tcl_DecrRefCount(msg);

	Tcl_GetChannelErrorInterp(interp, &msg);
	Tcl_SetObjResult(interp, msg);
5530
5531
5532
5533
5534
5535
5536
5537

5538
5539

5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561


5562
5563
5564
5565
5566
5567
5568
5569
5570
5571


5572
5573
5574
5575

5576
5577
5578
5579
5580
5581
5582
6094
6095
6096
6097
6098
6099
6100

6101


6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122


6123
6124

6125
6126
6127
6128
6129
6130
6131


6132
6133

6134
6135

6136
6137
6138
6139
6140
6141
6142
6143







-
+
-
-
+




















-
-
+
+
-







-
-
+
+
-


-
+







     * checking that the command is truly cut'able, no mutexes for
     * thread-safety). Its complementary command is "splice", see below.
     */

    if ((cmdName[0] == 'c') && (strncmp(cmdName, "cut", len) == 0)) {
	TestChannel *det;

	if (argc != 3) {
	if (objc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " cut channelName\"", NULL);
	    Tcl_WrongNumArgs(interp, 2, objv, "channel");
	    return TCL_ERROR;
	}

	Tcl_RegisterChannel(NULL, chan); /* prevent closing */
	Tcl_UnregisterChannel(interp, chan);

	Tcl_CutChannel(chan);

	/* Remember the channel in the pool of detached channels */

	det = (TestChannel *)Tcl_Alloc(sizeof(TestChannel));
	det->chan     = chan;
	det->nextPtr  = firstDetached;
	firstDetached = det;

	return TCL_OK;
    }

    if ((cmdName[0] == 'c') &&
	    (strncmp(cmdName, "clearchannelhandlers", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "channel");
		    " clearchannelhandlers channelName\"", NULL);
	    return TCL_ERROR;
	}
	Tcl_ClearChannelHandlers(chan);
	return TCL_OK;
    }

    if ((cmdName[0] == 'i') && (strncmp(cmdName, "info", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "channel");
		    " info channelName\"", NULL);
	    return TCL_ERROR;
	}
	Tcl_AppendElement(interp, argv[2]);
	Tcl_AppendElement(interp, Tcl_GetString(objv[2]));
	Tcl_AppendElement(interp, Tcl_ChannelName(chanPtr->typePtr));
	if (statePtr->flags & TCL_READABLE) {
	    Tcl_AppendElement(interp, "read");
	} else {
	    Tcl_AppendElement(interp, "");
	}
	if (statePtr->flags & TCL_WRITABLE) {
5656
5657
5658
5659
5660
5661
5662
5663
5664


5665
5666
5667
5668
5669

5670
5671
5672
5673
5674
5675


5676
5677
5678
5679
5680

5681
5682
5683
5684
5685
5686


5687
5688
5689
5690
5691

5692
5693
5694
5695
5696
5697


5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713





































5714
5715
5716


5717
5718
5719
5720
5721

5722
5723
5724
5725
5726
5727


5728
5729
5730

5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750


5751
5752
5753
5754
5755
5756

5757
5758
5759
5760
5761
5762
5763


5764
5765
5766
5767
5768

5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780

5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791


5792
5793
5794
5795
5796

5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809


5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823


5824
5825
5826

5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837

5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851

5852
5853

5854
5855
5856
5857
5858



5859
5860
5861
5862

5863
5864
5865
5866
5867
5868
5869
5870
5871

5872
5873

5874
5875
5876
5877
5878
5879
5880
5881

5882
5883
5884
5885
5886
5887
5888
6217
6218
6219
6220
6221
6222
6223


6224
6225
6226
6227
6228
6229

6230
6231
6232
6233
6234


6235
6236
6237
6238
6239
6240

6241
6242
6243
6244
6245


6246
6247
6248
6249
6250
6251

6252
6253
6254
6255
6256


6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312


6313
6314
6315
6316
6317
6318

6319
6320
6321
6322
6323


6324
6325
6326
6327

6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346


6347
6348
6349
6350
6351
6352
6353

6354
6355
6356
6357
6358
6359


6360
6361
6362
6363
6364
6365

6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377

6378
6379
6380
6381
6382
6383
6384
6385
6386
6387


6388
6389
6390
6391
6392
6393

6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405


6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419


6420
6421
6422
6423

6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434

6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448

6449


6450
6451
6452



6453
6454
6455
6456
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







-
-
+
+




-
+




-
-
+
+




-
+




-
-
+
+




-
+




-
-
+
+
















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+




-
+




-
-
+
+


-
+


















-
-
+
+





-
+





-
-
+
+




-
+











-
+









-
-
+
+




-
+











-
-
+
+












-
-
+
+


-
+










-
+













-
+
-
-
+


-
-
-
+
+
+



-
+
-







-
+
-
-
+







-
+







	Tcl_AppendElement(interp, buf);

	return TCL_OK;
    }

    if ((cmdName[0] == 'i') &&
	    (strncmp(cmdName, "inputbuffered", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	if (objc != 3) {
	    Tcl_AppendResult(interp, "channel name required", (char *)NULL);
	    return TCL_ERROR;
	}
	IOQueued = Tcl_InputBuffered(chan);
	TclFormatInt(buf, IOQueued);
	Tcl_AppendResult(interp, buf, NULL);
	Tcl_AppendResult(interp, buf, (char *)NULL);
	return TCL_OK;
    }

    if ((cmdName[0] == 'i') && (strncmp(cmdName, "isshared", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	if (objc != 3) {
	    Tcl_AppendResult(interp, "channel name required", (char *)NULL);
	    return TCL_ERROR;
	}

	TclFormatInt(buf, Tcl_IsChannelShared(chan));
	Tcl_AppendResult(interp, buf, NULL);
	Tcl_AppendResult(interp, buf, (char *)NULL);
	return TCL_OK;
    }

    if ((cmdName[0] == 'i') && (strncmp(cmdName, "isstandard", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	if (objc != 3) {
	    Tcl_AppendResult(interp, "channel name required", (char *)NULL);
	    return TCL_ERROR;
	}

	TclFormatInt(buf, Tcl_IsStandardChannel(chan));
	Tcl_AppendResult(interp, buf, NULL);
	Tcl_AppendResult(interp, buf, (char *)NULL);
	return TCL_OK;
    }

    if ((cmdName[0] == 'm') && (strncmp(cmdName, "mode", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	if (objc != 3) {
	    Tcl_AppendResult(interp, "channel name required", (char *)NULL);
	    return TCL_ERROR;
	}

	if (statePtr->flags & TCL_READABLE) {
	    Tcl_AppendElement(interp, "read");
	} else {
	    Tcl_AppendElement(interp, "");
	}
	if (statePtr->flags & TCL_WRITABLE) {
	    Tcl_AppendElement(interp, "write");
	} else {
	    Tcl_AppendElement(interp, "");
	}
	return TCL_OK;
    }

    if ((cmdName[0] == 'm') && (strncmp(cmdName, "maxmode", len) == 0)) {
	if (objc != 3) {
	    Tcl_AppendResult(interp, "channel name required", (char *)NULL);
	    return TCL_ERROR;
	}

	if (statePtr->maxPerms & TCL_READABLE) {
	    Tcl_AppendElement(interp, "read");
	} else {
	    Tcl_AppendElement(interp, "");
	}
	if (statePtr->maxPerms & TCL_WRITABLE) {
	    Tcl_AppendElement(interp, "write");
	} else {
	    Tcl_AppendElement(interp, "");
	}
	return TCL_OK;
    }

    if ((cmdName[0] == 'm') && (strncmp(cmdName, "mremove-rd", len) == 0)) {
	if (objc != 3) {
	    Tcl_AppendResult(interp, "channel name required", (char *)NULL);
	    return TCL_ERROR;
	}

	return Tcl_RemoveChannelMode(interp, chan, TCL_READABLE);
    }

    if ((cmdName[0] == 'm') && (strncmp(cmdName, "mremove-wr", len) == 0)) {
	if (objc != 3) {
	    Tcl_AppendResult(interp, "channel name required", (char *)NULL);
	    return TCL_ERROR;
	}

	return Tcl_RemoveChannelMode(interp, chan, TCL_WRITABLE);
    }

    if ((cmdName[0] == 'm') && (strncmp(cmdName, "mthread", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	if (objc != 3) {
	    Tcl_AppendResult(interp, "channel name required", (char *)NULL);
	    return TCL_ERROR;
	}

	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
		(Tcl_WideInt) (size_t) Tcl_GetChannelThread(chan)));
		(Tcl_WideInt)(size_t)Tcl_GetChannelThread(chan)));
	return TCL_OK;
    }

    if ((cmdName[0] == 'n') && (strncmp(cmdName, "name", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	if (objc != 3) {
	    Tcl_AppendResult(interp, "channel name required", (char *)NULL);
	    return TCL_ERROR;
	}
	Tcl_AppendResult(interp, statePtr->channelName, NULL);
	Tcl_AppendResult(interp, statePtr->channelName, (char *)NULL);
	return TCL_OK;
    }

    if ((cmdName[0] == 'o') && (strncmp(cmdName, "open", len) == 0)) {
	hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL);
	if (hTblPtr == NULL) {
	    return TCL_OK;
	}
	for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
	     hPtr != NULL;
	     hPtr = Tcl_NextHashEntry(&hSearch)) {
	    Tcl_AppendElement(interp, (char *)Tcl_GetHashKey(hTblPtr, hPtr));
	}
	return TCL_OK;
    }

    if ((cmdName[0] == 'o') &&
	    (strncmp(cmdName, "outputbuffered", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	if (objc != 3) {
	    Tcl_AppendResult(interp, "channel name required", (char *)NULL);
	    return TCL_ERROR;
	}

	IOQueued = Tcl_OutputBuffered(chan);
	TclFormatInt(buf, IOQueued);
	Tcl_AppendResult(interp, buf, NULL);
	Tcl_AppendResult(interp, buf, (char *)NULL);
	return TCL_OK;
    }

    if ((cmdName[0] == 'q') &&
	    (strncmp(cmdName, "queuedcr", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	if (objc != 3) {
	    Tcl_AppendResult(interp, "channel name required", (char *)NULL);
	    return TCL_ERROR;
	}

	Tcl_AppendResult(interp,
		(statePtr->flags & INPUT_SAW_CR) ? "1" : "0", NULL);
		(statePtr->flags & INPUT_SAW_CR) ? "1" : "0", (char *)NULL);
	return TCL_OK;
    }

    if ((cmdName[0] == 'r') && (strncmp(cmdName, "readable", len) == 0)) {
	hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL);
	if (hTblPtr == NULL) {
	    return TCL_OK;
	}
	for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
	     hPtr != NULL;
	     hPtr = Tcl_NextHashEntry(&hSearch)) {
	    chanPtr  = (Channel *) Tcl_GetHashValue(hPtr);
	    chanPtr  = (Channel *)Tcl_GetHashValue(hPtr);
	    statePtr = chanPtr->state;
	    if (statePtr->flags & TCL_READABLE) {
		Tcl_AppendElement(interp, (char *)Tcl_GetHashKey(hTblPtr, hPtr));
	    }
	}
	return TCL_OK;
    }

    if ((cmdName[0] == 'r') && (strncmp(cmdName, "refcount", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	if (objc != 3) {
	    Tcl_AppendResult(interp, "channel name required", (char *)NULL);
	    return TCL_ERROR;
	}

	TclFormatInt(buf, statePtr->refCount);
	Tcl_AppendResult(interp, buf, NULL);
	Tcl_AppendResult(interp, buf, (char *)NULL);
	return TCL_OK;
    }

    /*
     * "splice" is actually more a simplified attach facility as provided by
     * the Thread package. Without the safeguards of a regular command (no
     * checking that the command is truly cut'able, no mutexes for
     * thread-safety). Its complementary command is "cut", see above.
     */

    if ((cmdName[0] == 's') && (strncmp(cmdName, "splice", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	if (objc != 3) {
	    Tcl_AppendResult(interp, "channel name required", (char *)NULL);
	    return TCL_ERROR;
	}

	Tcl_SpliceChannel(chan);

	Tcl_RegisterChannel(interp, chan);
	Tcl_UnregisterChannel(NULL, chan);

	return TCL_OK;
    }

    if ((cmdName[0] == 't') && (strncmp(cmdName, "type", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	if (objc != 3) {
	    Tcl_AppendResult(interp, "channel name required", (char *)NULL);
	    return TCL_ERROR;
	}
	Tcl_AppendResult(interp, Tcl_ChannelName(chanPtr->typePtr), NULL);
	Tcl_AppendResult(interp, Tcl_ChannelName(chanPtr->typePtr), (char *)NULL);
	return TCL_OK;
    }

    if ((cmdName[0] == 'w') && (strncmp(cmdName, "writable", len) == 0)) {
	hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL);
	if (hTblPtr == NULL) {
	    return TCL_OK;
	}
	for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
		hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) {
	    chanPtr = (Channel *) Tcl_GetHashValue(hPtr);
	    chanPtr = (Channel *)Tcl_GetHashValue(hPtr);
	    statePtr = chanPtr->state;
	    if (statePtr->flags & TCL_WRITABLE) {
		Tcl_AppendElement(interp, (char *)Tcl_GetHashKey(hTblPtr, hPtr));
	    }
	}
	return TCL_OK;
    }

    if ((cmdName[0] == 't') && (strncmp(cmdName, "transform", len) == 0)) {
	/*
	 * Syntax: transform channel -command command
	 */

	if (argc != 5) {
	if (objc != 5) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " transform channelId -command cmd\"", NULL);
	    Tcl_WrongNumArgs(interp, 2, objv, "channel -command cmd");
	    return TCL_ERROR;
	}
	if (strcmp(argv[3], "-command") != 0) {
	    Tcl_AppendResult(interp, "bad argument \"", argv[3],
		    "\": should be \"-command\"", NULL);
	if (strcmp(Tcl_GetString(objv[3]), "-command") != 0) {
	    Tcl_AppendResult(interp, "bad argument \"", Tcl_GetString(objv[3]),
		    "\": should be \"-command\"", (char *)NULL);
	    return TCL_ERROR;
	}

	return TclChannelTransform(interp, chan,
	return TclChannelTransform(interp, chan, objv[4]);
		Tcl_NewStringObj(argv[4], -1));
    }

    if ((cmdName[0] == 'u') && (strncmp(cmdName, "unstack", len) == 0)) {
	/*
	 * Syntax: unstack channel
	 */

	if (argc != 3) {
	if (objc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " unstack channel\"", NULL);
	    Tcl_WrongNumArgs(interp, 2, objv, "channel");
	    return TCL_ERROR;
	}
	return Tcl_UnstackChannel(interp, chan);
    }

    Tcl_AppendResult(interp, "bad option \"", cmdName, "\": should be "
	    "cut, clearchannelhandlers, info, isshared, mode, open, "
	    "readable, splice, writable, transform, unstack", NULL);
	    "readable, splice, writable, transform, unstack", (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TestChannelEventCmd --
5899
5900
5901
5902
5903
5904
5905
5906
5907


5908
5909
5910
5911
5912
5913
5914


5915
5916

5917
5918

5919
5920
5921

5922
5923
5924
5925
5926
5927

5928
5929
5930

5931
5932

5933
5934
5935

5936
5937

5938
5939

5940
5941
5942
5943


5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954

5955
5956
5957
5958
5959
5960
5961
5962
5963
5964

5965
5966

5967
5968
5969

5970
5971
5972
5973
5974


5975
5976
5977
5978
5979
5980
5981
5982
5983
5984


5985
5986
5987
5988
5989
5990
5991
6494
6495
6496
6497
6498
6499
6500


6501
6502
6503
6504
6505
6506
6507
6508

6509
6510
6511

6512


6513
6514
6515

6516
6517
6518
6519
6520
6521

6522

6523

6524


6525
6526
6527

6528
6529

6530
6531

6532
6533
6534


6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546

6547
6548
6549
6550
6551
6552
6553
6554
6555
6556

6557


6558
6559
6560

6561
6562
6563
6564


6565
6566
6567
6568
6569
6570
6571
6572
6573
6574


6575
6576
6577
6578
6579
6580
6581
6582
6583







-
-
+
+






-
+
+

-
+
-
-
+


-
+





-
+
-

-
+
-
-
+


-
+

-
+

-
+


-
-
+
+










-
+









-
+
-
-
+


-
+



-
-
+
+








-
-
+
+







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

static int
TestChannelEventCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    Tcl_Obj *resultListPtr;
    Channel *chanPtr;
    ChannelState *statePtr;	/* state info for channel */
    EventScriptRecord *esPtr, *prevEsPtr, *nextEsPtr;
    const char *cmd;
    int index, i, mask, len;
    int index, i, mask;
    Tcl_Size len;

    if ((argc < 3) || (argc > 5)) {
    if ((objc < 3) || (objc > 5)) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" channelName cmd ?arg1? ?arg2?\"", NULL);
	Tcl_WrongNumArgs(interp, 1, objv, "channel cmd ?arg1? ?arg2?");
	return TCL_ERROR;
    }
    chanPtr = (Channel *) Tcl_GetChannel(interp, argv[1], NULL);
    chanPtr = (Channel *)Tcl_GetChannel(interp, Tcl_GetString(objv[1]), NULL);
    if (chanPtr == NULL) {
	return TCL_ERROR;
    }
    statePtr = chanPtr->state;

    cmd = argv[2];
    cmd = Tcl_GetStringFromObj(objv[2], &len);
    len = strlen(cmd);
    if ((cmd[0] == 'a') && (strncmp(cmd, "add", len) == 0)) {
	if (argc != 5) {
	if (objc != 5) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " channelName add eventSpec script\"", NULL);
	    Tcl_WrongNumArgs(interp, 1, objv, "channel add eventSpec script");
	    return TCL_ERROR;
	}
	if (strcmp(argv[3], "readable") == 0) {
	if (strcmp(Tcl_GetString(objv[3]), "readable") == 0) {
	    mask = TCL_READABLE;
	} else if (strcmp(argv[3], "writable") == 0) {
	} else if (strcmp(Tcl_GetString(objv[3]), "writable") == 0) {
	    mask = TCL_WRITABLE;
	} else if (strcmp(argv[3], "none") == 0) {
	} else if (strcmp(Tcl_GetString(objv[3]), "none") == 0) {
	    mask = 0;
	} else {
	    Tcl_AppendResult(interp, "bad event name \"", argv[3],
		    "\": must be readable, writable, or none", NULL);
	    Tcl_AppendResult(interp, "bad event name \"", Tcl_GetString(objv[3]),
		    "\": must be readable, writable, or none", (char *)NULL);
	    return TCL_ERROR;
	}

	esPtr = (EventScriptRecord *)Tcl_Alloc(sizeof(EventScriptRecord));
	esPtr->nextPtr = statePtr->scriptRecordPtr;
	statePtr->scriptRecordPtr = esPtr;

	esPtr->chanPtr = chanPtr;
	esPtr->interp = interp;
	esPtr->mask = mask;
	esPtr->scriptPtr = Tcl_NewStringObj(argv[4], -1);
	esPtr->scriptPtr = objv[4];
	Tcl_IncrRefCount(esPtr->scriptPtr);

	Tcl_CreateChannelHandler((Tcl_Channel) chanPtr, mask,
		TclChannelEventScriptInvoker, esPtr);

	return TCL_OK;
    }

    if ((cmd[0] == 'd') && (strncmp(cmd, "delete", len) == 0)) {
	if (argc != 4) {
	if (objc != 4) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " channelName delete index\"", NULL);
	    Tcl_WrongNumArgs(interp, 1, objv, "channel delete index");
	    return TCL_ERROR;
	}
	if (Tcl_GetInt(interp, argv[3], &index) == TCL_ERROR) {
	if (Tcl_GetIntFromObj(interp, objv[3], &index) == TCL_ERROR) {
	    return TCL_ERROR;
	}
	if (index < 0) {
	    Tcl_AppendResult(interp, "bad event index: ", argv[3],
		    ": must be nonnegative", NULL);
	    Tcl_AppendResult(interp, "bad event index: ", Tcl_GetString(objv[3]),
		    ": must be nonnegative", (char *)NULL);
	    return TCL_ERROR;
	}
	for (i = 0, esPtr = statePtr->scriptRecordPtr;
	     (i < index) && (esPtr != NULL);
	     i++, esPtr = esPtr->nextPtr) {
	    /* Empty loop body. */
	}
	if (esPtr == NULL) {
	    Tcl_AppendResult(interp, "bad event index ", argv[3],
		    ": out of range", NULL);
	    Tcl_AppendResult(interp, "bad event index ", Tcl_GetString(objv[3]),
		    ": out of range", (char *)NULL);
	    return TCL_ERROR;
	}
	if (esPtr == statePtr->scriptRecordPtr) {
	    statePtr->scriptRecordPtr = esPtr->nextPtr;
	} else {
	    for (prevEsPtr = statePtr->scriptRecordPtr;
		 (prevEsPtr != NULL) &&
6003
6004
6005
6006
6007
6008
6009
6010

6011
6012

6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033

6034
6035

6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052

6053
6054

6055
6056
6057

6058
6059
6060
6061
6062


6063
6064
6065
6066
6067
6068
6069
6070
6071
6072


6073
6074
6075
6076

6077
6078

6079
6080

6081
6082
6083
6084


6085
6086
6087
6088
6089
6090
6091
6092
6093

6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113




6114
6115
6116
6117
6118
6119


6120
6121
6122

6123
6124

6125
6126

6127
6128
6129

6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140









6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157























6158
6159
6160
6161

6162
6163
6164
6165
6166
6167
6168
6595
6596
6597
6598
6599
6600
6601

6602


6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623

6624


6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641

6642


6643
6644
6645

6646
6647
6648
6649


6650
6651
6652
6653
6654
6655
6656
6657
6658
6659


6660
6661
6662
6663
6664

6665
6666

6667
6668

6669
6670
6671


6672
6673
6674
6675
6676
6677
6678
6679
6680
6681

6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710


6711
6712
6713
6714

6715
6716

6717


6718
6719
6720

6721

6722
6723








6724
6725
6726
6727
6728
6729
6730
6731
6732

















6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758

6759
6760
6761
6762
6763
6764
6765
6766







-
+
-
-
+




















-
+
-
-
+
















-
+
-
-
+


-
+



-
-
+
+








-
-
+
+



-
+

-
+

-
+


-
-
+
+








-
+




















+
+
+
+




-
-
+
+


-
+

-
+
-
-
+


-
+
-


-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+







	Tcl_DecrRefCount(esPtr->scriptPtr);
	Tcl_Free(esPtr);

	return TCL_OK;
    }

    if ((cmd[0] == 'l') && (strncmp(cmd, "list", len) == 0)) {
	if (argc != 3) {
	if (objc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " channelName list\"", NULL);
	    Tcl_WrongNumArgs(interp, 1, objv, "channel list");
	    return TCL_ERROR;
	}
	resultListPtr = Tcl_GetObjResult(interp);
	for (esPtr = statePtr->scriptRecordPtr;
	     esPtr != NULL;
	     esPtr = esPtr->nextPtr) {
	    if (esPtr->mask) {
		Tcl_ListObjAppendElement(interp, resultListPtr, Tcl_NewStringObj(
		    (esPtr->mask == TCL_READABLE) ? "readable" : "writable", -1));
	    } else {
		Tcl_ListObjAppendElement(interp, resultListPtr,
			Tcl_NewStringObj("none", -1));
	    }
	    Tcl_ListObjAppendElement(interp, resultListPtr, esPtr->scriptPtr);
	}
	Tcl_SetObjResult(interp, resultListPtr);
	return TCL_OK;
    }

    if ((cmd[0] == 'r') && (strncmp(cmd, "removeall", len) == 0)) {
	if (argc != 3) {
	if (objc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " channelName removeall\"", NULL);
	    Tcl_WrongNumArgs(interp, 1, objv, "channel removeall");
	    return TCL_ERROR;
	}
	for (esPtr = statePtr->scriptRecordPtr;
	     esPtr != NULL;
	     esPtr = nextEsPtr) {
	    nextEsPtr = esPtr->nextPtr;
	    Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr,
		    TclChannelEventScriptInvoker, esPtr);
	    Tcl_DecrRefCount(esPtr->scriptPtr);
	    Tcl_Free(esPtr);
	}
	statePtr->scriptRecordPtr = NULL;
	return TCL_OK;
    }

    if	((cmd[0] == 's') && (strncmp(cmd, "set", len) == 0)) {
	if (argc != 5) {
	if (objc != 5) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " channelName delete index event\"", NULL);
	    Tcl_WrongNumArgs(interp, 1, objv, "channel delete index event");
	    return TCL_ERROR;
	}
	if (Tcl_GetInt(interp, argv[3], &index) == TCL_ERROR) {
	if (Tcl_GetIntFromObj(interp, objv[3], &index) == TCL_ERROR) {
	    return TCL_ERROR;
	}
	if (index < 0) {
	    Tcl_AppendResult(interp, "bad event index: ", argv[3],
		    ": must be nonnegative", NULL);
	    Tcl_AppendResult(interp, "bad event index: ", Tcl_GetString(objv[3]),
		    ": must be nonnegative", (char *)NULL);
	    return TCL_ERROR;
	}
	for (i = 0, esPtr = statePtr->scriptRecordPtr;
	     (i < index) && (esPtr != NULL);
	     i++, esPtr = esPtr->nextPtr) {
	    /* Empty loop body. */
	}
	if (esPtr == NULL) {
	    Tcl_AppendResult(interp, "bad event index ", argv[3],
		    ": out of range", NULL);
	    Tcl_AppendResult(interp, "bad event index ", Tcl_GetString(objv[3]),
		    ": out of range", (char *)NULL);
	    return TCL_ERROR;
	}

	if (strcmp(argv[4], "readable") == 0) {
	if (strcmp(Tcl_GetString(objv[4]), "readable") == 0) {
	    mask = TCL_READABLE;
	} else if (strcmp(argv[4], "writable") == 0) {
	} else if (strcmp(Tcl_GetString(objv[4]), "writable") == 0) {
	    mask = TCL_WRITABLE;
	} else if (strcmp(argv[4], "none") == 0) {
	} else if (strcmp(Tcl_GetString(objv[4]), "none") == 0) {
	    mask = 0;
	} else {
	    Tcl_AppendResult(interp, "bad event name \"", argv[4],
		    "\": must be readable, writable, or none", NULL);
	    Tcl_AppendResult(interp, "bad event name \"", Tcl_GetString(objv[4]),
		    "\": must be readable, writable, or none", (char *)NULL);
	    return TCL_ERROR;
	}
	esPtr->mask = mask;
	Tcl_CreateChannelHandler((Tcl_Channel) chanPtr, mask,
		TclChannelEventScriptInvoker, esPtr);
	return TCL_OK;
    }
    Tcl_AppendResult(interp, "bad command ", cmd, ", must be one of "
	    "add, delete, list, set, or removeall", NULL);
	    "add, delete, list, set, or removeall", (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TestSocketCmd --
 *
 *	Implements the Tcl "testsocket" debugging command and its
 *	subcommands. This is part of the testing environment.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

#define TCP_ASYNC_TEST_MODE	(1<<8)	/* Async testing activated.  Do not
					 * automatically continue connection
					 * process. */

static int
TestSocketCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Interpreter for result. */
    int argc,			/* Count of additional args. */
    const char **argv)		/* Additional arg strings. */
    int objc,			/* Count of additional args. */
    Tcl_Obj *const *objv)	/* Additional args. */
{
    const char *cmdName;	/* Sub command. */
    size_t len;			/* Length of subcommand string. */
    Tcl_Size len;			/* Length of subcommand string. */

    if (argc < 2) {
    if (objc < 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" subcommand ?additional args..?\"", NULL);
	Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?additional args..?");
	return TCL_ERROR;
    }
    cmdName = argv[1];
    cmdName = Tcl_GetStringFromObj(objv[1], &len);
    len = strlen(cmdName);

    if ((cmdName[0] == 't') && (strncmp(cmdName, "testflags", len) == 0)) {
        Tcl_Channel hChannel;
        int modePtr;
        TcpState *statePtr;
        /* Set test value in the socket driver
         */
        /* Check for argument "channel name"
         */
        if (argc < 4) {
	Tcl_Channel hChannel;
	int modePtr;
	int testMode;
	TcpState *statePtr;
	/* Set test value in the socket driver
	 */
	/* Check for argument "channel name"
	 */
	if (objc < 4) {
            Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    " testflags channel flags\"", NULL);
            return TCL_ERROR;
        }
        hChannel = Tcl_GetChannel(interp, argv[2], &modePtr);
        if ( NULL == hChannel ) {
            Tcl_AppendResult(interp, "unknown channel:", argv[2], NULL);
            return TCL_ERROR;
        }
        statePtr = (TcpState *)Tcl_GetChannelInstanceData(hChannel);
        if ( NULL == statePtr) {
            Tcl_AppendResult(interp, "No channel instance data:", argv[2],
                    NULL);
            return TCL_ERROR;
        }
        statePtr->testFlags = atoi(argv[3]);
        return TCL_OK;
	    Tcl_WrongNumArgs(interp, 2, objv, "channel flags");
	    return TCL_ERROR;
	}
	hChannel = Tcl_GetChannel(interp, Tcl_GetString(objv[2]), &modePtr);
	if ( NULL == hChannel ) {
	    Tcl_AppendResult(interp, "unknown channel:", Tcl_GetString(objv[2]), (char *)NULL);
	    return TCL_ERROR;
	}
	statePtr = (TcpState *)Tcl_GetChannelInstanceData(hChannel);
	if ( NULL == statePtr) {
	    Tcl_AppendResult(interp, "No channel instance data:", Tcl_GetString(objv[2]),
		    (char *)NULL);
	    return TCL_ERROR;
	}
	if (Tcl_GetBooleanFromObj(interp, objv[3], &testMode) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (testMode) {
	    statePtr->flags |= TCP_ASYNC_TEST_MODE;
	} else {
	    statePtr->flags &= ~TCP_ASYNC_TEST_MODE;
	}
	return TCL_OK;
    }

    Tcl_AppendResult(interp, "bad option \"", cmdName, "\": should be "
	    "testflags", NULL);
	    "testflags", (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TestServiceModeCmd --
6182
6183
6184
6185
6186
6187
6188
6189
6190


6191
6192
6193

6194
6195
6196


6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207









6208
6209

6210
6211
6212
6213
6214
6215
6216

6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230

6231
6232
6233

6234
6235
6236

6237
6238
6239
6240
6241
6242

6243
6244
6245
6246
6247
6248

6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260

6261

6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272

6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286

6287
6288
6289
6290
6291
6292
6293

6294
6295


6296
6297
6298


6299
6300
6301
6302
6303
6304
6305
6306
6307











6308

6309
6310

6311
6312
6313
6314



6315
6316
6317

6318
6319
6320
6321
6322
6323
6324

6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340

6341
6342
6343
6344
6345
6346
6347
6780
6781
6782
6783
6784
6785
6786


6787
6788
6789
6790

6791



6792
6793
6794
6795









6796
6797
6798
6799
6800
6801
6802
6803
6804
6805

6806
6807
6808
6809
6810
6811
6812

6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826

6827
6828
6829

6830
6831
6832

6833
6834
6835
6836



6837



6838
6839

6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853

6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864

6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878

6879
6880
6881
6882
6883
6884
6885

6886
6887

6888
6889
6890


6891
6892




6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908

6909
6910

6911
6912



6913
6914
6915
6916
6917

6918
6919
6920
6921
6922
6923
6924

6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940

6941
6942
6943
6944
6945
6946
6947
6948







-
-
+
+


-
+
-
-
-
+
+


-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
+






-
+













-
+


-
+


-
+



-
-
-
+
-
-
-


-
+












+
-
+










-
+













-
+






-
+

-
+
+

-
-
+
+
-
-
-
-





+
+
+
+
+
+
+
+
+
+
+
-
+

-
+

-
-
-
+
+
+


-
+






-
+















-
+







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

static int
TestServiceModeCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Arguments. */
{
    int newmode, oldmode;
    if (argc > 2) {
    if (objc > 2) {
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                         " ?newmode?\"", NULL);
        return TCL_ERROR;
	Tcl_WrongNumArgs(interp, 1, objv, "?newmode?");
	return TCL_ERROR;
    }
    oldmode = (Tcl_GetServiceMode() != TCL_SERVICE_NONE);
    if (argc == 2) {
        if (Tcl_GetInt(interp, argv[1], &newmode) == TCL_ERROR) {
            return TCL_ERROR;
        }
        if (newmode == 0) {
            Tcl_SetServiceMode(TCL_SERVICE_NONE);
        } else {
            Tcl_SetServiceMode(TCL_SERVICE_ALL);
        }
    if (objc == 2) {
	if (Tcl_GetIntFromObj(interp, objv[1], &newmode) == TCL_ERROR) {
	    return TCL_ERROR;
	}
	if (newmode == 0) {
	    Tcl_SetServiceMode(TCL_SERVICE_NONE);
	} else {
	    Tcl_SetServiceMode(TCL_SERVICE_ALL);
	}
    }
    Tcl_SetObjResult(interp, Tcl_NewIntObj(oldmode));
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(oldmode));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestWrongNumArgsObjCmd --
 * TestWrongNumArgsCmd --
 *
 *	Test the Tcl_WrongNumArgs function.
 *
 * Results:
 *	Standard Tcl result.
 *
 * Side effects:
 *	Sets interpreter result.
 *
 *----------------------------------------------------------------------
 */

static int
TestWrongNumArgsObjCmd(
TestWrongNumArgsCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Size objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int i, length;
    Tcl_Size i, length;
    const char *msg;

    if (objc < 3) {
	/*
	 * Don't use Tcl_WrongNumArgs here, as that is the function
	 * we want to test!
	goto insufArgs;
	 */
	Tcl_AppendResult(interp, "insufficient arguments", NULL);
	return TCL_ERROR;
    }

    if (Tcl_GetIntFromObj(interp, objv[1], &i) != TCL_OK) {
    if (Tcl_GetIntForIndex(interp, objv[1], TCL_INDEX_NONE, &i) != TCL_OK) {
	return TCL_ERROR;
    }

    msg = Tcl_GetStringFromObj(objv[2], &length);
    if (length == 0) {
	msg = NULL;
    }

    if (i > objc - 3) {
	/*
	 * Asked for more arguments than were given.
	 */
    insufArgs:
	Tcl_AppendResult(interp, "insufficient arguments", NULL);
	Tcl_AppendResult(interp, "insufficient arguments", (char *)NULL);
	return TCL_ERROR;
    }

    Tcl_WrongNumArgs(interp, i, &(objv[3]), msg);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestGetIndexFromObjStructObjCmd --
 * TestGetIndexFromObjStructCmd --
 *
 *	Test the Tcl_GetIndexFromObjStruct function.
 *
 * Results:
 *	Standard Tcl result.
 *
 * Side effects:
 *	Sets interpreter result.
 *
 *----------------------------------------------------------------------
 */

static int
TestGetIndexFromObjStructObjCmd(
TestGetIndexFromObjStructCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *const ary[] = {
	"a", "b", "c", "d", "e", "f", NULL, NULL
	"a", "b", "c", "d", "ee", "ff", NULL, NULL
    };
    int idx,target;
    int target, flags = 0;
    signed char idx[8];

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "argument targetvalue");
    if (objc != 3 && objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "argument targetvalue ?flags?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObjStruct(interp, objv[1], ary, 2*sizeof(char *),
	    "dummy", 0, &idx) != TCL_OK) {
	return TCL_ERROR;
    }
    if (Tcl_GetIntFromObj(interp, objv[2], &target) != TCL_OK) {
	return TCL_ERROR;
    }
    if ((objc > 3) && (Tcl_GetIntFromObj(interp, objv[3], &flags) != TCL_OK)) {
	return TCL_ERROR;
    }
    memset(idx, 85, sizeof(idx));
    if (Tcl_GetIndexFromObjStruct(interp, (Tcl_GetString(objv[1])[0] ? objv[1] : NULL), ary, 2*sizeof(char *),
	    "dummy", flags, &idx[1]) != TCL_OK) {
	return TCL_ERROR;
    }
    if (idx[0] != 85 || idx[2] != 85) {
	Tcl_AppendResult(interp, "Tcl_GetIndexFromObjStruct overwrites bytes near index variable", (char *)NULL);
	return TCL_ERROR;
    if (idx != target) {
    } else if (idx[1] != target) {
	char buffer[64];
	sprintf(buffer, "%d", idx);
	snprintf(buffer, sizeof(buffer), "%d", idx[1]);
	Tcl_AppendResult(interp, "index value comparison failed: got ",
		buffer, NULL);
	sprintf(buffer, "%d", target);
	Tcl_AppendResult(interp, " when ", buffer, " expected", NULL);
		buffer, (char *)NULL);
	snprintf(buffer, sizeof(buffer), "%d", target);
	Tcl_AppendResult(interp, " when ", buffer, " expected", (char *)NULL);
	return TCL_ERROR;
    }
    Tcl_WrongNumArgs(interp, 3, objv, NULL);
    Tcl_WrongNumArgs(interp, objc, objv, NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestFilesystemObjCmd --
 * TestFilesystemCmd --
 *
 *	This procedure implements the "testfilesystem" command. It is used to
 *	test Tcl_FSRegister, Tcl_FSUnregister, and can be used to test that
 *	the pluggable filesystem works.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Inserts or removes a filesystem from Tcl's stack.
 *
 *----------------------------------------------------------------------
 */

static int
TestFilesystemObjCmd(
TestFilesystemCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    int res, boolVal;
    const char *msg;
6451
6452
6453
6454
6455
6456
6457
6458

6459
6460
6461
6462
6463
6464
6465
7052
7053
7054
7055
7056
7057
7058

7059
7060
7061
7062
7063
7064
7065
7066







-
+







	if (arg2 != NULL) {
	    Tcl_DStringAppendElement(&ds, Tcl_GetString(arg2));
	}
	Tcl_DStringEndSublist(&ds);
	savedResult = Tcl_GetObjResult(interp);
	Tcl_IncrRefCount(savedResult);
	Tcl_SetObjResult(interp, Tcl_NewObj());
	Tcl_EvalEx(interp, Tcl_DStringValue(&ds), -1, 0);
	Tcl_EvalEx(interp, Tcl_DStringValue(&ds), TCL_INDEX_NONE, 0);
	Tcl_DStringFree(&ds);
	Tcl_ResetResult(interp);
	Tcl_SetObjResult(interp, savedResult);
	Tcl_DecrRefCount(savedResult);
    }
}

6704
6705
6706
6707
6708
6709
6710
6711

6712
6713
6714
6715
6716
6717
6718
7305
7306
7307
7308
7309
7310
7311

7312
7313
7314
7315
7316
7317
7318
7319







-
+







 *
 * Please do not consider this filesystem a model of how things are to be
 * done. It is quite the opposite!  But, it does allow us to test some
 * important features.
 */

static int
TestSimpleFilesystemObjCmd(
TestSimpleFilesystemCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    int res, boolVal;
    const char *msg;
6740
6741
6742
6743
6744
6745
6746
6747

6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761

6762
6763
6764
6765
6766
6767
6768
7341
7342
7343
7344
7345
7346
7347

7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361

7362
7363
7364
7365
7366
7367
7368
7369







-
+













-
+







 * (native) directory.
 */

static Tcl_Obj *
SimpleRedirect(
    Tcl_Obj *pathPtr)		/* Name of file to copy. */
{
    int len;
    Tcl_Size len;
    const char *str;
    Tcl_Obj *origPtr;

    /*
     * We assume the same name in the current directory is ok.
     */

    str = Tcl_GetStringFromObj(pathPtr, &len);
    if (len < 10 || strncmp(str, "simplefs:/", 10)) {
	/* Probably shouldn't ever reach here */
	Tcl_IncrRefCount(pathPtr);
	return pathPtr;
    }
    origPtr = Tcl_NewStringObj(str+10,-1);
    origPtr = Tcl_NewStringObj(str+10, -1);
    Tcl_IncrRefCount(origPtr);
    return origPtr;
}

static int
SimpleMatchInDirectory(
    Tcl_Interp *interp,		/* Interpreter for error
6786
6787
6788
6789
6790
6791
6792
6793

6794
6795
6796
6797
6798
6799
6800
7387
7388
7389
7390
7391
7392
7393

7394
7395
7396
7397
7398
7399
7400
7401







-
+







     * We assume the same name in the current directory is ok.
     */
    resPtr = Tcl_NewObj();
    Tcl_IncrRefCount(resPtr);
    origPtr = SimpleRedirect(dirPtr);
    res = Tcl_FSMatchInDirectory(interp, resPtr, origPtr, pattern, types);
    if (res == TCL_OK) {
	int gLength, j;
	Tcl_Size gLength, j;
	Tcl_ListObjLength(NULL, resPtr, &gLength);
	for (j = 0; j < gLength; j++) {
	    Tcl_Obj *gElt, *nElt;
	    Tcl_ListObjIndex(NULL, resPtr, j, &gElt);
	    nElt = Tcl_NewStringObj("simplefs:/",10);
	    Tcl_AppendObjToObj(nElt, gElt);
	    Tcl_ListObjAppendElement(NULL, resultPtr, nElt);
6813
6814
6815
6816
6817
6818
6819
6820
6821


6822
6823
6824
6825
6826
6827
6828
7414
7415
7416
7417
7418
7419
7420


7421
7422
7423
7424
7425
7426
7427
7428
7429







-
-
+
+







    int mode,			/* POSIX open mode. */
    int permissions)		/* If the open involves creating a file, with
				 * what modes to create it? */
{
    Tcl_Obj *tempPtr;
    Tcl_Channel chan;

    if ((mode != 0) && !(mode & O_RDONLY)) {
	Tcl_AppendResult(interp, "read-only", NULL);
    if ((mode & O_ACCMODE) != O_RDONLY) {
	Tcl_AppendResult(interp, "read-only", (char *)NULL);
	return NULL;
    }

    tempPtr = SimpleRedirect(pathPtr);
    chan = Tcl_FSOpenFileChannel(interp, tempPtr, "r", permissions);
    Tcl_DecrRefCount(tempPtr);
    return chan;
6872
6873
6874
6875
6876
6877
6878
6879

6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890

6891
6892
6893

6894
6895
6896


6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908

6909
6910
6911
6912
6913
6914
6915
6916


6917
6918


6919
6920
6921
6922

6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939

6940
6941
6942
6943
6944
6945
6946
6947
6948

6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964

6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982


6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995




























6996
6997
6998
6999
7000
7001
7002
7473
7474
7475
7476
7477
7478
7479

7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490

7491

7492

7493
7494


7495
7496
7497
7498
7499
7500
7501
7502
7503
7504
7505
7506
7507

7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518


7519
7520
7521
7522
7523

7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537
7538
7539
7540

7541
7542
7543
7544
7545
7546
7547
7548
7549

7550

7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564

7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581


7582
7583

7584
7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630







-
+










-
+
-

-
+

-
-
+
+











-
+








+
+
-
-
+
+



-
+
















-
+








-
+
-














-
+
















-
-
+
+
-












+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







static int
TestUtfNextCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    size_t numBytes;
    Tcl_Size numBytes;
    char *bytes;
    const char *result, *first;
    char buffer[32];
    static const char tobetested[] = "A\xA0\xC0\xC1\xC2\xD0\xE0\xE8\xF2\xF7\xF8\xFE\xFF";
    const char *p = tobetested;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?-bytestring? bytes");
	return TCL_ERROR;
    }
	bytes = Tcl_GetString(objv[1]);
	bytes = Tcl_GetStringFromObj(objv[1], &numBytes);
	numBytes = objv[1]->length;

    if (numBytes > (int)sizeof(buffer) - 4) {
    if ((size_t)numBytes > sizeof(buffer) - 4) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"\"testutfnext\" can only handle %d bytes",
		(int)sizeof(buffer) - 4));
		"\"testutfnext\" can only handle %" TCL_Z_MODIFIER "u bytes",
		sizeof(buffer) - 4));
	return TCL_ERROR;
    }

    memcpy(buffer + 1, bytes, numBytes);
    buffer[0] = buffer[numBytes + 1] = buffer[numBytes + 2] = buffer[numBytes + 3] = '\xA0';

    first = result = Tcl_UtfNext(buffer + 1);
    while ((buffer[0] = *p++) != '\0') {
	/* Run Tcl_UtfNext with many more possible bytes at src[-1], all should give the same result */
	result = Tcl_UtfNext(buffer + 1);
	if (first != result) {
	    Tcl_AppendResult(interp, "Tcl_UtfNext is not supposed to read src[-1]", NULL);
	    Tcl_AppendResult(interp, "Tcl_UtfNext is not supposed to read src[-1]", (char *)NULL);
	    return TCL_ERROR;
	}
    }
    p = tobetested;
    while ((buffer[numBytes + 1] = *p++) != '\0') {
	/* Run Tcl_UtfNext with many more possible bytes at src[end], all should give the same result */
	result = Tcl_UtfNext(buffer + 1);
	if (first != result) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "Tcl_UtfNext is not supposed to read src[end]\n"
	    first = buffer;
	    break;
		    "Different result when src[end] is %#x", UCHAR(p[-1])));
	    return TCL_ERROR;
	}
    }

    Tcl_SetObjResult(interp, Tcl_NewIntObj(first - buffer - 1));
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(first - buffer - 1));

    return TCL_OK;
}
/*
 * Used to check operations of Tcl_UtfPrev.
 *
 * Usage: testutfprev $bytes $offset
 */

static int
TestUtfPrevCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    size_t numBytes, offset;
    Tcl_Size numBytes, offset;
    char *bytes;
    const char *result;

    if (objc < 2 || objc > 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "bytes ?offset?");
	return TCL_ERROR;
    }

    bytes = Tcl_GetString(objv[1]);
    bytes = Tcl_GetStringFromObj(objv[1], &numBytes);
    numBytes = objv[1]->length;

    if (objc == 3) {
	if (TCL_OK != Tcl_GetIntForIndex(interp, objv[2], numBytes, &offset)) {
	    return TCL_ERROR;
	}
	if (offset == TCL_INDEX_NONE) {
	    offset = 0;
	}
	if (offset > numBytes) {
	    offset = numBytes;
	}
    } else {
	offset = numBytes;
    }
    result = TclUtfPrev(bytes + offset, bytes);
    result = Tcl_UtfPrev(bytes + offset, bytes);
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(result - bytes));
    return TCL_OK;
}

/*
 * Used to check correct string-length determining in Tcl_NumUtfChars
 */

static int
TestNumUtfCharsCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc > 1) {
	size_t len, limit = TCL_INDEX_NONE;
	const char *bytes = Tcl_GetString(objv[1]);
	Tcl_Size numBytes, len, limit = TCL_INDEX_NONE;
	const char *bytes = Tcl_GetStringFromObj(objv[1], &numBytes);
	size_t numBytes = objv[1]->length;

	if (objc > 2) {
	    if (Tcl_GetIntForIndex(interp, objv[2], numBytes, &limit) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (limit > numBytes + 1) {
		limit = numBytes + 1;
	    }
	}
	len = Tcl_NumUtfChars(bytes, limit);
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(len));
    }
    return TCL_OK;
}


/*
 * Used to check correct operation of Tcl_GetUniChar
 * testgetunichar STRING INDEX
 * This differs from just using "string index" in being a direct
 * call to Tcl_GetUniChar without any prior range checking.
 */
static int
TestGetUniCharCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter */
    int objc,			/* Number of arguments */
    Tcl_Obj *const objv[]	/* Argument strings */
    )
{
    int index;
    int c ;
    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "STRING INDEX");
	return TCL_ERROR;
    }
    Tcl_GetIntFromObj(interp, objv[2], &index);
    c = Tcl_GetUniChar(objv[1], index);
    Tcl_SetObjResult(interp, Tcl_NewIntObj(c));

    return TCL_OK;
}

/*
 * Used to check correct operation of Tcl_UtfFindFirst
 */

7036
7037
7038
7039
7040
7041
7042



























7043

7044
7045
7046
7047
7048
7049
7050
7664
7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692
7693
7694
7695
7696
7697

7698
7699
7700
7701
7702
7703
7704
7705







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+







	    (void) Tcl_GetIntFromObj(interp, objv[2], &len);
	}
	Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_UtfFindLast(Tcl_GetString(objv[1]), len), -1));
    }
    return TCL_OK;
}

static int
TestGetIntForIndexCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Size result;
    Tcl_WideInt endvalue;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "index endvalue");
	return TCL_ERROR;
    }

    if (Tcl_GetWideIntFromObj(interp, objv[2], &endvalue) != TCL_OK) {
	return TCL_ERROR;
    }
    if (Tcl_GetIntForIndex(interp, objv[1], endvalue, &result) != TCL_OK) {
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(result));
    return TCL_OK;
}



#if defined(HAVE_CPUID) || defined(_WIN32)
#if defined(HAVE_CPUID) && !defined(MAC_OSX_TCL)
/*
 *----------------------------------------------------------------------
 *
 * TestcpuidCmd --
 *
 *	Retrieves CPU ID information.
 *
7085
7086
7087
7088
7089
7090
7091
7092

7093
7094
7095
7096
7097
7098
7099
7740
7741
7742
7743
7744
7745
7746

7747
7748
7749
7750
7751
7752
7753
7754







-
+







    status = TclWinCPUID(index, regs);
    if (status != TCL_OK) {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("operation not available", -1));
	return status;
    }
    for (i=0 ; i<4 ; ++i) {
	regsObjs[i] = Tcl_NewIntObj(regs[i]);
	regsObjs[i] = Tcl_NewWideIntObj(regs[i]);
    }
    Tcl_SetObjResult(interp, Tcl_NewListObj(4, regsObjs));
    return TCL_OK;
}
#endif

/*
7118
7119
7120
7121
7122
7123
7124
7125

7126
7127
7128
7129
7130
7131
7132
7133
7134


7135
7136
7137
7138
7139
7140
7141
7142


7143
7144
7145
7146
7147
7148

7149
7150
7151


7152
7153
7154
7155
7156
7157


7158
7159
7160
7161
7162
7163
7164
7165

7166
7167
7168
7169
7170
7171

7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184


7185
7186
7187


7188
7189
7190


7191
7192
7193


7194
7195
7196
7197
7198

7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211


7212
7213
7214


7215
7216
7217

7218
7219
7220
7221
7222
7223
7224
7225
7226
7227

7228
7229
7230
7231


7232
7233
7234


7235
7236
7237


7238
7239
7240
7241
7242
7243





7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261

7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275


7276
7277

7278
7279
7280
7281

7282
7283
7284

7285
7286
7287
7288
7289
7290





7291
7292
7293
7294
7295
7296
7297

7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310

7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327


7328
7329
7330


7331
7332
7333
7334
7335
7336
7337
7773
7774
7775
7776
7777
7778
7779

7780
7781
7782
7783
7784
7785
7786
7787


7788
7789
7790
7791
7792
7793
7794
7795


7796
7797
7798
7799
7800
7801
7802

7803
7804


7805
7806
7807
7808
7809
7810


7811
7812
7813
7814
7815
7816
7817
7818
7819

7820
7821
7822
7823
7824
7825

7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837


7838
7839
7840


7841
7842
7843
7844

7845
7846
7847


7848
7849
7850
7851
7852
7853

7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865


7866
7867
7868


7869
7870
7871
7872

7873
7874
7875
7876
7877
7878
7879
7880
7881
7882

7883
7884
7885


7886
7887
7888


7889
7890
7891


7892
7893
7894





7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916

7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929


7930
7931
7932

7933
7934
7935
7936

7937
7938
7939

7940
7941





7942
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952

7953
7954
7955
7956
7957
7958
7959
7960
7961
7962
7963
7964
7965

7966
7967
7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981


7982
7983
7984
7985

7986
7987
7988
7989
7990
7991
7992
7993
7994







-
+







-
-
+
+






-
-
+
+





-
+

-
-
+
+




-
-
+
+







-
+





-
+











-
-
+
+

-
-
+
+


-
+
+

-
-
+
+




-
+











-
-
+
+

-
-
+
+


-
+









-
+


-
-
+
+

-
-
+
+

-
-
+
+

-
-
-
-
-
+
+
+
+
+

















-
+












-
-
+
+

-
+



-
+


-
+

-
-
-
-
-
+
+
+
+
+






-
+












-
+















-
-
+
+


-
+
+







    if (objc>1 && Tcl_GetIntFromObj(interp, objv[1], &limit)!=TCL_OK) {
	return TCL_ERROR;
    }

    Tcl_InitCustomHashTable(&hash, TCL_CUSTOM_TYPE_KEYS, &hkType);

    if (hash.numEntries != 0) {
	Tcl_AppendResult(interp, "non-zero initial size", NULL);
	Tcl_AppendResult(interp, "non-zero initial size", (char *)NULL);
	Tcl_DeleteHashTable(&hash);
	return TCL_ERROR;
    }

    for (i=0 ; i<limit ; i++) {
	hPtr = Tcl_CreateHashEntry(&hash, INT2PTR(i), &isNew);
	if (!isNew) {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(i));
	    Tcl_AppendToObj(Tcl_GetObjResult(interp)," creation problem",-1);
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(i));
	    Tcl_AppendToObj(Tcl_GetObjResult(interp)," creation problem", -1);
	    Tcl_DeleteHashTable(&hash);
	    return TCL_ERROR;
	}
	Tcl_SetHashValue(hPtr, INT2PTR(i+42));
    }

    if (hash.numEntries != (size_t)limit) {
	Tcl_AppendResult(interp, "unexpected maximal size", NULL);
    if (hash.numEntries != (Tcl_Size)limit) {
	Tcl_AppendResult(interp, "unexpected maximal size", (char *)NULL);
	Tcl_DeleteHashTable(&hash);
	return TCL_ERROR;
    }

    for (i=0 ; i<limit ; i++) {
	hPtr = Tcl_FindHashEntry(&hash, (char *) INT2PTR(i));
	hPtr = Tcl_FindHashEntry(&hash, (char *)INT2PTR(i));
	if (hPtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(i));
	    Tcl_AppendToObj(Tcl_GetObjResult(interp)," lookup problem",-1);
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(i));
	    Tcl_AppendToObj(Tcl_GetObjResult(interp)," lookup problem", -1);
	    Tcl_DeleteHashTable(&hash);
	    return TCL_ERROR;
	}
	if (PTR2INT(Tcl_GetHashValue(hPtr)) != i+42) {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(i));
	    Tcl_AppendToObj(Tcl_GetObjResult(interp)," value problem",-1);
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(i));
	    Tcl_AppendToObj(Tcl_GetObjResult(interp)," value problem", -1);
	    Tcl_DeleteHashTable(&hash);
	    return TCL_ERROR;
	}
	Tcl_DeleteHashEntry(hPtr);
    }

    if (hash.numEntries != 0) {
	Tcl_AppendResult(interp, "non-zero final size", NULL);
	Tcl_AppendResult(interp, "non-zero final size", (char *)NULL);
	Tcl_DeleteHashTable(&hash);
	return TCL_ERROR;
    }

    Tcl_DeleteHashTable(&hash);
    Tcl_AppendResult(interp, "OK", NULL);
    Tcl_AppendResult(interp, "OK", (char *)NULL);
    return TCL_OK;
}

/*
 * Used for testing Tcl_GetInt which is no longer used directly by the
 * core very much.
 */
static int
TestgetintCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int argc,
    const char **argv)
    int objc,
    Tcl_Obj *const *objv)
{
    if (argc < 2) {
	Tcl_AppendResult(interp, "wrong # args", NULL);
    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?args?");
	return TCL_ERROR;
    } else {
	int val, i, total=0;
	int val, total=0;
	int i;

	for (i=1 ; i<argc ; i++) {
	    if (Tcl_GetInt(interp, argv[i], &val) != TCL_OK) {
	for (i=1 ; i<objc ; i++) {
	    if (Tcl_GetInt(interp, Tcl_GetString(objv[i]), &val) != TCL_OK) {
		return TCL_ERROR;
	    }
	    total += val;
	}
	Tcl_SetObjResult(interp, Tcl_NewIntObj(total));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(total));
	return TCL_OK;
    }
}

/*
 * Used for determining sizeof(long) at script level.
 */
static int
TestlongsizeCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int argc,
    TCL_UNUSED(const char **) /*argv*/)
    int objc,
    Tcl_Obj *const *objv)
{
    if (argc != 1) {
	Tcl_AppendResult(interp, "wrong # args", NULL);
    if (objc > 1) {
	Tcl_WrongNumArgs(interp, 1, objv, "");
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewIntObj(sizeof(long)));
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sizeof(long)));
    return TCL_OK;
}

static int
NREUnwind_callback(
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int) /*result*/)
{
    int none;
    void *cStackPtr = TclGetCStackPtr();

    if (data[0] == INT2PTR(-1)) {
        Tcl_NRAddCallback(interp, NREUnwind_callback, &none, INT2PTR(-1),
                INT2PTR(-1), NULL);
	Tcl_NRAddCallback(interp, NREUnwind_callback, cStackPtr, INT2PTR(-1),
		INT2PTR(-1), NULL);
    } else if (data[1] == INT2PTR(-1)) {
        Tcl_NRAddCallback(interp, NREUnwind_callback, data[0], &none,
                INT2PTR(-1), NULL);
	Tcl_NRAddCallback(interp, NREUnwind_callback, data[0], cStackPtr,
		INT2PTR(-1), NULL);
    } else if (data[2] == INT2PTR(-1)) {
        Tcl_NRAddCallback(interp, NREUnwind_callback, data[0], data[1],
                &none, NULL);
	Tcl_NRAddCallback(interp, NREUnwind_callback, data[0], data[1],
		cStackPtr, NULL);
    } else {
        Tcl_Obj *idata[3];
        idata[0] = Tcl_NewIntObj(((char *) data[1] - (char *) data[0]));
        idata[1] = Tcl_NewIntObj(((char *) data[2] - (char *) data[0]));
        idata[2] = Tcl_NewIntObj(((char *) &none   - (char *) data[0]));
        Tcl_SetObjResult(interp, Tcl_NewListObj(3, idata));
	Tcl_Obj *idata[3];
	idata[0] = Tcl_NewWideIntObj(((char *)data[1] - (char *)data[0]));
	idata[1] = Tcl_NewWideIntObj(((char *)data[2] - (char *)data[0]));
	idata[2] = Tcl_NewWideIntObj(((char *)cStackPtr - (char *)data[0]));
	Tcl_SetObjResult(interp, Tcl_NewListObj(3, idata));
    }
    return TCL_OK;
}

static int
TestNREUnwind(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    TCL_UNUSED(int) /*objc*/,
    TCL_UNUSED(Tcl_Obj *const *) /*objv*/)
{
    /*
     * Insure that callbacks effectively run at the proper level during the
     * unwinding of the NRE stack.
     */

    Tcl_NRAddCallback(interp, NREUnwind_callback, INT2PTR(-1), INT2PTR(-1),
            INT2PTR(-1), NULL);
	    INT2PTR(-1), NULL);
    return TCL_OK;
}


static int
TestNRELevels(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    TCL_UNUSED(int) /*objc*/,
    TCL_UNUSED(Tcl_Obj *const *) /*objv*/)
{
    Interp *iPtr = (Interp *) interp;
    static ptrdiff_t *refDepth = NULL;
    ptrdiff_t depth;
    static Tcl_Size *refDepth = NULL;
    Tcl_Size depth;
    Tcl_Obj *levels[6];
    int i = 0;
    Tcl_Size i = 0;
    NRE_callback *cbPtr = iPtr->execEnvPtr->callbackPtr;

    if (refDepth == NULL) {
	refDepth = &depth;
	refDepth = (ptrdiff_t *)TclGetCStackPtr();
    }

    depth = (refDepth - &depth);
    depth = (refDepth - (ptrdiff_t *)TclGetCStackPtr());

    levels[0] = Tcl_NewIntObj(depth);
    levels[1] = Tcl_NewIntObj(iPtr->numLevels);
    levels[2] = Tcl_NewIntObj(iPtr->cmdFramePtr->level);
    levels[3] = Tcl_NewIntObj(iPtr->varFramePtr->level);
    levels[4] = Tcl_NewIntObj(iPtr->execEnvPtr->execStackPtr->tosPtr
    levels[0] = Tcl_NewWideIntObj(depth);
    levels[1] = Tcl_NewWideIntObj(iPtr->numLevels);
    levels[2] = Tcl_NewWideIntObj(iPtr->cmdFramePtr->level);
    levels[3] = Tcl_NewWideIntObj(iPtr->varFramePtr->level);
    levels[4] = Tcl_NewWideIntObj(iPtr->execEnvPtr->execStackPtr->tosPtr
	    - iPtr->execEnvPtr->execStackPtr->stackWords);

    while (cbPtr) {
	i++;
	cbPtr = cbPtr->nextPtr;
    }
    levels[5] = Tcl_NewIntObj(i);
    levels[5] = Tcl_NewWideIntObj(i);

    Tcl_SetObjResult(interp, Tcl_NewListObj(6, levels));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestconcatobjCmd --
 *
 *	This procedure implements the "testconcatobj" command. It is used
 *	to test that Tcl_ConcatObj does indeed return a fresh Tcl_Obj in all
 *	cases and thet it never corrupts its arguments. In other words, that
 *	cases and that it never corrupts its arguments. In other words, that
 *	[Bug 1447328] was fixed properly.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestconcatobjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*argc*/,
    TCL_UNUSED(const char **) /*argv*/)
    TCL_UNUSED(int) /*objc*/,
    TCL_UNUSED(Tcl_Obj *const *) /*objv*/)
{
    Tcl_Obj *list1Ptr, *list2Ptr, *emptyPtr, *concatPtr, *tmpPtr;
    int result = TCL_OK, len;
    int result = TCL_OK;
    Tcl_Size len;
    Tcl_Obj *objv[3];

    /*
     * Set the start of the error message as obj result; it will be cleared at
     * the end if no errors were found.
     */

7357
7358
7359
7360
7361
7362
7363
7364

7365
7366
7367
7368
7369

7370
7371
7372

7373
7374
7375

7376
7377
7378

7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391

7392
7393
7394
7395
7396

7397
7398
7399

7400
7401
7402
7403

7404
7405
7406

7407
7408
7409
7410

7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425

7426
7427
7428
7429
7430

7431
7432
7433

7434
7435
7436

7437
7438
7439

7440
7441
7442
7443
7444
7445
7446
7447
7448
7449
7450
7451
7452

7453
7454
7455
7456
7457

7458
7459
7460

7461
7462
7463
7464

7465
7466
7467

7468
7469
7470
7471

7472
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490

7491
7492
7493
7494
7495

7496
7497
7498
7499
7500

7501
7502
7503

7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520

7521
7522
7523
7524
7525

7526
7527
7528
7529
7530

7531
7532
7533

7534
7535
7536
7537
7538
7539
7540
7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551

7552
7553
7554
7555
7556

7557
7558
7559
7560
7561

7562
7563
7564

7565
7566
7567
7568
7569
7570
7571
8014
8015
8016
8017
8018
8019
8020

8021
8022
8023
8024
8025

8026
8027
8028

8029
8030
8031

8032
8033
8034

8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047

8048
8049
8050
8051
8052

8053
8054
8055

8056
8057
8058
8059

8060
8061
8062

8063
8064
8065
8066

8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
8077
8078
8079
8080
8081

8082
8083
8084
8085
8086

8087
8088
8089

8090
8091
8092

8093
8094
8095

8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108

8109
8110
8111
8112
8113

8114
8115
8116

8117
8118
8119
8120

8121
8122
8123

8124
8125
8126
8127

8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146

8147
8148
8149
8150
8151

8152
8153
8154
8155
8156

8157
8158
8159

8160
8161
8162
8163
8164
8165
8166
8167
8168
8169
8170
8171
8172
8173
8174
8175
8176

8177
8178
8179
8180
8181

8182
8183
8184
8185
8186

8187
8188
8189

8190
8191
8192
8193
8194
8195
8196
8197
8198
8199
8200
8201
8202
8203
8204
8205
8206
8207

8208
8209
8210
8211
8212

8213
8214
8215
8216
8217

8218
8219
8220

8221
8222
8223
8224
8225
8226
8227
8228







-
+




-
+


-
+


-
+


-
+












-
+




-
+


-
+



-
+


-
+



-
+














-
+




-
+


-
+


-
+


-
+












-
+




-
+


-
+



-
+


-
+



-
+


















-
+




-
+




-
+


-
+
















-
+




-
+




-
+


-
+

















-
+




-
+




-
+


-
+








    objv[0] = tmpPtr;
    objv[1] = emptyPtr;
    concatPtr = Tcl_ConcatObj(2, objv);
    if (concatPtr->refCount != 0) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp,
		"\n\t* (a) concatObj does not have refCount 0", NULL);
		"\n\t* (a) concatObj does not have refCount 0", (char *)NULL);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (a) concatObj is not a new obj ",
		NULL);
		(char *)NULL);
	switch (tmpPtr->refCount) {
	case 0:
	    Tcl_AppendResult(interp, "(no new refCount)", NULL);
	    Tcl_AppendResult(interp, "(no new refCount)", (char *)NULL);
	    break;
	case 1:
	    Tcl_AppendResult(interp, "(refCount added)", NULL);
	    Tcl_AppendResult(interp, "(refCount added)", (char *)NULL);
	    break;
	default:
	    Tcl_AppendResult(interp, "(more than one refCount added!)", NULL);
	    Tcl_AppendResult(interp, "(more than one refCount added!)", (char *)NULL);
	    Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
	}
	tmpPtr = Tcl_DuplicateObj(list1Ptr);
	objv[0] = tmpPtr;
    }
    Tcl_DecrRefCount(concatPtr);

    Tcl_IncrRefCount(tmpPtr);
    concatPtr = Tcl_ConcatObj(2, objv);
    if (concatPtr->refCount != 0) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp,
		"\n\t* (b) concatObj does not have refCount 0", NULL);
		"\n\t* (b) concatObj does not have refCount 0", (char *)NULL);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (b) concatObj is not a new obj ",
		NULL);
		(char *)NULL);
	switch (tmpPtr->refCount) {
	case 0:
	    Tcl_AppendResult(interp, "(refCount removed?)", NULL);
	    Tcl_AppendResult(interp, "(refCount removed?)", (char *)NULL);
	    Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
	    break;
	case 1:
	    Tcl_AppendResult(interp, "(no new refCount)", NULL);
	    Tcl_AppendResult(interp, "(no new refCount)", (char *)NULL);
	    break;
	case 2:
	    Tcl_AppendResult(interp, "(refCount added)", NULL);
	    Tcl_AppendResult(interp, "(refCount added)", (char *)NULL);
	    Tcl_DecrRefCount(tmpPtr);
	    break;
	default:
	    Tcl_AppendResult(interp, "(more than one refCount added!)", NULL);
	    Tcl_AppendResult(interp, "(more than one refCount added!)", (char *)NULL);
	    Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
	}
	tmpPtr = Tcl_DuplicateObj(list1Ptr);
	objv[0] = tmpPtr;
    }
    Tcl_DecrRefCount(concatPtr);

    objv[0] = emptyPtr;
    objv[1] = tmpPtr;
    objv[2] = emptyPtr;
    concatPtr = Tcl_ConcatObj(3, objv);
    if (concatPtr->refCount != 0) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp,
		"\n\t* (c) concatObj does not have refCount 0", NULL);
		"\n\t* (c) concatObj does not have refCount 0", (char *)NULL);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (c) concatObj is not a new obj ",
		NULL);
		(char *)NULL);
	switch (tmpPtr->refCount) {
	case 0:
	    Tcl_AppendResult(interp, "(no new refCount)", NULL);
	    Tcl_AppendResult(interp, "(no new refCount)", (char *)NULL);
	    break;
	case 1:
	    Tcl_AppendResult(interp, "(refCount added)", NULL);
	    Tcl_AppendResult(interp, "(refCount added)", (char *)NULL);
	    break;
	default:
	    Tcl_AppendResult(interp, "(more than one refCount added!)", NULL);
	    Tcl_AppendResult(interp, "(more than one refCount added!)", (char *)NULL);
	    Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
	}
	tmpPtr = Tcl_DuplicateObj(list1Ptr);
	objv[1] = tmpPtr;
    }
    Tcl_DecrRefCount(concatPtr);

    Tcl_IncrRefCount(tmpPtr);
    concatPtr = Tcl_ConcatObj(3, objv);
    if (concatPtr->refCount != 0) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp,
		"\n\t* (d) concatObj does not have refCount 0", NULL);
		"\n\t* (d) concatObj does not have refCount 0", (char *)NULL);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (d) concatObj is not a new obj ",
		NULL);
		(char *)NULL);
	switch (tmpPtr->refCount) {
	case 0:
	    Tcl_AppendResult(interp, "(refCount removed?)", NULL);
	    Tcl_AppendResult(interp, "(refCount removed?)", (char *)NULL);
	    Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
	    break;
	case 1:
	    Tcl_AppendResult(interp, "(no new refCount)", NULL);
	    Tcl_AppendResult(interp, "(no new refCount)", (char *)NULL);
	    break;
	case 2:
	    Tcl_AppendResult(interp, "(refCount added)", NULL);
	    Tcl_AppendResult(interp, "(refCount added)", (char *)NULL);
	    Tcl_DecrRefCount(tmpPtr);
	    break;
	default:
	    Tcl_AppendResult(interp, "(more than one refCount added!)", NULL);
	    Tcl_AppendResult(interp, "(more than one refCount added!)", (char *)NULL);
	    Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
	}
	tmpPtr = Tcl_DuplicateObj(list1Ptr);
	objv[1] = tmpPtr;
    }
    Tcl_DecrRefCount(concatPtr);

    /*
     * Verify that an unshared list is not corrupted when concat'ing things to
     * it.
     */

    objv[0] = tmpPtr;
    objv[1] = list2Ptr;
    concatPtr = Tcl_ConcatObj(2, objv);
    if (concatPtr->refCount != 0) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp,
		"\n\t* (e) concatObj does not have refCount 0", NULL);
		"\n\t* (e) concatObj does not have refCount 0", (char *)NULL);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (e) concatObj is not a new obj ",
		NULL);
		(char *)NULL);

	(void) Tcl_ListObjLength(NULL, concatPtr, &len);
	switch (tmpPtr->refCount) {
	case 3:
	    Tcl_AppendResult(interp, "(failed to concat)", NULL);
	    Tcl_AppendResult(interp, "(failed to concat)", (char *)NULL);
	    break;
	default:
	    Tcl_AppendResult(interp, "(corrupted input!)", NULL);
	    Tcl_AppendResult(interp, "(corrupted input!)", (char *)NULL);
	}
	if (Tcl_IsShared(tmpPtr)) {
	    Tcl_DecrRefCount(tmpPtr);
	}
	tmpPtr = Tcl_DuplicateObj(list1Ptr);
	objv[0] = tmpPtr;
    }
    Tcl_DecrRefCount(concatPtr);

    objv[0] = tmpPtr;
    objv[1] = list2Ptr;
    Tcl_IncrRefCount(tmpPtr);
    concatPtr = Tcl_ConcatObj(2, objv);
    if (concatPtr->refCount != 0) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp,
		"\n\t* (f) concatObj does not have refCount 0", NULL);
		"\n\t* (f) concatObj does not have refCount 0", (char *)NULL);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (f) concatObj is not a new obj ",
		NULL);
		(char *)NULL);

	(void) Tcl_ListObjLength(NULL, concatPtr, &len);
	switch (tmpPtr->refCount) {
	case 3:
	    Tcl_AppendResult(interp, "(failed to concat)", NULL);
	    Tcl_AppendResult(interp, "(failed to concat)", (char *)NULL);
	    break;
	default:
	    Tcl_AppendResult(interp, "(corrupted input!)", NULL);
	    Tcl_AppendResult(interp, "(corrupted input!)", (char *)NULL);
	}
	if (Tcl_IsShared(tmpPtr)) {
	    Tcl_DecrRefCount(tmpPtr);
	}
	tmpPtr = Tcl_DuplicateObj(list1Ptr);
	objv[0] = tmpPtr;
    }
    Tcl_DecrRefCount(concatPtr);

    objv[0] = tmpPtr;
    objv[1] = list2Ptr;
    Tcl_IncrRefCount(tmpPtr);
    Tcl_IncrRefCount(tmpPtr);
    concatPtr = Tcl_ConcatObj(2, objv);
    if (concatPtr->refCount != 0) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp,
		"\n\t* (g) concatObj does not have refCount 0", NULL);
		"\n\t* (g) concatObj does not have refCount 0", (char *)NULL);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (g) concatObj is not a new obj ",
		NULL);
		(char *)NULL);

	(void) Tcl_ListObjLength(NULL, concatPtr, &len);
	switch (tmpPtr->refCount) {
	case 3:
	    Tcl_AppendResult(interp, "(failed to concat)", NULL);
	    Tcl_AppendResult(interp, "(failed to concat)", (char *)NULL);
	    break;
	default:
	    Tcl_AppendResult(interp, "(corrupted input!)", NULL);
	    Tcl_AppendResult(interp, "(corrupted input!)", (char *)NULL);
	}
	Tcl_DecrRefCount(tmpPtr);
	if (Tcl_IsShared(tmpPtr)) {
	    Tcl_DecrRefCount(tmpPtr);
	}
	tmpPtr = Tcl_DuplicateObj(list1Ptr);
	objv[0] = tmpPtr;
7591
7592
7593
7594
7595
7596
7597
7598

7599
7600

7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611

7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623

7624
7625
7626
7627

7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646


7647
7648
7649
7650




7651






7652
7653
7654




7655
7656
7657
7658


7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685
7686

7687
7688
7689
7690
7691







7692
7693
7694
7695
7696

7697
7698
7699


7700


7701

7702
7703
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715

7716
7717
7718
7719
7720
7721

7722
7723
7724
7725
7726
7727
7728
7729
7730
7731

7732
7733
7734
7735
7736
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754






















7755
7756
7757


7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780






















7781
7782
7783


7784
7785
7786
7787



7788
7789
7790
7791
7792
7793





7794
7795
7796
7797
7798




7799
7800
7801
7802
7803
7804
7805
7806
7807
7808

7809
7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829

7830
7831

7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842
7843

7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866




7867
7868
7869


7870
7871
7872
7873



7874
7875

7876
7877
7878
7879

7880
7881

7882
7883

7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900

7901
7902
7903
7904
7905

7906
7907
7908
7909
7910
7911
7912
7913







7914
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926

7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938

7939
7940
7941
7942
7943
7944


7945
7946
7947
7948
7949
7950



7951
7952
7953
7954
7955
7956





7957
7958
7959
7960














































































































































































7961
7962
7963
7964
7965
7966
7967
7968
7969
8248
8249
8250
8251
8252
8253
8254

8255
8256

8257











8258












8259




8260







8261
8262
8263
8264
8265
8266
8267
8268
8269
8270


8271
8272
8273



8274
8275
8276
8277
8278
8279
8280
8281
8282
8283
8284



8285
8286
8287
8288
8289
8290


8291
8292
8293


















8294
8295
8296
8297
8298
8299
8300
8301
8302
8303





8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314

8315
8316


8317
8318
8319
8320
8321

8322
8323
8324
8325
8326
8327
8328
8329
8330
8331
8332
8333
8334
8335

8336
8337
8338
8339
8340
8341

8342
8343
8344
8345
8346
8347
8348
8349
8350
8351

8352
8353






















8354
8355
8356
8357
8358
8359
8360
8361
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371
8372
8373
8374
8375
8376


8377
8378
8379






















8380
8381
8382
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402


8403
8404
8405



8406
8407
8408
8409





8410
8411
8412
8413
8414
8415




8416
8417
8418
8419
8420
8421
8422
8423
8424
8425
8426
8427
8428

8429
8430
8431
8432
8433
8434
8435
8436
8437
8438
8439
8440
8441
8442
8443
8444
8445
8446
8447
8448
8449

8450
8451

8452
8453
8454
8455
8456
8457
8458
8459
8460
8461
8462
8463

8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483




8484
8485
8486
8487
8488


8489
8490
8491



8492
8493
8494
8495

8496
8497
8498
8499

8500
8501

8502
8503

8504
8505
8506
8507
8508
8509
8510
8511
8512
8513
8514
8515
8516
8517
8518
8519
8520

8521
8522
8523
8524
8525

8526
8527







8528
8529
8530
8531
8532
8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544
8545
8546

8547
8548
8549
8550
8551
8552
8553
8554
8555
8556
8557
8558

8559
8560
8561
8562
8563


8564
8565
8566
8567
8568



8569
8570
8571
8572





8573
8574
8575
8576
8577
8578
8579
8580

8581
8582
8583
8584
8585
8586
8587
8588
8589
8590
8591
8592
8593
8594
8595
8596
8597
8598
8599
8600
8601
8602
8603
8604
8605
8606
8607
8608
8609
8610
8611
8612
8613
8614
8615
8616
8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628
8629
8630
8631
8632
8633
8634
8635
8636
8637
8638
8639
8640
8641
8642
8643
8644
8645
8646
8647
8648
8649
8650
8651
8652
8653
8654
8655
8656
8657
8658
8659
8660
8661
8662
8663
8664
8665
8666
8667
8668
8669
8670
8671
8672
8673
8674
8675
8676
8677
8678
8679
8680
8681
8682
8683
8684
8685
8686
8687
8688
8689
8690
8691
8692
8693
8694
8695
8696
8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707
8708
8709
8710
8711
8712
8713
8714
8715
8716
8717
8718
8719
8720
8721
8722
8723
8724
8725
8726
8727
8728
8729
8730
8731
8732
8733
8734
8735
8736
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746
8747
8748
8749
8750
8751
8752
8753
8754
8755
8756
8757
8758
8759
8760
8761
8762
8763







-
+

-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-










-
-
+
+

-
-
-
+
+
+
+

+
+
+
+
+
+
-
-
-
+
+
+
+


-
-
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-









+
-
-
-
-
-
+
+
+
+
+
+
+




-
+

-
-
+
+

+
+
-
+













-
+





-
+









-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+

-
-
-
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
+
+
+
+









-
+




















-
+

-
+











-
+



















-
-
-
-
+
+
+
+

-
-
+
+

-
-
-
+
+
+

-
+



-
+

-
+

-
+
















-
+




-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+












-
+











-
+




-
-
+
+



-
-
-
+
+
+

-
-
-
-
-
+
+
+
+
+



-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TestgetencpathObjCmd --
 * TestparseargsCmd --
 *
 *	This function implements the "testgetencpath" command. It is used to
 *	This procedure implements the "testparseargs" command. It is used to
 *	test Tcl_GetEncodingSearchPath().
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

 *	test that Tcl_ParseArgsObjv does indeed return the right number of
static int
TestgetencpathObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)		/* Argument strings. */
{
    if (objc != 1) {
        Tcl_WrongNumArgs(interp, 1, objv, "");
        return TCL_ERROR;
    }

 *	arguments. In other words, that [Bug 3413857] was fixed properly.
    Tcl_SetObjResult(interp, Tcl_GetEncodingSearchPath());
    return TCL_OK;
}

 *	Also test for bug [7cb7409e05]
/*
 *----------------------------------------------------------------------
 *
 * TestsetencpathCmd --
 *
 *	This function implements the "testsetencpath" command. It is used to
 *	test Tcl_SetDefaultEncodingDir().
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestsetencpathObjCmd(
static Tcl_Size
ParseMedia(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Argument strings. */
    Tcl_Interp *interp,
    TCL_UNUSED(Tcl_Size),
    Tcl_Obj *const *objv,
    void *dstPtr)
{
    static const char *const mediaOpts[] = {"A4", "Legal", "Letter", NULL};
    static const char *const ExtendedMediaOpts[] = {
	"Paper size is ISO A4", "Paper size is US Legal",
	"Paper size is US Letter", NULL};
    int index;
    const char **media = (const char **) dstPtr;
    if (objc != 2) {
        Tcl_WrongNumArgs(interp, 1, objv, "defaultDir");
        return TCL_ERROR;

    if (Tcl_GetIndexFromObjStruct(interp, objv[0], mediaOpts,
	    sizeof(char *), "media", 0, &index) != TCL_OK) {
	return -1;
    }

    Tcl_SetEncodingSearchPath(objv[1]);
    return TCL_OK;
    *media = ExtendedMediaOpts[index];
    return 1;
}

/*
 *----------------------------------------------------------------------
 *
 * TestparseargsCmd --
 *
 *	This procedure implements the "testparseargs" command. It is used to
 *	test that Tcl_ParseArgsObjv does indeed return the right number of
 *	arguments. In other words, that [Bug 3413857] was fixed properly.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestparseargsCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Arguments. */
{
    static int foo = 0;
    const char *media = NULL, *color = NULL;
    int count = objc;
    Tcl_Obj **remObjv, *result[3];
    Tcl_ArgvInfo argTable[] = {
        {TCL_ARGV_CONSTANT, "-bool", INT2PTR(1), &foo, "booltest", NULL},
        TCL_ARGV_AUTO_REST, TCL_ARGV_AUTO_HELP, TCL_ARGV_TABLE_END
    Tcl_Size count = objc;
    Tcl_Obj **remObjv, *result[5];
    const Tcl_ArgvInfo argTable[] = {
	{TCL_ARGV_CONSTANT, "-bool", INT2PTR(1), &foo, "booltest", NULL},
	{TCL_ARGV_STRING,  "-colormode" ,  NULL, &color,  "color mode", NULL},
	{TCL_ARGV_GENFUNC, "-media", (void *)ParseMedia, &media,  "media page size", NULL},
	TCL_ARGV_AUTO_REST, TCL_ARGV_AUTO_HELP, TCL_ARGV_TABLE_END
    };

    foo = 0;
    if (Tcl_ParseArgsObjv(interp, argTable, &count, objv, &remObjv)!=TCL_OK) {
        return TCL_ERROR;
	return TCL_ERROR;
    }
    result[0] = Tcl_NewIntObj(foo);
    result[1] = Tcl_NewIntObj(count);
    result[0] = Tcl_NewWideIntObj(foo);
    result[1] = Tcl_NewWideIntObj(count);
    result[2] = Tcl_NewListObj(count, remObjv);
    result[3] = Tcl_NewStringObj(color ? color : "NULL", -1);
    result[4] = Tcl_NewStringObj(media ? media : "NULL", -1);
    Tcl_SetObjResult(interp, Tcl_NewListObj(3, result));
    Tcl_SetObjResult(interp, Tcl_NewListObj(5, result));
    Tcl_Free(remObjv);
    return TCL_OK;
}

/**
 * Test harness for command and variable resolvers.
 */

static int
InterpCmdResolver(
    Tcl_Interp *interp,
    const char *name,
    TCL_UNUSED(Tcl_Namespace *),
    TCL_UNUSED(int) /*flags*/,
    TCL_UNUSED(int) /* flags */,
    Tcl_Command *rPtr)
{
    Interp *iPtr = (Interp *) interp;
    CallFrame *varFramePtr = iPtr->varFramePtr;
    Proc *procPtr = (varFramePtr->isProcCallFrame & FRAME_IS_PROC) ?
            varFramePtr->procPtr : NULL;
	    varFramePtr->procPtr : NULL;
    Namespace *callerNsPtr = varFramePtr->nsPtr;
    Tcl_Command resolvedCmdPtr = NULL;

    /*
     * Just do something special on a cmd literal "z" in two cases:
     *  A)  when the caller is a proc "x", and the proc is either in "::" or in "::ns2".
     *  B) the caller's namespace is "ctx1" or "ctx2"
     */
    if ( (name[0] == 'z') && (name[1] == '\0') ) {
        Namespace *ns2NsPtr = (Namespace *) Tcl_FindNamespace(interp, "::ns2", NULL, 0);
	Namespace *ns2NsPtr = (Namespace *) Tcl_FindNamespace(interp, "::ns2", NULL, 0);

        if (procPtr != NULL
            && ((procPtr->cmdPtr->nsPtr == iPtr->globalNsPtr)
                || (ns2NsPtr != NULL && procPtr->cmdPtr->nsPtr == ns2NsPtr)
                )
            ) {
            /*
             * Case A)
             *
             *    - The context, in which this resolver becomes active, is
             *      determined by the name of the caller proc, which has to be
             *      named "x".
             *
             *    - To determine the name of the caller proc, the proc is taken
             *      from the topmost stack frame.
             *
             *    - Note that the context is NOT provided during byte-code
             *      compilation (e.g. in TclProcCompileProc)
             *
             *   When these conditions hold, this function resolves the
             *   passed-in cmd literal into a cmd "y", which is taken from the
             *   the global namespace (for simplicity).
             */
	if (procPtr != NULL
	    && ((procPtr->cmdPtr->nsPtr == iPtr->globalNsPtr)
		|| (ns2NsPtr != NULL && procPtr->cmdPtr->nsPtr == ns2NsPtr)
		)
	    ) {
	    /*
	     * Case A)
	     *
	     *    - The context, in which this resolver becomes active, is
	     *      determined by the name of the caller proc, which has to be
	     *      named "x".
	     *
	     *    - To determine the name of the caller proc, the proc is taken
	     *      from the topmost stack frame.
	     *
	     *    - Note that the context is NOT provided during byte-code
	     *      compilation (e.g. in TclProcCompileProc)
	     *
	     *   When these conditions hold, this function resolves the
	     *   passed-in cmd literal into a cmd "y", which is taken from
	     *   the global namespace (for simplicity).
	     */

            const char *callingCmdName =
                Tcl_GetCommandName(interp, (Tcl_Command) procPtr->cmdPtr);
	    const char *callingCmdName =
		Tcl_GetCommandName(interp, (Tcl_Command) procPtr->cmdPtr);

            if ( callingCmdName[0] == 'x' && callingCmdName[1] == '\0' ) {
                resolvedCmdPtr = Tcl_FindCommand(interp, "y", NULL, TCL_GLOBAL_ONLY);
            }
        } else if (callerNsPtr != NULL) {
            /*
             * Case B)
             *
             *    - The context, in which this resolver becomes active, is
             *      determined by the name of the parent namespace, which has
             *      to be named "ctx1" or "ctx2".
             *
             *    - To determine the name of the parent namesace, it is taken
             *      from the 2nd highest stack frame.
             *
             *    - Note that the context can be provided during byte-code
             *      compilation (e.g. in TclProcCompileProc)
             *
             *   When these conditions hold, this function resolves the
             *   passed-in cmd literal into a cmd "y" or "Y" depending on the
             *   context. The resolved procs are taken from the the global
             *   namespace (for simplicity).
             */
	    if ( callingCmdName[0] == 'x' && callingCmdName[1] == '\0' ) {
		resolvedCmdPtr = Tcl_FindCommand(interp, "y", NULL, TCL_GLOBAL_ONLY);
	    }
	} else if (callerNsPtr != NULL) {
	    /*
	     * Case B)
	     *
	     *    - The context, in which this resolver becomes active, is
	     *      determined by the name of the parent namespace, which has
	     *      to be named "ctx1" or "ctx2".
	     *
	     *    - To determine the name of the parent namesace, it is taken
	     *      from the 2nd highest stack frame.
	     *
	     *    - Note that the context can be provided during byte-code
	     *      compilation (e.g. in TclProcCompileProc)
	     *
	     *   When these conditions hold, this function resolves the
	     *   passed-in cmd literal into a cmd "y" or "Y" depending on the
	     *   context. The resolved procs are taken from the global
	     *   namespace (for simplicity).
	     */

            CallFrame *parentFramePtr = varFramePtr->callerPtr;
            const char *context = parentFramePtr != NULL ? parentFramePtr->nsPtr->name : "(NULL)";
	    CallFrame *parentFramePtr = varFramePtr->callerPtr;
	    const char *context = parentFramePtr != NULL ? parentFramePtr->nsPtr->name : "(NULL)";

            if (strcmp(context, "ctx1") == 0 && (name[0] == 'z') && (name[1] == '\0')) {
                resolvedCmdPtr = Tcl_FindCommand(interp, "y", NULL, TCL_GLOBAL_ONLY);
                /* fprintf(stderr, "... y ==> %p\n", resolvedCmdPtr);*/
	    if (strcmp(context, "ctx1") == 0 && (name[0] == 'z') && (name[1] == '\0')) {
		resolvedCmdPtr = Tcl_FindCommand(interp, "y", NULL, TCL_GLOBAL_ONLY);
		/* fprintf(stderr, "... y ==> %p\n", resolvedCmdPtr);*/

            } else if (strcmp(context, "ctx2") == 0 && (name[0] == 'z') && (name[1] == '\0')) {
                resolvedCmdPtr = Tcl_FindCommand(interp, "Y", NULL, TCL_GLOBAL_ONLY);
                /*fprintf(stderr, "... Y ==> %p\n", resolvedCmdPtr);*/
            }
        }
	    } else if (strcmp(context, "ctx2") == 0 && (name[0] == 'z') && (name[1] == '\0')) {
		resolvedCmdPtr = Tcl_FindCommand(interp, "Y", NULL, TCL_GLOBAL_ONLY);
		/*fprintf(stderr, "... Y ==> %p\n", resolvedCmdPtr);*/
	    }
	}

        if (resolvedCmdPtr != NULL) {
            *rPtr = resolvedCmdPtr;
            return TCL_OK;
        }
	if (resolvedCmdPtr != NULL) {
	    *rPtr = resolvedCmdPtr;
	    return TCL_OK;
	}
    }
    return TCL_CONTINUE;
}

static int
InterpVarResolver(
    TCL_UNUSED(Tcl_Interp *),
    TCL_UNUSED(const char *),
    TCL_UNUSED(Tcl_Namespace *),
    TCL_UNUSED(int),
    TCL_UNUSED(int), /* flags */
    TCL_UNUSED(Tcl_Var *))
{
    /*
     * Don't resolve the variable; use standard rules.
     */

    return TCL_CONTINUE;
}

typedef struct MyResolvedVarInfo {
    Tcl_ResolvedVarInfo vInfo;  /* This must be the first element. */
    Tcl_Var var;
    Tcl_Obj *nameObj;
} MyResolvedVarInfo;

static inline void
HashVarFree(
    Tcl_Var var)
{
    if (VarHashRefCount(var) < 2) {
        Tcl_Free(var);
	Tcl_Free(var);
    } else {
        VarHashRefCount(var)--;
	VarHashRefCount(var)--;
    }
}

static void
MyCompiledVarFree(
    Tcl_ResolvedVarInfo *vInfoPtr)
{
    MyResolvedVarInfo *resVarInfo = (MyResolvedVarInfo *) vInfoPtr;

    Tcl_DecrRefCount(resVarInfo->nameObj);
    if (resVarInfo->var) {
        HashVarFree(resVarInfo->var);
	HashVarFree(resVarInfo->var);
    }
    Tcl_Free(vInfoPtr);
}

#define TclVarHashGetValue(hPtr) \
    ((Var *) ((char *)hPtr - offsetof(VarInHash, entry)))

static Tcl_Var
MyCompiledVarFetch(
    Tcl_Interp *interp,
    Tcl_ResolvedVarInfo *vinfoPtr)
{
    MyResolvedVarInfo *resVarInfo = (MyResolvedVarInfo *) vinfoPtr;
    Tcl_Var var = resVarInfo->var;
    int isNewVar;
    Interp *iPtr = (Interp *) interp;
    Tcl_HashEntry *hPtr;

    if (var != NULL) {
        if (!(((Var *) var)->flags & VAR_DEAD_HASH)) {
            /*
             * The cached variable is valid, return it.
             */
	if (!(((Var *) var)->flags & VAR_DEAD_HASH)) {
	    /*
	     * The cached variable is valid, return it.
	     */

            return var;
        }
	    return var;
	}

        /*
         * The variable is not valid anymore. Clean it up.
         */
	/*
	 * The variable is not valid anymore. Clean it up.
	 */

        HashVarFree(var);
	HashVarFree(var);
    }

    hPtr = Tcl_CreateHashEntry((Tcl_HashTable *) &iPtr->globalNsPtr->varTable,
            (char *) resVarInfo->nameObj, &isNewVar);
	    resVarInfo->nameObj, &isNewVar);
    if (hPtr) {
        var = (Tcl_Var) TclVarHashGetValue(hPtr);
	var = (Tcl_Var) TclVarHashGetValue(hPtr);
    } else {
        var = NULL;
	var = NULL;
    }
    resVarInfo->var = var;

    /*
     * Increment the reference counter to avoid Tcl_Free() of the variable in
     * Tcl's FreeVarEntry(); for cleanup, we provide our own HashVarFree();
     */

    VarHashRefCount(var)++;
    return var;
}

static int
InterpCompiledVarResolver(
    TCL_UNUSED(Tcl_Interp *),
    const char *name,
    TCL_UNUSED(int) /*length*/,
    TCL_UNUSED(Tcl_Size) /* length */,
    TCL_UNUSED(Tcl_Namespace *),
    Tcl_ResolvedVarInfo **rPtr)
{
    if (*name == 'T') {
 	MyResolvedVarInfo *resVarInfo = (MyResolvedVarInfo *)Tcl_Alloc(sizeof(MyResolvedVarInfo));
	MyResolvedVarInfo *resVarInfo = (MyResolvedVarInfo *)Tcl_Alloc(sizeof(MyResolvedVarInfo));

 	resVarInfo->vInfo.fetchProc = MyCompiledVarFetch;
 	resVarInfo->vInfo.deleteProc = MyCompiledVarFree;
 	resVarInfo->var = NULL;
 	resVarInfo->nameObj = Tcl_NewStringObj(name, -1);
 	Tcl_IncrRefCount(resVarInfo->nameObj);
 	*rPtr = &resVarInfo->vInfo;
 	return TCL_OK;
	resVarInfo->vInfo.fetchProc = MyCompiledVarFetch;
	resVarInfo->vInfo.deleteProc = MyCompiledVarFree;
	resVarInfo->var = NULL;
	resVarInfo->nameObj = Tcl_NewStringObj(name, -1);
	Tcl_IncrRefCount(resVarInfo->nameObj);
	*rPtr = &resVarInfo->vInfo;
	return TCL_OK;
    }
    return TCL_CONTINUE;
}

static int
TestInterpResolverCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    static const char *const table[] = {
        "down", "up", NULL
	"down", "up", NULL
    };
    int idx;
#define RESOLVER_KEY "testInterpResolver"

    if ((objc < 2) || (objc > 3)) {
	Tcl_WrongNumArgs(interp, 1, objv, "up|down ?interp?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	interp = Tcl_GetChild(interp, Tcl_GetString(objv[2]));
	if (interp == NULL) {
	    Tcl_AppendResult(interp, "provided interpreter not found", NULL);
	    Tcl_AppendResult(interp, "provided interpreter not found", (char *)NULL);
	    return TCL_ERROR;
	}
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], table, "operation", TCL_EXACT,
            &idx) != TCL_OK) {
        return TCL_ERROR;
	    &idx) != TCL_OK) {
	return TCL_ERROR;
    }
    switch (idx) {
    case 1: /* up */
        Tcl_AddInterpResolvers(interp, RESOLVER_KEY, InterpCmdResolver,
                InterpVarResolver, InterpCompiledVarResolver);
        break;
	Tcl_AddInterpResolvers(interp, RESOLVER_KEY, InterpCmdResolver,
		InterpVarResolver, InterpCompiledVarResolver);
	break;
    case 0: /*down*/
        if (!Tcl_RemoveInterpResolvers(interp, RESOLVER_KEY)) {
            Tcl_AppendResult(interp, "could not remove the resolver scheme",
                    NULL);
            return TCL_ERROR;
        }
	if (!Tcl_RemoveInterpResolvers(interp, RESOLVER_KEY)) {
	    Tcl_AppendResult(interp, "could not remove the resolver scheme",
		    (char *)NULL);
	    return TCL_ERROR;
	}
    }
    return TCL_OK;
}


/*
 *------------------------------------------------------------------------
 *
 * TestApplyLambdaCmd --
 *
 *	Implements the Tcl command testapplylambda. This tests the apply
 *	implementation handling of a lambda where the lambda has a list
 *	internal representation where the second element's internal
 *	representation is already a byte code object.
 *
 * Results:
 *	TCL_OK    - Success. Caller should check result is 42
 *	TCL_ERROR - Error.
 *
 * Side effects:
 *	In the presence of the apply bug, may panic. Otherwise
 *	Interpreter result holds result or error message.
 *
 *------------------------------------------------------------------------
 */
int TestApplyLambdaCmd (
    TCL_UNUSED(void*),
    Tcl_Interp *interp,    /* Current interpreter. */
    TCL_UNUSED(int),       /* objc. */
    TCL_UNUSED(Tcl_Obj *const *)) /* objv. */
{
    Tcl_Obj *lambdaObjs[2];
    Tcl_Obj *evalObjs[2];
    Tcl_Obj *lambdaObj;
    int result;

    /* Create a lambda {{} {set a 42}} */
    lambdaObjs[0] = Tcl_NewObj(); /* No parameters */
    lambdaObjs[1] = Tcl_NewStringObj("set a 42", -1); /* Body */
    lambdaObj = Tcl_NewListObj(2, lambdaObjs);
    Tcl_IncrRefCount(lambdaObj);

    /* Create the command "apply {{} {set a 42}" */
    evalObjs[0] = Tcl_NewStringObj("apply", -1);
    Tcl_IncrRefCount(evalObjs[0]);
    /*
     * NOTE: IMPORTANT TO EXHIBIT THE BUG. We duplicate the lambda because
     * it will get shimmered to a Lambda internal representation but we
     * want to hold on to our list representation.
     */
    evalObjs[1] = Tcl_DuplicateObj(lambdaObj);
    Tcl_IncrRefCount(evalObjs[1]);

    /* Evaluate it */
    result = Tcl_EvalObjv(interp, 2, evalObjs, TCL_EVAL_GLOBAL);
    if (result != TCL_OK) {
	Tcl_DecrRefCount(evalObjs[0]);
	Tcl_DecrRefCount(evalObjs[1]);
	return result;
    }
    /*
     * So far so good. At this point,
     * - evalObjs[1] has an internal representation of Lambda
     * - lambdaObj[1] ({set a 42}) has been shimmered to
     * an internal representation of ByteCode.
     */
    Tcl_DecrRefCount(evalObjs[1]); /* Don't need this anymore */
    /*
     * The bug trigger. Repeating the command but:
     *  - we are calling apply with a lambda that is a list (as BEFORE),
     *    BUT
     *  - The body of the lambda (lambdaObjs[1]) ALREADY has internal
     *    representation of ByteCode and thus will not be compiled again
     */
    evalObjs[1] = lambdaObj; /* lambdaObj already has a ref count so no need for IncrRef */
    result = Tcl_EvalObjv(interp, 2, evalObjs, TCL_EVAL_GLOBAL);
    Tcl_DecrRefCount(evalObjs[0]);
    Tcl_DecrRefCount(lambdaObj);

    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TestLutilCmd --
 *
 *	This procedure implements the "testlequal" command. It is used to
 *	test compare two lists for equality using the string representation
 *      of each element. Implemented in C because script level loops are
 *	too slow for comparing large (GB count) lists.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestLutilCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Arguments. */
{
    Tcl_Size nL1, nL2;
    Tcl_Obj *l1Obj = NULL;
    Tcl_Obj *l2Obj = NULL;
    Tcl_Obj **l1Elems;
    Tcl_Obj **l2Elems;
    static const char *const subcmds[] = {
	   "equal", "diffindex", NULL
    };
    enum options {
	   LUTIL_EQUAL, LUTIL_DIFFINDEX
    } idx;

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "list1 list2");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], subcmds, "option", 0,
	    &idx) != TCL_OK) {
	return TCL_ERROR;
    }

    /* Protect against shimmering, just to be safe */
    l1Obj = Tcl_DuplicateObj(objv[2]);
    l2Obj = Tcl_DuplicateObj(objv[3]);

    int ret = TCL_ERROR;
    if (Tcl_ListObjGetElements(interp, l1Obj, &nL1, &l1Elems) != TCL_OK) {
	goto vamoose;
    }
    if (Tcl_ListObjGetElements(interp, l2Obj, &nL2, &l2Elems) != TCL_OK) {
	goto vamoose;
    }

    Tcl_Size i, nCmp;

    ret = TCL_OK;
    switch (idx) {
    case LUTIL_EQUAL:
	/* Avoid the loop below if lengths differ */
	if (nL1 != nL2) {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
	    break;
	}
	/* FALLTHRU */
    case LUTIL_DIFFINDEX:
	nCmp = nL1 <= nL2 ? nL1 : nL2;
	for (i = 0; i < nCmp; ++i) {
	    if (strcmp(Tcl_GetString(l1Elems[i]), Tcl_GetString(l2Elems[i]))) {
		break;
	    }
	}
	if (i == nCmp && nCmp == nL1 && nCmp == nL2) {
	    nCmp = idx == LUTIL_EQUAL ? 1 : -1;
	} else {
	    nCmp = idx == LUTIL_EQUAL ? 0 : i;
	}
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nCmp));
	break;
    }

vamoose:
    if (l1Obj) {
	Tcl_DecrRefCount(l1Obj);
    }
    if (l2Obj) {
	Tcl_DecrRefCount(l2Obj);
    }
    return ret;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * tab-width: 8
 * indent-tabs-mode: nil
 * End:
 */

Added generic/tclTestABSList.c.









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
// Tcl Abstract List test command: "lstring"

#undef BUILD_tcl
#undef STATIC_BUILD
#ifndef USE_TCL_STUBS
#   define USE_TCL_STUBS
#endif
#include <string.h>
#include <limits.h>
#include "tclInt.h"

/*
 * Forward references
 */

Tcl_Obj *myNewLStringObj(Tcl_WideInt start,
			 Tcl_WideInt length);
static void freeRep(Tcl_Obj* alObj);
static Tcl_Obj* my_LStringObjSetElem(Tcl_Interp *interp,
				     Tcl_Obj *listPtr,
				     Tcl_Size numIndcies,
				     Tcl_Obj *const indicies[],
				     Tcl_Obj *valueObj);
static void DupLStringRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
static Tcl_Size my_LStringObjLength(Tcl_Obj *lstringObjPtr);
static int my_LStringObjIndex(Tcl_Interp *interp,
			      Tcl_Obj *lstringObj,
			      Tcl_Size index,
			      Tcl_Obj **charObjPtr);
static int my_LStringObjRange(Tcl_Interp *interp, Tcl_Obj *lstringObj,
			      Tcl_Size fromIdx, Tcl_Size toIdx,
			      Tcl_Obj **newObjPtr);
static int my_LStringObjReverse(Tcl_Interp *interp, Tcl_Obj *srcObj,
			  Tcl_Obj **newObjPtr);
static int my_LStringReplace(Tcl_Interp *interp,
		      Tcl_Obj *listObj,
		      Tcl_Size first,
		      Tcl_Size numToDelete,
		      Tcl_Size numToInsert,
		      Tcl_Obj *const insertObjs[]);
static int my_LStringGetElements(Tcl_Interp *interp,
				 Tcl_Obj *listPtr,
				 Tcl_Size *objcptr,
				 Tcl_Obj ***objvptr);
static void lstringFreeElements(Tcl_Obj* lstringObj);
static void UpdateStringOfLString(Tcl_Obj *objPtr);

/*
 * Internal Representation of an lstring type value
 */

typedef struct LString {
    char *string;	// NULL terminated utf-8 string
    Tcl_Size strlen;	// num bytes in string
    Tcl_Size allocated; // num bytes allocated
    Tcl_Obj**elements;	// elements array, allocated when GetElements is
			// called
} LString;

/*
 * AbstractList definition of an lstring type
 */
static const Tcl_ObjType lstringTypes[11] = {
    {/*0*/
	"lstring",
	freeRep,
	DupLStringRep,
	UpdateStringOfLString,
	NULL,
	TCL_OBJTYPE_V2(
	    my_LStringObjLength,   /* Length */
	    my_LStringObjIndex,    /* Index */
	    my_LStringObjRange,    /* Slice */
	    my_LStringObjReverse,  /* Reverse */
	    my_LStringGetElements, /* GetElements */
	    my_LStringObjSetElem,  /* SetElement */
	    my_LStringReplace,     /* Replace */
	    NULL)                  /* "in" operator */
	},
    {/*1*/
	"lstring",
	freeRep,
	DupLStringRep,
	UpdateStringOfLString,
	NULL,
	TCL_OBJTYPE_V2(
	    NULL,   /* Length */
	    my_LStringObjIndex,    /* Index */
	    my_LStringObjRange,    /* Slice */
	    my_LStringObjReverse,  /* Reverse */
	    my_LStringGetElements, /* GetElements */
	    my_LStringObjSetElem,  /* SetElement */
	    my_LStringReplace,     /* Replace */
	    NULL)                  /* "in" operator */
    },
    {/*2*/
	"lstring",
	freeRep,
	DupLStringRep,
	UpdateStringOfLString,
	NULL,
	TCL_OBJTYPE_V2(
	    my_LStringObjLength,   /* Length */
	    NULL,                  /* Index */
	    my_LStringObjRange,    /* Slice */
	    my_LStringObjReverse,  /* Reverse */
	    my_LStringGetElements, /* GetElements */
	    my_LStringObjSetElem,  /* SetElement */
	    my_LStringReplace,     /* Replace */
	    NULL)                  /* "in" operator */
    },
    {/*3*/
	"lstring",
	freeRep,
	DupLStringRep,
	UpdateStringOfLString,
	NULL,
	TCL_OBJTYPE_V2(
	    my_LStringObjLength,   /* Length */
	    my_LStringObjIndex,    /* Index */
	    NULL,                  /* Slice */
	    my_LStringObjReverse,  /* Reverse */
	    my_LStringGetElements, /* GetElements */
	    my_LStringObjSetElem,  /* SetElement */
	    my_LStringReplace,     /* Replace */
	    NULL)                  /* "in" operator */
    },
    {/*4*/
	"lstring",
	freeRep,
	DupLStringRep,
	UpdateStringOfLString,
	NULL,
	TCL_OBJTYPE_V2(
	    my_LStringObjLength,   /* Length */
	    my_LStringObjIndex,    /* Index */
	    my_LStringObjRange,    /* Slice */
	    NULL,                  /* Reverse */
	    my_LStringGetElements, /* GetElements */
	    my_LStringObjSetElem,  /* SetElement */
	    my_LStringReplace,     /* Replace */
	    NULL)                  /* "in" operator */
    },
    {/*5*/
	"lstring",
	freeRep,
	DupLStringRep,
	UpdateStringOfLString,
	NULL,
	TCL_OBJTYPE_V2(
	    my_LStringObjLength,   /* Length */
	    my_LStringObjIndex,    /* Index */
	    my_LStringObjRange,    /* Slice */
	    my_LStringObjReverse,  /* Reverse */
	    NULL,                  /* GetElements */
	    my_LStringObjSetElem,  /* SetElement */
	    my_LStringReplace,     /* Replace */
	    NULL)                  /* "in" operator */
    },
    {/*6*/
	"lstring",
	freeRep,
	DupLStringRep,
	UpdateStringOfLString,
	NULL,
	TCL_OBJTYPE_V2(
	    my_LStringObjLength,   /* Length */
	    my_LStringObjIndex,    /* Index */
	    my_LStringObjRange,    /* Slice */
	    my_LStringObjReverse,  /* Reverse */
	    my_LStringGetElements, /* GetElements */
	    NULL,                  /* SetElement */
	    my_LStringReplace,     /* Replace */
	    NULL)                  /* "in" operator */
    },
    {/*7*/
	"lstring",
	freeRep,
	DupLStringRep,
	UpdateStringOfLString,
	NULL,
	TCL_OBJTYPE_V2(
	    my_LStringObjLength,   /* Length */
	    my_LStringObjIndex,    /* Index */
	    my_LStringObjRange,    /* Slice */
	    my_LStringObjReverse,  /* Reverse */
	    my_LStringGetElements, /* GetElements */
	    my_LStringObjSetElem,  /* SetElement */
	    NULL,                  /* Replace */
	    NULL)                  /* "in" operator */
    },
    {/*8*/
	"lstring",
	freeRep,
	DupLStringRep,
	UpdateStringOfLString,
	NULL,
	TCL_OBJTYPE_V2(
	    my_LStringObjLength,   /* Length */
	    my_LStringObjIndex,    /* Index */
	    my_LStringObjRange,    /* Slice */
	    my_LStringObjReverse,  /* Reverse */
	    my_LStringGetElements, /* GetElements */
	    my_LStringObjSetElem,  /* SetElement */
	    my_LStringReplace,     /* Replace */
	    NULL)                  /* "in" operator */
    },
    {/*9*/
	"lstring",
	freeRep,
	DupLStringRep,
	UpdateStringOfLString,
	NULL,
	TCL_OBJTYPE_V2(
	    my_LStringObjLength,   /* Length */
	    my_LStringObjIndex,    /* Index */
	    my_LStringObjRange,    /* Slice */
	    my_LStringObjReverse,  /* Reverse */
	    my_LStringGetElements, /* GetElements */
	    my_LStringObjSetElem,  /* SetElement */
	    my_LStringReplace,     /* Replace */
	    NULL)                  /* "in" operator */
    },
    {/*10*/
	"lstring",
	freeRep,
	DupLStringRep,
	UpdateStringOfLString,
	NULL,
	TCL_OBJTYPE_V2(
	    my_LStringObjLength,   /* Length */
	    my_LStringObjIndex,    /* Index */
	    my_LStringObjRange,    /* Slice */
	    my_LStringObjReverse,  /* Reverse */
	    my_LStringGetElements, /* GetElements */
	    my_LStringObjSetElem,  /* SetElement */
	    my_LStringReplace,     /* Replace */
	    NULL)                  /* "in" operator */
    }
};


/*
 *----------------------------------------------------------------------
 *
 * my_LStringObjIndex --
 *
 *	Implements the AbstractList Index function for the lstring type.  The
 *	Index function returns the value at the index position given. Caller
 *	is resposible for freeing the Obj.
 *
 * Results:
 *	TCL_OK on success. Returns a new Obj, with a 0 refcount in the
 *	supplied charObjPtr location. Call has ownership of the Obj.
 *
 * Side effects:
 *	Obj allocated.
 *
 *----------------------------------------------------------------------
 */

static int
my_LStringObjIndex(
    Tcl_Interp *interp,
    Tcl_Obj *lstringObj,
    Tcl_Size index,
    Tcl_Obj **charObjPtr)
{
    LString *lstringRepPtr = (LString*)lstringObj->internalRep.twoPtrValue.ptr1;

  (void)interp;

  if (index < lstringRepPtr->strlen) {
      char cchar[2];
      cchar[0] = lstringRepPtr->string[index];
      cchar[1] = 0;
      *charObjPtr = Tcl_NewStringObj(cchar,1);
  } else {
      *charObjPtr = NULL;
  }

  return TCL_OK;
}


/*
 *----------------------------------------------------------------------
 *
 * my_LStringObjLength --
 *
 *	Implements the AbstractList Length function for the lstring type.
 *	The Length function returns the number of elements in the list.
 *
 * Results:
 *	WideInt number of elements in the list.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Size
my_LStringObjLength(Tcl_Obj *lstringObjPtr)
{
    LString *lstringRepPtr = (LString *)lstringObjPtr->internalRep.twoPtrValue.ptr1;
    return lstringRepPtr->strlen;
}


/*
 *----------------------------------------------------------------------
 *
 * DupLStringRep --
 *
 *	Replicates the internal representation of the src value, and storing
 *	it in the copy
 *
 * Results:
 *	void
 *
 * Side effects:
 *	Modifies the rep of the copyObj.
 *
 *----------------------------------------------------------------------
 */

static void
DupLStringRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr)
{
  LString *srcLString = (LString*)srcPtr->internalRep.twoPtrValue.ptr1;
  LString *copyLString = (LString*)Tcl_Alloc(sizeof(LString));

  memcpy(copyLString, srcLString, sizeof(LString));
  copyLString->string = (char*)Tcl_Alloc(srcLString->allocated);
  strncpy(copyLString->string, srcLString->string, srcLString->strlen);
  copyLString->string[srcLString->strlen] = '\0';
  copyLString->elements = NULL;
  Tcl_ObjInternalRep itr;
  itr.twoPtrValue.ptr1 = copyLString;
  itr.twoPtrValue.ptr2 = NULL;
  Tcl_StoreInternalRep(copyPtr, srcPtr->typePtr, &itr);

  return;
}

/*
 *----------------------------------------------------------------------
 *
 * my_LStringObjSetElem --
 *
 *	Replace the element value at the given (nested) index with the
 *	valueObj provided.  If the lstring obj is shared, a new list is
 *	created conntaining the modifed element.
 *
 * Results:
 *	The modifed lstring is returned, either new or original. If the
 *	index is invalid, NULL is returned, and an error is added to the
 *	interp, if provided.
 *
 * Side effects:
 *	A new obj may be created.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Obj*
my_LStringObjSetElem(
    Tcl_Interp *interp,
    Tcl_Obj *lstringObj,
    Tcl_Size numIndicies,
    Tcl_Obj *const indicies[],
    Tcl_Obj *valueObj)
{
    LString *lstringRepPtr = (LString*)lstringObj->internalRep.twoPtrValue.ptr1;
    Tcl_Size index;
    int status;
    Tcl_Obj *returnObj;

    if (numIndicies > 1) {
	Tcl_SetObjResult(interp,
	    Tcl_ObjPrintf("Multiple indicies not supported by lstring."));
	return NULL;
    }

    status = Tcl_GetIntForIndex(interp, indicies[0], lstringRepPtr->strlen, &index);
    if (status != TCL_OK) {
	return NULL;
    }

    returnObj = Tcl_IsShared(lstringObj) ? Tcl_DuplicateObj(lstringObj) : lstringObj;
    lstringRepPtr = (LString*)returnObj->internalRep.twoPtrValue.ptr1;

    if (index >= lstringRepPtr->strlen) {
	index = lstringRepPtr->strlen;
	lstringRepPtr->strlen++;
	lstringRepPtr->string = (char*)Tcl_Realloc(lstringRepPtr->string, lstringRepPtr->strlen+1);
    }

    if (valueObj) {
	const char newvalue = Tcl_GetString(valueObj)[0];
	lstringRepPtr->string[index] = newvalue;
    } else if (index < lstringRepPtr->strlen) {
	/* Remove the char by sliding the tail of the string down */
	char *sptr = &lstringRepPtr->string[index];
	/* This is an overlapping copy, by definition */
	lstringRepPtr->strlen--;
	memmove(sptr, (sptr+1), (lstringRepPtr->strlen - index));
    }
    // else do nothing

    Tcl_InvalidateStringRep(returnObj);

    return returnObj;
}

/*
 *----------------------------------------------------------------------
 *
 * my_LStringObjRange --
 *
 *	Creates a new Obj with a slice of the src listPtr.
 *
 * Results:
 *	A new Obj is assigned to newObjPtr. Returns TCL_OK
 *
 * Side effects:
 *	A new Obj is created.
 *
 *----------------------------------------------------------------------
 */

static int my_LStringObjRange(
    Tcl_Interp *interp,
    Tcl_Obj *lstringObj,
    Tcl_Size fromIdx,
    Tcl_Size toIdx,
    Tcl_Obj **newObjPtr)
{
    Tcl_Obj *rangeObj;
    LString *lstringRepPtr = (LString*)lstringObj->internalRep.twoPtrValue.ptr1;
    LString *rangeRep;
    Tcl_WideInt len = toIdx - fromIdx + 1;

    if (lstringRepPtr->strlen < fromIdx ||
	lstringRepPtr->strlen < toIdx) {
	Tcl_SetObjResult(interp,
	    Tcl_ObjPrintf("Range out of bounds "));
	return TCL_ERROR;
    }

    if (len <= 0) {
	// Return empty value;
	*newObjPtr = Tcl_NewObj();
    } else {
	rangeRep = (LString*)Tcl_Alloc(sizeof(LString));
	rangeRep->allocated = len+1;
	rangeRep->strlen = len;
	rangeRep->string = (char*)Tcl_Alloc(rangeRep->allocated);
	strncpy(rangeRep->string,&lstringRepPtr->string[fromIdx],len);
	rangeRep->string[len] = 0;
	rangeRep->elements = NULL;
	rangeObj = Tcl_NewObj();
	Tcl_ObjInternalRep itr;
	itr.twoPtrValue.ptr1 = rangeRep;
	itr.twoPtrValue.ptr2 = NULL;
	Tcl_StoreInternalRep(rangeObj, lstringObj->typePtr, &itr);
	if (rangeRep->strlen > 0) {
	    Tcl_InvalidateStringRep(rangeObj);
	} else {
	    Tcl_InitStringRep(rangeObj, NULL, 0);
	}
	*newObjPtr = rangeObj;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * my_LStringObjReverse --
 *
 *	Creates a new Obj with the order of the elements in the lstring
 *	value reversed, where first is last and last is first, etc.
 *
 * Results:
 *	A new Obj is assigned to newObjPtr. Returns TCL_OK
 *
 * Side effects:
 *	A new Obj is created.
 *
 *----------------------------------------------------------------------
 */

static int
my_LStringObjReverse(Tcl_Interp *interp, Tcl_Obj *srcObj, Tcl_Obj **newObjPtr)
{
    LString *srcRep = (LString*)srcObj->internalRep.twoPtrValue.ptr1;
    Tcl_Obj *revObj;
    LString *revRep = (LString*)Tcl_Alloc(sizeof(LString));
    Tcl_ObjInternalRep itr;
    Tcl_Size len;
    char *srcp, *dstp, *endp;
    (void)interp;
    len = srcRep->strlen;
    revRep->strlen = len;
    revRep->allocated = len+1;
    revRep->string = (char*)Tcl_Alloc(revRep->allocated);
    revRep->elements = NULL;
    srcp = srcRep->string;
    endp = &srcRep->string[len];
    dstp = &revRep->string[len];
    *dstp-- = 0;
    while (srcp < endp) {
	*dstp-- = *srcp++;
    }
    revObj = Tcl_NewObj();
    itr.twoPtrValue.ptr1 = revRep;
    itr.twoPtrValue.ptr2 = NULL;
    Tcl_StoreInternalRep(revObj, srcObj->typePtr, &itr);
    if (revRep->strlen > 0) {
	Tcl_InvalidateStringRep(revObj);
    } else {
	Tcl_InitStringRep(revObj, NULL, 0);
    }
    *newObjPtr = revObj;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * my_LStringReplace --
 *
 *	Delete and/or Insert elements in the list, starting at index first.
 *	See more details in the comments below. This should not be called with
 *	a Shared Obj.
 *
 * Results:
 *	The value of the listObj is modified.
 *
 * Side effects:
 *	The string rep is invalidated.
 *
 *----------------------------------------------------------------------
 */

static int
my_LStringReplace(
    Tcl_Interp *interp,
    Tcl_Obj *listObj,
    Tcl_Size first,
    Tcl_Size numToDelete,
    Tcl_Size numToInsert,
    Tcl_Obj *const insertObjs[])
{
    LString *lstringRep = (LString*)listObj->internalRep.twoPtrValue.ptr1;
    Tcl_Size newLen;
    Tcl_Size x, ix, kx;
    char *newStr;
    char *oldStr = lstringRep->string;
    (void)interp;

    newLen = lstringRep->strlen - numToDelete + numToInsert;

    if (newLen >= lstringRep->allocated) {
	lstringRep->allocated = newLen+1;
	newStr = (char*)Tcl_Alloc(lstringRep->allocated);
	newStr[newLen] = 0;
    } else {
	newStr = oldStr;
    }

    /* Tcl_ListObjReplace replaces zero or more elements of the list
     * referenced by listPtr with the objc values in the array referenced by
     * objv.
     *
     * If listPtr does not point to a list value, Tcl_ListObjReplace
     * will attempt to convert it to one; if the conversion fails, it returns
     * TCL_ERROR and leaves an error message in the interpreter's result value
     * if interp is not NULL. Otherwise, it returns TCL_OK after replacing the
     * values.
     *
     *    * If objv is NULL, no new elements are added.
     *
     *    * If the argument first is zero or negative, it refers to the first
     *      element.
     *
     *    * If first is greater than or equal to the number of elements in the
     *      list, then no elements are deleted; the new elements are appended
     *      to the list. count gives the number of elements to replace.
     *
     *    * If count is zero or negative then no elements are deleted; the new
     *      elements are simply inserted before the one designated by first.
     *      Tcl_ListObjReplace invalidates listPtr's old string representation.
     *
     *    * The reference counts of any elements inserted from objv are
     *      incremented since the resulting list now refers to them. Similarly,
     *      the reference counts for any replaced values are decremented.
     */

    // copy 0 to first-1
    if (newStr != oldStr) {
	strncpy(newStr, oldStr, first);
    }

    // move front elements to keep
    for(x=0, kx=0; x<newLen && kx<first; kx++, x++) {
	newStr[x] = oldStr[kx];
    }
    // Insert new elements into new string
    for(x=first, ix=0; ix<numToInsert; x++, ix++) {
	char const *svalue = Tcl_GetString(insertObjs[ix]);
	newStr[x] = svalue[0];
    }
    // Move remaining elements
    if ((first+numToDelete) < newLen) {
	for(/*x,*/ kx=first+numToDelete; (kx <lstringRep->strlen && x<newLen); x++, kx++) {
	    newStr[x] = oldStr[kx];
	}
    }

    // Terminate new string.
    newStr[newLen] = 0;


    if (oldStr != newStr) {
	Tcl_Free(oldStr);
    }
    lstringRep->string = newStr;
    lstringRep->strlen = newLen;

    /* Changes made to value, string rep and elements array no longer valid */
    Tcl_InvalidateStringRep(listObj);
    lstringFreeElements(listObj);

    return TCL_OK;
}

static const Tcl_ObjType *
my_SetAbstractProc(int ptype)
{
    const Tcl_ObjType *typePtr = &lstringTypes[0]; /* default value */
    if (4 <= ptype && ptype <= 11) {
	/* Table has no entries for the slots upto setfromany */
	typePtr = &lstringTypes[(ptype-3)];
    }
    return typePtr;
}


/*
 *----------------------------------------------------------------------
 *
 * my_NewLStringObj --
 *
 *	Creates a new lstring Obj using the string value of objv[0]
 *
 * Results:
 *	results
 *
 * Side effects:
 *	side effects
 *
 *----------------------------------------------------------------------
 */

static Tcl_Obj *
my_NewLStringObj(
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj * const objv[])
{
    LString *lstringRepPtr;
    Tcl_ObjInternalRep itr;
    size_t repSize;
    Tcl_Obj *lstringPtr;
    const char *string;
    static const char* procTypeNames[] = {
	"FREEREP", "DUPREP", "UPDATESTRING", "SETFROMANY",
	"LENGTH", "INDEX", "SLICE", "REVERSE", "GETELEMENTS",
	"SETELEMENT", "REPLACE", NULL
    };
    int i = 0;
    int ptype;
    const Tcl_ObjType *lstringTypePtr = &lstringTypes[10];

    repSize = sizeof(LString);
    lstringRepPtr = (LString*)Tcl_Alloc(repSize);

    while (i<objc) {
	const char *s = Tcl_GetString(objv[i]);
	if (strcmp(s, "-not")==0) {
	    i++;
	    if (Tcl_GetIndexFromObj(interp, objv[i], procTypeNames, "proctype", 0, &ptype)==TCL_OK) {
		lstringTypePtr = my_SetAbstractProc(ptype);
	    }
	} else if (strcmp(s, "--") == 0) {
	    // End of options
	    i++;
	    break;
	} else {
	    break;
	}
	i++;
    }
    if (i != objc-1) {
	Tcl_Free((char*)lstringRepPtr);
	Tcl_WrongNumArgs(interp, 0, objv, "lstring string");
	return NULL;
    }
    string = Tcl_GetString(objv[i]);

    lstringRepPtr->strlen = strlen(string);
    lstringRepPtr->allocated = lstringRepPtr->strlen + 1;
    lstringRepPtr->string = (char*)Tcl_Alloc(lstringRepPtr->allocated);
    strcpy(lstringRepPtr->string, string);
    lstringRepPtr->elements = NULL;
    lstringPtr = Tcl_NewObj();
    itr.twoPtrValue.ptr1 = lstringRepPtr;
    itr.twoPtrValue.ptr2 = NULL;
    Tcl_StoreInternalRep(lstringPtr, lstringTypePtr, &itr);
    if (lstringRepPtr->strlen > 0) {
	Tcl_InvalidateStringRep(lstringPtr);
    } else {
	Tcl_InitStringRep(lstringPtr, NULL, 0);
    }
    return lstringPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * freeElements --
 *
 *      Free the element array
 *
 */

static void
lstringFreeElements(Tcl_Obj* lstringObj)
{
    LString *lstringRepPtr = (LString*)lstringObj->internalRep.twoPtrValue.ptr1;
    if (lstringRepPtr->elements) {
	Tcl_Obj **objptr = lstringRepPtr->elements;
	while (objptr < &lstringRepPtr->elements[lstringRepPtr->strlen]) {
	    Tcl_DecrRefCount(*objptr++);
	}
	Tcl_Free((char*)lstringRepPtr->elements);
	lstringRepPtr->elements = NULL;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * freeRep --
 *
 *	Free the value storage of the lstring Obj.
 *
 * Results:
 *	void
 *
 * Side effects:
 *	Memory free'd.
 *
 *----------------------------------------------------------------------
 */

static void
freeRep(Tcl_Obj* lstringObj)
{
    LString *lstringRepPtr = (LString*)lstringObj->internalRep.twoPtrValue.ptr1;
    if (lstringRepPtr->string) {
	Tcl_Free(lstringRepPtr->string);
    }
    lstringFreeElements(lstringObj);
    Tcl_Free((char*)lstringRepPtr);
    lstringObj->internalRep.twoPtrValue.ptr1 = NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * my_LStringGetElements --
 *
 *	Get the elements of the list in an array.
 *
 * Results:
 *	objc, objv return values
 *
 * Side effects:
 *	A Tcl_Obj is stored for every element of the abstract list
 *
 *----------------------------------------------------------------------
 */

static int my_LStringGetElements(Tcl_Interp *interp,
				 Tcl_Obj *lstringObj,
				 Tcl_Size *objcptr,
				 Tcl_Obj ***objvptr)
{
    LString *lstringRepPtr = (LString*)lstringObj->internalRep.twoPtrValue.ptr1;
    Tcl_Obj **objPtr;
    char *cptr = lstringRepPtr->string;
    (void)interp;
    if (lstringRepPtr->strlen == 0) {
	*objcptr = 0;
	*objvptr = NULL;
	return TCL_OK;
    }
    if (lstringRepPtr->elements == NULL) {
	lstringRepPtr->elements = (Tcl_Obj**)Tcl_Alloc(sizeof(Tcl_Obj*) * lstringRepPtr->strlen);
	objPtr=lstringRepPtr->elements;
	while (objPtr < &lstringRepPtr->elements[lstringRepPtr->strlen]) {
	    *objPtr = Tcl_NewStringObj(cptr++,1);
	    Tcl_IncrRefCount(*objPtr++);
	}
    }
    *objvptr = lstringRepPtr->elements;
    *objcptr = lstringRepPtr->strlen;
    return TCL_OK;
}

/*
** UpdateStringRep
*/

static void
UpdateStringOfLString(Tcl_Obj *objPtr)
{
#   define LOCAL_SIZE 64
    int localFlags[LOCAL_SIZE], *flagPtr = NULL;
    Tcl_ObjType const *typePtr = objPtr->typePtr;
    char *p;
    int bytesNeeded = 0;
    int llen, i;


    /*
     * Handle empty list case first, so rest of the routine is simpler.
     */
    llen = typePtr->lengthProc(objPtr);
    if (llen <= 0) {
	Tcl_InitStringRep(objPtr, NULL, 0);
	return;
    }

    /*
     * Pass 1: estimate space.
     */
    if (llen <= LOCAL_SIZE) {
	flagPtr = localFlags;
    } else {
	/* We know numElems <= LIST_MAX, so this is safe. */
	flagPtr = (int *) Tcl_Alloc(llen*sizeof(int));
    }
    for (bytesNeeded = 0, i = 0; i < llen; i++) {
	Tcl_Obj *elemObj;
	const char *elemStr;
	Tcl_Size elemLen;
	flagPtr[i] = (i ? TCL_DONT_QUOTE_HASH : 0);
	typePtr->indexProc(NULL, objPtr, i, &elemObj);
	Tcl_IncrRefCount(elemObj);
	elemStr = Tcl_GetStringFromObj(elemObj, &elemLen);
	/* Note TclScanElement updates flagPtr[i] */
	bytesNeeded += Tcl_ScanCountedElement(elemStr, elemLen, &flagPtr[i]);
	if (bytesNeeded < 0) {
	    Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
	}
	Tcl_DecrRefCount(elemObj);
    }
    if (bytesNeeded > INT_MAX - llen + 1) {
	Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
    }
    bytesNeeded += llen; /* Separating spaces and terminating nul */

    /*
     * Pass 2: generate the string repr.
     */
    objPtr->bytes = (char *) Tcl_Alloc(bytesNeeded);
    p = objPtr->bytes;
    for (i = 0; i < llen; i++) {
	Tcl_Obj *elemObj;
	const char *elemStr;
	Tcl_Size elemLen;
	flagPtr[i] |= (i ? TCL_DONT_QUOTE_HASH : 0);
	typePtr->indexProc(NULL, objPtr, i, &elemObj);
	Tcl_IncrRefCount(elemObj);
	elemStr = Tcl_GetStringFromObj(elemObj, &elemLen);
	p += Tcl_ConvertCountedElement(elemStr, elemLen, p, flagPtr[i]);
	*p++ = ' ';
	Tcl_DecrRefCount(elemObj);
    }
    p[-1] = '\0'; /* Overwrite last space added */

    /* Length of generated string */
    objPtr->length = p - 1 - objPtr->bytes;

    if (flagPtr != localFlags) {
	Tcl_Free(flagPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * lLStringObjCmd --
 *
 *	Script level command that creats an lstring Obj value.
 *
 * Results:
 *	Returns and lstring Obj value in the interp results.
 *
 * Side effects:
 *	Interp results modified.
 *
 *----------------------------------------------------------------------
 */

static int
lLStringObjCmd(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj * const objv[])
{
  Tcl_Obj *lstringObj;

  (void)clientData;
  if (objc < 2) {
      Tcl_WrongNumArgs(interp, 1, objv, "string");
      return TCL_ERROR;
  }

  lstringObj = my_NewLStringObj(interp, objc-1, &objv[1]);

  if (lstringObj) {
      Tcl_SetObjResult(interp, lstringObj);
      return TCL_OK;
  }
  return TCL_ERROR;
}

/*
** lgen - Derived from TIP 192 - Lazy Lists
** Generate a list using a command provided as argument(s).
** The command computes the value for a given index.
*/

/*
 * Internal rep for the Generate Series
 */
typedef struct LgenSeries {
    Tcl_Interp *interp; // used to evaluate gen script
    Tcl_Size len;       // list length
    Tcl_Size nargs;     // Number of arguments in genFn including "index"
    Tcl_Obj *genFnObj;  // The preformed command as a list. Index is set in
			// the last element (last argument)
} LgenSeries;

/*
 * Evaluate the generation function.
 * The provided funtion computes the value for a give index
 */
static Tcl_Obj*
lgen(
    Tcl_Obj* objPtr,
    Tcl_Size index)
{
    LgenSeries *lgenSeriesPtr = (LgenSeries*)objPtr->internalRep.twoPtrValue.ptr1;
    Tcl_Obj *elemObj = NULL;
    Tcl_Interp *intrp = lgenSeriesPtr->interp;
    Tcl_Obj *genCmd = lgenSeriesPtr->genFnObj;
    Tcl_Size endidx = lgenSeriesPtr->nargs-1;

    if (0 <= index && index < lgenSeriesPtr->len) {
	Tcl_Obj *indexObj = Tcl_NewWideIntObj(index);
	Tcl_ListObjReplace(intrp, genCmd, endidx, 1, 1, &indexObj);
	// EVAL DIRECT to avoid interfering with bytecode compile which may be
	// active on the stack
	int flags = TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT;
	int status = Tcl_EvalObjEx(intrp, genCmd, flags);
	elemObj = Tcl_GetObjResult(intrp);
	if (status != TCL_OK) {
	    Tcl_SetObjResult(intrp, Tcl_ObjPrintf(
		"Error: %s\nwhile executing %s\n",
		elemObj ? Tcl_GetString(elemObj) : "NULL", Tcl_GetString(genCmd)));
	    return NULL;
	}
    }
    return elemObj;
}

/*
 *  Abstract List Length function
 */
static Tcl_Size
lgenSeriesObjLength(Tcl_Obj *objPtr)
{
    LgenSeries *lgenSeriesRepPtr = (LgenSeries *)objPtr->internalRep.twoPtrValue.ptr1;
    return lgenSeriesRepPtr->len;
}

/*
 *  Abstract List Index function
 */
static int
lgenSeriesObjIndex(
    Tcl_Interp *interp,
    Tcl_Obj *lgenSeriesObjPtr,
    Tcl_Size index,
    Tcl_Obj **elemPtr)
{
    LgenSeries *lgenSeriesRepPtr;
    Tcl_Obj *element;

    lgenSeriesRepPtr = (LgenSeries*)lgenSeriesObjPtr->internalRep.twoPtrValue.ptr1;

    if (index < 0 || index >= lgenSeriesRepPtr->len) {
	*elemPtr = NULL;
	return TCL_OK;
    }
    if (lgenSeriesRepPtr->interp == NULL && interp == NULL) {
	return TCL_ERROR;
    }

    lgenSeriesRepPtr->interp = interp;

    element = lgen(lgenSeriesObjPtr, index);
    if (element) {
	*elemPtr = element;
    } else {
	return TCL_ERROR;
    }

    return TCL_OK;
}

/*
** UpdateStringRep
*/

static void
UpdateStringOfLgen(Tcl_Obj *objPtr)
{
    LgenSeries *lgenSeriesRepPtr;
    Tcl_Obj *element;
    Tcl_Size i;
    size_t bytlen;
    Tcl_Obj *tmpstr = Tcl_NewObj();

    lgenSeriesRepPtr = (LgenSeries*)objPtr->internalRep.twoPtrValue.ptr1;

    for (i=0, bytlen=0; i<lgenSeriesRepPtr->len; i++) {
	element = lgen(objPtr, i);
	if (element) {
	    if (i) {
		Tcl_AppendToObj(tmpstr," ",1);
	    }
	    Tcl_AppendObjToObj(tmpstr,element);
	}
    }

    bytlen = Tcl_GetCharLength(tmpstr);
    Tcl_InitStringRep(objPtr, Tcl_GetString(tmpstr), bytlen);
    Tcl_DecrRefCount(tmpstr);

    return;
}

/*
 *  ObjType Free Internal Rep function
 */
static void
FreeLgenInternalRep(Tcl_Obj *objPtr)
{
    LgenSeries *lgenSeries = (LgenSeries*)objPtr->internalRep.twoPtrValue.ptr1;
    if (lgenSeries->genFnObj) {
	Tcl_DecrRefCount(lgenSeries->genFnObj);
    }
    lgenSeries->interp = NULL;
    Tcl_Free(lgenSeries);
    objPtr->internalRep.twoPtrValue.ptr1 = 0;
}

static void DupLgenSeriesRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);

/*
 *  Abstract List ObjType definition
 */

static const Tcl_ObjType lgenType = {
    "lgenseries",
    FreeLgenInternalRep,
    DupLgenSeriesRep,
    UpdateStringOfLgen,
    NULL, /* SetFromAnyProc */
    TCL_OBJTYPE_V2(
	lgenSeriesObjLength,
	lgenSeriesObjIndex,
	NULL, /* slice */
	NULL, /* reverse */
	NULL, /* get elements */
	NULL, /* set element */
	NULL, /* replace */
	NULL) /* "in" operator */
};

/*
 *  ObjType Duplicate Internal Rep Function
 */
static void
DupLgenSeriesRep(
    Tcl_Obj *srcPtr,
    Tcl_Obj *copyPtr)
{
    LgenSeries *srcLgenSeries = (LgenSeries*)srcPtr->internalRep.twoPtrValue.ptr1;
    Tcl_Size repSize = sizeof(LgenSeries);
    LgenSeries *copyLgenSeries = (LgenSeries*)Tcl_Alloc(repSize);

    copyLgenSeries->interp = srcLgenSeries->interp;
    copyLgenSeries->nargs = srcLgenSeries->nargs;
    copyLgenSeries->len = srcLgenSeries->len;
    copyLgenSeries->genFnObj = Tcl_DuplicateObj(srcLgenSeries->genFnObj);
    Tcl_IncrRefCount(copyLgenSeries->genFnObj);
    copyPtr->typePtr = &lgenType;
    copyPtr->internalRep.twoPtrValue.ptr1 = copyLgenSeries;
    copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
    return;
}

/*
 *  Create a new lgen Tcl_Obj
 */
Tcl_Obj *
newLgenObj(
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj * const objv[])
{
    Tcl_WideInt length;
    LgenSeries *lGenSeriesRepPtr;
    Tcl_Size repSize;
    Tcl_Obj *lGenSeriesObj;

    if (objc < 2) {
	return NULL;
    }

    if (Tcl_GetWideIntFromObj(NULL, objv[0], &length) != TCL_OK
	|| length < 0) {
	return NULL;
    }

    lGenSeriesObj = Tcl_NewObj();
    repSize = sizeof(LgenSeries);
    lGenSeriesRepPtr = (LgenSeries*)Tcl_Alloc(repSize);
    lGenSeriesRepPtr->interp = interp; //Tcl_CreateInterp();
    lGenSeriesRepPtr->len = length;

    // Allocate array of *obj for cmd + index + args
    // objv  length cmd arg1 arg2 arg3 ...
    // argsv         0   1    2    3   ... index

    lGenSeriesRepPtr->nargs = objc;
    lGenSeriesRepPtr->genFnObj = Tcl_NewListObj(objc-1, objv+1);
    // Addd 0 placeholder for index
    Tcl_ListObjAppendElement(interp, lGenSeriesRepPtr->genFnObj, Tcl_NewIntObj(0));
    Tcl_IncrRefCount(lGenSeriesRepPtr->genFnObj);
    lGenSeriesObj->internalRep.twoPtrValue.ptr1 = lGenSeriesRepPtr;
    lGenSeriesObj->internalRep.twoPtrValue.ptr2 = NULL;
    lGenSeriesObj->typePtr = &lgenType;

    if (length > 0) {
	Tcl_InvalidateStringRep(lGenSeriesObj);
    } else {
	Tcl_InitStringRep(lGenSeriesObj, NULL, 0);
    }
    return lGenSeriesObj;
}

/*
 *  The [lgen] command
 */
static int
lGenObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj * const objv[])
{
    Tcl_Obj *genObj = newLgenObj(interp, objc-1, &objv[1]);
    if (genObj) {
	Tcl_SetObjResult(interp, genObj);
	return TCL_OK;
    }
    Tcl_WrongNumArgs(interp, 1, objv, "length cmd ?args?");
    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;
}



/*
 *----------------------------------------------------------------------
 *
 * ABSListTest_Init --
 *
 *	Provides Abstract List implemenations via new commands
 *
 * lstring command
 * Usage:
 *      lstring /string/
 *
 * Description:
 *      Creates a list where each character in the string is treated as an
 *      element. The string is kept as a string, not an actual list. Indexing
 *      is done by char.
 *
 * lgen command
 * Usage:
 *      lgen /length/ /cmd/ ?args...?
 *
 *      The /cmd/ should take the last argument as the index value, and return
 *      a value for that element.
 *
 * Results:
 *	The commands listed above are added to the interp.
 *
 * Side effects:
 *	New commands defined.
 *
 *----------------------------------------------------------------------
 */

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;
}

Changes to generic/tclTestObj.c.

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
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
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
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








-
-
-
+
+
+





+



+








+





-
+

-
-
+
+








+




-
+
+
+
+




+
-
-
+
+
-
+



-
+
+
+







/*
 * tclTestObj.c --
 *
 *	This file contains C command functions for the additional Tcl commands
 *	that are used for testing implementations of the Tcl object types.
 *	These commands are not normally included in Tcl applications; they're
 *	only used for testing.
 *
 * Copyright (c) 1995-1998 Sun Microsystems, Inc.
 * Copyright (c) 1999 by Scriptics Corporation.
 * Copyright (c) 2005 by Kevin B. Kenny.  All rights reserved.
 * Copyright © 1995-1998 Sun Microsystems, Inc.
 * Copyright © 1999 Scriptics Corporation.
 * Copyright © 2005 Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#undef BUILD_tcl
#ifndef USE_TCL_STUBS
#   define USE_TCL_STUBS
#endif
#define TCLBOOLWARNING(boolPtr) /* needed here because we compile with -Wc++-compat */
#include "tclInt.h"
#ifdef TCL_WITH_EXTERNAL_TOMMATH
#   include "tommath.h"
#else
#   include "tclTomMath.h"
#endif
#include "tclStringRep.h"

#include <assert.h>

/*
 * Forward declarations for functions defined later in this file:
 */

static int		CheckIfVarUnset(Tcl_Interp *interp, Tcl_Obj **varPtr, int varIndex);
static int		CheckIfVarUnset(Tcl_Interp *interp, Tcl_Obj **varPtr, Tcl_Size varIndex);
static int		GetVariableIndex(Tcl_Interp *interp,
			    const char *string, int *indexPtr);
static void		SetVarToObj(Tcl_Obj **varPtr, int varIndex, Tcl_Obj *objPtr);
			    Tcl_Obj *obj, Tcl_Size *indexPtr);
static void		SetVarToObj(Tcl_Obj **varPtr, Tcl_Size varIndex, Tcl_Obj *objPtr);
static Tcl_ObjCmdProc	TestbignumobjCmd;
static Tcl_ObjCmdProc	TestbooleanobjCmd;
static Tcl_ObjCmdProc	TestdoubleobjCmd;
static Tcl_ObjCmdProc	TestindexobjCmd;
static Tcl_ObjCmdProc	TestintobjCmd;
static Tcl_ObjCmdProc	TestlistobjCmd;
static Tcl_ObjCmdProc	TestobjCmd;
static Tcl_ObjCmdProc	TeststringobjCmd;
static Tcl_ObjCmdProc	TestbigdataCmd;

#define VARPTR_KEY "TCLOBJTEST_VARPTR"
#define NUMBER_OF_OBJECT_VARS 20

static void VarPtrDeleteProc(void *clientData, Tcl_Interp *interp)
static void
VarPtrDeleteProc(
    void *clientData,
    TCL_UNUSED(Tcl_Interp *))
{
    int i;
    Tcl_Obj **varPtr = (Tcl_Obj **) clientData;
    for (i = 0;  i < NUMBER_OF_OBJECT_VARS;  i++) {
	if (varPtr[i]) {
	if (varPtr[i]) Tcl_DecrRefCount(varPtr[i]);
    }
	    Tcl_DecrRefCount(varPtr[i]);
	}
    Tcl_DeleteAssocData(interp, VARPTR_KEY);
    }
    Tcl_Free(varPtr);
}

static Tcl_Obj **GetVarPtr(Tcl_Interp *interp)
static Tcl_Obj **
GetVarPtr(
    Tcl_Interp *interp)
{
    Tcl_InterpDeleteProc *proc;

    return (Tcl_Obj **) Tcl_GetAssocData(interp, VARPTR_KEY, &proc);
}

/*
90
91
92
93
94
95
96





97

98
99
100
101
102
103
104
100
101
102
103
104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119







+
+
+
+
+
-
+







    /*
     * 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]));
    varPtr = (Tcl_Obj **)Tcl_Alloc(NUMBER_OF_OBJECT_VARS * sizeof(varPtr[0]));
    if (!varPtr) {
	return TCL_ERROR;
    }
    Tcl_SetAssocData(interp, VARPTR_KEY, VarPtrDeleteProc, varPtr);
    for (i = 0;  i < NUMBER_OF_OBJECT_VARS;  i++) {
	varPtr[i] = NULL;
    }
114
115
116
117
118
119
120




121
122
123
124
125
126
127
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146







+
+
+
+







    Tcl_CreateObjCommand(interp, "testindexobj", TestindexobjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testlistobj", TestlistobjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testobj", TestobjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "teststringobj", TeststringobjCmd,
	    NULL, NULL);
    if (sizeof(Tcl_Size) == sizeof(Tcl_WideInt)) {
	Tcl_CreateObjCommand(interp, "testbigdata", TestbigdataCmd,
		NULL, NULL);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestbignumobjCmd --
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
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







-
+





-
-
+
+
+









-
+


-
-
+




-
+







static int
TestbignumobjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Argument count */
    Tcl_Obj *const objv[])	/* Argument vector */
{
    const char *const subcmds[] = {
    static const char *const subcmds[] = {
	"set", "get", "mult10", "div10", "iseven", "radixsize", NULL
    };
    enum options {
	BIGNUM_SET, BIGNUM_GET, BIGNUM_MULT10, BIGNUM_DIV10, BIGNUM_ISEVEN,
	BIGNUM_RADIXSIZE
    };
    int index, varIndex;
    } idx;
    int index;
    Tcl_Size varIndex;
    const char *string;
    mp_int bignumValue;
    Tcl_Obj **varPtr;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], subcmds, "option", 0,
	    &index) != TCL_OK) {
	    &idx) != TCL_OK) {
	return TCL_ERROR;
    }
    string = Tcl_GetString(objv[2]);
    if (GetVariableIndex(interp, string, &varIndex) != TCL_OK) {
    if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) {
	return TCL_ERROR;
    }
    varPtr = GetVarPtr(interp);

    switch (index) {
    switch (idx) {
    case BIGNUM_SET:
	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "var value");
	    return TCL_ERROR;
	}
	string = Tcl_GetString(objv[3]);
	if (mp_init(&bignumValue) != MP_OKAY) {
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
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







-
+

-
+




















-
+

-
+







	if (mp_mod_2d(&bignumValue, 1, &bignumValue) != MP_OKAY) {
	    mp_clear(&bignumValue);
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("error in mp_mod_2d", -1));
	    return TCL_ERROR;
	}
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetIntObj(varPtr[varIndex], mp_iszero(&bignumValue));
	    Tcl_SetBooleanObj(varPtr[varIndex], mp_iszero(&bignumValue));
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(mp_iszero(&bignumValue)));
	    SetVarToObj(varPtr, varIndex, Tcl_NewBooleanObj(mp_iszero(&bignumValue)));
	}
	mp_clear(&bignumValue);
	break;

    case BIGNUM_RADIXSIZE:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "varIndex");
	    return TCL_ERROR;
	}
	if (CheckIfVarUnset(interp, varPtr,varIndex)) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBignumFromObj(interp, varPtr[varIndex],
		&bignumValue) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (mp_radix_size(&bignumValue, 10, &index) != MP_OKAY) {
	    return TCL_ERROR;
	}
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetIntObj(varPtr[varIndex], index);
	    Tcl_SetWideIntObj(varPtr[varIndex], index);
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(index));
	    SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(index));
	}
	mp_clear(&bignumValue);
	break;
    }

    Tcl_SetObjResult(interp, varPtr[varIndex]);
    return TCL_OK;
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
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







+
-
-
+
+








-
-
+







static int
TestbooleanobjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Size varIndex;
    int varIndex, boolValue;
    const char *index, *subCmd;
    int boolValue;
    const char *subCmd;
    Tcl_Obj **varPtr;

    if (objc < 3) {
	wrongNumArgs:
	Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
	return TCL_ERROR;
    }

    index = Tcl_GetString(objv[2]);
    if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) {
    if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) {
	return TCL_ERROR;
    }

    varPtr = GetVarPtr(interp);

    subCmd = Tcl_GetString(objv[1]);
    if (strcmp(subCmd, "set") == 0) {
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
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
442







-
+

-
+


















-
+



-
+

-
+





-
+







	 * has ref count 1 (i.e. the object is unshared) we can modify that
	 * object directly. Otherwise, if RC>1 (i.e. the object is shared),
	 * we must create a new object to modify/set and decrement the old
	 * formerly-shared object's ref count. This is "copy on write".
	 */

	if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetWideIntObj(varPtr[varIndex], boolValue != 0);
	    Tcl_SetBooleanObj(varPtr[varIndex], boolValue);
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(boolValue != 0));
	    SetVarToObj(varPtr, varIndex, Tcl_NewBooleanObj(boolValue));
	}
	Tcl_SetObjResult(interp, varPtr[varIndex]);
    } else if (strcmp(subCmd, "get") == 0) {
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	if (CheckIfVarUnset(interp, varPtr,varIndex)) {
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, varPtr[varIndex]);
    } else if (strcmp(subCmd, "not") == 0) {
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	if (CheckIfVarUnset(interp, varPtr,varIndex)) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBooleanFromObj(interp, varPtr[varIndex],
				  &boolValue) != TCL_OK) {
		&boolValue) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetWideIntObj(varPtr[varIndex], boolValue == 0);
	    Tcl_SetBooleanObj(varPtr[varIndex], !boolValue);
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(boolValue == 0));
	    SetVarToObj(varPtr, varIndex, Tcl_NewBooleanObj(!boolValue));
	}
	Tcl_SetObjResult(interp, varPtr[varIndex]);
    } else {
	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
		"bad option \"", Tcl_GetString(objv[1]),
		"\": must be set, get, or not", NULL);
		"\": must be set, get, or not", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
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
467
468
469
470
471

472
473
474
475
476
477
478
479
460
461
462
463
464
465
466

467
468

469
470
471
472
473
474
475
476
477
478
479


480
481
482
483
484
485
486
487
488

489

490
491
492
493
494
495
496







-
+

-
+










-
-
+








-
+
-







static int
TestdoubleobjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int varIndex;
    Tcl_Size varIndex;
    double doubleValue;
    const char *index, *subCmd, *string;
    const char *subCmd;
    Tcl_Obj **varPtr;

    if (objc < 3) {
	wrongNumArgs:
	Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
	return TCL_ERROR;
    }

    varPtr = GetVarPtr(interp);

    index = Tcl_GetString(objv[2]);
    if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) {
    if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) {
	return TCL_ERROR;
    }

    subCmd = Tcl_GetString(objv[1]);
    if (strcmp(subCmd, "set") == 0) {
	if (objc != 4) {
	    goto wrongNumArgs;
	}
	string = Tcl_GetString(objv[3]);
	if (Tcl_GetDouble(interp, Tcl_GetString(objv[3]), &doubleValue) != TCL_OK) {
	if (Tcl_GetDouble(interp, string, &doubleValue) != TCL_OK) {
	    return TCL_ERROR;
	}

	/*
	 * If the object currently bound to the variable with index varIndex
	 * has ref count 1 (i.e. the object is unshared) we can modify that
	 * object directly. Otherwise, if RC>1 (i.e. the object is shared), we
499
500
501
502
503
504
505
506

507
508
509
510
511
512
513
516
517
518
519
520
521
522

523
524
525
526
527
528
529
530







-
+







	if (objc != 3) {
	    goto wrongNumArgs;
	}
	if (CheckIfVarUnset(interp, varPtr,varIndex)) {
	    return TCL_ERROR;
	}
	if (Tcl_GetDoubleFromObj(interp, varPtr[varIndex],
				 &doubleValue) != TCL_OK) {
		&doubleValue) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetDoubleObj(varPtr[varIndex], doubleValue * 10.0);
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewDoubleObj(doubleValue * 10.0));
	}
528
529
530
531
532
533
534
535

536
537
538
539
540
541
542
545
546
547
548
549
550
551

552
553
554
555
556
557
558
559







-
+







	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewDoubleObj(doubleValue / 10.0));
	}
	Tcl_SetObjResult(interp, varPtr[varIndex]);
    } else {
	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
		"bad option \"", Tcl_GetString(objv[1]),
		"\": must be set, get, mult10, or div10", NULL);
		"\": must be set, get, mult10, or div10", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
559
560
561
562
563
564
565
566


567
568
569
570
571
572
573
574
575
576


577
578

579
580
581
582
583
584
585
586
587
588

589
590
591
592
593
594
595
596
597
598

599
600
601
602
603
604
605
576
577
578
579
580
581
582

583
584
585
586
587
588
589
590
591
592


593
594


595
596
597
598
599
600
601
602
603
604

605
606
607
608
609
610
611
612
613
614

615
616
617
618
619
620
621
622







-
+
+








-
-
+
+
-
-
+









-
+









-
+







static int
TestindexobjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int allowAbbrev, index, index2, setError, i, result;
    int allowAbbrev, index, setError, i, result;
    Tcl_Size index2;
    const char **argv;
    static const char *const tablePtr[] = {"a", "b", "check", NULL};

    /*
     * Keep this structure declaration in sync with tclIndexObj.c
     */
    struct IndexRep {
	void *tablePtr;		/* Pointer to the table of strings. */
	size_t offset;		/* Offset between table entries. */
	size_t index;		/* Selected index into table. */
	Tcl_Size offset;		/* Offset between table entries. */
	Tcl_Size index;		/* Selected index into table. */
    };
    struct IndexRep *indexRep;
    } *indexRep;

    if ((objc == 3) && (strcmp(Tcl_GetString(objv[1]),
	    "check") == 0)) {
	/*
	 * This code checks to be sure that the results of Tcl_GetIndexFromObj
	 * are properly cached in the object and returned on subsequent
	 * lookups.
	 */

	if (Tcl_GetIntFromObj(interp, objv[2], &index2) != TCL_OK) {
	if (Tcl_GetIntForIndex(interp, objv[2], TCL_INDEX_NONE, &index2) != TCL_OK) {
	    return TCL_ERROR;
	}

	Tcl_GetIndexFromObj(NULL, objv[1], tablePtr, "token", 0, &index);
	indexRep = (struct IndexRep *)objv[1]->internalRep.twoPtrValue.ptr1;
	indexRep->index = index2;
	result = Tcl_GetIndexFromObj(NULL, objv[1],
		tablePtr, "token", 0, &index);
	if (result == TCL_OK) {
	    Tcl_SetIntObj(Tcl_GetObjResult(interp), index);
	    Tcl_SetWideIntObj(Tcl_GetObjResult(interp), index);
	}
	return result;
    }

    if (objc < 5) {
	Tcl_AppendToObj(Tcl_GetObjResult(interp), "wrong # args", -1);
	return TCL_ERROR;
619
620
621
622
623
624
625
626

627
628
629
630
631
632
633
636
637
638
639
640
641
642

643
644
645
646
647
648
649
650







-
+







    argv[objc-4] = NULL;

    result = Tcl_GetIndexFromObj((setError? interp : NULL), objv[3],
	    argv, "token", TCL_INDEX_TEMP_TABLE|(allowAbbrev? 0 : TCL_EXACT),
	    &index);
    Tcl_Free((void *)argv);
    if (result == TCL_OK) {
	Tcl_SetIntObj(Tcl_GetObjResult(interp), index);
	Tcl_SetWideIntObj(Tcl_GetObjResult(interp), index);
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
649
650
651
652
653
654
655
656




657
658

659
660
661
662
663
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
707
708

709
710

711
712
713
714
715
716
717

718
719
720
721
722

723
724

725
726
727
728
729
730
731
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
707
708
709

710
711

712
713
714
715
716
717
718


719
720
721

722

723
724

725
726
727
728
729
730


731
732
733

734

735
736

737
738
739
740
741
742
743
744







-
+
+
+
+

-
+









-
-
+








-
-
+


-










-
+

-
+






-
-
+


-

-
+

-
+





-
-
+


-

-
+

-
+







static int
TestintobjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int intValue, varIndex, i;
    Tcl_Size varIndex;
#if (INT_MAX != LONG_MAX)   /* int is not the same size as long */
    int i;
#endif
    Tcl_WideInt wideValue;
    const char *index, *subCmd, *string;
    const char *subCmd;
    Tcl_Obj **varPtr;

    if (objc < 3) {
	wrongNumArgs:
	Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
	return TCL_ERROR;
    }

    varPtr = GetVarPtr(interp);
    index = Tcl_GetString(objv[2]);
    if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) {
    if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) {
	return TCL_ERROR;
    }

    subCmd = Tcl_GetString(objv[1]);
    if (strcmp(subCmd, "set") == 0) {
	if (objc != 4) {
	    goto wrongNumArgs;
	}
	string = Tcl_GetString(objv[3]);
	if (Tcl_GetInt(interp, string, &i) != TCL_OK) {
	if (Tcl_GetWideIntFromObj(interp, objv[3], &wideValue) != TCL_OK) {
	    return TCL_ERROR;
	}
	intValue = i;

	/*
	 * If the object currently bound to the variable with index varIndex
	 * has ref count 1 (i.e. the object is unshared) we can modify that
	 * object directly. Otherwise, if RC>1 (i.e. the object is shared), we
	 * must create a new object to modify/set and decrement the old
	 * formerly-shared object's ref count. This is "copy on write".
	 */

	if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetIntObj(varPtr[varIndex], intValue);
	    Tcl_SetWideIntObj(varPtr[varIndex], wideValue);
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(intValue));
	    SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(wideValue));
	}
	Tcl_SetObjResult(interp, varPtr[varIndex]);
    } else if (strcmp(subCmd, "set2") == 0) { /* doesn't set result */
	if (objc != 4) {
	    goto wrongNumArgs;
	}
	string = Tcl_GetString(objv[3]);
	if (Tcl_GetInt(interp, string, &i) != TCL_OK) {
	if (Tcl_GetWideIntFromObj(interp, objv[3], &wideValue) != TCL_OK) {
	    return TCL_ERROR;
	}
	intValue = i;
	if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetIntObj(varPtr[varIndex], intValue);
	    Tcl_SetWideIntObj(varPtr[varIndex], wideValue);
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(intValue));
	    SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(wideValue));
	}
    } else if (strcmp(subCmd, "setint") == 0) {
	if (objc != 4) {
	    goto wrongNumArgs;
	}
	string = Tcl_GetString(objv[3]);
	if (Tcl_GetInt(interp, string, &i) != TCL_OK) {
	if (Tcl_GetWideIntFromObj(interp, objv[3], &wideValue) != TCL_OK) {
	    return TCL_ERROR;
	}
	intValue = i;
	if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetWideIntObj(varPtr[varIndex], intValue);
	    Tcl_SetWideIntObj(varPtr[varIndex], wideValue);
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(intValue));
	    SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(wideValue));
	}
	Tcl_SetObjResult(interp, varPtr[varIndex]);
    } else if (strcmp(subCmd, "setmax") == 0) {
	Tcl_WideInt maxWide = WIDE_MAX;
	if (objc != 3) {
	    goto wrongNumArgs;
	}
757
758
759
760
761
762
763
764
765

766
767
768
769
770
771
772
770
771
772
773
774
775
776


777
778
779
780
781
782
783
784







-
-
+







    } else if (strcmp(subCmd, "get2") == 0) {
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	if (CheckIfVarUnset(interp, varPtr,varIndex)) {
	    return TCL_ERROR;
	}
	string = Tcl_GetString(varPtr[varIndex]);
	Tcl_AppendToObj(Tcl_GetObjResult(interp), string, -1);
	Tcl_AppendToObj(Tcl_GetObjResult(interp), Tcl_GetString(varPtr[varIndex]), -1);
    } else if (strcmp(subCmd, "inttoobigtest") == 0) {
	/*
	 * If long ints have more bits than ints on this platform, verify that
	 * Tcl_GetIntFromObj returns an error if the long int held in an
	 * integer object's internal representation is too large to fit in an
	 * int.
	 */
792
793
794
795
796
797
798
799
800


801
802
803
804

805
806

807
808
809
810
811
812
813
814
815
816
817


818
819
820
821

822
823

824
825
826
827
828
829

830
831
832
833
834
835
836
837
838
839
840
841
842





























843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861

862
863
864





865
866
867
868
869
870





871
872
873

874
875
876


877

878
879
880
881
882
883
884
885

886
887
888
889
890
891
892
804
805
806
807
808
809
810


811
812
813
814
815

816
817

818
819
820
821
822
823
824
825
826
827


828
829
830
831
832

833
834

835
836
837
838
839
840

841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901

902
903
904

905
906
907
908
909
910
911
912
913


914
915
916
917
918
919


920



921
922
923
924
925
926
927
928
929
930


931
932
933
934
935
936
937
938







-
-
+
+



-
+

-
+









-
-
+
+



-
+

-
+





-
+













+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-
+


-
+
+
+
+
+




-
-
+
+
+
+
+

-
-
+
-
-
-
+
+

+






-
-
+







    } else if (strcmp(subCmd, "mult10") == 0) {
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	if (CheckIfVarUnset(interp, varPtr,varIndex)) {
	    return TCL_ERROR;
	}
	if (Tcl_GetIntFromObj(interp, varPtr[varIndex],
		&intValue) != TCL_OK) {
	if (Tcl_GetWideIntFromObj(interp, varPtr[varIndex],
		&wideValue) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetIntObj(varPtr[varIndex], intValue * 10);
	    Tcl_SetWideIntObj(varPtr[varIndex], wideValue * 10);
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(intValue * 10));
	    SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(wideValue * 10));
	}
	Tcl_SetObjResult(interp, varPtr[varIndex]);
    } else if (strcmp(subCmd, "div10") == 0) {
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	if (CheckIfVarUnset(interp, varPtr,varIndex)) {
	    return TCL_ERROR;
	}
	if (Tcl_GetIntFromObj(interp, varPtr[varIndex],
		&intValue) != TCL_OK) {
	if (Tcl_GetWideIntFromObj(interp, varPtr[varIndex],
		&wideValue) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetIntObj(varPtr[varIndex], intValue / 10);
	    Tcl_SetWideIntObj(varPtr[varIndex], wideValue / 10);
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(intValue / 10));
	    SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(wideValue / 10));
	}
	Tcl_SetObjResult(interp, varPtr[varIndex]);
    } else {
	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
		"bad option \"", Tcl_GetString(objv[1]),
		"\": must be set, get, get2, mult10, or div10", NULL);
		"\": must be set, get, get2, mult10, or div10", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *-----------------------------------------------------------------------------
 *
 * 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.
 *
 *	indexmemcheck - loops calling Tcl_ListObjIndex on each element. This
 *	is to test that abstract lists returning elements do not depend
 *	on caller to free them. The test case should check allocated counts
 *      with the following sequence:
 *            set before <get memory counts>
 *            testobj set VARINDEX [list a b c] (or lseq etc.)
 *            testlistobj indexnoop VARINDEX
 *            testobj unset VARINDEX
 *            set after <get memory counts>
 *      after calling this command AND freeing the passed list. The targeted
 *      bug is if Tcl_LOI returns a ephemeral Tcl_Obj with no other reference
 *      resulting in a memory leak. Conversely, the command also checks
 *      that the Tcl_Obj returned by Tcl_LOI does not have a zero reference
 *      count since it is supposed to have at least one reference held
 *      by the list implementation. Returns a message in interp otherwise.
 *
 *      getelementsmemcheck - as above but for Tcl_ListObjGetElements

 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	Creates, manipulates and frees list objects.
 *
 *-----------------------------------------------------------------------------
 */

static int
TestlistobjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Number of arguments */
    Tcl_Obj *const objv[])	/* Argument objects */
{
    /* Subcommands supported by this command */
    const char* subcommands[] = {
    static const char* const subcommands[] = {
	"set",
	"get",
	"replace"
	"replace",
	"indexmemcheck",
	"getelementsmemcheck",
	"index",
	NULL
    };
    enum listobjCmdIndex {
	LISTOBJ_SET,
	LISTOBJ_GET,
	LISTOBJ_REPLACE
    };
	LISTOBJ_REPLACE,
	LISTOBJ_INDEXMEMCHECK,
	LISTOBJ_GETELEMENTSMEMCHECK,
	LISTOBJ_INDEX,
    } cmdIndex;

    const char* index;		/* Argument giving the variable number */
    int varIndex;		/* Variable number converted to binary */
    Tcl_Size varIndex;		/* Variable number converted to binary */
    int cmdIndex;		/* Ordinal number of the subcommand */
    int first;			/* First index in the list */
    int count;			/* Count of elements in a list */
    Tcl_Size first;			/* First index in the list */
    Tcl_Size count;			/* Count of elements in a list */
    Tcl_Obj **varPtr;
    Tcl_Size i, len;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg...?");
	return TCL_ERROR;
    }
    varPtr = GetVarPtr(interp);
    index = Tcl_GetString(objv[2]);
    if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) {
    if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) {
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], subcommands, "command",
			    0, &cmdIndex) != TCL_OK) {
	return TCL_ERROR;
    }
    switch(cmdIndex) {
909
910
911
912
913
914
915
916

917
918
919
920


921
922
923
924
925
926
927
928







































































929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948



























949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119






















1120
1121
1122
1123
1124
1125
1126

1127
1128
1129
1130
1131
1132
1133



1134
1135
1136
1137
1138
1139
1140

1141
1142
1143
1144
1145
1146
1147
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124






1125


























1126




















1127
1128
1129








1130
1131











1132
1133
1134
1135
1136
1137
1138
1139
1140


1141
1142
1143
1144



1145
1146
1147
1148
1149
1150
1151
1152

1153


1154




1155
1156
1157
1158
1159
1160
1161
1162






1163
1164
1165
1166
1167
1168
1169
1170



1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182






1183
1184
1185
1186
1187
1188
1189
1190
1191



1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210










1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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







-
+


-
-
+
+







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
-
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+








-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-









-
-
+
+
+

-
-
-
+
+
+
+
+
+
+
+
-

-
-
+
-
-
-
-
+


+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
+







+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
-
-
-
+
+
+
+


+
+
-
-
+
+
+
+
+


-
+
+
+
+
+
+
+


-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-




-
+
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
+







	}
	Tcl_SetObjResult(interp, varPtr[varIndex]);
	break;

    case LISTOBJ_REPLACE:
	if (objc < 5) {
	    Tcl_WrongNumArgs(interp, 2, objv,
			     "varIndex start count ?element...?");
		    "varIndex start count ?element...?");
	    return TCL_ERROR;
	}
	if (Tcl_GetIntFromObj(interp, objv[3], &first) != TCL_OK
	    || Tcl_GetIntFromObj(interp, objv[4], &count) != TCL_OK) {
	if (Tcl_GetIntForIndex(interp, objv[3], TCL_INDEX_NONE, &first) != TCL_OK
	    || Tcl_GetIntForIndex(interp, objv[4], TCL_INDEX_NONE, &count) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_IsShared(varPtr[varIndex])) {
	    SetVarToObj(varPtr, varIndex, Tcl_DuplicateObj(varPtr[varIndex]));
	}
	Tcl_ResetResult(interp);
	return Tcl_ListObjReplace(interp, varPtr[varIndex], first, count,
				  objc-5, objv+5);
		objc-5, objv+5);

    case LISTOBJ_INDEXMEMCHECK:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "varIndex");
	    return TCL_ERROR;
	}
	if (CheckIfVarUnset(interp, varPtr, varIndex)) {
	    return TCL_ERROR;
	}
	if (Tcl_ListObjLength(interp, varPtr[varIndex], &len) != TCL_OK) {
	    return TCL_ERROR;
	}
	for (i = 0; i < len; ++i) {
	    Tcl_Obj *objP;
	    if (Tcl_ListObjIndex(interp, varPtr[varIndex], i, &objP)
		!= TCL_OK) {
		return TCL_ERROR;
	    }
	    if (objP->refCount < 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"Tcl_ListObjIndex returned object with ref count < 0",
			TCL_INDEX_NONE));
		/* Keep looping since we are also looping for leaks */
	    }
	    Tcl_BounceRefCount(objP);
	}
	break;

    case LISTOBJ_GETELEMENTSMEMCHECK:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "varIndex");
	    return TCL_ERROR;
	}
	if (CheckIfVarUnset(interp, varPtr, varIndex)) {
	    return TCL_ERROR;
	} else {
	    Tcl_Obj **elems;
	    if (Tcl_ListObjGetElements(interp, varPtr[varIndex], &len, &elems)
		!= TCL_OK) {
		return TCL_ERROR;
	    }
	    for (i = 0; i < len; ++i) {
		if (elems[i]->refCount <= 0) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "Tcl_ListObjGetElements element has ref count <= 0",
			    TCL_INDEX_NONE));
		    break;
		}
	    }
	}
	break;
    case LISTOBJ_INDEX:
	/*
	 * Tcl_ListObjIndex semantics differ from lindex for out of bounds.
	 * Hence this explicit test.
	 */
	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "varIndex listIndex");
	    return TCL_ERROR;
	}
	if (Tcl_GetIntForIndex(interp, objv[3], TCL_INDEX_NONE, &first) != TCL_OK) {
	    return TCL_ERROR;
	} else {
	    Tcl_Obj *objP;
	    if (Tcl_ListObjIndex(interp, varPtr[varIndex], first, &objP) != TCL_OK) {
		return TCL_ERROR;
	    }
	    Tcl_SetObjResult(interp, objP ? objP : Tcl_NewStringObj("null", -1));
	}
	break;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestobjCmd --
 *
 *	This function implements the "testobj" command. It is used to test
 *	the type-independent portions of the Tcl object type implementation.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	Creates and frees objects.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Size V1TestListObjLength(TCL_UNUSED(Tcl_Obj *)) {
    return 100;
}

static int V1TestListObjIndex(
    TCL_UNUSED(Tcl_Interp *),
    TCL_UNUSED(Tcl_Obj *),
    TCL_UNUSED(Tcl_Size),
    Tcl_Obj **objPtr)
{
    *objPtr = Tcl_NewStringObj("This indexProc should never be accessed (bug: e58d7e19e9)", -1);
    return TCL_OK;
}

static const Tcl_ObjType v1TestListType = {
    "testlist",			/* name */
    NULL,		/* freeIntRepProc */
    NULL,		/* dupIntRepProc */
    NULL,		/* updateStringProc */
    NULL,		/* setFromAnyProc */
    offsetof(Tcl_ObjType, indexProc),			/* This is a V1 objType, which doesn't have an indexProc */
    V1TestListObjLength, /* always return 100, doesn't really matter */
    V1TestListObjIndex, /* should never be accessed, because this objType = V1*/
    NULL, NULL, NULL, NULL, NULL, NULL
};


static int
TestobjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int varIndex, destIndex, i;
    const char *index, *subCmd, *string;
    Tcl_Size varIndex, destIndex;
    int i;
    const Tcl_ObjType *targetType;
    Tcl_Obj **varPtr;
    static const char *const subcommands[] = {
	"freeallvars", "bug3598580", "buge58d7e19e9",
	"types", "objtype", "newobj", "set",
	"assign", "convert", "duplicate",
	"invalidateStringRep", "refcount", "type",
	NULL
    };
    enum testobjCmdIndex {
	TESTOBJ_FREEALLVARS, TESTOBJ_BUG3598580, TESTOBJ_BUGE58D7E19E9,
	TESTOBJ_TYPES, TESTOBJ_OBJTYPE, TESTOBJ_NEWOBJ, TESTOBJ_SET,
	TESTOBJ_ASSIGN, TESTOBJ_CONVERT, TESTOBJ_DUPLICATE,
	TESTOBJ_INVALIDATESTRINGREP, TESTOBJ_REFCOUNT, TESTOBJ_TYPE,
    } cmdIndex;

    if (objc < 2) {
	wrongNumArgs:
	Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
	return TCL_ERROR;
    }

    varPtr = GetVarPtr(interp);
    subCmd = Tcl_GetString(objv[1]);
    if (strcmp(subCmd, "assign") == 0) {
	if (objc != 4) {
	    goto wrongNumArgs;
	}
	index = Tcl_GetString(objv[2]);
    if (Tcl_GetIndexFromObj(
	if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (CheckIfVarUnset(interp, varPtr,varIndex)) {
	    return TCL_ERROR;
	}
	string = Tcl_GetString(objv[3]);
	if (GetVariableIndex(interp, string, &destIndex) != TCL_OK) {
	    return TCL_ERROR;
	}
	SetVarToObj(varPtr, destIndex, varPtr[varIndex]);
	Tcl_SetObjResult(interp, varPtr[destIndex]);
    } else if (strcmp(subCmd, "bug3598580") == 0) {
	Tcl_Obj *listObjPtr, *elemObjPtr;
	if (objc != 2) {
	    goto wrongNumArgs;
	}
	elemObjPtr = Tcl_NewIntObj(123);
	listObjPtr = Tcl_NewListObj(1, &elemObjPtr);
	/* Replace the single list element through itself, nonsense but legal. */
	Tcl_ListObjReplace(interp, listObjPtr, 0, 1, 1, &elemObjPtr);
	Tcl_SetObjResult(interp, listObjPtr);
	return TCL_OK;
    } else if (strcmp(subCmd, "convert") == 0) {
	const char *typeName;

	    interp, objv[1], subcommands, "command", 0, &cmdIndex)
	if (objc != 4) {
	    goto wrongNumArgs;
	}
	index = Tcl_GetString(objv[2]);
	if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (CheckIfVarUnset(interp, varPtr,varIndex)) {
	    return TCL_ERROR;
	}
	typeName = Tcl_GetString(objv[3]);
	if ((targetType = Tcl_GetObjType(typeName)) == NULL) {
	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
		    "no type ", typeName, " found", NULL);
	    return TCL_ERROR;
	}
	if (Tcl_ConvertToType(interp, varPtr[varIndex], targetType)
		!= TCL_OK) {
	    return TCL_ERROR;
	}
	!= TCL_OK) {
	return TCL_ERROR;
    }
	Tcl_SetObjResult(interp, varPtr[varIndex]);
    } else if (strcmp(subCmd, "duplicate") == 0) {
	if (objc != 4) {
	    goto wrongNumArgs;
	}
	index = Tcl_GetString(objv[2]);
	if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) {
	    return TCL_ERROR;
    switch (cmdIndex) {
    case TESTOBJ_FREEALLVARS:
	}
	if (CheckIfVarUnset(interp, varPtr,varIndex)) {
	    return TCL_ERROR;
	}
	string = Tcl_GetString(objv[3]);
	if (GetVariableIndex(interp, string, &destIndex) != TCL_OK) {
	    return TCL_ERROR;
	}
	SetVarToObj(varPtr, destIndex, Tcl_DuplicateObj(varPtr[varIndex]));
	Tcl_SetObjResult(interp, varPtr[destIndex]);
    } else if (strcmp(subCmd, "freeallvars") == 0) {
	if (objc != 2) {
	    goto wrongNumArgs;
	}
	for (i = 0;  i < NUMBER_OF_OBJECT_VARS;  i++) {
	    if (varPtr[i] != NULL) {
		Tcl_DecrRefCount(varPtr[i]);
		varPtr[i] = NULL;
	    }
	}
    } else if (strcmp(subCmd, "invalidateStringRep") == 0) {
	if (objc != 3) {
	return TCL_OK;
    case TESTOBJ_BUG3598580:
	if (objc != 2) {
	    goto wrongNumArgs;
	}
	index = Tcl_GetString(objv[2]);
	if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) {
	} else {
	    Tcl_Obj *listObjPtr, *elemObjPtr;
	    elemObjPtr = Tcl_NewWideIntObj(123);
	    listObjPtr = Tcl_NewListObj(1, &elemObjPtr);
	    /* Replace the single list element through itself, nonsense but
	     * legal. */
	    Tcl_ListObjReplace(interp, listObjPtr, 0, 1, 1, &elemObjPtr);
	    Tcl_SetObjResult(interp, listObjPtr);
	    return TCL_ERROR;
	}
	if (CheckIfVarUnset(interp, varPtr,varIndex)) {
	    return TCL_ERROR;
	return TCL_OK;
	}
	Tcl_InvalidateStringRep(varPtr[varIndex]);
	Tcl_SetObjResult(interp, varPtr[varIndex]);
    } else if (strcmp(subCmd, "newobj") == 0) {
    case TESTOBJ_BUGE58D7E19E9:
	if (objc != 3) {
	    goto wrongNumArgs;
	} else {
	    Tcl_Obj *listObjPtr = Tcl_NewStringObj(Tcl_GetString(objv[2]), -1);
	    listObjPtr->typePtr = &v1TestListType;
	    Tcl_SetObjResult(interp, listObjPtr);
	}
	index = Tcl_GetString(objv[2]);
	if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) {
	    return TCL_ERROR;
	}
	SetVarToObj(varPtr, varIndex, Tcl_NewObj());
	Tcl_SetObjResult(interp, varPtr[varIndex]);
	return TCL_OK;
    case TESTOBJ_TYPES:
	if (objc != 2) {
	    goto wrongNumArgs;
	} else {
	    Tcl_Obj *typesObj = Tcl_NewListObj(0, NULL);
	    Tcl_AppendAllObjTypes(interp, typesObj);
	    Tcl_SetObjResult(interp, typesObj);
    } else if (strcmp(subCmd, "objtype") == 0) {
	const char *typeName;

	}
	return TCL_OK;
    case TESTOBJ_OBJTYPE:
	/*
	 * Return an object containing the name of the argument's type of
	 * internal rep. If none exists, return "none".
	 */

	if (objc != 3) {
	    goto wrongNumArgs;
	} else {
	    const char *typeName;
	}
	if (objv[2]->typePtr == NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj("none", -1));
	} else {
	    typeName = objv[2]->typePtr->name;
#ifndef TCL_WIDE_INT_IS_LONG

	    if (objv[2]->typePtr == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("none", -1));
	    } else {
		typeName = objv[2]->typePtr->name;
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(typeName, -1));
	    }
	}
	return TCL_OK;
	    if (!strcmp(typeName, "wideInt")) typeName = "int";
#endif
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(typeName, -1));
    case TESTOBJ_NEWOBJ:
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) {
	    return TCL_ERROR;
	}
	SetVarToObj(varPtr, varIndex, Tcl_NewObj());
	Tcl_SetObjResult(interp, varPtr[varIndex]);
	return TCL_OK;
    case TESTOBJ_SET:
	if (objc != 4) {
	    goto wrongNumArgs;
	}
	if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) {
	    return TCL_ERROR;
	}
	SetVarToObj(varPtr, varIndex, objv[3]);
	return TCL_OK;
    } else if (strcmp(subCmd, "refcount") == 0) {
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	index = Tcl_GetString(objv[2]);
	if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (CheckIfVarUnset(interp, varPtr,varIndex)) {
	    return TCL_ERROR;

    default:
	break;
    }

    /* All further commands expect an occupied varindex argument */
    if (objc < 3) {
	goto wrongNumArgs;
    }

    if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) {
	return TCL_ERROR;
    }
    if (CheckIfVarUnset(interp, varPtr, varIndex)) {
	return TCL_ERROR;
    }

    switch (cmdIndex) {
    case TESTOBJ_ASSIGN:
	if (objc != 4) {
	    goto wrongNumArgs;
	}
	if (GetVariableIndex(interp, objv[3], &destIndex) != TCL_OK) {
	    return TCL_ERROR;
	}
	SetVarToObj(varPtr, destIndex, varPtr[varIndex]);
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(varPtr[varIndex]->refCount));
    } else if (strcmp(subCmd, "type") == 0) {
	if (objc != 3) {
	Tcl_SetObjResult(interp, varPtr[destIndex]);
	break;
    case TESTOBJ_CONVERT:
	if (objc != 4) {
	    goto wrongNumArgs;
	}
	if ((targetType = Tcl_GetObjType(Tcl_GetString(objv[3]))) == NULL) {
	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
	index = Tcl_GetString(objv[2]);
	if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) {
		    "no type ", Tcl_GetString(objv[3]), " found", (char *)NULL);
	    return TCL_ERROR;
	}
	if (Tcl_ConvertToType(interp, varPtr[varIndex], targetType)
		!= TCL_OK) {
	    return TCL_ERROR;
	}
	if (CheckIfVarUnset(interp, varPtr,varIndex)) {
	Tcl_SetObjResult(interp, varPtr[varIndex]);
	break;
    case TESTOBJ_DUPLICATE:
	if (objc != 4) {
	    goto wrongNumArgs;
	}
	if (GetVariableIndex(interp, objv[3], &destIndex) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (varPtr[varIndex]->typePtr == NULL) { /* a string! */
	    Tcl_AppendToObj(Tcl_GetObjResult(interp), "string", -1);
#ifndef TCL_WIDE_INT_IS_LONG
	} else if (!strcmp(varPtr[varIndex]->typePtr->name, "wideInt")) {
	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
	SetVarToObj(varPtr, destIndex, Tcl_DuplicateObj(varPtr[varIndex]));
	Tcl_SetObjResult(interp, varPtr[destIndex]);
	break;
    case TESTOBJ_INVALIDATESTRINGREP:
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	Tcl_InvalidateStringRep(varPtr[varIndex]);
	Tcl_SetObjResult(interp, varPtr[varIndex]);
	break;
    case TESTOBJ_REFCOUNT:
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(varPtr[varIndex]->refCount));
	break;
    case TESTOBJ_TYPE:
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	if (varPtr[varIndex]->typePtr == NULL) { /* a string! */
	    Tcl_AppendToObj(Tcl_GetObjResult(interp), "string", -1);
		    "int", -1);
#endif
	} else {
	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
		    varPtr[varIndex]->typePtr->name, -1);
	}
    } else if (strcmp(subCmd, "types") == 0) {
	break;
	if (objc != 2) {
	    goto wrongNumArgs;
	}
	if (Tcl_AppendAllObjTypes(interp,
		Tcl_GetObjResult(interp)) != TCL_OK) {
	    return TCL_ERROR;
	}
    default:
	break;
    }
    } else {
	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
		"bad option \"", Tcl_GetString(objv[1]),
		"\": must be assign, convert, duplicate, freeallvars, "
		"newobj, objcount, objtype, refcount, type, or types", NULL);
	return TCL_ERROR;
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TeststringobjCmd --
1163
1164
1165
1166
1167
1168
1169

1170


1171
1172

1173
1174
1175
1176
1177
1178


1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189

1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202

1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218

1219
1220
1221
1222
1223
1224
1225
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

1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368


1369
1370
1371
1372
1373
1374
1375
1376







+
-
+
+

-
+




-
-
+
+









-
-
+












-
+














-
-
+







TeststringobjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_UniChar *unicode;
    Tcl_Size size, varIndex;
    int varIndex, option, i, length;
    int option, i;
    Tcl_Size length;
#define MAX_STRINGS 11
    const char *index, *string, *strings[MAX_STRINGS+1];
    const char *string, *strings[MAX_STRINGS+1];
    String *strPtr;
    Tcl_Obj **varPtr;
    static const char *const options[] = {
	"append", "appendstrings", "get", "get2", "length", "length2",
	"set", "set2", "setlength", "maxchars", "appendself",
	"appendself2", NULL
	"set", "set2", "setlength", "maxchars", "range", "appendself",
	"appendself2", "newunicode", NULL
    };

    if (objc < 3) {
	wrongNumArgs:
	Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
	return TCL_ERROR;
    }

    varPtr = GetVarPtr(interp);
    index = Tcl_GetString(objv[2]);
    if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) {
    if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) {
	return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &option)
	    != TCL_OK) {
	return TCL_ERROR;
    }
    switch (option) {
	case 0:				/* append */
	    if (objc != 5) {
		goto wrongNumArgs;
	    }
	    if (Tcl_GetIntFromObj(interp, objv[4], &length) != TCL_OK) {
	    if (Tcl_GetIntForIndex(interp, objv[4], TCL_INDEX_NONE, &length) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (varPtr[varIndex] == NULL) {
		SetVarToObj(varPtr, varIndex, Tcl_NewObj());
	    }

	    /*
	     * If the object bound to variable "varIndex" is shared, we must
	     * "copy on write" and append to a copy of the object.
	     */

	    if (Tcl_IsShared(varPtr[varIndex])) {
		SetVarToObj(varPtr, varIndex, Tcl_DuplicateObj(varPtr[varIndex]));
	    }
	    string = Tcl_GetString(objv[3]);
	    Tcl_AppendToObj(varPtr[varIndex], string, length);
	    Tcl_AppendToObj(varPtr[varIndex], Tcl_GetString(objv[3]), length);
	    Tcl_SetObjResult(interp, varPtr[varIndex]);
	    break;
	case 1:				/* appendstrings */
	    if (objc > (MAX_STRINGS+3)) {
		goto wrongNumArgs;
	    }
	    if (varPtr[varIndex] == NULL) {
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
1354
1355
1356
1357
1358
1359
1360

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
1387
1388
1389
1390
1391

1392
1393

1394
1395
1396

1397
1398
1399
1400
1401
1402

1403

















1404
1405
1406
1407
1408
1409






































































































































1410
1411
1412
1413
1414
1415
1416
1390
1391
1392
1393
1394
1395
1396

1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415


1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432

1433
1434

1435
1436

1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488

1489
1490

1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504

1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521

1522
1523

1524
1525
1526

1527
1528
1529
1530
1531
1532

1533
1534
1535

1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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







-
+


















-
-
+
















-
+

-
+

-
+















-
+


-
+

-
+













-
+
















-
+

-
+

+
+
+
+
+
+
+
+
+
+
+
+
-
+
















-
+

-
+


-
+





-
+


-
+
















-
+

-
+


-
+





-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    }
	    for ( ; i < 12 + 3; i++) {
		strings[i - 3] = NULL;
	    }
	    Tcl_AppendStringsToObj(varPtr[varIndex], strings[0], strings[1],
		    strings[2], strings[3], strings[4], strings[5],
		    strings[6], strings[7], strings[8], strings[9],
		    strings[10], strings[11]);
		    strings[10], strings[11], (char *)NULL);
	    Tcl_SetObjResult(interp, varPtr[varIndex]);
	    break;
	case 2:				/* get */
	    if (objc != 3) {
		goto wrongNumArgs;
	    }
	    if (CheckIfVarUnset(interp, varPtr,varIndex)) {
		return TCL_ERROR;
	    }
	    Tcl_SetObjResult(interp, varPtr[varIndex]);
	    break;
	case 3:				/* get2 */
	    if (objc != 3) {
		goto wrongNumArgs;
	    }
	    if (CheckIfVarUnset(interp, varPtr, varIndex)) {
		return TCL_ERROR;
	    }
	    string = Tcl_GetString(varPtr[varIndex]);
	    Tcl_AppendToObj(Tcl_GetObjResult(interp), string, -1);
	    Tcl_AppendToObj(Tcl_GetObjResult(interp), Tcl_GetString(varPtr[varIndex]), -1);
	    break;
	case 4:				/* length */
	    if (objc != 3) {
		goto wrongNumArgs;
	    }
	    Tcl_SetWideIntObj(Tcl_GetObjResult(interp), (varPtr[varIndex] != NULL)
		    ? (Tcl_WideInt)varPtr[varIndex]->length : (Tcl_WideInt)-1);
	    break;
	case 5:				/* length2 */
	    if (objc != 3) {
		goto wrongNumArgs;
	    }
	    if (varPtr[varIndex] != NULL) {
		Tcl_ConvertToType(NULL, varPtr[varIndex],
			Tcl_GetObjType("string"));
		strPtr = (String *)varPtr[varIndex]->internalRep.twoPtrValue.ptr1;
		length = (int) strPtr->allocated;
		length = strPtr->allocated;
	    } else {
		length = -1;
		length = TCL_INDEX_NONE;
	    }
	    Tcl_SetIntObj(Tcl_GetObjResult(interp), length);
	    Tcl_SetWideIntObj(Tcl_GetObjResult(interp), (Tcl_WideInt)((Tcl_WideUInt)(length + 1U)) - 1);
	    break;
	case 6:				/* set */
	    if (objc != 4) {
		goto wrongNumArgs;
	    }

	    /*
	     * If the object currently bound to the variable with index
	     * varIndex has ref count 1 (i.e. the object is unshared) we can
	     * modify that object directly. Otherwise, if RC>1 (i.e. the
	     * object is shared), we must create a new object to modify/set
	     * and decrement the old formerly-shared object's ref count. This
	     * is "copy on write".
	     */

	    string = Tcl_GetStringFromObj(objv[3], &length);
	    string = Tcl_GetStringFromObj(objv[3], &size);
	    if ((varPtr[varIndex] != NULL)
		    && !Tcl_IsShared(varPtr[varIndex])) {
		Tcl_SetStringObj(varPtr[varIndex], string, length);
		Tcl_SetStringObj(varPtr[varIndex], string, size);
	    } else {
		SetVarToObj(varPtr, varIndex, Tcl_NewStringObj(string, length));
		SetVarToObj(varPtr, varIndex, Tcl_NewStringObj(string, size));
	    }
	    Tcl_SetObjResult(interp, varPtr[varIndex]);
	    break;
	case 7:				/* set2 */
	    if (objc != 4) {
		goto wrongNumArgs;
	    }
	    SetVarToObj(varPtr, varIndex, objv[3]);
	    break;
	case 8:				/* setlength */
	    if (objc != 4) {
		goto wrongNumArgs;
	    }
	    if (Tcl_GetIntFromObj(interp, objv[3], &length) != TCL_OK) {
	    if (Tcl_GetIntForIndex(interp, objv[3], TCL_INDEX_NONE, &length) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (varPtr[varIndex] != NULL) {
		Tcl_SetObjLength(varPtr[varIndex], length);
	    }
	    break;
	case 9:				/* maxchars */
	    if (objc != 3) {
		goto wrongNumArgs;
	    }
	    if (varPtr[varIndex] != NULL) {
		Tcl_ConvertToType(NULL, varPtr[varIndex],
			Tcl_GetObjType("string"));
		strPtr = (String *)varPtr[varIndex]->internalRep.twoPtrValue.ptr1;
		length = strPtr->maxChars;
	    } else {
		length = -1;
		length = TCL_INDEX_NONE;
	    }
	    Tcl_SetIntObj(Tcl_GetObjResult(interp), length);
	    Tcl_SetWideIntObj(Tcl_GetObjResult(interp), length);
	    break;
	case 10: {				/* range */
	    Tcl_Size first, last;
	    if (objc != 5) {
		goto wrongNumArgs;
	    }
	    if ((Tcl_GetIntForIndex(interp, objv[3], TCL_INDEX_NONE, &first) != TCL_OK)
		    || (Tcl_GetIntForIndex(interp, objv[4], TCL_INDEX_NONE, &last) != TCL_OK)) {
		return TCL_ERROR;
	    }
	    Tcl_SetObjResult(interp, Tcl_GetRange(varPtr[varIndex], first, last));
	    break;
	}
	case 10:			/* appendself */
	case 11:			/* appendself */
	    if (objc != 4) {
		goto wrongNumArgs;
	    }
	    if (varPtr[varIndex] == NULL) {
		SetVarToObj(varPtr, varIndex, Tcl_NewObj());
	    }

	    /*
	     * If the object bound to variable "varIndex" is shared, we must
	     * "copy on write" and append to a copy of the object.
	     */

	    if (Tcl_IsShared(varPtr[varIndex])) {
		SetVarToObj(varPtr, varIndex, Tcl_DuplicateObj(varPtr[varIndex]));
	    }

	    string = Tcl_GetStringFromObj(varPtr[varIndex], &length);
	    string = Tcl_GetStringFromObj(varPtr[varIndex], &size);

	    if (Tcl_GetIntFromObj(interp, objv[3], &i) != TCL_OK) {
	    if (Tcl_GetIntForIndex(interp, objv[3], size-1, &length) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if ((i < 0) || (i > length)) {
	    if (length == TCL_INDEX_NONE) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"index value out of range", -1));
		return TCL_ERROR;
	    }

	    Tcl_AppendToObj(varPtr[varIndex], string + i, length - i);
	    Tcl_AppendToObj(varPtr[varIndex], string + length, size - length);
	    Tcl_SetObjResult(interp, varPtr[varIndex]);
	    break;
	case 11:			/* appendself2 */
	case 12:			/* appendself2 */
	    if (objc != 4) {
		goto wrongNumArgs;
	    }
	    if (varPtr[varIndex] == NULL) {
		SetVarToObj(varPtr, varIndex, Tcl_NewObj());
	    }

	    /*
	     * If the object bound to variable "varIndex" is shared, we must
	     * "copy on write" and append to a copy of the object.
	     */

	    if (Tcl_IsShared(varPtr[varIndex])) {
		SetVarToObj(varPtr, varIndex, Tcl_DuplicateObj(varPtr[varIndex]));
	    }

	    unicode = Tcl_GetUnicodeFromObj(varPtr[varIndex], &length);
	    unicode = Tcl_GetUnicodeFromObj(varPtr[varIndex], &size);

	    if (Tcl_GetIntFromObj(interp, objv[3], &i) != TCL_OK) {
	    if (Tcl_GetIntForIndex(interp, objv[3], size-1, &length) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if ((i < 0) || (i > length)) {
	    if (length == TCL_INDEX_NONE) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"index value out of range", -1));
		return TCL_ERROR;
	    }

	    TclAppendUnicodeToObj(varPtr[varIndex], unicode + i, length - i);
	    Tcl_AppendUnicodeToObj(varPtr[varIndex], unicode + length, size - length);
	    Tcl_SetObjResult(interp, varPtr[varIndex]);
	    break;
	case 13: /* newunicode*/
	    unicode = (Tcl_UniChar *)Tcl_Alloc((objc - 3) * sizeof(Tcl_UniChar));
	    for (i = 0; i < (objc - 3); ++i) {
		int val;
		if (Tcl_GetIntFromObj(interp, objv[i + 3], &val) != TCL_OK) {
		    break;
		}
		unicode[i] = (Tcl_UniChar)val;
	    }
	    if (i < (objc-3)) {
		Tcl_Free(unicode);
		return TCL_ERROR;
	    }
	    SetVarToObj(varPtr, varIndex, Tcl_NewUnicodeObj(unicode, objc - 3));
	    Tcl_SetObjResult(interp, varPtr[varIndex]);
	    Tcl_Free(unicode);
	    break;
    }

    return TCL_OK;
}

/*
 *------------------------------------------------------------------------
 *
 * TestbigdataCmd --
 *
 *    Implements the Tcl command testbigdata
 *	testbigdata string ?LEN? ?SPLIT? - returns 01234567890123...
 *      testbigdata bytearray ?LEN? ?SPLIT? - returns {0 1 2 3 4 5 6 7 8 9 0 1 ...}
 *      testbigdata dict ?SIZE? - returns dict mapping integers to themselves
 *    If no arguments given, returns the pattern used to generate strings.
 *    If SPLIT is specified, the character at that position is set to "X".
 *
 * Results:
 *    TCL_OK    - Success.
 *    TCL_ERROR - Error.
 *
 * Side effects:
 *    Interpreter result holds result or error message.
 *
 *------------------------------------------------------------------------
 */
static int
TestbigdataCmd (
    TCL_UNUSED(void *),
    Tcl_Interp *interp,    /* Current interpreter. */
    int objc,              /* Number of arguments. */
    Tcl_Obj *const objv[]) /* Argument objects. */
{
    static const char *const subcmds[] = {
	   "string", "bytearray", "list", "dict", NULL
    };
    enum options {
	   BIGDATA_STRING, BIGDATA_BYTEARRAY, BIGDATA_LIST, BIGDATA_DICT
    } idx;
    char *s;
    unsigned char *p;
    Tcl_Size i, len, split;
    Tcl_DString ds;
    Tcl_Obj *objPtr;
#define PATTERN_LEN 10
    Tcl_Obj *patternObjs[PATTERN_LEN];

    if (objc < 2 || objc > 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "command ?len? ?split?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], subcmds, "option", 0,
	    &idx) != TCL_OK) {
	return TCL_ERROR;
    }
    split = -1;
    if (objc == 2) {
	len = PATTERN_LEN;
    } else {
	if (Tcl_GetSizeIntFromObj(interp, objv[2], &len) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (objc == 4) {
	    if (Tcl_GetSizeIntFromObj(interp, objv[3], &split) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (split >= len) {
		split = len - 1; /* Last position */
	    }
	}
    }
    /* Need one byte for nul terminator */
    Tcl_Size limit = TCL_SIZE_MAX-1;
    if (len < 0 || len > limit) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"%s is greater than max permitted length %" TCL_SIZE_MODIFIER "d",
		Tcl_GetString(objv[2]), limit));
	return TCL_ERROR;
    }

    switch (idx) {
    case BIGDATA_STRING:
	Tcl_DStringInit(&ds);
	Tcl_DStringSetLength(&ds, len);/* Also stores \0 at index len+1 */
	s = Tcl_DStringValue(&ds);
	for (i = 0; i < len; ++i) {
	    s[i] = '0' + (i % PATTERN_LEN);
	}
	if (split >= 0) {
	    assert(split < len);
	    s[split] = 'X';
	}
	Tcl_DStringResult(interp, &ds);
	break;
    case BIGDATA_BYTEARRAY:
	objPtr = Tcl_NewByteArrayObj(NULL, len);
	p = Tcl_GetByteArrayFromObj(objPtr, &len);
	for (i = 0; i < len; ++i) {
	    p[i] = '0' + (i % PATTERN_LEN);
	}
	if (split >= 0) {
	    assert(split < len);
	    p[split] = 'X';
	}
	Tcl_SetObjResult(interp, objPtr);
	break;
    case BIGDATA_LIST:
	for (i = 0; i < PATTERN_LEN; ++i) {
	    patternObjs[i] = Tcl_NewIntObj(i);
	    Tcl_IncrRefCount(patternObjs[i]);
	}
	objPtr = Tcl_NewListObj(len, NULL);
	for (i = 0; i < len; ++i) {
	    Tcl_ListObjAppendElement(
		interp, objPtr, patternObjs[i % PATTERN_LEN]);
	}
	if (split >= 0) {
	    assert(split < len);
	    Tcl_Obj *splitMarker = Tcl_NewStringObj("X", 1);
	    Tcl_ListObjReplace(interp, objPtr, split, 1, 1, &splitMarker);
	}
	for (i = 0; i < PATTERN_LEN; ++i) {
	    patternObjs[i] = Tcl_NewIntObj(i);
	    Tcl_DecrRefCount(patternObjs[i]);
	}
	Tcl_SetObjResult(interp, objPtr);
	break;
    case BIGDATA_DICT:
	objPtr = Tcl_NewDictObj();
	for (i = 0; i < len; ++i) {
	    Tcl_Obj *objPtr2 = Tcl_NewWideIntObj(i);
	    Tcl_DictObjPut(interp, objPtr, objPtr2, objPtr2);
	}
	Tcl_SetObjResult(interp, objPtr);
	break;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * SetVarToObj --
 *
 *	Utility routine to assign a Tcl_Obj* to a test variable. The
 *	Tcl_Obj* can be NULL.
1425
1426
1427
1428
1429
1430
1431
1432

1433
1434
1435
1436
1437
1438
1439
1738
1739
1740
1741
1742
1743
1744

1745
1746
1747
1748
1749
1750
1751
1752







-
+







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

static void
SetVarToObj(
    Tcl_Obj **varPtr,
    int varIndex,		/* Designates the assignment variable. */
    Tcl_Size varIndex,		/* Designates the assignment variable. */
    Tcl_Obj *objPtr)		/* Points to object to assign to var. */
{
    if (varPtr[varIndex] != NULL) {
	Tcl_DecrRefCount(varPtr[varIndex]);
    }
    varPtr[varIndex] = objPtr;
    if (objPtr != NULL) {
1456
1457
1458
1459
1460
1461
1462
1463

1464
1465
1466

1467
1468

1469
1470

1471
1472
1473

1474
1475
1476
1477
1478
1479
1480
1769
1770
1771
1772
1773
1774
1775

1776
1777
1778

1779
1780

1781
1782

1783
1784
1785

1786
1787
1788
1789
1790
1791
1792
1793







-
+


-
+

-
+

-
+


-
+







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

static int
GetVariableIndex(
    Tcl_Interp *interp,		/* Interpreter for error reporting. */
    const char *string,		/* String containing a variable index
    Tcl_Obj *obj,		/* The variable index
				 * specified as a nonnegative number less than
				 * NUMBER_OF_OBJECT_VARS. */
    int *indexPtr)		/* Place to store converted result. */
    Tcl_Size *indexPtr)		/* Place to store converted result. */
{
    int index;
    Tcl_Size index;

    if (Tcl_GetInt(interp, string, &index) != TCL_OK) {
    if (Tcl_GetIntForIndex(interp, obj, NUMBER_OF_OBJECT_VARS - 1, &index) != TCL_OK) {
	return TCL_ERROR;
    }
    if (index < 0 || index >= NUMBER_OF_OBJECT_VARS) {
    if (index == TCL_INDEX_NONE) {
	Tcl_ResetResult(interp);
	Tcl_AppendToObj(Tcl_GetObjResult(interp), "bad variable index", -1);
	return TCL_ERROR;
    }

    *indexPtr = index;
    return TCL_OK;
1498
1499
1500
1501
1502
1503
1504
1505

1506
1507

1508
1509
1510

1511
1512
1513
1514
1515
1516
1517
1811
1812
1813
1814
1815
1816
1817

1818
1819

1820
1821
1822

1823
1824
1825
1826
1827
1828
1829
1830







-
+

-
+


-
+







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

static int
CheckIfVarUnset(
    Tcl_Interp *interp,		/* Interpreter for error reporting. */
    Tcl_Obj ** varPtr,
    int varIndex)		/* Index of the test variable to check. */
    Tcl_Size varIndex)		/* Index of the test variable to check. */
{
    if (varPtr[varIndex] == NULL) {
    if (varIndex < 0 || varPtr[varIndex] == NULL) {
	char buf[32 + TCL_INTEGER_SPACE];

	sprintf(buf, "variable %d is unset (NULL)", varIndex);
	snprintf(buf, sizeof(buf), "variable %" TCL_SIZE_MODIFIER "d is unset (NULL)", varIndex);
	Tcl_ResetResult(interp);
	Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
	return 1;
    }
    return 0;
}


Changes to generic/tclTestProcBodyObj.c.

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
30
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
30
31
32







-
+





+
+









-
+







/*
 * tclTestProcBodyObj.c --
 *
 *	Implements the "procbodytest" package, which contains commands to test
 *	creation of Tcl procedures whose body argument is a Tcl_Obj of type
 *	"procbody" rather than a string.
 *
 * Copyright (c) 1998 by Scriptics Corporation.
 * Copyright © 1998 Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#undef BUILD_tcl
#undef STATIC_BUILD
#ifndef USE_TCL_STUBS
#   define USE_TCL_STUBS
#endif
#include "tclInt.h"

/*
 * name and version of this package
 */

static const char packageName[] = "procbodytest";
static const char packageName[] = "tcl::procbodytest";
static const char packageVersion[] = "1.1";

/*
 * Name of the commands exported by this package
 */

static const char procCommand[] = "proc";
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
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







-
+
-
-
+
-










-
-
+
+




-
-
+
+








-
+







    int exportIt;		/* if 1, export the command */
} CmdTable;

/*
 * Declarations for functions defined in this file.
 */

static int	ProcBodyTestProcObjCmd(void *dummy,
static Tcl_ObjCmdProc ProcBodyTestProcCmd;
			Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
static int	ProcBodyTestCheckObjCmd(void *dummy,
static Tcl_ObjCmdProc ProcBodyTestCheckCmd;
			Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
static int	ProcBodyTestInitInternal(Tcl_Interp *interp, int isSafe);
static int	RegisterCommand(Tcl_Interp* interp,
			const char *namesp, const CmdTable *cmdTablePtr);

/*
 * List of commands to create when the package is loaded; must go after the
 * declarations of the enable command procedure.
 */

static const CmdTable commands[] = {
    { procCommand,	ProcBodyTestProcObjCmd,	1 },
    { checkCommand,	ProcBodyTestCheckObjCmd,	1 },
    { procCommand,	ProcBodyTestProcCmd,	1 },
    { checkCommand,	ProcBodyTestCheckCmd,	1 },
    { 0, 0, 0 }
};

static const CmdTable safeCommands[] = {
    { procCommand,	ProcBodyTestProcObjCmd,	1 },
    { checkCommand,	ProcBodyTestCheckObjCmd,	1 },
    { procCommand,	ProcBodyTestProcCmd,	1 },
    { checkCommand,	ProcBodyTestCheckCmd,	1 },
    { 0, 0, 0 }
};

/*
 *----------------------------------------------------------------------
 *
 * Procbodytest_Init --
 *
 *	This function initializes the "procbodytest" package.
 *	This function initializes the "tcl::procbodytest" package.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
95
96
97
98
99
100
101
102

103
104
105
106
107
108
109
95
96
97
98
99
100
101

102
103
104
105
106
107
108
109







-
+







}

/*
 *----------------------------------------------------------------------
 *
 * Procbodytest_SafeInit --
 *
 *	This function initializes the "procbodytest" package.
 *	This function initializes the "tcl::procbodytest" package.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
142
143
144
145
146
147
148
149

150
151

152
153
154
155
156

157
158
159
160
161
162
163
142
143
144
145
146
147
148

149
150

151
152
153
154
155

156
157
158
159
160
161
162
163







-
+

-
+




-
+







    const char *namesp,		/* the namespace in which the command is
				 * registered */
    const CmdTable *cmdTablePtr)/* the command to register */
{
    char buf[128];

    if (cmdTablePtr->exportIt) {
	sprintf(buf, "namespace eval %s { namespace export %s }",
	snprintf(buf, sizeof(buf), "namespace eval %s { namespace export %s }",
		namesp, cmdTablePtr->cmdName);
	if (Tcl_EvalEx(interp, buf, -1, 0) != TCL_OK) {
	if (Tcl_EvalEx(interp, buf, TCL_INDEX_NONE, 0) != TCL_OK) {
	    return TCL_ERROR;
	}
    }

    sprintf(buf, "%s::%s", namesp, cmdTablePtr->cmdName);
    snprintf(buf, sizeof(buf), "%s::%s", namesp, cmdTablePtr->cmdName);
    Tcl_CreateObjCommand(interp, buf, cmdTablePtr->proc, 0, 0);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
192
193
194
195
196
197
198
199

200
201
202
203
204
205
206
192
193
194
195
196
197
198

199
200
201
202
203
204
205
206







-
+








    return Tcl_PkgProvideEx(interp, packageName, packageVersion, NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * ProcBodyTestProcObjCmd --
 * ProcBodyTestProcCmd --
 *
 *  Implements the "procbodytest::proc" command. Here is the command
 *  description:
 *	procbodytest::proc newName argList bodyName
 *  Looks up a procedure called $bodyName and, if the procedure exists,
 *  constructs a Tcl_Obj of type "procbody" and calls Tcl_ProcObjCmd.
 *  Arguments:
223
224
225
226
227
228
229
230

231
232
233
234
235
236
237
223
224
225
226
227
228
229

230
231
232
233
234
235
236
237







-
+







 *  A new procedure is created.
 *  Leaves an error message in the interp's result on error.
 *
 *----------------------------------------------------------------------
 */

static int
ProcBodyTestProcObjCmd(
ProcBodyTestProcCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* the current interpreter */
    int objc,			/* argument count */
    Tcl_Obj *const objv[])	/* arguments */
{
    const char *fullName;
    Tcl_Command procCmd;
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
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







-
+










-
+











-
+



















-
+






-
+










-
+













-
+











    /*
     * check that this is a procedure and not a builtin command:
     * If a procedure, cmdPtr->objClientData is TclIsProc(cmdPtr).
     */

    if (cmdPtr->objClientData != TclIsProc(cmdPtr)) {
	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
		"command \"", fullName, "\" is not a Tcl procedure", NULL);
		"command \"", fullName, "\" is not a Tcl procedure", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * it is a Tcl procedure: the client data is the Proc structure
     */

    procPtr = (Proc *) cmdPtr->objClientData;
    if (procPtr == NULL) {
	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "procedure \"",
		fullName, "\" does not have a Proc struct!", NULL);
		fullName, "\" does not have a Proc struct!", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * create a new object, initialize our argument vector, call into Tcl
     */

    bodyObjPtr = TclNewProcBodyObj(procPtr);
    if (bodyObjPtr == NULL) {
	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
		"failed to create a procbody object for procedure \"",
		fullName, "\"", NULL);
		fullName, "\"", (char *)NULL);
	return TCL_ERROR;
    }
    Tcl_IncrRefCount(bodyObjPtr);

    myobjv[0] = objv[0];
    myobjv[1] = objv[1];
    myobjv[2] = objv[2];
    myobjv[3] = bodyObjPtr;
    myobjv[4] = NULL;

    result = Tcl_ProcObjCmd(NULL, interp, objc, myobjv);
    Tcl_DecrRefCount(bodyObjPtr);

    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * ProcBodyTestCheckObjCmd --
 * ProcBodyTestCheckCmd --
 *
 *  Implements the "procbodytest::check" command. Here is the command
 *  description:
 *	procbodytest::check
 *
 *  Performs an internal check that the Tcl_PkgPresent() command returns
 *  the same version number as was registered when the procbodytest package
 *  the same version number as was registered when the tcl::procbodytest package
 *  was provided.  Places a boolean in the interp result indicating the
 *  test outcome.
 *
 * Results:
 *  Returns a standard Tcl code.
 *
 *----------------------------------------------------------------------
 */

static int
ProcBodyTestCheckObjCmd(
ProcBodyTestCheckCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* the current interpreter */
    int objc,			/* argument count */
    Tcl_Obj *const objv[])	/* arguments */
{
    const char *version;

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

    version = Tcl_PkgPresentEx(interp, packageName, packageVersion, 1, NULL);
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
	    strcmp(version, packageVersion) == 0));
    return TCL_OK;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclThread.c.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * tclThread.c --
 *
 *	This file implements Platform independent thread operations. Most of
 *	the real work is done in the platform dependent files.
 *
 * Copyright (c) 1998 by Sun Microsystems, Inc.
 * Copyright (c) 2008 by George Peter Staplin
 * Copyright © 1998 Sun Microsystems, Inc.
 * Copyright © 2008 George Peter Staplin
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

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
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







-
+


















-
+







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

void *
Tcl_GetThreadData(
    Tcl_ThreadDataKey *keyPtr,	/* Identifier for the data chunk */
    size_t size)		/* Size of storage block */
    Tcl_Size size)		/* Size of storage block */
{
    void *result;
#if TCL_THREADS
    /*
     * Initialize the key for this thread.
     */

    result = TclThreadStorageKeyGet(keyPtr);

    if (result == NULL) {
	result = Tcl_Alloc(size);
	memset(result, 0, size);
	TclThreadStorageKeySet(keyPtr, result);
    }
#else /* TCL_THREADS */
    if (*keyPtr == NULL) {
	result = Tcl_Alloc(size);
	memset(result, 0, size);
	*keyPtr = result;
	*keyPtr = (Tcl_ThreadDataKey)result;
	RememberSyncObject(keyPtr, &keyRecord);
    } else {
	result = *keyPtr;
    }
#endif /* TCL_THREADS */
    return result;
}
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
140
141
142
143
144
145
146

147
148
149
150
151
152
153







-







static void
RememberSyncObject(
    void *objPtr,		/* Pointer to sync object */
    SyncObjRecord *recPtr)	/* Record of sync objects */
{
    void **newList;
    int i, j;


    /*
     * Reuse any free slot in the list.
     */

    for (i=0 ; i < recPtr->num ; ++i) {
	if (recPtr->list[i] == NULL) {
453
454
455
456
457
458
459
460

461
462
463
464
465
466
467
452
453
454
455
456
457
458

459
460
461
462
463
464
465
466







-
+







 *
 * Side effects:
 *	All thread exit handlers are invoked, then the thread dies.
 *
 *----------------------------------------------------------------------
 */

void
TCL_NORETURN void
Tcl_ExitThread(
    int status)
{
    Tcl_FinalizeThread();
    TclpThreadExit(status);
}

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
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







-
-
-
+
+
+






-
+






-
+






-
+











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

#undef Tcl_ConditionWait
void
Tcl_ConditionWait(
    Tcl_Condition *condPtr,	/* Really (pthread_cond_t **) */
    Tcl_Mutex *mutexPtr,	/* Really (pthread_mutex_t **) */
    const Tcl_Time *timePtr) /* Timeout on waiting period */
    TCL_UNUSED(Tcl_Condition *),	/* Really (pthread_cond_t **) */
    TCL_UNUSED(Tcl_Mutex *),	/* Really (pthread_mutex_t **) */
    TCL_UNUSED(const Tcl_Time *)) /* Timeout on waiting period */
{
}

#undef Tcl_ConditionNotify
void
Tcl_ConditionNotify(
    Tcl_Condition *condPtr)
    TCL_UNUSED(Tcl_Condition *))
{
}

#undef Tcl_MutexLock
void
Tcl_MutexLock(
    Tcl_Mutex *mutexPtr)
    TCL_UNUSED(Tcl_Mutex *))
{
}

#undef Tcl_MutexUnlock
void
Tcl_MutexUnlock(
    Tcl_Mutex *mutexPtr)
    TCL_UNUSED(Tcl_Mutex *))
{
}
#endif /* !TCL_THREADS */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclThreadAlloc.c.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







/*
 * tclThreadAlloc.c --
 *
 *	This is a very fast storage allocator for used with threads (designed
 *	avoid lock contention). The basic strategy is to allocate memory in
 *	fixed size blocks from block caches.
 *
 * The Initial Developer of the Original Code is America Online, Inc.
 * Portions created by AOL are Copyright (C) 1999 America Online, Inc.
 * Portions created by AOL are Copyright © 1999 America Online, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#if TCL_THREADS && defined(USE_THREAD_ALLOC)
65
66
67
68
69
70
71
72

73
74
75
76
77
78
79
65
66
67
68
69
70
71

72
73
74
75
76
77
78
79







-
+







#define sourceBucket	b.u.s.bucket
#define magicNum1	b.u.s.magic1
#define magicNum2	b.u.s.magic2
#define MAGIC		0xEF
#define blockReqSize	b.reqSize

/*
 * The following defines the minimum and and maximum block sizes and the number
 * The following defines the minimum and maximum block sizes and the number
 * of buckets in the bucket cache.
 */

#define MINALLOC	((sizeof(Block) + 8 + (TCL_ALLOCALIGN-1)) & ~(TCL_ALLOCALIGN-1))
#define NBUCKETS	(11 - (MINALLOC >> 5))
#define MAXALLOC	(MINALLOC << (NBUCKETS - 1))

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
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







-

-
+













-
+

-
+







    Block *lastPtr;		/* End of block list */
    size_t numFree;		/* Number of blocks available */

    /* All fields below for accounting only */

    size_t numRemoves;		/* Number of removes from bucket */
    size_t numInserts;		/* Number of inserts into bucket */
    size_t numWaits;		/* Number of waits to acquire a lock */
    size_t numLocks;		/* Number of locks acquired */
    size_t totalAssigned;	/* Total space assigned to bucket */
    size_t totalAssigned;		/* Total space assigned to bucket */
} Bucket;

/*
 * The following structure defines a cache of buckets and objs, of which there
 * will be (at most) one per thread. Any changes need to be reflected in the
 * struct AllocCache defined in tclInt.h, possibly also in the initialisation
 * code in Tcl_CreateInterp().
 */

typedef struct Cache {
    struct Cache *nextPtr;	/* Linked list of cache entries */
    Tcl_ThreadId owner;		/* Which thread's cache is this? */
    Tcl_Obj *firstObjPtr;	/* List of free objects for thread */
    int numObjects;		/* Number of objects for thread */
    size_t numObjects;		/* Number of objects for thread */
    Tcl_Obj *lastPtr;		/* Last object in this cache */
    int totalAssigned;		/* Total space assigned to thread */
    size_t totalAssigned;	/* Total space assigned to thread */
    Bucket buckets[NBUCKETS];	/* The buckets for this thread */
} Cache;

/*
 * The following array specifies various per-bucket limits and locks. The
 * values are statically initialized to avoid calculating them repeatedly.
 */
128
129
130
131
132
133
134
135

136
137
138
139
140



141
142
143
144
145
146
147
127
128
129
130
131
132
133

134
135
136



137
138
139
140
141
142
143
144
145
146







-
+


-
-
-
+
+
+







/*
 * Static functions defined in this file.
 */

static Cache *	GetCache(void);
static void	LockBucket(Cache *cachePtr, int bucket);
static void	UnlockBucket(Cache *cachePtr, int bucket);
static void	PutBlocks(Cache *cachePtr, int bucket, int numMove);
static void	PutBlocks(Cache *cachePtr, int bucket, size_t numMove);
static int	GetBlocks(Cache *cachePtr, int bucket);
static Block *	Ptr2Block(void *ptr);
static void *	Block2Ptr(Block *blockPtr, int bucket, unsigned int reqSize);
static void	MoveObjs(Cache *fromPtr, Cache *toPtr, int numMove);
static void	PutObjs(Cache *fromPtr, int numMove);
static void *	Block2Ptr(Block *blockPtr, int bucket, size_t reqSize);
static void	MoveObjs(Cache *fromPtr, Cache *toPtr, size_t numMove);
static void	PutObjs(Cache *fromPtr, size_t numMove);

/*
 * Local variables defined in this file and initialized at startup.
 */

static Tcl_Mutex *listLockPtr;
static Tcl_Mutex *objLockPtr;
211
212
213
214
215
216
217
218

219
220
221
222
223
224
225
210
211
212
213
214
215
216

217
218
219
220
221
222
223
224







-
+








    cachePtr = (Cache*)TclpGetAllocCache();
    if (cachePtr == NULL) {
	cachePtr = (Cache*)TclpSysAlloc(sizeof(Cache));
	if (cachePtr == NULL) {
	    Tcl_Panic("alloc: could not allocate new cache");
	}
        memset(cachePtr, 0, sizeof(Cache));
	memset(cachePtr, 0, sizeof(Cache));
	Tcl_MutexLock(listLockPtr);
	cachePtr->nextPtr = firstCachePtr;
	firstCachePtr = cachePtr;
	Tcl_MutexUnlock(listLockPtr);
	cachePtr->owner = Tcl_GetCurrentThread();
	TclpSetAllocCache(cachePtr);
    }
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
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







-
+
















-
+



-
+








    /*
     * Get this thread's obj list structure and move or allocate new objs if
     * necessary.
     */

    if (cachePtr->numObjects == 0) {
	int numMove;
	size_t numMove;

	Tcl_MutexLock(objLockPtr);
	numMove = sharedPtr->numObjects;
	if (numMove > 0) {
	    if (numMove > NOBJALLOC) {
		numMove = NOBJALLOC;
	    }
	    MoveObjs(sharedPtr, cachePtr, numMove);
	}
	Tcl_MutexUnlock(objLockPtr);
	if (cachePtr->numObjects == 0) {
	    Tcl_Obj *newObjsPtr;

	    cachePtr->numObjects = numMove = NOBJALLOC;
	    newObjsPtr = (Tcl_Obj *)TclpSysAlloc(sizeof(Tcl_Obj) * numMove);
	    if (newObjsPtr == NULL) {
		Tcl_Panic("alloc: could not allocate %d new objects", numMove);
		Tcl_Panic("alloc: could not allocate %" TCL_Z_MODIFIER "u new objects", numMove);
	    }
	    cachePtr->lastPtr = newObjsPtr + numMove - 1;
	    objPtr = cachePtr->firstObjPtr;	/* NULL */
	    while (--numMove >= 0) {
	    while (numMove-- > 0) {
		newObjsPtr[numMove].internalRep.twoPtrValue.ptr1 = objPtr;
		objPtr = newObjsPtr + numMove;
	    }
	    cachePtr->firstObjPtr = newObjsPtr;
	}
    }

637
638
639
640
641
642
643
644

645
646
647

648

649
650
651
652
653
654

655
656
657
658
659
660
661
662
636
637
638
639
640
641
642

643
644
645
646
647

648
649
650
651
652
653

654

655
656
657
658
659
660
661







-
+



+
-
+





-
+
-







    Tcl_MutexLock(listLockPtr);
    cachePtr = firstCachePtr;
    while (cachePtr != NULL) {
	Tcl_DStringStartSublist(dsPtr);
	if (cachePtr == sharedPtr) {
	    Tcl_DStringAppendElement(dsPtr, "shared");
	} else {
	    sprintf(buf, "thread%p", cachePtr->owner);
	    snprintf(buf, sizeof(buf), "thread%p", cachePtr->owner);
	    Tcl_DStringAppendElement(dsPtr, buf);
	}
	for (n = 0; n < NBUCKETS; ++n) {
	    snprintf(buf, sizeof(buf), "%" TCL_Z_MODIFIER "u %" TCL_Z_MODIFIER "u %" TCL_Z_MODIFIER "u %"
	    sprintf(buf, "%" TCL_Z_MODIFIER "u %" TCL_Z_MODIFIER "u %" TCL_Z_MODIFIER "u %" TCL_Z_MODIFIER "u %" TCL_Z_MODIFIER "u %" TCL_Z_MODIFIER "u %" TCL_Z_MODIFIER "u",
		    TCL_Z_MODIFIER "u %" TCL_Z_MODIFIER "u %" TCL_Z_MODIFIER "u",
		    bucketInfo[n].blockSize,
		    cachePtr->buckets[n].numFree,
		    cachePtr->buckets[n].numRemoves,
		    cachePtr->buckets[n].numInserts,
		    cachePtr->buckets[n].totalAssigned,
		    cachePtr->buckets[n].numLocks,
		    cachePtr->buckets[n].numLocks);
		    cachePtr->buckets[n].numWaits);
	    Tcl_DStringAppendElement(dsPtr, buf);
	}
	Tcl_DStringEndSublist(dsPtr);
	cachePtr = cachePtr->nextPtr;
    }
    Tcl_MutexUnlock(listLockPtr);
}
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
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







-
+












-
+







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

static void
MoveObjs(
    Cache *fromPtr,
    Cache *toPtr,
    int numMove)
    size_t numMove)
{
    Tcl_Obj *objPtr = fromPtr->firstObjPtr;
    Tcl_Obj *fromFirstObjPtr = objPtr;

    toPtr->numObjects += numMove;
    fromPtr->numObjects -= numMove;

    /*
     * Find the last object to be moved; set the next one (the first one not
     * to be moved) as the first object in the 'from' cache.
     */

    while (--numMove) {
    while (numMove-- > 1) {
	objPtr = (Tcl_Obj *)objPtr->internalRep.twoPtrValue.ptr1;
    }
    fromPtr->firstObjPtr = (Tcl_Obj *)objPtr->internalRep.twoPtrValue.ptr1;

    /*
     * Move all objects as a block - they are already linked to each other, we
     * just have to update the first and last.
724
725
726
727
728
729
730
731

732
733

734
735
736
737
738
739
740
741
742
743
744

745
746
747
748
749
750
751
723
724
725
726
727
728
729

730
731

732
733
734
735
736
737
738
739
740
741
742

743
744
745
746
747
748
749
750







-
+

-
+










-
+







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

static void
PutObjs(
    Cache *fromPtr,
    int numMove)
    size_t numMove)
{
    int keep = fromPtr->numObjects - numMove;
    size_t keep = fromPtr->numObjects - numMove;
    Tcl_Obj *firstPtr, *lastPtr = NULL;

    fromPtr->numObjects = keep;
    firstPtr = fromPtr->firstObjPtr;
    if (keep == 0) {
	fromPtr->firstObjPtr = NULL;
    } else {
	do {
	    lastPtr = firstPtr;
	    firstPtr = (Tcl_Obj *)firstPtr->internalRep.twoPtrValue.ptr1;
	} while (--keep > 0);
	} while (keep-- > 1);
	lastPtr->internalRep.twoPtrValue.ptr1 = NULL;
    }

    /*
     * Move all objects as a block - they are already linked to each other, we
     * just have to update the first and last.
     */
778
779
780
781
782
783
784
785

786
787
788
789
790
791
792
777
778
779
780
781
782
783

784
785
786
787
788
789
790
791







-
+







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

static void *
Block2Ptr(
    Block *blockPtr,
    int bucket,
    unsigned int reqSize)
    size_t reqSize)
{
    void *ptr;

    blockPtr->magicNum1 = blockPtr->magicNum2 = MAGIC;
    blockPtr->sourceBucket = bucket;
    blockPtr->blockReqSize = reqSize;
    ptr = ((void *) (blockPtr + 1));
868
869
870
871
872
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
898
899
900
867
868
869
870
871
872
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
898
899







-
+






-
+










-
+







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

static void
PutBlocks(
    Cache *cachePtr,
    int bucket,
    int numMove)
    size_t numMove)
{
    /*
     * We have numFree.  Want to shed numMove. So compute how many
     * Blocks to keep.
     */

    int keep = cachePtr->buckets[bucket].numFree - numMove;
    size_t keep = cachePtr->buckets[bucket].numFree - numMove;
    Block *lastPtr = NULL, *firstPtr;

    cachePtr->buckets[bucket].numFree = keep;
    firstPtr = cachePtr->buckets[bucket].firstPtr;
    if (keep == 0) {
	cachePtr->buckets[bucket].firstPtr = NULL;
    } else {
	do {
	    lastPtr = firstPtr;
	    firstPtr = firstPtr->nextBlock;
	} while (--keep > 0);
	} while (keep-- > 1);
	lastPtr->nextBlock = NULL;
    }

    /*
     * Aquire the lock and place the list of blocks at the front of the shared
     * cache bucket.
     */
934
935
936
937
938
939
940
941

942
943
944
945
946
947
948
933
934
935
936
937
938
939

940
941
942
943
944
945
946
947







-
+







    Cache *cachePtr,
    int bucket)
{
    Block *blockPtr;
    size_t n;

    /*
     * First, atttempt to move blocks from the shared cache. Note the
     * First, attempt to move blocks from the shared cache. Note the
     * potentially dirty read of numFree before acquiring the lock which is a
     * slight performance enhancement. The value is verified after the lock is
     * actually acquired.
     */

    if (cachePtr != sharedPtr && sharedPtr->buckets[bucket].numFree > 0) {
	LockBucket(cachePtr, bucket);
964
965
966
967
968
969
970
971

972
973
974
975
976
977
978
963
964
965
966
967
968
969

970
971
972
973
974
975
976
977







-
+







		sharedPtr->buckets[bucket].firstPtr = NULL;
		sharedPtr->buckets[bucket].numFree = 0;
	    } else {
		blockPtr = sharedPtr->buckets[bucket].firstPtr;
		cachePtr->buckets[bucket].firstPtr = blockPtr;
		sharedPtr->buckets[bucket].numFree -= n;
		cachePtr->buckets[bucket].numFree = n;
		while (--n > 0) {
		while (n-- > 1) {
		    blockPtr = blockPtr->nextBlock;
		}
		sharedPtr->buckets[bucket].firstPtr = blockPtr->nextBlock;
		cachePtr->buckets[bucket].lastPtr = blockPtr;
		blockPtr->nextBlock = NULL;
	    }
	}
986
987
988
989
990
991
992
993

994
995
996
997
998
999
1000
985
986
987
988
989
990
991

992
993
994
995
996
997
998
999







-
+







	 * If no blocks could be moved from shared, first look for a larger
	 * block in this cache to split up.
	 */

	blockPtr = NULL;
	n = NBUCKETS;
	size = 0;
	while (--n > (size_t)bucket) {
	while (n-- > (size_t)bucket + 1) {
	    if (cachePtr->buckets[n].numFree > 0) {
		size = bucketInfo[n].blockSize;
		blockPtr = cachePtr->buckets[n].firstPtr;
		cachePtr->buckets[n].firstPtr = blockPtr->nextBlock;
		cachePtr->buckets[n].numFree--;
		break;
	    }
1015
1016
1017
1018
1019
1020
1021
1022

1023
1024
1025
1026
1027
1028
1029
1014
1015
1016
1017
1018
1019
1020

1021
1022
1023
1024
1025
1026
1027
1028







-
+







	/*
	 * Split the larger block into smaller blocks for this bucket.
	 */

	n = size / bucketInfo[bucket].blockSize;
	cachePtr->buckets[bucket].numFree = n;
	cachePtr->buckets[bucket].firstPtr = blockPtr;
	while (--n > 0) {
	while (n-- > 1) {
	    blockPtr->nextBlock = (Block *)
		((char *) blockPtr + bucketInfo[bucket].blockSize);
	    blockPtr = blockPtr->nextBlock;
	}
	cachePtr->buckets[bucket].lastPtr = blockPtr;
	blockPtr->nextBlock = NULL;
    }
1054
1055
1056
1057
1058
1059
1060
1061

1062
1063
1064
1065
1066
1067
1068
1053
1054
1055
1056
1057
1058
1059

1060
1061
1062
1063
1064
1065
1066
1067







-
+








    listLockPtr = TclpNewAllocMutex();
    objLockPtr = TclpNewAllocMutex();
    for (i = 0; i < NBUCKETS; ++i) {
	bucketInfo[i].blockSize = MINALLOC << i;
	bucketInfo[i].maxBlocks = ((size_t)1) << (NBUCKETS - 1 - i);
	bucketInfo[i].numMove = i < NBUCKETS - 1 ?
		1 << (NBUCKETS - 2 - i) : 1;
		(size_t)1 << (NBUCKETS - 2 - i) : 1;
	bucketInfo[i].lockPtr = TclpNewAllocMutex();
    }
    TclpInitAllocCache();
}

/*
 *----------------------------------------------------------------------

Changes to generic/tclThreadJoin.c.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







/*
 * tclThreadJoin.c --
 *
 *	This file implements a platform independent emulation layer for the
 *	handling of joinable threads. The Windows platform uses this code to
 *	provide the functionality of joining threads.  This code is currently
 *	not necessary on Unix.
 *
 * Copyright (c) 2000 by Scriptics Corporation
 * Copyright © 2000 Scriptics Corporation
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

207
208
209
210
211
212
213
214
215


216
217
218
219
220
221
222
207
208
209
210
211
212
213


214
215
216
217
218
219
220
221
222







-
-
+
+







}

/*
 *----------------------------------------------------------------------
 *
 * TclRememberJoinableThread --
 *
 *	This procedure remebers a thread as joinable. Only a call to
 *	TclJoinThread will remove the structre created (and initialized) here.
 *	This procedure remembers a thread as joinable. Only a call to
 *	TclJoinThread will remove the structure created (and initialized) here.
 *	IOW, not waiting upon a joinable thread will cause memory leaks.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Allocates memory, adds it to the global list of all joinable threads.
301
302
303
304
305
306
307


308
309
310
311
312
313
314
315
316
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318







+
+










    if (threadPtr->waitedUpon) {
	Tcl_ConditionNotify(&threadPtr->cond);
    }

    Tcl_MutexUnlock(&threadPtr->threadMutex);
}
#else
TCL_MAC_EMPTY_FILE(generic_tclThreadJoin_c)
#endif /* _WIN32 */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclThreadStorage.c.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * tclThreadStorage.c --
 *
 *	This file implements platform independent thread storage operations to
 *	work around system limits on the number of thread-specific variables.
 *
 * Copyright (c) 2003-2004 by Joe Mistachkin
 * Copyright (c) 2008 by George Peter Staplin
 * Copyright © 2003-2004 Joe Mistachkin
 * Copyright © 2008 George Peter Staplin
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58







-
+







} tsdGlobal = { NULL, 0, NULL };

/*
 * The type of the data held per thread in a system TSD.
 */

typedef struct {
    ClientData *tablePtr;	/* The table of Tcl TSDs. */
    void **tablePtr;	/* The table of Tcl TSDs. */
    sig_atomic_t allocated;	/* The size of the table in the current
				 * thread. */
} TSDTable;

/*
 * The actual type of Tcl_ThreadDataKey.
 */
186
187
188
189
190
191
192
193

194
195
196
197
198
199
200
186
187
188
189
190
191
192

193
194
195
196
197
198
199
200







-
+







 */

void *
TclThreadStorageKeyGet(
    Tcl_ThreadDataKey *dataKeyPtr)
{
    TSDTable *tsdTablePtr = (TSDTable *)TclpThreadGetGlobalTSD(tsdGlobal.key);
    ClientData resultPtr = NULL;
    void *resultPtr = NULL;
    TSDUnion *keyPtr = (TSDUnion *) dataKeyPtr;
    sig_atomic_t offset = keyPtr->offset;

    if ((tsdTablePtr != NULL) && (offset > 0)
	    && (offset < tsdTablePtr->allocated)) {
	resultPtr = tsdTablePtr->tablePtr[offset];
    }

Changes to generic/tclThreadTest.c.

1
2
3
4
5
6
7
8
9
10


11
12
13
14
15


16
17
18
19
20
21
22
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24








-
-
+
+





+
+







/*
 * tclThreadTest.c --
 *
 *	This file implements the testthread command. Eventually this should be
 *	tclThreadCmd.c
 *	Some of this code is based on work done by Richard Hipp on behalf of
 *	Conservation Through Innovation, Limited, with their permission.
 *
 * Copyright (c) 1998 by Sun Microsystems, Inc.
 * Copyright (c) 2006-2008 by Joe Mistachkin.  All rights reserved.
 * Copyright © 1998 Sun Microsystems, Inc.
 * Copyright © 2006-2008 Joe Mistachkin.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#undef BUILD_tcl
#undef STATIC_BUILD
#ifndef USE_TCL_STUBS
#   define USE_TCL_STUBS
#endif
#include "tclInt.h"

#if TCL_THREADS
/*
115
116
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
117
118
119
120
121
122
123



124
125
126
127
128
129
130
131







-
-
-
+







/*
 * Access to the list of threads and to the thread send results is guarded by
 * this mutex.
 */

TCL_DECLARE_MUTEX(threadMutex)

static int		ThreadObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static Tcl_ObjCmdProc ThreadCmd;
static int		ThreadCreate(Tcl_Interp *interp, const char *script,
			    int joinable);
static int		ThreadList(Tcl_Interp *interp);
static int		ThreadSend(Tcl_Interp *interp, Tcl_ThreadId id,
			    const char *script, int wait);
static int		ThreadCancel(Tcl_Interp *interp, Tcl_ThreadId id,
			    const char *result, int flags);
167
168
169
170
171
172
173
174

175
176
177
178
179
180
181

182
183
184
185
186
187
188
167
168
169
170
171
172
173

174
175
176
177
178
179
180

181
182
183
184
185
186
187
188







-
+






-
+








    Tcl_MutexLock(&threadMutex);
    if (mainThreadId == 0) {
	mainThreadId = Tcl_GetCurrentThread();
    }
    Tcl_MutexUnlock(&threadMutex);

    Tcl_CreateObjCommand(interp, "testthread", ThreadObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testthread", ThreadCmd, NULL, NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ThreadObjCmd --
 * ThreadCmd --
 *
 *	This procedure is invoked to process the "testthread" Tcl command. See
 *	the user documentation for details on what it does.
 *
 *	thread cancel ?-unwind? id ?result?
 *	thread create ?-joinable? ?script?
 *	thread send ?-async? id script
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
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







-
+






-









-
+







 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ThreadObjCmd(
ThreadCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    int option;
    static const char *const threadOptions[] = {
	"cancel", "create", "event", "exit", "id",
	"join", "names", "send", "wait", "errorproc",
	NULL
    };
    enum options {
	THREAD_CANCEL, THREAD_CREATE, THREAD_EVENT, THREAD_EXIT,
	THREAD_ID, THREAD_JOIN, THREAD_NAMES, THREAD_SEND,
	THREAD_WAIT, THREAD_ERRORPROC
    };
    } option;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], threadOptions, "option", 0,
	    &option) != TCL_OK) {
240
241
242
243
244
245
246
247

248
249
250
251
252
253
254
239
240
241
242
243
244
245

246
247
248
249
250
251
252
253







-
+







	Tcl_MutexLock(&threadMutex);
	tsdPtr->interp = interp;
	ListUpdateInner(tsdPtr);
	Tcl_CreateThreadExitHandler(ThreadExitProc, NULL);
	Tcl_MutexUnlock(&threadMutex);
    }

    switch ((enum options)option) {
    switch (option) {
    case THREAD_CANCEL: {
	Tcl_WideInt id;
	const char *result;
	int flags, arg;

	if ((objc < 3) || (objc > 5)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?-unwind? id ?result?");
267
268
269
270
271
272
273
274

275
276
277
278


279
280
281
282
283
284
285
266
267
268
269
270
271
272

273
274
275
276

277
278
279
280
281
282
283
284
285







-
+



-
+
+







	}
	arg++;
	if (arg < objc) {
	    result = Tcl_GetString(objv[arg]);
	} else {
	    result = NULL;
	}
	return ThreadCancel(interp, (Tcl_ThreadId) (size_t) id, result, flags);
	return ThreadCancel(interp, (Tcl_ThreadId) INT2PTR(id), result, flags);
    }
    case THREAD_CREATE: {
	const char *script;
	int joinable, len;
	int joinable;
	Tcl_Size len;

	if (objc == 2) {
	    /*
	     * Neither joinable nor special script
	     */

	    joinable = 0;
331
332
333
334
335
336
337
338

339
340
341
342

343
344
345
346
347
348
349
331
332
333
334
335
336
337

338
339
340
341

342
343
344
345
346
347
348
349







-
+



-
+







	    Tcl_Obj *idObj;

	    /*
	     * Check if they want the main thread id or the current thread id.
	     */

	    if (objc == 2) {
		idObj = Tcl_NewWideIntObj((Tcl_WideInt)(size_t)Tcl_GetCurrentThread());
		idObj = Tcl_NewWideIntObj((Tcl_WideInt)PTR2INT(Tcl_GetCurrentThread()));
	    } else if (objc == 3
		    && strcmp("-main", Tcl_GetString(objv[2])) == 0) {
		Tcl_MutexLock(&threadMutex);
		idObj = Tcl_NewWideIntObj((Tcl_WideInt)(size_t)mainThreadId);
		idObj = Tcl_NewWideIntObj((Tcl_WideInt)PTR2INT(mainThreadId));
		Tcl_MutexUnlock(&threadMutex);
	    } else {
		Tcl_WrongNumArgs(interp, 2, objv, NULL);
		return TCL_ERROR;
	    }

	    Tcl_SetObjResult(interp, idObj);
360
361
362
363
364
365
366
367

368
369
370
371

372
373
374


375
376
377
378
379
380
381
360
361
362
363
364
365
366

367
368
369
370

371
372


373
374
375
376
377
378
379
380
381







-
+



-
+

-
-
+
+







	    Tcl_WrongNumArgs(interp, 2, objv, "id");
	    return TCL_ERROR;
	}
	if (Tcl_GetWideIntFromObj(interp, objv[2], &id) != TCL_OK) {
	    return TCL_ERROR;
	}

	result = Tcl_JoinThread((Tcl_ThreadId)(size_t)id, &status);
	result = Tcl_JoinThread((Tcl_ThreadId)INT2PTR(id), &status);
	if (result == TCL_OK) {
	    Tcl_SetIntObj(Tcl_GetObjResult(interp), status);
	} else {
	    char buf[20];
	    char buf[TCL_INTEGER_SPACE];

	    sprintf(buf, "%" TCL_LL_MODIFIER "d", id);
	    Tcl_AppendResult(interp, "cannot join thread ", buf, NULL);
	    snprintf(buf, sizeof(buf), "%" TCL_LL_MODIFIER "d", (long long)id);
	    Tcl_AppendResult(interp, "cannot join thread ", buf, (char *)NULL);
	}
	return result;
    }
    case THREAD_NAMES:
	if (objc > 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
402
403
404
405
406
407
408
409

410
411
412
413
414
415
416
402
403
404
405
406
407
408

409
410
411
412
413
414
415
416







-
+







	    arg = 2;
	}
	if (Tcl_GetWideIntFromObj(interp, objv[arg], &id) != TCL_OK) {
	    return TCL_ERROR;
	}
	arg++;
	script = Tcl_GetString(objv[arg]);
	return ThreadSend(interp, (Tcl_ThreadId)(size_t)id, script, wait);
	return ThreadSend(interp, (Tcl_ThreadId)INT2PTR(id), script, wait);
    }
    case THREAD_EVENT: {
	if (objc > 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
505
506
507
508
509
510
511
512

513
514
515
516
517
518
519
505
506
507
508
509
510
511

512
513
514
515
516
517
518
519







-
+








    joinable = joinable ? TCL_THREAD_JOINABLE : TCL_THREAD_NOFLAGS;

    Tcl_MutexLock(&threadMutex);
    if (Tcl_CreateThread(&id, NewTestThread, &ctrl,
	    TCL_THREAD_STACK_DEFAULT, joinable) != TCL_OK) {
	Tcl_MutexUnlock(&threadMutex);
	Tcl_AppendResult(interp, "can't create a new thread", NULL);
	Tcl_AppendResult(interp, "cannot create a new thread", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Wait for the thread to start because it is using something on our stack!
     */

606
607
608
609
610
611
612
613

614
615
616
617
618
619
620
606
607
608
609
610
611
612

613
614
615
616
617
618
619
620







-
+







    Tcl_MutexUnlock(&threadMutex);

    /*
     * Run the script.
     */

    Tcl_Preserve(tsdPtr->interp);
    result = Tcl_EvalEx(tsdPtr->interp, threadEvalScript, -1, 0);
    result = Tcl_EvalEx(tsdPtr->interp, threadEvalScript, TCL_INDEX_NONE, 0);
    if (result != TCL_OK) {
	ThreadErrorProc(tsdPtr->interp);
    }

    /*
     * Clean up.
     */
648
649
650
651
652
653
654
655

656
657
658
659
660
661
662
648
649
650
651
652
653
654

655
656
657
658
659
660
661
662







-
+







    Tcl_Interp *interp)		/* Interp that failed */
{
    Tcl_Channel errChannel;
    const char *errorInfo, *argv[3];
    char *script;
    char buf[TCL_DOUBLE_SPACE+1];

    sprintf(buf, "%p", Tcl_GetCurrentThread());
    snprintf(buf, sizeof(buf), "%p", Tcl_GetCurrentThread());

    errorInfo = Tcl_GetVar2(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY);
    if (errorProcString == NULL) {
	errChannel = Tcl_GetStdChannel(TCL_STDERR);
	Tcl_WriteChars(errChannel, "Error from thread ", -1);
	Tcl_WriteChars(errChannel, buf, -1);
	Tcl_WriteChars(errChannel, "\n", 1);
816
817
818
819
820
821
822
823

824
825
826
827
828

829
830
831
832
833
834
835
816
817
818
819
820
821
822

823
824
825
826
827

828
829
830
831
832
833
834
835







-
+




-
+







	if (tsdPtr->threadId == threadId) {
	    found = 1;
	    break;
	}
    }
    if (!found) {
	Tcl_MutexUnlock(&threadMutex);
	Tcl_AppendResult(interp, "invalid thread id", NULL);
	Tcl_AppendResult(interp, "invalid thread id", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Short circut sends to ourself. Ought to do something with -async, like
     * Short circuit sends to ourself. Ought to do something with -async, like
     * run in an idle handler.
     */

    if (threadId == Tcl_GetCurrentThread()) {
	Tcl_MutexUnlock(&threadMutex);
	return Tcl_EvalEx(interp, script,-1,TCL_EVAL_GLOBAL);
    }
874
875
876
877
878
879
880
881

882
883
884
885
886
887
888
889
874
875
876
877
878
879
880

881

882
883
884
885
886
887
888







-
+
-








    /*
     * Queue the event and poke the other thread's notifier.
     */

    threadEventPtr->event.proc = ThreadEventProc;
    Tcl_ThreadQueueEvent(threadId, (Tcl_Event *) threadEventPtr,
	    TCL_QUEUE_TAIL);
	    TCL_QUEUE_TAIL|TCL_QUEUE_ALERT_IF_EMPTY);
    Tcl_ThreadAlert(threadId);

    if (!wait) {
	Tcl_MutexUnlock(&threadMutex);
	return TCL_OK;
    }

    /*
911
912
913
914
915
916
917
918

919
920
921
922
923
924
925
926

927
928
929
930
931
932
933
910
911
912
913
914
915
916

917
918
919
920
921
922
923
924

925
926
927
928
929
930
931
932







-
+







-
+







    resultPtr->nextPtr = NULL;
    resultPtr->prevPtr = NULL;

    Tcl_MutexUnlock(&threadMutex);

    if (resultPtr->code != TCL_OK) {
	if (resultPtr->errorCode) {
	    Tcl_SetErrorCode(interp, resultPtr->errorCode, NULL);
	    Tcl_SetErrorCode(interp, resultPtr->errorCode, (char *)NULL);
	    Tcl_Free(resultPtr->errorCode);
	}
	if (resultPtr->errorInfo) {
	    Tcl_AddErrorInfo(interp, resultPtr->errorInfo);
	    Tcl_Free(resultPtr->errorInfo);
	}
    }
    Tcl_AppendResult(interp, resultPtr->result, NULL);
    Tcl_AppendResult(interp, resultPtr->result, (char *)NULL);
    Tcl_ConditionFinalize(&resultPtr->done);
    code = resultPtr->code;

    Tcl_Free(resultPtr->result);
    Tcl_Free(resultPtr);

    return code;
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
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







-
+











-
+







	if (tsdPtr->threadId == threadId) {
	    found = 1;
	    break;
	}
    }
    if (!found) {
	Tcl_MutexUnlock(&threadMutex);
	Tcl_AppendResult(interp, "invalid thread id", NULL);
	Tcl_AppendResult(interp, "invalid thread id", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Since Tcl_CancelEval can be safely called from any thread,
     * we do it now.
     */

    Tcl_MutexUnlock(&threadMutex);
    Tcl_ResetResult(interp);
    return Tcl_CancelEval(tsdPtr->interp,
    	(result != NULL) ? Tcl_NewStringObj(result, -1) : NULL, 0, flags);
	    (result != NULL) ? Tcl_NewStringObj(result, -1) : NULL, 0, flags);
}

/*
 *------------------------------------------------------------------------
 *
 * ThreadEventProc --
 *

Changes to generic/tclTimer.c.

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
30
31
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
30
31






-
+
















-
+







/*
 * tclTimer.c --
 *
 *	This file provides timer event management facilities for Tcl,
 *	including the "after" command.
 *
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 * Copyright © 1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

/*
 * For each timer callback that's pending there is one record of the following
 * type. The normal handlers (created by Tcl_CreateTimerHandler) are chained
 * together in a list sorted by time (earliest event first).
 */

typedef struct TimerHandler {
    Tcl_Time time;		/* When timer is to fire. */
    Tcl_TimerProc *proc;	/* Function to call. */
    ClientData clientData;	/* Argument to pass to proc. */
    void *clientData;	/* Argument to pass to proc. */
    Tcl_TimerToken token;	/* Identifies handler so it can be deleted. */
    struct TimerHandler *nextPtr;
				/* Next event in queue, or NULL for end of
				 * queue. */
} TimerHandler;

/*
69
70
71
72
73
74
75
76

77
78
79
80
81
82
83
69
70
71
72
73
74
75

76
77
78
79
80
81
82
83







-
+







 * There is one of the following structures for each of the handlers declared
 * in a call to Tcl_DoWhenIdle. All of the currently-active handlers are
 * linked together into a list.
 */

typedef struct IdleHandler {
    Tcl_IdleProc *proc;		/* Function to call. */
    ClientData clientData;	/* Value to pass to proc. */
    void *clientData;	/* Value to pass to proc. */
    int generation;		/* Used to distinguish older handlers from
				 * recently-created ones. */
    struct IdleHandler *nextPtr;/* Next in list of active handlers. */
} IdleHandler;

/*
 * The timer and idle queues are per-thread because they are associated with
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
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







-
+







-
+



-
+




















-
+


-
+




-
+

-
-
+
+







 * Helper macros for working with times. TCL_TIME_BEFORE encodes how to write
 * the ordering relation on (normalized) times, and TCL_TIME_DIFF_MS computes
 * the number of milliseconds difference between two times. Both macros use
 * both of their arguments multiple times, so make sure they are cheap and
 * side-effect free. The "prototypes" for these macros are:
 *
 * static int	TCL_TIME_BEFORE(Tcl_Time t1, Tcl_Time t2);
 * static long	TCL_TIME_DIFF_MS(Tcl_Time t1, Tcl_Time t2);
 * static Tcl_WideInt TCL_TIME_DIFF_MS(Tcl_Time t1, Tcl_Time t2);
 */

#define TCL_TIME_BEFORE(t1, t2) \
    (((t1).sec<(t2).sec) || ((t1).sec==(t2).sec && (t1).usec<(t2).usec))

#define TCL_TIME_DIFF_MS(t1, t2) \
    (1000*((Tcl_WideInt)(t1).sec - (Tcl_WideInt)(t2).sec) + \
	    ((long)(t1).usec - (long)(t2).usec)/1000)
	    ((t1).usec - (t2).usec)/1000)

#define TCL_TIME_DIFF_MS_CEILING(t1, t2) \
    (1000*((Tcl_WideInt)(t1).sec - (Tcl_WideInt)(t2).sec) + \
	    ((long)(t1).usec - (long)(t2).usec + 999)/1000)
	    ((t1).usec - (t2).usec + 999)/1000)

/*
 * Sleeps under that number of milliseconds don't get double-checked
 * and are done in exactly one Tcl_Sleep(). This to limit gettimeofday()s.
 */

#define SLEEP_OFFLOAD_GETTIMEOFDAY 20

/*
 * The maximum number of milliseconds for each Tcl_Sleep call in AfterDelay.
 * This is used to limit the maximum lag between interp limit and script
 * cancellation checks.
 */

#define TCL_TIME_MAXIMUM_SLICE 500

/*
 * Prototypes for functions referenced only in this file:
 */

static void		AfterCleanupProc(ClientData clientData,
static void		AfterCleanupProc(void *clientData,
			    Tcl_Interp *interp);
static int		AfterDelay(Tcl_Interp *interp, Tcl_WideInt ms);
static void		AfterProc(ClientData clientData);
static void		AfterProc(void *clientData);
static void		FreeAfterPtr(AfterInfo *afterPtr);
static AfterInfo *	GetAfterEvent(AfterAssocData *assocPtr,
			    Tcl_Obj *commandPtr);
static ThreadSpecificData *InitTimer(void);
static void		TimerExitProc(ClientData clientData);
static void		TimerExitProc(void *clientData);
static int		TimerHandlerEventProc(Tcl_Event *evPtr, int flags);
static void		TimerCheckProc(ClientData clientData, int flags);
static void		TimerSetupProc(ClientData clientData, int flags);
static void		TimerCheckProc(void *clientData, int flags);
static void		TimerSetupProc(void *clientData, int flags);

/*
 *----------------------------------------------------------------------
 *
 * InitTimer --
 *
 *	This function initializes the timer module.
207
208
209
210
211
212
213
214

215
216
217
218
219
220
221
207
208
209
210
211
212
213

214
215
216
217
218
219
220
221







-
+







 *	Removes the timer and idle event sources and remaining events.
 *
 *----------------------------------------------------------------------
 */

static void
TimerExitProc(
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);

    Tcl_DeleteEventSource(TimerSetupProc, TimerCheckProc, NULL);
    if (tsdPtr != NULL) {
	TimerHandler *timerHandlerPtr;

247
248
249
250
251
252
253
254

255
256
257
258
259
260
261
247
248
249
250
251
252
253

254
255
256
257
258
259
260
261







-
+







 */

Tcl_TimerToken
Tcl_CreateTimerHandler(
    int milliseconds,		/* How many milliseconds to wait before
				 * invoking proc. */
    Tcl_TimerProc *proc,	/* Function to invoke. */
    ClientData clientData)	/* Arbitrary data to pass to proc. */
    void *clientData)	/* Arbitrary data to pass to proc. */
{
    Tcl_Time time;

    /*
     * Compute when the event should fire.
     */

288
289
290
291
292
293
294
295

296
297
298
299
300
301
302
288
289
290
291
292
293
294

295
296
297
298
299
300
301
302







-
+







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

Tcl_TimerToken
TclCreateAbsoluteTimerHandler(
    Tcl_Time *timePtr,
    Tcl_TimerProc *proc,
    ClientData clientData)
    void *clientData)
{
    TimerHandler *timerHandlerPtr, *tPtr2, *prevPtr;
    ThreadSpecificData *tsdPtr = InitTimer();

    timerHandlerPtr = (TimerHandler *)Tcl_Alloc(sizeof(TimerHandler));

    /*
394
395
396
397
398
399
400
401

402
403
404
405
406
407
408
394
395
396
397
398
399
400

401
402
403
404
405
406
407
408







-
+







 *	May update the maximum notifier block time.
 *
 *----------------------------------------------------------------------
 */

static void
TimerSetupProc(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */
{
    Tcl_Time blockTime;
    ThreadSpecificData *tsdPtr = InitTimer();

    if (((flags & TCL_IDLE_EVENTS) && tsdPtr->idleList)
	    || ((flags & TCL_TIMER_EVENTS) && tsdPtr->timerPending)) {
452
453
454
455
456
457
458
459

460
461
462
463
464
465
466
452
453
454
455
456
457
458

459
460
461
462
463
464
465
466







-
+







 *	May queue an event and update the maximum notifier block time.
 *
 *----------------------------------------------------------------------
 */

static void
TimerCheckProc(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */
{
    Tcl_Event *timerEvPtr;
    Tcl_Time blockTime;
    ThreadSpecificData *tsdPtr = InitTimer();

    if ((flags & TCL_TIMER_EVENTS) && tsdPtr->firstTimerHandlerPtr) {
615
616
617
618
619
620
621
622

623
624
625
626
627
628
629
615
616
617
618
619
620
621

622
623
624
625
626
627
628
629







-
+







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

void
Tcl_DoWhenIdle(
    Tcl_IdleProc *proc,		/* Function to invoke. */
    ClientData clientData)	/* Arbitrary value to pass to proc. */
    void *clientData)	/* Arbitrary value to pass to proc. */
{
    IdleHandler *idlePtr;
    Tcl_Time blockTime;
    ThreadSpecificData *tsdPtr = InitTimer();

    idlePtr = (IdleHandler *)Tcl_Alloc(sizeof(IdleHandler));
    idlePtr->proc = proc;
659
660
661
662
663
664
665
666

667
668
669
670
671
672
673
659
660
661
662
663
664
665

666
667
668
669
670
671
672
673







-
+







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

void
Tcl_CancelIdleCall(
    Tcl_IdleProc *proc,		/* Function that was previously registered. */
    ClientData clientData)	/* Arbitrary value to pass to proc. */
    void *clientData)	/* Arbitrary value to pass to proc. */
{
    IdleHandler *idlePtr, *prevPtr;
    IdleHandler *nextPtr;
    ThreadSpecificData *tsdPtr = InitTimer();

    for (prevPtr = NULL, idlePtr = tsdPtr->idleList; idlePtr != NULL;
	    prevPtr = idlePtr, idlePtr = idlePtr->nextPtr) {
774
775
776
777
778
779
780
781

782
783
784
785
786
787
788
789
790

791
792
793
794
795
796
797
774
775
776
777
778
779
780

781
782
783
784
785
786
787
788
789

790
791
792
793
794
795
796
797







-
+








-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_AfterObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_WideInt ms = 0;		/* Number of milliseconds to wait */
    Tcl_Time wakeup;
    AfterInfo *afterPtr;
    AfterAssocData *assocPtr;
    size_t length;
    Tcl_Size length;
    int index = -1;
    static const char *const afterSubCmds[] = {
	"cancel", "idle", "info", NULL
    };
    enum afterSubCmdsEnum {AFTER_CANCEL, AFTER_IDLE, AFTER_INFO};
    ThreadSpecificData *tsdPtr = InitTimer();

813
814
815
816
817
818
819
820

821
822
823

824
825
826
827
828
829




830
831
832
833
834
835
836
813
814
815
816
817
818
819

820
821
822

823
824
825




826
827
828
829
830
831
832
833
834
835
836







-
+


-
+


-
-
-
-
+
+
+
+







	Tcl_SetAssocData(interp, "tclAfter", AfterCleanupProc, assocPtr);
    }

    /*
     * First lets see if the command was passed a number as the first argument.
     */

    if (Tcl_GetWideIntFromObj(NULL, objv[1], &ms) != TCL_OK) {
    if (TclGetWideIntFromObj(NULL, objv[1], &ms) != TCL_OK) {
	if (Tcl_GetIndexFromObj(NULL, objv[1], afterSubCmds, "", 0, &index)
		!= TCL_OK) {
            const char *arg = TclGetString(objv[1]);
	    const char *arg = TclGetString(objv[1]);

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "bad argument \"%s\": must be"
                    " cancel, idle, info, or an integer", arg));
            Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "argument",
                    arg, NULL);
		    "bad argument \"%s\": must be"
		    " cancel, idle, info, or an integer", arg));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "argument",
		    arg, (char *)NULL);
	    return TCL_ERROR;
	}
    }

    /*
     * At this point, either index = -1 and ms contains the number of ms
     * to wait, or else index is the index of a subcommand.
862
863
864
865
866
867
868
869
870


871
872
873
874
875
876
877
878
879
880
881
882
883
884
885

886
887
888
889
890
891
892
862
863
864
865
866
867
868


869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884

885
886
887
888
889
890
891
892







-
-
+
+














-
+







	 * 1-10 years. Thus it's unlikely that any old ids will still be
	 * around when wrap-around occurs.
	 */

	afterPtr->id = tsdPtr->afterId;
	tsdPtr->afterId += 1;
	Tcl_GetTime(&wakeup);
	wakeup.sec += (long)(ms / 1000);
	wakeup.usec += ((long)(ms % 1000)) * 1000;
	wakeup.sec += ms / 1000;
	wakeup.usec += ms % 1000 * 1000;
	if (wakeup.usec > 1000000) {
	    wakeup.sec++;
	    wakeup.usec -= 1000000;
	}
	afterPtr->token = TclCreateAbsoluteTimerHandler(&wakeup,
		AfterProc, afterPtr);
	afterPtr->nextPtr = assocPtr->firstAfterPtr;
	assocPtr->firstAfterPtr = afterPtr;
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("after#%d", afterPtr->id));
	return TCL_OK;
    }
    case AFTER_CANCEL: {
	Tcl_Obj *commandPtr;
	const char *command, *tempCommand;
	size_t tempLength;
	Tcl_Size tempLength;

	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "id|command");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    commandPtr = objv[2];
944
945
946
947
948
949
950
951
952


953
954
955

956
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
944
945
946
947
948
949
950


951
952
953
954

955
956
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







-
-
+
+


-
+








-
+


-
-
+
+


-
+

-
-
-
-
+
+
+
+

-
-
+
+







	if (objc == 2) {
	    Tcl_Obj *resultObj;

	    TclNewObj(resultObj);
	    for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL;
		    afterPtr = afterPtr->nextPtr) {
		if (assocPtr->interp == interp) {
                    Tcl_ListObjAppendElement(NULL, resultObj, Tcl_ObjPrintf(
                            "after#%d", afterPtr->id));
		    Tcl_ListObjAppendElement(NULL, resultObj, Tcl_ObjPrintf(
			    "after#%d", afterPtr->id));
		}
	    }
            Tcl_SetObjResult(interp, resultObj);
	    Tcl_SetObjResult(interp, resultObj);
	    return TCL_OK;
	}
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?id?");
	    return TCL_ERROR;
	}
	afterPtr = GetAfterEvent(assocPtr, objv[2]);
	if (afterPtr == NULL) {
            const char *eventStr = TclGetString(objv[2]);
	    const char *eventStr = TclGetString(objv[2]);

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "event \"%s\" doesn't exist", eventStr));
            Tcl_SetErrorCode(interp, "TCL","LOOKUP","EVENT", eventStr, NULL);
		    "event \"%s\" doesn't exist", eventStr));
	    Tcl_SetErrorCode(interp, "TCL","LOOKUP","EVENT", eventStr, (char *)NULL);
	    return TCL_ERROR;
	} else {
            Tcl_Obj *resultListPtr;
	    Tcl_Obj *resultListPtr;

            TclNewObj(resultListPtr);
            Tcl_ListObjAppendElement(interp, resultListPtr,
                    afterPtr->commandPtr);
            Tcl_ListObjAppendElement(interp, resultListPtr, Tcl_NewStringObj(
	    TclNewObj(resultListPtr);
	    Tcl_ListObjAppendElement(interp, resultListPtr,
		    afterPtr->commandPtr);
	    Tcl_ListObjAppendElement(interp, resultListPtr, Tcl_NewStringObj(
		    (afterPtr->token == NULL) ? "idle" : "timer", -1));
            Tcl_SetObjResult(interp, resultListPtr);
        }
	    Tcl_SetObjResult(interp, resultListPtr);
	}
	break;
    default:
	Tcl_Panic("Tcl_AfterObjCmd: bad subcommand index to afterSubCmds");
    }
    return TCL_OK;
}

1010
1011
1012
1013
1014
1015
1016
1017
1018


1019
1020
1021
1022
1023
1024
1025
1010
1011
1012
1013
1014
1015
1016


1017
1018
1019
1020
1021
1022
1023
1024
1025







-
-
+
+







    Interp *iPtr = (Interp *) interp;

    Tcl_Time endTime, now;
    Tcl_WideInt diff;

    Tcl_GetTime(&now);
    endTime = now;
    endTime.sec += (long)(ms / 1000);
    endTime.usec += ((int)(ms % 1000)) * 1000;
    endTime.sec += (ms / 1000);
    endTime.usec += (ms % 1000) * 1000;
    if (endTime.usec >= 1000000) {
	endTime.sec++;
	endTime.usec -= 1000000;
    }

    do {
	if (Tcl_AsyncReady()) {
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
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







-
-
-
+
+
+

-
-
-
-
+
+
+
+

-
-
+
+







	}
	if (iPtr->limit.timeEvent == NULL
		|| TCL_TIME_BEFORE(endTime, iPtr->limit.time)) {
	    diff = TCL_TIME_DIFF_MS_CEILING(endTime, now);
	    if (diff > TCL_TIME_MAXIMUM_SLICE) {
		diff = TCL_TIME_MAXIMUM_SLICE;
	    }
            if (diff == 0 && TCL_TIME_BEFORE(now, endTime)) {
                diff = 1;
            }
	    if (diff == 0 && TCL_TIME_BEFORE(now, endTime)) {
		diff = 1;
	    }
	    if (diff > 0) {
		Tcl_Sleep((long) diff);
                if (diff < SLEEP_OFFLOAD_GETTIMEOFDAY) {
                    break;
                }
		Tcl_Sleep((int) diff);
		if (diff < SLEEP_OFFLOAD_GETTIMEOFDAY) {
		    break;
		}
	    } else {
                break;
            }
		break;
	    }
	} else {
	    diff = TCL_TIME_DIFF_MS(iPtr->limit.time, now);
	    if (diff > TCL_TIME_MAXIMUM_SLICE) {
		diff = TCL_TIME_MAXIMUM_SLICE;
	    }
	    if (diff > 0) {
		Tcl_Sleep((int) diff);
1145
1146
1147
1148
1149
1150
1151
1152

1153
1154
1155
1156
1157
1158
1159
1145
1146
1147
1148
1149
1150
1151

1152
1153
1154
1155
1156
1157
1158
1159







-
+







 *	bgerror fails then information about the error is output on stderr.
 *
 *----------------------------------------------------------------------
 */

static void
AfterProc(
    ClientData clientData)	/* Describes command to execute. */
    void *clientData)	/* Describes command to execute. */
{
    AfterInfo *afterPtr = (AfterInfo *)clientData;
    AfterAssocData *assocPtr = afterPtr->assocPtr;
    AfterInfo *prevPtr;
    int result;
    Tcl_Interp *interp;

1247
1248
1249
1250
1251
1252
1253
1254

1255
1256
1257
1258
1259
1260
1261
1247
1248
1249
1250
1251
1252
1253

1254
1255
1256
1257
1258
1259
1260
1261







-
+







 *	After commands are removed.
 *
 *----------------------------------------------------------------------
 */

static void
AfterCleanupProc(
    ClientData clientData,	/* Points to AfterAssocData for the
    void *clientData,	/* Points to AfterAssocData for the
				 * interpreter. */
    TCL_UNUSED(Tcl_Interp *))
{
    AfterAssocData *assocPtr = (AfterAssocData *)clientData;
    AfterInfo *afterPtr;

    while (assocPtr->firstAfterPtr != NULL) {

Changes to generic/tclTomMath.decls.

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
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









-
+









-







# tclTomMath.decls --
#
#	This file contains the declarations for the functions in 'libtommath'
#	that are contained within the Tcl library.  This file is used to
#	generate the 'tclTomMathDecls.h' and 'tclStubInit.c' files.
#
# If you edit this file, advance the revision number (and the epoch
# if the new stubs are not backward compatible) in tclTomMathDecls.h
#
# Copyright (c) 2005 by Kevin B. Kenny.  All rights reserved.
# Copyright © 2005 Kevin B. Kenny.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

library tcl

# Define the unsupported generic interfaces.

interface tclTomMath
# hooks {tclTomMathInt}
scspec EXTERN

# Declare each of the functions in the Tcl tommath interface

declare 0 {
    int MP_WUR TclBN_epoch(void)
}
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
69
70
71
72
73
74
75




76
77
78
79

80
81
82
83
84
85
86
87







-
-
-
-




-
+







}
declare 15 {
    mp_err MP_WUR TclBN_mp_div_2(const mp_int *a, mp_int *q)
}
declare 16 {
    mp_err MP_WUR TclBN_mp_div_2d(const mp_int *a, int b, mp_int *q, mp_int *r)
}
# Removed in 9.0
#declare 17 {deprecated {is private function in libtommath}} {
#    mp_err TclBN_mp_div_3(const mp_int *a, mp_int *q, mp_digit *r)
#}
declare 18 {
    void TclBN_mp_exch(mp_int *a, mp_int *b)
}
declare 19 {
    mp_err MP_WUR TclBN_mp_expt_u32(const mp_int *a, uint32_t b, mp_int *c)
    mp_err MP_WUR TclBN_mp_expt_n(const mp_int *a, int b, mp_int *c)
}
declare 20 {
    mp_err MP_WUR TclBN_mp_grow(mp_int *a, int size)
}
declare 21 {
    mp_err MP_WUR TclBN_mp_init(mp_int *a)
}
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
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







-
-
-
-
-
-
-
-









-
-
-
-
-
-
-
-
-
-
-
-
-









-
-
-
-
-
-
-
-



-
-
-
-







-
-
-
-
-









+
+
+
-
+
-
-
-
-
+
+
-
-
-
-
-
+
+
+
-
-
-
+
+
-
-
-
+
+
+






-
-
-
-








}
declare 37 {
    void TclBN_mp_rshd(mp_int *a, int shift)
}
declare 38 {
    mp_err MP_WUR TclBN_mp_shrink(mp_int *a)
}
# Removed in 9.0
#declare 39 {deprecated {macro calling mp_set_u64}} {
#    void TclBN_mp_set(mp_int *a, unsigned int b)
#}
# Removed in 9.0
#declare 40 {nostub {is private function in libtommath}} {
#    mp_err TclBN_mp_sqr(const mp_int *a, mp_int *b)
#}
declare 41 {
    mp_err MP_WUR TclBN_mp_sqrt(const mp_int *a, mp_int *b)
}
declare 42 {
    mp_err MP_WUR TclBN_mp_sub(const mp_int *a, const mp_int *b, mp_int *c)
}
declare 43 {
    mp_err MP_WUR TclBN_mp_sub_d(const mp_int *a, mp_digit b, mp_int *c)
}
# Removed in 9.0
#declare 44 {
#    mp_err TclBN_mp_to_unsigned_bin(const mp_int *a, unsigned char *b)
#}
# Removed in 9.0
#declare 45 {
#    mp_err TclBN_mp_to_unsigned_bin_n(const mp_int *a, unsigned char *b,
#	    unsigned long *outlen)
#}
# Removed in 9.0
#declare 46 {
#    mp_err TclBN_mp_toradix_n(const mp_int *a, char *str, int radix, int maxlen)
#}
declare 47 {
    size_t MP_WUR TclBN_mp_ubin_size(const mp_int *a)
}
declare 48 {
    mp_err MP_WUR TclBN_mp_xor(const mp_int *a, const mp_int *b, mp_int *c)
}
declare 49 {
    void TclBN_mp_zero(mp_int *a)
}
# Removed in 9.0
#declare 61 {deprecated {macro calling mp_init_u64}} {
#    mp_err TclBN_mp_init_ul(mp_int *a, unsigned long i)
#}
# Removed in 9.0
#declare 62 {deprecated {macro calling mp_set_u64}} {
#    void TclBN_mp_set_ul(mp_int *a, unsigned long i)
#}
declare 63 {
    int MP_WUR TclBN_mp_cnt_lsb(const mp_int *a)
}
# Removed in 9.0
#declare 64 {deprecated {macro calling mp_init_i64}} {
#    int TclBN_mp_init_l(mp_int *bignum, long initVal)
#}
declare 65 {
    int MP_WUR TclBN_mp_init_i64(mp_int *bignum, int64_t initVal)
}
declare 66 {
    int MP_WUR TclBN_mp_init_u64(mp_int *bignum, uint64_t initVal)
}

# Removed in 9.0
#declare 67 {
#    mp_err TclBN_mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast)
#}
# Added in libtommath 1.0.1
declare 68 {
    void TclBN_mp_set_u64(mp_int *a, uint64_t i)
}
declare 69 {
    uint64_t MP_WUR TclBN_mp_get_mag_u64(const mp_int *a)
}
declare 70 {
    void TclBN_mp_set_i64(mp_int *a, int64_t i)
}
declare 71 {
    mp_err MP_WUR TclBN_mp_unpack(mp_int *rop, size_t count, mp_order order, size_t size,
	    mp_endian endian, size_t nails, const void *op)

}
# Added in libtommath 1.1.0
# No longer in use: replaced by mp_and()
#declare 73 {
#    int TclBN_mp_tc_and(const mp_int *a, const mp_int *b, mp_int *c)
declare 72 {
    mp_err MP_WUR TclBN_mp_pack(void *rop, size_t maxcount, size_t *written, mp_order order,
#}
# No longer in use: replaced by mp_or()
#declare 74 {
#    int TclBN_mp_tc_or(const mp_int *a, const mp_int *b, mp_int *c)
#}
	    size_t size, mp_endian endian, size_t nails, const mp_int *op)
}

# No longer in use: replaced by mp_xor()
#declare 75 {
#    int TclBN_mp_tc_xor(const mp_int *a, const mp_int *b, mp_int *c)
declare 76 {
    mp_err MP_WUR TclBN_mp_signed_rsh(const mp_int *a, int b, mp_int *c)
#}
declare 76 {
    mp_err MP_WUR TclBN_mp_signed_rsh(const mp_int *a, int b, mp_int *c)
}
declare 77 {
    size_t MP_WUR TclBN_mp_pack_count(const mp_int *a, size_t nails, size_t size)
}

# Added in libtommath 1.2.0
declare 78 {
    int MP_WUR TclBN_mp_to_ubin(const mp_int *a, unsigned char *buf, size_t maxlen, size_t *written)
}
# Removed in 9.0
#declare 79 {
#    mp_err MP_WUR TclBN_mp_div_ld(const mp_int *a, mp_digit b, mp_int *q, mp_digit *r)
#}
declare 80 {
    int MP_WUR TclBN_mp_to_radix(const mp_int *a, char *str, size_t maxlen, size_t *written, int radix)
}


# Local Variables:
# mode: tcl
# End:

Changes to generic/tclTomMath.h.

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
30
31
32
33
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
30
31
32
33
34
35



-
-
-
+
-
-
-
-
















+
+
+
+
+
+
+
+







#ifndef BN_TCL_H_
#define BN_TCL_H_

#ifdef MP_NO_STDINT
#   ifdef HAVE_STDINT_H
#	include <stdint.h>
#include <stdint.h>
#else
#	include "../compat/stdint.h"
#   endif
#endif
#if defined(TCL_NO_TOMMATH_H)
    typedef size_t mp_digit;
    typedef int mp_sign;
#   define MP_ZPOS       0   /* positive integer */
#   define MP_NEG        1   /* negative */
    typedef int mp_ord;
#   define MP_LT        -1   /* less than */
#   define MP_EQ         0   /* equal to */
#   define MP_GT         1   /* greater than */
    typedef int mp_err;
#   define MP_OKAY       0   /* no error */
#   define MP_ERR        -1  /* unknown error */
#   define MP_MEM        -2  /* out of mem */
#   define MP_VAL        -3  /* invalid input */
#   define MP_ITER       -4  /* maximum iterations reached */
#   define MP_BUF        -5  /* buffer overflow, supplied buffer too small */
    typedef int mp_order;
#   define MP_LSB_FIRST -1
#   define MP_MSB_FIRST  1
    typedef int mp_endian;
#   define MP_LITTLE_ENDIAN  -1
#   define MP_NATIVE_ENDIAN  0
#   define MP_BIG_ENDIAN     1
#   define MP_DEPRECATED_PRAGMA(s) /* nothing */
#   define MP_WUR            /* nothing */
#   define mp_iszero(a) ((a)->used == 0)
#   define mp_isneg(a)  ((a)->sign != 0)

    /* the infamous mp_int structure */
#   ifndef MP_INT_DECLARED
#	define MP_INT_DECLARED

Changes to generic/tclTomMathDecls.h.

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
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







-
+

-
+

-
+

-
+






-
-
-
+
+
+


+
+
+
-
+
+





-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







#define Tcl_TomMath_InitStubs(interp,version) \
    (TclTomMathInitializeStubs((interp),(version),\
                               TCLTOMMATH_EPOCH,TCLTOMMATH_REVISION))

/* Define custom memory allocation for libtommath */

/* MODULE_SCOPE void* TclBNAlloc( size_t ); */
#define TclBNAlloc(s) ((void*)Tcl_Alloc(s))
#define TclBNAlloc(s) Tcl_AttemptAlloc((size_t)(s))
/* MODULE_SCOPE void* TclBNCalloc( size_t, size_t ); */
#define TclBNCalloc(m,s) memset(Tcl_Alloc((size_t)(m)*(size_t)(s)),0,(size_t)(m)*(size_t)(s))
#define TclBNCalloc(m,s) memset(Tcl_AttemptAlloc((size_t)(m)*(size_t)(s)),0,(size_t)(m)*(size_t)(s))
/* MODULE_SCOPE void* TclBNRealloc( void*, size_t ); */
#define TclBNRealloc(x,s) ((void*)Tcl_Realloc((char*)(x),(size_t)(s)))
#define TclBNRealloc(x,s) Tcl_AttemptRealloc((x),(size_t)(s))
/* MODULE_SCOPE void  TclBNFree( void* ); */
#define TclBNFree(x) (Tcl_Free((char*)(x)))
#define TclBNFree(x) Tcl_Free(x)

#undef MP_MALLOC
#undef MP_CALLOC
#undef MP_REALLOC
#undef MP_FREE
#define MP_MALLOC(size)                   TclBNAlloc(size)
#define MP_CALLOC(nmemb, size)            TclBNCalloc(nmemb, size)
#define MP_REALLOC(mem, oldsize, newsize) TclBNRealloc(mem, newsize)
#define MP_FREE(mem, size)                TclBNFree(mem)
#define MP_CALLOC(nmemb, size)            TclBNCalloc((nmemb), (size))
#define MP_REALLOC(mem, oldsize, newsize) TclBNRealloc((mem), ((void)(oldsize), (newsize)))
#define MP_FREE(mem, size)                TclBNFree(((void)(size), (mem)))

#ifndef MODULE_SCOPE
#   ifdef __cplusplus
#	define MODULE_SCOPE extern "C"
#   else
#   define MODULE_SCOPE extern
#	define MODULE_SCOPE extern
#   endif
#endif

#ifdef __cplusplus
extern "C" {
#endif
MODULE_SCOPE mp_err TclBN_mp_sqr(const mp_int *a, mp_int *b);
MODULE_SCOPE mp_err TclBN_mp_div_3(const mp_int *a, mp_int *q, mp_digit *r);
MODULE_SCOPE mp_err	TclBN_mp_sqr(const mp_int *a, mp_int *b);
MODULE_SCOPE mp_err	TclBN_mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c);
MODULE_SCOPE mp_err	TclBN_mp_div_3(const mp_int *a, mp_int *c, mp_digit *d);
MODULE_SCOPE mp_err	TclBN_mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c);
MODULE_SCOPE mp_err	TclBN_mp_karatsuba_sqr(const mp_int *a, mp_int *b);
MODULE_SCOPE mp_err	TclBN_mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c);
MODULE_SCOPE mp_err	TclBN_mp_toom_sqr(const mp_int *a, mp_int *b);
MODULE_SCOPE mp_err TclBN_s_mp_add(const mp_int *a, const mp_int *b, mp_int *c);
MODULE_SCOPE mp_err TclBN_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs);
MODULE_SCOPE mp_err TclBN_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs);
MODULE_SCOPE void	TclBN_mp_reverse(unsigned char *s, size_t len);
MODULE_SCOPE mp_err	TclBN_s_mp_sqr(const mp_int *a, mp_int *b);
MODULE_SCOPE mp_err	TclBN_mp_sqr_fast(const mp_int *a, mp_int *b);
MODULE_SCOPE mp_err	TclBN_s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c);
MODULE_SCOPE const char *const TclBN_mp_s_rmap;
MODULE_SCOPE const uint8_t TclBN_mp_s_rmap_reverse[];
MODULE_SCOPE const size_t TclBN_mp_s_rmap_reverse_sz;
MODULE_SCOPE mp_err	TclBN_mp_set_int(mp_int *a, unsigned long b);
#ifdef __cplusplus
}
#endif

/* Rename the global symbols in libtommath to avoid linkage conflicts */

#ifndef TCL_WITH_EXTERNAL_TOMMATH
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
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







-


-
+
-
-
+


















+
+






-
+


















+




+


-
-
-
+
+
+

-
+







#define mp_cmp_mag TclBN_mp_cmp_mag
#define mp_cnt_lsb TclBN_mp_cnt_lsb
#define mp_copy TclBN_mp_copy
#define mp_count_bits TclBN_mp_count_bits
#define mp_div TclBN_mp_div
#define mp_div_d TclBN_mp_div_d
#define mp_div_2 TclBN_mp_div_2
#define mp_div_3 TclBN_mp_div_3
#define mp_div_2d TclBN_mp_div_2d
#define mp_exch TclBN_mp_exch
#define mp_expt_d TclBN_mp_expt_d
#define mp_expt_d TclBN_mp_expt_n
#define mp_expt_d_ex TclBN_mp_expt_d_ex
#define mp_expt_u32 TclBN_mp_expt_u32
#define mp_expt_n TclBN_mp_expt_n
#define mp_get_mag_u64 TclBN_mp_get_mag_u64
#define mp_grow TclBN_mp_grow
#define mp_init TclBN_mp_init
#define mp_init_copy TclBN_mp_init_copy
#define mp_init_i64 TclBN_mp_init_i64
#define mp_init_multi TclBN_mp_init_multi
#define mp_init_set TclBN_mp_init_set
#define mp_init_size TclBN_mp_init_size
#define mp_init_u64 TclBN_mp_init_u64
#define mp_lshd TclBN_mp_lshd
#define mp_mod TclBN_mp_mod
#define mp_mod_2d TclBN_mp_mod_2d
#define mp_mul TclBN_mp_mul
#define mp_mul_d TclBN_mp_mul_d
#define mp_mul_2 TclBN_mp_mul_2
#define mp_mul_2d TclBN_mp_mul_2d
#define mp_neg TclBN_mp_neg
#define mp_or TclBN_mp_or
#define mp_pack TclBN_mp_pack
#define mp_pack_count TclBN_mp_pack_count
#define mp_radix_size TclBN_mp_radix_size
#define mp_read_radix TclBN_mp_read_radix
#define mp_rshd TclBN_mp_rshd
#define mp_s_rmap TclBN_mp_s_rmap
#define mp_s_rmap_reverse TclBN_mp_s_rmap_reverse
#define mp_s_rmap_reverse_sz TclBN_mp_s_rmap_reverse_sz
#define mp_set TclBN_s_mp_set
#define mp_set TclBN_mp_set
#define mp_set_i64 TclBN_mp_set_i64
#define mp_set_u64 TclBN_mp_set_u64
#define mp_shrink TclBN_mp_shrink
#define mp_sqr TclBN_mp_sqr
#define mp_sqrt TclBN_mp_sqrt
#define mp_sub TclBN_mp_sub
#define mp_sub_d TclBN_mp_sub_d
#define mp_signed_rsh TclBN_mp_signed_rsh
#define mp_tc_and TclBN_mp_and
#define mp_tc_div_2d TclBN_mp_signed_rsh
#define mp_tc_or TclBN_mp_or
#define mp_tc_xor TclBN_mp_xor
#define mp_to_unsigned_bin TclBN_mp_to_unsigned_bin
#define mp_to_unsigned_bin_n TclBN_mp_to_unsigned_bin_n
#define mp_toradix_n TclBN_mp_toradix_n
#define mp_to_radix TclBN_mp_to_radix
#define mp_to_ubin TclBN_mp_to_ubin
#define mp_ubin_size TclBN_mp_ubin_size
#define mp_unpack TclBN_mp_unpack
#define mp_xor TclBN_mp_xor
#define mp_zero TclBN_mp_zero
#define s_mp_add TclBN_s_mp_add
#define s_mp_balance_mul TclBN_mp_balance_mul
#define s_mp_div_3 TclBN_mp_div_3
#define s_mp_karatsuba_mul TclBN_mp_karatsuba_mul
#define s_mp_karatsuba_sqr TclBN_mp_karatsuba_sqr
#define s_mp_mul_digs TclBN_s_mp_mul_digs
#define s_mp_mul_digs_fast TclBN_s_mp_mul_digs_fast
#define s_mp_reverse TclBN_s_mp_reverse
#define s_mp_mul_digs TclBN_mp_mul_digs
#define s_mp_mul_digs_fast TclBN_mp_mul_digs_fast
#define s_mp_reverse TclBN_mp_reverse
#define s_mp_sqr TclBN_s_mp_sqr
#define s_mp_sqr_fast TclBN_s_mp_sqr_fast
#define s_mp_sqr_fast TclBN_mp_sqr_fast
#define s_mp_sub TclBN_s_mp_sub
#define s_mp_toom_mul TclBN_mp_toom_mul
#define s_mp_toom_sqr TclBN_mp_toom_sqr
#endif /* !TCL_WITH_EXTERNAL_TOMMATH */

#undef TCL_STORAGE_CLASS
#ifdef BUILD_tcl
216
217
218
219
220
221
222
223

224
225
226
227
228
229
230
231
238
239
240
241
242
243
244

245

246
247
248
249
250
251
252







-
+
-







/* 16 */
EXTERN mp_err		TclBN_mp_div_2d(const mp_int *a, int b, mp_int *q,
				mp_int *r) MP_WUR;
/* Slot 17 is reserved */
/* 18 */
EXTERN void		TclBN_mp_exch(mp_int *a, mp_int *b);
/* 19 */
EXTERN mp_err		TclBN_mp_expt_u32(const mp_int *a, uint32_t b,
EXTERN mp_err		TclBN_mp_expt_n(const mp_int *a, int b, mp_int *c) MP_WUR;
				mp_int *c) MP_WUR;
/* 20 */
EXTERN mp_err		TclBN_mp_grow(mp_int *a, int size) MP_WUR;
/* 21 */
EXTERN mp_err		TclBN_mp_init(mp_int *a) MP_WUR;
/* 22 */
EXTERN mp_err		TclBN_mp_init_copy(mp_int *a, const mp_int *b) MP_WUR;
/* 23 */
309
310
311
312
313
314
315
316
317










318
319
320
321
322
323
324



325
326
327
328
329
330
331
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







-
-
+
+
+
+
+
+
+
+
+
+






-
+
+
+







/* Slot 67 is reserved */
/* 68 */
EXTERN void		TclBN_mp_set_u64(mp_int *a, uint64_t i);
/* 69 */
EXTERN uint64_t		TclBN_mp_get_mag_u64(const mp_int *a) MP_WUR;
/* 70 */
EXTERN void		TclBN_mp_set_i64(mp_int *a, int64_t i);
/* Slot 71 is reserved */
/* Slot 72 is reserved */
/* 71 */
EXTERN mp_err		TclBN_mp_unpack(mp_int *rop, size_t count,
				mp_order order, size_t size,
				mp_endian endian, size_t nails,
				const void *op) MP_WUR;
/* 72 */
EXTERN mp_err		TclBN_mp_pack(void *rop, size_t maxcount,
				size_t *written, mp_order order, size_t size,
				mp_endian endian, size_t nails,
				const mp_int *op) MP_WUR;
/* Slot 73 is reserved */
/* Slot 74 is reserved */
/* Slot 75 is reserved */
/* 76 */
EXTERN mp_err		TclBN_mp_signed_rsh(const mp_int *a, int b,
				mp_int *c) MP_WUR;
/* Slot 77 is reserved */
/* 77 */
EXTERN size_t		TclBN_mp_pack_count(const mp_int *a, size_t nails,
				size_t size) MP_WUR;
/* 78 */
EXTERN int		TclBN_mp_to_ubin(const mp_int *a, unsigned char *buf,
				size_t maxlen, size_t *written) MP_WUR;
/* Slot 79 is reserved */
/* 80 */
EXTERN int		TclBN_mp_to_radix(const mp_int *a, char *str,
				size_t maxlen, size_t *written, int radix) MP_WUR;
349
350
351
352
353
354
355
356

357
358
359
360
361
362
363
380
381
382
383
384
385
386

387
388
389
390
391
392
393
394







-
+







    int (*tclBN_mp_count_bits) (const mp_int *a) MP_WUR; /* 12 */
    mp_err (*tclBN_mp_div) (const mp_int *a, const mp_int *b, mp_int *q, mp_int *r) MP_WUR; /* 13 */
    mp_err (*tclBN_mp_div_d) (const mp_int *a, mp_digit b, mp_int *q, mp_digit *r) MP_WUR; /* 14 */
    mp_err (*tclBN_mp_div_2) (const mp_int *a, mp_int *q) MP_WUR; /* 15 */
    mp_err (*tclBN_mp_div_2d) (const mp_int *a, int b, mp_int *q, mp_int *r) MP_WUR; /* 16 */
    void (*reserved17)(void);
    void (*tclBN_mp_exch) (mp_int *a, mp_int *b); /* 18 */
    mp_err (*tclBN_mp_expt_u32) (const mp_int *a, uint32_t b, mp_int *c) MP_WUR; /* 19 */
    mp_err (*tclBN_mp_expt_n) (const mp_int *a, int b, mp_int *c) MP_WUR; /* 19 */
    mp_err (*tclBN_mp_grow) (mp_int *a, int size) MP_WUR; /* 20 */
    mp_err (*tclBN_mp_init) (mp_int *a) MP_WUR; /* 21 */
    mp_err (*tclBN_mp_init_copy) (mp_int *a, const mp_int *b) MP_WUR; /* 22 */
    mp_err (*tclBN_mp_init_multi) (mp_int *a, ...) MP_WUR; /* 23 */
    mp_err (*tclBN_mp_init_set) (mp_int *a, mp_digit b) MP_WUR; /* 24 */
    mp_err (*tclBN_mp_init_size) (mp_int *a, int size) MP_WUR; /* 25 */
    mp_err (*tclBN_mp_lshd) (mp_int *a, int shift) MP_WUR; /* 26 */
401
402
403
404
405
406
407
408
409


410
411
412
413
414

415
416
417
418
419
420
421
432
433
434
435
436
437
438


439
440
441
442
443
444

445
446
447
448
449
450
451
452







-
-
+
+




-
+







    void (*reserved64)(void);
    int (*tclBN_mp_init_i64) (mp_int *bignum, int64_t initVal) MP_WUR; /* 65 */
    int (*tclBN_mp_init_u64) (mp_int *bignum, uint64_t initVal) MP_WUR; /* 66 */
    void (*reserved67)(void);
    void (*tclBN_mp_set_u64) (mp_int *a, uint64_t i); /* 68 */
    uint64_t (*tclBN_mp_get_mag_u64) (const mp_int *a) MP_WUR; /* 69 */
    void (*tclBN_mp_set_i64) (mp_int *a, int64_t i); /* 70 */
    void (*reserved71)(void);
    void (*reserved72)(void);
    mp_err (*tclBN_mp_unpack) (mp_int *rop, size_t count, mp_order order, size_t size, mp_endian endian, size_t nails, const void *op) MP_WUR; /* 71 */
    mp_err (*tclBN_mp_pack) (void *rop, size_t maxcount, size_t *written, mp_order order, size_t size, mp_endian endian, size_t nails, const mp_int *op) MP_WUR; /* 72 */
    void (*reserved73)(void);
    void (*reserved74)(void);
    void (*reserved75)(void);
    mp_err (*tclBN_mp_signed_rsh) (const mp_int *a, int b, mp_int *c) MP_WUR; /* 76 */
    void (*reserved77)(void);
    size_t (*tclBN_mp_pack_count) (const mp_int *a, size_t nails, size_t size) MP_WUR; /* 77 */
    int (*tclBN_mp_to_ubin) (const mp_int *a, unsigned char *buf, size_t maxlen, size_t *written) MP_WUR; /* 78 */
    void (*reserved79)(void);
    int (*tclBN_mp_to_radix) (const mp_int *a, char *str, size_t maxlen, size_t *written, int radix) MP_WUR; /* 80 */
} TclTomMathStubs;

extern const TclTomMathStubs *tclTomMathStubsPtr;

462
463
464
465
466
467
468
469
470


471
472
473
474
475
476
477
493
494
495
496
497
498
499


500
501
502
503
504
505
506
507
508







-
-
+
+







#define TclBN_mp_div_2 \
	(tclTomMathStubsPtr->tclBN_mp_div_2) /* 15 */
#define TclBN_mp_div_2d \
	(tclTomMathStubsPtr->tclBN_mp_div_2d) /* 16 */
/* Slot 17 is reserved */
#define TclBN_mp_exch \
	(tclTomMathStubsPtr->tclBN_mp_exch) /* 18 */
#define TclBN_mp_expt_u32 \
	(tclTomMathStubsPtr->tclBN_mp_expt_u32) /* 19 */
#define TclBN_mp_expt_n \
	(tclTomMathStubsPtr->tclBN_mp_expt_n) /* 19 */
#define TclBN_mp_grow \
	(tclTomMathStubsPtr->tclBN_mp_grow) /* 20 */
#define TclBN_mp_init \
	(tclTomMathStubsPtr->tclBN_mp_init) /* 21 */
#define TclBN_mp_init_copy \
	(tclTomMathStubsPtr->tclBN_mp_init_copy) /* 22 */
#define TclBN_mp_init_multi \
546
547
548
549
550
551
552
553
554




555
556
557
558
559
560


561
562
563
564
565
566
567
577
578
579
580
581
582
583


584
585
586
587
588
589
590
591
592

593
594
595
596
597
598
599
600
601







-
-
+
+
+
+





-
+
+







/* Slot 67 is reserved */
#define TclBN_mp_set_u64 \
	(tclTomMathStubsPtr->tclBN_mp_set_u64) /* 68 */
#define TclBN_mp_get_mag_u64 \
	(tclTomMathStubsPtr->tclBN_mp_get_mag_u64) /* 69 */
#define TclBN_mp_set_i64 \
	(tclTomMathStubsPtr->tclBN_mp_set_i64) /* 70 */
/* Slot 71 is reserved */
/* Slot 72 is reserved */
#define TclBN_mp_unpack \
	(tclTomMathStubsPtr->tclBN_mp_unpack) /* 71 */
#define TclBN_mp_pack \
	(tclTomMathStubsPtr->tclBN_mp_pack) /* 72 */
/* Slot 73 is reserved */
/* Slot 74 is reserved */
/* Slot 75 is reserved */
#define TclBN_mp_signed_rsh \
	(tclTomMathStubsPtr->tclBN_mp_signed_rsh) /* 76 */
/* Slot 77 is reserved */
#define TclBN_mp_pack_count \
	(tclTomMathStubsPtr->tclBN_mp_pack_count) /* 77 */
#define TclBN_mp_to_ubin \
	(tclTomMathStubsPtr->tclBN_mp_to_ubin) /* 78 */
/* Slot 79 is reserved */
#define TclBN_mp_to_radix \
	(tclTomMathStubsPtr->tclBN_mp_to_radix) /* 80 */

#endif /* defined(USE_TCL_STUBS) */

Changes to generic/tclTomMathInterface.c.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







/*
 *----------------------------------------------------------------------
 *
 * tclTomMathInterface.c --
 *
 *	This file contains procedures that are used as a 'glue' layer between
 *	Tcl and libtommath.
 *
 * Copyright (c) 2005 by Kevin B. Kenny.  All rights reserved.
 * Copyright © 2005 Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclTomMath.h"

Changes to generic/tclTomMathStubLib.c.

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
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






-
-
+
+











-







/*
 * tclTomMathStubLib.c --
 *
 *	Stub object that will be statically linked into extensions that want
 *	to access Tcl.
 *
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright (c) 1998 Paul Duffin.
 * Copyright © 1998-1999 Scriptics Corporation.
 * Copyright © 1998 Paul Duffin.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclTomMath.h"

MODULE_SCOPE const TclTomMathStubs *tclTomMathStubsPtr;

const TclTomMathStubs *tclTomMathStubsPtr = NULL;


/*
 *----------------------------------------------------------------------
 *
 * TclTomMathInitStubs --
 *
 *	Initializes the Stubs table for Tcl's subset of libtommath

Changes to generic/tclTrace.c.

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
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
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
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





-
-
-
-
+
+
+
+














-
-
+
+


















-
+


-
+











-
+







/*
 * tclTrace.c --
 *
 *	This file contains code to handle most trace management.
 *
 * Copyright (c) 1987-1993 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 Scriptics Corporation.
 * Copyright (c) 2002 ActiveState Corporation.
 * Copyright © 1987-1993 The Regents of the University of California.
 * Copyright © 1994-1997 Sun Microsystems, Inc.
 * Copyright © 1998-2000 Scriptics Corporation.
 * Copyright © 2002 ActiveState Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

/*
 * Structures used to hold information about variable traces:
 */

typedef struct {
    int flags;			/* Operations for which Tcl command is to be
				 * invoked. */
    size_t length;		/* Number of non-NUL chars. in command. */
    char command[1];		/* Space for Tcl command to invoke. Actual
    Tcl_Size length;		/* Number of non-NUL chars. in command. */
    char command[TCLFLEXARRAY];		/* Space for Tcl command to invoke. Actual
				 * size will be as large as necessary to hold
				 * command. This field must be the last in the
				 * structure, so that it can be larger than 1
				 * byte. */
} TraceVarInfo;

typedef struct {
    VarTrace traceInfo;
    TraceVarInfo traceCmdInfo;
} CombinedTraceVarInfo;

/*
 * Structure used to hold information about command traces:
 */

typedef struct {
    int flags;			/* Operations for which Tcl command is to be
				 * invoked. */
    size_t length;		/* Number of non-NUL chars. in command. */
    Tcl_Size length;		/* Number of non-NUL chars. in command. */
    Tcl_Trace stepTrace;	/* Used for execution traces, when tracing
				 * inside the given command */
    int startLevel;		/* Used for bookkeeping with step execution
    Tcl_Size startLevel;		/* Used for bookkeeping with step execution
				 * traces, store the level at which the step
				 * trace was invoked */
    char *startCmd;		/* Used for bookkeeping with step execution
				 * traces, store the command name which
				 * invoked step trace */
    int curFlags;		/* Trace flags for the current command */
    int curCode;		/* Return code for the current command */
    size_t refCount;		/* Used to ensure this structure is not
				 * deleted too early. Keeps track of how many
				 * pieces of code have a pointer to this
				 * structure. */
    char command[1];		/* Space for Tcl command to invoke. Actual
    char command[TCLFLEXARRAY];		/* Space for Tcl command to invoke. Actual
				 * size will be as large as necessary to hold
				 * command. This field must be the last in the
				 * structure, so that it can be larger than 1
				 * byte. */
} TraceCommandInfo;

/*
88
89
90
91
92
93
94



95
96


97
98
99
100
101
102
103
88
89
90
91
92
93
94
95
96
97


98
99
100
101
102
103
104
105
106







+
+
+
-
-
+
+







#define TCL_TRACE_EXEC_IN_PROGRESS	0x10
#define TCL_TRACE_EXEC_DIRECT		0x20

/*
 * Forward declarations for functions defined in this file:
 */

enum traceOptionsEnum {
    TRACE_ADD, TRACE_INFO, TRACE_REMOVE
};
typedef int (Tcl_TraceTypeObjCmd)(Tcl_Interp *interp, int optionIndex,
	int objc, Tcl_Obj *const objv[]);
typedef int (Tcl_TraceTypeObjCmd)(Tcl_Interp *interp, enum traceOptionsEnum optionIndex,
	Tcl_Size objc, Tcl_Obj *const objv[]);

static Tcl_TraceTypeObjCmd TraceVariableObjCmd;
static Tcl_TraceTypeObjCmd TraceCommandObjCmd;
static Tcl_TraceTypeObjCmd TraceExecutionObjCmd;

/*
 * Each subcommand has a number of 'types' to which it can apply. Currently
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
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







-
-
-
+
+
+

-
+


-
-
-
+
+
+

-
-
+
+










-
+















-
-
+
+







};

/*
 * Declarations for local functions to this file:
 */

static int		CallTraceFunction(Tcl_Interp *interp, Trace *tracePtr,
			    Command *cmdPtr, const char *command, size_t numChars,
			    int objc, Tcl_Obj *const objv[]);
static char *		TraceVarProc(ClientData clientData, Tcl_Interp *interp,
			    Command *cmdPtr, const char *command, Tcl_Size numChars,
			    Tcl_Size objc, Tcl_Obj *const objv[]);
static char *		TraceVarProc(void *clientData, Tcl_Interp *interp,
			    const char *name1, const char *name2, int flags);
static void		TraceCommandProc(ClientData clientData,
static void		TraceCommandProc(void *clientData,
			    Tcl_Interp *interp, const char *oldName,
			    const char *newName, int flags);
static Tcl_CmdObjTraceProc TraceExecutionProc;
static int		StringTraceProc(ClientData clientData,
			    Tcl_Interp *interp, int level,
static Tcl_CmdObjTraceProc2 TraceExecutionProc;
static int		StringTraceProc(void *clientData,
			    Tcl_Interp *interp, Tcl_Size level,
			    const char *command, Tcl_Command commandInfo,
			    int objc, Tcl_Obj *const objv[]);
static void		StringTraceDeleteProc(ClientData clientData);
			    Tcl_Size objc, Tcl_Obj *const objv[]);
static void		StringTraceDeleteProc(void *clientData);
static void		DisposeTraceResult(int flags, char *result);
static int		TraceVarEx(Tcl_Interp *interp, const char *part1,
			    const char *part2, VarTrace *tracePtr);

/*
 * The following structure holds the client data for string-based
 * trace procs
 */

typedef struct {
    ClientData clientData;	/* Client data from Tcl_CreateTrace */
    void *clientData;	/* Client data from Tcl_CreateTrace */
    Tcl_CmdTraceProc *proc;	/* Trace function from Tcl_CreateTrace */
} StringTraceData;

/*
 * Convenience macros for iterating over the list of traces. Note that each of
 * these *must* be treated as a command, and *must* have a block following it.
 */

#define FOREACH_VAR_TRACE(interp, name, clientData) \
    (clientData) = NULL; \
    while (((clientData) = Tcl_VarTraceInfo2((interp), (name), NULL, \
	    0, TraceVarProc, (clientData))) != NULL)

#define FOREACH_COMMAND_TRACE(interp, name, clientData) \
    (clientData) = NULL; \
    while ((clientData = Tcl_CommandTraceInfo(interp, name, 0, \
	    TraceCommandProc, clientData)) != NULL)
    while (((clientData) = Tcl_CommandTraceInfo((interp), (name), 0, \
	    TraceCommandProc, (clientData))) != NULL)

/*
 *----------------------------------------------------------------------
 *
 * Tcl_TraceObjCmd --
 *
 *	This function is invoked to process the "trace" Tcl command. See the
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
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







-
-
-
-
-



-
-
-


-
-
+
-
-
-
-
-










-
+







int
Tcl_TraceObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int optionIndex;
#ifndef TCL_REMOVE_OBSOLETE_TRACES
    const char *name;
    const char *flagOps, *p;
#endif
    /* Main sub commands to 'trace' */
    static const char *const traceOptions[] = {
	"add", "info", "remove",
#ifndef TCL_REMOVE_OBSOLETE_TRACES
	"variable", "vdelete", "vinfo",
#endif
	NULL
    };
    /* 'OLD' options are pre-Tcl-8.4 style */
    enum traceOptionsEnum {
    enum traceOptionsEnum optionIndex;
	TRACE_ADD, TRACE_INFO, TRACE_REMOVE,
#ifndef TCL_REMOVE_OBSOLETE_TRACES
	TRACE_OLD_VARIABLE, TRACE_OLD_VDELETE, TRACE_OLD_VINFO
#endif
    };

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

    if (Tcl_GetIndexFromObj(interp, objv[1], traceOptions, "option", 0,
	    &optionIndex) != TCL_OK) {
	return TCL_ERROR;
    }
    switch ((enum traceOptionsEnum) optionIndex) {
    switch (optionIndex) {
    case TRACE_ADD:
    case TRACE_REMOVE: {
	/*
	 * All sub commands of trace add/remove must take at least one more
	 * argument. Beyond that we let the subcommand itself control the
	 * argument structure.
	 */
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
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
249
250
251
252
253
254
255








256




























































































257









258
259
260
261
262
263
264







-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-







		0, &typeIndex) != TCL_OK) {
	    return TCL_ERROR;
	}
	return traceSubCmds[typeIndex](interp, optionIndex, objc, objv);
	break;
    }

#ifndef TCL_REMOVE_OBSOLETE_TRACES
    case TRACE_OLD_VARIABLE:
    case TRACE_OLD_VDELETE: {
	Tcl_Obj *copyObjv[6];
	Tcl_Obj *opsList;
	int code;
	size_t numFlags;

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

	TclNewObj(opsList);
	Tcl_IncrRefCount(opsList);
	flagOps = TclGetStringFromObj(objv[3], &numFlags);
	if (numFlags == 0) {
	    Tcl_DecrRefCount(opsList);
	    goto badVarOps;
	}
	for (p = flagOps; *p != 0; p++) {
	    Tcl_Obj *opObj;

	    if (*p == 'r') {
		TclNewLiteralStringObj(opObj, "read");
	    } else if (*p == 'w') {
		TclNewLiteralStringObj(opObj, "write");
	    } else if (*p == 'u') {
		TclNewLiteralStringObj(opObj, "unset");
	    } else if (*p == 'a') {
		TclNewLiteralStringObj(opObj, "array");
	    } else {
		Tcl_DecrRefCount(opsList);
		goto badVarOps;
	    }
	    Tcl_ListObjAppendElement(NULL, opsList, opObj);
	}
	copyObjv[0] = NULL;
	memcpy(copyObjv+1, objv, objc*sizeof(Tcl_Obj *));
	copyObjv[4] = opsList;
	if (optionIndex == TRACE_OLD_VARIABLE) {
	    code = traceSubCmds[2](interp, TRACE_ADD, objc+1, copyObjv);
	} else {
	    code = traceSubCmds[2](interp, TRACE_REMOVE, objc+1, copyObjv);
	}
	Tcl_DecrRefCount(opsList);
	return code;
    }
    case TRACE_OLD_VINFO: {
	ClientData clientData;
	char ops[5];
	Tcl_Obj *resultListPtr, *pairObjPtr, *elemObjPtr;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name");
	    return TCL_ERROR;
	}
	TclNewObj(resultListPtr);
	name = TclGetString(objv[2]);
	FOREACH_VAR_TRACE(interp, name, clientData) {
	    TraceVarInfo *tvarPtr = (TraceVarInfo *)clientData;
	    char *q = ops;

	    pairObjPtr = Tcl_NewListObj(0, NULL);
	    if (tvarPtr->flags & TCL_TRACE_READS) {
		*q = 'r';
		q++;
	    }
	    if (tvarPtr->flags & TCL_TRACE_WRITES) {
		*q = 'w';
		q++;
	    }
	    if (tvarPtr->flags & TCL_TRACE_UNSETS) {
		*q = 'u';
		q++;
	    }
	    if (tvarPtr->flags & TCL_TRACE_ARRAY) {
		*q = 'a';
		q++;
	    }
	    *q = '\0';

	    /*
	     * Build a pair (2-item list) with the ops string as the first obj
	     * element and the tvarPtr->command string as the second obj
	     * element. Append the pair (as an element) to the end of the
	     * result object list.
	     */

	    elemObjPtr = Tcl_NewStringObj(ops, -1);
	    Tcl_ListObjAppendElement(NULL, pairObjPtr, elemObjPtr);
	    elemObjPtr = Tcl_NewStringObj(tvarPtr->command, -1);
	    Tcl_ListObjAppendElement(NULL, pairObjPtr, elemObjPtr);
	    Tcl_ListObjAppendElement(interp, resultListPtr, pairObjPtr);
	}
	Tcl_SetObjResult(interp, resultListPtr);
	break;
    }
#endif /* TCL_REMOVE_OBSOLETE_TRACES */
    }
    return TCL_OK;

#ifndef TCL_REMOVE_OBSOLETE_TRACES
  badVarOps:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "bad operations \"%s\": should be one or more of rwua",
	    flagOps));
    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRACE", "BADOPS", NULL);
    return TCL_ERROR;
#endif
}

/*
 *----------------------------------------------------------------------
 *
 * TraceExecutionObjCmd --
 *
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
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
467
468

469
470

471
472
473
474
475
476
477
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







-
-
+
+


-

-
+
-
-
-






-
+

-
+


-
-
+
+












-
+








-
+

+
+
+
+






-
+














-
+
-
-
+







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

static int
TraceExecutionObjCmd(
    Tcl_Interp *interp,		/* Current interpreter. */
    int optionIndex,		/* Add, info or remove */
    int objc,			/* Number of arguments. */
    enum traceOptionsEnum optionIndex,		/* Add, info or remove */
    Tcl_Size objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int index;
    const char *name, *command;
    size_t commandLength, length;
    Tcl_Size length;
    enum traceOptions {
	TRACE_ADD, TRACE_INFO, TRACE_REMOVE
    };
    static const char *const opStrings[] = {
	"enter", "leave", "enterstep", "leavestep", NULL
    };
    enum operations {
	TRACE_EXEC_ENTER, TRACE_EXEC_LEAVE,
	TRACE_EXEC_ENTER_STEP, TRACE_EXEC_LEAVE_STEP
    };
    } index;

    switch ((enum traceOptions) optionIndex) {
    switch (optionIndex) {
    case TRACE_ADD:
    case TRACE_REMOVE: {
	int flags = 0;
	int i, listLen, result;
	int flags = 0, result;
	Tcl_Size i, listLen;
	Tcl_Obj **elemPtrs;

	if (objc != 6) {
	    Tcl_WrongNumArgs(interp, 3, objv, "name opList command");
	    return TCL_ERROR;
	}

	/*
	 * Make sure the ops argument is a list object; get its length and a
	 * pointer to its array of element pointers.
	 */

	result = Tcl_ListObjGetElements(interp, objv[4], &listLen, &elemPtrs);
	result = TclListObjLength(interp, objv[4], &listLen);
	if (result != TCL_OK) {
	    return result;
	}
	if (listLen == 0) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "bad operation list \"\": must be one or more of"
		    " enter, leave, enterstep, or leavestep", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRACE", "NOOPS",
		    NULL);
		    (char *)NULL);
	    return TCL_ERROR;
	}
	result = TclListObjGetElements(interp, objv[4], &listLen, &elemPtrs);
	if (result != TCL_OK) {
	    return result;
	}
	for (i = 0; i < listLen; i++) {
	    if (Tcl_GetIndexFromObj(interp, elemPtrs[i], opStrings,
		    "operation", TCL_EXACT, &index) != TCL_OK) {
		return TCL_ERROR;
	    }
	    switch ((enum operations) index) {
	    switch (index) {
	    case TRACE_EXEC_ENTER:
		flags |= TCL_TRACE_ENTER_EXEC;
		break;
	    case TRACE_EXEC_LEAVE:
		flags |= TCL_TRACE_LEAVE_EXEC;
		break;
	    case TRACE_EXEC_ENTER_STEP:
		flags |= TCL_TRACE_ENTER_DURING_EXEC;
		break;
	    case TRACE_EXEC_LEAVE_STEP:
		flags |= TCL_TRACE_LEAVE_DURING_EXEC;
		break;
	    }
	}
	command = TclGetStringFromObj(objv[5], &commandLength);
	command = TclGetStringFromObj(objv[5], &length);
	length = commandLength;
	if ((enum traceOptions) optionIndex == TRACE_ADD) {
	if (optionIndex == TRACE_ADD) {
	    TraceCommandInfo *tcmdPtr = (TraceCommandInfo *)Tcl_Alloc(
		    offsetof(TraceCommandInfo, command) + 1 + length);

	    tcmdPtr->flags = flags;
	    tcmdPtr->stepTrace = NULL;
	    tcmdPtr->startLevel = 0;
	    tcmdPtr->startCmd = NULL;
492
493
494
495
496
497
498
499

500
501
502
503
504
505
506
372
373
374
375
376
377
378

379
380
381
382
383
384
385
386







-
+







	} else {
	    /*
	     * Search through all of our traces on this command to see if
	     * there's one with the given command. If so, then delete the
	     * first one that matches.
	     */

	    ClientData clientData;
	    void *clientData;

	    /*
	     * First ensure the name given is valid.
	     */

	    name = TclGetString(objv[3]);
	    if (Tcl_FindCommand(interp,name,NULL,TCL_LEAVE_ERR_MSG) == NULL) {
551
552
553
554
555
556
557
558

559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578

579
580
581
582
583
584
585
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







-
+



















-
+







		    break;
		}
	    }
	}
	break;
    }
    case TRACE_INFO: {
	ClientData clientData;
	void *clientData;
	Tcl_Obj *resultListPtr;

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

	name = TclGetString(objv[3]);

	/*
	 * First ensure the name given is valid.
	 */

	if (Tcl_FindCommand(interp, name, NULL, TCL_LEAVE_ERR_MSG) == NULL) {
	    return TCL_ERROR;
	}

	resultListPtr = Tcl_NewListObj(0, NULL);
	FOREACH_COMMAND_TRACE(interp, name, clientData) {
	    int numOps = 0;
	    Tcl_Size numOps = 0;
	    Tcl_Obj *opObj, *eachTraceObjPtr, *elemObjPtr;
	    TraceCommandInfo *tcmdPtr = (TraceCommandInfo *)clientData;

	    /*
	     * Build a list with the ops list as the first obj element and the
	     * tcmdPtr->command string as the second obj element. Append this
	     * list (as an element) to the end of the result object list.
599
600
601
602
603
604
605
606

607
608
609
610
611
612
613
479
480
481
482
483
484
485

486
487
488
489
490
491
492
493







-
+







		TclNewLiteralStringObj(opObj, "enterstep");
		Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj);
	    }
	    if (tcmdPtr->flags & TCL_TRACE_LEAVE_DURING_EXEC) {
		TclNewLiteralStringObj(opObj, "leavestep");
		Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj);
	    }
	    Tcl_ListObjLength(NULL, elemObjPtr, &numOps);
	    TclListObjLength(NULL, elemObjPtr, &numOps);
	    if (0 == numOps) {
		Tcl_DecrRefCount(elemObjPtr);
		continue;
	    }
	    eachTraceObjPtr = Tcl_NewListObj(0, NULL);
	    Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, elemObjPtr);
	    Tcl_DecrRefCount(elemObjPtr);
642
643
644
645
646
647
648
649
650


651
652
653
654
655

656
657
658

659
660

661
662
663
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
707

708
709
710
711
712
713
714
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
558
559
560
561
562
563

564
565
566
567
568
569

570
571
572
573
574
575

576
577
578
579
580
581
582
583
584
585

586


587
588
589
590
591
592
593
594







-
-
+
+


-

-
+
-

-
+

-
+


-
-
+
+












-
+








-
+


+
+
+
-
+





-
+









-
+
-
-
+







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

static int
TraceCommandObjCmd(
    Tcl_Interp *interp,		/* Current interpreter. */
    int optionIndex,		/* Add, info or remove */
    int objc,			/* Number of arguments. */
    enum traceOptionsEnum optionIndex,		/* Add, info or remove */
    Tcl_Size objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int index;
    const char *name, *command;
    size_t commandLength, length;
    Tcl_Size length;
    enum traceOptions { TRACE_ADD, TRACE_INFO, TRACE_REMOVE };
    static const char *const opStrings[] = { "delete", "rename", NULL };
    enum operations { TRACE_CMD_DELETE, TRACE_CMD_RENAME };
    enum operations { TRACE_CMD_DELETE, TRACE_CMD_RENAME } index;

    switch ((enum traceOptions) optionIndex) {
    switch (optionIndex) {
    case TRACE_ADD:
    case TRACE_REMOVE: {
	int flags = 0;
	int i, listLen, result;
	int flags = 0, result;
	Tcl_Size i, listLen;
	Tcl_Obj **elemPtrs;

	if (objc != 6) {
	    Tcl_WrongNumArgs(interp, 3, objv, "name opList command");
	    return TCL_ERROR;
	}

	/*
	 * Make sure the ops argument is a list object; get its length and a
	 * pointer to its array of element pointers.
	 */

	result = Tcl_ListObjGetElements(interp, objv[4], &listLen, &elemPtrs);
	result = TclListObjLength(interp, objv[4], &listLen);
	if (result != TCL_OK) {
	    return result;
	}
	if (listLen == 0) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "bad operation list \"\": must be one or more of"
		    " delete or rename", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRACE", "NOOPS",
		    NULL);
		    (char *)NULL);
	    return TCL_ERROR;
	}
	result = TclListObjGetElements(interp, objv[4], &listLen, &elemPtrs);
	if (result != TCL_OK) {
	    return result;

	}
	for (i = 0; i < listLen; i++) {
	    if (Tcl_GetIndexFromObj(interp, elemPtrs[i], opStrings,
		    "operation", TCL_EXACT, &index) != TCL_OK) {
		return TCL_ERROR;
	    }
	    switch ((enum operations) index) {
	    switch (index) {
	    case TRACE_CMD_RENAME:
		flags |= TCL_TRACE_RENAME;
		break;
	    case TRACE_CMD_DELETE:
		flags |= TCL_TRACE_DELETE;
		break;
	    }
	}

	command = TclGetStringFromObj(objv[5], &commandLength);
	command = TclGetStringFromObj(objv[5], &length);
	length = commandLength;
	if ((enum traceOptions) optionIndex == TRACE_ADD) {
	if (optionIndex == TRACE_ADD) {
	    TraceCommandInfo *tcmdPtr = (TraceCommandInfo *)Tcl_Alloc(
		    offsetof(TraceCommandInfo, command) + 1 + length);

	    tcmdPtr->flags = flags;
	    tcmdPtr->stepTrace = NULL;
	    tcmdPtr->startLevel = 0;
	    tcmdPtr->startCmd = NULL;
725
726
727
728
729
730
731
732

733
734
735
736
737
738
739
605
606
607
608
609
610
611

612
613
614
615
616
617
618
619







-
+







	} else {
	    /*
	     * Search through all of our traces on this command to see if
	     * there's one with the given command. If so, then delete the
	     * first one that matches.
	     */

	    ClientData clientData;
	    void *clientData;

	    /*
	     * First ensure the name given is valid.
	     */

	    name = TclGetString(objv[3]);
	    if (Tcl_FindCommand(interp,name,NULL,TCL_LEAVE_ERR_MSG) == NULL) {
755
756
757
758
759
760
761
762

763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781

782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801

802
803
804
805
806
807
808
635
636
637
638
639
640
641

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

661
662
663
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







-
+


















-
+



















-
+







		    break;
		}
	    }
	}
	break;
    }
    case TRACE_INFO: {
	ClientData clientData;
	void *clientData;
	Tcl_Obj *resultListPtr;

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

	/*
	 * First ensure the name given is valid.
	 */

	name = TclGetString(objv[3]);
	if (Tcl_FindCommand(interp, name, NULL, TCL_LEAVE_ERR_MSG) == NULL) {
	    return TCL_ERROR;
	}

	resultListPtr = Tcl_NewListObj(0, NULL);
	FOREACH_COMMAND_TRACE(interp, name, clientData) {
	    int numOps = 0;
	    Tcl_Size numOps = 0;
	    Tcl_Obj *opObj, *eachTraceObjPtr, *elemObjPtr;
	    TraceCommandInfo *tcmdPtr = (TraceCommandInfo *)clientData;

	    /*
	     * Build a list with the ops list as the first obj element and the
	     * tcmdPtr->command string as the second obj element. Append this
	     * list (as an element) to the end of the result object list.
	     */

	    elemObjPtr = Tcl_NewListObj(0, NULL);
	    Tcl_IncrRefCount(elemObjPtr);
	    if (tcmdPtr->flags & TCL_TRACE_RENAME) {
		TclNewLiteralStringObj(opObj, "rename");
		Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj);
	    }
	    if (tcmdPtr->flags & TCL_TRACE_DELETE) {
		TclNewLiteralStringObj(opObj, "delete");
		Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj);
	    }
	    Tcl_ListObjLength(NULL, elemObjPtr, &numOps);
	    TclListObjLength(NULL, elemObjPtr, &numOps);
	    if (0 == numOps) {
		Tcl_DecrRefCount(elemObjPtr);
		continue;
	    }
	    eachTraceObjPtr = Tcl_NewListObj(0, NULL);
	    Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, elemObjPtr);
	    Tcl_DecrRefCount(elemObjPtr);
836
837
838
839
840
841
842
843
844


845
846
847
848
849
850


851
852
853
854
855
856
857

858
859

860
861
862
863


864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908

909
910

911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
716
717
718
719
720
721
722


723
724
725
726

727


728
729

730
731
732
733
734

735
736

737
738
739


740
741
742
743
744
745
746
747
748
749
750
751
752
753

754
755
756
757
758
759
760
761
762

763
764
765
766
767
768
769
770
771
772
773
774

775
776
777
778
779
780
781
782
783
784
785
786
787
788
789

790


791
792
793
794
795
796





797
798
799
800
801
802
803







-
-
+
+


-

-
-
+
+
-





-
+

-
+


-
-
+
+












-
+








-
+

+
+
+
+






-
+














-
+
-
-
+





-
-
-
-
-







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

static int
TraceVariableObjCmd(
    Tcl_Interp *interp,		/* Current interpreter. */
    int optionIndex,		/* Add, info or remove */
    int objc,			/* Number of arguments. */
    enum traceOptionsEnum optionIndex,		/* Add, info or remove */
    Tcl_Size objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int index;
    const char *name, *command;
    size_t commandLength, length;
    ClientData clientData;
    Tcl_Size length;
    void *clientData;
    enum traceOptions { TRACE_ADD, TRACE_INFO, TRACE_REMOVE };
    static const char *const opStrings[] = {
	"array", "read", "unset", "write", NULL
    };
    enum operations {
	TRACE_VAR_ARRAY, TRACE_VAR_READ, TRACE_VAR_UNSET, TRACE_VAR_WRITE
    };
    } index;

    switch ((enum traceOptions) optionIndex) {
    switch (optionIndex) {
    case TRACE_ADD:
    case TRACE_REMOVE: {
	int flags = 0;
	int i, listLen, result;
	int flags = 0, result;
	Tcl_Size i, listLen;
	Tcl_Obj **elemPtrs;

	if (objc != 6) {
	    Tcl_WrongNumArgs(interp, 3, objv, "name opList command");
	    return TCL_ERROR;
	}

	/*
	 * Make sure the ops argument is a list object; get its length and a
	 * pointer to its array of element pointers.
	 */

	result = Tcl_ListObjGetElements(interp, objv[4], &listLen, &elemPtrs);
	result = TclListObjLength(interp, objv[4], &listLen);
	if (result != TCL_OK) {
	    return result;
	}
	if (listLen == 0) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "bad operation list \"\": must be one or more of"
		    " array, read, unset, or write", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRACE", "NOOPS",
		    NULL);
		    (char *)NULL);
	    return TCL_ERROR;
	}
	result = TclListObjGetElements(interp, objv[4], &listLen, &elemPtrs);
	if (result != TCL_OK) {
	    return result;
	}
	for (i = 0; i < listLen ; i++) {
	    if (Tcl_GetIndexFromObj(interp, elemPtrs[i], opStrings,
		    "operation", TCL_EXACT, &index) != TCL_OK) {
		return TCL_ERROR;
	    }
	    switch ((enum operations) index) {
	    switch (index) {
	    case TRACE_VAR_ARRAY:
		flags |= TCL_TRACE_ARRAY;
		break;
	    case TRACE_VAR_READ:
		flags |= TCL_TRACE_READS;
		break;
	    case TRACE_VAR_UNSET:
		flags |= TCL_TRACE_UNSETS;
		break;
	    case TRACE_VAR_WRITE:
		flags |= TCL_TRACE_WRITES;
		break;
	    }
	}
	command = TclGetStringFromObj(objv[5], &commandLength);
	command = TclGetStringFromObj(objv[5], &length);
	length = commandLength;
	if ((enum traceOptions) optionIndex == TRACE_ADD) {
	if (optionIndex == TRACE_ADD) {
	    CombinedTraceVarInfo *ctvarPtr = (CombinedTraceVarInfo *)Tcl_Alloc(
		    offsetof(CombinedTraceVarInfo, traceCmdInfo.command)
		    + 1 + length);

	    ctvarPtr->traceCmdInfo.flags = flags;
#ifndef TCL_REMOVE_OBSOLETE_TRACES
	    if (objv[0] == NULL) {
		ctvarPtr->traceCmdInfo.flags |= TCL_TRACE_OLD_STYLE;
	    }
#endif
	    ctvarPtr->traceCmdInfo.length = length;
	    flags |= TCL_TRACE_UNSETS | TCL_TRACE_RESULT_OBJECT;
	    memcpy(ctvarPtr->traceCmdInfo.command, command, length+1);
	    ctvarPtr->traceInfo.traceProc = TraceVarProc;
	    ctvarPtr->traceInfo.clientData = &ctvarPtr->traceCmdInfo;
	    ctvarPtr->traceInfo.flags = flags;
	    name = TclGetString(objv[3]);
938
939
940
941
942
943
944
945

946
947
948
949
950
951
952
953
954
955
956
814
815
816
817
818
819
820

821




822
823
824
825
826
827
828







-
+
-
-
-
-







	     */

	    name = TclGetString(objv[3]);
	    FOREACH_VAR_TRACE(interp, name, clientData) {
		TraceVarInfo *tvarPtr = (TraceVarInfo *)clientData;

		if ((tvarPtr->length == length)
			&& ((tvarPtr->flags
			&& ((tvarPtr->flags)==flags)
#ifndef TCL_REMOVE_OBSOLETE_TRACES
& ~TCL_TRACE_OLD_STYLE
#endif
						)==flags)
			&& (strncmp(command, tvarPtr->command,
				length) == 0)) {
		    Tcl_UntraceVar2(interp, name, NULL,
			    flags | TCL_TRACE_UNSETS | TCL_TRACE_RESULT_OBJECT,
			    TraceVarProc, clientData);
		    break;
		}
1031
1032
1033
1034
1035
1036
1037
1038

1039
1040
1041
1042
1043
1044

1045
1046
1047
1048
1049
1050
1051
903
904
905
906
907
908
909

910
911
912
913
914
915

916
917
918
919
920
921
922
923







-
+





-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

ClientData
void *
Tcl_CommandTraceInfo(
    Tcl_Interp *interp,		/* Interpreter containing command. */
    const char *cmdName,	/* Name of command. */
    TCL_UNUSED(int) /*flags*/,
    Tcl_CommandTraceProc *proc,	/* Function assocated with trace. */
    ClientData prevClientData)	/* If non-NULL, gives last value returned by
    void *prevClientData)	/* If non-NULL, gives last value returned by
				 * this function, so this call will return the
				 * next trace after that one. If NULL, this
				 * call will return the first trace. */
{
    Command *cmdPtr;
    CommandTrace *tracePtr;

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
1116
1117
1118
1119
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







-
+















-
+







 *	function to be invoked.
 *
 * Results:
 *	A standard Tcl return value.
 *
 * Side effects:
 *	A trace is set up on the command given by cmdName, such that future
 *	changes to the command will be intermediated by proc. See the manual
 *	changes to the command will be mediated by proc. See the manual
 *	entry for complete details on the calling sequence for proc.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_TraceCommand(
    Tcl_Interp *interp,		/* Interpreter in which command is to be
				 * traced. */
    const char *cmdName,	/* Name of command. */
    int flags,			/* OR-ed collection of bits, including any of
				 * TCL_TRACE_RENAME, TCL_TRACE_DELETE, and any
				 * of the TRACE_*_EXEC flags */
    Tcl_CommandTraceProc *proc,	/* Function to call when specified ops are
				 * invoked upon cmdName. */
    ClientData clientData)	/* Arbitrary argument to pass to proc. */
    void *clientData)	/* Arbitrary argument to pass to proc. */
{
    Command *cmdPtr;
    CommandTrace *tracePtr;

    cmdPtr = (Command *) Tcl_FindCommand(interp, cmdName, NULL,
	    TCL_LEAVE_ERR_MSG);
    if (cmdPtr == NULL) {
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1012
1013
1014
1015
1016
1017
1018

1019
1020
1021
1022
1023
1024
1025







-







	if ((cmdPtr->compileProc != NULL) && !(cmdPtr->flags & CMD_HAS_EXEC_TRACES)){
	    Interp *iPtr = (Interp *) interp;
	    iPtr->compileEpoch++;
	}
	cmdPtr->flags |= CMD_HAS_EXEC_TRACES;
    }


    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UntraceCommand --
1169
1170
1171
1172
1173
1174
1175
1176

1177
1178
1179
1180
1181
1182
1183
1040
1041
1042
1043
1044
1045
1046

1047
1048
1049
1050
1051
1052
1053
1054







-
+







Tcl_UntraceCommand(
    Tcl_Interp *interp,		/* Interpreter containing command. */
    const char *cmdName,	/* Name of command. */
    int flags,			/* OR-ed collection of bits, including any of
				 * TCL_TRACE_RENAME, TCL_TRACE_DELETE, and any
				 * of the TRACE_*_EXEC flags */
    Tcl_CommandTraceProc *proc,	/* Function assocated with trace. */
    ClientData clientData)	/* Arbitrary argument to pass to proc. */
    void *clientData)	/* Arbitrary argument to pass to proc. */
{
    CommandTrace *tracePtr;
    CommandTrace *prevPtr;
    Command *cmdPtr;
    Interp *iPtr = (Interp *)interp;
    ActiveCommandTrace *activePtr;
    int hasExecTraces = 0;
1244
1245
1246
1247
1248
1249
1250
1251

1252
1253
1254
1255
1256
1257
1258
1115
1116
1117
1118
1119
1120
1121

1122
1123
1124
1125
1126
1127
1128
1129







-
+







	/*
	 * None of the remaining traces on this command are execution traces.
	 * We therefore remove this flag:
	 */

	cmdPtr->flags &= ~CMD_HAS_EXEC_TRACES;

        /*
	/*
	 * Bug 3484621: up the interp's epoch if this is a BC'ed command
	 */

	if (cmdPtr->compileProc != NULL) {
	    iPtr->compileEpoch++;
	}
    }
1274
1275
1276
1277
1278
1279
1280
1281

1282
1283
1284
1285
1286
1287
1288
1145
1146
1147
1148
1149
1150
1151

1152
1153
1154
1155
1156
1157
1158
1159







-
+







 *	Depends on the command associated with the trace.
 *
 *----------------------------------------------------------------------
 */

static void
TraceCommandProc(
    ClientData clientData,	/* Information about the command trace. */
    void *clientData,	/* Information about the command trace. */
    Tcl_Interp *interp,		/* Interpreter containing command. */
    const char *oldName,	/* Name of command being changed. */
    const char *newName,	/* New name of command. Empty string or NULL
				 * means command is being deleted (renamed to
				 * ""). */
    int flags)			/* OR-ed bits giving operation and other
				 * information. */
1415
1416
1417
1418
1419
1420
1421
1422

1423
1424
1425
1426

1427
1428
1429
1430
1431
1432

1433
1434
1435
1436
1437
1438
1439
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







-
+



-
+





-
+







 */

int
TclCheckExecutionTraces(
    Tcl_Interp *interp,		/* The current interpreter. */
    const char *command,	/* Pointer to beginning of the current command
				 * string. */
    TCL_UNUSED(size_t) /*numChars*/,
    TCL_UNUSED(Tcl_Size) /*numChars*/,
    Command *cmdPtr,		/* Points to command's Command struct. */
    int code,			/* The current result code. */
    int traceFlags,		/* Current tracing situation. */
    int objc,			/* Number of arguments for the command. */
    Tcl_Size objc,			/* Number of arguments for the command. */
    Tcl_Obj *const objv[])	/* Pointers to Tcl_Obj of each argument. */
{
    Interp *iPtr = (Interp *) interp;
    CommandTrace *tracePtr, *lastTracePtr;
    ActiveCommandTrace active;
    int curLevel;
    Tcl_Size curLevel;
    int traceCode = TCL_OK;
    Tcl_InterpState state = NULL;

    if (cmdPtr->tracePtr == NULL) {
	return traceCode;
    }

1520
1521
1522
1523
1524
1525
1526
1527

1528
1529
1530
1531
1532

1533
1534
1535
1536
1537
1538

1539
1540
1541
1542
1543
1544
1545
1391
1392
1393
1394
1395
1396
1397

1398
1399
1400
1401
1402

1403
1404
1405
1406
1407
1408

1409
1410
1411
1412
1413
1414
1415
1416







-
+




-
+





-
+







 */

int
TclCheckInterpTraces(
    Tcl_Interp *interp,		/* The current interpreter. */
    const char *command,	/* Pointer to beginning of the current command
				 * string. */
    size_t numChars,		/* The number of characters in 'command' which
    Tcl_Size numChars,		/* The number of characters in 'command' which
				 * are part of the command string. */
    Command *cmdPtr,		/* Points to command's Command struct. */
    int code,			/* The current result code. */
    int traceFlags,		/* Current tracing situation. */
    int objc,			/* Number of arguments for the command. */
    Tcl_Size objc,			/* Number of arguments for the command. */
    Tcl_Obj *const objv[])	/* Pointers to Tcl_Obj of each argument. */
{
    Interp *iPtr = (Interp *) interp;
    Trace *tracePtr, *lastTracePtr;
    ActiveInterpTrace active;
    int curLevel;
    Tcl_Size curLevel;
    int traceCode = TCL_OK;
    Tcl_InterpState state = NULL;

    if ((iPtr->tracePtr == NULL)
	    || (iPtr->flags & INTERP_TRACE_IN_PROGRESS)) {
	return(traceCode);
    }
1580
1581
1582
1583
1584
1585
1586
1587

1588
1589
1590
1591
1592
1593
1594
1451
1452
1453
1454
1455
1456
1457

1458
1459
1460
1461
1462
1463
1464
1465







-
+








	if (tracePtr->level > 0 && curLevel > tracePtr->level) {
	    continue;
	}

	if (!(tracePtr->flags & TCL_TRACE_EXEC_IN_PROGRESS)) {
	    /*
	     * The proc invoked might delete the traced command which which
	     * The proc invoked might delete the traced command which
	     * might try to free tracePtr. We want to use tracePtr until the
	     * end of this if section, so we use Tcl_Preserve() and
	     * Tcl_Release() to be sure it is not freed while we still need
	     * it.
	     */

	    Tcl_Preserve(tracePtr);
1667
1668
1669
1670
1671
1672
1673
1674

1675
1676

1677
1678
1679
1680
1681
1682
1683
1538
1539
1540
1541
1542
1543
1544

1545
1546

1547
1548
1549
1550
1551
1552
1553
1554







-
+

-
+







static int
CallTraceFunction(
    Tcl_Interp *interp,		/* The current interpreter. */
    Trace *tracePtr,	/* Describes the trace function to call. */
    Command *cmdPtr,		/* Points to command's Command struct. */
    const char *command,	/* Points to the first character of the
				 * command's source before substitutions. */
    size_t numChars,		/* The number of characters in the command's
    Tcl_Size numChars,		/* The number of characters in the command's
				 * source. */
    int objc,		/* Number of arguments for the command. */
    Tcl_Size objc,		/* Number of arguments for the command. */
    Tcl_Obj *const objv[])	/* Pointers to Tcl_Obj of each argument. */
{
    Interp *iPtr = (Interp *) interp;
    char *commandCopy;
    int traceCode;

    /*
1714
1715
1716
1717
1718
1719
1720
1721

1722
1723
1724
1725
1726
1727
1728
1585
1586
1587
1588
1589
1590
1591

1592
1593
1594
1595
1596
1597
1598
1599







-
+







 *	May release memory.
 *
 *----------------------------------------------------------------------
 */

static void
CommandObjTraceDeleted(
    ClientData clientData)
    void *clientData)
{
    TraceCommandInfo *tcmdPtr = (TraceCommandInfo *)clientData;

    if (tcmdPtr->refCount-- <= 1) {
	Tcl_Free(tcmdPtr);
    }
}
1750
1751
1752
1753
1754
1755
1756
1757

1758
1759

1760
1761
1762
1763


1764
1765
1766
1767
1768
1769
1770
1621
1622
1623
1624
1625
1626
1627

1628
1629

1630
1631
1632


1633
1634
1635
1636
1637
1638
1639
1640
1641







-
+

-
+


-
-
+
+







 *	interpreter-wide trace.
 *
 *----------------------------------------------------------------------
 */

static int
TraceExecutionProc(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int level,
    Tcl_Size level,
    const char *command,
    TCL_UNUSED(Tcl_Command),
    int objc,
    struct Tcl_Obj *const objv[])
    Tcl_Size objc,
    Tcl_Obj *const objv[])
{
    int call = 0;
    Interp *iPtr = (Interp *) interp;
    TraceCommandInfo *tcmdPtr = (TraceCommandInfo *)clientData;
    int flags = tcmdPtr->curFlags;
    int code = tcmdPtr->curCode;
    int traceCode = TCL_OK;
1810
1811
1812
1813
1814
1815
1816

1817

1818
1819
1820
1821
1822
1823
1824
1681
1682
1683
1684
1685
1686
1687
1688

1689
1690
1691
1692
1693
1694
1695
1696







+
-
+








	/*
	 * Second, create the tcl callback, if required.
	 */

	if (call) {
	    Tcl_DString cmd, sub;
	    Tcl_Size i;
	    int i, saveInterpFlags;
	    int saveInterpFlags;

	    Tcl_DStringInit(&cmd);
	    Tcl_DStringAppend(&cmd, tcmdPtr->command, tcmdPtr->length);

	    /*
	     * Append command with arguments.
	     */
1917
1918
1919
1920
1921
1922
1923
1924

1925
1926
1927
1928
1929
1930
1931
1789
1790
1791
1792
1793
1794
1795

1796
1797
1798
1799
1800
1801
1802
1803







-
+







			TCL_TRACE_LEAVE_DURING_EXEC))) {
	    unsigned len = strlen(command) + 1;

	    tcmdPtr->startLevel = level;
	    tcmdPtr->startCmd = (char *)Tcl_Alloc(len);
	    memcpy(tcmdPtr->startCmd, command, len);
	    tcmdPtr->refCount++;
	    tcmdPtr->stepTrace = Tcl_CreateObjTrace(interp, 0,
	    tcmdPtr->stepTrace = Tcl_CreateObjTrace2(interp, 0,
		   (tcmdPtr->flags & TCL_TRACE_ANY_EXEC) >> 2,
		   TraceExecutionProc, tcmdPtr, CommandObjTraceDeleted);
	}
    }
    if (flags & TCL_TRACE_DESTROYED) {
	if (tcmdPtr->stepTrace != NULL) {
	    Tcl_DeleteTrace(interp, tcmdPtr->stepTrace);
1957
1958
1959
1960
1961
1962
1963
1964

1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982




1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
1829
1830
1831
1832
1833
1834
1835

1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850




1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869













1870
1871
1872
1873
1874
1875
1876
1877
1878



1879
1880
1881
1882
1883
1884
1885







-
+














-
-
-
-
+
+
+
+















-
-
-
-
-
-
-
-
-
-
-
-
-









-
-
-







 *	Depends on the command associated with the trace.
 *
 *----------------------------------------------------------------------
 */

static char *
TraceVarProc(
    ClientData clientData,	/* Information about the variable trace. */
    void *clientData,	/* Information about the variable trace. */
    Tcl_Interp *interp,		/* Interpreter containing variable. */
    const char *name1,		/* Name of variable or array. */
    const char *name2,		/* Name of element within array; NULL means
				 * scalar variable is being referenced. */
    int flags)			/* OR-ed bits giving operation and other
				 * information. */
{
    TraceVarInfo *tvarPtr = (TraceVarInfo *)clientData;
    char *result;
    int code, destroy = 0;
    Tcl_DString cmd;
    int rewind = ((Interp *)interp)->execEnvPtr->rewind;

    /*
     * We might call Tcl_EvalEx() below, and that might evaluate [trace vdelete]
     * which might try to free tvarPtr. We want to use tvarPtr until the end
     * of this function, so we use Tcl_Preserve() and Tcl_Release() to be sure
     * it is not freed while we still need it.
     * We might call Tcl_EvalEx() below, and that might evaluate
     * [trace remove variable] which might try to free tvarPtr. We want to
     * use tvarPtr until the end of this function, so we use Tcl_Preserve()
     * and Tcl_Release() to be sure it is not freed while we still need it.
     */

    result = NULL;
    if ((tvarPtr->flags & flags) && !Tcl_InterpDeleted(interp)
	    && !Tcl_LimitExceeded(interp)) {
	if (tvarPtr->length) {
	    /*
	     * Generate a command to execute by appending list elements for
	     * the two variable names and the operation.
	     */

	    Tcl_DStringInit(&cmd);
	    Tcl_DStringAppend(&cmd, tvarPtr->command, tvarPtr->length);
	    Tcl_DStringAppendElement(&cmd, name1);
	    Tcl_DStringAppendElement(&cmd, (name2 ? name2 : ""));
#ifndef TCL_REMOVE_OBSOLETE_TRACES
	    if (tvarPtr->flags & TCL_TRACE_OLD_STYLE) {
		if (flags & TCL_TRACE_ARRAY) {
		    TclDStringAppendLiteral(&cmd, " a");
		} else if (flags & TCL_TRACE_READS) {
		    TclDStringAppendLiteral(&cmd, " r");
		} else if (flags & TCL_TRACE_WRITES) {
		    TclDStringAppendLiteral(&cmd, " w");
		} else if (flags & TCL_TRACE_UNSETS) {
		    TclDStringAppendLiteral(&cmd, " u");
		}
	    } else {
#endif
		if (flags & TCL_TRACE_ARRAY) {
		    TclDStringAppendLiteral(&cmd, " array");
		} else if (flags & TCL_TRACE_READS) {
		    TclDStringAppendLiteral(&cmd, " read");
		} else if (flags & TCL_TRACE_WRITES) {
		    TclDStringAppendLiteral(&cmd, " write");
		} else if (flags & TCL_TRACE_UNSETS) {
		    TclDStringAppendLiteral(&cmd, " unset");
		}
#ifndef TCL_REMOVE_OBSOLETE_TRACES
	    }
#endif

	    /*
	     * Execute the command. We discard any object result the command
	     * returns.
	     *
	     * Add the TCL_TRACE_DESTROYED flag to tvarPtr to indicate to
	     * other areas that this will be destroyed by us, otherwise a
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
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
1958




1959
1960
1961
1962
1963
1964
1965







-
+












-
+
















-
-
-
-







    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_CreateObjTrace --
 * Tcl_CreateObjTrace/Tcl_CreateObjTrace2 --
 *
 *	Arrange for a function to be called to trace command execution.
 *
 * Results:
 *	The return value is a token for the trace, which may be passed to
 *	Tcl_DeleteTrace to eliminate the trace.
 *
 * Side effects:
 *	From now on, proc will be called just before a command function is
 *	called to execute a Tcl command. Calls to proc will have the following
 *	form:
 *
 *	void proc(ClientData	 clientData,
 *	void proc(void   *	 clientData,
 *		  Tcl_Interp *	 interp,
 *		  int		 level,
 *		  const char *	 command,
 *		  Tcl_Command	 commandInfo,
 *		  int		 objc,
 *		  Tcl_Obj *const objv[]);
 *
 *	The 'clientData' and 'interp' arguments to 'proc' will be the same as
 *	the arguments to Tcl_CreateObjTrace. The 'level' argument gives the
 *	nesting depth of command interpretation within the interpreter. The
 *	'command' argument is the ASCII text of the command being evaluated -
 *	before any substitutions are performed. The 'commandInfo' argument
 *	gives a handle to the command procedure that will be evaluated. The
 *	'objc' and 'objv' parameters give the parameter vector that will be
 *	passed to the command procedure. Proc does not return a value.
 *
 *	It is permissible for 'proc' to call Tcl_SetCommandTokenInfo to change
 *	the command procedure or client data for the command being evaluated,
 *	and these changes will take effect with the current evaluation.
 *
 *	The 'level' argument specifies the maximum nesting level of calls to
 *	be traced. If the execution depth of the interpreter exceeds 'level',
 *	the trace callback is not executed.
 *
 *	The 'flags' argument is either zero or the value,
 *	TCL_ALLOW_INLINE_COMPILATION. If the TCL_ALLOW_INLINE_COMPILATION flag
 *	is not present, the bytecode compiler will not generate inline code
2121
2122
2123
2124
2125
2126
2127
2128



































2129
2130
2131
2132

2133
2134
2135




















2136
2137
2138
2139
2140
2141
2142
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018

2019
2020
2021

2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+


-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *	applications such as profiling of run time.
 *
 *	When the trace is deleted, the 'delProc' function will be invoked,
 *	passing it the original client data.
 *
 *----------------------------------------------------------------------
 */

typedef struct {
    Tcl_CmdObjTraceProc *proc;
    Tcl_CmdObjTraceDeleteProc *delProc;
    void *clientData;
} TraceWrapperInfo;

static int
traceWrapperProc(
    void *clientData,
    Tcl_Interp *interp,
    Tcl_Size level,
    const char *command,
    Tcl_Command commandInfo,
    Tcl_Size objc,
    Tcl_Obj *const objv[])
{
    TraceWrapperInfo *info = (TraceWrapperInfo *)clientData;
    if (objc > INT_MAX) {
	objc = -1; /* Signal Tcl_CmdObjTraceProc that objc is out of range */
    }
    return info->proc(info->clientData, interp, (int)level, command, commandInfo, objc, objv);
}

static void
traceWrapperDelProc(
    void *clientData)
{
    TraceWrapperInfo *info = (TraceWrapperInfo *)clientData;
    clientData = info->clientData;
    if (info->delProc) {
	info->delProc(clientData);
    }
    Tcl_Free(info);
}

Tcl_Trace
Tcl_CreateObjTrace(
    Tcl_Interp *interp,		/* Tcl interpreter */
    int level,			/* Maximum nesting level */
    Tcl_Size level,			/* Maximum nesting level */
    int flags,			/* Flags, see above */
    Tcl_CmdObjTraceProc *proc,	/* Trace callback */
    ClientData clientData,	/* Client data for the callback */
    void *clientData,	/* Client data for the callback */
    Tcl_CmdObjTraceDeleteProc *delProc)
				/* Function to call when trace is deleted */
{
    TraceWrapperInfo *info = (TraceWrapperInfo *)Tcl_Alloc(sizeof(TraceWrapperInfo));
    info->proc = proc;
    info->delProc = delProc;
    info->clientData = clientData;
    return Tcl_CreateObjTrace2(interp, level, flags,
	    (proc ? traceWrapperProc : NULL),
	    info, traceWrapperDelProc);
}

Tcl_Trace
Tcl_CreateObjTrace2(
    Tcl_Interp *interp,		/* Tcl interpreter */
    Tcl_Size level,			/* Maximum nesting level */
    int flags,			/* Flags, see above */
    Tcl_CmdObjTraceProc2 *proc,	/* Trace callback */
    void *clientData,	/* Client data for the callback */
    Tcl_CmdObjTraceDeleteProc *delProc)
				/* Function to call when trace is deleted */
{
    Trace *tracePtr;
    Interp *iPtr = (Interp *) interp;

    /*
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

2222
2223
2224
2225

2226
2227
2228
2229
2230
2231

2232
2233
2234
2235
2236
2237
2238
2094
2095
2096
2097
2098
2099
2100

2101
2102
2103
2104
2105

2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126

2127
2128
2129
2130

2131
2132
2133
2134
2135
2136

2137
2138
2139
2140
2141
2142
2143
2144







-
+




-
+




















-
+



-
+





-
+







 *	From now on, proc will be called just before a command procedure is
 *	called to execute a Tcl command. Calls to proc will have the following
 *	form:
 *
 *	void
 *	proc(clientData, interp, level, command, cmdProc, cmdClientData,
 *		argc, argv)
 *	    ClientData clientData;
 *	    void *clientData;
 *	    Tcl_Interp *interp;
 *	    int level;
 *	    char *command;
 *	    int (*cmdProc)();
 *	    ClientData cmdClientData;
 *	    void *cmdClientData;
 *	    int argc;
 *	    char **argv;
 *	{
 *	}
 *
 *	The clientData and interp arguments to proc will be the same as the
 *	corresponding arguments to this function. Level gives the nesting
 *	level of command interpretation for this interpreter (0 corresponds to
 *	top level). Command gives the ASCII text of the raw command, cmdProc
 *	and cmdClientData give the function that will be called to process the
 *	command and the ClientData value it will receive, and argc and argv
 *	give the arguments to the command, after any argument parsing and
 *	substitution. Proc does not return a value.
 *
 *----------------------------------------------------------------------
 */

Tcl_Trace
Tcl_CreateTrace(
    Tcl_Interp *interp,		/* Interpreter in which to create trace. */
    int level,			/* Only call proc for commands at nesting
    Tcl_Size level,			/* Only call proc for commands at nesting
				 * level<=argument level (1=>top level). */
    Tcl_CmdTraceProc *proc,	/* Function to call before executing each
				 * command. */
    ClientData clientData)	/* Arbitrary value word to pass to proc. */
    void *clientData)	/* Arbitrary value word to pass to proc. */
{
    StringTraceData *data = (StringTraceData *)Tcl_Alloc(sizeof(StringTraceData));

    data->clientData = clientData;
    data->proc = proc;
    return Tcl_CreateObjTrace(interp, level, 0, StringTraceProc,
    return Tcl_CreateObjTrace2(interp, level, 0, StringTraceProc,
	    data, StringTraceDeleteProc);
}

/*
 *----------------------------------------------------------------------
 *
 * StringTraceProc --
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
2152
2153
2154
2155
2156
2157
2158

2159
2160

2161
2162
2163

2164
2165
2166
2167
2168
2169

2170
2171
2172
2173
2174
2175
2176
2177







-
+

-
+


-
+





-
+







 *	Whatever the string-based trace function does.
 *
 *----------------------------------------------------------------------
 */

static int
StringTraceProc(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,
    int level,
    Tcl_Size level,
    const char *command,
    Tcl_Command commandInfo,
    int objc,
    Tcl_Size objc,
    Tcl_Obj *const *objv)
{
    StringTraceData *data = (StringTraceData *)clientData;
    Command *cmdPtr = (Command *) commandInfo;
    const char **argv;		/* Args to pass to string trace proc */
    int i;
    Tcl_Size i;

    /*
     * This is a bit messy because we have to emulate the old trace interface,
     * which uses strings for everything.
     */

    argv = (const char **) TclStackAlloc(interp,
2302
2303
2304
2305
2306
2307
2308
2309

2310
2311
2312
2313
2314
2315
2316
2208
2209
2210
2211
2212
2213
2214

2215
2216
2217
2218
2219
2220
2221
2222







-
+







 *	Allocated memory is returned to the system.
 *
 *----------------------------------------------------------------------
 */

static void
StringTraceDeleteProc(
    ClientData clientData)
    void *clientData)
{
    Tcl_Free(clientData);
}

/*
 *----------------------------------------------------------------------
 *
2488
2489
2490
2491
2492
2493
2494
2495

2496
2497
2498
2499
2500
2501
2502
2394
2395
2396
2397
2398
2399
2400

2401
2402
2403
2404
2405
2406
2407
2408







-
+







    Var *arrayPtr,
    Tcl_Obj *name,
    int index)
{
    int code = TCL_OK;

    if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY)
	&& (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) {
	    && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) {
	Interp *iPtr = (Interp *)interp;

	code = TclObjCallVarTraces(iPtr, arrayPtr, varPtr, name, NULL,
		(TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| TCL_TRACE_ARRAY),
		/* leaveErrMsg */ 1, index);
    }
    return code;
2582
2583
2584
2585
2586
2587
2588

2589
2590
2591
2592
2593
2594
2595
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502







+







    Tcl_DString nameCopy;
    int copiedName;
    int code = TCL_OK;
    int disposeFlags = 0;
    Tcl_InterpState state = NULL;
    Tcl_HashEntry *hPtr;
    int traceflags = flags & VAR_ALL_TRACES;
    const char *element;

    /*
     * If there are already similar trace functions active for the variable,
     * don't call them again.
     */

    if (TclIsVarTraceActive(varPtr)) {
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
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
+







		    part2 = newPart1 + offset + 1;
		    copiedName = 1;
		}
		break;
	    }
	}
    }

    /* Keep the original pointer for possible use in an error message */
    element = part2;
    if (part2 == NULL) {
	if (TclIsVarArrayElement(varPtr)) {
	    Tcl_Obj *keyObj = VarHashGetKey(varPtr);
	    part2 = Tcl_GetString(keyObj);
	}
    } else if ((flags & VAR_TRACED_UNSET) && !(flags & VAR_ARRAY_ELEMENT)) {
	/* On unset traces, part2 has already been set by the caller, and
	 * the VAR_ARRAY_ELEMENT flag indicates whether the accessed
	 * variable actually has a second part, or is a scalar */
	element = NULL;
    }

    /*
     * Invoke traces on the array containing the variable, if relevant.
     */

    result = NULL;
    active.nextPtr = iPtr->activeVarTracePtr;
    iPtr->activeVarTracePtr = &active;
    Tcl_Preserve(iPtr);
    if (arrayPtr && !TclIsVarTraceActive(arrayPtr)
	    && (arrayPtr->flags & traceflags)) {
	hPtr = Tcl_FindHashEntry(&iPtr->varTraces, (char *) arrayPtr);
	hPtr = Tcl_FindHashEntry(&iPtr->varTraces, arrayPtr);
	active.varPtr = arrayPtr;
	for (tracePtr = (VarTrace *)Tcl_GetHashValue(hPtr);
		tracePtr != NULL; tracePtr = active.nextTracePtr) {
	    active.nextTracePtr = tracePtr->nextPtr;
	    if (!(tracePtr->flags & flags)) {
		continue;
	    }
2685
2686
2687
2688
2689
2690
2691
2692

2693
2694
2695
2696
2697
2698
2699
2606
2607
2608
2609
2610
2611
2612

2613
2614
2615
2616
2617
2618
2619
2620







-
+







     */

    if (flags & TCL_TRACE_UNSETS) {
	flags |= TCL_TRACE_DESTROYED;
    }
    active.varPtr = varPtr;
    if (varPtr->flags & traceflags) {
	hPtr = Tcl_FindHashEntry(&iPtr->varTraces, (char *) varPtr);
	hPtr = Tcl_FindHashEntry(&iPtr->varTraces, varPtr);
	for (tracePtr = (VarTrace *)Tcl_GetHashValue(hPtr);
		tracePtr != NULL; tracePtr = active.nextTracePtr) {
	    active.nextTracePtr = tracePtr->nextPtr;
	    if (!(tracePtr->flags & flags)) {
		continue;
	    }
	    Tcl_Preserve(tracePtr);
2753
2754
2755
2756
2757
2758
2759
2760
2761


2762
2763

2764
2765
2766

2767
2768
2769
2770
2771
2772
2773
2674
2675
2676
2677
2678
2679
2680


2681
2682
2683

2684
2685
2686

2687
2688
2689
2690
2691
2692
2693
2694







-
-
+
+

-
+


-
+







		Tcl_SetObjResult((Tcl_Interp *)iPtr,
			Tcl_NewStringObj(result, -1));
	    }
	    Tcl_AddErrorInfo((Tcl_Interp *)iPtr, "");

	    Tcl_AppendObjToErrorInfo((Tcl_Interp *)iPtr, Tcl_ObjPrintf(
		    "\n    (%s trace on \"%s%s%s%s\")", type, part1,
		    (part2 ? "(" : ""), (part2 ? part2 : ""),
		    (part2 ? ")" : "") ));
		    (element ? "(" : ""), (element ? element : ""),
		    (element ? ")" : "") ));
	    if (disposeFlags & TCL_TRACE_RESULT_OBJECT) {
		TclVarErrMsg((Tcl_Interp *) iPtr, part1, part2, verb,
		TclVarErrMsg((Tcl_Interp *) iPtr, part1, element, verb,
			TclGetString((Tcl_Obj *) result));
	    } else {
		TclVarErrMsg((Tcl_Interp *) iPtr, part1, part2, verb, result);
		TclVarErrMsg((Tcl_Interp *) iPtr, part1, element, verb, result);
	    }
	    iPtr->flags &= ~(ERR_ALREADY_LOGGED);
	    Tcl_DiscardInterpState(state);
	} else {
	    Tcl_RestoreInterpState((Tcl_Interp *) iPtr, state);
	}
	DisposeTraceResult(disposeFlags,result);
2850
2851
2852
2853
2854
2855
2856
2857
2858


2859
2860
2861
2862
2863
2864
2865
2771
2772
2773
2774
2775
2776
2777


2778
2779
2780
2781
2782
2783
2784
2785
2786







-
-
+
+







    const char *part2,		/* Name of element within array; NULL means
				 * trace applies to scalar variable or array
				 * as-a-whole. */
    int flags,			/* OR-ed collection of bits describing current
				 * trace, including any of TCL_TRACE_READS,
				 * TCL_TRACE_WRITES, TCL_TRACE_UNSETS,
				 * TCL_GLOBAL_ONLY, and TCL_NAMESPACE_ONLY. */
    Tcl_VarTraceProc *proc,	/* Function assocated with trace. */
    ClientData clientData)	/* Arbitrary argument to pass to proc. */
    Tcl_VarTraceProc *proc,	/* Function associated with trace. */
    void *clientData)	/* Arbitrary argument to pass to proc. */
{
    VarTrace *tracePtr;
    VarTrace *prevPtr, *nextPtr;
    Var *varPtr, *arrayPtr;
    Interp *iPtr = (Interp *) interp;
    ActiveVarTrace *activePtr;
    int flagMask, allFlags = 0;
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892

2893
2894
2895
2896
2897
2898
2899
2801
2802
2803
2804
2805
2806
2807



2808
2809

2810
2811
2812
2813
2814
2815
2816
2817







-
-
-


-
+







    /*
     * Set up a mask to mask out the parts of the flags that we are not
     * interested in now.
     */

    flagMask = TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS |
	  TCL_TRACE_ARRAY | TCL_TRACE_RESULT_DYNAMIC | TCL_TRACE_RESULT_OBJECT;
#ifndef TCL_REMOVE_OBSOLETE_TRACES
    flagMask |= TCL_TRACE_OLD_STYLE;
#endif
    flags &= flagMask;

    hPtr = Tcl_FindHashEntry(&iPtr->varTraces, (char *) varPtr);
    hPtr = Tcl_FindHashEntry(&iPtr->varTraces, varPtr);
    for (tracePtr = (VarTrace *)Tcl_GetHashValue(hPtr), prevPtr = NULL; ;
	    prevPtr = tracePtr, tracePtr = tracePtr->nextPtr) {
	if (tracePtr == NULL) {
	    goto updateFlags;
	}
	if ((tracePtr->traceProc == proc) && (tracePtr->flags == flags)
		&& (tracePtr->clientData == clientData)) {
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
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







-
+








-
-
+
+



















-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

ClientData
void *
Tcl_VarTraceInfo2(
    Tcl_Interp *interp,		/* Interpreter containing variable. */
    const char *part1,		/* Name of variable or array. */
    const char *part2,		/* Name of element within array; NULL means
				 * trace applies to scalar variable or array
				 * as-a-whole. */
    int flags,			/* OR-ed combination of TCL_GLOBAL_ONLY,
				 * TCL_NAMESPACE_ONLY. */
    Tcl_VarTraceProc *proc,	/* Function assocated with trace. */
    ClientData prevClientData)	/* If non-NULL, gives last value returned by
    Tcl_VarTraceProc *proc,	/* Function associated with trace. */
    void *prevClientData)	/* If non-NULL, gives last value returned by
				 * this function, so this call will return the
				 * next trace after that one. If NULL, this
				 * call will return the first trace. */
{
    Interp *iPtr = (Interp *) interp;
    Var *varPtr, *arrayPtr;
    Tcl_HashEntry *hPtr;

    varPtr = TclLookupVar(interp, part1, part2,
	    flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY), /*msg*/ NULL,
	    /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
    if (varPtr == NULL) {
	return NULL;
    }

    /*
     * Find the relevant trace, if any, and return its clientData.
     */

    hPtr = Tcl_FindHashEntry(&iPtr->varTraces, (char *) varPtr);
    hPtr = Tcl_FindHashEntry(&iPtr->varTraces, varPtr);

    if (hPtr) {
	VarTrace *tracePtr = (VarTrace *)Tcl_GetHashValue(hPtr);

	if (prevClientData != NULL) {
	    for (; tracePtr != NULL; tracePtr = tracePtr->nextPtr) {
		if ((tracePtr->clientData == prevClientData)
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
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







-
+




















-
+







 *	actions.
 *
 * Results:
 *	A standard Tcl return value.
 *
 * Side effects:
 *	A trace is set up on the variable given by part1 and part2, such that
 *	future references to the variable will be intermediated by proc. See
 *	future references to the variable will be mediated by proc. See
 *	the manual entry for complete details on the calling sequence for
 *	proc. The variable's flags are updated.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_TraceVar2(
    Tcl_Interp *interp,		/* Interpreter in which variable is to be
				 * traced. */
    const char *part1,		/* Name of scalar variable or array. */
    const char *part2,		/* Name of element within array; NULL means
				 * trace applies to scalar variable or array
				 * as-a-whole. */
    int flags,			/* OR-ed collection of bits, including any of
				 * TCL_TRACE_READS, TCL_TRACE_WRITES,
				 * TCL_TRACE_UNSETS, TCL_GLOBAL_ONLY, and
				 * TCL_NAMESPACE_ONLY. */
    Tcl_VarTraceProc *proc,	/* Function to call when specified ops are
				 * invoked upon varName. */
    ClientData clientData)	/* Arbitrary argument to pass to proc. */
    void *clientData)	/* Arbitrary argument to pass to proc. */
{
    VarTrace *tracePtr;
    int result;

    tracePtr = (VarTrace *)Tcl_Alloc(sizeof(VarTrace));
    tracePtr->traceProc = proc;
    tracePtr->clientData = clientData;
3089
3090
3091
3092
3093
3094
3095
3096

3097
3098
3099
3100
3101
3102
3103
3007
3008
3009
3010
3011
3012
3013

3014
3015
3016
3017
3018
3019
3020
3021







-
+







 *	actions.
 *
 * Results:
 *	A standard Tcl return value.
 *
 * Side effects:
 *	A trace is set up on the variable given by part1 and part2, such that
 *	future references to the variable will be intermediated by the
 *	future references to the variable will be mediated by the
 *	traceProc listed in tracePtr. See the manual entry for complete
 *	details on the calling sequence for proc.
 *
 *----------------------------------------------------------------------
 */

static int
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3065
3066
3067
3068
3069
3070
3071



3072
3073
3074
3075
3076
3077
3078







-
-
-








    /*
     * Set up trace information.
     */

    flagMask = TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS |
	  TCL_TRACE_ARRAY | TCL_TRACE_RESULT_DYNAMIC | TCL_TRACE_RESULT_OBJECT;
#ifndef TCL_REMOVE_OBSOLETE_TRACES
    flagMask |= TCL_TRACE_OLD_STYLE;
#endif
    tracePtr->flags = tracePtr->flags & flagMask;

    hPtr = Tcl_CreateHashEntry(&iPtr->varTraces, varPtr, &isNew);
    if (isNew) {
	tracePtr->nextPtr = NULL;
    } else {
	tracePtr->nextPtr = (VarTrace *)Tcl_GetHashValue(hPtr);

Changes to generic/tclUniData.c.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







/*
 * tclUniData.c --
 *
 *	Declarations of Unicode character information tables.  This file is
 *	automatically generated by the tools/uniParse.tcl script.  Do not
 *	modify this file by hand.
 *
 * Copyright (c) 1998 by Scriptics Corporation.
 * Copyright © 1998 Scriptics Corporation.
 * All rights reserved.
 */

/*
 * A 16-bit Unicode character is split into two parts in order to index
 * into the following tables.  The lower OFFSET_BITS comprise an offset
 * into a page of characters.  The upper bits comprise the page number.
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
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







-
-
-
-
-
-
+
+
+
+
+
+






-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








static const unsigned short pageMap[] = {
    0, 32, 64, 96, 0, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416,
    448, 224, 480, 512, 544, 576, 608, 640, 672, 704, 704, 736, 768, 800,
    832, 864, 896, 928, 960, 992, 224, 1024, 224, 1056, 224, 224, 1088,
    1120, 1152, 1184, 1216, 1248, 1280, 1312, 1344, 1376, 1408, 1344, 1344,
    1440, 1472, 1504, 1536, 1568, 1344, 1344, 1600, 1632, 1664, 1696, 1728,
    1760, 1792, 1824, 1856, 1888, 1920, 1952, 1984, 2016, 2048, 2080, 2112,
    2144, 2176, 2208, 2240, 2272, 2304, 2336, 2368, 2400, 2432, 2464, 2496,
    2528, 2560, 2592, 2624, 2656, 2688, 2720, 2752, 2784, 2816, 2848, 2880,
    2912, 2944, 2976, 3008, 3040, 3072, 3104, 3136, 3168, 3200, 3232, 3264,
    3296, 1824, 3328, 3360, 3392, 1824, 3424, 3456, 3488, 3520, 3552, 3584,
    3616, 1824, 1344, 3648, 3680, 3712, 3744, 3776, 3808, 3840, 1344, 1344,
    1760, 1792, 1824, 1344, 1856, 1888, 1920, 1952, 1984, 2016, 2048, 2080,
    2112, 2144, 2176, 2208, 2240, 2272, 2304, 2336, 2368, 2400, 2432, 2464,
    2496, 2528, 2560, 2592, 2624, 2656, 2688, 2720, 2752, 2784, 2816, 2848,
    2880, 2912, 2944, 2976, 3008, 3040, 3072, 3104, 3136, 3168, 3200, 3232,
    3264, 3296, 3328, 3360, 3392, 3296, 3424, 3456, 3488, 3520, 3552, 3584,
    3616, 3296, 1344, 3648, 3680, 3712, 3744, 3776, 3808, 3840, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 3872, 1344, 3904, 3936,
    3968, 1344, 4000, 1344, 4032, 4064, 4096, 4128, 4128, 4160, 4192, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 4224, 4256, 1344, 1344, 4288, 4320, 4352,
    4384, 4416, 1344, 4448, 4480, 4512, 4544, 1344, 4576, 4608, 4640, 4672,
    1344, 4704, 4736, 4768, 4800, 4832, 1344, 4864, 4896, 4928, 4960, 1344,
    4992, 5024, 5056, 5088, 5120, 1824, 5152, 5184, 5216, 5248, 5280, 5312,
    4992, 5024, 5056, 5088, 5120, 3296, 5152, 5184, 5216, 5248, 5280, 5312,
    1344, 5344, 1344, 5376, 5408, 5440, 5472, 5504, 5536, 5568, 5600, 5632,
    5664, 5696, 5728, 5664, 704, 5760, 224, 224, 224, 224, 5792, 224, 224,
    224, 5824, 5856, 5888, 5920, 5952, 5984, 6016, 6048, 6080, 6112, 6144,
    6176, 6208, 6240, 6272, 6304, 6336, 6368, 6400, 6432, 6464, 6496, 6528,
    6560, 6592, 6592, 6592, 6592, 6592, 6592, 6592, 6592, 6624, 6656, 4928,
    6688, 6720, 6752, 6784, 6816, 4928, 6848, 6880, 6912, 6944, 6976, 7008,
    7040, 4928, 4928, 4928, 4928, 4928, 7072, 7104, 7136, 4928, 4928, 4928,
    7168, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 7200, 7232, 4928, 7264,
    7296, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 6592, 6592, 6592,
    6592, 7328, 6592, 7360, 7392, 6592, 6592, 6592, 6592, 6592, 6592, 6592,
    6592, 4928, 7424, 7456, 7488, 7520, 4928, 4928, 4928, 7552, 7584, 7616,
    7648, 224, 224, 224, 7680, 7712, 7744, 1344, 7776, 7808, 7840, 7840,
    704, 7872, 7904, 7936, 1824, 7968, 4928, 4928, 8000, 4928, 4928, 4928,
    4928, 4928, 4928, 8032, 8064, 8096, 8128, 3232, 1344, 8160, 4192, 1344,
    8192, 8224, 8256, 1344, 1344, 8288, 1344, 4928, 8320, 8352, 8384, 8416,
    4928, 8384, 8448, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928,
    5664, 5696, 5728, 5664, 704, 704, 224, 224, 224, 224, 5760, 224, 224,
    224, 5792, 5824, 5856, 5888, 5920, 5952, 5984, 6016, 6048, 6080, 6112,
    6144, 6176, 6208, 6240, 6272, 6304, 6336, 6368, 6400, 6432, 6464, 6496,
    6528, 6560, 6560, 6560, 6560, 6560, 6560, 6560, 6560, 6592, 6624, 4928,
    6656, 6688, 6720, 6752, 6784, 4928, 6816, 6848, 6880, 6912, 6944, 6976,
    7008, 4928, 4928, 4928, 4928, 4928, 7040, 7072, 7104, 4928, 4928, 4928,
    7136, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 7168, 7200, 4928, 7232,
    7264, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 6560, 6560, 6560,
    6560, 7296, 6560, 7328, 7360, 6560, 6560, 6560, 6560, 6560, 6560, 6560,
    6560, 4928, 7392, 7424, 7456, 7488, 4928, 4928, 4928, 7520, 7552, 7584,
    7616, 224, 224, 224, 7648, 7680, 7712, 1344, 7744, 7776, 7808, 7808,
    704, 7840, 7872, 7904, 3296, 7936, 4928, 4928, 7968, 4928, 4928, 4928,
    4928, 4928, 4928, 8000, 8032, 8064, 8096, 3200, 1344, 8128, 4192, 1344,
    8160, 8192, 8224, 1344, 1344, 8256, 1344, 4928, 8288, 8320, 8352, 8384,
    4928, 8352, 8416, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928,
    4928, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
126
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141






142
143
144
145
146
147
148
126
127
128
129
130
131
132

133
134
135






136
137
138
139
140
141
142
143
144
145
146
147
148







-
+


-
-
-
-
-
-
+
+
+
+
+
+







    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    8480, 8512, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 8448, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 8544, 4928, 8576, 5440, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 8608, 8640, 224, 8672, 8704, 1344, 1344, 8736, 8768, 8800, 224,
    8832, 8864, 8896, 8928, 8960, 8992, 9024, 1344, 9056, 9088, 9120, 9152,
    9184, 1632, 9216, 9248, 8480, 1952, 9280, 9312, 9344, 1344, 9376, 9408,
    9440, 1344, 9472, 9504, 9536, 9568, 9600, 9632, 9664, 9696, 9696, 1344,
    9728, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 8480, 4928, 8512, 5440, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 8544, 8576, 224, 8608, 8640, 1344, 1344, 8672, 8704, 8736, 224,
    8768, 8800, 8832, 8864, 8896, 8928, 8960, 1344, 8992, 9024, 9056, 9088,
    9120, 1632, 9152, 9184, 9216, 1920, 9248, 9280, 9312, 1344, 9344, 9376,
    9408, 1344, 9440, 9472, 9504, 9536, 9568, 9600, 9632, 9664, 9664, 1344,
    9696, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570

571













































































































































































572
573
574
575
576
577
578







+
+
+
+
+
+
-
+




-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
-
-
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
+





+









-
-
+
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 9728, 9760, 9792, 9824, 9824, 9824, 9824, 9824, 9824, 9824,
    9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824,
    9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824,
    9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824,
    9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824,
    9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9824, 9856, 9856, 9856,
    1344, 1344, 9760, 9792, 9824, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9888, 9888, 9888,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888, 9888,
    9888, 9888, 9888, 9888, 9888, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 9920, 1344, 1344, 9952, 1824, 9984, 10016,
    10048, 1344, 1344, 10080, 10112, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 10144, 10176, 1344, 10208, 1344, 10240, 10272,
    10304, 10336, 10368, 10400, 1344, 1344, 1344, 10432, 10464, 64, 10496,
    10528, 10560, 4736, 10592, 10624
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856,
    9856, 9856, 9856, 9856, 9856, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 9888, 1344, 1344, 9920, 3296, 9952, 9984, 10016,
    1344, 1344, 10048, 10080, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 10112, 10144, 1344, 10176, 1344, 10208, 10240, 10272,
    10304, 10336, 10368, 1344, 1344, 1344, 10400, 10432, 64, 10464, 10496,
    10528, 4736, 10560, 10592
#if TCL_UTF_MAX > 3 || TCL_MAJOR_VERSION > 8 || TCL_MINOR_VERSION > 6
    ,10656, 10688, 10720, 1824, 1344, 1344, 1344, 10752, 10784, 10816,
    10848, 10880, 10912, 10944, 10976, 11008, 1824, 1824, 1824, 1824, 8480,
    1344, 11040, 11072, 1344, 11104, 11136, 11168, 11200, 1344, 11232,
    1824, 11264, 11296, 11328, 1344, 11360, 11392, 11424, 11456, 1344,
    11488, 1344, 11520, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 7808, 4704, 10240, 1824, 1824, 1824,
    1824, 11552, 11584, 11616, 11648, 4736, 11680, 1824, 11712, 11744,
    11776, 1824, 1824, 1344, 11808, 11840, 6912, 11872, 11904, 11936, 11968,
    12000, 1824, 12032, 12064, 1344, 12096, 12128, 12160, 12192, 12224,
    1824, 1824, 1344, 1344, 12256, 1824, 12288, 12320, 12352, 12384, 1344,
    ,10624, 10656, 10688, 3296, 1344, 1344, 1344, 10720, 10752, 10784,
    10816, 10848, 10880, 10912, 8032, 10944, 3296, 3296, 3296, 3296, 9216,
    1344, 10976, 11008, 1344, 11040, 11072, 11104, 11136, 1344, 11168,
    3296, 11200, 11232, 11264, 1344, 11296, 11328, 11360, 11392, 1344,
    11424, 1344, 11456, 11488, 11520, 1344, 11552, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 7776, 4704, 11584, 11616, 11648, 3296,
    3296, 11680, 11712, 11744, 11776, 4736, 11808, 3296, 11840, 11872,
    11904, 3296, 3296, 1344, 11936, 11968, 6880, 12000, 12032, 12064, 12096,
    12128, 3296, 12160, 12192, 1344, 12224, 12256, 12288, 12320, 12352,
    3296, 3296, 1344, 1344, 12384, 3296, 12416, 12448, 12480, 12512, 1344,
    12416, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 12448,
    1344, 12480, 1824, 1824, 12000, 12512, 12544, 1824, 1824, 10176, 12576,
    7808, 12608, 12640, 12672, 12704, 5280, 12736, 12768, 12800, 12832,
    12864, 12896, 12928, 5280, 12960, 12992, 13024, 13056, 13088, 1824,
    1824, 13120, 13152, 13184, 13216, 13248, 13280, 13312, 13344, 1824,
    12544, 12576, 12608, 12640, 3296, 3296, 3296, 3296, 3296, 3296, 12672,
    1344, 12704, 12736, 12768, 12128, 12800, 12832, 12864, 12896, 12864,
    12928, 7776, 12960, 12992, 13024, 13056, 5280, 13088, 13120, 13152,
    13184, 13216, 13248, 13280, 5280, 13312, 13344, 13376, 13408, 13440,
    1824, 1824, 1824, 1344, 13376, 13408, 13440, 1344, 13472, 13504, 1824,
    1824, 1824, 1824, 1824, 1344, 13536, 13568, 1824, 1344, 13600, 13632,
    13472, 3296, 13504, 13536, 13568, 13600, 13632, 13664, 13696, 13728,
    13664, 1344, 13696, 13728, 1824, 4032, 13760, 1824, 1824, 1824, 1824,
    1824, 1824, 1344, 13792, 1824, 1824, 1824, 13824, 13856, 13888, 13920,
    13952, 13984, 1824, 1824, 14016, 14048, 14080, 14112, 14144, 14176,
    1344, 14208, 14240, 1344, 4608, 1824, 1824, 1824, 1824, 1824, 1824,
    13760, 13792, 13824, 13856, 1344, 13888, 13920, 13952, 1344, 13984,
    14016, 3296, 3296, 3296, 3296, 3296, 1344, 14048, 14080, 3296, 1344,
    14112, 14144, 14176, 1344, 14208, 14240, 14272, 14304, 14336, 14368,
    1824, 1824, 14272, 14304, 14336, 14368, 14400, 14432, 1824, 1824, 14464,
    14496, 14528, 14560, 14592, 13728, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 14624, 1824, 1824, 1824, 1824, 1824, 14656, 14688,
    14720, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    3296, 3296, 3296, 3296, 3296, 1344, 14400, 3296, 3296, 3296, 14432,
    14464, 14496, 14528, 14560, 14592, 3296, 3296, 14624, 14656, 14688,
    14720, 14752, 14784, 1344, 14816, 14848, 1344, 4608, 14880, 3296, 3296,
    3296, 3296, 3296, 1344, 14912, 14944, 14976, 15008, 15040, 15072, 15104,
    3296, 3296, 15136, 15168, 15200, 15232, 15264, 15296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 15328, 15360, 15392, 15424, 3296,
    3296, 15456, 15488, 15520, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 9952, 1824, 1824, 1824, 10848,
    10848, 10848, 14752, 1344, 1344, 1344, 1344, 1344, 1344, 14784, 1824,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 9920, 3296, 3296,
    3296, 10816, 10816, 10816, 15552, 1344, 1344, 1344, 1344, 1344, 1344,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    15584, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 12864,
    1344, 1344, 15616, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 15648, 15680, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 14816, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 14848,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 10720, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 14368, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 15712, 15744, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 4608, 4736,
    14880, 1824, 1824, 10176, 14912, 1344, 14944, 14976, 15008, 15040,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 4608, 4736, 15776, 1344, 4736, 15808,
    15840, 1344, 15872, 15904, 15936, 15968, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 16000, 16032, 3296,
    3296, 3296, 3296, 3296, 3296, 14432, 14464, 16064, 3296, 3296, 3296,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 13824, 13856,
    15072, 1824, 1824, 1824, 1344, 1344, 15104, 15136, 15168, 1824, 1824,
    15200, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 16096, 16128, 16160, 3296, 3296, 16192, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 15232, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 16224, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 4704, 1824, 12256, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 4736, 1824, 15264,
    15296, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 9824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    4704, 16256, 12384, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 16288, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 16320, 16352, 16384, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 9792, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1344, 1344, 1344, 15328, 15360, 15392, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 1344, 1344, 1344,
    16416, 16448, 16480, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 4928, 4928, 4928, 4928, 4928, 4928,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 4928, 4928, 4928, 4928, 4928,
    4928, 4928, 8032, 4928, 15424, 4928, 15456, 15488, 15520, 4928, 15552,
    4928, 4928, 15584, 1824, 1824, 1824, 1824, 15616, 4928, 4928, 15648,
    15680, 1824, 1824, 1824, 1824, 15712, 15744, 15776, 15808, 15840, 15872,
    15904, 15936, 15968, 16000, 16032, 16064, 16096, 15712, 15744, 16128,
    15808, 16160, 16192, 16224, 15936, 16256, 16288, 16320, 16352, 16384,
    16416, 16448, 16480, 16512, 16544, 16576, 4928, 4928, 4928, 4928, 4928,
    4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 704,
    16608, 704, 16640, 16672, 16704, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    16736, 16768, 1824, 1824, 1824, 1824, 1824, 1824, 1344, 16800, 16832,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1344,
    16864, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344, 1344,
    4928, 16512, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928,
    4928, 4928, 4928, 4928, 7968, 3296, 3296, 704, 16544, 16576, 4928,
    4928, 4928, 16608, 3296, 4928, 4928, 4928, 4928, 4928, 4928, 4928,
    8000, 4928, 16640, 4928, 16672, 16704, 16736, 4928, 6848, 4928, 4928,
    16768, 3296, 3296, 3296, 16800, 16800, 4928, 4928, 16832, 16864, 3296,
    3296, 3296, 3296, 16896, 16928, 16960, 16992, 17024, 17056, 17088,
    17120, 17152, 17184, 17216, 17248, 17280, 16896, 16928, 17312, 16992,
    17344, 17376, 17408, 17120, 17440, 17472, 17504, 17536, 17568, 17600,
    17632, 17664, 17696, 17728, 17760, 4928, 4928, 4928, 4928, 4928, 4928,
    4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 704, 17792,
    704, 17824, 17856, 17888, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 17920, 17952, 3296, 3296, 3296, 3296, 3296, 3296,
    17984, 18016, 5664, 18048, 18080, 3296, 3296, 3296, 1344, 18112, 18144,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 12864, 18176,
    1344, 18208, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 12864, 18240, 3296, 3296, 3296, 3296,
    3296, 3296, 12864, 18272, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 18304, 1344, 1344,
    1344, 1344, 1344, 1344, 18336, 3296, 18368, 18400, 18432, 3296, 3296,
    16896, 1824, 16928, 16960, 16992, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 17024, 6912, 17056, 1824, 1824,
    17088, 17120, 1824, 1824, 1824, 1824, 1824, 1824, 17152, 17184, 17216,
    17248, 17280, 17312, 1824, 17344, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 4928, 17376, 4928, 4928, 8000, 17408, 17440, 8032, 17472,
    4928, 4928, 4928, 4928, 17504, 1824, 17536, 17568, 17600, 17632, 17664,
    1824, 1824, 1824, 1824, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 17696,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 18464,
    6880, 18496, 3296, 3296, 18528, 18560, 3296, 3296, 3296, 3296, 3296,
    3296, 18592, 18624, 18656, 18688, 18720, 18752, 3296, 18784, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 4928, 18816, 4928, 4928,
    7968, 18848, 18880, 8000, 18912, 4928, 4928, 4928, 4928, 18944, 3296,
    18976, 19008, 19040, 19072, 19104, 3296, 3296, 3296, 3296, 4928, 4928,
    4928, 4928, 4928, 4928, 4928, 19136, 4928, 4928, 4928, 4928, 4928,
    4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928,
    4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 17728,
    17760, 4928, 4928, 4928, 8000, 4928, 4928, 17792, 17824, 17376, 4928,
    17856, 4928, 17888, 17920, 1824, 1824, 4928, 4928, 4928, 17952, 4928,
    4928, 4928, 4928, 4928, 4928, 19168, 19200, 4928, 4928, 4928, 19232,
    4928, 4928, 19264, 19296, 18816, 4928, 19328, 4928, 19360, 19392, 19424,
    3296, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 7968,
    4928, 17984, 4928, 4928, 4928, 8000, 18016, 18048, 18080, 18112, 1824,
    4928, 4928, 4928, 4928, 18144, 4928, 6880, 18176, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    19456, 19488, 4928, 19520, 19552, 4928, 4928, 4928, 4928, 19584, 4928,
    4928, 16512, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 3296, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    9920, 1344, 1344, 1344, 1344, 1344, 1344, 11296, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 19616, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 19648, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    11296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 11296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1792, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 15968
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 11360, 1824, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 18208, 1344, 1344, 1344,
    1344, 1344, 1344, 11360, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 18240, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    18272, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 11360, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1792
#endif /* TCL_UTF_MAX > 3 */
};

/*
 * The groupMap is indexed by combining the alternate page number with
 * the page offset and returns a group number that identifies a unique
 * set of character attributes.
584
585
586
587
588
589
590
591
592
593
594




595
596

597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624



























625
626

627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648





















649
650
651
652
653




654
655
656


657
658

659
660
661


662
663

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
707
708
709
710





711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726















727
728
729
730











731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746




























747
748
749
750
751
752
753
754



755
756
757
758
759
760
761
762
763



764
765
766
767
768
769
770
771
772
773
774


775
776
777
778



779
780
781
782
783
784
785
786
787
788

789
790
791
792

793
794
795
796
797
798
799
800
801

802
803

804
805
806
807







808
809
810
811
812
813
814
815
816
817
818
819
820



















821
822
823
824
825
826
827
828

















829
830







831
832

833
834
835


836
837
838
839

840
841
842
843


844
845
846
847
848
849
850
851
852







853
854
855
856
857




858
859
860




861
862
863
864
865
866




867
868
869
870
871
872
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
898
899
900
901
902








903
904

905
906
907
908


909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944













































945
946

947
948

949
950














951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122








1123
1124

1125
1126
1127
1128
1129
1130
1131
1132






1133
1134
1135
1136
1137
1138
1139





1140
1141
1142


1143
1144
1145
1146

1147
1148



1149

1150
1151
1152



1153
1154
1155
1156
1157
1158







1159
1160
1161
1162
1163
1164
1165






1166
1167
1168
1169
1170




1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187





1188
1189
1190
1191

1192
1193
1194
1195
1196
1197
1198
1199
1200
1201







1202
1203
1204
1205
1206
1207
1208
1209
1210










1211
1212
1213

1214
1215
1216
1217
1218
1219







1220
1221
1222

1223
1224
1225

1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387


1388
1389
1390


1391
1392
1393
1394
1395
1396
1397







1398
1399
1400
1401
1402




1403
1404
1405
1406
1407
1408
1409
1410






1411
1412
1413
1414
1415










1416
1417
1418
1419


1420
1421
1422
1423

1424
1425
1426
1427
1428
1429





1430

1431
1432
1433
1434
1435
1436
1437








1438
1439
1440
1441
1442
1443
1444
1445
1446
1447





















































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

1478
1479
1480
1481






1482
1483


1484
1485
1486




1487
1488







1489
1490

1491
1492
1493
1494




1495
1496
1497



1498
1499
1500
1501




1502
1503
1504












1505
1506
1507
1508
1509
1510
1511
1512

1513
1514





1515
1516
1517
1518
1519
1520
1521
1522
1523
1524















1525
1526
1527
1528
1529
1530
1531







1532
1533
1534
1535
1536
1537
1538
596
597
598
599
600
601
602




603
604
605
606
607

608
609



























610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637

638
639





















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




662
663
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
707
708
709
710
711
712
713
714
715
716










717
718
719
720
721
722















723
724
725
726
727
728
729
730
731
732
733
734
735
736
737




738
739
740
741
742
743
744
745
746
747
748
749















750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778




779


780
781
782









783
784
785











786
787




788
789
790










791




792









793


794
795
796


797
798
799
800
801
802
803
804












805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823

824






825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851

852



853
854
855



856




857
858









859
860
861
862
863
864
865





866
867
868
869



870
871
872
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
898
899
900







901
902
903
904
905
906
907








908
909
910
911
912
913
914
915


916




917
918




































919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125








1126
1127
1128
1129
1130
1131
1132
1133
1134

1135
1136
1137






1138
1139
1140
1141
1142
1143
1144
1145





1146
1147
1148
1149
1150
1151


1152
1153




1154
1155

1156
1157
1158
1159
1160



1161
1162
1163






1164
1165
1166
1167
1168
1169
1170
1171






1172
1173
1174
1175
1176
1177
1178




1179
1180
1181
1182

1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193





1194
1195
1196
1197
1198
1199
1200
1201

1202

1203








1204
1205
1206
1207
1208
1209
1210
1211








1212
1213
1214
1215
1216
1217
1218
1219
1220
1221



1222
1223





1224
1225
1226
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




1354
1355
1356
1357
1358


1359











1360
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
1387
1388

1389

1390


1391






1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402


1403
1404



1405
1406
1407






1408
1409
1410
1411
1412
1413
1414





1415
1416
1417
1418
1419







1420
1421
1422
1423
1424
1425





1426
1427
1428
1429
1430
1431
1432
1433
1434
1435




1436
1437




1438






1439
1440
1441
1442
1443
1444
1445







1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511



1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527



1528
1529
1530







1531



1532
1533


1534
1535

1536



1537
1538
1539
1540
1541



1542
1543
1544


1545
1546
1547
1548




1549
1550
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







-
-
-
-
+
+
+
+

-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
+
+

-
+

-
-
+
+

-
+



-
-
-
-
+
+
+
+


-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+


-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-

-
-
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-
-
+


-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-

-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+

-
+
-
-
-
+
+

-
-
-
+
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
+


-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-


-
-
+
+
-
-
+
-
-
-
+
+
-
-
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
+

-
-
-
-
+
+
+
+
-
-

-
+




-
+


-
-
+
+

-
-
+
+

-
-
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
+


-
-
-
-
-
-
+
+
+
+
+
+


-
-
-
-
-
+
+
+
+
+

-
-
+
+
-
-
-
-
+

-
+
+
+

+
-
-
-
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
+
+
+
+
-











-
-
-
-
-
+
+
+
+
+



-
+
-

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
+

-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
-
-
-
+
-
-
-
-
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
-
-
-
-
-
+
+
+
+
-
-
-
-
+
-
-
-
-
-
-
-
+
+
+
+
-
-
+
-
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+
+

+
-
-
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
-

+
-
+
-
-
-
-
+
+
-
-
-
+
-
-
-
-
-
-
-
+
+
+
-
-
-
-
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
-
-
-
-
+
+
+
-

-
+
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
+
+
-
-
-
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
-
-
-
-
+
-
-
-
-
-
-
+
+
+
+
+

+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
+
-
-
-
+
+
-
-

+
-
+
-
-
-
+
+
+
+
+
-
-
-
+
+
+
-
-
+
+

+
-
-
-
-
+
+
+
+
+
+
-
-
+
+

-
-
+
+
+
+
-
-
+
+
+
+
+
+
+

-
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+







    23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 25, 26, 23, 24, 23,
    24, 23, 24, 21, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 21, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 27,
    23, 24, 23, 24, 23, 24, 28, 29, 30, 23, 24, 23, 24, 31, 23, 24, 32,
    32, 23, 24, 21, 33, 34, 35, 23, 24, 32, 36, 37, 38, 39, 23, 24, 40,
    21, 38, 41, 42, 43, 23, 24, 23, 24, 23, 24, 44, 23, 24, 44, 21, 21,
    23, 24, 44, 23, 24, 45, 45, 23, 24, 23, 24, 46, 23, 24, 21, 15, 23,
    24, 21, 47, 15, 15, 15, 15, 48, 49, 50, 48, 49, 50, 48, 49, 50, 23,
    24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 51, 23,
    41, 38, 42, 43, 44, 23, 24, 23, 24, 23, 24, 45, 23, 24, 45, 21, 21,
    23, 24, 45, 23, 24, 46, 46, 23, 24, 23, 24, 47, 23, 24, 21, 15, 23,
    24, 21, 48, 15, 15, 15, 15, 49, 50, 51, 49, 50, 51, 49, 50, 51, 23,
    24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 52, 23,
    24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    21, 48, 49, 50, 23, 24, 52, 53, 23, 24, 23, 24, 23, 24, 23, 24, 54,
    21, 49, 50, 51, 23, 24, 53, 54, 23, 24, 23, 24, 23, 24, 23, 24, 55,
    21, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    23, 24, 21, 21, 21, 21, 21, 21, 55, 23, 24, 56, 57, 58, 58, 23, 24,
    59, 60, 61, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 62, 63, 64, 65,
    66, 21, 67, 67, 21, 68, 21, 69, 70, 21, 21, 21, 67, 71, 21, 72, 21,
    73, 74, 21, 75, 76, 74, 77, 78, 21, 21, 76, 21, 79, 80, 21, 21, 81,
    21, 21, 21, 21, 21, 21, 21, 82, 21, 21, 83, 21, 84, 83, 21, 21, 21,
    85, 83, 86, 87, 87, 88, 21, 21, 21, 21, 21, 89, 21, 15, 21, 21, 21,
    21, 21, 21, 21, 21, 90, 91, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 11, 11, 11, 11, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
    11, 11, 11, 11, 92, 92, 92, 92, 92, 11, 11, 11, 11, 11, 11, 11, 92,
    11, 92, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
    11, 11, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 94, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 23, 24, 23,
    24, 92, 11, 23, 24, 0, 0, 92, 42, 42, 42, 3, 95, 0, 0, 0, 0, 11, 11,
    96, 3, 97, 97, 97, 0, 98, 0, 99, 99, 21, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 100, 101, 101, 101, 21, 13, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 13, 13, 13, 102, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 103, 104, 104, 105, 106, 107, 108, 108, 108, 109, 110, 111,
    23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 23, 24, 112, 113, 114, 115, 116, 117, 7, 23, 24,
    118, 23, 24, 21, 54, 54, 54, 119, 119, 119, 119, 119, 119, 119, 119,
    119, 119, 119, 119, 119, 119, 119, 119, 10, 10, 10, 10, 10, 10, 10,
    23, 24, 21, 21, 21, 21, 21, 21, 56, 23, 24, 57, 58, 59, 59, 23, 24,
    60, 61, 62, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 63, 64, 65, 66,
    67, 21, 68, 68, 21, 69, 21, 70, 71, 21, 21, 21, 68, 72, 21, 73, 74,
    75, 76, 21, 77, 78, 76, 79, 80, 21, 21, 78, 21, 81, 82, 21, 21, 83,
    21, 21, 21, 21, 21, 21, 21, 84, 21, 21, 85, 21, 86, 85, 21, 21, 21,
    87, 85, 88, 89, 89, 90, 21, 21, 21, 21, 21, 91, 21, 15, 21, 21, 21,
    21, 21, 21, 21, 21, 92, 93, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
    94, 94, 94, 94, 94, 94, 94, 94, 11, 11, 11, 11, 94, 94, 94, 94, 94,
    94, 94, 94, 94, 94, 94, 94, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
    11, 11, 11, 11, 94, 94, 94, 94, 94, 11, 11, 11, 11, 11, 11, 11, 94,
    11, 94, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
    11, 11, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 96, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 23, 24, 23,
    24, 94, 11, 23, 24, 0, 0, 94, 43, 43, 43, 3, 97, 0, 0, 0, 0, 11, 11,
    98, 3, 99, 99, 99, 0, 100, 0, 101, 101, 21, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 102, 103, 103, 103, 21, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 104, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 105, 106, 106, 107, 108, 109, 110, 110, 110, 111, 112,
    113, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    23, 24, 23, 24, 23, 24, 23, 24, 114, 115, 116, 117, 118, 119, 7, 23,
    24, 120, 23, 24, 21, 55, 55, 55, 121, 121, 121, 121, 121, 121, 121,
    121, 121, 121, 121, 121, 121, 121, 121, 121, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 113, 113, 113, 113, 113, 113, 113, 113, 113,
    113, 113, 113, 113, 113, 113, 113, 23, 24, 14, 93, 93, 93, 93, 93,
    120, 120, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 23, 24, 121, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 122, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    23, 24, 23, 24, 0, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
    123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
    123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
    0, 0, 92, 3, 3, 3, 3, 3, 3, 21, 124, 124, 124, 124, 124, 124, 124,
    124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
    124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
    124, 124, 124, 21, 21, 3, 8, 0, 0, 14, 14, 4, 0, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 8, 93, 3, 93, 93, 3, 93, 93, 3, 93, 0, 0, 0,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0,
    15, 15, 15, 15, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17,
    17, 17, 17, 7, 7, 7, 3, 3, 4, 3, 3, 14, 14, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 3, 17, 0, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15,
    13, 13, 13, 13, 13, 13, 13, 115, 115, 115, 115, 115, 115, 115, 115,
    115, 115, 115, 115, 115, 115, 115, 115, 23, 24, 14, 95, 95, 95, 95,
    95, 122, 122, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    23, 24, 23, 24, 23, 24, 23, 24, 123, 23, 24, 23, 24, 23, 24, 23, 24,
    23, 24, 23, 24, 23, 24, 124, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 0, 125, 125, 125, 125, 125, 125, 125, 125, 125,
    125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
    125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
    125, 0, 0, 94, 3, 3, 3, 3, 3, 3, 21, 126, 126, 126, 126, 126, 126,
    126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
    126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
    126, 126, 126, 126, 21, 21, 3, 8, 0, 0, 14, 14, 4, 0, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 95, 95, 8, 95, 3, 95, 95, 3, 95, 95, 3, 95, 0,
    0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0,
    0, 15, 15, 15, 15, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17,
    17, 17, 17, 7, 7, 7, 3, 3, 4, 3, 3, 14, 14, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 3, 17, 3, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 15, 15,
    93, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 94, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 15, 15,
    95, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 3, 15, 93, 93, 93, 93, 93, 93, 93, 17, 14, 93, 93, 93, 93,
    93, 93, 92, 92, 93, 93, 14, 93, 93, 93, 93, 15, 15, 9, 9, 9, 9, 9,
    15, 15, 3, 15, 95, 95, 95, 95, 95, 95, 95, 17, 14, 95, 95, 95, 95,
    95, 95, 94, 94, 95, 95, 14, 95, 95, 95, 95, 15, 15, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 9, 15, 15, 15, 14, 14, 15, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    3, 3, 3, 3, 0, 17, 15, 93, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    3, 3, 3, 3, 0, 17, 15, 95, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, 0, 15, 15, 15,
    15, 15, 15, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 0, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 15,
    15, 15, 15, 15, 15, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 15,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 92, 92, 14, 3, 3, 3, 92, 0, 0,
    93, 4, 4, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 93, 93, 93, 93, 92, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 92, 93, 93, 93, 92, 93, 93, 93, 93, 93, 0, 0, 3, 3,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 94, 14, 3, 3, 3, 94, 0, 0,
    95, 4, 4, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 95, 95, 95, 95, 94, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 94, 95, 95, 95, 94, 95, 95, 95, 95, 95, 0, 0, 3, 3,
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 93, 93, 93, 0, 0, 3, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 95, 95, 95, 0, 0, 3, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 17, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    15, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 11, 15, 15, 15, 15,
    15, 15, 0, 17, 17, 0, 0, 0, 0, 0, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 94, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    17, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 127,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 125, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 93, 125, 93, 15, 125, 125, 125, 93, 93, 93, 93,
    15, 15, 15, 95, 127, 95, 15, 127, 127, 127, 95, 95, 95, 95, 95, 95,
    93, 93, 93, 93, 125, 125, 125, 125, 93, 125, 125, 15, 93, 93, 93, 93,
    93, 93, 93, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 3, 3, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 93, 125, 125, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15,
    15, 15, 0, 15, 0, 0, 0, 15, 15, 15, 15, 0, 0, 93, 15, 125, 125, 125,
    93, 93, 93, 93, 0, 0, 125, 125, 0, 0, 125, 125, 93, 15, 0, 0, 0, 0,
    0, 0, 0, 0, 125, 0, 0, 0, 0, 15, 15, 0, 15, 15, 15, 93, 93, 0, 0, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 4, 4, 18, 18, 18, 18, 18, 18, 14,
    4, 15, 3, 93, 0, 0, 93, 93, 125, 0, 15, 15, 15, 15, 15, 15, 0, 0, 0,
    0, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15,
    0, 15, 15, 0, 15, 15, 0, 15, 15, 0, 0, 93, 0, 125, 125, 125, 93, 93,
    0, 0, 0, 0, 93, 93, 0, 0, 93, 93, 93, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0,
    95, 95, 127, 127, 127, 127, 95, 127, 127, 15, 95, 95, 95, 95, 95, 95,
    95, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 95, 95, 3, 3, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 3, 94, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 95, 127, 127, 0, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15,
    15, 0, 15, 0, 0, 0, 15, 15, 15, 15, 0, 0, 95, 15, 127, 127, 127, 95,
    95, 95, 95, 0, 0, 127, 127, 0, 0, 127, 127, 95, 15, 0, 0, 0, 0, 0,
    0, 0, 0, 127, 0, 0, 0, 0, 15, 15, 0, 15, 15, 15, 95, 95, 0, 0, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 4, 4, 18, 18, 18, 18, 18, 18, 14, 4,
    15, 3, 95, 0, 0, 95, 95, 127, 0, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0,
    15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15,
    15, 0, 15, 15, 0, 15, 15, 0, 0, 95, 0, 127, 127, 127, 95, 95, 0, 0,
    0, 0, 95, 95, 0, 0, 95, 95, 95, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 0, 15, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 95, 95, 15, 15, 15, 95, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 95,
    127, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 0, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15,
    0, 15, 15, 15, 15, 0, 15, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 93, 93, 15, 15, 15, 93, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93,
    93, 125, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15,
    15, 15, 15, 0, 0, 93, 15, 125, 125, 125, 93, 93, 93, 93, 93, 0, 93,
    93, 125, 0, 125, 125, 93, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 15, 15, 93, 93, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3,
    4, 0, 0, 0, 0, 0, 0, 0, 15, 93, 93, 93, 93, 93, 93, 0, 93, 125, 125,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 0, 0, 15, 15, 15,
    15, 15, 0, 0, 95, 15, 127, 127, 127, 95, 95, 95, 95, 95, 0, 95, 95,
    127, 0, 127, 127, 95, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 15, 15, 95, 95, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 4,
    0, 0, 0, 0, 0, 0, 0, 15, 95, 95, 95, 95, 95, 95, 0, 95, 127, 127, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15,
    15, 0, 0, 93, 15, 125, 93, 125, 93, 93, 93, 93, 0, 0, 125, 125, 0,
    0, 125, 125, 93, 0, 0, 0, 0, 0, 0, 0, 93, 93, 125, 0, 0, 0, 0, 15,
    15, 0, 15, 15, 15, 93, 93, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14,
    15, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 15, 0,
    15, 15, 15, 15, 15, 15, 0, 0, 0, 15, 15, 15, 0, 15, 15, 15, 15, 0,
    0, 0, 15, 15, 0, 15, 0, 15, 15, 0, 0, 0, 15, 15, 0, 0, 0, 15, 15, 15,
    0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0,
    125, 125, 93, 125, 125, 0, 0, 0, 125, 125, 125, 0, 125, 125, 125, 93,
    0, 0, 15, 0, 0, 0, 0, 0, 0, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 14, 14, 14, 14, 14,
    14, 4, 14, 0, 0, 0, 0, 0, 93, 125, 125, 125, 93, 15, 15, 15, 15, 15,
    15, 15, 15, 0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 15, 93,
    15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15,
    0, 0, 95, 15, 127, 95, 127, 95, 95, 95, 95, 0, 0, 127, 127, 0, 0, 127,
    127, 95, 0, 0, 0, 0, 0, 0, 0, 95, 95, 127, 0, 0, 0, 0, 15, 15, 0, 15,
    15, 15, 95, 95, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 15, 18, 18,
    18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 15, 0, 15, 15, 15,
    15, 15, 15, 0, 0, 0, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0, 0, 15, 15,
    0, 15, 0, 15, 15, 0, 0, 0, 15, 15, 0, 0, 0, 15, 15, 15, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 127, 127, 95,
    127, 127, 0, 0, 0, 127, 127, 127, 0, 127, 127, 127, 95, 0, 0, 15, 0,
    0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 14, 14, 14, 14, 14, 14, 4, 14,
    0, 0, 0, 0, 0, 95, 127, 127, 127, 95, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 95, 15, 95, 95, 95, 127,
    93, 93, 125, 125, 125, 125, 0, 93, 93, 93, 0, 93, 93, 93, 93, 0, 0,
    0, 0, 0, 0, 0, 93, 93, 0, 15, 15, 15, 0, 0, 0, 0, 0, 15, 15, 93, 93,
    0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 3, 18, 18,
    18, 18, 18, 18, 18, 14, 15, 93, 125, 125, 3, 15, 15, 15, 15, 15, 15,
    127, 127, 127, 0, 95, 95, 95, 0, 95, 95, 95, 95, 0, 0, 0, 0, 0, 0,
    0, 95, 95, 0, 15, 15, 15, 0, 0, 15, 0, 0, 15, 15, 95, 95, 0, 0, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 3, 18, 18, 18, 18,
    18, 18, 18, 14, 15, 95, 127, 127, 3, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 0, 0, 95, 15, 127, 95, 127,
    127, 127, 127, 127, 0, 95, 127, 127, 0, 127, 127, 95, 95, 0, 0, 0,
    0, 0, 0, 0, 127, 127, 0, 0, 0, 0, 0, 0, 15, 15, 0, 15, 15, 95, 95,
    0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 15, 15, 127, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 95, 95, 127, 127, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 0, 0, 93, 15, 125, 93,
    125, 125, 125, 125, 125, 0, 93, 125, 125, 0, 125, 125, 93, 93, 0, 0,
    0, 0, 0, 0, 0, 125, 125, 0, 0, 0, 0, 0, 0, 0, 15, 0, 15, 15, 93, 93,
    0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 15, 15, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 93, 93, 125, 125, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 15, 125, 125,
    125, 93, 93, 93, 93, 0, 125, 125, 125, 0, 125, 125, 125, 93, 15, 14,
    0, 0, 0, 0, 15, 15, 15, 125, 18, 18, 18, 18, 18, 18, 18, 15, 15, 15,
    93, 93, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 14, 15, 15, 15, 15, 15, 15, 0, 93, 125, 125, 0, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 95, 95, 15, 127,
    127, 127, 95, 95, 95, 95, 0, 127, 127, 127, 0, 127, 127, 127, 95, 15,
    14, 0, 0, 0, 0, 15, 15, 15, 127, 18, 18, 18, 18, 18, 18, 18, 15, 15,
    15, 95, 95, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 14, 15, 15, 15, 15, 15, 15, 0, 95, 127, 127, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 0, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 95, 0, 0,
    0, 0, 127, 127, 127, 95, 95, 95, 0, 95, 0, 127, 127, 127, 127, 127,
    127, 127, 127, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0,
    127, 127, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 95, 15, 15, 95, 95, 95, 95, 95,
    95, 95, 0, 0, 0, 0, 4, 15, 15, 15, 15, 15, 15, 94, 95, 95, 95, 95,
    95, 95, 95, 95, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 0, 15, 0, 15, 15, 15, 15, 15,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 95, 15, 15, 95, 95, 95, 95, 95, 95, 95, 95, 95, 15, 0,
    0, 15, 15, 15, 15, 15, 0, 94, 0, 95, 95, 95, 95, 95, 95, 95, 0, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 15, 15, 15, 15, 15, 14, 14, 14, 3,
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 14, 3, 14, 14, 14, 95, 95,
    14, 14, 14, 14, 14, 14, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 14, 95, 14, 95, 14, 95, 5, 6, 5, 6, 127, 127,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 93, 0, 0, 0,
    0, 125, 125, 125, 93, 93, 93, 0, 93, 0, 125, 125, 125, 125, 125, 125,
    125, 125, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 125,
    125, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 93, 15, 15, 93, 93, 93, 93, 93, 93,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 95, 95, 95,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 127, 95, 95, 95, 95, 95,
    3, 95, 95, 15, 15, 15, 15, 15, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    93, 0, 0, 0, 0, 4, 15, 15, 15, 15, 15, 15, 92, 93, 93, 93, 93, 93,
    93, 93, 93, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 0, 0, 0, 0, 0, 15,
    15, 0, 15, 0, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 15, 15, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 15, 0, 0, 15, 15, 15, 15, 15, 0, 92, 0,
    93, 93, 93, 93, 93, 93, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 15,
    15, 15, 15, 15, 14, 14, 14, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    3, 3, 14, 3, 14, 14, 14, 93, 93, 14, 14, 14, 14, 14, 14, 9, 9, 9, 9,
    95, 95, 0, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 0, 14, 14, 14, 14, 14, 14, 14, 14, 95, 14, 14,
    9, 9, 9, 9, 9, 9, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 93, 14,
    93, 14, 93, 5, 6, 5, 6, 125, 125, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 0, 0, 0, 0, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 125, 93, 93, 93, 93, 93, 3, 93, 93, 15, 15, 15, 15, 15, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, 14, 14, 14,
    14, 14, 14, 14, 14, 93, 14, 14, 14, 14, 14, 14, 0, 14, 14, 3, 3, 3,
    3, 3, 14, 14, 14, 14, 3, 3, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15,
    14, 14, 14, 14, 0, 14, 14, 3, 3, 3, 3, 3, 14, 14, 14, 14, 3, 3, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 127, 127, 95,
    15, 15, 15, 15, 15, 125, 125, 93, 93, 93, 93, 125, 93, 93, 93, 93,
    93, 93, 125, 93, 93, 125, 125, 93, 93, 15, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 3, 3, 3, 3, 3, 3, 15, 15, 15, 15, 15, 15, 125, 125, 93, 93, 15,
    15, 15, 15, 93, 93, 93, 15, 125, 125, 125, 15, 15, 125, 125, 125, 125,
    95, 95, 95, 127, 95, 95, 95, 95, 95, 95, 127, 95, 95, 127, 127, 95,
    95, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 3, 3, 15, 15, 15,
    15, 15, 15, 127, 127, 95, 95, 15, 15, 15, 15, 95, 95, 95, 15, 127,
    125, 125, 125, 15, 15, 15, 93, 93, 93, 93, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 93, 125, 125, 93, 93, 125, 125, 125, 125,
    125, 125, 93, 15, 125, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 125, 125, 125,
    93, 14, 14, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
    126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
    126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 0,
    126, 0, 0, 0, 0, 0, 126, 0, 0, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 127, 127, 127, 127, 127, 127, 3, 92, 127, 127, 127, 15, 15, 15,
    127, 127, 15, 15, 127, 127, 127, 127, 127, 127, 127, 15, 15, 15, 95,
    15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15,
    15, 15, 0, 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    95, 95, 95, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 95,
    15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 0, 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 93, 93, 93, 3, 3, 3, 3, 3, 3,
    3, 3, 3, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    127, 127, 95, 95, 127, 127, 127, 127, 127, 127, 95, 15, 127, 9, 9,
    15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0,
    0, 0, 0, 0, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
    9, 9, 9, 9, 9, 9, 9, 9, 127, 127, 127, 95, 14, 14, 128, 128, 128, 128,
    128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
    128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
    128, 128, 128, 128, 128, 128, 128, 128, 128, 105, 105, 105, 105, 105,
    105, 0, 0, 111, 111, 111, 111, 111, 111, 0, 0, 8, 15, 15, 15, 15, 15,
    128, 128, 128, 128, 128, 128, 0, 128, 0, 0, 0, 0, 0, 128, 0, 0, 129,
    129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
    129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
    129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
    3, 94, 129, 129, 129, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15,
    15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 15, 15, 15, 15,
    0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 14, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    5, 6, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 3, 3,
    129, 129, 129, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15,
    15, 93, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 93, 3,
    3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 15, 15,
    15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 95, 95, 95, 3, 3, 3, 3, 3, 3, 3, 3, 3, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 130, 130, 130, 130,
    130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
    130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
    130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
    130, 130, 107, 107, 107, 107, 107, 107, 0, 0, 113, 113, 113, 113, 113,
    113, 0, 0, 8, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 3, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 15,
    15, 15, 0, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    93, 93, 125, 93, 93, 93, 93, 93, 93, 93, 125, 125, 125, 125, 125, 125,
    125, 125, 93, 125, 125, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    3, 3, 3, 92, 3, 3, 3, 4, 15, 93, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0,
    0, 0, 0, 3, 3, 3, 3, 3, 3, 8, 3, 3, 3, 3, 93, 93, 93, 17, 0, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15, 92, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 5, 6, 0, 0, 0, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 3, 3, 3, 131, 131, 131, 15, 15, 15, 15, 15,
    15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 95, 95, 95, 127, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 95, 95, 127, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    95, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 0, 95, 95, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 95, 95, 127, 95, 95, 95, 95, 95, 95,
    95, 127, 127, 127, 127, 127, 127, 127, 127, 95, 127, 127, 95, 95, 95,
    95, 95, 95, 95, 95, 95, 95, 95, 3, 3, 3, 94, 3, 3, 3, 4, 15, 95, 0,
    0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 8, 3, 3,
    3, 3, 95, 95, 95, 17, 95, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0,
    0, 0, 15, 15, 15, 94, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15,
    95, 95, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 95, 15, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 93, 93, 15, 15, 15, 15, 15, 15,
    95, 95, 95, 127, 127, 127, 127, 95, 95, 127, 127, 127, 0, 0, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 15, 0, 0, 0, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    127, 127, 95, 127, 127, 127, 127, 127, 127, 95, 95, 95, 0, 0, 0, 0,
    14, 0, 0, 0, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 93, 93, 93, 125, 125, 125, 125,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 0, 0, 0,
    93, 93, 125, 125, 125, 0, 0, 0, 0, 125, 125, 93, 125, 125, 125, 125,
    125, 125, 93, 93, 93, 0, 0, 0, 0, 14, 0, 0, 0, 3, 3, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    18, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 125, 125, 93, 0, 0, 3,
    3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0,
    0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 0, 0, 0, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    95, 95, 127, 127, 95, 0, 0, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 127, 95, 127, 95, 95,
    15, 15, 15, 15, 15, 125, 93, 125, 93, 93, 93, 93, 93, 93, 93, 0, 93,
    125, 93, 125, 125, 93, 93, 93, 93, 93, 93, 93, 93, 125, 125, 125, 125,
    125, 125, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, 0, 93, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 92, 3, 3, 3, 3, 3, 3, 0, 0,
    95, 95, 95, 95, 95, 0, 95, 127, 95, 127, 127, 95, 95, 95, 95, 95, 95,
    95, 95, 127, 127, 127, 127, 127, 127, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 0, 0, 95, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 94,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 120, 93, 93,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 93, 93, 93, 93, 125, 15, 15, 15, 15, 15, 15,
    3, 3, 3, 3, 3, 3, 0, 0, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 122, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95,
    95, 95, 95, 127, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 93, 125, 93, 93, 93, 93, 93, 125, 93, 125,
    125, 125, 125, 125, 93, 125, 125, 15, 15, 15, 15, 15, 15, 15, 0, 0,
    0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 3, 3, 3, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 93, 93, 93, 93, 93, 93, 93, 93, 93, 14,
    95, 127, 95, 95, 95, 95, 95, 127, 95, 127, 127, 127, 127, 127, 95,
    127, 127, 15, 15, 15, 15, 15, 15, 15, 15, 0, 3, 3, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 3, 3, 3, 3, 3, 3, 3, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 95, 95, 95, 95, 95, 95, 95, 95, 95, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 93, 93, 125, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 125, 93, 93, 93, 93, 125, 125,
    93, 93, 125, 93, 93, 93, 15, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 125, 93, 93, 125, 125,
    125, 93, 125, 93, 93, 93, 125, 125, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3,
    3, 15, 15, 15, 15, 125, 125, 125, 125, 125, 125, 125, 125, 93, 93,
    93, 93, 93, 93, 93, 93, 125, 125, 93, 93, 0, 0, 0, 3, 3, 3, 3, 3, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 15, 15, 15, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92,
    92, 92, 92, 92, 3, 3, 130, 131, 132, 133, 133, 134, 135, 136, 137,
    0, 0, 0, 0, 0, 0, 0, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
    138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
    138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
    14, 14, 3, 3, 3, 95, 95, 127, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 127, 95, 95, 95, 95, 127, 127, 95, 95, 127, 95, 95, 95,
    15, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 95, 127, 95, 95, 127, 127, 127, 95, 127, 95, 95, 95,
    127, 127, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 15, 15, 15, 15, 127,
    127, 127, 127, 127, 127, 127, 127, 95, 95, 95, 95, 95, 95, 95, 95,
    127, 127, 95, 95, 0, 0, 0, 3, 3, 3, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 0, 0, 0, 15, 15, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 94, 94, 94, 94, 94, 94, 3, 3, 132,
    133, 134, 135, 135, 136, 137, 138, 139, 23, 24, 0, 0, 0, 0, 0, 140,
    140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
    140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
    140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
    138, 138, 138, 138, 138, 0, 0, 138, 138, 138, 3, 3, 3, 3, 3, 3, 3,
    3, 0, 0, 0, 0, 0, 0, 0, 0, 93, 93, 93, 3, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 125, 93, 93, 93, 93, 93, 93, 93, 15, 15, 15,
    15, 93, 15, 15, 15, 15, 15, 15, 93, 15, 15, 125, 93, 93, 15, 0, 0,
    0, 0, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    0, 0, 140, 140, 140, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0,
    95, 95, 95, 3, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    127, 95, 95, 95, 95, 95, 95, 95, 15, 15, 15, 15, 95, 15, 15, 15, 15,
    15, 15, 95, 15, 15, 127, 95, 95, 15, 0, 0, 0, 0, 0, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 92, 139, 21, 21, 21, 140, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 141, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
    94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
    94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
    94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
    94, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 94, 141, 21,
    21, 21, 142, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 143, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 94, 94,
    21, 21, 21, 21, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 0, 93, 93, 93, 93, 93, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 21, 21, 21, 21, 21,
    142, 21, 21, 143, 21, 144, 144, 144, 144, 144, 144, 144, 144, 145,
    145, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 0,
    0, 145, 145, 145, 145, 145, 145, 0, 0, 144, 144, 144, 144, 144, 144,
    144, 144, 145, 145, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144,
    94, 94, 94, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    23, 24, 23, 24, 23, 24, 23, 24, 21, 21, 21, 21, 21, 144, 21, 21, 145,
    21, 146, 146, 146, 146, 146, 146, 146, 146, 147, 147, 147, 147, 147,
    147, 147, 147, 146, 146, 146, 146, 146, 146, 0, 0, 147, 147, 147, 147,
    147, 147, 0, 0, 146, 146, 146, 146, 146, 146, 146, 146, 147, 147, 147,
    147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 146, 146, 146, 147,
    147, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 146, 0,
    0, 147, 147, 147, 147, 147, 147, 0, 0, 21, 146, 21, 146, 21, 146, 21,
    144, 144, 144, 144, 145, 145, 145, 145, 145, 145, 145, 145, 144, 144,
    144, 144, 144, 144, 0, 0, 145, 145, 145, 145, 145, 145, 0, 0, 21, 144,
    146, 0, 147, 0, 147, 0, 147, 0, 147, 146, 146, 146, 146, 146, 146,
    21, 144, 21, 144, 21, 144, 0, 145, 0, 145, 0, 145, 0, 145, 144, 144,
    144, 144, 144, 144, 144, 144, 145, 145, 145, 145, 145, 145, 145, 145,
    146, 146, 147, 147, 147, 147, 148, 148, 149, 149, 150, 150, 151, 151,
    0, 0, 144, 144, 144, 144, 144, 144, 144, 144, 152, 152, 152, 152, 152,
    146, 146, 147, 147, 147, 147, 147, 147, 147, 147, 148, 148, 149, 149,
    149, 149, 150, 150, 151, 151, 152, 152, 153, 153, 0, 0, 146, 146, 146,
    152, 152, 152, 144, 144, 144, 144, 144, 144, 144, 144, 152, 152, 152,
    152, 152, 152, 152, 152, 144, 144, 144, 144, 144, 144, 144, 144, 152,
    152, 152, 152, 152, 152, 152, 152, 144, 144, 21, 153, 21, 0, 21, 21,
    145, 145, 154, 154, 155, 11, 156, 11, 11, 11, 21, 153, 21, 0, 21, 21,
    157, 157, 157, 157, 155, 11, 11, 11, 144, 144, 21, 21, 0, 0, 21, 21,
    145, 145, 158, 158, 0, 11, 11, 11, 144, 144, 21, 21, 21, 114, 21, 21,
    145, 145, 159, 159, 118, 11, 11, 11, 0, 0, 21, 153, 21, 0, 21, 21,
    160, 160, 161, 161, 155, 11, 11, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    17, 17, 17, 17, 17, 8, 8, 8, 8, 8, 8, 3, 3, 16, 20, 5, 16, 16, 20,
    5, 16, 3, 3, 3, 3, 3, 3, 3, 3, 162, 163, 17, 17, 17, 17, 17, 2, 3,
    3, 3, 3, 3, 3, 3, 3, 3, 16, 20, 3, 3, 3, 3, 12, 12, 3, 3, 3, 7, 5,
    6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 12, 3, 3, 3, 3, 3, 3, 3,
    3, 3, 3, 2, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17,
    17, 17, 18, 92, 0, 0, 18, 18, 18, 18, 18, 18, 7, 7, 7, 5, 6, 92, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 7, 7, 7, 5, 6, 0, 92, 92, 92, 92,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4,
    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
    4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 120, 120, 120, 120, 93, 120, 120,
    120, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 108, 14, 14, 14, 14, 108, 14,
    14, 21, 108, 108, 108, 21, 21, 108, 108, 108, 21, 14, 108, 14, 14,
    7, 108, 108, 108, 108, 108, 14, 14, 14, 14, 14, 14, 108, 14, 164, 14,
    108, 14, 165, 166, 108, 108, 14, 21, 108, 108, 167, 108, 21, 15, 15,
    15, 15, 21, 14, 14, 21, 21, 108, 108, 7, 7, 7, 7, 7, 108, 21, 21, 21,
    21, 14, 7, 14, 14, 168, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 169, 169, 169, 169, 169, 169, 169, 169, 169,
    169, 169, 169, 169, 169, 169, 169, 170, 170, 170, 170, 170, 170, 170,
    170, 170, 170, 170, 170, 170, 170, 170, 170, 129, 129, 129, 23, 24,
    129, 129, 129, 129, 18, 14, 14, 0, 0, 0, 0, 7, 7, 7, 7, 7, 14, 14,
    14, 14, 14, 7, 7, 14, 14, 14, 14, 7, 14, 14, 7, 14, 14, 7, 14, 14,
    14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 7, 7, 14, 14, 7, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    146, 146, 146, 146, 146, 154, 154, 154, 154, 154, 154, 154, 154, 146,
    146, 146, 146, 146, 146, 146, 146, 154, 154, 154, 154, 154, 154, 154,
    154, 146, 146, 146, 146, 146, 146, 146, 146, 154, 154, 154, 154, 154,
    154, 154, 154, 146, 146, 21, 155, 21, 0, 21, 21, 147, 147, 156, 156,
    157, 11, 158, 11, 11, 11, 21, 155, 21, 0, 21, 21, 159, 159, 159, 159,
    157, 11, 11, 11, 146, 146, 21, 21, 0, 0, 21, 21, 147, 147, 160, 160,
    0, 11, 11, 11, 146, 146, 21, 21, 21, 116, 21, 21, 147, 147, 161, 161,
    120, 11, 11, 11, 0, 0, 21, 155, 21, 0, 21, 21, 162, 162, 163, 163,
    157, 11, 11, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17, 17,
    8, 8, 8, 8, 8, 8, 3, 3, 16, 20, 5, 16, 16, 20, 5, 16, 3, 3, 3, 3, 3,
    3, 3, 3, 164, 165, 17, 17, 17, 17, 17, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    16, 20, 3, 3, 3, 3, 12, 12, 3, 3, 3, 7, 5, 6, 3, 3, 3, 3, 3, 3, 3,
    3, 3, 3, 3, 7, 3, 12, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 17, 17, 17,
    17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 94, 0, 0, 18,
    18, 18, 18, 18, 18, 7, 7, 7, 5, 6, 94, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 7, 7, 7, 5, 6, 0, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
    94, 94, 94, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 122, 122, 122, 122, 95, 122, 122, 122, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 95, 95, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 14, 14, 110, 14, 14, 14, 14, 110, 14, 14, 21, 110, 110, 110,
    21, 21, 110, 110, 110, 21, 14, 110, 14, 14, 7, 110, 110, 110, 110,
    110, 14, 14, 14, 14, 14, 14, 110, 14, 166, 14, 110, 14, 167, 168, 110,
    110, 14, 21, 110, 110, 169, 110, 21, 15, 15, 15, 15, 21, 14, 14, 21,
    21, 110, 110, 7, 7, 7, 7, 7, 110, 21, 21, 21, 21, 14, 7, 14, 14, 170,
    14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171,
    171, 171, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172,
    172, 172, 172, 172, 131, 131, 131, 23, 24, 131, 131, 131, 131, 18,
    14, 14, 0, 0, 0, 0, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 7, 7, 14, 14,
    14, 14, 7, 14, 14, 7, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 7, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 14, 14, 7,
    14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 14, 14,
    14, 14, 14, 14, 14, 14, 5, 6, 5, 6, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 14, 14, 14, 14,
    14, 14, 14, 5, 6, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 5, 6, 5, 6, 14, 14,
    7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 7, 7, 14, 14, 14, 14, 14, 14, 14, 5, 6, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 173, 173, 173, 173, 173, 173,
    173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173,
    173, 173, 173, 173, 173, 173, 174, 174, 174, 174, 174, 174, 174, 174,
    174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174,
    174, 174, 174, 174, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7,
    7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    5, 6, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 5, 6, 7, 7, 7, 7,
    171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171,
    171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 172, 172,
    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172,
    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5,
    6, 5, 6, 5, 6, 5, 6, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 5, 6, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 5, 6, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 14, 14, 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 5, 6, 5, 6,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7,
    7, 7, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 5, 6, 5,
    6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 5, 6, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 7, 7, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 14, 14, 7, 7, 7, 7,
    7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0,
    14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 123, 123,
    123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 125, 125, 125, 125, 125, 125, 125,
    125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
    125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
    125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 126,
    126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
    126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
    126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
    126, 126, 126, 126, 126, 23, 24, 175, 176, 177, 178, 179, 23, 24, 23,
    24, 23, 24, 180, 181, 182, 183, 21, 23, 24, 21, 23, 24, 21, 21, 21,
    21, 21, 94, 94, 184, 184, 23, 24, 23, 24, 21, 14, 14, 14, 14, 14, 14,
    23, 24, 23, 24, 95, 95, 95, 23, 24, 0, 0, 0, 0, 0, 3, 3, 3, 3, 18,
    3, 3, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
    185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
    185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 0, 185, 0, 0,
    0, 0, 0, 185, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0,
    94, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 15, 15, 15, 15,
    123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
    123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
    123, 123, 123, 0, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
    124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
    124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
    124, 124, 124, 124, 124, 124, 124, 124, 124, 0, 23, 24, 173, 174, 175,
    176, 177, 23, 24, 23, 24, 23, 24, 178, 179, 180, 181, 21, 23, 24, 21,
    23, 24, 21, 21, 21, 21, 21, 92, 92, 182, 182, 23, 24, 23, 24, 21, 14,
    14, 14, 14, 14, 14, 23, 24, 23, 24, 93, 93, 93, 23, 24, 0, 0, 0, 0,
    0, 3, 3, 3, 3, 18, 3, 3, 183, 183, 183, 183, 183, 183, 183, 183, 183,
    183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183,
    183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183,
    183, 0, 183, 0, 0, 0, 0, 0, 183, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 0, 0, 0, 0, 0, 92, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 93, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15,
    15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15,
    15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 3, 3, 16, 20, 16, 20,
    3, 3, 3, 16, 20, 3, 16, 20, 3, 3, 3, 3, 3, 3, 3, 3, 3, 8, 3, 3, 8,
    3, 16, 20, 3, 3, 16, 20, 5, 6, 5, 6, 5, 6, 5, 6, 3, 3, 3, 3, 3, 92,
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 8, 3, 5, 3, 3, 3, 3,
    3, 3, 3, 3, 3, 3, 3, 3, 3, 14, 14, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0,
    2, 3, 3, 3, 14, 92, 15, 129, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 14, 14,
    5, 6, 5, 6, 5, 6, 5, 6, 8, 5, 6, 6, 14, 129, 129, 129, 129, 129, 129,
    129, 129, 129, 93, 93, 93, 93, 125, 125, 8, 92, 92, 92, 92, 92, 14,
    14, 129, 129, 129, 92, 15, 3, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 93,
    93, 11, 11, 92, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3,
    92, 92, 92, 15, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15,
    15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15,
    15, 15, 15, 15, 0, 3, 3, 16, 20, 16, 20, 3, 3, 3, 16, 20, 3, 16, 20,
    3, 3, 3, 3, 3, 3, 3, 3, 3, 8, 3, 3, 8, 3, 16, 20, 3, 3, 16, 20, 5,
    6, 5, 6, 5, 6, 5, 6, 3, 3, 3, 3, 3, 94, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    3, 8, 8, 3, 3, 3, 3, 8, 3, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    14, 14, 3, 3, 3, 5, 6, 5, 6, 5, 6, 5, 6, 8, 0, 0, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 3, 3, 3, 14, 94,
    15, 131, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 14, 14, 5, 6, 5, 6, 5, 6, 5,
    6, 8, 5, 6, 6, 14, 131, 131, 131, 131, 131, 131, 131, 131, 131, 95,
    95, 95, 95, 127, 127, 8, 94, 94, 94, 94, 94, 14, 14, 131, 131, 131,
    94, 15, 3, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 95, 95, 11, 11, 94,
    94, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 94, 94, 94, 15,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 14, 14,
    18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 14, 14, 18, 18, 18, 18,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    14, 14, 14, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 18, 18, 18, 18,
    18, 18, 18, 18, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 18, 18, 18, 18, 18, 18, 18,
    18, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 15, 15,
    18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 94, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 92, 3, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 94, 3, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 23, 24, 15, 93, 120, 120, 120, 3, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 3, 92, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 23, 24, 15, 95, 122, 122, 122, 3, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 95, 3, 94, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    23, 24, 92, 92, 93, 93, 15, 15, 15, 15, 15, 15, 129, 129, 129, 129,
    129, 129, 129, 129, 129, 129, 93, 93, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0,
    23, 24, 94, 94, 95, 95, 15, 15, 15, 15, 15, 15, 131, 131, 131, 131,
    131, 131, 131, 131, 131, 131, 95, 95, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0,
    0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
    11, 11, 11, 11, 11, 11, 11, 11, 11, 92, 92, 92, 92, 92, 92, 92, 92,
    92, 11, 11, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    11, 11, 11, 11, 11, 11, 11, 11, 11, 94, 94, 94, 94, 94, 94, 94, 94,
    94, 11, 11, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24,
    21, 21, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 92, 21,
    21, 21, 21, 21, 21, 21, 21, 23, 24, 23, 24, 184, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 92, 11, 11, 23, 24, 185, 21, 15, 23, 24, 23, 24,
    186, 21, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 187, 188, 189, 190, 187, 21, 191, 192, 193, 194,
    23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 0, 0, 23, 24, 195,
    196, 197, 23, 24, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 23, 24, 15, 92, 92, 21, 15, 15, 15, 15, 15, 15, 15,
    93, 15, 15, 15, 93, 15, 15, 15, 15, 93, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 125,
    125, 93, 93, 125, 14, 14, 14, 14, 93, 0, 0, 0, 18, 18, 18, 18, 18,
    18, 14, 14, 4, 14, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 3, 3, 3, 0, 0, 0,
    0, 0, 0, 0, 0, 125, 125, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 94, 21,
    21, 21, 21, 21, 21, 21, 21, 23, 24, 23, 24, 186, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 94, 11, 11, 23, 24, 187, 21, 15, 23, 24, 23, 24,
    188, 21, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23,
    24, 23, 24, 23, 24, 189, 190, 191, 192, 189, 21, 193, 194, 195, 196,
    23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 197,
    198, 199, 23, 24, 23, 24, 200, 23, 24, 0, 0, 23, 24, 0, 21, 0, 21,
    23, 24, 23, 24, 23, 24, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 94, 94, 94, 23, 24, 15, 94, 94, 21, 15, 15,
    15, 15, 15, 15, 15, 95, 15, 15, 15, 95, 15, 15, 15, 15, 95, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 127, 127, 95, 95, 127, 14, 14, 14, 14, 95, 0, 0, 0,
    18, 18, 18, 18, 18, 18, 14, 14, 4, 14, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 127, 127, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
    125, 125, 125, 125, 125, 125, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 15, 15, 15, 15,
    15, 15, 3, 3, 3, 15, 3, 15, 15, 93, 15, 15, 15, 15, 15, 15, 93, 93,
    93, 93, 93, 93, 93, 93, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 125, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 93, 125, 125, 93, 93, 93, 93, 125, 125, 93, 93, 125, 125,
    125, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 92, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 0, 0, 0, 0, 3, 3, 15, 15, 15, 15, 15, 93, 92, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15,
    15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 93, 93, 93, 93,
    125, 125, 93, 93, 125, 125, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,
    15, 15, 93, 15, 15, 15, 15, 15, 15, 15, 15, 93, 125, 0, 0, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 0, 0, 3, 3, 3, 3, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 15, 15, 15, 15, 15, 15, 14,
    14, 14, 15, 125, 93, 125, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 93, 15, 93, 93, 93, 15, 15, 93, 93, 15,
    15, 15, 15, 15, 93, 93, 15, 93, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 92, 3, 3, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 125, 93, 93, 125, 125, 3, 3, 15, 92,
    92, 125, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15,
    0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15,
    15, 15, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 127, 127, 127, 127, 127, 127,
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 95, 95, 0, 0, 0,
    0, 0, 0, 0, 0, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 15, 15, 15, 15, 15, 15, 3, 3, 3, 15, 3, 15, 15, 95, 15, 15, 15,
    15, 15, 15, 95, 95, 95, 95, 95, 95, 95, 95, 3, 3, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 127, 127, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 95, 127, 127, 95, 95, 95, 95, 127, 127, 95,
    95, 127, 127, 127, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 94, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 3, 3, 15, 15, 15, 15, 15, 95,
    94, 15, 15, 15, 15, 15, 15, 15, 15, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 95, 95,
    95, 95, 95, 95, 127, 127, 95, 95, 127, 127, 95, 95, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 15, 15, 15, 95, 15, 15, 15, 15, 15, 15, 15, 15, 95, 127,
    0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 3, 3, 3, 3, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 94, 15, 15, 15, 15,
    15, 15, 14, 14, 14, 15, 127, 95, 127, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 95, 15, 95, 95, 95, 15, 15,
    95, 95, 15, 15, 15, 15, 15, 95, 95, 15, 95, 15, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 94, 3, 3,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 127, 95, 95, 127, 127,
    3, 3, 15, 94, 94, 127, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15,
    15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15,
    15, 15, 15, 15, 15, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 198, 21, 21, 21, 21, 21, 21, 21, 11, 92, 92, 92, 92,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 92, 11, 11, 0, 0, 0, 0, 199, 199,
    199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
    199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
    199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
    199, 199, 199, 199, 15, 15, 15, 125, 125, 93, 125, 125, 93, 125, 125,
    3, 125, 93, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15,
    21, 21, 21, 21, 21, 21, 21, 202, 21, 21, 21, 21, 21, 21, 21, 11, 94,
    94, 94, 94, 21, 21, 21, 21, 21, 21, 21, 21, 21, 94, 11, 11, 0, 0, 0,
    0, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
    203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
    203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
    203, 203, 203, 203, 203, 203, 203, 15, 15, 15, 127, 127, 95, 127, 127,
    95, 127, 127, 3, 127, 95, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 0, 0, 0, 0, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
    200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
    200, 200, 200, 200, 200, 200, 200, 200, 201, 201, 201, 201, 201, 201,
    201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201,
    201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 204, 204, 204, 204, 204, 204, 204,
    204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
    204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205,
    205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
    205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
    205, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21, 21, 21, 21, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21, 21, 0, 0, 0, 0, 0, 15,
    93, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 7, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 0, 15, 0, 15,
    15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21, 21,
    21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21, 21, 0,
    0, 0, 0, 0, 15, 95, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 7, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15,
    15, 0, 15, 0, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 11, 11, 11,
    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 6, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 6, 5, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 4, 14, 0, 0, 93, 93, 93, 93, 93,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 14, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 3, 3, 3, 3, 3, 3, 3, 5,
    6, 3, 0, 0, 0, 0, 0, 0, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 3, 8, 8, 12, 12, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6,
    5, 6, 5, 6, 5, 6, 3, 3, 5, 6, 3, 3, 3, 3, 12, 12, 12, 3, 3, 3, 0, 3,
    3, 3, 3, 8, 5, 6, 5, 6, 5, 6, 3, 3, 3, 7, 8, 7, 7, 7, 0, 3, 4, 3, 3,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 4, 14, 14, 14, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 3, 3, 3, 3, 3, 3, 3, 5, 6, 3, 0, 0, 0, 0, 0, 0, 95,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 3, 8, 8,
    12, 12, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 3, 3, 5, 6,
    3, 3, 3, 3, 12, 12, 12, 3, 3, 3, 0, 3, 3, 3, 3, 8, 5, 6, 5, 6, 5, 6,
    3, 3, 3, 7, 8, 7, 7, 7, 0, 3, 4, 3, 3, 0, 0, 0, 0, 15, 15, 15, 15,
    15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 17, 0,
    3, 3, 3, 4, 3, 3, 3, 5, 6, 3, 7, 3, 8, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 3, 3, 7, 7, 7, 3, 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 5,
    7, 6, 7, 5, 6, 3, 5, 6, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 0, 0, 17, 0, 3, 3, 3, 4, 3, 3, 3, 5, 6,
    3, 7, 3, 8, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 7, 7, 7, 3, 11,
    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 13, 13, 13, 5, 7, 6, 7, 5, 6, 3, 5, 6, 3, 3,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 94, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 0, 0, 15, 15,
    15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15,
    15, 15, 0, 0, 15, 15, 15, 0, 0, 0, 4, 4, 7, 11, 14, 4, 4, 0, 14, 7,
    7, 7, 7, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 14, 14,
    15, 15, 15, 15, 15, 94, 94, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15,
    15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15,
    0, 0, 0, 4, 4, 7, 11, 14, 4, 4, 0, 14, 7, 7, 7, 7, 14, 14, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 14, 14, 0, 0
    0, 0
#if TCL_UTF_MAX > 3 || TCL_MAJOR_VERSION > 8 || TCL_MINOR_VERSION > 6
    ,15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 129, 129,
    129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
    129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
    129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
    129, 129, 129, 129, 129, 129, 129, 129, 129, 18, 18, 18, 18, 14, 14,
    18, 18, 18, 18, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 131, 131,
    131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131,
    131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131,
    131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131,
    131, 131, 131, 131, 131, 131, 131, 131, 131, 18, 18, 18, 18, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 18, 18,
    14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14,
    0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 93, 0,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 18, 18, 18, 18, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 129, 15, 15, 15, 15, 15, 15, 15, 15, 129, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    14, 14, 14, 14, 14, 95, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 95, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 18, 18,
    18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 131, 15, 15, 15, 15,
    15, 15, 15, 15, 131, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 93, 93, 93, 93, 93, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 3, 15, 15, 15, 15,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 3, 129, 129, 129, 129,
    129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 202, 202, 202, 202, 202, 202,
    202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
    202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
    202, 202, 202, 202, 202, 203, 203, 203, 203, 203, 203, 203, 203, 203,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 95, 95, 95, 95,
    95, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 3, 15, 15, 15, 15, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15,
    3, 131, 131, 131, 131, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 206,
    206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
    206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
    206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 207, 207, 207, 207,
    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
    203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
    203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
    203, 203, 203, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    207, 207, 207, 207, 207, 207, 207, 207, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 202, 202, 202, 202,
    202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
    202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
    202, 202, 202, 202, 0, 0, 0, 0, 203, 203, 203, 203, 203, 203, 203,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0,
    0, 0, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
    206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
    206, 206, 206, 206, 206, 206, 206, 206, 206, 0, 0, 0, 0, 207, 207,
    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
    203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
    203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
    203, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0,
    207, 207, 207, 207, 207, 207, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15,
    15, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 0, 0, 15,
    0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 3, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 0,
    208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
    208, 0, 208, 208, 208, 208, 208, 208, 208, 0, 208, 208, 0, 209, 209,
    209, 209, 209, 209, 209, 209, 209, 209, 209, 0, 209, 209, 209, 209,
    209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 0, 209, 209,
    209, 209, 209, 209, 209, 0, 209, 209, 0, 0, 0, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 0, 3, 18, 18, 18, 18, 18, 18, 18, 18, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0,
    15, 15, 15, 15, 15, 14, 14, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0,
    0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 0, 0, 0, 0, 18, 18, 18,
    18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 18, 18, 18, 18, 18, 18, 0, 0, 0, 3, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 3, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 0, 0, 0, 0, 18, 18, 15, 15, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94,
    94, 94, 94, 94, 94, 0, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
    94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
    94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 0, 94, 94,
    94, 94, 94, 94, 94, 94, 94, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15,
    0, 0, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 0,
    0, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 3, 18, 18, 18, 18, 18, 18, 18,
    18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 14, 14, 18, 18, 18, 18, 18, 18, 18, 0,
    0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0,
    18, 18, 18, 18, 18, 18, 15, 93, 93, 93, 0, 93, 93, 0, 0, 0, 0, 0, 93,
    93, 93, 93, 15, 15, 15, 15, 0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 0, 0, 93, 93, 93, 0, 0, 0, 0, 93, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3,
    3, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 18, 18, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 18,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 0, 0, 0, 0, 18,
    18, 18, 18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 18, 18, 18, 18, 18, 18, 0, 0, 0,
    3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 3, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 0, 0, 0, 18, 18, 15, 15, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 15, 95, 95, 95, 0, 95, 95, 0, 0, 0,
    0, 0, 95, 95, 95, 95, 15, 15, 15, 15, 0, 15, 15, 15, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 93, 93, 0, 0, 0, 0, 18, 18, 18, 18, 18, 3, 3, 3,
    3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0,
    3, 3, 3, 3, 3, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 18, 18, 18, 18, 18, 18,
    18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 95, 95, 95, 0, 0, 0, 0, 95,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3,
    3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 18, 18, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 18, 18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 95, 95, 0, 0, 0, 0, 18, 18, 18, 18,
    18, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 18, 18, 18,
    18, 18, 18, 18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18,
    18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 98, 98, 98, 98,
    15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 100,
    98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
    98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
    98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
    100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
    100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
    100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
    100, 100, 100, 100, 100, 100, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105,
    105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105,
    105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105,
    105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 0, 0, 0, 0, 0, 0,
    103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
    103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
    103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 0, 0, 0,
    0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 15, 15, 15, 15, 93, 93, 93, 93,
    0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0,
    0, 18, 18, 18, 18, 18, 18, 15, 15, 15, 15, 95, 95, 95, 95, 0, 0, 0,
    0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9,
    0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 93, 93, 8, 0, 0, 15, 15, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18,
    15, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 94, 15, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    0, 0, 0, 95, 95, 95, 95, 95, 8, 94, 13, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 18, 18, 18, 18, 3, 3, 3, 3, 3, 0, 0, 0, 0,
    0, 0, 15, 15, 15, 15, 15, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 93, 125, 15, 15,
    0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 3, 3, 3,
    3, 3, 3, 3, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 15, 15, 15, 15, 15, 15,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 0, 95, 95, 8, 0, 0, 15, 15, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 125, 125, 125, 93, 93, 93,
    93, 125, 125, 93, 93, 3, 3, 17, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 17, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0,
    0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 93, 93, 93, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 95, 95, 95, 95, 18, 18, 18, 18, 18, 18, 18, 15, 0, 0, 0, 0, 0,
    0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    15, 93, 93, 93, 93, 93, 125, 93, 93, 93, 93, 93, 93, 93, 93, 0, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 15, 125, 125, 15, 0, 0, 0, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 93, 3, 3, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    95, 18, 18, 18, 18, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 95, 95, 95, 95, 3, 3, 3, 3, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 125,
    125, 125, 93, 93, 93, 93, 93, 93, 93, 93, 93, 125, 125, 15, 15, 15,
    15, 3, 3, 3, 3, 93, 93, 93, 93, 3, 125, 93, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 15, 3, 15, 3, 3, 3, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 125, 125, 125, 93, 93,
    93, 125, 125, 93, 125, 93, 93, 3, 3, 3, 3, 3, 3, 93, 0, 15, 15, 15,
    15, 15, 15, 15, 0, 15, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 3, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 95, 127, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 95, 95, 95,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 3, 3, 3, 3, 3, 3, 3,
    0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 95, 15, 15, 95,
    95, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 127, 127, 127, 95, 95, 95, 95,
    127, 127, 95, 95, 3, 3, 17, 3, 3, 3, 3, 95, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 17, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 95, 95, 95, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 93, 125, 125, 125, 93, 93, 93, 93, 93, 93, 93, 93,
    0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 93,
    93, 125, 125, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    95, 95, 95, 95, 95, 127, 95, 95, 95, 95, 95, 95, 95, 95, 0, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 15, 127, 127, 15, 0, 0, 0, 0, 0, 0,
    0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 95, 3, 3, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15,
    15, 15, 15, 15, 0, 93, 93, 15, 125, 125, 93, 125, 125, 125, 125, 0,
    0, 125, 125, 0, 0, 125, 125, 125, 0, 0, 15, 0, 0, 0, 0, 0, 0, 125,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 125, 125, 0, 0, 93, 93, 93, 93,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 127, 127, 127,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 127, 127, 15, 15, 15, 15, 3, 3,
    3, 3, 95, 95, 95, 95, 3, 127, 95, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15,
    3, 15, 3, 3, 3, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    93, 93, 93, 0, 0, 0, 93, 93, 93, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 125, 125, 125, 93, 93, 93, 93, 93, 93, 93, 93,
    125, 125, 93, 93, 93, 125, 93, 15, 15, 15, 15, 3, 3, 3, 3, 3, 9, 9,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 127, 127, 127, 95, 95, 95, 127,
    127, 95, 127, 95, 95, 3, 3, 3, 3, 3, 3, 95, 15, 15, 95, 0, 0, 0, 0,
    9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 0, 3, 93, 15, 15, 15, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 15, 15, 15, 15, 0, 15,
    0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15,
    125, 125, 125, 93, 93, 93, 93, 93, 93, 125, 93, 125, 125, 125, 125,
    93, 93, 125, 93, 93, 15, 15, 3, 15, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 125, 125, 125, 93, 93, 93, 93, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 3, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    125, 125, 125, 125, 93, 93, 125, 93, 93, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 15, 15, 15, 15, 93, 93, 0,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    125, 125, 125, 93, 93, 93, 93, 93, 93, 93, 93, 125, 125, 93, 125, 93,
    93, 3, 3, 3, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 93, 125, 93, 125, 125, 93, 93, 93,
    93, 93, 93, 125, 93, 15, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 95, 127, 127, 127, 95, 95, 95,
    95, 95, 95, 95, 95, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0,
    0, 0, 0, 0, 0, 95, 95, 127, 127, 0, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 125, 125, 93, 93, 93, 93, 125, 93, 93, 93, 93, 93, 0, 0, 0, 0,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 3, 3, 3, 14, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 125, 125, 125, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 125, 93, 93, 3, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10,
    0, 0, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15,
    15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 0, 95, 95, 15, 127, 127, 95,
    127, 127, 127, 127, 0, 0, 127, 127, 0, 0, 127, 127, 127, 0, 0, 15,
    0, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 127, 127,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13,
    0, 0, 95, 95, 95, 95, 95, 95, 95, 0, 0, 0, 95, 95, 95, 95, 95, 0, 0,
    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 13, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15,
    15, 15, 15, 15, 15, 15, 0, 0, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 125, 125, 125, 125, 125,
    125, 0, 125, 125, 0, 0, 93, 93, 125, 93, 15, 125, 15, 125, 93, 3, 3,
    3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0,
    0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 15, 0, 0, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 127, 127, 127, 95, 95, 95,
    95, 95, 95, 0, 127, 0, 0, 127, 0, 127, 127, 127, 127, 0, 127, 127,
    95, 127, 95, 15, 95, 15, 3, 3, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 95,
    95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 127, 127, 127, 95, 95, 95,
    95, 95, 95, 95, 95, 127, 127, 95, 95, 95, 127, 95, 15, 15, 15, 15,
    3, 3, 3, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 0, 3, 95, 15, 15,
    15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 127, 127, 127, 95, 95, 95, 95, 95, 95, 127,
    95, 127, 127, 127, 127, 95, 95, 127, 95, 95, 15, 15, 3, 15, 0, 0, 0,
    0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 127, 127, 127,
    125, 125, 125, 93, 93, 93, 93, 0, 0, 93, 93, 125, 125, 125, 125, 93,
    15, 3, 15, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    95, 95, 95, 95, 0, 0, 127, 127, 127, 127, 95, 95, 127, 95, 95, 3, 3,
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 15,
    15, 15, 15, 95, 95, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 127, 127, 127, 95, 95, 95, 95, 95, 95, 95, 95,
    127, 127, 95, 127, 95, 95, 3, 3, 3, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3,
    3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 95, 127, 95,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 93, 93, 93, 93, 93, 93, 125, 15, 93, 93,
    93, 93, 3, 3, 3, 3, 3, 3, 3, 3, 93, 0, 0, 0, 0, 0, 0, 0, 0, 15, 93,
    127, 127, 95, 95, 95, 95, 95, 95, 127, 95, 15, 3, 0, 0, 0, 0, 0, 0,
    93, 93, 93, 93, 93, 125, 125, 93, 93, 93, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 125, 93, 93, 3, 3, 3, 15, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 125, 93, 93, 93,
    15, 15, 15, 15, 15, 15, 0, 0, 95, 127, 95, 127, 127, 95, 95, 95, 95,
    93, 93, 93, 93, 0, 93, 93, 93, 93, 93, 93, 125, 93, 15, 3, 3, 3, 3,
    3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18,
    127, 95, 95, 95, 95, 95, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 0, 0, 0, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 0, 125, 93, 93, 93, 93, 93, 93, 93, 125,
    93, 93, 125, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15,
    18, 18, 3, 3, 3, 14, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 127, 127, 127, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 127, 95, 95, 3, 0, 0, 0, 0, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
    13, 13, 13, 13, 13, 13, 13, 13, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 0, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 93, 93, 93, 93, 0, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 127, 127, 127, 127,
    127, 127, 0, 127, 127, 0, 0, 95, 95, 127, 95, 15, 127, 15, 127, 95,
    93, 0, 93, 93, 0, 93, 93, 93, 93, 93, 93, 93, 15, 93, 0, 0, 0, 0, 0,
    0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 125, 125, 125, 125, 125, 0, 93, 93, 0, 125, 125, 93,
    125, 93, 15, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 125, 125, 3, 3, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 127, 127, 127, 95, 95, 95, 95, 0, 0, 95, 95, 127, 127, 127, 127,
    95, 15, 3, 15, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 95, 95, 95, 95, 95, 95, 127, 15, 95,
    14, 14, 14, 14, 14, 14, 4, 4, 4, 4, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 3, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
    129, 129, 129, 0, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    95, 95, 95, 3, 3, 3, 3, 3, 3, 3, 3, 95, 0, 0, 0, 0, 0, 0, 0, 0, 15,
    95, 95, 95, 95, 95, 95, 127, 127, 95, 95, 95, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 127, 95, 95, 3, 3, 3, 15, 3, 3, 3, 3, 3, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0,
    93, 93, 93, 93, 93, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 93, 93, 93,
    15, 15, 15, 15, 15, 15, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 3, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 127,
    93, 93, 3, 3, 3, 3, 3, 14, 14, 14, 14, 92, 92, 92, 92, 3, 14, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 18, 18, 18,
    18, 18, 18, 18, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0,
    95, 95, 95, 95, 95, 95, 95, 0, 95, 95, 95, 95, 95, 95, 127, 95, 15,
    3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 0, 0, 0, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 0, 0, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 0, 127, 95, 95, 95, 95, 95, 95,
    95, 127, 95, 95, 127, 95, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 3,
    3, 3, 3, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 0, 0, 0, 93, 15, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 95, 95, 95, 95, 95, 95,
    0, 0, 0, 95, 0, 95, 95, 0, 95, 95, 95, 95, 95, 95, 95, 15, 95, 0, 0,
    125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
    125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
    125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
    125, 125, 125, 0, 0, 0, 0, 0, 0, 0, 93, 93, 93, 93, 92, 92, 92, 92,
    0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15,
    92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 3, 92, 93, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 125, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0,
    15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 127, 127, 127, 127, 127, 0, 95, 95, 0, 127,
    127, 95, 127, 95, 15, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 95, 95, 127, 127, 3, 3, 0, 0, 0, 0, 0, 0, 0, 95, 95, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 0, 0, 14, 93, 93, 3, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14,
    14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    127, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 127, 127,
    95, 95, 95, 95, 95, 0, 0, 0, 127, 127, 95, 127, 95, 3, 3, 3, 3, 3,
    3, 3, 3, 3, 3, 3, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 95, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, 14,
    14, 125, 125, 93, 93, 93, 14, 14, 14, 125, 125, 125, 125, 125, 125,
    17, 17, 17, 17, 17, 17, 17, 17, 93, 93, 93, 93, 93, 93, 93, 93, 14,
    14, 93, 93, 93, 93, 93, 93, 93, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 93, 93, 93, 93, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 14, 14, 93, 93, 93, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0,
    14, 14, 14, 14, 4, 4, 4, 4, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    3, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131,
    131, 131, 0, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15,
    15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 17,
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 95, 15,
    15, 15, 15, 15, 15, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 127, 127, 127, 95, 95, 95, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0,
    0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 3, 3, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 9, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 0, 0, 95, 95, 95, 95, 95, 3, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 95, 95, 95, 95, 95, 95, 95, 3, 3, 3, 3, 3, 14, 14, 14, 14,
    94, 94, 94, 94, 3, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 9, 0, 18, 18, 18, 18, 18, 18, 18, 0, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    94, 94, 94, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 94, 94, 3, 3, 3, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 3, 3, 3, 3,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0,
    0, 95, 15, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 0, 0, 0, 0, 0, 0, 0, 95, 95, 95, 95, 94, 94, 94, 94, 94, 94, 94,
    94, 94, 94, 94, 94, 94, 94, 94, 3, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 127, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 94, 94, 94,
    0, 94, 94, 94, 94, 94, 94, 94, 0, 94, 94, 0, 15, 15, 15, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15,
    0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15,
    0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 14, 95, 95, 3, 17, 17, 17,
    17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 95,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 0, 0, 95, 95, 95,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 108, 108,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 127, 127, 95, 95, 95, 14, 14, 14, 127, 127, 127, 127, 127,
    127, 17, 17, 17, 17, 17, 17, 17, 17, 95, 95, 95, 95, 95, 95, 95, 95,
    14, 14, 95, 95, 95, 95, 95, 95, 95, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 95, 95, 95, 95, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 95, 95, 95, 14, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    0, 0, 0, 0, 0, 0, 0, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
    110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
    110, 110, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 21, 21, 21, 21, 21, 21, 21, 0, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 108,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 110, 110, 110, 110, 110,
    0, 108, 108, 0, 0, 108, 0, 0, 108, 108, 0, 0, 108, 108, 108, 108, 0,
    108, 108, 108, 108, 108, 108, 108, 108, 21, 21, 21, 21, 0, 21, 0, 21,
    21, 21, 21, 21, 21, 21, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
    110, 110, 110, 110, 110, 110, 110, 21, 21, 21, 21, 21, 21, 21, 0, 21,
    21, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
    21, 21, 21, 21, 21, 21, 21, 21, 108, 108, 0, 108, 108, 108, 108, 0,
    110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 21, 21,
    0, 108, 108, 108, 108, 108, 108, 108, 108, 0, 108, 108, 108, 108, 108,
    108, 108, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 108, 108, 0, 108, 108,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 110, 0, 110, 110, 0, 0, 110, 0, 0, 110,
    110, 0, 0, 110, 110, 110, 110, 0, 110, 110, 110, 110, 110, 110, 110,
    110, 21, 21, 21, 21, 0, 21, 0, 21, 21, 21, 21, 21, 21, 21, 0, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 110, 110, 110, 110, 110, 110, 110,
    108, 108, 0, 108, 108, 108, 108, 108, 0, 108, 0, 0, 0, 108, 108, 108,
    108, 108, 108, 108, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 108, 108,
    110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
    110, 110, 110, 110, 110, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 110, 110,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 21, 21, 21, 21, 21,
    0, 110, 110, 110, 110, 0, 0, 110, 110, 110, 110, 110, 110, 110, 110,
    0, 110, 110, 110, 110, 110, 110, 110, 0, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 110, 110, 0, 110, 110, 110, 110, 0, 110, 110, 110, 110, 110,
    21, 21, 21, 21, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 108, 108, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 108,
    0, 110, 0, 0, 0, 110, 110, 110, 110, 110, 110, 110, 0, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 110, 110, 110, 110, 110, 110, 110, 110, 110,
    110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
    110, 110, 110, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 110, 110, 110,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 21, 21, 21,
    110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 110, 110,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 21, 21, 21, 21, 21, 21, 0, 0, 108,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 110, 110, 110, 110, 110, 110, 110,
    110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
    110, 110, 110, 110, 110, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 110, 110,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 7, 21, 21, 21, 21,
    110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
    21, 21, 21, 21, 21, 21, 0, 0, 110, 110, 110, 110, 110, 110, 110, 110,
    110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
    110, 110, 110, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7, 21, 21, 21, 21,
    21, 21, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
    110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 7,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 7, 21, 21, 21, 21, 21, 21, 108, 108, 108, 108, 108,
    21, 21, 21, 21, 21, 21, 21, 21, 7, 21, 21, 21, 21, 21, 21, 110, 110,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7,
    21, 21, 21, 21, 21, 21, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
    110, 110, 110, 110, 110, 110, 110, 110, 110, 7, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 7, 21, 21, 21, 21, 21, 21, 110, 110, 110, 110, 110, 110,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7, 21, 21, 21, 21, 21,
    110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
    110, 110, 110, 110, 110, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7, 21,
    21, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 7, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 7, 21, 21, 21, 21, 21, 21, 108, 108, 108,
    21, 21, 21, 21, 21, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
    110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
    110, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7, 21, 21, 21, 21, 21, 21,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 7, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    110, 21, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 14, 14, 14, 14,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 14, 14, 14, 14, 14, 14, 14, 14, 95, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 95, 14, 14, 3, 3, 3, 3, 3, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 95, 95, 95, 95, 0, 95, 95, 95,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    15, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21, 21, 21, 0, 0, 0,
    21, 21, 7, 21, 21, 21, 21, 21, 21, 108, 21, 0, 0, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 14, 14, 14, 14, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 14, 14, 14, 14, 14, 14, 14,
    14, 93, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 93,
    14, 14, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 95, 95, 95,
    93, 93, 93, 93, 93, 0, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93,
    95, 95, 95, 0, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 0, 0, 95, 95, 95, 95, 95, 95, 95, 0, 95, 95, 0, 95,
    95, 95, 95, 95, 0, 0, 0, 0, 0, 94, 94, 94, 94, 94, 94, 94, 94, 94,
    94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
    94, 94, 94, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    93, 93, 93, 93, 93, 93, 0, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 0, 0, 93, 93, 93, 93, 93, 93, 93, 0, 93,
    93, 0, 93, 93, 93, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 0, 0, 93, 93, 93, 93, 93, 93, 93, 92, 92, 92, 92, 92, 92, 92,
    0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 15, 14, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 93, 93, 93, 93, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0,
    0, 0, 0, 4, 15, 15, 15, 15, 15, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 93, 93, 93, 93, 93, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 204,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 0, 0, 95, 95, 95, 95, 95, 95, 95, 94, 94, 94, 94,
    94, 94, 94, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 15, 14,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 95, 95, 95, 95, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 4,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 94, 95, 95, 95, 95, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 95, 95, 15, 9, 9, 9, 9, 9, 9, 9, 9,
    9, 9, 0, 0, 0, 0, 3, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15,
    0, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 0, 15, 15, 15, 15, 15, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    95, 95, 95, 95, 95, 95, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 210, 210,
    204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
    204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
    204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
    205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
    205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 93, 93, 93, 93, 93,
    93, 93, 92, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 3,
    3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18,
    210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
    210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
    210, 210, 210, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
    211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
    211, 211, 211, 211, 211, 211, 211, 211, 211, 95, 95, 95, 95, 95, 95,
    95, 94, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 3, 3,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 14, 18, 18, 18, 4, 18, 18, 18, 18, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    18, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
    0, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
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
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







-
-
-
+
+
+

-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
+
-
-
-
-
-
+
+
+
-
-
-
+
+
-
-
+
-







    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0,
    0, 0, 0, 0, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14,
    14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    11, 11, 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0,
    0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 14, 14, 14,
    14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14,
    14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 0, 0, 0, 0, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14,
    14, 14, 14, 0, 0, 0, 14, 14, 14, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14,
    14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14,
    0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14,
    14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
#endif /* TCL_UTF_MAX > 3 */
};

/*
 * Each group represents a unique set of character attributes.  The attributes
 * are encoded into a 32-bit value as follows:
 *
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+







 *			    highest field so we can easily sign extend.
 */

static const int groups[] = {
    0, 15, 12, 25, 27, 21, 22, 26, 20, 9, 8257, 28, 19, 8322, 29,
    5, 23, 16, 11, -190078, 24, 2, -30846, 321, 386, -50879, 59522,
    -30911, 76930, -49790, 53825, 52801, 52545, 20289, 51777, 52033,
    53057, -24702, 54081, 53569, -41598, 54593, -33150, 54849, 55873,
    55617, 56129, -14206, 609, 451, 674, 20354, -24767, -14271, -33215,
    2763585, -41663, 2762817, -2768510, -49855, 17729, 18241, -2760318,
    -2759550, -2760062, 53890, 52866, 52610, 51842, 52098, -10833534,
    -10832510, 53122, -10823550, -10830718, 53634, 54146, -2750078,
    -10829950, -2751614, 54658, 54914, -2745982, 55938, -10830462,
    -10824062, 17794, 55682, 18306, 56194, -10818686, -10817918, 4,
    6, -21370, 29761, 9793, 9537, 16449, 16193, 9858, 9602, 8066,
    16514, 16258, 2113, 16002, 14722, 1, 12162, 13954, 2178, 22146,
    20610, -1662, 29826, -15295, 24706, -1727, 20545, 7, 3905, 3970,
    12353, 12418, 8, 1859649, -769822, 9949249, 10, 1601154, 1600898,
    1598594, 1598082, 1598338, 1596546, 1582466, -9027966, -769983,
    -9044862, -976254, -9058174, 15234, -1949375, -1918, -1983, -18814,
    -21886, -25470, -32638, -28542, -32126, -1981, -2174, -18879,
    -2237, 1844610, -21951, -25535, -28607, -32703, -32191, 13, 14,
    -1924287, -2145983, -2115007, 7233, 7298, 4170, 4234, 6749, 6813,
    -2750143, -976319, -2746047, 2763650, 2762882, -2759615, -2751679,
    -2760383, -2760127, -2768575, 1859714, -9044927, -10823615, -12158,
    -10830783, -10833599, -10832575, -10830015, -10817983, -10824127,
    -10818751, 237633, -12223, -10830527, -9058239, 237698, 9949314,
    18, 17, 10305, 10370, 8769, 8834
    53057, -24702, 54081, 53569, -41598, -10895486, 54593, -33150,
    54849, 55873, 55617, 56129, -14206, 609, 451, 674, 20354, -24767,
    -14271, -33215, 2763585, -41663, 2762817, -2768510, -49855, 17729,
    18241, -2760318, -2759550, -2760062, 53890, 52866, 52610, 51842,
    52098, -10833534, -10832510, 53122, -10839678, -10823550, -10830718,
    53634, 54146, -2750078, -10829950, -2751614, 54658, 54914, -2745982,
    55938, -10830462, -10824062, 17794, 55682, 18306, 56194, -10818686,
    -10817918, 4, 6, -21370, 29761, 9793, 9537, 16449, 16193, 9858,
    9602, 8066, 16514, 16258, 2113, 16002, 14722, 1, 12162, 13954,
    2178, 22146, 20610, -1662, 29826, -15295, 24706, -1727, 20545,
    7, 3905, 3970, 12353, 12418, 8, 1859649, -769822, 9949249, 10,
    1601154, 1600898, 1598594, 1598082, 1598338, 1596546, 1582466,
    -9027966, -769983, -9044862, -976254, -9058174, 15234, -1949375,
    -1918, -1983, -18814, -21886, -25470, -32638, -28542, -32126,
    -1981, -2174, -18879, -2237, 1844610, -21951, -25535, -28607,
    -32703, -32191, 13, 14, -1924287, -2145983, -2115007, 7233, 7298,
    4170, 4234, 6749, 6813, -2750143, -976319, -2746047, 2763650,
    2762882, -2759615, -2751679, -2760383, -2760127, -2768575, 1859714,
    -9044927, -10823615, -12158, -10830783, -10833599, -10832575,
    -10830015, -10817983, -10824127, -10818751, 237633, -12223, -10830527,
    -9058239, -10839743, -10895551, 237698, 9949314, 18, 17, 10305,
    10370, 10049, 10114, 8769, 8834
};

#if TCL_UTF_MAX > 3 || TCL_MAJOR_VERSION > 8 || TCL_MINOR_VERSION > 6
#   define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1FFFFF) >= 0x31360)
#   define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1FFFFF) >= 0x323C0)
#else
#   define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1F0000) != 0)
#endif

/*
 * The following constants are used to determine the category of a
 * Unicode character.

Changes to generic/tclUtf.c.

1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * tclUtf.c --
 *
 *	Routines for manipulating UTF-8 strings.
 *
 * Copyright (c) 1997-1998 Sun Microsystems, Inc.
 * Copyright © 1997-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

22
23
24
25
26
27
28
29

30
31
32
33
34
35
36
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36







-
+







 * values are shifted right by the category value to determine whether the
 * given category is included in the set.
 */

#define ALPHA_BITS ((1 << UPPERCASE_LETTER) | (1 << LOWERCASE_LETTER) \
	| (1 << TITLECASE_LETTER) | (1 << MODIFIER_LETTER) | (1<<OTHER_LETTER))

#define CONTROL_BITS ((1 << CONTROL) | (1 << FORMAT) | (1 << PRIVATE_USE))
#define CONTROL_BITS ((1 << CONTROL) | (1 << FORMAT))

#define DIGIT_BITS (1 << DECIMAL_DIGIT_NUMBER)

#define SPACE_BITS ((1 << SPACE_SEPARATOR) | (1 << LINE_SEPARATOR) \
	| (1 << PARAGRAPH_SEPARATOR))

#define WORD_BITS (ALPHA_BITS | DIGIT_BITS | (1 << CONNECTOR_PUNCTUATION))
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
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







-
-
+
+
-
-

-
+
-
-
-
-
-
-

-
+










-
+
-
-
-
-
-
-

-
+







 */

static const unsigned char totalBytes[256] = {
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
/* Tcl_UtfCharComplete() might point to 2nd byte of valid 4-byte sequence */
    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
/* End of "continuation byte section" */
    2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1
#if TCL_UTF_MAX > 3
    4,4,4,4,4,
#else
    1,1,1,1,1,
#endif
    1,1,1,1,1,1,1,1,1,1,1
};


static const unsigned char complete[256] = {
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
/* Tcl_UtfCharComplete() might point to 2nd byte of valid 4-byte sequence */
    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
/* End of "continuation byte section" */
    2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1
#if TCL_UTF_MAX > 3
    4,4,4,4,4,
#else
    3,3,3,3,3,
#endif
    1,1,1,1,1,1,1,1,1,1,1
};


/*
 * Functions used only in this module.
 */

static int		Invalid(const char *src);

/*
115
116
117
118
119
120
121
122

123
124
125
126
127
128
129
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115







-
+







 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

size_t
int
TclUtfCount(
    int ch)			/* The Unicode character whose size is returned. */
{
    if ((unsigned)(ch - 1) < (UNICODE_SELF - 1)) {
	return 1;
    }
    if (ch <= 0x7FF) {
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
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







-
-
+
+

-
+
-
-
-
-
-
+
+
+
+
-

-
-
+
+
-
-
+


-
+
-







-
+

-
-
+
+

-
-
-
+
+

+
+
+
+
+






-
-
+
+



+
-
+


+
-
+

-
-
+
+





+
+
+

+

-
+

-
-
+
+






-
-
-
-
+
+
+
+



+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+






-
-
-
+
+
+







}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UniCharToUtf --
 *
 *	Store the given Tcl_UniChar as a sequence of UTF-8 bytes in the
 *	provided buffer. Equivalent to Plan 9 runetochar().
 *	Stores the given Tcl_UniChar as a sequence of UTF-8 bytes in the provided
 *	buffer. Equivalent to Plan 9 runetochar().
 *
 *	Special handling of Surrogate pairs is handled as follows:
 *	Surrogate pairs are handled as follows: When ch is a high surrogate,
 *	When this function is called for ch being a high surrogate,
 *	the first byte of the 4-byte UTF-8 sequence is produced and
 *	the function returns 1. Calling the function again with a
 *	low surrogate, the remaining 3 bytes of the 4-byte UTF-8
 *	sequence is produced, and the function returns 3. The buffer
 *	the first byte of the 4-byte UTF-8 sequence is stored in the buffer and
 *	the function returns 1. If the function is called again with a low
 *	surrogate and the same buffer, the remaining 3 bytes of the 4-byte
 *	UTF-8 sequence are produced.
 *	is used to remember the high surrogate between the two calls.
 *
 *	If no low surrogate follows the high surrogate (which is actually
 *	illegal), this can be handled reasonably by calling Tcl_UniCharToUtf
 *	If no low surrogate follows the high surrogate (which is actually illegal),
 *	calling Tcl_UniCharToUtf again with ch being -1 produces a 3-byte UTF-8
 *	again with ch = -1. This will produce a 3-byte UTF-8 sequence
 *	representing the high surrogate.
 *	sequence representing the high surrogate.
 *
 * Results:
 *	The return values is the number of bytes in the buffer that were
 *	Returns the number of bytes stored into the buffer.
 *	consumed.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_Size
Tcl_UniCharToUtf(
    int ch,			/* The Tcl_UniChar to be stored in the
				 * buffer. */
    int ch,			/* The Tcl_UniChar to be stored in the buffer.
				 * Can be or'ed with flag TCL_COMBINE. */
    char *buf)			/* Buffer in which the UTF-8 representation of
				 * the Tcl_UniChar is stored. Buffer must be
				 * large enough to hold the UTF-8 character
				 * (at most 4 bytes). */
				 * ch is stored. Must be large enough to hold
				 * the UTF-8 character (at most 4 bytes). */
{
    int flags = ch;

    if (ch >= TCL_COMBINE) {
	ch &= (TCL_COMBINE - 1);
    }
    if ((unsigned)(ch - 1) < (UNICODE_SELF - 1)) {
	buf[0] = (char) ch;
	return 1;
    }
    if (ch >= 0) {
	if (ch <= 0x7FF) {
	    buf[1] = (char) ((ch | 0x80) & 0xBF);
	    buf[0] = (char) ((ch >> 6) | 0xC0);
	    buf[1] = (char) (0x80 | (0x3F & ch));
	    buf[0] = (char) (0xC0 | (ch >> 6));
	    return 2;
	}
	if (ch <= 0xFFFF) {
	    if ((flags & TCL_COMBINE) &&
	    if ((ch & 0xF800) == 0xD800) {
		    ((ch & 0xF800) == 0xD800)) {
		if (ch & 0x0400) {
		    /* Low surrogate */
		    if (    (0x80 == (0xC0 & buf[0]))
		    if (((buf[0] & 0xC0) == 0x80) && ((buf[1] & 0xCF) == 0)) {
			    && (0 == (0xCF & buf[1]))) {
			/* Previous Tcl_UniChar was a high surrogate, so combine */
			buf[2] = (char) ((ch & 0x3F) | 0x80);
			buf[1] |= (char) (((ch >> 6) & 0x0F) | 0x80);
			buf[2]  = (char) (0x80 | (0x3F & ch));
			buf[1] |= (char) (0x80 | (0x0F & (ch >> 6)));
			return 3;
		    }
		    /* Previous Tcl_UniChar was not a high surrogate, so just output */
		} else {
		    /* High surrogate */

		    /* Add 0x10000 to the raw number encoded in the surrogate
		     * pair in order to get the code point. */
		    ch += 0x40;

		    /* Fill buffer with specific 3-byte (invalid) byte combination,
		       so following low surrogate can recognize it and combine */
		     * so following low surrogate can recognize it and combine */
		    buf[2] = (char) ((ch << 4) & 0x30);
		    buf[1] = (char) (((ch >> 2) & 0x3F) | 0x80);
		    buf[0] = (char) (((ch >> 8) & 0x07) | 0xF0);
		    buf[1] = (char) (0x80 | (0x3F & (ch >> 2)));
		    buf[0] = (char) (0xF0 | (0x07 & (ch >> 8)));
		    return 1;
		}
	    }
	    goto three;
	}
	if (ch <= 0x10FFFF) {
	    buf[3] = (char) ((ch | 0x80) & 0xBF);
	    buf[2] = (char) (((ch >> 6) | 0x80) & 0xBF);
	    buf[1] = (char) (((ch >> 12) | 0x80) & 0xBF);
	    buf[0] = (char) ((ch >> 18) | 0xF0);
	    buf[3] = (char) (0x80 | (0x3F & ch));
	    buf[2] = (char) (0x80 | (0x3F & (ch >> 6)));
	    buf[1] = (char) (0x80 | (0x3F & (ch >> 12)));
	    buf[0] = (char) (0xF0 |         (ch >> 18));
	    return 4;
	}
    } else if (ch == -1) {
	if (       (0x80 == (0xC0 & buf[0]))
	if (((buf[0] & 0xC0) == 0x80) && ((buf[1] & 0xCF) == 0)
		&& ((buf[-1] & 0xF8) == 0xF0)) {
	    ch = 0xD7C0 + ((buf[-1] & 0x07) << 8) + ((buf[0] & 0x3F) << 2)
		    + ((buf[1] & 0x30) >> 4);
	    buf[1] = (char) ((ch | 0x80) & 0xBF);
	    buf[0] = (char) (((ch >> 6) | 0x80) & 0xBF);
	    buf[-1] = (char) ((ch >> 12) | 0xE0);
		&& (0    == (0xCF & buf[1]))
		&& (0xF0 == (0xF8 & buf[-1]))) {
	    ch = 0xD7C0
		+ ((0x07 & buf[-1]) << 8)
		+ ((0x3F & buf[0])  << 2)
		+ ((0x30 & buf[1])  >> 4);
	    buf[1]  = (char) (0x80 | (0x3F & ch));
	    buf[0]  = (char) (0x80 | (0x3F & (ch >> 6)));
	    buf[-1] = (char) (0xE0 | (ch >> 12));
	    return 2;
	}
    }

    ch = 0xFFFD;
three:
    buf[2] = (char) ((ch | 0x80) & 0xBF);
    buf[1] = (char) (((ch >> 6) | 0x80) & 0xBF);
    buf[0] = (char) ((ch >> 12) | 0xE0);
    buf[2] = (char) (0x80 | (0x3F & ch));
    buf[1] = (char) (0x80 | (0x3F & (ch >> 6)));
    buf[0] = (char) (0xE0 |         (ch >> 12));
    return 3;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UniCharToUtfDString --
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
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
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
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







-


-
-
+
+
+





-
+








-
+













+












-
+





-
+









-
+














+





-
+







 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

#undef Tcl_UniCharToUtfDString
char *
Tcl_UniCharToUtfDString(
    const int *uniStr,	/* Unicode string to convert to UTF-8. */
    size_t uniLength,		/* Length of Unicode string. */
    const int *uniStr,		/* Unicode string to convert to UTF-8. */
    Tcl_Size uniLength,		/* Length of Unicode string. Negative for nul
				 * terminated string */
    Tcl_DString *dsPtr)		/* UTF-8 representation of string is appended
				 * to this previously initialized DString. */
{
    const int *w, *wEnd;
    char *p, *string;
    size_t oldLength;
    Tcl_Size oldLength;

    /*
     * UTF-8 string length in bytes will be <= Unicode string length * 4.
     */

    if (uniStr == NULL) {
	return NULL;
    }
    if (uniLength == TCL_INDEX_NONE) {
    if (uniLength < 0) {
	uniLength = 0;
	w = uniStr;
	while (*w != '\0') {
	    uniLength++;
	    w++;
	}
    }
    oldLength = Tcl_DStringLength(dsPtr);
    Tcl_DStringSetLength(dsPtr, oldLength + (uniLength + 1) * 4);
    string = Tcl_DStringValue(dsPtr) + oldLength;

    p = string;
    wEnd = uniStr + uniLength;

    for (w = uniStr; w < wEnd; ) {
	p += Tcl_UniCharToUtf(*w, p);
	w++;
    }
    Tcl_DStringSetLength(dsPtr, oldLength + (p - string));

    return string;
}

char *
Tcl_Char16ToUtfDString(
    const unsigned short *uniStr,/* Utf-16 string to convert to UTF-8. */
    size_t uniLength,		/* Length of Utf-16 string. */
    Tcl_Size uniLength,		/* Length of Utf-16 string. */
    Tcl_DString *dsPtr)		/* UTF-8 representation of string is appended
				 * to this previously initialized DString. */
{
    const unsigned short *w, *wEnd;
    char *p, *string;
    size_t oldLength;
    Tcl_Size oldLength;
    int len = 1;

    /*
     * UTF-8 string length in bytes will be <= Utf16 string length * 3.
     */

    if (uniStr == NULL) {
	return NULL;
    }
    if (uniLength == TCL_INDEX_NONE) {
    if (uniLength < 0) {

	uniLength = 0;
	w = uniStr;
	while (*w != '\0') {
	    uniLength++;
	    w++;
	}
    }
    oldLength = Tcl_DStringLength(dsPtr);
    Tcl_DStringSetLength(dsPtr, oldLength + (uniLength + 1) * 3);
    string = Tcl_DStringValue(dsPtr) + oldLength;

    p = string;
    wEnd = uniStr + uniLength;

    for (w = uniStr; w < wEnd; ) {
	if (!len && ((*w & 0xFC00) != 0xDC00)) {
	    /* Special case for handling high surrogates. */
	    p += Tcl_UniCharToUtf(-1, p);
	}
	len = Tcl_UniCharToUtf(*w, p);
	len = Tcl_UniCharToUtf(*w | TCL_COMBINE, p);
	p += len;
	if ((*w >= 0xD800) && (len < 3)) {
	    len = 0; /* Indication that high surrogate was found */
	}
	w++;
    }
    if (!len) {
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
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







-
-
-
-
-
-
-
-
-

















-
+
-

-
-
-
+
+
+







 *	The caller must ensure that the source buffer is long enough that this
 *	routine does not run off the end and dereference non-existent memory
 *	looking for trail bytes. If the source buffer is known to be '\0'
 *	terminated, this cannot happen. Otherwise, the caller should call
 *	Tcl_UtfCharComplete() before calling this routine to ensure that
 *	enough bytes remain in the string.
 *
 *	If TCL_UTF_MAX <= 3, special handling of Surrogate pairs is done:
 *	For any UTF-8 string containing a character outside of the BMP, the
 *	first call to this function will fill *chPtr with the high surrogate
 *	and generate a return value of 1. Calling Tcl_UtfToUniChar again
 *	will produce the low surrogate and a return value of 3. Because *chPtr
 *	is used to remember whether the high surrogate is already produced, it
 *	is recommended to initialize the variable it points to as 0 before
 *	the first call to Tcl_UtfToUniChar is done.
 *
 * Results:
 *	*chPtr is filled with the Tcl_UniChar, and the return value is the
 *	number of bytes from the UTF-8 string that were consumed.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

static const unsigned short cp1252[32] = {
  0x20AC,   0x81, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
  0x02C6, 0x2030, 0x0160, 0x2039, 0x0152,   0x8D, 0x017D,   0x8F,
    0x90, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
   0x2DC, 0x2122, 0x0161, 0x203A, 0x0153,   0x9D, 0x017E, 0x0178
};

#undef Tcl_UtfToUniChar
Tcl_Size
int
Tcl_UtfToUniChar(
    const char *src,	/* The UTF-8 string. */
    int *chPtr)/* Filled with the Unicode character represented by
				 * the UTF-8 string. */
    const char *src,		/* The UTF-8 string. */
    int *chPtr)			/* Filled with the Unicode character
				 * represented by the UTF-8 string. */
{
    int byte;

    /*
     * Unroll 1 to 4 byte UTF-8 sequences.
     */

474
475
476
477
478
479
480
481

482
483
484
485
486
487
488
461
462
463
464
465
466
467

468
469
470
471
472
473
474
475







-
+







	if ((unsigned)(byte-0x80) < (unsigned)0x20) {
	    *chPtr = cp1252[byte-0x80];
	} else {
	    *chPtr = byte;
	}
	return 1;
    } else if (byte < 0xE0) {
	if ((src[1] & 0xC0) == 0x80) {
	if ((byte != 0xC1) && ((src[1] & 0xC0) == 0x80)) {
	    /*
	     * Two-byte-character lead-byte followed by a trail-byte.
	     */

	    *chPtr = (((byte & 0x1F) << 6) | (src[1] & 0x3F));
	    if ((unsigned)(*chPtr - 1) >= (UNICODE_SELF - 1)) {
		return 2;
506
507
508
509
510
511
512
513
514

515
516
517
518
519
520
521
493
494
495
496
497
498
499


500
501
502
503
504
505
506
507







-
-
+







	    }
	}

	/*
	 * A three-byte-character lead-byte not followed by two trail-bytes
	 * represents itself.
	 */
    }
    else if (byte < 0xF5) {
    } else if (byte < 0xF5) {
	if (((src[1] & 0xC0) == 0x80) && ((src[2] & 0xC0) == 0x80) && ((src[3] & 0xC0) == 0x80)) {
	    /*
	     * Four-byte-character lead byte followed by three trail bytes.
	     */
	    *chPtr = (((byte & 0x07) << 18) | ((src[1] & 0x3F) << 12)
		    | ((src[2] & 0x3F) << 6) | (src[3] & 0x3F));
	    if ((unsigned)(*chPtr - 0x10000) <= 0xFFFFF) {
529
530
531
532
533
534
535
536

537
538
539
540
541
542
543
515
516
517
518
519
520
521

522
523
524
525
526
527
528
529







-
+







	 */
    }

    *chPtr = byte;
    return 1;
}

int
Tcl_Size
Tcl_UtfToChar16(
    const char *src,	/* The UTF-8 string. */
    unsigned short *chPtr)/* Filled with the Tcl_UniChar represented by
				 * the UTF-8 string. This could be a surrogate too. */
{
    unsigned short byte;

570
571
572
573
574
575
576
577

578
579
580
581
582
583
584
556
557
558
559
560
561
562

563
564
565
566
567
568
569
570







-
+







	if ((unsigned)(byte-0x80) < (unsigned)0x20) {
	    *chPtr = cp1252[byte-0x80];
	} else {
	    *chPtr = byte;
	}
	return 1;
    } else if (byte < 0xE0) {
	if ((src[1] & 0xC0) == 0x80) {
	if ((byte != 0xC1) && ((src[1] & 0xC0) == 0x80)) {
	    /*
	     * Two-byte-character lead-byte followed by a trail-byte.
	     */

	    *chPtr = (((byte & 0x1F) << 6) | (src[1] & 0x3F));
	    if ((unsigned)(*chPtr - 1) >= (UNICODE_SELF - 1)) {
		return 2;
602
603
604
605
606
607
608
609
610

611
612
613
614
615
616
617
588
589
590
591
592
593
594


595
596
597
598
599
600
601
602







-
-
+







	    }
	}

	/*
	 * A three-byte-character lead-byte not followed by two trail-bytes
	 * represents itself.
	 */
    }
    else if (byte < 0xF5) {
    } else if (byte < 0xF5) {
	if (((src[1] & 0xC0) == 0x80) && ((src[2] & 0xC0) == 0x80)) {
	    /*
	     * Four-byte-character lead byte followed by at least two trail bytes.
	     * We don't test the validity of 3th trail byte, see [ed29806ba]
	     */
	    Tcl_UniChar high = (((byte & 0x07) << 8) | ((src[1] & 0x3F) << 2)
		    | ((src[2] & 0x3F) >> 4)) - 0x40;
647
648
649
650
651
652
653
654
655
656
657
658

659
660
661
662
663
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
707
708
709
710
711
712
713
714
715

716
717
718
719
720
721
722
723

724
725
726
727
728
729
730
731
732

733
734
735
736
737
738
739
632
633
634
635
636
637
638

639
640
641

642
643
644
645
646
647
648
649

650
651
652
653
654
655
656
657
658

659
660
661
662
663
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

707
708
709
710
711
712
713
714
715

716
717
718
719
720
721
722
723







-



-
+







-
+








-
+



















-
+


-
-
+
+















-
+







-
+








-
+







 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

#undef Tcl_UtfToUniCharDString
int *
Tcl_UtfToUniCharDString(
    const char *src,		/* UTF-8 string to convert to Unicode. */
    size_t length,			/* Length of UTF-8 string in bytes, or -1 for
    Tcl_Size length,		/* Length of UTF-8 string in bytes, or -1 for
				 * strlen(). */
    Tcl_DString *dsPtr)		/* Unicode representation of string is
				 * appended to this previously initialized
				 * DString. */
{
    int ch = 0, *w, *wString;
    const char *p;
    size_t oldLength;
    Tcl_Size oldLength;
    /* Pointer to the end of string. Never read endPtr[0] */
    const char *endPtr = src + length;
    /* Pointer to last byte where optimization still can be used */
    const char *optPtr = endPtr - TCL_UTF_MAX;

    if (src == NULL) {
	return NULL;
    }
    if (length == TCL_INDEX_NONE) {
    if (length < 0) {
	length = strlen(src);
    }

    /*
     * Unicode string length in Tcl_UniChars will be <= UTF-8 string length in
     * bytes.
     */

    oldLength = Tcl_DStringLength(dsPtr);

    Tcl_DStringSetLength(dsPtr,
	    oldLength + ((length + 1) * sizeof(int)));
    wString = (int *) (Tcl_DStringValue(dsPtr) + oldLength);

    w = wString;
    p = src;
    endPtr = src + length;
    optPtr = endPtr - 4;
    while (p <= optPtr) {
	p += TclUtfToUCS4(p, &ch);
	p += TclUtfToUniChar(p, &ch);
	*w++ = ch;
    }
    while ((p < endPtr) && TclUCS4Complete(p, endPtr-p)) {
	p += TclUtfToUCS4(p, &ch);
    while ((p < endPtr) && Tcl_UtfCharComplete(p, endPtr-p)) {
	p += TclUtfToUniChar(p, &ch);
	*w++ = ch;
    }
    while (p < endPtr) {
	*w++ = UCHAR(*p++);
    }
    *w = '\0';
    Tcl_DStringSetLength(dsPtr,
	    oldLength + ((char *) w - (char *) wString));

    return wString;
}

unsigned short *
Tcl_UtfToChar16DString(
    const char *src,		/* UTF-8 string to convert to Unicode. */
    size_t length,			/* Length of UTF-8 string in bytes, or -1 for
    Tcl_Size length,		/* Length of UTF-8 string in bytes, or -1 for
				 * strlen(). */
    Tcl_DString *dsPtr)		/* Unicode representation of string is
				 * appended to this previously initialized
				 * DString. */
{
    unsigned short ch = 0, *w, *wString;
    const char *p;
    size_t oldLength;
    Tcl_Size oldLength;
    /* Pointer to the end of string. Never read endPtr[0] */
    const char *endPtr = src + length;
    /* Pointer to last byte where optimization still can be used */
    const char *optPtr = endPtr - TCL_UTF_MAX;

    if (src == NULL) {
	return NULL;
    }
    if (length == TCL_INDEX_NONE) {
    if (length < 0) {
	length = strlen(src);
    }

    /*
     * Unicode string length in WCHARs will be <= UTF-8 string length in
     * bytes.
     */
749
750
751
752
753
754
755
756

757
758
759
760
761
762
763
733
734
735
736
737
738
739

740
741
742
743
744
745
746
747







-
+







    endPtr = src + length;
    optPtr = endPtr - 3;
    while (p <= optPtr) {
	p += Tcl_UtfToChar16(p, &ch);
	*w++ = ch;
    }
    while (p < endPtr) {
	if (TclChar16Complete(p, endPtr-p)) {
	if (Tcl_UtfCharComplete(p, endPtr-p)) {
	    p += Tcl_UtfToChar16(p, &ch);
	    *w++ = ch;
	} else {
	    *w++ = UCHAR(*p++);
	}
    }
    *w = '\0';
786
787
788
789
790
791
792
793

794
795
796
797
798
799
800
770
771
772
773
774
775
776

777
778
779
780
781
782
783
784







-
+







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

int
Tcl_UtfCharComplete(
    const char *src,		/* String to check if first few bytes contain
				 * a complete UTF-8 character. */
    size_t length)			/* Length of above string in bytes. */
    Tcl_Size length)		/* Length of above string in bytes. */
{
    return length >= complete[UCHAR(*src)];
}

/*
 *---------------------------------------------------------------------------
 *
809
810
811
812
813
814
815
816

817
818
819
820


821
822
823

824
825

826
827
828
829
830
831
832
833
834
835
836
837

838
839
840
841
842
843
844
793
794
795
796
797
798
799

800
801
802


803
804
805
806

807
808

809
810
811
812
813
814
815
816
817
818
819
820

821
822
823
824
825
826
827
828







-
+


-
-
+
+


-
+

-
+











-
+







 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

size_t
Tcl_Size
Tcl_NumUtfChars(
    const char *src,	/* The UTF-8 string to measure. */
    size_t length)	/* The length of the string in bytes, or
			 * TCL_INDEX_NONE for strlen(src). */
    Tcl_Size length)	/* The length of the string in bytes, or
			 * negative value for strlen(src). */
{
    Tcl_UniChar ch = 0;
    size_t i = 0;
    Tcl_Size i = 0;

    if (length == TCL_INDEX_NONE) {
    if (length < 0) {
	/* string is NUL-terminated, so TclUtfToUniChar calls are safe. */
	while (*src != '\0') {
	    src += TclUtfToUniChar(src, &ch);
	    i++;
	}
    } else {
	/* Will return value between 0 and length. No overflow checks. */

	/* Pointer to the end of string. Never read endPtr[0] */
	const char *endPtr = src + length;
	/* Pointer to last byte where optimization still can be used */
	const char *optPtr = endPtr - TCL_UTF_MAX;
	const char *optPtr = endPtr - 4;

	/*
	 * Optimize away the call in this loop. Justified because...
	 * when (src <= optPtr), (endPtr - src) >= (endPtr - optPtr)
	 * By initialization above (endPtr - optPtr) = TCL_UTF_MAX
	 * So (endPtr - src) >= TCL_UTF_MAX, and passing that to
	 * Tcl_UtfCharComplete we know will cause return of 1.
861
862
863
864
865
866
867




















































868
869
870
871
872
873
874
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    }
	    i++;
	}
    }
    return i;
}

Tcl_Size
TclNumUtfChars(
    const char *src,	/* The UTF-8 string to measure. */
    Tcl_Size length)	/* The length of the string in bytes, or
			 * negative for strlen(src). */
{
    unsigned short ch = 0;
    Tcl_Size i = 0;

    if (length < 0) {
	/* string is NUL-terminated, so TclUtfToUniChar calls are safe. */
	while (*src != '\0') {
	    src += Tcl_UtfToChar16(src, &ch);
	    i++;
	}
    } else {
	/* Will return value between 0 and length. No overflow checks. */

	/* Pointer to the end of string. Never read endPtr[0] */
	const char *endPtr = src + length;
	/* Pointer to last byte where optimization still can be used */
	const char *optPtr = endPtr - 4;

	/*
	 * Optimize away the call in this loop. Justified because...
	 * when (src <= optPtr), (endPtr - src) >= (endPtr - optPtr)
	 * By initialization above (endPtr - optPtr) = TCL_UTF_MAX
	 * So (endPtr - src) >= TCL_UTF_MAX, and passing that to
	 * Tcl_UtfCharComplete we know will cause return of 1.
	 */
	while (src <= optPtr
		/* && Tcl_UtfCharComplete(src, endPtr - src) */ ) {
	    src += Tcl_UtfToChar16(src, &ch);
	    i++;
	}
	/* Loop over the remaining string where call must happen */
	while (src < endPtr) {
	    if (Tcl_UtfCharComplete(src, endPtr - src)) {
		src += Tcl_UtfToChar16(src, &ch);
	    } else {
		/*
		 * src points to incomplete UTF-8 sequence
		 * Treat first byte as character and count it
		 */
		src++;
	    }
	    i++;
	}
    }
    return i;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UtfFindFirst --
 *
 *	Returns a pointer to the first occurrence of the given Unicode character
 *	in the NULL-terminated UTF-8 string. The NULL terminator is considered
886
887
888
889
890
891
892
893

894
895
896
897
898
899
900
922
923
924
925
926
927
928

929
930
931
932
933
934
935
936







-
+








const char *
Tcl_UtfFindFirst(
    const char *src,		/* The UTF-8 string to be searched. */
    int ch)			/* The Unicode character to search for. */
{
    while (1) {
	int find, len = TclUtfToUCS4(src, &find);
	int find, len = TclUtfToUniChar(src, &find);

	if (find == ch) {
	    return src;
	}
	if (*src == '\0') {
	    return NULL;
	}
925
926
927
928
929
930
931
932

933
934
935
936
937
938
939
961
962
963
964
965
966
967

968
969
970
971
972
973
974
975







-
+







Tcl_UtfFindLast(
    const char *src,		/* The UTF-8 string to be searched. */
    int ch)			/* The Unicode character to search for. */
{
    const char *last = NULL;

    while (1) {
	int find, len = TclUtfToUCS4(src, &find);
	int find, len = TclUtfToUniChar(src, &find);

	if (find == ch) {
	    last = src;
	}
	if (*src == '\0') {
	    break;
	}
963
964
965
966
967
968
969
970

971
972
973




974
975
976
977
978
979
980
999
1000
1001
1002
1003
1004
1005

1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020







-
+



+
+
+
+







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

const char *
Tcl_UtfNext(
    const char *src)		/* The current location in the string. */
{
    size_t left;
    int left;
    const char *next;

    if (((*src) & 0xC0) == 0x80) {
	/* Continuation byte, so we start 'inside' a (possible valid) UTF-8
	 * sequence. Since we are not allowed to access src[-1], we cannot
	 * check if the sequence is actually valid, the best we can do is
	 * just assume it is valid and locate the end. */
	if ((((*++src) & 0xC0) == 0x80) && (((*++src) & 0xC0) == 0x80)) {
	    ++src;
	}
	return src;
    }

    left = totalBytes[UCHAR(*src)];
1061
1062
1063
1064
1065
1066
1067
1068

1069
1070
1071
1072
1073
1074
1075
1101
1102
1103
1104
1105
1106
1107

1108
1109
1110
1111
1112
1113
1114
1115







-
+







		/*
		 * We've seen no trailing context to use to check
		 * anything. From what we know, this non-trail byte
		 * is a prefix of a previous character, and accepting
		 * it (the fallback) is correct.
		 */

		    || (trailBytesSeen >= complete[byte])) {
		    || (trailBytesSeen >= totalBytes[byte])) {
		/*
		 * That is, (1 + trailBytesSeen > needed).
		 * We've examined more bytes than needed to complete
		 * this lead byte. No matter about well-formedness or
		 * validity, the sequence starting with this lead byte
		 * will never include the fallback location, so we must
		 * return the fallback location. See test utf-7.17
1102
1103
1104
1105
1106
1107
1108
1109

1110
1111
1112

1113
1114

1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1142
1143
1144
1145
1146
1147
1148

1149
1150
1151

1152
1153

1154

1155

1156



1157
1158
1159
1160
1161
1162
1163







-
+


-
+

-
+
-

-

-
-
-







	     * and exit this loop before we run past the start of the string.
	     */
	    return fallback;
	}

	/* Continue the search backwards... */
	look--;
    } while (trailBytesSeen < TCL_UTF_MAX);
    } while (trailBytesSeen < 4);

    /*
     * We've seen TCL_UTF_MAX trail bytes, so we know there will not be a
     * We've seen 4 trail bytes, so we know there will not be a
     * properly formed byte sequence to find, and we can stop looking,
     * accepting the fallback (for TCL_UTF_MAX > 3) or just go back as
     * accepting the fallback.
     * far as we can.
     */
#if TCL_UTF_MAX > 3
    return fallback;
#else
    return src - TCL_UTF_MAX;
#endif
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UniCharAtIndex --
 *
1137
1138
1139
1140
1141
1142
1143
1144

1145
1146
1147
1148
1149

1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162

1163
1164
1165
1166
1167
1168
1169
1170
1171
1172

1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188

1189
1190
1191
1192














1193
1194
1195

1196
1197
1198

1199
1200
1201
1202
1203
1204
1205
1206
1207




1208
1209
1210
1211
1212

1213
1214
1215
1216
1217
1218
1219
1172
1173
1174
1175
1176
1177
1178

1179
1180
1181
1182
1183

1184
1185
1186
1187
1188
1189
1190







1191
1192
1193
1194
1195
1196
1197
1198
1199
1200

1201


1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214

1215
1216
1217


1218
1219
1220
1221
1222
1223
1224
1225
1226
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







-
+




-
+






-
-
-
-
-
-
-
+









-
+
-
-













-
+


-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-

-
+

-
-
+
-
-
-

-
-
-
-
-
+
+
+
+
-



-
+







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

int
Tcl_UniCharAtIndex(
    const char *src,	/* The UTF-8 string to dereference. */
    size_t index)		/* The position of the desired character. */
    Tcl_Size index)	/* The position of the desired character. */
{
    Tcl_UniChar ch = 0;
    int i = 0;

    if (index == TCL_INDEX_NONE) {
    if (index < 0) {
	return -1;
    }
    while (index--) {
	i = TclUtfToUniChar(src, &ch);
	src += i;
    }
#if TCL_UTF_MAX <= 3
    if ((ch >= 0xD800) && (i < 3)) {
	/* Index points at character following high Surrogate */
	return -1;
    }
#endif
    TclUtfToUCS4(src, &i);
    TclUtfToUniChar(src, &i);
    return i;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UtfAtIndex --
 *
 *	Returns a pointer to the specified character (not byte) position in
 *	the UTF-8 string. If TCL_UTF_MAX <= 3, characters > U+FFFF count as
 *	the UTF-8 string.
 *	2 positions, but then the pointer should never be placed between
 *	the two positions.
 *
 * Results:
 *	As above.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

const char *
Tcl_UtfAtIndex(
    const char *src,	/* The UTF-8 string. */
    size_t index)		/* The position of the desired character. */
    Tcl_Size index)	/* The position of the desired character. */
{
    Tcl_UniChar ch = 0;
#if TCL_UTF_MAX <= 3
    size_t len = 0;

    while (index-- > 0) {
	src += TclUtfToUniChar(src, &ch);
    }
    return src;
}

const char *
TclUtfAtIndex(
    const char *src,	/* The UTF-8 string. */
    Tcl_Size index)	/* The position of the desired character. */
{
    unsigned short ch = 0;
    Tcl_Size len = 0;
#endif

    if (index != TCL_INDEX_NONE) {
    if (index > 0) {
	while (index--) {
#if TCL_UTF_MAX <= 3
	    src += (len = TclUtfToUniChar(src, &ch));
	    src += (len = Tcl_UtfToChar16(src, &ch));
#else
	    src += TclUtfToUniChar(src, &ch);
#endif
	}
#if TCL_UTF_MAX <= 3
    if ((ch >= 0xD800) && (len < 3)) {
	/* Index points at character following high Surrogate */
	src += TclUtfToUniChar(src, &ch);
    }
	if ((ch >= 0xD800) && (len < 3)) {
	    /* Index points at character following high Surrogate */
	    src += Tcl_UtfToChar16(src, &ch);
	}
#endif
    }
    return src;
}


/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UtfBackslash --
 *
 *	Figure out how to handle a backslash sequence.
 *
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
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







-
+









+
-
+







 *	that represent the Unicode character is at least as large as the
 *	source buffer from which the backslashed sequence was extracted, no
 *	buffer overruns should occur.
 *
 *---------------------------------------------------------------------------
 */

size_t
Tcl_Size
Tcl_UtfBackslash(
    const char *src,		/* Points to the backslash character of a
				 * backslash sequence. */
    int *readPtr,		/* Fill in with number of characters read from
				 * src, unless NULL. */
    char *dst)			/* Filled with the bytes represented by the
				 * backslash sequence. */
{
#define LINE_LENGTH 128
    Tcl_Size numRead;
    size_t numRead, result;
    int result;

    result = TclParseBackslash(src, LINE_LENGTH, &numRead, dst);
    if (numRead == LINE_LENGTH) {
	/*
	 * We ate a whole line. Pay the price of a strlen()
	 */

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
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







-
+





-
+







-
+








-
+







 *
 * Side effects:
 *	Writes a terminating null after the last converted character.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_Size
Tcl_UtfToUpper(
    char *str)			/* String to convert in place. */
{
    int ch, upChar;
    char *src, *dst;
    size_t len;
    Tcl_Size len;

    /*
     * Iterate over the string until we hit the terminating null.
     */

    src = dst = str;
    while (*src) {
	len = TclUtfToUCS4(src, &ch);
	len = TclUtfToUniChar(src, &ch);
	upChar = Tcl_UniCharToUpper(ch);

	/*
	 * To keep badly formed Utf strings from getting inflated by the
	 * conversion (thereby causing a segfault), only copy the upper case
	 * char to dst if its size is <= the original char.
	 */

	if ((len < TclUtfCount(upChar)) || ((upChar & ~0x7FF) == 0xD800)) {
	if (len < TclUtfCount(upChar)) {
	    memmove(dst, src, len);
	    dst += len;
	} else {
	    dst += Tcl_UniCharToUtf(upChar, dst);
	}
	src += len;
    }
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
1354
1355
1356
1357
1358
1359

1360
1361
1362
1363
1364
1365
1366
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
1387
1388
1389
1390
1391

1392
1393
1394
1395
1396
1397
1398
1399







-
+





-
+







-
+








-
+







 *
 * Side effects:
 *	Writes a terminating null after the last converted character.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_Size
Tcl_UtfToLower(
    char *str)			/* String to convert in place. */
{
    int ch, lowChar;
    char *src, *dst;
    size_t len;
    Tcl_Size len;

    /*
     * Iterate over the string until we hit the terminating null.
     */

    src = dst = str;
    while (*src) {
	len = TclUtfToUCS4(src, &ch);
	len = TclUtfToUniChar(src, &ch);
	lowChar = Tcl_UniCharToLower(ch);

	/*
	 * To keep badly formed Utf strings from getting inflated by the
	 * conversion (thereby causing a segfault), only copy the lower case
	 * char to dst if its size is <= the original char.
	 */

	if ((len < TclUtfCount(lowChar)) || ((lowChar & ~0x7FF) == 0xD800)) {
	if (len < TclUtfCount(lowChar)) {
	    memmove(dst, src, len);
	    dst += len;
	} else {
	    dst += Tcl_UniCharToUtf(lowChar, dst);
	}
	src += len;
    }
1383
1384
1385
1386
1387
1388
1389
1390

1391
1392
1393
1394
1395
1396

1397
1398
1399
1400
1401
1402
1403
1404
1405
1406

1407
1408
1409

1410
1411
1412
1413
1414
1415
1416
1417
1418

1419
1420
1421
1422
1423
1424
1425

1426
1427
1428
1429
1430
1431
1432
1416
1417
1418
1419
1420
1421
1422

1423
1424
1425
1426
1427
1428

1429
1430
1431
1432
1433
1434
1435
1436
1437
1438

1439
1440
1441

1442
1443
1444
1445
1446
1447
1448
1449
1450

1451
1452
1453
1454
1455
1456
1457

1458
1459
1460
1461
1462
1463
1464
1465







-
+





-
+









-
+


-
+








-
+






-
+







 *
 * Side effects:
 *	Writes a terminating null after the last converted character.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_Size
Tcl_UtfToTitle(
    char *str)			/* String to convert in place. */
{
    int ch, titleChar, lowChar;
    char *src, *dst;
    size_t len;
    Tcl_Size len;

    /*
     * Capitalize the first character and then lowercase the rest of the
     * characters until we get to a null.
     */

    src = dst = str;

    if (*src) {
	len = TclUtfToUCS4(src, &ch);
	len = TclUtfToUniChar(src, &ch);
	titleChar = Tcl_UniCharToTitle(ch);

	if ((len < TclUtfCount(titleChar)) || ((titleChar & ~0x7FF) == 0xD800)) {
	if (len < TclUtfCount(titleChar)) {
	    memmove(dst, src, len);
	    dst += len;
	} else {
	    dst += Tcl_UniCharToUtf(titleChar, dst);
	}
	src += len;
    }
    while (*src) {
	len = TclUtfToUCS4(src, &ch);
	len = TclUtfToUniChar(src, &ch);
	lowChar = ch;
	/* Special exception for Georgian Asomtavruli chars, no titlecase. */
	if ((unsigned)(lowChar - 0x1C90) >= 0x30) {
	    lowChar = Tcl_UniCharToLower(lowChar);
	}

	if ((len < TclUtfCount(lowChar)) || ((lowChar & ~0x7FF) == 0xD800)) {
	if (len < TclUtfCount(lowChar)) {
	    memmove(dst, src, len);
	    dst += len;
	} else {
	    dst += Tcl_UniCharToUtf(lowChar, dst);
	}
	src += len;
    }
1449
1450
1451
1452
1453
1454
1455
1456
1457


1458
1459


1460
1461
1462
1463
1464
1465
1466
1482
1483
1484
1485
1486
1487
1488


1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501







-
-
+
+


+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclpUtfNcmp2(
    const char *cs,		/* UTF string to compare to ct. */
    const char *ct,		/* UTF string cs is compared to. */
    const void *csPtr,		/* UTF string to compare to ct. */
    const void *ctPtr,		/* UTF string cs is compared to. */
    size_t numBytes)	/* Number of *bytes* to compare. */
{
    const char *cs = (const char *)csPtr;
    const char *ct = (const char *)ctPtr;
    /*
     * We can't simply call 'memcmp(cs, ct, numBytes);' because we need to
     * check for Tcl's \xC0\x80 non-utf-8 null encoding. Otherwise utf-8 lexes
     * fine in the strcmp manner.
     */

    int result = 0;
1482
1483
1484
1485
1486
1487
1488
1489
1490


1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501






































1502
1503
1504
1505

1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546

1547
1548
1549
1550
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
1517
1518
1519
1520
1521
1522
1523


1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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







-
-
+
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+



















-
-
-
-
-
-
-
-
-
-











-
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+












-
-
-
-
-
-
-
-
-
-







}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UtfNcmp --
 *
 *	Compare at most numChars UTF chars of string cs to string ct. Both cs
 *	and ct are assumed to be at least numChars UTF chars long.
 *	Compare at most numChars chars (not bytes) of string cs to string ct. Both cs
 *	and ct are assumed to be at least numChars chars long.
 *
 * Results:
 *	Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclUtfNcmp(
    const char *cs,		/* UTF string to compare to ct. */
    const char *ct,		/* UTF string cs is compared to. */
    size_t numChars)	/* Number of UTF-16 chars to compare. */
{
    unsigned short ch1 = 0, ch2 = 0;

    /*
     * Cannot use 'memcmp(cs, ct, n);' as byte representation of \u0000 (the
     * pair of bytes 0xC0,0x80) is larger than byte representation of \u0001
     * (the byte 0x01.)
     */

    while (numChars-- > 0) {
	/*
	 * n must be interpreted as chars, not bytes. This should be called
	 * only when both strings are of at least n UTF-16 chars long (no need for \0
	 * check)
	 */

	cs += Tcl_UtfToChar16(cs, &ch1);
	ct += Tcl_UtfToChar16(ct, &ch2);
	if (ch1 != ch2) {
	    /* Surrogates always report higher than non-surrogates */
	    if (((ch1 & 0xFC00) == 0xD800)) {
	    if ((ch2 & 0xFC00) != 0xD800) {
		return ch1;
	    }
	    } else if ((ch2 & 0xFC00) == 0xD800) {
		return -ch2;
	    }
	    return (ch1 - ch2);
	}
    }
    return 0;
}

int
Tcl_UtfNcmp(
    const char *cs,		/* UTF string to compare to ct. */
    const char *ct,		/* UTF string cs is compared to. */
    size_t numChars)	/* Number of UTF chars to compare. */
    size_t numChars)	/* Number of chars to compare. */
{
    Tcl_UniChar ch1 = 0, ch2 = 0;

    /*
     * Cannot use 'memcmp(cs, ct, n);' as byte representation of \u0000 (the
     * pair of bytes 0xC0,0x80) is larger than byte representation of \u0001
     * (the byte 0x01.)
     */

    while (numChars-- > 0) {
	/*
	 * n must be interpreted as chars, not bytes. This should be called
	 * only when both strings are of at least n chars long (no need for \0
	 * check)
	 */

	cs += TclUtfToUniChar(cs, &ch1);
	ct += TclUtfToUniChar(ct, &ch2);
	if (ch1 != ch2) {
#if TCL_UTF_MAX <= 3
	    /* Surrogates always report higher than non-surrogates */
	    if (((ch1 & 0xFC00) == 0xD800)) {
	    if ((ch2 & 0xFC00) != 0xD800) {
		return ch1;
	    }
	    } else if ((ch2 & 0xFC00) == 0xD800) {
		return -ch2;
	    }
#endif
	    return (ch1 - ch2);
	}
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UtfNcasecmp --
 *
 *	Compare at most numChars UTF chars of string cs to string ct case
 *	Compare at most numChars chars (not bytes) of string cs to string ct case
 *	insensitive. Both cs and ct are assumed to be at least numChars UTF
 *	chars long.
 *
 * Results:
 *	Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclUtfNcasecmp(
    const char *cs,		/* UTF string to compare to ct. */
    const char *ct,		/* UTF string cs is compared to. */
    size_t numChars)	/* Number of UTF-16 chars to compare. */
{
    unsigned short ch1 = 0, ch2 = 0;

    while (numChars-- > 0) {
	/*
	 * n must be interpreted as UTF-16 chars, not bytes.
	 * This should be called only when both strings are of
	 * at least n UTF-16 chars long (no need for \0 check)
	 */
	cs += Tcl_UtfToChar16(cs, &ch1);
	ct += Tcl_UtfToChar16(ct, &ch2);
	if (ch1 != ch2) {
	    /* Surrogates always report higher than non-surrogates */
	    if (((ch1 & 0xFC00) == 0xD800)) {
	    if ((ch2 & 0xFC00) != 0xD800) {
		return ch1;
	    }
	    } else if ((ch2 & 0xFC00) == 0xD800) {
		return -ch2;
	    }
	    ch1 = Tcl_UniCharToLower(ch1);
	    ch2 = Tcl_UniCharToLower(ch2);
	    if (ch1 != ch2) {
		return (ch1 - ch2);
	    }
	}
    }
    return 0;
}

int
Tcl_UtfNcasecmp(
    const char *cs,		/* UTF string to compare to ct. */
    const char *ct,		/* UTF string cs is compared to. */
    size_t numChars)	/* Number of UTF chars to compare. */
    size_t numChars)	/* Number of chars to compare. */
{
    Tcl_UniChar ch1 = 0, ch2 = 0;

    while (numChars-- > 0) {
	/*
	 * n must be interpreted as chars, not bytes.
	 * This should be called only when both strings are of
	 * at least n chars long (no need for \0 check)
	 */
	cs += TclUtfToUniChar(cs, &ch1);
	ct += TclUtfToUniChar(ct, &ch2);
	if (ch1 != ch2) {
#if TCL_UTF_MAX <= 3
	    /* Surrogates always report higher than non-surrogates */
	    if (((ch1 & 0xFC00) == 0xD800)) {
	    if ((ch2 & 0xFC00) != 0xD800) {
		return ch1;
	    }
	    } else if ((ch2 & 0xFC00) == 0xD800) {
		return -ch2;
	    }
#endif
	    ch1 = Tcl_UniCharToLower(ch1);
	    ch2 = Tcl_UniCharToLower(ch2);
	    if (ch1 != ch2) {
		return (ch1 - ch2);
	    }
	}
    }
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
1706
1707
1708
1709
1710
1711
1712










1713
1714
1715
1716
1717

1718
1719
1720
1721
1722
1723
1724







-
-
-
-
-
-
-
-
-
-





-







{
    Tcl_UniChar ch1 = 0, ch2 = 0;

    while (*cs && *ct) {
	cs += TclUtfToUniChar(cs, &ch1);
	ct += TclUtfToUniChar(ct, &ch2);
	if (ch1 != ch2) {
#if TCL_UTF_MAX <= 3
	    /* Surrogates always report higher than non-surrogates */
	    if (((ch1 & 0xFC00) == 0xD800)) {
	    if ((ch2 & 0xFC00) != 0xD800) {
		return ch1;
	    }
	    } else if ((ch2 & 0xFC00) == 0xD800) {
		return -ch2;
	    }
#endif
	    return ch1 - ch2;
	}
    }
    return UCHAR(*cs) - UCHAR(*ct);
}


/*
 *----------------------------------------------------------------------
 *
 * TclUtfCasecmp --
 *
 *	Compare UTF chars of string cs to string ct case insensitively.
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
1741
1742
1743
1744
1745
1746
1747










1748
1749
1750
1751
1752
1753
1754
1755
1756

1757
1758
1759
1760
1761
1762
1763







-
-
-
-
-
-
-
-
-
-









-







{
    Tcl_UniChar ch1 = 0, ch2 = 0;

    while (*cs && *ct) {
	cs += TclUtfToUniChar(cs, &ch1);
	ct += TclUtfToUniChar(ct, &ch2);
	if (ch1 != ch2) {
#if TCL_UTF_MAX <= 3
	    /* Surrogates always report higher than non-surrogates */
	    if (((ch1 & 0xFC00) == 0xD800)) {
	    if ((ch2 & 0xFC00) != 0xD800) {
		return ch1;
	    }
	    } else if ((ch2 & 0xFC00) == 0xD800) {
		return -ch2;
	    }
#endif
	    ch1 = Tcl_UniCharToLower(ch1);
	    ch2 = Tcl_UniCharToLower(ch2);
	    if (ch1 != ch2) {
		return ch1 - ch2;
	    }
	}
    }
    return UCHAR(*cs) - UCHAR(*ct);
}


/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharToUpper --
 *
 *	Compute the uppercase equivalent of the given Unicode character.
1747
1748
1749
1750
1751
1752
1753
1754

1755
1756
1757
1758
1759
1760
1761
1813
1814
1815
1816
1817
1818
1819

1820
1821
1822
1823
1824
1825
1826
1827







-
+







	if ((mode & 0x02) && (mode != 0x7)) {
	    ch += GetDelta(info);
	}
    }
    /* Clear away extension bits, if any */
    return ch & 0x1FFFFF;
}


/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharToTitle --
 *
 *	Compute the titlecase equivalent of the given Unicode character.
 *
1791
1792
1793
1794
1795
1796
1797






























1798

1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814



1815
1816

1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831


1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846

1847
1848

1849
1850
1851
1852
1853
1854
1855
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+













-
-
-
+
+
+

-
+













-
-
+
+














-
+

-
+







    /* Clear away extension bits, if any */
    return ch & 0x1FFFFF;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Char16Len --
 *
 *	Find the length of a UniChar string. The str input must be null
 *	terminated.
 *
 * Results:
 *	Returns the length of str in UniChars (not bytes).
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
Tcl_Char16Len(
    const unsigned short *uniStr)	/* Unicode string to find length of. */
{
    Tcl_Size len = 0;

    while (*uniStr != '\0') {
	len++;
	uniStr++;
    }
    return len;
}

/*
 *----------------------------------------------------------------------
 *
 * TclUniCharLen --
 * Tcl_UniCharLen --
 *
 *	Find the length of a UniChar string. The str input must be null
 *	terminated.
 *
 * Results:
 *	Returns the length of str in UniChars (not bytes).
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
TclUniCharLen(
    const Tcl_UniChar *uniStr)	/* Unicode string to find length of. */
Tcl_Size
Tcl_UniCharLen(
    const int *uniStr)	/* Unicode string to find length of. */
{
    size_t len = 0;
    Tcl_Size len = 0;

    while (*uniStr != '\0') {
	len++;
	uniStr++;
    }
    return len;
}

/*
 *----------------------------------------------------------------------
 *
 * TclUniCharNcmp --
 *
 *	Compare at most numChars unichars of string ucs to string uct.
 *	Both ucs and uct are assumed to be at least numChars unichars long.
 *	Compare at most numChars chars (not bytes) of string ucs to string uct.
 *	Both ucs and uct are assumed to be at least numChars chars long.
 *
 * Results:
 *	Return <0 if ucs < uct, 0 if ucs == uct, or >0 if ucs > uct.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclUniCharNcmp(
    const Tcl_UniChar *ucs,	/* Unicode string to compare to uct. */
    const Tcl_UniChar *uct,	/* Unicode string ucs is compared to. */
    size_t numChars)	/* Number of unichars to compare. */
    size_t numChars)	/* Number of chars to compare. */
{
#ifdef WORDS_BIGENDIAN
#if defined(WORDS_BIGENDIAN)
    /*
     * We are definitely on a big-endian machine; memcmp() is safe
     */

    return memcmp(ucs, uct, numChars*sizeof(Tcl_UniChar));

#else /* !WORDS_BIGENDIAN */
1867
1868
1869
1870
1871
1872
1873
1874

1875
1876

1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891

1892
1893
1894
1895
1896
1897
1898
1963
1964
1965
1966
1967
1968
1969

1970
1971

1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986

1987
1988
1989
1990
1991
1992
1993
1994







-
+

-
+














-
+







}

/*
 *----------------------------------------------------------------------
 *
 * TclUniCharNcasecmp --
 *
 *	Compare at most numChars unichars of string ucs to string uct case
 *	Compare at most numChars chars (not bytes) of string ucs to string uct case
 *	insensitive. Both ucs and uct are assumed to be at least numChars
 *	unichars long.
 *	chars long.
 *
 * Results:
 *	Return <0 if ucs < uct, 0 if ucs == uct, or >0 if ucs > uct.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclUniCharNcasecmp(
    const Tcl_UniChar *ucs,	/* Unicode string to compare to uct. */
    const Tcl_UniChar *uct,	/* Unicode string ucs is compared to. */
    size_t numChars)	/* Number of unichars to compare. */
    size_t numChars)	/* Number of chars to compare. */
{
    for ( ; numChars != 0; numChars--, ucs++, uct++) {
	if (*ucs != *uct) {
	    Tcl_UniChar lcs = Tcl_UniCharToLower(*ucs);
	    Tcl_UniChar lct = Tcl_UniCharToLower(*uct);

	    if (lcs != lct) {
1974
1975
1976
1977
1978
1979
1980
1981

1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
2070
2071
2072
2073
2074
2075
2076

2077






2078
2079
2080
2081
2082
2083
2084







-
+
-
-
-
-
-
-







int
Tcl_UniCharIsControl(
    int ch)			/* Unicode character to test. */
{
    if (UNICODE_OUT_OF_RANGE(ch)) {
	/* Clear away extension bits, if any */
	ch &= 0x1FFFFF;
	if ((ch == 0xE0001) || ((ch >= 0xE0020) && (ch <= 0xE007F))) {
	return ((ch == 0xE0001) || ((unsigned)(ch - 0xE0020) <= 0x5F));
	    return 1;
	}
	if ((ch >= 0xF0000) && ((ch & 0xFFFF) <= 0xFFFD)) {
	    return 1;
	}
	return 0;
    }
    return ((CONTROL_BITS >> GetCategory(ch)) & 1);
}

/*
 *----------------------------------------------------------------------
 *
2421
2422
2423
2424
2425
2426
2427
2428

2429
2430
2431

2432
2433
2434
2435
2436
2437
2438
2511
2512
2513
2514
2515
2516
2517

2518
2519
2520

2521
2522
2523
2524
2525
2526
2527
2528







-
+


-
+







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

int
TclUniCharMatch(
    const Tcl_UniChar *string,	/* Unicode String. */
    size_t strLen,			/* Length of String */
    Tcl_Size strLen,		/* Length of String */
    const Tcl_UniChar *pattern,	/* Pattern, which may contain special
				 * characters. */
    size_t ptnLen,			/* Length of Pattern */
    Tcl_Size ptnLen,		/* Length of Pattern */
    int nocase)			/* 0 for case sensitive, 1 for insensitive */
{
    const Tcl_UniChar *stringEnd, *patternEnd;
    Tcl_UniChar p;

    stringEnd = string + strLen;
    patternEnd = pattern + ptnLen;
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
2678
2679
2680
2681
2682
2683
2684




















































2685
2686
2687
2688
2689
2690
2691







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	    return 0;
	}
	string++;
	pattern++;
    }
}

/*
 *---------------------------------------------------------------------------
 *
 * TclUtfToUCS4 --
 *
 *	Extract the 4-byte codepoint from the leading bytes of the
 *	Modified UTF-8 string "src".  This is a utility routine to
 *	contain the surrogate gymnastics in one place.
 *
 *	The caller must ensure that the source buffer is long enough that this
 *	routine does not run off the end and dereference non-existent memory
 *	looking for trail bytes. If the source buffer is known to be '\0'
 *	terminated, this cannot happen. Otherwise, the caller should call
 *	Tcl_UtfCharComplete() before calling this routine to ensure that
 *	enough bytes remain in the string.
 *
 * Results:
 *	*usc4Ptr is filled with the UCS4 code point, and the return value is
 *	the number of bytes from the UTF-8 string that were consumed.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

#if TCL_UTF_MAX <= 3
int
TclUtfToUCS4(
    const char *src,	/* The UTF-8 string. */
    int *ucs4Ptr)	/* Filled with the UCS4 codepoint represented
			 * by the UTF-8 string. */
{
    /* Make use of the #undef Tcl_UtfToUniChar above, which already handles UCS4. */
    return Tcl_UtfToUniChar(src, ucs4Ptr);
}

int
TclUniCharToUCS4(
    const Tcl_UniChar *src,	/* The Tcl_UniChar string. */
    int *ucs4Ptr)	/* Filled with the UCS4 codepoint represented
			 * by the Tcl_UniChar string. */
{
    if (((src[0] & 0xFC00) == 0xD800) && ((src[1] & 0xFC00) == 0xDC00)) {
	*ucs4Ptr = (((src[0] & 0x3FF) << 10) | (src[01] & 0x3FF)) + 0x10000;
	return 2;
    }
    *ucs4Ptr = src[0];
    return 1;
}
#endif

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclUtil.c.

1
2
3
4
5
6
7
8
9



10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22






-
-
-
+
+
+





+







/*
 * tclUtil.c --
 *
 *	This file contains utility functions that are used by many Tcl
 *	commands.
 *
 * Copyright (c) 1987-1993 The Regents of the University of California.
 * Copyright (c) 1994-1998 Sun Microsystems, Inc.
 * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
 * Copyright © 1987-1993 The Regents of the University of California.
 * Copyright © 1994-1998 Sun Microsystems, Inc.
 * Copyright © 2001 Kevin B. Kenny. All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include <assert.h>
#include "tclInt.h"
#include "tclParse.h"
#include "tclStringTrim.h"
#include "tclTomMath.h"
#include <math.h>

/*
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
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







-
-
+
+

-
+


-
+

-
+

-
+






-
+










-
+
+


+
+
+
+
+
+
+



















-
+







#define CONVERT_ANY	16

/*
 * Prototypes for functions defined later in this file.
 */

static void		ClearHash(Tcl_HashTable *tablePtr);
static void		FreeProcessGlobalValue(ClientData clientData);
static void		FreeThreadHash(ClientData clientData);
static void		FreeProcessGlobalValue(void *clientData);
static void		FreeThreadHash(void *clientData);
static int		GetEndOffsetFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    size_t endValue, Tcl_WideInt *indexPtr);
			    Tcl_WideInt endValue, Tcl_WideInt *indexPtr);
static Tcl_HashTable *	GetThreadHash(Tcl_ThreadDataKey *keyPtr);
static int		GetWideForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    size_t endValue, Tcl_WideInt *widePtr);
			    Tcl_WideInt endValue, Tcl_WideInt *widePtr);
static int		FindElement(Tcl_Interp *interp, const char *string,
			    int stringLength, const char *typeStr,
			    Tcl_Size stringLength, const char *typeStr,
			    const char *typeCode, const char **elementPtr,
			    const char **nextPtr, size_t *sizePtr,
			    const char **nextPtr, Tcl_Size *sizePtr,
			    int *literalPtr);
/*
 * The following is the Tcl object type definition for an object that
 * represents a list index in the form, "end-offset". It is used as a
 * performance optimization in Tcl_GetIntForIndex. The internal rep is
 * stored directly in the wideValue, so no memory management is required
 * for it. This is a caching intrep, keeping the result of a parse
 * for it. This is a caching internalrep, keeping the result of a parse
 * around. This type is only created from a pre-existing string, so an
 * updateStringProc will never be called and need not exist. The type
 * is unregistered, so has no need of a setFromAnyProc either.
 */

static const Tcl_ObjType endOffsetType = {
    "end-offset",			/* name */
    NULL,				/* freeIntRepProc */
    NULL,				/* dupIntRepProc */
    NULL,				/* updateStringProc */
    NULL				/* setFromAnyProc */
    NULL,				/* setFromAnyProc */
    TCL_OBJTYPE_V1(TclLengthOne)
};

Tcl_Size
TclLengthOne(
    TCL_UNUSED(Tcl_Obj *))
{
    return 1;
}

/*
 *	*	STRING REPRESENTATION OF LISTS	*	*	*
 *
 * The next several routines implement the conversions of strings to and from
 * Tcl lists. To understand their operation, the rules of parsing and
 * generating the string representation of lists must be known.  Here we
 * describe them in one place.
 *
 * A list is made up of zero or more elements. Any string is a list if it is
 * made up of alternating substrings of element-separating ASCII whitespace
 * and properly formatted elements.
 *
 * The ASCII characters which can make up the whitespace between list elements
 * are:
 *
 *	\u0009	\t	TAB
 *	\u000A	\n	NEWLINE
 *	\u000B	\v	VERTICAL TAB
 *	\u000C	\f	FORM FEED
 * 	\u000D	\r	CARRIAGE RETURN
 *	\u000D	\r	CARRIAGE RETURN
 *	\u0020		SPACE
 *
 * NOTE: differences between this and other places where Tcl defines a role
 * for "whitespace".
 *
 *	* Unlike command parsing, here NEWLINE is just another whitespace
 *	  character; its role as a command terminator in a script has no
263
264
265
266
267
268
269
270

271
272
273
274
275
276
277
272
273
274
275
276
277
278

279
280
281
282
283
284
285
286







-
+







 *   characters that have special meaning during script evaluation need
 *   special treatment when canonical lists are produced:
 *
 *	* Whitespace between elements may not include NEWLINE.
 *	* The command terminating character,
 *		\u003b	;	SEMICOLON
 *	  must be BRACEd, QUOTEd, or escaped so that it does not terminate the
 * 	  command prematurely.
 *	  command prematurely.
 *	* Any of the characters that begin substitutions in scripts,
 *		\u0024	$	DOLLAR
 *		\u005b	[	OPEN BRACKET
 *		\u005c	\	BACKSLASH
 *	  need to be BRACEd or escaped.
 *	* In any list where the first character of the first element is
 *		\u0023	#	HASH
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
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







-
-
-
-
+
+
+
+












-
+


-
+


-
+







/*
 *----------------------------------------------------------------------
 *
 * TclMaxListLength --
 *
 *	Given 'bytes' pointing to 'numBytes' bytes, scan through them and
 *	count the number of whitespace runs that could be list element
 *	separators. If 'numBytes' is -1, scan to the terminating '\0'. Not a
 *	full list parser. Typically used to get a quick and dirty overestimate
 *	of length size in order to allocate space for an actual list parser to
 *	operate with.
 *	separators. If 'numBytes' is TCL_INDEX_NONE, scan to the terminating
 *	'\0'. Not a full list parser. Typically used to get a quick and dirty
 *	overestimate of length size in order to allocate space for an actual
 *	list parser to operate with.
 *
 * Results:
 *	Returns the largest number of list elements that could possibly be in
 *	this string, interpreted as a Tcl list. If 'endPtr' is not NULL,
 *	writes a pointer to the end of the string scanned there.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_Size
TclMaxListLength(
    const char *bytes,
    size_t numBytes,
    Tcl_Size numBytes,
    const char **endPtr)
{
    size_t count = 0;
    Tcl_Size count = 0;

    if ((numBytes == 0) || ((numBytes == TCL_INDEX_NONE) && (*bytes == '\0'))) {
	/* Empty string case - quick exit */
	goto done;
    }

    /*
489
490
491
492
493
494
495
496

497
498
499
500
501
502

503
504
505
506
507
508
509
498
499
500
501
502
503
504

505
506
507
508
509
510

511
512
513
514
515
516
517
518







-
+





-
+







TclFindElement(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting. If
				 * NULL, then no error message is left after
				 * errors. */
    const char *list,		/* Points to the first byte of a string
				 * containing a Tcl list with zero or more
				 * elements (possibly in braces). */
    int listLength,		/* Number of bytes in the list's string. */
    Tcl_Size listLength,	/* Number of bytes in the list's string. */
    const char **elementPtr,	/* Where to put address of first significant
				 * character in first element of list. */
    const char **nextPtr,	/* Fill in with location of character just
				 * after all white space following end of
				 * argument (next arg or end of list). */
    size_t *sizePtr,		/* If non-zero, fill in with size of
    Tcl_Size *sizePtr,		/* If non-zero, fill in with size of
				 * element. */
    int *literalPtr)		/* If non-zero, fill in with non-zero/zero to
				 * indicate that the substring of *sizePtr
				 * bytes starting at **elementPtr is/is not
				 * the literal list element and therefore
				 * does not/does require a call to
				 * TclCopyAndCollapse() by the caller. */
517
518
519
520
521
522
523
524

525
526
527
528
529
530
531

532
533
534
535
536
537
538
526
527
528
529
530
531
532

533
534
535
536
537
538
539

540
541
542
543
544
545
546
547







-
+






-
+







    Tcl_Interp *interp,		/* Interpreter to use for error reporting. If
				 * NULL, then no error message is left after
				 * errors. */
    const char *dict,		/* Points to the first byte of a string
				 * containing a Tcl dictionary with zero or
				 * more keys and values (possibly in
				 * braces). */
    int dictLength,		/* Number of bytes in the dict's string. */
    Tcl_Size dictLength,	/* Number of bytes in the dict's string. */
    const char **elementPtr,	/* Where to put address of first significant
				 * character in the first element (i.e., key
				 * or value) of dict. */
    const char **nextPtr,	/* Fill in with location of character just
				 * after all white space following end of
				 * element (next arg or end of list). */
    size_t *sizePtr,		/* If non-zero, fill in with size of
    Tcl_Size *sizePtr,		/* If non-zero, fill in with size of
				 * element. */
    int *literalPtr)		/* If non-zero, fill in with non-zero/zero to
				 * indicate that the substring of *sizePtr
				 * bytes starting at **elementPtr is/is not
				 * the literal key or value and therefore
				 * does not/does require a call to
				 * TclCopyAndCollapse() by the caller. */
546
547
548
549
550
551
552
553

554
555
556
557
558
559
560
561
562
563

564
565
566
567
568
569
570
571
572
573
574
575

576
577
578


579
580
581
582
583
584
585
555
556
557
558
559
560
561

562
563
564
565
566
567
568
569
570
571

572
573
574
575
576
577
578
579
580
581
582
583

584
585


586
587
588
589
590
591
592
593
594







-
+









-
+











-
+

-
-
+
+







    Tcl_Interp *interp,		/* Interpreter to use for error reporting. If
				 * NULL, then no error message is left after
				 * errors. */
    const char *string,		/* Points to the first byte of a string
				 * containing a Tcl list or dictionary with
				 * zero or more elements (possibly in
				 * braces). */
    int stringLength,		/* Number of bytes in the string. */
    Tcl_Size stringLength,	/* Number of bytes in the string. */
    const char *typeStr,	/* The name of the type of thing we are
				 * parsing, for error messages. */
    const char *typeCode,	/* The type code for thing we are parsing, for
				 * error messages. */
    const char **elementPtr,	/* Where to put address of first significant
				 * character in first element. */
    const char **nextPtr,	/* Fill in with location of character just
				 * after all white space following end of
				 * argument (next arg or end of list/dict). */
    size_t *sizePtr,		/* If non-zero, fill in with size of
    Tcl_Size *sizePtr,		/* If non-zero, fill in with size of
				 * element. */
    int *literalPtr)		/* If non-zero, fill in with non-zero/zero to
				 * indicate that the substring of *sizePtr
				 * bytes starting at **elementPtr is/is not
				 * the literal list/dict element and therefore
				 * does not/does require a call to
				 * TclCopyAndCollapse() by the caller. */
{
    const char *p = string;
    const char *elemStart;	/* Points to first byte of first element. */
    const char *limit;		/* Points just after list/dict's last byte. */
    int openBraces = 0;		/* Brace nesting level during parse. */
    Tcl_Size openBraces = 0;	/* Brace nesting level during parse. */
    int inQuotes = 0;
    int size = 0;
    size_t numChars;
    Tcl_Size size = 0;
    Tcl_Size numChars;
    int literal = 1;
    const char *p2;

    /*
     * Skim off leading white space and check for an opening brace or quote.
     * We treat embedded NULLs in the list/dict as bytes belonging to a list
     * element (or dictionary key or value).
645
646
647
648
649
650
651
652

653
654
655
656
657
658
659
654
655
656
657
658
659
660

661
662
663
664
665
666
667
668







-
+







			    && (p2 < p+20)) {
			p2++;
		    }
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "%s element in braces followed by \"%.*s\" "
			    "instead of space", typeStr, (int) (p2-p), p));
		    Tcl_SetErrorCode(interp, "TCL", "VALUE", typeCode, "JUNK",
			    NULL);
			    (char *)NULL);
		}
		return TCL_ERROR;
	    }
	    break;

	    /*
	     * Backslash: skip over everything up to the end of the backslash
697
698
699
700
701
702
703
704

705
706
707
708
709
710
711
706
707
708
709
710
711
712

713
714
715
716
717
718
719
720







-
+







			    && (p2 < p+20)) {
			p2++;
		    }
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "%s element in quotes followed by \"%.*s\" "
			    "instead of space", typeStr, (int) (p2-p), p));
		    Tcl_SetErrorCode(interp, "TCL", "VALUE", typeCode, "JUNK",
			    NULL);
			    (char *)NULL);
		}
		return TCL_ERROR;
	    }
	    break;

	default:
	    if (TclIsSpaceProcM(*p)) {
730
731
732
733
734
735
736
737

738
739
740
741
742
743
744
745

746
747
748
749
750
751
752
739
740
741
742
743
744
745

746
747
748
749
750
751
752
753

754
755
756
757
758
759
760
761







-
+







-
+








    if (p == limit) {
	if (openBraces != 0) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"unmatched open brace in %s", typeStr));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", typeCode, "BRACE",
			NULL);
			(char *)NULL);
	    }
	    return TCL_ERROR;
	} else if (inQuotes) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"unmatched open quote in %s", typeStr));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", typeCode, "QUOTE",
			NULL);
			(char *)NULL);
	    }
	    return TCL_ERROR;
	}
	size = (p - elemStart);
    }

  done:
779
780
781
782
783
784
785
786

787
788

789
790
791
792

793
794
795
796
797

798
799


800

801
802
803
804
805
806
807
788
789
790
791
792
793
794

795
796

797
798
799
800

801
802
803
804
805
806
807


808
809
810
811
812
813
814
815
816
817
818







-
+

-
+



-
+





+
-
-
+
+

+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
TclCopyAndCollapse(
    size_t count,			/* Number of byte to copy from src. */
    Tcl_Size count,		/* Number of byte to copy from src. */
    const char *src,		/* Copy from here... */
    char *dst)			/* ... to here. */
{
    size_t newCount = 0;
    Tcl_Size newCount = 0;

    while (count > 0) {
	char c = *src;

	if (c == '\\') {
	    char buf[4] = "";
	    size_t numRead;
	    size_t backslashCount = TclParseBackslash(src, count, &numRead, dst);
	    Tcl_Size numRead;
	    Tcl_Size backslashCount = TclParseBackslash(src, count, &numRead, buf);

	    memcpy(dst, buf, backslashCount);
	    dst += backslashCount;
	    newCount += backslashCount;
	    src += numRead;
	    count -= numRead;
	} else {
	    *dst = c;
	    dst++;
838
839
840
841
842
843
844

845
846
847
848
849
850

851
852
853
854
855
856

857

858
859
860
861
862
863
864
865
866
867
868

869
870
871
872
873
874
875
849
850
851
852
853
854
855
856
857
858
859
860
861

862
863
864
865
866
867
868
869

870

871
872
873
874
875
876
877
878
879

880
881
882
883
884
885
886
887







+





-
+






+
-
+
-









-
+







 *
 * Side effects:
 *	Memory is allocated.
 *
 *----------------------------------------------------------------------
 */

#undef Tcl_SplitList
int
Tcl_SplitList(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting. If
				 * NULL, no error message is left. */
    const char *list,		/* Pointer to string with list structure. */
    int *argcPtr,		/* Pointer to location to fill in with the
    Tcl_Size *argcPtr,		/* Pointer to location to fill in with the
				 * number of elements in the list. */
    const char ***argvPtr)	/* Pointer to place to store pointer to array
				 * of pointers to list elements. */
{
    const char **argv, *end, *element;
    char *p;
    int result;
    int length, size, i, result;
    Tcl_Size length, size, i, elSize;
    size_t elSize;

    /*
     * Allocate enough space to work in. A (const char *) for each (possible)
     * list element plus one more for terminating NULL, plus as many bytes as
     * in the original string value, plus one more for a terminating '\0'.
     * Space used to hold element separating white space in the original
     * string gets re-purposed to hold '\0' characters in the argv array.
     */

    size = TclMaxListLength(list, -1, &end) + 1;
    size = TclMaxListLength(list, TCL_INDEX_NONE, &end) + 1;
    length = end - list;
    argv = (const char **)Tcl_Alloc((size * sizeof(char *)) + length + 1);

    for (i = 0, p = ((char *) argv) + size*sizeof(char *);
	    *list != 0;  i++) {
	const char *prevList = list;
	int literal;
886
887
888
889
890
891
892
893

894
895
896
897
898
899
900
898
899
900
901
902
903
904

905
906
907
908
909
910
911
912







-
+







	}
	if (i >= size) {
	    Tcl_Free((void *)argv);
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"internal error in Tcl_SplitList", -1));
		Tcl_SetErrorCode(interp, "TCL", "INTERNAL", "Tcl_SplitList",
			NULL);
			(char *)NULL);
	    }
	    return TCL_ERROR;
	}
	argv[i] = p;
	if (literal) {
	    memcpy(p, element, elSize);
	    p += elSize;
928
929
930
931
932
933
934
935

936
937
938
939
940
941

942
943
944
945
946
947
948
949
950
951
952
953


954
955
956
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
940
941
942
943
944
945
946

947
948
949
950
951
952

953
954
955
956
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







-
+





-
+










-
-
+
+













-
+


-
+




-
+













-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
Tcl_ScanElement(
    const char *src,	/* String to convert to list element. */
    int *flagPtr)	/* Where to store information to guide
			 * Tcl_ConvertCountedElement. */
{
    return Tcl_ScanCountedElement(src, -1, flagPtr);
    return Tcl_ScanCountedElement(src, TCL_INDEX_NONE, flagPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ScanCountedElement --
 *
 *	This function is a companion function to Tcl_ConvertCountedElement. It
 *	scans a string to see what needs to be done to it (e.g. add
 *	backslashes or enclosing braces) to make the string into a valid Tcl
 *	list element. If length is -1, then the string is scanned from src up
 *	to the first null byte.
 *	list element. If length is TCL_INDEX_NONE, then the string is scanned
 *	from src up to the first null byte.
 *
 * Results:
 *	The return value is an overestimate of the number of bytes that will
 *	be needed by Tcl_ConvertCountedElement to produce a valid list element
 *	from src. The word at *flagPtr is filled in with a value needed by
 *	Tcl_ConvertCountedElement when doing the actual conversion.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
Tcl_ScanCountedElement(
    const char *src,		/* String to convert to Tcl list element. */
    size_t length,		/* Number of bytes in src, or -1. */
    Tcl_Size length,		/* Number of bytes in src, or TCL_INDEX_NONE. */
    int *flagPtr)		/* Where to store information to guide
				 * Tcl_ConvertElement. */
{
    char flags = CONVERT_ANY;
    int numBytes = TclScanElement(src, length, &flags);
    Tcl_Size numBytes = TclScanElement(src, length, &flags);

    *flagPtr = flags;
    return numBytes;
}

/*
 *----------------------------------------------------------------------
 *
 * TclScanElement --
 *
 *	This function is a companion function to TclConvertElement. It scans a
 *	string to see what needs to be done to it (e.g. add backslashes or
 *	enclosing braces) to make the string into a valid Tcl list element. If
 *	length is -1, then the string is scanned from src up to the first null
 *	length is TCL_INDEX_NONE, then the string is scanned from src up to the first null
 *	byte. A NULL value for src is treated as an empty string. The incoming
 *	value of *flagPtr is a report from the caller what additional flags it
 *	will pass to TclConvertElement().
 *
 * Results:
 *	The recommended formatting mode for the element is determined and a
 *	value is written to *flagPtr indicating that recommendation. This
1004
1005
1006
1007
1008
1009
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
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







-
+


-
+




-
+




-
+


-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
TclScanElement(
    const char *src,		/* String to convert to Tcl list element. */
    size_t length,		/* Number of bytes in src, or -1. */
    Tcl_Size length,		/* Number of bytes in src, or TCL_INDEX_NONE. */
    char *flagPtr)		/* Where to store information to guide
				 * Tcl_ConvertElement. */
{
    const char *p = src;
    int nestingLevel = 0;	/* Brace nesting count */
    Tcl_Size nestingLevel = 0;	/* Brace nesting count */
    int forbidNone = 0;		/* Do not permit CONVERT_NONE mode. Something
				 * needs protection or escape. */
    int requireEscape = 0;	/* Force use of CONVERT_ESCAPE mode.  For some
				 * reason bare or brace-quoted form fails. */
    int extra = 0;		/* Count of number of extra bytes needed for
    Tcl_Size extra = 0;		/* Count of number of extra bytes needed for
				 * formatted element, assuming we use escape
				 * sequences in formatting. */
    size_t bytesNeeded;		/* Buffer length computed to complete the
    Tcl_Size bytesNeeded;		/* Buffer length computed to complete the
				 * element formatting in the selected mode. */
#if COMPAT
    int preferEscape = 0;	/* Use preferences to track whether to use */
    int preferBrace = 0;	/* CONVERT_MASK mode. */
    int braceCount = 0;		/* Count of all braces '{' '}' seen. */
#endif /* COMPAT */

1081
1082
1083
1084
1085
1086
1087
1088
1089

1090
1091
1092
1093
1094
1095
1096
1093
1094
1095
1096
1097
1098
1099


1100
1101
1102
1103
1104
1105
1106
1107







-
-
+







	    nestingLevel++;
	    break;
	case '}':	/* TYPE_BRACE */
#if COMPAT
	    braceCount++;
#endif /* COMPAT */
	    extra++;				/* Escape '}' => '\}' */
	    nestingLevel--;
	    if (nestingLevel < 0) {
	    if (nestingLevel-- < 1) {
		/*
		 * Unbalanced braces!  Cannot format with brace quoting.
		 */

		requireEscape = 1;
	    }
	    break;
1158
1159
1160
1161
1162
1163
1164
1165

1166
1167
1168
1169
1170

1171
1172
1173
1174
1175
1176
1177
1169
1170
1171
1172
1173
1174
1175

1176
1177
1178
1179
1180

1181
1182
1183
1184
1185
1186
1187
1188







-
+




-
+







#if COMPAT
		preferBrace = 1;
#endif
	    }
	    break;
	}
      }
	length -= (length+1 > 1);
	length -= (length > 0);
	p++;
    }

  endOfString:
    if (nestingLevel != 0) {
    if (nestingLevel > 0) {
	/*
	 * Unbalanced braces!  Cannot format with brace quoting.
	 */

	requireEscape = 1;
    }

1222
1223
1224
1225
1226
1227
1228
1229

1230
1231
1232
1233
1234
1235
1236
1233
1234
1235
1236
1237
1238
1239

1240
1241
1242
1243
1244
1245
1246
1247







-
+








#if COMPAT
	if (preferEscape && !preferBrace) {
	    /*
	     * If we are quoting solely due to ] or internal " characters use
	     * the CONVERT_MASK mode where we escape all special characters
	     * except for braces. "extra" counted space needed to escape
	     * braces too, so substract "braceCount" to get our actual needs.
	     * braces too, so subtract "braceCount" to get our actual needs.
	     */

	    bytesNeeded += (extra - braceCount);
	    /* Make room to escape leading #, if needed. */
	    if ((*src == '#') && !(*flagPtr & TCL_DONT_QUOTE_HASH)) {
		bytesNeeded++;
	    }
1306
1307
1308
1309
1310
1311
1312
1313

1314
1315
1316
1317
1318
1319

1320
1321
1322
1323
1324
1325
1326
1317
1318
1319
1320
1321
1322
1323

1324
1325
1326
1327
1328
1329

1330
1331
1332
1333
1334
1335
1336
1337







-
+





-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
Tcl_ConvertElement(
    const char *src,	/* Source information for list element. */
    char *dst,		/* Place to put list-ified element. */
    int flags)		/* Flags produced by Tcl_ScanElement. */
{
    return Tcl_ConvertCountedElement(src, -1, dst, flags);
    return Tcl_ConvertCountedElement(src, TCL_INDEX_NONE, dst, flags);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ConvertCountedElement --
 *
1336
1337
1338
1339
1340
1341
1342
1343

1344
1345
1346

1347
1348
1349
1350

1351
1352
1353
1354
1355
1356
1357
1347
1348
1349
1350
1351
1352
1353

1354
1355
1356

1357
1358
1359
1360

1361
1362
1363
1364
1365
1366
1367
1368







-
+


-
+



-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
Tcl_ConvertCountedElement(
    const char *src,	/* Source information for list element. */
    size_t length,		/* Number of bytes in src, or -1. */
    Tcl_Size length,		/* Number of bytes in src, or TCL_INDEX_NONE. */
    char *dst,			/* Place to put list-ified element. */
    int flags)			/* Flags produced by Tcl_ScanElement. */
{
    size_t numBytes = TclConvertElement(src, length, dst, flags);
    Tcl_Size numBytes = TclConvertElement(src, length, dst, flags);
    dst[numBytes] = '\0';
    return numBytes;
}

/*
 *----------------------------------------------------------------------
 *
1369
1370
1371
1372
1373
1374
1375
1376

1377
1378
1379

1380
1381
1382
1383
1384
1385
1386
1380
1381
1382
1383
1384
1385
1386

1387
1388
1389

1390
1391
1392
1393
1394
1395
1396
1397







-
+


-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
TclConvertElement(
    const char *src,	/* Source information for list element. */
    size_t length,		/* Number of bytes in src, or -1. */
    Tcl_Size length,		/* Number of bytes in src, or TCL_INDEX_NONE. */
    char *dst,			/* Place to put list-ified element. */
    int flags)			/* Flags produced by Tcl_ScanElement. */
{
    int conversion = flags & CONVERT_MASK;
    char *p = dst;

    /*
1407
1408
1409
1410
1411
1412
1413
1414

1415
1416
1417
1418
1419
1420
1421
1418
1419
1420
1421
1422
1423
1424

1425
1426
1427
1428
1429
1430
1431
1432







-
+








    if ((*src == '#') && !(flags & TCL_DONT_QUOTE_HASH)) {
	if (conversion == CONVERT_ESCAPE) {
	    p[0] = '\\';
	    p[1] = '#';
	    p += 2;
	    src++;
	    length -= (length+1 > 1);
	    length -= (length > 0);
	} else {
	    conversion = CONVERT_BRACE;
	}
    }

    /*
     * No escape or quoting needed.  Copy the literal string value.
1448
1449
1450
1451
1452
1453
1454
1455

1456
1457
1458
1459
1460
1461
1462
1463
1464

1465
1466
1467
1468
1469
1470
1471
1459
1460
1461
1462
1463
1464
1465

1466
1467
1468
1469
1470
1471
1472
1473
1474

1475
1476
1477
1478
1479
1480
1481
1482







-
+








-
+







	    }
	} else {
	    memcpy(p, src, length);
	    p += length;
	}
	*p = '}';
	p++;
	return (size_t)(p - dst);
	return (p - dst);
    }

    /* conversion == CONVERT_ESCAPE or CONVERT_MASK */

    /*
     * Formatted string is original string converted to escape sequences.
     */

    for ( ; length; src++, length -= (length+1 > 1)) {
    for ( ; length; src++, length -= (length > 0)) {
	switch (*src) {
	case ']':
	case '[':
	case '$':
	case ';':
	case ' ':
	case '\\':
1511
1512
1513
1514
1515
1516
1517
1518

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

1535
1536
1537
1538
1539
1540
1541
1522
1523
1524
1525
1526
1527
1528

1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544

1545
1546
1547
1548
1549
1550
1551
1552







-
+















-
+







	    *p = '\\';
	    p++;
	    *p = 'v';
	    p++;
	    continue;
	case '\0':
	    if (length == TCL_INDEX_NONE) {
		return (size_t)(p - dst);
		return (p - dst);
	    }

	    /*
	     * If we reach this point, there's an embedded NULL in the string
	     * range being processed, which should not happen when the
	     * encoding rules for Tcl strings are properly followed.  If the
	     * day ever comes when we stop tolerating such things, this is
	     * where to put the Tcl_Panic().
	     */

	    break;
	}
	*p = *src;
	p++;
    }
    return (size_t)(p - dst);
    return (p - dst);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Merge --
 *
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
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







-
+




-
+








+
-
+
+
+
















-
+











-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

char *
Tcl_Merge(
    int argc,			/* How many strings to merge. */
    Tcl_Size argc,			/* How many strings to merge. */
    const char *const *argv)	/* Array of string values. */
{
#define LOCAL_SIZE 64
    char localFlags[LOCAL_SIZE], *flagPtr = NULL;
    int i;
    Tcl_Size i;
    size_t bytesNeeded = 0;
    char *result, *dst;

    /*
     * Handle empty list case first, so logic of the general case can be
     * simpler.
     */

    if (argc <= 0) {
    if (argc == 0) {
	if (argc < 0) {
	    Tcl_Panic("Tcl_Merge called with negative argc (%" TCL_SIZE_MODIFIER "d)", argc);
	}
	result = (char *)Tcl_Alloc(1);
	result[0] = '\0';
	return result;
    }

    /*
     * Pass 1: estimate space, gather flags.
     */

    if (argc <= LOCAL_SIZE) {
	flagPtr = localFlags;
    } else {
	flagPtr = (char *)Tcl_Alloc(argc);
    }
    for (i = 0; i < argc; i++) {
	flagPtr[i] = ( i ? TCL_DONT_QUOTE_HASH : 0 );
	bytesNeeded += TclScanElement(argv[i], -1, &flagPtr[i]);
	bytesNeeded += TclScanElement(argv[i], TCL_INDEX_NONE, &flagPtr[i]);
    }
    bytesNeeded += argc;

    /*
     * Pass two: copy into the result area.
     */

    result = (char *)Tcl_Alloc(bytesNeeded);
    dst = result;
    for (i = 0; i < argc; i++) {
	flagPtr[i] |= ( i ? TCL_DONT_QUOTE_HASH : 0 );
	dst += TclConvertElement(argv[i], -1, dst, flagPtr[i]);
	dst += TclConvertElement(argv[i], TCL_INDEX_NONE, dst, flagPtr[i]);
	*dst = ' ';
	dst++;
    }
    dst[-1] = 0;

    if (flagPtr != localFlags) {
	Tcl_Free(flagPtr);
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
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







-
+


-
+



-
+

















-
+

-
+


-
+







-
+





-
-
+
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
TclTrimRight(
    const char *bytes,	/* String to be trimmed... */
    size_t numBytes,	/* ...and its length in bytes */
    Tcl_Size numBytes,	/* ...and its length in bytes */
			/* Calls to TclUtfToUniChar() in this routine
			 * rely on (bytes[numBytes] == '\0'). */
    const char *trim,	/* String of trim characters... */
    size_t numTrim)	/* ...and its length in bytes */
    Tcl_Size numTrim)	/* ...and its length in bytes */
			/* Calls to TclUtfToUniChar() in this routine
			 * rely on (trim[numTrim] == '\0'). */
{
    const char *pp, *p = bytes + numBytes;
    int ch1, ch2;

    /* Empty strings -> nothing to do */
    if ((numBytes == 0) || (numTrim == 0)) {
	return 0;
    }

    /*
     * Outer loop: iterate over string to be trimmed.
     */

    do {
	const char *q = trim;
    size_t pInc = 0, bytesLeft = numTrim;
	Tcl_Size pInc = 0, bytesLeft = numTrim;

	pp = TclUtfPrev(p, bytes);
	pp = Tcl_UtfPrev(p, bytes);
	do {
	    pp += pInc;
 	    pInc = TclUtfToUCS4(pp, &ch1);
	    pInc = TclUtfToUniChar(pp, &ch1);
	} while (pp + pInc < p);

	/*
	 * Inner loop: scan trim string for match to current character.
	 */

	do {
	    size_t qInc = TclUtfToUCS4(q, &ch2);
	    pInc = TclUtfToUniChar(q, &ch2);

	    if (ch1 == ch2) {
		break;
	    }

	    q += qInc;
	    bytesLeft -= qInc;
	    q += pInc;
	    bytesLeft -= pInc;
	} while (bytesLeft);

	if (bytesLeft == 0) {
	    /*
	     * No match; trim task done; *p is last non-trimmed char.
	     */

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
1749
1750
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
1749

1750
1751
1752
1753
1754
1755
1756

1757
1758
1759
1760
1761
1762
1763
1764







-
+


-
+



-
+




-
+











-
+

-
+






-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
TclTrimLeft(
    const char *bytes,	/* String to be trimmed... */
    size_t numBytes,	/* ...and its length in bytes */
    Tcl_Size numBytes,	/* ...and its length in bytes */
			/* Calls to TclUtfToUniChar() in this routine
			 * rely on (bytes[numBytes] == '\0'). */
    const char *trim,	/* String of trim characters... */
    size_t numTrim)	/* ...and its length in bytes */
    Tcl_Size numTrim)	/* ...and its length in bytes */
			/* Calls to TclUtfToUniChar() in this routine
			 * rely on (trim[numTrim] == '\0'). */
{
    const char *p = bytes;
	int ch1, ch2;
    int ch1, ch2;

    /* Empty strings -> nothing to do */
    if ((numBytes == 0) || (numTrim == 0)) {
	return 0;
    }

    /*
     * Outer loop: iterate over string to be trimmed.
     */

    do {
	size_t pInc = TclUtfToUCS4(p, &ch1);
	Tcl_Size pInc = TclUtfToUniChar(p, &ch1);
	const char *q = trim;
	size_t bytesLeft = numTrim;
	Tcl_Size bytesLeft = numTrim;

	/*
	 * Inner loop: scan trim string for match to current character.
	 */

	do {
	    size_t qInc = TclUtfToUCS4(q, &ch2);
	    Tcl_Size qInc = TclUtfToUniChar(q, &ch2);

	    if (ch1 == ch2) {
		break;
	    }

	    q += qInc;
	    bytesLeft -= qInc;
1777
1778
1779
1780
1781
1782
1783
1784

1785
1786
1787

1788
1789
1790
1791

1792
1793
1794

1795
1796

1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810

1811
1812
1813
1814
1815
1816
1817
1791
1792
1793
1794
1795
1796
1797

1798
1799
1800

1801
1802
1803
1804

1805
1806
1807

1808
1809

1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823

1824
1825
1826
1827
1828
1829
1830
1831







-
+


-
+



-
+


-
+

-
+













-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
TclTrim(
    const char *bytes,	/* String to be trimmed... */
    size_t numBytes,	/* ...and its length in bytes */
    Tcl_Size numBytes,	/* ...and its length in bytes */
			/* Calls in this routine
			 * rely on (bytes[numBytes] == '\0'). */
    const char *trim,	/* String of trim characters... */
    size_t numTrim,	/* ...and its length in bytes */
    Tcl_Size numTrim,	/* ...and its length in bytes */
			/* Calls in this routine
			 * rely on (trim[numTrim] == '\0'). */
    size_t *trimRightPtr)	/* Offset from the end of the string. */
    Tcl_Size *trimRightPtr)	/* Offset from the end of the string. */
{
    size_t trimLeft = 0, trimRight = 0;
    Tcl_Size trimLeft = 0, trimRight = 0;

    /* Empty strings -> nothing to do */
    if ((numBytes > 0) && (numTrim > 0)) {

	/* When bytes is NUL-terminated, returns 0 <= trimLeft <= numBytes */
	trimLeft = TclTrimLeft(bytes, numBytes, trim, numTrim);
	numBytes -= trimLeft;

	/* If we did not trim the whole string, it starts with a character
	 * that we will not trim. Skip over it. */
	if (numBytes > 0) {
	    int ch;
	    const char *first = bytes + trimLeft;
	    bytes += TclUtfToUCS4(first, &ch);
	    bytes += TclUtfToUniChar(first, &ch);
	    numBytes -= (bytes - first);

	    if (numBytes > 0) {
		/* When bytes is NUL-terminated, returns
		 * 0 <= trimRight <= numBytes */
		trimRight = TclTrimRight(bytes, numBytes, trim, numTrim);
	    }
1841
1842
1843
1844
1845
1846
1847
1848

1849
1850
1851
1852

1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870



1871
1872
1873
1874
1875








1876
1877
1878
1879
1880

1881
1882
1883
1884
1885
1886
1887
1855
1856
1857
1858
1859
1860
1861

1862
1863
1864


1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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







-
+


-
-
+


















+
+
+





+
+
+
+
+
+
+
+




-
+







 */

/* The whitespace characters trimmed during [concat] operations */
#define CONCAT_WS_SIZE (sizeof(CONCAT_TRIM_SET "") - 1)

char *
Tcl_Concat(
    int argc,			/* Number of strings to concatenate. */
    Tcl_Size argc,			/* Number of strings to concatenate. */
    const char *const *argv)	/* Array of strings to concatenate. */
{
    int i;
    size_t needSpace = 0, bytesNeeded = 0;
    Tcl_Size i, needSpace = 0, bytesNeeded = 0;
    char *result, *p;

    /*
     * Dispose of the empty result corner case first to simplify later code.
     */

    if (argc == 0) {
	result = (char *) Tcl_Alloc(1);
	result[0] = '\0';
	return result;
    }

    /*
     * First allocate the result buffer at the size required.
     */

    for (i = 0;  i < argc;  i++) {
	bytesNeeded += strlen(argv[i]);
	if (bytesNeeded < 0) {
	    Tcl_Panic("Tcl_Concat: max size of Tcl value exceeded");
	}
    }

    /*
     * All element bytes + (argc - 1) spaces + 1 terminating NULL.
     */
    if (bytesNeeded + argc - 1 < 0) {
	/*
	 * Panic test could be tighter, but not going to bother for this
	 * legacy routine.
	 */

	Tcl_Panic("Tcl_Concat: max size of Tcl value exceeded");
    }

    result = (char *)Tcl_Alloc(bytesNeeded + argc);

    for (p = result, i = 0;  i < argc;  i++) {
	size_t triml, trimr, elemLength;
	Tcl_Size triml, trimr, elemLength;
	const char *element;

	element = argv[i];
	elemLength = strlen(argv[i]);

	/* Trim away the leading/trailing whitespace. */
	triml = TclTrim(element, elemLength, CONCAT_TRIM_SET,
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968


1969
1970
1971







1972

1973
1974

1975
1976

1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992

1993
1994
1995
1996



1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011

2012
2013
2014
2015
2016
2017
2018
1955
1956
1957
1958
1959
1960
1961

1962
1963
1964


1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976

1977
1978
1979

1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992

1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004

2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026

2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048

2049
2050
2051
2052
2053
2054
2055
2056







-
+


-
-
+
+










-
+


-
+
+











-
+
+



+
+
+
+
+
+
+
-
+


+


+















-
+




+
+
+














-
+







 *	A new object is created.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
Tcl_ConcatObj(
    int objc,			/* Number of objects to concatenate. */
    Tcl_Size objc,		/* Number of objects to concatenate. */
    Tcl_Obj *const objv[])	/* Array of objects to concatenate. */
{
    int i, needSpace = 0;
    size_t bytesNeeded = 0, elemLength;
    int needSpace = 0;
    Tcl_Size i, bytesNeeded = 0, elemLength;
    const char *element;
    Tcl_Obj *objPtr, *resPtr;

    /*
     * Check first to see if all the items are of list type or empty. If so,
     * we will concat them together as lists, and return a list object. This
     * is only valid when the lists are in canonical form.
     */

    for (i = 0;  i < objc;  i++) {
	size_t length;
	Tcl_Size length;

	objPtr = objv[i];
	if (TclListObjIsCanonical(objPtr)) {
	if (TclListObjIsCanonical(objPtr) ||
		TclObjTypeHasProc(objPtr, indexProc)) {
	    continue;
	}
	(void)TclGetStringFromObj(objPtr, &length);
	if (length > 0) {
	    break;
	}
    }
    if (i == objc) {
	resPtr = NULL;
	for (i = 0;  i < objc;  i++) {
	    objPtr = objv[i];
	    if (!TclListObjIsCanonical(objPtr)) {
	    if (!TclListObjIsCanonical(objPtr) &&
		    !TclObjTypeHasProc(objPtr, indexProc)) {
		continue;
	    }
	    if (resPtr) {
		Tcl_Obj *elemPtr = NULL;

		Tcl_ListObjIndex(NULL, objPtr, 0, &elemPtr);
		if (elemPtr == NULL) {
		    continue;
		}
		if (TclGetString(elemPtr)[0] == '#' || TCL_OK
		if (TCL_OK != Tcl_ListObjAppendList(NULL, resPtr, objPtr)) {
			!= Tcl_ListObjAppendList(NULL, resPtr, objPtr)) {
		    /* Abandon ship! */
		    Tcl_DecrRefCount(resPtr);
		    Tcl_BounceRefCount(elemPtr); // could be an abstract list element
		    goto slow;
		}
		Tcl_BounceRefCount(elemPtr); // could be an an abstract list element
	    } else {
		resPtr = TclListObjCopy(NULL, objPtr);
	    }
	}
	if (!resPtr) {
	    TclNewObj(resPtr);
	}
	return resPtr;
    }

  slow:
    /*
     * Something cannot be determined to be safe, so build the concatenation
     * the slow way, using the string representations.
     *
     * First try to pre-allocate the size required.
     * First try to preallocate the size required.
     */

    for (i = 0;  i < objc;  i++) {
	element = TclGetStringFromObj(objv[i], &elemLength);
	if (bytesNeeded > (TCL_SIZE_MAX - elemLength)) {
	    break; /* Overflow. Do not preallocate. See comment below. */
	}
	bytesNeeded += elemLength;
    }

    /*
     * Does not matter if this fails, will simply try later to build up the
     * string with each Append reallocating as needed with the usual string
     * append algorithm.  When that fails it will report the error.
     */

    TclNewObj(resPtr);
    (void) Tcl_AttemptSetObjLength(resPtr, bytesNeeded + objc - 1);
    Tcl_SetObjLength(resPtr, 0);

    for (i = 0;  i < objc;  i++) {
	size_t triml, trimr;
	Tcl_Size triml, trimr;

	element = TclGetStringFromObj(objv[i], &elemLength);

	/* Trim away the leading/trailing whitespace. */
	triml = TclTrim(element, elemLength, CONCAT_TRIM_SET,
		CONCAT_WS_SIZE, &trimr);
	element += triml;
2095
2096
2097
2098
2099
2100
2101
2102

2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116

2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132

2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146

2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160

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
2222
2223
2224
2225
2226
2133
2134
2135
2136
2137
2138
2139

2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153

2154
2155
2156
2157
2158
2159
2160
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
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







-
+













-
+















-
+













-
+













-
+










-
+


















-
+













-
+














-
+







	 */

	if (p == '*') {
	    /*
	     * Skip all successive *'s in the pattern
	     */

	    while (*(++pattern) == '*') {}
	    while (*(++pattern) == '*');
	    p = *pattern;
	    if (p == '\0') {
		return 1;
	    }

	    /*
	     * This is a special case optimization for single-byte utf.
	     */

	    if (UCHAR(*pattern) < 0x80) {
		ch2 = (int)
			(nocase ? tolower(UCHAR(*pattern)) : UCHAR(*pattern));
	    } else {
		TclUtfToUCS4(pattern, &ch2);
		TclUtfToUniChar(pattern, &ch2);
		if (nocase) {
		    ch2 = Tcl_UniCharToLower(ch2);
		}
	    }

	    while (1) {
		/*
		 * Optimization for matching - cruise through the string
		 * quickly if the next char in the pattern isn't a special
		 * character
		 */

		if ((p != '[') && (p != '?') && (p != '\\')) {
		    if (nocase) {
			while (*str) {
			    charLen = TclUtfToUCS4(str, &ch1);
			    charLen = TclUtfToUniChar(str, &ch1);
			    if (ch2==ch1 || ch2==Tcl_UniCharToLower(ch1)) {
				break;
			    }
			    str += charLen;
			}
		    } else {
			/*
			 * There's no point in trying to make this code
			 * shorter, as the number of bytes you want to compare
			 * each time is non-constant.
			 */

			while (*str) {
			    charLen = TclUtfToUCS4(str, &ch1);
			    charLen = TclUtfToUniChar(str, &ch1);
			    if (ch2 == ch1) {
				break;
			    }
			    str += charLen;
			}
		    }
		}
		if (Tcl_StringCaseMatch(str, pattern, nocase)) {
		    return 1;
		}
		if (*str == '\0') {
		    return 0;
		}
		str += TclUtfToUCS4(str, &ch1);
		str += TclUtfToUniChar(str, &ch1);
	    }
	}

	/*
	 * Check for a "?" as the next pattern character. It matches any
	 * single character.
	 */

	if (p == '?') {
	    pattern++;
	    str += TclUtfToUCS4(str, &ch1);
	    str += TclUtfToUniChar(str, &ch1);
	    continue;
	}

	/*
	 * Check for a "[" as the next pattern character. It is followed by a
	 * list of characters that are acceptable, or by a range (two
	 * characters separated by "-").
	 */

	if (p == '[') {
	    int startChar = 0, endChar = 0;

	    pattern++;
	    if (UCHAR(*str) < 0x80) {
		ch1 = (int)
			(nocase ? tolower(UCHAR(*str)) : UCHAR(*str));
		str++;
	    } else {
		str += TclUtfToUCS4(str, &ch1);
		str += TclUtfToUniChar(str, &ch1);
		if (nocase) {
		    ch1 = Tcl_UniCharToLower(ch1);
		}
	    }
	    while (1) {
		if ((*pattern == ']') || (*pattern == '\0')) {
		    return 0;
		}
		if (UCHAR(*pattern) < 0x80) {
		    startChar = (int) (nocase
			    ? tolower(UCHAR(*pattern)) : UCHAR(*pattern));
		    pattern++;
		} else {
		    pattern += TclUtfToUCS4(pattern, &startChar);
		    pattern += TclUtfToUniChar(pattern, &startChar);
		    if (nocase) {
			startChar = Tcl_UniCharToLower(startChar);
		    }
		}
		if (*pattern == '-') {
		    pattern++;
		    if (*pattern == '\0') {
			return 0;
		    }
		    if (UCHAR(*pattern) < 0x80) {
			endChar = (int) (nocase
				? tolower(UCHAR(*pattern)) : UCHAR(*pattern));
			pattern++;
		    } else {
			pattern += TclUtfToUCS4(pattern, &endChar);
			pattern += TclUtfToUniChar(pattern, &endChar);
			if (nocase) {
			    endChar = Tcl_UniCharToLower(endChar);
			}
		    }
		    if (((startChar <= ch1) && (ch1 <= endChar))
			    || ((endChar <= ch1) && (ch1 <= startChar))) {
			/*
2260
2261
2262
2263
2264
2265
2266
2267
2268


2269
2270
2271
2272
2273
2274
2275
2298
2299
2300
2301
2302
2303
2304


2305
2306
2307
2308
2309
2310
2311
2312
2313







-
-
+
+







	}

	/*
	 * There's no special character. Just make sure that the next bytes of
	 * each string match.
	 */

	str += TclUtfToUCS4(str, &ch1);
	pattern += TclUtfToUCS4(pattern, &ch2);
	str += TclUtfToUniChar(str, &ch1);
	pattern += TclUtfToUniChar(pattern, &ch2);
	if (nocase) {
	    if (Tcl_UniCharToLower(ch1) != Tcl_UniCharToLower(ch2)) {
		return 0;
	    }
	} else if (ch1 != ch2) {
	    return 0;
	}
2295
2296
2297
2298
2299
2300
2301
2302

2303
2304
2305
2306

2307
2308
2309
2310
2311
2312
2313
2333
2334
2335
2336
2337
2338
2339

2340
2341
2342
2343

2344
2345
2346
2347
2348
2349
2350
2351







-
+



-
+







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

int
TclByteArrayMatch(
    const unsigned char *string,/* String. */
    size_t strLen,			/* Length of String */
    Tcl_Size strLen,			/* Length of String */
    const unsigned char *pattern,
				/* Pattern, which may contain special
				 * characters. */
    size_t ptnLen,			/* Length of Pattern */
    Tcl_Size ptnLen,			/* Length of Pattern */
    TCL_UNUSED(int) /*flags*/)
{
    const unsigned char *stringEnd, *patternEnd;
    unsigned char p;

    stringEnd = string + strLen;
    patternEnd = pattern + ptnLen;
2356
2357
2358
2359
2360
2361
2362
2363

2364
2365
2366
2367
2368
2369
2370
2394
2395
2396
2397
2398
2399
2400

2401
2402
2403
2404
2405
2406
2407
2408







-
+








		if ((p != '[') && (p != '?') && (p != '\\')) {
		    while ((string < stringEnd) && (p != *string)) {
			string++;
		    }
		}
		if (TclByteArrayMatch(string, stringEnd - string,
				pattern, patternEnd - pattern, 0)) {
			pattern, patternEnd - pattern, 0)) {
		    return 1;
		}
		if (string == stringEnd) {
		    return 0;
		}
		string++;
	    }
2477
2478
2479
2480
2481
2482
2483
2484

2485
2486
2487
2488
2489
2490
2491
2492
2493

2494
2495
2496
2497


2498
2499
2500
2501
2502
2503
2504


2505
2506
2507
2508
2509
2510
2511
2515
2516
2517
2518
2519
2520
2521

2522
2523
2524
2525
2526
2527
2528
2529
2530

2531
2532
2533


2534
2535
2536
2537
2538
2539
2540


2541
2542
2543
2544
2545
2546
2547
2548
2549







-
+








-
+


-
-
+
+





-
-
+
+







TclStringMatchObj(
    Tcl_Obj *strObj,		/* string object. */
    Tcl_Obj *ptnObj,		/* pattern object. */
    int flags)			/* Only TCL_MATCH_NOCASE should be passed, or
				 * 0. */
{
    int match;
    size_t length = 0, plen = 0;
    Tcl_Size length = 0, plen = 0;

    /*
     * Promote based on the type of incoming object.
     * XXX: Currently doesn't take advantage of exact-ness that
     * XXX: TclReToGlob tells us about
    trivial = nocase ? 0 : TclMatchIsTrivial(TclGetString(ptnObj));
     */

    if (TclHasIntRep(strObj, &tclStringType) || (strObj->typePtr == NULL)) {
    if (TclHasInternalRep(strObj, &tclStringType) || (strObj->typePtr == NULL)) {
	Tcl_UniChar *udata, *uptn;

	udata = TclGetUnicodeFromObj(strObj, &length);
	uptn  = TclGetUnicodeFromObj(ptnObj, &plen);
	udata = Tcl_GetUnicodeFromObj(strObj, &length);
	uptn  = Tcl_GetUnicodeFromObj(ptnObj, &plen);
	match = TclUniCharMatch(udata, length, uptn, plen, flags);
    } else if (TclIsPureByteArray(strObj) && TclIsPureByteArray(ptnObj)
		&& !flags) {
	unsigned char *data, *ptn;

	data = TclGetByteArrayFromObj(strObj, &length);
	ptn  = TclGetByteArrayFromObj(ptnObj, &plen);
	data = Tcl_GetBytesFromObj(NULL, strObj, &length);
	ptn  = Tcl_GetBytesFromObj(NULL, ptnObj, &plen);
	match = TclByteArrayMatch(data, length, ptn, plen, 0);
    } else {
	match = Tcl_StringCaseMatch(TclGetString(strObj),
		TclGetString(ptnObj), flags);
    }
    return match;
}
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
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







-
-
-
-
+
+
+
+
+

-
+

-
+


-

-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
+

-
-
+
+



-
+




+
-
+

-
-
-
-
-
+
+
+
+







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

char *
Tcl_DStringAppend(
    Tcl_DString *dsPtr,		/* Structure describing dynamic string. */
    const char *bytes,		/* String to append. If length is
				 * TCL_INDEX_NONE then this must be null-terminated. */
    size_t length)			/* Number of bytes from "bytes" to append. If
				 * TCL_INDEX_NONE, then append all of bytes, up to null
				 * at end. */
				 * TCL_INDEX_NONE then this must be
				 * null-terminated. */
    Tcl_Size length)		/* Number of bytes from "bytes" to append. If
				 * TCL_INDEX_NONE, then append all of bytes, up
				 * to null at end. */
{
    size_t newSize;
    Tcl_Size newSize;

    if (length == TCL_INDEX_NONE) {
    if (length < 0) {
	length = strlen(bytes);
    }
    newSize = length + dsPtr->length;

    /*
     * Allocate a larger buffer for the string if the current one isn't large
     * enough. Allocate extra space in the new buffer so that there will be
    if (length > (TCL_SIZE_MAX - dsPtr->length - 1)) {
	Tcl_Panic("max size for a Tcl value (%" TCL_SIZE_MODIFIER
		  "d bytes) exceeded",
     * room to grow before we have to allocate again.
     */

    if (newSize >= dsPtr->spaceAvl) {
	dsPtr->spaceAvl = newSize * 2;
		  TCL_SIZE_MAX);
	return NULL; /* NOTREACHED */
    }
    newSize = length + dsPtr->length + 1;

    if (newSize > dsPtr->spaceAvl) {
	if (dsPtr->string == dsPtr->staticSpace) {
	    char *newString = (char *)Tcl_Alloc(dsPtr->spaceAvl);

	    char *newString;
	    newString = (char *) TclAllocEx(newSize, &dsPtr->spaceAvl);
	    memcpy(newString, dsPtr->string, dsPtr->length);
	    dsPtr->string = newString;
	} else {
	    size_t index = TCL_INDEX_NONE;
	    Tcl_Size offset = -1;

	    /* See [16896d49fd] */
	    if (bytes >= dsPtr->string
		    && bytes <= dsPtr->string + dsPtr->length) {
		/* Source string is within this DString. Note offset */
		index = bytes - dsPtr->string;
		offset = bytes - dsPtr->string;
	    }

	    dsPtr->string = (char *)Tcl_Realloc(dsPtr->string, dsPtr->spaceAvl);

	    if (index != TCL_INDEX_NONE) {
		bytes = dsPtr->string + index;
	    dsPtr->string =
		(char *)TclReallocEx(dsPtr->string, newSize, &dsPtr->spaceAvl);
	    if (offset >= 0) {
		bytes = dsPtr->string + offset;
	    }
	}
    }

    /*
     * Copy the new string into the buffer at the end of the old one.
     */
2624
2625
2626
2627
2628
2629
2630
2631

2632
2633
2634
2635
2636
2637
2638
2663
2664
2665
2666
2667
2668
2669

2670
2671
2672
2673
2674
2675
2676
2677







-
+







 */

char *
TclDStringAppendObj(
    Tcl_DString *dsPtr,
    Tcl_Obj *objPtr)
{
    size_t length;
    Tcl_Size length;
    const char *bytes = TclGetStringFromObj(objPtr, &length);

    return Tcl_DStringAppend(dsPtr, bytes, length);
}

char *
TclDStringAppendDString(
2667
2668
2669
2670
2671
2672
2673
2674

2675
2676
2677
2678
2679
2680
2681
2706
2707
2708
2709
2710
2711
2712

2713
2714
2715
2716
2717
2718
2719
2720







-
+







    const char *element)	/* String to append. Must be
				 * null-terminated. */
{
    char *dst = dsPtr->string + dsPtr->length;
    int needSpace = TclNeedSpace(dsPtr->string, dst);
    char flags = 0;
    int quoteHash = 1;
    size_t newSize;
    Tcl_Size newSize;

    if (needSpace) {
	/*
	 * If we need a space to separate the new element from something
	 * already ending the string, we're not appending the first element
	 * of any list, so we need not quote any leading hash character.
	 */
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
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







-
+











-
-
+
+
-

-
+
-








+


-
-
-
+
+


















-
+








	/* Call again without whitespace to confound things. */
	quoteHash = !TclNeedSpace(dsPtr->string, dst+1);
    }
    if (!quoteHash) {
	flags |= TCL_DONT_QUOTE_HASH;
    }
    newSize = dsPtr->length + needSpace + TclScanElement(element, -1, &flags);
    newSize = dsPtr->length + needSpace + TclScanElement(element, TCL_INDEX_NONE, &flags);
    if (!quoteHash) {
	flags |= TCL_DONT_QUOTE_HASH;
    }

    /*
     * Allocate a larger buffer for the string if the current one isn't large
     * enough. Allocate extra space in the new buffer so that there will be
     * room to grow before we have to allocate again. SPECIAL NOTE: must use
     * memcpy, not strcpy, to copy the string to a larger buffer, since there
     * may be embedded NULLs in the string in some cases.
     */

    if (newSize >= dsPtr->spaceAvl) {
    newSize += 1; /* For terminating nul */
    if (newSize > dsPtr->spaceAvl) {
	dsPtr->spaceAvl = newSize * 2;
	if (dsPtr->string == dsPtr->staticSpace) {
	    char *newString = (char *)Tcl_Alloc(dsPtr->spaceAvl);
	    char *newString = (char *) TclAllocEx(newSize, &dsPtr->spaceAvl);

	    memcpy(newString, dsPtr->string, dsPtr->length);
	    dsPtr->string = newString;
	} else {
	    int offset = -1;

	    /* See [16896d49fd] */
	    if (element >= dsPtr->string
		    && element <= dsPtr->string + dsPtr->length) {
		/* Source string is within this DString. Note offset */
		offset = element - dsPtr->string;
	    }

	    dsPtr->string = (char *)Tcl_Realloc(dsPtr->string, dsPtr->spaceAvl);

	    dsPtr->string =
		    (char *)TclReallocEx(dsPtr->string, newSize, &dsPtr->spaceAvl);
	    if (offset >= 0) {
		element = dsPtr->string + offset;
	    }
	}
    }
    dst = dsPtr->string + dsPtr->length;

    /*
     * Convert the new string to a list element and copy it into the buffer at
     * the end, with a space, if needed.
     */

    if (needSpace) {
	*dst = ' ';
	dst++;
	dsPtr->length++;
    }

    dsPtr->length += TclConvertElement(element, -1, dst, flags);
    dsPtr->length += TclConvertElement(element, TCL_INDEX_NONE, dst, flags);
    dsPtr->string[dsPtr->length] = '\0';
    return dsPtr->string;
}

/*
 *----------------------------------------------------------------------
 *
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
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







-
+

-
+

+
+
+







-
-
-
-
+
+
+
+


+
+
+
-
+







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

void
Tcl_DStringSetLength(
    Tcl_DString *dsPtr,		/* Structure describing dynamic string. */
    size_t length)			/* New length for dynamic string. */
    Tcl_Size length)			/* New length for dynamic string. */
{
    size_t newsize;
    Tcl_Size newsize;

    if (length < 0) {
	length = 0;
    }
    if (length >= dsPtr->spaceAvl) {
	/*
	 * There are two interesting cases here. In the first case, the user
	 * may be trying to allocate a large buffer of a specific size. It
	 * would be wasteful to overallocate that buffer, so we just allocate
	 * enough for the requested size plus the trailing null byte. In the
	 * second case, we are growing the buffer incrementally, so we need
	 * behavior similar to Tcl_DStringAppend. The requested length will
	 * usually be a small delta above the current spaceAvl, so we'll end
	 * up doubling the old size. This won't grow the buffer quite as
	 * quickly, but it should be close enough.
	 * behavior similar to Tcl_DStringAppend.
	 * TODO - the above makes no sense to me. How does the code below
	 * translate into distinguishing the two cases above? IMO, if caller
	 * specifically sets the length, there is no cause for overallocation.
	 */

	if (length >= TCL_SIZE_MAX) {
	    Tcl_Panic("Tcl_Concat: max size of Tcl value exceeded");
	}
	newsize = dsPtr->spaceAvl * 2;
	newsize = TclUpsizeAlloc(dsPtr->spaceAvl, length + 1, TCL_SIZE_MAX);
	if (length < newsize) {
	    dsPtr->spaceAvl = newsize;
	} else {
	    dsPtr->spaceAvl = length + 1;
	}
	if (dsPtr->string == dsPtr->staticSpace) {
	    char *newString = (char *)Tcl_Alloc(dsPtr->spaceAvl);
2860
2861
2862
2863
2864
2865
2866
2867

2868
2869
2870
2871
2872
2873
2874
2903
2904
2905
2906
2907
2908
2909

2910
2911
2912
2913
2914
2915
2916
2917







-
+








void
Tcl_DStringResult(
    Tcl_Interp *interp,		/* Interpreter whose result is to be reset. */
    Tcl_DString *dsPtr)		/* Dynamic string that is to become the
				 * result of interp. */
{
    Tcl_SetObjResult(interp, TclDStringToObj(dsPtr));
    Tcl_SetObjResult(interp, Tcl_DStringToObj(dsPtr));
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DStringGetResult --
 *
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
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







-
+









-
+



















-
+







void
Tcl_DStringGetResult(
    Tcl_Interp *interp,		/* Interpreter whose result is to be reset. */
    Tcl_DString *dsPtr)		/* Dynamic string that is to become the result
				 * of interp. */
{
    Tcl_Obj *obj = Tcl_GetObjResult(interp);
    char *bytes = TclGetString(obj);
    const char *bytes = TclGetString(obj);

    Tcl_DStringFree(dsPtr);
    Tcl_DStringAppend(dsPtr, bytes, obj->length);
    Tcl_ResetResult(interp);
}

/*
 *----------------------------------------------------------------------
 *
 * TclDStringToObj --
 * Tcl_DStringToObj --
 *
 *	This function moves a dynamic string's contents to a new Tcl_Obj. Be
 *	aware that this function does *not* check that the encoding of the
 *	contents of the dynamic string is correct; this is the caller's
 *	responsibility to enforce.
 *
 * Results:
 *	The newly-allocated untyped (i.e., typePtr==NULL) Tcl_Obj with a
 *	reference count of zero.
 *
 * Side effects:
 *	The string is "moved" to the object. dsPtr is reinitialized to an
 *	empty string; it does not need to be Tcl_DStringFree'd after this if
 *	not used further.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TclDStringToObj(
Tcl_DStringToObj(
    Tcl_DString *dsPtr)
{
    Tcl_Obj *result;

    if (dsPtr->string == dsPtr->staticSpace) {
	if (dsPtr->length == 0) {
	    TclNewObj(result);
3047
3048
3049
3050
3051
3052
3053
3054

3055
3056
3057
3058
3059
3060
3061
3062
3063

3064
3065
3066
3067
3068
3069
3070
3090
3091
3092
3093
3094
3095
3096

3097
3098
3099
3100
3101
3102
3103
3104
3105

3106
3107
3108
3109
3110
3111
3112
3113







-
+








-
+







    char *digits;
    char *end;

    /*
     * Handle NaN.
     */

    if (TclIsNaN(value)) {
    if (isnan(value)) {
	TclFormatNaN(value, dst);
	return;
    }

    /*
     * Handle infinities.
     */

    if (TclIsInfinite(value)) {
    if (isinf(value)) {
	/*
	 * Remember to copy the terminating NUL too.
	 */

	if (value < 0) {
	    memcpy(dst, "-Inf", 5);
	} else {
3094
3095
3096
3097
3098
3099
3100
3101

3102
3103
3104
3105
3106
3107
3108
3137
3138
3139
3140
3141
3142
3143

3144
3145
3146
3147
3148
3149
3150
3151







-
+







	    *dst++ = '.';
	    while (c != '\0') {
		*dst++ = c;
		c = *++p;
	    }
	}

	sprintf(dst, "e%+d", exponent);
	snprintf(dst, TCL_DOUBLE_SPACE, "e%+d", exponent);
    } else {
	/*
	 * F format for others.
	 */

	if (exponent < 0) {
	    *dst++ = '0';
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195




3196
3197
3198
3199
3200
3201
3202
3203
3204

3205
3206
3207
3208
3209
3210
3211
3228
3229
3230
3231
3232
3233
3234




3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246

3247
3248
3249
3250
3251
3252
3253
3254







-
-
-
-
+
+
+
+








-
+







     *	Reconsider this if we ever start treating non-ASCII Unicode
     *	characters as meaningful list syntax, expanded Unicode spaces as
     *	element separators, for example.)
     *

    end = Tcl_UtfPrev(end, start);
    while (*end == '{') {
        if (end == start) {
            return 0;
        }
        end = Tcl_UtfPrev(end, start);
	if (end == start) {
	    return 0;
	}
	end = Tcl_UtfPrev(end, start);
    }

     *
     */

    while ((--end >= start) && (*end == '{')) {
    }
    if (end < start) {
        return 0;
	return 0;
    }

    /*
     * (c) the trailing character of the string is already a list-element
     *	   separator, Use the same testing routine as TclFindElement to
     *	   enforce consistency.
     */
3247
3248
3249
3250
3251
3252
3253
3254

3255
3256
3257
3258
3259
3260
3261

3262
3263
3264
3265
3266
3267
3268
3290
3291
3292
3293
3294
3295
3296

3297
3298
3299
3300
3301
3302
3303

3304
3305
3306
3307
3308
3309
3310
3311







-
+






-
+







 * Side effects:
 *	The formatted characters are written into the storage pointer to by
 *	the "buffer" argument.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
TclFormatInt(
    char *buffer,		/* Points to the storage into which the
				 * formatted characters are written. */
    Tcl_WideInt n)			/* The integer to format. */
{
    Tcl_WideUInt intVal;
    size_t i = 0, numFormatted, j;
    int i = 0, numFormatted, j;
    static const char digits[] = "0123456789";

    /*
     * Generate the characters of the result backwards in the buffer.
     */

    intVal = (n < 0 ? -(Tcl_WideUInt)n : (Tcl_WideUInt)n);
3317
3318
3319
3320
3321
3322
3323
3324

3325
3326

3327
3328

3329
3330
3331
3332


3333
3334
3335
3336
3337



3338
3339
3340
3341
3342
3343
3344
3360
3361
3362
3363
3364
3365
3366

3367
3368

3369
3370

3371
3372
3373


3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390







-
+

-
+

-
+


-
-
+
+





+
+
+








static int
GetWideForIndex(
    Tcl_Interp *interp,         /* Interpreter to use for error reporting. If
				 * NULL, then no error message is left after
				 * errors. */
    Tcl_Obj *objPtr,            /* Points to the value to be parsed */
    size_t endValue,            /* The value to be stored at *widePtr if
    Tcl_WideInt endValue,       /* The value to be stored at *widePtr if
				 * objPtr holds "end".
                                 * NOTE: this value may be TCL_INDEX_NONE. */
				 * NOTE: this value may be TCL_INDEX_NONE. */
    Tcl_WideInt *widePtr)       /* Location filled in with a wide integer
                                 * representing an index. */
				 * representing an index. */
{
    int numType;
    ClientData cd;
    int code = TclGetNumberFromObj(NULL, objPtr, &cd, &numType);
    void *cd;
    int code = Tcl_GetNumberFromObj(NULL, objPtr, &cd, &numType);

    if (code == TCL_OK) {
	if (numType == TCL_NUMBER_INT) {
	    /* objPtr holds an integer in the signed wide range */
	    *widePtr = *(Tcl_WideInt *)cd;
	    if ((*widePtr < 0)) {
		*widePtr = (endValue == -1) ? WIDE_MIN : -1;
	    }
	    return TCL_OK;
	}
	if (numType == TCL_NUMBER_BIG) {
	    /* objPtr holds an integer outside the signed wide range */
	    /* Truncate to the signed wide range. */
	    *widePtr = ((mp_isneg((mp_int *)cd)) ? WIDE_MIN : WIDE_MAX);
	    return TCL_OK;
3354
3355
3356
3357
3358
3359
3360








3361
3362


3363
3364

3365
3366
3367

3368
3369
3370
3371



3372
3373

3374
3375
3376

3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388

3389
3390
3391


3392
3393
3394
3395
3396
3397
3398
3399
3400



3401
3402
3403
3404






3405
3406

3407
3408
3409
3410

3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427


3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444


3445
3446

3447
3448

3449
3450

3451
3452
3453
3454



3455
3456
3457
3458
3459
3460

3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477

3478
3479
3480
3481
3482



3483
3484
3485
3486
3487


3488
3489
3490
3491
3492
3493
3494
3495
3496

3497
3498
3499
3500
3501
3502

3503
3504
3505
3506

3507
3508
3509
3510
3511
3512
3513


3514
3515
3516
3517
3518
3519
3520
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414


3415
3416
3417

3418

3419

3420
3421



3422
3423
3424
3425

3426
3427


3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439

3440



3441
3442
3443
3444
3445


3446
3447
3448
3449
3450
3451
3452




3453
3454
3455
3456
3457
3458
3459

3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481

3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498


3499
3500
3501

3502
3503

3504
3505

3506
3507



3508
3509
3510
3511
3512
3513
3514
3515

3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532

3533

3534



3535
3536
3537
3538
3539
3540


3541
3542
3543
3544
3545
3546
3547
3548
3549
3550

3551
3552
3553
3554
3555
3556

3557
3558
3559
3560

3561
3562
3563
3564
3565
3566


3567
3568
3569
3570
3571
3572
3573
3574
3575







+
+
+
+
+
+
+
+
-
-
+
+

-
+
-

-
+

-
-
-
+
+
+

-
+

-
-
+











-
+
-
-
-
+
+



-
-




+
+
+
-
-
-
-
+
+
+
+
+
+

-
+




+
















-
+
+















-
-
+
+

-
+

-
+

-
+

-
-
-
+
+
+





-
+
















-
+
-

-
-
-
+
+
+



-
-
+
+








-
+





-
+



-
+





-
-
+
+







 *
 * Tcl_GetIntForIndex --
 *
 *	Provides an integer corresponding to the list index held in a Tcl
 *	object. The string value 'objPtr' is expected have the format
 *	integer([+-]integer)? or end([+-]integer)?.
 *
 *	If the computed index lies within the valid range of Tcl indices
 *	(0..TCL_SIZE_MAX) it is returned. Higher values are returned as
 *	TCL_SIZE_MAX. Negative values are returned as TCL_INDEX_NONE (-1).
 *
 *	Callers should pass reasonable values for endValue - one in the
 *      valid index range or TCL_INDEX_NONE (-1), for example for an empty
 *	list.
 *
 * Value
 * 	TCL_OK
 * Results:
 *	TCL_OK
 *
 * 	    The index is stored at the address given by by 'indexPtr'. If
 *	    The index is stored at the address given by 'indexPtr'.
 * 	    'objPtr' has the value "end", the value stored is 'endValue'.
 *
 * 	TCL_ERROR
 *	TCL_ERROR
 *
 * 	    The value of 'objPtr' does not have one of the expected formats. If
 * 	    'interp' is non-NULL, an error message is left in the interpreter's
 * 	    result object.
 *	    The value of 'objPtr' does not have one of the expected formats. If
 *	    'interp' is non-NULL, an error message is left in the interpreter's
 *	    result object.
 *
 * Effect
 * Side effects:
 *
 * 	The object referenced by 'objPtr' is converted, as needed, to an
 * 	integer, wide integer, or end-based-index object.
 *	The internal representation contained within objPtr may shimmer.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_GetIntForIndex(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting. If
				 * NULL, then no error message is left after
				 * errors. */
    Tcl_Obj *objPtr,		/* Points to an object containing either "end"
				 * or an integer. */
    size_t endValue,		/* The value to be stored at "indexPtr" if
    Tcl_Size endValue,		/* The value corresponding to the "end" index */
				 * "objPtr" holds "end". */
    size_t *indexPtr)		/* Location filled in with an integer
				 * representing an index. */
    Tcl_Size *indexPtr)		/* Location filled in with an integer
				 * representing an index. May be NULL.*/
{
    Tcl_WideInt wide;

    /* Use platform-related size_t to wide-int to consider negative value
     * TCL_INDEX_NONE if wide-int and size_t have different dimensions. */
    if (GetWideForIndex(interp, objPtr, endValue, &wide) == TCL_ERROR) {
	return TCL_ERROR;
    }
    if (indexPtr != NULL) {
	/* Note: check against TCL_SIZE_MAX needed for 32-bit builds */
	if (wide >= 0 && wide <= TCL_SIZE_MAX) {
	    *indexPtr = (Tcl_Size)wide; /* A valid index */
	if ((wide < 0) && (endValue != TCL_INDEX_END)) {
	    *indexPtr = TCL_INDEX_NONE;
	} else if ((Tcl_WideUInt)wide > TCL_INDEX_END) {
	    *indexPtr = TCL_INDEX_END;
	} else if (wide > TCL_SIZE_MAX) {
	    *indexPtr = TCL_SIZE_MAX;   /* Beyond max possible index */
	} else if (wide < -1-TCL_SIZE_MAX) {
	    *indexPtr = -1-TCL_SIZE_MAX; /* Below most negative index */
	} else if ((wide < 0) && (endValue >= 0)) {
	    *indexPtr = TCL_INDEX_NONE; /* No clue why this special case */
	} else {
	    *indexPtr = (size_t) wide;
	    *indexPtr = (Tcl_Size) wide;
	}
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * GetEndOffsetFromObj --
 *
 *	Look for a string of the form "end[+-]offset" or "offset[+-]offset" and
 *	convert it to an internal representation.
 *
 *	The internal representation (wideValue) uses the following encoding:
 *
 *	WIDE_MIN:   Index value TCL_INDEX_NONE (or -1)
 *	WIDE_MIN+1: Index value n, for any n < -1  (usually same effect as -1)
 *	-$n:        Index "end-[expr {$n-1}]"
 *	-2:         Index "end-1"
 *	-1:         Index "end"
 *	0:          Index "0"
 *	WIDE_MAX-1: Index "end+n", for any n > 1
 *	WIDE_MAX-1: Index "end+n", for any n > 1. Distinguish from end+1 for
 *                  commands like lset.
 *	WIDE_MAX:   Index "end+1"
 *
 * Results:
 *	Tcl return code.
 *
 * Side effects:
 *	May store a Tcl_ObjType.
 *
 *----------------------------------------------------------------------
 */

static int
GetEndOffsetFromObj(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,            /* Pointer to the object to parse */
    size_t endValue,            /* The value to be stored at "indexPtr" if
                                 * "objPtr" holds "end". */
    Tcl_WideInt endValue,       /* The value to be stored at "widePtr" if
				 * "objPtr" holds "end". */
    Tcl_WideInt *widePtr)       /* Location filled in with an integer
                                 * representing an index. */
				 * representing an index. */
{
    Tcl_ObjIntRep *irPtr;
    Tcl_ObjInternalRep *irPtr;
    Tcl_WideInt offset = -1;	/* Offset in the "end-offset" expression - 1 */
    ClientData cd;
    void *cd;

    while ((irPtr = TclFetchIntRep(objPtr, &endOffsetType)) == NULL) {
	Tcl_ObjIntRep ir;
	size_t length;
    while ((irPtr = TclFetchInternalRep(objPtr, &endOffsetType)) == NULL) {
	Tcl_ObjInternalRep ir;
	Tcl_Size length;
	const char *bytes = TclGetStringFromObj(objPtr, &length);

	if (*bytes != 'e') {
	    int numType;
	    const char *opPtr;
	    int len, t1 = 0, t2 = 0;
	    int t1 = 0, t2 = 0;

	    /* Value doesn't start with "e" */

	    /* If we reach here, the string rep of objPtr exists. */

	    /*
	     * The valid index syntax does not include any value that is
	     * a list of more than one element. This is necessary so that
	     * lists of index values can be reliably distinguished from any
	     * single index value.
	     */

	    /*
	     * Quick scan to see if multi-value list is even possible.
	     * This relies on TclGetString() returning a NUL-terminated string.
	     */
	    if ((TclMaxListLength(bytes, -1, NULL) > 1)
	    if ((TclMaxListLength(bytes, TCL_INDEX_NONE, NULL) > 1)

		    /* If it's possible, do the full list parse. */
	            && (TCL_OK == Tcl_ListObjLength(NULL, objPtr, &len))
	            && (len > 1)) {
	        goto parseError;
		    && (TCL_OK == TclListObjLength(NULL, objPtr, &length))
		    && (length > 1)) {
		goto parseError;
	    }

	    /* Passed the list screen, so parse for index arithmetic expression */
	    if (TCL_OK == TclParseNumber(NULL, objPtr, NULL, NULL, -1, &opPtr,
	            TCL_PARSE_INTEGER_ONLY)) {
	    if (TCL_OK == TclParseNumber(NULL, objPtr, NULL, NULL, TCL_INDEX_NONE, &opPtr,
		    TCL_PARSE_INTEGER_ONLY)) {
		Tcl_WideInt w1=0, w2=0;

		/* value starts with valid integer... */

		if ((*opPtr == '-') || (*opPtr == '+')) {
		    /* ... value continues with [-+] ... */

		    /* Save first integer as wide if possible */
		    TclGetNumberFromObj(NULL, objPtr, &cd, &t1);
		    Tcl_GetNumberFromObj(NULL, objPtr, &cd, &t1);
		    if (t1 == TCL_NUMBER_INT) {
			w1 = (*(Tcl_WideInt *)cd);
		    }

		    if (TCL_OK == TclParseNumber(NULL, objPtr, NULL, opPtr + 1,
			    -1, NULL, TCL_PARSE_INTEGER_ONLY)) {
			    TCL_INDEX_NONE, NULL, TCL_PARSE_INTEGER_ONLY)) {
			/* ... value concludes with second valid integer */

			/* Save second integer as wide if possible */
			TclGetNumberFromObj(NULL, objPtr, &cd, &t2);
			Tcl_GetNumberFromObj(NULL, objPtr, &cd, &t2);
			if (t2 == TCL_NUMBER_INT) {
			    w2 = (*(Tcl_WideInt *)cd);
			}
		    }
		}
		/* Clear invalid intreps left by TclParseNumber */
		TclFreeIntRep(objPtr);
		/* Clear invalid internalreps left by TclParseNumber */
		TclFreeInternalRep(objPtr);

		if (t1 && t2) {
		    /* We have both integer values */
		    if ((t1 == TCL_NUMBER_INT) && (t2 == TCL_NUMBER_INT)) {
			/* Both are wide, do wide-integer math */
			if (*opPtr == '-') {
			    if (w2 == WIDE_MIN) {
3552
3553
3554
3555
3556
3557
3558
3559

3560
3561
3562
3563
3564
3565
3566
3607
3608
3609
3610
3611
3612
3613

3614
3615
3616
3617
3618
3619
3620
3621







-
+







			if (interp) {
			    Tcl_ExprObj(interp, objPtr, &sum);
			} else {
			    Tcl_Interp *compute = Tcl_CreateInterp();
			    Tcl_ExprObj(compute, objPtr, &sum);
			    Tcl_DeleteInterp(compute);
			}
			TclGetNumberFromObj(NULL, sum, &cd, &numType);
			Tcl_GetNumberFromObj(NULL, sum, &cd, &numType);

			if (numType == TCL_NUMBER_INT) {
			    /* sum holds an integer in the signed wide range */
			    offset = *(Tcl_WideInt *)cd;
			} else {
			    /* sum holds an integer outside the signed wide range */
			    /* Truncate to the signed wide range. */
3597
3598
3599
3600
3601
3602
3603
3604

3605
3606
3607
3608
3609
3610

3611
3612
3613
3614
3615
3616
3617
3652
3653
3654
3655
3656
3657
3658

3659
3660
3661
3662
3663
3664

3665
3666
3667
3668
3669
3670
3671
3672







-
+





-
+







	    if (TclIsSpaceProc(bytes[4])) {
		/* Space after + or - not permitted. */
		goto parseError;
	    }

	    /* Parse the integer offset */
	    if (TCL_OK != TclParseNumber(NULL, objPtr, NULL,
			bytes+4, length-4, NULL, TCL_PARSE_INTEGER_ONLY)) {
		    bytes + 4, length - 4, NULL, TCL_PARSE_INTEGER_ONLY)) {
		/* Not a recognized integer format */
		goto parseError;
	    }

	    /* Got an integer offset; pull it from where parser left it. */
	    TclGetNumberFromObj(NULL, objPtr, &cd, &t);
	    Tcl_GetNumberFromObj(NULL, objPtr, &cd, &t);

	    if (t == TCL_NUMBER_BIG) {
		/* Truncate to the signed wide range. */
		if (mp_isneg((mp_int *)cd)) {
		    offset = (bytes[3] == '-') ? WIDE_MAX : WIDE_MIN;
		} else {
		    offset = (bytes[3] == '-') ? WIDE_MIN : WIDE_MAX;
3631
3632
3633
3634
3635
3636
3637
3638

3639
3640
3641
3642
3643









3644

3645
3646

3647
3648
3649
3650

3651
3652
3653
3654

3655

3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669








3670
3671
3672
3673
3674
3675
3676
3677
3678




3679
3680
3681
3682

3683
3684

3685
3686
3687
3688
3689
3690
3691










3692
3693
3694
3695
3696
3697
3698
3686
3687
3688
3689
3690
3691
3692

3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707

3708
3709

3710


3711

3712
3713


3714
3715

3716
3717
3718
3719
3720
3721
3722








3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746

3747
3748

3749







3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766







-
+





+
+
+
+
+
+
+
+
+
-
+

-
+
-
-

-
+

-
-

+
-
+






-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+









+
+
+
+



-
+

-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+







		}
	    }
	}

    parseOK:
	/* Success. Store the new internal rep. */
	ir.wideValue = offset;
	Tcl_StoreIntRep(objPtr, &endOffsetType, &ir);
	Tcl_StoreInternalRep(objPtr, &endOffsetType, &ir);
    }

    offset = irPtr->wideValue;

    if (offset == WIDE_MAX) {
	/*
	 * Encodes end+1. This is distinguished from end+n as noted
	 * in function header.
	 * NOTE: this may wrap around if the caller passes (as lset does)
	 * listLen-1 as endValue and listLen is 0. The -1 will be
	 * interpreted as FF...FF and adding 1 will result in 0 which
	 * is what we want. Callers like lset which pass in listLen-1 == -1
	 * as endValue will have to adjust accordingly.
	 */
	*widePtr = endValue + 1;
	*widePtr = (endValue == -1) ? WIDE_MAX : endValue + 1;
    } else if (offset == WIDE_MIN) {
	*widePtr = -1;
	*widePtr = (endValue == -1) ? WIDE_MIN : -1;
    } else if (endValue == (size_t)-1) {
	*widePtr = offset;
    } else if (offset < 0) {
	/* Different signs, sum cannot overflow */
	/* end-(n-1) - Different signs, sum cannot overflow */
	*widePtr = endValue + offset + 1;
    } else if (offset < WIDE_MAX) {
	*widePtr = offset;
    } else {
	/* 0:WIDE_MAX - plain old index. */
	*widePtr = WIDE_MAX;
	*widePtr = offset;
    }
    return TCL_OK;

    /* Report a parse error. */
  parseError:
    if (interp != NULL) {
        char * bytes = TclGetString(objPtr);
        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                "bad index \"%s\": must be integer?[+-]integer? or"
                " end?[+-]integer?", bytes));
        if (!strncmp(bytes, "end-", 4)) {
            bytes += 4;
        }
        Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", NULL);
	char * bytes = TclGetString(objPtr);
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"bad index \"%s\": must be integer?[+-]integer? or"
		" end?[+-]integer?", bytes));
	if (!strncmp(bytes, "end-", 4)) {
	    bytes += 4;
	}
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", (char *)NULL);
    }

    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TclIndexEncode --
 *      IMPORTANT: function only encodes indices in the range that fits within
 *      an "int" type. Do NOT change this as the byte code compiler and engine
 *      which call this function cannot handle wider index types. Indices
 *      outside the range will result in the function returning an error.
 *
 *      Parse objPtr to determine if it is an index value. Two cases
 *	are possible.  The value objPtr might be parsed as an absolute
 *	index value in the C signed int range.  Note that this includes
 *	index value in the Tcl_Size range.  Note that this includes
 *	index values that are integers as presented and it includes index
 *      arithmetic expressions. The absolute index values that can be
 *      arithmetic expressions.
 *	directly meaningful as an index into either a list or a string are
 *	those integer values >= TCL_INDEX_START (0)
 *	and < INT_MAX.
 *      The largest string supported in Tcl 8 has bytelength INT_MAX.
 *      This means the largest supported character length is also INT_MAX,
 *      and the index of the last character in a string of length INT_MAX
 *      is INT_MAX-1.
 *
 *      The largest string supported in Tcl 8 has byte length TCL_SIZE_MAX.
 *      This means the largest supported character length is also TCL_SIZE_MAX,
 *      and the index of the last character in a string of length TCL_SIZE_MAX
 *      is TCL_SIZE_MAX-1. Thus the absolute index values that can be
 *	directly meaningful as an index into either a list or a string are
 *	integer values in the range 0 to TCL_SIZE_MAX - 1.
 *
 *      This function however can only handle integer indices in the range
 *      0 : INT_MAX-1.
 *
 *      Any absolute index value parsed outside that range is encoded
 *      using the before and after values passed in by the
 *      caller as the encoding to use for indices that are either
 *      less than or greater than the usable index range. TCL_INDEX_NONE
 *      is available as a good choice for most callers to use for
 *      after. Likewise, the value TCL_INDEX_NONE is good for
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721


3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735


3736
3737
3738
3739

3740

3741
3742
3743
3744
3745
3746

















































3747
3748
3749




3750





3751

3752
3753
3754




3755
3756
3757
3758


3759
3760
3761

3762
3763
3764

3765
3766






























3767
3768







3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786

3787
3788
3789

3790
3791

3792
3793

3794
3795


3796
3797
3798




































3799
3800
3801
3802
3803
3804
3805
3777
3778
3779
3780
3781
3782
3783




3784

3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798


3799
3800
3801
3802
3803
3804
3805
3806
3807






3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857


3858
3859
3860
3861
3862
3863
3864
3865
3866
3867

3868
3869


3870
3871
3872
3873
3874
3875


3876
3877
3878
3879

3880
3881
3882
3883
3884


3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940

3941
3942
3943

3944
3945

3946
3947
3948
3949


3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997







-
-
-
-

-
+
+












-
-
+
+




+

+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+
+

+
+
+
+
+
-
+

-
-
+
+
+
+


-
-
+
+


-
+



+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+

















-
+


-
+

-
+


+
-
-
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *      index "end" is encoded as -2, down to the index "end-0x7FFFFFFE"
 *      which is encoded as INT_MIN. Since the largest index into a
 *      string possible in Tcl 8 is 0x7FFFFFFE, the interpretation of
 *      "end-0x7FFFFFFE" for that largest string would be 0.  Thus,
 *      if the tokens "end-0x7FFFFFFF" or "end+-0x80000000" are parsed,
 *      they can be encoded with the before value.
 *
 *      These details will require re-examination whenever string and
 *      list length limits are increased, but that will likely also
 *      mean a revised routine capable of returning Tcl_WideInt values.
 *
 * Returns:
 *      TCL_OK if parsing succeeded, and TCL_ERROR if it failed.
 *      TCL_OK if parsing succeeded, and TCL_ERROR if it failed or the
 *      index does not fit in an int type.
 *
 * Side effects:
 *      When TCL_OK is returned, the encoded index value is written
 *      to *indexPtr.
 *
 *----------------------------------------------------------------------
 */

int
TclIndexEncode(
    Tcl_Interp *interp,	/* For error reporting, may be NULL */
    Tcl_Obj *objPtr,	/* Index value to parse */
    size_t before,		/* Value to return for index before beginning */
    size_t after,		/* Value to return for index after end */
    int before,		/* Value to return for index before beginning */
    int after,		/* Value to return for index after end */
    int *indexPtr)	/* Where to write the encoded answer, not NULL */
{
    Tcl_WideInt wide;
    int idx;
    const Tcl_WideInt ENDVALUE = 2 * (Tcl_WideInt) INT_MAX;

    assert(ENDVALUE < WIDE_MAX);
    if (TCL_OK == GetWideForIndex(interp, objPtr, (unsigned)TCL_INDEX_END , &wide)) {
	const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objPtr, &endOffsetType);
	if (irPtr && irPtr->wideValue >= 0) {
	    /* "int[+-]int" syntax, works the same here as "int" */
	    irPtr = NULL;
	}
    if (TCL_OK != GetWideForIndex(interp, objPtr, ENDVALUE, &wide)) {
	return TCL_ERROR;
    }
    /*
     * We passed 2*INT_MAX as the "end value" to GetWideForIndex. The computed
     * index will be in one of the following ranges that need to be
     * distinguished for encoding purposes in the following code.
     * (1) 0:INT_MAX when
     *     (a) objPtr was a pure non-negative numeric value in that range
     *     (b) objPtr was a numeric computation M+/-N with a result in that range
     *     (c) objPtr was of the form end-N where N was in range INT_MAX:2*INT_MAX
     * (2) INT_MAX+1:2*INT_MAX when
     *     (a,b) as above
     *     (c) objPtr was of the form end-N where N was in range 0:INT_MAX-1
     * (3) 2*INT_MAX:WIDE_MAX when
     *     (a,b) as above
     *     (c) objPtr was of the form end+N
     * (4) (2*INT_MAX)-TCL_SIZE_MAX : -1 when
     *     (a,b) as above
     *     (c) objPtr was of the form end-N where N was in the range 0:TCL_SIZE_MAX
     * (5) WIDE_MIN:(2*INT_MAX)-TCL_SIZE_MAX
     *     (a,b) as above
     *     (c) objPtr was of the form end-N where N was > TCL_SIZE_MAX
     *
     * For all cases (b) and (c), the internal representation of objPtr
     * will be shimmered to endOffsetType. That allows us to distinguish between
     * (for example) 1a (encodable) and 1c (not encodable) though the computed
     * index value is the same.
     *
     * Further note, the values TCL_SIZE_MAX < N < WIDE_MAX come into play
     * only in the 32-bit builds as TCL_SIZE_MAX == WIDE_MAX for 64-bits.
     */

    const Tcl_ObjInternalRep *irPtr =
	TclFetchInternalRep(objPtr, &endOffsetType);

    if (irPtr && irPtr->wideValue >= 0) {
	/*
	 * "int[+-]int" syntax, works the same here as "int".
	 * Note same does not hold for negative integers.
	 * Distinguishes 1b and 1c where wide will be in 0:INT_MAX for
	 * both but irPtr->wideValue will be negative for 1c.
	 */
	irPtr = NULL;
    }

    if (irPtr == NULL) {
	/* objPtr can be treated as a purely numeric value. */

	/*
	 * We parsed an end+offset index value.
	 * wide holds the offset value in the range WIDE_MIN...WIDE_MAX.
	 * On 64-bit systems, indices in the range INT_MAX:TCL_SIZE_MAX are
	 * valid indices but are not in the encodable range. Thus an
	 * error is raised. On 32-bit systems, indices in that range indicate
	 * the position after the end and so do not raise an error.
	 */
	if ((sizeof(int) != sizeof(Tcl_Size)) &&
		(wide > INT_MAX) && (wide < WIDE_MAX-1)) {
	    /* 2(a,b) on 64-bit systems*/
	    goto rangeerror;
	}
	if (wide > (unsigned)(irPtr ? TCL_INDEX_END : INT_MAX)) {
	if (wide > INT_MAX) {
	    /*
	     * All end+postive or end-negative expressions
	     * always indicate "after the end".
	     * 3(a,b) on 64-bit systems and 2(a,b), 3(a,b) on 32-bit systems
	     * Because of the check above, this case holds for indices
	     * greater than INT_MAX on 32-bit systems and > TCL_SIZE_MAX
	     * on 64-bit systems. Always maps to the element after the end.
	     */
	    idx = after;
	} else if (wide <= (irPtr ? INT_MAX : -1)) {
	    /* These indices always indicate "before the beginning */
	} else if (wide < 0) {
	    /* 4(a,b) (32-bit systems), 5(a,b) - before the beginning */
	    idx = before;
	} else {
	    /* Encoded end-positive (or end+negative) are offset */
	    /* 1(a,b) Encodable range */
	    idx = (int)wide;
	}
    } else {
	/* objPtr is not purely numeric (end etc.)  */
	return TCL_ERROR;
    }

	/*
	 * On 64-bit systems, indices in the range end-LIST_MAX:end-INT_MAX
	 * are valid indices (with max size strings/lists) but are not in
	 * the encodable range. Thus an error is raised. On 32-bit systems,
	 * indices in that range indicate the position before the beginning
	 * and so do not raise an error.
	 */
	if ((sizeof(int) != sizeof(Tcl_Size)) &&
		(wide > (ENDVALUE - LIST_MAX)) && (wide <= INT_MAX)) {
	    /* 1(c), 4(a,b) on 64-bit systems */
	    goto rangeerror;
	}
	if (wide > ENDVALUE) {
	    /*
	     * 2(c) (32-bit systems), 3(c)
	     * All end+positive or end-negative expressions
	     * always indicate "after the end".
	     * Note we will not reach here for a pure numeric value in this
	     * range because irPtr will be NULL in that case.
	     */
	    idx = after;
	} else if (wide <= INT_MAX) {
	    /* 1(c) (32-bit systems), 4(c) (32-bit systems), 5(c) */
	    idx = before;
	} else {
	    /* 2(c) Encodable end-positive (or end+negative) */
	    idx = (int)wide;
	}
    }
    *indexPtr = idx;
    return TCL_OK;

rangeerror:
    if (interp) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("index \"%s\" out of range", TclGetString(objPtr)));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", "OUTOFRANGE", (char *)NULL);
    }
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TclIndexDecode --
 *
 *	Decodes a value previously encoded by TclIndexEncode.  The argument
 *	endValue indicates what value of "end" should be used in the
 *	decoding.
 *
 * Results:
 *	The decoded index value.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
TclIndexDecode(
    int encoded,	/* Value to decode */
    size_t endValue)	/* Meaning of "end" to use, > TCL_INDEX_END */
    Tcl_Size endValue)	/* Meaning of "end" to use, > TCL_INDEX_END */
{
    if (encoded > (int)TCL_INDEX_END) {
    if (encoded > TCL_INDEX_END) {
	return encoded;
    }
    endValue += encoded - TCL_INDEX_END;
    if (endValue >= TCL_INDEX_END - encoded) {
	return endValue + encoded - TCL_INDEX_END;
    if (endValue >= 0) {
	return endValue;
    }
    return TCL_INDEX_NONE;
}

/*
 *------------------------------------------------------------------------
 *
 * TclCommandWordLimitErrpr --
 *
 *    Generates an error message limit on number of command words exceeded.
 *
 * Results:
 *    Always return TCL_ERROR.
 *
 * Side effects:
 *    If interp is not-NULL, an error message is stored in it.
 *
 *------------------------------------------------------------------------
 */
int
TclCommandWordLimitError(
    Tcl_Interp *interp,   /* May be NULL */
    Tcl_Size count)       /* If <= 0, "unknown" */
{
    if (interp) {
	if (count > 0) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "Number of words (%" TCL_SIZE_MODIFIER
		    "d) in command exceeds limit %" TCL_SIZE_MODIFIER "d.",
		    count, (Tcl_Size)INT_MAX));
	} else {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "Number of words in command exceeds limit %"
		    TCL_SIZE_MODIFIER "d.",
		    (Tcl_Size)INT_MAX));
	}
    }
    return TCL_ERROR; /* Always */
}

/*
 *----------------------------------------------------------------------
 *
 * ClearHash --
 *
 *	Remove all the entries in the hash table *tablePtr.
3868
3869
3870
3871
3872
3873
3874
3875

3876
3877
3878
3879
3880
3881
3882
4060
4061
4062
4063
4064
4065
4066

4067
4068
4069
4070
4071
4072
4073
4074







-
+







 *	Frees a Tcl_HashTable.
 *
 *----------------------------------------------------------------------
 */

static void
FreeThreadHash(
    ClientData clientData)
    void *clientData)
{
    Tcl_HashTable *tablePtr = (Tcl_HashTable *)clientData;

    ClearHash(tablePtr);
    Tcl_DeleteHashTable(tablePtr);
    Tcl_Free(tablePtr);
}
3890
3891
3892
3893
3894
3895
3896
3897

3898
3899
3900
3901
3902
3903
3904
4082
4083
4084
4085
4086
4087
4088

4089
4090
4091
4092
4093
4094
4095
4096







-
+







 *	ProcessGlobalValue at exit.
 *
 *----------------------------------------------------------------------
 */

static void
FreeProcessGlobalValue(
    ClientData clientData)
    void *clientData)
{
    ProcessGlobalValue *pgvPtr = (ProcessGlobalValue *)clientData;

    pgvPtr->epoch++;
    pgvPtr->numBytes = 0;
    Tcl_Free(pgvPtr->value);
    pgvPtr->value = NULL;
3919
3920
3921
3922
3923
3924
3925
3926

3927
3928
3929
3930
3931
3932

3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947



3948
3949


3950
3951
3952
3953

3954
3955
3956
3957

3958
3959
3960
3961
3962
3963
3964
4111
4112
4113
4114
4115
4116
4117

4118

4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143

4144
4145
4146
4147
4148

4149
4150
4151
4152

4153
4154
4155
4156
4157
4158
4159
4160







-
+
-





+















+
+
+

-
+
+



-
+



-
+







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

void
TclSetProcessGlobalValue(
    ProcessGlobalValue *pgvPtr,
    Tcl_Obj *newValue,
    Tcl_Obj *newValue)
    Tcl_Encoding encoding)
{
    const char *bytes;
    Tcl_HashTable *cacheMap;
    Tcl_HashEntry *hPtr;
    int dummy;
    Tcl_DString ds;

    Tcl_MutexLock(&pgvPtr->mutex);

    /*
     * Fill the global string value.
     */

    pgvPtr->epoch++;
    if (NULL != pgvPtr->value) {
	Tcl_Free(pgvPtr->value);
    } else {
	Tcl_CreateExitHandler(FreeProcessGlobalValue, pgvPtr);
    }
    bytes = TclGetString(newValue);
    pgvPtr->numBytes = newValue->length;
    Tcl_UtfToExternalDStringEx(NULL, NULL, bytes, pgvPtr->numBytes,
	    TCL_ENCODING_PROFILE_TCL8, &ds, NULL);
    pgvPtr->numBytes = Tcl_DStringLength(&ds);
    pgvPtr->value = (char *)Tcl_Alloc(pgvPtr->numBytes + 1);
    memcpy(pgvPtr->value, bytes, pgvPtr->numBytes + 1);
    memcpy(pgvPtr->value, Tcl_DStringValue(&ds), pgvPtr->numBytes + 1);
    Tcl_DStringFree(&ds);
    if (pgvPtr->encoding) {
	Tcl_FreeEncoding(pgvPtr->encoding);
    }
    pgvPtr->encoding = encoding;
    pgvPtr->encoding = NULL;

    /*
     * Fill the local thread copy directly with the Tcl_Obj value to avoid
     * loss of the intrep. Increment newValue refCount early to handle case
     * loss of the internalrep. Increment newValue refCount early to handle case
     * where we set a PGV to itself.
     */

    Tcl_IncrRefCount(newValue);
    cacheMap = GetThreadHash(&pgvPtr->key);
    ClearHash(cacheMap);
    hPtr = Tcl_CreateHashEntry(cacheMap, INT2PTR(pgvPtr->epoch), &dummy);
3983
3984
3985
3986
3987
3988
3989
3990


3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002

4003
4004
4005
4006
4007
4008
4009





4010
4011
4012
4013
4014
4015
4016
4179
4180
4181
4182
4183
4184
4185

4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198

4199
4200
4201
4202




4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214







-
+
+











-
+



-
-
-
-
+
+
+
+
+







Tcl_Obj *
TclGetProcessGlobalValue(
    ProcessGlobalValue *pgvPtr)
{
    Tcl_Obj *value = NULL;
    Tcl_HashTable *cacheMap;
    Tcl_HashEntry *hPtr;
    size_t epoch = pgvPtr->epoch;
    Tcl_Size epoch = pgvPtr->epoch;
    Tcl_DString newValue;

    if (pgvPtr->encoding) {
	Tcl_Encoding current = Tcl_GetEncoding(NULL, NULL);

	if (pgvPtr->encoding != current) {
	    /*
	     * The system encoding has changed since the global string value
	     * was saved. Convert the global value to be based on the new
	     * system encoding.
	     */

	    Tcl_DString native, newValue;
	    Tcl_DString native;

	    Tcl_MutexLock(&pgvPtr->mutex);
	    epoch = ++pgvPtr->epoch;
	    Tcl_UtfToExternalDString(pgvPtr->encoding, pgvPtr->value,
		    pgvPtr->numBytes, &native);
	    Tcl_ExternalToUtfDString(current, Tcl_DStringValue(&native),
	    Tcl_DStringLength(&native), &newValue);
	    Tcl_UtfToExternalDStringEx(NULL, pgvPtr->encoding, pgvPtr->value,
		pgvPtr->numBytes, TCL_ENCODING_PROFILE_TCL8, &native, NULL);
	    Tcl_ExternalToUtfDStringEx(NULL, current, Tcl_DStringValue(&native),
		Tcl_DStringLength(&native), TCL_ENCODING_PROFILE_TCL8,
		&newValue, NULL);
	    Tcl_DStringFree(&native);
	    Tcl_Free(pgvPtr->value);
	    pgvPtr->value = (char *)Tcl_Alloc(Tcl_DStringLength(&newValue) + 1);
	    memcpy(pgvPtr->value, Tcl_DStringValue(&newValue),
		    Tcl_DStringLength(&newValue) + 1);
	    Tcl_DStringFree(&newValue);
	    Tcl_FreeEncoding(pgvPtr->encoding);
4045
4046
4047
4048
4049
4050
4051
4052


4053
4054
4055


4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072


4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085

4086
4087

4088
4089
4090
4091
4092
4093
4094
4243
4244
4245
4246
4247
4248
4249

4250
4251
4252
4253

4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286

4287
4288

4289
4290
4291
4292
4293
4294
4295
4296







-
+
+


-
+
+

















+
+












-
+

-
+







	    if (pgvPtr->value == NULL) {
		Tcl_Panic("PGV Initializer did not initialize");
	    }
	    Tcl_CreateExitHandler(FreeProcessGlobalValue, pgvPtr);
	}

	/*
	 * Store a copy of the shared value in our epoch-indexed cache.
	 * Store a copy of the shared value (but then in utf-8)
	 * in our epoch-indexed cache.
	 */

	value = Tcl_NewStringObj(pgvPtr->value, pgvPtr->numBytes);
	Tcl_ExternalToUtfDString(NULL, pgvPtr->value, pgvPtr->numBytes, &newValue);
	value = Tcl_DStringToObj(&newValue);
	hPtr = Tcl_CreateHashEntry(cacheMap,
		INT2PTR(pgvPtr->epoch), &dummy);
	Tcl_MutexUnlock(&pgvPtr->mutex);
	Tcl_SetHashValue(hPtr, value);
	Tcl_IncrRefCount(value);
    }
    return (Tcl_Obj *)Tcl_GetHashValue(hPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TclSetObjNameOfExecutable --
 *
 *	This function stores the absolute pathname of the executable file
 *	(normally as computed by TclpFindExecutable).
 *
 *	Starting with Tcl 9.0, encoding parameter is not used any more.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Stores the executable name.
 *
 *----------------------------------------------------------------------
 */

void
TclSetObjNameOfExecutable(
    Tcl_Obj *name,
    Tcl_Encoding encoding)
    TCL_UNUSED(Tcl_Encoding))
{
    TclSetProcessGlobalValue(&executableName, name, encoding);
    TclSetProcessGlobalValue(&executableName, name);
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetObjNameOfExecutable --
 *
4189
4190
4191
4192
4193
4194
4195
4196

4197
4198
4199
4200
4201
4202
4203
4391
4392
4393
4394
4395
4396
4397

4398
4399
4400
4401
4402
4403
4404
4405







-
+







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

int
TclReToGlob(
    Tcl_Interp *interp,
    const char *reStr,
    size_t reStrLen,
    Tcl_Size reStrLen,
    Tcl_DString *dsPtr,
    int *exactPtr,
    int *quantifiersFoundPtr)
{
    int anchorLeft, anchorRight, lastIsStar, numStars;
    char *dsStr, *dsStrStart;
    const char *msg, *p, *strEnd, *code;
4383
4384
4385
4386
4387
4388
4389
4390

4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4585
4586
4587
4588
4589
4590
4591

4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604







-
+












    }

    return TCL_OK;

  invalidGlob:
    if (interp != NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1));
	Tcl_SetErrorCode(interp, "TCL", "RE2GLOB", code, NULL);
	Tcl_SetErrorCode(interp, "TCL", "RE2GLOB", code, (char *)NULL);
    }
    Tcl_DStringFree(dsPtr);
    return TCL_ERROR;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclVar.c.

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
30
31
32
33

34
35
36
37
38
39
40
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
30
31
32

33
34
35
36
37
38
39
40









-
-
-
-
-
+
+
+
+
+


















-
+







/*
 * tclVar.c --
 *
 *	This file contains routines that implement Tcl variables (both scalars
 *	and arrays).
 *
 *	The implementation of arrays is modelled after an initial
 *	implementation by Mark Diekhans and Karl Lehenbauer.
 *
 * Copyright (c) 1987-1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
 * Copyright (c) 2007 Miguel Sofer
 * Copyright © 1987-1994 The Regents of the University of California.
 * Copyright © 1994-1997 Sun Microsystems, Inc.
 * Copyright © 1998-1999 Scriptics Corporation.
 * Copyright © 2001 Kevin B. Kenny. All rights reserved.
 * Copyright © 2007 Miguel Sofer
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclOOInt.h"

/*
 * Prototypes for the variable hash key methods.
 */

static Tcl_HashEntry *	AllocVarEntry(Tcl_HashTable *tablePtr, void *keyPtr);
static void		FreeVarEntry(Tcl_HashEntry *hPtr);
static int		CompareVarKeys(void *keyPtr, Tcl_HashEntry *hPtr);

static const Tcl_HashKeyType tclVarHashKeyType = {
    TCL_HASH_KEY_TYPE_VERSION,	/* version */
    0,				/* flags */
    TCL_HASH_KEY_DIRECT_COMPARE,/* allows compare keys by pointers */
    TclHashObjKey,		/* hashKeyProc */
    CompareVarKeys,		/* compareKeysProc */
    AllocVarEntry,		/* allocEntryProc */
    FreeVarEntry		/* freeEntryProc */
};

static inline Var *	VarHashCreateVar(TclVarHashTable *tablePtr,
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
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







-
-
-




















+
+








    if (!hPtr) {
	return NULL;
    }
    return VarHashGetValue(hPtr);
}

#define VarHashGetKey(varPtr) \
    (((VarInHash *)(varPtr))->entry.key.objPtr)

#define VarHashDeleteTable(tablePtr) \
    Tcl_DeleteHashTable(&(tablePtr)->table)

/*
 * The strings below are used to indicate what went wrong when a variable
 * access is denied.
 */

static const char NOSUCHVAR[] =		"no such variable";
static const char ISARRAY[] =		"variable is array";
static const char NEEDARRAY[] =		"variable isn't array";
static const char NOSUCHELEMENT[] =	"no such element in array";
static const char DANGLINGELEMENT[] =
	"upvar refers to element in deleted array";
static const char DANGLINGVAR[] =
	"upvar refers to variable in deleted namespace";
static const char BADNAMESPACE[] =	"parent namespace doesn't exist";
static const char MISSINGNAME[] =	"missing variable name";
static const char ISARRAYELEMENT[] =
	"name refers to an element in an array";
static const char ISCONST[] =		"variable is a constant";
static const char EXISTS[] =		"variable already exists";

/*
 * A test to see if we are in a call frame that has local variables. This is
 * true if we are inside a procedure body.
 */

#define HasLocalVars(framePtr) ((framePtr)->isProcCallFrame & FRAME_IS_PROC)
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
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







-
+
+


















-
+











-
+
-
-









-
+







} ArrayVarHashTable;

/*
 * Forward references to functions defined later in this file:
 */

static void		AppendLocals(Tcl_Interp *interp, Tcl_Obj *listPtr,
			    Tcl_Obj *patternPtr, int includeLinks);
			    Tcl_Obj *patternPtr, int includeLinks,
			    int justConstants);
static void		ArrayPopulateSearch(Tcl_Interp *interp,
			    Tcl_Obj *arrayNameObj, Var *varPtr,
			    ArraySearch *searchPtr);
static void		ArrayDoneSearch(Interp *iPtr, Var *varPtr,
			    ArraySearch *searchPtr);
static Tcl_NRPostProc   ArrayForLoopCallback;
static Tcl_ObjCmdProc	ArrayForNRCmd;
static void		DeleteSearches(Interp *iPtr, Var *arrayVarPtr);
static void		DeleteArray(Interp *iPtr, Tcl_Obj *arrayNamePtr,
			    Var *varPtr, int flags, int index);
static int		LocateArray(Tcl_Interp *interp, Tcl_Obj *name,
			    Var **varPtrPtr, int *isArrayPtr);
static int		NotArrayError(Tcl_Interp *interp, Tcl_Obj *name);
static Tcl_Var		ObjFindNamespaceVar(Tcl_Interp *interp,
			    Tcl_Obj *namePtr, Tcl_Namespace *contextNsPtr,
			    int flags);
static int		ObjMakeUpvar(Tcl_Interp *interp,
			    CallFrame *framePtr, Tcl_Obj *otherP1Ptr,
			    const char *otherP2, const int otherFlags,
			    const char *otherP2, int otherFlags,
			    Tcl_Obj *myNamePtr, int myFlags, int index);
static ArraySearch *	ParseSearchId(Tcl_Interp *interp, const Var *varPtr,
			    Tcl_Obj *varNamePtr, Tcl_Obj *handleObj);
static void		UnsetVarStruct(Var *varPtr, Var *arrayPtr,
			    Interp *iPtr, Tcl_Obj *part1Ptr,
			    Tcl_Obj *part2Ptr, int flags, int index);

/*
 * TIP #508: [array default]
 */

static int		ArrayDefaultCmd(ClientData clientData,
static Tcl_ObjCmdProc	ArrayDefaultCmd;
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static void		DeleteArrayVar(Var *arrayPtr);
static void		SetArrayDefault(Var *arrayPtr, Tcl_Obj *defaultObj);

/*
 * Functions defined in this file that may be exported in the future for use
 * by the bytecode compiler and engine or to the public interface.
 */

MODULE_SCOPE Var *	TclLookupSimpleVar(Tcl_Interp *interp,
			    Tcl_Obj *varNamePtr, int flags, const int create,
			    Tcl_Obj *varNamePtr, int flags, int create,
			    const char **errMsgPtr, int *indexPtr);

static Tcl_DupInternalRepProc	DupLocalVarName;
static Tcl_FreeInternalRepProc	FreeLocalVarName;

static Tcl_FreeInternalRepProc	FreeParsedVarName;
static Tcl_DupInternalRepProc	DupParsedVarName;
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
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







-
+
+


-
+

-
+




-
+


-
+

-
-
-
-
+
+
+
+




-
+
+


-
+

-
+






-
+


-
+

-
-
+
+

-
-
+
+







 *			scalar variable
 *   twoPtrValue.ptr2:	pointer to the element name string (owned by this
 *			Tcl_Obj), or NULL if it is a scalar variable
 */

static const Tcl_ObjType localVarNameType = {
    "localVarName",
    FreeLocalVarName, DupLocalVarName, NULL, NULL
    FreeLocalVarName, DupLocalVarName, NULL, NULL,
    TCL_OBJTYPE_V0
};

#define LocalSetIntRep(objPtr, index, namePtr)				\
#define LocalSetInternalRep(objPtr, index, namePtr)			\
    do {								\
	Tcl_ObjIntRep ir;						\
	Tcl_ObjInternalRep ir;						\
	Tcl_Obj *ptr = (namePtr);					\
	if (ptr) {Tcl_IncrRefCount(ptr);}				\
	ir.twoPtrValue.ptr1 = ptr;					\
	ir.twoPtrValue.ptr2 = INT2PTR(index);				\
	Tcl_StoreIntRep((objPtr), &localVarNameType, &ir);		\
	Tcl_StoreInternalRep((objPtr), &localVarNameType, &ir);		\
    } while (0)

#define LocalGetIntRep(objPtr, index, name)				\
#define LocalGetInternalRep(objPtr, index, name)			\
    do {								\
	const Tcl_ObjIntRep *irPtr;					\
	irPtr = TclFetchIntRep((objPtr), &localVarNameType);		\
	(name) = irPtr ? (Tcl_Obj *)irPtr->twoPtrValue.ptr1 : NULL;		\
	(index) = irPtr ? PTR2INT(irPtr->twoPtrValue.ptr2) : -1;	\
	const Tcl_ObjInternalRep *irPtr;				\
	irPtr = TclFetchInternalRep((objPtr), &localVarNameType);	\
	(name) = irPtr ? (Tcl_Obj *)irPtr->twoPtrValue.ptr1 : NULL;	\
	(index) = irPtr ? PTR2INT(irPtr->twoPtrValue.ptr2) : TCL_INDEX_NONE; \
    } while (0)

static const Tcl_ObjType parsedVarNameType = {
    "parsedVarName",
    FreeParsedVarName, DupParsedVarName, NULL, NULL
    FreeParsedVarName, DupParsedVarName, NULL, NULL,
    TCL_OBJTYPE_V0
};

#define ParsedSetIntRep(objPtr, arrayPtr, elem)				\
#define ParsedSetInternalRep(objPtr, arrayPtr, elem)			\
    do {								\
	Tcl_ObjIntRep ir;						\
	Tcl_ObjInternalRep ir;						\
	Tcl_Obj *ptr1 = (arrayPtr);					\
	Tcl_Obj *ptr2 = (elem);						\
	if (ptr1) {Tcl_IncrRefCount(ptr1);}				\
	if (ptr2) {Tcl_IncrRefCount(ptr2);}				\
	ir.twoPtrValue.ptr1 = ptr1;					\
	ir.twoPtrValue.ptr2 = ptr2;					\
	Tcl_StoreIntRep((objPtr), &parsedVarNameType, &ir);		\
	Tcl_StoreInternalRep((objPtr), &parsedVarNameType, &ir);	\
    } while (0)

#define ParsedGetIntRep(objPtr, parsed, array, elem)			\
#define ParsedGetInternalRep(objPtr, parsed, array, elem)		\
    do {								\
	const Tcl_ObjIntRep *irPtr;					\
	irPtr = TclFetchIntRep((objPtr), &parsedVarNameType);		\
	const Tcl_ObjInternalRep *irPtr;				\
	irPtr = TclFetchInternalRep((objPtr), &parsedVarNameType);	\
	(parsed) = (irPtr != NULL);					\
	(array) = irPtr ? (Tcl_Obj *)irPtr->twoPtrValue.ptr1 : NULL;		\
	(elem) = irPtr ? (Tcl_Obj *)irPtr->twoPtrValue.ptr2 : NULL;		\
	(array) = irPtr ? (Tcl_Obj *)irPtr->twoPtrValue.ptr1 : NULL;	\
	(elem) = irPtr ? (Tcl_Obj *)irPtr->twoPtrValue.ptr2 : NULL;	\
    } while (0)

Var *
TclVarHashCreateVar(
    TclVarHashTable *tablePtr,
    const char *key,
    int *newPtr)
342
343
344
345
346
347
348
349

350
351
352
353
354
355
356
342
343
344
345
346
347
348

349
350
351
352
353
354
355
356







-
+







    Tcl_Interp *interp,
    Tcl_Obj *name)
{
    const char *nameStr = TclGetString(name);

    Tcl_SetObjResult(interp,
	    Tcl_ObjPrintf("\"%s\" isn't an array", nameStr));
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", nameStr, NULL);
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", nameStr, (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCleanupVar --
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
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







-
+









-
+







    Var *varPtr,		/* Pointer to variable that may be a candidate
				 * for being expunged. */
    Var *arrayPtr)		/* Array that contains the variable, or NULL
				 * if this variable isn't an array element. */
{
    if (TclIsVarUndefined(varPtr) && TclIsVarInHash(varPtr)
	    && !TclIsVarTraced(varPtr)
	    && (VarHashRefCount(varPtr) == (unsigned)
	    && (VarHashRefCount(varPtr) == (Tcl_Size)
		    !TclIsVarDeadHash(varPtr))) {
	if (VarHashRefCount(varPtr) == 0) {
	    Tcl_Free(varPtr);
	} else {
	    VarHashDeleteEntry(varPtr);
	}
    }
    if (arrayPtr != NULL && TclIsVarUndefined(arrayPtr) &&
	    TclIsVarInHash(arrayPtr) && !TclIsVarTraced(arrayPtr) &&
	    (VarHashRefCount(arrayPtr) == (unsigned)
	    (VarHashRefCount(arrayPtr) == (Tcl_Size)
		    !TclIsVarDeadHash(arrayPtr))) {
	if (VarHashRefCount(arrayPtr) == 0) {
	    Tcl_Free(arrayPtr);
	} else {
	    VarHashDeleteEntry(arrayPtr);
	}
    }
414
415
416
417
418
419
420
421

422
423
424
425
426
427
428
414
415
416
417
418
419
420

421
422
423
424
425
426
427
428







-
+







/*
 *----------------------------------------------------------------------
 *
 * TclLookupVar --
 *
 *	This function is used to locate a variable given its name(s). It has
 *	been mostly superseded by TclObjLookupVar, it is now only used by the
 *	trace code. It is kept in tcl8.5 mainly because it is in the internal
 *	trace code. It is kept in tcl9.0 mainly because it is in the internal
 *	stubs table, so that some extension may be calling it.
 *
 * Results:
 *	The return value is a pointer to the variable structure indicated by
 *	part1 and part2, or NULL if the variable couldn't be found. If the
 *	variable is found, *arrayPtrPtr is filled in with the address of the
 *	variable structure for the array that contains the variable (or NULL
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
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







-
+









-
+


-
+







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

Var *
TclObjLookupVar(
    Tcl_Interp *interp,		/* Interpreter to use for lookup. */
    Tcl_Obj *part1Ptr,	/* If part2 isn't NULL, this is the name of an
    Tcl_Obj *part1Ptr,		/* If part2 isn't NULL, this is the name of an
				 * array. Otherwise, this is a full variable
				 * name that could include a parenthesized
				 * array element. */
    const char *part2,		/* Name of element within array, or NULL. */
    int flags,			/* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
				 * and TCL_LEAVE_ERR_MSG bits matter. */
    const char *msg,		/* Verb to use in error messages, e.g. "read"
				 * or "set". Only needed if TCL_LEAVE_ERR_MSG
				 * is set in flags. */
    const int createPart1,	/* If 1, create hash table entry for part 1 of
    int createPart1,		/* If 1, create hash table entry for part 1 of
				 * name, if it doesn't already exist. If 0,
				 * return error if it doesn't exist. */
    const int createPart2,	/* If 1, create hash table entry for part 2 of
    int createPart2,		/* If 1, create hash table entry for part 2 of
				 * name, if it doesn't already exist. If 0,
				 * return error if it doesn't exist. */
    Var **arrayPtrPtr)		/* If the name refers to an element of an
				 * array, *arrayPtrPtr gets filled in with
				 * address of array variable. Otherwise this
				 * is set to NULL. */
{
587
588
589
590
591
592
593
594

595
596
597

598
599
600
601
602
603
604
605
606
607
608
609
610
611
612

613
614
615
616
617
618

619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639

640
641
642

643
644
645
646
647
648
649
650
651
652
653

654
655
656
657
658
659
660
661
662
663
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
707

708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724

725
726
727
728
729

730
731
732
733

734
735
736
737
738
739
740
741
742

743
744
745

746
747
748

749
750
751
752

753
754
755
756
757
758
759

760
761
762
763
764
765
766
587
588
589
590
591
592
593

594
595
596

597
598
599
600
601
602
603
604
605
606
607
608
609
610
611

612
613
614
615
616
617

618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638

639
640
641

642
643
644
645
646
647
648
649
650
651
652

653
654
655
656
657
658
659
660
661
662
663
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

707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723

724
725
726
727
728

729
730
731
732

733
734
735
736
737
738
739
740
741

742
743
744

745
746
747

748
749
750
751

752
753
754
755
756
757
758

759
760
761
762
763
764
765
766







-
+


-
+














-
+





-
+




















-
+


-
+










-
+













-
+











-
+








-
+


















-
+
















-
+




-
+



-
+








-
+


-
+


-
+



-
+






-
+







				 * parenthesized array element. */
    Tcl_Obj *part2Ptr,		/* Name of element within array, or NULL. */
    int flags,			/* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
				 * and TCL_LEAVE_ERR_MSG bits matter. */
    const char *msg,		/* Verb to use in error messages, e.g. "read"
				 * or "set". Only needed if TCL_LEAVE_ERR_MSG
				 * is set in flags. */
    const int createPart1,	/* If 1, create hash table entry for part 1 of
    int createPart1,		/* If 1, create hash table entry for part 1 of
				 * name, if it doesn't already exist. If 0,
				 * return error if it doesn't exist. */
    const int createPart2,	/* If 1, create hash table entry for part 2 of
    int createPart2,		/* If 1, create hash table entry for part 2 of
				 * name, if it doesn't already exist. If 0,
				 * return error if it doesn't exist. */
    Var **arrayPtrPtr)		/* If the name refers to an element of an
				 * array, *arrayPtrPtr gets filled in with
				 * address of array variable. Otherwise this
				 * is set to NULL. */
{
    Interp *iPtr = (Interp *) interp;
    CallFrame *varFramePtr = iPtr->varFramePtr;
    Var *varPtr;	/* Points to the variable's in-frame Var
				 * structure. */
    const char *errMsg = NULL;
    int index, parsed = 0;

    int localIndex;
    Tcl_Size localIndex;
    Tcl_Obj *namePtr, *arrayPtr, *elem;

    *arrayPtrPtr = NULL;

  restart:
    LocalGetIntRep(part1Ptr, localIndex, namePtr);
    LocalGetInternalRep(part1Ptr, localIndex, namePtr);
    if (localIndex >= 0) {
	if (HasLocalVars(varFramePtr)
		&& !(flags & (TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY))
		&& (localIndex < varFramePtr->numCompiledLocals)) {
	    /*
	     * Use the cached index if the names coincide.
	     */

	    Tcl_Obj *checkNamePtr = localName(varFramePtr, localIndex);

	    if ((!namePtr && (checkNamePtr == part1Ptr)) ||
		    (namePtr && (checkNamePtr == namePtr))) {
		varPtr = (Var *) &(varFramePtr->compiledLocals[localIndex]);
		goto donePart1;
	    }
	}
	goto doneParsing;
    }

    /*
     * If part1Ptr is a parsedVarNameType, retrieve the pre-parsed parts.
     * If part1Ptr is a parsedVarNameType, retrieve the preparsed parts.
     */

    ParsedGetIntRep(part1Ptr, parsed, arrayPtr, elem);
    ParsedGetInternalRep(part1Ptr, parsed, arrayPtr, elem);
    if (parsed && arrayPtr) {
	    if (part2Ptr != NULL) {
		/*
		 * ERROR: part1Ptr is already an array element, cannot specify
		 * a part2.
		 */

		if (flags & TCL_LEAVE_ERR_MSG) {
		    TclObjVarErrMsg(interp, part1Ptr, part2Ptr, msg,
			    NOSUCHVAR, -1);
		    Tcl_SetErrorCode(interp, "TCL", "VALUE", "VARNAME", NULL);
		    Tcl_SetErrorCode(interp, "TCL", "VALUE", "VARNAME", (char *)NULL);
		}
		return NULL;
	    }
	    part2Ptr = elem;
	    part1Ptr = arrayPtr;
	    goto restart;
    }

    if (!parsed) {
	/*
	 * part1Ptr is possibly an unparsed array element.
	 */

	size_t len;
	Tcl_Size len;
	const char *part1 = TclGetStringFromObj(part1Ptr, &len);

	if ((len > 1) && (part1[len - 1] == ')')) {
	    const char *part2 = strchr(part1, '(');

	    if (part2) {
		if (part2Ptr != NULL) {
		    if (flags & TCL_LEAVE_ERR_MSG) {
			TclObjVarErrMsg(interp, part1Ptr, part2Ptr, msg,
				NEEDARRAY, -1);
			Tcl_SetErrorCode(interp, "TCL", "VALUE", "VARNAME",
				NULL);
				(char *)NULL);
		    }
		    return NULL;
		}

		arrayPtr = Tcl_NewStringObj(part1, (part2 - part1));
		part2Ptr = Tcl_NewStringObj(part2 + 1,
			len - (part2 - part1) - 2);

		ParsedSetIntRep(part1Ptr, arrayPtr, part2Ptr);
		ParsedSetInternalRep(part1Ptr, arrayPtr, part2Ptr);

		part1Ptr = arrayPtr;
	    }
	}
    }

  doneParsing:
    /*
     * part1Ptr is not an array element; look it up, and convert it to one of
     * the cached types if possible.
     */

    varPtr = TclLookupSimpleVar(interp, part1Ptr, flags, createPart1,
	    &errMsg, &index);
    if (varPtr == NULL) {
	if ((errMsg != NULL) && (flags & TCL_LEAVE_ERR_MSG)) {
	    TclObjVarErrMsg(interp, part1Ptr, part2Ptr, msg, errMsg, -1);
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME",
		    TclGetString(part1Ptr), NULL);
		    TclGetString(part1Ptr), (char *)NULL);
	}
	return NULL;
    }

    /*
     * Cache the newly found variable if possible.
     */

    if (index >= 0) {
	/*
	 * An indexed local variable.
	 */

	Tcl_Obj *cachedNamePtr = localName(varFramePtr, index);

	if (part1Ptr == cachedNamePtr) {
	    LocalSetIntRep(part1Ptr, index, NULL);
	    LocalSetInternalRep(part1Ptr, index, NULL);
	} else {
	    /*
	     * [80304238ac] Trickiness here.  We will store and incr the
	     * refcount on cachedNamePtr.  Trouble is that it's possible
	     * (see test var-22.1) for cachedNamePtr to have an intrep
	     * (see test var-22.1) for cachedNamePtr to have an internalrep
	     * that contains a stored and refcounted part1Ptr.  This
	     * would be a reference cycle which leads to a memory leak.
	     *
	     * The solution here is to wipe away all intrep(s) in
	     * The solution here is to wipe away all internalrep(s) in
	     * cachedNamePtr and leave it as string only.  This is
	     * radical and destructive, so a better idea would be welcome.
	     */

	    /*
	     * Firstly set cached local var reference (avoid free before set,
	     * see [45b9faf103f2])
	     */
	    LocalSetIntRep(part1Ptr, index, cachedNamePtr);
	    LocalSetInternalRep(part1Ptr, index, cachedNamePtr);

	    /* Then wipe it */
	    TclFreeIntRep(cachedNamePtr);
	    TclFreeInternalRep(cachedNamePtr);

	    /*
	     * Now go ahead and convert it the the "localVarName" type,
	     * Now go ahead and convert it to the "localVarName" type,
	     * since we suspect at least some use of the value as a
	     * varname and we want to resolve it quickly.
	     */
	    LocalSetIntRep(cachedNamePtr, index, NULL);
	    LocalSetInternalRep(cachedNamePtr, index, NULL);
	}
    } else {
	/*
	 * At least mark part1Ptr as already parsed.
	 */

	ParsedSetIntRep(part1Ptr, NULL, NULL);
	ParsedSetInternalRep(part1Ptr, NULL, NULL);
    }

  donePart1:
    while (TclIsVarLink(varPtr)) {
	varPtr = varPtr->value.linkPtr;
    }

793
794
795
796
797
798
799
800

801
802
803
804
805
806
807
793
794
795
796
797
798
799

800
801
802
803
804
805
806
807







-
+







 *
 *	If the current CallFrame corresponds to a proc and the variable found
 *	is one of the compiledLocals, its index is placed in *indexPtr.
 *	Otherwise, *indexPtr will be set to (according to the needs of
 *	TclObjLookupVar):
 *	    -1 a global reference
 *	    -2 a reference to a namespace variable
 *	    -3 a non-cachable reference, i.e., one of:
 *	    -3 a non-cacheable reference, i.e., one of:
 *		. non-indexed local var
 *		. a reference of unknown origin;
 *		. resolution by a namespace or interp resolver
 *
 *	If the variable isn't found and creation wasn't specified, or some
 *	other error occurs, NULL is returned and the corresponding error
 *	message is left in *errMsgPtr.
823
824
825
826
827
828
829
830

831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850


851
852
853
854
855
856
857
823
824
825
826
827
828
829

830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848


849
850
851
852
853
854
855
856
857







-
+


















-
-
+
+







TclLookupSimpleVar(
    Tcl_Interp *interp,		/* Interpreter to use for lookup. */
    Tcl_Obj *varNamePtr,	/* This is a simple variable name that could
				 * represent a scalar or an array. */
    int flags,			/* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
				 * TCL_AVOID_RESOLVERS and TCL_LEAVE_ERR_MSG
				 * bits matter. */
    const int create,		/* If 1, create hash table entry for varname,
    int create,			/* If 1, create hash table entry for varname,
				 * if it doesn't already exist. If 0, return
				 * error if it doesn't exist. */
    const char **errMsgPtr,
    int *indexPtr)
{
    Interp *iPtr = (Interp *) interp;
    CallFrame *varFramePtr = iPtr->varFramePtr;
				/* Points to the procedure call frame whose
				 * variables are currently in use. Same as the
				 * current procedure's frame, if any, unless
				 * an "uplevel" is executing. */
    TclVarHashTable *tablePtr;	/* Points to the hashtable, if any, in which
				 * to look up the variable. */
    Tcl_Var var;		/* Used to search for global names. */
    Var *varPtr;		/* Points to the Var structure returned for
				 * the variable. */
    Namespace *varNsPtr, *cxtNsPtr, *dummy1Ptr, *dummy2Ptr;
    ResolverScheme *resPtr;
    int isNew, i, result;
    size_t varLen;
    int isNew, result;
    Tcl_Size i, varLen;
    const char *varName = TclGetStringFromObj(varNamePtr, &varLen);

    varPtr = NULL;
    varNsPtr = NULL;		/* Set non-NULL if a nonlocal variable. */
    *indexPtr = -3;

    if (flags & TCL_GLOBAL_ONLY) {
910
911
912
913
914
915
916
917

918
919
920
921
922
923
924
910
911
912
913
914
915
916

917
918
919
920
921
922
923
924







-
+








    if (((flags & (TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY)) != 0)
	    || !HasLocalVars(varFramePtr)
	    || (strstr(varName, "::") != NULL)) {
	const char *tail;
	int lookGlobal = (flags & TCL_GLOBAL_ONLY)
		|| (cxtNsPtr == iPtr->globalNsPtr)
		|| ((*varName == ':') && (*(varName+1) == ':'));
		|| ((varName[0] == ':') && (varName[1] == ':'));

	if (lookGlobal) {
	    *indexPtr = -1;
	    flags = (flags | TCL_GLOBAL_ONLY) & ~TCL_NAMESPACE_ONLY;
	} else {
	    flags = (flags | TCL_NAMESPACE_ONLY);
	    *indexPtr = -2;
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
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







-
+




-
+








-
+











+








		*indexPtr = -1;
	    } else {
		*indexPtr = -2;
	    }
	}
    } else {			/* Local var: look in frame varFramePtr. */
	int localCt = varFramePtr->numCompiledLocals;
	Tcl_Size localCt = varFramePtr->numCompiledLocals;

	if (localCt > 0) {
	    Tcl_Obj **objPtrPtr = &varFramePtr->localCachePtr->varName0;
	    const char *localNameStr;
	    size_t localLen;
	    Tcl_Size localLen;

	    for (i=0 ; i<localCt ; i++, objPtrPtr++) {
		Tcl_Obj *objPtr = *objPtrPtr;

		if (objPtr) {
		    localNameStr = TclGetStringFromObj(objPtr, &localLen);

		    if ((varLen == localLen) && (varName[0] == localNameStr[0])
			&& !memcmp(varName, localNameStr, varLen)) {
			    && !memcmp(varName, localNameStr, varLen)) {
			*indexPtr = i;
			return (Var *) &varFramePtr->compiledLocals[i];
		    }
		}
	    }
	}
	tablePtr = varFramePtr->varTablePtr;
	if (create) {
	    if (tablePtr == NULL) {
		tablePtr = (TclVarHashTable *)Tcl_Alloc(sizeof(TclVarHashTable));
		TclInitVarHashTable(tablePtr, NULL);
		tablePtr->arrayPtr = varPtr;
		varFramePtr->varTablePtr = tablePtr;
	    }
	    varPtr = VarHashCreateVar(tablePtr, varNamePtr, &isNew);
	} else {
	    varPtr = NULL;
	    if (tablePtr != NULL) {
		varPtr = VarHashFindVar(tablePtr, varNamePtr);
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
1116

1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137

1138
1139
1140
1141
1142
1143
1144
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
1116

1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137

1138
1139
1140
1141
1142
1143
1144
1145







-
+



-
+



-
+



















-
+














-
+










-
+




















-
+








Var *
TclLookupArrayElement(
    Tcl_Interp *interp,		/* Interpreter to use for lookup. */
    Tcl_Obj *arrayNamePtr,	/* This is the name of the array, or NULL if
				 * index>= 0. */
    Tcl_Obj *elNamePtr,		/* Name of element within array. */
    const int flags,		/* Only TCL_LEAVE_ERR_MSG bit matters. */
    int flags,			/* Only TCL_LEAVE_ERR_MSG bit matters. */
    const char *msg,		/* Verb to use in error messages, e.g. "read"
				 * or "set". Only needed if TCL_LEAVE_ERR_MSG
				 * is set in flags. */
    const int createArray,	/* If 1, transform arrayName to be an array if
    int createArray,		/* If 1, transform arrayName to be an array if
				 * it isn't one yet and the transformation is
				 * possible. If 0, return error if it isn't
				 * already an array. */
    const int createElem,	/* If 1, create hash table entry for the
    int createElem,		/* If 1, create hash table entry for the
				 * element, if it doesn't already exist. If 0,
				 * return error if it doesn't exist. */
    Var *arrayPtr,		/* Pointer to the array's Var structure. */
    int index)			/* If >=0, the index of the local array. */
{
    int isNew;
    Var *varPtr;

    /*
     * We're dealing with an array element. Make sure the variable is an array
     * and look up the element (create the element if desired).
     */

    if (TclIsVarUndefined(arrayPtr) && !TclIsVarArrayElement(arrayPtr)) {
	if (!createArray) {
	    if (flags & TCL_LEAVE_ERR_MSG) {
		TclObjVarErrMsg(interp, arrayNamePtr, elNamePtr, msg,
			NOSUCHVAR, index);
		Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME",
			arrayNamePtr?TclGetString(arrayNamePtr):NULL, NULL);
			arrayNamePtr?TclGetString(arrayNamePtr):NULL, (char *)NULL);
	    }
	    return NULL;
	}

	/*
	 * Make sure we are not resurrecting a namespace variable from a
	 * deleted namespace!
	 */

	if (TclIsVarDeadHash(arrayPtr)) {
	    if (flags & TCL_LEAVE_ERR_MSG) {
		TclObjVarErrMsg(interp, arrayNamePtr, elNamePtr, msg,
			DANGLINGVAR, index);
		Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME",
			arrayNamePtr?TclGetString(arrayNamePtr):NULL, NULL);
			arrayNamePtr?TclGetString(arrayNamePtr):NULL, (char *)NULL);
	    }
	    return NULL;
	}

	TclInitArrayVar(arrayPtr);
    } else if (!TclIsVarArray(arrayPtr)) {
	if (flags & TCL_LEAVE_ERR_MSG) {
	    TclObjVarErrMsg(interp, arrayNamePtr, elNamePtr, msg, NEEDARRAY,
		    index);
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME",
		    arrayNamePtr?TclGetString(arrayNamePtr):NULL, NULL);
		    arrayNamePtr?TclGetString(arrayNamePtr):NULL, (char *)NULL);
	}
	return NULL;
    }

    if (createElem) {
	varPtr = VarHashCreateVar(arrayPtr->value.tablePtr, elNamePtr,
		&isNew);
	if (isNew) {
	    if (arrayPtr->flags & VAR_SEARCH_ACTIVE) {
		DeleteSearches((Interp *) interp, arrayPtr);
	    }
	    TclSetVarArrayElement(varPtr);
	}
    } else {
	varPtr = VarHashFindVar(arrayPtr->value.tablePtr, elNamePtr);
	if (varPtr == NULL) {
	    if (flags & TCL_LEAVE_ERR_MSG) {
		TclObjVarErrMsg(interp, arrayNamePtr, elNamePtr, msg,
			NOSUCHELEMENT, index);
		Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ELEMENT",
			TclGetString(elNamePtr), NULL);
			TclGetString(elNamePtr), (char *)NULL);
	    }
	}
    }
    return varPtr;
}

/*
1272
1273
1274
1275
1276
1277
1278
1279

1280
1281
1282

1283
1284
1285
1286
1287
1288
1289
1273
1274
1275
1276
1277
1278
1279

1280
1281
1282

1283
1284
1285
1286
1287
1288
1289
1290







-
+


-
+







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

Tcl_Obj *
Tcl_ObjGetVar2(
    Tcl_Interp *interp,		/* Command interpreter in which variable is to
				 * be looked up. */
    Tcl_Obj *part1Ptr,	/* Points to an object holding the name of an
    Tcl_Obj *part1Ptr,		/* Points to an object holding the name of an
				 * array (if part2 is non-NULL) or the name of
				 * a variable. */
    Tcl_Obj *part2Ptr,	/* If non-null, points to an object holding
    Tcl_Obj *part2Ptr,		/* If non-null, points to an object holding
				 * the name of an element in the array
				 * part1Ptr. */
    int flags)			/* OR-ed combination of TCL_GLOBAL_ONLY and
				 * TCL_LEAVE_ERR_MSG bits. */
{
    Var *varPtr, *arrayPtr;

1331
1332
1333
1334
1335
1336
1337
1338

1339
1340
1341
1342
1343
1344
1345
1332
1333
1334
1335
1336
1337
1338

1339
1340
1341
1342
1343
1344
1345
1346







-
+







    Tcl_Var varPtr,		/* The variable to be read.*/
    Tcl_Var arrayPtr,		/* NULL for scalar variables, pointer to the
				 * containing array otherwise. */
    Tcl_Obj *part1Ptr,		/* Name of an array (if part2 is non-NULL) or
				 * the name of a variable. */
    Tcl_Obj *part2Ptr,		/* If non-NULL, gives the name of an element
				 * in the array part1. */
    const int flags)		/* OR-ed combination of TCL_GLOBAL_ONLY, and
    int flags)			/* OR-ed combination of TCL_GLOBAL_ONLY, and
				 * TCL_LEAVE_ERR_MSG bits. */
{
    if (varPtr == NULL) {
	Tcl_Panic("varPtr must not be NULL");
    }
    if (part1Ptr == NULL) {
	Tcl_Panic("part1Ptr must not be NULL");
1370
1371
1372
1373
1374
1375
1376
1377

1378
1379
1380
1381
1382
1383
1384

1385
1386
1387
1388
1389
1390
1391



1392
1393
1394
1395
1396
1397
1398
1371
1372
1373
1374
1375
1376
1377

1378
1379
1380
1381
1382
1383
1384

1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402







-
+






-
+







+
+
+







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

Tcl_Obj *
TclPtrGetVarIdx(
    Tcl_Interp *interp,		/* Command interpreter in which variable is to
				 * be looked up. */
    Var *varPtr,	/* The variable to be read.*/
    Var *varPtr,		/* The variable to be read.*/
    Var *arrayPtr,		/* NULL for scalar variables, pointer to the
				 * containing array otherwise. */
    Tcl_Obj *part1Ptr,		/* Name of an array (if part2 is non-NULL) or
				 * the name of a variable. */
    Tcl_Obj *part2Ptr,		/* If non-NULL, gives the name of an element
				 * in the array part1. */
    const int flags,		/* OR-ed combination of TCL_GLOBAL_ONLY, and
    int flags,			/* OR-ed combination of TCL_GLOBAL_ONLY, and
				 * TCL_LEAVE_ERR_MSG bits. */
    int index)			/* Index into the local variable table of the
				 * variable, or -1. Only used when part1Ptr is
				 * NULL. */
{
    Interp *iPtr = (Interp *) interp;
    const char *msg;
    Var *initialArrayPtr = arrayPtr;

    TclVarFindHiddenArray(varPtr, arrayPtr);

    /*
     * Invoke any read traces that have been set for the variable.
     */

    if ((varPtr->flags & VAR_TRACED_READ)
	    || (arrayPtr && (arrayPtr->flags & VAR_TRACED_READ))) {
1431
1432
1433
1434
1435
1436
1437
1438
1439


1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455

1456
1457
1458
1459
1460
1461
1462
1435
1436
1437
1438
1439
1440
1441


1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458

1459
1460
1461
1462
1463
1464
1465
1466







-
-
+
+















-
+








	if (avhtPtr->defaultObj) {
	    return avhtPtr->defaultObj;
	}
    }

    if (flags & TCL_LEAVE_ERR_MSG) {
	if (TclIsVarUndefined(varPtr) && arrayPtr
		&& !TclIsVarUndefined(arrayPtr)) {
	if (TclIsVarUndefined(varPtr) && initialArrayPtr
		&& !TclIsVarUndefined(initialArrayPtr)) {
	    msg = NOSUCHELEMENT;
	} else if (TclIsVarArray(varPtr)) {
	    msg = ISARRAY;
	} else {
	    msg = NOSUCHVAR;
	}
	TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "read", msg, index);
    }

    /*
     * An error. If the variable doesn't exist anymore and no-one's using it,
     * then free up the relevant structures and hash table entries.
     */

  errorReturn:
    Tcl_SetErrorCode(interp, "TCL", "READ", "VARNAME", NULL);
    Tcl_SetErrorCode(interp, "TCL", "READ", "VARNAME", (char *)NULL);
    if (TclIsVarUndefined(varPtr)) {
	TclCleanupVar(varPtr, arrayPtr);
    }
    return NULL;
}

/*
1474
1475
1476
1477
1478
1479
1480
1481
1482


1483
1484
1485
1486
1487
1488
1489
1478
1479
1480
1481
1482
1483
1484


1485
1486
1487
1488
1489
1490
1491
1492
1493







-
-
+
+







 *	A variable's value may be changed.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_SetObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,/* Current interpreter. */
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *varValueObj;

    if (objc == 2) {
	varValueObj = Tcl_ObjGetVar2(interp, objv[1], NULL,TCL_LEAVE_ERR_MSG);
1652
1653
1654
1655
1656
1657
1658
1659

1660
1661
1662

1663
1664
1665
1666
1667
1668
1669
1656
1657
1658
1659
1660
1661
1662

1663
1664
1665

1666
1667
1668
1669
1670
1671
1672
1673







-
+


-
+







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

Tcl_Obj *
Tcl_ObjSetVar2(
    Tcl_Interp *interp,		/* Command interpreter in which variable is to
				 * be found. */
    Tcl_Obj *part1Ptr,	/* Points to an object holding the name of an
    Tcl_Obj *part1Ptr,		/* Points to an object holding the name of an
				 * array (if part2 is non-NULL) or the name of
				 * a variable. */
    Tcl_Obj *part2Ptr,	/* If non-NULL, points to an object holding
    Tcl_Obj *part2Ptr,		/* If non-NULL, points to an object holding
				 * the name of an element in the array
				 * part1Ptr. */
    Tcl_Obj *newValuePtr,	/* New value for variable. */
    int flags)			/* Various flags that tell how to set value:
				 * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
				 * TCL_APPEND_VALUE, TCL_LIST_ELEMENT, or
				 * TCL_LEAVE_ERR_MSG. */
1723
1724
1725
1726
1727
1728
1729
1730

1731
1732
1733
1734
1735
1736
1737
1727
1728
1729
1730
1731
1732
1733

1734
1735
1736
1737
1738
1739
1740
1741







-
+







				 * variable, or NULL if the variable is a
				 * scalar. */
    Tcl_Obj *part1Ptr,		/* Name of an array (if part2 is non-NULL) or
				 * the name of a variable. */
    Tcl_Obj *part2Ptr,		/* If non-NULL, gives the name of an element
				 * in the array part1. */
    Tcl_Obj *newValuePtr,	/* New value for variable. */
    const int flags)		/* OR-ed combination of TCL_GLOBAL_ONLY, and
    int flags)			/* OR-ed combination of TCL_GLOBAL_ONLY, and
				 * TCL_LEAVE_ERR_MSG bits. */
{
    if (varPtr == NULL) {
	Tcl_Panic("varPtr must not be NULL");
    }
    if (part1Ptr == NULL) {
	Tcl_Panic("part1Ptr must not be NULL");
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
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







-
+









-
+







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

Tcl_Obj *
TclPtrSetVarIdx(
    Tcl_Interp *interp,		/* Command interpreter in which variable is to
				 * be looked up. */
    Var *varPtr,	/* Reference to the variable to set. */
    Var *varPtr,		/* Reference to the variable to set. */
    Var *arrayPtr,		/* Reference to the array containing the
				 * variable, or NULL if the variable is a
				 * scalar. */
    Tcl_Obj *part1Ptr,		/* Name of an array (if part2 is non-NULL) or
				 * the name of a variable. NULL if the 'index'
				 * parameter is >= 0 */
    Tcl_Obj *part2Ptr,		/* If non-NULL, gives the name of an element
				 * in the array part1. */
    Tcl_Obj *newValuePtr,	/* New value for variable. */
    const int flags,		/* OR-ed combination of TCL_GLOBAL_ONLY, and
    int flags,			/* OR-ed combination of TCL_GLOBAL_ONLY, and
				 * TCL_LEAVE_ERR_MSG bits. */
    int index)			/* Index of local var where part1 is to be
				 * found. */
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *oldValuePtr;
    Tcl_Obj *resultPtr = NULL;
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
1958
1959
1960
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
1958
1959
1960
1961
1962
1963
1964

1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977







-
+



-
+


+
+
+
+
+
+
+
+
+
+
+










-
+



+
+







     */

    if (TclIsVarDeadHash(varPtr)) {
	if (flags & TCL_LEAVE_ERR_MSG) {
	    if (TclIsVarArrayElement(varPtr)) {
		TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "set",
			DANGLINGELEMENT, index);
		Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ELEMENT", NULL);
		Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ELEMENT", (char *)NULL);
	    } else {
		TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "set",
			DANGLINGVAR, index);
		Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", NULL);
		Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", (char *)NULL);
	    }
	}
	goto earlyError;
    }

    /*
     * It's an error to try to set a constant.
     */
    if (TclIsVarConstant(varPtr)) {
	if (flags & TCL_LEAVE_ERR_MSG) {
	    TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "set", ISCONST,index);
	    Tcl_SetErrorCode(interp, "TCL", "WRITE", "CONST", (char *)NULL);
	}
	goto earlyError;
    }

    /*
     * It's an error to try to set an array variable itself.
     */

    if (TclIsVarArray(varPtr)) {
	if (flags & TCL_LEAVE_ERR_MSG) {
	    TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "set", ISARRAY,index);
	    Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", (char *)NULL);
	}
	goto earlyError;
    }

    TclVarFindHiddenArray(varPtr, arrayPtr);

    /*
     * Invoke any read traces that have been set for the variable if it is
     * requested. This was done for INST_LAPPEND_* but that was inconsistent
     * with the non-bc instruction, and would cause failures trying to
     * lappend to any non-existing ::env var, which is inconsistent with
     * documented behavior. [Bug #3057639].
2036
2037
2038
2039
2040
2041
2042
2043

2044
2045
2046
2047
2048
2049
2050
2053
2054
2055
2056
2057
2058
2059

2060
2061
2062
2063
2064
2065
2066
2067







-
+







    /*
     * If the variable doesn't exist anymore and no-one's using it, then free
     * up the relevant structures and hash table entries.
     */

  cleanup:
    if (resultPtr == NULL) {
	Tcl_SetErrorCode(interp, "TCL", "WRITE", "VARNAME", NULL);
	Tcl_SetErrorCode(interp, "TCL", "WRITE", "VARNAME", (char *)NULL);
    }
    if (TclIsVarUndefined(varPtr)) {
	TclCleanupVar(varPtr, arrayPtr);
    }
    return resultPtr;

  earlyError:
2148
2149
2150
2151
2152
2153
2154
2155

2156
2157
2158
2159
2160
2161
2162
2165
2166
2167
2168
2169
2170
2171

2172
2173
2174
2175
2176
2177
2178
2179







-
+







				 * array (if part2 is non-NULL) or the name of
				 * a variable. */
    Tcl_Obj *part2Ptr,		/* If non-null, points to an object holding
				 * the name of an element in the array
				 * part1Ptr. */
    Tcl_Obj *incrPtr,		/* Increment value. */
/* TODO: Which of these flag values really make sense? */
    const int flags)		/* Various flags that tell how to incr value:
    int flags)			/* Various flags that tell how to incr value:
				 * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
				 * TCL_APPEND_VALUE, TCL_LIST_ELEMENT,
				 * TCL_LEAVE_ERR_MSG. */
{
    if (varPtr == NULL) {
	Tcl_Panic("varPtr must not be NULL");
    }
2204
2205
2206
2207
2208
2209
2210
2211

2212
2213
2214
2215
2216
2217
2218
2219











2220
2221
2222
2223
2224
2225
2226
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







-
+








+
+
+
+
+
+
+
+
+
+
+







				 * array (if part2 is non-NULL) or the name of
				 * a variable. */
    Tcl_Obj *part2Ptr,		/* If non-null, points to an object holding
				 * the name of an element in the array
				 * part1Ptr. */
    Tcl_Obj *incrPtr,		/* Increment value. */
/* TODO: Which of these flag values really make sense? */
    const int flags,		/* Various flags that tell how to incr value:
    int flags,			/* Various flags that tell how to incr value:
				 * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
				 * TCL_APPEND_VALUE, TCL_LIST_ELEMENT,
				 * TCL_LEAVE_ERR_MSG. */
    int index)			/* Index into the local variable table of the
				 * variable, or -1. Only used when part1Ptr is
				 * NULL. */
{
    Tcl_Obj *varValuePtr;

    /*
     * It's an error to try to increment a constant.
     */
    if (TclIsVarConstant(varPtr)) {
	if (flags & TCL_LEAVE_ERR_MSG) {
	    TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "incr", ISCONST,index);
	    Tcl_SetErrorCode(interp, "TCL", "WRITE", "CONST", (char *)NULL);
	}
	return NULL;
    }

    if (TclIsVarInHash(varPtr)) {
	VarHashRefCount(varPtr)++;
    }
    varValuePtr = TclPtrGetVarIdx(interp, varPtr, arrayPtr, part1Ptr,
	    part2Ptr, flags, index);
    if (TclIsVarInHash(varPtr)) {
2382
2383
2384
2385
2386
2387
2388
2389

2390
2391
2392
2393
2394
2395
2396
2410
2411
2412
2413
2414
2415
2416

2417
2418
2419
2420
2421
2422
2423
2424







-
+







    Tcl_Var varPtr,		/* The variable to be unset. */
    Tcl_Var arrayPtr,		/* NULL for scalar variables, pointer to the
				 * containing array otherwise. */
    Tcl_Obj *part1Ptr,		/* Name of an array (if part2 is non-NULL) or
				 * the name of a variable. */
    Tcl_Obj *part2Ptr,		/* If non-NULL, gives the name of an element
				 * in the array part1. */
    const int flags)		/* OR-ed combination of any of
    int flags)			/* OR-ed combination of any of
				 * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
				 * TCL_LEAVE_ERR_MSG. */
{
    if (varPtr == NULL) {
	Tcl_Panic("varPtr must not be NULL");
    }
    if (part1Ptr == NULL) {
2422
2423
2424
2425
2426
2427
2428
2429

2430
2431
2432
2433
2434
2435
2436

2437
2438
2439
2440
2441
2442
2443
2444












2445
2446
2447
2448
2449
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
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507


2508
2509
2510
2511
2512
2513
2514
2515
2516







-
+






-
+








+
+
+
+
+
+
+
+
+
+
+
+











+
+










-
-
+
+







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

int
TclPtrUnsetVarIdx(
    Tcl_Interp *interp,		/* Command interpreter in which varName is to
				 * be looked up. */
    Var *varPtr,	/* The variable to be unset. */
    Var *varPtr,		/* The variable to be unset. */
    Var *arrayPtr,		/* NULL for scalar variables, pointer to the
				 * containing array otherwise. */
    Tcl_Obj *part1Ptr,		/* Name of an array (if part2 is non-NULL) or
				 * the name of a variable. */
    Tcl_Obj *part2Ptr,		/* If non-NULL, gives the name of an element
				 * in the array part1. */
    const int flags,		/* OR-ed combination of any of
    int flags,			/* OR-ed combination of any of
				 * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
				 * TCL_LEAVE_ERR_MSG. */
    int index)			/* Index into the local variable table of the
				 * variable, or -1. Only used when part1Ptr is
				 * NULL. */
{
    Interp *iPtr = (Interp *) interp;
    int result = (TclIsVarUndefined(varPtr)? TCL_ERROR : TCL_OK);
    Var *initialArrayPtr = arrayPtr;

    /*
     * It's an error to try to unset a constant.
     */
    if (TclIsVarConstant(varPtr)) {
	if (flags & TCL_LEAVE_ERR_MSG) {
	    TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "unset", ISCONST,index);
	    Tcl_SetErrorCode(interp, "TCL", "UNSET", "CONST", (char *)NULL);
	}
	return TCL_ERROR;
    }

    /*
     * Keep the variable alive until we're done with it. We used to
     * increase/decrease the refCount for each operation, making it hard to
     * find [Bug 735335] - caused by unsetting the variable whose value was
     * the variable's name.
     */

    if (TclIsVarInHash(varPtr)) {
	VarHashRefCount(varPtr)++;
    }

    TclVarFindHiddenArray(varPtr, arrayPtr);

    UnsetVarStruct(varPtr, arrayPtr, iPtr, part1Ptr, part2Ptr, flags, index);

    /*
     * It's an error to unset an undefined variable.
     */

    if (result != TCL_OK) {
	if (flags & TCL_LEAVE_ERR_MSG) {
	    TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "unset",
		    ((arrayPtr == NULL) ? NOSUCHVAR : NOSUCHELEMENT), index);
	    Tcl_SetErrorCode(interp, "TCL", "UNSET", "VARNAME", NULL);
	      ((initialArrayPtr == NULL) ? NOSUCHVAR : NOSUCHELEMENT), index);
	    Tcl_SetErrorCode(interp, "TCL", "UNSET", "VARNAME", (char *)NULL);
	}
    }

    /*
     * Finally, if the variable is truly not in use then free up its Var
     * structure and remove it from its hash table, if any. The ref count of
     * its value object, if any, was decremented above.
2567
2568
2569
2570
2571
2572
2573














2574
2575
2576

2577
2578
2579
2580
2581
2582
2583
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+







			&dummyVar, &isNew);
		Tcl_SetHashValue(tPtr, tracePtr);
	    }
	}

	if ((dummyVar.flags & VAR_TRACED_UNSET)
		|| (arrayPtr && (arrayPtr->flags & VAR_TRACED_UNSET))) {

	    /*
	     * Pass the array element name to TclObjCallVarTraces(), because
	     * it cannot be determined from dummyVar. Alternatively, indicate
	     * via flags whether the variable involved in the code that caused
	     * the trace to be triggered was an array element, for the correct
	     * formatting of error messages.
	     */
	    if (part2Ptr) {
		flags |= VAR_ARRAY_ELEMENT;
	    } else if (TclIsVarArrayElement(varPtr)) {
		part2Ptr = VarHashGetKey(varPtr);
	    }

	    dummyVar.flags &= ~VAR_TRACE_ACTIVE;
	    TclObjCallVarTraces(iPtr, arrayPtr, &dummyVar, part1Ptr, part2Ptr,
		    (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY))
	      (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|VAR_ARRAY_ELEMENT))
			    | TCL_TRACE_UNSETS,
		    /* leaveErrMsg */ 0, index);

	    /*
	     * The traces that we just called may have triggered a change in
	     * the set of traces. If so, reload the traces to manipulate.
	     */
2670
2671
2672
2673
2674
2675
2676
2677

2678
2679
2680
2681
2682
2683
2684
2726
2727
2728
2729
2730
2731
2732

2733
2734
2735
2736
2737
2738
2739
2740







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UnsetObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int i, flags = TCL_LEAVE_ERR_MSG;
    const char *name;

2737
2738
2739
2740
2741
2742
2743
2744

2745
2746
2747
2748
2749
2750
2751
2793
2794
2795
2796
2797
2798
2799

2800
2801
2802
2803
2804
2805
2806
2807







-
+







 *	A variable's value may be changed.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_AppendObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Var *varPtr, *arrayPtr;
    Tcl_Obj *varValuePtr = NULL;
				/* Initialized to avoid compiler warning. */
2802
2803
2804
2805
2806
2807
2808
2809

2810
2811
2812
2813
2814
2815

2816
2817

2818
2819
2820
2821
2822
2823
2824
2858
2859
2860
2861
2862
2863
2864

2865
2866
2867
2868
2869
2870

2871
2872

2873
2874
2875
2876
2877
2878
2879
2880







-
+





-
+

-
+







 *	A variable's value may be changed.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LappendObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *varValuePtr, *newValuePtr;
    int numElems, createdNewObj;
    Tcl_Size numElems;
    Var *varPtr, *arrayPtr;
    int result;
    int result, createdNewObj;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "varName ?value ...?");
	return TCL_ERROR;
    }
    if (objc == 2) {
	newValuePtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0);
2930
2931
2932
2933
2934
2935
2936
2937

2938
2939
2940
2941
2942
2943
2944
2986
2987
2988
2989
2990
2991
2992

2993
2994
2995
2996
2997
2998
2999
3000







-
+







/*
 *----------------------------------------------------------------------
 *
 * ArrayForObjCmd, ArrayForNRCmd, ArrayForLoopCallback, ArrayObjNext --
 *
 *	These functions implement the "array for" Tcl command.
 *	    array for {k v} a {}
 *	The array for command iterates over the array, setting the the
 *	The array for command iterates over the array, setting the
 *	specified loop variables, and executing the body each iteration.
 *
 *	ArrayForObjCmd() is the standard wrapper around ArrayForNRCmd().
 *
 *	ArrayForNRCmd() sets up the ArraySearch structure, sets arrayNamePtr
 *	inside the structure and calls VarHashFirstEntry to start the hash
 *	iteration.
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
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







-
+









-
+







-
+
+














-
+






-
+







    *valuePtrPtr = valueObj;

    return donerc;
}

static int
ArrayForObjCmd(
    ClientData clientData,
    void *clientData,
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    return Tcl_NRCallObjProc(interp, ArrayForNRCmd, clientData, objc, objv);
}

static int
ArrayForNRCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *varListObj, *arrayNameObj, *scriptObj;
    ArraySearch *searchPtr = NULL;
    Var *varPtr;
    int isArray, numVars;
    int isArray;
    Tcl_Size numVars;

    /*
     * array for {k v} a body
     */

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "{key value} arrayName script");
	return TCL_ERROR;
    }

    /*
     * Parse arguments.
     */

    if (Tcl_ListObjLength(interp, objv[1], &numVars) != TCL_OK) {
    if (TclListObjLength(interp, objv[1], &numVars) != TCL_OK) {
	return TCL_ERROR;
    }

    if (numVars != 2) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"must have two variable names", -1));
	Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "array", "for", NULL);
	Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "array", "for", (char *)NULL);
	return TCL_ERROR;
    }

    arrayNameObj = objv[2];

    if (TCL_ERROR == LocateArray(interp, arrayNameObj, &varPtr, &isArray)) {
	return TCL_ERROR;
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
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155

3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168

3169
3170
3171
3172
3173
3174
3175
3176
3177







+
+
+














-
+












-
+
+








    /*
     * Make sure that these objects (which we need throughout the body of the
     * loop) don't vanish.
     */

    varListObj = TclListObjCopy(NULL, objv[1]);
    if (!varListObj) {
	return TCL_ERROR;
    }
    scriptObj = objv[3];
    Tcl_IncrRefCount(scriptObj);

    /*
     * Run the script.
     */

    TclNRAddCallback(interp, ArrayForLoopCallback, searchPtr, varListObj,
	    arrayNameObj, scriptObj);
    return TCL_OK;
}

static int
ArrayForLoopCallback(
    ClientData data[],
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    ArraySearch *searchPtr = (ArraySearch *)data[0];
    Tcl_Obj *varListObj = (Tcl_Obj *)data[1];
    Tcl_Obj *arrayNameObj = (Tcl_Obj *)data[2];
    Tcl_Obj *scriptObj = (Tcl_Obj *)data[3];
    Tcl_Obj **varv;
    Tcl_Obj *keyObj, *valueObj;
    Var *varPtr;
    Var *arrayPtr;
    int done, varc;
    int done;
    Tcl_Size varc;

    /*
     * Process the result from the previous execution of the script body.
     */

    done = TCL_ERROR;

3145
3146
3147
3148
3149
3150
3151
3152

3153
3154
3155
3156
3157
3158
3159




3160
3161
3162
3163
3164
3165
3166
3206
3207
3208
3209
3210
3211
3212

3213
3214
3215
3216
3217
3218
3219

3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230







-
+






-
+
+
+
+








    result = TCL_OK;
    if (done != TCL_CONTINUE) {
	Tcl_ResetResult(interp);
	if (done == TCL_ERROR) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "array changed during iteration", -1));
	    Tcl_SetErrorCode(interp, "TCL", "READ", "array", "for", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "READ", "array", "for", (char *)NULL);
	    varPtr->flags |= TCL_LEAVE_ERR_MSG;
	    result = done;
	}
	goto arrayfordone;
    }

    Tcl_ListObjGetElements(NULL, varListObj, &varc, &varv);
    result = TclListObjGetElements(NULL, varListObj, &varc, &varv);
    if (result != TCL_OK) {
	goto arrayfordone;
    }
    if (Tcl_ObjSetVar2(interp, varv[0], NULL, keyObj,
	    TCL_LEAVE_ERR_MSG) == NULL) {
	result = TCL_ERROR;
	goto arrayfordone;
    }
    if (valueObj != NULL) {
	if (Tcl_ObjSetVar2(interp, varv[1], NULL, valueObj,
3247
3248
3249
3250
3251
3252
3253
3254

3255
3256
3257
3258
3259
3260
3261
3311
3312
3313
3314
3315
3316
3317

3318
3319
3320
3321
3322
3323
3324
3325







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayStartSearchCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Var *varPtr;
    int isArray;
    ArraySearch *searchPtr;
3342
3343
3344
3345
3346
3347
3348
3349

3350
3351
3352
3353
3354
3355
3356
3406
3407
3408
3409
3410
3411
3412

3413
3414
3415
3416
3417
3418
3419
3420







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayAnyMoreCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Interp *iPtr = (Interp *) interp;
    Var *varPtr;
    Tcl_Obj *varNameObj, *searchObj;
3420
3421
3422
3423
3424
3425
3426
3427

3428
3429
3430
3431
3432
3433
3434
3484
3485
3486
3487
3488
3489
3490

3491
3492
3493
3494
3495
3496
3497
3498







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayNextElementCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Var *varPtr;
    Tcl_Obj *varNameObj, *searchObj;
    ArraySearch *searchPtr;
3500
3501
3502
3503
3504
3505
3506
3507

3508
3509
3510
3511
3512
3513
3514
3564
3565
3566
3567
3568
3569
3570

3571
3572
3573
3574
3575
3576
3577
3578







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayDoneSearchCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Interp *iPtr = (Interp *) interp;
    Var *varPtr;
    Tcl_Obj *varNameObj, *searchObj;
3560
3561
3562
3563
3564
3565
3566
3567

3568
3569
3570
3571
3572
3573
3574
3624
3625
3626
3627
3628
3629
3630

3631
3632
3633
3634
3635
3636
3637
3638







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayExistsCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Interp *iPtr = (Interp *)interp;
    int isArray;

3600
3601
3602
3603
3604
3605
3606
3607

3608
3609
3610
3611
3612
3613
3614
3615
3616

3617

3618
3619
3620
3621
3622
3623
3624
3664
3665
3666
3667
3668
3669
3670

3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681

3682
3683
3684
3685
3686
3687
3688
3689







-
+









+
-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayGetCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Var *varPtr, *varPtr2;
    Tcl_Obj *varNameObj, *nameObj, *valueObj, *nameLstObj, *tmpResObj;
    Tcl_Obj **nameObjPtr, *patternObj;
    Tcl_HashSearch search;
    const char *pattern;
    Tcl_Size i, count;
    int i, count, result, isArray;
    int result, isArray;

    switch (objc) {
    case 2:
	varNameObj = objv[1];
	patternObj = NULL;
	break;
    case 3:
3692
3693
3694
3695
3696
3697
3698
3699

3700
3701
3702
3703
3704
3705
3706
3757
3758
3759
3760
3761
3762
3763

3764
3765
3766
3767
3768
3769
3770
3771







-
+







    }

    /*
     * Get the array values corresponding to each element name.
     */

    TclNewObj(tmpResObj);
    result = Tcl_ListObjGetElements(interp, nameLstObj, &count, &nameObjPtr);
    result = TclListObjGetElements(interp, nameLstObj, &count, &nameObjPtr);
    if (result != TCL_OK) {
	goto errorInArrayGet;
    }

    for (i=0 ; i<count ; i++) {
	nameObj = *nameObjPtr++;
	valueObj = Tcl_ObjGetVar2(interp, varNameObj, nameObj,
3759
3760
3761
3762
3763
3764
3765
3766

3767
3768
3769
3770
3771
3772
3773
3774

3775
3776
3777
3778
3779

3780
3781
3782
3783
3784
3785
3786
3824
3825
3826
3827
3828
3829
3830

3831
3832
3833
3834
3835
3836
3837
3838

3839
3840
3841
3842
3843

3844
3845
3846
3847
3848
3849
3850
3851







-
+







-
+




-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayNamesCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    static const char *const options[] = {
	"-exact", "-glob", "-regexp", NULL
    };
    enum arrayNamesOptionsEnum { OPT_EXACT, OPT_GLOB, OPT_REGEXP };
    enum arrayNamesOptionsEnum {OPT_EXACT, OPT_GLOB, OPT_REGEXP} mode = OPT_GLOB;
    Var *varPtr, *varPtr2;
    Tcl_Obj *nameObj, *resultObj, *patternObj;
    Tcl_HashSearch search;
    const char *pattern = NULL;
    int isArray, mode = OPT_GLOB;
    int isArray;

    if ((objc < 2) || (objc > 4)) {
	Tcl_WrongNumArgs(interp, 1, objv, "arrayName ?mode? ?pattern?");
	return TCL_ERROR;
    }
    patternObj = (objc > 2 ? objv[objc-1] : NULL);

3835
3836
3837
3838
3839
3840
3841
3842

3843
3844
3845
3846
3847
3848
3849
3900
3901
3902
3903
3904
3905
3906

3907
3908
3909
3910
3911
3912
3913
3914







-
+







	    continue;
	}
	nameObj = VarHashGetKey(varPtr2);
	if (patternObj) {
	    const char *name = TclGetString(nameObj);
	    int matched = 0;

	    switch ((enum arrayNamesOptionsEnum) mode) {
	    switch (mode) {
	    case OPT_EXACT:
		Tcl_Panic("exact matching shouldn't get here");
	    case OPT_GLOB:
		matched = Tcl_StringMatch(name, pattern);
		break;
	    case OPT_REGEXP:
		matched = Tcl_RegExpMatchObj(interp, nameObj, patternObj);
3902
3903
3904
3905
3906
3907
3908
3909

3910
3911
3912
3913
3914
3915
3916
3967
3968
3969
3970
3971
3972
3973

3974
3975
3976
3977
3978
3979
3980
3981







-
+







	Tcl_Obj *nameObj;
	int dummy;

	if (TclIsVarUndefined(varPtr)) {
	    continue;
	}
	nameObj = VarHashGetKey(varPtr);
	hPtr = Tcl_CreateHashEntry(tablePtr, (char *) nameObj, &dummy);
	hPtr = Tcl_CreateHashEntry(tablePtr, nameObj, &dummy);
	Tcl_SetHashValue(hPtr, nameObj);
    }
}

/*
 *----------------------------------------------------------------------
 *
3926
3927
3928
3929
3930
3931
3932
3933

3934
3935
3936
3937
3938
3939
3940
3941

3942
3943
3944
3945
3946
3947
3948
3991
3992
3993
3994
3995
3996
3997

3998
3999
4000
4001
4002
4003
4004
4005

4006
4007
4008
4009
4010
4011
4012
4013







-
+







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArraySetCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *arrayNameObj;
    Tcl_Obj *arrayElemObj;
    Var *varPtr, *arrayPtr;
    int result, i;
    int result;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "arrayName list");
	return TCL_ERROR;
    }

    if (TCL_ERROR == LocateArray(interp, objv[1], NULL, NULL)) {
3956
3957
3958
3959
3960
3961
3962
3963

3964
3965
3966
3967
3968
3969
3970
3971
3972

3973
3974
3975

3976
3977

3978
3979
3980

3981
3982
3983
3984
3985
3986
3987
4021
4022
4023
4024
4025
4026
4027

4028
4029
4030
4031
4032
4033
4034
4035
4036

4037
4038
4039
4040
4041
4042

4043
4044
4045

4046
4047
4048
4049
4050
4051
4052
4053







-
+








-
+



+

-
+


-
+







    if (varPtr == NULL) {
	return TCL_ERROR;
    }
    if (arrayPtr) {
	CleanupVar(varPtr, arrayPtr);
	TclObjVarErrMsg(interp, arrayNameObj, NULL, "set", NEEDARRAY, -1);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME",
		TclGetString(arrayNameObj), NULL);
		TclGetString(arrayNameObj), (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Install the contents of the dictionary or list into the array.
     */

    arrayElemObj = objv[2];
    if (TclHasIntRep(arrayElemObj, &tclDictType) && arrayElemObj->bytes == NULL) {
    if (TclHasInternalRep(arrayElemObj, &tclDictType) && arrayElemObj->bytes == NULL) {
	Tcl_Obj *keyPtr, *valuePtr;
	Tcl_DictSearch search;
	int done;
	Tcl_Size size;

	if (Tcl_DictObjSize(interp, arrayElemObj, &done) != TCL_OK) {
	if (Tcl_DictObjSize(interp, arrayElemObj, &size) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (done == 0) {
	if (size == 0) {
	    /*
	     * Empty, so we'll just force the array to be properly existing
	     * instead.
	     */

	    goto ensureArray;
	}
4012
4013
4014
4015
4016
4017
4018
4019

4020

4021
4022

4023
4024
4025
4026
4027
4028
4029
4030

4031
4032
4033
4034





4035
4036
4037
4038
4039
4040
4041
4042
4043



4044
4045
4046
4047
4048
4049
4050
4078
4079
4080
4081
4082
4083
4084

4085
4086
4087
4088

4089

4090
4091
4092
4093
4094
4095

4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124







-
+

+

-
+
-






-
+




+
+
+
+
+









+
+
+







	return TCL_OK;
    } else {
	/*
	 * Not a dictionary, so assume (and convert to, for backward-
	 * -compatibility reasons) a list.
	 */

	int elemLen;
	Tcl_Size elemLen;
	Tcl_Obj **elemPtrs, *copyListObj;
	Tcl_Size i;

	result = TclListObjGetElements(interp, arrayElemObj,
	result = TclListObjLength(interp, arrayElemObj, &elemLen);
		&elemLen, &elemPtrs);
	if (result != TCL_OK) {
	    return result;
	}
	if (elemLen & 1) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "list must have an even number of elements", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "FORMAT", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "FORMAT", (char *)NULL);
	    return TCL_ERROR;
	}
	if (elemLen == 0) {
	    goto ensureArray;
	}
	result = TclListObjGetElements(interp, arrayElemObj,
		&elemLen, &elemPtrs);
	if (result != TCL_OK) {
	    return result;
	}

	/*
	 * We needn't worry about traces invalidating arrayPtr: should that be
	 * the case, TclPtrSetVarIdx will return NULL so that we break out of
	 * the loop and return an error.
	 */

	copyListObj = TclListObjCopy(NULL, arrayElemObj);
	if (!copyListObj) {
	    return TCL_ERROR;
	}
	for (i=0 ; i<elemLen ; i+=2) {
	    Var *elemVarPtr = TclLookupArrayElement(interp, arrayNameObj,
		    elemPtrs[i], TCL_LEAVE_ERR_MSG, "set", 1, 1, varPtr, -1);

	    if ((elemVarPtr == NULL) ||
		    (TclPtrSetVarIdx(interp, elemVarPtr, varPtr, arrayNameObj,
			    elemPtrs[i], elemPtrs[i+1], TCL_LEAVE_ERR_MSG,
4074
4075
4076
4077
4078
4079
4080
4081

4082
4083
4084
4085
4086
4087
4088
4148
4149
4150
4151
4152
4153
4154

4155
4156
4157
4158
4159
4160
4161
4162







-
+







	if (TclIsVarArrayElement(varPtr) || !TclIsVarUndefined(varPtr)) {
	    /*
	     * Either an array element, or a scalar: lose!
	     */

	    TclObjVarErrMsg(interp, arrayNameObj, NULL, "array set",
		    NEEDARRAY, -1);
	    Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", (char *)NULL);
	    return TCL_ERROR;
	}
    }
    TclInitArrayVar(varPtr);
    return TCL_OK;
}

4101
4102
4103
4104
4105
4106
4107
4108

4109
4110
4111
4112
4113
4114
4115
4175
4176
4177
4178
4179
4180
4181

4182
4183
4184
4185
4186
4187
4188
4189







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArraySizeCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Var *varPtr;
    Tcl_HashSearch search;
    Var *varPtr2;
4160
4161
4162
4163
4164
4165
4166
4167

4168
4169
4170
4171
4172
4173
4174
4234
4235
4236
4237
4238
4239
4240

4241
4242
4243
4244
4245
4246
4247
4248







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayStatsCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Var *varPtr;
    Tcl_Obj *varNameObj;
    char *stats;
4214
4215
4216
4217
4218
4219
4220
4221

4222
4223
4224
4225
4226
4227
4228
4229
4230

4231
4232
4233
4234
4235
4236
4237
4288
4289
4290
4291
4292
4293
4294

4295
4296
4297
4298
4299
4300
4301
4302
4303

4304
4305
4306
4307
4308
4309
4310
4311







-
+








-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayUnsetCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Var *varPtr, *varPtr2, *protectedVarPtr;
    Tcl_Obj *varNameObj, *patternObj, *nameObj;
    Tcl_HashSearch search;
    const char *pattern;
    const int unsetFlags = 0;	/* Should this be TCL_LEAVE_ERR_MSG? */
    int unsetFlags = 0;	/* Should this be TCL_LEAVE_ERR_MSG? */
    int isArray;

    switch (objc) {
    case 2:
	varNameObj = objv[1];
	patternObj = NULL;
	break;
4402
4403
4404
4405
4406
4407
4408
4409

4410
4411
4412
4413
4414
4415
4416
4476
4477
4478
4479
4480
4481
4482

4483
4484
4485
4486
4487
4488
4489
4490







-
+







ObjMakeUpvar(
    Tcl_Interp *interp,		/* Interpreter containing variables. Used for
				 * error messages, too. */
    CallFrame *framePtr,	/* Call frame containing "other" variable.
				 * NULL means use global :: context. */
    Tcl_Obj *otherP1Ptr,
    const char *otherP2,	/* Two-part name of variable in framePtr. */
    const int otherFlags,	/* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY:
    int otherFlags,		/* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY:
				 * indicates scope of "other" variable. */
    Tcl_Obj *myNamePtr,		/* Name of variable which will refer to
				 * otherP1/otherP2. Must be a scalar. */
    int myFlags,		/* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY:
				 * indicates scope of myName. */
    int index)			/* If the variable to be linked is an indexed
				 * scalar, this is its index. Otherwise, -1 */
4458
4459
4460
4461
4462
4463
4464
4465

4466
4467
4468
4469
4470
4471
4472
4532
4533
4534
4535
4536
4537
4538

4539
4540
4541
4542
4543
4544
4545
4546







-
+







			|| (varFramePtr == NULL)
			|| !HasLocalVars(varFramePtr)
			|| (strstr(TclGetString(myNamePtr), "::") != NULL))) {
	    Tcl_SetObjResult((Tcl_Interp *) iPtr, Tcl_ObjPrintf(
		    "bad variable name \"%s\": can't create namespace "
		    "variable that refers to procedure variable",
		    TclGetString(myNamePtr)));
	    Tcl_SetErrorCode(interp, "TCL", "UPVAR", "INVERTED", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "UPVAR", "INVERTED", (char *)NULL);
	    return TCL_ERROR;
	}
    }

    return TclPtrObjMakeUpvarIdx(interp, otherPtr, myNamePtr, myFlags, index);
}

4574
4575
4576
4577
4578
4579
4580
4581

4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600

4601
4602
4603
4604
4605
4606
4607
4608

4609
4610
4611
4612
4613
4614
4615

4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630

4631
4632
4633
4634
4635
4636
4637
4648
4649
4650
4651
4652
4653
4654

4655
4656
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
4688

4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703

4704
4705
4706
4707
4708
4709
4710
4711







-
+


















-
+







-
+






-
+














-
+







		 * myName looks like an array reference.
		 */

		Tcl_SetObjResult((Tcl_Interp *) iPtr, Tcl_ObjPrintf(
			"bad variable name \"%s\": can't create a scalar "
			"variable that looks like an array element", myName));
		Tcl_SetErrorCode(interp, "TCL", "UPVAR", "LOCAL_ELEMENT",
			NULL);
			(char *)NULL);
		return TCL_ERROR;
	    }
	}

	/*
	 * Lookup and eventually create the new variable. Set the flag bit
	 * TCL_AVOID_RESOLVERS to indicate the special resolution rules for
	 * upvar purposes:
	 *   - Bug #696893 - variable is either proc-local or in the current
	 *     namespace; never follow the second (global) resolution path.
	 *   - Bug #631741 - do not use special namespace or interp resolvers.
	 */

	varPtr = TclLookupSimpleVar(interp, myNamePtr,
		myFlags|TCL_AVOID_RESOLVERS, /* create */ 1, &errMsg, &index);
	if (varPtr == NULL) {
	    TclObjVarErrMsg(interp, myNamePtr, NULL, "create", errMsg, -1);
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME",
		    TclGetString(myNamePtr), NULL);
		    TclGetString(myNamePtr), (char *)NULL);
	    return TCL_ERROR;
	}
    }

    if (varPtr == otherPtr) {
	Tcl_SetObjResult((Tcl_Interp *) iPtr, Tcl_NewStringObj(
		"can't upvar from variable to itself", -1));
	Tcl_SetErrorCode(interp, "TCL", "UPVAR", "SELF", NULL);
	Tcl_SetErrorCode(interp, "TCL", "UPVAR", "SELF", (char *)NULL);
	return TCL_ERROR;
    }

    if (TclIsVarTraced(varPtr)) {
	Tcl_SetObjResult((Tcl_Interp *) iPtr, Tcl_ObjPrintf(
		"variable \"%s\" has traces: can't use for upvar", myName));
	Tcl_SetErrorCode(interp, "TCL", "UPVAR", "TRACED", NULL);
	Tcl_SetErrorCode(interp, "TCL", "UPVAR", "TRACED", (char *)NULL);
	return TCL_ERROR;
    } else if (!TclIsVarUndefined(varPtr)) {
	Var *linkPtr;

	/*
	 * The variable already existed. Make sure this variable "varPtr"
	 * isn't the same as "otherPtr" (avoid circular links). Also, if it's
	 * not an upvar then it's an error. If it is an upvar, then just
	 * disconnect it from the thing it currently refers to.
	 */

	if (!TclIsVarLink(varPtr)) {
	    Tcl_SetObjResult((Tcl_Interp *) iPtr, Tcl_ObjPrintf(
		    "variable \"%s\" already exists", myName));
	    Tcl_SetErrorCode(interp, "TCL", "UPVAR", "EXISTS", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "UPVAR", "EXISTS", (char *)NULL);
	    return TCL_ERROR;
	}

	linkPtr = varPtr->value.linkPtr;
	if (linkPtr == otherPtr) {
	    return TCL_OK;
	}
4754
4755
4756
4757
4758
4759
4760
4761

4762
4763

4764
4765
4766
4767
4768











































































4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789

4790
4791
4792
4793
4794
4795
4796
4828
4829
4830
4831
4832
4833
4834

4835
4836

4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937

4938
4939
4940
4941
4942
4943
4944
4945







-
+

-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




















-
+







    }
    if (TclIsVarInHash(varPtr)) {
	if (!TclIsVarDeadHash(varPtr)) {
	    namePtr = VarHashGetKey(varPtr);
	    Tcl_AppendObjToObj(objPtr, namePtr);
	}
    } else if (iPtr->varFramePtr->procPtr) {
	int index = varPtr - iPtr->varFramePtr->compiledLocals;
	Tcl_Size index = varPtr - iPtr->varFramePtr->compiledLocals;

	if (index >= 0 && index < iPtr->varFramePtr->numCompiledLocals) {
	if (index < iPtr->varFramePtr->numCompiledLocals) {
	    namePtr = localName(iPtr->varFramePtr, index);
	    Tcl_AppendObjToObj(objPtr, namePtr);
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ConstObjCmd --
 *
 *	This function is invoked to process the "const" Tcl command.
 *	See the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result value.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ConstObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Var *varPtr, *arrayPtr;
    Tcl_Obj *part1Ptr;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "varName value");
	return TCL_ERROR;
    }

    part1Ptr = objv[1];
    varPtr = TclObjLookupVarEx(interp, part1Ptr, NULL, TCL_LEAVE_ERR_MSG,
	    "const", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
    if (TclIsVarArray(varPtr)) {
	TclObjVarErrMsg(interp, part1Ptr, NULL, "make constant", ISARRAY, -1);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CONST", (char *)NULL);
	return TCL_ERROR;
    }
    if (TclIsVarArrayElement(varPtr)) {
	if (TclIsVarUndefined(varPtr)) {
	    CleanupVar(varPtr, arrayPtr);
	}
	TclObjVarErrMsg(interp, part1Ptr, NULL, "make constant", ISARRAYELEMENT, -1);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CONST", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * If already exists, either a constant (no problem) or an error.
     */
    if (!TclIsVarUndefined(varPtr)) {
	if (TclIsVarConstant(varPtr)) {
	    return TCL_OK;
	}
	TclObjVarErrMsg(interp, part1Ptr, NULL, "make constant", EXISTS, -1);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CONST", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Make the variable and flag it as a constant.
     */
    if (TclPtrSetVar(interp, (Tcl_Var) varPtr, NULL, objv[1], NULL,
	    objv[2], TCL_LEAVE_ERR_MSG) == NULL) {
	if (TclIsVarUndefined(varPtr)) {
	    CleanupVar(varPtr, arrayPtr);
	}
	return TCL_ERROR;
    };
    TclSetVarConstant(varPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GlobalObjCmd --
 *
 *	This object-based function is invoked to process the "global" Tcl
 *	command. See the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result value.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_GlobalObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *objPtr, *tailPtr;
    const char *varName;
4818
4819
4820
4821
4822
4823
4824
4825

4826
4827
4828
4829
4830
4831
4832
4967
4968
4969
4970
4971
4972
4973

4974
4975
4976
4977
4978
4979
4980
4981







-
+







	 * The variable name might have a scope qualifier, but the name for
	 * the local "link" variable must be the simple name at the tail.
	 */

	for (tail=varName ; *tail!='\0' ; tail++) {
	    /* empty body */
	}
	while ((tail > varName) && ((*tail != ':') || (*(tail-1) != ':'))) {
	while ((tail > varName) && ((tail[0] != ':') || (tail[-1] != ':'))) {
	    tail--;
	}
	if ((*tail == ':') && (tail > varName)) {
	    tail++;
	}

	if (tail == varName) {
4886
4887
4888
4889
4890
4891
4892
4893

4894
4895
4896
4897
4898
4899
4900
5035
5036
5037
5038
5039
5040
5041

5042
5043
5044
5045
5046
5047
5048
5049







-
+







 *	result in the interpreter's result object.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_VariableObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    const char *varName, *tail, *cp;
    Var *varPtr, *arrayPtr;
4918
4919
4920
4921
4922
4923
4924
4925

4926
4927
4928
4929
4930
4931
4932
5067
5068
5069
5070
5071
5072
5073

5074
5075
5076
5077
5078
5079
5080
5081







-
+







	    /*
	     * Variable cannot be an element in an array. If arrayPtr is
	     * non-NULL, it is, so throw up an error and return.
	     */

	    TclObjVarErrMsg(interp, varNamePtr, NULL, "define",
		    ISARRAYELEMENT, -1);
	    Tcl_SetErrorCode(interp, "TCL", "UPVAR", "LOCAL_ELEMENT", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "UPVAR", "LOCAL_ELEMENT", (char *)NULL);
	    return TCL_ERROR;
	}

	if (varPtr == NULL) {
	    return TCL_ERROR;
	}

5019
5020
5021
5022
5023
5024
5025
5026

5027
5028
5029
5030
5031
5032
5033
5168
5169
5170
5171
5172
5173
5174

5175
5176
5177
5178
5179
5180
5181
5182







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UpvarObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    CallFrame *framePtr;
    int result, hasLevel;
    Tcl_Obj *levelObj;
5069
5070
5071
5072
5073
5074
5075
5076

5077
5078
5079
5080
5081
5082
5083
5218
5219
5220
5221
5222
5223
5224

5225
5226
5227
5228
5229
5230
5231
5232







-
+







	 * Synthesize an error message since TclObjGetFrame doesn't do this
	 * for this particular case.
	 */

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"bad level \"%s\"", TclGetString(levelObj)));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LEVEL",
		TclGetString(levelObj), NULL);
		TclGetString(levelObj), (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * We've now finished with parsing levels; skip to the variable names.
     */

5160
5161
5162
5163
5164
5165
5166
5167

5168
5169
5170
5171
5172
5173
5174
5309
5310
5311
5312
5313
5314
5315

5316
5317
5318
5319
5320
5321
5322
5323







-
+







	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"search identifier \"%s\" isn't for variable \"%s\"",
		handle, TclGetString(varNamePtr)));
    } else {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"couldn't find search \"%s\"", handle));
    }
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAYSEARCH", handle, NULL);
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAYSEARCH", handle, (char *)NULL);
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * DeleteSearches --
5184
5185
5186
5187
5188
5189
5190
5191

5192
5193
5194
5195
5196
5197
5198
5333
5334
5335
5336
5337
5338
5339

5340
5341
5342
5343
5344
5345
5346
5347







-
+







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

static void
DeleteSearches(
    Interp *iPtr,
    Var *arrayVarPtr)	/* Variable whose searches are to be
    Var *arrayVarPtr)		/* Variable whose searches are to be
				 * deleted. */
{
    ArraySearch *searchPtr, *nextPtr;
    Tcl_HashEntry *sPtr;

    if (arrayVarPtr->flags & VAR_SEARCH_ACTIVE) {
	sPtr = Tcl_FindHashEntry(&iPtr->varSearches, arrayVarPtr);
5343
5344
5345
5346
5347
5348
5349
5350

5351
5352
5353
5354
5355
5356
5357
5492
5493
5494
5495
5496
5497
5498

5499
5500
5501
5502
5503
5504
5505
5506







-
+







    if (tablePtr == &iPtr->globalNsPtr->varTable) {
	flags |= TCL_GLOBAL_ONLY;
    } else if (tablePtr == &currNsPtr->varTable) {
	flags |= TCL_NAMESPACE_ONLY;
    }

    for (varPtr = VarHashFirstVar(tablePtr, &search); varPtr != NULL;
	 varPtr = VarHashFirstVar(tablePtr, &search)) {
	    varPtr = VarHashFirstVar(tablePtr, &search)) {
	UnsetVarStruct(varPtr, NULL, iPtr, VarHashGetKey(varPtr), NULL, flags,
		-1);
	VarHashDeleteEntry(varPtr);
    }
    VarHashDeleteTable(tablePtr);
}

5380
5381
5382
5383
5384
5385
5386
5387

5388
5389
5390
5391
5392
5393
5394
5529
5530
5531
5532
5533
5534
5535

5536
5537
5538
5539
5540
5541
5542
5543







-
+







void
TclDeleteCompiledLocalVars(
    Interp *iPtr,		/* Interpreter to which variables belong. */
    CallFrame *framePtr)	/* Procedure call frame containing compiler-
				 * assigned local variables to delete. */
{
    Var *varPtr;
    int numLocals, i;
    Tcl_Size numLocals, i;
    Tcl_Obj **namePtrPtr;

    numLocals = framePtr->numCompiledLocals;
    varPtr = framePtr->compiledLocals;
    namePtrPtr = &localName(framePtr, 0);
    for (i=0 ; i<numLocals ; i++, namePtrPtr++, varPtr++) {
	UnsetVarStruct(varPtr, NULL, iPtr, *namePtrPtr, NULL,
5578
5579
5580
5581
5582
5583
5584
5585

5586
5587
5588

5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601

5602
5603
5604

5605
5606
5607
5608

5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627

5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644

5645
5646
5647

5648
5649
5650
5651
5652
5653
5654
5727
5728
5729
5730
5731
5732
5733

5734
5735
5736

5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749

5750
5751
5752

5753
5754
5755
5756

5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775

5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792

5793
5794
5795

5796
5797
5798
5799
5800
5801
5802
5803







-
+


-
+












-
+


-
+



-
+


















-
+
















-
+


-
+







 *   twoPtrValue.ptr2: index into locals table
 */

static void
FreeLocalVarName(
    Tcl_Obj *objPtr)
{
    int index;
    Tcl_Size index;
    Tcl_Obj *namePtr;

    LocalGetIntRep(objPtr, index, namePtr);
    LocalGetInternalRep(objPtr, index, namePtr);

    index++;	/* Compiler warning bait. */
    if (namePtr) {
	Tcl_DecrRefCount(namePtr);
    }
}

static void
DupLocalVarName(
    Tcl_Obj *srcPtr,
    Tcl_Obj *dupPtr)
{
    int index;
    Tcl_Size index;
    Tcl_Obj *namePtr;

    LocalGetIntRep(srcPtr, index, namePtr);
    LocalGetInternalRep(srcPtr, index, namePtr);
    if (!namePtr) {
	namePtr = srcPtr;
    }
    LocalSetIntRep(dupPtr, index, namePtr);
    LocalSetInternalRep(dupPtr, index, namePtr);
}

/*
 * parsedVarName -
 *
 * INTERNALREP DEFINITION:
 *   twoPtrValue.ptr1 = pointer to the array name Tcl_Obj (NULL if scalar)
 *   twoPtrValue.ptr2 = pointer to the element name string (owned by this
 *			Tcl_Obj), or NULL if it is a scalar variable
 */

static void
FreeParsedVarName(
    Tcl_Obj *objPtr)
{
    Tcl_Obj *arrayPtr, *elem;
    int parsed;

    ParsedGetIntRep(objPtr, parsed, arrayPtr, elem);
    ParsedGetInternalRep(objPtr, parsed, arrayPtr, elem);

    parsed++;				/* Silence compiler. */
    if (arrayPtr != NULL) {
	TclDecrRefCount(arrayPtr);
	TclDecrRefCount(elem);
    }
}

static void
DupParsedVarName(
    Tcl_Obj *srcPtr,
    Tcl_Obj *dupPtr)
{
    Tcl_Obj *arrayPtr, *elem;
    int parsed;

    ParsedGetIntRep(srcPtr, parsed, arrayPtr, elem);
    ParsedGetInternalRep(srcPtr, parsed, arrayPtr, elem);

    parsed++;				/* Silence compiler. */
    ParsedSetIntRep(dupPtr, arrayPtr, elem);
    ParsedSetInternalRep(dupPtr, arrayPtr, elem);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FindNamespaceVar -- MOVED OVER from tclNamesp.c
 *
5804
5805
5806
5807
5808
5809
5810
5811

5812
5813
5814
5815
5816
5817
5818
5953
5954
5955
5956
5957
5958
5959

5960
5961
5962
5963
5964
5965
5966
5967







-
+







    }
    if (simpleName != name) {
	Tcl_DecrRefCount(simpleNamePtr);
    }
    if ((varPtr == NULL) && (flags & TCL_LEAVE_ERR_MSG)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"unknown variable \"%s\"", name));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", name, NULL);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", name, (char *)NULL);
    }
    return (Tcl_Var) varPtr;
}

/*
 *----------------------------------------------------------------------
 *
5835
5836
5837
5838
5839
5840
5841
5842

5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5984
5985
5986
5987
5988
5989
5990

5991
5992
5993
5994
5995
5996
5997
5998
5999
6000

6001
6002
6003
6004
6005
6006
6007







-
+









-







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

int
TclInfoVarsCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    const char *varName, *pattern, *simplePattern;
    Tcl_HashSearch search;
    Var *varPtr;
    Namespace *nsPtr;
    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
    Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
    Tcl_Obj *listPtr, *elemObjPtr, *varNamePtr;
    int specificNsInPattern = 0;/* Init. to avoid compiler warning. */
    Tcl_Obj *simplePatternPtr = NULL;

    /*
     * Get the pattern and find the "effective namespace" in which to list
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
6074
6075
6076
6077
6078
6079
6080










6081
6082
6083
6084
6085
6086
6087







-
-
-
-
-
-
-
-
-
-







			Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr,
				elemObjPtr);
		    } else {
			elemObjPtr = VarHashGetKey(varPtr);
		    }
		    Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
		}
	    } else if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
		varPtr = VarHashFindVar(&globalNsPtr->varTable,
			simplePatternPtr);
		if (varPtr) {
		    if (!TclIsVarUndefined(varPtr)
			    || TclIsVarNamespaceVar(varPtr)) {
			Tcl_ListObjAppendElement(interp, listPtr,
				VarHashGetKey(varPtr));
		    }
		}
	    }
	} else {
	    /*
	     * Have to scan the tables of variables.
	     */

	    varPtr = VarHashFirstVar(&nsPtr->varTable, &search);
5962
5963
5964
5965
5966
5967
5968
5969

5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000

6001
6002
6003
6004
6005
6006
6007
6100
6101
6102
6103
6104
6105
6106

6107





























6108

6109
6110
6111
6112
6113
6114
6115
6116







-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
+







			    elemObjPtr = varNamePtr;
			}
			Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
		    }
		}
		varPtr = VarHashNextVar(&search);
	    }

	}
	    /*
	     * If the effective namespace isn't the global :: namespace, and a
	     * specific namespace wasn't requested in the pattern (i.e., the
	     * pattern only specifies variable names), then add in all global
	     * :: variables that match the simple pattern. Of course, add in
	     * only those variables that aren't hidden by a variable in the
	     * effective namespace.
	     */

	    if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
		varPtr = VarHashFirstVar(&globalNsPtr->varTable, &search);
		while (varPtr) {
		    if (!TclIsVarUndefined(varPtr)
			    || TclIsVarNamespaceVar(varPtr)) {
			varNamePtr = VarHashGetKey(varPtr);
			varName = TclGetString(varNamePtr);
			if ((simplePattern == NULL)
				|| Tcl_StringMatch(varName, simplePattern)) {
			    if (VarHashFindVar(&nsPtr->varTable,
				    varNamePtr) == NULL) {
				Tcl_ListObjAppendElement(interp, listPtr,
					varNamePtr);
			    }
			}
		    }
		    varPtr = VarHashNextVar(&search);
		}
	    }
	}
    } else if (iPtr->varFramePtr->procPtr != NULL) {
	AppendLocals(interp, listPtr, simplePatternPtr, 1);
	AppendLocals(interp, listPtr, simplePatternPtr, 1, 0);
    }

    if (simplePatternPtr) {
	Tcl_DecrRefCount(simplePatternPtr);
    }
    Tcl_SetObjResult(interp, listPtr);
    return TCL_OK;
6026
6027
6028
6029
6030
6031
6032
6033

6034
6035
6036
6037
6038
6039
6040
6135
6136
6137
6138
6139
6140
6141

6142
6143
6144
6145
6146
6147
6148
6149







-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

int
TclInfoGlobalsCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *varName, *pattern;
    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
    Tcl_HashSearch search;
6119
6120
6121
6122
6123
6124
6125
6126

6127
6128
6129
6130
6131
6132
6133
6228
6229
6230
6231
6232
6233
6234

6235
6236
6237
6238
6239
6240
6241
6242







-
+







 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

int
TclInfoLocalsCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *patternPtr, *listPtr;

6147
6148
6149
6150
6151
6152
6153
6154



































































































































































































6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174


















6175
6176
6177
6178
6179
6180
6181


6182
6183
6184
6185


6186
6187
6188
6189
6190
6191
6192
6256
6257
6258
6259
6260
6261
6262

6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
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

6502
6503
6504
6505
6506

6507
6508
6509
6510
6511
6512
6513
6514
6515







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+
+



-
+
+







    /*
     * Return a list containing names of first the compiled locals (i.e. the
     * ones stored in the call frame), then the variables in the local hash
     * table (if one exists).
     */

    listPtr = Tcl_NewListObj(0, NULL);
    AppendLocals(interp, listPtr, patternPtr, 0);
    AppendLocals(interp, listPtr, patternPtr, 0, 0);
    Tcl_SetObjResult(interp, listPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclInfoConstsCmd --
 *
 *	Called to implement the "info consts" command that returns the list of
 *	constants in the interpreter that match an optional pattern. The
 *	pattern, if any, consists of an optional sequence of namespace names
 *	separated by "::" qualifiers, which is followed by a glob-style
 *	pattern that restricts which variables are returned. Handles the
 *	following syntax:
 *
 *	    info consts ?pattern?
 *
 * Results:
 *	Returns TCL_OK if successful and TCL_ERROR if there is an error.
 *
 * Side effects:
 *	Returns a result in the interpreter's result object. If there is an
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

int
TclInfoConstsCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    const char *varName, *pattern, *simplePattern;
    Tcl_HashSearch search;
    Var *varPtr;
    Namespace *nsPtr;
    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
    Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
    Tcl_Obj *listPtr, *elemObjPtr, *varNamePtr;
    int specificNsInPattern = 0;/* Init. to avoid compiler warning. */
    Tcl_Obj *simplePatternPtr = NULL;

    /*
     * Get the pattern and find the "effective namespace" in which to list
     * variables. We only use this effective namespace if there's no active
     * Tcl procedure frame.
     */

    if (objc == 1) {
	simplePattern = NULL;
	nsPtr = currNsPtr;
	specificNsInPattern = 0;
    } else if (objc == 2) {
	/*
	 * From the pattern, get the effective namespace and the simple
	 * pattern (no namespace qualifiers or ::'s) at the end. If an error
	 * was found while parsing the pattern, return it. Otherwise, if the
	 * namespace wasn't found, just leave nsPtr NULL: we will return an
	 * empty list since no variables there can be found.
	 */

	Namespace *dummy1NsPtr, *dummy2NsPtr;

	pattern = TclGetString(objv[1]);
	TclGetNamespaceForQualName(interp, pattern, NULL, /*flags*/ 0,
		&nsPtr, &dummy1NsPtr, &dummy2NsPtr, &simplePattern);

	if (nsPtr != NULL) {	/* We successfully found the pattern's ns. */
	    specificNsInPattern = (strcmp(simplePattern, pattern) != 0);
	    if (simplePattern == pattern) {
		simplePatternPtr = objv[1];
	    } else {
		simplePatternPtr = Tcl_NewStringObj(simplePattern, -1);
	    }
	    Tcl_IncrRefCount(simplePatternPtr);
	}
    } else {
	Tcl_WrongNumArgs(interp, 1, objv, "?pattern?");
	return TCL_ERROR;
    }

    /*
     * If the namespace specified in the pattern wasn't found, just return.
     */

    if (nsPtr == NULL) {
	return TCL_OK;
    }

    listPtr = Tcl_NewListObj(0, NULL);

    if (!HasLocalVars(iPtr->varFramePtr) || specificNsInPattern) {
	/*
	 * There is no frame pointer, the frame pointer was pushed only to
	 * activate a namespace, or we are in a procedure call frame but a
	 * specific namespace was specified. Create a list containing only the
	 * variables in the effective namespace's variable table.
	 */

	if (simplePattern && TclMatchIsTrivial(simplePattern)) {
	    /*
	     * If we can just do hash lookups, that simplifies things a lot.
	     */

	    varPtr = VarHashFindVar(&nsPtr->varTable, simplePatternPtr);
	    if (varPtr && TclIsVarConstant(varPtr)) {
		if (!TclIsVarUndefined(varPtr)
			|| TclIsVarNamespaceVar(varPtr)) {
		    if (specificNsInPattern) {
			TclNewObj(elemObjPtr);
			Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr,
				elemObjPtr);
		    } else {
			elemObjPtr = VarHashGetKey(varPtr);
		    }
		    Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
		}
	    } else if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
		varPtr = VarHashFindVar(&globalNsPtr->varTable,
			simplePatternPtr);
		if (varPtr && TclIsVarConstant(varPtr)) {
		    if (!TclIsVarUndefined(varPtr)
			    || TclIsVarNamespaceVar(varPtr)) {
			Tcl_ListObjAppendElement(interp, listPtr,
				VarHashGetKey(varPtr));
		    }
		}
	    }
	} else {
	    /*
	     * Have to scan the tables of variables.
	     */

	    varPtr = VarHashFirstVar(&nsPtr->varTable, &search);
	    while (varPtr) {
		if (TclIsVarConstant(varPtr) && (!TclIsVarUndefined(varPtr)
			|| TclIsVarNamespaceVar(varPtr))) {
		    varNamePtr = VarHashGetKey(varPtr);
		    varName = TclGetString(varNamePtr);
		    if ((simplePattern == NULL)
			    || Tcl_StringMatch(varName, simplePattern)) {
			if (specificNsInPattern) {
			    TclNewObj(elemObjPtr);
			    Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr,
				    elemObjPtr);
			} else {
			    elemObjPtr = varNamePtr;
			}
			Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
		    }
		}
		varPtr = VarHashNextVar(&search);
	    }

	    /*
	     * If the effective namespace isn't the global :: namespace, and a
	     * specific namespace wasn't requested in the pattern (i.e., the
	     * pattern only specifies variable names), then add in all global
	     * :: variables that match the simple pattern. Of course, add in
	     * only those variables that aren't hidden by a variable in the
	     * effective namespace.
	     */

	    if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
		varPtr = VarHashFirstVar(&globalNsPtr->varTable, &search);
		while (varPtr) {
		    if (TclIsVarConstant(varPtr) && (!TclIsVarUndefined(varPtr)
			    || TclIsVarNamespaceVar(varPtr))) {
			varNamePtr = VarHashGetKey(varPtr);
			varName = TclGetString(varNamePtr);
			if ((simplePattern == NULL)
				|| Tcl_StringMatch(varName, simplePattern)) {
			    if (VarHashFindVar(&nsPtr->varTable,
				    varNamePtr) == NULL) {
				Tcl_ListObjAppendElement(interp, listPtr,
					varNamePtr);
			    }
			}
		    }
		    varPtr = VarHashNextVar(&search);
		}
	    }
	}
    } else if (iPtr->varFramePtr->procPtr != NULL) {
	AppendLocals(interp, listPtr, simplePatternPtr, 1, 1);
    }

    if (simplePatternPtr) {
	Tcl_DecrRefCount(simplePatternPtr);
    }
    Tcl_SetObjResult(interp, listPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * AppendLocals --
 *
 *	Append the local variables for the current frame to the specified list
 *	object.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
ContextObjectContainsConstant(
    Tcl_ObjectContext context,
    Tcl_Obj *varNamePtr)
{
    /*
     * Helper for AppendLocals to check if an object contains a variable
     * that is a constant. It's too complicated without factoring this
     * check out!
     */

    Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
    Namespace *nsPtr = (Namespace *) oPtr->namespacePtr;
    Var *varPtr = VarHashFindVar(&nsPtr->varTable, varNamePtr);

    return !TclIsVarUndefined(varPtr) && TclIsVarConstant(varPtr);
}

static void
AppendLocals(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Obj *listPtr,		/* List object to append names to. */
    Tcl_Obj *patternPtr,	/* Pattern to match against. */
    int includeLinks)		/* 1 if upvars should be included, else 0. */
    int includeLinks,		/* 1 if upvars should be included, else 0. */
    int justConstants)		/* 1 if just constants should be included. */
{
    Interp *iPtr = (Interp *) interp;
    Var *varPtr;
    int i, localVarCt, added;
    Tcl_Size i, localVarCt;
    int added;
    Tcl_Obj *objNamePtr;
    const char *varName;
    TclVarHashTable *localVarTablePtr;
    Tcl_HashSearch search;
    Tcl_HashTable addedTable;
    const char *pattern = patternPtr? TclGetString(patternPtr) : NULL;

6202
6203
6204
6205
6206
6207
6208
6209

6210
6211

6212


6213
6214
6215
6216
6217
6218
6219
6525
6526
6527
6528
6529
6530
6531

6532
6533
6534
6535

6536
6537
6538
6539
6540
6541
6542
6543
6544







-
+


+
-
+
+








	for (i = 0; i < localVarCt; i++, varNamePtr++) {
	    /*
	     * Skip nameless (temporary) variables and undefined variables.
	     */

	    if (*varNamePtr && !TclIsVarUndefined(varPtr)
		&& (includeLinks || !TclIsVarLink(varPtr))) {
		    && (includeLinks || !TclIsVarLink(varPtr))) {
		varName = TclGetString(*varNamePtr);
		if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) {
		    if (!justConstants || TclIsVarConstant(varPtr)) {
		    Tcl_ListObjAppendElement(interp, listPtr, *varNamePtr);
			Tcl_ListObjAppendElement(interp, listPtr, *varNamePtr);
		    }
		    if (includeLinks) {
			Tcl_CreateHashEntry(&addedTable, *varNamePtr, &added);
		    }
		}
	    }
	    varPtr++;
	}
6232
6233
6234
6235
6236
6237
6238

6239
6240



6241
6242
6243
6244
6245
6246
6247
6557
6558
6559
6560
6561
6562
6563
6564


6565
6566
6567
6568
6569
6570
6571
6572
6573
6574







+
-
-
+
+
+







     */

    if ((pattern != NULL) && TclMatchIsTrivial(pattern)) {
	varPtr = VarHashFindVar(localVarTablePtr, patternPtr);
	if (varPtr != NULL) {
	    if (!TclIsVarUndefined(varPtr)
		    && (includeLinks || !TclIsVarLink(varPtr))) {
		if ((!justConstants || TclIsVarConstant(varPtr))) {
		Tcl_ListObjAppendElement(interp, listPtr,
			VarHashGetKey(varPtr));
		    Tcl_ListObjAppendElement(interp, listPtr,
			    VarHashGetKey(varPtr));
		}
		if (includeLinks) {
		    Tcl_CreateHashEntry(&addedTable, VarHashGetKey(varPtr),
			    &added);
		}
	    }
	}
	goto objectVars;
6255
6256
6257
6258
6259
6260
6261

6262


6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275


6276

6277
6278
6279
6280
6281
6282
6283
6284




6285
6286
6287
6288
6289
6290
6291
6292




6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304




6305
6306
6307
6308
6309
6310
6311
6312




6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323









































6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336

6337
6338
6339
6340
6341
6342
6343
6582
6583
6584
6585
6586
6587
6588
6589

6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606

6607

6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731







+
-
+
+













+
+
-
+
-







+
+
+
+








+
+
+
+












+
+
+
+








+
+
+
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













+







	    varPtr != NULL;
	    varPtr = VarHashNextVar(&search)) {
	if (!TclIsVarUndefined(varPtr)
		&& (includeLinks || !TclIsVarLink(varPtr))) {
	    objNamePtr = VarHashGetKey(varPtr);
	    varName = TclGetString(objNamePtr);
	    if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) {
		if (!justConstants || TclIsVarConstant(varPtr)) {
		Tcl_ListObjAppendElement(interp, listPtr, objNamePtr);
		    Tcl_ListObjAppendElement(interp, listPtr, objNamePtr);
		}
		if (includeLinks) {
		    Tcl_CreateHashEntry(&addedTable, objNamePtr, &added);
		}
	    }
	}
    }

  objectVars:
    if (!includeLinks) {
	return;
    }

    if (iPtr->varFramePtr->isProcCallFrame & FRAME_IS_METHOD) {
	Tcl_ObjectContext context = (Tcl_ObjectContext)
		iPtr->varFramePtr->clientData;
	Method *mPtr = (Method *)
	Method *mPtr = (Method *) Tcl_ObjectContextMethod(context);
		Tcl_ObjectContextMethod((Tcl_ObjectContext)iPtr->varFramePtr->clientData);
	PrivateVariableMapping *privatePtr;

	if (mPtr->declaringObjectPtr) {
	    Object *oPtr = mPtr->declaringObjectPtr;

	    FOREACH(objNamePtr, oPtr->variables) {
		Tcl_CreateHashEntry(&addedTable, objNamePtr, &added);
		if (justConstants && !ContextObjectContainsConstant(context,
			objNamePtr)) {
		    continue;
		}
		if (added && (!pattern ||
			Tcl_StringMatch(TclGetString(objNamePtr), pattern))) {
		    Tcl_ListObjAppendElement(interp, listPtr, objNamePtr);
		}
	    }
	    FOREACH_STRUCT(privatePtr, oPtr->privateVariables) {
		Tcl_CreateHashEntry(&addedTable, privatePtr->variableObj,
			&added);
		if (justConstants && !ContextObjectContainsConstant(context,
			privatePtr->fullNameObj)) {
		    continue;
		}
		if (added && (!pattern ||
			Tcl_StringMatch(TclGetString(privatePtr->variableObj),
				pattern))) {
		    Tcl_ListObjAppendElement(interp, listPtr,
			    privatePtr->variableObj);
		}
	    }
	} else {
	    Class *clsPtr = mPtr->declaringClassPtr;

	    FOREACH(objNamePtr, clsPtr->variables) {
		Tcl_CreateHashEntry(&addedTable, objNamePtr, &added);
		if (justConstants && !ContextObjectContainsConstant(context,
			objNamePtr)) {
		    continue;
		}
		if (added && (!pattern ||
			Tcl_StringMatch(TclGetString(objNamePtr), pattern))) {
		    Tcl_ListObjAppendElement(interp, listPtr, objNamePtr);
		}
	    }
	    FOREACH_STRUCT(privatePtr, clsPtr->privateVariables) {
		Tcl_CreateHashEntry(&addedTable, privatePtr->variableObj,
			&added);
		if (justConstants && !ContextObjectContainsConstant(context,
			privatePtr->fullNameObj)) {
		    continue;
		}
		if (added && (!pattern ||
			Tcl_StringMatch(TclGetString(privatePtr->variableObj),
				pattern))) {
		    Tcl_ListObjAppendElement(interp, listPtr,
			    privatePtr->variableObj);
		}
	    }
	}
    }
    Tcl_DeleteHashTable(&addedTable);
}

/*
 *----------------------------------------------------------------------
 *
 * TclInfoConstantCmd --
 *
 *	Called to implement the "info constant" command that tests whether a
 *	specific variable is a constant. Handles the following syntax:
 *
 *	    info constant varName
 *
 * Results:
 *	Returns TCL_OK if successful and TCL_ERROR if there is an error.
 *
 * Side effects:
 *	Returns a result in the interpreter's result object. If there is an
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

int
TclInfoConstantCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Var *varPtr, *arrayPtr;
    int result;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "varName");
	return TCL_ERROR;
    }
    varPtr = TclObjLookupVar(interp, objv[1], NULL, 0, "lookup", 0, 0,
	    &arrayPtr);
    result = (varPtr && TclIsVarConstant(varPtr));
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result));
    return TCL_OK;
}

/*
 * Hash table implementation - first, just copy and adapt the obj key stuff
 */

void
TclInitVarHashTable(
    TclVarHashTable *tablePtr,
    Namespace *nsPtr)
{
    Tcl_InitCustomHashTable(&tablePtr->table,
	    TCL_CUSTOM_TYPE_KEYS, &tclVarHashKeyType);
    tablePtr->nsPtr = nsPtr;
    tablePtr->arrayPtr = NULL;
}

static Tcl_HashEntry *
AllocVarEntry(
    TCL_UNUSED(Tcl_HashTable *),
    void *keyPtr)		/* Key to store in the hash table entry. */
{
6374
6375
6376
6377
6378
6379
6380
6381

6382
6383
6384
6385
6386
6387
6388
6762
6763
6764
6765
6766
6767
6768

6769
6770
6771
6772
6773
6774
6775
6776







-
+







	VarHashRefCount(varPtr)--;
    }
    Tcl_DecrRefCount(objPtr);
}

static int
CompareVarKeys(
    void *keyPtr,			/* New key to compare. */
    void *keyPtr,		/* New key to compare. */
    Tcl_HashEntry *hPtr)	/* Existing key to compare. */
{
    Tcl_Obj *objPtr1 = (Tcl_Obj *)keyPtr;
    Tcl_Obj *objPtr2 = hPtr->key.objPtr;
    const char *p1, *p2;
    size_t l1, l2;

6424
6425
6426
6427
6428
6429
6430
6431

6432
6433
6434
6435
6436
6437
6438
6439

6440
6441
6442

6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
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
6812
6813
6814
6815
6816
6817
6818

6819
6820
6821
6822
6823
6824
6825
6826

6827
6828
6829

6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850

6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865

6866
6867
6868
6869
6870
6871
6872
6873







-
+







-
+


-
+




















-
+














-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayDefaultCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static const char *const options[] = {
	"get", "set", "exists", "unset", NULL
    };
    enum arrayDefaultOptionsEnum { OPT_GET, OPT_SET, OPT_EXISTS, OPT_UNSET };
    enum arrayDefaultOptionsEnum { OPT_GET, OPT_SET, OPT_EXISTS, OPT_UNSET } option;
    Tcl_Obj *arrayNameObj, *defaultValueObj;
    Var *varPtr, *arrayPtr;
    int isArray, option;
    int isArray;

    /*
     * Parse arguments.
     */

    if (objc != 3 && objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "option arrayName ?value?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], options, "option",
	    0, &option) != TCL_OK) {
	return TCL_ERROR;
    }

    arrayNameObj = objv[2];

    if (TCL_ERROR == LocateArray(interp, arrayNameObj, &varPtr, &isArray)) {
	return TCL_ERROR;
    }

    switch ((enum arrayDefaultOptionsEnum)option) {
    switch (option) {
    case OPT_GET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "arrayName");
	    return TCL_ERROR;
	}
	if (!varPtr || TclIsVarUndefined(varPtr) || !isArray) {
	    return NotArrayError(interp, arrayNameObj);
	}

	defaultValueObj = TclGetArrayDefault(varPtr);
	if (!defaultValueObj) {
	    /* Array default must exist. */
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "array has no default value", -1));
	    Tcl_SetErrorCode(interp, "TCL", "READ", "ARRAY", "DEFAULT", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "READ", "ARRAY", "DEFAULT", (char *)NULL);
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, defaultValueObj);
	return TCL_OK;

    case OPT_SET:
	if (objc != 4) {
6501
6502
6503
6504
6505
6506
6507
6508

6509
6510
6511
6512
6513
6514
6515
6516
6517
6518

6519
6520
6521
6522
6523
6524
6525
6889
6890
6891
6892
6893
6894
6895

6896
6897
6898
6899
6900
6901
6902
6903
6904
6905

6906
6907
6908
6909
6910
6911
6912
6913







-
+









-
+







	     * Not a valid array name.
	     */

	    CleanupVar(varPtr, arrayPtr);
	    TclObjVarErrMsg(interp, arrayNameObj, NULL, "array default set",
		    NEEDARRAY, -1);
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME",
		    TclGetString(arrayNameObj), NULL);
		    TclGetString(arrayNameObj), (char *)NULL);
	    return TCL_ERROR;
	}
	if (!TclIsVarArray(varPtr) && !TclIsVarUndefined(varPtr)) {
	    /*
	     * Not an array.
	     */

	    TclObjVarErrMsg(interp, arrayNameObj, NULL, "array default set",
		    NEEDARRAY, -1);
	    Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", (char *)NULL);
	    return TCL_ERROR;
	}

	if (!TclIsVarArray(varPtr)) {
	    TclInitArrayVar(varPtr);
	}
	defaultValueObj = objv[3];
6584
6585
6586
6587
6588
6589
6590

6591
6592
6593
6594
6595
6596
6597
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986







+








    /*
     * Regular TclVarHashTable initialization.
     */

    arrayPtr->value.tablePtr = (TclVarHashTable *) tablePtr;
    TclInitVarHashTable(arrayPtr->value.tablePtr, TclGetVarNsPtr(arrayPtr));
    arrayPtr->value.tablePtr->arrayPtr = arrayPtr;

    /*
     * Default value initialization.
     */

    tablePtr->defaultObj = NULL;
}
6653
6654
6655
6656
6657
6658
6659
6660
6661


6662
6663
6664
6665
6666


6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
7042
7043
7044
7045
7046
7047
7048


7049
7050
7051
7052
7053


7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
7065







-
-
+
+



-
-
+
+










     *
     *      array default set v 1
     *      lappend v(a) 2; # returns a new object {1 2}
     *      set v(b); # returns the original default object "1"
     */

    if (tablePtr->defaultObj) {
        Tcl_DecrRefCount(tablePtr->defaultObj);
        Tcl_DecrRefCount(tablePtr->defaultObj);
	Tcl_DecrRefCount(tablePtr->defaultObj);
	Tcl_DecrRefCount(tablePtr->defaultObj);
    }
    tablePtr->defaultObj = defaultObj;
    if (tablePtr->defaultObj) {
        Tcl_IncrRefCount(tablePtr->defaultObj);
        Tcl_IncrRefCount(tablePtr->defaultObj);
	Tcl_IncrRefCount(tablePtr->defaultObj);
	Tcl_IncrRefCount(tablePtr->defaultObj);
    }
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclZipfs.c.

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
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
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
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




-
+

-
-
+
+








+
+
+
+




+
+









-




+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+







-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-







/*
 * tclZipfs.c --
 *
 *	Implementation of the ZIP filesystem used in TIP 430
 *	Adapted from the implentation for AndroWish.
 *	Adapted from the implementation for AndroWish.
 *
 * Copyright (c) 2016-2017 Sean Woods <yoda@etoyoc.com>
 * Copyright (c) 2013-2015 Christian Werner <chw@ch-werner.de>
 * Copyright © 2016-2017 Sean Woods <yoda@etoyoc.com>
 * Copyright © 2013-2015 Christian Werner <chw@ch-werner.de>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * This file is distributed in two ways:
 *   generic/tclZipfs.c file in the TIP430-enabled Tcl cores.
 *   compat/tclZipfs.c file in the tclconfig (TEA) file system, for pre-tip430
 *	projects.
 *
 * Helpful docs:
 * https://pkware.cachefly.net/webdocs/APPNOTE/APPNOTE-6.3.9.TXT
 * https://libzip.org/specifications/appnote_iz.txt
 */

#include "tclInt.h"
#include "tclFileSystem.h"

#include <assert.h>

#ifndef _WIN32
#include <sys/mman.h>
#endif /* _WIN32*/

#ifndef MAP_FILE
#define MAP_FILE 0
#endif /* !MAP_FILE */
#define NOBYFOUR
#define crc32tab crc_table[0]
#ifndef TBLS
#define TBLS 1
#endif

#if !defined(_WIN32) && !defined(NO_DLFCN_H)
#include <dlfcn.h>
#endif
#ifdef HAVE_ZLIB

/*
 * Macros to report errors only if an interp is present.
 */

#define ZIPFS_ERROR(interp,errstr) \
    do {								\
	if (interp) {							\
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(errstr, -1));	\
	}								\
    } while (0)
#define ZIPFS_MEM_ERROR(interp) \
    do {								\
	if (interp) {							\
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(			\
		    "out of memory", -1));				\
	    Tcl_SetErrorCode(interp, "TCL", "MALLOC", (char *)NULL);		\
	}								\
    } while (0)
#define ZIPFS_POSIX_ERROR(interp,errstr) \
    do {								\
	if (interp) {							\
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(			\
		    "%s: %s", errstr, Tcl_PosixError(interp)));		\
	}								\
    } while (0)
#define ZIPFS_ERROR_CODE(interp,errcode) \
    do {								\
	if (interp) {							\
	    Tcl_SetErrorCode(interp, "TCL", "ZIPFS", errcode, (char *)NULL);	\
	}								\
    } while (0)

#include "zlib.h"
#include "crypt.h"
#include "zutil.h"
#include "crc32.h"

#ifdef CFG_RUNTIME_DLLFILE
static const z_crc_t* crc32tab;

/*
** We are compiling as part of the core.
** TIP430 style zipfs prefix
*/

#define ZIPFS_VOLUME	  "//zipfs:/"
#define ZIPFS_VOLUME_LEN  9
#define ZIPFS_ROOTDIR_DEPTH 3 /* Number of / in root mount */
#define ZIPFS_APP_MOUNT	  "//zipfs:/app"
#define ZIPFS_ZIP_MOUNT	  "//zipfs:/lib/tcl"

#else /* !CFG_RUNTIME_DLLFILE */

/*
** We are compiling from the /compat folder of tclconfig
** Pre TIP430 style zipfs prefix
** //zipfs:/ doesn't work straight out of the box on either windows or Unix
** without other changes made to tip 430
*/

#define ZIPFS_VOLUME	  "zipfs:/"
#define ZIPFS_VOLUME_LEN  7
#define ZIPFS_APP_MOUNT	  "zipfs:/app"
#define ZIPFS_ZIP_MOUNT	  "zipfs:/lib/tcl"

#define ZIPFS_VOLUME_LEN  9
#define ZIPFS_APP_MOUNT	  ZIPFS_VOLUME "app"
#define ZIPFS_ZIP_MOUNT	  ZIPFS_VOLUME "lib/tcl"
#define ZIPFS_FALLBACK_ENCODING "cp437"
#endif /* CFG_RUNTIME_DLLFILE */

/*
 * Various constants and offsets found in ZIP archive files
 */

#define ZIP_SIG_LEN			4

85
86
87
88
89
90
91


92
93
94
95
96
97
98
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126







+
+







#define ZIP_LOCAL_MTIME_OFFS		10
#define ZIP_LOCAL_MDATE_OFFS		12
#define ZIP_LOCAL_CRC32_OFFS		14
#define ZIP_LOCAL_COMPLEN_OFFS		18
#define ZIP_LOCAL_UNCOMPLEN_OFFS	22
#define ZIP_LOCAL_PATHLEN_OFFS		26
#define ZIP_LOCAL_EXTRALEN_OFFS		28

#define ZIP_LOCAL_FLAGS_UTF8		0x0800

/*
 * Central header of ZIP archive member at end of ZIP file.
 */

#define ZIP_CENTRAL_HEADER_SIG		0x02014b50
#define ZIP_CENTRAL_HEADER_LEN		46
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
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
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







-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-









+
+
+
+
+
+
















+
-
+




-
+












-
-
-
+
+
+
+
+

-
+

-
+


+
+
+
+







+
+
+
+
+
+
+
+
+
+
+





-
-
-
+
+
+
-

+
+
+
+
-
+


-
+


+
+
+
+
+
+
+







-
+










-
+
+
+
+
+
+
+




-
+
















+
+
-
+

+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+











+
+
+










+
-
+






-
-
+
+







#define ZIP_CENTRAL_COMMENTLEN_OFFS	20

#define ZIP_MIN_VERSION			20
#define ZIP_COMPMETH_STORED		0
#define ZIP_COMPMETH_DEFLATED		8

#define ZIP_PASSWORD_END_SIG		0x5a5a4b50

#define DEFAULT_WRITE_MAX_SIZE		(2 * 1024 * 1024)

/*
 * Macros to report errors only if an interp is present.
 */

#define ZIPFS_ERROR(interp,errstr) \
#define ZIP_CRYPT_HDR_LEN		12
    do {								\
	if (interp) {							\
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(errstr, -1));	\
	}								\
    } while (0)
#define ZIPFS_POSIX_ERROR(interp,errstr) \
    do {								\
	if (interp) {							\
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(			\
		    "%s: %s", errstr, Tcl_PosixError(interp)));		\
	}								\
    } while (0)

/*
 * Macros to read and write 16 and 32 bit integers from/to ZIP archives.
 */

#define ZIP_MAX_FILE_SIZE		INT_MAX
#define ZipReadInt(p) \
    ((p)[0] | ((p)[1] << 8) | ((p)[2] << 16) | ((p)[3] << 24))
#define ZipReadShort(p) \
    ((p)[0] | ((p)[1] << 8))

#define DEFAULT_WRITE_MAX_SIZE		ZIP_MAX_FILE_SIZE
#define ZipWriteInt(p, v) \
    do {			     \
	(p)[0] = (v) & 0xff;	     \
	(p)[1] = ((v) >> 8) & 0xff;  \
	(p)[2] = ((v) >> 16) & 0xff; \
	(p)[3] = ((v) >> 24) & 0xff; \
    } while (0)
#define ZipWriteShort(p, v) \
    do {			    \
	(p)[0] = (v) & 0xff;	    \
	(p)[1] = ((v) >> 8) & 0xff; \
    } while (0)

/*
 * Windows drive letters.
 */

#ifdef _WIN32
static const char drvletters[] =
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
#endif /* _WIN32 */

/*
 * Mutex to protect localtime(3) when no reentrant version available.
 */

#if !defined(_WIN32) && !defined(HAVE_LOCALTIME_R) && TCL_THREADS
TCL_DECLARE_MUTEX(localtimeMutex)
#endif /* !_WIN32 && !HAVE_LOCALTIME_R && TCL_THREADS */

/*
 * Forward declaration.
 */

struct ZipEntry;

/*
 * In-core description of mounted ZIP archive file.
 */

typedef struct ZipFile {
    char *name;			/* Archive name */
    size_t nameLength;		/* Length of archive name */
    char isMemBuffer;		/* When true, not a file but a memory buffer */
    Tcl_Channel chan;		/* Channel handle or NULL */
    unsigned char *data;	/* Memory mapped or malloc'ed file */
    size_t length;		/* Length of memory mapped file */
    void *ptrToFree;		/* Non-NULL if malloc'ed file */
    size_t numFiles;		/* Number of files in archive */
    size_t baseOffset;		/* Archive start */
    size_t passOffset;		/* Password start */
    size_t directoryOffset;	/* Archive directory start */
    size_t directorySize;       /* Size of archive directory */
    unsigned char passBuf[264];	/* Password buffer */
    unsigned char passBuf[264]; /* Password buffer */
    size_t numOpen;		/* Number of open files on archive */
    struct ZipEntry *entries;	/* List of files in archive */
    struct ZipEntry *topEnts;	/* List of top-level dirs in archive */
    char *mountPoint;		/* Mount point name */
    size_t mountPointLen;	/* Length of mount point name */
    Tcl_Size mountPointLen;	/* Length of mount point name */
#ifdef _WIN32
    HANDLE mountHandle;		/* Handle used for direct file access. */
#endif /* _WIN32 */
} ZipFile;

/*
 * In-core description of file contained in mounted ZIP archive.
 */

typedef struct ZipEntry {
    char *name;			/* The full pathname of the virtual file */
    ZipFile *zipFilePtr;	/* The ZIP file holding this virtual file */
    Tcl_WideInt offset;		/* Data offset into memory mapped ZIP file */
    int numBytes;		/* Uncompressed size of the virtual file */
    int numCompressedBytes;	/* Compressed size of the virtual file */
    size_t offset;		/* Data offset into memory mapped ZIP file */
    int numBytes;		/* Uncompressed size of the virtual file.
				 * -1 for zip64 */
    int numCompressedBytes;	/* Compressed size of the virtual file.
				 * -1 for zip64 */
    int compressMethod;		/* Compress method */
    int isDirectory;		/* Set to 1 if directory, or -1 if root */
    int isDirectory;		/* 0 if file, 1 if directory, -1 if root */
    int depth;			/* Number of slashes in path. */
    int crc32;			/* CRC-32 */
    int crc32;			/* CRC-32 as stored in ZIP */
    int timestamp;		/* Modification time */
    int isEncrypted;		/* True if data is encrypted */
    int flags;
#define ZE_F_CRC_COMPARED      0x0001  /* If 1, the CRC has been compared. */
#define ZE_F_CRC_CORRECT       0x0002  /* Only meaningful if ZE_F_CRC_COMPARED is 1 */
#define ZE_F_VOLUME            0x0004  /* Entry corresponds to //zipfs:/ */
    unsigned char *data;	/* File data if written */
    struct ZipEntry *next;	/* Next file in the same archive */
    struct ZipEntry *tnext;	/* Next top-level dir in archive */
} ZipEntry;

/*
 * File channel for file contained in mounted ZIP archive.
 *
 * Regarding data buffers:
 * For READ-ONLY files that are not encrypted and not compressed (zip STORE
 * method), ubuf points directly to the mapped zip file data in memory. No
 * additional storage is allocated and so ubufToFree is NULL.
 *
 * In all other combinations of compression and encryption or if channel is
 * writable, storage is allocated for the decrypted and/or uncompressed data
 * and a pointer to it is stored in ubufToFree and ubuf. When channel is
 * closed, ubufToFree is freed if not NULL. ubuf is irrelevant since it may
 * or may not point to allocated storage as above.
 */

typedef struct ZipChannel {
    ZipFile *zipFilePtr;	/* The ZIP file holding this channel */
    ZipEntry *zipEntryPtr;	/* Pointer back to virtual file */
    size_t maxWrite;		/* Maximum size for write */
    size_t numBytes;		/* Number of bytes of uncompressed data */
    size_t numRead;		/* Position of next byte to be read from the
    Tcl_Size maxWrite;		/* Maximum size for write */
    Tcl_Size numBytes;		/* Number of bytes of uncompressed data */
    Tcl_Size cursor;		/* Seek position for next read or write*/
				 * channel */
    unsigned char *ubuf;	/* Pointer to the uncompressed data */
    unsigned char *ubufToFree;  /* NULL if ubuf points to memory that does not
				   need freeing. Else memory to free (ubuf
				   may point *inside* the block) */
    Tcl_Size ubufSize;		/* Size of allocated ubufToFree */
    int iscompr;		/* True if data is compressed */
    int iscompr;                /* True if data is compressed */
    int isDirectory;		/* Set to 1 if directory, or -1 if root */
    int isEncrypted;		/* True if data is encrypted */
    int isWriting;		/* True if open for writing */
    int mode;			/* O_WRITE, O_APPEND, O_TRUNC etc.*/
    unsigned long keys[3];	/* Key for decryption */
} ZipChannel;

static inline int
ZipChannelWritable(
    ZipChannel *info)
{
    return (info->mode & (O_WRONLY | O_RDWR)) != 0;
}

/*
 * Global variables.
 *
 * Most are kept in single ZipFS struct. When build with threading support
 * this struct is protected by the ZipFSMutex (see below).
 *
 * The "fileHash" component is the process wide global table of all known ZIP
 * The "fileHash" component is the process-wide global table of all known ZIP
 * archive members in all mounted ZIP archives.
 *
 * The "zipHash" components is the process wide global table of all mounted
 * ZIP archive files.
 */

static struct {
    int initialized;		/* True when initialized */
    int lock;			/* RW lock, see below */
    int waiters;		/* RW lock, see below */
    int wrmax;			/* Maximum write size of a file */
    int wrmax;			/* Maximum write size of a file; only written
				 * to from Tcl code in a trusted interpreter,
				 * so NOT protected by mutex. */
    char *fallbackEntryEncoding;/* The fallback encoding for ZIP entries when
				 * they are believed to not be UTF-8; only
				 * written to from Tcl code in a trusted
				 * interpreter, so not protected by mutex. */
    int idCount;		/* Counter for channel names */
    Tcl_HashTable fileHash;	/* File name to ZipEntry mapping */
    Tcl_HashTable zipHash;	/* Mount to ZipFile mapping */
} ZipFS = {
    0, 0, 0, DEFAULT_WRITE_MAX_SIZE, 0,
    0, 0, 0, DEFAULT_WRITE_MAX_SIZE, NULL, 0,
	    {0,{0,0,0,0},0,0,0,0,0,0,0,0,0},
	    {0,{0,0,0,0},0,0,0,0,0,0,0,0,0}
};

/*
 * For password rotation.
 */

static const char pwrot[17] =
    "\x00\x80\x40\xC0\x20\xA0\x60\xE0"
    "\x10\x90\x50\xD0\x30\xB0\x70\xF0";

static const char *zipfs_literal_tcl_library = NULL;

/* Function prototypes */

static int		CopyImageFile(Tcl_Interp *interp, const char *imgName,
			    Tcl_Channel out);
static inline int	DescribeMounted(Tcl_Interp *interp,
static int		DescribeMounted(Tcl_Interp *interp,
			    const char *mountPoint);
static int		InitReadableChannel(Tcl_Interp *interp,
			    ZipChannel *info, ZipEntry *z);
static int		InitWritableChannel(Tcl_Interp *interp,
			    ZipChannel *info, ZipEntry *z, int trunc);
static inline int	ListMountPoints(Tcl_Interp *interp);
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);
static void		SerializeCentralDirectorySuffix(
			    const unsigned char *start,
			    const unsigned char *end, unsigned char *buf,
			    int entryCount, long long directoryStartOffset,
			    long long suffixStartOffset);
static void		SerializeLocalEntryHeader(
			    const unsigned char *start,
			    const unsigned char *end, unsigned char *buf,
			    ZipEntry *z, int nameLength, int align);
static int		IsCryptHeaderValid(ZipEntry *z,
			    unsigned char cryptHdr[ZIP_CRYPT_HDR_LEN]);
static int		DecodeCryptHeader(Tcl_Interp *interp, ZipEntry *z,
			    unsigned long keys[3],
			    unsigned char cryptHdr[ZIP_CRYPT_HDR_LEN]);
#if !defined(STATIC_BUILD)
static int		ZipfsAppHookFindTclInit(const char *archive);
#endif
static int		ZipFSPathInFilesystemProc(Tcl_Obj *pathPtr,
			    void **clientDataPtr);
static Tcl_Obj *	ZipFSFilesystemPathTypeProc(Tcl_Obj *pathPtr);
static Tcl_Obj *	ZipFSFilesystemSeparatorProc(Tcl_Obj *pathPtr);
static int		ZipFSStatProc(Tcl_Obj *pathPtr, Tcl_StatBuf *buf);
static int		ZipFSAccessProc(Tcl_Obj *pathPtr, int mode);
static Tcl_Channel	ZipFSOpenFileChannelProc(Tcl_Interp *interp,
			    Tcl_Obj *pathPtr, int mode, int permissions);
static int		ZipFSMatchInDirectoryProc(Tcl_Interp *interp,
			    Tcl_Obj *result, Tcl_Obj *pathPtr,
			    const char *pattern, Tcl_GlobTypeData *types);
static void		ZipFSMatchMountPoints(Tcl_Obj *result,
			    Tcl_Obj *normPathPtr, const char *pattern,
			    Tcl_DString *prefix);
static Tcl_Obj *	ZipFSListVolumesProc(void);
static const char *const *ZipFSFileAttrStringsProc(Tcl_Obj *pathPtr,
			    Tcl_Obj **objPtrRef);
static int		ZipFSFileAttrsGetProc(Tcl_Interp *interp, int index,
			    Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef);
static int		ZipFSFileAttrsSetProc(Tcl_Interp *interp, int index,
			    Tcl_Obj *pathPtr, Tcl_Obj *objPtr);
static int		ZipFSLoadFile(Tcl_Interp *interp, Tcl_Obj *path,
			    Tcl_LoadHandle *loadHandle,
			    Tcl_FSUnloadFileProc **unloadProcPtr, int flags);
static int		ZipMapArchive(Tcl_Interp *interp, ZipFile *zf,
static void		ZipfsExitHandler(ClientData clientData);
			    void *handle);
static void		ZipfsSetup(void);
static int		ZipChannelClose(void *instanceData,
			    Tcl_Interp *interp, int flags);
static Tcl_DriverGetHandleProc	ZipChannelGetFile;
static int		ZipChannelRead(void *instanceData, char *buf,
			    int toRead, int *errloc);
static Tcl_WideInt ZipChannelWideSeek(void *instanceData, Tcl_WideInt offset,
			    int mode, int *errloc);
static long long	ZipChannelWideSeek(void *instanceData,
			    long long offset, int mode, int *errloc);
static void		ZipChannelWatchChannel(void *instanceData,
			    int mask);
static int		ZipChannelWrite(void *instanceData,
			    const char *buf, int toWrite, int *errloc);

/*
 * Define the ZIP filesystem dispatch table.
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571







-
+







-
-
-
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    NULL, /* createDirectoryProc */
    NULL, /* removeDirectoryProc */
    NULL, /* deleteFileProc */
    NULL, /* copyFileProc */
    NULL, /* renameFileProc */
    NULL, /* copyDirectoryProc */
    NULL, /* lstatProc */
    (Tcl_FSLoadFileProc *)(void *)ZipFSLoadFile,
    (Tcl_FSLoadFileProc *) (void *) ZipFSLoadFile,
    NULL, /* getCwdProc */
    NULL, /* chdirProc */
};

/*
 * The channel type/driver definition used for ZIP archive members.
 */

static Tcl_ChannelType ZipChannelType = {
    "zip",		    /* Type name. */
static const Tcl_ChannelType zipChannelType = {
    "zip",
    TCL_CHANNEL_VERSION_5,
    NULL,	    /* Close channel, clean instance data */
    ZipChannelRead,	    /* Handle read request */
    ZipChannelWrite,	    /* Handle write request */
	NULL,	    /* Move location of access point, NULL'able */
    NULL,		    /* Set options, NULL'able */
    NULL,		    /* Get options, NULL'able */
    ZipChannelWatchChannel, /* Initialize notifier */
    ZipChannelGetFile,	    /* Get OS handle from the channel */
    ZipChannelClose,	    /* 2nd version of close channel, NULL'able */
    NULL,		    /* Set blocking mode for raw channel, NULL'able */
    NULL,		    /* Function to flush channel, NULL'able */
    NULL,		    /* Function to handle event, NULL'able */
    ZipChannelWideSeek,	/* Wide seek function, NULL'able */
    NULL,		    /* Thread action function, NULL'able */
    NULL,		    /* Truncate function, NULL'able */
    NULL,			/* Deprecated. */
    ZipChannelRead,
    ZipChannelWrite,
    NULL,			/* Deprecated. */
    NULL,			/* Set options proc. */
    NULL,			/* Get options proc. */
    ZipChannelWatchChannel,
    ZipChannelGetFile,
    ZipChannelClose,
    NULL,			/* Set blocking mode for raw channel. */
    NULL,			/* Function to flush channel. */
    NULL,			/* Function to handle bubbled events. */
    ZipChannelWideSeek,
    NULL,			/* Thread action function. */
    NULL,			/* Truncate function. */
};

/*
 *------------------------------------------------------------------------
 *
 * TclIsZipfsPath --
 *
 *    Checks if the passed path has a zipfs volume prefix.
 *
 * Results:
 *    0 if not a zipfs path
 *    else the length of the zipfs volume prefix
 *
 * Side effects:
 *    None.
 *
 *------------------------------------------------------------------------
 */
int
TclIsZipfsPath(
    const char *path)
{
#ifdef _WIN32
    return strncmp(path, ZIPFS_VOLUME, ZIPFS_VOLUME_LEN) ? 0 : ZIPFS_VOLUME_LEN;
#else
    int i;
    for (i = 0; i < ZIPFS_VOLUME_LEN; ++i) {
	if (path[i] != ZIPFS_VOLUME[i] &&
		(path[i] != '\\' || ZIPFS_VOLUME[i] != '/')) {
	    return 0;
	}
    }
    return ZIPFS_VOLUME_LEN;
#endif
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipReadInt, ZipReadShort, ZipWriteInt, ZipWriteShort --
 *
 *	Inline functions to read and write little-endian 16 and 32 bit
 *	integers from/to buffers representing parts of ZIP archives.
 *
 *	These take bufferStart and bufferEnd pointers, which are used to
 *	maintain a guarantee that out-of-bounds accesses don't happen when
 *	reading or writing critical directory structures.
 *
 *-------------------------------------------------------------------------
 */

static inline unsigned int
ZipReadInt(
    const unsigned char *bufferStart,
    const unsigned char *bufferEnd,
    const unsigned char *ptr)
{
    if (ptr < bufferStart || ptr + 4 > bufferEnd) {
	Tcl_Panic("out of bounds read(4): start=%p, end=%p, ptr=%p",
		bufferStart, bufferEnd, ptr);
    }
    return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) |
	    ((unsigned int)ptr[3] << 24);
}

static inline unsigned short
ZipReadShort(
    const unsigned char *bufferStart,
    const unsigned char *bufferEnd,
    const unsigned char *ptr)
{
    if (ptr < bufferStart || ptr + 2 > bufferEnd) {
	Tcl_Panic("out of bounds read(2): start=%p, end=%p, ptr=%p",
		bufferStart, bufferEnd, ptr);
    }
    return ptr[0] | (ptr[1] << 8);
}

static inline void
ZipWriteInt(
    const unsigned char *bufferStart,
    const unsigned char *bufferEnd,
    unsigned char *ptr,
    unsigned int value)
{
    if (ptr < bufferStart || ptr + 4 > bufferEnd) {
	Tcl_Panic("out of bounds write(4): start=%p, end=%p, ptr=%p",
		bufferStart, bufferEnd, ptr);
    }
    ptr[0] = value & 0xff;
    ptr[1] = (value >> 8) & 0xff;
    ptr[2] = (value >> 16) & 0xff;
    ptr[3] = (value >> 24) & 0xff;
}

static inline void
ZipWriteShort(
    const unsigned char *bufferStart,
    const unsigned char *bufferEnd,
    unsigned char *ptr,
    unsigned short value)
{
    if (ptr < bufferStart || ptr + 2 > bufferEnd) {
	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.
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
579
580
581
582
583
584
585

586
587
588
589
590
591
592
593
594
595
596
597
598

599
600
601
602
603
604
605
606
607
608
609
610
611

612
613
614
615
616
617
618
619







-
+












-
+












-
+








TCL_DECLARE_MUTEX(ZipFSMutex)

#if TCL_THREADS

static Tcl_Condition ZipFSCond;

static void
static inline void
ReadLock(void)
{
    Tcl_MutexLock(&ZipFSMutex);
    while (ZipFS.lock < 0) {
	ZipFS.waiters++;
	Tcl_ConditionWait(&ZipFSCond, &ZipFSMutex, NULL);
	ZipFS.waiters--;
    }
    ZipFS.lock++;
    Tcl_MutexUnlock(&ZipFSMutex);
}

static void
static inline void
WriteLock(void)
{
    Tcl_MutexLock(&ZipFSMutex);
    while (ZipFS.lock != 0) {
	ZipFS.waiters++;
	Tcl_ConditionWait(&ZipFSCond, &ZipFSMutex, NULL);
	ZipFS.waiters--;
    }
    ZipFS.lock = -1;
    Tcl_MutexUnlock(&ZipFSMutex);
}

static void
static inline void
Unlock(void)
{
    Tcl_MutexLock(&ZipFSMutex);
    if (ZipFS.lock > 0) {
	--ZipFS.lock;
    } else if (ZipFS.lock < 0) {
	ZipFS.lock = 0;
564
565
566
567
568
569
570
571

572
573
574
575

576
577
578
579
580
581
582
583
584
585
586
587
588

589







































590






























































591



















592
593




























































































































































































594
595
596

597
598
599
600

601
602

603
604
605
606
607
608
609





610

611

612

613
614
615

616
617
618
619
620
621

622
623
624
625

626
627
628
629
630
631
632
633


634
635
636
637
638
639
640
641
642
643
644

645
646

647
648
649
650
651

652
653

654
655
656
657




658
659
660
661


662
663
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
707
708
709
710



711
712
713


714
715


716
717
718
719
720
721
722
723
724
725

726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752



753
754
755
756
757
758
759
725
726
727
728
729
730
731

732
733
734
735

736
737
738
739
740
741
742
743
744
745
746
747
748

749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789

790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871


872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116



1117






1118



























1119
1120
1121
1122
1123
1124
1125
1126
1127
1128







-
+



-
+












-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+
-


-
+

-
+

-

-
-
-
-
+
+
+
+
+
-
+

+
-
+
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
+
-
-
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
+
+
+
+
-
-
+
-
-
-
+
+

-
+
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
+
+

-
+
+
-
-
-

-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+







 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
static inline size_t
CountSlashes(
    const char *string)
{
    int count = 0;
    size_t count = 0;
    const char *p = string;

    while (*p != '\0') {
	if (*p == '/') {
	    count++;
	}
	p++;
    }
    return count;
}

/*
 *-------------------------------------------------------------------------
 *------------------------------------------------------------------------
 *
 * IsCryptHeaderValid --
 *
 *    Computes the validity of the encryption header CRC for a ZipEntry.
 *
 * Results:
 *    Returns 1 if the header is valid else 0.
 *
 * Side effects:
 *    None.
 *
 *------------------------------------------------------------------------
 */
static int
IsCryptHeaderValid(
    ZipEntry *z,
    unsigned char cryptHeader[ZIP_CRYPT_HDR_LEN])
{
    /*
     * There are multiple possibilities. The last one or two bytes of the
     * encryption header should match the last one or two bytes of the
     * CRC of the file. Or the last byte of the encryption header should
     * be the high order byte of the file time. Depending on the archiver
     * and version, any of the might be in used. We follow libzip in checking
     * only one byte against both the crc and the time. Note that by design
     * the check generates high number of false positives in any case.
     * Also, in case a check is passed when it should not, the final CRC
     * calculation will (should) catch it. Only difference is it will be
     * reported as a corruption error instead of incorrect password.
     */
    int dosTime = ToDosTime(z->timestamp);
    if (cryptHeader[11] == (unsigned char)(dosTime >> 8)) {
	/* Infozip style - Tested with test-password.zip */
	return 1;
    }
    /* DOS time did not match, may be CRC does */
    if (z->crc32) {
	/* Pkware style - Tested with test-password2.zip */
	return (cryptHeader[11] == (unsigned char)(z->crc32 >> 24));
    }
 * CanonicalPath --

    /* No CRC, no way to verify. Assume valid */
    return 1;
}

/*
 *------------------------------------------------------------------------
 *
 * DecodeCryptHeader --
 *
 *    Decodes the crypt header and validates it.
 *
 * Results:
 *    TCL_OK on success, TCL_ERROR on failure.
 *
 * Side effects:
 *    On success, keys[] are updated. On failure, an error message is
 *    left in interp if not NULL.
 *
 *------------------------------------------------------------------------
 */
static int
DecodeCryptHeader(
    Tcl_Interp *interp,
    ZipEntry *z,
    unsigned long keys[3],	/* Updated on success. Must have been
				 * initialized by caller. */
    unsigned char cryptHeader[ZIP_CRYPT_HDR_LEN])
				/* From zip file content */
{
    int i;
    int ch;
    int len = z->zipFilePtr->passBuf[0] & 0xFF;
    char passBuf[260];

    for (i = 0; i < len; i++) {
	ch = z->zipFilePtr->passBuf[len - i];
	passBuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f];
    }
    passBuf[i] = '\0';
    init_keys(passBuf, keys, crc32tab);
    memset(passBuf, 0, sizeof(passBuf));
    unsigned char encheader[ZIP_CRYPT_HDR_LEN];
    memcpy(encheader, cryptHeader, ZIP_CRYPT_HDR_LEN);
    for (i = 0; i < ZIP_CRYPT_HDR_LEN; i++) {
	ch = cryptHeader[i];
	ch ^= decrypt_byte(keys, crc32tab);
	encheader[i] = ch;
	update_keys(keys, crc32tab, ch);
    }
    if (!IsCryptHeaderValid(z, encheader)) {
	ZIPFS_ERROR(interp, "invalid password");
	ZIPFS_ERROR_CODE(interp, "PASSWORD");
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
 * DecodeZipEntryText --
 *
 *	Given a sequence of bytes from an entry in a ZIP central directory,
 *	convert that into a Tcl string. This is complicated because we don't
 *	actually know what encoding is in use! So we try to use UTF-8, and if
 *	that goes wrong, we fall back to a user-specified encoding, or to an
 *	encoding we specify (Windows code page 437), or to ISO 8859-1 if
 *	absolutely nothing else works.
 *
 *	During Tcl startup, we skip the user-specified encoding and cp437, as
 *	we may well not have any loadable encodings yet. Tcl's own library
 *	files ought to be using ASCII filenames.
 *
 * Results:
 *	The decoded filename; the filename is owned by the argument DString.
 *
 * Side effects:
 *	Updates dstPtr.
 *
 *-------------------------------------------------------------------------
 */
 *	This function computes the canonical path from a directory and file
 *	name components into the specified Tcl_DString.

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().
     */

    encoding = NULL;
    if (ZipFS.fallbackEntryEncoding) {
	encoding = Tcl_GetEncoding(NULL, ZipFS.fallbackEntryEncoding);
    }
    if (!encoding) {
	encoding = Tcl_GetEncoding(NULL, ZIPFS_FALLBACK_ENCODING);
    }
    if (!encoding) {
	/*
	 * Fallback to internal encoding that always converts all bytes.
	 * Should only happen when a filename isn't UTF-8 and we've not got
	 * our encodings initialised for some reason.
	 */

	encoding = Tcl_GetEncoding(NULL, "iso8859-1");
    }

    char *converted = Tcl_ExternalToUtfDString(encoding,
	    (const char *) inputBytes, inputLength, dstPtr);
    Tcl_FreeEncoding(encoding);
    return converted;
}

/*
 *------------------------------------------------------------------------
 *
 * NormalizeMountPoint --
 *
 *    Converts the passed path into a normalized zipfs mount point
 *    of the form //zipfs:/some/path. On Windows any \ path separators
 *    are converted to /.
 *
 *    Mount points with a volume will raise an error unless the volume is
 *    zipfs root. Thus D:/foo is not a valid mount point.
 *
 *    Relative paths and absolute paths without a volume are mapped under
 *    the zipfs root.
 *
 *    The empty string is mapped to the zipfs root.
 *
 *    dsPtr is initialized by the function and must be cleared by caller
 *    on a successful return.
 *
 * Results:
 *    TCL_OK on success with normalized mount path in dsPtr
 *    TCL_ERROR on fail with error message in interp if not NULL
 *
 *------------------------------------------------------------------------
 */
static int
NormalizeMountPoint(
    Tcl_Interp *interp,
    const char *mountPath,
    Tcl_DString *dsPtr)		/* Must be initialized by caller! */
{
    const char *joiner[2];
    char *joinedPath;
    Tcl_Obj *unnormalizedObj;
    Tcl_Obj *normalizedObj;
    const char *normalizedPath;
    Tcl_Size normalizedLen;
    Tcl_DString dsJoin;

    /*
     * Several things need to happen here
     * - Absolute paths containing volumes (drive letter or UNC) raise error
     *   except of course if the volume is zipfs root
     * - \ -> / and // -> / conversions (except if UNC which is error)
     * - . and .. have to be dealt with
     * The first is explicitly checked, the others are dealt with a
     * combination file join and normalize. Easier than doing it ourselves
     * and not performance sensitive anyways.
     */

    joiner[0] = ZIPFS_VOLUME;
    joiner[1] = mountPath;
    Tcl_DStringInit(&dsJoin);
    joinedPath = Tcl_JoinPath(2, joiner, &dsJoin);

    /* Now joinedPath has all \ -> / and // -> / (except UNC) converted. */

    if (!strncmp(ZIPFS_VOLUME, joinedPath, ZIPFS_VOLUME_LEN)) {
	unnormalizedObj = Tcl_DStringToObj(&dsJoin);
    } else {
	if (joinedPath[0] != '/' || joinedPath[1] == '/') {
	    /* mount path was D:/x, D:x or //unc */
	    goto invalidMountPath;
	}
	unnormalizedObj = Tcl_ObjPrintf(ZIPFS_VOLUME "%s", joinedPath + 1);
    }
    Tcl_IncrRefCount(unnormalizedObj);
    normalizedObj = Tcl_FSGetNormalizedPath(interp, unnormalizedObj);
    if (normalizedObj == NULL) {
	Tcl_DecrRefCount(unnormalizedObj);
	goto errorReturn;
    }
    Tcl_IncrRefCount(normalizedObj); /* BEFORE DecrRefCount on unnormalizedObj */
    Tcl_DecrRefCount(unnormalizedObj);

    /* normalizedObj owned by Tcl!! Do NOT DecrRef without an IncrRef */
    normalizedPath = TclGetStringFromObj(normalizedObj, &normalizedLen);
    Tcl_DStringFree(&dsJoin);
    Tcl_DStringAppend(dsPtr, normalizedPath, normalizedLen);
    Tcl_DecrRefCount(normalizedObj);
    return TCL_OK;

invalidMountPath:
    if (interp) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"Invalid mount path \"%s\"", mountPath));
	ZIPFS_ERROR_CODE(interp, "MOUNT_PATH");
    }

errorReturn:
    Tcl_DStringFree(&dsJoin);
    return TCL_ERROR;
}

/*
 *------------------------------------------------------------------------
 *
 * MapPathToZipfs --
 *
 *    Maps a path as stored in a zip archive to its normalized location
 *    under a given zipfs mount point. Relative paths and Unix style
 *    absolute paths go directly under the mount point. Volume relative
 *    paths and absolute paths that have a volume (drive or UNC) are
 *    stripped of the volume before joining the mount point.
 *
 * Results:
 *	Returns the pointer to the canonical path contained in the specified
 *    Pointer to normalized path.
 *	Tcl_DString.
 *
 * Side effects:
 *	Modifies the specified Tcl_DString.
 *    Stores mapped path in dsPtr.
 *
 *-------------------------------------------------------------------------
 *------------------------------------------------------------------------
 */

static char *
CanonicalPath(
    const char *root,
    const char *tail,
    Tcl_DString *dsPtr,
MapPathToZipfs(
    Tcl_Interp *interp,
    const char *mountPath,	/* Must be fully normalized */
    const char *path,		/* Archive content path to map */
    Tcl_DString *dsPtr)		/* Must be initialized and cleared
    int inZipfs)
				 * by caller */
{
    const char *joiner[2];
    char *path;
    char *joinedPath;
    int i, j, c, isUNC = 0, isVfs = 0, n = 0;
    int haveZipfsPath = 1;

    Tcl_Obj *unnormalizedObj;
#ifdef _WIN32
    if (tail[0] != '\0' && strchr(drvletters, tail[0]) && tail[1] == ':') {
	tail += 2;
	haveZipfsPath = 0;
    }
    /* UNC style path */
    Tcl_Obj *normalizedObj;
    if (tail[0] == '\\') {
	root = "";
	++tail;
	haveZipfsPath = 0;
    const char *normalizedPath;
    }
    if (tail[0] == '\\') {
	root = "/";
	++tail;
	haveZipfsPath = 0;
    }
#endif /* _WIN32 */

    Tcl_Size normalizedLen;
    Tcl_DString dsJoin;
    if (haveZipfsPath) {
	/* UNC style path */
	if (root && strncmp(root, ZIPFS_VOLUME, ZIPFS_VOLUME_LEN) == 0) {
	    isVfs = 1;
	} else if (tail &&
		strncmp(tail, ZIPFS_VOLUME, ZIPFS_VOLUME_LEN) == 0) {
	    isVfs = 2;
	}
	if (isVfs != 1 && (root[0] == '/') && (root[1] == '/')) {
	    isUNC = 1;
	}

    }

    assert(TclIsZipfsPath(mountPath));
    if (isVfs != 2) {
	if (tail[0] == '/') {
	    if (isVfs != 1) {
		root = "";
	    }

	    ++tail;
	    isUNC = 0;
    joiner[0] = mountPath;
	}
	if (tail[0] == '/') {
	    if (isVfs != 1) {
		root = "/";
    joiner[1] = path;
#ifndef _WIN32
    /* On Unix C:/foo/bat is not treated as absolute by JoinPath so check ourself */
    if (path[0] && path[1] == ':') {
	    }
	    ++tail;
	    isUNC = 1;
	}
	joiner[1] += 2;
    }
    }
    i = strlen(root);
    j = strlen(tail);

#endif
    switch (isVfs) {
    case 1:
	if (i > ZIPFS_VOLUME_LEN) {
	    Tcl_DStringSetLength(dsPtr, i + j + 1);
	    path = Tcl_DStringValue(dsPtr);
    Tcl_DStringInit(&dsJoin);
	    memcpy(path, root, i);
	    path[i++] = '/';
	    memcpy(path + i, tail, j);
	} else {
	    Tcl_DStringSetLength(dsPtr, i + j);
	    path = Tcl_DStringValue(dsPtr);
    joinedPath = Tcl_JoinPath(2, joiner, &dsJoin);
	    memcpy(path, root, i);
	    memcpy(path + i, tail, j);
	}

	break;
    case 2:
	Tcl_DStringSetLength(dsPtr, j);
	path = Tcl_DStringValue(dsPtr);
	memcpy(path, tail, j);
	break;
    default:
	if (inZipfs) {
	    Tcl_DStringSetLength(dsPtr, i + j + ZIPFS_VOLUME_LEN);
	    path = Tcl_DStringValue(dsPtr);
    if (strncmp(ZIPFS_VOLUME, joinedPath, ZIPFS_VOLUME_LEN)) {
	/* path was not relative. Strip off the volume (e.g. UNC) */
	    memcpy(path, ZIPFS_VOLUME, ZIPFS_VOLUME_LEN);
	    memcpy(path + ZIPFS_VOLUME_LEN + i , tail, j);
	} else {
	    Tcl_DStringSetLength(dsPtr, i + j + 1);
	    path = Tcl_DStringValue(dsPtr);
	Tcl_Size numParts;
	const char **partsPtr;
	Tcl_SplitPath(path, &numParts, &partsPtr);
	Tcl_DStringFree(&dsJoin);
	    memcpy(path, root, i);
	    path[i++] = '/';
	partsPtr[0] = mountPath;
	    memcpy(path + i, tail, j);
	}
	break;
	(void)Tcl_JoinPath(numParts, partsPtr, &dsJoin);
	Tcl_Free(partsPtr);
    }

    unnormalizedObj = Tcl_DStringToObj(&dsJoin); /* Also resets dsJoin */
#ifdef _WIN32
    for (i = 0; path[i] != '\0'; i++) {
	if (path[i] == '\\') {
	    path[i] = '/';
	}
    }
#endif /* _WIN32 */

    if (inZipfs) {
    Tcl_IncrRefCount(unnormalizedObj);
    normalizedObj = Tcl_FSGetNormalizedPath(interp, unnormalizedObj);
    if (normalizedObj == NULL) {
	n = ZIPFS_VOLUME_LEN;
    } else {
	n = 0;
	/* Should not happen but continue... */
	normalizedObj = unnormalizedObj;
    }

    Tcl_IncrRefCount(normalizedObj); /* BEFORE DecrRefCount on unnormalizedObj */
    Tcl_DecrRefCount(unnormalizedObj);
    for (i = j = n; (c = path[i]) != '\0'; i++) {
	if (c == '/') {
	    int c2 = path[i + 1];

	    if (c2 == '\0' || c2 == '/') {
		continue;
	    }
	    if (c2 == '.') {
		int c3 = path[i + 2];

    /* normalizedObj owned by Tcl!! Do NOT DecrRef without an IncrRef */
		if ((c3 == '/') || (c3 == '\0')) {
		    i++;
		    continue;
		}
		if ((c3 == '.')
			&& ((path[i + 3] == '/') || (path[i + 3] == '\0'))) {
		    i += 2;
		    while ((j > 0) && (path[j - 1] != '/')) {
			j--;
		    }
		    if (j > isUNC) {
			--j;
			while ((j > 1 + isUNC) && (path[j - 2] == '/')) {
			    j--;
			}
		    }
		    continue;
		}
	    }
	}
	path[j++] = c;
    }
    if (j == 0) {
	path[j++] = '/';
    }
    path[j] = 0;
    Tcl_DStringSetLength(dsPtr, j);
    normalizedPath = TclGetStringFromObj(normalizedObj, &normalizedLen);
    Tcl_DStringAppend(dsPtr, normalizedPath, normalizedLen);
    Tcl_DecrRefCount(normalizedObj);
    return Tcl_DStringValue(dsPtr);
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSLookup --
768
769
770
771
772
773
774
775

776
777

778
779
780
781
782
783
784

785
786
787
788
789
790
791
792

793
794
795

796
797

798

799
800
801
802
803
804
805
806
807
808
809







































810
811
812
813











814
815
816


817




















818


819
820
821
822
823
824

























































825
826
827
828
829
830
831
1137
1138
1139
1140
1141
1142
1143

1144
1145

1146
1147
1148
1149
1150
1151
1152

1153
1154
1155
1156
1157
1158
1159
1160

1161
1162


1163
1164
1165
1166

1167
1168
1169
1170
1171
1172
1173
1174




1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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







-
+

-
+






-
+







-
+

-
-
+


+
-
+







-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+
+
+
+
+
+
+
+
+
+
+

-
-
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+





-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static ZipEntry *
static inline ZipEntry *
ZipFSLookup(
    char *filename)
    const char *filename)
{
    Tcl_HashEntry *hPtr;
    ZipEntry *z = NULL;

    hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, filename);
    if (hPtr) {
	z = (ZipEntry *)Tcl_GetHashValue(hPtr);
	z = (ZipEntry *) Tcl_GetHashValue(hPtr);
    }
    return z;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSLookupMount --
 * ZipFSLookupZip --
 *
 *	This function returns an indication if the given file name corresponds
 *	to a mounted ZIP archive file.
 *	This function gets the structure for a mounted ZIP archive.
 *
 * Results:
 *	Returns a pointer to the structure, or NULL if the file is ZIP file is
 *	Returns true, if the given file name is a mounted ZIP archive file.
 *	unknown/not mounted.
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

#ifdef NEVER_USED
static int
ZipFSLookupMount(
    char *filename)
static inline ZipFile *
ZipFSLookupZip(
    const char *mountPoint)
{
    Tcl_HashEntry *hPtr;
    ZipFile *zf = NULL;

    hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mountPoint);
    if (hPtr) {
	zf = (ZipFile *) Tcl_GetHashValue(hPtr);
    }
    return zf;
}

/*
 *------------------------------------------------------------------------
 *
 * ContainsMountPoint --
 *
 *    Check if there is a mount point anywhere under the specified path.
 *    Although the function will work for any path, for efficiency reasons
 *    it should be called only after checking ZipFSLookup does not find
 *    the path.
 *
 *    Caller must hold read lock before calling.
 *
 * Results:
 *    1 - there is at least one mount point under the path
 *    0 - otherwise
 *
 * Side effects:
 *    None.
 *
 *------------------------------------------------------------------------
 */
static int
ContainsMountPoint(
    const char *path,
    int pathLen)
{
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;

    if (ZipFS.zipHash.numEntries == 0) {
	return 0;
    }
    if (pathLen < 0) {
	pathLen = strlen(path);
    }

    /*
     * We are looking for the case where the path is //zipfs:/a/b
     * and there is a mount point //zipfs:/a/b/c/.. below it
     */
    for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
	   hPtr = Tcl_NextHashEntry(&search)) {
	ZipFile *zf = Tcl_GetHashValue(hPtr);
	    hPtr = Tcl_NextHashEntry(&search)) {
	ZipFile *zf = (ZipFile *) Tcl_GetHashValue(hPtr);

	if (zf->mountPointLen == 0) {
	    /*
	     * Enumerate the contents of the ZIP; it's mounted on the root.
	     * TODO - a holdover from androwish? Tcl does not allow mounting
	     * outside of the //zipfs:/ area.
	     */
	    ZipEntry *z;

	    for (z = zf->topEnts; z; z = z->tnext) {
		int lenz = (int) strlen(z->name);
		if ((lenz >= pathLen) &&
			(z->name[pathLen] == '/' || z->name[pathLen] == '\0') &&
			(strncmp(z->name, path, pathLen) == 0)) {
		    return 1;
		}
	    }
	} else if ((zf->mountPointLen >= pathLen) &&
		 (zf->mountPoint[pathLen] == '/' ||
		  zf->mountPoint[pathLen] == '\0' ||
		  pathLen == ZIPFS_VOLUME_LEN) &&
	if (strcmp(zf->mountPoint, filename) == 0) {
		 (strncmp(zf->mountPoint, path, pathLen) == 0)) {
	    /* Matched standard mount */
	    return 1;
	}
    }
    return 0;
}
#endif /* NEVER_USED */

/*
 *-------------------------------------------------------------------------
 *
 * AllocateZipFile, AllocateZipEntry, AllocateZipChannel --
 *
 *	Allocates the memory for a datastructure. Always ensures that it is
 *	zeroed out for safety.
 *
 * Returns:
 *	The allocated structure, or NULL if allocate fails.
 *
 * Side effects:
 *	The interpreter result may be written to on error. Which might fail
 *	(for ZipFile) in a low-memory situation. Always panics if ZipEntry
 *	allocation fails.
 *
 *-------------------------------------------------------------------------
 */

static inline ZipFile *
AllocateZipFile(
    Tcl_Interp *interp,
    size_t mountPointNameLength)
{
    size_t size = sizeof(ZipFile) + mountPointNameLength + 1;
    ZipFile *zf = (ZipFile *) Tcl_AttemptAlloc(size);

    if (!zf) {
	ZIPFS_MEM_ERROR(interp);
    } else {
	memset(zf, 0, size);
    }
    return zf;
}

static inline ZipEntry *
AllocateZipEntry(void)
{
    ZipEntry *z = (ZipEntry *) Tcl_Alloc(sizeof(ZipEntry));
    memset(z, 0, sizeof(ZipEntry));
    return z;
}

static inline ZipChannel *
AllocateZipChannel(
    Tcl_Interp *interp)
{
    ZipChannel *zc = (ZipChannel *) Tcl_AttemptAlloc(sizeof(ZipChannel));

    if (!zc) {
	ZIPFS_MEM_ERROR(interp);
    } else {
	memset(zc, 0, sizeof(ZipChannel));
    }
    return zc;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSCloseArchive --
 *
 *	This function closes a mounted ZIP archive file.
854
855
856
857
858
859
860




861
862
863
864
865
866
867
868
869
870
871
872

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
898
899
900
901



902
903
904
905
906
907
908
909
910
911
912
913




914






915
916
917
918




919
920
921

922
923

924
925
926






927
928
929
930
931
932
933
934
935
936
937




















938
939
940
941
942
943
944
945
946



947
948
949
950
951
952























953

954

955
956
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
1016
1017


1018
1019
1020
1021
1022
1023
1024
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
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
1387
1388

1389
1390
1391
1392
1393
1394
1395


1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408


1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419




1420
1421
1422
1423
1424
1425

1426
1427

1428
1429
1430

1431
1432
1433
1434
1435
1436
1437
1438
1439
1440







1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494

1495
1496
1497




1498
1499
1500
1501





1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515


1516
1517
1518
1519
1520
1521
1522
1523



1524
1525
1526


1527
1528

1529
1530



1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544


1545
1546


1547
1548
1549
1550
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







+
+
+
+











-
+








-
+











-
+






-
-
+
+
+










-
-
+
+
+
+

+
+
+
+
+
+
-
-
-
-
+
+
+
+


-
+

-
+


-
+
+
+
+
+
+




-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
-
-
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
-
+


-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-

+
+
+
+
+
+
+
-
-
-
+
+
+
-
-


-
+

-
-
-
+
+
+
+
+
+
+
+
+
+
+
+


-
-
+
+
-
-
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+

-
+
+

-
+



-

-
-
-
+















-
+
+







	    Tcl_Free(zf->ptrToFree);
	    zf->ptrToFree = NULL;
	}
	zf->data = NULL;
	return;
    }

    /*
     * Remove the memory mapping, if we have one.
     */

#ifdef _WIN32
    if (zf->data && !zf->ptrToFree) {
	UnmapViewOfFile(zf->data);
	zf->data = NULL;
    }
    if (zf->mountHandle != INVALID_HANDLE_VALUE) {
	CloseHandle(zf->mountHandle);
    }
#else /* !_WIN32 */
    if ((zf->data != MAP_FAILED) && !zf->ptrToFree) {
	munmap(zf->data, zf->length);
	zf->data = (unsigned char *)MAP_FAILED;
	zf->data = (unsigned char *) MAP_FAILED;
    }
#endif /* _WIN32 */

    if (zf->ptrToFree) {
	Tcl_Free(zf->ptrToFree);
	zf->ptrToFree = NULL;
    }
    if (zf->chan) {
	Tcl_CloseEx(interp, zf->chan, 0);
	Tcl_Close(interp, zf->chan);
	zf->chan = NULL;
    }
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSFindTOC --
 *
 *	This function takes a memory mapped zip file and indexes the contents.
 *	When "needZip" is zero an embedded ZIP archive in an executable file
 *	is accepted.
 *	is accepted. Note that we do not support ZIP64.
 *
 * Results:
 *	TCL_OK on success, TCL_ERROR otherwise with an error message placed
 *	into the given "interp" if it is not NULL.
 *
 * Side effects:
 *	The given ZipFile struct is filled with information about the ZIP
 *	archive file.
 *      The given ZipFile struct is filled with information about the ZIP
 *      archive file.  On error, ZipFSCloseArchive is called on zf but
 *      it is not freed.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSFindTOC(
    Tcl_Interp *interp,		/* Current interpreter. NULLable. */
    int needZip,
    ZipFile *zf)
{
    size_t i;
    unsigned char *p, *q;
    size_t i, minoff;
    const unsigned char *eocdPtr; /* End of Central Directory Record */
    const unsigned char *start = zf->data;
    const unsigned char *end = zf->data + zf->length;

    /*
     * Scan backwards from the end of the file for the signature. This is
     * necessary because ZIP archives aren't the only things that get tagged
     * on the end of executables; digital signatures can also go there.
     */

    p = zf->data + zf->length - ZIP_CENTRAL_END_LEN;
    while (p >= zf->data) {
	if (*p == (ZIP_CENTRAL_END_SIG & 0xFF)) {
	    if (ZipReadInt(p) == ZIP_CENTRAL_END_SIG) {
    eocdPtr = zf->data + zf->length - ZIP_CENTRAL_END_LEN;
    while (eocdPtr >= start) {
	if (*eocdPtr == (ZIP_CENTRAL_END_SIG & 0xFF)) {
	    if (ZipReadInt(start, end, eocdPtr) == ZIP_CENTRAL_END_SIG) {
		break;
	    }
	    p -= ZIP_SIG_LEN;
	    eocdPtr -= ZIP_SIG_LEN;
	} else {
	    --p;
	    --eocdPtr;
	}
    }
    if (p < zf->data) {
    if (eocdPtr < zf->data) {
	/*
	 * Didn't find it (or not enough space for a central directory!); not
	 * a ZIP archive. This might be OK or a problem.
	 */

	if (!needZip) {
	    zf->baseOffset = zf->passOffset = zf->length;
	    return TCL_OK;
	}
	ZIPFS_ERROR(interp, "wrong end signature");
	if (interp) {
	    Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "END_SIG", NULL);
	}
	goto error;
    }
    zf->numFiles = ZipReadShort(p + ZIP_CENTRAL_ENTS_OFFS);
	ZIPFS_ERROR(interp, "archive directory end signature not found");
	ZIPFS_ERROR_CODE(interp, "END_SIG");

  error:
	ZipFSCloseArchive(interp, zf);
	return TCL_ERROR;

    }

    /*
     * eocdPtr -> End of Central Directory (EOCD) record at this point.
     * Note this is not same as "end of Central Directory" :-) as EOCD
     * is a record/structure in the ZIP spec terminology
     */

    /*
     * How many files in the archive? If that's bogus, we're done here.
     */

    zf->numFiles = ZipReadShort(start, end, eocdPtr + ZIP_CENTRAL_ENTS_OFFS);
    if (zf->numFiles == 0) {
	if (!needZip) {
	    zf->baseOffset = zf->passOffset = zf->length;
	    return TCL_OK;
	}
	ZIPFS_ERROR(interp, "empty archive");
	if (interp) {
	    Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "EMPTY", NULL);
	}
	ZIPFS_ERROR_CODE(interp, "EMPTY");
	goto error;
    }
	goto error;
    }
    q = zf->data + ZipReadInt(p + ZIP_CENTRAL_DIRSTART_OFFS);
    p -= ZipReadInt(p + ZIP_CENTRAL_DIRSIZE_OFFS);
    if ((p < zf->data) || (p > zf->data + zf->length)
	    || (q < zf->data) || (q > zf->data + zf->length)) {

    /*
     * The Central Directory (CD) is a series of Central Directory File
     * Header (CDFH) records preceding the EOCD (but not necessarily
     * immediately preceding). cdirZipOffset is the offset into the
     * *archive* to the CD (first CDFH). The size of the CD is given by
     * cdirSize. NOTE: offset into archive does NOT mean offset into
     * (zf->data) as other data may precede the archive in the file.
     */
    ptrdiff_t eocdDataOffset = eocdPtr - zf->data;
    unsigned int cdirZipOffset = ZipReadInt(start, end, eocdPtr + ZIP_CENTRAL_DIRSTART_OFFS);
    unsigned int cdirSize = ZipReadInt(start, end, eocdPtr + ZIP_CENTRAL_DIRSIZE_OFFS);

    /*
     * As computed above,
     *    eocdDataOffset < zf->length.
     * In addition, the following consistency checks must be met
     * (1) cdirZipOffset <= eocdDataOffset (to prevent under flow in computation of (2))
     * (2) cdirZipOffset + cdirSize <= eocdDataOffset. Else the CD will be overlapping
     * the EOCD. Note this automatically means cdirZipOffset+cdirSize < zf->length.
     */
    if (!(cdirZipOffset <= (size_t)eocdDataOffset &&
	    cdirSize <= eocdDataOffset - cdirZipOffset)) {
	if (!needZip) {
	    /* Simply point to end od data */
	    zf->baseOffset = zf->passOffset = zf->length;
	    zf->directoryOffset = zf->baseOffset = zf->passOffset = zf->length;
	    return TCL_OK;
	}
	ZIPFS_ERROR(interp, "archive directory not found");
	if (interp) {
	    Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "NO_DIR", NULL);
	}
	ZIPFS_ERROR(interp, "archive directory truncated");
	ZIPFS_ERROR_CODE(interp, "NO_DIR");
	goto error;
    }
	goto error;
    }
    zf->baseOffset = zf->passOffset = p - q;
    zf->directoryOffset = p - zf->data;
    q = p;

    /*
     * Calculate the offset of the CD in the *data*. If there was no extra
     * "junk" preceding the archive, this would just be cdirZipOffset but
     * otherwise we have to account for it.
     */
    if (eocdDataOffset - cdirSize > cdirZipOffset) {
	zf->baseOffset = eocdDataOffset - cdirSize - cdirZipOffset;
    } else {
	zf->baseOffset = 0;
    }
    zf->passOffset = zf->baseOffset;
    zf->directoryOffset = cdirZipOffset + zf->baseOffset;
    zf->directorySize = cdirSize;
    for (i = 0; i < zf->numFiles; i++) {
	int pathlen, comlen, extra;

    /*
     * Read the central directory.
     */
    const unsigned char *const cdirStart = eocdPtr - cdirSize; /* Start of CD */
    const unsigned char *dirEntry;
    minoff = zf->length;
    for (dirEntry = cdirStart, i = 0; i < zf->numFiles; i++) {
	if (q + ZIP_CENTRAL_HEADER_LEN > zf->data + zf->length) {
	    ZIPFS_ERROR(interp, "wrong header length");
	    if (interp) {
	if ((dirEntry-cdirStart) + ZIP_CENTRAL_HEADER_LEN > (ptrdiff_t)zf->directorySize) {
	    ZIPFS_ERROR(interp, "truncated directory");
	    ZIPFS_ERROR_CODE(interp, "TRUNC_DIR");
		Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "HDR_LEN", NULL);
	    }
	    goto error;
	}
	if (ZipReadInt(q) != ZIP_CENTRAL_HEADER_SIG) {
	if (ZipReadInt(start, end, dirEntry) != ZIP_CENTRAL_HEADER_SIG) {
	    ZIPFS_ERROR(interp, "wrong header signature");
	    if (interp) {
		Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "HDR_SIG", NULL);
	    }
	    ZIPFS_ERROR_CODE(interp, "HDR_SIG");
	    goto error;
	}
	int pathlen = ZipReadShort(start, end, dirEntry + ZIP_CENTRAL_PATHLEN_OFFS);
	int comlen = ZipReadShort(start, end, dirEntry + ZIP_CENTRAL_FCOMMENTLEN_OFFS);
	int extra = ZipReadShort(start, end, dirEntry + ZIP_CENTRAL_EXTRALEN_OFFS);
	size_t localhdr_off = ZipReadInt(start, end, dirEntry + ZIP_CENTRAL_LOCALHDR_OFFS);
	const unsigned char *localP = zf->data + zf->baseOffset + localhdr_off;
	if (localP > (cdirStart - ZIP_LOCAL_HEADER_LEN) ||
		ZipReadInt(start, end, localP) != ZIP_LOCAL_HEADER_SIG) {
	    ZIPFS_ERROR(interp, "Failed to find local header");
	    ZIPFS_ERROR_CODE(interp, "LCL_HDR");
	    goto error;
	}
	pathlen = ZipReadShort(q + ZIP_CENTRAL_PATHLEN_OFFS);
	comlen = ZipReadShort(q + ZIP_CENTRAL_FCOMMENTLEN_OFFS);
	if (localhdr_off < minoff) {
	    minoff = localhdr_off;
	extra = ZipReadShort(q + ZIP_CENTRAL_EXTRALEN_OFFS);
	q += pathlen + comlen + extra + ZIP_CENTRAL_HEADER_LEN;
	}
	dirEntry += pathlen + comlen + extra + ZIP_CENTRAL_HEADER_LEN;
    }
    if ((dirEntry-cdirStart) < (ptrdiff_t) zf->directorySize) {
	/* file count and dir size do not match */
	ZIPFS_ERROR(interp, "short file count");
	ZIPFS_ERROR_CODE(interp, "FILE_COUNT");
	goto error;
    }

    zf->passOffset = minoff + zf->baseOffset;

    /*
     * If there's also an encoded password, extract that too (but don't decode
     * yet).
     * TODO - is this even part of the ZIP "standard". The idea of storing
     * a password with the archive seems absurd, encoded or not.
     */

    q = zf->data + zf->baseOffset;
    if ((zf->baseOffset >= 6) && (ZipReadInt(q - 4) == ZIP_PASSWORD_END_SIG)) {
    unsigned char *q = zf->data + zf->passOffset;
    if ((zf->passOffset >= 6) && (start < q-4) &&
	    (ZipReadInt(start, end, q - 4) == ZIP_PASSWORD_END_SIG)) {
	const unsigned char *passPtr;

	i = q[-5];
	if (q - 5 - i > zf->data) {
	passPtr = q - 5 - i;
	if (passPtr >= start && passPtr + i < end) {
	    zf->passBuf[0] = i;
	    memcpy(zf->passBuf + 1, q - 5 - i, i);
	    memcpy(zf->passBuf + 1, passPtr, i);
	    zf->passOffset -= i ? (5 + i) : 0;
	}
    }
    return TCL_OK;

  error:
    ZipFSCloseArchive(interp, zf);
    return TCL_ERROR;
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSOpenArchive --
 *
 *	This function opens a ZIP archive file for reading. An attempt is made
 *	to memory map that file. Otherwise it is read into an allocated memory
 *	buffer. The ZIP archive header is verified and must be valid for the
 *	function to succeed. When "needZip" is zero an embedded ZIP archive in
 *	an executable file is accepted.
 *
 * Results:
 *	TCL_OK on success, TCL_ERROR otherwise with an error message placed
 *	into the given "interp" if it is not NULL.
 *	into the given "interp" if it is not NULL. On error, ZipFSCloseArchive
 *      is called on zf but it is not freed.
 *
 * Side effects:
 *	ZIP archive is memory mapped or read into allocated memory, the given
 *	ZipFile struct is filled with information about the ZIP archive file.
 *
 *-------------------------------------------------------------------------
 */
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

1116
1117
1118
1119
1120
1121

1122
1123
1124
1125
1126
1127
1128





1129
1130
1131
1132
1133
1134
1135
1136







1137
1138
1139


















































































































1140
1141
1142
1143

1144
1145
1146

1147
1148
1149
1150
1151
1152
1153
1154
1155


1156
1157
1158
1159
1160
1161
1162



1163
1164
1165

1166




1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177



1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189

1190
1191



1192
1193
1194






1195
1196

1197
1198

1199
1200
1201
1202

1203
1204
1205


1206
1207
1208



1209
1210
1211
1212
1213
1214
1215
1216

1217
1218


1219
1220


1221
1222
1223
1224

1225
1226

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
1354



1355
1356
1357




1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
















1398
1399
1400
1401




1402
1403

1404
1405

1406
1407

1408
1409
1410
1411
1412
1413
1414
1415







1416
1417
1418
1419
1420
1421
1422

1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832

1833
1834
1835

1836
1837
1838
1839
1840
1841
1842
1843


1844
1845
1846
1847
1848
1849



1850
1851
1852
1853
1854

1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868



1869
1870
1871



1872
1873
1874
1875


1876


1877
1878
1879
1880
1881
1882



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
1958
1959
1960
1961



1962
1963
1964
1965

1966

1967
1968
1969
1970
1971
1972
1973
1974
1975


1976
1977
1978
1979

1980
1981


1982
1983
1984

1985
1986
1987
1988


1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009

2010

2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028


2029
2030


2031
2032
2033
2034


2035
2036
2037
2038
2039



2040
2041
2042
2043


2044
2045
2046
2047
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
2095
2096
2097
2098
2099




2100
2101
2102
2103


2104


2105


2106








2107
2108
2109
2110
2111
2112
2113

2114
2115
2116
2117
2118
2119
2120
2121
2122
2123

2124
2125
2126
2127
2128
2129
2130







-
+






+
+
+
+
+




+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+

-
+



+
+
-
-
+
+

-
+
-
-






-
+

-
-
+
-
-







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-


+
+
+
+
+








+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+


-
+







-
-
+
+




-
-
-
+
+
+


-
+

+
+
+
+








-
-
-
+
+
+
-
-
-




-
-

-
-
+


+
+
+
-
-
-
+
+
+
+
+
+
-
-
+
-
-
+



-
+

-
-
+
+


-
+
+
+


-
-
-
-
-
-
+
-
-
+
+
-
-
+
+
-
-
-
-
+
-

+

-
+

-
+
-
-











+



-
+


-

+


-

-
-
-

-
-
+
+
+
+
+
+
+







+
+





-
-
-
+
+
+

-
+
-









-
-
+
+


-
+

-
-
+
+

-
+



-
-
+
+



+















-
+
-
















+

-
-
+
+
-
-

+


-
-
+
+
+


-
-
-
+
+
+

-
-
+
+
+
+

-
-
-
+
+
+

-
-
+
+
+
+


-




+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
+
-
-
+
-
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-






+



-








    zf->nameLength = 0;
    zf->isMemBuffer = 0;
#ifdef _WIN32
    zf->data = NULL;
    zf->mountHandle = INVALID_HANDLE_VALUE;
#else /* !_WIN32 */
    zf->data = (unsigned char *)MAP_FAILED;
    zf->data = (unsigned char *) MAP_FAILED;
#endif /* _WIN32 */
    zf->length = 0;
    zf->numFiles = 0;
    zf->baseOffset = zf->passOffset = 0;
    zf->ptrToFree = NULL;
    zf->passBuf[0] = 0;

    /*
     * Actually open the file.
     */

    zf->chan = Tcl_OpenFileChannel(interp, zipname, "rb", 0);
    if (!zf->chan) {
	return TCL_ERROR;
    }

    /*
     * See if we can get the OS handle. If we can, we can use that to memory
     * map the file, which is nice and efficient. However, it totally depends
     * on the filename pointing to a real regular OS file.
     *
     * Opening real filesystem entities that are not files will lead to an
     * error.
     */

    if (Tcl_GetChannelHandle(zf->chan, TCL_READABLE, &handle) != TCL_OK) {
    if (Tcl_GetChannelHandle(zf->chan, TCL_READABLE, &handle) == TCL_OK) {
	if (ZipMapArchive(interp, zf, handle) != TCL_OK) {
	    goto error;
	}
    } else {
	/*
	 * Not an OS file, but rather something in a Tcl VFS. Must copy into
	 * memory.
	 */

	zf->length = Tcl_Seek(zf->chan, 0, SEEK_END);
	if (zf->length == TCL_IO_FAILURE) {
	if (zf->length == (size_t)TCL_INDEX_NONE) {
	    ZIPFS_POSIX_ERROR(interp, "seek error");
	    goto error;
	}
	/* What's the magic about 64 * 1024 * 1024 ? */
	if ((zf->length <= ZIP_CENTRAL_END_LEN) ||
	if ((zf->length - ZIP_CENTRAL_END_LEN)
		> (64 * 1024 * 1024 - ZIP_CENTRAL_END_LEN)) {
		(zf->length - ZIP_CENTRAL_END_LEN) >
			(64 * 1024 * 1024 - ZIP_CENTRAL_END_LEN)) {
	    ZIPFS_ERROR(interp, "illegal file size");
	    if (interp) {
	    ZIPFS_ERROR_CODE(interp, "FILE_SIZE");
		Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "FILE_SIZE", NULL);
	    }
	    goto error;
	}
	if (Tcl_Seek(zf->chan, 0, SEEK_SET) == -1) {
	    ZIPFS_POSIX_ERROR(interp, "seek error");
	    goto error;
	}
	zf->ptrToFree = zf->data = (unsigned char *)Tcl_AttemptAlloc(zf->length);
	zf->ptrToFree = zf->data = (unsigned char *) Tcl_AttemptAlloc(zf->length);
	if (!zf->ptrToFree) {
	    ZIPFS_ERROR(interp, "out of memory");
	    if (interp) {
	    ZIPFS_MEM_ERROR(interp);
		Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL);
	    }
	    goto error;
	}
	i = Tcl_Read(zf->chan, (char *) zf->data, zf->length);
	if (i != zf->length) {
	    ZIPFS_POSIX_ERROR(interp, "file read error");
	    goto error;
	}
	Tcl_CloseEx(interp, zf->chan, 0);
	zf->chan = NULL;
    } else {
#ifdef _WIN32
	int readSuccessful;
#   ifdef _WIN64
	i = GetFileSizeEx((HANDLE) handle, (PLARGE_INTEGER) &zf->length);
	readSuccessful = (i != 0);
#   else /* !_WIN64 */
	zf->length = GetFileSize((HANDLE) handle, 0);
	readSuccessful = (zf->length != (size_t) INVALID_FILE_SIZE);
#   endif /* _WIN64 */
	if (!readSuccessful || (zf->length < ZIP_CENTRAL_END_LEN)) {
	    ZIPFS_POSIX_ERROR(interp, "invalid file size");
	    goto error;
	}
    }
	zf->mountHandle = CreateFileMappingW((HANDLE) handle, 0, PAGE_READONLY,
		0, zf->length, 0);
	if (zf->mountHandle == INVALID_HANDLE_VALUE) {
	    ZIPFS_POSIX_ERROR(interp, "file mapping failed");
    /*
     * Close the Tcl channel. If the file was mapped, the mapping is
	    goto error;
	}
	zf->data = (unsigned char *)MapViewOfFile(zf->mountHandle, FILE_MAP_READ, 0, 0,
		zf->length);
	if (!zf->data) {
	    ZIPFS_POSIX_ERROR(interp, "file mapping failed");
	    goto error;
	}
#else /* !_WIN32 */
     * unaffected. It is important to close the channel otherwise there is a
     * potential chicken and egg issue at finalization time as the channels
     * are closed before the file systems are dismounted.
     */
	zf->length = lseek(PTR2INT(handle), 0, SEEK_END);
	if (zf->length == TCL_IO_FAILURE || zf->length < ZIP_CENTRAL_END_LEN) {
	    ZIPFS_POSIX_ERROR(interp, "invalid file size");
    Tcl_Close(interp, zf->chan);
	    goto error;
	}
	lseek(PTR2INT(handle), 0, SEEK_SET);
	zf->data = (unsigned char *) mmap(0, zf->length, PROT_READ,
		MAP_FILE | MAP_PRIVATE, PTR2INT(handle), 0);
	if (zf->data == MAP_FAILED) {
    zf->chan = NULL;
	    ZIPFS_POSIX_ERROR(interp, "file mapping failed");
	    goto error;
	}
#endif /* _WIN32 */
    }
    return ZipFSFindTOC(interp, needZip, zf);

    /*
     * Handle errors by closing the archive. This includes closing the channel
     * handle for the archive file.
     */

  error:
    ZipFSCloseArchive(interp, zf);
    return TCL_ERROR;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipMapArchive --
 *
 *	Wrapper around the platform-specific parts of mmap() (and Windows's
 *	equivalent) because it's not part of the standard channel API.
 *
 *-------------------------------------------------------------------------
 */
 * ZipFSRootNode --
 *
 *	This function generates the root node for a ZIPFS filesystem.

static int
ZipMapArchive(
    Tcl_Interp *interp,		/* Interpreter for error reporting. */
    ZipFile *zf,		/* The archive descriptor structure. */
    void *handle)		/* The OS handle to the open archive. */
{
#ifdef _WIN32
    HANDLE hFile = (HANDLE) handle;
    int readSuccessful;

    /*
     * Determine the file size.
     */

    readSuccessful = GetFileSizeEx(hFile, (PLARGE_INTEGER) &zf->length) != 0;
    if (!readSuccessful) {
	Tcl_WinConvertError(GetLastError());
	ZIPFS_POSIX_ERROR(interp, "failed to retrieve file size");
	return TCL_ERROR;
    }
    if (zf->length < ZIP_CENTRAL_END_LEN) {
	Tcl_SetErrno(EINVAL);
	ZIPFS_POSIX_ERROR(interp, "truncated file");
	return TCL_ERROR;
    }
    if (zf->length > TCL_SIZE_MAX) {
	Tcl_SetErrno(EFBIG);
	ZIPFS_POSIX_ERROR(interp, "zip archive too big");
	return TCL_ERROR;
    }

    /*
     * Map the file.
     */

    zf->mountHandle = CreateFileMappingW(hFile, 0, PAGE_READONLY, 0,
	    zf->length, 0);
    if (zf->mountHandle == INVALID_HANDLE_VALUE) {
	Tcl_WinConvertError(GetLastError());
	ZIPFS_POSIX_ERROR(interp, "file mapping failed");
	return TCL_ERROR;
    }
    zf->data = (unsigned char *)
	    MapViewOfFile(zf->mountHandle, FILE_MAP_READ, 0, 0, zf->length);
    if (!zf->data) {
	Tcl_WinConvertError(GetLastError());
	ZIPFS_POSIX_ERROR(interp, "file mapping failed");
	return TCL_ERROR;
    }
#else /* !_WIN32 */
    int fd = PTR2INT(handle);

    /*
     * Determine the file size.
     */

    zf->length = lseek(fd, 0, SEEK_END);
    if (zf->length == (size_t)-1) {
	ZIPFS_POSIX_ERROR(interp, "failed to retrieve file size");
	return TCL_ERROR;
    }
    if (zf->length < ZIP_CENTRAL_END_LEN) {
	Tcl_SetErrno(EINVAL);
	ZIPFS_POSIX_ERROR(interp, "truncated file");
	return TCL_ERROR;
    }
    lseek(fd, 0, SEEK_SET);

    zf->data = (unsigned char *)
	    mmap(0, zf->length, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
    if (zf->data == MAP_FAILED) {
	ZIPFS_POSIX_ERROR(interp, "file mapping failed");
	return TCL_ERROR;
    }
#endif /* _WIN32 */
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
 * IsPasswordValid --
 *
 *	Basic test for whether a passowrd is valid. If the test fails, sets an
 *	error message in the interpreter.
 *
 * Returns:
 *	TCL_OK if the test passes, TCL_ERROR if it fails.
 *
 *-------------------------------------------------------------------------
 */

static inline int
IsPasswordValid(
    Tcl_Interp *interp,
    const char *passwd,
    size_t pwlen)
{
    if ((pwlen > 255) || strchr(passwd, 0xff)) {
	ZIPFS_ERROR(interp, "illegal password");
	ZIPFS_ERROR_CODE(interp, "BAD_PASS");
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSCatalogFilesystem --
 *
 *	This function generates the root node for a ZIPFS filesystem by
 *	reading the ZIP's central directory.
 *
 * Results:
 *	TCL_OK on success, TCL_ERROR otherwise with an error message placed
 *	into the given "interp" if it is not NULL.
 *	into the given "interp" if it is not NULL. On error, frees zf!!
 *
 * Side effects:
 *	...
 *	Will acquire and release the write lock.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSCatalogFilesystem(
    Tcl_Interp *interp,		/* Current interpreter. NULLable. */
    ZipFile *zf0,
    const char *mountPoint,	/* Mount point path. */
    ZipFile *zf,		/* Temporary buffer hold archive descriptors */
    const char *mountPoint,	/* Mount point path. Must be fully normalized */
    const char *passwd,		/* Password for opening the ZIP, or NULL if
				 * the ZIP is unprotected. */
    const char *zipname)	/* Path to ZIP file to build a catalog of. */
{
    int pwlen, isNew;
    size_t i;
    ZipFile *zf;
    int isNew;
    size_t i, pwlen;
    ZipFile *zf0;
    ZipEntry *z;
    Tcl_HashEntry *hPtr;
    Tcl_DString ds, dsm, fpBuf;
    Tcl_DString ds, fpBuf;
    unsigned char *q;

    assert(TclIsZipfsPath(mountPoint)); /* Caller should have normalized */

    Tcl_DStringInit(&ds);

    /*
     * Basic verification of the password for sanity.
     */

    pwlen = 0;
    if (passwd) {
	pwlen = strlen(passwd);
	if ((pwlen > 255) || strchr(passwd, 0xff)) {
	    if (interp) {
		Tcl_SetObjResult(interp,
	if (IsPasswordValid(interp, passwd, pwlen) != TCL_OK) {
	    ZipFSCloseArchive(interp, zf);
	    Tcl_Free(zf);
			Tcl_NewStringObj("illegal password", -1));
		Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "BAD_PASS", NULL);
	    }
	    return TCL_ERROR;
	}
    }

    WriteLock();

    /*
     * Mount point sometimes is a relative or otherwise denormalized path.
     * But an absolute name is needed as mount point here.
     * Validate the TOC data. If that's bad, things fall apart.
     */

    if (zf->baseOffset >= zf->length || zf->passOffset >= zf->length ||
	    zf->directoryOffset >= zf->length) {
	ZIPFS_ERROR(interp, "bad zip data");
    Tcl_DStringInit(&ds);
    Tcl_DStringInit(&dsm);
    if (strcmp(mountPoint, "/") == 0) {
	ZIPFS_ERROR_CODE(interp, "BAD_ZIP");
	ZipFSCloseArchive(interp, zf);
	Tcl_Free(zf);
	return TCL_ERROR;
    }

	mountPoint = "";
    } else {
    WriteLock();
	mountPoint = CanonicalPath("", mountPoint, &dsm, 1);
    }

    hPtr = Tcl_CreateHashEntry(&ZipFS.zipHash, mountPoint, &isNew);
    if (!isNew) {
	if (interp) {
	    zf = (ZipFile *)Tcl_GetHashValue(hPtr);
	    zf0 = (ZipFile *) Tcl_GetHashValue(hPtr);
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "%s is already mounted on %s", zf->name, mountPoint));
	    Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "MOUNTED", NULL);
		    "%s is already mounted on %s", zf0->name, mountPoint));
	    ZIPFS_ERROR_CODE(interp, "MOUNTED");
	}
	Unlock();
	ZipFSCloseArchive(interp, zf0);
	ZipFSCloseArchive(interp, zf);
	Tcl_DStringFree(&ds);
	Tcl_Free(zf);
	return TCL_ERROR;
    }
    zf = (ZipFile *)Tcl_AttemptAlloc(sizeof(ZipFile) + strlen(mountPoint) + 1);
    if (!zf) {
	if (interp) {
	    Tcl_AppendResult(interp, "out of memory", (char *) NULL);
	    Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL);
	}

	Unlock();
	ZipFSCloseArchive(interp, zf0);
    /*
     * Convert to a real archive descriptor.
	return TCL_ERROR;
    }
     */

    Unlock();

    *zf = *zf0;
    zf->mountPoint = (char *)Tcl_GetHashKey(&ZipFS.zipHash, hPtr);
    zf->mountPoint = (char *) Tcl_GetHashKey(&ZipFS.zipHash, hPtr);
    Tcl_CreateExitHandler(ZipfsExitHandler, zf);
    zf->mountPointLen = strlen(zf->mountPoint);

    zf->nameLength = strlen(zipname);
    zf->name = (char *)Tcl_Alloc(zf->nameLength + 1);
    zf->name = (char *) Tcl_Alloc(zf->nameLength + 1);
    memcpy(zf->name, zipname, zf->nameLength + 1);
    zf->entries = NULL;

    zf->topEnts = NULL;
    zf->numOpen = 0;
    Tcl_SetHashValue(hPtr, zf);
    if ((zf->passBuf[0] == 0) && pwlen) {
	int k = 0;

	zf->passBuf[k++] = pwlen;
	for (i = pwlen; i-- > 0 ;) {
	    zf->passBuf[k++] = (passwd[i] & 0x0f)
		    | pwrot[(passwd[i] >> 4) & 0x0f];
	}
	zf->passBuf[k] = '\0';
    }
    /* TODO - is this test necessary? When will mountPoint[0] be \0 ? */
    if (mountPoint[0] != '\0') {
	hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, mountPoint, &isNew);
	if (isNew) {
	    z = (ZipEntry *)Tcl_Alloc(sizeof(ZipEntry));
	    z = AllocateZipEntry();
	    Tcl_SetHashValue(hPtr, z);

	    z->tnext = NULL;
	    z->depth = CountSlashes(mountPoint);
	    assert(z->depth >= ZIPFS_ROOTDIR_DEPTH);
	    z->zipFilePtr = zf;
	    z->isDirectory = (zf->baseOffset == 0) ? 1 : -1; /* root marker */
	    z->isEncrypted = 0;
	    z->offset = zf->baseOffset;
	    z->crc32 = 0;
	    z->timestamp = 0;
	    z->numBytes = z->numCompressedBytes = 0;
	    z->compressMethod = ZIP_COMPMETH_STORED;
	    z->data = NULL;
	    z->name = (char *)Tcl_GetHashKey(&ZipFS.fileHash, hPtr);
	    z->name = (char *) Tcl_GetHashKey(&ZipFS.fileHash, hPtr);
	    if (!strcmp(z->name, ZIPFS_VOLUME)) {
		z->flags |= ZE_F_VOLUME; /* Mark as root volume */
	    }
	    Tcl_Time t;
	    Tcl_GetTime(&t);
	    z->timestamp = t.sec;
	    z->next = zf->entries;
	    zf->entries = z;
	}
    }
    q = zf->data + zf->directoryOffset;
    Tcl_DStringInit(&fpBuf);
    for (i = 0; i < zf->numFiles; i++) {
	const unsigned char *start = zf->data;
	const unsigned char *end = zf->data + zf->length;
	int extra, isdir = 0, dosTime, dosDate, nbcompr;
	size_t offs, pathlen, comlen;
	unsigned char *lq, *gq = NULL;
	char *fullpath, *path;

	pathlen = ZipReadShort(q + ZIP_CENTRAL_PATHLEN_OFFS);
	comlen = ZipReadShort(q + ZIP_CENTRAL_FCOMMENTLEN_OFFS);
	extra = ZipReadShort(q + ZIP_CENTRAL_EXTRALEN_OFFS);
	pathlen = ZipReadShort(start, end, q + ZIP_CENTRAL_PATHLEN_OFFS);
	comlen = ZipReadShort(start, end, q + ZIP_CENTRAL_FCOMMENTLEN_OFFS);
	extra = ZipReadShort(start, end, q + ZIP_CENTRAL_EXTRALEN_OFFS);
	Tcl_DStringSetLength(&ds, 0);
	Tcl_DStringAppend(&ds, (char *) q + ZIP_CENTRAL_HEADER_LEN, pathlen);
	path = DecodeZipEntryText(q + ZIP_CENTRAL_HEADER_LEN, pathlen, &ds);
	path = Tcl_DStringValue(&ds);
	if ((pathlen > 0) && (path[pathlen - 1] == '/')) {
	    Tcl_DStringSetLength(&ds, pathlen - 1);
	    path = Tcl_DStringValue(&ds);
	    isdir = 1;
	}
	if ((strcmp(path, ".") == 0) || (strcmp(path, "..") == 0)) {
	    goto nextent;
	}
	lq = zf->data + zf->baseOffset
		+ ZipReadInt(q + ZIP_CENTRAL_LOCALHDR_OFFS);
	if ((lq < zf->data) || (lq > zf->data + zf->length)) {
		+ ZipReadInt(start, end, q + ZIP_CENTRAL_LOCALHDR_OFFS);
	if ((lq < start) || (lq + ZIP_LOCAL_HEADER_LEN > end)) {
	    goto nextent;
	}
	nbcompr = ZipReadInt(lq + ZIP_LOCAL_COMPLEN_OFFS);
	nbcompr = ZipReadInt(start, end, lq + ZIP_LOCAL_COMPLEN_OFFS);
	if (!isdir && (nbcompr == 0)
		&& (ZipReadInt(lq + ZIP_LOCAL_UNCOMPLEN_OFFS) == 0)
		&& (ZipReadInt(lq + ZIP_LOCAL_CRC32_OFFS) == 0)) {
		&& (ZipReadInt(start, end, lq + ZIP_LOCAL_UNCOMPLEN_OFFS) == 0)
		&& (ZipReadInt(start, end, lq + ZIP_LOCAL_CRC32_OFFS) == 0)) {
	    gq = q;
	    nbcompr = ZipReadInt(gq + ZIP_CENTRAL_COMPLEN_OFFS);
	    nbcompr = ZipReadInt(start, end, gq + ZIP_CENTRAL_COMPLEN_OFFS);
	}
	offs = (lq - zf->data)
		+ ZIP_LOCAL_HEADER_LEN
		+ ZipReadShort(lq + ZIP_LOCAL_PATHLEN_OFFS)
		+ ZipReadShort(lq + ZIP_LOCAL_EXTRALEN_OFFS);
		+ ZipReadShort(start, end, lq + ZIP_LOCAL_PATHLEN_OFFS)
		+ ZipReadShort(start, end, lq + ZIP_LOCAL_EXTRALEN_OFFS);
	if (offs + nbcompr > zf->length) {
	    goto nextent;
	}

	if (!isdir && (mountPoint[0] == '\0') && !CountSlashes(path)) {
#ifdef ANDROID
	    /*
	     * When mounting the ZIP archive on the root directory try to
	     * remap top level regular files of the archive to
	     * /assets/.root/... since this directory should not be in a valid
	     * APK due to the leading dot in the file name component. This
	     * trick should make the files AndroidManifest.xml,
	     * resources.arsc, and classes.dex visible to Tcl.
	     */
	    Tcl_DString ds2;

	    Tcl_DStringInit(&ds2);
	    Tcl_DStringAppend(&ds2, "assets/.root/", -1);
	    Tcl_DStringAppend(&ds2, path, -1);
	    hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, Tcl_DStringValue(&ds2));
	    if (ZipFSLookup(Tcl_DStringValue(&ds2))) {
	    if (hPtr) {
		/* should not happen but skip it anyway */
		Tcl_DStringFree(&ds2);
		goto nextent;
	    }
	    Tcl_DStringSetLength(&ds, 0);
	    Tcl_DStringAppend(&ds, Tcl_DStringValue(&ds2),
		    Tcl_DStringLength(&ds2));
	    path = Tcl_DStringValue(&ds);
	    Tcl_DStringFree(&ds2);
#else /* !ANDROID */
	    /*
	     * Regular files skipped when mounting on root.
	     */
	    goto nextent;
#endif /* ANDROID */
	}

	Tcl_DStringSetLength(&fpBuf, 0);
	fullpath = CanonicalPath(mountPoint, path, &fpBuf, 1);
	z = (ZipEntry *)Tcl_Alloc(sizeof(ZipEntry));
	fullpath = MapPathToZipfs(interp, mountPoint, path, &fpBuf);
	z = AllocateZipEntry();
	z->name = NULL;
	z->tnext = NULL;
	z->depth = CountSlashes(fullpath);
	assert(z->depth >= ZIPFS_ROOTDIR_DEPTH);
	z->zipFilePtr = zf;
	z->isDirectory = isdir;
	z->isEncrypted = (ZipReadShort(lq + ZIP_LOCAL_FLAGS_OFFS) & 1)
		&& (nbcompr > 12);
	z->isEncrypted =
		(ZipReadShort(start, end, lq + ZIP_LOCAL_FLAGS_OFFS) & 1)
		&& (nbcompr > ZIP_CRYPT_HDR_LEN);
	z->offset = offs;
	if (gq) {
	    z->crc32 = ZipReadInt(gq + ZIP_CENTRAL_CRC32_OFFS);
	    dosDate = ZipReadShort(gq + ZIP_CENTRAL_MDATE_OFFS);
	    dosTime = ZipReadShort(gq + ZIP_CENTRAL_MTIME_OFFS);
	    z->crc32 = ZipReadInt(start, end, gq + ZIP_CENTRAL_CRC32_OFFS);
	    dosDate = ZipReadShort(start, end, gq + ZIP_CENTRAL_MDATE_OFFS);
	    dosTime = ZipReadShort(start, end, gq + ZIP_CENTRAL_MTIME_OFFS);
	    z->timestamp = DosTimeDate(dosDate, dosTime);
	    z->numBytes = ZipReadInt(gq + ZIP_CENTRAL_UNCOMPLEN_OFFS);
	    z->compressMethod = ZipReadShort(gq + ZIP_CENTRAL_COMPMETH_OFFS);
	    z->numBytes = ZipReadInt(start, end,
		    gq + ZIP_CENTRAL_UNCOMPLEN_OFFS);
	    z->compressMethod = ZipReadShort(start, end,
		    gq + ZIP_CENTRAL_COMPMETH_OFFS);
	} else {
	    z->crc32 = ZipReadInt(lq + ZIP_LOCAL_CRC32_OFFS);
	    dosDate = ZipReadShort(lq + ZIP_LOCAL_MDATE_OFFS);
	    dosTime = ZipReadShort(lq + ZIP_LOCAL_MTIME_OFFS);
	    z->crc32 = ZipReadInt(start, end, lq + ZIP_LOCAL_CRC32_OFFS);
	    dosDate = ZipReadShort(start, end, lq + ZIP_LOCAL_MDATE_OFFS);
	    dosTime = ZipReadShort(start, end, lq + ZIP_LOCAL_MTIME_OFFS);
	    z->timestamp = DosTimeDate(dosDate, dosTime);
	    z->numBytes = ZipReadInt(lq + ZIP_LOCAL_UNCOMPLEN_OFFS);
	    z->compressMethod = ZipReadShort(lq + ZIP_LOCAL_COMPMETH_OFFS);
	    z->numBytes = ZipReadInt(start, end,
		    lq + ZIP_LOCAL_UNCOMPLEN_OFFS);
	    z->compressMethod = ZipReadShort(start, end,
		    lq + ZIP_LOCAL_COMPMETH_OFFS);
	}
	z->numCompressedBytes = nbcompr;
	z->data = NULL;
	hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, fullpath, &isNew);
	if (!isNew) {
	    /* should not happen but skip it anyway */
	    Tcl_Free(z);
	    goto nextent;
	}
	} else {
	    Tcl_SetHashValue(hPtr, z);
	    z->name = (char *)Tcl_GetHashKey(&ZipFS.fileHash, hPtr);
	    z->next = zf->entries;
	    zf->entries = z;
	    if (isdir && (mountPoint[0] == '\0') && (z->depth == 1)) {
		z->tnext = zf->topEnts;
		zf->topEnts = z;
	    }
	    if (!z->isDirectory && (z->depth > 1)) {
		char *dir, *end;
		ZipEntry *zd;

	Tcl_SetHashValue(hPtr, z);
	z->name = (char *) Tcl_GetHashKey(&ZipFS.fileHash, hPtr);
	z->next = zf->entries;
	zf->entries = z;
	if (isdir && (mountPoint[0] == '\0') && (z->depth == ZIPFS_ROOTDIR_DEPTH)) {
	    z->tnext = zf->topEnts;
	    zf->topEnts = z;
	}

	/*
	 * Make any directory nodes we need. ZIPs are not consistent about
	 * containing directory nodes.
	 */

	if (!z->isDirectory && (z->depth > ZIPFS_ROOTDIR_DEPTH)) {
	    char *dir, *endPtr;
	    ZipEntry *zd;

		Tcl_DStringSetLength(&ds, strlen(z->name) + 8);
		Tcl_DStringSetLength(&ds, 0);
		Tcl_DStringAppend(&ds, z->name, -1);
		dir = Tcl_DStringValue(&ds);
		for (end = strrchr(dir, '/'); end && (end != dir);
			end = strrchr(dir, '/')) {
		    Tcl_DStringSetLength(&ds, end - dir);
		    hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, dir, &isNew);
		    if (!isNew) {
			break;
		    }
		    zd = (ZipEntry *)Tcl_Alloc(sizeof(ZipEntry));
		    zd->name = NULL;
	    Tcl_DStringSetLength(&ds, strlen(z->name) + 8);
	    Tcl_DStringSetLength(&ds, 0);
	    Tcl_DStringAppend(&ds, z->name, -1);
	    dir = Tcl_DStringValue(&ds);
	    for (endPtr = strrchr(dir, '/'); endPtr && (endPtr != dir);
		    endPtr = strrchr(dir, '/')) {
		Tcl_DStringSetLength(&ds, endPtr - dir);
		hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, dir, &isNew);
		if (!isNew) {
		    /*
		     * Already made. That's fine.
		     */
		    break;
		}

		zd = AllocateZipEntry();
		    zd->tnext = NULL;
		    zd->depth = CountSlashes(dir);
		    zd->zipFilePtr = zf;
		    zd->isDirectory = 1;
		zd->depth = CountSlashes(dir);
		assert(zd->depth > ZIPFS_ROOTDIR_DEPTH);
		zd->zipFilePtr = zf;
		zd->isDirectory = 1;
		    zd->isEncrypted = 0;
		    zd->offset = z->offset;
		zd->offset = z->offset;
		    zd->crc32 = 0;
		    zd->timestamp = z->timestamp;
		zd->timestamp = z->timestamp;
		    zd->numBytes = zd->numCompressedBytes = 0;
		    zd->compressMethod = ZIP_COMPMETH_STORED;
		zd->compressMethod = ZIP_COMPMETH_STORED;
		    zd->data = NULL;
		    Tcl_SetHashValue(hPtr, zd);
		    zd->name = (char *)Tcl_GetHashKey(&ZipFS.fileHash, hPtr);
		    zd->next = zf->entries;
		    zf->entries = zd;
		    if ((mountPoint[0] == '\0') && (zd->depth == 1)) {
			zd->tnext = zf->topEnts;
			zf->topEnts = zd;
		Tcl_SetHashValue(hPtr, zd);
		zd->name = (char *) Tcl_GetHashKey(&ZipFS.fileHash, hPtr);
		zd->next = zf->entries;
		zf->entries = zd;
		if ((mountPoint[0] == '\0') && (zd->depth == ZIPFS_ROOTDIR_DEPTH)) {
		    zd->tnext = zf->topEnts;
		    zf->topEnts = zd;
		    }
		}
	    }
	}
    nextent:
	q += pathlen + comlen + extra + ZIP_CENTRAL_HEADER_LEN;
    }
    Unlock();
    Tcl_DStringFree(&fpBuf);
    Tcl_DStringFree(&ds);
    Tcl_FSMountsChanged(NULL);
    Unlock();
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipfsSetup --
1449
1450
1451
1452
1453
1454
1455

1456
1457
1458
1459
1460



1461
1462
1463
1464
1465
1466
1467
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168







+





+
+
+







     */

    Tcl_MutexLock(&ZipFSMutex);
    Tcl_ConditionWait(&ZipFSCond, &ZipFSMutex, &t);
    Tcl_MutexUnlock(&ZipFSMutex);
#endif /* TCL_THREADS */

    crc32tab = get_crc_table();
    Tcl_FSRegister(NULL, &zipfsFilesystem);
    Tcl_InitHashTable(&ZipFS.fileHash, TCL_STRING_KEYS);
    Tcl_InitHashTable(&ZipFS.zipHash, TCL_STRING_KEYS);
    ZipFS.idCount = 1;
    ZipFS.wrmax = DEFAULT_WRITE_MAX_SIZE;
    ZipFS.fallbackEntryEncoding = (char *)
	    Tcl_Alloc(strlen(ZIPFS_FALLBACK_ENCODING) + 1);
    strcpy(ZipFS.fallbackEntryEncoding, ZIPFS_FALLBACK_ENCODING);
    ZipFS.initialized = 1;
}

/*
 *-------------------------------------------------------------------------
 *
 * ListMountPoints --
1476
1477
1478
1479
1480
1481
1482
1483

1484
1485
1486
1487
1488
1489

1490










1491
1492






1493
1494
1495
1496
1497
1498
1499

































1500
1501
1502








1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522

1523
1524
1525
1526
1527
1528


1529
1530
1531
1532

1533
1534
1535
1536
1537
1538
1539
1540
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
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
2273
2274
2275


2276
2277
2278



2279

2280
2281
2282
2283
2284
2285
2286







-
+






+

+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+



















-
+




-
-
+
+

-
-
-
+
-







 *
 * Side effects:
 *	Interpreter result may be updated.
 *
 *-------------------------------------------------------------------------
 */

static inline int
static int
ListMountPoints(
    Tcl_Interp *interp)
{
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    ZipFile *zf;
    Tcl_Obj *resultList;

    if (!interp) {
	/*
	 * Are there any entries in the zipHash? Don't need to enumerate them
	 * all to know.
	 */

	return (ZipFS.zipHash.numEntries ? TCL_OK : TCL_BREAK);
    }

    TclNewObj(resultList);
    for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
	    hPtr = Tcl_NextHashEntry(&search)) {
	zf = (ZipFile *) Tcl_GetHashValue(hPtr);
	Tcl_ListObjAppendElement(NULL, resultList, Tcl_NewStringObj(
		zf->mountPoint, -1));
	Tcl_ListObjAppendElement(NULL, resultList, Tcl_NewStringObj(
		zf->name, -1));
    }
	if (!interp) {
	    return TCL_OK;
	}
	zf = (ZipFile *)Tcl_GetHashValue(hPtr);
	Tcl_AppendElement(interp, zf->mountPoint);
	Tcl_AppendElement(interp, zf->name);
    }
    Tcl_SetObjResult(interp, resultList);
    return TCL_OK;
}

/*
 *------------------------------------------------------------------------
 *
 * CleanupMount --
 *
 *    Releases all resources associated with a mounted archive. There
 *    must not be any open files in the archive.
 *
 *    Caller MUST be holding WriteLock() before calling this function.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Memory associated with the mounted archive is deallocated.
 *------------------------------------------------------------------------
 */
static void
CleanupMount(
    ZipFile *zf)		/* Mount point */
{
    ZipEntry *z, *znext;
    Tcl_HashEntry *hPtr;
    for (z = zf->entries; z; z = znext) {
	znext = z->next;
	hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, z->name);
	if (hPtr) {
	    Tcl_DeleteHashEntry(hPtr);
	}
    return (interp ? TCL_OK : TCL_BREAK);
}

	if (z->data) {
	    Tcl_Free(z->data);
	}
	Tcl_Free(z);
    }
    zf->entries = NULL;
}

/*
 *-------------------------------------------------------------------------
 *
 * DescribeMounted --
 *
 *	This procedure describes what is mounted at the given the mount point.
 *	The interpreter result is not updated if there is nothing mounted at
 *	the given point. The read lock must be held by the caller.
 *
 * Results:
 *	A standard Tcl result. TCL_OK (or TCL_BREAK if nothing mounted there
 *	and no interpreter).
 *
 * Side effects:
 *	Interpreter result may be updated.
 *
 *-------------------------------------------------------------------------
 */

static inline int
static int
DescribeMounted(
    Tcl_Interp *interp,
    const char *mountPoint)
{
    Tcl_HashEntry *hPtr;
    ZipFile *zf;
    if (interp) {
	ZipFile *zf = ZipFSLookupZip(mountPoint);

    if (interp) {
	hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mountPoint);
	if (hPtr) {
	if (zf) {
	    zf = (ZipFile *)Tcl_GetHashValue(hPtr);
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(zf->name, -1));
	    return TCL_OK;
	}
    }
    return (interp ? TCL_OK : TCL_BREAK);
}

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
2301
2302
2303
2304
2305
2306
2307
2308
2309

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

2390







2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401

2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416


2417
2418
2419
2420
2421
2422

2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435






2436
2437
2438
2439
2440
2441
2442

2443




2444





2445
2446
2447
2448
2449
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




2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501







+

-




+










-
-
+
+
+
+
+
+
+
+
+
+



-
+
-
-
-
-


+
+
+
+
+
-
+

+
+
-
-
-
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
-
-
-
-
+
+
+
-
-
+
-
-
+
-
-
+
-

-
-
-
-
-
-
-
+
+
+








-
+














-
-
+

+



-
+

+
+
+
+
+
+





-
-
-
-
-
-
+
+
+
+



-
+
-
-
-
-

-
-
-
-
-




+

-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
+
+



+


-
-
+
+
-
-
+
-
-
+
+




-
+


-
-
-
+
+
+
+
+
+
+

+
-
-
-
-
+
+
+
+
+
+







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

int
TclZipfs_Mount(
    Tcl_Interp *interp,		/* Current interpreter. NULLable. */
    const char *zipname,	/* Path to ZIP file to mount */
    const char *mountPoint,	/* Mount point path. */
    const char *zipname,	/* Path to ZIP file to mount. */
    const char *passwd)		/* Password for opening the ZIP, or NULL if
				 * the ZIP is unprotected. */
{
    ZipFile *zf;
    int ret;

    ReadLock();
    if (!ZipFS.initialized) {
	ZipfsSetup();
    }

    /*
     * No mount point, so list all mount points and what is mounted there.
     */

    if (!mountPoint) {
	int ret = ListMountPoints(interp);
    if (mountPoint == NULL) {
	ret = ListMountPoints(interp);
	Unlock();
	return ret;
    }

    Tcl_DString ds;
    Tcl_DStringInit(&ds);
    ret = NormalizeMountPoint(interp, mountPoint, &ds);
    if (ret != TCL_OK) {
	Unlock();
	return ret;
    }

    mountPoint = Tcl_DStringValue(&ds);
    /*
     * Mount point but no file, so describe what is mounted at that mount
     * point.
     */

    if (!zipname) {
	/*
	 * Mount point but no file, so describe what is mounted at that mount
	 * point.
	 */

	DescribeMounted(interp, mountPoint);
	ret = DescribeMounted(interp, mountPoint);
	Unlock();
    } else {
	/* Have both a mount point and a file (name) to mount there. */
	return TCL_OK;
    }
    Unlock();

	Tcl_Obj *zipPathObj;
	Tcl_Obj *normZipPathObj;

	Unlock();

    /*
     * Have both a mount point and a file (name) to mount there.
     */

    if (passwd) {
	if ((strlen(passwd) > 255) || strchr(passwd, 0xff)) {
	    if (interp) {
		Tcl_SetObjResult(interp,
			Tcl_NewStringObj("illegal password", -1));
		Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "BAD_PASS", NULL);
	    }
	zipPathObj = Tcl_NewStringObj(zipname, -1);
	Tcl_IncrRefCount(zipPathObj);
	normZipPathObj = Tcl_FSGetNormalizedPath(interp, zipPathObj);
	if (normZipPathObj == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "could not normalize zip filename \"%s\"", zipname));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NORMALIZE", (char *)NULL);
	    ret = TCL_ERROR;
	} else {
	    Tcl_IncrRefCount(normZipPathObj);
	    const char *normPath = Tcl_GetString(normZipPathObj);
	    if (passwd == NULL ||
		    (ret = IsPasswordValid(interp, passwd,
			    strlen(passwd))) == TCL_OK) {
		zf = AllocateZipFile(interp, strlen(mountPoint));
		if (zf == NULL) {
		    ret = TCL_ERROR;
		} else {
		    ret = ZipFSOpenArchive(interp, normPath, 1, zf);
		    if (ret != TCL_OK) {
			Tcl_Free(zf);
		    } else {
			ret = ZipFSCatalogFilesystem(
			    interp, zf, mountPoint, passwd, normPath);
			/* Note zf is already freed on error! */
		    }
	    return TCL_ERROR;
	}
    }
		}
	    }
    zf = (ZipFile *)Tcl_AttemptAlloc(sizeof(ZipFile) + strlen(mountPoint) + 1);
    if (!zf) {
	if (interp) {
	    Tcl_AppendResult(interp, "out of memory", (char *) NULL);
	    Tcl_DecrRefCount(normZipPathObj);
	    if (ret == TCL_OK && interp) {
		Tcl_DStringResult(interp, &ds);
	    Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL);
	}
	    }
	return TCL_ERROR;
    }
	}
    if (ZipFSOpenArchive(interp, zipname, 1, zf) != TCL_OK) {
	Tcl_Free(zf);
	Tcl_DecrRefCount(zipPathObj);
	return TCL_ERROR;
    }
    if (ZipFSCatalogFilesystem(interp, zf, mountPoint, passwd, zipname)
	    != TCL_OK) {
	Tcl_Free(zf);
	return TCL_ERROR;
    }
    Tcl_Free(zf);
    return TCL_OK;

    Tcl_DStringFree(&ds);
    return ret;
}

/*
 *-------------------------------------------------------------------------
 *
 * TclZipfs_MountBuffer --
 *
 *	This procedure is invoked to mount a given ZIP archive file on a given
 *	mountpoint with optional ZIP password.
 *	mountpoint.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	A ZIP archive file is read, analyzed and mounted, resources are
 *	allocated.
 *
 *-------------------------------------------------------------------------
 */

int
TclZipfs_MountBuffer(
    Tcl_Interp *interp,		/* Current interpreter. NULLable. */
    const char *mountPoint,	/* Mount point path. */
    unsigned char *data,
    const void *data,
    size_t datalen,
    const char *mountPoint,	/* Mount point path. */
    int copy)
{
    ZipFile *zf;
    int result;
    int ret;

    if (mountPoint == NULL || data == NULL) {
	ZIPFS_ERROR(interp, "mount point and/or data are null");
	return TCL_ERROR;
    }

    /* TODO - how come a *read* lock suffices for initialzing ? */
    ReadLock();
    if (!ZipFS.initialized) {
	ZipfsSetup();
    }

    /*
     * No mount point, so list all mount points and what is mounted there.
     */

    if (!mountPoint) {
	int ret = ListMountPoints(interp);
    Tcl_DString ds;
    Tcl_DStringInit(&ds);
    ret = NormalizeMountPoint(interp, mountPoint, &ds);
    if (ret != TCL_OK) {
	Unlock();
	return ret;
    }

    mountPoint = Tcl_DStringValue(&ds);
    /*
     * Mount point but no data, so describe what is mounted at that mount
     * point.
     */

    if (!data) {
	DescribeMounted(interp, mountPoint);
	Unlock();
	return TCL_OK;
    }
    Unlock();

    /*
     * Have both a mount point and data to mount there.
     * What's the magic about 64 * 1024 * 1024 ?
     */

    ret = TCL_ERROR;
    zf = (ZipFile *)Tcl_AttemptAlloc(sizeof(ZipFile) + strlen(mountPoint) + 1);
    if (!zf) {
	if (interp) {
	    Tcl_AppendResult(interp, "out of memory", (char *) NULL);
	    Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL);
	}
    if ((datalen <= ZIP_CENTRAL_END_LEN) ||
	    (datalen - ZIP_CENTRAL_END_LEN) >
		    (64 * 1024 * 1024 - ZIP_CENTRAL_END_LEN)) {
	ZIPFS_ERROR(interp, "illegal file size");
	ZIPFS_ERROR_CODE(interp, "FILE_SIZE");
	goto done;
    }
	return TCL_ERROR;
    zf = AllocateZipFile(interp, strlen(mountPoint));
    if (zf == NULL) {
	goto done;
    }
    zf->isMemBuffer = 1;
    zf->length = datalen;

    if (copy) {
	zf->data = (unsigned char *)Tcl_AttemptAlloc(datalen);
	if (!zf->data) {
	    if (interp) {
	if (zf->data == NULL) {
	    ZipFSCloseArchive(interp, zf);
		Tcl_AppendResult(interp, "out of memory", (char *) NULL);
		Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL);
	    Tcl_Free(zf);
	    }
	    return TCL_ERROR;
	    ZIPFS_MEM_ERROR(interp);
	    goto done;
	}
	memcpy(zf->data, data, datalen);
	zf->ptrToFree = zf->data;
    } else {
	zf->data = data;
	zf->data = (unsigned char *)data;
	zf->ptrToFree = NULL;
    }
    zf->passBuf[0] = 0;	/* stop valgrind cries */
    if (ZipFSFindTOC(interp, 0, zf) != TCL_OK) {
	return TCL_ERROR;
    ret = ZipFSFindTOC(interp, 1, zf);
    if (ret != TCL_OK) {
	Tcl_Free(zf);
    } else {
	/* Note ZipFSCatalogFilesystem will free zf on error */
	ret = ZipFSCatalogFilesystem(
	    interp, zf, mountPoint, NULL, "Memory Buffer");
    }
    if (ret == TCL_OK && interp) {
    result = ZipFSCatalogFilesystem(interp, zf, mountPoint, NULL,
	    "Memory Buffer");
    Tcl_Free(zf);
    return result;
	Tcl_DStringResult(interp, &ds);
    }

done:
    Tcl_DStringFree(&ds);
    return ret;
}

/*
 *-------------------------------------------------------------------------
 *
 * TclZipfs_Unmount --
 *
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751


1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764




1765
1766
1767
1768
1769
1770
1771
1772

1773
1774

1775
1776
1777
1778
1779
1780
1781
1782
1783
1784

1785
1786
1787
1788






1789
1790
1791

1792
1793

1794
1795

1796
1797
1798
1799
1800
1801
1802
2512
2513
2514
2515
2516
2517
2518

2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534


2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545

2546
2547
2548
2549
2550
2551
2552
2553






2554




2555
2556
2557
2558
2559
2560

2561

2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575







-



+
+











-
-
+
+
+
+







-
+


+




-
-
-
-
-
-
+
-
-
-
-
+
+
+
+
+
+
-

-
+


+


+








int
TclZipfs_Unmount(
    Tcl_Interp *interp,		/* Current interpreter. NULLable. */
    const char *mountPoint)	/* Mount point path. */
{
    ZipFile *zf;
    ZipEntry *z, *znext;
    Tcl_HashEntry *hPtr;
    Tcl_DString dsm;
    int ret = TCL_OK, unmounted = 0;

    Tcl_DStringInit(&dsm);

    WriteLock();
    if (!ZipFS.initialized) {
	goto done;
    }

    /*
     * Mount point sometimes is a relative or otherwise denormalized path.
     * But an absolute name is needed as mount point here.
     */

    Tcl_DStringInit(&dsm);
    mountPoint = CanonicalPath("", mountPoint, &dsm, 1);
    if (NormalizeMountPoint(interp, mountPoint, &dsm) != TCL_OK) {
	goto done;
    }
    mountPoint = Tcl_DStringValue(&dsm);

    hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mountPoint);
    /* don't report no-such-mount as an error */
    if (!hPtr) {
	goto done;
    }

    zf = (ZipFile *)Tcl_GetHashValue(hPtr);
    zf = (ZipFile *) Tcl_GetHashValue(hPtr);
    if (zf->numOpen > 0) {
	ZIPFS_ERROR(interp, "filesystem is busy");
	ZIPFS_ERROR_CODE(interp, "BUSY");
	ret = TCL_ERROR;
	goto done;
    }
    Tcl_DeleteHashEntry(hPtr);
    for (z = zf->entries; z; z = znext) {
	znext = z->next;
	hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, z->name);
	if (hPtr) {
	    Tcl_DeleteHashEntry(hPtr);
	}

	if (z->data) {
	    Tcl_Free(z->data);
	}
	Tcl_Free(z);
    /*
     * Now no longer mounted - the rest of the code won't find it - but we're
     * still cleaning things up.
     */

    CleanupMount(zf);
    }
    ZipFSCloseArchive(interp, zf);
    Tcl_DeleteExitHandler(ZipfsExitHandler, zf);

    Tcl_Free(zf);
    unmounted = 1;

  done:
    Unlock();
    Tcl_DStringFree(&dsm);
    if (unmounted) {
	Tcl_FSMountsChanged(NULL);
    }
    return ret;
}

/*
1813
1814
1815
1816
1817
1818
1819
1820

1821
1822
1823
1824


1825
1826
1827
1828

1829
1830
1831
1832
1833
1834



















1835
1836
1837
1838
1839
1840
1841
1842

1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855

1856
1857
1858
1859
1860
1861
1862



1863
1864
1865


1866
1867
1868
1869
1870

1871
1872
1873
1874
1875
1876
1877

1878
1879
1880
1881
1882
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
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







-
+




+
+



-
+


-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+












-
+




-
-
-
+
+
+

-
-
+
+


-
-
-
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-



-
+




















-
+

-
-
+
+

+
+
+
+







 *	A ZIP archive file is mounted, resources are allocated.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMountObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *mountPoint = NULL, *zipFile = NULL, *password = NULL;
    int result;

    if (objc > 4) {
	Tcl_WrongNumArgs(interp, 1, objv,
		 "?mountpoint? ?zipfile? ?password?");
		 "?zipfile? ?mountpoint? ?password?");
	return TCL_ERROR;
    }

    return TclZipfs_Mount(interp, (objc > 1) ? TclGetString(objv[1]) : NULL,
	    (objc > 2) ? TclGetString(objv[2]) : NULL,
	    (objc > 3) ? TclGetString(objv[3]) : NULL);
    /*
     * A single argument is treated as the mountpoint. Two arguments
     * are treated as zipfile and mountpoint.
     */
    if (objc > 1) {
	if (objc == 2) {
	    mountPoint = Tcl_GetString(objv[1]);
	} else {
	    /* 2 < objc < 4 */
	    zipFile = Tcl_GetString(objv[1]);
	    mountPoint = Tcl_GetString(objv[2]);
	    if (objc > 3) {
		password = Tcl_GetString(objv[3]);
	    }
	}
    }

    result = TclZipfs_Mount(interp, zipFile, mountPoint, password);
    return result;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSMountBufferObjCmd --
 *
 *	This procedure is invoked to process the [zipfs mount_data] command.
 *	This procedure is invoked to process the [zipfs mountdata] command.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	A ZIP archive file is mounted, resources are allocated.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMountBufferObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *mountPoint;	/* Mount point path. */
    unsigned char *data;
    size_t length = 0;
    const char *mountPoint = NULL;	/* Mount point path. */
    unsigned char *data = NULL;
    Tcl_Size length;

    if (objc > 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "?mountpoint? ?data?");
    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "data mountpoint");
	return TCL_ERROR;
    }
    if (objc < 2) {
	int ret;

    data = Tcl_GetBytesFromObj(interp, objv[1], &length);
	ReadLock();
	ret = ListMountPoints(interp);
	Unlock();
	return ret;
    }

    mountPoint = TclGetString(objv[1]);
    mountPoint = Tcl_GetString(objv[2]);
    if (objc < 3) {
	ReadLock();
	DescribeMounted(interp, mountPoint);
	Unlock();
	return TCL_OK;
    }

    data = TclGetBytesFromObj(interp, objv[2], &length);
    if (data == NULL) {
	return TCL_ERROR;
    }
    return TclZipfs_MountBuffer(interp, mountPoint, data, length, 1);
    return TclZipfs_MountBuffer(interp, data, length, mountPoint, 1);
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSRootObjCmd --
 *
 *	This procedure is invoked to process the [zipfs root] command. It
 *	returns the root that all zipfs file systems are mounted under.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSRootObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*objc*/,
    TCL_UNUSED(Tcl_Obj *const *)) /*objv*/
    int objc,
    Tcl_Obj *const *objv)
{
    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, "");
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewStringObj(ZIPFS_VOLUME, -1));
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
1930
1931
1932
1933
1934
1935
1936
1937

1938
1939
1940
1941
1942
1943
1944

1945
1946
1947
1948
1949
1950
1951
2708
2709
2710
2711
2712
2713
2714

2715
2716
2717
2718
2719

2720

2721
2722
2723
2724
2725
2726
2727
2728







-
+




-

-
+







 *	A mounted ZIP archive file is unmounted, resources are free'd.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSUnmountObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "zipfile");
	Tcl_WrongNumArgs(interp, 1, objv, "mountpoint");
	return TCL_ERROR;
    }
    return TclZipfs_Unmount(interp, TclGetString(objv[1]));
}

/*
 *-------------------------------------------------------------------------
1962
1963
1964
1965
1966
1967
1968
1969

1970
1971
1972
1973
1974
1975




1976
1977
1978
1979
1980
1981

1982
1983
1984
1985
1986
1987

1988
1989



1990
1991
1992
1993

1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004










































2005






2006
2007
2008
2009
2010
2011
2012
2013

2014
2015
2016



2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033




2034
2035
2036
2037
2038




2039


2040
2041
2042
2043

2044



2045
2046
2047



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
2095
2096
2097
2098


2099
2100

2101
2102

2103
2104
2105


2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117



2118
2119






2120







2121
2122

2123
2124
2125

2126
2127
2128




2129
2130
2131
2132
2133
2134
2135
2136
2137




2138





2139
2140
2141
2142




2143
2144

2145
2146





2147
2148
2149

2150
2151
2152
2153

2154
2155

2156
2157
2158
2159
2160
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
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
2273
2274

2275
2276
2277

2278
2279
2280
2281
2282
2283
2284

2285
2286
2287
2288
2289
2290
2291
2292
2293

2294
2295
2296
2297
2298
2299






2300
2301
2302


2303
2304



2305
2306

2307
2308
2309
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
2390
2391

2392
2393
2394
2395
2396
















2397
2398
2399
2400
2401
2402










2403
2404
2405
2406
2407


2408
2409
2410
2411
2412
2413
2414
2415


2416
2417
2418

2419
2420
2421
2422


2423

2424
2425
2426
2427
2428
2429

2430
2431

2432
2433
2434

2435

2436
2437
2438
2439
2440
2441

2442

2443
2444
2445
2446

2447
2448
2449
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
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

3134
3135
3136

3137



3138


3139
3140
3141
3142

3143
3144
3145
3146
3147
3148
3149
3150


3151


3152
3153
3154
3155
3156
3157
3158
3159
3160
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
3199










3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215

3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313

3314
3315
3316
3317
3318

3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334

3335
3336




3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354




3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377


3378
3379



3380


3381
3382
3383
3384

3385






3386


3387



3388

3389
3390
3391



3392
3393

3394
3395
3396
3397

3398
3399



3400
3401
3402
3403
3404
3405


3406
3407
3408
3409
3410
3411
3412
3413

3414
3415
3416
3417
3418

3419



3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430



3431
3432
3433




3434
3435
3436
3437
3438
3439
3440







-
+




-
-
+
+
+
+





-
+
-



-
-
+


+
+
+



-
+
-



-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+







-
+



+
+
+














-
-
-
+
+
+
+


-
-
-
+
+
+
+

+
+




+
-
+
+
+

-
-
+
+
+









-
-
-
+
+
+

-
+



+
+
+
+
+
+
+
+
+
+
-
+


-
-
+
+
+


-
+

+



-
+



-
+


-


-



-


+
+
+
+
+




-
+
+

-
+


+

-
-
+
+










-
-
+
+
+


+
+
+
+
+
+
-
+
+
+
+
+
+
+

-
+


-
+

-
-
+
+
+
+


-
-

-
-
-
-
+
+
+
+

+
+
+
+
+
-
-
-
-
+
+
+
+

-
+


+
+
+
+
+


-
+
-


-
+
-
-
+
-
-
-
-
-
-
-
+


-
-
-
-
-
-
-
-
-
-
-
-
+



-
-
+
+



-
-
-
+
+
+
-
-
+
-
-


-
+

+
+
+
+
+

-
+
+
+
+
+
+








-
-
-
+
+
+
+


+


-
+
-
-

-
+
-








-
+

-
-
+
+

-
+
+




-
+







-
-

-
-
+





+
+
+
+
+

-
+
+




+



-
+

-


+
+


-
+


-
+
-
-
-
+
-
-




-
+







-
-
+
-
-




+
+
+
+
+
+

-
-
+
+

-
+
+
+

-
+


-
-
+
+



+
+
+
+
+
-
+
+

-
-
-
-
-

-
+





-
-
+
-




-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+














-
+












+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+




-
+
+
+
+
+











-
+

-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
+
+
+
+
+
+
+
+
+
+





+
+






-
-
+
+
-
-
-
+
-
-


+
+
-
+
-
-
-
-
-
-
+
-
-
+
-
-
-
+
-
+


-
-
-

+
-
+



-
+

-
-
-
+
+




-
-
+
+


+
+
+
+
-
+




-
+
-
-
-
+
+
+
+
+
+





-
-
-
+
+
+
-
-
-
-







 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMkKeyObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int len, i = 0;
    char *pw, passBuf[264];
    Tcl_Size len, i = 0;
    const char *pw;
    Tcl_Obj *passObj;
    unsigned char *passBuf;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "password");
	return TCL_ERROR;
    }
    pw = TclGetString(objv[1]);
    pw = TclGetStringFromObj(objv[1], &len);
    len = strlen(pw);
    if (len == 0) {
	return TCL_OK;
    }
    if ((len > 255) || strchr(pw, 0xff)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("illegal password", -1));
    if (IsPasswordValid(interp, pw, len) != TCL_OK) {
	return TCL_ERROR;
    }

    passObj = Tcl_NewByteArrayObj(NULL, 264);
    passBuf = Tcl_GetBytesFromObj(NULL, passObj, (Tcl_Size *)NULL);
    while (len > 0) {
	int ch = pw[len - 1];

	passBuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f];
	passBuf[i++] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f];
	i++;
	len--;
    }
    passBuf[i] = i;
    ++i;
    passBuf[i++] = (char) ZIP_PASSWORD_END_SIG;
    passBuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 8);
    passBuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 16);
    passBuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 24);
    passBuf[i] = '\0';
    Tcl_AppendResult(interp, passBuf, (char *) NULL);
    i++;
    ZipWriteInt(passBuf, passBuf + 264, passBuf + i, ZIP_PASSWORD_END_SIG);
    Tcl_SetByteArrayLength(passObj, i + 4);
    Tcl_SetObjResult(interp, passObj);
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
 * RandomChar --
 *
 *	Worker for ZipAddFile().  Picks a random character (range: 0..255)
 *	using Tcl's standard PRNG.
 *
 * Returns:
 *	Tcl result code. Updates chPtr with random character on success.
 *
 * Side effects:
 *	Advances the PRNG state. May reenter the Tcl interpreter if the user
 *	has replaced the PRNG.
 *
 *-------------------------------------------------------------------------
 */

static int
RandomChar(
    Tcl_Interp *interp,
    int step,
    int *chPtr)
{
    double r;
    Tcl_Obj *ret;

    if (Tcl_EvalEx(interp, "::tcl::mathfunc::rand", TCL_INDEX_NONE, 0) != TCL_OK) {
	goto failed;
    }
    ret = Tcl_GetObjResult(interp);
    if (Tcl_GetDoubleFromObj(interp, ret, &r) != TCL_OK) {
	goto failed;
    }
    *chPtr = (int) (r * 256);
    return TCL_OK;

  failed:
    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
	    "\n    (evaluating PRNG step %d for password encoding)",
	    step));
    return TCL_ERROR;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipAddFile --
 *
 *	This procedure is used by ZipFSMkZipOrImgCmd() to add a single file to
 *	This procedure is used by ZipFSMkZipOrImg() to add a single file to
 *	the output ZIP archive file being written. A ZipEntry struct about the
 *	input file is added to the given fileHash table for later creation of
 *	the central ZIP directory.
 *
 *	Tcl *always* encodes filenames in the ZIP as UTF-8. Similarly, it
 *	would always encode comments as UTF-8, if it supported comments.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Input file is read and (compressed and) written to the output ZIP
 *	archive file.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipAddFile(
    Tcl_Interp *interp,		/* Current interpreter. */
    const char *path,
    const char *name,
    Tcl_Channel out,
    Tcl_Obj *pathObj,		/* Actual name of the file to add. */
    const char *name,		/* Name to use in the ZIP archive, in Tcl's
				 * internal encoding. */
    Tcl_Channel out,		/* The open ZIP archive being built. */
    const char *passwd,		/* Password for encoding the file, or NULL if
				 * the file is to be unprotected. */
    char *buf,
    int bufsize,
    Tcl_HashTable *fileHash)
    char *buf,			/* Working buffer. */
    int bufsize,		/* Size of buf */
    Tcl_HashTable *fileHash)	/* Where to record ZIP entry metdata so we can
				 * built the central directory. */
{
    const unsigned char *start = (unsigned char *) buf;
    const unsigned char *end = (unsigned char *) buf + bufsize;
    Tcl_Channel in;
    Tcl_HashEntry *hPtr;
    ZipEntry *z;
    z_stream stream;
    Tcl_DString zpathDs;	/* Buffer for the encoded filename. */
    const char *zpath;
    const char *zpathExt;	/* Filename in external encoding (true
				 * UTF-8). */
    const char *zpathTcl;	/* Filename in Tcl's internal encoding. */
    int crc, flush, zpathlen;
    size_t nbyte, nbytecompr, len, olen, align = 0;
    Tcl_WideInt pos[3];
    size_t nbyte, nbytecompr;
    Tcl_Size len, olen, align = 0;
    long long headerStartOffset, dataStartOffset, dataEndOffset;
    int mtime = 0, isNew, compMeth;
    unsigned long keys[3], keys0[3];
    char obuf[4096];

    /*
     * Trim leading '/' characters. If this results in an empty string, we've
     * nothing to do.
     */

    zpath = name;
    while (zpath && zpath[0] == '/') {
	zpath++;
    zpathTcl = name;
    while (zpathTcl && zpathTcl[0] == '/') {
	zpathTcl++;
    }
    if (!zpath || (zpath[0] == '\0')) {
    if (!zpathTcl || (zpathTcl[0] == '\0')) {
	return TCL_OK;
    }

    /*
     * Convert to encoded form. Note that we use strlen() here; if someone's
     * crazy enough to embed NULs in filenames, they deserve what they get!
     */

    if (Tcl_UtfToExternalDStringEx(interp, tclUtf8Encoding, zpathTcl, TCL_INDEX_NONE, 0, &zpathDs, NULL) != TCL_OK) {
	Tcl_DStringFree(&zpathDs);
	return TCL_ERROR;
    }
    zpathExt = Tcl_DStringValue(&zpathDs);
    zpathlen = strlen(zpath);
    zpathlen = strlen(zpathExt);
    if (zpathlen + ZIP_CENTRAL_HEADER_LEN > bufsize) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"path too long for \"%s\"", path));
	Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "PATH_LEN", NULL);
		"path too long for \"%s\"", TclGetString(pathObj)));
	ZIPFS_ERROR_CODE(interp, "PATH_LEN");
	Tcl_DStringFree(&zpathDs);
	return TCL_ERROR;
    }
    in = Tcl_OpenFileChannel(interp, path, "rb", 0);
    in = Tcl_FSOpenFileChannel(interp, pathObj, "rb", 0);
    if (!in) {
	Tcl_DStringFree(&zpathDs);
#ifdef _WIN32
	/* hopefully a directory */
	if (strcmp("permission denied", Tcl_PosixError(interp)) == 0) {
	    Tcl_CloseEx(interp, in, 0);
	    Tcl_Close(interp, in);
	    return TCL_OK;
	}
#endif /* _WIN32 */
	Tcl_CloseEx(interp, in, 0);
	Tcl_Close(interp, in);
	return TCL_ERROR;
    } else {
	Tcl_Obj *pathObj = Tcl_NewStringObj(path, -1);
	Tcl_StatBuf statBuf;

	Tcl_IncrRefCount(pathObj);
	if (Tcl_FSStat(pathObj, &statBuf) != -1) {
	    mtime = statBuf.st_mtime;
	}
	Tcl_DecrRefCount(pathObj);
    }
    Tcl_ResetResult(interp);

    /*
     * Compute the CRC.
     */

    crc = 0;
    nbyte = nbytecompr = 0;
    while (1) {
	len = Tcl_Read(in, buf, bufsize);
	if (len == TCL_IO_FAILURE) {
	if (len < 0) {
	    Tcl_DStringFree(&zpathDs);
	    if (nbyte == 0 && errno == EISDIR) {
		Tcl_CloseEx(interp, in, 0);
		Tcl_Close(interp, in);
		return TCL_OK;
	    }
	readErrorWithChannelOpen:
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf("read error on \"%s\": %s",
		    path, Tcl_PosixError(interp)));
	    Tcl_CloseEx(interp, in, 0);
		    TclGetString(pathObj), Tcl_PosixError(interp)));
	    Tcl_Close(interp, in);
	    return TCL_ERROR;
	}
	if (len == 0) {
	    break;
	}
	crc = crc32(crc, (unsigned char *) buf, len);
	nbyte += len;
    }
    if (Tcl_Seek(in, 0, SEEK_SET) == -1) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("seek error on \"%s\": %s",
		path, Tcl_PosixError(interp)));
	Tcl_CloseEx(interp, in, 0);
		TclGetString(pathObj), Tcl_PosixError(interp)));
	Tcl_Close(interp, in);
	Tcl_DStringFree(&zpathDs);
	return TCL_ERROR;
    }

    /*
     * Remember where we've got to so far so we can write the header (after
     * writing the file).
     */

    pos[0] = Tcl_Tell(out);
    headerStartOffset = Tcl_Tell(out);

    /*
     * Reserve space for the per-file header. Includes writing the file name
     * as we already know that.
     */

    memset(buf, '\0', ZIP_LOCAL_HEADER_LEN);
    memcpy(buf + ZIP_LOCAL_HEADER_LEN, zpath, zpathlen);
    memcpy(buf + ZIP_LOCAL_HEADER_LEN, zpathExt, zpathlen);
    len = zpathlen + ZIP_LOCAL_HEADER_LEN;
    if (Tcl_Write(out, buf, len) != len) {
    wrerr:
    writeErrorWithChannelOpen:
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"write error on %s: %s", path, Tcl_PosixError(interp)));
	Tcl_CloseEx(interp, in, 0);
		"write error on \"%s\": %s",
		TclGetString(pathObj), Tcl_PosixError(interp)));
	Tcl_Close(interp, in);
	Tcl_DStringFree(&zpathDs);
	return TCL_ERROR;
    }
    if ((len + pos[0]) & 3) {
	unsigned char abuf[8];

	/*
	 * Align payload to next 4-byte boundary using a dummy extra entry
	 * similar to the zipalign tool from Android's SDK.
	 */
    /*
     * Align payload to next 4-byte boundary (if necessary) using a dummy
     * extra entry similar to the zipalign tool from Android's SDK.
     */

    if ((len + headerStartOffset) & 3) {
	unsigned char abuf[8];
	const unsigned char *astart = abuf;
	const unsigned char *aend = abuf + 8;

	align = 4 + ((len + pos[0]) & 3);
	ZipWriteShort(abuf, 0xffff);
	ZipWriteShort(abuf + 2, align - 4);
	ZipWriteInt(abuf + 4, 0x03020100);
	align = 4 + ((len + headerStartOffset) & 3);
	ZipWriteShort(astart, aend, abuf, 0xffff);
	ZipWriteShort(astart, aend, abuf + 2, align - 4);
	ZipWriteInt(astart, aend, abuf + 4, 0x03020100);
	if (Tcl_Write(out, (const char *) abuf, align) != align) {
	    goto wrerr;
	    goto writeErrorWithChannelOpen;
	}
    }

    /*
     * Set up encryption if we were asked to.
     */

    if (passwd) {
	int i, ch, tmp;
	unsigned char kvbuf[24];
	unsigned char kvbuf[2*ZIP_CRYPT_HDR_LEN];
	Tcl_Obj *ret;

	init_keys(passwd, keys, crc32tab);
	for (i = 0; i < 12 - 2; i++) {
	for (i = 0; i < ZIP_CRYPT_HDR_LEN - 2; i++) {
	    double r;

	    if (RandomChar(interp, i, &ch) != TCL_OK) {
	    if (Tcl_EvalEx(interp, "::tcl::mathfunc::rand", -1, 0) != TCL_OK) {
		Tcl_Obj *eiPtr = Tcl_ObjPrintf(
			"\n    (evaluating PRNG step %d for password encoding)",
			i);

		Tcl_AppendObjToErrorInfo(interp, eiPtr);
		Tcl_CloseEx(interp, in, 0);
		Tcl_Close(interp, in);
		return TCL_ERROR;
	    }
	    ret = Tcl_GetObjResult(interp);
	    if (Tcl_GetDoubleFromObj(interp, ret, &r) != TCL_OK) {
		Tcl_Obj *eiPtr = Tcl_ObjPrintf(
			"\n    (evaluating PRNG step %d for password encoding)",
			i);

		Tcl_AppendObjToErrorInfo(interp, eiPtr);
		Tcl_CloseEx(interp, in, 0);
		return TCL_ERROR;
	    }
	    ch = (int) (r * 256);
	    kvbuf[i + 12] = UCHAR(zencode(keys, crc32tab, ch, tmp));
	    kvbuf[i + ZIP_CRYPT_HDR_LEN] = UCHAR(zencode(keys, crc32tab, ch, tmp));
	}
	Tcl_ResetResult(interp);
	init_keys(passwd, keys, crc32tab);
	for (i = 0; i < 12 - 2; i++) {
	    kvbuf[i] = UCHAR(zencode(keys, crc32tab, kvbuf[i + 12], tmp));
	for (i = 0; i < ZIP_CRYPT_HDR_LEN - 2; i++) {
	    kvbuf[i] = UCHAR(zencode(keys, crc32tab, kvbuf[i + ZIP_CRYPT_HDR_LEN], tmp));
	}
	kvbuf[i++] = UCHAR(zencode(keys, crc32tab, crc >> 16, tmp));
	kvbuf[i++] = UCHAR(zencode(keys, crc32tab, crc >> 24, tmp));
	len = Tcl_Write(out, (char *) kvbuf, 12);
	memset(kvbuf, 0, 24);
	if (len != 12) {
	len = Tcl_Write(out, (char *) kvbuf, ZIP_CRYPT_HDR_LEN);
	memset(kvbuf, 0, sizeof(kvbuf));
	if (len != ZIP_CRYPT_HDR_LEN) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "write error on %s: %s", path, Tcl_PosixError(interp)));
	    goto writeErrorWithChannelOpen;
	    Tcl_CloseEx(interp, in, 0);
	    return TCL_ERROR;
	}
	memcpy(keys0, keys, sizeof(keys0));
	nbytecompr += 12;
	nbytecompr += ZIP_CRYPT_HDR_LEN;
    }

    /*
     * Save where we've got to in case we need to just store this file.
     */

    Tcl_Flush(out);
    pos[2] = Tcl_Tell(out);
    dataStartOffset = Tcl_Tell(out);

    /*
     * Compress the stream.
     */

    compMeth = ZIP_COMPMETH_DEFLATED;
    memset(&stream, 0, sizeof(z_stream));
    stream.zalloc = Z_NULL;
    stream.zfree = Z_NULL;
    stream.opaque = Z_NULL;
    if (deflateInit2(&stream, 9, Z_DEFLATED, -15, 8,
	    Z_DEFAULT_STRATEGY) != Z_OK) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"compression init error on \"%s\"", path));
	Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "DEFLATE_INIT", NULL);
	Tcl_CloseEx(interp, in, 0);
		"compression init error on \"%s\"", TclGetString(pathObj)));
	ZIPFS_ERROR_CODE(interp, "DEFLATE_INIT");
	Tcl_Close(interp, in);
	Tcl_DStringFree(&zpathDs);
	return TCL_ERROR;
    }

    do {
	len = Tcl_Read(in, buf, bufsize);
	if (len == TCL_IO_FAILURE) {
	if (len < 0) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "read error on %s: %s", path, Tcl_PosixError(interp)));
	    deflateEnd(&stream);
	    Tcl_CloseEx(interp, in, 0);
	    goto readErrorWithChannelOpen;
	    return TCL_ERROR;
	}
	stream.avail_in = len;
	stream.next_in = (unsigned char *) buf;
	flush = Tcl_Eof(in) ? Z_FINISH : Z_NO_FLUSH;
	do {
	    stream.avail_out = sizeof(obuf);
	    stream.next_out = (unsigned char *) obuf;
	    len = deflate(&stream, flush);
	    if (len == (size_t) Z_STREAM_ERROR) {
	    if (len == Z_STREAM_ERROR) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"deflate error on %s", path));
		Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "DEFLATE", NULL);
			"deflate error on \"%s\"", TclGetString(pathObj)));
		ZIPFS_ERROR_CODE(interp, "DEFLATE");
		deflateEnd(&stream);
		Tcl_CloseEx(interp, in, 0);
		Tcl_Close(interp, in);
		Tcl_DStringFree(&zpathDs);
		return TCL_ERROR;
	    }
	    olen = sizeof(obuf) - stream.avail_out;
	    if (passwd) {
		size_t i;
		Tcl_Size i;
		int tmp;

		for (i = 0; i < olen; i++) {
		    obuf[i] = (char) zencode(keys, crc32tab, obuf[i], tmp);
		}
	    }
	    if (olen && (Tcl_Write(out, obuf, olen) != olen)) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"write error: %s", Tcl_PosixError(interp)));
		deflateEnd(&stream);
		Tcl_CloseEx(interp, in, 0);
		return TCL_ERROR;
		goto writeErrorWithChannelOpen;
	    }
	    nbytecompr += olen;
	} while (stream.avail_out == 0);
    } while (flush != Z_FINISH);
    deflateEnd(&stream);

    /*
     * Work out where we've got to.
     */

    Tcl_Flush(out);
    pos[1] = Tcl_Tell(out);
    dataEndOffset = Tcl_Tell(out);

    if (nbyte - nbytecompr <= 0) {
	/*
	 * Compressed file larger than input, write it again uncompressed.
	 */

	if (Tcl_Seek(in, 0, SEEK_SET) != 0) {
	    goto seekErr;
	}
	if (Tcl_Seek(out, pos[2], SEEK_SET) != pos[2]) {
	if (Tcl_Seek(out, dataStartOffset, SEEK_SET) != dataStartOffset) {
	seekErr:
	    Tcl_CloseEx(interp, in, 0);
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "seek error: %s", Tcl_PosixError(interp)));
	    Tcl_Close(interp, in);
	    Tcl_DStringFree(&zpathDs);
	    return TCL_ERROR;
	}
	nbytecompr = (passwd ? 12 : 0);
	nbytecompr = (passwd ? ZIP_CRYPT_HDR_LEN : 0);
	while (1) {
	    len = Tcl_Read(in, buf, bufsize);
	    if (len == TCL_IO_FAILURE) {
	    if (len < 0) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"read error on \"%s\": %s",
			path, Tcl_PosixError(interp)));
		goto readErrorWithChannelOpen;
		Tcl_CloseEx(interp, in, 0);
		return TCL_ERROR;
	    } else if (len == 0) {
		break;
	    }
	    if (passwd) {
		size_t i;
		Tcl_Size i;
		int tmp;

		for (i = 0; i < len; i++) {
		    buf[i] = (char) zencode(keys0, crc32tab, buf[i], tmp);
		}
	    }
	    if (Tcl_Write(out, buf, len) != len) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"write error: %s", Tcl_PosixError(interp)));
		goto writeErrorWithChannelOpen;
		Tcl_CloseEx(interp, in, 0);
		return TCL_ERROR;
	    }
	    nbytecompr += len;
	}
	compMeth = ZIP_COMPMETH_STORED;

	/*
	 * Chop off everything after this; it's the over-large compressed data
	 * and we don't know if it is going to get overwritten otherwise.
	 */

	Tcl_Flush(out);
	pos[1] = Tcl_Tell(out);
	Tcl_TruncateChannel(out, pos[1]);
	dataEndOffset = Tcl_Tell(out);
	Tcl_TruncateChannel(out, dataEndOffset);
    }
    Tcl_CloseEx(interp, in, 0);
    Tcl_Close(interp, in);
    Tcl_DStringFree(&zpathDs);
    zpathExt = NULL;

    hPtr = Tcl_CreateHashEntry(fileHash, zpath, &isNew);
    hPtr = Tcl_CreateHashEntry(fileHash, zpathTcl, &isNew);
    if (!isNew) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"non-unique path name \"%s\"", path));
	Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "DUPLICATE_PATH", NULL);
		"non-unique path name \"%s\"", TclGetString(pathObj)));
	ZIPFS_ERROR_CODE(interp, "DUPLICATE_PATH");
	return TCL_ERROR;
    }

    /*
     * Remember that we've written the file (for central directory generation)
     * and generate the local (per-file) header in the space that we reserved
     * earlier.
     */
    z = (ZipEntry *)Tcl_Alloc(sizeof(ZipEntry));

    z = AllocateZipEntry();
    Tcl_SetHashValue(hPtr, z);
    z->name = NULL;
    z->tnext = NULL;
    z->depth = 0;
    z->zipFilePtr = NULL;
    z->isDirectory = 0;
    z->isEncrypted = (passwd ? 1 : 0);
    z->offset = pos[0];
    z->offset = headerStartOffset;
    z->crc32 = crc;
    z->timestamp = mtime;
    z->numBytes = nbyte;
    z->numCompressedBytes = nbytecompr;
    z->compressMethod = compMeth;
    z->data = NULL;
    z->name = (char *)Tcl_GetHashKey(fileHash, hPtr);
    z->name = (char *) Tcl_GetHashKey(fileHash, hPtr);
    z->next = NULL;

    /*
     * Write final local header information.
     */
    ZipWriteInt(buf + ZIP_LOCAL_SIG_OFFS, ZIP_LOCAL_HEADER_SIG);
    ZipWriteShort(buf + ZIP_LOCAL_VERSION_OFFS, ZIP_MIN_VERSION);

    SerializeLocalEntryHeader(start, end, (unsigned char *) buf, z,
    ZipWriteShort(buf + ZIP_LOCAL_FLAGS_OFFS, z->isEncrypted);
    ZipWriteShort(buf + ZIP_LOCAL_COMPMETH_OFFS, z->compressMethod);
    ZipWriteShort(buf + ZIP_LOCAL_MTIME_OFFS, ToDosTime(z->timestamp));
    ZipWriteShort(buf + ZIP_LOCAL_MDATE_OFFS, ToDosDate(z->timestamp));
    ZipWriteInt(buf + ZIP_LOCAL_CRC32_OFFS, z->crc32);
    ZipWriteInt(buf + ZIP_LOCAL_COMPLEN_OFFS, z->numCompressedBytes);
    ZipWriteInt(buf + ZIP_LOCAL_UNCOMPLEN_OFFS, z->numBytes);
    ZipWriteShort(buf + ZIP_LOCAL_PATHLEN_OFFS, zpathlen);
    ZipWriteShort(buf + ZIP_LOCAL_EXTRALEN_OFFS, align);
    if (Tcl_Seek(out, pos[0], SEEK_SET) != pos[0]) {
	    zpathlen, align);
    if (Tcl_Seek(out, headerStartOffset, SEEK_SET) != headerStartOffset) {
	Tcl_DeleteHashEntry(hPtr);
	Tcl_Free(z);
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"seek error: %s", Tcl_PosixError(interp)));
	return TCL_ERROR;
    }
    if (Tcl_Write(out, buf, ZIP_LOCAL_HEADER_LEN) != ZIP_LOCAL_HEADER_LEN) {
	Tcl_DeleteHashEntry(hPtr);
	Tcl_Free(z);
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"write error: %s", Tcl_PosixError(interp)));
	return TCL_ERROR;
    }
    Tcl_Flush(out);
    if (Tcl_Seek(out, pos[1], SEEK_SET) != pos[1]) {
    if (Tcl_Seek(out, dataEndOffset, SEEK_SET) != dataEndOffset) {
	Tcl_DeleteHashEntry(hPtr);
	Tcl_Free(z);
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"seek error: %s", Tcl_PosixError(interp)));
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSFind --
 *
 *	Worker for ZipFSMkZipOrImg() that discovers the list of files to add.
 *	Simple wrapper around [zipfs find].
 *
 *-------------------------------------------------------------------------
 */

static Tcl_Obj *
ZipFSFind(
    Tcl_Interp *interp,
    Tcl_Obj *dirRoot)
{
    Tcl_Obj *cmd[2];
    int result;

    cmd[0] = Tcl_NewStringObj("::tcl::zipfs::find", -1);
    cmd[1] = dirRoot;
    Tcl_IncrRefCount(cmd[0]);
    result = Tcl_EvalObjv(interp, 2, cmd, 0);
    Tcl_DecrRefCount(cmd[0]);
    if (result != TCL_OK) {
	return NULL;
    }
    return Tcl_GetObjResult(interp);
}

/*
 *-------------------------------------------------------------------------
 *
 * ComputeNameInArchive --
 *
 *	Helper for ZipFSMkZipOrImg() that computes what the actual name of a
 *	file in the ZIP archive should be, stripping a prefix (if appropriate)
 *	and any leading slashes. If the result is an empty string, the entry
 *	should be skipped.
 *
 * Returns:
 *	Pointer to the name (in Tcl's internal encoding), which will be in
 *	memory owned by one of the argument objects.
 *
 * Side effects:
 *	None (if Tcl_Objs have string representations)
 *
 *-------------------------------------------------------------------------
 */

static inline const char *
ComputeNameInArchive(
    Tcl_Obj *pathObj,		/* The path to the origin file */
    Tcl_Obj *directNameObj,	/* User-specified name for use in the ZIP
				 * archive */
    const char *strip,		/* A prefix to strip; may be NULL if no
				 * stripping need be done. */
    Tcl_Size slen)			/* The length of the prefix; must be 0 if no
				 * stripping need be done. */
{
    const char *name;
    Tcl_Size len;

    if (directNameObj) {
	name = TclGetString(directNameObj);
    } else {
	name = TclGetStringFromObj(pathObj, &len);
	if (slen > 0) {
	    if ((len <= slen) || (strncmp(strip, name, slen) != 0)) {
		/*
		 * Guaranteed to be a NUL at the end, which will make this
		 * entry be skipped.
		 */

		return name + len;
	    }
	    name += slen;
	}
    }
    while (name[0] == '/') {
	++name;
    }
    return name;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSMkZipOrImgObjCmd --
 * ZipFSMkZipOrImg --
 *
 *	This procedure is creates a new ZIP archive file or image file given
 *	output filename, input directory of files to be archived, optional
 *	password, and optional image to be prepended to the output ZIP archive
 *	file.
 *	file. It's the core of the implementation of [zipfs mkzip], [zipfs
 *	mkimg], [zipfs lmkzip] and [zipfs lmkimg].
 *
 *	Tcl *always* encodes filenames in the ZIP as UTF-8. Similarly, it
 *	would always encode comments as UTF-8, if it supported comments.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	A new ZIP archive file or image file is written.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMkZipOrImgObjCmd(
ZipFSMkZipOrImg(
    Tcl_Interp *interp,		/* Current interpreter. */
    int isImg,
    int isList,
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
    int isImg,			/* Are we making an image? */
    Tcl_Obj *targetFile,	/* What file are we making? */
    Tcl_Obj *dirRoot,		/* What directory do we take files from? Do
				 * not specify at the same time as
				 * mappingList (one must be NULL). */
    Tcl_Obj *mappingList,	/* What files are we putting in, and with what
				 * names? Do not specify at the same time as
				 * dirRoot (one must be NULL). */
    Tcl_Obj *originFile,	/* If we're making an image, what file does
				 * the non-ZIP part of the image come from? */
    Tcl_Obj *stripPrefix,	/* Are we going to strip a prefix from
				 * filenames found beneath dirRoot? If NULL,
				 * do not strip anything (except for dirRoot
				 * itself). */
    Tcl_Obj *passwordObj)	/* The password for encoding things. NULL if
				 * there's no password protection. */
{
    Tcl_Channel out;
    int pwlen = 0, count, ret = TCL_ERROR, lobjc;
    size_t len, slen = 0, i = 0;
    Tcl_WideInt pos[3];
    Tcl_Obj **lobjv, *list = NULL;
    int count, ret = TCL_ERROR;
    Tcl_Size pwlen = 0, slen = 0, len, i = 0;
    Tcl_Size lobjc;
    long long directoryStartOffset;
    /* The overall file offset of the start of the
     * central directory. */
    long long suffixStartOffset;/* The overall file offset of the start of the
				 * suffix of the central directory (i.e.,
				 * where this data will be written). */
    Tcl_Obj **lobjv, *list = mappingList;
    ZipEntry *z;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    Tcl_HashTable fileHash;
    char *strip = NULL, *pw = NULL, passBuf[264], buf[4096];
    unsigned char *start = (unsigned char *) buf;
    unsigned char *end = start + sizeof(buf);

    /*
     * Caller has verified that the number of arguments is correct.
     */

    passBuf[0] = 0;
    if (objc > (isList ? 3 : 4)) {
	pw = TclGetString(objv[isList ? 3 : 4]);
    if (passwordObj != NULL) {
	pw = TclGetStringFromObj(passwordObj, &pwlen);
	pwlen = strlen(pw);
	if ((pwlen > 255) || strchr(pw, 0xff)) {
	    Tcl_SetObjResult(interp,
	if (IsPasswordValid(interp, pw, pwlen) != TCL_OK) {
		    Tcl_NewStringObj("illegal password", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "BAD_PASS", NULL);
	    return TCL_ERROR;
	}
	if (pwlen == 0) {
	    pw = NULL;
    }
	}
    if (isList) {
	list = objv[2];
	Tcl_IncrRefCount(list);
    } else {
	Tcl_Obj *cmd[3];

    }
	cmd[1] = Tcl_NewStringObj("::tcl::zipfs::find", -1);
	cmd[2] = objv[2];
    if (dirRoot != NULL) {
	cmd[0] = Tcl_NewListObj(2, cmd + 1);
	Tcl_IncrRefCount(cmd[0]);
	if (Tcl_EvalObjEx(interp, cmd[0], TCL_EVAL_DIRECT) != TCL_OK) {
	list = ZipFSFind(interp, dirRoot);
	    Tcl_DecrRefCount(cmd[0]);
	if (!list) {
	    return TCL_ERROR;
	}
	Tcl_DecrRefCount(cmd[0]);
	list = Tcl_GetObjResult(interp);
	Tcl_IncrRefCount(list);
    }
    Tcl_IncrRefCount(list);
    if (Tcl_ListObjGetElements(interp, list, &lobjc, &lobjv) != TCL_OK) {
    if (TclListObjLength(interp, list, &lobjc) != TCL_OK) {
	Tcl_DecrRefCount(list);
	return TCL_ERROR;
    }
    if (isList && (lobjc % 2)) {
    if (mappingList && (lobjc % 2)) {
	Tcl_DecrRefCount(list);
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("need even number of elements", -1));
	Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "LIST_LENGTH", NULL);
	ZIPFS_ERROR(interp, "need even number of elements");
	ZIPFS_ERROR_CODE(interp, "LIST_LENGTH");
	return TCL_ERROR;
    }
    if (lobjc == 0) {
	Tcl_DecrRefCount(list);
	Tcl_SetObjResult(interp, Tcl_NewStringObj("empty archive", -1));
	Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "EMPTY", NULL);
	ZIPFS_ERROR(interp, "empty archive");
	ZIPFS_ERROR_CODE(interp, "EMPTY");
	return TCL_ERROR;
    }
    if (TclListObjGetElements(interp, list, &lobjc, &lobjv) != TCL_OK) {
	Tcl_DecrRefCount(list);
	return TCL_ERROR;
    }
    out = Tcl_OpenFileChannel(interp, TclGetString(objv[1]), "wb", 0755);
    out = Tcl_FSOpenFileChannel(interp, targetFile, "wb", 0755);
    if (out == NULL) {
	Tcl_DecrRefCount(list);
	return TCL_ERROR;
    }
    if (pwlen <= 0) {

	pw = NULL;
	pwlen = 0;
    }
    /*
     * Copy the existing contents from the image if it is an executable image.
     * Care must be taken because this might include an existing ZIP, which
     * needs to be stripped.
     */

    if (isImg) {
	ZipFile *zf, zf0;
	int isMounted = 0;
	const char *imgName;

	if (isList) {
	    imgName = (objc > 4) ? TclGetString(objv[4]) :
		    Tcl_GetNameOfExecutable();
	// TODO: normalize the origin file name
	imgName = (originFile != NULL) ? TclGetString(originFile) :
		Tcl_GetNameOfExecutable();
	} else {
	    imgName = (objc > 5) ? TclGetString(objv[5]) :
		    Tcl_GetNameOfExecutable();
	}
	if (pwlen) {
	    i = 0;
	    for (len = pwlen; len-- > 0;) {
		int ch = pw[len];

		passBuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f];
		i++;
2497
2498
2499
2500
2501
2502
2503
2504

2505
2506
2507
2508
2509
2510
2511

2512
2513

2514
2515




2516

2517
2518
2519
2520
2521
2522

2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551

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
3451
3452
3453
3454
3455
3456
3457

3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475

3476
3477
3478
3479
3480
3481

3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499





3500
3501
3502
3503
3504


3505

3506
3507

3508
3509
3510











3511






3512















3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523

3524
3525
3526
3527
3528
3529
3530






3531


3532
3533
3534
3535



3536
3537
3538




3539
3540



3541


3542




3543
3544
3545
3546
3547
3548
3549
3550

3551
3552
3553
3554
3555
3556
3557
3558
3559
3560

3561
3562




3563
3564
3565
3566









3567









3568
3569
3570
3571





3572
3573
3574
3575
3576




3577
3578
3579
3580




3581









3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598

3599




3600
3601




3602
3603
3604
3605
3606
3607
3608
3609
3610
3611

3612
3613

3614
3615
3616
3617
3618

3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817

3818
3819
3820
3821
3822
3823

3824
3825
3826
3827
3828
3829
3830

3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842



3843
3844
3845
3846
3847
3848
3849

3850
3851
3852
3853
3854
3855

3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867



3868
3869
3870
3871
3872
3873

3874
3875
3876
3877
3878
3879
3880
3881
3882
3883

3884
3885
3886
3887
3888
3889

3890
3891
3892
3893
3894
3895
3896

3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909



3910
3911
3912
3913
3914
3915
3916
3917

3918
3919
3920
3921
3922
3923

3924
3925
3926
3927
3928
3929
3930
3931

3932
3933
3934
3935



3936
3937
3938
3939
3940
3941
3942

3943
3944
3945
3946
3947
3948
3949
3950
3951







-
+







+


+


+
+
+
+
-
+





-
+

















-
-
-
-
-





-
-
+
-


-
+


-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+







-
+






-
-
-
-
-
-
+
-
-
+
+
+

-
-
-
+
+
+
-
-
-
-
+
+
-
-
-
+
-
-
+
-
-
-
-
+
+
+
+
+



-
+




+
+
+
+
+
-
+

-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-




-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+


+


+


+
+
+
+
+

-
+
-
-
-
-
+
+
-
-
-
-










-
+

-
+




-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+





-
+






-
+




+
+





-
-
-
+
+


+
+
+
-
+
+




-
+




+
+





-
-
-
+
+


+
+
-
+
+








-
+





-
+






-
+




+
+






-
-
-
+
+


+
+
+
+
-
+
+




-
+




+
+

-
+



-
-
-
+
+


+
+
+
-
+
+







	/*
	 * Check for mounted image.
	 */

	WriteLock();
	for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
		hPtr = Tcl_NextHashEntry(&search)) {
	    zf = (ZipFile *)Tcl_GetHashValue(hPtr);
	    zf = (ZipFile *) Tcl_GetHashValue(hPtr);
	    if (strcmp(zf->name, imgName) == 0) {
		isMounted = 1;
		zf->numOpen++;
		break;
	    }
	}
	Unlock();

	if (!isMounted) {
	    zf = &zf0;
	    memset(&zf0, 0, sizeof(ZipFile));
	}
	if (isMounted || ZipFSOpenArchive(interp, imgName, 0, zf) == TCL_OK) {
	    /*
	     * Copy everything up to the ZIP-related suffix.
	     */

	    if (Tcl_Write(out, (char *) zf->data,
	    if ((size_t)Tcl_Write(out, (char *) zf->data,
		    zf->passOffset) != zf->passOffset) {
		memset(passBuf, 0, sizeof(passBuf));
		Tcl_DecrRefCount(list);
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"write error: %s", Tcl_PosixError(interp)));
		Tcl_CloseEx(interp, out, 0);
		Tcl_Close(interp, out);
		if (zf == &zf0) {
		    ZipFSCloseArchive(interp, zf);
		} else {
		    WriteLock();
		    zf->numOpen--;
		    Unlock();
		}
		return TCL_ERROR;
	    }
	    if (zf == &zf0) {
		ZipFSCloseArchive(interp, zf);
	    } else {
		WriteLock();
		zf->numOpen--;
		Unlock();
	    }
	} else {
	    size_t k;
	    int m, n;
	    Tcl_Channel in;
	    const char *errMsg = "seek error";

	    /*
	     * Fall back to read it as plain file which hopefully is a static
	     * tclsh or wish binary with proper zipfs infrastructure built in.
	     */

	    Tcl_ResetResult(interp);
	    in = Tcl_OpenFileChannel(interp, imgName, "rb", 0644);
	    if (CopyImageFile(interp, imgName, out) != TCL_OK) {
	    if (!in) {
		memset(passBuf, 0, sizeof(passBuf));
		Tcl_DecrRefCount(list);
		Tcl_CloseEx(interp, out, 0);
		Tcl_Close(interp, out);
		return TCL_ERROR;
	    }
	    i = Tcl_Seek(in, 0, SEEK_END);
	    if (i == TCL_IO_FAILURE) {
	    cperr:
		memset(passBuf, 0, sizeof(passBuf));
		Tcl_DecrRefCount(list);
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"%s: %s", errMsg, Tcl_PosixError(interp)));
		Tcl_CloseEx(interp, out, 0);
		Tcl_CloseEx(interp, in, 0);
		return TCL_ERROR;
	    }
	}
	    Tcl_Seek(in, 0, SEEK_SET);
	    for (k = 0; k < i; k += m) {
		m = i - k;
		if (m > (int) sizeof(buf)) {
		    m = (int) sizeof(buf);
		}

		n = Tcl_Read(in, buf, m);
		if (n == -1) {
		    errMsg = "read error";
		    goto cperr;
		} else if (n == 0) {
		    break;
		}
		m = Tcl_Write(out, buf, n);
		if (m != n) {
		    errMsg = "write error";
		    goto cperr;
		}
	    }
	    Tcl_CloseEx(interp, in, 0);
	}
	/*
	 * Store the password so that the automounter can find it.
	 */

	len = strlen(passBuf);
	if (len > 0) {
	    i = Tcl_Write(out, passBuf, len);
	    if (i != len) {
		Tcl_DecrRefCount(list);
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"write error: %s", Tcl_PosixError(interp)));
		Tcl_CloseEx(interp, out, 0);
		Tcl_Close(interp, out);
		return TCL_ERROR;
	    }
	}
	memset(passBuf, 0, sizeof(passBuf));
	Tcl_Flush(out);
    }
    Tcl_InitHashTable(&fileHash, TCL_STRING_KEYS);
    pos[0] = Tcl_Tell(out);
    if (!isList && (objc > 3)) {
	strip = TclGetString(objv[3]);
	slen = strlen(strip);
    }

    for (i = 0; i < (size_t) lobjc; i += (isList ? 2 : 1)) {
	const char *path, *name;
    /*
     * Prepare the contents of the ZIP archive.
     */

	path = TclGetString(lobjv[i]);
	if (isList) {
	    name = TclGetString(lobjv[i + 1]);
    Tcl_InitHashTable(&fileHash, TCL_STRING_KEYS);
    if (mappingList == NULL && stripPrefix != NULL) {
	strip = TclGetStringFromObj(stripPrefix, &slen);
	} else {
	    name = path;
	    if (slen > 0) {
		len = strlen(name);
	if (!slen) {
	    strip = NULL;
		if ((len <= slen) || (strncmp(strip, name, slen) != 0)) {
		    continue;
		}
	}
		name += slen;
	    }
    }
	}
	while (name[0] == '/') {
	    ++name;
	}
    for (i = 0; i < lobjc; i += (mappingList ? 2 : 1)) {
	Tcl_Obj *pathObj = lobjv[i];
	const char *name = ComputeNameInArchive(pathObj,
		(mappingList ? lobjv[i + 1] : NULL), strip, slen);

	if (name[0] == '\0') {
	    continue;
	}
	if (ZipAddFile(interp, path, name, out, pw, buf, sizeof(buf),
	if (ZipAddFile(interp, pathObj, name, out, pw, buf, sizeof(buf),
		&fileHash) != TCL_OK) {
	    goto done;
	}
    }

    /*
     * Construct the contents of the ZIP central directory.
     */

    pos[1] = Tcl_Tell(out);
    directoryStartOffset = Tcl_Tell(out);
    count = 0;
    for (i = 0; i < (size_t) lobjc; i += (isList ? 2 : 1)) {
	const char *path, *name;

	path = TclGetString(lobjv[i]);
    for (i = 0; i < lobjc; i += (mappingList ? 2 : 1)) {
	const char *name = ComputeNameInArchive(lobjv[i],
		(mappingList ? lobjv[i + 1] : NULL), strip, slen);
	Tcl_DString ds;
	if (isList) {
	    name = TclGetString(lobjv[i + 1]);
	} else {
	    name = path;
	    if (slen > 0) {
		len = strlen(name);
		if ((len <= slen) || (strncmp(strip, name, slen) != 0)) {
		    continue;
		}

		name += slen;
	    }
	}
	while (name[0] == '/') {
	    ++name;
	}
	if (name[0] == '\0') {
	    continue;
	}
	hPtr = Tcl_FindHashEntry(&fileHash, name);
	if (!hPtr) {
	    continue;
	}
	z = (ZipEntry *)Tcl_GetHashValue(hPtr);
	len = strlen(z->name);
	ZipWriteInt(buf + ZIP_CENTRAL_SIG_OFFS, ZIP_CENTRAL_HEADER_SIG);
	ZipWriteShort(buf + ZIP_CENTRAL_VERSIONMADE_OFFS, ZIP_MIN_VERSION);
	ZipWriteShort(buf + ZIP_CENTRAL_VERSION_OFFS, ZIP_MIN_VERSION);
	z = (ZipEntry *) Tcl_GetHashValue(hPtr);

	if (Tcl_UtfToExternalDStringEx(interp, tclUtf8Encoding, z->name, TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	    ret = TCL_ERROR;
	    goto done;
	ZipWriteShort(buf + ZIP_CENTRAL_FLAGS_OFFS, z->isEncrypted);
	ZipWriteShort(buf + ZIP_CENTRAL_COMPMETH_OFFS, z->compressMethod);
	ZipWriteShort(buf + ZIP_CENTRAL_MTIME_OFFS, ToDosTime(z->timestamp));
	ZipWriteShort(buf + ZIP_CENTRAL_MDATE_OFFS, ToDosDate(z->timestamp));
	}
	name = Tcl_DStringValue(&ds);
	len = Tcl_DStringLength(&ds);
	SerializeCentralDirectoryEntry(start, end, (unsigned char *) buf,
	ZipWriteInt(buf + ZIP_CENTRAL_CRC32_OFFS, z->crc32);
	ZipWriteInt(buf + ZIP_CENTRAL_COMPLEN_OFFS, z->numCompressedBytes);
	ZipWriteInt(buf + ZIP_CENTRAL_UNCOMPLEN_OFFS, z->numBytes);
	ZipWriteShort(buf + ZIP_CENTRAL_PATHLEN_OFFS, len);
		z, len);
	ZipWriteShort(buf + ZIP_CENTRAL_EXTRALEN_OFFS, 0);
	ZipWriteShort(buf + ZIP_CENTRAL_FCOMMENTLEN_OFFS, 0);
	ZipWriteShort(buf + ZIP_CENTRAL_DISKFILE_OFFS, 0);
	ZipWriteShort(buf + ZIP_CENTRAL_IATTR_OFFS, 0);
	ZipWriteInt(buf + ZIP_CENTRAL_EATTR_OFFS, 0);
	ZipWriteInt(buf + ZIP_CENTRAL_LOCALHDR_OFFS, z->offset - pos[0]);
	if ((Tcl_Write(out, buf,
		    ZIP_CENTRAL_HEADER_LEN) != ZIP_CENTRAL_HEADER_LEN)
		|| (Tcl_Write(out, z->name, len) != len)) {
	if ((Tcl_Write(out, buf, ZIP_CENTRAL_HEADER_LEN)
		!= ZIP_CENTRAL_HEADER_LEN)
		|| (Tcl_Write(out, name, len) != len)) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "write error: %s", Tcl_PosixError(interp)));
	    Tcl_DStringFree(&ds);
	    goto done;
	}
	Tcl_DStringFree(&ds);
	count++;
    }

    /*
     * Finalize the central directory.
     */

    Tcl_Flush(out);
    pos[2] = Tcl_Tell(out);
    suffixStartOffset = Tcl_Tell(out);
    ZipWriteInt(buf + ZIP_CENTRAL_END_SIG_OFFS, ZIP_CENTRAL_END_SIG);
    ZipWriteShort(buf + ZIP_CENTRAL_DISKNO_OFFS, 0);
    ZipWriteShort(buf + ZIP_CENTRAL_DISKDIR_OFFS, 0);
    ZipWriteShort(buf + ZIP_CENTRAL_ENTS_OFFS, count);
    SerializeCentralDirectorySuffix(start, end, (unsigned char *) buf,
	    count, directoryStartOffset, suffixStartOffset);
    ZipWriteShort(buf + ZIP_CENTRAL_TOTALENTS_OFFS, count);
    ZipWriteInt(buf + ZIP_CENTRAL_DIRSIZE_OFFS, pos[2] - pos[1]);
    ZipWriteInt(buf + ZIP_CENTRAL_DIRSTART_OFFS, pos[1] - pos[0]);
    ZipWriteShort(buf + ZIP_CENTRAL_COMMENTLEN_OFFS, 0);
    if (Tcl_Write(out, buf, ZIP_CENTRAL_END_LEN) != ZIP_CENTRAL_END_LEN) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"write error: %s", Tcl_PosixError(interp)));
	goto done;
    }
    Tcl_Flush(out);
    ret = TCL_OK;

  done:
    if (ret == TCL_OK) {
	ret = Tcl_CloseEx(interp, out, 0);
	ret = Tcl_Close(interp, out);
    } else {
	Tcl_CloseEx(interp, out, 0);
	Tcl_Close(interp, out);
    }
    Tcl_DecrRefCount(list);
    for (hPtr = Tcl_FirstHashEntry(&fileHash, &search); hPtr;
	    hPtr = Tcl_NextHashEntry(&search)) {
	z = (ZipEntry *)Tcl_GetHashValue(hPtr);
	z = (ZipEntry *) Tcl_GetHashValue(hPtr);
	Tcl_Free(z);
	Tcl_DeleteHashEntry(hPtr);
    }
    Tcl_DeleteHashTable(&fileHash);
    return ret;
}

/*
 * ---------------------------------------------------------------------
 *
 * CopyImageFile --
 *
 *	A simple file copy function that is used (by ZipFSMkZipOrImg) for
 *	anything that is not an image with a ZIP appended.
 *
 * Returns:
 *	A Tcl result code.
 *
 * Side effects:
 *	Writes to an output channel.
 *
 * ---------------------------------------------------------------------
 */

static int
CopyImageFile(
    Tcl_Interp *interp,		/* For error reporting. */
    const char *imgName,	/* Where to copy from. */
    Tcl_Channel out)		/* Where to copy to; already open for writing
				 * binary data. */
{
    Tcl_WideInt i, k;
    Tcl_Size m, n;
    Tcl_Channel in;
    char buf[4096];
    const char *errMsg;

    Tcl_ResetResult(interp);
    in = Tcl_OpenFileChannel(interp, imgName, "rb", 0644);
    if (!in) {
	return TCL_ERROR;
    }

    /*
     * Get the length of the file (and exclude non-files).
     */

    i = Tcl_Seek(in, 0, SEEK_END);
    if (i == -1) {
	errMsg = "seek error";
	goto copyError;
    }
    Tcl_Seek(in, 0, SEEK_SET);

    /*
     * Copy the whole file, 8 blocks at a time (reasonably efficient). Note
     * that this totally ignores things like Windows's Alternate File Streams.
     */

    for (k = 0; k < i; k += m) {
	m = i - k;
	if (m > (Tcl_Size) sizeof(buf)) {
	    m = sizeof(buf);
	}
	n = Tcl_Read(in, buf, m);
	if (n == -1) {
	    errMsg = "read error";
	    goto copyError;
	} else if (n == 0) {
	    break;
	}
	m = Tcl_Write(out, buf, n);
	if (m != n) {
	    errMsg = "write error";
	    goto copyError;
	}
    }
    Tcl_Close(interp, in);
    return TCL_OK;

  copyError:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "%s: %s", errMsg, Tcl_PosixError(interp)));
    Tcl_Close(interp, in);
    return TCL_ERROR;
}

/*
 * ---------------------------------------------------------------------
 *
 * SerializeLocalEntryHeader, SerializeCentralDirectoryEntry,
 * SerializeCentralDirectorySuffix --
 *
 *	Create serialized forms of the structures that make up the ZIP
 *	metadata. Note that the both the local entry and the central directory
 *	entry need to have the name of the entry written directly afterwards.
 *
 *	We could write these as structs except we need to guarantee that we
 *	are writing these out as little-endian values.
 *
 * Side effects:
 *	Both update their buffer arguments, but otherwise change nothing.
 *
 * ---------------------------------------------------------------------
 */

static void
SerializeLocalEntryHeader(
    const unsigned char *start,	/* The start of writable memory. */
    const unsigned char *end,	/* The end of writable memory. */
    unsigned char *buf,		/* Where to serialize to */
    ZipEntry *z,		/* The description of what to serialize. */
    int nameLength,		/* The length of the name. */
    int align)			/* The number of alignment bytes. */
{
    ZipWriteInt(start, end, buf + ZIP_LOCAL_SIG_OFFS, ZIP_LOCAL_HEADER_SIG);
    ZipWriteShort(start, end, buf + ZIP_LOCAL_VERSION_OFFS, ZIP_MIN_VERSION);
    ZipWriteShort(start, end, buf + ZIP_LOCAL_FLAGS_OFFS, z->isEncrypted + ZIP_LOCAL_FLAGS_UTF8);
    ZipWriteShort(start, end, buf + ZIP_LOCAL_COMPMETH_OFFS,
	    z->compressMethod);
    ZipWriteShort(start, end, buf + ZIP_LOCAL_MTIME_OFFS,
	    ToDosTime(z->timestamp));
    ZipWriteShort(start, end, buf + ZIP_LOCAL_MDATE_OFFS,
	    ToDosDate(z->timestamp));
    ZipWriteInt(start, end, buf + ZIP_LOCAL_CRC32_OFFS, z->crc32);
    ZipWriteInt(start, end, buf + ZIP_LOCAL_COMPLEN_OFFS,
	    z->numCompressedBytes);
    ZipWriteInt(start, end, buf + ZIP_LOCAL_UNCOMPLEN_OFFS, z->numBytes);
    ZipWriteShort(start, end, buf + ZIP_LOCAL_PATHLEN_OFFS, nameLength);
    ZipWriteShort(start, end, buf + ZIP_LOCAL_EXTRALEN_OFFS, align);
}

static void
SerializeCentralDirectoryEntry(
    const unsigned char *start,	/* The start of writable memory. */
    const unsigned char *end,	/* The end of writable memory. */
    unsigned char *buf,		/* Where to serialize to */
    ZipEntry *z,		/* The description of what to serialize. */
    size_t nameLength)		/* The length of the name. */
{
    ZipWriteInt(start, end, buf + ZIP_CENTRAL_SIG_OFFS,
	    ZIP_CENTRAL_HEADER_SIG);
    ZipWriteShort(start, end, buf + ZIP_CENTRAL_VERSIONMADE_OFFS,
	    ZIP_MIN_VERSION);
    ZipWriteShort(start, end, buf + ZIP_CENTRAL_VERSION_OFFS, ZIP_MIN_VERSION);
    ZipWriteShort(start, end, buf + ZIP_CENTRAL_FLAGS_OFFS, z->isEncrypted + ZIP_LOCAL_FLAGS_UTF8);
    ZipWriteShort(start, end, buf + ZIP_CENTRAL_COMPMETH_OFFS,
	    z->compressMethod);
    ZipWriteShort(start, end, buf + ZIP_CENTRAL_MTIME_OFFS,
	    ToDosTime(z->timestamp));
    ZipWriteShort(start, end, buf + ZIP_CENTRAL_MDATE_OFFS,
	    ToDosDate(z->timestamp));
    ZipWriteInt(start, end, buf + ZIP_CENTRAL_CRC32_OFFS, z->crc32);
    ZipWriteInt(start, end, buf + ZIP_CENTRAL_COMPLEN_OFFS,
	    z->numCompressedBytes);
    ZipWriteInt(start, end, buf + ZIP_CENTRAL_UNCOMPLEN_OFFS, z->numBytes);
    ZipWriteShort(start, end, buf + ZIP_CENTRAL_PATHLEN_OFFS, nameLength);
    ZipWriteShort(start, end, buf + ZIP_CENTRAL_EXTRALEN_OFFS, 0);
    ZipWriteShort(start, end, buf + ZIP_CENTRAL_FCOMMENTLEN_OFFS, 0);
    ZipWriteShort(start, end, buf + ZIP_CENTRAL_DISKFILE_OFFS, 0);
    ZipWriteShort(start, end, buf + ZIP_CENTRAL_IATTR_OFFS, 0);
    ZipWriteInt(start, end, buf + ZIP_CENTRAL_EATTR_OFFS, 0);
    ZipWriteInt(start, end, buf + ZIP_CENTRAL_LOCALHDR_OFFS,
	    z->offset);
}

static void
SerializeCentralDirectorySuffix(
    const unsigned char *start,	/* The start of writable memory. */
    const unsigned char *end,	/* The end of writable memory. */
    unsigned char *buf,		/* Where to serialize to */
    int entryCount,		/* The number of entries in the directory */
    long long directoryStartOffset,
				/* The overall file offset of the start of the
				 * central directory. */
    long long suffixStartOffset)/* The overall file offset of the start of the
				 * suffix of the central directory (i.e.,
				 * where this data will be written). */
{
    ZipWriteInt(start, end, buf + ZIP_CENTRAL_END_SIG_OFFS,
	    ZIP_CENTRAL_END_SIG);
    ZipWriteShort(start, end, buf + ZIP_CENTRAL_DISKNO_OFFS, 0);
    ZipWriteShort(start, end, buf + ZIP_CENTRAL_DISKDIR_OFFS, 0);
    ZipWriteShort(start, end, buf + ZIP_CENTRAL_ENTS_OFFS, entryCount);
    ZipWriteShort(start, end, buf + ZIP_CENTRAL_TOTALENTS_OFFS, entryCount);
    ZipWriteInt(start, end, buf + ZIP_CENTRAL_DIRSIZE_OFFS,
	    suffixStartOffset - directoryStartOffset);
    ZipWriteInt(start, end, buf + ZIP_CENTRAL_DIRSTART_OFFS,
	    directoryStartOffset);
    ZipWriteShort(start, end, buf + ZIP_CENTRAL_COMMENTLEN_OFFS, 0);
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSMkZipObjCmd, ZipFSLMkZipObjCmd --
 *
 *	These procedures are invoked to process the [zipfs mkzip] and [zipfs
 *	lmkzip] commands.  See description of ZipFSMkZipOrImgCmd().
 *	lmkzip] commands.  See description of ZipFSMkZipOrImg().
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See description of ZipFSMkZipOrImgCmd().
 *	See description of ZipFSMkZipOrImg().
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMkZipObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *stripPrefix, *password;

    if (objc < 3 || objc > 5) {
	Tcl_WrongNumArgs(interp, 1, objv, "outfile indir ?strip? ?password?");
	return TCL_ERROR;
    }
    if (Tcl_IsSafe(interp)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"operation not permitted in a safe interpreter", -1));
	Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "SAFE_INTERP", NULL);
	ZIPFS_ERROR(interp, "operation not permitted in a safe interpreter");
	ZIPFS_ERROR_CODE(interp, "SAFE_INTERP");
	return TCL_ERROR;
    }

    stripPrefix = (objc > 3 ? objv[3] : NULL);
    password = (objc > 4 ? objv[4] : NULL);
    return ZipFSMkZipOrImgObjCmd(interp, 0, 0, objc, objv);
    return ZipFSMkZipOrImg(interp, 0, objv[1], objv[2], NULL, NULL,
	    stripPrefix, password);
}

static int
ZipFSLMkZipObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *password;

    if (objc < 3 || objc > 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "outfile inlist ?password?");
	return TCL_ERROR;
    }
    if (Tcl_IsSafe(interp)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"operation not permitted in a safe interpreter", -1));
	Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "SAFE_INTERP", NULL);
	ZIPFS_ERROR(interp, "operation not permitted in a safe interpreter");
	ZIPFS_ERROR_CODE(interp, "SAFE_INTERP");
	return TCL_ERROR;
    }

    password = (objc > 3 ? objv[3] : NULL);
    return ZipFSMkZipOrImgObjCmd(interp, 0, 1, objc, objv);
    return ZipFSMkZipOrImg(interp, 0, objv[1], NULL, objv[2], NULL,
	    NULL, password);
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSMkImgObjCmd, ZipFSLMkImgObjCmd --
 *
 *	These procedures are invoked to process the [zipfs mkimg] and [zipfs
 *	lmkimg] commands.  See description of ZipFSMkZipOrImgCmd().
 *	lmkimg] commands.  See description of ZipFSMkZipOrImg().
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See description of ZipFSMkZipOrImgCmd().
 *	See description of ZipFSMkZipOrImg().
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMkImgObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *originFile, *stripPrefix, *password;

    if (objc < 3 || objc > 6) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"outfile indir ?strip? ?password? ?infile?");
	return TCL_ERROR;
    }
    if (Tcl_IsSafe(interp)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"operation not permitted in a safe interpreter", -1));
	Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "SAFE_INTERP", NULL);
	ZIPFS_ERROR(interp, "operation not permitted in a safe interpreter");
	ZIPFS_ERROR_CODE(interp, "SAFE_INTERP");
	return TCL_ERROR;
    }

    originFile = (objc > 5 ? objv[5] : NULL);
    stripPrefix = (objc > 3 ? objv[3] : NULL);
    password = (objc > 4 ? objv[4] : NULL);
    return ZipFSMkZipOrImgObjCmd(interp, 1, 0, objc, objv);
    return ZipFSMkZipOrImg(interp, 1, objv[1], objv[2], NULL,
	    originFile, stripPrefix, password);
}

static int
ZipFSLMkImgObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *originFile, *password;

    if (objc < 3 || objc > 5) {
	Tcl_WrongNumArgs(interp, 1, objv, "outfile inlist ?password infile?");
	Tcl_WrongNumArgs(interp, 1, objv, "outfile inlist ?password? ?infile?");
	return TCL_ERROR;
    }
    if (Tcl_IsSafe(interp)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"operation not permitted in a safe interpreter", -1));
	Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "SAFE_INTERP", NULL);
	ZIPFS_ERROR(interp, "operation not permitted in a safe interpreter");
	ZIPFS_ERROR_CODE(interp, "SAFE_INTERP");
	return TCL_ERROR;
    }

    originFile = (objc > 4 ? objv[4] : NULL);
    password = (objc > 3 ? objv[3] : NULL);
    return ZipFSMkZipOrImgObjCmd(interp, 1, 1, objc, objv);
    return ZipFSMkZipOrImg(interp, 1, objv[1], NULL, objv[2],
	    originFile, NULL, password);
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSCanonicalObjCmd --
 *
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
3959
3960
3961
3962
3963
3964
3965

3966
3967
3968
3969
3970

3971



3972
3973


3974
3975
3976
3977
3978

3979





3980
3981
3982
3983


3984


3985

3986
3987

3988


3989
3990
3991
3992
3993

3994
3995
3996
3997
3998
3999
4000
4001







-
+




-
+
-
-
-
+

-
-
+
+


+
-
+
-
-
-
-
-
+
+
+
+
-
-

-
-
+
-


-
+
-
-

+
+
+
+
-
+







 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSCanonicalObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    char *mntpoint = NULL;
    const char *mntPoint = NULL;
    char *filename = NULL;
    char *result;
    Tcl_DString dPath;
    Tcl_DString dsPath, dsMount;

    if (objc < 2 || objc > 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "?mountpoint? filename ?inZipfs?");
    if (objc < 2 || objc > 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "?mountpoint? filename");
	return TCL_ERROR;
    }

    Tcl_DStringInit(&dPath);
    Tcl_DStringInit(&dsPath);
    if (objc == 2) {
	filename = TclGetString(objv[1]);
	result = CanonicalPath("", filename, &dPath, 1);
    } else if (objc == 3) {
	mntpoint = TclGetString(objv[1]);
    Tcl_DStringInit(&dsMount);

    if (objc == 2) {
	mntPoint = ZIPFS_VOLUME;
	filename = TclGetString(objv[2]);
	result = CanonicalPath(mntpoint, filename, &dPath, 1);
    } else {
	int zipfs = 0;

	if (NormalizeMountPoint(interp, Tcl_GetString(objv[1]), &dsMount) != TCL_OK) {
	if (Tcl_GetBooleanFromObj(interp, objv[3], &zipfs)) {
	    return TCL_ERROR;
	}
	mntpoint = TclGetString(objv[1]);
	mntPoint = Tcl_DStringValue(&dsMount);
	filename = TclGetString(objv[2]);
	result = CanonicalPath(mntpoint, filename, &dPath, zipfs);
    }
    (void)MapPathToZipfs(interp,
			 mntPoint,
			 Tcl_GetString(objv[objc - 1]),
			 &dsPath);
    Tcl_SetObjResult(interp, Tcl_NewStringObj(result, -1));
    Tcl_SetObjResult(interp, Tcl_DStringToObj(&dsPath));
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSExistsObjCmd --
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
4011
4012
4013
4014
4015
4016
4017

4018
4019
4020
4021
4022
4023
4024

4025
4026
4027
4028
4029
4030




4031




4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050

4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066

4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099

4100
4101
4102
4103

4104
4105

4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126

4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148



4149
4150
4151
4152
4153
4154

4155
4156
4157

4158
4159
4160
4161
4162
4163





4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177

4178
4179
4180
4181
4182
4183
4184
4185
4186
4187

4188
4189
4190
4191
4192
4193
4194
4195
4196
4197

4198
4199
4200
4201
4202
4203
4204
4205







-
+






-






-
-
-
-

-
-
-
-



+
+
+
+
+











-
+















-
+






+


















+
+
+
+
+
+
+
-
+
+
+

-
+

-
+




















-
+









+
+
+
+
+
+






-
-
-
+
+
+
+
+
+
-
+
+

-
+
+




-
-
-
-
-
+




+
+
+
+
+




-
+









-
+









-
+







 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSExistsObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    char *filename;
    int exists;
    Tcl_DString ds;

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

    /*
     * Prepend ZIPFS_VOLUME to filename, eliding the final /
     */

    filename = TclGetString(objv[1]);
    Tcl_DStringInit(&ds);
    Tcl_DStringAppend(&ds, ZIPFS_VOLUME, ZIPFS_VOLUME_LEN - 1);
    Tcl_DStringAppend(&ds, filename, -1);
    filename = Tcl_DStringValue(&ds);

    ReadLock();
    exists = ZipFSLookup(filename) != NULL;
    if (!exists) {
	/* An ancestor directory of a file ? */
	exists = ContainsMountPoint(filename, -1);
    }

    Unlock();

    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(exists));
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSInfoObjCmd --
 *
 *	This procedure is invoked to process the [zipfs info] command.	 On
 *	This procedure is invoked to process the [zipfs info] command.  On
 *	success, it returns a Tcl list made up of name of ZIP archive file,
 *	size uncompressed, size compressed, and archive offset of a file in
 *	the ZIP filesystem.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSInfoObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    char *filename;
    ZipEntry *z;
    int ret;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "filename");
	return TCL_ERROR;
    }
    filename = TclGetString(objv[1]);
    ReadLock();
    z = ZipFSLookup(filename);
    if (z) {
	Tcl_Obj *result = Tcl_GetObjResult(interp);

	Tcl_ListObjAppendElement(interp, result,
		Tcl_NewStringObj(z->zipFilePtr->name, -1));
	Tcl_ListObjAppendElement(interp, result,
		Tcl_NewWideIntObj(z->numBytes));
	Tcl_ListObjAppendElement(interp, result,
		Tcl_NewWideIntObj(z->numCompressedBytes));
	Tcl_ListObjAppendElement(interp, result, Tcl_NewWideIntObj(z->offset));
	ret = TCL_OK;
    } else {
	Tcl_SetErrno(ENOENT);
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "path \"%s\" not found in any zipfs volume",
		    filename));
    }
	}
	ret = TCL_ERROR;
    }
    Unlock();
    return TCL_OK;
    return ret;
}


/*
 *-------------------------------------------------------------------------
 *
 * ZipFSListObjCmd --
 *
 *	This procedure is invoked to process the [zipfs list] command.	 On
 *	success, it returns a Tcl list of files of the ZIP filesystem which
 *	match a search pattern (glob or regexp).
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSListObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    char *pattern = NULL;
    Tcl_RegExp regexp = NULL;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    Tcl_Obj *result = Tcl_GetObjResult(interp);
    const char *options[] = {"-glob", "-regexp", NULL};
    enum list_options { OPT_GLOB, OPT_REGEXP };

    /*
     * Parse arguments.
     */

    if (objc > 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "?(-glob|-regexp)? ?pattern?");
	return TCL_ERROR;
    }
    if (objc == 3) {
	size_t n;
	char *what = TclGetStringFromObj(objv[1], &n);

	int idx;

	if (Tcl_GetIndexFromObj(interp, objv[1], options, "option",
		0, &idx) != TCL_OK) {
	    return TCL_ERROR;
	}
	if ((n >= 2) && (strncmp(what, "-glob", n) == 0)) {
	switch (idx) {
	case OPT_GLOB:
	    pattern = TclGetString(objv[2]);
	} else if ((n >= 2) && (strncmp(what, "-regexp", n) == 0)) {
	    break;
	case OPT_REGEXP:
	    regexp = Tcl_RegExpCompile(interp, TclGetString(objv[2]));
	    if (!regexp) {
		return TCL_ERROR;
	    }
	} else {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "unknown option \"%s\"", what));
	    Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "BAD_OPT", NULL);
	    return TCL_ERROR;
	    break;
	}
    } else if (objc == 2) {
	pattern = TclGetString(objv[1]);
    }

    /*
     * Scan for matching entries.
     */

    ReadLock();
    if (pattern) {
	for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search);
		hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
	    ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr);
	    ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr);

	    if (Tcl_StringMatch(z->name, pattern)) {
		Tcl_ListObjAppendElement(interp, result,
			Tcl_NewStringObj(z->name, -1));
	    }
	}
    } else if (regexp) {
	for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search);
		hPtr; hPtr = Tcl_NextHashEntry(&search)) {
	    ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr);
	    ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr);

	    if (Tcl_RegExpExec(interp, regexp, z->name, z->name)) {
		Tcl_ListObjAppendElement(interp, result,
			Tcl_NewStringObj(z->name, -1));
	    }
	}
    } else {
	for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search);
		hPtr; hPtr = Tcl_NextHashEntry(&search)) {
	    ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr);
	    ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr);

	    Tcl_ListObjAppendElement(interp, result,
		    Tcl_NewStringObj(z->name, -1));
	}
    }
    Unlock();
    return TCL_OK;
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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144

3145
3146
3147
3148
3149
3150
3151

3152

3153
3154



3155
3156

3157
3158
3159

3160
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
4220
4221
4222
4223
4224
4225
4226



4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253

4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266

4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
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







-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+
+











-
+













-
+







+
-
+


+
+
+

-
+
-
-
-
+
-
-
+
-
-
+

-
-
+
-
-
-
-
+
-
-
-
-
+
-
-
+
-
-
+

+
-
-
+
+

-
+
+







-
+







 * Side effects:
 *	May initialise the cache of where such library files are to be found.
 *	This cache is never cleared.
 *
 *-------------------------------------------------------------------------
 */

#ifdef _WIN32
#define LIBRARY_SIZE	    64
#endif /* _WIN32 */
/* 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();
    return libDirObj;
}

Tcl_Obj *
TclZipfs_TclLibrary(void)
{
    Tcl_Obj *vfsInitScript;
    int found;
#ifdef _WIN32
#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.
     */

    if (zipfs_literal_tcl_library) {
	return Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
	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 Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
	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)
#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 Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
    }

#elif /* !_WIN32 && */ defined(CFG_RUNTIME_DLLFILE)
    if (ZipfsAppHookFindTclInit(
    if (ZipfsAppHookFindTclInit(dllName) == TCL_OK) {
	    CFG_RUNTIME_LIBDIR "/" CFG_RUNTIME_DLLFILE) == TCL_OK) {
	return Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
	return ScriptLibrarySetup(zipfs_literal_tcl_library);
    }
#endif /* _WIN32 || CFG_RUNTIME_DLLFILE */

#elif !defined(NO_DLFCN_H)
    /*
     * If we're configured to know about a ZIP archive we should use, do that.
     */

    Dl_info dlinfo;
#ifdef CFG_RUNTIME_ZIPFILE
    if (ZipfsAppHookFindTclInit(
	    CFG_RUNTIME_LIBDIR "/" CFG_RUNTIME_ZIPFILE) == TCL_OK) {
	return Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
    if (dladdr((const void *)TclZipfs_TclLibrary, &dlinfo) && (dlinfo.dli_fname != NULL)
    }
    if (ZipfsAppHookFindTclInit(
	    && (ZipfsAppHookFindTclInit(dlinfo.dli_fname) == TCL_OK)) {
	    CFG_RUNTIME_SCRDIR "/" CFG_RUNTIME_ZIPFILE) == TCL_OK) {
	return Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
	return ScriptLibrarySetup(zipfs_literal_tcl_library);
    }
#else
    if (ZipfsAppHookFindTclInit(CFG_RUNTIME_ZIPFILE) == TCL_OK) {
	return Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
    if (ZipfsAppHookFindTclInit(CFG_RUNTIME_LIBDIR "/" CFG_RUNTIME_DLLFILE) == TCL_OK) {
	return ScriptLibrarySetup(zipfs_literal_tcl_library);
    }
#endif /* CFG_RUNTIME_ZIPFILE */
#endif /* _WIN32 */
#endif /* !defined(STATIC_BUILD) */

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

    if (zipfs_literal_tcl_library) {
	return Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
	return ScriptLibrarySetup(zipfs_literal_tcl_library);
    }
    return NULL;
}

/*
 *-------------------------------------------------------------------------
 *
3211
3212
3213
3214
3215
3216
3217
3218

3219
3220
3221
3222
3223
3224
3225
4341
4342
4343
4344
4345
4346
4347

4348
4349
4350
4351
4352
4353
4354
4355







-
+







 *	This cache is never cleared.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSTclLibraryObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*objc*/,
    TCL_UNUSED(Tcl_Obj *const *)) /*objv*/
{
    if (!Tcl_IsSafe(interp)) {
	Tcl_Obj *pResult = TclZipfs_TclLibrary();

3249
3250
3251
3252
3253
3254
3255
3256

3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270





3271


3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
























3286
3287
3288

3289
3290
3291
3292







3293
3294
3295
3296
3297
3298
3299
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
4436
4437
4438
4439
4440
4441
4442
4443
4444







-
+





-
-
-
-




-
+
+
+
+
+

+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
-
-


+
+
+
+
+
+
+








static int
ZipChannelClose(
    void *instanceData,
    TCL_UNUSED(Tcl_Interp *),
    int flags)
{
    ZipChannel *info = (ZipChannel *)instanceData;
    ZipChannel *info = (ZipChannel *) instanceData;

    if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
	return EINVAL;
    }

    if (info->iscompr && info->ubuf) {
	Tcl_Free(info->ubuf);
	info->ubuf = NULL;
    }
    if (info->isEncrypted) {
	info->isEncrypted = 0;
	memset(info->keys, 0, sizeof(info->keys));
    }
    if (info->isWriting) {
    WriteLock();
    if (ZipChannelWritable(info)) {
	/*
	 * Copy channel data back into original file in archive.
	 */
	ZipEntry *z = info->zipEntryPtr;
	assert(info->ubufToFree && info->ubuf);
	unsigned char *newdata;
	unsigned char *newdata = (unsigned char *)Tcl_AttemptRealloc(info->ubuf, info->numRead);

	if (newdata) {
	    if (z->data) {
		Tcl_Free(z->data);
	    }
	    z->data = newdata;
	    z->numBytes = z->numCompressedBytes = info->numBytes;
	    z->compressMethod = ZIP_COMPMETH_STORED;
	    z->timestamp = time(NULL);
	    z->isDirectory = 0;
	    z->isEncrypted = 0;
	    z->offset = 0;
	    z->crc32 = 0;
	newdata = (unsigned char *)Tcl_AttemptRealloc(
	    info->ubufToFree,
	    info->numBytes ? info->numBytes : 1); /* Bug [23dd83ce7c] */
	if (newdata == NULL) {
	    /* Could not reallocate, keep existing buffer */
	    newdata = info->ubufToFree;
	}
	info->ubufToFree = NULL; /* Now newdata! */
	info->ubuf = NULL;
	info->ubufSize = 0;

	/* Replace old content */
	if (z->data) {
	    Tcl_Free(z->data);
	}
	z->data = newdata; /* May be NULL when ubufToFree was NULL */
	z->numBytes = z->numCompressedBytes = info->numBytes;
	assert(z->data || z->numBytes == 0);
	z->compressMethod = ZIP_COMPMETH_STORED;
	z->timestamp = time(NULL);
	z->isDirectory = 0;
	z->isEncrypted = 0;
	z->offset = 0;
	z->crc32 = 0;
	} else {
	    Tcl_Free(info->ubuf);
	}
    }
    }
    WriteLock();
    info->zipFilePtr->numOpen--;
    Unlock();
    if (info->ubufToFree) {
	assert(info->ubuf);
	Tcl_Free(info->ubufToFree);
	info->ubuf = NULL;
	info->ubufToFree = NULL;
	info->ubufSize = 0;
    }
    Tcl_Free(info);
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
3314
3315
3316
3317
3318
3319
3320
3321

3322
3323
3324
3325
3326
3327
3328
3329
3330
3331



3332
3333
3334
3335
3336
3337
3338

3339
3340
3341
3342
3343
3344
3345
3346

3347
3348

3349
3350
3351
3352
3353
3354
3355
3356





3357
3358

3359
3360
3361
3362
3363

3364
3365

3366
3367
3368
3369
3370
3371
3372
4459
4460
4461
4462
4463
4464
4465

4466
4467
4468
4469
4470
4471
4472
4473



4474
4475
4476
4477
4478
4479
4480
4481
4482

4483
4484
4485
4486
4487
4488
4489
4490

4491
4492

4493
4494
4495
4496
4497
4498
4499
4500

4501
4502
4503
4504
4505
4506

4507
4508
4509
4510
4511

4512
4513

4514
4515
4516
4517
4518
4519
4520
4521







-
+







-
-
-
+
+
+






-
+







-
+

-
+







-
+
+
+
+
+

-
+




-
+

-
+







ZipChannelRead(
    void *instanceData,
    char *buf,
    int toRead,
    int *errloc)
{
    ZipChannel *info = (ZipChannel *) instanceData;
    unsigned long nextpos;
    Tcl_Size nextpos;

    if (info->isDirectory < 0) {
	/*
	 * Special case: when executable combined with ZIP archive file read
	 * data in front of ZIP, i.e. the executable itself.
	 */

	nextpos = info->numRead + toRead;
	if (nextpos > info->zipFilePtr->baseOffset) {
	    toRead = info->zipFilePtr->baseOffset - info->numRead;
	nextpos = info->cursor + toRead;
	if ((size_t)nextpos > info->zipFilePtr->baseOffset) {
	    toRead = info->zipFilePtr->baseOffset - info->cursor;
	    nextpos = info->zipFilePtr->baseOffset;
	}
	if (toRead == 0) {
	    return 0;
	}
	memcpy(buf, info->zipFilePtr->data, toRead);
	info->numRead = nextpos;
	info->cursor = nextpos;
	*errloc = 0;
	return toRead;
    }
    if (info->isDirectory) {
	*errloc = EISDIR;
	return -1;
    }
    nextpos = info->numRead + toRead;
    nextpos = info->cursor + toRead;
    if (nextpos > info->numBytes) {
	toRead = info->numBytes - info->numRead;
	toRead = info->numBytes - info->cursor;
	nextpos = info->numBytes;
    }
    if (toRead == 0) {
	return 0;
    }
    if (info->isEncrypted) {
	int i;

	/*
	 * TODO - when is this code ever exercised? Cannot reach it from
	 * tests. In particular, decryption is always done at channel open
	 * to allow for seeks and random reads.
	 */
	for (i = 0; i < toRead; i++) {
	    int ch = info->ubuf[i + info->numRead];
	    int ch = info->ubuf[i + info->cursor];

	    buf[i] = zdecode(info->keys, crc32tab, ch);
	}
    } else {
	memcpy(buf, info->ubuf + info->numRead, toRead);
	memcpy(buf, info->ubuf + info->cursor, toRead);
    }
    info->numRead = nextpos;
    info->cursor = nextpos;
    *errloc = 0;
    return toRead;
}

/*
 *-------------------------------------------------------------------------
 *
3389
3390
3391
3392
3393
3394
3395
3396

3397
3398
3399
3400
3401
3402
3403
3404







3405

3406
3407
































3408
3409
3410
3411




3412
3413
3414
3415
3416
3417
3418
4538
4539
4540
4541
4542
4543
4544

4545
4546
4547
4548





4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591




4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602







-
+



-
-
-
-
-
+
+
+
+
+
+
+

+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+







    const char *buf,
    int toWrite,
    int *errloc)
{
    ZipChannel *info = (ZipChannel *) instanceData;
    unsigned long nextpos;

    if (!info->isWriting) {
    if (!ZipChannelWritable(info)) {
	*errloc = EINVAL;
	return -1;
    }
    nextpos = info->numRead + toWrite;
    if (nextpos > info->maxWrite) {
	toWrite = info->maxWrite - info->numRead;
	nextpos = info->maxWrite;
    }

    assert(info->ubuf == info->ubufToFree);
    assert(info->ubufToFree && info->ubufSize > 0);
    assert(info->ubufSize <= info->maxWrite);
    assert(info->numBytes <= info->ubufSize);
    assert(info->cursor <= info->numBytes);

    if (toWrite == 0) {
	*errloc = 0;
	return 0;
    }

    if (info->mode & O_APPEND) {
	info->cursor = info->numBytes;
    }

    if (toWrite > (info->maxWrite - info->cursor)) {
	/* File would grow beyond max size permitted */
	/* Don't do partial writes in error case. Or should we? */
	*errloc = EFBIG;
	return -1;
    }

    if (toWrite > (info->ubufSize - info->cursor)) {
	/* grow the buffer. We have already checked will not exceed maxWrite */
	Tcl_Size needed = info->cursor + toWrite;
	/* Tack on a bit for future growth. */
	if (needed < (info->maxWrite - needed/2)) {
	    needed += needed / 2;
	} else {
	    needed = info->maxWrite;
	}
	unsigned char *newBuf =
	    (unsigned char *)Tcl_AttemptRealloc(info->ubufToFree, needed);
	if (newBuf == NULL) {
	    *errloc = ENOMEM;
	    return -1;
	}
	info->ubufToFree = newBuf;
	info->ubuf = info->ubufToFree;
	info->ubufSize = needed;
    }
    nextpos = info->cursor + toWrite;
    memcpy(info->ubuf + info->numRead, buf, toWrite);
    info->numRead = nextpos;
    if (info->numRead > info->numBytes) {
	info->numBytes = info->numRead;
    memcpy(info->ubuf + info->cursor, buf, toWrite);
    info->cursor = nextpos;
    if (info->cursor > info->numBytes) {
	info->numBytes = info->cursor;
    }
    *errloc = 0;
    return toWrite;
}

/*
 *-------------------------------------------------------------------------
3426
3427
3428
3429
3430
3431
3432
3433

3434
3435
3436

3437
3438
3439
3440
3441

3442
3443

3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457

3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468

3469
3470
3471
3472
3473


3474
3475
3476
3477

3478
3479
3480

3481
3482
3483
3484
3485


3486
3487
3488
3489
3490
3491
3492
4610
4611
4612
4613
4614
4615
4616

4617
4618
4619

4620
4621
4622
4623
4624

4625
4626

4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640

4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651

4652
4653
4654
4655


4656
4657
4658
4659
4660

4661
4662
4663

4664
4665
4666
4667


4668
4669
4670
4671
4672
4673
4674
4675
4676







-
+


-
+




-
+

-
+













-
+










-
+



-
-
+
+



-
+


-
+



-
-
+
+







 *
 * Side effects:
 *	File pointer is repositioned according to offset and mode.
 *
 *-------------------------------------------------------------------------
 */

static Tcl_WideInt
static long long
ZipChannelWideSeek(
    void *instanceData,
    Tcl_WideInt offset,
    long long offset,
    int mode,
    int *errloc)
{
    ZipChannel *info = (ZipChannel *) instanceData;
    size_t end;
    Tcl_Size end;

    if (!info->isWriting && (info->isDirectory < 0)) {
    if (!ZipChannelWritable(info) && (info->isDirectory < 0)) {
	/*
	 * Special case: when executable combined with ZIP archive file, seek
	 * within front of ZIP, i.e. the executable itself.
	 */
	end = info->zipFilePtr->baseOffset;
    } else if (info->isDirectory) {
	*errloc = EINVAL;
	return -1;
    } else {
	end = info->numBytes;
    }
    switch (mode) {
    case SEEK_CUR:
	offset += info->numRead;
	offset += info->cursor;
	break;
    case SEEK_END:
	offset += end;
	break;
    case SEEK_SET:
	break;
    default:
	*errloc = EINVAL;
	return -1;
    }
    if (offset < 0) {
    if (offset < 0 || offset > TCL_SIZE_MAX) {
	*errloc = EINVAL;
	return -1;
    }
    if (info->isWriting) {
	if ((size_t) offset > info->maxWrite) {
    if (ZipChannelWritable(info)) {
	if (offset > info->maxWrite) {
	    *errloc = EINVAL;
	    return -1;
	}
	if ((size_t) offset > info->numBytes) {
	if (offset > info->numBytes) {
	    info->numBytes = offset;
	}
    } else if ((size_t) offset > end) {
    } else if (offset > end) {
	*errloc = EINVAL;
	return -1;
    }
    info->numRead = (size_t) offset;
    return info->numRead;
    info->cursor = (Tcl_Size) offset;
    return info->cursor;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipChannelWatchChannel --
 *
3500
3501
3502
3503
3504
3505
3506
3507

3508
3509
3510
3511
3512
3513
3514
4684
4685
4686
4687
4688
4689
4690

4691
4692
4693
4694
4695
4696
4697
4698







-
+







 *	None.
 *
 *-------------------------------------------------------------------------
 */

static void
ZipChannelWatchChannel(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    TCL_UNUSED(int) /*mask*/)
{
    return;
}

/*
 *-------------------------------------------------------------------------
3525
3526
3527
3528
3529
3530
3531
3532

3533
3534

3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545

3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560


3561
3562
3563
3564
3565

3566
3567

3568
3569





3570
3571
3572
3573














3574
3575
3576





3577
3578
3579





















3580

3581
3582
3583

3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594

3595
3596
3597
3598
3599
3600





3601
3602

3603
3604
3605





3606


3607
3608
3609
3610
3611







3612
3613
3614
3615



3616
3617
3618
3619
3620
3621
3622
3623


3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636

3637
3638
3639
3640
3641
3642
3643
3644
3645
3646


3647
3648
3649
3650
3651
3652
3653


3654

3655
3656
3657
3658
3659













3660
3661
3662
3663
3664





3665
3666
3667





3668
3669
3670
3671
3672







3673
3674
3675

3676
3677

3678
3679

3680
3681
3682

3683
3684
3685
3686
3687








3688



3689
3690
3691
3692



3693
3694
3695
3696
3697

3698
3699
3700
3701
3702
3703










3704
3705

3706
3707
3708


3709
3710
3711





3712
3713
3714
3715
3716
3717
3718









3719
3720


3721
3722
3723
3724
3725






3726
3727
3728

3729
3730
3731






3732
3733


3734
3735
3736
3737
3738

3739
3740
3741


3742
3743
3744




3745
3746
3747
3748
3749
3750









3751
3752
3753
3754
3755
3756





3757
3758
3759
3760
3761
3762
3763


3764
3765
3766
3767
3768
3769
3770
3771

3772
3773
3774

3775
3776

3777
3778
3779
3780
3781


3782
3783

3784
3785
3786


3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800









3801
3802

3803
3804
3805
3806


3807
3808

3809
3810

3811
3812

3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828

3829
3830

3831
3832
3833
3834
3835


3836
3837

3838
3839
3840
3841




3842
3843
3844


3845
3846
3847

3848
3849
3850







3851

3852

3853
3854
3855



3856
3857
3858
3859
3860
3861


3862
3863

3864
3865




























































3866
3867
3868
3869
3870
3871
3872
3873
3874
3875














































3876

3877

3878
3879
3880







3881



























3882


3883














































3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895

3896
3897
3898
3899
3900
3901
3902
4709
4710
4711
4712
4713
4714
4715

4716
4717

4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728

4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742


4743
4744

4745
4746
4747

4748
4749
4750
4751


4752
4753
4754
4755
4756
4757



4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803

4804
4805
4806

4807
4808
4809
4810
4811


4812
4813
4814


4815

4816
4817



4818
4819
4820
4821
4822

4823
4824



4825
4826
4827
4828
4829
4830
4831
4832





4833
4834
4835
4836
4837
4838
4839




4840
4841
4842


4843
4844


4845

4846
4847
4848




4849
4850
4851
4852

4853


4854










4855
4856
4857




4858
4859
4860
4861

4862





4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875





4876
4877
4878
4879
4880



4881
4882
4883
4884
4885





4886
4887
4888
4889
4890
4891
4892



4893


4894


4895



4896





4897
4898
4899
4900
4901
4902
4903
4904

4905
4906
4907
4908



4909
4910
4911





4912






4913
4914
4915
4916
4917
4918
4919
4920
4921
4922


4923



4924
4925



4926
4927
4928
4929
4930







4931
4932
4933
4934
4935
4936
4937
4938
4939


4940
4941





4942
4943
4944
4945
4946
4947



4948



4949
4950
4951
4952
4953
4954


4955
4956





4957



4958
4959



4960
4961
4962
4963






4964
4965
4966
4967
4968
4969
4970
4971
4972
4973





4974
4975
4976
4977
4978
4979


4980



4981
4982








4983
4984


4985


4986





4987
4988


4989



4990
4991
4992
4993


4994
4995
4996
4997
4998
4999




5000
5001
5002
5003
5004
5005
5006
5007
5008


5009
5010
5011


5012
5013
5014

5015
5016

5017
5018

5019
















5020
5021

5022
5023
5024
5025


5026
5027


5028




5029
5030
5031
5032
5033


5034
5035



5036
5037


5038
5039
5040
5041
5042
5043
5044
5045
5046

5047



5048
5049
5050
5051





5052
5053
5054

5055

5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116










5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164

5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175

5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254










5255
5256
5257
5258
5259
5260
5261
5262







-
+

-
+










-
+













-
-
+
+
-



-
+


+
-
-
+
+
+
+
+

-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+



+
+
+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+


-
+




-
-



-
-
+
-


-
-
-
+
+
+
+
+
-

+
-
-
-
+
+
+
+
+

+
+
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
+
+
+
-
-


-
-

-
+
+

-
-
-
-




-

-
-
+
-
-
-
-
-
-
-
-
-
-
+
+

-
-
-
-


+
+
-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
-
-
+
-
-
+
-
-
-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
+
+

-
-
-
+
+
+
-
-
-
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
+
+
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
+
+
+
+
+
+
-
-
-
+
-
-
-
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
+
-
-
-
+
+
-
-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-

-
-
-
+
+
-
-
-
-
-
-
-
-
+

-
-
+
-
-
+
-
-
-
-
-
+
+
-
-
+
-
-
-
+
+


-
-






-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+


-
-
+
+

-
+

-
+

-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+

-
+



-
-
+
+
-
-
+
-
-
-
-
+
+
+
+

-
-
+
+
-
-
-
+

-
-
+
+
+
+
+
+
+

+
-
+
-
-
-
+
+
+

-
-
-
-
-
+
+

-
+
-

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
-
+



+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
-
-
-
+







 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipChannelGetFile(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    TCL_UNUSED(int) /*direction*/,
    TCL_UNUSED(ClientData *) /*handlePtr*/)
    TCL_UNUSED(void **) /*handlePtr*/)
{
    return TCL_ERROR;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipChannelOpen --
 *
 *	This function opens a Tcl_Channel on a file from a mounted ZIP archive
 *	according to given open mode.
 *	according to given open mode (already parsed by caller).
 *
 * Results:
 *	Tcl_Channel on success, or NULL on error.
 *
 * Side effects:
 *	Memory is allocated, the file from the ZIP archive is uncompressed.
 *
 *-------------------------------------------------------------------------
 */

static Tcl_Channel
ZipChannelOpen(
    Tcl_Interp *interp,		/* Current interpreter. */
    char *filename,
    int mode,
    char *filename,		/* What are we opening. */
    int mode)			/* O_WRONLY O_RDWR O_TRUNC flags */
    TCL_UNUSED(int) /*permissions*/)
{
    ZipEntry *z;
    ZipChannel *info;
    int i, ch, trunc, wr, flags = 0;
    int flags = 0;
    char cname[128];

    int wr = (mode & (O_WRONLY | O_RDWR)) != 0;
    if ((mode & O_APPEND)
	    || ((ZipFS.wrmax <= 0) && (mode & (O_WRONLY | O_RDWR)))) {

    /* Check for unsupported modes. */

    if ((ZipFS.wrmax <= 0) && wr) {
	Tcl_SetErrno(EACCES);
	if (interp) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("unsupported open mode", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "BAD_MODE", NULL);
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "writes not permitted: %s",
		    Tcl_PosixError(interp)));
	}
	return NULL;
    }

    if ((mode & (O_APPEND|O_TRUNC)) && !wr) {
	Tcl_SetErrno(EINVAL);
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "Invalid flags 0x%x. O_APPEND and "
		    "O_TRUNC require write access: %s",
		    mode, Tcl_PosixError(interp)));
	}
	return NULL;
    }

    /*
     * Is the file there?
     */

    WriteLock();
    z = ZipFSLookup(filename);
    if (!z) {
	Tcl_SetErrno(wr ? ENOTSUP : ENOENT);
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "file \"%s\" not %s: %s",
		    filename, wr ? "created" : "found",
		    Tcl_PosixError(interp)));
	}
	goto error;
    }

    if (z->numBytes < 0 || z->numCompressedBytes < 0 ||
	    z->offset >= z->zipFilePtr->length) {
	/* Normally this should only happen for zip64. */
	ZIPFS_ERROR(interp, "file size error (may be zip64)");
	ZIPFS_ERROR_CODE(interp, "FILE_SIZE");
	goto error;
    }

    /* Do we support opening the file that way? */

    if (wr && z->isDirectory) {
	Tcl_SetErrno(ENOENT);
	Tcl_SetErrno(EISDIR);
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "file not found \"%s\": %s", filename,
		    "unsupported file type: %s",
		    Tcl_PosixError(interp)));
	}
	goto error;
    }
    trunc = (mode & O_TRUNC) != 0;
    wr = (mode & (O_WRONLY | O_RDWR)) != 0;
    if ((z->compressMethod != ZIP_COMPMETH_STORED)
	    && (z->compressMethod != ZIP_COMPMETH_DEFLATED)) {
	ZIPFS_ERROR(interp, "unsupported compression method");
	if (interp) {
	    Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "COMP_METHOD", NULL);
	ZIPFS_ERROR_CODE(interp, "COMP_METHOD");
	}
	goto error;
    }
    if (wr && z->isDirectory) {
	ZIPFS_ERROR(interp, "unsupported file type");
	if (interp) {
    if (wr) {
	if ((mode & O_TRUNC) == 0 && !z->data && (z->numBytes > ZipFS.wrmax)) {
	    Tcl_SetErrno(EFBIG);
	    ZIPFS_POSIX_ERROR(interp, "file size exceeds max writable");
	    goto error;
	    Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "FILE_TYPE", NULL);
	}
	flags = TCL_WRITABLE;
	goto error;
    }
    if (!trunc) {
	if (mode & O_RDWR) {
	    flags |= TCL_READABLE;
	}
    } else {
	/* Read-only */
	flags |= TCL_READABLE;
    }

	if (z->isEncrypted && (z->zipFilePtr->passBuf[0] == 0)) {
	    ZIPFS_ERROR(interp, "decryption failed");
	    if (interp) {
		Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "DECRYPT", NULL);
	    }
    if (z->isEncrypted) {
	if (z->numCompressedBytes < ZIP_CRYPT_HDR_LEN) {
	    ZIPFS_ERROR(interp,
			"decryption failed: truncated decryption header");
	    ZIPFS_ERROR_CODE(interp, "DECRYPT");
	    goto error;
	}
	    goto error;
	} else if (wr && !z->data && (z->numBytes > ZipFS.wrmax)) {
	    ZIPFS_ERROR(interp, "file too large");
	    if (interp) {
	if (z->zipFilePtr->passBuf[0] == 0) {
	    ZIPFS_ERROR(interp, "decryption failed - no password provided");
	    ZIPFS_ERROR_CODE(interp, "DECRYPT");
		Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "FILE_SIZE", NULL);
	    }
	    goto error;
	}
    } else {
	flags = TCL_WRITABLE;
    }
    info = (ZipChannel *)Tcl_AttemptAlloc(sizeof(ZipChannel));

    info = AllocateZipChannel(interp);
    if (!info) {
	ZIPFS_ERROR(interp, "out of memory");
	if (interp) {
	    Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL);
	}
	goto error;
    }
    info->zipFilePtr = z->zipFilePtr;
    info->zipEntryPtr = z;
    info->numRead = 0;
    if (wr) {
	flags |= TCL_WRITABLE;
	info->isWriting = 1;
	/* Set up a writable channel. */
	info->isDirectory = 0;
	info->maxWrite = ZipFS.wrmax;
	info->iscompr = 0;
	info->isEncrypted = 0;
	info->ubuf = (unsigned char *)Tcl_AttemptAlloc(info->maxWrite);
	if (!info->ubuf) {
	merror0:
	    if (info->ubuf) {
		Tcl_Free(info->ubuf);
	    }

	if (InitWritableChannel(interp, info, z, mode) == TCL_ERROR) {
	    Tcl_Free(info);
	    ZIPFS_ERROR(interp, "out of memory");
	    if (interp) {
		Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL);
	    }
	    goto error;
	}
    } else if (z->data) {
	/* Set up a readable channel for direct data. */
	memset(info->ubuf, 0, info->maxWrite);

	if (trunc) {
	    info->numBytes = 0;
	} else if (z->data) {
	    size_t j = z->numBytes;

	info->numBytes = z->numBytes;
	info->ubuf = z->data;
	info->ubufToFree = NULL; /* Not dynamically allocated */
	info->ubufSize = 0;
    } else {
	/*
	 * Set up a readable channel.
	 */

	if (InitReadableChannel(interp, info, z) == TCL_ERROR) {
	    Tcl_Free(info);
	    goto error;
	}
	    if (j > info->maxWrite) {
		j = info->maxWrite;
	    }
	    memcpy(info->ubuf, z->data, j);
	    info->numBytes = j;
    }

    if (z->crc32) {
	if (!(z->flags & ZE_F_CRC_COMPARED)) {
	    int crc = crc32(0, NULL, info->numBytes);
	} else {
	    unsigned char *zbuf = z->zipFilePtr->data + z->offset;

	    crc = crc32(crc, info->ubuf, info->numBytes);
	    z->flags |= ZE_F_CRC_COMPARED;
	    if (crc == z->crc32) {
		z->flags |= ZE_F_CRC_CORRECT;
	    }
	    if (z->isEncrypted) {
		int len = z->zipFilePtr->passBuf[0] & 0xFF;
		char passBuf[260];

		for (i = 0; i < len; i++) {
	}
	if (!(z->flags & ZE_F_CRC_CORRECT)) {
	    ZIPFS_ERROR(interp, "invalid CRC");
	    ZIPFS_ERROR_CODE(interp, "CRC_FAILED");
	    if (info->ubufToFree) {
		Tcl_Free(info->ubufToFree);
		info->ubufSize = 0;
		    ch = z->zipFilePtr->passBuf[len - i];
		    passBuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f];
		}
	    }
		passBuf[i] = '\0';
		init_keys(passBuf, info->keys, crc32tab);
	    Tcl_Free(info);
		memset(passBuf, 0, sizeof(passBuf));
		for (i = 0; i < 12; i++) {
	    goto error;
		    ch = info->ubuf[i];
		    zdecode(info->keys, crc32tab, ch);
		}
	}
		zbuf += i;
	    }
	    if (z->compressMethod == ZIP_COMPMETH_DEFLATED) {
		z_stream stream;
		int err;
    }

    /*
     * Wrap the ZipChannel into a Tcl_Channel.
     */

    snprintf(cname, sizeof(cname), "zipfs_%" TCL_Z_MODIFIER "x_%d", z->offset,
	    ZipFS.idCount++);
		unsigned char *cbuf = NULL;
    z->zipFilePtr->numOpen++;
    Unlock();
    return Tcl_CreateChannel(&zipChannelType, cname, info, flags);

		memset(&stream, 0, sizeof(z_stream));
		stream.zalloc = Z_NULL;
		stream.zfree = Z_NULL;
  error:
    Unlock();
    return NULL;
		stream.opaque = Z_NULL;
		stream.avail_in = z->numCompressedBytes;
		if (z->isEncrypted) {
		    size_t j;

}
		    stream.avail_in -= 12;
		    cbuf = (unsigned char *)Tcl_AttemptAlloc(stream.avail_in);
		    if (!cbuf) {
			goto merror0;
		    }
		    for (j = 0; j < stream.avail_in; j++) {

/*
 *-------------------------------------------------------------------------
 *
 * InitWritableChannel --
 *
 *	Assistant for ZipChannelOpen() that sets up a writable channel. It's
 *	up to the caller to actually register the channel.
 *
 * Returns:
			ch = info->ubuf[j];
			cbuf[j] = zdecode(info->keys, crc32tab, ch);
 *	Tcl result code.
		    }
		    stream.next_in = cbuf;
		} else {
 *
 * Side effects:
		    stream.next_in = zbuf;
		}
		stream.next_out = info->ubuf;
 *	Allocates memory for the implementation of the channel. Writes to the
 *	interpreter's result on error.
 *
 *-------------------------------------------------------------------------
 */
		stream.avail_out = info->maxWrite;
		if (inflateInit2(&stream, -15) != Z_OK) {
		    goto cerror0;
		}
		err = inflate(&stream, Z_SYNC_FLUSH);
		inflateEnd(&stream);
		if ((err == Z_STREAM_END)

static int
InitWritableChannel(
    Tcl_Interp *interp,		/* Current interpreter, or NULL (when errors
				 * will be silent). */
    ZipChannel *info,		/* The channel to set up. */
    ZipEntry *z,		/* The zipped file that the channel will write
				 * to. */
    int mode)			/* O_APPEND, O_TRUNC */
			|| ((err == Z_OK) && (stream.avail_in == 0))) {
		    if (cbuf) {
{
    int i, ch;
			memset(info->keys, 0, sizeof(info->keys));
			Tcl_Free(cbuf);
		    }
		    goto wrapchan;
		}
    unsigned char *cbuf = NULL;

    /*
     * Set up a writable channel.
     */

	    cerror0:
		if (cbuf) {
		    memset(info->keys, 0, sizeof(info->keys));
    info->mode = mode;
		    Tcl_Free(cbuf);
		}
		if (info->ubuf) {
    info->maxWrite = ZipFS.wrmax;

    info->ubufSize = z->numBytes ? z->numBytes : 1;
    info->ubufToFree = (unsigned char *)Tcl_AttemptAlloc(info->ubufSize);
    info->ubuf = info->ubufToFree;
    if (info->ubufToFree == NULL) {
		    Tcl_Free(info->ubuf);
		}
	goto memoryError;
    }
		Tcl_Free(info);
		ZIPFS_ERROR(interp, "decompression error");
		if (interp) {
		    Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "CORRUPT", NULL);
		}

		goto error;
	    } else if (z->isEncrypted) {
		for (i = 0; i < z->numBytes - 12; i++) {
    if (z->isEncrypted) {
	assert(z->numCompressedBytes >= ZIP_CRYPT_HDR_LEN); /* caller should have checked*/
		    ch = zbuf[i];
		    info->ubuf[i] = zdecode(info->keys, crc32tab, ch);
		}
	if (DecodeCryptHeader(interp, z, info->keys,
		z->zipFilePtr->data + z->offset) != TCL_OK) {
	    goto error_cleanup;
	}
	    } else {
		memcpy(info->ubuf, zbuf, z->numBytes);
	    }
	    memset(info->keys, 0, sizeof(info->keys));
	    goto wrapchan;
	}
    }

    if (mode & O_TRUNC) {
	/*
	 * Truncate; nothing there.
	 */

	info->numBytes = 0;
	z->crc32 = 0; /* Truncated, CRC no longer applicable */
    } else if (z->data) {
	flags |= TCL_READABLE;
	info->isWriting = 0;
	info->iscompr = 0;
	info->isDirectory = 0;
	info->isEncrypted = 0;
	/*
	 * Already got uncompressed data.
	 */
	assert(info->ubufSize >= z->numBytes);
	memcpy(info->ubuf, z->data, z->numBytes);
	info->numBytes = z->numBytes;
	info->maxWrite = 0;
	info->ubuf = z->data;
    } else {
	flags |= TCL_READABLE;
	info->isWriting = 0;
	info->iscompr = (z->compressMethod == ZIP_COMPMETH_DEFLATED);
	/*
	 * Need to uncompress the existing data.
	info->ubuf = z->zipFilePtr->data + z->offset;
	info->isDirectory = z->isDirectory;
	info->isEncrypted = z->isEncrypted;
	info->numBytes = z->numBytes;
	info->maxWrite = 0;
	if (info->isEncrypted) {
	    int len = z->zipFilePtr->passBuf[0] & 0xFF;
	    char passBuf[260];
	 */

	    for (i = 0; i < len; i++) {
		ch = z->zipFilePtr->passBuf[len - i];
	unsigned char *zbuf = z->zipFilePtr->data + z->offset;
		passBuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f];
	    }

	    passBuf[i] = '\0';
	    init_keys(passBuf, info->keys, crc32tab);
	    memset(passBuf, 0, sizeof(passBuf));
	    for (i = 0; i < 12; i++) {
		ch = info->ubuf[i];
	if (z->isEncrypted) {
	    zbuf += ZIP_CRYPT_HDR_LEN;
		zdecode(info->keys, crc32tab, ch);
	    }
	}
	    info->ubuf += i;
	}
	if (info->iscompr) {

	if (z->compressMethod == ZIP_COMPMETH_DEFLATED) {
	    z_stream stream;
	    int err;
	    unsigned char *ubuf = NULL;
	    size_t j;

	    memset(&stream, 0, sizeof(z_stream));
	    stream.zalloc = Z_NULL;
	    stream.zfree = Z_NULL;
	    stream.opaque = Z_NULL;
	    stream.avail_in = z->numCompressedBytes;
	    if (info->isEncrypted) {
		stream.avail_in -= 12;
		ubuf = (unsigned char *)Tcl_AttemptAlloc(stream.avail_in);
		if (!ubuf) {
	    if (z->isEncrypted) {
		unsigned int j;

		/* Min length ZIP_CRYPT_HDR_LEN for keys should already been checked. */
		assert(stream.avail_in >= ZIP_CRYPT_HDR_LEN);

		stream.avail_in -= ZIP_CRYPT_HDR_LEN;
		cbuf = (unsigned char *) Tcl_AttemptAlloc(stream.avail_in ? stream.avail_in : 1);
		if (!cbuf) {
		    info->ubuf = NULL;
		    goto merror;
		    goto memoryError;
		}
		for (j = 0; j < stream.avail_in; j++) {
		    ch = info->ubuf[j];
		    ubuf[j] = zdecode(info->keys, crc32tab, ch);
		    ch = zbuf[j];
		    cbuf[j] = zdecode(info->keys, crc32tab, ch);
		}
		stream.next_in = ubuf;
		stream.next_in = cbuf;
	    } else {
		stream.next_in = info->ubuf;
		stream.next_in = zbuf;
	    }
	    stream.next_out = info->ubuf = (unsigned char *)Tcl_AttemptAlloc(info->numBytes);
	    stream.next_out = info->ubuf;
	    if (!info->ubuf) {
	    merror:
		if (ubuf) {
		    info->isEncrypted = 0;
		    memset(info->keys, 0, sizeof(info->keys));
		    Tcl_Free(ubuf);
		}
		Tcl_Free(info);
		if (interp) {
		    Tcl_SetObjResult(interp,
			    Tcl_NewStringObj("out of memory", -1));
		    Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL);
		}
		goto error;
	    }
	    stream.avail_out = info->numBytes;
	    stream.avail_out = info->ubufSize;
	    if (inflateInit2(&stream, -15) != Z_OK) {
		goto cerror;
		goto corruptionError;
	    }
	    err = inflate(&stream, Z_SYNC_FLUSH);
	    inflateEnd(&stream);
	    if ((err == Z_STREAM_END)
		    || ((err == Z_OK) && (stream.avail_in == 0))) {
	    if ((err != Z_STREAM_END) &&
		    ((err != Z_OK) || (stream.avail_in != 0))) {
		if (ubuf) {
		    info->isEncrypted = 0;
		goto corruptionError;
		    memset(info->keys, 0, sizeof(info->keys));
		    Tcl_Free(ubuf);
		}
		goto wrapchan;
	    }
	    /* Even if decompression succeeded, counts should be as expected */
	    if ((int) stream.total_out != z->numBytes) {
		goto corruptionError;
	    }
	cerror:
	    if (ubuf) {
	    info->numBytes = z->numBytes;
	    if (cbuf) {
		info->isEncrypted = 0;
		memset(info->keys, 0, sizeof(info->keys));
		Tcl_Free(ubuf);
		Tcl_Free(cbuf);
	    }
	    if (info->ubuf) {
		Tcl_Free(info->ubuf);
	} else if (z->isEncrypted) {
	    /*
	     * Need to decrypt some otherwise-simple stored data.
	     */
	    if (z->numCompressedBytes <= ZIP_CRYPT_HDR_LEN ||
		    (z->numCompressedBytes - ZIP_CRYPT_HDR_LEN) != z->numBytes) {
		goto corruptionError;
	    }
	    int len = z->numCompressedBytes - ZIP_CRYPT_HDR_LEN;
	    Tcl_Free(info);
	    assert(len <= info->ubufSize);
	    ZIPFS_ERROR(interp, "decompression error");
	    if (interp) {
		Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "CORRUPT", NULL);
	    for (i = 0; i < len; i++) {
		ch = zbuf[i];
		info->ubuf[i] = zdecode(info->keys, crc32tab, ch);
	    }
	    goto error;
	} else if (info->isEncrypted) {
	    unsigned char *ubuf = NULL;
	    size_t j, len;

	    info->numBytes = len;
	} else {
	    /*
	     * Decode encrypted but uncompressed file, since we support
	     * Simple stored data. Copy into our working buffer.
	     * Tcl_Seek() on it, and it can be randomly accessed later.
	     */
	    assert(info->ubufSize >= z->numBytes);
	    memcpy(info->ubuf, zbuf, z->numBytes);
	    info->numBytes = z->numBytes;
	}
	memset(info->keys, 0, sizeof(info->keys));
    }
    if (mode & O_APPEND) {
	info->cursor = info->numBytes;
    }

    return TCL_OK;

  memoryError:
    ZIPFS_MEM_ERROR(interp);
    goto error_cleanup;

  corruptionError:
    if (cbuf) {
	memset(info->keys, 0, sizeof(info->keys));
	Tcl_Free(cbuf);
    }
    ZIPFS_ERROR(interp, "decompression error");
    ZIPFS_ERROR_CODE(interp, "CORRUPT");

  error_cleanup:
    if (info->ubufToFree) {
	Tcl_Free(info->ubufToFree);
	info->ubufToFree = NULL;
	info->ubuf = NULL;
	info->ubufSize = 0;
    }
    return TCL_ERROR;
}

/*
 *-------------------------------------------------------------------------
 *
 * InitReadableChannel --
 *
 *	Assistant for ZipChannelOpen() that sets up a readable channel. It's
 *	up to the caller to actually register the channel. Caller should have
 *	validated the passed ZipEntry (byte counts in particular)
 *
 * Returns:
 *	Tcl result code.
 *
 * Side effects:
 *	Allocates memory for the implementation of the channel. Writes to the
 *	interpreter's result on error.
 *
 *-------------------------------------------------------------------------
 */

static int
InitReadableChannel(
    Tcl_Interp *interp,		/* Current interpreter, or NULL (when errors
				 * will be silent). */
    ZipChannel *info,		/* The channel to set up. */
    ZipEntry *z)		/* The zipped file that the channel will read
				 * from. */

	    len = z->numCompressedBytes - 12;
	    ubuf = (unsigned char *) Tcl_AttemptAlloc(len);
	    if (ubuf == NULL) {
		Tcl_Free((char *) info);
		if (interp != NULL) {
		    Tcl_SetObjResult(interp,
			Tcl_NewStringObj("out of memory", -1));
		}
		goto error;
{
    unsigned char *ubuf = NULL;
    int ch;

    info->iscompr = (z->compressMethod == ZIP_COMPMETH_DEFLATED);
    info->ubuf = z->zipFilePtr->data + z->offset;
    info->ubufToFree = NULL; /* ubuf memory not allocated */
    info->ubufSize = 0;
    info->isDirectory = z->isDirectory;
    info->isEncrypted = z->isEncrypted;
    info->mode = O_RDONLY;

    /* Caller must validate - bug [6ed3447a7e] */
    assert(z->numBytes >= 0 && z->numCompressedBytes >= 0);
    info->numBytes = z->numBytes;

    if (info->isEncrypted) {
	assert(z->numCompressedBytes >= ZIP_CRYPT_HDR_LEN); /* caller should have checked*/
	if (DecodeCryptHeader(interp, z, info->keys, info->ubuf) != TCL_OK) {
	    goto error_cleanup;
	}
	info->ubuf += ZIP_CRYPT_HDR_LEN;
    }

    if (info->iscompr) {
	z_stream stream;
	int err;
	unsigned int j;

	/*
	 * Data to decode is compressed, and possibly encrpyted too. If
	 * encrypted, local variable ubuf is used to hold the decrypted but
	 * still compressed data.
	 */

	memset(&stream, 0, sizeof(z_stream));
	stream.zalloc = Z_NULL;
	stream.zfree = Z_NULL;
	stream.opaque = Z_NULL;
	stream.avail_in = z->numCompressedBytes;
	if (info->isEncrypted) {
	    assert(stream.avail_in >= ZIP_CRYPT_HDR_LEN);
	    stream.avail_in -= ZIP_CRYPT_HDR_LEN;
	    ubuf = (unsigned char *) Tcl_AttemptAlloc(stream.avail_in ? stream.avail_in : 1);
	    if (!ubuf) {
		goto memoryError;
	    }

	    for (j = 0; j < len; j++) {
	    for (j = 0; j < stream.avail_in; j++) {
		ch = info->ubuf[j];
		ubuf[j] = zdecode(info->keys, crc32tab, ch);
	    }
	    stream.next_in = ubuf;
	} else {
	    stream.next_in = info->ubuf;
	}

	info->ubufSize = info->numBytes ? info->numBytes : 1;
	info->ubufToFree = (unsigned char *)Tcl_AttemptAlloc(info->ubufSize);
	    info->ubuf = ubuf;
	info->ubuf = info->ubufToFree;
	stream.next_out = info->ubuf;
	if (!info->ubuf) {
	    goto memoryError;
	}
	stream.avail_out = info->numBytes;
	if (inflateInit2(&stream, -15) != Z_OK) {
	    goto corruptionError;
	}
	err = inflate(&stream, Z_SYNC_FLUSH);
	inflateEnd(&stream);

	/*
	 * Decompression was successful if we're either in the END state, or
	 * in the OK state with no buffered bytes.
	 */

	if ((err != Z_STREAM_END)
		&& ((err != Z_OK) || (stream.avail_in != 0))) {
	    goto corruptionError;
	}
	/* Even if decompression succeeded, counts should be as expected */
	if ((int) stream.total_out != z->numBytes) {
	    goto corruptionError;
	}

	if (ubuf) {
	    info->isEncrypted = 0;
	    memset(info->keys, 0, sizeof(info->keys));
	    Tcl_Free(ubuf);
	}
    } else if (info->isEncrypted) {
	unsigned int j, len;

	/*
	 * Decode encrypted but uncompressed file, since we support Tcl_Seek()
	 * on it, and it can be randomly accessed later.
	 */
	if (z->numCompressedBytes <= ZIP_CRYPT_HDR_LEN ||
		(z->numCompressedBytes - ZIP_CRYPT_HDR_LEN) != z->numBytes) {
	    goto corruptionError;
	}
	len = z->numCompressedBytes - ZIP_CRYPT_HDR_LEN;
	ubuf = (unsigned char *) Tcl_AttemptAlloc(len);
	if (ubuf == NULL) {
	    goto memoryError;
	}
	for (j = 0; j < len; j++) {
	    ch = info->ubuf[j];
	    ubuf[j] = zdecode(info->keys, crc32tab, ch);
	}
	info->ubufSize = len;
	info->ubufToFree = ubuf;
	info->ubuf = info->ubufToFree;
	ubuf = NULL; /* So it does not inadvertently get free on future changes */
	info->isEncrypted = 0;
    }
    return TCL_OK;

  corruptionError:
    ZIPFS_ERROR(interp, "decompression error");
    ZIPFS_ERROR_CODE(interp, "CORRUPT");
    goto error_cleanup;

  memoryError:
    ZIPFS_MEM_ERROR(interp);

  error_cleanup:
    if (ubuf) {
	memset(info->keys, 0, sizeof(info->keys));
	Tcl_Free(ubuf);
    }
    if (info->ubufToFree) {
	Tcl_Free(info->ubufToFree);
	info->ubufToFree = NULL;
	info->ubuf = NULL;
	info->ubufSize = 0;
    }

  wrapchan:
    sprintf(cname, "zipfs_%" TCL_LL_MODIFIER "x_%d", z->offset,
	    ZipFS.idCount++);
    z->zipFilePtr->numOpen++;
    Unlock();
    return Tcl_CreateChannel(&ZipChannelType, cname, info, flags);

  error:
    Unlock();
    return NULL;
    return TCL_ERROR;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipEntryStat --
 *
3914
3915
3916
3917
3918
3919
3920
3921

3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936











3937
3938
3939
3940
3941
3942
3943
5274
5275
5276
5277
5278
5279
5280

5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314







-
+















+
+
+
+
+
+
+
+
+
+
+








static int
ZipEntryStat(
    char *path,
    Tcl_StatBuf *buf)
{
    ZipEntry *z;
    int ret = -1;
    int ret;

    ReadLock();
    z = ZipFSLookup(path);
    if (z) {
	memset(buf, 0, sizeof(Tcl_StatBuf));
	if (z->isDirectory) {
	    buf->st_mode = S_IFDIR | 0555;
	} else {
	    buf->st_mode = S_IFREG | 0555;
	}
	buf->st_size = z->numBytes;
	buf->st_mtime = z->timestamp;
	buf->st_ctime = z->timestamp;
	buf->st_atime = z->timestamp;
	ret = 0;
    } else if (ContainsMountPoint(path, -1)) {
	/* An intermediate dir under which a mount exists */
	memset(buf, 0, sizeof(Tcl_StatBuf));
	Tcl_Time t;
	Tcl_GetTime(&t);
	buf->st_atime = buf->st_mtime = buf->st_ctime = t.sec;
	buf->st_mode = S_IFDIR | 0555;
	ret = 0;
    } else {
	Tcl_SetErrno(ENOENT);
	ret = -1;
    }
    Unlock();
    return ret;
}

/*
 *-------------------------------------------------------------------------
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966

3967
3968

3969

3970















3971
3972

3973
3974

3975
3976
3977
3978
3979



3980

3981
3982

3983
3984
3985
3986
3987
3988
3989
3990
3991
3992

3993
3994
3995
3996
3997

3998

3999
4000
4001

4002
4003
4004
4005
4006
4007
4008
5328
5329
5330
5331
5332
5333
5334



5335
5336
5337
5338
5339
5340

5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356

5357
5358

5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381

5382
5383
5384
5385
5386
5387
5388

5389

5390

5391
5392
5393
5394
5395
5396
5397
5398







-
-
-
+


+

+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
+





+
+
+

+


+









-
+





+
-
+
-

-
+







 */

static int
ZipEntryAccess(
    char *path,
    int mode)
{
    ZipEntry *z;

    if (mode & 3) {
    if (mode & X_OK) {
	return -1;
    }

    ReadLock();
    int access;
    z = ZipFSLookup(path);
    ZipEntry *z = ZipFSLookup(path);
    if (z) {
	/* Currently existing files read/write but dirs are read-only */
	access = (z->isDirectory && (mode & W_OK)) ? -1 : 0;
    } else {
	if (mode & W_OK) {
	    access = -1;
	} else {
	    /*
	     * Even if entry does not exist, could be intermediate dir
	     * containing a mount point
	     */
	    access = ContainsMountPoint(path, -1) ? 0 : -1;
	}
    }
    Unlock();
    return (z ? 0 : -1);
    return access;
}


/*
 *-------------------------------------------------------------------------
 *
 * ZipFSOpenFileChannelProc --
 *
 *	Open a channel to a file in a mounted ZIP archive. Delegates to
 *	ZipChannelOpen().
 *
 * Results:
 *	Tcl_Channel on success, or NULL on error.
 *
 * Side effects:
 *	Allocates memory.
 *
 *-------------------------------------------------------------------------
 */

static Tcl_Channel
ZipFSOpenFileChannelProc(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Obj *pathPtr,
    int mode,
    int permissions)
    TCL_UNUSED(int) /* permissions */)
{
    pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
    if (!pathPtr) {
	return NULL;
    }

    return ZipChannelOpen(interp, TclGetString(pathPtr), mode,
    return ZipChannelOpen(interp, Tcl_GetString(pathPtr), mode);
	    permissions);
}


/*
 *-------------------------------------------------------------------------
 *
 * ZipFSStatProc --
 *
 *	This function implements the ZIP filesystem specific version of the
 *	library version of stat.
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
5407
5408
5409
5410
5411
5412
5413

5414
5415
5416
5417
5418
5419
5420







-







 */

static int
ZipFSStatProc(
    Tcl_Obj *pathPtr,
    Tcl_StatBuf *buf)
{

    pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
    if (!pathPtr) {
	return -1;
    }
    return ZipEntryStat(TclGetString(pathPtr), buf);
}

4083
4084
4085
4086
4087
4088
4089
































4090
4091
4092
4093
4094
4095
4096
4097
4098

4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112





4113
4114
4115
4116
4117
4118


4119
4120




4121
4122
4123
4124
4125

















4126

4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145

4146

4147
4148
4149






4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164


4165
4166
4167


4168

4169
4170


4171
4172
4173
4174




4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190




4191
4192



4193
4194
4195
4196
4197
4198








4199
4200
4201
4202
4203


4204
4205
4206

4207
4208
4209

4210
4211
4212

4213
4214
4215




4216
4217
4218
4219

4220
4221
4222

4223
4224

4225
4226
4227
4228


4229
4230
4231
4232
4233
4234
4235










4236
4237
4238

4239
4240
4241
4242
4243
4244
4245
4246
4247
4248








4249
4250
4251



4252

4253
4254
4255
4256






























4257
4258
4259
4260
4261
4262
4263











4264
4265
4266
4267
4268
4269

4270
4271
4272
4273
4274
4275
4276



























































































4277
4278
4279
4280
4281
4282
4283
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518

5519
5520
5521
5522
5523
5524
5525
5526
5527
5528





5529
5530
5531
5532
5533
5534


5535


5536
5537
5538

5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564

5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580


5581

5582
5583
5584



5585
5586
5587
5588
5589
5590
5591

5592












5593
5594



5595
5596
5597
5598


5599
5600
5601



5602
5603
5604
5605
















5606
5607
5608
5609


5610
5611
5612






5613
5614
5615
5616
5617
5618
5619
5620





5621
5622



5623



5624



5625



5626
5627
5628
5629




5630



5631


5632




5633
5634







5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646

5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665



5666
5667
5668
5669
5670




5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700







5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711



5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
+









-
-
-
-
-
+
+
+
+
+

-
-

-
-
+
+

-
+
+
+
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+















-
-

-
+

+
-
-
-
+
+
+
+
+
+

-

-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
+

+
-
-
+
+

-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
+
+
+
-
-
-
-
+
-
-
-
+
-
-
+
-
-
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+


-
+










+
+
+
+
+
+
+
+
-
-
-
+
+
+

+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-



+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







{
    return Tcl_NewStringObj("/", -1);
}

/*
 *-------------------------------------------------------------------------
 *
 * AppendWithPrefix --
 *
 *	Worker for ZipFSMatchInDirectoryProc() that is a wrapper around
 *	Tcl_ListObjAppendElement() which knows about handling prefixes.
 *
 *-------------------------------------------------------------------------
 */

static inline void
AppendWithPrefix(
    Tcl_Obj *result,		/* Where to append a list element to. */
    Tcl_DString *prefix,	/* The prefix to add to the element, or NULL
				 * for don't do that. */
    const char *name,		/* The name to append. */
    size_t nameLen)		/* The length of the name. May be TCL_INDEX_NONE for
				 * append-up-to-NUL-byte. */
{
    if (prefix) {
	size_t prefixLength = Tcl_DStringLength(prefix);

	Tcl_DStringAppend(prefix, name, nameLen);
	Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(
		Tcl_DStringValue(prefix), Tcl_DStringLength(prefix)));
	Tcl_DStringSetLength(prefix, prefixLength);
    } else {
	Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(name, nameLen));
    }
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSMatchInDirectoryProc --
 *
 *	This routine is used by the globbing code to search a directory for
 *	all files which match a given pattern.
 *
 * Results:
 *	The return value is a standard Tcl result indicating whether an error
 *	occurred in globbing. Errors are left in interp, good results are
 *	lappend'ed to resultPtr (which must be a valid object).
 *	lappend'ed to result (which must be a valid object).
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMatchInDirectoryProc(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Obj *result,
    Tcl_Obj *pathPtr,
    const char *pattern,
    Tcl_GlobTypeData *types)
    Tcl_Interp *interp,
    Tcl_Obj *result,		/* Where to append matched items to. */
    Tcl_Obj *pathPtr,		/* Where we are looking. */
    const char *pattern,	/* What names we are looking for. */
    Tcl_GlobTypeData *types)	/* What types we are looking for. */
{
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    Tcl_Obj *normPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
    int scnt, l, dirOnly = -1, strip = 0;
    size_t len, prefixLen;
    int scnt, l;
    Tcl_Size prefixLen, len, strip = 0;
    char *pat, *prefix, *path;
    Tcl_DString dsPref;
    Tcl_DString dsPref, *prefixBuf = NULL;
    int foundInHash, notDuplicate;
    ZipEntry *z;
    int wanted; /* TCL_GLOB_TYPE* */

    if (!normPathPtr) {
	return -1;
    }
    if (types) {
	wanted = types->type;
	if ((wanted & TCL_GLOB_TYPE_MOUNT) && (wanted != TCL_GLOB_TYPE_MOUNT)) {
	    if (interp) {
		ZIPFS_ERROR(interp,
			      "Internal error: TCL_GLOB_TYPE_MOUNT should not "
			      "be set in conjunction with other glob types.");
	    }
	    return TCL_ERROR;
	}
	if ((wanted & (TCL_GLOB_TYPE_DIR | TCL_GLOB_TYPE_FILE |
		TCL_GLOB_TYPE_MOUNT)) == 0) {
	    /* Not looking for files,dirs,mounts. zipfs cannot have others */
	    return TCL_OK;
	}
	wanted &=
	    (TCL_GLOB_TYPE_DIR | TCL_GLOB_TYPE_FILE | TCL_GLOB_TYPE_MOUNT);
    } else {
	dirOnly = (types->type & TCL_GLOB_TYPE_DIR) == TCL_GLOB_TYPE_DIR;
	wanted = TCL_GLOB_TYPE_DIR | TCL_GLOB_TYPE_FILE;
    }

    /*
     * The prefix that gets prepended to results.
     */

    prefix = TclGetStringFromObj(pathPtr, &prefixLen);

    /*
     * The (normalized) path we're searching.
     */

    path = TclGetStringFromObj(normPathPtr, &len);

    Tcl_DStringInit(&dsPref);
    Tcl_DStringAppend(&dsPref, prefix, prefixLen);

    if (strcmp(prefix, path) == 0) {
	prefix = NULL;
	prefixBuf = NULL;
    } else {
	/*
	strip = len + 1;
    }
    if (prefix) {
	 * We need to strip the normalized prefix of the filenames and replace
	 * it with the official prefix that we were expecting to get.
	 */

	strip = len + 1;
	Tcl_DStringAppend(&dsPref, prefix, prefixLen);
	Tcl_DStringAppend(&dsPref, "/", 1);
	prefixLen++;
	prefix = Tcl_DStringValue(&dsPref);
    }
    ReadLock();
    if (types && (types->type == TCL_GLOB_TYPE_MOUNT)) {
	l = CountSlashes(path);
	if (path[len - 1] == '/') {
	    len--;
	} else {
	    l++;
	}
	if (!pattern || (pattern[0] == '\0')) {
	    pattern = "*";
	}
	prefixBuf = &dsPref;
    }
	for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
		hPtr = Tcl_NextHashEntry(&search)) {
	    ZipFile *zf = (ZipFile *)Tcl_GetHashValue(hPtr);

    ReadLock();

    /*
	    if (zf->mountPointLen == 0) {
		ZipEntry *z;
     * Are we globbing the mount points?
     */

		for (z = zf->topEnts; z; z = z->tnext) {
		    size_t lenz = strlen(z->name);

    if (wanted & TCL_GLOB_TYPE_MOUNT) {
	ZipFSMatchMountPoints(result, normPathPtr, pattern, prefixBuf);
	goto end;
    }
		    if ((lenz > len + 1) && (strncmp(z->name, path, len) == 0)
			    && (z->name[len] == '/')
			    && (CountSlashes(z->name) == l)
			    && Tcl_StringCaseMatch(z->name + len + 1, pattern,
				    0)) {
			if (prefix) {
			    Tcl_DStringAppend(&dsPref, z->name, lenz);
			    Tcl_ListObjAppendElement(NULL, result,
				    Tcl_NewStringObj(Tcl_DStringValue(&dsPref),
					    Tcl_DStringLength(&dsPref)));
			    Tcl_DStringSetLength(&dsPref, prefixLen);
			} else {
			    Tcl_ListObjAppendElement(NULL, result,
				    Tcl_NewStringObj(z->name, lenz));
			}
		    }

    /* Should not reach here unless at least one of DIR or FILE is set */
    assert(wanted & (TCL_GLOB_TYPE_DIR | TCL_GLOB_TYPE_FILE));

		}
	    } else if ((zf->mountPointLen > len + 1)
    /* Does the path exist in the hash table? */
    z = ZipFSLookup(path);
    if (z) {
		    && (strncmp(zf->mountPoint, path, len) == 0)
		    && (zf->mountPoint[len] == '/')
		    && (CountSlashes(zf->mountPoint) == l)
		    && Tcl_StringCaseMatch(zf->mountPoint + len + 1,
			    pattern, 0)) {
		if (prefix) {
	/*
	 * Can we skip the complexity of actual globbing? Without a pattern,
	 * yes; it's a directory existence test.
	 */
	if (!pattern || (pattern[0] == '\0')) {
	    /* TODO - can't seem to get to this code from script for tests. */
	    /* Follow logic of what tclUnixFile.c does */
	    if ((wanted == (TCL_GLOB_TYPE_DIR | TCL_GLOB_TYPE_FILE)) ||
		    Tcl_DStringAppend(&dsPref, zf->mountPoint,
			    zf->mountPointLen);
		    Tcl_ListObjAppendElement(NULL, result,
			    Tcl_NewStringObj(Tcl_DStringValue(&dsPref),
				    Tcl_DStringLength(&dsPref)));
		    (wanted == TCL_GLOB_TYPE_DIR && z->isDirectory) ||
		    (wanted == TCL_GLOB_TYPE_FILE && !z->isDirectory)) {
		    Tcl_DStringSetLength(&dsPref, prefixLen);
		} else {
		    Tcl_ListObjAppendElement(NULL, result,
		Tcl_ListObjAppendElement(NULL, result, pathPtr);
			    Tcl_NewStringObj(zf->mountPoint,
				    zf->mountPointLen));
		}
	    }
	    }
	}
	goto end;
	    goto end;
    }

    if (!pattern || (pattern[0] == '\0')) {
	}
    } else {
	/* Not in the hash table but could be an intermediate dir in a mount */
	if (!pattern || (pattern[0] == '\0')) {
	hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, path);
	if (hPtr) {
	    ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr);

	    /* TODO - can't seem to get to this code from script for tests. */
	    if ((dirOnly < 0) || (!dirOnly && !z->isDirectory)
		    || (dirOnly && z->isDirectory)) {
		if (prefix) {
	    if ((wanted & TCL_GLOB_TYPE_DIR) && ContainsMountPoint(path, len)) {
		    Tcl_DStringAppend(&dsPref, z->name, -1);
		    Tcl_ListObjAppendElement(NULL, result,
		Tcl_ListObjAppendElement(NULL, result, pathPtr);
			    Tcl_NewStringObj(Tcl_DStringValue(&dsPref),
				    Tcl_DStringLength(&dsPref)));
		    Tcl_DStringSetLength(&dsPref, prefixLen);
		} else {
	    }
	    goto end;
		    Tcl_ListObjAppendElement(NULL, result,
			    Tcl_NewStringObj(z->name, -1));
		}
	    }
	}
	goto end;
    }
	}
    }

    foundInHash = (z != NULL);

    /*
     * We've got to work for our supper and do the actual globbing. And all
     * we've got really is an undifferentiated pile of all the filenames we've
     * got from all our ZIP mounts.
     */

    l = strlen(pattern);
    pat = (char *)Tcl_Alloc(len + l + 2);
    pat = (char *) Tcl_Alloc(len + l + 2);
    memcpy(pat, path, len);
    while ((len > 1) && (pat[len - 1] == '/')) {
	--len;
    }
    if ((len > 1) || (pat[0] != '/')) {
	pat[len] = '/';
	++len;
    }
    memcpy(pat + len, pattern, l + 1);
    scnt = CountSlashes(pat);

    Tcl_HashTable duplicates;
    notDuplicate = 0;
    Tcl_InitHashTable(&duplicates, TCL_STRING_KEYS);

    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    if (foundInHash) {
    for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search);
	    hPtr; hPtr = Tcl_NextHashEntry(&search)) {
	ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr);
	for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); hPtr;
		hPtr = Tcl_NextHashEntry(&search)) {
	    z = (ZipEntry *)Tcl_GetHashValue(hPtr);

	    if ((wanted == (TCL_GLOB_TYPE_DIR | TCL_GLOB_TYPE_FILE)) ||
	if ((dirOnly >= 0) && ((dirOnly && !z->isDirectory)
		|| (!dirOnly && z->isDirectory))) {
	    continue;
	}
		    (wanted == TCL_GLOB_TYPE_DIR && z->isDirectory) ||
		    (wanted == TCL_GLOB_TYPE_FILE && !z->isDirectory)) {
		if ((z->depth == scnt) &&
			((z->flags & ZE_F_VOLUME) == 0) /* Bug 14db54d81e */
			&& Tcl_StringCaseMatch(z->name, pat, 0)) {
		    Tcl_CreateHashEntry(&duplicates, z->name + strip,
			    &notDuplicate);
		    assert(notDuplicate);
		    AppendWithPrefix(result, prefixBuf, z->name + strip, -1);
		}
	    }
	}
    }
    if (wanted & TCL_GLOB_TYPE_DIR) {
	/*
	 * Also check paths that are ancestors of a mount. e.g. glob
	 * //zipfs:/a/? with mount at //zipfs:/a/b/c. Also have to be
	 * careful about duplicates, such as when another mount is
	 * //zipfs:/a/b/d
	 */
	Tcl_DString ds;
	Tcl_DStringInit(&ds);
	for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
		hPtr = Tcl_NextHashEntry(&search)) {
	    ZipFile *zf = (ZipFile *)Tcl_GetHashValue(hPtr);
	    if (Tcl_StringCaseMatch(zf->mountPoint, pat, 0)) {
		const char *tail = zf->mountPoint + len;
		if (*tail == '\0') {
		    continue;
		}
	if ((z->depth == scnt) && Tcl_StringCaseMatch(z->name, pat, 0)) {
	    if (prefix) {
		Tcl_DStringAppend(&dsPref, z->name + strip, -1);
		Tcl_ListObjAppendElement(NULL, result,
			Tcl_NewStringObj(Tcl_DStringValue(&dsPref),
				Tcl_DStringLength(&dsPref)));
		Tcl_DStringSetLength(&dsPref, prefixLen);
		const char *end = strchr(tail, '/');
		Tcl_DStringAppend(&ds, zf->mountPoint + strip,
			end ? (Tcl_Size)(end - zf->mountPoint) : -1);
		const char *matchedPath = Tcl_DStringValue(&ds);
		(void)Tcl_CreateHashEntry(
		    &duplicates, matchedPath, &notDuplicate);
		if (notDuplicate) {
		    AppendWithPrefix(
			result, prefixBuf, matchedPath, Tcl_DStringLength(&ds));
		}
		Tcl_DStringFree(&ds);
	    } else {
		Tcl_ListObjAppendElement(NULL, result,
			Tcl_NewStringObj(z->name + strip, -1));
	    }
	}
    }
    Tcl_DeleteHashTable(&duplicates);
    Tcl_Free(pat);

  end:
    Unlock();
    Tcl_DStringFree(&dsPref);
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSMatchMountPoints --
 *
 *	This routine is a worker for ZipFSMatchInDirectoryProc, used by the
 *	globbing code to search for all mount points files which match a given
 *	pattern.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Adds the matching mounts to the list in result, uses prefix as working
 *	space if it is non-NULL.
 *
 *-------------------------------------------------------------------------
 */

static void
ZipFSMatchMountPoints(
    Tcl_Obj *result,		/* The list of matches being built. */
    Tcl_Obj *normPathPtr,	/* Where we're looking from. */
    const char *pattern,	/* What we're looking for. NULL for a full
				 * list. */
    Tcl_DString *prefix)	/* Workspace filled with a prefix for all the
				 * filenames, or NULL if no prefix is to be
				 * used. */
{
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    int l;
    Tcl_Size normLength;
    const char *path = TclGetStringFromObj(normPathPtr, &normLength);
    Tcl_Size len = normLength;

    if (len < 1) {
	/*
	 * Shouldn't happen. But "shouldn't"...
	 */

	return;
    }
    l = CountSlashes(path);
    if (path[len - 1] == '/') {
	len--;
    } else {
	l++;
    }
    if (!pattern || (pattern[0] == '\0')) {
	pattern = "*";
    }

    for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
	    hPtr = Tcl_NextHashEntry(&search)) {
	ZipFile *zf = (ZipFile *) Tcl_GetHashValue(hPtr);

	if (zf->mountPointLen == 0) {
	    ZipEntry *z;

	    /*
	     * Enumerate the contents of the ZIP; it's mounted on the root.
	     * TODO - a holdover from androwish? Tcl does not allow mounting
	     * outside of the //zipfs:/ area.
	     */

	    for (z = zf->topEnts; z; z = z->tnext) {
		Tcl_Size lenz = strlen(z->name);

		if ((lenz > len + 1) && (strncmp(z->name, path, len) == 0)
			&& (z->name[len] == '/')
			&& ((int) CountSlashes(z->name) == l)
			&& Tcl_StringCaseMatch(z->name + len + 1, pattern, 0)) {
		    AppendWithPrefix(result, prefix, z->name, lenz);
		}
	    }
	} else if ((zf->mountPointLen > len + 1)
		&& (strncmp(zf->mountPoint, path, len) == 0)
		&& (zf->mountPoint[len] == '/')
		&& ((int) CountSlashes(zf->mountPoint) == l)
		&& Tcl_StringCaseMatch(zf->mountPoint + len + 1,
			pattern, 0)) {
	    /*
	     * Standard mount; append if it matches.
	     */

	    AppendWithPrefix(result, prefix, zf->mountPoint, zf->mountPointLen);
	}
    }
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSPathInFilesystemProc --
 *
 *	This function determines if the given path object is in the ZIP
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
5828
5829
5830
5831
5832
5833
5834

5835
5836











5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864




5865
5866







5867




5868



5869



5870


5871






5872
5873
5874


5875
5876
5877
5878



5879
5880
5881
5882
5883
5884
5885







-
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
+
-
-
-
+
-
-
+
-
-
-
-
-
-
+
+
+
-
-
+
+
+

-
-
-







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

static int
ZipFSPathInFilesystemProc(
    Tcl_Obj *pathPtr,
    TCL_UNUSED(ClientData *))
    TCL_UNUSED(void **))
{
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    int ret = -1;
    size_t len;
    char *path;

    pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
    if (!pathPtr) {
	return -1;
    }

    Tcl_Size len;
    char *path;
    int ret, decrRef = 0;

    if (TclFSCwdIsNative() || Tcl_FSGetPathType(pathPtr) == TCL_PATH_ABSOLUTE) {
	/*
	 * The cwd is native (or path is absolute), use the translated path
	 * without worrying about normalization (this will also usually be
	 * shorter so the utf-to-external conversion will be somewhat faster).
	 */

	pathPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
	if (pathPtr == NULL) {
	    return -1;
	}
	decrRef = 1; /* Tcl_FSGetTranslatedPath increases refCount */
    } else {
	/*
	 * Make sure the normalized path is set.
	 */

	pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
	if (!pathPtr) {
	    return -1;
	}
	/* Tcl_FSGetNormalizedPath doesn't increase refCount */
    }
    path = TclGetStringFromObj(pathPtr, &len);
    if (strncmp(path, ZIPFS_VOLUME, ZIPFS_VOLUME_LEN) != 0) {
	return -1;
    }


    /*
    ReadLock();
    hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, path);
    if (hPtr) {
	ret = TCL_OK;
	goto endloop;
    }

     * Claim any path under ZIPFS_VOLUME as ours. This is both a necessary
    for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
	    hPtr = Tcl_NextHashEntry(&search)) {
	ZipFile *zf = (ZipFile *)Tcl_GetHashValue(hPtr);

     * and sufficient condition as zipfs mounts at arbitrary paths are
	if (zf->mountPointLen == 0) {
	    ZipEntry *z;

     * not permitted (unlike Androwish).
	    for (z = zf->topEnts; z != NULL; z = z->tnext) {
		size_t lenz = strlen(z->name);

     */
		if ((len >= lenz) && (strncmp(path, z->name, lenz) == 0)) {
		    ret = TCL_OK;
    ret = (
		    goto endloop;
		}
	    }
	} else if ((len >= zf->mountPointLen) &&
		(strncmp(path, zf->mountPoint, zf->mountPointLen) == 0)) {
	    ret = TCL_OK;
	(len < ZIPFS_VOLUME_LEN) ||
	strncmp(path, ZIPFS_VOLUME, ZIPFS_VOLUME_LEN)
    ) ? -1 : TCL_OK;
	    break;
	}

    if (decrRef) {
	Tcl_DecrRefCount(pathPtr);
    }

  endloop:
    Unlock();
    return ret;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSListVolumesProc --
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
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955







+
+
+
+
+
+
+
+
+
+






+
+
+
+







+







 *	An array of strings
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

enum ZipFileAttrs {
    ZIP_ATTR_UNCOMPSIZE,
    ZIP_ATTR_COMPSIZE,
    ZIP_ATTR_OFFSET,
    ZIP_ATTR_MOUNT,
    ZIP_ATTR_ARCHIVE,
    ZIP_ATTR_PERMISSIONS,
    ZIP_ATTR_CRC
};

static const char *const *
ZipFSFileAttrStringsProc(
    TCL_UNUSED(Tcl_Obj *) /*pathPtr*/,
    TCL_UNUSED(Tcl_Obj **) /*objPtrRef*/)
{
    /*
     * Must match up with ZipFileAttrs enum above.
     */

    static const char *const attrs[] = {
	"-uncompsize",
	"-compsize",
	"-offset",
	"-mount",
	"-archive",
	"-permissions",
	"-crc",
	NULL,
    };

    return attrs;
}

/*
4428
4429
4430
4431
4432
4433
4434

4435
4436
4437
4438
4439
4440
4441
4442
4443

4444
4445
4446

4447
4448
4449
4450
4451

4452
4453
4454


4455
4456
4457


4458
4459
4460


4461
4462
4463
4464







4465
4466
4467


4468
4469

4470
4471



4472
4473

4474
4475
4476
4477
4478
4479
4480
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990

5991
5992
5993

5994
5995
5996
5997
5998
5999
6000
6001


6002
6003
6004


6005
6006
6007


6008
6009
6010



6011
6012
6013
6014
6015
6016
6017
6018


6019
6020
6021

6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037







+








-
+


-
+





+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
-
+
+
+
+
+
+
+

-
-
+
+

-
+


+
+
+


+







static int
ZipFSFileAttrsGetProc(
    Tcl_Interp *interp,		/* Current interpreter. */
    int index,
    Tcl_Obj *pathPtr,
    Tcl_Obj **objPtrRef)
{
    Tcl_Size len;
    int ret = TCL_OK;
    char *path;
    ZipEntry *z;

    pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
    if (!pathPtr) {
	return -1;
    }
    path = TclGetString(pathPtr);
    path = TclGetStringFromObj(pathPtr, &len);
    ReadLock();
    z = ZipFSLookup(path);
    if (!z) {
    if (!z && !ContainsMountPoint(path, -1)) {
	Tcl_SetErrno(ENOENT);
	ZIPFS_POSIX_ERROR(interp, "file not found");
	ret = TCL_ERROR;
	goto done;
    }
    /* z == NULL for intermediate directories that are ancestors of mounts */
    switch (index) {
    case 0:
	TclNewIntObj(*objPtrRef, z->numBytes);
    case ZIP_ATTR_UNCOMPSIZE:
	TclNewIntObj(*objPtrRef, z ? z->numBytes : 0);
	break;
    case 1:
	TclNewIntObj(*objPtrRef, z->numCompressedBytes);
    case ZIP_ATTR_COMPSIZE:
	TclNewIntObj(*objPtrRef, z ? z->numCompressedBytes : 0);
	break;
    case 2:
	TclNewIntObj(*objPtrRef, z->offset);
    case ZIP_ATTR_OFFSET:
	TclNewIntObj(*objPtrRef, z ? z->offset : 0);
	break;
    case 3:
	*objPtrRef = Tcl_NewStringObj(z->zipFilePtr->mountPoint,
		z->zipFilePtr->mountPointLen);
    case ZIP_ATTR_MOUNT:
	if (z) {
	    *objPtrRef = Tcl_NewStringObj(z->zipFilePtr->mountPoint,
					  z->zipFilePtr->mountPointLen);
	} else {
	    *objPtrRef = Tcl_NewStringObj("", 0);
	}
	break;
    case 4:
	*objPtrRef = Tcl_NewStringObj(z->zipFilePtr->name, -1);
    case ZIP_ATTR_ARCHIVE:
	*objPtrRef = Tcl_NewStringObj(z ? z->zipFilePtr->name : "", -1);
	break;
    case 5:
    case ZIP_ATTR_PERMISSIONS:
	*objPtrRef = Tcl_NewStringObj("0o555", -1);
	break;
    case ZIP_ATTR_CRC:
	TclNewIntObj(*objPtrRef, z ? z->crc32 : 0);
	break;
    default:
	ZIPFS_ERROR(interp, "unknown attribute");
	ZIPFS_ERROR_CODE(interp, "FILE_ATTR");
	ret = TCL_ERROR;
    }

  done:
    Unlock();
    return ret;
}
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508


4509
4510
4511
4512
4513
4514
4515
4516
6056
6057
6058
6059
6060
6061
6062



6063
6064

6065
6066
6067
6068
6069
6070
6071







-
-
-
+
+
-







static int
ZipFSFileAttrsSetProc(
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*index*/,
    TCL_UNUSED(Tcl_Obj *) /*pathPtr*/,
    TCL_UNUSED(Tcl_Obj *) /*objPtr*/)
{
    if (interp) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("unsupported operation", -1));
	Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "UNSUPPORTED_OP", NULL);
    ZIPFS_ERROR(interp, "unsupported operation");
    ZIPFS_ERROR_CODE(interp, "UNSUPPORTED_OP");
    }
    return TCL_ERROR;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSFilesystemPathTypeProc --
4604
4605
4606
4607
4608
4609
4610
4611

4612
4613
4614
4615
4616
4617
4618
6159
6160
6161
6162
6163
6164
6165

6166
6167
6168
6169
6170
6171
6172
6173







-
+







	 * [file dirname [info nameofexecutable]] is equal to [info
	 * nameofexecutable] due to VFS effects.
	 */

	if (execName) {
	    const char *p = strrchr(execName, '/');

	    if (p > execName + 1) {
	    if (p && p > execName + 1) {
		--p;
		objs[0] = Tcl_NewStringObj(execName, p - execName);
	    }
	}
	if (!objs[0]) {
	    objs[0] = TclPathPart(interp, TclGetObjNameOfExecutable(),
		    TCL_PATH_DIRNAME);
4630
4631
4632
4633
4634
4635
4636
4637


4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
6185
6186
6187
6188
6189
6190
6191

6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205


6206
6207
6208
6209
6210
6211
6212







-
+
+












-
-







    if (objs[0]) {
	Tcl_DecrRefCount(objs[0]);
    }
    if (objs[1]) {
	Tcl_DecrRefCount(objs[1]);
    }

    loadFileProc = (Tcl_FSLoadFileProc2 *)(void *)tclNativeFilesystem.loadFileProc;
    loadFileProc = (Tcl_FSLoadFileProc2 *) (void *)
	    tclNativeFilesystem.loadFileProc;
    if (loadFileProc) {
	ret = loadFileProc(interp, path, loadHandle, unloadProcPtr, flags);
    } else {
	Tcl_SetErrno(ENOENT);
	ZIPFS_ERROR(interp, Tcl_PosixError(interp));
    }
    if (altPath) {
	Tcl_DecrRefCount(altPath);
    }
    return ret;
#endif /* ANDROID */
}

#endif /* HAVE_ZLIB */

/*
 *-------------------------------------------------------------------------
 *
 * TclZipfs_Init --
 *
 *	Perform per interpreter initialization of this module.
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682

4683
4684
4685
4686
4687
4688
4689





4690
4691
4692
4693
4694
4695
4696



4697
4698
4699
4700
4701
4702
4703
6221
6222
6223
6224
6225
6226
6227

6228
6229
6230
6231
6232

6233

6234
6235
6236





6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247

6248
6249
6250
6251
6252
6253
6254
6255
6256
6257







-





-

-
+


-
-
-
-
-
+
+
+
+
+






-
+
+
+







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

int
TclZipfs_Init(
    Tcl_Interp *interp)		/* Current interpreter. */
{
#ifdef HAVE_ZLIB
    static const EnsembleImplMap initMap[] = {
	{"mkimg",	ZipFSMkImgObjCmd,	NULL, NULL, NULL, 1},
	{"mkzip",	ZipFSMkZipObjCmd,	NULL, NULL, NULL, 1},
	{"lmkimg",	ZipFSLMkImgObjCmd,	NULL, NULL, NULL, 1},
	{"lmkzip",	ZipFSLMkZipObjCmd,	NULL, NULL, NULL, 1},
	/* The 4 entries above are not available in safe interpreters */
	{"mount",	ZipFSMountObjCmd,	NULL, NULL, NULL, 1},
	{"mount_data",	ZipFSMountBufferObjCmd,	NULL, NULL, NULL, 1},
	{"mountdata",	ZipFSMountBufferObjCmd,	NULL, NULL, NULL, 1},
	{"unmount",	ZipFSUnmountObjCmd,	NULL, NULL, NULL, 1},
	{"mkkey",	ZipFSMkKeyObjCmd,	NULL, NULL, NULL, 1},
	{"exists",	ZipFSExistsObjCmd,	NULL, NULL, NULL, 0},
	{"info",	ZipFSInfoObjCmd,	NULL, NULL, NULL, 0},
	{"list",	ZipFSListObjCmd,	NULL, NULL, NULL, 0},
	{"canonical",	ZipFSCanonicalObjCmd,	NULL, NULL, NULL, 0},
	{"root",	ZipFSRootObjCmd,	NULL, NULL, NULL, 0},
	{"exists",	ZipFSExistsObjCmd,	NULL, NULL, NULL, 1},
	{"info",	ZipFSInfoObjCmd,	NULL, NULL, NULL, 1},
	{"list",	ZipFSListObjCmd,	NULL, NULL, NULL, 1},
	{"canonical",	ZipFSCanonicalObjCmd,	NULL, NULL, NULL, 1},
	{"root",	ZipFSRootObjCmd,	NULL, NULL, NULL, 1},
	{NULL, NULL, NULL, NULL, NULL, 0}
    };
    static const char findproc[] =
	"namespace eval ::tcl::zipfs {}\n"
	"proc ::tcl::zipfs::Find dir {\n"
	"    set result {}\n"
	"    if {[catch {glob -directory $dir -nocomplain * .*} list]} {\n"
	"    if {[catch {\n"
	"        concat [glob -directory $dir -nocomplain *] [glob -directory $dir -types hidden -nocomplain *]\n"
	"    } list]} {\n"
	"        return $result\n"
	"    }\n"
	"    foreach file $list {\n"
	"        if {[file tail $file] in {. ..}} {\n"
	"            continue\n"
	"        }\n"
	"        lappend result $file {*}[Find $file]\n"
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727







4728
4729
4730
4731
4732
4733
4734
4735
4736
4737

4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749

4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760

4761
4762
4763
4764
4765
4766
4767
6272
6273
6274
6275
6276
6277
6278



6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293


6294
6295
6296

6297
6298





6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311

6312
6313
6314
6315
6316
6317
6318
6319







-
-
-
+
+
+
+
+
+
+








-
-
+


-


-
-
-
-
-


+










-
+







    }
    Unlock();

    if (interp) {
	Tcl_Command ensemble;
	Tcl_Obj *mapObj;

	Tcl_EvalEx(interp, findproc, -1, TCL_EVAL_GLOBAL);
	Tcl_LinkVar(interp, "::tcl::zipfs::wrmax", (char *) &ZipFS.wrmax,
		TCL_LINK_INT);
	Tcl_EvalEx(interp, findproc, TCL_INDEX_NONE, TCL_EVAL_GLOBAL);
	if (!Tcl_IsSafe(interp)) {
	    Tcl_LinkVar(interp, "::tcl::zipfs::wrmax", (char *) &ZipFS.wrmax,
		    TCL_LINK_INT);
	    Tcl_LinkVar(interp, "::tcl::zipfs::fallbackEntryEncoding",
		    (char *) &ZipFS.fallbackEntryEncoding, TCL_LINK_STRING);
	}
	ensemble = TclMakeEnsemble(interp, "zipfs",
		Tcl_IsSafe(interp) ? (initMap + 4) : initMap);

	/*
	 * Add the [zipfs find] subcommand.
	 */

	Tcl_GetEnsembleMappingDict(NULL, ensemble, &mapObj);
	Tcl_DictObjPut(NULL, mapObj, Tcl_NewStringObj("find", -1),
		Tcl_NewStringObj("::tcl::zipfs::find", -1));
	TclDictPutString(NULL, mapObj, "find", "::tcl::zipfs::find");
	Tcl_CreateObjCommand(interp, "::tcl::zipfs::tcl_library_init",
		ZipFSTclLibraryObjCmd, NULL, NULL);
	Tcl_PkgProvideEx(interp, "zipfs", "2.0", NULL);
    }
    return TCL_OK;
#else /* !HAVE_ZLIB */
    ZIPFS_ERROR(interp, "no zlib available");
    Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "NO_ZLIB", NULL);
    return TCL_ERROR;
#endif /* HAVE_ZLIB */
}

#if !defined(STATIC_BUILD)
static int
ZipfsAppHookFindTclInit(
    const char *archive)
{
    Tcl_Obj *vfsInitScript;
    int found;

    if (zipfs_literal_tcl_library) {
	return TCL_ERROR;
    }
    if (TclZipfs_Mount(NULL, ZIPFS_ZIP_MOUNT, archive, NULL)) {
    if (TclZipfs_Mount(NULL, archive, ZIPFS_ZIP_MOUNT, NULL)) {
	/* Either the file doesn't exist or it is not a zip archive */
	return TCL_ERROR;
    }

    TclNewLiteralStringObj(vfsInitScript, ZIPFS_ZIP_MOUNT "/init.tcl");
    Tcl_IncrRefCount(vfsInitScript);
    found = Tcl_FSAccess(vfsInitScript, F_OK);
4779
4780
4781
4782
4783
4784
4785

4786

















4787
4788


4789
4790










4791
4792
4793
4794













4795



4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808

4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821


4822
4823
4824

4825
4826

4827
4828

4829
4830
4831
4832
4833
4834
4835
4836

4837
4838
4839
4840
4841
4842
4843
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356


6357
6358

6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369




6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398

6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411

6412
6413
6414
6415

6416
6417

6418
6419

6420
6421
6422
6423
6424
6425
6426
6427

6428
6429
6430
6431
6432
6433
6434
6435







+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-

+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+












-
+












-
+
+


-
+

-
+

-
+







-
+







    if (found == 0) {
	zipfs_literal_tcl_library = ZIPFS_ZIP_MOUNT "/tcl_library";
	return TCL_OK;
    }

    return TCL_ERROR;
}
#endif

/*
 *------------------------------------------------------------------------
 *
 * TclZipfsFinalize --
 *
 *    Frees all zipfs resources IRRESPECTIVE of open channels (there should
 *    not be any!) etc. To be called at process exit time (from
 *    Tcl_Finalize->TclFinalizeFilesystem)
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Frees up archives loaded into memory.
 *
 *------------------------------------------------------------------------
 */
static void
ZipfsExitHandler(
void
TclZipfsFinalize(void)
    ClientData clientData)
{
    WriteLock();
    if (!ZipFS.initialized) {
	Unlock();
	return;
    }

    Tcl_HashEntry *hPtr;
    Tcl_HashSearch zipSearch;
    for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &zipSearch); hPtr;
	    hPtr = Tcl_NextHashEntry(&zipSearch)) {
    ZipFile *zf = (ZipFile *)clientData;

    if (TCL_OK != TclZipfs_Unmount(NULL, zf->mountPoint)) {
	Tcl_Panic("tried to unmount busy filesystem");
	ZipFile *zf = (ZipFile *) Tcl_GetHashValue(hPtr);
	Tcl_DeleteHashEntry(hPtr);
	CleanupMount(zf); /* Frees file entries belonging to the archive */
	ZipFSCloseArchive(NULL, zf);
	Tcl_Free(zf);
    }

    Tcl_FSUnregister(&zipfsFilesystem);
    Tcl_DeleteHashTable(&ZipFS.fileHash);
    Tcl_DeleteHashTable(&ZipFS.zipHash);
    if (ZipFS.fallbackEntryEncoding) {
	Tcl_Free(ZipFS.fallbackEntryEncoding);
	ZipFS.fallbackEntryEncoding = NULL;
    }

    ZipFS.initialized = 0;
    Unlock();
}

/*
 *-------------------------------------------------------------------------
 *
 * TclZipfs_AppHook --
 *
 *	Performs the argument munging for the shell
 *
 *-------------------------------------------------------------------------
 */

int
const char *
TclZipfs_AppHook(
#ifdef SUPPORT_BUILTIN_ZIP_INSTALL
    int *argcPtr,		/* Pointer to argc */
#else
    TCL_UNUSED(int *), /*argcPtr*/
#endif
#ifdef _WIN32
    TCL_UNUSED(WCHAR ***)) /* argvPtr */
#else /* !_WIN32 */
    char ***argvPtr)		/* Pointer to argv */
#endif /* _WIN32 */
{
    char *archive;
    const char *archive;
    const char *result;

#ifdef _WIN32
    Tcl_FindExecutable(NULL);
    result = Tcl_FindExecutable(NULL);
#else
    Tcl_FindExecutable((*argvPtr)[0]);
    result = Tcl_FindExecutable((*argvPtr)[0]);
#endif
    archive = (char *) Tcl_GetNameOfExecutable();
    archive = Tcl_GetNameOfExecutable();
    TclZipfs_Init(NULL);

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

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

	TclNewLiteralStringObj(vfsInitScript, ZIPFS_APP_MOUNT "/main.tcl");
	Tcl_IncrRefCount(vfsInitScript);
	if (Tcl_FSAccess(vfsInitScript, F_OK) == 0) {
	    /*
4857
4858
4859
4860
4861
4862
4863
4864

4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878

4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898


4899
4900
4901
4902
4903
4904
4905
6449
6450
6451
6452
6453
6454
6455

6456
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







-
+













-
+


















-
-
+
+







	    TclNewLiteralStringObj(vfsInitScript,
		    ZIPFS_APP_MOUNT "/tcl_library/init.tcl");
	    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 TCL_OK;
		return result;
	    }
	}
#ifdef SUPPORT_BUILTIN_ZIP_INSTALL
    } else if (*argcPtr > 1) {
	/*
	 * If the first argument is "install", run the supplied installer
	 * script.
	 */

#ifdef _WIN32
	Tcl_DString ds;

	Tcl_DStringInit(&ds);
	archive = Tcl_WCharToUtfDString((*argvPtr)[1], -1, &ds);
	archive = Tcl_WCharToUtfDString((*argvPtr)[1], TCL_INDEX_NONE, &ds);
#else /* !_WIN32 */
	archive = (*argvPtr)[1];
#endif /* _WIN32 */
	if (strcmp(archive, "install") == 0) {
	    Tcl_Obj *vfsInitScript;

	    /*
	     * Run this now to ensure the file is present by the time Tcl_Main
	     * wants it.
	     */

	    TclZipfs_TclLibrary();
	    TclNewLiteralStringObj(vfsInitScript,
		    ZIPFS_ZIP_MOUNT "/tcl_library/install.tcl");
	    Tcl_IncrRefCount(vfsInitScript);
	    if (Tcl_FSAccess(vfsInitScript, F_OK) == 0) {
		Tcl_SetStartupScript(vfsInitScript, NULL);
	    }
	    return TCL_OK;
	} else if (!TclZipfs_Mount(NULL, ZIPFS_APP_MOUNT, archive, NULL)) {
	    return result;
	} else if (!TclZipfs_Mount(NULL, archive, ZIPFS_APP_MOUNT, NULL)) {
	    int found;
	    Tcl_Obj *vfsInitScript;

	    TclNewLiteralStringObj(vfsInitScript, ZIPFS_APP_MOUNT "/main.tcl");
	    Tcl_IncrRefCount(vfsInitScript);
	    if (Tcl_FSAccess(vfsInitScript, F_OK) == 0) {
		/*
4914
4915
4916
4917
4918
4919
4920
4921

4922
4923
4924
4925
4926
4927
4928
4929

4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
6506
6507
6508
6509
6510
6511
6512

6513
6514
6515
6516
6517
6518
6519
6520

6521
6522























































6523
6524
6525
6526
6527
6528
6529
6530







-
+







-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








	    TclNewLiteralStringObj(vfsInitScript,
		    ZIPFS_APP_MOUNT "/tcl_library/init.tcl");
	    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 TCL_OK;
		return result;
	    }
	}
#ifdef _WIN32
	Tcl_DStringFree(&ds);
#endif /* _WIN32 */
#endif /* SUPPORT_BUILTIN_ZIP_INSTALL */
    }
    return TCL_OK;
    return result;
}

#ifndef HAVE_ZLIB

/*
 *-------------------------------------------------------------------------
 *
 * TclZipfs_Mount, TclZipfs_MountBuffer, TclZipfs_Unmount --
 *
 *	Dummy version when no ZLIB support available.
 *
 *-------------------------------------------------------------------------
 */

int
TclZipfs_Mount(
    Tcl_Interp *interp,		/* Current interpreter. */
    const char *mountPoint,	/* Mount point path. */
    const char *zipname,	/* Path to ZIP file to mount. */
    const char *passwd)		/* Password for opening the ZIP, or NULL if
				 * the ZIP is unprotected. */
{
    ZIPFS_ERROR(interp, "no zlib available");
    if (interp) {
	Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "NO_ZLIB", NULL);
    }
    return TCL_ERROR;
}

int
TclZipfs_MountBuffer(
    Tcl_Interp *interp,		/* Current interpreter. NULLable. */
    const char *mountPoint,	/* Mount point path. */
    unsigned char *data,
    size_t datalen,
    int copy)
{
    ZIPFS_ERROR(interp, "no zlib available");
    if (interp) {
	Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "NO_ZLIB", NULL);
    }
    return TCL_ERROR;
}

int
TclZipfs_Unmount(
    Tcl_Interp *interp,		/* Current interpreter. */
    const char *mountPoint)	/* Mount point path. */
{
    ZIPFS_ERROR(interp, "no zlib available");
    if (interp) {
	Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "NO_ZLIB", NULL);
    }
    return TCL_ERROR;
}
#endif /* !HAVE_ZLIB */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclZlib.c.

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
30
31
32
33
34
35
36
37
38
39
40






41
42
43
44
45
46
47
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
30
31
32
33
34





35
36
37
38
39
40
41
42
43
44
45
46
47





-
-
-
+
+
+









-
-
+
















-
-
-
-
-
+
+
+
+
+
+







/*
 * tclZlib.c --
 *
 *	This file provides the interface to the Zlib library.
 *
 * Copyright (C) 2004-2005 Pascal Scheffers <pascal@scheffers.net>
 * Copyright (C) 2005 Unitas Software B.V.
 * Copyright (c) 2008-2012 Donal K. Fellows
 * Copyright © 2004-2005 Pascal Scheffers <pascal@scheffers.net>
 * Copyright © 2005 Unitas Software B.V.
 * Copyright © 2008-2012 Donal K. Fellows
 *
 * Parts written by Jean-Claude Wippler, as part of Tclkit, placed in the
 * public domain March 2003.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#ifdef HAVE_ZLIB
#include <zlib.h>
#include "zlib.h"
#include "tclIO.h"

/*
 * The version of the zlib "package" that this implements. Note that this
 * thoroughly supersedes the versions included with tclkit, which are "1.1",
 * so this is at least "2.0" (there's no general *commitment* to have the same
 * interface, even if that is mostly true).
 */

#define TCL_ZLIB_VERSION	"2.0.1"

/*
 * Magic flags used with wbits fields to indicate that we're handling the gzip
 * format or automatic detection of format. Putting it here is slightly less
 * gross!
 */

#define WBITS_RAW		(-MAX_WBITS)
#define WBITS_ZLIB		(MAX_WBITS)
#define WBITS_GZIP		(MAX_WBITS | 16)
#define WBITS_AUTODETECT	(MAX_WBITS | 32)
enum WBitsFlags {
    WBITS_RAW = (-MAX_WBITS),		/* RAW compressed data */
    WBITS_ZLIB = (MAX_WBITS),		/* Zlib-format compressed data */
    WBITS_GZIP = (MAX_WBITS | 16),	/* Gzip-format compressed data */
    WBITS_AUTODETECT = (MAX_WBITS | 32)	/* Auto-detect format from its header */
};

/*
 * Structure used for handling gzip headers that are generated from a
 * dictionary. It comprises the header structure itself plus some working
 * space that it is very convenient to have attached.
 */

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
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







-
+

















+
-
+


+







typedef struct {
    Tcl_Interp *interp;
    z_stream stream;		/* The interface to the zlib library. */
    int streamEnd;		/* If we've got to end-of-stream. */
    Tcl_Obj *inData, *outData;	/* Input / output buffers (lists) */
    Tcl_Obj *currentInput;	/* Pointer to what is currently being
				 * inflated. */
    size_t outPos;
    Tcl_Size outPos;		/* Index into output buffer to write to next. */
    int mode;			/* Either TCL_ZLIB_STREAM_DEFLATE or
				 * TCL_ZLIB_STREAM_INFLATE. */
    int format;			/* Flags from the TCL_ZLIB_FORMAT_* */
    int level;			/* Default 5, 0-9 */
    int flush;			/* Stores the flush param for deferred the
				 * decompression. */
    int wbits;			/* The encoded compression mode, so we can
				 * restart the stream if necessary. */
    Tcl_Command cmd;		/* Token for the associated Tcl command. */
    Tcl_Obj *compDictObj;	/* Byte-array object containing compression
				 * dictionary (not dictObj!) to use if
				 * necessary. */
    int flags;			/* Miscellaneous flag bits. */
    GzipHeader *gzHeaderPtr;	/* If we've allocated a gzip header
				 * structure. */
} ZlibStreamHandle;

enum ZlibStreamHandleFlags {
#define DICT_TO_SET	0x1	/* If we need to set a compression dictionary
    DICT_TO_SET = 0x1		/* If we need to set a compression dictionary
				 * in the low-level engine at the next
				 * opportunity. */
};

/*
 * Macros to make it clearer in some of the twiddlier accesses what is
 * happening.
 */

#define IsRawStream(zshPtr)	((zshPtr)->format == TCL_ZLIB_FORMAT_RAW)
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
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







-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-







    Tcl_TimerToken timer;	/* Timer used for keeping events fresh. */
    Tcl_Obj *compDictObj;	/* Byte-array object containing compression
				 * dictionary (not dictObj!) to use if
				 * necessary. */
} ZlibChannelData;

/*
 * Value bits for the flags field. Definitions are:
 *	ASYNC -		Whether this is an asynchronous channel.
 *	IN_HEADER -	Whether the inHeader field has been registered with
 *			the input compressor.
 *	OUT_HEADER -	Whether the outputHeader field has been registered
 *			with the output decompressor.
 *	STREAM_DECOMPRESS - Signal decompress pending data.
 *	STREAM_DONE -	Flag to signal stream end up to transform input.
 */

 * Value bits for the ZlibChannelData::flags field.
 */
enum ZlibChannelDataFlags {
    ASYNC = 0x01,		/* Set if this is an asynchronous channel. */
    IN_HEADER = 0x02,		/* Set if the inHeader field has been
				 * registered with the input compressor. */
    OUT_HEADER = 0x04,		/* Set if the outputHeader field has been
				 * registered with the output decompressor. */
    STREAM_DECOMPRESS = 0x08,	/* Set to signal decompress pending data. */
    STREAM_DONE = 0x10		/* Set to signal stream end up to transform
				 * input. */
};
#define ASYNC			0x01
#define IN_HEADER		0x02
#define OUT_HEADER		0x04
#define STREAM_DECOMPRESS	0x08
#define STREAM_DONE		0x10

/*
 * Size of buffers allocated by default, and the range it can be set to.  The
 * same sorts of values apply to streams, except with different limits (they
 * permit byte-level activity). Channels always use bytes unless told to use
 * larger buffers.
 */
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
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







-
-
+
+
+







-
+
+









-
+


-
+




-
+

-
+

-
-
-
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







static inline int	Deflate(z_streamp strm, void *bufferPtr,
			    size_t bufferSize, int flush, size_t *writtenPtr);
static void		ExtractHeader(gz_header *headerPtr, Tcl_Obj *dictObj);
static int		GenerateHeader(Tcl_Interp *interp, Tcl_Obj *dictObj,
			    GzipHeader *headerPtr, int *extraSizePtr);
static int		ZlibPushSubcmd(Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		ResultDecompress(ZlibChannelData *cd, char *buf,
			    int toRead, int flush, int *errorCodePtr);
static int		ResultDecompress(ZlibChannelData *chanDataPtr,
			    char *buf, int toRead, int flush,
			    int *errorCodePtr);
static Tcl_Channel	ZlibStackChannelTransform(Tcl_Interp *interp,
			    int mode, int format, int level, int limit,
			    Tcl_Channel channel, Tcl_Obj *gzipHeaderDictPtr,
			    Tcl_Obj *compDictObj);
static void		ZlibStreamCleanup(ZlibStreamHandle *zshPtr);
static int		ZlibStreamSubcmd(Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static inline void	ZlibTransformEventTimerKill(ZlibChannelData *cd);
static inline void	ZlibTransformEventTimerKill(
			    ZlibChannelData *chanDataPtr);
static void		ZlibTransformTimerRun(void *clientData);

/*
 * Type of zlib-based compressing and decompressing channels.
 */

static const Tcl_ChannelType zlibChannelType = {
    "zlib",
    TCL_CHANNEL_VERSION_5,
    NULL,
    NULL,			/* Deprecated. */
    ZlibTransformInput,
    ZlibTransformOutput,
    NULL,			/* seekProc */
    NULL,			/* Deprecated. */
    ZlibTransformSetOption,
    ZlibTransformGetOption,
    ZlibTransformWatch,
    ZlibTransformGetHandle,
	ZlibTransformClose,			/* close2Proc */
    ZlibTransformClose,
    ZlibTransformBlockMode,
    NULL,			/* flushProc */
    NULL,			/* Flush proc. */
    ZlibTransformEventHandler,
    NULL,			/* wideSeekProc */
    NULL,
    NULL
    NULL,			/* Seek proc. */
    NULL,			/* Thread action proc. */
    NULL			/* Truncate proc. */
};

/*
 *----------------------------------------------------------------------
 *
 * Latin1 --
 *	Helper to definitely get the ISO 8859-1 encoding. It's internally
 *	defined by Tcl so this operation should always succeed.
 *
 *----------------------------------------------------------------------
 */
static inline Tcl_Encoding
Latin1(void)
{
    Tcl_Encoding latin1enc = Tcl_GetEncoding(NULL, "iso8859-1");

    if (latin1enc == NULL) {
	Tcl_Panic("no latin-1 encoding");
    }
    return latin1enc;
}

/*
 *----------------------------------------------------------------------
 *
 * ConvertError --
 *
 *	Utility function for converting a zlib error into a Tcl error.
258
259
260
261
262
263
264
265


266
267
268
269
270
271
272
279
280
281
282
283
284
285

286
287
288
289
290
291
292
293
294







-
+
+







	 * Firstly, the case that is *different* because it's really coming
	 * from the OS and is just being reported via zlib. It should be
	 * really uncommon because Tcl handles all I/O rather than delegating
	 * it to zlib, but proving it can't happen is hard.
	 */

    case Z_ERRNO:
	Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_PosixError(interp),-1));
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		Tcl_PosixError(interp), TCL_AUTO_LENGTH));
	return;

	/*
	 * Normal errors/conditions, some of which have additional detail and
	 * some which don't. (This is not defined by array lookup because zlib
	 * error codes are sometimes negative.)
	 */
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
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







-
+




















-
+


-
+






-
+







	break;
    case Z_VERSION_ERROR:
	codeStr = "VERSION";
	break;
    case Z_NEED_DICT:
	codeStr = "NEED_DICT";
	codeStr2 = codeStrBuf;
	sprintf(codeStrBuf, "%lu", adler);
	snprintf(codeStrBuf, sizeof(codeStrBuf), "%lu", adler);
	break;

	/*
	 * These should _not_ happen! This function is for dealing with error
	 * cases, not non-errors!
	 */

    case Z_OK:
	Tcl_Panic("unexpected zlib result in error handler: Z_OK");
    case Z_STREAM_END:
	Tcl_Panic("unexpected zlib result in error handler: Z_STREAM_END");

	/*
	 * Anything else is bad news; it's unexpected. Convert to generic
	 * error.
	 */

    default:
	codeStr = "UNKNOWN";
	codeStr2 = codeStrBuf;
	sprintf(codeStrBuf, "%d", code);
	snprintf(codeStrBuf, sizeof(codeStrBuf), "%d", code);
	break;
    }
    Tcl_SetObjResult(interp, Tcl_NewStringObj(zError(code), -1));
    Tcl_SetObjResult(interp, Tcl_NewStringObj(zError(code), TCL_AUTO_LENGTH));

    /*
     * Tricky point! We might pass NULL twice here (and will when the error
     * type is known).
     */

    Tcl_SetErrorCode(interp, "TCL", "ZLIB", codeStr, codeStr2, NULL);
    Tcl_SetErrorCode(interp, "TCL", "ZLIB", codeStr, codeStr2, (char *)NULL);
}

static Tcl_Obj *
ConvertErrorToList(
    int code,			/* The zlib error code. */
    uLong adler)		/* The checksum expected (for Z_NEED_DICT) */
{
346
347
348
349
350
351
352
353

354
355
356
357

358
359
360
361
362
363
364
368
369
370
371
372
373
374

375
376
377
378

379
380
381
382
383
384
385
386







-
+



-
+







	TclNewLiteralStringObj(objv[2], "BUF");
	return Tcl_NewListObj(3, objv);
    case Z_VERSION_ERROR:
	TclNewLiteralStringObj(objv[2], "VERSION");
	return Tcl_NewListObj(3, objv);
    case Z_ERRNO:
	TclNewLiteralStringObj(objv[2], "POSIX");
	objv[3] = Tcl_NewStringObj(Tcl_ErrnoId(), -1);
	objv[3] = Tcl_NewStringObj(Tcl_ErrnoId(), TCL_AUTO_LENGTH);
	return Tcl_NewListObj(4, objv);
    case Z_NEED_DICT:
	TclNewLiteralStringObj(objv[2], "NEED_DICT");
	TclNewIntObj(objv[3], (Tcl_WideInt)adler);
	TclNewIntObj(objv[3], (Tcl_WideInt) adler);
	return Tcl_NewListObj(4, objv);

	/*
	 * These should _not_ happen! This function is for dealing with error
	 * cases, not non-errors!
	 */

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
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

467
468
469

















470
471
472
473
474
475
476
477

478
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
558
559
560
561

562
563
564
565


566
567
568
569



570
571
572

573
574
575

576
577
578
579


580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598


599



600
601
602
603
604
605
606
607
608
609
610
611
612


613



614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631

632
633
634
635
636
637
638
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










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
467
468
469
470

471
472
473
474
475
476
477

478
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
558
559
560
561
562
563
564
565
566






567



568





569
570
571
572

573
574
575





576




577
578




579
580
581
582
583

584
585
586

587
588
589


590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608


609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625


626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644


645
646

647
648
649
650
651
652
653
654







-
+












-
-
-
-
-
-
-
-
-
-
-
-
-
-











-
+


-
+




-
-
-
-
-
-
-
-
-
-
+


+

-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+






-
+


+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+











-
+

-
+





-
+


















-










-
-
-






+
+



-
-
-
-
-
-
+
-
-
-
+
-
-
-
-
-
+
+
+

-
+


-
-
-
-
-
+
-
-
-
-
+
+
-
-
-
-
+
+
+


-
+


-
+


-
-
+
+

















-
-
+
+

+
+
+











-
-
+
+

+
+
+













-
-


-
+








/*
 *----------------------------------------------------------------------
 *
 * GenerateHeader --
 *
 *	Function for creating a gzip header from the contents of a dictionary
 *	(as described in the documentation). GetValue is a helper function.
 *	(as described in the documentation).
 *
 * Results:
 *	A Tcl result code.
 *
 * Side effects:
 *	Updates the fields of the given gz_header structure. Adds amount of
 *	extra space required for the header to the variable referenced by the
 *	extraSizePtr argument.
 *
 *----------------------------------------------------------------------
 */

static inline int
GetValue(
    Tcl_Interp *interp,
    Tcl_Obj *dictObj,
    const char *nameStr,
    Tcl_Obj **valuePtrPtr)
{
    Tcl_Obj *name = Tcl_NewStringObj(nameStr, -1);
    int result = Tcl_DictObjGet(interp, dictObj, name, valuePtrPtr);

    TclDecrRefCount(name);
    return result;
}

static int
GenerateHeader(
    Tcl_Interp *interp,		/* Where to put error messages. */
    Tcl_Obj *dictObj,		/* The dictionary whose contents are to be
				 * parsed. */
    GzipHeader *headerPtr,	/* Where to store the parsed-out values. */
    int *extraSizePtr)		/* Variable to add the length of header
				 * strings (filename, comment) to. */
{
    Tcl_Obj *value;
    int len, result = TCL_ERROR;
    size_t length;
    Tcl_Size length;
    Tcl_WideInt wideValue = 0;
    const char *valueStr;
    Tcl_Encoding latin1enc;
    Tcl_Encoding latin1enc = Latin1();
    static const char *const types[] = {
	"binary", "text"
    };

    /*
     * RFC 1952 says that header strings are in ISO 8859-1 (LATIN-1).
     */

    latin1enc = Tcl_GetEncoding(NULL, "iso8859-1");
    if (latin1enc == NULL) {
	Tcl_Panic("no latin-1 encoding");
    }

    if (GetValue(interp, dictObj, "comment", &value) != TCL_OK) {
    if (TclDictGet(interp, dictObj, "comment", &value) != TCL_OK) {
	goto error;
    } else if (value != NULL) {
	Tcl_EncodingState state;
	valueStr = TclGetStringFromObj(value, &length);
	Tcl_UtfToExternal(NULL, latin1enc, valueStr, length, 0, NULL,
		headerPtr->nativeCommentBuf, MAX_COMMENT_LEN-1, NULL, &len,
		NULL);
	result = Tcl_UtfToExternal(NULL, latin1enc, valueStr, length,
		TCL_ENCODING_START|TCL_ENCODING_END|TCL_ENCODING_PROFILE_STRICT,
		&state, headerPtr->nativeCommentBuf, MAX_COMMENT_LEN - 1, NULL,
		&len, NULL);
	if (result != TCL_OK) {
	    if (interp) {
		if (result == TCL_CONVERT_UNKNOWN) {
		    Tcl_AppendResult(interp,
			    "Comment contains characters > 0xFF", (char *)NULL);
		} else {
		    Tcl_AppendResult(interp, "Comment too large for zip",
			    (char *)NULL);
		}
	    }
	    result = TCL_ERROR; /* TCL_CONVERT_* -> TCL_ERROR */
	    goto error;
	}
	headerPtr->nativeCommentBuf[len] = '\0';
	headerPtr->header.comment = (Bytef *) headerPtr->nativeCommentBuf;
	if (extraSizePtr != NULL) {
	    *extraSizePtr += len;
	}
    }

    if (GetValue(interp, dictObj, "crc", &value) != TCL_OK) {
    if (TclDictGet(interp, dictObj, "crc", &value) != TCL_OK) {
	goto error;
    } else if (value != NULL &&
	    Tcl_GetBooleanFromObj(interp, value, &headerPtr->header.hcrc)) {
	goto error;
    }

    if (GetValue(interp, dictObj, "filename", &value) != TCL_OK) {
    if (TclDictGet(interp, dictObj, "filename", &value) != TCL_OK) {
	goto error;
    } else if (value != NULL) {
	Tcl_EncodingState state;
	valueStr = TclGetStringFromObj(value, &length);
	Tcl_UtfToExternal(NULL, latin1enc, valueStr, length, 0, NULL,
		headerPtr->nativeFilenameBuf, MAXPATHLEN-1, NULL, &len, NULL);
	result = Tcl_UtfToExternal(NULL, latin1enc, valueStr, length,
		TCL_ENCODING_START|TCL_ENCODING_END|TCL_ENCODING_PROFILE_STRICT,
		&state, headerPtr->nativeFilenameBuf, MAXPATHLEN - 1, NULL,
		&len, NULL);
	if (result != TCL_OK) {
	    if (interp) {
		if (result == TCL_CONVERT_UNKNOWN) {
		    Tcl_AppendResult(interp,
			    "Filename contains characters > 0xFF", (char *)NULL);
		} else {
		    Tcl_AppendResult(interp,
			    "Filename too large for zip", (char *)NULL);
		}
	    }
	    result = TCL_ERROR;	/* TCL_CONVERT_* -> TCL_ERROR */
	    goto error;
	}
	headerPtr->nativeFilenameBuf[len] = '\0';
	headerPtr->header.name = (Bytef *) headerPtr->nativeFilenameBuf;
	if (extraSizePtr != NULL) {
	    *extraSizePtr += len;
	}
    }

    if (GetValue(interp, dictObj, "os", &value) != TCL_OK) {
    if (TclDictGet(interp, dictObj, "os", &value) != TCL_OK) {
	goto error;
    } else if (value != NULL && Tcl_GetIntFromObj(interp, value,
	    &headerPtr->header.os) != TCL_OK) {
	goto error;
    }

    /*
     * Ignore the 'size' field, since that is controlled by the size of the
     * input data.
     */

    if (GetValue(interp, dictObj, "time", &value) != TCL_OK) {
    if (TclDictGet(interp, dictObj, "time", &value) != TCL_OK) {
	goto error;
    } else if (value != NULL && Tcl_GetWideIntFromObj(interp, value,
    } else if (value != NULL && TclGetWideIntFromObj(interp, value,
	    &wideValue) != TCL_OK) {
	goto error;
    }
    headerPtr->header.time = wideValue;

    if (GetValue(interp, dictObj, "type", &value) != TCL_OK) {
    if (TclDictGet(interp, dictObj, "type", &value) != TCL_OK) {
	goto error;
    } else if (value != NULL && Tcl_GetIndexFromObj(interp, value, types,
	    "type", TCL_EXACT, &headerPtr->header.text) != TCL_OK) {
	goto error;
    }

    result = TCL_OK;
  error:
    Tcl_FreeEncoding(latin1enc);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * ExtractHeader --
 *
 *	Take the values out of a gzip header and store them in a dictionary.
 *	SetValue is a helper macro.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Updates the dictionary, which must be writable (i.e. refCount < 2).
 *
 *----------------------------------------------------------------------
 */

#define SetValue(dictObj, key, value) \
	Tcl_DictObjPut(NULL, (dictObj), Tcl_NewStringObj((key), -1), (value))

static void
ExtractHeader(
    gz_header *headerPtr,	/* The gzip header to extract from. */
    Tcl_Obj *dictObj)		/* The dictionary to store in. */
{
    Tcl_Encoding latin1enc = NULL;
				/* RFC 1952 says that header strings are in
				 * ISO 8859-1 (LATIN-1). */
    Tcl_DString tmp;

    if (headerPtr->comment != Z_NULL) {
	if (latin1enc == NULL) {
	    /*
	     * RFC 1952 says that header strings are in ISO 8859-1 (LATIN-1).
	     */

	    latin1enc = Tcl_GetEncoding(NULL, "iso8859-1");
	latin1enc = Latin1();
	    if (latin1enc == NULL) {
		Tcl_Panic("no latin-1 encoding");
	    }

	}

	Tcl_ExternalToUtfDString(latin1enc, (char *) headerPtr->comment, -1,
		&tmp);
	SetValue(dictObj, "comment", TclDStringToObj(&tmp));
	(void) Tcl_ExternalToUtfDString(latin1enc, (char *) headerPtr->comment,
		TCL_AUTO_LENGTH, &tmp);
	TclDictPut(NULL, dictObj, "comment", Tcl_DStringToObj(&tmp));
    }
    SetValue(dictObj, "crc", Tcl_NewBooleanObj(headerPtr->hcrc));
    TclDictPut(NULL, dictObj, "crc", Tcl_NewBooleanObj(headerPtr->hcrc));
    if (headerPtr->name != Z_NULL) {
	if (latin1enc == NULL) {
	    /*
	     * RFC 1952 says that header strings are in ISO 8859-1 (LATIN-1).
	     */

	    latin1enc = Tcl_GetEncoding(NULL, "iso8859-1");
	    latin1enc = Latin1();
	    if (latin1enc == NULL) {
		Tcl_Panic("no latin-1 encoding");
	    }
	}
	}


	Tcl_ExternalToUtfDString(latin1enc, (char *) headerPtr->name, -1,
		&tmp);
	SetValue(dictObj, "filename", TclDStringToObj(&tmp));
	(void) Tcl_ExternalToUtfDString(latin1enc, (char *) headerPtr->name,
		TCL_AUTO_LENGTH, &tmp);
	TclDictPut(NULL, dictObj, "filename", Tcl_DStringToObj(&tmp));
    }
    if (headerPtr->os != 255) {
	SetValue(dictObj, "os", Tcl_NewWideIntObj(headerPtr->os));
	TclDictPut(NULL, dictObj, "os", Tcl_NewWideIntObj(headerPtr->os));
    }
    if (headerPtr->time != 0 /* magic - no time */) {
	SetValue(dictObj, "time", Tcl_NewWideIntObj(headerPtr->time));
	TclDictPut(NULL, dictObj, "time", Tcl_NewWideIntObj(headerPtr->time));
    }
    if (headerPtr->text != Z_UNKNOWN) {
	SetValue(dictObj, "type",
		Tcl_NewStringObj(headerPtr->text ? "text" : "binary", -1));
	TclDictPutString(NULL, dictObj, "type",
		headerPtr->text ? "text" : "binary");
    }

    if (latin1enc != NULL) {
	Tcl_FreeEncoding(latin1enc);
    }
}

/*
 * Disentangle the worst of how the zlib API is used.
 */

static int
SetInflateDictionary(
    z_streamp strm,
    Tcl_Obj *compDictObj)
{
    if (compDictObj != NULL) {
	size_t length = 0;
	unsigned char *bytes = TclGetByteArrayFromObj(compDictObj, &length);
	Tcl_Size length = 0;
	unsigned char *bytes = Tcl_GetBytesFromObj(NULL, compDictObj, &length);

	if (bytes == NULL) {
	    return Z_DATA_ERROR;
	}
	return inflateSetDictionary(strm, bytes, length);
    }
    return Z_OK;
}

static int
SetDeflateDictionary(
    z_streamp strm,
    Tcl_Obj *compDictObj)
{
    if (compDictObj != NULL) {
	size_t length = 0;
	unsigned char *bytes = TclGetByteArrayFromObj(compDictObj, &length);
	Tcl_Size length = 0;
	unsigned char *bytes = Tcl_GetBytesFromObj(NULL, compDictObj, &length);

	if (bytes == NULL) {
	    return Z_DATA_ERROR;
	}
	return deflateSetDictionary(strm, bytes, length);
    }
    return Z_OK;
}

static inline int
Deflate(
    z_streamp strm,
    void *bufferPtr,
    size_t bufferSize,
    int flush,
    size_t *writtenPtr)
{
    int e;

    strm->next_out = (Bytef *) bufferPtr;
    strm->avail_out = bufferSize;
    e = deflate(strm, flush);
    int e = deflate(strm, flush);
    if (writtenPtr != NULL) {
	*writtenPtr = bufferSize - strm->avail_out;
    }
    return e;
}

static inline void
697
698
699
700
701
702
703
704

705
706
707
708
709
710
711
713
714
715
716
717
718
719

720
721
722
723
724
725
726
727







-
+







	switch (format) {
	case TCL_ZLIB_FORMAT_RAW:
	    wbits = WBITS_RAW;
	    break;
	case TCL_ZLIB_FORMAT_GZIP:
	    wbits = WBITS_GZIP;
	    if (dictObj) {
		gzHeaderPtr = (GzipHeader *)Tcl_Alloc(sizeof(GzipHeader));
		gzHeaderPtr = (GzipHeader *) Tcl_Alloc(sizeof(GzipHeader));
		memset(gzHeaderPtr, 0, sizeof(GzipHeader));
		if (GenerateHeader(interp, dictObj, gzHeaderPtr,
			NULL) != TCL_OK) {
		    Tcl_Free(gzHeaderPtr);
		    return TCL_ERROR;
		}
	    }
731
732
733
734
735
736
737
738

739
740
741
742
743
744
745
747
748
749
750
751
752
753

754
755
756
757
758
759
760
761







-
+








	switch (format) {
	case TCL_ZLIB_FORMAT_RAW:
	    wbits = WBITS_RAW;
	    break;
	case TCL_ZLIB_FORMAT_GZIP:
	    wbits = WBITS_GZIP;
	    gzHeaderPtr = (GzipHeader *)Tcl_Alloc(sizeof(GzipHeader));
	    gzHeaderPtr = (GzipHeader *) Tcl_Alloc(sizeof(GzipHeader));
	    memset(gzHeaderPtr, 0, sizeof(GzipHeader));
	    gzHeaderPtr->header.name = (Bytef *)
		    gzHeaderPtr->nativeFilenameBuf;
	    gzHeaderPtr->header.name_max = MAXPATHLEN - 1;
	    gzHeaderPtr->header.comment = (Bytef *)
		    gzHeaderPtr->nativeCommentBuf;
	    gzHeaderPtr->header.name_max = MAX_COMMENT_LEN - 1;
757
758
759
760
761
762
763
764

765
766
767
768
769
770
771
773
774
775
776
777
778
779

780
781
782
783
784
785
786
787







-
+







	}
	break;
    default:
	Tcl_Panic("bad mode, must be TCL_ZLIB_STREAM_DEFLATE or"
		" TCL_ZLIB_STREAM_INFLATE");
    }

    zshPtr = (ZlibStreamHandle *)Tcl_Alloc(sizeof(ZlibStreamHandle));
    zshPtr = (ZlibStreamHandle *) Tcl_Alloc(sizeof(ZlibStreamHandle));
    zshPtr->interp = interp;
    zshPtr->mode = mode;
    zshPtr->format = format;
    zshPtr->level = level;
    zshPtr->wbits = wbits;
    zshPtr->currentInput = NULL;
    zshPtr->streamEnd = 0;
800
801
802
803
804
805
806
807


808
809
810
811
812
813
814
815
816
817


818
819
820
821
822
823
824
816
817
818
819
820
821
822

823
824
825
826
827
828
829
830
831
832


833
834
835
836
837
838
839
840
841







-
+
+








-
-
+
+







    }

    /*
     * I could do all this in C, but this is easier.
     */

    if (interp != NULL) {
	if (Tcl_EvalEx(interp, "::incr ::tcl::zlib::cmdcounter", -1, 0) != TCL_OK) {
	if (Tcl_EvalEx(interp, "::incr ::tcl::zlib::cmdcounter",
		TCL_AUTO_LENGTH, 0) != TCL_OK) {
	    goto error;
	}
	Tcl_DStringInit(&cmdname);
	TclDStringAppendLiteral(&cmdname, "::tcl::zlib::streamcmd_");
	TclDStringAppendObj(&cmdname, Tcl_GetObjResult(interp));
	if (Tcl_FindCommand(interp, Tcl_DStringValue(&cmdname),
		NULL, 0) != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "BUG: Stream command name already exists", -1));
	    Tcl_SetErrorCode(interp, "TCL", "BUG", "EXISTING_CMD", NULL);
		    "BUG: Stream command name already exists", TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(interp, "TCL", "BUG", "EXISTING_CMD", (char *)NULL);
	    Tcl_DStringFree(&cmdname);
	    goto error;
	}
	Tcl_ResetResult(interp);

	/*
	 * Create the command.
882
883
884
885
886
887
888
889

890
891

892
893
894
895
896
897
898
899
900
901
902
903
904
905

906
907

908
909
910
911
912
913
914
915







-
+

-
+







 *	Invalidates the zlib stream handle as obtained from Tcl_ZlibStreamInit
 *
 *----------------------------------------------------------------------
 */

static void
ZlibStreamCmdDelete(
    void *cd)
    void *clientData)
{
    ZlibStreamHandle *zshPtr = (ZlibStreamHandle *)cd;
    ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) clientData;

    zshPtr->cmd = NULL;
    ZlibStreamCleanup(zshPtr);
}

/*
 *----------------------------------------------------------------------
1126
1127
1128
1129
1130
1131
1132
1133

1134
1135
1136
1137
1138
1139
1140
1143
1144
1145
1146
1147
1148
1149

1150
1151
1152
1153
1154
1155
1156
1157







-
+







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

int
Tcl_ZlibStreamChecksum(
    Tcl_ZlibStream zshandle)	/* As obtained from Tcl_ZlibStreamInit */
{
    ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle;
    ZlibStreamHandle *zshPtr = (ZlibStreamHandle *)zshandle;

    return zshPtr->stream.adler;
}

/*
 *----------------------------------------------------------------------
 *
1150
1151
1152
1153
1154
1155
1156
1157
1158


1159
1160
1161
1162
1163
1164
1165
1167
1168
1169
1170
1171
1172
1173


1174
1175
1176
1177
1178
1179
1180
1181
1182







-
-
+
+







void
Tcl_ZlibStreamSetCompressionDictionary(
    Tcl_ZlibStream zshandle,
    Tcl_Obj *compressionDictionaryObj)
{
    ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle;

    if (compressionDictionaryObj && (NULL == TclGetBytesFromObj(NULL,
	    compressionDictionaryObj, NULL))) {
    if (compressionDictionaryObj && (NULL == Tcl_GetBytesFromObj(NULL,
	    compressionDictionaryObj, (Tcl_Size *)NULL))) {
	/* Missing or invalid compression dictionary */
	compressionDictionaryObj = NULL;
    }
    if (compressionDictionaryObj != NULL) {
	if (Tcl_IsShared(compressionDictionaryObj)) {
	    compressionDictionaryObj =
		    Tcl_DuplicateObj(compressionDictionaryObj);
1194
1195
1196
1197
1198
1199
1200

1201

1202
1203
1204
1205
1206
1207
1208


1209
1210
1211
1212
1213

1214
1215
1216
1217
1218
1219
1220
1211
1212
1213
1214
1215
1216
1217
1218

1219
1220
1221
1222
1223
1224


1225
1226
1227
1228
1229
1230

1231
1232
1233
1234
1235
1236
1237
1238







+
-
+





-
-
+
+




-
+







    Tcl_Obj *data,		/* Data to compress/decompress */
    int flush)			/* TCL_ZLIB_NO_FLUSH, TCL_ZLIB_FLUSH,
				 * TCL_ZLIB_FULLFLUSH, or TCL_ZLIB_FINALIZE */
{
    ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle;
    char *dataTmp = NULL;
    int e;
    Tcl_Size size = 0;
    size_t size = 0, outSize, toStore;
    size_t outSize, toStore;
    unsigned char *bytes;

    if (zshPtr->streamEnd) {
	if (zshPtr->interp) {
	    Tcl_SetObjResult(zshPtr->interp, Tcl_NewStringObj(
		    "already past compressed stream end", -1));
	    Tcl_SetErrorCode(zshPtr->interp, "TCL", "ZIP", "CLOSED", NULL);
		    "already past compressed stream end", TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(zshPtr->interp, "TCL", "ZIP", "CLOSED", (char *)NULL);
	}
	return TCL_ERROR;
    }

    bytes = TclGetBytesFromObj(zshPtr->interp, data, &size);
    bytes = Tcl_GetBytesFromObj(zshPtr->interp, data, &size);
    if (bytes == NULL) {
	return TCL_ERROR;
    }

    if (zshPtr->mode == TCL_ZLIB_STREAM_DEFLATE) {
	zshPtr->stream.next_in = bytes;
	zshPtr->stream.avail_in = size;
1243
1244
1245
1246
1247
1248
1249
1250

1251
1252
1253
1254
1255
1256
1257
1261
1262
1263
1264
1265
1266
1267

1268
1269
1270
1271
1272
1273
1274
1275







-
+







	 * size.
	 */

	outSize = deflateBound(&zshPtr->stream, size) + 100;
	if (outSize > BUFFER_SIZE_LIMIT) {
	    outSize = BUFFER_SIZE_LIMIT;
	}
	dataTmp = (char *)Tcl_Alloc(outSize);
	dataTmp = (char *) Tcl_Alloc(outSize);

	while (1) {
	    e = Deflate(&zshPtr->stream, dataTmp, outSize, flush, &toStore);

	    /*
	     * Test if we've filled the buffer up and have to ask deflate() to
	     * give us some more. Note that the condition for needing to
1277
1278
1279
1280
1281
1282
1283
1284

1285
1286
1287
1288
1289
1290
1291
1295
1296
1297
1298
1299
1300
1301

1302
1303
1304
1305
1306
1307
1308
1309







-
+







	     */

	    AppendByteArray(zshPtr->outData, dataTmp, outSize);

	    if (outSize < BUFFER_SIZE_LIMIT) {
		outSize = BUFFER_SIZE_LIMIT;
		/* There may be *lots* of data left to output... */
		dataTmp = (char *)Tcl_Realloc(dataTmp, outSize);
		dataTmp = (char *) Tcl_Realloc(dataTmp, outSize);
	    }
	}

	/*
	 * And append the final data block to the outData list.
	 */

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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389

1390
1391
1392
1393
1394
1395
1396
1337
1338
1339
1340
1341
1342
1343

1344
1345
1346
1347


1348
1349
1350
1351

1352
1353
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393

1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406

1407
1408
1409
1410
1411
1412
1413
1414







-
+



-
-
+
+


-
+









-
+




-
+












-
+













-
+












-
+







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

int
Tcl_ZlibStreamGet(
    Tcl_ZlibStream zshandle,	/* As obtained from Tcl_ZlibStreamInit */
    Tcl_Obj *data,		/* A place to append the data. */
    size_t count)			/* Number of bytes to grab as a maximum, you
    Tcl_Size count)		/* Number of bytes to grab as a maximum, you
				 * may get less! */
{
    ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle;
    int e, i, listLen;
    size_t itemLen = 0, dataPos = 0;
    int e;
    Tcl_Size listLen, i, itemLen = 0, dataPos = 0;
    Tcl_Obj *itemObj;
    unsigned char *dataPtr, *itemPtr;
    size_t existing = 0;
    Tcl_Size existing = 0;

    /*
     * Getting beyond the of stream, just return empty string.
     */

    if (zshPtr->streamEnd) {
	return TCL_OK;
    }

    if (NULL == TclGetBytesFromObj(zshPtr->interp, data, &existing)) {
    if (NULL == Tcl_GetBytesFromObj(zshPtr->interp, data, &existing)) {
	return TCL_ERROR;
    }

    if (zshPtr->mode == TCL_ZLIB_STREAM_INFLATE) {
	if (count == TCL_INDEX_NONE) {
	if (count < 0) {
	    /*
	     * The only safe thing to do is restict to 65k. We might cause a
	     * panic for out of memory if we just kept growing the buffer.
	     */

	    count = MAX_BUFFER_SIZE;
	}

	/*
	 * Prepare the place to store the data.
	 */

	dataPtr = Tcl_SetByteArrayLength(data, existing+count);
	dataPtr = Tcl_SetByteArrayLength(data, existing + count);
	dataPtr += existing;

	zshPtr->stream.next_out = dataPtr;
	zshPtr->stream.avail_out = count;
	if (zshPtr->stream.avail_in == 0) {
	    /*
	     * zlib will probably need more data to decompress.
	     */

	    if (zshPtr->currentInput) {
		Tcl_DecrRefCount(zshPtr->currentInput);
		zshPtr->currentInput = NULL;
	    }
	    Tcl_ListObjLength(NULL, zshPtr->inData, &listLen);
	    TclListObjLength(NULL, zshPtr->inData, &listLen);
	    if (listLen > 0) {
		/*
		 * There is more input available, get it from the list and
		 * give it to zlib. At this point, the data must not be shared
		 * since we require the bytearray representation to not vanish
		 * under our feet. [Bug 3081008]
		 */

		Tcl_ListObjIndex(NULL, zshPtr->inData, 0, &itemObj);
		if (Tcl_IsShared(itemObj)) {
		    itemObj = Tcl_DuplicateObj(itemObj);
		}
		itemPtr = TclGetByteArrayFromObj(itemObj, &itemLen);
		itemPtr = Tcl_GetBytesFromObj(NULL, itemObj, &itemLen);
		Tcl_IncrRefCount(itemObj);
		zshPtr->currentInput = itemObj;
		zshPtr->stream.next_in = itemPtr;
		zshPtr->stream.avail_in = itemLen;

		/*
		 * And remove it from the list
1418
1419
1420
1421
1422
1423
1424
1425

1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438

1439
1440

1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461

1462
1463
1464
1465
1466
1467
1468
1436
1437
1438
1439
1440
1441
1442

1443
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
1474
1475
1476
1477
1478

1479
1480
1481
1482
1483
1484
1485
1486







-
+












-
+

-
+




















-
+







	if (e == Z_NEED_DICT && HaveDictToSet(zshPtr)) {
	    e = SetInflateDictionary(&zshPtr->stream, zshPtr->compDictObj);
	    if (e == Z_OK) {
		DictWasSet(zshPtr);
		e = inflate(&zshPtr->stream, zshPtr->flush);
	    }
	};
	Tcl_ListObjLength(NULL, zshPtr->inData, &listLen);
	TclListObjLength(NULL, zshPtr->inData, &listLen);

	while ((zshPtr->stream.avail_out > 0)
		&& (e == Z_OK || e == Z_BUF_ERROR) && (listLen > 0)) {
	    /*
	     * State: We have not satisfied the request yet and there may be
	     * more to inflate.
	     */

	    if (zshPtr->stream.avail_in > 0) {
		if (zshPtr->interp) {
		    Tcl_SetObjResult(zshPtr->interp, Tcl_NewStringObj(
			    "unexpected zlib internal state during"
			    " decompression", -1));
			    " decompression", TCL_AUTO_LENGTH));
		    Tcl_SetErrorCode(zshPtr->interp, "TCL", "ZIP", "STATE",
			    NULL);
			    (char *)NULL);
		}
		Tcl_SetByteArrayLength(data, existing);
		return TCL_ERROR;
	    }

	    if (zshPtr->currentInput) {
		Tcl_DecrRefCount(zshPtr->currentInput);
		zshPtr->currentInput = 0;
	    }

	    /*
	     * Get the next block of data to go to inflate. At this point, the
	     * data must not be shared since we require the bytearray
	     * representation to not vanish under our feet. [Bug 3081008]
	     */

	    Tcl_ListObjIndex(zshPtr->interp, zshPtr->inData, 0, &itemObj);
	    if (Tcl_IsShared(itemObj)) {
		itemObj = Tcl_DuplicateObj(itemObj);
	    }
	    itemPtr = TclGetByteArrayFromObj(itemObj, &itemLen);
	    itemPtr = Tcl_GetBytesFromObj(NULL, itemObj, &itemLen);
	    Tcl_IncrRefCount(itemObj);
	    zshPtr->currentInput = itemObj;
	    zshPtr->stream.next_in = itemPtr;
	    zshPtr->stream.avail_in = itemLen;

	    /*
	     * Remove it from the list.
1476
1477
1478
1479
1480
1481
1482
1483

1484
1485
1486
1487
1488
1489
1490
1494
1495
1496
1497
1498
1499
1500

1501
1502
1503
1504
1505
1506
1507
1508







-
+







	     */

	    do {
		e = inflate(&zshPtr->stream, zshPtr->flush);
		if (e != Z_NEED_DICT || !HaveDictToSet(zshPtr)) {
		    break;
		}
		e = SetInflateDictionary(&zshPtr->stream,zshPtr->compDictObj);
		e = SetInflateDictionary(&zshPtr->stream, zshPtr->compDictObj);
		DictWasSet(zshPtr);
	    } while (e == Z_OK);
	}
	if (zshPtr->stream.avail_out > 0) {
	    Tcl_SetByteArrayLength(data,
		    existing + count - zshPtr->stream.avail_out);
	}
1498
1499
1500
1501
1502
1503
1504
1505
1506


1507
1508
1509
1510

1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527

1528
1529
1530
1531
1532
1533
1534
1535
1536
1537



1538
1539
1540
1541
1542
1543
1544
1545
1546

1547
1548
1549
1550
1551
1552
1553
1516
1517
1518
1519
1520
1521
1522


1523
1524
1525
1526
1527

1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544

1545
1546
1547
1548
1549
1550
1551
1552



1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563

1564
1565
1566
1567
1568
1569
1570
1571







-
-
+
+



-
+
















-
+







-
-
-
+
+
+








-
+







	    if (zshPtr->currentInput) {
		Tcl_DecrRefCount(zshPtr->currentInput);
		zshPtr->currentInput = 0;
	    }
	    inflateEnd(&zshPtr->stream);
	}
    } else {
	Tcl_ListObjLength(NULL, zshPtr->outData, &listLen);
	if (count == TCL_INDEX_NONE) {
	TclListObjLength(NULL, zshPtr->outData, &listLen);
	if (count < 0) {
	    count = 0;
	    for (i=0; i<listLen; i++) {
		Tcl_ListObjIndex(NULL, zshPtr->outData, i, &itemObj);
		(void) TclGetByteArrayFromObj(itemObj, &itemLen);
		(void) Tcl_GetBytesFromObj(NULL, itemObj, &itemLen);
		if (i == 0) {
		    count += itemLen - zshPtr->outPos;
		} else {
		    count += itemLen;
		}
	    }
	}

	/*
	 * Prepare the place to store the data.
	 */

	dataPtr = Tcl_SetByteArrayLength(data, existing + count);
	dataPtr += existing;

	while ((count > dataPos) &&
		(Tcl_ListObjLength(NULL, zshPtr->outData, &listLen) == TCL_OK)
		(TclListObjLength(NULL, zshPtr->outData, &listLen) == TCL_OK)
		&& (listLen > 0)) {
	    /*
	     * Get the next chunk off our list of chunks and grab the data out
	     * of it.
	     */

	    Tcl_ListObjIndex(NULL, zshPtr->outData, 0, &itemObj);
	    itemPtr = TclGetByteArrayFromObj(itemObj, &itemLen);
	    if (itemLen-zshPtr->outPos + dataPos >= count) {
		size_t len = count - dataPos;
	    itemPtr = Tcl_GetBytesFromObj(NULL, itemObj, &itemLen);
	    if ((itemLen - zshPtr->outPos) >= (count - dataPos)) {
		Tcl_Size len = count - dataPos;

		memcpy(dataPtr + dataPos, itemPtr + zshPtr->outPos, len);
		zshPtr->outPos += len;
		dataPos += len;
		if (zshPtr->outPos == itemLen) {
		    zshPtr->outPos = 0;
		}
	    } else {
		size_t len = itemLen - zshPtr->outPos;
		Tcl_Size len = itemLen - zshPtr->outPos;

		memcpy(dataPtr + dataPos, itemPtr + zshPtr->outPos, len);
		dataPos += len;
		zshPtr->outPos = 0;
	    }
	    if (zshPtr->outPos == 0) {
		Tcl_ListObjReplace(NULL, zshPtr->outData, 0, 1, 0, NULL);
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
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







-
+















-
+







    Tcl_Interp *interp,
    int format,
    Tcl_Obj *data,
    int level,
    Tcl_Obj *gzipHeaderDictObj)
{
    int wbits = 0, e = 0, extraSize = 0;
    size_t inLen = 0;
    Tcl_Size inLen = 0;
    Byte *inData = NULL;
    z_stream stream;
    GzipHeader header;
    gz_header *headerPtr = NULL;
    Tcl_Obj *obj;

    if (!interp) {
	return TCL_ERROR;
    }

    /*
     * Obtain the pointer to the byte array, we'll pass this pointer straight
     * to the deflate command.
     */

    inData = TclGetBytesFromObj(interp, data, &inLen);
    inData = Tcl_GetBytesFromObj(interp, data, &inLen);
    if (inData == NULL) {
	return TCL_ERROR;
    }

    /*
     * Compressed format is specified by the wbits parameter. See zlib.h for
     * details.
1698
1699
1700
1701
1702
1703
1704
1705

1706
1707
1708
1709
1710
1711
1712
1716
1717
1718
1719
1720
1721
1722

1723
1724
1725
1726
1727
1728
1729
1730







-
+







    }

    if (e != Z_OK) {
	goto error;
    }

    /*
     * Reduce the bytearray length to the actual data length produced by
     * Reduce the ByteArray length to the actual data length produced by
     * deflate.
     */

    Tcl_SetByteArrayLength(obj, stream.total_out);
    Tcl_SetObjResult(interp, obj);
    return TCL_OK;

1727
1728
1729
1730
1731
1732
1733
1734

1735
1736
1737
1738

1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749

1750
1751
1752
1753
1754
1755
1756
1745
1746
1747
1748
1749
1750
1751

1752
1753
1754
1755

1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766

1767
1768
1769
1770
1771
1772
1773
1774







-
+



-
+










-
+







 */

int
Tcl_ZlibInflate(
    Tcl_Interp *interp,
    int format,
    Tcl_Obj *data,
    size_t bufferSize,
    Tcl_Size bufferSize,
    Tcl_Obj *gzipHeaderDictObj)
{
    int wbits = 0, e = 0;
    size_t inLen = 0, newBufferSize;
    Tcl_Size inLen = 0, newBufferSize;
    Byte *inData = NULL, *outData = NULL, *newOutData = NULL;
    z_stream stream;
    gz_header header, *headerPtr = NULL;
    Tcl_Obj *obj;
    char *nameBuf = NULL, *commentBuf = NULL;

    if (!interp) {
	return TCL_ERROR;
    }

    inData = TclGetBytesFromObj(interp, data, &inLen);
    inData = Tcl_GetBytesFromObj(interp, data, &inLen);
    if (inData == NULL) {
	return TCL_ERROR;
    }

    /*
     * Compressed format is specified by the wbits parameter. See zlib.h for
     * details.
1776
1777
1778
1779
1780
1781
1782
1783

1784
1785
1786

1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799




1800
1801
1802
1803
1804
1805
1806
1807
1808
1809

1810
1811
1812
1813
1814
1815
1816
1794
1795
1796
1797
1798
1799
1800

1801
1802
1803

1804
1805
1806
1807
1808
1809
1810
1811
1812
1813




1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826

1827
1828
1829
1830
1831
1832
1833
1834







-
+


-
+









-
-
-
-
+
+
+
+









-
+







		"TCL_ZLIB_FORMAT_GZIP, TCL_ZLIB_FORMAT_RAW or "
		"TCL_ZLIB_FORMAT_AUTO");
    }

    if (gzipHeaderDictObj) {
	headerPtr = &header;
	memset(headerPtr, 0, sizeof(gz_header));
	nameBuf = (char *)Tcl_Alloc(MAXPATHLEN);
	nameBuf = (char *) Tcl_Alloc(MAXPATHLEN);
	header.name = (Bytef *) nameBuf;
	header.name_max = MAXPATHLEN - 1;
	commentBuf = (char *)Tcl_Alloc(MAX_COMMENT_LEN);
	commentBuf = (char *) Tcl_Alloc(MAX_COMMENT_LEN);
	header.comment = (Bytef *) commentBuf;
	header.comm_max = MAX_COMMENT_LEN - 1;
    }

    if (bufferSize < 1) {
	/*
	 * Start with a buffer (up to) 3 times the size of the input data.
	 */

	if (inLen < 32*1024*1024) {
	    bufferSize = 3*inLen;
	} else if (inLen < 256*1024*1024) {
	    bufferSize = 2*inLen;
	if (inLen < 32 * 1024 * 1024) {
	    bufferSize = 3 * inLen;
	} else if (inLen < 256 * 1024 * 1024) {
	    bufferSize = 2 * inLen;
	} else {
	    bufferSize = inLen;
	}
    }

    TclNewObj(obj);
    outData = Tcl_SetByteArrayLength(obj, bufferSize);
    memset(&stream, 0, sizeof(z_stream));
    stream.avail_in = inLen+1;	/* +1 because zlib can "over-request"
					 * input (but ignore it!) */
				 * input (but ignore it!) */
    stream.next_in = inData;
    stream.avail_out = bufferSize;
    stream.next_out = outData;

    /*
     * Initialize zlib for decompression.
     */
1846
1847
1848
1849
1850
1851
1852
1853

1854
1855
1856
1857
1858
1859
1860
1864
1865
1866
1867
1868
1869
1870

1871
1872
1873
1874
1875
1876
1877
1878







-
+








	if ((stream.avail_in == 0) && (stream.avail_out > 0)) {
	    e = Z_STREAM_ERROR;
	    break;
	}
	newBufferSize = bufferSize + 5 * stream.avail_in;
	if (newBufferSize == bufferSize) {
	    newBufferSize = bufferSize+1000;
	    newBufferSize = bufferSize + 1000;
	}
	newOutData = Tcl_SetByteArrayLength(obj, newBufferSize);

	/*
	 * Set next out to the same offset in the new location.
	 */

1882
1883
1884
1885
1886
1887
1888
1889

1890
1891
1892
1893
1894
1895
1896
1900
1901
1902
1903
1904
1905
1906

1907
1908
1909
1910
1911
1912
1913
1914







-
+







    /*
     * Reduce the BA length to the actual data length produced by deflate.
     */

    Tcl_SetByteArrayLength(obj, stream.total_out);
    if (headerPtr != NULL) {
	ExtractHeader(&header, gzipHeaderDictObj);
	SetValue(gzipHeaderDictObj, "size",
	TclDictPut(NULL, gzipHeaderDictObj, "size",
		Tcl_NewWideIntObj(stream.total_out));
	Tcl_Free(nameBuf);
	Tcl_Free(commentBuf);
    }
    Tcl_SetObjResult(interp, obj);
    return TCL_OK;

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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969

1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982



1983
1984
1985
1986
1987

1988
1989
1990
1991

1992
1993
1994
1995
1996
1997
1998
1999


2000
2001
2002


2003
2004
2005
2006
2007

2008
2009
2010
2011

2012
2013
2014
2015
2016
2017
2018
2019


2020
2021
2022


2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038


2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054


2055
2056
2057
2058
2059
2060
2061
1934
1935
1936
1937
1938
1939
1940

1941
1942
1943
1944
1945
1946
1947
1948
1949
1950

1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974


1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990

1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001



2002
2003
2004
2005
2006
2007
2008

2009
2010
2011
2012

2013
2014
2015
2016
2017
2018
2019


2020
2021
2022


2023
2024
2025
2026
2027
2028

2029
2030
2031
2032

2033
2034
2035
2036
2037
2038
2039


2040
2041
2042


2043
2044
2045
2046
2047
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







-
+









-
+










+
+











-
-
+
+
+
+












-
+










-
-
-
+
+
+




-
+



-
+






-
-
+
+

-
-
+
+




-
+



-
+






-
-
+
+

-
-
+
+














-
-
+
+














-
-
+
+







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

unsigned int
Tcl_ZlibCRC32(
    unsigned int crc,
    const unsigned char *buf,
    size_t len)
    Tcl_Size len)
{
    /* Nothing much to do, just wrap the crc32(). */
    return crc32(crc, (Bytef *) buf, len);
}

unsigned int
Tcl_ZlibAdler32(
    unsigned int adler,
    const unsigned char *buf,
    size_t len)
    Tcl_Size len)
{
    return adler32(adler, (Bytef *) buf, len);
}

/*
 *----------------------------------------------------------------------
 *
 * ZlibCmd --
 *
 *	Implementation of the [zlib] command.
 *
 *	TODO: Convert this to an ensemble.
 *
 *----------------------------------------------------------------------
 */

static int
ZlibCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    int command, i, option, level = -1;
    size_t dlen = 0, start, buffersize = 0;
    int i, option, level = -1;
    size_t buffersize = 0;
    Tcl_Size dlen = 0;
    unsigned int start;
    Tcl_WideInt wideLen;
    Byte *data;
    Tcl_Obj *headerDictObj;
    const char *extraInfoStr = NULL;
    static const char *const commands[] = {
	"adler32", "compress", "crc32", "decompress", "deflate", "gunzip",
	"gzip", "inflate", "push", "stream",
	NULL
    };
    enum zlibCommands {
	CMD_ADLER, CMD_COMPRESS, CMD_CRC, CMD_DECOMPRESS, CMD_DEFLATE,
	CMD_GUNZIP, CMD_GZIP, CMD_INFLATE, CMD_PUSH, CMD_STREAM
    };
    } command;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "command arg ?...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], commands, "command", 0,
	    &command) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum zlibCommands) command) {
    case CMD_ADLER:			/* adler32 str ?startvalue?
					 * -> checksum */
    switch (command) {
    case CMD_ADLER:		/* adler32 str ?startvalue?
				 *	-> checksum */
	if (objc < 3 || objc > 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "data ?startValue?");
	    return TCL_ERROR;
	}
	data = TclGetBytesFromObj(interp, objv[2], &dlen);
	data = Tcl_GetBytesFromObj(interp, objv[2], &dlen);
	if (data == NULL) {
	    return TCL_ERROR;
	}
	if (objc>3 && Tcl_GetIntFromObj(interp, objv[3],
	if (objc > 3 && Tcl_GetIntFromObj(interp, objv[3],
		(int *) &start) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (objc < 4) {
	    start = Tcl_ZlibAdler32(0, NULL, 0);
	}
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt)
		(uLong) Tcl_ZlibAdler32(start, data, dlen)));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
		Tcl_ZlibAdler32(start, data, dlen)));
	return TCL_OK;
    case CMD_CRC:			/* crc32 str ?startvalue?
					 * -> checksum */
    case CMD_CRC:		/* crc32 str ?startvalue?
				 *	-> checksum */
	if (objc < 3 || objc > 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "data ?startValue?");
	    return TCL_ERROR;
	}
	data = TclGetBytesFromObj(interp, objv[2], &dlen);
	data = Tcl_GetBytesFromObj(interp, objv[2], &dlen);
	if (data == NULL) {
	    return TCL_ERROR;
	}
	if (objc>3 && Tcl_GetIntFromObj(interp, objv[3],
	if (objc > 3 && Tcl_GetIntFromObj(interp, objv[3],
		(int *) &start) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (objc < 4) {
	    start = Tcl_ZlibCRC32(0, NULL, 0);
	}
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt)
		(uLong) Tcl_ZlibCRC32(start, data, dlen)));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
		Tcl_ZlibCRC32(start, data, dlen)));
	return TCL_OK;
    case CMD_DEFLATE:			/* deflate data ?level?
					 * -> rawCompressedData */
    case CMD_DEFLATE:		/* deflate data ?level?
				 *	-> rawCompressedData */
	if (objc < 3 || objc > 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "data ?level?");
	    return TCL_ERROR;
	}
	if (objc > 3) {
	    if (Tcl_GetIntFromObj(interp, objv[3], &level) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (level < 0 || level > 9) {
		goto badLevel;
	    }
	}
	return Tcl_ZlibDeflate(interp, TCL_ZLIB_FORMAT_RAW, objv[2], level,
		NULL);
    case CMD_COMPRESS:			/* compress data ?level?
					 * -> zlibCompressedData */
    case CMD_COMPRESS:		/* compress data ?level?
				 *	-> zlibCompressedData */
	if (objc < 3 || objc > 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "data ?level?");
	    return TCL_ERROR;
	}
	if (objc > 3) {
	    if (Tcl_GetIntFromObj(interp, objv[3], &level) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (level < 0 || level > 9) {
		goto badLevel;
	    }
	}
	return Tcl_ZlibDeflate(interp, TCL_ZLIB_FORMAT_ZLIB, objv[2], level,
		NULL);
    case CMD_GZIP:			/* gzip data ?level?
					 * -> gzippedCompressedData */
    case CMD_GZIP:		/* gzip data ?level?
				 *	-> gzippedCompressedData */
	headerDictObj = NULL;

	/*
	 * Legacy argument format support.
	 */

	if (objc == 4
2080
2081
2082
2083
2084
2085
2086
2087

2088
2089
2090

2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104


2105
2106
2107
2108
2109
2110

2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122

2123
2124

2125
2126
2127
2128
2129
2130

2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143


2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
2102
2103
2104
2105
2106
2107
2108

2109
2110
2111

2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124


2125
2126
2127
2128
2129
2130
2131

2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143

2144


2145
2146
2147
2148
2149
2150

2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
2222


2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233

2234
2235
2236
2237
2238
2239
2240
2241







-
+


-
+












-
-
+
+





-
+











-
+
-
-
+





-
+











-
-
+
+


















-
+










-
+

















-
+
-
-
+

-
-
+
+

-
+




-
-
+
+
+








-
+








	    if (Tcl_GetIndexFromObj(interp, objv[i], gzipopts, "option", 0,
		    &option) != TCL_OK) {
		return TCL_ERROR;
	    }
	    switch (option) {
	    case 0:
		headerDictObj = objv[i+1];
		headerDictObj = objv[i + 1];
		break;
	    case 1:
		if (Tcl_GetIntFromObj(interp, objv[i+1],
		if (Tcl_GetIntFromObj(interp, objv[i + 1],
			&level) != TCL_OK) {
		    return TCL_ERROR;
		}
		if (level < 0 || level > 9) {
		    extraInfoStr = "\n    (in -level option)";
		    goto badLevel;
		}
		break;
	    }
	}
	return Tcl_ZlibDeflate(interp, TCL_ZLIB_FORMAT_GZIP, objv[2], level,
		headerDictObj);
    case CMD_INFLATE:			/* inflate rawcomprdata ?bufferSize?
					 *	-> decompressedData */
    case CMD_INFLATE:		/* inflate rawcomprdata ?bufferSize?
				 *	-> decompressedData */
	if (objc < 3 || objc > 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "data ?bufferSize?");
	    return TCL_ERROR;
	}
	if (objc > 3) {
	    if (Tcl_GetWideIntFromObj(interp, objv[3],
	    if (TclGetWideIntFromObj(interp, objv[3],
		    &wideLen) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (wideLen < MIN_NONSTREAM_BUFFER_SIZE
		    || wideLen > MAX_BUFFER_SIZE) {
		goto badBuffer;
	    }
	    buffersize = wideLen;
	}
	return Tcl_ZlibInflate(interp, TCL_ZLIB_FORMAT_RAW, objv[2],
		buffersize, NULL);
    case CMD_DECOMPRESS:		/* decompress zlibcomprdata \
    case CMD_DECOMPRESS:	/* decompress zlibcomprdata ?bufferSize?
					 *    ?bufferSize?
					 *	-> decompressedData */
				 *	-> decompressedData */
	if (objc < 3 || objc > 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "data ?bufferSize?");
	    return TCL_ERROR;
	}
	if (objc > 3) {
	    if (Tcl_GetWideIntFromObj(interp, objv[3],
	    if (TclGetWideIntFromObj(interp, objv[3],
		    &wideLen) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (wideLen < MIN_NONSTREAM_BUFFER_SIZE
		    || wideLen > MAX_BUFFER_SIZE) {
		goto badBuffer;
	    }
	    buffersize = wideLen;
	}
	return Tcl_ZlibInflate(interp, TCL_ZLIB_FORMAT_ZLIB, objv[2],
		buffersize, NULL);
    case CMD_GUNZIP: {			/* gunzip gzippeddata ?bufferSize?
					 *	-> decompressedData */
    case CMD_GUNZIP: {		/* gunzip gzippeddata ?-headerVar varName?
				 *	-> decompressedData */
	Tcl_Obj *headerVarObj;

	if (objc < 3 || objc > 5 || ((objc & 1) == 0)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "data ?-headerVar varName?");
	    return TCL_ERROR;
	}
	headerDictObj = headerVarObj = NULL;
	for (i=3 ; i<objc ; i+=2) {
	    static const char *const gunzipopts[] = {
		"-buffersize", "-headerVar", NULL
	    };

	    if (Tcl_GetIndexFromObj(interp, objv[i], gunzipopts, "option", 0,
		    &option) != TCL_OK) {
		return TCL_ERROR;
	    }
	    switch (option) {
	    case 0:
		if (Tcl_GetWideIntFromObj(interp, objv[i+1],
		if (TclGetWideIntFromObj(interp, objv[i + 1],
			&wideLen) != TCL_OK) {
		    return TCL_ERROR;
		}
		if (wideLen < MIN_NONSTREAM_BUFFER_SIZE
			|| wideLen > MAX_BUFFER_SIZE) {
		    goto badBuffer;
		}
		buffersize = wideLen;
		break;
	    case 1:
		headerVarObj = objv[i+1];
		headerVarObj = objv[i + 1];
		TclNewObj(headerDictObj);
		break;
	    }
	}
	if (Tcl_ZlibInflate(interp, TCL_ZLIB_FORMAT_GZIP, objv[2],
		buffersize, headerDictObj) != TCL_OK) {
	    if (headerDictObj) {
		TclDecrRefCount(headerDictObj);
	    }
	    return TCL_ERROR;
	}
	if (headerVarObj != NULL && Tcl_ObjSetVar2(interp, headerVarObj, NULL,
		headerDictObj, TCL_LEAVE_ERR_MSG) == NULL) {
	    return TCL_ERROR;
	}
	return TCL_OK;
    }
    case CMD_STREAM:			/* stream deflate/inflate/...gunzip \
    case CMD_STREAM:		/* stream deflate/inflate/...gunzip options...
					 *    ?options...?
					 *	-> handleCmd */
				 *	-> handleCmd */
	return ZlibStreamSubcmd(interp, objc, objv);
    case CMD_PUSH:			/* push mode channel options...
					 *	-> channel */
    case CMD_PUSH:		/* push mode channel options...
				 *	-> channel */
	return ZlibPushSubcmd(interp, objc, objv);
    };
    }

    return TCL_ERROR;

  badLevel:
    Tcl_SetObjResult(interp, Tcl_NewStringObj("level must be 0 to 9", -1));
    Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMPRESSIONLEVEL", NULL);
    Tcl_SetObjResult(interp, Tcl_NewStringObj(
	    "level must be 0 to 9", TCL_AUTO_LENGTH));
    Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMPRESSIONLEVEL", (char *)NULL);
    if (extraInfoStr) {
	Tcl_AddErrorInfo(interp, extraInfoStr);
    }
    return TCL_ERROR;
  badBuffer:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "buffer size must be %d to %d",
	    MIN_NONSTREAM_BUFFER_SIZE, MAX_BUFFER_SIZE));
    Tcl_SetErrorCode(interp, "TCL", "VALUE", "BUFFERSIZE", NULL);
    Tcl_SetErrorCode(interp, "TCL", "VALUE", "BUFFERSIZE", (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * ZlibStreamSubcmd --
2233
2234
2235
2236
2237
2238
2239
2240

2241
2242
2243
2244
2245
2246
2247
2254
2255
2256
2257
2258
2259
2260

2261
2262
2263
2264
2265
2266
2267
2268







-
+







    static const char *const stream_formats[] = {
	"compress", "decompress", "deflate", "gunzip", "gzip", "inflate",
	NULL
    };
    enum zlibFormats {
	FMT_COMPRESS, FMT_DECOMPRESS, FMT_DEFLATE, FMT_GUNZIP, FMT_GZIP,
	FMT_INFLATE
    };
    } fmt;
    int i, format, mode = 0, option, level;
    enum objIndices {
	OPT_COMPRESSION_DICTIONARY = 0,
	OPT_GZIP_HEADER = 1,
	OPT_COMPRESSION_LEVEL = 2,
	OPT_END = -1
    };
2274
2275
2276
2277
2278
2279
2280
2281

2282
2283
2284
2285
2286
2287
2288
2289
2290

2291
2292
2293
2294
2295
2296
2297
2295
2296
2297
2298
2299
2300
2301

2302
2303
2304
2305
2306
2307
2308
2309
2310

2311
2312
2313
2314
2315
2316
2317
2318







-
+








-
+







    Tcl_ZlibStream zh;

    if (objc < 3 || !(objc & 1)) {
	Tcl_WrongNumArgs(interp, 2, objv, "mode ?-option value...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[2], stream_formats, "mode", 0,
	    &format) != TCL_OK) {
	    &fmt) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * The format determines the compression mode and the options that may be
     * specified.
     */

    switch ((enum zlibFormats) format) {
    switch (fmt) {
    case FMT_DEFLATE:
	desc = compressionOpts;
	mode = TCL_ZLIB_STREAM_DEFLATE;
	format = TCL_ZLIB_FORMAT_RAW;
	break;
    case FMT_INFLATE:
	desc = expansionOpts;
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
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







-
+












-
-
+
+
+





-
+







     */

    for (i=3 ; i<objc ; i+=2) {
	if (Tcl_GetIndexFromObjStruct(interp, objv[i], desc,
		sizeof(OptDescriptor), "option", 0, &option) != TCL_OK) {
	    return TCL_ERROR;
	}
	obj[desc[option].offset] = objv[i+1];
	obj[desc[option].offset] = objv[i + 1];
    }

    /*
     * If a compression level was given, parse it (integral: 0..9). Otherwise
     * use the default.
     */

    if (levelObj == NULL) {
	level = Z_DEFAULT_COMPRESSION;
    } else if (Tcl_GetIntFromObj(interp, levelObj, &level) != TCL_OK) {
	return TCL_ERROR;
    } else if (level < 0 || level > 9) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("level must be 0 to 9",-1));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMPRESSIONLEVEL", NULL);
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"level must be 0 to 9", TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMPRESSIONLEVEL", (char *)NULL);
	Tcl_AddErrorInfo(interp, "\n    (in -level option)");
	return TCL_ERROR;
    }

    if (compDictObj) {
	if (NULL == TclGetBytesFromObj(interp, compDictObj, NULL)) {
	if (NULL == Tcl_GetBytesFromObj(interp, compDictObj, (Tcl_Size *)NULL)) {
	    return TCL_ERROR;
	}
    }

    /*
     * Construct the stream now we know its configuration.
     */
2393
2394
2395
2396
2397
2398
2399
2400

2401
2402

2403
2404
2405
2406
2407
2408
2409
2410

2411
2412


2413
2414
2415
2416
2417
2418
2419
2420

2421
2422
2423

2424
2425
2426
2427
2428
2429
2430
2415
2416
2417
2418
2419
2420
2421

2422
2423

2424
2425
2426
2427
2428
2429
2430
2431

2432
2433

2434
2435
2436
2437
2438
2439
2440
2441
2442

2443
2444
2445

2446
2447
2448
2449
2450
2451
2452
2453







-
+

-
+







-
+

-
+
+







-
+


-
+







    static const char *const stream_formats[] = {
	"compress", "decompress", "deflate", "gunzip", "gzip", "inflate",
	NULL
    };
    enum zlibFormats {
	FMT_COMPRESS, FMT_DECOMPRESS, FMT_DEFLATE, FMT_GUNZIP, FMT_GZIP,
	FMT_INFLATE
    };
    } fmt;
    Tcl_Channel chan;
    int chanMode, format, mode = 0, level, i, option;
    int chanMode, format, mode = 0, level, i;
    static const char *const pushCompressOptions[] = {
	"-dictionary", "-header", "-level", NULL
    };
    static const char *const pushDecompressOptions[] = {
	"-dictionary", "-header", "-level", "-limit", NULL
    };
    const char *const *pushOptions = pushDecompressOptions;
    enum pushOptionsEnum {poDictionary, poHeader, poLevel, poLimit};
    enum pushOptionsEnum {poDictionary, poHeader, poLevel, poLimit} option;
    Tcl_Obj *headerObj = NULL, *compDictObj = NULL;
    int limit = DEFAULT_BUFFER_SIZE, dummy;
    int limit = DEFAULT_BUFFER_SIZE;
    Tcl_Size dummy;

    if (objc < 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "mode channel ?options...?");
	return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObj(interp, objv[2], stream_formats, "mode", 0,
	    &format) != TCL_OK) {
	    &fmt) != TCL_OK) {
	return TCL_ERROR;
    }
    switch ((enum zlibFormats) format) {
    switch (fmt) {
    case FMT_DEFLATE:
	mode = TCL_ZLIB_STREAM_DEFLATE;
	format = TCL_ZLIB_FORMAT_RAW;
	pushOptions = pushCompressOptions;
	break;
    case FMT_INFLATE:
	mode = TCL_ZLIB_STREAM_INFLATE;
2448
2449
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
2489

2490
2491
2492
2493


2494
2495
2496
2497
2498
2499
2500


2501
2502
2503
2504
2505

2506
2507

2508
2509
2510
2511
2512


2513
2514
2515
2516
2517
2518
2519

2520
2521
2522
2523

2524
2525
2526
2527
2528


2529
2530
2531
2532
2533
2534
2535
2536


2537
2538
2539
2540
2541
2542
2543
2471
2472
2473
2474
2475
2476
2477

2478
2479
2480
2481
2482
2483
2484
2485
2486
2487


2488
2489
2490
2491
2492
2493
2494


2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510

2511
2512
2513

2514
2515
2516


2517
2518
2519
2520
2521
2522
2523


2524
2525
2526
2527
2528
2529

2530
2531

2532
2533
2534
2535


2536
2537
2538
2539
2540
2541
2542
2543

2544
2545
2546
2547

2548
2549
2550
2551


2552
2553
2554
2555
2556
2557
2558
2559
2560

2561
2562
2563
2564
2565
2566
2567
2568
2569







-
+









-
-
+
+
+




-
-
+
+
+













-
+


-
+


-
-
+
+





-
-
+
+




-
+

-
+



-
-
+
+






-
+



-
+



-
-
+
+







-
+
+







	mode = TCL_ZLIB_STREAM_INFLATE;
	format = TCL_ZLIB_FORMAT_GZIP;
	break;
    default:
	Tcl_Panic("should be unreachable");
    }

    if (TclGetChannelFromObj(interp, objv[3], &chan, &chanMode, 0) != TCL_OK){
    if (TclGetChannelFromObj(interp, objv[3], &chan, &chanMode, 0) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Sanity checks.
     */

    if (mode == TCL_ZLIB_STREAM_DEFLATE && !(chanMode & TCL_WRITABLE)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"compression may only be applied to writable channels", -1));
	Tcl_SetErrorCode(interp, "TCL", "ZIP", "UNWRITABLE", NULL);
		"compression may only be applied to writable channels",
		TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "ZIP", "UNWRITABLE", (char *)NULL);
	return TCL_ERROR;
    }
    if (mode == TCL_ZLIB_STREAM_INFLATE && !(chanMode & TCL_READABLE)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"decompression may only be applied to readable channels",-1));
	Tcl_SetErrorCode(interp, "TCL", "ZIP", "UNREADABLE", NULL);
		"decompression may only be applied to readable channels",
		TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "ZIP", "UNREADABLE", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Parse options.
     */

    level = Z_DEFAULT_COMPRESSION;
    for (i=4 ; i<objc ; i++) {
	if (Tcl_GetIndexFromObj(interp, objv[i], pushOptions, "option", 0,
		&option) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (++i > objc-1) {
	if (++i > objc - 1) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "value missing for %s option", pushOptions[option]));
	    Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", (char *)NULL);
	    return TCL_ERROR;
	}
	switch ((enum pushOptionsEnum) option) {
	case poHeader:
	switch (option) {
	case poHeader:		/* -header headerDict */
	    headerObj = objv[i];
	    if (Tcl_DictObjSize(interp, headerObj, &dummy) != TCL_OK) {
		goto genericOptionError;
	    }
	    break;
	case poLevel:
	    if (Tcl_GetIntFromObj(interp, objv[i], (int*) &level) != TCL_OK) {
	case poLevel:		/* -level compLevel */
	    if (Tcl_GetIntFromObj(interp, objv[i], (int *) &level) != TCL_OK) {
		goto genericOptionError;
	    }
	    if (level < 0 || level > 9) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"level must be 0 to 9", -1));
			"level must be 0 to 9", TCL_AUTO_LENGTH));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMPRESSIONLEVEL",
			NULL);
			(char *)NULL);
		goto genericOptionError;
	    }
	    break;
	case poLimit:
	    if (Tcl_GetIntFromObj(interp, objv[i], (int*) &limit) != TCL_OK) {
	case poLimit:		/* -limit numBytes */
	    if (Tcl_GetIntFromObj(interp, objv[i], (int *) &limit) != TCL_OK) {
		goto genericOptionError;
	    }
	    if (limit < 1 || limit > MAX_BUFFER_SIZE) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"read ahead limit must be 1 to %d",
			MAX_BUFFER_SIZE));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "BUFFERSIZE", NULL);
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "BUFFERSIZE", (char *)NULL);
		goto genericOptionError;
	    }
	    break;
	case poDictionary:
	case poDictionary:	/* -dictionary compDict */
	    if (format == TCL_ZLIB_FORMAT_GZIP) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"a compression dictionary may not be set in the "
			"gzip format", -1));
		Tcl_SetErrorCode(interp, "TCL", "ZIP", "BADOPT", NULL);
			"gzip format", TCL_AUTO_LENGTH));
		Tcl_SetErrorCode(interp, "TCL", "ZIP", "BADOPT", (char *)NULL);
		goto genericOptionError;
	    }
	    compDictObj = objv[i];
	    break;
	}
    }

    if (compDictObj && (NULL == TclGetBytesFromObj(interp, compDictObj, NULL))) {
    if (compDictObj && (NULL == Tcl_GetBytesFromObj(interp, compDictObj,
	    (Tcl_Size *)NULL))) {
	return TCL_ERROR;
    }

    if (ZlibStackChannelTransform(interp, mode, format, level, limit, chan,
	    headerObj, compDictObj) == NULL) {
	return TCL_ERROR;
    }
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
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







-
+




-
-
+
+









-
+











-
+







 *	Implementation of the commands returned by [zlib stream].
 *
 *----------------------------------------------------------------------
 */

static int
ZlibStreamCmd(
    void *cd,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_ZlibStream zstream = (Tcl_ZlibStream)cd;
    int command, count, code;
    Tcl_ZlibStream zstream = (Tcl_ZlibStream) clientData;
    int count, code;
    Tcl_Obj *obj;
    static const char *const cmds[] = {
	"add", "checksum", "close", "eof", "finalize", "flush",
	"fullflush", "get", "header", "put", "reset",
	NULL
    };
    enum zlibStreamCommands {
	zs_add, zs_checksum, zs_close, zs_eof, zs_finalize, zs_flush,
	zs_fullflush, zs_get, zs_header, zs_put, zs_reset
    };
    } command;

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

    if (Tcl_GetIndexFromObj(interp, objv[1], cmds, "option", 0,
	    &command) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum zlibStreamCommands) command) {
    switch (command) {
    case zs_add:		/* $strm add ?$flushopt? $data */
	return ZlibStreamAddCmd(zstream, interp, objc, objv);
    case zs_header:		/* $strm header */
	return ZlibStreamHeaderCmd(zstream, interp, objc, objv);
    case zs_put:		/* $strm put ?$flushopt? $data */
	return ZlibStreamPutCmd(zstream, interp, objc, objv);

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
3134
3135
3136
3137
3138
3139
3140
3141
3142


3143
3144
3145
3146
3147
3148
3149
3150
3151

3152
3153
3154
3155
3156

3157
3158
3159

3160
3161
3162
3163
3164
3165
3166
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
3134
3135

3136
3137
3138
3139
3140
3141
3142
3143
3144


3145
3146
3147

3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
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
3199
3200

3201
3202
3203
3204
3205
3206
3207
3208







-
+






-
-
+
+














-
+




-
-
+
+






-
+







-
-
+
+






-
+






-
+






-
-
+
+


-
-
+
+









-
+



-
-
+
+


-
-
+
+









-
-
+
+












-
+

-
+













-
+



















-
+




-
-
+
+






-
+







-
-
+
+






-
+






-
+






-
-
+
+


-
-
+
+








-
-
+
+












-
+

-
+












-
+




-
+




-
+








-
-
+
+
+













+
+
+
+
+
+
+
+
+
+
+












-
+

-
+











-
+





-
-
+
+

-
-
+
+








-
+




-
+




-
+
+












-
+






-
-
+
+
+
+


-
+






-
-
-
+
+
+


-
-
-
+
+
+

-
-
-
+
+
+

-
+




















-
+

-
+


-
-
-
+
+
+



-
-
-
+
+
+
+


-
+

-
+





-
+










-
+
+







-
-
+
+

-
+
+












-

-
+








-
+











-
-
+
+
-







-
+




-
+


-
+







	}
	return Tcl_ZlibStreamClose(zstream);
    case zs_eof:		/* $strm eof */
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tcl_ZlibStreamEof(zstream)));
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Tcl_ZlibStreamEof(zstream)));
	return TCL_OK;
    case zs_checksum:		/* $strm checksum */
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt)
		(uLong) Tcl_ZlibStreamChecksum(zstream)));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
		(uint32_t) Tcl_ZlibStreamChecksum(zstream)));
	return TCL_OK;
    case zs_reset:		/* $strm reset */
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	return Tcl_ZlibStreamReset(zstream);
    }

    return TCL_OK;
}

static int
ZlibStreamAddCmd(
    void *cd,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_ZlibStream zstream = (Tcl_ZlibStream)cd;
    int index, code, buffersize = -1, flush = -1, i;
    Tcl_ZlibStream zstream = (Tcl_ZlibStream) clientData;
    int code, buffersize = -1, flush = -1, i;
    Tcl_Obj *obj, *compDictObj = NULL;
    static const char *const add_options[] = {
	"-buffer", "-dictionary", "-finalize", "-flush", "-fullflush", NULL
    };
    enum addOptions {
	ao_buffer, ao_dictionary, ao_finalize, ao_flush, ao_fullflush
    };
    } index;

    for (i=2; i<objc-1; i++) {
	if (Tcl_GetIndexFromObj(interp, objv[i], add_options, "option", 0,
		&index) != TCL_OK) {
	    return TCL_ERROR;
	}

	switch ((enum addOptions) index) {
	case ao_flush: /* -flush */
	switch (index) {
	case ao_flush:		/* -flush */
	    if (flush >= 0) {
		flush = -2;
	    } else {
		flush = Z_SYNC_FLUSH;
	    }
	    break;
	case ao_fullflush: /* -fullflush */
	case ao_fullflush:	/* -fullflush */
	    if (flush >= 0) {
		flush = -2;
	    } else {
		flush = Z_FULL_FLUSH;
	    }
	    break;
	case ao_finalize: /* -finalize */
	case ao_finalize:	/* -finalize */
	    if (flush >= 0) {
		flush = -2;
	    } else {
		flush = Z_FINISH;
	    }
	    break;
	case ao_buffer: /* -buffer */
	    if (i == objc-2) {
	case ao_buffer:		/* -buffer bufferSize */
	    if (i == objc - 2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"\"-buffer\" option must be followed by integer "
			"decompression buffersize", -1));
		Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", NULL);
			"decompression buffersize", TCL_AUTO_LENGTH));
		Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", (char *)NULL);
		return TCL_ERROR;
	    }
	    if (Tcl_GetIntFromObj(interp, objv[++i], &buffersize) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (buffersize < 1 || buffersize > MAX_BUFFER_SIZE) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"buffer size must be 1 to %d",
			MAX_BUFFER_SIZE));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "BUFFERSIZE", NULL);
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "BUFFERSIZE", (char *)NULL);
		return TCL_ERROR;
	    }
	    break;
	case ao_dictionary:
	    if (i == objc-2) {
	case ao_dictionary:	/* -dictionary compDict */
	    if (i == objc - 2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"\"-dictionary\" option must be followed by"
			" compression dictionary bytes", -1));
		Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", NULL);
			" compression dictionary bytes", TCL_AUTO_LENGTH));
		Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", (char *)NULL);
		return TCL_ERROR;
	    }
	    compDictObj = objv[++i];
	    break;
	}

	if (flush == -2) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "\"-flush\", \"-fullflush\" and \"-finalize\" options"
		    " are mutually exclusive", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ZIP", "EXCLUSIVE", NULL);
		    " are mutually exclusive", TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(interp, "TCL", "ZIP", "EXCLUSIVE", (char *)NULL);
	    return TCL_ERROR;
	}
    }
    if (flush == -1) {
	flush = 0;
    }

    /*
     * Set the compression dictionary if requested.
     */

    if (compDictObj != NULL) {
	size_t len = 0;
	Tcl_Size len = 0;

	if (NULL == TclGetBytesFromObj(interp, compDictObj, &len)) {
	if (NULL == Tcl_GetBytesFromObj(interp, compDictObj, &len)) {
	    return TCL_ERROR;
	}

	if (len == 0) {
	    compDictObj = NULL;
	}
	Tcl_ZlibStreamSetCompressionDictionary(zstream, compDictObj);
    }

    /*
     * Send the data to the stream core, along with any flushing directive.
     */

    if (Tcl_ZlibStreamPut(zstream, objv[objc-1], flush) != TCL_OK) {
    if (Tcl_ZlibStreamPut(zstream, objv[objc - 1], flush) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Get such data out as we can (up to the requested length).
     */

    TclNewObj(obj);
    code = Tcl_ZlibStreamGet(zstream, obj, buffersize);
    if (code == TCL_OK) {
	Tcl_SetObjResult(interp, obj);
    } else {
	TclDecrRefCount(obj);
    }
    return code;
}

static int
ZlibStreamPutCmd(
    void *cd,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_ZlibStream zstream = (Tcl_ZlibStream)cd;
    int index, flush = -1, i;
    Tcl_ZlibStream zstream = (Tcl_ZlibStream) clientData;
    int flush = -1, i;
    Tcl_Obj *compDictObj = NULL;
    static const char *const put_options[] = {
	"-dictionary", "-finalize", "-flush", "-fullflush", NULL
    };
    enum putOptions {
	po_dictionary, po_finalize, po_flush, po_fullflush
    };
    } index;

    for (i=2; i<objc-1; i++) {
	if (Tcl_GetIndexFromObj(interp, objv[i], put_options, "option", 0,
		&index) != TCL_OK) {
	    return TCL_ERROR;
	}

	switch ((enum putOptions) index) {
	case po_flush: /* -flush */
	switch (index) {
	case po_flush:		/* -flush */
	    if (flush >= 0) {
		flush = -2;
	    } else {
		flush = Z_SYNC_FLUSH;
	    }
	    break;
	case po_fullflush: /* -fullflush */
	case po_fullflush:	/* -fullflush */
	    if (flush >= 0) {
		flush = -2;
	    } else {
		flush = Z_FULL_FLUSH;
	    }
	    break;
	case po_finalize: /* -finalize */
	case po_finalize:	/* -finalize */
	    if (flush >= 0) {
		flush = -2;
	    } else {
		flush = Z_FINISH;
	    }
	    break;
	case po_dictionary:
	    if (i == objc-2) {
	case po_dictionary:	/* -dictionary compDict */
	    if (i == objc - 2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"\"-dictionary\" option must be followed by"
			" compression dictionary bytes", -1));
		Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", NULL);
			" compression dictionary bytes", TCL_AUTO_LENGTH));
		Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", (char *)NULL);
		return TCL_ERROR;
	    }
	    compDictObj = objv[++i];
	    break;
	}
	if (flush == -2) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "\"-flush\", \"-fullflush\" and \"-finalize\" options"
		    " are mutually exclusive", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ZIP", "EXCLUSIVE", NULL);
		    " are mutually exclusive", TCL_AUTO_LENGTH));
	    Tcl_SetErrorCode(interp, "TCL", "ZIP", "EXCLUSIVE", (char *)NULL);
	    return TCL_ERROR;
	}
    }
    if (flush == -1) {
	flush = 0;
    }

    /*
     * Set the compression dictionary if requested.
     */

    if (compDictObj != NULL) {
	size_t len = 0;
	Tcl_Size len = 0;

	if (NULL == TclGetBytesFromObj(interp, compDictObj, &len)) {
	if (NULL == Tcl_GetBytesFromObj(interp, compDictObj, &len)) {
	    return TCL_ERROR;
	}
	if (len == 0) {
	    compDictObj = NULL;
	}
	Tcl_ZlibStreamSetCompressionDictionary(zstream, compDictObj);
    }

    /*
     * Send the data to the stream core, along with any flushing directive.
     */

    return Tcl_ZlibStreamPut(zstream, objv[objc-1], flush);
    return Tcl_ZlibStreamPut(zstream, objv[objc - 1], flush);
}

static int
ZlibStreamHeaderCmd(
    void *cd,
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    ZlibStreamHandle *zshPtr = (ZlibStreamHandle *)cd;
    ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) clientData;
    Tcl_Obj *resultObj;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 2, objv, NULL);
	return TCL_ERROR;
    } else if (zshPtr->mode != TCL_ZLIB_STREAM_INFLATE
	    || zshPtr->format != TCL_ZLIB_FORMAT_GZIP) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"only gunzip streams can produce header information", -1));
	Tcl_SetErrorCode(interp, "TCL", "ZIP", "BADOP", NULL);
		"only gunzip streams can produce header information",
		TCL_AUTO_LENGTH));
	Tcl_SetErrorCode(interp, "TCL", "ZIP", "BADOP", (char *)NULL);
	return TCL_ERROR;
    }

    TclNewObj(resultObj);
    ExtractHeader(&zshPtr->gzHeaderPtr->header, resultObj);
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *	Set of functions to support channel stacking.
 *----------------------------------------------------------------------
 */

static inline int
HaveFlag(
    ZlibChannelData *chanDataPtr,
    int flag)
{
    return (chanDataPtr->flags & flag) != 0;
}

/*
 *
 * ZlibTransformClose --
 *
 *	How to shut down a stacked compressing/decompressing transform.
 *
 *----------------------------------------------------------------------
 */

static int
ZlibTransformClose(
    void *instanceData,
    Tcl_Interp *interp,
	int flags)
    int flags)
{
    ZlibChannelData *cd = (ZlibChannelData *)instanceData;
    ZlibChannelData *chanDataPtr = (ZlibChannelData *) instanceData;
    int e, result = TCL_OK;
    size_t written;

    if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
	return EINVAL;
    }

    /*
     * Delete the support timer.
     */

    ZlibTransformEventTimerKill(cd);
    ZlibTransformEventTimerKill(chanDataPtr);

    /*
     * Flush any data waiting to be compressed.
     */

    if (cd->mode == TCL_ZLIB_STREAM_DEFLATE) {
	cd->outStream.avail_in = 0;
    if (chanDataPtr->mode == TCL_ZLIB_STREAM_DEFLATE) {
	chanDataPtr->outStream.avail_in = 0;
	do {
	    e = Deflate(&cd->outStream, cd->outBuffer, cd->outAllocated,
		    Z_FINISH, &written);
	    e = Deflate(&chanDataPtr->outStream, chanDataPtr->outBuffer,
		    chanDataPtr->outAllocated, Z_FINISH, &written);

	    /*
	     * Can't be sure that deflate() won't declare the buffer to be
	     * full (with Z_BUF_ERROR) so handle that case.
	     */

	    if (e == Z_BUF_ERROR) {
		e = Z_OK;
		written = cd->outAllocated;
		written = chanDataPtr->outAllocated;
	    }
	    if (e != Z_OK && e != Z_STREAM_END) {
		/* TODO: is this the right way to do errors on close? */
		if (!TclInThreadExit()) {
		    ConvertError(interp, e, cd->outStream.adler);
		    ConvertError(interp, e, chanDataPtr->outStream.adler);
		}
		result = TCL_ERROR;
		break;
	    }
	    if (written && Tcl_WriteRaw(cd->parent, cd->outBuffer, written) == TCL_IO_FAILURE) {
	    if (written && Tcl_WriteRaw(chanDataPtr->parent,
		    chanDataPtr->outBuffer, written) == TCL_IO_FAILURE) {
		/* TODO: is this the right way to do errors on close?
		 * Note: when close is called from FinalizeIOSubsystem then
		 * interp may be NULL */
		if (!TclInThreadExit() && interp) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "error while finalizing file: %s",
			    Tcl_PosixError(interp)));
		}
		result = TCL_ERROR;
		break;
	    }
	} while (e != Z_STREAM_END);
	(void) deflateEnd(&cd->outStream);
	(void) deflateEnd(&chanDataPtr->outStream);
    } else {
	/*
	 * If we have unused bytes from the read input (overshot by
	 * Z_STREAM_END or on possible error), unget them back to the parent
	 * channel, so that they appear as not being read yet.
	 */
	if (cd->inStream.avail_in) {
	    Tcl_Ungets (cd->parent, (char *)cd->inStream.next_in, cd->inStream.avail_in, 0);
	if (chanDataPtr->inStream.avail_in) {
	    Tcl_Ungets(chanDataPtr->parent,
		    (char *) chanDataPtr->inStream.next_in,
		    chanDataPtr->inStream.avail_in, 0);
	}

	(void) inflateEnd(&cd->inStream);
	(void) inflateEnd(&chanDataPtr->inStream);
    }

    /*
     * Release all memory.
     */

    if (cd->compDictObj) {
	Tcl_DecrRefCount(cd->compDictObj);
	cd->compDictObj = NULL;
    if (chanDataPtr->compDictObj) {
	Tcl_DecrRefCount(chanDataPtr->compDictObj);
	chanDataPtr->compDictObj = NULL;
    }

    if (cd->inBuffer) {
	Tcl_Free(cd->inBuffer);
	cd->inBuffer = NULL;
    if (chanDataPtr->inBuffer) {
	Tcl_Free(chanDataPtr->inBuffer);
	chanDataPtr->inBuffer = NULL;
    }
    if (cd->outBuffer) {
	Tcl_Free(cd->outBuffer);
	cd->outBuffer = NULL;
    if (chanDataPtr->outBuffer) {
	Tcl_Free(chanDataPtr->outBuffer);
	chanDataPtr->outBuffer = NULL;
    }
    Tcl_Free(cd);
    Tcl_Free(chanDataPtr);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * ZlibTransformInput --
 *
 *	Reader filter that does decompression.
 *
 *----------------------------------------------------------------------
 */

static int
ZlibTransformInput(
    void *instanceData,
    char *buf,
    int toRead,
    int *errorCodePtr)
{
    ZlibChannelData *cd = (ZlibChannelData *)instanceData;
    ZlibChannelData *chanDataPtr = (ZlibChannelData *) instanceData;
    Tcl_DriverInputProc *inProc =
	    Tcl_ChannelInputProc(Tcl_GetChannelType(cd->parent));
	    Tcl_ChannelInputProc(Tcl_GetChannelType(chanDataPtr->parent));
    int readBytes, gotBytes;

    if (cd->mode == TCL_ZLIB_STREAM_DEFLATE) {
	return inProc(Tcl_GetChannelInstanceData(cd->parent), buf, toRead,
		errorCodePtr);
    if (chanDataPtr->mode == TCL_ZLIB_STREAM_DEFLATE) {
	return inProc(Tcl_GetChannelInstanceData(chanDataPtr->parent), buf,
		toRead, errorCodePtr);
    }

    gotBytes = 0;
    readBytes = cd->inStream.avail_in; /* how many bytes in buffer now */
    while (!(cd->flags & STREAM_DONE) && toRead > 0) {
    	unsigned int n; int decBytes;
    readBytes = chanDataPtr->inStream.avail_in; /* how many bytes in buffer now */
    while (!HaveFlag(chanDataPtr, STREAM_DONE) && toRead > 0) {
	unsigned int n;
	int decBytes;

	/* if starting from scratch or continuation after full decompression */
	if (!cd->inStream.avail_in) {
	if (!chanDataPtr->inStream.avail_in) {
	    /* buffer to start, we can read to whole available buffer */
	    cd->inStream.next_in = (Bytef *) cd->inBuffer;
	    chanDataPtr->inStream.next_in = (Bytef *) chanDataPtr->inBuffer;
	}
	/*
	 * If done - no read needed anymore, check we have to copy rest of
	 * decompressed data, otherwise return with size (or 0 for Eof)
	 */
	if (cd->flags & STREAM_DECOMPRESS) {
	if (HaveFlag(chanDataPtr, STREAM_DECOMPRESS)) {
	    goto copyDecompressed;
	}
	/*
	 * The buffer is exhausted, but the caller wants even more. We now
	 * have to go to the underlying channel, get more bytes and then
	 * transform them for delivery. We may not get what we want (full EOF
	 * or temporarily out of data).
	 */

	/* Check free buffer size and adjust size of next chunk to read. */
	n = cd->inAllocated - ((char *)cd->inStream.next_in - cd->inBuffer);
	n = chanDataPtr->inAllocated - ((char *)
		chanDataPtr->inStream.next_in - chanDataPtr->inBuffer);
	if (n <= 0) {
	    /* Normally unreachable: not enough input buffer to uncompress.
	     * Todo: firstly try to realloc inBuffer upto MAX_BUFFER_SIZE.
	     */
	    *errorCodePtr = ENOBUFS;
	    return -1;
	}
	if (n > cd->readAheadLimit) {
	    n = cd->readAheadLimit;
	if (n > chanDataPtr->readAheadLimit) {
	    n = chanDataPtr->readAheadLimit;
	}
	readBytes = Tcl_ReadRaw(cd->parent, (char *)cd->inStream.next_in, n);
	readBytes = Tcl_ReadRaw(chanDataPtr->parent,
		(char *) chanDataPtr->inStream.next_in, n);

	/*
	 * Three cases here:
	 *  1.	Got some data from the underlying channel (readBytes > 0) so
	 *	it should be fed through the decompression engine.
	 *  2.	Got an error (readBytes == -1) which we should report up except
	 *	for the case where we can convert it to a short read.
	 *  3.	Got an end-of-data from EOF or blocking (readBytes == 0). If
	 *	it is EOF, try flushing the data out of the decompressor.
	 */

	if (readBytes == -1) {

	    /* See ReflectInput() in tclIORTrans.c */
	    if (Tcl_InputBlocked(cd->parent) && (gotBytes > 0)) {
	    if (Tcl_InputBlocked(chanDataPtr->parent) && (gotBytes > 0)) {
		break;
	    }

	    *errorCodePtr = Tcl_GetErrno();
	    return -1;
	}

	/* more bytes (or Eof if readBytes == 0) */
	cd->inStream.avail_in += readBytes;
	chanDataPtr->inStream.avail_in += readBytes;

copyDecompressed:

	/*
	 * Transform the read chunk, if not empty. Anything we get
	 * back is a transformation result to be put into our buffers, and
	 * the next iteration will put it into the result.
	 * For the case readBytes is 0 which signaling Eof in parent, the
	 * partial data waiting is converted and returned.
	 */

	decBytes = ResultDecompress(cd, buf, toRead,
		    (readBytes != 0) ? Z_NO_FLUSH : Z_SYNC_FLUSH,
	decBytes = ResultDecompress(chanDataPtr, buf, toRead,
		(readBytes != 0) ? Z_NO_FLUSH : Z_SYNC_FLUSH,  errorCodePtr);
		    errorCodePtr);
	if (decBytes == -1) {
	    return -1;
	}
	gotBytes += decBytes;
	buf += decBytes;
	toRead -= decBytes;

	if (((decBytes == 0) || (cd->flags & STREAM_DECOMPRESS))) {
	if ((decBytes == 0) || HaveFlag(chanDataPtr, STREAM_DECOMPRESS)) {
	    /*
	     * The drain delivered nothing (or buffer too small to decompress).
	     * Time to deliver what we've got.
	     */
	    if (!gotBytes && !(cd->flags & STREAM_DONE)) {
	    if (!gotBytes && !HaveFlag(chanDataPtr, STREAM_DONE)) {
		/* if no-data, but not ready - avoid signaling Eof,
		 * continue in blocking mode, otherwise EAGAIN */
		if (Tcl_InputBlocked(cd->parent)) {
		if (Tcl_InputBlocked(chanDataPtr->parent)) {
		    continue;
		}
		*errorCodePtr = EAGAIN;
		return -1;
	    }
	    break;
	}
3187
3188
3189
3190
3191
3192
3193
3194

3195
3196

3197
3198
3199
3200
3201
3202
3203



3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218





3219
3220
3221
3222

3223

3224
3225
3226
3227
3228
3229
3230

3231
3232
3233
3234


3235
3236

3237
3238
3239


3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257

3258
3259
3260
3261
3262
3263

3264
3265
3266
3267
3268
3269
3270


3271
3272

3273
3274
3275
3276
3277
3278
3279

3280

3281
3282
3283
3284
3285
3286
3287
3229
3230
3231
3232
3233
3234
3235

3236
3237

3238
3239
3240
3241
3242



3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255





3256
3257
3258
3259
3260
3261
3262
3263
3264
3265

3266
3267
3268
3269
3270
3271
3272

3273
3274
3275
3276

3277
3278
3279

3280
3281


3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300

3301
3302
3303
3304
3305
3306

3307
3308
3309
3310
3311
3312


3313
3314
3315

3316
3317
3318
3319
3320
3321
3322
3323
3324

3325
3326
3327
3328
3329
3330
3331
3332







-
+

-
+




-
-
-
+
+
+










-
-
-
-
-
+
+
+
+
+




+
-
+






-
+



-
+
+

-
+

-
-
+
+

















-
+





-
+





-
-
+
+

-
+







+
-
+







static int
ZlibTransformOutput(
    void *instanceData,
    const char *buf,
    int toWrite,
    int *errorCodePtr)
{
    ZlibChannelData *cd = (ZlibChannelData *)instanceData;
    ZlibChannelData *chanDataPtr = (ZlibChannelData *) instanceData;
    Tcl_DriverOutputProc *outProc =
	    Tcl_ChannelOutputProc(Tcl_GetChannelType(cd->parent));
	    Tcl_ChannelOutputProc(Tcl_GetChannelType(chanDataPtr->parent));
    int e;
    size_t produced;
    Tcl_Obj *errObj;

    if (cd->mode == TCL_ZLIB_STREAM_INFLATE) {
	return outProc(Tcl_GetChannelInstanceData(cd->parent), buf, toWrite,
		errorCodePtr);
    if (chanDataPtr->mode == TCL_ZLIB_STREAM_INFLATE) {
	return outProc(Tcl_GetChannelInstanceData(chanDataPtr->parent), buf,
		toWrite, errorCodePtr);
    }

    /*
     * No zero-length writes. Flushes must be explicit.
     */

    if (toWrite == 0) {
	return 0;
    }

    cd->outStream.next_in = (Bytef *) buf;
    cd->outStream.avail_in = toWrite;
    while (cd->outStream.avail_in > 0) {
	e = Deflate(&cd->outStream, cd->outBuffer, cd->outAllocated,
		Z_NO_FLUSH, &produced);
    chanDataPtr->outStream.next_in = (Bytef *) buf;
    chanDataPtr->outStream.avail_in = toWrite;
    while (chanDataPtr->outStream.avail_in > 0) {
	e = Deflate(&chanDataPtr->outStream, chanDataPtr->outBuffer,
		chanDataPtr->outAllocated, Z_NO_FLUSH, &produced);
	if (e != Z_OK || produced == 0) {
	    break;
	}

	if (Tcl_WriteRaw(chanDataPtr->parent, chanDataPtr->outBuffer,
	if (Tcl_WriteRaw(cd->parent, cd->outBuffer, produced) == TCL_IO_FAILURE) {
		produced) == TCL_IO_FAILURE) {
	    *errorCodePtr = Tcl_GetErrno();
	    return -1;
	}
    }

    if (e == Z_OK) {
	return toWrite - cd->outStream.avail_in;
	return toWrite - chanDataPtr->outStream.avail_in;
    }

    errObj = Tcl_NewListObj(0, NULL);
    Tcl_ListObjAppendElement(NULL, errObj, Tcl_NewStringObj("-errorcode",-1));
    Tcl_ListObjAppendElement(NULL, errObj, Tcl_NewStringObj(
	    "-errorcode", TCL_AUTO_LENGTH));
    Tcl_ListObjAppendElement(NULL, errObj,
	    ConvertErrorToList(e, cd->outStream.adler));
	    ConvertErrorToList(e, chanDataPtr->outStream.adler));
    Tcl_ListObjAppendElement(NULL, errObj,
	    Tcl_NewStringObj(cd->outStream.msg, -1));
    Tcl_SetChannelError(cd->parent, errObj);
	    Tcl_NewStringObj(chanDataPtr->outStream.msg, TCL_AUTO_LENGTH));
    Tcl_SetChannelError(chanDataPtr->parent, errObj);
    *errorCodePtr = EINVAL;
    return -1;
}

/*
 *----------------------------------------------------------------------
 *
 * ZlibTransformFlush --
 *
 *	How to perform a flush of a compressing transform.
 *
 *----------------------------------------------------------------------
 */

static int
ZlibTransformFlush(
    Tcl_Interp *interp,
    ZlibChannelData *cd,
    ZlibChannelData *chanDataPtr,
    int flushType)
{
    int e;
    size_t len;

    cd->outStream.avail_in = 0;
    chanDataPtr->outStream.avail_in = 0;
    do {
	/*
	 * Get the bytes to go out of the compression engine.
	 */

	e = Deflate(&cd->outStream, cd->outBuffer, cd->outAllocated,
		flushType, &len);
	e = Deflate(&chanDataPtr->outStream, chanDataPtr->outBuffer,
		chanDataPtr->outAllocated, flushType, &len);
	if (e != Z_OK && e != Z_BUF_ERROR) {
	    ConvertError(interp, e, cd->outStream.adler);
	    ConvertError(interp, e, chanDataPtr->outStream.adler);
	    return TCL_ERROR;
	}

	/*
	 * Write the bytes we've received to the next layer.
	 */

	if (len > 0 && Tcl_WriteRaw(chanDataPtr->parent, chanDataPtr->outBuffer,
	if (len > 0 && Tcl_WriteRaw(cd->parent, cd->outBuffer, len) == TCL_IO_FAILURE) {
		len) == TCL_IO_FAILURE) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "problem flushing channel: %s",
		    Tcl_PosixError(interp)));
	    return TCL_ERROR;
	}

	/*
3310
3311
3312
3313
3314
3315
3316
3317

3318
3319

3320
3321
3322
3323
3324

3325
3326
3327

3328
3329
3330
3331
3332
3333

3334
3335
3336
3337
3338


3339
3340

3341
3342
3343


3344
3345

3346
3347
3348
3349


3350
3351

3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370

3371
3372
3373
3374
3375
3376
3377
3378

3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389



3390
3391
3392
3393
3394
3395
3396

3397
3398

3399
3400
3401
3402

3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413


3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433

3434
3435

3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452


3453
3454

3455
3456
3457

3458
3459
3460
3461
3462

3463
3464
3465
3466
3467

3468
3469
3470
3471
3472
3473
3474
3475

3476
3477

3478
3479
3480
3481
3482
3483
3484




3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497

3498
3499
3500
3501
3502

3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519

3520
3521
3522
3523
3524
3525

3526
3527

3528
3529
3530
3531

3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552

3553
3554
3555
3556
3557
3558
3559
3560


3561
3562
3563
3564
3565
3566





3567
3568
3569
3570
3571
3572
3573
3574
3575

3576
3577

3578
3579
3580
3581
3582
3583

3584
3585
3586
3587



3588
3589
3590
3591
3592
3593
3594
3595

3596
3597
3598


3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618

3619
3620

3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638

3639
3640
3641

3642
3643

3644
3645
3646
3647
3648
3649
3650
3355
3356
3357
3358
3359
3360
3361

3362
3363

3364
3365
3366
3367
3368

3369
3370
3371

3372
3373
3374
3375
3376
3377

3378
3379
3380
3381


3382
3383
3384

3385
3386


3387
3388
3389

3390
3391
3392


3393
3394
3395

3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414

3415
3416
3417
3418
3419
3420
3421
3422

3423
3424
3425
3426
3427
3428
3429
3430
3431
3432


3433
3434
3435
3436
3437
3438
3439
3440
3441

3442
3443

3444
3445
3446
3447

3448
3449
3450
3451
3452
3453
3454
3455
3456
3457


3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478

3479
3480

3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496


3497
3498
3499

3500
3501
3502

3503
3504
3505
3506
3507

3508
3509
3510
3511
3512

3513
3514
3515
3516
3517
3518
3519
3520

3521
3522

3523
3524
3525
3526
3527



3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543

3544
3545
3546
3547
3548

3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565

3566
3567
3568
3569
3570
3571

3572
3573

3574
3575
3576
3577

3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598

3599
3600
3601
3602
3603
3604
3605


3606
3607
3608





3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621

3622
3623

3624
3625
3626
3627
3628
3629

3630
3631



3632
3633
3634
3635
3636
3637
3638
3639
3640
3641

3642
3643


3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664

3665
3666

3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684

3685
3686
3687

3688
3689

3690
3691
3692
3693
3694
3695
3696
3697







-
+

-
+




-
+


-
+





-
+



-
-
+
+

-
+

-
-
+
+

-
+


-
-
+
+

-
+


















-
+







-
+









-
-
+
+
+






-
+

-
+



-
+









-
-
+
+



















-
+

-
+















-
-
+
+

-
+


-
+




-
+




-
+







-
+

-
+




-
-
-
+
+
+
+












-
+




-
+
















-
+





-
+

-
+



-
+




















-
+






-
-
+
+

-
-
-
-
-
+
+
+
+
+








-
+

-
+





-
+

-
-
-
+
+
+







-
+

-
-
+
+



















-
+

-
+

















-
+


-
+

-
+







static int
ZlibTransformSetOption(			/* not used */
    void *instanceData,
    Tcl_Interp *interp,
    const char *optionName,
    const char *value)
{
    ZlibChannelData *cd = (ZlibChannelData *)instanceData;
    ZlibChannelData *chanDataPtr = (ZlibChannelData *) instanceData;
    Tcl_DriverSetOptionProc *setOptionProc =
	    Tcl_ChannelSetOptionProc(Tcl_GetChannelType(cd->parent));
	    Tcl_ChannelSetOptionProc(Tcl_GetChannelType(chanDataPtr->parent));
    static const char *compressChanOptions = "dictionary flush";
    static const char *gzipChanOptions = "flush";
    static const char *decompressChanOptions = "dictionary limit";
    static const char *gunzipChanOptions = "flush limit";
    int haveFlushOpt = (cd->mode == TCL_ZLIB_STREAM_DEFLATE);
    int haveFlushOpt = (chanDataPtr->mode == TCL_ZLIB_STREAM_DEFLATE);

    if (optionName && (strcmp(optionName, "-dictionary") == 0)
	    && (cd->format != TCL_ZLIB_FORMAT_GZIP)) {
	    && (chanDataPtr->format != TCL_ZLIB_FORMAT_GZIP)) {
	Tcl_Obj *compDictObj;
	int code;

	TclNewStringObj(compDictObj, value, strlen(value));
	Tcl_IncrRefCount(compDictObj);
	if (NULL == TclGetBytesFromObj(interp, compDictObj, NULL)) {
	if (NULL == Tcl_GetBytesFromObj(interp, compDictObj, (Tcl_Size *)NULL)) {
	    Tcl_DecrRefCount(compDictObj);
	    return TCL_ERROR;
	}
	if (cd->compDictObj) {
	    TclDecrRefCount(cd->compDictObj);
	if (chanDataPtr->compDictObj) {
	    TclDecrRefCount(chanDataPtr->compDictObj);
	}
	cd->compDictObj = compDictObj;
	chanDataPtr->compDictObj = compDictObj;
	code = Z_OK;
	if (cd->mode == TCL_ZLIB_STREAM_DEFLATE) {
	    code = SetDeflateDictionary(&cd->outStream, compDictObj);
	if (chanDataPtr->mode == TCL_ZLIB_STREAM_DEFLATE) {
	    code = SetDeflateDictionary(&chanDataPtr->outStream, compDictObj);
	    if (code != Z_OK) {
		ConvertError(interp, code, cd->outStream.adler);
		ConvertError(interp, code, chanDataPtr->outStream.adler);
		return TCL_ERROR;
	    }
	} else if (cd->format == TCL_ZLIB_FORMAT_RAW) {
	    code = SetInflateDictionary(&cd->inStream, compDictObj);
	} else if (chanDataPtr->format == TCL_ZLIB_FORMAT_RAW) {
	    code = SetInflateDictionary(&chanDataPtr->inStream, compDictObj);
	    if (code != Z_OK) {
		ConvertError(interp, code, cd->inStream.adler);
		ConvertError(interp, code, chanDataPtr->inStream.adler);
		return TCL_ERROR;
	    }
	}
	return TCL_OK;
    }

    if (haveFlushOpt) {
	if (optionName && strcmp(optionName, "-flush") == 0) {
	    int flushType;

	    if (value[0] == 'f' && strcmp(value, "full") == 0) {
		flushType = Z_FULL_FLUSH;
	    } else if (value[0] == 's' && strcmp(value, "sync") == 0) {
		flushType = Z_SYNC_FLUSH;
	    } else {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"unknown -flush type \"%s\": must be full or sync",
			value));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "FLUSH", NULL);
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "FLUSH", (char *)NULL);
		return TCL_ERROR;
	    }

	    /*
	     * Try to actually do the flush now.
	     */

	    return ZlibTransformFlush(interp, cd, flushType);
	    return ZlibTransformFlush(interp, chanDataPtr, flushType);
	}
    } else {
	if (optionName && strcmp(optionName, "-limit") == 0) {
	    int newLimit;

	    if (Tcl_GetInt(interp, value, &newLimit) != TCL_OK) {
		return TCL_ERROR;
	    } else if (newLimit < 1 || newLimit > MAX_BUFFER_SIZE) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"-limit must be between 1 and 65536", -1));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "READLIMIT", NULL);
			"-limit must be between 1 and 65536", TCL_AUTO_LENGTH));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "READLIMIT",
			(char *)NULL);
		return TCL_ERROR;
	    }
	}
    }

    if (setOptionProc == NULL) {
	if (cd->format == TCL_ZLIB_FORMAT_GZIP) {
	if (chanDataPtr->format == TCL_ZLIB_FORMAT_GZIP) {
	    return Tcl_BadChannelOption(interp, optionName,
		    (cd->mode == TCL_ZLIB_STREAM_DEFLATE)
		    (chanDataPtr->mode == TCL_ZLIB_STREAM_DEFLATE)
		    ? gzipChanOptions : gunzipChanOptions);
	} else {
	    return Tcl_BadChannelOption(interp, optionName,
		    (cd->mode == TCL_ZLIB_STREAM_DEFLATE)
		    (chanDataPtr->mode == TCL_ZLIB_STREAM_DEFLATE)
		    ? compressChanOptions : decompressChanOptions);
	}
    }

    /*
     * Pass all unknown options down, to deeper transforms and/or the base
     * channel.
     */

    return setOptionProc(Tcl_GetChannelInstanceData(cd->parent), interp,
	    optionName, value);
    return setOptionProc(Tcl_GetChannelInstanceData(chanDataPtr->parent),
	    interp, optionName, value);
}

/*
 *----------------------------------------------------------------------
 *
 * ZlibTransformGetOption --
 *
 *	Reading side of [fconfigure] on our channel.
 *
 *----------------------------------------------------------------------
 */

static int
ZlibTransformGetOption(
    void *instanceData,
    Tcl_Interp *interp,
    const char *optionName,
    Tcl_DString *dsPtr)
{
    ZlibChannelData *cd = (ZlibChannelData *)instanceData;
    ZlibChannelData *chanDataPtr = (ZlibChannelData *) instanceData;
    Tcl_DriverGetOptionProc *getOptionProc =
	    Tcl_ChannelGetOptionProc(Tcl_GetChannelType(cd->parent));
	    Tcl_ChannelGetOptionProc(Tcl_GetChannelType(chanDataPtr->parent));
    static const char *compressChanOptions = "checksum dictionary";
    static const char *gzipChanOptions = "checksum";
    static const char *decompressChanOptions = "checksum dictionary limit";
    static const char *gunzipChanOptions = "checksum header limit";

    /*
     * The "crc" option reports the current CRC (calculated with the Adler32
     * or CRC32 algorithm according to the format) given the data that has
     * been processed so far.
     */

    if (optionName == NULL || strcmp(optionName, "-checksum") == 0) {
	uLong crc;
	char buf[12];

	if (cd->mode == TCL_ZLIB_STREAM_DEFLATE) {
	    crc = cd->outStream.adler;
	if (chanDataPtr->mode == TCL_ZLIB_STREAM_DEFLATE) {
	    crc = chanDataPtr->outStream.adler;
	} else {
	    crc = cd->inStream.adler;
	    crc = chanDataPtr->inStream.adler;
	}

	sprintf(buf, "%lu", crc);
	snprintf(buf, sizeof(buf), "%lu", crc);
	if (optionName == NULL) {
	    Tcl_DStringAppendElement(dsPtr, "-checksum");
	    Tcl_DStringAppendElement(dsPtr, buf);
	} else {
	    Tcl_DStringAppend(dsPtr, buf, -1);
	    Tcl_DStringAppend(dsPtr, buf, TCL_AUTO_LENGTH);
	    return TCL_OK;
	}
    }

    if ((cd->format != TCL_ZLIB_FORMAT_GZIP) &&
    if ((chanDataPtr->format != TCL_ZLIB_FORMAT_GZIP) &&
	    (optionName == NULL || strcmp(optionName, "-dictionary") == 0)) {
	/*
	 * Embedded NUL bytes are ok; they'll be C080-encoded.
	 */

	if (optionName == NULL) {
	    Tcl_DStringAppendElement(dsPtr, "-dictionary");
	    if (cd->compDictObj) {
	    if (chanDataPtr->compDictObj) {
		Tcl_DStringAppendElement(dsPtr,
			TclGetString(cd->compDictObj));
			TclGetString(chanDataPtr->compDictObj));
	    } else {
		Tcl_DStringAppendElement(dsPtr, "");
	    }
	} else {
	    if (cd->compDictObj) {
		size_t length;
		const char *str = TclGetStringFromObj(cd->compDictObj, &length);
	    if (chanDataPtr->compDictObj) {
		Tcl_Size length;
		const char *str = TclGetStringFromObj(chanDataPtr->compDictObj,
			&length);

		Tcl_DStringAppend(dsPtr, str, length);
	    }
	    return TCL_OK;
	}
    }

    /*
     * The "header" option, which is only valid on inflating gzip channels,
     * reports the header that has been read from the start of the stream.
     */

    if ((cd->flags & IN_HEADER) && ((optionName == NULL) ||
    if (HaveFlag(chanDataPtr, IN_HEADER) && ((optionName == NULL) ||
	    (strcmp(optionName, "-header") == 0))) {
	Tcl_Obj *tmpObj;

	TclNewObj(tmpObj);
	ExtractHeader(&cd->inHeader.header, tmpObj);
	ExtractHeader(&chanDataPtr->inHeader.header, tmpObj);
	if (optionName == NULL) {
	    Tcl_DStringAppendElement(dsPtr, "-header");
	    Tcl_DStringAppendElement(dsPtr, TclGetString(tmpObj));
	    Tcl_DecrRefCount(tmpObj);
	} else {
	    TclDStringAppendObj(dsPtr, tmpObj);
	    Tcl_DecrRefCount(tmpObj);
	    return TCL_OK;
	}
    }

    /*
     * Now we do the standard processing of the stream we wrapped.
     */

    if (getOptionProc) {
	return getOptionProc(Tcl_GetChannelInstanceData(cd->parent),
	return getOptionProc(Tcl_GetChannelInstanceData(chanDataPtr->parent),
		interp, optionName, dsPtr);
    }
    if (optionName == NULL) {
	return TCL_OK;
    }
    if (cd->format == TCL_ZLIB_FORMAT_GZIP) {
    if (chanDataPtr->format == TCL_ZLIB_FORMAT_GZIP) {
	return Tcl_BadChannelOption(interp, optionName,
		(cd->mode == TCL_ZLIB_STREAM_DEFLATE)
		(chanDataPtr->mode == TCL_ZLIB_STREAM_DEFLATE)
		? gzipChanOptions : gunzipChanOptions);
    } else {
	return Tcl_BadChannelOption(interp, optionName,
		(cd->mode == TCL_ZLIB_STREAM_DEFLATE)
		(chanDataPtr->mode == TCL_ZLIB_STREAM_DEFLATE)
		? compressChanOptions : decompressChanOptions);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ZlibTransformWatch, ZlibTransformEventHandler --
 *
 *	If we have data pending, trigger a readable event after a short time
 *	(in order to allow a real event to catch up).
 *
 *----------------------------------------------------------------------
 */

static void
ZlibTransformWatch(
    void *instanceData,
    int mask)
{
    ZlibChannelData *cd = (ZlibChannelData *)instanceData;
    ZlibChannelData *chanDataPtr = (ZlibChannelData *) instanceData;
    Tcl_DriverWatchProc *watchProc;

    /*
     * This code is based on the code in tclIORTrans.c
     */

    watchProc = Tcl_ChannelWatchProc(Tcl_GetChannelType(cd->parent));
    watchProc(Tcl_GetChannelInstanceData(cd->parent), mask);
    watchProc = Tcl_ChannelWatchProc(Tcl_GetChannelType(chanDataPtr->parent));
    watchProc(Tcl_GetChannelInstanceData(chanDataPtr->parent), mask);

    if (!(mask & TCL_READABLE) || !(cd->flags & STREAM_DECOMPRESS)) {
	ZlibTransformEventTimerKill(cd);
    } else if (cd->timer == NULL) {
	cd->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
		ZlibTransformTimerRun, cd);
    if (!(mask & TCL_READABLE) || !HaveFlag(chanDataPtr, STREAM_DECOMPRESS)) {
	ZlibTransformEventTimerKill(chanDataPtr);
    } else if (chanDataPtr->timer == NULL) {
	chanDataPtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
		ZlibTransformTimerRun, chanDataPtr);
    }
}

static int
ZlibTransformEventHandler(
    void *instanceData,
    int interestMask)
{
    ZlibChannelData *cd = (ZlibChannelData *)instanceData;
    ZlibChannelData *chanDataPtr = (ZlibChannelData *) instanceData;

    ZlibTransformEventTimerKill(cd);
    ZlibTransformEventTimerKill(chanDataPtr);
    return interestMask;
}

static inline void
ZlibTransformEventTimerKill(
    ZlibChannelData *cd)
    ZlibChannelData *chanDataPtr)
{
    if (cd->timer != NULL) {
	Tcl_DeleteTimerHandler(cd->timer);
	cd->timer = NULL;
    if (chanDataPtr->timer != NULL) {
	Tcl_DeleteTimerHandler(chanDataPtr->timer);
	chanDataPtr->timer = NULL;
    }
}

static void
ZlibTransformTimerRun(
    void *clientData)
{
    ZlibChannelData *cd = (ZlibChannelData *)clientData;
    ZlibChannelData *chanDataPtr = (ZlibChannelData *) clientData;

    cd->timer = NULL;
    Tcl_NotifyChannel(cd->chan, TCL_READABLE);
    chanDataPtr->timer = NULL;
    Tcl_NotifyChannel(chanDataPtr->chan, TCL_READABLE);
}

/*
 *----------------------------------------------------------------------
 *
 * ZlibTransformGetHandle --
 *
 *	Anything that needs the OS handle is told to get it from what we are
 *	stacked on top of.
 *
 *----------------------------------------------------------------------
 */

static int
ZlibTransformGetHandle(
    void *instanceData,
    int direction,
    void **handlePtr)
{
    ZlibChannelData *cd = (ZlibChannelData *)instanceData;
    ZlibChannelData *chanDataPtr = (ZlibChannelData *) instanceData;

    return Tcl_GetChannelHandle(cd->parent, direction, handlePtr);
    return Tcl_GetChannelHandle(chanDataPtr->parent, direction, handlePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * ZlibTransformBlockMode --
 *
 *	We need to keep track of the blocking mode; it changes our behavior.
 *
 *----------------------------------------------------------------------
 */

static int
ZlibTransformBlockMode(
    void *instanceData,
    int mode)
{
    ZlibChannelData *cd = (ZlibChannelData *)instanceData;
    ZlibChannelData *chanDataPtr = (ZlibChannelData *) instanceData;

    if (mode == TCL_MODE_NONBLOCKING) {
	cd->flags |= ASYNC;
	chanDataPtr->flags |= ASYNC;
    } else {
	cd->flags &= ~ASYNC;
	chanDataPtr->flags &= ~ASYNC;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
3681
3682
3683
3684
3685
3686
3687

3688

3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699




3700
3701
3702
3703
3704
3705
3706



3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717







3718
3719
3720
3721
3722
3723
3724



3725
3726

3727

3728

3729

3730

3731

3732

3733

3734
3735


3736
3737
3738
3739
3740
3741
3742
3743
3744

3745
3746
3747
3748
3749



3750
3751
3752
3753




3754
3755
3756
3757
3758




3759
3760
3761
3762
3763

3764
3765
3766
3767
3768
3769
3770





3771
3772
3773
3774
3775



3776
3777
3778
3779
3780
3781

3782
3783
3784
3785
3786
3787
3788




3789
3790
3791
3792
3793
3794



3795
3796
3797
3798



3799
3800
3801


3802
3803

3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816


3817
3818
3819
3820


3821
3822
3823
3824
3825
3826
3827

3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840





3841



3842
3843
3844




3845
3846
3847

3848

3849

3850
3851
3852
3853
3854
3855
3856
3857
3858

3859
3860
3861
3862
3863
3864
3865

3866
3867
3868
3869
3870
3871
3872
3728
3729
3730
3731
3732
3733
3734
3735

3736
3737
3738
3739
3740
3741
3742
3743




3744
3745
3746
3747
3748
3749
3750
3751



3752
3753
3754
3755
3756
3757
3758







3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769



3770
3771
3772
3773
3774
3775

3776
3777
3778

3779
3780
3781

3782
3783
3784

3785
3786

3787
3788
3789
3790
3791
3792
3793
3794
3795
3796

3797
3798
3799



3800
3801
3802
3803



3804
3805
3806
3807
3808
3809
3810


3811
3812
3813
3814
3815
3816
3817
3818

3819
3820
3821
3822




3823
3824
3825
3826
3827
3828
3829
3830


3831
3832
3833
3834
3835
3836
3837
3838

3839
3840
3841
3842
3843



3844
3845
3846
3847
3848
3849
3850



3851
3852
3853
3854



3855
3856
3857
3858


3859
3860
3861

3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874

3875
3876
3877
3878


3879
3880
3881
3882
3883
3884
3885
3886

3887
3888
3889
3890
3891
3892
3893
3894
3895





3896
3897
3898
3899
3900
3901
3902
3903
3904



3905
3906
3907
3908
3909
3910

3911
3912
3913

3914
3915
3916
3917
3918
3919
3920
3921
3922

3923
3924
3925
3926
3927
3928
3929

3930
3931
3932
3933
3934
3935
3936
3937







+
-
+







-
-
-
-
+
+
+
+




-
-
-
+
+
+




-
-
-
-
-
-
-
+
+
+
+
+
+
+




-
-
-
+
+
+


+
-
+

+
-
+

+
-
+

+
-
+

-
+
+








-
+


-
-
-
+
+
+

-
-
-
+
+
+
+



-
-
+
+
+
+




-
+



-
-
-
-
+
+
+
+
+



-
-
+
+
+





-
+




-
-
-
+
+
+
+



-
-
-
+
+
+

-
-
-
+
+
+

-
-
+
+

-
+












-
+
+


-
-
+
+






-
+








-
-
-
-
-
+
+
+
+
+

+
+
+
-
-
-
+
+
+
+


-
+

+
-
+








-
+






-
+







    Tcl_Obj *gzipHeaderDictPtr,	/* A description of header to use, or NULL to
				 * use a default. Ignored if not compressing
				 * to produce gzip-format data. */
    Tcl_Obj *compDictObj)	/* Byte-array object containing compression
				 * dictionary (not dictObj!) to use if
				 * necessary. */
{
    ZlibChannelData *chanDataPtr = (ZlibChannelData *)
    ZlibChannelData *cd = (ZlibChannelData *)Tcl_Alloc(sizeof(ZlibChannelData));
	    Tcl_Alloc(sizeof(ZlibChannelData));
    Tcl_Channel chan;
    int wbits = 0;

    if (mode != TCL_ZLIB_STREAM_DEFLATE && mode != TCL_ZLIB_STREAM_INFLATE) {
	Tcl_Panic("unknown mode: %d", mode);
    }

    memset(cd, 0, sizeof(ZlibChannelData));
    cd->mode = mode;
    cd->format = format;
    cd->readAheadLimit = limit;
    memset(chanDataPtr, 0, sizeof(ZlibChannelData));
    chanDataPtr->mode = mode;
    chanDataPtr->format = format;
    chanDataPtr->readAheadLimit = limit;

    if (format == TCL_ZLIB_FORMAT_GZIP || format == TCL_ZLIB_FORMAT_AUTO) {
	if (mode == TCL_ZLIB_STREAM_DEFLATE) {
	    if (gzipHeaderDictPtr) {
		cd->flags |= OUT_HEADER;
		if (GenerateHeader(interp, gzipHeaderDictPtr, &cd->outHeader,
			NULL) != TCL_OK) {
		chanDataPtr->flags |= OUT_HEADER;
		if (GenerateHeader(interp, gzipHeaderDictPtr,
			&chanDataPtr->outHeader, NULL) != TCL_OK) {
		    goto error;
		}
	    }
	} else {
	    cd->flags |= IN_HEADER;
	    cd->inHeader.header.name = (Bytef *)
		    &cd->inHeader.nativeFilenameBuf;
	    cd->inHeader.header.name_max = MAXPATHLEN - 1;
	    cd->inHeader.header.comment = (Bytef *)
		    &cd->inHeader.nativeCommentBuf;
	    cd->inHeader.header.comm_max = MAX_COMMENT_LEN - 1;
	    chanDataPtr->flags |= IN_HEADER;
	    chanDataPtr->inHeader.header.name = (Bytef *)
		    &chanDataPtr->inHeader.nativeFilenameBuf;
	    chanDataPtr->inHeader.header.name_max = MAXPATHLEN - 1;
	    chanDataPtr->inHeader.header.comment = (Bytef *)
		    &chanDataPtr->inHeader.nativeCommentBuf;
	    chanDataPtr->inHeader.header.comm_max = MAX_COMMENT_LEN - 1;
	}
    }

    if (compDictObj != NULL) {
	cd->compDictObj = Tcl_DuplicateObj(compDictObj);
	Tcl_IncrRefCount(cd->compDictObj);
	Tcl_GetByteArrayFromObj(cd->compDictObj, NULL);
	chanDataPtr->compDictObj = Tcl_DuplicateObj(compDictObj);
	Tcl_IncrRefCount(chanDataPtr->compDictObj);
	Tcl_GetBytesFromObj(NULL, chanDataPtr->compDictObj, (Tcl_Size *)NULL);
    }

    switch (format) {
    if (format == TCL_ZLIB_FORMAT_RAW) {
    case  TCL_ZLIB_FORMAT_RAW:
	wbits = WBITS_RAW;
	break;
    } else if (format == TCL_ZLIB_FORMAT_ZLIB) {
    case TCL_ZLIB_FORMAT_ZLIB:
	wbits = WBITS_ZLIB;
	break;
    } else if (format == TCL_ZLIB_FORMAT_GZIP) {
    case TCL_ZLIB_FORMAT_GZIP:
	wbits = WBITS_GZIP;
	break;
    } else if (format == TCL_ZLIB_FORMAT_AUTO) {
    case TCL_ZLIB_FORMAT_AUTO:
	wbits = WBITS_AUTODETECT;
    } else {
	break;
    default:
	Tcl_Panic("bad format: %d", format);
    }

    /*
     * Initialize input inflater or the output deflater.
     */

    if (mode == TCL_ZLIB_STREAM_INFLATE) {
	if (inflateInit2(&cd->inStream, wbits) != Z_OK) {
	if (inflateInit2(&chanDataPtr->inStream, wbits) != Z_OK) {
	    goto error;
	}
	cd->inAllocated = DEFAULT_BUFFER_SIZE;
	if (cd->inAllocated < cd->readAheadLimit) {
	    cd->inAllocated = cd->readAheadLimit;
	chanDataPtr->inAllocated = DEFAULT_BUFFER_SIZE;
	if (chanDataPtr->inAllocated < chanDataPtr->readAheadLimit) {
	    chanDataPtr->inAllocated = chanDataPtr->readAheadLimit;
	}
	cd->inBuffer = (char *)Tcl_Alloc(cd->inAllocated);
	if (cd->flags & IN_HEADER) {
	    if (inflateGetHeader(&cd->inStream, &cd->inHeader.header) != Z_OK) {
	chanDataPtr->inBuffer = (char *) Tcl_Alloc(chanDataPtr->inAllocated);
	if (HaveFlag(chanDataPtr, IN_HEADER)) {
	    if (inflateGetHeader(&chanDataPtr->inStream,
		    &chanDataPtr->inHeader.header) != Z_OK) {
		goto error;
	    }
	}
	if (cd->format == TCL_ZLIB_FORMAT_RAW && cd->compDictObj) {
	    if (SetInflateDictionary(&cd->inStream, cd->compDictObj) != Z_OK) {
	if (chanDataPtr->format == TCL_ZLIB_FORMAT_RAW
		&& chanDataPtr->compDictObj) {
	    if (SetInflateDictionary(&chanDataPtr->inStream,
		    chanDataPtr->compDictObj) != Z_OK) {
		goto error;
	    }
	}
    } else {
	if (deflateInit2(&cd->outStream, level, Z_DEFLATED, wbits,
	if (deflateInit2(&chanDataPtr->outStream, level, Z_DEFLATED, wbits,
		MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) {
	    goto error;
	}
	cd->outAllocated = DEFAULT_BUFFER_SIZE;
	cd->outBuffer = (char *)Tcl_Alloc(cd->outAllocated);
	if (cd->flags & OUT_HEADER) {
	    if (deflateSetHeader(&cd->outStream, &cd->outHeader.header) != Z_OK) {
	chanDataPtr->outAllocated = DEFAULT_BUFFER_SIZE;
	chanDataPtr->outBuffer = (char *) Tcl_Alloc(chanDataPtr->outAllocated);
	if (HaveFlag(chanDataPtr, OUT_HEADER)) {
	    if (deflateSetHeader(&chanDataPtr->outStream,
		    &chanDataPtr->outHeader.header) != Z_OK) {
		goto error;
	    }
	}
	if (cd->compDictObj) {
	    if (SetDeflateDictionary(&cd->outStream, cd->compDictObj) != Z_OK) {
	if (chanDataPtr->compDictObj) {
	    if (SetDeflateDictionary(&chanDataPtr->outStream,
		    chanDataPtr->compDictObj) != Z_OK) {
		goto error;
	    }
	}
    }

    chan = Tcl_StackChannel(interp, &zlibChannelType, cd,
    chan = Tcl_StackChannel(interp, &zlibChannelType, chanDataPtr,
	    Tcl_GetChannelMode(channel), channel);
    if (chan == NULL) {
	goto error;
    }
    cd->chan = chan;
    cd->parent = Tcl_GetStackedChannel(chan);
    Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_GetChannelName(chan), -1));
    chanDataPtr->chan = chan;
    chanDataPtr->parent = Tcl_GetStackedChannel(chan);
    Tcl_SetObjResult(interp, Tcl_NewStringObj(
	    Tcl_GetChannelName(chan), TCL_AUTO_LENGTH));
    return chan;

  error:
    if (cd->inBuffer) {
	Tcl_Free(cd->inBuffer);
	inflateEnd(&cd->inStream);
    if (chanDataPtr->inBuffer) {
	Tcl_Free(chanDataPtr->inBuffer);
	inflateEnd(&chanDataPtr->inStream);
    }
    if (cd->outBuffer) {
	Tcl_Free(cd->outBuffer);
	deflateEnd(&cd->outStream);
    if (chanDataPtr->outBuffer) {
	Tcl_Free(chanDataPtr->outBuffer);
	deflateEnd(&chanDataPtr->outStream);
    }
    if (cd->compDictObj) {
	Tcl_DecrRefCount(cd->compDictObj);
    if (chanDataPtr->compDictObj) {
	Tcl_DecrRefCount(chanDataPtr->compDictObj);
    }
    Tcl_Free(cd);
    Tcl_Free(chanDataPtr);
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * ResultDecompress --
 *
 *	Extract uncompressed bytes from the compression engine and store them
 *	in our buffer (buf) up to toRead bytes.
 *
 * Result:
 *	Number of bytes decompressed or -1 if error (with *errorCodePtr updated with reason).
 *	Number of bytes decompressed or -1 if error (with *errorCodePtr updated
 *	with reason).
 *
 * Side effects:
 *	After execution it updates cd->inStream (next_in, avail_in) to reflect
 *	the data that has been decompressed.
 *	After execution it updates chanDataPtr->inStream (next_in, avail_in) to
 *	reflect the data that has been decompressed.
 *
 *----------------------------------------------------------------------
 */

static int
ResultDecompress(
    ZlibChannelData *cd,
    ZlibChannelData *chanDataPtr,
    char *buf,
    int toRead,
    int flush,
    int *errorCodePtr)
{
    int e, written, resBytes = 0;
    Tcl_Obj *errObj;


    cd->flags &= ~STREAM_DECOMPRESS;
    cd->inStream.next_out = (Bytef *) buf;
    cd->inStream.avail_out = toRead;
    while (cd->inStream.avail_out > 0) {
    chanDataPtr->flags &= ~STREAM_DECOMPRESS;
    chanDataPtr->inStream.next_out = (Bytef *) buf;
    chanDataPtr->inStream.avail_out = toRead;
    while (chanDataPtr->inStream.avail_out > 0) {
	e = inflate(&chanDataPtr->inStream, flush);

	/*
	 * Apply a compression dictionary if one is needed and we have one.
	 */
	e = inflate(&cd->inStream, flush);
	if (e == Z_NEED_DICT && cd->compDictObj) {
	    e = SetInflateDictionary(&cd->inStream, cd->compDictObj);

	if (e == Z_NEED_DICT && chanDataPtr->compDictObj) {
	    e = SetInflateDictionary(&chanDataPtr->inStream,
		    chanDataPtr->compDictObj);
	    if (e == Z_OK) {
		/*
		 * A repetition of Z_NEED_DICT is just an error.
		 * A repetition of Z_NEED_DICT now is just an error.
		 */

		e = inflate(&cd->inStream, flush);
		e = inflate(&chanDataPtr->inStream, flush);
	    }
	}

	/*
	 * avail_out is now the left over space in the output.  Therefore
	 * "toRead - avail_out" is the amount of bytes generated.
	 */

	written = toRead - cd->inStream.avail_out;
	written = toRead - chanDataPtr->inStream.avail_out;

	/*
	 * The cases where we're definitely done.
	 */

	if (e == Z_STREAM_END) {
	    cd->flags |= STREAM_DONE;
	    chanDataPtr->flags |= STREAM_DONE;
	    resBytes += written;
	    break;
	}
	if (e == Z_OK) {
	    if (written == 0) {
		break;
	    }
3890
3891
3892
3893
3894
3895
3896
3897

3898
3899
3900
3901
3902

3903

3904

3905
3906

3907
3908
3909
3910
3911
3912
3913
3914


3915
3916

3917
3918
3919


3920
3921
3922
3923
3924
3925
3926
3955
3956
3957
3958
3959
3960
3961

3962
3963
3964
3965
3966

3967
3968
3969

3970
3971

3972
3973
3974
3975
3976
3977
3978
3979

3980
3981
3982

3983
3984


3985
3986
3987
3988
3989
3990
3991
3992
3993







-
+




-
+

+
-
+

-
+







-
+
+

-
+

-
-
+
+







	    goto handleError;
	}

	/*
	 * Check if the inflate stopped early.
	 */

	if (cd->inStream.avail_in <= 0 && flush != Z_SYNC_FLUSH) {
	if (chanDataPtr->inStream.avail_in <= 0 && flush != Z_SYNC_FLUSH) {
	    break;
	}
    }

    if (!(cd->flags & STREAM_DONE)) {
    if (!HaveFlag(chanDataPtr, STREAM_DONE)) {
	/* if we have pending input data, but no available output buffer */
	if (chanDataPtr->inStream.avail_in
	if (cd->inStream.avail_in && !cd->inStream.avail_out) {
		&& !chanDataPtr->inStream.avail_out) {
	    /* next time try to decompress it got readable (new output buffer) */
	    cd->flags |= STREAM_DECOMPRESS;
	    chanDataPtr->flags |= STREAM_DECOMPRESS;
	}
    }

    return resBytes;

  handleError:
    errObj = Tcl_NewListObj(0, NULL);
    Tcl_ListObjAppendElement(NULL, errObj, Tcl_NewStringObj("-errorcode",-1));
    Tcl_ListObjAppendElement(NULL, errObj, Tcl_NewStringObj(
	    "-errorcode", TCL_AUTO_LENGTH));
    Tcl_ListObjAppendElement(NULL, errObj,
	    ConvertErrorToList(e, cd->inStream.adler));
	    ConvertErrorToList(e, chanDataPtr->inStream.adler));
    Tcl_ListObjAppendElement(NULL, errObj,
	    Tcl_NewStringObj(cd->inStream.msg, -1));
    Tcl_SetChannelError(cd->parent, errObj);
	    Tcl_NewStringObj(chanDataPtr->inStream.msg, TCL_AUTO_LENGTH));
    Tcl_SetChannelError(chanDataPtr->parent, errObj);
    *errorCodePtr = EINVAL;
    return -1;
}

/*
 *----------------------------------------------------------------------
 *	Finally, the TclZlibInit function. Used to install the zlib API.
3935
3936
3937
3938
3939
3940
3941
3942


3943
3944
3945
3946
3947
3948
3949
4002
4003
4004
4005
4006
4007
4008

4009
4010
4011
4012
4013
4014
4015
4016
4017







-
+
+








    /*
     * This does two things. It creates a counter used in the creation of
     * stream commands, and it creates the namespace that will contain those
     * commands.
     */

    Tcl_EvalEx(interp, "namespace eval ::tcl::zlib {variable cmdcounter 0}", -1, 0);
    Tcl_EvalEx(interp, "namespace eval ::tcl::zlib {variable cmdcounter 0}",
	    TCL_AUTO_LENGTH, 0);

    /*
     * Create the public scripted interface to this file's functionality.
     */

    Tcl_CreateObjCommand(interp, "zlib", ZlibCmd, 0, 0);

3965
3966
3967
3968
3969
3970
3971
3972

3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4033
4034
4035
4036
4037
4038
4039

4040
4041






































































































































4042
4043
4044
4045
4046
4047
4048
4049







-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-









    TclRegisterCommandTypeName(ZlibStreamCmd, "zlibStream");

    /*
     * Formally provide the package as a Tcl built-in.
     */

    return Tcl_PkgProvideEx(interp, "zlib", TCL_ZLIB_VERSION, NULL);
    return Tcl_PkgProvideEx(interp, "tcl::zlib", TCL_ZLIB_VERSION, NULL);
}

/*
 *----------------------------------------------------------------------
 *	Stubs used when a suitable zlib installation was not found during
 *	configure.
 *----------------------------------------------------------------------
 */

#else /* !HAVE_ZLIB */
int
Tcl_ZlibStreamInit(
    Tcl_Interp *interp,
    int mode,
    int format,
    int level,
    Tcl_Obj *dictObj,
    Tcl_ZlibStream *zshandle)
{
    if (interp) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("unimplemented", -1));
	Tcl_SetErrorCode(interp, "TCL", "UNIMPLEMENTED", NULL);
    }
    return TCL_ERROR;
}

int
Tcl_ZlibStreamClose(
    Tcl_ZlibStream zshandle)
{
    return TCL_OK;
}

int
Tcl_ZlibStreamReset(
    Tcl_ZlibStream zshandle)
{
    return TCL_OK;
}

Tcl_Obj *
Tcl_ZlibStreamGetCommandName(
    Tcl_ZlibStream zshandle)
{
    return NULL;
}

int
Tcl_ZlibStreamEof(
    Tcl_ZlibStream zshandle)
{
    return 1;
}

int
Tcl_ZlibStreamChecksum(
    Tcl_ZlibStream zshandle)
{
    return 0;
}

int
Tcl_ZlibStreamPut(
    Tcl_ZlibStream zshandle,
    Tcl_Obj *data,
    int flush)
{
    return TCL_OK;
}

int
Tcl_ZlibStreamGet(
    Tcl_ZlibStream zshandle,
    Tcl_Obj *data,
    size_t count)
{
    return TCL_OK;
}

int
Tcl_ZlibDeflate(
    Tcl_Interp *interp,
    int format,
    Tcl_Obj *data,
    int level,
    Tcl_Obj *gzipHeaderDictObj)
{
    if (interp) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("unimplemented", -1));
	Tcl_SetErrorCode(interp, "TCL", "UNIMPLEMENTED", NULL);
    }
    return TCL_ERROR;
}

int
Tcl_ZlibInflate(
    Tcl_Interp *interp,
    int format,
    Tcl_Obj *data,
    size_t bufferSize,
    Tcl_Obj *gzipHeaderDictObj)
{
    if (interp) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("unimplemented", -1));
	Tcl_SetErrorCode(interp, "TCL", "UNIMPLEMENTED", NULL);
    }
    return TCL_ERROR;
}

unsigned int
Tcl_ZlibCRC32(
    unsigned int crc,
    const unsigned char *buf,
    size_t len)
{
    return 0;
}

unsigned int
Tcl_ZlibAdler32(
    unsigned int adler,
    const unsigned char *buf,
    size_t len)
{
    return 0;
}

void
Tcl_ZlibStreamSetCompressionDictionary(
    Tcl_ZlibStream zshandle,
    Tcl_Obj *compressionDictionaryObj)
{
    /* Do nothing. */
}
#endif /* HAVE_ZLIB */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to library/auto.tcl.

1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







# auto.tcl --
#
# utility procs formerly in init.tcl dealing with auto execution of commands
# and can be auto loaded themselves.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1998 Sun Microsystems, Inc.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1998 Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#

# auto_reset --
#
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
41
42
43
44
45
46
47

48
49
50
51
52
53
54
55







-
+







# tcl_findLibrary --
#
#	This is a utility for extensions that searches for a library directory
#	using a canonical searching algorithm. A side effect is to source the
#	initialization script and set a global library variable.
#
# Arguments:
# 	basename	Prefix of the directory name, (e.g., "tk")
#	basename	Prefix of the directory name, (e.g., "tk")
#	version		Version number of the package, (e.g., "8.0")
#	patch		Patchlevel of the package, (e.g., "8.0.3")
#	initScript	Initialization script to source (e.g., tk.tcl)
#	enVarName	environment variable to honor (e.g., TK_LIBRARY)
#	varName		Global variable to set when done (e.g., tk_library)

proc tcl_findLibrary {basename version patch initScript enVarName varName} {
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
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







-
-
-
+
+
+


-
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    } else {
	# Do the canonical search

	# 1. From an environment variable, if it exists.  Placing this first
	#    gives the end-user ultimate control to work-around any bugs, or
	#    to customize.

        if {[info exists env($enVarName)]} {
            lappend dirs $env($enVarName)
        }
	if {[info exists env($enVarName)]} {
	    lappend dirs $env($enVarName)
	}

	catch {
      set found 0
	    set found 0
	    set root [zipfs root]
	    set mountpoint [file join $root lib [string tolower $basename]]
      lappend dirs [file join $root app ${basename}_library]
      lappend dirs [file join $root lib $mountpoint ${basename}_library]
      lappend dirs [file join $root lib $mountpoint]
	    set mountpoint [file join $root lib $basename]
	    lappend dirs [file join $root app ${basename}_library]
	    lappend dirs [file join $root lib ${basename} ${basename}_library]
	    lappend dirs [file join $root lib ${basename}]
	    if {![zipfs exists [file join $root app ${basename}_library]] \
	      && ![zipfs exists $mountpoint]} {
	      set found 0
	      foreach pkgdat [info loaded] {
	        lassign $pkgdat dllfile dllpkg
	        if {[string tolower $dllpkg] ne [string tolower $basename]} continue
	        if {$dllfile eq {}} {
	          # Loaded statically
	          break
	        }
          set found 1
	        zipfs mount $mountpoint $dllfile
	        break
	      }
	      if {!$found} {
  	      set paths {}
  	      lappend paths [file join $root app]
    	    lappend paths [::${basename}::pkgconfig get libdir,runtime]
	        lappend paths [::${basename}::pkgconfig get bindir,runtime]
	        if {[catch {::${basename}::pkgconfig get zipfile,runtime} zipfile]} {
		    && ![zipfs exists $mountpoint]} {
		set found 0
		foreach pkgdat [info loaded] {
		    lassign $pkgdat dllfile dllpkg
		    if {$dllpkg ne $basename} continue
		    if {$dllfile eq {}} {
			# Loaded statically
			break
		    }
		    set found 1
		    zipfs mount $dllfile $mountpoint
		    break
		}
		if {!$found} {
		    set paths {}
		    if {![catch {::${basename}::pkgconfig get libdir,runtime} dir]} {
			lappend paths $dir
		    } else {
			catch {lappend paths [::tcl::pkgconfig get libdir,runtime]}
		    }
		    if {![catch {::${basename}::pkgconfig get bindir,runtime} dir]} {
			lappend paths $dir
		    } else {
			catch {lappend paths [::tcl::pkgconfig get bindir,runtime]}
		    }
		    if {[catch {::${basename}::pkgconfig get dllfile,runtime} dllfile]} {
  	        set zipfile [string tolower \
  	          "lib${basename}_[join [list {*}[split $version .] {*}$patch] _].zip"]
  	      }
  	      lappend paths [file dirname [file join [pwd] [info nameofexecutable]]]
          foreach path $paths {
            set archive [file join $path $zipfile]
            if {![file exists $archive]} continue
            zipfs mount $mountpoint $archive
            if {[zipfs exists [file join $mountpoint ${basename}_library $initScript]]} {
              lappend dirs [file join $mountpoint ${basename}_library]
              set found 1
              break
            } elseif {[zipfs exists [file join $mountpoint $initScript]]} {
              lappend dirs [file join $mountpoint $initScript]
              set found 1
              break
            } else {
              catch {zipfs unmount $archive}
            }
          }
        }
      }
   }
			set dllfile "libtcl9${basename}${version}[info sharedlibextension]"
		    }
		    set dir [file dirname [file join [pwd] [info nameofexecutable]]]
		    lappend paths $dir
		    lappend paths [file join [file dirname $dir] lib]
		    foreach path $paths {
			set archive [file join $path $dllfile]
			if {![file exists $archive]} {
			    continue
			}
			zipfs mount $archive $mountpoint
			if {[zipfs exists [file join $mountpoint ${basename}_library $initScript]]} {
			    lappend dirs [file join $mountpoint ${basename}_library]
			    set found 1
			    break
			} elseif {[zipfs exists [file join $mountpoint $initScript]]} {
			    lappend dirs [file join $mountpoint $initScript]
			    set found 1
			    break
			} else {
			    catch {zipfs unmount $mountpoint}
			}
		    }
		}
	    }
	}

	# 2. In the package script directory registered within the
	#    configuration of the package itself.

	catch {
	    lappend dirs [::${basename}::pkgconfig get scriptdir,runtime]
	}
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
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







-
-
-
-
-
+
+
+
+
+







-
+














-
-
+
+




-
-
-
-
+
+
+
+


-
+







	#
	# ../../library		(From unix/arch directory in build hierarchy)
	# ../../foo1.0.1/library
	#		(From unix directory in parallel build hierarchy)
	# ../../../foo1.0.1/library
	#		(From unix/arch directory in parallel build hierarchy)

        set parentDir [file dirname [file dirname [info nameofexecutable]]]
        set grandParentDir [file dirname $parentDir]
        lappend dirs [file join $parentDir lib $basename$version]
        lappend dirs [file join $grandParentDir lib $basename$version]
        lappend dirs [file join $parentDir library]
	set parentDir [file dirname [file dirname [info nameofexecutable]]]
	set grandParentDir [file dirname $parentDir]
	lappend dirs [file join $parentDir lib $basename$version]
	lappend dirs [file join $grandParentDir lib $basename$version]
	lappend dirs [file join $parentDir library]
	if {0} {
	    lappend dirs [file join $grandParentDir library]
	    lappend dirs [file join $grandParentDir $basename$patch library]
	    lappend dirs [file join [file dirname $grandParentDir] \
			      $basename$patch library]
	}
    }
    # uniquify $dirs in order
    # make $dirs unique, preserving order
    array set seen {}
    foreach i $dirs {
	# Make sure $i is unique under normalization. Avoid repeated [source].
	if {[interp issafe]} {
	    # Safe interps have no [file normalize].
	    set norm $i
	} else {
	    set norm [file normalize $i]
	}
	if {[info exists seen($norm)]} {
	    continue
	}
	set seen($norm) {}

        set the_library $i
        set file [file join $i $initScript]
	set the_library $i
	set file [file join $i $initScript]

	# source everything when in a safe interpreter because we have a
	# source command, but no file exists command

        if {[interp issafe] || [file exists $file]} {
            if {![catch {uplevel #0 [list source $file]} msg opts]} {
                return
            }
	if {[interp issafe] || [file exists $file]} {
	    if {![catch {uplevel #0 [list source $file]} msg opts]} {
		return
	    }
	    append errors "$file: $msg\n"
	    append errors [dict get $opts -errorinfo]\n
        }
	}
    }
    unset -nocomplain the_library
    set msg "Can't find a usable $initScript in the following directories: \n"
    append msg "    $dirs\n\n"
    append msg "$errors\n\n"
    append msg "This probably means that $basename wasn't installed properly.\n"
    error $msg
232
233
234
235
236
237
238
239

240
241
242
243
244
245
246
242
243
244
245
246
247
248

249
250
251
252
253
254
255
256







-
+








# args -	Any number of additional arguments giving the names of files
#		within dir.  If no additional are given auto_mkindex will look
#		for *.tcl.

proc auto_mkindex {dir args} {
    if {[interp issafe]} {
        error "can't generate index within safe interpreter"
	error "can't generate index within safe interpreter"
    }

    set oldDir [pwd]
    cd $dir

    append index "# Tcl autoload index file, version 2.0\n"
    append index "# This file is generated by the \"auto_mkindex\" command\n"
288
289
290
291
292
293
294
295

296
297
298
299
300

301
302
303
304
305
306
307
298
299
300
301
302
303
304

305
306
307
308
309

310
311
312
313
314
315
316
317







-
+




-
+







    if {![llength $args]} {
	set args *.tcl
    }
    foreach file [lsort [glob -- {*}$args]] {
	set f ""
	set error [catch {
	    set f [open $file]
	    fconfigure $f -encoding utf-8 -eofchar \032
	    fconfigure $f -encoding utf-8 -eofchar \x1A
	    while {[gets $f line] >= 0} {
		if {[regexp {^proc[ 	]+([^ 	]*)} $line match procName]} {
		    set procName [lindex [auto_qualify $procName "::"] 0]
		    append index "set [list auto_index($procName)]"
		    append index " \[list source \[file join \$dir [list $file]\]\]\n"
		    append index " \[list source -encoding utf-8 \[file join \$dir [list $file]\]\]\n"
		}
	    }
	    close $f
	} msg opts]
	if {$error} {
	    catch {close $f}
	    cd $oldDir
366
367
368
369
370
371
372
373

374
375
376
377
378
379
380
376
377
378
379
380
381
382

383
384
385
386
387
388
389
390







-
+







	    # interp.  Put it back, but move it out of the way.

	    $parser expose namespace
	    $parser invokehidden rename namespace _%@namespace
	    $parser expose eval
	    $parser invokehidden rename eval _%@eval

	    # Install all the registered psuedo-command implementations
	    # Install all the registered pseudo-command implementations

	    foreach cmd $initCommands {
		eval $cmd
	    }
	}
    }
    proc cleanup {} {
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
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







-
+



















-
+







    variable scriptFile
    variable contextStack
    variable imports

    set scriptFile $file

    set fid [open $file]
    fconfigure $fid -encoding utf-8 -eofchar \032
    fconfigure $fid -encoding utf-8 -eofchar \x1A
    set contents [read $fid]
    close $fid

    # There is one problem with sourcing files into the safe interpreter:
    # references like "$x" will fail since code is not really being executed
    # and variables do not really exist.  To avoid this, we replace all $ with
    # \0 (literally, the null char) later, when getting proc names we will
    # have to reverse this replacement, in case there were any $ in the proc
    # name.  This will cause a problem if somebody actually tries to have a \0
    # in their proc name.  Too bad for them.
    set contents [string map [list \$ \0] $contents]

    set index ""
    set contextStack ""
    set imports ""

    $parser eval $contents

    foreach name $imports {
        catch {$parser eval [list _%@namespace forget $name]}
	catch {$parser eval [list _%@namespace forget $name]}
    }
    return $index
}

# auto_mkindex_parser::hook command
#
# Registers a Tcl command to evaluate when initializing the child interpreter
466
467
468
469
470
471
472
473

474
475

476
477
478
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
476
477
478
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







-
+

-
+











-
+

-
+







-
+

-
+








-
-
+
+











-
-
-
+
+
+

-
+







#
# This procedure allows extensions to register their own commands with the
# auto_mkindex facility.  For example, a package like [incr Tcl] might
# register a "class" command so that class definitions could be added to a
# "tclIndex" file for auto-loading.
#
# Arguments:
#	name 	Name of command recognized in Tcl files.
#	name	Name of command recognized in Tcl files.
#	arglist	Argument list for command.
#	body 	Implementation of command to handle indexing.
#	body	Implementation of command to handle indexing.

proc auto_mkindex_parser::command {name arglist body} {
    hook [list auto_mkindex_parser::commandInit $name $arglist $body]
}

# auto_mkindex_parser::commandInit --
#
# This does the actual work set up by auto_mkindex_parser::command. This is
# called when the interpreter used by the parser is created.
#
# Arguments:
#	name 	Name of command recognized in Tcl files.
#	name	Name of command recognized in Tcl files.
#	arglist	Argument list for command.
#	body 	Implementation of command to handle indexing.
#	body	Implementation of command to handle indexing.

proc auto_mkindex_parser::commandInit {name arglist body} {
    variable parser

    set ns [namespace qualifiers $name]
    set tail [namespace tail $name]
    if {$ns eq ""} {
        set fakeName [namespace current]::_%@fake_$tail
	set fakeName [namespace current]::_%@fake_$tail
    } else {
        set fakeName [namespace current]::[string map {:: _} _%@fake_$name]
	set fakeName [namespace current]::[string map {:: _} _%@fake_$name]
    }
    proc $fakeName $arglist $body

    # YUK!  Tcl won't let us alias fully qualified command names, so we can't
    # handle names like "::itcl::class".  Instead, we have to build procs with
    # the fully qualified names, and have the procs point to the aliases.

    if {[string match *::* $name]} {
        set exportCmd [list _%@namespace export [namespace tail $name]]
        $parser eval [list _%@namespace eval $ns $exportCmd]
	set exportCmd [list _%@namespace export [namespace tail $name]]
	$parser eval [list _%@namespace eval $ns $exportCmd]

	# The following proc definition does not work if you want to tolerate
	# space or something else diabolical in the procedure name, (i.e.,
	# space in $alias). The following does not work:
	#   "_%@eval {$alias} \$args"
	# because $alias gets concat'ed to $args.  The following does not work
	# because $cmd is somehow undefined
	#   "set cmd {$alias} \; _%@eval {\$cmd} \$args"
	# A gold star to someone that can make test autoMkindex-3.3 work
	# properly

        set alias [namespace tail $fakeName]
        $parser invokehidden proc $name {args} "_%@eval {$alias} \$args"
        $parser alias $alias $fakeName
	set alias [namespace tail $fakeName]
	$parser invokehidden proc $name {args} "_%@eval {$alias} \$args"
	$parser alias $alias $fakeName
    } else {
        $parser alias $name $fakeName
	$parser alias $name $fakeName
    }
    return
}

# auto_mkindex_parser::fullname --
#
# Used by commands like "proc" within the auto_mkindex parser.  Returns the
540
541
542
543
544
545
546
547
548
549
550
551
552






553
554
555
556

557
558

559
560
561
562
563
564
565
550
551
552
553
554
555
556






557
558
559
560
561
562
563
564
565

566
567

568
569
570
571
572
573
574
575







-
-
-
-
-
-
+
+
+
+
+
+



-
+

-
+







# Arguments:
# name -		Name that is being added to index.

proc auto_mkindex_parser::fullname {name} {
    variable contextStack

    if {![string match ::* $name]} {
        foreach ns $contextStack {
            set name "${ns}::$name"
            if {[string match ::* $name]} {
                break
            }
        }
	foreach ns $contextStack {
	    set name "${ns}::$name"
	    if {[string match ::* $name]} {
		break
	    }
	}
    }

    if {[namespace qualifiers $name] eq ""} {
        set name [namespace tail $name]
	set name [namespace tail $name]
    } elseif {![string match ::* $name]} {
        set name "::$name"
	set name "::$name"
    }

    # Earlier, mkindex replaced all $'s with \0.  Now, we have to reverse that
    # replacement.
    return [string map [list \0 \$] $name]
}

580
581
582
583
584
585
586
587

588
589
590
591
592
593
594
590
591
592
593
594
595
596

597
598
599
600
601
602
603
604







-
+







    # the file name that we know about (which will be a proper list, and so
    # correctly quoted).

    set name [string range [list \}[fullname $name]] 2 end]
    set filenameParts [file split $scriptFile]

    append index [format \
	    {set auto_index(%s) [list source [file join $dir %s]]%s} \
	    {set auto_index(%s) [list source -encoding utf-8 [file join $dir %s]]%s} \
	    $name $filenameParts \n]
    return
}

if {[llength $::auto_mkindex_parser::initCommands]} {
    return
}
619
620
621
622
623
624
625
626

627
628
629
630
631
632
633
629
630
631
632
633
634
635

636
637
638
639
640
641
642
643







-
+







    } on ok {} {
	if {[namespace which -command tbcload::bcproc] eq ""} {
	    auto_load tbcload::bcproc
	}
	load {} tbcload $auto_mkindex_parser::parser

	# AUTO MKINDEX:  tbcload::bcproc name arglist body
	# Adds an entry to the auto index list for the given pre-compiled
	# Adds an entry to the auto index list for the given precompiled
	# procedure name.

	auto_mkindex_parser::commandInit tbcload::bcproc {name args} {
	    indexEntry $name
	}
    }
}
641
642
643
644
645
646
647
648
649
650



651
652
653


654
655

656
657
658
659
660
661
662
663
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
651
652
653
654
655
656
657



658
659
660
661


662
663
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







-
-
-
+
+
+

-
-
+
+

-
+

-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+












-
+







# for any commands contained in a namespace that affect the index.  For
# example, a script may say "itcl::class ...", or it may import "itcl::*" and
# then say "class ...".  This procedure does the import operation, but keeps
# track of imported patterns so we can remove the imports later.

auto_mkindex_parser::command namespace {op args} {
    switch -- $op {
        eval {
            variable parser
            variable contextStack
	eval {
	    variable parser
	    variable contextStack

            set name [lindex $args 0]
            set args [lrange $args 1 end]
	    set name [lindex $args 0]
	    set args [lrange $args 1 end]

            set contextStack [linsert $contextStack 0 $name]
	    set contextStack [linsert $contextStack 0 $name]
	    $parser eval [list _%@namespace eval $name] $args
            set contextStack [lrange $contextStack 1 end]
        }
        import {
            variable parser
            variable imports
            foreach pattern $args {
                if {$pattern ne "-force"} {
                    lappend imports $pattern
                }
            }
            catch {$parser eval "_%@namespace import $args"}
        }
	    set contextStack [lrange $contextStack 1 end]
	}
	import {
	    variable parser
	    variable imports
	    foreach pattern $args {
		if {$pattern ne "-force"} {
		    lappend imports $pattern
		}
	    }
	    catch {$parser eval "_%@namespace import $args"}
	}
	ensemble {
	    variable parser
	    variable contextStack
	    if {[lindex $args 0] eq "create"} {
		set name ::[join [lreverse $contextStack] ::]
		catch {
		    set name [dict get [lrange $args 1 end] -command]
		    if {![string match ::* $name]} {
			set name ::[join [lreverse $contextStack] ::]$name
		    }
		    regsub -all ::+ $name :: name
		}
		# create artifical proc to force an entry in the tclIndex
		# create artificial proc to force an entry in the tclIndex
		$parser eval [list ::proc $name {} {}]
	    }
	}
    }
}

# AUTO MKINDEX:  oo::class create name ?definition?

Changes to library/clock.tcl.

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
30
31
32
33
34

35
36
37
38
39
40
41
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
30
31
32
33
34











-
+
+





-
+
-

-
-
+
-
-
-
-
-
-





-
+







#----------------------------------------------------------------------
#
# clock.tcl --
#
#	This file implements the portions of the [clock] ensemble that are
#	coded in Tcl.  Refer to the users' manual to see the description of
#	the [clock] command and its subcommands.
#
#
#----------------------------------------------------------------------
#
# Copyright (c) 2004,2005,2006,2007 by Kevin B. Kenny
# Copyright © 2004-2007 Kevin B. Kenny
# Copyright © 2015 Sergey G. Brester aka sebres.
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
#----------------------------------------------------------------------

# We must have message catalogs that support the root locale, and we need
# msgcat 1.7 features are used.
# access to the Registry on Windows systems.

uplevel \#0 {
    package require msgcat 1.6
package require msgcat 1.7
    if { $::tcl_platform(platform) eq {windows} } {
	if { [catch { package require registry 1.1 }] } {
	    namespace eval ::tcl::clock [list variable NoRegistry {}]
	}
    }
}

# Put the library directory into the namespace for the ensemble so that the
# library code can find message catalogs and time zone definition files.

namespace eval ::tcl::clock \
    [list variable LibDir [file dirname [info script]]]
    [list variable LibDir [info library]]

#----------------------------------------------------------------------
#
# clock --
#
#	Manipulate times.
#
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
47
48
49
50
51
52
53

54

55
56
57
58
59
60
61







-

-







    namespace export milliseconds
    namespace export scan
    namespace export seconds
    namespace export add

    # Import the message catalog commands that we use.

    namespace import ::msgcat::mcload
    namespace import ::msgcat::mclocale
    namespace import ::msgcat::mc
    namespace import ::msgcat::mcpackagelocale

}

#----------------------------------------------------------------------
#
# ::tcl::clock::Initialize --
145
146
147
148
149
150
151
152
153
154



155
156
157
158
159
160
161
136
137
138
139
140
141
142



143
144
145
146
147
148
149
150
151
152







-
-
-
+
+
+







	}
	LOCALE_TIME_FORMAT {%H:%M:%S}
	LOCALE_YEAR_FORMAT {%EC%Ey}
	MONTHS_ABBREV		{
	    Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
	}
	MONTHS_FULL		{
	    	January		February	March
	    	April		May		June
	    	July		August		September
		January		February	March
		April		May		June
		July		August		September
		October		November	December
	}
	PM {pm}
	TIME_FORMAT {%H:%M:%S}
	TIME_FORMAT_12 {%I:%M:%S %P}
	TIME_FORMAT_24 {%H:%M}
	TIME_FORMAT_24_SECS {%H:%M:%S}
219
220
221
222
223
224
225
226

227
228
229
230
231
232
233
210
211
212
213
214
215
216

217
218
219
220
221
222
223
224







-
+








    ::msgcat::mcset sv GREGORIAN_CHANGE_DATE 2361390

    # Russia

    ::msgcat::mcset ru GREGORIAN_CHANGE_DATE 2421639

    # Romania (Transylvania changed earler - perhaps de_RO should show the
    # Romania (Transylvania changed earlier - perhaps de_RO should show the
    # earlier date?)

    ::msgcat::mcset ro GREGORIAN_CHANGE_DATE 2422063

    # Greece

    ::msgcat::mcset el GREGORIAN_CHANGE_DATE 2423480
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
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







+
+
+
+
+
+
+







-
+















-
-
-
-
-
+
+
+
+
+



-
+



-
+

-
-
+
+




-
-
+
+







-
-
-
+
+
+

-
+


-
-
+
+

-
+




-
+







    variable MINWIDE -9223372036854775808
    variable MAXWIDE 9223372036854775807

    # Day before Leap Day

    variable FEB_28	       58

    # Default configuration

    ::tcl::unsupported::clock::configure -current-locale  [mclocale]
    #::tcl::unsupported::clock::configure -default-locale  C
    #::tcl::unsupported::clock::configure -year-century    2000 \
    #          -century-switch  38

    # Translation table to map Windows TZI onto cities, so that the Olson
    # rules can apply.  In some cases the mapping is ambiguous, so it's wise
    # to specify $::env(TCL_TZ) rather than simply depending on the system
    # time zone.

    # The keys are long lists of values obtained from the time zone
    # information in the Registry.  In order, the list elements are:
    # 	Bias StandardBias DaylightBias
    #   Bias StandardBias DaylightBias
    #   StandardDate.wYear StandardDate.wMonth StandardDate.wDayOfWeek
    #   StandardDate.wDay StandardDate.wHour StandardDate.wMinute
    #   StandardDate.wSecond StandardDate.wMilliseconds
    #   DaylightDate.wYear DaylightDate.wMonth DaylightDate.wDayOfWeek
    #   DaylightDate.wDay DaylightDate.wHour DaylightDate.wMinute
    #   DaylightDate.wSecond DaylightDate.wMilliseconds
    # The values are the names of time zones where those rules apply.  There
    # is considerable ambiguity in certain zones; an attempt has been made to
    # make a reasonable guess, but this table needs to be taken with a grain
    # of salt.

    variable WinZoneInfo [dict create {*}{
	{-43200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}  :Pacific/Kwajalein
	{-39600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}	 :Pacific/Midway
	{-36000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}  :Pacific/Honolulu
        {-32400 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Anchorage
        {-28800 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Los_Angeles
        {-28800 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Tijuana
        {-25200 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Denver
        {-25200 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Chihuahua
	{-32400 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Anchorage
	{-28800 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Los_Angeles
	{-28800 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Tijuana
	{-25200 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Denver
	{-25200 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Chihuahua
	{-25200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}  :America/Phoenix
	{-21600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}  :America/Regina
	{-21600 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Chicago
        {-21600 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Mexico_City
	{-21600 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Mexico_City
	{-18000 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/New_York
	{-18000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}  :America/Indianapolis
	{-14400 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}  :America/Caracas
        {-14400 0 3600 0 3 6 2 23 59 59 999 0 10 6 2 23 59 59 999}
	{-14400 0 3600 0 3 6 2 23 59 59 999 0 10 6 2 23 59 59 999}
							 :America/Santiago
        {-14400 0 3600 0 2 0 5 2 0 0 0 0 11 0 1 2 0 0 0} :America/Manaus
        {-14400 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Halifax
	{-14400 0 3600 0 2 0 5 2 0 0 0 0 11 0 1 2 0 0 0} :America/Manaus
	{-14400 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Halifax
	{-12600 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/St_Johns
	{-10800 0 3600 0 2 0 2 2 0 0 0 0 10 0 3 2 0 0 0} :America/Sao_Paulo
	{-10800 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Godthab
	{-10800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}  :America/Buenos_Aires
        {-10800 0 3600 0 2 0 5 2 0 0 0 0 11 0 1 2 0 0 0} :America/Bahia
        {-10800 0 3600 0 3 0 2 2 0 0 0 0 10 0 1 2 0 0 0} :America/Montevideo
	{-10800 0 3600 0 2 0 5 2 0 0 0 0 11 0 1 2 0 0 0} :America/Bahia
	{-10800 0 3600 0 3 0 2 2 0 0 0 0 10 0 1 2 0 0 0} :America/Montevideo
	{-7200 0 3600 0 9 0 5 2 0 0 0 0 3 0 5 2 0 0 0}   :America/Noronha
	{-3600 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0}  :Atlantic/Azores
	{-3600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}   :Atlantic/Cape_Verde
	{0 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}       :UTC
	{0 0 3600 0 10 0 5 2 0 0 0 0 3 0 5 1 0 0 0}      :Europe/London
	{3600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}    :Africa/Kinshasa
	{3600 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0}   :CET
        {7200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}    :Africa/Harare
        {7200 0 3600 0 9 4 5 23 59 59 0 0 4 4 5 23 59 59 0}
			      				 :Africa/Cairo
	{7200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}    :Africa/Harare
	{7200 0 3600 0 9 4 5 23 59 59 0 0 4 4 5 23 59 59 0}
							 :Africa/Cairo
	{7200 0 3600 0 10 0 5 4 0 0 0 0 3 0 5 3 0 0 0}   :Europe/Helsinki
        {7200 0 3600 0 9 0 3 2 0 0 0 0 3 5 5 2 0 0 0}    :Asia/Jerusalem
	{7200 0 3600 0 9 0 3 2 0 0 0 0 3 5 5 2 0 0 0}    :Asia/Jerusalem
	{7200 0 3600 0 9 0 5 1 0 0 0 0 3 0 5 0 0 0 0}    :Europe/Bucharest
	{7200 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0}   :Europe/Athens
        {7200 0 3600 0 9 5 5 1 0 0 0 0 3 4 5 0 0 0 0}    :Asia/Amman
        {7200 0 3600 0 10 6 5 23 59 59 999 0 3 0 5 0 0 0 0}
	{7200 0 3600 0 9 5 5 1 0 0 0 0 3 4 5 0 0 0 0}    :Asia/Amman
	{7200 0 3600 0 10 6 5 23 59 59 999 0 3 0 5 0 0 0 0}
							 :Asia/Beirut
        {7200 0 -3600 0 4 0 1 2 0 0 0 0 9 0 1 2 0 0 0}   :Africa/Windhoek
	{7200 0 -3600 0 4 0 1 2 0 0 0 0 9 0 1 2 0 0 0}   :Africa/Windhoek
	{10800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}   :Asia/Riyadh
	{10800 0 3600 0 10 0 1 4 0 0 0 0 4 0 1 3 0 0 0}  :Asia/Baghdad
	{10800 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0}  :Europe/Moscow
	{12600 0 3600 0 9 2 4 2 0 0 0 0 3 0 1 2 0 0 0}   :Asia/Tehran
        {14400 0 3600 0 10 0 5 5 0 0 0 0 3 0 5 4 0 0 0}  :Asia/Baku
	{14400 0 3600 0 10 0 5 5 0 0 0 0 3 0 5 4 0 0 0}  :Asia/Baku
	{14400 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}   :Asia/Muscat
	{14400 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0}  :Asia/Tbilisi
	{16200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}   :Asia/Kabul
	{18000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}   :Asia/Karachi
	{18000 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0}  :Asia/Yekaterinburg
	{19800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}   :Asia/Calcutta
	{20700 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}   :Asia/Katmandu
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
377
378
379
380
381
382
383


















































































































































384
385
386
387
388
389
390







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	{36000 0 3600 0 3 0 5 3 0 0 0 0 10 0 5 2 0 0 0}  :Australia/Sydney
	{39600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}   :Pacific/Noumea
	{43200 0 3600 0 3 0 3 3 0 0 0 0 10 0 1 2 0 0 0}  :Pacific/Auckland
	{43200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}   :Pacific/Fiji
	{46800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}   :Pacific/Tongatapu
    }]

    # Groups of fields that specify the date, priorities, and code bursts that
    # determine Julian Day Number given those groups.  The code in [clock
    # scan] will choose the highest priority (lowest numbered) set of fields
    # that determines the date.

    variable DateParseActions {

	{ seconds } 0 {}

	{ julianDay } 1 {}

	{ era century yearOfCentury month dayOfMonth } 2 {
	    dict set date year [expr { 100 * [dict get $date century]
				       + [dict get $date yearOfCentury] }]
	    set date [GetJulianDayFromEraYearMonthDay $date[set date {}] \
			  $changeover]
	}
	{ era century yearOfCentury dayOfYear } 2 {
	    dict set date year [expr { 100 * [dict get $date century]
				       + [dict get $date yearOfCentury] }]
	    set date [GetJulianDayFromEraYearDay $date[set date {}] \
			  $changeover]
	}

	{ century yearOfCentury month dayOfMonth } 3 {
	    dict set date era CE
	    dict set date year [expr { 100 * [dict get $date century]
				       + [dict get $date yearOfCentury] }]
	    set date [GetJulianDayFromEraYearMonthDay $date[set date {}] \
			  $changeover]
	}
	{ century yearOfCentury dayOfYear } 3 {
	    dict set date era CE
	    dict set date year [expr { 100 * [dict get $date century]
				       + [dict get $date yearOfCentury] }]
	    set date [GetJulianDayFromEraYearDay $date[set date {}] \
			  $changeover]
	}
	{ iso8601Century iso8601YearOfCentury iso8601Week dayOfWeek } 3 {
	    dict set date era CE
	    dict set date iso8601Year \
		[expr { 100 * [dict get $date iso8601Century]
			+ [dict get $date iso8601YearOfCentury] }]
	    set date [GetJulianDayFromEraYearWeekDay $date[set date {}] \
			 $changeover]
	}

	{ yearOfCentury month dayOfMonth } 4 {
	    set date [InterpretTwoDigitYear $date[set date {}] $baseTime]
	    dict set date era CE
	    set date [GetJulianDayFromEraYearMonthDay $date[set date {}] \
			  $changeover]
	}
	{ yearOfCentury dayOfYear } 4 {
	    set date [InterpretTwoDigitYear $date[set date {}] $baseTime]
	    dict set date era CE
	    set date [GetJulianDayFromEraYearDay $date[set date {}] \
			  $changeover]
	}
	{ iso8601YearOfCentury iso8601Week dayOfWeek } 4 {
	    set date [InterpretTwoDigitYear \
			  $date[set date {}] $baseTime \
			  iso8601YearOfCentury iso8601Year]
	    dict set date era CE
	    set date [GetJulianDayFromEraYearWeekDay $date[set date {}] \
			 $changeover]
	}

	{ month dayOfMonth } 5 {
	    set date [AssignBaseYear $date[set date {}] \
			  $baseTime $timeZone $changeover]
	    set date [GetJulianDayFromEraYearMonthDay $date[set date {}] \
			  $changeover]
	}
	{ dayOfYear } 5 {
	    set date [AssignBaseYear $date[set date {}] \
			  $baseTime $timeZone $changeover]
	    set date [GetJulianDayFromEraYearDay $date[set date {}] \
			 $changeover]
	}
	{ iso8601Week dayOfWeek } 5 {
	    set date [AssignBaseIso8601Year $date[set date {}] \
			  $baseTime $timeZone $changeover]
	    set date [GetJulianDayFromEraYearWeekDay $date[set date {}] \
			 $changeover]
	}

	{ dayOfMonth } 6 {
	    set date [AssignBaseMonth $date[set date {}] \
			  $baseTime $timeZone $changeover]
	    set date [GetJulianDayFromEraYearMonthDay $date[set date {}] \
			  $changeover]
	}

	{ dayOfWeek } 7 {
	    set date [AssignBaseWeek $date[set date {}] \
			  $baseTime $timeZone $changeover]
	    set date [GetJulianDayFromEraYearWeekDay $date[set date {}] \
			 $changeover]
	}

	{} 8 {
	    set date [AssignBaseJulianDay $date[set date {}] \
			  $baseTime $timeZone $changeover]
	}
    }

    # Groups of fields that specify time of day, priorities, and code that
    # processes them

    variable TimeParseActions {

	seconds 1 {}

	{ hourAMPM minute second amPmIndicator } 2 {
	    dict set date secondOfDay [InterpretHMSP $date]
	}
	{ hour minute second } 2 {
	    dict set date secondOfDay [InterpretHMS $date]
	}

	{ hourAMPM minute amPmIndicator } 3 {
	    dict set date second 0
	    dict set date secondOfDay [InterpretHMSP $date]
	}
	{ hour minute } 3 {
	    dict set date second 0
	    dict set date secondOfDay [InterpretHMS $date]
	}

	{ hourAMPM amPmIndicator } 4 {
	    dict set date minute 0
	    dict set date second 0
	    dict set date secondOfDay [InterpretHMSP $date]
	}
	{ hour } 4 {
	    dict set date minute 0
	    dict set date second 0
	    dict set date secondOfDay [InterpretHMS $date]
	}

	{ } 5 {
	    dict set date secondOfDay 0
	}
    }

    # Legacy time zones, used primarily for parsing RFC822 dates.

    variable LegacyTimeZone [dict create \
	gmt	+0000 \
	ut	+0000 \
	utc	+0000 \
	bst	+0100 \
550
551
552
553
554
555
556


557
558
559
560
561
562
563
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417







+
+







	cdt	-0500 \
	mst	-0700 \
	mdt	-0600 \
	pst	-0800 \
	pdt	-0700 \
	yst	-0900 \
	ydt	-0800 \
	akst	-0900 \
	akdt	-0800 \
	hst	-1000 \
	hdt	-0900 \
	cat	-1000 \
	ahst	-1000 \
	nt	-1100 \
	idlw	-1200 \
	cet	+0100 \
580
581
582
583
584
585
586
587
588


589
590
591
592
593
594
595
434
435
436
437
438
439
440


441
442
443
444
445
446
447
448
449







-
-
+
+







	wast	+0700 \
	wadt	+0800 \
	jt	+0730 \
	cct	+0800 \
	jst	+0900 \
	kst     +0900 \
	cast	+0930 \
        jdt     +1000 \
        kdt     +1000 \
	jdt     +1000 \
	kdt     +1000 \
	cadt	+1030 \
	east	+1000 \
	eadt	+1030 \
	gst	+1000 \
	nzt	+1200 \
	nzst	+1200 \
	nzdt	+1300 \
619
620
621
622
623
624
625
626
627


628
629
630
631
632
633
634
635
636
637


638
639

640
641
642
643
644
645
646
647



648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832

833
834
835
836
837

838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853






854
855
856
857
858
859


860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927

928
929
930
931
932
933
934
935
936
937
938
939
940

941
942

943
944
945
946
947
948



949
950
951



952
953
954


955
956

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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145

1146
1147

1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159

1160
1161
1162
1163
1164

1165
1166

1167
1168
1169

1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184

1185
1186

1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204

1205
1206

1207
1208

1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757

1758
1759
1760
1761
1762
1763

1764
1765
1766
1767
1768
1769
1770
1771
1772
1773


1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793

1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806

1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817

1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832



1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843

1844
1845
1846
1847

1848
1849
1850


1851
1852

1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983

1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027

2028
2029
2030

2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119

2120
2121
2122

2123
2124
2125
2126
2127

2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148

2149
2150
2151
2152

2153
2154

2155
2156
2157
2158
2159

2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285

2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306

2307
2308
2309


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
473
474
475
476
477
478
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
558
559
560
561
562



563







564
565
566
567
568
569
570
571
572






573














574

























575






576










577
578




















579













580











581















582
583
584











585




586



587
588


589



































































































































590


























591
592
















593



594



















595
596
597








598



599
600
601

602



603
604
605
606
607
608

609





610



611


612


613
































614



615





616





















617




618


619





620
























621
622



623






624



625








































626
627



628










629




630
631































632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652

653



654
655


656















657
658
659
660
661
662
663
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







-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+

-
+





-
-
-
+
+
+




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
-
-
+
-
-
-
+
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
+
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-

-
-
-
+


-
+
-
-
-






-
+
-
-
-
-
-
+
-
-
-
+
-
-
+
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-

-
-
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+




















-
+
-
-
-
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
-
+
-
-

+
-
+
-







	x	-1100 \
	y	-1200 \
	z	+0000 \
    ]

    # Caches

    variable LocaleNumeralCache {};	# Dictionary whose keys are locale
					# names and whose values are pairs
    variable LocFmtMap [dict create];	# Dictionary with localized format maps

					# comprising regexes matching numerals
					# in the given locales and dictionaries
					# mapping the numerals to their numeric
					# values.
    # variable CachedSystemTimeZone;    # If 'CachedSystemTimeZone' exists,
					# it contains the value of the
					# system time zone, as determined from
					# the environment.
    variable TimeZoneBad {};	        # Dictionary whose keys are time zone
    					# names and whose values are 1 if
    variable TimeZoneBad [dict create]; # Dictionary whose keys are time zone
					# names and whose values are 1 if
					# the time zone is unknown and 0
    					# if it is known.
					# if it is known.
    variable TZData;			# Array whose keys are time zone names
					# and whose values are lists of quads
					# comprising start time, UTC offset,
					# Daylight Saving Time indicator, and
					# time zone abbreviation.
    variable FormatProc;		# Array mapping format group
					# and locale to the name of a procedure
					# that renders the given format

    variable mcLocales	 [dict create];	# Dictionary with loaded locales
    variable mcMergedCat [dict create];	# Dictionary with merged locale catalogs
}
::tcl::clock::Initialize

#----------------------------------------------------------------------
#
# clock format --
#
#	Formats a count of seconds since the Posix Epoch as a time of day.
#
# The 'clock format' command formats times of day for output.  Refer to the
# user documentation to see what it does.
#
#----------------------------------------------------------------------

proc ::tcl::clock::format { args } {

    variable FormatProc
    variable TZData

    lassign [ParseFormatArgs {*}$args] format locale timezone
    set locale [string tolower $locale]
    set clockval [lindex $args 0]

    # Get the data for time changes in the given zone

    if {$timezone eq ""} {
	set timezone [GetSystemTimeZone]
    }
    if {![info exists TZData($timezone)]} {
	if {[catch {SetupTimeZone $timezone} retval opts]} {
	    dict unset opts -errorinfo
	    return -options $opts $retval
	}
    }

    # Build a procedure to format the result. Cache the built procedure's name
    # in the 'FormatProc' array to avoid losing its internal representation,
    # which contains the name resolution.

    set procName formatproc'$format'$locale
    set procName [namespace current]::[string map {: {\:} \\ {\\}} $procName]
    if {[info exists FormatProc($procName)]} {
	set procName $FormatProc($procName)
    } else {
	set FormatProc($procName) \
	    [ParseClockFormatFormat $procName $format $locale]
    }

    return [$procName $clockval $timezone]

}

#----------------------------------------------------------------------
#
# ParseClockFormatFormat --
#
#	Builds and caches a procedure that formats a time value.
#
# Parameters:
#	format -- Format string to use
#	locale -- Locale in which the format string is to be interpreted
#
# Results:
#	Returns the name of the newly-built procedure.
#
#----------------------------------------------------------------------

proc ::tcl::clock::ParseClockFormatFormat {procName format locale} {

    if {[namespace which $procName] ne {}} {
	return $procName
    }

    # Map away the locale-dependent composite format groups

    EnterLocale $locale

    # Change locale if a fresh locale has been given on the command line.

    try {
	return [ParseClockFormatFormat2 $format $locale $procName]
    } trap CLOCK {result opts} {
	dict unset opts -errorinfo
	return -options $opts $result
    }
}

proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
    set didLocaleEra 0
    set didLocaleNumerals 0
    set preFormatCode \
	[string map [list @GREGORIAN_CHANGE_DATE@ \
				       [mc GREGORIAN_CHANGE_DATE]] \
	     {
		 variable TZData
		 set date [GetDateFields $clockval \
			       $TZData($timezone) \
			       @GREGORIAN_CHANGE_DATE@]
	     }]
    set formatString {}
    set substituents {}
    set state {}

    set format [LocalizeFormat $locale $format]

    foreach char [split $format {}] {
	switch -exact -- $state {
	    {} {
		if { [string equal % $char] } {
		    set state percent
		} else {
		    append formatString $char
		}
	    }
	    percent {			# Character following a '%' character
		set state {}
		switch -exact -- $char {
		    % {			# A literal character, '%'
			append formatString %%
		    }
		    a {			# Day of week, abbreviated
			append formatString %s
			append substituents \
			    [string map \
				 [list @DAYS_OF_WEEK_ABBREV@ \
				      [list [mc DAYS_OF_WEEK_ABBREV]]] \
				 { [lindex @DAYS_OF_WEEK_ABBREV@ \
					[expr {[dict get $date dayOfWeek] \
						   % 7}]]}]
		    }
		    A {			# Day of week, spelt out.
			append formatString %s
			append substituents \
			    [string map \
				 [list @DAYS_OF_WEEK_FULL@ \
				      [list [mc DAYS_OF_WEEK_FULL]]] \
				 { [lindex @DAYS_OF_WEEK_FULL@ \
					[expr {[dict get $date dayOfWeek] \
						   % 7}]]}]
		    }
		    b - h {		# Name of month, abbreviated.
			append formatString %s
			append substituents \
			    [string map \
				 [list @MONTHS_ABBREV@ \
				      [list [mc MONTHS_ABBREV]]] \
				 { [lindex @MONTHS_ABBREV@ \
					[expr {[dict get $date month]-1}]]}]
		    }
		    B {			# Name of month, spelt out
			append formatString %s
			append substituents \
			    [string map \
				 [list @MONTHS_FULL@ \
				      [list [mc MONTHS_FULL]]] \
				 { [lindex @MONTHS_FULL@ \
					[expr {[dict get $date month]-1}]]}]
		    }
		    C {			# Century number
			append formatString %02d
			append substituents \
			    { [expr {[dict get $date year] / 100}]}
		    }
		    d {			# Day of month, with leading zero
			append formatString %02d
			append substituents { [dict get $date dayOfMonth]}
		    }
		    e {			# Day of month, without leading zero
			append formatString %2d
			append substituents { [dict get $date dayOfMonth]}
		    }
		    E {			# Format group in a locale-dependent
					# alternative era
			set state percentE
			if {!$didLocaleEra} {
			    append preFormatCode \
				[string map \
				     [list @LOCALE_ERAS@ \
					  [list [mc LOCALE_ERAS]]] \
				     {
					 set date [GetLocaleEra \
						       $date[set date {}] \
						       @LOCALE_ERAS@]}] \n
			    set didLocaleEra 1
			}

			if {!$didLocaleNumerals} {
			    append preFormatCode \
				[list set localeNumerals \
				     [mc LOCALE_NUMERALS]] \n
			    set didLocaleNumerals 1
# mcget --
			}
		    }
		    g {			# Two-digit year relative to ISO8601
					# week number
			append formatString %02d
			append substituents \
			    { [expr { [dict get $date iso8601Year] % 100 }]}
		    }
		    G {			# Four-digit year relative to ISO8601
					# week number
			append formatString %02d
			append substituents { [dict get $date iso8601Year]}
		    }
		    H {			# Hour in the 24-hour day, leading zero
			append formatString %02d
			append substituents \
#
#	Return the merged translation catalog for the ::tcl::clock namespace
#	Searching of catalog is similar to "msgcat::mc".
#
#	Contrary to "msgcat::mc" may additionally load a package catalog
#	on demand.
			    { [expr { [dict get $date localSeconds] \
					  / 3600 % 24}]}
		    }
		    I {			# Hour AM/PM, with leading zero
			append formatString %02d
			append substituents \
#
# Arguments:
			    { [expr { ( ( ( [dict get $date localSeconds] \
					    % 86400 ) \
					  + 86400 \
					  - 3600 ) \
					/ 3600 ) \
				      % 12 + 1 }] }
		    }
		    j {			# Day of year (001-366)
			append formatString %03d
			append substituents { [dict get $date dayOfYear]}
		    }
		    J {			# Julian Day Number
			append formatString %07ld
			append substituents { [dict get $date julianDay]}
		    }
		    k {			# Hour (0-23), no leading zero
			append formatString %2d
			append substituents \
			    { [expr { [dict get $date localSeconds]
				      / 3600
				      % 24 }]}
		    }
		    l {			# Hour (12-11), no leading zero
			append formatString %2d
			append substituents \
			    { [expr { ( ( ( [dict get $date localSeconds]
					   % 86400 )
					 + 86400
					 - 3600 )
				       / 3600 )
				     % 12 + 1 }]}
		    }
		    m {			# Month number, leading zero
			append formatString %02d
			append substituents { [dict get $date month]}
		    }
		    M {			# Minute of the hour, leading zero
			append formatString %02d
			append substituents \
			    { [expr { [dict get $date localSeconds]
				      / 60
				      % 60 }]}
		    }
		    n {			# A literal newline
			append formatString \n
		    }
		    N {			# Month number, no leading zero
			append formatString %2d
			append substituents { [dict get $date month]}
		    }
		    O {			# A format group in the locale's
					# alternative numerals
			set state percentO
			if {!$didLocaleNumerals} {
			    append preFormatCode \
				[list set localeNumerals \
				     [mc LOCALE_NUMERALS]] \n
			    set didLocaleNumerals 1
			}
		    }
		    p {			# Localized 'AM' or 'PM' indicator
					# converted to uppercase
			append formatString %s
			append preFormatCode \
			    [list set AM [string toupper [mc AM]]] \n \
			    [list set PM [string toupper [mc PM]]] \n
			append substituents \
			    { [expr {(([dict get $date localSeconds]
#	loc	The locale used for translation.
				       % 86400) < 43200) ?
				     $AM : $PM}]}
		    }
		    P {			# Localized 'AM' or 'PM' indicator
			append formatString %s
			append preFormatCode \
			    [list set am [mc AM]] \n \
			    [list set pm [mc PM]] \n
			append substituents \
			    { [expr {(([dict get $date localSeconds]
				       % 86400) < 43200) ?
				     $am : $pm}]}

#
		    }
		    Q {			# Hi, Jeff!
# Results:
			append formatString %s
			append substituents { [FormatStarDate $date]}
		    }
		    s {			# Seconds from the Posix Epoch
			append formatString %s
			append substituents { [dict get $date seconds]}
#	Returns the dictionary object as whole catalog of the package/locale.
#
proc ::tcl::clock::mcget {loc} {
		    }
		    S {			# Second of the minute, with
			# leading zero
    variable mcMergedCat
    switch -- $loc system {
	set loc [GetSystemLocale]
			append formatString %02d
			append substituents \
			    { [expr { [dict get $date localSeconds]
    } current {
	set loc [mclocale]
				      % 60 }]}
		    }
    }
		    t {			# A literal tab character
			append formatString \t
		    }
    if {$loc ne {}} {
		    u {			# Day of the week (1-Monday, 7-Sunday)
			append formatString %1d
	set loc [string tolower $loc]
			append substituents { [dict get $date dayOfWeek]}
		    }
    }
		    U {			# Week of the year (00-53). The
					# first Sunday of the year is the
					# first day of week 01
			append formatString %02d
			append preFormatCode {
			    set dow [dict get $date dayOfWeek]
			    if { $dow == 7 } {
				set dow 0
			    }
			    incr dow
			    set UweekNumber \
				[expr { ( [dict get $date dayOfYear]
					  - $dow + 7 )
					/ 7 }]
			}
			append substituents { $UweekNumber}
		    }
		    V {			# The ISO8601 week number
			append formatString %02d
			append substituents { [dict get $date iso8601Week]}
		    }
		    w {			# Day of the week (0-Sunday,
					# 6-Saturday)
			append formatString %1d
			append substituents \
			    { [expr { [dict get $date dayOfWeek] % 7 }]}
		    }
		    W {			# Week of the year (00-53). The first
					# Monday of the year is the first day
					# of week 01.
			append preFormatCode {
			    set WweekNumber \
				[expr { ( [dict get $date dayOfYear]
					  - [dict get $date dayOfWeek]
					  + 7 )
					/ 7 }]
			}
			append formatString %02d
			append substituents { $WweekNumber}
		    }
		    y {			# The two-digit year of the century
			append formatString %02d
			append substituents \
			    { [expr { [dict get $date year] % 100 }]}
		    }

		    Y {			# The four-digit year
			append formatString %04d
			append substituents { [dict get $date year]}
		    }
		    z {			# The time zone as hours and minutes
					# east (+) or west (-) of Greenwich
			append formatString %s
			append substituents { [FormatNumericTimeZone \
						   [dict get $date tzOffset]]}
		    }
		    Z {			# The name of the time zone
			append formatString %s
			append substituents { [dict get $date tzName]}
		    }
		    % {			# A literal percent character
			append formatString %%
		    }
		    default {		# An unknown escape sequence
			append formatString %% $char
		    }
		}
	    }
	    percentE {			# Character following %E
		set state {}
		switch -exact -- $char {
		    E {
			append formatString %s
			append substituents { } \
			    [string map \
				 [list @BCE@ [list [mc BCE]] \
				      @CE@ [list [mc CE]]] \
				      {[dict get {BCE @BCE@ CE @CE@} \
					    [dict get $date era]]}]
		    }
    # try to retrieve now if already available:
    if {[dict exists $mcMergedCat $loc]} {
	return [dict get $mcMergedCat $loc]
    }
		    C {			# Locale-dependent era
			append formatString %s
			append substituents { [dict get $date localeEra]}
		    }
		    y {			# Locale-dependent year of the era
			append preFormatCode {
			    set y [dict get $date localeYear]
			    if { $y >= 0 && $y < 100 } {
				set Eyear [lindex $localeNumerals $y]
			    } else {
				set Eyear $y
			    }
			}
			append formatString %s
			append substituents { $Eyear}
		    }
		    default {		# Unknown %E format group
			append formatString %%E $char
		    }
		}
	    }
	    percentO {			# Character following %O
		set state {}
		switch -exact -- $char {
		    d - e {		# Day of the month in alternative
			# numerals
			append formatString %s
			append substituents \
			    { [lindex $localeNumerals \
				   [dict get $date dayOfMonth]]}
		    }
		    H - k {		# Hour of the day in alternative
					# numerals
			append formatString %s
			append substituents \
			    { [lindex $localeNumerals \
				   [expr { [dict get $date localSeconds]
					   / 3600
					   % 24 }]]}
		    }
		    I - l {		# Hour (12-11) AM/PM in alternative
					# numerals
			append formatString %s
			append substituents \
			    { [lindex $localeNumerals \
				   [expr { ( ( ( [dict get $date localSeconds]
						 % 86400 )
					       + 86400
					       - 3600 )
					     / 3600 )
					   % 12 + 1 }]]}
		    }

		    m {			# Month number in alternative numerals
			append formatString %s
			append substituents \
			    { [lindex $localeNumerals [dict get $date month]]}
		    }
		    M {			# Minute of the hour in alternative
					# numerals
			append formatString %s
			append substituents \
			    { [lindex $localeNumerals \
				   [expr { [dict get $date localSeconds]
					   / 60
					   % 60 }]]}
		    }
		    S {			# Second of the minute in alternative
					# numerals
			append formatString %s
			append substituents \
			    { [lindex $localeNumerals \
				   [expr { [dict get $date localSeconds]
					   % 60 }]]}
		    }
		    u {			# Day of the week (Monday=1,Sunday=7)
					# in alternative numerals
			append formatString %s
			append substituents \
			    { [lindex $localeNumerals \
				   [dict get $date dayOfWeek]]}
			}
		    w {			# Day of the week (Sunday=0,Saturday=6)
					# in alternative numerals
			append formatString %s
			append substituents \
			    { [lindex $localeNumerals \
				   [expr { [dict get $date dayOfWeek] % 7 }]]}
		    }
		    y {			# Year of the century in alternative
					# numerals
			append formatString %s
			append substituents \
			    { [lindex $localeNumerals \
				   [expr { [dict get $date year] % 100 }]]}
		    }
		    default {	# Unknown format group
			append formatString %%O $char
		    }
		}
	    }
	}
    }

    # get locales list for given locale (de_de -> {de_de de {}})
    # Clean up any improperly terminated groups

    variable mcLocales
    switch -exact -- $state {
	percent {
	    append formatString %%
	}
	percentE {
	    append retval %%E
	}
	percentO {
	    append retval %%O
	}
    }

    if {[dict exists $mcLocales $loc]} {
    proc $procName {clockval timezone} "
        $preFormatCode
        return \[::format [list $formatString] $substituents\]
    "

	set loclist [dict get $mcLocales $loc]
    #    puts [list $procName [info args $procName] [info body $procName]]

    } else {
    return $procName
}

	# save current locale:
#----------------------------------------------------------------------
#
# clock scan --
#
#	Inputs a count of seconds since the Posix Epoch as a time of day.
#
# The 'clock format' command scans times of day on input.  Refer to the user
# documentation to see what it does.
#
#----------------------------------------------------------------------

proc ::tcl::clock::scan { args } {

    set format {}

	set prevloc [mclocale]
    # Check the count of args

	# lazy load catalog on demand (set it will load the catalog)
    if { [llength $args] < 1 || [llength $args] % 2 != 1 } {
	set cmdName "clock scan"
	return -code error \
	    -errorcode [list CLOCK wrongNumArgs] \
	    "wrong \# args: should be\
             \"$cmdName string\
             ?-base seconds?\
             ?-format string? ?-gmt boolean?\
             ?-locale LOCALE? ?-timezone ZONE?\""
    }

    # Set defaults

    set base [clock seconds]
    set string [lindex $args 0]
    set format {}
    set gmt 0
    set locale c
	mcpackagelocale set $loc
    set timezone [GetSystemTimeZone]

	set loclist [msgcat::mcutil::getpreferences $loc]
    # Pick up command line options.

	dict set $mcLocales $loc $loclist
    foreach { flag value } [lreplace $args 0 0] {
	set saw($flag) {}
	switch -exact -- $flag {
	    -b - -ba - -bas - -base {
		set base $value
	    }
	    -f - -fo - -for - -form - -forma - -format {
		set format $value
	    }
	    -g - -gm - -gmt {
		set gmt $value
	    }
	    -l - -lo - -loc - -loca - -local - -locale {
		set locale [string tolower $value]
	    }
	    -t - -ti - -tim - -time - -timez - -timezo - -timezon - -timezone {
		set timezone $value
	    }
	    default {
		return -code error \
		    -errorcode [list CLOCK badOption $flag] \
		    "bad option \"$flag\",\
                     must be -base, -format, -gmt, -locale or -timezone"
	    }
	}
    }

	# restore:
    # Check options for validity

	if {$prevloc ne $loc} {
    if { [info exists saw(-gmt)] && [info exists saw(-timezone)] } {
	return -code error \
	    -errorcode [list CLOCK gmtWithTimezone] \
	    "cannot use -gmt and -timezone in same call"
    }
    if { [catch { expr { wide($base) } } result] } {
	return -code error "expected integer but got \"$base\""
    }
    if { ![string is boolean -strict $gmt] } {
	return -code error "expected boolean value but got \"$gmt\""
    } elseif { $gmt } {
	set timezone :GMT
    }

    if { ![info exists saw(-format)] } {
	# Perhaps someday we'll localize the legacy code. Right now, it's not
	# localized.
	if { [info exists saw(-locale)] } {
	    return -code error \
		-errorcode [list CLOCK flagWithLegacyFormat] \
		"legacy \[clock scan\] does not support -locale"

	}
	return [FreeScan $string $base $timezone $locale]
    }

    # Change locale if a fresh locale has been given on the command line.

    EnterLocale $locale

    try {
	# Map away the locale-dependent composite format groups

	set scanner [ParseClockScanFormat $format $locale]
	return [$scanner $string $base $timezone]
    } trap CLOCK {result opts} {
	# Conceal location of generation of expected errors
	dict unset opts -errorinfo
	return -options $opts $result
    }
}

	   mcpackagelocale set $prevloc
#----------------------------------------------------------------------
#
# FreeScan --
#
#	Scans a time in free format
#
# Parameters:
#	string - String containing the time to scan
#	base - Base time, expressed in seconds from the Epoch
#	timezone - Default time zone in which the time will be expressed
#	locale - (Unused) Name of the locale where the time will be scanned.
#
# Results:
#	Returns the date and time extracted from the string in seconds from
#	the epoch
#
#----------------------------------------------------------------------

	}
proc ::tcl::clock::FreeScan { string base timezone locale } {

    }
    variable TZData

    # get whole catalog:
    # Get the data for time changes in the given zone

    mcMerge $loclist
    try {
	SetupTimeZone $timezone
    } on error {retval opts} {
	dict unset opts -errorinfo
	return -options $opts $retval
    }
}

    # Extract year, month and day from the base time for the parser to use as
    # defaults

    set date [GetDateFields $base $TZData($timezone) 2361222]
    dict set date secondOfDay [expr {
	[dict get $date localSeconds] % 86400
    }]

    # Parse the date.  The parser will return a list comprising date, time,
    # time zone, relative month/day/seconds, relative weekday, ordinal month.

    try {
	set scanned [Oldscan $string \
		     [dict get $date year] \
		     [dict get $date month] \
		     [dict get $date dayOfMonth]]
	lassign $scanned \
	    parseDate parseTime parseZone parseRel \
	    parseWeekday parseOrdinalMonth
    } on error message {
	return -code error \
	    "unable to convert date-time string \"$string\": $message"
    }

    # If the caller supplied a date in the string, update the 'date' dict with
    # the value. If the caller didn't specify a time with the date, default to
    # midnight.

    if { [llength $parseDate] > 0 } {
	lassign $parseDate y m d
	if { $y < 100 } {
	    if { $y >= 39 } {
		incr y 1900
	    } else {
		incr y 2000
	    }
	}
	dict set date era CE
	dict set date year $y
	dict set date month $m
	dict set date dayOfMonth $d
	if { $parseTime eq {} } {
	    set parseTime 0
	}
    }

    # If the caller supplied a time zone in the string, it comes back as a
    # two-element list; the first element is the number of minutes east of
    # Greenwich, and the second is a Daylight Saving Time indicator (1 == yes,
    # 0 == no, -1 == unknown). We make it into a time zone indicator of
    # +-hhmm.

    if { [llength $parseZone] > 0 } {
	lassign $parseZone minEast dstFlag
	set timezone [FormatNumericTimeZone \
			  [expr { 60 * $minEast + 3600 * $dstFlag }]]
	SetupTimeZone $timezone
    }
    dict set date tzName $timezone

    # Assemble date, time, zone into seconds-from-epoch

    set date [GetJulianDayFromEraYearMonthDay $date[set date {}] 2361222]
    if { $parseTime ne {} } {
	dict set date secondOfDay $parseTime
    } elseif { [llength $parseWeekday] != 0
	       || [llength $parseOrdinalMonth] != 0
	       || ( [llength $parseRel] != 0
		    && ( [lindex $parseRel 0] != 0
			 || [lindex $parseRel 1] != 0 ) ) } {
	dict set date secondOfDay 0
    }

    dict set date localSeconds [expr {
	-210866803200
	+ ( 86400 * wide([dict get $date julianDay]) )
	+ [dict get $date secondOfDay]
    }]
    dict set date tzName $timezone
    set date [ConvertLocalToUTC $date[set date {}] $TZData($timezone) 2361222]
    set seconds [dict get $date seconds]

    # Do relative times

    if { [llength $parseRel] > 0 } {
	lassign $parseRel relMonth relDay relSecond
	set seconds [add $seconds \
			 $relMonth months $relDay days $relSecond seconds \
			 -timezone $timezone -locale $locale]
    }

    # Do relative weekday

    if { [llength $parseWeekday] > 0 } {
	lassign $parseWeekday dayOrdinal dayOfWeek
	set date2 [GetDateFields $seconds $TZData($timezone) 2361222]
	dict set date2 era CE
	set jdwkday [WeekdayOnOrBefore $dayOfWeek [expr {
	    [dict get $date2 julianDay] + 6
	}]]
	incr jdwkday [expr { 7 * $dayOrdinal }]
	if { $dayOrdinal > 0 } {
	    incr jdwkday -7
	}
	dict set date2 secondOfDay \
	    [expr { [dict get $date2 localSeconds] % 86400 }]
	dict set date2 julianDay $jdwkday
	dict set date2 localSeconds [expr {
	    -210866803200
	    + ( 86400 * wide([dict get $date2 julianDay]) )
	    + [dict get $date secondOfDay]
	}]
	dict set date2 tzName $timezone
	set date2 [ConvertLocalToUTC $date2[set date2 {}] $TZData($timezone) \
		       2361222]
	set seconds [dict get $date2 seconds]

    }

    # Do relative month

    if { [llength $parseOrdinalMonth] > 0 } {
	lassign $parseOrdinalMonth monthOrdinal monthNumber
	if { $monthOrdinal > 0 } {
	    set monthDiff [expr { $monthNumber - [dict get $date month] }]
	    if { $monthDiff <= 0 } {
		incr monthDiff 12
	    }
	    incr monthOrdinal -1
	} else {
	    set monthDiff [expr { [dict get $date month] - $monthNumber }]
	    if { $monthDiff >= 0 } {
		incr monthDiff -12
	    }
	    incr monthOrdinal
	}
	set seconds [add $seconds $monthOrdinal years $monthDiff months \
			 -timezone $timezone -locale $locale]
    }

    return $seconds
}


#----------------------------------------------------------------------
#
# ParseClockScanFormat --
#
#	Parses a format string given to [clock scan -format]
#
# Parameters:
#	formatString - The format being parsed
#	locale - The current locale
#
# Results:
#	Constructs and returns a procedure that accepts the string being
#	scanned, the base time, and the time zone.  The procedure will either
#	return the scanned time or else throw an error that should be rethrown
#	to the caller of [clock scan]
#
# Side effects:
#	The given procedure is defined in the ::tcl::clock namespace.  Scan
#	procedures are not deleted once installed.
#
# Why do we parse dates by defining a procedure to parse them?  The reason is
# that by doing so, we have one convenient place to cache all the information:
# the regular expressions that match the patterns (which will be compiled),
# the code that assembles the date information, everything lands in one place.
# In this way, when a given format is reused at run time, all the information
# of how to apply it is available in a single place.
#
#----------------------------------------------------------------------

proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
    # Check whether the format has been parsed previously, and return the
    # existing recognizer if it has.

    set procName scanproc'$formatString'$locale
    set procName [namespace current]::[string map {: {\:} \\ {\\}} $procName]
    if { [namespace which $procName] != {} } {
	return $procName
    }

    variable DateParseActions
    variable TimeParseActions

    # Localize the %x, %X, etc. groups

    set formatString [LocalizeFormat $locale $formatString]

    # Condense whitespace

    regsub -all {[[:space:]]+} $formatString { } formatString

    # Walk through the groups of the format string.  In this loop, we
    # accumulate:
    #	- a regular expression that matches the string,
    #   - the count of capturing brackets in the regexp
    #   - a set of code that post-processes the fields captured by the regexp,
    #   - a dictionary whose keys are the names of fields that are present
    #     in the format string.

    set re {^[[:space:]]*}
    set captureCount 0
    set postcode {}
    set fieldSet [dict create]
    set fieldCount 0
    set postSep {}
    set state {}

    foreach c [split $formatString {}] {
	switch -exact -- $state {
	    {} {
		if { $c eq "%" } {
		    set state %
		} elseif { $c eq " " } {
		    append re {[[:space:]]+}
		} else {
		    if { ! [string is alnum $c] } {
			append re "\\"
		    }
		    append re $c
		}
	    }
	    % {
		set state {}
		switch -exact -- $c {
		    % {
			append re %
		    }
		    { } {
			append re "\[\[:space:\]\]*"
		    }
		    a - A { 		# Day of week, in words
			set l {}
			foreach \
			    i {7 1 2 3 4 5 6} \
			    abr [mc DAYS_OF_WEEK_ABBREV] \
			    full [mc DAYS_OF_WEEK_FULL] {
				dict set l [string tolower $abr] $i
				dict set l [string tolower $full] $i
				incr i
			    }
			lassign [UniquePrefixRegexp $l] regex lookup
			append re ( $regex )
			dict set fieldSet dayOfWeek [incr fieldCount]
			append postcode "dict set date dayOfWeek \[" \
			    "dict get " [list $lookup] " " \
			    \[ {string tolower $field} [incr captureCount] \] \
			    "\]\n"
		    }
		    b - B - h {		# Name of month
			set i 0
			set l {}
			foreach \
			    abr [mc MONTHS_ABBREV] \
			    full [mc MONTHS_FULL] {
				incr i
				dict set l [string tolower $abr] $i
				dict set l [string tolower $full] $i
			    }
			lassign [UniquePrefixRegexp $l] regex lookup
			append re ( $regex )
			dict set fieldSet month [incr fieldCount]
			append postcode "dict set date month \[" \
			    "dict get " [list $lookup] \
			    " " \[ {string tolower $field} \
			    [incr captureCount] \] \
			    "\]\n"
		    }
		    C {			# Gregorian century
			append re \\s*(\\d\\d?)
			dict set fieldSet century [incr fieldCount]
			append postcode "dict set date century \[" \
			    "::scan \$field" [incr captureCount] " %d" \
			    "\]\n"
		    }
		    d - e {		# Day of month
			append re \\s*(\\d\\d?)
			dict set fieldSet dayOfMonth [incr fieldCount]
			append postcode "dict set date dayOfMonth \[" \
			    "::scan \$field" [incr captureCount] " %d" \
			    "\]\n"
		    }
		    E {			# Prefix for locale-specific codes
			set state %E
		    }
		    g {			# ISO8601 2-digit year
			append re \\s*(\\d\\d)
			dict set fieldSet iso8601YearOfCentury \
			    [incr fieldCount]
			append postcode \
			    "dict set date iso8601YearOfCentury \[" \
			    "::scan \$field" [incr captureCount] " %d" \
			    "\]\n"
		    }
		    G {			# ISO8601 4-digit year
			append re \\s*(\\d\\d)(\\d\\d)
			dict set fieldSet iso8601Century [incr fieldCount]
			dict set fieldSet iso8601YearOfCentury \
			    [incr fieldCount]
			append postcode \
			    "dict set date iso8601Century \[" \
			    "::scan \$field" [incr captureCount] " %d" \
			    "\]\n" \
			    "dict set date iso8601YearOfCentury \[" \
			    "::scan \$field" [incr captureCount] " %d" \
			    "\]\n"
		    }
		    H - k {		# Hour of day
			append re \\s*(\\d\\d?)
			dict set fieldSet hour [incr fieldCount]
			append postcode "dict set date hour \[" \
			    "::scan \$field" [incr captureCount] " %d" \
			    "\]\n"
		    }
		    I - l {		# Hour, AM/PM
			append re \\s*(\\d\\d?)
			dict set fieldSet hourAMPM [incr fieldCount]
			append postcode "dict set date hourAMPM \[" \
			    "::scan \$field" [incr captureCount] " %d" \
			    "\]\n"
		    }
		    j {			# Day of year
			append re \\s*(\\d\\d?\\d?)
			dict set fieldSet dayOfYear [incr fieldCount]
			append postcode "dict set date dayOfYear \[" \
			    "::scan \$field" [incr captureCount] " %d" \
			    "\]\n"
		    }
		    J {			# Julian Day Number
			append re \\s*(\\d+)
			dict set fieldSet julianDay [incr fieldCount]
			append postcode "dict set date julianDay \[" \
			    "::scan \$field" [incr captureCount] " %ld" \
			    "\]\n"
		    }
		    m - N {		# Month number
			append re \\s*(\\d\\d?)
			dict set fieldSet month [incr fieldCount]
			append postcode "dict set date month \[" \
			    "::scan \$field" [incr captureCount] " %d" \
			    "\]\n"
		    }
		    M {			# Minute
			append re \\s*(\\d\\d?)
			dict set fieldSet minute [incr fieldCount]
			append postcode "dict set date minute \[" \
			    "::scan \$field" [incr captureCount] " %d" \
			    "\]\n"
		    }
		    n {			# Literal newline
			append re \\n
		    }
		    O {			# Prefix for locale numerics
			set state %O
		    }
		    p - P { 		# AM/PM indicator
			set l [list [string tolower [mc AM]] 0 \
				   [string tolower [mc PM]] 1]
			lassign [UniquePrefixRegexp $l] regex lookup
			append re ( $regex )
			dict set fieldSet amPmIndicator [incr fieldCount]
			append postcode "dict set date amPmIndicator \[" \
			    "dict get " [list $lookup] " \[string tolower " \
			    "\$field" \
			    [incr captureCount] \
			    "\]\]\n"
		    }
		    Q {			# Hi, Jeff!

# mcMerge --
			append re {Stardate\s+([-+]?\d+)(\d\d\d)[.](\d)}
			incr captureCount
#
#	Merge message catalog dictionaries to one dictionary.
#
# Arguments:
			dict set fieldSet seconds [incr fieldCount]
			append postcode {dict set date seconds } \[ \
			    {ParseStarDate $field} [incr captureCount] \
			    { $field} [incr captureCount] \
			    { $field} [incr captureCount] \
			    \] \n
		    }
		    s {			# Seconds from Posix Epoch
			# This next case is insanely difficult, because it's
			# problematic to determine whether the field is
			# actually within the range of a wide integer.
#	locales		List of locales to merge.
			append re {\s*([-+]?\d+)}
			dict set fieldSet seconds [incr fieldCount]
			append postcode {dict set date seconds } \[ \
			    {ScanWide $field} [incr captureCount] \] \n
		    }
		    S {			# Second
			append re \\s*(\\d\\d?)
			dict set fieldSet second [incr fieldCount]
			append postcode "dict set date second \[" \
#
# Results:
#	Returns the (weak pointer) to merged dictionary of message catalog.
#
proc ::tcl::clock::mcMerge {locales} {
    variable mcMergedCat
    if {[dict exists $mcMergedCat [set loc [lindex $locales 0]]]} {
	return [dict get $mcMergedCat $loc]
			    "::scan \$field" [incr captureCount] " %d" \
			    "\]\n"
		    }
    }
		    t {			# Literal tab character
			append re \\t
		    }
		    u - w {		# Day number within week, 0 or 7 == Sun
					# 1=Mon, 6=Sat
			append re \\s*(\\d)
			dict set fieldSet dayOfWeek [incr fieldCount]
    # package msgcat currently does not provide possibility to get whole catalog:
    upvar ::msgcat::Msgs Msgs
    set ns ::tcl::clock
    # Merge sequential locales (in reverse order, e. g. {} -> en -> en_en):
    if {[llength $locales] > 1} {
	set mrgcat [mcMerge [lrange $locales 1 end]]
	if {[dict exists $Msgs $ns $loc]} {
	    set mrgcat [dict merge $mrgcat [dict get $Msgs $ns $loc]]
	    dict set mrgcat L $loc
			append postcode {::scan $field} [incr captureCount] \
			    { %d dow} \n \
			    {
				if { $dow == 0 } {
				    set dow 7
				} elseif { $dow > 7 } {
	} else {
				    return -code error \
					-errorcode [list CLOCK badDayOfWeek] \
					"day of week is greater than 7"
				}
				dict set date dayOfWeek $dow
			    }
		    }
		    U {			# Week of year. The first Sunday of
					# the year is the first day of week
					# 01. No scan rule uses this group.
			append re \\s*\\d\\d?
		    }
		    V {			# Week of ISO8601 year

	    # be sure a duplicate is created, don't overwrite {} (common) locale:
			append re \\s*(\\d\\d?)
			dict set fieldSet iso8601Week [incr fieldCount]
			append postcode "dict set date iso8601Week \[" \
			    "::scan \$field" [incr captureCount] " %d" \
			    "\]\n"
		    }
		    W {			# Week of the year (00-53). The first
					# Monday of the year is the first day
					# of week 01. No scan rule uses this
					# group.
			append re \\s*\\d\\d?
		    }
		    y {			# Two-digit Gregorian year
			append re \\s*(\\d\\d?)
			dict set fieldSet yearOfCentury [incr fieldCount]
			append postcode "dict set date yearOfCentury \[" \
			    "::scan \$field" [incr captureCount] " %d" \
			    "\]\n"
		    }
		    Y {			# 4-digit Gregorian year
			append re \\s*(\\d\\d)(\\d\\d)
			dict set fieldSet century [incr fieldCount]
			dict set fieldSet yearOfCentury [incr fieldCount]
			append postcode \
			    "dict set date century \[" \
	    set mrgcat [dict merge $mrgcat [dict create L $loc]]
			    "::scan \$field" [incr captureCount] " %d" \
			    "\]\n" \
			    "dict set date yearOfCentury \[" \
			    "::scan \$field" [incr captureCount] " %d" \
			    "\]\n"
		    }
	}
		    z - Z {			# Time zone name
			append re {(?:([-+]\d\d(?::?\d\d(?::?\d\d)?)?)|([[:alnum:]]{1,4}))}
			dict set fieldSet tzName [incr fieldCount]
			append postcode \
			    {if } \{ { $field} [incr captureCount] \
			    { ne "" } \} { } \{ \n \
			    {dict set date tzName $field} \
			    $captureCount \n \
			    \} { else } \{ \n \
			    {dict set date tzName } \[ \
    } else {
	if {[dict exists $Msgs $ns $loc]} {
			    {ConvertLegacyTimeZone $field} \
			    [incr captureCount] \] \n \
			    \} \n \
		    }
		    % {			# Literal percent character
			append re %
		    }
		    default {
			append re %
			if { ! [string is alnum $c] } {
			    append re \\
			    }
			append re $c
		    }
		}
	    }
	    %E {
		switch -exact -- $c {
		    C {			# Locale-dependent era
			set d {}
	    set mrgcat [dict get $Msgs $ns $loc]
			foreach triple [mc LOCALE_ERAS] {
			    lassign $triple t symbol year
			    dict set d [string tolower $symbol] $year
			}
			lassign [UniquePrefixRegexp $d] regex lookup
			append re (?: $regex )
		    }
		    E {
			set l {}
			dict set l [string tolower [mc BCE]] BCE
			dict set l [string tolower [mc CE]] CE
			dict set l b.c.e. BCE
			dict set l c.e. CE
	    dict set mrgcat L $loc
			dict set l b.c. BCE
			dict set l a.d. CE
			lassign [UniquePrefixRegexp $l] regex lookup
			append re ( $regex )
			dict set fieldSet era [incr fieldCount]
			append postcode "dict set date era \["\
			    "dict get " [list $lookup] \
			    { } \[ {string tolower $field} \
			    [incr captureCount] \] \
			    "\]\n"
		    }
	} else {
		    y {			# Locale-dependent year of the era
			lassign [LocaleNumeralMatcher $locale] regex lookup
			append re $regex
			incr captureCount
		    }
		    default {
			append re %E
			if { ! [string is alnum $c] } {
			    append re \\
			    }
			append re $c
		    }
		}
		set state {}
	    }
	    # be sure a duplicate is created, don't overwrite {} (common) locale:
	    set mrgcat [dict create L $loc]
	}
	    %O {
		switch -exact -- $c {
		    d - e {
			lassign [LocaleNumeralMatcher $locale] regex lookup
			append re $regex
			dict set fieldSet dayOfMonth [incr fieldCount]
			append postcode "dict set date dayOfMonth \[" \
			    "dict get " [list $lookup] " \$field" \
			    [incr captureCount] \
			    "\]\n"
		    }
    }
		    H - k {
			lassign [LocaleNumeralMatcher $locale] regex lookup
			append re $regex
			dict set fieldSet hour [incr fieldCount]
    dict set mcMergedCat $loc $mrgcat
			append postcode "dict set date hour \[" \
			    "dict get " [list $lookup] " \$field" \
			    [incr captureCount] \
    # return smart reference (shared dict as object with exact one ref-counter)
    return $mrgcat
			    "\]\n"
		    }
}
		    I - l {
			lassign [LocaleNumeralMatcher $locale] regex lookup
			append re $regex
			dict set fieldSet hourAMPM [incr fieldCount]
			append postcode "dict set date hourAMPM \[" \
			    "dict get " [list $lookup] " \$field" \
			    [incr captureCount] \
			    "\]\n"
		    }
		    m {
			lassign [LocaleNumeralMatcher $locale] regex lookup
			append re $regex
			dict set fieldSet month [incr fieldCount]
			append postcode "dict set date month \[" \
			    "dict get " [list $lookup] " \$field" \
			    [incr captureCount] \
			    "\]\n"
		    }
		    M {
			lassign [LocaleNumeralMatcher $locale] regex lookup
			append re $regex
			dict set fieldSet minute [incr fieldCount]
			append postcode "dict set date minute \[" \
			    "dict get " [list $lookup] " \$field" \
			    [incr captureCount] \
			    "\]\n"
		    }
		    S {
			lassign [LocaleNumeralMatcher $locale] regex lookup
			append re $regex
			dict set fieldSet second [incr fieldCount]
			append postcode "dict set date second \[" \
			    "dict get " [list $lookup] " \$field" \
			    [incr captureCount] \
			    "\]\n"
		    }
		    u - w {
			lassign [LocaleNumeralMatcher $locale] regex lookup
			append re $regex
			dict set fieldSet dayOfWeek [incr fieldCount]
			append postcode "set dow \[dict get " [list $lookup] \
			    { $field} [incr captureCount] \] \n \
			    {
				if { $dow == 0 } {
				    set dow 7
				} elseif { $dow > 7 } {
				    return -code error \
					-errorcode [list CLOCK badDayOfWeek] \
					"day of week is greater than 7"
				}
				dict set date dayOfWeek $dow
			    }
		    }
		    y {
			lassign [LocaleNumeralMatcher $locale] regex lookup
			append re $regex
			dict set fieldSet yearOfCentury [incr fieldCount]
			append postcode {dict set date yearOfCentury } \[ \
			    {dict get } [list $lookup] { $field} \
			    [incr captureCount] \] \n
		    }
		    default {
			append re %O
			if { ! [string is alnum $c] } {
			    append re \\
			    }
			append re $c
		    }
		}
		set state {}
	    }
	}
    }

    # Clean up any unfinished format groups

    append re $state \\s*\$

    # Build the procedure

    set procBody {}
    append procBody "variable ::tcl::clock::TZData" \n
    append procBody "if \{ !\[ regexp -nocase [list $re] \$string ->"
    for { set i 1 } { $i <= $captureCount } { incr i } {
	append procBody " " field $i
    }
    append procBody "\] \} \{" \n
    append procBody {
	return -code error -errorcode [list CLOCK badInputString] \
	    {input string does not match supplied format}
    }
    append procBody \}\n
    append procBody "set date \[dict create\]" \n
    append procBody {dict set date tzName $timeZone} \n
    append procBody $postcode
    append procBody [list set changeover [mc GREGORIAN_CHANGE_DATE]] \n

    # Set up the time zone before doing anything with a default base date
    # that might need a timezone to interpret it.

    if { ![dict exists $fieldSet seconds]
	    && ![dict exists $fieldSet starDate] } {
	if { [dict exists $fieldSet tzName] } {
	    append procBody {
		set timeZone [dict get $date tzName]
	    }
	}
	append procBody {
	    ::tcl::clock::SetupTimeZone $timeZone
	}
    }

    # Add code that gets Julian Day Number from the fields.

    append procBody [MakeParseCodeFromFields $fieldSet $DateParseActions]

    # Get time of day

    append procBody [MakeParseCodeFromFields $fieldSet $TimeParseActions]

    # Assemble seconds from the Julian day and second of the day.
    # Convert to local time unless epoch seconds or stardate are
    # being processed - they're always absolute

    if { ![dict exists $fieldSet seconds]
         && ![dict exists $fieldSet starDate] } {
	append procBody {
	    if { [dict get $date julianDay] > 5373484 } {
		return -code error -errorcode [list CLOCK dateTooLarge] \
		    "requested date too large to represent"
	    }

	    dict set date localSeconds [expr {
		-210866803200
		+ ( 86400 * wide([dict get $date julianDay]) )
		+ [dict get $date secondOfDay]
	    }]
	}

	# Finally, convert the date to local time

	append procBody {
	    set date [::tcl::clock::ConvertLocalToUTC $date[set date {}] \
			  $TZData($timeZone) $changeover]
	}
    }

    # Return result

    append procBody {return [dict get $date seconds]} \n

    proc $procName { string baseTime timeZone } $procBody

    # puts [list proc $procName [list string baseTime timeZone] $procBody]

    return $procName
}

#----------------------------------------------------------------------
#
# LocaleNumeralMatcher --
#
#	Composes a regexp that captures the numerals in the given locale, and
#	a dictionary to map them to conventional numerals.
#
# Parameters:
#	locale - Name of the current locale
#
# Results:
#	Returns a two-element list comprising the regexp and the dictionary.
#
# Side effects:
#	Caches the result.
#
#----------------------------------------------------------------------

# GetSystemLocale --
proc ::tcl::clock::LocaleNumeralMatcher {l} {
    variable LocaleNumeralCache

#
    if { ![dict exists $LocaleNumeralCache $l] } {
	set d {}
	set i 0
	set sep \(
	foreach n [mc LOCALE_NUMERALS] {
	    dict set d $n $i
	    regsub -all {[^[:alnum:]]} $n \\\\& subex
	    append re $sep $subex
	    set sep |
	    incr i
	}
	append re \)
	dict set LocaleNumeralCache $l [list $re $d]
    }
    return [dict get $LocaleNumeralCache $l]
}



#	Determines the system locale, which corresponds to "system"
#	keyword for locale parameter of 'clock' command.
#
#----------------------------------------------------------------------
#
# UniquePrefixRegexp --
#
#	Composes a regexp that performs unique-prefix matching.  The RE
#	matches one of a supplied set of strings, or any unique prefix
#	thereof.
#
# Parameters:
#	data - List of alternating match-strings and values.
#	       Match-strings with distinct values are considered
#	       distinct.
#	None.
#
# Results:
#	Returns a two-element list.  The first is a regexp that matches any
#	Returns the system locale.
#	unique prefix of any of the strings.  The second is a dictionary whose
#	keys are match values from the regexp and whose values are the
#	corresponding values from 'data'.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc ::tcl::clock::UniquePrefixRegexp { data } {
proc ::tcl::clock::GetSystemLocale {} {
    # The 'successors' dictionary will contain, for each string that is a
    # prefix of any key, all characters that may follow that prefix.  The
    # 'prefixMapping' dictionary will have keys that are prefixes of keys and
    # values that correspond to the keys.

    if { $::tcl_platform(platform) ne {windows} } {
    set prefixMapping [dict create]
    set successors [dict create {} {}]

	# On a non-windows platform, the 'system' locale is the same as
    # Walk the key-value pairs

	# the 'current' locale
    foreach { key value } $data {
	# Construct all prefixes of the key;

	set prefix {}
	foreach char [split $key {}] {
	    set oldPrefix $prefix
	    dict set successors $oldPrefix $char {}
	    append prefix $char

	    # Put the prefixes in the 'prefixMapping' and 'successors'
	    # dictionaries

	    dict lappend prefixMapping $prefix $value
	    if { ![dict exists $successors $prefix] } {
		dict set successors $prefix {}
	    }
	}
    }

    # Identify those prefixes that designate unique values, and those that are
    # the full keys

    set uniquePrefixMapping {}
    dict for { key valueList } $prefixMapping {
	if { [llength $valueList] == 1 } {
	    dict set uniquePrefixMapping $key [lindex $valueList 0]
	}
    }
    foreach { key value } $data {
	dict set uniquePrefixMapping $key $value
    }

    # Construct the re.

    return [list \
	return [mclocale]
		[MakeUniquePrefixRegexp $successors $uniquePrefixMapping {}] \
		$uniquePrefixMapping]
}
    }

#----------------------------------------------------------------------
#
# MakeUniquePrefixRegexp --
#

#	Service procedure for 'UniquePrefixRegexp' that constructs a regular
#	expresison that matches the unique prefixes.
#
# Parameters:
#	successors - Dictionary whose keys are all prefixes
#		     of keys passed to 'UniquePrefixRegexp' and whose
#		     values are dictionaries whose keys are the characters
#		     that may follow those prefixes.
#	uniquePrefixMapping - Dictionary whose keys are the unique
#			      prefixes and whose values are not examined.
#	prefixString - Current prefix being processed.
#
# Results:
#	Returns a constructed regular expression that matches the set of
#	unique prefixes beginning with the 'prefixString'.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

    # On a windows platform, the 'system' locale is adapted from the
proc ::tcl::clock::MakeUniquePrefixRegexp { successors
					  uniquePrefixMapping
					  prefixString } {

    # 'current' locale by applying the date and time formats from the
    # Get the characters that may follow the current prefix string

    # Control Panel.  First, load the 'current' locale if it's not yet
    set schars [lsort -ascii [dict keys [dict get $successors $prefixString]]]
    if { [llength $schars] == 0 } {
	return {}
    }

    # loaded
    # If there is more than one successor character, or if the current prefix
    # is a unique prefix, surround the generated re with non-capturing
    # parentheses.

    set re {}
    if {
	[dict exists $uniquePrefixMapping $prefixString]
	|| [llength $schars] > 1
    } then {
	append re "(?:"
    }

    # Generate a regexp that matches the successors.

    set sep ""
    foreach { c } $schars {
	set nextPrefix $prefixString$c
	regsub -all {[^[:alnum:]]} $c \\\\& rechar
	append re $sep $rechar \
	    [MakeUniquePrefixRegexp \
		 $successors $uniquePrefixMapping $nextPrefix]
	set sep |
    }


    mcpackagelocale set [mclocale]
    # If the current prefix is a unique prefix, make all following text
    # optional. Otherwise, if there is more than one successor character,
    # close the non-capturing parentheses.

    if { [dict exists $uniquePrefixMapping $prefixString] } {
	append re ")?"
    } elseif { [llength $schars] > 1 } {
	append re ")"
    }

    # Make a new locale string for the system locale, and get the
    return $re
}

    # Control Panel information
#----------------------------------------------------------------------
#
# MakeParseCodeFromFields --
#
#	Composes Tcl code to extract the Julian Day Number from a dictionary
#	containing date fields.
#
# Parameters:
#	dateFields -- Dictionary whose keys are fields of the date,
#	              and whose values are the rightmost positions
#		      at which those fields appear.
#	parseActions -- List of triples: field set, priority, and
#			code to emit.  Smaller priorities are better, and
#			the list must be in ascending order by priority
#
# Results:
#	Returns a burst of code that extracts the day number from the given
#	date.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc ::tcl::clock::MakeParseCodeFromFields { dateFields parseActions } {

    set currPrio 999
    set currFieldPos [list]
    set currCodeBurst {
	error "in ::tcl::clock::MakeParseCodeFromFields: can't happen"
    }

    foreach { fieldSet prio parseAction } $parseActions {
	# If we've found an answer that's better than any that follow, quit
	# now.

	if { $prio > $currPrio } {
	    break
	}


    set locale [mclocale]_windows
	# Accumulate the field positions that are used in the current field
	# grouping.

    if { ! [mcpackagelocale present $locale] } {
	set fieldPos [list]
	set ok true
	foreach field $fieldSet {
	    if { ! [dict exists $dateFields $field] } {
		set ok 0
		break
	    }
	    lappend fieldPos [dict get $dateFields $field]
	}

	LoadWindowsDateTimeFormats $locale
	# Quit if we don't have a complete set of fields
	if { !$ok } {
	    continue
	}
    }

	# Determine whether the current answer is better than the last.

	set fPos [lsort -integer -decreasing $fieldPos]

	if { $prio ==  $currPrio } {
	    foreach currPos $currFieldPos newPos $fPos {
		if {
		    ![string is integer $newPos]
		    || ![string is integer $currPos]
		    || $newPos > $currPos
		} then {
		    break
		}
		if { $newPos < $currPos } {
		    set ok 0
		    break
		}
	    }
	}
	if { !$ok } {
	    continue
	}

	# Remember the best possibility for extracting date information

	set currPrio $prio
	set currFieldPos $fPos
	set currCodeBurst $parseAction
    }

    return $currCodeBurst
    return $locale
}

#----------------------------------------------------------------------
#
# EnterLocale --
#
#	Switch [mclocale] to a given locale if necessary
#
# Parameters:
#	locale -- Desired locale
#
# Results:
#	Returns the locale that was previously current.
#
# Side effects:
#	Does [mclocale].  If necessary, loades the designated locale's files.
#
#----------------------------------------------------------------------

proc ::tcl::clock::EnterLocale { locale } {
    if { $locale eq {system} } {
    switch -- $locale system {
	if { $::tcl_platform(platform) ne {windows} } {
	    # On a non-windows platform, the 'system' locale is the same as
	    # the 'current' locale
	set locale [GetSystemLocale]
    } current {

	    set locale current
	set locale [mclocale]
	} else {
	    # On a windows platform, the 'system' locale is adapted from the
	    # 'current' locale by applying the date and time formats from the
	    # Control Panel.  First, load the 'current' locale if it's not yet
	    # loaded

	    mcpackagelocale set [mclocale]

	    # Make a new locale string for the system locale, and get the
	    # Control Panel information

	    set locale [mclocale]_windows
	    if { ! [mcpackagelocale present $locale] } {
		LoadWindowsDateTimeFormats $locale
	    }
    }
    # 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
    }
	}
    if { $locale eq {current}} {
	set locale [mclocale]
    }
    proc ::tcl::clock::_hasRegistry {} [list return $res]
    # Eventually load the locale
    return $res
    mcpackagelocale set $locale
}

#----------------------------------------------------------------------
#
# LoadWindowsDateTimeFormats --
#
#	Load the date/time formats from the Control Panel in Windows and
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
709
710
711
712
713
714
715


716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735


736
737
738
739
740
741
742
743
744







-
-
+



















-
-
+
+







# default strings can be obtained if the Registry query fails.
#
#----------------------------------------------------------------------

proc ::tcl::clock::LoadWindowsDateTimeFormats { locale } {
    # Bail out if we can't find the Registry

    variable NoRegistry
    if { [info exists NoRegistry] } return
    if { ![_hasRegistry] } return

    if { ![catch {
	registry get "HKEY_CURRENT_USER\\Control Panel\\International" \
	    sShortDate
    } string] } {
	set quote {}
	set datefmt {}
	foreach { unquoted quoted } [split $string '] {
	    append datefmt $quote [string map {
		dddd %A
		ddd  %a
		dd   %d
		d    %e
		MMMM %B
		MMM  %b
		MM   %m
		M    %N
		yyyy %Y
		yy   %y
                y    %y
                gg   {}
		y    %y
		gg   {}
	    } $unquoted]
	    if { $quoted eq {} } {
		set quote '
	    } else {
		set quote $quoted
	    }
	}
2405
2406
2407
2408
2409
2410
2411
2412
2413


2414
2415
2416
2417
2418
2419
2420
759
760
761
762
763
764
765


766
767
768
769
770
771
772
773
774







-
-
+
+







		d    %e
		MMMM %B
		MMM  %b
		MM   %m
		M    %N
		yyyy %Y
		yy   %y
                y    %y
                gg   {}
		y    %y
		gg   {}
	    } $unquoted]
	    if { $quoted eq {} } {
		set quote '
	    } else {
		set quote $quoted
	    }
	}
2466
2467
2468
2469
2470
2471
2472


2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483


2484
2485

2486
2487
2488


2489
2490
2491
2492
2493
2494





2495
2496
2497
2498
2499
2500





2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512

2513
2514
2515
2516

2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838

839
840
841

842



843
844






845
846
847
848
849
850





851
852
853
854
855












856




857









































































































858



859


860







861


862


863



864











865















































































866





































































867



868
869






















870



871


872




















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
898
899


900
901
902
903
904
905

906
907
908
909
910
911
912
913
914
915
916

917














918
919
920
921
922
923
924
925
926

927
928

929
930
931


932
933


934


935
936





















937


938






939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958

959
960
961
962
963





964
965
966
967
968
969
970
971
972
973
974
975
976
977
978







+
+










-
+
+

-
+
-
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
-
-
+
-
-
-
-
-
-
-
+
-
-
+
-
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-
-
-
+
-
-
+
-
-
+
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
















-
-
+
+




-






+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-


-
+

+
-
-
+
+
-
-

-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-

-
-
-
-
-
-
+



















-
+



+
-
-
-
-
-
+
+
+
+
+
+
+
+







#
#	Map away locale-dependent format groups in a clock format.
#
# Parameters:
#	locale -- Current [mclocale] locale, supplied to avoid
#		  an extra call
#	format -- Format supplied to [clock scan] or [clock format]
#	mcd    -- Message catalog dictionary for current locale (read-only,
#		  don't store it to avoid shared references).
#
# Results:
#	Returns the string with locale-dependent composite format groups
#	substituted out.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc ::tcl::clock::LocalizeFormat { locale format } {
proc ::tcl::clock::LocalizeFormat { locale format mcd } {
    variable LocFmtMap

    # message catalog key to cache this format
    # get map list cached or build it:
    set key FORMAT_$format

    if { [::msgcat::mcexists -exactlocale -exactnamespace $key] } {
    if {[dict exists $LocFmtMap $locale]} {
	set mlst [dict get $LocFmtMap $locale]
	return [mc $key]
    }
    # Handle locale-dependent format groups by mapping them out of the format
    # string.  Note that the order of the [string map] operations is
    # significant because later formats can refer to later ones; for example
    # %c can refer to %X, which in turn can refer to %T.
    } else {
	# Handle locale-dependent format groups by mapping them out of the format
	# string.  Note that the order of the [string map] operations is
	# significant because later formats can refer to later ones; for example
	# %c can refer to %X, which in turn can refer to %T.

    set list {
	%% %%
	%D %m/%d/%Y
	%+ {%a %b %e %H:%M:%S %Z %Y}
    }
	set mlst {
	    %% %%
	    %D %m/%d/%Y
	    %+ {%a %b %e %H:%M:%S %Z %Y}
	}
    lappend list %EY [string map $list [mc LOCALE_YEAR_FORMAT]]
    lappend list %T  [string map $list [mc TIME_FORMAT_24_SECS]]
    lappend list %R  [string map $list [mc TIME_FORMAT_24]]
    lappend list %r  [string map $list [mc TIME_FORMAT_12]]
    lappend list %X  [string map $list [mc TIME_FORMAT]]
    lappend list %EX [string map $list [mc LOCALE_TIME_FORMAT]]
    lappend list %x  [string map $list [mc DATE_FORMAT]]
    lappend list %Ex [string map $list [mc LOCALE_DATE_FORMAT]]
    lappend list %c  [string map $list [mc DATE_TIME_FORMAT]]
    lappend list %Ec [string map $list [mc LOCALE_DATE_TIME_FORMAT]]
    set format [string map $list $format]

	lappend mlst %EY [string map $mlst [dict get $mcd LOCALE_YEAR_FORMAT]]
    ::msgcat::mcset $locale $key $format
    return $format
}

	lappend mlst %T  [string map $mlst [dict get $mcd TIME_FORMAT_24_SECS]]
#----------------------------------------------------------------------
#
# FormatNumericTimeZone --
#
#	Formats a time zone as +hhmmss
#
# Parameters:
#	z - Time zone in seconds east of Greenwich
#
# Results:
#	Returns the time zone formatted in a numeric form
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc ::tcl::clock::FormatNumericTimeZone { z } {
    if { $z < 0 } {
	set z [expr { - $z }]
	set retval -
    } else {
	set retval +
    }
    append retval [::format %02d [expr { $z / 3600 }]]
    set z [expr { $z % 3600 }]
    append retval [::format %02d [expr { $z / 60 }]]
    set z [expr { $z % 60 }]
    if { $z != 0 } {
	append retval [::format %02d $z]
    }
    return $retval
}

#----------------------------------------------------------------------
#
# FormatStarDate --
#
#	Formats a date as a StarDate.
#
# Parameters:
#	date - Dictionary containing 'year', 'dayOfYear', and
#	       'localSeconds' fields.
#
# Results:
#	Returns the given date formatted as a StarDate.
#
# Side effects:
#	None.
#
# Jeff Hobbs put this in to support an atrocious pun about Tcl being
# "Enterprise ready."  Now we're stuck with it.
#
#----------------------------------------------------------------------

proc ::tcl::clock::FormatStarDate { date } {
    variable Roddenberry

    # Get day of year, zero based

    set doy [expr { [dict get $date dayOfYear] - 1 }]

    # Determine whether the year is a leap year

    set lp [IsGregorianLeapYear $date]

    # Convert day of year to a fractional year

    if { $lp } {
	set fractYear [expr { 1000 * $doy / 366 }]
    } else {
	set fractYear [expr { 1000 * $doy / 365 }]
    }

    # Put together the StarDate

    return [::format "Stardate %02d%03d.%1d" \
		[expr { [dict get $date year] - $Roddenberry }] \
		$fractYear \
		[expr { [dict get $date localSeconds] % 86400
			/ ( 86400 / 10 ) }]]
}

#----------------------------------------------------------------------
#
# ParseStarDate --
#
#	Parses a StarDate
#
# Parameters:
#	year - Year from the Roddenberry epoch
#	fractYear - Fraction of a year specifiying the day of year.
#	fractDay - Fraction of a day
#
# Results:
#	Returns a count of seconds from the Posix epoch.
#
# Side effects:
#	None.
#
# Jeff Hobbs put this in to support an atrocious pun about Tcl being
# "Enterprise ready."  Now we're stuck with it.
#
#----------------------------------------------------------------------

	lappend mlst %R  [string map $mlst [dict get $mcd TIME_FORMAT_24]]
proc ::tcl::clock::ParseStarDate { year fractYear fractDay } {
    variable Roddenberry

	lappend mlst %r  [string map $mlst [dict get $mcd TIME_FORMAT_12]]
    # Build a tentative date from year and fraction.

	lappend mlst %X  [string map $mlst [dict get $mcd TIME_FORMAT]]
    set date [dict create \
		  gregorian 1 \
		  era CE \
		  year [expr { $year + $Roddenberry }] \
		  dayOfYear [expr { $fractYear * 365 / 1000 + 1 }]]
    set date [GetJulianDayFromGregorianEraYearDay $date[set date {}]]

	lappend mlst %EX [string map $mlst [dict get $mcd LOCALE_TIME_FORMAT]]
    # Determine whether the given year is a leap year

	lappend mlst %x  [string map $mlst [dict get $mcd DATE_FORMAT]]
    set lp [IsGregorianLeapYear $date]

	lappend mlst %Ex [string map $mlst [dict get $mcd LOCALE_DATE_FORMAT]]
    # Reconvert the fractional year according to whether the given year is a
    # leap year

	lappend mlst %c  [string map $mlst [dict get $mcd DATE_TIME_FORMAT]]
    if { $lp } {
	dict set date dayOfYear \
	    [expr { $fractYear * 366 / 1000 + 1 }]
    } else {
	dict set date dayOfYear \
	    [expr { $fractYear * 365 / 1000 + 1 }]
    }
    dict unset date julianDay
    dict unset date gregorian
    set date [GetJulianDayFromGregorianEraYearDay $date[set date {}]]

	lappend mlst %Ec [string map $mlst [dict get $mcd LOCALE_DATE_TIME_FORMAT]]
    return [expr {
	86400 * [dict get $date julianDay]
	- 210866803200
	+ ( 86400 / 10 ) * $fractDay
    }]
}

#----------------------------------------------------------------------
#
# ScanWide --
#
#	Scans a wide integer from an input
#
# Parameters:
#	str - String containing a decimal wide integer
#
# Results:
#	Returns the string as a pure wide integer.  Throws an error if the
#	string is misformatted or out of range.
#
#----------------------------------------------------------------------

proc ::tcl::clock::ScanWide { str } {
    set count [::scan $str {%ld %c} result junk]
    if { $count != 1 } {
	return -code error -errorcode [list CLOCK notAnInteger $str] \
	    "\"$str\" is not an integer"
    }
    if { [incr result 0] != $str } {
	return -code error -errorcode [list CLOCK integervalueTooLarge] \
	    "integer value too large to represent"
    }
    return $result
}

#----------------------------------------------------------------------
#
# InterpretTwoDigitYear --
#
#	Given a date that contains only the year of the century, determines
#	the target value of a two-digit year.
#
# Parameters:
#	date - Dictionary containing fields of the date.
#	baseTime - Base time relative to which the date is expressed.
#	twoDigitField - Name of the field that stores the two-digit year.
#			Default is 'yearOfCentury'
#	fourDigitField - Name of the field that will receive the four-digit
#	                 year.  Default is 'year'
#
# Results:
#	Returns the dictionary augmented with the four-digit year, stored in
#	the given key.
#
# Side effects:
#	None.
#
# The current rule for interpreting a two-digit year is that the year shall be
# between 1937 and 2037, thus staying within the range of a 32-bit signed
# value for time.  This rule may change to a sliding window in future
# versions, so the 'baseTime' parameter (which is currently ignored) is
# provided in the procedure signature.
#
#----------------------------------------------------------------------

proc ::tcl::clock::InterpretTwoDigitYear { date baseTime
					   { twoDigitField yearOfCentury }
					   { fourDigitField year } } {
    set yr [dict get $date $twoDigitField]
    if { $yr <= 37 } {
	dict set date $fourDigitField [expr { $yr + 2000 }]
    } else {
	dict set date $fourDigitField [expr { $yr + 1900 }]
    }
    return $date
}

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

# AssignBaseYear --
#
#	Places the number of the current year into a dictionary.
#
# Parameters:
#	date - Dictionary value to update
#	baseTime - Base time from which to extract the year, expressed
#		   in seconds from the Posix epoch
#	timezone - the time zone in which the date is being scanned
#	changeover - the Julian Day on which the Gregorian calendar
#		     was adopted in the target locale.
#
# Results:
#	Returns the dictionary with the current year assigned.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc ::tcl::clock::AssignBaseYear { date baseTime timezone changeover } {
    variable TZData

    # Find the Julian Day Number corresponding to the base time, and
    # find the Gregorian year corresponding to that Julian Day.

    set date2 [GetDateFields $baseTime $TZData($timezone) $changeover]

    # Store the converted year

    dict set date era [dict get $date2 era]
    dict set date year [dict get $date2 year]

    return $date
}

#----------------------------------------------------------------------
#
# AssignBaseIso8601Year --
#
#	Determines the base year in the ISO8601 fiscal calendar.
#
# Parameters:
#	date - Dictionary containing the fields of the date that
#	       is to be augmented with the base year.
#	baseTime - Base time expressed in seconds from the Posix epoch.
#	timeZone - Target time zone
#	changeover - Julian Day of adoption of the Gregorian calendar in
#		     the target locale.
#
# Results:
#	Returns the given date with "iso8601Year" set to the
#	base year.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc ::tcl::clock::AssignBaseIso8601Year {date baseTime timeZone changeover} {
    variable TZData

    # Find the Julian Day Number corresponding to the base time

    set date2 [GetDateFields $baseTime $TZData($timeZone) $changeover]

    # Calculate the ISO8601 date and transfer the year

    dict set date era CE
	dict set LocFmtMap $locale $mlst
    dict set date iso8601Year [dict get $date2 iso8601Year]
    return $date
}
    }

#----------------------------------------------------------------------
#
# AssignBaseMonth --
#
#	Places the number of the current year and month into a
#	dictionary.
#
# Parameters:
#	date - Dictionary value to update
#	baseTime - Time from which the year and month are to be
#	           obtained, expressed in seconds from the Posix epoch.
#	timezone - Name of the desired time zone
#	changeover - Julian Day on which the Gregorian calendar was adopted.
#
# Results:
#	Returns the dictionary with the base year and month assigned.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

    # translate copy of format (don't use format object here, because otherwise
proc ::tcl::clock::AssignBaseMonth {date baseTime timezone changeover} {
    variable TZData

    # it can lose its internal representation (string map - convert to unicode)
    # Find the year and month corresponding to the base time

    set locfmt [string map $mlst [string range " $format" 1 end]]
    set date2 [GetDateFields $baseTime $TZData($timezone) $changeover]
    dict set date era [dict get $date2 era]
    dict set date year [dict get $date2 year]
    dict set date month [dict get $date2 month]
    return $date
}

#----------------------------------------------------------------------
#
# AssignBaseWeek --
#
#	Determines the base year and week in the ISO8601 fiscal calendar.
#
# Parameters:
#	date - Dictionary containing the fields of the date that
#	       is to be augmented with the base year and week.
#	baseTime - Base time expressed in seconds from the Posix epoch.
#	changeover - Julian Day on which the Gregorian calendar was adopted
#		     in the target locale.
#

# Results:
#	Returns the given date with "iso8601Year" set to the
#	base year and "iso8601Week" to the week number.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

    # Save original format as long as possible, because of internal
proc ::tcl::clock::AssignBaseWeek {date baseTime timeZone changeover} {
    variable TZData

    # representation (performance).
    # Find the Julian Day Number corresponding to the base time

    # Note that in this case such format will be never localized (also
    set date2 [GetDateFields $baseTime $TZData($timeZone) $changeover]

    # using another locales). To prevent this return a duplicate (but
    # Calculate the ISO8601 date and transfer the year

    # it may be slower).
    dict set date era CE
    dict set date iso8601Year [dict get $date2 iso8601Year]
    dict set date iso8601Week [dict get $date2 iso8601Week]
    return $date
}

    if {$locfmt eq $format} {
#----------------------------------------------------------------------
#
# AssignBaseJulianDay --
#
#	Determines the base day for a time-of-day conversion.
#
# Parameters:
#	date - Dictionary that is to get the base day
#	baseTime - Base time expressed in seconds from the Posix epoch
#	changeover - Julian day on which the Gregorian calendar was
#		     adpoted in the target locale.
#
# Results:
#	Returns the given dictionary augmented with a 'julianDay' field
#	that contains the base day.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

	set locfmt $format
proc ::tcl::clock::AssignBaseJulianDay { date baseTime timeZone changeover } {
    variable TZData

    # Find the Julian Day Number corresponding to the base time

    set date2 [GetDateFields $baseTime $TZData($timeZone) $changeover]
    dict set date julianDay [dict get $date2 julianDay]

    }
    return $date
}


#----------------------------------------------------------------------
#
# InterpretHMSP --
#
#	Interprets a time in the form "hh:mm:ss am".
#
# Parameters:
#	date -- Dictionary containing "hourAMPM", "minute", "second"
#	        and "amPmIndicator" fields.
#
# Results:
#	Returns the number of seconds from local midnight.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc ::tcl::clock::InterpretHMSP { date } {
    set hr [dict get $date hourAMPM]
    if { $hr == 12 } {
	set hr 0
    }
    if { [dict get $date amPmIndicator] } {
	incr hr 12
    }
    dict set date hour $hr
    return [InterpretHMS $date[set date {}]]
}

#----------------------------------------------------------------------
#
# InterpretHMS --
#
#	Interprets a 24-hour time "hh:mm:ss"
#
# Parameters:
#	date -- Dictionary containing the "hour", "minute" and "second"
#	        fields.
#
# Results:
#	Returns the given dictionary augmented with a "secondOfDay"
#	field containing the number of seconds from local midnight.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc ::tcl::clock::InterpretHMS { date } {
    return [expr {
    return $locfmt
	( [dict get $date hour] * 60
	  + [dict get $date minute] ) * 60
	+ [dict get $date second]
    }]
}

#----------------------------------------------------------------------
#
# GetSystemTimeZone --
#
#	Determines the system time zone, which is the default for the
#	'clock' command if no other zone is supplied.
#
# Parameters:
#	None.
#
# Results:
#	Returns the system time zone.
#
# Side effects:
#	Stores the sustem time zone in the 'CachedSystemTimeZone'
#	variable, since determining it may be an expensive process.
#	Stores the system time zone in engine configuration, since
#	determining it may be an expensive process.
#
#----------------------------------------------------------------------

proc ::tcl::clock::GetSystemTimeZone {} {
    variable CachedSystemTimeZone
    variable TimeZoneBad

    if {[set result [getenv TCL_TZ]] ne {}} {
	set timezone $result
    } elseif {[set result [getenv TZ]] ne {}} {
	set timezone $result
    } else {
	# ask engine for the cached timezone:
	set timezone [::tcl::unsupported::clock::configure -system-tz]
	if { $timezone ne "" } {
	    return $timezone
    }
	}
    if {![info exists timezone]} {
        # Cache the time zone only if it was detected by one of the
        # expensive methods.
        if { [info exists CachedSystemTimeZone] } {
            set timezone $CachedSystemTimeZone
        } elseif { $::tcl_platform(platform) eq {windows} } {
            set timezone [GuessWindowsTimeZone]
        } elseif { [file exists /etc/localtime]
                   && ![catch {ReadZoneinfoFile \
                                   Tcl/Localtime /etc/localtime}] } {
            set timezone :Tcl/Localtime
        } else {
            set timezone :localtime
        }
	if { $::tcl_platform(platform) eq {windows} } {
	    set timezone [GuessWindowsTimeZone]
	} elseif { [file exists /etc/localtime]
		   && ![catch {ReadZoneinfoFile \
				   Tcl/Localtime /etc/localtime}] } {
	    set timezone :Tcl/Localtime
	} else {
	    set timezone :localtime
	}
	set CachedSystemTimeZone $timezone
    }
    if { ![dict exists $TimeZoneBad $timezone] } {
	dict set TimeZoneBad $timezone [catch {SetupTimeZone $timezone}]
	catch {set timezone [SetupTimeZone $timezone]}
    }

    if { [dict get $TimeZoneBad $timezone] } {
	return :localtime
    if { [dict exists $TimeZoneBad $timezone] } {
	set timezone :localtime
    } else {
	return $timezone
    }
}


    # tell backend - current system timezone:
#----------------------------------------------------------------------
#
# ConvertLegacyTimeZone --
#
#	Given an alphanumeric time zone identifier and the system time zone,
#	convert the alphanumeric identifier to an unambiguous time zone.
#
# Parameters:
#	tzname - Name of the time zone to convert
#
# Results:
#	Returns a time zone name corresponding to tzname, but in an
#	unambiguous form, generally +hhmm.
#
# This procedure is implemented primarily to allow the parsing of RFC822
# date/time strings.  Processing a time zone name on input is not recommended
# practice, because there is considerable room for ambiguity; for instance, is
# BST Brazilian Standard Time, or British Summer Time?
#
#----------------------------------------------------------------------

    ::tcl::unsupported::clock::configure -system-tz $timezone
proc ::tcl::clock::ConvertLegacyTimeZone { tzname } {
    variable LegacyTimeZone

    set tzname [string tolower $tzname]
    if { ![dict exists $LegacyTimeZone $tzname] } {
	return -code error -errorcode [list CLOCK badTZName $tzname] \
	    "time zone \"$tzname\" not found"
    }
    return [dict get $LegacyTimeZone $tzname]
    return $timezone
}

#----------------------------------------------------------------------
#
# SetupTimeZone --
#
#	Given the name or specification of a time zone, sets up its in-memory
#	data.
#
# Parameters:
#	tzname - Name of a time zone
#
# Results:
#	Unless the time zone is ':localtime', sets the TZData array to contain
#	the lookup table for local<->UTC conversion.  Returns an error if the
#	time zone cannot be parsed.
#
#----------------------------------------------------------------------

proc ::tcl::clock::SetupTimeZone { timezone } {
proc ::tcl::clock::SetupTimeZone { timezone {alias {}} } {
    variable TZData

    if {! [info exists TZData($timezone)] } {

	variable MINWIDE
	if { $timezone eq {:localtime} } {
	    # Nothing to do, we'll convert using the localtime function

	} elseif {
	variable TimeZoneBad
	if { [dict exists $TimeZoneBad $timezone] } {
	    return -code error \
		-errorcode [list CLOCK badTimeZone $timezone] \
		"time zone \"$timezone\" not found"
	}
	variable MINWIDE
	if {
	    [regexp {^([-+])(\d\d)(?::?(\d\d)(?::?(\d\d))?)?} $timezone \
		    -> s hh mm ss]
	} then {
	    # Make a fixed offset

	    ::scan $hh %d hh
	    if { $mm eq {} } {
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
3134
3135
3136
3137


3138
3139
3140
3141
3142
3143
3144
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

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







-
+

-
-
-
-
+
+
+
+
+
+
+
+



-
+
-
-
+
+
+
+

+
-
+

-
+



+
+
+




-
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
-
+





-
+
+







	    # Convert using a time zone file

	    if {
		[catch {
		    LoadTimeZoneFile [string range $timezone 1 end]
		}] && [catch {
		    LoadZoneinfoFile [string range $timezone 1 end]
		}]
		} ret opts]
	    } then {
		return -code error \
		    -errorcode [list CLOCK badTimeZone $timezone] \
		    "time zone \"$timezone\" not found"
	    }
		dict unset opts -errorinfo
		if {[lindex [dict get $opts -errorcode] 0] ne "CLOCK"} {
		    dict set opts -errorcode [list CLOCK badTimeZone $timezone]
		    set ret "time zone \"$timezone\" not found: $ret"
		}
		dict set TimeZoneBad $timezone 1
		return -options $opts $ret
	    }
	} elseif { ![catch {ParsePosixTimeZone $timezone} tzfields] } {
	    # This looks like a POSIX time zone - try to process it

	    if { [catch {ProcessPosixTimeZone $tzfields} data opts] } {
	    if { [catch {ProcessPosixTimeZone $tzfields} ret opts] } {
		if { [lindex [dict get $opts -errorcode] 0] eq {CLOCK} } {
		    dict unset opts -errorinfo
		dict unset opts -errorinfo
		if {[lindex [dict get $opts -errorcode] 0] ne "CLOCK"} {
		    dict set opts -errorcode [list CLOCK badTimeZone $timezone]
		    set ret "time zone \"$timezone\" not found: $ret"
		}
		dict set TimeZoneBad $timezone 1
		return -options $opts $data
		return -options $opts $ret
	    } else {
		set TZData($timezone) $data
		set TZData($timezone) $ret
	    }

	} else {

	    variable LegacyTimeZone

	    # We couldn't parse this as a POSIX time zone.  Try again with a
	    # time zone file - this time without a colon

	    if { [catch { LoadTimeZoneFile $timezone }]
		 && [catch { LoadZoneinfoFile $timezone } - opts] } {
		 && [catch { LoadZoneinfoFile $timezone } ret opts] } {

		# Check may be a legacy zone:

		if { $alias eq {} && ![catch {
		    set tzname [dict get $LegacyTimeZone [string tolower $timezone]]
		}] } {
		    set tzname [::tcl::clock::SetupTimeZone $tzname $timezone]
		    set TZData($timezone) $TZData($tzname)
		    # tell backend - timezone is initialized and return shared timezone object:
		    return [::tcl::unsupported::clock::configure -setup-tz $timezone]
		}

		dict unset opts -errorinfo
		if {[lindex [dict get $opts -errorcode] 0] ne "CLOCK"} {
		    dict set opts -errorcode [list CLOCK badTimeZone $timezone]
		    set ret "time zone \"$timezone\" not found: $ret"
		}
		dict set TimeZoneBad $timezone 1
		return -options $opts "time zone $timezone not found"
		return -options $opts $ret
	    }
	    set TZData($timezone) $TZData(:$timezone)
	}
    }

    return
    # tell backend - timezone is initialized and return shared timezone object:
    ::tcl::unsupported::clock::configure -setup-tz $timezone
}

#----------------------------------------------------------------------
#
# GuessWindowsTimeZone --
#
#	Determines the system time zone on windows.
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170

3171
3172
3173
3174
3175
3176
3177
1084
1085
1086
1087
1088
1089
1090

1091
1092

1093
1094
1095
1096
1097
1098
1099
1100







-


-
+







# zone that uses the same rules.  If it finds one, it returns it; otherwise,
# it constructs a Posix-style time zone string and returns that.
#
#----------------------------------------------------------------------

proc ::tcl::clock::GuessWindowsTimeZone {} {
    variable WinZoneInfo
    variable NoRegistry
    variable TimeZoneBad

    if { [info exists NoRegistry] } {
    if { ![_hasRegistry] } {
	return :localtime
    }

    # Dredge time zone information out of the registry

    if { [catch {
	set rpath HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\TimeZoneInformation
3201
3202
3203
3204
3205
3206
3207
3208

3209
3210
3211
3212
3213

3214
3215
3216
3217
3218
3219
3220
1124
1125
1126
1127
1128
1129
1130

1131
1132
1133
1134
1135

1136
1137
1138
1139
1140
1141
1142
1143







-
+




-
+







    # Make up a Posix time zone specifier if we can't find one.  Check here
    # that the tzdata file exists, in case we're running in an environment
    # (e.g. starpack) where tzdata is incomplete.  (Bug 1237907)

    if { [dict exists $WinZoneInfo $data] } {
	set tzname [dict get $WinZoneInfo $data]
	if { ! [dict exists $TimeZoneBad $tzname] } {
	    dict set TimeZoneBad $tzname [catch {SetupTimeZone $tzname}]
	    catch {set tzname [SetupTimeZone $tzname]}
	}
    } else {
	set tzname {}
    }
    if { $tzname eq {} || [dict get $TimeZoneBad $tzname] } {
    if { $tzname eq {} || [dict exists $TimeZoneBad $tzname] } {
	lassign $data \
	    bias stdBias dstBias \
	    stdYear stdMonth stdDayOfWeek stdDayOfMonth \
	    stdHour stdMinute stdSecond stdMillisec \
	    dstYear dstMonth dstDayOfWeek dstDayOfMonth \
	    dstHour dstMinute dstSecond dstMillisec
	set stdDelta [expr { $bias + $stdBias }]
3304
3305
3306
3307
3308
3309
3310
3311

3312
3313

3314
3315
3316
3317
3318
3319
3320
1227
1228
1229
1230
1231
1232
1233

1234
1235

1236
1237
1238
1239
1240
1241
1242
1243







-
+

-
+







	return
    }

    # Since an unsafe interp uses the [clock] command in the parent, this code
    # is security sensitive.  Make sure that the path name cannot escape the
    # given directory.

    if { ![regexp {^[[.-.][:alpha:]_]+(?:/[[.-.][:alpha:]_]+)*$} $fileName] } {
    if { [regexp {^[/\\]|^[a-zA-Z]+:|(?:^|[/\\])\.\.} $fileName] } {
	return -code error \
	    -errorcode [list CLOCK badTimeZone $:fileName] \
	    -errorcode [list CLOCK badTimeZone :$fileName] \
	    "time zone \":$fileName\" not valid"
    }
    try {
	source [file join $DataDir $fileName]
    } on error {} {
	return -code error \
	    -errorcode [list CLOCK badTimeZone :$fileName] \
3344
3345
3346
3347
3348
3349
3350
3351

3352
3353

3354
3355

3356
3357
3358
3359
3360
3361






3362
3363
3364
3365
3366
3367
3368
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







-
+

-
+


+





-
+
+
+
+
+
+







proc ::tcl::clock::LoadZoneinfoFile { fileName } {
    variable ZoneinfoPaths

    # Since an unsafe interp uses the [clock] command in the parent, this code
    # is security sensitive.  Make sure that the path name cannot escape the
    # given directory.

    if { ![regexp {^[[.-.][:alpha:]_]+(?:/[[.-.][:alpha:]_]+)*$} $fileName] } {
    if { [regexp {^[/\\]|^[a-zA-Z]+:|(?:^|[/\\])\.\.} $fileName] } {
	return -code error \
	    -errorcode [list CLOCK badTimeZone $:fileName] \
	    -errorcode [list CLOCK badTimeZone :$fileName] \
	    "time zone \":$fileName\" not valid"
    }
    set fname ""
    foreach d $ZoneinfoPaths {
	set fname [file join $d $fileName]
	if { [file readable $fname] && [file isfile $fname] } {
	    break
	}
	unset fname
	set fname ""
    }
    if {$fname eq ""} {
	return -code error \
	    -errorcode [list CLOCK badTimeZone :$fileName] \
	    "time zone \":$fileName\" not found"
    }
    ReadZoneinfoFile $fileName $fname
}

#----------------------------------------------------------------------
#
# ReadZoneinfoFile --
3398
3399
3400
3401
3402
3403
3404
3405

3406
3407
3408
3409
3410
3411
3412
1327
1328
1329
1330
1331
1332
1333

1334
1335
1336
1337
1338
1339
1340
1341







-
+








    set f [open $fname r]
    fconfigure $f -translation binary
    set d [read $f]
    close $f

    # The file begins with a magic number, sixteen reserved bytes, and then
    # six 4-byte integers giving counts of fileds in the file.
    # six 4-byte integers giving counts of fields in the file.

    binary scan $d a4a1x15IIIIII \
	magic version nIsGMT nIsStd nLeap nTime nType nChar
    set seek 44
    set ilen 4
    set iformat I
    if { $magic != {TZif} } {
3605
3606
3607
3608
3609
3610
3611
3612

3613
3614
3615
3616
3617
3618
3619
3620

3621
3622
3623
3624
3625
3626
3627
3628
3629

3630
3631
3632
3633
3634

3635
3636
3637
3638
3639


3640
3641
3642
3643
3644
3645
3646
3647
3648

3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661


3662
3663
3664
3665
3666
3667
3668
3669
3670

3671
3672
3673
3674
3675
3676
3677
3678
3679

3680
3681

3682
3683
3684
3685
3686
3687
3688
1534
1535
1536
1537
1538
1539
1540

1541
1542
1543
1544
1545
1546
1547
1548

1549
1550
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







-
+







-
+








-
+




-
+



-
-
+
+








-
+











-
-
+
+








-
+








-
+

-
+







	([-+]?)
	# 3 - Standard time zone offset, hours
	([[:digit:]]{1,2})
	(?:
	    # 4 - Standard time zone offset, minutes
	    : ([[:digit:]]{1,2})
	    (?:
	        # 5 - Standard time zone offset, seconds
		# 5 - Standard time zone offset, seconds
		: ([[:digit:]]{1,2} )
	    )?
	)?
	(?:
	    # 6 - DST time zone name
	    ([[:alpha:]]+ | <[-+[:alnum:]]+>)
	    (?:
	        (?:
		(?:
		    # 7 - DST time zone offset, signum
		    ([-+]?)
		    # 8 - DST time zone offset, hours
		    ([[:digit:]]{1,2})
		    (?:
			# 9 - DST time zone offset, minutes
			: ([[:digit:]]{1,2})
			(?:
		            # 10 - DST time zone offset, seconds
			    # 10 - DST time zone offset, seconds
			    : ([[:digit:]]{1,2})
			)?
		    )?
		)?
	        (?:
		(?:
		    ,
		    (?:
			# 11 - Optional J in n and Jn form 12 - Day of year
		        ( J ? )	( [[:digit:]]+ )
                        | M
			( J ? )	( [[:digit:]]+ )
			| M
			# 13 - Month number 14 - Week of month 15 - Day of week
			( [[:digit:]] + )
			[.] ( [[:digit:]] + )
			[.] ( [[:digit:]] + )
		    )
		    (?:
			# 16 - Start time of DST - hours
			/ ( [[:digit:]]{1,2} )
		        (?:
			(?:
			    # 17 - Start time of DST - minutes
			    : ( [[:digit:]]{1,2} )
			    (?:
				# 18 - Start time of DST - seconds
				: ( [[:digit:]]{1,2} )
			    )?
			)?
		    )?
		    ,
		    (?:
			# 19 - Optional J in n and Jn form 20 - Day of year
		        ( J ? )	( [[:digit:]]+ )
                        | M
			( J ? )	( [[:digit:]]+ )
			| M
			# 21 - Month number 22 - Week of month 23 - Day of week
			( [[:digit:]] + )
			[.] ( [[:digit:]] + )
			[.] ( [[:digit:]] + )
		    )
		    (?:
			# 24 - End time of DST - hours
			/ ( [[:digit:]]{1,2} )
		        (?:
			(?:
			    # 25 - End time of DST - minutes
			    : ( [[:digit:]]{1,2} )
			    (?:
				# 26 - End time of DST - seconds
				: ( [[:digit:]]{1,2} )
			    )?
			)?
		    )?
                )?
		)?
	    )?
        )?
	)?
	$
    } $tz -> x(stdName) x(stdSignum) x(stdHours) x(stdMinutes) x(stdSeconds) \
	     x(dstName) x(dstSignum) x(dstHours) x(dstMinutes) x(dstSeconds) \
	     x(startJ) x(startDayOfYear) \
	     x(startMonth) x(startWeekOfMonth) x(startDayOfWeek) \
	     x(startHours) x(startMinutes) x(startSeconds) \
	     x(endJ) x(endDayOfYear) \
3877
3878
3879
3880
3881
3882
3883
3884

3885
3886
3887
3888
3889
3890
3891

3892
3893
3894
3895
3896
3897
3898
1806
1807
1808
1809
1810
1811
1812

1813
1814
1815
1816
1817
1818
1819

1820
1821
1822
1823
1824
1825
1826
1827







-
+






-
+








proc ::tcl::clock::DeterminePosixDSTTime { z bound y } {

    variable FEB_28

    # Determine the start or end day of DST

    set date [dict create era CE year $y]
    set date [dict create era CE year $y gregorian 1]
    set doy [dict get $z ${bound}DayOfYear]
    if { $doy ne {} } {

	# Time was specified as a day of the year

	if { [dict get $z ${bound}J] ne {}
	     && [IsGregorianLeapYear $y]
	     && [IsGregorianLeapYear $date]
	     && ( $doy > $FEB_28 ) } {
	    incr doy
	}
	dict set date dayOfYear $doy
	set date [GetJulianDayFromEraYearDay $date[set date {}] 2361222]
    } else {
	# Time was specified as a day of the week within a month
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
1860
1861
1862
1863
1864
1865
1866





































1867
1868
1869
1870
1871
1872
1873







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    } else {
	set s [lindex [::scan $s %d] 0]
    }
    set tod [expr { ( $h * 60 + $m ) * 60 + $s }]
    return [expr { $seconds + $tod }]
}

#----------------------------------------------------------------------
#
# GetLocaleEra --
#
#	Given local time expressed in seconds from the Posix epoch,
#	determine localized era and year within the era.
#
# Parameters:
#	date - Dictionary that must contain the keys, 'localSeconds',
#	       whose value is expressed as the appropriate local time;
#	       and 'year', whose value is the Gregorian year.
#	etable - Value of the LOCALE_ERAS key in the message catalogue
#	         for the target locale.
#
# Results:
#	Returns the dictionary, augmented with the keys, 'localeEra' and
#	'localeYear'.
#
#----------------------------------------------------------------------

proc ::tcl::clock::GetLocaleEra { date etable } {
    set index [BSearch $etable [dict get $date localSeconds]]
    if { $index < 0} {
	dict set date localeEra \
	    [::format %02d [expr { [dict get $date year] / 100 }]]
	dict set date localeYear [expr {
	    [dict get $date year] % 100
	}]
    } else {
	dict set date localeEra [lindex $etable $index 1]
	dict set date localeYear [expr {
	    [dict get $date year] - [lindex $etable $index 2]
	}]
    }
    return $date
}

#----------------------------------------------------------------------
#
# GetJulianDayFromEraYearDay --
#
#	Given a year, month and day on the Gregorian calendar, determines
#	the Julian Day Number beginning at noon on that date.
#
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
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
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
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500

4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532


4533
4534

4535

4536
4537

4538
4539
4540



4541
4542
4543

4544
4545
4546
4547
2039
2040
2041
2042
2043
2044
2045





































































































































































































































































































































2046
2047
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

2095
2096
2097







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

















-
-
-
-
-
+
-
-
-
-
-
-
-
-
-




















-
-
-
+
+


+
-
+
-
-
+
-
-
-
+
+
+
-
-
-
+
-



proc ::tcl::clock::WeekdayOnOrBefore { weekday j } {
    set k [expr { ( $weekday + 6 )  % 7 }]
    return [expr { $j - ( $j - $k ) % 7 }]
}

#----------------------------------------------------------------------
#
# BSearch --
#
#	Service procedure that does binary search in several places inside the
#	'clock' command.
#
# Parameters:
#	list - List of lists, sorted in ascending order by the
#	       first elements
#	key - Value to search for
#
# Results:
#	Returns the index of the greatest element in $list that is less than
#	or equal to $key.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc ::tcl::clock::BSearch { list key } {
    if {[llength $list] == 0} {
	return -1
    }
    if { $key < [lindex $list 0 0] } {
	return -1
    }

    set l 0
    set u [expr { [llength $list] - 1 }]

    while { $l < $u } {
	# At this point, we know that
	#   $k >= [lindex $list $l 0]
	#   Either $u == [llength $list] or else $k < [lindex $list $u+1 0]
	# We find the midpoint of the interval {l,u} rounded UP, compare
	# against it, and set l or u to maintain the invariant.  Note that the
	# interval shrinks at each step, guaranteeing convergence.

	set m [expr { ( $l + $u + 1 ) / 2 }]
	if { $key >= [lindex $list $m 0] } {
	    set l $m
	} else {
	    set u [expr { $m - 1 }]
	}
    }

    return $l
}

#----------------------------------------------------------------------
#
# clock add --
#
#	Adds an offset to a given time.
#
# Syntax:
#	clock add clockval ?count unit?... ?-option value?
#
# Parameters:
#	clockval -- Starting time value
#	count -- Amount of a unit of time to add
#	unit -- Unit of time to add, must be one of:
#			years year months month weeks week
#			days day hours hour minutes minute
#			seconds second
#
# Options:
#	-gmt BOOLEAN
#		(Deprecated) Flag synonymous with '-timezone :GMT'
#	-timezone ZONE
#		Name of the time zone in which calculations are to be done.
#	-locale NAME
#		Name of the locale in which calculations are to be done.
#		Used to determine the Gregorian change date.
#
# Results:
#	Returns the given time adjusted by the given offset(s) in
#	order.
#
# Notes:
#	It is possible that adding a number of months or years will adjust the
#	day of the month as well.  For instance, the time at one month after
#	31 January is either 28 or 29 February, because February has fewer
#	than 31 days.
#
#----------------------------------------------------------------------

proc ::tcl::clock::add { clockval args } {
    if { [llength $args] % 2 != 0 } {
	set cmdName "clock add"
	return -code error \
	    -errorcode [list CLOCK wrongNumArgs] \
	    "wrong \# args: should be\
             \"$cmdName clockval ?number units?...\
             ?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?\""
    }
    if { [catch { expr {wide($clockval)} } result] } {
	return -code error $result
    }

    set offsets {}
    set gmt 0
    set locale c
    set timezone [GetSystemTimeZone]

    foreach { a b } $args {
	if { [string is integer -strict $a] } {
	    lappend offsets $a $b
	} else {
	    switch -exact -- $a {
		-g - -gm - -gmt {
		    set gmt $b
		}
		-l - -lo - -loc - -loca - -local - -locale {
		    set locale [string tolower $b]
		}
		-t - -ti - -tim - -time - -timez - -timezo - -timezon -
		-timezone {
		    set timezone $b
		}
		default {
		    throw [list CLOCK badOption $a] \
			"bad option \"$a\",\
                         must be -gmt, -locale or -timezone"
		}
	    }
	}
    }

    # Check options for validity

    if { [info exists saw(-gmt)] && [info exists saw(-timezone)] } {
	return -code error \
	    -errorcode [list CLOCK gmtWithTimezone] \
	    "cannot use -gmt and -timezone in same call"
    }
    if { [catch { expr { wide($clockval) } } result] } {
	return -code error "expected integer but got \"$clockval\""
    }
    if { ![string is boolean -strict $gmt] } {
	return -code error "expected boolean value but got \"$gmt\""
    } elseif { $gmt } {
	set timezone :GMT
    }

    EnterLocale $locale

    set changeover [mc GREGORIAN_CHANGE_DATE]

    if {[catch {SetupTimeZone $timezone} retval opts]} {
	dict unset opts -errorinfo
	return -options $opts $retval
    }

    try {
	foreach { quantity unit } $offsets {
	    switch -exact -- $unit {
		years - year {
		    set clockval [AddMonths [expr { 12 * $quantity }] \
			    $clockval $timezone $changeover]
		}
		months - month {
		    set clockval [AddMonths $quantity $clockval $timezone \
			    $changeover]
		}

		weeks - week {
		    set clockval [AddDays [expr { 7 * $quantity }] \
			    $clockval $timezone $changeover]
		}
		days - day {
		    set clockval [AddDays $quantity $clockval $timezone \
			    $changeover]
		}

		hours - hour {
		    set clockval [expr { 3600 * $quantity + $clockval }]
		}
		minutes - minute {
		    set clockval [expr { 60 * $quantity + $clockval }]
		}
		seconds - second {
		    set clockval [expr { $quantity + $clockval }]
		}

		default {
		    throw [list CLOCK badUnit $unit] \
			"unknown unit \"$unit\", must be \
                        years, months, weeks, days, hours, minutes or seconds"
		}
	    }
	}
	return $clockval
    } trap CLOCK {result opts} {
	# Conceal the innards of [clock] when it's an expected error
	dict unset opts -errorinfo
	return -options $opts $result
    }
}

#----------------------------------------------------------------------
#
# AddMonths --
#
#	Add a given number of months to a given clock value in a given
#	time zone.
#
# Parameters:
#	months - Number of months to add (may be negative)
#	clockval - Seconds since the epoch before the operation
#	timezone - Time zone in which the operation is to be performed
#
# Results:
#	Returns the new clock value as a number of seconds since
#	the epoch.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc ::tcl::clock::AddMonths { months clockval timezone changeover } {
    variable DaysInRomanMonthInCommonYear
    variable DaysInRomanMonthInLeapYear
    variable TZData

    # Convert the time to year, month, day, and fraction of day.

    set date [GetDateFields $clockval $TZData($timezone) $changeover]
    dict set date secondOfDay [expr {
	[dict get $date localSeconds] % 86400
    }]
    dict set date tzName $timezone

    # Add the requisite number of months

    set m [dict get $date month]
    incr m $months
    incr m -1
    set delta [expr { $m / 12 }]
    set mm [expr { $m % 12 }]
    dict set date month [expr { $mm + 1 }]
    dict incr date year $delta

    # If the date doesn't exist in the current month, repair it

    if { [IsGregorianLeapYear $date] } {
	set hath [lindex $DaysInRomanMonthInLeapYear $mm]
    } else {
	set hath [lindex $DaysInRomanMonthInCommonYear $mm]
    }
    if { [dict get $date dayOfMonth] > $hath } {
	dict set date dayOfMonth $hath
    }

    # Reconvert to a number of seconds

    set date [GetJulianDayFromEraYearMonthDay \
		  $date[set date {}]\
		  $changeover]
    dict set date localSeconds [expr {
	-210866803200
	+ ( 86400 * wide([dict get $date julianDay]) )
	+ [dict get $date secondOfDay]
    }]
    set date [ConvertLocalToUTC $date[set date {}] $TZData($timezone) \
		 $changeover]

    return [dict get $date seconds]

}

#----------------------------------------------------------------------
#
# AddDays --
#
#	Add a given number of days to a given clock value in a given time
#	zone.
#
# Parameters:
#	days - Number of days to add (may be negative)
#	clockval - Seconds since the epoch before the operation
#	timezone - Time zone in which the operation is to be performed
#	changeover - Julian Day on which the Gregorian calendar was adopted
#		     in the target locale.
#
# Results:
#	Returns the new clock value as a number of seconds since the epoch.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc ::tcl::clock::AddDays { days clockval timezone changeover } {
    variable TZData

    # Convert the time to Julian Day

    set date [GetDateFields $clockval $TZData($timezone) $changeover]
    dict set date secondOfDay [expr {
	[dict get $date localSeconds] % 86400
    }]
    dict set date tzName $timezone

    # Add the requisite number of days

    dict incr date julianDay $days

    # Reconvert to a number of seconds

    dict set date localSeconds [expr {
	-210866803200
	+ ( 86400 * wide([dict get $date julianDay]) )
	+ [dict get $date secondOfDay]
    }]
    set date [ConvertLocalToUTC $date[set date {}] $TZData($timezone) \
		  $changeover]

    return [dict get $date seconds]

}

#----------------------------------------------------------------------
#
# ChangeCurrentLocale --
#
#        The global locale was changed within msgcat.
#        Clears the buffered parse functions of the current locale.
#
# Parameters:
#        loclist (ignored)
#
# Results:
#        None.
#
# Side effects:
#        Buffered parse functions are cleared.
#
#----------------------------------------------------------------------

proc ::tcl::clock::ChangeCurrentLocale {args} {
    variable FormatProc
    variable LocaleNumeralCache
    variable CachedSystemTimeZone
    variable TimeZoneBad

    ::tcl::unsupported::clock::configure -current-locale [lindex $args 0]
    foreach p [info procs [namespace current]::scanproc'*'current] {
        rename $p {}
    }
    foreach p [info procs [namespace current]::formatproc'*'current] {
        rename $p {}
    }

    catch {array unset FormatProc *'current}
    set LocaleNumeralCache {}
}

#----------------------------------------------------------------------
#
# ClearCaches --
#
#	Clears all caches to reclaim the memory used in [clock]
#
# Parameters:
#	None.
#
# Results:
#	None.
#
# Side effects:
#	Caches are cleared.
#
#----------------------------------------------------------------------

proc ::tcl::clock::ClearCaches {} {
    variable FormatProc
    variable LocaleNumeralCache
    variable CachedSystemTimeZone
    variable LocFmtMap
    variable mcMergedCat
    variable TimeZoneBad

    # tell backend - should invalidate:
    foreach p [info procs [namespace current]::scanproc'*] {
    ::tcl::unsupported::clock::configure -clear
	rename $p {}
    }

    foreach p [info procs [namespace current]::formatproc'*] {
	rename $p {}
    }
    # clear msgcat cache:
    set mcMergedCat [dict create]


    catch {unset FormatProc}
    set LocaleNumeralCache {}
    set LocFmtMap {}
    catch {unset CachedSystemTimeZone}
    set TimeZoneBad {}
    InitTZData
}

Changes to library/cookiejar/cookiejar.tcl.

53
54
55
56
57
58
59
60

61
62

63
64
65
66
67
68
69
53
54
55
56
57
58
59

60
61

62
63
64
65
66
67
68
69







-
+

-
+







    }

    # Keep this in sync with pkgIndex.tcl and with the install directories in
    # Makefiles
    variable version 0.2.0

    variable domainlist \
	http://publicsuffix.org/list/effective_tld_names.dat
	https://publicsuffix.org/list/public_suffix_list.dat
    variable domainfile \
	[file join [file dirname [info script]] effective_tld_names.txt.gz]
	[file join [file dirname [info script]] public_suffix_list.dat.gz]
    # The list is directed to from http://publicsuffix.org/list/
    variable loglevel info
    variable vacuumtrigger 200
    variable retainlimit 100
    variable offline false
    variable purgeinterval 60000
    variable refreshinterval 10000000
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
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







-
+
















-
+






-
+







# Now we have enough information to provide the package.
package provide cookiejar \
    [set [info object namespace ::http::cookiejar]::version]

# The implementation of the cookiejar package
::oo::define ::http::cookiejar {
    self {
	method configure {{optionName "\u0000\u0000"} {optionValue "\u0000\u0000"}} {
	method configure {{optionName "\x00\x00"} {optionValue "\x00\x00"}} {
	    set tbl {
		-domainfile    {domainfile set}
		-domainlist    {domainlist set}
		-domainrefresh {refreshinterval setInterval}
		-loglevel      {loglevel setLog}
		-offline       {offline setBool}
		-purgeold      {purgeinterval setInterval}
		-retain        {retainlimit setInt}
		-vacuumtrigger {vacuumtrigger setInt}
	    }
	    dict lappend tbl -domainrefresh [namespace code {
		my IntervalTrigger PostponeRefresh
	    }]
	    dict lappend tbl -purgeold [namespace code {
		my IntervalTrigger PostponePurge
	    }]
	    if {$optionName eq "\u0000\u0000"} {
	    if {$optionName eq "\x00\x00"} {
		return [dict keys $tbl]
	    }
	    set opt [::tcl::prefix match -message "option" \
		    [dict keys $tbl] $optionName]
	    set setter [lassign [dict get $tbl $opt] varname]
	    namespace upvar [namespace current] $varname var
	    if {$optionValue ne "\u0000\u0000"} {
	    if {$optionValue ne "\x00\x00"} {
		{*}$setter var $optionValue
	    }
	    return $var
	}

	method IntervalTrigger {method} {
	    # TODO: handle subclassing

Deleted library/cookiejar/effective_tld_names.txt.gz.

cannot compute difference between binary files

Changes to library/cookiejar/idna.tcl.

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
30

31
32

33
34
35
36
37
38
39

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

30
31

32
33
34
35
36
37
38
39
-
+








-
+



















-
+

-
+







# cookiejar.tcl --
# idna.tcl --
#
#	Implementation of IDNA (Internationalized Domain Names for
#	Applications) encoding/decoding system, built on a punycode engine
#	developed directly from the code in RFC 3492, Appendix C (with
#	substantial modifications).
#
# This implementation includes code from that RFC, translated to Tcl; the
# other parts are:
# Copyright (c) 2014 Donal K. Fellows
# Copyright © 2014 Donal K. Fellows
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

namespace eval ::tcl::idna {
    namespace ensemble create -command puny -map {
	encode punyencode
	decode punydecode
    }
    namespace ensemble create -command ::tcl::idna -map {
	encode IDNAencode
	decode IDNAdecode
	puny puny
	version {::apply {{} {package present tcl::idna} ::}}
    }

    proc IDNAencode hostname {
	set parts {}
	# Split term from RFC 3490, Sec 3.1
	foreach part [split $hostname "\u002E\u3002\uFF0E\uFF61"] {
	foreach part [split $hostname "\x2E\u3002\uFF0E\uFF61"] {
	    if {[regexp {[^-A-Za-z0-9]} $part]} {
		if {[regexp {[^-A-Za-z0-9\u00a1-\uffff]} $part ch]} {
		if {[regexp {[^-A-Za-z0-9\xA1-\uFFFF]} $part ch]} {
		    scan $ch %c c
		    if {$ch < "!" || $ch > "~"} {
			set ch [format "\\u%04x" $c]
		    }
		    throw [list IDNA INVALID_NAME_CHARACTER $ch] \
			"bad character \"$ch\" in DNS name"
		}
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
47
48
49
50
51
52
53

54
55
56
57
58
59
60
61







-
+







	    lappend parts $part
	}
	return [join $parts .]
    }
    proc IDNAdecode hostname {
	set parts {}
	# Split term from RFC 3490, Sec 3.1
	foreach part [split $hostname "\u002E\u3002\uFF0E\uFF61"] {
	foreach part [split $hostname "\x2E\u3002\uFF0E\uFF61"] {
	    if {[string match -nocase "xn--*" $part]} {
		set part [punydecode [string range $part 4 end]]
	    }
	    lappend parts $part
	}
	return [join $parts .]
    }
112
113
114
115
116
117
118
119

120
121
122
123
124
125
126
112
113
114
115
116
117
118

119
120
121
122
123
124
125
126







-
+







	# Initialize the state:
	set n $initial_n
	set delta 0
	set bias $initial_bias

	# Handle the basic code points:
	foreach ch $string {
	    if {$ch < "\u0080"} {
	    if {$ch < "\x80"} {
		if {$case eq ""} {
		    append output $ch
		} elseif {[string is true $case]} {
		    append output [string toupper $ch]
		} elseif {[string is false $case]} {
		    append output [string tolower $ch]
		}

Added library/cookiejar/public_suffix_list.dat.gz.

cannot compute difference between binary files

Changes to library/dde/pkgIndex.tcl.

1
2

3











1
2

3
4
5
6
7
8
9
10
11
12
-

+
-
+
+
+
+
+
+
+
+
+
+
if {![package vsatisfies [package provide Tcl] 8.5-]} return
if {[info sharedlibextension] != ".dll"} return
if {[package vsatisfies [package provide Tcl] 9.0-]} {
package ifneeded dde 1.4.3 [list load [file join $dir tcldde14.dll] dde]
    package ifneeded dde 1.4.5 \
	    [list load [file join $dir tcl9dde14.dll] Dde]
} elseif {![package vsatisfies [package provide Tcl] 8.7]
	&& [::tcl::pkgconfig get debug]} {
    package ifneeded dde 1.4.5 \
	    [list load [file join $dir tcldde14g.dll] Dde]
} else {
    package ifneeded dde 1.4.5 \
	    [list load [file join $dir tcldde14.dll] Dde]
}

Changes to library/encoding/ascii.enc.

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







# Encoding file: ascii, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E0000
0070007100720073007400750076007700780079007A007B007C007D007E007F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000

Changes to library/encoding/big5.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20
21












-
-
+
+







# Encoding file: big5, multi-byte
M
003F 0 89
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
A1

Added library/encoding/cns11643.enc.

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# Encoding file: cns11643, double-byte
D
2134 0 93
21
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00004E284E364E3F4E854E054E04518251965338536953B64E2A4E874E4951E2
4E464E8F4EBC4EBE516651E35204529C53B95902590A5B805DDB5E7A5E7F5EF4
5F505F515F61961D4E3C4E634E624EA351854EC54ECF4ECE4ECC518451865722
572351E45205529E529D52FD5300533A5C735346535D538653B7620953CC6C15
53CE57216C3F5E005F0C623762386534653565E04F0E738D4E974EE04F144EF1
4EE74EF74EE64F1D4F024F054F2256D8518B518C519951E55213520B52A60000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
22
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000053225304530353075407531E535F536D538953BA53D0598053F653F753F9
597E53F4597F5B565724590459185932593059345DDF59755E845B825BF95C14
5FD55FD45FCF625C625E626462615E815E835F0D5F52625A5FCA5FC7623965EE
624F65E7672F6B7A6C39673F673C6C376C446C45738C75927676909390926C4B
6C4C4E214E204E224E684E894E984EF94EEF7F5182784EF84F064F034EFC4EEE
4F1690994F284F1C4F074F1A4EFA4F17514A962351724F3B51B451B351B20000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
23
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00004F6451E84F675214520F5215521852A84F33534B534F518F5350521C538B
522153BE52AE53D2541653FF538E540054305405541354155445541956E35735
57365731573258EE59054E545447593656E756E55741597A574C5986574B5752
5B865F535C1859985C3D5C78598E59A25990598F5C8059A15E085B925C285C2A
5C8D5EF55F0E5C8B5C895C925FD35FDA5C935FDB5DE0620F625D625F62676257
9F505E8D65EB65EA5F7867375FD2673267366B226BCE5FEE6C586C516C770000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
24
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006C3C5FFA6C5A5FF76C53706F7072706E6283628C707372B172B26287738F
627B627A6270793C6288808D808E6272827B65F08D718FB99096909A67454E24
4E7167554E9C4F454F4A4F394F37674B4F324F426C1A4F444F4B6C6B4F404F35
4F3151516C6F5150514E6C6D6C87519D6C9C51B551B851EC522352275226521F
522B522052B452B372C65325533B537473957397739373947392544D75397594
543A7681793D5444544C5423541A5432544B5421828F54345449545054220000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
25
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000543F5451545A542F8FC956E956F256F356EF56ED56EC56E6574896285744
573F573C575357564F85575F5743575857574F744F894F8457464F4C573D4F6A
57425754575558F158F258F0590B9EA656F1593D4F955994598C519E599C51BE
5235599F5233599B52315989599A530B658853925B8D54875BFE5BFF5BFD5C2B
54885C845C8E5C9C5465546C5C855DF55E09546F54615E0B54985E925E905F03
56F75F1E5F6357725FE75FFE5FE65FDC5FCE57805FFC5FDF5FEC5FF657620000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
26
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00005FF25FF05FF95945621359BA59CF623B623C628259C159B659BC6278628B
59B1629E62A5629B629C6299628D6285629D62755C445C475CAE65F65CA05CB5
5CAF66F5675B5C9F675467525CA267586744674A67615CB66C7F6C916C9E5E14
6C6E6C7C6C9F6C755F246C566CA26C795F7D6CA15FE56CAA6CA0601970797077
707E600A7075707B7264601E72BB72BC72C772B972BE72B66011600C7398601C
6214623D62AD7593768062BE768376C076C162AE62B377F477F562A97ACC0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
27
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00007ACD7CFA809F80918097809466048286828C65FB8295660B866C66058FB5
8FBE8FC766F68FC190A990A4678E6792677690A896279626962B963396349629
4E3D679F4E9D4F934F8A677D67814F6D4F8E4FA04FA24FA14F9F4FA36C1D4F72
6CEC4F8C51566CD96CB651906CAD6CE76CB751ED51FE522F6CC3523C52345239
52B952B552BF53556C9D5376537A53936D3053C153C253D554856CCF545F5493
548954799EFE548F5469546D70915494546A548A708356FD56FB56F872D80000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
28
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000056FC56F6576557815763576772D1576E5778577F73A673A258F3594B594C
74DD74E8753F59AD753E59C4759859C259B076F176F076F577F859BF77F959C9
59B859AC7942793F79C559B759D77AFB5B607CFD5B965B9E5B945B9F5B9D80B5
5C005C1982A082C05C495C4A82985CBB5CC182A782AE82BC5CB95C9E5CB45CBA
5DF65E135E125E7782C35E9882A25E995E9D5EF8866E5EF98FD25F065F218FCD
5F255F558FD790B290B45F845F8360306007963D6036963A96434FCD5FE90000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
29
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000603D60084FC94FCB62BA62B24FDC62B762E462A74FDB4FC74FD662D562E1
62DD62A662C162C562C062DF62E062DE53976589539965A665BA54A165FF54A5
66176618660165FE54AE670C54B6676B67966782678A54BC67A354BE67A2678F
54B067F967806B266B276B686B69579D6B816BB46BD1578F57996C1C579A5795
58F4590D59536C976C6C6CDF5A006CEA59DD6CE46CD86CB26CCE6CC859F2708B
70887090708F59F570877089708D70815BA8708C5CD05CD872405CD75CCB0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
2A
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00007265726672685CC95CC772CD72D372DB5CD472CF73A773A3739E5CDF73AF
5DF95E2173AA739C5E2075427544753B75415E9B759B759E5F0779C479C379C6
6037603979C7607279CA604560537ACF7C767C747CFF7CFC6042605F7F5980A8
6058606680B0624280B362CF80A480B680A780AC630380A65367820E82C4833E
829C63006313631462FA631582AA62F082C9654365AA82A682B2662166326635
8FCC8FD98FCA8FD88FCF90B7661D90AD90B99637670F9641963E96B697510000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
2B
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000097634E574E794EB24EB04EAF4EB14FD24FD567E44FBE4FB84FB04FB14FC8
67F667EE4FC64FCC4FE54FE34FB4516A67B2519F67C651C167CC51C251C35245
524867C967CA524F67EA67CB52C552CA52C453275358537D6BE053DD53DC53DA
53D954B96D1F54D054B454CA6D0A54A354DA54A46D1954B2549E549F54B56D1D
6D4254CD6D1854CC6D03570057AC5791578E578D579257A1579057A657A8709F
579C579657A770A170B470B570A958F572495909590872705952726E72CA0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
2C
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000059DF72E859EB59EF59F059D55A0D5A0459F95A0259F859E259D959E75B6A
73B473EB5BAB73C75C1B5C2F73C6663C73CB74EC74EE5CD15CDC5CE65CE15CCD
76795CE25CDD5CE55DFB5DFA5E1E76F75EA176FA77E75EFC5EFB5F2F78127805
5F66780F780E7809605C7813604E6051794B794560236031607C605279D66060
604A60617AD162187B017C7A7C787C797C7F7C807C81631F631762EA63216304
63057FBE6531654465408014654265BE80C76629661B80C86623662C661A0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
2D
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006630663B661E6637663880C9670E80D780E667E867D6822167C767BC6852
67BF67D567FE836367FB833A67B168016805680067D782F26B2A6B6B82FB82F6
82F082EA6BE182E082FA6D236CFF6D146D056D136D066D21884E6D156CAF6CF4
6D026D458A076D268FE36D448FEE6D2470A590BD70A390D570A270BB70A070AA
90C891D470A870B670B270A79653964A70B9722E5005723C5013726D5030501B
72E772ED503372EC72E572E24FF773C473BD73CF73C973C173D0503173CE0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
2E
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000074ED74EB519374EF754975507546754A5261754D75A6525E525F525575A8
52CD530E76C776FF54E276FD77E6780A54F37804780B78075504781578085511
79D379D479D079D77A7C54F854E07A7D7A837A8257017AD47AD57AD37AD07AD2
7AFE7AFC7C777C7C7C7B57B657BF57C757D057B957C1590E594A7F8F80D35A2D
80CB80D25A0F810980E280DF80C65B6C822482F782D882DD5C565C5482F882FC
5CEE5CF182E95D0082EE5E2982D0830E82E2830B82FD517986765F6786780000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
2F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000605A60678675867D6088884288666081898C8A0560958A0660978C9F609C
8FF18FE78FE98FEF90C290BC632C90C690C06336634390CD90C9634B90C4633C
958163419CEC50324FF9501D4FFF50044FF05003635150024FFC4FF250245008
5036502E65C35010503850394FFD50564FFB51A351A651A1681A684951C751C9
5260526452595265526752575263682B5253682F52CF684452CE52D052D152CC
68266828682E550D54F46825551354EF54F554F9550255006B6D808255180000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
30
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000054F054F66BE86BE355196BE7570557C96D6357B757CD6D0D6D616D9257BE
57BB6D6D57DB57C857C457C557D157CA57C06D676D605A215A2A6D7C5A1D6D82
5A0B6D2F6D686D8B6D7E5A226D846D165A246D7B5A145A316D905A2F5A1A5A12
70DD70CB5A2670E270D75BBC5BBB5BB75C055C065C525C5370C770DA5CFA5CEB
72425CF35CF55CE95CEF72FA5E2A5E305E2E5E2C5E2F5EAF5EA973D95EFD5F32
5F8E5F935F8F604F609973D2607E73D46074604B6073607573E874DE60560000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
31
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000060A9608B60A6755B609360AE609E60A7624575C075BF632E75BA63526330
635B771B6319631B77126331635D6337633563537722635C633F654B78227835
658B7828659A66506646664E6640782A664B6648795B66606644664D79526837
682479EC79E0681B683679EA682C681968566847683E681E7A8B681568226827
685968586855683068236B2E6B2B6B306B6C7B096B8B7C846BE96BEA6BE56D6B
7C8D7C856D736D577D117D0E6D5D6D566D8F6D5B6D1C6D9A6D9B6D997F610000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
32
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006D816D717F5D7F5B6D726D5C6D9670C470DB70CC70D070E370DF80F270D6
70EE70D580FB81008201822F727A833372F573028319835173E273EC73D573F9
73DF73E683228342834E831B73E473E174F3834D831683248320755675557558
7557755E75C38353831E75B4834B75B18348865376CB76CC772A86967716770F
869E8687773F772B770E772486857721771877DD86A7869578247836869D7958
79598843796279DA79D9887679E179E579E879DB886F79E279F08874887C0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
33
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00008A128C477ADA7ADD8CA47ADB7ADC8D788DB57B0D7B0B7B147C8E7C868FF5
7C877C837C8B90048FFC8FF690D67D2490D990DA90E37D257F627F937F997F97
90DC90E47FC47FC6800A91D591E28040803C803B80F680FF80EE810481038107
506A506180F750605053822D505D82278229831F8357505B504A506250158321
505F506983188358506450465040506E50738684869F869B868986A68692868F
86A0884F8878887A886E887B88848873555055348A0D8A0B8A19553655350000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
34
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000553055525545550C8FF990099008553990DE9151553B554091DB91DF91DE
91D691E095859660965957F4965657ED57FD96BD57F8580B5042505958075044
50665052505450715050507B507C505857E758015079506C507851A851D151CF
5268527652D45A5553A053C45A385558554C55685A5F55495A6C5A53555D5529
5A43555455535A44555A5A48553A553F552B57EA5A4C57EF5A695A4757DD57FE
5A4257DE57E65B6E57E857FF580358F768A6591F5D1A595B595D595E5D0D0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
35
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00005D265A2B5D0F5A3B5D125D235A615A3A5A6E5A4B5A6B5EB45EB95A455A4E
5A685A3D5A715A3F5A6F5A7560905A735A2C5A595A545A4F5A6360CF60E45BC8
60DD5BC360B15C5B5C6160CA5D215D0A5D0960C05D2C5D08638A63825D2A5D15
639E5D105D1363975D2F5D18636F5DE35E395E355E3A5E32639C636D63AE637C
5EBB5EBA5F345F39638563816391638D6098655360D066656661665B60D760AA
666260A160A4688760EE689C60E7686E68AE60DE6956686F637E638B68A90000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
36
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000687563796386639368776373636A686B636C68AA637F687163B263BA6896
688B6366637468A4655A687B654E654D658D658E65AD6B3365C765CA6B9165C9
6B8D65E366576C2A66636667671A671967166DAC6DE9689E68B6689868736E00
689A688E68B768DB68A5686C68C168846DDB6DF46895687A68996DF068B868B9
68706DCF6B356DD06B906BBB6BED6DD76DCD6DE36DC16DC36DCE70F771176DAD
6E0470F06DB970F36DE770FC6E086E0671136E0A6DB070F66DF86E0C710E0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
37
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006DB1727B6E026E076E096E016E176DFF6E12730A730871037107710170F5
70F1710870F2710F740170FE7407740073FA731A7310730E740273F374087564
73FB75CE75D275CF751B752375617568768F756775D37739772F769077317732
76D576D776D67730773B7726784877407849771E784A784C782678477850784B
7851784F78427846796B796E796C79F279F879F179F579F379F97A907B357B3B
7A9A7A937A917AE17B247B337B217B1C7B167B177B367B1F7B2F7C937C990000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
38
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00007C9A7C9C7C947D497C967D347D377D3D7D2D7D367D4C7D457D2C7D487D41
7D477F3B7D3F7D4A7D3B7D288008801A7F9C801D7F9B8049804580447C9B7FD1
7FC7812A812E801F801E81318047811A8134811781258119811B831D83718384
8380837283A18127837983918211839F83AD823A8234832382748385839C83B7
8658865A8373865786B2838F86AE8395839983758845889C889488A3888F88A5
88A988A6888A88A0889089928991899483B08A268A328A2883AE83768A1C0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
39
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000086568A2B8A2086C28A2986C586BA86B08A218C3A86B38C5B8C588C7C86BB
8CA68CAE8CAD8D6588528D7E88958D7C8D7F8D7A8DBD889188A18DC08DBB8EAD
8EAF8ED6889788A488AC888C88938ED9898289D69012900E90258A27901390EE
8C3990AB90F78C5D9159915491F291F091E591F68DC28DB995878DC1965A8EDE
8EDD966E8ED78EE08EE19679900B98E198E6900C9EC49ED24E8090F04E81508F
50975088508990EC90E950815160915A91535E4251D391F491F151D251D60000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
3A
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000527391F9527091EB91F791E853A853A653C5559755DE966D966B559655B4
96BF55859804559B55A0509B555950945586508B50A355AF557A508E509D5068
559E509255A9570F570E581A5312581F53A4583C5818583E582655AD583A5645
5822559358FB5963596455815AA85AA35A825A885AA15A855A9855955A99558E
5A895A815A965A80581E58275A91582857F5584858255ACF581B5833583F5836
582E58395A875AA0582C5A7959615A865AAB5AAA5AA45A8D5A7E5A785BD50000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
3B
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00005A7C5AA55AAC5C1E5C5F5C5E5D445D3E5A975D485D1C5AA95D5B5D4D5A8C
5A9C5D575A935D535D4F5BCD5D3B5D465BD15BCA5E465E475C305E485EC05EBD
5EBF5D4B5F115D355F3E5F3B5D555F3A5D3A5D525D3D5FA75D5960EA5D396107
6122610C5D325D3660B360D660D25E4160E360E560E95FAB60C9611160FD60E2
60CE611E61206121621E611663E263DE63E660F860FC60FE60C163F8611863FE
63C163BF63F763D1655F6560656163B063CE65D163E863EF667D666B667F0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
3C
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000063CA63E066736681666D6669646163DF671E68ED63DC63C463D863D36903
63C768FE68E5691E690263D763D9690968CA690065646901691868E268CF659D
692E68C568FF65D2691C68C3667B6B6F66716B6E666A6BBE67016BF46C2D6904
6DB66E756E1E68EA6E18690F6E4868F76E4F68E46E426E6A6E706DFE68E16907
6E6D69086E7B6E7E6E5968EF6E5769146E806E5068FD6E296E766E2A6E4C712A
68CE7135712C7137711D68F468D1713868D47134712B7133712771246B3B0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
3D
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000712D7232728372827287730673247338732A732C732B6DFC732F73287417
6E496E88741974386E45741F7414743C73F7741C74157418743974F975246E51
6E3B6E03756E756D7571758E6E6175E56E286E606E716E6B769476B36E3076D9
6E657748774977436E776E55774277DF6E66786378766E5A785F786679667971
712E713179767984797579FF7A0771287A0E7A09724B725A7288728972867285
7AE77AE27B55733073227B437B577B6C7B427B5373267B417335730C7CA70000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
3E
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00007CA07CA67CA47D74741A7D59742D7D607D577D6C7D7E7D6474207D5A7D5D
752F756F756C7D767D4D7D7575E67FD37FD675E475D78060804E8145813B7747
814881428149814081148141774C81EF81F68203786483ED785C83DA841883D2
8408787084007868785E786284178346841483D38405841F8402841683CD83E6
7AE6865D86D586E17B447B487B4C7B4E86EE884788467CA27C9E88BB7CA188BF
88B47D6388B57D56899A8A437D4F7D6D8A5A7D6B7D527D548A358A388A420000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
3F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00008A498A5D8A4B8A3D7F667FA27FA07FA18C608C5E8C7F8C7E8C8380D48CB1
8D878152814F8D888D83814D813A8D868D8B8D828DCA8DD28204823C8DD48DC9
8EB0833B83CF83F98EF28EE48EF38EEA83E78EFD83FC8F9D902B902A83C89028
9029902C840183DD903A90309037903B83CB910A83D683F583C991FE922083DE
920B84069218922283D5921B920883D1920E9213839A83C3959583EE83C483FB
968C967B967F968183FE968286E286E686D386E386DA96EE96ED86EB96EC0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
40
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000975F976F86D7976D86D188488856885588BA88D798F088B888C088BE9AA9
88BC88B79AE04EB7890188C950CC50BC899750AA50B989DB50AB50C350CD517E
527E52798A588A4452E152E052E7538053AB53AA53A953E055EA8C8055D78CBE
8CB055C157158D84586C8D89585C58505861586A5869585658605866585F5923
596659688EEF8EF75ACE8EF95AC55AC38EE58EF55AD08EE88EF68EEB8EF18EEC
8EF45B745B765BDC5BD75BDA5BDB91045C205D6D5D6690F95D645D6E91000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
41
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00005D605F425F5A5F6E9164915F6130613A612A614361196131921A613D920F
920C92006408643264389206643192276419921C6411921992176429641D957B
958D958C643C96876446644796899683643A640796C8656B96F16570656D9770
65E4669398A998EB9CE69EF9668F4E844EB6669250BF668E50AE694650CA50B4
50C850C250B050C150BA693150CB50C9693E50B8697C694352786973527C6955
55DB55CC6985694D69506947696769366964696155BF697D6B446B406B710000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
42
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006B736B9C55C855F255CD6BC155C26BFA6C316C325864584F6EB86EA8586F
6E916EBB585D6E9A5865585B6EA9586358716EB56E6C6EE85ACB6EDD6EDA6EE6
6EAC5AB05ABF5AC86ED96EE36EE96EDB5ACA716F5AB65ACD71485A90714A716B
5BD9714F715771745D635D4A5D6571457151716D5D6872517250724E5E4F7341
5E4A732E73465EC574275EC674487453743D5FAF745D74566149741E74477443
74587449612E744C7445743E61297501751E91686223757A75EE760276970000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
43
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00007698641064126409775D77647753775878827890788A6439787A787D6423
788B787864306428788D788878927881797E798364256427640B7980641B642E
64217A0F656F65927A1D66867AA17AA466907AE97AEA66997B627B6B67207B5E
695F7B79694E69627B6F7B686945696A7CAE6942695769597CB069487D906935
7D8A69337D8B7D997D9569787D877D787D977D897D986976695869417FA3694C
693B694B7FDD8057694F8163816A816C692F697B693C815D81756B43815F0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
44
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006B48817D816D6BFB6BFC8241844F84846E9B847F6EC88448842A847B8472
8464842E845C84536EC6844184C86EC184628480843E848384716EA6844A8455
84586EC36EDC6ED886FC86FD87156E8D871686FF6EBF6EB36ED0885888CF88E0
6EA371477154715289E78A6A8A80715D8A6F8A6571788A788A7D8A8871587143
8A648A7E715F8A678C638C88714D8CCD724F8CC9728C8DED7290728E733C7342
733B733A73408EB1734974448F048F9E8FA090439046904890459040904C0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
45
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000074427446910C9113911574FF916B9167925D9255923569839259922F923C
928F925C926A9262925F926B926E923B92449241959A7699959976DD7755775F
968F77529696775A7769776796F496FC776D9755788797797894788F788497EE
97F57886980B788398F37899788098F798FF98F5798298EC98F17A117A18999A
7A129AE29B3D9B5D9CE87A1B9CEB9CEF9CEE9E819F1450D050D950DC50D87B69
50E150EB7B737B7150F450E250DE7B767B637CB251F47CAF7D887D8652ED0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
46
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000052EA7D7F53327D7A53AE53B07D8355FB5603560B7D8456077D9255F87F6B
5628561E7F6C5618561156515605571758928164588C817758785884587358AD
58975895587758725896588D59108161596C82495AE782405AE4824584F15AEF
5626847684795AF05D7B84655D83844084865D8B5D8C844D5D785E5284598474
5ED05ECF85075FB35FB4843A8434847A617B8478616F6181613C614261386133
844261606169617D6186622C62288452644C84C56457647C8447843664550000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
47
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000064626471646A6456643B6481846E644F647E646486F7870C86FA86D686F5
657186F8870E66A5669A669C870D66A688D666A4698F69C569C8699269B288CC
88D0898569E369C069D669D1699F69A269D289DC89E68A7669E169D5699D8A3F
8A7769988A846B746BA18A816EF06EF38C3C8C4B6F1B6F0C6F1D6F346F286F17
8C856F446F426F046F116EFA6F4A7191718E8D93718B718D717F718C717E717C
71838DEE71888DE98DE372948DE773557353734F7354746C7465746674610000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
48
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000746B746874768F0B7460903F74747506760E91107607910F911176B99114
76B776E2916E7774777777767775923A777877719265777A715B777B78A678AE
78B8926C924F926078B178AF923679897987923192547A2992507A2A924E7A2D
7A2C92567A32959F7AEC7AF07B817B9E7B8396917B9296CE7BA37B9F7B9396F5
7B867CB87CB79772980F980D980E98AC7DC87DB699AF7DD199B07DA87DAB9AAB
7DB37DCD9CED7DCF7DA49EFD50E67F417F6F7F7150F350DB50EA50DD50E40000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
49
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000050D38023805B50EF8061805F818152805281818482135330824A824C5615
560C561284BD8495561C849284C35602849684A584B584B384A384E484D884D5
589884B784AD84DA84938736587A58875891873D872B87478739587B8745871D
58FE88FF88EA5AEE88F55AD5890088ED890388E95AF35AE289EA5ADB8A9B8A8E
8AA25AD98A9C8A948A908AA98AAC5C638A9F5D805D7D8A9D5D7A8C675D775D8A
8CD08CD68CD48D988D9A8D975D7F5E585E598E0B8E088E018EB48EB35EDC0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
4A
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00008FA18FA25ED2905A5F449061905F5FB6612C9125917B9176917C61739289
92F692B192AD929292819284617A92AE9290929E616A6161615695A295A7622B
642B644D645B645D96A0969D969F96D0647D96D1646664A6975964829764645C
644B64539819645098149815981A646B645964656477990665A098F89901669F
99BE99BC99B799B699C069C999B869CE699669B099C469BC99BF69999ADA9AE4
9AE99AE89AEA9AE569BF9B2669BD69A49B4069B969CA699A69CF69B369930000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
4B
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000069AA9EBD699E69D969976990510E69B550F769C650FC510D510151DA51D9
51DB5286528E52EE533353B16EF15647562D56546F37564B5652563156445656
5650562B6F18564D5637564F58A258B76F7358B26EEE58AA58B558B06F3C58B4
58A458A76F0E59265AFE6EFD5B046F395AFC6EFC5B065B0A5AFA5B0D5B005B0E
7187719071895D9171855D8F5D905D985DA45D9B5DA35D965DE45E5A72957293
5E5E734D5FB86157615C61A661956188747261A3618F75006164750361590000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
4C
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006178761661856187619E7611760A6198619C7781777C622F6480649B648E
648D649464C678B264A8648378AD64B9648664B464AF649178A064AA64A164A7
66B666B3798B66BC66AC799466AD6A0E79886A1C6A1A7A2B7A4A6A0B7A2F69EF
6A0C69F06A227AAC69D87B886A1269FA7B916A2A7B966A107B8C7B9B6A2969F9
69EA6A2C6A247BA469E96B526B4F6B537CBA7DA76F106F656F757DAA7DC17DC0
7DC56FD07DCE6F5C6F3D6F717DCC6F916F0B6F796F816F8F7DA66F596F740000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
4D
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00007DA171AE7F7371A371AD7FE57FDE71AB71A671A2818952F2725772557299
734B747A8215849784A4748C748484BA84CE74827493747B84AB750984B484C1
84CD84AA849A84B1778A849D779084BB78C678D378C078D278C778C284AF799F
799D799E84B67A4184A07A387A3A7A4284DB84B07A3E7AB07BAE7BB38728876B
7BBF872E871E7BCD87197BB28743872C8741873E8746872087327CC47CCD7CC2
7CC67CC37CC97CC787427DF887277DED7DE2871A873087117DDC7E027E010000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
4E
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000088F27DD688FE7DE47DFE88F67E007DFC7DFD88EB7DF57DFF899F7DEB7DE5
7F787FAE7FE78A998065806A80668068806B819481A18192819681938D968E09
85018DFF84F88DFD84F58E0385048E068E058DFE8E00851B85038533853484ED
9123911C853591228505911D911A91249121877D917A91729179877192A5885C
88E6890F891B92A089A989A589EE8AB1929A8ACC8ACE92978AB792A38AB58AE9
8AB492958AB38AC18AAF8ACA8AD09286928C92998C8E927E92878CE98CDB0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
4F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000928B8CEB8DA496A18DA28D9D977D977A977E97838E2A8E28977B97848EB8
8EB68EB98EB78F228F2B8F278F198FA499078FB3999C9071906A99BB99BA9188
918C92BF92B892BE92DC92E59B3F9B6092D492D69CF192DA92ED92F392DB5103
92B992E292EB95AF50F695B295B3510C50FD510A96A396A552F152EF56485642
970A563597879789978C97EF982A98225640981F563D9919563E99CA99DA563A
571A58AB99DE99C899E058A39AB69AB558A59AF458FF9B6B9B699B729B630000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
50
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00005AF69D0D5AF89D019D0C5B019CF85B055B0F9CFE9D029E845D9F9EAB9EAA
511D51165DA0512B511E511B5290529453145E605E5C56675EDB567B5EE1565F
5661618B6183617961B161B061A2618958C358CA58BB58C058C459015B1F5B18
5B115B1561B35B125B1C64705B225B795DA664975DB35DAB5EEA648A5F5B64A3
649F61B761CE61B961BD61CF61C06199619765B361BB61D061C4623166B764D3
64C06A006A066A1769E564DC64D164C869E464D566C369EC69E266BF66C50000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
51
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000069FE66CD66C167066A1467246A636A426A5269E66A436A3369FC6A6C6A57
6A046A4C6A6E6A0F69F66A266A0769F46A376B516A716A4A6A366BA66A536C00
6A456A706F416F266A5C6B586B576F926F8D6F896F8C6F626F4F6FBB6F5A6F96
6FBE6F6C6F826F556FB56FD36F9F6F576FB76FF571B76F0071BB6F6B71D16F67
71BA6F5371B671CC6F7F6F9571D3749B6F6A6F7B749674A2749D750A750E719A
7581762C76377636763B71A476A171AA719C779871B37796729A735873520000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
52
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000078D678EB736078DC735B79A579A998347A537A4574897A4F74867ABD7ABB
7AF17488747C7BEC7BED7507757E7CD3761E7CE1761D7E197623761A76287E27
7E26769D769E806E81AF778F778981AD78CD81AA821878CC78D178CE78D4856F
854C78C48542799A855C8570855F79A2855A854B853F878A7AB4878B87A1878E
7BBE7BAC8799885E885F892489A78AEA8AFD8AF98AE38AE57DDB7DEA8AEC7DD7
7DE17E037DFA8CF27DF68CEF7DF08DA67DDF7F767FAC8E3B8E437FED8E320000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
53
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00008F318F307FE68F2D8F3C8FA78FA5819F819E819591379195918E82169196
82539345930A824E825192FD9317931C930793319332932C9330930393058527
95C284FB95B884FA95C1850C84F4852A96AB96B784F784EB97159714851284EA
970C971784FE9793851D97D2850284FD983698319833983C982E983A84F0983D
84F998B5992299239920991C991D866299A0876399EF99E899EB877387588754
99E199E68761875A9AF89AF5876D876A9B839B949B84875D9B8B9B8F877A0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
54
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009B8C875C9B89874F9B8E8775876287679D249D0F89059D139D0A890B8917
891889199D2A9D1A89119D279D169D2189A49E859EAC9EC69EC59ED79F538AB8
5128512751DF8AD5533553B38ABE568A567D56898AC358CD58D08AD95B2B5B33
5B295B355B315B375C365DBE8CDD5DB98DA05DBB8DA161E261DB61DD61DC61DA
8E2E61D98E1B8E1664DF8E198E2664E18E1464EE8E1865B566D466D58E1A66D0
66D166CE66D78F208F236A7D6A8A90736AA7906F6A996A826A88912B91290000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
55
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006A8691326A986A9D918591866A8F91816AAA91846B5D92D06C0A92C46FD7
6FD66FE592CF92F192DF6FD96FDA6FEA92DD6FF692EF92C271E392CA71E992CE
71EB71EF71F371EA92E092DE92E792D192D3737192E174AE92C674B3957C74AC
95AB95AE75837645764E764476A376A577A677A4978A77A977AF97D097CF981E
78F078F878F198287A49981B982798B27AC27AF27AF37BFA99167BF67BFC7C18
7C087C1299D399D47CDB7CDA99D699D899CB7E2C7E4D9AB39AEC7F467FF60000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
56
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000802B807481B881C89B679B749B71859285939B75857F85AB85979B6C9CFC
85AC9CFD9CFF9CF787CE9D0087CD9CFB9D0887C187B187C79ED389409F10893F
893951178943511151DE533489AB56708B1F8B098B0C566656638C4056728C96
56778CF68CF758C88E468E4F58BF58BA58C28F3D8F4193669378935D93699374
937D936E93729373936293489353935F93685DB1937F936B5DB595C45DAE96AF
96AD96B25DAD5DAF971A971B5E685E665E6F5EE9979B979F5EE85EE55F4B0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
57
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00005FBC5FBB619D61A86196984061B4984761C198B761BA61BF61B8618C64D7
99A264D064CF9A0099F3648964C399F564F364D99ABD9B009B0265A29B349B49
9B9F66CA9BA39BCD9B999B9D66BA66CC9D396A349D446A496A679D356A686A3E
9EAF6A6D512F6A5B6A519F8E6A5A569F569B569E5696569456A06A4F5B3B6A6F
6A695B3A5DC15F4D5F5D61F36A4D6A4E6A466B5564F664E564EA64E765056BC8
64F96C046C036C066AAB6AED6AB26AB06AB56ABE6AC16AC86FC46AC06ABC0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
58
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006AB16AC46ABF6FA56FAE700870036FFD7010700270136FA271FA720074B9
74BC6FB2765B7651764F76EB77B871D677B977C177C077BE790B71C77907790A
790871BC790D7906791579AF729E736973667AF5736C73657C2E736A7C1B749A
7C1A7C24749274957CE67CE37580762F7E5D7E4F7E667E5B7F477FB476327630
76BB7FFA802E779D77A181CE779B77A282197795779985CC85B278E985BB85C1
78DE78E378DB87E987EE87F087D6880E87DA8948894A894E894D89B189B00000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
59
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000089B37AB78B388B327BE78B2D7BD58B347BDA8B298C747BD47BEA8D037BDC
7BEB8DA98E587CD27CD48EBF8EC18F4A8FAC7E219089913D913C91A993A07E0E
93907E159393938B93AD93BB93B87E0D7E14939C95D895D77F7B7F7C7F7A975D
97A997DA8029806C81B181A6985481B99855984B81B0983F98B981B281B781A7
81F29938993699408556993B993999A4855385619A089A0C85469A1085419B07
85449BD285479BC29BBB9BCC9BCB854E856E9D4D9D639D4E85609D509D550000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
5A
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000855D9D5E85659E909EB29EB186649ECA9F029F279F26879356AF58E058DC
87965B39877987875B7C5BF3879087915C6B5DC4650B6508650A8789891E65DC
8930892D66E166DF6ACE6AD46AE36AD76AE2892C891F89F18AE06AD86AD56AD2
8AF58ADD701E702C70256FF37204720872158AE874C474C974C774C876A977C6
77C57918791A79208CF37A667A647A6A8DA78E338E3E8E388E408E457C357C34
8E3D8E417E6C8E3F7E6E7E718F2E81D481D6821A82628265827685DB85D60000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
5B
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000908685E79133913585F4919387FD87D58807918F880F87F89308931F8987
930F89B589F5933C8B3F8B438B4C93018D0B8E6B8E688E708E758E7792FA8EC3
92F993E993EA93CB93C593C6932993ED93D3932A93E5930C930B93DB93EB93E0
93C1931695BC95DD95BE95B995BA95B695BF95B595BD96A996D497B297B497B1
97B597F2979497F097F89856982F98329924994499279A269A1F9A189A219A17
99E49B0999E399EA9BC59BDF9AB99BE39AB49BE99BEE9AFA9AF99D669D7A0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
5C
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009B809D6E9D919D839D769D7E9D6D9B939E959EE39B7A9B959F039F049D25
9F179D2051369D1453369D1D5B429D229D105B445B465B7E5DCA5DC85DCC5EF0
9ED5658566E566E79F3D512651256AF451246AE9512952F45693568C568D703D
56847036567E7216567F7212720F72177211720B5B2D5B2574CD74D074CC74CE
74D15B2F75895B7B7A6F7C4B7C445E6C5E6A5FBE61C361B57E7F8B7161E0802F
807A807B807C64EF64E964E385FC861086026581658085EE860366D2860D0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
5D
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000086138608860F881888126A9B6AA18967896589BB8B698B626A838B6E6AA4
8B616A7F8B648B4D8C516A8C6A928E838EC66C09941F6FA99404941794089405
6FED93F3941E9402941A941B9427941C71E196B571E871F2973371F097349731
97B897BA749797FC74AB749098C374AD994D74A59A2F7510751175129AC97584
9AC89AC49B2A9B389B5076E99C0A9BFB9C049BFC9BFE77B477B177A89C029BF6
9C1B9BF99C159C109BFF9C009C0C78F978FE9D959DA579A87A5C7A5B7A560000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
5E
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009E989EC17A5A9F5A516456BB7C0558E65B495BF77BFF7BFB5DD07BF45FC2
7BF365117C096AFF6AFE6AFD7BFD6B017BF07BF1704B704D704774D376687667
7E33984877D179307932792E7E479F9D7AC97AC87E3B7C567C517E3A7F457F7F
7E857E897E8E7E84802C826A862B862F862881C586168615861D881A825A825C
858389BC8B758B7C85958D118D128F5C91BB85A493F4859E8577942D858985A1
96E497379736976797BE97BD97E29868986698C898CA98C798DC8585994F0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
5F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000099A99A3C85909A3B9ACE87BE9B149B5387C59C2E87AC9C1F87B587BC87AE
87C99DB09DBD87CC87B79DAE9DC49E7B87B487B69E9E87B89F0587DE9F699FA1
56C7571D5B4A5DD389525F72620289AD62356527651E651F8B1E8B186B076B06
8B058B0B7054721C72207AF88B077C5D7C588B067E927F4E8B1A8C4F8C708827
8C718B818B838C948C448D6F8E4E8E4D8E539442944D9454944E8F409443907E
9138973C974097C09199919F91A1919D995A9A5193839ADD936493569C380000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
60
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000937C9C459C3A93769C359350935193609EF1938F9F93529A937993578641
5DD7934F65289377937B936170537059936772219359766F793779B57C627C5E
7CF596AE96B0863D9720882D89898B8D8B878B908D1A8E99979E979D97D5945F
97F1984194569461945B945A945C9465992B9741992A9933986E986C986D9931
99AA9A5C9A589ADE9A029C4F9C5199F79C5399F899F699FB9DFC9F3999FC513E
9ABE56D29AFD5B4F6B149B487A727A739B9E9B9B9BA68B919BA59BA491BF0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
61
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009BA2946C9BAF9D3396E697459D3697C897E4995D9D389B219D459B2C9B57
9D3E9D379C5D9C619C659E089E8A9E899E8D9EB09EC89F459EFB9EFF620566EF
6B1B6B1D722572247C6D512E8642864956978978898A8B9759708C9B8D1C5C6A
8EA25E6D5E6E61D861DF61ED61EE61F161EA9C6C61EB9C6F61E99E0E65049F08
9F1D9FA3650364FC5F606B1C66DA66DB66D87CF36AB98B9B8EA791C46ABA947A
6AB76AC79A619A639AD79C766C0B9FA5700C7067700172AB864A897D8B9D0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
62
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00008C538F65947B6FFC98CD98DD72019B309E16720371FD737674B874C096E7
9E189EA274B69F7C74C27E9E9484765C9E1C76597C7197CA7657765A76A69EA3
76EC9C7B9F97790C7913975079097910791257275C1379AC7A5F7C1C7C297C19
7C205FC87C2D7C1D7C267C287C2267657C307E5C52BD7E565B667E5865F96788
6CE66CCB7E574FBD5F8D7FB36018604880756B2970A681D07706825E85B485C6
5A105CFC5CFE85B385B585BD85C785C485BF70C985CE85C885C585B185B60000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
63
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000085D28624957985B796BA866987E787E687E287DB87EB87EA7B29812887F3
8A2E87D487DC87D39AD987D8582B584587D963FA87F487E887DD6E86894B894F
894C89468950586789495BDD656E8B238B338B308C878B4750D250DF8B3E8B31
8B258B3769BA8B366B9D8B2480598B3D8B3A8C428C758C998C988C978CFE8D04
8D028D008E5C6F8A8E608E577BC37BC28E658E678E5B8E5A90F68E5D98238E54
8F468F478F488F4B71CD7499913B913E91A891A591A7984291AA93B5938C0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
64
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000093927F84939B939D938993A7938E8D0E939E9861939593888B73939F9C27
938D945877D69B2D93A493A893B493A395D295D395D196B396D796DA5DC296DF
96D896DD97239722972597AC97AE97A84F664F684FE7503F97A550A6510F523E
53245365539B517F54CB55735571556B55F456225620569256BA569156B05759
578A580F581258135847589B5900594D5AD15AD35B675C575C775CD55D755D8E
5DA55DB65DBF5E655ECD5EED5F945F9A5FBA6125615062A36360636463B60000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
65
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000640364B6651A7A255C2166E2670267A467AC68106806685E685A692C6929
6A2D6A776A7A6ACA6AE66AF56B0D6B0E6BDC6BDD6BF66C1E6C636DA56E0F6E8A
6E846E8B6E7C6F4C6F486F496F9D6F996FF8702E702D705C79CC70BF70EA70E5
71117112713F7139713B713D71777175717671717196719371B471DD71DE720E
591172187347734873EF7412743B74A4748D74B47673767776BC7819781B783D
78537854785878B778D878EE7922794D7986799979A379BC7AA77B377B590000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
66
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00007BD07C2F7C327C427C4E7C687CA97CED7DD07E077DD37E647F40791E8041
806380BB6711672582488310836283128421841E84E284DE84E1857385D485F5
863786458672874A87A987A587F5883488508887895489848B038C528CD88D0C
8D188DB08EBC8ED58FAA909C85E8915C922B9221927392F492F5933F93429386
93BE93BC93BD93F193F293EF94229423942494679466959795CE95E7973B974D
98E499429B1D9B9889629D4964495E715E8561D3990E8002781E898889B70000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
67
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00005528557255BA55F055EE56B856B956C4805392B08B558B518B428B528B57
8C438C778C768C9A8D068D078D098DAC8DAA8DAD8DAB8E6D8E788E738E6A8E6F
8E7B8EC28F528F518F4F8F508F538FB49140913F91B091AD93DE93C793CF93C2
93DA93D093F993EC93CC93D993A993E693CA93D493EE93E393D593C493CE93C0
93D293A593E7957D95DA95DB96E19729972B972C9728972697B397B797B697DD
97DE97DF985C9859985D985798BF98BD98BB98BE99489947994399A699A70000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
68
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009A1A9A159A259A1D9A249A1B9A229A209A279A239A1E9A1C9A149AC29B0B
9B0A9B0E9B0C9B379BEA9BEB9BE09BDE9BE49BE69BE29BF09BD49BD79BEC9BDC
9BD99BE59BD59BE19BDA9D779D819D8A9D849D889D719D809D789D869D8B9D8C
9D7D9D6B9D749D759D709D699D859D739D7B9D829D6F9D799D7F9D879D689E94
9E919EC09EFC9F2D9F409F419F4D9F569F579F58533756B256B556B358E35B45
5DC65DC75EEE5EEF5FC05FC161F9651765166515651365DF66E866E366E40000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
69
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006AF36AF06AEA6AE86AF96AF16AEE6AEF703C7035702F7037703470317042
7038703F703A7039702A7040703B703370417213721472A8737D737C74BA76AB
76AA76BE76ED77CC77CE77CF77CD77F279257923792779287924792979B27A6E
7A6C7A6D7AF77C497C487C4A7C477C457CEE7E7B7E7E7E817E807FBA7FFF8079
81DB81D982688269862285FF860185FE861B860085F6860486098605860C85FD
8819881088118817881388168963896689B989F78B608B6A8B5D8B688B630000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
6A
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00008B658B678B6D8DAE8E868E888E848F598F568F578F558F588F5A908D9143
914191B791B591B291B3940B941393FB9420940F941493FE9415941094289419
940D93F5940093F79407940E9416941293FA940993F8943C940A93FF93FC940C
93F69411940695DE95E095DF972E972F97B997BB97FD97FE986098629863985F
98C198C29950994E9959994C994B99539A329A349A319A2C9A2A9A369A299A2E
9A389A2D9AC79ACA9AC69B109B129B119C0B9C089BF79C059C129BF89C400000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
6B
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009C079C0E9C069C179C149C099D9F9D999DA49D9D9D929D989D909D9B9DA0
9D949D9C9DAA9D979DA19D9A9DA29DA89D9E9DA39DBF9DA99D969DA69DA79E99
9E9B9E9A9EE59EE49EE79EE69F309F2E9F5B9F609F5E9F5D9F599F91513A5139
5298529756C356BD56BE5B485B475DCB5DCF5EF161FD651B6B026AFC6B036AF8
6B0070437044704A7048704970457046721D721A7219737E7517766A77D0792D
7931792F7C547C537CF27E8A7E877E887E8B7E867E8D7F4D7FBB803081DD0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
6C
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00008618862A8626861F8623861C86198627862E862186208629861E86258829
881D881B88208824881C882B884A896D8969896E896B89FA8B798B788B458B7A
8B7B8D108D148DAF8E8E8E8C8F5E8F5B8F5D91469144914591B9943F943B9436
9429943D94309439942A9437942C9440943195E595E495E39735973A97BF97E1
986498C998C698C0995899569A399A3D9A469A449A429A419A3A9A3F9ACD9B15
9B179B189B169B3A9B529C2B9C1D9C1C9C2C9C239C289C299C249C219DB70000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
6D
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009DB69DBC9DC19DC79DCA9DCF9DBE9DC59DC39DBB9DB59DCE9DB99DBA9DAC
9DC89DB19DAD9DCC9DB39DCD9DB29E7A9E9C9EEB9EEE9EED9F1B9F189F1A9F31
9F4E9F659F649F924EB956C656C556CB59715B4B5B4C5DD55DD15EF265216520
652665226B0B6B086B096C0D7055705670577052721E721F72A9737F74D874D5
74D974D7766D76AD793579B47A707A717C577C5C7C597C5B7C5A7CF47CF17E91
7F4F7F8781DE826B863486358633862C86328636882C88288826882A88250000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
6E
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000897189BF89BE89FB8B7E8B848B828B868B858B7F8D158E958E948E9A8E92
8E908E968E978F608F629147944C9450944A944B944F94479445944894499446
973F97E3986A986998CB9954995B9A4E9A539A549A4C9A4F9A489A4A9A499A52
9A509AD09B199B2B9B3B9B569B559C469C489C3F9C449C399C339C419C3C9C37
9C349C329C3D9C369DDB9DD29DDE9DDA9DCB9DD09DDC9DD19DDF9DE99DD99DD8
9DD69DF59DD59DDD9EB69EF09F359F339F329F429F6B9F959FA2513D52990000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
6F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000058E858E759725B4D5DD8882F5F4F62016203620465296525659666EB6B11
6B126B0F6BCA705B705A7222738273817383767077D47C677C667E95826C863A
86408639863C8631863B863E88308832882E883389768974897389FE8B8C8B8E
8B8B8B888C458D198E988F648F6391BC94629455945D9457945E97C497C59800
9A569A599B1E9B1F9B209C529C589C509C4A9C4D9C4B9C559C599C4C9C4E9DFB
9DF79DEF9DE39DEB9DF89DE49DF69DE19DEE9DE69DF29DF09DE29DEC9DF40000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
70
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009DF39DE89DED9EC29ED09EF29EF39F069F1C9F389F379F369F439F4F9F71
9F709F6E9F6F56D356CD5B4E5C6D652D66ED66EE6B13705F7061705D70607223
74DB74E577D5793879B779B67C6A7E977F89826D8643883888378835884B8B94
8B958E9E8E9F8EA08E9D91BE91BD91C2946B9468946996E597469743974797C7
97E59A5E9AD59B599C639C679C669C629C5E9C609E029DFE9E079E039E069E05
9E009E019E099DFF9DFD9E049EA09F1E9F469F749F759F7656D4652E65B80000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
71
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006B186B196B176B1A7062722672AA77D877D979397C697C6B7CF67E9A7E98
7E9B7E9981E081E18646864786488979897A897C897B89FF8B988B998EA58EA4
8EA3946E946D946F9471947397499872995F9C689C6E9C6D9E0B9E0D9E109E0F
9E129E119EA19EF59F099F479F789F7B9F7A9F79571E70667C6F883C8DB28EA6
91C394749478947694759A609B2E9C749C739C719C759E149E139EF69F0A9FA4
706870657CF7866A883E883D883F8B9E8C9C8EA98EC9974B9873987498CC0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
72
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000996199AB9A649A669A679B249E159E179F4862076B1E7227864C8EA89482
948094819A699A689E19864B8B9F94839C799EB776759A6B9C7A9E1D7069706A
72299EA49F7E9F499F988AF68AFC8C6B8C6D8C938CF48E448E318E348E428E39
8E358F3B8F2F8F388F338FA88FA69075907490789072907C907A913491929320
933692F89333932F932292FC932B9304931A9310932693219315932E931995BB
96A796A896AA96D5970E97119716970D9713970F975B975C9766979898300000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
73
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009838983B9837982D9839982499109928991E991B9921991A99ED99E299F1
9AB89ABC9AFB9AED9B289B919D159D239D269D289D129D1B9ED89ED49F8D9F9C
512A511F5121513252F5568E5680569056855687568F58D558D358D158CE5B30
5B2A5B245B7A5C375C685DBC5DBA5DBD5DB85E6B5F4C5FBD61C961C261C761E6
61CB6232623464CE64CA64D864E064F064E664EC64F164E264ED6582658366D9
66D66A806A946A846AA26A9C6ADB6AA36A7E6A976A906AA06B5C6BAE6BDA0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
74
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00006C086FD86FF16FDF6FE06FDB6FE46FEB6FEF6F806FEC6FE16FE96FD56FEE
6FF071E771DF71EE71E671E571ED71EC71F471E0723572467370737274A974B0
74A674A876467642764C76EA77B377AA77B077AC77A777AD77EF78F778FA78F4
78EF790179A779AA7A577ABF7C077C0D7BFE7BF77C0C7BE07CE07CDC7CDE7CE2
7CDF7CD97CDD7E2E7E3E7E467E377E327E437E2B7E3D7E317E457E417E347E39
7E487E357E3F7E2F7F447FF37FFC807180728070806F807381C681C381BA0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
75
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000081C281C081BF81BD81C981BE81E88209827185AA8584857E859C85918594
85AF859B858785A8858A85A6866787C087D187B387D287C687AB87BB87BA87C8
87CB893B893689448938893D89AC8B0E8B178B198B1B8B0A8B208B1D8B048B10
8C418C3F8C738CFA8CFD8CFC8CF88CFB8DA88E498E4B8E488E4A8F448F3E8F42
8F458F3F907F907D9084908190829080913991A3919E919C934D938293289375
934A9365934B9318937E936C935B9370935A935495CA95CB95CC95C895C60000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
76
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000096B196B896D6971C971E97A097D3984698B699359A0199FF9BAE9BAB9BAA
9BAD9D3B9D3F9E8B9ECF9EDE9EDC9EDD9EDB9F3E9F4B53E2569556AE58D958D8
5B385F5E61E3623364F464F264FE650664FA64FB64F765B766DC67266AB36AAC
6AC36ABB6AB86AC26AAE6AAF6B5F6B786BAF7009700B6FFE70066FFA7011700F
71FB71FC71FE71F87377737574A774BF751576567658765277BD77BF77BB77BC
790E79AE7A617A627A607AC47AC57C2B7C277C2A7C1E7C237C217CE77E540000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
77
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00007E557E5E7E5A7E617E527E597F487FF97FFB8077807681CD81CF820A85CF
85A985CD85D085C985B085BA85B987EF87EC87F287E0898689B289F48B288B39
8B2C8B2B8C508D058E598E638E668E648E5F8E558EC08F498F4D908790839088
91AB91AC91D09394938A939693A293B393AE93AC93B09398939A939795D495D6
95D095D596E296DC96D996DB96DE972497A397A697AD97F9984D984F984C984E
985398BA993E993F993D992E99A59A0E9AC19B039B069B4F9B4E9B4D9BCA0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
78
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009BC99BFD9BC89BC09D519D5D9D609EE09F159F2C513356A556A858DE58DF
58E25BF59F905EEC61F261F761F661F56500650F66E066DD6AE56ADD6ADA6AD3
701B701F7028701A701D701570187206720D725872A27378737A74BD74CA74E3
75877586765F766177C7791979B17A6B7A697C3E7C3F7C387C3D7C377C407E6B
7E6D7E797E697E6A7E737F857FB67FB97FB881D885E985DD85EA85D585E485E5
85F787FB8805880D87F987FE8960895F8956895E8B418B5C8B588B498B5A0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
79
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00008B4E8B4F8B468B598D088D0A8E7C8E728E878E768E6C8E7A8E748F548F4E
8FAD908A908B91B191AE93E193D193DF93C393C893DC93DD93D693E293CD93D8
93E493D793E895DC96B496E3972A9727976197DC97FB985E9858985B98BC9945
99499A169A199B0D9BE89BE79BD69BDB9D899D619D729D6A9D6C9E929E979E93
9EB452F856B756B656B456BC58E45B405B435B7D5BF65DC961F861FA65186514
651966E667276AEC703E703070327210737B74CF766276657926792A792C0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
7A
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000792B7AC77AF67C4C7C437C4D7CEF7CF08FAE7E7D7E7C7E827F4C800081DA
826685FB85F9861185FA8606860B8607860A88148815896489BA89F88B708B6C
8B668B6F8B5F8B6B8D0F8D0D8E898E818E858E8291B491CB9418940393FD95E1
973098C49952995199A89A2B9A309A379A359C139C0D9E799EB59EE89F2F9F5F
9F639F615137513856C156C056C259145C6C5DCD61FC61FE651D651C659566E9
6AFB6B046AFA6BB2704C721B72A774D674D4766977D37C507E8F7E8C7FBC0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
7B
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00008617862D861A882388228821881F896A896C89BD8B748B778B7D8D138E8A
8E8D8E8B8F5F8FAF91BA942E94339435943A94389432942B95E2973897399732
97FF9867986599579A459A439A409A3E9ACF9B549B519C2D9C259DAF9DB49DC2
9DB89E9D9EEF9F199F5C9F669F67513C513B56C856CA56C95B7F5DD45DD25F4E
61FF65246B0A6B6170517058738074E4758A766E766C79B37C607C5F807E807D
81DF8972896F89FC8B808D168D178E918E938F619148944494519452973D0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
7C
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000973E97C397C1986B99559A559A4D9AD29B1A9C499C319C3E9C3B9DD39DD7
9F349F6C9F6A9F9456CC5DD662006523652B652A66EC6B1074DA7ACA7C647C63
7C657E937E967E9481E28638863F88318B8A9090908F9463946094649768986F
995C9A5A9A5B9A579AD39AD49AD19C549C579C569DE59E9F9EF456D158E9652C
705E7671767277D77F507F888836883988628B938B928B9682778D1B91C0946A
97429748974497C698709A5F9B229B589C5F9DF99DFA9E7C9E7D9F079F770000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
7D
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00009F725EF36B1670637C6C7C6E883B89C08EA191C1947294709871995E9AD6
9B239ECC706477DA8B9A947797C99A629A657E9C8B9C8EAA91C5947D947E947C
9C779C789EF78C54947F9E1A72289A6A9B319E1B9E1E7C720000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000

Changes to library/encoding/cp1250.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20












-
-
+
+






# Encoding file: cp1250, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0083201E2026202020210088203001602039015A0164017D0179
009020182019201C201D202220132014009821220161203A015B0165017E017A
20AC0000201A0000201E2026202020210000203001602039015A0164017D0179
000020182019201C201D202220132014000021220161203A015B0165017E017A
00A002C702D8014100A4010400A600A700A800A9015E00AB00AC00AD00AE017B
00B000B102DB014200B400B500B600B700B80105015F00BB013D02DD013E017C
015400C100C2010200C40139010600C7010C00C9011800CB011A00CD00CE010E
01100143014700D300D4015000D600D70158016E00DA017000DC00DD016200DF
015500E100E2010300E4013A010700E7010D00E9011900EB011B00ED00EE010F
01110144014800F300F4015100F600F70159016F00FA017100FC00FD016302D9

Changes to library/encoding/cp1251.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20













-
+






# Encoding file: cp1251, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
04020403201A0453201E20262020202120AC203004092039040A040C040B040F
045220182019201C201D202220132014009821220459203A045A045C045B045F
045220182019201C201D202220132014000021220459203A045A045C045B045F
00A0040E045E040800A4049000A600A7040100A9040400AB00AC00AD00AE0407
00B000B104060456049100B500B600B704512116045400BB0458040504550457
0410041104120413041404150416041704180419041A041B041C041D041E041F
0420042104220423042404250426042704280429042A042B042C042D042E042F
0430043104320433043404350436043704380439043A043B043C043D043E043F
0440044104420443044404450446044704480449044A044B044C044D044E044F

Changes to library/encoding/cp1252.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20












-
-
+
+






# Encoding file: cp1252, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0192201E20262020202102C62030016020390152008D017D008F
009020182019201C201D20222013201402DC21220161203A0153009D017E0178
20AC0000201A0192201E20262020202102C620300160203901520000017D0000
000020182019201C201D20222013201402DC21220161203A01530000017E0178
00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF
00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF
00C000C100C200C300C400C500C600C700C800C900CA00CB00CC00CD00CE00CF
00D000D100D200D300D400D500D600D700D800D900DA00DB00DC00DD00DE00DF
00E000E100E200E300E400E500E600E700E800E900EA00EB00EC00ED00EE00EF
00F000F100F200F300F400F500F600F700F800F900FA00FB00FC00FD00FE00FF

Changes to library/encoding/cp1253.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20












-
-
+
+






# Encoding file: cp1253, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0192201E20262020202100882030008A2039008C008D008E008F
009020182019201C201D20222013201400982122009A203A009C009D009E009F
20AC0000201A0192201E20262020202100002030000020390000000000000000
000020182019201C201D202220132014000021220000203A0000000000000000
00A00385038600A300A400A500A600A700A800A9000000AB00AC00AD00AE2015
00B000B100B200B3038400B500B600B703880389038A00BB038C00BD038E038F
0390039103920393039403950396039703980399039A039B039C039D039E039F
03A003A1000003A303A403A503A603A703A803A903AA03AB03AC03AD03AE03AF
03B003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF
03C003C103C203C303C403C503C603C703C803C903CA03CB03CC03CD03CE0000

Changes to library/encoding/cp1254.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20












-
-
+
+






# Encoding file: cp1254, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0192201E20262020202102C62030016020390152008D008E008F
009020182019201C201D20222013201402DC21220161203A0153009D009E0178
20AC0000201A0192201E20262020202102C62030016020390152000000000000
000020182019201C201D20222013201402DC21220161203A0153000000000178
00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF
00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF
00C000C100C200C300C400C500C600C700C800C900CA00CB00CC00CD00CE00CF
011E00D100D200D300D400D500D600D700D800D900DA00DB00DC0130015E00DF
00E000E100E200E300E400E500E600E700E800E900EA00EB00EC00ED00EE00EF
011F00F100F200F300F400F500F600F700F800F900FA00FB00FC0131015F00FF

Changes to library/encoding/cp1255.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20












-
-
+
+






# Encoding file: cp1255, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0192201E20262020202102C62030008A2039008C008D008E008F
009020182019201C201D20222013201402DC2122009A203A009C009D009E009F
20AC0000201A0192201E20262020202102C62030000020390000000000000000
000020182019201C201D20222013201402DC21220000203A0000000000000000
00A000A100A200A320AA00A500A600A700A800A900D700AB00AC00AD00AE00AF
00B000B100B200B300B400B500B600B700B800B900F700BB00BC00BD00BE00BF
05B005B105B205B305B405B505B605B705B805B9000005BB05BC05BD05BE05BF
05C005C105C205C305F005F105F205F305F40000000000000000000000000000
05D005D105D205D305D405D505D605D705D805D905DA05DB05DC05DD05DE05DF
05E005E105E205E305E405E505E605E705E805E905EA00000000200E200F0000

Changes to library/encoding/cp1257.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20












-
-
+
+






# Encoding file: cp1257, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0083201E20262020202100882030008A2039008C00A802C700B8
009020182019201C201D20222013201400982122009A203A009C00AF02DB009F
20AC0000201A0000201E2026202020210000203000002039000000A802C700B8
000020182019201C201D202220132014000021220000203A000000AF02DB0000
00A0000000A200A300A4000000A600A700D800A9015600AB00AC00AD00AE00C6
00B000B100B200B300B400B500B600B700F800B9015700BB00BC00BD00BE00E6
0104012E0100010600C400C501180112010C00C90179011601220136012A013B
01600143014500D3014C00D500D600D701720141015A016A00DC017B017D00DF
0105012F0101010700E400E501190113010D00E9017A011701230137012B013C
01610144014600F3014D00F500F600F701730142015B016B00FC017C017E02D9

Changes to library/encoding/cp1258.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20












-
-
+
+






# Encoding file: cp1258, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0192201E20262020202102C62030008A20390152008D008E008F
009020182019201C201D20222013201402DC2122009A203A0153009D009E0178
20AC0000201A0192201E20262020202102C62030000020390152000000000000
000020182019201C201D20222013201402DC21220000203A0153000000000178
00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF
00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF
00C000C100C2010200C400C500C600C700C800C900CA00CB030000CD00CE00CF
011000D1030900D300D401A000D600D700D800D900DA00DB00DC01AF030300DF
00E000E100E2010300E400E500E600E700E800E900EA00EB030100ED00EE00EF
011100F1032300F300F401A100F600F700F800F900FA00FB00FC01B020AB00FF

Changes to library/encoding/cp864.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20













-
+






# Encoding file: cp864, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
00200021002200230024066A0026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
00B000B72219221A259225002502253C2524252C251C25342510250C25142518
03B2221E03C600B100BD00BC224800AB00BBFEF7FEF8009B009CFEFBFEFC009F
03B2221E03C600B100BD00BC224800AB00BBFEF7FEF800000000FEFBFEFC0000
00A000ADFE8200A300A4FE8400000000FE8EFE8FFE95FE99060CFE9DFEA1FEA5
0660066106620663066406650666066706680669FED1061BFEB1FEB5FEB9061F
00A2FE80FE81FE83FE85FECAFE8BFE8DFE91FE93FE97FE9BFE9FFEA3FEA7FEA9
FEABFEADFEAFFEB3FEB7FEBBFEBFFEC1FEC5FECBFECF00A600AC00F700D7FEC9
0640FED3FED7FEDBFEDFFEE3FEE7FEEBFEEDFEEFFEF3FEBDFECCFECEFECDFEE1
FE7D0651FEE5FEE9FEECFEF0FEF2FED0FED5FEF5FEF6FEDDFED9FEF125A00000

Changes to library/encoding/cp869.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20












-
-
+
+






# Encoding file: cp869, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850386008700B700AC00A620182019038820150389
038A03AA038C00930094038E03AB00A9038F00B200B303AC00A303AD03AE03AF
0000000000000000000000000386000000B700AC00A620182019038820150389
038A03AA038C00000000038E03AB00A9038F00B200B303AC00A303AD03AE03AF
03CA039003CC03CD039103920393039403950396039700BD0398039900AB00BB
25912592259325022524039A039B039C039D256325512557255D039E039F2510
25142534252C251C2500253C03A003A1255A25542569256625602550256C03A3
03A403A503A603A703A803A903B103B203B32518250C2588258403B403B52580
03B603B703B803B903BA03BB03BC03BD03BE03BF03C003C103C303C203C40384
00AD00B103C503C603C700A703C8038500B000A803C903CB03B003CE25A000A0

Changes to library/encoding/cp874.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20












-
-
+
+






# Encoding file: cp874, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC008100820083008420260086008700880089008A008B008C008D008E008F
009020182019201C201D20222013201400980099009A009B009C009D009E009F
20AC000000000000000020260000000000000000000000000000000000000000
000020182019201C201D20222013201400000000000000000000000000000000
00A00E010E020E030E040E050E060E070E080E090E0A0E0B0E0C0E0D0E0E0E0F
0E100E110E120E130E140E150E160E170E180E190E1A0E1B0E1C0E1D0E1E0E1F
0E200E210E220E230E240E250E260E270E280E290E2A0E2B0E2C0E2D0E2E0E2F
0E300E310E320E330E340E350E360E370E380E390E3A00000000000000000E3F
0E400E410E420E430E440E450E460E470E480E490E4A0E4B0E4C0E4D0E4E0E4F
0E500E510E520E530E540E550E560E570E580E590E5A0E5B0000000000000000

Changes to library/encoding/cp932.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







# Encoding file: cp932, multi-byte
M
003F 0 46
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080000000000000000000850086000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F
FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F
FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F
FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000

Changes to library/encoding/cp949.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







# Encoding file: cp949, multi-byte
M
003F 0 125
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000

Changes to library/encoding/cp950.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20
21












-
-
+
+







# Encoding file: cp950, multi-byte
M
003F 0 88
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
A1

Changes to library/encoding/dingbats.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20












-
-
+
+






# Encoding file: dingbats, single-byte
S
003F 1 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
00202701270227032704260E2706270727082709261B261E270C270D270E270F
2710271127122713271427152716271727182719271A271B271C271D271E271F
2720272127222723272427252726272726052729272A272B272C272D272E272F
2730273127322733273427352736273727382739273A273B273C273D273E273F
2740274127422743274427452746274727482749274A274B25CF274D25A0274F
27502751275225B225BC25C6275625D727582759275A275B275C275D275E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000276127622763276427652766276726632666266526602460246124622463
2464246524662467246824692776277727782779277A277B277C277D277E277F
2780278127822783278427852786278727882789278A278B278C278D278E278F
2790279127922793279421922194219527982799279A279B279C279D279E279F
27A027A127A227A327A427A527A627A727A827A927AA27AB27AC27AD27AE27AF
000027B127B227B327B427B527B627B727B827B927BA27BB27BC27BD27BE0000

Changes to library/encoding/ebcdic.enc.


1
2
3
4
5
6
7
1
2
3
4
5
6
7
8
+







# Encoding file: ebcdic, single-byte
S
006F 0 1
00
0000000100020003008500090086007F0087008D008E000B000C000D000E000F
0010001100120013008F000A0008009700180019009C009D001C001D001E001F
0080008100820083008400920017001B00880089008A008B008C000500060007
0090009100160093009400950096000400980099009A009B00140015009E001A

Changes to library/encoding/euc-cn.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20
21












-
-
+
+







# Encoding file: euc-cn, multi-byte
M
003F 0 82
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
A1

Changes to library/encoding/euc-jp.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20
21












-
-
+
+







# Encoding file: euc-jp, multi-byte
M
003F 0 79
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850086008700880089008A008B008C008D0000008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
8E

Changes to library/encoding/euc-kr.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20
21












-
-
+
+







# Encoding file: euc-kr, multi-byte
M
003F 0 90
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
A1

Changes to library/encoding/gb1988.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20












-
-
+
+






# Encoding file: gb1988, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
002000210022002300A500250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D203E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F
FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F
FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F
FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000

Added library/encoding/iso8859-11.enc.





















1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# Encoding file: iso8859-11, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
00A00E010E020E030E040E050E060E070E080E090E0A0E0B0E0C0E0D0E0E0E0F
0E100E110E120E130E140E150E160E170E180E190E1A0E1B0E1C0E1D0E1E0E1F
0E200E210E220E230E240E250E260E270E280E290E2A0E2B0E2C0E2D0E2E0E2F
0E300E310E320E330E340E350E360E370E380E390E3A00000000000000000E3F
0E400E410E420E430E440E450E460E470E480E490E4A0E4B0E4C0E4D0E4E0E4F
0E500E510E520E530E540E550E560E570E580E590E5A0E5B0000000000000000

Changes to library/encoding/iso8859-7.enc.

8
9
10
11
12
13
14
15

16
17
18
19
20
8
9
10
11
12
13
14

15
16
17
18
19
20







-
+





0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
00A02018201900A30000000000A600A700A800A9000000AB00AC00AD00002015
00A02018201900A320AC20AF00A600A700A800A9037A00AB00AC00AD00002015
00B000B100B200B303840385038600B703880389038A00BB038C00BD038E038F
0390039103920393039403950396039703980399039A039B039C039D039E039F
03A003A1000003A303A403A503A603A703A803A903AA03AB03AC03AD03AE03AF
03B003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF
03C003C103C203C303C403C503C603C703C803C903CA03CB03CC03CD03CE0000

Changes to library/encoding/jis0201.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20












-
-
+
+






# Encoding file: jis0201, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D203E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F
FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F
FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F
FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000

Added library/encoding/koi8-ru.enc.





















1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# Encoding file: koi8-ru, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
25002502250C251025142518251C2524252C2534253C258025842588258C2590
259125922593232025A02219221A22482264226500A0232100B000B200B700F7
25502551255204510454255404560457255725582559255A255B0491045E255E
255F25602561040104042563040604072566256725682569256A0490040E00A9
044E0430043104460434043504440433044504380439043A043B043C043D043E
043F044F044004410442044304360432044C044B04370448044D04490447044A
042E0410041104260414041504240413042504180419041A041B041C041D041E
041F042F042004210422042304160412042C042B04170428042D04290427042A

Added library/encoding/koi8-t.enc.





















1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# Encoding file: koi8-t, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
049B0493201A0492201E2026202020210000203004B3203904B204B704B60000
049A20182019201C201D202220132014000021220000203A0000000000000000
000004EF04EE045100A404E300A600A700000000000000AB00AC00AD00AE0000
00B000B100B20401000004E200B600B700002116000000BB00000000000000A9
044E0430043104460434043504440433044504380439043A043B043C043D043E
043F044F044004410442044304360432044C044B04370448044D04490447044A
042E0410041104260414041504240413042504180419041A041B041C041D041E
041F042F042004210422042304160412042C042B04170428042D04290427042A

Changes to library/encoding/koi8-u.enc.

9
10
11
12
13
14
15
16

17
18
19
20
9
10
11
12
13
14
15

16
17
18
19
20







-
+




0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
25002502250C251025142518251C2524252C2534253C258025842588258C2590
259125922593232025A02219221A22482264226500A0232100B000B200B700F7
25502551255204510454255404560457255725582559255A255B0491255D255E
255F25602561040104032563040604072566256725682569256A0490256C00A9
255F25602561040104042563040604072566256725682569256A0490256C00A9
044E0430043104460434043504440433044504380439043A043B043C043D043E
043F044F044004410442044304360432044C044B04370448044D04490447044A
042E0410041104260414041504240413042504180419041A041B041C041D041E
041F042F042004210422042304160412042C042B04170428042D04290427042A

Changes to library/encoding/macDingbats.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20












-
-
+
+






# Encoding file: macDingbats, single-byte
S
003F 1 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
00202701270227032704260E2706270727082709261B261E270C270D270E270F
2710271127122713271427152716271727182719271A271B271C271D271E271F
2720272127222723272427252726272726052729272A272B272C272D272E272F
2730273127322733273427352736273727382739273A273B273C273D273E273F
2740274127422743274427452746274727482749274A274B25CF274D25A0274F
27502751275225B225BC25C6275625D727582759275A275B275C275D275E007F
F8D7F8D8F8D9F8DAF8DBF8DCF8DDF8DEF8DFF8E0F8E1F8E2F8E3F8E4008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
F8D7F8D8F8D9F8DAF8DBF8DCF8DDF8DEF8DFF8E0F8E1F8E2F8E3F8E400000000
0000000000000000000000000000000000000000000000000000000000000000
0000276127622763276427652766276726632666266526602460246124622463
2464246524662467246824692776277727782779277A277B277C277D277E277F
2780278127822783278427852786278727882789278A278B278C278D278E278F
2790279127922793279421922194219527982799279A279B279C279D279E279F
27A027A127A227A327A427A527A627A727A827A927AA27AB27AC27AD27AE27AF
000027B127B227B327B427B527B627B727B827B927BA27BB27BC27BD27BE0000

Changes to library/encoding/macJapan.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







# Encoding file: macJapan, multi-byte
M
003F 0 46
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00A0FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F
FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F
FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F
FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F
0000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000A921222026

Changes to library/encoding/shiftjis.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







# Encoding file: shiftjis, multi-byte
M
003F 0 40
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080000000000000000000850086008700000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F
FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F
FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F
FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000

Changes to library/encoding/symbol.enc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20












-
-
+
+






# Encoding file: symbol, single-byte
S
003F 1 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002122000023220300250026220D002800292217002B002C2212002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
22450391039203A70394039503A603930397039903D1039A039B039C039D039F
03A0039803A103A303A403A503C203A9039E03A80396005B2234005D22A5005F
F8E503B103B203C703B403B503C603B303B703B903D503BA03BB03BC03BD03BF
03C003B803C103C303C403C503D603C903BE03C803B6007B007C007D223C007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000003D2203222642044221E0192266326662665266021942190219121922193
00B000B12033226500D7221D2202202200F72260226122482026F8E6F8E721B5
21352111211C21182297229522052229222A2283228722842282228622082209
2220220700AE00A92122220F221A22C500AC2227222821D421D021D121D221D3
22C42329F8E8F8E9F8EA2211F8EBF8ECF8EDF8EEF8EFF8F0F8F1F8F2F8F3F8F4
F8FF232A222B2320F8F52321F8F6F8F7F8F8F8F9F8FAF8FBF8FCF8FDF8FE0000

Changes to library/encoding/tis-620.enc.

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







# Encoding file: tis-620, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E0000
0070007100720073007400750076007700780079007A007B007C007D007E007F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000E010E020E030E040E050E060E070E080E090E0A0E0B0E0C0E0D0E0E0E0F
0E100E110E120E130E140E150E160E170E180E190E1A0E1B0E1C0E1D0E1E0E1F
0E200E210E220E230E240E250E260E270E280E290E2A0E2B0E2C0E2D0E2E0E2F
0E300E310E320E330E340E350E360E370E380E390E3A00000000000000000E3F
0E400E410E420E430E440E450E460E470E480E490E4A0E4B0E4C0E4D0E4E0E4F

Added library/foreachline.tcl.


























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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# foreachLine:
# Iterate over the contents of a file, a line at a time.
# The body script is run for each, with variable varName set to the line
# contents.
#
# Copyright © 2023 Donal K Fellows.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#

proc foreachLine {varName filename body} {
    upvar 1 $varName line
    set f [open $filename "r"]
    try {
	while {[gets $f line] >= 0} {
	    uplevel 1 $body
	}
    } on return {msg opt} {
	dict incr opt -level
	return -options $opt $msg
    } finally {
	close $f
    }
}

Changes to library/history.tcl.

1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# history.tcl --
#
# Implementation of the history command.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright © 1997 Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#

# The tcl::history array holds the history list and some additional
# bookkeeping variables.
49
50
51
52
53
54
55
56

57
58
59
60
61
62
63
49
50
51
52
53
54
55

56
57
58
59
60
61
62
63







-
+







    # given at all.

    if {![llength $args]} {
	set args info
    }

    # Tricky stuff needed to make stack and errors come out right!
    tailcall apply {arglist {tailcall history {*}$arglist} ::tcl} $args
    tailcall apply {arglist {tailcall ::tcl::history {*}$arglist} ::tcl} $args
}

# (unnamed) --
#
#	Callback when [::history] is destroyed. Destroys the implementation.
#
# Parameters:
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
85
86
87
88
89
90
91

92
93
94
95
96
97
98
99







-
+







#	Add an item to the history, and optionally eval it at the global scope
#
# Parameters:
#	event		the command to add
#	exec		(optional) a substring of "exec" causes the command to
#			be evaled.
# Results:
# 	If executing, then the results of the command are returned
#	If executing, then the results of the command are returned
#
# Side Effects:
#	Adds to the history list

proc ::tcl::HistAdd {event {exec {}}} {
    variable history

193
194
195
196
197
198
199
200

201
202
203
204
205
206
207
193
194
195
196
197
198
199

200
201
202
203
204
205
206
207







-
+







    set result {}
    set newline ""
    for {set i [expr {$history(nextid) - $count + 1}]} \
	    {$i <= $history(nextid)} {incr i} {
	if {![info exists history($i)]} {
	    continue
	}
        set cmd [string map [list \n \n\t] [string trimright $history($i) \ \n]]
	set cmd [string map [list \n \n\t] [string trimright $history($i) \ \n]]
	append result $newline[format "%6d  %s" $i $cmd]
	set newline \n
    }
    return $result
}

# tcl::HistRedo --
264
265
266
267
268
269
270
271

272
273
274
275
276
277
278
264
265
266
267
268
269
270

271
272
273
274
275
276
277
278







-
+







    } else {
	set i $event
    }
    if {$i <= $history(oldest)} {
	return -code error "event \"$event\" is too far in the past"
    }
    if {$i > $history(nextid)} {
	return -code error "event \"$event\" hasn't occured yet"
	return -code error "event \"$event\" hasn't occurred yet"
    }
    return $i
}

# tcl::HistEvent --
#
#	Map from an event specifier to the value in the history list.

Changes to library/http/http.tcl.

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

30
31
32
33
34
35
36
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
30
31
32
33
34
35
36
37
38
39













-
+














+
+

+







# http.tcl --
#
#	Client-side HTTP for GET, POST, and HEAD commands. These routines can
#	be used in untrusted code that uses the Safesock security policy.
#	These procedures use a callback interface to avoid using vwait, which
#	is not defined in the safe base.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require Tcl 8.6-
# Keep this in sync with pkgIndex.tcl and with the install directories in
# Makefiles
package provide http 2.10.0a1
package provide http 2.10.0

namespace eval http {
    # Allow resourcing to not clobber existing data

    variable http
    if {![info exists http]} {
	array set http {
	    -accept */*
	    -cookiejar {}
	    -pipeline 1
	    -postfresh 0
	    -proxyhost {}
	    -proxyport {}
	    -proxyfilter http::ProxyRequired
	    -proxynot {}
	    -proxyauth {}
	    -repost 0
	    -threadlevel 0
	    -urlencoding utf-8
	    -zip 1
	}
	# We need a useragent string of this style or various servers will
	# refuse to send us compressed content even when we ask for it. This
	# follows the de-facto layout of user-agent strings in current browsers.
	# Safe interpreters do not have ::tcl_platform(os) or
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
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







+


+
+




















+


+
+





+


+
+
+





-
+








	# Create a map for HTTP/1.1 open sockets
	variable socketMapping
	variable socketRdState
	variable socketWrState
	variable socketRdQueue
	variable socketWrQueue
	variable socketPhQueue
	variable socketClosing
	variable socketPlayCmd
	variable socketCoEvent
	variable socketProxyId
	if {[info exists socketMapping]} {
	    # Close open sockets on re-init.  Do not permit retries.
	    foreach {url sock} [array get socketMapping] {
		unset -nocomplain socketClosing($url)
		unset -nocomplain socketPlayCmd($url)
		CloseSocket $sock
	    }
	}

	# CloseSocket should have unset the socket* arrays, one element at
	# a time.  Now unset anything that was overlooked.
	# Traces on "unset socketRdState(*)" will call CancelReadPipeline and
	# cancel any queued responses.
	# Traces on "unset socketWrState(*)" will call CancelWritePipeline and
	# cancel any queued requests.
	array unset socketMapping
	array unset socketRdState
	array unset socketWrState
	array unset socketRdQueue
	array unset socketWrQueue
	array unset socketPhQueue
	array unset socketClosing
	array unset socketPlayCmd
	array unset socketCoEvent
	array unset socketProxyId
	array set socketMapping {}
	array set socketRdState {}
	array set socketWrState {}
	array set socketRdQueue {}
	array set socketWrQueue {}
	array set socketPhQueue {}
	array set socketClosing {}
	array set socketPlayCmd {}
	array set socketCoEvent {}
	array set socketProxyId {}
	return
    }
    init

    variable urlTypes
    if {![info exists urlTypes]} {
	set urlTypes(http) [list 80 ::socket]
	set urlTypes(http) [list 80 ::http::AltSocket {} 1 0]
    }

    variable encodings [string tolower [encoding names]]
    # This can be changed, but iso8859-1 is the RFC standard.
    variable defaultCharset
    if {![info exists defaultCharset]} {
	set defaultCharset "iso8859-1"
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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+

+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+

















-
-
-
+
+
+
+
+
+
+
+
+

+
-
+

-
+

-
+
+
+
+
+
+
+
+
+
+
+
+
+









+
-
+








+
+
+
+
+
+
+











-
+




















+
+
+





+
+
+


+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














-
+







+


+
+









-
-
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+



+
-
-
+
+
+
+
+
+
+


-
+










+
-
+
+










+

+








-
+












+


+
+







	([!\u0023-+\u002D-:<-\u005B\u005D-~]*)         # Match the value
	(?:
	 \s* ; \s*                                     # LITERAL: semicolon
	 ([^\u0000]+)                                  # Match the options
	)?
    }

    variable TmpSockCounter 0
    variable ThreadCounter  0

    variable reasonDict [dict create {*}{
	100 Continue
	101 {Switching Protocols}
	102 Processing
	103 {Early Hints}
	200 OK
	201 Created
	202 Accepted
	203 {Non-Authoritative Information}
	204 {No Content}
	205 {Reset Content}
	206 {Partial Content}
	207 Multi-Status
	208 {Already Reported}
	226 {IM Used}
	300 {Multiple Choices}
	301 {Moved Permanently}
	302 Found
	303 {See Other}
	304 {Not Modified}
	305 {Use Proxy}
	306 (Unused)
	307 {Temporary Redirect}
	308 {Permanent Redirect}
	400 {Bad Request}
	401 Unauthorized
	402 {Payment Required}
	403 Forbidden
	404 {Not Found}
	405 {Method Not Allowed}
	406 {Not Acceptable}
	407 {Proxy Authentication Required}
	408 {Request Timeout}
	409 Conflict
	410 Gone
	411 {Length Required}
	412 {Precondition Failed}
	413 {Content Too Large}
	414 {URI Too Long}
	415 {Unsupported Media Type}
	416 {Range Not Satisfiable}
	417 {Expectation Failed}
	418 (Unused)
	421 {Misdirected Request}
	422 {Unprocessable Content}
	423 Locked
	424 {Failed Dependency}
	425 {Too Early}
	426 {Upgrade Required}
	428 {Precondition Required}
	429 {Too Many Requests}
	431 {Request Header Fields Too Large}
	451 {Unavailable For Legal Reasons}
	500 {Internal Server Error}
	501 {Not Implemented}
	502 {Bad Gateway}
	503 {Service Unavailable}
	504 {Gateway Timeout}
	505 {HTTP Version Not Supported}
	506 {Variant Also Negotiates}
	507 {Insufficient Storage}
	508 {Loop Detected}
	510 {Not Extended (OBSOLETED)}
	511 {Network Authentication Required}
    }]

    variable failedProxyValues {
	binary
	body
	charset
	coding
	connection
	connectionRespFlag
	currentsize
	host
	http
	httpResponse
	meta
	method
	querylength
	queryoffset
	reasonPhrase
	requestHeaders
	requestLine
	responseCode
	state
	status
	tid
	totalsize
	transfer
	type
    }

    namespace export geturl config reset wait formatQuery quoteString
    namespace export geturl config reset wait formatQuery postError quoteString
    namespace export register unregister registerError
    namespace export requestLine requestHeaders requestHeaderValue
    namespace export responseLine responseHeaders responseHeaderValue
    namespace export responseCode responseBody responseInfo reasonPhrase
    # - Legacy aliases, were never exported:
    #     data, code, mapReply, meta, ncode
    # - Callable from outside (e.g. from TLS) by fully-qualified name, but
    # - Useful, but not exported: data, size, status, code, cleanup, error,
    #   meta, ncode, mapReply, init.  Comments suggest that "init" can be used
    #   for re-initialisation, although the command is undocumented.
    # - Not exported, probably should be upper-case initial letter as part
    #   of the internals: getTextLine, make-transformation-chunked.
    #   not exported:
    #     socket
    # - Useful, but never exported (and likely to have naming collisions):
    #     size, status, cleanup, error, init
    #   Comments suggest that "init" can be used for re-initialisation,
    #   although the command is undocumented.
    # - Never exported, renamed from lower-case names:
    #   GetTextLine, MakeTransformationChunked.
}

# http::Log --
#
#	Debugging output -- define this to observe HTTP/1.1 socket usage.
#	Should echo any args received.
#
# Arguments:
#     msg	Message to output
#
if {[info command http::Log] eq {}} {proc http::Log {args} {}}

# http::register --
#
#     See documentation for details.
#
# Arguments:
#     proto	URL protocol prefix, e.g. https
#     port	Default port for protocol
#     command	Command to use to create socket
#     proto		URL protocol prefix, e.g. https
#     port		Default port for protocol
#     command		Command to use to create socket
#     socketCmdVarName	(optional) name of variable provided by the protocol
#                       handler whose value is the callback used by argument
#                       "command" to open a socket. The default value "::socket"
#                       will be overwritten by http.
#     useSockThread	(optional, boolean)
#     endToEndProxy	(optional, boolean)
# Results:
#     list of port, command, variable name, (boolean) threadability,
#     list of port and command that was registered.
#     and (boolean) endToEndProxy that was registered.

proc http::register {proto port command} {
proc http::register {proto port command {socketCmdVarName {}} {useSockThread 0} {endToEndProxy 0}} {
    variable urlTypes
    set urlTypes([string tolower $proto]) [list $port $command]
    set lower [string tolower $proto]
    if {[info exists urlTypes($lower)]} {
	unregister $lower
    }
    set urlTypes($lower) [list $port $command $socketCmdVarName $useSockThread $endToEndProxy]

    # If the external handler for protocol $proto has given $socketCmdVarName the expected
    # value "::socket", overwrite it with the new value.
    if {($socketCmdVarName ne {}) && ([set $socketCmdVarName] eq {::socket})} {
	set $socketCmdVarName ::http::socketAsCallback
    }

    return $urlTypes($lower)
}

# http::unregister --
#
#     Unregisters URL protocol handler
#
# Arguments:
#     proto	URL protocol prefix, e.g. https
# Results:
#     list of port, command, variable name, (boolean) useSockThread,
#     list of port and command that was unregistered.
#     and (boolean) endToEndProxy that was unregistered.

proc http::unregister {proto} {
    variable urlTypes
    set lower [string tolower $proto]
    if {![info exists urlTypes($lower)]} {
	return -code error "unsupported url type \"$proto\""
    }
    set old $urlTypes($lower)

    # Restore the external handler's original value for $socketCmdVarName.
    lassign $old defport defcmd socketCmdVarName useSockThread endToEndProxy
    if {($socketCmdVarName ne {}) && ([set $socketCmdVarName] eq {::http::socketAsCallback})} {
	set $socketCmdVarName ::socket
    }

    unset urlTypes($lower)
    return $old
}

# http::config --
#
#	See documentation for details.
#
# Arguments:
#	args		Options parsed by the procedure.
# Results:
#        TODO
#	TODO

proc http::config {args} {
    variable http
    set options [lsort [array names http -*]]
    set usage [join $options ", "]
    if {[llength $args] == 0} {
	set result {}
	foreach name $options {
	    lappend result $name $http($name)
	}
	return $result
    }
    set options [string map {- ""} $options]
    set pat ^-(?:[join $options |])$
    if {[llength $args] == 1} {
	set flag [lindex $args 0]
	if {![regexp -- $pat $flag]} {
	    return -code error "Unknown option $flag, must be: $usage"
	}
	return $http($flag)
    } elseif {[llength $args] % 2} {
	return -code error "If more than one argument is supplied, the\
		number of arguments must be even"
    } else {
	foreach {flag value} $args {
	    if {![regexp -- $pat $flag]} {
		return -code error "Unknown option $flag, must be: $usage"
	    }
	    if {($flag eq {-threadlevel}) && ($value ni {0 1 2})} {
		return -code error {Option -threadlevel must be 0, 1 or 2}
	    }
	    set http($flag) $value
	}
	return
    }
}

# ------------------------------------------------------------------------------
#  Proc http::reasonPhrase
# ------------------------------------------------------------------------------
# Command to return the IANA-recommended "reason phrase" for a HTTP Status Code.
# Information obtained from:
# https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
#
# Arguments:
# code        - A valid HTTP Status Code (integer from 100 to 599)
#
# Return Value: the reason phrase
# ------------------------------------------------------------------------------

proc http::reasonPhrase {code} {
    variable reasonDict
    if {![regexp -- {^[1-5][0-9][0-9]$} $code]} {
	set msg {argument must be a three-digit integer from 100 to 599}
	return -code error $msg
    }
    if {[dict exists $reasonDict $code]} {
	set reason [dict get $reasonDict $code]
    } else {
	set reason Unassigned
    }
    return $reason
}

# http::Finish --
#
#	Clean up the socket and eval close time callbacks
#
# Arguments:
#	token	    Connection token.
#	errormsg    (optional) If set, forces status to error.
#	skipCB      (optional) If set, don't call the -command callback. This
#		    is useful when geturl wants to throw an exception instead
#		    of calling the callback. That way, the same error isn't
#		    reported to two places.
#
# Side Effects:
#        May close the socket.
#	May close the socket.

proc http::Finish {token {errormsg ""} {skipCB 0}} {
    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue
    variable socketPhQueue
    variable socketClosing
    variable socketPlayCmd
    variable socketCoEvent
    variable socketProxyId

    variable $token
    upvar 0 $token state
    global errorInfo errorCode
    set closeQueue 0
    if {$errormsg ne ""} {
	set state(error) [list $errormsg $errorInfo $errorCode]
	set state(status) "error"
    }
    if {[info commands ${token}EventCoroutine] ne {}} {
	rename ${token}EventCoroutine {}
    if {[info commands ${token}--EventCoroutine] ne {}} {
	rename ${token}--EventCoroutine {}
    }
    if {[info commands ${token}--SocketCoroutine] ne {}} {
	rename ${token}--SocketCoroutine {}
    }
    if {[info exists state(socketcoro)]} {
	Log $token Cancel socket after-idle event (Finish)
	after cancel $state(socketcoro)
	unset state(socketcoro)
    }

    # Is this an upgrade request/response?
    set upgradeResponse \
	[expr {    [info exists state(upgradeRequest)]
		&& $state(upgradeRequest)
		&& [info exists state(http)]
		&& ([ncode $token] eq {101})
		&& [info exists state(connection)]
		&& ("upgrade" in $state(connection))
		&& [info exists state(upgrade)]
		&& ("" ne $state(upgrade))
	}]

    if {  ($state(status) eq "timeout")
       || ($state(status) eq "error")
       || ($state(status) eq "eof")
    } {
	set closeQueue 1
	set connId $state(socketinfo)
	if {[info exists state(sock)]} {
	    set sock $state(sock)
	    CloseSocket $state(sock) $token
	} else {
	    # When opening the socket and calling http::reset
	    # immediately, the socket may not yet exist.
	    # Test http-4.11 may come here.
	}
	if {$state(tid) ne {}} {
	    # When opening the socket in a thread, and calling http::reset
	    # immediately, the thread may still exist.
	    # Test http-4.11 may come here.
	    thread::release $state(tid)
	    set state(tid) {}
	} else {
	}
    } elseif {$upgradeResponse} {
	# Special handling for an upgrade request/response.
	# - geturl ensures that this is not a "persistent" socket used for
	#   multiple HTTP requests, so a call to KeepSocket is not needed.
	# - Leave socket open, so a call to CloseSocket is not needed either.
	# - Remove fileevent bindings.  The caller will set its own bindings.
	# - THE CALLER MUST PROCESS THE UPGRADED SOCKET IN THE CALLBACK COMMAND
	#   PASSED TO http::geturl AS -command callback.
	catch {fileevent $state(sock) readable {}}
	catch {fileevent $state(sock) writable {}}
       || ([info exists state(-keepalive)] && !$state(-keepalive))
       || ([info exists state(connection)] && ($state(connection) eq "close"))
    } elseif {([info exists state(-keepalive)] && !$state(-keepalive))
	    || ([info exists state(connection)] && ("close" in $state(connection)))
    } {
	set closeQueue 1
	set connId $state(socketinfo)
	if {[info exists state(sock)]} {
	set sock $state(sock)
	CloseSocket $state(sock) $token
	    set sock $state(sock)
	    CloseSocket $state(sock) $token
	} else {
	    # When opening the socket and calling http::reset
	    # immediately, the socket may not yet exist.
	    # Test http-4.11 may come here.
	}
    } elseif {
	  ([info exists state(-keepalive)] && $state(-keepalive))
       && ([info exists state(connection)] && ($state(connection) ne "close"))
       && ([info exists state(connection)] && ("close" ni $state(connection)))
    } {
	KeepSocket $token
    }
    if {[info exists state(after)]} {
	after cancel $state(after)
	unset state(after)
    }
    if {[info exists state(-command)] && (!$skipCB)
	    && (![info exists state(done-command-cb)])} {
	set state(done-command-cb) yes
	if {    [catch {namespace eval :: $state(-command) $token} err]
	if {[catch {eval $state(-command) {$token}} err] && $errormsg eq ""} {
	     && ($errormsg eq "")
	} {
	    set state(error) [list $err $errorInfo $errorCode]
	    set state(status) error
	}
    }

    if {    $closeQueue
	 && [info exists socketMapping($connId)]
	 && ($socketMapping($connId) eq $sock)
    } {
	http::CloseQueuedQueries $connId $token
	# This calls Unset.  Other cases do not need the call.
    }
    return
}

# http::KeepSocket -
#
#	Keep a socket in the persistent sockets table and connect it to its next
#	queued task if possible.  Otherwise leave it idle and ready for its next
#	use.
#
#	If $socketClosing(*), then ($state(connection) eq "close") and therefore
#	If $socketClosing(*), then ("close" in $state(connection)) and therefore
#	this command will not be called by Finish.
#
# Arguments:
#	token	    Connection token.

proc http::KeepSocket {token} {
    variable http
    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue
    variable socketPhQueue
    variable socketClosing
    variable socketPlayCmd
    variable socketCoEvent
    variable socketProxyId

    variable $token
    upvar 0 $token state
    set tk [namespace tail $token]

    # Keep this socket open for another request ("Keep-Alive").
    # React if the server half-closes the socket.
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
601
602
603
604
605
606
607



608
609
610
611
612
613
614







-
-
-







	     && [info exists socketRdQueue($connId)]
	     && [llength $socketRdQueue($connId)]
	} {
	    # The usual case for pipelined responses - if another response is
	    # queued, arrange to read it.
	    set token3 [lindex $socketRdQueue($connId) 0]
	    set socketRdQueue($connId) [lrange $socketRdQueue($connId) 1 end]
	    variable $token3
	    upvar 0 $token3 state3
	    set tk2 [namespace tail $token3]

	    #Log pipelined, GRANT read access to $token3 in KeepSocket
	    set socketRdState($connId) $token3
	    ReceiveResponse $token3

	    # Other pipelined cases.
	    # - The test above ensures that, for the pipelined cases in the two
397
398
399
400
401
402
403
404
405

406
407
408
409
410
411
412
639
640
641
642
643
644
645


646
647
648
649
650
651
652
653







-
-
+







	    #   "pending" write token is in front of the rest of the write
	    #   queue.
	    # - The write state is not Wready and therefore appears to be busy,
	    #   but because it is "pending" we know that it is reserved for the
	    #   first item in the write queue, a non-pipelined request that is
	    #   waiting for the read queue to empty.  That has now happened: so
	    #   give that request read and write access.
	    variable $token3
	    set conn [set ${token3}(tmpConnArgs)]
	    set conn [set ${token3}(connArgs)]
	    #Log nonpipeline, GRANT r/w access to $token3 in KeepSocket
	    set socketRdState($connId) $token3
	    set socketWrState($connId) $token3
	    set socketWrQueue($connId) [lrange $socketWrQueue($connId) 1 end]
	    # Connect does its own fconfigure.
	    fileevent $state(sock) writable [list http::Connect $token3 {*}$conn]
	    #Log ---- $state(sock) << conn to $token3 for HTTP request (c)
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
467
468
469
470
471
472

473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490

491
492
493
494
495
496
497
683
684
685
686
687
688
689


690
691
692
693
694
695
696
697
698
699
700
701
702

703
704
705
706
707
708
709
710


711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737







-
-
+












-
+







-
-
+


















+







	    # Tests:
	    # - In this case the read state (tested above) is Rready and the
	    #   write state (tested here) is Wready - there is no "pending"
	    #   request.
	    # Code:
	    # - The code is the same as the code below for the nonpipelined
	    #   case with a queued request.
	    variable $token3
	    set conn [set ${token3}(tmpConnArgs)]
	    set conn [set ${token3}(connArgs)]
	    #Log nonpipeline, GRANT r/w access to $token3 in KeepSocket
	    set socketRdState($connId) $token3
	    set socketWrState($connId) $token3
	    set socketWrQueue($connId) [lrange $socketWrQueue($connId) 1 end]
	    # Connect does its own fconfigure.
	    fileevent $state(sock) writable [list http::Connect $token3 {*}$conn]
	    #Log ---- $state(sock) << conn to $token3 for HTTP request (c)

	} elseif {
		(!$state(-pipeline))
	     && [info exists socketWrQueue($connId)]
	     && [llength $socketWrQueue($connId)]
	     && ($state(connection) ne "close")
	     && ("close" ni $state(connection))
	} {
	    # If not pipelined, (socketRdState eq Rready) tells us that we are
	    # ready for the next write - there is no need to check
	    # socketWrState. Write the next request, if one is waiting.
	    # If the next request is pipelined, it receives premature read
	    # access to the socket. This is not a problem.
	    set token3 [lindex $socketWrQueue($connId) 0]
	    variable $token3
	    set conn [set ${token3}(tmpConnArgs)]
	    set conn [set ${token3}(connArgs)]
	    #Log nonpipeline, GRANT r/w access to $token3 in KeepSocket
	    set socketRdState($connId) $token3
	    set socketWrState($connId) $token3
	    set socketWrQueue($connId) [lrange $socketWrQueue($connId) 1 end]
	    # Connect does its own fconfigure.
	    fileevent $state(sock) writable [list http::Connect $token3 {*}$conn]
	    #Log ---- $state(sock) << conn to $token3 for HTTP request (d)

	} elseif {(!$state(-pipeline))} {
	    set socketWrState($connId) Wready
	    # Rready and Wready and idle: nothing to do.
	}

    } else {
	CloseSocket $state(sock) $token
	# There is no socketMapping($state(socketinfo)), so it does not matter
	# that CloseQueuedQueries is not called.
    }
    return
}

# http::CheckEof -
#
#	Read from a socket and close it if eof.
#	The command is bound to "fileevent readable" on an idle socket, and
#	"eof" is the only event that should trigger the binding, occurring when
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
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783







+















+


+
+








    if {[catch {eof $sock} res] || $res} {
	# The server has half-closed the socket.
	# If a new write has started, its transaction will fail and
	# will then be error-handled.
	CloseSocket $sock
    }
    return
}

# http::CloseSocket -
#
#	Close a socket and remove it from the persistent sockets table.  If
#	possible an http token is included here but when we are called from a
#	fileevent on remote closure we need to find the correct entry - hence
#	the "else" block of the first "if" command.

proc http::CloseSocket {s {token {}}} {
    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue
    variable socketPhQueue
    variable socketClosing
    variable socketPlayCmd
    variable socketCoEvent
    variable socketProxyId

    set tk [namespace tail $token]

    catch {fileevent $s readable {}}
    set connId {}
    if {$token ne ""} {
	variable $token
552
553
554
555
556
557
558

559
560
561
562
563

564
565
566
567
568

569
570

571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586

587
588


589

590
591
592
593
594
595
596
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848







+





+





+


+
















+


+
+

+







    if {    ($connId ne {})
	 && [info exists socketMapping($connId)]
	 && ($socketMapping($connId) eq $s)
    } {
	Log "Closing connection $connId (sock $socketMapping($connId))"
	if {[catch {close $socketMapping($connId)} err]} {
	    Log "Error closing connection: $err"
	} else {
	}
	if {$token eq {}} {
	    # Cases with a non-empty token are handled by Finish, so the tokens
	    # are finished in connection order.
	    http::CloseQueuedQueries $connId
	} else {
	}
    } else {
	Log "Closing socket $s (no connection info)"
	if {[catch {close $s} err]} {
	    Log "Error closing socket: $err"
	} else {
	}
    }
    return
}

# http::CloseQueuedQueries
#
#	connId  - identifier "domain:port" for the connection
#	token   - (optional) used only for logging
#
# Called from http::CloseSocket and http::Finish, after a connection is closed,
# to clear the read and write queues if this has not already been done.

proc http::CloseQueuedQueries {connId {token {}}} {
    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue
    variable socketPhQueue
    variable socketClosing
    variable socketPlayCmd
    variable socketCoEvent
    variable socketProxyId

    ##Log CloseQueuedQueries $connId $token
    if {![info exists socketMapping($connId)]} {
	# Command has already been called.
	# Don't come here again - especially recursively.
	return
    }

    # Used only for logging.
606
607
608
609
610
611
612

613
614
615
616
617
618
619
620
621
622
623
624

625

626

627
628
629
630
631
632
633
634
635
636
637
638
639
640
641

642
643


644
645
646
647
648
649
650
651


652
653
654
655
656
657
658
659
660
661
662
663

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
707
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922

923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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







+











-
+

+

+















+


+
+








+
+











-
+












+

+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+




+
+
+







	# Before unsetting, there is some unfinished business.
	# - If the server sent "Connection: close", we have stored the command
	#   for retrying any queued requests in socketPlayCmd, so copy that
	#   value for execution below.  socketClosing(*) was also set.
	# - Also clear the queues to prevent calls to Finish that would set the
	#   state for the requests that will be retried to "finished with error
	#   status".
	# - At this stage socketPhQueue is empty.
	set unfinished $socketPlayCmd($connId)
	set socketRdQueue($connId) {}
	set socketWrQueue($connId) {}
    } else {
	set unfinished {}
    }

    Unset $connId

    if {$unfinished ne {}} {
	Log ^R$tk Any unfinished transactions (excluding $token) failed \
		- token $token
		- token $token - unfinished $unfinished
	{*}$unfinished
	# Calls ReplayIfClose.
    }
    return
}

# http::Unset
#
#	The trace on "unset socketRdState(*)" will call CancelReadPipeline
#	and cancel any queued responses.
#	The trace on "unset socketWrState(*)" will call CancelWritePipeline
#	and cancel any queued requests.

proc http::Unset {connId} {
    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue
    variable socketPhQueue
    variable socketClosing
    variable socketPlayCmd
    variable socketCoEvent
    variable socketProxyId

    unset socketMapping($connId)
    unset socketRdState($connId)
    unset socketWrState($connId)
    unset -nocomplain socketRdQueue($connId)
    unset -nocomplain socketWrQueue($connId)
    unset -nocomplain socketClosing($connId)
    unset -nocomplain socketPlayCmd($connId)
    unset -nocomplain socketProxyId($connId)
    return
}

# http::reset --
#
#	See documentation for details.
#
# Arguments:
#	token	Connection token.
#	why	Status info.
#
# Side Effects:
#        See Finish
#	See Finish

proc http::reset {token {why reset}} {
    variable $token
    upvar 0 $token state
    set state(status) $why
    catch {fileevent $state(sock) readable {}}
    catch {fileevent $state(sock) writable {}}
    Finish $token
    if {[info exists state(error)]} {
	set errorlist $state(error)
	unset state
	eval ::error $errorlist
	# i.e. error msg errorInfo errorCode
    }
    return
}

# http::geturl --
#
#	Establishes a connection to a remote url via http.
#
# Arguments:
#	url		The http URL to goget.
#	args		Option value pairs. Valid options include:
#				-blocksize, -validate, -headers, -timeout
# Results:
#	Returns a token for this connection. This token is the name of an
#	array that the caller should unset to garbage collect the state.

proc http::geturl {url args} {
    variable urlTypes

    # - If ::tls::socketCmd has its default value "::socket", change it to the
    #   new value ::http::socketAsCallback.
    # - If the old value is different, then it has been modified either by the
    #   script or by the Tcl installation, and replaced by a new command.  The
    #   script or installation that modified ::tls::socketCmd is also
    #   responsible for integrating ::http::socketAsCallback into its own "new"
    #   command, if it wishes to do so.
    # - Commands that open a socket:
    #   - ::socket                 - basic
    #   - ::http::AltSocket        - can use a thread to avoid blockage by slow
    #                                DNS lookup.  See http::config option
    #                                -threadlevel.
    #   - ::http::socketAsCallback - as ::http::AltSocket, but can also open a
    #                                socket for HTTPS/TLS through a proxy.

    set token [CreateToken $url {*}$args]
    variable $token
    upvar 0 $token state

    AsyncTransaction $token

    # --------------------------------------------------------------------------
    # Synchronous Call to http::geturl
    # --------------------------------------------------------------------------
    # - If the call to http::geturl is asynchronous, it is now complete (apart
    #   from delivering the return value).
    # - If the call to http::geturl is synchronous, the command must now wait
    #   for the HTTP transaction to be completed.  The call to http::wait uses
    #   vwait, which may be inappropriate if the caller makes other HTTP
    #   requests in the background.
    # --------------------------------------------------------------------------

    if {![info exists state(-command)]} {
	# geturl does EVERYTHING asynchronously, so if the user
	# calls it synchronously, we just do a wait here.
	http::wait $token

	if {![info exists state]} {
	    # If we timed out then Finish has been called and the users
	    # command callback may have cleaned up the token. If so we end up
	    # here with nothing left to do.
	    return $token
	} elseif {$state(status) eq "error"} {
	    # Something went wrong while trying to establish the connection.
	    # Clean up after events and such, but DON'T call the command
	    # callback (if available) because we're going to throw an
	    # exception from here instead.
	    set err [lindex $state(error) 0]
	    cleanup $token
	    return -code error $err
	}
    }

    return $token
}

# ------------------------------------------------------------------------------
#  Proc http::CreateToken
# ------------------------------------------------------------------------------
# Command to convert arguments into an initialised request token.
# The return value is the variable name of the token.
#
# Other effects:
# - Sets ::http::http(usingThread) if not already done
# - Sets ::http::http(uid) if not already done
# - Increments ::http::http(uid)
# - May increment ::http::TmpSockCounter
# - Alters ::http::socketPlayCmd, ::http::socketWrQueue if a -keepalive 1
#   request is appended to the queue of a persistent socket that is already
#   scheduled to close.
#   This also sets state(alreadyQueued) to 1.
# - Alters ::http::socketPhQueue if a -keepalive 1 request is appended to the
#   queue of a persistent socket that has not yet been created (and is therefore
#   represented by a placeholder).
#   This also sets state(ReusingPlaceholder) to 1.
# ------------------------------------------------------------------------------

proc http::CreateToken {url args} {
    variable http
    variable urlTypes
    variable defaultCharset
    variable defaultKeepalive
    variable strict
    variable TmpSockCounter

    # Initialize the state variable, an array. We'll return the name of this
    # array as the token for the transaction.

    if {![info exists http(usingThread)]} {
	set http(usingThread) 0
    }
    if {![info exists http(uid)]} {
	set http(uid) 0
    }
    set token [namespace current]::[incr http(uid)]
    ##Log Starting http::geturl - token $token
    variable $token
    upvar 0 $token state
717
718
719
720
721
722
723

724
725
726
727
728
729
730
731
732
733

734
735
736



737







738
739
740
741
742
743
744

745
746
747
748
749

750
751
752
753

754
755
756
757
758
759
760
761
762
763
764


765
766
767
768





769
770
771
772
773
774
775
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
1116
1117
1118
1119
1120


1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138







+









-
+



+
+
+

+
+
+
+
+
+
+







+




-
+



-
+









-
-
+
+




+
+
+
+
+







	-queryblocksize 8192
	-validate	0
	-headers	{}
	-timeout	0
	-type		application/x-www-form-urlencoded
	-queryprogress	{}
	-protocol	1.1
	-guesstype      0
	binary		0
	state		created
	meta		{}
	method		{}
	coding		{}
	currentsize	0
	totalsize	0
	querylength	0
	queryoffset	0
	type		text/html
	type		application/octet-stream
	body		{}
	status		""
	http		""
	httpResponse    {}
	responseCode    {}
	reasonPhrase    {}
	connection	keep-alive
	tid             {}
	requestHeaders  {}
	requestLine     {}
	transfer        {}
	proxyUsed       none
	protoSockThread 0
	protoProxyConn  0
    }
    set state(-keepalive) $defaultKeepalive
    set state(-strict) $strict
    # These flags have their types verified [Bug 811170]
    array set type {
	-binary		boolean
	-blocksize	integer
	-guesstype      boolean
	-queryblocksize integer
	-strict		boolean
	-timeout	integer
	-validate	boolean
	-headers	dict
	-headers	list
    }
    set state(charset)	$defaultCharset
    set options {
	-binary -blocksize -channel -command -handler -headers -keepalive
	-binary -blocksize -channel -command -guesstype -handler -headers -keepalive
	-method -myaddr -progress -protocol -query -queryblocksize
	-querychannel -queryprogress -strict -timeout -type -validate
    }
    set usage [join [lsort $options] ", "]
    set options [string map {- ""} $options]
    set pat ^-(?:[join $options |])$
    foreach {flag value} $args {
	if {[regexp -- $pat $flag]} {
	    # Validate numbers
	    if {($flag eq "-headers") ? [catch {dict size $value}] :
		([info exists type($flag)] && ![string is $type($flag) -strict $value])
	    if {    [info exists type($flag)]
		    && (![string is $type($flag) -strict $value])
	    } {
		unset $token
		return -code error \
		    "Bad value for $flag ($value), must be $type($flag)"
	    }
	    if {($flag eq "-headers") && ([llength $value] % 2 != 0)} {
		unset $token
		return -code error "Bad value for $flag ($value), number\
			of list elements must be even"
	    }
	    set state($flag) $value
	} else {
	    unset $token
	    return -code error "Unknown option $flag, can be: $usage"
	}
    }
813
814
815
816
817
818
819



820
821
822
823
824
825
826
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192







+
+
+







    # The "http" is the protocol, the user is "jschmoe", the password is
    # "xyzzy", the host is "www.bogus.net", the port is "8000", the path is
    # "/foo/bar.tml", the query is "q=foo", and the fragment is "changes".
    #
    # Note that the RE actually combines the user and password parts, as
    # recommended in RFC 3986. Indeed, that RFC states that putting passwords
    # in URLs is a Really Bad Idea, something with which I would agree utterly.
    # RFC 9110 Sec 4.2.4 goes further than this, and deprecates the format
    # "user:password@".  It is retained here for backward compatibility,
    # but its use is not recommended.
    #
    # From a validation perspective, we need to ensure that the parts of the
    # URL that are going to the server are correctly encoded.  This is only
    # done if $state(-strict) is true (inherited from $::http::strict).

    set URLmatcher {(?x)		# this is _expanded_ syntax
	^
916
917
918
919
920
921
922

923
924









925
926
927
928
929
930
931



932
933
934
935
936
937
938
939
940
941
942
943
944
945

946
947
948
949
950
951
952
953
954
955
956
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


1016
1017
1018
1019
1020
1021
1022
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421

1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441







+
-
-
+
+
+
+
+
+
+
+
+







+
+
+













-
+


-
-
-
-
-
-
-
-
-
-
-







+
+
+
+
+
+
+
+
+
+















+
+
+
+
+

-
+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+
+






+


+
+







	set proto http
    }
    set lower [string tolower $proto]
    if {![info exists urlTypes($lower)]} {
	unset $token
	return -code error "Unsupported URL type \"$proto\""
    }
    lassign $urlTypes($lower) defport defcmd socketCmdVarName useSockThread end2EndProxy
    set defport [lindex $urlTypes($lower) 0]
    set defcmd [lindex $urlTypes($lower) 1]

    # If the external handler for protocol $proto has given $socketCmdVarName the expected
    # value "::socket", overwrite it with the new value.
    if {($socketCmdVarName ne {}) && ([set $socketCmdVarName] eq {::socket})} {
	set $socketCmdVarName ::http::socketAsCallback
    }

    set state(protoSockThread) $useSockThread
    set state(protoProxyConn) $end2EndProxy

    if {$port eq ""} {
	set port $defport
    }
    if {![catch {$http(-proxyfilter) $host} proxy]} {
	set phost [lindex $proxy 0]
	set pport [lindex $proxy 1]
    } else {
	set phost {}
	set pport {}
    }

    # OK, now reassemble into a full URL
    set url ${proto}://
    if {$user ne ""} {
	append url $user
	append url @
    }
    append url $host
    if {$port != $defport} {
	append url : $port
    }
    append url $srvurl
    # Don't append the fragment!
    # Don't append the fragment! RFC 7230 Sec 5.1
    set state(url) $url

    set sockopts [list -async]

    # If we are using the proxy, we must pass in the full URL that includes
    # the server name.

    if {[info exists phost] && ($phost ne "")} {
	set srvurl $url
	set targetAddr [list $phost $pport]
    } else {
	set targetAddr [list $host $port]
    }
    # Proxy connections aren't shared among different hosts.
    set state(socketinfo) $host:$port

    # Save the accept types at this point to prevent a race condition. [Bug
    # c11a51c482]
    set state(accept-types) $http(-accept)

    # Check whether this is an Upgrade request.
    set connectionValues [SplitCommaSeparatedFieldValue \
			      [GetFieldValue $state(-headers) Connection]]
    set connectionValues [string tolower $connectionValues]
    set upgradeValues [SplitCommaSeparatedFieldValue \
			   [GetFieldValue $state(-headers) Upgrade]]
    set state(upgradeRequest) [expr {    "upgrade" in $connectionValues
				      && [llength $upgradeValues] >= 1}]
    set state(connectionValues) $connectionValues

    if {$isQuery || $isQueryChannel} {
	# It's a POST.
	# A client wishing to send a non-idempotent request SHOULD wait to send
	# that request until it has received the response status for the
	# previous request.
	if {$http(-postfresh)} {
	    # Override -keepalive for a POST.  Use a new connection, and thus
	    # avoid the small risk of a race against server timeout.
	    set state(-keepalive) 0
	} else {
	    # Allow -keepalive but do not -pipeline - wait for the previous
	    # transaction to finish.
	    # There is a small risk of a race against server timeout.
	    set state(-pipeline) 0
	}
    } elseif {$state(upgradeRequest)} {
	# It's an upgrade request.  Method must be GET (untested).
	# Force -keepalive to 0 so the connection is not made over a persistent
	# socket, i.e. one used for multiple HTTP requests.
	set state(-keepalive) 0
    } else {
	# It's a GET or HEAD.
	# It's a non-upgrade GET or HEAD.
	set state(-pipeline) $http(-pipeline)
    }

    # We cannot handle chunked encodings with -handler, so force HTTP/1.0
    # until we can manage this.
    if {[info exists state(-handler)]} {
	set state(-protocol) 1.0
    }

    # RFC 7320 A.1 - HTTP/1.0 Keep-Alive is problematic. We do not support it.
    if {$state(-protocol) eq "1.0"} {
	set state(connection) close
	set state(-keepalive) 0
    }

    # Handle proxy requests here for http:// but not for https://
    # The proxying for https is done in the ::http::socketAsCallback command.
    # A proxy request for http:// needs the full URL in the HTTP request line,
    # including the server name.
    # The *tls* test below attempts to describe protocols in addition to
    # "https on port 443" that use HTTP over TLS.
    if {($phost ne "") && (!$end2EndProxy)} {
	set srvurl $url
	set targetAddr [list $phost $pport]
	set state(proxyUsed) HttpProxy
	# The value of state(proxyUsed) none|HttpProxy depends only on the
	# all-transactions http::config settings and on the target URL.
	# Even if this is a persistent socket there is no need to change the
	# value of state(proxyUsed) for other transactions that use the socket:
	# they have the same value already.
    } else {
	set targetAddr [list $host $port]
    }

    set sockopts [list -async]

    # Pass -myaddr directly to the socket command
    if {[info exists state(-myaddr)]} {
	lappend sockopts -myaddr $state(-myaddr)
    }

    if {$useSockThread} {
	set targs [list -type $token]
    } else {
	set targs {}
    }
    set state(connArgs) [list $proto $phost $srvurl]
    set state(openCmd) [list {*}$defcmd {*}$sockopts {*}$targs {*}$targetAddr]

    # See if we are supposed to use a previously opened channel.
    # - In principle, ANY call to http::geturl could use a previously opened
    #   channel if it is available - the "Connection: keep-alive" header is a
    #   request to leave the channel open AFTER completion of this call.
    # - In fact, we try to use an existing channel only if -keepalive 1 -- this
    #   means that at most one channel is left open for each value of
    #   $state(socketinfo). This property simplifies the mapping of open
    #   channels.
    set reusing 0
    set alreadyQueued 0
    set state(alreadyQueued) 0
    set state(ReusingPlaceholder) 0
    if {$state(-keepalive)} {
	variable socketMapping
	variable socketRdState
	variable socketWrState
	variable socketRdQueue
	variable socketWrQueue
	variable socketPhQueue
	variable socketClosing
	variable socketPlayCmd
	variable socketCoEvent
	variable socketProxyId

	if {[info exists socketMapping($state(socketinfo))]} {
	    # - If the connection is idle, it has a "fileevent readable" binding
	    #   to http::CheckEof, in case the server times out and half-closes
	    #   the socket (http::CheckEof closes the other half).
	    # - We leave this binding in place until just before the last
	    #   puts+flush in http::Connected (GET/HEAD) or http::Write (POST),
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
1116
1117
1118
1119
1120
1121















































1122










1123
1124
1125
1126
1127
1128
1129
1130
1131



1132
1133
1134
1135
1136










1137
1138
1139
1140
1141
1142


































1143
1144
1145
1146
1147
1148
1149
1150
1151
1152














































































1153
1154
1155
1156

1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169

















1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180



































1181
1182

1183
1184
1185









1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209























1210








































1211




1212
1213
1214
1215
1216
1217
1218
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
1478
1479
1480
1481
1482
1483
1484




1485
1486
1487
1488
1489
1490
1491
1492
1493
1494


1495
1496
1497
1498
1499
1500
1501
1502
1503
1504













1505
1506









1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791



1792
1793
1794
1795
1796
1797
1798
1799
1800
1801






1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835










1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972


1973



1974
1975
1976
1977
1978
1979
1980
1981
1982
























1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046

2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057







+
-
+

-
+




+
+
+
-
+
+
+
+













-
-
-
-
+
+
+
+
+


+
+
+
-
-
+
+
+
+






-
-
-
-
-
-
-
-
-
-
-
-
-

+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+









+
+
+


-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+
-



-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+







		# Since we have only one persistent socket per server, and the
		# old socket is not yet dead, add the request to the write queue
		# of the dying socket, which will be replayed by ReplayIfClose.
		# Also add it to socketWrQueue(*) which is used only if an error
		# causes a call to Finish.
		set reusing 1
		set sock $socketMapping($state(socketinfo))
		set state(proxyUsed) $socketProxyId($state(socketinfo))
		Log "reusing socket $sock for $state(socketinfo) - token $token"
		Log "reusing closing socket $sock for $state(socketinfo) - token $token"

		set alreadyQueued 1
		set state(alreadyQueued) 1
		lassign $socketPlayCmd($state(socketinfo)) com0 com1 com2 com3
		lappend com3 $token
		set socketPlayCmd($state(socketinfo)) [list $com0 $com1 $com2 $com3]
		lappend socketWrQueue($state(socketinfo)) $token
		##Log socketPlayCmd($state(socketinfo)) is $socketPlayCmd($state(socketinfo))
		##Log socketWrQueue($state(socketinfo)) is $socketWrQueue($state(socketinfo))
	    } elseif {
	    } elseif {[catch {fconfigure $socketMapping($state(socketinfo))}]} {
		   [catch {fconfigure $socketMapping($state(socketinfo))}]
		&& (![SockIsPlaceHolder $socketMapping($state(socketinfo))])
	    } {
		###Log "Socket $socketMapping($state(socketinfo)) for $state(socketinfo)"
		# FIXME Is it still possible for this code to be executed? If
		#       so, this could be another place to call TestForReplay,
		#       rather than discarding the queued transactions.
		Log "WARNING: socket for $state(socketinfo) was closed\
			- token $token"
		Log "WARNING - if testing, pay special attention to this\
			case (GH) which is seldom executed - token $token"

		# This will call CancelReadPipeline, CancelWritePipeline, and
		# cancel any queued requests, responses.
		Unset $state(socketinfo)
	    } else {
		# Use the persistent socket.
		# The socket may not be ready to write: an earlier request might
		# still be still writing (in the pipelined case) or
		# writing/reading (in the nonpipeline case). This possibility
		# is handled by socketWrQueue later in this command.
		# - The socket may not be ready to write: an earlier request might
		#   still be still writing (in the pipelined case) or
		#   writing/reading (in the nonpipeline case). This possibility
		#   is handled by socketWrQueue later in this command.
		# - The socket may not yet exist, and be defined with a placeholder.
		set reusing 1
		set sock $socketMapping($state(socketinfo))
		set state(proxyUsed) $socketProxyId($state(socketinfo))
		if {[SockIsPlaceHolder $sock]} {
		    set state(ReusingPlaceholder) 1
		Log "reusing socket $sock for $state(socketinfo) - token $token"

		    lappend socketPhQueue($sock) $token
		} else {
		}
		Log "reusing open socket $sock for $state(socketinfo) - token $token"
	    }
	    # Do not automatically close the connection socket.
	    set state(connection) keep-alive
	}
    }

    if {$reusing} {
	# Define state(tmpState) and state(tmpOpenCmd) for use
	# by http::ReplayIfDead if the persistent connection has died.
	set state(tmpState) [array get state]

	# Pass -myaddr directly to the socket command
	if {[info exists state(-myaddr)]} {
	    lappend sockopts -myaddr $state(-myaddr)
	}

	set state(tmpOpenCmd) [list {*}$defcmd {*}$sockopts {*}$targetAddr]
    }

    set state(reusing) $reusing
    unset reusing
    # Excluding ReplayIfDead and the decision whether to call it, there are four
    # places outside http::geturl where state(reusing) is used:
    # - Connected   - if reusing and not pipelined, start the state(-timeout)
    #                 timeout (when writing).
    # - DoneRequest - if reusing and pipelined, send the next pipelined write
    # - Event       - if reusing and pipelined, start the state(-timeout)
    #                 timeout (when reading).
    # - Event       - if (not reusing) and pipelined, send the next pipelined
    #                 write

    if {![info exists sock]} {
	# N.B. At this point ([info exists sock] == $state(reusing)).
	# This will no longer be true after we set a value of sock here.
	# Give the socket a placeholder name.
	set sock HTTP_PLACEHOLDER_[incr TmpSockCounter]
    }
    set state(sock) $sock

    if {$state(reusing)} {
	# Define these for use (only) by http::ReplayIfDead if the persistent
	# connection has died.
	set state(tmpConnArgs) $state(connArgs)
	set state(tmpState) [array get state]
	set state(tmpOpenCmd) $state(openCmd)
    }
    return $token
}


# ------------------------------------------------------------------------------
#  Proc ::http::SockIsPlaceHolder
# ------------------------------------------------------------------------------
# Command to return 0 if the argument is a genuine socket handle, or 1 if is a
# placeholder value generated by geturl or ReplayCore before the real socket is
# created.
#
# Arguments:
# sock        - either a valid socket handle or a placeholder value
#
# Return Value: 0 or 1
# ------------------------------------------------------------------------------

proc http::SockIsPlaceHolder {sock} {
    expr {[string range $sock 0 16] eq {HTTP_PLACEHOLDER_}}
}


# ------------------------------------------------------------------------------
# state(reusing)
# ------------------------------------------------------------------------------
# - state(reusing) is set by geturl, ReplayCore
# - state(reusing) is used by geturl, AsyncTransaction, OpenSocket,
#   ConfigureNewSocket, and ScheduleRequest when creating and configuring the
#   connection.
# - state(reusing) is used by Connect, Connected, Event x 2 when deciding
#   whether to call TestForReplay.
# - Other places where state(reusing) is used:
#   - Connected   - if reusing and not pipelined, start the state(-timeout)
#                   timeout (when writing).
#   - DoneRequest - if reusing and pipelined, send the next pipelined write
#   - Event       - if reusing and pipelined, start the state(-timeout)
#                   timeout (when reading).
#   - Event       - if (not reusing) and pipelined, send the next pipelined
#                   write.
# ------------------------------------------------------------------------------


# ------------------------------------------------------------------------------
#  Proc http::AsyncTransaction
# ------------------------------------------------------------------------------
# This command is called by geturl and ReplayCore to prepare the HTTP
# transaction prescribed by a suitably prepared token.
#
# Arguments:
# token         - connection token (name of an array)
#
# Return Value: none
# ------------------------------------------------------------------------------

proc http::AsyncTransaction {token} {
    variable $token
    upvar 0 $token state
    set tk [namespace tail $token]

    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue
    variable socketPhQueue
    variable socketClosing
    variable socketPlayCmd
    variable socketCoEvent
    variable socketProxyId

    set sock $state(sock)

    # See comments above re the start of this timeout in other cases.
    if {(!$state(reusing)) && ($state(-timeout) > 0)} {
	set state(after) [after $state(-timeout) \
		[list http::reset $token timeout]]
    }

    if {    $state(-keepalive)
	 && (![info exists socketMapping($state(socketinfo))])
    } {
	# This code is executed only for the first -keepalive request on a
	# socket.  It makes the socket persistent.
	##Log "  PreparePersistentConnection" $token -- $sock -- DO
	set DoLater [PreparePersistentConnection $token]
    } else {
	##Log "  PreparePersistentConnection" $token -- $sock -- SKIP
	set DoLater {-traceread 0 -tracewrite 0}
    }

    if {$state(ReusingPlaceholder)} {
	# - This request was added to the socketPhQueue of a persistent
	#   connection.
	# - But the connection has not yet been created and is a placeholder;
	# - And the placeholder was created by an earlier request.
	# - When that earlier request calls OpenSocket, its placeholder is
	#   replaced with a true socket, and it then executes the equivalent of
	#   OpenSocket for any subsequent requests that have
	#   $state(ReusingPlaceholder).
	Log >J$tk after idle coro NO - ReusingPlaceholder
    } elseif {$state(alreadyQueued)} {
	# - This request was added to the socketWrQueue and socketPlayCmd
	#   of a persistent connection that will close at the end of its current
	#   read operation.
	Log >J$tk after idle coro NO - alreadyQueued
    } else {
	Log >J$tk after idle coro YES
	set CoroName ${token}--SocketCoroutine
	set cancel [after idle [list coroutine $CoroName ::http::OpenSocket \
		$token $DoLater]]
	dict set socketCoEvent($state(socketinfo)) $token $cancel
	set state(socketcoro) $cancel
    }

    return
}


# ------------------------------------------------------------------------------
#  Proc http::PreparePersistentConnection
# ------------------------------------------------------------------------------
# This command is called by AsyncTransaction to initialise a "persistent
# connection" based upon a socket placeholder.  It is called the first time the
# socket is associated with a "-keepalive" request.
#
# Arguments:
# token         - connection token (name of an array)
#
# Return Value: - DoLater, a dictionary of boolean values listing unfinished
#                 tasks; to be passed to ConfigureNewSocket via OpenSocket.
# ------------------------------------------------------------------------------

proc http::PreparePersistentConnection {token} {
    variable $token
    upvar 0 $token state

    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue
    variable socketPhQueue
    variable socketClosing
    variable socketPlayCmd
    variable socketCoEvent
    variable socketProxyId

    set DoLater {-traceread 0 -tracewrite 0}
    set socketMapping($state(socketinfo)) $state(sock)
    set socketProxyId($state(socketinfo)) $state(proxyUsed)
    # - The value of state(proxyUsed) was set in http::CreateToken to either
    #   "none" or "HttpProxy".
    # - $token is the first transaction to use this placeholder, so there are
    #   no other tokens whose (proxyUsed) must be modified.

    if {![info exists socketRdState($state(socketinfo))]} {
	set socketRdState($state(socketinfo)) {}
	# set varName ::http::socketRdState($state(socketinfo))
	# trace add variable $varName unset ::http::CancelReadPipeline
	dict set DoLater -traceread 1
    }
    if {![info exists sock]} {
	# Pass -myaddr directly to the socket command
	if {[info exists state(-myaddr)]} {
	    lappend sockopts -myaddr $state(-myaddr)
	}
	set pre [clock milliseconds]
	##Log pre socket opened, - token $token
    if {![info exists socketWrState($state(socketinfo))]} {
	set socketWrState($state(socketinfo)) {}
	# set varName ::http::socketWrState($state(socketinfo))
	# trace add variable $varName unset ::http::CancelWritePipeline
	dict set DoLater -tracewrite 1
    }

    if {$state(-pipeline)} {
	#Log new, init for pipelined, GRANT write access to $token in geturl
	# Also grant premature read access to the socket. This is OK.
	set socketRdState($state(socketinfo)) $token
	set socketWrState($state(socketinfo)) $token
    } else {
	# socketWrState is not used by this non-pipelined transaction.
	# We cannot leave it as "Wready" because the next call to
	# http::geturl with a pipelined transaction would conclude that the
	# socket is available for writing.
	#Log new, init for nonpipeline, GRANT r/w access to $token in geturl
	set socketRdState($state(socketinfo)) $token
	set socketWrState($state(socketinfo)) $token
    }

    # Value of socketPhQueue() may have already been set by ReplayCore.
    if {![info exists socketPhQueue($state(sock))]} {
	set socketPhQueue($state(sock))   {}
	##Log [concat $defcmd $sockopts $targetAddr] - token $token
	if {[catch {eval $defcmd $sockopts $targetAddr} sock errdict]} {
	    # Something went wrong while trying to establish the connection.
	    # Clean up after events and such, but DON'T call the command
    }
    set socketRdQueue($state(socketinfo)) {}
    set socketWrQueue($state(socketinfo)) {}
    set socketClosing($state(socketinfo)) 0
    set socketPlayCmd($state(socketinfo)) {ReplayIfClose Wready {} {}}
    set socketCoEvent($state(socketinfo)) {}
    set socketProxyId($state(socketinfo)) {}

    return $DoLater
}

	    # callback (if available) because we're going to throw an
	    # exception from here instead.

	    set state(sock) NONE
	    Finish $token $sock 1
	    cleanup $token
	    dict unset errdict -level
	    return -options $errdict $sock
# ------------------------------------------------------------------------------
#  Proc ::http::OpenSocket
# ------------------------------------------------------------------------------
# This command is called as a coroutine idletask to start the asynchronous HTTP
# transaction in most cases.  For the exceptions, see the calling code in
# command AsyncTransaction.
#
# Arguments:
# token       - connection token (name of an array)
# DoLater     - dictionary of boolean values listing unfinished tasks
#
# Return Value: none
# ------------------------------------------------------------------------------

proc http::OpenSocket {token DoLater} {
    variable $token
    upvar 0 $token state
    set tk [namespace tail $token]

    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue
    variable socketPhQueue
    variable socketClosing
    variable socketPlayCmd
    variable socketCoEvent
    variable socketProxyId

    Log >K$tk Start OpenSocket coroutine

    if {![info exists state(-keepalive)]} {
	# The request has already been cancelled by the calling script.
	return
    }

    set sockOld $state(sock)

    dict unset socketCoEvent($state(socketinfo)) $token
    unset -nocomplain state(socketcoro)

    if {[catch {
	if {$state(reusing)} {
	    # If ($state(reusing)) is true, then we do not need to create a new
	    # socket, even if $sockOld is only a placeholder for a socket.
	    set sock $sockOld
	} else {
	    # set sock in the [catch] below.
	    set pre [clock milliseconds]
	    ##Log pre socket opened, - token $token
	    ##Log $state(openCmd) - token $token
	    set sock [namespace eval :: $state(openCmd)]
	    set state(sock) $sock
	    # Normal return from $state(openCmd) always returns a valid socket.
	    # A TLS proxy connection with 407 or other failure from the
	    # proxy server raises an error.

	    # Initialisation of a new socket.
	    ##Log post socket opened, - token $token
	    ##Log socket opened, now fconfigure - token $token
	    set delay [expr {[clock milliseconds] - $pre}]
	    if {$delay > 3000} {
		Log socket delay $delay - token $token
	    }
	    fconfigure $sock -translation {auto crlf} \
			     -buffersize $state(-blocksize)
	    if {[package vsatisfies [package provide Tcl] 9.0-]} {
		fconfigure $sock -profile replace
	    }
	    ##Log socket opened, DONE fconfigure - token $token
	}
    }
    # Command [socket] is called with -async, but takes 5s to 5.1s to return,
    # with probability of order 1 in 10,000.  This may be a bizarre scheduling

	Log "Using $sock for $state(socketinfo) - token $token" \
	    [expr {$state(-keepalive)?"keepalive":""}]

	# Code above has set state(sock) $sock
	ConfigureNewSocket $token $sockOld $DoLater
	##Log OpenSocket success $sock - token $token
    } result errdict]} {
	##Log OpenSocket failed $result - token $token
	# There may be other requests in the socketPhQueue.
    # issue with my (KJN's) system (Fedora Linux).
    # This does not cause a problem (unless the request times out when this
    # command returns).

    set state(sock) $sock
    Log "Using $sock for $state(socketinfo) - token $token" \
	# Prepare socketPlayCmd so that Finish will replay them.
	if {    ($state(-keepalive)) && (!$state(reusing))
	     && [info exists socketPhQueue($sockOld)]
	     && ($socketPhQueue($sockOld) ne {})
	} {
	    if {$socketMapping($state(socketinfo)) ne $sockOld} {
		Log "WARNING: this code should not be reached.\
			{$socketMapping($state(socketinfo)) ne $sockOld}"
	    }
	    set socketPlayCmd($state(socketinfo)) [list ReplayIfClose Wready {} $socketPhQueue($sockOld)]
	    set socketPhQueue($sockOld) {}
	}
	if {[string range $result 0 20] eq {proxy connect failed:}} {
	    # - The HTTPS proxy did not create a socket.  The pre-existing value
	    #   (a "placeholder socket") is unchanged.
	    # - The proxy returned a valid HTTP response to the failed CONNECT
	    #   request, and http::SecureProxyConnect copied this to $token,
	    #   and also set ${token}(connection) set to "close".
	    # - Remove the error message $result so that Finish delivers this
	    #   HTTP response to the caller.
	    set result {}
	}
	Finish $token $result
	# Because socket creation failed, the placeholder "socket" must be
	# "closed" and (if persistent) removed from the persistent sockets
	# table.  In the {proxy connect failed:} case Finish does this because
	# the value of ${token}(connection) is "close". In the other cases here,
	# it does so because $result is non-empty.
    }
    ##Log Leaving http::OpenSocket coroutine [info coroutine] - token $token
    return
}


	[expr {$state(-keepalive)?"keepalive":""}]

    if {    $state(-keepalive)
	 && (![info exists socketMapping($state(socketinfo))])
    } {
	# Freshly-opened socket that we would like to become persistent.
	set socketMapping($state(socketinfo)) $sock

	if {![info exists socketRdState($state(socketinfo))]} {
	    set socketRdState($state(socketinfo)) {}
# ------------------------------------------------------------------------------
#  Proc ::http::ConfigureNewSocket
# ------------------------------------------------------------------------------
# Command to initialise a newly-created socket.  Called only from OpenSocket.
#
# This command is called by OpenSocket whenever a genuine socket (sockNew) has
# been opened for for use by HTTP.  It does two things:
# (1) If $token uses a placeholder socket, this command replaces the placeholder
#     socket with the real socket, not only in $token but in all other requests
#     that use the same placeholder.
# (2) It calls ScheduleRequest to schedule each request that uses the socket.
#
#
# Value of sockOld/sockNew can be "sock" (genuine socket) or "ph" (placeholder).
# sockNew is ${token}(sock)
# sockOld   sockNew  CASES
#  sock       sock   (if $reusing, and sockOld is sock)
#  ph         sock   (if (not $reusing), and sockOld is ph)
#  ph         ph     (if $reusing, and sockOld is ph) - not called in this case
#  sock       ph     (cannot occur unless a bug)      - not called in this case
#                    (if (not $reusing), and sockOld is sock) - illogical
#
# Arguments:
# token         - connection token (name of an array)
# sockOld       - handle or placeholder used for a socket before the call to
#                 OpenSocket
# DoLater       - dictionary of boolean values listing unfinished tasks
#
# Return Value: none
# ------------------------------------------------------------------------------

proc http::ConfigureNewSocket {token sockOld DoLater} {
    variable $token
    upvar 0 $token state
    set tk [namespace tail $token]

    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue
    variable socketPhQueue
    variable socketClosing
    variable socketPlayCmd
    variable socketCoEvent
    variable socketProxyId

    set reusing $state(reusing)
    set sock $state(sock)
    set proxyUsed $state(proxyUsed)
    ##Log "  ConfigureNewSocket" $token $sockOld ... -- $reusing $sock $proxyUsed

    if {(!$reusing) && ($sock ne $sockOld)} {
	# Replace the placeholder value sockOld with sock.

	if {    [info exists socketMapping($state(socketinfo))]
	     && ($socketMapping($state(socketinfo)) eq $sockOld)
	} {
	    set socketMapping($state(socketinfo)) $sock
	    set socketProxyId($state(socketinfo)) $proxyUsed
	    # tokens that use the placeholder $sockOld are updated below.
	    ##Log set socketMapping($state(socketinfo)) $sock
	}

	# Now finish any tasks left over from PreparePersistentConnection on
	# the connection.
	#
	# The "unset" traces are fired by init (clears entire arrays), and
	# by http::Unset.
	# Unset is called by CloseQueuedQueries and (possibly never) by geturl.
	#
	# CancelReadPipeline, CancelWritePipeline call http::Finish for each
	# token.
	#
	# FIXME If Finish is placeholder-aware, these traces can be set earlier,
	# in PreparePersistentConnection.

	if {[dict get $DoLater -traceread]} {
	    set varName ::http::socketRdState($state(socketinfo))
	    trace add variable $varName unset ::http::CancelReadPipeline
	}
	if {![info exists socketWrState($state(socketinfo))]} {
	if {[dict get $DoLater -tracewrite]} {
	    set socketWrState($state(socketinfo)) {}
	    set varName ::http::socketWrState($state(socketinfo))
	    trace add variable $varName unset ::http::CancelWritePipeline
	}

	if {$state(-pipeline)} {
	    #Log new, init for pipelined, GRANT write access to $token in geturl
	    # Also grant premature read access to the socket. This is OK.
	    set socketRdState($state(socketinfo)) $token
	    set socketWrState($state(socketinfo)) $token
	} else {
	    # socketWrState is not used by this non-pipelined transaction.
	    # We cannot leave it as "Wready" because the next call to
    }

    # Do this in all cases.
    ScheduleRequest $token

    # Now look at all other tokens that use the placeholder $sockOld.
    if {    (!$reusing)
	 && ($sock ne $sockOld)
	 && [info exists socketPhQueue($sockOld)]
    } {
	##Log "  ConfigureNewSocket" $token scheduled, now do $socketPhQueue($sockOld)
	foreach tok $socketPhQueue($sockOld) {
	    # 1. Amend the token's (sock).
	    ##Log set ${tok}(sock) $sock
	    set ${tok}(sock) $sock
	    set ${tok}(proxyUsed) $proxyUsed

	    # http::geturl with a pipelined transaction would conclude that the
	    # socket is available for writing.
	    #Log new, init for nonpipeline, GRANT r/w access to $token in geturl
	    set socketRdState($state(socketinfo)) $token
	    set socketWrState($state(socketinfo)) $token
	}

	set socketRdQueue($state(socketinfo)) {}
	set socketWrQueue($state(socketinfo)) {}
	set socketClosing($state(socketinfo)) 0
	set socketPlayCmd($state(socketinfo)) {ReplayIfClose Wready {} {}}
	    # 2. Schedule the token's HTTP request.
	    # Every token in socketPhQueue(*) has reusing 1 alreadyQueued 0.
	    set ${tok}(reusing) 1
	    set ${tok}(alreadyQueued) 0
	    ScheduleRequest $tok
	}
	set socketPhQueue($sockOld) {}
    }
    ##Log "  ConfigureNewSocket" $token DONE

    return
}


# ------------------------------------------------------------------------------
# The values of array variables socketMapping etc.
# ------------------------------------------------------------------------------
# connId                 "$host:$port"
# socketMapping($connId) the handle or placeholder for the socket that is used
#                        for "-keepalive 1" requests to $connId.
# socketRdState($connId) the token that is currently reading from the socket.
#                        Other values: Rready (ready for next token to read).
# socketWrState($connId) the token that is currently writing to the socket.
#                        Other values: Wready (ready for next token to write),
#                        peNding (would be ready for next write, except that
#                        the integrity of a non-pipelined transaction requires
#                        waiting until the read(s) in progress are finished).
# socketRdQueue($connId) List of tokens that are queued for reading later.
# socketWrQueue($connId) List of tokens that are queued for writing later.
# socketPhQueue($sock)   List of tokens that are queued to use a placeholder
#                        socket, when the real socket has not yet been created.
# socketClosing($connId) (boolean) true iff a server response header indicates
#                        that the server will close the connection at the end of
#                        the current response.
# socketPlayCmd($connId) The command to execute to replay pending and
    }

#                        part-completed transactions if the socket closes early.
    if {![info exists phost]} {
	set phost ""
    }
# socketCoEvent($connId) Identifier for the "after idle" event that will launch
#                        an OpenSocket coroutine to open or re-use a socket.
# socketProxyId($connId) The type of proxy that this socket uses: values are
#                        those of state(proxyUsed) i.e. none, HttpProxy,
#                        SecureProxy, and SecureProxyFailed.
#                        The value is not used for anything by http, its purpose
#                        is to set the value of state() for caller information.
# ------------------------------------------------------------------------------

    if {$reusing} {
	# For use by http::ReplayIfDead if the persistent connection has died.
	# Also used by NextPipelinedWrite.
	set state(tmpConnArgs) [list $proto $phost $srvurl]
    }

    # The element socketWrState($connId) has a value which is either the name of
    # the token that is permitted to write to the socket, or "Wready" if no
    # token is permitted to write.
    #
    # The code that sets the value to Wready immediately calls
    # http::NextPipelinedWrite, which examines socketWrQueue($connId) and
    # processes the next request in the queue, if there is one.  The value
    # Wready is not found when the interpreter is in the event loop unless the
    # socket is idle.
    #
    # The element socketRdState($connId) has a value which is either the name of
    # the token that is permitted to read from the socket, or "Rready" if no
    # token is permitted to read.
    #
    # The code that sets the value to Rready then examines
    # socketRdQueue($connId) and processes the next request in the queue, if
    # there is one.  The value Rready is not found when the interpreter is in
    # the event loop unless the socket is idle.

# ------------------------------------------------------------------------------
# Using socketWrState(*), socketWrQueue(*), socketRdState(*), socketRdQueue(*)
# ------------------------------------------------------------------------------
# The element socketWrState($connId) has a value which is either the name of
# the token that is permitted to write to the socket, or "Wready" if no
# token is permitted to write.
#
# The code that sets the value to Wready immediately calls
# http::NextPipelinedWrite, which examines socketWrQueue($connId) and
# processes the next request in the queue, if there is one.  The value
# Wready is not found when the interpreter is in the event loop unless the
# socket is idle.
#
# The element socketRdState($connId) has a value which is either the name of
# the token that is permitted to read from the socket, or "Rready" if no
# token is permitted to read.
#
# The code that sets the value to Rready then examines
# socketRdQueue($connId) and processes the next request in the queue, if
# there is one.  The value Rready is not found when the interpreter is in
# the event loop unless the socket is idle.
# ------------------------------------------------------------------------------


# ------------------------------------------------------------------------------
#  Proc http::ScheduleRequest
# ------------------------------------------------------------------------------
# Command to either begin the HTTP request, or add it to the appropriate queue.
# Called from two places in ConfigureNewSocket.
#
# Arguments:
# token         - connection token (name of an array)
#
# Return Value: none
# ------------------------------------------------------------------------------

proc http::ScheduleRequest {token} {
    variable $token
    upvar 0 $token state
    set tk [namespace tail $token]

    Log >L$tk ScheduleRequest

    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue
    variable socketPhQueue
    variable socketClosing
    variable socketPlayCmd
    variable socketCoEvent
    variable socketProxyId

    set Unfinished 0

    set reusing $state(reusing)
    set sockNew $state(sock)

    # The "if" tests below: must test against the current values of
    # socketWrState, socketRdState, and so the tests must be done here,
    # not earlier in PreparePersistentConnection.

    if {$alreadyQueued} {
    if {$state(alreadyQueued)} {
	# The request has been appended to the queue of a persistent socket
	# (that is scheduled to close and have its queue replayed).
	#
	# A write may or may not be in progress.  There is no need to set
	# socketWrState to prevent another call stealing write access - all
	# subsequent calls on this socket will come here because the socket
	# will close after the current read, and its
	# socketClosing($connId) is 1.
	##Log "HTTP request for token $token is queued"

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
2076
2077
2078
2079
2080
2081
2082

2083
2084
2085
2086
2087

2088
2089
2090
2091

2092
2093


2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105


2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119



2120
2121
2122
2123
2124
2125
2126







2127
2128





2129
2130
2131











2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161







-





-
+
+
+

-

+
-
-
+
+
+
+


+


+
+
+
-
-
+
+
+
+
+
+
+

+

+
+
+
+
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	       && ($socketRdState($state(socketinfo)) ne "Rready")
    } {
	# A read is queued or in progress, but not a write.  Cannot start the
	# nonpipeline transaction, but must set socketWrState to prevent a
	# pipelined request jumping the queue.
	##Log "HTTP request for token $token is queued for nonpipeline use"
	#Log re-use nonpipeline, GRANT delayed write access to $token in geturl

	set socketWrState($state(socketinfo)) peNding
	lappend socketWrQueue($state(socketinfo)) $token

    } else {
	if {$reusing && $state(-pipeline)} {
	    #Log re-use pipelined, GRANT write access to $token in geturl
	    #Log new, init for pipelined, GRANT write access to $token in geturl
	    # DO NOT grant premature read access to the socket.
	    # set socketRdState($state(socketinfo)) $token
	    set socketWrState($state(socketinfo)) $token

	} elseif {$reusing} {
	    # socketWrState is not used by this non-pipelined transaction.
	    # Cf tests above - both are ready.
	    #Log re-use nonpipeline, GRANT r/w access to $token in geturl
	    # We cannot leave it as "Wready" because the next call to
	    # http::geturl with a pipelined transaction would conclude that the
	    # socket is available for writing.
	    #Log new, init for nonpipeline, GRANT r/w access to $token in geturl
	    set socketRdState($state(socketinfo)) $token
	    set socketWrState($state(socketinfo)) $token
	} else {
	}

	# Process the request now.
	# - Command is not called unless $state(sock) is a real socket handle
	#   and not a placeholder.
	# All (!$reusing) cases come here, and also some $reusing cases if the
	# connection is ready.
	# - All (!$reusing) cases come here.
	# - Some $reusing cases come here too if the connection is
	#   marked as ready.  Those $reusing cases are:
	#   $reusing && ($socketWrState($state(socketinfo)) eq "Wready") &&
	#   EITHER !$pipeline && ($socketRdState($state(socketinfo)) eq "Rready")
	#   OR      $pipeline
	#
	#Log ---- $state(socketinfo) << conn to $token for HTTP request (a)
	##Log "  ScheduleRequest" $token -- fileevent $state(sock) writable for $token
	# Connect does its own fconfigure.

	lassign $state(connArgs) proto phost srvurl

	if {[catch {
	fileevent $sock writable \
		[list http::Connect $token $proto $phost $srvurl]
    }
		fileevent $state(sock) writable \
			[list http::Connect $token $proto $phost $srvurl]
	} res opts]} {
	    # The socket no longer exists.
	    ##Log bug -- socket gone -- $res -- $opts
	}

    # Wait for the connection to complete.
    if {![info exists state(-command)]} {
	# geturl does EVERYTHING asynchronously, so if the user
	# calls it synchronously, we just do a wait here.
	http::wait $token

	if {![info exists state]} {
    }

	    # If we timed out then Finish has been called and the users
	    # command callback may have cleaned up the token. If so we end up
	    # here with nothing left to do.
	    return $token
	} elseif {$state(status) eq "error"} {
    return
}

	    # Something went wrong while trying to establish the connection.
	    # Clean up after events and such, but DON'T call the command
	    # callback (if available) because we're going to throw an
	    # exception from here instead.
	    set err [lindex $state(error) 0]
	    cleanup $token
	    return -code error $err
	}
    }
    ##Log Leaving http::geturl - token $token
    return $token

# ------------------------------------------------------------------------------
#  Proc http::SendHeader
# ------------------------------------------------------------------------------
# Command to send a request header, and keep a copy in state(requestHeaders)
# for debugging purposes.
#
# Arguments:
# token       - connection token (name of an array)
# key         - header name
# value       - header value
#
# Return Value: none
# ------------------------------------------------------------------------------

proc http::SendHeader {token key value} {
    variable $token
    upvar 0 $token state
    set tk [namespace tail $token]
    set sock $state(sock)
    lappend state(requestHeaders) [string tolower $key] $value
    puts $sock "$key: $value"
    return
}

# http::Connected --
#
#	Callback used when the connection to the HTTP server is actually
#	established.
#
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
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







+


+
+














-
+
-










+
+
+







    variable http
    variable urlTypes
    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue
    variable socketPhQueue
    variable socketClosing
    variable socketPlayCmd
    variable socketCoEvent
    variable socketProxyId

    variable $token
    upvar 0 $token state
    set tk [namespace tail $token]

    if {$state(reusing) && (!$state(-pipeline)) && ($state(-timeout) > 0)} {
	set state(after) [after $state(-timeout) \
		[list http::reset $token timeout]]
    }

    # Set back the variables needed here.
    set sock $state(sock)
    set isQueryChannel [info exists state(-querychannel)]
    set isQuery [info exists state(-query)]
    set host [lindex [split $state(socketinfo) :] 0]
    regexp {^(.+):([^:]+)$} $state(socketinfo) {} host port
    set port [lindex [split $state(socketinfo) :] 1]

    set lower [string tolower $proto]
    set defport [lindex $urlTypes($lower) 0]

    # Send data in cr-lf format, but accept any line terminators.
    # Initialisation to {auto *} now done in geturl, KeepSocket and DoneRequest.
    # We are concerned here with the request (write) not the response (read).
    lassign [fconfigure $sock -translation] trRead trWrite
    fconfigure $sock -translation [list $trRead crlf] \
		     -buffersize $state(-blocksize)
    if {[package vsatisfies [package provide Tcl] 9.0-]} {
	fconfigure $sock -profile replace
    }

    # The following is disallowed in safe interpreters, but the socket is
    # already in non-blocking mode in that case.

    catch {fconfigure $sock -blocking off}
    set how GET
    if {$isQuery} {
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
1393
1394
1395

1396
1397
1398
1399
1400





1401
1402
1403
1404
1405
1406
1407






1408
1409
1410
1411
1412

1413

1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431























1432
1433

1434
1435
1436
1437
1438
1439

1440
1441
1442
1443
1444


1445





1446
1447
1448
1449
1450
1451
1452
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





2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283

2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295

2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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







+
+
+
+
+
-
-
-
+
+
+
+
+
+
+

-
-
-
+
+




-
+


-
+

-
+



-
+
-
-
-
-
-
+
+
+
+
+






-
+
+
+
+
+
+





+
-
+


















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+





-
+





+
+
-
+
+
+
+
+







	set how $state(-method)
    }
    set accept_types_seen 0

    Log ^B$tk begin sending request - token $token

    if {[catch {
	if {[info exists state(bypass)]} {
	    set state(method) [lindex [split $state(bypass) { }] 0]
	    set state(requestHeaders) {}
	    set state(requestLine) $state(bypass)
	} else {
	set state(method) $how
	puts $sock "$how $srvurl HTTP/$state(-protocol)"
	if {[dict exists $state(-headers) Host]} {
	    set state(method) $how
	    set state(requestHeaders) {}
	    set state(requestLine) "$how $srvurl HTTP/$state(-protocol)"
	}
	puts $sock $state(requestLine)
	set hostValue [GetFieldValue $state(-headers) Host]
	if {$hostValue ne {}} {
	    # Allow Host spoofing. [Bug 928154]
	    set hostHdr [dict get $state(-headers) Host]
	    regexp {^[^:]+} $hostHdr state(host)
	    puts $sock "Host: $hostHdr"
	    regexp {^[^:]+} $hostValue state(host)
	    SendHeader $token Host $hostValue
	} elseif {$port == $defport} {
	    # Don't add port in this case, to handle broken servers. [Bug
	    # #504508]
	    set state(host) $host
	    puts $sock "Host: $host"
	    SendHeader $token Host $host
	} else {
	    set state(host) $host
	    puts $sock "Host: $host:$port"
	    SendHeader $token Host "$host:$port"
	}
	puts $sock "User-Agent: $http(-useragent)"
	SendHeader $token User-Agent $http(-useragent)
	if {($state(-protocol) > 1.0) && $state(-keepalive)} {
	    # Send this header, because a 1.1 server is not compelled to treat
	    # this as the default.
	    puts $sock "Connection: keep-alive"
	    set ConnVal keep-alive
	}
	if {($state(-protocol) > 1.0) && !$state(-keepalive)} {
	    puts $sock "Connection: close" ;# RFC2616 sec 8.1.2.1
	}
	if {($state(-protocol) < 1.1)} {
	} elseif {($state(-protocol) > 1.0)} {
	    # RFC2616 sec 8.1.2.1
	    set ConnVal close
	} else {
	    # ($state(-protocol) <= 1.0)
	    # RFC7230 A.1
	    # Some server implementations of HTTP/1.0 have a faulty
	    # implementation of RFC 2068 Keep-Alive.
	    # Don't leave this to chance.
	    # For HTTP/1.0 we have already "set state(connection) close"
	    # and "state(-keepalive) 0".
	    puts $sock "Connection: close"
	    set ConnVal close
	}
	# Proxy authorisation (cf. mod by Anders Ramdahl to autoproxy by
	# Pat Thoyts).
	if {($http(-proxyauth) ne {}) && ($state(proxyUsed) eq {HttpProxy})} {
	    SendHeader $token Proxy-Authorization $http(-proxyauth)
	}
	# RFC7230 A.1 - "clients are encouraged not to send the
	# Proxy-Connection header field in any requests"
	set accept_encoding_seen 0
	set content_type_seen 0
	set connection_seen 0
	dict for {key value} $state(-headers) {
	foreach {key value} $state(-headers) {
	    set value [string map [list \n "" \r ""] $value]
	    set key [string map {" " -} [string trim $key]]
	    if {[string equal -nocase $key "host"]} {
		continue
	    }
	    if {[string equal -nocase $key "accept-encoding"]} {
		set accept_encoding_seen 1
	    }
	    if {[string equal -nocase $key "accept"]} {
		set accept_types_seen 1
	    }
	    if {[string equal -nocase $key "content-type"]} {
		set content_type_seen 1
	    }
	    if {[string equal -nocase $key "content-length"]} {
		set contDone 1
		set state(querylength) $value
	    }
	    if {    [string equal -nocase $key "connection"]
		    && [info exists state(bypass)]
	    } {
		# Value supplied in -headers overrides $ConnVal.
		set connection_seen 1
	    } elseif {[string equal -nocase $key "connection"]} {
		# Remove "close" or "keep-alive" and use our own value.
		# In an upgrade request, the upgrade is not guaranteed.
		# Value "close" or "keep-alive" tells the server what to do
		# if it refuses the upgrade.  We send a single "Connection"
		# header because some websocket servers, e.g. civetweb, reject
		# multiple headers. Bug [d01de3281f] of tcllib/websocket.
		set connection_seen 1
		set listVal $state(connectionValues)
		if {[set pos [lsearch $listVal close]] != -1} {
		    set listVal [lreplace $listVal $pos $pos]
		}
		if {[set pos [lsearch $listVal keep-alive]] != -1} {
		    set listVal [lreplace $listVal $pos $pos]
		}
		lappend listVal $ConnVal
		set value [join $listVal {, }]
	    }
	    if {[string length $key]} {
		puts $sock "$key: $value"
		SendHeader $token $key $value
	    }
	}
	# Allow overriding the Accept header on a per-connection basis. Useful
	# for working with REST services. [Bug c11a51c482]
	if {!$accept_types_seen} {
	    puts $sock "Accept: $state(accept-types)"
	    SendHeader $token Accept $state(accept-types)
	}
	if {    (!$accept_encoding_seen)
	     && (![info exists state(-handler)])
	     && $http(-zip)
	} {
	    SendHeader $token Accept-Encoding gzip,deflate
	} elseif {!$accept_encoding_seen} {
	    puts $sock "Accept-Encoding: gzip,deflate,compress"
	    SendHeader $token Accept-Encoding identity
	} else {
	}
	if {!$connection_seen} {
	    SendHeader $token Connection $ConnVal
	}
	if {$isQueryChannel && ($state(querylength) == 0)} {
	    # Try to determine size of data in channel. If we cannot seek, the
	    # surrounding catch will trap us

	    set start [tell $state(-querychannel)]
	    seek $state(-querychannel) 0 end
1463
1464
1465
1466
1467
1468
1469
1470

1471
1472
1473
1474
1475
1476
1477
2375
2376
2377
2378
2379
2380
2381

2382
2383
2384
2385
2386
2387
2388
2389







-
+







	    set separator ""
	    foreach {key value} [{*}$http(-cookiejar) \
		    getCookies $proto $host $state(path)] {
		append cookies $separator $key = $value
		set separator "; "
	    }
	    if {$cookies ne ""} {
		puts $sock "Cookie: $cookies"
		SendHeader $token Cookie $cookies
	    }
	}

	# Flush the request header and set up the fileevent that will either
	# push the POST data or read the response.
	#
	# fileevent note:
1487
1488
1489
1490
1491
1492
1493
1494

1495
1496
1497

1498
1499
1500
1501
1502
1503
1504
2399
2400
2401
2402
2403
2404
2405

2406
2407
2408

2409
2410
2411
2412
2413
2414
2415
2416







-
+


-
+







	# the same, and none behave all that well in any case. Servers should
	# always read their POST data if they expect the client to read their
	# response.

	if {$isQuery || $isQueryChannel} {
	    # POST method.
	    if {!$content_type_seen} {
		puts $sock "Content-Type: $state(-type)"
		SendHeader $token Content-Type $state(-type)
	    }
	    if {!$contDone} {
		puts $sock "Content-Length: $state(querylength)"
		SendHeader $token Content-Length $state(querylength)
	    }
	    puts $sock ""
	    flush $sock
	    # Flush flushes the error in the https case with a bad handshake:
	    # else the socket never becomes writable again, and hangs until
	    # timeout (if any).

1532
1533
1534
1535
1536
1537
1538
1539

1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551


1552
1553
1554
1555
1556
1557
1558
1559
1560
1561

1562
1563
1564
1565
1566
1567
1568
2444
2445
2446
2447
2448
2449
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







-
+











-
+
+










+







	# later, OR https handshake error, which may be discovered as late as
	# the "flush" command above...
	Log "WARNING - if testing, pay special attention to this\
		case (GI) which is seldom executed - token $token"
	if {[info exists state(reusing)] && $state(reusing)} {
	    # The socket was closed at the server end, and closed at
	    # this end by http::CheckEof.
    	    if {[TestForReplay $token write $err a]} {
	    if {[TestForReplay $token write $err a]} {
		return
	    } else {
		Finish $token {failed to re-use socket}
	    }

	    # else:
	    # This is NOT a persistent socket that has been closed since its
	    # last use.
	    # If any other requests are in flight or pipelined/queued, they will
	    # be discarded.
	} elseif {$state(status) eq ""} {
	    # ...https handshake errors come here.
	    # https handshake errors come here, for
	    # Tcl 8.7 without http::SecureProxyConnect, and for Tcl 8.6.
	    set msg [registerError $sock]
	    registerError $sock {}
	    if {$msg eq {}} {
		set msg {failed to use socket}
	    }
	    Finish $token $msg
	} elseif {$state(status) ne "error"} {
	    Finish $token $err
	}
    }
    return
}

# http::registerError
#
#	Called (for example when processing TclTLS activity) to register
#	an error for a connection on a specific socket.  This helps
#	http::Connected to deliver meaningful error messages, e.g. when a TLS
1600
1601
1602
1603
1604
1605
1606

1607
1608


1609
1610
1611
1612
1613
1614
1615
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532







+


+
+







proc http::DoneRequest {token} {
    variable http
    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue
    variable socketPhQueue
    variable socketClosing
    variable socketPlayCmd
    variable socketCoEvent
    variable socketProxyId

    variable $token
    upvar 0 $token state
    set tk [namespace tail $token]
    set sock $state(sock)

    # If pipelined, connect the next HTTP request to the socket.
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
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







+
















+
+
+


-
+

-
+

-
+







	lappend socketRdQueue($state(socketinfo)) $token
    } else {
	# In the pipelined case, connection for reading depends on the
	# value of socketRdState.
	# In the nonpipeline case, connection for reading always occurs.
	ReceiveResponse $token
    }
    return
}

# http::ReceiveResponse
#
#	Connects token to its socket for reading.

proc http::ReceiveResponse {token} {
    variable $token
    upvar 0 $token state
    set tk [namespace tail $token]
    set sock $state(sock)

    #Log ---- $state(socketinfo) >> conn to $token for HTTP response
    lassign [fconfigure $sock -translation] trRead trWrite
    fconfigure $sock -translation [list auto $trWrite] \
		     -buffersize $state(-blocksize)
    if {[package vsatisfies [package provide Tcl] 9.0-]} {
	fconfigure $sock -profile replace
    }
    Log ^D$tk begin receiving response - token $token

    coroutine ${token}EventCoroutine http::Event $sock $token
    coroutine ${token}--EventCoroutine http::Event $sock $token
    if {[info exists state(-handler)] || [info exists state(-progress)]} {
        fileevent $sock readable [list http::EventGateway $sock $token]
	fileevent $sock readable [list http::EventGateway $sock $token]
    } else {
        fileevent $sock readable ${token}EventCoroutine
	fileevent $sock readable ${token}--EventCoroutine
    }
    return
}


# http::EventGateway
#
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
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







-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+







#	  used only if -handler or -progress is specified.  In other cases,
#	  the coroutine is called directly.

proc http::EventGateway {sock token} {
    variable $token
    upvar 0 $token state
    fileevent $sock readable {}
    catch {${token}EventCoroutine} res opts
    if {[info commands ${token}EventCoroutine] ne {}} {
        # The coroutine can be deleted by completion (a non-yield return), by
        # http::Finish (when there is a premature end to the transaction), by
        # http::reset or http::cleanup, or if the caller set option -channel
        # but not option -handler: in the last case reading from the socket is
        # now managed by commands ::http::Copy*, http::ReceiveChunked, and
        # http::make-transformation-chunked.
        #
        # Catch in case the coroutine has closed the socket.
        catch {fileevent $sock readable [list http::EventGateway $sock $token]}
    catch {${token}--EventCoroutine} res opts
    if {[info commands ${token}--EventCoroutine] ne {}} {
	# The coroutine can be deleted by completion (a non-yield return), by
	# http::Finish (when there is a premature end to the transaction), by
	# http::reset or http::cleanup, or if the caller set option -channel
	# but not option -handler: in the last case reading from the socket is
	# now managed by commands ::http::Copy*, http::ReceiveChunked, and
	# http::MakeTransformationChunked.
	#
	# Catch in case the coroutine has closed the socket.
	catch {fileevent $sock readable [list http::EventGateway $sock $token]}
    }

    # If there was an error, re-throw it.
    return -options $opts $res
}


1775
1776
1777
1778
1779
1780
1781
1782

1783
1784
1785
1786
1787
1788
1789
2696
2697
2698
2699
2700
2701
2702

2703
2704
2705
2706
2707
2708
2709
2710







-
+







	 && ([set token2 [lindex $socketWrQueue($connId) 0]
	      set ${token2}(-pipeline)
	     ]
	    )
    } {
	# - The usual case for a pipelined connection, ready for a new request.
	#Log pipelined, GRANT write access to $token2 in NextPipelinedWrite
	set conn [set ${token2}(tmpConnArgs)]
	set conn [set ${token2}(connArgs)]
	set socketWrState($connId) $token2
	set socketWrQueue($connId) [lrange $socketWrQueue($connId) 1 end]
	# Connect does its own fconfigure.
	fileevent $state(sock) writable [list http::Connect $token2 {*}$conn]
	#Log ---- $connId << conn to $token2 for HTTP request (b)

	# In the tests below, the next request will be nonpipeline.
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809

1810
1811
1812
1813
1814
1815
1816
2721
2722
2723
2724
2725
2726
2727



2728
2729
2730
2731
2732
2733
2734
2735







-
-
-
+








	       && [info exists socketRdState($connId)]
	       && ($socketRdState($connId) eq "Rready")
    } {
	# The case in which the next request will be non-pipelined, and the read
	# and write queues is ready: which is the condition for a non-pipelined
	# write.
	variable $token3
	upvar 0 $token3 state3
	set conn [set ${token3}(tmpConnArgs)]
	set conn [set ${token3}(connArgs)]
	#Log nonpipeline, GRANT r/w access to $token3 in NextPipelinedWrite
	set socketRdState($connId) $token3
	set socketWrState($connId) $token3
	set socketWrQueue($connId) [lrange $socketWrQueue($connId) 1 end]
	# Connect does its own fconfigure.
	fileevent $state(sock) writable [list http::Connect $token3 {*}$conn]
	#Log ---- $state(sock) << conn to $token3 for HTTP request (c)
1834
1835
1836
1837
1838
1839
1840

1841
1842
1843
1844
1845
1846
1847
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767







+







	# - Because socketWrState($connId) is not set to Wready, the assignment
	#   of the connection to $token2 will be done elsewhere - by command
	#   http::KeepSocket when $socketRdState($connId) is set to "Rready".

	#Log re-use nonpipeline, GRANT delayed write access to $token in NextP..
	set socketWrState($connId) peNding
    }
    return
}

# http::CancelReadPipeline
#
#	Cancel pipelined responses on a closing "Keep-Alive" socket.
#
#	- Called by a variable trace on "unset socketRdState($connId)".
1866
1867
1868
1869
1870
1871
1872

1873
1874
1875
1876
1877
1878
1879
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800







+







	    set tk [namespace tail $token]
	    Log ^X$tk end of response "($msg)" - token $token
	    set ${token}(status) eof
	    Finish $token ;#$msg
	}
	set socketRdQueue($connId) {}
    }
    return
}

# http::CancelWritePipeline
#
#	Cancel queued events on a closing "Keep-Alive" socket.
#
#	- Called by a variable trace on "unset socketWrState($connId)".
1899
1900
1901
1902
1903
1904
1905

1906
1907
1908
1909
1910
1911
1912
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834







+







	    set tk [namespace tail $token]
	    Log ^X$tk end of response "($msg)" - token $token
	    set ${token}(status) eof
	    Finish $token ;#$msg
	}
	set socketWrQueue($connId) {}
    }
    return
}

# http::ReplayIfDead --
#
# - A query on a re-used persistent socket failed at the earliest opportunity,
#   because the socket had been closed by the server.  Keep the token, tidy up,
#   and try to connect on a fresh socket.
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


1958
1959

1960
1961

1962
1963
1964
1965


1966
1967

1968
1969

1970
1971
1972

1973
1974
1975


1976
1977
1978
1979



1980
1981
1982
1983
1984


1985
1986
1987
1988



1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999





2000
2001
2002
2003
2004


2005
2006
2007
2008



2009
2010
2011
2012


2013
2014
2015
2016
2017

2018
2019

2020
2021
2022

2023
2024

2025
2026
2027


2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038

2039
2040
2041
2042
2043
2044
2045
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







-
+





+


+
+

-
-
+
+

-
+








-
+






-
-
+
+

-
+

-
+


-
-
+
+

-
+

-
+


-
+

-
-
+
+

-
-
-
+
+
+



-
-
+
+

-
-
-
+
+
+






-
-
-
-
-
+
+
+
+
+



-
-
+
+

-
-
-
+
+
+


-
-
+
+




-
+

-
+


-
+

-
+


-
+
+











+







#
# Arguments:
#	token	Connection token.
#
# Side Effects:
#	Use the same token, but try to open a new socket.

proc http::ReplayIfDead {tokenArg doing} {
proc http::ReplayIfDead {token doing} {
    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue
    variable socketPhQueue
    variable socketClosing
    variable socketPlayCmd
    variable socketCoEvent
    variable socketProxyId

    variable $tokenArg
    upvar 0 $tokenArg stateArg
    variable $token
    upvar 0 $token state

    Log running http::ReplayIfDead for $tokenArg $doing
    Log running http::ReplayIfDead for $token $doing

    # 1. Merge the tokens for transactions in flight, the read (response) queue,
    #    and the write (request) queue.

    set InFlightR {}
    set InFlightW {}

    # Obtain the tokens for transactions in flight.
    if {$stateArg(-pipeline)} {
    if {$state(-pipeline)} {
	# Two transactions may be in flight.  The "read" transaction was first.
	# It is unlikely that the server would close the socket if a response
	# was pending; however, an earlier request (as well as the present
	# request) may have been sent and ignored if the socket was half-closed
	# by the server.

	if {    [info exists socketRdState($stateArg(socketinfo))]
	     && ($socketRdState($stateArg(socketinfo)) ne "Rready")
	if {    [info exists socketRdState($state(socketinfo))]
	     && ($socketRdState($state(socketinfo)) ne "Rready")
	} {
	    lappend InFlightR $socketRdState($stateArg(socketinfo))
	    lappend InFlightR $socketRdState($state(socketinfo))
	} elseif {($doing eq "read")} {
	    lappend InFlightR $tokenArg
	    lappend InFlightR $token
	}

	if {    [info exists socketWrState($stateArg(socketinfo))]
	     && $socketWrState($stateArg(socketinfo)) ni {Wready peNding}
	if {    [info exists socketWrState($state(socketinfo))]
	     && $socketWrState($state(socketinfo)) ni {Wready peNding}
	} {
	    lappend InFlightW $socketWrState($stateArg(socketinfo))
	    lappend InFlightW $socketWrState($state(socketinfo))
	} elseif {($doing eq "write")} {
	    lappend InFlightW $tokenArg
	    lappend InFlightW $token
	}

	# Report any inconsistency of $tokenArg with socket*state.
	# Report any inconsistency of $token with socket*state.
	if {    ($doing eq "read")
	     && [info exists socketRdState($stateArg(socketinfo))]
	     && ($tokenArg ne $socketRdState($stateArg(socketinfo)))
	     && [info exists socketRdState($state(socketinfo))]
	     && ($token ne $socketRdState($state(socketinfo)))
	} {
	    Log WARNING - ReplayIfDead pipelined tokenArg $tokenArg $doing \
		    ne socketRdState($stateArg(socketinfo)) \
		      $socketRdState($stateArg(socketinfo))
	    Log WARNING - ReplayIfDead pipelined token $token $doing \
		    ne socketRdState($state(socketinfo)) \
		      $socketRdState($state(socketinfo))

	} elseif {
		($doing eq "write")
	     && [info exists socketWrState($stateArg(socketinfo))]
	     && ($tokenArg ne $socketWrState($stateArg(socketinfo)))
	     && [info exists socketWrState($state(socketinfo))]
	     && ($token ne $socketWrState($state(socketinfo)))
	} {
	    Log WARNING - ReplayIfDead pipelined tokenArg $tokenArg $doing \
		    ne socketWrState($stateArg(socketinfo)) \
		      $socketWrState($stateArg(socketinfo))
	    Log WARNING - ReplayIfDead pipelined token $token $doing \
		    ne socketWrState($state(socketinfo)) \
		      $socketWrState($state(socketinfo))
	}
    } else {
	# One transaction should be in flight.
	# socketRdState, socketWrQueue are used.
	# socketRdQueue should be empty.

	# Report any inconsistency of $tokenArg with socket*state.
	if {$tokenArg ne $socketRdState($stateArg(socketinfo))} {
	    Log WARNING - ReplayIfDead nonpipeline tokenArg $tokenArg $doing \
		    ne socketRdState($stateArg(socketinfo)) \
		      $socketRdState($stateArg(socketinfo))
	# Report any inconsistency of $token with socket*state.
	if {$token ne $socketRdState($state(socketinfo))} {
	    Log WARNING - ReplayIfDead nonpipeline token $token $doing \
		    ne socketRdState($state(socketinfo)) \
		      $socketRdState($state(socketinfo))
	}

	# Report the inconsistency that socketRdQueue is non-empty.
	if {    [info exists socketRdQueue($stateArg(socketinfo))]
	     && ($socketRdQueue($stateArg(socketinfo)) ne {})
	if {    [info exists socketRdQueue($state(socketinfo))]
	     && ($socketRdQueue($state(socketinfo)) ne {})
	} {
	    Log WARNING - ReplayIfDead nonpipeline tokenArg $tokenArg $doing \
		    has read queue socketRdQueue($stateArg(socketinfo)) \
		    $socketRdQueue($stateArg(socketinfo)) ne {}
	    Log WARNING - ReplayIfDead nonpipeline token $token $doing \
		    has read queue socketRdQueue($state(socketinfo)) \
		    $socketRdQueue($state(socketinfo)) ne {}
	}

	lappend InFlightW $socketRdState($stateArg(socketinfo))
	set socketRdQueue($stateArg(socketinfo)) {}
	lappend InFlightW $socketRdState($state(socketinfo))
	set socketRdQueue($state(socketinfo)) {}
    }

    set newQueue {}
    lappend newQueue {*}$InFlightR
    lappend newQueue {*}$socketRdQueue($stateArg(socketinfo))
    lappend newQueue {*}$socketRdQueue($state(socketinfo))
    lappend newQueue {*}$InFlightW
    lappend newQueue {*}$socketWrQueue($stateArg(socketinfo))
    lappend newQueue {*}$socketWrQueue($state(socketinfo))


    # 2. Tidy up tokenArg.  This is a cut-down form of Finish/CloseSocket.
    # 2. Tidy up token.  This is a cut-down form of Finish/CloseSocket.
    #    Do not change state(status).
    #    No need to after cancel stateArg(after) - either this is done in
    #    No need to after cancel state(after) - either this is done in
    #    ReplayCore/ReInit, or Finish is called.

    catch {close $stateArg(sock)}
    catch {close $state(sock)}
    Unset $state(socketinfo)

    # 2a. Tidy the tokens in the queues - this is done in ReplayCore/ReInit.
    # - Transactions, if any, that are awaiting responses cannot be completed.
    #   They are listed for re-sending in newQueue.
    # - All tokens are preserved for re-use by ReplayCore, and their variables
    #   will be re-initialised by calls to ReInit.
    # - The relevant element of socketMapping, socketRdState, socketWrState,
    #   socketRdQueue, socketWrQueue, socketClosing, socketPlayCmd will be set
    #   to new values in ReplayCore.

    ReplayCore $newQueue
    return
}

# http::ReplayIfClose --
#
#	A request on a socket that was previously "Connection: keep-alive" has
#	received a "Connection: close" response header.  The server supplies
#	that response correctly, but any later requests already queued on this
2062
2063
2064
2065
2066
2067
2068
2069

2070
2071
2072
2073
2074
2075
2076
2077

2078
2079
2080
2081
2082
2083
2084
2989
2990
2991
2992
2993
2994
2995

2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012







-
+








+







    }

    # 1. Create newQueue
    set InFlightW {}
    if {$Wstate ni {Wready peNding}} {
	lappend InFlightW $Wstate
    }

    ##Log $Rqueue -- $InFlightW -- $Wqueue
    set newQueue {}
    lappend newQueue {*}$Rqueue
    lappend newQueue {*}$InFlightW
    lappend newQueue {*}$Wqueue

    # 2. Cleanup - none needed, done by the caller.

    ReplayCore $newQueue
    return
}

# http::ReInit --
#
#	Command to restore a token's state to a condition that
#	makes it ready to replay a request.
#
2114
2115
2116
2117
2118
2119
2120





2121
2122
2123
2124
2125
2126
2127
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060







+
+
+
+
+







	return 0
    }

    if {[info exists state(after)]} {
	after cancel $state(after)
	unset state(after)
    }
    if {[info exists state(socketcoro)]} {
	Log $token Cancel socket after-idle event (ReInit)
	after cancel $state(socketcoro)
	unset state(socketcoro)
    }

    # Don't alter state(status) - this would trigger http::wait if it is in use.
    set tmpState    $state(tmpState)
    set tmpOpenCmd  $state(tmpOpenCmd)
    set tmpConnArgs $state(tmpConnArgs)
    foreach name [array names state] {
	if {$name ne "status"} {
2153
2154
2155
2156
2157
2158
2159


2160
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
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
2273

2274
2275
2276
2277
2278
2279
2280

2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292

2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305

2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399


2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422

2423
2424


2425
2426
2427
2428
2429
2430
2431
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
3134
3135
3136



3137
3138
3139



3140
3141




3142




3143



3144











3145




3146






























3147
3148
3149
3150
3151
3152
3153
3154
3155
3156

3157
3158
3159
3160



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
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230

3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246

3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343

3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362

3363
3364
3365
3366
3367


3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390

3391
3392
3393
3394
3395
3396
3397

3398
3399
3400
3401
3402
3403
3404
3405

3406




3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432


3433
3434




3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465







+
+





+


+
+



















+












-
-
-
+
+
+
-
-
-
+
+
-
-
-
-
+
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-




+
+

+


-
+



-
-
-
+
-

-
-
-
-
-
+
-
-
-








-
+












-
+




-
+
+
+
+
+
+













+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+
+
+
+
+
+
+
+
+










-
+




-
-
+
+
+
+
+




+
+
+
+
+




+




-
+






-
+





+
+
-
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+















-
-
+
+
-
-
-
-



















+


+
+







# Arguments:
#	newQueue	List of connection tokens.
#
# Side Effects:
#	Use existing tokens, but try to open a new socket.

proc http::ReplayCore {newQueue} {
    variable TmpSockCounter

    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue
    variable socketPhQueue
    variable socketClosing
    variable socketPlayCmd
    variable socketCoEvent
    variable socketProxyId

    if {[llength $newQueue] == 0} {
	# Nothing to do.
	return
    }

    ##Log running ReplayCore for {*}$newQueue
    set newToken [lindex $newQueue 0]
    set newQueue [lrange $newQueue 1 end]

    # 3. Use newToken, and restore its values of state(*).  Do not restore
    #    elements tmp* - we try again only once.

    set token $newToken
    variable $token
    upvar 0 $token state

    if {![ReInit $token]} {
	Log FAILED in http::ReplayCore - NO tmp vars
	Log ReplayCore reject $token
	Finish $token {cannot send this request again}
	return
    }

    set tmpState    $state(tmpState)
    set tmpOpenCmd  $state(tmpOpenCmd)
    set tmpConnArgs $state(tmpConnArgs)
    unset state(tmpState)
    unset state(tmpOpenCmd)
    unset state(tmpConnArgs)

    set state(reusing) 0

    if {$state(-timeout) > 0} {
	set resetCmd [list http::reset $token timeout]
    set state(ReusingPlaceholder) 0
    set state(alreadyQueued) 0
    Log ReplayCore replay $token
	set state(after) [after $state(-timeout) $resetCmd]
    }


    # Give the socket a placeholder name before it is created.
    set pre [clock milliseconds]
    ##Log pre socket opened, - token $token
    ##Log $tmpOpenCmd - token $token
    # 4. Open a socket.
    set sock HTTP_PLACEHOLDER_[incr TmpSockCounter]
    if {[catch {eval $tmpOpenCmd} sock]} {
	# Something went wrong while trying to establish the connection.
	Log FAILED - $sock
	set state(sock) NONE
    set state(sock) $sock
	Finish $token $sock
	return
    }

    ##Log post socket opened, - token $token
    set delay [expr {[clock milliseconds] - $pre}]
    if {$delay > 3000} {
	Log socket delay $delay - token $token
    }
    # Command [socket] is called with -async, but takes 5s to 5.1s to return,
    # with probability of order 1 in 10,000.  This may be a bizarre scheduling
    # issue with my (KJN's) system (Fedora Linux).
    # This does not cause a problem (unless the request times out when this
    # command returns).

    # Move the $newQueue into the placeholder socket's socketPhQueue.
    # 5. Configure the persistent socket data.
    if {$state(-keepalive)} {
	set socketMapping($state(socketinfo)) $sock

    set socketPhQueue($sock) {}
	if {![info exists socketRdState($state(socketinfo))]} {
	    set socketRdState($state(socketinfo)) {}
	    set varName ::http::socketRdState($state(socketinfo))
	    trace add variable $varName unset ::http::CancelReadPipeline
	}

	if {![info exists socketWrState($state(socketinfo))]} {
	    set socketWrState($state(socketinfo)) {}
	    set varName ::http::socketWrState($state(socketinfo))
	    trace add variable $varName unset ::http::CancelWritePipeline
	}

	if {$state(-pipeline)} {
	    #Log new, init for pipelined, GRANT write acc to $token ReplayCore
	    set socketRdState($state(socketinfo)) $token
	    set socketWrState($state(socketinfo)) $token
	} else {
	    #Log new, init for nonpipeline, GRANT r/w acc to $token ReplayCore
	    set socketRdState($state(socketinfo)) $token
	    set socketWrState($state(socketinfo)) $token
	}

	set socketRdQueue($state(socketinfo)) {}
	set socketWrQueue($state(socketinfo)) $newQueue
	set socketClosing($state(socketinfo)) 0
	set socketPlayCmd($state(socketinfo)) {ReplayIfClose Wready {} {}}
    }

    ##Log pre newQueue ReInit, - token $token
    # 6. Configure sockets in the queue.
    foreach tok $newQueue {
	if {[ReInit $tok]} {
	    set ${tok}(reusing) 1
	    set ${tok}(sock) $sock
	    lappend socketPhQueue($sock) $tok
	    Log ReplayCore replay $tok
	} else {
	    Log ReplayCore reject $tok
	    set ${tok}(reusing) 1
	    set ${tok}(sock) NONE
	    Finish $token {cannot send this request again}
	    Finish $tok {cannot send this request again}
	}
    }

    # 7. Configure the socket for newToken to send a request.
    set state(sock) $sock
    Log "Using $sock for $state(socketinfo) - token $token" \
    AsyncTransaction $token
	[expr {$state(-keepalive)?"keepalive":""}]

    # Initialisation of a new socket.
    ##Log socket opened, now fconfigure - token $token
    fconfigure $sock -translation {auto crlf} -buffersize $state(-blocksize)
    ##Log socket opened, DONE fconfigure - token $token

    return
    # Connect does its own fconfigure.
    fileevent $sock writable [list http::Connect $token {*}$tmpConnArgs]
    #Log ---- $sock << conn to $token for HTTP request (e)
}

# Data access functions:
# Data - the URL data
# Status - the transaction status: ok, reset, eof, timeout, error
# Code - the HTTP transaction code, e.g., 200
# Size - the size of the URL data

proc http::data {token} {
proc http::responseBody {token} {
    variable $token
    upvar 0 $token state
    return $state(body)
}
proc http::status {token} {
    if {![info exists $token]} {
	return "error"
    }
    variable $token
    upvar 0 $token state
    return $state(status)
}
proc http::code {token} {
proc http::responseLine {token} {
    variable $token
    upvar 0 $token state
    return $state(http)
}
proc http::ncode {token} {
proc http::requestLine {token} {
    variable $token
    upvar 0 $token state
    return $state(requestLine)
}
proc http::responseCode {token} {
    variable $token
    upvar 0 $token state
    if {[regexp {[0-9]{3}} $state(http) numeric_code]} {
	return $numeric_code
    } else {
	return $state(http)
    }
}
proc http::size {token} {
    variable $token
    upvar 0 $token state
    return $state(currentsize)
}
proc http::requestHeaders {token args} {
    set lenny  [llength $args]
    if {$lenny > 1} {
	return -code error {usage: ::http::requestHeaders token ?headerName?}
    } else {
	return [Meta $token request {*}$args]
    }
}
proc http::responseHeaders {token args} {
    set lenny  [llength $args]
    if {$lenny > 1} {
	return -code error {usage: ::http::responseHeaders token ?headerName?}
    } else {
	return [Meta $token response {*}$args]
    }
}
proc http::requestHeaderValue {token header} {
    Meta $token request $header VALUE
}
proc http::responseHeaderValue {token header} {
    Meta $token response $header VALUE
}
proc http::meta {token} {
proc http::Meta {token who args} {
    variable $token
    upvar 0 $token state

    if {$who eq {request}} {
	set whom requestHeaders
    } elseif {$who eq {response}} {
	set whom meta
    } else {
	return -code error {usage: ::http::Meta token request|response ?headerName ?VALUE??}
    }

    set header [string tolower [lindex $args 0]]
    set how    [string tolower [lindex $args 1]]
    set lenny  [llength $args]
    if {$lenny == 0} {
    return $state(meta)
	return $state($whom)
    } elseif {($lenny > 2) || (($lenny == 2) && ($how ne {value}))} {
	return -code error {usage: ::http::Meta token request|response ?headerName ?VALUE??}
    } else {
	set result {}
	set combined {}
	foreach {key value} $state($whom) {
	    if {$key eq $header} {
		lappend result $key $value
		append combined $value {, }
	    }
	}
	if {$lenny == 1} {
	    return $result
	} else {
	    return [string range $combined 0 end-2]
	}
    }
}


# ------------------------------------------------------------------------------
#  Proc http::responseInfo
# ------------------------------------------------------------------------------
# Command to return a dictionary of the most useful metadata of a HTTP
# response.
#
# Arguments:
# token       - connection token (name of an array)
#
# Return Value: a dict. See man page http(n) for a description of each item.
# ------------------------------------------------------------------------------

proc http::responseInfo {token} {
    variable $token
    upvar 0 $token state
    set result {}
    foreach {key origin name} {
	stage                 STATE  state
	status                STATE  status
	responseCode          STATE  responseCode
	reasonPhrase          STATE  reasonPhrase
	contentType           STATE  type
	binary                STATE  binary
	redirection           RESP   location
	upgrade               STATE  upgrade
	error                 ERROR  -
	postError             STATE  posterror
	method                STATE  method
	charset               STATE  charset
	compression           STATE  coding
	httpRequest           STATE  -protocol
	httpResponse          STATE  httpResponse
	url                   STATE  url
	connectionRequest     REQ    connection
	connectionResponse    RESP   connection
	connectionActual      STATE  connection
	transferEncoding      STATE  transfer
	totalPost             STATE  querylength
	currentPost           STATE  queryoffset
	totalSize             STATE  totalsize
	currentSize           STATE  currentsize
	proxyUsed             STATE  proxyUsed
    } {
	if {$origin eq {STATE}} {
	    if {[info exists state($name)]} {
		dict set result $key $state($name)
	    } else {
		# Should never come here
		dict set result $key {}
	    }
	} elseif {$origin eq {REQ}} {
	    dict set result $key [requestHeaderValue $token $name]
	} elseif {$origin eq {RESP}} {
	    dict set result $key [responseHeaderValue $token $name]
	} elseif {$origin eq {ERROR}} {
	    # Don't flood the dict with data.  The command ::http::error is
	    # available.
	    if {[info exists state(error)]} {
		set msg [lindex $state(error) 0]
	    } else {
		set msg {}
	    }
	    dict set result $key $msg
	} else {
	    # Should never come here
	    dict set result $key {}
	}
    }
    return $result
}
proc http::error {token} {
    variable $token
    upvar 0 $token state
    if {[info exists state(error)]} {
	return $state(error)
    }
    return ""
    return
}
proc http::postError {token} {
    variable $token
    upvar 0 $token state
    if {[info exists state(postErrorFull)]} {
	return $state(postErrorFull)
    }
    return
}

# http::cleanup
#
#	Garbage collect the state associated with a transaction
#
# Arguments
#	token	The token returned from http::geturl
#
# Side Effects
#	unsets the state array
#	Unsets the state array.

proc http::cleanup {token} {
    variable $token
    upvar 0 $token state
    if {[info commands ${token}EventCoroutine] ne {}} {
	rename ${token}EventCoroutine {}
    if {[info commands ${token}--EventCoroutine] ne {}} {
	rename ${token}--EventCoroutine {}
    }
    if {[info commands ${token}--SocketCoroutine] ne {}} {
	rename ${token}--SocketCoroutine {}
    }
    if {[info exists state(after)]} {
	after cancel $state(after)
	unset state(after)
    }
    if {[info exists state(socketcoro)]} {
	Log $token Cancel socket after-idle event (cleanup)
	after cancel $state(socketcoro)
	unset state(socketcoro)
    }
    if {[info exists state]} {
	unset state
    }
    return
}

# http::Connect
#
#	This callback is made when an asyncronous connection completes.
#	This callback is made when an asynchronous connection completes.
#
# Arguments
#	token	The token returned from http::geturl
#
# Side Effects
#	Sets the status of the connection, which unblocks
# 	the waiting geturl call
#	the waiting geturl call

proc http::Connect {token proto phost srvurl} {
    variable $token
    upvar 0 $token state
    set tk [namespace tail $token]

    if {[catch {eof $state(sock)} tmp] || $tmp} {
    set err "due to unexpected EOF"
	set err "due to unexpected EOF"
    if {
	[eof $state(sock)] ||
	[set err [fconfigure $state(sock) -error]] ne ""
    } {
    } elseif {[set err [fconfigure $state(sock) -error]] ne ""} {
	# set err is done in test
    } else {
	# All OK
	set state(state) connecting
	fileevent $state(sock) writable {}
	::http::Connected $token $proto $phost $srvurl
	return
    }

    # Error cases.
	Log "WARNING - if testing, pay special attention to this\
		case (GJ) which is seldom executed - token $token"
	if {[info exists state(reusing)] && $state(reusing)} {
	    # The socket was closed at the server end, and closed at
	    # this end by http::CheckEof.
	    if {[TestForReplay $token write $err b]} {
		return
	    }

	    # else:
	    # This is NOT a persistent socket that has been closed since its
	    # last use.
	    # If any other requests are in flight or pipelined/queued, they will
	    # be discarded.
	}
	Finish $token "connect failed $err"
    } else {
	Finish $token "connect failed: $err"
    return
	set state(state) connecting
	fileevent $state(sock) writable {}
	::http::Connected $token $proto $phost $srvurl
    }
}

# http::Write
#
#	Write POST query data to the socket
#
# Arguments
#	token	The token for the connection
#
# Side Effects
#	Write the socket and handle callbacks.

proc http::Write {token} {
    variable http
    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue
    variable socketPhQueue
    variable socketClosing
    variable socketPlayCmd
    variable socketCoEvent
    variable socketProxyId

    variable $token
    upvar 0 $token state
    set tk [namespace tail $token]
    set sock $state(sock)

    # Output a block.  Tcl will buffer this if the socket blocks
2478
2479
2480
2481
2482
2483
2484
2485

2486
2487
2488
2489



2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505

2506
2507

2508
2509
2510
2511
2512
2513

2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529

2530
2531


2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542

2543
2544
2545

2546

2547
2548
2549
2550

2551
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
3512
3513
3514
3515
3516
3517
3518

3519
3520
3521

3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540

3541
3542
3543
3544
3545
3546
3547
3548
3549

3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581

3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615


3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631

3632
3633
3634
3635
3636
3637

3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692

3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715

3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749

3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763



3764
3765
3766
3767
3768
3769
3770
3771
3772
3773

3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858

3859
3860
3861

3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893

3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904

3905
3906
3907
3908
3909
3910
3911
3912
3913







-
+


-

+
+
+















-
+


+





-
+
















+


+
+










-
+



+

+




+










+











-
-
+
+






+
+
+
+
+
+
+

-
+





-
+









+







+


















+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+










+











-
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












-














-
-
-
+
+
+
+
+





-
+
+

+



+
+
+
+
+
+
+
+
+
+
+
+
+
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

















-
+


-
+









+











+




+




-
+


+

+





-
+
+







	    }
	    puts -nonewline $sock $outStr
	    incr state(queryoffset) [string length $outStr]
	    if {[eof $state(-querychannel)]} {
		set done 1
	    }
	}
    } err]} {
    } err opts]} {
	# Do not call Finish here, but instead let the read half of the socket
	# process whatever server reply there is to get.

	set state(posterror) $err
	set info [dict get $opts -errorinfo]
	set code [dict get $opts -code]
	set state(postErrorFull) [list $err $info $code]
	set done 1
    }

    if {$done} {
	catch {flush $sock}
	fileevent $sock writable {}
	Log ^C$tk end sending request - token $token
	# End of writing (POST method).  The request has been sent.

	DoneRequest $token
    }

    # Callback to the client after we've completely handled everything.

    if {[string length $state(-queryprogress)]} {
	eval $state(-queryprogress) \
	namespace eval :: $state(-queryprogress) \
	    [list $token $state(querylength) $state(queryoffset)]
    }
    return
}

# http::Event
#
#	Handle input on the socket. This command is the core of
#	the coroutine commands ${token}EventCoroutine that are
#	the coroutine commands ${token}--EventCoroutine that are
#	bound to "fileevent $sock readable" and process input.
#
# Arguments
#	sock	The socket receiving input.
#	token	The token returned from http::geturl
#
# Side Effects
#	Read the socket and handle callbacks.

proc http::Event {sock token} {
    variable http
    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue
    variable socketPhQueue
    variable socketClosing
    variable socketPlayCmd
    variable socketCoEvent
    variable socketProxyId

    variable $token
    upvar 0 $token state
    set tk [namespace tail $token]
    while 1 {
	yield
	##Log Event call - token $token

	if {![info exists state]} {
	    Log "Event $sock with invalid token '$token' - remote close?"
	    if {![eof $sock]} {
	    if {!([catch {eof $sock} tmp] || $tmp)} {
		if {[set d [read $sock]] ne ""} {
		    Log "WARNING: additional data left on closed socket\
			    - token $token"
		} else {
		}
	    } else {
	    }
	    Log ^X$tk end of response (token error) - token $token
	    CloseSocket $sock
	    return
	} else {
	}
	if {$state(state) eq "connecting"} {
	    ##Log - connecting - token $token
	    if {    $state(reusing)
		 && $state(-pipeline)
		 && ($state(-timeout) > 0)
		 && (![info exists state(after)])
	    } {
		set state(after) [after $state(-timeout) \
			[list http::reset $token timeout]]
	    } else {
	    }

	    if {[catch {gets $sock state(http)} nsl]} {
		Log "WARNING - if testing, pay special attention to this\
			case (GK) which is seldom executed - token $token"
		if {[info exists state(reusing)] && $state(reusing)} {
		    # The socket was closed at the server end, and closed at
		    # this end by http::CheckEof.

		    if {[TestForReplay $token read $nsl c]} {
			return
		    }

		    } else {
		    }
		    # else:
		    # This is NOT a persistent socket that has been closed since
		    # its last use.
		    # If any other requests are in flight or pipelined/queued,
		    # they will be discarded.
		} else {
		    # https handshake errors come here, for
		    # Tcl 8.7 with http::SecureProxyConnect.
		    set msg [registerError $sock]
		    registerError $sock {}
		    if {$msg eq {}} {
			set msg $nsl
		    }
		    Log ^X$tk end of response (error) - token $token
		    Finish $token $nsl
		    Finish $token $msg
		    return
		}
	    } elseif {$nsl >= 0} {
		##Log - connecting 1 - token $token
		set state(state) "header"
	    } elseif {    [eof $sock]
	    } elseif {    ([catch {eof $sock} tmp] || $tmp)
		       && [info exists state(reusing)]
		       && $state(reusing)
	    } {
		# The socket was closed at the server end, and we didn't notice.
		# This is the first read - where the closure is usually first
		# detected.

		if {[TestForReplay $token read {} d]} {
		    return
		} else {
		}

		# else:
		# This is NOT a persistent socket that has been closed since its
		# last use.
		# If any other requests are in flight or pipelined/queued, they
		# will be discarded.
	    } else {
	    }
	} elseif {$state(state) eq "header"} {
	    if {[catch {gets $sock line} nhl]} {
		##Log header failed - token $token
		Log ^X$tk end of response (error) - token $token
		Finish $token $nhl
		return
	    } elseif {$nhl == 0} {
		##Log header done - token $token
		Log ^E$tk end of response headers - token $token
		# We have now read all headers
		# We ignore HTTP/1.1 100 Continue returns. RFC2616 sec 8.2.3
		if {    ($state(http) == "")
		     || ([regexp {^\S+\s(\d+)} $state(http) {} x] && $x == 100)
		} {
		    set state(state) "connecting"
		    continue
		    # This was a "return" in the pre-coroutine code.
		} else {
		}

		# We have $state(http) so let's split it into its components.
		if {[regexp {^HTTP/(\S+) ([0-9]{3}) (.*)$} $state(http) \
			-> httpResponse responseCode reasonPhrase]
		} {
		    set state(httpResponse) $httpResponse
		    set state(responseCode) $responseCode
		    set state(reasonPhrase) $reasonPhrase
		} else {
		    set state(httpResponse) $state(http)
		    set state(responseCode) $state(http)
		    set state(reasonPhrase) $state(http)
		}

		if {    ([info exists state(connection)])
		     && ([info exists socketMapping($state(socketinfo))])
		     && ($state(connection) eq "keep-alive")
		     && ("keep-alive" in $state(connection))
		     && ($state(-keepalive))
		     && (!$state(reusing))
		     && ($state(-pipeline))
		} {
		    # Response headers received for first request on a
		    # persistent socket.  Now ready for pipelined writes (if
		    # any).
		    # Previous value is $token. It cannot be "pending".
		    set socketWrState($state(socketinfo)) Wready
		    http::NextPipelinedWrite $token
		} else {
		}

		# Once a "close" has been signaled, the client MUST NOT send any
		# more requests on that connection.
		#
		# If either the client or the server sends the "close" token in
		# the Connection header, that request becomes the last one for
		# the connection.

		if {    ([info exists state(connection)])
		     && ([info exists socketMapping($state(socketinfo))])
		     && ($state(connection) eq "close")
		     && ("close" in $state(connection))
		     && ($state(-keepalive))
		} {
		    # The server warns that it will close the socket after this
		    # response.
		    ##Log WARNING - socket will close after response for $token
		    # Prepare data for a call to ReplayIfClose.
		    Log $token socket will close after this transaction
		    # 1. Cancel socket-assignment coro events that have not yet
		    # launched, and add the tokens to the write queue.
		    if {[info exists socketCoEvent($state(socketinfo))]} {
			foreach {tok can} $socketCoEvent($state(socketinfo)) {
			    lappend socketWrQueue($state(socketinfo)) $tok
			    unset -nocomplain ${tok}(socketcoro)
			    after cancel $can
			    Log $tok Cancel socket after-idle event (Event)
			    Log Move $tok from socketCoEvent to socketWrQueue and cancel its after idle coro
			}
			set socketCoEvent($state(socketinfo)) {}
		    } else {
		    }

		    if {    ($socketRdQueue($state(socketinfo)) ne {})
			 || ($socketWrQueue($state(socketinfo)) ne {})
			 || ($socketWrState($state(socketinfo)) ni
						[list Wready peNding $token])
		    } {
			set InFlightW $socketWrState($state(socketinfo))
			if {$InFlightW in [list Wready peNding $token]} {
			    set InFlightW Wready
			} else {
			    set msg "token ${InFlightW} is InFlightW"
			    ##Log $msg - token $token
			}

			set socketPlayCmd($state(socketinfo)) \
				[list ReplayIfClose $InFlightW \
				$socketRdQueue($state(socketinfo)) \
				$socketWrQueue($state(socketinfo))]

			# - All tokens are preserved for re-use by ReplayCore.
			# - Queues are preserved in case of Finish with error,
			#   but are not used for anything else because
			#   socketClosing(*) is set below.
			# - Cancel the state(after) timeout events.
			foreach tokenVal $socketRdQueue($state(socketinfo)) {
			    if {[info exists ${tokenVal}(after)]} {
				after cancel [set ${tokenVal}(after)]
				unset ${tokenVal}(after)
			    }
			}

			    } else {
			    }
			    # Tokens in the read queue have no (socketcoro) to
			    # cancel.
			}
		    } else {
			set socketPlayCmd($state(socketinfo)) \
				{ReplayIfClose Wready {} {}}
		    }

		    # Do not allow further connections on this socket.
		    # Do not allow further connections on this socket (but
		    # geturl can add new requests to the replay).
		    set socketClosing($state(socketinfo)) 1
		} else {
		}

		set state(state) body

		# According to
		# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection
		# any comma-separated "Connection:" list implies keep-alive, but I
		# don't see this in the RFC so we'll play safe and
		# scan any list for "close".
		# Done here to support combining duplicate header field's values.
		if {   [info exists state(connection)]
		    && ("close" ni $state(connection))
		    && ("keep-alive" ni $state(connection))
		} {
		    lappend state(connection) "keep-alive"
		} else {
		}

		# If doing a HEAD, then we won't get any body
		if {$state(-validate)} {
		    Log ^F$tk end of response for HEAD request - token $token
		    set state(state) complete
		    Eot $token
		    return
		} elseif {
			($state(method) eq {CONNECT})
		     && [string is integer -strict $state(responseCode)]
		     && ($state(responseCode) >= 200)
		     && ($state(responseCode) < 300)
		} {
		    # A successful CONNECT response has no body.
		    # (An unsuccessful CONNECT has headers and body.)
		    # The code below is abstracted from Eot/Finish, but
		    # keeps the socket open.
		    catch {fileevent $state(sock) readable {}}
		    catch {fileevent $state(sock) writable {}}
		    set state(state) complete
		    set state(status) ok
		    if {[info commands ${token}--EventCoroutine] ne {}} {
			rename ${token}--EventCoroutine {}
		    }
		    if {[info commands ${token}--SocketCoroutine] ne {}} {
			rename ${token}--SocketCoroutine {}
		    }
		    if {[info exists state(socketcoro)]} {
			Log $token Cancel socket after-idle event (Finish)
			after cancel $state(socketcoro)
			unset state(socketcoro)
		    }
		    if {[info exists state(after)]} {
			after cancel $state(after)
			unset state(after)
		    }
		    if {    [info exists state(-command)]
			 && (![info exists state(done-command-cb)])
		    } {
			set state(done-command-cb) yes
			if {[catch {namespace eval :: $state(-command) $token} err]} {
			    set state(error) [list $err $errorInfo $errorCode]
			    set state(status) error
			}
		    }
		    return
		} else {
		}

		# - For non-chunked transfer we may have no body - in this case
		#   we may get no further file event if the connection doesn't
		#   close and no more data is sent. We can tell and must finish
		#   up now - not later - the alternative would be to wait until
		#   the server times out.
		# - In this case, the server has NOT told the client it will
		#   close the connection, AND it has NOT indicated the resource
		#   length EITHER by setting the Content-Length (totalsize) OR
		#   by using chunked Transfer-Encoding.
		# - Do not worry here about the case (Connection: close) because
		#   the server should close the connection.
		# - IF (NOT Connection: close) AND (NOT chunked encoding) AND
		#      (totalsize == 0).

		if {    (!(    [info exists state(connection)]
			    && ($state(connection) eq "close")
			    && ("close" in $state(connection))
			  )
			)
		     && (![info exists state(transfer)])
		     && ($state(transfer) eq {})
		     && ($state(totalsize) == 0)
		} {
		    set msg {body size is 0 and no events likely - complete}
		    Log "$msg - token $token"
		    set msg {(length unknown, set to 0)}
		    Log ^F$tk end of response body {*}$msg - token $token
		    set state(state) complete
		    Eot $token
		    return
		} else {
		}

		# We have to use binary translation to count bytes properly.
		lassign [fconfigure $sock -translation] trRead trWrite
		fconfigure $sock -translation [list binary $trWrite]

		if {
		    $state(-binary) || [IsBinaryContentType $state(type)]
		} {
		    # Turn off conversions for non-text data.
		    set state(binary) 1
		} else {
		}
		if {[info exists state(-channel)]} {
		    if {$state(binary) || [llength [ContentEncoding $token]]} {
			fconfigure $state(-channel) -translation binary
		    } else {
		    }
		    if {![info exists state(-handler)]} {
			# Initiate a sequence of background fcopies.
			fileevent $sock readable {}
			rename ${token}EventCoroutine {}
			rename ${token}--EventCoroutine {}
			CopyStart $sock $token
			return
		    } else {
		    }
		} else {
		}
	    } elseif {$nhl > 0} {
		# Process header lines.
		##Log header - token $token - $line
		if {[regexp -nocase {^([^:]+):(.+)$} $line x key value]} {
		    switch -- [string tolower $key] {
		    set key [string tolower $key]
		    switch -- $key {
			content-type {
			    set state(type) [string trim [string tolower $value]]
			    # Grab the optional charset information.
			    if {[regexp -nocase \
				    {charset\s*=\s*\"((?:[^""]|\\\")*)\"} \
				    $state(type) -> cs]} {
				set state(charset) [string map {{\"} \"} $cs]
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
3924
3925
3926
3927
3928
3929
3930

3931


3932
3933
3934









3935


3936





3937



3938
3939
3940
3941



3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962

3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979







-

-
-
+
+
+
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
+
-
-
-
+
+
+
+
-
-
-
+
+
+




+




+

+






-
+








+







			}
			transfer-encoding {
			    set state(transfer) \
				    [string trim [string tolower $value]]
			}
			proxy-connection -
			connection {
			    set tmpHeader [string trim [string tolower $value]]
			    # RFC 7230 Section 6.1 states that a comma-separated
			    # list is an acceptable value.  According to
			    # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection
			    # list is an acceptable value.
			    if {![info exists state(connectionRespFlag)]} {
				# This is the first "Connection" response header.
			    # any comma-separated list implies keep-alive, but I
			    # don't see this in the RFC so we'll play safe and
			    # scan any list for "close".
			    if {$tmpHeader in {close keep-alive}} {
				# The common cases, continue.
			    } elseif {[string first , $tmpHeader] < 0} {
				# Not a comma-separated list, not "close",
				# therefore "keep-alive".
				set tmpHeader keep-alive
				# Scrub the earlier value set by iniitialisation.
			    } else {
				set tmpResult keep-alive
				set state(connectionRespFlag) {}
				set tmpCsl [split $tmpHeader ,]
				# Optional whitespace either side of separator.
				foreach el $tmpCsl {
				    if {[string trim $el] eq {close}} {
					set tmpResult close
				set state(connection) {}
					break
				    }
			        }
			    }
			    foreach el [SplitCommaSeparatedFieldValue $value] {
				lappend state(connection) [string tolower $el]
			    }
				set tmpHeader $tmpResult
			    }
			    set state(connection) $tmpHeader
			}
			upgrade {
			    set state(upgrade) [string trim $value]
			}
			set-cookie {
			    if {$http(-cookiejar) ne ""} {
				ParseCookie $token [string trim $value]
			    } else {
			    }
			}
		    }
		    lappend state(meta) $key [string trim $value]
		} else {
		}
	    } else {
	    }
	} else {
	    # Now reading body
	    ##Log body - token $token
	    if {[catch {
		if {[info exists state(-handler)]} {
		    set n [eval $state(-handler) [list $sock $token]]
		    set n [namespace eval :: $state(-handler) [list $sock $token]]
		    ##Log handler $n - token $token
		    # N.B. the protocol has been set to 1.0 because the -handler
		    # logic is not expected to handle chunked encoding.
		    # FIXME Allow -handler with 1.1 on dechunked stacked chan.
		    if {$state(totalsize) == 0} {
			# We know the transfer is complete only when the server
			# closes the connection - i.e. eof is not an error.
			set state(state) complete
		    } else {
		    }
		    if {![string is integer -strict $n]} {
			if 1 {
			    # Do not tolerate bad -handler - fail with error
			    # status.
			    set msg {the -handler command for http::geturl must\
				    return an integer (the number of bytes\
2857
2858
2859
2860
2861
2862
2863

2864
2865
2866
2867

2868
2869
2870
2871
2872
2873
2874
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005

4006
4007
4008
4009
4010
4011
4012
4013







+



-
+







			    #     HTTP/1.0 equivalent; or it MUST fail (as
			    #     above) if the server sends
			    #     "Connection: keep-alive" or the HTTP/1.0
			    #     equivalent.
			    set n 0
			    set state(state) complete
			}
		    } else {
		    }
		} elseif {[info exists state(transfer_final)]} {
		    # This code forgives EOF in place of the final CRLF.
		    set line [getTextLine $sock]
		    set line [GetTextLine $sock]
		    set n [string length $line]
		    set state(state) complete
		    if {$n > 0} {
			# - HTTP trailers (late response headers) are permitted
			#   by Chunked Transfer-Encoding, and can be safely
			#   ignored.
			# - Do not count these bytes in the total received for
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
4022
4023
4024
4025
4026
4027
4028

4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058

4059
4060
4061
4062
4063
4064
4065
4066







-
+












+












+



-
+







			Eot $token
		    }
		} elseif {    [info exists state(transfer)]
			   && ($state(transfer) eq "chunked")
		} {
		    ##Log chunked - token $token
		    set size 0
		    set hexLenChunk [getTextLine $sock]
		    set hexLenChunk [GetTextLine $sock]
		    #set ntl [string length $hexLenChunk]
		    if {[string trim $hexLenChunk] ne ""} {
			scan $hexLenChunk %x size
			if {$size != 0} {
			    ##Log chunk-measure $size - token $token
			    set chunk [BlockingRead $sock $size]
			    set n [string length $chunk]
			    if {$n >= 0} {
				append state(body) $chunk
				incr state(log_size) [string length $chunk]
				##Log chunk $n cumul $state(log_size) -\
					token $token
			    } else {
			    }
			    if {$size != [string length $chunk]} {
				Log "WARNING: mis-sized chunk:\
				    was [string length $chunk], should be\
				    $size - token $token"
				set n 0
				set state(connection) close
				Log ^X$tk end of response (chunk error) \
					- token $token
				set msg {error in chunked encoding - fetch\
					terminated}
				Eot $token $msg
			    } else {
			    }
			    # CRLF that follows chunk.
			    # If eof, this is handled at the end of this proc.
			    getTextLine $sock
			    GetTextLine $sock
			} else {
			    set n 0
			    set state(transfer_final) {}
			}
		    } else {
			# Line expected to hold chunk length is empty, or eof.
			##Log bad-chunk-measure - token $token
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
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135

4136
4137
4138
4139
4140
4141
4142
4143
4144

4145
4146
4147
4148
4149
4150
4151
4152
4153







+











+










+

+







-
+

+






-
+
+







			    token $token
		    set block [read $sock $reqSize]
		    set n [string length $block]
		    if {$n >= 0} {
			append state(body) $block
			##Log non-chunk [string length $state(body)] -\
				token $token
		    } else {
		    }
		}
		# This calculation uses n from the -handler, chunked, or
		# unchunked case as appropriate.
		if {[info exists state]} {
		    if {$n >= 0} {
			incr state(currentsize) $n
			set c $state(currentsize)
			set t $state(totalsize)
			##Log another $n currentsize $c totalsize $t -\
				token $token
		    } else {
		    }
		    # If Content-Length - check for end of data.
		    if {
			   ($state(totalsize) > 0)
			&& ($state(currentsize) >= $state(totalsize))
		    } {
			Log ^F$tk end of response body (unchunked) -\
				token $token
			set state(state) complete
			Eot $token
		    } else {
		    }
		} else {
		}
	    } err]} {
		Log ^X$tk end of response (error ${err}) - token $token
		Finish $token $err
		return
	    } else {
		if {[info exists state(-progress)]} {
		    eval $state(-progress) \
		    namespace eval :: $state(-progress) \
			[list $token $state(totalsize) $state(currentsize)]
		} else {
		}
	    }
	}

	# catch as an Eot above may have closed the socket already
	# $state(state) may be connecting, header, body, or complete
	if {![set cc [catch {eof $sock} eof]] && $eof} {
	if {(![catch {eof $sock} eof]) && $eof} {
	    # [eof sock] succeeded and the result was 1
	    ##Log eof - token $token
	    if {[info exists $token]} {
		set state(connection) close
		if {$state(state) eq "complete"} {
		    # This includes all cases in which the transaction
		    # can be completed by eof.
		    # The value "complete" is set only in http::Event, and it is
3014
3015
3016
3017
3018
3019
3020
3021
3022



3023
3024

3025
3026
3027
3028
3029
3030
3031
4161
4162
4163
4164
4165
4166
4167


4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180







-
-
+
+
+


+







		    Eot $token eof
		}
	    } else {
		# open connection closed on a token that has been cleaned up.
		Log ^X$tk end of response (token error) - token $token
		CloseSocket $sock
	    }
	} elseif {$cc} {
	    return
	} else {
	    # EITHER [eof sock] failed - presumed done by Eot
	    # OR     [eof sock] succeeded and the result was 0
	}
    }
    return
}

# http::TestForReplay
#
#	Command called if eof is discovered when a socket is first used for a
#	new transaction.  Typically this occurs if a persistent socket is used
#	after a period of idleness and the server has half-closed the socket.
3184
3185
3186
3187
3188
3189
3190
3191

3192
3193
3194


3195
3196
3197
3198
3199
3200
3201
3202
3203
3204

3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216


3217
3218
3219
3220
3221
3222
3223
3224
3225
3226

3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246

3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267

3268
3269






3270

3271
3272

3273
3274
3275






3276

3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289

3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303

3304
3305
3306
3307
3308
3309
3310

3311





3312
3313
3314
3315
3316
3317
3318

3319
3320
3321
3322
3323
3324
3325
3326
3327

3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338

3339
3340
3341
3342
3343
3344
3345
3346
3347
3348

3349
3350
3351
3352
3353
3354
3355
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
4436
4437
4438
4439

4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467

4468
4469
4470
4471
4472
4473
4474
4475
4476

4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497

4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508

4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527







-
+


-
+
+









-
+












+
+









-
+



















-
+




















-
+


+
+
+
+
+
+
-
+

-
+



+
+
+
+
+
+
-
+













+













-
+







+
-
+
+
+
+
+







+








-
+










-
+










+







	}
    }
    dict set realopts key $cookiename
    dict set realopts value $cookieval
    {*}$http(-cookiejar) storeCookie $realopts
}

# http::getTextLine --
# http::GetTextLine --
#
#	Get one line with the stream in crlf mode.
#	Used if Transfer-Encoding is chunked.
#	Used if Transfer-Encoding is chunked, to read the line that
#	reports the size of the following chunk.
#	Empty line is not distinguished from eof.  The caller must
#	be able to handle this.
#
# Arguments
#	sock	The socket receiving input.
#
# Results:
#	The line of text, without trailing newline

proc http::getTextLine {sock} {
proc http::GetTextLine {sock} {
    set tr [fconfigure $sock -translation]
    lassign $tr trRead trWrite
    fconfigure $sock -translation [list crlf $trWrite]
    set r [BlockingGets $sock]
    fconfigure $sock -translation $tr
    return $r
}

# http::BlockingRead
#
#	Replacement for a blocking read.
#	The caller must be a coroutine.
#	Used when we expect to read a chunked-encoding
#	chunk of known size.

proc http::BlockingRead {sock size} {
    if {$size < 1} {
	return
    }
    set result {}
    while 1 {
	set need [expr {$size - [string length $result]}]
	set block [read $sock $need]
	set eof [eof $sock]
	set eof [expr {[catch {eof $sock} tmp] || $tmp}]
	append result $block
	if {[string length $result] >= $size || $eof} {
	    return $result
	} else {
	    yield
	}
    }
}

# http::BlockingGets
#
#	Replacement for a blocking gets.
#	The caller must be a coroutine.
#	Empty line is not distinguished from eof.  The caller must
#	be able to handle this.

proc http::BlockingGets {sock} {
    while 1 {
	set count [gets $sock line]
	set eof [eof $sock]
	set eof [expr {[catch {eof $sock} tmp] || $tmp}]
	if {$count >= 0 || $eof} {
	    return $line
	} else {
	    yield
	}
    }
}

# http::CopyStart
#
#	Error handling wrapper around fcopy
#
# Arguments
#	sock	The socket to copy from
#	token	The token returned from http::geturl
#
# Side Effects
#	This closes the connection upon error

proc http::CopyStart {sock token {initial 1}} {
    upvar #0 $token state
    upvar 0 $token state
    if {[info exists state(transfer)] && $state(transfer) eq "chunked"} {
	foreach coding [ContentEncoding $token] {
	    if {$coding eq {deflateX}} {
		# Use the standards-compliant choice.
		set coding2 decompress
	    } else {
		set coding2 $coding
	    }
	    lappend state(zlib) [zlib stream $coding]
	    lappend state(zlib) [zlib stream $coding2]
	}
	make-transformation-chunked $sock [namespace code [list CopyChunk $token]]
	MakeTransformationChunked $sock [namespace code [list CopyChunk $token]]
    } else {
	if {$initial} {
	    foreach coding [ContentEncoding $token] {
		if {$coding eq {deflateX}} {
		    # Use the standards-compliant choice.
		    set coding2 decompress
		} else {
		    set coding2 $coding
		}
		zlib push $coding $sock
		zlib push $coding2 $sock
	    }
	}
	if {[catch {
	    # FIXME Keep-Alive on https tls::socket with unchunked transfer
	    # hangs until the server times out. A workaround is possible, as for
	    # the case without -channel, but it does not use the neat "fcopy"
	    # solution.
	    fcopy $sock $state(-channel) -size $state(-blocksize) -command \
		[list http::CopyDone $token]
	} err]} {
	    Finish $token $err
	}
    }
    return
}

proc http::CopyChunk {token chunk} {
    upvar 0 $token state
    if {[set count [string length $chunk]]} {
	incr state(currentsize) $count
	if {[info exists state(zlib)]} {
	    foreach stream $state(zlib) {
		set chunk [$stream add $chunk]
	    }
	}
	puts -nonewline $state(-channel) $chunk
	if {[info exists state(-progress)]} {
	    eval [linsert $state(-progress) end \
	    namespace eval :: [linsert $state(-progress) end \
		      $token $state(totalsize) $state(currentsize)]
	}
    } else {
	Log "CopyChunk Finish - token $token"
	if {[info exists state(zlib)]} {
	    set excess ""
	    foreach stream $state(zlib) {
		catch {
		catch {set excess [$stream add -finalize $excess]}
		    $stream put -finalize $excess
		    set excess ""
		    set overflood ""
		    while {[set overflood [$stream get]] ne ""} { append excess $overflood }
		}
	    }
	    puts -nonewline $state(-channel) $excess
	    foreach stream $state(zlib) { $stream close }
	    unset state(zlib)
	}
	Eot $token ;# FIX ME: pipelining.
    }
    return
}

# http::CopyDone
#
#	fcopy completion callback
#
# Arguments
#	token	The token returned from http::geturl
#	count	The amount transfered
#	count	The amount transferred
#
# Side Effects
#	Invokes callbacks

proc http::CopyDone {token count {error {}}} {
    variable $token
    upvar 0 $token state
    set sock $state(sock)
    incr state(currentsize) $count
    if {[info exists state(-progress)]} {
	eval $state(-progress) \
	namespace eval :: $state(-progress) \
	    [list $token $state(totalsize) $state(currentsize)]
    }
    # At this point the token may have been reset.
    if {[string length $error]} {
	Finish $token $error
    } elseif {[catch {eof $sock} iseof] || $iseof} {
	Eot $token
    } else {
	CopyStart $sock $token 0
    }
    return
}

# http::Eot
#
#	Called when either:
#	a. An eof condition is detected on the socket.
#	b. The client decides that the response is complete.
3363
3364
3365
3366
3367
3368
3369
3370

3371
3372
3373
3374
3375
3376
3377
4535
4536
4537
4538
4539
4540
4541

4542
4543
4544
4545
4546
4547
4548
4549







-
+







#
# Arguments
#	token	The token returned from http::geturl
#	force	(previously) optional, has no effect
#	reason	- "eof" means premature EOF (not EOF as the natural end of
#		  the response)
#		- "" means completion of response, with or without EOF
#		- anything else describes an error confition other than
#		- anything else describes an error condition other than
#		  premature EOF.
#
# Side Effects
#	Clean up the socket

proc http::Eot {token {reason {}}} {
    variable $token
3387
3388
3389
3390
3391
3392
3393












3394


3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409



3410


3411
3412
3413
3414
3415


3416


3417

3418


















































































3419
3420
3421
3422
3423
3424
3425
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577

4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597

4598
4599
4600
4601
4602
4603
4604
4605
4606

4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
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
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700







+
+
+
+
+
+
+
+
+
+
+
+
-
+
+















+
+
+
-
+
+





+
+
-
+
+

+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	# The response is complete.
	set state(status) ok
    }

    if {[string length $state(body)] > 0} {
	if {[catch {
	    foreach coding [ContentEncoding $token] {
		if {$coding eq {deflateX}} {
		    # First try the standards-compliant choice.
		    set coding2 decompress
		    if {[catch {zlib $coding2 $state(body)} result]} {
			# If that fails, try the MS non-compliant choice.
			set coding2 inflate
			set state(body) [zlib $coding2 $state(body)]
		    } else {
			# error {failed at standards-compliant deflate}
			set state(body) $result
		    }
		} else {
		set state(body) [zlib $coding $state(body)]
		    set state(body) [zlib $coding $state(body)]
		}
	    }
	} err]} {
	    Log "error doing decompression for token $token: $err"
	    Finish $token $err
	    return
	}

	if {!$state(binary)} {
	    # If we are getting text, set the incoming channel's encoding
	    # correctly.  iso8859-1 is the RFC default, but this could be any
	    # IANA charset.  However, we only know how to convert what we have
	    # encodings for.

	    set enc [CharsetToEncoding $state(charset)]
	    if {$enc ne "binary"} {
		if {[package vsatisfies [package provide Tcl] 9.0-]} {
		    set state(body) [encoding convertfrom -profile replace $enc $state(body)]
		} else {
		set state(body) [encoding convertfrom $enc $state(body)]
		    set state(body) [encoding convertfrom $enc $state(body)]
		}
	    }

	    # Translate text line endings.
	    set state(body) [string map {\r\n \n \r \n} $state(body)]
	}
	if {[info exists state(-guesstype)] && $state(-guesstype)} {
	    GuessType $token
    }
	}
    }
    Finish $token $reason
    return
}


# ------------------------------------------------------------------------------
#  Proc http::GuessType
# ------------------------------------------------------------------------------
# Command to attempt limited analysis of a resource with undetermined
# Content-Type, i.e. "application/octet-stream".  This value can be set for two
# reasons:
# (a) by the server, in a Content-Type header
# (b) by http::geturl, as the default value if the server does not supply a
#     Content-Type header.
#
# This command converts a resource if:
# (1) it has type application/octet-stream
# (2) it begins with an XML declaration "<?xml name="value" ... >?"
# (3) one tag is named "encoding" and has a recognised value; or no "encoding"
#     tag exists (defaulting to utf-8)
#
# RFC 9110 Sec. 8.3 states:
# "If a Content-Type header field is not present, the recipient MAY either
# assume a media type of "application/octet-stream" ([RFC2046], Section 4.5.1)
# or examine the data to determine its type."
#
# The RFC goes on to describe the pitfalls of "MIME sniffing", including
# possible security risks.
#
# Arguments:
# token       - connection token
#
# Return Value: (boolean) true iff a change has been made
# ------------------------------------------------------------------------------

proc http::GuessType {token} {
    variable $token
    upvar 0 $token state

    if {$state(type) ne {application/octet-stream}} {
	return 0
    }

    set body $state(body)
    # e.g. {<?xml version="1.0" encoding="utf-8"?> ...}

    if {![regexp -nocase -- {^<[?]xml[[:space:]][^>?]*[?]>} $body match]} {
	return 0
    }
    # e.g. {<?xml version="1.0" encoding="utf-8"?>}

    set contents [regsub -- {[[:space:]]+} $match { }]
    set contents [string range [string tolower $contents] 6 end-2]
    # e.g. {version="1.0" encoding="utf-8"}
    # without excess whitespace or upper-case letters

    if {![regexp -- {^([^=" ]+="[^"]+" )+$} "$contents "]} {
	return 0
    }
    # The application/xml default encoding:
    set res utf-8

    set tagList [regexp -all -inline -- {[^=" ]+="[^"]+"} $contents]
    foreach tag $tagList {
	regexp -- {([^=" ]+)="([^"]+)"} $tag -> name value
	if {$name eq {encoding}} {
	    set res $value
	}
    }
    set enc [CharsetToEncoding $res]
    if {$enc eq "binary"} {
	return 0
    }
    if {[package vsatisfies [package provide Tcl] 9.0-]} {
	set state(body) [encoding convertfrom -profile replace $enc $state(body)]
    } else {
	set state(body) [encoding convertfrom $enc $state(body)]
    }
    set state(body) [string map {\r\n \n \r \n} $state(body)]
    set state(type) application/xml
    set state(binary) 0
    set state(charset) $res
    return 1
}


# http::wait --
#
#	See documentation for details.
#
# Arguments:
#	token	Connection token.
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459




3460
3461
3462
3463
3464

3465
3466
3467
3468
3469
3470
3471
3472
3473
3474

3475
3476
3477
3478
3479
3480
3481
3482
3483
3484

3485
3486
3487
3488
3489
3490
3491

3492


3493
3494
3495
3496

3497
3498
3499
3500
3501
3502

3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518

3519
3520
3521
3522
3523
3524
3525
3526
















3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543

3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554



3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567




3568






















3569
3570
3571
3572
3573
3574
3575

3576
3577
3578




3579
3580

3581
3582
3583
3584
3585
3586
3587
4724
4725
4726
4727
4728
4729
4730




4731
4732
4733
4734
4735
4736
4737
4738

4739
4740
4741
4742
4743
4744
4745
4746
4747
4748

4749
4750
4751
4752
4753
4754
4755
4756
4757
4758

4759
4760
4761
4762
4763
4764
4765
4766
4767

4768
4769
4770

4771

4772






4773



4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785

4786








4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818

4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879

4880
4881

4882
4883
4884
4885
4886
4887

4888
4889
4890
4891
4892
4893
4894
4895







-
-
-
-
+
+
+
+




-
+









-
+









-
+







+
-
+
+

-

-
+
-
-
-
-
-
-
+
-
-
-












-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
















-
+











+
+
+













+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+

-

+
+
+
+

-
+







#	args	A list of name-value pairs.
#
# Results:
#	TODO

proc http::formatQuery {args} {
    if {[llength $args] % 2} {
        return \
            -code error \
            -errorcode [list HTTP BADARGCNT $args] \
            {Incorrect number of arguments, must be an even number.}
	return \
	    -code error \
	    -errorcode [list HTTP BADARGCNT $args] \
	    {Incorrect number of arguments, must be an even number.}
    }
    set result ""
    set sep ""
    foreach i $args {
	append result $sep [mapReply $i]
	append result $sep [quoteString $i]
	if {$sep eq "="} {
	    set sep &
	} else {
	    set sep =
	}
    }
    return $result
}

# http::mapReply --
# http::quoteString --
#
#	Do x-www-urlencoded character mapping
#
# Arguments:
#	string	The string the needs to be encoded
#
# Results:
#       The encoded string

proc http::mapReply {string} {
proc http::quoteString {string} {
    variable http
    variable formMap

    # The spec says: "non-alphanumeric characters are replaced by '%HH'". Use
    # a pre-computed map and [string map] to do the conversion (much faster
    # than [regsub]/[subst]). [Bug 1020491]

    if {[package vsatisfies [package provide Tcl] 9.0-]} {
    if {$http(-urlencoding) ne ""} {
	set string [encoding convertto -profile replace $http(-urlencoding) $string]
    } else {
	set string [encoding convertto $http(-urlencoding) $string]
	return [string map $formMap $string]
    }
    set converted [string map $formMap $string]
    return [string map $formMap $string]
    if {[string match "*\[\u0100-\uffff\]*" $converted]} {
	regexp "\[\u0100-\uffff\]" $converted badChar
	# Return this error message for maximum compatibility... :^/
	return -code error \
	    "can't read \"formMap($badChar)\": no such element in array"
    }
}
    return $converted
}
interp alias {} http::quoteString {} http::mapReply

# http::ProxyRequired --
#	Default proxy filter.
#
# Arguments:
#	host	The destination host
#
# Results:
#       The current proxy settings

proc http::ProxyRequired {host} {
    variable http
    if {[info exists http(-proxyhost)] && [string length $http(-proxyhost)]} {
    if {(![info exists http(-proxyhost)]) || ($http(-proxyhost) eq {})} {
	if {
	    ![info exists http(-proxyport)] ||
	    ![string length $http(-proxyport)]
	} {
	    set http(-proxyport) 8080
	}
	return [list $http(-proxyhost) $http(-proxyport)]
    }
	return
    }
    if {![info exists http(-proxyport)] || ($http(-proxyport) eq {})} {
	set port 8080
    } else {
	set port $http(-proxyport)
    }

    # Simple test (cf. autoproxy) for hosts that must be accessed directly,
    # not through the proxy server.
    foreach domain $http(-proxynot) {
	if {[string match -nocase $domain $host]} {
	    return {}
	}
    }
    return [list $http(-proxyhost) $port]
}

# http::CharsetToEncoding --
#
#	Tries to map a given IANA charset to a tcl encoding.  If no encoding
#	can be found, returns binary.
#

proc http::CharsetToEncoding {charset} {
    variable encodings

    set charset [string tolower $charset]
    if {[regexp {iso-?8859-([0-9]+)} $charset -> num]} {
	set encoding "iso8859-$num"
    } elseif {[regexp {iso-?2022-(jp|kr)} $charset -> ext]} {
	set encoding "iso2022-$ext"
    } elseif {[regexp {shift[-_]?js} $charset]} {
    } elseif {[regexp {shift[-_]?jis} $charset]} {
	set encoding "shiftjis"
    } elseif {[regexp {(?:windows|cp)-?([0-9]+)} $charset -> num]} {
	set encoding "cp$num"
    } elseif {$charset eq "us-ascii"} {
	set encoding "ascii"
    } elseif {[regexp {(?:iso-?)?lat(?:in)?-?([0-9]+)} $charset -> num]} {
	switch -- $num {
	    5 {set encoding "iso8859-9"}
	    1 - 2 - 3 {
		set encoding "iso8859-$num"
	    }
	    default {
		set encoding "binary"
	    }
	}
    } else {
	# other charset, like euc-xx, utf-8,...  may directly map to encoding
	set encoding $charset
    }
    set idx [lsearch -exact $encodings $encoding]
    if {$idx >= 0} {
	return $encoding
    } else {
	return "binary"
    }
}


# ------------------------------------------------------------------------------
#  Proc http::ContentEncoding
# ------------------------------------------------------------------------------
# Return the list of content-encoding transformations we need to do in order.
#
    # --------------------------------------------------------------------------
    # Options for Accept-Encoding, Content-Encoding: the switch command
    # --------------------------------------------------------------------------
    # The symbol deflateX allows http to attempt both versions of "deflate",
    # unless there is a -channel - for a -channel, only "decompress" is tried.
    # Alternative/extra lines for switch:
    # The standards-compliant version of "deflate" can be chosen with:
    #		deflate { lappend r decompress }
    # The Microsoft non-compliant version of "deflate" can be chosen with:
    #		deflate { lappend r inflate }
    # The previously used implementation of "compress", which appears to be
    # incorrect and is rarely used by web servers, can be chosen with:
    #		compress - x-compress { lappend r decompress }
    # --------------------------------------------------------------------------
#
# Arguments:
# token  - Connection token.
#
# Return Value: list
# ------------------------------------------------------------------------------

proc http::ContentEncoding {token} {
    upvar 0 $token state
    set r {}
    if {[info exists state(coding)]} {
	foreach coding [split $state(coding) ,] {
	    switch -exact -- $coding {
		deflate { lappend r inflate }
		deflate { lappend r deflateX }
		gzip - x-gzip { lappend r gunzip }
		compress - x-compress { lappend r decompress }
		identity {}
		br {
		    return -code error\
			    "content-encoding \"br\" not implemented"
		}
		default {
		    return -code error "unsupported content-encoding \"$coding\""
		    Log "unknown content-encoding \"$coding\" ignored"
		}
	    }
	}
    }
    return $r
}

3611
3612
3613
3614
3615
3616
3617














































3618

3619
3620























































































































































































































































































































































































































































































































































3621
3622
3623
3624
3625
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971

4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





	    # channel might have been closed in the callback
	    catch {chan event $chan readable {}}
	    return
	}
    }
}

# http::SplitCommaSeparatedFieldValue --
#	Return the individual values of a comma-separated field value.
#
# Arguments:
#	fieldValue	Comma-separated header field value.
#
# Results:
#       List of values.
proc http::SplitCommaSeparatedFieldValue {fieldValue} {
    set r {}
    foreach el [split $fieldValue ,] {
	lappend r [string trim $el]
    }
    return $r
}


# http::GetFieldValue --
#	Return the value of a header field.
#
# Arguments:
#	headers	Headers key-value list
#	fieldName	Name of header field whose value to return.
#
# Results:
#       The value of the fieldName header field
#
# Field names are matched case-insensitively (RFC 7230 Section 3.2).
#
# If the field is present multiple times, it is assumed that the field is
# defined as a comma-separated list and the values are combined (by separating
# them with commas, see RFC 7230 Section 3.2.2) and returned at once.
proc http::GetFieldValue {headers fieldName} {
    set r {}
    foreach {field value} $headers {
	if {[string equal -nocase $fieldName $field]} {
	    if {$r eq {}} {
		set r $value
	    } else {
		append r ", $value"
	    }
	}
    }
    return $r
}

proc http::make-transformation-chunked {chan command} {
proc http::MakeTransformationChunked {chan command} {
    coroutine [namespace current]::dechunk$chan ::http::ReceiveChunked $chan $command
    chan event $chan readable [namespace current]::dechunk$chan
    return
}

interp alias {} http::data {} http::responseBody
interp alias {} http::code {} http::responseLine
interp alias {} http::mapReply {} http::quoteString
interp alias {} http::meta {} http::responseHeaders
interp alias {} http::metaValue {} http::responseHeaderValue
interp alias {} http::ncode {} http::responseCode


# ------------------------------------------------------------------------------
#  Proc http::socketAsCallback
# ------------------------------------------------------------------------------
# Command to use in place of ::socket as the value of ::tls::socketCmd.
# This command does the same as http::AltSocket, and also handles https
# connections through a proxy server.
#
# Notes.
# - The proxy server works differently for https and http.  This implementation
#   is for https.  The proxy for http is implemented in http::CreateToken (in
#   code that was previously part of http::geturl).
# - This code implicitly uses the tls options set for https in a call to
#   http::register, and does not need to call commands tls::*.  This simple
#   implementation is possible because tls uses a callback to ::socket that can
#   be redirected by changing the value of ::tls::socketCmd.
#
# Arguments:
# args        - as for ::socket
#
# Return Value: a socket identifier
# ------------------------------------------------------------------------------

proc http::socketAsCallback {args} {
    variable http

    set targ [lsearch -exact $args -type]
    if {$targ != -1} {
	set token [lindex $args $targ+1]
	upvar 0 ${token} state
	set protoProxyConn $state(protoProxyConn)
    } else {
	set protoProxyConn 0
    }

    set host [lindex $args end-1]
    set port [lindex $args end]
    if {    ($http(-proxyfilter) ne {})
	 && (![catch {$http(-proxyfilter) $host} proxy])
	 && $protoProxyConn
    } {
	set phost [lindex $proxy 0]
	set pport [lindex $proxy 1]
    } else {
	set phost {}
	set pport {}
    }
    if {$phost eq ""} {
	set sock [::http::AltSocket {*}$args]
    } else {
	set sock [::http::SecureProxyConnect {*}$args $phost $pport]
    }
    return $sock
}


# ------------------------------------------------------------------------------
#  Proc http::SecureProxyConnect
# ------------------------------------------------------------------------------
# Command to open a socket through a proxy server to a remote server for use by
# tls. The caller must perform the tls handshake.
#
# Notes
# - Based on patch supplied by Melissa Chawla in ticket 1173760, and
#   Proxy-Authorization header cf. autoproxy by Pat Thoyts.
# - Rewritten as a call to http::geturl, because response headers and body are
#   needed if the CONNECT request fails.  CONNECT is implemented for this case
#   only, by state(bypass).
# - FUTURE WORK: give http::geturl a -connect option for a general CONNECT.
# - The request header Proxy-Connection is discouraged in RFC 7230 (June 2014),
#   RFC 9112 (June 2022).
#
# Arguments:
# args        - as for ::socket, ending in host, port; with proxy host, proxy
#               port appended.
#
# Return Value: a socket identifier
# ------------------------------------------------------------------------------

proc http::SecureProxyConnect {args} {
    variable http
    variable ConnectVar
    variable ConnectCounter
    variable failedProxyValues
    set varName ::http::ConnectVar([incr ConnectCounter])

    # Extract (non-proxy) target from args.
    set host [lindex $args end-3]
    set port [lindex $args end-2]
    set args [lreplace $args end-3 end-2]

    # Proxy server URL for connection.
    # This determines where the socket is opened.
    set phost [lindex $args end-1]
    set pport [lindex $args end]
    if {[string first : $phost] != -1} {
	# IPv6 address, wrap it in [] so we can append :pport
	set phost "\[${phost}\]"
    }
    set url http://${phost}:${pport}
    # Elements of args other than host and port are not used when
    # AsyncTransaction opens a socket.  Those elements are -async and the
    # -type $tokenName for the https transaction.  Option -async is used by
    # AsyncTransaction anyway, and -type $tokenName should not be
    # propagated: the proxy request adds its own -type value.

    set targ [lsearch -exact $args -type]
    if {$targ != -1} {
	# Record in the token that this is a proxy call.
	set token [lindex $args $targ+1]
	upvar 0 ${token} state
	set tim $state(-timeout)
	set state(proxyUsed) SecureProxyFailed
	# This value is overwritten with "SecureProxy" below if the CONNECT is
	# successful.  If it is unsuccessful, the socket will be closed
	# below, and so in this unsuccessful case there are no other transactions
	# whose (proxyUsed) must be updated.
    } else {
	set tim 0
    }
    if {$tim == 0} {
	# Do not use infinite timeout for the proxy.
	set tim 30000
    }

    # Prepare and send a CONNECT request to the proxy, using
    # code similar to http::geturl.
    set requestHeaders [list Host $host]
    lappend requestHeaders Connection keep-alive
    if {$http(-proxyauth) != {}} {
	lappend requestHeaders Proxy-Authorization $http(-proxyauth)
    }

    set token2 [CreateToken $url -keepalive 0 -timeout $tim \
	    -headers $requestHeaders -command [list http::AllDone $varName]]
    variable $token2
    upvar 0 $token2 state2

    # Kludges:
    # Setting this variable overrides the HTTP request line and also allows
    # -headers to override the Connection: header set by -keepalive.
    # The arguments "-keepalive 0" ensure that when Finish is called for an
    # unsuccessful request, the socket is always closed.
    set state2(bypass) "CONNECT $host:$port HTTP/1.1"

    AsyncTransaction $token2

    if {[info coroutine] ne {}} {
	# All callers in the http package are coroutines launched by
	# the event loop.
	# The cwait command requires a coroutine because it yields
	# to the caller; $varName is traced and the coroutine resumes
	# when the variable is written.
	cwait $varName
    } else {
	return -code error {code must run in a coroutine}
	# For testing with a non-coroutine caller outside the http package.
	# vwait $varName
    }
    unset $varName

    if {    ($state2(state) ne "complete")
	 || ($state2(status) ne "ok")
	 || (![string is integer -strict $state2(responseCode)])
    } {
	set msg {the HTTP request to the proxy server did not return a valid\
		and complete response}
	if {[info exists state2(error)]} {
	    append msg ": " [lindex $state2(error) 0]
	}
	cleanup $token2
	return -code error $msg
    }

    set code $state2(responseCode)

    if {($code >= 200) && ($code < 300)} {
	# All OK.  The caller in package tls will now call "tls::import $sock".
	# The cleanup command does not close $sock.
	# Other tidying was done in http::Event.

	# If this is a persistent socket, any other transactions that are
	# already marked to use the socket will have their (proxyUsed) updated
	# when http::OpenSocket calls http::ConfigureNewSocket.
	set state(proxyUsed) SecureProxy
	set sock $state2(sock)
	cleanup $token2
	return $sock
    }

    if {$targ != -1} {
	# Non-OK HTTP status code; token is known because option -type
	# (cf. targ) was passed through tcltls, and so the useful
	# parts of the proxy's response can be copied to state(*).
	# Do not copy state2(sock).
	# Return the proxy response to the caller of geturl.
	foreach name $failedProxyValues {
	    if {[info exists state2($name)]} {
		set state($name) $state2($name)
	    }
	}
	set state(connection) close
	set msg "proxy connect failed: $code"
	# - This error message will be detected by http::OpenSocket and will
	#   cause it to present the proxy's HTTP response as that of the
	#   original $token transaction, identified only by state(proxyUsed)
	#   as the response of the proxy.
	# - The cases where this would mislead the caller of http::geturl are
	#   given a different value of msg (below) so that http::OpenSocket will
	#   treat them as errors, but will preserve the $token array for
	#   inspection by the caller.
	# - Status code 305 (Proxy Required) was deprecated for security reasons
	#   in RFC 2616 (June 1999) and in any case should never be served by a
	#   proxy.
	# - Other 3xx responses from the proxy are inappropriate, and should not
	#   occur.
	# - A 401 response from the proxy is inappropriate, and should not
	#   occur.  It would be confusing if returned to the caller.

	if {($code >= 300) && ($code < 400)} {
	    set msg "the proxy server responded to the HTTP request with an\
		    inappropriate $code redirect"
	    set loc [responseHeaderValue $token2 location]
	    if {$loc ne {}} {
		append msg "to " $loc
	    }
	} elseif {($code == 401)} {
	    set msg "the proxy server responded to the HTTP request with an\
		    inappropriate 401 request for target-host credentials"
	} else {
	}
    } else {
	set msg "connection to proxy failed with status code $code"
    }

    # - ${token2}(sock) has already been closed because -keepalive 0.
    # - Error return does not pass the socket ID to the
    #   $token transaction, which retains its socket placeholder.
    cleanup $token2
    return -code error $msg
}

proc http::AllDone {varName args} {
    set $varName done
    return
}


# ------------------------------------------------------------------------------
#  Proc http::AltSocket
# ------------------------------------------------------------------------------
# This command is a drop-in replacement for ::socket.
# Arguments and return value as for ::socket.
#
# Notes.
# - http::AltSocket is specified in place of ::socket by the definition of
#   urlTypes in the namespace header of this file (http.tcl).
# - The command makes a simple call to ::socket unless the user has called
#   http::config to change the value of -threadlevel from the default value 0.
# - For -threadlevel 1 or 2, if the Thread package is available, the command
#   waits in the event loop while the socket is opened in another thread.  This
#   is a workaround for bug [824251] - it prevents http::geturl from blocking
#   the event loop if the DNS lookup or server connection is slow.
# - FIXME Use a thread pool if connections are very frequent.
# - FIXME The peer thread can transfer the socket only to the main interpreter
#   in the present thread.  Therefore this code works only if this script runs
#   in the main interpreter.  In a child interpreter, the parent must alias a
#   command to ::http::AltSocket in the child, run http::AltSocket in the
#   parent, and then transfer the socket to the child.
# - The http::AltSocket command is simple, and can easily be replaced with an
#   alternative command that uses a different technique to open a socket while
#   entering the event loop.
# - Unexpected behaviour by thread::send -async (Thread 2.8.6).
#   An error in thread::send -async causes return of just the error message
#   (not the expected 3 elements), and raises a bgerror in the main thread.
#   Hence wrap the command with catch as a precaution.
# - Bug in Thread 2.8.8 - on Windows, read/write operations fail on a socket
#   moved from another thread by thread::transfer.
# ------------------------------------------------------------------------------

proc http::AltSocket {args} {
    variable ThreadVar
    variable ThreadCounter
    variable http

    LoadThreadIfNeeded

    set targ [lsearch -exact $args -type]
    if {$targ != -1} {
	set token [lindex $args $targ+1]
	set args [lreplace $args $targ $targ+1]
	upvar 0 $token state
    }

    if {$http(usingThread) && [info exists state] && $state(protoSockThread)} {
    } else {
	# Use plain "::socket".  This is the default.
	return [eval ::socket $args]
    }

    set defcmd ::socket
    set sockargs $args
    set script "
	set code \[catch {
	    [list proc ::SockInThread {caller defcmd sockargs} [info body ::http::SockInThread]]
	    [list ::SockInThread [thread::id] $defcmd $sockargs]
	} result opts\]
	list \$code \$opts \$result
    "

    set state(tid) [thread::create]
    set varName ::http::ThreadVar([incr ThreadCounter])
    thread::send -async $state(tid) $script $varName
    Log >T Thread Start Wait $args -- coro [info coroutine] $varName
    if {[info coroutine] ne {}} {
	# All callers in the http package are coroutines launched by
	# the event loop.
	# The cwait command requires a coroutine because it yields
	# to the caller; $varName is traced and the coroutine resumes
	# when the variable is written.
	cwait $varName
    } else {
	return -code error {code must run in a coroutine}
	# For testing with a non-coroutine caller outside the http package.
	# vwait $varName
    }
    Log >U Thread End Wait $args -- coro [info coroutine] $varName [set $varName]
    thread::release $state(tid)
    set state(tid) {}
    set result [set $varName]
    unset $varName
    if {(![string is list $result]) || ([llength $result] != 3)} {
	return -code error "result from peer thread is not a list of\
		length 3: it is \n$result"
    }
    lassign $result threadCode threadDict threadResult
    if {($threadCode != 0)} {
	# This is an error in thread::send.  Return the lot.
	return -options $threadDict -code error $threadResult
    }

    # Now the results of the catch in the peer thread.
    lassign $threadResult catchCode errdict sock

    if {($catchCode == 0) && ($sock ni [chan names])} {
	return -code error {Transfer of socket from peer thread failed.\
		Check that this script is not running in a child interpreter.}
    }
    return -options $errdict -code $catchCode $sock
}

# The commands below are dependencies of http::AltSocket and
# http::SecureProxyConnect and are not used elsewhere.

# ------------------------------------------------------------------------------
#  Proc http::LoadThreadIfNeeded
# ------------------------------------------------------------------------------
# Command to load the Thread package if it is needed.  If it is needed and not
# loadable, the outcome depends on $http(-threadlevel):
# value 0 => Thread package not required, no problem
# value 1 => operate as if -threadlevel 0
# value 2 => error return
#
# The command assigns a value to http(usingThread), which records whether
# command http::AltSocket can use a separate thread.
#
# Arguments: none
# Return Value: none
# ------------------------------------------------------------------------------

proc http::LoadThreadIfNeeded {} {
    variable http
    if {$http(-threadlevel) == 0} {
	set http(usingThread) 0
	return
    }
    if {[catch {package require Thread}]} {
	if {$http(-threadlevel) == 2} {
	    set msg {[http::config -threadlevel] has value 2,\
		     but the Thread package is not available}
	    return -code error $msg
	}
	set http(usingThread) 0
	return
    }
    set http(usingThread) 1
    return
}


# ------------------------------------------------------------------------------
#  Proc http::SockInThread
# ------------------------------------------------------------------------------
# Command http::AltSocket is a ::socket replacement.  It defines and runs this
# command, http::SockInThread, in a peer thread.
#
# Arguments:
# caller
# defcmd
# sockargs
#
# Return value: list of values that describe the outcome.  The return is
# intended to be a normal (non-error) return in all cases.
# ------------------------------------------------------------------------------

proc http::SockInThread {caller defcmd sockargs} {
    package require Thread

    set catchCode [catch {eval $defcmd $sockargs} sock errdict]
    if {$catchCode == 0} {
	set catchCode [catch {thread::transfer $caller $sock; set sock} sock errdict]
    }
    return [list $catchCode $errdict $sock]
}


# ------------------------------------------------------------------------------
#  Proc http::cwaiter::cwait
# ------------------------------------------------------------------------------
# Command to substitute for vwait, without the ordering issues.
# A command that uses cwait must be a coroutine that is launched by an event,
# e.g. fileevent or after idle, and has no calling code to be resumed upon
# "yield".  It cannot return a value.
#
# Arguments:
# varName      - fully-qualified name of the variable that the calling script
#                will write to resume the coroutine.  Any scalar variable or
#                array element is permitted.
# coroName     - (optional) name of the coroutine to be called when varName is
#                written - defaults to this coroutine
# timeout      - (optional) timeout value in ms
# timeoutValue - (optional) value to assign to varName if there is a timeout
#
# Return Value: none
# ------------------------------------------------------------------------------

namespace eval http::cwaiter {
    namespace export cwait
    variable log   {}
    variable logOn 0
}

proc http::cwaiter::cwait {
    varName {coroName {}} {timeout {}} {timeoutValue {}}
} {
    set thisCoro [info coroutine]
    if {$thisCoro eq {}} {
	return -code error {cwait cannot be called outside a coroutine}
    }
    if {$coroName eq {}} {
	set coroName $thisCoro
    }
    if {[string range $varName 0 1] ne {::}} {
	return -code error {argument varName must be fully qualified}
    }
    if {$timeout eq {}} {
	set toe {}
    } elseif {[string is integer -strict $timeout] && ($timeout > 0)} {
	set toe [after $timeout [list set $varName $timeoutValue]]
    } else {
	return -code error {if timeout is supplied it must be a positive integer}
    }

    set cmd [list ::http::cwaiter::CwaitHelper $varName $coroName $toe]
    trace add variable $varName write $cmd
    CoLog "Yield $varName $coroName"
    yield
    CoLog "Resume $varName $coroName"
    return
}


# ------------------------------------------------------------------------------
#  Proc http::cwaiter::CwaitHelper
# ------------------------------------------------------------------------------
# Helper command called by the trace set by cwait.
# - Ignores the arguments added by trace.
# - A simple call to $coroName works, and in error cases gives a suitable stack
#   trace, but because it is inside a trace the headline error message is
#   something like {can't set "::Result(6)": error}, not the actual
#   error.  So let the trace command return.
# - Remove the trace immediately.  We don't want multiple calls.
# ------------------------------------------------------------------------------

proc http::cwaiter::CwaitHelper {varName coroName toe args} {
    CoLog "got $varName for $coroName"
    set cmd [list ::http::cwaiter::CwaitHelper $varName $coroName $toe]
    trace remove variable $varName write $cmd
    after cancel $toe

    after 0 $coroName
    return
}


# ------------------------------------------------------------------------------
#  Proc http::cwaiter::LogInit
# ------------------------------------------------------------------------------
# Call this command to initiate debug logging and clear the log.
# ------------------------------------------------------------------------------

proc http::cwaiter::LogInit {} {
    variable log
    variable logOn
    set log {}
    set logOn 1
    return
}

proc http::cwaiter::LogRead {} {
    variable log
    return $log
}

proc http::cwaiter::CoLog {msg} {
    variable log
    variable logOn
    if {$logOn} {
	append log $msg \n
    }
    return
}

namespace eval http {
    namespace import ::http::cwaiter::*
}

# Local variables:
# indent-tabs-mode: t
# End:

Changes to library/http/pkgIndex.tcl.

1
2

1

2

-
+
if {![package vsatisfies [package provide Tcl] 8.6-]} {return}
package ifneeded http 2.10.0a1 [list tclPkgSetup $dir http 2.10.0a1 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}]
package ifneeded http 2.10.0 [list tclPkgSetup $dir http 2.10.0 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}]

Added library/icu.tcl.


















































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#----------------------------------------------------------------------
#
# icu.tcl --
#
#	This file implements the portions of the [tcl::unsupported::icu]
#       ensemble that are coded in Tcl.
#
#----------------------------------------------------------------------
#
# Copyright © 2024 Ashok P. Nadkarni
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
#----------------------------------------------------------------------

::tcl::unsupported::loadIcu

namespace eval ::tcl::unsupported::icu {
    # Map Tcl encoding names to ICU and back. Note ICU has multiple aliases
    # for the same encoding.
    variable tclToIcu
    variable icuToTcl

    proc LogError {message} {
	puts stderr $message
    }

    proc Init {} {
	variable tclToIcu
	variable icuToTcl
	# There are some special cases where names do not line up
	# at all. Map Tcl -> ICU
	array set specialCases {
	    ebcdic ebcdic-cp-us
	    macCentEuro maccentraleurope
	    utf16 UTF16_PlatformEndian
	    utf-16be UnicodeBig
	    utf-16le UnicodeLittle
	    utf32 UTF32_PlatformEndian
	}
	# Ignore all errors. Do not want to hold up Tcl
	# if ICU not available
	if {[catch {
	    foreach tclName [encoding names] {
		if {[catch {
		    set icuNames [aliases $tclName]
		} erMsg]} {
		    LogError "Could not get aliases for $tclName: $erMsg"
		    continue
		}
		if {[llength $icuNames] == 0} {
		    # E.g. macGreek -> x-MacGreek
		    set icuNames [aliases x-$tclName]
		    if {[llength $icuNames] == 0} {
			# Still no joy, check for special cases
			if {[info exists specialCases($tclName)]} {
			    set icuNames [aliases $specialCases($tclName)]
			}
		    }
		}
		# If the Tcl name is also an ICU name use it else use
		# the first name which is the canonical ICU name
		set pos [lsearch -exact -nocase $icuNames $tclName]
		if {$pos >= 0} {
		    lappend tclToIcu($tclName) [lindex $icuNames $pos] {*}[lreplace $icuNames $pos $pos]
		} else {
		    set tclToIcu($tclName) $icuNames
		}
		foreach icuName $icuNames {
		    lappend icuToTcl($icuName) $tclName
		}
	    }
	} errMsg]} {
	    LogError $errMsg
	}
	array default set tclToIcu ""
	array default set icuToTcl ""

	# Redefine ourselves to no-op.
	proc Init {} {}
    }
    # Primarily used during development
    proc MappedIcuNames {{pat *}} {
	Init
	variable icuToTcl
	return [array names icuToTcl $pat]
    }
    # Primarily used during development
    proc UnmappedIcuNames {{pat *}} {
	Init
	variable icuToTcl
	set unmappedNames {}
	foreach icuName [converters] {
	    if {[llength [icuToTcl $icuName]] == 0} {
		lappend unmappedNames $icuName
	    }
	    foreach alias [aliases $icuName] {
		if {[llength [icuToTcl $alias]] == 0} {
		    lappend unmappedNames $alias
		}
	    }
	}
	# Aliases can be duplicates. Remove
	return [lsort -unique [lsearch -inline -all $unmappedNames $pat]]
    }
    # Primarily used during development
    proc UnmappedTclNames {{pat *}} {
	Init
	variable tclToIcu
	set unmappedNames {}
	foreach tclName [encoding names] {
	    # Note entry will always exist. Check if empty
	    if {[llength [tclToIcu $tclName]] == 0} {
		lappend unmappedNames $tclName
	    }
	}
	return [lsearch -inline -all $unmappedNames $pat]
    }

    # Returns the Tcl equivalent of an ICU encoding name or
    # the empty string in case not found.
    proc icuToTcl {icuName} {
	Init
	proc icuToTcl {icuName} {
	    variable icuToTcl
	    return [lindex $icuToTcl($icuName) 0]
	}
	icuToTcl $icuName
    }

    # Returns the ICU equivalent of an Tcl encoding name or
    # the empty string in case not found.
    proc tclToIcu {tclName} {
	Init
	proc tclToIcu {tclName} {
	    variable tclToIcu
	    return [lindex $tclToIcu($tclName) 0]
	}
	tclToIcu $tclName
    }


    namespace export {[a-z]*}
    namespace ensemble create
}

Changes to library/init.tcl.

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
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





-
-
-
-
-
+
+
+
+
+







-
-
-
-
-
+







# init.tcl --
#
# Default system startup file for Tcl-based applications.  Defines
# "unknown" procedure and auto-load facilities.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 Scriptics Corporation.
# Copyright (c) 2004 by Kevin B. Kenny.
# Copyright (c) 2018 by Sean Woods
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2004 Kevin B. Kenny.
# Copyright © 2018 Sean Woods
#
# All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#

# This test intentionally written in pre-7.5 Tcl
if {[info commands package] == ""} {
    error "version mismatch: library\nscripts expect Tcl version 7.5b1 or later but the loaded version is\nonly [info patchlevel]"
}
package require -exact Tcl 9.0a2
package require -exact tcl 9.0.1

# 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.
43
44
45
46
47
48
49
50









51
52
53
54

55
56
57
58
59
60
61
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







-
+
+
+
+
+
+
+
+
+




+







#
# (Ticket 41c9857bdd) In a safe interpreter, this file does not set
# ::auto_path (other than to {} if it is undefined). The caller, typically
# a Safe Base command, is responsible for setting ::auto_path.

if {![info exists auto_path]} {
    if {[info exists env(TCLLIBPATH)] && (![interp issafe])} {
	set auto_path $env(TCLLIBPATH)
	set auto_path [apply {{} {
	    lmap path $::env(TCLLIBPATH) {
		# Paths relative to unresolvable home dirs are ignored
		if {[catch {file tildeexpand $path} expanded_path]} {
		    continue
		}
		set expanded_path
	    }
	}}]
    } else {
	set auto_path ""
    }
}

namespace eval tcl {
    if {![interp issafe]} {
	variable Dir
	foreach Dir [list $::tcl_library [file dirname $::tcl_library]] {
	    if {$Dir ni $::auto_path} {
		lappend ::auto_path $Dir
	    }
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
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







-
-
+
-
-
-
-
-
+
+
+
-
-
-
-
+
-
-
-
-
+
+
+
+
-












-
+







		{::tcl::MacOSXPkgUnknown ::tclPkgUnknown}}
    } else {
	package unknown {::tcl::tm::UnknownHandler ::tclPkgUnknown}
    }

    # Set up the 'clock' ensemble

    namespace eval ::tcl::clock [list variable TclLibDir $::tcl_library]

    apply {{} {
    proc ::tcl::initClock {} {
	# Auto-loading stubs for 'clock.tcl'

	foreach cmd {add format scan} {
	    proc ::tcl::clock::$cmd args {
	set cmdmap [dict create]
	foreach cmd {add clicks format microseconds milliseconds scan seconds} {
	    dict set cmdmap $cmd ::tcl::clock::$cmd
		variable TclLibDir
		source [file join $TclLibDir clock.tcl]
		return [uplevel 1 [info level 0]]
	    }
	}
	}

	rename ::tcl::initClock {}
    }
	namespace inscope ::tcl::clock [list namespace ensemble create -command \
	    ::clock -map $cmdmap]
	::tcl::unsupported::clock::configure -init-complete
    }}
    ::tcl::initClock
}

# Conditionalize for presence of exec.

if {[namespace which -command exec] eq ""} {

    # Some machines do not have exec. Also, on all
    # platforms, safe interpreters do not have exec.

    set auto_noexec 1
}

# Define a log command (which can be overwitten to log errors
# Define a log command (which can be overwritten to log errors
# differently, specially when stderr is not available)

if {[namespace which -command tclLog] eq ""} {
    proc tclLog {string} {
	catch {puts stderr $string}
    }
}
210
211
212
213
214
215
216
217

218
219

220
221
222
223
224
225
226
208
209
210
211
212
213
214

215
216

217
218
219
220
221
222
223
224







-
+

-
+







		# Compute stack trace contribution from the [uplevel].
		# Note the dependence on how Tcl_AddErrorInfo, etc.
		# construct the stack trace.
		#
		set errInfo [dict get $opts -errorinfo]
		set errCode [dict get $opts -errorcode]
		set cinfo $args
		if {[string bytelength $cinfo] > 150} {
		if {[string length [encoding convertto utf-8 $cinfo]] > 150} {
		    set cinfo [string range $cinfo 0 150]
		    while {[string bytelength $cinfo] > 150} {
		    while {[string length [encoding convertto utf-8 $cinfo]] > 150} {
			set cinfo [string range $cinfo 0 end-1]
		    }
		    append cinfo ...
		}
		set tail "\n    (\"uplevel\" body line 1)\n    invoked\
			from within\n\"uplevel 1 \$args\""
		set expect "$msg\n    while executing\n\"$cinfo\"$tail"
299
300
301
302
303
304
305
306

307
308
309
310
311
312
313

314
315
316
317
318
319
320
297
298
299
300
301
302
303

304
305
306
307
308
309
310

311
312
313
314
315
316
317
318







-
+






-
+







	    history change $newcmd 0
	    uplevel 1 [list ::catch $newcmd \
		    ::tcl::UnknownResult ::tcl::UnknownOptions]
	    dict incr ::tcl::UnknownOptions -level
	    return -options $::tcl::UnknownOptions $::tcl::UnknownResult
	}

	set ret [catch {set candidates [info commands $name*]} msg]
	set ret [catch [list uplevel 1 [list info commands $name*]] candidates]
	if {$name eq "::"} {
	    set name ""
	}
	if {$ret != 0} {
	    dict append opts -errorinfo \
		    "\n    (expanding command prefix \"$name\" in unknown)"
	    return -options $opts $msg
	    return -options $opts $candidates
	}
	# Filter out bogus matches when $name contained
	# a glob-special char [Bug 946952]
	if {$name eq ""} {
	    # Handle empty $name separately due to strangeness
	    # in [string first] (See RFE 1243354)
	    set cmds $candidates
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
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







+






-
-
+
+
+
+
+

-
+











+
-
+
+



-



-
-
-
-
-
-
-
+
+
+
+
-







# namespace (optional)  The namespace where the command is being used - must be
#                       a canonical namespace as returned [namespace current]
#                       for instance. If not given, namespace current is used.

proc auto_load {cmd {namespace {}}} {
    global auto_index auto_path

    # qualify names:
    if {$namespace eq ""} {
	set namespace [uplevel 1 [list ::namespace current]]
    }
    set nameList [auto_qualify $cmd $namespace]
    # workaround non canonical auto_index entries that might be around
    # from older auto_mkindex versions
    lappend nameList $cmd
    foreach name $nameList {
    if {$cmd ni $nameList} {lappend nameList $cmd}

    # try to load (and create sub-cmd handler "_sub_load_cmd" for further usage):
    foreach name $nameList [set _sub_load_cmd {
	# via auto_index:
	if {[info exists auto_index($name)]} {
	    namespace eval :: $auto_index($name)
	    namespace inscope :: $auto_index($name)
	    # There's a couple of ways to look for a command of a given
	    # name.  One is to use
	    #    info commands $name
	    # Unfortunately, if the name has glob-magic chars in it like *
	    # or [], it may not match.  For our purposes here, a better
	    # route is to use
	    #    namespace which -command $name
	    if {[namespace which -command $name] ne ""} {
		return 1
	    }
	}
    }]
    }

    # load auto_index if possible:
    if {![info exists auto_path]} {
	return 0
    }

    if {![auto_load_index]} {
	return 0
    }
    foreach name $nameList {
	if {[info exists auto_index($name)]} {
	    namespace eval :: $auto_index($name)
	    if {[namespace which -command $name] ne ""} {
		return 1
	    }
	}

    # try again (something new could be loaded):
    foreach name $nameList $_sub_load_cmd

    }
    return 0
}

# ::tcl::Pkg::source --
# This procedure provides an alternative "source" command, which doesn't
# register the file for the "package files" command. Safe interpreters
# don't have to do anything special.
438
439
440
441
442
443
444
445

446
447
448
449
450
451
452
437
438
439
440
441
442
443

444
445
446
447
448
449
450
451







-
+







	set f ""
	if {$issafe} {
	    catch {source [file join $dir tclIndex]}
	} elseif {[catch {set f [open [file join $dir tclIndex]]}]} {
	    continue
	} else {
	    set error [catch {
		fconfigure $f -eofchar \032
		fconfigure $f -encoding utf-8 -eofchar \x1A
		set id [gets $f]
		if {$id eq "# Tcl autoload index file, version 2.0"} {
		    eval [read $f]
		} elseif {$id eq "# Tcl autoload index file: each line identifies a Tcl"} {
		    while {[gets $f line] >= 0} {
			if {([string index $line 0] eq "#") \
				|| ([llength $line] != 2)} {
551
552
553
554
555
556
557
558
559


560
561
562
563



564
565
566
567
568
569
570
550
551
552
553
554
555
556


557
558
559



560
561
562
563
564
565
566
567
568
569







-
-
+
+

-
-
-
+
+
+








    set ns [uplevel 1 [list ::namespace current]]
    set patternList [auto_qualify $pattern $ns]

    auto_load_index

    foreach pattern $patternList {
        foreach name [array names auto_index $pattern] {
            if {([namespace which -command $name] eq "")
	foreach name [array names auto_index $pattern] {
	    if {([namespace which -command $name] eq "")
		    && ([namespace qualifiers $pattern] eq [namespace qualifiers $name])} {
                namespace eval :: $auto_index($name)
            }
        }
		namespace inscope :: $auto_index($name)
	    }
	}
    }
}

# auto_execok --
#
# Returns string that indicates name of program to execute if
# name corresponds to a shell builtin or an executable in the
587
588
589
590
591
592
593
594

595
596
597
598
599
600
601
586
587
588
589
590
591
592

593
594
595
596
597
598
599
600







-
+







    global auto_execs env tcl_platform

    if {[info exists auto_execs($name)]} {
	return $auto_execs($name)
    }
    set auto_execs($name) ""

    set shellBuiltins [list assoc cls copy date del dir echo erase ftype \
    set shellBuiltins [list assoc cls copy date del dir echo erase exit ftype \
	    md mkdir mklink move rd ren rename rmdir start time type ver vol]
    if {[info exists env(PATHEXT)]} {
	# Add an initial ; to have the {} extension check first.
	set execExtensions [split ";$env(PATHEXT)" ";"]
    } else {
	set execExtensions [list {} .com .exe .bat .cmd]
    }
617
618
619
620
621
622
623
624

625
626
627
628
629
630
631
616
617
618
619
620
621
622

623
624
625
626
627
628
629
630







-
+







	    if {[file exists $file] && ![file isdirectory $file]} {
		return [set auto_execs($name) [list $file]]
	    }
	}
	return ""
    }

    set path "[file dirname [info nameof]];.;"
    set path "[file dirname [info nameofexecutable]];.;"
    if {[info exists env(SystemRoot)]} {
	set windir $env(SystemRoot)
    } elseif {[info exists env(WINDIR)]} {
	set windir $env(WINDIR)
    }
    if {[info exists windir]} {
	append path "$windir/system32;$windir/system;$windir;"
722
723
724
725
726
727
728
729

730
731
732
733
734
735
736
737
738
739
740
741

742
743
744
745
746
747
748
721
722
723
724
725
726
727

728
729
730
731
732
733
734
735
736
737
738
739

740
741
742
743
744
745
746
747







-
+











-
+







	    # We used to throw an error here, but, looking more closely
	    # at the core copy code in tclFCmd.c, if the destination
	    # exists, then we should only call this function if -force
	    # is true, which means we just want to over-write.  So,
	    # the following code is now commented out.
	    #
	    # return -code error "error $action \"$src\" to\
	    # \"$dest\": file already exists"
	    # \"$dest\": file exists"
	} else {
	    # Depending on the platform, and on the current
	    # working directory, the directories '.', '..'
	    # can be returned in various combinations.  Anyway,
	    # if any other file is returned, we must signal an error.
	    set existing [glob -nocomplain -directory $dest * .*]
	    lappend existing {*}[glob -nocomplain -directory $dest \
		    -type hidden * .*]
	    foreach s $existing {
		if {[file tail $s] ni {. ..}} {
		    return -code error "error $action \"$src\" to\
		      \"$dest\": file already exists"
		      \"$dest\": file exists"
		}
	    }
	}
    } else {
	if {[string first $nsrc $ndest] >= 0} {
	    set srclen [expr {[llength [file split $nsrc]] - 1}]
	    set ndest [lindex [file split $ndest] $srclen]

Changes to library/install.tcl.

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
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







-
+




-
-
-
-
-
+
+
+
+
+



-
-
-
-
-
+
+
+
+
+






-
+






-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+





-
+







      ###
      set package [lindex [split $fname -] 0]
      set version [lindex [split $fname -] 1]
      ###
      # Read the file, and override assumptions as needed
      ###
      set fin [open $file r]
      fconfigure $fin -encoding utf-8 -eofchar \032
      fconfigure $fin -encoding utf-8 -eofchar \x1A
      set dat [read $fin]
      close $fin
      # Look for a teapot style Package statement
      foreach line [split $dat \n] {
        set line [string trim $line]
        if { [string range $line 0 9] != "# Package " } continue
        set package [lindex $line 2]
        set version [lindex $line 3]
        break
	set line [string trim $line]
	if { [string range $line 0 9] != "# Package " } continue
	set package [lindex $line 2]
	set version [lindex $line 3]
	break
      }
      # Look for a package provide statement
      foreach line [split $dat \n] {
        set line [string trim $line]
        if { [string range $line 0 14] != "package provide" } continue
        set package [lindex $line 2]
        set version [lindex $line 3]
        break
	set line [string trim $line]
	if { [string range $line 0 14] != "package provide" } continue
	set package [lindex $line 2]
	set version [lindex $line 3]
	break
      }
      append buffer "package ifneeded $package $version \[list source \[file join \$dir [file tail $file]\]\]" \n
    }
    foreach file [glob -nocomplain $path/*.tcl] {
      if { [file tail $file] == "version_info.tcl" } continue
      set fin [open $file r]
      fconfigure $fin -encoding utf-8 -eofchar \032
      fconfigure $fin -encoding utf-8 -eofchar \x1A
      set dat [read $fin]
      close $fin
      if {![regexp "package provide" $dat]} continue
      set fname [file rootname [file tail $file]]
      # Look for a package provide statement
      foreach line [split $dat \n] {
        set line [string trim $line]
        if { [string range $line 0 14] != "package provide" } continue
        set package [lindex $line 2]
        set version [lindex $line 3]
        if {[string index $package 0] in "\$ \[ @"} continue
        if {[string index $version 0] in "\$ \[ @"} continue
        append buffer "package ifneeded $package $version \[list source \[file join \$dir [file tail $file]\]\]" \n
        break
	set line [string trim $line]
	if { [string range $line 0 14] != "package provide" } continue
	set package [lindex $line 2]
	set version [lindex $line 3]
	if {[string index $package 0] in "\$ \[ @"} continue
	if {[string index $version 0] in "\$ \[ @"} continue
	append buffer "package ifneeded $package $version \[list source \[file join \$dir [file tail $file]\]\]" \n
	break
      }
    }
    return $buffer
  }
  set fin [open $pkgidxfile r]
  fconfigure $fin -encoding utf-8 -eofchar \032
  fconfigure $fin -encoding utf-8 -eofchar \x1A
  set dat [read $fin]
  close $fin
  set trace 0
  #if {[file tail $path] eq "tool"} {
  #  set trace 1
  #}
  set thisline {}
145
146
147
148
149
150
151
152
153


154
155
156
157
158
159
160
145
146
147
148
149
150
151


152
153
154
155
156
157
158
159
160







-
-
+
+







      if {[file tail $dir] eq "teapot"} continue
      lappend paths $dir {*}[::practcl::_pkgindex_path_subdir $dir]
    }
    set i    [string length  $base]
    # Build a list of all of the paths
    if {[llength $paths]} {
      foreach path $paths {
        if {$path eq $base} continue
        set path_indexed($path) 0
	if {$path eq $base} continue
	set path_indexed($path) 0
      }
    } else {
      puts [list WARNING: NO PATHS FOUND IN $base]
    }
    set path_indexed($base) 1
    set path_indexed([file join $base boot tcl]) 1
    foreach teapath [glob -nocomplain [file join $base teapot *]] {
168
169
170
171
172
173
174
175
176
177



178
179
180
181
182
183
184
168
169
170
171
172
173
174



175
176
177
178
179
180
181
182
183
184







-
-
-
+
+
+







}
    }
    foreach path $paths {
      if {$path_indexed($path)} continue
      set thisdir [file_relative $base $path]
      set idxbuf [::practcl::_pkgindex_directory $path]
      if {[string length $idxbuf]} {
        incr path_indexed($path)
        append buffer "set dir \[set PKGDIR \[file join \[lindex \$::PATHSTACK end\] $thisdir\]\]" \n
        append buffer [string map {$dir $PKGDIR} [string trimright $idxbuf]] \n
	incr path_indexed($path)
	append buffer "set dir \[set PKGDIR \[file join \[lindex \$::PATHSTACK end\] $thisdir\]\]" \n
	append buffer [string map {$dir $PKGDIR} [string trimright $idxbuf]] \n
      }
    }
  }
  append buffer {
set dir [lindex $::PATHSTACK end]
set ::PATHSTACK [lrange $::PATHSTACK 0 end-1]
}
198
199
200
201
202
203
204
205

206
207

208
209
210
211
212
213

214
215
216
217
218
219
220
198
199
200
201
202
203
204

205
206

207
208
209
210
211
212

213
214
215
216
217
218
219
220







-
+

-
+





-
+







  foreach ftail [glob -directory $d1 -nocomplain -tails *] {
    set f [file join $d1 $ftail]
    if {[file isdirectory $f] && [string compare CVS $ftail]} {
      installDir $f [file join $d2 $ftail]
    } elseif {[file isfile $f]} {
	    file copy -force $f [file join $d2 $ftail]
	    if {$::tcl_platform(platform) eq {unix}} {
        file attributes [file join $d2 $ftail] -permissions 0644
	file attributes [file join $d2 $ftail] -permissions 0o644
	    } else {
        file attributes [file join $d2 $ftail] -readonly 1
	file attributes [file join $d2 $ftail] -readonly 1
	    }
    }
  }

  if {$::tcl_platform(platform) eq {unix}} {
    file attributes $d2 -permissions 0755
    file attributes $d2 -permissions 0o755
  } else {
    file attributes $d2 -readonly 1
  }
}

proc ::practcl::copyDir {d1 d2 {toplevel 1}} {
  #if {$toplevel} {

Changes to library/manifest.txt.

1
2
3
4
5
6
7
8

9
10

11
12
13

14
15

16
17
18
19
20
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 ::test [info script]
  set isafe [interp issafe]
  foreach {safe package version file} {
    0 http            2.10.0a1  {http http.tcl}
    0 http            2.10.0 {http http.tcl}
    1 msgcat          1.7.1  {msgcat msgcat.tcl}
    1 opt             0.4.8  {opt optparse.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.14 {platform platform.tcl}
    0 platform        1.0.19 {platform platform.tcl}
    0 platform::shell 1.1.4  {platform shell.tcl}
    1 tcltest         2.5.3  {tcltest tcltest.tcl}
    1 tcltest         2.5.9  {tcltest tcltest.tcl}
  } {
    if {$isafe && !$safe} continue
    package ifneeded $package $version  [list source [file join $dir {*}$file]]
  }
}} $dir

Changes to library/msgcat/msgcat.tcl.

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
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
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
30
31
32
33
34
35
36

37
38
39
40
41
42
43
44






-
-
-
+
+
+













-
+













-
+







# msgcat.tcl --
#
#	This file defines various procedures which implement a
#	message catalog facility for Tcl programs.  It should be
#	loaded with the command "package require msgcat".
#
# Copyright (c) 2010-2018 by Harald Oehlmann.
# Copyright (c) 1998-2000 by Ajuba Solutions.
# Copyright (c) 1998 by Mark Harrison.
# Copyright © 2010-2018 Harald Oehlmann.
# Copyright © 1998-2000 Ajuba Solutions.
# Copyright © 1998 Mark Harrison.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

# We use oo::define::self, which is new in Tcl 8.7
package require Tcl 8.7-
# When the version number changes, be sure to update the pkgIndex.tcl file,
# and the installation directory in the Makefiles.
package provide msgcat 1.7.1

namespace eval msgcat {
    namespace export mc mcn mcexists mcload mclocale mcmax\
	    mcmset mcpreferences mcset\
            mcunknown mcflset mcflmset mcloadedlocales mcforgetpackage\
	    mcunknown mcflset mcflmset mcloadedlocales mcforgetpackage\
	    mcpackagenamespaceget mcpackageconfig mcpackagelocale mcutil

    # Records the list of locales to search
    variable Loclist {}

    # List of currently loaded locales
    variable LoadedLocales {}

    # Records the locale of the currently sourced message catalogue file
    variable FileLocale

    # Configuration values per Package (e.g. client namespace).
    # The dict key is of the form "<option> <namespace>" and the value is the
    # configuration option. A nonexisting key is an unset option.
    # configuration option. A non-existing key is an unset option.
    variable PackageConfig [dict create mcfolder {} loadcmd {} changecmd {}\
	    unknowncmd {} loadedlocales {} loclist {}]

    # Records the mapping between source strings and translated strings.  The
    # dict key is of the form "<namespace> <locale> <src>", where locale and
    # namespace should be themselves dict values and the value is
    # the translated string.
207
208
209
210
211
212
213

214
215
216
217
218
219
220
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221







+







# msgcat::mcn --
#
#	Find the translation for the given string based on the current
#	locale setting. Check the passed namespace first, then look in each
#	parent namespace until the source is found.  If additional args are
#	specified, use the format command to work them into the translated
#	string.
#
#	If no catalog item is found, mcunknown is called in the caller frame
#	and its result is returned.
#
# Arguments:
#	ns	Package namespace of the translation
#	src	The string to translate.
#	args	Args to pass to the format command
680
681
682
683
684
685
686
687

688
689
690
691
692
693
694
681
682
683
684
685
686
687

688
689
690
691
692
693
694
695







-
+







#	    unset	Clear option. return "".
#
#	Available options are:
#
#	mcfolder
#	    The message catalog folder of the package.
#	    This is automatically set by mcload.
#	    If the value is changed using the set subcommand, an evntual
#	    If the value is changed using the set subcommand, an eventual
#	    loadcmd is invoked and all message files of the package locale are
#	    loaded.
#
#	loadcmd
#	    The command gets executed before a message file would be
#	    sourced for this module.
#	    The command is invoked with the expanded locale list to load.
733
734
735
736
737
738
739
740

741
742
743
744
745
746
747
734
735
736
737
738
739
740

741
742
743
744
745
746
747
748







-
+







    if {[llength [info level 0]] == 4 } {
	# value provided
	if {$subcommand in {"get" "isset" "unset"}} {
	    return -code error "wrong # args: should be\
		    \"[lrange [info level 0] 0 2] value\""
	}
    } elseif {$subcommand eq "set"} {
        return -code error\
	return -code error\
		"wrong # args: should be \"[lrange [info level 0] 0 2]\""
    }

    # Execute subcommands
    switch -exact -- $subcommand {
	get {	# Operation get return current value
	    if {![dict exists $PackageConfig $option $ns]} {
1215
1216
1217
1218
1219
1220
1221
1222









1223
1224

1225
1226
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
1216
1217
1218
1219
1220
1221
1222

1223
1224
1225
1226
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







-
+
+
+
+
+
+
+
+
+

-
+


-
+



-
+


-
+




-
-
-
-
-
+
+

+







# helper function to find package namespace of stack-frame -2
# There are 4 possibilities:
# - called from a proc
# - called within a class definition script
# - called from an class defined oo object
# - called from a classless oo object
proc ::msgcat::PackageNamespaceGet {} {
    uplevel 2 {
    set ns [uplevel 2 { namespace current }]

    if {![string match {::oo::*} $ns]} {
	# Not in object environment
	return $ns
    }
    # Ticket 91b3a5bb14: call to self may fail if namespace is stored
    # so catch all this
    try {
	# Check self namespace to determine environment
	switch -exact -- [namespace which self] {
	switch -exact -- [uplevel 2 { namespace which -command self }] {
	    {::oo::define::self} {
		# We are within a class definition
		return [namespace qualifiers [self]]
		return [namespace qualifiers [uplevel 2 { self }]]
	    }
	    {::oo::Helpers::self} {
		# We are within an object
		set Class [info object class [self]]
		set Class [info object class [uplevel 2 { self }]]
		# Check for classless defined object
		if {$Class eq {::oo::object}} {
		    return [namespace qualifiers [self]]
		    return [namespace qualifiers [uplevel 2 { self }]]
		}
		# Class defined object
		return [namespace qualifiers $Class]
	    }
	    default {
		# Not in object environment
		return [namespace current]
	    }
	}
	}
    } on error {} {
    }
    return $ns
}

# Initialize the default locale
proc msgcat::mcutil::getsystemlocale {} {
    global env

    #

Changes to library/msgcat/pkgIndex.tcl.

1
2

1

2

-
+
if {![package vsatisfies [package provide Tcl] 8.7-]} {return}
package ifneeded msgcat 1.7.1 [list source [file join $dir msgcat.tcl]]
package ifneeded msgcat 1.7.1 [list source -encoding utf-8 [file join $dir msgcat.tcl]]

Changes to library/opt/optparse.tcl.

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
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
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
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













-
+





-
-
-
-
+
+
+
+

















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+















-
+







# optparse.tcl --
#
#       (private) Option parsing package
#       Primarily used internally by the safe:: code.
#
#	WARNING: This code will go away in a future release
#	of Tcl.  It is NOT supported and you should not rely
#	on it.  If your code does rely on this package you
#	may directly incorporate this code into your application.

package require Tcl 8.5-
# When this version number changes, update the pkgIndex.tcl file
# and the install directory in the Makefiles.
package provide opt 0.4.8
package provide opt 0.4.9

namespace eval ::tcl {

    # Exported APIs
    namespace export OptKeyRegister OptKeyDelete OptKeyError OptKeyParse \
             OptProc OptProcArgGiven OptParse \
	     Lempty Lget \
             Lassign Lvarpop Lvarpop1 Lvarset Lvarincr \
             SetMax SetMin
	    OptProc OptProcArgGiven OptParse \
	    Lempty Lget \
	    Lassign Lvarpop Lvarpop1 Lvarset Lvarincr \
	    SetMax SetMin


#################  Example of use / 'user documentation'  ###################

    proc OptCreateTestProc {} {

	# Defines ::tcl::OptParseTest as a test proc with parsed arguments
	# (can't be defined before the code below is loaded (before "OptProc"))

	# Every OptProc give usage information on "procname -help".
	# Try "tcl::OptParseTest -help" and "tcl::OptParseTest -a" and
	# then other arguments.
	#
	# example of 'valid' call:
	# ::tcl::OptParseTest save -4 -pr 23 -libsok SybTcl\
	#		-nostatics false ch1
	OptProc OptParseTest {
            {subcommand -choice {save print} "sub command"}
            {arg1 3 "some number"}
            {-aflag}
            {-intflag      7}
            {-weirdflag                    "help string"}
            {-noStatics                    "Not ok to load static packages"}
            {-nestedloading1 true           "OK to load into nested children"}
            {-nestedloading2 -boolean true "OK to load into nested children"}
            {-libsOK        -choice {Tk SybTcl}
		                      "List of packages that can be loaded"}
            {-precision     -int 12        "Number of digits of precision"}
            {-intval        7               "An integer"}
            {-scale         -float 1.0     "Scale factor"}
            {-zoom          1.0             "Zoom factor"}
            {-arbitrary     foobar          "Arbitrary string"}
            {-random        -string 12   "Random string"}
            {-listval       -list {}       "List value"}
            {-blahflag       -blah abc       "Funny type"}
	    {subcommand -choice {save print} "sub command"}
	    {arg1 3 "some number"}
	    {-aflag}
	    {-intflag      7}
	    {-weirdflag                    "help string"}
	    {-noStatics                    "Not ok to load static packages"}
	    {-nestedloading1 true          "OK to load into nested children"}
	    {-nestedloading2 -boolean true "OK to load into nested children"}
	    {-libsOK        -choice {Tk SybTcl}
					   "List of packages that can be loaded"}
	    {-precision     -int 12        "Number of digits of precision"}
	    {-intval        7              "An integer"}
	    {-scale         -float 1.0     "Scale factor"}
	    {-zoom          1.0            "Zoom factor"}
	    {-arbitrary     foobar         "Arbitrary string"}
	    {-random        -string 12     "Random string"}
	    {-listval       -list {}       "List value"}
	    {-blahflag       -blah abc     "Funny type"}
	    {arg2 -boolean "a boolean"}
	    {arg3 -choice "ch1 ch2"}
	    {?optarg? -list {} "optional argument"}
        } {
	} {
	    foreach v [info locals] {
		puts stderr [format "%14s : %s" $v [set $v]]
	    }
	}
    }

###################  No User serviceable part below ! ###############

    # Array storing the parsed descriptions
    variable OptDesc
    array set OptDesc {}
    # Next potentially free key id (numeric)
    variable OptDescN 0

# Inside algorithm/mechanism description:
# (not for the faint hearted ;-)
# (not for the faint-hearted ;-)
#
# The argument description is parsed into a "program tree"
# It is called a "program" because it is the program used by
# the state machine interpreter that use that program to
# actually parse the arguments at run time.
#
# The general structure of a "program" is
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
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







-
+

-
+









-
-
-
-
+
+
+
+

















-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+








# Performance/Implementation issues
# ---------------------------------
# We use tcl lists instead of arrays because with tcl8.0
# they should start to be much faster.
# But this code use a lot of helper procs (like Lvarset)
# which are quite slow and would be helpfully optimized
# for instance by being written in C. Also our struture
# for instance by being written in C. Also our structure
# is complex and there is maybe some places where the
# string rep might be calculated at great exense. to be checked.
# string rep might be calculated at great expense. to be checked.

#
# Parse a given description and saves it here under the given key
# generate a unused keyid if not given
#
proc ::tcl::OptKeyRegister {desc {key ""}} {
    variable OptDesc
    variable OptDescN
    if {[string equal $key ""]} {
        # in case a key given to us as a parameter was a number
        while {[info exists OptDesc($OptDescN)]} {incr OptDescN}
        set key $OptDescN
        incr OptDescN
	# in case a key given to us as a parameter was a number
	while {[info exists OptDesc($OptDescN)]} {incr OptDescN}
	set key $OptDescN
	incr OptDescN
    }
    # program counter
    set program [list [list "P" 1]]

    # are we processing flags (which makes a single program step)
    set inflags 0

    set state {}

    # flag used to detect that we just have a single (flags set) subprogram.
    set empty 1

    foreach item $desc {
	if {$state == "args"} {
	    # more items after 'args'...
	    return -code error "'args' special argument must be the last one"
	}
        set res [OptNormalizeOne $item]
        set state [lindex $res 0]
        if {$inflags} {
            if {$state == "flags"} {
	set res [OptNormalizeOne $item]
	set state [lindex $res 0]
	if {$inflags} {
	    if {$state == "flags"} {
		# add to 'subprogram'
                lappend flagsprg $res
            } else {
                # put in the flags
                # structure for flag programs items is a list of
                # {subprgcounter {prg flag 1} {prg flag 2} {...}}
                lappend program $flagsprg
                # put the other regular stuff
                lappend program $res
		lappend flagsprg $res
	    } else {
		# put in the flags
		# structure for flag programs items is a list of
		# {subprgcounter {prg flag 1} {prg flag 2} {...}}
		lappend program $flagsprg
		# put the other regular stuff
		lappend program $res
		set inflags 0
		set empty 0
            }
        } else {
           if {$state == "flags"} {
               set inflags 1
               # sub program counter + first sub program
               set flagsprg [list [list "P" 1] $res]
           } else {
               lappend program $res
               set empty 0
           }
	    }
	} else {
	   if {$state == "flags"} {
	       set inflags 1
	       # sub program counter + first sub program
	       set flagsprg [list [list "P" 1] $res]
	   } else {
	       lappend program $res
	       set empty 0
	   }
       }
   }
   if {$inflags} {
       if {$empty} {
	   # We just have the subprogram, optimize and remove
	   # unneeded level:
	   set program $flagsprg
215
216
217
218
219
220
221
222
223
224
225
226





227
228
229

230
231
232
233
234
235
236
215
216
217
218
219
220
221





222
223
224
225
226
227
228

229
230
231
232
233
234
235
236







-
-
-
-
-
+
+
+
+
+


-
+







proc ::tcl::OptKeyDelete {key} {
    variable OptDesc
    unset OptDesc($key)
}

    # Get the parsed description stored under the given key.
    proc OptKeyGetDesc {descKey} {
        variable OptDesc
        if {![info exists OptDesc($descKey)]} {
            return -code error "Unknown option description key \"$descKey\""
        }
        set OptDesc($descKey)
	variable OptDesc
	if {![info exists OptDesc($descKey)]} {
	    return -code error "Unknown option description key \"$descKey\""
	}
	set OptDesc($descKey)
    }

# Parse entry point for ppl who don't want to register with a key,
# Parse entry point for people who don't want to register with a key,
# for instance because the description changes dynamically.
#  (otherwise one should really use OptKeyRegister once + OptKeyParse
#   as it is way faster or simply OptProc which does it all)
# Assign a temporary key, call OptKeyParse and then free the storage
proc ::tcl::OptParse {desc arglist} {
    set tempkey [OptKeyRegister $desc]
    set ret [catch {uplevel 1 [list ::tcl::OptKeyParse $tempkey $arglist]} res]
244
245
246
247
248
249
250
251
252


253
254
255


256
257
258
259
260
261
262
244
245
246
247
248
249
250


251
252
253


254
255
256
257
258
259
260
261
262







-
-
+
+

-
-
+
+







# and add a first line to the code to call the OptKeyParse proc
# Stores the list of variables that have been actually given by the user
# (the other will be sets to their default value)
# into local variable named "Args".
proc ::tcl::OptProc {name desc body} {
    set namespace [uplevel 1 [list ::namespace current]]
    if {[string match "::*" $name] || [string equal $namespace "::"]} {
        # absolute name or global namespace, name is the key
        set key $name
	# absolute name or global namespace, name is the key
	set key $name
    } else {
        # we are relative to some non top level namespace:
        set key "${namespace}::${name}"
	# we are relative to some non top level namespace:
	set key "${namespace}::${name}"
    }
    OptKeyRegister $desc $key
    uplevel 1 [list ::proc $name args "set Args \[::tcl::OptKeyParse $key \$args\]\n$body"]
    return $key
}
# Check that a argument has been given
# assumes that "OptProc" has been used as it will check in "Args" list
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
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
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
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







-
+




-
+




-
+

-
-
-
+
+
+













-
+


-
-
-
+
+
+





-
+

-
+




-
+





-
+

-
+

-
+

-
+


















-
+










-
+









-
+





-
+





-
-
+
+







	    lappend res [Lget $lst $idx]
	}
	return $res
    }

    # Advance to next description
    proc OptNextDesc {descName} {
        uplevel 1 [list Lvarincr $descName {0 1}]
	uplevel 1 [list Lvarincr $descName {0 1}]
    }

    # Get the current description, eventually descend
    proc OptCurDesc {descriptions} {
        lindex $descriptions [OptGetPrgCounter $descriptions]
	lindex $descriptions [OptGetPrgCounter $descriptions]
    }
    # get the current description, eventually descend
    # through sub programs as needed.
    proc OptCurDescFinal {descriptions} {
        set item [OptCurDesc $descriptions]
	set item [OptCurDesc $descriptions]
	# Descend untill we get the actual item and not a sub program
        while {[OptIsPrg $item]} {
            set item [OptCurDesc $item]
        }
	while {[OptIsPrg $item]} {
	    set item [OptCurDesc $item]
	}
	return $item
    }
    # Current final instruction adress
    proc OptCurAddr {descriptions {start {}}} {
	set adress [OptGetPrgCounter $descriptions]
	lappend start $adress
	set item [lindex $descriptions $adress]
	if {[OptIsPrg $item]} {
	    return [OptCurAddr $item $start]
	} else {
	    return $start
	}
    }
    # Set the value field of the current instruction
    # Set the value field of the current instruction.
    proc OptCurSetValue {descriptionsName value} {
	upvar $descriptionsName descriptions
	# get the current item full adress
        set adress [OptCurAddr $descriptions]
	# use the 3th field of the item  (see OptValue / OptNewInst)
	# Get the current item full address.
	set adress [OptCurAddr $descriptions]
	# Use the 3rd field of the item  (see OptValue / OptNewInst).
	lappend adress 2
	Lvarset descriptions $adress [list 1 $value]
	#                                  ^hasBeenSet flag
    }

    # empty state means done/paste the end of the program
    # Empty state means done/paste the end of the program.
    proc OptState {item} {
        lindex $item 0
	lindex $item 0
    }

    # current state
    proc OptCurState {descriptions} {
        OptState [OptCurDesc $descriptions]
	OptState [OptCurDesc $descriptions]
    }

    #######
    # Arguments manipulation

    # Returns the argument that has to be processed now
    # Returns the argument that has to be processed now.
    proc OptCurrentArg {lst} {
        lindex $lst 0
	lindex $lst 0
    }
    # Advance to next argument
    # Advance to next argument.
    proc OptNextArg {argsName} {
        uplevel 1 [list Lvarpop1 $argsName]
	uplevel 1 [list Lvarpop1 $argsName]
    }
    #######





    # Loop over all descriptions, calling OptDoOne which will
    # eventually eat all the arguments.
    proc OptDoAll {descriptionsName argumentsName} {
	upvar $descriptionsName descriptions
	upvar $argumentsName arguments
#	puts "entered DoAll"
	# Nb: the places where "state" can be set are tricky to figure
	#     because DoOne sets the state to flagsValue and return -continue
	#     when needed...
	set state [OptCurState $descriptions]
	# We'll exit the loop in "OptDoOne" or when state is empty.
        while 1 {
	while 1 {
	    set curitem [OptCurDesc $descriptions]
	    # Do subprograms if needed, call ourselves on the sub branch
	    while {[OptIsPrg $curitem]} {
		OptDoAll curitem arguments
#		puts "done DoAll sub"
		# Insert back the results in current tree
		Lvarset1nc descriptions [OptGetPrgCounter $descriptions]\
			$curitem
		OptNextDesc descriptions
		set curitem [OptCurDesc $descriptions]
                set state [OptCurState $descriptions]
		set state [OptCurState $descriptions]
	    }
#           puts "state = \"$state\" - arguments=($arguments)"
	    if {[Lempty $state]} {
		# Nothing left to do, we are done in this branch:
		break
	    }
	    # The following statement can make us terminate/continue
	    # as it use return -code {break, continue, return and error}
	    # codes
            OptDoOne descriptions state arguments
	    OptDoOne descriptions state arguments
	    # If we are here, no special return code where issued,
	    # we'll step to next instruction :
#           puts "new state  = \"$state\""
	    OptNextDesc descriptions
	    set state [OptCurState $descriptions]
        }
	}
    }

    # Process one step for the state machine,
    # eventually consuming the current argument.
    proc OptDoOne {descriptionsName stateName argumentsName} {
        upvar $argumentsName arguments
        upvar $descriptionsName descriptions
	upvar $argumentsName arguments
	upvar $descriptionsName descriptions
	upvar $stateName state

	# the special state/instruction "args" eats all
	# the remaining args (if any)
	if {($state == "args")} {
	    if {![Lempty $arguments]} {
		# If there is no additional arguments, leave the default value
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
467






468
469

470
471
472
473
474



475
476
477

478
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
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
467
468

469
470
471



472
473
474
475
476

477
478
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







-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
+


-
-
-
+
+
+


-
+



-
+




-
-
+
+













-
+












-
+







	    } else {
		return -code error [OptMissingValue $descriptions]
	    }
	} else {
	    set arg [OptCurrentArg $arguments]
	}

        switch $state {
            flags {
                # A non-dash argument terminates the options, as does --
	switch $state {
	    flags {
		# A non-dash argument terminates the options, as does --

                # Still a flag ?
                if {![OptIsFlag $arg]} {
                    # don't consume the argument, return to previous prg
                    return -code return
                }
                # consume the flag
                OptNextArg arguments
                if {[string equal "--" $arg]} {
                    # return from 'flags' state
                    return -code return
                }
		# Still a flag ?
		if {![OptIsFlag $arg]} {
		    # don't consume the argument, return to previous prg
		    return -code return
		}
		# consume the flag
		OptNextArg arguments
		if {[string equal "--" $arg]} {
		    # return from 'flags' state
		    return -code return
		}

                set hits [OptHits descriptions $arg]
                if {$hits > 1} {
                    return -code error [OptAmbigous $descriptions $arg]
                } elseif {$hits == 0} {
                    return -code error [OptFlagUsage $descriptions $arg]
                }
		set hits [OptHits descriptions $arg]
		if {$hits > 1} {
		    return -code error [OptAmbigous $descriptions $arg]
		} elseif {$hits == 0} {
		    return -code error [OptFlagUsage $descriptions $arg]
		}
		set item [OptCurDesc $descriptions]
                if {[OptNeedValue $item]} {
		if {[OptNeedValue $item]} {
		    # we need a value, next state is
		    set state flagValue
                } else {
                    OptCurSetValue descriptions 1
                }
		} else {
		    OptCurSetValue descriptions 1
		}
		# continue
		return -code continue
            }
	    }
	    flagValue -
	    value {
		set item [OptCurDesc $descriptions]
                # Test the values against their required type
		# Test the values against their required type
		if {[catch {OptCheckType $arg\
			[OptType $item] [OptTypeArgs $item]} val]} {
		    return -code error [OptBadValue $item $arg $val]
		}
                # consume the value
                OptNextArg arguments
		# consume the value
		OptNextArg arguments
		# set the value
		OptCurSetValue descriptions $val
		# go to next state
		if {$state == "flagValue"} {
		    set state flags
		    return -code continue
		} else {
		    set state next; # not used, for debug only
		    return ; # will go on next step
		}
	    }
	    optValue {
		set item [OptCurDesc $descriptions]
                # Test the values against their required type
		# Test the values against their required type
		if {![catch {OptCheckType $arg\
			[OptType $item] [OptTypeArgs $item]} val]} {
		    # right type, so :
		    # consume the value
		    OptNextArg arguments
		    # set the value
		    OptCurSetValue descriptions $val
		}
		# go to next state
		set state next; # not used, for debug only
		return ; # will go on next step
	    }
        }
	}
	# If we reach this point: an unknown
	# state as been entered !
	return -code error "Bug! unknown state in DoOne \"$state\"\
		(prg counter [OptGetPrgCounter $descriptions]:\
			[OptCurDesc $descriptions])"
    }

549
550
551
552
553
554
555
556

557
558
559
560
561
562
563
549
550
551
552
553
554
555

556
557
558
559
560
561
562
563







-
+







		set vnamesLst [OptTreeVars $item $level $vnamesLst]
	    } else {
		set vname [OptVarName $item]
		upvar $level $vname var
		if {[OptHasBeenSet $item]} {
#		    puts "adding $vname"
		    # lets use the input name for the returned list
		    # it is more usefull, for instance you can check that
		    # it is more useful, for instance you can check that
		    # no flags at all was given with expr
		    # {![string match "*-*" $Args]}
		    lappend vnamesLst [OptName $item]
		    set var [OptValue $item]
		} else {
		    set var [OptDefaultValue $item]
		}
572
573
574
575
576
577
578
579
580
581
582




583
584
585
586
587




588
589

590
591

592
593
594
595
596


597
598
599

600
601
602
603
604
605
606





607
608

609
610
611
612
613
614
615
616



617
618

619
620
621
622
623
624
625
626
627
628
629
630



631
632
633
634
635
636
637
638


639
640
641
642
643
644
645
646
647
648
649
650
651

652
653

654
655
656
657

658
659
660
661
662
663

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
707
708
709
710
711
712
713
714
715


716
717
718
719
720
721
722



723
724
725
726
727
728
729
730
731
732
733
734
735
736

737
738

739
740
741
742



743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767














768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783









784
785

786
787
788

789
790
791
792
793
794
795


796
797
798
799
800




801
802
803
804
805
806
807
808
809








810
811
812
813
814
815
816
817
818
819
820
821
822
823










824
825
826
827
828
829

830
831
832

833
834
835

836
837
838
839
840
841
842
843
844
845
846
847
848

849
850
851
852
853
854


855
856
857
858
859
860
861
572
573
574
575
576
577
578




579
580
581
582
583




584
585
586
587
588

589
590

591
592
593
594


595
596
597
598

599
600
601





602
603
604
605
606
607

608
609
610
611
612
613



614
615
616
617

618
619
620
621
622
623
624
625
626
627



628
629
630
631
632
633
634
635
636


637
638
639
640
641
642
643
644
645
646
647
648
649
650

651
652

653
654
655
656

657
658
659
660
661
662

663
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
707
708
709
710
711
712
713


714
715
716
717
718
719



720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735

736
737

738
739



740
741
742
743
744
745
746
747
748
749
750
751
752
753














754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774









775
776
777
778
779
780
781
782
783
784

785
786
787

788
789
790
791
792
793


794
795
796




797
798
799
800
801








802
803
804
805
806
807
808
809
810
811
812
813










814
815
816
817
818
819
820
821
822
823
824
825
826
827
828

829
830
831

832
833
834

835
836
837
838
839
840
841
842
843
844
845
846
847

848
849
850
851
852


853
854
855
856
857
858
859
860
861







-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+

-
+

-
+



-
-
+
+


-
+


-
-
-
-
-
+
+
+
+
+

-
+





-
-
-
+
+
+

-
+









-
-
-
+
+
+






-
-
+
+












-
+

-
+



-
+





-
+









-
+


-
+


-
-
-
-
+
+
+
+


-
-
+
+


-
+


-
+


-
+


-
+


-
-
-
+
+
+










-
-
+
+




-
-
-
+
+
+













-
+

-
+

-
-
-
+
+
+











-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
+


-
+





-
-
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+




-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+





-
+


-
+


-
+












-
+




-
-
+
+







# otherwise returns the canonical value of that arg (ie 0/1 for booleans)
proc ::tcl::OptCheckType {arg type {typeArgs ""}} {
#    puts "checking '$arg' against '$type' ($typeArgs)"

    # only types "any", "choice", and numbers can have leading "-"

    switch -exact -- $type {
        int {
            if {![string is integer -strict $arg]} {
                error "not an integer"
            }
	int {
	    if {![string is integer -strict $arg]} {
		error "not an integer"
	    }
	    return $arg
        }
        float {
            return [expr {double($arg)}]
        }
	}
	float {
	    return [expr {double($arg)}]
	}
	script -
        list {
	list {
	    # if llength fail : malformed list
            if {[llength $arg]==0 && [OptIsFlag $arg]} {
	    if {[llength $arg]==0 && [OptIsFlag $arg]} {
		error "no values with leading -"
	    }
	    return $arg
        }
        boolean {
	}
	boolean {
	    if {![string is boolean -strict $arg]} {
		error "non canonic boolean"
            }
	    }
	    # convert true/false because expr/if is broken with "!,...
	    return [expr {$arg ? 1 : 0}]
        }
        choice {
            if {[lsearch -exact $typeArgs $arg] < 0} {
                error "invalid choice"
            }
	}
	choice {
	    if {$arg ni $typeArgs} {
		error "invalid choice"
	    }
	    return $arg
        }
	}
	any {
	    return $arg
	}
	string -
	default {
            if {[OptIsFlag $arg]} {
                error "no values with leading -"
            }
	    if {[OptIsFlag $arg]} {
		error "no values with leading -"
	    }
	    return $arg
        }
	}
    }
    return neverReached
}

    # internal utilities

    # returns the number of flags matching the given arg
    # sets the (local) prg counter to the list of matches
    proc OptHits {descName arg} {
        upvar $descName desc
        set hits 0
        set hitems {}
	upvar $descName desc
	set hits 0
	set hitems {}
	set i 1

	set larg [string tolower $arg]
	set len  [string length $larg]
	set last [expr {$len-1}]

        foreach item [lrange $desc 1 end] {
            set flag [OptName $item]
	foreach item [lrange $desc 1 end] {
	    set flag [OptName $item]
	    # lets try to match case insensitively
	    # (string length ought to be cheap)
	    set lflag [string tolower $flag]
	    if {$len == [string length $lflag]} {
		if {[string equal $larg $lflag]} {
		    # Exact match case
		    OptSetPrgCounter desc $i
		    return 1
		}
	    } elseif {[string equal $larg [string range $lflag 0 $last]]} {
		lappend hitems $i
		incr hits
            }
	    }
	    incr i
        }
	}
	if {$hits} {
	    OptSetPrgCounter desc $hitems
	}
        return $hits
	return $hits
    }

    # Extract fields from the list structure:

    proc OptName {item} {
        lindex $item 1
	lindex $item 1
    }
    proc OptHasBeenSet {item} {
	Lget $item {2 0}
    }
    proc OptValue {item} {
	Lget $item {2 1}
    }

    proc OptIsFlag {name} {
        string match "-*" $name
	string match "-*" $name
    }
    proc OptIsOpt {name} {
        string match {\?*} $name
	string match {\?*} $name
    }
    proc OptVarName {item} {
        set name [OptName $item]
        if {[OptIsFlag $name]} {
            return [string range $name 1 end]
        } elseif {[OptIsOpt $name]} {
	set name [OptName $item]
	if {[OptIsFlag $name]} {
	    return [string range $name 1 end]
	} elseif {[OptIsOpt $name]} {
	    return [string trim $name "?"]
	} else {
            return $name
        }
	    return $name
	}
    }
    proc OptType {item} {
        lindex $item 3
	lindex $item 3
    }
    proc OptTypeArgs {item} {
        lindex $item 4
	lindex $item 4
    }
    proc OptHelp {item} {
        lindex $item 5
	lindex $item 5
    }
    proc OptNeedValue {item} {
        expr {![string equal [OptType $item] boolflag]}
	expr {![string equal [OptType $item] boolflag]}
    }
    proc OptDefaultValue {item} {
        set val [OptTypeArgs $item]
        switch -exact -- [OptType $item] {
            choice {return [lindex $val 0]}
	set val [OptTypeArgs $item]
	switch -exact -- [OptType $item] {
	    choice {return [lindex $val 0]}
	    boolean -
	    boolflag {
		# convert back false/true to 0/1 because expr !$bool
		# is broken..
		if {$val} {
		    return 1
		} else {
		    return 0
		}
	    }
        }
        return $val
	}
	return $val
    }

    # Description format error helper
    proc OptOptUsage {item {what ""}} {
        return -code error "invalid description format$what: $item\n\
                should be a list of {varname|-flagname ?-type? ?defaultvalue?\
                ?helpstring?}"
	return -code error "invalid description format$what: $item\n\
		should be a list of {varname|-flagname ?-type? ?defaultvalue?\
		?helpstring?}"
    }


    # Generate a canonical form single instruction
    proc OptNewInst {state varname type typeArgs help} {
	list $state $varname [list 0 {}] $type $typeArgs $help
	#                          ^  ^
	#                          |  |
	#               hasBeenSet=+  +=currentValue
    }

    # Translate one item to canonical form
    proc OptNormalizeOne {item} {
        set lg [Lassign $item varname arg1 arg2 arg3]
	set lg [Lassign $item varname arg1 arg2 arg3]
#       puts "called optnormalizeone '$item' v=($varname), lg=$lg"
        set isflag [OptIsFlag $varname]
	set isflag [OptIsFlag $varname]
	set isopt  [OptIsOpt  $varname]
        if {$isflag} {
            set state "flags"
        } elseif {$isopt} {
	if {$isflag} {
	    set state "flags"
	} elseif {$isopt} {
	    set state "optValue"
	} elseif {![string equal $varname "args"]} {
	    set state "value"
	} else {
	    set state "args"
	}

	# apply 'smart' 'fuzzy' logic to try to make
	# description writer's life easy, and our's difficult :
	# let's guess the missing arguments :-)

        switch $lg {
            1 {
                if {$isflag} {
                    return [OptNewInst $state $varname boolflag false ""]
                } else {
                    return [OptNewInst $state $varname any "" ""]
                }
            }
            2 {
                # varname default
                # varname help
                set type [OptGuessType $arg1]
                if {[string equal $type "string"]} {
                    if {$isflag} {
	switch $lg {
	    1 {
		if {$isflag} {
		    return [OptNewInst $state $varname boolflag false ""]
		} else {
		    return [OptNewInst $state $varname any "" ""]
		}
	    }
	    2 {
		# varname default
		# varname help
		set type [OptGuessType $arg1]
		if {[string equal $type "string"]} {
		    if {$isflag} {
			set type boolflag
			set def false
		    } else {
			set type any
			set def ""
		    }
		    set help $arg1
                } else {
                    set help ""
                    set def $arg1
                }
                return [OptNewInst $state $varname $type $def $help]
            }
            3 {
                # varname type value
                # varname value comment
		} else {
		    set help ""
		    set def $arg1
		}
		return [OptNewInst $state $varname $type $def $help]
	    }
	    3 {
		# varname type value
		# varname value comment

                if {[regexp {^-(.+)$} $arg1 x type]} {
		if {[regexp {^-(.+)$} $arg1 x type]} {
		    # flags/optValue as they are optional, need a "value",
		    # on the contrary, for a variable (non optional),
	            # default value is pointless, 'cept for choices :
		    # default value is pointless, 'cept for choices :
		    if {$isflag || $isopt || ($type == "choice")} {
			return [OptNewInst $state $varname $type $arg2 ""]
		    } else {
			return [OptNewInst $state $varname $type "" $arg2]
		    }
                } else {
                    return [OptNewInst $state $varname\
		} else {
		    return [OptNewInst $state $varname\
			    [OptGuessType $arg1] $arg1 $arg2]
                }
            }
            4 {
                if {[regexp {^-(.+)$} $arg1 x type]} {
		}
	    }
	    4 {
		if {[regexp {^-(.+)$} $arg1 x type]} {
		    return [OptNewInst $state $varname $type $arg2 $arg3]
                } else {
                    return -code error [OptOptUsage $item]
                }
            }
            default {
                return -code error [OptOptUsage $item]
            }
        }
		} else {
		    return -code error [OptOptUsage $item]
		}
	    }
	    default {
		return -code error [OptOptUsage $item]
	    }
	}
    }

    # Auto magic lazy type determination
    proc OptGuessType {arg} {
 	 if { $arg == "true" || $arg == "false" } {
            return boolean
        }
        if {[string is integer -strict $arg]} {
            return int
        }
        if {[string is double -strict $arg]} {
            return float
        }
        return string
	if { $arg == "true" || $arg == "false" } {
	    return boolean
	}
	if {[string is integer -strict $arg]} {
	    return int
	}
	if {[string is double -strict $arg]} {
	    return float
	}
	return string
    }

    # Error messages front ends

    proc OptAmbigous {desc arg} {
        OptError "ambigous option \"$arg\", choose from:" [OptSelection $desc]
	OptError "ambigous option \"$arg\", choose from:" [OptSelection $desc]
    }
    proc OptFlagUsage {desc arg} {
        OptError "bad flag \"$arg\", must be one of" $desc
	OptError "bad flag \"$arg\", must be one of" $desc
    }
    proc OptTooManyArgs {desc arguments} {
        OptError "too many arguments (unexpected argument(s): $arguments),\
	OptError "too many arguments (unexpected argument(s): $arguments),\
		usage:"\
		$desc 1
    }
    proc OptParamType {item} {
	if {[OptIsFlag $item]} {
	    return "flag"
	} else {
	    return "parameter"
	}
    }
    proc OptBadValue {item arg {err {}}} {
#       puts "bad val err = \"$err\""
        OptError "bad value \"$arg\" for [OptParamType $item]"\
	OptError "bad value \"$arg\" for [OptParamType $item]"\
		[list $item]
    }
    proc OptMissingValue {descriptions} {
#        set item [OptCurDescFinal $descriptions]
        set item [OptCurDesc $descriptions]
        OptError "no value given for [OptParamType $item] \"[OptName $item]\"\
	set item [OptCurDesc $descriptions]
	OptError "no value given for [OptParamType $item] \"[OptName $item]\"\
		(use -help for full usage) :"\
		[list $item]
    }

proc ::tcl::OptKeyError {prefix descKey {header 0}} {
    OptError $prefix [OptKeyGetDesc $descKey] $header
}
939
940
941
942
943
944
945
946

947
948
949
950
951
952
953
954
955
956
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
1016
1017
939
940
941
942
943
944
945

946
947
948
949
950
951
952
953
954
955
956
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
1016
1017







-
+














-
+

-
-
-
+
+
+


-
-
-
-
+
+
+
+










-
-
-
-
-
+
+
+
+
+

-
+












-
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+







proc ::tcl::Lempty {list} {
    expr {[llength $list]==0}
}

# Gets the value of one leaf of a lists tree
proc ::tcl::Lget {list indexLst} {
    if {[llength $indexLst] <= 1} {
        return [lindex $list $indexLst]
	return [lindex $list $indexLst]
    }
    Lget [lindex $list [lindex $indexLst 0]] [lrange $indexLst 1 end]
}
# Sets the value of one leaf of a lists tree
# (we use the version that does not create the elements because
#  it would be even slower... needs to be written in C !)
# (nb: there is a non trivial recursive problem with indexes 0,
#  which appear because there is no difference between a list
#  of 1 element and 1 element alone : [list "a"] == "a" while
#  it should be {a} and [listp a] should be 0 while [listp {a b}] would be 1
#  and [listp "a b"] maybe 0. listp does not exist either...)
proc ::tcl::Lvarset {listName indexLst newValue} {
    upvar $listName list
    if {[llength $indexLst] <= 1} {
        Lvarset1nc list $indexLst $newValue
	Lvarset1nc list $indexLst $newValue
    } else {
        set idx [lindex $indexLst 0]
        set targetList [lindex $list $idx]
        # reduce refcount on targetList (not really usefull now,
	set idx [lindex $indexLst 0]
	set targetList [lindex $list $idx]
	# reduce refcount on targetList (not really usefull now,
	# could be with optimizing compiler)
#        Lvarset1 list $idx {}
        # recursively replace in targetList
        Lvarset targetList [lrange $indexLst 1 end] $newValue
        # put updated sub list back in the tree
        Lvarset1nc list $idx $targetList
	# recursively replace in targetList
	Lvarset targetList [lrange $indexLst 1 end] $newValue
	# put updated sub list back in the tree
	Lvarset1nc list $idx $targetList
    }
}
# Set one cell to a value, eventually create all the needed elements
# (on level-1 of lists)
variable emptyList {}
proc ::tcl::Lvarset1 {listName index newValue} {
    upvar $listName list
    if {$index < 0} {return -code error "invalid negative index"}
    set lg [llength $list]
    if {$index >= $lg} {
        variable emptyList
        for {set i $lg} {$i<$index} {incr i} {
            lappend list $emptyList
        }
        lappend list $newValue
	variable emptyList
	for {set i $lg} {$i<$index} {incr i} {
	    lappend list $emptyList
	}
	lappend list $newValue
    } else {
        set list [lreplace $list $index $index $newValue]
	set list [lreplace $list $index $index $newValue]
    }
}
# same as Lvarset1 but no bound checking / creation
proc ::tcl::Lvarset1nc {listName index newValue} {
    upvar $listName list
    set list [lreplace $list $index $index $newValue]
}
# Increments the value of one leaf of a lists tree
# (which must exists)
proc ::tcl::Lvarincr {listName indexLst {howMuch 1}} {
    upvar $listName list
    if {[llength $indexLst] <= 1} {
        Lvarincr1 list $indexLst $howMuch
	Lvarincr1 list $indexLst $howMuch
    } else {
        set idx [lindex $indexLst 0]
        set targetList [lindex $list $idx]
        # reduce refcount on targetList
        Lvarset1nc list $idx {}
        # recursively replace in targetList
        Lvarincr targetList [lrange $indexLst 1 end] $howMuch
        # put updated sub list back in the tree
        Lvarset1nc list $idx $targetList
	set idx [lindex $indexLst 0]
	set targetList [lindex $list $idx]
	# reduce refcount on targetList
	Lvarset1nc list $idx {}
	# recursively replace in targetList
	Lvarincr targetList [lrange $indexLst 1 end] $howMuch
	# put updated sub list back in the tree
	Lvarset1nc list $idx $targetList
    }
}
# Increments the value of one cell of a list
proc ::tcl::Lvarincr1 {listName index {howMuch 1}} {
    upvar $listName list
    set newValue [expr {[lindex $list $index]+$howMuch}]
    set list [lreplace $list $index $index $newValue]
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
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







-
-
-
+
+
+











-
+








-
+









}
# Assign list elements to variables and return the length of the list
proc ::tcl::Lassign {list args} {
    # faster than direct blown foreach (which does not byte compile)
    set i 0
    set lg [llength $list]
    foreach vname $args {
        if {$i>=$lg} break
        uplevel 1 [list ::set $vname [lindex $list $i]]
        incr i
	if {$i>=$lg} break
	uplevel 1 [list ::set $vname [lindex $list $i]]
	incr i
    }
    return $lg
}

# Misc utilities

# Set the varname to value if value is greater than varname's current value
# or if varname is undefined
proc ::tcl::SetMax {varname value} {
    upvar 1 $varname var
    if {![info exists var] || $value > $var} {
        set var $value
	set var $value
    }
}

# Set the varname to value if value is smaller than varname's current value
# or if varname is undefined
proc ::tcl::SetMin {varname value} {
    upvar 1 $varname var
    if {![info exists var] || $value < $var} {
        set var $value
	set var $value
    }
}


    # everything loaded fine, lets create the test proc:
 #    OptCreateTestProc
    # Don't need the create temp proc anymore:
 #    rename OptCreateTestProc {}
}

Changes to library/opt/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
10
11
12

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 opt 0.4.8 [list source [file join $dir optparse.tcl]]
package ifneeded opt 0.4.9 [list source -encoding utf-8 [file join $dir optparse.tcl]]

Changes to library/package.tcl.

1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







# package.tcl --
#
# utility procs formerly in init.tcl which can be loaded on demand
# for package management.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1998 Sun Microsystems, Inc.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1998 Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#

namespace eval tcl::Pkg {}

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
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







-
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+










-
+

















-
+







# Results:
#  Returns 1 if the extension matches, 0 otherwise

proc tcl::Pkg::CompareExtension {fileName {ext {}}} {
    global tcl_platform
    if {$ext eq ""} {set ext [info sharedlibextension]}
    if {$tcl_platform(platform) eq "windows"} {
        return [string equal -nocase [file extension $fileName] $ext]
	return [string equal -nocase [file extension $fileName] $ext]
    } else {
        # Some unices add trailing numbers after the .so, so
        # we could have something like '.so.1.2'.
        set root $fileName
        while {1} {
            set currExt [file extension $root]
            if {$currExt eq $ext} {
                return 1
            }
	# Some unices add trailing numbers after the .so, so
	# we could have something like '.so.1.2'.
	set root $fileName
	while {1} {
	    set currExt [file extension $root]
	    if {$currExt eq $ext} {
		return 1
	    }

	    # The current extension does not match; if it is not a numeric
	    # value, quit, as we are only looking to ignore version number
	    # extensions.  Otherwise we might return 1 in this case:
	    #		tcl::Pkg::CompareExtension foo.so.bar .so
	    # which should not match.

	    if {![string is integer -strict [string range $currExt 1 end]]} {
		return 0
	    }
            set root [file rootname $root]
	    set root [file rootname $root]
	}
    }
}

# pkg_mkIndex --
# This procedure creates a package index in a given directory.  The package
# index consists of a "pkgIndex.tcl" file whose contents are a Tcl script that
# sets up package information with "package require" commands.  The commands
# describe all of the packages defined by the files given as arguments.
#
# Arguments:
# -direct		(optional) If this flag is present, the generated
#			code in pkgMkIndex.tcl will cause the package to be
#			loaded when "package require" is executed, rather
#			than lazily when the first reference to an exported
#			procedure in the package is made.
# -verbose		(optional) Verbose output; the name of each file that
#			was successfully rocessed is printed out. Additionally,
#			was successfully processed is printed out. Additionally,
#			if processing of a file failed a message is printed.
# -load pat		(optional) Preload any packages whose names match
#			the pattern.  Used to handle DLLs that depend on
#			other packages during their Init procedure.
# dir -			Name of the directory in which to create the index.
# args -		Any number of additional arguments, each giving
#			a glob pattern that matches the names of one or
133
134
135
136
137
138
139



140
141
142
143
144
145
146
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149







+
+
+








    try {
	set fileList [glob -directory $dir -tails -types {r f} -- \
		{*}$patternList]
    } on error {msg opt} {
	return -options $opt $msg
    }
    if {[llength $fileList] == 0} {
	return -code error "no files matched glob pattern \"$patternList\""
    }
    foreach file $fileList {
	# For each file, figure out what commands and packages it provides.
	# To do this, create a child interpreter, load the file into the
	# interpreter, and get a list of the new commands and packages that
	# are defined.

	if {$file eq "pkgIndex.tcl"} {
202
203
204
205
206
207
208
209

210
211
212
213
214
215
216
205
206
207
208
209
210
211

212
213
214
215
216
217
218
219







-
+







		    }
		}
	    }
	    proc tclPkgUnknown args {}
	    package unknown tclPkgUnknown

	    # Stub out the unknown command so package can call into each other
	    # during their initialilzation.
	    # during their initialization.

	    proc unknown {args} {}

	    # Stub out the auto_import mechanism

	    proc auto_import {args} {}

497
498
499
500
501
502
503
504

505
506
507
508
509
510
511
500
501
502
503
504
505
506

507
508
509
510
511
512
513
514







-
+







			# $file was not readable; silently ignore
			continue
		    } on error msg {
			if {[regexp {version conflict for package} $msg]} {
			    # In case of version conflict, silently ignore
			    continue
			}
    			tclLog "error reading package index file $file: $msg"
			tclLog "error reading package index file $file: $msg"
		    } on ok {} {
			set procdDirs($dir) 1
		    }
		}
	    }
	}
	set dir [lindex $use_path end]
605
606
607
608
609
610
611
612

613
614
615
616
617
618
619
608
609
610
611
612
613
614

615
616
617
618
619
620
621
622







-
+







		try {
		    ::tcl::Pkg::source $file
		} trap {POSIX EACCES} {} {
		    # $file was not readable; silently ignore
		    continue
		} on error msg {
		    if {[regexp {version conflict for package} $msg]} {
		 	# In case of version conflict, silently ignore
			# In case of version conflict, silently ignore
			continue
		    }
		    tclLog "error reading package index file $file: $msg"
		} on ok {} {
		    set procdDirs($dir) 1
		}
	    }
729
730
731
732
733
734
735
736

737
738
739
740
741
742
743
732
733
734
735
736
737
738

739
740
741
742
743
744
745
746







-
+







	error [format $err(valueMissing) "-version"]
    }

    if {!([llength $opts(-source)] || [llength $opts(-load)])} {
	error $err(noLoadOrSource)
    }

    # OK, now everything is good.  Generate the package ifneeded statment.
    # OK, now everything is good.  Generate the package ifneeded statement.
    set cmdline "package ifneeded $opts(-name) $opts(-version) "

    set cmdList {}
    set lazyFileList {}

    # Handle -load and -source specs
    foreach key {load source} {

Changes to library/parray.tcl.

1
2
3
4
5


6
7
8
9
10
11
12
1
2
3


4
5
6
7
8
9
10
11
12



-
-
+
+







# parray:
# Print the contents of a global array on stdout.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#

proc parray {a {pattern *}} {
    upvar 1 $a array

Changes to library/platform/pkgIndex.tcl.

1
2


3


1
2
3
-
-
+
+

package ifneeded platform        1.0.14 [list source [file join $dir platform.tcl]]
package ifneeded platform::shell 1.1.4 [list source [file join $dir shell.tcl]]
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]]

Changes to library/platform/platform.tcl.

25
26
27
28
29
30
31

32
33

34
35
36
37
38
39
40
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42







+


+







# result.
#
# General
# Only the first element of 'os' is used - we don't care whether we
# are on "Windows NT" or "Windows XP" or whatever.
#
# Machine specific
# % amd64  -> x86_64
# % arm*   -> arm
# % sun4*  -> sparc
# % ia32*  -> ix86
# % intel  -> ix86
# % i*86*  -> ix86
# % Power* -> powerpc
# % x86_64 + wordSize 4 => x86 code
#
# OS specific
# % AIX are always powerpc machines
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
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







+









+














-
-
-







    set cpu  $tcl_platform(machine)

    switch -glob -- $cpu {
	sun4* {
	    set cpu sparc
	}
	intel -
	ia32* -
	i*86* {
	    set cpu ix86
	}
	x86_64 {
	    if {$tcl_platform(wordSize) == 4} {
		# See Example <1> at the top of this file.
		set cpu ix86
	    }
	}
	ppc -
	"Power*" {
	    set cpu powerpc
	}
	"arm*" {
	    set cpu arm
	}
	ia64 {
	    if {$tcl_platform(wordSize) == 4} {
		append cpu _32
	    }
	}
    }

    switch -glob -- $plat {
	cygwin* {
	    set plat cygwin
	}
	windows {
	    if {$tcl_platform(platform) == "unix"} {
		set plat cygwin
	    } else {
		set plat win32
	    }
	    if {$cpu eq "amd64"} {
145
146
147
148
149
150
151



152
153
154
155
156
157
158
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162







+
+
+







		    append cpu 64
		}
	    }
	}
	osf1 {
	    set plat tru64
	}
	default {
	    set plat [lindex [split $plat _-] 0]
	}
    }

    return "${plat}-${cpu}"
}

# -- platform::identify
#
171
172
173
174
175
176
177
178





179
180
181
182

183
184
185
186
187
188
189
175
176
177
178
179
180
181

182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198







-
+
+
+
+
+




+







	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 > 8} {
	    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)

	    set v unknown

252
253
254
255
256
257
258
259

260
261
262
263
264
265
266
261
262
263
264
265
266
267

268
269
270
271
272
273
274
275







-
+







    upvar 1 $vv v
    set libclist [lsort [glob -nocomplain -directory $base libc*]]

    if {![llength $libclist]} { return 0 }

    set libc [lindex $libclist 0]

    # Try executing the library first. This should suceed
    # Try executing the library first. This should succeed
    # for a glibc library, and return the version
    # information.

    if {![catch {
	set vdata [lindex [split [exec $libc] \n] 0]
    }]} {
	regexp {version ([0-9]+(\.[0-9]+)*)} $vdata -> v
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
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







-
+







-
+
+
+
+
+
+
+
+
+
+






-

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
-
+
+







	macosx-x86_64 {
	    lappend res macosx-i386-x86_64
	}
	macosx-ix86 {
	    lappend res macosx-universal macosx-i386-x86_64
	}
	macosx*-*    {
	    # 10.5+
	    # 10.5+,11.0+
	    if {[regexp {macosx([^-]*)-(.*)} $id -> v cpu]} {

		switch -exact -- $cpu {
		    ix86    {
			lappend alt i386-x86_64
			lappend alt universal
		    }
		    x86_64  { lappend alt i386-x86_64 }
		    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

		    # Add 10.5 to 10.minor to patterns.
		    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}
			    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}
374
375
376
377
378
379
380
381

382
383
384
385
386
387
388
427
428
429
430
431
432
433

434
435
436
437
438
439
440
441







-
+







    return $res
}


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

package provide platform 1.0.14
package provide platform 1.0.19

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

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

Changes to library/platform/shell.tcl.

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
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







-
+



-
+




















-
+



-
+







proc ::platform::shell::generic {shell} {
    # Argument is the path to a tcl shell.

    CHECK $shell
    LOCATE base out

    set     code {}
    # Forget any pre-existing platform package, it might be in
    # Forget any preexisting platform package, it might be in
    # conflict with this one.
    lappend code {package forget platform}
    # Inject our platform package
    lappend code [list source $base]
    lappend code [list source -encoding utf-8 $base]
    # Query and print the architecture
    lappend code {puts [platform::generic]}
    # And done
    lappend code {exit 0}

    set arch [RUN $shell [join $code \n]]

    if {$out} {file delete -force $base}
    return $arch
}

# -- platform::shell::identify

proc ::platform::shell::identify {shell} {
    # Argument is the path to a tcl shell.

    CHECK $shell
    LOCATE base out

    set     code {}
    # Forget any pre-existing platform package, it might be in
    # Forget any preexisting platform package, it might be in
    # conflict with this one.
    lappend code {package forget platform}
    # Inject our platform package
    lappend code [list source $base]
    lappend code [list source -encoding utf-8 $base]
    # Query and print the architecture
    lappend code {puts [platform::identify]}
    # And done
    lappend code {exit 0}

    set arch [RUN $shell [join $code \n]]

95
96
97
98
99
100
101
102

103
104
105
106
107
108
109

110
111
112
113
114
115
116
95
96
97
98
99
100
101

102
103
104
105
106
107
108

109
110
111
112
113
114
115
116







-
+






-
+







    return
}

proc ::platform::shell::LOCATE {bv ov} {
    upvar 1 $bv base $ov out

    # Locate the platform package for injection into the specified
    # shell. We are using package management to find it, whereever it
    # shell. We are using package management to find it, wherever it
    # is, instead of using hardwired relative paths. This allows us to
    # install the two packages as TMs without breaking the code
    # here. If the found package is wrapped we copy the code somewhere
    # where the spawned shell will be able to read it.

    # This code is brittle, it needs has to adapt to whatever changes
    # are made to the TM code, i.e. the provide statement generated by
    # are made to the TM code, i.e. the "provide" statement generated by
    # tm.tcl

    set pl [package ifneeded platform [package require platform]]
    set base [lindex $pl end]

    set out 0
    if {[lindex [file system $base]] ne "native"} {
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141







-
+







    set    cc [open $c w]
    puts  $cc $code
    close $cc

    set e [TEMP]

    set code [catch {
        exec $shell $c 2> $e
	exec $shell $c 2> $e
    } res]

    file delete $c

    if {$code} {
	append res \n[read [set chan [open $e r]]][close $chan]
	file delete $e
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
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







-
-
-
+
+
+

-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+


-
+

-
+







    set maxtries 10
    set access [list RDWR CREAT EXCL TRUNC]
    set permission 0600
    set channel ""
    set checked_dir_writable 0
    set mypid [pid]
    for {set i 0} {$i < $maxtries} {incr i} {
 	set newname $prefix
 	for {set j 0} {$j < $nrand_chars} {incr j} {
 	    append newname [string index $chars \
	set newname $prefix
	for {set j 0} {$j < $nrand_chars} {incr j} {
	    append newname [string index $chars \
		    [expr {int(rand()*62)}]]
 	}
	}
	set newname [file join $tmpdir $newname]
 	if {[file exists $newname]} {
 	    after 1
 	} else {
 	    if {[catch {open $newname $access $permission} channel]} {
 		if {!$checked_dir_writable} {
 		    set dirname [file dirname $newname]
 		    if {![file writable $dirname]} {
 			return -code error "Directory $dirname is not writable"
 		    }
 		    set checked_dir_writable 1
 		}
 	    } else {
 		# Success
	if {[file exists $newname]} {
	    after 1
	} else {
	    if {[catch {open $newname $access $permission} channel]} {
		if {!$checked_dir_writable} {
		set dirname [file dirname $newname]
		    if {![file writable $dirname]} {
			return -code error "Directory $dirname is not writable"
		    }
		    set checked_dir_writable 1
		}
	    } else {
		# Success
		close $channel
 		return [file normalize $newname]
 	    }
 	}
		return [file normalize $newname]
	    }
	}
    }
    if {$channel ne ""} {
 	return -code error "Failed to open a temporary file: $channel"
	return -code error "Failed to open a temporary file: $channel"
    } else {
 	return -code error "Failed to find an unused temporary file name"
	return -code error "Failed to find an unused temporary file name"
    }
}

proc ::platform::shell::DIR {} {
    # This code is copied out of Tcllib's fileutil package.
    # (TempDir/tempdir)

Added library/readfile.tcl.
























1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# readFile:
# Read the contents of a file.
#
# Copyright © 2023 Donal K Fellows.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#

proc readFile {filename {mode text}} {
    # Parse the arguments
    set MODES {binary text}
    set ERR [list -level 1 -errorcode [list TCL LOOKUP MODE $mode]]
    set mode [tcl::prefix match -message "mode" -error $ERR $MODES $mode]

    # Read the file
    set f [open $filename [dict get {text r binary rb} $mode]]
    try {
	return [read $f]
    } finally {
	close $f
    }
}

Deleted library/reg/pkgIndex.tcl.

1
2
3
4




-
-
-
-
if {![package vsatisfies [package provide Tcl] 8.5-]} return
if {[info sharedlibextension] != ".dll"} return
package ifneeded registry 1.3.5 \
        [list load [file join $dir tclreg13.dll] registry]

Added library/registry/pkgIndex.tcl.










1
2
3
4
5
6
7
8
9
+
+
+
+
+
+
+
+
+
if {![package vsatisfies [package provide Tcl] 8.5-]} return
if {[info sharedlibextension] != ".dll"} return
if {[package vsatisfies [package provide Tcl] 9.0-]} {
    package ifneeded registry 1.3.7 \
	    [list load [file join $dir tcl9registry13.dll] Registry]
} else {
    package ifneeded registry 1.3.7 \
	    [list load [file join $dir tclregistry13.dll] Registry]
}

Changes to library/safe.tcl.

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
30
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
30









-
+












-
+







# safe.tcl --
#
# This file provide a safe loading/sourcing mechanism for safe interpreters.
# It implements a virtual path mecanism to hide the real pathnames from the
# child. It runs in a parent interpreter and sets up data structure and
# aliases that will be invoked when used from a child interpreter.
#
# See the safe.n man page for details.
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright © 1996-1997 Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

#
# The implementation is based on namespaces. These naming conventions are
# followed:
# Private procs starts with uppercase.
# Public  procs are exported and starts with lowercase
#

# Needed utilities package
package require opt 0.4.8
package require opt 0.4.9

# Create the safe namespace
namespace eval ::safe {
    # Exported API:
    namespace export interpCreate interpInit interpConfigure interpDelete \
	interpAddToAccessPath interpFindInAccessPath setLogCmd
}
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
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







+
+
+
+


+
+

-
+



+
+
+
+





+
+

-
+







#
#  API entry points that needs argument parsing :
#
####

# Interface/entry point function and front end for "Create"
proc ::safe::interpCreate {args} {
    variable AutoPathSync
    if {$AutoPathSync} {
	set autoPath {}
    }
    set Args [::tcl::OptKeyParse ::safe::interpCreate $args]
    RejectExcessColons $child

    set withAutoPath [::tcl::OptProcArgGiven -autoPath]
    InterpCreate $child $accessPath \
	[InterpStatics] [InterpNested] $deleteHook
	[InterpStatics] [InterpNested] $deleteHook $autoPath $withAutoPath
}

proc ::safe::interpInit {args} {
    variable AutoPathSync
    if {$AutoPathSync} {
	set autoPath {}
    }
    set Args [::tcl::OptKeyParse ::safe::interpIC $args]
    if {![::interp exists $child]} {
	return -code error "\"$child\" is not an interpreter"
    }
    RejectExcessColons $child

    set withAutoPath [::tcl::OptProcArgGiven -autoPath]
    InterpInit $child $accessPath \
	[InterpStatics] [InterpNested] $deleteHook
	[InterpStatics] [InterpNested] $deleteHook $autoPath $withAutoPath
}

# Check that the given child is "one of us"
proc ::safe::CheckInterp {child} {
    namespace upvar ::safe [VarName $child] state
    if {![info exists state] || ![::interp exists $child]} {
	return -code error \
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
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







+










-
+



-
+
+
+
+
+
+








# This is even more complicated by the boolean flags with no values that
# we had the bad idea to support for the sake of user simplicity in
# create/init but which makes life hard in configure...
# So this will be hopefully written and some integrated with opt1.0
# (hopefully for tcl9.0 ?)
proc ::safe::interpConfigure {args} {
    variable AutoPathSync
    switch [llength $args] {
	1 {
	    # If we have exactly 1 argument the semantic is to return all
	    # the current configuration. We still call OptKeyParse though
	    # we know that "child" is our given argument because it also
	    # checks for the "-help" option.
	    set Args [::tcl::OptKeyParse ::safe::interpIC $args]
	    CheckInterp $child
	    namespace upvar ::safe [VarName $child] state

	    return [join [list \
	    set TMP [list \
		[list -accessPath $state(access_path)] \
		[list -statics    $state(staticsok)]   \
		[list -nested     $state(nestedok)]    \
	        [list -deleteHook $state(cleanupHook)]]]
		[list -deleteHook $state(cleanupHook)] \
	    ]
	    if {!$AutoPathSync} {
		lappend TMP [list -autoPath $state(auto_path)]
	    }
	    return [join $TMP]
	}
	2 {
	    # If we have exactly 2 arguments the semantic is a "configure
	    # get"
	    lassign $args child arg

	    # get the flag sub program (we 'know' about Opt's internal
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
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







+
+
+
+
+
+
+














-
+







	    namespace upvar ::safe [VarName $child] state

	    set item [::tcl::OptCurDesc $desc]
	    set name [::tcl::OptName $item]
	    switch -exact -- $name {
		-accessPath {
		    return [list -accessPath $state(access_path)]
		}
		-autoPath {
		    if {$AutoPathSync} {
			return -code error "unknown flag $name (bug)"
		    } else {
			return [list -autoPath $state(auto_path)]
		    }
		}
		-statics    {
		    return [list -statics $state(staticsok)]
		}
		-nested     {
		    return [list -nested $state(nestedok)]
		}
		-deleteHook {
		    return [list -deleteHook $state(cleanupHook)]
		}
		-noStatics {
		    # it is most probably a set in fact but we would need
		    # then to jump to the set part and it is not *sure*
		    # that it is a set action that the user want, so force
		    # it to use the unambigous -statics ?value? instead:
		    # it to use the unambiguous -statics ?value? instead:
		    return -code error\
			"ambigous query (get or set -noStatics ?)\
				use -statics instead"
		}
		-nestedLoadOk {
		    return -code error\
			"ambigous query (get or set -nestedLoadOk ?)\
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
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







+
+
+
+
+
+



















-
-
-
+
+
+
+
+







	    # not been given:
	    if {![::tcl::OptProcArgGiven -accessPath]} {
		set doreset 0
		set accessPath $state(access_path)
	    } else {
		set doreset 1
	    }
	    if {(!$AutoPathSync) && (![::tcl::OptProcArgGiven -autoPath])} {
		set autoPath $state(auto_path)
	    } elseif {$AutoPathSync} {
		set autoPath {}
	    } else {
	    }
	    if {
		![::tcl::OptProcArgGiven -statics]
		&& ![::tcl::OptProcArgGiven -noStatics]
	    } then {
		set statics    $state(staticsok)
	    } else {
		set statics    [InterpStatics]
	    }
	    if {
		[::tcl::OptProcArgGiven -nested] ||
		[::tcl::OptProcArgGiven -nestedLoadOk]
	    } then {
		set nested     [InterpNested]
	    } else {
		set nested     $state(nestedok)
	    }
	    if {![::tcl::OptProcArgGiven -deleteHook]} {
		set deleteHook $state(cleanupHook)
	    }
	    # we can now reconfigure :
	    InterpSetConfig $child $accessPath $statics $nested $deleteHook
	    # auto_reset the child (to completly synch the new access_path)
	    # Now reconfigure
	    set withAutoPath [::tcl::OptProcArgGiven -autoPath]
	    InterpSetConfig $child $accessPath $statics $nested $deleteHook $autoPath $withAutoPath

	    # auto_reset the child (to completely sync the new access_path) tests safe-9.8 safe-9.9
	    if {$doreset} {
		if {[catch {::interp eval $child {auto_reset}} msg]} {
		    Log $child "auto_reset failed: $msg"
		} else {
		    Log $child "successful auto_reset" NOTICE
		}

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
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







-
+
+


-
+









+
+













-
+




-
+





-
-
+
+
+
+
+
+

+







# {},...  {because the state array is stored as part of the name}
#
# Returns the child name.
#
# Optional Arguments :
# + child name : if empty, generated name will be used
# + access_path: path list controlling where load/source can occur,
#                if empty: the parent auto_path will be used.
#                if empty: the parent auto_path and its subdirectories will be
#                used.
# + staticsok  : flag, if 0 :no static package can be loaded (load {} Xxx)
#                      if 1 :static packages are ok.
# + nestedok: flag, if 0 :no loading to sub-sub interps (load xx xx sub)
# + nestedok   : flag, if 0 :no loading to sub-sub interps (load xx xx sub)
#                      if 1 : multiple levels are ok.

# use the full name and no indent so auto_mkIndex can find us
proc ::safe::InterpCreate {
			   child
			   access_path
			   staticsok
			   nestedok
			   deletehook
			   autoPath
			   withAutoPath
		       } {
    # Create the child.
    # If evaluated in ::safe, the interpreter command for foo is ::foo;
    # but for foo::bar is safe::foo::bar.  So evaluate in :: instead.
    if {$child ne ""} {
	namespace eval :: [list ::interp create -safe $child]
    } else {
	# empty argument: generate child name
	set child [::interp create -safe]
    }
    Log $child "Created" NOTICE

    # Initialize it. (returns child name)
    InterpInit $child $access_path $staticsok $nestedok $deletehook
    InterpInit $child $access_path $staticsok $nestedok $deletehook $autoPath $withAutoPath
}

#
# InterpSetConfig (was setAccessPath) :
#    Sets up child virtual auto_path and corresponding structure within
#    Sets up child virtual access path and corresponding structure within
#    the parent. Also sets the tcl_library in the child to be the first
#    directory in the path.
#    NB: If you change the path after the child has been initialized you
#    probably need to call "auto_reset" in the child in order that it gets
#    the right auto_index() array values.

proc ::safe::InterpSetConfig {child access_path staticsok nestedok deletehook} {
#
#    It is the caller's responsibility, if it supplies a non-empty value for
#    access_path, to make the first directory in the path suitable for use as
#    tcl_library, and (if ![setSyncMode]), to set the child's ::auto_path.

proc ::safe::InterpSetConfig {child access_path staticsok nestedok deletehook autoPath withAutoPath} {
    global auto_path
    variable AutoPathSync

    # determine and store the access path if empty
    if {$access_path eq ""} {
	set access_path $auto_path

	# Make sure that tcl_library is in auto_path and at the first
	# position (needed by setAccessPath)
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
366
367
368














369
370
371
372
373
374
375
376
377
378
379

380
381
382
383
384
385
386
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
442
443

444
445
446
447
448
449
450
451







+
+
-
+



+
+
+
+
+
+




+
+
+









-
















+
+
+
+
+
+
+
+
+
+
+
+
+
+










-
+







	    set access_path [linsert \
				 [lreplace $access_path $where $where] \
				 0 [info library]]
	    Log $child "tcl_libray was not in first in auto_path,\
			moved it to front of child's access_path" NOTICE
	}

	set raw_auto_path $access_path

	# Add 1st level sub dirs (will searched by auto loading from tcl
	# Add 1st level subdirs (will searched by auto loading from tcl
	# code in the child using glob and thus fail, so we add them here
	# so by default it works the same).
	set access_path [AddSubDirs $access_path]
    } else {
	set raw_auto_path $autoPath
    }

    if {$withAutoPath} {
	set raw_auto_path $autoPath
    }

    Log $child "Setting accessPath=($access_path) staticsok=$staticsok\
		nestedok=$nestedok deletehook=($deletehook)" NOTICE
    if {!$AutoPathSync} {
	Log $child "Setting auto_path=($raw_auto_path)" NOTICE
    }

    namespace upvar ::safe [VarName $child] state

    # clear old autopath if it existed
    # build new one
    # Extend the access list with the paths used to look for Tcl Modules.
    # We save the virtual form separately as well, as syncing it with the
    # child has to be defered until the necessary commands are present for
    # setup.

    set norm_access_path  {}
    set child_access_path {}
    set map_access_path   {}
    set remap_access_path {}
    set child_tm_path     {}

    set i 0
    foreach dir $access_path {
	set token [PathToken $i]
	lappend child_access_path  $token
	lappend map_access_path    $token $dir
	lappend remap_access_path  $dir $token
	lappend norm_access_path   [file normalize $dir]
	incr i
    }

    # Set the child auto_path to a tokenized raw_auto_path.
    # Silently ignore any directories that are not in the access path.
    # If [setSyncMode], SyncAccessPath will overwrite this value with the
    # full access path.
    # If ![setSyncMode], Safe Base code will not change this value.
    set tokens_auto_path {}
    foreach dir $raw_auto_path {
	if {[dict exists $remap_access_path $dir]} {
	    lappend tokens_auto_path [dict get $remap_access_path $dir]
	}
    }
    ::interp eval $child [list set auto_path $tokens_auto_path]

    # Add the tcl::tm directories to the access path.
    set morepaths [::tcl::tm::list]
    set firstpass 1
    while {[llength $morepaths]} {
	set addpaths $morepaths
	set morepaths {}

	foreach dir $addpaths {
	    # Prevent the addition of dirs on the tm list to the
	    # result if they are already known.
	    if {[dict exists $remap_access_path $dir]} {
	        if {$firstpass} {
		if {$firstpass} {
		    # $dir is in [::tcl::tm::list] and belongs in the child_tm_path.
		    # Later passes handle subdirectories, which belong in the
		    # access path but not in the module path.
		    lappend child_tm_path  [dict get $remap_access_path $dir]
		}
		continue
	    }
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
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







+
+
+
+





-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+


+
+










+







    set state(access_path,remap) $remap_access_path
    set state(access_path,norm)  $norm_access_path
    set state(access_path,child) $child_access_path
    set state(tm_path_child)     $child_tm_path
    set state(staticsok)         $staticsok
    set state(nestedok)          $nestedok
    set state(cleanupHook)       $deletehook

    if {!$AutoPathSync} {
	set state(auto_path)     $raw_auto_path
    }

    SyncAccessPath $child
    return
}

#

#
# DetokPath:
#    Convert tokens to directories where possible.
#    Leave undefined tokens unconverted.  They are
#    nonsense in both the child and the parent.
#
proc ::safe::DetokPath {child tokenPath} {
    namespace upvar ::safe [VarName $child] state

    set childPath {}
    foreach token $tokenPath {
	if {[dict exists $state(access_path,map) $token]} {
	    lappend childPath [dict get $state(access_path,map) $token]
	} else {
	    lappend childPath $token
	}
    }
    return $childPath
}

#
#
# FindInAccessPath:
# interpFindInAccessPath:
#    Search for a real directory and returns its virtual Id (including the
#    "$")
#
#    When debugging, use TranslatePath for the inverse operation.
proc ::safe::interpFindInAccessPath {child path} {
    CheckInterp $child
    namespace upvar ::safe [VarName $child] state

    if {![dict exists $state(access_path,remap) $path]} {
	return -code error "$path not found in access path"
    }

    return [dict get $state(access_path,remap) $path]
}


#
# addToAccessPath:
#    add (if needed) a real directory to access path and return its
#    virtual token (including the "$").
proc ::safe::interpAddToAccessPath {child path} {
    # first check if the directory is already in there
472
473
474
475
476
477
478


479
480
481

482
483
484
485
486
487
488
565
566
567
568
569
570
571
572
573
574
575

576
577
578
579
580
581
582
583







+
+


-
+







# into a preexisting safe interpreter.
proc ::safe::InterpInit {
			 child
			 access_path
			 staticsok
			 nestedok
			 deletehook
			 autoPath
			 withAutoPath
		     } {
    # Configure will generate an access_path when access_path is empty.
    InterpSetConfig $child $access_path $staticsok $nestedok $deletehook
    InterpSetConfig $child $access_path $staticsok $nestedok $deletehook $autoPath $withAutoPath

    # NB we need to add [namespace current], aliases are always absolute
    # paths.

    # These aliases let the child load files to define new commands
    # This alias lets the child use the encoding names, convertfrom,
    # convertto, and system, but not "encoding system <name>" to set the
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
615
616
617
618
619
620
621


622
623
624
625
626
627
628







-
-







    ::interp alias $child ::tcl::encoding::system {} \
	::safe::AliasEncodingSystem $child

    # Subcommands of info
    ::interp alias $child ::tcl::info::nameofexecutable {} \
	::safe::AliasExeName $child

    # The allowed child variables already have been set by Tcl_MakeSafe(3)

    # Source init.tcl and tm.tcl into the child, to get auto_load and
    # other procedures defined:

    if {[catch {::interp eval $child {
	source [file join $tcl_library init.tcl]
    }} msg opt]} {
	Log $child "can't source init.tcl ($msg)"
590
591
592
593
594
595
596
597
598
599



600
601
602
603

604
605
606
607
608
609
610
683
684
685
686
687
688
689



690
691
692
693
694
695

696
697
698
699
700
701
702
703







-
-
-
+
+
+



-
+








    # When an interpreter is deleted with [interp delete], any sub-interpreters
    # are deleted automatically, but this leaves behind their data in the Safe
    # Base. To clean up properly, we call safe::interpDelete recursively on each
    # Safe Base sub-interpreter, so each one is deleted cleanly and not by
    # the automatic mechanism built into [interp delete].
    foreach sub [interp children $child] {
        if {[info exists ::safe::[VarName [list $child $sub]]]} {
            ::safe::interpDelete [list $child $sub]
        }
	if {[info exists ::safe::[VarName [list $child $sub]]]} {
	    ::safe::interpDelete [list $child $sub]
	}
    }

    # If the child has a cleanup hook registered, call it.  Check the
    # existance because we might be called to delete an interp which has
    # existence because we might be called to delete an interp which has
    # not been registered with us at all

    if {[info exists state(cleanupHook)]} {
	set hook $state(cleanupHook)
	if {[llength $hook]} {
	    # remove the hook now, otherwise if the hook calls us somehow,
	    # we'll loop
630
631
632
633
634
635
636
637

638
639
640
641
642
643
644
723
724
725
726
727
728
729

730
731
732
733
734
735
736
737







-
+







	::interp delete $child
	Log $child "Deleted" NOTICE
    }

    return
}

# Set (or get) the logging mecanism
# Set (or get) the logging mechanism

proc ::safe::setLogCmd {args} {
    variable Log
    set la [llength $args]
    if {$la == 0} {
	return $Log
    } elseif {$la == 1} {
661
662
663
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
754
755
756
757
758
759
760


761
762
763
764
765
766
767
768
769

770
771



772
773
774
775
776

777
778
779
780
781
782
783
784
785
786
787
788
789







-
-
+
+


+



+
-
+

-
-
-
+
+
+
+

-
+




+







	}
    }
}

# ------------------- END OF PUBLIC METHODS ------------

#
# Sets the child auto_path to the parent recorded value.  Also sets
# tcl_library to the first token of the virtual path.
# Sets the child auto_path to its recorded access path.  Also sets
# tcl_library to the first token of the access path.
#
proc ::safe::SyncAccessPath {child} {
    variable AutoPathSync
    namespace upvar ::safe [VarName $child] state

    set child_access_path $state(access_path,child)
    if {$AutoPathSync} {
    ::interp eval $child [list set auto_path $child_access_path]
	::interp eval $child [list set auto_path $child_access_path]

    Log $child "auto_path in $child has been set to $child_access_path"\
	NOTICE

	Log $child "auto_path in $child has been set to $child_access_path"\
		NOTICE
    }

    # This code assumes that info library is the first element in the
    # list of auto_path's. See -> InterpSetConfig for the code which
    # list of access path's. See -> InterpSetConfig for the code which
    # ensures this condition.

    ::interp eval $child [list \
	      set tcl_library [lindex $child_access_path 0]]
    return
}

# Returns the virtual token for directory number N.
proc ::safe::PathToken {n} {
    # We need to have a ":" in the token string so [file join] on the
    # mac won't turn it into a relative path.
    return "\$p(:$n:)" ;# Form tested by case 7.2
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744

745
746
747
748
749
750
751
826
827
828
829
830
831
832



833
834
835
836
837
838
839
840
841
842
843
844
845
846







-
-
-






+







}

# AliasFileSubcommand handles selected subcommands of [file] in safe
# interpreters that are *almost* safe. In particular, it just acts to
# prevent discovery of what home directories exist.

proc ::safe::AliasFileSubcommand {child subcommand name} {
    if {[string match ~* $name]} {
	set name ./$name
    }
    tailcall ::interp invokehidden $child tcl:file:$subcommand $name
}

# AliasGlob is the target of the "glob" alias in safe interpreters.

proc ::safe::AliasGlob {child args} {
    variable AutoPathSync
    Log $child "GLOB ! $args" NOTICE
    set cmd {}
    set at 0
    array set got {
	-directory 0
	-nocomplain 0
	-join 0
785
786
787
788
789
790
791

792
793
794
795
796
797
798
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894







+







		set got($opt) 1
		set virtualdir [lindex $args [incr at]]
		incr at
	    }
	    -* {
		Log $child "Safe base rejecting glob option '$opt'"
		return -code error "Safe base rejecting glob option '$opt'"
		# unsafe/unnecessary options rejected: -path
	    }
	    default {
		break
	    }
	}
	if {$got(--)} break
    }
819
820
821
822
823
824
825
826

827
828
829
830
831
832
833
915
916
917
918
919
920
921

922
923
924
925
926
927
928
929







-
+







	# no results in this case, if it were allowed to proceed.  Instead,
	# return now and reduce the number of cases to be considered later.
	Log $child {option -directory must be supplied}
	if {$got(-nocomplain)} return
	return -code error "permission denied"
    }

    # Apply the -join semantics ourselves.
    # Apply the -join semantics ourselves (hence -join not copied to $cmd)
    if {$got(-join)} {
	set args [lreplace $args $at end [join [lrange $args $at end] "/"]]
    }

    # Process the pattern arguments.  If we've done a join there is only one
    # pattern argument.

976
977
978
979
980
981
982
983

984
985
986
987
988




989
990
991
992
993
994
995
1072
1073
1074
1075
1076
1077
1078

1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095







-
+





+
+
+
+







    # Passed all the tests, lets source it. Note that we do this all manually
    # because we want to control [info script] in the child so information
    # doesn't leak so much. [Bug 2913625]
    set old [::interp eval $child {info script}]
    set replacementMsg "script error"
    set code [catch {
	set f [open $realfile]
	fconfigure $f -encoding $encoding -eofchar \032
	fconfigure $f -encoding $encoding -eofchar \x1A
	set contents [read $f]
	close $f
	::interp eval $child [list info script $file]
    } msg opt]
    if {$code == 0} {
	# See [Bug 1d26e580cf]
	if {[string index $contents 0] eq "\uFEFF"} {
	    set contents [string range $contents 1 end]
	}
	set code [catch {::interp eval $child $contents} msg opt]
	set replacementMsg $msg
    }
    catch {interp eval $child [list info script $old]}
    # Note that all non-errors are fine result codes from [source], so we must
    # take a little care to do it properly. [Bug 2923613]
    if {$code == 1} {
1005
1006
1007
1008
1009
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
1105
1106
1107
1108
1109
1110
1111


1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124

1125
1126
1127
1128
1129
1130
1131



1132
1133
1134
1135
1136
1137
1138



1139
1140
1141
1142
1143
1144
1145
1146
1147
1148







-
-
+
+











-
+






-
-
-
+
+
+




-
-
-
+
+
+







    set argc [llength $args]
    if {$argc > 2} {
	set msg "load error: too many arguments"
	Log $child "$msg ($argc) {$file $args}"
	return -code error $msg
    }

    # package name (can be empty if file is not).
    set package [lindex $args 0]
    # prefix (can be empty if file is not).
    set prefix [lindex $args 0]

    namespace upvar ::safe [VarName $child] state

    # Determine where to load. load use a relative interp path and {}
    # means self, so we can directly and safely use passed arg.
    set target [lindex $args 1]
    if {$target ne ""} {
	# we will try to load into a sub sub interp; check that we want to
	# authorize that.
	if {!$state(nestedok)} {
	    Log $child "loading to a sub interp (nestedok)\
			disabled (trying to load $package to $target)"
			disabled (trying to load $prefix to $target)"
	    return -code error "permission denied (nested load)"
	}
    }

    # Determine what kind of load is requested
    if {$file eq ""} {
	# static package loading
	if {$package eq ""} {
	    set msg "load error: empty filename and no package name"
	# static loading
	if {$prefix eq ""} {
	    set msg "load error: empty filename and no prefix"
	    Log $child $msg
	    return -code error $msg
	}
	if {!$state(staticsok)} {
	    Log $child "static packages loading disabled\
			(trying to load $package to $target)"
	    return -code error "permission denied (static package)"
	    Log $child "static loading disabled\
			(trying to load $prefix to $target)"
	    return -code error "permission denied (static library)"
	}
    } else {
	# file loading

	# get the real path from the virtual one.
	try {
	    set file [TranslatePath $child $file]
1057
1058
1059
1060
1061
1062
1063
1064

1065
1066
1067


1068
1069
1070
1071
1072
1073
1074
1157
1158
1159
1160
1161
1162
1163

1164
1165


1166
1167
1168
1169
1170
1171
1172
1173
1174







-
+

-
-
+
+







	} on error msg {
	    Log $child $msg
	    return -code error "permission denied (path)"
	}
    }

    try {
	return [::interp invokehidden $child load $file $package $target]
	return [::interp invokehidden $child load $file $prefix $target]
    } on error msg {
	# Some packages return no error message.
	set msg0 "load of binary library for package $package failed"
	# Some libraries return no error message.
	set msg0 "load of library for prefix $prefix failed"
	if {$msg eq {}} {
	    set msg $msg0
	} else {
	    set msg "$msg0: $msg"
	}
	Log $child $msg
	return -code error $msg
1180
1181
1182
1183
1184
1185
1186
1187

1188
1189
1190
1191


1192
1193
1194

1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209

1210
1211
1212

1213
1214
1215
1216
1217
1218
1219





1220
1221
1222
1223
1224
1225
1226
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







-
+


-
-
+
+


-
+















+


-
+






-
+
+
+
+
+







#     becomes
#         namespace upvar ::safe [VarName $child] state
# ------------------------------------------------------------------------------

proc ::safe::RejectExcessColons {child} {
    set stripped [regsub -all -- {:::*} $child ::]
    if {[string range $stripped end-1 end] eq {::}} {
        return -code error {interpreter name must not end in "::"}
	return -code error {interpreter name must not end in "::"}
    }
    if {$stripped ne $child} {
        set msg {interpreter name has excess colons in namespace separators}
        return -code error $msg
	set msg {interpreter name has excess colons in namespace separators}
	return -code error $msg
    }
    if {[string range $stripped 0 1] eq {::}} {
        return -code error {interpreter name must not begin "::"}
	return -code error {interpreter name must not begin "::"}
    }
    return
}

proc ::safe::VarName {child} {
    # return S$child
    return S[string map {:: @N @ @A} $child]
}

proc ::safe::Setup {} {
    ####
    #
    # Setup the arguments parsing
    #
    ####
    variable AutoPathSync

    # Share the descriptions
    set temp [::tcl::OptKeyRegister {
    set OptList {
	{-accessPath -list {} "access path for the child"}
	{-noStatics "prevent loading of statically linked pkgs"}
	{-statics true "loading of statically linked pkgs"}
	{-nestedLoadOk "allow nested loading"}
	{-nested false "nested loading"}
	{-deleteHook -script {} "delete hook"}
    }]
    }
    if {!$AutoPathSync} {
	lappend OptList {-autoPath -list {} "::auto_path for the child"}
    }
    set temp [::tcl::OptKeyRegister $OptList]

    # create case (child is optional)
    ::tcl::OptKeyRegister {
	{?child? -name {} "name of the child (optional)"}
    } ::safe::interpCreate

    # adding the flags sub programs to the command program (relying on Opt's
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
1353
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405

1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

















+




+
+
+
+
+
+
+
+
+
+



    setLogCmd {}

    # Log eventually.
    # To enable error logging, set Log to {puts stderr} for instance,
    # via setLogCmd.
    return
}

# Accessor method for ::safe::AutoPathSync
# Usage: ::safe::setSyncMode ?newValue?
# Respond to changes by calling Setup again, preserving any
# caller-defined logging.  This allows complete equivalence with
# prior Safe Base behavior if AutoPathSync is true.
#
#                   >>> WARNING <<<
#
# DO NOT CHANGE AutoPathSync EXCEPT BY THIS COMMAND - IT IS VITAL THAT WHENEVER
# THE VALUE CHANGES, THE EXISTING PARSE TOKENS ARE DELETED AND Setup IS CALLED
# AGAIN.
# (The initialization of AutoPathSync at the end of this file is acceptable
#  because Setup has not yet been called.)

proc ::safe::setSyncMode {args} {
    variable AutoPathSync

    if {[llength $args] == 0} {
    } elseif {[llength $args] == 1} {
	set newValue [lindex $args 0]
	if {![string is boolean -strict $newValue]} {
	    return -code error "new value must be a valid boolean"
	}
	set args [expr {$newValue && $newValue}]
	if {([info vars ::safe::S*] ne {}) && ($args != $AutoPathSync)} {
	    return -code error \
		    "cannot set new value while Safe Base child interpreters exist"
	}
	if {($args != $AutoPathSync)} {
	    set AutoPathSync {*}$args
	    ::tcl::OptKeyDelete ::safe::interpCreate
	    ::tcl::OptKeyDelete ::safe::interpIC
	    set TmpLog [setLogCmd]
	    Setup
	    setLogCmd $TmpLog
	}
    } else {
	set msg {wrong # args: should be "safe::setSyncMode ?newValue?"}
	return -code error $msg
    }

    return $AutoPathSync
}

namespace eval ::safe {
    # internal variables
    # internal variables (must not begin with "S")

    # AutoPathSync
    #
    # Set AutoPathSync to 0 to give a child's ::auto_path the same meaning as
    # for an unsafe interpreter: the package command will search its directories
    # and first-level subdirectories for pkgIndex.tcl files; the auto-loader
    # will search its directories for tclIndex files.  The access path and
    # module path will be maintained as separate values, and ::auto_path will
    # not be updated when the user calls ::safe::interpAddToAccessPath to add to
    # the access path.  If the user specifies an access path when calling
    # interpCreate, interpInit or interpConfigure, it is the user's
    # responsibility to define the child's auto_path.  If these commands are
    # called with no (or empty) access path, the child's auto_path will be set
    # to a tokenized form of the parent's auto_path, and these directories and
    # their first-level subdirectories will be added to the access path.
    #
    # Set to 1 for "traditional" behavior: a child's entire access path and
    # module path are copied to its ::auto_path, which is updated whenever
    # the user calls ::safe::interpAddToAccessPath to add to the access path.
    variable AutoPathSync 0

    # Log command, set via 'setLogCmd'. Logging is disabled when empty.
    variable Log {}

    # The package maintains a state array per child interp under its
    # control. The name of this array is S<interp-name>. This array is
    # brought into scope where needed, using 'namespace upvar'. The S
    # prefix is used to avoid that a child interp called "Log" smashes
    # the "Log" variable.
    #
    # The array's elements are:
    #
    # access_path       : List of paths accessible to the child.
    # access_path,norm  : Ditto, in normalized form.
    # access_path,child : Ditto, as the path tokens as seen by the child.
    # access_path,map   : dict ( token -> path )
    # access_path,remap : dict ( path -> token )
    # auto_path         : List of paths requested by the caller as child's ::auto_path.
    # tm_path_child     : List of TM root directories, as tokens seen by the child.
    # staticsok         : Value of option -statics
    # nestedok          : Value of option -nested
    # cleanupHook       : Value of option -deleteHook
    #
    # In principle, the child can change its value of ::auto_path -
    # - a package might add a path (that is already in the access path) for
    #   access to tclIndex files;
    # - the script might remove some elements of the auto_path.
    # However, this is really the business of the parent, and the auto_path will
    # be reset whenever the token mapping changes (i.e. when option -accessPath is
    # used to change the access path).
    # -autoPath is now stored in the array and is no longer obtained from
    # the child.
}

::safe::Setup

Changes to library/tclIndex.

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
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
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
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





-



















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









+
+






+








+











+





-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+
-
-
+
-
-
-
-
# Tcl autoload index file, version 2.0
# -*- tcl -*-
# This file is generated by the "auto_mkindex" command
# and sourced to set up indexing information for one or
# more commands.  Typically each line is a command that
# sets an element in the auto_index array, where the
# element name is the name of a command and the value is
# a script that loads the command.

set auto_index(auto_reset) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(tcl_findLibrary) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(auto_mkindex) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(auto_mkindex_old) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::init) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::cleanup) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::mkindex) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::hook) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::childhook) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::command) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::commandInit) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::fullname) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::indexEntry) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::tcl::clock::Initialize) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::mcget) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::mcMerge) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::GetSystemLocale) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::EnterLocale) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::_hasRegistry) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::LoadWindowsDateTimeFormats) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::LocalizeFormat) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::GetSystemTimeZone) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::SetupTimeZone) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::GuessWindowsTimeZone) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::LoadTimeZoneFile) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::LoadZoneinfoFile) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::ReadZoneinfoFile) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::ParsePosixTimeZone) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::ProcessPosixTimeZone) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::DeterminePosixDSTTime) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::GetJulianDayFromEraYearDay) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::GetJulianDayFromEraYearMonthWeekDay) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::IsGregorianLeapYear) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::WeekdayOnOrBefore) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::ChangeCurrentLocale) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::ClearCaches) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(foreachLine) [list ::tcl::Pkg::source [file join $dir foreachline.tcl]]
set auto_index(::tcl::history) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(history) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(::tcl::HistAdd) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(::tcl::HistKeep) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(::tcl::HistClear) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(::tcl::HistInfo) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(::tcl::HistRedo) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(::tcl::HistIndex) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(::tcl::HistEvent) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(::tcl::HistChange) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(::tcl::HistNextID) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(::tcl::Pkg::CompareExtension) [list ::tcl::Pkg::source [file join $dir package.tcl]]
set auto_index(pkg_mkIndex) [list ::tcl::Pkg::source [file join $dir package.tcl]]
set auto_index(tclPkgSetup) [list ::tcl::Pkg::source [file join $dir package.tcl]]
set auto_index(tclPkgUnknown) [list ::tcl::Pkg::source [file join $dir package.tcl]]
set auto_index(::tcl::MacOSXPkgUnknown) [list ::tcl::Pkg::source [file join $dir package.tcl]]
set auto_index(::pkg::create) [list ::tcl::Pkg::source [file join $dir package.tcl]]
set auto_index(parray) [list ::tcl::Pkg::source [file join $dir parray.tcl]]
set auto_index(readFile) [list ::tcl::Pkg::source [file join $dir readfile.tcl]]
set auto_index(::safe::InterpStatics) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::InterpNested) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::interpCreate) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::interpInit) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::CheckInterp) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::interpConfigure) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::InterpCreate) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::InterpSetConfig) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::DetokPath) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::interpFindInAccessPath) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::interpAddToAccessPath) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::InterpInit) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::AddSubDirs) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::interpDelete) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::setLogCmd) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::SyncAccessPath) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::PathToken) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::TranslatePath) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::Log) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::CheckFileName) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::AliasFileSubcommand) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::AliasGlob) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::AliasSource) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::AliasLoad) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::FileInAccessPath) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::DirInAccessPath) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::Subset) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::AliasSubset) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::AliasEncoding) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::BadSubcommand) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::AliasEncodingSystem) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::AliasExeName) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::RejectExcessColons) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::VarName) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::Setup) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::safe::setSyncMode) [list ::tcl::Pkg::source [file join $dir safe.tcl]]
set auto_index(::tcl::tm::path) [list ::tcl::Pkg::source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::add) [list ::tcl::Pkg::source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::remove) [list ::tcl::Pkg::source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::list) [list ::tcl::Pkg::source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::UnknownHandler) [list ::tcl::Pkg::source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::Defaults) [list ::tcl::Pkg::source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::roots) [list ::tcl::Pkg::source [file join $dir tm.tcl]]
set auto_index(::tcl::UpdateWordBreakREs) [list ::tcl::Pkg::source [file join $dir word.tcl]]
set auto_index(tcl_wordBreakAfter) [list ::tcl::Pkg::source [file join $dir word.tcl]]
set auto_index(tcl_wordBreakBefore) [list ::tcl::Pkg::source [file join $dir word.tcl]]
set auto_index(tcl_endOfWord) [list ::tcl::Pkg::source [file join $dir word.tcl]]
set auto_index(tcl_startOfNextWord) [list ::tcl::Pkg::source [file join $dir word.tcl]]
set auto_index(tcl_startOfPreviousWord) [list ::tcl::Pkg::source [file join $dir word.tcl]]
set auto_index(::tcl::tm::add) [list ::tcl::Pkg::source [file join $dir tm.tcl]]
set auto_index(writeFile) [list ::tcl::Pkg::source [file join $dir writefile.tcl]]
set auto_index(::tcl::tm::remove) [list ::tcl::Pkg::source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::list) [list ::tcl::Pkg::source [file join $dir tm.tcl]]
set auto_index(::tcl::unsupported::icu) [list ::tcl::Pkg::source [file join $dir icu.tcl]]
set auto_index(::tcl::tm::Defaults) [list ::tcl::Pkg::source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::UnknownHandler) [list ::tcl::Pkg::source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::roots) [list ::tcl::Pkg::source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::path) [list ::tcl::Pkg::source [file join $dir tm.tcl]]

Changes to library/tcltest/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
10
11
12

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.3 [list source [file join $dir tcltest.tcl]]
package ifneeded tcltest 2.5.9 [list source -encoding utf-8 [file join $dir tcltest.tcl]]

Changes to library/tcltest/tcltest.tcl.

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
30

31
32



33
34
35
36
37
38
39
40
41
42
43

44


45
46
47
48
49
50
51
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
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












-
-
-
+
+
+



-





-
+


-
+

-
+


+
+
+











+
-
+
+







# tcltest.tcl --
#
#	This file contains support code for the Tcl test suite.  It
#       defines the tcltest namespace and finds and defines the output
#       directory, constraints available, output and error channels,
#	etc. used by Tcl tests.  See the tcltest man page for more
#	details.
#
#       This design was based on the Tcl testing approach designed and
#       initially implemented by Mary Ann May-Pumphrey of Sun
#	Microsystems.
#
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2000 by Ajuba Solutions
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2000 Ajuba Solutions
# Contributions from Don Porter, NIST, 2002.  (not subject to US copyright)
# All rights reserved.

package require Tcl 8.5-		;# -verbose line uses [info frame]
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.3
    variable Version 2.5.9

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

    # Detect if we can use code points >= \U10000
    variable fullutf [package vsatisfies $version 8.7-]

##### Export the public tcltest procs; several categories
    #
    # Export the main functional commands that do useful things
    namespace export cleanupTests loadTestedCommands makeDirectory \
	makeFile removeDirectory removeFile runAllTests test

    # Export configuration commands that control the functional commands
    namespace export configure customMatch errorChannel interpreter \
	    outputChannel testConstraint

    # Export commands that are duplication (candidates for deprecation)
    if {![package vsatisfies [package provide Tcl] 9.0-]} {
    namespace export bytestring		;# dups [encoding convertfrom identity]
	namespace export bytestring	;# dups [encoding convertfrom identity]
    }
    namespace export debug		;#	[configure -debug]
    namespace export errorFile		;#	[configure -errfile]
    namespace export limitConstraints	;#	[configure -limitconstraints]
    namespace export loadFile		;#	[configure -loadfile]
    namespace export loadScript		;#	[configure -load]
    namespace export match		;#	[configure -match]
    namespace export matchFiles		;#	[configure -file]
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
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







-
+









-
+







	if {![file isdir $directory]} {
	    return -code error "\"$directory\" is not a directory"
	}
	return [AcceptReadable $directory]
    }

##### Initialize internal arrays of tcltest, but only if the caller
    # has not already pre-initialized them.  This is done to support
    # has not already preinitialized them.  This is done to support
    # compatibility with older tests that directly access internals
    # rather than go through command interfaces.
    #
    proc ArrayDefault {varName value} {
	variable $varName
	if {[array exists $varName]} {
	    return
	}
	if {[info exists $varName]} {
	    # Pre-initialized value is a scalar: destroy it!
	    # Preinitialized value is a scalar:  Destroy it!
	    unset $varName
	}
	array set $varName $value
    }

    # save the original environment so that it can be restored later
    ArrayDefault originalEnv [array get ::env]
190
191
192
193
194
195
196
197

198
199
200
201
202
203
204
194
195
196
197
198
199
200

201
202
203
204
205
206
207
208







-
+








    # initialize the testConstraints array to keep track of valid
    # predefined constraints (see the explanation for the
    # InitConstraints proc for more details).
    ArrayDefault testConstraints {}

##### Initialize internal variables of tcltest, but only if the caller
    # has not already pre-initialized them.  This is done to support
    # has not already preinitialized them.  This is done to support
    # compatibility with older tests that directly access internals
    # rather than go through command interfaces.
    #
    proc Default {varName value {verify AcceptAll}} {
	variable $varName
	if {![info exists $varName]} {
	    variable $varName [$verify $value]
223
224
225
226
227
228
229
230

231
232
233
234
235
236
237
227
228
229
230
231
232
233

234
235
236
237
238
239
240
241







-
+







    Default currentFailure false AcceptBoolean
    Default failFiles {} AcceptList

    # Tests should remove all files they create.  The test suite will
    # check the current working dir for files created by the tests.
    # filesMade keeps track of such files created using the makeFile and
    # makeDirectory procedures.  filesExisted stores the names of
    # pre-existing files.
    # preexisting files.
    #
    # Note that $filesExisted lists only those files that exist in
    # the original [temporaryDirectory].
    Default filesMade {} AcceptList
    Default filesExisted {} AcceptList
    proc FillFilesExisted {} {
	variable filesExisted
292
293
294
295
296
297
298
299

300
301
302
303
304
305
306
296
297
298
299
300
301
302

303
304
305
306
307
308
309
310







-
+







    # stdout and stderr buffers for use when we want to store them
    Default outData {}
    Default errData {}

    # keep track of test level for nested test commands
    variable testLevel 0

    # the variables and procs that existed when saveState was called are
    # the variables and procedures that existed when saveState was called are
    # stored in a variable of the same name
    Default saveState {}

    # Internationalization support -- used in [SetIso8859_1_Locale] and
    # [RestoreLocale]. Those commands are used in cmdIL.test.

    if {![info exists [namespace current]::isoLocale]} {
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
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







+









-
+




-
+








    variable ChannelsWeOpened; array set ChannelsWeOpened {}
    # output goes to stdout by default
    Default outputChannel stdout
    proc outputChannel { {filename ""} } {
	variable outputChannel
	variable ChannelsWeOpened
	variable fullutf

	# This is very subtle and tricky, so let me try to explain.
	# (Hopefully this longer comment will be clear when I come
	# back in a few months, unlike its predecessor :) )
	#
	# The [outputChannel] command (and underlying variable) have to
	# be kept in sync with the [configure -outfile] configuration
	# option ( and underlying variable Option(-outfile) ).  This is
	# accomplished with a write trace on Option(-outfile) that will
	# update [outputChannel] whenver a new value is written.  That
	# update [outputChannel] whenever a new value is written.  That
	# much is easy.
	#
	# The trick is that in order to maintain compatibility with
	# version 1 of tcltest, we must allow every configuration option
	# to get its inital value from command line arguments.  This is
	# to get its initial value from command line arguments.  This is
	# accomplished by setting initial read traces on all the
	# configuration options to parse the command line option the first
	# time they are read.  These traces are cancelled whenever the
	# program itself calls [configure].
	#
	# OK, then so to support tcltest 1 compatibility, it seems we want
	# to get the return from [outputFile] to trigger the read traces,
393
394
395
396
397
398
399



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







+
+
+







	switch -exact -- $filename {
	    stderr -
	    stdout {
		set outputChannel $filename
	    }
	    default {
		set outputChannel [open $filename a]
		if {$fullutf} {
		    fconfigure $outputChannel -profile tcl8 -encoding utf-8
		}
		set ChannelsWeOpened($outputChannel) 1

		# If we created the file in [temporaryDirectory], then
		# [cleanupTests] will delete it, unless we claim it was
		# already there.
		set outdir [normalizePath [file dirname \
			[file join [pwd] $filename]]]
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
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







+



















+
+
+







    }

    # errors go to stderr by default
    Default errorChannel stderr
    proc errorChannel { {filename ""} } {
	variable errorChannel
	variable ChannelsWeOpened
	variable fullutf

	# This is subtle and tricky.  See the comment above in
	# [outputChannel] for a detailed explanation.
	debug

	if {[llength [info level 0]] == 1} {
	    return $errorChannel
	}
	if {[info exists ChannelsWeOpened($errorChannel)]} {
	    close $errorChannel
	    unset ChannelsWeOpened($errorChannel)
	}
	switch -exact -- $filename {
	    stderr -
	    stdout {
		set errorChannel $filename
	    }
	    default {
		set errorChannel [open $filename a]
		if {$fullutf} {
		    fconfigure $errorChannel -profile tcl8 -encoding utf-8
		}
		set ChannelsWeOpened($errorChannel) 1

		# If we created the file in [temporaryDirectory], then
		# [cleanupTests] will delete it, unless we claim it was
		# already there.
		set outdir [normalizePath [file dirname \
			[file join [pwd] $filename]]]
470
471
472
473
474
475
476
477

478
479
480
481
482
483
484
482
483
484
485
486
487
488

489
490
491
492
493
494
495
496







-
+







    variable Usage; array set Usage {}

    # Verification commands for those options
    variable Verify; array set Verify {}

    # Initialize the default values of the configurable options that are
    # historically associated with an exported variable.  If that variable
    # is already set, support compatibility by accepting its pre-set value.
    # is already set, support compatibility by accepting its preset value.
    # Use [trace] to establish ongoing connection between the deprecated
    # exported variable and the modern option kept as a true internal var.
    # Also set up usage string and value testing for the option.
    proc Option {option value usage {verify AcceptAll} {varName {}}} {
	variable Option
	variable Verify
	variable Usage
499
500
501
502
503
504
505
506

507
508
509
510
511
512
513
511
512
513
514
515
516
517

518
519
520
521
522
523
524
525







-
+







		    return -code error $msg
		} else {
		    set Option($option) $msg
		}
		unset $varName
	    }
	    namespace eval [namespace current] \
	    	    [list upvar 0 Option($option) $varName]
		    [list upvar 0 Option($option) $varName]
	    # Workaround for Bug (now Feature Request) 572889.  Grrrr....
	    # Track all the variables tied to options
	    lappend OptionControlledVariables $varName
	    # Later, set auto-configure read traces on all
	    # of them, since a single trace on Option does not work.
	    proc $varName {{value {}}} [subst -nocommands {
		if {[llength [info level 0]] == 2} {
636
637
638
639
640
641
642
643

644
645
646
647
648
649
650
648
649
650
651
652
653
654

655
656
657
658
659
660
661
662







-
+







	    }
	}
	return $valid
    }

    proc IsVerbose {level} {
	variable Option
	return [expr {[lsearch -exact $Option(-verbose) $level] >= 0}]
	return [expr {$level in $Option(-verbose)}]
    }

    # Default verbosity is to show bodies of failed tests
    Option -verbose {body error} {
	Takes any combination of the values 'p', 's', 'b', 't', 'e' and 'l'.
	Test suite will display all passed tests if 'p' is specified, all
	skipped tests if 's' is specified, the bodies of failed tests if
749
750
751
752
753
754
755
756

757
758
759
760
761
762
763
761
762
763
764
765
766
767

768
769
770
771
772
773
774
775







-
+







	set directory [AcceptDirectory $directory]
	if {![file writable $directory]} {
	    if {[workingDirectory] eq $directory} {
		# Special exception: accept the default value
		# even if the directory is not writable
		return $directory
	    }
	    return -code error "\"$directory\" is not writeable"
	    return -code error "\"$directory\" is not writable"
	}
	return $directory
    }

    # Directory where files should be created
    Option -tmpdir [workingDirectory] {
	Save temporary files in the specified directory.
777
778
779
780
781
782
783


784
785



786
787
788
789
790
791
792
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809







+
+


+
+
+







    proc AcceptLoadFile { file } {
	if {$file eq {}} {return $file}
	set file [file join [temporaryDirectory] $file]
	return [AcceptReadable $file]
    }
    proc ReadLoadScript {args} {
	variable Option
	variable fullutf

	if {$Option(-loadfile) eq {}} {return}
	set tmp [open $Option(-loadfile) r]
	if {$fullutf} {
	    fconfigure $tmp -profile tcl8 -encoding utf-8
	}
	loadScript [read $tmp]
	close $tmp
    }
    Option -loadfile {} {
	Read the script to load the tested commands from the specified file.
    } AcceptLoadFile loadFile
    trace add variable Option(-loadfile) write [namespace code ReadLoadScript]
837
838
839
840
841
842
843
844

845
846
847
848
849
850
851
854
855
856
857
858
859
860

861
862
863
864
865
866
867
868







-
+







}

#####################################################################

# tcltest::Debug* --
#
#     Internal helper procedures to write out debug information
#     dependent on the chosen level. A test shell may overide
#     dependent on the chosen level. A test shell may override
#     them, f.e. to redirect the output into a different
#     channel, or even into a GUI.

# tcltest::DebugPuts --
#
#     Prints the specified string if the current debug level is
#     higher than the provided level argument.
1118
1119
1120
1121
1122
1123
1124































1125
1126
1127
1128
1129
1130
1131
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    if {$n2 eq {}} {return}
    if {![info exists testConstraints($n2)]} {
	if {[catch {testConstraint $n2 [eval [ConstraintInitializer $n2]]}]} {
	    testConstraint $n2 0
	}
    }
}

# tcltest::Asciify --
#
#       Transforms the passed string to contain only printable ascii characters.
#       Useful for printing to terminals. Non-printables are mapped to
#       \x, \u or \U sequences, except \n.
#
# Arguments:
#       s - string to transform
#
# Results:
#       The transformed strings
#
# Side effects:
#       None.

proc tcltest::Asciify {s} {
    set print ""
    foreach c [split $s ""] {
	if {(($c < "\x7F") && [string is print $c]) || ($c eq "\n")} {
	    append print $c
	} elseif {$c < "\u0100"} {
	    append print \\x[format %02X [scan $c %c]]
	} elseif {$c > "\uFFFF"} {
	    append print \\U[format %08X [scan $c %c]]
	} else {
	    append print \\u[format %04X [scan $c %c]]
	}
    }
    return $print
}

# tcltest::ConstraintInitializer --
#
#	Get or set a script that when evaluated in the tcltest namespace
#	will return a boolean value with which to initialize the
#	associated constraint.
#
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
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







-
+



-
+



-
+
+
+
+
+



-
+







    ConstraintInitializer pcCrash {expr {![testConstraint pc]}}
    ConstraintInitializer winCrash {expr {![testConstraint win]}}
    ConstraintInitializer macCrash {expr {![testConstraint mac]}}
    ConstraintInitializer unixCrash {expr {![testConstraint unix]}}

    # Skip empty tests

    ConstraintInitializer emptyTest {format 0}
    ConstraintInitializer emptyTest {expr 0}

    # By default, tests that expose known bugs are skipped.

    ConstraintInitializer knownBug {format 0}
    ConstraintInitializer knownBug {expr 0}

    # By default, non-portable tests are skipped.

    ConstraintInitializer nonPortable {format 0}
    ConstraintInitializer nonPortable {expr 0}

    # By default, extremely slow, extensive or IO-aggressive tests are skipped.

    ConstraintInitializer extensive {expr 0}

    # Some tests require user interaction.

    ConstraintInitializer userInteraction {format 0}
    ConstraintInitializer userInteraction {expr 0}

    # Some tests must be skipped if the interpreter is not in
    # interactive mode

    ConstraintInitializer interactive \
	    {expr {[info exists ::tcl_interactive] && $::tcl_interactive}}

1265
1266
1267
1268
1269
1270
1271
1272

1273
1274
1275
1276
1277
1278
1279
1317
1318
1319
1320
1321
1322
1323

1324
1325
1326
1327
1328
1329
1330
1331







-
+







    ConstraintInitializer notRoot {expr {![testConstraint root]}}

    # Set nonBlockFiles constraint: 1 means this platform supports
    # setting files into nonblocking mode.

    ConstraintInitializer nonBlockFiles {
	    set code [expr {[catch {set f [open defs r]}]
		    || [catch {chan configure $f -blocking off}]}]
		    || [catch {fconfigure $f -blocking off}]}]
	    catch {close $f}
	    set code
    }

    # Set asyncPipeClose constraint: 1 means this platform supports
    # async flush and async close on a pipe.
    #
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
1343
1344
1345
1346
1347
1348
1349

1350
1351


1352
1353
1354


1355
1356
1357

1358
1359












1360
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
1387
1388
1389
1390
1391
1392
1393
1394







-
+

-
-
+
+

-
-
+
+

-
+

-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
+


-
+




+
+


+
+
+







    ConstraintInitializer eformat {string equal [format %g 5e-5] 5e-05}

    # Test to see if execed commands such as cat, echo, rm and so forth
    # are present on this machine.

    ConstraintInitializer unixExecs {
	set code 1
        if {$::tcl_platform(platform) eq "macintosh"} {
	if {$::tcl_platform(platform) eq "macintosh"} {
	    set code 0
        }
        if {$::tcl_platform(platform) eq "windows"} {
	}
	if {$::tcl_platform(platform) eq "windows"} {
	    if {[catch {
	        set file _tcl_test_remove_me.txt
	        makeFile {hello} $file
		set file _tcl_test_remove_me.txt
		makeFile {hello} $file
	    }]} {
	        set code 0
		set code 0
	    } elseif {
	        [catch {exec cat $file}] ||
	        [catch {exec echo hello}] ||
	        [catch {exec sh -c echo hello}] ||
	        [catch {exec wc $file}] ||
	        [catch {exec sleep 1}] ||
	        [catch {exec echo abc > $file}] ||
	        [catch {exec chmod 644 $file}] ||
	        [catch {exec rm $file}] ||
	        [llength [auto_execok mkdir]] == 0 ||
	        [llength [auto_execok fgrep]] == 0 ||
	        [llength [auto_execok grep]] == 0 ||
	        [llength [auto_execok ps]] == 0
		[catch {exec cat $file}] ||
		[catch {exec echo hello}] ||
		[catch {exec sh -c echo hello}] ||
		[catch {exec wc $file}] ||
		[catch {exec sleep 1}] ||
		[catch {exec echo abc > $file}] ||
		[catch {exec chmod 644 $file}] ||
		[catch {exec rm $file}] ||
		[llength [auto_execok mkdir]] == 0 ||
		[llength [auto_execok fgrep]] == 0 ||
		[llength [auto_execok grep]] == 0 ||
		[llength [auto_execok ps]] == 0
	    } {
	        set code 0
		set code 0
	    }
	    removeFile $file
        }
	}
	set code
    }

    ConstraintInitializer stdio {
	variable fullutf

	set code 0
	if {![catch {set f [open "|[list [interpreter]]" w]}]} {
	    if {$fullutf} {
		fconfigure $f -profile tcl8 -encoding utf-8
	    }
	    if {![catch {puts $f exit}]} {
		if {![catch {close $f}]} {
		    set code 1
		}
	    }
	}
	set code
1487
1488
1489
1490
1491
1492
1493
1494
1495


1496
1497
1498
1499
1500
1501
1502
1544
1545
1546
1547
1548
1549
1550


1551
1552
1553
1554
1555
1556
1557
1558
1559







-
-
+
+







		    "missing value for option [lindex $args 0]"
	    exit 1
	}
    }

    # Call the hook
    catch {
        array set flag $flagArray
        processCmdLineArgsHook [array get flag]
	array set flag $flagArray
	processCmdLineArgsHook [array get flag]
    }
    return
}

# tcltest::ProcessCmdLineArgs --
#
#       This procedure must be run after constraint initialization is
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
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







-
+











-
+







	1 {
	    # Only the string to be printed is specified
	    append outData [lindex $args 0]\n
	    return
	    # return [Puts [lindex $args 0]]
	}
	2 {
	    # Either -nonewline or channelId has been specified
	    # Either -nonewline or channel has been specified
	    if {[lindex $args 0] eq "-nonewline"} {
		append outData [lindex $args end]
		return
		# return [Puts -nonewline [lindex $args end]]
	    } else {
		set channel [lindex $args 0]
		set newline \n
	    }
	}
	3 {
	    if {[lindex $args 0] eq "-nonewline"} {
		# Both -nonewline and channelId are specified, unless
		# Both -nonewline and channel are specified, unless
		# it's an error.  -nonewline is supposed to be argv[0].
		set channel [lindex $args 1]
		set newline ""
	    }
	}
    }

1671
1672
1673
1674
1675
1676
1677
1678

1679
1680
1681
1682
1683
1684
1685
1728
1729
1730
1731
1732
1733
1734

1735
1736
1737
1738
1739
1740
1741
1742







-
+







#
# Side effects:
#	None.

proc tcltest::CompareStrings {actual expected mode} {
    variable CustomMatch
    if {![info exists CustomMatch($mode)]} {
        return -code error "No matching command registered for `-match $mode'"
	return -code error "No matching command registered for `-match $mode'"
    }
    set match [namespace eval :: $CustomMatch($mode) [list $expected $actual]]
    if {[catch {expr {$match && $match}} result]} {
	return -code error "Invalid result from `-match $mode' command: $result"
    }
    return $match
}
1740
1741
1742
1743
1744
1745
1746
1747

1748
1749
1750
1751
1752
1753
1754
1755
1756
1757


1758
1759

1760
1761

1762
1763
1764
1765



1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776










1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791














1792
1793
1794
1795
1796
1797
1798






1799
1800
1801
1802
1803
1804

1805
1806
1807
1808
1809
1810
1811
1797
1798
1799
1800
1801
1802
1803

1804
1805
1806
1807
1808
1809
1810
1811
1812


1813
1814
1815

1816
1817

1818
1819



1820
1821
1822
1823










1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834














1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849






1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860

1861
1862
1863
1864
1865
1866
1867
1868







-
+








-
-
+
+

-
+

-
+

-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+





-
+







#

proc tcltest::SubstArguments {argList} {

    # We need to split the argList up into tokens but cannot use list
    # operations as they throw away some significant quoting, and
    # [split] ignores braces as it should.  Therefore what we do is
    # gradually build up a string out of whitespace seperated strings.
    # gradually build up a string out of whitespace-separated strings.
    # We cannot use [split] to split the argList into whitespace
    # separated strings as it throws away the whitespace which maybe
    # important so we have to do it all by hand.

    set result {}
    set token ""

    while {[string length $argList]} {
        # Look for the next word containing a quote: " { }
        if {[regexp -indices {[^ \t\n]*[\"\{\}]+[^ \t\n]*} \
	# Look for the next word containing a quote: " { }
	if {[regexp -indices {[^ \t\n]*[\"\{\}]+[^ \t\n]*} \
		$argList all]} {
            # Get the text leading up to this word, but not including
	    # Get the text leading up to this word, but not including
	    # this word, from the argList.
            set text [string range $argList 0 \
	    set text [string range $argList 0 \
		    [expr {[lindex $all 0] - 1}]]
            # Get the word with the quote
            set word [string range $argList \
                    [lindex $all 0] [lindex $all 1]]
	    # Get the word with the quote
	    set word [string range $argList \
		    [lindex $all 0] [lindex $all 1]]

            # Remove all text up to and including the word from the
            # argList.
            set argList [string range $argList \
                    [expr {[lindex $all 1] + 1}] end]
        } else {
            # Take everything up to the end of the argList.
            set text $argList
            set word {}
            set argList {}
        }
	    # Remove all text up to and including the word from the
	    # argList.
	    set argList [string range $argList \
		    [expr {[lindex $all 1] + 1}] end]
	} else {
	    # Take everything up to the end of the argList.
	    set text $argList
	    set word {}
	    set argList {}
	}

        if {$token ne {}} {
            # If we saw a word with quote before, then there is a
            # multi-word token starting with that word.  In this case,
            # add the text and the current word to this token.
            append token $text $word
        } else {
            # Add the text to the result.  There is no need to parse
            # the text because it couldn't be a part of any multi-word
            # token.  Then start a new multi-word token with the word
            # because we need to pass this token to the Tcl parser to
            # check for balancing quotes
            append result $text
            set token $word
        }
	if {$token ne {}} {
	    # If we saw a word with quote before, then there is a
	    # multi-word token starting with that word.  In this case,
	    # add the text and the current word to this token.
	    append token $text $word
	} else {
	    # Add the text to the result.  There is no need to parse
	    # the text because it couldn't be a part of any multi-word
	    # token.  Then start a new multi-word token with the word
	    # because we need to pass this token to the Tcl parser to
	    # check for balancing quotes
	    append result $text
	    set token $word
	}

        if { [catch {llength $token} length] == 0 && $length == 1} {
            # The token is a valid list so add it to the result.
            # lappend result [string trim $token]
            append result \{$token\}
            set token {}
        }
	if { [catch {llength $token} length] == 0 && $length == 1} {
	    # The token is a valid list so add it to the result.
	    # lappend result [string trim $token]
	    append result \{$token\}
	    set token {}
	}
    }

    # If the last token has not been added to the list then there
    # is a problem.
    if { [string length $token] } {
        error "incomplete token \"$token\""
	error "incomplete token \"$token\""
    }

    return $result
}


# tcltest::test --
1847
1848
1849
1850
1851
1852
1853
1854

1855
1856
1857
1858
1859
1860

1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872


1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885

1886
1887
1888
1889
1890
1891
1892
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







-
+





-
+












+
+












-
+







#   setup -             Code to run before $script (above).  This
#                       attribute is optional; default is {}.
#   cleanup -           Code to run after $script (above).  This
#                       attribute is optional; default is {}.
#   match -             specifies type of matching to do on result,
#                       output, errorOutput; this must be a string
#			previously registered by a call to [customMatch].
#			The strings exact, glob, and regexp are pre-registered
#			The strings exact, glob, and regexp are preregistered
#			by the tcltest package.  Default value is exact.
#
# Arguments:
#   name -		Name of test, in the form foo-1.2.
#   description -	Short textual description of the test, to
#  		  	help humans understand what it does.
#			help humans understand what it does.
#
# Results:
#	None.
#
# Side effects:
#       Just about anything is possible depending on the test.
#

proc tcltest::test {name description args} {
    global tcl_platform
    variable testLevel
    variable coreModTime
    variable fullutf

    DebugPuts 3 "test $name $args"
    DebugDo 1 {
	variable TestNames
	catch {
	    puts "test name '$name' re-used; prior use in $TestNames($name)"
	}
	set TestNames($name) [info script]
    }

    FillFilesExisted
    incr testLevel

    # Pre-define everything to null except output and errorOutput.  We
    # Predefine everything to null except output and errorOutput.  We
    # determine whether or not to trap output based on whether or not
    # these variables (output & errorOutput) are defined.
    lassign {} constraints setup cleanup body result returnCodes errorCode match

    # Set the default match mode
    set match exact

1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956




1957
1958
1959
1960
1961
1962
1963
2005
2006
2007
2008
2009
2010
2011




2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022







-
-
-
-
+
+
+
+







		    must be $values"
	}

	# Replace symbolic valies supplied for -returnCodes
	foreach {strcode numcode} {ok 0 normal 0 error 1 return 2 break 3 continue 4} {
	    set returnCodes [string map -nocase [list $strcode $numcode] $returnCodes]
	}
        # errorCode without returnCode 1 is meaningless
        if {$errorCode ne "*" && 1 ni $returnCodes} {
            set returnCodes 1
        }
	# errorCode without returnCode 1 is meaningless
	if {$errorCode ne "*" && 1 ni $returnCodes} {
	    set returnCodes 1
	}
    } else {
	# This is parsing for the old test command format; it is here
	# for backward compatibility.
	set result [lindex $args end]
	if {[llength $args] == 2} {
	    set body [lindex $args 0]
	} elseif {[llength $args] == 3} {
2032
2033
2034
2035
2036
2037
2038
2039

2040
2041
2042
2043
2044
2045
2046
2091
2092
2093
2094
2095
2096
2097

2098
2099
2100
2101
2102
2103
2104
2105







-
+







    # check if the return code matched the expected return code
    set codeFailure 0
    if {$processTest && !$setupFailure && ($returnCode ni $returnCodes)} {
	set codeFailure 1
    }
    set errorCodeFailure 0
    if {$processTest && !$setupFailure && !$codeFailure && $returnCode == 1 && \
                ![string match $errorCode $errorCodeRes(body)]} {
	    ![string match $errorCode $errorCodeRes(body)]} {
	set errorCodeFailure 1
    }

    # If expected output/error strings exist, we have to compare
    # them.  If the comparison fails, then so did the test.
    set outputFailure 0
    variable outData
2065
2066
2067
2068
2069
2070
2071
2072

2073
2074
2075
2076
2077
2078
2079
2124
2125
2126
2127
2128
2129
2130

2131
2132
2133
2134
2135
2136
2137
2138







-
+







	    set errorFailure 1
	}
    }

    # check if the answer matched the expected answer
    # Only check if we ran the body of the test (no setup failure)
    if {!$processTest} {
    	set scriptFailure 0
	set scriptFailure 0
    } elseif {$setupFailure || $codeFailure} {
	set scriptFailure 0
    } elseif {[set scriptCompare [catch {
	CompareStrings $actualAnswer $result $match
    } scriptMatch]] == 0} {
	set scriptFailure [expr {!$scriptMatch}]
    } else {
2123
2124
2125
2126
2127
2128
2129
2130

2131
2132
2133
2134
2135
2136
2137
2182
2183
2184
2185
2186
2187
2188

2189
2190
2191
2192
2193
2194
2195
2196







-
+







	    }
	}
    }

    if {[IsVerbose msec] || [IsVerbose usec]} {
	set t [expr {[clock microseconds] - $timeStart}]
	if {[IsVerbose usec]} {
	    puts [outputChannel] "++++ $name took $t μs"
	    puts [outputChannel] "++++ $name took $t \xB5s"
	}
	if {[IsVerbose msec]} {
	    puts [outputChannel] "++++ $name took [expr {round($t/1000.)}] ms"
	}
    }

    # if skipped, it is safe to return here
2171
2172
2173
2174
2175
2176
2177



2178
2179
2180
2181
2182
2183
2184
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246







+
+
+







		[dict get $testFrame type] eq "source"} {
	    set testFile [dict get $testFrame file]
	    set testLine [dict get $testFrame line]
	} else {
	    set testFile [file normalize [uplevel 1 {info script}]]
	    if {[file readable $testFile]} {
		set testFd [open $testFile r]
		if {$fullutf} {
		    fconfigure $testFd -profile tcl8 -encoding utf-8
		}
		set testLine [expr {[lsearch -regexp \
			[split [read $testFd] "\n"] \
			"^\[ \t\]*test [string map {. \\.} $name] "] + 1}]
		close $testFd
	    }
	}
	if {[info exists testLine]} {
2200
2201
2202
2203
2204
2205
2206

2207




2208
2209

2210
2211
2212
2213
2214
2215
2216
2262
2263
2264
2265
2266
2267
2268
2269

2270
2271
2272
2273
2274

2275
2276
2277
2278
2279
2280
2281
2282







+
-
+
+
+
+

-
+







	    puts [outputChannel] "---- errorCode(setup): $errorCodeRes(setup)"
	}
    }
    if {$processTest && $scriptFailure} {
	if {$scriptCompare} {
	    puts [outputChannel] "---- Error testing result: $scriptMatch"
	} else {
	    if {[catch {
	    puts [outputChannel] "---- Result was:\n$actualAnswer"
		puts [outputChannel] "---- Result was:\n[Asciify $actualAnswer]"
	    } errMsg]} {
		puts [outputChannel] "\n---- Result was:\n<error printing result: $errMsg>"
	    }
	    puts [outputChannel] "---- Result should have been\
		    ($match matching):\n$result"
		    ($match matching):\n[Asciify $result]"
	}
    }
    if {$errorCodeFailure} {
	puts [outputChannel] "---- Error code was: '$errorCodeRes(body)'"
	puts [outputChannel] "---- Error code should have been: '$errorCode'"
    }
    if {$codeFailure} {
2344
2345
2346
2347
2348
2349
2350

2351
2352
2353
2354
2355
2356
2357
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424







+







	    return 1
	}
    } else {
	# "constraints" argument exists;
	# make sure that the constraints are satisfied.

	set doTest 0
	set constraints [string trim $constraints]
	if {[string match {*[$\[]*} $constraints] != 0} {
	    # full expression, e.g. {$foo > [info tclversion]}
	    catch {set doTest [uplevel #0 [list expr $constraints]]}
	} elseif {[regexp {[^.:_a-zA-Z0-9 \n\r\t]+} $constraints] != 0} {
	    # something like {a || b} should be turned into
	    # $testConstraints(a) || $testConstraints(b).
	    regsub -all {[.\w]+} $constraints {$testConstraints(&)} c
2470
2471
2472
2473
2474
2475
2476
2477

2478
2479
2480
2481
2482
2483
2484
2537
2538
2539
2540
2541
2542
2543

2544
2545
2546
2547
2548
2549
2550
2551







-
+







    }

    # Call the cleanup hook
    cleanupTestsHook

    # Remove files and directories created by the makeFile and
    # makeDirectory procedures.  Record the names of files in
    # workingDirectory that were not pre-existing, and associate them
    # workingDirectory that were not preexisting, and associate them
    # with the test file that created them.

    if {!$calledFromAllFile} {
	foreach file $filesMade {
	    if {[file exists $file]} {
		DebugDo 1 {Warn "cleanupTests deleting $file..."}
		catch {file delete -force -- $file}
2561
2562
2563
2564
2565
2566
2567
2568

2569
2570
2571
2572
2573
2574
2575
2628
2629
2630
2631
2632
2633
2634

2635
2636
2637
2638
2639
2640
2641
2642







-
+







	}

	# exit only if running Tk in non-interactive mode
	# This should be changed to determine if an event
	# loop is running, which is the real issue.
	# Actually, this doesn't belong here at all.  A package
	# really has no business [exit]-ing an application.
	if {![catch {package present Tk}] && ![testConstraint interactive]} {
	if {[info exists ::tk_version] && ![testConstraint interactive]} {
	    exit
	}
    } else {

	# if we're deferring stat-reporting until all files are sourced,
	# then add current file to failFile list if any tests in this
	# file failed
2794
2795
2796
2797
2798
2799
2800

2801
2802
2803
2804
2805
2806
2807
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875







+








proc tcltest::runAllTests { {shell ""} } {
    variable testSingleFile
    variable numTestFiles
    variable numTests
    variable failFiles
    variable DefaultValue
    variable fullutf

    FillFilesExisted
    if {[llength [info level 0]] == 1} {
	set shell [interpreter]
    }

    set testSingleFile false
2851
2852
2853
2854
2855
2856
2857
2858

2859
2860
2861
2862
2863
2864
2865
2919
2920
2921
2922
2923
2924
2925

2926
2927
2928
2929
2930
2931
2932
2933







-
+







	set tail [file tail $file]
	puts [outputChannel] $tail
	flush [outputChannel]

	if {[singleProcess]} {
	    if {[catch {
		incr numTestFiles
		uplevel 1 [list ::source $file]
		uplevel 1 [list ::source -encoding utf-8 $file]
	    } msg]} {
		puts [outputChannel] "Test file error: $msg"
		# append the name of the test to a list to be reported
		# later
		lappend testFileFailures $file
	    }
	    if {$numTests(Failed) > 0} {
2879
2880
2881
2882
2883
2884
2885



2886
2887
2888
2889
2890
2891
2892
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963







+
+
+







		}
		lappend childargv $opt $value
	    }
	    set cmd [linsert $childargv 0 | $shell $file]
	    if {[catch {
		incr numTestFiles
		set pipeFd [open $cmd "r"]
		if {$fullutf} {
		    fconfigure $pipeFd -profile tcl8 -encoding utf-8
		}
		while {[gets $pipeFd line] >= 0} {
		    if {[regexp [join {
			    {^([^:]+):\t}
			    {Total\t([0-9]+)\t}
			    {Passed\t([0-9]+)\t}
			    {Skipped\t([0-9]+)\t}
			    {Failed\t([0-9]+)}
2933
2934
2935
2936
2937
2938
2939
2940

2941
2942
2943
2944
2945
2946
2947
3004
3005
3006
3007
3008
3009
3010

3011
3012
3013
3014
3015
3016
3017
3018







-
+








    # Checking for subdirectories in which to run tests
    foreach directory [GetMatchingDirectories [testsDirectory]] {
	set dir [file tail $directory]
	puts [outputChannel] [string repeat ~ 44]
	puts [outputChannel] "$dir test began at [eval $timeCmd]\n"

	uplevel 1 [list ::source [file join $directory all.tcl]]
	uplevel 1 [list ::source -encoding utf-8 [file join $directory all.tcl]]

	set endTime [eval $timeCmd]
	puts [outputChannel] "\n$dir test ended at $endTime"
	puts [outputChannel] ""
	puts [outputChannel] [string repeat ~ 44]
    }
    return [expr {[info exists testFileFailures] || [info exists failFilesSet]}]
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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154

3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165







+
+












-
+
+
+
+







#	absolute path to the file created
#
# Side effects:
#	None.

proc tcltest::makeFile {contents name {directory ""}} {
    variable filesMade
    variable fullutf

    FillFilesExisted

    if {[llength [info level 0]] == 3} {
	set directory [temporaryDirectory]
    }

    set fullName [file join $directory $name]

    DebugPuts 3 "[lindex [info level 0] 0]:\
	     putting ``$contents'' into $fullName"

    set fd [open $fullName w]
    chan configure $fd -translation lf
    fconfigure $fd -translation lf
    if {$fullutf} {
	fconfigure $fd -profile tcl8 -encoding utf-8
    }
    if {[string index $contents end] eq "\n"} {
	puts -nonewline $fd $contents
    } else {
	puts $fd $contents
    }
    close $fd

3218
3219
3220
3221
3222
3223
3224


3225
3226
3227
3228
3229
3230



3231
3232
3233
3234
3235
3236
3237
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318







+
+






+
+
+







# Results:
#	content of the named file
#
# Side effects:
#	None.

proc tcltest::viewFile {name {directory ""}} {
    variable fullutf

    FillFilesExisted
    if {[llength [info level 0]] == 2} {
	set directory [temporaryDirectory]
    }
    set fullName [file join $directory $name]
    set f [open $fullName]
    if {$fullutf} {
	fconfigure $f -profile tcl8 -encoding utf-8
    }
    set data [read -nonewline $f]
    close $f
    return $data
}

# tcltest::bytestring --
#
3245
3246
3247
3248
3249
3250
3251



3252
3253
3254
3255
3256
3257
3258
3259
3260

3261
3262



3263
3264
3265
3266
3267
3268
3269
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345


3346
3347
3348
3349
3350
3351
3352
3353
3354
3355







+
+
+









+
-
-
+
+
+







#    instance to confirm that "\xE0\0" in a Tcl script is stored
#    internally in UTF-8 as the sequence of bytes "\xC3\xA0\xC0\x80".
#
# Generally, it's a bad idea to examine the bytes in a Tcl string or to
# construct improperly formed strings in this manner, because it involves
# exposing that Tcl uses UTF-8 internally.
#
# This function doesn't work any more in Tcl 8.7, since the 'identity'
# is gone (TIP #345)
#
# Arguments:
#	string being converted
#
# Results:
#	result fom encoding
#
# Side effects:
#	None

if {![package vsatisfies [package provide Tcl] 9.0-]} {
proc tcltest::bytestring {string} {
    return [encoding convertfrom identity $string]
    proc tcltest::bytestring {string} {
	return [encoding convertfrom identity $string]
    }
}

# tcltest::OpenFiles --
#
#	used in io tests, uses testchannel
#
# Arguments:
3414
3415
3416
3417
3418
3419
3420
3421

3422
3423
3424
3425
3426
3427
3428
3429
3430

3431
3432
3433
3434
3435
3436
3437
3500
3501
3502
3503
3504
3505
3506

3507
3508
3509
3510
3511
3512
3513
3514
3515

3516
3517
3518
3519
3520
3521
3522
3523







-
+








-
+







	return 1
    }
    return 0
}

# Initialize the constraints and set up command line arguments
namespace eval tcltest {
    # Define initializers for all the built-in contraint definitions
    # Define initializers for all the built-in constraint definitions
    DefineConstraintInitializers

    # Set up the constraints in the testConstraints array to be lazily
    # initialized by a registered initializer, or by "false" if no
    # initializer is registered.
    trace add variable testConstraints read [namespace code SafeFetch]

    # Only initialize constraints at package load time if an
    # [initConstraintsHook] has been pre-defined.  This is only
    # [initConstraintsHook] has been predefined.  This is only
    # for compatibility support.  The modern way to add a custom
    # test constraint is to just call the [testConstraint] command
    # straight away, without all this "hook" nonsense.
    if {[namespace current] eq
	    [namespace qualifiers [namespace which initConstraintsHook]]} {
	InitConstraints
    } else {

Changes to library/tm.tcl.

18
19
20
21
22
23
24
25

26
27
28

29
30
31
32
33
34
35
18
19
20
21
22
23
24

25
26
27

28
29
30
31
32
33
34
35







-
+


-
+







#   [package require] something that wasn't there on the first scan.
#
#   Either
#   1) It is there now:  If we rescan, you get it; if not you don't.
#
#      This covers the possibility that the application asked for a package
#      late, and the package was actually added to the installation after the
#      application was started. It shoukld still be able to find it.
#      application was started. It should still be able to find it.
#
#   2) It still is not there: Either way, you don't get it, but the rescan
#      takes time. This is however an error case and we dont't care that much
#      takes time. This is however an error case and we don't care that much
#      about it
#
#   3) It was there the first time; but for some reason a "package forget" has
#      been run, and "package" doesn't know about it anymore.
#
#      This can be an indication that the application wishes to reload some
#      functionality. And should work as well.
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
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







-
+

-
+








-
+















-
-
+
+







#	args -	The paths to add/remove. Must not appear querying the
#		path with 'list'.
#
# Results
#	No result for subcommands 'add' and 'remove'. A list of paths for
#	'list'.
#
# Sideeffects
# Side effects
#	The subcommands 'add' and 'remove' manipulate the list of paths to
#	search for Tcl Modules. The subcommand 'list' has no sideeffects.
#	search for Tcl Modules. The subcommand 'list' has no side effects.

proc ::tcl::tm::add {args} {
    # PART OF THE ::tcl::tm::path ENSEMBLE
    #
    # The path is added at the head to the list of module paths.
    #
    # The command enforces the restriction that no path may be an ancestor
    # directory of any other path on the list. If the new path violates this
    # restriction an error wil be raised.
    # restriction an error will be raised.
    #
    # If the path is already present as is no error will be raised and no
    # action will be taken.

    variable paths

    # We use a copy of the path as source during validation, and extend it as
    # well. Because we not only have to detect if the new paths are bogus with
    # respect to the existing paths, but also between themselves. Otherwise we
    # can still add bogus paths, by specifying them in a single call. This
    # makes the use of the new paths simpler as well, a trivial assignment of
    # the collected paths to the official state var.

    set newpaths $paths
    foreach p $args {
	if {$p in $newpaths} {
	    # Ignore a path already on the list.
	if {($p eq "") || ($p in $newpaths)} {
	    # Ignore any path which is empty or already on the list.
	    continue
	}

	# Search for paths which are subdirectories of the new one. If there
	# are any then the new path violates the restriction about ancestors.

	set pos [lsearch -glob $newpaths ${p}/*]
162
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177
178

179
180
181
182
183
184
185
162
163
164
165
166
167
168

169
170
171
172
173
174
175
176
177

178
179
180
181
182
183
184
185







-
+








-
+







#	Unknown handler for Tcl Modules, i.e. packages in module form.
#
# Arguments
#	original	- Original [package unknown] procedure.
#	name		- Name of desired package.
#	version		- Version of desired package. Can be the
#			  empty string.
#	exact		- Either -exact or ommitted.
#	exact		- Either -exact or omitted.
#
#	Name, version, and exact are used to determine satisfaction. The
#	original is called iff no satisfaction was achieved. The name is also
#	used to compute the directory to target in the search.
#
# Results
#	None.
#
# Sideeffects
# Side effects
#	May populate the package ifneeded database with additional provide
#	scripts.

proc ::tcl::tm::UnknownHandler {original name args} {
    # Import the list of paths to search for packages in module form.
    # Import the pattern used to check package names in detail.

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
366
367
368
369
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
366
367







-
+





-
+









-
-
-
-
-




-
+

-
-
+
+
+
+
+
















-
+



-
+







#
# Arguments
#	None
#
# Results
#	None.
#
# Sideeffects
# Side effects
#	May add paths to the list of defaults.

proc ::tcl::tm::Defaults {} {
    global env tcl_platform

    regexp {^(\d+)\.(\d+)} [package provide Tcl] - major minor
    regexp {^(\d+)\.(\d+)} [package provide tcl] - major minor
    set exe [file normalize [info nameofexecutable]]

    # Note that we're using [::list], not [list] because [list] means
    # something other than [::list] in this namespace.
    roots [::list \
	    [file dirname [info library]] \
	    [file join [file dirname [file dirname $exe]] lib] \
	    ]

    if {$tcl_platform(platform) eq "windows"} {
	set sep ";"
    } else {
	set sep ":"
    }
    for {set n $minor} {$n >= 0} {incr n -1} {
	foreach ev [::list \
			TCL${major}.${n}_TM_PATH \
			TCL${major}_${n}_TM_PATH \
        ] {
	] {
	    if {![info exists env($ev)]} continue
	    foreach p [split $env($ev) $sep] {
		path add $p
	    foreach p [split $env($ev) $::tcl_platform(pathSeparator)] {
		# Paths relative to unresolvable home dirs are ignored
		if {![catch {file tildeexpand $p} expanded_path]} {
		    path add $expanded_path
		}
	    }
	}
    }
    return
}

# ::tcl::tm::roots --
#
#	Public API to the module path. See specification.
#
# Arguments
#	paths -	List of 'root' paths to derive search paths from.
#
# Results
#	No result.
#
# Sideeffects
# Side effects
#	Calls 'path add' to paths to the list of module search paths.

proc ::tcl::tm::roots {paths} {
    regexp {^(\d+)\.(\d+)} [package provide Tcl] - major minor
    regexp {^(\d+)\.(\d+)} [package provide tcl] - major minor
    foreach pa $paths {
	set p [file join $pa tcl$major]
	for {set n $minor} {$n >= 0} {incr n -1} {
	    set px [file join $p ${major}.${n}]
	    if {![interp issafe]} {set px [file normalize $px]}
	    path add $px
	}

Changes to library/tzdata/Africa/Accra.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
1
2
3


4
5


















































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Africa/Abidjan)]} {
    LoadTimeZoneFile Africa/Abidjan

set TZData(:Africa/Accra) {
}
set TZData(:Africa/Accra) $TZData(:Africa/Abidjan)
    {-9223372036854775808 -52 0 LMT}
    {-1640995148 0 0 GMT}
    {-1556841600 1200 1 GMT}
    {-1546388400 0 0 GMT}
    {-1525305600 1200 1 GMT}
    {-1514852400 0 0 GMT}
    {-1493769600 1200 1 GMT}
    {-1483316400 0 0 GMT}
    {-1462233600 1200 1 GMT}
    {-1451780400 0 0 GMT}
    {-1430611200 1200 1 GMT}
    {-1420158000 0 0 GMT}
    {-1399075200 1200 1 GMT}
    {-1388622000 0 0 GMT}
    {-1367539200 1200 1 GMT}
    {-1357086000 0 0 GMT}
    {-1336003200 1200 1 GMT}
    {-1325550000 0 0 GMT}
    {-1304380800 1200 1 GMT}
    {-1293927600 0 0 GMT}
    {-1272844800 1200 1 GMT}
    {-1262391600 0 0 GMT}
    {-1241308800 1200 1 GMT}
    {-1230855600 0 0 GMT}
    {-1209772800 1200 1 GMT}
    {-1199319600 0 0 GMT}
    {-1178150400 1200 1 GMT}
    {-1167697200 0 0 GMT}
    {-1146614400 1200 1 GMT}
    {-1136161200 0 0 GMT}
    {-1115078400 1200 1 GMT}
    {-1104625200 0 0 GMT}
    {-1083542400 1200 1 GMT}
    {-1073089200 0 0 GMT}
    {-1051920000 1200 1 GMT}
    {-1041466800 0 0 GMT}
    {-1020384000 1200 1 GMT}
    {-1009930800 0 0 GMT}
    {-988848000 1200 1 GMT}
    {-978394800 0 0 GMT}
    {-957312000 1200 1 GMT}
    {-946858800 0 0 GMT}
    {-925689600 1200 1 GMT}
    {-915236400 0 0 GMT}
    {-894153600 1200 1 GMT}
    {-883700400 0 0 GMT}
    {-862617600 1200 1 GMT}
    {-852164400 0 0 GMT}
}

Changes to library/tzdata/Africa/Bissau.

1
2
3
4
5

6
7
1
2
3
4

5
6
7




-
+


# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/Bissau) {
    {-9223372036854775808 -3740 0 LMT}
    {-1830380400 -3600 0 -01}
    {-1830380400 -3600 0 -0100}
    {157770000 0 0 GMT}
}

Changes to library/tzdata/Africa/Cairo.

125
126
127
128
129
130
131


























































































































































132
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

    {1281474000 7200 0 EET}
    {1284069600 10800 1 EEST}
    {1285880400 7200 0 EET}
    {1400191200 10800 1 EEST}
    {1403816400 7200 0 EET}
    {1406844000 10800 1 EEST}
    {1411678800 7200 0 EET}
    {1682632800 10800 1 EEST}
    {1698354000 7200 0 EET}
    {1714082400 10800 1 EEST}
    {1730408400 7200 0 EET}
    {1745532000 10800 1 EEST}
    {1761858000 7200 0 EET}
    {1776981600 10800 1 EEST}
    {1793307600 7200 0 EET}
    {1809036000 10800 1 EEST}
    {1824757200 7200 0 EET}
    {1840485600 10800 1 EEST}
    {1856206800 7200 0 EET}
    {1871935200 10800 1 EEST}
    {1887656400 7200 0 EET}
    {1903384800 10800 1 EEST}
    {1919710800 7200 0 EET}
    {1934834400 10800 1 EEST}
    {1951160400 7200 0 EET}
    {1966888800 10800 1 EEST}
    {1982610000 7200 0 EET}
    {1998338400 10800 1 EEST}
    {2014059600 7200 0 EET}
    {2029788000 10800 1 EEST}
    {2045509200 7200 0 EET}
    {2061237600 10800 1 EEST}
    {2076958800 7200 0 EET}
    {2092687200 10800 1 EEST}
    {2109013200 7200 0 EET}
    {2124136800 10800 1 EEST}
    {2140462800 7200 0 EET}
    {2156191200 10800 1 EEST}
    {2171912400 7200 0 EET}
    {2187640800 10800 1 EEST}
    {2203362000 7200 0 EET}
    {2219090400 10800 1 EEST}
    {2234811600 7200 0 EET}
    {2250540000 10800 1 EEST}
    {2266866000 7200 0 EET}
    {2281989600 10800 1 EEST}
    {2298315600 7200 0 EET}
    {2313439200 10800 1 EEST}
    {2329765200 7200 0 EET}
    {2345493600 10800 1 EEST}
    {2361214800 7200 0 EET}
    {2376943200 10800 1 EEST}
    {2392664400 7200 0 EET}
    {2408392800 10800 1 EEST}
    {2424114000 7200 0 EET}
    {2439842400 10800 1 EEST}
    {2456168400 7200 0 EET}
    {2471292000 10800 1 EEST}
    {2487618000 7200 0 EET}
    {2503346400 10800 1 EEST}
    {2519067600 7200 0 EET}
    {2534796000 10800 1 EEST}
    {2550517200 7200 0 EET}
    {2566245600 10800 1 EEST}
    {2581966800 7200 0 EET}
    {2597695200 10800 1 EEST}
    {2614021200 7200 0 EET}
    {2629144800 10800 1 EEST}
    {2645470800 7200 0 EET}
    {2660594400 10800 1 EEST}
    {2676920400 7200 0 EET}
    {2692648800 10800 1 EEST}
    {2708370000 7200 0 EET}
    {2724098400 10800 1 EEST}
    {2739819600 7200 0 EET}
    {2755548000 10800 1 EEST}
    {2771269200 7200 0 EET}
    {2786997600 10800 1 EEST}
    {2803323600 7200 0 EET}
    {2818447200 10800 1 EEST}
    {2834773200 7200 0 EET}
    {2850501600 10800 1 EEST}
    {2866222800 7200 0 EET}
    {2881951200 10800 1 EEST}
    {2897672400 7200 0 EET}
    {2913400800 10800 1 EEST}
    {2929122000 7200 0 EET}
    {2944850400 10800 1 EEST}
    {2960571600 7200 0 EET}
    {2976300000 10800 1 EEST}
    {2992626000 7200 0 EET}
    {3007749600 10800 1 EEST}
    {3024075600 7200 0 EET}
    {3039804000 10800 1 EEST}
    {3055525200 7200 0 EET}
    {3071253600 10800 1 EEST}
    {3086974800 7200 0 EET}
    {3102703200 10800 1 EEST}
    {3118424400 7200 0 EET}
    {3134152800 10800 1 EEST}
    {3150478800 7200 0 EET}
    {3165602400 10800 1 EEST}
    {3181928400 7200 0 EET}
    {3197052000 10800 1 EEST}
    {3213378000 7200 0 EET}
    {3229106400 10800 1 EEST}
    {3244827600 7200 0 EET}
    {3260556000 10800 1 EEST}
    {3276277200 7200 0 EET}
    {3292005600 10800 1 EEST}
    {3307726800 7200 0 EET}
    {3323455200 10800 1 EEST}
    {3339781200 7200 0 EET}
    {3354904800 10800 1 EEST}
    {3371230800 7200 0 EET}
    {3386959200 10800 1 EEST}
    {3402680400 7200 0 EET}
    {3418408800 10800 1 EEST}
    {3434130000 7200 0 EET}
    {3449858400 10800 1 EEST}
    {3465579600 7200 0 EET}
    {3481308000 10800 1 EEST}
    {3497634000 7200 0 EET}
    {3512757600 10800 1 EEST}
    {3529083600 7200 0 EET}
    {3544207200 10800 1 EEST}
    {3560533200 7200 0 EET}
    {3576261600 10800 1 EEST}
    {3591982800 7200 0 EET}
    {3607711200 10800 1 EEST}
    {3623432400 7200 0 EET}
    {3639160800 10800 1 EEST}
    {3654882000 7200 0 EET}
    {3670610400 10800 1 EEST}
    {3686936400 7200 0 EET}
    {3702060000 10800 1 EEST}
    {3718386000 7200 0 EET}
    {3734114400 10800 1 EEST}
    {3749835600 7200 0 EET}
    {3765564000 10800 1 EEST}
    {3781285200 7200 0 EET}
    {3797013600 10800 1 EEST}
    {3812734800 7200 0 EET}
    {3828463200 10800 1 EEST}
    {3844184400 7200 0 EET}
    {3859912800 10800 1 EEST}
    {3876238800 7200 0 EET}
    {3891362400 10800 1 EEST}
    {3907688400 7200 0 EET}
    {3923416800 10800 1 EEST}
    {3939138000 7200 0 EET}
    {3954866400 10800 1 EEST}
    {3970587600 7200 0 EET}
    {3986316000 10800 1 EEST}
    {4002037200 7200 0 EET}
    {4017765600 10800 1 EEST}
    {4034091600 7200 0 EET}
    {4049215200 10800 1 EEST}
    {4065541200 7200 0 EET}
    {4080664800 10800 1 EEST}
    {4096990800 7200 0 EET}
}

Changes to library/tzdata/Africa/Casablanca.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/Casablanca) {
    {-9223372036854775808 -1820 0 LMT}
    {-1773012580 0 0 +00}
    {-956361600 3600 1 +00}
    {-950490000 0 0 +00}
    {-942019200 3600 1 +00}
    {-761187600 0 0 +00}
    {-617241600 3600 1 +00}
    {-605149200 0 0 +00}
    {-81432000 3600 1 +00}
    {-71110800 0 0 +00}
    {141264000 3600 1 +00}
    {147222000 0 0 +00}
    {199756800 3600 1 +00}
    {207702000 0 0 +00}
    {231292800 3600 1 +00}
    {244249200 0 0 +00}
    {265507200 3600 1 +00}
    {271033200 0 0 +00}
    {448243200 3600 0 +01}
    {504918000 0 0 +00}
    {1212278400 3600 1 +00}
    {1220223600 0 0 +00}
    {1243814400 3600 1 +00}
    {1250809200 0 0 +00}
    {1272758400 3600 1 +00}
    {1281222000 0 0 +00}
    {1301788800 3600 1 +00}
    {1312066800 0 0 +00}
    {1335664800 3600 1 +00}
    {1342749600 0 0 +00}
    {1345428000 3600 1 +00}
    {1348970400 0 0 +00}
    {1367114400 3600 1 +00}
    {1373162400 0 0 +00}
    {1376100000 3600 1 +00}
    {1382839200 0 0 +00}
    {1396144800 3600 1 +00}
    {1403920800 0 0 +00}
    {1406944800 3600 1 +00}
    {1414288800 0 0 +00}
    {1427594400 3600 1 +00}
    {1434247200 0 0 +00}
    {1437271200 3600 1 +00}
    {1445738400 0 0 +00}
    {1459044000 3600 1 +00}
    {1465092000 0 0 +00}
    {1468116000 3600 1 +00}
    {1477792800 0 0 +00}
    {1490493600 3600 1 +00}
    {1495332000 0 0 +00}
    {1498960800 3600 1 +00}
    {1509242400 0 0 +00}
    {1521943200 3600 1 +00}
    {1526176800 0 0 +00}
    {1529200800 3600 1 +00}
    {1540695600 3600 0 +01}
    {1557021600 0 1 +01}
    {1560045600 3600 0 +01}
    {1587261600 0 1 +01}
    {1590890400 3600 0 +01}
    {1618106400 0 1 +01}
    {1621130400 3600 0 +01}
    {1648346400 0 1 +01}
    {1651975200 3600 0 +01}
    {1679191200 0 1 +01}
    {1682820000 3600 0 +01}
    {1710036000 0 1 +01}
    {1713060000 3600 0 +01}
    {1740276000 0 1 +01}
    {1743904800 3600 0 +01}
    {1771120800 0 1 +01}
    {1774144800 3600 0 +01}
    {1801965600 0 1 +01}
    {1804989600 3600 0 +01}
    {1832205600 0 1 +01}
    {1835834400 3600 0 +01}
    {1863050400 0 1 +01}
    {1866074400 3600 0 +01}
    {1893290400 0 1 +01}
    {1896919200 3600 0 +01}
    {1924135200 0 1 +01}
    {1927764000 3600 0 +01}
    {1954980000 0 1 +01}
    {1958004000 3600 0 +01}
    {1985220000 0 1 +01}
    {1988848800 3600 0 +01}
    {2016064800 0 1 +01}
    {2019088800 3600 0 +01}
    {2046304800 0 1 +01}
    {2049933600 3600 0 +01}
    {2077149600 0 1 +01}
    {2080778400 3600 0 +01}
    {2107994400 0 1 +01}
    {2111018400 3600 0 +01}
    {2138234400 0 1 +01}
    {2141863200 3600 0 +01}
    {2169079200 0 1 +01}
    {2172708000 3600 0 +01}
    {2199924000 0 1 +01}
    {2202948000 3600 0 +01}
    {2230164000 0 1 +01}
    {2233792800 3600 0 +01}
    {2261008800 0 1 +01}
    {2264032800 3600 0 +01}
    {2291248800 0 1 +01}
    {2294877600 3600 0 +01}
    {2322093600 0 1 +01}
    {2325722400 3600 0 +01}
    {2352938400 0 1 +01}
    {2355962400 3600 0 +01}
    {2383178400 0 1 +01}
    {2386807200 3600 0 +01}
    {2414023200 0 1 +01}
    {2417652000 3600 0 +01}
    {2444868000 0 1 +01}
    {2447892000 3600 0 +01}
    {2475108000 0 1 +01}
    {2478736800 3600 0 +01}
    {2505952800 0 1 +01}
    {2508976800 3600 0 +01}
    {2536192800 0 1 +01}
    {2539821600 3600 0 +01}
    {2567037600 0 1 +01}
    {2570666400 3600 0 +01}
    {2597882400 0 1 +01}
    {2600906400 3600 0 +01}
    {2628122400 0 1 +01}
    {2631751200 3600 0 +01}
    {2658967200 0 1 +01}
    {2662596000 3600 0 +01}
    {2689812000 0 1 +01}
    {2692836000 3600 0 +01}
    {2720052000 0 1 +01}
    {2723680800 3600 0 +01}
    {2750896800 0 1 +01}
    {2753920800 3600 0 +01}
    {2781136800 0 1 +01}
    {2784765600 3600 0 +01}
    {2811981600 0 1 +01}
    {2815610400 3600 0 +01}
    {2842826400 0 1 +01}
    {2845850400 3600 0 +01}
    {2873066400 0 1 +01}
    {2876695200 3600 0 +01}
    {2903911200 0 1 +01}
    {2907540000 3600 0 +01}
    {2934756000 0 1 +01}
    {2937780000 3600 0 +01}
    {2964996000 0 1 +01}
    {2968624800 3600 0 +01}
    {2995840800 0 1 +01}
    {2998864800 3600 0 +01}
    {3026080800 0 1 +01}
    {3029709600 3600 0 +01}
    {3056925600 0 1 +01}
    {3060554400 3600 0 +01}
    {3087770400 0 1 +01}
    {3090794400 3600 0 +01}
    {3118010400 0 1 +01}
    {3121639200 3600 0 +01}
    {3148855200 0 1 +01}
    {3152484000 3600 0 +01}
    {3179700000 0 1 +01}
    {3182724000 3600 0 +01}
    {3209940000 0 1 +01}
    {3213568800 3600 0 +01}
    {3240784800 0 1 +01}
    {3243808800 3600 0 +01}
    {3271024800 0 1 +01}
    {3274653600 3600 0 +01}
    {3301869600 0 1 +01}
    {3305498400 3600 0 +01}
    {3332714400 0 1 +01}
    {3335738400 3600 0 +01}
    {3362954400 0 1 +01}
    {3366583200 3600 0 +01}
    {3393799200 0 1 +01}
    {3397428000 3600 0 +01}
    {3424644000 0 1 +01}
    {3427668000 3600 0 +01}
    {3454884000 0 1 +01}
    {3458512800 3600 0 +01}
    {3485728800 0 1 +01}
    {3488752800 3600 0 +01}
    {3515968800 0 1 +01}
    {3519597600 3600 0 +01}
    {3546813600 0 1 +01}
    {3550442400 3600 0 +01}
    {3577658400 0 1 +01}
    {3580682400 3600 0 +01}
    {3607898400 0 1 +01}
    {3611527200 3600 0 +01}
    {3638743200 0 1 +01}
    {3642372000 3600 0 +01}
    {3669588000 0 1 +01}
    {3672612000 3600 0 +01}
    {3699828000 0 1 +01}
    {3703456800 3600 0 +01}
    {-1773012580 0 0 +0000}
    {-956361600 3600 1 +0100}
    {-950490000 0 0 +0000}
    {-942019200 3600 1 +0100}
    {-761187600 0 0 +0000}
    {-617241600 3600 1 +0100}
    {-605149200 0 0 +0000}
    {-81432000 3600 1 +0100}
    {-71110800 0 0 +0000}
    {141264000 3600 1 +0100}
    {147222000 0 0 +0000}
    {199756800 3600 1 +0100}
    {207702000 0 0 +0000}
    {231292800 3600 1 +0100}
    {244249200 0 0 +0000}
    {265507200 3600 1 +0100}
    {271033200 0 0 +0000}
    {448243200 3600 0 +0100}
    {504918000 0 0 +0000}
    {1212278400 3600 1 +0100}
    {1220223600 0 0 +0000}
    {1243814400 3600 1 +0100}
    {1250809200 0 0 +0000}
    {1272758400 3600 1 +0100}
    {1281222000 0 0 +0000}
    {1301788800 3600 1 +0100}
    {1312066800 0 0 +0000}
    {1335664800 3600 1 +0100}
    {1342749600 0 0 +0000}
    {1345428000 3600 1 +0100}
    {1348970400 0 0 +0000}
    {1367114400 3600 1 +0100}
    {1373162400 0 0 +0000}
    {1376100000 3600 1 +0100}
    {1382839200 0 0 +0000}
    {1396144800 3600 1 +0100}
    {1403920800 0 0 +0000}
    {1406944800 3600 1 +0100}
    {1414288800 0 0 +0000}
    {1427594400 3600 1 +0100}
    {1434247200 0 0 +0000}
    {1437271200 3600 1 +0100}
    {1445738400 0 0 +0000}
    {1459044000 3600 1 +0100}
    {1465092000 0 0 +0000}
    {1468116000 3600 1 +0100}
    {1477792800 0 0 +0000}
    {1490493600 3600 1 +0100}
    {1495332000 0 0 +0000}
    {1498960800 3600 1 +0100}
    {1509242400 0 0 +0000}
    {1521943200 3600 1 +0100}
    {1526176800 0 0 +0000}
    {1529200800 3600 1 +0100}
    {1540695600 3600 0 +0100}
    {1557021600 0 1 +0000}
    {1560045600 3600 0 +0100}
    {1587261600 0 1 +0000}
    {1590890400 3600 0 +0100}
    {1618106400 0 1 +0000}
    {1621130400 3600 0 +0100}
    {1648346400 0 1 +0000}
    {1651975200 3600 0 +0100}
    {1679191200 0 1 +0000}
    {1682215200 3600 0 +0100}
    {1710036000 0 1 +0000}
    {1713060000 3600 0 +0100}
    {1740276000 0 1 +0000}
    {1743904800 3600 0 +0100}
    {1771120800 0 1 +0000}
    {1774144800 3600 0 +0100}
    {1801965600 0 1 +0000}
    {1804989600 3600 0 +0100}
    {1832205600 0 1 +0000}
    {1835834400 3600 0 +0100}
    {1863050400 0 1 +0000}
    {1866074400 3600 0 +0100}
    {1893290400 0 1 +0000}
    {1896919200 3600 0 +0100}
    {1924135200 0 1 +0000}
    {1927159200 3600 0 +0100}
    {1954980000 0 1 +0000}
    {1958004000 3600 0 +0100}
    {1985220000 0 1 +0000}
    {1988848800 3600 0 +0100}
    {2016064800 0 1 +0000}
    {2019088800 3600 0 +0100}
    {2046304800 0 1 +0000}
    {2049933600 3600 0 +0100}
    {2077149600 0 1 +0000}
    {2080778400 3600 0 +0100}
    {2107994400 0 1 +0000}
    {2111018400 3600 0 +0100}
    {2138234400 0 1 +0000}
    {2141863200 3600 0 +0100}
    {2169079200 0 1 +0000}
    {2172103200 3600 0 +0100}
    {2199924000 0 1 +0000}
    {2202948000 3600 0 +0100}
    {2230164000 0 1 +0000}
    {2233792800 3600 0 +0100}
    {2261008800 0 1 +0000}
    {2264032800 3600 0 +0100}
    {2291248800 0 1 +0000}
    {2294877600 3600 0 +0100}
    {2322093600 0 1 +0000}
    {2325722400 3600 0 +0100}
    {2352938400 0 1 +0000}
    {2355962400 3600 0 +0100}
    {2383178400 0 1 +0000}
    {2386807200 3600 0 +0100}
    {2414023200 0 1 +0000}
    {2417047200 3600 0 +0100}
    {2444868000 0 1 +0000}
    {2447892000 3600 0 +0100}
    {2475108000 0 1 +0000}
    {2478736800 3600 0 +0100}
    {2505952800 0 1 +0000}
    {2508976800 3600 0 +0100}
    {2536192800 0 1 +0000}
    {2539821600 3600 0 +0100}
    {2567037600 0 1 +0000}
    {2570666400 3600 0 +0100}
    {2597882400 0 1 +0000}
    {2600906400 3600 0 +0100}
    {2628122400 0 1 +0000}
    {2631751200 3600 0 +0100}
    {2658967200 0 1 +0000}
    {2661991200 3600 0 +0100}
    {2689812000 0 1 +0000}
    {2692836000 3600 0 +0100}
    {2720052000 0 1 +0000}
    {2723680800 3600 0 +0100}
    {2750896800 0 1 +0000}
    {2753920800 3600 0 +0100}
    {2781136800 0 1 +0000}
    {2784765600 3600 0 +0100}
    {2811981600 0 1 +0000}
    {2815610400 3600 0 +0100}
    {2842826400 0 1 +0000}
    {2845850400 3600 0 +0100}
    {2873066400 0 1 +0000}
    {2876695200 3600 0 +0100}
    {2903911200 0 1 +0000}
    {2906935200 3600 0 +0100}
    {2934756000 0 1 +0000}
    {2937780000 3600 0 +0100}
    {2964996000 0 1 +0000}
    {2968624800 3600 0 +0100}
    {2995840800 0 1 +0000}
    {2998864800 3600 0 +0100}
    {3026080800 0 1 +0000}
    {3029709600 3600 0 +0100}
    {3056925600 0 1 +0000}
    {3060554400 3600 0 +0100}
    {3087770400 0 1 +0000}
    {3090794400 3600 0 +0100}
    {3118010400 0 1 +0000}
    {3121639200 3600 0 +0100}
    {3148855200 0 1 +0000}
    {3151879200 3600 0 +0100}
    {3179700000 0 1 +0000}
    {3182724000 3600 0 +0100}
    {3209940000 0 1 +0000}
    {3213568800 3600 0 +0100}
    {3240784800 0 1 +0000}
    {3243808800 3600 0 +0100}
    {3271024800 0 1 +0000}
    {3274653600 3600 0 +0100}
    {3301869600 0 1 +0000}
    {3305498400 3600 0 +0100}
    {3332714400 0 1 +0000}
    {3335738400 3600 0 +0100}
    {3362954400 0 1 +0000}
    {3366583200 3600 0 +0100}
    {3393799200 0 1 +0000}
    {3396823200 3600 0 +0100}
    {3424644000 0 1 +0000}
    {3427668000 3600 0 +0100}
    {3454884000 0 1 +0000}
    {3458512800 3600 0 +0100}
    {3485728800 0 1 +0000}
    {3488752800 3600 0 +0100}
    {3515968800 0 1 +0000}
    {3519597600 3600 0 +0100}
    {3546813600 0 1 +0000}
    {3549837600 3600 0 +0100}
    {3577658400 0 1 +0000}
    {3580682400 3600 0 +0100}
    {3607898400 0 1 +0000}
    {3611527200 3600 0 +0100}
    {3638743200 0 1 +0000}
    {3641767200 3600 0 +0100}
    {3669588000 0 1 +0000}
    {3672612000 3600 0 +0100}
    {3699828000 0 1 +0000}
    {3703456800 3600 0 +0100}
}

Changes to library/tzdata/Africa/El_Aaiun.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/El_Aaiun) {
    {-9223372036854775808 -3168 0 LMT}
    {-1136070432 -3600 0 -01}
    {198291600 0 0 +00}
    {199756800 3600 1 +00}
    {207702000 0 0 +00}
    {231292800 3600 1 +00}
    {244249200 0 0 +00}
    {265507200 3600 1 +00}
    {271033200 0 0 +00}
    {1212278400 3600 1 +00}
    {1220223600 0 0 +00}
    {1243814400 3600 1 +00}
    {1250809200 0 0 +00}
    {1272758400 3600 1 +00}
    {1281222000 0 0 +00}
    {1301788800 3600 1 +00}
    {1312066800 0 0 +00}
    {1335664800 3600 1 +00}
    {1342749600 0 0 +00}
    {1345428000 3600 1 +00}
    {1348970400 0 0 +00}
    {1367114400 3600 1 +00}
    {1373162400 0 0 +00}
    {1376100000 3600 1 +00}
    {1382839200 0 0 +00}
    {1396144800 3600 1 +00}
    {1403920800 0 0 +00}
    {1406944800 3600 1 +00}
    {1414288800 0 0 +00}
    {1427594400 3600 1 +00}
    {1434247200 0 0 +00}
    {1437271200 3600 1 +00}
    {1445738400 0 0 +00}
    {1459044000 3600 1 +00}
    {1465092000 0 0 +00}
    {1468116000 3600 1 +00}
    {1477792800 0 0 +00}
    {1490493600 3600 1 +00}
    {1495332000 0 0 +00}
    {1498960800 3600 1 +00}
    {1509242400 0 0 +00}
    {1521943200 3600 1 +00}
    {1526176800 0 0 +00}
    {1529200800 3600 1 +00}
    {1540695600 3600 0 +01}
    {1557021600 0 1 +01}
    {1560045600 3600 0 +01}
    {1587261600 0 1 +01}
    {1590890400 3600 0 +01}
    {1618106400 0 1 +01}
    {1621130400 3600 0 +01}
    {1648346400 0 1 +01}
    {1651975200 3600 0 +01}
    {1679191200 0 1 +01}
    {1682820000 3600 0 +01}
    {1710036000 0 1 +01}
    {1713060000 3600 0 +01}
    {1740276000 0 1 +01}
    {1743904800 3600 0 +01}
    {1771120800 0 1 +01}
    {1774144800 3600 0 +01}
    {1801965600 0 1 +01}
    {1804989600 3600 0 +01}
    {1832205600 0 1 +01}
    {1835834400 3600 0 +01}
    {1863050400 0 1 +01}
    {1866074400 3600 0 +01}
    {1893290400 0 1 +01}
    {1896919200 3600 0 +01}
    {-1136070432 -3600 0 -0100}
    {198291600 0 0 +0000}
    {199756800 3600 1 +0100}
    {207702000 0 0 +0000}
    {231292800 3600 1 +0100}
    {244249200 0 0 +0000}
    {265507200 3600 1 +0100}
    {271033200 0 0 +0000}
    {1212278400 3600 1 +0100}
    {1220223600 0 0 +0000}
    {1243814400 3600 1 +0100}
    {1250809200 0 0 +0000}
    {1272758400 3600 1 +0100}
    {1281222000 0 0 +0000}
    {1301788800 3600 1 +0100}
    {1312066800 0 0 +0000}
    {1335664800 3600 1 +0100}
    {1342749600 0 0 +0000}
    {1345428000 3600 1 +0100}
    {1348970400 0 0 +0000}
    {1367114400 3600 1 +0100}
    {1373162400 0 0 +0000}
    {1376100000 3600 1 +0100}
    {1382839200 0 0 +0000}
    {1396144800 3600 1 +0100}
    {1403920800 0 0 +0000}
    {1406944800 3600 1 +0100}
    {1414288800 0 0 +0000}
    {1427594400 3600 1 +0100}
    {1434247200 0 0 +0000}
    {1437271200 3600 1 +0100}
    {1445738400 0 0 +0000}
    {1459044000 3600 1 +0100}
    {1465092000 0 0 +0000}
    {1468116000 3600 1 +0100}
    {1477792800 0 0 +0000}
    {1490493600 3600 1 +0100}
    {1495332000 0 0 +0000}
    {1498960800 3600 1 +0100}
    {1509242400 0 0 +0000}
    {1521943200 3600 1 +0100}
    {1526176800 0 0 +0000}
    {1529200800 3600 1 +0100}
    {1540695600 3600 0 +0100}
    {1557021600 0 1 +0000}
    {1560045600 3600 0 +0100}
    {1587261600 0 1 +0000}
    {1590890400 3600 0 +0100}
    {1618106400 0 1 +0000}
    {1621130400 3600 0 +0100}
    {1648346400 0 1 +0000}
    {1651975200 3600 0 +0100}
    {1679191200 0 1 +0000}
    {1682215200 3600 0 +0100}
    {1710036000 0 1 +0000}
    {1713060000 3600 0 +0100}
    {1740276000 0 1 +0000}
    {1743904800 3600 0 +0100}
    {1771120800 0 1 +0000}
    {1774144800 3600 0 +0100}
    {1801965600 0 1 +0000}
    {1804989600 3600 0 +0100}
    {1832205600 0 1 +0000}
    {1835834400 3600 0 +0100}
    {1863050400 0 1 +0000}
    {1866074400 3600 0 +0100}
    {1893290400 0 1 +0000}
    {1896919200 3600 0 +0100}
    {1924135200 0 1 +0000}
    {1927159200 3600 0 +0100}
    {1924135200 0 1 +01}
    {1927764000 3600 0 +01}
    {1954980000 0 1 +01}
    {1958004000 3600 0 +01}
    {1985220000 0 1 +01}
    {1988848800 3600 0 +01}
    {2016064800 0 1 +01}
    {2019088800 3600 0 +01}
    {2046304800 0 1 +01}
    {2049933600 3600 0 +01}
    {2077149600 0 1 +01}
    {2080778400 3600 0 +01}
    {2107994400 0 1 +01}
    {2111018400 3600 0 +01}
    {2138234400 0 1 +01}
    {2141863200 3600 0 +01}
    {2169079200 0 1 +01}
    {2172708000 3600 0 +01}
    {2199924000 0 1 +01}
    {2202948000 3600 0 +01}
    {2230164000 0 1 +01}
    {2233792800 3600 0 +01}
    {2261008800 0 1 +01}
    {2264032800 3600 0 +01}
    {2291248800 0 1 +01}
    {2294877600 3600 0 +01}
    {2322093600 0 1 +01}
    {2325722400 3600 0 +01}
    {2352938400 0 1 +01}
    {2355962400 3600 0 +01}
    {2383178400 0 1 +01}
    {2386807200 3600 0 +01}
    {2414023200 0 1 +01}
    {2417652000 3600 0 +01}
    {2444868000 0 1 +01}
    {2447892000 3600 0 +01}
    {2475108000 0 1 +01}
    {2478736800 3600 0 +01}
    {2505952800 0 1 +01}
    {2508976800 3600 0 +01}
    {2536192800 0 1 +01}
    {2539821600 3600 0 +01}
    {2567037600 0 1 +01}
    {2570666400 3600 0 +01}
    {2597882400 0 1 +01}
    {2600906400 3600 0 +01}
    {2628122400 0 1 +01}
    {2631751200 3600 0 +01}
    {2658967200 0 1 +01}
    {2662596000 3600 0 +01}
    {2689812000 0 1 +01}
    {2692836000 3600 0 +01}
    {2720052000 0 1 +01}
    {2723680800 3600 0 +01}
    {2750896800 0 1 +01}
    {2753920800 3600 0 +01}
    {2781136800 0 1 +01}
    {2784765600 3600 0 +01}
    {2811981600 0 1 +01}
    {2815610400 3600 0 +01}
    {2842826400 0 1 +01}
    {2845850400 3600 0 +01}
    {2873066400 0 1 +01}
    {2876695200 3600 0 +01}
    {2903911200 0 1 +01}
    {2907540000 3600 0 +01}
    {2934756000 0 1 +01}
    {2937780000 3600 0 +01}
    {2964996000 0 1 +01}
    {2968624800 3600 0 +01}
    {2995840800 0 1 +01}
    {2998864800 3600 0 +01}
    {3026080800 0 1 +01}
    {3029709600 3600 0 +01}
    {3056925600 0 1 +01}
    {3060554400 3600 0 +01}
    {3087770400 0 1 +01}
    {3090794400 3600 0 +01}
    {3118010400 0 1 +01}
    {3121639200 3600 0 +01}
    {3148855200 0 1 +01}
    {3152484000 3600 0 +01}
    {3179700000 0 1 +01}
    {3182724000 3600 0 +01}
    {3209940000 0 1 +01}
    {3213568800 3600 0 +01}
    {3240784800 0 1 +01}
    {3243808800 3600 0 +01}
    {3271024800 0 1 +01}
    {3274653600 3600 0 +01}
    {3301869600 0 1 +01}
    {3305498400 3600 0 +01}
    {3332714400 0 1 +01}
    {3335738400 3600 0 +01}
    {3362954400 0 1 +01}
    {3366583200 3600 0 +01}
    {3393799200 0 1 +01}
    {3397428000 3600 0 +01}
    {3424644000 0 1 +01}
    {3427668000 3600 0 +01}
    {3454884000 0 1 +01}
    {3458512800 3600 0 +01}
    {3485728800 0 1 +01}
    {3488752800 3600 0 +01}
    {3515968800 0 1 +01}
    {3519597600 3600 0 +01}
    {3546813600 0 1 +01}
    {3550442400 3600 0 +01}
    {3577658400 0 1 +01}
    {3580682400 3600 0 +01}
    {3607898400 0 1 +01}
    {3611527200 3600 0 +01}
    {3638743200 0 1 +01}
    {3642372000 3600 0 +01}
    {3669588000 0 1 +01}
    {3672612000 3600 0 +01}
    {3699828000 0 1 +01}
    {3703456800 3600 0 +01}
    {1954980000 0 1 +0000}
    {1958004000 3600 0 +0100}
    {1985220000 0 1 +0000}
    {1988848800 3600 0 +0100}
    {2016064800 0 1 +0000}
    {2019088800 3600 0 +0100}
    {2046304800 0 1 +0000}
    {2049933600 3600 0 +0100}
    {2077149600 0 1 +0000}
    {2080778400 3600 0 +0100}
    {2107994400 0 1 +0000}
    {2111018400 3600 0 +0100}
    {2138234400 0 1 +0000}
    {2141863200 3600 0 +0100}
    {2169079200 0 1 +0000}
    {2172103200 3600 0 +0100}
    {2199924000 0 1 +0000}
    {2202948000 3600 0 +0100}
    {2230164000 0 1 +0000}
    {2233792800 3600 0 +0100}
    {2261008800 0 1 +0000}
    {2264032800 3600 0 +0100}
    {2291248800 0 1 +0000}
    {2294877600 3600 0 +0100}
    {2322093600 0 1 +0000}
    {2325722400 3600 0 +0100}
    {2352938400 0 1 +0000}
    {2355962400 3600 0 +0100}
    {2383178400 0 1 +0000}
    {2386807200 3600 0 +0100}
    {2414023200 0 1 +0000}
    {2417047200 3600 0 +0100}
    {2444868000 0 1 +0000}
    {2447892000 3600 0 +0100}
    {2475108000 0 1 +0000}
    {2478736800 3600 0 +0100}
    {2505952800 0 1 +0000}
    {2508976800 3600 0 +0100}
    {2536192800 0 1 +0000}
    {2539821600 3600 0 +0100}
    {2567037600 0 1 +0000}
    {2570666400 3600 0 +0100}
    {2597882400 0 1 +0000}
    {2600906400 3600 0 +0100}
    {2628122400 0 1 +0000}
    {2631751200 3600 0 +0100}
    {2658967200 0 1 +0000}
    {2661991200 3600 0 +0100}
    {2689812000 0 1 +0000}
    {2692836000 3600 0 +0100}
    {2720052000 0 1 +0000}
    {2723680800 3600 0 +0100}
    {2750896800 0 1 +0000}
    {2753920800 3600 0 +0100}
    {2781136800 0 1 +0000}
    {2784765600 3600 0 +0100}
    {2811981600 0 1 +0000}
    {2815610400 3600 0 +0100}
    {2842826400 0 1 +0000}
    {2845850400 3600 0 +0100}
    {2873066400 0 1 +0000}
    {2876695200 3600 0 +0100}
    {2903911200 0 1 +0000}
    {2906935200 3600 0 +0100}
    {2934756000 0 1 +0000}
    {2937780000 3600 0 +0100}
    {2964996000 0 1 +0000}
    {2968624800 3600 0 +0100}
    {2995840800 0 1 +0000}
    {2998864800 3600 0 +0100}
    {3026080800 0 1 +0000}
    {3029709600 3600 0 +0100}
    {3056925600 0 1 +0000}
    {3060554400 3600 0 +0100}
    {3087770400 0 1 +0000}
    {3090794400 3600 0 +0100}
    {3118010400 0 1 +0000}
    {3121639200 3600 0 +0100}
    {3148855200 0 1 +0000}
    {3151879200 3600 0 +0100}
    {3179700000 0 1 +0000}
    {3182724000 3600 0 +0100}
    {3209940000 0 1 +0000}
    {3213568800 3600 0 +0100}
    {3240784800 0 1 +0000}
    {3243808800 3600 0 +0100}
    {3271024800 0 1 +0000}
    {3274653600 3600 0 +0100}
    {3301869600 0 1 +0000}
    {3305498400 3600 0 +0100}
    {3332714400 0 1 +0000}
    {3335738400 3600 0 +0100}
    {3362954400 0 1 +0000}
    {3366583200 3600 0 +0100}
    {3393799200 0 1 +0000}
    {3396823200 3600 0 +0100}
    {3424644000 0 1 +0000}
    {3427668000 3600 0 +0100}
    {3454884000 0 1 +0000}
    {3458512800 3600 0 +0100}
    {3485728800 0 1 +0000}
    {3488752800 3600 0 +0100}
    {3515968800 0 1 +0000}
    {3519597600 3600 0 +0100}
    {3546813600 0 1 +0000}
    {3549837600 3600 0 +0100}
    {3577658400 0 1 +0000}
    {3580682400 3600 0 +0100}
    {3607898400 0 1 +0000}
    {3611527200 3600 0 +0100}
    {3638743200 0 1 +0000}
    {3641767200 3600 0 +0100}
    {3669588000 0 1 +0000}
    {3672612000 3600 0 +0100}
    {3699828000 0 1 +0000}
    {3703456800 3600 0 +0100}
}

Changes to library/tzdata/Africa/Juba.

32
33
34
35
36
37
38

39
32
33
34
35
36
37
38
39
40







+

    {419983200 10800 1 CAST}
    {435013200 7200 0 CAT}
    {452037600 10800 1 CAST}
    {466635600 7200 0 CAT}
    {483487200 10800 1 CAST}
    {498171600 7200 0 CAT}
    {947930400 10800 0 EAT}
    {1612126800 7200 0 CAT}
}

Changes to library/tzdata/Africa/Lagos.

1
2
3
4
5





6
1
2
3


4
5
6
7
8
9



-
-
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/Lagos) {
    {-9223372036854775808 816 0 LMT}
    {-1588464816 3600 0 WAT}
    {-9223372036854775808 815 0 LMT}
    {-2035584815 0 0 GMT}
    {-1940889600 815 0 LMT}
    {-1767226415 1800 0 +0030}
    {-1588465800 3600 0 WAT}
}

Changes to library/tzdata/Africa/Maputo.

1
2
3
4
5


6
1
2
3


4
5
6



-
-
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/Maputo) {
    {-9223372036854775808 7820 0 LMT}
    {-2109291020 7200 0 CAT}
    {-9223372036854775808 7818 0 LMT}
    {-1924999818 7200 0 CAT}
}

Changes to library/tzdata/Africa/Nairobi.

1
2
3
4

5
6
7
8




9
1
2
3
4
5




6
7
8
9
10




+
-
-
-
-
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/Nairobi) {
    {-9223372036854775808 8836 0 LMT}
    {-1946168836 9000 0 +0230}
    {-1309746436 10800 0 EAT}
    {-1262314800 9000 0 +0230}
    {-946780200 9900 0 +0245}
    {-315629100 10800 0 EAT}
    {-1309746600 10800 0 EAT}
    {-1261969200 9000 0 +0230}
    {-1041388200 9900 0 +0245}
    {-865305900 10800 0 EAT}
}

Changes to library/tzdata/America/Anguilla.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Anguilla) $TZData(:America/Port_of_Spain)
set TZData(:America/Anguilla) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Antigua.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Antigua) $TZData(:America/Port_of_Spain)
set TZData(:America/Antigua) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Araguaina.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Araguaina) {
    {-9223372036854775808 -11568 0 LMT}
    {-1767214032 -10800 0 -03}
    {-1206957600 -7200 1 -03}
    {-1191362400 -10800 0 -03}
    {-1175374800 -7200 1 -03}
    {-1159826400 -10800 0 -03}
    {-633819600 -7200 1 -03}
    {-622069200 -10800 0 -03}
    {-602283600 -7200 1 -03}
    {-591832800 -10800 0 -03}
    {-570747600 -7200 1 -03}
    {-560210400 -10800 0 -03}
    {-539125200 -7200 1 -03}
    {-531352800 -10800 0 -03}
    {-191365200 -7200 1 -03}
    {-184197600 -10800 0 -03}
    {-155163600 -7200 1 -03}
    {-150069600 -10800 0 -03}
    {-128898000 -7200 1 -03}
    {-121125600 -10800 0 -03}
    {-99954000 -7200 1 -03}
    {-89589600 -10800 0 -03}
    {-68418000 -7200 1 -03}
    {-57967200 -10800 0 -03}
    {499748400 -7200 1 -03}
    {511236000 -10800 0 -03}
    {530593200 -7200 1 -03}
    {540266400 -10800 0 -03}
    {562129200 -7200 1 -03}
    {571197600 -10800 0 -03}
    {592974000 -7200 1 -03}
    {602042400 -10800 0 -03}
    {624423600 -7200 1 -03}
    {634701600 -10800 0 -03}
    {653536800 -10800 0 -03}
    {811047600 -10800 0 -03}
    {813726000 -7200 1 -03}
    {824004000 -10800 0 -03}
    {844570800 -7200 1 -03}
    {856058400 -10800 0 -03}
    {876106800 -7200 1 -03}
    {888717600 -10800 0 -03}
    {908074800 -7200 1 -03}
    {919562400 -10800 0 -03}
    {938919600 -7200 1 -03}
    {951616800 -10800 0 -03}
    {970974000 -7200 1 -03}
    {982461600 -10800 0 -03}
    {1003028400 -7200 1 -03}
    {1013911200 -10800 0 -03}
    {1036292400 -7200 1 -03}
    {1045360800 -10800 0 -03}
    {1064368800 -10800 0 -03}
    {1350788400 -7200 0 -03}
    {1361066400 -10800 0 -03}
    {1378000800 -10800 0 -03}
    {-1767214032 -10800 0 -0300}
    {-1206957600 -7200 1 -0200}
    {-1191362400 -10800 0 -0300}
    {-1175374800 -7200 1 -0200}
    {-1159826400 -10800 0 -0300}
    {-633819600 -7200 1 -0200}
    {-622069200 -10800 0 -0300}
    {-602283600 -7200 1 -0200}
    {-591832800 -10800 0 -0300}
    {-570747600 -7200 1 -0200}
    {-560210400 -10800 0 -0300}
    {-539125200 -7200 1 -0200}
    {-531352800 -10800 0 -0300}
    {-191365200 -7200 1 -0200}
    {-184197600 -10800 0 -0300}
    {-155163600 -7200 1 -0200}
    {-150069600 -10800 0 -0300}
    {-128898000 -7200 1 -0200}
    {-121125600 -10800 0 -0300}
    {-99954000 -7200 1 -0200}
    {-89589600 -10800 0 -0300}
    {-68418000 -7200 1 -0200}
    {-57967200 -10800 0 -0300}
    {499748400 -7200 1 -0200}
    {511236000 -10800 0 -0300}
    {530593200 -7200 1 -0200}
    {540266400 -10800 0 -0300}
    {562129200 -7200 1 -0200}
    {571197600 -10800 0 -0300}
    {592974000 -7200 1 -0200}
    {602042400 -10800 0 -0300}
    {624423600 -7200 1 -0200}
    {634701600 -10800 0 -0300}
    {653536800 -10800 0 -0300}
    {811047600 -10800 0 -0300}
    {813726000 -7200 1 -0200}
    {824004000 -10800 0 -0300}
    {844570800 -7200 1 -0200}
    {856058400 -10800 0 -0300}
    {876106800 -7200 1 -0200}
    {888717600 -10800 0 -0300}
    {908074800 -7200 1 -0200}
    {919562400 -10800 0 -0300}
    {938919600 -7200 1 -0200}
    {951616800 -10800 0 -0300}
    {970974000 -7200 1 -0200}
    {982461600 -10800 0 -0300}
    {1003028400 -7200 1 -0200}
    {1013911200 -10800 0 -0300}
    {1036292400 -7200 1 -0200}
    {1045360800 -10800 0 -0300}
    {1064368800 -10800 0 -0300}
    {1350788400 -7200 0 -0200}
    {1361066400 -10800 0 -0300}
    {1378000800 -10800 0 -0300}
}

Changes to library/tzdata/America/Argentina/Buenos_Aires.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Argentina/Buenos_Aires) {
    {-9223372036854775808 -14028 0 LMT}
    {-2372097972 -15408 0 CMT}
    {-1567453392 -14400 0 -04}
    {-1233432000 -10800 0 -04}
    {-1222981200 -14400 0 -04}
    {-1205956800 -10800 1 -04}
    {-1194037200 -14400 0 -04}
    {-1172865600 -10800 1 -04}
    {-1162501200 -14400 0 -04}
    {-1141329600 -10800 1 -04}
    {-1130965200 -14400 0 -04}
    {-1109793600 -10800 1 -04}
    {-1099429200 -14400 0 -04}
    {-1078257600 -10800 1 -04}
    {-1067806800 -14400 0 -04}
    {-1046635200 -10800 1 -04}
    {-1036270800 -14400 0 -04}
    {-1015099200 -10800 1 -04}
    {-1004734800 -14400 0 -04}
    {-983563200 -10800 1 -04}
    {-973198800 -14400 0 -04}
    {-952027200 -10800 1 -04}
    {-941576400 -14400 0 -04}
    {-931032000 -10800 1 -04}
    {-900882000 -14400 0 -04}
    {-890337600 -10800 1 -04}
    {-833749200 -14400 0 -04}
    {-827265600 -10800 1 -04}
    {-752274000 -14400 0 -04}
    {-733780800 -10800 1 -04}
    {-197326800 -14400 0 -04}
    {-190843200 -10800 1 -04}
    {-184194000 -14400 0 -04}
    {-164491200 -10800 1 -04}
    {-152658000 -14400 0 -04}
    {-132955200 -10800 1 -04}
    {-121122000 -14400 0 -04}
    {-101419200 -10800 1 -04}
    {-86821200 -14400 0 -04}
    {-71092800 -10800 1 -04}
    {-54766800 -14400 0 -04}
    {-39038400 -10800 1 -04}
    {-23317200 -14400 0 -04}
    {-7588800 -10800 0 -03}
    {128142000 -7200 1 -03}
    {136605600 -10800 0 -03}
    {596948400 -7200 1 -03}
    {605066400 -10800 0 -03}
    {624423600 -7200 1 -03}
    {636516000 -10800 0 -03}
    {656478000 -7200 1 -03}
    {667965600 -10800 0 -03}
    {687927600 -7200 1 -03}
    {699415200 -10800 0 -03}
    {719377200 -7200 1 -03}
    {731469600 -10800 0 -03}
    {938916000 -10800 0 -04}
    {938919600 -10800 1 -04}
    {952056000 -10800 0 -03}
    {1198983600 -7200 1 -03}
    {1205632800 -10800 0 -03}
    {1224385200 -7200 1 -03}
    {1237082400 -10800 0 -03}
    {-1567453392 -14400 0 -0400}
    {-1233432000 -10800 0 -0300}
    {-1222981200 -14400 0 -0400}
    {-1205956800 -10800 1 -0300}
    {-1194037200 -14400 0 -0400}
    {-1172865600 -10800 1 -0300}
    {-1162501200 -14400 0 -0400}
    {-1141329600 -10800 1 -0300}
    {-1130965200 -14400 0 -0400}
    {-1109793600 -10800 1 -0300}
    {-1099429200 -14400 0 -0400}
    {-1078257600 -10800 1 -0300}
    {-1067806800 -14400 0 -0400}
    {-1046635200 -10800 1 -0300}
    {-1036270800 -14400 0 -0400}
    {-1015099200 -10800 1 -0300}
    {-1004734800 -14400 0 -0400}
    {-983563200 -10800 1 -0300}
    {-973198800 -14400 0 -0400}
    {-952027200 -10800 1 -0300}
    {-941576400 -14400 0 -0400}
    {-931032000 -10800 1 -0300}
    {-900882000 -14400 0 -0400}
    {-890337600 -10800 1 -0300}
    {-833749200 -14400 0 -0400}
    {-827265600 -10800 1 -0300}
    {-752274000 -14400 0 -0400}
    {-733780800 -10800 1 -0300}
    {-197326800 -14400 0 -0400}
    {-190843200 -10800 1 -0300}
    {-184194000 -14400 0 -0400}
    {-164491200 -10800 1 -0300}
    {-152658000 -14400 0 -0400}
    {-132955200 -10800 1 -0300}
    {-121122000 -14400 0 -0400}
    {-101419200 -10800 1 -0300}
    {-86821200 -14400 0 -0400}
    {-71092800 -10800 1 -0300}
    {-54766800 -14400 0 -0400}
    {-39038400 -10800 1 -0300}
    {-23317200 -14400 0 -0400}
    {-7588800 -10800 0 -0300}
    {128142000 -7200 1 -0200}
    {136605600 -10800 0 -0300}
    {596948400 -7200 1 -0200}
    {605066400 -10800 0 -0300}
    {624423600 -7200 1 -0200}
    {636516000 -10800 0 -0300}
    {656478000 -7200 1 -0200}
    {667965600 -10800 0 -0300}
    {687927600 -7200 1 -0200}
    {699415200 -10800 0 -0300}
    {719377200 -7200 1 -0200}
    {731469600 -10800 0 -0300}
    {938916000 -10800 0 -0300}
    {938919600 -10800 1 -0300}
    {952056000 -10800 0 -0300}
    {1198983600 -7200 1 -0200}
    {1205632800 -10800 0 -0300}
    {1224385200 -7200 1 -0200}
    {1237082400 -10800 0 -0300}
}

Changes to library/tzdata/America/Argentina/Catamarca.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Argentina/Catamarca) {
    {-9223372036854775808 -15788 0 LMT}
    {-2372096212 -15408 0 CMT}
    {-1567453392 -14400 0 -04}
    {-1233432000 -10800 0 -04}
    {-1222981200 -14400 0 -04}
    {-1205956800 -10800 1 -04}
    {-1194037200 -14400 0 -04}
    {-1172865600 -10800 1 -04}
    {-1162501200 -14400 0 -04}
    {-1141329600 -10800 1 -04}
    {-1130965200 -14400 0 -04}
    {-1109793600 -10800 1 -04}
    {-1099429200 -14400 0 -04}
    {-1078257600 -10800 1 -04}
    {-1067806800 -14400 0 -04}
    {-1046635200 -10800 1 -04}
    {-1036270800 -14400 0 -04}
    {-1015099200 -10800 1 -04}
    {-1004734800 -14400 0 -04}
    {-983563200 -10800 1 -04}
    {-973198800 -14400 0 -04}
    {-952027200 -10800 1 -04}
    {-941576400 -14400 0 -04}
    {-931032000 -10800 1 -04}
    {-900882000 -14400 0 -04}
    {-890337600 -10800 1 -04}
    {-833749200 -14400 0 -04}
    {-827265600 -10800 1 -04}
    {-752274000 -14400 0 -04}
    {-733780800 -10800 1 -04}
    {-197326800 -14400 0 -04}
    {-190843200 -10800 1 -04}
    {-184194000 -14400 0 -04}
    {-164491200 -10800 1 -04}
    {-152658000 -14400 0 -04}
    {-132955200 -10800 1 -04}
    {-121122000 -14400 0 -04}
    {-101419200 -10800 1 -04}
    {-86821200 -14400 0 -04}
    {-71092800 -10800 1 -04}
    {-54766800 -14400 0 -04}
    {-39038400 -10800 1 -04}
    {-23317200 -14400 0 -04}
    {-7588800 -10800 0 -03}
    {128142000 -7200 1 -03}
    {136605600 -10800 0 -03}
    {596948400 -7200 1 -03}
    {605066400 -10800 0 -03}
    {624423600 -7200 1 -03}
    {636516000 -10800 0 -03}
    {656478000 -7200 1 -03}
    {667965600 -14400 0 -04}
    {687931200 -7200 0 -03}
    {699415200 -10800 0 -03}
    {719377200 -7200 1 -03}
    {731469600 -10800 0 -03}
    {938916000 -10800 0 -04}
    {938919600 -10800 1 -04}
    {952056000 -10800 0 -03}
    {1086058800 -14400 0 -04}
    {1087704000 -10800 0 -03}
    {1198983600 -7200 1 -03}
    {1205632800 -10800 0 -03}
    {1224295200 -10800 0 -03}
    {-1567453392 -14400 0 -0400}
    {-1233432000 -10800 0 -0300}
    {-1222981200 -14400 0 -0400}
    {-1205956800 -10800 1 -0300}
    {-1194037200 -14400 0 -0400}
    {-1172865600 -10800 1 -0300}
    {-1162501200 -14400 0 -0400}
    {-1141329600 -10800 1 -0300}
    {-1130965200 -14400 0 -0400}
    {-1109793600 -10800 1 -0300}
    {-1099429200 -14400 0 -0400}
    {-1078257600 -10800 1 -0300}
    {-1067806800 -14400 0 -0400}
    {-1046635200 -10800 1 -0300}
    {-1036270800 -14400 0 -0400}
    {-1015099200 -10800 1 -0300}
    {-1004734800 -14400 0 -0400}
    {-983563200 -10800 1 -0300}
    {-973198800 -14400 0 -0400}
    {-952027200 -10800 1 -0300}
    {-941576400 -14400 0 -0400}
    {-931032000 -10800 1 -0300}
    {-900882000 -14400 0 -0400}
    {-890337600 -10800 1 -0300}
    {-833749200 -14400 0 -0400}
    {-827265600 -10800 1 -0300}
    {-752274000 -14400 0 -0400}
    {-733780800 -10800 1 -0300}
    {-197326800 -14400 0 -0400}
    {-190843200 -10800 1 -0300}
    {-184194000 -14400 0 -0400}
    {-164491200 -10800 1 -0300}
    {-152658000 -14400 0 -0400}
    {-132955200 -10800 1 -0300}
    {-121122000 -14400 0 -0400}
    {-101419200 -10800 1 -0300}
    {-86821200 -14400 0 -0400}
    {-71092800 -10800 1 -0300}
    {-54766800 -14400 0 -0400}
    {-39038400 -10800 1 -0300}
    {-23317200 -14400 0 -0400}
    {-7588800 -10800 0 -0300}
    {128142000 -7200 1 -0200}
    {136605600 -10800 0 -0300}
    {596948400 -7200 1 -0200}
    {605066400 -10800 0 -0300}
    {624423600 -7200 1 -0200}
    {636516000 -10800 0 -0300}
    {656478000 -7200 1 -0200}
    {667965600 -14400 0 -0400}
    {687931200 -7200 0 -0200}
    {699415200 -10800 0 -0300}
    {719377200 -7200 1 -0200}
    {731469600 -10800 0 -0300}
    {938916000 -10800 0 -0300}
    {938919600 -10800 1 -0300}
    {952056000 -10800 0 -0300}
    {1086058800 -14400 0 -0400}
    {1087704000 -10800 0 -0300}
    {1198983600 -7200 1 -0200}
    {1205632800 -10800 0 -0300}
    {1224295200 -10800 0 -0300}
}

Changes to library/tzdata/America/Argentina/Cordoba.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Argentina/Cordoba) {
    {-9223372036854775808 -15408 0 LMT}
    {-2372096592 -15408 0 CMT}
    {-1567453392 -14400 0 -04}
    {-1233432000 -10800 0 -04}
    {-1222981200 -14400 0 -04}
    {-1205956800 -10800 1 -04}
    {-1194037200 -14400 0 -04}
    {-1172865600 -10800 1 -04}
    {-1162501200 -14400 0 -04}
    {-1141329600 -10800 1 -04}
    {-1130965200 -14400 0 -04}
    {-1109793600 -10800 1 -04}
    {-1099429200 -14400 0 -04}
    {-1078257600 -10800 1 -04}
    {-1067806800 -14400 0 -04}
    {-1046635200 -10800 1 -04}
    {-1036270800 -14400 0 -04}
    {-1015099200 -10800 1 -04}
    {-1004734800 -14400 0 -04}
    {-983563200 -10800 1 -04}
    {-973198800 -14400 0 -04}
    {-952027200 -10800 1 -04}
    {-941576400 -14400 0 -04}
    {-931032000 -10800 1 -04}
    {-900882000 -14400 0 -04}
    {-890337600 -10800 1 -04}
    {-833749200 -14400 0 -04}
    {-827265600 -10800 1 -04}
    {-752274000 -14400 0 -04}
    {-733780800 -10800 1 -04}
    {-197326800 -14400 0 -04}
    {-190843200 -10800 1 -04}
    {-184194000 -14400 0 -04}
    {-164491200 -10800 1 -04}
    {-152658000 -14400 0 -04}
    {-132955200 -10800 1 -04}
    {-121122000 -14400 0 -04}
    {-101419200 -10800 1 -04}
    {-86821200 -14400 0 -04}
    {-71092800 -10800 1 -04}
    {-54766800 -14400 0 -04}
    {-39038400 -10800 1 -04}
    {-23317200 -14400 0 -04}
    {-7588800 -10800 0 -03}
    {128142000 -7200 1 -03}
    {136605600 -10800 0 -03}
    {596948400 -7200 1 -03}
    {605066400 -10800 0 -03}
    {624423600 -7200 1 -03}
    {636516000 -10800 0 -03}
    {656478000 -7200 1 -03}
    {667965600 -14400 0 -04}
    {687931200 -7200 0 -03}
    {699415200 -10800 0 -03}
    {719377200 -7200 1 -03}
    {731469600 -10800 0 -03}
    {938916000 -10800 0 -04}
    {938919600 -10800 1 -04}
    {952056000 -10800 0 -03}
    {1198983600 -7200 1 -03}
    {1205632800 -10800 0 -03}
    {1224385200 -7200 1 -03}
    {1237082400 -10800 0 -03}
    {-1567453392 -14400 0 -0400}
    {-1233432000 -10800 0 -0300}
    {-1222981200 -14400 0 -0400}
    {-1205956800 -10800 1 -0300}
    {-1194037200 -14400 0 -0400}
    {-1172865600 -10800 1 -0300}
    {-1162501200 -14400 0 -0400}
    {-1141329600 -10800 1 -0300}
    {-1130965200 -14400 0 -0400}
    {-1109793600 -10800 1 -0300}
    {-1099429200 -14400 0 -0400}
    {-1078257600 -10800 1 -0300}
    {-1067806800 -14400 0 -0400}
    {-1046635200 -10800 1 -0300}
    {-1036270800 -14400 0 -0400}
    {-1015099200 -10800 1 -0300}
    {-1004734800 -14400 0 -0400}
    {-983563200 -10800 1 -0300}
    {-973198800 -14400 0 -0400}
    {-952027200 -10800 1 -0300}
    {-941576400 -14400 0 -0400}
    {-931032000 -10800 1 -0300}
    {-900882000 -14400 0 -0400}
    {-890337600 -10800 1 -0300}
    {-833749200 -14400 0 -0400}
    {-827265600 -10800 1 -0300}
    {-752274000 -14400 0 -0400}
    {-733780800 -10800 1 -0300}
    {-197326800 -14400 0 -0400}
    {-190843200 -10800 1 -0300}
    {-184194000 -14400 0 -0400}
    {-164491200 -10800 1 -0300}
    {-152658000 -14400 0 -0400}
    {-132955200 -10800 1 -0300}
    {-121122000 -14400 0 -0400}
    {-101419200 -10800 1 -0300}
    {-86821200 -14400 0 -0400}
    {-71092800 -10800 1 -0300}
    {-54766800 -14400 0 -0400}
    {-39038400 -10800 1 -0300}
    {-23317200 -14400 0 -0400}
    {-7588800 -10800 0 -0300}
    {128142000 -7200 1 -0200}
    {136605600 -10800 0 -0300}
    {596948400 -7200 1 -0200}
    {605066400 -10800 0 -0300}
    {624423600 -7200 1 -0200}
    {636516000 -10800 0 -0300}
    {656478000 -7200 1 -0200}
    {667965600 -14400 0 -0400}
    {687931200 -7200 0 -0200}
    {699415200 -10800 0 -0300}
    {719377200 -7200 1 -0200}
    {731469600 -10800 0 -0300}
    {938916000 -10800 0 -0300}
    {938919600 -10800 1 -0300}
    {952056000 -10800 0 -0300}
    {1198983600 -7200 1 -0200}
    {1205632800 -10800 0 -0300}
    {1224385200 -7200 1 -0200}
    {1237082400 -10800 0 -0300}
}

Changes to library/tzdata/America/Argentina/Jujuy.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Argentina/Jujuy) {
    {-9223372036854775808 -15672 0 LMT}
    {-2372096328 -15408 0 CMT}
    {-1567453392 -14400 0 -04}
    {-1233432000 -10800 0 -04}
    {-1222981200 -14400 0 -04}
    {-1205956800 -10800 1 -04}
    {-1194037200 -14400 0 -04}
    {-1172865600 -10800 1 -04}
    {-1162501200 -14400 0 -04}
    {-1141329600 -10800 1 -04}
    {-1130965200 -14400 0 -04}
    {-1109793600 -10800 1 -04}
    {-1099429200 -14400 0 -04}
    {-1078257600 -10800 1 -04}
    {-1067806800 -14400 0 -04}
    {-1046635200 -10800 1 -04}
    {-1036270800 -14400 0 -04}
    {-1015099200 -10800 1 -04}
    {-1004734800 -14400 0 -04}
    {-983563200 -10800 1 -04}
    {-973198800 -14400 0 -04}
    {-952027200 -10800 1 -04}
    {-941576400 -14400 0 -04}
    {-931032000 -10800 1 -04}
    {-900882000 -14400 0 -04}
    {-890337600 -10800 1 -04}
    {-833749200 -14400 0 -04}
    {-827265600 -10800 1 -04}
    {-752274000 -14400 0 -04}
    {-733780800 -10800 1 -04}
    {-197326800 -14400 0 -04}
    {-190843200 -10800 1 -04}
    {-184194000 -14400 0 -04}
    {-164491200 -10800 1 -04}
    {-152658000 -14400 0 -04}
    {-132955200 -10800 1 -04}
    {-121122000 -14400 0 -04}
    {-101419200 -10800 1 -04}
    {-86821200 -14400 0 -04}
    {-71092800 -10800 1 -04}
    {-54766800 -14400 0 -04}
    {-39038400 -10800 1 -04}
    {-23317200 -14400 0 -04}
    {-7588800 -10800 0 -03}
    {128142000 -7200 1 -03}
    {136605600 -10800 0 -03}
    {596948400 -7200 1 -03}
    {605066400 -10800 0 -03}
    {624423600 -7200 1 -03}
    {636516000 -14400 0 -04}
    {657086400 -10800 1 -03}
    {669178800 -14400 0 -04}
    {686721600 -7200 1 -02}
    {694231200 -7200 0 -03}
    {699415200 -10800 0 -03}
    {719377200 -7200 1 -03}
    {731469600 -10800 0 -03}
    {938916000 -10800 0 -04}
    {938919600 -10800 1 -04}
    {952056000 -10800 0 -03}
    {1198983600 -7200 1 -03}
    {1205632800 -10800 0 -03}
    {1224295200 -10800 0 -03}
    {-1567453392 -14400 0 -0400}
    {-1233432000 -10800 0 -0300}
    {-1222981200 -14400 0 -0400}
    {-1205956800 -10800 1 -0300}
    {-1194037200 -14400 0 -0400}
    {-1172865600 -10800 1 -0300}
    {-1162501200 -14400 0 -0400}
    {-1141329600 -10800 1 -0300}
    {-1130965200 -14400 0 -0400}
    {-1109793600 -10800 1 -0300}
    {-1099429200 -14400 0 -0400}
    {-1078257600 -10800 1 -0300}
    {-1067806800 -14400 0 -0400}
    {-1046635200 -10800 1 -0300}
    {-1036270800 -14400 0 -0400}
    {-1015099200 -10800 1 -0300}
    {-1004734800 -14400 0 -0400}
    {-983563200 -10800 1 -0300}
    {-973198800 -14400 0 -0400}
    {-952027200 -10800 1 -0300}
    {-941576400 -14400 0 -0400}
    {-931032000 -10800 1 -0300}
    {-900882000 -14400 0 -0400}
    {-890337600 -10800 1 -0300}
    {-833749200 -14400 0 -0400}
    {-827265600 -10800 1 -0300}
    {-752274000 -14400 0 -0400}
    {-733780800 -10800 1 -0300}
    {-197326800 -14400 0 -0400}
    {-190843200 -10800 1 -0300}
    {-184194000 -14400 0 -0400}
    {-164491200 -10800 1 -0300}
    {-152658000 -14400 0 -0400}
    {-132955200 -10800 1 -0300}
    {-121122000 -14400 0 -0400}
    {-101419200 -10800 1 -0300}
    {-86821200 -14400 0 -0400}
    {-71092800 -10800 1 -0300}
    {-54766800 -14400 0 -0400}
    {-39038400 -10800 1 -0300}
    {-23317200 -14400 0 -0400}
    {-7588800 -10800 0 -0300}
    {128142000 -7200 1 -0200}
    {136605600 -10800 0 -0300}
    {596948400 -7200 1 -0200}
    {605066400 -10800 0 -0300}
    {624423600 -7200 1 -0200}
    {636516000 -14400 0 -0400}
    {657086400 -10800 1 -0300}
    {669178800 -14400 0 -0400}
    {686721600 -7200 1 -0200}
    {694231200 -7200 0 -0200}
    {699415200 -10800 0 -0300}
    {719377200 -7200 1 -0200}
    {731469600 -10800 0 -0300}
    {938916000 -10800 0 -0300}
    {938919600 -10800 1 -0300}
    {952056000 -10800 0 -0300}
    {1198983600 -7200 1 -0200}
    {1205632800 -10800 0 -0300}
    {1224295200 -10800 0 -0300}
}

Changes to library/tzdata/America/Argentina/La_Rioja.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Argentina/La_Rioja) {
    {-9223372036854775808 -16044 0 LMT}
    {-2372095956 -15408 0 CMT}
    {-1567453392 -14400 0 -04}
    {-1233432000 -10800 0 -04}
    {-1222981200 -14400 0 -04}
    {-1205956800 -10800 1 -04}
    {-1194037200 -14400 0 -04}
    {-1172865600 -10800 1 -04}
    {-1162501200 -14400 0 -04}
    {-1141329600 -10800 1 -04}
    {-1130965200 -14400 0 -04}
    {-1109793600 -10800 1 -04}
    {-1099429200 -14400 0 -04}
    {-1078257600 -10800 1 -04}
    {-1067806800 -14400 0 -04}
    {-1046635200 -10800 1 -04}
    {-1036270800 -14400 0 -04}
    {-1015099200 -10800 1 -04}
    {-1004734800 -14400 0 -04}
    {-983563200 -10800 1 -04}
    {-973198800 -14400 0 -04}
    {-952027200 -10800 1 -04}
    {-941576400 -14400 0 -04}
    {-931032000 -10800 1 -04}
    {-900882000 -14400 0 -04}
    {-890337600 -10800 1 -04}
    {-833749200 -14400 0 -04}
    {-827265600 -10800 1 -04}
    {-752274000 -14400 0 -04}
    {-733780800 -10800 1 -04}
    {-197326800 -14400 0 -04}
    {-190843200 -10800 1 -04}
    {-184194000 -14400 0 -04}
    {-164491200 -10800 1 -04}
    {-152658000 -14400 0 -04}
    {-132955200 -10800 1 -04}
    {-121122000 -14400 0 -04}
    {-101419200 -10800 1 -04}
    {-86821200 -14400 0 -04}
    {-71092800 -10800 1 -04}
    {-54766800 -14400 0 -04}
    {-39038400 -10800 1 -04}
    {-23317200 -14400 0 -04}
    {-7588800 -10800 0 -03}
    {128142000 -7200 1 -03}
    {136605600 -10800 0 -03}
    {596948400 -7200 1 -03}
    {605066400 -10800 0 -03}
    {624423600 -7200 1 -03}
    {636516000 -10800 0 -03}
    {656478000 -7200 1 -03}
    {667792800 -14400 0 -04}
    {673588800 -10800 0 -03}
    {687927600 -7200 1 -03}
    {699415200 -10800 0 -03}
    {719377200 -7200 1 -03}
    {731469600 -10800 0 -03}
    {938916000 -10800 0 -04}
    {938919600 -10800 1 -04}
    {952056000 -10800 0 -03}
    {1086058800 -14400 0 -04}
    {1087704000 -10800 0 -03}
    {1198983600 -7200 1 -03}
    {1205632800 -10800 0 -03}
    {1224295200 -10800 0 -03}
    {-1567453392 -14400 0 -0400}
    {-1233432000 -10800 0 -0300}
    {-1222981200 -14400 0 -0400}
    {-1205956800 -10800 1 -0300}
    {-1194037200 -14400 0 -0400}
    {-1172865600 -10800 1 -0300}
    {-1162501200 -14400 0 -0400}
    {-1141329600 -10800 1 -0300}
    {-1130965200 -14400 0 -0400}
    {-1109793600 -10800 1 -0300}
    {-1099429200 -14400 0 -0400}
    {-1078257600 -10800 1 -0300}
    {-1067806800 -14400 0 -0400}
    {-1046635200 -10800 1 -0300}
    {-1036270800 -14400 0 -0400}
    {-1015099200 -10800 1 -0300}
    {-1004734800 -14400 0 -0400}
    {-983563200 -10800 1 -0300}
    {-973198800 -14400 0 -0400}
    {-952027200 -10800 1 -0300}
    {-941576400 -14400 0 -0400}
    {-931032000 -10800 1 -0300}
    {-900882000 -14400 0 -0400}
    {-890337600 -10800 1 -0300}
    {-833749200 -14400 0 -0400}
    {-827265600 -10800 1 -0300}
    {-752274000 -14400 0 -0400}
    {-733780800 -10800 1 -0300}
    {-197326800 -14400 0 -0400}
    {-190843200 -10800 1 -0300}
    {-184194000 -14400 0 -0400}
    {-164491200 -10800 1 -0300}
    {-152658000 -14400 0 -0400}
    {-132955200 -10800 1 -0300}
    {-121122000 -14400 0 -0400}
    {-101419200 -10800 1 -0300}
    {-86821200 -14400 0 -0400}
    {-71092800 -10800 1 -0300}
    {-54766800 -14400 0 -0400}
    {-39038400 -10800 1 -0300}
    {-23317200 -14400 0 -0400}
    {-7588800 -10800 0 -0300}
    {128142000 -7200 1 -0200}
    {136605600 -10800 0 -0300}
    {596948400 -7200 1 -0200}
    {605066400 -10800 0 -0300}
    {624423600 -7200 1 -0200}
    {636516000 -10800 0 -0300}
    {656478000 -7200 1 -0200}
    {667792800 -14400 0 -0400}
    {673588800 -10800 0 -0300}
    {687927600 -7200 1 -0200}
    {699415200 -10800 0 -0300}
    {719377200 -7200 1 -0200}
    {731469600 -10800 0 -0300}
    {938916000 -10800 0 -0300}
    {938919600 -10800 1 -0300}
    {952056000 -10800 0 -0300}
    {1086058800 -14400 0 -0400}
    {1087704000 -10800 0 -0300}
    {1198983600 -7200 1 -0200}
    {1205632800 -10800 0 -0300}
    {1224295200 -10800 0 -0300}
}

Changes to library/tzdata/America/Argentina/Mendoza.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Argentina/Mendoza) {
    {-9223372036854775808 -16516 0 LMT}
    {-2372095484 -15408 0 CMT}
    {-1567453392 -14400 0 -04}
    {-1233432000 -10800 0 -04}
    {-1222981200 -14400 0 -04}
    {-1205956800 -10800 1 -04}
    {-1194037200 -14400 0 -04}
    {-1172865600 -10800 1 -04}
    {-1162501200 -14400 0 -04}
    {-1141329600 -10800 1 -04}
    {-1130965200 -14400 0 -04}
    {-1109793600 -10800 1 -04}
    {-1099429200 -14400 0 -04}
    {-1078257600 -10800 1 -04}
    {-1067806800 -14400 0 -04}
    {-1046635200 -10800 1 -04}
    {-1036270800 -14400 0 -04}
    {-1015099200 -10800 1 -04}
    {-1004734800 -14400 0 -04}
    {-983563200 -10800 1 -04}
    {-973198800 -14400 0 -04}
    {-952027200 -10800 1 -04}
    {-941576400 -14400 0 -04}
    {-931032000 -10800 1 -04}
    {-900882000 -14400 0 -04}
    {-890337600 -10800 1 -04}
    {-833749200 -14400 0 -04}
    {-827265600 -10800 1 -04}
    {-752274000 -14400 0 -04}
    {-733780800 -10800 1 -04}
    {-197326800 -14400 0 -04}
    {-190843200 -10800 1 -04}
    {-184194000 -14400 0 -04}
    {-164491200 -10800 1 -04}
    {-152658000 -14400 0 -04}
    {-132955200 -10800 1 -04}
    {-121122000 -14400 0 -04}
    {-101419200 -10800 1 -04}
    {-86821200 -14400 0 -04}
    {-71092800 -10800 1 -04}
    {-54766800 -14400 0 -04}
    {-39038400 -10800 1 -04}
    {-23317200 -14400 0 -04}
    {-7588800 -10800 0 -03}
    {128142000 -7200 1 -03}
    {136605600 -10800 0 -03}
    {596948400 -7200 1 -03}
    {605066400 -10800 0 -03}
    {624423600 -7200 1 -03}
    {636516000 -14400 0 -04}
    {655963200 -10800 1 -03}
    {667796400 -14400 0 -04}
    {687499200 -10800 1 -03}
    {699418800 -14400 0 -04}
    {719380800 -7200 0 -03}
    {731469600 -10800 0 -03}
    {938916000 -10800 0 -04}
    {938919600 -10800 1 -04}
    {952056000 -10800 0 -03}
    {1085281200 -14400 0 -04}
    {1096171200 -10800 0 -03}
    {1198983600 -7200 1 -03}
    {1205632800 -10800 0 -03}
    {1224295200 -10800 0 -03}
    {-1567453392 -14400 0 -0400}
    {-1233432000 -10800 0 -0300}
    {-1222981200 -14400 0 -0400}
    {-1205956800 -10800 1 -0300}
    {-1194037200 -14400 0 -0400}
    {-1172865600 -10800 1 -0300}
    {-1162501200 -14400 0 -0400}
    {-1141329600 -10800 1 -0300}
    {-1130965200 -14400 0 -0400}
    {-1109793600 -10800 1 -0300}
    {-1099429200 -14400 0 -0400}
    {-1078257600 -10800 1 -0300}
    {-1067806800 -14400 0 -0400}
    {-1046635200 -10800 1 -0300}
    {-1036270800 -14400 0 -0400}
    {-1015099200 -10800 1 -0300}
    {-1004734800 -14400 0 -0400}
    {-983563200 -10800 1 -0300}
    {-973198800 -14400 0 -0400}
    {-952027200 -10800 1 -0300}
    {-941576400 -14400 0 -0400}
    {-931032000 -10800 1 -0300}
    {-900882000 -14400 0 -0400}
    {-890337600 -10800 1 -0300}
    {-833749200 -14400 0 -0400}
    {-827265600 -10800 1 -0300}
    {-752274000 -14400 0 -0400}
    {-733780800 -10800 1 -0300}
    {-197326800 -14400 0 -0400}
    {-190843200 -10800 1 -0300}
    {-184194000 -14400 0 -0400}
    {-164491200 -10800 1 -0300}
    {-152658000 -14400 0 -0400}
    {-132955200 -10800 1 -0300}
    {-121122000 -14400 0 -0400}
    {-101419200 -10800 1 -0300}
    {-86821200 -14400 0 -0400}
    {-71092800 -10800 1 -0300}
    {-54766800 -14400 0 -0400}
    {-39038400 -10800 1 -0300}
    {-23317200 -14400 0 -0400}
    {-7588800 -10800 0 -0300}
    {128142000 -7200 1 -0200}
    {136605600 -10800 0 -0300}
    {596948400 -7200 1 -0200}
    {605066400 -10800 0 -0300}
    {624423600 -7200 1 -0200}
    {636516000 -14400 0 -0400}
    {655963200 -10800 1 -0300}
    {667796400 -14400 0 -0400}
    {687499200 -10800 1 -0300}
    {699418800 -14400 0 -0400}
    {719380800 -7200 0 -0200}
    {731469600 -10800 0 -0300}
    {938916000 -10800 0 -0300}
    {938919600 -10800 1 -0300}
    {952056000 -10800 0 -0300}
    {1085281200 -14400 0 -0400}
    {1096171200 -10800 0 -0300}
    {1198983600 -7200 1 -0200}
    {1205632800 -10800 0 -0300}
    {1224295200 -10800 0 -0300}
}

Changes to library/tzdata/America/Argentina/Rio_Gallegos.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Argentina/Rio_Gallegos) {
    {-9223372036854775808 -16612 0 LMT}
    {-2372095388 -15408 0 CMT}
    {-1567453392 -14400 0 -04}
    {-1233432000 -10800 0 -04}
    {-1222981200 -14400 0 -04}
    {-1205956800 -10800 1 -04}
    {-1194037200 -14400 0 -04}
    {-1172865600 -10800 1 -04}
    {-1162501200 -14400 0 -04}
    {-1141329600 -10800 1 -04}
    {-1130965200 -14400 0 -04}
    {-1109793600 -10800 1 -04}
    {-1099429200 -14400 0 -04}
    {-1078257600 -10800 1 -04}
    {-1067806800 -14400 0 -04}
    {-1046635200 -10800 1 -04}
    {-1036270800 -14400 0 -04}
    {-1015099200 -10800 1 -04}
    {-1004734800 -14400 0 -04}
    {-983563200 -10800 1 -04}
    {-973198800 -14400 0 -04}
    {-952027200 -10800 1 -04}
    {-941576400 -14400 0 -04}
    {-931032000 -10800 1 -04}
    {-900882000 -14400 0 -04}
    {-890337600 -10800 1 -04}
    {-833749200 -14400 0 -04}
    {-827265600 -10800 1 -04}
    {-752274000 -14400 0 -04}
    {-733780800 -10800 1 -04}
    {-197326800 -14400 0 -04}
    {-190843200 -10800 1 -04}
    {-184194000 -14400 0 -04}
    {-164491200 -10800 1 -04}
    {-152658000 -14400 0 -04}
    {-132955200 -10800 1 -04}
    {-121122000 -14400 0 -04}
    {-101419200 -10800 1 -04}
    {-86821200 -14400 0 -04}
    {-71092800 -10800 1 -04}
    {-54766800 -14400 0 -04}
    {-39038400 -10800 1 -04}
    {-23317200 -14400 0 -04}
    {-7588800 -10800 0 -03}
    {128142000 -7200 1 -03}
    {136605600 -10800 0 -03}
    {596948400 -7200 1 -03}
    {605066400 -10800 0 -03}
    {624423600 -7200 1 -03}
    {636516000 -10800 0 -03}
    {656478000 -7200 1 -03}
    {667965600 -10800 0 -03}
    {687927600 -7200 1 -03}
    {699415200 -10800 0 -03}
    {719377200 -7200 1 -03}
    {731469600 -10800 0 -03}
    {938916000 -10800 0 -04}
    {938919600 -10800 1 -04}
    {952056000 -10800 0 -03}
    {1086058800 -14400 0 -04}
    {1087704000 -10800 0 -03}
    {1198983600 -7200 1 -03}
    {1205632800 -10800 0 -03}
    {1224295200 -10800 0 -03}
    {-1567453392 -14400 0 -0400}
    {-1233432000 -10800 0 -0300}
    {-1222981200 -14400 0 -0400}
    {-1205956800 -10800 1 -0300}
    {-1194037200 -14400 0 -0400}
    {-1172865600 -10800 1 -0300}
    {-1162501200 -14400 0 -0400}
    {-1141329600 -10800 1 -0300}
    {-1130965200 -14400 0 -0400}
    {-1109793600 -10800 1 -0300}
    {-1099429200 -14400 0 -0400}
    {-1078257600 -10800 1 -0300}
    {-1067806800 -14400 0 -0400}
    {-1046635200 -10800 1 -0300}
    {-1036270800 -14400 0 -0400}
    {-1015099200 -10800 1 -0300}
    {-1004734800 -14400 0 -0400}
    {-983563200 -10800 1 -0300}
    {-973198800 -14400 0 -0400}
    {-952027200 -10800 1 -0300}
    {-941576400 -14400 0 -0400}
    {-931032000 -10800 1 -0300}
    {-900882000 -14400 0 -0400}
    {-890337600 -10800 1 -0300}
    {-833749200 -14400 0 -0400}
    {-827265600 -10800 1 -0300}
    {-752274000 -14400 0 -0400}
    {-733780800 -10800 1 -0300}
    {-197326800 -14400 0 -0400}
    {-190843200 -10800 1 -0300}
    {-184194000 -14400 0 -0400}
    {-164491200 -10800 1 -0300}
    {-152658000 -14400 0 -0400}
    {-132955200 -10800 1 -0300}
    {-121122000 -14400 0 -0400}
    {-101419200 -10800 1 -0300}
    {-86821200 -14400 0 -0400}
    {-71092800 -10800 1 -0300}
    {-54766800 -14400 0 -0400}
    {-39038400 -10800 1 -0300}
    {-23317200 -14400 0 -0400}
    {-7588800 -10800 0 -0300}
    {128142000 -7200 1 -0200}
    {136605600 -10800 0 -0300}
    {596948400 -7200 1 -0200}
    {605066400 -10800 0 -0300}
    {624423600 -7200 1 -0200}
    {636516000 -10800 0 -0300}
    {656478000 -7200 1 -0200}
    {667965600 -10800 0 -0300}
    {687927600 -7200 1 -0200}
    {699415200 -10800 0 -0300}
    {719377200 -7200 1 -0200}
    {731469600 -10800 0 -0300}
    {938916000 -10800 0 -0300}
    {938919600 -10800 1 -0300}
    {952056000 -10800 0 -0300}
    {1086058800 -14400 0 -0400}
    {1087704000 -10800 0 -0300}
    {1198983600 -7200 1 -0200}
    {1205632800 -10800 0 -0300}
    {1224295200 -10800 0 -0300}
}

Changes to library/tzdata/America/Argentina/Salta.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Argentina/Salta) {
    {-9223372036854775808 -15700 0 LMT}
    {-2372096300 -15408 0 CMT}
    {-1567453392 -14400 0 -04}
    {-1233432000 -10800 0 -04}
    {-1222981200 -14400 0 -04}
    {-1205956800 -10800 1 -04}
    {-1194037200 -14400 0 -04}
    {-1172865600 -10800 1 -04}
    {-1162501200 -14400 0 -04}
    {-1141329600 -10800 1 -04}
    {-1130965200 -14400 0 -04}
    {-1109793600 -10800 1 -04}
    {-1099429200 -14400 0 -04}
    {-1078257600 -10800 1 -04}
    {-1067806800 -14400 0 -04}
    {-1046635200 -10800 1 -04}
    {-1036270800 -14400 0 -04}
    {-1015099200 -10800 1 -04}
    {-1004734800 -14400 0 -04}
    {-983563200 -10800 1 -04}
    {-973198800 -14400 0 -04}
    {-952027200 -10800 1 -04}
    {-941576400 -14400 0 -04}
    {-931032000 -10800 1 -04}
    {-900882000 -14400 0 -04}
    {-890337600 -10800 1 -04}
    {-833749200 -14400 0 -04}
    {-827265600 -10800 1 -04}
    {-752274000 -14400 0 -04}
    {-733780800 -10800 1 -04}
    {-197326800 -14400 0 -04}
    {-190843200 -10800 1 -04}
    {-184194000 -14400 0 -04}
    {-164491200 -10800 1 -04}
    {-152658000 -14400 0 -04}
    {-132955200 -10800 1 -04}
    {-121122000 -14400 0 -04}
    {-101419200 -10800 1 -04}
    {-86821200 -14400 0 -04}
    {-71092800 -10800 1 -04}
    {-54766800 -14400 0 -04}
    {-39038400 -10800 1 -04}
    {-23317200 -14400 0 -04}
    {-7588800 -10800 0 -03}
    {128142000 -7200 1 -03}
    {136605600 -10800 0 -03}
    {596948400 -7200 1 -03}
    {605066400 -10800 0 -03}
    {624423600 -7200 1 -03}
    {636516000 -10800 0 -03}
    {656478000 -7200 1 -03}
    {667965600 -14400 0 -04}
    {687931200 -7200 0 -03}
    {699415200 -10800 0 -03}
    {719377200 -7200 1 -03}
    {731469600 -10800 0 -03}
    {938916000 -10800 0 -04}
    {938919600 -10800 1 -04}
    {952056000 -10800 0 -03}
    {1198983600 -7200 1 -03}
    {1205632800 -10800 0 -03}
    {1224295200 -10800 0 -03}
    {-1567453392 -14400 0 -0400}
    {-1233432000 -10800 0 -0300}
    {-1222981200 -14400 0 -0400}
    {-1205956800 -10800 1 -0300}
    {-1194037200 -14400 0 -0400}
    {-1172865600 -10800 1 -0300}
    {-1162501200 -14400 0 -0400}
    {-1141329600 -10800 1 -0300}
    {-1130965200 -14400 0 -0400}
    {-1109793600 -10800 1 -0300}
    {-1099429200 -14400 0 -0400}
    {-1078257600 -10800 1 -0300}
    {-1067806800 -14400 0 -0400}
    {-1046635200 -10800 1 -0300}
    {-1036270800 -14400 0 -0400}
    {-1015099200 -10800 1 -0300}
    {-1004734800 -14400 0 -0400}
    {-983563200 -10800 1 -0300}
    {-973198800 -14400 0 -0400}
    {-952027200 -10800 1 -0300}
    {-941576400 -14400 0 -0400}
    {-931032000 -10800 1 -0300}
    {-900882000 -14400 0 -0400}
    {-890337600 -10800 1 -0300}
    {-833749200 -14400 0 -0400}
    {-827265600 -10800 1 -0300}
    {-752274000 -14400 0 -0400}
    {-733780800 -10800 1 -0300}
    {-197326800 -14400 0 -0400}
    {-190843200 -10800 1 -0300}
    {-184194000 -14400 0 -0400}
    {-164491200 -10800 1 -0300}
    {-152658000 -14400 0 -0400}
    {-132955200 -10800 1 -0300}
    {-121122000 -14400 0 -0400}
    {-101419200 -10800 1 -0300}
    {-86821200 -14400 0 -0400}
    {-71092800 -10800 1 -0300}
    {-54766800 -14400 0 -0400}
    {-39038400 -10800 1 -0300}
    {-23317200 -14400 0 -0400}
    {-7588800 -10800 0 -0300}
    {128142000 -7200 1 -0200}
    {136605600 -10800 0 -0300}
    {596948400 -7200 1 -0200}
    {605066400 -10800 0 -0300}
    {624423600 -7200 1 -0200}
    {636516000 -10800 0 -0300}
    {656478000 -7200 1 -0200}
    {667965600 -14400 0 -0400}
    {687931200 -7200 0 -0200}
    {699415200 -10800 0 -0300}
    {719377200 -7200 1 -0200}
    {731469600 -10800 0 -0300}
    {938916000 -10800 0 -0300}
    {938919600 -10800 1 -0300}
    {952056000 -10800 0 -0300}
    {1198983600 -7200 1 -0200}
    {1205632800 -10800 0 -0300}
    {1224295200 -10800 0 -0300}
}

Changes to library/tzdata/America/Argentina/San_Juan.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Argentina/San_Juan) {
    {-9223372036854775808 -16444 0 LMT}
    {-2372095556 -15408 0 CMT}
    {-1567453392 -14400 0 -04}
    {-1233432000 -10800 0 -04}
    {-1222981200 -14400 0 -04}
    {-1205956800 -10800 1 -04}
    {-1194037200 -14400 0 -04}
    {-1172865600 -10800 1 -04}
    {-1162501200 -14400 0 -04}
    {-1141329600 -10800 1 -04}
    {-1130965200 -14400 0 -04}
    {-1109793600 -10800 1 -04}
    {-1099429200 -14400 0 -04}
    {-1078257600 -10800 1 -04}
    {-1067806800 -14400 0 -04}
    {-1046635200 -10800 1 -04}
    {-1036270800 -14400 0 -04}
    {-1015099200 -10800 1 -04}
    {-1004734800 -14400 0 -04}
    {-983563200 -10800 1 -04}
    {-973198800 -14400 0 -04}
    {-952027200 -10800 1 -04}
    {-941576400 -14400 0 -04}
    {-931032000 -10800 1 -04}
    {-900882000 -14400 0 -04}
    {-890337600 -10800 1 -04}
    {-833749200 -14400 0 -04}
    {-827265600 -10800 1 -04}
    {-752274000 -14400 0 -04}
    {-733780800 -10800 1 -04}
    {-197326800 -14400 0 -04}
    {-190843200 -10800 1 -04}
    {-184194000 -14400 0 -04}
    {-164491200 -10800 1 -04}
    {-152658000 -14400 0 -04}
    {-132955200 -10800 1 -04}
    {-121122000 -14400 0 -04}
    {-101419200 -10800 1 -04}
    {-86821200 -14400 0 -04}
    {-71092800 -10800 1 -04}
    {-54766800 -14400 0 -04}
    {-39038400 -10800 1 -04}
    {-23317200 -14400 0 -04}
    {-7588800 -10800 0 -03}
    {128142000 -7200 1 -03}
    {136605600 -10800 0 -03}
    {596948400 -7200 1 -03}
    {605066400 -10800 0 -03}
    {624423600 -7200 1 -03}
    {636516000 -10800 0 -03}
    {656478000 -7200 1 -03}
    {667792800 -14400 0 -04}
    {673588800 -10800 0 -03}
    {687927600 -7200 1 -03}
    {699415200 -10800 0 -03}
    {719377200 -7200 1 -03}
    {731469600 -10800 0 -03}
    {938916000 -10800 0 -04}
    {938919600 -10800 1 -04}
    {952056000 -10800 0 -03}
    {1085972400 -14400 0 -04}
    {1090728000 -10800 0 -03}
    {1198983600 -7200 1 -03}
    {1205632800 -10800 0 -03}
    {1224295200 -10800 0 -03}
    {-1567453392 -14400 0 -0400}
    {-1233432000 -10800 0 -0300}
    {-1222981200 -14400 0 -0400}
    {-1205956800 -10800 1 -0300}
    {-1194037200 -14400 0 -0400}
    {-1172865600 -10800 1 -0300}
    {-1162501200 -14400 0 -0400}
    {-1141329600 -10800 1 -0300}
    {-1130965200 -14400 0 -0400}
    {-1109793600 -10800 1 -0300}
    {-1099429200 -14400 0 -0400}
    {-1078257600 -10800 1 -0300}
    {-1067806800 -14400 0 -0400}
    {-1046635200 -10800 1 -0300}
    {-1036270800 -14400 0 -0400}
    {-1015099200 -10800 1 -0300}
    {-1004734800 -14400 0 -0400}
    {-983563200 -10800 1 -0300}
    {-973198800 -14400 0 -0400}
    {-952027200 -10800 1 -0300}
    {-941576400 -14400 0 -0400}
    {-931032000 -10800 1 -0300}
    {-900882000 -14400 0 -0400}
    {-890337600 -10800 1 -0300}
    {-833749200 -14400 0 -0400}
    {-827265600 -10800 1 -0300}
    {-752274000 -14400 0 -0400}
    {-733780800 -10800 1 -0300}
    {-197326800 -14400 0 -0400}
    {-190843200 -10800 1 -0300}
    {-184194000 -14400 0 -0400}
    {-164491200 -10800 1 -0300}
    {-152658000 -14400 0 -0400}
    {-132955200 -10800 1 -0300}
    {-121122000 -14400 0 -0400}
    {-101419200 -10800 1 -0300}
    {-86821200 -14400 0 -0400}
    {-71092800 -10800 1 -0300}
    {-54766800 -14400 0 -0400}
    {-39038400 -10800 1 -0300}
    {-23317200 -14400 0 -0400}
    {-7588800 -10800 0 -0300}
    {128142000 -7200 1 -0200}
    {136605600 -10800 0 -0300}
    {596948400 -7200 1 -0200}
    {605066400 -10800 0 -0300}
    {624423600 -7200 1 -0200}
    {636516000 -10800 0 -0300}
    {656478000 -7200 1 -0200}
    {667792800 -14400 0 -0400}
    {673588800 -10800 0 -0300}
    {687927600 -7200 1 -0200}
    {699415200 -10800 0 -0300}
    {719377200 -7200 1 -0200}
    {731469600 -10800 0 -0300}
    {938916000 -10800 0 -0300}
    {938919600 -10800 1 -0300}
    {952056000 -10800 0 -0300}
    {1085972400 -14400 0 -0400}
    {1090728000 -10800 0 -0300}
    {1198983600 -7200 1 -0200}
    {1205632800 -10800 0 -0300}
    {1224295200 -10800 0 -0300}
}

Changes to library/tzdata/America/Argentina/San_Luis.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Argentina/San_Luis) {
    {-9223372036854775808 -15924 0 LMT}
    {-2372096076 -15408 0 CMT}
    {-1567453392 -14400 0 -04}
    {-1233432000 -10800 0 -04}
    {-1222981200 -14400 0 -04}
    {-1205956800 -10800 1 -04}
    {-1194037200 -14400 0 -04}
    {-1172865600 -10800 1 -04}
    {-1162501200 -14400 0 -04}
    {-1141329600 -10800 1 -04}
    {-1130965200 -14400 0 -04}
    {-1109793600 -10800 1 -04}
    {-1099429200 -14400 0 -04}
    {-1078257600 -10800 1 -04}
    {-1067806800 -14400 0 -04}
    {-1046635200 -10800 1 -04}
    {-1036270800 -14400 0 -04}
    {-1015099200 -10800 1 -04}
    {-1004734800 -14400 0 -04}
    {-983563200 -10800 1 -04}
    {-973198800 -14400 0 -04}
    {-952027200 -10800 1 -04}
    {-941576400 -14400 0 -04}
    {-931032000 -10800 1 -04}
    {-900882000 -14400 0 -04}
    {-890337600 -10800 1 -04}
    {-833749200 -14400 0 -04}
    {-827265600 -10800 1 -04}
    {-752274000 -14400 0 -04}
    {-733780800 -10800 1 -04}
    {-197326800 -14400 0 -04}
    {-190843200 -10800 1 -04}
    {-184194000 -14400 0 -04}
    {-164491200 -10800 1 -04}
    {-152658000 -14400 0 -04}
    {-132955200 -10800 1 -04}
    {-121122000 -14400 0 -04}
    {-101419200 -10800 1 -04}
    {-86821200 -14400 0 -04}
    {-71092800 -10800 1 -04}
    {-54766800 -14400 0 -04}
    {-39038400 -10800 1 -04}
    {-23317200 -14400 0 -04}
    {-7588800 -10800 0 -03}
    {128142000 -7200 1 -03}
    {136605600 -10800 0 -03}
    {596948400 -7200 1 -03}
    {605066400 -10800 0 -03}
    {624423600 -7200 1 -03}
    {631159200 -7200 1 -02}
    {637380000 -14400 0 -04}
    {655963200 -10800 1 -03}
    {667796400 -14400 0 -04}
    {675748800 -10800 0 -03}
    {938919600 -10800 1 -03}
    {952052400 -10800 0 -03}
    {1085972400 -14400 0 -04}
    {1090728000 -10800 0 -03}
    {1198983600 -7200 1 -03}
    {1200880800 -10800 0 -04}
    {1205031600 -14400 0 -04}
    {1223784000 -10800 1 -04}
    {1236481200 -14400 0 -04}
    {1255233600 -10800 0 -03}
    {-1567453392 -14400 0 -0400}
    {-1233432000 -10800 0 -0300}
    {-1222981200 -14400 0 -0400}
    {-1205956800 -10800 1 -0300}
    {-1194037200 -14400 0 -0400}
    {-1172865600 -10800 1 -0300}
    {-1162501200 -14400 0 -0400}
    {-1141329600 -10800 1 -0300}
    {-1130965200 -14400 0 -0400}
    {-1109793600 -10800 1 -0300}
    {-1099429200 -14400 0 -0400}
    {-1078257600 -10800 1 -0300}
    {-1067806800 -14400 0 -0400}
    {-1046635200 -10800 1 -0300}
    {-1036270800 -14400 0 -0400}
    {-1015099200 -10800 1 -0300}
    {-1004734800 -14400 0 -0400}
    {-983563200 -10800 1 -0300}
    {-973198800 -14400 0 -0400}
    {-952027200 -10800 1 -0300}
    {-941576400 -14400 0 -0400}
    {-931032000 -10800 1 -0300}
    {-900882000 -14400 0 -0400}
    {-890337600 -10800 1 -0300}
    {-833749200 -14400 0 -0400}
    {-827265600 -10800 1 -0300}
    {-752274000 -14400 0 -0400}
    {-733780800 -10800 1 -0300}
    {-197326800 -14400 0 -0400}
    {-190843200 -10800 1 -0300}
    {-184194000 -14400 0 -0400}
    {-164491200 -10800 1 -0300}
    {-152658000 -14400 0 -0400}
    {-132955200 -10800 1 -0300}
    {-121122000 -14400 0 -0400}
    {-101419200 -10800 1 -0300}
    {-86821200 -14400 0 -0400}
    {-71092800 -10800 1 -0300}
    {-54766800 -14400 0 -0400}
    {-39038400 -10800 1 -0300}
    {-23317200 -14400 0 -0400}
    {-7588800 -10800 0 -0300}
    {128142000 -7200 1 -0200}
    {136605600 -10800 0 -0300}
    {596948400 -7200 1 -0200}
    {605066400 -10800 0 -0300}
    {624423600 -7200 1 -0200}
    {631159200 -7200 1 -0200}
    {637380000 -14400 0 -0400}
    {655963200 -10800 1 -0300}
    {667796400 -14400 0 -0400}
    {675748800 -10800 0 -0300}
    {938919600 -10800 1 -0300}
    {952052400 -10800 0 -0300}
    {1085972400 -14400 0 -0400}
    {1090728000 -10800 0 -0300}
    {1198983600 -7200 1 -0200}
    {1200880800 -10800 0 -0300}
    {1205031600 -14400 0 -0400}
    {1223784000 -10800 1 -0300}
    {1236481200 -14400 0 -0400}
    {1255233600 -10800 0 -0300}
}

Changes to library/tzdata/America/Argentina/Tucuman.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Argentina/Tucuman) {
    {-9223372036854775808 -15652 0 LMT}
    {-2372096348 -15408 0 CMT}
    {-1567453392 -14400 0 -04}
    {-1233432000 -10800 0 -04}
    {-1222981200 -14400 0 -04}
    {-1205956800 -10800 1 -04}
    {-1194037200 -14400 0 -04}
    {-1172865600 -10800 1 -04}
    {-1162501200 -14400 0 -04}
    {-1141329600 -10800 1 -04}
    {-1130965200 -14400 0 -04}
    {-1109793600 -10800 1 -04}
    {-1099429200 -14400 0 -04}
    {-1078257600 -10800 1 -04}
    {-1067806800 -14400 0 -04}
    {-1046635200 -10800 1 -04}
    {-1036270800 -14400 0 -04}
    {-1015099200 -10800 1 -04}
    {-1004734800 -14400 0 -04}
    {-983563200 -10800 1 -04}
    {-973198800 -14400 0 -04}
    {-952027200 -10800 1 -04}
    {-941576400 -14400 0 -04}
    {-931032000 -10800 1 -04}
    {-900882000 -14400 0 -04}
    {-890337600 -10800 1 -04}
    {-833749200 -14400 0 -04}
    {-827265600 -10800 1 -04}
    {-752274000 -14400 0 -04}
    {-733780800 -10800 1 -04}
    {-197326800 -14400 0 -04}
    {-190843200 -10800 1 -04}
    {-184194000 -14400 0 -04}
    {-164491200 -10800 1 -04}
    {-152658000 -14400 0 -04}
    {-132955200 -10800 1 -04}
    {-121122000 -14400 0 -04}
    {-101419200 -10800 1 -04}
    {-86821200 -14400 0 -04}
    {-71092800 -10800 1 -04}
    {-54766800 -14400 0 -04}
    {-39038400 -10800 1 -04}
    {-23317200 -14400 0 -04}
    {-7588800 -10800 0 -03}
    {128142000 -7200 1 -03}
    {136605600 -10800 0 -03}
    {596948400 -7200 1 -03}
    {605066400 -10800 0 -03}
    {624423600 -7200 1 -03}
    {636516000 -10800 0 -03}
    {656478000 -7200 1 -03}
    {667965600 -14400 0 -04}
    {687931200 -7200 0 -03}
    {699415200 -10800 0 -03}
    {719377200 -7200 1 -03}
    {731469600 -10800 0 -03}
    {938916000 -10800 0 -04}
    {938919600 -10800 1 -04}
    {952056000 -10800 0 -03}
    {1086058800 -14400 0 -04}
    {1087099200 -10800 0 -03}
    {1198983600 -7200 1 -03}
    {1205632800 -10800 0 -03}
    {1224385200 -7200 1 -03}
    {1237082400 -10800 0 -03}
    {-1567453392 -14400 0 -0400}
    {-1233432000 -10800 0 -0300}
    {-1222981200 -14400 0 -0400}
    {-1205956800 -10800 1 -0300}
    {-1194037200 -14400 0 -0400}
    {-1172865600 -10800 1 -0300}
    {-1162501200 -14400 0 -0400}
    {-1141329600 -10800 1 -0300}
    {-1130965200 -14400 0 -0400}
    {-1109793600 -10800 1 -0300}
    {-1099429200 -14400 0 -0400}
    {-1078257600 -10800 1 -0300}
    {-1067806800 -14400 0 -0400}
    {-1046635200 -10800 1 -0300}
    {-1036270800 -14400 0 -0400}
    {-1015099200 -10800 1 -0300}
    {-1004734800 -14400 0 -0400}
    {-983563200 -10800 1 -0300}
    {-973198800 -14400 0 -0400}
    {-952027200 -10800 1 -0300}
    {-941576400 -14400 0 -0400}
    {-931032000 -10800 1 -0300}
    {-900882000 -14400 0 -0400}
    {-890337600 -10800 1 -0300}
    {-833749200 -14400 0 -0400}
    {-827265600 -10800 1 -0300}
    {-752274000 -14400 0 -0400}
    {-733780800 -10800 1 -0300}
    {-197326800 -14400 0 -0400}
    {-190843200 -10800 1 -0300}
    {-184194000 -14400 0 -0400}
    {-164491200 -10800 1 -0300}
    {-152658000 -14400 0 -0400}
    {-132955200 -10800 1 -0300}
    {-121122000 -14400 0 -0400}
    {-101419200 -10800 1 -0300}
    {-86821200 -14400 0 -0400}
    {-71092800 -10800 1 -0300}
    {-54766800 -14400 0 -0400}
    {-39038400 -10800 1 -0300}
    {-23317200 -14400 0 -0400}
    {-7588800 -10800 0 -0300}
    {128142000 -7200 1 -0200}
    {136605600 -10800 0 -0300}
    {596948400 -7200 1 -0200}
    {605066400 -10800 0 -0300}
    {624423600 -7200 1 -0200}
    {636516000 -10800 0 -0300}
    {656478000 -7200 1 -0200}
    {667965600 -14400 0 -0400}
    {687931200 -7200 0 -0200}
    {699415200 -10800 0 -0300}
    {719377200 -7200 1 -0200}
    {731469600 -10800 0 -0300}
    {938916000 -10800 0 -0300}
    {938919600 -10800 1 -0300}
    {952056000 -10800 0 -0300}
    {1086058800 -14400 0 -0400}
    {1087099200 -10800 0 -0300}
    {1198983600 -7200 1 -0200}
    {1205632800 -10800 0 -0300}
    {1224385200 -7200 1 -0200}
    {1237082400 -10800 0 -0300}
}

Changes to library/tzdata/America/Argentina/Ushuaia.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Argentina/Ushuaia) {
    {-9223372036854775808 -16392 0 LMT}
    {-2372095608 -15408 0 CMT}
    {-1567453392 -14400 0 -04}
    {-1233432000 -10800 0 -04}
    {-1222981200 -14400 0 -04}
    {-1205956800 -10800 1 -04}
    {-1194037200 -14400 0 -04}
    {-1172865600 -10800 1 -04}
    {-1162501200 -14400 0 -04}
    {-1141329600 -10800 1 -04}
    {-1130965200 -14400 0 -04}
    {-1109793600 -10800 1 -04}
    {-1099429200 -14400 0 -04}
    {-1078257600 -10800 1 -04}
    {-1067806800 -14400 0 -04}
    {-1046635200 -10800 1 -04}
    {-1036270800 -14400 0 -04}
    {-1015099200 -10800 1 -04}
    {-1004734800 -14400 0 -04}
    {-983563200 -10800 1 -04}
    {-973198800 -14400 0 -04}
    {-952027200 -10800 1 -04}
    {-941576400 -14400 0 -04}
    {-931032000 -10800 1 -04}
    {-900882000 -14400 0 -04}
    {-890337600 -10800 1 -04}
    {-833749200 -14400 0 -04}
    {-827265600 -10800 1 -04}
    {-752274000 -14400 0 -04}
    {-733780800 -10800 1 -04}
    {-197326800 -14400 0 -04}
    {-190843200 -10800 1 -04}
    {-184194000 -14400 0 -04}
    {-164491200 -10800 1 -04}
    {-152658000 -14400 0 -04}
    {-132955200 -10800 1 -04}
    {-121122000 -14400 0 -04}
    {-101419200 -10800 1 -04}
    {-86821200 -14400 0 -04}
    {-71092800 -10800 1 -04}
    {-54766800 -14400 0 -04}
    {-39038400 -10800 1 -04}
    {-23317200 -14400 0 -04}
    {-7588800 -10800 0 -03}
    {128142000 -7200 1 -03}
    {136605600 -10800 0 -03}
    {596948400 -7200 1 -03}
    {605066400 -10800 0 -03}
    {624423600 -7200 1 -03}
    {636516000 -10800 0 -03}
    {656478000 -7200 1 -03}
    {667965600 -10800 0 -03}
    {687927600 -7200 1 -03}
    {699415200 -10800 0 -03}
    {719377200 -7200 1 -03}
    {731469600 -10800 0 -03}
    {938916000 -10800 0 -04}
    {938919600 -10800 1 -04}
    {952056000 -10800 0 -03}
    {1085886000 -14400 0 -04}
    {1087704000 -10800 0 -03}
    {1198983600 -7200 1 -03}
    {1205632800 -10800 0 -03}
    {1224295200 -10800 0 -03}
    {-1567453392 -14400 0 -0400}
    {-1233432000 -10800 0 -0300}
    {-1222981200 -14400 0 -0400}
    {-1205956800 -10800 1 -0300}
    {-1194037200 -14400 0 -0400}
    {-1172865600 -10800 1 -0300}
    {-1162501200 -14400 0 -0400}
    {-1141329600 -10800 1 -0300}
    {-1130965200 -14400 0 -0400}
    {-1109793600 -10800 1 -0300}
    {-1099429200 -14400 0 -0400}
    {-1078257600 -10800 1 -0300}
    {-1067806800 -14400 0 -0400}
    {-1046635200 -10800 1 -0300}
    {-1036270800 -14400 0 -0400}
    {-1015099200 -10800 1 -0300}
    {-1004734800 -14400 0 -0400}
    {-983563200 -10800 1 -0300}
    {-973198800 -14400 0 -0400}
    {-952027200 -10800 1 -0300}
    {-941576400 -14400 0 -0400}
    {-931032000 -10800 1 -0300}
    {-900882000 -14400 0 -0400}
    {-890337600 -10800 1 -0300}
    {-833749200 -14400 0 -0400}
    {-827265600 -10800 1 -0300}
    {-752274000 -14400 0 -0400}
    {-733780800 -10800 1 -0300}
    {-197326800 -14400 0 -0400}
    {-190843200 -10800 1 -0300}
    {-184194000 -14400 0 -0400}
    {-164491200 -10800 1 -0300}
    {-152658000 -14400 0 -0400}
    {-132955200 -10800 1 -0300}
    {-121122000 -14400 0 -0400}
    {-101419200 -10800 1 -0300}
    {-86821200 -14400 0 -0400}
    {-71092800 -10800 1 -0300}
    {-54766800 -14400 0 -0400}
    {-39038400 -10800 1 -0300}
    {-23317200 -14400 0 -0400}
    {-7588800 -10800 0 -0300}
    {128142000 -7200 1 -0200}
    {136605600 -10800 0 -0300}
    {596948400 -7200 1 -0200}
    {605066400 -10800 0 -0300}
    {624423600 -7200 1 -0200}
    {636516000 -10800 0 -0300}
    {656478000 -7200 1 -0200}
    {667965600 -10800 0 -0300}
    {687927600 -7200 1 -0200}
    {699415200 -10800 0 -0300}
    {719377200 -7200 1 -0200}
    {731469600 -10800 0 -0300}
    {938916000 -10800 0 -0300}
    {938919600 -10800 1 -0300}
    {952056000 -10800 0 -0300}
    {1085886000 -14400 0 -0400}
    {1087704000 -10800 0 -0300}
    {1198983600 -7200 1 -0200}
    {1205632800 -10800 0 -0300}
    {1224295200 -10800 0 -0300}
}

Changes to library/tzdata/America/Aruba.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Curacao)]} {
    LoadTimeZoneFile America/Curacao
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Aruba) $TZData(:America/Curacao)
set TZData(:America/Aruba) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Asuncion.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Asuncion) {
    {-9223372036854775808 -13840 0 LMT}
    {-2524507760 -13840 0 AMT}
    {-1206389360 -14400 0 -04}
    {86760000 -10800 0 -03}
    {134017200 -14400 0 -04}
    {162878400 -14400 0 -04}
    {181368000 -10800 1 -04}
    {194497200 -14400 0 -04}
    {212990400 -10800 1 -04}
    {226033200 -14400 0 -04}
    {244526400 -10800 1 -04}
    {257569200 -14400 0 -04}
    {276062400 -10800 1 -04}
    {291783600 -14400 0 -04}
    {307598400 -10800 1 -04}
    {323406000 -14400 0 -04}
    {339220800 -10800 1 -04}
    {354942000 -14400 0 -04}
    {370756800 -10800 1 -04}
    {386478000 -14400 0 -04}
    {402292800 -10800 1 -04}
    {418014000 -14400 0 -04}
    {433828800 -10800 1 -04}
    {449636400 -14400 0 -04}
    {465451200 -10800 1 -04}
    {481172400 -14400 0 -04}
    {496987200 -10800 1 -04}
    {512708400 -14400 0 -04}
    {528523200 -10800 1 -04}
    {544244400 -14400 0 -04}
    {560059200 -10800 1 -04}
    {575866800 -14400 0 -04}
    {591681600 -10800 1 -04}
    {607402800 -14400 0 -04}
    {625032000 -10800 1 -04}
    {638938800 -14400 0 -04}
    {654753600 -10800 1 -04}
    {670474800 -14400 0 -04}
    {686721600 -10800 1 -04}
    {699418800 -14400 0 -04}
    {718257600 -10800 1 -04}
    {733546800 -14400 0 -04}
    {749448000 -10800 1 -04}
    {762318000 -14400 0 -04}
    {780984000 -10800 1 -04}
    {793767600 -14400 0 -04}
    {812520000 -10800 1 -04}
    {825649200 -14400 0 -04}
    {844574400 -10800 1 -04}
    {856666800 -14400 0 -04}
    {876024000 -10800 1 -04}
    {888721200 -14400 0 -04}
    {907473600 -10800 1 -04}
    {920775600 -14400 0 -04}
    {938923200 -10800 1 -04}
    {952225200 -14400 0 -04}
    {970372800 -10800 1 -04}
    {983674800 -14400 0 -04}
    {1002427200 -10800 1 -04}
    {1018148400 -14400 0 -04}
    {1030852800 -10800 1 -04}
    {1049598000 -14400 0 -04}
    {1062907200 -10800 1 -04}
    {1081047600 -14400 0 -04}
    {1097985600 -10800 1 -04}
    {1110682800 -14400 0 -04}
    {1129435200 -10800 1 -04}
    {1142132400 -14400 0 -04}
    {1160884800 -10800 1 -04}
    {1173582000 -14400 0 -04}
    {1192939200 -10800 1 -04}
    {1205031600 -14400 0 -04}
    {1224388800 -10800 1 -04}
    {1236481200 -14400 0 -04}
    {1255838400 -10800 1 -04}
    {1270954800 -14400 0 -04}
    {1286078400 -10800 1 -04}
    {1302404400 -14400 0 -04}
    {1317528000 -10800 1 -04}
    {1333854000 -14400 0 -04}
    {1349582400 -10800 1 -04}
    {1364094000 -14400 0 -04}
    {1381032000 -10800 1 -04}
    {1395543600 -14400 0 -04}
    {1412481600 -10800 1 -04}
    {1426993200 -14400 0 -04}
    {1443931200 -10800 1 -04}
    {1459047600 -14400 0 -04}
    {1475380800 -10800 1 -04}
    {1490497200 -14400 0 -04}
    {1506830400 -10800 1 -04}
    {1521946800 -14400 0 -04}
    {1538884800 -10800 1 -04}
    {1553396400 -14400 0 -04}
    {1570334400 -10800 1 -04}
    {1584846000 -14400 0 -04}
    {1601784000 -10800 1 -04}
    {1616900400 -14400 0 -04}
    {1633233600 -10800 1 -04}
    {1648350000 -14400 0 -04}
    {1664683200 -10800 1 -04}
    {1679799600 -14400 0 -04}
    {1696132800 -10800 1 -04}
    {1711249200 -14400 0 -04}
    {1728187200 -10800 1 -04}
    {1742698800 -14400 0 -04}
    {1759636800 -10800 1 -04}
    {1774148400 -14400 0 -04}
    {1791086400 -10800 1 -04}
    {1806202800 -14400 0 -04}
    {1822536000 -10800 1 -04}
    {1837652400 -14400 0 -04}
    {1853985600 -10800 1 -04}
    {1869102000 -14400 0 -04}
    {1886040000 -10800 1 -04}
    {1900551600 -14400 0 -04}
    {1917489600 -10800 1 -04}
    {1932001200 -14400 0 -04}
    {1948939200 -10800 1 -04}
    {1964055600 -14400 0 -04}
    {1980388800 -10800 1 -04}
    {1995505200 -14400 0 -04}
    {2011838400 -10800 1 -04}
    {2026954800 -14400 0 -04}
    {2043288000 -10800 1 -04}
    {2058404400 -14400 0 -04}
    {2075342400 -10800 1 -04}
    {2089854000 -14400 0 -04}
    {2106792000 -10800 1 -04}
    {2121303600 -14400 0 -04}
    {2138241600 -10800 1 -04}
    {2153358000 -14400 0 -04}
    {2169691200 -10800 1 -04}
    {2184807600 -14400 0 -04}
    {2201140800 -10800 1 -04}
    {2216257200 -14400 0 -04}
    {2233195200 -10800 1 -04}
    {2247706800 -14400 0 -04}
    {2264644800 -10800 1 -04}
    {2279156400 -14400 0 -04}
    {2296094400 -10800 1 -04}
    {2310606000 -14400 0 -04}
    {2327544000 -10800 1 -04}
    {2342660400 -14400 0 -04}
    {2358993600 -10800 1 -04}
    {2374110000 -14400 0 -04}
    {2390443200 -10800 1 -04}
    {2405559600 -14400 0 -04}
    {2422497600 -10800 1 -04}
    {2437009200 -14400 0 -04}
    {2453947200 -10800 1 -04}
    {2468458800 -14400 0 -04}
    {2485396800 -10800 1 -04}
    {2500513200 -14400 0 -04}
    {2516846400 -10800 1 -04}
    {2531962800 -14400 0 -04}
    {2548296000 -10800 1 -04}
    {2563412400 -14400 0 -04}
    {2579745600 -10800 1 -04}
    {2594862000 -14400 0 -04}
    {2611800000 -10800 1 -04}
    {2626311600 -14400 0 -04}
    {2643249600 -10800 1 -04}
    {2657761200 -14400 0 -04}
    {2674699200 -10800 1 -04}
    {2689815600 -14400 0 -04}
    {2706148800 -10800 1 -04}
    {2721265200 -14400 0 -04}
    {2737598400 -10800 1 -04}
    {2752714800 -14400 0 -04}
    {2769652800 -10800 1 -04}
    {2784164400 -14400 0 -04}
    {2801102400 -10800 1 -04}
    {2815614000 -14400 0 -04}
    {2832552000 -10800 1 -04}
    {2847668400 -14400 0 -04}
    {2864001600 -10800 1 -04}
    {2879118000 -14400 0 -04}
    {2895451200 -10800 1 -04}
    {2910567600 -14400 0 -04}
    {2926900800 -10800 1 -04}
    {2942017200 -14400 0 -04}
    {2958955200 -10800 1 -04}
    {2973466800 -14400 0 -04}
    {2990404800 -10800 1 -04}
    {3004916400 -14400 0 -04}
    {3021854400 -10800 1 -04}
    {3036970800 -14400 0 -04}
    {3053304000 -10800 1 -04}
    {3068420400 -14400 0 -04}
    {3084753600 -10800 1 -04}
    {3099870000 -14400 0 -04}
    {3116808000 -10800 1 -04}
    {3131319600 -14400 0 -04}
    {3148257600 -10800 1 -04}
    {3162769200 -14400 0 -04}
    {3179707200 -10800 1 -04}
    {3194218800 -14400 0 -04}
    {3211156800 -10800 1 -04}
    {3226273200 -14400 0 -04}
    {3242606400 -10800 1 -04}
    {3257722800 -14400 0 -04}
    {3274056000 -10800 1 -04}
    {3289172400 -14400 0 -04}
    {3306110400 -10800 1 -04}
    {3320622000 -14400 0 -04}
    {3337560000 -10800 1 -04}
    {3352071600 -14400 0 -04}
    {3369009600 -10800 1 -04}
    {3384126000 -14400 0 -04}
    {3400459200 -10800 1 -04}
    {3415575600 -14400 0 -04}
    {3431908800 -10800 1 -04}
    {3447025200 -14400 0 -04}
    {3463358400 -10800 1 -04}
    {3478474800 -14400 0 -04}
    {3495412800 -10800 1 -04}
    {3509924400 -14400 0 -04}
    {3526862400 -10800 1 -04}
    {3541374000 -14400 0 -04}
    {3558312000 -10800 1 -04}
    {3573428400 -14400 0 -04}
    {3589761600 -10800 1 -04}
    {3604878000 -14400 0 -04}
    {3621211200 -10800 1 -04}
    {3636327600 -14400 0 -04}
    {3653265600 -10800 1 -04}
    {3667777200 -14400 0 -04}
    {3684715200 -10800 1 -04}
    {3699226800 -14400 0 -04}
    {3716164800 -10800 1 -04}
    {3731281200 -14400 0 -04}
    {3747614400 -10800 1 -04}
    {3762730800 -14400 0 -04}
    {3779064000 -10800 1 -04}
    {3794180400 -14400 0 -04}
    {3810513600 -10800 1 -04}
    {3825630000 -14400 0 -04}
    {3842568000 -10800 1 -04}
    {3857079600 -14400 0 -04}
    {3874017600 -10800 1 -04}
    {3888529200 -14400 0 -04}
    {3905467200 -10800 1 -04}
    {3920583600 -14400 0 -04}
    {3936916800 -10800 1 -04}
    {3952033200 -14400 0 -04}
    {3968366400 -10800 1 -04}
    {3983482800 -14400 0 -04}
    {4000420800 -10800 1 -04}
    {4014932400 -14400 0 -04}
    {4031870400 -10800 1 -04}
    {4046382000 -14400 0 -04}
    {4063320000 -10800 1 -04}
    {4077831600 -14400 0 -04}
    {4094769600 -10800 1 -04}
    {-1206389360 -14400 0 -0400}
    {86760000 -10800 0 -0300}
    {134017200 -14400 0 -0400}
    {162878400 -14400 0 -0400}
    {181368000 -10800 1 -0300}
    {194497200 -14400 0 -0400}
    {212990400 -10800 1 -0300}
    {226033200 -14400 0 -0400}
    {244526400 -10800 1 -0300}
    {257569200 -14400 0 -0400}
    {276062400 -10800 1 -0300}
    {291783600 -14400 0 -0400}
    {307598400 -10800 1 -0300}
    {323406000 -14400 0 -0400}
    {339220800 -10800 1 -0300}
    {354942000 -14400 0 -0400}
    {370756800 -10800 1 -0300}
    {386478000 -14400 0 -0400}
    {402292800 -10800 1 -0300}
    {418014000 -14400 0 -0400}
    {433828800 -10800 1 -0300}
    {449636400 -14400 0 -0400}
    {465451200 -10800 1 -0300}
    {481172400 -14400 0 -0400}
    {496987200 -10800 1 -0300}
    {512708400 -14400 0 -0400}
    {528523200 -10800 1 -0300}
    {544244400 -14400 0 -0400}
    {560059200 -10800 1 -0300}
    {575866800 -14400 0 -0400}
    {591681600 -10800 1 -0300}
    {607402800 -14400 0 -0400}
    {625032000 -10800 1 -0300}
    {638938800 -14400 0 -0400}
    {654753600 -10800 1 -0300}
    {670474800 -14400 0 -0400}
    {686721600 -10800 1 -0300}
    {699418800 -14400 0 -0400}
    {718257600 -10800 1 -0300}
    {733546800 -14400 0 -0400}
    {749448000 -10800 1 -0300}
    {762318000 -14400 0 -0400}
    {780984000 -10800 1 -0300}
    {793767600 -14400 0 -0400}
    {812520000 -10800 1 -0300}
    {825649200 -14400 0 -0400}
    {844574400 -10800 1 -0300}
    {856666800 -14400 0 -0400}
    {876024000 -10800 1 -0300}
    {888721200 -14400 0 -0400}
    {907473600 -10800 1 -0300}
    {920775600 -14400 0 -0400}
    {938923200 -10800 1 -0300}
    {952225200 -14400 0 -0400}
    {970372800 -10800 1 -0300}
    {983674800 -14400 0 -0400}
    {1002427200 -10800 1 -0300}
    {1018148400 -14400 0 -0400}
    {1030852800 -10800 1 -0300}
    {1049598000 -14400 0 -0400}
    {1062907200 -10800 1 -0300}
    {1081047600 -14400 0 -0400}
    {1097985600 -10800 1 -0300}
    {1110682800 -14400 0 -0400}
    {1129435200 -10800 1 -0300}
    {1142132400 -14400 0 -0400}
    {1160884800 -10800 1 -0300}
    {1173582000 -14400 0 -0400}
    {1192939200 -10800 1 -0300}
    {1205031600 -14400 0 -0400}
    {1224388800 -10800 1 -0300}
    {1236481200 -14400 0 -0400}
    {1255838400 -10800 1 -0300}
    {1270954800 -14400 0 -0400}
    {1286078400 -10800 1 -0300}
    {1302404400 -14400 0 -0400}
    {1317528000 -10800 1 -0300}
    {1333854000 -14400 0 -0400}
    {1349582400 -10800 1 -0300}
    {1364094000 -14400 0 -0400}
    {1381032000 -10800 1 -0300}
    {1395543600 -14400 0 -0400}
    {1412481600 -10800 1 -0300}
    {1426993200 -14400 0 -0400}
    {1443931200 -10800 1 -0300}
    {1459047600 -14400 0 -0400}
    {1475380800 -10800 1 -0300}
    {1490497200 -14400 0 -0400}
    {1506830400 -10800 1 -0300}
    {1521946800 -14400 0 -0400}
    {1538884800 -10800 1 -0300}
    {1553396400 -14400 0 -0400}
    {1570334400 -10800 1 -0300}
    {1584846000 -14400 0 -0400}
    {1601784000 -10800 1 -0300}
    {1616900400 -14400 0 -0400}
    {1633233600 -10800 1 -0300}
    {1648350000 -14400 0 -0400}
    {1664683200 -10800 1 -0300}
    {1679799600 -14400 0 -0400}
    {1696132800 -10800 1 -0300}
    {1711249200 -14400 0 -0400}
    {1728187200 -10800 1 -0300}
    {1742698800 -14400 0 -0400}
    {1759636800 -10800 1 -0300}
    {1774148400 -14400 0 -0400}
    {1791086400 -10800 1 -0300}
    {1806202800 -14400 0 -0400}
    {1822536000 -10800 1 -0300}
    {1837652400 -14400 0 -0400}
    {1853985600 -10800 1 -0300}
    {1869102000 -14400 0 -0400}
    {1886040000 -10800 1 -0300}
    {1900551600 -14400 0 -0400}
    {1917489600 -10800 1 -0300}
    {1932001200 -14400 0 -0400}
    {1948939200 -10800 1 -0300}
    {1964055600 -14400 0 -0400}
    {1980388800 -10800 1 -0300}
    {1995505200 -14400 0 -0400}
    {2011838400 -10800 1 -0300}
    {2026954800 -14400 0 -0400}
    {2043288000 -10800 1 -0300}
    {2058404400 -14400 0 -0400}
    {2075342400 -10800 1 -0300}
    {2089854000 -14400 0 -0400}
    {2106792000 -10800 1 -0300}
    {2121303600 -14400 0 -0400}
    {2138241600 -10800 1 -0300}
    {2153358000 -14400 0 -0400}
    {2169691200 -10800 1 -0300}
    {2184807600 -14400 0 -0400}
    {2201140800 -10800 1 -0300}
    {2216257200 -14400 0 -0400}
    {2233195200 -10800 1 -0300}
    {2247706800 -14400 0 -0400}
    {2264644800 -10800 1 -0300}
    {2279156400 -14400 0 -0400}
    {2296094400 -10800 1 -0300}
    {2310606000 -14400 0 -0400}
    {2327544000 -10800 1 -0300}
    {2342660400 -14400 0 -0400}
    {2358993600 -10800 1 -0300}
    {2374110000 -14400 0 -0400}
    {2390443200 -10800 1 -0300}
    {2405559600 -14400 0 -0400}
    {2422497600 -10800 1 -0300}
    {2437009200 -14400 0 -0400}
    {2453947200 -10800 1 -0300}
    {2468458800 -14400 0 -0400}
    {2485396800 -10800 1 -0300}
    {2500513200 -14400 0 -0400}
    {2516846400 -10800 1 -0300}
    {2531962800 -14400 0 -0400}
    {2548296000 -10800 1 -0300}
    {2563412400 -14400 0 -0400}
    {2579745600 -10800 1 -0300}
    {2594862000 -14400 0 -0400}
    {2611800000 -10800 1 -0300}
    {2626311600 -14400 0 -0400}
    {2643249600 -10800 1 -0300}
    {2657761200 -14400 0 -0400}
    {2674699200 -10800 1 -0300}
    {2689815600 -14400 0 -0400}
    {2706148800 -10800 1 -0300}
    {2721265200 -14400 0 -0400}
    {2737598400 -10800 1 -0300}
    {2752714800 -14400 0 -0400}
    {2769652800 -10800 1 -0300}
    {2784164400 -14400 0 -0400}
    {2801102400 -10800 1 -0300}
    {2815614000 -14400 0 -0400}
    {2832552000 -10800 1 -0300}
    {2847668400 -14400 0 -0400}
    {2864001600 -10800 1 -0300}
    {2879118000 -14400 0 -0400}
    {2895451200 -10800 1 -0300}
    {2910567600 -14400 0 -0400}
    {2926900800 -10800 1 -0300}
    {2942017200 -14400 0 -0400}
    {2958955200 -10800 1 -0300}
    {2973466800 -14400 0 -0400}
    {2990404800 -10800 1 -0300}
    {3004916400 -14400 0 -0400}
    {3021854400 -10800 1 -0300}
    {3036970800 -14400 0 -0400}
    {3053304000 -10800 1 -0300}
    {3068420400 -14400 0 -0400}
    {3084753600 -10800 1 -0300}
    {3099870000 -14400 0 -0400}
    {3116808000 -10800 1 -0300}
    {3131319600 -14400 0 -0400}
    {3148257600 -10800 1 -0300}
    {3162769200 -14400 0 -0400}
    {3179707200 -10800 1 -0300}
    {3194218800 -14400 0 -0400}
    {3211156800 -10800 1 -0300}
    {3226273200 -14400 0 -0400}
    {3242606400 -10800 1 -0300}
    {3257722800 -14400 0 -0400}
    {3274056000 -10800 1 -0300}
    {3289172400 -14400 0 -0400}
    {3306110400 -10800 1 -0300}
    {3320622000 -14400 0 -0400}
    {3337560000 -10800 1 -0300}
    {3352071600 -14400 0 -0400}
    {3369009600 -10800 1 -0300}
    {3384126000 -14400 0 -0400}
    {3400459200 -10800 1 -0300}
    {3415575600 -14400 0 -0400}
    {3431908800 -10800 1 -0300}
    {3447025200 -14400 0 -0400}
    {3463358400 -10800 1 -0300}
    {3478474800 -14400 0 -0400}
    {3495412800 -10800 1 -0300}
    {3509924400 -14400 0 -0400}
    {3526862400 -10800 1 -0300}
    {3541374000 -14400 0 -0400}
    {3558312000 -10800 1 -0300}
    {3573428400 -14400 0 -0400}
    {3589761600 -10800 1 -0300}
    {3604878000 -14400 0 -0400}
    {3621211200 -10800 1 -0300}
    {3636327600 -14400 0 -0400}
    {3653265600 -10800 1 -0300}
    {3667777200 -14400 0 -0400}
    {3684715200 -10800 1 -0300}
    {3699226800 -14400 0 -0400}
    {3716164800 -10800 1 -0300}
    {3731281200 -14400 0 -0400}
    {3747614400 -10800 1 -0300}
    {3762730800 -14400 0 -0400}
    {3779064000 -10800 1 -0300}
    {3794180400 -14400 0 -0400}
    {3810513600 -10800 1 -0300}
    {3825630000 -14400 0 -0400}
    {3842568000 -10800 1 -0300}
    {3857079600 -14400 0 -0400}
    {3874017600 -10800 1 -0300}
    {3888529200 -14400 0 -0400}
    {3905467200 -10800 1 -0300}
    {3920583600 -14400 0 -0400}
    {3936916800 -10800 1 -0300}
    {3952033200 -14400 0 -0400}
    {3968366400 -10800 1 -0300}
    {3983482800 -14400 0 -0400}
    {4000420800 -10800 1 -0300}
    {4014932400 -14400 0 -0400}
    {4031870400 -10800 1 -0300}
    {4046382000 -14400 0 -0400}
    {4063320000 -10800 1 -0300}
    {4077831600 -14400 0 -0400}
    {4094769600 -10800 1 -0300}
}

Changes to library/tzdata/America/Atikokan.

1


2
3


4
5
6
7
8
9
10
11
12
1
2
3


4
5










+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Panama)]} {
    LoadTimeZoneFile America/Panama

set TZData(:America/Atikokan) {
}
set TZData(:America/Atikokan) $TZData(:America/Panama)
    {-9223372036854775808 -21988 0 LMT}
    {-2366733212 -21600 0 CST}
    {-1632067200 -18000 1 CDT}
    {-1615136400 -21600 0 CST}
    {-923248800 -18000 1 CDT}
    {-880214400 -18000 0 CWT}
    {-769395600 -18000 1 CPT}
    {-765388800 -18000 0 EST}
}

Changes to library/tzdata/America/Bahia.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Bahia) {
    {-9223372036854775808 -9244 0 LMT}
    {-1767216356 -10800 0 -03}
    {-1206957600 -7200 1 -03}
    {-1191362400 -10800 0 -03}
    {-1175374800 -7200 1 -03}
    {-1159826400 -10800 0 -03}
    {-633819600 -7200 1 -03}
    {-622069200 -10800 0 -03}
    {-602283600 -7200 1 -03}
    {-591832800 -10800 0 -03}
    {-570747600 -7200 1 -03}
    {-560210400 -10800 0 -03}
    {-539125200 -7200 1 -03}
    {-531352800 -10800 0 -03}
    {-191365200 -7200 1 -03}
    {-184197600 -10800 0 -03}
    {-155163600 -7200 1 -03}
    {-150069600 -10800 0 -03}
    {-128898000 -7200 1 -03}
    {-121125600 -10800 0 -03}
    {-99954000 -7200 1 -03}
    {-89589600 -10800 0 -03}
    {-68418000 -7200 1 -03}
    {-57967200 -10800 0 -03}
    {499748400 -7200 1 -03}
    {511236000 -10800 0 -03}
    {530593200 -7200 1 -03}
    {540266400 -10800 0 -03}
    {562129200 -7200 1 -03}
    {571197600 -10800 0 -03}
    {592974000 -7200 1 -03}
    {602042400 -10800 0 -03}
    {624423600 -7200 1 -03}
    {634701600 -10800 0 -03}
    {656478000 -7200 1 -03}
    {666756000 -10800 0 -03}
    {687927600 -7200 1 -03}
    {697600800 -10800 0 -03}
    {719982000 -7200 1 -03}
    {728445600 -10800 0 -03}
    {750826800 -7200 1 -03}
    {761709600 -10800 0 -03}
    {782276400 -7200 1 -03}
    {793159200 -10800 0 -03}
    {813726000 -7200 1 -03}
    {824004000 -10800 0 -03}
    {844570800 -7200 1 -03}
    {856058400 -10800 0 -03}
    {876106800 -7200 1 -03}
    {888717600 -10800 0 -03}
    {908074800 -7200 1 -03}
    {919562400 -10800 0 -03}
    {938919600 -7200 1 -03}
    {951616800 -10800 0 -03}
    {970974000 -7200 1 -03}
    {982461600 -10800 0 -03}
    {1003028400 -7200 1 -03}
    {1013911200 -10800 0 -03}
    {1036292400 -7200 1 -03}
    {1045360800 -10800 0 -03}
    {1064368800 -10800 0 -03}
    {1318734000 -7200 0 -03}
    {1330221600 -10800 0 -03}
    {1350784800 -10800 0 -03}
    {-1767216356 -10800 0 -0300}
    {-1206957600 -7200 1 -0200}
    {-1191362400 -10800 0 -0300}
    {-1175374800 -7200 1 -0200}
    {-1159826400 -10800 0 -0300}
    {-633819600 -7200 1 -0200}
    {-622069200 -10800 0 -0300}
    {-602283600 -7200 1 -0200}
    {-591832800 -10800 0 -0300}
    {-570747600 -7200 1 -0200}
    {-560210400 -10800 0 -0300}
    {-539125200 -7200 1 -0200}
    {-531352800 -10800 0 -0300}
    {-191365200 -7200 1 -0200}
    {-184197600 -10800 0 -0300}
    {-155163600 -7200 1 -0200}
    {-150069600 -10800 0 -0300}
    {-128898000 -7200 1 -0200}
    {-121125600 -10800 0 -0300}
    {-99954000 -7200 1 -0200}
    {-89589600 -10800 0 -0300}
    {-68418000 -7200 1 -0200}
    {-57967200 -10800 0 -0300}
    {499748400 -7200 1 -0200}
    {511236000 -10800 0 -0300}
    {530593200 -7200 1 -0200}
    {540266400 -10800 0 -0300}
    {562129200 -7200 1 -0200}
    {571197600 -10800 0 -0300}
    {592974000 -7200 1 -0200}
    {602042400 -10800 0 -0300}
    {624423600 -7200 1 -0200}
    {634701600 -10800 0 -0300}
    {656478000 -7200 1 -0200}
    {666756000 -10800 0 -0300}
    {687927600 -7200 1 -0200}
    {697600800 -10800 0 -0300}
    {719982000 -7200 1 -0200}
    {728445600 -10800 0 -0300}
    {750826800 -7200 1 -0200}
    {761709600 -10800 0 -0300}
    {782276400 -7200 1 -0200}
    {793159200 -10800 0 -0300}
    {813726000 -7200 1 -0200}
    {824004000 -10800 0 -0300}
    {844570800 -7200 1 -0200}
    {856058400 -10800 0 -0300}
    {876106800 -7200 1 -0200}
    {888717600 -10800 0 -0300}
    {908074800 -7200 1 -0200}
    {919562400 -10800 0 -0300}
    {938919600 -7200 1 -0200}
    {951616800 -10800 0 -0300}
    {970974000 -7200 1 -0200}
    {982461600 -10800 0 -0300}
    {1003028400 -7200 1 -0200}
    {1013911200 -10800 0 -0300}
    {1036292400 -7200 1 -0200}
    {1045360800 -10800 0 -0300}
    {1064368800 -10800 0 -0300}
    {1318734000 -7200 0 -0200}
    {1330221600 -10800 0 -0300}
    {1350784800 -10800 0 -0300}
}

Changes to library/tzdata/America/Bahia_Banderas.

1
2
3
4
5
6

7
8

9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5

6
7

8
9
10
11


12
13
14
15
16
17
18
19





-
+

-
+



-
-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Bahia_Banderas) {
    {-9223372036854775808 -25260 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1343149200 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 0 CST}
    {-1220461200 -21600 1 MDT}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {-873828000 -25200 0 MST}
    {-661539600 -28800 0 PST}
    {28800 -25200 0 MST}
    {25200 -25200 0 MST}
    {828867600 -21600 1 MDT}
    {846403200 -25200 0 MST}
    {860317200 -21600 1 MDT}
    {877852800 -25200 0 MST}
    {891766800 -21600 1 MDT}
    {909302400 -25200 0 MST}
    {923216400 -21600 1 MDT}
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
60
61
62
63
64
65
66


























































































































































67







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

    {1572159600 -21600 0 CST}
    {1586073600 -18000 1 CDT}
    {1603609200 -21600 0 CST}
    {1617523200 -18000 1 CDT}
    {1635663600 -21600 0 CST}
    {1648972800 -18000 1 CDT}
    {1667113200 -21600 0 CST}
    {1680422400 -18000 1 CDT}
    {1698562800 -21600 0 CST}
    {1712476800 -18000 1 CDT}
    {1730012400 -21600 0 CST}
    {1743926400 -18000 1 CDT}
    {1761462000 -21600 0 CST}
    {1775376000 -18000 1 CDT}
    {1792911600 -21600 0 CST}
    {1806825600 -18000 1 CDT}
    {1824966000 -21600 0 CST}
    {1838275200 -18000 1 CDT}
    {1856415600 -21600 0 CST}
    {1869724800 -18000 1 CDT}
    {1887865200 -21600 0 CST}
    {1901779200 -18000 1 CDT}
    {1919314800 -21600 0 CST}
    {1933228800 -18000 1 CDT}
    {1950764400 -21600 0 CST}
    {1964678400 -18000 1 CDT}
    {1982818800 -21600 0 CST}
    {1996128000 -18000 1 CDT}
    {2014268400 -21600 0 CST}
    {2027577600 -18000 1 CDT}
    {2045718000 -21600 0 CST}
    {2059027200 -18000 1 CDT}
    {2077167600 -21600 0 CST}
    {2091081600 -18000 1 CDT}
    {2108617200 -21600 0 CST}
    {2122531200 -18000 1 CDT}
    {2140066800 -21600 0 CST}
    {2153980800 -18000 1 CDT}
    {2172121200 -21600 0 CST}
    {2185430400 -18000 1 CDT}
    {2203570800 -21600 0 CST}
    {2216880000 -18000 1 CDT}
    {2235020400 -21600 0 CST}
    {2248934400 -18000 1 CDT}
    {2266470000 -21600 0 CST}
    {2280384000 -18000 1 CDT}
    {2297919600 -21600 0 CST}
    {2311833600 -18000 1 CDT}
    {2329369200 -21600 0 CST}
    {2343283200 -18000 1 CDT}
    {2361423600 -21600 0 CST}
    {2374732800 -18000 1 CDT}
    {2392873200 -21600 0 CST}
    {2406182400 -18000 1 CDT}
    {2424322800 -21600 0 CST}
    {2438236800 -18000 1 CDT}
    {2455772400 -21600 0 CST}
    {2469686400 -18000 1 CDT}
    {2487222000 -21600 0 CST}
    {2501136000 -18000 1 CDT}
    {2519276400 -21600 0 CST}
    {2532585600 -18000 1 CDT}
    {2550726000 -21600 0 CST}
    {2564035200 -18000 1 CDT}
    {2582175600 -21600 0 CST}
    {2596089600 -18000 1 CDT}
    {2613625200 -21600 0 CST}
    {2627539200 -18000 1 CDT}
    {2645074800 -21600 0 CST}
    {2658988800 -18000 1 CDT}
    {2676524400 -21600 0 CST}
    {2690438400 -18000 1 CDT}
    {2708578800 -21600 0 CST}
    {2721888000 -18000 1 CDT}
    {2740028400 -21600 0 CST}
    {2753337600 -18000 1 CDT}
    {2771478000 -21600 0 CST}
    {2785392000 -18000 1 CDT}
    {2802927600 -21600 0 CST}
    {2816841600 -18000 1 CDT}
    {2834377200 -21600 0 CST}
    {2848291200 -18000 1 CDT}
    {2866431600 -21600 0 CST}
    {2879740800 -18000 1 CDT}
    {2897881200 -21600 0 CST}
    {2911190400 -18000 1 CDT}
    {2929330800 -21600 0 CST}
    {2942640000 -18000 1 CDT}
    {2960780400 -21600 0 CST}
    {2974694400 -18000 1 CDT}
    {2992230000 -21600 0 CST}
    {3006144000 -18000 1 CDT}
    {3023679600 -21600 0 CST}
    {3037593600 -18000 1 CDT}
    {3055734000 -21600 0 CST}
    {3069043200 -18000 1 CDT}
    {3087183600 -21600 0 CST}
    {3100492800 -18000 1 CDT}
    {3118633200 -21600 0 CST}
    {3132547200 -18000 1 CDT}
    {3150082800 -21600 0 CST}
    {3163996800 -18000 1 CDT}
    {3181532400 -21600 0 CST}
    {3195446400 -18000 1 CDT}
    {3212982000 -21600 0 CST}
    {3226896000 -18000 1 CDT}
    {3245036400 -21600 0 CST}
    {3258345600 -18000 1 CDT}
    {3276486000 -21600 0 CST}
    {3289795200 -18000 1 CDT}
    {3307935600 -21600 0 CST}
    {3321849600 -18000 1 CDT}
    {3339385200 -21600 0 CST}
    {3353299200 -18000 1 CDT}
    {3370834800 -21600 0 CST}
    {3384748800 -18000 1 CDT}
    {3402889200 -21600 0 CST}
    {3416198400 -18000 1 CDT}
    {3434338800 -21600 0 CST}
    {3447648000 -18000 1 CDT}
    {3465788400 -21600 0 CST}
    {3479702400 -18000 1 CDT}
    {3497238000 -21600 0 CST}
    {3511152000 -18000 1 CDT}
    {3528687600 -21600 0 CST}
    {3542601600 -18000 1 CDT}
    {3560137200 -21600 0 CST}
    {3574051200 -18000 1 CDT}
    {3592191600 -21600 0 CST}
    {3605500800 -18000 1 CDT}
    {3623641200 -21600 0 CST}
    {3636950400 -18000 1 CDT}
    {3655090800 -21600 0 CST}
    {3669004800 -18000 1 CDT}
    {3686540400 -21600 0 CST}
    {3700454400 -18000 1 CDT}
    {3717990000 -21600 0 CST}
    {3731904000 -18000 1 CDT}
    {3750044400 -21600 0 CST}
    {3763353600 -18000 1 CDT}
    {3781494000 -21600 0 CST}
    {3794803200 -18000 1 CDT}
    {3812943600 -21600 0 CST}
    {3826252800 -18000 1 CDT}
    {3844393200 -21600 0 CST}
    {3858307200 -18000 1 CDT}
    {3875842800 -21600 0 CST}
    {3889756800 -18000 1 CDT}
    {3907292400 -21600 0 CST}
    {3921206400 -18000 1 CDT}
    {3939346800 -21600 0 CST}
    {3952656000 -18000 1 CDT}
    {3970796400 -21600 0 CST}
    {3984105600 -18000 1 CDT}
    {4002246000 -21600 0 CST}
    {4016160000 -18000 1 CDT}
    {4033695600 -21600 0 CST}
    {4047609600 -18000 1 CDT}
    {4065145200 -21600 0 CST}
    {4079059200 -18000 1 CDT}
    {4096594800 -21600 0 CST}
}

Changes to library/tzdata/America/Barbados.

1
2
3
4
5
6









7
8
9
10
11
12
13
1
2
3
4


5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20




-
-
+
+
+
+
+
+
+
+
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Barbados) {
    {-9223372036854775808 -14309 0 LMT}
    {-1451678491 -14309 0 BMT}
    {-1199217691 -14400 0 AST}
    {-1841256091 -14400 0 AST}
    {-874263600 -10800 1 ADT}
    {-862682400 -14400 0 AST}
    {-841604400 -10800 1 ADT}
    {-830714400 -14400 0 AST}
    {-820526400 -14400 0 -0330}
    {-811882800 -12600 1 AST}
    {-798660000 -14400 0 -0330}
    {-788904000 -14400 0 AST}
    {234943200 -10800 1 ADT}
    {244616400 -14400 0 AST}
    {261554400 -10800 1 ADT}
    {276066000 -14400 0 AST}
    {293004000 -10800 1 ADT}
    {307515600 -14400 0 AST}
    {325058400 -10800 1 ADT}

Changes to library/tzdata/America/Belem.

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
30
31
32
33
34






























35
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
30
31
32
33
34
35




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Belem) {
    {-9223372036854775808 -11636 0 LMT}
    {-1767213964 -10800 0 -03}
    {-1206957600 -7200 1 -03}
    {-1191362400 -10800 0 -03}
    {-1175374800 -7200 1 -03}
    {-1159826400 -10800 0 -03}
    {-633819600 -7200 1 -03}
    {-622069200 -10800 0 -03}
    {-602283600 -7200 1 -03}
    {-591832800 -10800 0 -03}
    {-570747600 -7200 1 -03}
    {-560210400 -10800 0 -03}
    {-539125200 -7200 1 -03}
    {-531352800 -10800 0 -03}
    {-191365200 -7200 1 -03}
    {-184197600 -10800 0 -03}
    {-155163600 -7200 1 -03}
    {-150069600 -10800 0 -03}
    {-128898000 -7200 1 -03}
    {-121125600 -10800 0 -03}
    {-99954000 -7200 1 -03}
    {-89589600 -10800 0 -03}
    {-68418000 -7200 1 -03}
    {-57967200 -10800 0 -03}
    {499748400 -7200 1 -03}
    {511236000 -10800 0 -03}
    {530593200 -7200 1 -03}
    {540266400 -10800 0 -03}
    {562129200 -7200 1 -03}
    {571197600 -10800 0 -03}
    {590032800 -10800 0 -03}
    {-1767213964 -10800 0 -0300}
    {-1206957600 -7200 1 -0200}
    {-1191362400 -10800 0 -0300}
    {-1175374800 -7200 1 -0200}
    {-1159826400 -10800 0 -0300}
    {-633819600 -7200 1 -0200}
    {-622069200 -10800 0 -0300}
    {-602283600 -7200 1 -0200}
    {-591832800 -10800 0 -0300}
    {-570747600 -7200 1 -0200}
    {-560210400 -10800 0 -0300}
    {-539125200 -7200 1 -0200}
    {-531352800 -10800 0 -0300}
    {-191365200 -7200 1 -0200}
    {-184197600 -10800 0 -0300}
    {-155163600 -7200 1 -0200}
    {-150069600 -10800 0 -0300}
    {-128898000 -7200 1 -0200}
    {-121125600 -10800 0 -0300}
    {-99954000 -7200 1 -0200}
    {-89589600 -10800 0 -0300}
    {-68418000 -7200 1 -0200}
    {-57967200 -10800 0 -0300}
    {499748400 -7200 1 -0200}
    {511236000 -10800 0 -0300}
    {530593200 -7200 1 -0200}
    {540266400 -10800 0 -0300}
    {562129200 -7200 1 -0200}
    {571197600 -10800 0 -0300}
    {590032800 -10800 0 -0300}
}

Changes to library/tzdata/America/Belize.

47
48
49
50
51
52
53







































54
55






56
57
58
59
60
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+





    {-974658600 -21600 0 CST}
    {-954093600 -19800 1 -0530}
    {-943209000 -21600 0 CST}
    {-922644000 -19800 1 -0530}
    {-911759400 -21600 0 CST}
    {-891194400 -19800 1 -0530}
    {-879705000 -21600 0 CST}
    {-868212000 -18000 1 CWT}
    {-769395600 -18000 1 CPT}
    {-758746800 -21600 0 CST}
    {-701892000 -19800 1 -0530}
    {-690402600 -21600 0 CST}
    {-670442400 -19800 1 -0530}
    {-658953000 -21600 0 CST}
    {-638992800 -19800 1 -0530}
    {-627503400 -21600 0 CST}
    {-606938400 -19800 1 -0530}
    {-596053800 -21600 0 CST}
    {-575488800 -19800 1 -0530}
    {-564604200 -21600 0 CST}
    {-544039200 -19800 1 -0530}
    {-532549800 -21600 0 CST}
    {-512589600 -19800 1 -0530}
    {-501100200 -21600 0 CST}
    {-481140000 -19800 1 -0530}
    {-469650600 -21600 0 CST}
    {-449690400 -19800 1 -0530}
    {-438201000 -21600 0 CST}
    {-417636000 -19800 1 -0530}
    {-406751400 -21600 0 CST}
    {-386186400 -19800 1 -0530}
    {-375301800 -21600 0 CST}
    {-354736800 -19800 1 -0530}
    {-343247400 -21600 0 CST}
    {-323287200 -19800 1 -0530}
    {-311797800 -21600 0 CST}
    {-291837600 -19800 1 -0530}
    {-280348200 -21600 0 CST}
    {-259783200 -19800 1 -0530}
    {-248898600 -21600 0 CST}
    {-228333600 -19800 1 -0530}
    {-217449000 -21600 0 CST}
    {-196884000 -19800 1 -0530}
    {-185999400 -21600 0 CST}
    {-165434400 -19800 1 -0530}
    {-153945000 -21600 0 CST}
    {-859744800 -19800 1 -0530}
    {-848255400 -21600 0 CST}
    {-133984800 -19800 1 -0530}
    {-122495400 -21600 0 CST}
    {-102535200 -19800 1 -0530}
    {-91045800 -21600 0 CST}
    {-70480800 -19800 1 -0530}
    {-59596200 -21600 0 CST}
    {123919200 -18000 1 CDT}
    {129618000 -21600 0 CST}
    {409039200 -18000 1 CDT}
    {413874000 -21600 0 CST}
}

Changes to library/tzdata/America/Blanc-Sablon.

1


2
3


4
5
6
7
8
9
10
11
12
1
2
3


4
5










+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico

set TZData(:America/Blanc-Sablon) {
}
set TZData(:America/Blanc-Sablon) $TZData(:America/Puerto_Rico)
    {-9223372036854775808 -13708 0 LMT}
    {-2713896692 -14400 0 AST}
    {-1632074400 -10800 1 ADT}
    {-1615143600 -14400 0 AST}
    {-880221600 -10800 1 AWT}
    {-769395600 -10800 1 APT}
    {-765399600 -14400 0 AST}
    {14400 -14400 0 AST}
}

Changes to library/tzdata/America/Boa_Vista.

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
30
31
32
33
34
35
36
37
38
39



































40
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
30
31
32
33
34
35
36
37
38
39
40




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Boa_Vista) {
    {-9223372036854775808 -14560 0 LMT}
    {-1767211040 -14400 0 -04}
    {-1206954000 -10800 1 -04}
    {-1191358800 -14400 0 -04}
    {-1175371200 -10800 1 -04}
    {-1159822800 -14400 0 -04}
    {-633816000 -10800 1 -04}
    {-622065600 -14400 0 -04}
    {-602280000 -10800 1 -04}
    {-591829200 -14400 0 -04}
    {-570744000 -10800 1 -04}
    {-560206800 -14400 0 -04}
    {-539121600 -10800 1 -04}
    {-531349200 -14400 0 -04}
    {-191361600 -10800 1 -04}
    {-184194000 -14400 0 -04}
    {-155160000 -10800 1 -04}
    {-150066000 -14400 0 -04}
    {-128894400 -10800 1 -04}
    {-121122000 -14400 0 -04}
    {-99950400 -10800 1 -04}
    {-89586000 -14400 0 -04}
    {-68414400 -10800 1 -04}
    {-57963600 -14400 0 -04}
    {499752000 -10800 1 -04}
    {511239600 -14400 0 -04}
    {530596800 -10800 1 -04}
    {540270000 -14400 0 -04}
    {562132800 -10800 1 -04}
    {571201200 -14400 0 -04}
    {590036400 -14400 0 -04}
    {938664000 -14400 0 -04}
    {938923200 -10800 1 -04}
    {951620400 -14400 0 -04}
    {970977600 -10800 1 -04}
    {971578800 -14400 0 -04}
    {-1767211040 -14400 0 -0400}
    {-1206954000 -10800 1 -0300}
    {-1191358800 -14400 0 -0400}
    {-1175371200 -10800 1 -0300}
    {-1159822800 -14400 0 -0400}
    {-633816000 -10800 1 -0300}
    {-622065600 -14400 0 -0400}
    {-602280000 -10800 1 -0300}
    {-591829200 -14400 0 -0400}
    {-570744000 -10800 1 -0300}
    {-560206800 -14400 0 -0400}
    {-539121600 -10800 1 -0300}
    {-531349200 -14400 0 -0400}
    {-191361600 -10800 1 -0300}
    {-184194000 -14400 0 -0400}
    {-155160000 -10800 1 -0300}
    {-150066000 -14400 0 -0400}
    {-128894400 -10800 1 -0300}
    {-121122000 -14400 0 -0400}
    {-99950400 -10800 1 -0300}
    {-89586000 -14400 0 -0400}
    {-68414400 -10800 1 -0300}
    {-57963600 -14400 0 -0400}
    {499752000 -10800 1 -0300}
    {511239600 -14400 0 -0400}
    {530596800 -10800 1 -0300}
    {540270000 -14400 0 -0400}
    {562132800 -10800 1 -0300}
    {571201200 -14400 0 -0400}
    {590036400 -14400 0 -0400}
    {938664000 -14400 0 -0400}
    {938923200 -10800 1 -0300}
    {951620400 -14400 0 -0400}
    {970977600 -10800 1 -0300}
    {971578800 -14400 0 -0400}
}

Changes to library/tzdata/America/Bogota.

1
2
3
4
5
6
7
8



9
1
2
3
4
5



6
7
8
9





-
-
-
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Bogota) {
    {-9223372036854775808 -17776 0 LMT}
    {-2707671824 -17776 0 BMT}
    {-1739041424 -18000 0 -05}
    {704869200 -14400 1 -05}
    {733896000 -18000 0 -05}
    {-1739041424 -18000 0 -0500}
    {704869200 -14400 1 -0400}
    {729057600 -18000 0 -0500}
}

Changes to library/tzdata/America/Cambridge_Bay.

1
2
3
4
5
6
7
8




9
10












11
12
13
14
15
16
17
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
30
31








+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Cambridge_Bay) {
    {-9223372036854775808 0 0 -00}
    {-1577923200 -25200 0 MST}
    {-880210800 -21600 1 MWT}
    {-769395600 -21600 1 MPT}
    {-765388800 -25200 0 MST}
    {73472400 -21600 1 MDT}
    {89193600 -25200 0 MST}
    {104922000 -21600 1 MDT}
    {120643200 -25200 0 MST}
    {-147891600 -18000 1 MDDT}
    {-131562000 -25200 0 MST}
    {136371600 -21600 1 MDT}
    {152092800 -25200 0 MST}
    {167821200 -21600 1 MDT}
    {183542400 -25200 0 MST}
    {199270800 -21600 1 MDT}
    {215596800 -25200 0 MST}
    {230720400 -21600 1 MDT}
    {247046400 -25200 0 MST}
    {262774800 -21600 1 MDT}
    {278496000 -25200 0 MST}
    {294224400 -21600 1 MDT}
    {309945600 -25200 0 MST}
    {325674000 -21600 1 MDT}
    {341395200 -25200 0 MST}
    {357123600 -21600 1 MDT}
    {372844800 -25200 0 MST}
    {388573200 -21600 1 MDT}
    {404899200 -25200 0 MST}
    {420022800 -21600 1 MDT}

Changes to library/tzdata/America/Campo_Grande.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Campo_Grande) {
    {-9223372036854775808 -13108 0 LMT}
    {-1767212492 -14400 0 -04}
    {-1206954000 -10800 1 -04}
    {-1191358800 -14400 0 -04}
    {-1175371200 -10800 1 -04}
    {-1159822800 -14400 0 -04}
    {-633816000 -10800 1 -04}
    {-622065600 -14400 0 -04}
    {-602280000 -10800 1 -04}
    {-591829200 -14400 0 -04}
    {-570744000 -10800 1 -04}
    {-560206800 -14400 0 -04}
    {-539121600 -10800 1 -04}
    {-531349200 -14400 0 -04}
    {-191361600 -10800 1 -04}
    {-184194000 -14400 0 -04}
    {-155160000 -10800 1 -04}
    {-150066000 -14400 0 -04}
    {-128894400 -10800 1 -04}
    {-121122000 -14400 0 -04}
    {-99950400 -10800 1 -04}
    {-89586000 -14400 0 -04}
    {-68414400 -10800 1 -04}
    {-57963600 -14400 0 -04}
    {499752000 -10800 1 -04}
    {511239600 -14400 0 -04}
    {530596800 -10800 1 -04}
    {540270000 -14400 0 -04}
    {562132800 -10800 1 -04}
    {571201200 -14400 0 -04}
    {592977600 -10800 1 -04}
    {602046000 -14400 0 -04}
    {624427200 -10800 1 -04}
    {634705200 -14400 0 -04}
    {656481600 -10800 1 -04}
    {666759600 -14400 0 -04}
    {687931200 -10800 1 -04}
    {697604400 -14400 0 -04}
    {719985600 -10800 1 -04}
    {728449200 -14400 0 -04}
    {750830400 -10800 1 -04}
    {761713200 -14400 0 -04}
    {782280000 -10800 1 -04}
    {793162800 -14400 0 -04}
    {813729600 -10800 1 -04}
    {824007600 -14400 0 -04}
    {844574400 -10800 1 -04}
    {856062000 -14400 0 -04}
    {876110400 -10800 1 -04}
    {888721200 -14400 0 -04}
    {908078400 -10800 1 -04}
    {919566000 -14400 0 -04}
    {938923200 -10800 1 -04}
    {951620400 -14400 0 -04}
    {970977600 -10800 1 -04}
    {982465200 -14400 0 -04}
    {1003032000 -10800 1 -04}
    {1013914800 -14400 0 -04}
    {1036296000 -10800 1 -04}
    {1045364400 -14400 0 -04}
    {1066536000 -10800 1 -04}
    {1076814000 -14400 0 -04}
    {1099368000 -10800 1 -04}
    {1108868400 -14400 0 -04}
    {1129435200 -10800 1 -04}
    {1140318000 -14400 0 -04}
    {1162699200 -10800 1 -04}
    {1172372400 -14400 0 -04}
    {1192334400 -10800 1 -04}
    {1203217200 -14400 0 -04}
    {1224388800 -10800 1 -04}
    {1234666800 -14400 0 -04}
    {1255838400 -10800 1 -04}
    {1266721200 -14400 0 -04}
    {1287288000 -10800 1 -04}
    {1298170800 -14400 0 -04}
    {1318737600 -10800 1 -04}
    {1330225200 -14400 0 -04}
    {1350792000 -10800 1 -04}
    {1361070000 -14400 0 -04}
    {1382241600 -10800 1 -04}
    {1392519600 -14400 0 -04}
    {1413691200 -10800 1 -04}
    {1424574000 -14400 0 -04}
    {1445140800 -10800 1 -04}
    {1456023600 -14400 0 -04}
    {1476590400 -10800 1 -04}
    {1487473200 -14400 0 -04}
    {1508040000 -10800 1 -04}
    {1518922800 -14400 0 -04}
    {1541304000 -10800 1 -04}
    {1550372400 -14400 0 -04}
    {-1767212492 -14400 0 -0400}
    {-1206954000 -10800 1 -0300}
    {-1191358800 -14400 0 -0400}
    {-1175371200 -10800 1 -0300}
    {-1159822800 -14400 0 -0400}
    {-633816000 -10800 1 -0300}
    {-622065600 -14400 0 -0400}
    {-602280000 -10800 1 -0300}
    {-591829200 -14400 0 -0400}
    {-570744000 -10800 1 -0300}
    {-560206800 -14400 0 -0400}
    {-539121600 -10800 1 -0300}
    {-531349200 -14400 0 -0400}
    {-191361600 -10800 1 -0300}
    {-184194000 -14400 0 -0400}
    {-155160000 -10800 1 -0300}
    {-150066000 -14400 0 -0400}
    {-128894400 -10800 1 -0300}
    {-121122000 -14400 0 -0400}
    {-99950400 -10800 1 -0300}
    {-89586000 -14400 0 -0400}
    {-68414400 -10800 1 -0300}
    {-57963600 -14400 0 -0400}
    {499752000 -10800 1 -0300}
    {511239600 -14400 0 -0400}
    {530596800 -10800 1 -0300}
    {540270000 -14400 0 -0400}
    {562132800 -10800 1 -0300}
    {571201200 -14400 0 -0400}
    {592977600 -10800 1 -0300}
    {602046000 -14400 0 -0400}
    {624427200 -10800 1 -0300}
    {634705200 -14400 0 -0400}
    {656481600 -10800 1 -0300}
    {666759600 -14400 0 -0400}
    {687931200 -10800 1 -0300}
    {697604400 -14400 0 -0400}
    {719985600 -10800 1 -0300}
    {728449200 -14400 0 -0400}
    {750830400 -10800 1 -0300}
    {761713200 -14400 0 -0400}
    {782280000 -10800 1 -0300}
    {793162800 -14400 0 -0400}
    {813729600 -10800 1 -0300}
    {824007600 -14400 0 -0400}
    {844574400 -10800 1 -0300}
    {856062000 -14400 0 -0400}
    {876110400 -10800 1 -0300}
    {888721200 -14400 0 -0400}
    {908078400 -10800 1 -0300}
    {919566000 -14400 0 -0400}
    {938923200 -10800 1 -0300}
    {951620400 -14400 0 -0400}
    {970977600 -10800 1 -0300}
    {982465200 -14400 0 -0400}
    {1003032000 -10800 1 -0300}
    {1013914800 -14400 0 -0400}
    {1036296000 -10800 1 -0300}
    {1045364400 -14400 0 -0400}
    {1066536000 -10800 1 -0300}
    {1076814000 -14400 0 -0400}
    {1099368000 -10800 1 -0300}
    {1108868400 -14400 0 -0400}
    {1129435200 -10800 1 -0300}
    {1140318000 -14400 0 -0400}
    {1162699200 -10800 1 -0300}
    {1172372400 -14400 0 -0400}
    {1192334400 -10800 1 -0300}
    {1203217200 -14400 0 -0400}
    {1224388800 -10800 1 -0300}
    {1234666800 -14400 0 -0400}
    {1255838400 -10800 1 -0300}
    {1266721200 -14400 0 -0400}
    {1287288000 -10800 1 -0300}
    {1298170800 -14400 0 -0400}
    {1318737600 -10800 1 -0300}
    {1330225200 -14400 0 -0400}
    {1350792000 -10800 1 -0300}
    {1361070000 -14400 0 -0400}
    {1382241600 -10800 1 -0300}
    {1392519600 -14400 0 -0400}
    {1413691200 -10800 1 -0300}
    {1424574000 -14400 0 -0400}
    {1445140800 -10800 1 -0300}
    {1456023600 -14400 0 -0400}
    {1476590400 -10800 1 -0300}
    {1487473200 -14400 0 -0400}
    {1508040000 -10800 1 -0300}
    {1518922800 -14400 0 -0400}
    {1541304000 -10800 1 -0300}
    {1550372400 -14400 0 -0400}
}

Changes to library/tzdata/America/Cancun.

1
2
3
4
5
6
7
8
9
10






11
12
13
14
15
16
17
1
2
3
4
5





6
7
8
9
10
11
12
13
14
15
16
17
18





-
-
-
-
-
+
+
+
+
+
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Cancun) {
    {-9223372036854775808 -20824 0 LMT}
    {-1514743200 -21600 0 CST}
    {377935200 -18000 0 EST}
    {828860400 -14400 1 EDT}
    {846396000 -18000 0 EST}
    {860310000 -14400 1 EDT}
    {877845600 -18000 0 EST}
    {378201600 -18000 0 EST}
    {410504400 -21600 0 CST}
    {828864000 -18000 1 CDT}
    {846399600 -21600 0 CST}
    {860313600 -18000 1 CDT}
    {877852800 -18000 0 EST}
    {891759600 -14400 1 EDT}
    {902041200 -18000 0 CDT}
    {909298800 -21600 0 CST}
    {923212800 -18000 1 CDT}
    {941353200 -21600 0 CST}
    {954662400 -18000 1 CDT}
    {972802800 -21600 0 CST}

Changes to library/tzdata/America/Caracas.

1
2
3
4
5
6
7
8
9




10
1
2
3
4
5




6
7
8
9
10





-
-
-
-
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Caracas) {
    {-9223372036854775808 -16064 0 LMT}
    {-2524505536 -16060 0 CMT}
    {-1826739140 -16200 0 -0430}
    {-157750200 -14400 0 -04}
    {1197183600 -16200 0 -0430}
    {1462086000 -14400 0 -04}
    {-1826739140 -16200 0 -0530}
    {-157750200 -14400 0 -0400}
    {1197183600 -16200 0 -0530}
    {1462086000 -14400 0 -0400}
}

Changes to library/tzdata/America/Cayenne.

1
2
3
4
5
6


7
1
2
3
4


5
6
7




-
-
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Cayenne) {
    {-9223372036854775808 -12560 0 LMT}
    {-1846269040 -14400 0 -04}
    {-71092800 -10800 0 -03}
    {-1846269040 -14400 0 -0400}
    {-71092800 -10800 0 -0300}
}

Changes to library/tzdata/America/Chihuahua.

1
2
3
4
5
6

7
8

9
10
11
12
13
14
15
1
2
3
4
5

6
7

8
9
10
11
12
13
14
15





-
+

-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Chihuahua) {
    {-9223372036854775808 -25460 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1343149200 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 0 CST}
    {-1220461200 -21600 1 MDT}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {820476000 -21600 0 CST}
    {828864000 -18000 1 CDT}
    {846399600 -21600 0 CST}
    {860313600 -18000 1 CDT}
    {877849200 -21600 0 CST}
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
59
60
61
62
63
64
65




66























































































































































67







-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

    {1554627600 -21600 1 MDT}
    {1572163200 -25200 0 MST}
    {1586077200 -21600 1 MDT}
    {1603612800 -25200 0 MST}
    {1617526800 -21600 1 MDT}
    {1635667200 -25200 0 MST}
    {1648976400 -21600 1 MDT}
    {1667116800 -25200 0 MST}
    {1680426000 -21600 1 MDT}
    {1698566400 -25200 0 MST}
    {1712480400 -21600 1 MDT}
    {1667120400 -21600 0 CST}
    {1730016000 -25200 0 MST}
    {1743930000 -21600 1 MDT}
    {1761465600 -25200 0 MST}
    {1775379600 -21600 1 MDT}
    {1792915200 -25200 0 MST}
    {1806829200 -21600 1 MDT}
    {1824969600 -25200 0 MST}
    {1838278800 -21600 1 MDT}
    {1856419200 -25200 0 MST}
    {1869728400 -21600 1 MDT}
    {1887868800 -25200 0 MST}
    {1901782800 -21600 1 MDT}
    {1919318400 -25200 0 MST}
    {1933232400 -21600 1 MDT}
    {1950768000 -25200 0 MST}
    {1964682000 -21600 1 MDT}
    {1982822400 -25200 0 MST}
    {1996131600 -21600 1 MDT}
    {2014272000 -25200 0 MST}
    {2027581200 -21600 1 MDT}
    {2045721600 -25200 0 MST}
    {2059030800 -21600 1 MDT}
    {2077171200 -25200 0 MST}
    {2091085200 -21600 1 MDT}
    {2108620800 -25200 0 MST}
    {2122534800 -21600 1 MDT}
    {2140070400 -25200 0 MST}
    {2153984400 -21600 1 MDT}
    {2172124800 -25200 0 MST}
    {2185434000 -21600 1 MDT}
    {2203574400 -25200 0 MST}
    {2216883600 -21600 1 MDT}
    {2235024000 -25200 0 MST}
    {2248938000 -21600 1 MDT}
    {2266473600 -25200 0 MST}
    {2280387600 -21600 1 MDT}
    {2297923200 -25200 0 MST}
    {2311837200 -21600 1 MDT}
    {2329372800 -25200 0 MST}
    {2343286800 -21600 1 MDT}
    {2361427200 -25200 0 MST}
    {2374736400 -21600 1 MDT}
    {2392876800 -25200 0 MST}
    {2406186000 -21600 1 MDT}
    {2424326400 -25200 0 MST}
    {2438240400 -21600 1 MDT}
    {2455776000 -25200 0 MST}
    {2469690000 -21600 1 MDT}
    {2487225600 -25200 0 MST}
    {2501139600 -21600 1 MDT}
    {2519280000 -25200 0 MST}
    {2532589200 -21600 1 MDT}
    {2550729600 -25200 0 MST}
    {2564038800 -21600 1 MDT}
    {2582179200 -25200 0 MST}
    {2596093200 -21600 1 MDT}
    {2613628800 -25200 0 MST}
    {2627542800 -21600 1 MDT}
    {2645078400 -25200 0 MST}
    {2658992400 -21600 1 MDT}
    {2676528000 -25200 0 MST}
    {2690442000 -21600 1 MDT}
    {2708582400 -25200 0 MST}
    {2721891600 -21600 1 MDT}
    {2740032000 -25200 0 MST}
    {2753341200 -21600 1 MDT}
    {2771481600 -25200 0 MST}
    {2785395600 -21600 1 MDT}
    {2802931200 -25200 0 MST}
    {2816845200 -21600 1 MDT}
    {2834380800 -25200 0 MST}
    {2848294800 -21600 1 MDT}
    {2866435200 -25200 0 MST}
    {2879744400 -21600 1 MDT}
    {2897884800 -25200 0 MST}
    {2911194000 -21600 1 MDT}
    {2929334400 -25200 0 MST}
    {2942643600 -21600 1 MDT}
    {2960784000 -25200 0 MST}
    {2974698000 -21600 1 MDT}
    {2992233600 -25200 0 MST}
    {3006147600 -21600 1 MDT}
    {3023683200 -25200 0 MST}
    {3037597200 -21600 1 MDT}
    {3055737600 -25200 0 MST}
    {3069046800 -21600 1 MDT}
    {3087187200 -25200 0 MST}
    {3100496400 -21600 1 MDT}
    {3118636800 -25200 0 MST}
    {3132550800 -21600 1 MDT}
    {3150086400 -25200 0 MST}
    {3164000400 -21600 1 MDT}
    {3181536000 -25200 0 MST}
    {3195450000 -21600 1 MDT}
    {3212985600 -25200 0 MST}
    {3226899600 -21600 1 MDT}
    {3245040000 -25200 0 MST}
    {3258349200 -21600 1 MDT}
    {3276489600 -25200 0 MST}
    {3289798800 -21600 1 MDT}
    {3307939200 -25200 0 MST}
    {3321853200 -21600 1 MDT}
    {3339388800 -25200 0 MST}
    {3353302800 -21600 1 MDT}
    {3370838400 -25200 0 MST}
    {3384752400 -21600 1 MDT}
    {3402892800 -25200 0 MST}
    {3416202000 -21600 1 MDT}
    {3434342400 -25200 0 MST}
    {3447651600 -21600 1 MDT}
    {3465792000 -25200 0 MST}
    {3479706000 -21600 1 MDT}
    {3497241600 -25200 0 MST}
    {3511155600 -21600 1 MDT}
    {3528691200 -25200 0 MST}
    {3542605200 -21600 1 MDT}
    {3560140800 -25200 0 MST}
    {3574054800 -21600 1 MDT}
    {3592195200 -25200 0 MST}
    {3605504400 -21600 1 MDT}
    {3623644800 -25200 0 MST}
    {3636954000 -21600 1 MDT}
    {3655094400 -25200 0 MST}
    {3669008400 -21600 1 MDT}
    {3686544000 -25200 0 MST}
    {3700458000 -21600 1 MDT}
    {3717993600 -25200 0 MST}
    {3731907600 -21600 1 MDT}
    {3750048000 -25200 0 MST}
    {3763357200 -21600 1 MDT}
    {3781497600 -25200 0 MST}
    {3794806800 -21600 1 MDT}
    {3812947200 -25200 0 MST}
    {3826256400 -21600 1 MDT}
    {3844396800 -25200 0 MST}
    {3858310800 -21600 1 MDT}
    {3875846400 -25200 0 MST}
    {3889760400 -21600 1 MDT}
    {3907296000 -25200 0 MST}
    {3921210000 -21600 1 MDT}
    {3939350400 -25200 0 MST}
    {3952659600 -21600 1 MDT}
    {3970800000 -25200 0 MST}
    {3984109200 -21600 1 MDT}
    {4002249600 -25200 0 MST}
    {4016163600 -21600 1 MDT}
    {4033699200 -25200 0 MST}
    {4047613200 -21600 1 MDT}
    {4065148800 -25200 0 MST}
    {4079062800 -21600 1 MDT}
    {4096598400 -25200 0 MST}
}

Added library/tzdata/America/Ciudad_Juarez.
































































































































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Ciudad_Juarez) {
    {-9223372036854775808 -25556 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343149200 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220461200 -21600 1 MDT}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {820476000 -21600 0 CST}
    {828864000 -18000 1 CDT}
    {846399600 -21600 0 CST}
    {860313600 -18000 1 CDT}
    {877849200 -21600 0 CST}
    {883634400 -21600 0 CST}
    {891766800 -21600 0 MDT}
    {909302400 -25200 0 MST}
    {923216400 -21600 1 MDT}
    {941356800 -25200 0 MST}
    {954666000 -21600 1 MDT}
    {972806400 -25200 0 MST}
    {989139600 -21600 1 MDT}
    {1001836800 -25200 0 MST}
    {1018170000 -21600 1 MDT}
    {1035705600 -25200 0 MST}
    {1049619600 -21600 1 MDT}
    {1067155200 -25200 0 MST}
    {1081069200 -21600 1 MDT}
    {1099209600 -25200 0 MST}
    {1112518800 -21600 1 MDT}
    {1130659200 -25200 0 MST}
    {1143968400 -21600 1 MDT}
    {1162108800 -25200 0 MST}
    {1175418000 -21600 1 MDT}
    {1193558400 -25200 0 MST}
    {1207472400 -21600 1 MDT}
    {1225008000 -25200 0 MST}
    {1238922000 -21600 1 MDT}
    {1256457600 -25200 0 MST}
    {1262329200 -25200 0 MST}
    {1268557200 -21600 1 MDT}
    {1289116800 -25200 0 MST}
    {1300006800 -21600 1 MDT}
    {1320566400 -25200 0 MST}
    {1331456400 -21600 1 MDT}
    {1352016000 -25200 0 MST}
    {1362906000 -21600 1 MDT}
    {1383465600 -25200 0 MST}
    {1394355600 -21600 1 MDT}
    {1414915200 -25200 0 MST}
    {1425805200 -21600 1 MDT}
    {1446364800 -25200 0 MST}
    {1457859600 -21600 1 MDT}
    {1478419200 -25200 0 MST}
    {1489309200 -21600 1 MDT}
    {1509868800 -25200 0 MST}
    {1520758800 -21600 1 MDT}
    {1541318400 -25200 0 MST}
    {1552208400 -21600 1 MDT}
    {1572768000 -25200 0 MST}
    {1583658000 -21600 1 MDT}
    {1604217600 -25200 0 MST}
    {1615712400 -21600 1 MDT}
    {1636272000 -25200 0 MST}
    {1647162000 -21600 1 MDT}
    {1667120400 -21600 0 CST}
    {1669788000 -25200 0 MST}
    {1678611600 -21600 1 MDT}
    {1699171200 -25200 0 MST}
    {1710061200 -21600 1 MDT}
    {1730620800 -25200 0 MST}
    {1741510800 -21600 1 MDT}
    {1762070400 -25200 0 MST}
    {1772960400 -21600 1 MDT}
    {1793520000 -25200 0 MST}
    {1805014800 -21600 1 MDT}
    {1825574400 -25200 0 MST}
    {1836464400 -21600 1 MDT}
    {1857024000 -25200 0 MST}
    {1867914000 -21600 1 MDT}
    {1888473600 -25200 0 MST}
    {1899363600 -21600 1 MDT}
    {1919923200 -25200 0 MST}
    {1930813200 -21600 1 MDT}
    {1951372800 -25200 0 MST}
    {1962867600 -21600 1 MDT}
    {1983427200 -25200 0 MST}
    {1994317200 -21600 1 MDT}
    {2014876800 -25200 0 MST}
    {2025766800 -21600 1 MDT}
    {2046326400 -25200 0 MST}
    {2057216400 -21600 1 MDT}
    {2077776000 -25200 0 MST}
    {2088666000 -21600 1 MDT}
    {2109225600 -25200 0 MST}
    {2120115600 -21600 1 MDT}
    {2140675200 -25200 0 MST}
    {2152170000 -21600 1 MDT}
    {2172729600 -25200 0 MST}
    {2183619600 -21600 1 MDT}
    {2204179200 -25200 0 MST}
    {2215069200 -21600 1 MDT}
    {2235628800 -25200 0 MST}
    {2246518800 -21600 1 MDT}
    {2267078400 -25200 0 MST}
    {2277968400 -21600 1 MDT}
    {2298528000 -25200 0 MST}
    {2309418000 -21600 1 MDT}
    {2329977600 -25200 0 MST}
    {2341472400 -21600 1 MDT}
    {2362032000 -25200 0 MST}
    {2372922000 -21600 1 MDT}
    {2393481600 -25200 0 MST}
    {2404371600 -21600 1 MDT}
    {2424931200 -25200 0 MST}
    {2435821200 -21600 1 MDT}
    {2456380800 -25200 0 MST}
    {2467270800 -21600 1 MDT}
    {2487830400 -25200 0 MST}
    {2499325200 -21600 1 MDT}
    {2519884800 -25200 0 MST}
    {2530774800 -21600 1 MDT}
    {2551334400 -25200 0 MST}
    {2562224400 -21600 1 MDT}
    {2582784000 -25200 0 MST}
    {2593674000 -21600 1 MDT}
    {2614233600 -25200 0 MST}
    {2625123600 -21600 1 MDT}
    {2645683200 -25200 0 MST}
    {2656573200 -21600 1 MDT}
    {2677132800 -25200 0 MST}
    {2688627600 -21600 1 MDT}
    {2709187200 -25200 0 MST}
    {2720077200 -21600 1 MDT}
    {2740636800 -25200 0 MST}
    {2751526800 -21600 1 MDT}
    {2772086400 -25200 0 MST}
    {2782976400 -21600 1 MDT}
    {2803536000 -25200 0 MST}
    {2814426000 -21600 1 MDT}
    {2834985600 -25200 0 MST}
    {2846480400 -21600 1 MDT}
    {2867040000 -25200 0 MST}
    {2877930000 -21600 1 MDT}
    {2898489600 -25200 0 MST}
    {2909379600 -21600 1 MDT}
    {2929939200 -25200 0 MST}
    {2940829200 -21600 1 MDT}
    {2961388800 -25200 0 MST}
    {2972278800 -21600 1 MDT}
    {2992838400 -25200 0 MST}
    {3003728400 -21600 1 MDT}
    {3024288000 -25200 0 MST}
    {3035782800 -21600 1 MDT}
    {3056342400 -25200 0 MST}
    {3067232400 -21600 1 MDT}
    {3087792000 -25200 0 MST}
    {3098682000 -21600 1 MDT}
    {3119241600 -25200 0 MST}
    {3130131600 -21600 1 MDT}
    {3150691200 -25200 0 MST}
    {3161581200 -21600 1 MDT}
    {3182140800 -25200 0 MST}
    {3193030800 -21600 1 MDT}
    {3213590400 -25200 0 MST}
    {3225085200 -21600 1 MDT}
    {3245644800 -25200 0 MST}
    {3256534800 -21600 1 MDT}
    {3277094400 -25200 0 MST}
    {3287984400 -21600 1 MDT}
    {3308544000 -25200 0 MST}
    {3319434000 -21600 1 MDT}
    {3339993600 -25200 0 MST}
    {3350883600 -21600 1 MDT}
    {3371443200 -25200 0 MST}
    {3382938000 -21600 1 MDT}
    {3403497600 -25200 0 MST}
    {3414387600 -21600 1 MDT}
    {3434947200 -25200 0 MST}
    {3445837200 -21600 1 MDT}
    {3466396800 -25200 0 MST}
    {3477286800 -21600 1 MDT}
    {3497846400 -25200 0 MST}
    {3508736400 -21600 1 MDT}
    {3529296000 -25200 0 MST}
    {3540186000 -21600 1 MDT}
    {3560745600 -25200 0 MST}
    {3572240400 -21600 1 MDT}
    {3592800000 -25200 0 MST}
    {3603690000 -21600 1 MDT}
    {3624249600 -25200 0 MST}
    {3635139600 -21600 1 MDT}
    {3655699200 -25200 0 MST}
    {3666589200 -21600 1 MDT}
    {3687148800 -25200 0 MST}
    {3698038800 -21600 1 MDT}
    {3718598400 -25200 0 MST}
    {3730093200 -21600 1 MDT}
    {3750652800 -25200 0 MST}
    {3761542800 -21600 1 MDT}
    {3782102400 -25200 0 MST}
    {3792992400 -21600 1 MDT}
    {3813552000 -25200 0 MST}
    {3824442000 -21600 1 MDT}
    {3845001600 -25200 0 MST}
    {3855891600 -21600 1 MDT}
    {3876451200 -25200 0 MST}
    {3887341200 -21600 1 MDT}
    {3907900800 -25200 0 MST}
    {3919395600 -21600 1 MDT}
    {3939955200 -25200 0 MST}
    {3950845200 -21600 1 MDT}
    {3971404800 -25200 0 MST}
    {3982294800 -21600 1 MDT}
    {4002854400 -25200 0 MST}
    {4013744400 -21600 1 MDT}
    {4034304000 -25200 0 MST}
    {4045194000 -21600 1 MDT}
    {4065753600 -25200 0 MST}
    {4076643600 -21600 1 MDT}
    {4097203200 -25200 0 MST}
}

Changes to library/tzdata/America/Coral_Harbour.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Atikokan)]} {
    LoadTimeZoneFile America/Atikokan
if {![info exists TZData(America/Panama)]} {
    LoadTimeZoneFile America/Panama
}
set TZData(:America/Coral_Harbour) $TZData(:America/Atikokan)
set TZData(:America/Coral_Harbour) $TZData(:America/Panama)

Changes to library/tzdata/America/Creston.

1


2
3


4
5
6
7
8
1
2
3


4
5






+
+
-
-
+
+
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Phoenix)]} {
    LoadTimeZoneFile America/Phoenix

set TZData(:America/Creston) {
}
set TZData(:America/Creston) $TZData(:America/Phoenix)
    {-9223372036854775808 -27964 0 LMT}
    {-2713882436 -25200 0 MST}
    {-1680454800 -28800 0 PST}
    {-1627833600 -25200 0 MST}
}

Changes to library/tzdata/America/Cuiaba.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Cuiaba) {
    {-9223372036854775808 -13460 0 LMT}
    {-1767212140 -14400 0 -04}
    {-1206954000 -10800 1 -04}
    {-1191358800 -14400 0 -04}
    {-1175371200 -10800 1 -04}
    {-1159822800 -14400 0 -04}
    {-633816000 -10800 1 -04}
    {-622065600 -14400 0 -04}
    {-602280000 -10800 1 -04}
    {-591829200 -14400 0 -04}
    {-570744000 -10800 1 -04}
    {-560206800 -14400 0 -04}
    {-539121600 -10800 1 -04}
    {-531349200 -14400 0 -04}
    {-191361600 -10800 1 -04}
    {-184194000 -14400 0 -04}
    {-155160000 -10800 1 -04}
    {-150066000 -14400 0 -04}
    {-128894400 -10800 1 -04}
    {-121122000 -14400 0 -04}
    {-99950400 -10800 1 -04}
    {-89586000 -14400 0 -04}
    {-68414400 -10800 1 -04}
    {-57963600 -14400 0 -04}
    {499752000 -10800 1 -04}
    {511239600 -14400 0 -04}
    {530596800 -10800 1 -04}
    {540270000 -14400 0 -04}
    {562132800 -10800 1 -04}
    {571201200 -14400 0 -04}
    {592977600 -10800 1 -04}
    {602046000 -14400 0 -04}
    {624427200 -10800 1 -04}
    {634705200 -14400 0 -04}
    {656481600 -10800 1 -04}
    {666759600 -14400 0 -04}
    {687931200 -10800 1 -04}
    {697604400 -14400 0 -04}
    {719985600 -10800 1 -04}
    {728449200 -14400 0 -04}
    {750830400 -10800 1 -04}
    {761713200 -14400 0 -04}
    {782280000 -10800 1 -04}
    {793162800 -14400 0 -04}
    {813729600 -10800 1 -04}
    {824007600 -14400 0 -04}
    {844574400 -10800 1 -04}
    {856062000 -14400 0 -04}
    {876110400 -10800 1 -04}
    {888721200 -14400 0 -04}
    {908078400 -10800 1 -04}
    {919566000 -14400 0 -04}
    {938923200 -10800 1 -04}
    {951620400 -14400 0 -04}
    {970977600 -10800 1 -04}
    {982465200 -14400 0 -04}
    {1003032000 -10800 1 -04}
    {1013914800 -14400 0 -04}
    {1036296000 -10800 1 -04}
    {1045364400 -14400 0 -04}
    {1064372400 -14400 0 -04}
    {1096603200 -14400 0 -04}
    {1099368000 -10800 1 -04}
    {1108868400 -14400 0 -04}
    {1129435200 -10800 1 -04}
    {1140318000 -14400 0 -04}
    {1162699200 -10800 1 -04}
    {1172372400 -14400 0 -04}
    {1192334400 -10800 1 -04}
    {1203217200 -14400 0 -04}
    {1224388800 -10800 1 -04}
    {1234666800 -14400 0 -04}
    {1255838400 -10800 1 -04}
    {1266721200 -14400 0 -04}
    {1287288000 -10800 1 -04}
    {1298170800 -14400 0 -04}
    {1318737600 -10800 1 -04}
    {1330225200 -14400 0 -04}
    {1350792000 -10800 1 -04}
    {1361070000 -14400 0 -04}
    {1382241600 -10800 1 -04}
    {1392519600 -14400 0 -04}
    {1413691200 -10800 1 -04}
    {1424574000 -14400 0 -04}
    {1445140800 -10800 1 -04}
    {1456023600 -14400 0 -04}
    {1476590400 -10800 1 -04}
    {1487473200 -14400 0 -04}
    {1508040000 -10800 1 -04}
    {1518922800 -14400 0 -04}
    {1541304000 -10800 1 -04}
    {1550372400 -14400 0 -04}
    {-1767212140 -14400 0 -0400}
    {-1206954000 -10800 1 -0300}
    {-1191358800 -14400 0 -0400}
    {-1175371200 -10800 1 -0300}
    {-1159822800 -14400 0 -0400}
    {-633816000 -10800 1 -0300}
    {-622065600 -14400 0 -0400}
    {-602280000 -10800 1 -0300}
    {-591829200 -14400 0 -0400}
    {-570744000 -10800 1 -0300}
    {-560206800 -14400 0 -0400}
    {-539121600 -10800 1 -0300}
    {-531349200 -14400 0 -0400}
    {-191361600 -10800 1 -0300}
    {-184194000 -14400 0 -0400}
    {-155160000 -10800 1 -0300}
    {-150066000 -14400 0 -0400}
    {-128894400 -10800 1 -0300}
    {-121122000 -14400 0 -0400}
    {-99950400 -10800 1 -0300}
    {-89586000 -14400 0 -0400}
    {-68414400 -10800 1 -0300}
    {-57963600 -14400 0 -0400}
    {499752000 -10800 1 -0300}
    {511239600 -14400 0 -0400}
    {530596800 -10800 1 -0300}
    {540270000 -14400 0 -0400}
    {562132800 -10800 1 -0300}
    {571201200 -14400 0 -0400}
    {592977600 -10800 1 -0300}
    {602046000 -14400 0 -0400}
    {624427200 -10800 1 -0300}
    {634705200 -14400 0 -0400}
    {656481600 -10800 1 -0300}
    {666759600 -14400 0 -0400}
    {687931200 -10800 1 -0300}
    {697604400 -14400 0 -0400}
    {719985600 -10800 1 -0300}
    {728449200 -14400 0 -0400}
    {750830400 -10800 1 -0300}
    {761713200 -14400 0 -0400}
    {782280000 -10800 1 -0300}
    {793162800 -14400 0 -0400}
    {813729600 -10800 1 -0300}
    {824007600 -14400 0 -0400}
    {844574400 -10800 1 -0300}
    {856062000 -14400 0 -0400}
    {876110400 -10800 1 -0300}
    {888721200 -14400 0 -0400}
    {908078400 -10800 1 -0300}
    {919566000 -14400 0 -0400}
    {938923200 -10800 1 -0300}
    {951620400 -14400 0 -0400}
    {970977600 -10800 1 -0300}
    {982465200 -14400 0 -0400}
    {1003032000 -10800 1 -0300}
    {1013914800 -14400 0 -0400}
    {1036296000 -10800 1 -0300}
    {1045364400 -14400 0 -0400}
    {1064372400 -14400 0 -0400}
    {1096603200 -14400 0 -0400}
    {1099368000 -10800 1 -0300}
    {1108868400 -14400 0 -0400}
    {1129435200 -10800 1 -0300}
    {1140318000 -14400 0 -0400}
    {1162699200 -10800 1 -0300}
    {1172372400 -14400 0 -0400}
    {1192334400 -10800 1 -0300}
    {1203217200 -14400 0 -0400}
    {1224388800 -10800 1 -0300}
    {1234666800 -14400 0 -0400}
    {1255838400 -10800 1 -0300}
    {1266721200 -14400 0 -0400}
    {1287288000 -10800 1 -0300}
    {1298170800 -14400 0 -0400}
    {1318737600 -10800 1 -0300}
    {1330225200 -14400 0 -0400}
    {1350792000 -10800 1 -0300}
    {1361070000 -14400 0 -0400}
    {1382241600 -10800 1 -0300}
    {1392519600 -14400 0 -0400}
    {1413691200 -10800 1 -0300}
    {1424574000 -14400 0 -0400}
    {1445140800 -10800 1 -0300}
    {1456023600 -14400 0 -0400}
    {1476590400 -10800 1 -0300}
    {1487473200 -14400 0 -0400}
    {1508040000 -10800 1 -0300}
    {1518922800 -14400 0 -0400}
    {1541304000 -10800 1 -0300}
    {1550372400 -14400 0 -0400}
}

Changes to library/tzdata/America/Curacao.

1


2
3


4
5
6
7
1
2
3


4
5





+
+
-
-
+
+
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico

set TZData(:America/Curacao) {
}
set TZData(:America/Curacao) $TZData(:America/Puerto_Rico)
    {-9223372036854775808 -16547 0 LMT}
    {-1826738653 -16200 0 -0430}
    {-157750200 -14400 0 AST}
}

Changes to library/tzdata/America/Danmarkshavn.

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
30
31
32
33
34
35
36
37

































38
39
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
30
31
32
33
34
35
36
37
38
39




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Danmarkshavn) {
    {-9223372036854775808 -4480 0 LMT}
    {-1686091520 -10800 0 -03}
    {323845200 -7200 0 -02}
    {338950800 -10800 0 -03}
    {354675600 -7200 1 -02}
    {370400400 -10800 0 -03}
    {386125200 -7200 1 -02}
    {401850000 -10800 0 -03}
    {417574800 -7200 1 -02}
    {433299600 -10800 0 -03}
    {449024400 -7200 1 -02}
    {465354000 -10800 0 -03}
    {481078800 -7200 1 -02}
    {496803600 -10800 0 -03}
    {512528400 -7200 1 -02}
    {528253200 -10800 0 -03}
    {543978000 -7200 1 -02}
    {559702800 -10800 0 -03}
    {575427600 -7200 1 -02}
    {591152400 -10800 0 -03}
    {606877200 -7200 1 -02}
    {622602000 -10800 0 -03}
    {638326800 -7200 1 -02}
    {654656400 -10800 0 -03}
    {670381200 -7200 1 -02}
    {686106000 -10800 0 -03}
    {701830800 -7200 1 -02}
    {717555600 -10800 0 -03}
    {733280400 -7200 1 -02}
    {749005200 -10800 0 -03}
    {764730000 -7200 1 -02}
    {780454800 -10800 0 -03}
    {796179600 -7200 1 -02}
    {811904400 -10800 0 -03}
    {-1686091520 -10800 0 -0300}
    {323845200 -7200 0 -0200}
    {338950800 -10800 0 -0300}
    {354675600 -7200 1 -0200}
    {370400400 -10800 0 -0300}
    {386125200 -7200 1 -0200}
    {401850000 -10800 0 -0300}
    {417574800 -7200 1 -0200}
    {433299600 -10800 0 -0300}
    {449024400 -7200 1 -0200}
    {465354000 -10800 0 -0300}
    {481078800 -7200 1 -0200}
    {496803600 -10800 0 -0300}
    {512528400 -7200 1 -0200}
    {528253200 -10800 0 -0300}
    {543978000 -7200 1 -0200}
    {559702800 -10800 0 -0300}
    {575427600 -7200 1 -0200}
    {591152400 -10800 0 -0300}
    {606877200 -7200 1 -0200}
    {622602000 -10800 0 -0300}
    {638326800 -7200 1 -0200}
    {654656400 -10800 0 -0300}
    {670381200 -7200 1 -0200}
    {686106000 -10800 0 -0300}
    {701830800 -7200 1 -0200}
    {717555600 -10800 0 -0300}
    {733280400 -7200 1 -0200}
    {749005200 -10800 0 -0300}
    {764730000 -7200 1 -0200}
    {780454800 -10800 0 -0300}
    {796179600 -7200 1 -0200}
    {811904400 -10800 0 -0300}
    {820465200 0 0 GMT}
}

Changes to library/tzdata/America/Dawson.

1
2
3
4
5
6
7
8
9
10
11
12

13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23












+


+







# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Dawson) {
    {-9223372036854775808 -33460 0 LMT}
    {-2188996940 -32400 0 YST}
    {-1632056400 -28800 1 YDT}
    {-1615125600 -32400 0 YST}
    {-1596978000 -28800 1 YDT}
    {-1583164800 -32400 0 YST}
    {-880203600 -28800 1 YWT}
    {-769395600 -28800 1 YPT}
    {-765381600 -32400 0 YST}
    {-157734000 -32400 0 YST}
    {-147884400 -25200 1 YDDT}
    {-131554800 -32400 0 YST}
    {120646800 -28800 0 PST}
    {315561600 -28800 0 PST}
    {325677600 -25200 1 PDT}
    {341398800 -28800 0 PST}
    {357127200 -25200 1 PDT}
    {372848400 -28800 0 PST}
    {388576800 -25200 1 PDT}
    {404902800 -28800 0 PST}

Changes to library/tzdata/America/Dominica.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Dominica) $TZData(:America/Port_of_Spain)
set TZData(:America/Dominica) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Eirunepe.

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
30
31
32
33
34
35
36
37
38
39
40




































41
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
30
31
32
33
34
35
36
37
38
39
40
41




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Eirunepe) {
    {-9223372036854775808 -16768 0 LMT}
    {-1767208832 -18000 0 -05}
    {-1206950400 -14400 1 -05}
    {-1191355200 -18000 0 -05}
    {-1175367600 -14400 1 -05}
    {-1159819200 -18000 0 -05}
    {-633812400 -14400 1 -05}
    {-622062000 -18000 0 -05}
    {-602276400 -14400 1 -05}
    {-591825600 -18000 0 -05}
    {-570740400 -14400 1 -05}
    {-560203200 -18000 0 -05}
    {-539118000 -14400 1 -05}
    {-531345600 -18000 0 -05}
    {-191358000 -14400 1 -05}
    {-184190400 -18000 0 -05}
    {-155156400 -14400 1 -05}
    {-150062400 -18000 0 -05}
    {-128890800 -14400 1 -05}
    {-121118400 -18000 0 -05}
    {-99946800 -14400 1 -05}
    {-89582400 -18000 0 -05}
    {-68410800 -14400 1 -05}
    {-57960000 -18000 0 -05}
    {499755600 -14400 1 -05}
    {511243200 -18000 0 -05}
    {530600400 -14400 1 -05}
    {540273600 -18000 0 -05}
    {562136400 -14400 1 -05}
    {571204800 -18000 0 -05}
    {590040000 -18000 0 -05}
    {749192400 -18000 0 -05}
    {750834000 -14400 1 -05}
    {761716800 -18000 0 -05}
    {780206400 -18000 0 -05}
    {1214283600 -14400 0 -04}
    {1384056000 -18000 0 -05}
    {-1767208832 -18000 0 -0500}
    {-1206950400 -14400 1 -0400}
    {-1191355200 -18000 0 -0500}
    {-1175367600 -14400 1 -0400}
    {-1159819200 -18000 0 -0500}
    {-633812400 -14400 1 -0400}
    {-622062000 -18000 0 -0500}
    {-602276400 -14400 1 -0400}
    {-591825600 -18000 0 -0500}
    {-570740400 -14400 1 -0400}
    {-560203200 -18000 0 -0500}
    {-539118000 -14400 1 -0400}
    {-531345600 -18000 0 -0500}
    {-191358000 -14400 1 -0400}
    {-184190400 -18000 0 -0500}
    {-155156400 -14400 1 -0400}
    {-150062400 -18000 0 -0500}
    {-128890800 -14400 1 -0400}
    {-121118400 -18000 0 -0500}
    {-99946800 -14400 1 -0400}
    {-89582400 -18000 0 -0500}
    {-68410800 -14400 1 -0400}
    {-57960000 -18000 0 -0500}
    {499755600 -14400 1 -0400}
    {511243200 -18000 0 -0500}
    {530600400 -14400 1 -0400}
    {540273600 -18000 0 -0500}
    {562136400 -14400 1 -0400}
    {571204800 -18000 0 -0500}
    {590040000 -18000 0 -0500}
    {749192400 -18000 0 -0500}
    {750834000 -14400 1 -0400}
    {761716800 -18000 0 -0500}
    {780206400 -18000 0 -0500}
    {1214283600 -14400 0 -0400}
    {1384056000 -18000 0 -0500}
}

Changes to library/tzdata/America/Fortaleza.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47











































48
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Fortaleza) {
    {-9223372036854775808 -9240 0 LMT}
    {-1767216360 -10800 0 -03}
    {-1206957600 -7200 1 -03}
    {-1191362400 -10800 0 -03}
    {-1175374800 -7200 1 -03}
    {-1159826400 -10800 0 -03}
    {-633819600 -7200 1 -03}
    {-622069200 -10800 0 -03}
    {-602283600 -7200 1 -03}
    {-591832800 -10800 0 -03}
    {-570747600 -7200 1 -03}
    {-560210400 -10800 0 -03}
    {-539125200 -7200 1 -03}
    {-531352800 -10800 0 -03}
    {-191365200 -7200 1 -03}
    {-184197600 -10800 0 -03}
    {-155163600 -7200 1 -03}
    {-150069600 -10800 0 -03}
    {-128898000 -7200 1 -03}
    {-121125600 -10800 0 -03}
    {-99954000 -7200 1 -03}
    {-89589600 -10800 0 -03}
    {-68418000 -7200 1 -03}
    {-57967200 -10800 0 -03}
    {499748400 -7200 1 -03}
    {511236000 -10800 0 -03}
    {530593200 -7200 1 -03}
    {540266400 -10800 0 -03}
    {562129200 -7200 1 -03}
    {571197600 -10800 0 -03}
    {592974000 -7200 1 -03}
    {602042400 -10800 0 -03}
    {624423600 -7200 1 -03}
    {634701600 -10800 0 -03}
    {653536800 -10800 0 -03}
    {938660400 -10800 0 -03}
    {938919600 -7200 1 -03}
    {951616800 -10800 0 -03}
    {970974000 -7200 1 -03}
    {972180000 -10800 0 -03}
    {1000350000 -10800 0 -03}
    {1003028400 -7200 1 -03}
    {1013911200 -10800 0 -03}
    {1033437600 -10800 0 -03}
    {-1767216360 -10800 0 -0300}
    {-1206957600 -7200 1 -0200}
    {-1191362400 -10800 0 -0300}
    {-1175374800 -7200 1 -0200}
    {-1159826400 -10800 0 -0300}
    {-633819600 -7200 1 -0200}
    {-622069200 -10800 0 -0300}
    {-602283600 -7200 1 -0200}
    {-591832800 -10800 0 -0300}
    {-570747600 -7200 1 -0200}
    {-560210400 -10800 0 -0300}
    {-539125200 -7200 1 -0200}
    {-531352800 -10800 0 -0300}
    {-191365200 -7200 1 -0200}
    {-184197600 -10800 0 -0300}
    {-155163600 -7200 1 -0200}
    {-150069600 -10800 0 -0300}
    {-128898000 -7200 1 -0200}
    {-121125600 -10800 0 -0300}
    {-99954000 -7200 1 -0200}
    {-89589600 -10800 0 -0300}
    {-68418000 -7200 1 -0200}
    {-57967200 -10800 0 -0300}
    {499748400 -7200 1 -0200}
    {511236000 -10800 0 -0300}
    {530593200 -7200 1 -0200}
    {540266400 -10800 0 -0300}
    {562129200 -7200 1 -0200}
    {571197600 -10800 0 -0300}
    {592974000 -7200 1 -0200}
    {602042400 -10800 0 -0300}
    {624423600 -7200 1 -0200}
    {634701600 -10800 0 -0300}
    {653536800 -10800 0 -0300}
    {938660400 -10800 0 -0300}
    {938919600 -7200 1 -0200}
    {951616800 -10800 0 -0300}
    {970974000 -7200 1 -0200}
    {972180000 -10800 0 -0300}
    {1000350000 -10800 0 -0300}
    {1003028400 -7200 1 -0200}
    {1013911200 -10800 0 -0300}
    {1033437600 -10800 0 -0300}
}

Changes to library/tzdata/America/Grand_Turk.

73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
88
73
74
75
76
77
78
79

80

81
82
83
84
85
86
87







-
+
-







    {1320559200 -18000 0 EST}
    {1331449200 -14400 1 EDT}
    {1352008800 -18000 0 EST}
    {1362898800 -14400 1 EDT}
    {1383458400 -18000 0 EST}
    {1394348400 -14400 1 EDT}
    {1414908000 -18000 0 EST}
    {1425798000 -14400 1 EDT}
    {1425798000 -14400 0 AST}
    {1446361200 -14400 0 AST}
    {1520751600 -14400 0 EDT}
    {1541311200 -18000 0 EST}
    {1552201200 -14400 1 EDT}
    {1572760800 -18000 0 EST}
    {1583650800 -14400 1 EDT}
    {1604210400 -18000 0 EST}
    {1615705200 -14400 1 EDT}

Changes to library/tzdata/America/Grenada.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Grenada) $TZData(:America/Port_of_Spain)
set TZData(:America/Grenada) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Guadeloupe.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Guadeloupe) $TZData(:America/Port_of_Spain)
set TZData(:America/Guadeloupe) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Guayaquil.

1
2
3
4
5
6
7
8



9
1
2
3
4
5



6
7
8
9





-
-
-
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Guayaquil) {
    {-9223372036854775808 -19160 0 LMT}
    {-2524502440 -18840 0 QMT}
    {-1230749160 -18000 0 -05}
    {722926800 -14400 1 -05}
    {728884800 -18000 0 -05}
    {-1230749160 -18000 0 -0500}
    {722926800 -14400 1 -0400}
    {728884800 -18000 0 -0500}
}

Changes to library/tzdata/America/Guyana.

1
2
3
4
5
6
7





8
1
2
3




4
5
6
7
8
9



-
-
-
-
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Guyana) {
    {-9223372036854775808 -13960 0 LMT}
    {-1730578040 -13500 0 -0345}
    {176010300 -10800 0 -03}
    {662698800 -14400 0 -04}
    {-9223372036854775808 -13959 0 LMT}
    {-1843589241 -14400 0 -0400}
    {-1730577600 -13500 0 -0445}
    {176096700 -10800 0 -0300}
    {701841600 -14400 0 -0400}
}

Changes to library/tzdata/America/Hermosillo.

1
2
3
4
5
6

7
8

9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5

6
7

8
9
10
11


12
13
14
15
16
17
18
19





-
+

-
+



-
-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Hermosillo) {
    {-9223372036854775808 -26632 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1343149200 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 0 CST}
    {-1220461200 -21600 1 MDT}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {-873828000 -25200 0 MST}
    {-661539600 -28800 0 PST}
    {28800 -25200 0 MST}
    {820479600 -25200 0 MST}
    {828867600 -21600 1 MDT}
    {846403200 -25200 0 MST}
    {860317200 -21600 1 MDT}
    {877852800 -25200 0 MST}
    {891766800 -21600 1 MDT}
    {909302400 -25200 0 MST}
    {915174000 -25200 0 MST}

Changes to library/tzdata/America/Inuvik.

1
2
3
4
5
6
7
















8
9
10
11
12
13
14
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





-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Inuvik) {
    {-9223372036854775808 0 0 -00}
    {-536457600 -28800 0 PST}
    {-147888000 -21600 1 PDDT}
    {-131558400 -28800 0 PST}
    {73476000 -25200 1 PDT}
    {89197200 -28800 0 PST}
    {104925600 -25200 1 PDT}
    {120646800 -28800 0 PST}
    {136375200 -25200 1 PDT}
    {152096400 -28800 0 PST}
    {167824800 -25200 1 PDT}
    {183546000 -28800 0 PST}
    {199274400 -25200 1 PDT}
    {215600400 -28800 0 PST}
    {230724000 -25200 1 PDT}
    {247050000 -28800 0 PST}
    {262778400 -25200 1 PDT}
    {278499600 -28800 0 PST}
    {294228000 -21600 0 MDT}
    {309945600 -25200 0 MST}
    {315558000 -25200 0 MST}
    {325674000 -21600 1 MDT}
    {341395200 -25200 0 MST}
    {357123600 -21600 1 MDT}
    {372844800 -25200 0 MST}
    {388573200 -21600 1 MDT}
    {404899200 -25200 0 MST}

Changes to library/tzdata/America/Iqaluit.

1
2
3
4
5
6
7


8
9














10
11
12
13
14
15
16
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
30







+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Iqaluit) {
    {-9223372036854775808 0 0 -00}
    {-865296000 -14400 0 EWT}
    {-769395600 -14400 1 EPT}
    {-765396000 -18000 0 EST}
    {73465200 -14400 1 EDT}
    {89186400 -18000 0 EST}
    {-147898800 -10800 1 EDDT}
    {-131569200 -18000 0 EST}
    {104914800 -14400 1 EDT}
    {120636000 -18000 0 EST}
    {136364400 -14400 1 EDT}
    {152085600 -18000 0 EST}
    {167814000 -14400 1 EDT}
    {183535200 -18000 0 EST}
    {199263600 -14400 1 EDT}
    {215589600 -18000 0 EST}
    {230713200 -14400 1 EDT}
    {247039200 -18000 0 EST}
    {262767600 -14400 1 EDT}
    {278488800 -18000 0 EST}
    {294217200 -14400 1 EDT}
    {309938400 -18000 0 EST}
    {325666800 -14400 1 EDT}
    {341388000 -18000 0 EST}
    {357116400 -14400 1 EDT}
    {372837600 -18000 0 EST}
    {388566000 -14400 1 EDT}
    {404892000 -18000 0 EST}
    {420015600 -14400 1 EDT}

Changes to library/tzdata/America/Kralendijk.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Curacao)]} {
    LoadTimeZoneFile America/Curacao
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Kralendijk) $TZData(:America/Curacao)
set TZData(:America/Kralendijk) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/La_Paz.

1
2
3
4
5
6
7

8
1
2
3
4
5
6

7
8






-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/La_Paz) {
    {-9223372036854775808 -16356 0 LMT}
    {-2524505244 -16356 0 CMT}
    {-1205954844 -12756 1 BST}
    {-1192307244 -14400 0 -04}
    {-1192307244 -14400 0 -0400}
}

Changes to library/tzdata/America/Lima.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15










16
1
2
3
4
5










6
7
8
9
10
11
12
13
14
15
16





-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Lima) {
    {-9223372036854775808 -18492 0 LMT}
    {-2524503108 -18516 0 LMT}
    {-1938538284 -14400 0 -05}
    {-1002052800 -18000 0 -05}
    {-986756400 -14400 1 -05}
    {-971035200 -18000 0 -05}
    {-955306800 -14400 1 -05}
    {-939585600 -18000 0 -05}
    {512712000 -18000 0 -05}
    {544248000 -18000 0 -05}
    {638942400 -18000 0 -05}
    {765172800 -18000 0 -05}
    {-1938538284 -14400 0 -0400}
    {-1002052800 -18000 0 -0500}
    {-986756400 -14400 1 -0400}
    {-971035200 -18000 0 -0500}
    {-955306800 -14400 1 -0400}
    {-939585600 -18000 0 -0500}
    {512712000 -18000 0 -0500}
    {544248000 -18000 0 -0500}
    {638942400 -18000 0 -0500}
    {765172800 -18000 0 -0500}
}

Changes to library/tzdata/America/Lower_Princes.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Curacao)]} {
    LoadTimeZoneFile America/Curacao
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Lower_Princes) $TZData(:America/Curacao)
set TZData(:America/Lower_Princes) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Maceio.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51















































52
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Maceio) {
    {-9223372036854775808 -8572 0 LMT}
    {-1767217028 -10800 0 -03}
    {-1206957600 -7200 1 -03}
    {-1191362400 -10800 0 -03}
    {-1175374800 -7200 1 -03}
    {-1159826400 -10800 0 -03}
    {-633819600 -7200 1 -03}
    {-622069200 -10800 0 -03}
    {-602283600 -7200 1 -03}
    {-591832800 -10800 0 -03}
    {-570747600 -7200 1 -03}
    {-560210400 -10800 0 -03}
    {-539125200 -7200 1 -03}
    {-531352800 -10800 0 -03}
    {-191365200 -7200 1 -03}
    {-184197600 -10800 0 -03}
    {-155163600 -7200 1 -03}
    {-150069600 -10800 0 -03}
    {-128898000 -7200 1 -03}
    {-121125600 -10800 0 -03}
    {-99954000 -7200 1 -03}
    {-89589600 -10800 0 -03}
    {-68418000 -7200 1 -03}
    {-57967200 -10800 0 -03}
    {499748400 -7200 1 -03}
    {511236000 -10800 0 -03}
    {530593200 -7200 1 -03}
    {540266400 -10800 0 -03}
    {562129200 -7200 1 -03}
    {571197600 -10800 0 -03}
    {592974000 -7200 1 -03}
    {602042400 -10800 0 -03}
    {624423600 -7200 1 -03}
    {634701600 -10800 0 -03}
    {653536800 -10800 0 -03}
    {813553200 -10800 0 -03}
    {813726000 -7200 1 -03}
    {824004000 -10800 0 -03}
    {841802400 -10800 0 -03}
    {938660400 -10800 0 -03}
    {938919600 -7200 1 -03}
    {951616800 -10800 0 -03}
    {970974000 -7200 1 -03}
    {972180000 -10800 0 -03}
    {1000350000 -10800 0 -03}
    {1003028400 -7200 1 -03}
    {1013911200 -10800 0 -03}
    {1033437600 -10800 0 -03}
    {-1767217028 -10800 0 -0300}
    {-1206957600 -7200 1 -0200}
    {-1191362400 -10800 0 -0300}
    {-1175374800 -7200 1 -0200}
    {-1159826400 -10800 0 -0300}
    {-633819600 -7200 1 -0200}
    {-622069200 -10800 0 -0300}
    {-602283600 -7200 1 -0200}
    {-591832800 -10800 0 -0300}
    {-570747600 -7200 1 -0200}
    {-560210400 -10800 0 -0300}
    {-539125200 -7200 1 -0200}
    {-531352800 -10800 0 -0300}
    {-191365200 -7200 1 -0200}
    {-184197600 -10800 0 -0300}
    {-155163600 -7200 1 -0200}
    {-150069600 -10800 0 -0300}
    {-128898000 -7200 1 -0200}
    {-121125600 -10800 0 -0300}
    {-99954000 -7200 1 -0200}
    {-89589600 -10800 0 -0300}
    {-68418000 -7200 1 -0200}
    {-57967200 -10800 0 -0300}
    {499748400 -7200 1 -0200}
    {511236000 -10800 0 -0300}
    {530593200 -7200 1 -0200}
    {540266400 -10800 0 -0300}
    {562129200 -7200 1 -0200}
    {571197600 -10800 0 -0300}
    {592974000 -7200 1 -0200}
    {602042400 -10800 0 -0300}
    {624423600 -7200 1 -0200}
    {634701600 -10800 0 -0300}
    {653536800 -10800 0 -0300}
    {813553200 -10800 0 -0300}
    {813726000 -7200 1 -0200}
    {824004000 -10800 0 -0300}
    {841802400 -10800 0 -0300}
    {938660400 -10800 0 -0300}
    {938919600 -7200 1 -0200}
    {951616800 -10800 0 -0300}
    {970974000 -7200 1 -0200}
    {972180000 -10800 0 -0300}
    {1000350000 -10800 0 -0300}
    {1003028400 -7200 1 -0200}
    {1013911200 -10800 0 -0300}
    {1033437600 -10800 0 -0300}
}

Changes to library/tzdata/America/Manaus.

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
30
31
32
33
34
35
36
37
38


































39
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
30
31
32
33
34
35
36
37
38
39




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Manaus) {
    {-9223372036854775808 -14404 0 LMT}
    {-1767211196 -14400 0 -04}
    {-1206954000 -10800 1 -04}
    {-1191358800 -14400 0 -04}
    {-1175371200 -10800 1 -04}
    {-1159822800 -14400 0 -04}
    {-633816000 -10800 1 -04}
    {-622065600 -14400 0 -04}
    {-602280000 -10800 1 -04}
    {-591829200 -14400 0 -04}
    {-570744000 -10800 1 -04}
    {-560206800 -14400 0 -04}
    {-539121600 -10800 1 -04}
    {-531349200 -14400 0 -04}
    {-191361600 -10800 1 -04}
    {-184194000 -14400 0 -04}
    {-155160000 -10800 1 -04}
    {-150066000 -14400 0 -04}
    {-128894400 -10800 1 -04}
    {-121122000 -14400 0 -04}
    {-99950400 -10800 1 -04}
    {-89586000 -14400 0 -04}
    {-68414400 -10800 1 -04}
    {-57963600 -14400 0 -04}
    {499752000 -10800 1 -04}
    {511239600 -14400 0 -04}
    {530596800 -10800 1 -04}
    {540270000 -14400 0 -04}
    {562132800 -10800 1 -04}
    {571201200 -14400 0 -04}
    {590036400 -14400 0 -04}
    {749188800 -14400 0 -04}
    {750830400 -10800 1 -04}
    {761713200 -14400 0 -04}
    {780202800 -14400 0 -04}
    {-1767211196 -14400 0 -0400}
    {-1206954000 -10800 1 -0300}
    {-1191358800 -14400 0 -0400}
    {-1175371200 -10800 1 -0300}
    {-1159822800 -14400 0 -0400}
    {-633816000 -10800 1 -0300}
    {-622065600 -14400 0 -0400}
    {-602280000 -10800 1 -0300}
    {-591829200 -14400 0 -0400}
    {-570744000 -10800 1 -0300}
    {-560206800 -14400 0 -0400}
    {-539121600 -10800 1 -0300}
    {-531349200 -14400 0 -0400}
    {-191361600 -10800 1 -0300}
    {-184194000 -14400 0 -0400}
    {-155160000 -10800 1 -0300}
    {-150066000 -14400 0 -0400}
    {-128894400 -10800 1 -0300}
    {-121122000 -14400 0 -0400}
    {-99950400 -10800 1 -0300}
    {-89586000 -14400 0 -0400}
    {-68414400 -10800 1 -0300}
    {-57963600 -14400 0 -0400}
    {499752000 -10800 1 -0300}
    {511239600 -14400 0 -0400}
    {530596800 -10800 1 -0300}
    {540270000 -14400 0 -0400}
    {562132800 -10800 1 -0300}
    {571201200 -14400 0 -0400}
    {590036400 -14400 0 -0400}
    {749188800 -14400 0 -0400}
    {750830400 -10800 1 -0300}
    {761713200 -14400 0 -0400}
    {780202800 -14400 0 -0400}
}

Changes to library/tzdata/America/Marigot.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Marigot) $TZData(:America/Port_of_Spain)
set TZData(:America/Marigot) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Matamoros.

1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Matamoros) {
    {-9223372036854775808 -24000 0 LMT}
    {-9223372036854775808 -23400 0 LMT}
    {-1514743200 -21600 0 CST}
    {568015200 -21600 0 CST}
    {576057600 -18000 1 CDT}
    {594198000 -21600 0 CST}
    {599637600 -21600 0 CST}
    {828864000 -18000 1 CDT}
    {846399600 -21600 0 CST}

Changes to library/tzdata/America/Mazatlan.

1
2
3
4
5
6

7
8

9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5

6
7

8
9
10
11


12
13
14
15
16
17
18
19





-
+

-
+



-
-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Mazatlan) {
    {-9223372036854775808 -25540 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1343149200 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 0 CST}
    {-1220461200 -21600 1 MDT}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {-873828000 -25200 0 MST}
    {-661539600 -28800 0 PST}
    {28800 -25200 0 MST}
    {25200 -25200 0 MST}
    {828867600 -21600 1 MDT}
    {846403200 -25200 0 MST}
    {860317200 -21600 1 MDT}
    {877852800 -25200 0 MST}
    {891766800 -21600 1 MDT}
    {909302400 -25200 0 MST}
    {923216400 -21600 1 MDT}
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
60
61
62
63
64
65
66


























































































































































67







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

    {1572163200 -25200 0 MST}
    {1586077200 -21600 1 MDT}
    {1603612800 -25200 0 MST}
    {1617526800 -21600 1 MDT}
    {1635667200 -25200 0 MST}
    {1648976400 -21600 1 MDT}
    {1667116800 -25200 0 MST}
    {1680426000 -21600 1 MDT}
    {1698566400 -25200 0 MST}
    {1712480400 -21600 1 MDT}
    {1730016000 -25200 0 MST}
    {1743930000 -21600 1 MDT}
    {1761465600 -25200 0 MST}
    {1775379600 -21600 1 MDT}
    {1792915200 -25200 0 MST}
    {1806829200 -21600 1 MDT}
    {1824969600 -25200 0 MST}
    {1838278800 -21600 1 MDT}
    {1856419200 -25200 0 MST}
    {1869728400 -21600 1 MDT}
    {1887868800 -25200 0 MST}
    {1901782800 -21600 1 MDT}
    {1919318400 -25200 0 MST}
    {1933232400 -21600 1 MDT}
    {1950768000 -25200 0 MST}
    {1964682000 -21600 1 MDT}
    {1982822400 -25200 0 MST}
    {1996131600 -21600 1 MDT}
    {2014272000 -25200 0 MST}
    {2027581200 -21600 1 MDT}
    {2045721600 -25200 0 MST}
    {2059030800 -21600 1 MDT}
    {2077171200 -25200 0 MST}
    {2091085200 -21600 1 MDT}
    {2108620800 -25200 0 MST}
    {2122534800 -21600 1 MDT}
    {2140070400 -25200 0 MST}
    {2153984400 -21600 1 MDT}
    {2172124800 -25200 0 MST}
    {2185434000 -21600 1 MDT}
    {2203574400 -25200 0 MST}
    {2216883600 -21600 1 MDT}
    {2235024000 -25200 0 MST}
    {2248938000 -21600 1 MDT}
    {2266473600 -25200 0 MST}
    {2280387600 -21600 1 MDT}
    {2297923200 -25200 0 MST}
    {2311837200 -21600 1 MDT}
    {2329372800 -25200 0 MST}
    {2343286800 -21600 1 MDT}
    {2361427200 -25200 0 MST}
    {2374736400 -21600 1 MDT}
    {2392876800 -25200 0 MST}
    {2406186000 -21600 1 MDT}
    {2424326400 -25200 0 MST}
    {2438240400 -21600 1 MDT}
    {2455776000 -25200 0 MST}
    {2469690000 -21600 1 MDT}
    {2487225600 -25200 0 MST}
    {2501139600 -21600 1 MDT}
    {2519280000 -25200 0 MST}
    {2532589200 -21600 1 MDT}
    {2550729600 -25200 0 MST}
    {2564038800 -21600 1 MDT}
    {2582179200 -25200 0 MST}
    {2596093200 -21600 1 MDT}
    {2613628800 -25200 0 MST}
    {2627542800 -21600 1 MDT}
    {2645078400 -25200 0 MST}
    {2658992400 -21600 1 MDT}
    {2676528000 -25200 0 MST}
    {2690442000 -21600 1 MDT}
    {2708582400 -25200 0 MST}
    {2721891600 -21600 1 MDT}
    {2740032000 -25200 0 MST}
    {2753341200 -21600 1 MDT}
    {2771481600 -25200 0 MST}
    {2785395600 -21600 1 MDT}
    {2802931200 -25200 0 MST}
    {2816845200 -21600 1 MDT}
    {2834380800 -25200 0 MST}
    {2848294800 -21600 1 MDT}
    {2866435200 -25200 0 MST}
    {2879744400 -21600 1 MDT}
    {2897884800 -25200 0 MST}
    {2911194000 -21600 1 MDT}
    {2929334400 -25200 0 MST}
    {2942643600 -21600 1 MDT}
    {2960784000 -25200 0 MST}
    {2974698000 -21600 1 MDT}
    {2992233600 -25200 0 MST}
    {3006147600 -21600 1 MDT}
    {3023683200 -25200 0 MST}
    {3037597200 -21600 1 MDT}
    {3055737600 -25200 0 MST}
    {3069046800 -21600 1 MDT}
    {3087187200 -25200 0 MST}
    {3100496400 -21600 1 MDT}
    {3118636800 -25200 0 MST}
    {3132550800 -21600 1 MDT}
    {3150086400 -25200 0 MST}
    {3164000400 -21600 1 MDT}
    {3181536000 -25200 0 MST}
    {3195450000 -21600 1 MDT}
    {3212985600 -25200 0 MST}
    {3226899600 -21600 1 MDT}
    {3245040000 -25200 0 MST}
    {3258349200 -21600 1 MDT}
    {3276489600 -25200 0 MST}
    {3289798800 -21600 1 MDT}
    {3307939200 -25200 0 MST}
    {3321853200 -21600 1 MDT}
    {3339388800 -25200 0 MST}
    {3353302800 -21600 1 MDT}
    {3370838400 -25200 0 MST}
    {3384752400 -21600 1 MDT}
    {3402892800 -25200 0 MST}
    {3416202000 -21600 1 MDT}
    {3434342400 -25200 0 MST}
    {3447651600 -21600 1 MDT}
    {3465792000 -25200 0 MST}
    {3479706000 -21600 1 MDT}
    {3497241600 -25200 0 MST}
    {3511155600 -21600 1 MDT}
    {3528691200 -25200 0 MST}
    {3542605200 -21600 1 MDT}
    {3560140800 -25200 0 MST}
    {3574054800 -21600 1 MDT}
    {3592195200 -25200 0 MST}
    {3605504400 -21600 1 MDT}
    {3623644800 -25200 0 MST}
    {3636954000 -21600 1 MDT}
    {3655094400 -25200 0 MST}
    {3669008400 -21600 1 MDT}
    {3686544000 -25200 0 MST}
    {3700458000 -21600 1 MDT}
    {3717993600 -25200 0 MST}
    {3731907600 -21600 1 MDT}
    {3750048000 -25200 0 MST}
    {3763357200 -21600 1 MDT}
    {3781497600 -25200 0 MST}
    {3794806800 -21600 1 MDT}
    {3812947200 -25200 0 MST}
    {3826256400 -21600 1 MDT}
    {3844396800 -25200 0 MST}
    {3858310800 -21600 1 MDT}
    {3875846400 -25200 0 MST}
    {3889760400 -21600 1 MDT}
    {3907296000 -25200 0 MST}
    {3921210000 -21600 1 MDT}
    {3939350400 -25200 0 MST}
    {3952659600 -21600 1 MDT}
    {3970800000 -25200 0 MST}
    {3984109200 -21600 1 MDT}
    {4002249600 -25200 0 MST}
    {4016163600 -21600 1 MDT}
    {4033699200 -25200 0 MST}
    {4047613200 -21600 1 MDT}
    {4065148800 -25200 0 MST}
    {4079062800 -21600 1 MDT}
    {4096598400 -25200 0 MST}
}

Changes to library/tzdata/America/Merida.

1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Merida) {
    {-9223372036854775808 -21508 0 LMT}
    {-1514743200 -21600 0 CST}
    {377935200 -18000 0 EST}
    {407653200 -21600 0 CST}
    {378201600 -18000 0 EST}
    {405068400 -21600 0 CST}
    {828864000 -18000 1 CDT}
    {846399600 -21600 0 CST}
    {860313600 -18000 1 CDT}
    {877849200 -21600 0 CST}
    {891763200 -18000 1 CDT}
    {909298800 -21600 0 CST}
    {923212800 -18000 1 CDT}
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
55
56
57
58
59
60
61


























































































































































62







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

    {1572159600 -21600 0 CST}
    {1586073600 -18000 1 CDT}
    {1603609200 -21600 0 CST}
    {1617523200 -18000 1 CDT}
    {1635663600 -21600 0 CST}
    {1648972800 -18000 1 CDT}
    {1667113200 -21600 0 CST}
    {1680422400 -18000 1 CDT}
    {1698562800 -21600 0 CST}
    {1712476800 -18000 1 CDT}
    {1730012400 -21600 0 CST}
    {1743926400 -18000 1 CDT}
    {1761462000 -21600 0 CST}
    {1775376000 -18000 1 CDT}
    {1792911600 -21600 0 CST}
    {1806825600 -18000 1 CDT}
    {1824966000 -21600 0 CST}
    {1838275200 -18000 1 CDT}
    {1856415600 -21600 0 CST}
    {1869724800 -18000 1 CDT}
    {1887865200 -21600 0 CST}
    {1901779200 -18000 1 CDT}
    {1919314800 -21600 0 CST}
    {1933228800 -18000 1 CDT}
    {1950764400 -21600 0 CST}
    {1964678400 -18000 1 CDT}
    {1982818800 -21600 0 CST}
    {1996128000 -18000 1 CDT}
    {2014268400 -21600 0 CST}
    {2027577600 -18000 1 CDT}
    {2045718000 -21600 0 CST}
    {2059027200 -18000 1 CDT}
    {2077167600 -21600 0 CST}
    {2091081600 -18000 1 CDT}
    {2108617200 -21600 0 CST}
    {2122531200 -18000 1 CDT}
    {2140066800 -21600 0 CST}
    {2153980800 -18000 1 CDT}
    {2172121200 -21600 0 CST}
    {2185430400 -18000 1 CDT}
    {2203570800 -21600 0 CST}
    {2216880000 -18000 1 CDT}
    {2235020400 -21600 0 CST}
    {2248934400 -18000 1 CDT}
    {2266470000 -21600 0 CST}
    {2280384000 -18000 1 CDT}
    {2297919600 -21600 0 CST}
    {2311833600 -18000 1 CDT}
    {2329369200 -21600 0 CST}
    {2343283200 -18000 1 CDT}
    {2361423600 -21600 0 CST}
    {2374732800 -18000 1 CDT}
    {2392873200 -21600 0 CST}
    {2406182400 -18000 1 CDT}
    {2424322800 -21600 0 CST}
    {2438236800 -18000 1 CDT}
    {2455772400 -21600 0 CST}
    {2469686400 -18000 1 CDT}
    {2487222000 -21600 0 CST}
    {2501136000 -18000 1 CDT}
    {2519276400 -21600 0 CST}
    {2532585600 -18000 1 CDT}
    {2550726000 -21600 0 CST}
    {2564035200 -18000 1 CDT}
    {2582175600 -21600 0 CST}
    {2596089600 -18000 1 CDT}
    {2613625200 -21600 0 CST}
    {2627539200 -18000 1 CDT}
    {2645074800 -21600 0 CST}
    {2658988800 -18000 1 CDT}
    {2676524400 -21600 0 CST}
    {2690438400 -18000 1 CDT}
    {2708578800 -21600 0 CST}
    {2721888000 -18000 1 CDT}
    {2740028400 -21600 0 CST}
    {2753337600 -18000 1 CDT}
    {2771478000 -21600 0 CST}
    {2785392000 -18000 1 CDT}
    {2802927600 -21600 0 CST}
    {2816841600 -18000 1 CDT}
    {2834377200 -21600 0 CST}
    {2848291200 -18000 1 CDT}
    {2866431600 -21600 0 CST}
    {2879740800 -18000 1 CDT}
    {2897881200 -21600 0 CST}
    {2911190400 -18000 1 CDT}
    {2929330800 -21600 0 CST}
    {2942640000 -18000 1 CDT}
    {2960780400 -21600 0 CST}
    {2974694400 -18000 1 CDT}
    {2992230000 -21600 0 CST}
    {3006144000 -18000 1 CDT}
    {3023679600 -21600 0 CST}
    {3037593600 -18000 1 CDT}
    {3055734000 -21600 0 CST}
    {3069043200 -18000 1 CDT}
    {3087183600 -21600 0 CST}
    {3100492800 -18000 1 CDT}
    {3118633200 -21600 0 CST}
    {3132547200 -18000 1 CDT}
    {3150082800 -21600 0 CST}
    {3163996800 -18000 1 CDT}
    {3181532400 -21600 0 CST}
    {3195446400 -18000 1 CDT}
    {3212982000 -21600 0 CST}
    {3226896000 -18000 1 CDT}
    {3245036400 -21600 0 CST}
    {3258345600 -18000 1 CDT}
    {3276486000 -21600 0 CST}
    {3289795200 -18000 1 CDT}
    {3307935600 -21600 0 CST}
    {3321849600 -18000 1 CDT}
    {3339385200 -21600 0 CST}
    {3353299200 -18000 1 CDT}
    {3370834800 -21600 0 CST}
    {3384748800 -18000 1 CDT}
    {3402889200 -21600 0 CST}
    {3416198400 -18000 1 CDT}
    {3434338800 -21600 0 CST}
    {3447648000 -18000 1 CDT}
    {3465788400 -21600 0 CST}
    {3479702400 -18000 1 CDT}
    {3497238000 -21600 0 CST}
    {3511152000 -18000 1 CDT}
    {3528687600 -21600 0 CST}
    {3542601600 -18000 1 CDT}
    {3560137200 -21600 0 CST}
    {3574051200 -18000 1 CDT}
    {3592191600 -21600 0 CST}
    {3605500800 -18000 1 CDT}
    {3623641200 -21600 0 CST}
    {3636950400 -18000 1 CDT}
    {3655090800 -21600 0 CST}
    {3669004800 -18000 1 CDT}
    {3686540400 -21600 0 CST}
    {3700454400 -18000 1 CDT}
    {3717990000 -21600 0 CST}
    {3731904000 -18000 1 CDT}
    {3750044400 -21600 0 CST}
    {3763353600 -18000 1 CDT}
    {3781494000 -21600 0 CST}
    {3794803200 -18000 1 CDT}
    {3812943600 -21600 0 CST}
    {3826252800 -18000 1 CDT}
    {3844393200 -21600 0 CST}
    {3858307200 -18000 1 CDT}
    {3875842800 -21600 0 CST}
    {3889756800 -18000 1 CDT}
    {3907292400 -21600 0 CST}
    {3921206400 -18000 1 CDT}
    {3939346800 -21600 0 CST}
    {3952656000 -18000 1 CDT}
    {3970796400 -21600 0 CST}
    {3984105600 -18000 1 CDT}
    {4002246000 -21600 0 CST}
    {4016160000 -18000 1 CDT}
    {4033695600 -21600 0 CST}
    {4047609600 -18000 1 CDT}
    {4065145200 -21600 0 CST}
    {4079059200 -18000 1 CDT}
    {4096594800 -21600 0 CST}
}

Changes to library/tzdata/America/Mexico_City.

1
2
3
4
5
6

7
8

9
10
11
12
13
14
15
1
2
3
4
5

6
7

8
9
10
11
12
13
14
15





-
+

-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Mexico_City) {
    {-9223372036854775808 -23796 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1343149200 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 0 CST}
    {-1220461200 -21600 1 MDT}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {-975261600 -18000 1 CDT}
    {-963169200 -21600 0 CST}
    {-917114400 -18000 1 CDT}
    {-907354800 -21600 0 CST}
    {-821901600 -18000 1 CWT}
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
67
68
69
70
71
72
73


























































































































































74







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

    {1572159600 -21600 0 CST}
    {1586073600 -18000 1 CDT}
    {1603609200 -21600 0 CST}
    {1617523200 -18000 1 CDT}
    {1635663600 -21600 0 CST}
    {1648972800 -18000 1 CDT}
    {1667113200 -21600 0 CST}
    {1680422400 -18000 1 CDT}
    {1698562800 -21600 0 CST}
    {1712476800 -18000 1 CDT}
    {1730012400 -21600 0 CST}
    {1743926400 -18000 1 CDT}
    {1761462000 -21600 0 CST}
    {1775376000 -18000 1 CDT}
    {1792911600 -21600 0 CST}
    {1806825600 -18000 1 CDT}
    {1824966000 -21600 0 CST}
    {1838275200 -18000 1 CDT}
    {1856415600 -21600 0 CST}
    {1869724800 -18000 1 CDT}
    {1887865200 -21600 0 CST}
    {1901779200 -18000 1 CDT}
    {1919314800 -21600 0 CST}
    {1933228800 -18000 1 CDT}
    {1950764400 -21600 0 CST}
    {1964678400 -18000 1 CDT}
    {1982818800 -21600 0 CST}
    {1996128000 -18000 1 CDT}
    {2014268400 -21600 0 CST}
    {2027577600 -18000 1 CDT}
    {2045718000 -21600 0 CST}
    {2059027200 -18000 1 CDT}
    {2077167600 -21600 0 CST}
    {2091081600 -18000 1 CDT}
    {2108617200 -21600 0 CST}
    {2122531200 -18000 1 CDT}
    {2140066800 -21600 0 CST}
    {2153980800 -18000 1 CDT}
    {2172121200 -21600 0 CST}
    {2185430400 -18000 1 CDT}
    {2203570800 -21600 0 CST}
    {2216880000 -18000 1 CDT}
    {2235020400 -21600 0 CST}
    {2248934400 -18000 1 CDT}
    {2266470000 -21600 0 CST}
    {2280384000 -18000 1 CDT}
    {2297919600 -21600 0 CST}
    {2311833600 -18000 1 CDT}
    {2329369200 -21600 0 CST}
    {2343283200 -18000 1 CDT}
    {2361423600 -21600 0 CST}
    {2374732800 -18000 1 CDT}
    {2392873200 -21600 0 CST}
    {2406182400 -18000 1 CDT}
    {2424322800 -21600 0 CST}
    {2438236800 -18000 1 CDT}
    {2455772400 -21600 0 CST}
    {2469686400 -18000 1 CDT}
    {2487222000 -21600 0 CST}
    {2501136000 -18000 1 CDT}
    {2519276400 -21600 0 CST}
    {2532585600 -18000 1 CDT}
    {2550726000 -21600 0 CST}
    {2564035200 -18000 1 CDT}
    {2582175600 -21600 0 CST}
    {2596089600 -18000 1 CDT}
    {2613625200 -21600 0 CST}
    {2627539200 -18000 1 CDT}
    {2645074800 -21600 0 CST}
    {2658988800 -18000 1 CDT}
    {2676524400 -21600 0 CST}
    {2690438400 -18000 1 CDT}
    {2708578800 -21600 0 CST}
    {2721888000 -18000 1 CDT}
    {2740028400 -21600 0 CST}
    {2753337600 -18000 1 CDT}
    {2771478000 -21600 0 CST}
    {2785392000 -18000 1 CDT}
    {2802927600 -21600 0 CST}
    {2816841600 -18000 1 CDT}
    {2834377200 -21600 0 CST}
    {2848291200 -18000 1 CDT}
    {2866431600 -21600 0 CST}
    {2879740800 -18000 1 CDT}
    {2897881200 -21600 0 CST}
    {2911190400 -18000 1 CDT}
    {2929330800 -21600 0 CST}
    {2942640000 -18000 1 CDT}
    {2960780400 -21600 0 CST}
    {2974694400 -18000 1 CDT}
    {2992230000 -21600 0 CST}
    {3006144000 -18000 1 CDT}
    {3023679600 -21600 0 CST}
    {3037593600 -18000 1 CDT}
    {3055734000 -21600 0 CST}
    {3069043200 -18000 1 CDT}
    {3087183600 -21600 0 CST}
    {3100492800 -18000 1 CDT}
    {3118633200 -21600 0 CST}
    {3132547200 -18000 1 CDT}
    {3150082800 -21600 0 CST}
    {3163996800 -18000 1 CDT}
    {3181532400 -21600 0 CST}
    {3195446400 -18000 1 CDT}
    {3212982000 -21600 0 CST}
    {3226896000 -18000 1 CDT}
    {3245036400 -21600 0 CST}
    {3258345600 -18000 1 CDT}
    {3276486000 -21600 0 CST}
    {3289795200 -18000 1 CDT}
    {3307935600 -21600 0 CST}
    {3321849600 -18000 1 CDT}
    {3339385200 -21600 0 CST}
    {3353299200 -18000 1 CDT}
    {3370834800 -21600 0 CST}
    {3384748800 -18000 1 CDT}
    {3402889200 -21600 0 CST}
    {3416198400 -18000 1 CDT}
    {3434338800 -21600 0 CST}
    {3447648000 -18000 1 CDT}
    {3465788400 -21600 0 CST}
    {3479702400 -18000 1 CDT}
    {3497238000 -21600 0 CST}
    {3511152000 -18000 1 CDT}
    {3528687600 -21600 0 CST}
    {3542601600 -18000 1 CDT}
    {3560137200 -21600 0 CST}
    {3574051200 -18000 1 CDT}
    {3592191600 -21600 0 CST}
    {3605500800 -18000 1 CDT}
    {3623641200 -21600 0 CST}
    {3636950400 -18000 1 CDT}
    {3655090800 -21600 0 CST}
    {3669004800 -18000 1 CDT}
    {3686540400 -21600 0 CST}
    {3700454400 -18000 1 CDT}
    {3717990000 -21600 0 CST}
    {3731904000 -18000 1 CDT}
    {3750044400 -21600 0 CST}
    {3763353600 -18000 1 CDT}
    {3781494000 -21600 0 CST}
    {3794803200 -18000 1 CDT}
    {3812943600 -21600 0 CST}
    {3826252800 -18000 1 CDT}
    {3844393200 -21600 0 CST}
    {3858307200 -18000 1 CDT}
    {3875842800 -21600 0 CST}
    {3889756800 -18000 1 CDT}
    {3907292400 -21600 0 CST}
    {3921206400 -18000 1 CDT}
    {3939346800 -21600 0 CST}
    {3952656000 -18000 1 CDT}
    {3970796400 -21600 0 CST}
    {3984105600 -18000 1 CDT}
    {4002246000 -21600 0 CST}
    {4016160000 -18000 1 CDT}
    {4033695600 -21600 0 CST}
    {4047609600 -18000 1 CDT}
    {4065145200 -21600 0 CST}
    {4079059200 -18000 1 CDT}
    {4096594800 -21600 0 CST}
}

Changes to library/tzdata/America/Miquelon.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Miquelon) {
    {-9223372036854775808 -13480 0 LMT}
    {-1850328920 -14400 0 AST}
    {326001600 -10800 0 -03}
    {536468400 -10800 0 -02}
    {544597200 -7200 1 -02}
    {562132800 -10800 0 -02}
    {576046800 -7200 1 -02}
    {594187200 -10800 0 -02}
    {607496400 -7200 1 -02}
    {625636800 -10800 0 -02}
    {638946000 -7200 1 -02}
    {657086400 -10800 0 -02}
    {671000400 -7200 1 -02}
    {688536000 -10800 0 -02}
    {702450000 -7200 1 -02}
    {719985600 -10800 0 -02}
    {733899600 -7200 1 -02}
    {752040000 -10800 0 -02}
    {765349200 -7200 1 -02}
    {783489600 -10800 0 -02}
    {796798800 -7200 1 -02}
    {814939200 -10800 0 -02}
    {828853200 -7200 1 -02}
    {846388800 -10800 0 -02}
    {860302800 -7200 1 -02}
    {877838400 -10800 0 -02}
    {891752400 -7200 1 -02}
    {909288000 -10800 0 -02}
    {923202000 -7200 1 -02}
    {941342400 -10800 0 -02}
    {954651600 -7200 1 -02}
    {972792000 -10800 0 -02}
    {986101200 -7200 1 -02}
    {1004241600 -10800 0 -02}
    {1018155600 -7200 1 -02}
    {1035691200 -10800 0 -02}
    {1049605200 -7200 1 -02}
    {1067140800 -10800 0 -02}
    {1081054800 -7200 1 -02}
    {1099195200 -10800 0 -02}
    {1112504400 -7200 1 -02}
    {1130644800 -10800 0 -02}
    {1143954000 -7200 1 -02}
    {1162094400 -10800 0 -02}
    {1173589200 -7200 1 -02}
    {1194148800 -10800 0 -02}
    {1205038800 -7200 1 -02}
    {1225598400 -10800 0 -02}
    {1236488400 -7200 1 -02}
    {1257048000 -10800 0 -02}
    {1268542800 -7200 1 -02}
    {1289102400 -10800 0 -02}
    {1299992400 -7200 1 -02}
    {1320552000 -10800 0 -02}
    {1331442000 -7200 1 -02}
    {1352001600 -10800 0 -02}
    {1362891600 -7200 1 -02}
    {1383451200 -10800 0 -02}
    {1394341200 -7200 1 -02}
    {1414900800 -10800 0 -02}
    {1425790800 -7200 1 -02}
    {1446350400 -10800 0 -02}
    {1457845200 -7200 1 -02}
    {1478404800 -10800 0 -02}
    {1489294800 -7200 1 -02}
    {1509854400 -10800 0 -02}
    {1520744400 -7200 1 -02}
    {1541304000 -10800 0 -02}
    {1552194000 -7200 1 -02}
    {1572753600 -10800 0 -02}
    {1583643600 -7200 1 -02}
    {1604203200 -10800 0 -02}
    {1615698000 -7200 1 -02}
    {1636257600 -10800 0 -02}
    {1647147600 -7200 1 -02}
    {1667707200 -10800 0 -02}
    {1678597200 -7200 1 -02}
    {1699156800 -10800 0 -02}
    {1710046800 -7200 1 -02}
    {1730606400 -10800 0 -02}
    {1741496400 -7200 1 -02}
    {1762056000 -10800 0 -02}
    {1772946000 -7200 1 -02}
    {1793505600 -10800 0 -02}
    {1805000400 -7200 1 -02}
    {1825560000 -10800 0 -02}
    {1836450000 -7200 1 -02}
    {1857009600 -10800 0 -02}
    {1867899600 -7200 1 -02}
    {1888459200 -10800 0 -02}
    {1899349200 -7200 1 -02}
    {1919908800 -10800 0 -02}
    {1930798800 -7200 1 -02}
    {1951358400 -10800 0 -02}
    {1962853200 -7200 1 -02}
    {1983412800 -10800 0 -02}
    {1994302800 -7200 1 -02}
    {2014862400 -10800 0 -02}
    {2025752400 -7200 1 -02}
    {2046312000 -10800 0 -02}
    {2057202000 -7200 1 -02}
    {2077761600 -10800 0 -02}
    {2088651600 -7200 1 -02}
    {2109211200 -10800 0 -02}
    {2120101200 -7200 1 -02}
    {2140660800 -10800 0 -02}
    {2152155600 -7200 1 -02}
    {2172715200 -10800 0 -02}
    {2183605200 -7200 1 -02}
    {2204164800 -10800 0 -02}
    {2215054800 -7200 1 -02}
    {2235614400 -10800 0 -02}
    {2246504400 -7200 1 -02}
    {2267064000 -10800 0 -02}
    {2277954000 -7200 1 -02}
    {2298513600 -10800 0 -02}
    {2309403600 -7200 1 -02}
    {2329963200 -10800 0 -02}
    {2341458000 -7200 1 -02}
    {2362017600 -10800 0 -02}
    {2372907600 -7200 1 -02}
    {2393467200 -10800 0 -02}
    {2404357200 -7200 1 -02}
    {2424916800 -10800 0 -02}
    {2435806800 -7200 1 -02}
    {2456366400 -10800 0 -02}
    {2467256400 -7200 1 -02}
    {2487816000 -10800 0 -02}
    {2499310800 -7200 1 -02}
    {2519870400 -10800 0 -02}
    {2530760400 -7200 1 -02}
    {2551320000 -10800 0 -02}
    {2562210000 -7200 1 -02}
    {2582769600 -10800 0 -02}
    {2593659600 -7200 1 -02}
    {2614219200 -10800 0 -02}
    {2625109200 -7200 1 -02}
    {2645668800 -10800 0 -02}
    {2656558800 -7200 1 -02}
    {2677118400 -10800 0 -02}
    {2688613200 -7200 1 -02}
    {2709172800 -10800 0 -02}
    {2720062800 -7200 1 -02}
    {2740622400 -10800 0 -02}
    {2751512400 -7200 1 -02}
    {2772072000 -10800 0 -02}
    {2782962000 -7200 1 -02}
    {2803521600 -10800 0 -02}
    {2814411600 -7200 1 -02}
    {2834971200 -10800 0 -02}
    {2846466000 -7200 1 -02}
    {2867025600 -10800 0 -02}
    {2877915600 -7200 1 -02}
    {2898475200 -10800 0 -02}
    {2909365200 -7200 1 -02}
    {2929924800 -10800 0 -02}
    {2940814800 -7200 1 -02}
    {2961374400 -10800 0 -02}
    {2972264400 -7200 1 -02}
    {2992824000 -10800 0 -02}
    {3003714000 -7200 1 -02}
    {3024273600 -10800 0 -02}
    {3035768400 -7200 1 -02}
    {3056328000 -10800 0 -02}
    {3067218000 -7200 1 -02}
    {3087777600 -10800 0 -02}
    {3098667600 -7200 1 -02}
    {3119227200 -10800 0 -02}
    {3130117200 -7200 1 -02}
    {3150676800 -10800 0 -02}
    {3161566800 -7200 1 -02}
    {3182126400 -10800 0 -02}
    {3193016400 -7200 1 -02}
    {3213576000 -10800 0 -02}
    {3225070800 -7200 1 -02}
    {3245630400 -10800 0 -02}
    {3256520400 -7200 1 -02}
    {3277080000 -10800 0 -02}
    {3287970000 -7200 1 -02}
    {3308529600 -10800 0 -02}
    {3319419600 -7200 1 -02}
    {3339979200 -10800 0 -02}
    {3350869200 -7200 1 -02}
    {3371428800 -10800 0 -02}
    {3382923600 -7200 1 -02}
    {3403483200 -10800 0 -02}
    {3414373200 -7200 1 -02}
    {3434932800 -10800 0 -02}
    {3445822800 -7200 1 -02}
    {3466382400 -10800 0 -02}
    {3477272400 -7200 1 -02}
    {3497832000 -10800 0 -02}
    {3508722000 -7200 1 -02}
    {3529281600 -10800 0 -02}
    {3540171600 -7200 1 -02}
    {3560731200 -10800 0 -02}
    {3572226000 -7200 1 -02}
    {3592785600 -10800 0 -02}
    {3603675600 -7200 1 -02}
    {3624235200 -10800 0 -02}
    {3635125200 -7200 1 -02}
    {3655684800 -10800 0 -02}
    {3666574800 -7200 1 -02}
    {3687134400 -10800 0 -02}
    {3698024400 -7200 1 -02}
    {3718584000 -10800 0 -02}
    {3730078800 -7200 1 -02}
    {3750638400 -10800 0 -02}
    {3761528400 -7200 1 -02}
    {3782088000 -10800 0 -02}
    {3792978000 -7200 1 -02}
    {3813537600 -10800 0 -02}
    {3824427600 -7200 1 -02}
    {3844987200 -10800 0 -02}
    {3855877200 -7200 1 -02}
    {3876436800 -10800 0 -02}
    {3887326800 -7200 1 -02}
    {3907886400 -10800 0 -02}
    {3919381200 -7200 1 -02}
    {3939940800 -10800 0 -02}
    {3950830800 -7200 1 -02}
    {3971390400 -10800 0 -02}
    {3982280400 -7200 1 -02}
    {4002840000 -10800 0 -02}
    {4013730000 -7200 1 -02}
    {4034289600 -10800 0 -02}
    {4045179600 -7200 1 -02}
    {4065739200 -10800 0 -02}
    {4076629200 -7200 1 -02}
    {4097188800 -10800 0 -02}
    {-1847650520 -14400 0 AST}
    {326001600 -10800 0 -0300}
    {536468400 -10800 0 -0300}
    {544597200 -7200 1 -0200}
    {562132800 -10800 0 -0300}
    {576046800 -7200 1 -0200}
    {594187200 -10800 0 -0300}
    {607496400 -7200 1 -0200}
    {625636800 -10800 0 -0300}
    {638946000 -7200 1 -0200}
    {657086400 -10800 0 -0300}
    {671000400 -7200 1 -0200}
    {688536000 -10800 0 -0300}
    {702450000 -7200 1 -0200}
    {719985600 -10800 0 -0300}
    {733899600 -7200 1 -0200}
    {752040000 -10800 0 -0300}
    {765349200 -7200 1 -0200}
    {783489600 -10800 0 -0300}
    {796798800 -7200 1 -0200}
    {814939200 -10800 0 -0300}
    {828853200 -7200 1 -0200}
    {846388800 -10800 0 -0300}
    {860302800 -7200 1 -0200}
    {877838400 -10800 0 -0300}
    {891752400 -7200 1 -0200}
    {909288000 -10800 0 -0300}
    {923202000 -7200 1 -0200}
    {941342400 -10800 0 -0300}
    {954651600 -7200 1 -0200}
    {972792000 -10800 0 -0300}
    {986101200 -7200 1 -0200}
    {1004241600 -10800 0 -0300}
    {1018155600 -7200 1 -0200}
    {1035691200 -10800 0 -0300}
    {1049605200 -7200 1 -0200}
    {1067140800 -10800 0 -0300}
    {1081054800 -7200 1 -0200}
    {1099195200 -10800 0 -0300}
    {1112504400 -7200 1 -0200}
    {1130644800 -10800 0 -0300}
    {1143954000 -7200 1 -0200}
    {1162094400 -10800 0 -0300}
    {1173589200 -7200 1 -0200}
    {1194148800 -10800 0 -0300}
    {1205038800 -7200 1 -0200}
    {1225598400 -10800 0 -0300}
    {1236488400 -7200 1 -0200}
    {1257048000 -10800 0 -0300}
    {1268542800 -7200 1 -0200}
    {1289102400 -10800 0 -0300}
    {1299992400 -7200 1 -0200}
    {1320552000 -10800 0 -0300}
    {1331442000 -7200 1 -0200}
    {1352001600 -10800 0 -0300}
    {1362891600 -7200 1 -0200}
    {1383451200 -10800 0 -0300}
    {1394341200 -7200 1 -0200}
    {1414900800 -10800 0 -0300}
    {1425790800 -7200 1 -0200}
    {1446350400 -10800 0 -0300}
    {1457845200 -7200 1 -0200}
    {1478404800 -10800 0 -0300}
    {1489294800 -7200 1 -0200}
    {1509854400 -10800 0 -0300}
    {1520744400 -7200 1 -0200}
    {1541304000 -10800 0 -0300}
    {1552194000 -7200 1 -0200}
    {1572753600 -10800 0 -0300}
    {1583643600 -7200 1 -0200}
    {1604203200 -10800 0 -0300}
    {1615698000 -7200 1 -0200}
    {1636257600 -10800 0 -0300}
    {1647147600 -7200 1 -0200}
    {1667707200 -10800 0 -0300}
    {1678597200 -7200 1 -0200}
    {1699156800 -10800 0 -0300}
    {1710046800 -7200 1 -0200}
    {1730606400 -10800 0 -0300}
    {1741496400 -7200 1 -0200}
    {1762056000 -10800 0 -0300}
    {1772946000 -7200 1 -0200}
    {1793505600 -10800 0 -0300}
    {1805000400 -7200 1 -0200}
    {1825560000 -10800 0 -0300}
    {1836450000 -7200 1 -0200}
    {1857009600 -10800 0 -0300}
    {1867899600 -7200 1 -0200}
    {1888459200 -10800 0 -0300}
    {1899349200 -7200 1 -0200}
    {1919908800 -10800 0 -0300}
    {1930798800 -7200 1 -0200}
    {1951358400 -10800 0 -0300}
    {1962853200 -7200 1 -0200}
    {1983412800 -10800 0 -0300}
    {1994302800 -7200 1 -0200}
    {2014862400 -10800 0 -0300}
    {2025752400 -7200 1 -0200}
    {2046312000 -10800 0 -0300}
    {2057202000 -7200 1 -0200}
    {2077761600 -10800 0 -0300}
    {2088651600 -7200 1 -0200}
    {2109211200 -10800 0 -0300}
    {2120101200 -7200 1 -0200}
    {2140660800 -10800 0 -0300}
    {2152155600 -7200 1 -0200}
    {2172715200 -10800 0 -0300}
    {2183605200 -7200 1 -0200}
    {2204164800 -10800 0 -0300}
    {2215054800 -7200 1 -0200}
    {2235614400 -10800 0 -0300}
    {2246504400 -7200 1 -0200}
    {2267064000 -10800 0 -0300}
    {2277954000 -7200 1 -0200}
    {2298513600 -10800 0 -0300}
    {2309403600 -7200 1 -0200}
    {2329963200 -10800 0 -0300}
    {2341458000 -7200 1 -0200}
    {2362017600 -10800 0 -0300}
    {2372907600 -7200 1 -0200}
    {2393467200 -10800 0 -0300}
    {2404357200 -7200 1 -0200}
    {2424916800 -10800 0 -0300}
    {2435806800 -7200 1 -0200}
    {2456366400 -10800 0 -0300}
    {2467256400 -7200 1 -0200}
    {2487816000 -10800 0 -0300}
    {2499310800 -7200 1 -0200}
    {2519870400 -10800 0 -0300}
    {2530760400 -7200 1 -0200}
    {2551320000 -10800 0 -0300}
    {2562210000 -7200 1 -0200}
    {2582769600 -10800 0 -0300}
    {2593659600 -7200 1 -0200}
    {2614219200 -10800 0 -0300}
    {2625109200 -7200 1 -0200}
    {2645668800 -10800 0 -0300}
    {2656558800 -7200 1 -0200}
    {2677118400 -10800 0 -0300}
    {2688613200 -7200 1 -0200}
    {2709172800 -10800 0 -0300}
    {2720062800 -7200 1 -0200}
    {2740622400 -10800 0 -0300}
    {2751512400 -7200 1 -0200}
    {2772072000 -10800 0 -0300}
    {2782962000 -7200 1 -0200}
    {2803521600 -10800 0 -0300}
    {2814411600 -7200 1 -0200}
    {2834971200 -10800 0 -0300}
    {2846466000 -7200 1 -0200}
    {2867025600 -10800 0 -0300}
    {2877915600 -7200 1 -0200}
    {2898475200 -10800 0 -0300}
    {2909365200 -7200 1 -0200}
    {2929924800 -10800 0 -0300}
    {2940814800 -7200 1 -0200}
    {2961374400 -10800 0 -0300}
    {2972264400 -7200 1 -0200}
    {2992824000 -10800 0 -0300}
    {3003714000 -7200 1 -0200}
    {3024273600 -10800 0 -0300}
    {3035768400 -7200 1 -0200}
    {3056328000 -10800 0 -0300}
    {3067218000 -7200 1 -0200}
    {3087777600 -10800 0 -0300}
    {3098667600 -7200 1 -0200}
    {3119227200 -10800 0 -0300}
    {3130117200 -7200 1 -0200}
    {3150676800 -10800 0 -0300}
    {3161566800 -7200 1 -0200}
    {3182126400 -10800 0 -0300}
    {3193016400 -7200 1 -0200}
    {3213576000 -10800 0 -0300}
    {3225070800 -7200 1 -0200}
    {3245630400 -10800 0 -0300}
    {3256520400 -7200 1 -0200}
    {3277080000 -10800 0 -0300}
    {3287970000 -7200 1 -0200}
    {3308529600 -10800 0 -0300}
    {3319419600 -7200 1 -0200}
    {3339979200 -10800 0 -0300}
    {3350869200 -7200 1 -0200}
    {3371428800 -10800 0 -0300}
    {3382923600 -7200 1 -0200}
    {3403483200 -10800 0 -0300}
    {3414373200 -7200 1 -0200}
    {3434932800 -10800 0 -0300}
    {3445822800 -7200 1 -0200}
    {3466382400 -10800 0 -0300}
    {3477272400 -7200 1 -0200}
    {3497832000 -10800 0 -0300}
    {3508722000 -7200 1 -0200}
    {3529281600 -10800 0 -0300}
    {3540171600 -7200 1 -0200}
    {3560731200 -10800 0 -0300}
    {3572226000 -7200 1 -0200}
    {3592785600 -10800 0 -0300}
    {3603675600 -7200 1 -0200}
    {3624235200 -10800 0 -0300}
    {3635125200 -7200 1 -0200}
    {3655684800 -10800 0 -0300}
    {3666574800 -7200 1 -0200}
    {3687134400 -10800 0 -0300}
    {3698024400 -7200 1 -0200}
    {3718584000 -10800 0 -0300}
    {3730078800 -7200 1 -0200}
    {3750638400 -10800 0 -0300}
    {3761528400 -7200 1 -0200}
    {3782088000 -10800 0 -0300}
    {3792978000 -7200 1 -0200}
    {3813537600 -10800 0 -0300}
    {3824427600 -7200 1 -0200}
    {3844987200 -10800 0 -0300}
    {3855877200 -7200 1 -0200}
    {3876436800 -10800 0 -0300}
    {3887326800 -7200 1 -0200}
    {3907886400 -10800 0 -0300}
    {3919381200 -7200 1 -0200}
    {3939940800 -10800 0 -0300}
    {3950830800 -7200 1 -0200}
    {3971390400 -10800 0 -0300}
    {3982280400 -7200 1 -0200}
    {4002840000 -10800 0 -0300}
    {4013730000 -7200 1 -0200}
    {4034289600 -10800 0 -0300}
    {4045179600 -7200 1 -0200}
    {4065739200 -10800 0 -0300}
    {4076629200 -7200 1 -0200}
    {4097188800 -10800 0 -0300}
}

Changes to library/tzdata/America/Monterrey.

1
2
3
4
5






6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17




-
+
+
+
+
+
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Monterrey) {
    {-9223372036854775808 -24076 0 LMT}
    {-1514743200 -21600 0 CST}
    {-1514743200 -25200 0 MST}
    {-1343149200 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220461200 -21600 1 MDT}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {568015200 -21600 0 CST}
    {576057600 -18000 1 CDT}
    {594198000 -21600 0 CST}
    {599637600 -21600 0 CST}
    {828864000 -18000 1 CDT}
    {846399600 -21600 0 CST}
    {860313600 -18000 1 CDT}
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
62
63
64
65
66
67
68


























































































































































69







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

    {1572159600 -21600 0 CST}
    {1586073600 -18000 1 CDT}
    {1603609200 -21600 0 CST}
    {1617523200 -18000 1 CDT}
    {1635663600 -21600 0 CST}
    {1648972800 -18000 1 CDT}
    {1667113200 -21600 0 CST}
    {1680422400 -18000 1 CDT}
    {1698562800 -21600 0 CST}
    {1712476800 -18000 1 CDT}
    {1730012400 -21600 0 CST}
    {1743926400 -18000 1 CDT}
    {1761462000 -21600 0 CST}
    {1775376000 -18000 1 CDT}
    {1792911600 -21600 0 CST}
    {1806825600 -18000 1 CDT}
    {1824966000 -21600 0 CST}
    {1838275200 -18000 1 CDT}
    {1856415600 -21600 0 CST}
    {1869724800 -18000 1 CDT}
    {1887865200 -21600 0 CST}
    {1901779200 -18000 1 CDT}
    {1919314800 -21600 0 CST}
    {1933228800 -18000 1 CDT}
    {1950764400 -21600 0 CST}
    {1964678400 -18000 1 CDT}
    {1982818800 -21600 0 CST}
    {1996128000 -18000 1 CDT}
    {2014268400 -21600 0 CST}
    {2027577600 -18000 1 CDT}
    {2045718000 -21600 0 CST}
    {2059027200 -18000 1 CDT}
    {2077167600 -21600 0 CST}
    {2091081600 -18000 1 CDT}
    {2108617200 -21600 0 CST}
    {2122531200 -18000 1 CDT}
    {2140066800 -21600 0 CST}
    {2153980800 -18000 1 CDT}
    {2172121200 -21600 0 CST}
    {2185430400 -18000 1 CDT}
    {2203570800 -21600 0 CST}
    {2216880000 -18000 1 CDT}
    {2235020400 -21600 0 CST}
    {2248934400 -18000 1 CDT}
    {2266470000 -21600 0 CST}
    {2280384000 -18000 1 CDT}
    {2297919600 -21600 0 CST}
    {2311833600 -18000 1 CDT}
    {2329369200 -21600 0 CST}
    {2343283200 -18000 1 CDT}
    {2361423600 -21600 0 CST}
    {2374732800 -18000 1 CDT}
    {2392873200 -21600 0 CST}
    {2406182400 -18000 1 CDT}
    {2424322800 -21600 0 CST}
    {2438236800 -18000 1 CDT}
    {2455772400 -21600 0 CST}
    {2469686400 -18000 1 CDT}
    {2487222000 -21600 0 CST}
    {2501136000 -18000 1 CDT}
    {2519276400 -21600 0 CST}
    {2532585600 -18000 1 CDT}
    {2550726000 -21600 0 CST}
    {2564035200 -18000 1 CDT}
    {2582175600 -21600 0 CST}
    {2596089600 -18000 1 CDT}
    {2613625200 -21600 0 CST}
    {2627539200 -18000 1 CDT}
    {2645074800 -21600 0 CST}
    {2658988800 -18000 1 CDT}
    {2676524400 -21600 0 CST}
    {2690438400 -18000 1 CDT}
    {2708578800 -21600 0 CST}
    {2721888000 -18000 1 CDT}
    {2740028400 -21600 0 CST}
    {2753337600 -18000 1 CDT}
    {2771478000 -21600 0 CST}
    {2785392000 -18000 1 CDT}
    {2802927600 -21600 0 CST}
    {2816841600 -18000 1 CDT}
    {2834377200 -21600 0 CST}
    {2848291200 -18000 1 CDT}
    {2866431600 -21600 0 CST}
    {2879740800 -18000 1 CDT}
    {2897881200 -21600 0 CST}
    {2911190400 -18000 1 CDT}
    {2929330800 -21600 0 CST}
    {2942640000 -18000 1 CDT}
    {2960780400 -21600 0 CST}
    {2974694400 -18000 1 CDT}
    {2992230000 -21600 0 CST}
    {3006144000 -18000 1 CDT}
    {3023679600 -21600 0 CST}
    {3037593600 -18000 1 CDT}
    {3055734000 -21600 0 CST}
    {3069043200 -18000 1 CDT}
    {3087183600 -21600 0 CST}
    {3100492800 -18000 1 CDT}
    {3118633200 -21600 0 CST}
    {3132547200 -18000 1 CDT}
    {3150082800 -21600 0 CST}
    {3163996800 -18000 1 CDT}
    {3181532400 -21600 0 CST}
    {3195446400 -18000 1 CDT}
    {3212982000 -21600 0 CST}
    {3226896000 -18000 1 CDT}
    {3245036400 -21600 0 CST}
    {3258345600 -18000 1 CDT}
    {3276486000 -21600 0 CST}
    {3289795200 -18000 1 CDT}
    {3307935600 -21600 0 CST}
    {3321849600 -18000 1 CDT}
    {3339385200 -21600 0 CST}
    {3353299200 -18000 1 CDT}
    {3370834800 -21600 0 CST}
    {3384748800 -18000 1 CDT}
    {3402889200 -21600 0 CST}
    {3416198400 -18000 1 CDT}
    {3434338800 -21600 0 CST}
    {3447648000 -18000 1 CDT}
    {3465788400 -21600 0 CST}
    {3479702400 -18000 1 CDT}
    {3497238000 -21600 0 CST}
    {3511152000 -18000 1 CDT}
    {3528687600 -21600 0 CST}
    {3542601600 -18000 1 CDT}
    {3560137200 -21600 0 CST}
    {3574051200 -18000 1 CDT}
    {3592191600 -21600 0 CST}
    {3605500800 -18000 1 CDT}
    {3623641200 -21600 0 CST}
    {3636950400 -18000 1 CDT}
    {3655090800 -21600 0 CST}
    {3669004800 -18000 1 CDT}
    {3686540400 -21600 0 CST}
    {3700454400 -18000 1 CDT}
    {3717990000 -21600 0 CST}
    {3731904000 -18000 1 CDT}
    {3750044400 -21600 0 CST}
    {3763353600 -18000 1 CDT}
    {3781494000 -21600 0 CST}
    {3794803200 -18000 1 CDT}
    {3812943600 -21600 0 CST}
    {3826252800 -18000 1 CDT}
    {3844393200 -21600 0 CST}
    {3858307200 -18000 1 CDT}
    {3875842800 -21600 0 CST}
    {3889756800 -18000 1 CDT}
    {3907292400 -21600 0 CST}
    {3921206400 -18000 1 CDT}
    {3939346800 -21600 0 CST}
    {3952656000 -18000 1 CDT}
    {3970796400 -21600 0 CST}
    {3984105600 -18000 1 CDT}
    {4002246000 -21600 0 CST}
    {4016160000 -18000 1 CDT}
    {4033695600 -21600 0 CST}
    {4047609600 -18000 1 CDT}
    {4065145200 -21600 0 CST}
    {4079059200 -18000 1 CDT}
    {4096594800 -21600 0 CST}
}

Changes to library/tzdata/America/Montevideo.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Montevideo) {
    {-9223372036854775808 -13491 0 LMT}
    {-1942690509 -13491 0 MMT}
    {-1567455309 -14400 0 -04}
    {-1459627200 -10800 0 -0330}
    {-1443819600 -12600 0 -0330}
    {-1428006600 -10800 1 -0330}
    {-1412283600 -12600 0 -0330}
    {-1396470600 -10800 1 -0330}
    {-1380747600 -12600 0 -0330}
    {-1141590600 -10800 1 -0330}
    {-1128286800 -12600 0 -0330}
    {-1110141000 -10800 1 -0330}
    {-1096837200 -12600 0 -0330}
    {-1078691400 -10800 1 -0330}
    {-1065387600 -12600 0 -0330}
    {-1047241800 -10800 1 -0330}
    {-1033938000 -12600 0 -0330}
    {-1015187400 -10800 1 -0330}
    {-1002488400 -12600 0 -0330}
    {-983737800 -10800 1 -0330}
    {-971038800 -12600 0 -0330}
    {-954707400 -10800 1 -0330}
    {-938984400 -12600 0 -0330}
    {-920838600 -10800 1 -0330}
    {-907534800 -12600 0 -0330}
    {-896819400 -10800 1 -0330}
    {-853621200 -9000 0 -03}
    {-845847000 -10800 0 -03}
    {-334789200 -9000 1 -03}
    {-319671000 -10800 0 -03}
    {-315608400 -10800 0 -03}
    {-314226000 -7200 1 -03}
    {-309996000 -10800 0 -03}
    {-149720400 -7200 1 -03}
    {-134604000 -10800 0 -03}
    {-63147600 -10800 0 -03}
    {-50446800 -9000 1 -03}
    {-34205400 -10800 0 -03}
    {10800 -10800 0 -03}
    {9860400 -7200 1 -03}
    {14176800 -10800 0 -03}
    {72846000 -7200 1 -03}
    {80100000 -10800 0 -03}
    {126241200 -10800 0 -03}
    {127278000 -5400 1 -03}
    {132112800 -9000 0 -03}
    {147234600 -10800 0 -03}
    {156909600 -10800 0 -03}
    {156913200 -7200 1 -03}
    {165376800 -10800 0 -03}
    {219812400 -7200 1 -03}
    {226461600 -10800 0 -03}
    {250052400 -7200 1 -03}
    {257911200 -10800 0 -03}
    {282711600 -7200 1 -03}
    {289360800 -10800 0 -03}
    {294202800 -7200 1 -03}
    {322020000 -10800 0 -03}
    {566449200 -7200 1 -03}
    {573012000 -10800 0 -03}
    {597812400 -7200 1 -03}
    {605066400 -10800 0 -03}
    {625633200 -7200 1 -03}
    {635911200 -10800 0 -03}
    {656478000 -7200 1 -03}
    {667965600 -10800 0 -03}
    {688532400 -7200 1 -03}
    {699415200 -10800 0 -03}
    {719377200 -7200 1 -03}
    {730864800 -10800 0 -03}
    {1095562800 -7200 1 -03}
    {1111896000 -10800 0 -03}
    {1128834000 -7200 1 -03}
    {1142136000 -10800 0 -03}
    {1159678800 -7200 1 -03}
    {1173585600 -10800 0 -03}
    {1191733200 -7200 1 -03}
    {1205035200 -10800 0 -03}
    {1223182800 -7200 1 -03}
    {1236484800 -10800 0 -03}
    {1254632400 -7200 1 -03}
    {1268539200 -10800 0 -03}
    {1286082000 -7200 1 -03}
    {1299988800 -10800 0 -03}
    {1317531600 -7200 1 -03}
    {1331438400 -10800 0 -03}
    {1349586000 -7200 1 -03}
    {1362888000 -10800 0 -03}
    {1381035600 -7200 1 -03}
    {1394337600 -10800 0 -03}
    {1412485200 -7200 1 -03}
    {1425787200 -10800 0 -03}
    {-1567455309 -14400 0 -0400}
    {-1459627200 -10800 0 -0300}
    {-1443819600 -12600 0 -0430}
    {-1428006600 -10800 1 -0300}
    {-1412283600 -12600 0 -0430}
    {-1396470600 -10800 1 -0300}
    {-1380747600 -12600 0 -0430}
    {-1141590600 -10800 1 -0300}
    {-1128286800 -12600 0 -0430}
    {-1110141000 -10800 1 -0300}
    {-1096837200 -12600 0 -0430}
    {-1078691400 -10800 1 -0300}
    {-1065387600 -12600 0 -0430}
    {-1047241800 -10800 1 -0300}
    {-1033938000 -12600 0 -0430}
    {-1015187400 -10800 1 -0300}
    {-1002488400 -12600 0 -0430}
    {-983737800 -10800 1 -0300}
    {-971038800 -12600 0 -0430}
    {-954707400 -10800 1 -0300}
    {-938984400 -12600 0 -0430}
    {-920838600 -10800 1 -0300}
    {-907534800 -12600 0 -0430}
    {-896819400 -10800 1 -0300}
    {-853621200 -9000 0 -0330}
    {-845847000 -10800 0 -0300}
    {-334789200 -9000 1 -0330}
    {-319671000 -10800 0 -0300}
    {-315608400 -10800 0 -0300}
    {-314226000 -7200 1 -0200}
    {-309996000 -10800 0 -0300}
    {-149720400 -7200 1 -0200}
    {-134604000 -10800 0 -0300}
    {-63147600 -10800 0 -0300}
    {-50446800 -9000 1 -0330}
    {-34205400 -10800 0 -0300}
    {10800 -10800 0 -0300}
    {9860400 -7200 1 -0200}
    {14176800 -10800 0 -0300}
    {72846000 -7200 1 -0200}
    {80100000 -10800 0 -0300}
    {126241200 -10800 0 -0300}
    {127278000 -5400 1 -0230}
    {132112800 -9000 0 -0330}
    {147234600 -10800 0 -0300}
    {156909600 -10800 0 -0300}
    {156913200 -7200 1 -0200}
    {165376800 -10800 0 -0300}
    {219812400 -7200 1 -0200}
    {226461600 -10800 0 -0300}
    {250052400 -7200 1 -0200}
    {257911200 -10800 0 -0300}
    {282711600 -7200 1 -0200}
    {289360800 -10800 0 -0300}
    {294202800 -7200 1 -0200}
    {322020000 -10800 0 -0300}
    {566449200 -7200 1 -0200}
    {573012000 -10800 0 -0300}
    {597812400 -7200 1 -0200}
    {605066400 -10800 0 -0300}
    {625633200 -7200 1 -0200}
    {635911200 -10800 0 -0300}
    {656478000 -7200 1 -0200}
    {667965600 -10800 0 -0300}
    {688532400 -7200 1 -0200}
    {699415200 -10800 0 -0300}
    {719377200 -7200 1 -0200}
    {730864800 -10800 0 -0300}
    {1095562800 -7200 1 -0200}
    {1111896000 -10800 0 -0300}
    {1128834000 -7200 1 -0200}
    {1142136000 -10800 0 -0300}
    {1159678800 -7200 1 -0200}
    {1173585600 -10800 0 -0300}
    {1191733200 -7200 1 -0200}
    {1205035200 -10800 0 -0300}
    {1223182800 -7200 1 -0200}
    {1236484800 -10800 0 -0300}
    {1254632400 -7200 1 -0200}
    {1268539200 -10800 0 -0300}
    {1286082000 -7200 1 -0200}
    {1299988800 -10800 0 -0300}
    {1317531600 -7200 1 -0200}
    {1331438400 -10800 0 -0300}
    {1349586000 -7200 1 -0200}
    {1362888000 -10800 0 -0300}
    {1381035600 -7200 1 -0200}
    {1394337600 -10800 0 -0300}
    {1412485200 -7200 1 -0200}
    {1425787200 -10800 0 -0300}
}

Changes to library/tzdata/America/Montserrat.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Montserrat) $TZData(:America/Port_of_Spain)
set TZData(:America/Montserrat) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Nassau.

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
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
1
2
3


4
5





















































































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Toronto)]} {
    LoadTimeZoneFile America/Toronto

set TZData(:America/Nassau) {
}
set TZData(:America/Nassau) $TZData(:America/Toronto)
    {-9223372036854775808 -18570 0 LMT}
    {-1825095030 -18000 0 EST}
    {-179341200 -14400 1 EDT}
    {-163620000 -18000 0 EST}
    {-147891600 -14400 1 EDT}
    {-131565600 -18000 0 EST}
    {-116442000 -14400 1 EDT}
    {-100116000 -18000 0 EST}
    {-84387600 -14400 1 EDT}
    {-68666400 -18000 0 EST}
    {-52938000 -14400 1 EDT}
    {-37216800 -18000 0 EST}
    {-21488400 -14400 1 EDT}
    {-5767200 -18000 0 EST}
    {9961200 -14400 1 EDT}
    {25682400 -18000 0 EST}
    {41410800 -14400 1 EDT}
    {57736800 -18000 0 EST}
    {73465200 -14400 1 EDT}
    {89186400 -18000 0 EST}
    {104914800 -14400 1 EDT}
    {120636000 -18000 0 EST}
    {136364400 -14400 1 EDT}
    {152085600 -18000 0 EST}
    {167814000 -14400 1 EDT}
    {183535200 -18000 0 EST}
    {189320400 -18000 0 EST}
    {199263600 -14400 1 EDT}
    {215589600 -18000 0 EST}
    {230713200 -14400 1 EDT}
    {247039200 -18000 0 EST}
    {262767600 -14400 1 EDT}
    {278488800 -18000 0 EST}
    {294217200 -14400 1 EDT}
    {309938400 -18000 0 EST}
    {325666800 -14400 1 EDT}
    {341388000 -18000 0 EST}
    {357116400 -14400 1 EDT}
    {372837600 -18000 0 EST}
    {388566000 -14400 1 EDT}
    {404892000 -18000 0 EST}
    {420015600 -14400 1 EDT}
    {436341600 -18000 0 EST}
    {452070000 -14400 1 EDT}
    {467791200 -18000 0 EST}
    {483519600 -14400 1 EDT}
    {499240800 -18000 0 EST}
    {514969200 -14400 1 EDT}
    {530690400 -18000 0 EST}
    {544604400 -14400 1 EDT}
    {562140000 -18000 0 EST}
    {576054000 -14400 1 EDT}
    {594194400 -18000 0 EST}
    {607503600 -14400 1 EDT}
    {625644000 -18000 0 EST}
    {638953200 -14400 1 EDT}
    {657093600 -18000 0 EST}
    {671007600 -14400 1 EDT}
    {688543200 -18000 0 EST}
    {702457200 -14400 1 EDT}
    {719992800 -18000 0 EST}
    {733906800 -14400 1 EDT}
    {752047200 -18000 0 EST}
    {765356400 -14400 1 EDT}
    {783496800 -18000 0 EST}
    {796806000 -14400 1 EDT}
    {814946400 -18000 0 EST}
    {828860400 -14400 1 EDT}
    {846396000 -18000 0 EST}
    {860310000 -14400 1 EDT}
    {877845600 -18000 0 EST}
    {891759600 -14400 1 EDT}
    {909295200 -18000 0 EST}
    {923209200 -14400 1 EDT}
    {941349600 -18000 0 EST}
    {954658800 -14400 1 EDT}
    {972799200 -18000 0 EST}
    {986108400 -14400 1 EDT}
    {1004248800 -18000 0 EST}
    {1018162800 -14400 1 EDT}
    {1035698400 -18000 0 EST}
    {1049612400 -14400 1 EDT}
    {1067148000 -18000 0 EST}
    {1081062000 -14400 1 EDT}
    {1099202400 -18000 0 EST}
    {1112511600 -14400 1 EDT}
    {1130652000 -18000 0 EST}
    {1143961200 -14400 1 EDT}
    {1162101600 -18000 0 EST}
    {1173596400 -14400 1 EDT}
    {1194156000 -18000 0 EST}
    {1205046000 -14400 1 EDT}
    {1225605600 -18000 0 EST}
    {1236495600 -14400 1 EDT}
    {1257055200 -18000 0 EST}
    {1268550000 -14400 1 EDT}
    {1289109600 -18000 0 EST}
    {1299999600 -14400 1 EDT}
    {1320559200 -18000 0 EST}
    {1331449200 -14400 1 EDT}
    {1352008800 -18000 0 EST}
    {1362898800 -14400 1 EDT}
    {1383458400 -18000 0 EST}
    {1394348400 -14400 1 EDT}
    {1414908000 -18000 0 EST}
    {1425798000 -14400 1 EDT}
    {1446357600 -18000 0 EST}
    {1457852400 -14400 1 EDT}
    {1478412000 -18000 0 EST}
    {1489302000 -14400 1 EDT}
    {1509861600 -18000 0 EST}
    {1520751600 -14400 1 EDT}
    {1541311200 -18000 0 EST}
    {1552201200 -14400 1 EDT}
    {1572760800 -18000 0 EST}
    {1583650800 -14400 1 EDT}
    {1604210400 -18000 0 EST}
    {1615705200 -14400 1 EDT}
    {1636264800 -18000 0 EST}
    {1647154800 -14400 1 EDT}
    {1667714400 -18000 0 EST}
    {1678604400 -14400 1 EDT}
    {1699164000 -18000 0 EST}
    {1710054000 -14400 1 EDT}
    {1730613600 -18000 0 EST}
    {1741503600 -14400 1 EDT}
    {1762063200 -18000 0 EST}
    {1772953200 -14400 1 EDT}
    {1793512800 -18000 0 EST}
    {1805007600 -14400 1 EDT}
    {1825567200 -18000 0 EST}
    {1836457200 -14400 1 EDT}
    {1857016800 -18000 0 EST}
    {1867906800 -14400 1 EDT}
    {1888466400 -18000 0 EST}
    {1899356400 -14400 1 EDT}
    {1919916000 -18000 0 EST}
    {1930806000 -14400 1 EDT}
    {1951365600 -18000 0 EST}
    {1962860400 -14400 1 EDT}
    {1983420000 -18000 0 EST}
    {1994310000 -14400 1 EDT}
    {2014869600 -18000 0 EST}
    {2025759600 -14400 1 EDT}
    {2046319200 -18000 0 EST}
    {2057209200 -14400 1 EDT}
    {2077768800 -18000 0 EST}
    {2088658800 -14400 1 EDT}
    {2109218400 -18000 0 EST}
    {2120108400 -14400 1 EDT}
    {2140668000 -18000 0 EST}
    {2152162800 -14400 1 EDT}
    {2172722400 -18000 0 EST}
    {2183612400 -14400 1 EDT}
    {2204172000 -18000 0 EST}
    {2215062000 -14400 1 EDT}
    {2235621600 -18000 0 EST}
    {2246511600 -14400 1 EDT}
    {2267071200 -18000 0 EST}
    {2277961200 -14400 1 EDT}
    {2298520800 -18000 0 EST}
    {2309410800 -14400 1 EDT}
    {2329970400 -18000 0 EST}
    {2341465200 -14400 1 EDT}
    {2362024800 -18000 0 EST}
    {2372914800 -14400 1 EDT}
    {2393474400 -18000 0 EST}
    {2404364400 -14400 1 EDT}
    {2424924000 -18000 0 EST}
    {2435814000 -14400 1 EDT}
    {2456373600 -18000 0 EST}
    {2467263600 -14400 1 EDT}
    {2487823200 -18000 0 EST}
    {2499318000 -14400 1 EDT}
    {2519877600 -18000 0 EST}
    {2530767600 -14400 1 EDT}
    {2551327200 -18000 0 EST}
    {2562217200 -14400 1 EDT}
    {2582776800 -18000 0 EST}
    {2593666800 -14400 1 EDT}
    {2614226400 -18000 0 EST}
    {2625116400 -14400 1 EDT}
    {2645676000 -18000 0 EST}
    {2656566000 -14400 1 EDT}
    {2677125600 -18000 0 EST}
    {2688620400 -14400 1 EDT}
    {2709180000 -18000 0 EST}
    {2720070000 -14400 1 EDT}
    {2740629600 -18000 0 EST}
    {2751519600 -14400 1 EDT}
    {2772079200 -18000 0 EST}
    {2782969200 -14400 1 EDT}
    {2803528800 -18000 0 EST}
    {2814418800 -14400 1 EDT}
    {2834978400 -18000 0 EST}
    {2846473200 -14400 1 EDT}
    {2867032800 -18000 0 EST}
    {2877922800 -14400 1 EDT}
    {2898482400 -18000 0 EST}
    {2909372400 -14400 1 EDT}
    {2929932000 -18000 0 EST}
    {2940822000 -14400 1 EDT}
    {2961381600 -18000 0 EST}
    {2972271600 -14400 1 EDT}
    {2992831200 -18000 0 EST}
    {3003721200 -14400 1 EDT}
    {3024280800 -18000 0 EST}
    {3035775600 -14400 1 EDT}
    {3056335200 -18000 0 EST}
    {3067225200 -14400 1 EDT}
    {3087784800 -18000 0 EST}
    {3098674800 -14400 1 EDT}
    {3119234400 -18000 0 EST}
    {3130124400 -14400 1 EDT}
    {3150684000 -18000 0 EST}
    {3161574000 -14400 1 EDT}
    {3182133600 -18000 0 EST}
    {3193023600 -14400 1 EDT}
    {3213583200 -18000 0 EST}
    {3225078000 -14400 1 EDT}
    {3245637600 -18000 0 EST}
    {3256527600 -14400 1 EDT}
    {3277087200 -18000 0 EST}
    {3287977200 -14400 1 EDT}
    {3308536800 -18000 0 EST}
    {3319426800 -14400 1 EDT}
    {3339986400 -18000 0 EST}
    {3350876400 -14400 1 EDT}
    {3371436000 -18000 0 EST}
    {3382930800 -14400 1 EDT}
    {3403490400 -18000 0 EST}
    {3414380400 -14400 1 EDT}
    {3434940000 -18000 0 EST}
    {3445830000 -14400 1 EDT}
    {3466389600 -18000 0 EST}
    {3477279600 -14400 1 EDT}
    {3497839200 -18000 0 EST}
    {3508729200 -14400 1 EDT}
    {3529288800 -18000 0 EST}
    {3540178800 -14400 1 EDT}
    {3560738400 -18000 0 EST}
    {3572233200 -14400 1 EDT}
    {3592792800 -18000 0 EST}
    {3603682800 -14400 1 EDT}
    {3624242400 -18000 0 EST}
    {3635132400 -14400 1 EDT}
    {3655692000 -18000 0 EST}
    {3666582000 -14400 1 EDT}
    {3687141600 -18000 0 EST}
    {3698031600 -14400 1 EDT}
    {3718591200 -18000 0 EST}
    {3730086000 -14400 1 EDT}
    {3750645600 -18000 0 EST}
    {3761535600 -14400 1 EDT}
    {3782095200 -18000 0 EST}
    {3792985200 -14400 1 EDT}
    {3813544800 -18000 0 EST}
    {3824434800 -14400 1 EDT}
    {3844994400 -18000 0 EST}
    {3855884400 -14400 1 EDT}
    {3876444000 -18000 0 EST}
    {3887334000 -14400 1 EDT}
    {3907893600 -18000 0 EST}
    {3919388400 -14400 1 EDT}
    {3939948000 -18000 0 EST}
    {3950838000 -14400 1 EDT}
    {3971397600 -18000 0 EST}
    {3982287600 -14400 1 EDT}
    {4002847200 -18000 0 EST}
    {4013737200 -14400 1 EDT}
    {4034296800 -18000 0 EST}
    {4045186800 -14400 1 EDT}
    {4065746400 -18000 0 EST}
    {4076636400 -14400 1 EDT}
    {4097196000 -18000 0 EST}
}

Changes to library/tzdata/America/Nipigon.

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
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
1
2
3


4
5






































































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Toronto)]} {
    LoadTimeZoneFile America/Toronto

set TZData(:America/Nipigon) {
}
set TZData(:America/Nipigon) $TZData(:America/Toronto)
    {-9223372036854775808 -21184 0 LMT}
    {-2366734016 -18000 0 EST}
    {-1632070800 -14400 1 EDT}
    {-1615140000 -18000 0 EST}
    {-923252400 -14400 1 EDT}
    {-880218000 -14400 0 EWT}
    {-769395600 -14400 1 EPT}
    {-765396000 -18000 0 EST}
    {136364400 -14400 1 EDT}
    {152085600 -18000 0 EST}
    {167814000 -14400 1 EDT}
    {183535200 -18000 0 EST}
    {199263600 -14400 1 EDT}
    {215589600 -18000 0 EST}
    {230713200 -14400 1 EDT}
    {247039200 -18000 0 EST}
    {262767600 -14400 1 EDT}
    {278488800 -18000 0 EST}
    {294217200 -14400 1 EDT}
    {309938400 -18000 0 EST}
    {325666800 -14400 1 EDT}
    {341388000 -18000 0 EST}
    {357116400 -14400 1 EDT}
    {372837600 -18000 0 EST}
    {388566000 -14400 1 EDT}
    {404892000 -18000 0 EST}
    {420015600 -14400 1 EDT}
    {436341600 -18000 0 EST}
    {452070000 -14400 1 EDT}
    {467791200 -18000 0 EST}
    {483519600 -14400 1 EDT}
    {499240800 -18000 0 EST}
    {514969200 -14400 1 EDT}
    {530690400 -18000 0 EST}
    {544604400 -14400 1 EDT}
    {562140000 -18000 0 EST}
    {576054000 -14400 1 EDT}
    {594194400 -18000 0 EST}
    {607503600 -14400 1 EDT}
    {625644000 -18000 0 EST}
    {638953200 -14400 1 EDT}
    {657093600 -18000 0 EST}
    {671007600 -14400 1 EDT}
    {688543200 -18000 0 EST}
    {702457200 -14400 1 EDT}
    {719992800 -18000 0 EST}
    {733906800 -14400 1 EDT}
    {752047200 -18000 0 EST}
    {765356400 -14400 1 EDT}
    {783496800 -18000 0 EST}
    {796806000 -14400 1 EDT}
    {814946400 -18000 0 EST}
    {828860400 -14400 1 EDT}
    {846396000 -18000 0 EST}
    {860310000 -14400 1 EDT}
    {877845600 -18000 0 EST}
    {891759600 -14400 1 EDT}
    {909295200 -18000 0 EST}
    {923209200 -14400 1 EDT}
    {941349600 -18000 0 EST}
    {954658800 -14400 1 EDT}
    {972799200 -18000 0 EST}
    {986108400 -14400 1 EDT}
    {1004248800 -18000 0 EST}
    {1018162800 -14400 1 EDT}
    {1035698400 -18000 0 EST}
    {1049612400 -14400 1 EDT}
    {1067148000 -18000 0 EST}
    {1081062000 -14400 1 EDT}
    {1099202400 -18000 0 EST}
    {1112511600 -14400 1 EDT}
    {1130652000 -18000 0 EST}
    {1143961200 -14400 1 EDT}
    {1162101600 -18000 0 EST}
    {1173596400 -14400 1 EDT}
    {1194156000 -18000 0 EST}
    {1205046000 -14400 1 EDT}
    {1225605600 -18000 0 EST}
    {1236495600 -14400 1 EDT}
    {1257055200 -18000 0 EST}
    {1268550000 -14400 1 EDT}
    {1289109600 -18000 0 EST}
    {1299999600 -14400 1 EDT}
    {1320559200 -18000 0 EST}
    {1331449200 -14400 1 EDT}
    {1352008800 -18000 0 EST}
    {1362898800 -14400 1 EDT}
    {1383458400 -18000 0 EST}
    {1394348400 -14400 1 EDT}
    {1414908000 -18000 0 EST}
    {1425798000 -14400 1 EDT}
    {1446357600 -18000 0 EST}
    {1457852400 -14400 1 EDT}
    {1478412000 -18000 0 EST}
    {1489302000 -14400 1 EDT}
    {1509861600 -18000 0 EST}
    {1520751600 -14400 1 EDT}
    {1541311200 -18000 0 EST}
    {1552201200 -14400 1 EDT}
    {1572760800 -18000 0 EST}
    {1583650800 -14400 1 EDT}
    {1604210400 -18000 0 EST}
    {1615705200 -14400 1 EDT}
    {1636264800 -18000 0 EST}
    {1647154800 -14400 1 EDT}
    {1667714400 -18000 0 EST}
    {1678604400 -14400 1 EDT}
    {1699164000 -18000 0 EST}
    {1710054000 -14400 1 EDT}
    {1730613600 -18000 0 EST}
    {1741503600 -14400 1 EDT}
    {1762063200 -18000 0 EST}
    {1772953200 -14400 1 EDT}
    {1793512800 -18000 0 EST}
    {1805007600 -14400 1 EDT}
    {1825567200 -18000 0 EST}
    {1836457200 -14400 1 EDT}
    {1857016800 -18000 0 EST}
    {1867906800 -14400 1 EDT}
    {1888466400 -18000 0 EST}
    {1899356400 -14400 1 EDT}
    {1919916000 -18000 0 EST}
    {1930806000 -14400 1 EDT}
    {1951365600 -18000 0 EST}
    {1962860400 -14400 1 EDT}
    {1983420000 -18000 0 EST}
    {1994310000 -14400 1 EDT}
    {2014869600 -18000 0 EST}
    {2025759600 -14400 1 EDT}
    {2046319200 -18000 0 EST}
    {2057209200 -14400 1 EDT}
    {2077768800 -18000 0 EST}
    {2088658800 -14400 1 EDT}
    {2109218400 -18000 0 EST}
    {2120108400 -14400 1 EDT}
    {2140668000 -18000 0 EST}
    {2152162800 -14400 1 EDT}
    {2172722400 -18000 0 EST}
    {2183612400 -14400 1 EDT}
    {2204172000 -18000 0 EST}
    {2215062000 -14400 1 EDT}
    {2235621600 -18000 0 EST}
    {2246511600 -14400 1 EDT}
    {2267071200 -18000 0 EST}
    {2277961200 -14400 1 EDT}
    {2298520800 -18000 0 EST}
    {2309410800 -14400 1 EDT}
    {2329970400 -18000 0 EST}
    {2341465200 -14400 1 EDT}
    {2362024800 -18000 0 EST}
    {2372914800 -14400 1 EDT}
    {2393474400 -18000 0 EST}
    {2404364400 -14400 1 EDT}
    {2424924000 -18000 0 EST}
    {2435814000 -14400 1 EDT}
    {2456373600 -18000 0 EST}
    {2467263600 -14400 1 EDT}
    {2487823200 -18000 0 EST}
    {2499318000 -14400 1 EDT}
    {2519877600 -18000 0 EST}
    {2530767600 -14400 1 EDT}
    {2551327200 -18000 0 EST}
    {2562217200 -14400 1 EDT}
    {2582776800 -18000 0 EST}
    {2593666800 -14400 1 EDT}
    {2614226400 -18000 0 EST}
    {2625116400 -14400 1 EDT}
    {2645676000 -18000 0 EST}
    {2656566000 -14400 1 EDT}
    {2677125600 -18000 0 EST}
    {2688620400 -14400 1 EDT}
    {2709180000 -18000 0 EST}
    {2720070000 -14400 1 EDT}
    {2740629600 -18000 0 EST}
    {2751519600 -14400 1 EDT}
    {2772079200 -18000 0 EST}
    {2782969200 -14400 1 EDT}
    {2803528800 -18000 0 EST}
    {2814418800 -14400 1 EDT}
    {2834978400 -18000 0 EST}
    {2846473200 -14400 1 EDT}
    {2867032800 -18000 0 EST}
    {2877922800 -14400 1 EDT}
    {2898482400 -18000 0 EST}
    {2909372400 -14400 1 EDT}
    {2929932000 -18000 0 EST}
    {2940822000 -14400 1 EDT}
    {2961381600 -18000 0 EST}
    {2972271600 -14400 1 EDT}
    {2992831200 -18000 0 EST}
    {3003721200 -14400 1 EDT}
    {3024280800 -18000 0 EST}
    {3035775600 -14400 1 EDT}
    {3056335200 -18000 0 EST}
    {3067225200 -14400 1 EDT}
    {3087784800 -18000 0 EST}
    {3098674800 -14400 1 EDT}
    {3119234400 -18000 0 EST}
    {3130124400 -14400 1 EDT}
    {3150684000 -18000 0 EST}
    {3161574000 -14400 1 EDT}
    {3182133600 -18000 0 EST}
    {3193023600 -14400 1 EDT}
    {3213583200 -18000 0 EST}
    {3225078000 -14400 1 EDT}
    {3245637600 -18000 0 EST}
    {3256527600 -14400 1 EDT}
    {3277087200 -18000 0 EST}
    {3287977200 -14400 1 EDT}
    {3308536800 -18000 0 EST}
    {3319426800 -14400 1 EDT}
    {3339986400 -18000 0 EST}
    {3350876400 -14400 1 EDT}
    {3371436000 -18000 0 EST}
    {3382930800 -14400 1 EDT}
    {3403490400 -18000 0 EST}
    {3414380400 -14400 1 EDT}
    {3434940000 -18000 0 EST}
    {3445830000 -14400 1 EDT}
    {3466389600 -18000 0 EST}
    {3477279600 -14400 1 EDT}
    {3497839200 -18000 0 EST}
    {3508729200 -14400 1 EDT}
    {3529288800 -18000 0 EST}
    {3540178800 -14400 1 EDT}
    {3560738400 -18000 0 EST}
    {3572233200 -14400 1 EDT}
    {3592792800 -18000 0 EST}
    {3603682800 -14400 1 EDT}
    {3624242400 -18000 0 EST}
    {3635132400 -14400 1 EDT}
    {3655692000 -18000 0 EST}
    {3666582000 -14400 1 EDT}
    {3687141600 -18000 0 EST}
    {3698031600 -14400 1 EDT}
    {3718591200 -18000 0 EST}
    {3730086000 -14400 1 EDT}
    {3750645600 -18000 0 EST}
    {3761535600 -14400 1 EDT}
    {3782095200 -18000 0 EST}
    {3792985200 -14400 1 EDT}
    {3813544800 -18000 0 EST}
    {3824434800 -14400 1 EDT}
    {3844994400 -18000 0 EST}
    {3855884400 -14400 1 EDT}
    {3876444000 -18000 0 EST}
    {3887334000 -14400 1 EDT}
    {3907893600 -18000 0 EST}
    {3919388400 -14400 1 EDT}
    {3939948000 -18000 0 EST}
    {3950838000 -14400 1 EDT}
    {3971397600 -18000 0 EST}
    {3982287600 -14400 1 EDT}
    {4002847200 -18000 0 EST}
    {4013737200 -14400 1 EDT}
    {4034296800 -18000 0 EST}
    {4045186800 -14400 1 EDT}
    {4065746400 -18000 0 EST}
    {4076636400 -14400 1 EDT}
    {4097196000 -18000 0 EST}
}

Changes to library/tzdata/America/Noronha.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47











































48
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Noronha) {
    {-9223372036854775808 -7780 0 LMT}
    {-1767217820 -7200 0 -02}
    {-1206961200 -3600 1 -02}
    {-1191366000 -7200 0 -02}
    {-1175378400 -3600 1 -02}
    {-1159830000 -7200 0 -02}
    {-633823200 -3600 1 -02}
    {-622072800 -7200 0 -02}
    {-602287200 -3600 1 -02}
    {-591836400 -7200 0 -02}
    {-570751200 -3600 1 -02}
    {-560214000 -7200 0 -02}
    {-539128800 -3600 1 -02}
    {-531356400 -7200 0 -02}
    {-191368800 -3600 1 -02}
    {-184201200 -7200 0 -02}
    {-155167200 -3600 1 -02}
    {-150073200 -7200 0 -02}
    {-128901600 -3600 1 -02}
    {-121129200 -7200 0 -02}
    {-99957600 -3600 1 -02}
    {-89593200 -7200 0 -02}
    {-68421600 -3600 1 -02}
    {-57970800 -7200 0 -02}
    {499744800 -3600 1 -02}
    {511232400 -7200 0 -02}
    {530589600 -3600 1 -02}
    {540262800 -7200 0 -02}
    {562125600 -3600 1 -02}
    {571194000 -7200 0 -02}
    {592970400 -3600 1 -02}
    {602038800 -7200 0 -02}
    {624420000 -3600 1 -02}
    {634698000 -7200 0 -02}
    {653533200 -7200 0 -02}
    {938656800 -7200 0 -02}
    {938916000 -3600 1 -02}
    {951613200 -7200 0 -02}
    {970970400 -3600 1 -02}
    {971571600 -7200 0 -02}
    {1000346400 -7200 0 -02}
    {1003024800 -3600 1 -02}
    {1013907600 -7200 0 -02}
    {1033434000 -7200 0 -02}
    {-1767217820 -7200 0 -0200}
    {-1206961200 -3600 1 -0100}
    {-1191366000 -7200 0 -0200}
    {-1175378400 -3600 1 -0100}
    {-1159830000 -7200 0 -0200}
    {-633823200 -3600 1 -0100}
    {-622072800 -7200 0 -0200}
    {-602287200 -3600 1 -0100}
    {-591836400 -7200 0 -0200}
    {-570751200 -3600 1 -0100}
    {-560214000 -7200 0 -0200}
    {-539128800 -3600 1 -0100}
    {-531356400 -7200 0 -0200}
    {-191368800 -3600 1 -0100}
    {-184201200 -7200 0 -0200}
    {-155167200 -3600 1 -0100}
    {-150073200 -7200 0 -0200}
    {-128901600 -3600 1 -0100}
    {-121129200 -7200 0 -0200}
    {-99957600 -3600 1 -0100}
    {-89593200 -7200 0 -0200}
    {-68421600 -3600 1 -0100}
    {-57970800 -7200 0 -0200}
    {499744800 -3600 1 -0100}
    {511232400 -7200 0 -0200}
    {530589600 -3600 1 -0100}
    {540262800 -7200 0 -0200}
    {562125600 -3600 1 -0100}
    {571194000 -7200 0 -0200}
    {592970400 -3600 1 -0100}
    {602038800 -7200 0 -0200}
    {624420000 -3600 1 -0100}
    {634698000 -7200 0 -0200}
    {653533200 -7200 0 -0200}
    {938656800 -7200 0 -0200}
    {938916000 -3600 1 -0100}
    {951613200 -7200 0 -0200}
    {970970400 -3600 1 -0100}
    {971571600 -7200 0 -0200}
    {1000346400 -7200 0 -0200}
    {1003024800 -3600 1 -0100}
    {1013907600 -7200 0 -0200}
    {1033434000 -7200 0 -0200}
}

Changes to library/tzdata/America/Nuuk.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Nuuk) {
    {-9223372036854775808 -12416 0 LMT}
    {-1686083584 -10800 0 -03}
    {323845200 -7200 0 -02}
    {338950800 -10800 0 -03}
    {354675600 -7200 1 -02}
    {370400400 -10800 0 -03}
    {386125200 -7200 1 -02}
    {401850000 -10800 0 -03}
    {417574800 -7200 1 -02}
    {433299600 -10800 0 -03}
    {449024400 -7200 1 -02}
    {465354000 -10800 0 -03}
    {481078800 -7200 1 -02}
    {496803600 -10800 0 -03}
    {512528400 -7200 1 -02}
    {528253200 -10800 0 -03}
    {543978000 -7200 1 -02}
    {559702800 -10800 0 -03}
    {575427600 -7200 1 -02}
    {591152400 -10800 0 -03}
    {606877200 -7200 1 -02}
    {622602000 -10800 0 -03}
    {638326800 -7200 1 -02}
    {654656400 -10800 0 -03}
    {670381200 -7200 1 -02}
    {686106000 -10800 0 -03}
    {701830800 -7200 1 -02}
    {717555600 -10800 0 -03}
    {733280400 -7200 1 -02}
    {749005200 -10800 0 -03}
    {764730000 -7200 1 -02}
    {780454800 -10800 0 -03}
    {796179600 -7200 1 -02}
    {811904400 -10800 0 -03}
    {828234000 -7200 1 -02}
    {846378000 -10800 0 -03}
    {859683600 -7200 1 -02}
    {877827600 -10800 0 -03}
    {891133200 -7200 1 -02}
    {909277200 -10800 0 -03}
    {922582800 -7200 1 -02}
    {941331600 -10800 0 -03}
    {954032400 -7200 1 -02}
    {972781200 -10800 0 -03}
    {985482000 -7200 1 -02}
    {1004230800 -10800 0 -03}
    {1017536400 -7200 1 -02}
    {1035680400 -10800 0 -03}
    {1048986000 -7200 1 -02}
    {1067130000 -10800 0 -03}
    {1080435600 -7200 1 -02}
    {1099184400 -10800 0 -03}
    {1111885200 -7200 1 -02}
    {1130634000 -10800 0 -03}
    {1143334800 -7200 1 -02}
    {1162083600 -10800 0 -03}
    {1174784400 -7200 1 -02}
    {1193533200 -10800 0 -03}
    {1206838800 -7200 1 -02}
    {1224982800 -10800 0 -03}
    {1238288400 -7200 1 -02}
    {1256432400 -10800 0 -03}
    {1269738000 -7200 1 -02}
    {1288486800 -10800 0 -03}
    {1301187600 -7200 1 -02}
    {1319936400 -10800 0 -03}
    {1332637200 -7200 1 -02}
    {1351386000 -10800 0 -03}
    {1364691600 -7200 1 -02}
    {1382835600 -10800 0 -03}
    {1396141200 -7200 1 -02}
    {1414285200 -10800 0 -03}
    {1427590800 -7200 1 -02}
    {1445734800 -10800 0 -03}
    {1459040400 -7200 1 -02}
    {1477789200 -10800 0 -03}
    {1490490000 -7200 1 -02}
    {1509238800 -10800 0 -03}
    {1521939600 -7200 1 -02}
    {1540688400 -10800 0 -03}
    {1553994000 -7200 1 -02}
    {1572138000 -10800 0 -03}
    {1585443600 -7200 1 -02}
    {1603587600 -10800 0 -03}
    {1616893200 -7200 1 -02}
    {1635642000 -10800 0 -03}
    {1648342800 -7200 1 -02}
    {1667091600 -10800 0 -03}
    {1679792400 -7200 1 -02}
    {1698541200 -10800 0 -03}
    {1711846800 -7200 1 -02}
    {1729990800 -10800 0 -03}
    {1743296400 -7200 1 -02}
    {1761440400 -10800 0 -03}
    {1774746000 -7200 1 -02}
    {1792890000 -10800 0 -03}
    {1806195600 -7200 1 -02}
    {1824944400 -10800 0 -03}
    {1837645200 -7200 1 -02}
    {1856394000 -10800 0 -03}
    {1869094800 -7200 1 -02}
    {1887843600 -10800 0 -03}
    {1901149200 -7200 1 -02}
    {1919293200 -10800 0 -03}
    {1932598800 -7200 1 -02}
    {1950742800 -10800 0 -03}
    {1964048400 -7200 1 -02}
    {1982797200 -10800 0 -03}
    {1995498000 -7200 1 -02}
    {2014246800 -10800 0 -03}
    {2026947600 -7200 1 -02}
    {2045696400 -10800 0 -03}
    {2058397200 -7200 1 -02}
    {2077146000 -10800 0 -03}
    {2090451600 -7200 1 -02}
    {2108595600 -10800 0 -03}
    {2121901200 -7200 1 -02}
    {2140045200 -10800 0 -03}
    {2153350800 -7200 1 -02}
    {2172099600 -10800 0 -03}
    {2184800400 -7200 1 -02}
    {2203549200 -10800 0 -03}
    {2216250000 -7200 1 -02}
    {2234998800 -10800 0 -03}
    {2248304400 -7200 1 -02}
    {2266448400 -10800 0 -03}
    {2279754000 -7200 1 -02}
    {2297898000 -10800 0 -03}
    {2311203600 -7200 1 -02}
    {2329347600 -10800 0 -03}
    {2342653200 -7200 1 -02}
    {2361402000 -10800 0 -03}
    {2374102800 -7200 1 -02}
    {2392851600 -10800 0 -03}
    {2405552400 -7200 1 -02}
    {2424301200 -10800 0 -03}
    {2437606800 -7200 1 -02}
    {2455750800 -10800 0 -03}
    {2469056400 -7200 1 -02}
    {2487200400 -10800 0 -03}
    {2500506000 -7200 1 -02}
    {2519254800 -10800 0 -03}
    {2531955600 -7200 1 -02}
    {2550704400 -10800 0 -03}
    {2563405200 -7200 1 -02}
    {2582154000 -10800 0 -03}
    {2595459600 -7200 1 -02}
    {2613603600 -10800 0 -03}
    {2626909200 -7200 1 -02}
    {2645053200 -10800 0 -03}
    {2658358800 -7200 1 -02}
    {2676502800 -10800 0 -03}
    {2689808400 -7200 1 -02}
    {2708557200 -10800 0 -03}
    {2721258000 -7200 1 -02}
    {2740006800 -10800 0 -03}
    {2752707600 -7200 1 -02}
    {2771456400 -10800 0 -03}
    {2784762000 -7200 1 -02}
    {2802906000 -10800 0 -03}
    {2816211600 -7200 1 -02}
    {2834355600 -10800 0 -03}
    {2847661200 -7200 1 -02}
    {2866410000 -10800 0 -03}
    {2879110800 -7200 1 -02}
    {2897859600 -10800 0 -03}
    {2910560400 -7200 1 -02}
    {2929309200 -10800 0 -03}
    {2942010000 -7200 1 -02}
    {2960758800 -10800 0 -03}
    {2974064400 -7200 1 -02}
    {2992208400 -10800 0 -03}
    {3005514000 -7200 1 -02}
    {3023658000 -10800 0 -03}
    {3036963600 -7200 1 -02}
    {3055712400 -10800 0 -03}
    {3068413200 -7200 1 -02}
    {3087162000 -10800 0 -03}
    {3099862800 -7200 1 -02}
    {3118611600 -10800 0 -03}
    {3131917200 -7200 1 -02}
    {3150061200 -10800 0 -03}
    {3163366800 -7200 1 -02}
    {3181510800 -10800 0 -03}
    {3194816400 -7200 1 -02}
    {3212960400 -10800 0 -03}
    {3226266000 -7200 1 -02}
    {3245014800 -10800 0 -03}
    {3257715600 -7200 1 -02}
    {3276464400 -10800 0 -03}
    {3289165200 -7200 1 -02}
    {3307914000 -10800 0 -03}
    {3321219600 -7200 1 -02}
    {3339363600 -10800 0 -03}
    {3352669200 -7200 1 -02}
    {3370813200 -10800 0 -03}
    {3384118800 -7200 1 -02}
    {3402867600 -10800 0 -03}
    {3415568400 -7200 1 -02}
    {3434317200 -10800 0 -03}
    {3447018000 -7200 1 -02}
    {3465766800 -10800 0 -03}
    {3479072400 -7200 1 -02}
    {3497216400 -10800 0 -03}
    {3510522000 -7200 1 -02}
    {3528666000 -10800 0 -03}
    {3541971600 -7200 1 -02}
    {3560115600 -10800 0 -03}
    {3573421200 -7200 1 -02}
    {3592170000 -10800 0 -03}
    {3604870800 -7200 1 -02}
    {3623619600 -10800 0 -03}
    {3636320400 -7200 1 -02}
    {3655069200 -10800 0 -03}
    {3668374800 -7200 1 -02}
    {3686518800 -10800 0 -03}
    {3699824400 -7200 1 -02}
    {3717968400 -10800 0 -03}
    {3731274000 -7200 1 -02}
    {3750022800 -10800 0 -03}
    {3762723600 -7200 1 -02}
    {3781472400 -10800 0 -03}
    {3794173200 -7200 1 -02}
    {3812922000 -10800 0 -03}
    {3825622800 -7200 1 -02}
    {3844371600 -10800 0 -03}
    {3857677200 -7200 1 -02}
    {3875821200 -10800 0 -03}
    {3889126800 -7200 1 -02}
    {3907270800 -10800 0 -03}
    {3920576400 -7200 1 -02}
    {3939325200 -10800 0 -03}
    {3952026000 -7200 1 -02}
    {3970774800 -10800 0 -03}
    {3983475600 -7200 1 -02}
    {4002224400 -10800 0 -03}
    {4015530000 -7200 1 -02}
    {4033674000 -10800 0 -03}
    {4046979600 -7200 1 -02}
    {4065123600 -10800 0 -03}
    {4078429200 -7200 1 -02}
    {4096573200 -10800 0 -03}
    {-1686083584 -10800 0 -0300}
    {323845200 -7200 0 -0200}
    {338950800 -10800 0 -0300}
    {354675600 -7200 1 -0200}
    {370400400 -10800 0 -0300}
    {386125200 -7200 1 -0200}
    {401850000 -10800 0 -0300}
    {417574800 -7200 1 -0200}
    {433299600 -10800 0 -0300}
    {449024400 -7200 1 -0200}
    {465354000 -10800 0 -0300}
    {481078800 -7200 1 -0200}
    {496803600 -10800 0 -0300}
    {512528400 -7200 1 -0200}
    {528253200 -10800 0 -0300}
    {543978000 -7200 1 -0200}
    {559702800 -10800 0 -0300}
    {575427600 -7200 1 -0200}
    {591152400 -10800 0 -0300}
    {606877200 -7200 1 -0200}
    {622602000 -10800 0 -0300}
    {638326800 -7200 1 -0200}
    {654656400 -10800 0 -0300}
    {670381200 -7200 1 -0200}
    {686106000 -10800 0 -0300}
    {701830800 -7200 1 -0200}
    {717555600 -10800 0 -0300}
    {733280400 -7200 1 -0200}
    {749005200 -10800 0 -0300}
    {764730000 -7200 1 -0200}
    {780454800 -10800 0 -0300}
    {796179600 -7200 1 -0200}
    {811904400 -10800 0 -0300}
    {828234000 -7200 1 -0200}
    {846378000 -10800 0 -0300}
    {859683600 -7200 1 -0200}
    {877827600 -10800 0 -0300}
    {891133200 -7200 1 -0200}
    {909277200 -10800 0 -0300}
    {922582800 -7200 1 -0200}
    {941331600 -10800 0 -0300}
    {954032400 -7200 1 -0200}
    {972781200 -10800 0 -0300}
    {985482000 -7200 1 -0200}
    {1004230800 -10800 0 -0300}
    {1017536400 -7200 1 -0200}
    {1035680400 -10800 0 -0300}
    {1048986000 -7200 1 -0200}
    {1067130000 -10800 0 -0300}
    {1080435600 -7200 1 -0200}
    {1099184400 -10800 0 -0300}
    {1111885200 -7200 1 -0200}
    {1130634000 -10800 0 -0300}
    {1143334800 -7200 1 -0200}
    {1162083600 -10800 0 -0300}
    {1174784400 -7200 1 -0200}
    {1193533200 -10800 0 -0300}
    {1206838800 -7200 1 -0200}
    {1224982800 -10800 0 -0300}
    {1238288400 -7200 1 -0200}
    {1256432400 -10800 0 -0300}
    {1269738000 -7200 1 -0200}
    {1288486800 -10800 0 -0300}
    {1301187600 -7200 1 -0200}
    {1319936400 -10800 0 -0300}
    {1332637200 -7200 1 -0200}
    {1351386000 -10800 0 -0300}
    {1364691600 -7200 1 -0200}
    {1382835600 -10800 0 -0300}
    {1396141200 -7200 1 -0200}
    {1414285200 -10800 0 -0300}
    {1427590800 -7200 1 -0200}
    {1445734800 -10800 0 -0300}
    {1459040400 -7200 1 -0200}
    {1477789200 -10800 0 -0300}
    {1490490000 -7200 1 -0200}
    {1509238800 -10800 0 -0300}
    {1521939600 -7200 1 -0200}
    {1540688400 -10800 0 -0300}
    {1553994000 -7200 1 -0200}
    {1572138000 -10800 0 -0300}
    {1585443600 -7200 1 -0200}
    {1603587600 -10800 0 -0300}
    {1616893200 -7200 1 -0200}
    {1635642000 -10800 0 -0300}
    {1648342800 -7200 1 -0200}
    {1667091600 -10800 0 -0300}
    {1679792400 -7200 0 -0200}
    {1698541200 -7200 0 -0200}
    {1711846800 -3600 1 -0100}
    {1729990800 -7200 0 -0200}
    {1743296400 -3600 1 -0100}
    {1761440400 -7200 0 -0200}
    {1774746000 -3600 1 -0100}
    {1792890000 -7200 0 -0200}
    {1806195600 -3600 1 -0100}
    {1824944400 -7200 0 -0200}
    {1837645200 -3600 1 -0100}
    {1856394000 -7200 0 -0200}
    {1869094800 -3600 1 -0100}
    {1887843600 -7200 0 -0200}
    {1901149200 -3600 1 -0100}
    {1919293200 -7200 0 -0200}
    {1932598800 -3600 1 -0100}
    {1950742800 -7200 0 -0200}
    {1964048400 -3600 1 -0100}
    {1982797200 -7200 0 -0200}
    {1995498000 -3600 1 -0100}
    {2014246800 -7200 0 -0200}
    {2026947600 -3600 1 -0100}
    {2045696400 -7200 0 -0200}
    {2058397200 -3600 1 -0100}
    {2077146000 -7200 0 -0200}
    {2090451600 -3600 1 -0100}
    {2108595600 -7200 0 -0200}
    {2121901200 -3600 1 -0100}
    {2140045200 -7200 0 -0200}
    {2153350800 -3600 1 -0100}
    {2172099600 -7200 0 -0200}
    {2184800400 -3600 1 -0100}
    {2203549200 -7200 0 -0200}
    {2216250000 -3600 1 -0100}
    {2234998800 -7200 0 -0200}
    {2248304400 -3600 1 -0100}
    {2266448400 -7200 0 -0200}
    {2279754000 -3600 1 -0100}
    {2297898000 -7200 0 -0200}
    {2311203600 -3600 1 -0100}
    {2329347600 -7200 0 -0200}
    {2342653200 -3600 1 -0100}
    {2361402000 -7200 0 -0200}
    {2374102800 -3600 1 -0100}
    {2392851600 -7200 0 -0200}
    {2405552400 -3600 1 -0100}
    {2424301200 -7200 0 -0200}
    {2437606800 -3600 1 -0100}
    {2455750800 -7200 0 -0200}
    {2469056400 -3600 1 -0100}
    {2487200400 -7200 0 -0200}
    {2500506000 -3600 1 -0100}
    {2519254800 -7200 0 -0200}
    {2531955600 -3600 1 -0100}
    {2550704400 -7200 0 -0200}
    {2563405200 -3600 1 -0100}
    {2582154000 -7200 0 -0200}
    {2595459600 -3600 1 -0100}
    {2613603600 -7200 0 -0200}
    {2626909200 -3600 1 -0100}
    {2645053200 -7200 0 -0200}
    {2658358800 -3600 1 -0100}
    {2676502800 -7200 0 -0200}
    {2689808400 -3600 1 -0100}
    {2708557200 -7200 0 -0200}
    {2721258000 -3600 1 -0100}
    {2740006800 -7200 0 -0200}
    {2752707600 -3600 1 -0100}
    {2771456400 -7200 0 -0200}
    {2784762000 -3600 1 -0100}
    {2802906000 -7200 0 -0200}
    {2816211600 -3600 1 -0100}
    {2834355600 -7200 0 -0200}
    {2847661200 -3600 1 -0100}
    {2866410000 -7200 0 -0200}
    {2879110800 -3600 1 -0100}
    {2897859600 -7200 0 -0200}
    {2910560400 -3600 1 -0100}
    {2929309200 -7200 0 -0200}
    {2942010000 -3600 1 -0100}
    {2960758800 -7200 0 -0200}
    {2974064400 -3600 1 -0100}
    {2992208400 -7200 0 -0200}
    {3005514000 -3600 1 -0100}
    {3023658000 -7200 0 -0200}
    {3036963600 -3600 1 -0100}
    {3055712400 -7200 0 -0200}
    {3068413200 -3600 1 -0100}
    {3087162000 -7200 0 -0200}
    {3099862800 -3600 1 -0100}
    {3118611600 -7200 0 -0200}
    {3131917200 -3600 1 -0100}
    {3150061200 -7200 0 -0200}
    {3163366800 -3600 1 -0100}
    {3181510800 -7200 0 -0200}
    {3194816400 -3600 1 -0100}
    {3212960400 -7200 0 -0200}
    {3226266000 -3600 1 -0100}
    {3245014800 -7200 0 -0200}
    {3257715600 -3600 1 -0100}
    {3276464400 -7200 0 -0200}
    {3289165200 -3600 1 -0100}
    {3307914000 -7200 0 -0200}
    {3321219600 -3600 1 -0100}
    {3339363600 -7200 0 -0200}
    {3352669200 -3600 1 -0100}
    {3370813200 -7200 0 -0200}
    {3384118800 -3600 1 -0100}
    {3402867600 -7200 0 -0200}
    {3415568400 -3600 1 -0100}
    {3434317200 -7200 0 -0200}
    {3447018000 -3600 1 -0100}
    {3465766800 -7200 0 -0200}
    {3479072400 -3600 1 -0100}
    {3497216400 -7200 0 -0200}
    {3510522000 -3600 1 -0100}
    {3528666000 -7200 0 -0200}
    {3541971600 -3600 1 -0100}
    {3560115600 -7200 0 -0200}
    {3573421200 -3600 1 -0100}
    {3592170000 -7200 0 -0200}
    {3604870800 -3600 1 -0100}
    {3623619600 -7200 0 -0200}
    {3636320400 -3600 1 -0100}
    {3655069200 -7200 0 -0200}
    {3668374800 -3600 1 -0100}
    {3686518800 -7200 0 -0200}
    {3699824400 -3600 1 -0100}
    {3717968400 -7200 0 -0200}
    {3731274000 -3600 1 -0100}
    {3750022800 -7200 0 -0200}
    {3762723600 -3600 1 -0100}
    {3781472400 -7200 0 -0200}
    {3794173200 -3600 1 -0100}
    {3812922000 -7200 0 -0200}
    {3825622800 -3600 1 -0100}
    {3844371600 -7200 0 -0200}
    {3857677200 -3600 1 -0100}
    {3875821200 -7200 0 -0200}
    {3889126800 -3600 1 -0100}
    {3907270800 -7200 0 -0200}
    {3920576400 -3600 1 -0100}
    {3939325200 -7200 0 -0200}
    {3952026000 -3600 1 -0100}
    {3970774800 -7200 0 -0200}
    {3983475600 -3600 1 -0100}
    {4002224400 -7200 0 -0200}
    {4015530000 -3600 1 -0100}
    {4033674000 -7200 0 -0200}
    {4046979600 -3600 1 -0100}
    {4065123600 -7200 0 -0200}
    {4078429200 -3600 1 -0100}
    {4096573200 -7200 0 -0200}
}

Changes to library/tzdata/America/Ojinaga.

1
2
3
4
5
6

7
8

9
10
11
12
13
14
15
1
2
3
4
5

6
7

8
9
10
11
12
13
14
15





-
+

-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Ojinaga) {
    {-9223372036854775808 -25060 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1343149200 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 0 CST}
    {-1220461200 -21600 1 MDT}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {820476000 -21600 0 CST}
    {828864000 -18000 1 CDT}
    {846399600 -21600 0 CST}
    {860313600 -18000 1 CDT}
    {877849200 -21600 0 CST}
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+

    {1552208400 -21600 1 MDT}
    {1572768000 -25200 0 MST}
    {1583658000 -21600 1 MDT}
    {1604217600 -25200 0 MST}
    {1615712400 -21600 1 MDT}
    {1636272000 -25200 0 MST}
    {1647162000 -21600 1 MDT}
    {1667721600 -25200 0 MST}
    {1678611600 -21600 1 MDT}
    {1699171200 -25200 0 MST}
    {1710061200 -21600 1 MDT}
    {1730620800 -25200 0 MST}
    {1741510800 -21600 1 MDT}
    {1762070400 -25200 0 MST}
    {1772960400 -21600 1 MDT}
    {1793520000 -25200 0 MST}
    {1805014800 -21600 1 MDT}
    {1825574400 -25200 0 MST}
    {1836464400 -21600 1 MDT}
    {1857024000 -25200 0 MST}
    {1867914000 -21600 1 MDT}
    {1888473600 -25200 0 MST}
    {1899363600 -21600 1 MDT}
    {1919923200 -25200 0 MST}
    {1930813200 -21600 1 MDT}
    {1951372800 -25200 0 MST}
    {1962867600 -21600 1 MDT}
    {1983427200 -25200 0 MST}
    {1994317200 -21600 1 MDT}
    {2014876800 -25200 0 MST}
    {2025766800 -21600 1 MDT}
    {2046326400 -25200 0 MST}
    {2057216400 -21600 1 MDT}
    {1667120400 -21600 0 CST}
    {1669788000 -21600 0 CST}
    {1678608000 -18000 1 CDT}
    {1699167600 -21600 0 CST}
    {1710057600 -18000 1 CDT}
    {1730617200 -21600 0 CST}
    {1741507200 -18000 1 CDT}
    {1762066800 -21600 0 CST}
    {1772956800 -18000 1 CDT}
    {1793516400 -21600 0 CST}
    {1805011200 -18000 1 CDT}
    {1825570800 -21600 0 CST}
    {1836460800 -18000 1 CDT}
    {1857020400 -21600 0 CST}
    {1867910400 -18000 1 CDT}
    {1888470000 -21600 0 CST}
    {1899360000 -18000 1 CDT}
    {1919919600 -21600 0 CST}
    {1930809600 -18000 1 CDT}
    {1951369200 -21600 0 CST}
    {1962864000 -18000 1 CDT}
    {1983423600 -21600 0 CST}
    {1994313600 -18000 1 CDT}
    {2014873200 -21600 0 CST}
    {2025763200 -18000 1 CDT}
    {2046322800 -21600 0 CST}
    {2057212800 -18000 1 CDT}
    {2077772400 -21600 0 CST}
    {2077776000 -25200 0 MST}
    {2088666000 -21600 1 MDT}
    {2109225600 -25200 0 MST}
    {2120115600 -21600 1 MDT}
    {2140675200 -25200 0 MST}
    {2152170000 -21600 1 MDT}
    {2172729600 -25200 0 MST}
    {2183619600 -21600 1 MDT}
    {2204179200 -25200 0 MST}
    {2215069200 -21600 1 MDT}
    {2235628800 -25200 0 MST}
    {2246518800 -21600 1 MDT}
    {2267078400 -25200 0 MST}
    {2277968400 -21600 1 MDT}
    {2298528000 -25200 0 MST}
    {2309418000 -21600 1 MDT}
    {2329977600 -25200 0 MST}
    {2341472400 -21600 1 MDT}
    {2362032000 -25200 0 MST}
    {2372922000 -21600 1 MDT}
    {2393481600 -25200 0 MST}
    {2404371600 -21600 1 MDT}
    {2424931200 -25200 0 MST}
    {2435821200 -21600 1 MDT}
    {2456380800 -25200 0 MST}
    {2467270800 -21600 1 MDT}
    {2487830400 -25200 0 MST}
    {2499325200 -21600 1 MDT}
    {2519884800 -25200 0 MST}
    {2530774800 -21600 1 MDT}
    {2551334400 -25200 0 MST}
    {2562224400 -21600 1 MDT}
    {2582784000 -25200 0 MST}
    {2593674000 -21600 1 MDT}
    {2614233600 -25200 0 MST}
    {2625123600 -21600 1 MDT}
    {2645683200 -25200 0 MST}
    {2656573200 -21600 1 MDT}
    {2677132800 -25200 0 MST}
    {2688627600 -21600 1 MDT}
    {2709187200 -25200 0 MST}
    {2720077200 -21600 1 MDT}
    {2740636800 -25200 0 MST}
    {2751526800 -21600 1 MDT}
    {2772086400 -25200 0 MST}
    {2782976400 -21600 1 MDT}
    {2803536000 -25200 0 MST}
    {2814426000 -21600 1 MDT}
    {2834985600 -25200 0 MST}
    {2846480400 -21600 1 MDT}
    {2088662400 -18000 1 CDT}
    {2109222000 -21600 0 CST}
    {2120112000 -18000 1 CDT}
    {2140671600 -21600 0 CST}
    {2152166400 -18000 1 CDT}
    {2172726000 -21600 0 CST}
    {2183616000 -18000 1 CDT}
    {2204175600 -21600 0 CST}
    {2215065600 -18000 1 CDT}
    {2235625200 -21600 0 CST}
    {2246515200 -18000 1 CDT}
    {2267074800 -21600 0 CST}
    {2277964800 -18000 1 CDT}
    {2298524400 -21600 0 CST}
    {2309414400 -18000 1 CDT}
    {2329974000 -21600 0 CST}
    {2341468800 -18000 1 CDT}
    {2362028400 -21600 0 CST}
    {2372918400 -18000 1 CDT}
    {2393478000 -21600 0 CST}
    {2404368000 -18000 1 CDT}
    {2424927600 -21600 0 CST}
    {2435817600 -18000 1 CDT}
    {2456377200 -21600 0 CST}
    {2467267200 -18000 1 CDT}
    {2487826800 -21600 0 CST}
    {2499321600 -18000 1 CDT}
    {2519881200 -21600 0 CST}
    {2530771200 -18000 1 CDT}
    {2551330800 -21600 0 CST}
    {2562220800 -18000 1 CDT}
    {2582780400 -21600 0 CST}
    {2593670400 -18000 1 CDT}
    {2614230000 -21600 0 CST}
    {2625120000 -18000 1 CDT}
    {2645679600 -21600 0 CST}
    {2656569600 -18000 1 CDT}
    {2677129200 -21600 0 CST}
    {2688624000 -18000 1 CDT}
    {2709183600 -21600 0 CST}
    {2720073600 -18000 1 CDT}
    {2740633200 -21600 0 CST}
    {2751523200 -18000 1 CDT}
    {2772082800 -21600 0 CST}
    {2782972800 -18000 1 CDT}
    {2803532400 -21600 0 CST}
    {2814422400 -18000 1 CDT}
    {2834982000 -21600 0 CST}
    {2846476800 -18000 1 CDT}
    {2867036400 -21600 0 CST}
    {2867040000 -25200 0 MST}
    {2877930000 -21600 1 MDT}
    {2898489600 -25200 0 MST}
    {2909379600 -21600 1 MDT}
    {2929939200 -25200 0 MST}
    {2940829200 -21600 1 MDT}
    {2961388800 -25200 0 MST}
    {2972278800 -21600 1 MDT}
    {2992838400 -25200 0 MST}
    {3003728400 -21600 1 MDT}
    {3024288000 -25200 0 MST}
    {3035782800 -21600 1 MDT}
    {3056342400 -25200 0 MST}
    {3067232400 -21600 1 MDT}
    {3087792000 -25200 0 MST}
    {3098682000 -21600 1 MDT}
    {3119241600 -25200 0 MST}
    {3130131600 -21600 1 MDT}
    {3150691200 -25200 0 MST}
    {3161581200 -21600 1 MDT}
    {3182140800 -25200 0 MST}
    {3193030800 -21600 1 MDT}
    {3213590400 -25200 0 MST}
    {3225085200 -21600 1 MDT}
    {3245644800 -25200 0 MST}
    {3256534800 -21600 1 MDT}
    {3277094400 -25200 0 MST}
    {3287984400 -21600 1 MDT}
    {3308544000 -25200 0 MST}
    {3319434000 -21600 1 MDT}
    {3339993600 -25200 0 MST}
    {3350883600 -21600 1 MDT}
    {3371443200 -25200 0 MST}
    {3382938000 -21600 1 MDT}
    {3403497600 -25200 0 MST}
    {3414387600 -21600 1 MDT}
    {3434947200 -25200 0 MST}
    {3445837200 -21600 1 MDT}
    {3466396800 -25200 0 MST}
    {3477286800 -21600 1 MDT}
    {3497846400 -25200 0 MST}
    {3508736400 -21600 1 MDT}
    {3529296000 -25200 0 MST}
    {3540186000 -21600 1 MDT}
    {3560745600 -25200 0 MST}
    {3572240400 -21600 1 MDT}
    {3592800000 -25200 0 MST}
    {3603690000 -21600 1 MDT}
    {3624249600 -25200 0 MST}
    {3635139600 -21600 1 MDT}
    {3655699200 -25200 0 MST}
    {3666589200 -21600 1 MDT}
    {3687148800 -25200 0 MST}
    {3698038800 -21600 1 MDT}
    {3718598400 -25200 0 MST}
    {3730093200 -21600 1 MDT}
    {3750652800 -25200 0 MST}
    {3761542800 -21600 1 MDT}
    {3782102400 -25200 0 MST}
    {3792992400 -21600 1 MDT}
    {3813552000 -25200 0 MST}
    {3824442000 -21600 1 MDT}
    {3845001600 -25200 0 MST}
    {3855891600 -21600 1 MDT}
    {3876451200 -25200 0 MST}
    {3887341200 -21600 1 MDT}
    {3907900800 -25200 0 MST}
    {3919395600 -21600 1 MDT}
    {3939955200 -25200 0 MST}
    {3950845200 -21600 1 MDT}
    {3971404800 -25200 0 MST}
    {3982294800 -21600 1 MDT}
    {2877926400 -18000 1 CDT}
    {2898486000 -21600 0 CST}
    {2909376000 -18000 1 CDT}
    {2929935600 -21600 0 CST}
    {2940825600 -18000 1 CDT}
    {2961385200 -21600 0 CST}
    {2972275200 -18000 1 CDT}
    {2992834800 -21600 0 CST}
    {3003724800 -18000 1 CDT}
    {3024284400 -21600 0 CST}
    {3035779200 -18000 1 CDT}
    {3056338800 -21600 0 CST}
    {3067228800 -18000 1 CDT}
    {3087788400 -21600 0 CST}
    {3098678400 -18000 1 CDT}
    {3119238000 -21600 0 CST}
    {3130128000 -18000 1 CDT}
    {3150687600 -21600 0 CST}
    {3161577600 -18000 1 CDT}
    {3182137200 -21600 0 CST}
    {3193027200 -18000 1 CDT}
    {3213586800 -21600 0 CST}
    {3225081600 -18000 1 CDT}
    {3245641200 -21600 0 CST}
    {3256531200 -18000 1 CDT}
    {3277090800 -21600 0 CST}
    {3287980800 -18000 1 CDT}
    {3308540400 -21600 0 CST}
    {3319430400 -18000 1 CDT}
    {3339990000 -21600 0 CST}
    {3350880000 -18000 1 CDT}
    {3371439600 -21600 0 CST}
    {3382934400 -18000 1 CDT}
    {3403494000 -21600 0 CST}
    {3414384000 -18000 1 CDT}
    {3434943600 -21600 0 CST}
    {3445833600 -18000 1 CDT}
    {3466393200 -21600 0 CST}
    {3477283200 -18000 1 CDT}
    {3497842800 -21600 0 CST}
    {3508732800 -18000 1 CDT}
    {3529292400 -21600 0 CST}
    {3540182400 -18000 1 CDT}
    {3560742000 -21600 0 CST}
    {3572236800 -18000 1 CDT}
    {3592796400 -21600 0 CST}
    {3603686400 -18000 1 CDT}
    {3624246000 -21600 0 CST}
    {3635136000 -18000 1 CDT}
    {3655695600 -21600 0 CST}
    {3666585600 -18000 1 CDT}
    {3687145200 -21600 0 CST}
    {3698035200 -18000 1 CDT}
    {3718594800 -21600 0 CST}
    {3730089600 -18000 1 CDT}
    {3750649200 -21600 0 CST}
    {3761539200 -18000 1 CDT}
    {3782098800 -21600 0 CST}
    {3792988800 -18000 1 CDT}
    {3813548400 -21600 0 CST}
    {3824438400 -18000 1 CDT}
    {3844998000 -21600 0 CST}
    {3855888000 -18000 1 CDT}
    {3876447600 -21600 0 CST}
    {3887337600 -18000 1 CDT}
    {3907897200 -21600 0 CST}
    {3919392000 -18000 1 CDT}
    {3939951600 -21600 0 CST}
    {3950841600 -18000 1 CDT}
    {3971401200 -21600 0 CST}
    {3982291200 -18000 1 CDT}
    {4002850800 -21600 0 CST}
    {4002854400 -25200 0 MST}
    {4013744400 -21600 1 MDT}
    {4034304000 -25200 0 MST}
    {4045194000 -21600 1 MDT}
    {4065753600 -25200 0 MST}
    {4076643600 -21600 1 MDT}
    {4097203200 -25200 0 MST}
    {4013740800 -18000 1 CDT}
    {4034300400 -21600 0 CST}
    {4045190400 -18000 1 CDT}
    {4065750000 -21600 0 CST}
    {4076640000 -18000 1 CDT}
    {4097199600 -21600 0 CST}
}

Changes to library/tzdata/America/Pangnirtung.

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
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
1
2
3


4
5


























































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Iqaluit)]} {
    LoadTimeZoneFile America/Iqaluit

set TZData(:America/Pangnirtung) {
}
set TZData(:America/Pangnirtung) $TZData(:America/Iqaluit)
    {-9223372036854775808 0 0 -00}
    {-1546300800 -14400 0 AST}
    {-880221600 -10800 1 AWT}
    {-769395600 -10800 1 APT}
    {-765399600 -14400 0 AST}
    {-147902400 -7200 1 ADDT}
    {-131572800 -14400 0 AST}
    {325663200 -10800 1 ADT}
    {341384400 -14400 0 AST}
    {357112800 -10800 1 ADT}
    {372834000 -14400 0 AST}
    {388562400 -10800 1 ADT}
    {404888400 -14400 0 AST}
    {420012000 -10800 1 ADT}
    {436338000 -14400 0 AST}
    {452066400 -10800 1 ADT}
    {467787600 -14400 0 AST}
    {483516000 -10800 1 ADT}
    {499237200 -14400 0 AST}
    {514965600 -10800 1 ADT}
    {530686800 -14400 0 AST}
    {544600800 -10800 1 ADT}
    {562136400 -14400 0 AST}
    {576050400 -10800 1 ADT}
    {594190800 -14400 0 AST}
    {607500000 -10800 1 ADT}
    {625640400 -14400 0 AST}
    {638949600 -10800 1 ADT}
    {657090000 -14400 0 AST}
    {671004000 -10800 1 ADT}
    {688539600 -14400 0 AST}
    {702453600 -10800 1 ADT}
    {719989200 -14400 0 AST}
    {733903200 -10800 1 ADT}
    {752043600 -14400 0 AST}
    {765352800 -10800 1 ADT}
    {783493200 -14400 0 AST}
    {796802400 -18000 0 EST}
    {796806000 -14400 1 EDT}
    {814946400 -18000 0 EST}
    {828860400 -14400 1 EDT}
    {846396000 -18000 0 EST}
    {860310000 -14400 1 EDT}
    {877845600 -18000 0 EST}
    {891759600 -14400 1 EDT}
    {909295200 -18000 0 EST}
    {923209200 -14400 1 EDT}
    {941353200 -21600 0 CST}
    {954662400 -18000 1 CDT}
    {972806400 -18000 0 EST}
    {986108400 -14400 1 EDT}
    {1004248800 -18000 0 EST}
    {1018162800 -14400 1 EDT}
    {1035698400 -18000 0 EST}
    {1049612400 -14400 1 EDT}
    {1067148000 -18000 0 EST}
    {1081062000 -14400 1 EDT}
    {1099202400 -18000 0 EST}
    {1112511600 -14400 1 EDT}
    {1130652000 -18000 0 EST}
    {1143961200 -14400 1 EDT}
    {1162101600 -18000 0 EST}
    {1173596400 -14400 1 EDT}
    {1194156000 -18000 0 EST}
    {1205046000 -14400 1 EDT}
    {1225605600 -18000 0 EST}
    {1236495600 -14400 1 EDT}
    {1257055200 -18000 0 EST}
    {1268550000 -14400 1 EDT}
    {1289109600 -18000 0 EST}
    {1299999600 -14400 1 EDT}
    {1320559200 -18000 0 EST}
    {1331449200 -14400 1 EDT}
    {1352008800 -18000 0 EST}
    {1362898800 -14400 1 EDT}
    {1383458400 -18000 0 EST}
    {1394348400 -14400 1 EDT}
    {1414908000 -18000 0 EST}
    {1425798000 -14400 1 EDT}
    {1446357600 -18000 0 EST}
    {1457852400 -14400 1 EDT}
    {1478412000 -18000 0 EST}
    {1489302000 -14400 1 EDT}
    {1509861600 -18000 0 EST}
    {1520751600 -14400 1 EDT}
    {1541311200 -18000 0 EST}
    {1552201200 -14400 1 EDT}
    {1572760800 -18000 0 EST}
    {1583650800 -14400 1 EDT}
    {1604210400 -18000 0 EST}
    {1615705200 -14400 1 EDT}
    {1636264800 -18000 0 EST}
    {1647154800 -14400 1 EDT}
    {1667714400 -18000 0 EST}
    {1678604400 -14400 1 EDT}
    {1699164000 -18000 0 EST}
    {1710054000 -14400 1 EDT}
    {1730613600 -18000 0 EST}
    {1741503600 -14400 1 EDT}
    {1762063200 -18000 0 EST}
    {1772953200 -14400 1 EDT}
    {1793512800 -18000 0 EST}
    {1805007600 -14400 1 EDT}
    {1825567200 -18000 0 EST}
    {1836457200 -14400 1 EDT}
    {1857016800 -18000 0 EST}
    {1867906800 -14400 1 EDT}
    {1888466400 -18000 0 EST}
    {1899356400 -14400 1 EDT}
    {1919916000 -18000 0 EST}
    {1930806000 -14400 1 EDT}
    {1951365600 -18000 0 EST}
    {1962860400 -14400 1 EDT}
    {1983420000 -18000 0 EST}
    {1994310000 -14400 1 EDT}
    {2014869600 -18000 0 EST}
    {2025759600 -14400 1 EDT}
    {2046319200 -18000 0 EST}
    {2057209200 -14400 1 EDT}
    {2077768800 -18000 0 EST}
    {2088658800 -14400 1 EDT}
    {2109218400 -18000 0 EST}
    {2120108400 -14400 1 EDT}
    {2140668000 -18000 0 EST}
    {2152162800 -14400 1 EDT}
    {2172722400 -18000 0 EST}
    {2183612400 -14400 1 EDT}
    {2204172000 -18000 0 EST}
    {2215062000 -14400 1 EDT}
    {2235621600 -18000 0 EST}
    {2246511600 -14400 1 EDT}
    {2267071200 -18000 0 EST}
    {2277961200 -14400 1 EDT}
    {2298520800 -18000 0 EST}
    {2309410800 -14400 1 EDT}
    {2329970400 -18000 0 EST}
    {2341465200 -14400 1 EDT}
    {2362024800 -18000 0 EST}
    {2372914800 -14400 1 EDT}
    {2393474400 -18000 0 EST}
    {2404364400 -14400 1 EDT}
    {2424924000 -18000 0 EST}
    {2435814000 -14400 1 EDT}
    {2456373600 -18000 0 EST}
    {2467263600 -14400 1 EDT}
    {2487823200 -18000 0 EST}
    {2499318000 -14400 1 EDT}
    {2519877600 -18000 0 EST}
    {2530767600 -14400 1 EDT}
    {2551327200 -18000 0 EST}
    {2562217200 -14400 1 EDT}
    {2582776800 -18000 0 EST}
    {2593666800 -14400 1 EDT}
    {2614226400 -18000 0 EST}
    {2625116400 -14400 1 EDT}
    {2645676000 -18000 0 EST}
    {2656566000 -14400 1 EDT}
    {2677125600 -18000 0 EST}
    {2688620400 -14400 1 EDT}
    {2709180000 -18000 0 EST}
    {2720070000 -14400 1 EDT}
    {2740629600 -18000 0 EST}
    {2751519600 -14400 1 EDT}
    {2772079200 -18000 0 EST}
    {2782969200 -14400 1 EDT}
    {2803528800 -18000 0 EST}
    {2814418800 -14400 1 EDT}
    {2834978400 -18000 0 EST}
    {2846473200 -14400 1 EDT}
    {2867032800 -18000 0 EST}
    {2877922800 -14400 1 EDT}
    {2898482400 -18000 0 EST}
    {2909372400 -14400 1 EDT}
    {2929932000 -18000 0 EST}
    {2940822000 -14400 1 EDT}
    {2961381600 -18000 0 EST}
    {2972271600 -14400 1 EDT}
    {2992831200 -18000 0 EST}
    {3003721200 -14400 1 EDT}
    {3024280800 -18000 0 EST}
    {3035775600 -14400 1 EDT}
    {3056335200 -18000 0 EST}
    {3067225200 -14400 1 EDT}
    {3087784800 -18000 0 EST}
    {3098674800 -14400 1 EDT}
    {3119234400 -18000 0 EST}
    {3130124400 -14400 1 EDT}
    {3150684000 -18000 0 EST}
    {3161574000 -14400 1 EDT}
    {3182133600 -18000 0 EST}
    {3193023600 -14400 1 EDT}
    {3213583200 -18000 0 EST}
    {3225078000 -14400 1 EDT}
    {3245637600 -18000 0 EST}
    {3256527600 -14400 1 EDT}
    {3277087200 -18000 0 EST}
    {3287977200 -14400 1 EDT}
    {3308536800 -18000 0 EST}
    {3319426800 -14400 1 EDT}
    {3339986400 -18000 0 EST}
    {3350876400 -14400 1 EDT}
    {3371436000 -18000 0 EST}
    {3382930800 -14400 1 EDT}
    {3403490400 -18000 0 EST}
    {3414380400 -14400 1 EDT}
    {3434940000 -18000 0 EST}
    {3445830000 -14400 1 EDT}
    {3466389600 -18000 0 EST}
    {3477279600 -14400 1 EDT}
    {3497839200 -18000 0 EST}
    {3508729200 -14400 1 EDT}
    {3529288800 -18000 0 EST}
    {3540178800 -14400 1 EDT}
    {3560738400 -18000 0 EST}
    {3572233200 -14400 1 EDT}
    {3592792800 -18000 0 EST}
    {3603682800 -14400 1 EDT}
    {3624242400 -18000 0 EST}
    {3635132400 -14400 1 EDT}
    {3655692000 -18000 0 EST}
    {3666582000 -14400 1 EDT}
    {3687141600 -18000 0 EST}
    {3698031600 -14400 1 EDT}
    {3718591200 -18000 0 EST}
    {3730086000 -14400 1 EDT}
    {3750645600 -18000 0 EST}
    {3761535600 -14400 1 EDT}
    {3782095200 -18000 0 EST}
    {3792985200 -14400 1 EDT}
    {3813544800 -18000 0 EST}
    {3824434800 -14400 1 EDT}
    {3844994400 -18000 0 EST}
    {3855884400 -14400 1 EDT}
    {3876444000 -18000 0 EST}
    {3887334000 -14400 1 EDT}
    {3907893600 -18000 0 EST}
    {3919388400 -14400 1 EDT}
    {3939948000 -18000 0 EST}
    {3950838000 -14400 1 EDT}
    {3971397600 -18000 0 EST}
    {3982287600 -14400 1 EDT}
    {4002847200 -18000 0 EST}
    {4013737200 -14400 1 EDT}
    {4034296800 -18000 0 EST}
    {4045186800 -14400 1 EDT}
    {4065746400 -18000 0 EST}
    {4076636400 -14400 1 EDT}
    {4097196000 -18000 0 EST}
}

Changes to library/tzdata/America/Paramaribo.

1
2
3
4
5
6
7
8


9
1
2
3
4
5
6


7
8
9






-
-
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Paramaribo) {
    {-9223372036854775808 -13240 0 LMT}
    {-1861906760 -13252 0 PMT}
    {-1104524348 -13236 0 PMT}
    {-765317964 -12600 0 -0330}
    {465449400 -10800 0 -03}
    {-765317964 -12600 0 -0430}
    {465449400 -10800 0 -0300}
}

Changes to library/tzdata/America/Port_of_Spain.

1


2
3


4
5
6
1
2
3


4
5




+
+
-
-
+
+
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico

set TZData(:America/Port_of_Spain) {
}
set TZData(:America/Port_of_Spain) $TZData(:America/Puerto_Rico)
    {-9223372036854775808 -14764 0 LMT}
    {-1825098836 -14400 0 AST}
}

Changes to library/tzdata/America/Porto_Velho.

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
30
31
32
33
34






























35
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
30
31
32
33
34
35




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Porto_Velho) {
    {-9223372036854775808 -15336 0 LMT}
    {-1767210264 -14400 0 -04}
    {-1206954000 -10800 1 -04}
    {-1191358800 -14400 0 -04}
    {-1175371200 -10800 1 -04}
    {-1159822800 -14400 0 -04}
    {-633816000 -10800 1 -04}
    {-622065600 -14400 0 -04}
    {-602280000 -10800 1 -04}
    {-591829200 -14400 0 -04}
    {-570744000 -10800 1 -04}
    {-560206800 -14400 0 -04}
    {-539121600 -10800 1 -04}
    {-531349200 -14400 0 -04}
    {-191361600 -10800 1 -04}
    {-184194000 -14400 0 -04}
    {-155160000 -10800 1 -04}
    {-150066000 -14400 0 -04}
    {-128894400 -10800 1 -04}
    {-121122000 -14400 0 -04}
    {-99950400 -10800 1 -04}
    {-89586000 -14400 0 -04}
    {-68414400 -10800 1 -04}
    {-57963600 -14400 0 -04}
    {499752000 -10800 1 -04}
    {511239600 -14400 0 -04}
    {530596800 -10800 1 -04}
    {540270000 -14400 0 -04}
    {562132800 -10800 1 -04}
    {571201200 -14400 0 -04}
    {590036400 -14400 0 -04}
    {-1767210264 -14400 0 -0400}
    {-1206954000 -10800 1 -0300}
    {-1191358800 -14400 0 -0400}
    {-1175371200 -10800 1 -0300}
    {-1159822800 -14400 0 -0400}
    {-633816000 -10800 1 -0300}
    {-622065600 -14400 0 -0400}
    {-602280000 -10800 1 -0300}
    {-591829200 -14400 0 -0400}
    {-570744000 -10800 1 -0300}
    {-560206800 -14400 0 -0400}
    {-539121600 -10800 1 -0300}
    {-531349200 -14400 0 -0400}
    {-191361600 -10800 1 -0300}
    {-184194000 -14400 0 -0400}
    {-155160000 -10800 1 -0300}
    {-150066000 -14400 0 -0400}
    {-128894400 -10800 1 -0300}
    {-121122000 -14400 0 -0400}
    {-99950400 -10800 1 -0300}
    {-89586000 -14400 0 -0400}
    {-68414400 -10800 1 -0300}
    {-57963600 -14400 0 -0400}
    {499752000 -10800 1 -0300}
    {511239600 -14400 0 -0400}
    {530596800 -10800 1 -0300}
    {540270000 -14400 0 -0400}
    {562132800 -10800 1 -0300}
    {571201200 -14400 0 -0400}
    {590036400 -14400 0 -0400}
}

Changes to library/tzdata/America/Punta_Arenas.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Punta_Arenas) {
    {-9223372036854775808 -17020 0 LMT}
    {-2524504580 -16966 0 SMT}
    {-1892661434 -18000 0 -05}
    {-1688410800 -16966 0 SMT}
    {-1619205434 -14400 0 -04}
    {-1593806400 -16966 0 SMT}
    {-1335986234 -18000 0 -05}
    {-1335985200 -14400 1 -05}
    {-1317585600 -18000 0 -05}
    {-1304362800 -14400 1 -05}
    {-1286049600 -18000 0 -05}
    {-1272826800 -14400 1 -05}
    {-1254513600 -18000 0 -05}
    {-1241290800 -14400 1 -05}
    {-1222977600 -18000 0 -05}
    {-1209754800 -14400 1 -05}
    {-1191355200 -18000 0 -05}
    {-1178132400 -14400 0 -04}
    {-870552000 -18000 0 -05}
    {-865278000 -14400 0 -04}
    {-718056000 -18000 0 -05}
    {-713649600 -14400 0 -04}
    {-36619200 -10800 1 -04}
    {-23922000 -14400 0 -04}
    {-3355200 -10800 1 -04}
    {7527600 -14400 0 -04}
    {24465600 -10800 1 -04}
    {37767600 -14400 0 -04}
    {55915200 -10800 1 -04}
    {69217200 -14400 0 -04}
    {87969600 -10800 1 -04}
    {100666800 -14400 0 -04}
    {118209600 -10800 1 -04}
    {132116400 -14400 0 -04}
    {150868800 -10800 1 -04}
    {163566000 -14400 0 -04}
    {182318400 -10800 1 -04}
    {195620400 -14400 0 -04}
    {213768000 -10800 1 -04}
    {227070000 -14400 0 -04}
    {245217600 -10800 1 -04}
    {258519600 -14400 0 -04}
    {277272000 -10800 1 -04}
    {289969200 -14400 0 -04}
    {308721600 -10800 1 -04}
    {321418800 -14400 0 -04}
    {340171200 -10800 1 -04}
    {353473200 -14400 0 -04}
    {371620800 -10800 1 -04}
    {384922800 -14400 0 -04}
    {403070400 -10800 1 -04}
    {416372400 -14400 0 -04}
    {434520000 -10800 1 -04}
    {447822000 -14400 0 -04}
    {466574400 -10800 1 -04}
    {479271600 -14400 0 -04}
    {498024000 -10800 1 -04}
    {510721200 -14400 0 -04}
    {529473600 -10800 1 -04}
    {545194800 -14400 0 -04}
    {560923200 -10800 1 -04}
    {574225200 -14400 0 -04}
    {592372800 -10800 1 -04}
    {605674800 -14400 0 -04}
    {624427200 -10800 1 -04}
    {637124400 -14400 0 -04}
    {653457600 -10800 1 -04}
    {668574000 -14400 0 -04}
    {687326400 -10800 1 -04}
    {700628400 -14400 0 -04}
    {718776000 -10800 1 -04}
    {732078000 -14400 0 -04}
    {750225600 -10800 1 -04}
    {763527600 -14400 0 -04}
    {781675200 -10800 1 -04}
    {794977200 -14400 0 -04}
    {813729600 -10800 1 -04}
    {826426800 -14400 0 -04}
    {845179200 -10800 1 -04}
    {859690800 -14400 0 -04}
    {876628800 -10800 1 -04}
    {889930800 -14400 0 -04}
    {906868800 -10800 1 -04}
    {923194800 -14400 0 -04}
    {939528000 -10800 1 -04}
    {952830000 -14400 0 -04}
    {971582400 -10800 1 -04}
    {984279600 -14400 0 -04}
    {1003032000 -10800 1 -04}
    {1015729200 -14400 0 -04}
    {1034481600 -10800 1 -04}
    {1047178800 -14400 0 -04}
    {1065931200 -10800 1 -04}
    {1079233200 -14400 0 -04}
    {1097380800 -10800 1 -04}
    {1110682800 -14400 0 -04}
    {1128830400 -10800 1 -04}
    {1142132400 -14400 0 -04}
    {1160884800 -10800 1 -04}
    {1173582000 -14400 0 -04}
    {1192334400 -10800 1 -04}
    {1206846000 -14400 0 -04}
    {1223784000 -10800 1 -04}
    {1237086000 -14400 0 -04}
    {1255233600 -10800 1 -04}
    {1270350000 -14400 0 -04}
    {1286683200 -10800 1 -04}
    {1304823600 -14400 0 -04}
    {1313899200 -10800 1 -04}
    {1335668400 -14400 0 -04}
    {1346558400 -10800 1 -04}
    {1367118000 -14400 0 -04}
    {1378612800 -10800 1 -04}
    {1398567600 -14400 0 -04}
    {1410062400 -10800 1 -04}
    {1463281200 -14400 0 -04}
    {1471147200 -10800 1 -04}
    {1480820400 -10800 0 -03}
    {-2524504580 -16965 0 SMT}
    {-1892661435 -18000 0 -0500}
    {-1688410800 -16965 0 SMT}
    {-1619205435 -14400 0 -0400}
    {-1593806400 -16965 0 SMT}
    {-1335986235 -18000 0 -0500}
    {-1335985200 -14400 1 -0400}
    {-1317585600 -18000 0 -0500}
    {-1304362800 -14400 1 -0400}
    {-1286049600 -18000 0 -0500}
    {-1272826800 -14400 1 -0400}
    {-1254513600 -18000 0 -0500}
    {-1241290800 -14400 1 -0400}
    {-1222977600 -18000 0 -0500}
    {-1209754800 -14400 1 -0400}
    {-1191355200 -18000 0 -0500}
    {-1178132400 -14400 0 -0400}
    {-870552000 -18000 0 -0500}
    {-865278000 -14400 0 -0400}
    {-736632000 -14400 1 -0400}
    {-718056000 -18000 0 -0500}
    {-713649600 -14400 0 -0400}
    {-36619200 -10800 1 -0300}
    {-23922000 -14400 0 -0400}
    {-3355200 -10800 1 -0300}
    {7527600 -14400 0 -0400}
    {24465600 -10800 1 -0300}
    {37767600 -14400 0 -0400}
    {55915200 -10800 1 -0300}
    {69217200 -14400 0 -0400}
    {87969600 -10800 1 -0300}
    {100666800 -14400 0 -0400}
    {118209600 -10800 1 -0300}
    {132116400 -14400 0 -0400}
    {150868800 -10800 1 -0300}
    {163566000 -14400 0 -0400}
    {182318400 -10800 1 -0300}
    {195620400 -14400 0 -0400}
    {213768000 -10800 1 -0300}
    {227070000 -14400 0 -0400}
    {245217600 -10800 1 -0300}
    {258519600 -14400 0 -0400}
    {277272000 -10800 1 -0300}
    {289969200 -14400 0 -0400}
    {308721600 -10800 1 -0300}
    {321418800 -14400 0 -0400}
    {340171200 -10800 1 -0300}
    {353473200 -14400 0 -0400}
    {371620800 -10800 1 -0300}
    {384922800 -14400 0 -0400}
    {403070400 -10800 1 -0300}
    {416372400 -14400 0 -0400}
    {434520000 -10800 1 -0300}
    {447822000 -14400 0 -0400}
    {466574400 -10800 1 -0300}
    {479271600 -14400 0 -0400}
    {498024000 -10800 1 -0300}
    {510721200 -14400 0 -0400}
    {529473600 -10800 1 -0300}
    {545194800 -14400 0 -0400}
    {560923200 -10800 1 -0300}
    {574225200 -14400 0 -0400}
    {592372800 -10800 1 -0300}
    {605674800 -14400 0 -0400}
    {624427200 -10800 1 -0300}
    {637124400 -14400 0 -0400}
    {653457600 -10800 1 -0300}
    {668574000 -14400 0 -0400}
    {687326400 -10800 1 -0300}
    {700628400 -14400 0 -0400}
    {718776000 -10800 1 -0300}
    {732078000 -14400 0 -0400}
    {750225600 -10800 1 -0300}
    {763527600 -14400 0 -0400}
    {781675200 -10800 1 -0300}
    {794977200 -14400 0 -0400}
    {813729600 -10800 1 -0300}
    {826426800 -14400 0 -0400}
    {845179200 -10800 1 -0300}
    {859690800 -14400 0 -0400}
    {876628800 -10800 1 -0300}
    {889930800 -14400 0 -0400}
    {906868800 -10800 1 -0300}
    {923194800 -14400 0 -0400}
    {939528000 -10800 1 -0300}
    {952830000 -14400 0 -0400}
    {971582400 -10800 1 -0300}
    {984279600 -14400 0 -0400}
    {1003032000 -10800 1 -0300}
    {1015729200 -14400 0 -0400}
    {1034481600 -10800 1 -0300}
    {1047178800 -14400 0 -0400}
    {1065931200 -10800 1 -0300}
    {1079233200 -14400 0 -0400}
    {1097380800 -10800 1 -0300}
    {1110682800 -14400 0 -0400}
    {1128830400 -10800 1 -0300}
    {1142132400 -14400 0 -0400}
    {1160884800 -10800 1 -0300}
    {1173582000 -14400 0 -0400}
    {1192334400 -10800 1 -0300}
    {1206846000 -14400 0 -0400}
    {1223784000 -10800 1 -0300}
    {1237086000 -14400 0 -0400}
    {1255233600 -10800 1 -0300}
    {1270350000 -14400 0 -0400}
    {1286683200 -10800 1 -0300}
    {1304823600 -14400 0 -0400}
    {1313899200 -10800 1 -0300}
    {1335668400 -14400 0 -0400}
    {1346558400 -10800 1 -0300}
    {1367118000 -14400 0 -0400}
    {1378612800 -10800 1 -0300}
    {1398567600 -14400 0 -0400}
    {1410062400 -10800 1 -0300}
    {1463281200 -14400 0 -0400}
    {1471147200 -10800 1 -0300}
    {1480820400 -10800 0 -0300}
}

Changes to library/tzdata/America/Rainy_River.

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
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
1
2
3


4
5






































































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Winnipeg)]} {
    LoadTimeZoneFile America/Winnipeg

set TZData(:America/Rainy_River) {
}
set TZData(:America/Rainy_River) $TZData(:America/Winnipeg)
    {-9223372036854775808 -22696 0 LMT}
    {-2366732504 -21600 0 CST}
    {-1632067200 -18000 1 CDT}
    {-1615136400 -21600 0 CST}
    {-923248800 -18000 1 CDT}
    {-880214400 -18000 0 CWT}
    {-769395600 -18000 1 CPT}
    {-765392400 -21600 0 CST}
    {136368000 -18000 1 CDT}
    {152089200 -21600 0 CST}
    {167817600 -18000 1 CDT}
    {183538800 -21600 0 CST}
    {199267200 -18000 1 CDT}
    {215593200 -21600 0 CST}
    {230716800 -18000 1 CDT}
    {247042800 -21600 0 CST}
    {262771200 -18000 1 CDT}
    {278492400 -21600 0 CST}
    {294220800 -18000 1 CDT}
    {309942000 -21600 0 CST}
    {325670400 -18000 1 CDT}
    {341391600 -21600 0 CST}
    {357120000 -18000 1 CDT}
    {372841200 -21600 0 CST}
    {388569600 -18000 1 CDT}
    {404895600 -21600 0 CST}
    {420019200 -18000 1 CDT}
    {436345200 -21600 0 CST}
    {452073600 -18000 1 CDT}
    {467794800 -21600 0 CST}
    {483523200 -18000 1 CDT}
    {499244400 -21600 0 CST}
    {514972800 -18000 1 CDT}
    {530694000 -21600 0 CST}
    {544608000 -18000 1 CDT}
    {562143600 -21600 0 CST}
    {576057600 -18000 1 CDT}
    {594198000 -21600 0 CST}
    {607507200 -18000 1 CDT}
    {625647600 -21600 0 CST}
    {638956800 -18000 1 CDT}
    {657097200 -21600 0 CST}
    {671011200 -18000 1 CDT}
    {688546800 -21600 0 CST}
    {702460800 -18000 1 CDT}
    {719996400 -21600 0 CST}
    {733910400 -18000 1 CDT}
    {752050800 -21600 0 CST}
    {765360000 -18000 1 CDT}
    {783500400 -21600 0 CST}
    {796809600 -18000 1 CDT}
    {814950000 -21600 0 CST}
    {828864000 -18000 1 CDT}
    {846399600 -21600 0 CST}
    {860313600 -18000 1 CDT}
    {877849200 -21600 0 CST}
    {891763200 -18000 1 CDT}
    {909298800 -21600 0 CST}
    {923212800 -18000 1 CDT}
    {941353200 -21600 0 CST}
    {954662400 -18000 1 CDT}
    {972802800 -21600 0 CST}
    {986112000 -18000 1 CDT}
    {1004252400 -21600 0 CST}
    {1018166400 -18000 1 CDT}
    {1035702000 -21600 0 CST}
    {1049616000 -18000 1 CDT}
    {1067151600 -21600 0 CST}
    {1081065600 -18000 1 CDT}
    {1099206000 -21600 0 CST}
    {1112515200 -18000 1 CDT}
    {1130655600 -21600 0 CST}
    {1143964800 -18000 1 CDT}
    {1162105200 -21600 0 CST}
    {1173600000 -18000 1 CDT}
    {1194159600 -21600 0 CST}
    {1205049600 -18000 1 CDT}
    {1225609200 -21600 0 CST}
    {1236499200 -18000 1 CDT}
    {1257058800 -21600 0 CST}
    {1268553600 -18000 1 CDT}
    {1289113200 -21600 0 CST}
    {1300003200 -18000 1 CDT}
    {1320562800 -21600 0 CST}
    {1331452800 -18000 1 CDT}
    {1352012400 -21600 0 CST}
    {1362902400 -18000 1 CDT}
    {1383462000 -21600 0 CST}
    {1394352000 -18000 1 CDT}
    {1414911600 -21600 0 CST}
    {1425801600 -18000 1 CDT}
    {1446361200 -21600 0 CST}
    {1457856000 -18000 1 CDT}
    {1478415600 -21600 0 CST}
    {1489305600 -18000 1 CDT}
    {1509865200 -21600 0 CST}
    {1520755200 -18000 1 CDT}
    {1541314800 -21600 0 CST}
    {1552204800 -18000 1 CDT}
    {1572764400 -21600 0 CST}
    {1583654400 -18000 1 CDT}
    {1604214000 -21600 0 CST}
    {1615708800 -18000 1 CDT}
    {1636268400 -21600 0 CST}
    {1647158400 -18000 1 CDT}
    {1667718000 -21600 0 CST}
    {1678608000 -18000 1 CDT}
    {1699167600 -21600 0 CST}
    {1710057600 -18000 1 CDT}
    {1730617200 -21600 0 CST}
    {1741507200 -18000 1 CDT}
    {1762066800 -21600 0 CST}
    {1772956800 -18000 1 CDT}
    {1793516400 -21600 0 CST}
    {1805011200 -18000 1 CDT}
    {1825570800 -21600 0 CST}
    {1836460800 -18000 1 CDT}
    {1857020400 -21600 0 CST}
    {1867910400 -18000 1 CDT}
    {1888470000 -21600 0 CST}
    {1899360000 -18000 1 CDT}
    {1919919600 -21600 0 CST}
    {1930809600 -18000 1 CDT}
    {1951369200 -21600 0 CST}
    {1962864000 -18000 1 CDT}
    {1983423600 -21600 0 CST}
    {1994313600 -18000 1 CDT}
    {2014873200 -21600 0 CST}
    {2025763200 -18000 1 CDT}
    {2046322800 -21600 0 CST}
    {2057212800 -18000 1 CDT}
    {2077772400 -21600 0 CST}
    {2088662400 -18000 1 CDT}
    {2109222000 -21600 0 CST}
    {2120112000 -18000 1 CDT}
    {2140671600 -21600 0 CST}
    {2152166400 -18000 1 CDT}
    {2172726000 -21600 0 CST}
    {2183616000 -18000 1 CDT}
    {2204175600 -21600 0 CST}
    {2215065600 -18000 1 CDT}
    {2235625200 -21600 0 CST}
    {2246515200 -18000 1 CDT}
    {2267074800 -21600 0 CST}
    {2277964800 -18000 1 CDT}
    {2298524400 -21600 0 CST}
    {2309414400 -18000 1 CDT}
    {2329974000 -21600 0 CST}
    {2341468800 -18000 1 CDT}
    {2362028400 -21600 0 CST}
    {2372918400 -18000 1 CDT}
    {2393478000 -21600 0 CST}
    {2404368000 -18000 1 CDT}
    {2424927600 -21600 0 CST}
    {2435817600 -18000 1 CDT}
    {2456377200 -21600 0 CST}
    {2467267200 -18000 1 CDT}
    {2487826800 -21600 0 CST}
    {2499321600 -18000 1 CDT}
    {2519881200 -21600 0 CST}
    {2530771200 -18000 1 CDT}
    {2551330800 -21600 0 CST}
    {2562220800 -18000 1 CDT}
    {2582780400 -21600 0 CST}
    {2593670400 -18000 1 CDT}
    {2614230000 -21600 0 CST}
    {2625120000 -18000 1 CDT}
    {2645679600 -21600 0 CST}
    {2656569600 -18000 1 CDT}
    {2677129200 -21600 0 CST}
    {2688624000 -18000 1 CDT}
    {2709183600 -21600 0 CST}
    {2720073600 -18000 1 CDT}
    {2740633200 -21600 0 CST}
    {2751523200 -18000 1 CDT}
    {2772082800 -21600 0 CST}
    {2782972800 -18000 1 CDT}
    {2803532400 -21600 0 CST}
    {2814422400 -18000 1 CDT}
    {2834982000 -21600 0 CST}
    {2846476800 -18000 1 CDT}
    {2867036400 -21600 0 CST}
    {2877926400 -18000 1 CDT}
    {2898486000 -21600 0 CST}
    {2909376000 -18000 1 CDT}
    {2929935600 -21600 0 CST}
    {2940825600 -18000 1 CDT}
    {2961385200 -21600 0 CST}
    {2972275200 -18000 1 CDT}
    {2992834800 -21600 0 CST}
    {3003724800 -18000 1 CDT}
    {3024284400 -21600 0 CST}
    {3035779200 -18000 1 CDT}
    {3056338800 -21600 0 CST}
    {3067228800 -18000 1 CDT}
    {3087788400 -21600 0 CST}
    {3098678400 -18000 1 CDT}
    {3119238000 -21600 0 CST}
    {3130128000 -18000 1 CDT}
    {3150687600 -21600 0 CST}
    {3161577600 -18000 1 CDT}
    {3182137200 -21600 0 CST}
    {3193027200 -18000 1 CDT}
    {3213586800 -21600 0 CST}
    {3225081600 -18000 1 CDT}
    {3245641200 -21600 0 CST}
    {3256531200 -18000 1 CDT}
    {3277090800 -21600 0 CST}
    {3287980800 -18000 1 CDT}
    {3308540400 -21600 0 CST}
    {3319430400 -18000 1 CDT}
    {3339990000 -21600 0 CST}
    {3350880000 -18000 1 CDT}
    {3371439600 -21600 0 CST}
    {3382934400 -18000 1 CDT}
    {3403494000 -21600 0 CST}
    {3414384000 -18000 1 CDT}
    {3434943600 -21600 0 CST}
    {3445833600 -18000 1 CDT}
    {3466393200 -21600 0 CST}
    {3477283200 -18000 1 CDT}
    {3497842800 -21600 0 CST}
    {3508732800 -18000 1 CDT}
    {3529292400 -21600 0 CST}
    {3540182400 -18000 1 CDT}
    {3560742000 -21600 0 CST}
    {3572236800 -18000 1 CDT}
    {3592796400 -21600 0 CST}
    {3603686400 -18000 1 CDT}
    {3624246000 -21600 0 CST}
    {3635136000 -18000 1 CDT}
    {3655695600 -21600 0 CST}
    {3666585600 -18000 1 CDT}
    {3687145200 -21600 0 CST}
    {3698035200 -18000 1 CDT}
    {3718594800 -21600 0 CST}
    {3730089600 -18000 1 CDT}
    {3750649200 -21600 0 CST}
    {3761539200 -18000 1 CDT}
    {3782098800 -21600 0 CST}
    {3792988800 -18000 1 CDT}
    {3813548400 -21600 0 CST}
    {3824438400 -18000 1 CDT}
    {3844998000 -21600 0 CST}
    {3855888000 -18000 1 CDT}
    {3876447600 -21600 0 CST}
    {3887337600 -18000 1 CDT}
    {3907897200 -21600 0 CST}
    {3919392000 -18000 1 CDT}
    {3939951600 -21600 0 CST}
    {3950841600 -18000 1 CDT}
    {3971401200 -21600 0 CST}
    {3982291200 -18000 1 CDT}
    {4002850800 -21600 0 CST}
    {4013740800 -18000 1 CDT}
    {4034300400 -21600 0 CST}
    {4045190400 -18000 1 CDT}
    {4065750000 -21600 0 CST}
    {4076640000 -18000 1 CDT}
    {4097199600 -21600 0 CST}
}

Changes to library/tzdata/America/Rankin_Inlet.

1
2
3
4
5
6
7
















8
9
10
11
12
13
14
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





-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Rankin_Inlet) {
    {-9223372036854775808 0 0 -00}
    {-410227200 -21600 0 CST}
    {-147895200 -14400 1 CDDT}
    {-131565600 -21600 0 CST}
    {73468800 -18000 1 CDT}
    {89190000 -21600 0 CST}
    {104918400 -18000 1 CDT}
    {120639600 -21600 0 CST}
    {136368000 -18000 1 CDT}
    {152089200 -21600 0 CST}
    {167817600 -18000 1 CDT}
    {183538800 -21600 0 CST}
    {199267200 -18000 1 CDT}
    {215593200 -21600 0 CST}
    {230716800 -18000 1 CDT}
    {247042800 -21600 0 CST}
    {262771200 -18000 1 CDT}
    {278492400 -21600 0 CST}
    {294220800 -18000 1 CDT}
    {309942000 -21600 0 CST}
    {325670400 -18000 1 CDT}
    {341391600 -21600 0 CST}
    {357120000 -18000 1 CDT}
    {372841200 -21600 0 CST}
    {388569600 -18000 1 CDT}
    {404895600 -21600 0 CST}
    {420019200 -18000 1 CDT}

Changes to library/tzdata/America/Recife.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47











































48
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Recife) {
    {-9223372036854775808 -8376 0 LMT}
    {-1767217224 -10800 0 -03}
    {-1206957600 -7200 1 -03}
    {-1191362400 -10800 0 -03}
    {-1175374800 -7200 1 -03}
    {-1159826400 -10800 0 -03}
    {-633819600 -7200 1 -03}
    {-622069200 -10800 0 -03}
    {-602283600 -7200 1 -03}
    {-591832800 -10800 0 -03}
    {-570747600 -7200 1 -03}
    {-560210400 -10800 0 -03}
    {-539125200 -7200 1 -03}
    {-531352800 -10800 0 -03}
    {-191365200 -7200 1 -03}
    {-184197600 -10800 0 -03}
    {-155163600 -7200 1 -03}
    {-150069600 -10800 0 -03}
    {-128898000 -7200 1 -03}
    {-121125600 -10800 0 -03}
    {-99954000 -7200 1 -03}
    {-89589600 -10800 0 -03}
    {-68418000 -7200 1 -03}
    {-57967200 -10800 0 -03}
    {499748400 -7200 1 -03}
    {511236000 -10800 0 -03}
    {530593200 -7200 1 -03}
    {540266400 -10800 0 -03}
    {562129200 -7200 1 -03}
    {571197600 -10800 0 -03}
    {592974000 -7200 1 -03}
    {602042400 -10800 0 -03}
    {624423600 -7200 1 -03}
    {634701600 -10800 0 -03}
    {653536800 -10800 0 -03}
    {938660400 -10800 0 -03}
    {938919600 -7200 1 -03}
    {951616800 -10800 0 -03}
    {970974000 -7200 1 -03}
    {971575200 -10800 0 -03}
    {1000350000 -10800 0 -03}
    {1003028400 -7200 1 -03}
    {1013911200 -10800 0 -03}
    {1033437600 -10800 0 -03}
    {-1767217224 -10800 0 -0300}
    {-1206957600 -7200 1 -0200}
    {-1191362400 -10800 0 -0300}
    {-1175374800 -7200 1 -0200}
    {-1159826400 -10800 0 -0300}
    {-633819600 -7200 1 -0200}
    {-622069200 -10800 0 -0300}
    {-602283600 -7200 1 -0200}
    {-591832800 -10800 0 -0300}
    {-570747600 -7200 1 -0200}
    {-560210400 -10800 0 -0300}
    {-539125200 -7200 1 -0200}
    {-531352800 -10800 0 -0300}
    {-191365200 -7200 1 -0200}
    {-184197600 -10800 0 -0300}
    {-155163600 -7200 1 -0200}
    {-150069600 -10800 0 -0300}
    {-128898000 -7200 1 -0200}
    {-121125600 -10800 0 -0300}
    {-99954000 -7200 1 -0200}
    {-89589600 -10800 0 -0300}
    {-68418000 -7200 1 -0200}
    {-57967200 -10800 0 -0300}
    {499748400 -7200 1 -0200}
    {511236000 -10800 0 -0300}
    {530593200 -7200 1 -0200}
    {540266400 -10800 0 -0300}
    {562129200 -7200 1 -0200}
    {571197600 -10800 0 -0300}
    {592974000 -7200 1 -0200}
    {602042400 -10800 0 -0300}
    {624423600 -7200 1 -0200}
    {634701600 -10800 0 -0300}
    {653536800 -10800 0 -0300}
    {938660400 -10800 0 -0300}
    {938919600 -7200 1 -0200}
    {951616800 -10800 0 -0300}
    {970974000 -7200 1 -0200}
    {971575200 -10800 0 -0300}
    {1000350000 -10800 0 -0300}
    {1003028400 -7200 1 -0200}
    {1013911200 -10800 0 -0300}
    {1033437600 -10800 0 -0300}
}

Changes to library/tzdata/America/Resolute.

1
2
3
4
5
6
7
















8
9
10
11
12
13
14
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





-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Resolute) {
    {-9223372036854775808 0 0 -00}
    {-704937600 -21600 0 CST}
    {-147895200 -14400 1 CDDT}
    {-131565600 -21600 0 CST}
    {73468800 -18000 1 CDT}
    {89190000 -21600 0 CST}
    {104918400 -18000 1 CDT}
    {120639600 -21600 0 CST}
    {136368000 -18000 1 CDT}
    {152089200 -21600 0 CST}
    {167817600 -18000 1 CDT}
    {183538800 -21600 0 CST}
    {199267200 -18000 1 CDT}
    {215593200 -21600 0 CST}
    {230716800 -18000 1 CDT}
    {247042800 -21600 0 CST}
    {262771200 -18000 1 CDT}
    {278492400 -21600 0 CST}
    {294220800 -18000 1 CDT}
    {309942000 -21600 0 CST}
    {325670400 -18000 1 CDT}
    {341391600 -21600 0 CST}
    {357120000 -18000 1 CDT}
    {372841200 -21600 0 CST}
    {388569600 -18000 1 CDT}
    {404895600 -21600 0 CST}
    {420019200 -18000 1 CDT}

Changes to library/tzdata/America/Rio_Branco.

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
30
31
32
33
34
35
36
































37
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
30
31
32
33
34
35
36
37




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Rio_Branco) {
    {-9223372036854775808 -16272 0 LMT}
    {-1767209328 -18000 0 -05}
    {-1206950400 -14400 1 -05}
    {-1191355200 -18000 0 -05}
    {-1175367600 -14400 1 -05}
    {-1159819200 -18000 0 -05}
    {-633812400 -14400 1 -05}
    {-622062000 -18000 0 -05}
    {-602276400 -14400 1 -05}
    {-591825600 -18000 0 -05}
    {-570740400 -14400 1 -05}
    {-560203200 -18000 0 -05}
    {-539118000 -14400 1 -05}
    {-531345600 -18000 0 -05}
    {-191358000 -14400 1 -05}
    {-184190400 -18000 0 -05}
    {-155156400 -14400 1 -05}
    {-150062400 -18000 0 -05}
    {-128890800 -14400 1 -05}
    {-121118400 -18000 0 -05}
    {-99946800 -14400 1 -05}
    {-89582400 -18000 0 -05}
    {-68410800 -14400 1 -05}
    {-57960000 -18000 0 -05}
    {499755600 -14400 1 -05}
    {511243200 -18000 0 -05}
    {530600400 -14400 1 -05}
    {540273600 -18000 0 -05}
    {562136400 -14400 1 -05}
    {571204800 -18000 0 -05}
    {590040000 -18000 0 -05}
    {1214283600 -14400 0 -04}
    {1384056000 -18000 0 -05}
    {-1767209328 -18000 0 -0500}
    {-1206950400 -14400 1 -0400}
    {-1191355200 -18000 0 -0500}
    {-1175367600 -14400 1 -0400}
    {-1159819200 -18000 0 -0500}
    {-633812400 -14400 1 -0400}
    {-622062000 -18000 0 -0500}
    {-602276400 -14400 1 -0400}
    {-591825600 -18000 0 -0500}
    {-570740400 -14400 1 -0400}
    {-560203200 -18000 0 -0500}
    {-539118000 -14400 1 -0400}
    {-531345600 -18000 0 -0500}
    {-191358000 -14400 1 -0400}
    {-184190400 -18000 0 -0500}
    {-155156400 -14400 1 -0400}
    {-150062400 -18000 0 -0500}
    {-128890800 -14400 1 -0400}
    {-121118400 -18000 0 -0500}
    {-99946800 -14400 1 -0400}
    {-89582400 -18000 0 -0500}
    {-68410800 -14400 1 -0400}
    {-57960000 -18000 0 -0500}
    {499755600 -14400 1 -0400}
    {511243200 -18000 0 -0500}
    {530600400 -14400 1 -0400}
    {540273600 -18000 0 -0500}
    {562136400 -14400 1 -0400}
    {571204800 -18000 0 -0500}
    {590040000 -18000 0 -0500}
    {1214283600 -14400 0 -0400}
    {1384056000 -18000 0 -0500}
}

Changes to library/tzdata/America/Santarem.

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
30
31
32
33
34
35































36
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
30
31
32
33
34
35
36




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Santarem) {
    {-9223372036854775808 -13128 0 LMT}
    {-1767212472 -14400 0 -04}
    {-1206954000 -10800 1 -04}
    {-1191358800 -14400 0 -04}
    {-1175371200 -10800 1 -04}
    {-1159822800 -14400 0 -04}
    {-633816000 -10800 1 -04}
    {-622065600 -14400 0 -04}
    {-602280000 -10800 1 -04}
    {-591829200 -14400 0 -04}
    {-570744000 -10800 1 -04}
    {-560206800 -14400 0 -04}
    {-539121600 -10800 1 -04}
    {-531349200 -14400 0 -04}
    {-191361600 -10800 1 -04}
    {-184194000 -14400 0 -04}
    {-155160000 -10800 1 -04}
    {-150066000 -14400 0 -04}
    {-128894400 -10800 1 -04}
    {-121122000 -14400 0 -04}
    {-99950400 -10800 1 -04}
    {-89586000 -14400 0 -04}
    {-68414400 -10800 1 -04}
    {-57963600 -14400 0 -04}
    {499752000 -10800 1 -04}
    {511239600 -14400 0 -04}
    {530596800 -10800 1 -04}
    {540270000 -14400 0 -04}
    {562132800 -10800 1 -04}
    {571201200 -14400 0 -04}
    {590036400 -14400 0 -04}
    {1214280000 -10800 0 -03}
    {-1767212472 -14400 0 -0400}
    {-1206954000 -10800 1 -0300}
    {-1191358800 -14400 0 -0400}
    {-1175371200 -10800 1 -0300}
    {-1159822800 -14400 0 -0400}
    {-633816000 -10800 1 -0300}
    {-622065600 -14400 0 -0400}
    {-602280000 -10800 1 -0300}
    {-591829200 -14400 0 -0400}
    {-570744000 -10800 1 -0300}
    {-560206800 -14400 0 -0400}
    {-539121600 -10800 1 -0300}
    {-531349200 -14400 0 -0400}
    {-191361600 -10800 1 -0300}
    {-184194000 -14400 0 -0400}
    {-155160000 -10800 1 -0300}
    {-150066000 -14400 0 -0400}
    {-128894400 -10800 1 -0300}
    {-121122000 -14400 0 -0400}
    {-99950400 -10800 1 -0300}
    {-89586000 -14400 0 -0400}
    {-68414400 -10800 1 -0300}
    {-57963600 -14400 0 -0400}
    {499752000 -10800 1 -0300}
    {511239600 -14400 0 -0400}
    {530596800 -10800 1 -0300}
    {540270000 -14400 0 -0400}
    {562132800 -10800 1 -0300}
    {571201200 -14400 0 -0400}
    {590036400 -14400 0 -0400}
    {1214280000 -10800 0 -0300}
}

Changes to library/tzdata/America/Santiago.

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
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
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
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



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Santiago) {
    {-9223372036854775808 -16966 0 LMT}
    {-2524504634 -16966 0 SMT}
    {-1892661434 -18000 0 -05}
    {-1688410800 -16966 0 SMT}
    {-1619205434 -14400 0 -04}
    {-1593806400 -16966 0 SMT}
    {-1335986234 -18000 0 -05}
    {-1335985200 -14400 1 -05}
    {-1317585600 -18000 0 -05}
    {-1304362800 -14400 1 -05}
    {-1286049600 -18000 0 -05}
    {-1272826800 -14400 1 -05}
    {-1254513600 -18000 0 -05}
    {-1241290800 -14400 1 -05}
    {-1222977600 -18000 0 -05}
    {-1209754800 -14400 1 -05}
    {-1191355200 -18000 0 -05}
    {-1178132400 -14400 0 -04}
    {-870552000 -18000 0 -05}
    {-865278000 -14400 0 -04}
    {-740520000 -10800 1 -03}
    {-736376400 -14400 0 -04}
    {-718056000 -18000 0 -05}
    {-713649600 -14400 0 -04}
    {-36619200 -10800 1 -04}
    {-23922000 -14400 0 -04}
    {-3355200 -10800 1 -04}
    {7527600 -14400 0 -04}
    {24465600 -10800 1 -04}
    {37767600 -14400 0 -04}
    {55915200 -10800 1 -04}
    {69217200 -14400 0 -04}
    {87969600 -10800 1 -04}
    {100666800 -14400 0 -04}
    {118209600 -10800 1 -04}
    {132116400 -14400 0 -04}
    {150868800 -10800 1 -04}
    {163566000 -14400 0 -04}
    {182318400 -10800 1 -04}
    {195620400 -14400 0 -04}
    {213768000 -10800 1 -04}
    {227070000 -14400 0 -04}
    {245217600 -10800 1 -04}
    {258519600 -14400 0 -04}
    {277272000 -10800 1 -04}
    {289969200 -14400 0 -04}
    {308721600 -10800 1 -04}
    {321418800 -14400 0 -04}
    {340171200 -10800 1 -04}
    {353473200 -14400 0 -04}
    {371620800 -10800 1 -04}
    {384922800 -14400 0 -04}
    {403070400 -10800 1 -04}
    {416372400 -14400 0 -04}
    {434520000 -10800 1 -04}
    {447822000 -14400 0 -04}
    {466574400 -10800 1 -04}
    {479271600 -14400 0 -04}
    {498024000 -10800 1 -04}
    {510721200 -14400 0 -04}
    {529473600 -10800 1 -04}
    {545194800 -14400 0 -04}
    {560923200 -10800 1 -04}
    {574225200 -14400 0 -04}
    {592372800 -10800 1 -04}
    {605674800 -14400 0 -04}
    {624427200 -10800 1 -04}
    {637124400 -14400 0 -04}
    {653457600 -10800 1 -04}
    {668574000 -14400 0 -04}
    {687326400 -10800 1 -04}
    {700628400 -14400 0 -04}
    {718776000 -10800 1 -04}
    {732078000 -14400 0 -04}
    {750225600 -10800 1 -04}
    {763527600 -14400 0 -04}
    {781675200 -10800 1 -04}
    {794977200 -14400 0 -04}
    {813729600 -10800 1 -04}
    {826426800 -14400 0 -04}
    {845179200 -10800 1 -04}
    {859690800 -14400 0 -04}
    {876628800 -10800 1 -04}
    {889930800 -14400 0 -04}
    {906868800 -10800 1 -04}
    {923194800 -14400 0 -04}
    {939528000 -10800 1 -04}
    {952830000 -14400 0 -04}
    {971582400 -10800 1 -04}
    {984279600 -14400 0 -04}
    {1003032000 -10800 1 -04}
    {1015729200 -14400 0 -04}
    {1034481600 -10800 1 -04}
    {1047178800 -14400 0 -04}
    {1065931200 -10800 1 -04}
    {1079233200 -14400 0 -04}
    {1097380800 -10800 1 -04}
    {1110682800 -14400 0 -04}
    {1128830400 -10800 1 -04}
    {1142132400 -14400 0 -04}
    {1160884800 -10800 1 -04}
    {1173582000 -14400 0 -04}
    {1192334400 -10800 1 -04}
    {1206846000 -14400 0 -04}
    {1223784000 -10800 1 -04}
    {1237086000 -14400 0 -04}
    {1255233600 -10800 1 -04}
    {1270350000 -14400 0 -04}
    {1286683200 -10800 1 -04}
    {1304823600 -14400 0 -04}
    {1313899200 -10800 1 -04}
    {1335668400 -14400 0 -04}
    {1346558400 -10800 1 -04}
    {1367118000 -14400 0 -04}
    {1378612800 -10800 1 -04}
    {1398567600 -14400 0 -04}
    {1410062400 -10800 1 -04}
    {1463281200 -14400 0 -04}
    {1471147200 -10800 1 -04}
    {1494730800 -14400 0 -04}
    {1502596800 -10800 1 -04}
    {1526180400 -14400 0 -04}
    {1534046400 -10800 1 -04}
    {1554606000 -14400 0 -04}
    {1567915200 -10800 1 -04}
    {1586055600 -14400 0 -04}
    {1599364800 -10800 1 -04}
    {1617505200 -14400 0 -04}
    {1630814400 -10800 1 -04}
    {1648954800 -14400 0 -04}
    {1662264000 -10800 1 -04}
    {1680404400 -14400 0 -04}
    {1693713600 -10800 1 -04}
    {1712458800 -14400 0 -04}
    {1725768000 -10800 1 -04}
    {1743908400 -14400 0 -04}
    {1757217600 -10800 1 -04}
    {1775358000 -14400 0 -04}
    {1788667200 -10800 1 -04}
    {1806807600 -14400 0 -04}
    {1820116800 -10800 1 -04}
    {1838257200 -14400 0 -04}
    {1851566400 -10800 1 -04}
    {1870311600 -14400 0 -04}
    {1883016000 -10800 1 -04}
    {1901761200 -14400 0 -04}
    {1915070400 -10800 1 -04}
    {1933210800 -14400 0 -04}
    {1946520000 -10800 1 -04}
    {1964660400 -14400 0 -04}
    {1977969600 -10800 1 -04}
    {1996110000 -14400 0 -04}
    {2009419200 -10800 1 -04}
    {2027559600 -14400 0 -04}
    {2040868800 -10800 1 -04}
    {2059614000 -14400 0 -04}
    {2072318400 -10800 1 -04}
    {2091063600 -14400 0 -04}
    {2104372800 -10800 1 -04}
    {2122513200 -14400 0 -04}
    {2135822400 -10800 1 -04}
    {2153962800 -14400 0 -04}
    {2167272000 -10800 1 -04}
    {2185412400 -14400 0 -04}
    {2198721600 -10800 1 -04}
    {2217466800 -14400 0 -04}
    {2230171200 -10800 1 -04}
    {2248916400 -14400 0 -04}
    {2262225600 -10800 1 -04}
    {2280366000 -14400 0 -04}
    {2293675200 -10800 1 -04}
    {2311815600 -14400 0 -04}
    {2325124800 -10800 1 -04}
    {2343265200 -14400 0 -04}
    {2356574400 -10800 1 -04}
    {2374714800 -14400 0 -04}
    {2388024000 -10800 1 -04}
    {2406769200 -14400 0 -04}
    {2419473600 -10800 1 -04}
    {2438218800 -14400 0 -04}
    {2451528000 -10800 1 -04}
    {2469668400 -14400 0 -04}
    {2482977600 -10800 1 -04}
    {2501118000 -14400 0 -04}
    {2514427200 -10800 1 -04}
    {2532567600 -14400 0 -04}
    {2545876800 -10800 1 -04}
    {2564017200 -14400 0 -04}
    {2577326400 -10800 1 -04}
    {2596071600 -14400 0 -04}
    {2609380800 -10800 1 -04}
    {2627521200 -14400 0 -04}
    {2640830400 -10800 1 -04}
    {2658970800 -14400 0 -04}
    {2672280000 -10800 1 -04}
    {2690420400 -14400 0 -04}
    {2703729600 -10800 1 -04}
    {2721870000 -14400 0 -04}
    {2735179200 -10800 1 -04}
    {2753924400 -14400 0 -04}
    {2766628800 -10800 1 -04}
    {2785374000 -14400 0 -04}
    {2798683200 -10800 1 -04}
    {2816823600 -14400 0 -04}
    {2830132800 -10800 1 -04}
    {2848273200 -14400 0 -04}
    {2861582400 -10800 1 -04}
    {2879722800 -14400 0 -04}
    {2893032000 -10800 1 -04}
    {2911172400 -14400 0 -04}
    {2924481600 -10800 1 -04}
    {2943226800 -14400 0 -04}
    {2955931200 -10800 1 -04}
    {2974676400 -14400 0 -04}
    {2987985600 -10800 1 -04}
    {3006126000 -14400 0 -04}
    {3019435200 -10800 1 -04}
    {3037575600 -14400 0 -04}
    {3050884800 -10800 1 -04}
    {3069025200 -14400 0 -04}
    {3082334400 -10800 1 -04}
    {3101079600 -14400 0 -04}
    {3113784000 -10800 1 -04}
    {3132529200 -14400 0 -04}
    {3145838400 -10800 1 -04}
    {3163978800 -14400 0 -04}
    {3177288000 -10800 1 -04}
    {3195428400 -14400 0 -04}
    {3208737600 -10800 1 -04}
    {3226878000 -14400 0 -04}
    {3240187200 -10800 1 -04}
    {3258327600 -14400 0 -04}
    {3271636800 -10800 1 -04}
    {3290382000 -14400 0 -04}
    {3303086400 -10800 1 -04}
    {3321831600 -14400 0 -04}
    {3335140800 -10800 1 -04}
    {3353281200 -14400 0 -04}
    {3366590400 -10800 1 -04}
    {3384730800 -14400 0 -04}
    {3398040000 -10800 1 -04}
    {3416180400 -14400 0 -04}
    {3429489600 -10800 1 -04}
    {3447630000 -14400 0 -04}
    {3460939200 -10800 1 -04}
    {3479684400 -14400 0 -04}
    {3492993600 -10800 1 -04}
    {3511134000 -14400 0 -04}
    {3524443200 -10800 1 -04}
    {3542583600 -14400 0 -04}
    {3555892800 -10800 1 -04}
    {3574033200 -14400 0 -04}
    {3587342400 -10800 1 -04}
    {3605482800 -14400 0 -04}
    {3618792000 -10800 1 -04}
    {3637537200 -14400 0 -04}
    {3650241600 -10800 1 -04}
    {3668986800 -14400 0 -04}
    {3682296000 -10800 1 -04}
    {3700436400 -14400 0 -04}
    {3713745600 -10800 1 -04}
    {3731886000 -14400 0 -04}
    {3745195200 -10800 1 -04}
    {3763335600 -14400 0 -04}
    {3776644800 -10800 1 -04}
    {3794785200 -14400 0 -04}
    {3808094400 -10800 1 -04}
    {3826839600 -14400 0 -04}
    {3839544000 -10800 1 -04}
    {3858289200 -14400 0 -04}
    {3871598400 -10800 1 -04}
    {3889738800 -14400 0 -04}
    {3903048000 -10800 1 -04}
    {3921188400 -14400 0 -04}
    {3934497600 -10800 1 -04}
    {3952638000 -14400 0 -04}
    {3965947200 -10800 1 -04}
    {3984692400 -14400 0 -04}
    {3997396800 -10800 1 -04}
    {4016142000 -14400 0 -04}
    {4029451200 -10800 1 -04}
    {4047591600 -14400 0 -04}
    {4060900800 -10800 1 -04}
    {4079041200 -14400 0 -04}
    {4092350400 -10800 1 -04}
    {-9223372036854775808 -16965 0 LMT}
    {-2524504635 -16965 0 SMT}
    {-1892661435 -18000 0 -0500}
    {-1688410800 -16965 0 SMT}
    {-1619205435 -14400 0 -0400}
    {-1593806400 -16965 0 SMT}
    {-1335986235 -18000 0 -0500}
    {-1335985200 -14400 1 -0400}
    {-1317585600 -18000 0 -0500}
    {-1304362800 -14400 1 -0400}
    {-1286049600 -18000 0 -0500}
    {-1272826800 -14400 1 -0400}
    {-1254513600 -18000 0 -0500}
    {-1241290800 -14400 1 -0400}
    {-1222977600 -18000 0 -0500}
    {-1209754800 -14400 1 -0400}
    {-1191355200 -18000 0 -0500}
    {-1178132400 -14400 0 -0400}
    {-870552000 -18000 0 -0500}
    {-865278000 -14400 0 -0400}
    {-740520000 -10800 1 -0300}
    {-736635600 -14400 1 -0400}
    {-718056000 -18000 0 -0500}
    {-713649600 -14400 0 -0400}
    {-36619200 -10800 1 -0300}
    {-23922000 -14400 0 -0400}
    {-3355200 -10800 1 -0300}
    {7527600 -14400 0 -0400}
    {24465600 -10800 1 -0300}
    {37767600 -14400 0 -0400}
    {55915200 -10800 1 -0300}
    {69217200 -14400 0 -0400}
    {87969600 -10800 1 -0300}
    {100666800 -14400 0 -0400}
    {118209600 -10800 1 -0300}
    {132116400 -14400 0 -0400}
    {150868800 -10800 1 -0300}
    {163566000 -14400 0 -0400}
    {182318400 -10800 1 -0300}
    {195620400 -14400 0 -0400}
    {213768000 -10800 1 -0300}
    {227070000 -14400 0 -0400}
    {245217600 -10800 1 -0300}
    {258519600 -14400 0 -0400}
    {277272000 -10800 1 -0300}
    {289969200 -14400 0 -0400}
    {308721600 -10800 1 -0300}
    {321418800 -14400 0 -0400}
    {340171200 -10800 1 -0300}
    {353473200 -14400 0 -0400}
    {371620800 -10800 1 -0300}
    {384922800 -14400 0 -0400}
    {403070400 -10800 1 -0300}
    {416372400 -14400 0 -0400}
    {434520000 -10800 1 -0300}
    {447822000 -14400 0 -0400}
    {466574400 -10800 1 -0300}
    {479271600 -14400 0 -0400}
    {498024000 -10800 1 -0300}
    {510721200 -14400 0 -0400}
    {529473600 -10800 1 -0300}
    {545194800 -14400 0 -0400}
    {560923200 -10800 1 -0300}
    {574225200 -14400 0 -0400}
    {592372800 -10800 1 -0300}
    {605674800 -14400 0 -0400}
    {624427200 -10800 1 -0300}
    {637124400 -14400 0 -0400}
    {653457600 -10800 1 -0300}
    {668574000 -14400 0 -0400}
    {687326400 -10800 1 -0300}
    {700628400 -14400 0 -0400}
    {718776000 -10800 1 -0300}
    {732078000 -14400 0 -0400}
    {750225600 -10800 1 -0300}
    {763527600 -14400 0 -0400}
    {781675200 -10800 1 -0300}
    {794977200 -14400 0 -0400}
    {813729600 -10800 1 -0300}
    {826426800 -14400 0 -0400}
    {845179200 -10800 1 -0300}
    {859690800 -14400 0 -0400}
    {876628800 -10800 1 -0300}
    {889930800 -14400 0 -0400}
    {906868800 -10800 1 -0300}
    {923194800 -14400 0 -0400}
    {939528000 -10800 1 -0300}
    {952830000 -14400 0 -0400}
    {971582400 -10800 1 -0300}
    {984279600 -14400 0 -0400}
    {1003032000 -10800 1 -0300}
    {1015729200 -14400 0 -0400}
    {1034481600 -10800 1 -0300}
    {1047178800 -14400 0 -0400}
    {1065931200 -10800 1 -0300}
    {1079233200 -14400 0 -0400}
    {1097380800 -10800 1 -0300}
    {1110682800 -14400 0 -0400}
    {1128830400 -10800 1 -0300}
    {1142132400 -14400 0 -0400}
    {1160884800 -10800 1 -0300}
    {1173582000 -14400 0 -0400}
    {1192334400 -10800 1 -0300}
    {1206846000 -14400 0 -0400}
    {1223784000 -10800 1 -0300}
    {1237086000 -14400 0 -0400}
    {1255233600 -10800 1 -0300}
    {1270350000 -14400 0 -0400}
    {1286683200 -10800 1 -0300}
    {1304823600 -14400 0 -0400}
    {1313899200 -10800 1 -0300}
    {1335668400 -14400 0 -0400}
    {1346558400 -10800 1 -0300}
    {1367118000 -14400 0 -0400}
    {1378612800 -10800 1 -0300}
    {1398567600 -14400 0 -0400}
    {1410062400 -10800 1 -0300}
    {1463281200 -14400 0 -0400}
    {1471147200 -10800 1 -0300}
    {1494730800 -14400 0 -0400}
    {1502596800 -10800 1 -0300}
    {1526180400 -14400 0 -0400}
    {1534046400 -10800 1 -0300}
    {1554606000 -14400 0 -0400}
    {1567915200 -10800 1 -0300}
    {1586055600 -14400 0 -0400}
    {1599364800 -10800 1 -0300}
    {1617505200 -14400 0 -0400}
    {1630814400 -10800 1 -0300}
    {1648954800 -14400 0 -0400}
    {1662868800 -10800 1 -0300}
    {1680404400 -14400 0 -0400}
    {1693713600 -10800 1 -0300}
    {1712458800 -14400 0 -0400}
    {1725768000 -10800 1 -0300}
    {1743908400 -14400 0 -0400}
    {1757217600 -10800 1 -0300}
    {1775358000 -14400 0 -0400}
    {1788667200 -10800 1 -0300}
    {1806807600 -14400 0 -0400}
    {1820116800 -10800 1 -0300}
    {1838257200 -14400 0 -0400}
    {1851566400 -10800 1 -0300}
    {1870311600 -14400 0 -0400}
    {1883016000 -10800 1 -0300}
    {1901761200 -14400 0 -0400}
    {1915070400 -10800 1 -0300}
    {1933210800 -14400 0 -0400}
    {1946520000 -10800 1 -0300}
    {1964660400 -14400 0 -0400}
    {1977969600 -10800 1 -0300}
    {1996110000 -14400 0 -0400}
    {2009419200 -10800 1 -0300}
    {2027559600 -14400 0 -0400}
    {2040868800 -10800 1 -0300}
    {2059614000 -14400 0 -0400}
    {2072318400 -10800 1 -0300}
    {2091063600 -14400 0 -0400}
    {2104372800 -10800 1 -0300}
    {2122513200 -14400 0 -0400}
    {2135822400 -10800 1 -0300}
    {2153962800 -14400 0 -0400}
    {2167272000 -10800 1 -0300}
    {2185412400 -14400 0 -0400}
    {2198721600 -10800 1 -0300}
    {2217466800 -14400 0 -0400}
    {2230171200 -10800 1 -0300}
    {2248916400 -14400 0 -0400}
    {2262225600 -10800 1 -0300}
    {2280366000 -14400 0 -0400}
    {2293675200 -10800 1 -0300}
    {2311815600 -14400 0 -0400}
    {2325124800 -10800 1 -0300}
    {2343265200 -14400 0 -0400}
    {2356574400 -10800 1 -0300}
    {2374714800 -14400 0 -0400}
    {2388024000 -10800 1 -0300}
    {2406769200 -14400 0 -0400}
    {2419473600 -10800 1 -0300}
    {2438218800 -14400 0 -0400}
    {2451528000 -10800 1 -0300}
    {2469668400 -14400 0 -0400}
    {2482977600 -10800 1 -0300}
    {2501118000 -14400 0 -0400}
    {2514427200 -10800 1 -0300}
    {2532567600 -14400 0 -0400}
    {2545876800 -10800 1 -0300}
    {2564017200 -14400 0 -0400}
    {2577326400 -10800 1 -0300}
    {2596071600 -14400 0 -0400}
    {2609380800 -10800 1 -0300}
    {2627521200 -14400 0 -0400}
    {2640830400 -10800 1 -0300}
    {2658970800 -14400 0 -0400}
    {2672280000 -10800 1 -0300}
    {2690420400 -14400 0 -0400}
    {2703729600 -10800 1 -0300}
    {2721870000 -14400 0 -0400}
    {2735179200 -10800 1 -0300}
    {2753924400 -14400 0 -0400}
    {2766628800 -10800 1 -0300}
    {2785374000 -14400 0 -0400}
    {2798683200 -10800 1 -0300}
    {2816823600 -14400 0 -0400}
    {2830132800 -10800 1 -0300}
    {2848273200 -14400 0 -0400}
    {2861582400 -10800 1 -0300}
    {2879722800 -14400 0 -0400}
    {2893032000 -10800 1 -0300}
    {2911172400 -14400 0 -0400}
    {2924481600 -10800 1 -0300}
    {2943226800 -14400 0 -0400}
    {2955931200 -10800 1 -0300}
    {2974676400 -14400 0 -0400}
    {2987985600 -10800 1 -0300}
    {3006126000 -14400 0 -0400}
    {3019435200 -10800 1 -0300}
    {3037575600 -14400 0 -0400}
    {3050884800 -10800 1 -0300}
    {3069025200 -14400 0 -0400}
    {3082334400 -10800 1 -0300}
    {3101079600 -14400 0 -0400}
    {3113784000 -10800 1 -0300}
    {3132529200 -14400 0 -0400}
    {3145838400 -10800 1 -0300}
    {3163978800 -14400 0 -0400}
    {3177288000 -10800 1 -0300}
    {3195428400 -14400 0 -0400}
    {3208737600 -10800 1 -0300}
    {3226878000 -14400 0 -0400}
    {3240187200 -10800 1 -0300}
    {3258327600 -14400 0 -0400}
    {3271636800 -10800 1 -0300}
    {3290382000 -14400 0 -0400}
    {3303086400 -10800 1 -0300}
    {3321831600 -14400 0 -0400}
    {3335140800 -10800 1 -0300}
    {3353281200 -14400 0 -0400}
    {3366590400 -10800 1 -0300}
    {3384730800 -14400 0 -0400}
    {3398040000 -10800 1 -0300}
    {3416180400 -14400 0 -0400}
    {3429489600 -10800 1 -0300}
    {3447630000 -14400 0 -0400}
    {3460939200 -10800 1 -0300}
    {3479684400 -14400 0 -0400}
    {3492993600 -10800 1 -0300}
    {3511134000 -14400 0 -0400}
    {3524443200 -10800 1 -0300}
    {3542583600 -14400 0 -0400}
    {3555892800 -10800 1 -0300}
    {3574033200 -14400 0 -0400}
    {3587342400 -10800 1 -0300}
    {3605482800 -14400 0 -0400}
    {3618792000 -10800 1 -0300}
    {3637537200 -14400 0 -0400}
    {3650241600 -10800 1 -0300}
    {3668986800 -14400 0 -0400}
    {3682296000 -10800 1 -0300}
    {3700436400 -14400 0 -0400}
    {3713745600 -10800 1 -0300}
    {3731886000 -14400 0 -0400}
    {3745195200 -10800 1 -0300}
    {3763335600 -14400 0 -0400}
    {3776644800 -10800 1 -0300}
    {3794785200 -14400 0 -0400}
    {3808094400 -10800 1 -0300}
    {3826839600 -14400 0 -0400}
    {3839544000 -10800 1 -0300}
    {3858289200 -14400 0 -0400}
    {3871598400 -10800 1 -0300}
    {3889738800 -14400 0 -0400}
    {3903048000 -10800 1 -0300}
    {3921188400 -14400 0 -0400}
    {3934497600 -10800 1 -0300}
    {3952638000 -14400 0 -0400}
    {3965947200 -10800 1 -0300}
    {3984692400 -14400 0 -0400}
    {3997396800 -10800 1 -0300}
    {4016142000 -14400 0 -0400}
    {4029451200 -10800 1 -0300}
    {4047591600 -14400 0 -0400}
    {4060900800 -10800 1 -0300}
    {4079041200 -14400 0 -0400}
    {4092350400 -10800 1 -0300}
}

Changes to library/tzdata/America/Sao_Paulo.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Sao_Paulo) {
    {-9223372036854775808 -11188 0 LMT}
    {-1767214412 -10800 0 -03}
    {-1206957600 -7200 1 -03}
    {-1191362400 -10800 0 -03}
    {-1175374800 -7200 1 -03}
    {-1159826400 -10800 0 -03}
    {-633819600 -7200 1 -03}
    {-622069200 -10800 0 -03}
    {-602283600 -7200 1 -03}
    {-591832800 -10800 0 -03}
    {-570747600 -7200 1 -03}
    {-560210400 -10800 0 -03}
    {-539125200 -7200 1 -03}
    {-531352800 -10800 0 -03}
    {-195429600 -7200 1 -02}
    {-189381600 -7200 0 -03}
    {-184197600 -10800 0 -03}
    {-155163600 -7200 1 -03}
    {-150069600 -10800 0 -03}
    {-128898000 -7200 1 -03}
    {-121125600 -10800 0 -03}
    {-99954000 -7200 1 -03}
    {-89589600 -10800 0 -03}
    {-68418000 -7200 1 -03}
    {-57967200 -10800 0 -03}
    {499748400 -7200 1 -03}
    {511236000 -10800 0 -03}
    {530593200 -7200 1 -03}
    {540266400 -10800 0 -03}
    {562129200 -7200 1 -03}
    {571197600 -10800 0 -03}
    {592974000 -7200 1 -03}
    {602042400 -10800 0 -03}
    {624423600 -7200 1 -03}
    {634701600 -10800 0 -03}
    {656478000 -7200 1 -03}
    {666756000 -10800 0 -03}
    {687927600 -7200 1 -03}
    {697600800 -10800 0 -03}
    {719982000 -7200 1 -03}
    {728445600 -10800 0 -03}
    {750826800 -7200 1 -03}
    {761709600 -10800 0 -03}
    {782276400 -7200 1 -03}
    {793159200 -10800 0 -03}
    {813726000 -7200 1 -03}
    {824004000 -10800 0 -03}
    {844570800 -7200 1 -03}
    {856058400 -10800 0 -03}
    {876106800 -7200 1 -03}
    {888717600 -10800 0 -03}
    {908074800 -7200 1 -03}
    {919562400 -10800 0 -03}
    {938919600 -7200 1 -03}
    {951616800 -10800 0 -03}
    {970974000 -7200 1 -03}
    {982461600 -10800 0 -03}
    {1003028400 -7200 1 -03}
    {1013911200 -10800 0 -03}
    {1036292400 -7200 1 -03}
    {1045360800 -10800 0 -03}
    {1066532400 -7200 1 -03}
    {1076810400 -10800 0 -03}
    {1099364400 -7200 1 -03}
    {1108864800 -10800 0 -03}
    {1129431600 -7200 1 -03}
    {1140314400 -10800 0 -03}
    {1162695600 -7200 1 -03}
    {1172368800 -10800 0 -03}
    {1192330800 -7200 1 -03}
    {1203213600 -10800 0 -03}
    {1224385200 -7200 1 -03}
    {1234663200 -10800 0 -03}
    {1255834800 -7200 1 -03}
    {1266717600 -10800 0 -03}
    {1287284400 -7200 1 -03}
    {1298167200 -10800 0 -03}
    {1318734000 -7200 1 -03}
    {1330221600 -10800 0 -03}
    {1350788400 -7200 1 -03}
    {1361066400 -10800 0 -03}
    {1382238000 -7200 1 -03}
    {1392516000 -10800 0 -03}
    {1413687600 -7200 1 -03}
    {1424570400 -10800 0 -03}
    {1445137200 -7200 1 -03}
    {1456020000 -10800 0 -03}
    {1476586800 -7200 1 -03}
    {1487469600 -10800 0 -03}
    {1508036400 -7200 1 -03}
    {1518919200 -10800 0 -03}
    {1541300400 -7200 1 -03}
    {1550368800 -10800 0 -03}
    {-1767214412 -10800 0 -0300}
    {-1206957600 -7200 1 -0200}
    {-1191362400 -10800 0 -0300}
    {-1175374800 -7200 1 -0200}
    {-1159826400 -10800 0 -0300}
    {-633819600 -7200 1 -0200}
    {-622069200 -10800 0 -0300}
    {-602283600 -7200 1 -0200}
    {-591832800 -10800 0 -0300}
    {-570747600 -7200 1 -0200}
    {-560210400 -10800 0 -0300}
    {-539125200 -7200 1 -0200}
    {-531352800 -10800 0 -0300}
    {-195429600 -7200 1 -0200}
    {-189381600 -7200 0 -0200}
    {-184197600 -10800 0 -0300}
    {-155163600 -7200 1 -0200}
    {-150069600 -10800 0 -0300}
    {-128898000 -7200 1 -0200}
    {-121125600 -10800 0 -0300}
    {-99954000 -7200 1 -0200}
    {-89589600 -10800 0 -0300}
    {-68418000 -7200 1 -0200}
    {-57967200 -10800 0 -0300}
    {499748400 -7200 1 -0200}
    {511236000 -10800 0 -0300}
    {530593200 -7200 1 -0200}
    {540266400 -10800 0 -0300}
    {562129200 -7200 1 -0200}
    {571197600 -10800 0 -0300}
    {592974000 -7200 1 -0200}
    {602042400 -10800 0 -0300}
    {624423600 -7200 1 -0200}
    {634701600 -10800 0 -0300}
    {656478000 -7200 1 -0200}
    {666756000 -10800 0 -0300}
    {687927600 -7200 1 -0200}
    {697600800 -10800 0 -0300}
    {719982000 -7200 1 -0200}
    {728445600 -10800 0 -0300}
    {750826800 -7200 1 -0200}
    {761709600 -10800 0 -0300}
    {782276400 -7200 1 -0200}
    {793159200 -10800 0 -0300}
    {813726000 -7200 1 -0200}
    {824004000 -10800 0 -0300}
    {844570800 -7200 1 -0200}
    {856058400 -10800 0 -0300}
    {876106800 -7200 1 -0200}
    {888717600 -10800 0 -0300}
    {908074800 -7200 1 -0200}
    {919562400 -10800 0 -0300}
    {938919600 -7200 1 -0200}
    {951616800 -10800 0 -0300}
    {970974000 -7200 1 -0200}
    {982461600 -10800 0 -0300}
    {1003028400 -7200 1 -0200}
    {1013911200 -10800 0 -0300}
    {1036292400 -7200 1 -0200}
    {1045360800 -10800 0 -0300}
    {1066532400 -7200 1 -0200}
    {1076810400 -10800 0 -0300}
    {1099364400 -7200 1 -0200}
    {1108864800 -10800 0 -0300}
    {1129431600 -7200 1 -0200}
    {1140314400 -10800 0 -0300}
    {1162695600 -7200 1 -0200}
    {1172368800 -10800 0 -0300}
    {1192330800 -7200 1 -0200}
    {1203213600 -10800 0 -0300}
    {1224385200 -7200 1 -0200}
    {1234663200 -10800 0 -0300}
    {1255834800 -7200 1 -0200}
    {1266717600 -10800 0 -0300}
    {1287284400 -7200 1 -0200}
    {1298167200 -10800 0 -0300}
    {1318734000 -7200 1 -0200}
    {1330221600 -10800 0 -0300}
    {1350788400 -7200 1 -0200}
    {1361066400 -10800 0 -0300}
    {1382238000 -7200 1 -0200}
    {1392516000 -10800 0 -0300}
    {1413687600 -7200 1 -0200}
    {1424570400 -10800 0 -0300}
    {1445137200 -7200 1 -0200}
    {1456020000 -10800 0 -0300}
    {1476586800 -7200 1 -0200}
    {1487469600 -10800 0 -0300}
    {1508036400 -7200 1 -0200}
    {1518919200 -10800 0 -0300}
    {1541300400 -7200 1 -0200}
    {1550368800 -10800 0 -0300}
}

Changes to library/tzdata/America/Scoresbysund.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Scoresbysund) {
    {-9223372036854775808 -5272 0 LMT}
    {-1686090728 -7200 0 -02}
    {323841600 -3600 0 -01}
    {338961600 -7200 0 -02}
    {354679200 0 0 +00}
    {370400400 -3600 0 -01}
    {386125200 0 1 +00}
    {401850000 -3600 0 -01}
    {417574800 0 1 +00}
    {433299600 -3600 0 -01}
    {449024400 0 1 +00}
    {465354000 -3600 0 -01}
    {481078800 0 1 +00}
    {496803600 -3600 0 -01}
    {512528400 0 1 +00}
    {528253200 -3600 0 -01}
    {543978000 0 1 +00}
    {559702800 -3600 0 -01}
    {575427600 0 1 +00}
    {591152400 -3600 0 -01}
    {606877200 0 1 +00}
    {622602000 -3600 0 -01}
    {638326800 0 1 +00}
    {654656400 -3600 0 -01}
    {670381200 0 1 +00}
    {686106000 -3600 0 -01}
    {701830800 0 1 +00}
    {717555600 -3600 0 -01}
    {733280400 0 1 +00}
    {749005200 -3600 0 -01}
    {764730000 0 1 +00}
    {780454800 -3600 0 -01}
    {796179600 0 1 +00}
    {811904400 -3600 0 -01}
    {828234000 0 1 +00}
    {846378000 -3600 0 -01}
    {859683600 0 1 +00}
    {877827600 -3600 0 -01}
    {891133200 0 1 +00}
    {909277200 -3600 0 -01}
    {922582800 0 1 +00}
    {941331600 -3600 0 -01}
    {954032400 0 1 +00}
    {972781200 -3600 0 -01}
    {985482000 0 1 +00}
    {1004230800 -3600 0 -01}
    {1017536400 0 1 +00}
    {1035680400 -3600 0 -01}
    {1048986000 0 1 +00}
    {1067130000 -3600 0 -01}
    {1080435600 0 1 +00}
    {1099184400 -3600 0 -01}
    {1111885200 0 1 +00}
    {1130634000 -3600 0 -01}
    {1143334800 0 1 +00}
    {1162083600 -3600 0 -01}
    {1174784400 0 1 +00}
    {1193533200 -3600 0 -01}
    {1206838800 0 1 +00}
    {1224982800 -3600 0 -01}
    {1238288400 0 1 +00}
    {1256432400 -3600 0 -01}
    {1269738000 0 1 +00}
    {1288486800 -3600 0 -01}
    {1301187600 0 1 +00}
    {1319936400 -3600 0 -01}
    {1332637200 0 1 +00}
    {1351386000 -3600 0 -01}
    {1364691600 0 1 +00}
    {1382835600 -3600 0 -01}
    {1396141200 0 1 +00}
    {1414285200 -3600 0 -01}
    {1427590800 0 1 +00}
    {1445734800 -3600 0 -01}
    {1459040400 0 1 +00}
    {1477789200 -3600 0 -01}
    {1490490000 0 1 +00}
    {1509238800 -3600 0 -01}
    {1521939600 0 1 +00}
    {1540688400 -3600 0 -01}
    {1553994000 0 1 +00}
    {1572138000 -3600 0 -01}
    {1585443600 0 1 +00}
    {1603587600 -3600 0 -01}
    {1616893200 0 1 +00}
    {1635642000 -3600 0 -01}
    {1648342800 0 1 +00}
    {1667091600 -3600 0 -01}
    {1679792400 0 1 +00}
    {1698541200 -3600 0 -01}
    {1711846800 0 1 +00}
    {1729990800 -3600 0 -01}
    {1743296400 0 1 +00}
    {1761440400 -3600 0 -01}
    {1774746000 0 1 +00}
    {1792890000 -3600 0 -01}
    {1806195600 0 1 +00}
    {1824944400 -3600 0 -01}
    {1837645200 0 1 +00}
    {1856394000 -3600 0 -01}
    {1869094800 0 1 +00}
    {1887843600 -3600 0 -01}
    {1901149200 0 1 +00}
    {1919293200 -3600 0 -01}
    {1932598800 0 1 +00}
    {1950742800 -3600 0 -01}
    {1964048400 0 1 +00}
    {1982797200 -3600 0 -01}
    {1995498000 0 1 +00}
    {2014246800 -3600 0 -01}
    {2026947600 0 1 +00}
    {2045696400 -3600 0 -01}
    {2058397200 0 1 +00}
    {2077146000 -3600 0 -01}
    {2090451600 0 1 +00}
    {2108595600 -3600 0 -01}
    {2121901200 0 1 +00}
    {2140045200 -3600 0 -01}
    {2153350800 0 1 +00}
    {2172099600 -3600 0 -01}
    {2184800400 0 1 +00}
    {2203549200 -3600 0 -01}
    {2216250000 0 1 +00}
    {2234998800 -3600 0 -01}
    {2248304400 0 1 +00}
    {2266448400 -3600 0 -01}
    {2279754000 0 1 +00}
    {2297898000 -3600 0 -01}
    {2311203600 0 1 +00}
    {2329347600 -3600 0 -01}
    {2342653200 0 1 +00}
    {2361402000 -3600 0 -01}
    {2374102800 0 1 +00}
    {2392851600 -3600 0 -01}
    {2405552400 0 1 +00}
    {2424301200 -3600 0 -01}
    {2437606800 0 1 +00}
    {2455750800 -3600 0 -01}
    {2469056400 0 1 +00}
    {2487200400 -3600 0 -01}
    {2500506000 0 1 +00}
    {2519254800 -3600 0 -01}
    {2531955600 0 1 +00}
    {2550704400 -3600 0 -01}
    {2563405200 0 1 +00}
    {2582154000 -3600 0 -01}
    {2595459600 0 1 +00}
    {2613603600 -3600 0 -01}
    {2626909200 0 1 +00}
    {2645053200 -3600 0 -01}
    {2658358800 0 1 +00}
    {2676502800 -3600 0 -01}
    {2689808400 0 1 +00}
    {2708557200 -3600 0 -01}
    {2721258000 0 1 +00}
    {2740006800 -3600 0 -01}
    {2752707600 0 1 +00}
    {2771456400 -3600 0 -01}
    {2784762000 0 1 +00}
    {2802906000 -3600 0 -01}
    {2816211600 0 1 +00}
    {2834355600 -3600 0 -01}
    {2847661200 0 1 +00}
    {2866410000 -3600 0 -01}
    {2879110800 0 1 +00}
    {2897859600 -3600 0 -01}
    {2910560400 0 1 +00}
    {2929309200 -3600 0 -01}
    {2942010000 0 1 +00}
    {2960758800 -3600 0 -01}
    {2974064400 0 1 +00}
    {2992208400 -3600 0 -01}
    {3005514000 0 1 +00}
    {3023658000 -3600 0 -01}
    {3036963600 0 1 +00}
    {3055712400 -3600 0 -01}
    {3068413200 0 1 +00}
    {3087162000 -3600 0 -01}
    {3099862800 0 1 +00}
    {3118611600 -3600 0 -01}
    {3131917200 0 1 +00}
    {3150061200 -3600 0 -01}
    {3163366800 0 1 +00}
    {3181510800 -3600 0 -01}
    {3194816400 0 1 +00}
    {3212960400 -3600 0 -01}
    {3226266000 0 1 +00}
    {3245014800 -3600 0 -01}
    {3257715600 0 1 +00}
    {3276464400 -3600 0 -01}
    {3289165200 0 1 +00}
    {3307914000 -3600 0 -01}
    {3321219600 0 1 +00}
    {3339363600 -3600 0 -01}
    {3352669200 0 1 +00}
    {3370813200 -3600 0 -01}
    {3384118800 0 1 +00}
    {3402867600 -3600 0 -01}
    {3415568400 0 1 +00}
    {3434317200 -3600 0 -01}
    {3447018000 0 1 +00}
    {3465766800 -3600 0 -01}
    {3479072400 0 1 +00}
    {3497216400 -3600 0 -01}
    {3510522000 0 1 +00}
    {3528666000 -3600 0 -01}
    {3541971600 0 1 +00}
    {3560115600 -3600 0 -01}
    {3573421200 0 1 +00}
    {3592170000 -3600 0 -01}
    {3604870800 0 1 +00}
    {3623619600 -3600 0 -01}
    {3636320400 0 1 +00}
    {3655069200 -3600 0 -01}
    {3668374800 0 1 +00}
    {3686518800 -3600 0 -01}
    {3699824400 0 1 +00}
    {3717968400 -3600 0 -01}
    {3731274000 0 1 +00}
    {3750022800 -3600 0 -01}
    {3762723600 0 1 +00}
    {3781472400 -3600 0 -01}
    {3794173200 0 1 +00}
    {3812922000 -3600 0 -01}
    {3825622800 0 1 +00}
    {3844371600 -3600 0 -01}
    {3857677200 0 1 +00}
    {3875821200 -3600 0 -01}
    {3889126800 0 1 +00}
    {3907270800 -3600 0 -01}
    {3920576400 0 1 +00}
    {3939325200 -3600 0 -01}
    {3952026000 0 1 +00}
    {3970774800 -3600 0 -01}
    {3983475600 0 1 +00}
    {4002224400 -3600 0 -01}
    {4015530000 0 1 +00}
    {4033674000 -3600 0 -01}
    {4046979600 0 1 +00}
    {4065123600 -3600 0 -01}
    {4078429200 0 1 +00}
    {4096573200 -3600 0 -01}
    {-1686090728 -7200 0 -0200}
    {323841600 -3600 0 -0100}
    {338961600 -7200 0 -0200}
    {354679200 0 0 +0000}
    {370400400 -3600 0 -0100}
    {386125200 0 1 +0000}
    {401850000 -3600 0 -0100}
    {417574800 0 1 +0000}
    {433299600 -3600 0 -0100}
    {449024400 0 1 +0000}
    {465354000 -3600 0 -0100}
    {481078800 0 1 +0000}
    {496803600 -3600 0 -0100}
    {512528400 0 1 +0000}
    {528253200 -3600 0 -0100}
    {543978000 0 1 +0000}
    {559702800 -3600 0 -0100}
    {575427600 0 1 +0000}
    {591152400 -3600 0 -0100}
    {606877200 0 1 +0000}
    {622602000 -3600 0 -0100}
    {638326800 0 1 +0000}
    {654656400 -3600 0 -0100}
    {670381200 0 1 +0000}
    {686106000 -3600 0 -0100}
    {701830800 0 1 +0000}
    {717555600 -3600 0 -0100}
    {733280400 0 1 +0000}
    {749005200 -3600 0 -0100}
    {764730000 0 1 +0000}
    {780454800 -3600 0 -0100}
    {796179600 0 1 +0000}
    {811904400 -3600 0 -0100}
    {828234000 0 1 +0000}
    {846378000 -3600 0 -0100}
    {859683600 0 1 +0000}
    {877827600 -3600 0 -0100}
    {891133200 0 1 +0000}
    {909277200 -3600 0 -0100}
    {922582800 0 1 +0000}
    {941331600 -3600 0 -0100}
    {954032400 0 1 +0000}
    {972781200 -3600 0 -0100}
    {985482000 0 1 +0000}
    {1004230800 -3600 0 -0100}
    {1017536400 0 1 +0000}
    {1035680400 -3600 0 -0100}
    {1048986000 0 1 +0000}
    {1067130000 -3600 0 -0100}
    {1080435600 0 1 +0000}
    {1099184400 -3600 0 -0100}
    {1111885200 0 1 +0000}
    {1130634000 -3600 0 -0100}
    {1143334800 0 1 +0000}
    {1162083600 -3600 0 -0100}
    {1174784400 0 1 +0000}
    {1193533200 -3600 0 -0100}
    {1206838800 0 1 +0000}
    {1224982800 -3600 0 -0100}
    {1238288400 0 1 +0000}
    {1256432400 -3600 0 -0100}
    {1269738000 0 1 +0000}
    {1288486800 -3600 0 -0100}
    {1301187600 0 1 +0000}
    {1319936400 -3600 0 -0100}
    {1332637200 0 1 +0000}
    {1351386000 -3600 0 -0100}
    {1364691600 0 1 +0000}
    {1382835600 -3600 0 -0100}
    {1396141200 0 1 +0000}
    {1414285200 -3600 0 -0100}
    {1427590800 0 1 +0000}
    {1445734800 -3600 0 -0100}
    {1459040400 0 1 +0000}
    {1477789200 -3600 0 -0100}
    {1490490000 0 1 +0000}
    {1509238800 -3600 0 -0100}
    {1521939600 0 1 +0000}
    {1540688400 -3600 0 -0100}
    {1553994000 0 1 +0000}
    {1572138000 -3600 0 -0100}
    {1585443600 0 1 +0000}
    {1603587600 -3600 0 -0100}
    {1616893200 0 1 +0000}
    {1635642000 -3600 0 -0100}
    {1648342800 0 1 +0000}
    {1667091600 -3600 0 -0100}
    {1679792400 0 1 +0000}
    {1698541200 -3600 0 -0100}
    {1711846800 -3600 0 -0100}
    {1729990800 -7200 0 -0200}
    {1743296400 -3600 1 -0100}
    {1761440400 -7200 0 -0200}
    {1774746000 -3600 1 -0100}
    {1792890000 -7200 0 -0200}
    {1806195600 -3600 1 -0100}
    {1824944400 -7200 0 -0200}
    {1837645200 -3600 1 -0100}
    {1856394000 -7200 0 -0200}
    {1869094800 -3600 1 -0100}
    {1887843600 -7200 0 -0200}
    {1901149200 -3600 1 -0100}
    {1919293200 -7200 0 -0200}
    {1932598800 -3600 1 -0100}
    {1950742800 -7200 0 -0200}
    {1964048400 -3600 1 -0100}
    {1982797200 -7200 0 -0200}
    {1995498000 -3600 1 -0100}
    {2014246800 -7200 0 -0200}
    {2026947600 -3600 1 -0100}
    {2045696400 -7200 0 -0200}
    {2058397200 -3600 1 -0100}
    {2077146000 -7200 0 -0200}
    {2090451600 -3600 1 -0100}
    {2108595600 -7200 0 -0200}
    {2121901200 -3600 1 -0100}
    {2140045200 -7200 0 -0200}
    {2153350800 -3600 1 -0100}
    {2172099600 -7200 0 -0200}
    {2184800400 -3600 1 -0100}
    {2203549200 -7200 0 -0200}
    {2216250000 -3600 1 -0100}
    {2234998800 -7200 0 -0200}
    {2248304400 -3600 1 -0100}
    {2266448400 -7200 0 -0200}
    {2279754000 -3600 1 -0100}
    {2297898000 -7200 0 -0200}
    {2311203600 -3600 1 -0100}
    {2329347600 -7200 0 -0200}
    {2342653200 -3600 1 -0100}
    {2361402000 -7200 0 -0200}
    {2374102800 -3600 1 -0100}
    {2392851600 -7200 0 -0200}
    {2405552400 -3600 1 -0100}
    {2424301200 -7200 0 -0200}
    {2437606800 -3600 1 -0100}
    {2455750800 -7200 0 -0200}
    {2469056400 -3600 1 -0100}
    {2487200400 -7200 0 -0200}
    {2500506000 -3600 1 -0100}
    {2519254800 -7200 0 -0200}
    {2531955600 -3600 1 -0100}
    {2550704400 -7200 0 -0200}
    {2563405200 -3600 1 -0100}
    {2582154000 -7200 0 -0200}
    {2595459600 -3600 1 -0100}
    {2613603600 -7200 0 -0200}
    {2626909200 -3600 1 -0100}
    {2645053200 -7200 0 -0200}
    {2658358800 -3600 1 -0100}
    {2676502800 -7200 0 -0200}
    {2689808400 -3600 1 -0100}
    {2708557200 -7200 0 -0200}
    {2721258000 -3600 1 -0100}
    {2740006800 -7200 0 -0200}
    {2752707600 -3600 1 -0100}
    {2771456400 -7200 0 -0200}
    {2784762000 -3600 1 -0100}
    {2802906000 -7200 0 -0200}
    {2816211600 -3600 1 -0100}
    {2834355600 -7200 0 -0200}
    {2847661200 -3600 1 -0100}
    {2866410000 -7200 0 -0200}
    {2879110800 -3600 1 -0100}
    {2897859600 -7200 0 -0200}
    {2910560400 -3600 1 -0100}
    {2929309200 -7200 0 -0200}
    {2942010000 -3600 1 -0100}
    {2960758800 -7200 0 -0200}
    {2974064400 -3600 1 -0100}
    {2992208400 -7200 0 -0200}
    {3005514000 -3600 1 -0100}
    {3023658000 -7200 0 -0200}
    {3036963600 -3600 1 -0100}
    {3055712400 -7200 0 -0200}
    {3068413200 -3600 1 -0100}
    {3087162000 -7200 0 -0200}
    {3099862800 -3600 1 -0100}
    {3118611600 -7200 0 -0200}
    {3131917200 -3600 1 -0100}
    {3150061200 -7200 0 -0200}
    {3163366800 -3600 1 -0100}
    {3181510800 -7200 0 -0200}
    {3194816400 -3600 1 -0100}
    {3212960400 -7200 0 -0200}
    {3226266000 -3600 1 -0100}
    {3245014800 -7200 0 -0200}
    {3257715600 -3600 1 -0100}
    {3276464400 -7200 0 -0200}
    {3289165200 -3600 1 -0100}
    {3307914000 -7200 0 -0200}
    {3321219600 -3600 1 -0100}
    {3339363600 -7200 0 -0200}
    {3352669200 -3600 1 -0100}
    {3370813200 -7200 0 -0200}
    {3384118800 -3600 1 -0100}
    {3402867600 -7200 0 -0200}
    {3415568400 -3600 1 -0100}
    {3434317200 -7200 0 -0200}
    {3447018000 -3600 1 -0100}
    {3465766800 -7200 0 -0200}
    {3479072400 -3600 1 -0100}
    {3497216400 -7200 0 -0200}
    {3510522000 -3600 1 -0100}
    {3528666000 -7200 0 -0200}
    {3541971600 -3600 1 -0100}
    {3560115600 -7200 0 -0200}
    {3573421200 -3600 1 -0100}
    {3592170000 -7200 0 -0200}
    {3604870800 -3600 1 -0100}
    {3623619600 -7200 0 -0200}
    {3636320400 -3600 1 -0100}
    {3655069200 -7200 0 -0200}
    {3668374800 -3600 1 -0100}
    {3686518800 -7200 0 -0200}
    {3699824400 -3600 1 -0100}
    {3717968400 -7200 0 -0200}
    {3731274000 -3600 1 -0100}
    {3750022800 -7200 0 -0200}
    {3762723600 -3600 1 -0100}
    {3781472400 -7200 0 -0200}
    {3794173200 -3600 1 -0100}
    {3812922000 -7200 0 -0200}
    {3825622800 -3600 1 -0100}
    {3844371600 -7200 0 -0200}
    {3857677200 -3600 1 -0100}
    {3875821200 -7200 0 -0200}
    {3889126800 -3600 1 -0100}
    {3907270800 -7200 0 -0200}
    {3920576400 -3600 1 -0100}
    {3939325200 -7200 0 -0200}
    {3952026000 -3600 1 -0100}
    {3970774800 -7200 0 -0200}
    {3983475600 -3600 1 -0100}
    {4002224400 -7200 0 -0200}
    {4015530000 -3600 1 -0100}
    {4033674000 -7200 0 -0200}
    {4046979600 -3600 1 -0100}
    {4065123600 -7200 0 -0200}
    {4078429200 -3600 1 -0100}
    {4096573200 -7200 0 -0200}
}

Changes to library/tzdata/America/St_Barthelemy.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/St_Barthelemy) $TZData(:America/Port_of_Spain)
set TZData(:America/St_Barthelemy) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/St_Kitts.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/St_Kitts) $TZData(:America/Port_of_Spain)
set TZData(:America/St_Kitts) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/St_Lucia.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/St_Lucia) $TZData(:America/Port_of_Spain)
set TZData(:America/St_Lucia) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/St_Thomas.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/St_Thomas) $TZData(:America/Port_of_Spain)
set TZData(:America/St_Thomas) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/St_Vincent.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/St_Vincent) $TZData(:America/Port_of_Spain)
set TZData(:America/St_Vincent) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Thunder_Bay.

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
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
1
2
3


4
5














































































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Toronto)]} {
    LoadTimeZoneFile America/Toronto

set TZData(:America/Thunder_Bay) {
}
set TZData(:America/Thunder_Bay) $TZData(:America/Toronto)
    {-9223372036854775808 -21420 0 LMT}
    {-2366733780 -21600 0 CST}
    {-1893434400 -18000 0 EST}
    {-883594800 -18000 0 EST}
    {-880218000 -14400 1 EWT}
    {-769395600 -14400 1 EPT}
    {-765396000 -18000 0 EST}
    {18000 -18000 0 EST}
    {9961200 -14400 1 EDT}
    {25682400 -18000 0 EST}
    {41410800 -14400 1 EDT}
    {57736800 -18000 0 EST}
    {73465200 -14400 1 EDT}
    {89186400 -18000 0 EST}
    {94712400 -18000 0 EST}
    {126248400 -18000 0 EST}
    {136364400 -14400 1 EDT}
    {152085600 -18000 0 EST}
    {167814000 -14400 1 EDT}
    {183535200 -18000 0 EST}
    {199263600 -14400 1 EDT}
    {215589600 -18000 0 EST}
    {230713200 -14400 1 EDT}
    {247039200 -18000 0 EST}
    {262767600 -14400 1 EDT}
    {278488800 -18000 0 EST}
    {294217200 -14400 1 EDT}
    {309938400 -18000 0 EST}
    {325666800 -14400 1 EDT}
    {341388000 -18000 0 EST}
    {357116400 -14400 1 EDT}
    {372837600 -18000 0 EST}
    {388566000 -14400 1 EDT}
    {404892000 -18000 0 EST}
    {420015600 -14400 1 EDT}
    {436341600 -18000 0 EST}
    {452070000 -14400 1 EDT}
    {467791200 -18000 0 EST}
    {483519600 -14400 1 EDT}
    {499240800 -18000 0 EST}
    {514969200 -14400 1 EDT}
    {530690400 -18000 0 EST}
    {544604400 -14400 1 EDT}
    {562140000 -18000 0 EST}
    {576054000 -14400 1 EDT}
    {594194400 -18000 0 EST}
    {607503600 -14400 1 EDT}
    {625644000 -18000 0 EST}
    {638953200 -14400 1 EDT}
    {657093600 -18000 0 EST}
    {671007600 -14400 1 EDT}
    {688543200 -18000 0 EST}
    {702457200 -14400 1 EDT}
    {719992800 -18000 0 EST}
    {733906800 -14400 1 EDT}
    {752047200 -18000 0 EST}
    {765356400 -14400 1 EDT}
    {783496800 -18000 0 EST}
    {796806000 -14400 1 EDT}
    {814946400 -18000 0 EST}
    {828860400 -14400 1 EDT}
    {846396000 -18000 0 EST}
    {860310000 -14400 1 EDT}
    {877845600 -18000 0 EST}
    {891759600 -14400 1 EDT}
    {909295200 -18000 0 EST}
    {923209200 -14400 1 EDT}
    {941349600 -18000 0 EST}
    {954658800 -14400 1 EDT}
    {972799200 -18000 0 EST}
    {986108400 -14400 1 EDT}
    {1004248800 -18000 0 EST}
    {1018162800 -14400 1 EDT}
    {1035698400 -18000 0 EST}
    {1049612400 -14400 1 EDT}
    {1067148000 -18000 0 EST}
    {1081062000 -14400 1 EDT}
    {1099202400 -18000 0 EST}
    {1112511600 -14400 1 EDT}
    {1130652000 -18000 0 EST}
    {1143961200 -14400 1 EDT}
    {1162101600 -18000 0 EST}
    {1173596400 -14400 1 EDT}
    {1194156000 -18000 0 EST}
    {1205046000 -14400 1 EDT}
    {1225605600 -18000 0 EST}
    {1236495600 -14400 1 EDT}
    {1257055200 -18000 0 EST}
    {1268550000 -14400 1 EDT}
    {1289109600 -18000 0 EST}
    {1299999600 -14400 1 EDT}
    {1320559200 -18000 0 EST}
    {1331449200 -14400 1 EDT}
    {1352008800 -18000 0 EST}
    {1362898800 -14400 1 EDT}
    {1383458400 -18000 0 EST}
    {1394348400 -14400 1 EDT}
    {1414908000 -18000 0 EST}
    {1425798000 -14400 1 EDT}
    {1446357600 -18000 0 EST}
    {1457852400 -14400 1 EDT}
    {1478412000 -18000 0 EST}
    {1489302000 -14400 1 EDT}
    {1509861600 -18000 0 EST}
    {1520751600 -14400 1 EDT}
    {1541311200 -18000 0 EST}
    {1552201200 -14400 1 EDT}
    {1572760800 -18000 0 EST}
    {1583650800 -14400 1 EDT}
    {1604210400 -18000 0 EST}
    {1615705200 -14400 1 EDT}
    {1636264800 -18000 0 EST}
    {1647154800 -14400 1 EDT}
    {1667714400 -18000 0 EST}
    {1678604400 -14400 1 EDT}
    {1699164000 -18000 0 EST}
    {1710054000 -14400 1 EDT}
    {1730613600 -18000 0 EST}
    {1741503600 -14400 1 EDT}
    {1762063200 -18000 0 EST}
    {1772953200 -14400 1 EDT}
    {1793512800 -18000 0 EST}
    {1805007600 -14400 1 EDT}
    {1825567200 -18000 0 EST}
    {1836457200 -14400 1 EDT}
    {1857016800 -18000 0 EST}
    {1867906800 -14400 1 EDT}
    {1888466400 -18000 0 EST}
    {1899356400 -14400 1 EDT}
    {1919916000 -18000 0 EST}
    {1930806000 -14400 1 EDT}
    {1951365600 -18000 0 EST}
    {1962860400 -14400 1 EDT}
    {1983420000 -18000 0 EST}
    {1994310000 -14400 1 EDT}
    {2014869600 -18000 0 EST}
    {2025759600 -14400 1 EDT}
    {2046319200 -18000 0 EST}
    {2057209200 -14400 1 EDT}
    {2077768800 -18000 0 EST}
    {2088658800 -14400 1 EDT}
    {2109218400 -18000 0 EST}
    {2120108400 -14400 1 EDT}
    {2140668000 -18000 0 EST}
    {2152162800 -14400 1 EDT}
    {2172722400 -18000 0 EST}
    {2183612400 -14400 1 EDT}
    {2204172000 -18000 0 EST}
    {2215062000 -14400 1 EDT}
    {2235621600 -18000 0 EST}
    {2246511600 -14400 1 EDT}
    {2267071200 -18000 0 EST}
    {2277961200 -14400 1 EDT}
    {2298520800 -18000 0 EST}
    {2309410800 -14400 1 EDT}
    {2329970400 -18000 0 EST}
    {2341465200 -14400 1 EDT}
    {2362024800 -18000 0 EST}
    {2372914800 -14400 1 EDT}
    {2393474400 -18000 0 EST}
    {2404364400 -14400 1 EDT}
    {2424924000 -18000 0 EST}
    {2435814000 -14400 1 EDT}
    {2456373600 -18000 0 EST}
    {2467263600 -14400 1 EDT}
    {2487823200 -18000 0 EST}
    {2499318000 -14400 1 EDT}
    {2519877600 -18000 0 EST}
    {2530767600 -14400 1 EDT}
    {2551327200 -18000 0 EST}
    {2562217200 -14400 1 EDT}
    {2582776800 -18000 0 EST}
    {2593666800 -14400 1 EDT}
    {2614226400 -18000 0 EST}
    {2625116400 -14400 1 EDT}
    {2645676000 -18000 0 EST}
    {2656566000 -14400 1 EDT}
    {2677125600 -18000 0 EST}
    {2688620400 -14400 1 EDT}
    {2709180000 -18000 0 EST}
    {2720070000 -14400 1 EDT}
    {2740629600 -18000 0 EST}
    {2751519600 -14400 1 EDT}
    {2772079200 -18000 0 EST}
    {2782969200 -14400 1 EDT}
    {2803528800 -18000 0 EST}
    {2814418800 -14400 1 EDT}
    {2834978400 -18000 0 EST}
    {2846473200 -14400 1 EDT}
    {2867032800 -18000 0 EST}
    {2877922800 -14400 1 EDT}
    {2898482400 -18000 0 EST}
    {2909372400 -14400 1 EDT}
    {2929932000 -18000 0 EST}
    {2940822000 -14400 1 EDT}
    {2961381600 -18000 0 EST}
    {2972271600 -14400 1 EDT}
    {2992831200 -18000 0 EST}
    {3003721200 -14400 1 EDT}
    {3024280800 -18000 0 EST}
    {3035775600 -14400 1 EDT}
    {3056335200 -18000 0 EST}
    {3067225200 -14400 1 EDT}
    {3087784800 -18000 0 EST}
    {3098674800 -14400 1 EDT}
    {3119234400 -18000 0 EST}
    {3130124400 -14400 1 EDT}
    {3150684000 -18000 0 EST}
    {3161574000 -14400 1 EDT}
    {3182133600 -18000 0 EST}
    {3193023600 -14400 1 EDT}
    {3213583200 -18000 0 EST}
    {3225078000 -14400 1 EDT}
    {3245637600 -18000 0 EST}
    {3256527600 -14400 1 EDT}
    {3277087200 -18000 0 EST}
    {3287977200 -14400 1 EDT}
    {3308536800 -18000 0 EST}
    {3319426800 -14400 1 EDT}
    {3339986400 -18000 0 EST}
    {3350876400 -14400 1 EDT}
    {3371436000 -18000 0 EST}
    {3382930800 -14400 1 EDT}
    {3403490400 -18000 0 EST}
    {3414380400 -14400 1 EDT}
    {3434940000 -18000 0 EST}
    {3445830000 -14400 1 EDT}
    {3466389600 -18000 0 EST}
    {3477279600 -14400 1 EDT}
    {3497839200 -18000 0 EST}
    {3508729200 -14400 1 EDT}
    {3529288800 -18000 0 EST}
    {3540178800 -14400 1 EDT}
    {3560738400 -18000 0 EST}
    {3572233200 -14400 1 EDT}
    {3592792800 -18000 0 EST}
    {3603682800 -14400 1 EDT}
    {3624242400 -18000 0 EST}
    {3635132400 -14400 1 EDT}
    {3655692000 -18000 0 EST}
    {3666582000 -14400 1 EDT}
    {3687141600 -18000 0 EST}
    {3698031600 -14400 1 EDT}
    {3718591200 -18000 0 EST}
    {3730086000 -14400 1 EDT}
    {3750645600 -18000 0 EST}
    {3761535600 -14400 1 EDT}
    {3782095200 -18000 0 EST}
    {3792985200 -14400 1 EDT}
    {3813544800 -18000 0 EST}
    {3824434800 -14400 1 EDT}
    {3844994400 -18000 0 EST}
    {3855884400 -14400 1 EDT}
    {3876444000 -18000 0 EST}
    {3887334000 -14400 1 EDT}
    {3907893600 -18000 0 EST}
    {3919388400 -14400 1 EDT}
    {3939948000 -18000 0 EST}
    {3950838000 -14400 1 EDT}
    {3971397600 -18000 0 EST}
    {3982287600 -14400 1 EDT}
    {4002847200 -18000 0 EST}
    {4013737200 -14400 1 EDT}
    {4034296800 -18000 0 EST}
    {4045186800 -14400 1 EDT}
    {4065746400 -18000 0 EST}
    {4076636400 -14400 1 EDT}
    {4097196000 -18000 0 EST}
}

Changes to library/tzdata/America/Tijuana.

1
2
3
4
5

6
7

8
9
10
11
12
13

14
15






16
17
18
19
20
21
22
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




-
+

-
+





-
+


+
+
+
+
+
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Tijuana) {
    {-9223372036854775808 -28084 0 LMT}
    {-1514736000 -25200 0 MST}
    {-1514739600 -25200 0 MST}
    {-1451667600 -28800 0 PST}
    {-1343062800 -25200 0 MST}
    {-1343145600 -25200 0 MST}
    {-1234803600 -28800 0 PST}
    {-1222963200 -25200 1 PDT}
    {-1207242000 -28800 0 PST}
    {-873820800 -25200 1 PWT}
    {-769395600 -25200 1 PPT}
    {-761677200 -28800 0 PST}
    {-761418000 -28800 0 PST}
    {-686073600 -25200 1 PDT}
    {-661539600 -28800 0 PST}
    {-620755200 -25200 1 PDT}
    {-608144400 -28800 0 PST}
    {-589384800 -25200 1 PDT}
    {-576082800 -28800 0 PST}
    {-557935200 -25200 1 PDT}
    {-544633200 -28800 0 PST}
    {-504892800 -28800 0 PST}
    {-495039600 -25200 1 PDT}
    {-481734000 -28800 0 PST}
    {-463590000 -25200 1 PDT}
    {-450284400 -28800 0 PST}
    {-431535600 -25200 1 PDT}
    {-418230000 -28800 0 PST}

Changes to library/tzdata/America/Toronto.

51
52
53
54
55
56
57
58
59
60
61
62
63






64
65
66
67
68
69
70
51
52
53
54
55
56
57






58
59
60
61
62
63
64
65
66
67
68
69
70







-
-
-
-
-
-
+
+
+
+
+
+







    {-936550800 -14400 1 EDT}
    {-880218000 -14400 0 EWT}
    {-769395600 -14400 1 EPT}
    {-765396000 -18000 0 EST}
    {-757364400 -18000 0 EST}
    {-747248400 -14400 1 EDT}
    {-733946400 -18000 0 EST}
    {-715806000 -14400 1 EDT}
    {-702504000 -18000 0 EST}
    {-684356400 -14400 1 EDT}
    {-671054400 -18000 0 EST}
    {-652906800 -14400 1 EDT}
    {-634161600 -18000 0 EST}
    {-715798800 -14400 1 EDT}
    {-702496800 -18000 0 EST}
    {-684349200 -14400 1 EDT}
    {-671047200 -18000 0 EST}
    {-652899600 -14400 1 EDT}
    {-634154400 -18000 0 EST}
    {-620845200 -14400 1 EDT}
    {-602704800 -18000 0 EST}
    {-589395600 -14400 1 EDT}
    {-576093600 -18000 0 EST}
    {-557946000 -14400 1 EDT}
    {-544644000 -18000 0 EST}
    {-526496400 -14400 1 EDT}

Changes to library/tzdata/America/Tortola.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Tortola) $TZData(:America/Port_of_Spain)
set TZData(:America/Tortola) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Virgin.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
if {![info exists TZData(America/Puerto_Rico)]} {
    LoadTimeZoneFile America/Puerto_Rico
}
set TZData(:America/Virgin) $TZData(:America/Port_of_Spain)
set TZData(:America/Virgin) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Whitehorse.

1
2
3
4
5
6
7
8
9
10
11
12

13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23












+


+







# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Whitehorse) {
    {-9223372036854775808 -32412 0 LMT}
    {-2188997988 -32400 0 YST}
    {-1632056400 -28800 1 YDT}
    {-1615125600 -32400 0 YST}
    {-1596978000 -28800 1 YDT}
    {-1583164800 -32400 0 YST}
    {-880203600 -28800 1 YWT}
    {-769395600 -28800 1 YPT}
    {-765381600 -32400 0 YST}
    {-157734000 -32400 0 YST}
    {-147884400 -25200 1 YDDT}
    {-131554800 -32400 0 YST}
    {-121273200 -28800 0 PST}
    {315561600 -28800 0 PST}
    {325677600 -25200 1 PDT}
    {341398800 -28800 0 PST}
    {357127200 -25200 1 PDT}
    {372848400 -28800 0 PST}
    {388576800 -25200 1 PDT}
    {404902800 -28800 0 PST}

Changes to library/tzdata/America/Yellowknife.

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
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
1
2
3


4
5


























































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Edmonton)]} {
    LoadTimeZoneFile America/Edmonton

set TZData(:America/Yellowknife) {
}
set TZData(:America/Yellowknife) $TZData(:America/Edmonton)
    {-9223372036854775808 0 0 -00}
    {-1104537600 -25200 0 MST}
    {-880210800 -21600 1 MWT}
    {-769395600 -21600 1 MPT}
    {-765388800 -25200 0 MST}
    {-147891600 -18000 1 MDDT}
    {-131562000 -25200 0 MST}
    {315558000 -25200 0 MST}
    {325674000 -21600 1 MDT}
    {341395200 -25200 0 MST}
    {357123600 -21600 1 MDT}
    {372844800 -25200 0 MST}
    {388573200 -21600 1 MDT}
    {404899200 -25200 0 MST}
    {420022800 -21600 1 MDT}
    {436348800 -25200 0 MST}
    {452077200 -21600 1 MDT}
    {467798400 -25200 0 MST}
    {483526800 -21600 1 MDT}
    {499248000 -25200 0 MST}
    {514976400 -21600 1 MDT}
    {530697600 -25200 0 MST}
    {544611600 -21600 1 MDT}
    {562147200 -25200 0 MST}
    {576061200 -21600 1 MDT}
    {594201600 -25200 0 MST}
    {607510800 -21600 1 MDT}
    {625651200 -25200 0 MST}
    {638960400 -21600 1 MDT}
    {657100800 -25200 0 MST}
    {671014800 -21600 1 MDT}
    {688550400 -25200 0 MST}
    {702464400 -21600 1 MDT}
    {720000000 -25200 0 MST}
    {733914000 -21600 1 MDT}
    {752054400 -25200 0 MST}
    {765363600 -21600 1 MDT}
    {783504000 -25200 0 MST}
    {796813200 -21600 1 MDT}
    {814953600 -25200 0 MST}
    {828867600 -21600 1 MDT}
    {846403200 -25200 0 MST}
    {860317200 -21600 1 MDT}
    {877852800 -25200 0 MST}
    {891766800 -21600 1 MDT}
    {909302400 -25200 0 MST}
    {923216400 -21600 1 MDT}
    {941356800 -25200 0 MST}
    {954666000 -21600 1 MDT}
    {972806400 -25200 0 MST}
    {986115600 -21600 1 MDT}
    {1004256000 -25200 0 MST}
    {1018170000 -21600 1 MDT}
    {1035705600 -25200 0 MST}
    {1049619600 -21600 1 MDT}
    {1067155200 -25200 0 MST}
    {1081069200 -21600 1 MDT}
    {1099209600 -25200 0 MST}
    {1112518800 -21600 1 MDT}
    {1130659200 -25200 0 MST}
    {1143968400 -21600 1 MDT}
    {1162108800 -25200 0 MST}
    {1173603600 -21600 1 MDT}
    {1194163200 -25200 0 MST}
    {1205053200 -21600 1 MDT}
    {1225612800 -25200 0 MST}
    {1236502800 -21600 1 MDT}
    {1257062400 -25200 0 MST}
    {1268557200 -21600 1 MDT}
    {1289116800 -25200 0 MST}
    {1300006800 -21600 1 MDT}
    {1320566400 -25200 0 MST}
    {1331456400 -21600 1 MDT}
    {1352016000 -25200 0 MST}
    {1362906000 -21600 1 MDT}
    {1383465600 -25200 0 MST}
    {1394355600 -21600 1 MDT}
    {1414915200 -25200 0 MST}
    {1425805200 -21600 1 MDT}
    {1446364800 -25200 0 MST}
    {1457859600 -21600 1 MDT}
    {1478419200 -25200 0 MST}
    {1489309200 -21600 1 MDT}
    {1509868800 -25200 0 MST}
    {1520758800 -21600 1 MDT}
    {1541318400 -25200 0 MST}
    {1552208400 -21600 1 MDT}
    {1572768000 -25200 0 MST}
    {1583658000 -21600 1 MDT}
    {1604217600 -25200 0 MST}
    {1615712400 -21600 1 MDT}
    {1636272000 -25200 0 MST}
    {1647162000 -21600 1 MDT}
    {1667721600 -25200 0 MST}
    {1678611600 -21600 1 MDT}
    {1699171200 -25200 0 MST}
    {1710061200 -21600 1 MDT}
    {1730620800 -25200 0 MST}
    {1741510800 -21600 1 MDT}
    {1762070400 -25200 0 MST}
    {1772960400 -21600 1 MDT}
    {1793520000 -25200 0 MST}
    {1805014800 -21600 1 MDT}
    {1825574400 -25200 0 MST}
    {1836464400 -21600 1 MDT}
    {1857024000 -25200 0 MST}
    {1867914000 -21600 1 MDT}
    {1888473600 -25200 0 MST}
    {1899363600 -21600 1 MDT}
    {1919923200 -25200 0 MST}
    {1930813200 -21600 1 MDT}
    {1951372800 -25200 0 MST}
    {1962867600 -21600 1 MDT}
    {1983427200 -25200 0 MST}
    {1994317200 -21600 1 MDT}
    {2014876800 -25200 0 MST}
    {2025766800 -21600 1 MDT}
    {2046326400 -25200 0 MST}
    {2057216400 -21600 1 MDT}
    {2077776000 -25200 0 MST}
    {2088666000 -21600 1 MDT}
    {2109225600 -25200 0 MST}
    {2120115600 -21600 1 MDT}
    {2140675200 -25200 0 MST}
    {2152170000 -21600 1 MDT}
    {2172729600 -25200 0 MST}
    {2183619600 -21600 1 MDT}
    {2204179200 -25200 0 MST}
    {2215069200 -21600 1 MDT}
    {2235628800 -25200 0 MST}
    {2246518800 -21600 1 MDT}
    {2267078400 -25200 0 MST}
    {2277968400 -21600 1 MDT}
    {2298528000 -25200 0 MST}
    {2309418000 -21600 1 MDT}
    {2329977600 -25200 0 MST}
    {2341472400 -21600 1 MDT}
    {2362032000 -25200 0 MST}
    {2372922000 -21600 1 MDT}
    {2393481600 -25200 0 MST}
    {2404371600 -21600 1 MDT}
    {2424931200 -25200 0 MST}
    {2435821200 -21600 1 MDT}
    {2456380800 -25200 0 MST}
    {2467270800 -21600 1 MDT}
    {2487830400 -25200 0 MST}
    {2499325200 -21600 1 MDT}
    {2519884800 -25200 0 MST}
    {2530774800 -21600 1 MDT}
    {2551334400 -25200 0 MST}
    {2562224400 -21600 1 MDT}
    {2582784000 -25200 0 MST}
    {2593674000 -21600 1 MDT}
    {2614233600 -25200 0 MST}
    {2625123600 -21600 1 MDT}
    {2645683200 -25200 0 MST}
    {2656573200 -21600 1 MDT}
    {2677132800 -25200 0 MST}
    {2688627600 -21600 1 MDT}
    {2709187200 -25200 0 MST}
    {2720077200 -21600 1 MDT}
    {2740636800 -25200 0 MST}
    {2751526800 -21600 1 MDT}
    {2772086400 -25200 0 MST}
    {2782976400 -21600 1 MDT}
    {2803536000 -25200 0 MST}
    {2814426000 -21600 1 MDT}
    {2834985600 -25200 0 MST}
    {2846480400 -21600 1 MDT}
    {2867040000 -25200 0 MST}
    {2877930000 -21600 1 MDT}
    {2898489600 -25200 0 MST}
    {2909379600 -21600 1 MDT}
    {2929939200 -25200 0 MST}
    {2940829200 -21600 1 MDT}
    {2961388800 -25200 0 MST}
    {2972278800 -21600 1 MDT}
    {2992838400 -25200 0 MST}
    {3003728400 -21600 1 MDT}
    {3024288000 -25200 0 MST}
    {3035782800 -21600 1 MDT}
    {3056342400 -25200 0 MST}
    {3067232400 -21600 1 MDT}
    {3087792000 -25200 0 MST}
    {3098682000 -21600 1 MDT}
    {3119241600 -25200 0 MST}
    {3130131600 -21600 1 MDT}
    {3150691200 -25200 0 MST}
    {3161581200 -21600 1 MDT}
    {3182140800 -25200 0 MST}
    {3193030800 -21600 1 MDT}
    {3213590400 -25200 0 MST}
    {3225085200 -21600 1 MDT}
    {3245644800 -25200 0 MST}
    {3256534800 -21600 1 MDT}
    {3277094400 -25200 0 MST}
    {3287984400 -21600 1 MDT}
    {3308544000 -25200 0 MST}
    {3319434000 -21600 1 MDT}
    {3339993600 -25200 0 MST}
    {3350883600 -21600 1 MDT}
    {3371443200 -25200 0 MST}
    {3382938000 -21600 1 MDT}
    {3403497600 -25200 0 MST}
    {3414387600 -21600 1 MDT}
    {3434947200 -25200 0 MST}
    {3445837200 -21600 1 MDT}
    {3466396800 -25200 0 MST}
    {3477286800 -21600 1 MDT}
    {3497846400 -25200 0 MST}
    {3508736400 -21600 1 MDT}
    {3529296000 -25200 0 MST}
    {3540186000 -21600 1 MDT}
    {3560745600 -25200 0 MST}
    {3572240400 -21600 1 MDT}
    {3592800000 -25200 0 MST}
    {3603690000 -21600 1 MDT}
    {3624249600 -25200 0 MST}
    {3635139600 -21600 1 MDT}
    {3655699200 -25200 0 MST}
    {3666589200 -21600 1 MDT}
    {3687148800 -25200 0 MST}
    {3698038800 -21600 1 MDT}
    {3718598400 -25200 0 MST}
    {3730093200 -21600 1 MDT}
    {3750652800 -25200 0 MST}
    {3761542800 -21600 1 MDT}
    {3782102400 -25200 0 MST}
    {3792992400 -21600 1 MDT}
    {3813552000 -25200 0 MST}
    {3824442000 -21600 1 MDT}
    {3845001600 -25200 0 MST}
    {3855891600 -21600 1 MDT}
    {3876451200 -25200 0 MST}
    {3887341200 -21600 1 MDT}
    {3907900800 -25200 0 MST}
    {3919395600 -21600 1 MDT}
    {3939955200 -25200 0 MST}
    {3950845200 -21600 1 MDT}
    {3971404800 -25200 0 MST}
    {3982294800 -21600 1 MDT}
    {4002854400 -25200 0 MST}
    {4013744400 -21600 1 MDT}
    {4034304000 -25200 0 MST}
    {4045194000 -21600 1 MDT}
    {4065753600 -25200 0 MST}
    {4076643600 -21600 1 MDT}
    {4097203200 -25200 0 MST}
}

Changes to library/tzdata/Antarctica/Casey.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

















17
1
2
3
4












5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22




-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Antarctica/Casey) {
    {-9223372036854775808 0 0 -00}
    {-31536000 28800 0 +08}
    {1255802400 39600 0 +11}
    {1267714800 28800 0 +08}
    {1319738400 39600 0 +11}
    {1329843600 28800 0 +08}
    {1477065600 39600 0 +11}
    {1520701200 28800 0 +08}
    {1538856000 39600 0 +11}
    {1552752000 28800 0 +08}
    {1570129200 39600 0 +11}
    {1583596800 28800 0 +08}
    {1601740860 39600 0 +11}
    {-31536000 28800 0 +0800}
    {1255802400 39600 0 +1100}
    {1267714800 28800 0 +0800}
    {1319738400 39600 0 +1100}
    {1329843600 28800 0 +0800}
    {1477065600 39600 0 +1100}
    {1520701200 28800 0 +0800}
    {1538856000 39600 0 +1100}
    {1552752000 28800 0 +0800}
    {1570129200 39600 0 +1100}
    {1583596800 28800 0 +0800}
    {1601740860 39600 0 +1100}
    {1615640400 28800 0 +0800}
    {1633190460 39600 0 +1100}
    {1647090000 28800 0 +0800}
    {1664640060 39600 0 +1100}
    {1678291200 28800 0 +0800}
}

Changes to library/tzdata/Antarctica/Davis.

1
2
3
4
5

6
7
8
9
10
11





12
1
2
3
4

5
6





7
8
9
10
11
12




-
+

-
-
-
-
-
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Antarctica/Davis) {
    {-9223372036854775808 0 0 -00}
    {-409190400 25200 0 +07}
    {-409190400 25200 0 +0700}
    {-163062000 0 0 -00}
    {-28857600 25200 0 +07}
    {1255806000 18000 0 +05}
    {1268251200 25200 0 +07}
    {1319742000 18000 0 +05}
    {1329854400 25200 0 +07}
    {-28857600 25200 0 +0700}
    {1255806000 18000 0 +0500}
    {1268251200 25200 0 +0700}
    {1319742000 18000 0 +0500}
    {1329854400 25200 0 +0700}
}

Changes to library/tzdata/Antarctica/DumontDUrville.

1


2
3


4
5
6
7
8
1
2
3


4
5






+
+
-
-
+
+
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Port_Moresby)]} {
    LoadTimeZoneFile Pacific/Port_Moresby

set TZData(:Antarctica/DumontDUrville) {
}
set TZData(:Antarctica/DumontDUrville) $TZData(:Pacific/Port_Moresby)
    {-9223372036854775808 0 0 -00}
    {-725846400 36000 0 +10}
    {-566992800 0 0 -00}
    {-415497600 36000 0 +10}
}

Changes to library/tzdata/Antarctica/Macquarie.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Antarctica/Macquarie) {
    {-9223372036854775808 0 0 -00}
    {-2214259200 36000 0 AEST}
    {-1680508800 39600 1 AEDT}
    {-1669892400 39600 0 AEDT}
    {-1665392400 36000 0 AEST}
    {-1665388800 36000 0 AEST}
    {-1601719200 0 0 -00}
    {-94730400 36000 0 AEST}
    {-71136000 39600 1 AEDT}
    {-55411200 36000 0 AEST}
    {-37267200 39600 1 AEDT}
    {-25776000 36000 0 AEST}
    {-5817600 39600 1 AEDT}

Changes to library/tzdata/Antarctica/Mawson.

1
2
3
4
5
6


7
1
2
3
4


5
6
7




-
-
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Antarctica/Mawson) {
    {-9223372036854775808 0 0 -00}
    {-501206400 21600 0 +06}
    {1255809600 18000 0 +05}
    {-501206400 21600 0 +0600}
    {1255809600 18000 0 +0500}
}

Changes to library/tzdata/Antarctica/Palmer.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Antarctica/Palmer) {
    {-9223372036854775808 0 0 -00}
    {-157766400 -14400 0 -04}
    {-152654400 -14400 0 -04}
    {-132955200 -10800 1 -04}
    {-121122000 -14400 0 -04}
    {-101419200 -10800 1 -04}
    {-86821200 -14400 0 -04}
    {-71092800 -10800 1 -04}
    {-54766800 -14400 0 -04}
    {-39038400 -10800 1 -04}
    {-23317200 -14400 0 -04}
    {-7588800 -10800 0 -03}
    {128142000 -7200 1 -03}
    {136605600 -10800 0 -03}
    {389070000 -14400 0 -04}
    {403070400 -10800 1 -04}
    {416372400 -14400 0 -04}
    {434520000 -10800 1 -04}
    {447822000 -14400 0 -04}
    {466574400 -10800 1 -04}
    {479271600 -14400 0 -04}
    {498024000 -10800 1 -04}
    {510721200 -14400 0 -04}
    {529473600 -10800 1 -04}
    {545194800 -14400 0 -04}
    {560923200 -10800 1 -04}
    {574225200 -14400 0 -04}
    {592372800 -10800 1 -04}
    {605674800 -14400 0 -04}
    {624427200 -10800 1 -04}
    {637124400 -14400 0 -04}
    {653457600 -10800 1 -04}
    {668574000 -14400 0 -04}
    {687326400 -10800 1 -04}
    {700628400 -14400 0 -04}
    {718776000 -10800 1 -04}
    {732078000 -14400 0 -04}
    {750225600 -10800 1 -04}
    {763527600 -14400 0 -04}
    {781675200 -10800 1 -04}
    {794977200 -14400 0 -04}
    {813729600 -10800 1 -04}
    {826426800 -14400 0 -04}
    {845179200 -10800 1 -04}
    {859690800 -14400 0 -04}
    {876628800 -10800 1 -04}
    {889930800 -14400 0 -04}
    {906868800 -10800 1 -04}
    {923194800 -14400 0 -04}
    {939528000 -10800 1 -04}
    {952830000 -14400 0 -04}
    {971582400 -10800 1 -04}
    {984279600 -14400 0 -04}
    {1003032000 -10800 1 -04}
    {1015729200 -14400 0 -04}
    {1034481600 -10800 1 -04}
    {1047178800 -14400 0 -04}
    {1065931200 -10800 1 -04}
    {1079233200 -14400 0 -04}
    {1097380800 -10800 1 -04}
    {1110682800 -14400 0 -04}
    {1128830400 -10800 1 -04}
    {1142132400 -14400 0 -04}
    {1160884800 -10800 1 -04}
    {1173582000 -14400 0 -04}
    {1192334400 -10800 1 -04}
    {1206846000 -14400 0 -04}
    {1223784000 -10800 1 -04}
    {1237086000 -14400 0 -04}
    {1255233600 -10800 1 -04}
    {1270350000 -14400 0 -04}
    {1286683200 -10800 1 -04}
    {1304823600 -14400 0 -04}
    {1313899200 -10800 1 -04}
    {1335668400 -14400 0 -04}
    {1346558400 -10800 1 -04}
    {1367118000 -14400 0 -04}
    {1378612800 -10800 1 -04}
    {1398567600 -14400 0 -04}
    {1410062400 -10800 1 -04}
    {1463281200 -14400 0 -04}
    {1471147200 -10800 1 -04}
    {1480820400 -10800 0 -03}
    {-157766400 -14400 0 -0400}
    {-152654400 -14400 0 -0400}
    {-132955200 -10800 1 -0300}
    {-121122000 -14400 0 -0400}
    {-101419200 -10800 1 -0300}
    {-86821200 -14400 0 -0400}
    {-71092800 -10800 1 -0300}
    {-54766800 -14400 0 -0400}
    {-39038400 -10800 1 -0300}
    {-23317200 -14400 0 -0400}
    {-7588800 -10800 0 -0300}
    {128142000 -7200 1 -0200}
    {136605600 -10800 0 -0300}
    {389070000 -14400 0 -0400}
    {403070400 -10800 1 -0300}
    {416372400 -14400 0 -0400}
    {434520000 -10800 1 -0300}
    {447822000 -14400 0 -0400}
    {466574400 -10800 1 -0300}
    {479271600 -14400 0 -0400}
    {498024000 -10800 1 -0300}
    {510721200 -14400 0 -0400}
    {529473600 -10800 1 -0300}
    {545194800 -14400 0 -0400}
    {560923200 -10800 1 -0300}
    {574225200 -14400 0 -0400}
    {592372800 -10800 1 -0300}
    {605674800 -14400 0 -0400}
    {624427200 -10800 1 -0300}
    {637124400 -14400 0 -0400}
    {653457600 -10800 1 -0300}
    {668574000 -14400 0 -0400}
    {687326400 -10800 1 -0300}
    {700628400 -14400 0 -0400}
    {718776000 -10800 1 -0300}
    {732078000 -14400 0 -0400}
    {750225600 -10800 1 -0300}
    {763527600 -14400 0 -0400}
    {781675200 -10800 1 -0300}
    {794977200 -14400 0 -0400}
    {813729600 -10800 1 -0300}
    {826426800 -14400 0 -0400}
    {845179200 -10800 1 -0300}
    {859690800 -14400 0 -0400}
    {876628800 -10800 1 -0300}
    {889930800 -14400 0 -0400}
    {906868800 -10800 1 -0300}
    {923194800 -14400 0 -0400}
    {939528000 -10800 1 -0300}
    {952830000 -14400 0 -0400}
    {971582400 -10800 1 -0300}
    {984279600 -14400 0 -0400}
    {1003032000 -10800 1 -0300}
    {1015729200 -14400 0 -0400}
    {1034481600 -10800 1 -0300}
    {1047178800 -14400 0 -0400}
    {1065931200 -10800 1 -0300}
    {1079233200 -14400 0 -0400}
    {1097380800 -10800 1 -0300}
    {1110682800 -14400 0 -0400}
    {1128830400 -10800 1 -0300}
    {1142132400 -14400 0 -0400}
    {1160884800 -10800 1 -0300}
    {1173582000 -14400 0 -0400}
    {1192334400 -10800 1 -0300}
    {1206846000 -14400 0 -0400}
    {1223784000 -10800 1 -0300}
    {1237086000 -14400 0 -0400}
    {1255233600 -10800 1 -0300}
    {1270350000 -14400 0 -0400}
    {1286683200 -10800 1 -0300}
    {1304823600 -14400 0 -0400}
    {1313899200 -10800 1 -0300}
    {1335668400 -14400 0 -0400}
    {1346558400 -10800 1 -0300}
    {1367118000 -14400 0 -0400}
    {1378612800 -10800 1 -0300}
    {1398567600 -14400 0 -0400}
    {1410062400 -10800 1 -0300}
    {1463281200 -14400 0 -0400}
    {1471147200 -10800 1 -0300}
    {1480820400 -10800 0 -0300}
}

Changes to library/tzdata/Antarctica/Rothera.

1
2
3
4
5

6
1
2
3
4

5
6




-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Antarctica/Rothera) {
    {-9223372036854775808 0 0 -00}
    {218246400 -10800 0 -03}
    {218246400 -10800 0 -0300}
}

Changes to library/tzdata/Antarctica/Syowa.

1


2
3


4
5
6
1
2
3


4
5




+
+
-
-
+
+
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Asia/Riyadh)]} {
    LoadTimeZoneFile Asia/Riyadh

set TZData(:Antarctica/Syowa) {
}
set TZData(:Antarctica/Syowa) $TZData(:Asia/Riyadh)
    {-9223372036854775808 0 0 -00}
    {-407808000 10800 0 +03}
}

Changes to library/tzdata/Antarctica/Vostok.

1
2
3
4
5




6
1
2
3
4

5
6
7
8
9




-
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Antarctica/Vostok) {
    {-9223372036854775808 0 0 -00}
    {-380073600 21600 0 +06}
    {-380073600 25200 0 +0700}
    {760035600 0 0 -00}
    {783648000 25200 0 +0700}
    {1702839600 18000 0 +0500}
}

Changes to library/tzdata/Arctic/Longyearbyen.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Oslo)]} {
    LoadTimeZoneFile Europe/Oslo
if {![info exists TZData(Europe/Berlin)]} {
    LoadTimeZoneFile Europe/Berlin
}
set TZData(:Arctic/Longyearbyen) $TZData(:Europe/Oslo)
set TZData(:Arctic/Longyearbyen) $TZData(:Europe/Berlin)

Changes to library/tzdata/Asia/Almaty.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Almaty) {
    {-9223372036854775808 18468 0 LMT}
    {-1441170468 18000 0 +05}
    {-1247547600 21600 0 +06}
    {354909600 25200 1 +06}
    {370717200 21600 0 +06}
    {386445600 25200 1 +06}
    {402253200 21600 0 +06}
    {417981600 25200 1 +06}
    {433789200 21600 0 +06}
    {449604000 25200 1 +06}
    {465336000 21600 0 +06}
    {481060800 25200 1 +06}
    {496785600 21600 0 +06}
    {512510400 25200 1 +06}
    {528235200 21600 0 +06}
    {543960000 25200 1 +06}
    {559684800 21600 0 +06}
    {575409600 25200 1 +06}
    {591134400 21600 0 +06}
    {606859200 25200 1 +06}
    {622584000 21600 0 +06}
    {638308800 25200 1 +06}
    {654638400 21600 0 +06}
    {670363200 18000 0 +05}
    {670366800 21600 1 +05}
    {686091600 18000 0 +05}
    {695768400 21600 0 +06}
    {701812800 25200 1 +06}
    {717537600 21600 0 +06}
    {733262400 25200 1 +06}
    {748987200 21600 0 +06}
    {764712000 25200 1 +06}
    {780436800 21600 0 +06}
    {796161600 25200 1 +06}
    {811886400 21600 0 +06}
    {828216000 25200 1 +06}
    {846360000 21600 0 +06}
    {859665600 25200 1 +06}
    {877809600 21600 0 +06}
    {891115200 25200 1 +06}
    {909259200 21600 0 +06}
    {922564800 25200 1 +06}
    {941313600 21600 0 +06}
    {954014400 25200 1 +06}
    {972763200 21600 0 +06}
    {985464000 25200 1 +06}
    {1004212800 21600 0 +06}
    {1017518400 25200 1 +06}
    {1035662400 21600 0 +06}
    {1048968000 25200 1 +06}
    {1067112000 21600 0 +06}
    {1080417600 25200 1 +06}
    {1099166400 21600 0 +06}
    {-1441170468 18000 0 +0500}
    {-1247547600 21600 0 +0600}
    {354909600 25200 1 +0700}
    {370717200 21600 0 +0600}
    {386445600 25200 1 +0700}
    {402253200 21600 0 +0600}
    {417981600 25200 1 +0700}
    {433789200 21600 0 +0600}
    {449604000 25200 1 +0700}
    {465336000 21600 0 +0600}
    {481060800 25200 1 +0700}
    {496785600 21600 0 +0600}
    {512510400 25200 1 +0700}
    {528235200 21600 0 +0600}
    {543960000 25200 1 +0700}
    {559684800 21600 0 +0600}
    {575409600 25200 1 +0700}
    {591134400 21600 0 +0600}
    {606859200 25200 1 +0700}
    {622584000 21600 0 +0600}
    {638308800 25200 1 +0700}
    {654638400 21600 0 +0600}
    {670363200 18000 0 +0500}
    {670366800 21600 1 +0600}
    {686091600 18000 0 +0500}
    {695768400 21600 0 +0600}
    {701812800 25200 1 +0700}
    {717537600 21600 0 +0600}
    {733262400 25200 1 +0700}
    {748987200 21600 0 +0600}
    {764712000 25200 1 +0700}
    {780436800 21600 0 +0600}
    {796161600 25200 1 +0700}
    {811886400 21600 0 +0600}
    {828216000 25200 1 +0700}
    {846360000 21600 0 +0600}
    {859665600 25200 1 +0700}
    {877809600 21600 0 +0600}
    {891115200 25200 1 +0700}
    {909259200 21600 0 +0600}
    {922564800 25200 1 +0700}
    {941313600 21600 0 +0600}
    {954014400 25200 1 +0700}
    {972763200 21600 0 +0600}
    {985464000 25200 1 +0700}
    {1004212800 21600 0 +0600}
    {1017518400 25200 1 +0700}
    {1035662400 21600 0 +0600}
    {1048968000 25200 1 +0700}
    {1067112000 21600 0 +0600}
    {1080417600 25200 1 +0700}
    {1099166400 21600 0 +0600}
    {1709229600 18000 0 +0500}
}

Changes to library/tzdata/Asia/Amman.

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
83
84
85
86
87
88
89


90
91


























































































































































92







-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

    {1540504800 7200 0 EET}
    {1553810400 10800 1 EEST}
    {1571954400 7200 0 EET}
    {1585260000 10800 1 EEST}
    {1604008800 7200 0 EET}
    {1616709600 10800 1 EEST}
    {1635458400 7200 0 EET}
    {1648764000 10800 1 EEST}
    {1666908000 7200 0 EET}
    {1645740000 10800 1 EEST}
    {1666908000 10800 0 +0300}
    {1680213600 10800 1 EEST}
    {1698357600 7200 0 EET}
    {1711663200 10800 1 EEST}
    {1729807200 7200 0 EET}
    {1743112800 10800 1 EEST}
    {1761861600 7200 0 EET}
    {1774562400 10800 1 EEST}
    {1793311200 7200 0 EET}
    {1806012000 10800 1 EEST}
    {1824760800 7200 0 EET}
    {1838066400 10800 1 EEST}
    {1856210400 7200 0 EET}
    {1869516000 10800 1 EEST}
    {1887660000 7200 0 EET}
    {1900965600 10800 1 EEST}
    {1919109600 7200 0 EET}
    {1932415200 10800 1 EEST}
    {1951164000 7200 0 EET}
    {1963864800 10800 1 EEST}
    {1982613600 7200 0 EET}
    {1995919200 10800 1 EEST}
    {2014063200 7200 0 EET}
    {2027368800 10800 1 EEST}
    {2045512800 7200 0 EET}
    {2058818400 10800 1 EEST}
    {2076962400 7200 0 EET}
    {2090268000 10800 1 EEST}
    {2109016800 7200 0 EET}
    {2121717600 10800 1 EEST}
    {2140466400 7200 0 EET}
    {2153167200 10800 1 EEST}
    {2171916000 7200 0 EET}
    {2185221600 10800 1 EEST}
    {2203365600 7200 0 EET}
    {2216671200 10800 1 EEST}
    {2234815200 7200 0 EET}
    {2248120800 10800 1 EEST}
    {2266264800 7200 0 EET}
    {2279570400 10800 1 EEST}
    {2298319200 7200 0 EET}
    {2311020000 10800 1 EEST}
    {2329768800 7200 0 EET}
    {2343074400 10800 1 EEST}
    {2361218400 7200 0 EET}
    {2374524000 10800 1 EEST}
    {2392668000 7200 0 EET}
    {2405973600 10800 1 EEST}
    {2424117600 7200 0 EET}
    {2437423200 10800 1 EEST}
    {2455567200 7200 0 EET}
    {2468872800 10800 1 EEST}
    {2487621600 7200 0 EET}
    {2500322400 10800 1 EEST}
    {2519071200 7200 0 EET}
    {2532376800 10800 1 EEST}
    {2550520800 7200 0 EET}
    {2563826400 10800 1 EEST}
    {2581970400 7200 0 EET}
    {2595276000 10800 1 EEST}
    {2613420000 7200 0 EET}
    {2626725600 10800 1 EEST}
    {2645474400 7200 0 EET}
    {2658175200 10800 1 EEST}
    {2676924000 7200 0 EET}
    {2689624800 10800 1 EEST}
    {2708373600 7200 0 EET}
    {2721679200 10800 1 EEST}
    {2739823200 7200 0 EET}
    {2753128800 10800 1 EEST}
    {2771272800 7200 0 EET}
    {2784578400 10800 1 EEST}
    {2802722400 7200 0 EET}
    {2816028000 10800 1 EEST}
    {2834776800 7200 0 EET}
    {2847477600 10800 1 EEST}
    {2866226400 7200 0 EET}
    {2879532000 10800 1 EEST}
    {2897676000 7200 0 EET}
    {2910981600 10800 1 EEST}
    {2929125600 7200 0 EET}
    {2942431200 10800 1 EEST}
    {2960575200 7200 0 EET}
    {2973880800 10800 1 EEST}
    {2992629600 7200 0 EET}
    {3005330400 10800 1 EEST}
    {3024079200 7200 0 EET}
    {3036780000 10800 1 EEST}
    {3055528800 7200 0 EET}
    {3068834400 10800 1 EEST}
    {3086978400 7200 0 EET}
    {3100284000 10800 1 EEST}
    {3118428000 7200 0 EET}
    {3131733600 10800 1 EEST}
    {3149877600 7200 0 EET}
    {3163183200 10800 1 EEST}
    {3181932000 7200 0 EET}
    {3194632800 10800 1 EEST}
    {3213381600 7200 0 EET}
    {3226687200 10800 1 EEST}
    {3244831200 7200 0 EET}
    {3258136800 10800 1 EEST}
    {3276280800 7200 0 EET}
    {3289586400 10800 1 EEST}
    {3307730400 7200 0 EET}
    {3321036000 10800 1 EEST}
    {3339180000 7200 0 EET}
    {3352485600 10800 1 EEST}
    {3371234400 7200 0 EET}
    {3383935200 10800 1 EEST}
    {3402684000 7200 0 EET}
    {3415989600 10800 1 EEST}
    {3434133600 7200 0 EET}
    {3447439200 10800 1 EEST}
    {3465583200 7200 0 EET}
    {3478888800 10800 1 EEST}
    {3497032800 7200 0 EET}
    {3510338400 10800 1 EEST}
    {3529087200 7200 0 EET}
    {3541788000 10800 1 EEST}
    {3560536800 7200 0 EET}
    {3573237600 10800 1 EEST}
    {3591986400 7200 0 EET}
    {3605292000 10800 1 EEST}
    {3623436000 7200 0 EET}
    {3636741600 10800 1 EEST}
    {3654885600 7200 0 EET}
    {3668191200 10800 1 EEST}
    {3686335200 7200 0 EET}
    {3699640800 10800 1 EEST}
    {3718389600 7200 0 EET}
    {3731090400 10800 1 EEST}
    {3749839200 7200 0 EET}
    {3763144800 10800 1 EEST}
    {3781288800 7200 0 EET}
    {3794594400 10800 1 EEST}
    {3812738400 7200 0 EET}
    {3826044000 10800 1 EEST}
    {3844188000 7200 0 EET}
    {3857493600 10800 1 EEST}
    {3876242400 7200 0 EET}
    {3888943200 10800 1 EEST}
    {3907692000 7200 0 EET}
    {3920392800 10800 1 EEST}
    {3939141600 7200 0 EET}
    {3952447200 10800 1 EEST}
    {3970591200 7200 0 EET}
    {3983896800 10800 1 EEST}
    {4002040800 7200 0 EET}
    {4015346400 10800 1 EEST}
    {4033490400 7200 0 EET}
    {4046796000 10800 1 EEST}
    {4065544800 7200 0 EET}
    {4078245600 10800 1 EEST}
    {4096994400 7200 0 EET}
}

Changes to library/tzdata/Asia/Anadyr.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Anadyr) {
    {-9223372036854775808 42596 0 LMT}
    {-1441194596 43200 0 +12}
    {-1247572800 46800 0 +14}
    {354884400 50400 1 +14}
    {370692000 46800 0 +13}
    {386420400 43200 0 +13}
    {386424000 46800 1 +13}
    {402231600 43200 0 +12}
    {417960000 46800 1 +13}
    {433767600 43200 0 +12}
    {449582400 46800 1 +13}
    {465314400 43200 0 +12}
    {481039200 46800 1 +13}
    {496764000 43200 0 +12}
    {512488800 46800 1 +13}
    {528213600 43200 0 +12}
    {543938400 46800 1 +13}
    {559663200 43200 0 +12}
    {575388000 46800 1 +13}
    {591112800 43200 0 +12}
    {606837600 46800 1 +13}
    {622562400 43200 0 +12}
    {638287200 46800 1 +13}
    {654616800 43200 0 +12}
    {670341600 39600 0 +12}
    {670345200 43200 1 +12}
    {686070000 39600 0 +11}
    {695746800 43200 0 +13}
    {701791200 46800 1 +13}
    {717516000 43200 0 +12}
    {733240800 46800 1 +13}
    {748965600 43200 0 +12}
    {764690400 46800 1 +13}
    {780415200 43200 0 +12}
    {796140000 46800 1 +13}
    {811864800 43200 0 +12}
    {828194400 46800 1 +13}
    {846338400 43200 0 +12}
    {859644000 46800 1 +13}
    {877788000 43200 0 +12}
    {891093600 46800 1 +13}
    {909237600 43200 0 +12}
    {922543200 46800 1 +13}
    {941292000 43200 0 +12}
    {953992800 46800 1 +13}
    {972741600 43200 0 +12}
    {985442400 46800 1 +13}
    {1004191200 43200 0 +12}
    {1017496800 46800 1 +13}
    {1035640800 43200 0 +12}
    {1048946400 46800 1 +13}
    {1067090400 43200 0 +12}
    {1080396000 46800 1 +13}
    {1099144800 43200 0 +12}
    {1111845600 46800 1 +13}
    {1130594400 43200 0 +12}
    {1143295200 46800 1 +13}
    {1162044000 43200 0 +12}
    {1174744800 46800 1 +13}
    {1193493600 43200 0 +12}
    {1206799200 46800 1 +13}
    {1224943200 43200 0 +12}
    {1238248800 46800 1 +13}
    {1256392800 43200 0 +12}
    {1269698400 39600 0 +12}
    {1269702000 43200 1 +12}
    {1288450800 39600 0 +11}
    {1301151600 43200 0 +12}
    {-1441194596 43200 0 +1200}
    {-1247572800 46800 0 +1300}
    {354884400 50400 1 +1400}
    {370692000 46800 0 +1300}
    {386420400 43200 0 +1200}
    {386424000 46800 1 +1300}
    {402231600 43200 0 +1200}
    {417960000 46800 1 +1300}
    {433767600 43200 0 +1200}
    {449582400 46800 1 +1300}
    {465314400 43200 0 +1200}
    {481039200 46800 1 +1300}
    {496764000 43200 0 +1200}
    {512488800 46800 1 +1300}
    {528213600 43200 0 +1200}
    {543938400 46800 1 +1300}
    {559663200 43200 0 +1200}
    {575388000 46800 1 +1300}
    {591112800 43200 0 +1200}
    {606837600 46800 1 +1300}
    {622562400 43200 0 +1200}
    {638287200 46800 1 +1300}
    {654616800 43200 0 +1200}
    {670341600 39600 0 +1100}
    {670345200 43200 1 +1200}
    {686070000 39600 0 +1100}
    {695746800 43200 0 +1200}
    {701791200 46800 1 +1300}
    {717516000 43200 0 +1200}
    {733240800 46800 1 +1300}
    {748965600 43200 0 +1200}
    {764690400 46800 1 +1300}
    {780415200 43200 0 +1200}
    {796140000 46800 1 +1300}
    {811864800 43200 0 +1200}
    {828194400 46800 1 +1300}
    {846338400 43200 0 +1200}
    {859644000 46800 1 +1300}
    {877788000 43200 0 +1200}
    {891093600 46800 1 +1300}
    {909237600 43200 0 +1200}
    {922543200 46800 1 +1300}
    {941292000 43200 0 +1200}
    {953992800 46800 1 +1300}
    {972741600 43200 0 +1200}
    {985442400 46800 1 +1300}
    {1004191200 43200 0 +1200}
    {1017496800 46800 1 +1300}
    {1035640800 43200 0 +1200}
    {1048946400 46800 1 +1300}
    {1067090400 43200 0 +1200}
    {1080396000 46800 1 +1300}
    {1099144800 43200 0 +1200}
    {1111845600 46800 1 +1300}
    {1130594400 43200 0 +1200}
    {1143295200 46800 1 +1300}
    {1162044000 43200 0 +1200}
    {1174744800 46800 1 +1300}
    {1193493600 43200 0 +1200}
    {1206799200 46800 1 +1300}
    {1224943200 43200 0 +1200}
    {1238248800 46800 1 +1300}
    {1256392800 43200 0 +1200}
    {1269698400 39600 0 +1100}
    {1269702000 43200 1 +1200}
    {1288450800 39600 0 +1100}
    {1301151600 43200 0 +1200}
}

Changes to library/tzdata/Asia/Aqtau.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Aqtau) {
    {-9223372036854775808 12064 0 LMT}
    {-1441164064 14400 0 +04}
    {-1247544000 18000 0 +05}
    {370724400 21600 0 +06}
    {386445600 18000 0 +05}
    {386449200 21600 1 +05}
    {402256800 18000 0 +05}
    {417985200 21600 1 +05}
    {433792800 18000 0 +05}
    {449607600 21600 1 +05}
    {465339600 18000 0 +05}
    {481064400 21600 1 +05}
    {496789200 18000 0 +05}
    {512514000 21600 1 +05}
    {528238800 18000 0 +05}
    {543963600 21600 1 +05}
    {559688400 18000 0 +05}
    {575413200 21600 1 +05}
    {591138000 18000 0 +05}
    {606862800 21600 1 +05}
    {622587600 18000 0 +05}
    {638312400 21600 1 +05}
    {654642000 18000 0 +05}
    {670366800 14400 0 +04}
    {670370400 18000 1 +04}
    {686095200 14400 0 +04}
    {695772000 18000 0 +05}
    {701816400 21600 1 +05}
    {717541200 18000 0 +05}
    {733266000 21600 1 +05}
    {748990800 18000 0 +05}
    {764715600 21600 1 +05}
    {780440400 18000 0 +04}
    {780444000 14400 0 +04}
    {796168800 18000 1 +04}
    {811893600 14400 0 +04}
    {828223200 18000 1 +04}
    {846367200 14400 0 +04}
    {859672800 18000 1 +04}
    {877816800 14400 0 +04}
    {891122400 18000 1 +04}
    {909266400 14400 0 +04}
    {922572000 18000 1 +04}
    {941320800 14400 0 +04}
    {954021600 18000 1 +04}
    {972770400 14400 0 +04}
    {985471200 18000 1 +04}
    {1004220000 14400 0 +04}
    {1017525600 18000 1 +04}
    {1035669600 14400 0 +04}
    {1048975200 18000 1 +04}
    {1067119200 14400 0 +04}
    {1080424800 18000 1 +04}
    {1099173600 18000 0 +05}
    {-1441164064 14400 0 +0400}
    {-1247544000 18000 0 +0500}
    {370724400 21600 0 +0600}
    {386445600 18000 0 +0500}
    {386449200 21600 1 +0600}
    {402256800 18000 0 +0500}
    {417985200 21600 1 +0600}
    {433792800 18000 0 +0500}
    {449607600 21600 1 +0600}
    {465339600 18000 0 +0500}
    {481064400 21600 1 +0600}
    {496789200 18000 0 +0500}
    {512514000 21600 1 +0600}
    {528238800 18000 0 +0500}
    {543963600 21600 1 +0600}
    {559688400 18000 0 +0500}
    {575413200 21600 1 +0600}
    {591138000 18000 0 +0500}
    {606862800 21600 1 +0600}
    {622587600 18000 0 +0500}
    {638312400 21600 1 +0600}
    {654642000 18000 0 +0500}
    {670366800 14400 0 +0400}
    {670370400 18000 1 +0500}
    {686095200 14400 0 +0400}
    {695772000 18000 0 +0500}
    {701816400 21600 1 +0600}
    {717541200 18000 0 +0500}
    {733266000 21600 1 +0600}
    {748990800 18000 0 +0500}
    {764715600 21600 1 +0600}
    {780440400 18000 0 +0500}
    {780444000 14400 0 +0400}
    {796168800 18000 1 +0500}
    {811893600 14400 0 +0400}
    {828223200 18000 1 +0500}
    {846367200 14400 0 +0400}
    {859672800 18000 1 +0500}
    {877816800 14400 0 +0400}
    {891122400 18000 1 +0500}
    {909266400 14400 0 +0400}
    {922572000 18000 1 +0500}
    {941320800 14400 0 +0400}
    {954021600 18000 1 +0500}
    {972770400 14400 0 +0400}
    {985471200 18000 1 +0500}
    {1004220000 14400 0 +0400}
    {1017525600 18000 1 +0500}
    {1035669600 14400 0 +0400}
    {1048975200 18000 1 +0500}
    {1067119200 14400 0 +0400}
    {1080424800 18000 1 +0500}
    {1099173600 18000 0 +0500}
}

Changes to library/tzdata/Asia/Aqtobe.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Aqtobe) {
    {-9223372036854775808 13720 0 LMT}
    {-1441165720 14400 0 +04}
    {-1247544000 18000 0 +05}
    {354913200 21600 1 +06}
    {370720800 21600 0 +06}
    {386445600 18000 0 +05}
    {386449200 21600 1 +05}
    {402256800 18000 0 +05}
    {417985200 21600 1 +05}
    {433792800 18000 0 +05}
    {449607600 21600 1 +05}
    {465339600 18000 0 +05}
    {481064400 21600 1 +05}
    {496789200 18000 0 +05}
    {512514000 21600 1 +05}
    {528238800 18000 0 +05}
    {543963600 21600 1 +05}
    {559688400 18000 0 +05}
    {575413200 21600 1 +05}
    {591138000 18000 0 +05}
    {606862800 21600 1 +05}
    {622587600 18000 0 +05}
    {638312400 21600 1 +05}
    {654642000 18000 0 +05}
    {670366800 14400 0 +04}
    {670370400 18000 1 +04}
    {686095200 14400 0 +04}
    {695772000 18000 0 +05}
    {701816400 21600 1 +05}
    {717541200 18000 0 +05}
    {733266000 21600 1 +05}
    {748990800 18000 0 +05}
    {764715600 21600 1 +05}
    {780440400 18000 0 +05}
    {796165200 21600 1 +05}
    {811890000 18000 0 +05}
    {828219600 21600 1 +05}
    {846363600 18000 0 +05}
    {859669200 21600 1 +05}
    {877813200 18000 0 +05}
    {891118800 21600 1 +05}
    {909262800 18000 0 +05}
    {922568400 21600 1 +05}
    {941317200 18000 0 +05}
    {954018000 21600 1 +05}
    {972766800 18000 0 +05}
    {985467600 21600 1 +05}
    {1004216400 18000 0 +05}
    {1017522000 21600 1 +05}
    {1035666000 18000 0 +05}
    {1048971600 21600 1 +05}
    {1067115600 18000 0 +05}
    {1080421200 21600 1 +05}
    {1099170000 18000 0 +05}
    {-1441165720 14400 0 +0400}
    {-1247544000 18000 0 +0500}
    {354913200 21600 1 +0600}
    {370720800 21600 0 +0600}
    {386445600 18000 0 +0500}
    {386449200 21600 1 +0600}
    {402256800 18000 0 +0500}
    {417985200 21600 1 +0600}
    {433792800 18000 0 +0500}
    {449607600 21600 1 +0600}
    {465339600 18000 0 +0500}
    {481064400 21600 1 +0600}
    {496789200 18000 0 +0500}
    {512514000 21600 1 +0600}
    {528238800 18000 0 +0500}
    {543963600 21600 1 +0600}
    {559688400 18000 0 +0500}
    {575413200 21600 1 +0600}
    {591138000 18000 0 +0500}
    {606862800 21600 1 +0600}
    {622587600 18000 0 +0500}
    {638312400 21600 1 +0600}
    {654642000 18000 0 +0500}
    {670366800 14400 0 +0400}
    {670370400 18000 1 +0500}
    {686095200 14400 0 +0400}
    {695772000 18000 0 +0500}
    {701816400 21600 1 +0600}
    {717541200 18000 0 +0500}
    {733266000 21600 1 +0600}
    {748990800 18000 0 +0500}
    {764715600 21600 1 +0600}
    {780440400 18000 0 +0500}
    {796165200 21600 1 +0600}
    {811890000 18000 0 +0500}
    {828219600 21600 1 +0600}
    {846363600 18000 0 +0500}
    {859669200 21600 1 +0600}
    {877813200 18000 0 +0500}
    {891118800 21600 1 +0600}
    {909262800 18000 0 +0500}
    {922568400 21600 1 +0600}
    {941317200 18000 0 +0500}
    {954018000 21600 1 +0600}
    {972766800 18000 0 +0500}
    {985467600 21600 1 +0600}
    {1004216400 18000 0 +0500}
    {1017522000 21600 1 +0600}
    {1035666000 18000 0 +0500}
    {1048971600 21600 1 +0600}
    {1067115600 18000 0 +0500}
    {1080421200 21600 1 +0600}
    {1099170000 18000 0 +0500}
}

Changes to library/tzdata/Asia/Ashgabat.

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
30


























31
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
30
31




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Ashgabat) {
    {-9223372036854775808 14012 0 LMT}
    {-1441166012 14400 0 +04}
    {-1247544000 18000 0 +05}
    {354913200 21600 1 +05}
    {370720800 18000 0 +05}
    {386449200 21600 1 +05}
    {402256800 18000 0 +05}
    {417985200 21600 1 +05}
    {433792800 18000 0 +05}
    {449607600 21600 1 +05}
    {465339600 18000 0 +05}
    {481064400 21600 1 +05}
    {496789200 18000 0 +05}
    {512514000 21600 1 +05}
    {528238800 18000 0 +05}
    {543963600 21600 1 +05}
    {559688400 18000 0 +05}
    {575413200 21600 1 +05}
    {591138000 18000 0 +05}
    {606862800 21600 1 +05}
    {622587600 18000 0 +05}
    {638312400 21600 1 +05}
    {654642000 18000 0 +05}
    {670366800 14400 0 +04}
    {670370400 18000 1 +04}
    {686095200 14400 0 +04}
    {695772000 18000 0 +05}
    {-1441166012 14400 0 +0400}
    {-1247544000 18000 0 +0500}
    {354913200 21600 1 +0600}
    {370720800 18000 0 +0500}
    {386449200 21600 1 +0600}
    {402256800 18000 0 +0500}
    {417985200 21600 1 +0600}
    {433792800 18000 0 +0500}
    {449607600 21600 1 +0600}
    {465339600 18000 0 +0500}
    {481064400 21600 1 +0600}
    {496789200 18000 0 +0500}
    {512514000 21600 1 +0600}
    {528238800 18000 0 +0500}
    {543963600 21600 1 +0600}
    {559688400 18000 0 +0500}
    {575413200 21600 1 +0600}
    {591138000 18000 0 +0500}
    {606862800 21600 1 +0600}
    {622587600 18000 0 +0500}
    {638312400 21600 1 +0600}
    {654642000 18000 0 +0500}
    {670366800 14400 0 +0400}
    {670370400 18000 1 +0500}
    {686095200 14400 0 +0400}
    {695772000 18000 0 +0500}
}

Changes to library/tzdata/Asia/Atyrau.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Atyrau) {
    {-9223372036854775808 12464 0 LMT}
    {-1441164464 10800 0 +03}
    {-1247540400 18000 0 +05}
    {370724400 21600 0 +06}
    {386445600 18000 0 +05}
    {386449200 21600 1 +05}
    {402256800 18000 0 +05}
    {417985200 21600 1 +05}
    {433792800 18000 0 +05}
    {449607600 21600 1 +05}
    {465339600 18000 0 +05}
    {481064400 21600 1 +05}
    {496789200 18000 0 +05}
    {512514000 21600 1 +05}
    {528238800 18000 0 +05}
    {543963600 21600 1 +05}
    {559688400 18000 0 +05}
    {575413200 21600 1 +05}
    {591138000 18000 0 +05}
    {606862800 21600 1 +05}
    {622587600 18000 0 +05}
    {638312400 21600 1 +05}
    {654642000 18000 0 +05}
    {670366800 14400 0 +04}
    {670370400 18000 1 +04}
    {686095200 14400 0 +04}
    {695772000 18000 0 +05}
    {701816400 21600 1 +05}
    {717541200 18000 0 +05}
    {733266000 21600 1 +05}
    {748990800 18000 0 +05}
    {764715600 21600 1 +05}
    {780440400 18000 0 +05}
    {796165200 21600 1 +05}
    {811890000 18000 0 +05}
    {828219600 21600 1 +05}
    {846363600 18000 0 +05}
    {859669200 21600 1 +05}
    {877813200 18000 0 +05}
    {891118800 21600 1 +05}
    {909262800 18000 0 +05}
    {922568400 14400 0 +04}
    {922572000 18000 1 +04}
    {941320800 14400 0 +04}
    {954021600 18000 1 +04}
    {972770400 14400 0 +04}
    {985471200 18000 1 +04}
    {1004220000 14400 0 +04}
    {1017525600 18000 1 +04}
    {1035669600 14400 0 +04}
    {1048975200 18000 1 +04}
    {1067119200 14400 0 +04}
    {1080424800 18000 1 +04}
    {1099173600 18000 0 +05}
    {-1441164464 10800 0 +0300}
    {-1247540400 18000 0 +0500}
    {370724400 21600 0 +0600}
    {386445600 18000 0 +0500}
    {386449200 21600 1 +0600}
    {402256800 18000 0 +0500}
    {417985200 21600 1 +0600}
    {433792800 18000 0 +0500}
    {449607600 21600 1 +0600}
    {465339600 18000 0 +0500}
    {481064400 21600 1 +0600}
    {496789200 18000 0 +0500}
    {512514000 21600 1 +0600}
    {528238800 18000 0 +0500}
    {543963600 21600 1 +0600}
    {559688400 18000 0 +0500}
    {575413200 21600 1 +0600}
    {591138000 18000 0 +0500}
    {606862800 21600 1 +0600}
    {622587600 18000 0 +0500}
    {638312400 21600 1 +0600}
    {654642000 18000 0 +0500}
    {670366800 14400 0 +0400}
    {670370400 18000 1 +0500}
    {686095200 14400 0 +0400}
    {695772000 18000 0 +0500}
    {701816400 21600 1 +0600}
    {717541200 18000 0 +0500}
    {733266000 21600 1 +0600}
    {748990800 18000 0 +0500}
    {764715600 21600 1 +0600}
    {780440400 18000 0 +0500}
    {796165200 21600 1 +0600}
    {811890000 18000 0 +0500}
    {828219600 21600 1 +0600}
    {846363600 18000 0 +0500}
    {859669200 21600 1 +0600}
    {877813200 18000 0 +0500}
    {891118800 21600 1 +0600}
    {909262800 18000 0 +0500}
    {922568400 14400 0 +0400}
    {922572000 18000 1 +0500}
    {941320800 14400 0 +0400}
    {954021600 18000 1 +0500}
    {972770400 14400 0 +0400}
    {985471200 18000 1 +0500}
    {1004220000 14400 0 +0400}
    {1017525600 18000 1 +0500}
    {1035669600 14400 0 +0400}
    {1048975200 18000 1 +0500}
    {1067119200 14400 0 +0400}
    {1080424800 18000 1 +0500}
    {1099173600 18000 0 +0500}
}

Changes to library/tzdata/Asia/Baghdad.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Baghdad) {
    {-9223372036854775808 10660 0 LMT}
    {-2524532260 10656 0 BMT}
    {-1641005856 10800 0 +03}
    {389048400 14400 0 +03}
    {402264000 10800 0 +03}
    {417906000 14400 1 +03}
    {433800000 10800 0 +03}
    {449614800 14400 1 +03}
    {465422400 10800 0 +03}
    {481150800 14400 1 +03}
    {496792800 10800 0 +03}
    {512517600 14400 1 +03}
    {528242400 10800 0 +03}
    {543967200 14400 1 +03}
    {559692000 10800 0 +03}
    {575416800 14400 1 +03}
    {591141600 10800 0 +03}
    {606866400 14400 1 +03}
    {622591200 10800 0 +03}
    {638316000 14400 1 +03}
    {654645600 10800 0 +03}
    {670464000 14400 1 +03}
    {686275200 10800 0 +03}
    {702086400 14400 1 +03}
    {717897600 10800 0 +03}
    {733622400 14400 1 +03}
    {749433600 10800 0 +03}
    {765158400 14400 1 +03}
    {780969600 10800 0 +03}
    {796694400 14400 1 +03}
    {812505600 10800 0 +03}
    {828316800 14400 1 +03}
    {844128000 10800 0 +03}
    {859852800 14400 1 +03}
    {875664000 10800 0 +03}
    {891388800 14400 1 +03}
    {907200000 10800 0 +03}
    {922924800 14400 1 +03}
    {938736000 10800 0 +03}
    {954547200 14400 1 +03}
    {970358400 10800 0 +03}
    {986083200 14400 1 +03}
    {1001894400 10800 0 +03}
    {1017619200 14400 1 +03}
    {1033430400 10800 0 +03}
    {1049155200 14400 1 +03}
    {1064966400 10800 0 +03}
    {1080777600 14400 1 +03}
    {1096588800 10800 0 +03}
    {1112313600 14400 1 +03}
    {1128124800 10800 0 +03}
    {1143849600 14400 1 +03}
    {1159660800 10800 0 +03}
    {1175385600 14400 1 +03}
    {1191196800 10800 0 +03}
    {-1641005856 10800 0 +0300}
    {389048400 14400 0 +0400}
    {402264000 10800 0 +0300}
    {417906000 14400 1 +0400}
    {433800000 10800 0 +0300}
    {449614800 14400 1 +0400}
    {465422400 10800 0 +0300}
    {481150800 14400 1 +0400}
    {496792800 10800 0 +0300}
    {512517600 14400 1 +0400}
    {528242400 10800 0 +0300}
    {543967200 14400 1 +0400}
    {559692000 10800 0 +0300}
    {575416800 14400 1 +0400}
    {591141600 10800 0 +0300}
    {606866400 14400 1 +0400}
    {622591200 10800 0 +0300}
    {638316000 14400 1 +0400}
    {654645600 10800 0 +0300}
    {670464000 14400 1 +0400}
    {686275200 10800 0 +0300}
    {702086400 14400 1 +0400}
    {717897600 10800 0 +0300}
    {733622400 14400 1 +0400}
    {749433600 10800 0 +0300}
    {765158400 14400 1 +0400}
    {780969600 10800 0 +0300}
    {796694400 14400 1 +0400}
    {812505600 10800 0 +0300}
    {828316800 14400 1 +0400}
    {844128000 10800 0 +0300}
    {859852800 14400 1 +0400}
    {875664000 10800 0 +0300}
    {891388800 14400 1 +0400}
    {907200000 10800 0 +0300}
    {922924800 14400 1 +0400}
    {938736000 10800 0 +0300}
    {954547200 14400 1 +0400}
    {970358400 10800 0 +0300}
    {986083200 14400 1 +0400}
    {1001894400 10800 0 +0300}
    {1017619200 14400 1 +0400}
    {1033430400 10800 0 +0300}
    {1049155200 14400 1 +0400}
    {1064966400 10800 0 +0300}
    {1080777600 14400 1 +0400}
    {1096588800 10800 0 +0300}
    {1112313600 14400 1 +0400}
    {1128124800 10800 0 +0300}
    {1143849600 14400 1 +0400}
    {1159660800 10800 0 +0300}
    {1175385600 14400 1 +0400}
    {1191196800 10800 0 +0300}
}

Changes to library/tzdata/Asia/Baku.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Baku) {
    {-9223372036854775808 11964 0 LMT}
    {-1441163964 10800 0 +03}
    {-405140400 14400 0 +04}
    {354916800 18000 1 +04}
    {370724400 14400 0 +04}
    {386452800 18000 1 +04}
    {402260400 14400 0 +04}
    {417988800 18000 1 +04}
    {433796400 14400 0 +04}
    {449611200 18000 1 +04}
    {465343200 14400 0 +04}
    {481068000 18000 1 +04}
    {496792800 14400 0 +04}
    {512517600 18000 1 +04}
    {528242400 14400 0 +04}
    {543967200 18000 1 +04}
    {559692000 14400 0 +04}
    {575416800 18000 1 +04}
    {591141600 14400 0 +04}
    {606866400 18000 1 +04}
    {622591200 14400 0 +04}
    {638316000 18000 1 +04}
    {654645600 14400 0 +04}
    {670370400 10800 0 +03}
    {670374000 14400 1 +03}
    {686098800 10800 0 +03}
    {701823600 14400 1 +03}
    {717548400 14400 0 +04}
    {820440000 14400 0 +04}
    {828234000 18000 1 +05}
    {846378000 14400 0 +04}
    {852062400 14400 0 +04}
    {859680000 18000 1 +04}
    {877824000 14400 0 +04}
    {891129600 18000 1 +04}
    {909273600 14400 0 +04}
    {922579200 18000 1 +04}
    {941328000 14400 0 +04}
    {954028800 18000 1 +04}
    {972777600 14400 0 +04}
    {985478400 18000 1 +04}
    {1004227200 14400 0 +04}
    {1017532800 18000 1 +04}
    {1035676800 14400 0 +04}
    {1048982400 18000 1 +04}
    {1067126400 14400 0 +04}
    {1080432000 18000 1 +04}
    {1099180800 14400 0 +04}
    {1111881600 18000 1 +04}
    {1130630400 14400 0 +04}
    {1143331200 18000 1 +04}
    {1162080000 14400 0 +04}
    {1174780800 18000 1 +04}
    {1193529600 14400 0 +04}
    {1206835200 18000 1 +04}
    {1224979200 14400 0 +04}
    {1238284800 18000 1 +04}
    {1256428800 14400 0 +04}
    {1269734400 18000 1 +04}
    {1288483200 14400 0 +04}
    {1301184000 18000 1 +04}
    {1319932800 14400 0 +04}
    {1332633600 18000 1 +04}
    {1351382400 14400 0 +04}
    {1364688000 18000 1 +04}
    {1382832000 14400 0 +04}
    {1396137600 18000 1 +04}
    {1414281600 14400 0 +04}
    {1427587200 18000 1 +04}
    {1445731200 14400 0 +04}
    {-1441163964 10800 0 +0300}
    {-405140400 14400 0 +0400}
    {354916800 18000 1 +0500}
    {370724400 14400 0 +0400}
    {386452800 18000 1 +0500}
    {402260400 14400 0 +0400}
    {417988800 18000 1 +0500}
    {433796400 14400 0 +0400}
    {449611200 18000 1 +0500}
    {465343200 14400 0 +0400}
    {481068000 18000 1 +0500}
    {496792800 14400 0 +0400}
    {512517600 18000 1 +0500}
    {528242400 14400 0 +0400}
    {543967200 18000 1 +0500}
    {559692000 14400 0 +0400}
    {575416800 18000 1 +0500}
    {591141600 14400 0 +0400}
    {606866400 18000 1 +0500}
    {622591200 14400 0 +0400}
    {638316000 18000 1 +0500}
    {654645600 14400 0 +0400}
    {670370400 10800 0 +0300}
    {670374000 14400 1 +0400}
    {686098800 10800 0 +0300}
    {701823600 14400 1 +0400}
    {717548400 14400 0 +0400}
    {820440000 14400 0 +0400}
    {828234000 18000 1 +0500}
    {846378000 14400 0 +0400}
    {852062400 14400 0 +0400}
    {859680000 18000 1 +0500}
    {877824000 14400 0 +0400}
    {891129600 18000 1 +0500}
    {909273600 14400 0 +0400}
    {922579200 18000 1 +0500}
    {941328000 14400 0 +0400}
    {954028800 18000 1 +0500}
    {972777600 14400 0 +0400}
    {985478400 18000 1 +0500}
    {1004227200 14400 0 +0400}
    {1017532800 18000 1 +0500}
    {1035676800 14400 0 +0400}
    {1048982400 18000 1 +0500}
    {1067126400 14400 0 +0400}
    {1080432000 18000 1 +0500}
    {1099180800 14400 0 +0400}
    {1111881600 18000 1 +0500}
    {1130630400 14400 0 +0400}
    {1143331200 18000 1 +0500}
    {1162080000 14400 0 +0400}
    {1174780800 18000 1 +0500}
    {1193529600 14400 0 +0400}
    {1206835200 18000 1 +0500}
    {1224979200 14400 0 +0400}
    {1238284800 18000 1 +0500}
    {1256428800 14400 0 +0400}
    {1269734400 18000 1 +0500}
    {1288483200 14400 0 +0400}
    {1301184000 18000 1 +0500}
    {1319932800 14400 0 +0400}
    {1332633600 18000 1 +0500}
    {1351382400 14400 0 +0400}
    {1364688000 18000 1 +0500}
    {1382832000 14400 0 +0400}
    {1396137600 18000 1 +0500}
    {1414281600 14400 0 +0400}
    {1427587200 18000 1 +0500}
    {1445731200 14400 0 +0400}
}

Changes to library/tzdata/Asia/Bangkok.

1
2
3
4
5
6

7
1
2
3
4
5

6
7





-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Bangkok) {
    {-9223372036854775808 24124 0 LMT}
    {-2840164924 24124 0 BMT}
    {-1570084924 25200 0 +07}
    {-1570084924 25200 0 +0700}
}

Changes to library/tzdata/Asia/Barnaul.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Barnaul) {
    {-9223372036854775808 20100 0 LMT}
    {-1579844100 21600 0 +06}
    {-1247551200 25200 0 +08}
    {354906000 28800 1 +08}
    {370713600 25200 0 +07}
    {386442000 28800 1 +08}
    {402249600 25200 0 +07}
    {417978000 28800 1 +08}
    {433785600 25200 0 +07}
    {449600400 28800 1 +08}
    {465332400 25200 0 +07}
    {481057200 28800 1 +08}
    {496782000 25200 0 +07}
    {512506800 28800 1 +08}
    {528231600 25200 0 +07}
    {543956400 28800 1 +08}
    {559681200 25200 0 +07}
    {575406000 28800 1 +08}
    {591130800 25200 0 +07}
    {606855600 28800 1 +08}
    {622580400 25200 0 +07}
    {638305200 28800 1 +08}
    {654634800 25200 0 +07}
    {670359600 21600 0 +07}
    {670363200 25200 1 +07}
    {686088000 21600 0 +06}
    {695764800 25200 0 +08}
    {701809200 28800 1 +08}
    {717534000 25200 0 +07}
    {733258800 28800 1 +08}
    {748983600 25200 0 +07}
    {764708400 28800 1 +08}
    {780433200 25200 0 +07}
    {796158000 28800 1 +08}
    {801594000 25200 0 +07}
    {811886400 21600 0 +06}
    {828216000 25200 1 +07}
    {846360000 21600 0 +06}
    {859665600 25200 1 +07}
    {877809600 21600 0 +06}
    {891115200 25200 1 +07}
    {909259200 21600 0 +06}
    {922564800 25200 1 +07}
    {941313600 21600 0 +06}
    {954014400 25200 1 +07}
    {972763200 21600 0 +06}
    {985464000 25200 1 +07}
    {1004212800 21600 0 +06}
    {1017518400 25200 1 +07}
    {1035662400 21600 0 +06}
    {1048968000 25200 1 +07}
    {1067112000 21600 0 +06}
    {1080417600 25200 1 +07}
    {1099166400 21600 0 +06}
    {1111867200 25200 1 +07}
    {1130616000 21600 0 +06}
    {1143316800 25200 1 +07}
    {1162065600 21600 0 +06}
    {1174766400 25200 1 +07}
    {1193515200 21600 0 +06}
    {1206820800 25200 1 +07}
    {1224964800 21600 0 +06}
    {1238270400 25200 1 +07}
    {1256414400 21600 0 +06}
    {1269720000 25200 1 +07}
    {1288468800 21600 0 +06}
    {1301169600 25200 0 +07}
    {1414263600 21600 0 +06}
    {1459022400 25200 0 +07}
    {-1579844100 21600 0 +0600}
    {-1247551200 25200 0 +0700}
    {354906000 28800 1 +0800}
    {370713600 25200 0 +0700}
    {386442000 28800 1 +0800}
    {402249600 25200 0 +0700}
    {417978000 28800 1 +0800}
    {433785600 25200 0 +0700}
    {449600400 28800 1 +0800}
    {465332400 25200 0 +0700}
    {481057200 28800 1 +0800}
    {496782000 25200 0 +0700}
    {512506800 28800 1 +0800}
    {528231600 25200 0 +0700}
    {543956400 28800 1 +0800}
    {559681200 25200 0 +0700}
    {575406000 28800 1 +0800}
    {591130800 25200 0 +0700}
    {606855600 28800 1 +0800}
    {622580400 25200 0 +0700}
    {638305200 28800 1 +0800}
    {654634800 25200 0 +0700}
    {670359600 21600 0 +0600}
    {670363200 25200 1 +0700}
    {686088000 21600 0 +0600}
    {695764800 25200 0 +0700}
    {701809200 28800 1 +0800}
    {717534000 25200 0 +0700}
    {733258800 28800 1 +0800}
    {748983600 25200 0 +0700}
    {764708400 28800 1 +0800}
    {780433200 25200 0 +0700}
    {796158000 28800 1 +0800}
    {801594000 25200 0 +0700}
    {811886400 21600 0 +0600}
    {828216000 25200 1 +0700}
    {846360000 21600 0 +0600}
    {859665600 25200 1 +0700}
    {877809600 21600 0 +0600}
    {891115200 25200 1 +0700}
    {909259200 21600 0 +0600}
    {922564800 25200 1 +0700}
    {941313600 21600 0 +0600}
    {954014400 25200 1 +0700}
    {972763200 21600 0 +0600}
    {985464000 25200 1 +0700}
    {1004212800 21600 0 +0600}
    {1017518400 25200 1 +0700}
    {1035662400 21600 0 +0600}
    {1048968000 25200 1 +0700}
    {1067112000 21600 0 +0600}
    {1080417600 25200 1 +0700}
    {1099166400 21600 0 +0600}
    {1111867200 25200 1 +0700}
    {1130616000 21600 0 +0600}
    {1143316800 25200 1 +0700}
    {1162065600 21600 0 +0600}
    {1174766400 25200 1 +0700}
    {1193515200 21600 0 +0600}
    {1206820800 25200 1 +0700}
    {1224964800 21600 0 +0600}
    {1238270400 25200 1 +0700}
    {1256414400 21600 0 +0600}
    {1269720000 25200 1 +0700}
    {1288468800 21600 0 +0600}
    {1301169600 25200 0 +0700}
    {1414263600 21600 0 +0600}
    {1459022400 25200 0 +0700}
}

Changes to library/tzdata/Asia/Bishkek.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Bishkek) {
    {-9223372036854775808 17904 0 LMT}
    {-1441169904 18000 0 +05}
    {-1247547600 21600 0 +06}
    {354909600 25200 1 +06}
    {370717200 21600 0 +06}
    {386445600 25200 1 +06}
    {402253200 21600 0 +06}
    {417981600 25200 1 +06}
    {433789200 21600 0 +06}
    {449604000 25200 1 +06}
    {465336000 21600 0 +06}
    {481060800 25200 1 +06}
    {496785600 21600 0 +06}
    {512510400 25200 1 +06}
    {528235200 21600 0 +06}
    {543960000 25200 1 +06}
    {559684800 21600 0 +06}
    {575409600 25200 1 +06}
    {591134400 21600 0 +06}
    {606859200 25200 1 +06}
    {622584000 21600 0 +06}
    {638308800 25200 1 +06}
    {654638400 21600 0 +06}
    {670363200 18000 0 +05}
    {670366800 21600 1 +05}
    {683586000 18000 0 +05}
    {703018800 21600 1 +05}
    {717530400 18000 0 +05}
    {734468400 21600 1 +05}
    {748980000 18000 0 +05}
    {765918000 21600 1 +05}
    {780429600 18000 0 +05}
    {797367600 21600 1 +05}
    {811879200 18000 0 +05}
    {828817200 21600 1 +05}
    {843933600 18000 0 +05}
    {859671000 21600 1 +05}
    {877811400 18000 0 +05}
    {891120600 21600 1 +05}
    {909261000 18000 0 +05}
    {922570200 21600 1 +05}
    {941315400 18000 0 +05}
    {954019800 21600 1 +05}
    {972765000 18000 0 +05}
    {985469400 21600 1 +05}
    {1004214600 18000 0 +05}
    {1017523800 21600 1 +05}
    {1035664200 18000 0 +05}
    {1048973400 21600 1 +05}
    {1067113800 18000 0 +05}
    {1080423000 21600 1 +05}
    {1099168200 18000 0 +05}
    {1111872600 21600 1 +05}
    {1123783200 21600 0 +06}
    {-1441169904 18000 0 +0500}
    {-1247547600 21600 0 +0600}
    {354909600 25200 1 +0700}
    {370717200 21600 0 +0600}
    {386445600 25200 1 +0700}
    {402253200 21600 0 +0600}
    {417981600 25200 1 +0700}
    {433789200 21600 0 +0600}
    {449604000 25200 1 +0700}
    {465336000 21600 0 +0600}
    {481060800 25200 1 +0700}
    {496785600 21600 0 +0600}
    {512510400 25200 1 +0700}
    {528235200 21600 0 +0600}
    {543960000 25200 1 +0700}
    {559684800 21600 0 +0600}
    {575409600 25200 1 +0700}
    {591134400 21600 0 +0600}
    {606859200 25200 1 +0700}
    {622584000 21600 0 +0600}
    {638308800 25200 1 +0700}
    {654638400 21600 0 +0600}
    {670363200 18000 0 +0500}
    {670366800 21600 1 +0600}
    {683586000 18000 0 +0500}
    {703018800 21600 1 +0600}
    {717530400 18000 0 +0500}
    {734468400 21600 1 +0600}
    {748980000 18000 0 +0500}
    {765918000 21600 1 +0600}
    {780429600 18000 0 +0500}
    {797367600 21600 1 +0600}
    {811879200 18000 0 +0500}
    {828817200 21600 1 +0600}
    {843933600 18000 0 +0500}
    {859671000 21600 1 +0600}
    {877811400 18000 0 +0500}
    {891120600 21600 1 +0600}
    {909261000 18000 0 +0500}
    {922570200 21600 1 +0600}
    {941315400 18000 0 +0500}
    {954019800 21600 1 +0600}
    {972765000 18000 0 +0500}
    {985469400 21600 1 +0600}
    {1004214600 18000 0 +0500}
    {1017523800 21600 1 +0600}
    {1035664200 18000 0 +0500}
    {1048973400 21600 1 +0600}
    {1067113800 18000 0 +0500}
    {1080423000 21600 1 +0600}
    {1099168200 18000 0 +0500}
    {1111872600 21600 1 +0600}
    {1123783200 21600 0 +0600}
}

Changes to library/tzdata/Asia/Brunei.

1


2
3


4
5
6
7
1
2
3


4
5





+
+
-
-
+
+
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Asia/Kuching)]} {
    LoadTimeZoneFile Asia/Kuching

set TZData(:Asia/Brunei) {
}
set TZData(:Asia/Brunei) $TZData(:Asia/Kuching)
    {-9223372036854775808 27580 0 LMT}
    {-1383464380 27000 0 +0730}
    {-1167636600 28800 0 +08}
}

Changes to library/tzdata/Asia/Chita.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Chita) {
    {-9223372036854775808 27232 0 LMT}
    {-1579419232 28800 0 +08}
    {-1247558400 32400 0 +10}
    {354898800 36000 1 +10}
    {370706400 32400 0 +09}
    {386434800 36000 1 +10}
    {402242400 32400 0 +09}
    {417970800 36000 1 +10}
    {433778400 32400 0 +09}
    {449593200 36000 1 +10}
    {465325200 32400 0 +09}
    {481050000 36000 1 +10}
    {496774800 32400 0 +09}
    {512499600 36000 1 +10}
    {528224400 32400 0 +09}
    {543949200 36000 1 +10}
    {559674000 32400 0 +09}
    {575398800 36000 1 +10}
    {591123600 32400 0 +09}
    {606848400 36000 1 +10}
    {622573200 32400 0 +09}
    {638298000 36000 1 +10}
    {654627600 32400 0 +09}
    {670352400 28800 0 +09}
    {670356000 32400 1 +09}
    {686080800 28800 0 +08}
    {695757600 32400 0 +10}
    {701802000 36000 1 +10}
    {717526800 32400 0 +09}
    {733251600 36000 1 +10}
    {748976400 32400 0 +09}
    {764701200 36000 1 +10}
    {780426000 32400 0 +09}
    {796150800 36000 1 +10}
    {811875600 32400 0 +09}
    {828205200 36000 1 +10}
    {846349200 32400 0 +09}
    {859654800 36000 1 +10}
    {877798800 32400 0 +09}
    {891104400 36000 1 +10}
    {909248400 32400 0 +09}
    {922554000 36000 1 +10}
    {941302800 32400 0 +09}
    {954003600 36000 1 +10}
    {972752400 32400 0 +09}
    {985453200 36000 1 +10}
    {1004202000 32400 0 +09}
    {1017507600 36000 1 +10}
    {1035651600 32400 0 +09}
    {1048957200 36000 1 +10}
    {1067101200 32400 0 +09}
    {1080406800 36000 1 +10}
    {1099155600 32400 0 +09}
    {1111856400 36000 1 +10}
    {1130605200 32400 0 +09}
    {1143306000 36000 1 +10}
    {1162054800 32400 0 +09}
    {1174755600 36000 1 +10}
    {1193504400 32400 0 +09}
    {1206810000 36000 1 +10}
    {1224954000 32400 0 +09}
    {1238259600 36000 1 +10}
    {1256403600 32400 0 +09}
    {1269709200 36000 1 +10}
    {1288458000 32400 0 +09}
    {1301158800 36000 0 +10}
    {1414252800 28800 0 +08}
    {1459015200 32400 0 +09}
    {-1579419232 28800 0 +0800}
    {-1247558400 32400 0 +0900}
    {354898800 36000 1 +1000}
    {370706400 32400 0 +0900}
    {386434800 36000 1 +1000}
    {402242400 32400 0 +0900}
    {417970800 36000 1 +1000}
    {433778400 32400 0 +0900}
    {449593200 36000 1 +1000}
    {465325200 32400 0 +0900}
    {481050000 36000 1 +1000}
    {496774800 32400 0 +0900}
    {512499600 36000 1 +1000}
    {528224400 32400 0 +0900}
    {543949200 36000 1 +1000}
    {559674000 32400 0 +0900}
    {575398800 36000 1 +1000}
    {591123600 32400 0 +0900}
    {606848400 36000 1 +1000}
    {622573200 32400 0 +0900}
    {638298000 36000 1 +1000}
    {654627600 32400 0 +0900}
    {670352400 28800 0 +0800}
    {670356000 32400 1 +0900}
    {686080800 28800 0 +0800}
    {695757600 32400 0 +0900}
    {701802000 36000 1 +1000}
    {717526800 32400 0 +0900}
    {733251600 36000 1 +1000}
    {748976400 32400 0 +0900}
    {764701200 36000 1 +1000}
    {780426000 32400 0 +0900}
    {796150800 36000 1 +1000}
    {811875600 32400 0 +0900}
    {828205200 36000 1 +1000}
    {846349200 32400 0 +0900}
    {859654800 36000 1 +1000}
    {877798800 32400 0 +0900}
    {891104400 36000 1 +1000}
    {909248400 32400 0 +0900}
    {922554000 36000 1 +1000}
    {941302800 32400 0 +0900}
    {954003600 36000 1 +1000}
    {972752400 32400 0 +0900}
    {985453200 36000 1 +1000}
    {1004202000 32400 0 +0900}
    {1017507600 36000 1 +1000}
    {1035651600 32400 0 +0900}
    {1048957200 36000 1 +1000}
    {1067101200 32400 0 +0900}
    {1080406800 36000 1 +1000}
    {1099155600 32400 0 +0900}
    {1111856400 36000 1 +1000}
    {1130605200 32400 0 +0900}
    {1143306000 36000 1 +1000}
    {1162054800 32400 0 +0900}
    {1174755600 36000 1 +1000}
    {1193504400 32400 0 +0900}
    {1206810000 36000 1 +1000}
    {1224954000 32400 0 +0900}
    {1238259600 36000 1 +1000}
    {1256403600 32400 0 +0900}
    {1269709200 36000 1 +1000}
    {1288458000 32400 0 +0900}
    {1301158800 36000 0 +1000}
    {1414252800 28800 0 +0800}
    {1459015200 32400 0 +0900}
}

Changes to library/tzdata/Asia/Choibalsan.

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
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
1
2
3


4
5






















































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Asia/Ulaanbaatar)]} {
    LoadTimeZoneFile Asia/Ulaanbaatar

set TZData(:Asia/Choibalsan) {
}
set TZData(:Asia/Choibalsan) $TZData(:Asia/Ulaanbaatar)
    {-9223372036854775808 27480 0 LMT}
    {-2032933080 25200 0 +07}
    {252435600 28800 0 +08}
    {417974400 36000 0 +09}
    {433778400 32400 0 +09}
    {449593200 36000 1 +09}
    {465314400 32400 0 +09}
    {481042800 36000 1 +09}
    {496764000 32400 0 +09}
    {512492400 36000 1 +09}
    {528213600 32400 0 +09}
    {543942000 36000 1 +09}
    {559663200 32400 0 +09}
    {575391600 36000 1 +09}
    {591112800 32400 0 +09}
    {606841200 36000 1 +09}
    {622562400 32400 0 +09}
    {638290800 36000 1 +09}
    {654616800 32400 0 +09}
    {670345200 36000 1 +09}
    {686066400 32400 0 +09}
    {701794800 36000 1 +09}
    {717516000 32400 0 +09}
    {733244400 36000 1 +09}
    {748965600 32400 0 +09}
    {764694000 36000 1 +09}
    {780415200 32400 0 +09}
    {796143600 36000 1 +09}
    {811864800 32400 0 +09}
    {828198000 36000 1 +09}
    {843919200 32400 0 +09}
    {859647600 36000 1 +09}
    {875368800 32400 0 +09}
    {891097200 36000 1 +09}
    {906818400 32400 0 +09}
    {988390800 36000 1 +09}
    {1001692800 32400 0 +09}
    {1017421200 36000 1 +09}
    {1033142400 32400 0 +09}
    {1048870800 36000 1 +09}
    {1064592000 32400 0 +09}
    {1080320400 36000 1 +09}
    {1096041600 32400 0 +09}
    {1111770000 36000 1 +09}
    {1127491200 32400 0 +09}
    {1143219600 36000 1 +09}
    {1159545600 32400 0 +09}
    {1206889200 28800 0 +08}
    {1427479200 32400 1 +08}
    {1443193200 28800 0 +08}
    {1458928800 32400 1 +08}
    {1474642800 28800 0 +08}
}

Changes to library/tzdata/Asia/Colombo.

1
2
3
4
5
6
7

8
9
10
11

12
13
1
2
3
4
5
6

7
8
9
10

11
12
13






-
+



-
+


# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Colombo) {
    {-9223372036854775808 19164 0 LMT}
    {-2840159964 19172 0 MMT}
    {-2019705572 19800 0 +0530}
    {-883287000 21600 1 +06}
    {-883287000 21600 1 +0600}
    {-862639200 23400 1 +0630}
    {-764051400 19800 0 +0530}
    {832962600 23400 0 +0630}
    {846266400 21600 0 +06}
    {846266400 21600 0 +0600}
    {1145039400 19800 0 +0530}
}

Changes to library/tzdata/Asia/Damascus.

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
118
119
120
121
122
123
124




























125































































































































126







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

    {1553810400 10800 1 EEST}
    {1571950800 7200 0 EET}
    {1585260000 10800 1 EEST}
    {1604005200 7200 0 EET}
    {1616709600 10800 1 EEST}
    {1635454800 7200 0 EET}
    {1648159200 10800 1 EEST}
    {1666904400 7200 0 EET}
    {1680213600 10800 1 EEST}
    {1698354000 7200 0 EET}
    {1711663200 10800 1 EEST}
    {1729803600 7200 0 EET}
    {1743112800 10800 1 EEST}
    {1761858000 7200 0 EET}
    {1774562400 10800 1 EEST}
    {1793307600 7200 0 EET}
    {1806012000 10800 1 EEST}
    {1824757200 7200 0 EET}
    {1838066400 10800 1 EEST}
    {1856206800 7200 0 EET}
    {1869516000 10800 1 EEST}
    {1887656400 7200 0 EET}
    {1900965600 10800 1 EEST}
    {1919106000 7200 0 EET}
    {1932415200 10800 1 EEST}
    {1951160400 7200 0 EET}
    {1963864800 10800 1 EEST}
    {1982610000 7200 0 EET}
    {1995314400 10800 1 EEST}
    {2014059600 7200 0 EET}
    {2027368800 10800 1 EEST}
    {2045509200 7200 0 EET}
    {2058818400 10800 1 EEST}
    {2076958800 7200 0 EET}
    {2090268000 10800 1 EEST}
    {1666908000 10800 0 +0300}
    {2109013200 7200 0 EET}
    {2121717600 10800 1 EEST}
    {2140462800 7200 0 EET}
    {2153167200 10800 1 EEST}
    {2171912400 7200 0 EET}
    {2184616800 10800 1 EEST}
    {2203362000 7200 0 EET}
    {2216671200 10800 1 EEST}
    {2234811600 7200 0 EET}
    {2248120800 10800 1 EEST}
    {2266261200 7200 0 EET}
    {2279570400 10800 1 EEST}
    {2298315600 7200 0 EET}
    {2311020000 10800 1 EEST}
    {2329765200 7200 0 EET}
    {2342469600 10800 1 EEST}
    {2361214800 7200 0 EET}
    {2374524000 10800 1 EEST}
    {2392664400 7200 0 EET}
    {2405973600 10800 1 EEST}
    {2424114000 7200 0 EET}
    {2437423200 10800 1 EEST}
    {2455563600 7200 0 EET}
    {2468872800 10800 1 EEST}
    {2487618000 7200 0 EET}
    {2500322400 10800 1 EEST}
    {2519067600 7200 0 EET}
    {2531772000 10800 1 EEST}
    {2550517200 7200 0 EET}
    {2563826400 10800 1 EEST}
    {2581966800 7200 0 EET}
    {2595276000 10800 1 EEST}
    {2613416400 7200 0 EET}
    {2626725600 10800 1 EEST}
    {2645470800 7200 0 EET}
    {2658175200 10800 1 EEST}
    {2676920400 7200 0 EET}
    {2689624800 10800 1 EEST}
    {2708370000 7200 0 EET}
    {2721679200 10800 1 EEST}
    {2739819600 7200 0 EET}
    {2753128800 10800 1 EEST}
    {2771269200 7200 0 EET}
    {2784578400 10800 1 EEST}
    {2802718800 7200 0 EET}
    {2816028000 10800 1 EEST}
    {2834773200 7200 0 EET}
    {2847477600 10800 1 EEST}
    {2866222800 7200 0 EET}
    {2878927200 10800 1 EEST}
    {2897672400 7200 0 EET}
    {2910981600 10800 1 EEST}
    {2929122000 7200 0 EET}
    {2942431200 10800 1 EEST}
    {2960571600 7200 0 EET}
    {2973880800 10800 1 EEST}
    {2992626000 7200 0 EET}
    {3005330400 10800 1 EEST}
    {3024075600 7200 0 EET}
    {3036780000 10800 1 EEST}
    {3055525200 7200 0 EET}
    {3068229600 10800 1 EEST}
    {3086974800 7200 0 EET}
    {3100284000 10800 1 EEST}
    {3118424400 7200 0 EET}
    {3131733600 10800 1 EEST}
    {3149874000 7200 0 EET}
    {3163183200 10800 1 EEST}
    {3181928400 7200 0 EET}
    {3194632800 10800 1 EEST}
    {3213378000 7200 0 EET}
    {3226082400 10800 1 EEST}
    {3244827600 7200 0 EET}
    {3258136800 10800 1 EEST}
    {3276277200 7200 0 EET}
    {3289586400 10800 1 EEST}
    {3307726800 7200 0 EET}
    {3321036000 10800 1 EEST}
    {3339176400 7200 0 EET}
    {3352485600 10800 1 EEST}
    {3371230800 7200 0 EET}
    {3383935200 10800 1 EEST}
    {3402680400 7200 0 EET}
    {3415384800 10800 1 EEST}
    {3434130000 7200 0 EET}
    {3447439200 10800 1 EEST}
    {3465579600 7200 0 EET}
    {3478888800 10800 1 EEST}
    {3497029200 7200 0 EET}
    {3510338400 10800 1 EEST}
    {3529083600 7200 0 EET}
    {3541788000 10800 1 EEST}
    {3560533200 7200 0 EET}
    {3573237600 10800 1 EEST}
    {3591982800 7200 0 EET}
    {3605292000 10800 1 EEST}
    {3623432400 7200 0 EET}
    {3636741600 10800 1 EEST}
    {3654882000 7200 0 EET}
    {3668191200 10800 1 EEST}
    {3686331600 7200 0 EET}
    {3699640800 10800 1 EEST}
    {3718386000 7200 0 EET}
    {3731090400 10800 1 EEST}
    {3749835600 7200 0 EET}
    {3762540000 10800 1 EEST}
    {3781285200 7200 0 EET}
    {3794594400 10800 1 EEST}
    {3812734800 7200 0 EET}
    {3826044000 10800 1 EEST}
    {3844184400 7200 0 EET}
    {3857493600 10800 1 EEST}
    {3876238800 7200 0 EET}
    {3888943200 10800 1 EEST}
    {3907688400 7200 0 EET}
    {3920392800 10800 1 EEST}
    {3939138000 7200 0 EET}
    {3951842400 10800 1 EEST}
    {3970587600 7200 0 EET}
    {3983896800 10800 1 EEST}
    {4002037200 7200 0 EET}
    {4015346400 10800 1 EEST}
    {4033486800 7200 0 EET}
    {4046796000 10800 1 EEST}
    {4065541200 7200 0 EET}
    {4078245600 10800 1 EEST}
    {4096990800 7200 0 EET}
}

Changes to library/tzdata/Asia/Dhaka.

1
2
3
4
5
6
7
8
9
10
11
12




13
1
2
3
4
5
6
7
8




9
10
11
12
13








-
-
-
-
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Dhaka) {
    {-9223372036854775808 21700 0 LMT}
    {-2524543300 21200 0 HMT}
    {-891582800 23400 0 +0630}
    {-872058600 19800 0 +0530}
    {-862637400 23400 0 +0630}
    {-576138600 21600 0 +06}
    {1230746400 21600 0 +06}
    {1245430800 25200 1 +06}
    {1262278800 21600 0 +06}
    {-576138600 21600 0 +0600}
    {1230746400 21600 0 +0600}
    {1245430800 25200 1 +0700}
    {1262278800 21600 0 +0600}
}

Changes to library/tzdata/Asia/Dili.

1
2
3
4
5
6
7
8




9
1
2
3
4




5
6
7
8
9




-
-
-
-
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Dili) {
    {-9223372036854775808 30140 0 LMT}
    {-1830414140 28800 0 +08}
    {-879152400 32400 0 +09}
    {199897200 28800 0 +08}
    {969120000 32400 0 +09}
    {-1830412800 28800 0 +0800}
    {-879152400 32400 0 +0900}
    {199897200 28800 0 +0800}
    {969120000 32400 0 +0900}
}

Changes to library/tzdata/Asia/Dubai.

1
2
3
4
5

6
1
2
3
4

5
6




-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Dubai) {
    {-9223372036854775808 13272 0 LMT}
    {-1577936472 14400 0 +04}
    {-1577936472 14400 0 +0400}
}

Changes to library/tzdata/Asia/Dushanbe.

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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Dushanbe) {
    {-9223372036854775808 16512 0 LMT}
    {-1441168512 18000 0 +05}
    {-1247547600 21600 0 +06}
    {354909600 25200 1 +06}
    {370717200 21600 0 +06}
    {386445600 25200 1 +06}
    {402253200 21600 0 +06}
    {417981600 25200 1 +06}
    {433789200 21600 0 +06}
    {449604000 25200 1 +06}
    {465336000 21600 0 +06}
    {481060800 25200 1 +06}
    {496785600 21600 0 +06}
    {512510400 25200 1 +06}
    {528235200 21600 0 +06}
    {543960000 25200 1 +06}
    {559684800 21600 0 +06}
    {575409600 25200 1 +06}
    {591134400 21600 0 +06}
    {606859200 25200 1 +06}
    {622584000 21600 0 +06}
    {638308800 25200 1 +06}
    {654638400 21600 0 +06}
    {670363200 21600 1 +06}
    {684363600 18000 0 +05}
    {-1441168512 18000 0 +0500}
    {-1247547600 21600 0 +0600}
    {354909600 25200 1 +0700}
    {370717200 21600 0 +0600}
    {386445600 25200 1 +0700}
    {402253200 21600 0 +0600}
    {417981600 25200 1 +0700}
    {433789200 21600 0 +0600}
    {449604000 25200 1 +0700}
    {465336000 21600 0 +0600}
    {481060800 25200 1 +0700}
    {496785600 21600 0 +0600}
    {512510400 25200 1 +0700}
    {528235200 21600 0 +0600}
    {543960000 25200 1 +0700}
    {559684800 21600 0 +0600}
    {575409600 25200 1 +0700}
    {591134400 21600 0 +0600}
    {606859200 25200 1 +0700}
    {622584000 21600 0 +0600}
    {638308800 25200 1 +0700}
    {654638400 21600 0 +0600}
    {670363200 21600 1 +0600}
    {684363600 18000 0 +0500}
}

Changes to library/tzdata/Asia/Famagusta.

83
84
85
86
87
88
89
90

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

90
91
92
93
94
95
96
97







-
+







    {1364691600 10800 1 EEST}
    {1382835600 7200 0 EET}
    {1396141200 10800 1 EEST}
    {1414285200 7200 0 EET}
    {1427590800 10800 1 EEST}
    {1445734800 7200 0 EET}
    {1459040400 10800 1 EEST}
    {1473285600 10800 0 +03}
    {1473285600 10800 0 +0300}
    {1509238800 7200 0 EET}
    {1521939600 10800 1 EEST}
    {1540688400 7200 0 EET}
    {1553994000 10800 1 EEST}
    {1572138000 7200 0 EET}
    {1585443600 10800 1 EEST}
    {1603587600 7200 0 EET}

Changes to library/tzdata/Asia/Gaza.

1
2
3
4
5
6
7




8
9
10
11
12
13





14
15

16
17
18
19
20
21
22
1
2
3
4
5


6
7
8
9
10





11
12
13
14
15
16

17
18
19
20
21
22
23
24





-
-
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Gaza) {
    {-9223372036854775808 8272 0 LMT}
    {-2185409872 7200 0 EEST}
    {-933645600 10800 1 EEST}
    {-857358000 7200 0 EEST}
    {-933638400 10800 1 EEST}
    {-923097600 7200 0 EEST}
    {-919036800 10800 1 EEST}
    {-857347200 7200 0 EEST}
    {-844300800 10800 1 EEST}
    {-825822000 7200 0 EEST}
    {-812685600 10800 1 EEST}
    {-794199600 7200 0 EEST}
    {-779853600 10800 1 EEST}
    {-762656400 7200 0 EEST}
    {-825811200 7200 0 EEST}
    {-812678400 10800 1 EEST}
    {-794188800 7200 0 EEST}
    {-779846400 10800 1 EEST}
    {-762652800 7200 0 EEST}
    {-748310400 10800 1 EEST}
    {-731127600 7200 0 EEST}
    {-731116800 7200 0 EEST}
    {-682653600 7200 0 EET}
    {-399088800 10800 1 EEST}
    {-386650800 7200 0 EET}
    {-368330400 10800 1 EEST}
    {-355114800 7200 0 EET}
    {-336790800 10800 1 EEST}
    {-323654400 7200 0 EET}
36
37
38
39
40
41
42
43
44
45
46




47
48

49
50
51
52
53
54
55
38
39
40
41
42
43
44




45
46
47
48
49

50
51
52
53
54
55
56
57







-
-
-
-
+
+
+
+

-
+







    {-102643200 7200 0 EET}
    {-84330000 10800 1 EEST}
    {-81313200 10800 0 IST}
    {142376400 10800 1 IDT}
    {150843600 7200 0 IST}
    {167176800 10800 1 IDT}
    {178664400 7200 0 IST}
    {334015200 10800 1 IDT}
    {337644000 7200 0 IST}
    {452556000 10800 1 IDT}
    {462232800 7200 0 IST}
    {334101600 10800 1 IDT}
    {337730400 7200 0 IST}
    {452642400 10800 1 IDT}
    {462319200 7200 0 IST}
    {482277600 10800 1 IDT}
    {495579600 7200 0 IST}
    {494370000 7200 0 IST}
    {516751200 10800 1 IDT}
    {526424400 7200 0 IST}
    {545436000 10800 1 IDT}
    {558478800 7200 0 IST}
    {576626400 10800 1 IDT}
    {589323600 7200 0 IST}
    {609890400 10800 1 IDT}
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

    {1521846000 10800 1 EEST}
    {1540591200 7200 0 EET}
    {1553810400 10800 1 EEST}
    {1572037200 7200 0 EET}
    {1585346400 10800 1 EEST}
    {1603490400 7200 0 EET}
    {1616796000 10800 1 EEST}
    {1635544800 7200 0 EET}
    {1648245600 10800 1 EEST}
    {1666994400 7200 0 EET}
    {1679695200 10800 1 EEST}
    {1698444000 7200 0 EET}
    {1711749600 10800 1 EEST}
    {1729893600 7200 0 EET}
    {1743199200 10800 1 EEST}
    {1761343200 7200 0 EET}
    {1774648800 10800 1 EEST}
    {1792792800 7200 0 EET}
    {1806098400 10800 1 EEST}
    {1824847200 7200 0 EET}
    {1837548000 10800 1 EEST}
    {1856296800 7200 0 EET}
    {1868997600 10800 1 EEST}
    {1887746400 7200 0 EET}
    {1901052000 10800 1 EEST}
    {1919196000 7200 0 EET}
    {1932501600 10800 1 EEST}
    {1950645600 7200 0 EET}
    {1963951200 10800 1 EEST}
    {1982700000 7200 0 EET}
    {1995400800 10800 1 EEST}
    {2014149600 7200 0 EET}
    {2026850400 10800 1 EEST}
    {2045599200 7200 0 EET}
    {2058300000 10800 1 EEST}
    {2077048800 7200 0 EET}
    {2090354400 10800 1 EEST}
    {2108498400 7200 0 EET}
    {2121804000 10800 1 EEST}
    {2139948000 7200 0 EET}
    {2153253600 10800 1 EEST}
    {2172002400 7200 0 EET}
    {2184703200 10800 1 EEST}
    {2203452000 7200 0 EET}
    {2216152800 10800 1 EEST}
    {2234901600 7200 0 EET}
    {2248207200 10800 1 EEST}
    {2266351200 7200 0 EET}
    {2279656800 10800 1 EEST}
    {2297800800 7200 0 EET}
    {2311106400 10800 1 EEST}
    {2329250400 7200 0 EET}
    {2342556000 10800 1 EEST}
    {2361304800 7200 0 EET}
    {2374005600 10800 1 EEST}
    {2392754400 7200 0 EET}
    {2405455200 10800 1 EEST}
    {2424204000 7200 0 EET}
    {2437509600 10800 1 EEST}
    {2455653600 7200 0 EET}
    {2468959200 10800 1 EEST}
    {2487103200 7200 0 EET}
    {2500408800 10800 1 EEST}
    {2519157600 7200 0 EET}
    {2531858400 10800 1 EEST}
    {2550607200 7200 0 EET}
    {2563308000 10800 1 EEST}
    {2582056800 7200 0 EET}
    {2595362400 10800 1 EEST}
    {2613506400 7200 0 EET}
    {2626812000 10800 1 EEST}
    {2644956000 7200 0 EET}
    {2658261600 10800 1 EEST}
    {2676405600 7200 0 EET}
    {2689711200 10800 1 EEST}
    {2708460000 7200 0 EET}
    {2721160800 10800 1 EEST}
    {2739909600 7200 0 EET}
    {2752610400 10800 1 EEST}
    {2771359200 7200 0 EET}
    {2784664800 10800 1 EEST}
    {2802808800 7200 0 EET}
    {2816114400 10800 1 EEST}
    {2834258400 7200 0 EET}
    {2847564000 10800 1 EEST}
    {2866312800 7200 0 EET}
    {2879013600 10800 1 EEST}
    {2897762400 7200 0 EET}
    {2910463200 10800 1 EEST}
    {2929212000 7200 0 EET}
    {2941912800 10800 1 EEST}
    {2960661600 7200 0 EET}
    {2973967200 10800 1 EEST}
    {2992111200 7200 0 EET}
    {3005416800 10800 1 EEST}
    {3023560800 7200 0 EET}
    {3036866400 10800 1 EEST}
    {3055615200 7200 0 EET}
    {3068316000 10800 1 EEST}
    {3087064800 7200 0 EET}
    {3099765600 10800 1 EEST}
    {3118514400 7200 0 EET}
    {3131820000 10800 1 EEST}
    {3149964000 7200 0 EET}
    {3163269600 10800 1 EEST}
    {3181413600 7200 0 EET}
    {3194719200 10800 1 EEST}
    {3212863200 7200 0 EET}
    {3226168800 10800 1 EEST}
    {3244917600 7200 0 EET}
    {3257618400 10800 1 EEST}
    {3276367200 7200 0 EET}
    {3289068000 10800 1 EEST}
    {3307816800 7200 0 EET}
    {3321122400 10800 1 EEST}
    {3339266400 7200 0 EET}
    {3352572000 10800 1 EEST}
    {3370716000 7200 0 EET}
    {3384021600 10800 1 EEST}
    {3402770400 7200 0 EET}
    {3415471200 10800 1 EEST}
    {3434220000 7200 0 EET}
    {3446920800 10800 1 EEST}
    {3465669600 7200 0 EET}
    {3478975200 10800 1 EEST}
    {3497119200 7200 0 EET}
    {3510424800 10800 1 EEST}
    {3528568800 7200 0 EET}
    {3541874400 10800 1 EEST}
    {3560018400 7200 0 EET}
    {3573324000 10800 1 EEST}
    {3592072800 7200 0 EET}
    {3604773600 10800 1 EEST}
    {3623522400 7200 0 EET}
    {3636223200 10800 1 EEST}
    {3654972000 7200 0 EET}
    {3668277600 10800 1 EEST}
    {3686421600 7200 0 EET}
    {3699727200 10800 1 EEST}
    {3717871200 7200 0 EET}
    {3731176800 10800 1 EEST}
    {3749925600 7200 0 EET}
    {3762626400 10800 1 EEST}
    {3781375200 7200 0 EET}
    {3794076000 10800 1 EEST}
    {3812824800 7200 0 EET}
    {3825525600 10800 1 EEST}
    {3844274400 7200 0 EET}
    {3857580000 10800 1 EEST}
    {3875724000 7200 0 EET}
    {3889029600 10800 1 EEST}
    {3907173600 7200 0 EET}
    {3920479200 10800 1 EEST}
    {3939228000 7200 0 EET}
    {3951928800 10800 1 EEST}
    {3970677600 7200 0 EET}
    {3983378400 10800 1 EEST}
    {4002127200 7200 0 EET}
    {4015432800 10800 1 EEST}
    {4033576800 7200 0 EET}
    {4046882400 10800 1 EEST}
    {4065026400 7200 0 EET}
    {4078332000 10800 1 EEST}
    {4096476000 7200 0 EET}
    {1635458400 7200 0 EET}
    {1648332000 10800 1 EEST}
    {1666998000 7200 0 EET}
    {1682726400 10800 1 EEST}
    {1698447600 7200 0 EET}
    {1713571200 10800 1 EEST}
    {1729897200 7200 0 EET}
    {1744416000 10800 1 EEST}
    {1761346800 7200 0 EET}
    {1774656000 10800 1 EEST}
    {1792796400 7200 0 EET}
    {1806105600 10800 1 EEST}
    {1824850800 7200 0 EET}
    {1837555200 10800 1 EEST}
    {1856300400 7200 0 EET}
    {1869004800 10800 1 EEST}
    {1887750000 7200 0 EET}
    {1901059200 10800 1 EEST}
    {1919199600 7200 0 EET}
    {1932508800 10800 1 EEST}
    {1950649200 7200 0 EET}
    {1963958400 10800 1 EEST}
    {1982703600 7200 0 EET}
    {1995408000 10800 1 EEST}
    {2014153200 7200 0 EET}
    {2026857600 10800 1 EEST}
    {2045602800 7200 0 EET}
    {2058307200 10800 1 EEST}
    {2077052400 7200 0 EET}
    {2090361600 10800 1 EEST}
    {2107897200 7200 0 EET}
    {2121811200 10800 1 EEST}
    {2138742000 7200 0 EET}
    {2153260800 10800 1 EEST}
    {2168982000 7200 0 EET}
    {2184710400 10800 1 EEST}
    {2199826800 7200 0 EET}
    {2216160000 10800 1 EEST}
    {2230066800 7200 0 EET}
    {2234304000 10800 1 EEST}
    {2234905200 7200 0 EET}
    {2248214400 10800 1 EEST}
    {2260911600 7200 0 EET}
    {2264544000 10800 1 EEST}
    {2266354800 7200 0 EET}
    {2279664000 10800 1 EEST}
    {2291756400 7200 0 EET}
    {2295388800 10800 1 EEST}
    {2297804400 7200 0 EET}
    {2311113600 10800 1 EEST}
    {2321996400 7200 0 EET}
    {2326233600 10800 1 EEST}
    {2329254000 7200 0 EET}
    {2342563200 10800 1 EEST}
    {2352841200 7200 0 EET}
    {2356473600 10800 1 EEST}
    {2361308400 7200 0 EET}
    {2374012800 10800 1 EEST}
    {2383686000 7200 0 EET}
    {2387318400 10800 1 EEST}
    {2392758000 7200 0 EET}
    {2405462400 10800 1 EEST}
    {2413926000 7200 0 EET}
    {2418163200 10800 1 EEST}
    {2424207600 7200 0 EET}
    {2437516800 10800 1 EEST}
    {2444770800 7200 0 EET}
    {2448403200 10800 1 EEST}
    {2455657200 7200 0 EET}
    {2468966400 10800 1 EEST}
    {2475010800 7200 0 EET}
    {2479248000 10800 1 EEST}
    {2487106800 7200 0 EET}
    {2500416000 10800 1 EEST}
    {2505855600 7200 0 EET}
    {2509488000 10800 1 EEST}
    {2519161200 7200 0 EET}
    {2531865600 10800 1 EEST}
    {2536700400 7200 0 EET}
    {2540332800 10800 1 EEST}
    {2550610800 7200 0 EET}
    {2563315200 10800 1 EEST}
    {2566940400 7200 0 EET}
    {2571177600 10800 1 EEST}
    {2582060400 7200 0 EET}
    {2595369600 10800 1 EEST}
    {2597785200 7200 0 EET}
    {2601417600 10800 1 EEST}
    {2613510000 7200 0 EET}
    {2626819200 10800 1 EEST}
    {2628025200 7200 0 EET}
    {2632262400 10800 1 EEST}
    {2644959600 7200 0 EET}
    {2658268800 10800 1 EEST}
    {2658870000 7200 0 EET}
    {2663107200 10800 1 EEST}
    {2676409200 7200 0 EET}
    {2693347200 10800 1 EEST}
    {2708463600 7200 0 EET}
    {2724192000 10800 1 EEST}
    {2739913200 7200 0 EET}
    {2754432000 10800 1 EEST}
    {2771362800 7200 0 EET}
    {2785276800 10800 1 EEST}
    {2802812400 7200 0 EET}
    {2816121600 10800 1 EEST}
    {2834262000 7200 0 EET}
    {2847571200 10800 1 EEST}
    {2866316400 7200 0 EET}
    {2879020800 10800 1 EEST}
    {2897766000 7200 0 EET}
    {2910470400 10800 1 EEST}
    {2929215600 7200 0 EET}
    {2941920000 10800 1 EEST}
    {2960665200 7200 0 EET}
    {2973974400 10800 1 EEST}
    {2992114800 7200 0 EET}
    {3005424000 10800 1 EEST}
    {3023564400 7200 0 EET}
    {3036873600 10800 1 EEST}
    {3055618800 7200 0 EET}
    {3068323200 10800 1 EEST}
    {3087068400 7200 0 EET}
    {3099772800 10800 1 EEST}
    {3117913200 7200 0 EET}
    {3131827200 10800 1 EEST}
    {3148758000 7200 0 EET}
    {3163276800 10800 1 EEST}
    {3179602800 7200 0 EET}
    {3194726400 10800 1 EEST}
    {3209842800 7200 0 EET}
    {3226176000 10800 1 EEST}
    {3240687600 7200 0 EET}
    {3244320000 10800 1 EEST}
    {3244921200 7200 0 EET}
    {3257625600 10800 1 EEST}
    {3271532400 7200 0 EET}
    {3275164800 10800 1 EEST}
    {3276370800 7200 0 EET}
    {3289075200 10800 1 EEST}
    {3301772400 7200 0 EET}
    {3306009600 10800 1 EEST}
    {3307820400 7200 0 EET}
    {3321129600 10800 1 EEST}
    {3332617200 7200 0 EET}
    {3336249600 10800 1 EEST}
    {3339270000 7200 0 EET}
    {3352579200 10800 1 EEST}
    {3362857200 7200 0 EET}
    {3367094400 10800 1 EEST}
    {3370719600 7200 0 EET}
    {3384028800 10800 1 EEST}
    {3393702000 7200 0 EET}
    {3397939200 10800 1 EEST}
    {3402774000 7200 0 EET}
    {3415478400 10800 1 EEST}
    {3424546800 7200 0 EET}
    {3428179200 10800 1 EEST}
    {3434223600 7200 0 EET}
    {3446928000 10800 1 EEST}
    {3454786800 7200 0 EET}
    {3459024000 10800 1 EEST}
    {3465673200 7200 0 EET}
    {3478982400 10800 1 EEST}
    {3485631600 7200 0 EET}
    {3489264000 10800 1 EEST}
    {3497122800 7200 0 EET}
    {3510432000 10800 1 EEST}
    {3516476400 7200 0 EET}
    {3520108800 10800 1 EEST}
    {3528572400 7200 0 EET}
    {3541881600 10800 1 EEST}
    {3546716400 7200 0 EET}
    {3550953600 10800 1 EEST}
    {3560022000 7200 0 EET}
    {3573331200 10800 1 EEST}
    {3577561200 7200 0 EET}
    {3581193600 10800 1 EEST}
    {3592076400 7200 0 EET}
    {3604780800 10800 1 EEST}
    {3607801200 7200 0 EET}
    {3612038400 10800 1 EEST}
    {3623526000 7200 0 EET}
    {3636230400 10800 1 EEST}
    {3638646000 7200 0 EET}
    {3642883200 10800 1 EEST}
    {3654975600 7200 0 EET}
    {3668284800 10800 1 EEST}
    {3669490800 7200 0 EET}
    {3673123200 10800 1 EEST}
    {3686425200 7200 0 EET}
    {3699734400 10800 1 EEST}
    {3717874800 7200 0 EET}
    {3731184000 10800 1 EEST}
    {3749929200 7200 0 EET}
    {3762633600 10800 1 EEST}
    {3781378800 7200 0 EET}
    {3794083200 10800 1 EEST}
    {3812828400 7200 0 EET}
    {3825532800 10800 1 EEST}
    {3844278000 7200 0 EET}
    {3857587200 10800 1 EEST}
    {3875727600 7200 0 EET}
    {3889036800 10800 1 EEST}
    {3907177200 7200 0 EET}
    {3920486400 10800 1 EEST}
    {3939231600 7200 0 EET}
    {3951936000 10800 1 EEST}
    {3970681200 7200 0 EET}
    {3983385600 10800 1 EEST}
    {4002130800 7200 0 EET}
    {4015440000 10800 1 EEST}
    {4033580400 7200 0 EET}
    {4046889600 10800 1 EEST}
    {4065030000 7200 0 EET}
    {4078339200 10800 1 EEST}
    {4096479600 7200 0 EET}
}

Changes to library/tzdata/Asia/Hebron.

1
2
3
4
5
6
7




8
9
10
11
12
13





14
15

16
17
18
19
20
21
22
1
2
3
4
5


6
7
8
9
10





11
12
13
14
15
16

17
18
19
20
21
22
23
24





-
-
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Hebron) {
    {-9223372036854775808 8423 0 LMT}
    {-2185410023 7200 0 EEST}
    {-933645600 10800 1 EEST}
    {-857358000 7200 0 EEST}
    {-933638400 10800 1 EEST}
    {-923097600 7200 0 EEST}
    {-919036800 10800 1 EEST}
    {-857347200 7200 0 EEST}
    {-844300800 10800 1 EEST}
    {-825822000 7200 0 EEST}
    {-812685600 10800 1 EEST}
    {-794199600 7200 0 EEST}
    {-779853600 10800 1 EEST}
    {-762656400 7200 0 EEST}
    {-825811200 7200 0 EEST}
    {-812678400 10800 1 EEST}
    {-794188800 7200 0 EEST}
    {-779846400 10800 1 EEST}
    {-762652800 7200 0 EEST}
    {-748310400 10800 1 EEST}
    {-731127600 7200 0 EEST}
    {-731116800 7200 0 EEST}
    {-682653600 7200 0 EET}
    {-399088800 10800 1 EEST}
    {-386650800 7200 0 EET}
    {-368330400 10800 1 EEST}
    {-355114800 7200 0 EET}
    {-336790800 10800 1 EEST}
    {-323654400 7200 0 EET}
36
37
38
39
40
41
42
43
44
45
46




47
48

49
50
51
52
53
54
55
38
39
40
41
42
43
44




45
46
47
48
49

50
51
52
53
54
55
56
57







-
-
-
-
+
+
+
+

-
+







    {-102643200 7200 0 EET}
    {-84330000 10800 1 EEST}
    {-81313200 10800 0 IST}
    {142376400 10800 1 IDT}
    {150843600 7200 0 IST}
    {167176800 10800 1 IDT}
    {178664400 7200 0 IST}
    {334015200 10800 1 IDT}
    {337644000 7200 0 IST}
    {452556000 10800 1 IDT}
    {462232800 7200 0 IST}
    {334101600 10800 1 IDT}
    {337730400 7200 0 IST}
    {452642400 10800 1 IDT}
    {462319200 7200 0 IST}
    {482277600 10800 1 IDT}
    {495579600 7200 0 IST}
    {494370000 7200 0 IST}
    {516751200 10800 1 IDT}
    {526424400 7200 0 IST}
    {545436000 10800 1 IDT}
    {558478800 7200 0 IST}
    {576626400 10800 1 IDT}
    {589323600 7200 0 IST}
    {609890400 10800 1 IDT}
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

    {1521846000 10800 1 EEST}
    {1540591200 7200 0 EET}
    {1553810400 10800 1 EEST}
    {1572037200 7200 0 EET}
    {1585346400 10800 1 EEST}
    {1603490400 7200 0 EET}
    {1616796000 10800 1 EEST}
    {1635544800 7200 0 EET}
    {1648245600 10800 1 EEST}
    {1666994400 7200 0 EET}
    {1679695200 10800 1 EEST}
    {1698444000 7200 0 EET}
    {1711749600 10800 1 EEST}
    {1729893600 7200 0 EET}
    {1743199200 10800 1 EEST}
    {1761343200 7200 0 EET}
    {1774648800 10800 1 EEST}
    {1792792800 7200 0 EET}
    {1806098400 10800 1 EEST}
    {1824847200 7200 0 EET}
    {1837548000 10800 1 EEST}
    {1856296800 7200 0 EET}
    {1868997600 10800 1 EEST}
    {1887746400 7200 0 EET}
    {1901052000 10800 1 EEST}
    {1919196000 7200 0 EET}
    {1932501600 10800 1 EEST}
    {1950645600 7200 0 EET}
    {1963951200 10800 1 EEST}
    {1982700000 7200 0 EET}
    {1995400800 10800 1 EEST}
    {2014149600 7200 0 EET}
    {2026850400 10800 1 EEST}
    {2045599200 7200 0 EET}
    {2058300000 10800 1 EEST}
    {2077048800 7200 0 EET}
    {2090354400 10800 1 EEST}
    {2108498400 7200 0 EET}
    {2121804000 10800 1 EEST}
    {2139948000 7200 0 EET}
    {2153253600 10800 1 EEST}
    {2172002400 7200 0 EET}
    {2184703200 10800 1 EEST}
    {2203452000 7200 0 EET}
    {2216152800 10800 1 EEST}
    {2234901600 7200 0 EET}
    {2248207200 10800 1 EEST}
    {2266351200 7200 0 EET}
    {2279656800 10800 1 EEST}
    {2297800800 7200 0 EET}
    {2311106400 10800 1 EEST}
    {2329250400 7200 0 EET}
    {2342556000 10800 1 EEST}
    {2361304800 7200 0 EET}
    {2374005600 10800 1 EEST}
    {2392754400 7200 0 EET}
    {2405455200 10800 1 EEST}
    {2424204000 7200 0 EET}
    {2437509600 10800 1 EEST}
    {2455653600 7200 0 EET}
    {2468959200 10800 1 EEST}
    {2487103200 7200 0 EET}
    {2500408800 10800 1 EEST}
    {2519157600 7200 0 EET}
    {2531858400 10800 1 EEST}
    {2550607200 7200 0 EET}
    {2563308000 10800 1 EEST}
    {2582056800 7200 0 EET}
    {2595362400 10800 1 EEST}
    {2613506400 7200 0 EET}
    {2626812000 10800 1 EEST}
    {2644956000 7200 0 EET}
    {2658261600 10800 1 EEST}
    {2676405600 7200 0 EET}
    {2689711200 10800 1 EEST}
    {2708460000 7200 0 EET}
    {2721160800 10800 1 EEST}
    {2739909600 7200 0 EET}
    {2752610400 10800 1 EEST}
    {2771359200 7200 0 EET}
    {2784664800 10800 1 EEST}
    {2802808800 7200 0 EET}
    {2816114400 10800 1 EEST}
    {2834258400 7200 0 EET}
    {2847564000 10800 1 EEST}
    {2866312800 7200 0 EET}
    {2879013600 10800 1 EEST}
    {2897762400 7200 0 EET}
    {2910463200 10800 1 EEST}
    {2929212000 7200 0 EET}
    {2941912800 10800 1 EEST}
    {2960661600 7200 0 EET}
    {2973967200 10800 1 EEST}
    {2992111200 7200 0 EET}
    {3005416800 10800 1 EEST}
    {3023560800 7200 0 EET}
    {3036866400 10800 1 EEST}
    {3055615200 7200 0 EET}
    {3068316000 10800 1 EEST}
    {3087064800 7200 0 EET}
    {3099765600 10800 1 EEST}
    {3118514400 7200 0 EET}
    {3131820000 10800 1 EEST}
    {3149964000 7200 0 EET}
    {3163269600 10800 1 EEST}
    {3181413600 7200 0 EET}
    {3194719200 10800 1 EEST}
    {3212863200 7200 0 EET}
    {3226168800 10800 1 EEST}
    {3244917600 7200 0 EET}
    {3257618400 10800 1 EEST}
    {3276367200 7200 0 EET}
    {3289068000 10800 1 EEST}
    {3307816800 7200 0 EET}
    {3321122400 10800 1 EEST}
    {3339266400 7200 0 EET}
    {3352572000 10800 1 EEST}
    {3370716000 7200 0 EET}
    {3384021600 10800 1 EEST}
    {3402770400 7200 0 EET}
    {3415471200 10800 1 EEST}
    {3434220000 7200 0 EET}
    {3446920800 10800 1 EEST}
    {3465669600 7200 0 EET}
    {3478975200 10800 1 EEST}
    {3497119200 7200 0 EET}
    {3510424800 10800 1 EEST}
    {3528568800 7200 0 EET}
    {3541874400 10800 1 EEST}
    {3560018400 7200 0 EET}
    {3573324000 10800 1 EEST}
    {3592072800 7200 0 EET}
    {3604773600 10800 1 EEST}
    {3623522400 7200 0 EET}
    {3636223200 10800 1 EEST}
    {3654972000 7200 0 EET}
    {3668277600 10800 1 EEST}
    {3686421600 7200 0 EET}
    {3699727200 10800 1 EEST}
    {3717871200 7200 0 EET}
    {3731176800 10800 1 EEST}
    {3749925600 7200 0 EET}
    {3762626400 10800 1 EEST}
    {3781375200 7200 0 EET}
    {3794076000 10800 1 EEST}
    {3812824800 7200 0 EET}
    {3825525600 10800 1 EEST}
    {3844274400 7200 0 EET}
    {3857580000 10800 1 EEST}
    {3875724000 7200 0 EET}
    {3889029600 10800 1 EEST}
    {3907173600 7200 0 EET}
    {3920479200 10800 1 EEST}
    {3939228000 7200 0 EET}
    {3951928800 10800 1 EEST}
    {3970677600 7200 0 EET}
    {3983378400 10800 1 EEST}
    {4002127200 7200 0 EET}
    {4015432800 10800 1 EEST}
    {4033576800 7200 0 EET}
    {4046882400 10800 1 EEST}
    {4065026400 7200 0 EET}
    {4078332000 10800 1 EEST}
    {4096476000 7200 0 EET}
    {1635458400 7200 0 EET}
    {1648332000 10800 1 EEST}
    {1666998000 7200 0 EET}
    {1682726400 10800 1 EEST}
    {1698447600 7200 0 EET}
    {1713571200 10800 1 EEST}
    {1729897200 7200 0 EET}
    {1744416000 10800 1 EEST}
    {1761346800 7200 0 EET}
    {1774656000 10800 1 EEST}
    {1792796400 7200 0 EET}
    {1806105600 10800 1 EEST}
    {1824850800 7200 0 EET}
    {1837555200 10800 1 EEST}
    {1856300400 7200 0 EET}
    {1869004800 10800 1 EEST}
    {1887750000 7200 0 EET}
    {1901059200 10800 1 EEST}
    {1919199600 7200 0 EET}
    {1932508800 10800 1 EEST}
    {1950649200 7200 0 EET}
    {1963958400 10800 1 EEST}
    {1982703600 7200 0 EET}
    {1995408000 10800 1 EEST}
    {2014153200 7200 0 EET}
    {2026857600 10800 1 EEST}
    {2045602800 7200 0 EET}
    {2058307200 10800 1 EEST}
    {2077052400 7200 0 EET}
    {2090361600 10800 1 EEST}
    {2107897200 7200 0 EET}
    {2121811200 10800 1 EEST}
    {2138742000 7200 0 EET}
    {2153260800 10800 1 EEST}
    {2168982000 7200 0 EET}
    {2184710400 10800 1 EEST}
    {2199826800 7200 0 EET}
    {2216160000 10800 1 EEST}
    {2230066800 7200 0 EET}
    {2234304000 10800 1 EEST}
    {2234905200 7200 0 EET}
    {2248214400 10800 1 EEST}
    {2260911600 7200 0 EET}
    {2264544000 10800 1 EEST}
    {2266354800 7200 0 EET}
    {2279664000 10800 1 EEST}
    {2291756400 7200 0 EET}
    {2295388800 10800 1 EEST}
    {2297804400 7200 0 EET}
    {2311113600 10800 1 EEST}
    {2321996400 7200 0 EET}
    {2326233600 10800 1 EEST}
    {2329254000 7200 0 EET}
    {2342563200 10800 1 EEST}
    {2352841200 7200 0 EET}
    {2356473600 10800 1 EEST}
    {2361308400 7200 0 EET}
    {2374012800 10800 1 EEST}
    {2383686000 7200 0 EET}
    {2387318400 10800 1 EEST}
    {2392758000 7200 0 EET}
    {2405462400 10800 1 EEST}
    {2413926000 7200 0 EET}
    {2418163200 10800 1 EEST}
    {2424207600 7200 0 EET}
    {2437516800 10800 1 EEST}
    {2444770800 7200 0 EET}
    {2448403200 10800 1 EEST}
    {2455657200 7200 0 EET}
    {2468966400 10800 1 EEST}
    {2475010800 7200 0 EET}
    {2479248000 10800 1 EEST}
    {2487106800 7200 0 EET}
    {2500416000 10800 1 EEST}
    {2505855600 7200 0 EET}
    {2509488000 10800 1 EEST}
    {2519161200 7200 0 EET}
    {2531865600 10800 1 EEST}
    {2536700400 7200 0 EET}
    {2540332800 10800 1 EEST}
    {2550610800 7200 0 EET}
    {2563315200 10800 1 EEST}
    {2566940400 7200 0 EET}
    {2571177600 10800 1 EEST}
    {2582060400 7200 0 EET}
    {2595369600 10800 1 EEST}
    {2597785200 7200 0 EET}
    {2601417600 10800 1 EEST}
    {2613510000 7200 0 EET}
    {2626819200 10800 1 EEST}
    {2628025200 7200 0 EET}
    {2632262400 10800 1 EEST}
    {2644959600 7200 0 EET}
    {2658268800 10800 1 EEST}
    {2658870000 7200 0 EET}
    {2663107200 10800 1 EEST}
    {2676409200 7200 0 EET}
    {2693347200 10800 1 EEST}
    {2708463600 7200 0 EET}
    {2724192000 10800 1 EEST}
    {2739913200 7200 0 EET}
    {2754432000 10800 1 EEST}
    {2771362800 7200 0 EET}
    {2785276800 10800 1 EEST}
    {2802812400 7200 0 EET}
    {2816121600 10800 1 EEST}
    {2834262000 7200 0 EET}
    {2847571200 10800 1 EEST}
    {2866316400 7200 0 EET}
    {2879020800 10800 1 EEST}
    {2897766000 7200 0 EET}
    {2910470400 10800 1 EEST}
    {2929215600 7200 0 EET}
    {2941920000 10800 1 EEST}
    {2960665200 7200 0 EET}
    {2973974400 10800 1 EEST}
    {2992114800 7200 0 EET}
    {3005424000 10800 1 EEST}
    {3023564400 7200 0 EET}
    {3036873600 10800 1 EEST}
    {3055618800 7200 0 EET}
    {3068323200 10800 1 EEST}
    {3087068400 7200 0 EET}
    {3099772800 10800 1 EEST}
    {3117913200 7200 0 EET}
    {3131827200 10800 1 EEST}
    {3148758000 7200 0 EET}
    {3163276800 10800 1 EEST}
    {3179602800 7200 0 EET}
    {3194726400 10800 1 EEST}
    {3209842800 7200 0 EET}
    {3226176000 10800 1 EEST}
    {3240687600 7200 0 EET}
    {3244320000 10800 1 EEST}
    {3244921200 7200 0 EET}
    {3257625600 10800 1 EEST}
    {3271532400 7200 0 EET}
    {3275164800 10800 1 EEST}
    {3276370800 7200 0 EET}
    {3289075200 10800 1 EEST}
    {3301772400 7200 0 EET}
    {3306009600 10800 1 EEST}
    {3307820400 7200 0 EET}
    {3321129600 10800 1 EEST}
    {3332617200 7200 0 EET}
    {3336249600 10800 1 EEST}
    {3339270000 7200 0 EET}
    {3352579200 10800 1 EEST}
    {3362857200 7200 0 EET}
    {3367094400 10800 1 EEST}
    {3370719600 7200 0 EET}
    {3384028800 10800 1 EEST}
    {3393702000 7200 0 EET}
    {3397939200 10800 1 EEST}
    {3402774000 7200 0 EET}
    {3415478400 10800 1 EEST}
    {3424546800 7200 0 EET}
    {3428179200 10800 1 EEST}
    {3434223600 7200 0 EET}
    {3446928000 10800 1 EEST}
    {3454786800 7200 0 EET}
    {3459024000 10800 1 EEST}
    {3465673200 7200 0 EET}
    {3478982400 10800 1 EEST}
    {3485631600 7200 0 EET}
    {3489264000 10800 1 EEST}
    {3497122800 7200 0 EET}
    {3510432000 10800 1 EEST}
    {3516476400 7200 0 EET}
    {3520108800 10800 1 EEST}
    {3528572400 7200 0 EET}
    {3541881600 10800 1 EEST}
    {3546716400 7200 0 EET}
    {3550953600 10800 1 EEST}
    {3560022000 7200 0 EET}
    {3573331200 10800 1 EEST}
    {3577561200 7200 0 EET}
    {3581193600 10800 1 EEST}
    {3592076400 7200 0 EET}
    {3604780800 10800 1 EEST}
    {3607801200 7200 0 EET}
    {3612038400 10800 1 EEST}
    {3623526000 7200 0 EET}
    {3636230400 10800 1 EEST}
    {3638646000 7200 0 EET}
    {3642883200 10800 1 EEST}
    {3654975600 7200 0 EET}
    {3668284800 10800 1 EEST}
    {3669490800 7200 0 EET}
    {3673123200 10800 1 EEST}
    {3686425200 7200 0 EET}
    {3699734400 10800 1 EEST}
    {3717874800 7200 0 EET}
    {3731184000 10800 1 EEST}
    {3749929200 7200 0 EET}
    {3762633600 10800 1 EEST}
    {3781378800 7200 0 EET}
    {3794083200 10800 1 EEST}
    {3812828400 7200 0 EET}
    {3825532800 10800 1 EEST}
    {3844278000 7200 0 EET}
    {3857587200 10800 1 EEST}
    {3875727600 7200 0 EET}
    {3889036800 10800 1 EEST}
    {3907177200 7200 0 EET}
    {3920486400 10800 1 EEST}
    {3939231600 7200 0 EET}
    {3951936000 10800 1 EEST}
    {3970681200 7200 0 EET}
    {3983385600 10800 1 EEST}
    {4002130800 7200 0 EET}
    {4015440000 10800 1 EEST}
    {4033580400 7200 0 EET}
    {4046889600 10800 1 EEST}
    {4065030000 7200 0 EET}
    {4078339200 10800 1 EEST}
    {4096479600 7200 0 EET}
}

Changes to library/tzdata/Asia/Ho_Chi_Minh.

1
2
3
4
5
6
7
8
9
10
11
12
13










14
1
2
3










4
5
6
7
8
9
10
11
12
13
14



-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Ho_Chi_Minh) {
    {-9223372036854775808 25600 0 LMT}
    {-2004073600 25590 0 PLMT}
    {-1851577590 25200 0 +07}
    {-852105600 28800 0 +08}
    {-782643600 32400 0 +09}
    {-767869200 25200 0 +07}
    {-718095600 28800 0 +08}
    {-457776000 25200 0 +07}
    {-315648000 28800 0 +08}
    {171820800 25200 0 +07}
    {-9223372036854775808 25590 0 LMT}
    {-2004073590 25590 0 PLMT}
    {-1851577590 25200 0 +0700}
    {-852105600 28800 0 +0800}
    {-782643600 32400 0 +0900}
    {-767869200 25200 0 +0700}
    {-718095600 28800 0 +0800}
    {-457772400 25200 0 +0700}
    {-315648000 28800 0 +0800}
    {171820800 25200 0 +0700}
}

Changes to library/tzdata/Asia/Hovd.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Hovd) {
    {-9223372036854775808 21996 0 LMT}
    {-2032927596 21600 0 +06}
    {252439200 25200 0 +07}
    {417978000 28800 1 +07}
    {433785600 25200 0 +07}
    {449600400 28800 1 +07}
    {465321600 25200 0 +07}
    {481050000 28800 1 +07}
    {496771200 25200 0 +07}
    {512499600 28800 1 +07}
    {528220800 25200 0 +07}
    {543949200 28800 1 +07}
    {559670400 25200 0 +07}
    {575398800 28800 1 +07}
    {591120000 25200 0 +07}
    {606848400 28800 1 +07}
    {622569600 25200 0 +07}
    {638298000 28800 1 +07}
    {654624000 25200 0 +07}
    {670352400 28800 1 +07}
    {686073600 25200 0 +07}
    {701802000 28800 1 +07}
    {717523200 25200 0 +07}
    {733251600 28800 1 +07}
    {748972800 25200 0 +07}
    {764701200 28800 1 +07}
    {780422400 25200 0 +07}
    {796150800 28800 1 +07}
    {811872000 25200 0 +07}
    {828205200 28800 1 +07}
    {843926400 25200 0 +07}
    {859654800 28800 1 +07}
    {875376000 25200 0 +07}
    {891104400 28800 1 +07}
    {906825600 25200 0 +07}
    {988398000 28800 1 +07}
    {1001700000 25200 0 +07}
    {1017428400 28800 1 +07}
    {1033149600 25200 0 +07}
    {1048878000 28800 1 +07}
    {1064599200 25200 0 +07}
    {1080327600 28800 1 +07}
    {1096048800 25200 0 +07}
    {1111777200 28800 1 +07}
    {1127498400 25200 0 +07}
    {1143226800 28800 1 +07}
    {1159552800 25200 0 +07}
    {1427482800 28800 1 +07}
    {1443196800 25200 0 +07}
    {1458932400 28800 1 +07}
    {1474646400 25200 0 +07}
    {-2032927596 21600 0 +0600}
    {252439200 25200 0 +0700}
    {417978000 28800 1 +0800}
    {433785600 25200 0 +0700}
    {449600400 28800 1 +0800}
    {465321600 25200 0 +0700}
    {481050000 28800 1 +0800}
    {496771200 25200 0 +0700}
    {512499600 28800 1 +0800}
    {528220800 25200 0 +0700}
    {543949200 28800 1 +0800}
    {559670400 25200 0 +0700}
    {575398800 28800 1 +0800}
    {591120000 25200 0 +0700}
    {606848400 28800 1 +0800}
    {622569600 25200 0 +0700}
    {638298000 28800 1 +0800}
    {654624000 25200 0 +0700}
    {670352400 28800 1 +0800}
    {686073600 25200 0 +0700}
    {701802000 28800 1 +0800}
    {717523200 25200 0 +0700}
    {733251600 28800 1 +0800}
    {748972800 25200 0 +0700}
    {764701200 28800 1 +0800}
    {780422400 25200 0 +0700}
    {796150800 28800 1 +0800}
    {811872000 25200 0 +0700}
    {828205200 28800 1 +0800}
    {843926400 25200 0 +0700}
    {859654800 28800 1 +0800}
    {875376000 25200 0 +0700}
    {891104400 28800 1 +0800}
    {906825600 25200 0 +0700}
    {988398000 28800 1 +0800}
    {1001700000 25200 0 +0700}
    {1017428400 28800 1 +0800}
    {1033149600 25200 0 +0700}
    {1048878000 28800 1 +0800}
    {1064599200 25200 0 +0700}
    {1080327600 28800 1 +0800}
    {1096048800 25200 0 +0700}
    {1111777200 28800 1 +0800}
    {1127498400 25200 0 +0700}
    {1143226800 28800 1 +0800}
    {1159552800 25200 0 +0700}
    {1427482800 28800 1 +0800}
    {1443196800 25200 0 +0700}
    {1458932400 28800 1 +0800}
    {1474646400 25200 0 +0700}
}

Changes to library/tzdata/Asia/Irkutsk.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Irkutsk) {
    {-9223372036854775808 25025 0 LMT}
    {-2840165825 25025 0 IMT}
    {-1575874625 25200 0 +07}
    {-1247554800 28800 0 +09}
    {354902400 32400 1 +09}
    {370710000 28800 0 +08}
    {386438400 32400 1 +09}
    {402246000 28800 0 +08}
    {417974400 32400 1 +09}
    {433782000 28800 0 +08}
    {449596800 32400 1 +09}
    {465328800 28800 0 +08}
    {481053600 32400 1 +09}
    {496778400 28800 0 +08}
    {512503200 32400 1 +09}
    {528228000 28800 0 +08}
    {543952800 32400 1 +09}
    {559677600 28800 0 +08}
    {575402400 32400 1 +09}
    {591127200 28800 0 +08}
    {606852000 32400 1 +09}
    {622576800 28800 0 +08}
    {638301600 32400 1 +09}
    {654631200 28800 0 +08}
    {670356000 25200 0 +08}
    {670359600 28800 1 +08}
    {686084400 25200 0 +07}
    {695761200 28800 0 +09}
    {701805600 32400 1 +09}
    {717530400 28800 0 +08}
    {733255200 32400 1 +09}
    {748980000 28800 0 +08}
    {764704800 32400 1 +09}
    {780429600 28800 0 +08}
    {796154400 32400 1 +09}
    {811879200 28800 0 +08}
    {828208800 32400 1 +09}
    {846352800 28800 0 +08}
    {859658400 32400 1 +09}
    {877802400 28800 0 +08}
    {891108000 32400 1 +09}
    {909252000 28800 0 +08}
    {922557600 32400 1 +09}
    {941306400 28800 0 +08}
    {954007200 32400 1 +09}
    {972756000 28800 0 +08}
    {985456800 32400 1 +09}
    {1004205600 28800 0 +08}
    {1017511200 32400 1 +09}
    {1035655200 28800 0 +08}
    {1048960800 32400 1 +09}
    {1067104800 28800 0 +08}
    {1080410400 32400 1 +09}
    {1099159200 28800 0 +08}
    {1111860000 32400 1 +09}
    {1130608800 28800 0 +08}
    {1143309600 32400 1 +09}
    {1162058400 28800 0 +08}
    {1174759200 32400 1 +09}
    {1193508000 28800 0 +08}
    {1206813600 32400 1 +09}
    {1224957600 28800 0 +08}
    {1238263200 32400 1 +09}
    {1256407200 28800 0 +08}
    {1269712800 32400 1 +09}
    {1288461600 28800 0 +08}
    {1301162400 32400 0 +09}
    {1414256400 28800 0 +08}
    {-1575874625 25200 0 +0700}
    {-1247554800 28800 0 +0800}
    {354902400 32400 1 +0900}
    {370710000 28800 0 +0800}
    {386438400 32400 1 +0900}
    {402246000 28800 0 +0800}
    {417974400 32400 1 +0900}
    {433782000 28800 0 +0800}
    {449596800 32400 1 +0900}
    {465328800 28800 0 +0800}
    {481053600 32400 1 +0900}
    {496778400 28800 0 +0800}
    {512503200 32400 1 +0900}
    {528228000 28800 0 +0800}
    {543952800 32400 1 +0900}
    {559677600 28800 0 +0800}
    {575402400 32400 1 +0900}
    {591127200 28800 0 +0800}
    {606852000 32400 1 +0900}
    {622576800 28800 0 +0800}
    {638301600 32400 1 +0900}
    {654631200 28800 0 +0800}
    {670356000 25200 0 +0700}
    {670359600 28800 1 +0800}
    {686084400 25200 0 +0700}
    {695761200 28800 0 +0800}
    {701805600 32400 1 +0900}
    {717530400 28800 0 +0800}
    {733255200 32400 1 +0900}
    {748980000 28800 0 +0800}
    {764704800 32400 1 +0900}
    {780429600 28800 0 +0800}
    {796154400 32400 1 +0900}
    {811879200 28800 0 +0800}
    {828208800 32400 1 +0900}
    {846352800 28800 0 +0800}
    {859658400 32400 1 +0900}
    {877802400 28800 0 +0800}
    {891108000 32400 1 +0900}
    {909252000 28800 0 +0800}
    {922557600 32400 1 +0900}
    {941306400 28800 0 +0800}
    {954007200 32400 1 +0900}
    {972756000 28800 0 +0800}
    {985456800 32400 1 +0900}
    {1004205600 28800 0 +0800}
    {1017511200 32400 1 +0900}
    {1035655200 28800 0 +0800}
    {1048960800 32400 1 +0900}
    {1067104800 28800 0 +0800}
    {1080410400 32400 1 +0900}
    {1099159200 28800 0 +0800}
    {1111860000 32400 1 +0900}
    {1130608800 28800 0 +0800}
    {1143309600 32400 1 +0900}
    {1162058400 28800 0 +0800}
    {1174759200 32400 1 +0900}
    {1193508000 28800 0 +0800}
    {1206813600 32400 1 +0900}
    {1224957600 28800 0 +0800}
    {1238263200 32400 1 +0900}
    {1256407200 28800 0 +0800}
    {1269712800 32400 1 +0900}
    {1288461600 28800 0 +0800}
    {1301162400 32400 0 +0900}
    {1414256400 28800 0 +0800}
}

Changes to library/tzdata/Asia/Jakarta.

1
2
3
4
5
6
7
8

9
10

11
12
13
1
2
3
4
5
6
7

8
9

10
11
12
13







-
+

-
+



# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Jakarta) {
    {-9223372036854775808 25632 0 LMT}
    {-3231299232 25632 0 BMT}
    {-1451719200 26400 0 +0720}
    {-1172906400 27000 0 +0730}
    {-876641400 32400 0 +09}
    {-876641400 32400 0 +0900}
    {-766054800 27000 0 +0730}
    {-683883000 28800 0 +08}
    {-683883000 28800 0 +0800}
    {-620812800 27000 0 +0730}
    {-189415800 25200 0 WIB}
}

Changes to library/tzdata/Asia/Jayapura.

1
2
3
4
5

6
7
8
1
2
3
4

5
6
7
8




-
+



# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Jayapura) {
    {-9223372036854775808 33768 0 LMT}
    {-1172913768 32400 0 +09}
    {-1172913768 32400 0 +0900}
    {-799491600 34200 0 +0930}
    {-189423000 32400 0 WIT}
}

Changes to library/tzdata/Asia/Jerusalem.

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
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
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
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






-
-
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
+





-
-
-
-
-
+
+
+
+
+

-
-
+
+




-
-
-
-
+
+
+
+

-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Jerusalem) {
    {-9223372036854775808 8454 0 LMT}
    {-2840149254 8440 0 JMT}
    {-1641003640 7200 0 IST}
    {-933645600 10800 1 IDT}
    {-857358000 7200 0 IST}
    {-933638400 10800 1 IDT}
    {-923097600 7200 0 IST}
    {-919036800 10800 1 IDT}
    {-857347200 7200 0 IST}
    {-844300800 10800 1 IDT}
    {-825822000 7200 0 IST}
    {-812685600 10800 1 IDT}
    {-794199600 7200 0 IST}
    {-779853600 10800 1 IDT}
    {-762656400 7200 0 IST}
    {-825811200 7200 0 IST}
    {-812678400 10800 1 IDT}
    {-794188800 7200 0 IST}
    {-779846400 10800 1 IDT}
    {-762652800 7200 0 IST}
    {-748310400 10800 1 IDT}
    {-731127600 7200 0 IST}
    {-681962400 14400 1 IDDT}
    {-673243200 10800 1 IDT}
    {-667962000 7200 0 IST}
    {-652327200 10800 1 IDT}
    {-636426000 7200 0 IST}
    {-622087200 10800 1 IDT}
    {-731116800 7200 0 IST}
    {-681955200 14400 1 IDDT}
    {-673228800 10800 1 IDT}
    {-667958400 7200 0 IST}
    {-652320000 10800 1 IDT}
    {-636422400 7200 0 IST}
    {-622080000 10800 1 IDT}
    {-608947200 7200 0 IST}
    {-591847200 10800 1 IDT}
    {-591840000 10800 1 IDT}
    {-572486400 7200 0 IST}
    {-558576000 10800 1 IDT}
    {-542851200 7200 0 IST}
    {-527731200 10800 1 IDT}
    {-514425600 7200 0 IST}
    {-490845600 10800 1 IDT}
    {-482986800 7200 0 IST}
    {-459475200 10800 1 IDT}
    {-451537200 7200 0 IST}
    {-428551200 10800 1 IDT}
    {-490838400 10800 1 IDT}
    {-482976000 7200 0 IST}
    {-459388800 10800 1 IDT}
    {-451526400 7200 0 IST}
    {-428544000 10800 1 IDT}
    {-418262400 7200 0 IST}
    {-400032000 10800 1 IDT}
    {-387428400 7200 0 IST}
    {-400118400 10800 1 IDT}
    {-387417600 7200 0 IST}
    {142380000 10800 1 IDT}
    {150843600 7200 0 IST}
    {167176800 10800 1 IDT}
    {178664400 7200 0 IST}
    {334015200 10800 1 IDT}
    {337644000 7200 0 IST}
    {452556000 10800 1 IDT}
    {462232800 7200 0 IST}
    {334101600 10800 1 IDT}
    {337730400 7200 0 IST}
    {452642400 10800 1 IDT}
    {462319200 7200 0 IST}
    {482277600 10800 1 IDT}
    {495579600 7200 0 IST}
    {494370000 7200 0 IST}
    {516751200 10800 1 IDT}
    {526424400 7200 0 IST}
    {545436000 10800 1 IDT}
    {558478800 7200 0 IST}
    {576626400 10800 1 IDT}
    {589323600 7200 0 IST}
    {609890400 10800 1 IDT}

Changes to library/tzdata/Asia/Kabul.

1
2
3
4
5

6
7
1
2
3
4

5
6
7




-
+


# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Kabul) {
    {-9223372036854775808 16608 0 LMT}
    {-2524538208 14400 0 +04}
    {-2524538208 14400 0 +0400}
    {-788932800 16200 0 +0430}
}

Changes to library/tzdata/Asia/Kamchatka.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Kamchatka) {
    {-9223372036854775808 38076 0 LMT}
    {-1487759676 39600 0 +11}
    {-1247569200 43200 0 +13}
    {354888000 46800 1 +13}
    {370695600 43200 0 +12}
    {386424000 46800 1 +13}
    {402231600 43200 0 +12}
    {417960000 46800 1 +13}
    {433767600 43200 0 +12}
    {449582400 46800 1 +13}
    {465314400 43200 0 +12}
    {481039200 46800 1 +13}
    {496764000 43200 0 +12}
    {512488800 46800 1 +13}
    {528213600 43200 0 +12}
    {543938400 46800 1 +13}
    {559663200 43200 0 +12}
    {575388000 46800 1 +13}
    {591112800 43200 0 +12}
    {606837600 46800 1 +13}
    {622562400 43200 0 +12}
    {638287200 46800 1 +13}
    {654616800 43200 0 +12}
    {670341600 39600 0 +12}
    {670345200 43200 1 +12}
    {686070000 39600 0 +11}
    {695746800 43200 0 +13}
    {701791200 46800 1 +13}
    {717516000 43200 0 +12}
    {733240800 46800 1 +13}
    {748965600 43200 0 +12}
    {764690400 46800 1 +13}
    {780415200 43200 0 +12}
    {796140000 46800 1 +13}
    {811864800 43200 0 +12}
    {828194400 46800 1 +13}
    {846338400 43200 0 +12}
    {859644000 46800 1 +13}
    {877788000 43200 0 +12}
    {891093600 46800 1 +13}
    {909237600 43200 0 +12}
    {922543200 46800 1 +13}
    {941292000 43200 0 +12}
    {953992800 46800 1 +13}
    {972741600 43200 0 +12}
    {985442400 46800 1 +13}
    {1004191200 43200 0 +12}
    {1017496800 46800 1 +13}
    {1035640800 43200 0 +12}
    {1048946400 46800 1 +13}
    {1067090400 43200 0 +12}
    {1080396000 46800 1 +13}
    {1099144800 43200 0 +12}
    {1111845600 46800 1 +13}
    {1130594400 43200 0 +12}
    {1143295200 46800 1 +13}
    {1162044000 43200 0 +12}
    {1174744800 46800 1 +13}
    {1193493600 43200 0 +12}
    {1206799200 46800 1 +13}
    {1224943200 43200 0 +12}
    {1238248800 46800 1 +13}
    {1256392800 43200 0 +12}
    {1269698400 39600 0 +12}
    {1269702000 43200 1 +12}
    {1288450800 39600 0 +11}
    {1301151600 43200 0 +12}
    {-1487759676 39600 0 +1100}
    {-1247569200 43200 0 +1200}
    {354888000 46800 1 +1300}
    {370695600 43200 0 +1200}
    {386424000 46800 1 +1300}
    {402231600 43200 0 +1200}
    {417960000 46800 1 +1300}
    {433767600 43200 0 +1200}
    {449582400 46800 1 +1300}
    {465314400 43200 0 +1200}
    {481039200 46800 1 +1300}
    {496764000 43200 0 +1200}
    {512488800 46800 1 +1300}
    {528213600 43200 0 +1200}
    {543938400 46800 1 +1300}
    {559663200 43200 0 +1200}
    {575388000 46800 1 +1300}
    {591112800 43200 0 +1200}
    {606837600 46800 1 +1300}
    {622562400 43200 0 +1200}
    {638287200 46800 1 +1300}
    {654616800 43200 0 +1200}
    {670341600 39600 0 +1100}
    {670345200 43200 1 +1200}
    {686070000 39600 0 +1100}
    {695746800 43200 0 +1200}
    {701791200 46800 1 +1300}
    {717516000 43200 0 +1200}
    {733240800 46800 1 +1300}
    {748965600 43200 0 +1200}
    {764690400 46800 1 +1300}
    {780415200 43200 0 +1200}
    {796140000 46800 1 +1300}
    {811864800 43200 0 +1200}
    {828194400 46800 1 +1300}
    {846338400 43200 0 +1200}
    {859644000 46800 1 +1300}
    {877788000 43200 0 +1200}
    {891093600 46800 1 +1300}
    {909237600 43200 0 +1200}
    {922543200 46800 1 +1300}
    {941292000 43200 0 +1200}
    {953992800 46800 1 +1300}
    {972741600 43200 0 +1200}
    {985442400 46800 1 +1300}
    {1004191200 43200 0 +1200}
    {1017496800 46800 1 +1300}
    {1035640800 43200 0 +1200}
    {1048946400 46800 1 +1300}
    {1067090400 43200 0 +1200}
    {1080396000 46800 1 +1300}
    {1099144800 43200 0 +1200}
    {1111845600 46800 1 +1300}
    {1130594400 43200 0 +1200}
    {1143295200 46800 1 +1300}
    {1162044000 43200 0 +1200}
    {1174744800 46800 1 +1300}
    {1193493600 43200 0 +1200}
    {1206799200 46800 1 +1300}
    {1224943200 43200 0 +1200}
    {1238248800 46800 1 +1300}
    {1256392800 43200 0 +1200}
    {1269698400 39600 0 +1100}
    {1269702000 43200 1 +1200}
    {1288450800 39600 0 +1100}
    {1301151600 43200 0 +1200}
}

Changes to library/tzdata/Asia/Karachi.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Karachi) {
    {-9223372036854775808 16092 0 LMT}
    {-1988166492 19800 0 +0530}
    {-862637400 23400 1 +0630}
    {-764145000 19800 0 +0530}
    {-576135000 18000 0 +05}
    {-576135000 18000 0 +0500}
    {38775600 18000 0 PKT}
    {1018119600 21600 1 PKST}
    {1033840800 18000 0 PKT}
    {1212260400 21600 1 PKST}
    {1225476000 18000 0 PKT}
    {1239735600 21600 1 PKST}
    {1257012000 18000 0 PKT}

Changes to library/tzdata/Asia/Khandyga.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Khandyga) {
    {-9223372036854775808 32533 0 LMT}
    {-1579424533 28800 0 +08}
    {-1247558400 32400 0 +10}
    {354898800 36000 1 +10}
    {370706400 32400 0 +09}
    {386434800 36000 1 +10}
    {402242400 32400 0 +09}
    {417970800 36000 1 +10}
    {433778400 32400 0 +09}
    {449593200 36000 1 +10}
    {465325200 32400 0 +09}
    {481050000 36000 1 +10}
    {496774800 32400 0 +09}
    {512499600 36000 1 +10}
    {528224400 32400 0 +09}
    {543949200 36000 1 +10}
    {559674000 32400 0 +09}
    {575398800 36000 1 +10}
    {591123600 32400 0 +09}
    {606848400 36000 1 +10}
    {622573200 32400 0 +09}
    {638298000 36000 1 +10}
    {654627600 32400 0 +09}
    {670352400 28800 0 +09}
    {670356000 32400 1 +09}
    {686080800 28800 0 +08}
    {695757600 32400 0 +10}
    {701802000 36000 1 +10}
    {717526800 32400 0 +09}
    {733251600 36000 1 +10}
    {748976400 32400 0 +09}
    {764701200 36000 1 +10}
    {780426000 32400 0 +09}
    {796150800 36000 1 +10}
    {811875600 32400 0 +09}
    {828205200 36000 1 +10}
    {846349200 32400 0 +09}
    {859654800 36000 1 +10}
    {877798800 32400 0 +09}
    {891104400 36000 1 +10}
    {909248400 32400 0 +09}
    {922554000 36000 1 +10}
    {941302800 32400 0 +09}
    {954003600 36000 1 +10}
    {972752400 32400 0 +09}
    {985453200 36000 1 +10}
    {1004202000 32400 0 +09}
    {1017507600 36000 1 +10}
    {1035651600 32400 0 +09}
    {1048957200 36000 1 +10}
    {1067101200 32400 0 +09}
    {1072882800 36000 0 +11}
    {1080403200 39600 1 +11}
    {1099152000 36000 0 +10}
    {1111852800 39600 1 +11}
    {1130601600 36000 0 +10}
    {1143302400 39600 1 +11}
    {1162051200 36000 0 +10}
    {1174752000 39600 1 +11}
    {1193500800 36000 0 +10}
    {1206806400 39600 1 +11}
    {1224950400 36000 0 +10}
    {1238256000 39600 1 +11}
    {1256400000 36000 0 +10}
    {1269705600 39600 1 +11}
    {1288454400 36000 0 +10}
    {1301155200 39600 0 +11}
    {1315832400 36000 0 +10}
    {1414252800 32400 0 +09}
    {-1579424533 28800 0 +0800}
    {-1247558400 32400 0 +0900}
    {354898800 36000 1 +1000}
    {370706400 32400 0 +0900}
    {386434800 36000 1 +1000}
    {402242400 32400 0 +0900}
    {417970800 36000 1 +1000}
    {433778400 32400 0 +0900}
    {449593200 36000 1 +1000}
    {465325200 32400 0 +0900}
    {481050000 36000 1 +1000}
    {496774800 32400 0 +0900}
    {512499600 36000 1 +1000}
    {528224400 32400 0 +0900}
    {543949200 36000 1 +1000}
    {559674000 32400 0 +0900}
    {575398800 36000 1 +1000}
    {591123600 32400 0 +0900}
    {606848400 36000 1 +1000}
    {622573200 32400 0 +0900}
    {638298000 36000 1 +1000}
    {654627600 32400 0 +0900}
    {670352400 28800 0 +0800}
    {670356000 32400 1 +0900}
    {686080800 28800 0 +0800}
    {695757600 32400 0 +0900}
    {701802000 36000 1 +1000}
    {717526800 32400 0 +0900}
    {733251600 36000 1 +1000}
    {748976400 32400 0 +0900}
    {764701200 36000 1 +1000}
    {780426000 32400 0 +0900}
    {796150800 36000 1 +1000}
    {811875600 32400 0 +0900}
    {828205200 36000 1 +1000}
    {846349200 32400 0 +0900}
    {859654800 36000 1 +1000}
    {877798800 32400 0 +0900}
    {891104400 36000 1 +1000}
    {909248400 32400 0 +0900}
    {922554000 36000 1 +1000}
    {941302800 32400 0 +0900}
    {954003600 36000 1 +1000}
    {972752400 32400 0 +0900}
    {985453200 36000 1 +1000}
    {1004202000 32400 0 +0900}
    {1017507600 36000 1 +1000}
    {1035651600 32400 0 +0900}
    {1048957200 36000 1 +1000}
    {1067101200 32400 0 +0900}
    {1072882800 36000 0 +1000}
    {1080403200 39600 1 +1100}
    {1099152000 36000 0 +1000}
    {1111852800 39600 1 +1100}
    {1130601600 36000 0 +1000}
    {1143302400 39600 1 +1100}
    {1162051200 36000 0 +1000}
    {1174752000 39600 1 +1100}
    {1193500800 36000 0 +1000}
    {1206806400 39600 1 +1100}
    {1224950400 36000 0 +1000}
    {1238256000 39600 1 +1100}
    {1256400000 36000 0 +1000}
    {1269705600 39600 1 +1100}
    {1288454400 36000 0 +1000}
    {1301155200 39600 0 +1100}
    {1315832400 36000 0 +1000}
    {1414252800 32400 0 +0900}
}

Changes to library/tzdata/Asia/Krasnoyarsk.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Krasnoyarsk) {
    {-9223372036854775808 22286 0 LMT}
    {-1577513486 21600 0 +06}
    {-1247551200 25200 0 +08}
    {354906000 28800 1 +08}
    {370713600 25200 0 +07}
    {386442000 28800 1 +08}
    {402249600 25200 0 +07}
    {417978000 28800 1 +08}
    {433785600 25200 0 +07}
    {449600400 28800 1 +08}
    {465332400 25200 0 +07}
    {481057200 28800 1 +08}
    {496782000 25200 0 +07}
    {512506800 28800 1 +08}
    {528231600 25200 0 +07}
    {543956400 28800 1 +08}
    {559681200 25200 0 +07}
    {575406000 28800 1 +08}
    {591130800 25200 0 +07}
    {606855600 28800 1 +08}
    {622580400 25200 0 +07}
    {638305200 28800 1 +08}
    {654634800 25200 0 +07}
    {670359600 21600 0 +07}
    {670363200 25200 1 +07}
    {686088000 21600 0 +06}
    {695764800 25200 0 +08}
    {701809200 28800 1 +08}
    {717534000 25200 0 +07}
    {733258800 28800 1 +08}
    {748983600 25200 0 +07}
    {764708400 28800 1 +08}
    {780433200 25200 0 +07}
    {796158000 28800 1 +08}
    {811882800 25200 0 +07}
    {828212400 28800 1 +08}
    {846356400 25200 0 +07}
    {859662000 28800 1 +08}
    {877806000 25200 0 +07}
    {891111600 28800 1 +08}
    {909255600 25200 0 +07}
    {922561200 28800 1 +08}
    {941310000 25200 0 +07}
    {954010800 28800 1 +08}
    {972759600 25200 0 +07}
    {985460400 28800 1 +08}
    {1004209200 25200 0 +07}
    {1017514800 28800 1 +08}
    {1035658800 25200 0 +07}
    {1048964400 28800 1 +08}
    {1067108400 25200 0 +07}
    {1080414000 28800 1 +08}
    {1099162800 25200 0 +07}
    {1111863600 28800 1 +08}
    {1130612400 25200 0 +07}
    {1143313200 28800 1 +08}
    {1162062000 25200 0 +07}
    {1174762800 28800 1 +08}
    {1193511600 25200 0 +07}
    {1206817200 28800 1 +08}
    {1224961200 25200 0 +07}
    {1238266800 28800 1 +08}
    {1256410800 25200 0 +07}
    {1269716400 28800 1 +08}
    {1288465200 25200 0 +07}
    {1301166000 28800 0 +08}
    {1414260000 25200 0 +07}
    {-1577513486 21600 0 +0600}
    {-1247551200 25200 0 +0700}
    {354906000 28800 1 +0800}
    {370713600 25200 0 +0700}
    {386442000 28800 1 +0800}
    {402249600 25200 0 +0700}
    {417978000 28800 1 +0800}
    {433785600 25200 0 +0700}
    {449600400 28800 1 +0800}
    {465332400 25200 0 +0700}
    {481057200 28800 1 +0800}
    {496782000 25200 0 +0700}
    {512506800 28800 1 +0800}
    {528231600 25200 0 +0700}
    {543956400 28800 1 +0800}
    {559681200 25200 0 +0700}
    {575406000 28800 1 +0800}
    {591130800 25200 0 +0700}
    {606855600 28800 1 +0800}
    {622580400 25200 0 +0700}
    {638305200 28800 1 +0800}
    {654634800 25200 0 +0700}
    {670359600 21600 0 +0600}
    {670363200 25200 1 +0700}
    {686088000 21600 0 +0600}
    {695764800 25200 0 +0700}
    {701809200 28800 1 +0800}
    {717534000 25200 0 +0700}
    {733258800 28800 1 +0800}
    {748983600 25200 0 +0700}
    {764708400 28800 1 +0800}
    {780433200 25200 0 +0700}
    {796158000 28800 1 +0800}
    {811882800 25200 0 +0700}
    {828212400 28800 1 +0800}
    {846356400 25200 0 +0700}
    {859662000 28800 1 +0800}
    {877806000 25200 0 +0700}
    {891111600 28800 1 +0800}
    {909255600 25200 0 +0700}
    {922561200 28800 1 +0800}
    {941310000 25200 0 +0700}
    {954010800 28800 1 +0800}
    {972759600 25200 0 +0700}
    {985460400 28800 1 +0800}
    {1004209200 25200 0 +0700}
    {1017514800 28800 1 +0800}
    {1035658800 25200 0 +0700}
    {1048964400 28800 1 +0800}
    {1067108400 25200 0 +0700}
    {1080414000 28800 1 +0800}
    {1099162800 25200 0 +0700}
    {1111863600 28800 1 +0800}
    {1130612400 25200 0 +0700}
    {1143313200 28800 1 +0800}
    {1162062000 25200 0 +0700}
    {1174762800 28800 1 +0800}
    {1193511600 25200 0 +0700}
    {1206817200 28800 1 +0800}
    {1224961200 25200 0 +0700}
    {1238266800 28800 1 +0800}
    {1256410800 25200 0 +0700}
    {1269716400 28800 1 +0800}
    {1288465200 25200 0 +0700}
    {1301166000 28800 0 +0800}
    {1414260000 25200 0 +0700}
}

Changes to library/tzdata/Asia/Kuala_Lumpur.

1


2
3


4
5
6
7
8
9
10
11
12
13
1
2
3


4
5











+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Asia/Singapore)]} {
    LoadTimeZoneFile Asia/Singapore

set TZData(:Asia/Kuala_Lumpur) {
}
set TZData(:Asia/Kuala_Lumpur) $TZData(:Asia/Singapore)
    {-9223372036854775808 24406 0 LMT}
    {-2177477206 24925 0 SMT}
    {-2038200925 25200 0 +07}
    {-1167634800 26400 1 +0720}
    {-1073028000 26400 0 +0720}
    {-894180000 27000 0 +0730}
    {-879665400 32400 0 +09}
    {-767005200 27000 0 +0730}
    {378664200 28800 0 +08}
}

Changes to library/tzdata/Asia/Kuching.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

















23
1
2
3
4
5

















6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Kuching) {
    {-9223372036854775808 26480 0 LMT}
    {-1383463280 27000 0 +0730}
    {-1167636600 28800 0 +08}
    {-1082448000 30000 1 +08}
    {-1074586800 28800 0 +08}
    {-1050825600 30000 1 +08}
    {-1042964400 28800 0 +08}
    {-1019289600 30000 1 +08}
    {-1011428400 28800 0 +08}
    {-987753600 30000 1 +08}
    {-979892400 28800 0 +08}
    {-956217600 30000 1 +08}
    {-948356400 28800 0 +08}
    {-924595200 30000 1 +08}
    {-916734000 28800 0 +08}
    {-893059200 30000 1 +08}
    {-885198000 28800 0 +08}
    {-879667200 32400 0 +09}
    {-767005200 28800 0 +08}
    {-1167636600 28800 0 +0800}
    {-1082448000 30000 1 +0820}
    {-1074586800 28800 0 +0800}
    {-1050825600 30000 1 +0820}
    {-1042964400 28800 0 +0800}
    {-1019289600 30000 1 +0820}
    {-1011428400 28800 0 +0800}
    {-987753600 30000 1 +0820}
    {-979892400 28800 0 +0800}
    {-956217600 30000 1 +0820}
    {-948356400 28800 0 +0800}
    {-924595200 30000 1 +0820}
    {-916734000 28800 0 +0800}
    {-893059200 30000 1 +0820}
    {-885198000 28800 0 +0800}
    {-879667200 32400 0 +0900}
    {-767005200 28800 0 +0800}
}

Changes to library/tzdata/Asia/Macau.

1
2
3
4
5
6
7
8
9
10





11
12
13
14
15
16
17
1
2
3
4
5





6
7
8
9
10
11
12
13
14
15
16
17





-
-
-
-
-
+
+
+
+
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Macau) {
    {-9223372036854775808 27250 0 LMT}
    {-2056692850 28800 0 CST}
    {-884509200 32400 0 +09}
    {-873280800 36000 1 +09}
    {-855918000 32400 0 +09}
    {-841744800 36000 1 +09}
    {-828529200 32400 0 +10}
    {-884509200 32400 0 +0900}
    {-873280800 36000 1 +1000}
    {-855918000 32400 0 +0900}
    {-841744800 36000 1 +1000}
    {-828529200 32400 0 +0900}
    {-765363600 28800 0 CT}
    {-747046800 32400 1 CDT}
    {-733827600 28800 0 CST}
    {-716461200 32400 1 CDT}
    {-697021200 28800 0 CST}
    {-683715600 32400 1 CDT}
    {-667990800 28800 0 CST}

Changes to library/tzdata/Asia/Magadan.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Magadan) {
    {-9223372036854775808 36192 0 LMT}
    {-1441188192 36000 0 +10}
    {-1247565600 39600 0 +12}
    {354891600 43200 1 +12}
    {370699200 39600 0 +11}
    {386427600 43200 1 +12}
    {402235200 39600 0 +11}
    {417963600 43200 1 +12}
    {433771200 39600 0 +11}
    {449586000 43200 1 +12}
    {465318000 39600 0 +11}
    {481042800 43200 1 +12}
    {496767600 39600 0 +11}
    {512492400 43200 1 +12}
    {528217200 39600 0 +11}
    {543942000 43200 1 +12}
    {559666800 39600 0 +11}
    {575391600 43200 1 +12}
    {591116400 39600 0 +11}
    {606841200 43200 1 +12}
    {622566000 39600 0 +11}
    {638290800 43200 1 +12}
    {654620400 39600 0 +11}
    {670345200 36000 0 +11}
    {670348800 39600 1 +11}
    {686073600 36000 0 +10}
    {695750400 39600 0 +12}
    {701794800 43200 1 +12}
    {717519600 39600 0 +11}
    {733244400 43200 1 +12}
    {748969200 39600 0 +11}
    {764694000 43200 1 +12}
    {780418800 39600 0 +11}
    {796143600 43200 1 +12}
    {811868400 39600 0 +11}
    {828198000 43200 1 +12}
    {846342000 39600 0 +11}
    {859647600 43200 1 +12}
    {877791600 39600 0 +11}
    {891097200 43200 1 +12}
    {909241200 39600 0 +11}
    {922546800 43200 1 +12}
    {941295600 39600 0 +11}
    {953996400 43200 1 +12}
    {972745200 39600 0 +11}
    {985446000 43200 1 +12}
    {1004194800 39600 0 +11}
    {1017500400 43200 1 +12}
    {1035644400 39600 0 +11}
    {1048950000 43200 1 +12}
    {1067094000 39600 0 +11}
    {1080399600 43200 1 +12}
    {1099148400 39600 0 +11}
    {1111849200 43200 1 +12}
    {1130598000 39600 0 +11}
    {1143298800 43200 1 +12}
    {1162047600 39600 0 +11}
    {1174748400 43200 1 +12}
    {1193497200 39600 0 +11}
    {1206802800 43200 1 +12}
    {1224946800 39600 0 +11}
    {1238252400 43200 1 +12}
    {1256396400 39600 0 +11}
    {1269702000 43200 1 +12}
    {1288450800 39600 0 +11}
    {1301151600 43200 0 +12}
    {1414245600 36000 0 +10}
    {1461427200 39600 0 +11}
    {-1441188192 36000 0 +1000}
    {-1247565600 39600 0 +1100}
    {354891600 43200 1 +1200}
    {370699200 39600 0 +1100}
    {386427600 43200 1 +1200}
    {402235200 39600 0 +1100}
    {417963600 43200 1 +1200}
    {433771200 39600 0 +1100}
    {449586000 43200 1 +1200}
    {465318000 39600 0 +1100}
    {481042800 43200 1 +1200}
    {496767600 39600 0 +1100}
    {512492400 43200 1 +1200}
    {528217200 39600 0 +1100}
    {543942000 43200 1 +1200}
    {559666800 39600 0 +1100}
    {575391600 43200 1 +1200}
    {591116400 39600 0 +1100}
    {606841200 43200 1 +1200}
    {622566000 39600 0 +1100}
    {638290800 43200 1 +1200}
    {654620400 39600 0 +1100}
    {670345200 36000 0 +1000}
    {670348800 39600 1 +1100}
    {686073600 36000 0 +1000}
    {695750400 39600 0 +1100}
    {701794800 43200 1 +1200}
    {717519600 39600 0 +1100}
    {733244400 43200 1 +1200}
    {748969200 39600 0 +1100}
    {764694000 43200 1 +1200}
    {780418800 39600 0 +1100}
    {796143600 43200 1 +1200}
    {811868400 39600 0 +1100}
    {828198000 43200 1 +1200}
    {846342000 39600 0 +1100}
    {859647600 43200 1 +1200}
    {877791600 39600 0 +1100}
    {891097200 43200 1 +1200}
    {909241200 39600 0 +1100}
    {922546800 43200 1 +1200}
    {941295600 39600 0 +1100}
    {953996400 43200 1 +1200}
    {972745200 39600 0 +1100}
    {985446000 43200 1 +1200}
    {1004194800 39600 0 +1100}
    {1017500400 43200 1 +1200}
    {1035644400 39600 0 +1100}
    {1048950000 43200 1 +1200}
    {1067094000 39600 0 +1100}
    {1080399600 43200 1 +1200}
    {1099148400 39600 0 +1100}
    {1111849200 43200 1 +1200}
    {1130598000 39600 0 +1100}
    {1143298800 43200 1 +1200}
    {1162047600 39600 0 +1100}
    {1174748400 43200 1 +1200}
    {1193497200 39600 0 +1100}
    {1206802800 43200 1 +1200}
    {1224946800 39600 0 +1100}
    {1238252400 43200 1 +1200}
    {1256396400 39600 0 +1100}
    {1269702000 43200 1 +1200}
    {1288450800 39600 0 +1100}
    {1301151600 43200 0 +1200}
    {1414245600 36000 0 +1000}
    {1461427200 39600 0 +1100}
}

Changes to library/tzdata/Asia/Makassar.

1
2
3
4
5
6
7


8
9
1
2
3
4
5


6
7
8
9





-
-
+
+


# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Makassar) {
    {-9223372036854775808 28656 0 LMT}
    {-1577951856 28656 0 MMT}
    {-1172908656 28800 0 +08}
    {-880272000 32400 0 +09}
    {-1172908656 28800 0 +0800}
    {-880272000 32400 0 +0900}
    {-766054800 28800 0 WITA}
}

Changes to library/tzdata/Asia/Novokuznetsk.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Novokuznetsk) {
    {-9223372036854775808 20928 0 LMT}
    {-1441259328 21600 0 +06}
    {-1247551200 25200 0 +08}
    {354906000 28800 1 +08}
    {370713600 25200 0 +07}
    {386442000 28800 1 +08}
    {402249600 25200 0 +07}
    {417978000 28800 1 +08}
    {433785600 25200 0 +07}
    {449600400 28800 1 +08}
    {465332400 25200 0 +07}
    {481057200 28800 1 +08}
    {496782000 25200 0 +07}
    {512506800 28800 1 +08}
    {528231600 25200 0 +07}
    {543956400 28800 1 +08}
    {559681200 25200 0 +07}
    {575406000 28800 1 +08}
    {591130800 25200 0 +07}
    {606855600 28800 1 +08}
    {622580400 25200 0 +07}
    {638305200 28800 1 +08}
    {654634800 25200 0 +07}
    {670359600 21600 0 +07}
    {670363200 25200 1 +07}
    {686088000 21600 0 +06}
    {695764800 25200 0 +08}
    {701809200 28800 1 +08}
    {717534000 25200 0 +07}
    {733258800 28800 1 +08}
    {748983600 25200 0 +07}
    {764708400 28800 1 +08}
    {780433200 25200 0 +07}
    {796158000 28800 1 +08}
    {811882800 25200 0 +07}
    {828212400 28800 1 +08}
    {846356400 25200 0 +07}
    {859662000 28800 1 +08}
    {877806000 25200 0 +07}
    {891111600 28800 1 +08}
    {909255600 25200 0 +07}
    {922561200 28800 1 +08}
    {941310000 25200 0 +07}
    {954010800 28800 1 +08}
    {972759600 25200 0 +07}
    {985460400 28800 1 +08}
    {1004209200 25200 0 +07}
    {1017514800 28800 1 +08}
    {1035658800 25200 0 +07}
    {1048964400 28800 1 +08}
    {1067108400 25200 0 +07}
    {1080414000 28800 1 +08}
    {1099162800 25200 0 +07}
    {1111863600 28800 1 +08}
    {1130612400 25200 0 +07}
    {1143313200 28800 1 +08}
    {1162062000 25200 0 +07}
    {1174762800 28800 1 +08}
    {1193511600 25200 0 +07}
    {1206817200 28800 1 +08}
    {1224961200 25200 0 +07}
    {1238266800 28800 1 +08}
    {1256410800 25200 0 +07}
    {1269716400 21600 0 +07}
    {1269720000 25200 1 +07}
    {1288468800 21600 0 +06}
    {1301169600 25200 0 +07}
    {-1441259328 21600 0 +0600}
    {-1247551200 25200 0 +0700}
    {354906000 28800 1 +0800}
    {370713600 25200 0 +0700}
    {386442000 28800 1 +0800}
    {402249600 25200 0 +0700}
    {417978000 28800 1 +0800}
    {433785600 25200 0 +0700}
    {449600400 28800 1 +0800}
    {465332400 25200 0 +0700}
    {481057200 28800 1 +0800}
    {496782000 25200 0 +0700}
    {512506800 28800 1 +0800}
    {528231600 25200 0 +0700}
    {543956400 28800 1 +0800}
    {559681200 25200 0 +0700}
    {575406000 28800 1 +0800}
    {591130800 25200 0 +0700}
    {606855600 28800 1 +0800}
    {622580400 25200 0 +0700}
    {638305200 28800 1 +0800}
    {654634800 25200 0 +0700}
    {670359600 21600 0 +0600}
    {670363200 25200 1 +0700}
    {686088000 21600 0 +0600}
    {695764800 25200 0 +0700}
    {701809200 28800 1 +0800}
    {717534000 25200 0 +0700}
    {733258800 28800 1 +0800}
    {748983600 25200 0 +0700}
    {764708400 28800 1 +0800}
    {780433200 25200 0 +0700}
    {796158000 28800 1 +0800}
    {811882800 25200 0 +0700}
    {828212400 28800 1 +0800}
    {846356400 25200 0 +0700}
    {859662000 28800 1 +0800}
    {877806000 25200 0 +0700}
    {891111600 28800 1 +0800}
    {909255600 25200 0 +0700}
    {922561200 28800 1 +0800}
    {941310000 25200 0 +0700}
    {954010800 28800 1 +0800}
    {972759600 25200 0 +0700}
    {985460400 28800 1 +0800}
    {1004209200 25200 0 +0700}
    {1017514800 28800 1 +0800}
    {1035658800 25200 0 +0700}
    {1048964400 28800 1 +0800}
    {1067108400 25200 0 +0700}
    {1080414000 28800 1 +0800}
    {1099162800 25200 0 +0700}
    {1111863600 28800 1 +0800}
    {1130612400 25200 0 +0700}
    {1143313200 28800 1 +0800}
    {1162062000 25200 0 +0700}
    {1174762800 28800 1 +0800}
    {1193511600 25200 0 +0700}
    {1206817200 28800 1 +0800}
    {1224961200 25200 0 +0700}
    {1238266800 28800 1 +0800}
    {1256410800 25200 0 +0700}
    {1269716400 21600 0 +0600}
    {1269720000 25200 1 +0700}
    {1288468800 21600 0 +0600}
    {1301169600 25200 0 +0700}
}

Changes to library/tzdata/Asia/Novosibirsk.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Novosibirsk) {
    {-9223372036854775808 19900 0 LMT}
    {-1579476700 21600 0 +06}
    {-1247551200 25200 0 +08}
    {354906000 28800 1 +08}
    {370713600 25200 0 +07}
    {386442000 28800 1 +08}
    {402249600 25200 0 +07}
    {417978000 28800 1 +08}
    {433785600 25200 0 +07}
    {449600400 28800 1 +08}
    {465332400 25200 0 +07}
    {481057200 28800 1 +08}
    {496782000 25200 0 +07}
    {512506800 28800 1 +08}
    {528231600 25200 0 +07}
    {543956400 28800 1 +08}
    {559681200 25200 0 +07}
    {575406000 28800 1 +08}
    {591130800 25200 0 +07}
    {606855600 28800 1 +08}
    {622580400 25200 0 +07}
    {638305200 28800 1 +08}
    {654634800 25200 0 +07}
    {670359600 21600 0 +07}
    {670363200 25200 1 +07}
    {686088000 21600 0 +06}
    {695764800 25200 0 +08}
    {701809200 28800 1 +08}
    {717534000 25200 0 +07}
    {733258800 28800 1 +08}
    {738090000 25200 0 +07}
    {748987200 21600 0 +06}
    {764712000 25200 1 +07}
    {780436800 21600 0 +06}
    {796161600 25200 1 +07}
    {811886400 21600 0 +06}
    {828216000 25200 1 +07}
    {846360000 21600 0 +06}
    {859665600 25200 1 +07}
    {877809600 21600 0 +06}
    {891115200 25200 1 +07}
    {909259200 21600 0 +06}
    {922564800 25200 1 +07}
    {941313600 21600 0 +06}
    {954014400 25200 1 +07}
    {972763200 21600 0 +06}
    {985464000 25200 1 +07}
    {1004212800 21600 0 +06}
    {1017518400 25200 1 +07}
    {1035662400 21600 0 +06}
    {1048968000 25200 1 +07}
    {1067112000 21600 0 +06}
    {1080417600 25200 1 +07}
    {1099166400 21600 0 +06}
    {1111867200 25200 1 +07}
    {1130616000 21600 0 +06}
    {1143316800 25200 1 +07}
    {1162065600 21600 0 +06}
    {1174766400 25200 1 +07}
    {1193515200 21600 0 +06}
    {1206820800 25200 1 +07}
    {1224964800 21600 0 +06}
    {1238270400 25200 1 +07}
    {1256414400 21600 0 +06}
    {1269720000 25200 1 +07}
    {1288468800 21600 0 +06}
    {1301169600 25200 0 +07}
    {1414263600 21600 0 +06}
    {1469304000 25200 0 +07}
    {-1579476700 21600 0 +0600}
    {-1247551200 25200 0 +0700}
    {354906000 28800 1 +0800}
    {370713600 25200 0 +0700}
    {386442000 28800 1 +0800}
    {402249600 25200 0 +0700}
    {417978000 28800 1 +0800}
    {433785600 25200 0 +0700}
    {449600400 28800 1 +0800}
    {465332400 25200 0 +0700}
    {481057200 28800 1 +0800}
    {496782000 25200 0 +0700}
    {512506800 28800 1 +0800}
    {528231600 25200 0 +0700}
    {543956400 28800 1 +0800}
    {559681200 25200 0 +0700}
    {575406000 28800 1 +0800}
    {591130800 25200 0 +0700}
    {606855600 28800 1 +0800}
    {622580400 25200 0 +0700}
    {638305200 28800 1 +0800}
    {654634800 25200 0 +0700}
    {670359600 21600 0 +0600}
    {670363200 25200 1 +0700}
    {686088000 21600 0 +0600}
    {695764800 25200 0 +0700}
    {701809200 28800 1 +0800}
    {717534000 25200 0 +0700}
    {733258800 28800 1 +0800}
    {738090000 25200 0 +0700}
    {748987200 21600 0 +0600}
    {764712000 25200 1 +0700}
    {780436800 21600 0 +0600}
    {796161600 25200 1 +0700}
    {811886400 21600 0 +0600}
    {828216000 25200 1 +0700}
    {846360000 21600 0 +0600}
    {859665600 25200 1 +0700}
    {877809600 21600 0 +0600}
    {891115200 25200 1 +0700}
    {909259200 21600 0 +0600}
    {922564800 25200 1 +0700}
    {941313600 21600 0 +0600}
    {954014400 25200 1 +0700}
    {972763200 21600 0 +0600}
    {985464000 25200 1 +0700}
    {1004212800 21600 0 +0600}
    {1017518400 25200 1 +0700}
    {1035662400 21600 0 +0600}
    {1048968000 25200 1 +0700}
    {1067112000 21600 0 +0600}
    {1080417600 25200 1 +0700}
    {1099166400 21600 0 +0600}
    {1111867200 25200 1 +0700}
    {1130616000 21600 0 +0600}
    {1143316800 25200 1 +0700}
    {1162065600 21600 0 +0600}
    {1174766400 25200 1 +0700}
    {1193515200 21600 0 +0600}
    {1206820800 25200 1 +0700}
    {1224964800 21600 0 +0600}
    {1238270400 25200 1 +0700}
    {1256414400 21600 0 +0600}
    {1269720000 25200 1 +0700}
    {1288468800 21600 0 +0600}
    {1301169600 25200 0 +0700}
    {1414263600 21600 0 +0600}
    {1469304000 25200 0 +0700}
}

Changes to library/tzdata/Asia/Omsk.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Omsk) {
    {-9223372036854775808 17610 0 LMT}
    {-1582088010 18000 0 +05}
    {-1247547600 21600 0 +07}
    {354909600 25200 1 +07}
    {370717200 21600 0 +06}
    {386445600 25200 1 +07}
    {402253200 21600 0 +06}
    {417981600 25200 1 +07}
    {433789200 21600 0 +06}
    {449604000 25200 1 +07}
    {465336000 21600 0 +06}
    {481060800 25200 1 +07}
    {496785600 21600 0 +06}
    {512510400 25200 1 +07}
    {528235200 21600 0 +06}
    {543960000 25200 1 +07}
    {559684800 21600 0 +06}
    {575409600 25200 1 +07}
    {591134400 21600 0 +06}
    {606859200 25200 1 +07}
    {622584000 21600 0 +06}
    {638308800 25200 1 +07}
    {654638400 21600 0 +06}
    {670363200 18000 0 +06}
    {670366800 21600 1 +06}
    {686091600 18000 0 +05}
    {695768400 21600 0 +07}
    {701812800 25200 1 +07}
    {717537600 21600 0 +06}
    {733262400 25200 1 +07}
    {748987200 21600 0 +06}
    {764712000 25200 1 +07}
    {780436800 21600 0 +06}
    {796161600 25200 1 +07}
    {811886400 21600 0 +06}
    {828216000 25200 1 +07}
    {846360000 21600 0 +06}
    {859665600 25200 1 +07}
    {877809600 21600 0 +06}
    {891115200 25200 1 +07}
    {909259200 21600 0 +06}
    {922564800 25200 1 +07}
    {941313600 21600 0 +06}
    {954014400 25200 1 +07}
    {972763200 21600 0 +06}
    {985464000 25200 1 +07}
    {1004212800 21600 0 +06}
    {1017518400 25200 1 +07}
    {1035662400 21600 0 +06}
    {1048968000 25200 1 +07}
    {1067112000 21600 0 +06}
    {1080417600 25200 1 +07}
    {1099166400 21600 0 +06}
    {1111867200 25200 1 +07}
    {1130616000 21600 0 +06}
    {1143316800 25200 1 +07}
    {1162065600 21600 0 +06}
    {1174766400 25200 1 +07}
    {1193515200 21600 0 +06}
    {1206820800 25200 1 +07}
    {1224964800 21600 0 +06}
    {1238270400 25200 1 +07}
    {1256414400 21600 0 +06}
    {1269720000 25200 1 +07}
    {1288468800 21600 0 +06}
    {1301169600 25200 0 +07}
    {1414263600 21600 0 +06}
    {-1582088010 18000 0 +0500}
    {-1247547600 21600 0 +0600}
    {354909600 25200 1 +0700}
    {370717200 21600 0 +0600}
    {386445600 25200 1 +0700}
    {402253200 21600 0 +0600}
    {417981600 25200 1 +0700}
    {433789200 21600 0 +0600}
    {449604000 25200 1 +0700}
    {465336000 21600 0 +0600}
    {481060800 25200 1 +0700}
    {496785600 21600 0 +0600}
    {512510400 25200 1 +0700}
    {528235200 21600 0 +0600}
    {543960000 25200 1 +0700}
    {559684800 21600 0 +0600}
    {575409600 25200 1 +0700}
    {591134400 21600 0 +0600}
    {606859200 25200 1 +0700}
    {622584000 21600 0 +0600}
    {638308800 25200 1 +0700}
    {654638400 21600 0 +0600}
    {670363200 18000 0 +0500}
    {670366800 21600 1 +0600}
    {686091600 18000 0 +0500}
    {695768400 21600 0 +0600}
    {701812800 25200 1 +0700}
    {717537600 21600 0 +0600}
    {733262400 25200 1 +0700}
    {748987200 21600 0 +0600}
    {764712000 25200 1 +0700}
    {780436800 21600 0 +0600}
    {796161600 25200 1 +0700}
    {811886400 21600 0 +0600}
    {828216000 25200 1 +0700}
    {846360000 21600 0 +0600}
    {859665600 25200 1 +0700}
    {877809600 21600 0 +0600}
    {891115200 25200 1 +0700}
    {909259200 21600 0 +0600}
    {922564800 25200 1 +0700}
    {941313600 21600 0 +0600}
    {954014400 25200 1 +0700}
    {972763200 21600 0 +0600}
    {985464000 25200 1 +0700}
    {1004212800 21600 0 +0600}
    {1017518400 25200 1 +0700}
    {1035662400 21600 0 +0600}
    {1048968000 25200 1 +0700}
    {1067112000 21600 0 +0600}
    {1080417600 25200 1 +0700}
    {1099166400 21600 0 +0600}
    {1111867200 25200 1 +0700}
    {1130616000 21600 0 +0600}
    {1143316800 25200 1 +0700}
    {1162065600 21600 0 +0600}
    {1174766400 25200 1 +0700}
    {1193515200 21600 0 +0600}
    {1206820800 25200 1 +0700}
    {1224964800 21600 0 +0600}
    {1238270400 25200 1 +0700}
    {1256414400 21600 0 +0600}
    {1269720000 25200 1 +0700}
    {1288468800 21600 0 +0600}
    {1301169600 25200 0 +0700}
    {1414263600 21600 0 +0600}
}

Changes to library/tzdata/Asia/Oral.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Oral) {
    {-9223372036854775808 12324 0 LMT}
    {-1441164324 10800 0 +03}
    {-1247540400 18000 0 +05}
    {354913200 21600 1 +06}
    {370720800 21600 0 +06}
    {386445600 18000 0 +05}
    {386449200 21600 1 +05}
    {402256800 18000 0 +05}
    {417985200 21600 1 +05}
    {433792800 18000 0 +05}
    {449607600 21600 1 +05}
    {465339600 18000 0 +05}
    {481064400 21600 1 +05}
    {496789200 18000 0 +05}
    {512514000 21600 1 +05}
    {528238800 18000 0 +05}
    {543963600 21600 1 +05}
    {559688400 18000 0 +05}
    {575413200 21600 1 +05}
    {591138000 18000 0 +05}
    {606862800 14400 0 +04}
    {606866400 18000 1 +04}
    {622591200 14400 0 +04}
    {638316000 18000 1 +04}
    {654645600 14400 0 +04}
    {670370400 18000 1 +04}
    {686095200 14400 0 +04}
    {701816400 14400 0 +04}
    {701820000 18000 1 +04}
    {717544800 14400 0 +04}
    {733269600 18000 1 +04}
    {748994400 14400 0 +04}
    {764719200 18000 1 +04}
    {780444000 14400 0 +04}
    {796168800 18000 1 +04}
    {811893600 14400 0 +04}
    {828223200 18000 1 +04}
    {846367200 14400 0 +04}
    {859672800 18000 1 +04}
    {877816800 14400 0 +04}
    {891122400 18000 1 +04}
    {909266400 14400 0 +04}
    {922572000 18000 1 +04}
    {941320800 14400 0 +04}
    {954021600 18000 1 +04}
    {972770400 14400 0 +04}
    {985471200 18000 1 +04}
    {1004220000 14400 0 +04}
    {1017525600 18000 1 +04}
    {1035669600 14400 0 +04}
    {1048975200 18000 1 +04}
    {1067119200 14400 0 +04}
    {1080424800 18000 1 +04}
    {1099173600 18000 0 +05}
    {-1441164324 10800 0 +0300}
    {-1247540400 18000 0 +0500}
    {354913200 21600 1 +0600}
    {370720800 21600 0 +0600}
    {386445600 18000 0 +0500}
    {386449200 21600 1 +0600}
    {402256800 18000 0 +0500}
    {417985200 21600 1 +0600}
    {433792800 18000 0 +0500}
    {449607600 21600 1 +0600}
    {465339600 18000 0 +0500}
    {481064400 21600 1 +0600}
    {496789200 18000 0 +0500}
    {512514000 21600 1 +0600}
    {528238800 18000 0 +0500}
    {543963600 21600 1 +0600}
    {559688400 18000 0 +0500}
    {575413200 21600 1 +0600}
    {591138000 18000 0 +0500}
    {606862800 14400 0 +0400}
    {606866400 18000 1 +0500}
    {622591200 14400 0 +0400}
    {638316000 18000 1 +0500}
    {654645600 14400 0 +0400}
    {670370400 18000 1 +0500}
    {686095200 14400 0 +0400}
    {701816400 14400 0 +0400}
    {701820000 18000 1 +0500}
    {717544800 14400 0 +0400}
    {733269600 18000 1 +0500}
    {748994400 14400 0 +0400}
    {764719200 18000 1 +0500}
    {780444000 14400 0 +0400}
    {796168800 18000 1 +0500}
    {811893600 14400 0 +0400}
    {828223200 18000 1 +0500}
    {846367200 14400 0 +0400}
    {859672800 18000 1 +0500}
    {877816800 14400 0 +0400}
    {891122400 18000 1 +0500}
    {909266400 14400 0 +0400}
    {922572000 18000 1 +0500}
    {941320800 14400 0 +0400}
    {954021600 18000 1 +0500}
    {972770400 14400 0 +0400}
    {985471200 18000 1 +0500}
    {1004220000 14400 0 +0400}
    {1017525600 18000 1 +0500}
    {1035669600 14400 0 +0400}
    {1048975200 18000 1 +0500}
    {1067119200 14400 0 +0400}
    {1080424800 18000 1 +0500}
    {1099173600 18000 0 +0500}
}

Changes to library/tzdata/Asia/Pontianak.

1
2
3
4
5
6
7

8
9

10
11
12
13
1
2
3
4
5
6

7
8

9
10
11
12
13






-
+

-
+




# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Pontianak) {
    {-9223372036854775808 26240 0 LMT}
    {-1946186240 26240 0 PMT}
    {-1172906240 27000 0 +0730}
    {-881220600 32400 0 +09}
    {-881220600 32400 0 +0900}
    {-766054800 27000 0 +0730}
    {-683883000 28800 0 +08}
    {-683883000 28800 0 +0800}
    {-620812800 27000 0 +0730}
    {-189415800 28800 0 WITA}
    {567964800 25200 0 WIB}
}

Changes to library/tzdata/Asia/Qatar.

1
2
3
4
5
6


7
1
2
3
4


5
6
7




-
-
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Qatar) {
    {-9223372036854775808 12368 0 LMT}
    {-1577935568 14400 0 +04}
    {76190400 10800 0 +03}
    {-1577935568 14400 0 +0400}
    {76190400 10800 0 +0300}
}

Changes to library/tzdata/Asia/Qostanay.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Qostanay) {
    {-9223372036854775808 15268 0 LMT}
    {-1441167268 14400 0 +04}
    {-1247544000 18000 0 +05}
    {354913200 21600 1 +06}
    {370720800 21600 0 +06}
    {386445600 18000 0 +05}
    {386449200 21600 1 +05}
    {402256800 18000 0 +05}
    {417985200 21600 1 +05}
    {433792800 18000 0 +05}
    {449607600 21600 1 +05}
    {465339600 18000 0 +05}
    {481064400 21600 1 +05}
    {496789200 18000 0 +05}
    {512514000 21600 1 +05}
    {528238800 18000 0 +05}
    {543963600 21600 1 +05}
    {559688400 18000 0 +05}
    {575413200 21600 1 +05}
    {591138000 18000 0 +05}
    {606862800 21600 1 +05}
    {622587600 18000 0 +05}
    {638312400 21600 1 +05}
    {654642000 18000 0 +05}
    {670366800 14400 0 +04}
    {670370400 18000 1 +04}
    {686095200 14400 0 +04}
    {695772000 18000 0 +05}
    {701816400 21600 1 +05}
    {717541200 18000 0 +05}
    {733266000 21600 1 +05}
    {748990800 18000 0 +05}
    {764715600 21600 1 +05}
    {780440400 18000 0 +05}
    {796165200 21600 1 +05}
    {811890000 18000 0 +05}
    {828219600 21600 1 +05}
    {846363600 18000 0 +05}
    {859669200 21600 1 +05}
    {877813200 18000 0 +05}
    {891118800 21600 1 +05}
    {909262800 18000 0 +05}
    {922568400 21600 1 +05}
    {941317200 18000 0 +05}
    {954018000 21600 1 +05}
    {972766800 18000 0 +05}
    {985467600 21600 1 +05}
    {1004216400 18000 0 +05}
    {1017522000 21600 1 +05}
    {1035666000 18000 0 +05}
    {1048971600 21600 1 +05}
    {1067115600 18000 0 +05}
    {1080421200 21600 1 +05}
    {1099170000 21600 0 +06}
    {-1441167268 14400 0 +0400}
    {-1247544000 18000 0 +0500}
    {354913200 21600 1 +0600}
    {370720800 21600 0 +0600}
    {386445600 18000 0 +0500}
    {386449200 21600 1 +0600}
    {402256800 18000 0 +0500}
    {417985200 21600 1 +0600}
    {433792800 18000 0 +0500}
    {449607600 21600 1 +0600}
    {465339600 18000 0 +0500}
    {481064400 21600 1 +0600}
    {496789200 18000 0 +0500}
    {512514000 21600 1 +0600}
    {528238800 18000 0 +0500}
    {543963600 21600 1 +0600}
    {559688400 18000 0 +0500}
    {575413200 21600 1 +0600}
    {591138000 18000 0 +0500}
    {606862800 21600 1 +0600}
    {622587600 18000 0 +0500}
    {638312400 21600 1 +0600}
    {654642000 18000 0 +0500}
    {670366800 14400 0 +0400}
    {670370400 18000 1 +0500}
    {686095200 14400 0 +0400}
    {695772000 18000 0 +0500}
    {701816400 21600 1 +0600}
    {717541200 18000 0 +0500}
    {733266000 21600 1 +0600}
    {748990800 18000 0 +0500}
    {764715600 21600 1 +0600}
    {780440400 18000 0 +0500}
    {796165200 21600 1 +0600}
    {811890000 18000 0 +0500}
    {828219600 21600 1 +0600}
    {846363600 18000 0 +0500}
    {859669200 21600 1 +0600}
    {877813200 18000 0 +0500}
    {891118800 21600 1 +0600}
    {909262800 18000 0 +0500}
    {922568400 21600 1 +0600}
    {941317200 18000 0 +0500}
    {954018000 21600 1 +0600}
    {972766800 18000 0 +0500}
    {985467600 21600 1 +0600}
    {1004216400 18000 0 +0500}
    {1017522000 21600 1 +0600}
    {1035666000 18000 0 +0500}
    {1048971600 21600 1 +0600}
    {1067115600 18000 0 +0500}
    {1080421200 21600 1 +0600}
    {1099170000 21600 0 +0600}
    {1709229600 18000 0 +0500}
}

Changes to library/tzdata/Asia/Qyzylorda.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Qyzylorda) {
    {-9223372036854775808 15712 0 LMT}
    {-1441167712 14400 0 +04}
    {-1247544000 18000 0 +05}
    {354913200 21600 1 +06}
    {370720800 21600 0 +06}
    {386445600 18000 0 +05}
    {386449200 21600 1 +05}
    {402256800 18000 0 +05}
    {417985200 21600 1 +05}
    {433792800 18000 0 +05}
    {449607600 21600 1 +05}
    {465339600 18000 0 +05}
    {481064400 21600 1 +05}
    {496789200 18000 0 +05}
    {512514000 21600 1 +05}
    {528238800 18000 0 +05}
    {543963600 21600 1 +05}
    {559688400 18000 0 +05}
    {575413200 21600 1 +05}
    {591138000 18000 0 +05}
    {606862800 21600 1 +05}
    {622587600 18000 0 +05}
    {638312400 21600 1 +05}
    {654642000 18000 0 +05}
    {670366800 14400 0 +04}
    {670370400 18000 1 +04}
    {701812800 18000 0 +05}
    {701816400 21600 1 +05}
    {717541200 18000 0 +05}
    {733266000 21600 1 +05}
    {748990800 18000 0 +05}
    {764715600 21600 1 +05}
    {780440400 18000 0 +05}
    {796165200 21600 1 +05}
    {811890000 18000 0 +05}
    {828219600 21600 1 +05}
    {846363600 18000 0 +05}
    {859669200 21600 1 +05}
    {877813200 18000 0 +05}
    {891118800 21600 1 +05}
    {909262800 18000 0 +05}
    {922568400 21600 1 +05}
    {941317200 18000 0 +05}
    {954018000 21600 1 +05}
    {972766800 18000 0 +05}
    {985467600 21600 1 +05}
    {1004216400 18000 0 +05}
    {1017522000 21600 1 +05}
    {1035666000 18000 0 +05}
    {1048971600 21600 1 +05}
    {1067115600 18000 0 +05}
    {1080421200 21600 1 +05}
    {1099170000 21600 0 +06}
    {1545328800 18000 0 +05}
    {-1441167712 14400 0 +0400}
    {-1247544000 18000 0 +0500}
    {354913200 21600 1 +0600}
    {370720800 21600 0 +0600}
    {386445600 18000 0 +0500}
    {386449200 21600 1 +0600}
    {402256800 18000 0 +0500}
    {417985200 21600 1 +0600}
    {433792800 18000 0 +0500}
    {449607600 21600 1 +0600}
    {465339600 18000 0 +0500}
    {481064400 21600 1 +0600}
    {496789200 18000 0 +0500}
    {512514000 21600 1 +0600}
    {528238800 18000 0 +0500}
    {543963600 21600 1 +0600}
    {559688400 18000 0 +0500}
    {575413200 21600 1 +0600}
    {591138000 18000 0 +0500}
    {606862800 21600 1 +0600}
    {622587600 18000 0 +0500}
    {638312400 21600 1 +0600}
    {654642000 18000 0 +0500}
    {670366800 14400 0 +0400}
    {670370400 18000 1 +0500}
    {701812800 18000 0 +0500}
    {701816400 21600 1 +0600}
    {717541200 18000 0 +0500}
    {733266000 21600 1 +0600}
    {748990800 18000 0 +0500}
    {764715600 21600 1 +0600}
    {780440400 18000 0 +0500}
    {796165200 21600 1 +0600}
    {811890000 18000 0 +0500}
    {828219600 21600 1 +0600}
    {846363600 18000 0 +0500}
    {859669200 21600 1 +0600}
    {877813200 18000 0 +0500}
    {891118800 21600 1 +0600}
    {909262800 18000 0 +0500}
    {922568400 21600 1 +0600}
    {941317200 18000 0 +0500}
    {954018000 21600 1 +0600}
    {972766800 18000 0 +0500}
    {985467600 21600 1 +0600}
    {1004216400 18000 0 +0500}
    {1017522000 21600 1 +0600}
    {1035666000 18000 0 +0500}
    {1048971600 21600 1 +0600}
    {1067115600 18000 0 +0500}
    {1080421200 21600 1 +0600}
    {1099170000 21600 0 +0600}
    {1545328800 18000 0 +0500}
}

Changes to library/tzdata/Asia/Riyadh.

1
2
3
4
5

6
1
2
3
4

5
6




-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Riyadh) {
    {-9223372036854775808 11212 0 LMT}
    {-719636812 10800 0 +03}
    {-719636812 10800 0 +0300}
}

Changes to library/tzdata/Asia/Sakhalin.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Sakhalin) {
    {-9223372036854775808 34248 0 LMT}
    {-2031039048 32400 0 +09}
    {-768560400 39600 0 +12}
    {354891600 43200 1 +12}
    {370699200 39600 0 +11}
    {386427600 43200 1 +12}
    {402235200 39600 0 +11}
    {417963600 43200 1 +12}
    {433771200 39600 0 +11}
    {449586000 43200 1 +12}
    {465318000 39600 0 +11}
    {481042800 43200 1 +12}
    {496767600 39600 0 +11}
    {512492400 43200 1 +12}
    {528217200 39600 0 +11}
    {543942000 43200 1 +12}
    {559666800 39600 0 +11}
    {575391600 43200 1 +12}
    {591116400 39600 0 +11}
    {606841200 43200 1 +12}
    {622566000 39600 0 +11}
    {638290800 43200 1 +12}
    {654620400 39600 0 +11}
    {670345200 36000 0 +11}
    {670348800 39600 1 +11}
    {686073600 36000 0 +10}
    {695750400 39600 0 +12}
    {701794800 43200 1 +12}
    {717519600 39600 0 +11}
    {733244400 43200 1 +12}
    {748969200 39600 0 +11}
    {764694000 43200 1 +12}
    {780418800 39600 0 +11}
    {796143600 43200 1 +12}
    {811868400 39600 0 +11}
    {828198000 43200 1 +12}
    {846342000 39600 0 +11}
    {859647600 36000 0 +11}
    {859651200 39600 1 +11}
    {877795200 36000 0 +10}
    {891100800 39600 1 +11}
    {909244800 36000 0 +10}
    {922550400 39600 1 +11}
    {941299200 36000 0 +10}
    {954000000 39600 1 +11}
    {972748800 36000 0 +10}
    {985449600 39600 1 +11}
    {1004198400 36000 0 +10}
    {1017504000 39600 1 +11}
    {1035648000 36000 0 +10}
    {1048953600 39600 1 +11}
    {1067097600 36000 0 +10}
    {1080403200 39600 1 +11}
    {1099152000 36000 0 +10}
    {1111852800 39600 1 +11}
    {1130601600 36000 0 +10}
    {1143302400 39600 1 +11}
    {1162051200 36000 0 +10}
    {1174752000 39600 1 +11}
    {1193500800 36000 0 +10}
    {1206806400 39600 1 +11}
    {1224950400 36000 0 +10}
    {1238256000 39600 1 +11}
    {1256400000 36000 0 +10}
    {1269705600 39600 1 +11}
    {1288454400 36000 0 +10}
    {1301155200 39600 0 +11}
    {1414249200 36000 0 +10}
    {1459008000 39600 0 +11}
    {-2031039048 32400 0 +0900}
    {-768560400 39600 0 +1100}
    {354891600 43200 1 +1200}
    {370699200 39600 0 +1100}
    {386427600 43200 1 +1200}
    {402235200 39600 0 +1100}
    {417963600 43200 1 +1200}
    {433771200 39600 0 +1100}
    {449586000 43200 1 +1200}
    {465318000 39600 0 +1100}
    {481042800 43200 1 +1200}
    {496767600 39600 0 +1100}
    {512492400 43200 1 +1200}
    {528217200 39600 0 +1100}
    {543942000 43200 1 +1200}
    {559666800 39600 0 +1100}
    {575391600 43200 1 +1200}
    {591116400 39600 0 +1100}
    {606841200 43200 1 +1200}
    {622566000 39600 0 +1100}
    {638290800 43200 1 +1200}
    {654620400 39600 0 +1100}
    {670345200 36000 0 +1000}
    {670348800 39600 1 +1100}
    {686073600 36000 0 +1000}
    {695750400 39600 0 +1100}
    {701794800 43200 1 +1200}
    {717519600 39600 0 +1100}
    {733244400 43200 1 +1200}
    {748969200 39600 0 +1100}
    {764694000 43200 1 +1200}
    {780418800 39600 0 +1100}
    {796143600 43200 1 +1200}
    {811868400 39600 0 +1100}
    {828198000 43200 1 +1200}
    {846342000 39600 0 +1100}
    {859647600 36000 0 +1000}
    {859651200 39600 1 +1100}
    {877795200 36000 0 +1000}
    {891100800 39600 1 +1100}
    {909244800 36000 0 +1000}
    {922550400 39600 1 +1100}
    {941299200 36000 0 +1000}
    {954000000 39600 1 +1100}
    {972748800 36000 0 +1000}
    {985449600 39600 1 +1100}
    {1004198400 36000 0 +1000}
    {1017504000 39600 1 +1100}
    {1035648000 36000 0 +1000}
    {1048953600 39600 1 +1100}
    {1067097600 36000 0 +1000}
    {1080403200 39600 1 +1100}
    {1099152000 36000 0 +1000}
    {1111852800 39600 1 +1100}
    {1130601600 36000 0 +1000}
    {1143302400 39600 1 +1100}
    {1162051200 36000 0 +1000}
    {1174752000 39600 1 +1100}
    {1193500800 36000 0 +1000}
    {1206806400 39600 1 +1100}
    {1224950400 36000 0 +1000}
    {1238256000 39600 1 +1100}
    {1256400000 36000 0 +1000}
    {1269705600 39600 1 +1100}
    {1288454400 36000 0 +1000}
    {1301155200 39600 0 +1100}
    {1414249200 36000 0 +1000}
    {1459008000 39600 0 +1100}
}

Changes to library/tzdata/Asia/Samarkand.

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
30


























31
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
30
31




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Samarkand) {
    {-9223372036854775808 16073 0 LMT}
    {-1441168073 14400 0 +04}
    {-1247544000 18000 0 +05}
    {354913200 21600 1 +06}
    {370720800 21600 0 +06}
    {386445600 18000 0 +05}
    {386449200 21600 1 +05}
    {402256800 18000 0 +05}
    {417985200 21600 1 +05}
    {433792800 18000 0 +05}
    {449607600 21600 1 +05}
    {465339600 18000 0 +05}
    {481064400 21600 1 +05}
    {496789200 18000 0 +05}
    {512514000 21600 1 +05}
    {528238800 18000 0 +05}
    {543963600 21600 1 +05}
    {559688400 18000 0 +05}
    {575413200 21600 1 +05}
    {591138000 18000 0 +05}
    {606862800 21600 1 +05}
    {622587600 18000 0 +05}
    {638312400 21600 1 +05}
    {654642000 18000 0 +05}
    {670366800 21600 1 +05}
    {686091600 18000 0 +05}
    {694206000 18000 0 +05}
    {-1441168073 14400 0 +0400}
    {-1247544000 18000 0 +0500}
    {354913200 21600 1 +0600}
    {370720800 21600 0 +0600}
    {386445600 18000 0 +0500}
    {386449200 21600 1 +0600}
    {402256800 18000 0 +0500}
    {417985200 21600 1 +0600}
    {433792800 18000 0 +0500}
    {449607600 21600 1 +0600}
    {465339600 18000 0 +0500}
    {481064400 21600 1 +0600}
    {496789200 18000 0 +0500}
    {512514000 21600 1 +0600}
    {528238800 18000 0 +0500}
    {543963600 21600 1 +0600}
    {559688400 18000 0 +0500}
    {575413200 21600 1 +0600}
    {591138000 18000 0 +0500}
    {606862800 21600 1 +0600}
    {622587600 18000 0 +0500}
    {638312400 21600 1 +0600}
    {654642000 18000 0 +0500}
    {670366800 21600 1 +0600}
    {686091600 18000 0 +0500}
    {694206000 18000 0 +0500}
}

Changes to library/tzdata/Asia/Singapore.

1
2
3
4
5
6

7
8
9
10

11
12

13
1
2
3
4
5

6
7
8
9

10
11

12
13





-
+



-
+

-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Singapore) {
    {-9223372036854775808 24925 0 LMT}
    {-2177477725 24925 0 SMT}
    {-2038200925 25200 0 +07}
    {-2038200925 25200 0 +0700}
    {-1167634800 26400 1 +0720}
    {-1073028000 26400 0 +0720}
    {-894180000 27000 0 +0730}
    {-879665400 32400 0 +09}
    {-879665400 32400 0 +0900}
    {-767005200 27000 0 +0730}
    {378664200 28800 0 +08}
    {378662400 28800 0 +0800}
}

Changes to library/tzdata/Asia/Srednekolymsk.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Srednekolymsk) {
    {-9223372036854775808 36892 0 LMT}
    {-1441188892 36000 0 +10}
    {-1247565600 39600 0 +12}
    {354891600 43200 1 +12}
    {370699200 39600 0 +11}
    {386427600 43200 1 +12}
    {402235200 39600 0 +11}
    {417963600 43200 1 +12}
    {433771200 39600 0 +11}
    {449586000 43200 1 +12}
    {465318000 39600 0 +11}
    {481042800 43200 1 +12}
    {496767600 39600 0 +11}
    {512492400 43200 1 +12}
    {528217200 39600 0 +11}
    {543942000 43200 1 +12}
    {559666800 39600 0 +11}
    {575391600 43200 1 +12}
    {591116400 39600 0 +11}
    {606841200 43200 1 +12}
    {622566000 39600 0 +11}
    {638290800 43200 1 +12}
    {654620400 39600 0 +11}
    {670345200 36000 0 +11}
    {670348800 39600 1 +11}
    {686073600 36000 0 +10}
    {695750400 39600 0 +12}
    {701794800 43200 1 +12}
    {717519600 39600 0 +11}
    {733244400 43200 1 +12}
    {748969200 39600 0 +11}
    {764694000 43200 1 +12}
    {780418800 39600 0 +11}
    {796143600 43200 1 +12}
    {811868400 39600 0 +11}
    {828198000 43200 1 +12}
    {846342000 39600 0 +11}
    {859647600 43200 1 +12}
    {877791600 39600 0 +11}
    {891097200 43200 1 +12}
    {909241200 39600 0 +11}
    {922546800 43200 1 +12}
    {941295600 39600 0 +11}
    {953996400 43200 1 +12}
    {972745200 39600 0 +11}
    {985446000 43200 1 +12}
    {1004194800 39600 0 +11}
    {1017500400 43200 1 +12}
    {1035644400 39600 0 +11}
    {1048950000 43200 1 +12}
    {1067094000 39600 0 +11}
    {1080399600 43200 1 +12}
    {1099148400 39600 0 +11}
    {1111849200 43200 1 +12}
    {1130598000 39600 0 +11}
    {1143298800 43200 1 +12}
    {1162047600 39600 0 +11}
    {1174748400 43200 1 +12}
    {1193497200 39600 0 +11}
    {1206802800 43200 1 +12}
    {1224946800 39600 0 +11}
    {1238252400 43200 1 +12}
    {1256396400 39600 0 +11}
    {1269702000 43200 1 +12}
    {1288450800 39600 0 +11}
    {1301151600 43200 0 +12}
    {1414245600 39600 0 +11}
    {-1441188892 36000 0 +1000}
    {-1247565600 39600 0 +1100}
    {354891600 43200 1 +1200}
    {370699200 39600 0 +1100}
    {386427600 43200 1 +1200}
    {402235200 39600 0 +1100}
    {417963600 43200 1 +1200}
    {433771200 39600 0 +1100}
    {449586000 43200 1 +1200}
    {465318000 39600 0 +1100}
    {481042800 43200 1 +1200}
    {496767600 39600 0 +1100}
    {512492400 43200 1 +1200}
    {528217200 39600 0 +1100}
    {543942000 43200 1 +1200}
    {559666800 39600 0 +1100}
    {575391600 43200 1 +1200}
    {591116400 39600 0 +1100}
    {606841200 43200 1 +1200}
    {622566000 39600 0 +1100}
    {638290800 43200 1 +1200}
    {654620400 39600 0 +1100}
    {670345200 36000 0 +1000}
    {670348800 39600 1 +1100}
    {686073600 36000 0 +1000}
    {695750400 39600 0 +1100}
    {701794800 43200 1 +1200}
    {717519600 39600 0 +1100}
    {733244400 43200 1 +1200}
    {748969200 39600 0 +1100}
    {764694000 43200 1 +1200}
    {780418800 39600 0 +1100}
    {796143600 43200 1 +1200}
    {811868400 39600 0 +1100}
    {828198000 43200 1 +1200}
    {846342000 39600 0 +1100}
    {859647600 43200 1 +1200}
    {877791600 39600 0 +1100}
    {891097200 43200 1 +1200}
    {909241200 39600 0 +1100}
    {922546800 43200 1 +1200}
    {941295600 39600 0 +1100}
    {953996400 43200 1 +1200}
    {972745200 39600 0 +1100}
    {985446000 43200 1 +1200}
    {1004194800 39600 0 +1100}
    {1017500400 43200 1 +1200}
    {1035644400 39600 0 +1100}
    {1048950000 43200 1 +1200}
    {1067094000 39600 0 +1100}
    {1080399600 43200 1 +1200}
    {1099148400 39600 0 +1100}
    {1111849200 43200 1 +1200}
    {1130598000 39600 0 +1100}
    {1143298800 43200 1 +1200}
    {1162047600 39600 0 +1100}
    {1174748400 43200 1 +1200}
    {1193497200 39600 0 +1100}
    {1206802800 43200 1 +1200}
    {1224946800 39600 0 +1100}
    {1238252400 43200 1 +1200}
    {1256396400 39600 0 +1100}
    {1269702000 43200 1 +1200}
    {1288450800 39600 0 +1100}
    {1301151600 43200 0 +1200}
    {1414245600 39600 0 +1100}
}

Changes to library/tzdata/Asia/Tashkent.

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
30


























31
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
30
31




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Tashkent) {
    {-9223372036854775808 16631 0 LMT}
    {-1441168631 18000 0 +05}
    {-1247547600 21600 0 +06}
    {354909600 25200 1 +06}
    {370717200 21600 0 +06}
    {386445600 25200 1 +06}
    {402253200 21600 0 +06}
    {417981600 25200 1 +06}
    {433789200 21600 0 +06}
    {449604000 25200 1 +06}
    {465336000 21600 0 +06}
    {481060800 25200 1 +06}
    {496785600 21600 0 +06}
    {512510400 25200 1 +06}
    {528235200 21600 0 +06}
    {543960000 25200 1 +06}
    {559684800 21600 0 +06}
    {575409600 25200 1 +06}
    {591134400 21600 0 +06}
    {606859200 25200 1 +06}
    {622584000 21600 0 +06}
    {638308800 25200 1 +06}
    {654638400 21600 0 +06}
    {670363200 18000 0 +05}
    {670366800 21600 1 +05}
    {686091600 18000 0 +05}
    {694206000 18000 0 +05}
    {-1441168631 18000 0 +0500}
    {-1247547600 21600 0 +0600}
    {354909600 25200 1 +0700}
    {370717200 21600 0 +0600}
    {386445600 25200 1 +0700}
    {402253200 21600 0 +0600}
    {417981600 25200 1 +0700}
    {433789200 21600 0 +0600}
    {449604000 25200 1 +0700}
    {465336000 21600 0 +0600}
    {481060800 25200 1 +0700}
    {496785600 21600 0 +0600}
    {512510400 25200 1 +0700}
    {528235200 21600 0 +0600}
    {543960000 25200 1 +0700}
    {559684800 21600 0 +0600}
    {575409600 25200 1 +0700}
    {591134400 21600 0 +0600}
    {606859200 25200 1 +0700}
    {622584000 21600 0 +0600}
    {638308800 25200 1 +0700}
    {654638400 21600 0 +0600}
    {670363200 18000 0 +0500}
    {670366800 21600 1 +0600}
    {686091600 18000 0 +0500}
    {694206000 18000 0 +0500}
}

Changes to library/tzdata/Asia/Tbilisi.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Tbilisi) {
    {-9223372036854775808 10751 0 LMT}
    {-2840151551 10751 0 TBMT}
    {-1441162751 10800 0 +03}
    {-405140400 14400 0 +04}
    {354916800 18000 1 +04}
    {370724400 14400 0 +04}
    {386452800 18000 1 +04}
    {402260400 14400 0 +04}
    {417988800 18000 1 +04}
    {433796400 14400 0 +04}
    {449611200 18000 1 +04}
    {465343200 14400 0 +04}
    {481068000 18000 1 +04}
    {496792800 14400 0 +04}
    {512517600 18000 1 +04}
    {528242400 14400 0 +04}
    {543967200 18000 1 +04}
    {559692000 14400 0 +04}
    {575416800 18000 1 +04}
    {591141600 14400 0 +04}
    {606866400 18000 1 +04}
    {622591200 14400 0 +04}
    {638316000 18000 1 +04}
    {654645600 14400 0 +04}
    {670370400 10800 0 +03}
    {670374000 14400 1 +03}
    {686098800 10800 0 +03}
    {694213200 10800 0 +03}
    {701816400 14400 1 +03}
    {717537600 10800 0 +03}
    {733266000 14400 1 +03}
    {748987200 10800 0 +03}
    {764715600 14400 1 +03}
    {780440400 14400 0 +04}
    {796161600 18000 1 +04}
    {811882800 14400 0 +04}
    {828216000 18000 1 +04}
    {846360000 18000 1 +05}
    {859662000 18000 0 +04}
    {877806000 14400 0 +04}
    {891115200 18000 1 +04}
    {909255600 14400 0 +04}
    {922564800 18000 1 +04}
    {941310000 14400 0 +04}
    {954014400 18000 1 +04}
    {972759600 14400 0 +04}
    {985464000 18000 1 +04}
    {1004209200 14400 0 +04}
    {1017518400 18000 1 +04}
    {1035658800 14400 0 +04}
    {1048968000 18000 1 +04}
    {1067108400 14400 0 +04}
    {1080417600 18000 1 +04}
    {1088280000 14400 0 +03}
    {1099177200 10800 0 +03}
    {1111878000 14400 0 +04}
    {-1441162751 10800 0 +0300}
    {-405140400 14400 0 +0400}
    {354916800 18000 1 +0500}
    {370724400 14400 0 +0400}
    {386452800 18000 1 +0500}
    {402260400 14400 0 +0400}
    {417988800 18000 1 +0500}
    {433796400 14400 0 +0400}
    {449611200 18000 1 +0500}
    {465343200 14400 0 +0400}
    {481068000 18000 1 +0500}
    {496792800 14400 0 +0400}
    {512517600 18000 1 +0500}
    {528242400 14400 0 +0400}
    {543967200 18000 1 +0500}
    {559692000 14400 0 +0400}
    {575416800 18000 1 +0500}
    {591141600 14400 0 +0400}
    {606866400 18000 1 +0500}
    {622591200 14400 0 +0400}
    {638316000 18000 1 +0500}
    {654645600 14400 0 +0400}
    {670370400 10800 0 +0300}
    {670374000 14400 1 +0400}
    {686098800 10800 0 +0300}
    {694213200 10800 0 +0300}
    {701816400 14400 1 +0400}
    {717537600 10800 0 +0300}
    {733266000 14400 1 +0400}
    {748987200 10800 0 +0300}
    {764715600 14400 1 +0400}
    {780440400 14400 0 +0400}
    {796161600 18000 1 +0500}
    {811882800 14400 0 +0400}
    {828216000 18000 1 +0500}
    {846360000 18000 1 +0500}
    {859662000 18000 0 +0500}
    {877806000 14400 0 +0400}
    {891115200 18000 1 +0500}
    {909255600 14400 0 +0400}
    {922564800 18000 1 +0500}
    {941310000 14400 0 +0400}
    {954014400 18000 1 +0500}
    {972759600 14400 0 +0400}
    {985464000 18000 1 +0500}
    {1004209200 14400 0 +0400}
    {1017518400 18000 1 +0500}
    {1035658800 14400 0 +0400}
    {1048968000 18000 1 +0500}
    {1067108400 14400 0 +0400}
    {1080417600 18000 1 +0500}
    {1088280000 14400 0 +0400}
    {1099177200 10800 0 +0300}
    {1111878000 14400 0 +0400}
}

Changes to library/tzdata/Asia/Tehran.

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

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
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

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





-
-
-
-
+
+
+
+
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Tehran) {
    {-9223372036854775808 12344 0 LMT}
    {-1704165944 12344 0 TMT}
    {-757394744 12600 0 +0330}
    {247177800 14400 0 +04}
    {259272000 18000 1 +04}
    {277758000 14400 0 +04}
    {-1090466744 12600 0 +0330}
    {227820600 16200 1 +0430}
    {246227400 14400 0 +0400}
    {259617600 18000 1 +0500}
    {271108800 14400 0 +0400}
    {283982400 12600 0 +0330}
    {290809800 16200 1 +0330}
    {296598600 16200 1 +0430}
    {306531000 12600 0 +0330}
    {322432200 16200 1 +0330}
    {322432200 16200 1 +0430}
    {338499000 12600 0 +0330}
    {673216200 16200 1 +0330}
    {673216200 16200 1 +0430}
    {685481400 12600 0 +0330}
    {701209800 16200 1 +0330}
    {701209800 16200 1 +0430}
    {717103800 12600 0 +0330}
    {732745800 16200 1 +0330}
    {732745800 16200 1 +0430}
    {748639800 12600 0 +0330}
    {764281800 16200 1 +0330}
    {764281800 16200 1 +0430}
    {780175800 12600 0 +0330}
    {795817800 16200 1 +0330}
    {795817800 16200 1 +0430}
    {811711800 12600 0 +0330}
    {827353800 16200 1 +0330}
    {827353800 16200 1 +0430}
    {843247800 12600 0 +0330}
    {858976200 16200 1 +0330}
    {858976200 16200 1 +0430}
    {874870200 12600 0 +0330}
    {890512200 16200 1 +0330}
    {890512200 16200 1 +0430}
    {906406200 12600 0 +0330}
    {922048200 16200 1 +0330}
    {922048200 16200 1 +0430}
    {937942200 12600 0 +0330}
    {953584200 16200 1 +0330}
    {953584200 16200 1 +0430}
    {969478200 12600 0 +0330}
    {985206600 16200 1 +0330}
    {985206600 16200 1 +0430}
    {1001100600 12600 0 +0330}
    {1016742600 16200 1 +0330}
    {1016742600 16200 1 +0430}
    {1032636600 12600 0 +0330}
    {1048278600 16200 1 +0330}
    {1048278600 16200 1 +0430}
    {1064172600 12600 0 +0330}
    {1079814600 16200 1 +0330}
    {1079814600 16200 1 +0430}
    {1095708600 12600 0 +0330}
    {1111437000 16200 1 +0330}
    {1111437000 16200 1 +0430}
    {1127331000 12600 0 +0330}
    {1206045000 16200 1 +0330}
    {1206045000 16200 1 +0430}
    {1221939000 12600 0 +0330}
    {1237667400 16200 1 +0330}
    {1237667400 16200 1 +0430}
    {1253561400 12600 0 +0330}
    {1269203400 16200 1 +0330}
    {1269203400 16200 1 +0430}
    {1285097400 12600 0 +0330}
    {1300739400 16200 1 +0330}
    {1300739400 16200 1 +0430}
    {1316633400 12600 0 +0330}
    {1332275400 16200 1 +0330}
    {1332275400 16200 1 +0430}
    {1348169400 12600 0 +0330}
    {1363897800 16200 1 +0330}
    {1363897800 16200 1 +0430}
    {1379791800 12600 0 +0330}
    {1395433800 16200 1 +0330}
    {1395433800 16200 1 +0430}
    {1411327800 12600 0 +0330}
    {1426969800 16200 1 +0330}
    {1426969800 16200 1 +0430}
    {1442863800 12600 0 +0330}
    {1458505800 16200 1 +0330}
    {1458505800 16200 1 +0430}
    {1474399800 12600 0 +0330}
    {1490128200 16200 1 +0330}
    {1490128200 16200 1 +0430}
    {1506022200 12600 0 +0330}
    {1521664200 16200 1 +0330}
    {1521664200 16200 1 +0430}
    {1537558200 12600 0 +0330}
    {1553200200 16200 1 +0330}
    {1553200200 16200 1 +0430}
    {1569094200 12600 0 +0330}
    {1584736200 16200 1 +0330}
    {1584736200 16200 1 +0430}
    {1600630200 12600 0 +0330}
    {1616358600 16200 1 +0330}
    {1616358600 16200 1 +0430}
    {1632252600 12600 0 +0330}
    {1647894600 16200 1 +0330}
    {1647894600 16200 1 +0430}
    {1663788600 12600 0 +0330}
    {1679430600 16200 1 +0330}
    {1695324600 12600 0 +0330}
    {1710966600 16200 1 +0330}
    {1726860600 12600 0 +0330}
    {1742589000 16200 1 +0330}
    {1758483000 12600 0 +0330}
    {1774125000 16200 1 +0330}
    {1790019000 12600 0 +0330}
    {1805661000 16200 1 +0330}
    {1821555000 12600 0 +0330}
    {1837197000 16200 1 +0330}
    {1853091000 12600 0 +0330}
    {1868733000 16200 1 +0330}
    {1884627000 12600 0 +0330}
    {1900355400 16200 1 +0330}
    {1916249400 12600 0 +0330}
    {1931891400 16200 1 +0330}
    {1947785400 12600 0 +0330}
    {1963427400 16200 1 +0330}
    {1979321400 12600 0 +0330}
    {1994963400 16200 1 +0330}
    {2010857400 12600 0 +0330}
    {2026585800 16200 1 +0330}
    {2042479800 12600 0 +0330}
    {2058121800 16200 1 +0330}
    {2074015800 12600 0 +0330}
    {2089657800 16200 1 +0330}
    {2105551800 12600 0 +0330}
    {2121193800 16200 1 +0330}
    {2137087800 12600 0 +0330}
    {2152816200 16200 1 +0330}
    {2168710200 12600 0 +0330}
    {2184352200 16200 1 +0330}
    {2200246200 12600 0 +0330}
    {2215888200 16200 1 +0330}
    {2231782200 12600 0 +0330}
    {2247424200 16200 1 +0330}
    {2263318200 12600 0 +0330}
    {2279046600 16200 1 +0330}
    {2294940600 12600 0 +0330}
    {2310582600 16200 1 +0330}
    {2326476600 12600 0 +0330}
    {2342118600 16200 1 +0330}
    {2358012600 12600 0 +0330}
    {2373654600 16200 1 +0330}
    {2389548600 12600 0 +0330}
    {2405277000 16200 1 +0330}
    {2421171000 12600 0 +0330}
    {2436813000 16200 1 +0330}
    {2452707000 12600 0 +0330}
    {2468349000 16200 1 +0330}
    {2484243000 12600 0 +0330}
    {2499885000 16200 1 +0330}
    {2515779000 12600 0 +0330}
    {2531507400 16200 1 +0330}
    {2547401400 12600 0 +0330}
    {2563043400 16200 1 +0330}
    {2578937400 12600 0 +0330}
    {2594579400 16200 1 +0330}
    {2610473400 12600 0 +0330}
    {2626115400 16200 1 +0330}
    {2642009400 12600 0 +0330}
    {2657737800 16200 1 +0330}
    {2673631800 12600 0 +0330}
    {2689273800 16200 1 +0330}
    {2705167800 12600 0 +0330}
    {2720809800 16200 1 +0330}
    {2736703800 12600 0 +0330}
    {2752345800 16200 1 +0330}
    {2768239800 12600 0 +0330}
    {2783968200 16200 1 +0330}
    {2799862200 12600 0 +0330}
    {2815504200 16200 1 +0330}
    {2831398200 12600 0 +0330}
    {2847040200 16200 1 +0330}
    {2862934200 12600 0 +0330}
    {2878576200 16200 1 +0330}
    {2894470200 12600 0 +0330}
    {2910112200 16200 1 +0330}
    {2926006200 12600 0 +0330}
    {2941734600 16200 1 +0330}
    {2957628600 12600 0 +0330}
    {2973270600 16200 1 +0330}
    {2989164600 12600 0 +0330}
    {3004806600 16200 1 +0330}
    {3020700600 12600 0 +0330}
    {3036342600 16200 1 +0330}
    {3052236600 12600 0 +0330}
    {3067965000 16200 1 +0330}
    {3083859000 12600 0 +0330}
    {3099501000 16200 1 +0330}
    {3115395000 12600 0 +0330}
    {3131037000 16200 1 +0330}
    {3146931000 12600 0 +0330}
    {3162573000 16200 1 +0330}
    {3178467000 12600 0 +0330}
    {3194195400 16200 1 +0330}
    {3210089400 12600 0 +0330}
    {3225731400 16200 1 +0330}
    {3241625400 12600 0 +0330}
    {3257267400 16200 1 +0330}
    {3273161400 12600 0 +0330}
    {3288803400 16200 1 +0330}
    {3304697400 12600 0 +0330}
    {3320425800 16200 1 +0330}
    {3336319800 12600 0 +0330}
    {3351961800 16200 1 +0330}
    {3367855800 12600 0 +0330}
    {3383497800 16200 1 +0330}
    {3399391800 12600 0 +0330}
    {3415033800 16200 1 +0330}
    {3430927800 12600 0 +0330}
    {3446656200 16200 1 +0330}
    {3462550200 12600 0 +0330}
    {3478192200 16200 1 +0330}
    {3494086200 12600 0 +0330}
    {3509728200 16200 1 +0330}
    {3525622200 12600 0 +0330}
    {3541264200 16200 1 +0330}
    {3557158200 12600 0 +0330}
    {3572886600 16200 1 +0330}
    {3588780600 12600 0 +0330}
    {3604422600 16200 1 +0330}
    {3620316600 12600 0 +0330}
    {3635958600 16200 1 +0330}
    {3651852600 12600 0 +0330}
    {3667494600 16200 1 +0330}
    {3683388600 12600 0 +0330}
    {3699117000 16200 1 +0330}
    {3715011000 12600 0 +0330}
    {3730653000 16200 1 +0330}
    {3746547000 12600 0 +0330}
    {3762189000 16200 1 +0330}
    {3778083000 12600 0 +0330}
    {3793725000 16200 1 +0330}
    {3809619000 12600 0 +0330}
    {3825261000 16200 1 +0330}
    {3841155000 12600 0 +0330}
    {3856883400 16200 1 +0330}
    {3872777400 12600 0 +0330}
    {3888419400 16200 1 +0330}
    {3904313400 12600 0 +0330}
    {3919955400 16200 1 +0330}
    {3935849400 12600 0 +0330}
    {3951491400 16200 1 +0330}
    {3967385400 12600 0 +0330}
    {3983113800 16200 1 +0330}
    {3999007800 12600 0 +0330}
    {4014649800 16200 1 +0330}
    {4030543800 12600 0 +0330}
    {4046185800 16200 1 +0330}
    {4062079800 12600 0 +0330}
    {4077721800 16200 1 +0330}
    {4093615800 12600 0 +0330}
}

Changes to library/tzdata/Asia/Thimphu.

1
2
3
4
5
6

7
1
2
3
4
5

6
7





-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Thimphu) {
    {-9223372036854775808 21516 0 LMT}
    {-706341516 19800 0 +0530}
    {560025000 21600 0 +06}
    {560025000 21600 0 +0600}
}

Changes to library/tzdata/Asia/Tomsk.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Tomsk) {
    {-9223372036854775808 20391 0 LMT}
    {-1578807591 21600 0 +06}
    {-1247551200 25200 0 +08}
    {354906000 28800 1 +08}
    {370713600 25200 0 +07}
    {386442000 28800 1 +08}
    {402249600 25200 0 +07}
    {417978000 28800 1 +08}
    {433785600 25200 0 +07}
    {449600400 28800 1 +08}
    {465332400 25200 0 +07}
    {481057200 28800 1 +08}
    {496782000 25200 0 +07}
    {512506800 28800 1 +08}
    {528231600 25200 0 +07}
    {543956400 28800 1 +08}
    {559681200 25200 0 +07}
    {575406000 28800 1 +08}
    {591130800 25200 0 +07}
    {606855600 28800 1 +08}
    {622580400 25200 0 +07}
    {638305200 28800 1 +08}
    {654634800 25200 0 +07}
    {670359600 21600 0 +07}
    {670363200 25200 1 +07}
    {686088000 21600 0 +06}
    {695764800 25200 0 +08}
    {701809200 28800 1 +08}
    {717534000 25200 0 +07}
    {733258800 28800 1 +08}
    {748983600 25200 0 +07}
    {764708400 28800 1 +08}
    {780433200 25200 0 +07}
    {796158000 28800 1 +08}
    {811882800 25200 0 +07}
    {828212400 28800 1 +08}
    {846356400 25200 0 +07}
    {859662000 28800 1 +08}
    {877806000 25200 0 +07}
    {891111600 28800 1 +08}
    {909255600 25200 0 +07}
    {922561200 28800 1 +08}
    {941310000 25200 0 +07}
    {954010800 28800 1 +08}
    {972759600 25200 0 +07}
    {985460400 28800 1 +08}
    {1004209200 25200 0 +07}
    {1017514800 28800 1 +08}
    {1020196800 25200 0 +07}
    {1035662400 21600 0 +06}
    {1048968000 25200 1 +07}
    {1067112000 21600 0 +06}
    {1080417600 25200 1 +07}
    {1099166400 21600 0 +06}
    {1111867200 25200 1 +07}
    {1130616000 21600 0 +06}
    {1143316800 25200 1 +07}
    {1162065600 21600 0 +06}
    {1174766400 25200 1 +07}
    {1193515200 21600 0 +06}
    {1206820800 25200 1 +07}
    {1224964800 21600 0 +06}
    {1238270400 25200 1 +07}
    {1256414400 21600 0 +06}
    {1269720000 25200 1 +07}
    {1288468800 21600 0 +06}
    {1301169600 25200 0 +07}
    {1414263600 21600 0 +06}
    {1464465600 25200 0 +07}
    {-1578807591 21600 0 +0600}
    {-1247551200 25200 0 +0700}
    {354906000 28800 1 +0800}
    {370713600 25200 0 +0700}
    {386442000 28800 1 +0800}
    {402249600 25200 0 +0700}
    {417978000 28800 1 +0800}
    {433785600 25200 0 +0700}
    {449600400 28800 1 +0800}
    {465332400 25200 0 +0700}
    {481057200 28800 1 +0800}
    {496782000 25200 0 +0700}
    {512506800 28800 1 +0800}
    {528231600 25200 0 +0700}
    {543956400 28800 1 +0800}
    {559681200 25200 0 +0700}
    {575406000 28800 1 +0800}
    {591130800 25200 0 +0700}
    {606855600 28800 1 +0800}
    {622580400 25200 0 +0700}
    {638305200 28800 1 +0800}
    {654634800 25200 0 +0700}
    {670359600 21600 0 +0600}
    {670363200 25200 1 +0700}
    {686088000 21600 0 +0600}
    {695764800 25200 0 +0700}
    {701809200 28800 1 +0800}
    {717534000 25200 0 +0700}
    {733258800 28800 1 +0800}
    {748983600 25200 0 +0700}
    {764708400 28800 1 +0800}
    {780433200 25200 0 +0700}
    {796158000 28800 1 +0800}
    {811882800 25200 0 +0700}
    {828212400 28800 1 +0800}
    {846356400 25200 0 +0700}
    {859662000 28800 1 +0800}
    {877806000 25200 0 +0700}
    {891111600 28800 1 +0800}
    {909255600 25200 0 +0700}
    {922561200 28800 1 +0800}
    {941310000 25200 0 +0700}
    {954010800 28800 1 +0800}
    {972759600 25200 0 +0700}
    {985460400 28800 1 +0800}
    {1004209200 25200 0 +0700}
    {1017514800 28800 1 +0800}
    {1020196800 25200 0 +0700}
    {1035662400 21600 0 +0600}
    {1048968000 25200 1 +0700}
    {1067112000 21600 0 +0600}
    {1080417600 25200 1 +0700}
    {1099166400 21600 0 +0600}
    {1111867200 25200 1 +0700}
    {1130616000 21600 0 +0600}
    {1143316800 25200 1 +0700}
    {1162065600 21600 0 +0600}
    {1174766400 25200 1 +0700}
    {1193515200 21600 0 +0600}
    {1206820800 25200 1 +0700}
    {1224964800 21600 0 +0600}
    {1238270400 25200 1 +0700}
    {1256414400 21600 0 +0600}
    {1269720000 25200 1 +0700}
    {1288468800 21600 0 +0600}
    {1301169600 25200 0 +0700}
    {1414263600 21600 0 +0600}
    {1464465600 25200 0 +0700}
}

Changes to library/tzdata/Asia/Ulaanbaatar.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Ulaanbaatar) {
    {-9223372036854775808 25652 0 LMT}
    {-2032931252 25200 0 +07}
    {252435600 28800 0 +08}
    {417974400 32400 1 +08}
    {433782000 28800 0 +08}
    {449596800 32400 1 +08}
    {465318000 28800 0 +08}
    {481046400 32400 1 +08}
    {496767600 28800 0 +08}
    {512496000 32400 1 +08}
    {528217200 28800 0 +08}
    {543945600 32400 1 +08}
    {559666800 28800 0 +08}
    {575395200 32400 1 +08}
    {591116400 28800 0 +08}
    {606844800 32400 1 +08}
    {622566000 28800 0 +08}
    {638294400 32400 1 +08}
    {654620400 28800 0 +08}
    {670348800 32400 1 +08}
    {686070000 28800 0 +08}
    {701798400 32400 1 +08}
    {717519600 28800 0 +08}
    {733248000 32400 1 +08}
    {748969200 28800 0 +08}
    {764697600 32400 1 +08}
    {780418800 28800 0 +08}
    {796147200 32400 1 +08}
    {811868400 28800 0 +08}
    {828201600 32400 1 +08}
    {843922800 28800 0 +08}
    {859651200 32400 1 +08}
    {875372400 28800 0 +08}
    {891100800 32400 1 +08}
    {906822000 28800 0 +08}
    {988394400 32400 1 +08}
    {1001696400 28800 0 +08}
    {1017424800 32400 1 +08}
    {1033146000 28800 0 +08}
    {1048874400 32400 1 +08}
    {1064595600 28800 0 +08}
    {1080324000 32400 1 +08}
    {1096045200 28800 0 +08}
    {1111773600 32400 1 +08}
    {1127494800 28800 0 +08}
    {1143223200 32400 1 +08}
    {1159549200 28800 0 +08}
    {1427479200 32400 1 +08}
    {1443193200 28800 0 +08}
    {1458928800 32400 1 +08}
    {1474642800 28800 0 +08}
    {-2032931252 25200 0 +0700}
    {252435600 28800 0 +0800}
    {417974400 32400 1 +0900}
    {433782000 28800 0 +0800}
    {449596800 32400 1 +0900}
    {465318000 28800 0 +0800}
    {481046400 32400 1 +0900}
    {496767600 28800 0 +0800}
    {512496000 32400 1 +0900}
    {528217200 28800 0 +0800}
    {543945600 32400 1 +0900}
    {559666800 28800 0 +0800}
    {575395200 32400 1 +0900}
    {591116400 28800 0 +0800}
    {606844800 32400 1 +0900}
    {622566000 28800 0 +0800}
    {638294400 32400 1 +0900}
    {654620400 28800 0 +0800}
    {670348800 32400 1 +0900}
    {686070000 28800 0 +0800}
    {701798400 32400 1 +0900}
    {717519600 28800 0 +0800}
    {733248000 32400 1 +0900}
    {748969200 28800 0 +0800}
    {764697600 32400 1 +0900}
    {780418800 28800 0 +0800}
    {796147200 32400 1 +0900}
    {811868400 28800 0 +0800}
    {828201600 32400 1 +0900}
    {843922800 28800 0 +0800}
    {859651200 32400 1 +0900}
    {875372400 28800 0 +0800}
    {891100800 32400 1 +0900}
    {906822000 28800 0 +0800}
    {988394400 32400 1 +0900}
    {1001696400 28800 0 +0800}
    {1017424800 32400 1 +0900}
    {1033146000 28800 0 +0800}
    {1048874400 32400 1 +0900}
    {1064595600 28800 0 +0800}
    {1080324000 32400 1 +0900}
    {1096045200 28800 0 +0800}
    {1111773600 32400 1 +0900}
    {1127494800 28800 0 +0800}
    {1143223200 32400 1 +0900}
    {1159549200 28800 0 +0800}
    {1427479200 32400 1 +0900}
    {1443193200 28800 0 +0800}
    {1458928800 32400 1 +0900}
    {1474642800 28800 0 +0800}
}

Changes to library/tzdata/Asia/Urumqi.

1
2
3
4
5

6
1
2
3
4

5
6




-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Urumqi) {
    {-9223372036854775808 21020 0 LMT}
    {-1325483420 21600 0 +06}
    {-1325483420 21600 0 +0600}
}

Changes to library/tzdata/Asia/Ust-Nera.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Ust-Nera) {
    {-9223372036854775808 34374 0 LMT}
    {-1579426374 28800 0 +08}
    {354898800 43200 0 +12}
    {370699200 39600 0 +11}
    {386427600 43200 1 +12}
    {402235200 39600 0 +11}
    {417963600 43200 1 +12}
    {433771200 39600 0 +11}
    {449586000 43200 1 +12}
    {465318000 39600 0 +11}
    {481042800 43200 1 +12}
    {496767600 39600 0 +11}
    {512492400 43200 1 +12}
    {528217200 39600 0 +11}
    {543942000 43200 1 +12}
    {559666800 39600 0 +11}
    {575391600 43200 1 +12}
    {591116400 39600 0 +11}
    {606841200 43200 1 +12}
    {622566000 39600 0 +11}
    {638290800 43200 1 +12}
    {654620400 39600 0 +11}
    {670345200 36000 0 +11}
    {670348800 39600 1 +11}
    {686073600 36000 0 +10}
    {695750400 39600 0 +12}
    {701794800 43200 1 +12}
    {717519600 39600 0 +11}
    {733244400 43200 1 +12}
    {748969200 39600 0 +11}
    {764694000 43200 1 +12}
    {780418800 39600 0 +11}
    {796143600 43200 1 +12}
    {811868400 39600 0 +11}
    {828198000 43200 1 +12}
    {846342000 39600 0 +11}
    {859647600 43200 1 +12}
    {877791600 39600 0 +11}
    {891097200 43200 1 +12}
    {909241200 39600 0 +11}
    {922546800 43200 1 +12}
    {941295600 39600 0 +11}
    {953996400 43200 1 +12}
    {972745200 39600 0 +11}
    {985446000 43200 1 +12}
    {1004194800 39600 0 +11}
    {1017500400 43200 1 +12}
    {1035644400 39600 0 +11}
    {1048950000 43200 1 +12}
    {1067094000 39600 0 +11}
    {1080399600 43200 1 +12}
    {1099148400 39600 0 +11}
    {1111849200 43200 1 +12}
    {1130598000 39600 0 +11}
    {1143298800 43200 1 +12}
    {1162047600 39600 0 +11}
    {1174748400 43200 1 +12}
    {1193497200 39600 0 +11}
    {1206802800 43200 1 +12}
    {1224946800 39600 0 +11}
    {1238252400 43200 1 +12}
    {1256396400 39600 0 +11}
    {1269702000 43200 1 +12}
    {1288450800 39600 0 +11}
    {1301151600 43200 0 +12}
    {1315828800 39600 0 +11}
    {1414249200 36000 0 +10}
    {-1579426374 28800 0 +0800}
    {354898800 43200 0 +1200}
    {370699200 39600 0 +1100}
    {386427600 43200 1 +1200}
    {402235200 39600 0 +1100}
    {417963600 43200 1 +1200}
    {433771200 39600 0 +1100}
    {449586000 43200 1 +1200}
    {465318000 39600 0 +1100}
    {481042800 43200 1 +1200}
    {496767600 39600 0 +1100}
    {512492400 43200 1 +1200}
    {528217200 39600 0 +1100}
    {543942000 43200 1 +1200}
    {559666800 39600 0 +1100}
    {575391600 43200 1 +1200}
    {591116400 39600 0 +1100}
    {606841200 43200 1 +1200}
    {622566000 39600 0 +1100}
    {638290800 43200 1 +1200}
    {654620400 39600 0 +1100}
    {670345200 36000 0 +1000}
    {670348800 39600 1 +1100}
    {686073600 36000 0 +1000}
    {695750400 39600 0 +1100}
    {701794800 43200 1 +1200}
    {717519600 39600 0 +1100}
    {733244400 43200 1 +1200}
    {748969200 39600 0 +1100}
    {764694000 43200 1 +1200}
    {780418800 39600 0 +1100}
    {796143600 43200 1 +1200}
    {811868400 39600 0 +1100}
    {828198000 43200 1 +1200}
    {846342000 39600 0 +1100}
    {859647600 43200 1 +1200}
    {877791600 39600 0 +1100}
    {891097200 43200 1 +1200}
    {909241200 39600 0 +1100}
    {922546800 43200 1 +1200}
    {941295600 39600 0 +1100}
    {953996400 43200 1 +1200}
    {972745200 39600 0 +1100}
    {985446000 43200 1 +1200}
    {1004194800 39600 0 +1100}
    {1017500400 43200 1 +1200}
    {1035644400 39600 0 +1100}
    {1048950000 43200 1 +1200}
    {1067094000 39600 0 +1100}
    {1080399600 43200 1 +1200}
    {1099148400 39600 0 +1100}
    {1111849200 43200 1 +1200}
    {1130598000 39600 0 +1100}
    {1143298800 43200 1 +1200}
    {1162047600 39600 0 +1100}
    {1174748400 43200 1 +1200}
    {1193497200 39600 0 +1100}
    {1206802800 43200 1 +1200}
    {1224946800 39600 0 +1100}
    {1238252400 43200 1 +1200}
    {1256396400 39600 0 +1100}
    {1269702000 43200 1 +1200}
    {1288450800 39600 0 +1100}
    {1301151600 43200 0 +1200}
    {1315828800 39600 0 +1100}
    {1414249200 36000 0 +1000}
}

Changes to library/tzdata/Asia/Vladivostok.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Vladivostok) {
    {-9223372036854775808 31651 0 LMT}
    {-1487321251 32400 0 +09}
    {-1247562000 36000 0 +11}
    {354895200 39600 1 +11}
    {370702800 36000 0 +10}
    {386431200 39600 1 +11}
    {402238800 36000 0 +10}
    {417967200 39600 1 +11}
    {433774800 36000 0 +10}
    {449589600 39600 1 +11}
    {465321600 36000 0 +10}
    {481046400 39600 1 +11}
    {496771200 36000 0 +10}
    {512496000 39600 1 +11}
    {528220800 36000 0 +10}
    {543945600 39600 1 +11}
    {559670400 36000 0 +10}
    {575395200 39600 1 +11}
    {591120000 36000 0 +10}
    {606844800 39600 1 +11}
    {622569600 36000 0 +10}
    {638294400 39600 1 +11}
    {654624000 36000 0 +10}
    {670348800 32400 0 +10}
    {670352400 36000 1 +10}
    {686077200 32400 0 +09}
    {695754000 36000 0 +11}
    {701798400 39600 1 +11}
    {717523200 36000 0 +10}
    {733248000 39600 1 +11}
    {748972800 36000 0 +10}
    {764697600 39600 1 +11}
    {780422400 36000 0 +10}
    {796147200 39600 1 +11}
    {811872000 36000 0 +10}
    {828201600 39600 1 +11}
    {846345600 36000 0 +10}
    {859651200 39600 1 +11}
    {877795200 36000 0 +10}
    {891100800 39600 1 +11}
    {909244800 36000 0 +10}
    {922550400 39600 1 +11}
    {941299200 36000 0 +10}
    {954000000 39600 1 +11}
    {972748800 36000 0 +10}
    {985449600 39600 1 +11}
    {1004198400 36000 0 +10}
    {1017504000 39600 1 +11}
    {1035648000 36000 0 +10}
    {1048953600 39600 1 +11}
    {1067097600 36000 0 +10}
    {1080403200 39600 1 +11}
    {1099152000 36000 0 +10}
    {1111852800 39600 1 +11}
    {1130601600 36000 0 +10}
    {1143302400 39600 1 +11}
    {1162051200 36000 0 +10}
    {1174752000 39600 1 +11}
    {1193500800 36000 0 +10}
    {1206806400 39600 1 +11}
    {1224950400 36000 0 +10}
    {1238256000 39600 1 +11}
    {1256400000 36000 0 +10}
    {1269705600 39600 1 +11}
    {1288454400 36000 0 +10}
    {1301155200 39600 0 +11}
    {1414249200 36000 0 +10}
    {-1487321251 32400 0 +0900}
    {-1247562000 36000 0 +1000}
    {354895200 39600 1 +1100}
    {370702800 36000 0 +1000}
    {386431200 39600 1 +1100}
    {402238800 36000 0 +1000}
    {417967200 39600 1 +1100}
    {433774800 36000 0 +1000}
    {449589600 39600 1 +1100}
    {465321600 36000 0 +1000}
    {481046400 39600 1 +1100}
    {496771200 36000 0 +1000}
    {512496000 39600 1 +1100}
    {528220800 36000 0 +1000}
    {543945600 39600 1 +1100}
    {559670400 36000 0 +1000}
    {575395200 39600 1 +1100}
    {591120000 36000 0 +1000}
    {606844800 39600 1 +1100}
    {622569600 36000 0 +1000}
    {638294400 39600 1 +1100}
    {654624000 36000 0 +1000}
    {670348800 32400 0 +0900}
    {670352400 36000 1 +1000}
    {686077200 32400 0 +0900}
    {695754000 36000 0 +1000}
    {701798400 39600 1 +1100}
    {717523200 36000 0 +1000}
    {733248000 39600 1 +1100}
    {748972800 36000 0 +1000}
    {764697600 39600 1 +1100}
    {780422400 36000 0 +1000}
    {796147200 39600 1 +1100}
    {811872000 36000 0 +1000}
    {828201600 39600 1 +1100}
    {846345600 36000 0 +1000}
    {859651200 39600 1 +1100}
    {877795200 36000 0 +1000}
    {891100800 39600 1 +1100}
    {909244800 36000 0 +1000}
    {922550400 39600 1 +1100}
    {941299200 36000 0 +1000}
    {954000000 39600 1 +1100}
    {972748800 36000 0 +1000}
    {985449600 39600 1 +1100}
    {1004198400 36000 0 +1000}
    {1017504000 39600 1 +1100}
    {1035648000 36000 0 +1000}
    {1048953600 39600 1 +1100}
    {1067097600 36000 0 +1000}
    {1080403200 39600 1 +1100}
    {1099152000 36000 0 +1000}
    {1111852800 39600 1 +1100}
    {1130601600 36000 0 +1000}
    {1143302400 39600 1 +1100}
    {1162051200 36000 0 +1000}
    {1174752000 39600 1 +1100}
    {1193500800 36000 0 +1000}
    {1206806400 39600 1 +1100}
    {1224950400 36000 0 +1000}
    {1238256000 39600 1 +1100}
    {1256400000 36000 0 +1000}
    {1269705600 39600 1 +1100}
    {1288454400 36000 0 +1000}
    {1301155200 39600 0 +1100}
    {1414249200 36000 0 +1000}
}

Changes to library/tzdata/Asia/Yakutsk.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Yakutsk) {
    {-9223372036854775808 31138 0 LMT}
    {-1579423138 28800 0 +08}
    {-1247558400 32400 0 +10}
    {354898800 36000 1 +10}
    {370706400 32400 0 +09}
    {386434800 36000 1 +10}
    {402242400 32400 0 +09}
    {417970800 36000 1 +10}
    {433778400 32400 0 +09}
    {449593200 36000 1 +10}
    {465325200 32400 0 +09}
    {481050000 36000 1 +10}
    {496774800 32400 0 +09}
    {512499600 36000 1 +10}
    {528224400 32400 0 +09}
    {543949200 36000 1 +10}
    {559674000 32400 0 +09}
    {575398800 36000 1 +10}
    {591123600 32400 0 +09}
    {606848400 36000 1 +10}
    {622573200 32400 0 +09}
    {638298000 36000 1 +10}
    {654627600 32400 0 +09}
    {670352400 28800 0 +09}
    {670356000 32400 1 +09}
    {686080800 28800 0 +08}
    {695757600 32400 0 +10}
    {701802000 36000 1 +10}
    {717526800 32400 0 +09}
    {733251600 36000 1 +10}
    {748976400 32400 0 +09}
    {764701200 36000 1 +10}
    {780426000 32400 0 +09}
    {796150800 36000 1 +10}
    {811875600 32400 0 +09}
    {828205200 36000 1 +10}
    {846349200 32400 0 +09}
    {859654800 36000 1 +10}
    {877798800 32400 0 +09}
    {891104400 36000 1 +10}
    {909248400 32400 0 +09}
    {922554000 36000 1 +10}
    {941302800 32400 0 +09}
    {954003600 36000 1 +10}
    {972752400 32400 0 +09}
    {985453200 36000 1 +10}
    {1004202000 32400 0 +09}
    {1017507600 36000 1 +10}
    {1035651600 32400 0 +09}
    {1048957200 36000 1 +10}
    {1067101200 32400 0 +09}
    {1080406800 36000 1 +10}
    {1099155600 32400 0 +09}
    {1111856400 36000 1 +10}
    {1130605200 32400 0 +09}
    {1143306000 36000 1 +10}
    {1162054800 32400 0 +09}
    {1174755600 36000 1 +10}
    {1193504400 32400 0 +09}
    {1206810000 36000 1 +10}
    {1224954000 32400 0 +09}
    {1238259600 36000 1 +10}
    {1256403600 32400 0 +09}
    {1269709200 36000 1 +10}
    {1288458000 32400 0 +09}
    {1301158800 36000 0 +10}
    {1414252800 32400 0 +09}
    {-1579423138 28800 0 +0800}
    {-1247558400 32400 0 +0900}
    {354898800 36000 1 +1000}
    {370706400 32400 0 +0900}
    {386434800 36000 1 +1000}
    {402242400 32400 0 +0900}
    {417970800 36000 1 +1000}
    {433778400 32400 0 +0900}
    {449593200 36000 1 +1000}
    {465325200 32400 0 +0900}
    {481050000 36000 1 +1000}
    {496774800 32400 0 +0900}
    {512499600 36000 1 +1000}
    {528224400 32400 0 +0900}
    {543949200 36000 1 +1000}
    {559674000 32400 0 +0900}
    {575398800 36000 1 +1000}
    {591123600 32400 0 +0900}
    {606848400 36000 1 +1000}
    {622573200 32400 0 +0900}
    {638298000 36000 1 +1000}
    {654627600 32400 0 +0900}
    {670352400 28800 0 +0800}
    {670356000 32400 1 +0900}
    {686080800 28800 0 +0800}
    {695757600 32400 0 +0900}
    {701802000 36000 1 +1000}
    {717526800 32400 0 +0900}
    {733251600 36000 1 +1000}
    {748976400 32400 0 +0900}
    {764701200 36000 1 +1000}
    {780426000 32400 0 +0900}
    {796150800 36000 1 +1000}
    {811875600 32400 0 +0900}
    {828205200 36000 1 +1000}
    {846349200 32400 0 +0900}
    {859654800 36000 1 +1000}
    {877798800 32400 0 +0900}
    {891104400 36000 1 +1000}
    {909248400 32400 0 +0900}
    {922554000 36000 1 +1000}
    {941302800 32400 0 +0900}
    {954003600 36000 1 +1000}
    {972752400 32400 0 +0900}
    {985453200 36000 1 +1000}
    {1004202000 32400 0 +0900}
    {1017507600 36000 1 +1000}
    {1035651600 32400 0 +0900}
    {1048957200 36000 1 +1000}
    {1067101200 32400 0 +0900}
    {1080406800 36000 1 +1000}
    {1099155600 32400 0 +0900}
    {1111856400 36000 1 +1000}
    {1130605200 32400 0 +0900}
    {1143306000 36000 1 +1000}
    {1162054800 32400 0 +0900}
    {1174755600 36000 1 +1000}
    {1193504400 32400 0 +0900}
    {1206810000 36000 1 +1000}
    {1224954000 32400 0 +0900}
    {1238259600 36000 1 +1000}
    {1256403600 32400 0 +0900}
    {1269709200 36000 1 +1000}
    {1288458000 32400 0 +0900}
    {1301158800 36000 0 +1000}
    {1414252800 32400 0 +0900}
}

Changes to library/tzdata/Asia/Yangon.

1
2
3
4
5
6
7

8
9
1
2
3
4
5
6

7
8
9






-
+


# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Yangon) {
    {-9223372036854775808 23087 0 LMT}
    {-2840163887 23087 0 RMT}
    {-1577946287 23400 0 +0630}
    {-873268200 32400 0 +09}
    {-873268200 32400 0 +0900}
    {-778410000 23400 0 +0630}
}

Changes to library/tzdata/Asia/Yekaterinburg.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Yekaterinburg) {
    {-9223372036854775808 14553 0 LMT}
    {-1688270553 13505 0 PMT}
    {-1592610305 14400 0 +04}
    {-1247544000 18000 0 +06}
    {354913200 21600 1 +06}
    {370720800 18000 0 +05}
    {386449200 21600 1 +06}
    {402256800 18000 0 +05}
    {417985200 21600 1 +06}
    {433792800 18000 0 +05}
    {449607600 21600 1 +06}
    {465339600 18000 0 +05}
    {481064400 21600 1 +06}
    {496789200 18000 0 +05}
    {512514000 21600 1 +06}
    {528238800 18000 0 +05}
    {543963600 21600 1 +06}
    {559688400 18000 0 +05}
    {575413200 21600 1 +06}
    {591138000 18000 0 +05}
    {606862800 21600 1 +06}
    {622587600 18000 0 +05}
    {638312400 21600 1 +06}
    {654642000 18000 0 +05}
    {670366800 14400 0 +05}
    {670370400 18000 1 +05}
    {686095200 14400 0 +04}
    {695772000 18000 0 +06}
    {701816400 21600 1 +06}
    {717541200 18000 0 +05}
    {733266000 21600 1 +06}
    {748990800 18000 0 +05}
    {764715600 21600 1 +06}
    {780440400 18000 0 +05}
    {796165200 21600 1 +06}
    {811890000 18000 0 +05}
    {828219600 21600 1 +06}
    {846363600 18000 0 +05}
    {859669200 21600 1 +06}
    {877813200 18000 0 +05}
    {891118800 21600 1 +06}
    {909262800 18000 0 +05}
    {922568400 21600 1 +06}
    {941317200 18000 0 +05}
    {954018000 21600 1 +06}
    {972766800 18000 0 +05}
    {985467600 21600 1 +06}
    {1004216400 18000 0 +05}
    {1017522000 21600 1 +06}
    {1035666000 18000 0 +05}
    {1048971600 21600 1 +06}
    {1067115600 18000 0 +05}
    {1080421200 21600 1 +06}
    {1099170000 18000 0 +05}
    {1111870800 21600 1 +06}
    {1130619600 18000 0 +05}
    {1143320400 21600 1 +06}
    {1162069200 18000 0 +05}
    {1174770000 21600 1 +06}
    {1193518800 18000 0 +05}
    {1206824400 21600 1 +06}
    {1224968400 18000 0 +05}
    {1238274000 21600 1 +06}
    {1256418000 18000 0 +05}
    {1269723600 21600 1 +06}
    {1288472400 18000 0 +05}
    {1301173200 21600 0 +06}
    {1414267200 18000 0 +05}
    {-1592610305 14400 0 +0400}
    {-1247544000 18000 0 +0500}
    {354913200 21600 1 +0600}
    {370720800 18000 0 +0500}
    {386449200 21600 1 +0600}
    {402256800 18000 0 +0500}
    {417985200 21600 1 +0600}
    {433792800 18000 0 +0500}
    {449607600 21600 1 +0600}
    {465339600 18000 0 +0500}
    {481064400 21600 1 +0600}
    {496789200 18000 0 +0500}
    {512514000 21600 1 +0600}
    {528238800 18000 0 +0500}
    {543963600 21600 1 +0600}
    {559688400 18000 0 +0500}
    {575413200 21600 1 +0600}
    {591138000 18000 0 +0500}
    {606862800 21600 1 +0600}
    {622587600 18000 0 +0500}
    {638312400 21600 1 +0600}
    {654642000 18000 0 +0500}
    {670366800 14400 0 +0400}
    {670370400 18000 1 +0500}
    {686095200 14400 0 +0400}
    {695772000 18000 0 +0500}
    {701816400 21600 1 +0600}
    {717541200 18000 0 +0500}
    {733266000 21600 1 +0600}
    {748990800 18000 0 +0500}
    {764715600 21600 1 +0600}
    {780440400 18000 0 +0500}
    {796165200 21600 1 +0600}
    {811890000 18000 0 +0500}
    {828219600 21600 1 +0600}
    {846363600 18000 0 +0500}
    {859669200 21600 1 +0600}
    {877813200 18000 0 +0500}
    {891118800 21600 1 +0600}
    {909262800 18000 0 +0500}
    {922568400 21600 1 +0600}
    {941317200 18000 0 +0500}
    {954018000 21600 1 +0600}
    {972766800 18000 0 +0500}
    {985467600 21600 1 +0600}
    {1004216400 18000 0 +0500}
    {1017522000 21600 1 +0600}
    {1035666000 18000 0 +0500}
    {1048971600 21600 1 +0600}
    {1067115600 18000 0 +0500}
    {1080421200 21600 1 +0600}
    {1099170000 18000 0 +0500}
    {1111870800 21600 1 +0600}
    {1130619600 18000 0 +0500}
    {1143320400 21600 1 +0600}
    {1162069200 18000 0 +0500}
    {1174770000 21600 1 +0600}
    {1193518800 18000 0 +0500}
    {1206824400 21600 1 +0600}
    {1224968400 18000 0 +0500}
    {1238274000 21600 1 +0600}
    {1256418000 18000 0 +0500}
    {1269723600 21600 1 +0600}
    {1288472400 18000 0 +0500}
    {1301173200 21600 0 +0600}
    {1414267200 18000 0 +0500}
}

Changes to library/tzdata/Asia/Yerevan.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Yerevan) {
    {-9223372036854775808 10680 0 LMT}
    {-1441162680 10800 0 +03}
    {-405140400 14400 0 +04}
    {354916800 18000 1 +04}
    {370724400 14400 0 +04}
    {386452800 18000 1 +04}
    {402260400 14400 0 +04}
    {417988800 18000 1 +04}
    {433796400 14400 0 +04}
    {449611200 18000 1 +04}
    {465343200 14400 0 +04}
    {481068000 18000 1 +04}
    {496792800 14400 0 +04}
    {512517600 18000 1 +04}
    {528242400 14400 0 +04}
    {543967200 18000 1 +04}
    {559692000 14400 0 +04}
    {575416800 18000 1 +04}
    {591141600 14400 0 +04}
    {606866400 18000 1 +04}
    {622591200 14400 0 +04}
    {638316000 18000 1 +04}
    {654645600 14400 0 +04}
    {670370400 10800 0 +03}
    {670374000 14400 1 +03}
    {686098800 10800 0 +03}
    {701823600 14400 1 +03}
    {717548400 10800 0 +03}
    {733273200 14400 1 +03}
    {748998000 10800 0 +03}
    {764722800 14400 1 +03}
    {780447600 10800 0 +03}
    {796172400 14400 1 +03}
    {811897200 14400 0 +04}
    {852062400 14400 0 +04}
    {859672800 18000 1 +04}
    {877816800 14400 0 +04}
    {891122400 18000 1 +04}
    {909266400 14400 0 +04}
    {922572000 18000 1 +04}
    {941320800 14400 0 +04}
    {954021600 18000 1 +04}
    {972770400 14400 0 +04}
    {985471200 18000 1 +04}
    {1004220000 14400 0 +04}
    {1017525600 18000 1 +04}
    {1035669600 14400 0 +04}
    {1048975200 18000 1 +04}
    {1067119200 14400 0 +04}
    {1080424800 18000 1 +04}
    {1099173600 14400 0 +04}
    {1111874400 18000 1 +04}
    {1130623200 14400 0 +04}
    {1143324000 18000 1 +04}
    {1162072800 14400 0 +04}
    {1174773600 18000 1 +04}
    {1193522400 14400 0 +04}
    {1206828000 18000 1 +04}
    {1224972000 14400 0 +04}
    {1238277600 18000 1 +04}
    {1256421600 14400 0 +04}
    {1269727200 18000 1 +04}
    {1288476000 14400 0 +04}
    {1293825600 14400 0 +04}
    {1301176800 18000 1 +04}
    {1319925600 14400 0 +04}
    {-1441162680 10800 0 +0300}
    {-405140400 14400 0 +0400}
    {354916800 18000 1 +0500}
    {370724400 14400 0 +0400}
    {386452800 18000 1 +0500}
    {402260400 14400 0 +0400}
    {417988800 18000 1 +0500}
    {433796400 14400 0 +0400}
    {449611200 18000 1 +0500}
    {465343200 14400 0 +0400}
    {481068000 18000 1 +0500}
    {496792800 14400 0 +0400}
    {512517600 18000 1 +0500}
    {528242400 14400 0 +0400}
    {543967200 18000 1 +0500}
    {559692000 14400 0 +0400}
    {575416800 18000 1 +0500}
    {591141600 14400 0 +0400}
    {606866400 18000 1 +0500}
    {622591200 14400 0 +0400}
    {638316000 18000 1 +0500}
    {654645600 14400 0 +0400}
    {670370400 10800 0 +0300}
    {670374000 14400 1 +0400}
    {686098800 10800 0 +0300}
    {701823600 14400 1 +0400}
    {717548400 10800 0 +0300}
    {733273200 14400 1 +0400}
    {748998000 10800 0 +0300}
    {764722800 14400 1 +0400}
    {780447600 10800 0 +0300}
    {796172400 14400 1 +0400}
    {811897200 14400 0 +0400}
    {852062400 14400 0 +0400}
    {859672800 18000 1 +0500}
    {877816800 14400 0 +0400}
    {891122400 18000 1 +0500}
    {909266400 14400 0 +0400}
    {922572000 18000 1 +0500}
    {941320800 14400 0 +0400}
    {954021600 18000 1 +0500}
    {972770400 14400 0 +0400}
    {985471200 18000 1 +0500}
    {1004220000 14400 0 +0400}
    {1017525600 18000 1 +0500}
    {1035669600 14400 0 +0400}
    {1048975200 18000 1 +0500}
    {1067119200 14400 0 +0400}
    {1080424800 18000 1 +0500}
    {1099173600 14400 0 +0400}
    {1111874400 18000 1 +0500}
    {1130623200 14400 0 +0400}
    {1143324000 18000 1 +0500}
    {1162072800 14400 0 +0400}
    {1174773600 18000 1 +0500}
    {1193522400 14400 0 +0400}
    {1206828000 18000 1 +0500}
    {1224972000 14400 0 +0400}
    {1238277600 18000 1 +0500}
    {1256421600 14400 0 +0400}
    {1269727200 18000 1 +0500}
    {1288476000 14400 0 +0400}
    {1293825600 14400 0 +0400}
    {1301176800 18000 1 +0500}
    {1319925600 14400 0 +0400}
}

Changes to library/tzdata/Atlantic/Azores.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Atlantic/Azores) {
    {-9223372036854775808 -6160 0 LMT}
    {-2713904240 -6872 0 HMT}
    {-1830376800 -7200 0 -02}
    {-1689548400 -3600 1 -01}
    {-1677794400 -7200 0 -02}
    {-1667430000 -3600 1 -01}
    {-1647730800 -7200 0 -02}
    {-1635807600 -3600 1 -01}
    {-1616194800 -7200 0 -02}
    {-1604358000 -3600 1 -01}
    {-1584658800 -7200 0 -02}
    {-1572735600 -3600 1 -01}
    {-1553036400 -7200 0 -02}
    {-1541199600 -3600 1 -01}
    {-1521500400 -7200 0 -02}
    {-1442444400 -3600 1 -01}
    {-1426806000 -7200 0 -02}
    {-1379286000 -3600 1 -01}
    {-1364770800 -7200 0 -02}
    {-1348441200 -3600 1 -01}
    {-1333321200 -7200 0 -02}
    {-1316386800 -3600 1 -01}
    {-1301266800 -7200 0 -02}
    {-1284332400 -3600 1 -01}
    {-1269817200 -7200 0 -02}
    {-1221433200 -3600 1 -01}
    {-1206918000 -7200 0 -02}
    {-1191193200 -3600 1 -01}
    {-1175468400 -7200 0 -02}
    {-1127689200 -3600 1 -01}
    {-1111964400 -7200 0 -02}
    {-1096844400 -3600 1 -01}
    {-1080514800 -7200 0 -02}
    {-1063580400 -3600 1 -01}
    {-1049065200 -7200 0 -02}
    {-1033340400 -3600 1 -01}
    {-1017615600 -7200 0 -02}
    {-1002495600 -3600 1 -01}
    {-986166000 -7200 0 -02}
    {-969231600 -3600 1 -01}
    {-950482800 -7200 0 -02}
    {-942015600 -3600 1 -01}
    {-922662000 -7200 0 -02}
    {-906937200 -3600 1 -01}
    {-891126000 -7200 0 -02}
    {-877302000 -3600 1 -01}
    {-864000000 -3600 0 -01}
    {-857948400 -7200 0 -02}
    {-845852400 -3600 1 -01}
    {-831340800 -3600 0 -01}
    {-825894000 -7200 0 -02}
    {-814402800 -3600 1 -01}
    {-799891200 -3600 0 -01}
    {-794444400 -7200 0 -02}
    {-782953200 -3600 1 -01}
    {-768441600 -3600 0 -01}
    {-762994800 -7200 0 -02}
    {-749084400 -3600 1 -01}
    {-733359600 -7200 0 -02}
    {-717624000 -3600 1 -01}
    {-701899200 -7200 0 -02}
    {-686174400 -3600 1 -01}
    {-670449600 -7200 0 -02}
    {-654724800 -3600 1 -01}
    {-639000000 -7200 0 -02}
    {-591825600 -3600 1 -01}
    {-575496000 -7200 0 -02}
    {-559771200 -3600 1 -01}
    {-544046400 -7200 0 -02}
    {-528321600 -3600 1 -01}
    {-512596800 -7200 0 -02}
    {-496872000 -3600 1 -01}
    {-481147200 -7200 0 -02}
    {-465422400 -3600 1 -01}
    {-449697600 -7200 0 -02}
    {-433972800 -3600 1 -01}
    {-417643200 -7200 0 -02}
    {-401918400 -3600 1 -01}
    {-386193600 -7200 0 -02}
    {-370468800 -3600 1 -01}
    {-354744000 -7200 0 -02}
    {-339019200 -3600 1 -01}
    {-323294400 -7200 0 -02}
    {-307569600 -3600 1 -01}
    {-291844800 -7200 0 -02}
    {-276120000 -3600 1 -01}
    {-260395200 -7200 0 -02}
    {-244670400 -3600 1 -01}
    {-228340800 -7200 0 -02}
    {-212616000 -3600 1 -01}
    {-196891200 -7200 0 -02}
    {-181166400 -3600 1 -01}
    {-165441600 -7200 0 -02}
    {-149716800 -3600 1 -01}
    {-133992000 -7200 0 -02}
    {-118267200 -3600 0 -01}
    {-1830376800 -7200 0 -0200}
    {-1689548400 -3600 1 -0100}
    {-1677794400 -7200 0 -0200}
    {-1667426400 -3600 1 -0100}
    {-1647730800 -7200 0 -0200}
    {-1635890400 -3600 1 -0100}
    {-1616194800 -7200 0 -0200}
    {-1604354400 -3600 1 -0100}
    {-1584658800 -7200 0 -0200}
    {-1572732000 -3600 1 -0100}
    {-1553036400 -7200 0 -0200}
    {-1541196000 -3600 1 -0100}
    {-1521500400 -7200 0 -0200}
    {-1442444400 -3600 1 -0100}
    {-1427670000 -7200 0 -0200}
    {-1379286000 -3600 1 -0100}
    {-1364770800 -7200 0 -0200}
    {-1348441200 -3600 1 -0100}
    {-1333321200 -7200 0 -0200}
    {-1316386800 -3600 1 -0100}
    {-1301266800 -7200 0 -0200}
    {-1284332400 -3600 1 -0100}
    {-1269817200 -7200 0 -0200}
    {-1221433200 -3600 1 -0100}
    {-1206918000 -7200 0 -0200}
    {-1191193200 -3600 1 -0100}
    {-1175468400 -7200 0 -0200}
    {-1127689200 -3600 1 -0100}
    {-1111964400 -7200 0 -0200}
    {-1096844400 -3600 1 -0100}
    {-1080514800 -7200 0 -0200}
    {-1063580400 -3600 1 -0100}
    {-1049065200 -7200 0 -0200}
    {-1033340400 -3600 1 -0100}
    {-1017615600 -7200 0 -0200}
    {-1002495600 -3600 1 -0100}
    {-986166000 -7200 0 -0200}
    {-969231600 -3600 1 -0100}
    {-950482800 -7200 0 -0200}
    {-942015600 -3600 1 -0100}
    {-922489200 -7200 0 -0200}
    {-906937200 -3600 1 -0100}
    {-891126000 -7200 0 -0200}
    {-877302000 -3600 1 -0100}
    {-873676800 0 1 +0000}
    {-864000000 -3600 1 -0100}
    {-857948400 -7200 0 -0200}
    {-845852400 -3600 1 -0100}
    {-842832000 0 1 +0000}
    {-831340800 -3600 1 -0100}
    {-825894000 -7200 0 -0200}
    {-814402800 -3600 1 -0100}
    {-810777600 0 1 +0000}
    {-799891200 -3600 1 -0100}
    {-794444400 -7200 0 -0200}
    {-782953200 -3600 1 -0100}
    {-779328000 0 1 +0000}
    {-768441600 -3600 1 -0100}
    {-762994800 -7200 0 -0200}
    {-749084400 -3600 1 -0100}
    {-733359600 -7200 0 -0200}
    {-717624000 -3600 1 -0100}
    {-701899200 -7200 0 -0200}
    {-686174400 -3600 1 -0100}
    {-670449600 -7200 0 -0200}
    {-654724800 -3600 1 -0100}
    {-639000000 -7200 0 -0200}
    {-623275200 -3600 1 -0100}
    {-607550400 -7200 0 -0200}
    {-591825600 -3600 1 -0100}
    {-575496000 -7200 0 -0200}
    {-559771200 -3600 1 -0100}
    {-544046400 -7200 0 -0200}
    {-528321600 -3600 1 -0100}
    {-512596800 -7200 0 -0200}
    {-496872000 -3600 1 -0100}
    {-481147200 -7200 0 -0200}
    {-465422400 -3600 1 -0100}
    {-449697600 -7200 0 -0200}
    {-433972800 -3600 1 -0100}
    {-417643200 -7200 0 -0200}
    {-401918400 -3600 1 -0100}
    {-386193600 -7200 0 -0200}
    {-370468800 -3600 1 -0100}
    {-354744000 -7200 0 -0200}
    {-339019200 -3600 1 -0100}
    {-323294400 -7200 0 -0200}
    {-307569600 -3600 1 -0100}
    {-291844800 -7200 0 -0200}
    {-276120000 -3600 1 -0100}
    {-260395200 -7200 0 -0200}
    {-244670400 -3600 1 -0100}
    {-228340800 -7200 0 -0200}
    {-212616000 -3600 1 -0100}
    {-196891200 -7200 0 -0200}
    {-181166400 -3600 1 -0100}
    {-165441600 -7200 0 -0200}
    {-149716800 -3600 1 -0100}
    {-133992000 -7200 0 -0200}
    {-118267200 -3600 1 -0100}
    {228272400 0 1 +00}
    {243997200 -3600 0 -01}
    {260326800 0 1 +00}
    {276051600 -3600 0 -01}
    {291776400 0 1 +00}
    {307504800 -3600 0 -01}
    {323226000 0 1 +00}
    {338954400 -3600 0 -01}
    {354679200 0 1 +00}
    {370404000 -3600 0 -01}
    {-102542400 -3600 0 -0100}
    {386125200 0 0 +0000}
    {401850000 -3600 0 -0100}
    {417574800 0 1 +0000}
    {433299600 -3600 0 -0100}
    {449024400 0 1 +0000}
    {465354000 -3600 0 -0100}
    {481078800 0 1 +0000}
    {496803600 -3600 0 -0100}
    {386128800 0 1 +00}
    {401853600 -3600 0 -01}
    {417582000 0 1 +00}
    {433303200 -3600 0 -01}
    {449028000 0 1 +00}
    {465357600 -3600 0 -01}
    {481082400 0 1 +00}
    {496807200 -3600 0 -01}
    {512532000 0 1 +00}
    {528256800 -3600 0 -01}
    {543981600 0 1 +00}
    {559706400 -3600 0 -01}
    {575431200 0 1 +00}
    {591156000 -3600 0 -01}
    {606880800 0 1 +00}
    {622605600 -3600 0 -01}
    {638330400 0 1 +00}
    {654660000 -3600 0 -01}
    {670384800 0 1 +00}
    {686109600 -3600 0 -01}
    {504925200 -3600 0 -0100}
    {512528400 0 1 +0000}
    {528253200 -3600 0 -0100}
    {543978000 0 1 +0000}
    {559702800 -3600 0 -0100}
    {575427600 0 1 +0000}
    {591152400 -3600 0 -0100}
    {606877200 0 1 +0000}
    {622602000 -3600 0 -0100}
    {638326800 0 1 +0000}
    {654656400 -3600 0 -0100}
    {670381200 0 1 +0000}
    {686106000 -3600 0 -0100}
    {701830800 0 1 +0000}
    {717555600 -3600 0 -0100}
    {725421600 0 0 WET}
    {733280400 3600 1 WEST}
    {740278800 0 0 +0000}
    {749005200 -3600 0 -0100}
    {701834400 0 1 +00}
    {733280400 0 0 +00}
    {749005200 -3600 0 -01}
    {764730000 0 1 +00}
    {780454800 -3600 0 -01}
    {796179600 0 1 +00}
    {811904400 -3600 0 -01}
    {828234000 0 1 +00}
    {846378000 -3600 0 -01}
    {859683600 0 1 +00}
    {877827600 -3600 0 -01}
    {891133200 0 1 +00}
    {909277200 -3600 0 -01}
    {922582800 0 1 +00}
    {941331600 -3600 0 -01}
    {954032400 0 1 +00}
    {972781200 -3600 0 -01}
    {985482000 0 1 +00}
    {1004230800 -3600 0 -01}
    {1017536400 0 1 +00}
    {1035680400 -3600 0 -01}
    {1048986000 0 1 +00}
    {1067130000 -3600 0 -01}
    {1080435600 0 1 +00}
    {1099184400 -3600 0 -01}
    {1111885200 0 1 +00}
    {1130634000 -3600 0 -01}
    {1143334800 0 1 +00}
    {1162083600 -3600 0 -01}
    {1174784400 0 1 +00}
    {1193533200 -3600 0 -01}
    {1206838800 0 1 +00}
    {1224982800 -3600 0 -01}
    {1238288400 0 1 +00}
    {1256432400 -3600 0 -01}
    {1269738000 0 1 +00}
    {1288486800 -3600 0 -01}
    {1301187600 0 1 +00}
    {1319936400 -3600 0 -01}
    {1332637200 0 1 +00}
    {1351386000 -3600 0 -01}
    {1364691600 0 1 +00}
    {1382835600 -3600 0 -01}
    {1396141200 0 1 +00}
    {1414285200 -3600 0 -01}
    {1427590800 0 1 +00}
    {1445734800 -3600 0 -01}
    {1459040400 0 1 +00}
    {1477789200 -3600 0 -01}
    {1490490000 0 1 +00}
    {1509238800 -3600 0 -01}
    {1521939600 0 1 +00}
    {1540688400 -3600 0 -01}
    {1553994000 0 1 +00}
    {1572138000 -3600 0 -01}
    {1585443600 0 1 +00}
    {1603587600 -3600 0 -01}
    {1616893200 0 1 +00}
    {1635642000 -3600 0 -01}
    {1648342800 0 1 +00}
    {1667091600 -3600 0 -01}
    {1679792400 0 1 +00}
    {1698541200 -3600 0 -01}
    {1711846800 0 1 +00}
    {1729990800 -3600 0 -01}
    {1743296400 0 1 +00}
    {1761440400 -3600 0 -01}
    {1774746000 0 1 +00}
    {1792890000 -3600 0 -01}
    {1806195600 0 1 +00}
    {1824944400 -3600 0 -01}
    {1837645200 0 1 +00}
    {1856394000 -3600 0 -01}
    {1869094800 0 1 +00}
    {1887843600 -3600 0 -01}
    {1901149200 0 1 +00}
    {1919293200 -3600 0 -01}
    {1932598800 0 1 +00}
    {1950742800 -3600 0 -01}
    {1964048400 0 1 +00}
    {1982797200 -3600 0 -01}
    {1995498000 0 1 +00}
    {2014246800 -3600 0 -01}
    {2026947600 0 1 +00}
    {2045696400 -3600 0 -01}
    {2058397200 0 1 +00}
    {2077146000 -3600 0 -01}
    {2090451600 0 1 +00}
    {2108595600 -3600 0 -01}
    {2121901200 0 1 +00}
    {2140045200 -3600 0 -01}
    {2153350800 0 1 +00}
    {2172099600 -3600 0 -01}
    {2184800400 0 1 +00}
    {2203549200 -3600 0 -01}
    {2216250000 0 1 +00}
    {2234998800 -3600 0 -01}
    {2248304400 0 1 +00}
    {2266448400 -3600 0 -01}
    {2279754000 0 1 +00}
    {2297898000 -3600 0 -01}
    {2311203600 0 1 +00}
    {2329347600 -3600 0 -01}
    {2342653200 0 1 +00}
    {2361402000 -3600 0 -01}
    {2374102800 0 1 +00}
    {2392851600 -3600 0 -01}
    {2405552400 0 1 +00}
    {2424301200 -3600 0 -01}
    {2437606800 0 1 +00}
    {2455750800 -3600 0 -01}
    {2469056400 0 1 +00}
    {2487200400 -3600 0 -01}
    {2500506000 0 1 +00}
    {2519254800 -3600 0 -01}
    {2531955600 0 1 +00}
    {2550704400 -3600 0 -01}
    {2563405200 0 1 +00}
    {2582154000 -3600 0 -01}
    {2595459600 0 1 +00}
    {2613603600 -3600 0 -01}
    {2626909200 0 1 +00}
    {2645053200 -3600 0 -01}
    {2658358800 0 1 +00}
    {2676502800 -3600 0 -01}
    {2689808400 0 1 +00}
    {2708557200 -3600 0 -01}
    {2721258000 0 1 +00}
    {2740006800 -3600 0 -01}
    {2752707600 0 1 +00}
    {2771456400 -3600 0 -01}
    {2784762000 0 1 +00}
    {2802906000 -3600 0 -01}
    {2816211600 0 1 +00}
    {2834355600 -3600 0 -01}
    {2847661200 0 1 +00}
    {2866410000 -3600 0 -01}
    {2879110800 0 1 +00}
    {2897859600 -3600 0 -01}
    {2910560400 0 1 +00}
    {2929309200 -3600 0 -01}
    {2942010000 0 1 +00}
    {2960758800 -3600 0 -01}
    {2974064400 0 1 +00}
    {2992208400 -3600 0 -01}
    {3005514000 0 1 +00}
    {3023658000 -3600 0 -01}
    {3036963600 0 1 +00}
    {3055712400 -3600 0 -01}
    {3068413200 0 1 +00}
    {3087162000 -3600 0 -01}
    {3099862800 0 1 +00}
    {3118611600 -3600 0 -01}
    {3131917200 0 1 +00}
    {3150061200 -3600 0 -01}
    {3163366800 0 1 +00}
    {3181510800 -3600 0 -01}
    {3194816400 0 1 +00}
    {3212960400 -3600 0 -01}
    {3226266000 0 1 +00}
    {3245014800 -3600 0 -01}
    {3257715600 0 1 +00}
    {3276464400 -3600 0 -01}
    {3289165200 0 1 +00}
    {3307914000 -3600 0 -01}
    {3321219600 0 1 +00}
    {3339363600 -3600 0 -01}
    {3352669200 0 1 +00}
    {3370813200 -3600 0 -01}
    {3384118800 0 1 +00}
    {3402867600 -3600 0 -01}
    {3415568400 0 1 +00}
    {3434317200 -3600 0 -01}
    {3447018000 0 1 +00}
    {3465766800 -3600 0 -01}
    {3479072400 0 1 +00}
    {3497216400 -3600 0 -01}
    {3510522000 0 1 +00}
    {3528666000 -3600 0 -01}
    {3541971600 0 1 +00}
    {3560115600 -3600 0 -01}
    {3573421200 0 1 +00}
    {3592170000 -3600 0 -01}
    {3604870800 0 1 +00}
    {3623619600 -3600 0 -01}
    {3636320400 0 1 +00}
    {3655069200 -3600 0 -01}
    {3668374800 0 1 +00}
    {3686518800 -3600 0 -01}
    {3699824400 0 1 +00}
    {3717968400 -3600 0 -01}
    {3731274000 0 1 +00}
    {3750022800 -3600 0 -01}
    {3762723600 0 1 +00}
    {3781472400 -3600 0 -01}
    {3794173200 0 1 +00}
    {3812922000 -3600 0 -01}
    {3825622800 0 1 +00}
    {3844371600 -3600 0 -01}
    {3857677200 0 1 +00}
    {3875821200 -3600 0 -01}
    {3889126800 0 1 +00}
    {3907270800 -3600 0 -01}
    {3920576400 0 1 +00}
    {3939325200 -3600 0 -01}
    {3952026000 0 1 +00}
    {3970774800 -3600 0 -01}
    {3983475600 0 1 +00}
    {4002224400 -3600 0 -01}
    {4015530000 0 1 +00}
    {4033674000 -3600 0 -01}
    {4046979600 0 1 +00}
    {4065123600 -3600 0 -01}
    {4078429200 0 1 +00}
    {4096573200 -3600 0 -01}
    {764730000 0 1 +0000}
    {780454800 -3600 0 -0100}
    {796179600 0 1 +0000}
    {811904400 -3600 0 -0100}
    {828234000 0 1 +0000}
    {846378000 -3600 0 -0100}
    {859683600 0 1 +0000}
    {877827600 -3600 0 -0100}
    {891133200 0 1 +0000}
    {909277200 -3600 0 -0100}
    {922582800 0 1 +0000}
    {941331600 -3600 0 -0100}
    {954032400 0 1 +0000}
    {972781200 -3600 0 -0100}
    {985482000 0 1 +0000}
    {1004230800 -3600 0 -0100}
    {1017536400 0 1 +0000}
    {1035680400 -3600 0 -0100}
    {1048986000 0 1 +0000}
    {1067130000 -3600 0 -0100}
    {1080435600 0 1 +0000}
    {1099184400 -3600 0 -0100}
    {1111885200 0 1 +0000}
    {1130634000 -3600 0 -0100}
    {1143334800 0 1 +0000}
    {1162083600 -3600 0 -0100}
    {1174784400 0 1 +0000}
    {1193533200 -3600 0 -0100}
    {1206838800 0 1 +0000}
    {1224982800 -3600 0 -0100}
    {1238288400 0 1 +0000}
    {1256432400 -3600 0 -0100}
    {1269738000 0 1 +0000}
    {1288486800 -3600 0 -0100}
    {1301187600 0 1 +0000}
    {1319936400 -3600 0 -0100}
    {1332637200 0 1 +0000}
    {1351386000 -3600 0 -0100}
    {1364691600 0 1 +0000}
    {1382835600 -3600 0 -0100}
    {1396141200 0 1 +0000}
    {1414285200 -3600 0 -0100}
    {1427590800 0 1 +0000}
    {1445734800 -3600 0 -0100}
    {1459040400 0 1 +0000}
    {1477789200 -3600 0 -0100}
    {1490490000 0 1 +0000}
    {1509238800 -3600 0 -0100}
    {1521939600 0 1 +0000}
    {1540688400 -3600 0 -0100}
    {1553994000 0 1 +0000}
    {1572138000 -3600 0 -0100}
    {1585443600 0 1 +0000}
    {1603587600 -3600 0 -0100}
    {1616893200 0 1 +0000}
    {1635642000 -3600 0 -0100}
    {1648342800 0 1 +0000}
    {1667091600 -3600 0 -0100}
    {1679792400 0 1 +0000}
    {1698541200 -3600 0 -0100}
    {1711846800 0 1 +0000}
    {1729990800 -3600 0 -0100}
    {1743296400 0 1 +0000}
    {1761440400 -3600 0 -0100}
    {1774746000 0 1 +0000}
    {1792890000 -3600 0 -0100}
    {1806195600 0 1 +0000}
    {1824944400 -3600 0 -0100}
    {1837645200 0 1 +0000}
    {1856394000 -3600 0 -0100}
    {1869094800 0 1 +0000}
    {1887843600 -3600 0 -0100}
    {1901149200 0 1 +0000}
    {1919293200 -3600 0 -0100}
    {1932598800 0 1 +0000}
    {1950742800 -3600 0 -0100}
    {1964048400 0 1 +0000}
    {1982797200 -3600 0 -0100}
    {1995498000 0 1 +0000}
    {2014246800 -3600 0 -0100}
    {2026947600 0 1 +0000}
    {2045696400 -3600 0 -0100}
    {2058397200 0 1 +0000}
    {2077146000 -3600 0 -0100}
    {2090451600 0 1 +0000}
    {2108595600 -3600 0 -0100}
    {2121901200 0 1 +0000}
    {2140045200 -3600 0 -0100}
    {2153350800 0 1 +0000}
    {2172099600 -3600 0 -0100}
    {2184800400 0 1 +0000}
    {2203549200 -3600 0 -0100}
    {2216250000 0 1 +0000}
    {2234998800 -3600 0 -0100}
    {2248304400 0 1 +0000}
    {2266448400 -3600 0 -0100}
    {2279754000 0 1 +0000}
    {2297898000 -3600 0 -0100}
    {2311203600 0 1 +0000}
    {2329347600 -3600 0 -0100}
    {2342653200 0 1 +0000}
    {2361402000 -3600 0 -0100}
    {2374102800 0 1 +0000}
    {2392851600 -3600 0 -0100}
    {2405552400 0 1 +0000}
    {2424301200 -3600 0 -0100}
    {2437606800 0 1 +0000}
    {2455750800 -3600 0 -0100}
    {2469056400 0 1 +0000}
    {2487200400 -3600 0 -0100}
    {2500506000 0 1 +0000}
    {2519254800 -3600 0 -0100}
    {2531955600 0 1 +0000}
    {2550704400 -3600 0 -0100}
    {2563405200 0 1 +0000}
    {2582154000 -3600 0 -0100}
    {2595459600 0 1 +0000}
    {2613603600 -3600 0 -0100}
    {2626909200 0 1 +0000}
    {2645053200 -3600 0 -0100}
    {2658358800 0 1 +0000}
    {2676502800 -3600 0 -0100}
    {2689808400 0 1 +0000}
    {2708557200 -3600 0 -0100}
    {2721258000 0 1 +0000}
    {2740006800 -3600 0 -0100}
    {2752707600 0 1 +0000}
    {2771456400 -3600 0 -0100}
    {2784762000 0 1 +0000}
    {2802906000 -3600 0 -0100}
    {2816211600 0 1 +0000}
    {2834355600 -3600 0 -0100}
    {2847661200 0 1 +0000}
    {2866410000 -3600 0 -0100}
    {2879110800 0 1 +0000}
    {2897859600 -3600 0 -0100}
    {2910560400 0 1 +0000}
    {2929309200 -3600 0 -0100}
    {2942010000 0 1 +0000}
    {2960758800 -3600 0 -0100}
    {2974064400 0 1 +0000}
    {2992208400 -3600 0 -0100}
    {3005514000 0 1 +0000}
    {3023658000 -3600 0 -0100}
    {3036963600 0 1 +0000}
    {3055712400 -3600 0 -0100}
    {3068413200 0 1 +0000}
    {3087162000 -3600 0 -0100}
    {3099862800 0 1 +0000}
    {3118611600 -3600 0 -0100}
    {3131917200 0 1 +0000}
    {3150061200 -3600 0 -0100}
    {3163366800 0 1 +0000}
    {3181510800 -3600 0 -0100}
    {3194816400 0 1 +0000}
    {3212960400 -3600 0 -0100}
    {3226266000 0 1 +0000}
    {3245014800 -3600 0 -0100}
    {3257715600 0 1 +0000}
    {3276464400 -3600 0 -0100}
    {3289165200 0 1 +0000}
    {3307914000 -3600 0 -0100}
    {3321219600 0 1 +0000}
    {3339363600 -3600 0 -0100}
    {3352669200 0 1 +0000}
    {3370813200 -3600 0 -0100}
    {3384118800 0 1 +0000}
    {3402867600 -3600 0 -0100}
    {3415568400 0 1 +0000}
    {3434317200 -3600 0 -0100}
    {3447018000 0 1 +0000}
    {3465766800 -3600 0 -0100}
    {3479072400 0 1 +0000}
    {3497216400 -3600 0 -0100}
    {3510522000 0 1 +0000}
    {3528666000 -3600 0 -0100}
    {3541971600 0 1 +0000}
    {3560115600 -3600 0 -0100}
    {3573421200 0 1 +0000}
    {3592170000 -3600 0 -0100}
    {3604870800 0 1 +0000}
    {3623619600 -3600 0 -0100}
    {3636320400 0 1 +0000}
    {3655069200 -3600 0 -0100}
    {3668374800 0 1 +0000}
    {3686518800 -3600 0 -0100}
    {3699824400 0 1 +0000}
    {3717968400 -3600 0 -0100}
    {3731274000 0 1 +0000}
    {3750022800 -3600 0 -0100}
    {3762723600 0 1 +0000}
    {3781472400 -3600 0 -0100}
    {3794173200 0 1 +0000}
    {3812922000 -3600 0 -0100}
    {3825622800 0 1 +0000}
    {3844371600 -3600 0 -0100}
    {3857677200 0 1 +0000}
    {3875821200 -3600 0 -0100}
    {3889126800 0 1 +0000}
    {3907270800 -3600 0 -0100}
    {3920576400 0 1 +0000}
    {3939325200 -3600 0 -0100}
    {3952026000 0 1 +0000}
    {3970774800 -3600 0 -0100}
    {3983475600 0 1 +0000}
    {4002224400 -3600 0 -0100}
    {4015530000 0 1 +0000}
    {4033674000 -3600 0 -0100}
    {4046979600 0 1 +0000}
    {4065123600 -3600 0 -0100}
    {4078429200 0 1 +0000}
    {4096573200 -3600 0 -0100}
}

Changes to library/tzdata/Atlantic/Bermuda.

1
2
3
4





5























6
7
8
9
10
11
12
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
30
31
32
33
34
35
36
37
38
39




+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Atlantic/Bermuda) {
    {-9223372036854775808 -15558 0 LMT}
    {-2524506042 -15558 0 BMT}
    {-1664307642 -11958 1 BMT}
    {-1648932042 -15558 0 BMT}
    {-1632080442 -11958 1 BMT}
    {-1618692042 -15558 0 BST}
    {-1262281242 -14400 0 AST}
    {-1262281242 -14400 0 AT}
    {-882727200 -10800 1 ADT}
    {-858538800 -14400 0 AST}
    {-845229600 -10800 1 ADT}
    {-825879600 -14400 0 AST}
    {-814384800 -10800 1 ADT}
    {-793825200 -14400 0 AST}
    {-782935200 -10800 1 ADT}
    {-762375600 -14400 0 AST}
    {-713988000 -10800 1 ADT}
    {-703710000 -14400 0 AST}
    {-681933600 -10800 1 ADT}
    {-672865200 -14400 0 AST}
    {-650484000 -10800 1 ADT}
    {-641415600 -14400 0 AST}
    {-618429600 -10800 1 ADT}
    {-609966000 -14400 0 AST}
    {-586980000 -10800 1 ADT}
    {-578516400 -14400 0 AST}
    {-555530400 -10800 1 ADT}
    {-546462000 -14400 0 AST}
    {-429127200 -10800 1 ADT}
    {-415825200 -14400 0 AST}
    {136360800 -10800 0 ADT}
    {152082000 -14400 0 AST}
    {167810400 -10800 1 ADT}
    {183531600 -14400 0 AST}
    {189316800 -14400 0 AST}
    {199260000 -10800 1 ADT}
    {215586000 -14400 0 AST}

Changes to library/tzdata/Atlantic/Canary.

1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Atlantic/Canary) {
    {-9223372036854775808 -3696 0 LMT}
    {-1509663504 -3600 0 -01}
    {-1509663504 -3600 0 -0100}
    {-733874400 0 0 WET}
    {323827200 3600 1 WEST}
    {338950800 0 0 WET}
    {354675600 3600 1 WEST}
    {370400400 0 0 WET}
    {386125200 3600 1 WEST}
    {401850000 0 0 WET}

Changes to library/tzdata/Atlantic/Cape_Verde.

1
2
3
4
5
6
7
8




9
1
2
3
4




5
6
7
8
9




-
-
-
-
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Atlantic/Cape_Verde) {
    {-9223372036854775808 -5644 0 LMT}
    {-1830376800 -7200 0 -02}
    {-862610400 -3600 1 -01}
    {-764118000 -7200 0 -02}
    {186120000 -3600 0 -01}
    {-1830376800 -7200 0 -0200}
    {-862610400 -3600 1 -0100}
    {-764118000 -7200 0 -0200}
    {186120000 -3600 0 -0100}
}

Changes to library/tzdata/Atlantic/Jan_Mayen.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Oslo)]} {
    LoadTimeZoneFile Europe/Oslo
if {![info exists TZData(Europe/Berlin)]} {
    LoadTimeZoneFile Europe/Berlin
}
set TZData(:Atlantic/Jan_Mayen) $TZData(:Europe/Oslo)
set TZData(:Atlantic/Jan_Mayen) $TZData(:Europe/Berlin)

Changes to library/tzdata/Atlantic/Madeira.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
-
-
-
-
-
+
-
-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Atlantic/Madeira) {
    {-9223372036854775808 -4056 0 LMT}
    {-2713906344 -4056 0 FMT}
    {-1830380400 -3600 0 -01}
    {-1689552000 0 1 +00}
    {-1677798000 -3600 0 -01}
    {-1667433600 0 1 +00}
    {-1647734400 -3600 0 -01}
    {-1635811200 0 1 +00}
    {-1616198400 -3600 0 -01}
    {-1604361600 0 1 +00}
    {-1584662400 -3600 0 -01}
    {-1572739200 0 1 +00}
    {-1553040000 -3600 0 -01}
    {-1541203200 0 1 +00}
    {-1521504000 -3600 0 -01}
    {-1442448000 0 1 +00}
    {-1426809600 -3600 0 -01}
    {-1379289600 0 1 +00}
    {-1364774400 -3600 0 -01}
    {-1348444800 0 1 +00}
    {-1333324800 -3600 0 -01}
    {-1316390400 0 1 +00}
    {-1301270400 -3600 0 -01}
    {-1284336000 0 1 +00}
    {-1269820800 -3600 0 -01}
    {-1221436800 0 1 +00}
    {-1206921600 -3600 0 -01}
    {-1191196800 0 1 +00}
    {-1175472000 -3600 0 -01}
    {-1127692800 0 1 +00}
    {-1111968000 -3600 0 -01}
    {-1096848000 0 1 +00}
    {-1080518400 -3600 0 -01}
    {-1063584000 0 1 +00}
    {-1049068800 -3600 0 -01}
    {-1033344000 0 1 +00}
    {-1017619200 -3600 0 -01}
    {-1002499200 0 1 +00}
    {-986169600 -3600 0 -01}
    {-969235200 0 1 +00}
    {-950486400 -3600 0 -01}
    {-942019200 0 1 +00}
    {-922665600 -3600 0 -01}
    {-906940800 0 1 +00}
    {-891129600 -3600 0 -01}
    {-877305600 0 1 +00}
    {-864003600 0 0 +00}
    {-857952000 -3600 0 -01}
    {-845856000 0 1 +00}
    {-831344400 0 0 +00}
    {-825897600 -3600 0 -01}
    {-814406400 0 1 +00}
    {-799894800 0 0 +00}
    {-794448000 -3600 0 -01}
    {-782956800 0 1 +00}
    {-768445200 0 0 +00}
    {-762998400 -3600 0 -01}
    {-749088000 0 1 +00}
    {-733363200 -3600 0 -01}
    {-717627600 0 1 +00}
    {-701902800 -3600 0 -01}
    {-686178000 0 1 +00}
    {-670453200 -3600 0 -01}
    {-654728400 0 1 +00}
    {-639003600 -3600 0 -01}
    {-591829200 0 1 +00}
    {-575499600 -3600 0 -01}
    {-559774800 0 1 +00}
    {-544050000 -3600 0 -01}
    {-528325200 0 1 +00}
    {-512600400 -3600 0 -01}
    {-496875600 0 1 +00}
    {-481150800 -3600 0 -01}
    {-465426000 0 1 +00}
    {-449701200 -3600 0 -01}
    {-433976400 0 1 +00}
    {-417646800 -3600 0 -01}
    {-401922000 0 1 +00}
    {-386197200 -3600 0 -01}
    {-370472400 0 1 +00}
    {-354747600 -3600 0 -01}
    {-339022800 0 1 +00}
    {-323298000 -3600 0 -01}
    {-307573200 0 1 +00}
    {-291848400 -3600 0 -01}
    {-276123600 0 1 +00}
    {-260398800 -3600 0 -01}
    {-244674000 0 1 +00}
    {-228344400 -3600 0 -01}
    {-212619600 0 1 +00}
    {-196894800 -3600 0 -01}
    {-181170000 0 1 +00}
    {-165445200 -3600 0 -01}
    {-149720400 0 1 +00}
    {-133995600 -3600 0 -01}
    {-118270800 0 0 WET}
    {-1830380400 -3600 0 -0100}
    {-1689552000 0 1 +0000}
    {-1677798000 -3600 0 -0100}
    {-1667430000 0 1 +0000}
    {-1647734400 -3600 0 -0100}
    {-1635894000 0 1 +0000}
    {-1616198400 -3600 0 -0100}
    {-1604358000 0 1 +0000}
    {-1584662400 -3600 0 -0100}
    {-1572735600 0 1 +0000}
    {-1553040000 -3600 0 -0100}
    {-1541199600 0 1 +0000}
    {-1521504000 -3600 0 -0100}
    {-1442448000 0 1 +0000}
    {-1427673600 -3600 0 -0100}
    {-1379289600 0 1 +0000}
    {-1364774400 -3600 0 -0100}
    {-1348444800 0 1 +0000}
    {-1333324800 -3600 0 -0100}
    {-1316390400 0 1 +0000}
    {-1301270400 -3600 0 -0100}
    {-1284336000 0 1 +0000}
    {-1269820800 -3600 0 -0100}
    {-1221436800 0 1 +0000}
    {-1206921600 -3600 0 -0100}
    {-1191196800 0 1 +0000}
    {-1175472000 -3600 0 -0100}
    {-1127692800 0 1 +0000}
    {-1111968000 -3600 0 -0100}
    {-1096848000 0 1 +0000}
    {-1080518400 -3600 0 -0100}
    {-1063584000 0 1 +0000}
    {-1049068800 -3600 0 -0100}
    {-1033344000 0 1 +0000}
    {-1017619200 -3600 0 -0100}
    {-1002499200 0 1 +0000}
    {-986169600 -3600 0 -0100}
    {-969235200 0 1 +0000}
    {-950486400 -3600 0 -0100}
    {-942019200 0 1 +0000}
    {-922492800 -3600 0 -0100}
    {-906940800 0 1 +0000}
    {-891129600 -3600 0 -0100}
    {-877305600 0 1 +0000}
    {-873680400 3600 1 +0100}
    {-864003600 0 1 +0000}
    {-857952000 -3600 0 -0100}
    {-845856000 0 1 +0000}
    {-842835600 3600 1 +0100}
    {-831344400 0 1 +0000}
    {-825897600 -3600 0 -0100}
    {-814406400 0 1 +0000}
    {-810781200 3600 1 +0100}
    {-799894800 0 1 +0000}
    {-794448000 -3600 0 -0100}
    {-782956800 0 1 +0000}
    {-779331600 3600 1 +0100}
    {-768445200 0 1 +0000}
    {-762998400 -3600 0 -0100}
    {-749088000 0 1 +0000}
    {-733363200 -3600 0 -0100}
    {-717627600 0 1 +0000}
    {-701902800 -3600 0 -0100}
    {-686178000 0 1 +0000}
    {-670453200 -3600 0 -0100}
    {-654728400 0 1 +0000}
    {-639003600 -3600 0 -0100}
    {-623278800 0 1 +0000}
    {-607554000 -3600 0 -0100}
    {-591829200 0 1 +0000}
    {-575499600 -3600 0 -0100}
    {-559774800 0 1 +0000}
    {-544050000 -3600 0 -0100}
    {-528325200 0 1 +0000}
    {-512600400 -3600 0 -0100}
    {-496875600 0 1 +0000}
    {-481150800 -3600 0 -0100}
    {-465426000 0 1 +0000}
    {-449701200 -3600 0 -0100}
    {-433976400 0 1 +0000}
    {-417646800 -3600 0 -0100}
    {-401922000 0 1 +0000}
    {-386197200 -3600 0 -0100}
    {-370472400 0 1 +0000}
    {-354747600 -3600 0 -0100}
    {-339022800 0 1 +0000}
    {-323298000 -3600 0 -0100}
    {-307573200 0 1 +0000}
    {-291848400 -3600 0 -0100}
    {-276123600 0 1 +0000}
    {-260398800 -3600 0 -0100}
    {-244674000 0 1 +0000}
    {-228344400 -3600 0 -0100}
    {-212619600 0 1 +0000}
    {-196894800 -3600 0 -0100}
    {-181170000 0 1 +0000}
    {-165445200 -3600 0 -0100}
    {-149720400 0 1 +0000}
    {-133995600 -3600 0 -0100}
    {-118270800 0 1 +0000}
    {228268800 3600 1 WEST}
    {243993600 0 0 WET}
    {260323200 3600 1 WEST}
    {276048000 0 0 WET}
    {291772800 3600 1 WEST}
    {307501200 0 0 WET}
    {323222400 3600 1 WEST}
    {-102546000 0 0 WET}
    {386726400 3600 0 WEST}
    {401846400 0 0 WET}
    {417571200 3600 1 WEST}
    {433296000 0 0 WET}
    {449020800 3600 1 WEST}
    {338950800 0 0 WET}
    {354675600 3600 1 WEST}
    {370400400 0 0 WET}
    {386125200 3600 1 WEST}
    {401850000 0 0 WET}
    {465350400 0 0 WET}
    {481075200 3600 1 WEST}
    {496800000 0 0 WET}
    {417578400 3600 1 WEST}
    {433299600 0 0 WET}
    {449024400 3600 1 WEST}
    {465354000 0 0 WET}
    {481078800 3600 1 WEST}
    {512524800 3600 1 WEST}
    {496803600 0 0 WET}
    {512528400 3600 1 WEST}
    {523148400 3600 0 WEST}
    {528253200 0 0 WET}
    {543978000 3600 1 WEST}
    {559702800 0 0 WET}
    {575427600 3600 1 WEST}
    {591152400 0 0 WET}
    {606877200 3600 1 WEST}
    {622602000 0 0 WET}

Changes to library/tzdata/Atlantic/Reykjavik.

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
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
1
2
3


4
5







































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Africa/Abidjan)]} {
    LoadTimeZoneFile Africa/Abidjan

set TZData(:Atlantic/Reykjavik) {
}
set TZData(:Atlantic/Reykjavik) $TZData(:Africa/Abidjan)
    {-9223372036854775808 -5280 0 LMT}
    {-1956609120 -3600 0 -01}
    {-1668211200 0 1 -01}
    {-1647212400 -3600 0 -01}
    {-1636675200 0 1 -01}
    {-1613430000 -3600 0 -01}
    {-1605139200 0 1 -01}
    {-1581894000 -3600 0 -01}
    {-1539561600 0 1 -01}
    {-1531350000 -3600 0 -01}
    {-968025600 0 1 -01}
    {-952293600 -3600 0 -01}
    {-942008400 0 1 -01}
    {-920239200 -3600 0 -01}
    {-909957600 0 1 -01}
    {-888789600 -3600 0 -01}
    {-877903200 0 1 -01}
    {-857944800 -3600 0 -01}
    {-846453600 0 1 -01}
    {-826495200 -3600 0 -01}
    {-815004000 0 1 -01}
    {-795045600 -3600 0 -01}
    {-783554400 0 1 -01}
    {-762991200 -3600 0 -01}
    {-752104800 0 1 -01}
    {-731541600 -3600 0 -01}
    {-717631200 0 1 -01}
    {-700092000 -3600 0 -01}
    {-686181600 0 1 -01}
    {-668642400 -3600 0 -01}
    {-654732000 0 1 -01}
    {-636588000 -3600 0 -01}
    {-623282400 0 1 -01}
    {-605743200 -3600 0 -01}
    {-591832800 0 1 -01}
    {-573688800 -3600 0 -01}
    {-559778400 0 1 -01}
    {-542239200 -3600 0 -01}
    {-528328800 0 1 -01}
    {-510789600 -3600 0 -01}
    {-496879200 0 1 -01}
    {-479340000 -3600 0 -01}
    {-465429600 0 1 -01}
    {-447890400 -3600 0 -01}
    {-433980000 0 1 -01}
    {-415836000 -3600 0 -01}
    {-401925600 0 1 -01}
    {-384386400 -3600 0 -01}
    {-370476000 0 1 -01}
    {-352936800 -3600 0 -01}
    {-339026400 0 1 -01}
    {-321487200 -3600 0 -01}
    {-307576800 0 1 -01}
    {-290037600 -3600 0 -01}
    {-276127200 0 1 -01}
    {-258588000 -3600 0 -01}
    {-244677600 0 1 -01}
    {-226533600 -3600 0 -01}
    {-212623200 0 1 -01}
    {-195084000 -3600 0 -01}
    {-181173600 0 1 -01}
    {-163634400 -3600 0 -01}
    {-149724000 0 1 -01}
    {-132184800 -3600 0 -01}
    {-118274400 0 1 -01}
    {-100735200 -3600 0 -01}
    {-86824800 0 1 -01}
    {-68680800 -3600 0 -01}
    {-54770400 0 0 GMT}
}

Changes to library/tzdata/Atlantic/South_Georgia.

1
2
3
4
5

6
1
2
3
4

5
6




-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Atlantic/South_Georgia) {
    {-9223372036854775808 -8768 0 LMT}
    {-2524512832 -7200 0 -02}
    {-2524512832 -7200 0 -0200}
}

Changes to library/tzdata/Atlantic/Stanley.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Atlantic/Stanley) {
    {-9223372036854775808 -13884 0 LMT}
    {-2524507716 -13884 0 SMT}
    {-1824235716 -14400 0 -04}
    {-1018209600 -10800 1 -04}
    {-1003093200 -14400 0 -04}
    {-986760000 -10800 1 -04}
    {-971643600 -14400 0 -04}
    {-954705600 -10800 1 -04}
    {-939589200 -14400 0 -04}
    {-923256000 -10800 1 -04}
    {-908139600 -14400 0 -04}
    {-891806400 -10800 1 -04}
    {-876690000 -14400 0 -04}
    {-860356800 -10800 1 -04}
    {420606000 -7200 0 -03}
    {433303200 -7200 1 -03}
    {452052000 -10800 0 -03}
    {464151600 -7200 1 -03}
    {483501600 -10800 0 -03}
    {495597600 -14400 0 -04}
    {495604800 -10800 1 -04}
    {514350000 -14400 0 -04}
    {527054400 -10800 1 -04}
    {545799600 -14400 0 -04}
    {558504000 -10800 1 -04}
    {577249200 -14400 0 -04}
    {589953600 -10800 1 -04}
    {608698800 -14400 0 -04}
    {621403200 -10800 1 -04}
    {640753200 -14400 0 -04}
    {652852800 -10800 1 -04}
    {672202800 -14400 0 -04}
    {684907200 -10800 1 -04}
    {703652400 -14400 0 -04}
    {716356800 -10800 1 -04}
    {735102000 -14400 0 -04}
    {747806400 -10800 1 -04}
    {766551600 -14400 0 -04}
    {779256000 -10800 1 -04}
    {798001200 -14400 0 -04}
    {810705600 -10800 1 -04}
    {830055600 -14400 0 -04}
    {842760000 -10800 1 -04}
    {861505200 -14400 0 -04}
    {874209600 -10800 1 -04}
    {892954800 -14400 0 -04}
    {905659200 -10800 1 -04}
    {924404400 -14400 0 -04}
    {937108800 -10800 1 -04}
    {955854000 -14400 0 -04}
    {968558400 -10800 1 -04}
    {987310800 -14400 0 -04}
    {999410400 -10800 1 -04}
    {1019365200 -14400 0 -04}
    {1030860000 -10800 1 -04}
    {1050814800 -14400 0 -04}
    {1062914400 -10800 1 -04}
    {1082264400 -14400 0 -04}
    {1094364000 -10800 1 -04}
    {1113714000 -14400 0 -04}
    {1125813600 -10800 1 -04}
    {1145163600 -14400 0 -04}
    {1157263200 -10800 1 -04}
    {1176613200 -14400 0 -04}
    {1188712800 -10800 1 -04}
    {1208667600 -14400 0 -04}
    {1220767200 -10800 1 -04}
    {1240117200 -14400 0 -04}
    {1252216800 -10800 1 -04}
    {1271566800 -14400 0 -04}
    {1283662800 -10800 0 -03}
    {-1824235716 -14400 0 -0400}
    {-1018209600 -10800 1 -0300}
    {-1003093200 -14400 0 -0400}
    {-986760000 -10800 1 -0300}
    {-971643600 -14400 0 -0400}
    {-954705600 -10800 1 -0300}
    {-939589200 -14400 0 -0400}
    {-923256000 -10800 1 -0300}
    {-908139600 -14400 0 -0400}
    {-891806400 -10800 1 -0300}
    {-876690000 -14400 0 -0400}
    {-860356800 -10800 1 -0300}
    {420606000 -7200 0 -0200}
    {433303200 -7200 1 -0200}
    {452052000 -10800 0 -0300}
    {464151600 -7200 1 -0200}
    {483501600 -10800 0 -0300}
    {495597600 -14400 0 -0400}
    {495604800 -10800 1 -0300}
    {514350000 -14400 0 -0400}
    {527054400 -10800 1 -0300}
    {545799600 -14400 0 -0400}
    {558504000 -10800 1 -0300}
    {577249200 -14400 0 -0400}
    {589953600 -10800 1 -0300}
    {608698800 -14400 0 -0400}
    {621403200 -10800 1 -0300}
    {640753200 -14400 0 -0400}
    {652852800 -10800 1 -0300}
    {672202800 -14400 0 -0400}
    {684907200 -10800 1 -0300}
    {703652400 -14400 0 -0400}
    {716356800 -10800 1 -0300}
    {735102000 -14400 0 -0400}
    {747806400 -10800 1 -0300}
    {766551600 -14400 0 -0400}
    {779256000 -10800 1 -0300}
    {798001200 -14400 0 -0400}
    {810705600 -10800 1 -0300}
    {830055600 -14400 0 -0400}
    {842760000 -10800 1 -0300}
    {861505200 -14400 0 -0400}
    {874209600 -10800 1 -0300}
    {892954800 -14400 0 -0400}
    {905659200 -10800 1 -0300}
    {924404400 -14400 0 -0400}
    {937108800 -10800 1 -0300}
    {955854000 -14400 0 -0400}
    {968558400 -10800 1 -0300}
    {987310800 -14400 0 -0400}
    {999410400 -10800 1 -0300}
    {1019365200 -14400 0 -0400}
    {1030860000 -10800 1 -0300}
    {1050814800 -14400 0 -0400}
    {1062914400 -10800 1 -0300}
    {1082264400 -14400 0 -0400}
    {1094364000 -10800 1 -0300}
    {1113714000 -14400 0 -0400}
    {1125813600 -10800 1 -0300}
    {1145163600 -14400 0 -0400}
    {1157263200 -10800 1 -0300}
    {1176613200 -14400 0 -0400}
    {1188712800 -10800 1 -0300}
    {1208667600 -14400 0 -0400}
    {1220767200 -10800 1 -0300}
    {1240117200 -14400 0 -0400}
    {1252216800 -10800 1 -0300}
    {1271566800 -14400 0 -0400}
    {1283662800 -10800 0 -0300}
}

Changes to library/tzdata/Australia/Adelaide.

1
2
3
4
5
6
7
8


9
10

11
12

13
14

15
16
17
18
19
20
21
1
2
3
4
5
6


7
8
9

10
11

12
13

14
15
16
17
18
19
20
21






-
-
+
+

-
+

-
+

-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Adelaide) {
    {-9223372036854775808 33260 0 LMT}
    {-2364110060 32400 0 ACST}
    {-2230189200 34200 0 ACST}
    {-1672565340 37800 1 ACDT}
    {-1665390600 34200 0 ACST}
    {-1672558200 37800 1 ACDT}
    {-1665387000 34200 0 ACST}
    {-883639800 37800 1 ACDT}
    {-876126600 34200 0 ACST}
    {-876123000 34200 0 ACST}
    {-860398200 37800 1 ACDT}
    {-844677000 34200 0 ACST}
    {-844673400 34200 0 ACST}
    {-828343800 37800 1 ACDT}
    {-813227400 34200 0 ACST}
    {-813223800 34200 0 ACST}
    {31501800 34200 0 ACST}
    {57688200 37800 1 ACDT}
    {67969800 34200 0 ACST}
    {89137800 37800 1 ACDT}
    {100024200 34200 0 ACST}
    {120587400 37800 1 ACDT}
    {131473800 34200 0 ACST}

Changes to library/tzdata/Australia/Brisbane.

1
2
3
4
5
6
7


8
9

10
11

12
13

14
15
16
17
18
19
20
1
2
3
4
5


6
7
8

9
10

11
12

13
14
15
16
17
18
19
20





-
-
+
+

-
+

-
+

-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Brisbane) {
    {-9223372036854775808 36728 0 LMT}
    {-2366791928 36000 0 AEST}
    {-1672567140 39600 1 AEDT}
    {-1665392400 36000 0 AEST}
    {-1672560000 39600 1 AEDT}
    {-1665388800 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876128400 36000 0 AEST}
    {-876124800 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844678800 36000 0 AEST}
    {-844675200 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813229200 36000 0 AEST}
    {-813225600 36000 0 AEST}
    {31500000 36000 0 AEST}
    {57686400 39600 1 AEDT}
    {67968000 36000 0 AEST}
    {625593600 39600 1 AEDT}
    {636480000 36000 0 AEST}
    {657043200 39600 1 AEDT}
    {667929600 36000 0 AEST}

Changes to library/tzdata/Australia/Broken_Hill.

1
2
3
4
5
6
7
8
9


10
11

12
13

14
15

16
17
18
19
20
21
22
1
2
3
4
5
6
7


8
9
10

11
12

13
14

15
16
17
18
19
20
21
22







-
-
+
+

-
+

-
+

-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Broken_Hill) {
    {-9223372036854775808 33948 0 LMT}
    {-2364110748 36000 0 AEST}
    {-2314951200 32400 0 ACST}
    {-2230189200 34200 0 ACST}
    {-1672565340 37800 1 ACDT}
    {-1665390600 34200 0 ACST}
    {-1672558200 37800 1 ACDT}
    {-1665387000 34200 0 ACST}
    {-883639800 37800 1 ACDT}
    {-876126600 34200 0 ACST}
    {-876123000 34200 0 ACST}
    {-860398200 37800 1 ACDT}
    {-844677000 34200 0 ACST}
    {-844673400 34200 0 ACST}
    {-828343800 37800 1 ACDT}
    {-813227400 34200 0 ACST}
    {-813223800 34200 0 ACST}
    {31501800 34200 0 ACST}
    {57688200 37800 1 ACDT}
    {67969800 34200 0 ACST}
    {89137800 37800 1 ACDT}
    {100024200 34200 0 ACST}
    {120587400 37800 1 ACDT}
    {131473800 34200 0 ACST}

Changes to library/tzdata/Australia/Currie.

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
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
1
2
3


4
5















































































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Australia/Hobart)]} {
    LoadTimeZoneFile Australia/Hobart

set TZData(:Australia/Currie) {
}
set TZData(:Australia/Currie) $TZData(:Australia/Hobart)
    {-9223372036854775808 34528 0 LMT}
    {-2345794528 36000 0 AEST}
    {-1680508800 39600 1 AEDT}
    {-1669892400 39600 0 AEDT}
    {-1665392400 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876128400 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844678800 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813229200 36000 0 AEST}
    {47138400 36000 0 AEST}
    {57686400 39600 1 AEDT}
    {67968000 36000 0 AEST}
    {89136000 39600 1 AEDT}
    {100022400 36000 0 AEST}
    {120585600 39600 1 AEDT}
    {131472000 36000 0 AEST}
    {152035200 39600 1 AEDT}
    {162921600 36000 0 AEST}
    {183484800 39600 1 AEDT}
    {194976000 36000 0 AEST}
    {215539200 39600 1 AEDT}
    {226425600 36000 0 AEST}
    {246988800 39600 1 AEDT}
    {257875200 36000 0 AEST}
    {278438400 39600 1 AEDT}
    {289324800 36000 0 AEST}
    {309888000 39600 1 AEDT}
    {320774400 36000 0 AEST}
    {341337600 39600 1 AEDT}
    {352224000 36000 0 AEST}
    {372787200 39600 1 AEDT}
    {386092800 36000 0 AEST}
    {404841600 39600 1 AEDT}
    {417542400 36000 0 AEST}
    {436291200 39600 1 AEDT}
    {447177600 36000 0 AEST}
    {467740800 39600 1 AEDT}
    {478627200 36000 0 AEST}
    {499190400 39600 1 AEDT}
    {510076800 36000 0 AEST}
    {530035200 39600 1 AEDT}
    {542736000 36000 0 AEST}
    {562089600 39600 1 AEDT}
    {574790400 36000 0 AEST}
    {594144000 39600 1 AEDT}
    {606240000 36000 0 AEST}
    {625593600 39600 1 AEDT}
    {637689600 36000 0 AEST}
    {657043200 39600 1 AEDT}
    {670348800 36000 0 AEST}
    {686678400 39600 1 AEDT}
    {701798400 36000 0 AEST}
    {718128000 39600 1 AEDT}
    {733248000 36000 0 AEST}
    {749577600 39600 1 AEDT}
    {764697600 36000 0 AEST}
    {781027200 39600 1 AEDT}
    {796147200 36000 0 AEST}
    {812476800 39600 1 AEDT}
    {828201600 36000 0 AEST}
    {844531200 39600 1 AEDT}
    {859651200 36000 0 AEST}
    {875980800 39600 1 AEDT}
    {891100800 36000 0 AEST}
    {907430400 39600 1 AEDT}
    {922550400 36000 0 AEST}
    {938880000 39600 1 AEDT}
    {954000000 36000 0 AEST}
    {967305600 39600 1 AEDT}
    {985449600 36000 0 AEST}
    {1002384000 39600 1 AEDT}
    {1017504000 36000 0 AEST}
    {1033833600 39600 1 AEDT}
    {1048953600 36000 0 AEST}
    {1065283200 39600 1 AEDT}
    {1080403200 36000 0 AEST}
    {1096732800 39600 1 AEDT}
    {1111852800 36000 0 AEST}
    {1128182400 39600 1 AEDT}
    {1143907200 36000 0 AEST}
    {1159632000 39600 1 AEDT}
    {1174752000 36000 0 AEST}
    {1191686400 39600 1 AEDT}
    {1207411200 36000 0 AEST}
    {1223136000 39600 1 AEDT}
    {1238860800 36000 0 AEST}
    {1254585600 39600 1 AEDT}
    {1270310400 36000 0 AEST}
    {1286035200 39600 1 AEDT}
    {1301760000 36000 0 AEST}
    {1317484800 39600 1 AEDT}
    {1333209600 36000 0 AEST}
    {1349539200 39600 1 AEDT}
    {1365264000 36000 0 AEST}
    {1380988800 39600 1 AEDT}
    {1396713600 36000 0 AEST}
    {1412438400 39600 1 AEDT}
    {1428163200 36000 0 AEST}
    {1443888000 39600 1 AEDT}
    {1459612800 36000 0 AEST}
    {1475337600 39600 1 AEDT}
    {1491062400 36000 0 AEST}
    {1506787200 39600 1 AEDT}
    {1522512000 36000 0 AEST}
    {1538841600 39600 1 AEDT}
    {1554566400 36000 0 AEST}
    {1570291200 39600 1 AEDT}
    {1586016000 36000 0 AEST}
    {1601740800 39600 1 AEDT}
    {1617465600 36000 0 AEST}
    {1633190400 39600 1 AEDT}
    {1648915200 36000 0 AEST}
    {1664640000 39600 1 AEDT}
    {1680364800 36000 0 AEST}
    {1696089600 39600 1 AEDT}
    {1712419200 36000 0 AEST}
    {1728144000 39600 1 AEDT}
    {1743868800 36000 0 AEST}
    {1759593600 39600 1 AEDT}
    {1775318400 36000 0 AEST}
    {1791043200 39600 1 AEDT}
    {1806768000 36000 0 AEST}
    {1822492800 39600 1 AEDT}
    {1838217600 36000 0 AEST}
    {1853942400 39600 1 AEDT}
    {1869667200 36000 0 AEST}
    {1885996800 39600 1 AEDT}
    {1901721600 36000 0 AEST}
    {1917446400 39600 1 AEDT}
    {1933171200 36000 0 AEST}
    {1948896000 39600 1 AEDT}
    {1964620800 36000 0 AEST}
    {1980345600 39600 1 AEDT}
    {1996070400 36000 0 AEST}
    {2011795200 39600 1 AEDT}
    {2027520000 36000 0 AEST}
    {2043244800 39600 1 AEDT}
    {2058969600 36000 0 AEST}
    {2075299200 39600 1 AEDT}
    {2091024000 36000 0 AEST}
    {2106748800 39600 1 AEDT}
    {2122473600 36000 0 AEST}
    {2138198400 39600 1 AEDT}
    {2153923200 36000 0 AEST}
    {2169648000 39600 1 AEDT}
    {2185372800 36000 0 AEST}
    {2201097600 39600 1 AEDT}
    {2216822400 36000 0 AEST}
    {2233152000 39600 1 AEDT}
    {2248876800 36000 0 AEST}
    {2264601600 39600 1 AEDT}
    {2280326400 36000 0 AEST}
    {2296051200 39600 1 AEDT}
    {2311776000 36000 0 AEST}
    {2327500800 39600 1 AEDT}
    {2343225600 36000 0 AEST}
    {2358950400 39600 1 AEDT}
    {2374675200 36000 0 AEST}
    {2390400000 39600 1 AEDT}
    {2406124800 36000 0 AEST}
    {2422454400 39600 1 AEDT}
    {2438179200 36000 0 AEST}
    {2453904000 39600 1 AEDT}
    {2469628800 36000 0 AEST}
    {2485353600 39600 1 AEDT}
    {2501078400 36000 0 AEST}
    {2516803200 39600 1 AEDT}
    {2532528000 36000 0 AEST}
    {2548252800 39600 1 AEDT}
    {2563977600 36000 0 AEST}
    {2579702400 39600 1 AEDT}
    {2596032000 36000 0 AEST}
    {2611756800 39600 1 AEDT}
    {2627481600 36000 0 AEST}
    {2643206400 39600 1 AEDT}
    {2658931200 36000 0 AEST}
    {2674656000 39600 1 AEDT}
    {2690380800 36000 0 AEST}
    {2706105600 39600 1 AEDT}
    {2721830400 36000 0 AEST}
    {2737555200 39600 1 AEDT}
    {2753280000 36000 0 AEST}
    {2769609600 39600 1 AEDT}
    {2785334400 36000 0 AEST}
    {2801059200 39600 1 AEDT}
    {2816784000 36000 0 AEST}
    {2832508800 39600 1 AEDT}
    {2848233600 36000 0 AEST}
    {2863958400 39600 1 AEDT}
    {2879683200 36000 0 AEST}
    {2895408000 39600 1 AEDT}
    {2911132800 36000 0 AEST}
    {2926857600 39600 1 AEDT}
    {2942582400 36000 0 AEST}
    {2958912000 39600 1 AEDT}
    {2974636800 36000 0 AEST}
    {2990361600 39600 1 AEDT}
    {3006086400 36000 0 AEST}
    {3021811200 39600 1 AEDT}
    {3037536000 36000 0 AEST}
    {3053260800 39600 1 AEDT}
    {3068985600 36000 0 AEST}
    {3084710400 39600 1 AEDT}
    {3100435200 36000 0 AEST}
    {3116764800 39600 1 AEDT}
    {3132489600 36000 0 AEST}
    {3148214400 39600 1 AEDT}
    {3163939200 36000 0 AEST}
    {3179664000 39600 1 AEDT}
    {3195388800 36000 0 AEST}
    {3211113600 39600 1 AEDT}
    {3226838400 36000 0 AEST}
    {3242563200 39600 1 AEDT}
    {3258288000 36000 0 AEST}
    {3274012800 39600 1 AEDT}
    {3289737600 36000 0 AEST}
    {3306067200 39600 1 AEDT}
    {3321792000 36000 0 AEST}
    {3337516800 39600 1 AEDT}
    {3353241600 36000 0 AEST}
    {3368966400 39600 1 AEDT}
    {3384691200 36000 0 AEST}
    {3400416000 39600 1 AEDT}
    {3416140800 36000 0 AEST}
    {3431865600 39600 1 AEDT}
    {3447590400 36000 0 AEST}
    {3463315200 39600 1 AEDT}
    {3479644800 36000 0 AEST}
    {3495369600 39600 1 AEDT}
    {3511094400 36000 0 AEST}
    {3526819200 39600 1 AEDT}
    {3542544000 36000 0 AEST}
    {3558268800 39600 1 AEDT}
    {3573993600 36000 0 AEST}
    {3589718400 39600 1 AEDT}
    {3605443200 36000 0 AEST}
    {3621168000 39600 1 AEDT}
    {3636892800 36000 0 AEST}
    {3653222400 39600 1 AEDT}
    {3668947200 36000 0 AEST}
    {3684672000 39600 1 AEDT}
    {3700396800 36000 0 AEST}
    {3716121600 39600 1 AEDT}
    {3731846400 36000 0 AEST}
    {3747571200 39600 1 AEDT}
    {3763296000 36000 0 AEST}
    {3779020800 39600 1 AEDT}
    {3794745600 36000 0 AEST}
    {3810470400 39600 1 AEDT}
    {3826195200 36000 0 AEST}
    {3842524800 39600 1 AEDT}
    {3858249600 36000 0 AEST}
    {3873974400 39600 1 AEDT}
    {3889699200 36000 0 AEST}
    {3905424000 39600 1 AEDT}
    {3921148800 36000 0 AEST}
    {3936873600 39600 1 AEDT}
    {3952598400 36000 0 AEST}
    {3968323200 39600 1 AEDT}
    {3984048000 36000 0 AEST}
    {4000377600 39600 1 AEDT}
    {4016102400 36000 0 AEST}
    {4031827200 39600 1 AEDT}
    {4047552000 36000 0 AEST}
    {4063276800 39600 1 AEDT}
    {4079001600 36000 0 AEST}
    {4094726400 39600 1 AEDT}
}

Changes to library/tzdata/Australia/Darwin.

1
2
3
4
5
6
7
8


9
10

11
12

13
14

15
1
2
3
4
5
6


7
8
9

10
11

12
13

14
15






-
-
+
+

-
+

-
+

-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Darwin) {
    {-9223372036854775808 31400 0 LMT}
    {-2364108200 32400 0 ACST}
    {-2230189200 34200 0 ACST}
    {-1672565340 37800 1 ACDT}
    {-1665390600 34200 0 ACST}
    {-1672558200 37800 1 ACDT}
    {-1665387000 34200 0 ACST}
    {-883639800 37800 1 ACDT}
    {-876126600 34200 0 ACST}
    {-876123000 34200 0 ACST}
    {-860398200 37800 1 ACDT}
    {-844677000 34200 0 ACST}
    {-844673400 34200 0 ACST}
    {-828343800 37800 1 ACDT}
    {-813227400 34200 0 ACST}
    {-813223800 34200 0 ACST}
}

Changes to library/tzdata/Australia/Eucla.

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
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




-
-
-
+
+
+

-
+

-
+


-
+

-
+

-
+

-
+

-
+

-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Eucla) {
    {-9223372036854775808 30928 0 LMT}
    {-2337928528 31500 0 +0945}
    {-1672562640 35100 1 +0945}
    {-1665387900 31500 0 +0945}
    {-2337928528 31500 0 +0845}
    {-1672555500 35100 1 +0945}
    {-1665384300 31500 0 +0845}
    {-883637100 35100 1 +0945}
    {-876123900 31500 0 +0945}
    {-876120300 31500 0 +0845}
    {-860395500 35100 1 +0945}
    {-844674300 31500 0 +0945}
    {-844670700 31500 0 +0845}
    {-836473500 35100 0 +0945}
    {152039700 35100 1 +0945}
    {162926100 31500 0 +0945}
    {162926100 31500 0 +0845}
    {436295700 35100 1 +0945}
    {447182100 31500 0 +0945}
    {447182100 31500 0 +0845}
    {690311700 35100 1 +0945}
    {699383700 31500 0 +0945}
    {699383700 31500 0 +0845}
    {1165079700 35100 1 +0945}
    {1174756500 31500 0 +0945}
    {1174756500 31500 0 +0845}
    {1193505300 35100 1 +0945}
    {1206810900 31500 0 +0945}
    {1206810900 31500 0 +0845}
    {1224954900 35100 1 +0945}
    {1238260500 31500 0 +0945}
    {1238260500 31500 0 +0845}
}

Changes to library/tzdata/Australia/Hobart.

1
2
3
4
5
6



7
8



9
10

11
12

13
14

15
16
17
18
19
20
21
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






+
+
+
-
-
+
+
+

-
+

-
+

-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Hobart) {
    {-9223372036854775808 35356 0 LMT}
    {-2345795356 36000 0 AEST}
    {-1680508800 39600 1 AEDT}
    {-1665388800 36000 0 AEST}
    {-1646640000 39600 1 AEDT}
    {-1635753600 36000 0 AEST}
    {-1669892400 39600 0 AEDT}
    {-1665392400 36000 0 AEST}
    {-1615190400 39600 1 AEDT}
    {-1604304000 36000 0 AEST}
    {-1583920800 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876128400 36000 0 AEST}
    {-876124800 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844678800 36000 0 AEST}
    {-844675200 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813229200 36000 0 AEST}
    {-813225600 36000 0 AEST}
    {-94730400 36000 0 AEST}
    {-71136000 39600 1 AEDT}
    {-55411200 36000 0 AEST}
    {-37267200 39600 1 AEDT}
    {-25776000 36000 0 AEST}
    {-5817600 39600 1 AEDT}
    {5673600 36000 0 AEST}

Changes to library/tzdata/Australia/Lindeman.

1
2
3
4
5
6
7


8
9

10
11

12
13

14
15
16
17
18
19
20
1
2
3
4
5


6
7
8

9
10

11
12

13
14
15
16
17
18
19
20





-
-
+
+

-
+

-
+

-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Lindeman) {
    {-9223372036854775808 35756 0 LMT}
    {-2366790956 36000 0 AEST}
    {-1672567140 39600 1 AEDT}
    {-1665392400 36000 0 AEST}
    {-1672560000 39600 1 AEDT}
    {-1665388800 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876128400 36000 0 AEST}
    {-876124800 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844678800 36000 0 AEST}
    {-844675200 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813229200 36000 0 AEST}
    {-813225600 36000 0 AEST}
    {31500000 36000 0 AEST}
    {57686400 39600 1 AEDT}
    {67968000 36000 0 AEST}
    {625593600 39600 1 AEDT}
    {636480000 36000 0 AEST}
    {657043200 39600 1 AEDT}
    {667929600 36000 0 AEST}

Changes to library/tzdata/Australia/Lord_Howe.

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
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
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

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






-
+

-
+

-
+

-
+


-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Lord_Howe) {
    {-9223372036854775808 38180 0 LMT}
    {-2364114980 36000 0 AEST}
    {352216800 37800 0 +1030}
    {372785400 41400 1 +1030}
    {372785400 41400 1 +1130}
    {384273000 37800 0 +1030}
    {404839800 41400 1 +1030}
    {404839800 41400 1 +1130}
    {415722600 37800 0 +1030}
    {436289400 41400 1 +1030}
    {436289400 41400 1 +1130}
    {447172200 37800 0 +1030}
    {467739000 41400 1 +1030}
    {467739000 41400 1 +1130}
    {478621800 37800 0 +1030}
    {488984400 37800 0 +1030}
    {499188600 39600 1 +1030}
    {499188600 39600 1 +1100}
    {511282800 37800 0 +1030}
    {530033400 39600 1 +1030}
    {530033400 39600 1 +1100}
    {542732400 37800 0 +1030}
    {562087800 39600 1 +1030}
    {562087800 39600 1 +1100}
    {574786800 37800 0 +1030}
    {594142200 39600 1 +1030}
    {594142200 39600 1 +1100}
    {606236400 37800 0 +1030}
    {625591800 39600 1 +1030}
    {625591800 39600 1 +1100}
    {636476400 37800 0 +1030}
    {657041400 39600 1 +1030}
    {657041400 39600 1 +1100}
    {667926000 37800 0 +1030}
    {688491000 39600 1 +1030}
    {688491000 39600 1 +1100}
    {699375600 37800 0 +1030}
    {719940600 39600 1 +1030}
    {719940600 39600 1 +1100}
    {731430000 37800 0 +1030}
    {751995000 39600 1 +1030}
    {751995000 39600 1 +1100}
    {762879600 37800 0 +1030}
    {783444600 39600 1 +1030}
    {783444600 39600 1 +1100}
    {794329200 37800 0 +1030}
    {814894200 39600 1 +1030}
    {814894200 39600 1 +1100}
    {828198000 37800 0 +1030}
    {846343800 39600 1 +1030}
    {846343800 39600 1 +1100}
    {859647600 37800 0 +1030}
    {877793400 39600 1 +1030}
    {877793400 39600 1 +1100}
    {891097200 37800 0 +1030}
    {909243000 39600 1 +1030}
    {909243000 39600 1 +1100}
    {922546800 37800 0 +1030}
    {941297400 39600 1 +1030}
    {941297400 39600 1 +1100}
    {953996400 37800 0 +1030}
    {967303800 39600 1 +1030}
    {967303800 39600 1 +1100}
    {985446000 37800 0 +1030}
    {1004196600 39600 1 +1030}
    {1004196600 39600 1 +1100}
    {1017500400 37800 0 +1030}
    {1035646200 39600 1 +1030}
    {1035646200 39600 1 +1100}
    {1048950000 37800 0 +1030}
    {1067095800 39600 1 +1030}
    {1067095800 39600 1 +1100}
    {1080399600 37800 0 +1030}
    {1099150200 39600 1 +1030}
    {1099150200 39600 1 +1100}
    {1111849200 37800 0 +1030}
    {1130599800 39600 1 +1030}
    {1130599800 39600 1 +1100}
    {1143903600 37800 0 +1030}
    {1162049400 39600 1 +1030}
    {1162049400 39600 1 +1100}
    {1174748400 37800 0 +1030}
    {1193499000 39600 1 +1030}
    {1193499000 39600 1 +1100}
    {1207407600 37800 0 +1030}
    {1223134200 39600 1 +1030}
    {1223134200 39600 1 +1100}
    {1238857200 37800 0 +1030}
    {1254583800 39600 1 +1030}
    {1254583800 39600 1 +1100}
    {1270306800 37800 0 +1030}
    {1286033400 39600 1 +1030}
    {1286033400 39600 1 +1100}
    {1301756400 37800 0 +1030}
    {1317483000 39600 1 +1030}
    {1317483000 39600 1 +1100}
    {1333206000 37800 0 +1030}
    {1349537400 39600 1 +1030}
    {1349537400 39600 1 +1100}
    {1365260400 37800 0 +1030}
    {1380987000 39600 1 +1030}
    {1380987000 39600 1 +1100}
    {1396710000 37800 0 +1030}
    {1412436600 39600 1 +1030}
    {1412436600 39600 1 +1100}
    {1428159600 37800 0 +1030}
    {1443886200 39600 1 +1030}
    {1443886200 39600 1 +1100}
    {1459609200 37800 0 +1030}
    {1475335800 39600 1 +1030}
    {1475335800 39600 1 +1100}
    {1491058800 37800 0 +1030}
    {1506785400 39600 1 +1030}
    {1506785400 39600 1 +1100}
    {1522508400 37800 0 +1030}
    {1538839800 39600 1 +1030}
    {1538839800 39600 1 +1100}
    {1554562800 37800 0 +1030}
    {1570289400 39600 1 +1030}
    {1570289400 39600 1 +1100}
    {1586012400 37800 0 +1030}
    {1601739000 39600 1 +1030}
    {1601739000 39600 1 +1100}
    {1617462000 37800 0 +1030}
    {1633188600 39600 1 +1030}
    {1633188600 39600 1 +1100}
    {1648911600 37800 0 +1030}
    {1664638200 39600 1 +1030}
    {1664638200 39600 1 +1100}
    {1680361200 37800 0 +1030}
    {1696087800 39600 1 +1030}
    {1696087800 39600 1 +1100}
    {1712415600 37800 0 +1030}
    {1728142200 39600 1 +1030}
    {1728142200 39600 1 +1100}
    {1743865200 37800 0 +1030}
    {1759591800 39600 1 +1030}
    {1759591800 39600 1 +1100}
    {1775314800 37800 0 +1030}
    {1791041400 39600 1 +1030}
    {1791041400 39600 1 +1100}
    {1806764400 37800 0 +1030}
    {1822491000 39600 1 +1030}
    {1822491000 39600 1 +1100}
    {1838214000 37800 0 +1030}
    {1853940600 39600 1 +1030}
    {1853940600 39600 1 +1100}
    {1869663600 37800 0 +1030}
    {1885995000 39600 1 +1030}
    {1885995000 39600 1 +1100}
    {1901718000 37800 0 +1030}
    {1917444600 39600 1 +1030}
    {1917444600 39600 1 +1100}
    {1933167600 37800 0 +1030}
    {1948894200 39600 1 +1030}
    {1948894200 39600 1 +1100}
    {1964617200 37800 0 +1030}
    {1980343800 39600 1 +1030}
    {1980343800 39600 1 +1100}
    {1996066800 37800 0 +1030}
    {2011793400 39600 1 +1030}
    {2011793400 39600 1 +1100}
    {2027516400 37800 0 +1030}
    {2043243000 39600 1 +1030}
    {2043243000 39600 1 +1100}
    {2058966000 37800 0 +1030}
    {2075297400 39600 1 +1030}
    {2075297400 39600 1 +1100}
    {2091020400 37800 0 +1030}
    {2106747000 39600 1 +1030}
    {2106747000 39600 1 +1100}
    {2122470000 37800 0 +1030}
    {2138196600 39600 1 +1030}
    {2138196600 39600 1 +1100}
    {2153919600 37800 0 +1030}
    {2169646200 39600 1 +1030}
    {2169646200 39600 1 +1100}
    {2185369200 37800 0 +1030}
    {2201095800 39600 1 +1030}
    {2201095800 39600 1 +1100}
    {2216818800 37800 0 +1030}
    {2233150200 39600 1 +1030}
    {2233150200 39600 1 +1100}
    {2248873200 37800 0 +1030}
    {2264599800 39600 1 +1030}
    {2264599800 39600 1 +1100}
    {2280322800 37800 0 +1030}
    {2296049400 39600 1 +1030}
    {2296049400 39600 1 +1100}
    {2311772400 37800 0 +1030}
    {2327499000 39600 1 +1030}
    {2327499000 39600 1 +1100}
    {2343222000 37800 0 +1030}
    {2358948600 39600 1 +1030}
    {2358948600 39600 1 +1100}
    {2374671600 37800 0 +1030}
    {2390398200 39600 1 +1030}
    {2390398200 39600 1 +1100}
    {2406121200 37800 0 +1030}
    {2422452600 39600 1 +1030}
    {2422452600 39600 1 +1100}
    {2438175600 37800 0 +1030}
    {2453902200 39600 1 +1030}
    {2453902200 39600 1 +1100}
    {2469625200 37800 0 +1030}
    {2485351800 39600 1 +1030}
    {2485351800 39600 1 +1100}
    {2501074800 37800 0 +1030}
    {2516801400 39600 1 +1030}
    {2516801400 39600 1 +1100}
    {2532524400 37800 0 +1030}
    {2548251000 39600 1 +1030}
    {2548251000 39600 1 +1100}
    {2563974000 37800 0 +1030}
    {2579700600 39600 1 +1030}
    {2579700600 39600 1 +1100}
    {2596028400 37800 0 +1030}
    {2611755000 39600 1 +1030}
    {2611755000 39600 1 +1100}
    {2627478000 37800 0 +1030}
    {2643204600 39600 1 +1030}
    {2643204600 39600 1 +1100}
    {2658927600 37800 0 +1030}
    {2674654200 39600 1 +1030}
    {2674654200 39600 1 +1100}
    {2690377200 37800 0 +1030}
    {2706103800 39600 1 +1030}
    {2706103800 39600 1 +1100}
    {2721826800 37800 0 +1030}
    {2737553400 39600 1 +1030}
    {2737553400 39600 1 +1100}
    {2753276400 37800 0 +1030}
    {2769607800 39600 1 +1030}
    {2769607800 39600 1 +1100}
    {2785330800 37800 0 +1030}
    {2801057400 39600 1 +1030}
    {2801057400 39600 1 +1100}
    {2816780400 37800 0 +1030}
    {2832507000 39600 1 +1030}
    {2832507000 39600 1 +1100}
    {2848230000 37800 0 +1030}
    {2863956600 39600 1 +1030}
    {2863956600 39600 1 +1100}
    {2879679600 37800 0 +1030}
    {2895406200 39600 1 +1030}
    {2895406200 39600 1 +1100}
    {2911129200 37800 0 +1030}
    {2926855800 39600 1 +1030}
    {2926855800 39600 1 +1100}
    {2942578800 37800 0 +1030}
    {2958910200 39600 1 +1030}
    {2958910200 39600 1 +1100}
    {2974633200 37800 0 +1030}
    {2990359800 39600 1 +1030}
    {2990359800 39600 1 +1100}
    {3006082800 37800 0 +1030}
    {3021809400 39600 1 +1030}
    {3021809400 39600 1 +1100}
    {3037532400 37800 0 +1030}
    {3053259000 39600 1 +1030}
    {3053259000 39600 1 +1100}
    {3068982000 37800 0 +1030}
    {3084708600 39600 1 +1030}
    {3084708600 39600 1 +1100}
    {3100431600 37800 0 +1030}
    {3116763000 39600 1 +1030}
    {3116763000 39600 1 +1100}
    {3132486000 37800 0 +1030}
    {3148212600 39600 1 +1030}
    {3148212600 39600 1 +1100}
    {3163935600 37800 0 +1030}
    {3179662200 39600 1 +1030}
    {3179662200 39600 1 +1100}
    {3195385200 37800 0 +1030}
    {3211111800 39600 1 +1030}
    {3211111800 39600 1 +1100}
    {3226834800 37800 0 +1030}
    {3242561400 39600 1 +1030}
    {3242561400 39600 1 +1100}
    {3258284400 37800 0 +1030}
    {3274011000 39600 1 +1030}
    {3274011000 39600 1 +1100}
    {3289734000 37800 0 +1030}
    {3306065400 39600 1 +1030}
    {3306065400 39600 1 +1100}
    {3321788400 37800 0 +1030}
    {3337515000 39600 1 +1030}
    {3337515000 39600 1 +1100}
    {3353238000 37800 0 +1030}
    {3368964600 39600 1 +1030}
    {3368964600 39600 1 +1100}
    {3384687600 37800 0 +1030}
    {3400414200 39600 1 +1030}
    {3400414200 39600 1 +1100}
    {3416137200 37800 0 +1030}
    {3431863800 39600 1 +1030}
    {3431863800 39600 1 +1100}
    {3447586800 37800 0 +1030}
    {3463313400 39600 1 +1030}
    {3463313400 39600 1 +1100}
    {3479641200 37800 0 +1030}
    {3495367800 39600 1 +1030}
    {3495367800 39600 1 +1100}
    {3511090800 37800 0 +1030}
    {3526817400 39600 1 +1030}
    {3526817400 39600 1 +1100}
    {3542540400 37800 0 +1030}
    {3558267000 39600 1 +1030}
    {3558267000 39600 1 +1100}
    {3573990000 37800 0 +1030}
    {3589716600 39600 1 +1030}
    {3589716600 39600 1 +1100}
    {3605439600 37800 0 +1030}
    {3621166200 39600 1 +1030}
    {3621166200 39600 1 +1100}
    {3636889200 37800 0 +1030}
    {3653220600 39600 1 +1030}
    {3653220600 39600 1 +1100}
    {3668943600 37800 0 +1030}
    {3684670200 39600 1 +1030}
    {3684670200 39600 1 +1100}
    {3700393200 37800 0 +1030}
    {3716119800 39600 1 +1030}
    {3716119800 39600 1 +1100}
    {3731842800 37800 0 +1030}
    {3747569400 39600 1 +1030}
    {3747569400 39600 1 +1100}
    {3763292400 37800 0 +1030}
    {3779019000 39600 1 +1030}
    {3779019000 39600 1 +1100}
    {3794742000 37800 0 +1030}
    {3810468600 39600 1 +1030}
    {3810468600 39600 1 +1100}
    {3826191600 37800 0 +1030}
    {3842523000 39600 1 +1030}
    {3842523000 39600 1 +1100}
    {3858246000 37800 0 +1030}
    {3873972600 39600 1 +1030}
    {3873972600 39600 1 +1100}
    {3889695600 37800 0 +1030}
    {3905422200 39600 1 +1030}
    {3905422200 39600 1 +1100}
    {3921145200 37800 0 +1030}
    {3936871800 39600 1 +1030}
    {3936871800 39600 1 +1100}
    {3952594800 37800 0 +1030}
    {3968321400 39600 1 +1030}
    {3968321400 39600 1 +1100}
    {3984044400 37800 0 +1030}
    {4000375800 39600 1 +1030}
    {4000375800 39600 1 +1100}
    {4016098800 37800 0 +1030}
    {4031825400 39600 1 +1030}
    {4031825400 39600 1 +1100}
    {4047548400 37800 0 +1030}
    {4063275000 39600 1 +1030}
    {4063275000 39600 1 +1100}
    {4078998000 37800 0 +1030}
    {4094724600 39600 1 +1030}
    {4094724600 39600 1 +1100}
}

Changes to library/tzdata/Australia/Melbourne.

1
2
3
4
5
6
7


8
9

10
11

12
13

14
15
16
17
18
19
20
1
2
3
4
5


6
7
8

9
10

11
12

13
14
15
16
17
18
19
20





-
-
+
+

-
+

-
+

-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Melbourne) {
    {-9223372036854775808 34792 0 LMT}
    {-2364111592 36000 0 AEST}
    {-1672567140 39600 1 AEDT}
    {-1665392400 36000 0 AEST}
    {-1672560000 39600 1 AEDT}
    {-1665388800 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876128400 36000 0 AEST}
    {-876124800 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844678800 36000 0 AEST}
    {-844675200 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813229200 36000 0 AEST}
    {-813225600 36000 0 AEST}
    {31500000 36000 0 AEST}
    {57686400 39600 1 AEDT}
    {67968000 36000 0 AEST}
    {89136000 39600 1 AEDT}
    {100022400 36000 0 AEST}
    {120585600 39600 1 AEDT}
    {131472000 36000 0 AEST}

Changes to library/tzdata/Australia/Perth.

1
2
3
4
5
6
7


8
9

10
11

12
13
14
15
16
17
18
1
2
3
4
5


6
7
8

9
10

11
12
13
14
15
16
17
18





-
-
+
+

-
+

-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Perth) {
    {-9223372036854775808 27804 0 LMT}
    {-2337925404 28800 0 AWST}
    {-1672559940 32400 1 AWDT}
    {-1665385200 28800 0 AWST}
    {-1672552800 32400 1 AWDT}
    {-1665381600 28800 0 AWST}
    {-883634400 32400 1 AWDT}
    {-876121200 28800 0 AWST}
    {-876117600 28800 0 AWST}
    {-860392800 32400 1 AWDT}
    {-844671600 28800 0 AWST}
    {-844668000 28800 0 AWST}
    {-836470800 32400 0 AWST}
    {152042400 32400 1 AWDT}
    {162928800 28800 0 AWST}
    {436298400 32400 1 AWDT}
    {447184800 28800 0 AWST}
    {690314400 32400 1 AWDT}
    {699386400 28800 0 AWST}

Changes to library/tzdata/Australia/Sydney.

1
2
3
4
5
6
7


8
9

10
11

12
13

14
15
16
17
18
19
20
1
2
3
4
5


6
7
8

9
10

11
12

13
14
15
16
17
18
19
20





-
-
+
+

-
+

-
+

-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Sydney) {
    {-9223372036854775808 36292 0 LMT}
    {-2364113092 36000 0 AEST}
    {-1672567140 39600 1 AEDT}
    {-1665392400 36000 0 AEST}
    {-1672560000 39600 1 AEDT}
    {-1665388800 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876128400 36000 0 AEST}
    {-876124800 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844678800 36000 0 AEST}
    {-844675200 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813229200 36000 0 AEST}
    {-813225600 36000 0 AEST}
    {31500000 36000 0 AEST}
    {57686400 39600 1 AEDT}
    {67968000 36000 0 AEST}
    {89136000 39600 1 AEDT}
    {100022400 36000 0 AEST}
    {120585600 39600 1 AEDT}
    {131472000 36000 0 AEST}

Changes to library/tzdata/CET.

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
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
1
2
3


4
5







































































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Brussels)]} {
    LoadTimeZoneFile Europe/Brussels

set TZData(:CET) {
}
set TZData(:CET) $TZData(:Europe/Brussels)
    {-9223372036854775808 3600 0 CET}
    {-1693706400 7200 1 CEST}
    {-1680483600 3600 0 CET}
    {-1663455600 7200 1 CEST}
    {-1650150000 3600 0 CET}
    {-1632006000 7200 1 CEST}
    {-1618700400 3600 0 CET}
    {-938905200 7200 1 CEST}
    {-857257200 3600 0 CET}
    {-844556400 7200 1 CEST}
    {-828226800 3600 0 CET}
    {-812502000 7200 1 CEST}
    {-796777200 3600 0 CET}
    {-781052400 7200 1 CEST}
    {-766623600 3600 0 CET}
    {228877200 7200 1 CEST}
    {243997200 3600 0 CET}
    {260326800 7200 1 CEST}
    {276051600 3600 0 CET}
    {291776400 7200 1 CEST}
    {307501200 3600 0 CET}
    {323830800 7200 1 CEST}
    {338950800 3600 0 CET}
    {354675600 7200 1 CEST}
    {370400400 3600 0 CET}
    {386125200 7200 1 CEST}
    {401850000 3600 0 CET}
    {417574800 7200 1 CEST}
    {433299600 3600 0 CET}
    {449024400 7200 1 CEST}
    {465354000 3600 0 CET}
    {481078800 7200 1 CEST}
    {496803600 3600 0 CET}
    {512528400 7200 1 CEST}
    {528253200 3600 0 CET}
    {543978000 7200 1 CEST}
    {559702800 3600 0 CET}
    {575427600 7200 1 CEST}
    {591152400 3600 0 CET}
    {606877200 7200 1 CEST}
    {622602000 3600 0 CET}
    {638326800 7200 1 CEST}
    {654656400 3600 0 CET}
    {670381200 7200 1 CEST}
    {686106000 3600 0 CET}
    {701830800 7200 1 CEST}
    {717555600 3600 0 CET}
    {733280400 7200 1 CEST}
    {749005200 3600 0 CET}
    {764730000 7200 1 CEST}
    {780454800 3600 0 CET}
    {796179600 7200 1 CEST}
    {811904400 3600 0 CET}
    {828234000 7200 1 CEST}
    {846378000 3600 0 CET}
    {859683600 7200 1 CEST}
    {877827600 3600 0 CET}
    {891133200 7200 1 CEST}
    {909277200 3600 0 CET}
    {922582800 7200 1 CEST}
    {941331600 3600 0 CET}
    {954032400 7200 1 CEST}
    {972781200 3600 0 CET}
    {985482000 7200 1 CEST}
    {1004230800 3600 0 CET}
    {1017536400 7200 1 CEST}
    {1035680400 3600 0 CET}
    {1048986000 7200 1 CEST}
    {1067130000 3600 0 CET}
    {1080435600 7200 1 CEST}
    {1099184400 3600 0 CET}
    {1111885200 7200 1 CEST}
    {1130634000 3600 0 CET}
    {1143334800 7200 1 CEST}
    {1162083600 3600 0 CET}
    {1174784400 7200 1 CEST}
    {1193533200 3600 0 CET}
    {1206838800 7200 1 CEST}
    {1224982800 3600 0 CET}
    {1238288400 7200 1 CEST}
    {1256432400 3600 0 CET}
    {1269738000 7200 1 CEST}
    {1288486800 3600 0 CET}
    {1301187600 7200 1 CEST}
    {1319936400 3600 0 CET}
    {1332637200 7200 1 CEST}
    {1351386000 3600 0 CET}
    {1364691600 7200 1 CEST}
    {1382835600 3600 0 CET}
    {1396141200 7200 1 CEST}
    {1414285200 3600 0 CET}
    {1427590800 7200 1 CEST}
    {1445734800 3600 0 CET}
    {1459040400 7200 1 CEST}
    {1477789200 3600 0 CET}
    {1490490000 7200 1 CEST}
    {1509238800 3600 0 CET}
    {1521939600 7200 1 CEST}
    {1540688400 3600 0 CET}
    {1553994000 7200 1 CEST}
    {1572138000 3600 0 CET}
    {1585443600 7200 1 CEST}
    {1603587600 3600 0 CET}
    {1616893200 7200 1 CEST}
    {1635642000 3600 0 CET}
    {1648342800 7200 1 CEST}
    {1667091600 3600 0 CET}
    {1679792400 7200 1 CEST}
    {1698541200 3600 0 CET}
    {1711846800 7200 1 CEST}
    {1729990800 3600 0 CET}
    {1743296400 7200 1 CEST}
    {1761440400 3600 0 CET}
    {1774746000 7200 1 CEST}
    {1792890000 3600 0 CET}
    {1806195600 7200 1 CEST}
    {1824944400 3600 0 CET}
    {1837645200 7200 1 CEST}
    {1856394000 3600 0 CET}
    {1869094800 7200 1 CEST}
    {1887843600 3600 0 CET}
    {1901149200 7200 1 CEST}
    {1919293200 3600 0 CET}
    {1932598800 7200 1 CEST}
    {1950742800 3600 0 CET}
    {1964048400 7200 1 CEST}
    {1982797200 3600 0 CET}
    {1995498000 7200 1 CEST}
    {2014246800 3600 0 CET}
    {2026947600 7200 1 CEST}
    {2045696400 3600 0 CET}
    {2058397200 7200 1 CEST}
    {2077146000 3600 0 CET}
    {2090451600 7200 1 CEST}
    {2108595600 3600 0 CET}
    {2121901200 7200 1 CEST}
    {2140045200 3600 0 CET}
    {2153350800 7200 1 CEST}
    {2172099600 3600 0 CET}
    {2184800400 7200 1 CEST}
    {2203549200 3600 0 CET}
    {2216250000 7200 1 CEST}
    {2234998800 3600 0 CET}
    {2248304400 7200 1 CEST}
    {2266448400 3600 0 CET}
    {2279754000 7200 1 CEST}
    {2297898000 3600 0 CET}
    {2311203600 7200 1 CEST}
    {2329347600 3600 0 CET}
    {2342653200 7200 1 CEST}
    {2361402000 3600 0 CET}
    {2374102800 7200 1 CEST}
    {2392851600 3600 0 CET}
    {2405552400 7200 1 CEST}
    {2424301200 3600 0 CET}
    {2437606800 7200 1 CEST}
    {2455750800 3600 0 CET}
    {2469056400 7200 1 CEST}
    {2487200400 3600 0 CET}
    {2500506000 7200 1 CEST}
    {2519254800 3600 0 CET}
    {2531955600 7200 1 CEST}
    {2550704400 3600 0 CET}
    {2563405200 7200 1 CEST}
    {2582154000 3600 0 CET}
    {2595459600 7200 1 CEST}
    {2613603600 3600 0 CET}
    {2626909200 7200 1 CEST}
    {2645053200 3600 0 CET}
    {2658358800 7200 1 CEST}
    {2676502800 3600 0 CET}
    {2689808400 7200 1 CEST}
    {2708557200 3600 0 CET}
    {2721258000 7200 1 CEST}
    {2740006800 3600 0 CET}
    {2752707600 7200 1 CEST}
    {2771456400 3600 0 CET}
    {2784762000 7200 1 CEST}
    {2802906000 3600 0 CET}
    {2816211600 7200 1 CEST}
    {2834355600 3600 0 CET}
    {2847661200 7200 1 CEST}
    {2866410000 3600 0 CET}
    {2879110800 7200 1 CEST}
    {2897859600 3600 0 CET}
    {2910560400 7200 1 CEST}
    {2929309200 3600 0 CET}
    {2942010000 7200 1 CEST}
    {2960758800 3600 0 CET}
    {2974064400 7200 1 CEST}
    {2992208400 3600 0 CET}
    {3005514000 7200 1 CEST}
    {3023658000 3600 0 CET}
    {3036963600 7200 1 CEST}
    {3055712400 3600 0 CET}
    {3068413200 7200 1 CEST}
    {3087162000 3600 0 CET}
    {3099862800 7200 1 CEST}
    {3118611600 3600 0 CET}
    {3131917200 7200 1 CEST}
    {3150061200 3600 0 CET}
    {3163366800 7200 1 CEST}
    {3181510800 3600 0 CET}
    {3194816400 7200 1 CEST}
    {3212960400 3600 0 CET}
    {3226266000 7200 1 CEST}
    {3245014800 3600 0 CET}
    {3257715600 7200 1 CEST}
    {3276464400 3600 0 CET}
    {3289165200 7200 1 CEST}
    {3307914000 3600 0 CET}
    {3321219600 7200 1 CEST}
    {3339363600 3600 0 CET}
    {3352669200 7200 1 CEST}
    {3370813200 3600 0 CET}
    {3384118800 7200 1 CEST}
    {3402867600 3600 0 CET}
    {3415568400 7200 1 CEST}
    {3434317200 3600 0 CET}
    {3447018000 7200 1 CEST}
    {3465766800 3600 0 CET}
    {3479072400 7200 1 CEST}
    {3497216400 3600 0 CET}
    {3510522000 7200 1 CEST}
    {3528666000 3600 0 CET}
    {3541971600 7200 1 CEST}
    {3560115600 3600 0 CET}
    {3573421200 7200 1 CEST}
    {3592170000 3600 0 CET}
    {3604870800 7200 1 CEST}
    {3623619600 3600 0 CET}
    {3636320400 7200 1 CEST}
    {3655069200 3600 0 CET}
    {3668374800 7200 1 CEST}
    {3686518800 3600 0 CET}
    {3699824400 7200 1 CEST}
    {3717968400 3600 0 CET}
    {3731274000 7200 1 CEST}
    {3750022800 3600 0 CET}
    {3762723600 7200 1 CEST}
    {3781472400 3600 0 CET}
    {3794173200 7200 1 CEST}
    {3812922000 3600 0 CET}
    {3825622800 7200 1 CEST}
    {3844371600 3600 0 CET}
    {3857677200 7200 1 CEST}
    {3875821200 3600 0 CET}
    {3889126800 7200 1 CEST}
    {3907270800 3600 0 CET}
    {3920576400 7200 1 CEST}
    {3939325200 3600 0 CET}
    {3952026000 7200 1 CEST}
    {3970774800 3600 0 CET}
    {3983475600 7200 1 CEST}
    {4002224400 3600 0 CET}
    {4015530000 7200 1 CEST}
    {4033674000 3600 0 CET}
    {4046979600 7200 1 CEST}
    {4065123600 3600 0 CET}
    {4078429200 7200 1 CEST}
    {4096573200 3600 0 CET}
}

Changes to library/tzdata/CST6CDT.

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
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
1
2
3


4
5




















































































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Chicago)]} {
    LoadTimeZoneFile America/Chicago

set TZData(:CST6CDT) {
}
set TZData(:CST6CDT) $TZData(:America/Chicago)
    {-9223372036854775808 -21600 0 CST}
    {-1633276800 -18000 1 CDT}
    {-1615136400 -21600 0 CST}
    {-1601827200 -18000 1 CDT}
    {-1583686800 -21600 0 CST}
    {-880214400 -18000 1 CWT}
    {-769395600 -18000 1 CPT}
    {-765392400 -21600 0 CST}
    {-84384000 -18000 1 CDT}
    {-68662800 -21600 0 CST}
    {-52934400 -18000 1 CDT}
    {-37213200 -21600 0 CST}
    {-21484800 -18000 1 CDT}
    {-5763600 -21600 0 CST}
    {9964800 -18000 1 CDT}
    {25686000 -21600 0 CST}
    {41414400 -18000 1 CDT}
    {57740400 -21600 0 CST}
    {73468800 -18000 1 CDT}
    {89190000 -21600 0 CST}
    {104918400 -18000 1 CDT}
    {120639600 -21600 0 CST}
    {126691200 -18000 1 CDT}
    {152089200 -21600 0 CST}
    {162374400 -18000 1 CDT}
    {183538800 -21600 0 CST}
    {199267200 -18000 1 CDT}
    {215593200 -21600 0 CST}
    {230716800 -18000 1 CDT}
    {247042800 -21600 0 CST}
    {262771200 -18000 1 CDT}
    {278492400 -21600 0 CST}
    {294220800 -18000 1 CDT}
    {309942000 -21600 0 CST}
    {325670400 -18000 1 CDT}
    {341391600 -21600 0 CST}
    {357120000 -18000 1 CDT}
    {372841200 -21600 0 CST}
    {388569600 -18000 1 CDT}
    {404895600 -21600 0 CST}
    {420019200 -18000 1 CDT}
    {436345200 -21600 0 CST}
    {452073600 -18000 1 CDT}
    {467794800 -21600 0 CST}
    {483523200 -18000 1 CDT}
    {499244400 -21600 0 CST}
    {514972800 -18000 1 CDT}
    {530694000 -21600 0 CST}
    {544608000 -18000 1 CDT}
    {562143600 -21600 0 CST}
    {576057600 -18000 1 CDT}
    {594198000 -21600 0 CST}
    {607507200 -18000 1 CDT}
    {625647600 -21600 0 CST}
    {638956800 -18000 1 CDT}
    {657097200 -21600 0 CST}
    {671011200 -18000 1 CDT}
    {688546800 -21600 0 CST}
    {702460800 -18000 1 CDT}
    {719996400 -21600 0 CST}
    {733910400 -18000 1 CDT}
    {752050800 -21600 0 CST}
    {765360000 -18000 1 CDT}
    {783500400 -21600 0 CST}
    {796809600 -18000 1 CDT}
    {814950000 -21600 0 CST}
    {828864000 -18000 1 CDT}
    {846399600 -21600 0 CST}
    {860313600 -18000 1 CDT}
    {877849200 -21600 0 CST}
    {891763200 -18000 1 CDT}
    {909298800 -21600 0 CST}
    {923212800 -18000 1 CDT}
    {941353200 -21600 0 CST}
    {954662400 -18000 1 CDT}
    {972802800 -21600 0 CST}
    {986112000 -18000 1 CDT}
    {1004252400 -21600 0 CST}
    {1018166400 -18000 1 CDT}
    {1035702000 -21600 0 CST}
    {1049616000 -18000 1 CDT}
    {1067151600 -21600 0 CST}
    {1081065600 -18000 1 CDT}
    {1099206000 -21600 0 CST}
    {1112515200 -18000 1 CDT}
    {1130655600 -21600 0 CST}
    {1143964800 -18000 1 CDT}
    {1162105200 -21600 0 CST}
    {1173600000 -18000 1 CDT}
    {1194159600 -21600 0 CST}
    {1205049600 -18000 1 CDT}
    {1225609200 -21600 0 CST}
    {1236499200 -18000 1 CDT}
    {1257058800 -21600 0 CST}
    {1268553600 -18000 1 CDT}
    {1289113200 -21600 0 CST}
    {1300003200 -18000 1 CDT}
    {1320562800 -21600 0 CST}
    {1331452800 -18000 1 CDT}
    {1352012400 -21600 0 CST}
    {1362902400 -18000 1 CDT}
    {1383462000 -21600 0 CST}
    {1394352000 -18000 1 CDT}
    {1414911600 -21600 0 CST}
    {1425801600 -18000 1 CDT}
    {1446361200 -21600 0 CST}
    {1457856000 -18000 1 CDT}
    {1478415600 -21600 0 CST}
    {1489305600 -18000 1 CDT}
    {1509865200 -21600 0 CST}
    {1520755200 -18000 1 CDT}
    {1541314800 -21600 0 CST}
    {1552204800 -18000 1 CDT}
    {1572764400 -21600 0 CST}
    {1583654400 -18000 1 CDT}
    {1604214000 -21600 0 CST}
    {1615708800 -18000 1 CDT}
    {1636268400 -21600 0 CST}
    {1647158400 -18000 1 CDT}
    {1667718000 -21600 0 CST}
    {1678608000 -18000 1 CDT}
    {1699167600 -21600 0 CST}
    {1710057600 -18000 1 CDT}
    {1730617200 -21600 0 CST}
    {1741507200 -18000 1 CDT}
    {1762066800 -21600 0 CST}
    {1772956800 -18000 1 CDT}
    {1793516400 -21600 0 CST}
    {1805011200 -18000 1 CDT}
    {1825570800 -21600 0 CST}
    {1836460800 -18000 1 CDT}
    {1857020400 -21600 0 CST}
    {1867910400 -18000 1 CDT}
    {1888470000 -21600 0 CST}
    {1899360000 -18000 1 CDT}
    {1919919600 -21600 0 CST}
    {1930809600 -18000 1 CDT}
    {1951369200 -21600 0 CST}
    {1962864000 -18000 1 CDT}
    {1983423600 -21600 0 CST}
    {1994313600 -18000 1 CDT}
    {2014873200 -21600 0 CST}
    {2025763200 -18000 1 CDT}
    {2046322800 -21600 0 CST}
    {2057212800 -18000 1 CDT}
    {2077772400 -21600 0 CST}
    {2088662400 -18000 1 CDT}
    {2109222000 -21600 0 CST}
    {2120112000 -18000 1 CDT}
    {2140671600 -21600 0 CST}
    {2152166400 -18000 1 CDT}
    {2172726000 -21600 0 CST}
    {2183616000 -18000 1 CDT}
    {2204175600 -21600 0 CST}
    {2215065600 -18000 1 CDT}
    {2235625200 -21600 0 CST}
    {2246515200 -18000 1 CDT}
    {2267074800 -21600 0 CST}
    {2277964800 -18000 1 CDT}
    {2298524400 -21600 0 CST}
    {2309414400 -18000 1 CDT}
    {2329974000 -21600 0 CST}
    {2341468800 -18000 1 CDT}
    {2362028400 -21600 0 CST}
    {2372918400 -18000 1 CDT}
    {2393478000 -21600 0 CST}
    {2404368000 -18000 1 CDT}
    {2424927600 -21600 0 CST}
    {2435817600 -18000 1 CDT}
    {2456377200 -21600 0 CST}
    {2467267200 -18000 1 CDT}
    {2487826800 -21600 0 CST}
    {2499321600 -18000 1 CDT}
    {2519881200 -21600 0 CST}
    {2530771200 -18000 1 CDT}
    {2551330800 -21600 0 CST}
    {2562220800 -18000 1 CDT}
    {2582780400 -21600 0 CST}
    {2593670400 -18000 1 CDT}
    {2614230000 -21600 0 CST}
    {2625120000 -18000 1 CDT}
    {2645679600 -21600 0 CST}
    {2656569600 -18000 1 CDT}
    {2677129200 -21600 0 CST}
    {2688624000 -18000 1 CDT}
    {2709183600 -21600 0 CST}
    {2720073600 -18000 1 CDT}
    {2740633200 -21600 0 CST}
    {2751523200 -18000 1 CDT}
    {2772082800 -21600 0 CST}
    {2782972800 -18000 1 CDT}
    {2803532400 -21600 0 CST}
    {2814422400 -18000 1 CDT}
    {2834982000 -21600 0 CST}
    {2846476800 -18000 1 CDT}
    {2867036400 -21600 0 CST}
    {2877926400 -18000 1 CDT}
    {2898486000 -21600 0 CST}
    {2909376000 -18000 1 CDT}
    {2929935600 -21600 0 CST}
    {2940825600 -18000 1 CDT}
    {2961385200 -21600 0 CST}
    {2972275200 -18000 1 CDT}
    {2992834800 -21600 0 CST}
    {3003724800 -18000 1 CDT}
    {3024284400 -21600 0 CST}
    {3035779200 -18000 1 CDT}
    {3056338800 -21600 0 CST}
    {3067228800 -18000 1 CDT}
    {3087788400 -21600 0 CST}
    {3098678400 -18000 1 CDT}
    {3119238000 -21600 0 CST}
    {3130128000 -18000 1 CDT}
    {3150687600 -21600 0 CST}
    {3161577600 -18000 1 CDT}
    {3182137200 -21600 0 CST}
    {3193027200 -18000 1 CDT}
    {3213586800 -21600 0 CST}
    {3225081600 -18000 1 CDT}
    {3245641200 -21600 0 CST}
    {3256531200 -18000 1 CDT}
    {3277090800 -21600 0 CST}
    {3287980800 -18000 1 CDT}
    {3308540400 -21600 0 CST}
    {3319430400 -18000 1 CDT}
    {3339990000 -21600 0 CST}
    {3350880000 -18000 1 CDT}
    {3371439600 -21600 0 CST}
    {3382934400 -18000 1 CDT}
    {3403494000 -21600 0 CST}
    {3414384000 -18000 1 CDT}
    {3434943600 -21600 0 CST}
    {3445833600 -18000 1 CDT}
    {3466393200 -21600 0 CST}
    {3477283200 -18000 1 CDT}
    {3497842800 -21600 0 CST}
    {3508732800 -18000 1 CDT}
    {3529292400 -21600 0 CST}
    {3540182400 -18000 1 CDT}
    {3560742000 -21600 0 CST}
    {3572236800 -18000 1 CDT}
    {3592796400 -21600 0 CST}
    {3603686400 -18000 1 CDT}
    {3624246000 -21600 0 CST}
    {3635136000 -18000 1 CDT}
    {3655695600 -21600 0 CST}
    {3666585600 -18000 1 CDT}
    {3687145200 -21600 0 CST}
    {3698035200 -18000 1 CDT}
    {3718594800 -21600 0 CST}
    {3730089600 -18000 1 CDT}
    {3750649200 -21600 0 CST}
    {3761539200 -18000 1 CDT}
    {3782098800 -21600 0 CST}
    {3792988800 -18000 1 CDT}
    {3813548400 -21600 0 CST}
    {3824438400 -18000 1 CDT}
    {3844998000 -21600 0 CST}
    {3855888000 -18000 1 CDT}
    {3876447600 -21600 0 CST}
    {3887337600 -18000 1 CDT}
    {3907897200 -21600 0 CST}
    {3919392000 -18000 1 CDT}
    {3939951600 -21600 0 CST}
    {3950841600 -18000 1 CDT}
    {3971401200 -21600 0 CST}
    {3982291200 -18000 1 CDT}
    {4002850800 -21600 0 CST}
    {4013740800 -18000 1 CDT}
    {4034300400 -21600 0 CST}
    {4045190400 -18000 1 CDT}
    {4065750000 -21600 0 CST}
    {4076640000 -18000 1 CDT}
    {4097199600 -21600 0 CST}
}

Deleted library/tzdata/Canada/East-Saskatchewan.

1
2
3
4
5





-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Regina)]} {
    LoadTimeZoneFile America/Regina
}
set TZData(:Canada/East-Saskatchewan) $TZData(:America/Regina)

Changes to library/tzdata/EET.

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
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
1
2
3


4
5

























































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Athens)]} {
    LoadTimeZoneFile Europe/Athens

set TZData(:EET) {
}
set TZData(:EET) $TZData(:Europe/Athens)
    {-9223372036854775808 7200 0 EET}
    {228877200 10800 1 EEST}
    {243997200 7200 0 EET}
    {260326800 10800 1 EEST}
    {276051600 7200 0 EET}
    {291776400 10800 1 EEST}
    {307501200 7200 0 EET}
    {323830800 10800 1 EEST}
    {338950800 7200 0 EET}
    {354675600 10800 1 EEST}
    {370400400 7200 0 EET}
    {386125200 10800 1 EEST}
    {401850000 7200 0 EET}
    {417574800 10800 1 EEST}
    {433299600 7200 0 EET}
    {449024400 10800 1 EEST}
    {465354000 7200 0 EET}
    {481078800 10800 1 EEST}
    {496803600 7200 0 EET}
    {512528400 10800 1 EEST}
    {528253200 7200 0 EET}
    {543978000 10800 1 EEST}
    {559702800 7200 0 EET}
    {575427600 10800 1 EEST}
    {591152400 7200 0 EET}
    {606877200 10800 1 EEST}
    {622602000 7200 0 EET}
    {638326800 10800 1 EEST}
    {654656400 7200 0 EET}
    {670381200 10800 1 EEST}
    {686106000 7200 0 EET}
    {701830800 10800 1 EEST}
    {717555600 7200 0 EET}
    {733280400 10800 1 EEST}
    {749005200 7200 0 EET}
    {764730000 10800 1 EEST}
    {780454800 7200 0 EET}
    {796179600 10800 1 EEST}
    {811904400 7200 0 EET}
    {828234000 10800 1 EEST}
    {846378000 7200 0 EET}
    {859683600 10800 1 EEST}
    {877827600 7200 0 EET}
    {891133200 10800 1 EEST}
    {909277200 7200 0 EET}
    {922582800 10800 1 EEST}
    {941331600 7200 0 EET}
    {954032400 10800 1 EEST}
    {972781200 7200 0 EET}
    {985482000 10800 1 EEST}
    {1004230800 7200 0 EET}
    {1017536400 10800 1 EEST}
    {1035680400 7200 0 EET}
    {1048986000 10800 1 EEST}
    {1067130000 7200 0 EET}
    {1080435600 10800 1 EEST}
    {1099184400 7200 0 EET}
    {1111885200 10800 1 EEST}
    {1130634000 7200 0 EET}
    {1143334800 10800 1 EEST}
    {1162083600 7200 0 EET}
    {1174784400 10800 1 EEST}
    {1193533200 7200 0 EET}
    {1206838800 10800 1 EEST}
    {1224982800 7200 0 EET}
    {1238288400 10800 1 EEST}
    {1256432400 7200 0 EET}
    {1269738000 10800 1 EEST}
    {1288486800 7200 0 EET}
    {1301187600 10800 1 EEST}
    {1319936400 7200 0 EET}
    {1332637200 10800 1 EEST}
    {1351386000 7200 0 EET}
    {1364691600 10800 1 EEST}
    {1382835600 7200 0 EET}
    {1396141200 10800 1 EEST}
    {1414285200 7200 0 EET}
    {1427590800 10800 1 EEST}
    {1445734800 7200 0 EET}
    {1459040400 10800 1 EEST}
    {1477789200 7200 0 EET}
    {1490490000 10800 1 EEST}
    {1509238800 7200 0 EET}
    {1521939600 10800 1 EEST}
    {1540688400 7200 0 EET}
    {1553994000 10800 1 EEST}
    {1572138000 7200 0 EET}
    {1585443600 10800 1 EEST}
    {1603587600 7200 0 EET}
    {1616893200 10800 1 EEST}
    {1635642000 7200 0 EET}
    {1648342800 10800 1 EEST}
    {1667091600 7200 0 EET}
    {1679792400 10800 1 EEST}
    {1698541200 7200 0 EET}
    {1711846800 10800 1 EEST}
    {1729990800 7200 0 EET}
    {1743296400 10800 1 EEST}
    {1761440400 7200 0 EET}
    {1774746000 10800 1 EEST}
    {1792890000 7200 0 EET}
    {1806195600 10800 1 EEST}
    {1824944400 7200 0 EET}
    {1837645200 10800 1 EEST}
    {1856394000 7200 0 EET}
    {1869094800 10800 1 EEST}
    {1887843600 7200 0 EET}
    {1901149200 10800 1 EEST}
    {1919293200 7200 0 EET}
    {1932598800 10800 1 EEST}
    {1950742800 7200 0 EET}
    {1964048400 10800 1 EEST}
    {1982797200 7200 0 EET}
    {1995498000 10800 1 EEST}
    {2014246800 7200 0 EET}
    {2026947600 10800 1 EEST}
    {2045696400 7200 0 EET}
    {2058397200 10800 1 EEST}
    {2077146000 7200 0 EET}
    {2090451600 10800 1 EEST}
    {2108595600 7200 0 EET}
    {2121901200 10800 1 EEST}
    {2140045200 7200 0 EET}
    {2153350800 10800 1 EEST}
    {2172099600 7200 0 EET}
    {2184800400 10800 1 EEST}
    {2203549200 7200 0 EET}
    {2216250000 10800 1 EEST}
    {2234998800 7200 0 EET}
    {2248304400 10800 1 EEST}
    {2266448400 7200 0 EET}
    {2279754000 10800 1 EEST}
    {2297898000 7200 0 EET}
    {2311203600 10800 1 EEST}
    {2329347600 7200 0 EET}
    {2342653200 10800 1 EEST}
    {2361402000 7200 0 EET}
    {2374102800 10800 1 EEST}
    {2392851600 7200 0 EET}
    {2405552400 10800 1 EEST}
    {2424301200 7200 0 EET}
    {2437606800 10800 1 EEST}
    {2455750800 7200 0 EET}
    {2469056400 10800 1 EEST}
    {2487200400 7200 0 EET}
    {2500506000 10800 1 EEST}
    {2519254800 7200 0 EET}
    {2531955600 10800 1 EEST}
    {2550704400 7200 0 EET}
    {2563405200 10800 1 EEST}
    {2582154000 7200 0 EET}
    {2595459600 10800 1 EEST}
    {2613603600 7200 0 EET}
    {2626909200 10800 1 EEST}
    {2645053200 7200 0 EET}
    {2658358800 10800 1 EEST}
    {2676502800 7200 0 EET}
    {2689808400 10800 1 EEST}
    {2708557200 7200 0 EET}
    {2721258000 10800 1 EEST}
    {2740006800 7200 0 EET}
    {2752707600 10800 1 EEST}
    {2771456400 7200 0 EET}
    {2784762000 10800 1 EEST}
    {2802906000 7200 0 EET}
    {2816211600 10800 1 EEST}
    {2834355600 7200 0 EET}
    {2847661200 10800 1 EEST}
    {2866410000 7200 0 EET}
    {2879110800 10800 1 EEST}
    {2897859600 7200 0 EET}
    {2910560400 10800 1 EEST}
    {2929309200 7200 0 EET}
    {2942010000 10800 1 EEST}
    {2960758800 7200 0 EET}
    {2974064400 10800 1 EEST}
    {2992208400 7200 0 EET}
    {3005514000 10800 1 EEST}
    {3023658000 7200 0 EET}
    {3036963600 10800 1 EEST}
    {3055712400 7200 0 EET}
    {3068413200 10800 1 EEST}
    {3087162000 7200 0 EET}
    {3099862800 10800 1 EEST}
    {3118611600 7200 0 EET}
    {3131917200 10800 1 EEST}
    {3150061200 7200 0 EET}
    {3163366800 10800 1 EEST}
    {3181510800 7200 0 EET}
    {3194816400 10800 1 EEST}
    {3212960400 7200 0 EET}
    {3226266000 10800 1 EEST}
    {3245014800 7200 0 EET}
    {3257715600 10800 1 EEST}
    {3276464400 7200 0 EET}
    {3289165200 10800 1 EEST}
    {3307914000 7200 0 EET}
    {3321219600 10800 1 EEST}
    {3339363600 7200 0 EET}
    {3352669200 10800 1 EEST}
    {3370813200 7200 0 EET}
    {3384118800 10800 1 EEST}
    {3402867600 7200 0 EET}
    {3415568400 10800 1 EEST}
    {3434317200 7200 0 EET}
    {3447018000 10800 1 EEST}
    {3465766800 7200 0 EET}
    {3479072400 10800 1 EEST}
    {3497216400 7200 0 EET}
    {3510522000 10800 1 EEST}
    {3528666000 7200 0 EET}
    {3541971600 10800 1 EEST}
    {3560115600 7200 0 EET}
    {3573421200 10800 1 EEST}
    {3592170000 7200 0 EET}
    {3604870800 10800 1 EEST}
    {3623619600 7200 0 EET}
    {3636320400 10800 1 EEST}
    {3655069200 7200 0 EET}
    {3668374800 10800 1 EEST}
    {3686518800 7200 0 EET}
    {3699824400 10800 1 EEST}
    {3717968400 7200 0 EET}
    {3731274000 10800 1 EEST}
    {3750022800 7200 0 EET}
    {3762723600 10800 1 EEST}
    {3781472400 7200 0 EET}
    {3794173200 10800 1 EEST}
    {3812922000 7200 0 EET}
    {3825622800 10800 1 EEST}
    {3844371600 7200 0 EET}
    {3857677200 10800 1 EEST}
    {3875821200 7200 0 EET}
    {3889126800 10800 1 EEST}
    {3907270800 7200 0 EET}
    {3920576400 10800 1 EEST}
    {3939325200 7200 0 EET}
    {3952026000 10800 1 EEST}
    {3970774800 7200 0 EET}
    {3983475600 10800 1 EEST}
    {4002224400 7200 0 EET}
    {4015530000 10800 1 EEST}
    {4033674000 7200 0 EET}
    {4046979600 10800 1 EEST}
    {4065123600 7200 0 EET}
    {4078429200 10800 1 EEST}
    {4096573200 7200 0 EET}
}

Changes to library/tzdata/EST.

1


2
3


4
5
1
2
3


4
5



+
+
-
-
+
+
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Panama)]} {
    LoadTimeZoneFile America/Panama

set TZData(:EST) {
}
set TZData(:EST) $TZData(:America/Panama)
    {-9223372036854775808 -18000 0 EST}
}

Changes to library/tzdata/EST5EDT.

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
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
1
2
3


4
5




















































































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/New_York)]} {
    LoadTimeZoneFile America/New_York

set TZData(:EST5EDT) {
}
set TZData(:EST5EDT) $TZData(:America/New_York)
    {-9223372036854775808 -18000 0 EST}
    {-1633280400 -14400 1 EDT}
    {-1615140000 -18000 0 EST}
    {-1601830800 -14400 1 EDT}
    {-1583690400 -18000 0 EST}
    {-880218000 -14400 1 EWT}
    {-769395600 -14400 1 EPT}
    {-765396000 -18000 0 EST}
    {-84387600 -14400 1 EDT}
    {-68666400 -18000 0 EST}
    {-52938000 -14400 1 EDT}
    {-37216800 -18000 0 EST}
    {-21488400 -14400 1 EDT}
    {-5767200 -18000 0 EST}
    {9961200 -14400 1 EDT}
    {25682400 -18000 0 EST}
    {41410800 -14400 1 EDT}
    {57736800 -18000 0 EST}
    {73465200 -14400 1 EDT}
    {89186400 -18000 0 EST}
    {104914800 -14400 1 EDT}
    {120636000 -18000 0 EST}
    {126687600 -14400 1 EDT}
    {152085600 -18000 0 EST}
    {162370800 -14400 1 EDT}
    {183535200 -18000 0 EST}
    {199263600 -14400 1 EDT}
    {215589600 -18000 0 EST}
    {230713200 -14400 1 EDT}
    {247039200 -18000 0 EST}
    {262767600 -14400 1 EDT}
    {278488800 -18000 0 EST}
    {294217200 -14400 1 EDT}
    {309938400 -18000 0 EST}
    {325666800 -14400 1 EDT}
    {341388000 -18000 0 EST}
    {357116400 -14400 1 EDT}
    {372837600 -18000 0 EST}
    {388566000 -14400 1 EDT}
    {404892000 -18000 0 EST}
    {420015600 -14400 1 EDT}
    {436341600 -18000 0 EST}
    {452070000 -14400 1 EDT}
    {467791200 -18000 0 EST}
    {483519600 -14400 1 EDT}
    {499240800 -18000 0 EST}
    {514969200 -14400 1 EDT}
    {530690400 -18000 0 EST}
    {544604400 -14400 1 EDT}
    {562140000 -18000 0 EST}
    {576054000 -14400 1 EDT}
    {594194400 -18000 0 EST}
    {607503600 -14400 1 EDT}
    {625644000 -18000 0 EST}
    {638953200 -14400 1 EDT}
    {657093600 -18000 0 EST}
    {671007600 -14400 1 EDT}
    {688543200 -18000 0 EST}
    {702457200 -14400 1 EDT}
    {719992800 -18000 0 EST}
    {733906800 -14400 1 EDT}
    {752047200 -18000 0 EST}
    {765356400 -14400 1 EDT}
    {783496800 -18000 0 EST}
    {796806000 -14400 1 EDT}
    {814946400 -18000 0 EST}
    {828860400 -14400 1 EDT}
    {846396000 -18000 0 EST}
    {860310000 -14400 1 EDT}
    {877845600 -18000 0 EST}
    {891759600 -14400 1 EDT}
    {909295200 -18000 0 EST}
    {923209200 -14400 1 EDT}
    {941349600 -18000 0 EST}
    {954658800 -14400 1 EDT}
    {972799200 -18000 0 EST}
    {986108400 -14400 1 EDT}
    {1004248800 -18000 0 EST}
    {1018162800 -14400 1 EDT}
    {1035698400 -18000 0 EST}
    {1049612400 -14400 1 EDT}
    {1067148000 -18000 0 EST}
    {1081062000 -14400 1 EDT}
    {1099202400 -18000 0 EST}
    {1112511600 -14400 1 EDT}
    {1130652000 -18000 0 EST}
    {1143961200 -14400 1 EDT}
    {1162101600 -18000 0 EST}
    {1173596400 -14400 1 EDT}
    {1194156000 -18000 0 EST}
    {1205046000 -14400 1 EDT}
    {1225605600 -18000 0 EST}
    {1236495600 -14400 1 EDT}
    {1257055200 -18000 0 EST}
    {1268550000 -14400 1 EDT}
    {1289109600 -18000 0 EST}
    {1299999600 -14400 1 EDT}
    {1320559200 -18000 0 EST}
    {1331449200 -14400 1 EDT}
    {1352008800 -18000 0 EST}
    {1362898800 -14400 1 EDT}
    {1383458400 -18000 0 EST}
    {1394348400 -14400 1 EDT}
    {1414908000 -18000 0 EST}
    {1425798000 -14400 1 EDT}
    {1446357600 -18000 0 EST}
    {1457852400 -14400 1 EDT}
    {1478412000 -18000 0 EST}
    {1489302000 -14400 1 EDT}
    {1509861600 -18000 0 EST}
    {1520751600 -14400 1 EDT}
    {1541311200 -18000 0 EST}
    {1552201200 -14400 1 EDT}
    {1572760800 -18000 0 EST}
    {1583650800 -14400 1 EDT}
    {1604210400 -18000 0 EST}
    {1615705200 -14400 1 EDT}
    {1636264800 -18000 0 EST}
    {1647154800 -14400 1 EDT}
    {1667714400 -18000 0 EST}
    {1678604400 -14400 1 EDT}
    {1699164000 -18000 0 EST}
    {1710054000 -14400 1 EDT}
    {1730613600 -18000 0 EST}
    {1741503600 -14400 1 EDT}
    {1762063200 -18000 0 EST}
    {1772953200 -14400 1 EDT}
    {1793512800 -18000 0 EST}
    {1805007600 -14400 1 EDT}
    {1825567200 -18000 0 EST}
    {1836457200 -14400 1 EDT}
    {1857016800 -18000 0 EST}
    {1867906800 -14400 1 EDT}
    {1888466400 -18000 0 EST}
    {1899356400 -14400 1 EDT}
    {1919916000 -18000 0 EST}
    {1930806000 -14400 1 EDT}
    {1951365600 -18000 0 EST}
    {1962860400 -14400 1 EDT}
    {1983420000 -18000 0 EST}
    {1994310000 -14400 1 EDT}
    {2014869600 -18000 0 EST}
    {2025759600 -14400 1 EDT}
    {2046319200 -18000 0 EST}
    {2057209200 -14400 1 EDT}
    {2077768800 -18000 0 EST}
    {2088658800 -14400 1 EDT}
    {2109218400 -18000 0 EST}
    {2120108400 -14400 1 EDT}
    {2140668000 -18000 0 EST}
    {2152162800 -14400 1 EDT}
    {2172722400 -18000 0 EST}
    {2183612400 -14400 1 EDT}
    {2204172000 -18000 0 EST}
    {2215062000 -14400 1 EDT}
    {2235621600 -18000 0 EST}
    {2246511600 -14400 1 EDT}
    {2267071200 -18000 0 EST}
    {2277961200 -14400 1 EDT}
    {2298520800 -18000 0 EST}
    {2309410800 -14400 1 EDT}
    {2329970400 -18000 0 EST}
    {2341465200 -14400 1 EDT}
    {2362024800 -18000 0 EST}
    {2372914800 -14400 1 EDT}
    {2393474400 -18000 0 EST}
    {2404364400 -14400 1 EDT}
    {2424924000 -18000 0 EST}
    {2435814000 -14400 1 EDT}
    {2456373600 -18000 0 EST}
    {2467263600 -14400 1 EDT}
    {2487823200 -18000 0 EST}
    {2499318000 -14400 1 EDT}
    {2519877600 -18000 0 EST}
    {2530767600 -14400 1 EDT}
    {2551327200 -18000 0 EST}
    {2562217200 -14400 1 EDT}
    {2582776800 -18000 0 EST}
    {2593666800 -14400 1 EDT}
    {2614226400 -18000 0 EST}
    {2625116400 -14400 1 EDT}
    {2645676000 -18000 0 EST}
    {2656566000 -14400 1 EDT}
    {2677125600 -18000 0 EST}
    {2688620400 -14400 1 EDT}
    {2709180000 -18000 0 EST}
    {2720070000 -14400 1 EDT}
    {2740629600 -18000 0 EST}
    {2751519600 -14400 1 EDT}
    {2772079200 -18000 0 EST}
    {2782969200 -14400 1 EDT}
    {2803528800 -18000 0 EST}
    {2814418800 -14400 1 EDT}
    {2834978400 -18000 0 EST}
    {2846473200 -14400 1 EDT}
    {2867032800 -18000 0 EST}
    {2877922800 -14400 1 EDT}
    {2898482400 -18000 0 EST}
    {2909372400 -14400 1 EDT}
    {2929932000 -18000 0 EST}
    {2940822000 -14400 1 EDT}
    {2961381600 -18000 0 EST}
    {2972271600 -14400 1 EDT}
    {2992831200 -18000 0 EST}
    {3003721200 -14400 1 EDT}
    {3024280800 -18000 0 EST}
    {3035775600 -14400 1 EDT}
    {3056335200 -18000 0 EST}
    {3067225200 -14400 1 EDT}
    {3087784800 -18000 0 EST}
    {3098674800 -14400 1 EDT}
    {3119234400 -18000 0 EST}
    {3130124400 -14400 1 EDT}
    {3150684000 -18000 0 EST}
    {3161574000 -14400 1 EDT}
    {3182133600 -18000 0 EST}
    {3193023600 -14400 1 EDT}
    {3213583200 -18000 0 EST}
    {3225078000 -14400 1 EDT}
    {3245637600 -18000 0 EST}
    {3256527600 -14400 1 EDT}
    {3277087200 -18000 0 EST}
    {3287977200 -14400 1 EDT}
    {3308536800 -18000 0 EST}
    {3319426800 -14400 1 EDT}
    {3339986400 -18000 0 EST}
    {3350876400 -14400 1 EDT}
    {3371436000 -18000 0 EST}
    {3382930800 -14400 1 EDT}
    {3403490400 -18000 0 EST}
    {3414380400 -14400 1 EDT}
    {3434940000 -18000 0 EST}
    {3445830000 -14400 1 EDT}
    {3466389600 -18000 0 EST}
    {3477279600 -14400 1 EDT}
    {3497839200 -18000 0 EST}
    {3508729200 -14400 1 EDT}
    {3529288800 -18000 0 EST}
    {3540178800 -14400 1 EDT}
    {3560738400 -18000 0 EST}
    {3572233200 -14400 1 EDT}
    {3592792800 -18000 0 EST}
    {3603682800 -14400 1 EDT}
    {3624242400 -18000 0 EST}
    {3635132400 -14400 1 EDT}
    {3655692000 -18000 0 EST}
    {3666582000 -14400 1 EDT}
    {3687141600 -18000 0 EST}
    {3698031600 -14400 1 EDT}
    {3718591200 -18000 0 EST}
    {3730086000 -14400 1 EDT}
    {3750645600 -18000 0 EST}
    {3761535600 -14400 1 EDT}
    {3782095200 -18000 0 EST}
    {3792985200 -14400 1 EDT}
    {3813544800 -18000 0 EST}
    {3824434800 -14400 1 EDT}
    {3844994400 -18000 0 EST}
    {3855884400 -14400 1 EDT}
    {3876444000 -18000 0 EST}
    {3887334000 -14400 1 EDT}
    {3907893600 -18000 0 EST}
    {3919388400 -14400 1 EDT}
    {3939948000 -18000 0 EST}
    {3950838000 -14400 1 EDT}
    {3971397600 -18000 0 EST}
    {3982287600 -14400 1 EDT}
    {4002847200 -18000 0 EST}
    {4013737200 -14400 1 EDT}
    {4034296800 -18000 0 EST}
    {4045186800 -14400 1 EDT}
    {4065746400 -18000 0 EST}
    {4076636400 -14400 1 EDT}
    {4097196000 -18000 0 EST}
}

Changes to library/tzdata/Etc/GMT+1.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT+1) {
    {-9223372036854775808 -3600 0 -01}
    {-9223372036854775808 -3600 0 -0100}
}

Changes to library/tzdata/Etc/GMT+10.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT+10) {
    {-9223372036854775808 -36000 0 -10}
    {-9223372036854775808 -36000 0 -1000}
}

Changes to library/tzdata/Etc/GMT+11.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT+11) {
    {-9223372036854775808 -39600 0 -11}
    {-9223372036854775808 -39600 0 -1100}
}

Changes to library/tzdata/Etc/GMT+12.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT+12) {
    {-9223372036854775808 -43200 0 -12}
    {-9223372036854775808 -43200 0 -1200}
}

Changes to library/tzdata/Etc/GMT+2.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT+2) {
    {-9223372036854775808 -7200 0 -02}
    {-9223372036854775808 -7200 0 -0200}
}

Changes to library/tzdata/Etc/GMT+3.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT+3) {
    {-9223372036854775808 -10800 0 -03}
    {-9223372036854775808 -10800 0 -0300}
}

Changes to library/tzdata/Etc/GMT+4.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT+4) {
    {-9223372036854775808 -14400 0 -04}
    {-9223372036854775808 -14400 0 -0400}
}

Changes to library/tzdata/Etc/GMT+5.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT+5) {
    {-9223372036854775808 -18000 0 -05}
    {-9223372036854775808 -18000 0 -0500}
}

Changes to library/tzdata/Etc/GMT+6.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT+6) {
    {-9223372036854775808 -21600 0 -06}
    {-9223372036854775808 -21600 0 -0600}
}

Changes to library/tzdata/Etc/GMT+7.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT+7) {
    {-9223372036854775808 -25200 0 -07}
    {-9223372036854775808 -25200 0 -0700}
}

Changes to library/tzdata/Etc/GMT+8.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT+8) {
    {-9223372036854775808 -28800 0 -08}
    {-9223372036854775808 -28800 0 -0800}
}

Changes to library/tzdata/Etc/GMT+9.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT+9) {
    {-9223372036854775808 -32400 0 -09}
    {-9223372036854775808 -32400 0 -0900}
}

Changes to library/tzdata/Etc/GMT-1.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT-1) {
    {-9223372036854775808 3600 0 +01}
    {-9223372036854775808 3600 0 +0100}
}

Changes to library/tzdata/Etc/GMT-10.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT-10) {
    {-9223372036854775808 36000 0 +10}
    {-9223372036854775808 36000 0 +1000}
}

Changes to library/tzdata/Etc/GMT-11.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT-11) {
    {-9223372036854775808 39600 0 +11}
    {-9223372036854775808 39600 0 +1100}
}

Changes to library/tzdata/Etc/GMT-12.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT-12) {
    {-9223372036854775808 43200 0 +12}
    {-9223372036854775808 43200 0 +1200}
}

Changes to library/tzdata/Etc/GMT-13.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT-13) {
    {-9223372036854775808 46800 0 +13}
    {-9223372036854775808 46800 0 +1300}
}

Changes to library/tzdata/Etc/GMT-14.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT-14) {
    {-9223372036854775808 50400 0 +14}
    {-9223372036854775808 50400 0 +1400}
}

Changes to library/tzdata/Etc/GMT-2.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT-2) {
    {-9223372036854775808 7200 0 +02}
    {-9223372036854775808 7200 0 +0200}
}

Changes to library/tzdata/Etc/GMT-3.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT-3) {
    {-9223372036854775808 10800 0 +03}
    {-9223372036854775808 10800 0 +0300}
}

Changes to library/tzdata/Etc/GMT-4.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT-4) {
    {-9223372036854775808 14400 0 +04}
    {-9223372036854775808 14400 0 +0400}
}

Changes to library/tzdata/Etc/GMT-5.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT-5) {
    {-9223372036854775808 18000 0 +05}
    {-9223372036854775808 18000 0 +0500}
}

Changes to library/tzdata/Etc/GMT-6.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT-6) {
    {-9223372036854775808 21600 0 +06}
    {-9223372036854775808 21600 0 +0600}
}

Changes to library/tzdata/Etc/GMT-7.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT-7) {
    {-9223372036854775808 25200 0 +07}
    {-9223372036854775808 25200 0 +0700}
}

Changes to library/tzdata/Etc/GMT-8.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT-8) {
    {-9223372036854775808 28800 0 +08}
    {-9223372036854775808 28800 0 +0800}
}

Changes to library/tzdata/Etc/GMT-9.

1
2
3
4

5
1
2
3

4
5



-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Etc/GMT-9) {
    {-9223372036854775808 32400 0 +09}
    {-9223372036854775808 32400 0 +0900}
}

Changes to library/tzdata/Europe/Amsterdam.

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
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

1

2


























































































































































3

























































































































































4
5

-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

+
# created by tools/tclZIC.tcl - do not edit

if {![info exists TZData(Europe/Brussels)]} {
set TZData(:Europe/Amsterdam) {
    {-9223372036854775808 1172 0 LMT}
    {-4260212372 1172 0 AMT}
    {-1693700372 4772 1 NST}
    {-1680484772 1172 0 AMT}
    {-1663453172 4772 1 NST}
    {-1650147572 1172 0 AMT}
    {-1633213172 4772 1 NST}
    {-1617488372 1172 0 AMT}
    {-1601158772 4772 1 NST}
    {-1586038772 1172 0 AMT}
    {-1569709172 4772 1 NST}
    {-1554589172 1172 0 AMT}
    {-1538259572 4772 1 NST}
    {-1523139572 1172 0 AMT}
    {-1507501172 4772 1 NST}
    {-1490566772 1172 0 AMT}
    {-1470176372 4772 1 NST}
    {-1459117172 1172 0 AMT}
    {-1443997172 4772 1 NST}
    {-1427667572 1172 0 AMT}
    {-1406672372 4772 1 NST}
    {-1396217972 1172 0 AMT}
    {-1376950772 4772 1 NST}
    {-1364768372 1172 0 AMT}
    {-1345414772 4772 1 NST}
    {-1333318772 1172 0 AMT}
    {-1313792372 4772 1 NST}
    {-1301264372 1172 0 AMT}
    {-1282256372 4772 1 NST}
    {-1269814772 1172 0 AMT}
    {-1250720372 4772 1 NST}
    {-1238365172 1172 0 AMT}
    {-1219184372 4772 1 NST}
    {-1206915572 1172 0 AMT}
    {-1186957172 4772 1 NST}
    {-1175465972 1172 0 AMT}
    {-1156025972 4772 1 NST}
    {-1143411572 1172 0 AMT}
    {-1124489972 4772 1 NST}
    {-1111961972 1172 0 AMT}
    {-1092953972 4772 1 NST}
    {-1080512372 1172 0 AMT}
    {-1061331572 4772 1 NST}
    {-1049062772 1172 0 AMT}
    {-1029190772 4772 1 NST}
    {-1025741972 4800 0 +0120}
    {-1017613200 1200 0 +0020}
    {-998259600 4800 1 +0120}
    {-986163600 1200 0 +0020}
    {-966723600 4800 1 +0120}
    {-954109200 1200 0 +0020}
    {-935022000 7200 0 CEST}
    {-857257200 3600 0 CET}
    {-844556400 7200 1 CEST}
    {-828226800 3600 0 CET}
    {-812502000 7200 1 CEST}
    {-796777200 3600 0 CET}
    {-781052400 7200 0 CEST}
    {-766623600 3600 0 CET}
    {220921200 3600 0 CET}
    {228877200 7200 1 CEST}
    {243997200 3600 0 CET}
    {260326800 7200 1 CEST}
    {276051600 3600 0 CET}
    {291776400 7200 1 CEST}
    {307501200 3600 0 CET}
    {323830800 7200 1 CEST}
    {338950800 3600 0 CET}
    {354675600 7200 1 CEST}
    {370400400 3600 0 CET}
    {386125200 7200 1 CEST}
    {401850000 3600 0 CET}
    {417574800 7200 1 CEST}
    {433299600 3600 0 CET}
    {449024400 7200 1 CEST}
    {465354000 3600 0 CET}
    {481078800 7200 1 CEST}
    {496803600 3600 0 CET}
    {512528400 7200 1 CEST}
    {528253200 3600 0 CET}
    {543978000 7200 1 CEST}
    {559702800 3600 0 CET}
    {575427600 7200 1 CEST}
    {591152400 3600 0 CET}
    {606877200 7200 1 CEST}
    {622602000 3600 0 CET}
    {638326800 7200 1 CEST}
    {654656400 3600 0 CET}
    {670381200 7200 1 CEST}
    {686106000 3600 0 CET}
    {701830800 7200 1 CEST}
    {717555600 3600 0 CET}
    {733280400 7200 1 CEST}
    {749005200 3600 0 CET}
    {764730000 7200 1 CEST}
    {780454800 3600 0 CET}
    {796179600 7200 1 CEST}
    {811904400 3600 0 CET}
    {828234000 7200 1 CEST}
    {846378000 3600 0 CET}
    {859683600 7200 1 CEST}
    {877827600 3600 0 CET}
    {891133200 7200 1 CEST}
    {909277200 3600 0 CET}
    {922582800 7200 1 CEST}
    {941331600 3600 0 CET}
    {954032400 7200 1 CEST}
    {972781200 3600 0 CET}
    {985482000 7200 1 CEST}
    {1004230800 3600 0 CET}
    {1017536400 7200 1 CEST}
    {1035680400 3600 0 CET}
    {1048986000 7200 1 CEST}
    {1067130000 3600 0 CET}
    {1080435600 7200 1 CEST}
    {1099184400 3600 0 CET}
    {1111885200 7200 1 CEST}
    {1130634000 3600 0 CET}
    {1143334800 7200 1 CEST}
    {1162083600 3600 0 CET}
    {1174784400 7200 1 CEST}
    {1193533200 3600 0 CET}
    {1206838800 7200 1 CEST}
    {1224982800 3600 0 CET}
    {1238288400 7200 1 CEST}
    {1256432400 3600 0 CET}
    {1269738000 7200 1 CEST}
    {1288486800 3600 0 CET}
    {1301187600 7200 1 CEST}
    {1319936400 3600 0 CET}
    {1332637200 7200 1 CEST}
    {1351386000 3600 0 CET}
    {1364691600 7200 1 CEST}
    {1382835600 3600 0 CET}
    {1396141200 7200 1 CEST}
    {1414285200 3600 0 CET}
    {1427590800 7200 1 CEST}
    {1445734800 3600 0 CET}
    {1459040400 7200 1 CEST}
    {1477789200 3600 0 CET}
    {1490490000 7200 1 CEST}
    {1509238800 3600 0 CET}
    {1521939600 7200 1 CEST}
    {1540688400 3600 0 CET}
    {1553994000 7200 1 CEST}
    {1572138000 3600 0 CET}
    {1585443600 7200 1 CEST}
    {1603587600 3600 0 CET}
    {1616893200 7200 1 CEST}
    {1635642000 3600 0 CET}
    {1648342800 7200 1 CEST}
    {1667091600 3600 0 CET}
    {1679792400 7200 1 CEST}
    LoadTimeZoneFile Europe/Brussels
    {1698541200 3600 0 CET}
    {1711846800 7200 1 CEST}
    {1729990800 3600 0 CET}
    {1743296400 7200 1 CEST}
    {1761440400 3600 0 CET}
    {1774746000 7200 1 CEST}
    {1792890000 3600 0 CET}
    {1806195600 7200 1 CEST}
    {1824944400 3600 0 CET}
    {1837645200 7200 1 CEST}
    {1856394000 3600 0 CET}
    {1869094800 7200 1 CEST}
    {1887843600 3600 0 CET}
    {1901149200 7200 1 CEST}
    {1919293200 3600 0 CET}
    {1932598800 7200 1 CEST}
    {1950742800 3600 0 CET}
    {1964048400 7200 1 CEST}
    {1982797200 3600 0 CET}
    {1995498000 7200 1 CEST}
    {2014246800 3600 0 CET}
    {2026947600 7200 1 CEST}
    {2045696400 3600 0 CET}
    {2058397200 7200 1 CEST}
    {2077146000 3600 0 CET}
    {2090451600 7200 1 CEST}
    {2108595600 3600 0 CET}
    {2121901200 7200 1 CEST}
    {2140045200 3600 0 CET}
    {2153350800 7200 1 CEST}
    {2172099600 3600 0 CET}
    {2184800400 7200 1 CEST}
    {2203549200 3600 0 CET}
    {2216250000 7200 1 CEST}
    {2234998800 3600 0 CET}
    {2248304400 7200 1 CEST}
    {2266448400 3600 0 CET}
    {2279754000 7200 1 CEST}
    {2297898000 3600 0 CET}
    {2311203600 7200 1 CEST}
    {2329347600 3600 0 CET}
    {2342653200 7200 1 CEST}
    {2361402000 3600 0 CET}
    {2374102800 7200 1 CEST}
    {2392851600 3600 0 CET}
    {2405552400 7200 1 CEST}
    {2424301200 3600 0 CET}
    {2437606800 7200 1 CEST}
    {2455750800 3600 0 CET}
    {2469056400 7200 1 CEST}
    {2487200400 3600 0 CET}
    {2500506000 7200 1 CEST}
    {2519254800 3600 0 CET}
    {2531955600 7200 1 CEST}
    {2550704400 3600 0 CET}
    {2563405200 7200 1 CEST}
    {2582154000 3600 0 CET}
    {2595459600 7200 1 CEST}
    {2613603600 3600 0 CET}
    {2626909200 7200 1 CEST}
    {2645053200 3600 0 CET}
    {2658358800 7200 1 CEST}
    {2676502800 3600 0 CET}
    {2689808400 7200 1 CEST}
    {2708557200 3600 0 CET}
    {2721258000 7200 1 CEST}
    {2740006800 3600 0 CET}
    {2752707600 7200 1 CEST}
    {2771456400 3600 0 CET}
    {2784762000 7200 1 CEST}
    {2802906000 3600 0 CET}
    {2816211600 7200 1 CEST}
    {2834355600 3600 0 CET}
    {2847661200 7200 1 CEST}
    {2866410000 3600 0 CET}
    {2879110800 7200 1 CEST}
    {2897859600 3600 0 CET}
    {2910560400 7200 1 CEST}
    {2929309200 3600 0 CET}
    {2942010000 7200 1 CEST}
    {2960758800 3600 0 CET}
    {2974064400 7200 1 CEST}
    {2992208400 3600 0 CET}
    {3005514000 7200 1 CEST}
    {3023658000 3600 0 CET}
    {3036963600 7200 1 CEST}
    {3055712400 3600 0 CET}
    {3068413200 7200 1 CEST}
    {3087162000 3600 0 CET}
    {3099862800 7200 1 CEST}
    {3118611600 3600 0 CET}
    {3131917200 7200 1 CEST}
    {3150061200 3600 0 CET}
    {3163366800 7200 1 CEST}
    {3181510800 3600 0 CET}
    {3194816400 7200 1 CEST}
    {3212960400 3600 0 CET}
    {3226266000 7200 1 CEST}
    {3245014800 3600 0 CET}
    {3257715600 7200 1 CEST}
    {3276464400 3600 0 CET}
    {3289165200 7200 1 CEST}
    {3307914000 3600 0 CET}
    {3321219600 7200 1 CEST}
    {3339363600 3600 0 CET}
    {3352669200 7200 1 CEST}
    {3370813200 3600 0 CET}
    {3384118800 7200 1 CEST}
    {3402867600 3600 0 CET}
    {3415568400 7200 1 CEST}
    {3434317200 3600 0 CET}
    {3447018000 7200 1 CEST}
    {3465766800 3600 0 CET}
    {3479072400 7200 1 CEST}
    {3497216400 3600 0 CET}
    {3510522000 7200 1 CEST}
    {3528666000 3600 0 CET}
    {3541971600 7200 1 CEST}
    {3560115600 3600 0 CET}
    {3573421200 7200 1 CEST}
    {3592170000 3600 0 CET}
    {3604870800 7200 1 CEST}
    {3623619600 3600 0 CET}
    {3636320400 7200 1 CEST}
    {3655069200 3600 0 CET}
    {3668374800 7200 1 CEST}
    {3686518800 3600 0 CET}
    {3699824400 7200 1 CEST}
    {3717968400 3600 0 CET}
    {3731274000 7200 1 CEST}
    {3750022800 3600 0 CET}
    {3762723600 7200 1 CEST}
    {3781472400 3600 0 CET}
    {3794173200 7200 1 CEST}
    {3812922000 3600 0 CET}
    {3825622800 7200 1 CEST}
    {3844371600 3600 0 CET}
    {3857677200 7200 1 CEST}
    {3875821200 3600 0 CET}
    {3889126800 7200 1 CEST}
    {3907270800 3600 0 CET}
    {3920576400 7200 1 CEST}
    {3939325200 3600 0 CET}
    {3952026000 7200 1 CEST}
    {3970774800 3600 0 CET}
    {3983475600 7200 1 CEST}
    {4002224400 3600 0 CET}
    {4015530000 7200 1 CEST}
    {4033674000 3600 0 CET}
    {4046979600 7200 1 CEST}
    {4065123600 3600 0 CET}
    {4078429200 7200 1 CEST}
    {4096573200 3600 0 CET}
}
set TZData(:Europe/Amsterdam) $TZData(:Europe/Brussels)

Changes to library/tzdata/Europe/Astrakhan.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Astrakhan) {
    {-9223372036854775808 11532 0 LMT}
    {-1441249932 10800 0 +03}
    {-1247540400 14400 0 +05}
    {354916800 18000 1 +05}
    {370724400 14400 0 +04}
    {386452800 18000 1 +05}
    {402260400 14400 0 +04}
    {417988800 18000 1 +05}
    {433796400 14400 0 +04}
    {449611200 18000 1 +05}
    {465343200 14400 0 +04}
    {481068000 18000 1 +05}
    {496792800 14400 0 +04}
    {512517600 18000 1 +05}
    {528242400 14400 0 +04}
    {543967200 18000 1 +05}
    {559692000 14400 0 +04}
    {575416800 18000 1 +05}
    {591141600 14400 0 +04}
    {606866400 10800 0 +04}
    {606870000 14400 1 +04}
    {622594800 10800 0 +03}
    {638319600 14400 1 +04}
    {654649200 10800 0 +03}
    {670374000 14400 0 +04}
    {701820000 10800 0 +04}
    {701823600 14400 1 +04}
    {717548400 10800 0 +03}
    {733273200 14400 1 +04}
    {748998000 10800 0 +03}
    {764722800 14400 1 +04}
    {780447600 10800 0 +03}
    {796172400 14400 1 +04}
    {811897200 10800 0 +03}
    {828226800 14400 1 +04}
    {846370800 10800 0 +03}
    {859676400 14400 1 +04}
    {877820400 10800 0 +03}
    {891126000 14400 1 +04}
    {909270000 10800 0 +03}
    {922575600 14400 1 +04}
    {941324400 10800 0 +03}
    {954025200 14400 1 +04}
    {972774000 10800 0 +03}
    {985474800 14400 1 +04}
    {1004223600 10800 0 +03}
    {1017529200 14400 1 +04}
    {1035673200 10800 0 +03}
    {1048978800 14400 1 +04}
    {1067122800 10800 0 +03}
    {1080428400 14400 1 +04}
    {1099177200 10800 0 +03}
    {1111878000 14400 1 +04}
    {1130626800 10800 0 +03}
    {1143327600 14400 1 +04}
    {1162076400 10800 0 +03}
    {1174777200 14400 1 +04}
    {1193526000 10800 0 +03}
    {1206831600 14400 1 +04}
    {1224975600 10800 0 +03}
    {1238281200 14400 1 +04}
    {1256425200 10800 0 +03}
    {1269730800 14400 1 +04}
    {1288479600 10800 0 +03}
    {1301180400 14400 0 +04}
    {1414274400 10800 0 +03}
    {1459033200 14400 0 +04}
    {-1441249932 10800 0 +0300}
    {-1247540400 14400 0 +0400}
    {354916800 18000 1 +0500}
    {370724400 14400 0 +0400}
    {386452800 18000 1 +0500}
    {402260400 14400 0 +0400}
    {417988800 18000 1 +0500}
    {433796400 14400 0 +0400}
    {449611200 18000 1 +0500}
    {465343200 14400 0 +0400}
    {481068000 18000 1 +0500}
    {496792800 14400 0 +0400}
    {512517600 18000 1 +0500}
    {528242400 14400 0 +0400}
    {543967200 18000 1 +0500}
    {559692000 14400 0 +0400}
    {575416800 18000 1 +0500}
    {591141600 14400 0 +0400}
    {606866400 10800 0 +0300}
    {606870000 14400 1 +0400}
    {622594800 10800 0 +0300}
    {638319600 14400 1 +0400}
    {654649200 10800 0 +0300}
    {670374000 14400 0 +0400}
    {701820000 10800 0 +0300}
    {701823600 14400 1 +0400}
    {717548400 10800 0 +0300}
    {733273200 14400 1 +0400}
    {748998000 10800 0 +0300}
    {764722800 14400 1 +0400}
    {780447600 10800 0 +0300}
    {796172400 14400 1 +0400}
    {811897200 10800 0 +0300}
    {828226800 14400 1 +0400}
    {846370800 10800 0 +0300}
    {859676400 14400 1 +0400}
    {877820400 10800 0 +0300}
    {891126000 14400 1 +0400}
    {909270000 10800 0 +0300}
    {922575600 14400 1 +0400}
    {941324400 10800 0 +0300}
    {954025200 14400 1 +0400}
    {972774000 10800 0 +0300}
    {985474800 14400 1 +0400}
    {1004223600 10800 0 +0300}
    {1017529200 14400 1 +0400}
    {1035673200 10800 0 +0300}
    {1048978800 14400 1 +0400}
    {1067122800 10800 0 +0300}
    {1080428400 14400 1 +0400}
    {1099177200 10800 0 +0300}
    {1111878000 14400 1 +0400}
    {1130626800 10800 0 +0300}
    {1143327600 14400 1 +0400}
    {1162076400 10800 0 +0300}
    {1174777200 14400 1 +0400}
    {1193526000 10800 0 +0300}
    {1206831600 14400 1 +0400}
    {1224975600 10800 0 +0300}
    {1238281200 14400 1 +0400}
    {1256425200 10800 0 +0300}
    {1269730800 14400 1 +0400}
    {1288479600 10800 0 +0300}
    {1301180400 14400 0 +0400}
    {1414274400 10800 0 +0300}
    {1459033200 14400 0 +0400}
}

Changes to library/tzdata/Europe/Copenhagen.

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
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
1
2
3


4
5






































































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Berlin)]} {
    LoadTimeZoneFile Europe/Berlin

set TZData(:Europe/Copenhagen) {
}
set TZData(:Europe/Copenhagen) $TZData(:Europe/Berlin)
    {-9223372036854775808 3020 0 LMT}
    {-2524524620 3020 0 CMT}
    {-2398294220 3600 0 CET}
    {-1692496800 7200 1 CEST}
    {-1680490800 3600 0 CET}
    {-935110800 7200 1 CEST}
    {-857257200 3600 0 CET}
    {-844556400 7200 1 CEST}
    {-828226800 3600 0 CET}
    {-812502000 7200 1 CEST}
    {-796777200 3600 0 CET}
    {-781052400 7200 0 CEST}
    {-769388400 3600 0 CET}
    {-747010800 7200 1 CEST}
    {-736383600 3600 0 CET}
    {-715215600 7200 1 CEST}
    {-706748400 3600 0 CET}
    {-683161200 7200 1 CEST}
    {-675298800 3600 0 CET}
    {315529200 3600 0 CET}
    {323830800 7200 1 CEST}
    {338950800 3600 0 CET}
    {354675600 7200 1 CEST}
    {370400400 3600 0 CET}
    {386125200 7200 1 CEST}
    {401850000 3600 0 CET}
    {417574800 7200 1 CEST}
    {433299600 3600 0 CET}
    {449024400 7200 1 CEST}
    {465354000 3600 0 CET}
    {481078800 7200 1 CEST}
    {496803600 3600 0 CET}
    {512528400 7200 1 CEST}
    {528253200 3600 0 CET}
    {543978000 7200 1 CEST}
    {559702800 3600 0 CET}
    {575427600 7200 1 CEST}
    {591152400 3600 0 CET}
    {606877200 7200 1 CEST}
    {622602000 3600 0 CET}
    {638326800 7200 1 CEST}
    {654656400 3600 0 CET}
    {670381200 7200 1 CEST}
    {686106000 3600 0 CET}
    {701830800 7200 1 CEST}
    {717555600 3600 0 CET}
    {733280400 7200 1 CEST}
    {749005200 3600 0 CET}
    {764730000 7200 1 CEST}
    {780454800 3600 0 CET}
    {796179600 7200 1 CEST}
    {811904400 3600 0 CET}
    {828234000 7200 1 CEST}
    {846378000 3600 0 CET}
    {859683600 7200 1 CEST}
    {877827600 3600 0 CET}
    {891133200 7200 1 CEST}
    {909277200 3600 0 CET}
    {922582800 7200 1 CEST}
    {941331600 3600 0 CET}
    {954032400 7200 1 CEST}
    {972781200 3600 0 CET}
    {985482000 7200 1 CEST}
    {1004230800 3600 0 CET}
    {1017536400 7200 1 CEST}
    {1035680400 3600 0 CET}
    {1048986000 7200 1 CEST}
    {1067130000 3600 0 CET}
    {1080435600 7200 1 CEST}
    {1099184400 3600 0 CET}
    {1111885200 7200 1 CEST}
    {1130634000 3600 0 CET}
    {1143334800 7200 1 CEST}
    {1162083600 3600 0 CET}
    {1174784400 7200 1 CEST}
    {1193533200 3600 0 CET}
    {1206838800 7200 1 CEST}
    {1224982800 3600 0 CET}
    {1238288400 7200 1 CEST}
    {1256432400 3600 0 CET}
    {1269738000 7200 1 CEST}
    {1288486800 3600 0 CET}
    {1301187600 7200 1 CEST}
    {1319936400 3600 0 CET}
    {1332637200 7200 1 CEST}
    {1351386000 3600 0 CET}
    {1364691600 7200 1 CEST}
    {1382835600 3600 0 CET}
    {1396141200 7200 1 CEST}
    {1414285200 3600 0 CET}
    {1427590800 7200 1 CEST}
    {1445734800 3600 0 CET}
    {1459040400 7200 1 CEST}
    {1477789200 3600 0 CET}
    {1490490000 7200 1 CEST}
    {1509238800 3600 0 CET}
    {1521939600 7200 1 CEST}
    {1540688400 3600 0 CET}
    {1553994000 7200 1 CEST}
    {1572138000 3600 0 CET}
    {1585443600 7200 1 CEST}
    {1603587600 3600 0 CET}
    {1616893200 7200 1 CEST}
    {1635642000 3600 0 CET}
    {1648342800 7200 1 CEST}
    {1667091600 3600 0 CET}
    {1679792400 7200 1 CEST}
    {1698541200 3600 0 CET}
    {1711846800 7200 1 CEST}
    {1729990800 3600 0 CET}
    {1743296400 7200 1 CEST}
    {1761440400 3600 0 CET}
    {1774746000 7200 1 CEST}
    {1792890000 3600 0 CET}
    {1806195600 7200 1 CEST}
    {1824944400 3600 0 CET}
    {1837645200 7200 1 CEST}
    {1856394000 3600 0 CET}
    {1869094800 7200 1 CEST}
    {1887843600 3600 0 CET}
    {1901149200 7200 1 CEST}
    {1919293200 3600 0 CET}
    {1932598800 7200 1 CEST}
    {1950742800 3600 0 CET}
    {1964048400 7200 1 CEST}
    {1982797200 3600 0 CET}
    {1995498000 7200 1 CEST}
    {2014246800 3600 0 CET}
    {2026947600 7200 1 CEST}
    {2045696400 3600 0 CET}
    {2058397200 7200 1 CEST}
    {2077146000 3600 0 CET}
    {2090451600 7200 1 CEST}
    {2108595600 3600 0 CET}
    {2121901200 7200 1 CEST}
    {2140045200 3600 0 CET}
    {2153350800 7200 1 CEST}
    {2172099600 3600 0 CET}
    {2184800400 7200 1 CEST}
    {2203549200 3600 0 CET}
    {2216250000 7200 1 CEST}
    {2234998800 3600 0 CET}
    {2248304400 7200 1 CEST}
    {2266448400 3600 0 CET}
    {2279754000 7200 1 CEST}
    {2297898000 3600 0 CET}
    {2311203600 7200 1 CEST}
    {2329347600 3600 0 CET}
    {2342653200 7200 1 CEST}
    {2361402000 3600 0 CET}
    {2374102800 7200 1 CEST}
    {2392851600 3600 0 CET}
    {2405552400 7200 1 CEST}
    {2424301200 3600 0 CET}
    {2437606800 7200 1 CEST}
    {2455750800 3600 0 CET}
    {2469056400 7200 1 CEST}
    {2487200400 3600 0 CET}
    {2500506000 7200 1 CEST}
    {2519254800 3600 0 CET}
    {2531955600 7200 1 CEST}
    {2550704400 3600 0 CET}
    {2563405200 7200 1 CEST}
    {2582154000 3600 0 CET}
    {2595459600 7200 1 CEST}
    {2613603600 3600 0 CET}
    {2626909200 7200 1 CEST}
    {2645053200 3600 0 CET}
    {2658358800 7200 1 CEST}
    {2676502800 3600 0 CET}
    {2689808400 7200 1 CEST}
    {2708557200 3600 0 CET}
    {2721258000 7200 1 CEST}
    {2740006800 3600 0 CET}
    {2752707600 7200 1 CEST}
    {2771456400 3600 0 CET}
    {2784762000 7200 1 CEST}
    {2802906000 3600 0 CET}
    {2816211600 7200 1 CEST}
    {2834355600 3600 0 CET}
    {2847661200 7200 1 CEST}
    {2866410000 3600 0 CET}
    {2879110800 7200 1 CEST}
    {2897859600 3600 0 CET}
    {2910560400 7200 1 CEST}
    {2929309200 3600 0 CET}
    {2942010000 7200 1 CEST}
    {2960758800 3600 0 CET}
    {2974064400 7200 1 CEST}
    {2992208400 3600 0 CET}
    {3005514000 7200 1 CEST}
    {3023658000 3600 0 CET}
    {3036963600 7200 1 CEST}
    {3055712400 3600 0 CET}
    {3068413200 7200 1 CEST}
    {3087162000 3600 0 CET}
    {3099862800 7200 1 CEST}
    {3118611600 3600 0 CET}
    {3131917200 7200 1 CEST}
    {3150061200 3600 0 CET}
    {3163366800 7200 1 CEST}
    {3181510800 3600 0 CET}
    {3194816400 7200 1 CEST}
    {3212960400 3600 0 CET}
    {3226266000 7200 1 CEST}
    {3245014800 3600 0 CET}
    {3257715600 7200 1 CEST}
    {3276464400 3600 0 CET}
    {3289165200 7200 1 CEST}
    {3307914000 3600 0 CET}
    {3321219600 7200 1 CEST}
    {3339363600 3600 0 CET}
    {3352669200 7200 1 CEST}
    {3370813200 3600 0 CET}
    {3384118800 7200 1 CEST}
    {3402867600 3600 0 CET}
    {3415568400 7200 1 CEST}
    {3434317200 3600 0 CET}
    {3447018000 7200 1 CEST}
    {3465766800 3600 0 CET}
    {3479072400 7200 1 CEST}
    {3497216400 3600 0 CET}
    {3510522000 7200 1 CEST}
    {3528666000 3600 0 CET}
    {3541971600 7200 1 CEST}
    {3560115600 3600 0 CET}
    {3573421200 7200 1 CEST}
    {3592170000 3600 0 CET}
    {3604870800 7200 1 CEST}
    {3623619600 3600 0 CET}
    {3636320400 7200 1 CEST}
    {3655069200 3600 0 CET}
    {3668374800 7200 1 CEST}
    {3686518800 3600 0 CET}
    {3699824400 7200 1 CEST}
    {3717968400 3600 0 CET}
    {3731274000 7200 1 CEST}
    {3750022800 3600 0 CET}
    {3762723600 7200 1 CEST}
    {3781472400 3600 0 CET}
    {3794173200 7200 1 CEST}
    {3812922000 3600 0 CET}
    {3825622800 7200 1 CEST}
    {3844371600 3600 0 CET}
    {3857677200 7200 1 CEST}
    {3875821200 3600 0 CET}
    {3889126800 7200 1 CEST}
    {3907270800 3600 0 CET}
    {3920576400 7200 1 CEST}
    {3939325200 3600 0 CET}
    {3952026000 7200 1 CEST}
    {3970774800 3600 0 CET}
    {3983475600 7200 1 CEST}
    {4002224400 3600 0 CET}
    {4015530000 7200 1 CEST}
    {4033674000 3600 0 CET}
    {4046979600 7200 1 CEST}
    {4065123600 3600 0 CET}
    {4078429200 7200 1 CEST}
    {4096573200 3600 0 CET}
}

Changes to library/tzdata/Europe/Dublin.

1
2
3
4
5


6
7
8
9
10
11
12
1
2
3


4
5
6
7
8
9
10
11
12



-
-
+
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Dublin) {
    {-9223372036854775808 -1500 0 LMT}
    {-2821649700 -1521 0 DMT}
    {-9223372036854775808 -1521 0 LMT}
    {-2821649679 -1521 0 DMT}
    {-1691962479 2079 1 IST}
    {-1680471279 0 0 GMT}
    {-1664143200 3600 1 BST}
    {-1650146400 0 0 GMT}
    {-1633903200 3600 1 BST}
    {-1617487200 0 0 GMT}
    {-1601848800 3600 1 BST}

Changes to library/tzdata/Europe/Istanbul.

45
46
47
48
49
50
51
52
53
54
55




56
57
58
59
60
61
62
45
46
47
48
49
50
51




52
53
54
55
56
57
58
59
60
61
62







-
-
-
-
+
+
+
+







    {164678400 10800 1 EEST}
    {184114800 7200 0 EET}
    {196214400 10800 1 EEST}
    {215564400 7200 0 EET}
    {228873600 10800 1 EEST}
    {245804400 7200 0 EET}
    {260323200 10800 1 EEST}
    {267919200 10800 0 +03}
    {277254000 10800 0 +03}
    {428454000 14400 1 +04}
    {433893600 10800 0 +03}
    {267919200 10800 0 +0300}
    {277254000 10800 0 +0300}
    {428454000 14400 1 +0400}
    {433893600 10800 0 +0300}
    {468111600 7200 0 EET}
    {482799600 10800 1 EEST}
    {496710000 7200 0 EET}
    {512521200 10800 1 EEST}
    {528246000 7200 0 EET}
    {543970800 10800 1 EEST}
    {559695600 7200 0 EET}
117
118
119
120
121
122
123
124

125
117
118
119
120
121
122
123

124
125







-
+

    {1396141200 7200 0 EET}
    {1396227600 10800 0 EEST}
    {1414285200 7200 0 EET}
    {1427590800 10800 1 EEST}
    {1445734800 10800 1 EEST}
    {1446944400 7200 0 EET}
    {1459040400 10800 1 EEST}
    {1473199200 10800 0 +03}
    {1473199200 10800 0 +0300}
}

Changes to library/tzdata/Europe/Kaliningrad.

77
78
79
80
81
82
83
84

85
86
77
78
79
80
81
82
83

84
85
86







-
+


    {1193529600 7200 0 EET}
    {1206835200 10800 1 EEST}
    {1224979200 7200 0 EET}
    {1238284800 10800 1 EEST}
    {1256428800 7200 0 EET}
    {1269734400 10800 1 EEST}
    {1288483200 7200 0 EET}
    {1301184000 10800 0 +03}
    {1301184000 10800 0 +0300}
    {1414278000 7200 0 EET}
}

Changes to library/tzdata/Europe/Kiev.

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
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
1
2
3


4
5

























































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Kyiv)]} {
    LoadTimeZoneFile Europe/Kyiv

set TZData(:Europe/Kiev) {
}
set TZData(:Europe/Kiev) $TZData(:Europe/Kyiv)
    {-9223372036854775808 7324 0 LMT}
    {-2840148124 7324 0 KMT}
    {-1441159324 7200 0 EET}
    {-1247536800 10800 0 MSK}
    {-892522800 3600 0 CET}
    {-857257200 3600 0 CET}
    {-844556400 7200 1 CEST}
    {-828226800 3600 0 CET}
    {-825382800 10800 0 MSD}
    {354920400 14400 1 MSD}
    {370728000 10800 0 MSK}
    {386456400 14400 1 MSD}
    {402264000 10800 0 MSK}
    {417992400 14400 1 MSD}
    {433800000 10800 0 MSK}
    {449614800 14400 1 MSD}
    {465346800 10800 0 MSK}
    {481071600 14400 1 MSD}
    {496796400 10800 0 MSK}
    {512521200 14400 1 MSD}
    {528246000 10800 0 MSK}
    {543970800 14400 1 MSD}
    {559695600 10800 0 MSK}
    {575420400 14400 1 MSD}
    {591145200 10800 0 MSK}
    {606870000 14400 1 MSD}
    {622594800 10800 0 MSK}
    {638319600 14400 1 MSD}
    {646786800 10800 1 EEST}
    {686102400 7200 0 EET}
    {701820000 10800 1 EEST}
    {717541200 7200 0 EET}
    {733269600 10800 1 EEST}
    {748990800 7200 0 EET}
    {764719200 10800 1 EEST}
    {780440400 7200 0 EET}
    {788911200 7200 0 EET}
    {796179600 10800 1 EEST}
    {811904400 7200 0 EET}
    {828234000 10800 1 EEST}
    {846378000 7200 0 EET}
    {859683600 10800 1 EEST}
    {877827600 7200 0 EET}
    {891133200 10800 1 EEST}
    {909277200 7200 0 EET}
    {922582800 10800 1 EEST}
    {941331600 7200 0 EET}
    {954032400 10800 1 EEST}
    {972781200 7200 0 EET}
    {985482000 10800 1 EEST}
    {1004230800 7200 0 EET}
    {1017536400 10800 1 EEST}
    {1035680400 7200 0 EET}
    {1048986000 10800 1 EEST}
    {1067130000 7200 0 EET}
    {1080435600 10800 1 EEST}
    {1099184400 7200 0 EET}
    {1111885200 10800 1 EEST}
    {1130634000 7200 0 EET}
    {1143334800 10800 1 EEST}
    {1162083600 7200 0 EET}
    {1174784400 10800 1 EEST}
    {1193533200 7200 0 EET}
    {1206838800 10800 1 EEST}
    {1224982800 7200 0 EET}
    {1238288400 10800 1 EEST}
    {1256432400 7200 0 EET}
    {1269738000 10800 1 EEST}
    {1288486800 7200 0 EET}
    {1301187600 10800 1 EEST}
    {1319936400 7200 0 EET}
    {1332637200 10800 1 EEST}
    {1351386000 7200 0 EET}
    {1364691600 10800 1 EEST}
    {1382835600 7200 0 EET}
    {1396141200 10800 1 EEST}
    {1414285200 7200 0 EET}
    {1427590800 10800 1 EEST}
    {1445734800 7200 0 EET}
    {1459040400 10800 1 EEST}
    {1477789200 7200 0 EET}
    {1490490000 10800 1 EEST}
    {1509238800 7200 0 EET}
    {1521939600 10800 1 EEST}
    {1540688400 7200 0 EET}
    {1553994000 10800 1 EEST}
    {1572138000 7200 0 EET}
    {1585443600 10800 1 EEST}
    {1603587600 7200 0 EET}
    {1616893200 10800 1 EEST}
    {1635642000 7200 0 EET}
    {1648342800 10800 1 EEST}
    {1667091600 7200 0 EET}
    {1679792400 10800 1 EEST}
    {1698541200 7200 0 EET}
    {1711846800 10800 1 EEST}
    {1729990800 7200 0 EET}
    {1743296400 10800 1 EEST}
    {1761440400 7200 0 EET}
    {1774746000 10800 1 EEST}
    {1792890000 7200 0 EET}
    {1806195600 10800 1 EEST}
    {1824944400 7200 0 EET}
    {1837645200 10800 1 EEST}
    {1856394000 7200 0 EET}
    {1869094800 10800 1 EEST}
    {1887843600 7200 0 EET}
    {1901149200 10800 1 EEST}
    {1919293200 7200 0 EET}
    {1932598800 10800 1 EEST}
    {1950742800 7200 0 EET}
    {1964048400 10800 1 EEST}
    {1982797200 7200 0 EET}
    {1995498000 10800 1 EEST}
    {2014246800 7200 0 EET}
    {2026947600 10800 1 EEST}
    {2045696400 7200 0 EET}
    {2058397200 10800 1 EEST}
    {2077146000 7200 0 EET}
    {2090451600 10800 1 EEST}
    {2108595600 7200 0 EET}
    {2121901200 10800 1 EEST}
    {2140045200 7200 0 EET}
    {2153350800 10800 1 EEST}
    {2172099600 7200 0 EET}
    {2184800400 10800 1 EEST}
    {2203549200 7200 0 EET}
    {2216250000 10800 1 EEST}
    {2234998800 7200 0 EET}
    {2248304400 10800 1 EEST}
    {2266448400 7200 0 EET}
    {2279754000 10800 1 EEST}
    {2297898000 7200 0 EET}
    {2311203600 10800 1 EEST}
    {2329347600 7200 0 EET}
    {2342653200 10800 1 EEST}
    {2361402000 7200 0 EET}
    {2374102800 10800 1 EEST}
    {2392851600 7200 0 EET}
    {2405552400 10800 1 EEST}
    {2424301200 7200 0 EET}
    {2437606800 10800 1 EEST}
    {2455750800 7200 0 EET}
    {2469056400 10800 1 EEST}
    {2487200400 7200 0 EET}
    {2500506000 10800 1 EEST}
    {2519254800 7200 0 EET}
    {2531955600 10800 1 EEST}
    {2550704400 7200 0 EET}
    {2563405200 10800 1 EEST}
    {2582154000 7200 0 EET}
    {2595459600 10800 1 EEST}
    {2613603600 7200 0 EET}
    {2626909200 10800 1 EEST}
    {2645053200 7200 0 EET}
    {2658358800 10800 1 EEST}
    {2676502800 7200 0 EET}
    {2689808400 10800 1 EEST}
    {2708557200 7200 0 EET}
    {2721258000 10800 1 EEST}
    {2740006800 7200 0 EET}
    {2752707600 10800 1 EEST}
    {2771456400 7200 0 EET}
    {2784762000 10800 1 EEST}
    {2802906000 7200 0 EET}
    {2816211600 10800 1 EEST}
    {2834355600 7200 0 EET}
    {2847661200 10800 1 EEST}
    {2866410000 7200 0 EET}
    {2879110800 10800 1 EEST}
    {2897859600 7200 0 EET}
    {2910560400 10800 1 EEST}
    {2929309200 7200 0 EET}
    {2942010000 10800 1 EEST}
    {2960758800 7200 0 EET}
    {2974064400 10800 1 EEST}
    {2992208400 7200 0 EET}
    {3005514000 10800 1 EEST}
    {3023658000 7200 0 EET}
    {3036963600 10800 1 EEST}
    {3055712400 7200 0 EET}
    {3068413200 10800 1 EEST}
    {3087162000 7200 0 EET}
    {3099862800 10800 1 EEST}
    {3118611600 7200 0 EET}
    {3131917200 10800 1 EEST}
    {3150061200 7200 0 EET}
    {3163366800 10800 1 EEST}
    {3181510800 7200 0 EET}
    {3194816400 10800 1 EEST}
    {3212960400 7200 0 EET}
    {3226266000 10800 1 EEST}
    {3245014800 7200 0 EET}
    {3257715600 10800 1 EEST}
    {3276464400 7200 0 EET}
    {3289165200 10800 1 EEST}
    {3307914000 7200 0 EET}
    {3321219600 10800 1 EEST}
    {3339363600 7200 0 EET}
    {3352669200 10800 1 EEST}
    {3370813200 7200 0 EET}
    {3384118800 10800 1 EEST}
    {3402867600 7200 0 EET}
    {3415568400 10800 1 EEST}
    {3434317200 7200 0 EET}
    {3447018000 10800 1 EEST}
    {3465766800 7200 0 EET}
    {3479072400 10800 1 EEST}
    {3497216400 7200 0 EET}
    {3510522000 10800 1 EEST}
    {3528666000 7200 0 EET}
    {3541971600 10800 1 EEST}
    {3560115600 7200 0 EET}
    {3573421200 10800 1 EEST}
    {3592170000 7200 0 EET}
    {3604870800 10800 1 EEST}
    {3623619600 7200 0 EET}
    {3636320400 10800 1 EEST}
    {3655069200 7200 0 EET}
    {3668374800 10800 1 EEST}
    {3686518800 7200 0 EET}
    {3699824400 10800 1 EEST}
    {3717968400 7200 0 EET}
    {3731274000 10800 1 EEST}
    {3750022800 7200 0 EET}
    {3762723600 10800 1 EEST}
    {3781472400 7200 0 EET}
    {3794173200 10800 1 EEST}
    {3812922000 7200 0 EET}
    {3825622800 10800 1 EEST}
    {3844371600 7200 0 EET}
    {3857677200 10800 1 EEST}
    {3875821200 7200 0 EET}
    {3889126800 10800 1 EEST}
    {3907270800 7200 0 EET}
    {3920576400 10800 1 EEST}
    {3939325200 7200 0 EET}
    {3952026000 10800 1 EEST}
    {3970774800 7200 0 EET}
    {3983475600 10800 1 EEST}
    {4002224400 7200 0 EET}
    {4015530000 10800 1 EEST}
    {4033674000 7200 0 EET}
    {4046979600 10800 1 EEST}
    {4065123600 7200 0 EET}
    {4078429200 10800 1 EEST}
    {4096573200 7200 0 EET}
}

Changes to library/tzdata/Europe/Kirov.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Kirov) {
    {-9223372036854775808 11928 0 LMT}
    {-1593820800 10800 0 +03}
    {-1247540400 14400 0 +05}
    {354916800 18000 1 +05}
    {370724400 14400 0 +04}
    {386452800 18000 1 +05}
    {402260400 14400 0 +04}
    {417988800 18000 1 +05}
    {433796400 14400 0 +04}
    {449611200 18000 1 +05}
    {465343200 14400 0 +04}
    {481068000 18000 1 +05}
    {496792800 14400 0 +04}
    {512517600 18000 1 +05}
    {528242400 14400 0 +04}
    {543967200 18000 1 +05}
    {559692000 14400 0 +04}
    {575416800 18000 1 +05}
    {591141600 14400 0 +04}
    {606866400 10800 0 +04}
    {606870000 14400 1 +04}
    {622594800 10800 0 +03}
    {638319600 14400 1 +04}
    {654649200 10800 0 +03}
    {670374000 14400 0 +04}
    {701820000 10800 0 +04}
    {701823600 14400 1 +04}
    {717548400 10800 0 +03}
    {733273200 14400 1 +04}
    {748998000 10800 0 +03}
    {764722800 14400 1 +04}
    {780447600 10800 0 +03}
    {796172400 14400 1 +04}
    {811897200 10800 0 +03}
    {828226800 14400 1 +04}
    {846370800 10800 0 +03}
    {859676400 14400 1 +04}
    {877820400 10800 0 +03}
    {891126000 14400 1 +04}
    {909270000 10800 0 +03}
    {922575600 14400 1 +04}
    {941324400 10800 0 +03}
    {954025200 14400 1 +04}
    {972774000 10800 0 +03}
    {985474800 14400 1 +04}
    {1004223600 10800 0 +03}
    {1017529200 14400 1 +04}
    {1035673200 10800 0 +03}
    {1048978800 14400 1 +04}
    {1067122800 10800 0 +03}
    {1080428400 14400 1 +04}
    {1099177200 10800 0 +03}
    {1111878000 14400 1 +04}
    {1130626800 10800 0 +03}
    {1143327600 14400 1 +04}
    {1162076400 10800 0 +03}
    {1174777200 14400 1 +04}
    {1193526000 10800 0 +03}
    {1206831600 14400 1 +04}
    {1224975600 10800 0 +03}
    {1238281200 14400 1 +04}
    {1256425200 10800 0 +03}
    {1269730800 14400 1 +04}
    {1288479600 10800 0 +03}
    {1301180400 14400 0 +04}
    {1414274400 10800 0 +03}
    {-1593820800 10800 0 +0300}
    {-1247540400 14400 0 +0400}
    {354916800 18000 1 +0500}
    {370724400 14400 0 +0400}
    {386452800 18000 1 +0500}
    {402260400 14400 0 +0400}
    {417988800 18000 1 +0500}
    {433796400 14400 0 +0400}
    {449611200 18000 1 +0500}
    {465343200 14400 0 +0400}
    {481068000 18000 1 +0500}
    {496792800 14400 0 +0400}
    {512517600 18000 1 +0500}
    {528242400 14400 0 +0400}
    {543967200 18000 1 +0500}
    {559692000 14400 0 +0400}
    {575416800 18000 1 +0500}
    {591141600 14400 0 +0400}
    {606866400 10800 0 MSD}
    {606870000 14400 1 MSD}
    {622594800 10800 0 MSK}
    {638319600 14400 1 MSD}
    {654649200 10800 0 MSK}
    {670374000 14400 0 +0400}
    {701820000 10800 0 MSD}
    {701823600 14400 1 MSD}
    {717548400 10800 0 MSK}
    {733273200 14400 1 MSD}
    {748998000 10800 0 MSK}
    {764722800 14400 1 MSD}
    {780447600 10800 0 MSK}
    {796172400 14400 1 MSD}
    {811897200 10800 0 MSK}
    {828226800 14400 1 MSD}
    {846370800 10800 0 MSK}
    {859676400 14400 1 MSD}
    {877820400 10800 0 MSK}
    {891126000 14400 1 MSD}
    {909270000 10800 0 MSK}
    {922575600 14400 1 MSD}
    {941324400 10800 0 MSK}
    {954025200 14400 1 MSD}
    {972774000 10800 0 MSK}
    {985474800 14400 1 MSD}
    {1004223600 10800 0 MSK}
    {1017529200 14400 1 MSD}
    {1035673200 10800 0 MSK}
    {1048978800 14400 1 MSD}
    {1067122800 10800 0 MSK}
    {1080428400 14400 1 MSD}
    {1099177200 10800 0 MSK}
    {1111878000 14400 1 MSD}
    {1130626800 10800 0 MSK}
    {1143327600 14400 1 MSD}
    {1162076400 10800 0 MSK}
    {1174777200 14400 1 MSD}
    {1193526000 10800 0 MSK}
    {1206831600 14400 1 MSD}
    {1224975600 10800 0 MSK}
    {1238281200 14400 1 MSD}
    {1256425200 10800 0 MSK}
    {1269730800 14400 1 MSD}
    {1288479600 10800 0 MSK}
    {1301180400 14400 0 MSK}
    {1414274400 10800 0 MSK}
}

Added library/tzdata/Europe/Kyiv.




























































































































































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Kyiv) {
    {-9223372036854775808 7324 0 LMT}
    {-2840148124 7324 0 KMT}
    {-1441159324 7200 0 EET}
    {-1247536800 10800 0 MSK}
    {-892522800 3600 0 CET}
    {-857257200 3600 0 CET}
    {-844556400 7200 1 CEST}
    {-828226800 3600 0 CET}
    {-825382800 10800 0 MSD}
    {354920400 14400 1 MSD}
    {370728000 10800 0 MSK}
    {386456400 14400 1 MSD}
    {402264000 10800 0 MSK}
    {417992400 14400 1 MSD}
    {433800000 10800 0 MSK}
    {449614800 14400 1 MSD}
    {465346800 10800 0 MSK}
    {481071600 14400 1 MSD}
    {496796400 10800 0 MSK}
    {512521200 14400 1 MSD}
    {528246000 10800 0 MSK}
    {543970800 14400 1 MSD}
    {559695600 10800 0 MSK}
    {575420400 14400 1 MSD}
    {591145200 10800 0 MSK}
    {606870000 14400 1 MSD}
    {622594800 10800 0 MSK}
    {638319600 14400 1 MSD}
    {646786800 10800 1 EEST}
    {686102400 7200 0 EET}
    {701827200 10800 1 EEST}
    {717552000 7200 0 EET}
    {733276800 10800 1 EEST}
    {749001600 7200 0 EET}
    {764726400 10800 1 EEST}
    {780451200 7200 0 EET}
    {796176000 10800 1 EEST}
    {811900800 7200 0 EET}
    {828230400 10800 1 EEST}
    {831938400 10800 0 EEST}
    {846378000 7200 0 EET}
    {859683600 10800 1 EEST}
    {877827600 7200 0 EET}
    {891133200 10800 1 EEST}
    {909277200 7200 0 EET}
    {922582800 10800 1 EEST}
    {941331600 7200 0 EET}
    {954032400 10800 1 EEST}
    {972781200 7200 0 EET}
    {985482000 10800 1 EEST}
    {1004230800 7200 0 EET}
    {1017536400 10800 1 EEST}
    {1035680400 7200 0 EET}
    {1048986000 10800 1 EEST}
    {1067130000 7200 0 EET}
    {1080435600 10800 1 EEST}
    {1099184400 7200 0 EET}
    {1111885200 10800 1 EEST}
    {1130634000 7200 0 EET}
    {1143334800 10800 1 EEST}
    {1162083600 7200 0 EET}
    {1174784400 10800 1 EEST}
    {1193533200 7200 0 EET}
    {1206838800 10800 1 EEST}
    {1224982800 7200 0 EET}
    {1238288400 10800 1 EEST}
    {1256432400 7200 0 EET}
    {1269738000 10800 1 EEST}
    {1288486800 7200 0 EET}
    {1301187600 10800 1 EEST}
    {1319936400 7200 0 EET}
    {1332637200 10800 1 EEST}
    {1351386000 7200 0 EET}
    {1364691600 10800 1 EEST}
    {1382835600 7200 0 EET}
    {1396141200 10800 1 EEST}
    {1414285200 7200 0 EET}
    {1427590800 10800 1 EEST}
    {1445734800 7200 0 EET}
    {1459040400 10800 1 EEST}
    {1477789200 7200 0 EET}
    {1490490000 10800 1 EEST}
    {1509238800 7200 0 EET}
    {1521939600 10800 1 EEST}
    {1540688400 7200 0 EET}
    {1553994000 10800 1 EEST}
    {1572138000 7200 0 EET}
    {1585443600 10800 1 EEST}
    {1603587600 7200 0 EET}
    {1616893200 10800 1 EEST}
    {1635642000 7200 0 EET}
    {1648342800 10800 1 EEST}
    {1667091600 7200 0 EET}
    {1679792400 10800 1 EEST}
    {1698541200 7200 0 EET}
    {1711846800 10800 1 EEST}
    {1729990800 7200 0 EET}
    {1743296400 10800 1 EEST}
    {1761440400 7200 0 EET}
    {1774746000 10800 1 EEST}
    {1792890000 7200 0 EET}
    {1806195600 10800 1 EEST}
    {1824944400 7200 0 EET}
    {1837645200 10800 1 EEST}
    {1856394000 7200 0 EET}
    {1869094800 10800 1 EEST}
    {1887843600 7200 0 EET}
    {1901149200 10800 1 EEST}
    {1919293200 7200 0 EET}
    {1932598800 10800 1 EEST}
    {1950742800 7200 0 EET}
    {1964048400 10800 1 EEST}
    {1982797200 7200 0 EET}
    {1995498000 10800 1 EEST}
    {2014246800 7200 0 EET}
    {2026947600 10800 1 EEST}
    {2045696400 7200 0 EET}
    {2058397200 10800 1 EEST}
    {2077146000 7200 0 EET}
    {2090451600 10800 1 EEST}
    {2108595600 7200 0 EET}
    {2121901200 10800 1 EEST}
    {2140045200 7200 0 EET}
    {2153350800 10800 1 EEST}
    {2172099600 7200 0 EET}
    {2184800400 10800 1 EEST}
    {2203549200 7200 0 EET}
    {2216250000 10800 1 EEST}
    {2234998800 7200 0 EET}
    {2248304400 10800 1 EEST}
    {2266448400 7200 0 EET}
    {2279754000 10800 1 EEST}
    {2297898000 7200 0 EET}
    {2311203600 10800 1 EEST}
    {2329347600 7200 0 EET}
    {2342653200 10800 1 EEST}
    {2361402000 7200 0 EET}
    {2374102800 10800 1 EEST}
    {2392851600 7200 0 EET}
    {2405552400 10800 1 EEST}
    {2424301200 7200 0 EET}
    {2437606800 10800 1 EEST}
    {2455750800 7200 0 EET}
    {2469056400 10800 1 EEST}
    {2487200400 7200 0 EET}
    {2500506000 10800 1 EEST}
    {2519254800 7200 0 EET}
    {2531955600 10800 1 EEST}
    {2550704400 7200 0 EET}
    {2563405200 10800 1 EEST}
    {2582154000 7200 0 EET}
    {2595459600 10800 1 EEST}
    {2613603600 7200 0 EET}
    {2626909200 10800 1 EEST}
    {2645053200 7200 0 EET}
    {2658358800 10800 1 EEST}
    {2676502800 7200 0 EET}
    {2689808400 10800 1 EEST}
    {2708557200 7200 0 EET}
    {2721258000 10800 1 EEST}
    {2740006800 7200 0 EET}
    {2752707600 10800 1 EEST}
    {2771456400 7200 0 EET}
    {2784762000 10800 1 EEST}
    {2802906000 7200 0 EET}
    {2816211600 10800 1 EEST}
    {2834355600 7200 0 EET}
    {2847661200 10800 1 EEST}
    {2866410000 7200 0 EET}
    {2879110800 10800 1 EEST}
    {2897859600 7200 0 EET}
    {2910560400 10800 1 EEST}
    {2929309200 7200 0 EET}
    {2942010000 10800 1 EEST}
    {2960758800 7200 0 EET}
    {2974064400 10800 1 EEST}
    {2992208400 7200 0 EET}
    {3005514000 10800 1 EEST}
    {3023658000 7200 0 EET}
    {3036963600 10800 1 EEST}
    {3055712400 7200 0 EET}
    {3068413200 10800 1 EEST}
    {3087162000 7200 0 EET}
    {3099862800 10800 1 EEST}
    {3118611600 7200 0 EET}
    {3131917200 10800 1 EEST}
    {3150061200 7200 0 EET}
    {3163366800 10800 1 EEST}
    {3181510800 7200 0 EET}
    {3194816400 10800 1 EEST}
    {3212960400 7200 0 EET}
    {3226266000 10800 1 EEST}
    {3245014800 7200 0 EET}
    {3257715600 10800 1 EEST}
    {3276464400 7200 0 EET}
    {3289165200 10800 1 EEST}
    {3307914000 7200 0 EET}
    {3321219600 10800 1 EEST}
    {3339363600 7200 0 EET}
    {3352669200 10800 1 EEST}
    {3370813200 7200 0 EET}
    {3384118800 10800 1 EEST}
    {3402867600 7200 0 EET}
    {3415568400 10800 1 EEST}
    {3434317200 7200 0 EET}
    {3447018000 10800 1 EEST}
    {3465766800 7200 0 EET}
    {3479072400 10800 1 EEST}
    {3497216400 7200 0 EET}
    {3510522000 10800 1 EEST}
    {3528666000 7200 0 EET}
    {3541971600 10800 1 EEST}
    {3560115600 7200 0 EET}
    {3573421200 10800 1 EEST}
    {3592170000 7200 0 EET}
    {3604870800 10800 1 EEST}
    {3623619600 7200 0 EET}
    {3636320400 10800 1 EEST}
    {3655069200 7200 0 EET}
    {3668374800 10800 1 EEST}
    {3686518800 7200 0 EET}
    {3699824400 10800 1 EEST}
    {3717968400 7200 0 EET}
    {3731274000 10800 1 EEST}
    {3750022800 7200 0 EET}
    {3762723600 10800 1 EEST}
    {3781472400 7200 0 EET}
    {3794173200 10800 1 EEST}
    {3812922000 7200 0 EET}
    {3825622800 10800 1 EEST}
    {3844371600 7200 0 EET}
    {3857677200 10800 1 EEST}
    {3875821200 7200 0 EET}
    {3889126800 10800 1 EEST}
    {3907270800 7200 0 EET}
    {3920576400 10800 1 EEST}
    {3939325200 7200 0 EET}
    {3952026000 10800 1 EEST}
    {3970774800 7200 0 EET}
    {3983475600 10800 1 EEST}
    {4002224400 7200 0 EET}
    {4015530000 10800 1 EEST}
    {4033674000 7200 0 EET}
    {4046979600 10800 1 EEST}
    {4065123600 7200 0 EET}
    {4078429200 10800 1 EEST}
    {4096573200 7200 0 EET}
}

Changes to library/tzdata/Europe/Lisbon.

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
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








-
+

-
+

-
+

-
+

-
+


-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Lisbon) {
    {-9223372036854775808 -2205 0 LMT}
    {-2713908195 -2205 0 LMT}
    {-1830384000 0 0 WET}
    {-1689555600 3600 1 WEST}
    {-1677801600 0 0 WET}
    {-1667437200 3600 1 WEST}
    {-1667433600 3600 1 WEST}
    {-1647738000 0 0 WET}
    {-1635814800 3600 1 WEST}
    {-1635897600 3600 1 WEST}
    {-1616202000 0 0 WET}
    {-1604365200 3600 1 WEST}
    {-1604361600 3600 1 WEST}
    {-1584666000 0 0 WET}
    {-1572742800 3600 1 WEST}
    {-1572739200 3600 1 WEST}
    {-1553043600 0 0 WET}
    {-1541206800 3600 1 WEST}
    {-1541203200 3600 1 WEST}
    {-1521507600 0 0 WET}
    {-1442451600 3600 1 WEST}
    {-1426813200 0 0 WET}
    {-1427677200 0 0 WET}
    {-1379293200 3600 1 WEST}
    {-1364778000 0 0 WET}
    {-1348448400 3600 1 WEST}
    {-1333328400 0 0 WET}
    {-1316394000 3600 1 WEST}
    {-1301274000 0 0 WET}
    {-1284339600 3600 1 WEST}
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53







-
+







    {-1033347600 3600 1 WEST}
    {-1017622800 0 0 WET}
    {-1002502800 3600 1 WEST}
    {-986173200 0 0 WET}
    {-969238800 3600 1 WEST}
    {-950490000 0 0 WET}
    {-942022800 3600 1 WEST}
    {-922669200 0 0 WET}
    {-922496400 0 0 WET}
    {-906944400 3600 1 WEST}
    {-891133200 0 0 WET}
    {-877309200 3600 1 WEST}
    {-873684000 7200 1 WEMT}
    {-864007200 3600 1 WEST}
    {-857955600 0 0 WET}
    {-845859600 3600 1 WEST}
66
67
68
69
70
71
72


73
74
75
76
77
78
79
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81







+
+







    {-733366800 0 0 WET}
    {-717631200 3600 1 WEST}
    {-701906400 0 0 WET}
    {-686181600 3600 1 WEST}
    {-670456800 0 0 WET}
    {-654732000 3600 1 WEST}
    {-639007200 0 0 WET}
    {-623282400 3600 1 WEST}
    {-607557600 0 0 WET}
    {-591832800 3600 1 WEST}
    {-575503200 0 0 WET}
    {-559778400 3600 1 WEST}
    {-544053600 0 0 WET}
    {-528328800 3600 1 WEST}
    {-512604000 0 0 WET}
    {-496879200 3600 1 WEST}
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
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







-
+
+

+


-
-
-
+
+
+

-
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+







    {-228348000 0 0 WET}
    {-212623200 3600 1 WEST}
    {-196898400 0 0 WET}
    {-181173600 3600 1 WEST}
    {-165448800 0 0 WET}
    {-149724000 3600 1 WEST}
    {-133999200 0 0 WET}
    {-118274400 3600 0 CET}
    {-118274400 3600 1 WEST}
    {-102549600 3600 0 CET}
    {212544000 0 0 WET}
    {212547600 0 0 WET}
    {228268800 3600 1 WEST}
    {243993600 0 0 WET}
    {260323200 3600 1 WEST}
    {276048000 0 0 WET}
    {291772800 3600 1 WEST}
    {260326800 3600 1 WEST}
    {276051600 0 0 WET}
    {291776400 3600 1 WEST}
    {307501200 0 0 WET}
    {323222400 3600 1 WEST}
    {323830800 3600 1 WEST}
    {338950800 0 0 WET}
    {354675600 3600 1 WEST}
    {370400400 0 0 WET}
    {386125200 3600 1 WEST}
    {401850000 0 0 WET}
    {417578400 3600 1 WEST}
    {433299600 0 0 WET}
    {449024400 3600 1 WEST}
    {465354000 0 0 WET}
    {481078800 3600 1 WEST}
    {496803600 0 0 WET}
    {354672000 3600 1 WEST}
    {370396800 0 0 WET}
    {386121600 3600 1 WEST}
    {401846400 0 0 WET}
    {417571200 3600 1 WEST}
    {433296000 0 0 WET}
    {449020800 3600 1 WEST}
    {465350400 0 0 WET}
    {481075200 3600 1 WEST}
    {496800000 0 0 WET}
    {504921600 0 0 WET}
    {512528400 3600 1 WEST}
    {528253200 0 0 WET}
    {543978000 3600 1 WEST}
    {559702800 0 0 WET}
    {575427600 3600 1 WEST}
    {591152400 0 0 WET}
    {606877200 3600 1 WEST}

Changes to library/tzdata/Europe/Luxembourg.

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
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

1

2




























































































































































3


























































































































































4
5

-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

+
# created by tools/tclZIC.tcl - do not edit

if {![info exists TZData(Europe/Brussels)]} {
set TZData(:Europe/Luxembourg) {
    {-9223372036854775808 1476 0 LMT}
    {-2069713476 3600 0 CET}
    {-1692496800 7200 1 CEST}
    {-1680483600 3600 0 CET}
    {-1662343200 7200 1 CEST}
    {-1650157200 3600 0 CET}
    {-1632006000 7200 1 CEST}
    {-1618700400 3600 0 CET}
    {-1612659600 0 0 WET}
    {-1604278800 3600 1 WEST}
    {-1585519200 0 0 WET}
    {-1574038800 3600 1 WEST}
    {-1552258800 0 0 WET}
    {-1539997200 3600 1 WEST}
    {-1520550000 0 0 WET}
    {-1507510800 3600 1 WEST}
    {-1490572800 0 0 WET}
    {-1473642000 3600 1 WEST}
    {-1459119600 0 0 WET}
    {-1444006800 3600 1 WEST}
    {-1427673600 0 0 WET}
    {-1411866000 3600 1 WEST}
    {-1396224000 0 0 WET}
    {-1379293200 3600 1 WEST}
    {-1364774400 0 0 WET}
    {-1348448400 3600 1 WEST}
    {-1333324800 0 0 WET}
    {-1316394000 3600 1 WEST}
    {-1301270400 0 0 WET}
    {-1284339600 3600 1 WEST}
    {-1269813600 0 0 WET}
    {-1253484000 3600 1 WEST}
    {-1238364000 0 0 WET}
    {-1221429600 3600 1 WEST}
    {-1206914400 0 0 WET}
    {-1191189600 3600 1 WEST}
    {-1175464800 0 0 WET}
    {-1160344800 3600 1 WEST}
    {-1143410400 0 0 WET}
    {-1127685600 3600 1 WEST}
    {-1111960800 0 0 WET}
    {-1096840800 3600 1 WEST}
    {-1080511200 0 0 WET}
    {-1063576800 3600 1 WEST}
    {-1049061600 0 0 WET}
    {-1033336800 3600 1 WEST}
    {-1017612000 0 0 WET}
    {-1002492000 3600 1 WEST}
    {-986162400 0 0 WET}
    {-969228000 3600 1 WEST}
    {-950479200 0 0 WET}
    {-942012000 3600 1 WEST}
    {-935186400 7200 0 WEST}
    {-857257200 3600 0 WET}
    {-844556400 7200 1 WEST}
    {-828226800 3600 0 WET}
    {-812502000 7200 1 WEST}
    {-797983200 3600 0 CET}
    {-781052400 7200 1 CEST}
    {-766623600 3600 0 CET}
    {-745455600 7200 1 CEST}
    {-733273200 3600 0 CET}
    {220921200 3600 0 CET}
    {228877200 7200 1 CEST}
    {243997200 3600 0 CET}
    {260326800 7200 1 CEST}
    {276051600 3600 0 CET}
    {291776400 7200 1 CEST}
    {307501200 3600 0 CET}
    {323830800 7200 1 CEST}
    {338950800 3600 0 CET}
    {354675600 7200 1 CEST}
    {370400400 3600 0 CET}
    {386125200 7200 1 CEST}
    {401850000 3600 0 CET}
    {417574800 7200 1 CEST}
    {433299600 3600 0 CET}
    {449024400 7200 1 CEST}
    {465354000 3600 0 CET}
    {481078800 7200 1 CEST}
    {496803600 3600 0 CET}
    {512528400 7200 1 CEST}
    {528253200 3600 0 CET}
    {543978000 7200 1 CEST}
    {559702800 3600 0 CET}
    {575427600 7200 1 CEST}
    {591152400 3600 0 CET}
    {606877200 7200 1 CEST}
    {622602000 3600 0 CET}
    {638326800 7200 1 CEST}
    {654656400 3600 0 CET}
    {670381200 7200 1 CEST}
    {686106000 3600 0 CET}
    {701830800 7200 1 CEST}
    {717555600 3600 0 CET}
    {733280400 7200 1 CEST}
    {749005200 3600 0 CET}
    {764730000 7200 1 CEST}
    {780454800 3600 0 CET}
    {796179600 7200 1 CEST}
    {811904400 3600 0 CET}
    {828234000 7200 1 CEST}
    {846378000 3600 0 CET}
    {859683600 7200 1 CEST}
    {877827600 3600 0 CET}
    {891133200 7200 1 CEST}
    {909277200 3600 0 CET}
    {922582800 7200 1 CEST}
    {941331600 3600 0 CET}
    {954032400 7200 1 CEST}
    {972781200 3600 0 CET}
    {985482000 7200 1 CEST}
    {1004230800 3600 0 CET}
    {1017536400 7200 1 CEST}
    {1035680400 3600 0 CET}
    {1048986000 7200 1 CEST}
    {1067130000 3600 0 CET}
    {1080435600 7200 1 CEST}
    {1099184400 3600 0 CET}
    {1111885200 7200 1 CEST}
    {1130634000 3600 0 CET}
    {1143334800 7200 1 CEST}
    {1162083600 3600 0 CET}
    {1174784400 7200 1 CEST}
    {1193533200 3600 0 CET}
    {1206838800 7200 1 CEST}
    {1224982800 3600 0 CET}
    {1238288400 7200 1 CEST}
    {1256432400 3600 0 CET}
    {1269738000 7200 1 CEST}
    {1288486800 3600 0 CET}
    {1301187600 7200 1 CEST}
    {1319936400 3600 0 CET}
    {1332637200 7200 1 CEST}
    {1351386000 3600 0 CET}
    {1364691600 7200 1 CEST}
    {1382835600 3600 0 CET}
    {1396141200 7200 1 CEST}
    {1414285200 3600 0 CET}
    {1427590800 7200 1 CEST}
    {1445734800 3600 0 CET}
    {1459040400 7200 1 CEST}
    {1477789200 3600 0 CET}
    {1490490000 7200 1 CEST}
    {1509238800 3600 0 CET}
    {1521939600 7200 1 CEST}
    {1540688400 3600 0 CET}
    {1553994000 7200 1 CEST}
    {1572138000 3600 0 CET}
    {1585443600 7200 1 CEST}
    {1603587600 3600 0 CET}
    {1616893200 7200 1 CEST}
    {1635642000 3600 0 CET}
    {1648342800 7200 1 CEST}
    {1667091600 3600 0 CET}
    LoadTimeZoneFile Europe/Brussels
    {1679792400 7200 1 CEST}
    {1698541200 3600 0 CET}
    {1711846800 7200 1 CEST}
    {1729990800 3600 0 CET}
    {1743296400 7200 1 CEST}
    {1761440400 3600 0 CET}
    {1774746000 7200 1 CEST}
    {1792890000 3600 0 CET}
    {1806195600 7200 1 CEST}
    {1824944400 3600 0 CET}
    {1837645200 7200 1 CEST}
    {1856394000 3600 0 CET}
    {1869094800 7200 1 CEST}
    {1887843600 3600 0 CET}
    {1901149200 7200 1 CEST}
    {1919293200 3600 0 CET}
    {1932598800 7200 1 CEST}
    {1950742800 3600 0 CET}
    {1964048400 7200 1 CEST}
    {1982797200 3600 0 CET}
    {1995498000 7200 1 CEST}
    {2014246800 3600 0 CET}
    {2026947600 7200 1 CEST}
    {2045696400 3600 0 CET}
    {2058397200 7200 1 CEST}
    {2077146000 3600 0 CET}
    {2090451600 7200 1 CEST}
    {2108595600 3600 0 CET}
    {2121901200 7200 1 CEST}
    {2140045200 3600 0 CET}
    {2153350800 7200 1 CEST}
    {2172099600 3600 0 CET}
    {2184800400 7200 1 CEST}
    {2203549200 3600 0 CET}
    {2216250000 7200 1 CEST}
    {2234998800 3600 0 CET}
    {2248304400 7200 1 CEST}
    {2266448400 3600 0 CET}
    {2279754000 7200 1 CEST}
    {2297898000 3600 0 CET}
    {2311203600 7200 1 CEST}
    {2329347600 3600 0 CET}
    {2342653200 7200 1 CEST}
    {2361402000 3600 0 CET}
    {2374102800 7200 1 CEST}
    {2392851600 3600 0 CET}
    {2405552400 7200 1 CEST}
    {2424301200 3600 0 CET}
    {2437606800 7200 1 CEST}
    {2455750800 3600 0 CET}
    {2469056400 7200 1 CEST}
    {2487200400 3600 0 CET}
    {2500506000 7200 1 CEST}
    {2519254800 3600 0 CET}
    {2531955600 7200 1 CEST}
    {2550704400 3600 0 CET}
    {2563405200 7200 1 CEST}
    {2582154000 3600 0 CET}
    {2595459600 7200 1 CEST}
    {2613603600 3600 0 CET}
    {2626909200 7200 1 CEST}
    {2645053200 3600 0 CET}
    {2658358800 7200 1 CEST}
    {2676502800 3600 0 CET}
    {2689808400 7200 1 CEST}
    {2708557200 3600 0 CET}
    {2721258000 7200 1 CEST}
    {2740006800 3600 0 CET}
    {2752707600 7200 1 CEST}
    {2771456400 3600 0 CET}
    {2784762000 7200 1 CEST}
    {2802906000 3600 0 CET}
    {2816211600 7200 1 CEST}
    {2834355600 3600 0 CET}
    {2847661200 7200 1 CEST}
    {2866410000 3600 0 CET}
    {2879110800 7200 1 CEST}
    {2897859600 3600 0 CET}
    {2910560400 7200 1 CEST}
    {2929309200 3600 0 CET}
    {2942010000 7200 1 CEST}
    {2960758800 3600 0 CET}
    {2974064400 7200 1 CEST}
    {2992208400 3600 0 CET}
    {3005514000 7200 1 CEST}
    {3023658000 3600 0 CET}
    {3036963600 7200 1 CEST}
    {3055712400 3600 0 CET}
    {3068413200 7200 1 CEST}
    {3087162000 3600 0 CET}
    {3099862800 7200 1 CEST}
    {3118611600 3600 0 CET}
    {3131917200 7200 1 CEST}
    {3150061200 3600 0 CET}
    {3163366800 7200 1 CEST}
    {3181510800 3600 0 CET}
    {3194816400 7200 1 CEST}
    {3212960400 3600 0 CET}
    {3226266000 7200 1 CEST}
    {3245014800 3600 0 CET}
    {3257715600 7200 1 CEST}
    {3276464400 3600 0 CET}
    {3289165200 7200 1 CEST}
    {3307914000 3600 0 CET}
    {3321219600 7200 1 CEST}
    {3339363600 3600 0 CET}
    {3352669200 7200 1 CEST}
    {3370813200 3600 0 CET}
    {3384118800 7200 1 CEST}
    {3402867600 3600 0 CET}
    {3415568400 7200 1 CEST}
    {3434317200 3600 0 CET}
    {3447018000 7200 1 CEST}
    {3465766800 3600 0 CET}
    {3479072400 7200 1 CEST}
    {3497216400 3600 0 CET}
    {3510522000 7200 1 CEST}
    {3528666000 3600 0 CET}
    {3541971600 7200 1 CEST}
    {3560115600 3600 0 CET}
    {3573421200 7200 1 CEST}
    {3592170000 3600 0 CET}
    {3604870800 7200 1 CEST}
    {3623619600 3600 0 CET}
    {3636320400 7200 1 CEST}
    {3655069200 3600 0 CET}
    {3668374800 7200 1 CEST}
    {3686518800 3600 0 CET}
    {3699824400 7200 1 CEST}
    {3717968400 3600 0 CET}
    {3731274000 7200 1 CEST}
    {3750022800 3600 0 CET}
    {3762723600 7200 1 CEST}
    {3781472400 3600 0 CET}
    {3794173200 7200 1 CEST}
    {3812922000 3600 0 CET}
    {3825622800 7200 1 CEST}
    {3844371600 3600 0 CET}
    {3857677200 7200 1 CEST}
    {3875821200 3600 0 CET}
    {3889126800 7200 1 CEST}
    {3907270800 3600 0 CET}
    {3920576400 7200 1 CEST}
    {3939325200 3600 0 CET}
    {3952026000 7200 1 CEST}
    {3970774800 3600 0 CET}
    {3983475600 7200 1 CEST}
    {4002224400 3600 0 CET}
    {4015530000 7200 1 CEST}
    {4033674000 3600 0 CET}
    {4046979600 7200 1 CEST}
    {4065123600 3600 0 CET}
    {4078429200 7200 1 CEST}
    {4096573200 3600 0 CET}
}
set TZData(:Europe/Luxembourg) $TZData(:Europe/Brussels)

Changes to library/tzdata/Europe/Minsk.

67
68
69
70
71
72
73
74

75
67
68
69
70
71
72
73

74
75







-
+

    {1193529600 7200 0 EET}
    {1206835200 10800 1 EEST}
    {1224979200 7200 0 EET}
    {1238284800 10800 1 EEST}
    {1256428800 7200 0 EET}
    {1269734400 10800 1 EEST}
    {1288483200 7200 0 EET}
    {1301184000 10800 0 +03}
    {1301184000 10800 0 +0300}
}

Changes to library/tzdata/Europe/Monaco.

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
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

1

2





























































































































































3



























































































































































4
5

-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

+
# created by tools/tclZIC.tcl - do not edit

if {![info exists TZData(Europe/Paris)]} {
set TZData(:Europe/Monaco) {
    {-9223372036854775808 1772 0 LMT}
    {-2448318572 561 0 PMT}
    {-1854403761 0 0 WET}
    {-1689814800 3600 1 WEST}
    {-1680397200 0 0 WET}
    {-1665363600 3600 1 WEST}
    {-1648342800 0 0 WET}
    {-1635123600 3600 1 WEST}
    {-1616893200 0 0 WET}
    {-1604278800 3600 1 WEST}
    {-1585443600 0 0 WET}
    {-1574038800 3600 1 WEST}
    {-1552266000 0 0 WET}
    {-1539997200 3600 1 WEST}
    {-1520557200 0 0 WET}
    {-1507510800 3600 1 WEST}
    {-1490576400 0 0 WET}
    {-1470618000 3600 1 WEST}
    {-1459126800 0 0 WET}
    {-1444006800 3600 1 WEST}
    {-1427677200 0 0 WET}
    {-1411952400 3600 1 WEST}
    {-1396227600 0 0 WET}
    {-1379293200 3600 1 WEST}
    {-1364778000 0 0 WET}
    {-1348448400 3600 1 WEST}
    {-1333328400 0 0 WET}
    {-1316394000 3600 1 WEST}
    {-1301274000 0 0 WET}
    {-1284339600 3600 1 WEST}
    {-1269824400 0 0 WET}
    {-1253494800 3600 1 WEST}
    {-1238374800 0 0 WET}
    {-1221440400 3600 1 WEST}
    {-1206925200 0 0 WET}
    {-1191200400 3600 1 WEST}
    {-1175475600 0 0 WET}
    {-1160355600 3600 1 WEST}
    {-1143421200 0 0 WET}
    {-1127696400 3600 1 WEST}
    {-1111971600 0 0 WET}
    {-1096851600 3600 1 WEST}
    {-1080522000 0 0 WET}
    {-1063587600 3600 1 WEST}
    {-1049072400 0 0 WET}
    {-1033347600 3600 1 WEST}
    {-1017622800 0 0 WET}
    {-1002502800 3600 1 WEST}
    {-986173200 0 0 WET}
    {-969238800 3600 1 WEST}
    {-950490000 0 0 WET}
    {-942012000 3600 1 WEST}
    {-904438800 7200 1 WEMT}
    {-891136800 3600 1 WEST}
    {-877827600 7200 1 WEMT}
    {-857257200 3600 1 WEST}
    {-844556400 7200 1 WEMT}
    {-828226800 3600 1 WEST}
    {-812502000 7200 1 WEMT}
    {-796266000 3600 1 WEST}
    {-781052400 7200 1 WEMT}
    {-766616400 3600 0 CET}
    {196819200 7200 1 CEST}
    {212540400 3600 0 CET}
    {220921200 3600 0 CET}
    {228877200 7200 1 CEST}
    {243997200 3600 0 CET}
    {260326800 7200 1 CEST}
    {276051600 3600 0 CET}
    {291776400 7200 1 CEST}
    {307501200 3600 0 CET}
    {323830800 7200 1 CEST}
    {338950800 3600 0 CET}
    {354675600 7200 1 CEST}
    {370400400 3600 0 CET}
    {386125200 7200 1 CEST}
    {401850000 3600 0 CET}
    {417574800 7200 1 CEST}
    {433299600 3600 0 CET}
    {449024400 7200 1 CEST}
    {465354000 3600 0 CET}
    {481078800 7200 1 CEST}
    {496803600 3600 0 CET}
    {512528400 7200 1 CEST}
    {528253200 3600 0 CET}
    {543978000 7200 1 CEST}
    {559702800 3600 0 CET}
    {575427600 7200 1 CEST}
    {591152400 3600 0 CET}
    {606877200 7200 1 CEST}
    {622602000 3600 0 CET}
    {638326800 7200 1 CEST}
    {654656400 3600 0 CET}
    {670381200 7200 1 CEST}
    {686106000 3600 0 CET}
    {701830800 7200 1 CEST}
    {717555600 3600 0 CET}
    {733280400 7200 1 CEST}
    {749005200 3600 0 CET}
    {764730000 7200 1 CEST}
    {780454800 3600 0 CET}
    {796179600 7200 1 CEST}
    {811904400 3600 0 CET}
    {828234000 7200 1 CEST}
    {846378000 3600 0 CET}
    {859683600 7200 1 CEST}
    {877827600 3600 0 CET}
    {891133200 7200 1 CEST}
    {909277200 3600 0 CET}
    {922582800 7200 1 CEST}
    {941331600 3600 0 CET}
    {954032400 7200 1 CEST}
    {972781200 3600 0 CET}
    {985482000 7200 1 CEST}
    {1004230800 3600 0 CET}
    {1017536400 7200 1 CEST}
    {1035680400 3600 0 CET}
    {1048986000 7200 1 CEST}
    {1067130000 3600 0 CET}
    {1080435600 7200 1 CEST}
    {1099184400 3600 0 CET}
    {1111885200 7200 1 CEST}
    {1130634000 3600 0 CET}
    {1143334800 7200 1 CEST}
    {1162083600 3600 0 CET}
    {1174784400 7200 1 CEST}
    {1193533200 3600 0 CET}
    {1206838800 7200 1 CEST}
    {1224982800 3600 0 CET}
    {1238288400 7200 1 CEST}
    {1256432400 3600 0 CET}
    {1269738000 7200 1 CEST}
    {1288486800 3600 0 CET}
    {1301187600 7200 1 CEST}
    {1319936400 3600 0 CET}
    {1332637200 7200 1 CEST}
    {1351386000 3600 0 CET}
    {1364691600 7200 1 CEST}
    {1382835600 3600 0 CET}
    {1396141200 7200 1 CEST}
    {1414285200 3600 0 CET}
    {1427590800 7200 1 CEST}
    {1445734800 3600 0 CET}
    {1459040400 7200 1 CEST}
    {1477789200 3600 0 CET}
    {1490490000 7200 1 CEST}
    {1509238800 3600 0 CET}
    {1521939600 7200 1 CEST}
    {1540688400 3600 0 CET}
    {1553994000 7200 1 CEST}
    {1572138000 3600 0 CET}
    {1585443600 7200 1 CEST}
    {1603587600 3600 0 CET}
    {1616893200 7200 1 CEST}
    {1635642000 3600 0 CET}
    {1648342800 7200 1 CEST}
    LoadTimeZoneFile Europe/Paris
    {1667091600 3600 0 CET}
    {1679792400 7200 1 CEST}
    {1698541200 3600 0 CET}
    {1711846800 7200 1 CEST}
    {1729990800 3600 0 CET}
    {1743296400 7200 1 CEST}
    {1761440400 3600 0 CET}
    {1774746000 7200 1 CEST}
    {1792890000 3600 0 CET}
    {1806195600 7200 1 CEST}
    {1824944400 3600 0 CET}
    {1837645200 7200 1 CEST}
    {1856394000 3600 0 CET}
    {1869094800 7200 1 CEST}
    {1887843600 3600 0 CET}
    {1901149200 7200 1 CEST}
    {1919293200 3600 0 CET}
    {1932598800 7200 1 CEST}
    {1950742800 3600 0 CET}
    {1964048400 7200 1 CEST}
    {1982797200 3600 0 CET}
    {1995498000 7200 1 CEST}
    {2014246800 3600 0 CET}
    {2026947600 7200 1 CEST}
    {2045696400 3600 0 CET}
    {2058397200 7200 1 CEST}
    {2077146000 3600 0 CET}
    {2090451600 7200 1 CEST}
    {2108595600 3600 0 CET}
    {2121901200 7200 1 CEST}
    {2140045200 3600 0 CET}
    {2153350800 7200 1 CEST}
    {2172099600 3600 0 CET}
    {2184800400 7200 1 CEST}
    {2203549200 3600 0 CET}
    {2216250000 7200 1 CEST}
    {2234998800 3600 0 CET}
    {2248304400 7200 1 CEST}
    {2266448400 3600 0 CET}
    {2279754000 7200 1 CEST}
    {2297898000 3600 0 CET}
    {2311203600 7200 1 CEST}
    {2329347600 3600 0 CET}
    {2342653200 7200 1 CEST}
    {2361402000 3600 0 CET}
    {2374102800 7200 1 CEST}
    {2392851600 3600 0 CET}
    {2405552400 7200 1 CEST}
    {2424301200 3600 0 CET}
    {2437606800 7200 1 CEST}
    {2455750800 3600 0 CET}
    {2469056400 7200 1 CEST}
    {2487200400 3600 0 CET}
    {2500506000 7200 1 CEST}
    {2519254800 3600 0 CET}
    {2531955600 7200 1 CEST}
    {2550704400 3600 0 CET}
    {2563405200 7200 1 CEST}
    {2582154000 3600 0 CET}
    {2595459600 7200 1 CEST}
    {2613603600 3600 0 CET}
    {2626909200 7200 1 CEST}
    {2645053200 3600 0 CET}
    {2658358800 7200 1 CEST}
    {2676502800 3600 0 CET}
    {2689808400 7200 1 CEST}
    {2708557200 3600 0 CET}
    {2721258000 7200 1 CEST}
    {2740006800 3600 0 CET}
    {2752707600 7200 1 CEST}
    {2771456400 3600 0 CET}
    {2784762000 7200 1 CEST}
    {2802906000 3600 0 CET}
    {2816211600 7200 1 CEST}
    {2834355600 3600 0 CET}
    {2847661200 7200 1 CEST}
    {2866410000 3600 0 CET}
    {2879110800 7200 1 CEST}
    {2897859600 3600 0 CET}
    {2910560400 7200 1 CEST}
    {2929309200 3600 0 CET}
    {2942010000 7200 1 CEST}
    {2960758800 3600 0 CET}
    {2974064400 7200 1 CEST}
    {2992208400 3600 0 CET}
    {3005514000 7200 1 CEST}
    {3023658000 3600 0 CET}
    {3036963600 7200 1 CEST}
    {3055712400 3600 0 CET}
    {3068413200 7200 1 CEST}
    {3087162000 3600 0 CET}
    {3099862800 7200 1 CEST}
    {3118611600 3600 0 CET}
    {3131917200 7200 1 CEST}
    {3150061200 3600 0 CET}
    {3163366800 7200 1 CEST}
    {3181510800 3600 0 CET}
    {3194816400 7200 1 CEST}
    {3212960400 3600 0 CET}
    {3226266000 7200 1 CEST}
    {3245014800 3600 0 CET}
    {3257715600 7200 1 CEST}
    {3276464400 3600 0 CET}
    {3289165200 7200 1 CEST}
    {3307914000 3600 0 CET}
    {3321219600 7200 1 CEST}
    {3339363600 3600 0 CET}
    {3352669200 7200 1 CEST}
    {3370813200 3600 0 CET}
    {3384118800 7200 1 CEST}
    {3402867600 3600 0 CET}
    {3415568400 7200 1 CEST}
    {3434317200 3600 0 CET}
    {3447018000 7200 1 CEST}
    {3465766800 3600 0 CET}
    {3479072400 7200 1 CEST}
    {3497216400 3600 0 CET}
    {3510522000 7200 1 CEST}
    {3528666000 3600 0 CET}
    {3541971600 7200 1 CEST}
    {3560115600 3600 0 CET}
    {3573421200 7200 1 CEST}
    {3592170000 3600 0 CET}
    {3604870800 7200 1 CEST}
    {3623619600 3600 0 CET}
    {3636320400 7200 1 CEST}
    {3655069200 3600 0 CET}
    {3668374800 7200 1 CEST}
    {3686518800 3600 0 CET}
    {3699824400 7200 1 CEST}
    {3717968400 3600 0 CET}
    {3731274000 7200 1 CEST}
    {3750022800 3600 0 CET}
    {3762723600 7200 1 CEST}
    {3781472400 3600 0 CET}
    {3794173200 7200 1 CEST}
    {3812922000 3600 0 CET}
    {3825622800 7200 1 CEST}
    {3844371600 3600 0 CET}
    {3857677200 7200 1 CEST}
    {3875821200 3600 0 CET}
    {3889126800 7200 1 CEST}
    {3907270800 3600 0 CET}
    {3920576400 7200 1 CEST}
    {3939325200 3600 0 CET}
    {3952026000 7200 1 CEST}
    {3970774800 3600 0 CET}
    {3983475600 7200 1 CEST}
    {4002224400 3600 0 CET}
    {4015530000 7200 1 CEST}
    {4033674000 3600 0 CET}
    {4046979600 7200 1 CEST}
    {4065123600 3600 0 CET}
    {4078429200 7200 1 CEST}
    {4096573200 3600 0 CET}
}
set TZData(:Europe/Monaco) $TZData(:Europe/Paris)

Changes to library/tzdata/Europe/Oslo.

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
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
1
2
3


4
5













































































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Berlin)]} {
    LoadTimeZoneFile Europe/Berlin

set TZData(:Europe/Oslo) {
}
set TZData(:Europe/Oslo) $TZData(:Europe/Berlin)
    {-9223372036854775808 2580 0 LMT}
    {-2366757780 3600 0 CET}
    {-1691884800 7200 1 CEST}
    {-1680573600 3600 0 CET}
    {-927511200 7200 0 CEST}
    {-857257200 3600 0 CET}
    {-844556400 7200 1 CEST}
    {-828226800 3600 0 CET}
    {-812502000 7200 1 CEST}
    {-796777200 3600 0 CET}
    {-781052400 7200 0 CEST}
    {-765327600 3600 0 CET}
    {-340844400 7200 1 CEST}
    {-324514800 3600 0 CET}
    {-308790000 7200 1 CEST}
    {-293065200 3600 0 CET}
    {-277340400 7200 1 CEST}
    {-261615600 3600 0 CET}
    {-245890800 7200 1 CEST}
    {-230166000 3600 0 CET}
    {-214441200 7200 1 CEST}
    {-198716400 3600 0 CET}
    {-182991600 7200 1 CEST}
    {-166662000 3600 0 CET}
    {-147913200 7200 1 CEST}
    {-135212400 3600 0 CET}
    {315529200 3600 0 CET}
    {323830800 7200 1 CEST}
    {338950800 3600 0 CET}
    {354675600 7200 1 CEST}
    {370400400 3600 0 CET}
    {386125200 7200 1 CEST}
    {401850000 3600 0 CET}
    {417574800 7200 1 CEST}
    {433299600 3600 0 CET}
    {449024400 7200 1 CEST}
    {465354000 3600 0 CET}
    {481078800 7200 1 CEST}
    {496803600 3600 0 CET}
    {512528400 7200 1 CEST}
    {528253200 3600 0 CET}
    {543978000 7200 1 CEST}
    {559702800 3600 0 CET}
    {575427600 7200 1 CEST}
    {591152400 3600 0 CET}
    {606877200 7200 1 CEST}
    {622602000 3600 0 CET}
    {638326800 7200 1 CEST}
    {654656400 3600 0 CET}
    {670381200 7200 1 CEST}
    {686106000 3600 0 CET}
    {701830800 7200 1 CEST}
    {717555600 3600 0 CET}
    {733280400 7200 1 CEST}
    {749005200 3600 0 CET}
    {764730000 7200 1 CEST}
    {780454800 3600 0 CET}
    {796179600 7200 1 CEST}
    {811904400 3600 0 CET}
    {828234000 7200 1 CEST}
    {846378000 3600 0 CET}
    {859683600 7200 1 CEST}
    {877827600 3600 0 CET}
    {891133200 7200 1 CEST}
    {909277200 3600 0 CET}
    {922582800 7200 1 CEST}
    {941331600 3600 0 CET}
    {954032400 7200 1 CEST}
    {972781200 3600 0 CET}
    {985482000 7200 1 CEST}
    {1004230800 3600 0 CET}
    {1017536400 7200 1 CEST}
    {1035680400 3600 0 CET}
    {1048986000 7200 1 CEST}
    {1067130000 3600 0 CET}
    {1080435600 7200 1 CEST}
    {1099184400 3600 0 CET}
    {1111885200 7200 1 CEST}
    {1130634000 3600 0 CET}
    {1143334800 7200 1 CEST}
    {1162083600 3600 0 CET}
    {1174784400 7200 1 CEST}
    {1193533200 3600 0 CET}
    {1206838800 7200 1 CEST}
    {1224982800 3600 0 CET}
    {1238288400 7200 1 CEST}
    {1256432400 3600 0 CET}
    {1269738000 7200 1 CEST}
    {1288486800 3600 0 CET}
    {1301187600 7200 1 CEST}
    {1319936400 3600 0 CET}
    {1332637200 7200 1 CEST}
    {1351386000 3600 0 CET}
    {1364691600 7200 1 CEST}
    {1382835600 3600 0 CET}
    {1396141200 7200 1 CEST}
    {1414285200 3600 0 CET}
    {1427590800 7200 1 CEST}
    {1445734800 3600 0 CET}
    {1459040400 7200 1 CEST}
    {1477789200 3600 0 CET}
    {1490490000 7200 1 CEST}
    {1509238800 3600 0 CET}
    {1521939600 7200 1 CEST}
    {1540688400 3600 0 CET}
    {1553994000 7200 1 CEST}
    {1572138000 3600 0 CET}
    {1585443600 7200 1 CEST}
    {1603587600 3600 0 CET}
    {1616893200 7200 1 CEST}
    {1635642000 3600 0 CET}
    {1648342800 7200 1 CEST}
    {1667091600 3600 0 CET}
    {1679792400 7200 1 CEST}
    {1698541200 3600 0 CET}
    {1711846800 7200 1 CEST}
    {1729990800 3600 0 CET}
    {1743296400 7200 1 CEST}
    {1761440400 3600 0 CET}
    {1774746000 7200 1 CEST}
    {1792890000 3600 0 CET}
    {1806195600 7200 1 CEST}
    {1824944400 3600 0 CET}
    {1837645200 7200 1 CEST}
    {1856394000 3600 0 CET}
    {1869094800 7200 1 CEST}
    {1887843600 3600 0 CET}
    {1901149200 7200 1 CEST}
    {1919293200 3600 0 CET}
    {1932598800 7200 1 CEST}
    {1950742800 3600 0 CET}
    {1964048400 7200 1 CEST}
    {1982797200 3600 0 CET}
    {1995498000 7200 1 CEST}
    {2014246800 3600 0 CET}
    {2026947600 7200 1 CEST}
    {2045696400 3600 0 CET}
    {2058397200 7200 1 CEST}
    {2077146000 3600 0 CET}
    {2090451600 7200 1 CEST}
    {2108595600 3600 0 CET}
    {2121901200 7200 1 CEST}
    {2140045200 3600 0 CET}
    {2153350800 7200 1 CEST}
    {2172099600 3600 0 CET}
    {2184800400 7200 1 CEST}
    {2203549200 3600 0 CET}
    {2216250000 7200 1 CEST}
    {2234998800 3600 0 CET}
    {2248304400 7200 1 CEST}
    {2266448400 3600 0 CET}
    {2279754000 7200 1 CEST}
    {2297898000 3600 0 CET}
    {2311203600 7200 1 CEST}
    {2329347600 3600 0 CET}
    {2342653200 7200 1 CEST}
    {2361402000 3600 0 CET}
    {2374102800 7200 1 CEST}
    {2392851600 3600 0 CET}
    {2405552400 7200 1 CEST}
    {2424301200 3600 0 CET}
    {2437606800 7200 1 CEST}
    {2455750800 3600 0 CET}
    {2469056400 7200 1 CEST}
    {2487200400 3600 0 CET}
    {2500506000 7200 1 CEST}
    {2519254800 3600 0 CET}
    {2531955600 7200 1 CEST}
    {2550704400 3600 0 CET}
    {2563405200 7200 1 CEST}
    {2582154000 3600 0 CET}
    {2595459600 7200 1 CEST}
    {2613603600 3600 0 CET}
    {2626909200 7200 1 CEST}
    {2645053200 3600 0 CET}
    {2658358800 7200 1 CEST}
    {2676502800 3600 0 CET}
    {2689808400 7200 1 CEST}
    {2708557200 3600 0 CET}
    {2721258000 7200 1 CEST}
    {2740006800 3600 0 CET}
    {2752707600 7200 1 CEST}
    {2771456400 3600 0 CET}
    {2784762000 7200 1 CEST}
    {2802906000 3600 0 CET}
    {2816211600 7200 1 CEST}
    {2834355600 3600 0 CET}
    {2847661200 7200 1 CEST}
    {2866410000 3600 0 CET}
    {2879110800 7200 1 CEST}
    {2897859600 3600 0 CET}
    {2910560400 7200 1 CEST}
    {2929309200 3600 0 CET}
    {2942010000 7200 1 CEST}
    {2960758800 3600 0 CET}
    {2974064400 7200 1 CEST}
    {2992208400 3600 0 CET}
    {3005514000 7200 1 CEST}
    {3023658000 3600 0 CET}
    {3036963600 7200 1 CEST}
    {3055712400 3600 0 CET}
    {3068413200 7200 1 CEST}
    {3087162000 3600 0 CET}
    {3099862800 7200 1 CEST}
    {3118611600 3600 0 CET}
    {3131917200 7200 1 CEST}
    {3150061200 3600 0 CET}
    {3163366800 7200 1 CEST}
    {3181510800 3600 0 CET}
    {3194816400 7200 1 CEST}
    {3212960400 3600 0 CET}
    {3226266000 7200 1 CEST}
    {3245014800 3600 0 CET}
    {3257715600 7200 1 CEST}
    {3276464400 3600 0 CET}
    {3289165200 7200 1 CEST}
    {3307914000 3600 0 CET}
    {3321219600 7200 1 CEST}
    {3339363600 3600 0 CET}
    {3352669200 7200 1 CEST}
    {3370813200 3600 0 CET}
    {3384118800 7200 1 CEST}
    {3402867600 3600 0 CET}
    {3415568400 7200 1 CEST}
    {3434317200 3600 0 CET}
    {3447018000 7200 1 CEST}
    {3465766800 3600 0 CET}
    {3479072400 7200 1 CEST}
    {3497216400 3600 0 CET}
    {3510522000 7200 1 CEST}
    {3528666000 3600 0 CET}
    {3541971600 7200 1 CEST}
    {3560115600 3600 0 CET}
    {3573421200 7200 1 CEST}
    {3592170000 3600 0 CET}
    {3604870800 7200 1 CEST}
    {3623619600 3600 0 CET}
    {3636320400 7200 1 CEST}
    {3655069200 3600 0 CET}
    {3668374800 7200 1 CEST}
    {3686518800 3600 0 CET}
    {3699824400 7200 1 CEST}
    {3717968400 3600 0 CET}
    {3731274000 7200 1 CEST}
    {3750022800 3600 0 CET}
    {3762723600 7200 1 CEST}
    {3781472400 3600 0 CET}
    {3794173200 7200 1 CEST}
    {3812922000 3600 0 CET}
    {3825622800 7200 1 CEST}
    {3844371600 3600 0 CET}
    {3857677200 7200 1 CEST}
    {3875821200 3600 0 CET}
    {3889126800 7200 1 CEST}
    {3907270800 3600 0 CET}
    {3920576400 7200 1 CEST}
    {3939325200 3600 0 CET}
    {3952026000 7200 1 CEST}
    {3970774800 3600 0 CET}
    {3983475600 7200 1 CEST}
    {4002224400 3600 0 CET}
    {4015530000 7200 1 CEST}
    {4033674000 3600 0 CET}
    {4046979600 7200 1 CEST}
    {4065123600 3600 0 CET}
    {4078429200 7200 1 CEST}
    {4096573200 3600 0 CET}
}

Changes to library/tzdata/Europe/Samara.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Samara) {
    {-9223372036854775808 12020 0 LMT}
    {-1593820800 10800 0 +03}
    {-1247540400 14400 0 +04}
    {-1102305600 14400 0 +05}
    {354916800 18000 1 +05}
    {370724400 14400 0 +04}
    {386452800 18000 1 +05}
    {402260400 14400 0 +04}
    {417988800 18000 1 +05}
    {433796400 14400 0 +04}
    {449611200 18000 1 +05}
    {465343200 14400 0 +04}
    {481068000 18000 1 +05}
    {496792800 14400 0 +04}
    {512517600 18000 1 +05}
    {528242400 14400 0 +04}
    {543967200 18000 1 +05}
    {559692000 14400 0 +04}
    {575416800 18000 1 +05}
    {591141600 14400 0 +04}
    {606866400 10800 0 +04}
    {606870000 14400 1 +04}
    {622594800 10800 0 +03}
    {638319600 14400 1 +04}
    {654649200 10800 0 +03}
    {670374000 7200 0 +03}
    {670377600 10800 1 +03}
    {686102400 10800 0 +03}
    {687916800 14400 0 +04}
    {701820000 18000 1 +05}
    {717544800 14400 0 +04}
    {733269600 18000 1 +05}
    {748994400 14400 0 +04}
    {764719200 18000 1 +05}
    {780444000 14400 0 +04}
    {796168800 18000 1 +05}
    {811893600 14400 0 +04}
    {828223200 18000 1 +05}
    {846367200 14400 0 +04}
    {859672800 18000 1 +05}
    {877816800 14400 0 +04}
    {891122400 18000 1 +05}
    {909266400 14400 0 +04}
    {922572000 18000 1 +05}
    {941320800 14400 0 +04}
    {954021600 18000 1 +05}
    {972770400 14400 0 +04}
    {985471200 18000 1 +05}
    {1004220000 14400 0 +04}
    {1017525600 18000 1 +05}
    {1035669600 14400 0 +04}
    {1048975200 18000 1 +05}
    {1067119200 14400 0 +04}
    {1080424800 18000 1 +05}
    {1099173600 14400 0 +04}
    {1111874400 18000 1 +05}
    {1130623200 14400 0 +04}
    {1143324000 18000 1 +05}
    {1162072800 14400 0 +04}
    {1174773600 18000 1 +05}
    {1193522400 14400 0 +04}
    {1206828000 18000 1 +05}
    {1224972000 14400 0 +04}
    {1238277600 18000 1 +05}
    {1256421600 14400 0 +04}
    {1269727200 10800 0 +04}
    {1269730800 14400 1 +04}
    {1288479600 10800 0 +03}
    {1301180400 14400 0 +04}
    {-1593820800 10800 0 +0300}
    {-1247540400 14400 0 +0400}
    {-1102305600 14400 0 +0400}
    {354916800 18000 1 +0500}
    {370724400 14400 0 +0400}
    {386452800 18000 1 +0500}
    {402260400 14400 0 +0400}
    {417988800 18000 1 +0500}
    {433796400 14400 0 +0400}
    {449611200 18000 1 +0500}
    {465343200 14400 0 +0400}
    {481068000 18000 1 +0500}
    {496792800 14400 0 +0400}
    {512517600 18000 1 +0500}
    {528242400 14400 0 +0400}
    {543967200 18000 1 +0500}
    {559692000 14400 0 +0400}
    {575416800 18000 1 +0500}
    {591141600 14400 0 +0400}
    {606866400 10800 0 +0300}
    {606870000 14400 1 +0400}
    {622594800 10800 0 +0300}
    {638319600 14400 1 +0400}
    {654649200 10800 0 +0300}
    {670374000 7200 0 +0200}
    {670377600 10800 1 +0300}
    {686102400 10800 0 +0300}
    {687916800 14400 0 +0400}
    {701820000 18000 1 +0500}
    {717544800 14400 0 +0400}
    {733269600 18000 1 +0500}
    {748994400 14400 0 +0400}
    {764719200 18000 1 +0500}
    {780444000 14400 0 +0400}
    {796168800 18000 1 +0500}
    {811893600 14400 0 +0400}
    {828223200 18000 1 +0500}
    {846367200 14400 0 +0400}
    {859672800 18000 1 +0500}
    {877816800 14400 0 +0400}
    {891122400 18000 1 +0500}
    {909266400 14400 0 +0400}
    {922572000 18000 1 +0500}
    {941320800 14400 0 +0400}
    {954021600 18000 1 +0500}
    {972770400 14400 0 +0400}
    {985471200 18000 1 +0500}
    {1004220000 14400 0 +0400}
    {1017525600 18000 1 +0500}
    {1035669600 14400 0 +0400}
    {1048975200 18000 1 +0500}
    {1067119200 14400 0 +0400}
    {1080424800 18000 1 +0500}
    {1099173600 14400 0 +0400}
    {1111874400 18000 1 +0500}
    {1130623200 14400 0 +0400}
    {1143324000 18000 1 +0500}
    {1162072800 14400 0 +0400}
    {1174773600 18000 1 +0500}
    {1193522400 14400 0 +0400}
    {1206828000 18000 1 +0500}
    {1224972000 14400 0 +0400}
    {1238277600 18000 1 +0500}
    {1256421600 14400 0 +0400}
    {1269727200 10800 0 +0300}
    {1269730800 14400 1 +0400}
    {1288479600 10800 0 +0300}
    {1301180400 14400 0 +0400}
}

Changes to library/tzdata/Europe/Saratov.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Saratov) {
    {-9223372036854775808 11058 0 LMT}
    {-1593820800 10800 0 +03}
    {-1247540400 14400 0 +05}
    {354916800 18000 1 +05}
    {370724400 14400 0 +04}
    {386452800 18000 1 +05}
    {402260400 14400 0 +04}
    {417988800 18000 1 +05}
    {433796400 14400 0 +04}
    {449611200 18000 1 +05}
    {465343200 14400 0 +04}
    {481068000 18000 1 +05}
    {496792800 14400 0 +04}
    {512517600 18000 1 +05}
    {528242400 14400 0 +04}
    {543967200 18000 1 +05}
    {559692000 14400 0 +04}
    {575416800 10800 0 +04}
    {575420400 14400 1 +04}
    {591145200 10800 0 +03}
    {606870000 14400 1 +04}
    {622594800 10800 0 +03}
    {638319600 14400 1 +04}
    {654649200 10800 0 +03}
    {670374000 14400 0 +04}
    {701820000 10800 0 +04}
    {701823600 14400 1 +04}
    {717548400 10800 0 +03}
    {733273200 14400 1 +04}
    {748998000 10800 0 +03}
    {764722800 14400 1 +04}
    {780447600 10800 0 +03}
    {796172400 14400 1 +04}
    {811897200 10800 0 +03}
    {828226800 14400 1 +04}
    {846370800 10800 0 +03}
    {859676400 14400 1 +04}
    {877820400 10800 0 +03}
    {891126000 14400 1 +04}
    {909270000 10800 0 +03}
    {922575600 14400 1 +04}
    {941324400 10800 0 +03}
    {954025200 14400 1 +04}
    {972774000 10800 0 +03}
    {985474800 14400 1 +04}
    {1004223600 10800 0 +03}
    {1017529200 14400 1 +04}
    {1035673200 10800 0 +03}
    {1048978800 14400 1 +04}
    {1067122800 10800 0 +03}
    {1080428400 14400 1 +04}
    {1099177200 10800 0 +03}
    {1111878000 14400 1 +04}
    {1130626800 10800 0 +03}
    {1143327600 14400 1 +04}
    {1162076400 10800 0 +03}
    {1174777200 14400 1 +04}
    {1193526000 10800 0 +03}
    {1206831600 14400 1 +04}
    {1224975600 10800 0 +03}
    {1238281200 14400 1 +04}
    {1256425200 10800 0 +03}
    {1269730800 14400 1 +04}
    {1288479600 10800 0 +03}
    {1301180400 14400 0 +04}
    {1414274400 10800 0 +03}
    {1480806000 14400 0 +04}
    {-1593820800 10800 0 +0300}
    {-1247540400 14400 0 +0400}
    {354916800 18000 1 +0500}
    {370724400 14400 0 +0400}
    {386452800 18000 1 +0500}
    {402260400 14400 0 +0400}
    {417988800 18000 1 +0500}
    {433796400 14400 0 +0400}
    {449611200 18000 1 +0500}
    {465343200 14400 0 +0400}
    {481068000 18000 1 +0500}
    {496792800 14400 0 +0400}
    {512517600 18000 1 +0500}
    {528242400 14400 0 +0400}
    {543967200 18000 1 +0500}
    {559692000 14400 0 +0400}
    {575416800 10800 0 +0300}
    {575420400 14400 1 +0400}
    {591145200 10800 0 +0300}
    {606870000 14400 1 +0400}
    {622594800 10800 0 +0300}
    {638319600 14400 1 +0400}
    {654649200 10800 0 +0300}
    {670374000 14400 0 +0400}
    {701820000 10800 0 +0300}
    {701823600 14400 1 +0400}
    {717548400 10800 0 +0300}
    {733273200 14400 1 +0400}
    {748998000 10800 0 +0300}
    {764722800 14400 1 +0400}
    {780447600 10800 0 +0300}
    {796172400 14400 1 +0400}
    {811897200 10800 0 +0300}
    {828226800 14400 1 +0400}
    {846370800 10800 0 +0300}
    {859676400 14400 1 +0400}
    {877820400 10800 0 +0300}
    {891126000 14400 1 +0400}
    {909270000 10800 0 +0300}
    {922575600 14400 1 +0400}
    {941324400 10800 0 +0300}
    {954025200 14400 1 +0400}
    {972774000 10800 0 +0300}
    {985474800 14400 1 +0400}
    {1004223600 10800 0 +0300}
    {1017529200 14400 1 +0400}
    {1035673200 10800 0 +0300}
    {1048978800 14400 1 +0400}
    {1067122800 10800 0 +0300}
    {1080428400 14400 1 +0400}
    {1099177200 10800 0 +0300}
    {1111878000 14400 1 +0400}
    {1130626800 10800 0 +0300}
    {1143327600 14400 1 +0400}
    {1162076400 10800 0 +0300}
    {1174777200 14400 1 +0400}
    {1193526000 10800 0 +0300}
    {1206831600 14400 1 +0400}
    {1224975600 10800 0 +0300}
    {1238281200 14400 1 +0400}
    {1256425200 10800 0 +0300}
    {1269730800 14400 1 +0400}
    {1288479600 10800 0 +0300}
    {1301180400 14400 0 +0400}
    {1414274400 10800 0 +0300}
    {1480806000 14400 0 +0400}
}

Changes to library/tzdata/Europe/Simferopol.

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
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







-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
+
+
+

-
+







    {559695600 10800 0 MSK}
    {575420400 14400 1 MSD}
    {591145200 10800 0 MSK}
    {606870000 14400 1 MSD}
    {622594800 10800 0 MSK}
    {631141200 10800 0 MSK}
    {646786800 7200 0 EET}
    {694216800 7200 0 EET}
    {701820000 10800 1 EEST}
    {717541200 7200 0 EET}
    {733269600 10800 1 EEST}
    {748990800 7200 0 EET}
    {764719200 10800 1 EEST}
    {701042400 7200 0 EET}
    {701827200 10800 1 EEST}
    {717552000 7200 0 EET}
    {733276800 10800 1 EEST}
    {749001600 7200 0 EET}
    {764726400 10800 1 EEST}
    {767743200 14400 0 MSD}
    {780436800 10800 0 MSK}
    {796165200 14400 1 MSD}
    {811886400 10800 0 MSK}
    {780447600 10800 0 MSK}
    {796172400 14400 1 MSD}
    {811897200 10800 0 MSK}
    {828219600 14400 1 MSD}
    {852066000 10800 0 MSK}
    {846374400 10800 0 MSK}
    {859683600 10800 0 EEST}
    {877827600 7200 0 EET}
    {891133200 10800 1 EEST}
    {909277200 7200 0 EET}
    {922582800 10800 1 EEST}
    {941331600 7200 0 EET}
    {954032400 10800 1 EEST}

Changes to library/tzdata/Europe/Stockholm.

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
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
1
2
3


4
5
























































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Berlin)]} {
    LoadTimeZoneFile Europe/Berlin

set TZData(:Europe/Stockholm) {
}
set TZData(:Europe/Stockholm) $TZData(:Europe/Berlin)
    {-9223372036854775808 4332 0 LMT}
    {-2871681132 3614 0 SET}
    {-2208992414 3600 0 CET}
    {-1692496800 7200 1 CEST}
    {-1680483600 3600 0 CET}
    {315529200 3600 0 CET}
    {323830800 7200 1 CEST}
    {338950800 3600 0 CET}
    {354675600 7200 1 CEST}
    {370400400 3600 0 CET}
    {386125200 7200 1 CEST}
    {401850000 3600 0 CET}
    {417574800 7200 1 CEST}
    {433299600 3600 0 CET}
    {449024400 7200 1 CEST}
    {465354000 3600 0 CET}
    {481078800 7200 1 CEST}
    {496803600 3600 0 CET}
    {512528400 7200 1 CEST}
    {528253200 3600 0 CET}
    {543978000 7200 1 CEST}
    {559702800 3600 0 CET}
    {575427600 7200 1 CEST}
    {591152400 3600 0 CET}
    {606877200 7200 1 CEST}
    {622602000 3600 0 CET}
    {638326800 7200 1 CEST}
    {654656400 3600 0 CET}
    {670381200 7200 1 CEST}
    {686106000 3600 0 CET}
    {701830800 7200 1 CEST}
    {717555600 3600 0 CET}
    {733280400 7200 1 CEST}
    {749005200 3600 0 CET}
    {764730000 7200 1 CEST}
    {780454800 3600 0 CET}
    {796179600 7200 1 CEST}
    {811904400 3600 0 CET}
    {828234000 7200 1 CEST}
    {846378000 3600 0 CET}
    {859683600 7200 1 CEST}
    {877827600 3600 0 CET}
    {891133200 7200 1 CEST}
    {909277200 3600 0 CET}
    {922582800 7200 1 CEST}
    {941331600 3600 0 CET}
    {954032400 7200 1 CEST}
    {972781200 3600 0 CET}
    {985482000 7200 1 CEST}
    {1004230800 3600 0 CET}
    {1017536400 7200 1 CEST}
    {1035680400 3600 0 CET}
    {1048986000 7200 1 CEST}
    {1067130000 3600 0 CET}
    {1080435600 7200 1 CEST}
    {1099184400 3600 0 CET}
    {1111885200 7200 1 CEST}
    {1130634000 3600 0 CET}
    {1143334800 7200 1 CEST}
    {1162083600 3600 0 CET}
    {1174784400 7200 1 CEST}
    {1193533200 3600 0 CET}
    {1206838800 7200 1 CEST}
    {1224982800 3600 0 CET}
    {1238288400 7200 1 CEST}
    {1256432400 3600 0 CET}
    {1269738000 7200 1 CEST}
    {1288486800 3600 0 CET}
    {1301187600 7200 1 CEST}
    {1319936400 3600 0 CET}
    {1332637200 7200 1 CEST}
    {1351386000 3600 0 CET}
    {1364691600 7200 1 CEST}
    {1382835600 3600 0 CET}
    {1396141200 7200 1 CEST}
    {1414285200 3600 0 CET}
    {1427590800 7200 1 CEST}
    {1445734800 3600 0 CET}
    {1459040400 7200 1 CEST}
    {1477789200 3600 0 CET}
    {1490490000 7200 1 CEST}
    {1509238800 3600 0 CET}
    {1521939600 7200 1 CEST}
    {1540688400 3600 0 CET}
    {1553994000 7200 1 CEST}
    {1572138000 3600 0 CET}
    {1585443600 7200 1 CEST}
    {1603587600 3600 0 CET}
    {1616893200 7200 1 CEST}
    {1635642000 3600 0 CET}
    {1648342800 7200 1 CEST}
    {1667091600 3600 0 CET}
    {1679792400 7200 1 CEST}
    {1698541200 3600 0 CET}
    {1711846800 7200 1 CEST}
    {1729990800 3600 0 CET}
    {1743296400 7200 1 CEST}
    {1761440400 3600 0 CET}
    {1774746000 7200 1 CEST}
    {1792890000 3600 0 CET}
    {1806195600 7200 1 CEST}
    {1824944400 3600 0 CET}
    {1837645200 7200 1 CEST}
    {1856394000 3600 0 CET}
    {1869094800 7200 1 CEST}
    {1887843600 3600 0 CET}
    {1901149200 7200 1 CEST}
    {1919293200 3600 0 CET}
    {1932598800 7200 1 CEST}
    {1950742800 3600 0 CET}
    {1964048400 7200 1 CEST}
    {1982797200 3600 0 CET}
    {1995498000 7200 1 CEST}
    {2014246800 3600 0 CET}
    {2026947600 7200 1 CEST}
    {2045696400 3600 0 CET}
    {2058397200 7200 1 CEST}
    {2077146000 3600 0 CET}
    {2090451600 7200 1 CEST}
    {2108595600 3600 0 CET}
    {2121901200 7200 1 CEST}
    {2140045200 3600 0 CET}
    {2153350800 7200 1 CEST}
    {2172099600 3600 0 CET}
    {2184800400 7200 1 CEST}
    {2203549200 3600 0 CET}
    {2216250000 7200 1 CEST}
    {2234998800 3600 0 CET}
    {2248304400 7200 1 CEST}
    {2266448400 3600 0 CET}
    {2279754000 7200 1 CEST}
    {2297898000 3600 0 CET}
    {2311203600 7200 1 CEST}
    {2329347600 3600 0 CET}
    {2342653200 7200 1 CEST}
    {2361402000 3600 0 CET}
    {2374102800 7200 1 CEST}
    {2392851600 3600 0 CET}
    {2405552400 7200 1 CEST}
    {2424301200 3600 0 CET}
    {2437606800 7200 1 CEST}
    {2455750800 3600 0 CET}
    {2469056400 7200 1 CEST}
    {2487200400 3600 0 CET}
    {2500506000 7200 1 CEST}
    {2519254800 3600 0 CET}
    {2531955600 7200 1 CEST}
    {2550704400 3600 0 CET}
    {2563405200 7200 1 CEST}
    {2582154000 3600 0 CET}
    {2595459600 7200 1 CEST}
    {2613603600 3600 0 CET}
    {2626909200 7200 1 CEST}
    {2645053200 3600 0 CET}
    {2658358800 7200 1 CEST}
    {2676502800 3600 0 CET}
    {2689808400 7200 1 CEST}
    {2708557200 3600 0 CET}
    {2721258000 7200 1 CEST}
    {2740006800 3600 0 CET}
    {2752707600 7200 1 CEST}
    {2771456400 3600 0 CET}
    {2784762000 7200 1 CEST}
    {2802906000 3600 0 CET}
    {2816211600 7200 1 CEST}
    {2834355600 3600 0 CET}
    {2847661200 7200 1 CEST}
    {2866410000 3600 0 CET}
    {2879110800 7200 1 CEST}
    {2897859600 3600 0 CET}
    {2910560400 7200 1 CEST}
    {2929309200 3600 0 CET}
    {2942010000 7200 1 CEST}
    {2960758800 3600 0 CET}
    {2974064400 7200 1 CEST}
    {2992208400 3600 0 CET}
    {3005514000 7200 1 CEST}
    {3023658000 3600 0 CET}
    {3036963600 7200 1 CEST}
    {3055712400 3600 0 CET}
    {3068413200 7200 1 CEST}
    {3087162000 3600 0 CET}
    {3099862800 7200 1 CEST}
    {3118611600 3600 0 CET}
    {3131917200 7200 1 CEST}
    {3150061200 3600 0 CET}
    {3163366800 7200 1 CEST}
    {3181510800 3600 0 CET}
    {3194816400 7200 1 CEST}
    {3212960400 3600 0 CET}
    {3226266000 7200 1 CEST}
    {3245014800 3600 0 CET}
    {3257715600 7200 1 CEST}
    {3276464400 3600 0 CET}
    {3289165200 7200 1 CEST}
    {3307914000 3600 0 CET}
    {3321219600 7200 1 CEST}
    {3339363600 3600 0 CET}
    {3352669200 7200 1 CEST}
    {3370813200 3600 0 CET}
    {3384118800 7200 1 CEST}
    {3402867600 3600 0 CET}
    {3415568400 7200 1 CEST}
    {3434317200 3600 0 CET}
    {3447018000 7200 1 CEST}
    {3465766800 3600 0 CET}
    {3479072400 7200 1 CEST}
    {3497216400 3600 0 CET}
    {3510522000 7200 1 CEST}
    {3528666000 3600 0 CET}
    {3541971600 7200 1 CEST}
    {3560115600 3600 0 CET}
    {3573421200 7200 1 CEST}
    {3592170000 3600 0 CET}
    {3604870800 7200 1 CEST}
    {3623619600 3600 0 CET}
    {3636320400 7200 1 CEST}
    {3655069200 3600 0 CET}
    {3668374800 7200 1 CEST}
    {3686518800 3600 0 CET}
    {3699824400 7200 1 CEST}
    {3717968400 3600 0 CET}
    {3731274000 7200 1 CEST}
    {3750022800 3600 0 CET}
    {3762723600 7200 1 CEST}
    {3781472400 3600 0 CET}
    {3794173200 7200 1 CEST}
    {3812922000 3600 0 CET}
    {3825622800 7200 1 CEST}
    {3844371600 3600 0 CET}
    {3857677200 7200 1 CEST}
    {3875821200 3600 0 CET}
    {3889126800 7200 1 CEST}
    {3907270800 3600 0 CET}
    {3920576400 7200 1 CEST}
    {3939325200 3600 0 CET}
    {3952026000 7200 1 CEST}
    {3970774800 3600 0 CET}
    {3983475600 7200 1 CEST}
    {4002224400 3600 0 CET}
    {4015530000 7200 1 CEST}
    {4033674000 3600 0 CET}
    {4046979600 7200 1 CEST}
    {4065123600 3600 0 CET}
    {4078429200 7200 1 CEST}
    {4096573200 3600 0 CET}
}

Changes to library/tzdata/Europe/Ulyanovsk.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Ulyanovsk) {
    {-9223372036854775808 11616 0 LMT}
    {-1593820800 10800 0 +03}
    {-1247540400 14400 0 +05}
    {354916800 18000 1 +05}
    {370724400 14400 0 +04}
    {386452800 18000 1 +05}
    {402260400 14400 0 +04}
    {417988800 18000 1 +05}
    {433796400 14400 0 +04}
    {449611200 18000 1 +05}
    {465343200 14400 0 +04}
    {481068000 18000 1 +05}
    {496792800 14400 0 +04}
    {512517600 18000 1 +05}
    {528242400 14400 0 +04}
    {543967200 18000 1 +05}
    {559692000 14400 0 +04}
    {575416800 18000 1 +05}
    {591141600 14400 0 +04}
    {606866400 10800 0 +04}
    {606870000 14400 1 +04}
    {622594800 10800 0 +03}
    {638319600 14400 1 +04}
    {654649200 10800 0 +03}
    {670374000 7200 0 +03}
    {670377600 10800 1 +03}
    {686102400 7200 0 +02}
    {695779200 10800 0 +04}
    {701823600 14400 1 +04}
    {717548400 10800 0 +03}
    {733273200 14400 1 +04}
    {748998000 10800 0 +03}
    {764722800 14400 1 +04}
    {780447600 10800 0 +03}
    {796172400 14400 1 +04}
    {811897200 10800 0 +03}
    {828226800 14400 1 +04}
    {846370800 10800 0 +03}
    {859676400 14400 1 +04}
    {877820400 10800 0 +03}
    {891126000 14400 1 +04}
    {909270000 10800 0 +03}
    {922575600 14400 1 +04}
    {941324400 10800 0 +03}
    {954025200 14400 1 +04}
    {972774000 10800 0 +03}
    {985474800 14400 1 +04}
    {1004223600 10800 0 +03}
    {1017529200 14400 1 +04}
    {1035673200 10800 0 +03}
    {1048978800 14400 1 +04}
    {1067122800 10800 0 +03}
    {1080428400 14400 1 +04}
    {1099177200 10800 0 +03}
    {1111878000 14400 1 +04}
    {1130626800 10800 0 +03}
    {1143327600 14400 1 +04}
    {1162076400 10800 0 +03}
    {1174777200 14400 1 +04}
    {1193526000 10800 0 +03}
    {1206831600 14400 1 +04}
    {1224975600 10800 0 +03}
    {1238281200 14400 1 +04}
    {1256425200 10800 0 +03}
    {1269730800 14400 1 +04}
    {1288479600 10800 0 +03}
    {1301180400 14400 0 +04}
    {1414274400 10800 0 +03}
    {1459033200 14400 0 +04}
    {-1593820800 10800 0 +0300}
    {-1247540400 14400 0 +0400}
    {354916800 18000 1 +0500}
    {370724400 14400 0 +0400}
    {386452800 18000 1 +0500}
    {402260400 14400 0 +0400}
    {417988800 18000 1 +0500}
    {433796400 14400 0 +0400}
    {449611200 18000 1 +0500}
    {465343200 14400 0 +0400}
    {481068000 18000 1 +0500}
    {496792800 14400 0 +0400}
    {512517600 18000 1 +0500}
    {528242400 14400 0 +0400}
    {543967200 18000 1 +0500}
    {559692000 14400 0 +0400}
    {575416800 18000 1 +0500}
    {591141600 14400 0 +0400}
    {606866400 10800 0 +0300}
    {606870000 14400 1 +0400}
    {622594800 10800 0 +0300}
    {638319600 14400 1 +0400}
    {654649200 10800 0 +0300}
    {670374000 7200 0 +0200}
    {670377600 10800 1 +0300}
    {686102400 7200 0 +0200}
    {695779200 10800 0 +0300}
    {701823600 14400 1 +0400}
    {717548400 10800 0 +0300}
    {733273200 14400 1 +0400}
    {748998000 10800 0 +0300}
    {764722800 14400 1 +0400}
    {780447600 10800 0 +0300}
    {796172400 14400 1 +0400}
    {811897200 10800 0 +0300}
    {828226800 14400 1 +0400}
    {846370800 10800 0 +0300}
    {859676400 14400 1 +0400}
    {877820400 10800 0 +0300}
    {891126000 14400 1 +0400}
    {909270000 10800 0 +0300}
    {922575600 14400 1 +0400}
    {941324400 10800 0 +0300}
    {954025200 14400 1 +0400}
    {972774000 10800 0 +0300}
    {985474800 14400 1 +0400}
    {1004223600 10800 0 +0300}
    {1017529200 14400 1 +0400}
    {1035673200 10800 0 +0300}
    {1048978800 14400 1 +0400}
    {1067122800 10800 0 +0300}
    {1080428400 14400 1 +0400}
    {1099177200 10800 0 +0300}
    {1111878000 14400 1 +0400}
    {1130626800 10800 0 +0300}
    {1143327600 14400 1 +0400}
    {1162076400 10800 0 +0300}
    {1174777200 14400 1 +0400}
    {1193526000 10800 0 +0300}
    {1206831600 14400 1 +0400}
    {1224975600 10800 0 +0300}
    {1238281200 14400 1 +0400}
    {1256425200 10800 0 +0300}
    {1269730800 14400 1 +0400}
    {1288479600 10800 0 +0300}
    {1301180400 14400 0 +0400}
    {1414274400 10800 0 +0300}
    {1459033200 14400 0 +0400}
}

Changes to library/tzdata/Europe/Uzhgorod.

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
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
1
2
3


4
5




























































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Kyiv)]} {
    LoadTimeZoneFile Europe/Kyiv

set TZData(:Europe/Uzhgorod) {
}
set TZData(:Europe/Uzhgorod) $TZData(:Europe/Kyiv)
    {-9223372036854775808 5352 0 LMT}
    {-2500939752 3600 0 CET}
    {-946774800 3600 0 CET}
    {-938905200 7200 1 CEST}
    {-857257200 3600 0 CET}
    {-844556400 7200 1 CEST}
    {-828226800 3600 0 CET}
    {-812502000 7200 1 CEST}
    {-796870800 7200 1 CEST}
    {-794714400 3600 0 CET}
    {-773456400 10800 0 MSD}
    {354920400 14400 1 MSD}
    {370728000 10800 0 MSK}
    {386456400 14400 1 MSD}
    {402264000 10800 0 MSK}
    {417992400 14400 1 MSD}
    {433800000 10800 0 MSK}
    {449614800 14400 1 MSD}
    {465346800 10800 0 MSK}
    {481071600 14400 1 MSD}
    {496796400 10800 0 MSK}
    {512521200 14400 1 MSD}
    {528246000 10800 0 MSK}
    {543970800 14400 1 MSD}
    {559695600 10800 0 MSK}
    {575420400 14400 1 MSD}
    {591145200 10800 0 MSK}
    {606870000 14400 1 MSD}
    {622594800 10800 0 MSK}
    {631141200 10800 0 MSK}
    {646786800 3600 0 CET}
    {670384800 7200 0 EET}
    {694216800 7200 0 EET}
    {701820000 10800 1 EEST}
    {717541200 7200 0 EET}
    {733269600 10800 1 EEST}
    {748990800 7200 0 EET}
    {764719200 10800 1 EEST}
    {780440400 7200 0 EET}
    {788911200 7200 0 EET}
    {796179600 10800 1 EEST}
    {811904400 7200 0 EET}
    {828234000 10800 1 EEST}
    {846378000 7200 0 EET}
    {859683600 10800 1 EEST}
    {877827600 7200 0 EET}
    {891133200 10800 1 EEST}
    {909277200 7200 0 EET}
    {922582800 10800 1 EEST}
    {941331600 7200 0 EET}
    {954032400 10800 1 EEST}
    {972781200 7200 0 EET}
    {985482000 10800 1 EEST}
    {1004230800 7200 0 EET}
    {1017536400 10800 1 EEST}
    {1035680400 7200 0 EET}
    {1048986000 10800 1 EEST}
    {1067130000 7200 0 EET}
    {1080435600 10800 1 EEST}
    {1099184400 7200 0 EET}
    {1111885200 10800 1 EEST}
    {1130634000 7200 0 EET}
    {1143334800 10800 1 EEST}
    {1162083600 7200 0 EET}
    {1174784400 10800 1 EEST}
    {1193533200 7200 0 EET}
    {1206838800 10800 1 EEST}
    {1224982800 7200 0 EET}
    {1238288400 10800 1 EEST}
    {1256432400 7200 0 EET}
    {1269738000 10800 1 EEST}
    {1288486800 7200 0 EET}
    {1301187600 10800 1 EEST}
    {1319936400 7200 0 EET}
    {1332637200 10800 1 EEST}
    {1351386000 7200 0 EET}
    {1364691600 10800 1 EEST}
    {1382835600 7200 0 EET}
    {1396141200 10800 1 EEST}
    {1414285200 7200 0 EET}
    {1427590800 10800 1 EEST}
    {1445734800 7200 0 EET}
    {1459040400 10800 1 EEST}
    {1477789200 7200 0 EET}
    {1490490000 10800 1 EEST}
    {1509238800 7200 0 EET}
    {1521939600 10800 1 EEST}
    {1540688400 7200 0 EET}
    {1553994000 10800 1 EEST}
    {1572138000 7200 0 EET}
    {1585443600 10800 1 EEST}
    {1603587600 7200 0 EET}
    {1616893200 10800 1 EEST}
    {1635642000 7200 0 EET}
    {1648342800 10800 1 EEST}
    {1667091600 7200 0 EET}
    {1679792400 10800 1 EEST}
    {1698541200 7200 0 EET}
    {1711846800 10800 1 EEST}
    {1729990800 7200 0 EET}
    {1743296400 10800 1 EEST}
    {1761440400 7200 0 EET}
    {1774746000 10800 1 EEST}
    {1792890000 7200 0 EET}
    {1806195600 10800 1 EEST}
    {1824944400 7200 0 EET}
    {1837645200 10800 1 EEST}
    {1856394000 7200 0 EET}
    {1869094800 10800 1 EEST}
    {1887843600 7200 0 EET}
    {1901149200 10800 1 EEST}
    {1919293200 7200 0 EET}
    {1932598800 10800 1 EEST}
    {1950742800 7200 0 EET}
    {1964048400 10800 1 EEST}
    {1982797200 7200 0 EET}
    {1995498000 10800 1 EEST}
    {2014246800 7200 0 EET}
    {2026947600 10800 1 EEST}
    {2045696400 7200 0 EET}
    {2058397200 10800 1 EEST}
    {2077146000 7200 0 EET}
    {2090451600 10800 1 EEST}
    {2108595600 7200 0 EET}
    {2121901200 10800 1 EEST}
    {2140045200 7200 0 EET}
    {2153350800 10800 1 EEST}
    {2172099600 7200 0 EET}
    {2184800400 10800 1 EEST}
    {2203549200 7200 0 EET}
    {2216250000 10800 1 EEST}
    {2234998800 7200 0 EET}
    {2248304400 10800 1 EEST}
    {2266448400 7200 0 EET}
    {2279754000 10800 1 EEST}
    {2297898000 7200 0 EET}
    {2311203600 10800 1 EEST}
    {2329347600 7200 0 EET}
    {2342653200 10800 1 EEST}
    {2361402000 7200 0 EET}
    {2374102800 10800 1 EEST}
    {2392851600 7200 0 EET}
    {2405552400 10800 1 EEST}
    {2424301200 7200 0 EET}
    {2437606800 10800 1 EEST}
    {2455750800 7200 0 EET}
    {2469056400 10800 1 EEST}
    {2487200400 7200 0 EET}
    {2500506000 10800 1 EEST}
    {2519254800 7200 0 EET}
    {2531955600 10800 1 EEST}
    {2550704400 7200 0 EET}
    {2563405200 10800 1 EEST}
    {2582154000 7200 0 EET}
    {2595459600 10800 1 EEST}
    {2613603600 7200 0 EET}
    {2626909200 10800 1 EEST}
    {2645053200 7200 0 EET}
    {2658358800 10800 1 EEST}
    {2676502800 7200 0 EET}
    {2689808400 10800 1 EEST}
    {2708557200 7200 0 EET}
    {2721258000 10800 1 EEST}
    {2740006800 7200 0 EET}
    {2752707600 10800 1 EEST}
    {2771456400 7200 0 EET}
    {2784762000 10800 1 EEST}
    {2802906000 7200 0 EET}
    {2816211600 10800 1 EEST}
    {2834355600 7200 0 EET}
    {2847661200 10800 1 EEST}
    {2866410000 7200 0 EET}
    {2879110800 10800 1 EEST}
    {2897859600 7200 0 EET}
    {2910560400 10800 1 EEST}
    {2929309200 7200 0 EET}
    {2942010000 10800 1 EEST}
    {2960758800 7200 0 EET}
    {2974064400 10800 1 EEST}
    {2992208400 7200 0 EET}
    {3005514000 10800 1 EEST}
    {3023658000 7200 0 EET}
    {3036963600 10800 1 EEST}
    {3055712400 7200 0 EET}
    {3068413200 10800 1 EEST}
    {3087162000 7200 0 EET}
    {3099862800 10800 1 EEST}
    {3118611600 7200 0 EET}
    {3131917200 10800 1 EEST}
    {3150061200 7200 0 EET}
    {3163366800 10800 1 EEST}
    {3181510800 7200 0 EET}
    {3194816400 10800 1 EEST}
    {3212960400 7200 0 EET}
    {3226266000 10800 1 EEST}
    {3245014800 7200 0 EET}
    {3257715600 10800 1 EEST}
    {3276464400 7200 0 EET}
    {3289165200 10800 1 EEST}
    {3307914000 7200 0 EET}
    {3321219600 10800 1 EEST}
    {3339363600 7200 0 EET}
    {3352669200 10800 1 EEST}
    {3370813200 7200 0 EET}
    {3384118800 10800 1 EEST}
    {3402867600 7200 0 EET}
    {3415568400 10800 1 EEST}
    {3434317200 7200 0 EET}
    {3447018000 10800 1 EEST}
    {3465766800 7200 0 EET}
    {3479072400 10800 1 EEST}
    {3497216400 7200 0 EET}
    {3510522000 10800 1 EEST}
    {3528666000 7200 0 EET}
    {3541971600 10800 1 EEST}
    {3560115600 7200 0 EET}
    {3573421200 10800 1 EEST}
    {3592170000 7200 0 EET}
    {3604870800 10800 1 EEST}
    {3623619600 7200 0 EET}
    {3636320400 10800 1 EEST}
    {3655069200 7200 0 EET}
    {3668374800 10800 1 EEST}
    {3686518800 7200 0 EET}
    {3699824400 10800 1 EEST}
    {3717968400 7200 0 EET}
    {3731274000 10800 1 EEST}
    {3750022800 7200 0 EET}
    {3762723600 10800 1 EEST}
    {3781472400 7200 0 EET}
    {3794173200 10800 1 EEST}
    {3812922000 7200 0 EET}
    {3825622800 10800 1 EEST}
    {3844371600 7200 0 EET}
    {3857677200 10800 1 EEST}
    {3875821200 7200 0 EET}
    {3889126800 10800 1 EEST}
    {3907270800 7200 0 EET}
    {3920576400 10800 1 EEST}
    {3939325200 7200 0 EET}
    {3952026000 10800 1 EEST}
    {3970774800 7200 0 EET}
    {3983475600 10800 1 EEST}
    {4002224400 7200 0 EET}
    {4015530000 10800 1 EEST}
    {4033674000 7200 0 EET}
    {4046979600 10800 1 EEST}
    {4065123600 7200 0 EET}
    {4078429200 10800 1 EEST}
    {4096573200 7200 0 EET}
}

Changes to library/tzdata/Europe/Volgograd.

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
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
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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Europe/Volgograd) {
    {-9223372036854775808 10660 0 LMT}
    {-1577761060 10800 0 +03}
    {-1247540400 14400 0 +04}
    {-256881600 14400 0 +05}
    {354916800 18000 1 +05}
    {370724400 14400 0 +04}
    {386452800 18000 1 +05}
    {402260400 14400 0 +04}
    {417988800 18000 1 +05}
    {433796400 14400 0 +04}
    {449611200 18000 1 +05}
    {465343200 14400 0 +04}
    {481068000 18000 1 +05}
    {496792800 14400 0 +04}
    {512517600 18000 1 +05}
    {528242400 14400 0 +04}
    {543967200 18000 1 +05}
    {559692000 14400 0 +04}
    {575416800 10800 0 +04}
    {575420400 14400 1 +04}
    {591145200 10800 0 +03}
    {606870000 14400 1 +04}
    {622594800 10800 0 +03}
    {638319600 14400 1 +04}
    {654649200 10800 0 +03}
    {670374000 14400 0 +04}
    {701820000 10800 0 +04}
    {701823600 14400 1 +04}
    {717548400 10800 0 +03}
    {733273200 14400 1 +04}
    {748998000 10800 0 +03}
    {764722800 14400 1 +04}
    {780447600 10800 0 +03}
    {796172400 14400 1 +04}
    {811897200 10800 0 +03}
    {828226800 14400 1 +04}
    {846370800 10800 0 +03}
    {859676400 14400 1 +04}
    {877820400 10800 0 +03}
    {891126000 14400 1 +04}
    {909270000 10800 0 +03}
    {922575600 14400 1 +04}
    {941324400 10800 0 +03}
    {954025200 14400 1 +04}
    {972774000 10800 0 +03}
    {985474800 14400 1 +04}
    {1004223600 10800 0 +03}
    {1017529200 14400 1 +04}
    {1035673200 10800 0 +03}
    {1048978800 14400 1 +04}
    {1067122800 10800 0 +03}
    {1080428400 14400 1 +04}
    {1099177200 10800 0 +03}
    {1111878000 14400 1 +04}
    {1130626800 10800 0 +03}
    {1143327600 14400 1 +04}
    {1162076400 10800 0 +03}
    {1174777200 14400 1 +04}
    {1193526000 10800 0 +03}
    {1206831600 14400 1 +04}
    {1224975600 10800 0 +03}
    {1238281200 14400 1 +04}
    {1256425200 10800 0 +03}
    {1269730800 14400 1 +04}
    {1288479600 10800 0 +03}
    {1301180400 14400 0 +04}
    {1414274400 10800 0 +03}
    {1540681200 14400 0 +04}
    {-1577761060 10800 0 +0300}
    {-1247540400 14400 0 +0400}
    {-256881600 14400 0 +0400}
    {354916800 18000 1 +0500}
    {370724400 14400 0 +0400}
    {386452800 18000 1 +0500}
    {402260400 14400 0 +0400}
    {417988800 18000 1 +0500}
    {433796400 14400 0 +0400}
    {449611200 18000 1 +0500}
    {465343200 14400 0 +0400}
    {481068000 18000 1 +0500}
    {496792800 14400 0 +0400}
    {512517600 18000 1 +0500}
    {528242400 14400 0 +0400}
    {543967200 18000 1 +0500}
    {559692000 14400 0 +0400}
    {575416800 10800 0 MSD}
    {575420400 14400 1 MSD}
    {591145200 10800 0 MSK}
    {606870000 14400 1 MSD}
    {622594800 10800 0 MSK}
    {638319600 14400 1 MSD}
    {654649200 10800 0 MSK}
    {670374000 14400 0 +0400}
    {701820000 10800 0 MSD}
    {701823600 14400 1 MSD}
    {717548400 10800 0 MSK}
    {733273200 14400 1 MSD}
    {748998000 10800 0 MSK}
    {764722800 14400 1 MSD}
    {780447600 10800 0 MSK}
    {796172400 14400 1 MSD}
    {811897200 10800 0 MSK}
    {828226800 14400 1 MSD}
    {846370800 10800 0 MSK}
    {859676400 14400 1 MSD}
    {877820400 10800 0 MSK}
    {891126000 14400 1 MSD}
    {909270000 10800 0 MSK}
    {922575600 14400 1 MSD}
    {941324400 10800 0 MSK}
    {954025200 14400 1 MSD}
    {972774000 10800 0 MSK}
    {985474800 14400 1 MSD}
    {1004223600 10800 0 MSK}
    {1017529200 14400 1 MSD}
    {1035673200 10800 0 MSK}
    {1048978800 14400 1 MSD}
    {1067122800 10800 0 MSK}
    {1080428400 14400 1 MSD}
    {1099177200 10800 0 MSK}
    {1111878000 14400 1 MSD}
    {1130626800 10800 0 MSK}
    {1143327600 14400 1 MSD}
    {1162076400 10800 0 MSK}
    {1174777200 14400 1 MSD}
    {1193526000 10800 0 MSK}
    {1206831600 14400 1 MSD}
    {1224975600 10800 0 MSK}
    {1238281200 14400 1 MSD}
    {1256425200 10800 0 MSK}
    {1269730800 14400 1 MSD}
    {1288479600 10800 0 MSK}
    {1301180400 14400 0 MSK}
    {1414274400 10800 0 MSK}
    {1540681200 14400 0 +0400}
    {1609020000 10800 0 MSK}
}

Changes to library/tzdata/Europe/Zaporozhye.

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
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
1
2
3


4
5


























































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Kyiv)]} {
    LoadTimeZoneFile Europe/Kyiv

set TZData(:Europe/Zaporozhye) {
}
set TZData(:Europe/Zaporozhye) $TZData(:Europe/Kyiv)
    {-9223372036854775808 8440 0 LMT}
    {-2840149240 8400 0 +0220}
    {-1441160400 7200 0 EET}
    {-1247536800 10800 0 MSK}
    {-894769200 3600 0 CET}
    {-857257200 3600 0 CET}
    {-844556400 7200 1 CEST}
    {-828226800 3600 0 CET}
    {-826419600 10800 0 MSD}
    {354920400 14400 1 MSD}
    {370728000 10800 0 MSK}
    {386456400 14400 1 MSD}
    {402264000 10800 0 MSK}
    {417992400 14400 1 MSD}
    {433800000 10800 0 MSK}
    {449614800 14400 1 MSD}
    {465346800 10800 0 MSK}
    {481071600 14400 1 MSD}
    {496796400 10800 0 MSK}
    {512521200 14400 1 MSD}
    {528246000 10800 0 MSK}
    {543970800 14400 1 MSD}
    {559695600 10800 0 MSK}
    {575420400 14400 1 MSD}
    {591145200 10800 0 MSK}
    {606870000 14400 1 MSD}
    {622594800 10800 0 MSK}
    {638319600 14400 1 MSD}
    {654649200 10800 0 MSK}
    {670374000 10800 0 EEST}
    {686091600 7200 0 EET}
    {701820000 10800 1 EEST}
    {717541200 7200 0 EET}
    {733269600 10800 1 EEST}
    {748990800 7200 0 EET}
    {764719200 10800 1 EEST}
    {780440400 7200 0 EET}
    {788911200 7200 0 EET}
    {796179600 10800 1 EEST}
    {811904400 7200 0 EET}
    {828234000 10800 1 EEST}
    {846378000 7200 0 EET}
    {859683600 10800 1 EEST}
    {877827600 7200 0 EET}
    {891133200 10800 1 EEST}
    {909277200 7200 0 EET}
    {922582800 10800 1 EEST}
    {941331600 7200 0 EET}
    {954032400 10800 1 EEST}
    {972781200 7200 0 EET}
    {985482000 10800 1 EEST}
    {1004230800 7200 0 EET}
    {1017536400 10800 1 EEST}
    {1035680400 7200 0 EET}
    {1048986000 10800 1 EEST}
    {1067130000 7200 0 EET}
    {1080435600 10800 1 EEST}
    {1099184400 7200 0 EET}
    {1111885200 10800 1 EEST}
    {1130634000 7200 0 EET}
    {1143334800 10800 1 EEST}
    {1162083600 7200 0 EET}
    {1174784400 10800 1 EEST}
    {1193533200 7200 0 EET}
    {1206838800 10800 1 EEST}
    {1224982800 7200 0 EET}
    {1238288400 10800 1 EEST}
    {1256432400 7200 0 EET}
    {1269738000 10800 1 EEST}
    {1288486800 7200 0 EET}
    {1301187600 10800 1 EEST}
    {1319936400 7200 0 EET}
    {1332637200 10800 1 EEST}
    {1351386000 7200 0 EET}
    {1364691600 10800 1 EEST}
    {1382835600 7200 0 EET}
    {1396141200 10800 1 EEST}
    {1414285200 7200 0 EET}
    {1427590800 10800 1 EEST}
    {1445734800 7200 0 EET}
    {1459040400 10800 1 EEST}
    {1477789200 7200 0 EET}
    {1490490000 10800 1 EEST}
    {1509238800 7200 0 EET}
    {1521939600 10800 1 EEST}
    {1540688400 7200 0 EET}
    {1553994000 10800 1 EEST}
    {1572138000 7200 0 EET}
    {1585443600 10800 1 EEST}
    {1603587600 7200 0 EET}
    {1616893200 10800 1 EEST}
    {1635642000 7200 0 EET}
    {1648342800 10800 1 EEST}
    {1667091600 7200 0 EET}
    {1679792400 10800 1 EEST}
    {1698541200 7200 0 EET}
    {1711846800 10800 1 EEST}
    {1729990800 7200 0 EET}
    {1743296400 10800 1 EEST}
    {1761440400 7200 0 EET}
    {1774746000 10800 1 EEST}
    {1792890000 7200 0 EET}
    {1806195600 10800 1 EEST}
    {1824944400 7200 0 EET}
    {1837645200 10800 1 EEST}
    {1856394000 7200 0 EET}
    {1869094800 10800 1 EEST}
    {1887843600 7200 0 EET}
    {1901149200 10800 1 EEST}
    {1919293200 7200 0 EET}
    {1932598800 10800 1 EEST}
    {1950742800 7200 0 EET}
    {1964048400 10800 1 EEST}
    {1982797200 7200 0 EET}
    {1995498000 10800 1 EEST}
    {2014246800 7200 0 EET}
    {2026947600 10800 1 EEST}
    {2045696400 7200 0 EET}
    {2058397200 10800 1 EEST}
    {2077146000 7200 0 EET}
    {2090451600 10800 1 EEST}
    {2108595600 7200 0 EET}
    {2121901200 10800 1 EEST}
    {2140045200 7200 0 EET}
    {2153350800 10800 1 EEST}
    {2172099600 7200 0 EET}
    {2184800400 10800 1 EEST}
    {2203549200 7200 0 EET}
    {2216250000 10800 1 EEST}
    {2234998800 7200 0 EET}
    {2248304400 10800 1 EEST}
    {2266448400 7200 0 EET}
    {2279754000 10800 1 EEST}
    {2297898000 7200 0 EET}
    {2311203600 10800 1 EEST}
    {2329347600 7200 0 EET}
    {2342653200 10800 1 EEST}
    {2361402000 7200 0 EET}
    {2374102800 10800 1 EEST}
    {2392851600 7200 0 EET}
    {2405552400 10800 1 EEST}
    {2424301200 7200 0 EET}
    {2437606800 10800 1 EEST}
    {2455750800 7200 0 EET}
    {2469056400 10800 1 EEST}
    {2487200400 7200 0 EET}
    {2500506000 10800 1 EEST}
    {2519254800 7200 0 EET}
    {2531955600 10800 1 EEST}
    {2550704400 7200 0 EET}
    {2563405200 10800 1 EEST}
    {2582154000 7200 0 EET}
    {2595459600 10800 1 EEST}
    {2613603600 7200 0 EET}
    {2626909200 10800 1 EEST}
    {2645053200 7200 0 EET}
    {2658358800 10800 1 EEST}
    {2676502800 7200 0 EET}
    {2689808400 10800 1 EEST}
    {2708557200 7200 0 EET}
    {2721258000 10800 1 EEST}
    {2740006800 7200 0 EET}
    {2752707600 10800 1 EEST}
    {2771456400 7200 0 EET}
    {2784762000 10800 1 EEST}
    {2802906000 7200 0 EET}
    {2816211600 10800 1 EEST}
    {2834355600 7200 0 EET}
    {2847661200 10800 1 EEST}
    {2866410000 7200 0 EET}
    {2879110800 10800 1 EEST}
    {2897859600 7200 0 EET}
    {2910560400 10800 1 EEST}
    {2929309200 7200 0 EET}
    {2942010000 10800 1 EEST}
    {2960758800 7200 0 EET}
    {2974064400 10800 1 EEST}
    {2992208400 7200 0 EET}
    {3005514000 10800 1 EEST}
    {3023658000 7200 0 EET}
    {3036963600 10800 1 EEST}
    {3055712400 7200 0 EET}
    {3068413200 10800 1 EEST}
    {3087162000 7200 0 EET}
    {3099862800 10800 1 EEST}
    {3118611600 7200 0 EET}
    {3131917200 10800 1 EEST}
    {3150061200 7200 0 EET}
    {3163366800 10800 1 EEST}
    {3181510800 7200 0 EET}
    {3194816400 10800 1 EEST}
    {3212960400 7200 0 EET}
    {3226266000 10800 1 EEST}
    {3245014800 7200 0 EET}
    {3257715600 10800 1 EEST}
    {3276464400 7200 0 EET}
    {3289165200 10800 1 EEST}
    {3307914000 7200 0 EET}
    {3321219600 10800 1 EEST}
    {3339363600 7200 0 EET}
    {3352669200 10800 1 EEST}
    {3370813200 7200 0 EET}
    {3384118800 10800 1 EEST}
    {3402867600 7200 0 EET}
    {3415568400 10800 1 EEST}
    {3434317200 7200 0 EET}
    {3447018000 10800 1 EEST}
    {3465766800 7200 0 EET}
    {3479072400 10800 1 EEST}
    {3497216400 7200 0 EET}
    {3510522000 10800 1 EEST}
    {3528666000 7200 0 EET}
    {3541971600 10800 1 EEST}
    {3560115600 7200 0 EET}
    {3573421200 10800 1 EEST}
    {3592170000 7200 0 EET}
    {3604870800 10800 1 EEST}
    {3623619600 7200 0 EET}
    {3636320400 10800 1 EEST}
    {3655069200 7200 0 EET}
    {3668374800 10800 1 EEST}
    {3686518800 7200 0 EET}
    {3699824400 10800 1 EEST}
    {3717968400 7200 0 EET}
    {3731274000 10800 1 EEST}
    {3750022800 7200 0 EET}
    {3762723600 10800 1 EEST}
    {3781472400 7200 0 EET}
    {3794173200 10800 1 EEST}
    {3812922000 7200 0 EET}
    {3825622800 10800 1 EEST}
    {3844371600 7200 0 EET}
    {3857677200 10800 1 EEST}
    {3875821200 7200 0 EET}
    {3889126800 10800 1 EEST}
    {3907270800 7200 0 EET}
    {3920576400 10800 1 EEST}
    {3939325200 7200 0 EET}
    {3952026000 10800 1 EEST}
    {3970774800 7200 0 EET}
    {3983475600 10800 1 EEST}
    {4002224400 7200 0 EET}
    {4015530000 10800 1 EEST}
    {4033674000 7200 0 EET}
    {4046979600 10800 1 EEST}
    {4065123600 7200 0 EET}
    {4078429200 10800 1 EEST}
    {4096573200 7200 0 EET}
}

Changes to library/tzdata/HST.

1


2
3


4
5
1
2
3


4
5



+
+
-
-
+
+
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Honolulu)]} {
    LoadTimeZoneFile Pacific/Honolulu

set TZData(:HST) {
}
set TZData(:HST) $TZData(:Pacific/Honolulu)
    {-9223372036854775808 -36000 0 HST}
}

Changes to library/tzdata/Iceland.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Atlantic/Reykjavik)]} {
    LoadTimeZoneFile Atlantic/Reykjavik
if {![info exists TZData(Africa/Abidjan)]} {
    LoadTimeZoneFile Africa/Abidjan
}
set TZData(:Iceland) $TZData(:Atlantic/Reykjavik)
set TZData(:Iceland) $TZData(:Africa/Abidjan)

Changes to library/tzdata/Indian/Chagos.

1
2
3
4
5
6


7
1
2
3
4


5
6
7




-
-
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Indian/Chagos) {
    {-9223372036854775808 17380 0 LMT}
    {-1988167780 18000 0 +05}
    {820436400 21600 0 +06}
    {-1988167780 18000 0 +0500}
    {820436400 21600 0 +0600}
}

Changes to library/tzdata/Indian/Christmas.

1


2
3


4
5
6
1
2
3


4
5




+
+
-
-
+
+
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Asia/Bangkok)]} {
    LoadTimeZoneFile Asia/Bangkok

set TZData(:Indian/Christmas) {
}
set TZData(:Indian/Christmas) $TZData(:Asia/Bangkok)
    {-9223372036854775808 25372 0 LMT}
    {-2364102172 25200 0 +07}
}

Changes to library/tzdata/Indian/Cocos.

1


2
3


4
5
6
1
2
3


4
5




+
+
-
-
+
+
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Asia/Yangon)]} {
    LoadTimeZoneFile Asia/Yangon

set TZData(:Indian/Cocos) {
}
set TZData(:Indian/Cocos) $TZData(:Asia/Yangon)
    {-9223372036854775808 23260 0 LMT}
    {-2209012060 23400 0 +0630}
}

Changes to library/tzdata/Indian/Kerguelen.

1


2
3


4
5
6
1
2
3


4
5




+
+
-
-
+
+
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Indian/Maldives)]} {
    LoadTimeZoneFile Indian/Maldives

set TZData(:Indian/Kerguelen) {
}
set TZData(:Indian/Kerguelen) $TZData(:Indian/Maldives)
    {-9223372036854775808 0 0 -00}
    {-631152000 18000 0 +05}
}

Changes to library/tzdata/Indian/Mahe.

1


2
3


4
5
6
1
2
3


4
5




+
+
-
-
+
+
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Asia/Dubai)]} {
    LoadTimeZoneFile Asia/Dubai

set TZData(:Indian/Mahe) {
}
set TZData(:Indian/Mahe) $TZData(:Asia/Dubai)
    {-9223372036854775808 13308 0 LMT}
    {-2006653308 14400 0 +04}
}

Changes to library/tzdata/Indian/Maldives.

1
2
3
4
5
6

7
1
2
3
4
5

6
7





-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Indian/Maldives) {
    {-9223372036854775808 17640 0 LMT}
    {-2840158440 17640 0 MMT}
    {-315636840 18000 0 +05}
    {-315636840 18000 0 +0500}
}

Changes to library/tzdata/Indian/Mauritius.

1
2
3
4
5
6
7
8
9





10
1
2
3
4





5
6
7
8
9
10




-
-
-
-
-
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Indian/Mauritius) {
    {-9223372036854775808 13800 0 LMT}
    {-1988164200 14400 0 +04}
    {403041600 18000 1 +04}
    {417034800 14400 0 +04}
    {1224972000 18000 1 +04}
    {1238274000 14400 0 +04}
    {-1988164200 14400 0 +0400}
    {403041600 18000 1 +0500}
    {417034800 14400 0 +0400}
    {1224972000 18000 1 +0500}
    {1238274000 14400 0 +0400}
}

Changes to library/tzdata/Indian/Reunion.

1


2
3


4
5
6
1
2
3


4
5




+
+
-
-
+
+
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Asia/Dubai)]} {
    LoadTimeZoneFile Asia/Dubai

set TZData(:Indian/Reunion) {
}
set TZData(:Indian/Reunion) $TZData(:Asia/Dubai)
    {-9223372036854775808 13312 0 LMT}
    {-1848886912 14400 0 +04}
}

Changes to library/tzdata/MET.

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
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
1
2
3


4
5







































































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Brussels)]} {
    LoadTimeZoneFile Europe/Brussels

set TZData(:MET) {
}
set TZData(:MET) $TZData(:Europe/Brussels)
    {-9223372036854775808 3600 0 MET}
    {-1693706400 7200 1 MEST}
    {-1680483600 3600 0 MET}
    {-1663455600 7200 1 MEST}
    {-1650150000 3600 0 MET}
    {-1632006000 7200 1 MEST}
    {-1618700400 3600 0 MET}
    {-938905200 7200 1 MEST}
    {-857257200 3600 0 MET}
    {-844556400 7200 1 MEST}
    {-828226800 3600 0 MET}
    {-812502000 7200 1 MEST}
    {-796777200 3600 0 MET}
    {-781052400 7200 1 MEST}
    {-766623600 3600 0 MET}
    {228877200 7200 1 MEST}
    {243997200 3600 0 MET}
    {260326800 7200 1 MEST}
    {276051600 3600 0 MET}
    {291776400 7200 1 MEST}
    {307501200 3600 0 MET}
    {323830800 7200 1 MEST}
    {338950800 3600 0 MET}
    {354675600 7200 1 MEST}
    {370400400 3600 0 MET}
    {386125200 7200 1 MEST}
    {401850000 3600 0 MET}
    {417574800 7200 1 MEST}
    {433299600 3600 0 MET}
    {449024400 7200 1 MEST}
    {465354000 3600 0 MET}
    {481078800 7200 1 MEST}
    {496803600 3600 0 MET}
    {512528400 7200 1 MEST}
    {528253200 3600 0 MET}
    {543978000 7200 1 MEST}
    {559702800 3600 0 MET}
    {575427600 7200 1 MEST}
    {591152400 3600 0 MET}
    {606877200 7200 1 MEST}
    {622602000 3600 0 MET}
    {638326800 7200 1 MEST}
    {654656400 3600 0 MET}
    {670381200 7200 1 MEST}
    {686106000 3600 0 MET}
    {701830800 7200 1 MEST}
    {717555600 3600 0 MET}
    {733280400 7200 1 MEST}
    {749005200 3600 0 MET}
    {764730000 7200 1 MEST}
    {780454800 3600 0 MET}
    {796179600 7200 1 MEST}
    {811904400 3600 0 MET}
    {828234000 7200 1 MEST}
    {846378000 3600 0 MET}
    {859683600 7200 1 MEST}
    {877827600 3600 0 MET}
    {891133200 7200 1 MEST}
    {909277200 3600 0 MET}
    {922582800 7200 1 MEST}
    {941331600 3600 0 MET}
    {954032400 7200 1 MEST}
    {972781200 3600 0 MET}
    {985482000 7200 1 MEST}
    {1004230800 3600 0 MET}
    {1017536400 7200 1 MEST}
    {1035680400 3600 0 MET}
    {1048986000 7200 1 MEST}
    {1067130000 3600 0 MET}
    {1080435600 7200 1 MEST}
    {1099184400 3600 0 MET}
    {1111885200 7200 1 MEST}
    {1130634000 3600 0 MET}
    {1143334800 7200 1 MEST}
    {1162083600 3600 0 MET}
    {1174784400 7200 1 MEST}
    {1193533200 3600 0 MET}
    {1206838800 7200 1 MEST}
    {1224982800 3600 0 MET}
    {1238288400 7200 1 MEST}
    {1256432400 3600 0 MET}
    {1269738000 7200 1 MEST}
    {1288486800 3600 0 MET}
    {1301187600 7200 1 MEST}
    {1319936400 3600 0 MET}
    {1332637200 7200 1 MEST}
    {1351386000 3600 0 MET}
    {1364691600 7200 1 MEST}
    {1382835600 3600 0 MET}
    {1396141200 7200 1 MEST}
    {1414285200 3600 0 MET}
    {1427590800 7200 1 MEST}
    {1445734800 3600 0 MET}
    {1459040400 7200 1 MEST}
    {1477789200 3600 0 MET}
    {1490490000 7200 1 MEST}
    {1509238800 3600 0 MET}
    {1521939600 7200 1 MEST}
    {1540688400 3600 0 MET}
    {1553994000 7200 1 MEST}
    {1572138000 3600 0 MET}
    {1585443600 7200 1 MEST}
    {1603587600 3600 0 MET}
    {1616893200 7200 1 MEST}
    {1635642000 3600 0 MET}
    {1648342800 7200 1 MEST}
    {1667091600 3600 0 MET}
    {1679792400 7200 1 MEST}
    {1698541200 3600 0 MET}
    {1711846800 7200 1 MEST}
    {1729990800 3600 0 MET}
    {1743296400 7200 1 MEST}
    {1761440400 3600 0 MET}
    {1774746000 7200 1 MEST}
    {1792890000 3600 0 MET}
    {1806195600 7200 1 MEST}
    {1824944400 3600 0 MET}
    {1837645200 7200 1 MEST}
    {1856394000 3600 0 MET}
    {1869094800 7200 1 MEST}
    {1887843600 3600 0 MET}
    {1901149200 7200 1 MEST}
    {1919293200 3600 0 MET}
    {1932598800 7200 1 MEST}
    {1950742800 3600 0 MET}
    {1964048400 7200 1 MEST}
    {1982797200 3600 0 MET}
    {1995498000 7200 1 MEST}
    {2014246800 3600 0 MET}
    {2026947600 7200 1 MEST}
    {2045696400 3600 0 MET}
    {2058397200 7200 1 MEST}
    {2077146000 3600 0 MET}
    {2090451600 7200 1 MEST}
    {2108595600 3600 0 MET}
    {2121901200 7200 1 MEST}
    {2140045200 3600 0 MET}
    {2153350800 7200 1 MEST}
    {2172099600 3600 0 MET}
    {2184800400 7200 1 MEST}
    {2203549200 3600 0 MET}
    {2216250000 7200 1 MEST}
    {2234998800 3600 0 MET}
    {2248304400 7200 1 MEST}
    {2266448400 3600 0 MET}
    {2279754000 7200 1 MEST}
    {2297898000 3600 0 MET}
    {2311203600 7200 1 MEST}
    {2329347600 3600 0 MET}
    {2342653200 7200 1 MEST}
    {2361402000 3600 0 MET}
    {2374102800 7200 1 MEST}
    {2392851600 3600 0 MET}
    {2405552400 7200 1 MEST}
    {2424301200 3600 0 MET}
    {2437606800 7200 1 MEST}
    {2455750800 3600 0 MET}
    {2469056400 7200 1 MEST}
    {2487200400 3600 0 MET}
    {2500506000 7200 1 MEST}
    {2519254800 3600 0 MET}
    {2531955600 7200 1 MEST}
    {2550704400 3600 0 MET}
    {2563405200 7200 1 MEST}
    {2582154000 3600 0 MET}
    {2595459600 7200 1 MEST}
    {2613603600 3600 0 MET}
    {2626909200 7200 1 MEST}
    {2645053200 3600 0 MET}
    {2658358800 7200 1 MEST}
    {2676502800 3600 0 MET}
    {2689808400 7200 1 MEST}
    {2708557200 3600 0 MET}
    {2721258000 7200 1 MEST}
    {2740006800 3600 0 MET}
    {2752707600 7200 1 MEST}
    {2771456400 3600 0 MET}
    {2784762000 7200 1 MEST}
    {2802906000 3600 0 MET}
    {2816211600 7200 1 MEST}
    {2834355600 3600 0 MET}
    {2847661200 7200 1 MEST}
    {2866410000 3600 0 MET}
    {2879110800 7200 1 MEST}
    {2897859600 3600 0 MET}
    {2910560400 7200 1 MEST}
    {2929309200 3600 0 MET}
    {2942010000 7200 1 MEST}
    {2960758800 3600 0 MET}
    {2974064400 7200 1 MEST}
    {2992208400 3600 0 MET}
    {3005514000 7200 1 MEST}
    {3023658000 3600 0 MET}
    {3036963600 7200 1 MEST}
    {3055712400 3600 0 MET}
    {3068413200 7200 1 MEST}
    {3087162000 3600 0 MET}
    {3099862800 7200 1 MEST}
    {3118611600 3600 0 MET}
    {3131917200 7200 1 MEST}
    {3150061200 3600 0 MET}
    {3163366800 7200 1 MEST}
    {3181510800 3600 0 MET}
    {3194816400 7200 1 MEST}
    {3212960400 3600 0 MET}
    {3226266000 7200 1 MEST}
    {3245014800 3600 0 MET}
    {3257715600 7200 1 MEST}
    {3276464400 3600 0 MET}
    {3289165200 7200 1 MEST}
    {3307914000 3600 0 MET}
    {3321219600 7200 1 MEST}
    {3339363600 3600 0 MET}
    {3352669200 7200 1 MEST}
    {3370813200 3600 0 MET}
    {3384118800 7200 1 MEST}
    {3402867600 3600 0 MET}
    {3415568400 7200 1 MEST}
    {3434317200 3600 0 MET}
    {3447018000 7200 1 MEST}
    {3465766800 3600 0 MET}
    {3479072400 7200 1 MEST}
    {3497216400 3600 0 MET}
    {3510522000 7200 1 MEST}
    {3528666000 3600 0 MET}
    {3541971600 7200 1 MEST}
    {3560115600 3600 0 MET}
    {3573421200 7200 1 MEST}
    {3592170000 3600 0 MET}
    {3604870800 7200 1 MEST}
    {3623619600 3600 0 MET}
    {3636320400 7200 1 MEST}
    {3655069200 3600 0 MET}
    {3668374800 7200 1 MEST}
    {3686518800 3600 0 MET}
    {3699824400 7200 1 MEST}
    {3717968400 3600 0 MET}
    {3731274000 7200 1 MEST}
    {3750022800 3600 0 MET}
    {3762723600 7200 1 MEST}
    {3781472400 3600 0 MET}
    {3794173200 7200 1 MEST}
    {3812922000 3600 0 MET}
    {3825622800 7200 1 MEST}
    {3844371600 3600 0 MET}
    {3857677200 7200 1 MEST}
    {3875821200 3600 0 MET}
    {3889126800 7200 1 MEST}
    {3907270800 3600 0 MET}
    {3920576400 7200 1 MEST}
    {3939325200 3600 0 MET}
    {3952026000 7200 1 MEST}
    {3970774800 3600 0 MET}
    {3983475600 7200 1 MEST}
    {4002224400 3600 0 MET}
    {4015530000 7200 1 MEST}
    {4033674000 3600 0 MET}
    {4046979600 7200 1 MEST}
    {4065123600 3600 0 MET}
    {4078429200 7200 1 MEST}
    {4096573200 3600 0 MET}
}

Changes to library/tzdata/MST.

1


2
3


4
5
1
2
3


4
5



+
+
-
-
+
+
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Phoenix)]} {
    LoadTimeZoneFile America/Phoenix

set TZData(:MST) {
}
set TZData(:MST) $TZData(:America/Phoenix)
    {-9223372036854775808 -25200 0 MST}
}

Changes to library/tzdata/MST7MDT.

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
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
1
2
3


4
5




















































































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Denver)]} {
    LoadTimeZoneFile America/Denver

set TZData(:MST7MDT) {
}
set TZData(:MST7MDT) $TZData(:America/Denver)
    {-9223372036854775808 -25200 0 MST}
    {-1633273200 -21600 1 MDT}
    {-1615132800 -25200 0 MST}
    {-1601823600 -21600 1 MDT}
    {-1583683200 -25200 0 MST}
    {-880210800 -21600 1 MWT}
    {-769395600 -21600 1 MPT}
    {-765388800 -25200 0 MST}
    {-84380400 -21600 1 MDT}
    {-68659200 -25200 0 MST}
    {-52930800 -21600 1 MDT}
    {-37209600 -25200 0 MST}
    {-21481200 -21600 1 MDT}
    {-5760000 -25200 0 MST}
    {9968400 -21600 1 MDT}
    {25689600 -25200 0 MST}
    {41418000 -21600 1 MDT}
    {57744000 -25200 0 MST}
    {73472400 -21600 1 MDT}
    {89193600 -25200 0 MST}
    {104922000 -21600 1 MDT}
    {120643200 -25200 0 MST}
    {126694800 -21600 1 MDT}
    {152092800 -25200 0 MST}
    {162378000 -21600 1 MDT}
    {183542400 -25200 0 MST}
    {199270800 -21600 1 MDT}
    {215596800 -25200 0 MST}
    {230720400 -21600 1 MDT}
    {247046400 -25200 0 MST}
    {262774800 -21600 1 MDT}
    {278496000 -25200 0 MST}
    {294224400 -21600 1 MDT}
    {309945600 -25200 0 MST}
    {325674000 -21600 1 MDT}
    {341395200 -25200 0 MST}
    {357123600 -21600 1 MDT}
    {372844800 -25200 0 MST}
    {388573200 -21600 1 MDT}
    {404899200 -25200 0 MST}
    {420022800 -21600 1 MDT}
    {436348800 -25200 0 MST}
    {452077200 -21600 1 MDT}
    {467798400 -25200 0 MST}
    {483526800 -21600 1 MDT}
    {499248000 -25200 0 MST}
    {514976400 -21600 1 MDT}
    {530697600 -25200 0 MST}
    {544611600 -21600 1 MDT}
    {562147200 -25200 0 MST}
    {576061200 -21600 1 MDT}
    {594201600 -25200 0 MST}
    {607510800 -21600 1 MDT}
    {625651200 -25200 0 MST}
    {638960400 -21600 1 MDT}
    {657100800 -25200 0 MST}
    {671014800 -21600 1 MDT}
    {688550400 -25200 0 MST}
    {702464400 -21600 1 MDT}
    {720000000 -25200 0 MST}
    {733914000 -21600 1 MDT}
    {752054400 -25200 0 MST}
    {765363600 -21600 1 MDT}
    {783504000 -25200 0 MST}
    {796813200 -21600 1 MDT}
    {814953600 -25200 0 MST}
    {828867600 -21600 1 MDT}
    {846403200 -25200 0 MST}
    {860317200 -21600 1 MDT}
    {877852800 -25200 0 MST}
    {891766800 -21600 1 MDT}
    {909302400 -25200 0 MST}
    {923216400 -21600 1 MDT}
    {941356800 -25200 0 MST}
    {954666000 -21600 1 MDT}
    {972806400 -25200 0 MST}
    {986115600 -21600 1 MDT}
    {1004256000 -25200 0 MST}
    {1018170000 -21600 1 MDT}
    {1035705600 -25200 0 MST}
    {1049619600 -21600 1 MDT}
    {1067155200 -25200 0 MST}
    {1081069200 -21600 1 MDT}
    {1099209600 -25200 0 MST}
    {1112518800 -21600 1 MDT}
    {1130659200 -25200 0 MST}
    {1143968400 -21600 1 MDT}
    {1162108800 -25200 0 MST}
    {1173603600 -21600 1 MDT}
    {1194163200 -25200 0 MST}
    {1205053200 -21600 1 MDT}
    {1225612800 -25200 0 MST}
    {1236502800 -21600 1 MDT}
    {1257062400 -25200 0 MST}
    {1268557200 -21600 1 MDT}
    {1289116800 -25200 0 MST}
    {1300006800 -21600 1 MDT}
    {1320566400 -25200 0 MST}
    {1331456400 -21600 1 MDT}
    {1352016000 -25200 0 MST}
    {1362906000 -21600 1 MDT}
    {1383465600 -25200 0 MST}
    {1394355600 -21600 1 MDT}
    {1414915200 -25200 0 MST}
    {1425805200 -21600 1 MDT}
    {1446364800 -25200 0 MST}
    {1457859600 -21600 1 MDT}
    {1478419200 -25200 0 MST}
    {1489309200 -21600 1 MDT}
    {1509868800 -25200 0 MST}
    {1520758800 -21600 1 MDT}
    {1541318400 -25200 0 MST}
    {1552208400 -21600 1 MDT}
    {1572768000 -25200 0 MST}
    {1583658000 -21600 1 MDT}
    {1604217600 -25200 0 MST}
    {1615712400 -21600 1 MDT}
    {1636272000 -25200 0 MST}
    {1647162000 -21600 1 MDT}
    {1667721600 -25200 0 MST}
    {1678611600 -21600 1 MDT}
    {1699171200 -25200 0 MST}
    {1710061200 -21600 1 MDT}
    {1730620800 -25200 0 MST}
    {1741510800 -21600 1 MDT}
    {1762070400 -25200 0 MST}
    {1772960400 -21600 1 MDT}
    {1793520000 -25200 0 MST}
    {1805014800 -21600 1 MDT}
    {1825574400 -25200 0 MST}
    {1836464400 -21600 1 MDT}
    {1857024000 -25200 0 MST}
    {1867914000 -21600 1 MDT}
    {1888473600 -25200 0 MST}
    {1899363600 -21600 1 MDT}
    {1919923200 -25200 0 MST}
    {1930813200 -21600 1 MDT}
    {1951372800 -25200 0 MST}
    {1962867600 -21600 1 MDT}
    {1983427200 -25200 0 MST}
    {1994317200 -21600 1 MDT}
    {2014876800 -25200 0 MST}
    {2025766800 -21600 1 MDT}
    {2046326400 -25200 0 MST}
    {2057216400 -21600 1 MDT}
    {2077776000 -25200 0 MST}
    {2088666000 -21600 1 MDT}
    {2109225600 -25200 0 MST}
    {2120115600 -21600 1 MDT}
    {2140675200 -25200 0 MST}
    {2152170000 -21600 1 MDT}
    {2172729600 -25200 0 MST}
    {2183619600 -21600 1 MDT}
    {2204179200 -25200 0 MST}
    {2215069200 -21600 1 MDT}
    {2235628800 -25200 0 MST}
    {2246518800 -21600 1 MDT}
    {2267078400 -25200 0 MST}
    {2277968400 -21600 1 MDT}
    {2298528000 -25200 0 MST}
    {2309418000 -21600 1 MDT}
    {2329977600 -25200 0 MST}
    {2341472400 -21600 1 MDT}
    {2362032000 -25200 0 MST}
    {2372922000 -21600 1 MDT}
    {2393481600 -25200 0 MST}
    {2404371600 -21600 1 MDT}
    {2424931200 -25200 0 MST}
    {2435821200 -21600 1 MDT}
    {2456380800 -25200 0 MST}
    {2467270800 -21600 1 MDT}
    {2487830400 -25200 0 MST}
    {2499325200 -21600 1 MDT}
    {2519884800 -25200 0 MST}
    {2530774800 -21600 1 MDT}
    {2551334400 -25200 0 MST}
    {2562224400 -21600 1 MDT}
    {2582784000 -25200 0 MST}
    {2593674000 -21600 1 MDT}
    {2614233600 -25200 0 MST}
    {2625123600 -21600 1 MDT}
    {2645683200 -25200 0 MST}
    {2656573200 -21600 1 MDT}
    {2677132800 -25200 0 MST}
    {2688627600 -21600 1 MDT}
    {2709187200 -25200 0 MST}
    {2720077200 -21600 1 MDT}
    {2740636800 -25200 0 MST}
    {2751526800 -21600 1 MDT}
    {2772086400 -25200 0 MST}
    {2782976400 -21600 1 MDT}
    {2803536000 -25200 0 MST}
    {2814426000 -21600 1 MDT}
    {2834985600 -25200 0 MST}
    {2846480400 -21600 1 MDT}
    {2867040000 -25200 0 MST}
    {2877930000 -21600 1 MDT}
    {2898489600 -25200 0 MST}
    {2909379600 -21600 1 MDT}
    {2929939200 -25200 0 MST}
    {2940829200 -21600 1 MDT}
    {2961388800 -25200 0 MST}
    {2972278800 -21600 1 MDT}
    {2992838400 -25200 0 MST}
    {3003728400 -21600 1 MDT}
    {3024288000 -25200 0 MST}
    {3035782800 -21600 1 MDT}
    {3056342400 -25200 0 MST}
    {3067232400 -21600 1 MDT}
    {3087792000 -25200 0 MST}
    {3098682000 -21600 1 MDT}
    {3119241600 -25200 0 MST}
    {3130131600 -21600 1 MDT}
    {3150691200 -25200 0 MST}
    {3161581200 -21600 1 MDT}
    {3182140800 -25200 0 MST}
    {3193030800 -21600 1 MDT}
    {3213590400 -25200 0 MST}
    {3225085200 -21600 1 MDT}
    {3245644800 -25200 0 MST}
    {3256534800 -21600 1 MDT}
    {3277094400 -25200 0 MST}
    {3287984400 -21600 1 MDT}
    {3308544000 -25200 0 MST}
    {3319434000 -21600 1 MDT}
    {3339993600 -25200 0 MST}
    {3350883600 -21600 1 MDT}
    {3371443200 -25200 0 MST}
    {3382938000 -21600 1 MDT}
    {3403497600 -25200 0 MST}
    {3414387600 -21600 1 MDT}
    {3434947200 -25200 0 MST}
    {3445837200 -21600 1 MDT}
    {3466396800 -25200 0 MST}
    {3477286800 -21600 1 MDT}
    {3497846400 -25200 0 MST}
    {3508736400 -21600 1 MDT}
    {3529296000 -25200 0 MST}
    {3540186000 -21600 1 MDT}
    {3560745600 -25200 0 MST}
    {3572240400 -21600 1 MDT}
    {3592800000 -25200 0 MST}
    {3603690000 -21600 1 MDT}
    {3624249600 -25200 0 MST}
    {3635139600 -21600 1 MDT}
    {3655699200 -25200 0 MST}
    {3666589200 -21600 1 MDT}
    {3687148800 -25200 0 MST}
    {3698038800 -21600 1 MDT}
    {3718598400 -25200 0 MST}
    {3730093200 -21600 1 MDT}
    {3750652800 -25200 0 MST}
    {3761542800 -21600 1 MDT}
    {3782102400 -25200 0 MST}
    {3792992400 -21600 1 MDT}
    {3813552000 -25200 0 MST}
    {3824442000 -21600 1 MDT}
    {3845001600 -25200 0 MST}
    {3855891600 -21600 1 MDT}
    {3876451200 -25200 0 MST}
    {3887341200 -21600 1 MDT}
    {3907900800 -25200 0 MST}
    {3919395600 -21600 1 MDT}
    {3939955200 -25200 0 MST}
    {3950845200 -21600 1 MDT}
    {3971404800 -25200 0 MST}
    {3982294800 -21600 1 MDT}
    {4002854400 -25200 0 MST}
    {4013744400 -21600 1 MDT}
    {4034304000 -25200 0 MST}
    {4045194000 -21600 1 MDT}
    {4065753600 -25200 0 MST}
    {4076643600 -21600 1 MDT}
    {4097203200 -25200 0 MST}
}

Changes to library/tzdata/PST8PDT.

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
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
1
2
3


4
5




















































































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Los_Angeles)]} {
    LoadTimeZoneFile America/Los_Angeles

set TZData(:PST8PDT) {
}
set TZData(:PST8PDT) $TZData(:America/Los_Angeles)
    {-9223372036854775808 -28800 0 PST}
    {-1633269600 -25200 1 PDT}
    {-1615129200 -28800 0 PST}
    {-1601820000 -25200 1 PDT}
    {-1583679600 -28800 0 PST}
    {-880207200 -25200 1 PWT}
    {-769395600 -25200 1 PPT}
    {-765385200 -28800 0 PST}
    {-84376800 -25200 1 PDT}
    {-68655600 -28800 0 PST}
    {-52927200 -25200 1 PDT}
    {-37206000 -28800 0 PST}
    {-21477600 -25200 1 PDT}
    {-5756400 -28800 0 PST}
    {9972000 -25200 1 PDT}
    {25693200 -28800 0 PST}
    {41421600 -25200 1 PDT}
    {57747600 -28800 0 PST}
    {73476000 -25200 1 PDT}
    {89197200 -28800 0 PST}
    {104925600 -25200 1 PDT}
    {120646800 -28800 0 PST}
    {126698400 -25200 1 PDT}
    {152096400 -28800 0 PST}
    {162381600 -25200 1 PDT}
    {183546000 -28800 0 PST}
    {199274400 -25200 1 PDT}
    {215600400 -28800 0 PST}
    {230724000 -25200 1 PDT}
    {247050000 -28800 0 PST}
    {262778400 -25200 1 PDT}
    {278499600 -28800 0 PST}
    {294228000 -25200 1 PDT}
    {309949200 -28800 0 PST}
    {325677600 -25200 1 PDT}
    {341398800 -28800 0 PST}
    {357127200 -25200 1 PDT}
    {372848400 -28800 0 PST}
    {388576800 -25200 1 PDT}
    {404902800 -28800 0 PST}
    {420026400 -25200 1 PDT}
    {436352400 -28800 0 PST}
    {452080800 -25200 1 PDT}
    {467802000 -28800 0 PST}
    {483530400 -25200 1 PDT}
    {499251600 -28800 0 PST}
    {514980000 -25200 1 PDT}
    {530701200 -28800 0 PST}
    {544615200 -25200 1 PDT}
    {562150800 -28800 0 PST}
    {576064800 -25200 1 PDT}
    {594205200 -28800 0 PST}
    {607514400 -25200 1 PDT}
    {625654800 -28800 0 PST}
    {638964000 -25200 1 PDT}
    {657104400 -28800 0 PST}
    {671018400 -25200 1 PDT}
    {688554000 -28800 0 PST}
    {702468000 -25200 1 PDT}
    {720003600 -28800 0 PST}
    {733917600 -25200 1 PDT}
    {752058000 -28800 0 PST}
    {765367200 -25200 1 PDT}
    {783507600 -28800 0 PST}
    {796816800 -25200 1 PDT}
    {814957200 -28800 0 PST}
    {828871200 -25200 1 PDT}
    {846406800 -28800 0 PST}
    {860320800 -25200 1 PDT}
    {877856400 -28800 0 PST}
    {891770400 -25200 1 PDT}
    {909306000 -28800 0 PST}
    {923220000 -25200 1 PDT}
    {941360400 -28800 0 PST}
    {954669600 -25200 1 PDT}
    {972810000 -28800 0 PST}
    {986119200 -25200 1 PDT}
    {1004259600 -28800 0 PST}
    {1018173600 -25200 1 PDT}
    {1035709200 -28800 0 PST}
    {1049623200 -25200 1 PDT}
    {1067158800 -28800 0 PST}
    {1081072800 -25200 1 PDT}
    {1099213200 -28800 0 PST}
    {1112522400 -25200 1 PDT}
    {1130662800 -28800 0 PST}
    {1143972000 -25200 1 PDT}
    {1162112400 -28800 0 PST}
    {1173607200 -25200 1 PDT}
    {1194166800 -28800 0 PST}
    {1205056800 -25200 1 PDT}
    {1225616400 -28800 0 PST}
    {1236506400 -25200 1 PDT}
    {1257066000 -28800 0 PST}
    {1268560800 -25200 1 PDT}
    {1289120400 -28800 0 PST}
    {1300010400 -25200 1 PDT}
    {1320570000 -28800 0 PST}
    {1331460000 -25200 1 PDT}
    {1352019600 -28800 0 PST}
    {1362909600 -25200 1 PDT}
    {1383469200 -28800 0 PST}
    {1394359200 -25200 1 PDT}
    {1414918800 -28800 0 PST}
    {1425808800 -25200 1 PDT}
    {1446368400 -28800 0 PST}
    {1457863200 -25200 1 PDT}
    {1478422800 -28800 0 PST}
    {1489312800 -25200 1 PDT}
    {1509872400 -28800 0 PST}
    {1520762400 -25200 1 PDT}
    {1541322000 -28800 0 PST}
    {1552212000 -25200 1 PDT}
    {1572771600 -28800 0 PST}
    {1583661600 -25200 1 PDT}
    {1604221200 -28800 0 PST}
    {1615716000 -25200 1 PDT}
    {1636275600 -28800 0 PST}
    {1647165600 -25200 1 PDT}
    {1667725200 -28800 0 PST}
    {1678615200 -25200 1 PDT}
    {1699174800 -28800 0 PST}
    {1710064800 -25200 1 PDT}
    {1730624400 -28800 0 PST}
    {1741514400 -25200 1 PDT}
    {1762074000 -28800 0 PST}
    {1772964000 -25200 1 PDT}
    {1793523600 -28800 0 PST}
    {1805018400 -25200 1 PDT}
    {1825578000 -28800 0 PST}
    {1836468000 -25200 1 PDT}
    {1857027600 -28800 0 PST}
    {1867917600 -25200 1 PDT}
    {1888477200 -28800 0 PST}
    {1899367200 -25200 1 PDT}
    {1919926800 -28800 0 PST}
    {1930816800 -25200 1 PDT}
    {1951376400 -28800 0 PST}
    {1962871200 -25200 1 PDT}
    {1983430800 -28800 0 PST}
    {1994320800 -25200 1 PDT}
    {2014880400 -28800 0 PST}
    {2025770400 -25200 1 PDT}
    {2046330000 -28800 0 PST}
    {2057220000 -25200 1 PDT}
    {2077779600 -28800 0 PST}
    {2088669600 -25200 1 PDT}
    {2109229200 -28800 0 PST}
    {2120119200 -25200 1 PDT}
    {2140678800 -28800 0 PST}
    {2152173600 -25200 1 PDT}
    {2172733200 -28800 0 PST}
    {2183623200 -25200 1 PDT}
    {2204182800 -28800 0 PST}
    {2215072800 -25200 1 PDT}
    {2235632400 -28800 0 PST}
    {2246522400 -25200 1 PDT}
    {2267082000 -28800 0 PST}
    {2277972000 -25200 1 PDT}
    {2298531600 -28800 0 PST}
    {2309421600 -25200 1 PDT}
    {2329981200 -28800 0 PST}
    {2341476000 -25200 1 PDT}
    {2362035600 -28800 0 PST}
    {2372925600 -25200 1 PDT}
    {2393485200 -28800 0 PST}
    {2404375200 -25200 1 PDT}
    {2424934800 -28800 0 PST}
    {2435824800 -25200 1 PDT}
    {2456384400 -28800 0 PST}
    {2467274400 -25200 1 PDT}
    {2487834000 -28800 0 PST}
    {2499328800 -25200 1 PDT}
    {2519888400 -28800 0 PST}
    {2530778400 -25200 1 PDT}
    {2551338000 -28800 0 PST}
    {2562228000 -25200 1 PDT}
    {2582787600 -28800 0 PST}
    {2593677600 -25200 1 PDT}
    {2614237200 -28800 0 PST}
    {2625127200 -25200 1 PDT}
    {2645686800 -28800 0 PST}
    {2656576800 -25200 1 PDT}
    {2677136400 -28800 0 PST}
    {2688631200 -25200 1 PDT}
    {2709190800 -28800 0 PST}
    {2720080800 -25200 1 PDT}
    {2740640400 -28800 0 PST}
    {2751530400 -25200 1 PDT}
    {2772090000 -28800 0 PST}
    {2782980000 -25200 1 PDT}
    {2803539600 -28800 0 PST}
    {2814429600 -25200 1 PDT}
    {2834989200 -28800 0 PST}
    {2846484000 -25200 1 PDT}
    {2867043600 -28800 0 PST}
    {2877933600 -25200 1 PDT}
    {2898493200 -28800 0 PST}
    {2909383200 -25200 1 PDT}
    {2929942800 -28800 0 PST}
    {2940832800 -25200 1 PDT}
    {2961392400 -28800 0 PST}
    {2972282400 -25200 1 PDT}
    {2992842000 -28800 0 PST}
    {3003732000 -25200 1 PDT}
    {3024291600 -28800 0 PST}
    {3035786400 -25200 1 PDT}
    {3056346000 -28800 0 PST}
    {3067236000 -25200 1 PDT}
    {3087795600 -28800 0 PST}
    {3098685600 -25200 1 PDT}
    {3119245200 -28800 0 PST}
    {3130135200 -25200 1 PDT}
    {3150694800 -28800 0 PST}
    {3161584800 -25200 1 PDT}
    {3182144400 -28800 0 PST}
    {3193034400 -25200 1 PDT}
    {3213594000 -28800 0 PST}
    {3225088800 -25200 1 PDT}
    {3245648400 -28800 0 PST}
    {3256538400 -25200 1 PDT}
    {3277098000 -28800 0 PST}
    {3287988000 -25200 1 PDT}
    {3308547600 -28800 0 PST}
    {3319437600 -25200 1 PDT}
    {3339997200 -28800 0 PST}
    {3350887200 -25200 1 PDT}
    {3371446800 -28800 0 PST}
    {3382941600 -25200 1 PDT}
    {3403501200 -28800 0 PST}
    {3414391200 -25200 1 PDT}
    {3434950800 -28800 0 PST}
    {3445840800 -25200 1 PDT}
    {3466400400 -28800 0 PST}
    {3477290400 -25200 1 PDT}
    {3497850000 -28800 0 PST}
    {3508740000 -25200 1 PDT}
    {3529299600 -28800 0 PST}
    {3540189600 -25200 1 PDT}
    {3560749200 -28800 0 PST}
    {3572244000 -25200 1 PDT}
    {3592803600 -28800 0 PST}
    {3603693600 -25200 1 PDT}
    {3624253200 -28800 0 PST}
    {3635143200 -25200 1 PDT}
    {3655702800 -28800 0 PST}
    {3666592800 -25200 1 PDT}
    {3687152400 -28800 0 PST}
    {3698042400 -25200 1 PDT}
    {3718602000 -28800 0 PST}
    {3730096800 -25200 1 PDT}
    {3750656400 -28800 0 PST}
    {3761546400 -25200 1 PDT}
    {3782106000 -28800 0 PST}
    {3792996000 -25200 1 PDT}
    {3813555600 -28800 0 PST}
    {3824445600 -25200 1 PDT}
    {3845005200 -28800 0 PST}
    {3855895200 -25200 1 PDT}
    {3876454800 -28800 0 PST}
    {3887344800 -25200 1 PDT}
    {3907904400 -28800 0 PST}
    {3919399200 -25200 1 PDT}
    {3939958800 -28800 0 PST}
    {3950848800 -25200 1 PDT}
    {3971408400 -28800 0 PST}
    {3982298400 -25200 1 PDT}
    {4002858000 -28800 0 PST}
    {4013748000 -25200 1 PDT}
    {4034307600 -28800 0 PST}
    {4045197600 -25200 1 PDT}
    {4065757200 -28800 0 PST}
    {4076647200 -25200 1 PDT}
    {4097206800 -28800 0 PST}
}

Changes to library/tzdata/Pacific/Apia.

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
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
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
30



















31





-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Apia) {
    {-9223372036854775808 45184 0 LMT}
    {-2445424384 -41216 0 LMT}
    {-1861878784 -41400 0 -1130}
    {-631110600 -39600 0 -11}
    {1285498800 -36000 1 -11}
    {1301752800 -39600 0 -11}
    {1316872800 -36000 1 -11}
    {1325239200 50400 0 +13}
    {1333202400 46800 0 +13}
    {1348927200 50400 1 +13}
    {1365256800 46800 0 +13}
    {1380376800 50400 1 +13}
    {1396706400 46800 0 +13}
    {1411826400 50400 1 +13}
    {1428156000 46800 0 +13}
    {-1861878784 -41400 0 -1230}
    {-631110600 -39600 0 -1100}
    {1285498800 -36000 1 -1000}
    {1301752800 -39600 0 -1100}
    {1316872800 -36000 1 -1000}
    {1325239200 50400 0 +1400}
    {1333202400 46800 0 +1300}
    {1348927200 50400 1 +1400}
    {1365256800 46800 0 +1300}
    {1380376800 50400 1 +1400}
    {1396706400 46800 0 +1300}
    {1411826400 50400 1 +1400}
    {1428156000 46800 0 +1300}
    {1443276000 50400 1 +13}
    {1459605600 46800 0 +13}
    {1474725600 50400 1 +13}
    {1491055200 46800 0 +13}
    {1506175200 50400 1 +13}
    {1522504800 46800 0 +13}
    {1538229600 50400 1 +13}
    {1554559200 46800 0 +13}
    {1569679200 50400 1 +13}
    {1586008800 46800 0 +13}
    {1601128800 50400 1 +13}
    {1617458400 46800 0 +13}
    {1632578400 50400 1 +13}
    {1648908000 46800 0 +13}
    {1664028000 50400 1 +13}
    {1680357600 46800 0 +13}
    {1695477600 50400 1 +13}
    {1712412000 46800 0 +13}
    {1727532000 50400 1 +13}
    {1743861600 46800 0 +13}
    {1758981600 50400 1 +13}
    {1775311200 46800 0 +13}
    {1790431200 50400 1 +13}
    {1806760800 46800 0 +13}
    {1821880800 50400 1 +13}
    {1838210400 46800 0 +13}
    {1853330400 50400 1 +13}
    {1869660000 46800 0 +13}
    {1885384800 50400 1 +13}
    {1901714400 46800 0 +13}
    {1916834400 50400 1 +13}
    {1933164000 46800 0 +13}
    {1948284000 50400 1 +13}
    {1964613600 46800 0 +13}
    {1979733600 50400 1 +13}
    {1996063200 46800 0 +13}
    {2011183200 50400 1 +13}
    {2027512800 46800 0 +13}
    {2042632800 50400 1 +13}
    {2058962400 46800 0 +13}
    {2074687200 50400 1 +13}
    {2091016800 46800 0 +13}
    {2106136800 50400 1 +13}
    {2122466400 46800 0 +13}
    {2137586400 50400 1 +13}
    {2153916000 46800 0 +13}
    {2169036000 50400 1 +13}
    {2185365600 46800 0 +13}
    {2200485600 50400 1 +13}
    {2216815200 46800 0 +13}
    {2232540000 50400 1 +13}
    {2248869600 46800 0 +13}
    {2263989600 50400 1 +13}
    {2280319200 46800 0 +13}
    {2295439200 50400 1 +13}
    {2311768800 46800 0 +13}
    {2326888800 50400 1 +13}
    {2343218400 46800 0 +13}
    {2358338400 50400 1 +13}
    {2374668000 46800 0 +13}
    {2389788000 50400 1 +13}
    {2406117600 46800 0 +13}
    {2421842400 50400 1 +13}
    {2438172000 46800 0 +13}
    {2453292000 50400 1 +13}
    {2469621600 46800 0 +13}
    {2484741600 50400 1 +13}
    {2501071200 46800 0 +13}
    {2516191200 50400 1 +13}
    {2532520800 46800 0 +13}
    {2547640800 50400 1 +13}
    {2563970400 46800 0 +13}
    {2579090400 50400 1 +13}
    {2596024800 46800 0 +13}
    {2611144800 50400 1 +13}
    {2627474400 46800 0 +13}
    {2642594400 50400 1 +13}
    {2658924000 46800 0 +13}
    {2674044000 50400 1 +13}
    {2690373600 46800 0 +13}
    {2705493600 50400 1 +13}
    {2721823200 46800 0 +13}
    {2736943200 50400 1 +13}
    {2753272800 46800 0 +13}
    {2768997600 50400 1 +13}
    {2785327200 46800 0 +13}
    {2800447200 50400 1 +13}
    {2816776800 46800 0 +13}
    {2831896800 50400 1 +13}
    {2848226400 46800 0 +13}
    {2863346400 50400 1 +13}
    {2879676000 46800 0 +13}
    {2894796000 50400 1 +13}
    {2911125600 46800 0 +13}
    {2926245600 50400 1 +13}
    {2942575200 46800 0 +13}
    {1443276000 50400 1 +1400}
    {1459605600 46800 0 +1300}
    {1474725600 50400 1 +1400}
    {1491055200 46800 0 +1300}
    {2958300000 50400 1 +13}
    {2974629600 46800 0 +13}
    {2989749600 50400 1 +13}
    {3006079200 46800 0 +13}
    {3021199200 50400 1 +13}
    {3037528800 46800 0 +13}
    {3052648800 50400 1 +13}
    {3068978400 46800 0 +13}
    {3084098400 50400 1 +13}
    {3100428000 46800 0 +13}
    {3116152800 50400 1 +13}
    {3132482400 46800 0 +13}
    {3147602400 50400 1 +13}
    {3163932000 46800 0 +13}
    {3179052000 50400 1 +13}
    {3195381600 46800 0 +13}
    {3210501600 50400 1 +13}
    {3226831200 46800 0 +13}
    {3241951200 50400 1 +13}
    {3258280800 46800 0 +13}
    {3273400800 50400 1 +13}
    {3289730400 46800 0 +13}
    {3305455200 50400 1 +13}
    {3321784800 46800 0 +13}
    {1506175200 50400 1 +1400}
    {1522504800 46800 0 +1300}
    {3336904800 50400 1 +13}
    {3353234400 46800 0 +13}
    {3368354400 50400 1 +13}
    {3384684000 46800 0 +13}
    {3399804000 50400 1 +13}
    {3416133600 46800 0 +13}
    {3431253600 50400 1 +13}
    {3447583200 46800 0 +13}
    {3462703200 50400 1 +13}
    {3479637600 46800 0 +13}
    {3494757600 50400 1 +13}
    {3511087200 46800 0 +13}
    {3526207200 50400 1 +13}
    {3542536800 46800 0 +13}
    {3557656800 50400 1 +13}
    {3573986400 46800 0 +13}
    {3589106400 50400 1 +13}
    {3605436000 46800 0 +13}
    {3620556000 50400 1 +13}
    {3636885600 46800 0 +13}
    {3652610400 50400 1 +13}
    {3668940000 46800 0 +13}
    {3684060000 50400 1 +13}
    {3700389600 46800 0 +13}
    {3715509600 50400 1 +13}
    {3731839200 46800 0 +13}
    {3746959200 50400 1 +13}
    {3763288800 46800 0 +13}
    {3778408800 50400 1 +13}
    {3794738400 46800 0 +13}
    {1538229600 50400 1 +1400}
    {1554559200 46800 0 +1300}
    {1569679200 50400 1 +1400}
    {1586008800 46800 0 +1300}
    {1601128800 50400 1 +1400}
    {1617458400 46800 0 +1300}
    {3809858400 50400 1 +13}
    {3826188000 46800 0 +13}
    {3841912800 50400 1 +13}
    {3858242400 46800 0 +13}
    {3873362400 50400 1 +13}
    {3889692000 46800 0 +13}
    {3904812000 50400 1 +13}
    {3921141600 46800 0 +13}
    {3936261600 50400 1 +13}
    {3952591200 46800 0 +13}
    {3967711200 50400 1 +13}
    {3984040800 46800 0 +13}
    {3999765600 50400 1 +13}
    {4016095200 46800 0 +13}
    {4031215200 50400 1 +13}
    {4047544800 46800 0 +13}
    {4062664800 50400 1 +13}
    {4078994400 46800 0 +13}
    {4094114400 50400 1 +13}
}

Changes to library/tzdata/Pacific/Bougainville.

1
2
3
4
5
6
7
8
9




10
1
2
3
4
5




6
7
8
9
10





-
-
-
-
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Bougainville) {
    {-9223372036854775808 37336 0 LMT}
    {-2840178136 35312 0 PMMT}
    {-2366790512 36000 0 +10}
    {-868010400 32400 0 +09}
    {-768906000 36000 0 +10}
    {1419696000 39600 0 +11}
    {-2366790512 36000 0 +1000}
    {-868010400 32400 0 +0900}
    {-768906000 36000 0 +1000}
    {1419696000 39600 0 +1100}
}

Changes to library/tzdata/Pacific/Chatham.

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

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
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
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






-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Chatham) {
    {-9223372036854775808 44028 0 LMT}
    {-3192437628 44100 0 +1215}
    {-757426500 45900 0 +1245}
    {152632800 49500 1 +1245}
    {152632800 49500 1 +1345}
    {162309600 45900 0 +1245}
    {183477600 49500 1 +1245}
    {183477600 49500 1 +1345}
    {194968800 45900 0 +1245}
    {215532000 49500 1 +1245}
    {215532000 49500 1 +1345}
    {226418400 45900 0 +1245}
    {246981600 49500 1 +1245}
    {246981600 49500 1 +1345}
    {257868000 45900 0 +1245}
    {278431200 49500 1 +1245}
    {278431200 49500 1 +1345}
    {289317600 45900 0 +1245}
    {309880800 49500 1 +1245}
    {309880800 49500 1 +1345}
    {320767200 45900 0 +1245}
    {341330400 49500 1 +1245}
    {341330400 49500 1 +1345}
    {352216800 45900 0 +1245}
    {372780000 49500 1 +1245}
    {372780000 49500 1 +1345}
    {384271200 45900 0 +1245}
    {404834400 49500 1 +1245}
    {404834400 49500 1 +1345}
    {415720800 45900 0 +1245}
    {436284000 49500 1 +1245}
    {436284000 49500 1 +1345}
    {447170400 45900 0 +1245}
    {467733600 49500 1 +1245}
    {467733600 49500 1 +1345}
    {478620000 45900 0 +1245}
    {499183200 49500 1 +1245}
    {499183200 49500 1 +1345}
    {510069600 45900 0 +1245}
    {530632800 49500 1 +1245}
    {530632800 49500 1 +1345}
    {541519200 45900 0 +1245}
    {562082400 49500 1 +1245}
    {562082400 49500 1 +1345}
    {573573600 45900 0 +1245}
    {594136800 49500 1 +1245}
    {594136800 49500 1 +1345}
    {605023200 45900 0 +1245}
    {623772000 49500 1 +1245}
    {623772000 49500 1 +1345}
    {637682400 45900 0 +1245}
    {655221600 49500 1 +1245}
    {655221600 49500 1 +1345}
    {669132000 45900 0 +1245}
    {686671200 49500 1 +1245}
    {686671200 49500 1 +1345}
    {700581600 45900 0 +1245}
    {718120800 49500 1 +1245}
    {718120800 49500 1 +1345}
    {732636000 45900 0 +1245}
    {749570400 49500 1 +1245}
    {749570400 49500 1 +1345}
    {764085600 45900 0 +1245}
    {781020000 49500 1 +1245}
    {781020000 49500 1 +1345}
    {795535200 45900 0 +1245}
    {812469600 49500 1 +1245}
    {812469600 49500 1 +1345}
    {826984800 45900 0 +1245}
    {844524000 49500 1 +1245}
    {844524000 49500 1 +1345}
    {858434400 45900 0 +1245}
    {875973600 49500 1 +1245}
    {875973600 49500 1 +1345}
    {889884000 45900 0 +1245}
    {907423200 49500 1 +1245}
    {907423200 49500 1 +1345}
    {921938400 45900 0 +1245}
    {938872800 49500 1 +1245}
    {938872800 49500 1 +1345}
    {953388000 45900 0 +1245}
    {970322400 49500 1 +1245}
    {970322400 49500 1 +1345}
    {984837600 45900 0 +1245}
    {1002376800 49500 1 +1245}
    {1002376800 49500 1 +1345}
    {1016287200 45900 0 +1245}
    {1033826400 49500 1 +1245}
    {1033826400 49500 1 +1345}
    {1047736800 45900 0 +1245}
    {1065276000 49500 1 +1245}
    {1065276000 49500 1 +1345}
    {1079791200 45900 0 +1245}
    {1096725600 49500 1 +1245}
    {1096725600 49500 1 +1345}
    {1111240800 45900 0 +1245}
    {1128175200 49500 1 +1245}
    {1128175200 49500 1 +1345}
    {1142690400 45900 0 +1245}
    {1159624800 49500 1 +1245}
    {1159624800 49500 1 +1345}
    {1174140000 45900 0 +1245}
    {1191074400 49500 1 +1245}
    {1191074400 49500 1 +1345}
    {1207404000 45900 0 +1245}
    {1222524000 49500 1 +1245}
    {1222524000 49500 1 +1345}
    {1238853600 45900 0 +1245}
    {1253973600 49500 1 +1245}
    {1253973600 49500 1 +1345}
    {1270303200 45900 0 +1245}
    {1285423200 49500 1 +1245}
    {1285423200 49500 1 +1345}
    {1301752800 45900 0 +1245}
    {1316872800 49500 1 +1245}
    {1316872800 49500 1 +1345}
    {1333202400 45900 0 +1245}
    {1348927200 49500 1 +1245}
    {1348927200 49500 1 +1345}
    {1365256800 45900 0 +1245}
    {1380376800 49500 1 +1245}
    {1380376800 49500 1 +1345}
    {1396706400 45900 0 +1245}
    {1411826400 49500 1 +1245}
    {1411826400 49500 1 +1345}
    {1428156000 45900 0 +1245}
    {1443276000 49500 1 +1245}
    {1443276000 49500 1 +1345}
    {1459605600 45900 0 +1245}
    {1474725600 49500 1 +1245}
    {1474725600 49500 1 +1345}
    {1491055200 45900 0 +1245}
    {1506175200 49500 1 +1245}
    {1506175200 49500 1 +1345}
    {1522504800 45900 0 +1245}
    {1538229600 49500 1 +1245}
    {1538229600 49500 1 +1345}
    {1554559200 45900 0 +1245}
    {1569679200 49500 1 +1245}
    {1569679200 49500 1 +1345}
    {1586008800 45900 0 +1245}
    {1601128800 49500 1 +1245}
    {1601128800 49500 1 +1345}
    {1617458400 45900 0 +1245}
    {1632578400 49500 1 +1245}
    {1632578400 49500 1 +1345}
    {1648908000 45900 0 +1245}
    {1664028000 49500 1 +1245}
    {1664028000 49500 1 +1345}
    {1680357600 45900 0 +1245}
    {1695477600 49500 1 +1245}
    {1695477600 49500 1 +1345}
    {1712412000 45900 0 +1245}
    {1727532000 49500 1 +1245}
    {1727532000 49500 1 +1345}
    {1743861600 45900 0 +1245}
    {1758981600 49500 1 +1245}
    {1758981600 49500 1 +1345}
    {1775311200 45900 0 +1245}
    {1790431200 49500 1 +1245}
    {1790431200 49500 1 +1345}
    {1806760800 45900 0 +1245}
    {1821880800 49500 1 +1245}
    {1821880800 49500 1 +1345}
    {1838210400 45900 0 +1245}
    {1853330400 49500 1 +1245}
    {1853330400 49500 1 +1345}
    {1869660000 45900 0 +1245}
    {1885384800 49500 1 +1245}
    {1885384800 49500 1 +1345}
    {1901714400 45900 0 +1245}
    {1916834400 49500 1 +1245}
    {1916834400 49500 1 +1345}
    {1933164000 45900 0 +1245}
    {1948284000 49500 1 +1245}
    {1948284000 49500 1 +1345}
    {1964613600 45900 0 +1245}
    {1979733600 49500 1 +1245}
    {1979733600 49500 1 +1345}
    {1996063200 45900 0 +1245}
    {2011183200 49500 1 +1245}
    {2011183200 49500 1 +1345}
    {2027512800 45900 0 +1245}
    {2042632800 49500 1 +1245}
    {2042632800 49500 1 +1345}
    {2058962400 45900 0 +1245}
    {2074687200 49500 1 +1245}
    {2074687200 49500 1 +1345}
    {2091016800 45900 0 +1245}
    {2106136800 49500 1 +1245}
    {2106136800 49500 1 +1345}
    {2122466400 45900 0 +1245}
    {2137586400 49500 1 +1245}
    {2137586400 49500 1 +1345}
    {2153916000 45900 0 +1245}
    {2169036000 49500 1 +1245}
    {2169036000 49500 1 +1345}
    {2185365600 45900 0 +1245}
    {2200485600 49500 1 +1245}
    {2200485600 49500 1 +1345}
    {2216815200 45900 0 +1245}
    {2232540000 49500 1 +1245}
    {2232540000 49500 1 +1345}
    {2248869600 45900 0 +1245}
    {2263989600 49500 1 +1245}
    {2263989600 49500 1 +1345}
    {2280319200 45900 0 +1245}
    {2295439200 49500 1 +1245}
    {2295439200 49500 1 +1345}
    {2311768800 45900 0 +1245}
    {2326888800 49500 1 +1245}
    {2326888800 49500 1 +1345}
    {2343218400 45900 0 +1245}
    {2358338400 49500 1 +1245}
    {2358338400 49500 1 +1345}
    {2374668000 45900 0 +1245}
    {2389788000 49500 1 +1245}
    {2389788000 49500 1 +1345}
    {2406117600 45900 0 +1245}
    {2421842400 49500 1 +1245}
    {2421842400 49500 1 +1345}
    {2438172000 45900 0 +1245}
    {2453292000 49500 1 +1245}
    {2453292000 49500 1 +1345}
    {2469621600 45900 0 +1245}
    {2484741600 49500 1 +1245}
    {2484741600 49500 1 +1345}
    {2501071200 45900 0 +1245}
    {2516191200 49500 1 +1245}
    {2516191200 49500 1 +1345}
    {2532520800 45900 0 +1245}
    {2547640800 49500 1 +1245}
    {2547640800 49500 1 +1345}
    {2563970400 45900 0 +1245}
    {2579090400 49500 1 +1245}
    {2579090400 49500 1 +1345}
    {2596024800 45900 0 +1245}
    {2611144800 49500 1 +1245}
    {2611144800 49500 1 +1345}
    {2627474400 45900 0 +1245}
    {2642594400 49500 1 +1245}
    {2642594400 49500 1 +1345}
    {2658924000 45900 0 +1245}
    {2674044000 49500 1 +1245}
    {2674044000 49500 1 +1345}
    {2690373600 45900 0 +1245}
    {2705493600 49500 1 +1245}
    {2705493600 49500 1 +1345}
    {2721823200 45900 0 +1245}
    {2736943200 49500 1 +1245}
    {2736943200 49500 1 +1345}
    {2753272800 45900 0 +1245}
    {2768997600 49500 1 +1245}
    {2768997600 49500 1 +1345}
    {2785327200 45900 0 +1245}
    {2800447200 49500 1 +1245}
    {2800447200 49500 1 +1345}
    {2816776800 45900 0 +1245}
    {2831896800 49500 1 +1245}
    {2831896800 49500 1 +1345}
    {2848226400 45900 0 +1245}
    {2863346400 49500 1 +1245}
    {2863346400 49500 1 +1345}
    {2879676000 45900 0 +1245}
    {2894796000 49500 1 +1245}
    {2894796000 49500 1 +1345}
    {2911125600 45900 0 +1245}
    {2926245600 49500 1 +1245}
    {2926245600 49500 1 +1345}
    {2942575200 45900 0 +1245}
    {2958300000 49500 1 +1245}
    {2958300000 49500 1 +1345}
    {2974629600 45900 0 +1245}
    {2989749600 49500 1 +1245}
    {2989749600 49500 1 +1345}
    {3006079200 45900 0 +1245}
    {3021199200 49500 1 +1245}
    {3021199200 49500 1 +1345}
    {3037528800 45900 0 +1245}
    {3052648800 49500 1 +1245}
    {3052648800 49500 1 +1345}
    {3068978400 45900 0 +1245}
    {3084098400 49500 1 +1245}
    {3084098400 49500 1 +1345}
    {3100428000 45900 0 +1245}
    {3116152800 49500 1 +1245}
    {3116152800 49500 1 +1345}
    {3132482400 45900 0 +1245}
    {3147602400 49500 1 +1245}
    {3147602400 49500 1 +1345}
    {3163932000 45900 0 +1245}
    {3179052000 49500 1 +1245}
    {3179052000 49500 1 +1345}
    {3195381600 45900 0 +1245}
    {3210501600 49500 1 +1245}
    {3210501600 49500 1 +1345}
    {3226831200 45900 0 +1245}
    {3241951200 49500 1 +1245}
    {3241951200 49500 1 +1345}
    {3258280800 45900 0 +1245}
    {3273400800 49500 1 +1245}
    {3273400800 49500 1 +1345}
    {3289730400 45900 0 +1245}
    {3305455200 49500 1 +1245}
    {3305455200 49500 1 +1345}
    {3321784800 45900 0 +1245}
    {3336904800 49500 1 +1245}
    {3336904800 49500 1 +1345}
    {3353234400 45900 0 +1245}
    {3368354400 49500 1 +1245}
    {3368354400 49500 1 +1345}
    {3384684000 45900 0 +1245}
    {3399804000 49500 1 +1245}
    {3399804000 49500 1 +1345}
    {3416133600 45900 0 +1245}
    {3431253600 49500 1 +1245}
    {3431253600 49500 1 +1345}
    {3447583200 45900 0 +1245}
    {3462703200 49500 1 +1245}
    {3462703200 49500 1 +1345}
    {3479637600 45900 0 +1245}
    {3494757600 49500 1 +1245}
    {3494757600 49500 1 +1345}
    {3511087200 45900 0 +1245}
    {3526207200 49500 1 +1245}
    {3526207200 49500 1 +1345}
    {3542536800 45900 0 +1245}
    {3557656800 49500 1 +1245}
    {3557656800 49500 1 +1345}
    {3573986400 45900 0 +1245}
    {3589106400 49500 1 +1245}
    {3589106400 49500 1 +1345}
    {3605436000 45900 0 +1245}
    {3620556000 49500 1 +1245}
    {3620556000 49500 1 +1345}
    {3636885600 45900 0 +1245}
    {3652610400 49500 1 +1245}
    {3652610400 49500 1 +1345}
    {3668940000 45900 0 +1245}
    {3684060000 49500 1 +1245}
    {3684060000 49500 1 +1345}
    {3700389600 45900 0 +1245}
    {3715509600 49500 1 +1245}
    {3715509600 49500 1 +1345}
    {3731839200 45900 0 +1245}
    {3746959200 49500 1 +1245}
    {3746959200 49500 1 +1345}
    {3763288800 45900 0 +1245}
    {3778408800 49500 1 +1245}
    {3778408800 49500 1 +1345}
    {3794738400 45900 0 +1245}
    {3809858400 49500 1 +1245}
    {3809858400 49500 1 +1345}
    {3826188000 45900 0 +1245}
    {3841912800 49500 1 +1245}
    {3841912800 49500 1 +1345}
    {3858242400 45900 0 +1245}
    {3873362400 49500 1 +1245}
    {3873362400 49500 1 +1345}
    {3889692000 45900 0 +1245}
    {3904812000 49500 1 +1245}
    {3904812000 49500 1 +1345}
    {3921141600 45900 0 +1245}
    {3936261600 49500 1 +1245}
    {3936261600 49500 1 +1345}
    {3952591200 45900 0 +1245}
    {3967711200 49500 1 +1245}
    {3967711200 49500 1 +1345}
    {3984040800 45900 0 +1245}
    {3999765600 49500 1 +1245}
    {3999765600 49500 1 +1345}
    {4016095200 45900 0 +1245}
    {4031215200 49500 1 +1245}
    {4031215200 49500 1 +1345}
    {4047544800 45900 0 +1245}
    {4062664800 49500 1 +1245}
    {4062664800 49500 1 +1345}
    {4078994400 45900 0 +1245}
    {4094114400 49500 1 +1245}
    {4094114400 49500 1 +1345}
}

Changes to library/tzdata/Pacific/Chuuk.

1


2
3


4
5
6
7
8
9
10
11
1
2
3


4
5









+
+
-
-
+
+
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Port_Moresby)]} {
    LoadTimeZoneFile Pacific/Port_Moresby

set TZData(:Pacific/Chuuk) {
}
set TZData(:Pacific/Chuuk) $TZData(:Pacific/Port_Moresby)
    {-9223372036854775808 -49972 0 LMT}
    {-3944628428 36428 0 LMT}
    {-2177489228 36000 0 +10}
    {-1743674400 32400 0 +09}
    {-1606813200 36000 0 +10}
    {-907408800 32400 0 +09}
    {-770634000 36000 0 +10}
}

Changes to library/tzdata/Pacific/Easter.

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
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
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
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





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Easter) {
    {-9223372036854775808 -26248 0 LMT}
    {-2524495352 -26248 0 EMT}
    {-1178124152 -25200 0 -07}
    {-36619200 -21600 1 -07}
    {-23922000 -25200 0 -07}
    {-3355200 -21600 1 -07}
    {7527600 -25200 0 -07}
    {24465600 -21600 1 -07}
    {37767600 -25200 0 -07}
    {55915200 -21600 1 -07}
    {69217200 -25200 0 -07}
    {87969600 -21600 1 -07}
    {100666800 -25200 0 -07}
    {118209600 -21600 1 -07}
    {132116400 -25200 0 -07}
    {150868800 -21600 1 -07}
    {163566000 -25200 0 -07}
    {182318400 -21600 1 -07}
    {195620400 -25200 0 -07}
    {213768000 -21600 1 -07}
    {227070000 -25200 0 -07}
    {245217600 -21600 1 -07}
    {258519600 -25200 0 -07}
    {277272000 -21600 1 -07}
    {289969200 -25200 0 -07}
    {308721600 -21600 1 -07}
    {321418800 -25200 0 -07}
    {340171200 -21600 1 -07}
    {353473200 -25200 0 -07}
    {371620800 -21600 1 -07}
    {384922800 -21600 0 -06}
    {403070400 -18000 1 -06}
    {416372400 -21600 0 -06}
    {434520000 -18000 1 -06}
    {447822000 -21600 0 -06}
    {466574400 -18000 1 -06}
    {479271600 -21600 0 -06}
    {498024000 -18000 1 -06}
    {510721200 -21600 0 -06}
    {529473600 -18000 1 -06}
    {545194800 -21600 0 -06}
    {560923200 -18000 1 -06}
    {574225200 -21600 0 -06}
    {592372800 -18000 1 -06}
    {605674800 -21600 0 -06}
    {624427200 -18000 1 -06}
    {637124400 -21600 0 -06}
    {653457600 -18000 1 -06}
    {668574000 -21600 0 -06}
    {687326400 -18000 1 -06}
    {700628400 -21600 0 -06}
    {718776000 -18000 1 -06}
    {732078000 -21600 0 -06}
    {750225600 -18000 1 -06}
    {763527600 -21600 0 -06}
    {781675200 -18000 1 -06}
    {794977200 -21600 0 -06}
    {813729600 -18000 1 -06}
    {826426800 -21600 0 -06}
    {845179200 -18000 1 -06}
    {859690800 -21600 0 -06}
    {876628800 -18000 1 -06}
    {889930800 -21600 0 -06}
    {906868800 -18000 1 -06}
    {923194800 -21600 0 -06}
    {939528000 -18000 1 -06}
    {952830000 -21600 0 -06}
    {971582400 -18000 1 -06}
    {984279600 -21600 0 -06}
    {1003032000 -18000 1 -06}
    {1015729200 -21600 0 -06}
    {1034481600 -18000 1 -06}
    {1047178800 -21600 0 -06}
    {1065931200 -18000 1 -06}
    {1079233200 -21600 0 -06}
    {1097380800 -18000 1 -06}
    {1110682800 -21600 0 -06}
    {1128830400 -18000 1 -06}
    {1142132400 -21600 0 -06}
    {1160884800 -18000 1 -06}
    {1173582000 -21600 0 -06}
    {1192334400 -18000 1 -06}
    {1206846000 -21600 0 -06}
    {1223784000 -18000 1 -06}
    {1237086000 -21600 0 -06}
    {1255233600 -18000 1 -06}
    {1270350000 -21600 0 -06}
    {1286683200 -18000 1 -06}
    {1304823600 -21600 0 -06}
    {1313899200 -18000 1 -06}
    {1335668400 -21600 0 -06}
    {1346558400 -18000 1 -06}
    {1367118000 -21600 0 -06}
    {1378612800 -18000 1 -06}
    {1398567600 -21600 0 -06}
    {1410062400 -18000 1 -06}
    {1463281200 -21600 0 -06}
    {1471147200 -18000 1 -06}
    {1494730800 -21600 0 -06}
    {1502596800 -18000 1 -06}
    {1526180400 -21600 0 -06}
    {1534046400 -18000 1 -06}
    {1554606000 -21600 0 -06}
    {1567915200 -18000 1 -06}
    {1586055600 -21600 0 -06}
    {1599364800 -18000 1 -06}
    {1617505200 -21600 0 -06}
    {1630814400 -18000 1 -06}
    {1648954800 -21600 0 -06}
    {1662264000 -18000 1 -06}
    {1680404400 -21600 0 -06}
    {1693713600 -18000 1 -06}
    {1712458800 -21600 0 -06}
    {1725768000 -18000 1 -06}
    {1743908400 -21600 0 -06}
    {1757217600 -18000 1 -06}
    {1775358000 -21600 0 -06}
    {1788667200 -18000 1 -06}
    {1806807600 -21600 0 -06}
    {1820116800 -18000 1 -06}
    {1838257200 -21600 0 -06}
    {1851566400 -18000 1 -06}
    {1870311600 -21600 0 -06}
    {1883016000 -18000 1 -06}
    {1901761200 -21600 0 -06}
    {1915070400 -18000 1 -06}
    {1933210800 -21600 0 -06}
    {1946520000 -18000 1 -06}
    {1964660400 -21600 0 -06}
    {1977969600 -18000 1 -06}
    {1996110000 -21600 0 -06}
    {2009419200 -18000 1 -06}
    {2027559600 -21600 0 -06}
    {2040868800 -18000 1 -06}
    {2059614000 -21600 0 -06}
    {2072318400 -18000 1 -06}
    {2091063600 -21600 0 -06}
    {2104372800 -18000 1 -06}
    {2122513200 -21600 0 -06}
    {2135822400 -18000 1 -06}
    {2153962800 -21600 0 -06}
    {2167272000 -18000 1 -06}
    {2185412400 -21600 0 -06}
    {2198721600 -18000 1 -06}
    {2217466800 -21600 0 -06}
    {2230171200 -18000 1 -06}
    {2248916400 -21600 0 -06}
    {2262225600 -18000 1 -06}
    {2280366000 -21600 0 -06}
    {2293675200 -18000 1 -06}
    {2311815600 -21600 0 -06}
    {2325124800 -18000 1 -06}
    {2343265200 -21600 0 -06}
    {2356574400 -18000 1 -06}
    {2374714800 -21600 0 -06}
    {2388024000 -18000 1 -06}
    {2406769200 -21600 0 -06}
    {2419473600 -18000 1 -06}
    {2438218800 -21600 0 -06}
    {2451528000 -18000 1 -06}
    {2469668400 -21600 0 -06}
    {2482977600 -18000 1 -06}
    {2501118000 -21600 0 -06}
    {2514427200 -18000 1 -06}
    {2532567600 -21600 0 -06}
    {2545876800 -18000 1 -06}
    {2564017200 -21600 0 -06}
    {2577326400 -18000 1 -06}
    {2596071600 -21600 0 -06}
    {2609380800 -18000 1 -06}
    {2627521200 -21600 0 -06}
    {2640830400 -18000 1 -06}
    {2658970800 -21600 0 -06}
    {2672280000 -18000 1 -06}
    {2690420400 -21600 0 -06}
    {2703729600 -18000 1 -06}
    {2721870000 -21600 0 -06}
    {2735179200 -18000 1 -06}
    {2753924400 -21600 0 -06}
    {2766628800 -18000 1 -06}
    {2785374000 -21600 0 -06}
    {2798683200 -18000 1 -06}
    {2816823600 -21600 0 -06}
    {2830132800 -18000 1 -06}
    {2848273200 -21600 0 -06}
    {2861582400 -18000 1 -06}
    {2879722800 -21600 0 -06}
    {2893032000 -18000 1 -06}
    {2911172400 -21600 0 -06}
    {2924481600 -18000 1 -06}
    {2943226800 -21600 0 -06}
    {2955931200 -18000 1 -06}
    {2974676400 -21600 0 -06}
    {2987985600 -18000 1 -06}
    {3006126000 -21600 0 -06}
    {3019435200 -18000 1 -06}
    {3037575600 -21600 0 -06}
    {3050884800 -18000 1 -06}
    {3069025200 -21600 0 -06}
    {3082334400 -18000 1 -06}
    {3101079600 -21600 0 -06}
    {3113784000 -18000 1 -06}
    {3132529200 -21600 0 -06}
    {3145838400 -18000 1 -06}
    {3163978800 -21600 0 -06}
    {3177288000 -18000 1 -06}
    {3195428400 -21600 0 -06}
    {3208737600 -18000 1 -06}
    {3226878000 -21600 0 -06}
    {3240187200 -18000 1 -06}
    {3258327600 -21600 0 -06}
    {3271636800 -18000 1 -06}
    {3290382000 -21600 0 -06}
    {3303086400 -18000 1 -06}
    {3321831600 -21600 0 -06}
    {3335140800 -18000 1 -06}
    {3353281200 -21600 0 -06}
    {3366590400 -18000 1 -06}
    {3384730800 -21600 0 -06}
    {3398040000 -18000 1 -06}
    {3416180400 -21600 0 -06}
    {3429489600 -18000 1 -06}
    {3447630000 -21600 0 -06}
    {3460939200 -18000 1 -06}
    {3479684400 -21600 0 -06}
    {3492993600 -18000 1 -06}
    {3511134000 -21600 0 -06}
    {3524443200 -18000 1 -06}
    {3542583600 -21600 0 -06}
    {3555892800 -18000 1 -06}
    {3574033200 -21600 0 -06}
    {3587342400 -18000 1 -06}
    {3605482800 -21600 0 -06}
    {3618792000 -18000 1 -06}
    {3637537200 -21600 0 -06}
    {3650241600 -18000 1 -06}
    {3668986800 -21600 0 -06}
    {3682296000 -18000 1 -06}
    {3700436400 -21600 0 -06}
    {3713745600 -18000 1 -06}
    {3731886000 -21600 0 -06}
    {3745195200 -18000 1 -06}
    {3763335600 -21600 0 -06}
    {3776644800 -18000 1 -06}
    {3794785200 -21600 0 -06}
    {3808094400 -18000 1 -06}
    {3826839600 -21600 0 -06}
    {3839544000 -18000 1 -06}
    {3858289200 -21600 0 -06}
    {3871598400 -18000 1 -06}
    {3889738800 -21600 0 -06}
    {3903048000 -18000 1 -06}
    {3921188400 -21600 0 -06}
    {3934497600 -18000 1 -06}
    {3952638000 -21600 0 -06}
    {3965947200 -18000 1 -06}
    {3984692400 -21600 0 -06}
    {3997396800 -18000 1 -06}
    {4016142000 -21600 0 -06}
    {4029451200 -18000 1 -06}
    {4047591600 -21600 0 -06}
    {4060900800 -18000 1 -06}
    {4079041200 -21600 0 -06}
    {4092350400 -18000 1 -06}
    {-1178124152 -25200 0 -0700}
    {-36619200 -21600 1 -0600}
    {-23922000 -25200 0 -0700}
    {-3355200 -21600 1 -0600}
    {7527600 -25200 0 -0700}
    {24465600 -21600 1 -0600}
    {37767600 -25200 0 -0700}
    {55915200 -21600 1 -0600}
    {69217200 -25200 0 -0700}
    {87969600 -21600 1 -0600}
    {100666800 -25200 0 -0700}
    {118209600 -21600 1 -0600}
    {132116400 -25200 0 -0700}
    {150868800 -21600 1 -0600}
    {163566000 -25200 0 -0700}
    {182318400 -21600 1 -0600}
    {195620400 -25200 0 -0700}
    {213768000 -21600 1 -0600}
    {227070000 -25200 0 -0700}
    {245217600 -21600 1 -0600}
    {258519600 -25200 0 -0700}
    {277272000 -21600 1 -0600}
    {289969200 -25200 0 -0700}
    {308721600 -21600 1 -0600}
    {321418800 -25200 0 -0700}
    {340171200 -21600 1 -0600}
    {353473200 -25200 0 -0700}
    {371620800 -21600 1 -0600}
    {384922800 -21600 0 -0600}
    {403070400 -18000 1 -0500}
    {416372400 -21600 0 -0600}
    {434520000 -18000 1 -0500}
    {447822000 -21600 0 -0600}
    {466574400 -18000 1 -0500}
    {479271600 -21600 0 -0600}
    {498024000 -18000 1 -0500}
    {510721200 -21600 0 -0600}
    {529473600 -18000 1 -0500}
    {545194800 -21600 0 -0600}
    {560923200 -18000 1 -0500}
    {574225200 -21600 0 -0600}
    {592372800 -18000 1 -0500}
    {605674800 -21600 0 -0600}
    {624427200 -18000 1 -0500}
    {637124400 -21600 0 -0600}
    {653457600 -18000 1 -0500}
    {668574000 -21600 0 -0600}
    {687326400 -18000 1 -0500}
    {700628400 -21600 0 -0600}
    {718776000 -18000 1 -0500}
    {732078000 -21600 0 -0600}
    {750225600 -18000 1 -0500}
    {763527600 -21600 0 -0600}
    {781675200 -18000 1 -0500}
    {794977200 -21600 0 -0600}
    {813729600 -18000 1 -0500}
    {826426800 -21600 0 -0600}
    {845179200 -18000 1 -0500}
    {859690800 -21600 0 -0600}
    {876628800 -18000 1 -0500}
    {889930800 -21600 0 -0600}
    {906868800 -18000 1 -0500}
    {923194800 -21600 0 -0600}
    {939528000 -18000 1 -0500}
    {952830000 -21600 0 -0600}
    {971582400 -18000 1 -0500}
    {984279600 -21600 0 -0600}
    {1003032000 -18000 1 -0500}
    {1015729200 -21600 0 -0600}
    {1034481600 -18000 1 -0500}
    {1047178800 -21600 0 -0600}
    {1065931200 -18000 1 -0500}
    {1079233200 -21600 0 -0600}
    {1097380800 -18000 1 -0500}
    {1110682800 -21600 0 -0600}
    {1128830400 -18000 1 -0500}
    {1142132400 -21600 0 -0600}
    {1160884800 -18000 1 -0500}
    {1173582000 -21600 0 -0600}
    {1192334400 -18000 1 -0500}
    {1206846000 -21600 0 -0600}
    {1223784000 -18000 1 -0500}
    {1237086000 -21600 0 -0600}
    {1255233600 -18000 1 -0500}
    {1270350000 -21600 0 -0600}
    {1286683200 -18000 1 -0500}
    {1304823600 -21600 0 -0600}
    {1313899200 -18000 1 -0500}
    {1335668400 -21600 0 -0600}
    {1346558400 -18000 1 -0500}
    {1367118000 -21600 0 -0600}
    {1378612800 -18000 1 -0500}
    {1398567600 -21600 0 -0600}
    {1410062400 -18000 1 -0500}
    {1463281200 -21600 0 -0600}
    {1471147200 -18000 1 -0500}
    {1494730800 -21600 0 -0600}
    {1502596800 -18000 1 -0500}
    {1526180400 -21600 0 -0600}
    {1534046400 -18000 1 -0500}
    {1554606000 -21600 0 -0600}
    {1567915200 -18000 1 -0500}
    {1586055600 -21600 0 -0600}
    {1599364800 -18000 1 -0500}
    {1617505200 -21600 0 -0600}
    {1630814400 -18000 1 -0500}
    {1648954800 -21600 0 -0600}
    {1662868800 -18000 1 -0500}
    {1680404400 -21600 0 -0600}
    {1693713600 -18000 1 -0500}
    {1712458800 -21600 0 -0600}
    {1725768000 -18000 1 -0500}
    {1743908400 -21600 0 -0600}
    {1757217600 -18000 1 -0500}
    {1775358000 -21600 0 -0600}
    {1788667200 -18000 1 -0500}
    {1806807600 -21600 0 -0600}
    {1820116800 -18000 1 -0500}
    {1838257200 -21600 0 -0600}
    {1851566400 -18000 1 -0500}
    {1870311600 -21600 0 -0600}
    {1883016000 -18000 1 -0500}
    {1901761200 -21600 0 -0600}
    {1915070400 -18000 1 -0500}
    {1933210800 -21600 0 -0600}
    {1946520000 -18000 1 -0500}
    {1964660400 -21600 0 -0600}
    {1977969600 -18000 1 -0500}
    {1996110000 -21600 0 -0600}
    {2009419200 -18000 1 -0500}
    {2027559600 -21600 0 -0600}
    {2040868800 -18000 1 -0500}
    {2059614000 -21600 0 -0600}
    {2072318400 -18000 1 -0500}
    {2091063600 -21600 0 -0600}
    {2104372800 -18000 1 -0500}
    {2122513200 -21600 0 -0600}
    {2135822400 -18000 1 -0500}
    {2153962800 -21600 0 -0600}
    {2167272000 -18000 1 -0500}
    {2185412400 -21600 0 -0600}
    {2198721600 -18000 1 -0500}
    {2217466800 -21600 0 -0600}
    {2230171200 -18000 1 -0500}
    {2248916400 -21600 0 -0600}
    {2262225600 -18000 1 -0500}
    {2280366000 -21600 0 -0600}
    {2293675200 -18000 1 -0500}
    {2311815600 -21600 0 -0600}
    {2325124800 -18000 1 -0500}
    {2343265200 -21600 0 -0600}
    {2356574400 -18000 1 -0500}
    {2374714800 -21600 0 -0600}
    {2388024000 -18000 1 -0500}
    {2406769200 -21600 0 -0600}
    {2419473600 -18000 1 -0500}
    {2438218800 -21600 0 -0600}
    {2451528000 -18000 1 -0500}
    {2469668400 -21600 0 -0600}
    {2482977600 -18000 1 -0500}
    {2501118000 -21600 0 -0600}
    {2514427200 -18000 1 -0500}
    {2532567600 -21600 0 -0600}
    {2545876800 -18000 1 -0500}
    {2564017200 -21600 0 -0600}
    {2577326400 -18000 1 -0500}
    {2596071600 -21600 0 -0600}
    {2609380800 -18000 1 -0500}
    {2627521200 -21600 0 -0600}
    {2640830400 -18000 1 -0500}
    {2658970800 -21600 0 -0600}
    {2672280000 -18000 1 -0500}
    {2690420400 -21600 0 -0600}
    {2703729600 -18000 1 -0500}
    {2721870000 -21600 0 -0600}
    {2735179200 -18000 1 -0500}
    {2753924400 -21600 0 -0600}
    {2766628800 -18000 1 -0500}
    {2785374000 -21600 0 -0600}
    {2798683200 -18000 1 -0500}
    {2816823600 -21600 0 -0600}
    {2830132800 -18000 1 -0500}
    {2848273200 -21600 0 -0600}
    {2861582400 -18000 1 -0500}
    {2879722800 -21600 0 -0600}
    {2893032000 -18000 1 -0500}
    {2911172400 -21600 0 -0600}
    {2924481600 -18000 1 -0500}
    {2943226800 -21600 0 -0600}
    {2955931200 -18000 1 -0500}
    {2974676400 -21600 0 -0600}
    {2987985600 -18000 1 -0500}
    {3006126000 -21600 0 -0600}
    {3019435200 -18000 1 -0500}
    {3037575600 -21600 0 -0600}
    {3050884800 -18000 1 -0500}
    {3069025200 -21600 0 -0600}
    {3082334400 -18000 1 -0500}
    {3101079600 -21600 0 -0600}
    {3113784000 -18000 1 -0500}
    {3132529200 -21600 0 -0600}
    {3145838400 -18000 1 -0500}
    {3163978800 -21600 0 -0600}
    {3177288000 -18000 1 -0500}
    {3195428400 -21600 0 -0600}
    {3208737600 -18000 1 -0500}
    {3226878000 -21600 0 -0600}
    {3240187200 -18000 1 -0500}
    {3258327600 -21600 0 -0600}
    {3271636800 -18000 1 -0500}
    {3290382000 -21600 0 -0600}
    {3303086400 -18000 1 -0500}
    {3321831600 -21600 0 -0600}
    {3335140800 -18000 1 -0500}
    {3353281200 -21600 0 -0600}
    {3366590400 -18000 1 -0500}
    {3384730800 -21600 0 -0600}
    {3398040000 -18000 1 -0500}
    {3416180400 -21600 0 -0600}
    {3429489600 -18000 1 -0500}
    {3447630000 -21600 0 -0600}
    {3460939200 -18000 1 -0500}
    {3479684400 -21600 0 -0600}
    {3492993600 -18000 1 -0500}
    {3511134000 -21600 0 -0600}
    {3524443200 -18000 1 -0500}
    {3542583600 -21600 0 -0600}
    {3555892800 -18000 1 -0500}
    {3574033200 -21600 0 -0600}
    {3587342400 -18000 1 -0500}
    {3605482800 -21600 0 -0600}
    {3618792000 -18000 1 -0500}
    {3637537200 -21600 0 -0600}
    {3650241600 -18000 1 -0500}
    {3668986800 -21600 0 -0600}
    {3682296000 -18000 1 -0500}
    {3700436400 -21600 0 -0600}
    {3713745600 -18000 1 -0500}
    {3731886000 -21600 0 -0600}
    {3745195200 -18000 1 -0500}
    {3763335600 -21600 0 -0600}
    {3776644800 -18000 1 -0500}
    {3794785200 -21600 0 -0600}
    {3808094400 -18000 1 -0500}
    {3826839600 -21600 0 -0600}
    {3839544000 -18000 1 -0500}
    {3858289200 -21600 0 -0600}
    {3871598400 -18000 1 -0500}
    {3889738800 -21600 0 -0600}
    {3903048000 -18000 1 -0500}
    {3921188400 -21600 0 -0600}
    {3934497600 -18000 1 -0500}
    {3952638000 -21600 0 -0600}
    {3965947200 -18000 1 -0500}
    {3984692400 -21600 0 -0600}
    {3997396800 -18000 1 -0500}
    {4016142000 -21600 0 -0600}
    {4029451200 -18000 1 -0500}
    {4047591600 -21600 0 -0600}
    {4060900800 -18000 1 -0500}
    {4079041200 -21600 0 -0600}
    {4092350400 -18000 1 -0500}
}

Changes to library/tzdata/Pacific/Efate.

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
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




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Efate) {
    {-9223372036854775808 40396 0 LMT}
    {-1829387596 39600 0 +11}
    {433256400 43200 1 +11}
    {448977600 39600 0 +11}
    {467298000 43200 1 +11}
    {480427200 39600 0 +11}
    {496760400 43200 1 +11}
    {511876800 39600 0 +11}
    {528210000 43200 1 +11}
    {543931200 39600 0 +11}
    {559659600 43200 1 +11}
    {575380800 39600 0 +11}
    {591109200 43200 1 +11}
    {606830400 39600 0 +11}
    {622558800 43200 1 +11}
    {638280000 39600 0 +11}
    {654008400 43200 1 +11}
    {669729600 39600 0 +11}
    {686062800 43200 1 +11}
    {696340800 39600 0 +11}
    {719931600 43200 1 +11}
    {727790400 39600 0 +11}
    {-1829387596 39600 0 +1100}
    {125409600 43200 1 +1200}
    {133876800 39600 0 +1100}
    {433256400 43200 1 +1200}
    {448977600 39600 0 +1100}
    {464706000 43200 1 +1200}
    {480427200 39600 0 +1100}
    {496760400 43200 1 +1200}
    {511876800 39600 0 +1100}
    {528210000 43200 1 +1200}
    {543931200 39600 0 +1100}
    {559659600 43200 1 +1200}
    {575380800 39600 0 +1100}
    {591109200 43200 1 +1200}
    {606830400 39600 0 +1100}
    {622558800 43200 1 +1200}
    {638280000 39600 0 +1100}
    {654008400 43200 1 +1200}
    {669729600 39600 0 +1100}
    {686062800 43200 1 +1200}
    {696340800 39600 0 +1100}
    {719931600 43200 1 +1200}
    {727790400 39600 0 +1100}
}

Changes to library/tzdata/Pacific/Enderbury.

1


2
3


4
5
6
7
8
1
2
3


4
5






+
+
-
-
+
+
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Kanton)]} {
    LoadTimeZoneFile Pacific/Kanton

set TZData(:Pacific/Enderbury) {
}
set TZData(:Pacific/Enderbury) $TZData(:Pacific/Kanton)
    {-9223372036854775808 -41060 0 LMT}
    {-2177411740 -43200 0 -12}
    {307627200 -39600 0 -11}
    {788871600 46800 0 +13}
}

Changes to library/tzdata/Pacific/Fakaofo.

1
2
3
4
5
6


7
1
2
3
4


5
6
7




-
-
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Fakaofo) {
    {-9223372036854775808 -41096 0 LMT}
    {-2177411704 -39600 0 -11}
    {1325242800 46800 0 +13}
    {-2177411704 -39600 0 -1100}
    {1325242800 46800 0 +1300}
}

Changes to library/tzdata/Pacific/Fiji.

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
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
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
30





31







32





33



















34




-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
+
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Fiji) {
    {-9223372036854775808 42944 0 LMT}
    {-1709985344 43200 0 +12}
    {909842400 46800 1 +12}
    {920124000 43200 0 +12}
    {941896800 46800 1 +12}
    {951573600 43200 0 +12}
    {1259416800 46800 1 +12}
    {1269698400 43200 0 +12}
    {1287842400 46800 1 +12}
    {1299333600 43200 0 +12}
    {1319292000 46800 1 +12}
    {1327154400 43200 0 +12}
    {1350741600 46800 1 +12}
    {1358604000 43200 0 +12}
    {-1709985344 43200 0 +1200}
    {909842400 46800 1 +1300}
    {920124000 43200 0 +1200}
    {941896800 46800 1 +1300}
    {951573600 43200 0 +1200}
    {1259416800 46800 1 +1300}
    {1269698400 43200 0 +1200}
    {1287842400 46800 1 +1300}
    {1299333600 43200 0 +1200}
    {1319292000 46800 1 +1300}
    {1327154400 43200 0 +1200}
    {1350741600 46800 1 +1300}
    {1358604000 43200 0 +1200}
    {1382796000 46800 1 +12}
    {1390050000 43200 0 +12}
    {1414850400 46800 1 +12}
    {1421503200 43200 0 +12}
    {1446300000 46800 1 +12}
    {1452952800 43200 0 +12}
    {1478354400 46800 1 +12}
    {1484402400 43200 0 +12}
    {1509804000 46800 1 +12}
    {1515852000 43200 0 +12}
    {1541253600 46800 1 +12}
    {1547301600 43200 0 +12}
    {1573308000 46800 1 +12}
    {1578751200 43200 0 +12}
    {1608386400 46800 1 +12}
    {1610805600 43200 0 +12}
    {1636812000 46800 1 +12}
    {1642255200 43200 0 +12}
    {1668261600 46800 1 +12}
    {1673704800 43200 0 +12}
    {1699711200 46800 1 +12}
    {1705154400 43200 0 +12}
    {1731160800 46800 1 +12}
    {1736604000 43200 0 +12}
    {1762610400 46800 1 +12}
    {1768658400 43200 0 +12}
    {1794060000 46800 1 +12}
    {1800108000 43200 0 +12}
    {1826114400 46800 1 +12}
    {1831557600 43200 0 +12}
    {1857564000 46800 1 +12}
    {1863007200 43200 0 +12}
    {1889013600 46800 1 +12}
    {1894456800 43200 0 +12}
    {1920463200 46800 1 +12}
    {1925906400 43200 0 +12}
    {1951912800 46800 1 +12}
    {1957960800 43200 0 +12}
    {1983967200 46800 1 +12}
    {1989410400 43200 0 +12}
    {2015416800 46800 1 +12}
    {2020860000 43200 0 +12}
    {2046866400 46800 1 +12}
    {2052309600 43200 0 +12}
    {2078316000 46800 1 +12}
    {2083759200 43200 0 +12}
    {2109765600 46800 1 +12}
    {2115813600 43200 0 +12}
    {2141215200 46800 1 +12}
    {2147263200 43200 0 +12}
    {2173269600 46800 1 +12}
    {2178712800 43200 0 +12}
    {2204719200 46800 1 +12}
    {2210162400 43200 0 +12}
    {2236168800 46800 1 +12}
    {2241612000 43200 0 +12}
    {2267618400 46800 1 +12}
    {2273061600 43200 0 +12}
    {2299068000 46800 1 +12}
    {2305116000 43200 0 +12}
    {2330517600 46800 1 +12}
    {2336565600 43200 0 +12}
    {2362572000 46800 1 +12}
    {2368015200 43200 0 +12}
    {2394021600 46800 1 +12}
    {2399464800 43200 0 +12}
    {2425471200 46800 1 +12}
    {2430914400 43200 0 +12}
    {2456920800 46800 1 +12}
    {2462364000 43200 0 +12}
    {2488370400 46800 1 +12}
    {2494418400 43200 0 +12}
    {2520424800 46800 1 +12}
    {2525868000 43200 0 +12}
    {2551874400 46800 1 +12}
    {2557317600 43200 0 +12}
    {2583324000 46800 1 +12}
    {2588767200 43200 0 +12}
    {2614773600 46800 1 +12}
    {2620216800 43200 0 +12}
    {2646223200 46800 1 +12}
    {2652271200 43200 0 +12}
    {2677672800 46800 1 +12}
    {2683720800 43200 0 +12}
    {2709727200 46800 1 +12}
    {2715170400 43200 0 +12}
    {2741176800 46800 1 +12}
    {2746620000 43200 0 +12}
    {2772626400 46800 1 +12}
    {2778069600 43200 0 +12}
    {2804076000 46800 1 +12}
    {2809519200 43200 0 +12}
    {2835525600 46800 1 +12}
    {1382796000 46800 1 +1300}
    {1390050000 43200 0 +1200}
    {1414850400 46800 1 +1300}
    {2841573600 43200 0 +12}
    {2867580000 46800 1 +12}
    {2873023200 43200 0 +12}
    {1421503200 43200 0 +1200}
    {2899029600 46800 1 +12}
    {2904472800 43200 0 +12}
    {2930479200 46800 1 +12}
    {2935922400 43200 0 +12}
    {2961928800 46800 1 +12}
    {2967372000 43200 0 +12}
    {2993378400 46800 1 +12}
    {2999426400 43200 0 +12}
    {3024828000 46800 1 +12}
    {1446300000 46800 1 +1300}
    {3030876000 43200 0 +12}
    {3056882400 46800 1 +12}
    {3062325600 43200 0 +12}
    {3088332000 46800 1 +12}
    {3093775200 43200 0 +12}
    {3119781600 46800 1 +12}
    {3125224800 43200 0 +12}
    {1452952800 43200 0 +1200}
    {3151231200 46800 1 +12}
    {3156674400 43200 0 +12}
    {3182680800 46800 1 +12}
    {3188728800 43200 0 +12}
    {3214130400 46800 1 +12}
    {3220178400 43200 0 +12}
    {3246184800 46800 1 +12}
    {3251628000 43200 0 +12}
    {3277634400 46800 1 +12}
    {3283077600 43200 0 +12}
    {3309084000 46800 1 +12}
    {3314527200 43200 0 +12}
    {3340533600 46800 1 +12}
    {3345976800 43200 0 +12}
    {3371983200 46800 1 +12}
    {3378031200 43200 0 +12}
    {1478354400 46800 1 +1300}
    {1484402400 43200 0 +1200}
    {3404037600 46800 1 +12}
    {3409480800 43200 0 +12}
    {3435487200 46800 1 +12}
    {1509804000 46800 1 +1300}
    {3440930400 43200 0 +12}
    {3466936800 46800 1 +12}
    {3472380000 43200 0 +12}
    {3498386400 46800 1 +12}
    {3503829600 43200 0 +12}
    {3529836000 46800 1 +12}
    {1515852000 43200 0 +1200}
    {1541253600 46800 1 +1300}
    {1547301600 43200 0 +1200}
    {1573308000 46800 1 +1300}
    {3535884000 43200 0 +12}
    {3561285600 46800 1 +12}
    {3567333600 43200 0 +12}
    {3593340000 46800 1 +12}
    {3598783200 43200 0 +12}
    {1578751200 43200 0 +1200}
    {3624789600 46800 1 +12}
    {3630232800 43200 0 +12}
    {3656239200 46800 1 +12}
    {3661682400 43200 0 +12}
    {3687688800 46800 1 +12}
    {3693132000 43200 0 +12}
    {3719138400 46800 1 +12}
    {1608386400 46800 1 +1300}
    {3725186400 43200 0 +12}
    {3751192800 46800 1 +12}
    {3756636000 43200 0 +12}
    {3782642400 46800 1 +12}
    {3788085600 43200 0 +12}
    {1610805600 43200 0 +1200}
    {3814092000 46800 1 +12}
    {3819535200 43200 0 +12}
    {3845541600 46800 1 +12}
    {3850984800 43200 0 +12}
    {3876991200 46800 1 +12}
    {3883039200 43200 0 +12}
    {3908440800 46800 1 +12}
    {3914488800 43200 0 +12}
    {3940495200 46800 1 +12}
    {3945938400 43200 0 +12}
    {3971944800 46800 1 +12}
    {3977388000 43200 0 +12}
    {4003394400 46800 1 +12}
    {4008837600 43200 0 +12}
    {4034844000 46800 1 +12}
    {4040287200 43200 0 +12}
    {4066293600 46800 1 +12}
    {4072341600 43200 0 +12}
    {4097743200 46800 1 +12}
}

Changes to library/tzdata/Pacific/Funafuti.

1


2
3


4
5
6
1
2
3


4
5




+
+
-
-
+
+
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Tarawa)]} {
    LoadTimeZoneFile Pacific/Tarawa

set TZData(:Pacific/Funafuti) {
}
set TZData(:Pacific/Funafuti) $TZData(:Pacific/Tarawa)
    {-9223372036854775808 43012 0 LMT}
    {-2177495812 43200 0 +12}
}

Changes to library/tzdata/Pacific/Galapagos.

1
2
3
4
5
6
7
8




9
1
2
3
4




5
6
7
8
9




-
-
-
-
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Galapagos) {
    {-9223372036854775808 -21504 0 LMT}
    {-1230746496 -18000 0 -05}
    {504939600 -21600 0 -06}
    {722930400 -18000 1 -06}
    {728888400 -21600 0 -06}
    {-1230746496 -18000 0 -0500}
    {504939600 -21600 0 -0600}
    {722930400 -18000 1 -0500}
    {728888400 -21600 0 -0600}
}

Changes to library/tzdata/Pacific/Gambier.

1
2
3
4
5

6
1
2
3
4

5
6




-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Gambier) {
    {-9223372036854775808 -32388 0 LMT}
    {-1806678012 -32400 0 -09}
    {-1806678012 -32400 0 -0900}
}

Changes to library/tzdata/Pacific/Guadalcanal.

1
2
3
4
5

6
1
2
3
4

5
6




-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Guadalcanal) {
    {-9223372036854775808 38388 0 LMT}
    {-1806748788 39600 0 +11}
    {-1806748788 39600 0 +1100}
}

Changes to library/tzdata/Pacific/Guam.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Guam) {
    {-9223372036854775808 -51660 0 LMT}
    {-3944626740 34740 0 LMT}
    {-2177487540 36000 0 GST}
    {-885549600 32400 0 +09}
    {-885549600 32400 0 +0900}
    {-802256400 36000 0 GST}
    {-331891200 39600 1 GDT}
    {-281610000 36000 0 GST}
    {-73728000 39600 1 GDT}
    {-29415540 36000 0 GST}
    {-16704000 39600 1 GDT}
    {-10659600 36000 0 GST}

Added library/tzdata/Pacific/Kanton.









1
2
3
4
5
6
7
8
+
+
+
+
+
+
+
+
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Kanton) {
    {-9223372036854775808 0 0 -00}
    {-1020470400 -43200 0 -1200}
    {307627200 -39600 0 -1100}
    {788871600 46800 0 +1300}
}

Changes to library/tzdata/Pacific/Kiritimati.

1
2
3
4
5
6
7



8
1
2
3
4



5
6
7
8




-
-
-
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Kiritimati) {
    {-9223372036854775808 -37760 0 LMT}
    {-2177415040 -38400 0 -1040}
    {307622400 -36000 0 -10}
    {788868000 50400 0 +14}
    {-2177415040 -38400 0 -1140}
    {307622400 -36000 0 -1000}
    {788868000 50400 0 +1400}
}

Changes to library/tzdata/Pacific/Kosrae.

1
2
3
4
5
6
7
8
9
10
11
12
13








14
1
2
3
4
5








6
7
8
9
10
11
12
13
14





-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Kosrae) {
    {-9223372036854775808 -47284 0 LMT}
    {-3944631116 39116 0 LMT}
    {-2177491916 39600 0 +11}
    {-1743678000 32400 0 +09}
    {-1606813200 39600 0 +11}
    {-1041418800 36000 0 +10}
    {-907408800 32400 0 +09}
    {-770634000 39600 0 +11}
    {-7988400 43200 0 +12}
    {915105600 39600 0 +11}
    {-2177491916 39600 0 +1100}
    {-1743678000 32400 0 +0900}
    {-1606813200 39600 0 +1100}
    {-1041418800 36000 0 +1000}
    {-907408800 32400 0 +0900}
    {-770634000 39600 0 +1100}
    {-7988400 43200 0 +1200}
    {915105600 39600 0 +1100}
}

Changes to library/tzdata/Pacific/Kwajalein.

1
2
3
4
5
6
7
8
9
10






11
1
2
3
4






5
6
7
8
9
10
11




-
-
-
-
-
-
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Kwajalein) {
    {-9223372036854775808 40160 0 LMT}
    {-2177492960 39600 0 +11}
    {-1041418800 36000 0 +10}
    {-907408800 32400 0 +09}
    {-817462800 39600 0 +11}
    {-7988400 -43200 0 -12}
    {745934400 43200 0 +12}
    {-2177492960 39600 0 +1100}
    {-1041418800 36000 0 +1000}
    {-907408800 32400 0 +0900}
    {-817462800 39600 0 +1100}
    {-7988400 -43200 0 -1200}
    {745934400 43200 0 +1200}
}

Changes to library/tzdata/Pacific/Majuro.

1


2
3


4
5
6
7
8
9
10
11
12
1
2
3


4
5










+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Tarawa)]} {
    LoadTimeZoneFile Pacific/Tarawa

set TZData(:Pacific/Majuro) {
}
set TZData(:Pacific/Majuro) $TZData(:Pacific/Tarawa)
    {-9223372036854775808 41088 0 LMT}
    {-2177493888 39600 0 +11}
    {-1743678000 32400 0 +09}
    {-1606813200 39600 0 +11}
    {-1041418800 36000 0 +10}
    {-907408800 32400 0 +09}
    {-818067600 39600 0 +11}
    {-7988400 43200 0 +12}
}

Changes to library/tzdata/Pacific/Marquesas.

1
2
3
4
5

6
1
2
3
4

5
6




-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Marquesas) {
    {-9223372036854775808 -33480 0 LMT}
    {-1806676920 -34200 0 -0930}
    {-1806676920 -34200 0 -1030}
}

Changes to library/tzdata/Pacific/Nauru.

1
2
3
4
5
6

7
8

9
1
2
3
4
5

6
7

8
9





-
+

-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Nauru) {
    {-9223372036854775808 40060 0 LMT}
    {-1545131260 41400 0 +1130}
    {-862918200 32400 0 +09}
    {-862918200 32400 0 +0900}
    {-767350800 41400 0 +1130}
    {287418600 43200 0 +12}
    {287418600 43200 0 +1200}
}

Changes to library/tzdata/Pacific/Niue.

1
2
3
4
5

6
7

8
1
2
3
4

5


6
7




-
+
-
-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Niue) {
    {-9223372036854775808 -40780 0 LMT}
    {-2177412020 -40800 0 -1120}
    {-543069620 -40800 0 -1220}
    {-599575200 -41400 0 -1130}
    {276089400 -39600 0 -11}
    {-173623200 -39600 0 -1100}
}

Changes to library/tzdata/Pacific/Norfolk.

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
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
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
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








-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Norfolk) {
    {-9223372036854775808 40312 0 LMT}
    {-2177493112 40320 0 +1112}
    {-599656320 41400 0 +1130}
    {152029800 45000 1 +1230}
    {162916200 41400 0 +1130}
    {1443882600 39600 0 +11}
    {1561899600 39600 0 +12}
    {1570287600 43200 1 +12}
    {1586012400 39600 0 +12}
    {1601737200 43200 1 +12}
    {1617462000 39600 0 +12}
    {1633186800 43200 1 +12}
    {1648911600 39600 0 +12}
    {1664636400 43200 1 +12}
    {1680361200 39600 0 +12}
    {1696086000 43200 1 +12}
    {1712415600 39600 0 +12}
    {1728140400 43200 1 +12}
    {1743865200 39600 0 +12}
    {1759590000 43200 1 +12}
    {1775314800 39600 0 +12}
    {1791039600 43200 1 +12}
    {1806764400 39600 0 +12}
    {1822489200 43200 1 +12}
    {1838214000 39600 0 +12}
    {1853938800 43200 1 +12}
    {1869663600 39600 0 +12}
    {1885993200 43200 1 +12}
    {1901718000 39600 0 +12}
    {1917442800 43200 1 +12}
    {1933167600 39600 0 +12}
    {1948892400 43200 1 +12}
    {1964617200 39600 0 +12}
    {1980342000 43200 1 +12}
    {1996066800 39600 0 +12}
    {2011791600 43200 1 +12}
    {2027516400 39600 0 +12}
    {2043241200 43200 1 +12}
    {2058966000 39600 0 +12}
    {2075295600 43200 1 +12}
    {2091020400 39600 0 +12}
    {2106745200 43200 1 +12}
    {2122470000 39600 0 +12}
    {2138194800 43200 1 +12}
    {2153919600 39600 0 +12}
    {2169644400 43200 1 +12}
    {2185369200 39600 0 +12}
    {2201094000 43200 1 +12}
    {2216818800 39600 0 +12}
    {2233148400 43200 1 +12}
    {2248873200 39600 0 +12}
    {2264598000 43200 1 +12}
    {2280322800 39600 0 +12}
    {2296047600 43200 1 +12}
    {2311772400 39600 0 +12}
    {2327497200 43200 1 +12}
    {2343222000 39600 0 +12}
    {2358946800 43200 1 +12}
    {2374671600 39600 0 +12}
    {2390396400 43200 1 +12}
    {2406121200 39600 0 +12}
    {2422450800 43200 1 +12}
    {2438175600 39600 0 +12}
    {2453900400 43200 1 +12}
    {2469625200 39600 0 +12}
    {2485350000 43200 1 +12}
    {2501074800 39600 0 +12}
    {2516799600 43200 1 +12}
    {2532524400 39600 0 +12}
    {2548249200 43200 1 +12}
    {2563974000 39600 0 +12}
    {2579698800 43200 1 +12}
    {2596028400 39600 0 +12}
    {2611753200 43200 1 +12}
    {2627478000 39600 0 +12}
    {2643202800 43200 1 +12}
    {2658927600 39600 0 +12}
    {2674652400 43200 1 +12}
    {2690377200 39600 0 +12}
    {2706102000 43200 1 +12}
    {2721826800 39600 0 +12}
    {2737551600 43200 1 +12}
    {2753276400 39600 0 +12}
    {2769606000 43200 1 +12}
    {2785330800 39600 0 +12}
    {2801055600 43200 1 +12}
    {2816780400 39600 0 +12}
    {2832505200 43200 1 +12}
    {2848230000 39600 0 +12}
    {2863954800 43200 1 +12}
    {2879679600 39600 0 +12}
    {2895404400 43200 1 +12}
    {2911129200 39600 0 +12}
    {2926854000 43200 1 +12}
    {2942578800 39600 0 +12}
    {2958908400 43200 1 +12}
    {2974633200 39600 0 +12}
    {2990358000 43200 1 +12}
    {3006082800 39600 0 +12}
    {3021807600 43200 1 +12}
    {3037532400 39600 0 +12}
    {3053257200 43200 1 +12}
    {3068982000 39600 0 +12}
    {3084706800 43200 1 +12}
    {3100431600 39600 0 +12}
    {3116761200 43200 1 +12}
    {3132486000 39600 0 +12}
    {3148210800 43200 1 +12}
    {3163935600 39600 0 +12}
    {3179660400 43200 1 +12}
    {3195385200 39600 0 +12}
    {3211110000 43200 1 +12}
    {3226834800 39600 0 +12}
    {3242559600 43200 1 +12}
    {3258284400 39600 0 +12}
    {3274009200 43200 1 +12}
    {3289734000 39600 0 +12}
    {3306063600 43200 1 +12}
    {3321788400 39600 0 +12}
    {3337513200 43200 1 +12}
    {3353238000 39600 0 +12}
    {3368962800 43200 1 +12}
    {3384687600 39600 0 +12}
    {3400412400 43200 1 +12}
    {3416137200 39600 0 +12}
    {3431862000 43200 1 +12}
    {3447586800 39600 0 +12}
    {3463311600 43200 1 +12}
    {3479641200 39600 0 +12}
    {3495366000 43200 1 +12}
    {3511090800 39600 0 +12}
    {3526815600 43200 1 +12}
    {3542540400 39600 0 +12}
    {3558265200 43200 1 +12}
    {3573990000 39600 0 +12}
    {3589714800 43200 1 +12}
    {3605439600 39600 0 +12}
    {3621164400 43200 1 +12}
    {3636889200 39600 0 +12}
    {3653218800 43200 1 +12}
    {3668943600 39600 0 +12}
    {3684668400 43200 1 +12}
    {3700393200 39600 0 +12}
    {3716118000 43200 1 +12}
    {3731842800 39600 0 +12}
    {3747567600 43200 1 +12}
    {3763292400 39600 0 +12}
    {3779017200 43200 1 +12}
    {3794742000 39600 0 +12}
    {3810466800 43200 1 +12}
    {3826191600 39600 0 +12}
    {3842521200 43200 1 +12}
    {3858246000 39600 0 +12}
    {3873970800 43200 1 +12}
    {3889695600 39600 0 +12}
    {3905420400 43200 1 +12}
    {3921145200 39600 0 +12}
    {3936870000 43200 1 +12}
    {3952594800 39600 0 +12}
    {3968319600 43200 1 +12}
    {3984044400 39600 0 +12}
    {4000374000 43200 1 +12}
    {4016098800 39600 0 +12}
    {4031823600 43200 1 +12}
    {4047548400 39600 0 +12}
    {4063273200 43200 1 +12}
    {4078998000 39600 0 +12}
    {4094722800 43200 1 +12}
    {1443882600 39600 0 +1100}
    {1561899600 39600 0 +1100}
    {1570287600 43200 1 +1200}
    {1586012400 39600 0 +1100}
    {1601737200 43200 1 +1200}
    {1617462000 39600 0 +1100}
    {1633186800 43200 1 +1200}
    {1648911600 39600 0 +1100}
    {1664636400 43200 1 +1200}
    {1680361200 39600 0 +1100}
    {1696086000 43200 1 +1200}
    {1712415600 39600 0 +1100}
    {1728140400 43200 1 +1200}
    {1743865200 39600 0 +1100}
    {1759590000 43200 1 +1200}
    {1775314800 39600 0 +1100}
    {1791039600 43200 1 +1200}
    {1806764400 39600 0 +1100}
    {1822489200 43200 1 +1200}
    {1838214000 39600 0 +1100}
    {1853938800 43200 1 +1200}
    {1869663600 39600 0 +1100}
    {1885993200 43200 1 +1200}
    {1901718000 39600 0 +1100}
    {1917442800 43200 1 +1200}
    {1933167600 39600 0 +1100}
    {1948892400 43200 1 +1200}
    {1964617200 39600 0 +1100}
    {1980342000 43200 1 +1200}
    {1996066800 39600 0 +1100}
    {2011791600 43200 1 +1200}
    {2027516400 39600 0 +1100}
    {2043241200 43200 1 +1200}
    {2058966000 39600 0 +1100}
    {2075295600 43200 1 +1200}
    {2091020400 39600 0 +1100}
    {2106745200 43200 1 +1200}
    {2122470000 39600 0 +1100}
    {2138194800 43200 1 +1200}
    {2153919600 39600 0 +1100}
    {2169644400 43200 1 +1200}
    {2185369200 39600 0 +1100}
    {2201094000 43200 1 +1200}
    {2216818800 39600 0 +1100}
    {2233148400 43200 1 +1200}
    {2248873200 39600 0 +1100}
    {2264598000 43200 1 +1200}
    {2280322800 39600 0 +1100}
    {2296047600 43200 1 +1200}
    {2311772400 39600 0 +1100}
    {2327497200 43200 1 +1200}
    {2343222000 39600 0 +1100}
    {2358946800 43200 1 +1200}
    {2374671600 39600 0 +1100}
    {2390396400 43200 1 +1200}
    {2406121200 39600 0 +1100}
    {2422450800 43200 1 +1200}
    {2438175600 39600 0 +1100}
    {2453900400 43200 1 +1200}
    {2469625200 39600 0 +1100}
    {2485350000 43200 1 +1200}
    {2501074800 39600 0 +1100}
    {2516799600 43200 1 +1200}
    {2532524400 39600 0 +1100}
    {2548249200 43200 1 +1200}
    {2563974000 39600 0 +1100}
    {2579698800 43200 1 +1200}
    {2596028400 39600 0 +1100}
    {2611753200 43200 1 +1200}
    {2627478000 39600 0 +1100}
    {2643202800 43200 1 +1200}
    {2658927600 39600 0 +1100}
    {2674652400 43200 1 +1200}
    {2690377200 39600 0 +1100}
    {2706102000 43200 1 +1200}
    {2721826800 39600 0 +1100}
    {2737551600 43200 1 +1200}
    {2753276400 39600 0 +1100}
    {2769606000 43200 1 +1200}
    {2785330800 39600 0 +1100}
    {2801055600 43200 1 +1200}
    {2816780400 39600 0 +1100}
    {2832505200 43200 1 +1200}
    {2848230000 39600 0 +1100}
    {2863954800 43200 1 +1200}
    {2879679600 39600 0 +1100}
    {2895404400 43200 1 +1200}
    {2911129200 39600 0 +1100}
    {2926854000 43200 1 +1200}
    {2942578800 39600 0 +1100}
    {2958908400 43200 1 +1200}
    {2974633200 39600 0 +1100}
    {2990358000 43200 1 +1200}
    {3006082800 39600 0 +1100}
    {3021807600 43200 1 +1200}
    {3037532400 39600 0 +1100}
    {3053257200 43200 1 +1200}
    {3068982000 39600 0 +1100}
    {3084706800 43200 1 +1200}
    {3100431600 39600 0 +1100}
    {3116761200 43200 1 +1200}
    {3132486000 39600 0 +1100}
    {3148210800 43200 1 +1200}
    {3163935600 39600 0 +1100}
    {3179660400 43200 1 +1200}
    {3195385200 39600 0 +1100}
    {3211110000 43200 1 +1200}
    {3226834800 39600 0 +1100}
    {3242559600 43200 1 +1200}
    {3258284400 39600 0 +1100}
    {3274009200 43200 1 +1200}
    {3289734000 39600 0 +1100}
    {3306063600 43200 1 +1200}
    {3321788400 39600 0 +1100}
    {3337513200 43200 1 +1200}
    {3353238000 39600 0 +1100}
    {3368962800 43200 1 +1200}
    {3384687600 39600 0 +1100}
    {3400412400 43200 1 +1200}
    {3416137200 39600 0 +1100}
    {3431862000 43200 1 +1200}
    {3447586800 39600 0 +1100}
    {3463311600 43200 1 +1200}
    {3479641200 39600 0 +1100}
    {3495366000 43200 1 +1200}
    {3511090800 39600 0 +1100}
    {3526815600 43200 1 +1200}
    {3542540400 39600 0 +1100}
    {3558265200 43200 1 +1200}
    {3573990000 39600 0 +1100}
    {3589714800 43200 1 +1200}
    {3605439600 39600 0 +1100}
    {3621164400 43200 1 +1200}
    {3636889200 39600 0 +1100}
    {3653218800 43200 1 +1200}
    {3668943600 39600 0 +1100}
    {3684668400 43200 1 +1200}
    {3700393200 39600 0 +1100}
    {3716118000 43200 1 +1200}
    {3731842800 39600 0 +1100}
    {3747567600 43200 1 +1200}
    {3763292400 39600 0 +1100}
    {3779017200 43200 1 +1200}
    {3794742000 39600 0 +1100}
    {3810466800 43200 1 +1200}
    {3826191600 39600 0 +1100}
    {3842521200 43200 1 +1200}
    {3858246000 39600 0 +1100}
    {3873970800 43200 1 +1200}
    {3889695600 39600 0 +1100}
    {3905420400 43200 1 +1200}
    {3921145200 39600 0 +1100}
    {3936870000 43200 1 +1200}
    {3952594800 39600 0 +1100}
    {3968319600 43200 1 +1200}
    {3984044400 39600 0 +1100}
    {4000374000 43200 1 +1200}
    {4016098800 39600 0 +1100}
    {4031823600 43200 1 +1200}
    {4047548400 39600 0 +1100}
    {4063273200 43200 1 +1200}
    {4078998000 39600 0 +1100}
    {4094722800 43200 1 +1200}
}

Changes to library/tzdata/Pacific/Noumea.

1
2
3
4
5
6
7
8
9
10
11







12
1
2
3
4







5
6
7
8
9
10
11
12




-
-
-
-
-
-
-
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Noumea) {
    {-9223372036854775808 39948 0 LMT}
    {-1829387148 39600 0 +11}
    {250002000 43200 1 +11}
    {257342400 39600 0 +11}
    {281451600 43200 1 +11}
    {288878400 39600 0 +11}
    {849366000 43200 1 +11}
    {857228400 39600 0 +11}
    {-1829387148 39600 0 +1100}
    {250002000 43200 1 +1200}
    {257342400 39600 0 +1100}
    {281451600 43200 1 +1200}
    {288878400 39600 0 +1100}
    {849366000 43200 1 +1200}
    {857228400 39600 0 +1100}
}

Changes to library/tzdata/Pacific/Palau.

1
2
3
4
5
6

7
1
2
3
4
5

6
7





-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Palau) {
    {-9223372036854775808 -54124 0 LMT}
    {-3944624276 32276 0 LMT}
    {-2177485076 32400 0 +09}
    {-2177485076 32400 0 +0900}
}

Changes to library/tzdata/Pacific/Pitcairn.

1
2
3
4
5
6


7
1
2
3
4


5
6
7




-
-
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Pitcairn) {
    {-9223372036854775808 -31220 0 LMT}
    {-2177421580 -30600 0 -0830}
    {893665800 -28800 0 -08}
    {-2177421580 -30600 0 -0930}
    {893665800 -28800 0 -0800}
}

Changes to library/tzdata/Pacific/Pohnpei.

1


2
3


4
5
6
7
8
9
10
11
12
1
2
3


4
5










+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Guadalcanal)]} {
    LoadTimeZoneFile Pacific/Guadalcanal

set TZData(:Pacific/Pohnpei) {
}
set TZData(:Pacific/Pohnpei) $TZData(:Pacific/Guadalcanal)
    {-9223372036854775808 -48428 0 LMT}
    {-3944629972 37972 0 LMT}
    {-2177490772 39600 0 +11}
    {-1743678000 32400 0 +09}
    {-1606813200 39600 0 +11}
    {-1041418800 36000 0 +10}
    {-907408800 32400 0 +09}
    {-770634000 39600 0 +11}
}

Changes to library/tzdata/Pacific/Ponape.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Pohnpei)]} {
    LoadTimeZoneFile Pacific/Pohnpei
if {![info exists TZData(Pacific/Guadalcanal)]} {
    LoadTimeZoneFile Pacific/Guadalcanal
}
set TZData(:Pacific/Ponape) $TZData(:Pacific/Pohnpei)
set TZData(:Pacific/Ponape) $TZData(:Pacific/Guadalcanal)

Changes to library/tzdata/Pacific/Port_Moresby.

1
2
3
4
5
6

7
1
2
3
4
5

6
7





-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Port_Moresby) {
    {-9223372036854775808 35320 0 LMT}
    {-2840176120 35312 0 PMMT}
    {-2366790512 36000 0 +10}
    {-2366790512 36000 0 +1000}
}

Changes to library/tzdata/Pacific/Rarotonga.

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
30
31





























32
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
30
31
32
33



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Rarotonga) {
    {-9223372036854775808 -38344 0 LMT}
    {-2177414456 -37800 0 -1030}
    {279714600 -34200 0 -10}
    {289387800 -36000 0 -10}
    {309952800 -34200 1 -10}
    {320837400 -36000 0 -10}
    {341402400 -34200 1 -10}
    {352287000 -36000 0 -10}
    {372852000 -34200 1 -10}
    {384341400 -36000 0 -10}
    {404906400 -34200 1 -10}
    {415791000 -36000 0 -10}
    {436356000 -34200 1 -10}
    {447240600 -36000 0 -10}
    {467805600 -34200 1 -10}
    {478690200 -36000 0 -10}
    {499255200 -34200 1 -10}
    {510139800 -36000 0 -10}
    {530704800 -34200 1 -10}
    {541589400 -36000 0 -10}
    {562154400 -34200 1 -10}
    {573643800 -36000 0 -10}
    {594208800 -34200 1 -10}
    {605093400 -36000 0 -10}
    {625658400 -34200 1 -10}
    {636543000 -36000 0 -10}
    {657108000 -34200 1 -10}
    {667992600 -36000 0 -10}
    {-9223372036854775808 48056 0 LMT}
    {-2209555256 -38344 0 LMT}
    {-543072056 -37800 0 -1130}
    {279714600 -34200 0 -1030}
    {289387800 -36000 0 -1000}
    {309952800 -34200 1 -1030}
    {320837400 -36000 0 -1000}
    {341402400 -34200 1 -1030}
    {352287000 -36000 0 -1000}
    {372852000 -34200 1 -1030}
    {384341400 -36000 0 -1000}
    {404906400 -34200 1 -1030}
    {415791000 -36000 0 -1000}
    {436356000 -34200 1 -1030}
    {447240600 -36000 0 -1000}
    {467805600 -34200 1 -1030}
    {478690200 -36000 0 -1000}
    {499255200 -34200 1 -1030}
    {510139800 -36000 0 -1000}
    {530704800 -34200 1 -1030}
    {541589400 -36000 0 -1000}
    {562154400 -34200 1 -1030}
    {573643800 -36000 0 -1000}
    {594208800 -34200 1 -1030}
    {605093400 -36000 0 -1000}
    {625658400 -34200 1 -1030}
    {636543000 -36000 0 -1000}
    {657108000 -34200 1 -1030}
    {667992600 -36000 0 -1000}
}

Changes to library/tzdata/Pacific/Tahiti.

1
2
3
4
5

6
1
2
3
4

5
6




-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Tahiti) {
    {-9223372036854775808 -35896 0 LMT}
    {-1806674504 -36000 0 -10}
    {-1806674504 -36000 0 -1000}
}

Changes to library/tzdata/Pacific/Tarawa.

1
2
3
4
5

6
1
2
3
4

5
6




-
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Tarawa) {
    {-9223372036854775808 41524 0 LMT}
    {-2177494324 43200 0 +12}
    {-2177494324 43200 0 +1200}
}

Changes to library/tzdata/Pacific/Tongatapu.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15












16
1
2
3












4
5
6
7
8
9
10
11
12
13
14
15
16



-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Tongatapu) {
    {-9223372036854775808 44360 0 LMT}
    {-2177497160 44400 0 +1220}
    {-915193200 46800 0 +13}
    {915102000 46800 0 +13}
    {939214800 50400 1 +13}
    {953384400 46800 0 +13}
    {973342800 50400 1 +13}
    {980596800 46800 0 +13}
    {1004792400 50400 1 +13}
    {1012046400 46800 0 +13}
    {1478350800 50400 1 +13}
    {1484398800 46800 0 +13}
    {-9223372036854775808 44352 0 LMT}
    {-767189952 44400 0 +1220}
    {-284041200 46800 0 +1300}
    {915102000 46800 0 +1300}
    {939214800 50400 1 +1400}
    {953384400 46800 0 +1300}
    {973342800 50400 1 +1400}
    {980596800 46800 0 +1300}
    {1004792400 50400 1 +1400}
    {1012046400 46800 0 +1300}
    {1478350800 50400 1 +1400}
    {1484398800 46800 0 +1300}
}

Changes to library/tzdata/Pacific/Truk.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Chuuk)]} {
    LoadTimeZoneFile Pacific/Chuuk
if {![info exists TZData(Pacific/Port_Moresby)]} {
    LoadTimeZoneFile Pacific/Port_Moresby
}
set TZData(:Pacific/Truk) $TZData(:Pacific/Chuuk)
set TZData(:Pacific/Truk) $TZData(:Pacific/Port_Moresby)

Changes to library/tzdata/Pacific/Wake.

1


2
3


4
5
6
1
2
3


4
5




+
+
-
-
+
+
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Tarawa)]} {
    LoadTimeZoneFile Pacific/Tarawa

set TZData(:Pacific/Wake) {
}
set TZData(:Pacific/Wake) $TZData(:Pacific/Tarawa)
    {-9223372036854775808 39988 0 LMT}
    {-2177492788 43200 0 +12}
}

Changes to library/tzdata/Pacific/Wallis.

1


2
3


4
5
6
1
2
3


4
5




+
+
-
-
+
+
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Tarawa)]} {
    LoadTimeZoneFile Pacific/Tarawa

set TZData(:Pacific/Wallis) {
}
set TZData(:Pacific/Wallis) $TZData(:Pacific/Tarawa)
    {-9223372036854775808 44120 0 LMT}
    {-2177496920 43200 0 +12}
}

Changes to library/tzdata/Pacific/Yap.

1
2
3


4
5

1


2
3
4

5

-
-
+
+

-
+
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Chuuk)]} {
    LoadTimeZoneFile Pacific/Chuuk
if {![info exists TZData(Pacific/Port_Moresby)]} {
    LoadTimeZoneFile Pacific/Port_Moresby
}
set TZData(:Pacific/Yap) $TZData(:Pacific/Chuuk)
set TZData(:Pacific/Yap) $TZData(:Pacific/Port_Moresby)

Deleted library/tzdata/US/Pacific-New.

1
2
3
4
5





-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Los_Angeles)]} {
    LoadTimeZoneFile America/Los_Angeles
}
set TZData(:US/Pacific-New) $TZData(:America/Los_Angeles)

Changes to library/tzdata/WET.

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
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
1
2
3


4
5

























































































































































































































































+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Lisbon)]} {
    LoadTimeZoneFile Europe/Lisbon

set TZData(:WET) {
}
set TZData(:WET) $TZData(:Europe/Lisbon)
    {-9223372036854775808 0 0 WET}
    {228877200 3600 1 WEST}
    {243997200 0 0 WET}
    {260326800 3600 1 WEST}
    {276051600 0 0 WET}
    {291776400 3600 1 WEST}
    {307501200 0 0 WET}
    {323830800 3600 1 WEST}
    {338950800 0 0 WET}
    {354675600 3600 1 WEST}
    {370400400 0 0 WET}
    {386125200 3600 1 WEST}
    {401850000 0 0 WET}
    {417574800 3600 1 WEST}
    {433299600 0 0 WET}
    {449024400 3600 1 WEST}
    {465354000 0 0 WET}
    {481078800 3600 1 WEST}
    {496803600 0 0 WET}
    {512528400 3600 1 WEST}
    {528253200 0 0 WET}
    {543978000 3600 1 WEST}
    {559702800 0 0 WET}
    {575427600 3600 1 WEST}
    {591152400 0 0 WET}
    {606877200 3600 1 WEST}
    {622602000 0 0 WET}
    {638326800 3600 1 WEST}
    {654656400 0 0 WET}
    {670381200 3600 1 WEST}
    {686106000 0 0 WET}
    {701830800 3600 1 WEST}
    {717555600 0 0 WET}
    {733280400 3600 1 WEST}
    {749005200 0 0 WET}
    {764730000 3600 1 WEST}
    {780454800 0 0 WET}
    {796179600 3600 1 WEST}
    {811904400 0 0 WET}
    {828234000 3600 1 WEST}
    {846378000 0 0 WET}
    {859683600 3600 1 WEST}
    {877827600 0 0 WET}
    {891133200 3600 1 WEST}
    {909277200 0 0 WET}
    {922582800 3600 1 WEST}
    {941331600 0 0 WET}
    {954032400 3600 1 WEST}
    {972781200 0 0 WET}
    {985482000 3600 1 WEST}
    {1004230800 0 0 WET}
    {1017536400 3600 1 WEST}
    {1035680400 0 0 WET}
    {1048986000 3600 1 WEST}
    {1067130000 0 0 WET}
    {1080435600 3600 1 WEST}
    {1099184400 0 0 WET}
    {1111885200 3600 1 WEST}
    {1130634000 0 0 WET}
    {1143334800 3600 1 WEST}
    {1162083600 0 0 WET}
    {1174784400 3600 1 WEST}
    {1193533200 0 0 WET}
    {1206838800 3600 1 WEST}
    {1224982800 0 0 WET}
    {1238288400 3600 1 WEST}
    {1256432400 0 0 WET}
    {1269738000 3600 1 WEST}
    {1288486800 0 0 WET}
    {1301187600 3600 1 WEST}
    {1319936400 0 0 WET}
    {1332637200 3600 1 WEST}
    {1351386000 0 0 WET}
    {1364691600 3600 1 WEST}
    {1382835600 0 0 WET}
    {1396141200 3600 1 WEST}
    {1414285200 0 0 WET}
    {1427590800 3600 1 WEST}
    {1445734800 0 0 WET}
    {1459040400 3600 1 WEST}
    {1477789200 0 0 WET}
    {1490490000 3600 1 WEST}
    {1509238800 0 0 WET}
    {1521939600 3600 1 WEST}
    {1540688400 0 0 WET}
    {1553994000 3600 1 WEST}
    {1572138000 0 0 WET}
    {1585443600 3600 1 WEST}
    {1603587600 0 0 WET}
    {1616893200 3600 1 WEST}
    {1635642000 0 0 WET}
    {1648342800 3600 1 WEST}
    {1667091600 0 0 WET}
    {1679792400 3600 1 WEST}
    {1698541200 0 0 WET}
    {1711846800 3600 1 WEST}
    {1729990800 0 0 WET}
    {1743296400 3600 1 WEST}
    {1761440400 0 0 WET}
    {1774746000 3600 1 WEST}
    {1792890000 0 0 WET}
    {1806195600 3600 1 WEST}
    {1824944400 0 0 WET}
    {1837645200 3600 1 WEST}
    {1856394000 0 0 WET}
    {1869094800 3600 1 WEST}
    {1887843600 0 0 WET}
    {1901149200 3600 1 WEST}
    {1919293200 0 0 WET}
    {1932598800 3600 1 WEST}
    {1950742800 0 0 WET}
    {1964048400 3600 1 WEST}
    {1982797200 0 0 WET}
    {1995498000 3600 1 WEST}
    {2014246800 0 0 WET}
    {2026947600 3600 1 WEST}
    {2045696400 0 0 WET}
    {2058397200 3600 1 WEST}
    {2077146000 0 0 WET}
    {2090451600 3600 1 WEST}
    {2108595600 0 0 WET}
    {2121901200 3600 1 WEST}
    {2140045200 0 0 WET}
    {2153350800 3600 1 WEST}
    {2172099600 0 0 WET}
    {2184800400 3600 1 WEST}
    {2203549200 0 0 WET}
    {2216250000 3600 1 WEST}
    {2234998800 0 0 WET}
    {2248304400 3600 1 WEST}
    {2266448400 0 0 WET}
    {2279754000 3600 1 WEST}
    {2297898000 0 0 WET}
    {2311203600 3600 1 WEST}
    {2329347600 0 0 WET}
    {2342653200 3600 1 WEST}
    {2361402000 0 0 WET}
    {2374102800 3600 1 WEST}
    {2392851600 0 0 WET}
    {2405552400 3600 1 WEST}
    {2424301200 0 0 WET}
    {2437606800 3600 1 WEST}
    {2455750800 0 0 WET}
    {2469056400 3600 1 WEST}
    {2487200400 0 0 WET}
    {2500506000 3600 1 WEST}
    {2519254800 0 0 WET}
    {2531955600 3600 1 WEST}
    {2550704400 0 0 WET}
    {2563405200 3600 1 WEST}
    {2582154000 0 0 WET}
    {2595459600 3600 1 WEST}
    {2613603600 0 0 WET}
    {2626909200 3600 1 WEST}
    {2645053200 0 0 WET}
    {2658358800 3600 1 WEST}
    {2676502800 0 0 WET}
    {2689808400 3600 1 WEST}
    {2708557200 0 0 WET}
    {2721258000 3600 1 WEST}
    {2740006800 0 0 WET}
    {2752707600 3600 1 WEST}
    {2771456400 0 0 WET}
    {2784762000 3600 1 WEST}
    {2802906000 0 0 WET}
    {2816211600 3600 1 WEST}
    {2834355600 0 0 WET}
    {2847661200 3600 1 WEST}
    {2866410000 0 0 WET}
    {2879110800 3600 1 WEST}
    {2897859600 0 0 WET}
    {2910560400 3600 1 WEST}
    {2929309200 0 0 WET}
    {2942010000 3600 1 WEST}
    {2960758800 0 0 WET}
    {2974064400 3600 1 WEST}
    {2992208400 0 0 WET}
    {3005514000 3600 1 WEST}
    {3023658000 0 0 WET}
    {3036963600 3600 1 WEST}
    {3055712400 0 0 WET}
    {3068413200 3600 1 WEST}
    {3087162000 0 0 WET}
    {3099862800 3600 1 WEST}
    {3118611600 0 0 WET}
    {3131917200 3600 1 WEST}
    {3150061200 0 0 WET}
    {3163366800 3600 1 WEST}
    {3181510800 0 0 WET}
    {3194816400 3600 1 WEST}
    {3212960400 0 0 WET}
    {3226266000 3600 1 WEST}
    {3245014800 0 0 WET}
    {3257715600 3600 1 WEST}
    {3276464400 0 0 WET}
    {3289165200 3600 1 WEST}
    {3307914000 0 0 WET}
    {3321219600 3600 1 WEST}
    {3339363600 0 0 WET}
    {3352669200 3600 1 WEST}
    {3370813200 0 0 WET}
    {3384118800 3600 1 WEST}
    {3402867600 0 0 WET}
    {3415568400 3600 1 WEST}
    {3434317200 0 0 WET}
    {3447018000 3600 1 WEST}
    {3465766800 0 0 WET}
    {3479072400 3600 1 WEST}
    {3497216400 0 0 WET}
    {3510522000 3600 1 WEST}
    {3528666000 0 0 WET}
    {3541971600 3600 1 WEST}
    {3560115600 0 0 WET}
    {3573421200 3600 1 WEST}
    {3592170000 0 0 WET}
    {3604870800 3600 1 WEST}
    {3623619600 0 0 WET}
    {3636320400 3600 1 WEST}
    {3655069200 0 0 WET}
    {3668374800 3600 1 WEST}
    {3686518800 0 0 WET}
    {3699824400 3600 1 WEST}
    {3717968400 0 0 WET}
    {3731274000 3600 1 WEST}
    {3750022800 0 0 WET}
    {3762723600 3600 1 WEST}
    {3781472400 0 0 WET}
    {3794173200 3600 1 WEST}
    {3812922000 0 0 WET}
    {3825622800 3600 1 WEST}
    {3844371600 0 0 WET}
    {3857677200 3600 1 WEST}
    {3875821200 0 0 WET}
    {3889126800 3600 1 WEST}
    {3907270800 0 0 WET}
    {3920576400 3600 1 WEST}
    {3939325200 0 0 WET}
    {3952026000 3600 1 WEST}
    {3970774800 0 0 WET}
    {3983475600 3600 1 WEST}
    {4002224400 0 0 WET}
    {4015530000 3600 1 WEST}
    {4033674000 0 0 WET}
    {4046979600 3600 1 WEST}
    {4065123600 0 0 WET}
    {4078429200 3600 1 WEST}
    {4096573200 0 0 WET}
}

Changes to library/word.tcl.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







# word.tcl --
#
# This file defines various procedures for computing word boundaries in
# strings. This file is primarily needed so Tk text and entry widgets behave
# properly for different platforms.
#
# Copyright (c) 1996 by Sun Microsystems, Inc.
# Copyright (c) 1998 by Scritpics Corporation.
# Copyright © 1996 Sun Microsystems, Inc.
# Copyright © 1998 Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

# The following variables are used to determine which characters are
# interpreted as word characters. See bug [f1253530cdd8]. Will
# probably be removed in Tcl 9.
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
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







+
+
+


















+
-
+
+


















+
+
+


















+
+
+

















-
+




# Arguments:
# str -		String to search.
# start -	Index into string specifying starting point.

proc tcl_wordBreakAfter {str start} {
    variable ::tcl::WordBreakRE
    set result {-1 -1}
    if {$start < 0} {
	set start 0;
    }
    regexp -indices -start $start -- $WordBreakRE(after) $str result
    return [lindex $result 1]
}

# tcl_wordBreakBefore --
#
# This procedure returns the index of the first word boundary before the
# starting point in the given string, or -1 if there are no more boundaries in
# the given string. The index returned refers to the second character of the
# pair that comprises a boundary.
#
# Arguments:
# str -		String to search.
# start -	Index into string specifying starting point.

proc tcl_wordBreakBefore {str start} {
    variable ::tcl::WordBreakRE
    set result {-1 -1}
    if {$start >= 0} {
    regexp -indices -- $WordBreakRE(before) [string range $str 0 $start] result
	regexp -indices -- $WordBreakRE(before) [string range $str 0 $start] result
    }
    return [lindex $result 1]
}

# tcl_endOfWord --
#
# This procedure returns the index of the first end-of-word location after a
# starting index in the given string. An end-of-word location is defined to be
# the first whitespace character following the first non-whitespace character
# after the starting point. Returns -1 if there are no more words after the
# starting point.
#
# Arguments:
# str -		String to search.
# start -	Index into string specifying starting point.

proc tcl_endOfWord {str start} {
    variable ::tcl::WordBreakRE
    set result {-1 -1}
    if {$start < 0} {
	set start 0
    }
    regexp -indices -start $start -- $WordBreakRE(end) $str result
    return [lindex $result 1]
}

# tcl_startOfNextWord --
#
# This procedure returns the index of the first start-of-word location after a
# starting index in the given string. A start-of-word location is defined to
# be a non-whitespace character following a whitespace character. Returns -1
# if there are no more start-of-word locations after the starting point.
#
# Arguments:
# str -		String to search.
# start -	Index into string specifying starting point.

proc tcl_startOfNextWord {str start} {
    variable ::tcl::WordBreakRE
    set result {-1 -1}
    if {$start < 0} {
	set start 0
    }
    regexp -indices -start $start -- $WordBreakRE(next) $str result
    return [lindex $result 1]
}

# tcl_startOfPreviousWord --
#
# This procedure returns the index of the first start-of-word location before
# a starting index in the given string.
#
# Arguments:
# str -		String to search.
# start -	Index into string specifying starting point.

proc tcl_startOfPreviousWord {str start} {
    variable ::tcl::WordBreakRE
    set word {-1 -1}
    if {$start > 0} {
	regexp -indices -- $WordBreakRE(previous) [string range $str 0 $start-1] \
	regexp -indices -- $WordBreakRE(previous) [string range [string range $str 0 $start] 0 end-1] \
		result word
    }
    return [lindex $word 0]
}

Added library/writefile.tcl.






































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
30
31
32
33
34
35
36
37
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# writeFile:
# Write the contents of a file.
#
# Copyright © 2023 Donal K Fellows.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#

proc writeFile {args} {
    # Parse the arguments
    switch [llength $args] {
	2 {
	    lassign $args filename data
	    set mode text
	}
	3 {
	    lassign $args filename mode data
	    set MODES {binary text}
	    set ERR [list -level 1 -errorcode [list TCL LOOKUP MODE $mode]]
	    set mode [tcl::prefix match -message "mode" -error $ERR $MODES $mode]
	}
	default {
	    set COMMAND [lindex [info level 0] 0]
	    return -code error -errorcode {TCL WRONGARGS} \
		"wrong # args: should be \"$COMMAND filename ?mode? data\""
	}
    }

    # Write the file
    set f [open $filename [dict get {text w binary wb} $mode]]
    try {
	puts -nonewline $f $data
    } finally {
	close $f
    }
}

Added libtommath/CMakeLists.txt.
























































































































































































































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# SPDX-License-Identifier: Unlicense
#
# LibTomMath, a free open source portable number theoretic multiple-precision
# integer (MPI) library written entirely in C.
#

cmake_minimum_required(VERSION 3.10)

project(libtommath
    VERSION 1.3.0
    DESCRIPTION "A free open source portable number theoretic multiple-precision integer (MPI) library written entirely in C."
    HOMEPAGE_URL "https://www.libtom.net/LibTomMath"
    LANGUAGES C)

# package release version
# bump if re-releasing the same VERSION + patches
# set to 1 if releasing a new VERSION
set(PACKAGE_RELEASE_VERSION 1)

#-----------------------------------------------------------------------------
# Include cmake modules
#-----------------------------------------------------------------------------
include(GNUInstallDirs)
include(CheckIPOSupported)
include(CMakePackageConfigHelpers)
# default is "No tests"
option(BUILD_TESTING "" OFF)
include(CTest)
include(sources.cmake)

#-----------------------------------------------------------------------------
# Options
#-----------------------------------------------------------------------------
option(BUILD_SHARED_LIBS "Build shared library and only the shared library if \"ON\", default is static" OFF)

#-----------------------------------------------------------------------------
# Add support for ccache if desired
#-----------------------------------------------------------------------------
find_program(CCACHE ccache)

if(CCACHE)
    option(ENABLE_CCACHE "Enable ccache." ON)
endif()

# use ccache if installed
if(CCACHE AND ENABLE_CCACHE)
    set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE})
endif()

#-----------------------------------------------------------------------------
# Compose CFLAGS
#-----------------------------------------------------------------------------

# Some information ported from makefile_include.mk


if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  message(STATUS "Setting build type to 'Release' as none was specified.")
  set(CMAKE_BUILD_TYPE "Release")
endif()

# We only differentiate between MSVC and GCC-compatible compilers
if(MSVC)
    set(LTM_C_FLAGS -W3)
elseif(WATCOM)
    set(LTM_C_FLAGS -fo=.obj -oaxt -3r -w3)
else()
    set(LTM_C_FLAGS -Wall -Wsign-compare -Wextra -Wshadow
                    -Wdeclaration-after-statement -Wbad-function-cast -Wcast-align
                    -Wstrict-prototypes -Wpointer-arith -Wsystem-headers)
    set(CMAKE_C_FLAGS_DEBUG "-g3")
    set(CMAKE_C_FLAGS_RELEASE "-O3 -funroll-loops -fomit-frame-pointer")
    set(CMAKE_C_FLAGS_RELWITHDEBINFO "-g3 -O2")
    set(CMAKE_C_FLAGS_MINSIZEREL "-Os")
endif()

# What compiler do we have and what are their...uhm... peculiarities
if(CMAKE_C_COMPILER_ID MATCHES "(C|c?)lang")
    list(APPEND LTM_C_FLAGS -Wno-typedef-redefinition -Wno-tautological-compare -Wno-builtin-requires-header)
    # Clang requires at least '-O1' for dead code elimination
    set(CMAKE_C_FLAGS_DEBUG "-O1 ${CMAKE_C_FLAGS_DEBUG}")
endif()
if(CMAKE_C_COMPILER MATCHES "mingw")
    list(APPEND LTM_C_FLAGS -Wno-shadow -Wno-expansion-to-defined -Wno-declaration-after-statement -Wno-bad-function-cast)
endif()
if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
    list(APPEND LTM_C_FLAGS -Wno-nullability-completeness)
endif()
if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN")
    list(APPEND LTM_C_FLAGS -no-undefined)
endif()

# TODO: coverage (lgcov)

# If the user set the environment variables at generate-time, append them
# in order to allow overriding our defaults.
# ${LTM_CFLAGS} means the user passed it via sth like:
# $ cmake -DLTM_CFLAGS="foo"
list(APPEND LTM_C_FLAGS ${LTM_CFLAGS})
list(APPEND LTM_LD_FLAGS ${LTM_LDFLAGS})

#-----------------------------------------------------------------------------
# library target
#-----------------------------------------------------------------------------
add_library(${PROJECT_NAME}
    ${SOURCES}
    ${HEADERS}
)

target_include_directories(${PROJECT_NAME} PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}>
)

target_compile_options(${PROJECT_NAME} BEFORE PRIVATE
    ${LTM_C_FLAGS}
)
target_link_options(${PROJECT_NAME} BEFORE PRIVATE
    ${LTM_LD_FLAGS}
)

set(PUBLIC_HEADERS tommath.h)
set(C89 False CACHE BOOL "(Usually maintained automatically) Enable when the library is in c89 mode to package the correct header files on install")
if(C89)
    list(APPEND PUBLIC_HEADERS tommath_c89.h)
endif()

set_target_properties(${PROJECT_NAME} PROPERTIES
    OUTPUT_NAME tommath
    VERSION ${PROJECT_VERSION}
    SOVERSION ${PROJECT_VERSION_MAJOR}
    PUBLIC_HEADER "${PUBLIC_HEADERS}"
)

option(COMPILE_LTO "Build with LTO enabled")
if(COMPILE_LTO)
    check_ipo_supported(RESULT COMPILER_SUPPORTS_LTO)
    if(COMPILER_SUPPORTS_LTO)
        set_property(TARGET ${PROJECT_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
    else()
        message(SEND_ERROR "This compiler does not support LTO. Reconfigure ${PROJECT_NAME} with -DCOMPILE_LTO=OFF.")
    endif()
endif()

#-----------------------------------------------------------------------------
# demo target
#-----------------------------------------------------------------------------

if(BUILD_TESTING)
    enable_testing()
    add_subdirectory(demo)
endif()

#-----------------------------------------------------------------------------
# Install/export targets and files
#-----------------------------------------------------------------------------
set(CONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
set(PROJECT_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake")
set(PROJECT_CONFIG_FILE "${PROJECT_NAME}-config.cmake")
set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")

install(TARGETS ${PROJECT_NAME}
    EXPORT ${TARGETS_EXPORT_NAME}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT Libraries
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

# Install libtommath.pc for pkg-config if we build a shared library
if(BUILD_SHARED_LIBS)
    # Let the user override the default directory of the pkg-config file (usually this shouldn't be required to be changed)
    set(CMAKE_INSTALL_PKGCONFIGDIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig" CACHE PATH "Folder where to install .pc files")

    configure_file(
        ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc.in
        ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc
        @ONLY
    )

    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc
        DESTINATION ${CMAKE_INSTALL_PKGCONFIGDIR}
    )
endif()

# generate package version file
write_basic_package_version_file(
    ${PROJECT_VERSION_FILE}
    VERSION ${PROJECT_VERSION}
    COMPATIBILITY SameMajorVersion
)

# install version file
install(FILES ${PROJECT_VERSION_FILE}
        DESTINATION ${CONFIG_INSTALL_DIR}
)

# build directory package config
export(EXPORT ${TARGETS_EXPORT_NAME}
       FILE ${PROJECT_CONFIG_FILE}
)

# installed package config
install(EXPORT ${TARGETS_EXPORT_NAME}
        DESTINATION ${CONFIG_INSTALL_DIR}
        FILE ${PROJECT_CONFIG_FILE}
)

# add to CMake registry
export(PACKAGE ${PROJECT_NAME})

#---------------------------------------------------------------------------------------
# Create release packages
#---------------------------------------------------------------------------------------

# determine distribution and architecture
find_program(LSB_RELEASE lsb_release)
find_program(SYSCTL sysctl)
find_program(UNAME uname)

if(UNAME)
    execute_process(COMMAND uname -m OUTPUT_VARIABLE MACHINE_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
elseif(SYSCTL)
    execute_process(COMMAND sysctl -b hw.machine_arch OUTPUT_VARIABLE MACHINE_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
else()
    string(TOLOWER ${CMAKE_SYSTEM_NAME} MACHINE_ARCH)
endif()

if(LSB_RELEASE)
    execute_process(COMMAND lsb_release -si OUTPUT_VARIABLE LINUX_DISTRO OUTPUT_STRIP_TRAILING_WHITESPACE)
    execute_process(COMMAND lsb_release -sc OUTPUT_VARIABLE LINUX_DISTRO_CODENAME OUTPUT_STRIP_TRAILING_WHITESPACE)
    execute_process(COMMAND lsb_release -sr OUTPUT_VARIABLE LINUX_DISTRO_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)

    string(TOLOWER ${LINUX_DISTRO} LINUX_DISTRO)
    if(LINUX_DISTRO_CODENAME STREQUAL "n/a")
        set(DISTRO_PACK_PATH ${LINUX_DISTRO}/${LINUX_DISTRO_VERSION}/)
    else()
        set(DISTRO_PACK_PATH ${LINUX_DISTRO}/${LINUX_DISTRO_CODENAME}/)
    endif()
else()
    set(DISTRO_PACK_PATH ${CMAKE_SYSTEM_NAME}/)
endif()

# make sure untagged versions get a different package name
execute_process(COMMAND git describe --exact-match --tags ERROR_QUIET RESULT_VARIABLE REPO_HAS_TAG)
if(REPO_HAS_TAG EQUAL 0)
    set(PACKAGE_NAME_SUFFIX "")
else()
    set(PACKAGE_NAME_SUFFIX "-git")
    message(STATUS "Use -git suffix")
endif()

# default CPack generators
set(CPACK_GENERATOR TGZ STGZ)

# extra CPack generators
if(LINUX_DISTRO STREQUAL "debian" OR LINUX_DISTRO STREQUAL "ubuntu" OR LINUX_DISTRO STREQUAL "linuxmint")
    list(APPEND CPACK_GENERATOR DEB)
elseif(LINUX_DISTRO STREQUAL "fedora" OR LINUX_DISTRO STREQUAL "opensuse" OR LINUX_DISTRO STREQUAL "centos")
    list(APPEND CPACK_GENERATOR RPM)
elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
    list(APPEND CPACK_GENERATOR FREEBSD)
endif()

set(LTM_DEBIAN_SHARED_PACKAGE_NAME "${PROJECT_NAME}${PACKAGE_NAME_SUFFIX}${PROJECT_VERSION_MAJOR}")

# general CPack config
set(CPACK_PACKAGE_DIRECTORY ${CMAKE_BINARY_DIR}/packages/${DISTRO_PACK_PATH})
message(STATUS "CPack: packages will be generated under ${CPACK_PACKAGE_DIRECTORY}")
if(BUILD_SHARED_LIBS)
    set(CPACK_PACKAGE_NAME "${PROJECT_NAME}${PROJECT_VERSION_MAJOR}")
    set(CPACK_DEBIAN_PACKAGE_NAME "${LTM_DEBIAN_SHARED_PACKAGE_NAME}")
else()
    set(CPACK_PACKAGE_NAME "${PROJECT_NAME}-devel")
    set(CPACK_DEBIAN_LIBRARIES_PACKAGE_NAME "${PROJECT_NAME}${PACKAGE_NAME_SUFFIX}-dev")
endif()
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "LibTomMath")
set(CPACK_PACKAGE_VENDOR "libtom projects")
set(CPACK_PACKAGE_CONTACT "libtom@googlegroups.com")
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
set(PACKAGE_NAME_TRAILER ${CPACK_PACKAGE_VERSION}-${PACKAGE_RELEASE_VERSION}_${MACHINE_ARCH})
set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${PACKAGE_NAME_TRAILER})

# deb specific CPack config
set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)
set(CPACK_DEBIAN_DEBUGINFO_PACKAGE ON)
set(CPACK_DEBIAN_PACKAGE_RELEASE ${PACKAGE_RELEASE_VERSION})
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
if(BUILD_SHARED_LIBS)
    set(CPACK_DEBIAN_PACKAGE_SECTION "libs")
else()
    set(CPACK_DEBIAN_PACKAGE_SECTION "devel")
    set(CPACK_DEBIAN_PACKAGE_DEPENDS ${LTM_DEBIAN_SHARED_PACKAGE_NAME})
    set(CPACK_DEB_COMPONENT_INSTALL ON)
    set(CPACK_ARCHIVE_COMPONENT_INSTALL ON)
    set(CPACK_COMPONENTS_ALL Libraries)
endif()

# rpm specific CPack config
set(CPACK_RPM_PACKAGE_RELEASE ${PACKAGE_RELEASE_VERSION})
set(CPACK_RPM_PACKAGE_ARCHITECTURE ${MACHINE_ARCH})
set(CPACK_RPM_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-${PROJECT_VERSION}")
set(CPACK_RPM_PACKAGE_LICENSE "The Unlicense")

# FreeBSD specific CPack config
set(CPACK_FREEBSD_PACKAGE_MAINTAINER "gahr@FreeBSD.org")
set(CPACK_FREEBSD_PACKAGE_ORIGIN "math/libtommath")
set(CPACK_FREEBSD_PACKAGE_CATEGORIES "math")

include(CPack)

Changes to libtommath/appveyor.yml.

1

2
3
4
5
6
7
8
9
10
11
12
13
14

1
2
3
4
5
6

7
8
9
10
11
12
13
-
+





-







version: 1.2.0-{build}
version: 1.3.0-{build}
branches:
  only:
  - master
  - develop
  - /^release/
  - /^support/
  - /^travis/
image:
- Visual Studio 2019
- Visual Studio 2017
- Visual Studio 2015
build_script:
- cmd: >-

Changes to libtommath/bn_deprecated.c.

69
70
71
72
73
74
75






76
77
78
79
80
81
82
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88







+
+
+
+
+
+







}
#endif
#ifdef BN_MP_BALANCE_MUL_C
mp_err mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c)
{
   return s_mp_balance_mul(a, b, c);
}
#endif
#ifdef BN_MP_DIV_3_C
mp_err mp_div_3(const mp_int *a, mp_int *c, mp_digit *d)
{
   return s_mp_div_3(a, c, d);
}
#endif
#ifdef BN_MP_EXPTMOD_FAST_C
mp_err mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode)
{
   return s_mp_exptmod_fast(G, X, P, Y, redmode);
}
#endif
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
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







-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+
+
+
+
+
+
+
+
+
+
+
+
+





-
+


-
+





-
+


-
+
+
+
+
+
+
+
+
+
+






-
+


-
+





-
+


-
+
+
+
+
+
+
+







{
   return (unsigned long)mp_get_mag_ul(a);
}
#endif
#ifdef BN_MP_GET_LONG_LONG_C
unsigned long long mp_get_long_long(const mp_int *a)
{
   return mp_get_mag_ull(a);
   return (unsigned long long)mp_get_mag_u64(a);
}
#endif
#ifdef BN_MP_GET_LL_C
MP_GET_SIGNED(mp_get_ll, mp_get_mag_u64, long long, uint64_t)
#endif
#ifdef BN_MP_GET_MAG_ULL_C
MP_GET_MAG(mp_get_mag_ull, unsigned long long)
#endif
#ifdef BN_MP_INIT_LL_C
MP_INIT_INT(mp_init_ll, mp_set_i64, long long)
#endif
#ifdef BN_MP_SET_LL_C
MP_SET_SIGNED(mp_set_ll, mp_set_i64, long long, long long)
#endif
#ifdef BN_MP_INIT_ULL_C
MP_INIT_INT(mp_init_ull, mp_set_u64, unsigned long long)
#endif
#ifdef BN_MP_SET_ULL_C
MP_SET_UNSIGNED(mp_set_ull, unsigned long long)
#endif
#ifdef BN_MP_PRIME_IS_DIVISIBLE_C
mp_err mp_prime_is_divisible(const mp_int *a, mp_bool *result)
{
   return s_mp_prime_is_divisible(a, result);
}
#endif
#ifdef BN_MP_LOG_U32_C
mp_err mp_log_u32(const mp_int *a, uint32_t base, uint32_t *c)
{
   mp_err e;
   int c_;
   if (base > MP_MIN(MP_DIGIT_MAX, INT_MAX)) {
      return MP_VAL;
   }
   e = mp_log_n(a, (int)base, &c_);
   *c = (uint32_t)c_;
   return e;
}
#endif
#ifdef BN_MP_EXPT_D_EX_C
mp_err mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast)
{
   (void)fast;
   if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) {
   if (b > MP_MIN(MP_DIGIT_MAX, INT_MAX)) {
      return MP_VAL;
   }
   return mp_expt_u32(a, (uint32_t)b, c);
   return mp_expt_n(a, (int)b, c);
}
#endif
#ifdef BN_MP_EXPT_D_C
mp_err mp_expt_d(const mp_int *a, mp_digit b, mp_int *c)
{
   if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) {
   if (b > MP_MIN(MP_DIGIT_MAX, INT_MAX)) {
      return MP_VAL;
   }
   return mp_expt_u32(a, (uint32_t)b, c);
   return mp_expt_n(a, (int)b, c);
}
#endif
#ifdef BN_MP_EXPT_U32_C
mp_err mp_expt_u32(const mp_int *a, uint32_t b, mp_int *c)
{
   if (b > MP_MIN(MP_DIGIT_MAX, INT_MAX)) {
      return MP_VAL;
   }
   return mp_expt_n(a, (int)b, c);
}
#endif
#ifdef BN_MP_N_ROOT_EX_C
mp_err mp_n_root_ex(const mp_int *a, mp_digit b, mp_int *c, int fast)
{
   (void)fast;
   if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) {
   if (b > MP_MIN(MP_DIGIT_MAX, INT_MAX)) {
      return MP_VAL;
   }
   return mp_root_u32(a, (uint32_t)b, c);
   return mp_root_n(a, (int)b, c);
}
#endif
#ifdef BN_MP_N_ROOT_C
mp_err mp_n_root(const mp_int *a, mp_digit b, mp_int *c)
{
   if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) {
   if (b > MP_MIN(MP_DIGIT_MAX, INT_MAX)) {
      return MP_VAL;
   }
   return mp_root_u32(a, (uint32_t)b, c);
   return mp_root_n(a, (int)b, c);
}
#endif
#ifdef BN_MP_ROOT_U32_C
mp_err mp_root_u32(const mp_int *a, uint32_t b, mp_int *c)
{
   return mp_root_n(a, (int)b, c);
}
#endif
#ifdef BN_MP_UNSIGNED_BIN_SIZE_C
int mp_unsigned_bin_size(const mp_int *a)
{
   return (int)mp_ubin_size(a);
}

Changes to libtommath/bn_mp_2expt.c.

1
2
3
4
5
6
7
8
9
10
11
12
13




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













+
+
+
+







#include "tommath_private.h"
#ifdef BN_MP_2EXPT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

/* computes a = 2**b
 *
 * Simple algorithm which zeroes the int, grows it then just sets one bit
 * as required.
 */
mp_err mp_2expt(mp_int *a, int b)
{
   mp_err    err;

   if (b < 0) {
      return MP_VAL;
   }

   /* zero a as per default */
   mp_zero(a);

   /* grow a to accomodate the single bit */
   if ((err = mp_grow(a, (b / MP_DIGIT_BIT) + 1)) != MP_OKAY) {
      return err;

Changes to libtommath/bn_mp_div.c.

27
28
29
30
31
32
33
34

35
36
37
38
39
40
41
27
28
29
30
31
32
33

34
35
36
37
38
39
40
41







-
+







      if (c != NULL) {
         mp_zero(c);
      }
      return err;
   }

   /* init our temps */
   if ((err = mp_init_multi(&ta, &tb, &tq, &q, NULL)) != MP_OKAY) {
   if ((err = mp_init_multi(&ta, &tb, &tq, &q, (void *)NULL)) != MP_OKAY) {
      return err;
   }


   mp_set(&tq, 1uL);
   n = mp_count_bits(a) - mp_count_bits(b);
   if ((err = mp_abs(a, &ta)) != MP_OKAY)                         goto LBL_ERR;
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74







-
+







      c->sign  = MP_IS_ZERO(c) ? MP_ZPOS : n2;
   }
   if (d != NULL) {
      mp_exch(d, &ta);
      d->sign = MP_IS_ZERO(d) ? MP_ZPOS : n;
   }
LBL_ERR:
   mp_clear_multi(&ta, &tb, &tq, &q, NULL);
   mp_clear_multi(&ta, &tb, &tq, &q, (void *)NULL);
   return err;
}

#else

/* integer signed division.
 * c*b + d == a [e.g. a/b, c=quotient, d=remainder]

Deleted libtommath/bn_mp_div_3.c.

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
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































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include "tommath_private.h"
#ifdef BN_MP_DIV_3_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

/* divide by three (based on routine from MPI and the GMP manual) */
mp_err mp_div_3(const mp_int *a, mp_int *c, mp_digit *d)
{
   mp_int   q;
   mp_word  w, t;
   mp_digit b;
   mp_err   err;
   int      ix;

   /* b = 2**MP_DIGIT_BIT / 3 */
   b = ((mp_word)1 << (mp_word)MP_DIGIT_BIT) / (mp_word)3;

   if ((err = mp_init_size(&q, a->used)) != MP_OKAY) {
      return err;
   }

   q.used = a->used;
   q.sign = a->sign;
   w = 0;
   for (ix = a->used - 1; ix >= 0; ix--) {
      w = (w << (mp_word)MP_DIGIT_BIT) | (mp_word)a->dp[ix];

      if (w >= 3u) {
         /* multiply w by [1/3] */
         t = (w * (mp_word)b) >> (mp_word)MP_DIGIT_BIT;

         /* now subtract 3 * [w/3] from w, to get the remainder */
         w -= t+t+t;

         /* fixup the remainder as required since
          * the optimization is not exact.
          */
         while (w >= 3u) {
            t += 1u;
            w -= 3u;
         }
      } else {
         t = 0;
      }
      q.dp[ix] = (mp_digit)t;
   }

   /* [optional] store the remainder */
   if (d != NULL) {
      *d = (mp_digit)w;
   }

   /* [optional] store the quotient */
   if (c != NULL) {
      mp_clamp(&q);
      mp_exch(&q, c);
   }
   mp_clear(&q);

   return err;
}

#endif

Changes to libtommath/bn_mp_div_d.c.

40
41
42
43
44
45
46
47
48


49
50
51
52
53
54
55
40
41
42
43
44
45
46


47
48
49
50
51
52
53
54
55







-
-
+
+







      if (c != NULL) {
         return mp_div_2d(a, ix, c, NULL);
      }
      return MP_OKAY;
   }

   /* three? */
   if (MP_HAS(MP_DIV_3) && (b == 3u)) {
      return mp_div_3(a, c, d);
   if (MP_HAS(S_MP_DIV_3) && (b == 3u)) {
      return s_mp_div_3(a, c, d);
   }

   /* no easy answer [c'est la vie].  Just division */
   if ((err = mp_init_size(&q, a->used)) != MP_OKAY) {
      return err;
   }

Added libtommath/bn_mp_expt_n.c.












































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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#include "tommath_private.h"
#ifdef BN_MP_EXPT_N_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

/* calculate c = a**b  using a square-multiply algorithm */
mp_err mp_expt_n(const mp_int *a, int b, mp_int *c)
{
   mp_err err;
   mp_int  g;

   if ((err = mp_init_copy(&g, a)) != MP_OKAY) {
      return err;
   }

   /* set initial result */
   mp_set(c, 1uL);

   while (b > 0) {
      /* if the bit is set multiply */
      if ((b & 1) != 0) {
         if ((err = mp_mul(c, &g, c)) != MP_OKAY) {
            goto LBL_ERR;
         }
      }

      /* square */
      if (b > 1) {
         if ((err = mp_sqr(&g, &g)) != MP_OKAY) {
            goto LBL_ERR;
         }
      }

      /* shift to next bit */
      b >>= 1;
   }

LBL_ERR:
   mp_clear(&g);
   return err;
}

#endif

Deleted libtommath/bn_mp_expt_u32.c.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46














































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include "tommath_private.h"
#ifdef BN_MP_EXPT_U32_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

/* calculate c = a**b  using a square-multiply algorithm */
mp_err mp_expt_u32(const mp_int *a, uint32_t b, mp_int *c)
{
   mp_err err;

   mp_int  g;

   if ((err = mp_init_copy(&g, a)) != MP_OKAY) {
      return err;
   }

   /* set initial result */
   mp_set(c, 1uL);

   while (b > 0u) {
      /* if the bit is set multiply */
      if ((b & 1u) != 0u) {
         if ((err = mp_mul(c, &g, c)) != MP_OKAY) {
            goto LBL_ERR;
         }
      }

      /* square */
      if (b > 1u) {
         if ((err = mp_sqr(&g, &g)) != MP_OKAY) {
            goto LBL_ERR;
         }
      }

      /* shift to next bit */
      b >>= 1;
   }

   err = MP_OKAY;

LBL_ERR:
   mp_clear(&g);
   return err;
}

#endif

Changes to libtommath/bn_mp_exptmod.c.

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
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







-
+
















-
+







      mp_int tmpG, tmpX;
      mp_err err;

      if (!MP_HAS(MP_INVMOD)) {
         return MP_VAL;
      }

      if ((err = mp_init_multi(&tmpG, &tmpX, NULL)) != MP_OKAY) {
      if ((err = mp_init_multi(&tmpG, &tmpX, (void *)NULL)) != MP_OKAY) {
         return err;
      }

      /* first compute 1/G mod P */
      if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
         goto LBL_ERR;
      }

      /* now get |X| */
      if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
         goto LBL_ERR;
      }

      /* and now compute (1/G)**|X| instead of G**X [X < 0] */
      err = mp_exptmod(&tmpG, &tmpX, P, Y);
LBL_ERR:
      mp_clear_multi(&tmpG, &tmpX, NULL);
      mp_clear_multi(&tmpG, &tmpX, (void *)NULL);
      return err;
   }

   /* modified diminished radix reduction */
   if (MP_HAS(MP_REDUCE_IS_2K_L) && MP_HAS(MP_REDUCE_2K_L) && MP_HAS(S_MP_EXPTMOD) &&
       (mp_reduce_is_2k_l(P) == MP_YES)) {
      return s_mp_exptmod(G, X, P, Y, 1);

Changes to libtommath/bn_mp_exteuclid.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







#include "tommath_private.h"
#ifdef BN_MP_EXTEUCLID_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

/* Extended euclidean algorithm of (a, b) produces
   a*u1 + b*u2 = u3
 */
mp_err mp_exteuclid(const mp_int *a, const mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3)
{
   mp_int u1, u2, u3, v1, v2, v3, t1, t2, t3, q, tmp;
   mp_err err;

   if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) {
   if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, (void *)NULL)) != MP_OKAY) {
      return err;
   }

   /* initialize, (u1,u2,u3) = (1,0,a) */
   mp_set(&u1, 1uL);
   if ((err = mp_copy(a, &u3)) != MP_OKAY)                        goto LBL_ERR;

63
64
65
66
67
68
69
70

71
72
73
63
64
65
66
67
68
69

70
71
72
73







-
+



   }
   if (U3 != NULL) {
      mp_exch(U3, &u3);
   }

   err = MP_OKAY;
LBL_ERR:
   mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
   mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, (void *)NULL);
   return err;
}
#endif

Deleted libtommath/bn_mp_get_ll.c.

1
2
3
4
5
6
7







-
-
-
-
-
-
-
#include "tommath_private.h"
#ifdef BN_MP_GET_LL_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

MP_GET_SIGNED(mp_get_ll, mp_get_mag_ull, long long, unsigned long long)
#endif

Deleted libtommath/bn_mp_get_mag_ull.c.

1
2
3
4
5
6
7







-
-
-
-
-
-
-
#include "tommath_private.h"
#ifdef BN_MP_GET_MAG_ULL_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

MP_GET_MAG(mp_get_mag_ull, unsigned long long)
#endif

Changes to libtommath/bn_mp_grow.c.

1
2
3
4
5
6
7
8
9
10




11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21










+
+
+
+







#include "tommath_private.h"
#ifdef BN_MP_GROW_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

/* grow as required */
mp_err mp_grow(mp_int *a, int size)
{
   int     i;
   mp_digit *tmp;

   if (size < 0) {
      return MP_VAL;
   }

   /* if the alloc size is smaller alloc more ram */
   if (a->alloc < size) {
      /* reallocate the array a->dp
       *
       * We store the return in a temporary variable
       * in case the operation failed we don't want

Deleted libtommath/bn_mp_init_ll.c.

1
2
3
4
5
6
7







-
-
-
-
-
-
-
#include "tommath_private.h"
#ifdef BN_MP_INIT_LL_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

MP_INIT_INT(mp_init_ll, mp_set_ll, long long)
#endif

Changes to libtommath/bn_mp_init_size.c.

1
2
3
4
5
6
7
8





9
10
11
12
13
14
15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20








+
+
+
+
+







#include "tommath_private.h"
#ifdef BN_MP_INIT_SIZE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

/* init an mp_init for a given size */
mp_err mp_init_size(mp_int *a, int size)
{

   if (size < 0) {
      return MP_VAL;
   }

   size = MP_MAX(MP_MIN_PREC, size);

   /* alloc mem */
   a->dp = (mp_digit *) MP_CALLOC((size_t)size, sizeof(mp_digit));
   if (a->dp == NULL) {
      return MP_MEM;
   }

Deleted libtommath/bn_mp_init_ull.c.

1
2
3
4
5
6
7







-
-
-
-
-
-
-
#include "tommath_private.h"
#ifdef BN_MP_INIT_ULL_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

MP_INIT_INT(mp_init_ull, mp_set_ull, unsigned long long)
#endif

Changes to libtommath/bn_mp_lcm.c.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







#include "tommath_private.h"
#ifdef BN_MP_LCM_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

/* computes least common multiple as |a*b|/(a, b) */
mp_err mp_lcm(const mp_int *a, const mp_int *b, mp_int *c)
{
   mp_err  err;
   mp_int  t1, t2;


   if ((err = mp_init_multi(&t1, &t2, NULL)) != MP_OKAY) {
   if ((err = mp_init_multi(&t1, &t2, (void *)NULL)) != MP_OKAY) {
      return err;
   }

   /* t1 = get the GCD of the two inputs */
   if ((err = mp_gcd(a, b, &t1)) != MP_OKAY) {
      goto LBL_T;
   }
34
35
36
37
38
39
40
41

42
43
44
34
35
36
37
38
39
40

41
42
43
44







-
+



      err = mp_mul(a, &t2, c);
   }

   /* fix the sign to positive */
   c->sign = MP_ZPOS;

LBL_T:
   mp_clear_multi(&t1, &t2, NULL);
   mp_clear_multi(&t1, &t2, (void *)NULL);
   return err;
}
#endif

Added libtommath/bn_mp_log_n.c.






























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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#include "tommath_private.h"
#ifdef BN_MP_LOG_N_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

mp_err mp_log_n(const mp_int *a, int base, int *c)
{
   if (mp_isneg(a) || mp_iszero(a) || (base < 2) || (unsigned)base > (unsigned)MP_DIGIT_MAX) {
      return MP_VAL;
   }

   if (MP_HAS(S_MP_LOG_2EXPT) && MP_IS_2EXPT((mp_digit)base)) {
      *c = s_mp_log_2expt(a, (mp_digit)base);
      return MP_OKAY;
   }

   if (MP_HAS(S_MP_LOG_D) && (a->used == 1)) {
      *c = s_mp_log_d((mp_digit)base, a->dp[0]);
      return MP_OKAY;
   }

   if (MP_HAS(S_MP_LOG)) {
      return s_mp_log(a, (mp_digit)base, c);
   }

   return MP_VAL;
}

#endif

Deleted libtommath/bn_mp_log_u32.c.

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
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




















































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include "tommath_private.h"
#ifdef BN_MP_LOG_U32_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

/* Compute log_{base}(a) */
static mp_word s_pow(mp_word base, mp_word exponent)
{
   mp_word result = 1u;
   while (exponent != 0u) {
      if ((exponent & 1u) == 1u) {
         result *= base;
      }
      exponent >>= 1;
      base *= base;
   }

   return result;
}

static mp_digit s_digit_ilogb(mp_digit base, mp_digit n)
{
   mp_word bracket_low = 1u, bracket_mid, bracket_high, N;
   mp_digit ret, high = 1u, low = 0uL, mid;

   if (n < base) {
      return 0uL;
   }
   if (n == base) {
      return 1uL;
   }

   bracket_high = (mp_word) base ;
   N = (mp_word) n;

   while (bracket_high < N) {
      low = high;
      bracket_low = bracket_high;
      high <<= 1;
      bracket_high *= bracket_high;
   }

   while (((mp_digit)(high - low)) > 1u) {
      mid = (low + high) >> 1;
      bracket_mid = bracket_low * s_pow(base, (mp_word)(mid - low));

      if (N < bracket_mid) {
         high = mid ;
         bracket_high = bracket_mid ;
      }
      if (N > bracket_mid) {
         low = mid ;
         bracket_low = bracket_mid ;
      }
      if (N == bracket_mid) {
         return (mp_digit) mid;
      }
   }

   if (bracket_high == N) {
      ret = high;
   } else {
      ret = low;
   }

   return ret;
}

/* TODO: output could be "int" because the output of mp_radix_size is int, too,
         as is the output of mp_bitcount.
         With the same problem: max size is INT_MAX * MP_DIGIT not INT_MAX only!
*/
mp_err mp_log_u32(const mp_int *a, uint32_t base, uint32_t *c)
{
   mp_err err;
   mp_ord cmp;
   uint32_t high, low, mid;
   mp_int bracket_low, bracket_high, bracket_mid, t, bi_base;

   err = MP_OKAY;

   if (a->sign == MP_NEG) {
      return MP_VAL;
   }

   if (MP_IS_ZERO(a)) {
      return MP_VAL;
   }

   if (base < 2u) {
      return MP_VAL;
   }

   /* A small shortcut for bases that are powers of two. */
   if ((base & (base - 1u)) == 0u) {
      int y, bit_count;
      for (y=0; (y < 7) && ((base & 1u) == 0u); y++) {
         base >>= 1;
      }
      bit_count = mp_count_bits(a) - 1;
      *c = (uint32_t)(bit_count/y);
      return MP_OKAY;
   }

   if (a->used == 1) {
      *c = (uint32_t)s_digit_ilogb(base, a->dp[0]);
      return err;
   }

   cmp = mp_cmp_d(a, base);
   if ((cmp == MP_LT) || (cmp == MP_EQ)) {
      *c = cmp == MP_EQ;
      return err;
   }

   if ((err =
           mp_init_multi(&bracket_low, &bracket_high,
                         &bracket_mid, &t, &bi_base, NULL)) != MP_OKAY) {
      return err;
   }

   low = 0u;
   mp_set(&bracket_low, 1uL);
   high = 1u;

   mp_set(&bracket_high, base);

   /*
       A kind of Giant-step/baby-step algorithm.
       Idea shamelessly stolen from https://programmingpraxis.com/2010/05/07/integer-logarithms/2/
       The effect is asymptotic, hence needs benchmarks to test if the Giant-step should be skipped
       for small n.
    */
   while (mp_cmp(&bracket_high, a) == MP_LT) {
      low = high;
      if ((err = mp_copy(&bracket_high, &bracket_low)) != MP_OKAY) {
         goto LBL_ERR;
      }
      high <<= 1;
      if ((err = mp_sqr(&bracket_high, &bracket_high)) != MP_OKAY) {
         goto LBL_ERR;
      }
   }
   mp_set(&bi_base, base);

   while ((high - low) > 1u) {
      mid = (high + low) >> 1;

      if ((err = mp_expt_u32(&bi_base, (uint32_t)(mid - low), &t)) != MP_OKAY) {
         goto LBL_ERR;
      }
      if ((err = mp_mul(&bracket_low, &t, &bracket_mid)) != MP_OKAY) {
         goto LBL_ERR;
      }
      cmp = mp_cmp(a, &bracket_mid);
      if (cmp == MP_LT) {
         high = mid;
         mp_exch(&bracket_mid, &bracket_high);
      }
      if (cmp == MP_GT) {
         low = mid;
         mp_exch(&bracket_mid, &bracket_low);
      }
      if (cmp == MP_EQ) {
         *c = mid;
         goto LBL_END;
      }
   }

   *c = (mp_cmp(&bracket_high, a) == MP_EQ) ? high : low;

LBL_END:
LBL_ERR:
   mp_clear_multi(&bracket_low, &bracket_high, &bracket_mid,
                  &t, &bi_base, NULL);
   return err;
}


#endif

Changes to libtommath/bn_mp_mul.c.

15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29







-
+







   if (a == b) {
       return mp_sqr(a,c);
   } else if (MP_HAS(S_MP_BALANCE_MUL) &&
       /* Check sizes. The smaller one needs to be larger than the Karatsuba cut-off.
        * The bigger one needs to be at least about one MP_KARATSUBA_MUL_CUTOFF bigger
        * to make some sense, but it depends on architecture, OS, position of the
        * stars... so YMMV.
        * Using it to cut the input into slices small enough for fast_s_mp_mul_digs
        * Using it to cut the input into slices small enough for s_mp_mul_digs_fast
        * was actually slower on the author's machine, but YMMV.
        */
       (min_len >= MP_KARATSUBA_MUL_CUTOFF) &&
       ((max_len / 2) >= MP_KARATSUBA_MUL_CUTOFF) &&
       /* Not much effect was observed below a ratio of 1:2, but again: YMMV. */
       (max_len >= (2 * min_len))) {
      err = s_mp_balance_mul(a,b,c);

Changes to libtommath/bn_mp_mul_2d.c.

1
2
3
4
5
6
7
8
9
10




11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21










+
+
+
+







#include "tommath_private.h"
#ifdef BN_MP_MUL_2D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

/* shift left by a certain bit count */
mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c)
{
   mp_digit d;
   mp_err   err;

   if (b < 0) {
      return MP_VAL;
   }

   /* copy */
   if (a != c) {
      if ((err = mp_copy(a, c)) != MP_OKAY) {
         return err;
      }
   }

Changes to libtommath/bn_mp_prime_frobenius_underwood.c.

28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
28
29
30
31
32
33
34

35
36
37
38
39
40
41
42







-
+







   mp_int T1z, T2z, Np1z, sz, tz;

   int a, ap2, length, i, j;
   mp_err err;

   *result = MP_NO;

   if ((err = mp_init_multi(&T1z, &T2z, &Np1z, &sz, &tz, NULL)) != MP_OKAY) {
   if ((err = mp_init_multi(&T1z, &T2z, &Np1z, &sz, &tz, (void *)NULL)) != MP_OKAY) {
      return err;
   }

   for (a = 0; a < LTM_FROBENIUS_UNDERWOOD_A; a++) {
      /* TODO: That's ugly! No, really, it is! */
      if ((a==2) || (a==4) || (a==7) || (a==8) || (a==10) ||
          (a==14) || (a==18) || (a==23) || (a==26) || (a==28)) {
120
121
122
123
124
125
126
127

128
129
130
131
132
120
121
122
123
124
125
126

127
128
129
130
131
132







-
+





   mp_set_u32(&T1z, (uint32_t)((2 * a) + 5));
   if ((err = mp_mod(&T1z, N, &T1z)) != MP_OKAY)                  goto LBL_FU_ERR;
   if (MP_IS_ZERO(&sz) && (mp_cmp(&tz, &T1z) == MP_EQ)) {
      *result = MP_YES;
   }

LBL_FU_ERR:
   mp_clear_multi(&tz, &sz, &Np1z, &T2z, &T1z, NULL);
   mp_clear_multi(&tz, &sz, &Np1z, &T2z, &T1z, (void *)NULL);
   return err;
}

#endif
#endif

Changes to libtommath/bn_mp_prime_rand.c.

32
33
34
35
36
37
38
39




40
41
42
43
44
45
46
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47
48
49







-
+
+
+
+








   /* MP_PRIME_SAFE implies MP_PRIME_BBS */
   if ((flags & MP_PRIME_SAFE) != 0) {
      flags |= MP_PRIME_BBS;
   }

   /* calc the byte size */
   bsize = (size>>3) + ((size&7)?1:0);
   bsize = (size>>3);
   if (size&7) {
      bsize++;
   }

   /* we need a buffer of bsize bytes */
   tmp = (unsigned char *) MP_MALLOC((size_t)bsize);
   if (tmp == NULL) {
      return MP_MEM;
   }

Changes to libtommath/bn_mp_prime_strong_lucas_selfridge.c.

69
70
71
72
73
74
75
76

77
78
79
80
81
82
83
69
70
71
72
73
74
75

76
77
78
79
80
81
82
83







-
+







   such that Jacobi(D,N) = -1 (Selfridge's algorithm). Theory
   indicates that, if N is not a perfect square, D will "nearly
   always" be "small." Just in case, an overflow trap for D is
   included.
   */

   if ((err = mp_init_multi(&Dz, &gcd, &Np1, &Uz, &Vz, &U2mz, &V2mz, &Qmz, &Q2mz, &Qkdz, &T1z, &T2z, &T3z, &T4z, &Q2kdz,
                            NULL)) != MP_OKAY) {
                            (void *)NULL)) != MP_OKAY) {
      return err;
   }

   D = 5;
   sign = 1;

   for (;;) {
277
278
279
280
281
282
283
284

285
286
287
288
289
277
278
279
280
281
282
283

284
285
286
287
288
289







-
+





      if (r < (s - 1)) {
         if ((err = mp_sqr(&Qkdz, &Qkdz)) != MP_OKAY)             goto LBL_LS_ERR;
         if ((err = mp_mod(&Qkdz, a, &Qkdz)) != MP_OKAY)          goto LBL_LS_ERR;
         if ((err = mp_mul_2(&Qkdz, &Q2kdz)) != MP_OKAY)          goto LBL_LS_ERR;
      }
   }
LBL_LS_ERR:
   mp_clear_multi(&Q2kdz, &T4z, &T3z, &T2z, &T1z, &Qkdz, &Q2mz, &Qmz, &V2mz, &U2mz, &Vz, &Uz, &Np1, &gcd, &Dz, NULL);
   mp_clear_multi(&Q2kdz, &T4z, &T3z, &T2z, &T1z, &Qkdz, &Q2mz, &Qmz, &V2mz, &U2mz, &Vz, &Uz, &Np1, &gcd, &Dz, (void *)NULL);
   return err;
}
#endif
#endif
#endif

Added libtommath/bn_mp_root_n.c.














































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#include "tommath_private.h"
#ifdef BN_MP_ROOT_N_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

/* find the n'th root of an integer
 *
 * Result found such that (c)**b <= a and (c+1)**b > a
 *
 * This algorithm uses Newton's approximation
 * x[i+1] = x[i] - f(x[i])/f'(x[i])
 * which will find the root in log(N) time where
 * each step involves a fair bit.
 */
mp_err mp_root_n(const mp_int *a, int b, mp_int *c)
{
   mp_int t1, t2, t3, a_;
   int    ilog2;
   mp_err err;

   if ((unsigned)b > (unsigned)MP_MIN(MP_DIGIT_MAX, INT_MAX)) {
      return MP_VAL;
   }

   /* input must be positive if b is even */
   if (((b & 1) == 0) && mp_isneg(a)) {
      return MP_VAL;
   }

   if ((err = mp_init_multi(&t1, &t2, &t3, (void *)NULL)) != MP_OKAY) {
      return err;
   }

   /* if a is negative fudge the sign but keep track */
   a_ = *a;
   a_.sign = MP_ZPOS;

   /* Compute seed: 2^(log_2(n)/b + 2)*/
   ilog2 = mp_count_bits(a);

   /*
     If "b" is larger than INT_MAX it is also larger than
     log_2(n) because the bit-length of the "n" is measured
     with an int and hence the root is always < 2 (two).
   */
   if (b > INT_MAX/2) {
      mp_set(c, 1uL);
      c->sign = a->sign;
      err = MP_OKAY;
      goto LBL_ERR;
   }

   /* "b" is smaller than INT_MAX, we can cast safely */
   if (ilog2 < b) {
      mp_set(c, 1uL);
      c->sign = a->sign;
      err = MP_OKAY;
      goto LBL_ERR;
   }
   ilog2 =  ilog2 / b;
   if (ilog2 == 0) {
      mp_set(c, 1uL);
      c->sign = a->sign;
      err = MP_OKAY;
      goto LBL_ERR;
   }
   /* Start value must be larger than root */
   ilog2 += 2;
   if ((err = mp_2expt(&t2,ilog2)) != MP_OKAY)                    goto LBL_ERR;
   do {
      /* t1 = t2 */
      if ((err = mp_copy(&t2, &t1)) != MP_OKAY)                   goto LBL_ERR;

      /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */

      /* t3 = t1**(b-1) */
      if ((err = mp_expt_n(&t1, b - 1, &t3)) != MP_OKAY)       goto LBL_ERR;

      /* numerator */
      /* t2 = t1**b */
      if ((err = mp_mul(&t3, &t1, &t2)) != MP_OKAY)               goto LBL_ERR;

      /* t2 = t1**b - a */
      if ((err = mp_sub(&t2, &a_, &t2)) != MP_OKAY)               goto LBL_ERR;

      /* denominator */
      /* t3 = t1**(b-1) * b  */
      if ((err = mp_mul_d(&t3, (mp_digit)b, &t3)) != MP_OKAY)               goto LBL_ERR;

      /* t3 = (t1**b - a)/(b * t1**(b-1)) */
      if ((err = mp_div(&t2, &t3, &t3, NULL)) != MP_OKAY)         goto LBL_ERR;

      if ((err = mp_sub(&t1, &t3, &t2)) != MP_OKAY)               goto LBL_ERR;

      /*
          Number of rounds is at most log_2(root). If it is more it
          got stuck, so break out of the loop and do the rest manually.
       */
      if (ilog2-- == 0) {
         break;
      }
   }  while (mp_cmp(&t1, &t2) != MP_EQ);

   /* result can be off by a few so check */
   /* Loop beneath can overshoot by one if found root is smaller than actual root */
   for (;;) {
      mp_ord cmp;
      if ((err = mp_expt_n(&t1, b, &t2)) != MP_OKAY)            goto LBL_ERR;
      cmp = mp_cmp(&t2, &a_);
      if (cmp == MP_EQ) {
         err = MP_OKAY;
         goto LBL_ERR;
      }
      if (cmp == MP_LT) {
         if ((err = mp_add_d(&t1, 1uL, &t1)) != MP_OKAY)          goto LBL_ERR;
      } else {
         break;
      }
   }
   /* correct overshoot from above or from recurrence */
   for (;;) {
      if ((err = mp_expt_n(&t1, b, &t2)) != MP_OKAY)            goto LBL_ERR;
      if (mp_cmp(&t2, &a_) == MP_GT) {
         if ((err = mp_sub_d(&t1, 1uL, &t1)) != MP_OKAY)          goto LBL_ERR;
      } else {
         break;
      }
   }

   /* set the result */
   mp_exch(&t1, c);

   /* set the sign of the result */
   c->sign = a->sign;

LBL_ERR:
   mp_clear_multi(&t1, &t2, &t3, (void *)NULL);
   return err;
}

#endif

Deleted libtommath/bn_mp_root_u32.c.

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
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











































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include "tommath_private.h"
#ifdef BN_MP_ROOT_U32_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

/* find the n'th root of an integer
 *
 * Result found such that (c)**b <= a and (c+1)**b > a
 *
 * This algorithm uses Newton's approximation
 * x[i+1] = x[i] - f(x[i])/f'(x[i])
 * which will find the root in log(N) time where
 * each step involves a fair bit.
 */
mp_err mp_root_u32(const mp_int *a, uint32_t b, mp_int *c)
{
   mp_int t1, t2, t3, a_;
   mp_ord cmp;
   int    ilog2;
   mp_err err;

   /* input must be positive if b is even */
   if (((b & 1u) == 0u) && (a->sign == MP_NEG)) {
      return MP_VAL;
   }

   if ((err = mp_init_multi(&t1, &t2, &t3, NULL)) != MP_OKAY) {
      return err;
   }

   /* if a is negative fudge the sign but keep track */
   a_ = *a;
   a_.sign = MP_ZPOS;

   /* Compute seed: 2^(log_2(n)/b + 2)*/
   ilog2 = mp_count_bits(a);

   /*
     If "b" is larger than INT_MAX it is also larger than
     log_2(n) because the bit-length of the "n" is measured
     with an int and hence the root is always < 2 (two).
   */
   if (b > (uint32_t)(INT_MAX/2)) {
      mp_set(c, 1uL);
      c->sign = a->sign;
      err = MP_OKAY;
      goto LBL_ERR;
   }

   /* "b" is smaller than INT_MAX, we can cast safely */
   if (ilog2 < (int)b) {
      mp_set(c, 1uL);
      c->sign = a->sign;
      err = MP_OKAY;
      goto LBL_ERR;
   }
   ilog2 =  ilog2 / ((int)b);
   if (ilog2 == 0) {
      mp_set(c, 1uL);
      c->sign = a->sign;
      err = MP_OKAY;
      goto LBL_ERR;
   }
   /* Start value must be larger than root */
   ilog2 += 2;
   if ((err = mp_2expt(&t2,ilog2)) != MP_OKAY)                    goto LBL_ERR;
   do {
      /* t1 = t2 */
      if ((err = mp_copy(&t2, &t1)) != MP_OKAY)                   goto LBL_ERR;

      /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */

      /* t3 = t1**(b-1) */
      if ((err = mp_expt_u32(&t1, b - 1u, &t3)) != MP_OKAY)       goto LBL_ERR;

      /* numerator */
      /* t2 = t1**b */
      if ((err = mp_mul(&t3, &t1, &t2)) != MP_OKAY)               goto LBL_ERR;

      /* t2 = t1**b - a */
      if ((err = mp_sub(&t2, &a_, &t2)) != MP_OKAY)               goto LBL_ERR;

      /* denominator */
      /* t3 = t1**(b-1) * b  */
      if ((err = mp_mul_d(&t3, b, &t3)) != MP_OKAY)               goto LBL_ERR;

      /* t3 = (t1**b - a)/(b * t1**(b-1)) */
      if ((err = mp_div(&t2, &t3, &t3, NULL)) != MP_OKAY)         goto LBL_ERR;

      if ((err = mp_sub(&t1, &t3, &t2)) != MP_OKAY)               goto LBL_ERR;

      /*
          Number of rounds is at most log_2(root). If it is more it
          got stuck, so break out of the loop and do the rest manually.
       */
      if (ilog2-- == 0) {
         break;
      }
   }  while (mp_cmp(&t1, &t2) != MP_EQ);

   /* result can be off by a few so check */
   /* Loop beneath can overshoot by one if found root is smaller than actual root */
   for (;;) {
      if ((err = mp_expt_u32(&t1, b, &t2)) != MP_OKAY)            goto LBL_ERR;
      cmp = mp_cmp(&t2, &a_);
      if (cmp == MP_EQ) {
         err = MP_OKAY;
         goto LBL_ERR;
      }
      if (cmp == MP_LT) {
         if ((err = mp_add_d(&t1, 1uL, &t1)) != MP_OKAY)          goto LBL_ERR;
      } else {
         break;
      }
   }
   /* correct overshoot from above or from recurrence */
   for (;;) {
      if ((err = mp_expt_u32(&t1, b, &t2)) != MP_OKAY)            goto LBL_ERR;
      if (mp_cmp(&t2, &a_) == MP_GT) {
         if ((err = mp_sub_d(&t1, 1uL, &t1)) != MP_OKAY)          goto LBL_ERR;
      } else {
         break;
      }
   }

   /* set the result */
   mp_exch(&t1, c);

   /* set the sign of the result */
   c->sign = a->sign;

   err = MP_OKAY;

LBL_ERR:
   mp_clear_multi(&t1, &t2, &t3, NULL);
   return err;
}

#endif

Changes to libtommath/bn_mp_set_double.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
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







-
+













-
+







   union {
      double   dbl;
      uint64_t bits;
   } cast;
   cast.dbl = b;

   exp = (int)((unsigned)(cast.bits >> 52) & 0x7FFu);
   frac = (cast.bits & (((uint64_t)1 << 52) - (uint64_t)1)) | ((uint64_t)1 << 52);
   frac = (cast.bits & ((1uLL << 52) - 1uLL)) | (1uLL << 52);

   if (exp == 0x7FF) { /* +-inf, NaN */
      return MP_VAL;
   }
   exp -= 1023 + 52;

   mp_set_u64(a, frac);

   err = (exp < 0) ? mp_div_2d(a, -exp, a, NULL) : mp_mul_2d(a, exp, a);
   if (err != MP_OKAY) {
      return err;
   }

   if (((cast.bits >> 63) != 0u) && !MP_IS_ZERO(a)) {
   if (((cast.bits >> 63) != 0uLL) && !MP_IS_ZERO(a)) {
      a->sign = MP_NEG;
   }

   return MP_OKAY;
}
#else
/* pragma message() not supported by several compilers (in mostly older but still used versions) */

Deleted libtommath/bn_mp_set_ll.c.

1
2
3
4
5
6
7







-
-
-
-
-
-
-
#include "tommath_private.h"
#ifdef BN_MP_SET_LL_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

MP_SET_SIGNED(mp_set_ll, mp_set_ull, long long, unsigned long long)
#endif

Deleted libtommath/bn_mp_set_ull.c.

1
2
3
4
5
6
7







-
-
-
-
-
-
-
#include "tommath_private.h"
#ifdef BN_MP_SET_ULL_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

MP_SET_UNSIGNED(mp_set_ull, unsigned long long)
#endif

Changes to libtommath/bn_mp_sqrt.c.

1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5
6
7
8
9
10
11
12
13
14






+







#include "tommath_private.h"
#ifdef BN_MP_SQRT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

#ifndef NO_FLOATING_POINT
#include <float.h>
#include <math.h>
#if (MP_DIGIT_BIT != 28) || (FLT_RADIX != 2) || (DBL_MANT_DIG != 53) || (DBL_MAX_EXP != 1024)
#define NO_FLOATING_POINT
#endif
#endif

/* this function is less generic than mp_n_root, simpler and faster */

Changes to libtommath/bn_mp_sqrtmod_prime.c.

21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
21
22
23
24
25
26
27

28
29
30
31
32
33
34
35







-
+







      mp_zero(ret);
      return MP_OKAY;
   }
   if (mp_cmp_d(prime, 2uL) == MP_EQ)                            return MP_VAL; /* prime must be odd */
   if ((err = mp_kronecker(n, prime, &legendre)) != MP_OKAY)        return err;
   if (legendre == -1)                                           return MP_VAL; /* quadratic non-residue mod prime */

   if ((err = mp_init_multi(&t1, &C, &Q, &S, &Z, &M, &T, &R, &two, NULL)) != MP_OKAY) {
   if ((err = mp_init_multi(&t1, &C, &Q, &S, &Z, &M, &T, &R, &two, (void *)NULL)) != MP_OKAY) {
      return err;
   }

   /* SPECIAL CASE: if prime mod 4 == 3
    * compute directly: err = n^(prime+1)/4 mod prime
    * Handbook of Applied Cryptography algorithm 3.36
    */
107
108
109
110
111
112
113
114

115
116
117
118
107
108
109
110
111
112
113

114
115
116
117
118







-
+




      if ((err = mp_mulmod(&T, &C, prime, &T)) != MP_OKAY)        goto cleanup;
      /* T = (T * C) mod prime */
      mp_set(&M, i);
      /* M = i */
   }

cleanup:
   mp_clear_multi(&t1, &C, &Q, &S, &Z, &M, &T, &R, &two, NULL);
   mp_clear_multi(&t1, &C, &Q, &S, &Z, &M, &T, &R, &two, (void *)NULL);
   return err;
}

#endif

Changes to libtommath/bn_s_mp_balance_mul.c.

15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29







-
+








   nblocks = MP_MAX(a->used, b->used) / MP_MIN(a->used, b->used);
   bsize = MP_MIN(a->used, b->used) ;

   if ((err = mp_init_size(&a0, bsize + 2)) != MP_OKAY) {
      return err;
   }
   if ((err = mp_init_multi(&tmp, &r, NULL)) != MP_OKAY) {
   if ((err = mp_init_multi(&tmp, &r, (void *)NULL)) != MP_OKAY) {
      mp_clear(&a0);
      return err;
   }

   /* Make sure that A is the larger one*/
   if (len_a < len_b) {
      B = *a;
71
72
73
74
75
76
77
78

79
80
81
71
72
73
74
75
76
77

78
79
80
81







-
+



      if ((err = mp_add(&r, &tmp, &r)) != MP_OKAY) {
         goto LBL_ERR;
      }
   }

   mp_exch(&r,c);
LBL_ERR:
   mp_clear_multi(&a0, &tmp, &r,NULL);
   mp_clear_multi(&a0, &tmp, &r, (void *)NULL);
   return err;
}
#endif

Added libtommath/bn_s_mp_div_3.c.
































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#include "tommath_private.h"
#ifdef BN_S_MP_DIV_3_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

/* divide by three (based on routine from MPI and the GMP manual) */
mp_err s_mp_div_3(const mp_int *a, mp_int *c, mp_digit *d)
{
   mp_int   q;
   mp_word  w, t;
   mp_digit b;
   mp_err   err;
   int      ix;

   /* b = 2**MP_DIGIT_BIT / 3 */
   b = ((mp_word)1 << (mp_word)MP_DIGIT_BIT) / (mp_word)3;

   if ((err = mp_init_size(&q, a->used)) != MP_OKAY) {
      return err;
   }

   q.used = a->used;
   q.sign = a->sign;
   w = 0;
   for (ix = a->used - 1; ix >= 0; ix--) {
      w = (w << (mp_word)MP_DIGIT_BIT) | (mp_word)a->dp[ix];

      if (w >= 3u) {
         /* multiply w by [1/3] */
         t = (w * (mp_word)b) >> (mp_word)MP_DIGIT_BIT;

         /* now subtract 3 * [w/3] from w, to get the remainder */
         w -= t+t+t;

         /* fixup the remainder as required since
          * the optimization is not exact.
          */
         while (w >= 3u) {
            t += 1u;
            w -= 3u;
         }
      } else {
         t = 0;
      }
      q.dp[ix] = (mp_digit)t;
   }

   /* [optional] store the remainder */
   if (d != NULL) {
      *d = (mp_digit)w;
   }

   /* [optional] store the quotient */
   if (c != NULL) {
      mp_clamp(&q);
      mp_exch(&q, c);
   }
   mp_clear(&q);

   return err;
}

#endif

Changes to libtommath/bn_s_mp_invmod_fast.c.

17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31







-
+








   /* 2. [modified] b must be odd   */
   if (MP_IS_EVEN(b)) {
      return MP_VAL;
   }

   /* init all our temps */
   if ((err = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) {
   if ((err = mp_init_multi(&x, &y, &u, &v, &B, &D, (void *)NULL)) != MP_OKAY) {
      return err;
   }

   /* x == modulus, y == value to invert */
   if ((err = mp_copy(b, &x)) != MP_OKAY)                         goto LBL_ERR;

   /* we need y = |a| */
108
109
110
111
112
113
114
115

116
117
118
108
109
110
111
112
113
114

115
116
117
118







-
+



   }

   mp_exch(&D, c);
   c->sign = neg;
   err = MP_OKAY;

LBL_ERR:
   mp_clear_multi(&x, &y, &u, &v, &B, &D, NULL);
   mp_clear_multi(&x, &y, &u, &v, &B, &D, (void *)NULL);
   return err;
}
#endif

Changes to libtommath/bn_s_mp_invmod_slow.c.

12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26







-
+







   /* b cannot be negative */
   if ((b->sign == MP_NEG) || MP_IS_ZERO(b)) {
      return MP_VAL;
   }

   /* init temps */
   if ((err = mp_init_multi(&x, &y, &u, &v,
                            &A, &B, &C, &D, NULL)) != MP_OKAY) {
                            &A, &B, &C, &D, (void *)NULL)) != MP_OKAY) {
      return err;
   }

   /* x = a, y = b */
   if ((err = mp_mod(a, b, &x)) != MP_OKAY)                       goto LBL_ERR;
   if ((err = mp_copy(b, &y)) != MP_OKAY)                         goto LBL_ERR;

109
110
111
112
113
114
115
116

117
118
119
109
110
111
112
113
114
115

116
117
118
119







-
+



      if ((err = mp_sub(&C, b, &C)) != MP_OKAY)                   goto LBL_ERR;
   }

   /* C is now the inverse */
   mp_exch(&C, c);
   err = MP_OKAY;
LBL_ERR:
   mp_clear_multi(&x, &y, &u, &v, &A, &B, &C, &D, NULL);
   mp_clear_multi(&x, &y, &u, &v, &A, &B, &C, &D, (void *)NULL);
   return err;
}
#endif

Added libtommath/bn_s_mp_log.c.


















































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#include "tommath_private.h"
#ifdef BN_S_MP_LOG_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

mp_err s_mp_log(const mp_int *a, mp_digit base, int *c)
{
   mp_err err;
   int high, low;
   mp_int bracket_low, bracket_high, bracket_mid, t, bi_base;

   mp_ord cmp = mp_cmp_d(a, base);
   if ((cmp == MP_LT) || (cmp == MP_EQ)) {
      *c = cmp == MP_EQ;
      return MP_OKAY;
   }

   if ((err =
           mp_init_multi(&bracket_low, &bracket_high,
                         &bracket_mid, &t, &bi_base, (void *)NULL)) != MP_OKAY) {
      return err;
   }

   low = 0;
   mp_set(&bracket_low, 1uL);
   high = 1;

   mp_set(&bracket_high, base);

   /*
       A kind of Giant-step/baby-step algorithm.
       Idea shamelessly stolen from https://programmingpraxis.com/2010/05/07/integer-logarithms/2/
       The effect is asymptotic, hence needs benchmarks to test if the Giant-step should be skipped
       for small n.
    */
   while (mp_cmp(&bracket_high, a) == MP_LT) {
      low = high;
      if ((err = mp_copy(&bracket_high, &bracket_low)) != MP_OKAY) {
         goto LBL_END;
      }
      high <<= 1;
      if ((err = mp_sqr(&bracket_high, &bracket_high)) != MP_OKAY) {
         goto LBL_END;
      }
   }
   mp_set(&bi_base, base);

   while ((high - low) > 1) {
      int mid = (high + low) >> 1;

      if ((err = mp_expt_n(&bi_base, mid - low, &t)) != MP_OKAY) {
         goto LBL_END;
      }
      if ((err = mp_mul(&bracket_low, &t, &bracket_mid)) != MP_OKAY) {
         goto LBL_END;
      }
      cmp = mp_cmp(a, &bracket_mid);
      if (cmp == MP_LT) {
         high = mid;
         mp_exch(&bracket_mid, &bracket_high);
      }
      if (cmp == MP_GT) {
         low = mid;
         mp_exch(&bracket_mid, &bracket_low);
      }
      if (cmp == MP_EQ) {
         *c = mid;
         goto LBL_END;
      }
   }

   *c = (mp_cmp(&bracket_high, a) == MP_EQ) ? high : low;

LBL_END:
   mp_clear_multi(&bracket_low, &bracket_high, &bracket_mid,
                  &t, &bi_base, (void *)NULL);
   return err;
}


#endif

Added libtommath/bn_s_mp_log_2expt.c.













1
2
3
4
5
6
7
8
9
10
11
12
+
+
+
+
+
+
+
+
+
+
+
+
#include "tommath_private.h"
#ifdef BN_S_MP_LOG_2EXPT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

int s_mp_log_2expt(const mp_int *a, mp_digit base)
{
   int y;
   for (y = 0; (base & 1) == 0; y++, base >>= 1) {}
   return (mp_count_bits(a) - 1) / y;
}
#endif

Added libtommath/bn_s_mp_log_d.c.


































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#include "tommath_private.h"
#ifdef BN_S_MP_LOG_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

static mp_word s_pow(mp_word base, mp_word exponent)
{
   mp_word result = 1u;
   while (exponent != 0u) {
      if ((exponent & 1u) == 1u) {
         result *= base;
      }
      exponent >>= 1;
      base *= base;
   }

   return result;
}

int s_mp_log_d(mp_digit base, mp_digit n)
{
   mp_word bracket_low = 1uLL, bracket_high = base, N = n;
   int ret, high = 1, low = 0;

   if (n < base) {
      return 0;
   }
   if (n == base) {
      return 1;
   }

   while (bracket_high < N) {
      low = high;
      bracket_low = bracket_high;
      high <<= 1;
      bracket_high *= bracket_high;
   }

   while (((mp_digit)(high - low)) > 1uL) {
      int mid = (low + high) >> 1;
      mp_word bracket_mid = bracket_low * s_pow(base, (mp_word)(mid - low));

      if (N < bracket_mid) {
         high = mid ;
         bracket_high = bracket_mid ;
      }
      if (N > bracket_mid) {
         low = mid ;
         bracket_low = bracket_mid ;
      }
      if (N == bracket_mid) {
         return mid;
      }
   }

   if (bracket_high == N) {
      ret = high;
   } else {
      ret = low;
   }

   return ret;
}

#endif

Changes to libtommath/bn_s_mp_mul_digs.c.

11
12
13
14
15
16
17




18
19
20
21
22
23
24
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28







+
+
+
+







{
   mp_int  t;
   mp_err  err;
   int     pa, pb, ix, iy;
   mp_digit u;
   mp_word r;
   mp_digit tmpx, *tmpt, *tmpy;

   if (digs < 0) {
      return MP_VAL;
   }

   /* can we use the fast multiplier? */
   if ((digs < MP_WARRAY) &&
       (MP_MIN(a->used, b->used) < MP_MAXFAST)) {
      return s_mp_mul_digs_fast(a, b, c, digs);
   }

Changes to libtommath/bn_s_mp_mul_digs_fast.c.

21
22
23
24
25
26
27




28
29
30
31
32
33
34
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38







+
+
+
+







 */
mp_err s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs)
{
   int      olduse, pa, ix, iz;
   mp_err   err;
   mp_digit W[MP_WARRAY];
   mp_word  _W;

   if (digs < 0) {
      return MP_VAL;
   }

   /* grow the destination as required */
   if (c->alloc < digs) {
      if ((err = mp_grow(c, digs)) != MP_OKAY) {
         return err;
      }
   }

Changes to libtommath/bn_s_mp_mul_high_digs.c.

10
11
12
13
14
15
16




17
18
19
20
21
22
23
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27







+
+
+
+







{
   mp_int   t;
   int      pa, pb, ix, iy;
   mp_err   err;
   mp_digit u;
   mp_word  r;
   mp_digit tmpx, *tmpt, *tmpy;

   if (digs < 0) {
      return MP_VAL;
   }

   /* can we use the fast multiplier? */
   if (MP_HAS(S_MP_MUL_HIGH_DIGS_FAST)
       && ((a->used + b->used + 1) < MP_WARRAY)
       && (MP_MIN(a->used, b->used) < MP_MAXFAST)) {
      return s_mp_mul_high_digs_fast(a, b, c, digs);
   }

Changes to libtommath/bn_s_mp_mul_high_digs_fast.c.

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
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
30
31





-
+














+
+
+
+







#include "tommath_private.h"
#ifdef BN_S_MP_MUL_HIGH_DIGS_FAST_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

/* this is a modified version of s_mp_mul_digs_fast that only produces
/* this is a modified version of s_mp_mul_digs_fast  that only produces
 * output digits *above* digs.  See the comments for s_mp_mul_digs_fast
 * to see how it works.
 *
 * This is used in the Barrett reduction since for one of the multiplications
 * only the higher digits were needed.  This essentially halves the work.
 *
 * Based on Algorithm 14.12 on pp.595 of HAC.
 */
mp_err s_mp_mul_high_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs)
{
   int     olduse, pa, ix, iz;
   mp_err   err;
   mp_digit W[MP_WARRAY];
   mp_word  _W;

   if (digs < 0) {
      return MP_VAL;
   }

   /* grow the destination as required */
   pa = a->used + b->used;
   if (c->alloc < pa) {
      if ((err = mp_grow(c, pa)) != MP_OKAY) {
         return err;
      }

Changes to libtommath/bn_s_mp_toom_mul.c.

32
33
34
35
36
37
38
39

40
41
42
43
44
45
46
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46







-
+







mp_err s_mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c)
{
   mp_int S1, S2, T1, a0, a1, a2, b0, b1, b2;
   int B, count;
   mp_err err;

   /* init temps */
   if ((err = mp_init_multi(&S1, &S2, &T1, NULL)) != MP_OKAY) {
   if ((err = mp_init_multi(&S1, &S2, &T1, (void *)NULL)) != MP_OKAY) {
      return err;
   }

   /* B */
   B = MP_MIN(a->used, b->used) / 3;

   /** a = a2 * x^2 + a1 * x + a0; */
142
143
144
145
146
147
148
149

150
151
152
153
154
155
156
142
143
144
145
146
147
148

149
150
151
152
153
154
155
156







-
+







   if ((err = mp_mul(&a2, &b2, &b1)) != MP_OKAY)                  goto LBL_ERR;

   /** \\S2 = (S2 - S3)/3; */
   /** S2 = S2 - a1; */
   if ((err = mp_sub(&S2, &a1, &S2)) != MP_OKAY)                  goto LBL_ERR;

   /** S2 = S2 / 3; \\ this is an exact division  */
   if ((err = mp_div_3(&S2, &S2, NULL)) != MP_OKAY)               goto LBL_ERR;
   if ((err = s_mp_div_3(&S2, &S2, NULL)) != MP_OKAY)             goto LBL_ERR;

   /** a1 = S1 - a1; */
   if ((err = mp_sub(&S1, &a1, &a1)) != MP_OKAY)                  goto LBL_ERR;

   /** a1 = a1 >> 1; */
   if ((err = mp_div_2(&a1, &a1)) != MP_OKAY)                     goto LBL_ERR;

204
205
206
207
208
209
210
211

212
213
214
215
204
205
206
207
208
209
210

211
212
213
214
215







-
+




LBL_ERRb0:
   mp_clear(&a2);
LBL_ERRa2:
   mp_clear(&a1);
LBL_ERRa1:
   mp_clear(&a0);
LBL_ERRa0:
   mp_clear_multi(&S1, &S2, &T1, NULL);
   mp_clear_multi(&S1, &S2, &T1, (void *)NULL);
   return err;
}

#endif

Changes to libtommath/changes.txt.












1
2
3
4
5
6
7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
+
+
+
+
+
+
+
+
+
+
+







Mar 27th, 2024
v1.3.0
       -- Deprecate more APIs which are replaced in develop (PR #572)
       -- Add support for CMake (PR #573)
       -- Add support for GitHub Actions (PR #573)

Sep 04th, 2023
v1.2.1
       -- Bugfix release because of potential integer overflow
          c.f. PR #546 resp. CVE-2023-36328

Oct 22nd, 2019
v1.2.0
       -- A huge refactoring of the library happened - renaming,
          deprecating and replacing existing functions by improved API's.

          All deprecated functions, macros and symbols are only marked as such
          so this version is still API and ABI compatible to v1.x.
408
409
410
411
412
413
414
415

416
417
418
419
420
421
422
419
420
421
422
423
424
425

426
427
428
429
430
431
432
433







-
+







          to other functions like mp_invmod, mp_div, etc...
       -- Sped up mp_exptmod_fast by using new code to find R mod m [e.g. B^n mod m]
       -- minor fixes

Jan 17th, 2003
v0.12  -- re-wrote the majority of the makefile so its more portable and will
          install via "make install" on most *nix platforms
       -- Re-packaged all the source as seperate files.  Means the library a single
       -- Re-packaged all the source as separate files.  Means the library a single
          file packagage any more.  Instead of just adding "bn.c" you have to add
          libtommath.a
       -- Renamed "bn.h" to "tommath.h"
       -- Changes to the manual to reflect all of this
       -- Used GNU Indent to clean up the source

Jan 15th, 2003

Changes to libtommath/helper.pl.

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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+
+
-
-
+
+


















-
+


+
-
+
+







    }
    else {
      die "patch_file failed: " . substr($v, 0, 30) . "..";
    }
  }
  return $content;
}

sub make_sources_cmake {
  my ($src_ref, $hdr_ref) = @_;
  my @sources = @{ $src_ref };
  my @headers = @{ $hdr_ref };
  my $output = "# SPDX-License-Identifier: Unlicense
# Autogenerated File! Do not edit.

set(SOURCES\n";
  foreach my $sobj (sort @sources) {
    $output .= $sobj . "\n";
  }
  $output .= ")\n\nset(HEADERS\n";
  foreach my $hobj (sort @headers) {
    $output .= $hobj . "\n";
  }
  $output .= ")\n";
  return $output;
}

sub process_makefiles {
  my $write = shift;
  my $changed_count = 0;
  my @headers = bsd_glob("*.h");
  my @sources = bsd_glob("*.c");
  my @o = map { my $x = $_; $x =~ s/\.c$/.o/; $x } bsd_glob("*.c");
  my @all = bsd_glob("*.{c,h}");
  my @o = map { my $x = $_; $x =~ s/\.c$/.o/; $x } @sources;
  my @all = sort(@sources, @headers);

  my $var_o = prepare_variable("OBJECTS", @o);
  (my $var_obj = $var_o) =~ s/\.o\b/.obj/sg;

  # update MSVC project files
  my $msvc_files = prepare_msvc_files_xml(\@all, qr/NOT_USED_HERE/, ['Debug|Win32', 'Release|Win32', 'Debug|x64', 'Release|x64']);
  for my $m (qw/libtommath_VS2008.vcproj/) {
    my $old = read_file($m);
    my $new = $old;
    $new =~ s|<Files>.*</Files>|$msvc_files|s;
    if ($old ne $new) {
      write_file($m, $new) if $write;
      warn "changed: $m\n";
      $changed_count++;
    }
  }

  # update OBJECTS + HEADERS in makefile*
  for my $m (qw/ makefile makefile.shared makefile_include.mk makefile.msvc makefile.unix makefile.mingw /) {
  for my $m (qw/ makefile makefile.shared makefile_include.mk makefile.msvc makefile.unix makefile.mingw sources.cmake /) {
    my $old = read_file($m);
    my $new = $m eq 'makefile.msvc' ? patch_file($old, $var_obj)
            : $m eq 'sources.cmake' ? make_sources_cmake(\@sources, \@headers)
                                    : patch_file($old, $var_o);
            :                         patch_file($old, $var_o);

    if ($old ne $new) {
      write_file($m, $new) if $write;
      warn "changed: $m\n";
      $changed_count++;
    }
  }

385
386
387
388
389
390
391





392
393
394
395
396
397
398
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426







+
+
+
+
+







                my $a = $&;
                next if $a eq "mp_err";
                $a =~ tr/[a-z]/[A-Z]/;
                $a = 'BN_' . $a . '_C';
                push @deps, $a;
            }
        }
        if ($filename =~ "BN_DEPRECATED") {
            push(@deps, qw(BN_MP_GET_LL_C BN_MP_INIT_LL_C BN_MP_SET_LL_C));
            push(@deps, qw(BN_MP_GET_MAG_ULL_C BN_MP_INIT_ULL_C BN_MP_SET_ULL_C));
            push(@deps, qw(BN_MP_DIV_3_C BN_MP_EXPT_U32_C BN_MP_ROOT_U32_C BN_MP_LOG_U32_C));
        }
        @deps = sort(@deps);
        foreach my $a (@deps) {
            if ($list !~ /$a/) {
                print {$class} "#   define $a\n";
            }
            $list = $list . ',' . $a;
        }
431
432
433
434
435
436
437


438
439
440
441
442
443
444
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474







+
+







sub generate_def {
    my @files = split /\n/, `git ls-files`;
    @files = grep(/\.c/, @files);
    @files = map { my $x = $_; $x =~ s/^bn_|\.c$//g; $x; } @files;
    @files = grep(!/mp_radix_smap/, @files);

    push(@files, qw(mp_set_int mp_set_long mp_set_long_long mp_get_int mp_get_long mp_get_long_long mp_init_set_int));
    push(@files, qw(mp_get_ll mp_get_mag_ull mp_init_ll mp_set_ll mp_init_ull mp_set_ull));
    push(@files, qw(mp_div_3 mp_expt_u32 mp_root_u32 mp_log_u32));

    my $files = join("\n    ", sort(grep(/^mp_/, @files)));
    write_file "tommath.def", "; libtommath
;
; Use this command to produce a 32-bit .lib file, for use in any MSVC version
;   lib -machine:X86 -name:libtommath.dll -def:tommath.def -out:tommath.lib
; Use this command to produce a 64-bit .lib file, for use in any MSVC version

Changes to libtommath/libtommath.pc.in.

1
2


3
4

5
6
7
8

9
10


1
2


3
4
5
6

7
8
9
-
-
+
+
-
-
+



-
+


prefix=@to-be-replaced@
exec_prefix=${prefix}
prefix=@CMAKE_INSTALL_PREFIX@
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
libdir=${exec_prefix}/lib
includedir=${prefix}/include
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@

Name: LibTomMath
Description: public domain library for manipulating large integer numbers
Version: @to-be-replaced@
Version: @PROJECT_VERSION@
Libs: -L${libdir} -ltommath
Cflags: -I${includedir}

Changes to libtommath/libtommath_VS2008.sln.

Changes to libtommath/libtommath_VS2008.vcproj.

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




402
403
404
405
406
407
408







-
-
-
-







		<File
			RelativePath="bn_mp_div_2.c"
			>
		</File>
		<File
			RelativePath="bn_mp_div_2d.c"
			>
		</File>
		<File
			RelativePath="bn_mp_div_3.c"
			>
		</File>
		<File
			RelativePath="bn_mp_div_d.c"
			>
		</File>
		<File
			RelativePath="bn_mp_dr_is_modulus.c"
425
426
427
428
429
430
431
432

433
434
435
436
437
438
439
421
422
423
424
425
426
427

428
429
430
431
432
433
434
435







-
+







			>
		</File>
		<File
			RelativePath="bn_mp_exch.c"
			>
		</File>
		<File
			RelativePath="bn_mp_expt_u32.c"
			RelativePath="bn_mp_expt_n.c"
			>
		</File>
		<File
			RelativePath="bn_mp_exptmod.c"
			>
		</File>
		<File
471
472
473
474
475
476
477
478
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
467
468
469
470
471
472
473




474
475
476
477
478
479
480
481
482
483
484
485




486
487
488
489
490
491
492







-
-
-
-












-
-
-
-







		<File
			RelativePath="bn_mp_get_i64.c"
			>
		</File>
		<File
			RelativePath="bn_mp_get_l.c"
			>
		</File>
		<File
			RelativePath="bn_mp_get_ll.c"
			>
		</File>
		<File
			RelativePath="bn_mp_get_mag_u32.c"
			>
		</File>
		<File
			RelativePath="bn_mp_get_mag_u64.c"
			>
		</File>
		<File
			RelativePath="bn_mp_get_mag_ul.c"
			>
		</File>
		<File
			RelativePath="bn_mp_get_mag_ull.c"
			>
		</File>
		<File
			RelativePath="bn_mp_grow.c"
			>
		</File>
		<File
			RelativePath="bn_mp_incr.c"
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
507
508
509
510
511
512
513




514
515
516
517
518
519
520







-
-
-
-







		<File
			RelativePath="bn_mp_init_i64.c"
			>
		</File>
		<File
			RelativePath="bn_mp_init_l.c"
			>
		</File>
		<File
			RelativePath="bn_mp_init_ll.c"
			>
		</File>
		<File
			RelativePath="bn_mp_init_multi.c"
			>
		</File>
		<File
			RelativePath="bn_mp_init_set.c"
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
531
532
533
534
535
536
537




538
539
540
541
542
543
544







-
-
-
-







		<File
			RelativePath="bn_mp_init_u64.c"
			>
		</File>
		<File
			RelativePath="bn_mp_init_ul.c"
			>
		</File>
		<File
			RelativePath="bn_mp_init_ull.c"
			>
		</File>
		<File
			RelativePath="bn_mp_invmod.c"
			>
		</File>
		<File
			RelativePath="bn_mp_is_square.c"
577
578
579
580
581
582
583
584

585
586
587
588
589
590
591
557
558
559
560
561
562
563

564
565
566
567
568
569
570
571







-
+







			>
		</File>
		<File
			RelativePath="bn_mp_lcm.c"
			>
		</File>
		<File
			RelativePath="bn_mp_log_u32.c"
			RelativePath="bn_mp_log_n.c"
			>
		</File>
		<File
			RelativePath="bn_mp_lshd.c"
			>
		</File>
		<File
725
726
727
728
729
730
731
732

733
734
735
736
737
738
739
705
706
707
708
709
710
711

712
713
714
715
716
717
718
719







-
+







			>
		</File>
		<File
			RelativePath="bn_mp_reduce_setup.c"
			>
		</File>
		<File
			RelativePath="bn_mp_root_u32.c"
			RelativePath="bn_mp_root_n.c"
			>
		</File>
		<File
			RelativePath="bn_mp_rshd.c"
			>
		</File>
		<File
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
735
736
737
738
739
740
741




742
743
744
745
746
747
748
749
750
751
752
753




754
755
756
757
758
759
760







-
-
-
-












-
-
-
-







		<File
			RelativePath="bn_mp_set_i64.c"
			>
		</File>
		<File
			RelativePath="bn_mp_set_l.c"
			>
		</File>
		<File
			RelativePath="bn_mp_set_ll.c"
			>
		</File>
		<File
			RelativePath="bn_mp_set_u32.c"
			>
		</File>
		<File
			RelativePath="bn_mp_set_u64.c"
			>
		</File>
		<File
			RelativePath="bn_mp_set_ul.c"
			>
		</File>
		<File
			RelativePath="bn_mp_set_ull.c"
			>
		</File>
		<File
			RelativePath="bn_mp_shrink.c"
			>
		</File>
		<File
			RelativePath="bn_mp_signed_rsh.c"
851
852
853
854
855
856
857




858
859
860
861
862
863
864
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840







+
+
+
+







		<File
			RelativePath="bn_s_mp_add.c"
			>
		</File>
		<File
			RelativePath="bn_s_mp_balance_mul.c"
			>
		</File>
		<File
			RelativePath="bn_s_mp_div_3.c"
			>
		</File>
		<File
			RelativePath="bn_s_mp_exptmod.c"
			>
		</File>
		<File
			RelativePath="bn_s_mp_exptmod_fast.c"
879
880
881
882
883
884
885












886
887
888
889
890
891
892
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880







+
+
+
+
+
+
+
+
+
+
+
+







		<File
			RelativePath="bn_s_mp_karatsuba_mul.c"
			>
		</File>
		<File
			RelativePath="bn_s_mp_karatsuba_sqr.c"
			>
		</File>
		<File
			RelativePath="bn_s_mp_log.c"
			>
		</File>
		<File
			RelativePath="bn_s_mp_log_2expt.c"
			>
		</File>
		<File
			RelativePath="bn_s_mp_log_d.c"
			>
		</File>
		<File
			RelativePath="bn_s_mp_montgomery_reduce_fast.c"
			>
		</File>
		<File
			RelativePath="bn_s_mp_mul_digs.c"

Changes to libtommath/makefile.

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
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







-
-
+
+

-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








LCOV_ARGS=--directory .

#START_INS
OBJECTS=bn_cutoffs.o bn_deprecated.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o bn_mp_addmod.o \
bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \
bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o bn_mp_div.o bn_mp_div_2.o \
bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \
bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_u32.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \
bn_mp_div_2d.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \
bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_n.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \
bn_mp_from_sbin.o bn_mp_from_ubin.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_double.o bn_mp_get_i32.o \
bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_ll.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o \
bn_mp_get_mag_ull.o bn_mp_grow.o bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o \
bn_mp_init_i64.o bn_mp_init_l.o bn_mp_init_ll.o bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o \
bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o bn_mp_grow.o \
bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o bn_mp_init_i64.o bn_mp_init_l.o \
bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o \
bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o bn_mp_init_ull.o bn_mp_invmod.o bn_mp_is_square.o \
bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_u32.o bn_mp_lshd.o bn_mp_mod.o \
bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o \
bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o bn_mp_neg.o \
bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o bn_mp_prime_frobenius_underwood.o \
bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o \
bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o bn_mp_prime_strong_lucas_selfridge.o \
bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o \
bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o \
bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_root_u32.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o \
bn_mp_set_double.o bn_mp_set_i32.o bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_ll.o bn_mp_set_u32.o \
bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_set_ull.o bn_mp_shrink.o bn_mp_signed_rsh.o bn_mp_sqr.o \
bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o bn_mp_submod.o \
bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o bn_mp_xor.o bn_mp_zero.o \
bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o \
bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o \
bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o \
bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o \
bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o \
bn_s_mp_sub.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o
bn_mp_invmod.o bn_mp_is_square.o bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_n.o \
bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o \
bn_mp_montgomery_reduce.o bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o \
bn_mp_mulmod.o bn_mp_neg.o bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o \
bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o \
bn_mp_prime_next_prime.o bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o \
bn_mp_prime_strong_lucas_selfridge.o bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o \
bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o \
bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o \
bn_mp_root_n.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o bn_mp_set_double.o bn_mp_set_i32.o \
bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_u32.o bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_shrink.o \
bn_mp_signed_rsh.o bn_mp_sqr.o bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o \
bn_mp_submod.o bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o \
bn_mp_xor.o bn_mp_zero.o bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_div_3.o \
bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o \
bn_s_mp_karatsuba_mul.o bn_s_mp_karatsuba_sqr.o bn_s_mp_log.o bn_s_mp_log_2expt.o bn_s_mp_log_d.o \
bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o bn_s_mp_mul_high_digs.o \
bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o bn_s_mp_rand_jenkins.o \
bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o \
bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o

#END_INS

$(LIBNAME):  $(OBJECTS)
	$(AR) $(ARFLAGS) $@ $(OBJECTS)
	$(RANLIB) $@

129
130
131
132
133
134
135




136

137
138
139
140
141
142
143
129
130
131
132
133
134
135
136
137
138
139

140
141
142
143
144
145
146
147







+
+
+
+
-
+







.PHONY: pre_gen
pre_gen:
	mkdir -p pre_gen
	perl gen.pl
	sed -e 's/[[:blank:]]*$$//' mpi.c > pre_gen/mpi.c
	rm mpi.c

zipup:
	$(MAKE) clean
	$(MAKE) .zipup

zipup: clean astyle new_file docs
.zipup: astyle new_file docs
	@# Update the index, so diff-index won't fail in case the pdf has been created.
	@#   As the pdf creation modifies the tex files, git sometimes detects the
	@#   modified files, but misses that it's put back to its original version.
	@git update-index --refresh
	@git diff-index --quiet HEAD -- || ( echo "FAILURE: uncommited changes or not a git" && exit 1 )
	rm -rf libtommath-$(VERSION) ltm-$(VERSION).*
	@# files/dirs excluded from "git archive" are defined in .gitattributes

Changes to libtommath/makefile.mingw.

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
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
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
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













-
+
+
+



-
+
+
+




-
+











-
-
+
+

-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




















-
+







# MAKEFILE for MS Windows (mingw + gcc + gmake)
#
# BEWARE: variable OBJECTS is updated via helper.pl

### USAGE:
# Open a command prompt with gcc + gmake in PATH and start:
#
# gmake -f makefile.mingw all
# test.exe
# gmake -f makefile.mingw PREFIX=c:\devel\libtom install

#The following can be overridden from command line e.g. make -f makefile.mingw CC=gcc ARFLAGS=rcs
PREFIX    = c:\mingw
CC        = gcc
CC        = i686-w64-mingw32-gcc
#CC        = x86_64-w64-mingw32-clang
#CC        = aarch64-w64-mingw32-clang
AR        = ar
ARFLAGS   = r
RANLIB    = ranlib
STRIP     = strip
STRIP     = i686-w64-mingw32-gcc-strip
#STRIP     = x86_64-w64-mingw32-strip
#STRIP     = aarch64-w64-mingw32-strip
CFLAGS    = -O2
LDFLAGS   =

#Compilation flags
LTM_CFLAGS  = -I. $(CFLAGS)
LTM_CFLAGS  = -I. $(CFLAGS) -DTCL_WITH_EXTERNAL_TOMMATH
LTM_LDFLAGS = $(LDFLAGS) -static-libgcc

#Libraries to be created
LIBMAIN_S =libtommath.a
LIBMAIN_I =libtommath.dll.a
LIBMAIN_D =libtommath.dll

#List of objects to compile (all goes to libtommath.a)
OBJECTS=bn_cutoffs.o bn_deprecated.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o bn_mp_addmod.o \
bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \
bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o bn_mp_div.o bn_mp_div_2.o \
bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \
bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_u32.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \
bn_mp_div_2d.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \
bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_n.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \
bn_mp_from_sbin.o bn_mp_from_ubin.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_double.o bn_mp_get_i32.o \
bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_ll.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o \
bn_mp_get_mag_ull.o bn_mp_grow.o bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o \
bn_mp_init_i64.o bn_mp_init_l.o bn_mp_init_ll.o bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o \
bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o bn_mp_grow.o \
bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o bn_mp_init_i64.o bn_mp_init_l.o \
bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o \
bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o bn_mp_init_ull.o bn_mp_invmod.o bn_mp_is_square.o \
bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_u32.o bn_mp_lshd.o bn_mp_mod.o \
bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o \
bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o bn_mp_neg.o \
bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o bn_mp_prime_frobenius_underwood.o \
bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o \
bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o bn_mp_prime_strong_lucas_selfridge.o \
bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o \
bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o \
bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_root_u32.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o \
bn_mp_set_double.o bn_mp_set_i32.o bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_ll.o bn_mp_set_u32.o \
bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_set_ull.o bn_mp_shrink.o bn_mp_signed_rsh.o bn_mp_sqr.o \
bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o bn_mp_submod.o \
bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o bn_mp_xor.o bn_mp_zero.o \
bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o \
bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o \
bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o \
bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o \
bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o \
bn_s_mp_sub.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o
bn_mp_invmod.o bn_mp_is_square.o bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_n.o \
bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o \
bn_mp_montgomery_reduce.o bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o \
bn_mp_mulmod.o bn_mp_neg.o bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o \
bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o \
bn_mp_prime_next_prime.o bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o \
bn_mp_prime_strong_lucas_selfridge.o bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o \
bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o \
bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o \
bn_mp_root_n.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o bn_mp_set_double.o bn_mp_set_i32.o \
bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_u32.o bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_shrink.o \
bn_mp_signed_rsh.o bn_mp_sqr.o bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o \
bn_mp_submod.o bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o \
bn_mp_xor.o bn_mp_zero.o bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_div_3.o \
bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o \
bn_s_mp_karatsuba_mul.o bn_s_mp_karatsuba_sqr.o bn_s_mp_log.o bn_s_mp_log_2expt.o bn_s_mp_log_d.o \
bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o bn_s_mp_mul_high_digs.o \
bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o bn_s_mp_rand_jenkins.o \
bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o \
bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o

HEADERS_PUB=tommath.h
HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB)

#The default rule for make builds the libtommath.a library (static)
default: $(LIBMAIN_S)

#Dependencies on *.h
$(OBJECTS): $(HEADERS)

.c.o:
	$(CC) $(LTM_CFLAGS) -c $< -o $@

#Create libtommath.a
$(LIBMAIN_S): $(OBJECTS)
	$(AR) $(ARFLAGS) $@ $(OBJECTS)
	$(RANLIB) $@

#Create DLL + import library libtommath.dll.a
$(LIBMAIN_D) $(LIBMAIN_I): $(OBJECTS)
	$(CC) -s -shared -o $(LIBMAIN_D) $^ -Wl,--enable-auto-import,--export-all -Wl,--out-implib=$(LIBMAIN_I) $(LTM_LDFLAGS)
	$(CC) -s -shared -o $(LIBMAIN_D) $^ -Wl,--enable-auto-import tommath.def -Wl,--out-implib=$(LIBMAIN_I) $(LTM_LDFLAGS)
	$(STRIP) -S $(LIBMAIN_D)

#Build test suite
test.exe: demo/shared.o demo/test.o $(LIBMAIN_S)
	$(CC) $(LTM_CFLAGS) $(LTM_LDFLAGS) $^ -o $@
	@echo NOTICE: start the tests by launching test.exe

Changes to libtommath/makefile.msvc.

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
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







-
-
+
+

-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+







#Libraries to be created (this makefile builds only static libraries)
LIBMAIN_S =tommath.lib

#List of objects to compile (all goes to tommath.lib)
OBJECTS=bn_cutoffs.obj bn_deprecated.obj bn_mp_2expt.obj bn_mp_abs.obj bn_mp_add.obj bn_mp_add_d.obj bn_mp_addmod.obj \
bn_mp_and.obj bn_mp_clamp.obj bn_mp_clear.obj bn_mp_clear_multi.obj bn_mp_cmp.obj bn_mp_cmp_d.obj bn_mp_cmp_mag.obj \
bn_mp_cnt_lsb.obj bn_mp_complement.obj bn_mp_copy.obj bn_mp_count_bits.obj bn_mp_decr.obj bn_mp_div.obj bn_mp_div_2.obj \
bn_mp_div_2d.obj bn_mp_div_3.obj bn_mp_div_d.obj bn_mp_dr_is_modulus.obj bn_mp_dr_reduce.obj bn_mp_dr_setup.obj \
bn_mp_error_to_string.obj bn_mp_exch.obj bn_mp_expt_u32.obj bn_mp_exptmod.obj bn_mp_exteuclid.obj bn_mp_fread.obj \
bn_mp_div_2d.obj bn_mp_div_d.obj bn_mp_dr_is_modulus.obj bn_mp_dr_reduce.obj bn_mp_dr_setup.obj \
bn_mp_error_to_string.obj bn_mp_exch.obj bn_mp_expt_n.obj bn_mp_exptmod.obj bn_mp_exteuclid.obj bn_mp_fread.obj \
bn_mp_from_sbin.obj bn_mp_from_ubin.obj bn_mp_fwrite.obj bn_mp_gcd.obj bn_mp_get_double.obj bn_mp_get_i32.obj \
bn_mp_get_i64.obj bn_mp_get_l.obj bn_mp_get_ll.obj bn_mp_get_mag_u32.obj bn_mp_get_mag_u64.obj bn_mp_get_mag_ul.obj \
bn_mp_get_mag_ull.obj bn_mp_grow.obj bn_mp_incr.obj bn_mp_init.obj bn_mp_init_copy.obj bn_mp_init_i32.obj \
bn_mp_init_i64.obj bn_mp_init_l.obj bn_mp_init_ll.obj bn_mp_init_multi.obj bn_mp_init_set.obj bn_mp_init_size.obj \
bn_mp_get_i64.obj bn_mp_get_l.obj bn_mp_get_mag_u32.obj bn_mp_get_mag_u64.obj bn_mp_get_mag_ul.obj bn_mp_grow.obj \
bn_mp_incr.obj bn_mp_init.obj bn_mp_init_copy.obj bn_mp_init_i32.obj bn_mp_init_i64.obj bn_mp_init_l.obj \
bn_mp_init_multi.obj bn_mp_init_set.obj bn_mp_init_size.obj bn_mp_init_u32.obj bn_mp_init_u64.obj bn_mp_init_ul.obj \
bn_mp_init_u32.obj bn_mp_init_u64.obj bn_mp_init_ul.obj bn_mp_init_ull.obj bn_mp_invmod.obj bn_mp_is_square.obj \
bn_mp_iseven.obj bn_mp_isodd.obj bn_mp_kronecker.obj bn_mp_lcm.obj bn_mp_log_u32.obj bn_mp_lshd.obj bn_mp_mod.obj \
bn_mp_mod_2d.obj bn_mp_mod_d.obj bn_mp_montgomery_calc_normalization.obj bn_mp_montgomery_reduce.obj \
bn_mp_montgomery_setup.obj bn_mp_mul.obj bn_mp_mul_2.obj bn_mp_mul_2d.obj bn_mp_mul_d.obj bn_mp_mulmod.obj bn_mp_neg.obj \
bn_mp_or.obj bn_mp_pack.obj bn_mp_pack_count.obj bn_mp_prime_fermat.obj bn_mp_prime_frobenius_underwood.obj \
bn_mp_prime_is_prime.obj bn_mp_prime_miller_rabin.obj bn_mp_prime_next_prime.obj \
bn_mp_prime_rabin_miller_trials.obj bn_mp_prime_rand.obj bn_mp_prime_strong_lucas_selfridge.obj \
bn_mp_radix_size.obj bn_mp_radix_smap.obj bn_mp_rand.obj bn_mp_read_radix.obj bn_mp_reduce.obj bn_mp_reduce_2k.obj \
bn_mp_reduce_2k_l.obj bn_mp_reduce_2k_setup.obj bn_mp_reduce_2k_setup_l.obj bn_mp_reduce_is_2k.obj \
bn_mp_reduce_is_2k_l.obj bn_mp_reduce_setup.obj bn_mp_root_u32.obj bn_mp_rshd.obj bn_mp_sbin_size.obj bn_mp_set.obj \
bn_mp_set_double.obj bn_mp_set_i32.obj bn_mp_set_i64.obj bn_mp_set_l.obj bn_mp_set_ll.obj bn_mp_set_u32.obj \
bn_mp_invmod.obj bn_mp_is_square.obj bn_mp_iseven.obj bn_mp_isodd.obj bn_mp_kronecker.obj bn_mp_lcm.obj bn_mp_log_n.obj \
bn_mp_lshd.obj bn_mp_mod.obj bn_mp_mod_2d.obj bn_mp_mod_d.obj bn_mp_montgomery_calc_normalization.obj \
bn_mp_montgomery_reduce.obj bn_mp_montgomery_setup.obj bn_mp_mul.obj bn_mp_mul_2.obj bn_mp_mul_2d.obj bn_mp_mul_d.obj \
bn_mp_mulmod.obj bn_mp_neg.obj bn_mp_or.obj bn_mp_pack.obj bn_mp_pack_count.obj bn_mp_prime_fermat.obj \
bn_mp_prime_frobenius_underwood.obj bn_mp_prime_is_prime.obj bn_mp_prime_miller_rabin.obj \
bn_mp_prime_next_prime.obj bn_mp_prime_rabin_miller_trials.obj bn_mp_prime_rand.obj \
bn_mp_prime_strong_lucas_selfridge.obj bn_mp_radix_size.obj bn_mp_radix_smap.obj bn_mp_rand.obj \
bn_mp_read_radix.obj bn_mp_reduce.obj bn_mp_reduce_2k.obj bn_mp_reduce_2k_l.obj bn_mp_reduce_2k_setup.obj \
bn_mp_reduce_2k_setup_l.obj bn_mp_reduce_is_2k.obj bn_mp_reduce_is_2k_l.obj bn_mp_reduce_setup.obj \
bn_mp_root_n.obj bn_mp_rshd.obj bn_mp_sbin_size.obj bn_mp_set.obj bn_mp_set_double.obj bn_mp_set_i32.obj \
bn_mp_set_i64.obj bn_mp_set_l.obj bn_mp_set_u32.obj bn_mp_set_u64.obj bn_mp_set_ul.obj bn_mp_shrink.obj \
bn_mp_set_u64.obj bn_mp_set_ul.obj bn_mp_set_ull.obj bn_mp_shrink.obj bn_mp_signed_rsh.obj bn_mp_sqr.obj \
bn_mp_sqrmod.obj bn_mp_sqrt.obj bn_mp_sqrtmod_prime.obj bn_mp_sub.obj bn_mp_sub_d.obj bn_mp_submod.obj \
bn_mp_to_radix.obj bn_mp_to_sbin.obj bn_mp_to_ubin.obj bn_mp_ubin_size.obj bn_mp_unpack.obj bn_mp_xor.obj bn_mp_zero.obj \
bn_prime_tab.obj bn_s_mp_add.obj bn_s_mp_balance_mul.obj bn_s_mp_exptmod.obj bn_s_mp_exptmod_fast.obj \
bn_s_mp_get_bit.obj bn_s_mp_invmod_fast.obj bn_s_mp_invmod_slow.obj bn_s_mp_karatsuba_mul.obj \
bn_s_mp_karatsuba_sqr.obj bn_s_mp_montgomery_reduce_fast.obj bn_s_mp_mul_digs.obj bn_s_mp_mul_digs_fast.obj \
bn_s_mp_mul_high_digs.obj bn_s_mp_mul_high_digs_fast.obj bn_s_mp_prime_is_divisible.obj \
bn_s_mp_rand_jenkins.obj bn_s_mp_rand_platform.obj bn_s_mp_reverse.obj bn_s_mp_sqr.obj bn_s_mp_sqr_fast.obj \
bn_s_mp_sub.obj bn_s_mp_toom_mul.obj bn_s_mp_toom_sqr.obj
bn_mp_signed_rsh.obj bn_mp_sqr.obj bn_mp_sqrmod.obj bn_mp_sqrt.obj bn_mp_sqrtmod_prime.obj bn_mp_sub.obj bn_mp_sub_d.obj \
bn_mp_submod.obj bn_mp_to_radix.obj bn_mp_to_sbin.obj bn_mp_to_ubin.obj bn_mp_ubin_size.obj bn_mp_unpack.obj \
bn_mp_xor.obj bn_mp_zero.obj bn_prime_tab.obj bn_s_mp_add.obj bn_s_mp_balance_mul.obj bn_s_mp_div_3.obj \
bn_s_mp_exptmod.obj bn_s_mp_exptmod_fast.obj bn_s_mp_get_bit.obj bn_s_mp_invmod_fast.obj bn_s_mp_invmod_slow.obj \
bn_s_mp_karatsuba_mul.obj bn_s_mp_karatsuba_sqr.obj bn_s_mp_log.obj bn_s_mp_log_2expt.obj bn_s_mp_log_d.obj \
bn_s_mp_montgomery_reduce_fast.obj bn_s_mp_mul_digs.obj bn_s_mp_mul_digs_fast.obj bn_s_mp_mul_high_digs.obj \
bn_s_mp_mul_high_digs_fast.obj bn_s_mp_prime_is_divisible.obj bn_s_mp_rand_jenkins.obj \
bn_s_mp_rand_platform.obj bn_s_mp_reverse.obj bn_s_mp_sqr.obj bn_s_mp_sqr_fast.obj bn_s_mp_sub.obj \
bn_s_mp_toom_mul.obj bn_s_mp_toom_sqr.obj

HEADERS_PUB=tommath.h
HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB)

#The default rule for make builds the tommath.lib library (static)
default: $(LIBMAIN_S)

Changes to libtommath/makefile.shared.

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
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







-
-
+
+

-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-
+
+








LCOV_ARGS=--directory .libs --directory .

#START_INS
OBJECTS=bn_cutoffs.o bn_deprecated.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o bn_mp_addmod.o \
bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \
bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o bn_mp_div.o bn_mp_div_2.o \
bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \
bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_u32.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \
bn_mp_div_2d.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \
bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_n.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \
bn_mp_from_sbin.o bn_mp_from_ubin.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_double.o bn_mp_get_i32.o \
bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_ll.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o \
bn_mp_get_mag_ull.o bn_mp_grow.o bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o \
bn_mp_init_i64.o bn_mp_init_l.o bn_mp_init_ll.o bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o \
bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o bn_mp_grow.o \
bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o bn_mp_init_i64.o bn_mp_init_l.o \
bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o \
bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o bn_mp_init_ull.o bn_mp_invmod.o bn_mp_is_square.o \
bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_u32.o bn_mp_lshd.o bn_mp_mod.o \
bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o \
bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o bn_mp_neg.o \
bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o bn_mp_prime_frobenius_underwood.o \
bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o \
bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o bn_mp_prime_strong_lucas_selfridge.o \
bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o \
bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o \
bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_root_u32.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o \
bn_mp_set_double.o bn_mp_set_i32.o bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_ll.o bn_mp_set_u32.o \
bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_set_ull.o bn_mp_shrink.o bn_mp_signed_rsh.o bn_mp_sqr.o \
bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o bn_mp_submod.o \
bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o bn_mp_xor.o bn_mp_zero.o \
bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o \
bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o \
bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o \
bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o \
bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o \
bn_s_mp_sub.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o
bn_mp_invmod.o bn_mp_is_square.o bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_n.o \
bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o \
bn_mp_montgomery_reduce.o bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o \
bn_mp_mulmod.o bn_mp_neg.o bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o \
bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o \
bn_mp_prime_next_prime.o bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o \
bn_mp_prime_strong_lucas_selfridge.o bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o \
bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o \
bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o \
bn_mp_root_n.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o bn_mp_set_double.o bn_mp_set_i32.o \
bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_u32.o bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_shrink.o \
bn_mp_signed_rsh.o bn_mp_sqr.o bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o \
bn_mp_submod.o bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o \
bn_mp_xor.o bn_mp_zero.o bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_div_3.o \
bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o \
bn_s_mp_karatsuba_mul.o bn_s_mp_karatsuba_sqr.o bn_s_mp_log.o bn_s_mp_log_2expt.o bn_s_mp_log_d.o \
bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o bn_s_mp_mul_high_digs.o \
bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o bn_s_mp_rand_jenkins.o \
bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o \
bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o

#END_INS

objs: $(OBJECTS)

.c.o: $(HEADERS)
	$(LTCOMPILE) $(LTM_CFLAGS) $(LTM_LDFLAGS) -o $@ -c $<

LOBJECTS = $(OBJECTS:.o=.lo)

$(LIBNAME):  $(OBJECTS)
	$(LTLINK) $(LTM_LDFLAGS) $(LOBJECTS) -o $(LIBNAME) -rpath $(LIBPATH) -version-info $(VERSION_SO) $(LTM_LIBTOOLFLAGS)

install: $(LIBNAME)
	install -d $(DESTDIR)$(LIBPATH)
	install -d $(DESTDIR)$(INCPATH)
	$(LIBTOOL) --mode=install install -m 644 $(LIBNAME) $(DESTDIR)$(LIBPATH)/$(LIBNAME)
	install -m 644 $(HEADERS_PUB) $(DESTDIR)$(INCPATH)
	sed -e 's,^prefix=.*,prefix=$(PREFIX),' -e 's,^Version:.*,Version: $(VERSION_PC),' libtommath.pc.in > libtommath.pc
	sed -e 's,^prefix=.*,prefix=$(PREFIX),' -e 's,^Version:.*,Version: $(VERSION_PC),' -e 's,@CMAKE_INSTALL_LIBDIR@,lib,' \
		-e 's,@CMAKE_INSTALL_INCLUDEDIR@,include,' libtommath.pc.in > libtommath.pc
	install -d $(DESTDIR)$(LIBPATH)/pkgconfig
	install -m 644 libtommath.pc $(DESTDIR)$(LIBPATH)/pkgconfig/

uninstall:
	$(LIBTOOL) --mode=uninstall rm $(DESTDIR)$(LIBPATH)/$(LIBNAME)
	rm $(HEADERS_PUB:%=$(DESTDIR)$(INCPATH)/%)
	rm $(DESTDIR)$(LIBPATH)/pkgconfig/libtommath.pc

Changes to libtommath/makefile.unix.

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
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







-
+











-
-
+
+

-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







CC        = cc
AR        = ar
ARFLAGS   = r
RANLIB    = ranlib
CFLAGS    = -O2
LDFLAGS   =

VERSION   = 1.2.0
VERSION   = 1.3.0

#Compilation flags
LTM_CFLAGS  = -I. $(CFLAGS)
LTM_LDFLAGS = $(LDFLAGS)

#Library to be created (this makefile builds only static library)
LIBMAIN_S = libtommath.a

OBJECTS=bn_cutoffs.o bn_deprecated.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o bn_mp_addmod.o \
bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \
bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o bn_mp_div.o bn_mp_div_2.o \
bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \
bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_u32.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \
bn_mp_div_2d.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \
bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_n.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \
bn_mp_from_sbin.o bn_mp_from_ubin.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_double.o bn_mp_get_i32.o \
bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_ll.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o \
bn_mp_get_mag_ull.o bn_mp_grow.o bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o \
bn_mp_init_i64.o bn_mp_init_l.o bn_mp_init_ll.o bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o \
bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o bn_mp_grow.o \
bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o bn_mp_init_i64.o bn_mp_init_l.o \
bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o \
bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o bn_mp_init_ull.o bn_mp_invmod.o bn_mp_is_square.o \
bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_u32.o bn_mp_lshd.o bn_mp_mod.o \
bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o \
bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o bn_mp_neg.o \
bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o bn_mp_prime_frobenius_underwood.o \
bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o \
bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o bn_mp_prime_strong_lucas_selfridge.o \
bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o \
bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o \
bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_root_u32.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o \
bn_mp_set_double.o bn_mp_set_i32.o bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_ll.o bn_mp_set_u32.o \
bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_set_ull.o bn_mp_shrink.o bn_mp_signed_rsh.o bn_mp_sqr.o \
bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o bn_mp_submod.o \
bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o bn_mp_xor.o bn_mp_zero.o \
bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o \
bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o \
bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o \
bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o \
bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o \
bn_s_mp_sub.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o
bn_mp_invmod.o bn_mp_is_square.o bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_n.o \
bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o \
bn_mp_montgomery_reduce.o bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o \
bn_mp_mulmod.o bn_mp_neg.o bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o \
bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o \
bn_mp_prime_next_prime.o bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o \
bn_mp_prime_strong_lucas_selfridge.o bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o \
bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o \
bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o \
bn_mp_root_n.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o bn_mp_set_double.o bn_mp_set_i32.o \
bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_u32.o bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_shrink.o \
bn_mp_signed_rsh.o bn_mp_sqr.o bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o \
bn_mp_submod.o bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o \
bn_mp_xor.o bn_mp_zero.o bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_div_3.o \
bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o \
bn_s_mp_karatsuba_mul.o bn_s_mp_karatsuba_sqr.o bn_s_mp_log.o bn_s_mp_log_2expt.o bn_s_mp_log_d.o \
bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o bn_s_mp_mul_high_digs.o \
bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o bn_s_mp_rand_jenkins.o \
bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o \
bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o

HEADERS_PUB=tommath.h
HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB)

#The default rule for make builds the libtommath.a library (static)
default: $(LIBMAIN_S)

Changes to libtommath/makefile_include.mk.

1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15





-
-
-
+
+
+







#
# Include makefile for libtommath
#

#version of library
VERSION=1.2.0
VERSION_PC=1.2.0
VERSION_SO=3:0:2
VERSION=1.3.0
VERSION_PC=1.3.0
VERSION_SO=4:0:3

PLATFORM := $(shell uname | sed -e 's/_.*//')

# default make target
default: ${LIBNAME}

# Compiler and Linker Names
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
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







-
+


-
+















-
-
-
-







  _ARCH := $(shell sysctl -b hw.machine_arch)
else
  _ARCH := $(shell uname -m)
endif

# adjust coverage set
ifneq ($(filter $(_ARCH), i386 i686 x86_64 amd64 ia64),)
   COVERAGE = test timing
   COVERAGE = test_standalone timing
   COVERAGE_APP = ./test && ./timing
else
   COVERAGE = test
   COVERAGE = test_standalone
   COVERAGE_APP = ./test
endif

HEADERS_PUB=tommath.h
HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB)

#LIBPATH  The directory for libtommath to be installed to.
#INCPATH  The directory to install the header files for libtommath.
#DATAPATH The directory to install the pdf docs.
DESTDIR  ?=
PREFIX   ?= /usr/local
LIBPATH  ?= $(PREFIX)/lib
INCPATH  ?= $(PREFIX)/include
DATAPATH ?= $(PREFIX)/share/doc/libtommath/pdf

# build & run test-suite
check: test
	./test

#make the code coverage of the library
#
coverage: LTM_CFLAGS += -fprofile-arcs -ftest-coverage -DTIMING_NO_LOGS
coverage: LTM_LFLAGS += -lgcov
coverage: LTM_LDFLAGS += -lgcov

coverage: $(COVERAGE)

Added libtommath/sources.cmake.








































































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# SPDX-License-Identifier: Unlicense
# Autogenerated File! Do not edit.

set(SOURCES
bn_cutoffs.c
bn_deprecated.c
bn_mp_2expt.c
bn_mp_abs.c
bn_mp_add.c
bn_mp_add_d.c
bn_mp_addmod.c
bn_mp_and.c
bn_mp_clamp.c
bn_mp_clear.c
bn_mp_clear_multi.c
bn_mp_cmp.c
bn_mp_cmp_d.c
bn_mp_cmp_mag.c
bn_mp_cnt_lsb.c
bn_mp_complement.c
bn_mp_copy.c
bn_mp_count_bits.c
bn_mp_decr.c
bn_mp_div.c
bn_mp_div_2.c
bn_mp_div_2d.c
bn_mp_div_d.c
bn_mp_dr_is_modulus.c
bn_mp_dr_reduce.c
bn_mp_dr_setup.c
bn_mp_error_to_string.c
bn_mp_exch.c
bn_mp_expt_n.c
bn_mp_exptmod.c
bn_mp_exteuclid.c
bn_mp_fread.c
bn_mp_from_sbin.c
bn_mp_from_ubin.c
bn_mp_fwrite.c
bn_mp_gcd.c
bn_mp_get_double.c
bn_mp_get_i32.c
bn_mp_get_i64.c
bn_mp_get_l.c
bn_mp_get_mag_u32.c
bn_mp_get_mag_u64.c
bn_mp_get_mag_ul.c
bn_mp_grow.c
bn_mp_incr.c
bn_mp_init.c
bn_mp_init_copy.c
bn_mp_init_i32.c
bn_mp_init_i64.c
bn_mp_init_l.c
bn_mp_init_multi.c
bn_mp_init_set.c
bn_mp_init_size.c
bn_mp_init_u32.c
bn_mp_init_u64.c
bn_mp_init_ul.c
bn_mp_invmod.c
bn_mp_is_square.c
bn_mp_iseven.c
bn_mp_isodd.c
bn_mp_kronecker.c
bn_mp_lcm.c
bn_mp_log_n.c
bn_mp_lshd.c
bn_mp_mod.c
bn_mp_mod_2d.c
bn_mp_mod_d.c
bn_mp_montgomery_calc_normalization.c
bn_mp_montgomery_reduce.c
bn_mp_montgomery_setup.c
bn_mp_mul.c
bn_mp_mul_2.c
bn_mp_mul_2d.c
bn_mp_mul_d.c
bn_mp_mulmod.c
bn_mp_neg.c
bn_mp_or.c
bn_mp_pack.c
bn_mp_pack_count.c
bn_mp_prime_fermat.c
bn_mp_prime_frobenius_underwood.c
bn_mp_prime_is_prime.c
bn_mp_prime_miller_rabin.c
bn_mp_prime_next_prime.c
bn_mp_prime_rabin_miller_trials.c
bn_mp_prime_rand.c
bn_mp_prime_strong_lucas_selfridge.c
bn_mp_radix_size.c
bn_mp_radix_smap.c
bn_mp_rand.c
bn_mp_read_radix.c
bn_mp_reduce.c
bn_mp_reduce_2k.c
bn_mp_reduce_2k_l.c
bn_mp_reduce_2k_setup.c
bn_mp_reduce_2k_setup_l.c
bn_mp_reduce_is_2k.c
bn_mp_reduce_is_2k_l.c
bn_mp_reduce_setup.c
bn_mp_root_n.c
bn_mp_rshd.c
bn_mp_sbin_size.c
bn_mp_set.c
bn_mp_set_double.c
bn_mp_set_i32.c
bn_mp_set_i64.c
bn_mp_set_l.c
bn_mp_set_u32.c
bn_mp_set_u64.c
bn_mp_set_ul.c
bn_mp_shrink.c
bn_mp_signed_rsh.c
bn_mp_sqr.c
bn_mp_sqrmod.c
bn_mp_sqrt.c
bn_mp_sqrtmod_prime.c
bn_mp_sub.c
bn_mp_sub_d.c
bn_mp_submod.c
bn_mp_to_radix.c
bn_mp_to_sbin.c
bn_mp_to_ubin.c
bn_mp_ubin_size.c
bn_mp_unpack.c
bn_mp_xor.c
bn_mp_zero.c
bn_prime_tab.c
bn_s_mp_add.c
bn_s_mp_balance_mul.c
bn_s_mp_div_3.c
bn_s_mp_exptmod.c
bn_s_mp_exptmod_fast.c
bn_s_mp_get_bit.c
bn_s_mp_invmod_fast.c
bn_s_mp_invmod_slow.c
bn_s_mp_karatsuba_mul.c
bn_s_mp_karatsuba_sqr.c
bn_s_mp_log.c
bn_s_mp_log_2expt.c
bn_s_mp_log_d.c
bn_s_mp_montgomery_reduce_fast.c
bn_s_mp_mul_digs.c
bn_s_mp_mul_digs_fast.c
bn_s_mp_mul_high_digs.c
bn_s_mp_mul_high_digs_fast.c
bn_s_mp_prime_is_divisible.c
bn_s_mp_rand_jenkins.c
bn_s_mp_rand_platform.c
bn_s_mp_reverse.c
bn_s_mp_sqr.c
bn_s_mp_sqr_fast.c
bn_s_mp_sub.c
bn_s_mp_toom_mul.c
bn_s_mp_toom_sqr.c
)

set(HEADERS
tommath.h
tommath_class.h
tommath_cutoffs.h
tommath_private.h
tommath_superclass.h
)

Changes to libtommath/tommath.def.

29
30
31
32
33
34
35

36
37
38
39
40
41
42
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43







+







    mp_div_3
    mp_div_d
    mp_dr_is_modulus
    mp_dr_reduce
    mp_dr_setup
    mp_error_to_string
    mp_exch
    mp_expt_n
    mp_expt_u32
    mp_exptmod
    mp_exteuclid
    mp_fread
    mp_from_sbin
    mp_from_ubin
    mp_fwrite
71
72
73
74
75
76
77

78
79
80
81
82
83
84
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86







+







    mp_init_ull
    mp_invmod
    mp_is_square
    mp_iseven
    mp_isodd
    mp_kronecker
    mp_lcm
    mp_log_n
    mp_log_u32
    mp_lshd
    mp_mod
    mp_mod_2d
    mp_mod_d
    mp_montgomery_calc_normalization
    mp_montgomery_reduce
107
108
109
110
111
112
113

114
115
116
117
118
119
120
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123







+







    mp_reduce_2k
    mp_reduce_2k_l
    mp_reduce_2k_setup
    mp_reduce_2k_setup_l
    mp_reduce_is_2k
    mp_reduce_is_2k_l
    mp_reduce_setup
    mp_root_n
    mp_root_u32
    mp_rshd
    mp_sbin_size
    mp_set
    mp_set_double
    mp_set_i32
    mp_set_i64
139
140
141
142
143
144
145












142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160







+
+
+
+
+
+
+
+
+
+
+
+
    mp_to_radix
    mp_to_sbin
    mp_to_ubin
    mp_ubin_size
    mp_unpack
    mp_xor
    mp_zero
    s_mp_add
    s_mp_balance_mul
    s_mp_karatsuba_mul
    s_mp_karatsuba_sqr
    s_mp_mul_digs
    s_mp_mul_digs_fast
    s_mp_reverse
    s_mp_sqr
    s_mp_sqr_fast
    s_mp_sub
    s_mp_toom_mul
    s_mp_toom_sqr

Changes to libtommath/tommath.h.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
1
2
3
4
5
6



7

8
9
10
11
12
13
14






-
-
-
+
-







/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

#ifndef BN_H_
#define BN_H_

#if !defined(MP_NO_STDINT) && !defined(_STDINT_H) && !defined(_STDINT_H_) \
	&& !defined(__CLANG_STDINT_H) && !defined(_STDINT)
#  include <stdint.h>
#include <stdint.h>
#endif
#include <stddef.h>
#include <limits.h>

#ifdef LTM_NO_FILE
#  warning LTM_NO_FILE has been deprecated, use MP_NO_FILE.
#  define MP_NO_FILE
#endif
34
35
36
37
38
39
40
41

42
43
44
45
46
47
48

49
50
51
52
53
54
55
31
32
33
34
35
36
37

38
39
40
41
42
43
44

45
46
47
48
49
50
51
52







-
+






-
+








/* MS Visual C++ doesn't have a 128bit type for words, so fall back to 32bit MPI's (where words are 64bit) */
#if (defined(_MSC_VER) || defined(__LLP64__) || defined(__e2k__) || defined(__LCC__)) && !defined(MP_32BIT) && !defined(MP_64BIT)
#   define MP_32BIT
#endif

/* detect 64-bit mode if possible */
#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || \
#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || defined(_M_ARM64) || \
    defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || \
    defined(__s390x__) || defined(__arch64__) || defined(__aarch64__) || \
    defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__) || \
    defined(__ia64) || defined(__ia64__) || defined(__itanium__) || defined(_M_IA64) || \
    defined(__LP64__) || defined(_LP64) || defined(__64BIT__)
#   if !(defined(MP_64BIT) || defined(MP_32BIT) || defined(MP_16BIT) || defined(MP_8BIT))
#      if defined(__GNUC__) && !defined(__hppa)
#      if defined(__GNUC__) && defined(__SIZEOF_INT128__) && !defined(__hppa)
/* we support 128bit integers only via: __attribute__((mode(TI))) */
#         define MP_64BIT
#      else
/* otherwise we fall back to MP_32BIT even on 64bit platforms */
#         define MP_32BIT
#      endif
#   endif
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
230
231
232
233
234
235
236








237
238
239
240
241

242



243
244
245
246
247
248
249
250







-
-
-
-
-
-
-
-



+

-
+
-
-
-
+







#  else
#     define MP_WUR
#  endif
#endif

#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 405)
#  define MP_DEPRECATED(x) __attribute__((deprecated("replaced by " #x)))
#elif defined(_MSC_VER) && _MSC_VER >= 1500
#  define MP_DEPRECATED(x) __declspec(deprecated("replaced by " #x))
#else
#  define MP_DEPRECATED(x)
#endif

#ifndef MP_NO_DEPRECATED_PRAGMA
#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 301)
#  define PRIVATE_MP_DEPRECATED_PRAGMA(s) _Pragma(#s)
#  define MP_DEPRECATED_PRAGMA(s) PRIVATE_MP_DEPRECATED_PRAGMA(GCC warning s)
#elif defined(_MSC_VER) && _MSC_VER >= 1500
#  define MP_DEPRECATED(x) __declspec(deprecated("replaced by " #x))
#  define MP_DEPRECATED_PRAGMA(s) __pragma(message(s))
#endif
#else
#endif

#ifndef MP_DEPRECATED_PRAGMA
#  define MP_DEPRECATED(s)
#  define MP_DEPRECATED_PRAGMA(s)
#endif

#define DIGIT_BIT   (MP_DEPRECATED_PRAGMA("DIGIT_BIT macro is deprecated, MP_DIGIT_BIT instead") MP_DIGIT_BIT)
#define USED(m)     (MP_DEPRECATED_PRAGMA("USED macro is deprecated, use z->used instead") (m)->used)
#define DIGIT(m, k) (MP_DEPRECATED_PRAGMA("DIGIT macro is deprecated, use z->dp instead") (m)->dp[(k)])
#define SIGN(m)     (MP_DEPRECATED_PRAGMA("SIGN macro is deprecated, use z->sign instead") (m)->sign)
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
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
366
367
368
369
370
371







-
-
-
-
+
-











-

-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+


-
-
-
+
+
+
-








-
-
+
-


-
-
+
-







void mp_set_u64(mp_int *a, uint64_t b);
mp_err mp_init_u64(mp_int *a, uint64_t b) MP_WUR;

/* get magnitude */
uint32_t mp_get_mag_u32(const mp_int *a) MP_WUR;
uint64_t mp_get_mag_u64(const mp_int *a) MP_WUR;
unsigned long mp_get_mag_ul(const mp_int *a) MP_WUR;
#ifdef _MSC_VER
#define mp_get_mag_ull(a) ((unsigned __int64)mp_get_mag_u64(a))
#else
unsigned long long mp_get_mag_ull(const mp_int *a) MP_WUR;
MP_DEPRECATED(mp_get_mag_u64) unsigned long long mp_get_mag_ull(const mp_int *a) MP_WUR;
#endif

/* get integer, set integer (long) */
long mp_get_l(const mp_int *a) MP_WUR;
void mp_set_l(mp_int *a, long b);
mp_err mp_init_l(mp_int *a, long b) MP_WUR;

/* get integer, set integer (unsigned long) */
#define mp_get_ul(a) ((unsigned long)mp_get_l(a))
void mp_set_ul(mp_int *a, unsigned long b);
mp_err mp_init_ul(mp_int *a, unsigned long b) MP_WUR;

#ifdef _MSC_VER
/* get integer, set integer (long long) */
#define mp_get_ll(a) ((__int64)mp_get_i64(a))
#define mp_set_ll(a,b) mp_set_i64(a,b)
#define mp_init_ll(a,b) mp_init_i64(a,b)

/* get integer, set integer (unsigned long long) */
#define mp_get_ull(a) ((unsigned __int64)mp_get_i64(a))
#define mp_set_ull(a,b) mp_set_u64(a,b)
#define mp_init_ull(a,b) mp_init_u64(a,b)
#else
/* get integer, set integer (long long) */
long long mp_get_ll(const mp_int *a) MP_WUR;
void mp_set_ll(mp_int *a, long long b);
mp_err mp_init_ll(mp_int *a, long long b) MP_WUR;
MP_DEPRECATED(mp_get_i64) long long mp_get_ll(const mp_int *a) MP_WUR;
MP_DEPRECATED(mp_set_i64) void mp_set_ll(mp_int *a, long long b);
MP_DEPRECATED(mp_init_i64) mp_err mp_init_ll(mp_int *a, long long b) MP_WUR;

/* get integer, set integer (unsigned long long) */
#define mp_get_ull(a) ((unsigned long long)mp_get_ll(a))
void mp_set_ull(mp_int *a, unsigned long long b);
mp_err mp_init_ull(mp_int *a, unsigned long long b) MP_WUR;
#define mp_get_ull(a) (MP_DEPRECATED_PRAGMA("mp_get_ull() has been deprecated, use mp_get_u64()") ((unsigned long long)mp_get_ll(a)))
MP_DEPRECATED(mp_set_u64) void mp_set_ull(mp_int *a, unsigned long long b);
MP_DEPRECATED(mp_init_u64) mp_err mp_init_ull(mp_int *a, unsigned long long b) MP_WUR;
#endif

/* set to single unsigned digit, up to MP_DIGIT_MAX */
void mp_set(mp_int *a, mp_digit b);
mp_err mp_init_set(mp_int *a, mp_digit b) MP_WUR;

/* get integer, set integer and init with integer (deprecated) */
MP_DEPRECATED(mp_get_mag_u32/mp_get_u32) unsigned long mp_get_int(const mp_int *a) MP_WUR;
MP_DEPRECATED(mp_get_mag_ul/mp_get_ul) unsigned long mp_get_long(const mp_int *a) MP_WUR;
#ifdef _MSC_VER
MP_DEPRECATED(mp_get_mag_ull/mp_get_ull) unsigned __int64 mp_get_long_long(const mp_int *a) MP_WUR;
MP_DEPRECATED(mp_get_mag_u64/mp_get_u64) unsigned long long mp_get_long_long(const mp_int *a) MP_WUR;
#endif
MP_DEPRECATED(mp_set_ul) mp_err mp_set_int(mp_int *a, unsigned long b);
MP_DEPRECATED(mp_set_ul) mp_err mp_set_long(mp_int *a, unsigned long b);
#ifdef _MSC_VER
MP_DEPRECATED(mp_set_ull) mp_err mp_set_long_long(mp_int *a, unsigned __int64 b);
MP_DEPRECATED(mp_set_ull) mp_err mp_set_long_long(mp_int *a, unsigned long long b);
#endif
MP_DEPRECATED(mp_init_ul) mp_err mp_init_set_int(mp_int *a, unsigned long b) MP_WUR;

/* copy, b = a */
mp_err mp_copy(const mp_int *a, mp_int *b) MP_WUR;

/* inits and copies, a = b */
mp_err mp_init_copy(mp_int *a, const mp_int *b) MP_WUR;
435
436
437
438
439
440
441
442

443
444
445
446
447
448
449
403
404
405
406
407
408
409

410
411
412
413
414
415
416
417







-
+







/* c = a / 2**b, implemented as c = a >> b */
mp_err mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d) MP_WUR;

/* b = a/2 */
mp_err mp_div_2(const mp_int *a, mp_int *b) MP_WUR;

/* a/3 => 3c + d == a */
mp_err mp_div_3(const mp_int *a, mp_int *c, mp_digit *d) MP_WUR;
MP_DEPRECATED(mp_div_d) mp_err mp_div_3(const mp_int *a, mp_int *c, mp_digit *d) MP_WUR;

/* c = a * 2**b, implemented as c = a << b */
mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c) MP_WUR;

/* b = a*2 */
mp_err mp_mul_2(const mp_int *a, mp_int *b) MP_WUR;

582
583
584
585
586
587
588










589
590
591
592

593
594
595



596
597
598
599
600
601
602
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571



572
573
574
575
576
577
578
579
580
581







+
+
+
+
+
+
+
+
+
+




+
-
-
-
+
+
+








/* produces value such that U1*a + U2*b = U3 */
mp_err mp_exteuclid(const mp_int *a, const mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) MP_WUR;

/* c = [a, b] or (a*b)/(a, b) */
mp_err mp_lcm(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR;

/* Integer logarithm to integer base */
mp_err mp_log_n(const mp_int *a, int base, int *c) MP_WUR;
MP_DEPRECATED(mp_log_n) mp_err mp_log_u32(const mp_int *a, uint32_t base, uint32_t *c) MP_WUR;

/* c = a**b */
mp_err mp_expt_n(const mp_int *a, int b, mp_int *c) MP_WUR;
MP_DEPRECATED(mp_expt_n) mp_err mp_expt_u32(const mp_int *a, uint32_t b, mp_int *c) MP_WUR;
MP_DEPRECATED(mp_expt_n) mp_err mp_expt_d(const mp_int *a, mp_digit b, mp_int *c) MP_WUR;
MP_DEPRECATED(mp_expt_n) mp_err mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) MP_WUR;

/* finds one of the b'th root of a, such that |c|**b <= |a|
 *
 * returns error if a < 0 and b is even
 */
mp_err mp_root_n(const mp_int *a, int b, mp_int *c) MP_WUR;
mp_err mp_root_u32(const mp_int *a, uint32_t b, mp_int *c) MP_WUR;
MP_DEPRECATED(mp_root_u32) mp_err mp_n_root(const mp_int *a, mp_digit b, mp_int *c) MP_WUR;
MP_DEPRECATED(mp_root_u32) mp_err mp_n_root_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) MP_WUR;
MP_DEPRECATED(mp_root_n) mp_err mp_root_u32(const mp_int *a, uint32_t b, mp_int *c) MP_WUR;
MP_DEPRECATED(mp_root_n) mp_err mp_n_root(const mp_int *a, mp_digit b, mp_int *c) MP_WUR;
MP_DEPRECATED(mp_root_n) mp_err mp_n_root_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) MP_WUR;

/* special sqrt algo */
mp_err mp_sqrt(const mp_int *arg, mp_int *ret) MP_WUR;

/* special sqrt (mod prime) */
mp_err mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret) MP_WUR;

748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
727
728
729
730
731
732
733








734
735
736
737
738
739
740







-
-
-
-
-
-
-
-







 * so it can be NULL
 *
 */
MP_DEPRECATED(mp_prime_rand) mp_err mp_prime_random_ex(mp_int *a, int t, int size, int flags,
      private_mp_prime_callback cb, void *dat) MP_WUR;
mp_err mp_prime_rand(mp_int *a, int t, int size, int flags) MP_WUR;

/* Integer logarithm to integer base */
mp_err mp_log_u32(const mp_int *a, uint32_t base, uint32_t *c) MP_WUR;

/* c = a**b */
mp_err mp_expt_u32(const mp_int *a, uint32_t b, mp_int *c) MP_WUR;
MP_DEPRECATED(mp_expt_u32) mp_err mp_expt_d(const mp_int *a, mp_digit b, mp_int *c) MP_WUR;
MP_DEPRECATED(mp_expt_u32) mp_err mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) MP_WUR;

/* ---> radix conversion <--- */
int mp_count_bits(const mp_int *a) MP_WUR;


MP_DEPRECATED(mp_ubin_size) int mp_unsigned_bin_size(const mp_int *a) MP_WUR;
MP_DEPRECATED(mp_from_ubin) mp_err mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c) MP_WUR;
MP_DEPRECATED(mp_to_ubin) mp_err mp_to_unsigned_bin(const mp_int *a, unsigned char *b) MP_WUR;

Changes to libtommath/tommath_class.h.

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
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







-






-
+











-



-







-






-






-
+







#   define BN_MP_COMPLEMENT_C
#   define BN_MP_COPY_C
#   define BN_MP_COUNT_BITS_C
#   define BN_MP_DECR_C
#   define BN_MP_DIV_C
#   define BN_MP_DIV_2_C
#   define BN_MP_DIV_2D_C
#   define BN_MP_DIV_3_C
#   define BN_MP_DIV_D_C
#   define BN_MP_DR_IS_MODULUS_C
#   define BN_MP_DR_REDUCE_C
#   define BN_MP_DR_SETUP_C
#   define BN_MP_ERROR_TO_STRING_C
#   define BN_MP_EXCH_C
#   define BN_MP_EXPT_U32_C
#   define BN_MP_EXPT_N_C
#   define BN_MP_EXPTMOD_C
#   define BN_MP_EXTEUCLID_C
#   define BN_MP_FREAD_C
#   define BN_MP_FROM_SBIN_C
#   define BN_MP_FROM_UBIN_C
#   define BN_MP_FWRITE_C
#   define BN_MP_GCD_C
#   define BN_MP_GET_DOUBLE_C
#   define BN_MP_GET_I32_C
#   define BN_MP_GET_I64_C
#   define BN_MP_GET_L_C
#   define BN_MP_GET_LL_C
#   define BN_MP_GET_MAG_U32_C
#   define BN_MP_GET_MAG_U64_C
#   define BN_MP_GET_MAG_UL_C
#   define BN_MP_GET_MAG_ULL_C
#   define BN_MP_GROW_C
#   define BN_MP_INCR_C
#   define BN_MP_INIT_C
#   define BN_MP_INIT_COPY_C
#   define BN_MP_INIT_I32_C
#   define BN_MP_INIT_I64_C
#   define BN_MP_INIT_L_C
#   define BN_MP_INIT_LL_C
#   define BN_MP_INIT_MULTI_C
#   define BN_MP_INIT_SET_C
#   define BN_MP_INIT_SIZE_C
#   define BN_MP_INIT_U32_C
#   define BN_MP_INIT_U64_C
#   define BN_MP_INIT_UL_C
#   define BN_MP_INIT_ULL_C
#   define BN_MP_INVMOD_C
#   define BN_MP_IS_SQUARE_C
#   define BN_MP_ISEVEN_C
#   define BN_MP_ISODD_C
#   define BN_MP_KRONECKER_C
#   define BN_MP_LCM_C
#   define BN_MP_LOG_U32_C
#   define BN_MP_LOG_N_C
#   define BN_MP_LSHD_C
#   define BN_MP_MOD_C
#   define BN_MP_MOD_2D_C
#   define BN_MP_MOD_D_C
#   define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
#   define BN_MP_MONTGOMERY_REDUCE_C
#   define BN_MP_MONTGOMERY_SETUP_C
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
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







-
+







-



-



















+







+
+
+







#   define BN_MP_REDUCE_2K_C
#   define BN_MP_REDUCE_2K_L_C
#   define BN_MP_REDUCE_2K_SETUP_C
#   define BN_MP_REDUCE_2K_SETUP_L_C
#   define BN_MP_REDUCE_IS_2K_C
#   define BN_MP_REDUCE_IS_2K_L_C
#   define BN_MP_REDUCE_SETUP_C
#   define BN_MP_ROOT_U32_C
#   define BN_MP_ROOT_N_C
#   define BN_MP_RSHD_C
#   define BN_MP_SBIN_SIZE_C
#   define BN_MP_SET_C
#   define BN_MP_SET_DOUBLE_C
#   define BN_MP_SET_I32_C
#   define BN_MP_SET_I64_C
#   define BN_MP_SET_L_C
#   define BN_MP_SET_LL_C
#   define BN_MP_SET_U32_C
#   define BN_MP_SET_U64_C
#   define BN_MP_SET_UL_C
#   define BN_MP_SET_ULL_C
#   define BN_MP_SHRINK_C
#   define BN_MP_SIGNED_RSH_C
#   define BN_MP_SQR_C
#   define BN_MP_SQRMOD_C
#   define BN_MP_SQRT_C
#   define BN_MP_SQRTMOD_PRIME_C
#   define BN_MP_SUB_C
#   define BN_MP_SUB_D_C
#   define BN_MP_SUBMOD_C
#   define BN_MP_TO_RADIX_C
#   define BN_MP_TO_SBIN_C
#   define BN_MP_TO_UBIN_C
#   define BN_MP_UBIN_SIZE_C
#   define BN_MP_UNPACK_C
#   define BN_MP_XOR_C
#   define BN_MP_ZERO_C
#   define BN_PRIME_TAB_C
#   define BN_S_MP_ADD_C
#   define BN_S_MP_BALANCE_MUL_C
#   define BN_S_MP_DIV_3_C
#   define BN_S_MP_EXPTMOD_C
#   define BN_S_MP_EXPTMOD_FAST_C
#   define BN_S_MP_GET_BIT_C
#   define BN_S_MP_INVMOD_FAST_C
#   define BN_S_MP_INVMOD_SLOW_C
#   define BN_S_MP_KARATSUBA_MUL_C
#   define BN_S_MP_KARATSUBA_SQR_C
#   define BN_S_MP_LOG_C
#   define BN_S_MP_LOG_2EXPT_C
#   define BN_S_MP_LOG_D_C
#   define BN_S_MP_MONTGOMERY_REDUCE_FAST_C
#   define BN_S_MP_MUL_DIGS_C
#   define BN_S_MP_MUL_DIGS_FAST_C
#   define BN_S_MP_MUL_HIGH_DIGS_C
#   define BN_S_MP_MUL_HIGH_DIGS_FAST_C
#   define BN_S_MP_PRIME_IS_DIVISIBLE_C
#   define BN_S_MP_RAND_JENKINS_C
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
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







+




+





+



+



+


+





+
+









+



+




+







#   define BN_FAST_MP_MONTGOMERY_REDUCE_C
#   define BN_FAST_S_MP_MUL_DIGS_C
#   define BN_FAST_S_MP_MUL_HIGH_DIGS_C
#   define BN_FAST_S_MP_SQR_C
#   define BN_MP_AND_C
#   define BN_MP_BALANCE_MUL_C
#   define BN_MP_CMP_D_C
#   define BN_MP_DIV_3_C
#   define BN_MP_EXPORT_C
#   define BN_MP_EXPTMOD_FAST_C
#   define BN_MP_EXPT_D_C
#   define BN_MP_EXPT_D_EX_C
#   define BN_MP_EXPT_N_C
#   define BN_MP_EXPT_U32_C
#   define BN_MP_FROM_SBIN_C
#   define BN_MP_FROM_UBIN_C
#   define BN_MP_GET_BIT_C
#   define BN_MP_GET_INT_C
#   define BN_MP_GET_LL_C
#   define BN_MP_GET_LONG_C
#   define BN_MP_GET_LONG_LONG_C
#   define BN_MP_GET_MAG_U32_C
#   define BN_MP_GET_MAG_U64_C
#   define BN_MP_GET_MAG_ULL_C
#   define BN_MP_GET_MAG_UL_C
#   define BN_MP_IMPORT_C
#   define BN_MP_INIT_LL_C
#   define BN_MP_INIT_SET_INT_C
#   define BN_MP_INIT_U32_C
#   define BN_MP_INIT_ULL_C
#   define BN_MP_INVMOD_SLOW_C
#   define BN_MP_JACOBI_C
#   define BN_MP_KARATSUBA_MUL_C
#   define BN_MP_KARATSUBA_SQR_C
#   define BN_MP_KRONECKER_C
#   define BN_MP_LOG_N_C
#   define BN_MP_LOG_U32_C
#   define BN_MP_N_ROOT_C
#   define BN_MP_N_ROOT_EX_C
#   define BN_MP_OR_C
#   define BN_MP_PACK_C
#   define BN_MP_PRIME_IS_DIVISIBLE_C
#   define BN_MP_PRIME_RANDOM_EX_C
#   define BN_MP_RAND_DIGIT_C
#   define BN_MP_READ_SIGNED_BIN_C
#   define BN_MP_READ_UNSIGNED_BIN_C
#   define BN_MP_ROOT_N_C
#   define BN_MP_ROOT_U32_C
#   define BN_MP_SBIN_SIZE_C
#   define BN_MP_SET_INT_C
#   define BN_MP_SET_LL_C
#   define BN_MP_SET_LONG_C
#   define BN_MP_SET_LONG_LONG_C
#   define BN_MP_SET_U32_C
#   define BN_MP_SET_U64_C
#   define BN_MP_SET_ULL_C
#   define BN_MP_SIGNED_BIN_SIZE_C
#   define BN_MP_SIGNED_RSH_C
#   define BN_MP_TC_AND_C
#   define BN_MP_TC_DIV_2D_C
#   define BN_MP_TC_OR_C
#   define BN_MP_TC_XOR_C
#   define BN_MP_TOOM_MUL_C
238
239
240
241
242
243
244

245
246
247
248
249
250
251
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260







+







#   define BN_MP_TO_UNSIGNED_BIN_C
#   define BN_MP_TO_UNSIGNED_BIN_N_C
#   define BN_MP_UBIN_SIZE_C
#   define BN_MP_UNPACK_C
#   define BN_MP_UNSIGNED_BIN_SIZE_C
#   define BN_MP_XOR_C
#   define BN_S_MP_BALANCE_MUL_C
#   define BN_S_MP_DIV_3_C
#   define BN_S_MP_EXPTMOD_FAST_C
#   define BN_S_MP_GET_BIT_C
#   define BN_S_MP_INVMOD_FAST_C
#   define BN_S_MP_INVMOD_SLOW_C
#   define BN_S_MP_KARATSUBA_MUL_C
#   define BN_S_MP_KARATSUBA_SQR_C
#   define BN_S_MP_MONTGOMERY_REDUCE_FAST_C
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
374
375
376
377
378
379
380







381
382
383
384
385



386
387
388
389
390
391
392
393
394
395







-
-
-
-
-
-
-





-
-
-
+
+
+







#   define BN_MP_CLAMP_C
#   define BN_MP_COPY_C
#   define BN_MP_MOD_2D_C
#   define BN_MP_RSHD_C
#   define BN_MP_ZERO_C
#endif

#if defined(BN_MP_DIV_3_C)
#   define BN_MP_CLAMP_C
#   define BN_MP_CLEAR_C
#   define BN_MP_EXCH_C
#   define BN_MP_INIT_SIZE_C
#endif

#if defined(BN_MP_DIV_D_C)
#   define BN_MP_CLAMP_C
#   define BN_MP_CLEAR_C
#   define BN_MP_COPY_C
#   define BN_MP_DIV_2D_C
#   define BN_MP_DIV_3_C
#   define BN_MP_EXCH_C
#   define BN_MP_INIT_SIZE_C
#   define BN_MP_EXCH_C
#   define BN_MP_INIT_SIZE_C
#   define BN_S_MP_DIV_3_C
#endif

#if defined(BN_MP_DR_IS_MODULUS_C)
#endif

#if defined(BN_MP_DR_REDUCE_C)
#   define BN_MP_CLAMP_C
401
402
403
404
405
406
407
408

409
410
411
412
413
414
415
403
404
405
406
407
408
409

410
411
412
413
414
415
416
417







-
+








#if defined(BN_MP_ERROR_TO_STRING_C)
#endif

#if defined(BN_MP_EXCH_C)
#endif

#if defined(BN_MP_EXPT_U32_C)
#if defined(BN_MP_EXPT_N_C)
#   define BN_MP_CLEAR_C
#   define BN_MP_INIT_COPY_C
#   define BN_MP_MUL_C
#   define BN_MP_SET_C
#   define BN_MP_SQR_C
#endif

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
484
485
486
487
488
489
490




491
492
493
494
495
496
497
498
499



500
501
502
503
504
505
506







-
-
-
-









-
-
-







#   define BN_MP_GET_MAG_U64_C
#endif

#if defined(BN_MP_GET_L_C)
#   define BN_MP_GET_MAG_UL_C
#endif

#if defined(BN_MP_GET_LL_C)
#   define BN_MP_GET_MAG_ULL_C
#endif

#if defined(BN_MP_GET_MAG_U32_C)
#endif

#if defined(BN_MP_GET_MAG_U64_C)
#endif

#if defined(BN_MP_GET_MAG_UL_C)
#endif

#if defined(BN_MP_GET_MAG_ULL_C)
#endif

#if defined(BN_MP_GROW_C)
#endif

#if defined(BN_MP_INCR_C)
#   define BN_MP_ADD_D_C
#   define BN_MP_DECR_C
#   define BN_MP_SET_C
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
526
527
528
529
530
531
532





533
534
535
536
537
538
539







-
-
-
-
-







#endif

#if defined(BN_MP_INIT_L_C)
#   define BN_MP_INIT_C
#   define BN_MP_SET_L_C
#endif

#if defined(BN_MP_INIT_LL_C)
#   define BN_MP_INIT_C
#   define BN_MP_SET_LL_C
#endif

#if defined(BN_MP_INIT_MULTI_C)
#   define BN_MP_CLEAR_C
#   define BN_MP_INIT_C
#endif

#if defined(BN_MP_INIT_SET_C)
#   define BN_MP_INIT_C
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
554
555
556
557
558
559
560





561
562
563
564
565
566
567







-
-
-
-
-







#endif

#if defined(BN_MP_INIT_UL_C)
#   define BN_MP_INIT_C
#   define BN_MP_SET_UL_C
#endif

#if defined(BN_MP_INIT_ULL_C)
#   define BN_MP_INIT_C
#   define BN_MP_SET_ULL_C
#endif

#if defined(BN_MP_INVMOD_C)
#   define BN_MP_CMP_D_C
#   define BN_S_MP_INVMOD_FAST_C
#   define BN_S_MP_INVMOD_SLOW_C
#endif

#if defined(BN_MP_IS_SQUARE_C)
612
613
614
615
616
617
618
619

620
621

622
623

624
625

626
627
628
629
630
631
632
633
634
635
636
637
597
598
599
600
601
602
603

604


605


606


607





608
609
610
611
612
613
614







-
+
-
-
+
-
-
+
-
-
+
-
-
-
-
-







#   define BN_MP_CMP_MAG_C
#   define BN_MP_DIV_C
#   define BN_MP_GCD_C
#   define BN_MP_INIT_MULTI_C
#   define BN_MP_MUL_C
#endif

#if defined(BN_MP_LOG_U32_C)
#if defined(BN_MP_LOG_N_C)
#   define BN_MP_CLEAR_MULTI_C
#   define BN_MP_CMP_C
#   define BN_S_MP_LOG_2EXPT_C
#   define BN_MP_CMP_D_C
#   define BN_MP_COPY_C
#   define BN_S_MP_LOG_C
#   define BN_MP_COUNT_BITS_C
#   define BN_MP_EXCH_C
#   define BN_S_MP_LOG_D_C
#   define BN_MP_EXPT_U32_C
#   define BN_MP_INIT_MULTI_C
#   define BN_MP_MUL_C
#   define BN_MP_SET_C
#   define BN_MP_SQR_C
#endif

#if defined(BN_MP_LSHD_C)
#   define BN_MP_GROW_C
#endif

#if defined(BN_MP_MOD_C)
925
926
927
928
929
930
931
932

933
934
935
936
937
938
939
940
941

942
943
944
945
946
947
948
902
903
904
905
906
907
908

909
910
911
912
913
914
915
916
917

918
919
920
921
922
923
924
925







-
+








-
+







#endif

#if defined(BN_MP_REDUCE_SETUP_C)
#   define BN_MP_2EXPT_C
#   define BN_MP_DIV_C
#endif

#if defined(BN_MP_ROOT_U32_C)
#if defined(BN_MP_ROOT_N_C)
#   define BN_MP_2EXPT_C
#   define BN_MP_ADD_D_C
#   define BN_MP_CLEAR_MULTI_C
#   define BN_MP_CMP_C
#   define BN_MP_COPY_C
#   define BN_MP_COUNT_BITS_C
#   define BN_MP_DIV_C
#   define BN_MP_EXCH_C
#   define BN_MP_EXPT_U32_C
#   define BN_MP_EXPT_N_C
#   define BN_MP_INIT_MULTI_C
#   define BN_MP_MUL_C
#   define BN_MP_MUL_D_C
#   define BN_MP_SET_C
#   define BN_MP_SUB_C
#   define BN_MP_SUB_D_C
#endif
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
949
950
951
952
953
954
955




956
957
958
959
960
961
962
963
964



965
966
967
968
969
970
971







-
-
-
-









-
-
-







#   define BN_MP_SET_U64_C
#endif

#if defined(BN_MP_SET_L_C)
#   define BN_MP_SET_UL_C
#endif

#if defined(BN_MP_SET_LL_C)
#   define BN_MP_SET_ULL_C
#endif

#if defined(BN_MP_SET_U32_C)
#endif

#if defined(BN_MP_SET_U64_C)
#endif

#if defined(BN_MP_SET_UL_C)
#endif

#if defined(BN_MP_SET_ULL_C)
#endif

#if defined(BN_MP_SHRINK_C)
#endif

#if defined(BN_MP_SIGNED_RSH_C)
#   define BN_MP_ADD_D_C
#   define BN_MP_DIV_2D_C
#   define BN_MP_SUB_D_C
1116
1117
1118
1119
1120
1121
1122







1123
1124
1125
1126
1127
1128
1129
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106







+
+
+
+
+
+
+







#   define BN_MP_CLEAR_MULTI_C
#   define BN_MP_EXCH_C
#   define BN_MP_INIT_MULTI_C
#   define BN_MP_INIT_SIZE_C
#   define BN_MP_LSHD_C
#   define BN_MP_MUL_C
#endif

#if defined(BN_S_MP_DIV_3_C)
#   define BN_MP_CLAMP_C
#   define BN_MP_CLEAR_C
#   define BN_MP_EXCH_C
#   define BN_MP_INIT_SIZE_C
#endif

#if defined(BN_S_MP_EXPTMOD_C)
#   define BN_MP_CLEAR_C
#   define BN_MP_COPY_C
#   define BN_MP_COUNT_BITS_C
#   define BN_MP_EXCH_C
#   define BN_MP_INIT_C
1208
1209
1210
1211
1212
1213
1214




















1215
1216
1217
1218
1219
1220
1221
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







#   define BN_MP_CLEAR_C
#   define BN_MP_INIT_SIZE_C
#   define BN_MP_LSHD_C
#   define BN_MP_SQR_C
#   define BN_S_MP_ADD_C
#   define BN_S_MP_SUB_C
#endif

#if defined(BN_S_MP_LOG_C)
#   define BN_MP_CLEAR_MULTI_C
#   define BN_MP_CMP_C
#   define BN_MP_CMP_D_C
#   define BN_MP_COPY_C
#   define BN_MP_EXCH_C
#   define BN_MP_EXPT_N_C
#   define BN_MP_INIT_MULTI_C
#   define BN_MP_MUL_C
#   define BN_MP_SET_C
#   define BN_MP_SQR_C
#endif

#if defined(BN_S_MP_LOG_2EXPT_C)
#   define BN_MP_COUNT_BITS_C
#endif

#if defined(BN_S_MP_LOG_D_C)
#endif

#if defined(BN_S_MP_MONTGOMERY_REDUCE_FAST_C)
#   define BN_MP_CLAMP_C
#   define BN_MP_CMP_MAG_C
#   define BN_MP_GROW_C
#   define BN_S_MP_SUB_C
#endif
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292

1293
1294
1295
1296
1297
1298
1299
1276
1277
1278
1279
1280
1281
1282

1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296







-






+








#if defined(BN_S_MP_TOOM_MUL_C)
#   define BN_MP_ADD_C
#   define BN_MP_CLAMP_C
#   define BN_MP_CLEAR_C
#   define BN_MP_CLEAR_MULTI_C
#   define BN_MP_DIV_2_C
#   define BN_MP_DIV_3_C
#   define BN_MP_INIT_MULTI_C
#   define BN_MP_INIT_SIZE_C
#   define BN_MP_LSHD_C
#   define BN_MP_MUL_2_C
#   define BN_MP_MUL_C
#   define BN_MP_SUB_C
#   define BN_S_MP_DIV_3_C
#endif

#if defined(BN_S_MP_TOOM_SQR_C)
#   define BN_MP_ADD_C
#   define BN_MP_CLAMP_C
#   define BN_MP_CLEAR_C
#   define BN_MP_DIV_2_C

Changes to libtommath/tommath_private.h.

1
2
3
4
5
6
7
8
9



10
11

12
13
14
15
16
17
18
19
20
21
1
2
3
4
5
6



7
8
9
10

11
12


13
14
15
16
17
18
19






-
-
-
+
+
+

-
+

-
-







/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */

#ifndef TOMMATH_PRIV_H_
#define TOMMATH_PRIV_H_

#ifdef MP_NO_STDINT
#ifdef HAVE_STDINT_H
#  include <stdint.h>
#include <stdint.h>
#ifndef TCL_WITH_EXTERNAL_TOMMATH
# include "tclTomMath.h"
#else
#  include "../compat/stdint.h"
# include "tommath.h"
#endif
#endif
#include "tclTomMath.h"
#include "tommath_class.h"

/*
 * Private symbols
 * ---------------
 *
 * On Unix symbols can be marked as hidden if libtommath is compiled
161
162
163
164
165
166
167


168
169
170
171
172
173
174
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174







+
+







#undef mp_word
typedef private_mp_word mp_word;
#endif

#define MP_MIN(x, y) (((x) < (y)) ? (x) : (y))
#define MP_MAX(x, y) (((x) > (y)) ? (x) : (y))

#define MP_IS_2EXPT(x) (((x) != 0u) && (((x) & ((x) - 1u)) == 0u))

/* Static assertion */
#define MP_STATIC_ASSERT(msg, cond) typedef char mp_static_assert_##msg[(cond) ? 1 : -1];

/* ---> Basic Manipulations <--- */
#define MP_IS_ZERO(a) ((a)->used == 0)
#define MP_IS_EVEN(a) (((a)->used == 0) || (((a)->dp[0] & 1u) == 0u))
#define MP_IS_ODD(a)  (((a)->used > 0) && (((a)->dp[0] & 1u) == 1u))
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
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







+
+


+
















+







MP_STATIC_ASSERT(prec_geq_min_prec, MP_PREC >= MP_MIN_PREC)

/* random number source */
extern MP_PRIVATE mp_err(*s_mp_rand_source)(void *out, size_t size);

/* lowlevel functions, do not call! */
MP_PRIVATE mp_bool s_mp_get_bit(const mp_int *a, unsigned int b);
MP_PRIVATE int s_mp_log_2expt(const mp_int *a, mp_digit base) MP_WUR;
MP_PRIVATE int s_mp_log_d(mp_digit base, mp_digit n) MP_WUR;
MP_PRIVATE mp_err s_mp_add(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR;
MP_PRIVATE mp_err s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR;
MP_PRIVATE mp_err s_mp_div_3(const mp_int *a, mp_int *c, mp_digit *d) MP_WUR;
MP_PRIVATE mp_err s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR;
MP_PRIVATE mp_err s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR;
MP_PRIVATE mp_err s_mp_mul_high_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR;
MP_PRIVATE mp_err s_mp_mul_high_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR;
MP_PRIVATE mp_err s_mp_sqr_fast(const mp_int *a, mp_int *b) MP_WUR;
MP_PRIVATE mp_err s_mp_sqr(const mp_int *a, mp_int *b) MP_WUR;
MP_PRIVATE mp_err s_mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR;
MP_PRIVATE mp_err s_mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR;
MP_PRIVATE mp_err s_mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR;
MP_PRIVATE mp_err s_mp_karatsuba_sqr(const mp_int *a, mp_int *b) MP_WUR;
MP_PRIVATE mp_err s_mp_toom_sqr(const mp_int *a, mp_int *b) MP_WUR;
MP_PRIVATE mp_err s_mp_invmod_fast(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR;
MP_PRIVATE mp_err s_mp_invmod_slow(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR;
MP_PRIVATE mp_err s_mp_montgomery_reduce_fast(mp_int *x, const mp_int *n, mp_digit rho) MP_WUR;
MP_PRIVATE mp_err s_mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) MP_WUR;
MP_PRIVATE mp_err s_mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) MP_WUR;
MP_PRIVATE mp_err s_mp_log(const mp_int *a, mp_digit base, int *c) MP_WUR;
MP_PRIVATE mp_err s_mp_rand_platform(void *p, size_t n) MP_WUR;
MP_PRIVATE mp_err s_mp_prime_random_ex(mp_int *a, int t, int size, int flags, private_mp_prime_callback cb, void *dat);
MP_PRIVATE void s_mp_reverse(unsigned char *s, size_t len);
MP_PRIVATE mp_err s_mp_prime_is_divisible(const mp_int *a, mp_bool *result);

/* TODO: jenkins prng is not thread safe as of now */
MP_PRIVATE mp_err s_mp_rand_jenkins(void *p, size_t n) MP_WUR;

Changes to libtommath/win32/libtommath.dll.

cannot compute difference between binary files

Changes to libtommath/win32/tommath.lib.

cannot compute difference between binary files

Added libtommath/win64-arm/libtommath.dll.

cannot compute difference between binary files

Added libtommath/win64-arm/libtommath.dll.a.

cannot compute difference between binary files

Added libtommath/win64-arm/tommath.lib.

cannot compute difference between binary files

Changes to libtommath/win64/libtommath.dll.

cannot compute difference between binary files

Changes to libtommath/win64/libtommath.dll.a.

cannot compute difference between binary files

Changes to libtommath/win64/tommath.lib.

cannot compute difference between binary files

Changes to macosx/GNUmakefile.

1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







########################################################################################################
#
# Makefile wrapper to build tcl on Mac OS X in a way compatible with the tk/macosx Xcode buildsystem
#	uses the standard unix build system in tcl/unix (which can be used directly instead of this
#	uses the standard Unix build system in tcl/unix (which can be used directly instead of this
#	if you are not using the tk/macosx projects).
#
# Copyright (c) 2002-2008 Daniel A. Steffen <das@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
########################################################################################################
84
85
86
87
88
89
90
91

92
93
94
95
96
97
98
84
85
86
87
88
89
90

91
92
93
94
95
96
97
98







-
+







OBJ_DIR			= ${OBJROOT}/${BUILD_STYLE}

empty			:=
space			:= ${empty} ${empty}
objdir			= $(subst ${space},\ ,${OBJ_DIR})

develop_make_args	:= BUILD_STYLE=Development CONFIGURE_ARGS=--enable-symbols
deploy_make_args	:= BUILD_STYLE=Deployment INSTALL_TARGET=install \
deploy_make_args	:= BUILD_STYLE=Deployment INSTALL_TARGET=install-strip \
			   EXTRA_CFLAGS=-DNDEBUG
embedded_make_args	:= EMBEDDED_BUILD=1
install_make_args	:= INSTALL_BUILD=1

${targets}:
	${MAKE} ${action}${PROJECT} \
	$(foreach s,${styles} embedded install,$(if $(findstring $s,$@),${${s}_make_args}))
140
141
142
143
144
145
146
147

148
149
150
151
152
153

154
155
156
157
158
159
160
140
141
142
143
144
145
146

147
148
149
150
151
152

153
154
155
156
157
158
159
160







-
+





-
+







	${MAKE} install-${PROJECT} INSTALL_ROOT="${OBJ_DIR}/"

${objdir}/Makefile: ${UNIX_DIR}/Makefile.in ${UNIX_DIR}/configure \
		     ${UNIX_DIR}/tclConfig.sh.in Tcl-Info.plist.in
	mkdir -p "${OBJ_DIR}" && cd "${OBJ_DIR}" && \
	if [ ${UNIX_DIR}/configure -nt config.status ]; then ${UNIX_DIR}/configure -C \
	--prefix="${PREFIX}" --bindir="${BINDIR}" --libdir="${LIBDIR}" \
	--mandir="${MANDIR}" --enable-framework --enable-dtrace \
	--mandir="${MANDIR}" --enable-framework --enable-dtrace --disable-zipfs \
	${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS}; else ./config.status; fi

build-${PROJECT}: ${objdir}/Makefile
	${DO_MAKE}
ifeq (${INSTALL_BUILD},)
# symolic link hackery to trick
# symbolic link hackery to trick
# 'make install INSTALL_ROOT=${OBJ_DIR}'
# into building Tcl.framework and tclsh in ${SYMROOT}
	@cd "${OBJ_DIR}" && mkdir -p $(dir $(subst ${space},\ ,.${LIBDIR})) $(dir $(subst ${space},\ ,.${BINDIR})) "${SYMROOT}" && \
	rm -f ".${LIBDIR}" ".${BINDIR}" && ln -fs "${SYMROOT}" ".${LIBDIR}" && \
	ln -fs "${SYMROOT}" ".${BINDIR}" && ln -fs "${OBJ_DIR}/tcltest" "${SYMROOT}"
endif

Changes to macosx/README.

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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
+
-
-
+
-

-
+
-












-
-

-
-
+
+







(see below for details), but can also be built with the standard unix configure
and make buildsystem in tcl/unix as on any other unix platform (indeed, the
GNUmakefile is just a wrapper around the unix buildsystem).
The Mac OS X specific configure flags are --enable-framework and
--disable-corefoundation (which disables CF and notably reverts to the standard
select based notifier).

- It is also possible to build with the Xcode IDE via the projects in
tcl/macosx, take care to use the project matching your DevTools and OS version:
	Tcl.xcode: 		    for Xcode 3.1 on 10.5
	Tcl.xcodeproj:		    for Xcode 3.2 on 10.6
These have the following targets:
	Tcl:			    calls through to tcl/macosx/GNUMakefile.
	tcltest:		    static build of tcltest for debugging.
	tests:			    build tcltest target and run tcl testsuite.
The following build configurations are available:
	Debug:			    debug build for the active architecture,
				    with Fix & Continue enabled.
	Debug clang:		    use clang compiler.
	Debug llvm-gcc:		    use llvm-gcc compiler.
	Debug gcc40:		    use gcc 4.0 compiler.
	DebugNoFixAndContinue:      disable Fix & Continue.
	DebugUnthreaded:	    disable threading.
	DebugNoCF:		    disable corefoundation.
	DebugNoCFUnthreaded:	    disable corefoundation an threading.
	DebugMemCompile:	    enable memory and bytecode debugging.
	DebugLeaks:		    define PURIFY.
	DebugGCov:		    enable generation of gcov data files.
	Debug64bit:		    configure with --enable-64bit (requires
				    building on a 64bit capable processor).
	Release:		    release build for the active architecture.
	ReleaseUniversal:	    32/64-bit universal build.
	ReleaseUniversal clang:	    use clang compiler.
	ReleaseUniversal llvm-gcc:  use llvm-gcc compiler.
	ReleaseUniversal gcc40:	    use gcc 4.0 compiler.
	ReleaseUniversal10.5SDK:    build against the 10.5 SDK (with 10.5
				    deployment target).
	Note that the non-SDK configurations have their deployment target set to
	10.5 (Tcl.xcode) resp. 10.6 (Tcl.xcodeproj).
The Xcode projects refer to the toplevel tcl source directory via the
TCL_SRCROOT user build setting, by default this is set to the project-relative
path '../../tcl', if your tcl source directory is named differently, e.g.
'../../tcl9.0', you need to manually change the TCL_SRCROOT setting by editing
your ${USER}.pbxuser file (located inside the Tcl.xcodeproj bundle directory)
with a text editor.

- To build universal binaries outside of the Xcode IDE, set CFLAGS as follows:
	export CFLAGS="-arch i386 -arch x86_64 -arch ppc"
	export CFLAGS="-arch x86_64 -arch arm64"
This requires Mac OS X 10.4 and Xcode 2.4 (or Xcode 2.2 if -arch x86_64 is
omitted, but _not_ Xcode 2.1) and will work on any architecture (on PowerPC
This requires Mac OS X 10.6 and Xcode 10.2 and will work on any architecture.
Tiger you need to add "-isysroot /Developer/SDKs/MacOSX10.4u.sdk").
Note that configure requires CFLAGS to contain a least one architecture that can
be run on the build machine (i.e. ppc on G3/G4, ppc or ppc64 on G5, ppc or i386
be run on the build machine (i.e. x86_64 on Core2/Xeon).
on Core and ppc, i386 or x86_64 on Core2/Xeon).
Universal builds of Tcl TEA extensions are also possible with CFLAGS set as
above, they will be [load]able by universal as well as thin binaries of Tcl.

Detailed Instructions for building with macosx/GNUmakefile
----------------------------------------------------------

- Unpack the Tcl source release archive.

- The following instructions assume the Tcl source tree is named "tcl${ver}",
(where ${ver} is a shell variable containing the Tcl version number e.g. '9.0').
Setup this shell variable as follows:
	ver="9.0"
If you are building from CVS, omit this step (CVS source tree names usually do
not contain a version number).

- Setup environment variables as desired, e.g. for a universal build on 10.5:
	CFLAGS="-arch i386 -arch x86_64 -arch ppc -mmacosx-version-min=10.5"
- Setup environment variables as desired, e.g. for a universal build on 10.9:
	CFLAGS="-arch x86_64 -arch arm64 -mmacosx-version-min=10.9"
	export CFLAGS

- Change to the directory containing the Tcl source tree and build:
	make -C tcl${ver}/macosx

- Install Tcl onto the root volume (admin password required):
	sudo make -C tcl${ver}/macosx install

Deleted macosx/Tcl-Common.xcconfig.

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
30
31
32
33
34
35
36
37





































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
//
// Tcl-Common.xcconfig --
//
//	This file contains the Xcode build settings comon to all
//	project configurations in Tcl.xcodeproj.
//
// Copyright (c) 2007-2008 Daniel A. Steffen <das@users.sourceforge.net>
//
// See the file "license.terms" for information on usage and redistribution
// of this file, and for a DISCLAIMER OF ALL WARRANTIES.

HEADER_SEARCH_PATHS = "$(DERIVED_FILE_DIR)/tcl" $(HEADER_SEARCH_PATHS)
OTHER_LDFLAGS = -headerpad_max_install_names -sectcreate __TEXT __info_plist "$(DERIVED_FILE_DIR)/tcl/Tclsh-Info.plist" $(OTHER_LDFLAGS)
INSTALL_PATH = $(BINDIR)
INSTALL_MODE_FLAG = go-w,a+rX
GCC_PREFIX_HEADER = $(DERIVED_FILE_DIR)/tcl/tclConfig.h
GCC_GENERATE_DEBUGGING_SYMBOLS = YES
GCC_NO_COMMON_BLOCKS = YES
GCC_DYNAMIC_NO_PIC = YES
GCC_VERSION = 4.2
GCC = gcc-$(GCC_VERSION)
WARNING_CFLAGS = -Wall -Wextra -Wshadow -Wwrite-strings -Wpointer-arith -Wc++-compat -Wdeclaration-after-statement -Winit-self -Wcast-align -Wdisabled-optimization -Winline $(WARNING_CFLAGS)
BINDIR = $(PREFIX)/bin
CFLAGS = $(CFLAGS)
CPPFLAGS = -mmacosx-version-min=$(MACOSX_DEPLOYMENT_TARGET) $(CPPFLAGS)
FRAMEWORK_INSTALL_PATH = /Library/Frameworks
INCLUDEDIR = $(PREFIX)/include
LIBDIR = $(PREFIX)/lib
MANDIR = $(PREFIX)/man
PER_ARCH_CFLAGS_ppc = -mcpu=G3 -mtune=G4 $(PER_ARCH_CFLAGS_ppc)
PER_ARCH_CFLAGS_ppc64 = -mcpu=G5 -mpowerpc64 $(PER_ARCH_CFLAGS_ppc64)
PREFIX = /usr/local
TCL_CONFIGURE_ARGS = --enable-dtrace
TCL_LIBRARY = $(LIBDIR)/tcl$(VERSION)
TCL_PACKAGE_PATH = "$(LIBDIR)"
TCL_DEFS = HAVE_TCL_CONFIG_H
VERSION = 9.0

Deleted macosx/Tcl-Debug.xcconfig.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20




















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
//
// Tcl-Debug.xcconfig --
//
//	This file contains the Xcode build settings for all Debug
//	project configurations in Tcl.xcodeproj.
//
// Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
//
// See the file "license.terms" for information on usage and redistribution
// of this file, and for a DISCLAIMER OF ALL WARRANTIES.

#include "Tcl-Common.xcconfig"

DEBUG_INFORMATION_FORMAT = dwarf
DEAD_CODE_STRIPPING = NO
DEPLOYMENT_POSTPROCESSING = NO
GCC_OPTIMIZATION_LEVEL = 0
GCC_PREPROCESSOR_DEFINITIONS = $(TCL_DEFS) $(GCC_PREPROCESSOR_DEFINITIONS)
CONFIGURE_ARGS = --enable-symbols $(TCL_CONFIGURE_ARGS) $(CONFIGURE_ARGS)
MAKE_TARGET = develop

Deleted macosx/Tcl-Release.xcconfig.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20




















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
//
// Tcl-Release.xcconfig --
//
//	This file contains the Xcode build settings for all Release
//	project configurations in Tcl.xcodeproj.
//
// Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
//
// See the file "license.terms" for information on usage and redistribution
// of this file, and for a DISCLAIMER OF ALL WARRANTIES.

#include "Tcl-Common.xcconfig"

DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
DEAD_CODE_STRIPPING = YES
DEPLOYMENT_POSTPROCESSING = YES
GCC_OPTIMIZATION_LEVEL = s
GCC_PREPROCESSOR_DEFINITIONS = NDEBUG $(TCL_DEFS) $(GCC_PREPROCESSOR_DEFINITIONS)
CONFIGURE_ARGS = --disable-symbols $(TCL_CONFIGURE_ARGS) $(CONFIGURE_ARGS)
MAKE_TARGET = deploy

Deleted macosx/Tcl.xcode/default.pbxuser.

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
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








































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
// !$*UTF8*$!
{
	08FB7793FE84155DC02AAC07 /* Project object */ = {
		activeBuildConfigurationName = Debug;
		activeExecutable = F9E61D1C090A4282002B3151 /* tclsh */;
		activeTarget = F9E61D16090A3E94002B3151 /* Tcl */;
		codeSenseManager = F944EB9D08F798180049FDD4 /* Code sense */;
		executables = (
			F9E61D1C090A4282002B3151 /* tclsh */,
			F944EB8F08F798100049FDD4 /* tcltest */,
		);
		perUserDictionary = {
			com.apple.ide.smrt.PBXUserSmartGroupsKey.Rev10 = <040b73747265616d747970656481e8038401408484840e4e534d757461626c654172726179008484074e534172726179008484084e534f626a65637400858401690192848484134e534d757461626c6544696374696f6e6172790084840c4e5344696374696f6e6172790095960792848484084e53537472696e67019584012b046e616d658692849a9a14496d706c656d656e746174696f6e2046696c65738692849a9a146162736f6c75746550617468546f42756e646c658692849a9a008692849a9a195042585472616e7369656e744c6f636174696f6e4174546f708692849a9a06626f74746f6d8692849a9a03636c7a8692849a9a1550425846696c656e616d65536d61727447726f75708692849a9a0b6465736372697074696f6e8692849a9a103c6e6f206465736372697074696f6e3e8692849a9a0b707265666572656e63657386928497960892849a9a07666e6d617463688692849a9a008692849a9a05696d6167658692849a9a0b536d617274466f6c6465728692849a9a04726f6f748692849a9a093c50524f4a4543543e8692849a9a0572656765788692849a9a065c2e286329248692849a9a097265637572736976658692848484084e534e756d626572008484074e5356616c7565009584012a849696018692849a9a0669734c656166869284b09db296008692849a9a0763616e536176658692af92849a9a1250425850726f6a65637453636f70654b65798692849a9a03594553868692849a9a08676c6f62616c49448692849a9a18314343304541343030343335304546393030343434313042868686>;
		};
		sourceControlManager = F944EB9C08F798180049FDD4 /* Source Control */;
		userBuildSettings = {
			SYMROOT = "${SRCROOT}/../../build/tcl";
			TCL_SRCROOT = "${SRCROOT}/../../tcl";
		};
	};
	8DD76FA90486AB0100D96B5E /* tcltest */ = {
		activeExec = 0;
		executables = (
			F944EB8F08F798100049FDD4 /* tcltest */,
		);
	};
	F944EB8F08F798100049FDD4 /* tcltest */ = {
		isa = PBXExecutable;
		activeArgIndices = (
			NO,
			NO,
			NO,
		);
		argumentStrings = (
			"${TCL_SRCROOT}/tests/all.tcl",
			"-singleproc 1",
			"-verbose \"bet\"",
		);
		autoAttachOnCrash = 1;
		breakpointsEnabled = 1;
		configStateDict = {
			"PBXLSLaunchAction-0" = {
				PBXLSLaunchAction = 0;
				PBXLSLaunchStartAction = 1;
				PBXLSLaunchStdioStyle = 2;
				PBXLSLaunchStyle = 0;
				class = PBXLSRunLaunchConfig;
				displayName = "Executable Runner";
				identifier = com.apple.Xcode.launch.runConfig;
				remoteHostInfo = "";
				startActionInfo = "";
			};
			"PBXLSLaunchAction-1" = {
				PBXLSLaunchAction = 1;
				PBXLSLaunchStartAction = 1;
				PBXLSLaunchStdioStyle = 2;
				PBXLSLaunchStyle = 0;
				class = PBXGDB_LaunchConfig;
				displayName = GDB;
				identifier = com.apple.Xcode.launch.GDBMI_Config;
				remoteHostInfo = "";
				startActionInfo = "";
			};
		};
		customDataFormattersEnabled = 1;
		debuggerPlugin = GDBDebugging;
		disassemblyDisplayState = 0;
		dylibVariantSuffix = "";
		enableDebugStr = 0;
		environmentEntries = (
			{
				active = YES;
				name = TCL_LIBRARY;
				value = "${TCL_SRCROOT}/library";
			},
			{
				active = YES;
				name = TCLLIBPATH;
				value = /Library/Tcl;
			},
			{
				active = NO;
				name = DYLD_PRINT_LIBRARIES;
			},
			{
				active = NO;
				name = MallocBadFreeAbort;
				value = 1;
			},
			{
				active = NO;
				name = MallocLogFile;
				value = /tmp/malloc.log;
			},
			{
				active = NO;
				name = MallocStackLogging;
				value = 1;
			},
			{
				active = NO;
				name = MallocStackLoggingNoCompact;
				value = 1;
			},
			{
				active = NO;
				name = MallocPreScribble;
				value = 1;
			},
			{
				active = NO;
				name = MallocScribble;
				value = 1;
			},
		);
		executableSystemSymbolLevel = 0;
		executableUserSymbolLevel = 0;
		libgmallocEnabled = 0;
		name = tcltest;
		sourceDirectories = (
		);
	};
	F944EB9C08F798180049FDD4 /* Source Control */ = {
		isa = PBXSourceControlManager;
		fallbackIsa = XCSourceControlManager;
		isSCMEnabled = 0;
		scmConfiguration = {
			CVSToolPath = /usr/bin/cvs;
			CVSUseSSH = NO;
			SubversionToolPath = /usr/bin/svn;
			repositoryNamesForRoots = {
				.. = "";
			};
		};
		scmType = scm.cvs;
	};
	F944EB9D08F798180049FDD4 /* Code sense */ = {
		isa = PBXCodeSenseManager;
		indexTemplatePath = "";
	};
	F97258A50A86873C00096C78 /* tests */ = {
		activeExec = 0;
	};
	F9E61D16090A3E94002B3151 /* Tcl */ = {
		activeExec = 0;
		executables = (
			F9E61D1C090A4282002B3151 /* tclsh */,
		);
	};
	F9E61D1C090A4282002B3151 /* tclsh */ = {
		isa = PBXExecutable;
		activeArgIndices = (
		);
		argumentStrings = (
		);
		autoAttachOnCrash = 1;
		breakpointsEnabled = 1;
		configStateDict = {
			"PBXLSLaunchAction-0" = {
				PBXLSLaunchAction = 0;
				PBXLSLaunchStartAction = 1;
				PBXLSLaunchStdioStyle = 2;
				PBXLSLaunchStyle = 0;
				class = PBXLSRunLaunchConfig;
				displayName = "Executable Runner";
				identifier = com.apple.Xcode.launch.runConfig;
				remoteHostInfo = "";
				startActionInfo = "";
			};
			"PBXLSLaunchAction-1" = {
				PBXLSLaunchAction = 1;
				PBXLSLaunchStartAction = 1;
				PBXLSLaunchStdioStyle = 2;
				PBXLSLaunchStyle = 0;
				class = PBXGDB_LaunchConfig;
				displayName = GDB;
				identifier = com.apple.Xcode.launch.GDBMI_Config;
				remoteHostInfo = "";
				startActionInfo = "";
			};
		};
		customDataFormattersEnabled = 1;
		debuggerPlugin = GDBDebugging;
		disassemblyDisplayState = 0;
		dylibVariantSuffix = _debug;
		enableDebugStr = 0;
		environmentEntries = (
			{
				active = NO;
				name = DYLD_PRINT_LIBRARIES;
			},
		);
		executableSystemSymbolLevel = 0;
		executableUserSymbolLevel = 0;
		libgmallocEnabled = 0;
		name = tclsh;
		sourceDirectories = (
		);
	};
}

Deleted macosx/Tcl.xcode/project.pbxproj.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 45;
	objects = {

/* Begin PBXBuildFile section */
		F90509300913A72400327603 /* tclAppInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445508F272B9004A47F5 /* tclAppInit.c */; settings = {COMPILER_FLAGS = "-DTCL_TEST -DTCL_BUILDTIME_LIBRARY=\\\"$(TCL_SRCROOT)/library\\\""; }; };
		F93599B30DF1F75400E04F67 /* tclOO.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B20DF1F75400E04F67 /* tclOO.c */; };
		F93599B70DF1F76100E04F67 /* tclOOBasic.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B60DF1F76100E04F67 /* tclOOBasic.c */; };
		F93599B90DF1F76600E04F67 /* tclOOCall.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B80DF1F76600E04F67 /* tclOOCall.c */; };
		F93599BC0DF1F77000E04F67 /* tclOODefineCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */; };
		F93599BE0DF1F77400E04F67 /* tclOOInfo.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599BD0DF1F77400E04F67 /* tclOOInfo.c */; };
		F93599C20DF1F78300E04F67 /* tclOOMethod.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C10DF1F78300E04F67 /* tclOOMethod.c */; };
		F93599C40DF1F78800E04F67 /* tclOOStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C30DF1F78800E04F67 /* tclOOStubInit.c */; };
		F93599C60DF1F78D00E04F67 /* tclOOStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */; };
		F95D77EA0DFD820D00A8BF6F /* tclIORTrans.c in Sources */ = {isa = PBXBuildFile; fileRef = F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */; };
		F96437CA0EF0D4B2003F468E /* tclZlib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96437C90EF0D4B2003F468E /* tclZlib.c */; };
		F96437E70EF0D652003F468E /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F96437E60EF0D652003F468E /* libz.dylib */; };
		F966C07508F2820D005CB29B /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F966C07408F2820D005CB29B /* CoreFoundation.framework */; };
		F96D456F08F272BB004A47F5 /* regcomp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED008F272A7004A47F5 /* regcomp.c */; };
		F96D457208F272BB004A47F5 /* regerror.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED308F272A7004A47F5 /* regerror.c */; };
		F96D457508F272BB004A47F5 /* regexec.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED608F272A7004A47F5 /* regexec.c */; };
		F96D457608F272BB004A47F5 /* regfree.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED708F272A7004A47F5 /* regfree.c */; };
		F96D457B08F272BB004A47F5 /* tclAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDC08F272A7004A47F5 /* tclAlloc.c */; settings = {COMPILER_FLAGS = "-DUSE_TCLALLOC=0"; }; };
		F96D457C08F272BB004A47F5 /* tclAsync.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDD08F272A7004A47F5 /* tclAsync.c */; };
		F96D457D08F272BB004A47F5 /* tclBasic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDE08F272A7004A47F5 /* tclBasic.c */; };
		F96D457E08F272BC004A47F5 /* tclBinary.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDF08F272A7004A47F5 /* tclBinary.c */; };
		F96D457F08F272BC004A47F5 /* tclCkalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE008F272A7004A47F5 /* tclCkalloc.c */; };
		F96D458008F272BC004A47F5 /* tclClock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE108F272A7004A47F5 /* tclClock.c */; };
		F96D458108F272BC004A47F5 /* tclCmdAH.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE208F272A7004A47F5 /* tclCmdAH.c */; };
		F96D458208F272BC004A47F5 /* tclCmdIL.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE308F272A7004A47F5 /* tclCmdIL.c */; };
		F96D458308F272BC004A47F5 /* tclCmdMZ.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */; };
		F96D458408F272BC004A47F5 /* tclCompCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE508F272A7004A47F5 /* tclCompCmds.c */; };
		F96D458508F272BC004A47F5 /* tclCompExpr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE608F272A7004A47F5 /* tclCompExpr.c */; };
		F96D458608F272BC004A47F5 /* tclCompile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE708F272A7004A47F5 /* tclCompile.c */; };
		F96D458808F272BC004A47F5 /* tclConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE908F272A7004A47F5 /* tclConfig.c */; };
		F96D458908F272BC004A47F5 /* tclDate.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEA08F272A7004A47F5 /* tclDate.c */; };
		F96D458B08F272BC004A47F5 /* tclDictObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEC08F272A7004A47F5 /* tclDictObj.c */; };
		F96D458C08F272BC004A47F5 /* tclEncoding.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EED08F272A7004A47F5 /* tclEncoding.c */; };
		F96D458D08F272BC004A47F5 /* tclEnv.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEE08F272A7004A47F5 /* tclEnv.c */; };
		F96D458E08F272BC004A47F5 /* tclEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEF08F272A7004A47F5 /* tclEvent.c */; };
		F96D458F08F272BC004A47F5 /* tclExecute.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF008F272A7004A47F5 /* tclExecute.c */; };
		F96D459008F272BC004A47F5 /* tclFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF108F272A7004A47F5 /* tclFCmd.c */; };
		F96D459108F272BC004A47F5 /* tclFileName.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF208F272A7004A47F5 /* tclFileName.c */; };
		F96D459308F272BC004A47F5 /* tclGet.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF408F272A7004A47F5 /* tclGet.c */; };
		F96D459508F272BC004A47F5 /* tclHash.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF608F272A7004A47F5 /* tclHash.c */; };
		F96D459608F272BC004A47F5 /* tclHistory.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF708F272A7004A47F5 /* tclHistory.c */; };
		F96D459708F272BC004A47F5 /* tclIndexObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF808F272A7004A47F5 /* tclIndexObj.c */; };
		F96D459B08F272BC004A47F5 /* tclInterp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFC08F272A7004A47F5 /* tclInterp.c */; };
		F96D459D08F272BC004A47F5 /* tclIO.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFE08F272A7004A47F5 /* tclIO.c */; };
		F96D459F08F272BC004A47F5 /* tclIOCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0008F272A7004A47F5 /* tclIOCmd.c */; };
		F96D45A008F272BC004A47F5 /* tclIOGT.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0108F272A7004A47F5 /* tclIOGT.c */; };
		F96D45A108F272BC004A47F5 /* tclIORChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0208F272A7004A47F5 /* tclIORChan.c */; };
		F96D45A208F272BC004A47F5 /* tclIOSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0308F272A7004A47F5 /* tclIOSock.c */; };
		F96D45A308F272BC004A47F5 /* tclIOUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0408F272A7004A47F5 /* tclIOUtil.c */; };
		F96D45A408F272BC004A47F5 /* tclLink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0508F272A7004A47F5 /* tclLink.c */; };
		F96D45A508F272BC004A47F5 /* tclListObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0608F272A7004A47F5 /* tclListObj.c */; };
		F96D45A608F272BC004A47F5 /* tclLiteral.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0708F272A7004A47F5 /* tclLiteral.c */; };
		F96D45A708F272BC004A47F5 /* tclLoad.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0808F272A7004A47F5 /* tclLoad.c */; };
		F96D45A908F272BC004A47F5 /* tclMain.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0A08F272A7004A47F5 /* tclMain.c */; };
		F96D45AA08F272BC004A47F5 /* tclNamesp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0B08F272A7004A47F5 /* tclNamesp.c */; };
		F96D45AB08F272BC004A47F5 /* tclNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0C08F272A7004A47F5 /* tclNotify.c */; };
		F96D45AC08F272BC004A47F5 /* tclObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0D08F272A7004A47F5 /* tclObj.c */; };
		F96D45AD08F272BC004A47F5 /* tclPanic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0E08F272A7004A47F5 /* tclPanic.c */; };
		F96D45AE08F272BC004A47F5 /* tclParse.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0F08F272A7004A47F5 /* tclParse.c */; };
		F96D45B008F272BC004A47F5 /* tclPathObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1108F272A7004A47F5 /* tclPathObj.c */; };
		F96D45B108F272BC004A47F5 /* tclPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1208F272A7004A47F5 /* tclPipe.c */; };
		F96D45B208F272BC004A47F5 /* tclPkg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1308F272A7004A47F5 /* tclPkg.c */; };
		F96D45B308F272BC004A47F5 /* tclPkgConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */; settings = {COMPILER_FLAGS = "-DCFG_INSTALL_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_INSTALL_BINDIR=\\\"$(BINDIR)\\\" -DCFG_INSTALL_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_INSTALL_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_INSTALL_DOCDIR=\\\"$(MANDIR)\\\" -DCFG_RUNTIME_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_RUNTIME_BINDIR=\\\"$(BINDIR)\\\" -DCFG_RUNTIME_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_RUNTIME_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_RUNTIME_DOCDIR=\\\"$(MANDIR)\\\""; }; };
		F96D45B608F272BC004A47F5 /* tclPosixStr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1708F272A7004A47F5 /* tclPosixStr.c */; };
		F96D45B708F272BC004A47F5 /* tclPreserve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1808F272A7004A47F5 /* tclPreserve.c */; };
		F96D45B808F272BC004A47F5 /* tclProc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1908F272A7004A47F5 /* tclProc.c */; };
		F96D45B908F272BC004A47F5 /* tclRegexp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1A08F272A7004A47F5 /* tclRegexp.c */; };
		F96D45BB08F272BC004A47F5 /* tclResolve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1C08F272A7004A47F5 /* tclResolve.c */; };
		F96D45BC08F272BC004A47F5 /* tclResult.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1D08F272A7004A47F5 /* tclResult.c */; };
		F96D45BD08F272BC004A47F5 /* tclScan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1E08F272A7004A47F5 /* tclScan.c */; };
		F96D45BE08F272BC004A47F5 /* tclStringObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1F08F272A7004A47F5 /* tclStringObj.c */; };
		F96D45C308F272BC004A47F5 /* tclStrToD.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2408F272A7004A47F5 /* tclStrToD.c */; };
		F96D45C408F272BC004A47F5 /* tclStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2508F272A7004A47F5 /* tclStubInit.c */; };
		F96D45C508F272BC004A47F5 /* tclStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2608F272A7004A47F5 /* tclStubLib.c */; };
		F96D45C608F272BC004A47F5 /* tclTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2708F272A7004A47F5 /* tclTest.c */; };
		F96D45C708F272BC004A47F5 /* tclTestObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2808F272A7004A47F5 /* tclTestObj.c */; };
		F96D45C808F272BC004A47F5 /* tclTestProcBodyObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */; };
		F96D45C908F272BC004A47F5 /* tclThread.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2A08F272A7004A47F5 /* tclThread.c */; };
		F96D45CA08F272BC004A47F5 /* tclThreadAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */; };
		F96D45CB08F272BC004A47F5 /* tclThreadJoin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */; };
		F96D45CC08F272BC004A47F5 /* tclThreadStorage.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */; };
		F96D45CD08F272BC004A47F5 /* tclThreadTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */; };
		F96D45CE08F272BC004A47F5 /* tclTimer.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2F08F272A7004A47F5 /* tclTimer.c */; };
		F96D45D008F272BC004A47F5 /* tclTomMathInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */; };
		F96D45D108F272BC004A47F5 /* tclTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3208F272A7004A47F5 /* tclTrace.c */; };
		F96D45D308F272BC004A47F5 /* tclUtf.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3408F272A7004A47F5 /* tclUtf.c */; };
		F96D45D408F272BC004A47F5 /* tclUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3508F272A7004A47F5 /* tclUtil.c */; };
		F96D45D508F272BC004A47F5 /* tclVar.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3608F272A7004A47F5 /* tclVar.c */; };
		F96D48E208F272C3004A47F5 /* bn_fast_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */; };
		F96D48E408F272C3004A47F5 /* bn_fast_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */; };
		F96D48E708F272C3004A47F5 /* bn_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426908F272B3004A47F5 /* bn_mp_add.c */; };
		F96D48E808F272C3004A47F5 /* bn_mp_add_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */; };
		F96D48EB08F272C3004A47F5 /* bn_mp_clamp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */; };
		F96D48EC08F272C3004A47F5 /* bn_mp_clear.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426E08F272B3004A47F5 /* bn_mp_clear.c */; };
		F96D48ED08F272C3004A47F5 /* bn_mp_clear_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */; };
		F96D48EE08F272C3004A47F5 /* bn_mp_cmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427008F272B3004A47F5 /* bn_mp_cmp.c */; };
		F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */; };
		F96D48F208F272C3004A47F5 /* bn_mp_cnt_lsb.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_cnt_lsb.c */; };
		F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_copy.c */; };
		F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */; };
		F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427608F272B3004A47F5 /* bn_mp_div.c */; };
		F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427708F272B3004A47F5 /* bn_mp_div_2.c */; };
		F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */; };
		F96D48F708F272C3004A47F5 /* bn_mp_div_3.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427908F272B3004A47F5 /* bn_mp_div_3.c */; };
		F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */; };
		F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427E08F272B3004A47F5 /* bn_mp_exch.c */; };
		F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428708F272B3004A47F5 /* bn_mp_grow.c */; };
		F96D490608F272C3004A47F5 /* bn_mp_init.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428808F272B3004A47F5 /* bn_mp_init.c */; };
		F96D490708F272C3004A47F5 /* bn_mp_init_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */; };
		F96D490808F272C3004A47F5 /* bn_mp_init_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */; };
		F96D490908F272C3004A47F5 /* bn_mp_init_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */; };
		F96D490B08F272C3004A47F5 /* bn_mp_init_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */; };
		F96D491008F272C3004A47F5 /* bn_mp_karatsuba_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */; };
		F96D491108F272C3004A47F5 /* bn_mp_karatsuba_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */; };
		F96D491308F272C3004A47F5 /* bn_mp_lshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429508F272B3004A47F5 /* bn_mp_lshd.c */; };
		F96D491408F272C3004A47F5 /* bn_mp_mod.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429608F272B3004A47F5 /* bn_mp_mod.c */; };
		F96D491508F272C3004A47F5 /* bn_mp_mod_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */; };
		F96D491A08F272C3004A47F5 /* bn_mp_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429C08F272B3004A47F5 /* bn_mp_mul.c */; };
		F96D491B08F272C3004A47F5 /* bn_mp_mul_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */; };
		F96D491C08F272C3004A47F5 /* bn_mp_mul_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */; };
		F96D491D08F272C3004A47F5 /* bn_mp_mul_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */; };
		F96D492908F272C3004A47F5 /* bn_mp_radix_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */; };
		F96D492A08F272C3004A47F5 /* bn_mp_radix_smap.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */; };
		F96D492C08F272C3004A47F5 /* bn_mp_read_radix.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */; };
		F96D493708F272C3004A47F5 /* bn_mp_rshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */; };
		F96D493808F272C3004A47F5 /* bn_mp_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BA08F272B3004A47F5 /* bn_mp_set.c */; };
		F96D493C08F272C3004A47F5 /* bn_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */; };
		F96D493F08F272C3004A47F5 /* bn_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C108F272B3004A47F5 /* bn_mp_sub.c */; };
		F96D494008F272C3004A47F5 /* bn_mp_sub_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */; };
		F96D494608F272C3004A47F5 /* bn_mp_toom_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */; };
		F96D494708F272C3004A47F5 /* bn_mp_toom_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */; };
		F96D494908F272C3004A47F5 /* bn_mp_to_radix.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CB08F272B3004A47F5 /* bn_mp_to_radix.c */; };
		F96D494C08F272C3004A47F5 /* bn_mp_zero.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */; };
		F96D494F08F272C3004A47F5 /* bn_s_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */; };
		F96D495108F272C3004A47F5 /* bn_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */; };
		F96D495308F272C3004A47F5 /* bn_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */; };
		F96D495408F272C3004A47F5 /* bn_s_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */; };
		F96D49A908F272C4004A47F5 /* tclMacOSXBundle.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */; };
		F96D49AD08F272C4004A47F5 /* tclMacOSXFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */; };
		F96D49AE08F272C4004A47F5 /* tclMacOSXNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */; };
		F96D4AC608F272C9004A47F5 /* tclLoadDyld.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445B08F272B9004A47F5 /* tclLoadDyld.c */; settings = {COMPILER_FLAGS = "-Wno-deprecated-declarations"; }; };
		F96D4ACA08F272C9004A47F5 /* tclUnixChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445F08F272B9004A47F5 /* tclUnixChan.c */; };
		F96D4ACB08F272C9004A47F5 /* tclUnixEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446008F272B9004A47F5 /* tclUnixEvent.c */; };
		F96D4ACC08F272C9004A47F5 /* tclUnixFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446108F272B9004A47F5 /* tclUnixFCmd.c */; };
		F96D4ACD08F272C9004A47F5 /* tclUnixFile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446208F272B9004A47F5 /* tclUnixFile.c */; };
		F96D4ACE08F272C9004A47F5 /* tclUnixInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446308F272B9004A47F5 /* tclUnixInit.c */; settings = {COMPILER_FLAGS = "-DTCL_LIBRARY=\\\"$(TCL_LIBRARY)\\\" -DTCL_PACKAGE_PATH=\\\"$(TCL_PACKAGE_PATH)\\\""; }; };
		F96D4ACF08F272C9004A47F5 /* tclUnixNotfy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446408F272B9004A47F5 /* tclUnixNotfy.c */; };
		F96D4AD008F272C9004A47F5 /* tclUnixPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446508F272B9004A47F5 /* tclUnixPipe.c */; };
		F96D4AD208F272CA004A47F5 /* tclUnixSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446708F272B9004A47F5 /* tclUnixSock.c */; };
		F96D4AD308F272CA004A47F5 /* tclUnixTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446808F272B9004A47F5 /* tclUnixTest.c */; };
		F96D4AD408F272CA004A47F5 /* tclUnixThrd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446908F272B9004A47F5 /* tclUnixThrd.c */; };
		F96D4AD608F272CA004A47F5 /* tclUnixTime.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446B08F272B9004A47F5 /* tclUnixTime.c */; };
		F9E61D28090A481F002B3151 /* bn_mp_cmp_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */; };
		F9E61D29090A486C002B3151 /* bn_mp_neg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A208F272B3004A47F5 /* bn_mp_neg.c */; };
		F9E61D2A090A4891002B3151 /* bn_mp_sqrt.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */; };
		F9E61D2B090A48A4002B3151 /* bn_mp_and.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426C08F272B3004A47F5 /* bn_mp_and.c */; };
		F9E61D2C090A48AC002B3151 /* bn_mp_expt_u32.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427F08F272B3004A47F5 /* bn_mp_expt_u32.c */; };
		F9E61D2C090A48AC002B3151 /* bn_mp_expt_d_ex.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427F08F272B3004A47F5 /* bn_mp_expt_d_ex.c */; };
		F9E61D2D090A48BB002B3151 /* bn_mp_xor.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */; };
		F9E61D2E090A48BF002B3151 /* bn_mp_or.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A308F272B3004A47F5 /* bn_mp_or.c */; };
		F9E61D2F090A48C7002B3151 /* bn_mp_shrink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */; };
		F9E61D31090A48F9002B3151 /* bn_mp_to_ubin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C608F272B3004A47F5 /* bn_mp_to_ubin.c */; };
		F9E61D32090A48FA002B3151 /* bn_mp_ubin_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CC08F272B3004A47F5 /* bn_mp_ubin_size.c */; };
		F9F4415E0C8BAE6F00BCCD67 /* tclDTrace.d in Sources */ = {isa = PBXBuildFile; fileRef = F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */; };
		F9FC77B80AB29E9100B7077D /* tclUnixCompat.c in Sources */ = {isa = PBXBuildFile; fileRef = F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
		F97258D20A868C6F00096C78 /* PBXContainerItemProxy */ = {
			isa = PBXContainerItemProxy;
			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
			proxyType = 1;
			remoteGlobalIDString = 8DD76FA90486AB0100D96B5E;
			remoteInfo = tcltest;
		};
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
		8DD76FB20486AB0100D96B5E /* tcltest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tcltest; sourceTree = BUILT_PRODUCTS_DIR; };
		F915432A0EF201CF0032D1E8 /* zlib.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = zlib.test; sourceTree = "<group>"; };
		F915432D0EF201EE0032D1E8 /* zlib.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = zlib.n; sourceTree = "<group>"; };
		F9183E640EFC80CD0030B814 /* throw.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = throw.n; sourceTree = "<group>"; };
		F9183E650EFC80D70030B814 /* try.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = try.n; sourceTree = "<group>"; };
		F9183E6A0EFC81560030B814 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F9183E8F0EFC817B0030B814 /* tdbc */ = {isa = PBXFileReference; lastKnownFileType = folder; path = tdbc; sourceTree = "<group>"; };
		F91DC23C0E44C51B002CB8D1 /* nre.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = nre.test; sourceTree = "<group>"; };
		F91E62260C1AE686006C9D96 /* Tclsh-Info.plist.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "Tclsh-Info.plist.in"; sourceTree = "<group>"; };
		F92D7F100DE777240033A13A /* tsdPerf.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tsdPerf.tcl; sourceTree = "<group>"; };
		F93599B20DF1F75400E04F67 /* tclOO.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOO.c; sourceTree = "<group>"; };
		F93599B40DF1F75900E04F67 /* tclOO.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclOO.decls; sourceTree = "<group>"; };
		F93599B50DF1F75D00E04F67 /* tclOO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOO.h; sourceTree = "<group>"; };
		F93599B60DF1F76100E04F67 /* tclOOBasic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOBasic.c; sourceTree = "<group>"; };
		F93599B80DF1F76600E04F67 /* tclOOCall.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOCall.c; sourceTree = "<group>"; };
		F93599BA0DF1F76A00E04F67 /* tclOODecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOODecls.h; sourceTree = "<group>"; };
		F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOODefineCmds.c; sourceTree = "<group>"; };
		F93599BD0DF1F77400E04F67 /* tclOOInfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOInfo.c; sourceTree = "<group>"; };
		F93599BF0DF1F77900E04F67 /* tclOOInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOOInt.h; sourceTree = "<group>"; };
		F93599C00DF1F77D00E04F67 /* tclOOIntDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOOIntDecls.h; sourceTree = "<group>"; };
		F93599C10DF1F78300E04F67 /* tclOOMethod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOMethod.c; sourceTree = "<group>"; };
		F93599C30DF1F78800E04F67 /* tclOOStubInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOStubInit.c; sourceTree = "<group>"; };
		F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOStubLib.c; sourceTree = "<group>"; };
		F93599C80DF1F81900E04F67 /* oo.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = oo.test; sourceTree = "<group>"; };
		F93599CF0DF1F87F00E04F67 /* Class.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Class.3; sourceTree = "<group>"; };
		F93599D00DF1F89E00E04F67 /* class.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = class.n; sourceTree = "<group>"; };
		F93599D20DF1F8DF00E04F67 /* copy.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = copy.n; sourceTree = "<group>"; };
		F93599D30DF1F8F500E04F67 /* define.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = define.n; sourceTree = "<group>"; };
		F93599D40DF1F91900E04F67 /* Method.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Method.3; sourceTree = "<group>"; };
		F93599D50DF1F93700E04F67 /* my.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = my.n; sourceTree = "<group>"; };
		F93599D60DF1F95000E04F67 /* next.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = next.n; sourceTree = "<group>"; };
		F93599D70DF1F96800E04F67 /* object.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = object.n; sourceTree = "<group>"; };
		F93599D80DF1F98300E04F67 /* self.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = self.n; sourceTree = "<group>"; };
		F946FB8B0FBE3AED00CD6495 /* itcl */ = {isa = PBXFileReference; lastKnownFileType = folder; path = itcl; sourceTree = "<group>"; };
		F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIORTrans.c; sourceTree = "<group>"; };
		F95FAFF90B34F1130072E431 /* macOSXLoad.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = macOSXLoad.test; sourceTree = "<group>"; };
		F96437C90EF0D4B2003F468E /* tclZlib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclZlib.c; sourceTree = "<group>"; };
		F96437E60EF0D652003F468E /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = "<absolute>"; };
		F966C07408F2820D005CB29B /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
		F96D3DFA08F272A4004A47F5 /* ChangeLog */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = ChangeLog; sourceTree = "<group>"; };
		F96D3DFB08F272A4004A47F5 /* changes */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = changes; sourceTree = "<group>"; };
		F96D3DFD08F272A4004A47F5 /* Access.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Access.3; sourceTree = "<group>"; };
		F96D3DFE08F272A4004A47F5 /* AddErrInfo.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AddErrInfo.3; sourceTree = "<group>"; };
		F96D3DFF08F272A4004A47F5 /* after.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = after.n; sourceTree = "<group>"; };
		F96D3E0008F272A4004A47F5 /* Alloc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Alloc.3; sourceTree = "<group>"; };
		F96D3E0108F272A4004A47F5 /* AllowExc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AllowExc.3; sourceTree = "<group>"; };
		F96D3E0208F272A4004A47F5 /* append.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = append.n; sourceTree = "<group>"; };
		F96D3E0308F272A4004A47F5 /* AppInit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AppInit.3; sourceTree = "<group>"; };
		F96D3E0408F272A5004A47F5 /* array.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = array.n; sourceTree = "<group>"; };
		F96D3E0508F272A5004A47F5 /* AssocData.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AssocData.3; sourceTree = "<group>"; };
		F96D3E0608F272A5004A47F5 /* Async.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Async.3; sourceTree = "<group>"; };
		F96D3E0708F272A5004A47F5 /* BackgdErr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = BackgdErr.3; sourceTree = "<group>"; };
		F96D3E0808F272A5004A47F5 /* Backslash.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Backslash.3; sourceTree = "<group>"; };
		F96D3E0908F272A5004A47F5 /* bgerror.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = bgerror.n; sourceTree = "<group>"; };
		F96D3E0A08F272A5004A47F5 /* binary.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = binary.n; sourceTree = "<group>"; };
		F96D3E0B08F272A5004A47F5 /* BoolObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = BoolObj.3; sourceTree = "<group>"; };
		F96D3E0C08F272A5004A47F5 /* break.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = break.n; sourceTree = "<group>"; };
		F96D3E0D08F272A5004A47F5 /* ByteArrObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ByteArrObj.3; sourceTree = "<group>"; };
		F96D3E0E08F272A5004A47F5 /* CallDel.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CallDel.3; sourceTree = "<group>"; };
		F96D3E0F08F272A5004A47F5 /* case.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = case.n; sourceTree = "<group>"; };
		F96D3E1008F272A5004A47F5 /* catch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = catch.n; sourceTree = "<group>"; };
		F96D3E1108F272A5004A47F5 /* cd.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = cd.n; sourceTree = "<group>"; };
		F96D3E1208F272A5004A47F5 /* chan.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = chan.n; sourceTree = "<group>"; };
		F96D3E1308F272A5004A47F5 /* ChnlStack.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ChnlStack.3; sourceTree = "<group>"; };
		F96D3E1408F272A5004A47F5 /* clock.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = clock.n; sourceTree = "<group>"; };
		F96D3E1508F272A5004A47F5 /* close.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = close.n; sourceTree = "<group>"; };
		F96D3E1608F272A5004A47F5 /* CmdCmplt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CmdCmplt.3; sourceTree = "<group>"; };
		F96D3E1708F272A5004A47F5 /* Concat.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Concat.3; sourceTree = "<group>"; };
		F96D3E1808F272A5004A47F5 /* concat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = concat.n; sourceTree = "<group>"; };
		F96D3E1908F272A5004A47F5 /* continue.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = continue.n; sourceTree = "<group>"; };
		F96D3E1A08F272A5004A47F5 /* CrtChannel.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtChannel.3; sourceTree = "<group>"; };
		F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtChnlHdlr.3; sourceTree = "<group>"; };
		F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCloseHdlr.3; sourceTree = "<group>"; };
		F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCommand.3; sourceTree = "<group>"; };
		F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtFileHdlr.3; sourceTree = "<group>"; };
		F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtInterp.3; sourceTree = "<group>"; };
		F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtMathFnc.3; sourceTree = "<group>"; };
		F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtObjCmd.3; sourceTree = "<group>"; };
		F96D3E2208F272A5004A47F5 /* CrtAlias.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtAlias.3; sourceTree = "<group>"; };
		F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTimerHdlr.3; sourceTree = "<group>"; };
		F96D3E2408F272A5004A47F5 /* CrtTrace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTrace.3; sourceTree = "<group>"; };
		F96D3E2508F272A5004A47F5 /* dde.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dde.n; sourceTree = "<group>"; };
		F96D3E2608F272A5004A47F5 /* DetachPids.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DetachPids.3; sourceTree = "<group>"; };
		F96D3E2708F272A5004A47F5 /* dict.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dict.n; sourceTree = "<group>"; };
		F96D3E2808F272A5004A47F5 /* DictObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DictObj.3; sourceTree = "<group>"; };
		F96D3E2908F272A5004A47F5 /* DoOneEvent.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoOneEvent.3; sourceTree = "<group>"; };
		F96D3E2A08F272A5004A47F5 /* DoubleObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoubleObj.3; sourceTree = "<group>"; };
		F96D3E2B08F272A5004A47F5 /* DoWhenIdle.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoWhenIdle.3; sourceTree = "<group>"; };
		F96D3E2C08F272A5004A47F5 /* DString.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DString.3; sourceTree = "<group>"; };
		F96D3E2D08F272A5004A47F5 /* DumpActiveMemory.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DumpActiveMemory.3; sourceTree = "<group>"; };
		F96D3E2E08F272A5004A47F5 /* Encoding.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Encoding.3; sourceTree = "<group>"; };
		F96D3E2F08F272A5004A47F5 /* encoding.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = encoding.n; sourceTree = "<group>"; };
		F96D3E3008F272A5004A47F5 /* Ensemble.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Ensemble.3; sourceTree = "<group>"; };
		F96D3E3108F272A5004A47F5 /* Environment.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Environment.3; sourceTree = "<group>"; };
		F96D3E3208F272A5004A47F5 /* eof.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = eof.n; sourceTree = "<group>"; };
		F96D3E3308F272A5004A47F5 /* error.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = error.n; sourceTree = "<group>"; };
		F96D3E3408F272A5004A47F5 /* Eval.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Eval.3; sourceTree = "<group>"; };
		F96D3E3508F272A5004A47F5 /* eval.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = eval.n; sourceTree = "<group>"; };
		F96D3E3608F272A5004A47F5 /* exec.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = exec.n; sourceTree = "<group>"; };
		F96D3E3708F272A5004A47F5 /* Exit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Exit.3; sourceTree = "<group>"; };
		F96D3E3808F272A5004A47F5 /* exit.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = exit.n; sourceTree = "<group>"; };
		F96D3E3908F272A5004A47F5 /* expr.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = expr.n; sourceTree = "<group>"; };
		F96D3E3A08F272A5004A47F5 /* ExprLong.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ExprLong.3; sourceTree = "<group>"; };
		F96D3E3B08F272A5004A47F5 /* ExprLongObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ExprLongObj.3; sourceTree = "<group>"; };
		F96D3E3C08F272A5004A47F5 /* fblocked.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fblocked.n; sourceTree = "<group>"; };
		F96D3E3D08F272A5004A47F5 /* fconfigure.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fconfigure.n; sourceTree = "<group>"; };
		F96D3E3E08F272A5004A47F5 /* fcopy.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fcopy.n; sourceTree = "<group>"; };
		F96D3E3F08F272A5004A47F5 /* file.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = file.n; sourceTree = "<group>"; };
		F96D3E4008F272A5004A47F5 /* fileevent.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fileevent.n; sourceTree = "<group>"; };
		F96D3E4108F272A5004A47F5 /* filename.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = filename.n; sourceTree = "<group>"; };
		F96D3E4208F272A5004A47F5 /* FileSystem.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FileSystem.3; sourceTree = "<group>"; };
		F96D3E4308F272A5004A47F5 /* FindExec.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FindExec.3; sourceTree = "<group>"; };
		F96D3E4408F272A5004A47F5 /* flush.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = flush.n; sourceTree = "<group>"; };
		F96D3E4508F272A5004A47F5 /* for.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = for.n; sourceTree = "<group>"; };
		F96D3E4608F272A5004A47F5 /* foreach.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = foreach.n; sourceTree = "<group>"; };
		F96D3E4708F272A5004A47F5 /* format.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = format.n; sourceTree = "<group>"; };
		F96D3E4808F272A5004A47F5 /* GetCwd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetCwd.3; sourceTree = "<group>"; };
		F96D3E4908F272A5004A47F5 /* GetHostName.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetHostName.3; sourceTree = "<group>"; };
		F96D3E4A08F272A5004A47F5 /* GetIndex.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetIndex.3; sourceTree = "<group>"; };
		F96D3E4B08F272A5004A47F5 /* GetInt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetInt.3; sourceTree = "<group>"; };
		F96D3E4C08F272A5004A47F5 /* GetOpnFl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetOpnFl.3; sourceTree = "<group>"; };
		F96D3E4D08F272A5004A47F5 /* gets.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = gets.n; sourceTree = "<group>"; };
		F96D3E4E08F272A5004A47F5 /* GetStdChan.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetStdChan.3; sourceTree = "<group>"; };
		F96D3E4F08F272A5004A47F5 /* GetTime.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetTime.3; sourceTree = "<group>"; };
		F96D3E5008F272A5004A47F5 /* GetVersion.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetVersion.3; sourceTree = "<group>"; };
		F96D3E5108F272A5004A47F5 /* glob.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = glob.n; sourceTree = "<group>"; };
		F96D3E5208F272A6004A47F5 /* global.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = global.n; sourceTree = "<group>"; };
		F96D3E5308F272A6004A47F5 /* Hash.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Hash.3; sourceTree = "<group>"; };
		F96D3E5408F272A6004A47F5 /* history.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = history.n; sourceTree = "<group>"; };
		F96D3E5508F272A6004A47F5 /* http.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = http.n; sourceTree = "<group>"; };
		F96D3E5608F272A6004A47F5 /* if.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = if.n; sourceTree = "<group>"; };
		F96D3E5708F272A6004A47F5 /* incr.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = incr.n; sourceTree = "<group>"; };
		F96D3E5808F272A6004A47F5 /* info.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = info.n; sourceTree = "<group>"; };
		F96D3E5908F272A6004A47F5 /* Init.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Init.3; sourceTree = "<group>"; };
		F96D3E5A08F272A6004A47F5 /* InitStubs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = InitStubs.3; sourceTree = "<group>"; };
		F96D3E5B08F272A6004A47F5 /* Interp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Interp.3; sourceTree = "<group>"; };
		F96D3E5C08F272A6004A47F5 /* interp.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = interp.n; sourceTree = "<group>"; };
		F96D3E5D08F272A6004A47F5 /* IntObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = IntObj.3; sourceTree = "<group>"; };
		F96D3E5E08F272A6004A47F5 /* join.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = join.n; sourceTree = "<group>"; };
		F96D3E5F08F272A6004A47F5 /* lappend.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lappend.n; sourceTree = "<group>"; };
		F96D3E6008F272A6004A47F5 /* lassign.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lassign.n; sourceTree = "<group>"; };
		F96D3E6108F272A6004A47F5 /* library.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = library.n; sourceTree = "<group>"; };
		F96D3E6208F272A6004A47F5 /* Limit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Limit.3; sourceTree = "<group>"; };
		F96D3E6308F272A6004A47F5 /* lindex.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lindex.n; sourceTree = "<group>"; };
		F96D3E6408F272A6004A47F5 /* LinkVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = LinkVar.3; sourceTree = "<group>"; };
		F96D3E6508F272A6004A47F5 /* linsert.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = linsert.n; sourceTree = "<group>"; };
		F96D3E6608F272A6004A47F5 /* list.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = list.n; sourceTree = "<group>"; };
		F96D3E6708F272A6004A47F5 /* ListObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ListObj.3; sourceTree = "<group>"; };
		F96D3E6808F272A6004A47F5 /* llength.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = llength.n; sourceTree = "<group>"; };
		F96D3E6908F272A6004A47F5 /* load.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = load.n; sourceTree = "<group>"; };
		F96D3E6A08F272A6004A47F5 /* lrange.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lrange.n; sourceTree = "<group>"; };
		F96D3E6B08F272A6004A47F5 /* lrepeat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lrepeat.n; sourceTree = "<group>"; };
		F96D3E6C08F272A6004A47F5 /* lreplace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lreplace.n; sourceTree = "<group>"; };
		F96D3E6D08F272A6004A47F5 /* lsearch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lsearch.n; sourceTree = "<group>"; };
		F96D3E6E08F272A6004A47F5 /* lset.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lset.n; sourceTree = "<group>"; };
		F96D3E6F08F272A6004A47F5 /* lsort.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lsort.n; sourceTree = "<group>"; };
		F96D3E7008F272A6004A47F5 /* man.macros */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = man.macros; sourceTree = "<group>"; };
		F96D3E7108F272A6004A47F5 /* mathfunc.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = mathfunc.n; sourceTree = "<group>"; };
		F96D3E7208F272A6004A47F5 /* memory.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = memory.n; sourceTree = "<group>"; };
		F96D3E7308F272A6004A47F5 /* msgcat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = msgcat.n; sourceTree = "<group>"; };
		F96D3E7408F272A6004A47F5 /* Namespace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Namespace.3; sourceTree = "<group>"; };
		F96D3E7508F272A6004A47F5 /* namespace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = namespace.n; sourceTree = "<group>"; };
		F96D3E7608F272A6004A47F5 /* Notifier.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Notifier.3; sourceTree = "<group>"; };
		F96D3E7708F272A6004A47F5 /* Object.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Object.3; sourceTree = "<group>"; };
		F96D3E7808F272A6004A47F5 /* ObjectType.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ObjectType.3; sourceTree = "<group>"; };
		F96D3E7908F272A6004A47F5 /* open.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = open.n; sourceTree = "<group>"; };
		F96D3E7A08F272A6004A47F5 /* OpenFileChnl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = OpenFileChnl.3; sourceTree = "<group>"; };
		F96D3E7B08F272A6004A47F5 /* OpenTcp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = OpenTcp.3; sourceTree = "<group>"; };
		F96D3E7C08F272A6004A47F5 /* package.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = package.n; sourceTree = "<group>"; };
		F96D3E7D08F272A6004A47F5 /* packagens.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = packagens.n; sourceTree = "<group>"; };
		F96D3E7E08F272A6004A47F5 /* Panic.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Panic.3; sourceTree = "<group>"; };
		F96D3E7F08F272A6004A47F5 /* ParseCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ParseCmd.3; sourceTree = "<group>"; };
		F96D3E8008F272A6004A47F5 /* pid.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pid.n; sourceTree = "<group>"; };
		F96D3E8108F272A6004A47F5 /* pkgMkIndex.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pkgMkIndex.n; sourceTree = "<group>"; };
		F96D3E8208F272A6004A47F5 /* PkgRequire.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = PkgRequire.3; sourceTree = "<group>"; };
		F96D3E8308F272A6004A47F5 /* Preserve.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Preserve.3; sourceTree = "<group>"; };
		F96D3E8408F272A6004A47F5 /* PrintDbl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = PrintDbl.3; sourceTree = "<group>"; };
		F96D3E8508F272A6004A47F5 /* proc.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = proc.n; sourceTree = "<group>"; };
		F96D3E8608F272A6004A47F5 /* puts.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = puts.n; sourceTree = "<group>"; };
		F96D3E8708F272A6004A47F5 /* pwd.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pwd.n; sourceTree = "<group>"; };
		F96D3E8808F272A6004A47F5 /* re_syntax.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = re_syntax.n; sourceTree = "<group>"; };
		F96D3E8908F272A6004A47F5 /* read.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = read.n; sourceTree = "<group>"; };
		F96D3E8A08F272A6004A47F5 /* RecEvalObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RecEvalObj.3; sourceTree = "<group>"; };
		F96D3E8B08F272A6004A47F5 /* RecordEval.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RecordEval.3; sourceTree = "<group>"; };
		F96D3E8C08F272A6004A47F5 /* RegConfig.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RegConfig.3; sourceTree = "<group>"; };
		F96D3E8D08F272A6004A47F5 /* RegExp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RegExp.3; sourceTree = "<group>"; };
		F96D3E8E08F272A6004A47F5 /* regexp.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = regexp.n; sourceTree = "<group>"; };
		F96D3E8F08F272A6004A47F5 /* registry.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = registry.n; sourceTree = "<group>"; };
		F96D3E9008F272A6004A47F5 /* regsub.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = regsub.n; sourceTree = "<group>"; };
		F96D3E9108F272A6004A47F5 /* rename.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = rename.n; sourceTree = "<group>"; };
		F96D3E9208F272A6004A47F5 /* return.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = return.n; sourceTree = "<group>"; };
		F96D3E9308F272A6004A47F5 /* safe.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = safe.n; sourceTree = "<group>"; };
		F96D3E9408F272A6004A47F5 /* SaveResult.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SaveResult.3; sourceTree = "<group>"; };
		F96D3E9508F272A6004A47F5 /* scan.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = scan.n; sourceTree = "<group>"; };
		F96D3E9608F272A6004A47F5 /* seek.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = seek.n; sourceTree = "<group>"; };
		F96D3E9708F272A6004A47F5 /* set.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = set.n; sourceTree = "<group>"; };
		F96D3E9808F272A6004A47F5 /* SetChanErr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetChanErr.3; sourceTree = "<group>"; };
		F96D3E9908F272A6004A47F5 /* SetErrno.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetErrno.3; sourceTree = "<group>"; };
		F96D3E9A08F272A6004A47F5 /* SetRecLmt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetRecLmt.3; sourceTree = "<group>"; };
		F96D3E9B08F272A7004A47F5 /* SetResult.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetResult.3; sourceTree = "<group>"; };
		F96D3E9C08F272A7004A47F5 /* SetVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetVar.3; sourceTree = "<group>"; };
		F96D3E9D08F272A7004A47F5 /* Signal.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Signal.3; sourceTree = "<group>"; };
		F96D3E9E08F272A7004A47F5 /* Sleep.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Sleep.3; sourceTree = "<group>"; };
		F96D3E9F08F272A7004A47F5 /* socket.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = socket.n; sourceTree = "<group>"; };
		F96D3EA008F272A7004A47F5 /* source.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = source.n; sourceTree = "<group>"; };
		F96D3EA108F272A7004A47F5 /* SourceRCFile.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SourceRCFile.3; sourceTree = "<group>"; };
		F96D3EA208F272A7004A47F5 /* split.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = split.n; sourceTree = "<group>"; };
		F96D3EA308F272A7004A47F5 /* SplitList.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitList.3; sourceTree = "<group>"; };
		F96D3EA408F272A7004A47F5 /* SplitPath.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitPath.3; sourceTree = "<group>"; };
		F96D3EA508F272A7004A47F5 /* StaticPkg.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StaticPkg.3; sourceTree = "<group>"; };
		F96D3EA608F272A7004A47F5 /* StdChannels.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StdChannels.3; sourceTree = "<group>"; };
		F96D3EA708F272A7004A47F5 /* string.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = string.n; sourceTree = "<group>"; };
		F96D3EA808F272A7004A47F5 /* StringObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StringObj.3; sourceTree = "<group>"; };
		F96D3EA908F272A7004A47F5 /* StrMatch.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StrMatch.3; sourceTree = "<group>"; };
		F96D3EAA08F272A7004A47F5 /* subst.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = subst.n; sourceTree = "<group>"; };
		F96D3EAB08F272A7004A47F5 /* SubstObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SubstObj.3; sourceTree = "<group>"; };
		F96D3EAC08F272A7004A47F5 /* switch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = switch.n; sourceTree = "<group>"; };
		F96D3EAD08F272A7004A47F5 /* Tcl.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tcl.n; sourceTree = "<group>"; };
		F96D3EAE08F272A7004A47F5 /* Tcl_Main.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tcl_Main.3; sourceTree = "<group>"; };
		F96D3EAF08F272A7004A47F5 /* TCL_MEM_DEBUG.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TCL_MEM_DEBUG.3; sourceTree = "<group>"; };
		F96D3EB008F272A7004A47F5 /* tclsh.1 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tclsh.1; sourceTree = "<group>"; };
		F96D3EB108F272A7004A47F5 /* tcltest.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tcltest.n; sourceTree = "<group>"; };
		F96D3EB208F272A7004A47F5 /* tclvars.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tclvars.n; sourceTree = "<group>"; };
		F96D3EB308F272A7004A47F5 /* tell.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tell.n; sourceTree = "<group>"; };
		F96D3EB408F272A7004A47F5 /* Thread.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Thread.3; sourceTree = "<group>"; };
		F96D3EB508F272A7004A47F5 /* time.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = time.n; sourceTree = "<group>"; };
		F96D3EB608F272A7004A47F5 /* tm.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tm.n; sourceTree = "<group>"; };
		F96D3EB708F272A7004A47F5 /* ToUpper.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ToUpper.3; sourceTree = "<group>"; };
		F96D3EB808F272A7004A47F5 /* trace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = trace.n; sourceTree = "<group>"; };
		F96D3EB908F272A7004A47F5 /* TraceCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TraceCmd.3; sourceTree = "<group>"; };
		F96D3EBA08F272A7004A47F5 /* TraceVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TraceVar.3; sourceTree = "<group>"; };
		F96D3EBB08F272A7004A47F5 /* Translate.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Translate.3; sourceTree = "<group>"; };
		F96D3EBC08F272A7004A47F5 /* UniCharIsAlpha.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = UniCharIsAlpha.3; sourceTree = "<group>"; };
		F96D3EBD08F272A7004A47F5 /* unknown.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unknown.n; sourceTree = "<group>"; };
		F96D3EBE08F272A7004A47F5 /* unload.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unload.n; sourceTree = "<group>"; };
		F96D3EBF08F272A7004A47F5 /* unset.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unset.n; sourceTree = "<group>"; };
		F96D3EC008F272A7004A47F5 /* update.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = update.n; sourceTree = "<group>"; };
		F96D3EC108F272A7004A47F5 /* uplevel.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = uplevel.n; sourceTree = "<group>"; };
		F96D3EC208F272A7004A47F5 /* UpVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = UpVar.3; sourceTree = "<group>"; };
		F96D3EC308F272A7004A47F5 /* upvar.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = upvar.n; sourceTree = "<group>"; };
		F96D3EC408F272A7004A47F5 /* Utf.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Utf.3; sourceTree = "<group>"; };
		F96D3EC508F272A7004A47F5 /* variable.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = variable.n; sourceTree = "<group>"; };
		F96D3EC608F272A7004A47F5 /* vwait.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = vwait.n; sourceTree = "<group>"; };
		F96D3EC708F272A7004A47F5 /* while.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = while.n; sourceTree = "<group>"; };
		F96D3EC808F272A7004A47F5 /* WrongNumArgs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = WrongNumArgs.3; sourceTree = "<group>"; };
		F96D3ECA08F272A7004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D3ECB08F272A7004A47F5 /* regc_color.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_color.c; sourceTree = "<group>"; };
		F96D3ECC08F272A7004A47F5 /* regc_cvec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_cvec.c; sourceTree = "<group>"; };
		F96D3ECD08F272A7004A47F5 /* regc_lex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_lex.c; sourceTree = "<group>"; };
		F96D3ECE08F272A7004A47F5 /* regc_locale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_locale.c; sourceTree = "<group>"; };
		F96D3ECF08F272A7004A47F5 /* regc_nfa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_nfa.c; sourceTree = "<group>"; };
		F96D3ED008F272A7004A47F5 /* regcomp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regcomp.c; sourceTree = "<group>"; };
		F96D3ED108F272A7004A47F5 /* regcustom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regcustom.h; sourceTree = "<group>"; };
		F96D3ED208F272A7004A47F5 /* rege_dfa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rege_dfa.c; sourceTree = "<group>"; };
		F96D3ED308F272A7004A47F5 /* regerror.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regerror.c; sourceTree = "<group>"; };
		F96D3ED408F272A7004A47F5 /* regerrs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regerrs.h; sourceTree = "<group>"; };
		F96D3ED508F272A7004A47F5 /* regex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regex.h; sourceTree = "<group>"; };
		F96D3ED608F272A7004A47F5 /* regexec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regexec.c; sourceTree = "<group>"; };
		F96D3ED708F272A7004A47F5 /* regfree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regfree.c; sourceTree = "<group>"; };
		F96D3ED808F272A7004A47F5 /* regfronts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regfronts.c; sourceTree = "<group>"; };
		F96D3ED908F272A7004A47F5 /* regguts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regguts.h; sourceTree = "<group>"; };
		F96D3EDA08F272A7004A47F5 /* tcl.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcl.decls; sourceTree = "<group>"; };
		F96D3EDB08F272A7004A47F5 /* tcl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tcl.h; sourceTree = "<group>"; };
		F96D3EDC08F272A7004A47F5 /* tclAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAlloc.c; sourceTree = "<group>"; };
		F96D3EDD08F272A7004A47F5 /* tclAsync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAsync.c; sourceTree = "<group>"; };
		F96D3EDE08F272A7004A47F5 /* tclBasic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclBasic.c; sourceTree = "<group>"; };
		F96D3EDF08F272A7004A47F5 /* tclBinary.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclBinary.c; sourceTree = "<group>"; };
		F96D3EE008F272A7004A47F5 /* tclCkalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCkalloc.c; sourceTree = "<group>"; };
		F96D3EE108F272A7004A47F5 /* tclClock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclClock.c; sourceTree = "<group>"; };
		F96D3EE208F272A7004A47F5 /* tclCmdAH.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdAH.c; sourceTree = "<group>"; };
		F96D3EE308F272A7004A47F5 /* tclCmdIL.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdIL.c; sourceTree = "<group>"; };
		F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdMZ.c; sourceTree = "<group>"; };
		F96D3EE508F272A7004A47F5 /* tclCompCmds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompCmds.c; sourceTree = "<group>"; };
		F96D3EE608F272A7004A47F5 /* tclCompExpr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompExpr.c; sourceTree = "<group>"; };
		F96D3EE708F272A7004A47F5 /* tclCompile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompile.c; sourceTree = "<group>"; };
		F96D3EE808F272A7004A47F5 /* tclCompile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclCompile.h; sourceTree = "<group>"; };
		F96D3EE908F272A7004A47F5 /* tclConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclConfig.c; sourceTree = "<group>"; };
		F96D3EEA08F272A7004A47F5 /* tclDate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclDate.c; sourceTree = "<group>"; };
		F96D3EEB08F272A7004A47F5 /* tclDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclDecls.h; sourceTree = "<group>"; };
		F96D3EEC08F272A7004A47F5 /* tclDictObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclDictObj.c; sourceTree = "<group>"; };
		F96D3EED08F272A7004A47F5 /* tclEncoding.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEncoding.c; sourceTree = "<group>"; };
		F96D3EEE08F272A7004A47F5 /* tclEnv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEnv.c; sourceTree = "<group>"; };
		F96D3EEF08F272A7004A47F5 /* tclEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEvent.c; sourceTree = "<group>"; };
		F96D3EF008F272A7004A47F5 /* tclExecute.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclExecute.c; sourceTree = "<group>"; };
		F96D3EF108F272A7004A47F5 /* tclFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclFCmd.c; sourceTree = "<group>"; };
		F96D3EF208F272A7004A47F5 /* tclFileName.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclFileName.c; sourceTree = "<group>"; };
		F96D3EF308F272A7004A47F5 /* tclFileSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclFileSystem.h; sourceTree = "<group>"; };
		F96D3EF408F272A7004A47F5 /* tclGet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclGet.c; sourceTree = "<group>"; };
		F96D3EF508F272A7004A47F5 /* tclGetDate.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; path = tclGetDate.y; sourceTree = "<group>"; };
		F96D3EF608F272A7004A47F5 /* tclHash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclHash.c; sourceTree = "<group>"; };
		F96D3EF708F272A7004A47F5 /* tclHistory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclHistory.c; sourceTree = "<group>"; };
		F96D3EF808F272A7004A47F5 /* tclIndexObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIndexObj.c; sourceTree = "<group>"; };
		F96D3EF908F272A7004A47F5 /* tclInt.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclInt.decls; sourceTree = "<group>"; };
		F96D3EFA08F272A7004A47F5 /* tclInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclInt.h; sourceTree = "<group>"; };
		F96D3EFB08F272A7004A47F5 /* tclIntDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIntDecls.h; sourceTree = "<group>"; };
		F96D3EFC08F272A7004A47F5 /* tclInterp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclInterp.c; sourceTree = "<group>"; };
		F96D3EFD08F272A7004A47F5 /* tclIntPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIntPlatDecls.h; sourceTree = "<group>"; };
		F96D3EFE08F272A7004A47F5 /* tclIO.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIO.c; sourceTree = "<group>"; };
		F96D3EFF08F272A7004A47F5 /* tclIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIO.h; sourceTree = "<group>"; };
		F96D3F0008F272A7004A47F5 /* tclIOCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOCmd.c; sourceTree = "<group>"; };
		F96D3F0108F272A7004A47F5 /* tclIOGT.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOGT.c; sourceTree = "<group>"; };
		F96D3F0208F272A7004A47F5 /* tclIORChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIORChan.c; sourceTree = "<group>"; };
		F96D3F0308F272A7004A47F5 /* tclIOSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOSock.c; sourceTree = "<group>"; };
		F96D3F0408F272A7004A47F5 /* tclIOUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOUtil.c; sourceTree = "<group>"; };
		F96D3F0508F272A7004A47F5 /* tclLink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLink.c; sourceTree = "<group>"; };
		F96D3F0608F272A7004A47F5 /* tclListObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclListObj.c; sourceTree = "<group>"; };
		F96D3F0708F272A7004A47F5 /* tclLiteral.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLiteral.c; sourceTree = "<group>"; };
		F96D3F0808F272A7004A47F5 /* tclLoad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoad.c; sourceTree = "<group>"; };
		F96D3F0908F272A7004A47F5 /* tclLoadNone.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadNone.c; sourceTree = "<group>"; };
		F96D3F0A08F272A7004A47F5 /* tclMain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMain.c; sourceTree = "<group>"; };
		F96D3F0B08F272A7004A47F5 /* tclNamesp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclNamesp.c; sourceTree = "<group>"; };
		F96D3F0C08F272A7004A47F5 /* tclNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclNotify.c; sourceTree = "<group>"; };
		F96D3F0D08F272A7004A47F5 /* tclObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclObj.c; sourceTree = "<group>"; };
		F96D3F0E08F272A7004A47F5 /* tclPanic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPanic.c; sourceTree = "<group>"; };
		F96D3F0F08F272A7004A47F5 /* tclParse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclParse.c; sourceTree = "<group>"; };
		F96D3F1108F272A7004A47F5 /* tclPathObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPathObj.c; sourceTree = "<group>"; };
		F96D3F1208F272A7004A47F5 /* tclPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPipe.c; sourceTree = "<group>"; };
		F96D3F1308F272A7004A47F5 /* tclPkg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPkg.c; sourceTree = "<group>"; };
		F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPkgConfig.c; sourceTree = "<group>"; };
		F96D3F1508F272A7004A47F5 /* tclPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclPlatDecls.h; sourceTree = "<group>"; };
		F96D3F1608F272A7004A47F5 /* tclPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclPort.h; sourceTree = "<group>"; };
		F96D3F1708F272A7004A47F5 /* tclPosixStr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPosixStr.c; sourceTree = "<group>"; };
		F96D3F1808F272A7004A47F5 /* tclPreserve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPreserve.c; sourceTree = "<group>"; };
		F96D3F1908F272A7004A47F5 /* tclProc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclProc.c; sourceTree = "<group>"; };
		F96D3F1A08F272A7004A47F5 /* tclRegexp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclRegexp.c; sourceTree = "<group>"; };
		F96D3F1B08F272A7004A47F5 /* tclRegexp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclRegexp.h; sourceTree = "<group>"; };
		F96D3F1C08F272A7004A47F5 /* tclResolve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclResolve.c; sourceTree = "<group>"; };
		F96D3F1D08F272A7004A47F5 /* tclResult.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclResult.c; sourceTree = "<group>"; };
		F96D3F1E08F272A7004A47F5 /* tclScan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclScan.c; sourceTree = "<group>"; };
		F96D3F1F08F272A7004A47F5 /* tclStringObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStringObj.c; sourceTree = "<group>"; };
		F96D3F2408F272A7004A47F5 /* tclStrToD.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStrToD.c; sourceTree = "<group>"; };
		F96D3F2508F272A7004A47F5 /* tclStubInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStubInit.c; sourceTree = "<group>"; };
		F96D3F2608F272A7004A47F5 /* tclStubLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStubLib.c; sourceTree = "<group>"; };
		F96D3F2708F272A7004A47F5 /* tclTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTest.c; sourceTree = "<group>"; };
		F96D3F2808F272A7004A47F5 /* tclTestObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTestObj.c; sourceTree = "<group>"; };
		F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTestProcBodyObj.c; sourceTree = "<group>"; };
		F96D3F2A08F272A7004A47F5 /* tclThread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThread.c; sourceTree = "<group>"; };
		F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadAlloc.c; sourceTree = "<group>"; };
		F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadJoin.c; sourceTree = "<group>"; };
		F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadStorage.c; sourceTree = "<group>"; };
		F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadTest.c; sourceTree = "<group>"; };
		F96D3F2F08F272A7004A47F5 /* tclTimer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTimer.c; sourceTree = "<group>"; };
		F96D3F3008F272A7004A47F5 /* tclTomMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMath.h; sourceTree = "<group>"; };
		F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTomMathInterface.c; sourceTree = "<group>"; };
		F96D3F3208F272A7004A47F5 /* tclTrace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTrace.c; sourceTree = "<group>"; };
		F96D3F3308F272A7004A47F5 /* tclUniData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUniData.c; sourceTree = "<group>"; };
		F96D3F3408F272A7004A47F5 /* tclUtf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUtf.c; sourceTree = "<group>"; };
		F96D3F3508F272A7004A47F5 /* tclUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUtil.c; sourceTree = "<group>"; };
		F96D3F3608F272A7004A47F5 /* tclVar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclVar.c; sourceTree = "<group>"; };
		F96D3F3908F272A8004A47F5 /* auto.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = auto.tcl; sourceTree = "<group>"; };
		F96D3F3A08F272A8004A47F5 /* clock.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clock.tcl; sourceTree = "<group>"; };
		F96D3F3C08F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
		F96D3F8C08F272A8004A47F5 /* history.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = history.tcl; sourceTree = "<group>"; };
		F96D3F8E08F272A8004A47F5 /* http.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.tcl; sourceTree = "<group>"; };
		F96D3F8F08F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
		F96D3F9108F272A8004A47F5 /* http.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.tcl; sourceTree = "<group>"; };
		F96D3F9208F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
		F96D3F9308F272A8004A47F5 /* init.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = init.tcl; sourceTree = "<group>"; };
		F96D3F9508F272A8004A47F5 /* msgcat.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgcat.tcl; sourceTree = "<group>"; };
		F96D3F9608F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
		F96D401808F272AA004A47F5 /* optparse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = optparse.tcl; sourceTree = "<group>"; };
		F96D401908F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
		F96D401A08F272AA004A47F5 /* package.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = package.tcl; sourceTree = "<group>"; };
		F96D401B08F272AA004A47F5 /* parray.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parray.tcl; sourceTree = "<group>"; };
		F96D401D08F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
		F96D401E08F272AA004A47F5 /* safe.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safe.tcl; sourceTree = "<group>"; };
		F96D401F08F272AA004A47F5 /* tclIndex */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclIndex; sourceTree = "<group>"; };
		F96D402108F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
		F96D402208F272AA004A47F5 /* tcltest.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcltest.tcl; sourceTree = "<group>"; };
		F96D402308F272AA004A47F5 /* tm.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tm.tcl; sourceTree = "<group>"; };
		F96D425B08F272B2004A47F5 /* word.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = word.tcl; sourceTree = "<group>"; };
		F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_s_mp_mul_digs.c; sourceTree = "<group>"; };
		F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_s_mp_sqr.c; sourceTree = "<group>"; };
		F96D426908F272B3004A47F5 /* bn_mp_add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_add.c; sourceTree = "<group>"; };
		F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_add_d.c; sourceTree = "<group>"; };
		F96D426C08F272B3004A47F5 /* bn_mp_and.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_and.c; sourceTree = "<group>"; };
		F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clamp.c; sourceTree = "<group>"; };
		F96D426E08F272B3004A47F5 /* bn_mp_clear.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clear.c; sourceTree = "<group>"; };
		F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clear_multi.c; sourceTree = "<group>"; };
		F96D427008F272B3004A47F5 /* bn_mp_cmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp.c; sourceTree = "<group>"; };
		F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_d.c; sourceTree = "<group>"; };
		F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_mag.c; sourceTree = "<group>"; };
		F96D427408F272B3004A47F5 /* bn_mp_copy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_copy.c; sourceTree = "<group>"; };
		F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_count_bits.c; sourceTree = "<group>"; };
		F96D427608F272B3004A47F5 /* bn_mp_div.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div.c; sourceTree = "<group>"; };
		F96D427708F272B3004A47F5 /* bn_mp_div_2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2.c; sourceTree = "<group>"; };
		F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2d.c; sourceTree = "<group>"; };
		F96D427908F272B3004A47F5 /* bn_mp_div_3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_3.c; sourceTree = "<group>"; };
		F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_d.c; sourceTree = "<group>"; };
		F96D427E08F272B3004A47F5 /* bn_mp_exch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_exch.c; sourceTree = "<group>"; };
		F96D427F08F272B3004A47F5 /* bn_mp_expt_u32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_expt_u32.c; sourceTree = "<group>"; };
		F96D428708F272B3004A47F5 /* bn_mp_grow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_grow.c; sourceTree = "<group>"; };
		F96D428808F272B3004A47F5 /* bn_mp_init.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init.c; sourceTree = "<group>"; };
		F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_copy.c; sourceTree = "<group>"; };
		F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_multi.c; sourceTree = "<group>"; };
		F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_set.c; sourceTree = "<group>"; };
		F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_size.c; sourceTree = "<group>"; };
		F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_karatsuba_mul.c; sourceTree = "<group>"; };
		F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_karatsuba_sqr.c; sourceTree = "<group>"; };
		F96D429508F272B3004A47F5 /* bn_mp_lshd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_lshd.c; sourceTree = "<group>"; };
		F96D429608F272B3004A47F5 /* bn_mp_mod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mod.c; sourceTree = "<group>"; };
		F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mod_2d.c; sourceTree = "<group>"; };
		F96D429C08F272B3004A47F5 /* bn_mp_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul.c; sourceTree = "<group>"; };
		F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_2.c; sourceTree = "<group>"; };
		F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_2d.c; sourceTree = "<group>"; };
		F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_d.c; sourceTree = "<group>"; };
		F96D42A208F272B3004A47F5 /* bn_mp_neg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_neg.c; sourceTree = "<group>"; };
		F96D42A308F272B3004A47F5 /* bn_mp_or.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_or.c; sourceTree = "<group>"; };
		F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_radix_size.c; sourceTree = "<group>"; };
		F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_radix_smap.c; sourceTree = "<group>"; };
		F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_read_radix.c; sourceTree = "<group>"; };
		F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_rshd.c; sourceTree = "<group>"; };
		F96D42BA08F272B3004A47F5 /* bn_mp_set.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_set.c; sourceTree = "<group>"; };
		F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_shrink.c; sourceTree = "<group>"; };
		F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sqr.c; sourceTree = "<group>"; };
		F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sqrt.c; sourceTree = "<group>"; };
		F96D42C108F272B3004A47F5 /* bn_mp_sub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sub.c; sourceTree = "<group>"; };
		F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sub_d.c; sourceTree = "<group>"; };
		F96D42C608F272B3004A47F5 /* bn_mp_to_ubin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_ubin.c; sourceTree = "<group>"; };
		F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toom_mul.c; sourceTree = "<group>"; };
		F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toom_sqr.c; sourceTree = "<group>"; };
		F96D42CB08F272B3004A47F5 /* bn_mp_to_radix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_radix.c; sourceTree = "<group>"; };
		F96D42CC08F272B3004A47F5 /* bn_mp_ubin_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_ubin_size.c; sourceTree = "<group>"; };
		F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_xor.c; sourceTree = "<group>"; };
		F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_zero.c; sourceTree = "<group>"; };
		F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_add.c; sourceTree = "<group>"; };
		F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_mul_digs.c; sourceTree = "<group>"; };
		F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_sqr.c; sourceTree = "<group>"; };
		F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_sub.c; sourceTree = "<group>"; };
		F96D432908F272B4004A47F5 /* tommath_class.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath_class.h; sourceTree = "<group>"; };
		F96D432A08F272B4004A47F5 /* tommath_superclass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath_superclass.h; sourceTree = "<group>"; };
		F96D432B08F272B4004A47F5 /* license.terms */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = license.terms; sourceTree = "<group>"; };
		F96D432E08F272B5004A47F5 /* configure.ac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure.ac; sourceTree = "<group>"; };
		F96D432F08F272B5004A47F5 /* GNUmakefile */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = GNUmakefile; sourceTree = "<group>"; };
		F96D433108F272B5004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D433208F272B5004A47F5 /* Tcl-Info.plist.in */ = {isa = PBXFileReference; explicitFileType = text.plist; fileEncoding = 4; path = "Tcl-Info.plist.in"; sourceTree = "<group>"; };
		F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXBundle.c; sourceTree = "<group>"; };
		F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXFCmd.c; sourceTree = "<group>"; };
		F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXNotify.c; sourceTree = "<group>"; };
		F96D434308F272B5004A47F5 /* README */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = README; sourceTree = "<group>"; };
		F96D434508F272B5004A47F5 /* all.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = all.tcl; sourceTree = "<group>"; };
		F96D434608F272B5004A47F5 /* append.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = append.test; sourceTree = "<group>"; };
		F96D434708F272B5004A47F5 /* appendComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = appendComp.test; sourceTree = "<group>"; };
		F96D434808F272B5004A47F5 /* assocd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = assocd.test; sourceTree = "<group>"; };
		F96D434908F272B5004A47F5 /* async.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = async.test; sourceTree = "<group>"; };
		F96D434A08F272B5004A47F5 /* autoMkindex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = autoMkindex.test; sourceTree = "<group>"; };
		F96D434B08F272B5004A47F5 /* basic.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = basic.test; sourceTree = "<group>"; };
		F96D434C08F272B5004A47F5 /* binary.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = binary.test; sourceTree = "<group>"; };
		F96D434D08F272B5004A47F5 /* case.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = case.test; sourceTree = "<group>"; };
		F96D434E08F272B5004A47F5 /* chan.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = chan.test; sourceTree = "<group>"; };
		F96D434F08F272B5004A47F5 /* clock.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clock.test; sourceTree = "<group>"; };
		F96D435008F272B5004A47F5 /* cmdAH.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdAH.test; sourceTree = "<group>"; };
		F96D435108F272B5004A47F5 /* cmdIL.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdIL.test; sourceTree = "<group>"; };
		F96D435208F272B5004A47F5 /* cmdInfo.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdInfo.test; sourceTree = "<group>"; };
		F96D435308F272B5004A47F5 /* cmdMZ.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdMZ.test; sourceTree = "<group>"; };
		F96D435408F272B5004A47F5 /* compExpr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "compExpr-old.test"; sourceTree = "<group>"; };
		F96D435508F272B5004A47F5 /* compExpr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = compExpr.test; sourceTree = "<group>"; };
		F96D435608F272B5004A47F5 /* compile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = compile.test; sourceTree = "<group>"; };
		F96D435708F272B5004A47F5 /* concat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = concat.test; sourceTree = "<group>"; };
		F96D435808F272B5004A47F5 /* config.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = config.test; sourceTree = "<group>"; };
		F96D435908F272B5004A47F5 /* dcall.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dcall.test; sourceTree = "<group>"; };
		F96D435A08F272B5004A47F5 /* dict.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dict.test; sourceTree = "<group>"; };
		F96D435C08F272B5004A47F5 /* dstring.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dstring.test; sourceTree = "<group>"; };
		F96D435E08F272B5004A47F5 /* encoding.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = encoding.test; sourceTree = "<group>"; };
		F96D435F08F272B5004A47F5 /* env.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = env.test; sourceTree = "<group>"; };
		F96D436008F272B5004A47F5 /* error.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = error.test; sourceTree = "<group>"; };
		F96D436108F272B5004A47F5 /* eval.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = eval.test; sourceTree = "<group>"; };
		F96D436208F272B5004A47F5 /* event.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = event.test; sourceTree = "<group>"; };
		F96D436308F272B5004A47F5 /* exec.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = exec.test; sourceTree = "<group>"; };
		F96D436408F272B5004A47F5 /* execute.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = execute.test; sourceTree = "<group>"; };
		F96D436508F272B5004A47F5 /* expr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "expr-old.test"; sourceTree = "<group>"; };
		F96D436608F272B5004A47F5 /* expr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = expr.test; sourceTree = "<group>"; };
		F96D436708F272B6004A47F5 /* fCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fCmd.test; sourceTree = "<group>"; };
		F96D436808F272B6004A47F5 /* fileName.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fileName.test; sourceTree = "<group>"; };
		F96D436908F272B6004A47F5 /* fileSystem.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fileSystem.test; sourceTree = "<group>"; };
		F96D436A08F272B6004A47F5 /* for-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "for-old.test"; sourceTree = "<group>"; };
		F96D436B08F272B6004A47F5 /* for.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = for.test; sourceTree = "<group>"; };
		F96D436C08F272B6004A47F5 /* foreach.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = foreach.test; sourceTree = "<group>"; };
		F96D436D08F272B6004A47F5 /* format.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = format.test; sourceTree = "<group>"; };
		F96D436E08F272B6004A47F5 /* get.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = get.test; sourceTree = "<group>"; };
		F96D436F08F272B6004A47F5 /* history.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = history.test; sourceTree = "<group>"; };
		F96D437008F272B6004A47F5 /* http.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.test; sourceTree = "<group>"; };
		F96D437108F272B6004A47F5 /* httpd */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpd; sourceTree = "<group>"; };
		F96D437208F272B6004A47F5 /* httpold.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpold.test; sourceTree = "<group>"; };
		F96D437308F272B6004A47F5 /* if-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "if-old.test"; sourceTree = "<group>"; };
		F96D437408F272B6004A47F5 /* if.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = if.test; sourceTree = "<group>"; };
		F96D437508F272B6004A47F5 /* incr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "incr-old.test"; sourceTree = "<group>"; };
		F96D437608F272B6004A47F5 /* incr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = incr.test; sourceTree = "<group>"; };
		F96D437708F272B6004A47F5 /* indexObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = indexObj.test; sourceTree = "<group>"; };
		F96D437808F272B6004A47F5 /* info.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = info.test; sourceTree = "<group>"; };
		F96D437908F272B6004A47F5 /* init.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = init.test; sourceTree = "<group>"; };
		F96D437A08F272B6004A47F5 /* interp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = interp.test; sourceTree = "<group>"; };
		F96D437B08F272B6004A47F5 /* io.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = io.test; sourceTree = "<group>"; };
		F96D437C08F272B6004A47F5 /* ioCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ioCmd.test; sourceTree = "<group>"; };
		F96D437D08F272B6004A47F5 /* iogt.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = iogt.test; sourceTree = "<group>"; };
		F96D437F08F272B6004A47F5 /* join.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = join.test; sourceTree = "<group>"; };
		F96D438008F272B6004A47F5 /* lindex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lindex.test; sourceTree = "<group>"; };
		F96D438108F272B6004A47F5 /* link.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = link.test; sourceTree = "<group>"; };
		F96D438208F272B6004A47F5 /* linsert.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = linsert.test; sourceTree = "<group>"; };
		F96D438308F272B6004A47F5 /* list.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = list.test; sourceTree = "<group>"; };
		F96D438408F272B6004A47F5 /* listObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = listObj.test; sourceTree = "<group>"; };
		F96D438508F272B6004A47F5 /* llength.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = llength.test; sourceTree = "<group>"; };
		F96D438608F272B6004A47F5 /* load.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = load.test; sourceTree = "<group>"; };
		F96D438708F272B6004A47F5 /* lrange.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lrange.test; sourceTree = "<group>"; };
		F96D438808F272B6004A47F5 /* lrepeat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lrepeat.test; sourceTree = "<group>"; };
		F96D438908F272B6004A47F5 /* lreplace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lreplace.test; sourceTree = "<group>"; };
		F96D438A08F272B6004A47F5 /* lsearch.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lsearch.test; sourceTree = "<group>"; };
		F96D438B08F272B6004A47F5 /* lset.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lset.test; sourceTree = "<group>"; };
		F96D438C08F272B6004A47F5 /* lsetComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lsetComp.test; sourceTree = "<group>"; };
		F96D438D08F272B6004A47F5 /* macOSXFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = macOSXFCmd.test; sourceTree = "<group>"; };
		F96D438E08F272B6004A47F5 /* main.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = main.test; sourceTree = "<group>"; };
		F96D438F08F272B6004A47F5 /* misc.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = misc.test; sourceTree = "<group>"; };
		F96D439008F272B6004A47F5 /* msgcat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgcat.test; sourceTree = "<group>"; };
		F96D439108F272B6004A47F5 /* namespace-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "namespace-old.test"; sourceTree = "<group>"; };
		F96D439208F272B7004A47F5 /* namespace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = namespace.test; sourceTree = "<group>"; };
		F96D439308F272B7004A47F5 /* notify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = notify.test; sourceTree = "<group>"; };
		F96D439408F272B7004A47F5 /* obj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = obj.test; sourceTree = "<group>"; };
		F96D439508F272B7004A47F5 /* opt.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = opt.test; sourceTree = "<group>"; };
		F96D439608F272B7004A47F5 /* package.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = package.test; sourceTree = "<group>"; };
		F96D439708F272B7004A47F5 /* parse.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parse.test; sourceTree = "<group>"; };
		F96D439808F272B7004A47F5 /* parseExpr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parseExpr.test; sourceTree = "<group>"; };
		F96D439908F272B7004A47F5 /* parseOld.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parseOld.test; sourceTree = "<group>"; };
		F96D439A08F272B7004A47F5 /* pid.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pid.test; sourceTree = "<group>"; };
		F96D439B08F272B7004A47F5 /* pkg.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkg.test; sourceTree = "<group>"; };
		F96D439C08F272B7004A47F5 /* pkgMkIndex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgMkIndex.test; sourceTree = "<group>"; };
		F96D439D08F272B7004A47F5 /* platform.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = platform.test; sourceTree = "<group>"; };
		F96D439E08F272B7004A47F5 /* proc-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "proc-old.test"; sourceTree = "<group>"; };
		F96D439F08F272B7004A47F5 /* proc.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = proc.test; sourceTree = "<group>"; };
		F96D43A008F272B7004A47F5 /* pwd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pwd.test; sourceTree = "<group>"; };
		F96D43A108F272B7004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D43A208F272B7004A47F5 /* reg.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = reg.test; sourceTree = "<group>"; };
		F96D43A308F272B7004A47F5 /* regexp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexp.test; sourceTree = "<group>"; };
		F96D43A408F272B7004A47F5 /* regexpComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexpComp.test; sourceTree = "<group>"; };
		F96D43A508F272B7004A47F5 /* registry.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = registry.test; sourceTree = "<group>"; };
		F96D43A608F272B7004A47F5 /* remote.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = remote.tcl; sourceTree = "<group>"; };
		F96D43A708F272B7004A47F5 /* rename.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = rename.test; sourceTree = "<group>"; };
		F96D43A808F272B7004A47F5 /* result.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = result.test; sourceTree = "<group>"; };
		F96D43A908F272B7004A47F5 /* safe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safe.test; sourceTree = "<group>"; };
		F96D43AA08F272B7004A47F5 /* scan.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scan.test; sourceTree = "<group>"; };
		F96D43AB08F272B7004A47F5 /* security.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = security.test; sourceTree = "<group>"; };
		F96D43AC08F272B7004A47F5 /* set-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "set-old.test"; sourceTree = "<group>"; };
		F96D43AD08F272B7004A47F5 /* set.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = set.test; sourceTree = "<group>"; };
		F96D43AE08F272B7004A47F5 /* socket.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = socket.test; sourceTree = "<group>"; };
		F96D43AF08F272B7004A47F5 /* source.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = source.test; sourceTree = "<group>"; };
		F96D43B008F272B7004A47F5 /* split.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = split.test; sourceTree = "<group>"; };
		F96D43B108F272B7004A47F5 /* stack.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stack.test; sourceTree = "<group>"; };
		F96D43B208F272B7004A47F5 /* string.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = string.test; sourceTree = "<group>"; };
		F96D43B308F272B7004A47F5 /* stringComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stringComp.test; sourceTree = "<group>"; };
		F96D43B408F272B7004A47F5 /* stringObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stringObj.test; sourceTree = "<group>"; };
		F96D43B508F272B7004A47F5 /* subst.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = subst.test; sourceTree = "<group>"; };
		F96D43B608F272B7004A47F5 /* switch.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = switch.test; sourceTree = "<group>"; };
		F96D43B708F272B7004A47F5 /* tcltest.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcltest.test; sourceTree = "<group>"; };
		F96D43B808F272B7004A47F5 /* thread.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = thread.test; sourceTree = "<group>"; };
		F96D43B908F272B7004A47F5 /* timer.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = timer.test; sourceTree = "<group>"; };
		F96D43BA08F272B7004A47F5 /* tm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tm.test; sourceTree = "<group>"; };
		F96D43BB08F272B7004A47F5 /* trace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = trace.test; sourceTree = "<group>"; };
		F96D43BC08F272B7004A47F5 /* unixFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixFCmd.test; sourceTree = "<group>"; };
		F96D43BD08F272B7004A47F5 /* unixFile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixFile.test; sourceTree = "<group>"; };
		F96D43BE08F272B7004A47F5 /* unixInit.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixInit.test; sourceTree = "<group>"; };
		F96D43BF08F272B7004A47F5 /* unixNotfy.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixNotfy.test; sourceTree = "<group>"; };
		F96D43C008F272B7004A47F5 /* unknown.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unknown.test; sourceTree = "<group>"; };
		F96D43C108F272B7004A47F5 /* unload.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unload.test; sourceTree = "<group>"; };
		F96D43C208F272B7004A47F5 /* uplevel.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uplevel.test; sourceTree = "<group>"; };
		F96D43C308F272B7004A47F5 /* upvar.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = upvar.test; sourceTree = "<group>"; };
		F96D43C408F272B7004A47F5 /* utf.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = utf.test; sourceTree = "<group>"; };
		F96D43C508F272B7004A47F5 /* util.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = util.test; sourceTree = "<group>"; };
		F96D43C608F272B7004A47F5 /* var.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = var.test; sourceTree = "<group>"; };
		F96D43C708F272B7004A47F5 /* while-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "while-old.test"; sourceTree = "<group>"; };
		F96D43C808F272B7004A47F5 /* while.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = while.test; sourceTree = "<group>"; };
		F96D43C908F272B7004A47F5 /* winConsole.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winConsole.test; sourceTree = "<group>"; };
		F96D43CA08F272B7004A47F5 /* winDde.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winDde.test; sourceTree = "<group>"; };
		F96D43CB08F272B7004A47F5 /* winFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFCmd.test; sourceTree = "<group>"; };
		F96D43CC08F272B7004A47F5 /* winFile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFile.test; sourceTree = "<group>"; };
		F96D43CD08F272B7004A47F5 /* winNotify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winNotify.test; sourceTree = "<group>"; };
		F96D43CE08F272B7004A47F5 /* winPipe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winPipe.test; sourceTree = "<group>"; };
		F96D43CF08F272B7004A47F5 /* winTime.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winTime.test; sourceTree = "<group>"; };
		F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = checkLibraryDoc.tcl; sourceTree = "<group>"; };
		F96D43D208F272B8004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F96D43D308F272B8004A47F5 /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = "<group>"; };
		F96D442508F272B8004A47F5 /* genStubs.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = genStubs.tcl; sourceTree = "<group>"; };
		F96D442708F272B8004A47F5 /* index.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = index.tcl; sourceTree = "<group>"; };
		F96D442808F272B8004A47F5 /* installData.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = installData.tcl; sourceTree = "<group>"; };
		F96D442908F272B8004A47F5 /* loadICU.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = loadICU.tcl; sourceTree = "<group>"; };
		F96D442A08F272B8004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F96D442B08F272B8004A47F5 /* makeTestCases.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = makeTestCases.tcl; sourceTree = "<group>"; };
		F96D442C08F272B8004A47F5 /* man2help.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2help.tcl; sourceTree = "<group>"; };
		F96D442D08F272B8004A47F5 /* man2help2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2help2.tcl; sourceTree = "<group>"; };
		F96D442E08F272B8004A47F5 /* man2html.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html.tcl; sourceTree = "<group>"; };
		F96D442F08F272B8004A47F5 /* man2html1.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html1.tcl; sourceTree = "<group>"; };
		F96D443008F272B8004A47F5 /* man2html2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html2.tcl; sourceTree = "<group>"; };
		F96D443108F272B8004A47F5 /* man2tcl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = man2tcl.c; sourceTree = "<group>"; };
		F96D443208F272B8004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D443308F272B8004A47F5 /* regexpTestLib.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexpTestLib.tcl; sourceTree = "<group>"; };
		F96D443508F272B8004A47F5 /* tcl.hpj.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.hpj.in; sourceTree = "<group>"; };
		F96D443908F272B9004A47F5 /* tcltk-man2html.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "tcltk-man2html.tcl"; sourceTree = "<group>"; };
		F96D443A08F272B9004A47F5 /* tclZIC.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclZIC.tcl; sourceTree = "<group>"; };
		F96D443B08F272B9004A47F5 /* uniClass.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniClass.tcl; sourceTree = "<group>"; };
		F96D443C08F272B9004A47F5 /* uniParse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniParse.tcl; sourceTree = "<group>"; };
		F96D444008F272B9004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
		F96D444108F272B9004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F96D444208F272B9004A47F5 /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = "<group>"; };
		F96D444408F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F96D444508F272B9004A47F5 /* pkga.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkga.c; sourceTree = "<group>"; };
		F96D444608F272B9004A47F5 /* pkgb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgb.c; sourceTree = "<group>"; };
		F96D444708F272B9004A47F5 /* pkgc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgc.c; sourceTree = "<group>"; };
		F96D444808F272B9004A47F5 /* pkgd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgd.c; sourceTree = "<group>"; };
		F96D444908F272B9004A47F5 /* pkge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkge.c; sourceTree = "<group>"; };
		F96D444B08F272B9004A47F5 /* pkgua.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgua.c; sourceTree = "<group>"; };
		F96D444C08F272B9004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D444D08F272B9004A47F5 /* install-sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "install-sh"; sourceTree = "<group>"; };
		F96D444E08F272B9004A47F5 /* installManPage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = installManPage; sourceTree = "<group>"; };
		F96D444F08F272B9004A47F5 /* ldAix */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ldAix; sourceTree = "<group>"; };
		F96D445008F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F96D445208F272B9004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D445308F272B9004A47F5 /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
		F96D445408F272B9004A47F5 /* tcl.spec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.spec; sourceTree = "<group>"; };
		F96D445508F272B9004A47F5 /* tclAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAppInit.c; sourceTree = "<group>"; };
		F96D445608F272B9004A47F5 /* tclConfig.h.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = tclConfig.h.in; sourceTree = "<group>"; };
		F96D445708F272B9004A47F5 /* tclConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tclConfig.sh.in; sourceTree = "<group>"; };
		F96D445808F272B9004A47F5 /* tclLoadAix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadAix.c; sourceTree = "<group>"; };
		F96D445908F272B9004A47F5 /* tclLoadDl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadDl.c; sourceTree = "<group>"; };
		F96D445B08F272B9004A47F5 /* tclLoadDyld.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadDyld.c; sourceTree = "<group>"; };
		F96D445C08F272B9004A47F5 /* tclLoadNext.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadNext.c; sourceTree = "<group>"; };
		F96D445D08F272B9004A47F5 /* tclLoadOSF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadOSF.c; sourceTree = "<group>"; };
		F96D445E08F272B9004A47F5 /* tclLoadShl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadShl.c; sourceTree = "<group>"; };
		F96D445F08F272B9004A47F5 /* tclUnixChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixChan.c; sourceTree = "<group>"; };
		F96D446008F272B9004A47F5 /* tclUnixEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixEvent.c; sourceTree = "<group>"; };
		F96D446108F272B9004A47F5 /* tclUnixFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixFCmd.c; sourceTree = "<group>"; };
		F96D446208F272B9004A47F5 /* tclUnixFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixFile.c; sourceTree = "<group>"; };
		F96D446308F272B9004A47F5 /* tclUnixInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixInit.c; sourceTree = "<group>"; };
		F96D446408F272B9004A47F5 /* tclUnixNotfy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixNotfy.c; sourceTree = "<group>"; };
		F96D446508F272B9004A47F5 /* tclUnixPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixPipe.c; sourceTree = "<group>"; };
		F96D446608F272B9004A47F5 /* tclUnixPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclUnixPort.h; sourceTree = "<group>"; };
		F96D446708F272B9004A47F5 /* tclUnixSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixSock.c; sourceTree = "<group>"; };
		F96D446808F272B9004A47F5 /* tclUnixTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTest.c; sourceTree = "<group>"; };
		F96D446908F272B9004A47F5 /* tclUnixThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixThrd.c; sourceTree = "<group>"; };
		F96D446B08F272B9004A47F5 /* tclUnixTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTime.c; sourceTree = "<group>"; };
		F96D446C08F272B9004A47F5 /* tclXtNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtNotify.c; sourceTree = "<group>"; };
		F96D446D08F272B9004A47F5 /* tclXtTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtTest.c; sourceTree = "<group>"; };
		F96D447008F272BA004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
		F96D447108F272BA004A47F5 /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = "<group>"; };
		F96D447208F272BA004A47F5 /* cat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cat.c; sourceTree = "<group>"; };
		F96D447308F272BA004A47F5 /* coffbase.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = coffbase.txt; sourceTree = "<group>"; };
		F96D447408F272BA004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F96D447508F272BA004A47F5 /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = "<group>"; };
		F96D447708F272BA004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F96D447808F272BA004A47F5 /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = "<group>"; };
		F96D447908F272BA004A47F5 /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = "<group>"; };
		F96D447A08F272BA004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D447C08F272BA004A47F5 /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = "<group>"; };
		F96D447D08F272BA004A47F5 /* stub16.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stub16.c; sourceTree = "<group>"; };
		F96D447E08F272BA004A47F5 /* tcl.dsp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.dsp; sourceTree = "<group>"; };
		F96D447F08F272BA004A47F5 /* tcl.dsw */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.dsw; sourceTree = "<group>"; };
		F96D448008F272BA004A47F5 /* tcl.hpj.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.hpj.in; sourceTree = "<group>"; };
		F96D448108F272BA004A47F5 /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
		F96D448208F272BA004A47F5 /* tcl.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.rc; sourceTree = "<group>"; };
		F96D448308F272BA004A47F5 /* tclAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAppInit.c; sourceTree = "<group>"; };
		F96D448408F272BA004A47F5 /* tclConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tclConfig.sh.in; sourceTree = "<group>"; };
		F96D448608F272BA004A47F5 /* tclsh.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tclsh.rc; sourceTree = "<group>"; };
		F96D448708F272BA004A47F5 /* tclWin32Dll.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWin32Dll.c; sourceTree = "<group>"; };
		F96D448808F272BA004A47F5 /* tclWinChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinChan.c; sourceTree = "<group>"; };
		F96D448908F272BA004A47F5 /* tclWinConsole.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinConsole.c; sourceTree = "<group>"; };
		F96D448A08F272BA004A47F5 /* tclWinDde.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinDde.c; sourceTree = "<group>"; };
		F96D448B08F272BA004A47F5 /* tclWinError.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinError.c; sourceTree = "<group>"; };
		F96D448C08F272BA004A47F5 /* tclWinFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinFCmd.c; sourceTree = "<group>"; };
		F96D448D08F272BA004A47F5 /* tclWinFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinFile.c; sourceTree = "<group>"; };
		F96D448E08F272BA004A47F5 /* tclWinInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinInit.c; sourceTree = "<group>"; };
		F96D448F08F272BA004A47F5 /* tclWinInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinInt.h; sourceTree = "<group>"; };
		F96D449008F272BA004A47F5 /* tclWinLoad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinLoad.c; sourceTree = "<group>"; };
		F96D449108F272BA004A47F5 /* tclWinNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinNotify.c; sourceTree = "<group>"; };
		F96D449208F272BA004A47F5 /* tclWinPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinPipe.c; sourceTree = "<group>"; };
		F96D449308F272BA004A47F5 /* tclWinPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinPort.h; sourceTree = "<group>"; };
		F96D449408F272BA004A47F5 /* tclWinReg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinReg.c; sourceTree = "<group>"; };
		F96D449508F272BA004A47F5 /* tclWinSerial.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSerial.c; sourceTree = "<group>"; };
		F96D449608F272BA004A47F5 /* tclWinSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSock.c; sourceTree = "<group>"; };
		F96D449708F272BA004A47F5 /* tclWinTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTest.c; sourceTree = "<group>"; };
		F96D449808F272BA004A47F5 /* tclWinThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinThrd.c; sourceTree = "<group>"; };
		F96D449A08F272BA004A47F5 /* tclWinTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTime.c; sourceTree = "<group>"; };
		F974D56C0FBE7D6300BF728B /* http11.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http11.test; sourceTree = "<group>"; };
		F974D56D0FBE7D6300BF728B /* httpd11.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpd11.tcl; sourceTree = "<group>"; };
		F974D5720FBE7DC600BF728B /* coroutine.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = coroutine.n; sourceTree = "<group>"; };
		F974D5760FBE7E1900BF728B /* tailcall.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tailcall.n; sourceTree = "<group>"; };
		F974D5770FBE7E6100BF728B /* coroutine.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = coroutine.test; sourceTree = "<group>"; };
		F974D5780FBE7E6100BF728B /* tailcall.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tailcall.test; sourceTree = "<group>"; };
		F974D5790FBE7E9C00BF728B /* tcl.pc.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.pc.in; sourceTree = "<group>"; };
		F97AE7F10B65C1E900310EA2 /* Tcl-Common.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Common.xcconfig"; sourceTree = "<group>"; };
		F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Release.xcconfig"; sourceTree = "<group>"; };
		F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Debug.xcconfig"; sourceTree = "<group>"; };
		F9903CAF094FAADA004613E9 /* tclTomMath.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclTomMath.decls; sourceTree = "<group>"; };
		F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMathDecls.h; sourceTree = "<group>"; };
		F99D61180EF5573A00BBFE01 /* TclZlib.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TclZlib.3; sourceTree = "<group>"; };
		F9A3084B08F2D4CE00BAE1AB /* tclsh */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tclsh; sourceTree = BUILT_PRODUCTS_DIR; };
		F9A3084E08F2D4F400BAE1AB /* Tcl.framework */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.framework; path = Tcl.framework; sourceTree = BUILT_PRODUCTS_DIR; };
		F9A493240CEBF38300B78AE2 /* chanio.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = chanio.test; sourceTree = "<group>"; };
		F9ECB1120B26521500A28025 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
		F9ECB1130B26521500A28025 /* platform.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = platform.tcl; sourceTree = "<group>"; };
		F9ECB1140B26521500A28025 /* shell.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = shell.tcl; sourceTree = "<group>"; };
		F9ECB1CA0B2652D300A28025 /* apply.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = apply.test; sourceTree = "<group>"; };
		F9ECB1CB0B26534C00A28025 /* mathop.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = mathop.test; sourceTree = "<group>"; };
		F9ECB1E10B26543C00A28025 /* platform_shell.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = platform_shell.n; sourceTree = "<group>"; };
		F9ECB1E20B26543C00A28025 /* platform.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = platform.n; sourceTree = "<group>"; };
		F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = tclDTrace.d; sourceTree = "<group>"; };
		F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixCompat.c; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		8DD76FAD0486AB0100D96B5E /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
				F966C07508F2820D005CB29B /* CoreFoundation.framework in Frameworks */,
				F96437E70EF0D652003F468E /* libz.dylib in Frameworks */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
		08FB7794FE84155DC02AAC07 /* Tcl */ = {
			isa = PBXGroup;
			children = (
				F96D3DF608F27169004A47F5 /* Tcl Sources */,
				F966C06F08F281DC005CB29B /* Frameworks */,
				1AB674ADFE9D54B511CA2CBB /* Products */,
			);
			comments = "Copyright (c) 2004-2009 Daniel A. Steffen <das@users.sourceforge.net>\nCopyright 2008-2009, Apple Inc.\n\nSee the file \"license.terms\" for information on usage and redistribution of\nthis file, and for a DISCLAIMER OF ALL WARRANTIES.\n\n";
			name = Tcl;
			path = .;
			sourceTree = SOURCE_ROOT;
		};
		1AB674ADFE9D54B511CA2CBB /* Products */ = {
			isa = PBXGroup;
			children = (
				F9A3084B08F2D4CE00BAE1AB /* tclsh */,
				8DD76FB20486AB0100D96B5E /* tcltest */,
				F9A3084E08F2D4F400BAE1AB /* Tcl.framework */,
			);
			includeInIndex = 0;
			name = Products;
			sourceTree = "<group>";
		};
		F9183E690EFC81560030B814 /* pkgs */ = {
			isa = PBXGroup;
			children = (
				F9183E6A0EFC81560030B814 /* README */,
				F946FB8B0FBE3AED00CD6495 /* itcl */,
				F9183E8F0EFC817B0030B814 /* tdbc */,
			);
			path = pkgs;
			sourceTree = "<group>";
		};
		F966C06F08F281DC005CB29B /* Frameworks */ = {
			isa = PBXGroup;
			children = (
				F966C07408F2820D005CB29B /* CoreFoundation.framework */,
				F96437E60EF0D652003F468E /* libz.dylib */,
			);
			name = Frameworks;
			sourceTree = "<group>";
		};
		F96D3DF608F27169004A47F5 /* Tcl Sources */ = {
			isa = PBXGroup;
			children = (
				F96D3EC908F272A7004A47F5 /* generic */,
				F96D432C08F272B4004A47F5 /* macosx */,
				F96D443E08F272B9004A47F5 /* unix */,
				F96D425C08F272B2004A47F5 /* libtommath */,
				F96D446E08F272B9004A47F5 /* win */,
				F96D3F3808F272A7004A47F5 /* library */,
				F96D434408F272B5004A47F5 /* tests */,
				F96D3DFC08F272A4004A47F5 /* doc */,
				F96D43D008F272B8004A47F5 /* tools */,
				F9183E690EFC81560030B814 /* pkgs */,
				F96D3DFA08F272A4004A47F5 /* ChangeLog */,
				F96D3DFB08F272A4004A47F5 /* changes */,
				F96D434308F272B5004A47F5 /* README */,
				F96D432B08F272B4004A47F5 /* license.terms */,
			);
			name = "Tcl Sources";
			sourceTree = TCL_SRCROOT;
		};
		F96D3DFC08F272A4004A47F5 /* doc */ = {
			isa = PBXGroup;
			children = (
				F96D3DFD08F272A4004A47F5 /* Access.3 */,
				F96D3DFE08F272A4004A47F5 /* AddErrInfo.3 */,
				F96D3DFF08F272A4004A47F5 /* after.n */,
				F96D3E0008F272A4004A47F5 /* Alloc.3 */,
				F96D3E0108F272A4004A47F5 /* AllowExc.3 */,
				F96D3E0208F272A4004A47F5 /* append.n */,
				F96D3E0308F272A4004A47F5 /* AppInit.3 */,
				F96D3E0408F272A5004A47F5 /* array.n */,
				F96D3E0508F272A5004A47F5 /* AssocData.3 */,
				F96D3E0608F272A5004A47F5 /* Async.3 */,
				F96D3E0708F272A5004A47F5 /* BackgdErr.3 */,
				F96D3E0808F272A5004A47F5 /* Backslash.3 */,
				F96D3E0908F272A5004A47F5 /* bgerror.n */,
				F96D3E0A08F272A5004A47F5 /* binary.n */,
				F96D3E0B08F272A5004A47F5 /* BoolObj.3 */,
				F96D3E0C08F272A5004A47F5 /* break.n */,
				F96D3E0D08F272A5004A47F5 /* ByteArrObj.3 */,
				F96D3E0E08F272A5004A47F5 /* CallDel.3 */,
				F96D3E0F08F272A5004A47F5 /* case.n */,
				F96D3E1008F272A5004A47F5 /* catch.n */,
				F96D3E1108F272A5004A47F5 /* cd.n */,
				F96D3E1208F272A5004A47F5 /* chan.n */,
				F96D3E1308F272A5004A47F5 /* ChnlStack.3 */,
				F93599CF0DF1F87F00E04F67 /* Class.3 */,
				F93599D00DF1F89E00E04F67 /* class.n */,
				F96D3E1408F272A5004A47F5 /* clock.n */,
				F96D3E1508F272A5004A47F5 /* close.n */,
				F96D3E1608F272A5004A47F5 /* CmdCmplt.3 */,
				F96D3E1708F272A5004A47F5 /* Concat.3 */,
				F96D3E1808F272A5004A47F5 /* concat.n */,
				F96D3E1908F272A5004A47F5 /* continue.n */,
				F93599D20DF1F8DF00E04F67 /* copy.n */,
				F974D5720FBE7DC600BF728B /* coroutine.n */,
				F96D3E1A08F272A5004A47F5 /* CrtChannel.3 */,
				F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */,
				F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */,
				F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */,
				F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */,
				F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */,
				F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */,
				F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */,
				F96D3E2208F272A5004A47F5 /* CrtAlias.3 */,
				F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */,
				F96D3E2408F272A5004A47F5 /* CrtTrace.3 */,
				F96D3E2508F272A5004A47F5 /* dde.n */,
				F93599D30DF1F8F500E04F67 /* define.n */,
				F96D3E2608F272A5004A47F5 /* DetachPids.3 */,
				F96D3E2708F272A5004A47F5 /* dict.n */,
				F96D3E2808F272A5004A47F5 /* DictObj.3 */,
				F96D3E2908F272A5004A47F5 /* DoOneEvent.3 */,
				F96D3E2A08F272A5004A47F5 /* DoubleObj.3 */,
				F96D3E2B08F272A5004A47F5 /* DoWhenIdle.3 */,
				F96D3E2C08F272A5004A47F5 /* DString.3 */,
				F96D3E2D08F272A5004A47F5 /* DumpActiveMemory.3 */,
				F96D3E2E08F272A5004A47F5 /* Encoding.3 */,
				F96D3E2F08F272A5004A47F5 /* encoding.n */,
				F96D3E3008F272A5004A47F5 /* Ensemble.3 */,
				F96D3E3108F272A5004A47F5 /* Environment.3 */,
				F96D3E3208F272A5004A47F5 /* eof.n */,
				F96D3E3308F272A5004A47F5 /* error.n */,
				F96D3E3408F272A5004A47F5 /* Eval.3 */,
				F96D3E3508F272A5004A47F5 /* eval.n */,
				F96D3E3608F272A5004A47F5 /* exec.n */,
				F96D3E3708F272A5004A47F5 /* Exit.3 */,
				F96D3E3808F272A5004A47F5 /* exit.n */,
				F96D3E3908F272A5004A47F5 /* expr.n */,
				F96D3E3A08F272A5004A47F5 /* ExprLong.3 */,
				F96D3E3B08F272A5004A47F5 /* ExprLongObj.3 */,
				F96D3E3C08F272A5004A47F5 /* fblocked.n */,
				F96D3E3D08F272A5004A47F5 /* fconfigure.n */,
				F96D3E3E08F272A5004A47F5 /* fcopy.n */,
				F96D3E3F08F272A5004A47F5 /* file.n */,
				F96D3E4008F272A5004A47F5 /* fileevent.n */,
				F96D3E4108F272A5004A47F5 /* filename.n */,
				F96D3E4208F272A5004A47F5 /* FileSystem.3 */,
				F96D3E4308F272A5004A47F5 /* FindExec.3 */,
				F96D3E4408F272A5004A47F5 /* flush.n */,
				F96D3E4508F272A5004A47F5 /* for.n */,
				F96D3E4608F272A5004A47F5 /* foreach.n */,
				F96D3E4708F272A5004A47F5 /* format.n */,
				F96D3E4808F272A5004A47F5 /* GetCwd.3 */,
				F96D3E4908F272A5004A47F5 /* GetHostName.3 */,
				F96D3E4A08F272A5004A47F5 /* GetIndex.3 */,
				F96D3E4B08F272A5004A47F5 /* GetInt.3 */,
				F96D3E4C08F272A5004A47F5 /* GetOpnFl.3 */,
				F96D3E4D08F272A5004A47F5 /* gets.n */,
				F96D3E4E08F272A5004A47F5 /* GetStdChan.3 */,
				F96D3E4F08F272A5004A47F5 /* GetTime.3 */,
				F96D3E5008F272A5004A47F5 /* GetVersion.3 */,
				F96D3E5108F272A5004A47F5 /* glob.n */,
				F96D3E5208F272A6004A47F5 /* global.n */,
				F96D3E5308F272A6004A47F5 /* Hash.3 */,
				F96D3E5408F272A6004A47F5 /* history.n */,
				F96D3E5508F272A6004A47F5 /* http.n */,
				F96D3E5608F272A6004A47F5 /* if.n */,
				F96D3E5708F272A6004A47F5 /* incr.n */,
				F96D3E5808F272A6004A47F5 /* info.n */,
				F96D3E5908F272A6004A47F5 /* Init.3 */,
				F96D3E5A08F272A6004A47F5 /* InitStubs.3 */,
				F96D3E5B08F272A6004A47F5 /* Interp.3 */,
				F96D3E5C08F272A6004A47F5 /* interp.n */,
				F96D3E5D08F272A6004A47F5 /* IntObj.3 */,
				F96D3E5E08F272A6004A47F5 /* join.n */,
				F96D3E5F08F272A6004A47F5 /* lappend.n */,
				F96D3E6008F272A6004A47F5 /* lassign.n */,
				F96D3E6108F272A6004A47F5 /* library.n */,
				F96D3E6208F272A6004A47F5 /* Limit.3 */,
				F96D3E6308F272A6004A47F5 /* lindex.n */,
				F96D3E6408F272A6004A47F5 /* LinkVar.3 */,
				F96D3E6508F272A6004A47F5 /* linsert.n */,
				F96D3E6608F272A6004A47F5 /* list.n */,
				F96D3E6708F272A6004A47F5 /* ListObj.3 */,
				F96D3E6808F272A6004A47F5 /* llength.n */,
				F96D3E6908F272A6004A47F5 /* load.n */,
				F96D3E6A08F272A6004A47F5 /* lrange.n */,
				F96D3E6B08F272A6004A47F5 /* lrepeat.n */,
				F96D3E6C08F272A6004A47F5 /* lreplace.n */,
				F96D3E6D08F272A6004A47F5 /* lsearch.n */,
				F96D3E6E08F272A6004A47F5 /* lset.n */,
				F96D3E6F08F272A6004A47F5 /* lsort.n */,
				F96D3E7008F272A6004A47F5 /* man.macros */,
				F96D3E7108F272A6004A47F5 /* mathfunc.n */,
				F96D3E7208F272A6004A47F5 /* memory.n */,
				F93599D40DF1F91900E04F67 /* Method.3 */,
				F96D3E7308F272A6004A47F5 /* msgcat.n */,
				F93599D50DF1F93700E04F67 /* my.n */,
				F96D3E7408F272A6004A47F5 /* Namespace.3 */,
				F96D3E7508F272A6004A47F5 /* namespace.n */,
				F93599D60DF1F95000E04F67 /* next.n */,
				F96D3E7608F272A6004A47F5 /* Notifier.3 */,
				F96D3E7708F272A6004A47F5 /* Object.3 */,
				F93599D70DF1F96800E04F67 /* object.n */,
				F96D3E7808F272A6004A47F5 /* ObjectType.3 */,
				F96D3E7908F272A6004A47F5 /* open.n */,
				F96D3E7A08F272A6004A47F5 /* OpenFileChnl.3 */,
				F96D3E7B08F272A6004A47F5 /* OpenTcp.3 */,
				F96D3E7C08F272A6004A47F5 /* package.n */,
				F96D3E7D08F272A6004A47F5 /* packagens.n */,
				F96D3E7E08F272A6004A47F5 /* Panic.3 */,
				F96D3E7F08F272A6004A47F5 /* ParseCmd.3 */,
				F96D3E8008F272A6004A47F5 /* pid.n */,
				F96D3E8108F272A6004A47F5 /* pkgMkIndex.n */,
				F96D3E8208F272A6004A47F5 /* PkgRequire.3 */,
				F9ECB1E10B26543C00A28025 /* platform_shell.n */,
				F9ECB1E20B26543C00A28025 /* platform.n */,
				F96D3E8308F272A6004A47F5 /* Preserve.3 */,
				F96D3E8408F272A6004A47F5 /* PrintDbl.3 */,
				F96D3E8508F272A6004A47F5 /* proc.n */,
				F96D3E8608F272A6004A47F5 /* puts.n */,
				F96D3E8708F272A6004A47F5 /* pwd.n */,
				F96D3E8808F272A6004A47F5 /* re_syntax.n */,
				F96D3E8908F272A6004A47F5 /* read.n */,
				F96D3E8A08F272A6004A47F5 /* RecEvalObj.3 */,
				F96D3E8B08F272A6004A47F5 /* RecordEval.3 */,
				F96D3E8C08F272A6004A47F5 /* RegConfig.3 */,
				F96D3E8D08F272A6004A47F5 /* RegExp.3 */,
				F96D3E8E08F272A6004A47F5 /* regexp.n */,
				F96D3E8F08F272A6004A47F5 /* registry.n */,
				F96D3E9008F272A6004A47F5 /* regsub.n */,
				F96D3E9108F272A6004A47F5 /* rename.n */,
				F96D3E9208F272A6004A47F5 /* return.n */,
				F96D3E9308F272A6004A47F5 /* safe.n */,
				F96D3E9408F272A6004A47F5 /* SaveResult.3 */,
				F96D3E9508F272A6004A47F5 /* scan.n */,
				F96D3E9608F272A6004A47F5 /* seek.n */,
				F93599D80DF1F98300E04F67 /* self.n */,
				F96D3E9708F272A6004A47F5 /* set.n */,
				F96D3E9808F272A6004A47F5 /* SetChanErr.3 */,
				F96D3E9908F272A6004A47F5 /* SetErrno.3 */,
				F96D3E9A08F272A6004A47F5 /* SetRecLmt.3 */,
				F96D3E9B08F272A7004A47F5 /* SetResult.3 */,
				F96D3E9C08F272A7004A47F5 /* SetVar.3 */,
				F96D3E9D08F272A7004A47F5 /* Signal.3 */,
				F96D3E9E08F272A7004A47F5 /* Sleep.3 */,
				F96D3E9F08F272A7004A47F5 /* socket.n */,
				F96D3EA008F272A7004A47F5 /* source.n */,
				F96D3EA108F272A7004A47F5 /* SourceRCFile.3 */,
				F96D3EA208F272A7004A47F5 /* split.n */,
				F96D3EA308F272A7004A47F5 /* SplitList.3 */,
				F96D3EA408F272A7004A47F5 /* SplitPath.3 */,
				F96D3EA508F272A7004A47F5 /* StaticPkg.3 */,
				F96D3EA608F272A7004A47F5 /* StdChannels.3 */,
				F96D3EA708F272A7004A47F5 /* string.n */,
				F96D3EA808F272A7004A47F5 /* StringObj.3 */,
				F96D3EA908F272A7004A47F5 /* StrMatch.3 */,
				F96D3EAA08F272A7004A47F5 /* subst.n */,
				F96D3EAB08F272A7004A47F5 /* SubstObj.3 */,
				F96D3EAC08F272A7004A47F5 /* switch.n */,
				F974D5760FBE7E1900BF728B /* tailcall.n */,
				F96D3EAD08F272A7004A47F5 /* Tcl.n */,
				F99D61180EF5573A00BBFE01 /* TclZlib.3 */,
				F96D3EAE08F272A7004A47F5 /* Tcl_Main.3 */,
				F96D3EAF08F272A7004A47F5 /* TCL_MEM_DEBUG.3 */,
				F96D3EB008F272A7004A47F5 /* tclsh.1 */,
				F96D3EB108F272A7004A47F5 /* tcltest.n */,
				F96D3EB208F272A7004A47F5 /* tclvars.n */,
				F96D3EB308F272A7004A47F5 /* tell.n */,
				F96D3EB408F272A7004A47F5 /* Thread.3 */,
				F9183E640EFC80CD0030B814 /* throw.n */,
				F96D3EB508F272A7004A47F5 /* time.n */,
				F96D3EB608F272A7004A47F5 /* tm.n */,
				F96D3EB708F272A7004A47F5 /* ToUpper.3 */,
				F96D3EB808F272A7004A47F5 /* trace.n */,
				F96D3EB908F272A7004A47F5 /* TraceCmd.3 */,
				F96D3EBA08F272A7004A47F5 /* TraceVar.3 */,
				F96D3EBB08F272A7004A47F5 /* Translate.3 */,
				F9183E650EFC80D70030B814 /* try.n */,
				F96D3EBC08F272A7004A47F5 /* UniCharIsAlpha.3 */,
				F96D3EBD08F272A7004A47F5 /* unknown.n */,
				F96D3EBE08F272A7004A47F5 /* unload.n */,
				F96D3EBF08F272A7004A47F5 /* unset.n */,
				F96D3EC008F272A7004A47F5 /* update.n */,
				F96D3EC108F272A7004A47F5 /* uplevel.n */,
				F96D3EC208F272A7004A47F5 /* UpVar.3 */,
				F96D3EC308F272A7004A47F5 /* upvar.n */,
				F96D3EC408F272A7004A47F5 /* Utf.3 */,
				F96D3EC508F272A7004A47F5 /* variable.n */,
				F96D3EC608F272A7004A47F5 /* vwait.n */,
				F96D3EC708F272A7004A47F5 /* while.n */,
				F96D3EC808F272A7004A47F5 /* WrongNumArgs.3 */,
				F915432D0EF201EE0032D1E8 /* zlib.n */,
			);
			path = doc;
			sourceTree = "<group>";
		};
		F96D3EC908F272A7004A47F5 /* generic */ = {
			isa = PBXGroup;
			children = (
				F96D3ECA08F272A7004A47F5 /* README */,
				F96D3ECB08F272A7004A47F5 /* regc_color.c */,
				F96D3ECC08F272A7004A47F5 /* regc_cvec.c */,
				F96D3ECD08F272A7004A47F5 /* regc_lex.c */,
				F96D3ECE08F272A7004A47F5 /* regc_locale.c */,
				F96D3ECF08F272A7004A47F5 /* regc_nfa.c */,
				F96D3ED008F272A7004A47F5 /* regcomp.c */,
				F96D3ED108F272A7004A47F5 /* regcustom.h */,
				F96D3ED208F272A7004A47F5 /* rege_dfa.c */,
				F96D3ED308F272A7004A47F5 /* regerror.c */,
				F96D3ED408F272A7004A47F5 /* regerrs.h */,
				F96D3ED508F272A7004A47F5 /* regex.h */,
				F96D3ED608F272A7004A47F5 /* regexec.c */,
				F96D3ED708F272A7004A47F5 /* regfree.c */,
				F96D3ED808F272A7004A47F5 /* regfronts.c */,
				F96D3ED908F272A7004A47F5 /* regguts.h */,
				F96D3EDA08F272A7004A47F5 /* tcl.decls */,
				F96D3EDB08F272A7004A47F5 /* tcl.h */,
				F96D3EDC08F272A7004A47F5 /* tclAlloc.c */,
				F96D3EDD08F272A7004A47F5 /* tclAsync.c */,
				F96D3EDE08F272A7004A47F5 /* tclBasic.c */,
				F96D3EDF08F272A7004A47F5 /* tclBinary.c */,
				F96D3EE008F272A7004A47F5 /* tclCkalloc.c */,
				F96D3EE108F272A7004A47F5 /* tclClock.c */,
				F96D3EE208F272A7004A47F5 /* tclCmdAH.c */,
				F96D3EE308F272A7004A47F5 /* tclCmdIL.c */,
				F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */,
				F96D3EE508F272A7004A47F5 /* tclCompCmds.c */,
				F96D3EE608F272A7004A47F5 /* tclCompExpr.c */,
				F96D3EE708F272A7004A47F5 /* tclCompile.c */,
				F96D3EE808F272A7004A47F5 /* tclCompile.h */,
				F96D3EE908F272A7004A47F5 /* tclConfig.c */,
				F96D3EEA08F272A7004A47F5 /* tclDate.c */,
				F96D3EEB08F272A7004A47F5 /* tclDecls.h */,
				F96D3EEC08F272A7004A47F5 /* tclDictObj.c */,
				F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */,
				F96D3EED08F272A7004A47F5 /* tclEncoding.c */,
				F96D3EEE08F272A7004A47F5 /* tclEnv.c */,
				F96D3EEF08F272A7004A47F5 /* tclEvent.c */,
				F96D3EF008F272A7004A47F5 /* tclExecute.c */,
				F96D3EF108F272A7004A47F5 /* tclFCmd.c */,
				F96D3EF208F272A7004A47F5 /* tclFileName.c */,
				F96D3EF308F272A7004A47F5 /* tclFileSystem.h */,
				F96D3EF408F272A7004A47F5 /* tclGet.c */,
				F96D3EF508F272A7004A47F5 /* tclGetDate.y */,
				F96D3EF608F272A7004A47F5 /* tclHash.c */,
				F96D3EF708F272A7004A47F5 /* tclHistory.c */,
				F96D3EF808F272A7004A47F5 /* tclIndexObj.c */,
				F96D3EF908F272A7004A47F5 /* tclInt.decls */,
				F96D3EFA08F272A7004A47F5 /* tclInt.h */,
				F96D3EFB08F272A7004A47F5 /* tclIntDecls.h */,
				F96D3EFC08F272A7004A47F5 /* tclInterp.c */,
				F96D3EFD08F272A7004A47F5 /* tclIntPlatDecls.h */,
				F96D3EFE08F272A7004A47F5 /* tclIO.c */,
				F96D3EFF08F272A7004A47F5 /* tclIO.h */,
				F96D3F0008F272A7004A47F5 /* tclIOCmd.c */,
				F96D3F0108F272A7004A47F5 /* tclIOGT.c */,
				F96D3F0208F272A7004A47F5 /* tclIORChan.c */,
				F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */,
				F96D3F0308F272A7004A47F5 /* tclIOSock.c */,
				F96D3F0408F272A7004A47F5 /* tclIOUtil.c */,
				F96D3F0508F272A7004A47F5 /* tclLink.c */,
				F96D3F0608F272A7004A47F5 /* tclListObj.c */,
				F96D3F0708F272A7004A47F5 /* tclLiteral.c */,
				F96D3F0808F272A7004A47F5 /* tclLoad.c */,
				F96D3F0908F272A7004A47F5 /* tclLoadNone.c */,
				F96D3F0A08F272A7004A47F5 /* tclMain.c */,
				F96D3F0B08F272A7004A47F5 /* tclNamesp.c */,
				F96D3F0C08F272A7004A47F5 /* tclNotify.c */,
				F96D3F0D08F272A7004A47F5 /* tclObj.c */,
				F93599B20DF1F75400E04F67 /* tclOO.c */,
				F93599B40DF1F75900E04F67 /* tclOO.decls */,
				F93599B50DF1F75D00E04F67 /* tclOO.h */,
				F93599B60DF1F76100E04F67 /* tclOOBasic.c */,
				F93599B80DF1F76600E04F67 /* tclOOCall.c */,
				F93599BA0DF1F76A00E04F67 /* tclOODecls.h */,
				F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */,
				F93599BD0DF1F77400E04F67 /* tclOOInfo.c */,
				F93599BF0DF1F77900E04F67 /* tclOOInt.h */,
				F93599C00DF1F77D00E04F67 /* tclOOIntDecls.h */,
				F93599C10DF1F78300E04F67 /* tclOOMethod.c */,
				F93599C30DF1F78800E04F67 /* tclOOStubInit.c */,
				F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */,
				F96D3F0E08F272A7004A47F5 /* tclPanic.c */,
				F96D3F0F08F272A7004A47F5 /* tclParse.c */,
				F96D3F1108F272A7004A47F5 /* tclPathObj.c */,
				F96D3F1208F272A7004A47F5 /* tclPipe.c */,
				F96D3F1308F272A7004A47F5 /* tclPkg.c */,
				F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */,
				F96D3F1508F272A7004A47F5 /* tclPlatDecls.h */,
				F96D3F1608F272A7004A47F5 /* tclPort.h */,
				F96D3F1708F272A7004A47F5 /* tclPosixStr.c */,
				F96D3F1808F272A7004A47F5 /* tclPreserve.c */,
				F96D3F1908F272A7004A47F5 /* tclProc.c */,
				F96D3F1A08F272A7004A47F5 /* tclRegexp.c */,
				F96D3F1B08F272A7004A47F5 /* tclRegexp.h */,
				F96D3F1C08F272A7004A47F5 /* tclResolve.c */,
				F96D3F1D08F272A7004A47F5 /* tclResult.c */,
				F96D3F1E08F272A7004A47F5 /* tclScan.c */,
				F96D3F1F08F272A7004A47F5 /* tclStringObj.c */,
				F96D3F2408F272A7004A47F5 /* tclStrToD.c */,
				F96D3F2508F272A7004A47F5 /* tclStubInit.c */,
				F96D3F2608F272A7004A47F5 /* tclStubLib.c */,
				F96D3F2708F272A7004A47F5 /* tclTest.c */,
				F96D3F2808F272A7004A47F5 /* tclTestObj.c */,
				F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */,
				F96D3F2A08F272A7004A47F5 /* tclThread.c */,
				F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */,
				F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */,
				F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */,
				F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */,
				F96D3F2F08F272A7004A47F5 /* tclTimer.c */,
				F9903CAF094FAADA004613E9 /* tclTomMath.decls */,
				F96D3F3008F272A7004A47F5 /* tclTomMath.h */,
				F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */,
				F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */,
				F96D3F3208F272A7004A47F5 /* tclTrace.c */,
				F96D3F3308F272A7004A47F5 /* tclUniData.c */,
				F96D3F3408F272A7004A47F5 /* tclUtf.c */,
				F96D3F3508F272A7004A47F5 /* tclUtil.c */,
				F96D3F3608F272A7004A47F5 /* tclVar.c */,
				F96437C90EF0D4B2003F468E /* tclZlib.c */,
			);
			path = generic;
			sourceTree = "<group>";
		};
		F96D3F3808F272A7004A47F5 /* library */ = {
			isa = PBXGroup;
			children = (
				F96D3F3908F272A8004A47F5 /* auto.tcl */,
				F96D3F3A08F272A8004A47F5 /* clock.tcl */,
				F96D3F3B08F272A8004A47F5 /* dde */,
				F96D3F8C08F272A8004A47F5 /* history.tcl */,
				F96D3F8D08F272A8004A47F5 /* http */,
				F96D3F9308F272A8004A47F5 /* init.tcl */,
				F96D3F9408F272A8004A47F5 /* msgcat */,
				F96D401708F272AA004A47F5 /* opt */,
				F96D401A08F272AA004A47F5 /* package.tcl */,
				F96D401B08F272AA004A47F5 /* parray.tcl */,
				F9ECB1110B26521500A28025 /* platform */,
				F96D401C08F272AA004A47F5 /* reg */,
				F96D401E08F272AA004A47F5 /* safe.tcl */,
				F96D401F08F272AA004A47F5 /* tclIndex */,
				F96D402008F272AA004A47F5 /* tcltest */,
				F96D402308F272AA004A47F5 /* tm.tcl */,
				F96D425B08F272B2004A47F5 /* word.tcl */,
			);
			path = library;
			sourceTree = "<group>";
		};
		F96D3F3B08F272A8004A47F5 /* dde */ = {
			isa = PBXGroup;
			children = (
				F96D3F3C08F272A8004A47F5 /* pkgIndex.tcl */,
			);
			path = dde;
			sourceTree = "<group>";
		};
		F96D3F8D08F272A8004A47F5 /* http */ = {
			isa = PBXGroup;
			children = (
				F96D3F8E08F272A8004A47F5 /* http.tcl */,
				F96D3F8F08F272A8004A47F5 /* pkgIndex.tcl */,
			);
			path = http;
			sourceTree = "<group>";
		};
		F96D3F9408F272A8004A47F5 /* msgcat */ = {
			isa = PBXGroup;
			children = (
				F96D3F9508F272A8004A47F5 /* msgcat.tcl */,
				F96D3F9608F272A8004A47F5 /* pkgIndex.tcl */,
			);
			path = msgcat;
			sourceTree = "<group>";
		};
		F96D401708F272AA004A47F5 /* opt */ = {
			isa = PBXGroup;
			children = (
				F96D401808F272AA004A47F5 /* optparse.tcl */,
				F96D401908F272AA004A47F5 /* pkgIndex.tcl */,
			);
			path = opt;
			sourceTree = "<group>";
		};
		F96D401C08F272AA004A47F5 /* reg */ = {
			isa = PBXGroup;
			children = (
				F96D401D08F272AA004A47F5 /* pkgIndex.tcl */,
			);
			path = reg;
			sourceTree = "<group>";
		};
		F96D402008F272AA004A47F5 /* tcltest */ = {
			isa = PBXGroup;
			children = (
				F96D402108F272AA004A47F5 /* pkgIndex.tcl */,
				F96D402208F272AA004A47F5 /* tcltest.tcl */,
			);
			path = tcltest;
			sourceTree = "<group>";
		};
		F96D425C08F272B2004A47F5 /* libtommath */ = {
			isa = PBXGroup;
			children = (
				F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */,
				F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */,
				F96D426908F272B3004A47F5 /* bn_mp_add.c */,
				F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */,
				F96D426C08F272B3004A47F5 /* bn_mp_and.c */,
				F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */,
				F96D426E08F272B3004A47F5 /* bn_mp_clear.c */,
				F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */,
				F96D427008F272B3004A47F5 /* bn_mp_cmp.c */,
				F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */,
				F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */,
				F96D427408F272B3004A47F5 /* bn_mp_copy.c */,
				F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */,
				F96D427608F272B3004A47F5 /* bn_mp_div.c */,
				F96D427708F272B3004A47F5 /* bn_mp_div_2.c */,
				F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */,
				F96D427908F272B3004A47F5 /* bn_mp_div_3.c */,
				F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */,
				F96D427E08F272B3004A47F5 /* bn_mp_exch.c */,
				F96D427F08F272B3004A47F5 /* bn_mp_expt_u32.c */,
				F96D427F08F272B3004A47F5 /* bn_mp_expt_d_ex.c */,
				F96D428708F272B3004A47F5 /* bn_mp_grow.c */,
				F96D428808F272B3004A47F5 /* bn_mp_init.c */,
				F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */,
				F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */,
				F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */,
				F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */,
				F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */,
				F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */,
				F96D429508F272B3004A47F5 /* bn_mp_lshd.c */,
				F96D429608F272B3004A47F5 /* bn_mp_mod.c */,
				F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */,
				F96D429C08F272B3004A47F5 /* bn_mp_mul.c */,
				F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */,
				F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */,
				F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */,
				F96D42A208F272B3004A47F5 /* bn_mp_neg.c */,
				F96D42A308F272B3004A47F5 /* bn_mp_or.c */,
				F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */,
				F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */,
				F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */,
				F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */,
				F96D42BA08F272B3004A47F5 /* bn_mp_set.c */,
				F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */,
				F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */,
				F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */,
				F96D42C108F272B3004A47F5 /* bn_mp_sub.c */,
				F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */,
				F96D42C608F272B3004A47F5 /* bn_mp_to_ubin.c */,
				F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */,
				F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */,
				F96D42CB08F272B3004A47F5 /* bn_mp_to_radix.c */,
				F96D42CC08F272B3004A47F5 /* bn_mp_ubin_size.c */,
				F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */,
				F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */,
				F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */,
				F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */,
				F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */,
				F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */,
				F96D432908F272B4004A47F5 /* tommath_class.h */,
				F96D432A08F272B4004A47F5 /* tommath_superclass.h */,
			);
			path = libtommath;
			sourceTree = "<group>";
		};
		F96D432C08F272B4004A47F5 /* macosx */ = {
			isa = PBXGroup;
			children = (
				F96D432E08F272B5004A47F5 /* configure.ac */,
				F96D432F08F272B5004A47F5 /* GNUmakefile */,
				F96D433108F272B5004A47F5 /* README */,
				F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */,
				F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */,
				F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */,
				F96D433208F272B5004A47F5 /* Tcl-Info.plist.in */,
				F91E62260C1AE686006C9D96 /* Tclsh-Info.plist.in */,
				F97AE7F10B65C1E900310EA2 /* Tcl-Common.xcconfig */,
				F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */,
				F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */,
			);
			path = macosx;
			sourceTree = "<group>";
		};
		F96D434408F272B5004A47F5 /* tests */ = {
			isa = PBXGroup;
			children = (
				F96D434508F272B5004A47F5 /* all.tcl */,
				F96D434608F272B5004A47F5 /* append.test */,
				F96D434708F272B5004A47F5 /* appendComp.test */,
				F9ECB1CA0B2652D300A28025 /* apply.test */,
				F96D434808F272B5004A47F5 /* assocd.test */,
				F96D434908F272B5004A47F5 /* async.test */,
				F96D434A08F272B5004A47F5 /* autoMkindex.test */,
				F96D434B08F272B5004A47F5 /* basic.test */,
				F96D434C08F272B5004A47F5 /* binary.test */,
				F96D434D08F272B5004A47F5 /* case.test */,
				F96D434E08F272B5004A47F5 /* chan.test */,
				F9A493240CEBF38300B78AE2 /* chanio.test */,
				F96D434F08F272B5004A47F5 /* clock.test */,
				F96D435008F272B5004A47F5 /* cmdAH.test */,
				F96D435108F272B5004A47F5 /* cmdIL.test */,
				F96D435208F272B5004A47F5 /* cmdInfo.test */,
				F96D435308F272B5004A47F5 /* cmdMZ.test */,
				F96D435408F272B5004A47F5 /* compExpr-old.test */,
				F96D435508F272B5004A47F5 /* compExpr.test */,
				F96D435608F272B5004A47F5 /* compile.test */,
				F96D435708F272B5004A47F5 /* concat.test */,
				F96D435808F272B5004A47F5 /* config.test */,
				F974D5770FBE7E6100BF728B /* coroutine.test */,
				F96D435908F272B5004A47F5 /* dcall.test */,
				F96D435A08F272B5004A47F5 /* dict.test */,
				F96D435C08F272B5004A47F5 /* dstring.test */,
				F96D435E08F272B5004A47F5 /* encoding.test */,
				F96D435F08F272B5004A47F5 /* env.test */,
				F96D436008F272B5004A47F5 /* error.test */,
				F96D436108F272B5004A47F5 /* eval.test */,
				F96D436208F272B5004A47F5 /* event.test */,
				F96D436308F272B5004A47F5 /* exec.test */,
				F96D436408F272B5004A47F5 /* execute.test */,
				F96D436508F272B5004A47F5 /* expr-old.test */,
				F96D436608F272B5004A47F5 /* expr.test */,
				F96D436708F272B6004A47F5 /* fCmd.test */,
				F96D436808F272B6004A47F5 /* fileName.test */,
				F96D436908F272B6004A47F5 /* fileSystem.test */,
				F96D436A08F272B6004A47F5 /* for-old.test */,
				F96D436B08F272B6004A47F5 /* for.test */,
				F96D436C08F272B6004A47F5 /* foreach.test */,
				F96D436D08F272B6004A47F5 /* format.test */,
				F96D436E08F272B6004A47F5 /* get.test */,
				F96D436F08F272B6004A47F5 /* history.test */,
				F96D437008F272B6004A47F5 /* http.test */,
				F974D56C0FBE7D6300BF728B /* http11.test */,
				F96D437108F272B6004A47F5 /* httpd */,
				F974D56D0FBE7D6300BF728B /* httpd11.tcl */,
				F96D437208F272B6004A47F5 /* httpold.test */,
				F96D437308F272B6004A47F5 /* if-old.test */,
				F96D437408F272B6004A47F5 /* if.test */,
				F96D437508F272B6004A47F5 /* incr-old.test */,
				F96D437608F272B6004A47F5 /* incr.test */,
				F96D437708F272B6004A47F5 /* indexObj.test */,
				F96D437808F272B6004A47F5 /* info.test */,
				F96D437908F272B6004A47F5 /* init.test */,
				F96D437A08F272B6004A47F5 /* interp.test */,
				F96D437B08F272B6004A47F5 /* io.test */,
				F96D437C08F272B6004A47F5 /* ioCmd.test */,
				F96D437D08F272B6004A47F5 /* iogt.test */,
				F96D437F08F272B6004A47F5 /* join.test */,
				F96D438008F272B6004A47F5 /* lindex.test */,
				F96D438108F272B6004A47F5 /* link.test */,
				F96D438208F272B6004A47F5 /* linsert.test */,
				F96D438308F272B6004A47F5 /* list.test */,
				F96D438408F272B6004A47F5 /* listObj.test */,
				F96D438508F272B6004A47F5 /* llength.test */,
				F96D438608F272B6004A47F5 /* load.test */,
				F96D438708F272B6004A47F5 /* lrange.test */,
				F96D438808F272B6004A47F5 /* lrepeat.test */,
				F96D438908F272B6004A47F5 /* lreplace.test */,
				F96D438A08F272B6004A47F5 /* lsearch.test */,
				F96D438B08F272B6004A47F5 /* lset.test */,
				F96D438C08F272B6004A47F5 /* lsetComp.test */,
				F96D438D08F272B6004A47F5 /* macOSXFCmd.test */,
				F95FAFF90B34F1130072E431 /* macOSXLoad.test */,
				F96D438E08F272B6004A47F5 /* main.test */,
				F9ECB1CB0B26534C00A28025 /* mathop.test */,
				F96D438F08F272B6004A47F5 /* misc.test */,
				F96D439008F272B6004A47F5 /* msgcat.test */,
				F96D439108F272B6004A47F5 /* namespace-old.test */,
				F96D439208F272B7004A47F5 /* namespace.test */,
				F96D439308F272B7004A47F5 /* notify.test */,
				F91DC23C0E44C51B002CB8D1 /* nre.test */,
				F96D439408F272B7004A47F5 /* obj.test */,
				F93599C80DF1F81900E04F67 /* oo.test */,
				F96D439508F272B7004A47F5 /* opt.test */,
				F96D439608F272B7004A47F5 /* package.test */,
				F96D439708F272B7004A47F5 /* parse.test */,
				F96D439808F272B7004A47F5 /* parseExpr.test */,
				F96D439908F272B7004A47F5 /* parseOld.test */,
				F96D439A08F272B7004A47F5 /* pid.test */,
				F96D439B08F272B7004A47F5 /* pkg.test */,
				F96D439C08F272B7004A47F5 /* pkgMkIndex.test */,
				F96D439D08F272B7004A47F5 /* platform.test */,
				F96D439E08F272B7004A47F5 /* proc-old.test */,
				F96D439F08F272B7004A47F5 /* proc.test */,
				F96D43A008F272B7004A47F5 /* pwd.test */,
				F96D43A108F272B7004A47F5 /* README */,
				F96D43A208F272B7004A47F5 /* reg.test */,
				F96D43A308F272B7004A47F5 /* regexp.test */,
				F96D43A408F272B7004A47F5 /* regexpComp.test */,
				F96D43A508F272B7004A47F5 /* registry.test */,
				F96D43A608F272B7004A47F5 /* remote.tcl */,
				F96D43A708F272B7004A47F5 /* rename.test */,
				F96D43A808F272B7004A47F5 /* result.test */,
				F96D43A908F272B7004A47F5 /* safe.test */,
				F96D43AA08F272B7004A47F5 /* scan.test */,
				F96D43AB08F272B7004A47F5 /* security.test */,
				F96D43AC08F272B7004A47F5 /* set-old.test */,
				F96D43AD08F272B7004A47F5 /* set.test */,
				F96D43AE08F272B7004A47F5 /* socket.test */,
				F96D43AF08F272B7004A47F5 /* source.test */,
				F96D43B008F272B7004A47F5 /* split.test */,
				F96D43B108F272B7004A47F5 /* stack.test */,
				F96D43B208F272B7004A47F5 /* string.test */,
				F96D43B308F272B7004A47F5 /* stringComp.test */,
				F96D43B408F272B7004A47F5 /* stringObj.test */,
				F96D43B508F272B7004A47F5 /* subst.test */,
				F96D43B608F272B7004A47F5 /* switch.test */,
				F974D5780FBE7E6100BF728B /* tailcall.test */,
				F96D43B708F272B7004A47F5 /* tcltest.test */,
				F96D43B808F272B7004A47F5 /* thread.test */,
				F96D43B908F272B7004A47F5 /* timer.test */,
				F96D43BA08F272B7004A47F5 /* tm.test */,
				F96D43BB08F272B7004A47F5 /* trace.test */,
				F96D43BC08F272B7004A47F5 /* unixFCmd.test */,
				F96D43BD08F272B7004A47F5 /* unixFile.test */,
				F96D43BE08F272B7004A47F5 /* unixInit.test */,
				F96D43BF08F272B7004A47F5 /* unixNotfy.test */,
				F96D43C008F272B7004A47F5 /* unknown.test */,
				F96D43C108F272B7004A47F5 /* unload.test */,
				F96D43C208F272B7004A47F5 /* uplevel.test */,
				F96D43C308F272B7004A47F5 /* upvar.test */,
				F96D43C408F272B7004A47F5 /* utf.test */,
				F96D43C508F272B7004A47F5 /* util.test */,
				F96D43C608F272B7004A47F5 /* var.test */,
				F96D43C708F272B7004A47F5 /* while-old.test */,
				F96D43C808F272B7004A47F5 /* while.test */,
				F96D43C908F272B7004A47F5 /* winConsole.test */,
				F96D43CA08F272B7004A47F5 /* winDde.test */,
				F96D43CB08F272B7004A47F5 /* winFCmd.test */,
				F96D43CC08F272B7004A47F5 /* winFile.test */,
				F96D43CD08F272B7004A47F5 /* winNotify.test */,
				F96D43CE08F272B7004A47F5 /* winPipe.test */,
				F96D43CF08F272B7004A47F5 /* winTime.test */,
				F915432A0EF201CF0032D1E8 /* zlib.test */,
			);
			path = tests;
			sourceTree = "<group>";
		};
		F96D43D008F272B8004A47F5 /* tools */ = {
			isa = PBXGroup;
			children = (
				F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */,
				F96D43D208F272B8004A47F5 /* configure */,
				F96D43D308F272B8004A47F5 /* configure.ac */,
				F96D442508F272B8004A47F5 /* genStubs.tcl */,
				F96D442708F272B8004A47F5 /* index.tcl */,
				F96D442808F272B8004A47F5 /* installData.tcl */,
				F96D442908F272B8004A47F5 /* loadICU.tcl */,
				F96D442A08F272B8004A47F5 /* Makefile.in */,
				F96D442B08F272B8004A47F5 /* makeTestCases.tcl */,
				F96D442C08F272B8004A47F5 /* man2help.tcl */,
				F96D442D08F272B8004A47F5 /* man2help2.tcl */,
				F96D442E08F272B8004A47F5 /* man2html.tcl */,
				F96D442F08F272B8004A47F5 /* man2html1.tcl */,
				F96D443008F272B8004A47F5 /* man2html2.tcl */,
				F96D443108F272B8004A47F5 /* man2tcl.c */,
				F96D443208F272B8004A47F5 /* README */,
				F96D443308F272B8004A47F5 /* regexpTestLib.tcl */,
				F96D443508F272B8004A47F5 /* tcl.hpj.in */,
				F96D443908F272B9004A47F5 /* tcltk-man2html.tcl */,
				F96D443A08F272B9004A47F5 /* tclZIC.tcl */,
				F92D7F100DE777240033A13A /* tsdPerf.tcl */,
				F96D443B08F272B9004A47F5 /* uniClass.tcl */,
				F96D443C08F272B9004A47F5 /* uniParse.tcl */,
			);
			path = tools;
			sourceTree = "<group>";
		};
		F96D443E08F272B9004A47F5 /* unix */ = {
			isa = PBXGroup;
			children = (
				F96D444008F272B9004A47F5 /* aclocal.m4 */,
				F96D444108F272B9004A47F5 /* configure */,
				F96D444208F272B9004A47F5 /* configure.ac */,
				F96D444308F272B9004A47F5 /* dltest */,
				F96D444D08F272B9004A47F5 /* install-sh */,
				F96D444E08F272B9004A47F5 /* installManPage */,
				F96D444F08F272B9004A47F5 /* ldAix */,
				F96D445008F272B9004A47F5 /* Makefile.in */,
				F96D445208F272B9004A47F5 /* README */,
				F96D445308F272B9004A47F5 /* tcl.m4 */,
				F974D5790FBE7E9C00BF728B /* tcl.pc.in */,
				F96D445408F272B9004A47F5 /* tcl.spec */,
				F96D445508F272B9004A47F5 /* tclAppInit.c */,
				F96D445608F272B9004A47F5 /* tclConfig.h.in */,
				F96D445708F272B9004A47F5 /* tclConfig.sh.in */,
				F96D445808F272B9004A47F5 /* tclLoadAix.c */,
				F96D445908F272B9004A47F5 /* tclLoadDl.c */,
				F96D445B08F272B9004A47F5 /* tclLoadDyld.c */,
				F96D445C08F272B9004A47F5 /* tclLoadNext.c */,
				F96D445D08F272B9004A47F5 /* tclLoadOSF.c */,
				F96D445E08F272B9004A47F5 /* tclLoadShl.c */,
				F96D445F08F272B9004A47F5 /* tclUnixChan.c */,
				F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */,
				F96D446008F272B9004A47F5 /* tclUnixEvent.c */,
				F96D446108F272B9004A47F5 /* tclUnixFCmd.c */,
				F96D446208F272B9004A47F5 /* tclUnixFile.c */,
				F96D446308F272B9004A47F5 /* tclUnixInit.c */,
				F96D446408F272B9004A47F5 /* tclUnixNotfy.c */,
				F96D446508F272B9004A47F5 /* tclUnixPipe.c */,
				F96D446608F272B9004A47F5 /* tclUnixPort.h */,
				F96D446708F272B9004A47F5 /* tclUnixSock.c */,
				F96D446808F272B9004A47F5 /* tclUnixTest.c */,
				F96D446908F272B9004A47F5 /* tclUnixThrd.c */,
				F96D446B08F272B9004A47F5 /* tclUnixTime.c */,
				F96D446C08F272B9004A47F5 /* tclXtNotify.c */,
				F96D446D08F272B9004A47F5 /* tclXtTest.c */,
			);
			path = unix;
			sourceTree = "<group>";
		};
		F96D444308F272B9004A47F5 /* dltest */ = {
			isa = PBXGroup;
			children = (
				F96D444408F272B9004A47F5 /* Makefile.in */,
				F96D444508F272B9004A47F5 /* pkga.c */,
				F96D444608F272B9004A47F5 /* pkgb.c */,
				F96D444708F272B9004A47F5 /* pkgc.c */,
				F96D444808F272B9004A47F5 /* pkgd.c */,
				F96D444908F272B9004A47F5 /* pkge.c */,
				F96D444B08F272B9004A47F5 /* pkgua.c */,
				F96D444C08F272B9004A47F5 /* README */,
			);
			path = dltest;
			sourceTree = "<group>";
		};
		F96D446E08F272B9004A47F5 /* win */ = {
			isa = PBXGroup;
			children = (
				F96D447008F272BA004A47F5 /* aclocal.m4 */,
				F96D447108F272BA004A47F5 /* buildall.vc.bat */,
				F96D447208F272BA004A47F5 /* cat.c */,
				F96D447308F272BA004A47F5 /* coffbase.txt */,
				F96D447408F272BA004A47F5 /* configure */,
				F96D447508F272BA004A47F5 /* configure.ac */,
				F96D447708F272BA004A47F5 /* Makefile.in */,
				F96D447808F272BA004A47F5 /* makefile.vc */,
				F96D447908F272BA004A47F5 /* nmakehlp.c */,
				F96D447A08F272BA004A47F5 /* README */,
				F96D447C08F272BA004A47F5 /* rules.vc */,
				F96D447D08F272BA004A47F5 /* stub16.c */,
				F96D447E08F272BA004A47F5 /* tcl.dsp */,
				F96D447F08F272BA004A47F5 /* tcl.dsw */,
				F96D448008F272BA004A47F5 /* tcl.hpj.in */,
				F96D448108F272BA004A47F5 /* tcl.m4 */,
				F96D448208F272BA004A47F5 /* tcl.rc */,
				F96D448308F272BA004A47F5 /* tclAppInit.c */,
				F96D448408F272BA004A47F5 /* tclConfig.sh.in */,
				F96D448608F272BA004A47F5 /* tclsh.rc */,
				F96D448708F272BA004A47F5 /* tclWin32Dll.c */,
				F96D448808F272BA004A47F5 /* tclWinChan.c */,
				F96D448908F272BA004A47F5 /* tclWinConsole.c */,
				F96D448A08F272BA004A47F5 /* tclWinDde.c */,
				F96D448B08F272BA004A47F5 /* tclWinError.c */,
				F96D448C08F272BA004A47F5 /* tclWinFCmd.c */,
				F96D448D08F272BA004A47F5 /* tclWinFile.c */,
				F96D448E08F272BA004A47F5 /* tclWinInit.c */,
				F96D448F08F272BA004A47F5 /* tclWinInt.h */,
				F96D449008F272BA004A47F5 /* tclWinLoad.c */,
				F96D449108F272BA004A47F5 /* tclWinNotify.c */,
				F96D449208F272BA004A47F5 /* tclWinPipe.c */,
				F96D449308F272BA004A47F5 /* tclWinPort.h */,
				F96D449408F272BA004A47F5 /* tclWinReg.c */,
				F96D449508F272BA004A47F5 /* tclWinSerial.c */,
				F96D449608F272BA004A47F5 /* tclWinSock.c */,
				F96D449708F272BA004A47F5 /* tclWinTest.c */,
				F96D449808F272BA004A47F5 /* tclWinThrd.c */,
				F96D449A08F272BA004A47F5 /* tclWinTime.c */,
			);
			path = win;
			sourceTree = "<group>";
		};
		F9ECB1110B26521500A28025 /* platform */ = {
			isa = PBXGroup;
			children = (
				F9ECB1120B26521500A28025 /* pkgIndex.tcl */,
				F9ECB1130B26521500A28025 /* platform.tcl */,
				F9ECB1140B26521500A28025 /* shell.tcl */,
			);
			path = platform;
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
		8DD76FA90486AB0100D96B5E /* tcltest */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = F95CC8B009158F3100EA5ACE /* Build configuration list for PBXNativeTarget "tcltest" */;
			buildPhases = (
				F9A5C5F508F651A2008AE941 /* Configure Tcl */,
				8DD76FAB0486AB0100D96B5E /* Sources */,
				8DD76FAD0486AB0100D96B5E /* Frameworks */,
				F95FA74C0B32CE190072E431 /* Build dltest */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = tcltest;
			productInstallPath = "$(BINDIR)";
			productName = tcltest;
			productReference = 8DD76FB20486AB0100D96B5E /* tcltest */;
			productType = "com.apple.product-type.tool";
		};
		F97258A50A86873C00096C78 /* tests */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = F97258A80A86873D00096C78 /* Build configuration list for PBXNativeTarget "tests" */;
			buildPhases = (
				F97258A40A86873C00096C78 /* Run Testsuite */,
			);
			buildRules = (
			);
			dependencies = (
				F97258D30A868C6F00096C78 /* PBXTargetDependency */,
			);
			name = tests;
			productName = tests;
			productType = "com.apple.product-type.bundle";
		};
		F9E61D16090A3E94002B3151 /* Tcl */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = F95CC8AB09158F3100EA5ACE /* Build configuration list for PBXNativeTarget "Tcl" */;
			buildPhases = (
				F97AF02F0B665DA900310EA2 /* Build Tcl */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = Tcl;
			productName = tclsh;
			productReference = F9A3084B08F2D4CE00BAE1AB /* tclsh */;
			productType = "com.apple.product-type.tool";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		08FB7793FE84155DC02AAC07 /* Project object */ = {
			isa = PBXProject;
			attributes = {
				BuildIndependentTargetsInParallel = YES;
			};
			buildConfigurationList = F95CC8B509158F3100EA5ACE /* Build configuration list for PBXProject "Tcl" */;
			compatibilityVersion = "Xcode 3.1";
			hasScannedForEncodings = 1;
			mainGroup = 08FB7794FE84155DC02AAC07 /* Tcl */;
			projectDirPath = "";
			projectRoot = ..;
			targets = (
				F9E61D16090A3E94002B3151 /* Tcl */,
				8DD76FA90486AB0100D96B5E /* tcltest */,
				F97258A50A86873C00096C78 /* tests */,
			);
		};
/* End PBXProject section */

/* Begin PBXShellScriptBuildPhase section */
		F95FA74C0B32CE190072E431 /* Build dltest */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
				"$(DERIVED_FILE_DIR)/tcl/tclConfig.sh",
				"$(TCL_SRCROOT)/generic/tclStubLib.c",
				"$(TCL_SRCROOT)/unix/dltest/pkga.c",
				"$(TCL_SRCROOT)/unix/dltest/pkgb.c",
				"$(TCL_SRCROOT)/unix/dltest/pkgc.c",
				"$(TCL_SRCROOT)/unix/dltest/pkgd.c",
				"$(TCL_SRCROOT)/unix/dltest/pkge.c",
				"$(TCL_SRCROOT)/unix/dltest/pkgua.c",
			);
			name = "Build dltest";
			outputPaths = (
				"$(DERIVED_FILE_DIR)/tcl/dltest.marker",
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/bash;
			shellScript = "## dltest build script phase\n\nrm -f \"${DERIVED_FILE_DIR}/tcl/dltest.marker\"\nmake -C \"${DERIVED_FILE_DIR}/tcl\" dltest.marker\nln -fsh \"${DERIVED_FILE_DIR}/tcl/dltest\" \"${CONFIGURATION_BUILD_DIR}\"\n";
			showEnvVarsInLog = 0;
		};
		F97258A40A86873C00096C78 /* Run Testsuite */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "Run Testsuite";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/bash;
			shellScript = "if [ \"${ACTION:-build}\" == \"build\" ]; then\nif [ -z \"${HOME}\" ]; then export HOME=\"$(echo ~)\"; fi\ncd \"${TARGET_TEMP_DIR}\"; rm -rf \"${DERIVED_FILE_DIR}\"; mkdir -p \"${DERIVED_FILE_DIR}\"\nprintf '%s%s%s%s%s' '\npackage require tcltest 2.5\nnamespace import tcltest::*\nconfigure -testdir [file normalize {' \"${TCL_SRCROOT}\" '/tests}]\nconfigure -tmpdir [file normalize {' \"${DERIVED_FILE_DIR}\" '}]\nconfigure -verbose [concat [configure -verbose] line]\nrunAllTests\n' | \"${TEST_RIG}\"; TEST_RIG_RESULT=$?\n[ ${TEST_RIG_RESULT} -ne 0 ] && echo \"tcltest:0: error: tcltest exited abnormally with code ${TEST_RIG_RESULT}.\"\nexit ${TEST_RIG_RESULT}\nfi";
			showEnvVarsInLog = 0;
		};
		F97AF02F0B665DA900310EA2 /* Build Tcl */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
				"${TARGET_TEMP_DIR}/.none",
			);
			name = "Build Tcl";
			outputPaths = (
				"${TARGET_BUILD_DIR}/${EXECUTABLE_NAME}",
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/bash;
			shellScript = "if [ -e \"${TARGET_BUILD_DIR}/tclsh\" ]; then\n    mv -f \"${TARGET_BUILD_DIR}/tclsh\" \"${TARGET_BUILD_DIR}/tclsh${VERSION}\"\nfi\nexport CC=$(xcrun -find ${GCC} || echo ${GCC}); export LD=${CC}\ngnumake -C \"${TCL_SRCROOT}/macosx\" -j \"$(sysctl -n hw.activecpu)\" \"$(echo \"${ACTION}\" | sed -e s/build// -e s/clean/distclean/ -e s/..\\*/\\&-/)${MAKE_TARGET}\" CFLAGS_WARNING=\"${WARNING_CFLAGS}\" CFLAGS_OPTIMIZE=\"-O${GCC_OPTIMIZATION_LEVEL}\" SYMROOT=\"${BUILT_PRODUCTS_DIR}\" OBJ_DIR=\"${OBJECT_FILE_DIR}\" INSTALL_ROOT=\"${DSTROOT}\" PREFIX=\"${PREFIX}\" BINDIR=\"${BINDIR}\" LIBDIR=\"${FRAMEWORK_INSTALL_PATH}\" MANDIR=\"${MANDIR}\" EXTRA_CONFIGURE_ARGS=\"${CONFIGURE_ARGS}\" ${EXTRA_MAKE_FLAGS}\nresult=$?\nif [ -e \"${TARGET_BUILD_DIR}/tclsh${VERSION}\" ]; then\n    mv -f \"${TARGET_BUILD_DIR}/tclsh${VERSION}\" \"${TARGET_BUILD_DIR}/tclsh\"\nfi\nif [ -e \"${BUILT_PRODUCTS_DIR}/tcltest\" ]; then\n\trm -f \"${BUILT_PRODUCTS_DIR}/tcltest\"\nfi\necho \"Done\"\nrm -f \"${SCRIPT_INPUT_FILE_0}\"\nexit ${result}\n";
			showEnvVarsInLog = 0;
		};
		F9A5C5F508F651A2008AE941 /* Configure Tcl */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
				"$(TCL_SRCROOT)/macosx/configure.ac",
				"$(TCL_SRCROOT)/unix/configure.ac",
				"$(TCL_SRCROOT)/unix/tcl.m4",
				"$(TCL_SRCROOT)/unix/aclocal.m4",
				"$(TCL_SRCROOT)/unix/tclConfig.sh.in",
				"$(TCL_SRCROOT)/unix/Makefile.in",
				"$(TCL_SRCROOT)/unix/dltest/Makefile.in",
			);
			name = "Configure Tcl";
			outputPaths = (
				"$(DERIVED_FILE_DIR)/tcl/tclConfig.sh",
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/bash;
			shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.ac -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n    echo \"Running autoconf & autoheader in tcl/macosx\"\n    rm -rf autom4te.cache\n    ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n    rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n    echo \"Configuring Tcl\"\n    CC=$(xcrun -find ${GCC} || echo ${GCC})\n    \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n    ./config.status\nfi\n";
			showEnvVarsInLog = 0;
		};
/* End PBXShellScriptBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		8DD76FAB0486AB0100D96B5E /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				F96D456F08F272BB004A47F5 /* regcomp.c in Sources */,
				F96D457208F272BB004A47F5 /* regerror.c in Sources */,
				F96D457508F272BB004A47F5 /* regexec.c in Sources */,
				F96D457608F272BB004A47F5 /* regfree.c in Sources */,
				F96D457B08F272BB004A47F5 /* tclAlloc.c in Sources */,
				F96D457C08F272BB004A47F5 /* tclAsync.c in Sources */,
				F96D457D08F272BB004A47F5 /* tclBasic.c in Sources */,
				F96D457E08F272BC004A47F5 /* tclBinary.c in Sources */,
				F96D457F08F272BC004A47F5 /* tclCkalloc.c in Sources */,
				F96D458008F272BC004A47F5 /* tclClock.c in Sources */,
				F96D458108F272BC004A47F5 /* tclCmdAH.c in Sources */,
				F96D458208F272BC004A47F5 /* tclCmdIL.c in Sources */,
				F96D458308F272BC004A47F5 /* tclCmdMZ.c in Sources */,
				F96D458408F272BC004A47F5 /* tclCompCmds.c in Sources */,
				F96D458508F272BC004A47F5 /* tclCompExpr.c in Sources */,
				F96D458608F272BC004A47F5 /* tclCompile.c in Sources */,
				F96D458808F272BC004A47F5 /* tclConfig.c in Sources */,
				F96D458908F272BC004A47F5 /* tclDate.c in Sources */,
				F96D458B08F272BC004A47F5 /* tclDictObj.c in Sources */,
				F96D458C08F272BC004A47F5 /* tclEncoding.c in Sources */,
				F96D458D08F272BC004A47F5 /* tclEnv.c in Sources */,
				F96D458E08F272BC004A47F5 /* tclEvent.c in Sources */,
				F96D458F08F272BC004A47F5 /* tclExecute.c in Sources */,
				F96D459008F272BC004A47F5 /* tclFCmd.c in Sources */,
				F96D459108F272BC004A47F5 /* tclFileName.c in Sources */,
				F96D459308F272BC004A47F5 /* tclGet.c in Sources */,
				F96D459508F272BC004A47F5 /* tclHash.c in Sources */,
				F96D459608F272BC004A47F5 /* tclHistory.c in Sources */,
				F96D459708F272BC004A47F5 /* tclIndexObj.c in Sources */,
				F96D459B08F272BC004A47F5 /* tclInterp.c in Sources */,
				F96D459D08F272BC004A47F5 /* tclIO.c in Sources */,
				F96D459F08F272BC004A47F5 /* tclIOCmd.c in Sources */,
				F96D45A008F272BC004A47F5 /* tclIOGT.c in Sources */,
				F96D45A108F272BC004A47F5 /* tclIORChan.c in Sources */,
				F95D77EA0DFD820D00A8BF6F /* tclIORTrans.c in Sources */,
				F96D45A208F272BC004A47F5 /* tclIOSock.c in Sources */,
				F96D45A308F272BC004A47F5 /* tclIOUtil.c in Sources */,
				F96D45A408F272BC004A47F5 /* tclLink.c in Sources */,
				F96D45A508F272BC004A47F5 /* tclListObj.c in Sources */,
				F96D45A608F272BC004A47F5 /* tclLiteral.c in Sources */,
				F96D45A708F272BC004A47F5 /* tclLoad.c in Sources */,
				F96D45A908F272BC004A47F5 /* tclMain.c in Sources */,
				F96D45AA08F272BC004A47F5 /* tclNamesp.c in Sources */,
				F96D45AB08F272BC004A47F5 /* tclNotify.c in Sources */,
				F96D45AC08F272BC004A47F5 /* tclObj.c in Sources */,
				F93599B30DF1F75400E04F67 /* tclOO.c in Sources */,
				F93599B70DF1F76100E04F67 /* tclOOBasic.c in Sources */,
				F93599B90DF1F76600E04F67 /* tclOOCall.c in Sources */,
				F93599BC0DF1F77000E04F67 /* tclOODefineCmds.c in Sources */,
				F93599BE0DF1F77400E04F67 /* tclOOInfo.c in Sources */,
				F93599C20DF1F78300E04F67 /* tclOOMethod.c in Sources */,
				F93599C40DF1F78800E04F67 /* tclOOStubInit.c in Sources */,
				F93599C60DF1F78D00E04F67 /* tclOOStubLib.c in Sources */,
				F96D45AD08F272BC004A47F5 /* tclPanic.c in Sources */,
				F96D45AE08F272BC004A47F5 /* tclParse.c in Sources */,
				F96D45B008F272BC004A47F5 /* tclPathObj.c in Sources */,
				F96D45B108F272BC004A47F5 /* tclPipe.c in Sources */,
				F96D45B208F272BC004A47F5 /* tclPkg.c in Sources */,
				F96D45B308F272BC004A47F5 /* tclPkgConfig.c in Sources */,
				F96D45B608F272BC004A47F5 /* tclPosixStr.c in Sources */,
				F96D45B708F272BC004A47F5 /* tclPreserve.c in Sources */,
				F96D45B808F272BC004A47F5 /* tclProc.c in Sources */,
				F96D45B908F272BC004A47F5 /* tclRegexp.c in Sources */,
				F96D45BB08F272BC004A47F5 /* tclResolve.c in Sources */,
				F96D45BC08F272BC004A47F5 /* tclResult.c in Sources */,
				F96D45BD08F272BC004A47F5 /* tclScan.c in Sources */,
				F96D45BE08F272BC004A47F5 /* tclStringObj.c in Sources */,
				F96D45C308F272BC004A47F5 /* tclStrToD.c in Sources */,
				F96D45C408F272BC004A47F5 /* tclStubInit.c in Sources */,
				F96D45C508F272BC004A47F5 /* tclStubLib.c in Sources */,
				F96D45C608F272BC004A47F5 /* tclTest.c in Sources */,
				F96D45C708F272BC004A47F5 /* tclTestObj.c in Sources */,
				F96D45C808F272BC004A47F5 /* tclTestProcBodyObj.c in Sources */,
				F96D45C908F272BC004A47F5 /* tclThread.c in Sources */,
				F96D45CA08F272BC004A47F5 /* tclThreadAlloc.c in Sources */,
				F96D45CB08F272BC004A47F5 /* tclThreadJoin.c in Sources */,
				F96D45CC08F272BC004A47F5 /* tclThreadStorage.c in Sources */,
				F96D45CD08F272BC004A47F5 /* tclThreadTest.c in Sources */,
				F96D45CE08F272BC004A47F5 /* tclTimer.c in Sources */,
				F96D45D008F272BC004A47F5 /* tclTomMathInterface.c in Sources */,
				F96D45D108F272BC004A47F5 /* tclTrace.c in Sources */,
				F96D45D308F272BC004A47F5 /* tclUtf.c in Sources */,
				F96D45D408F272BC004A47F5 /* tclUtil.c in Sources */,
				F96D45D508F272BC004A47F5 /* tclVar.c in Sources */,
				F96437CA0EF0D4B2003F468E /* tclZlib.c in Sources */,
				F96D48E208F272C3004A47F5 /* bn_fast_s_mp_mul_digs.c in Sources */,
				F96D48E408F272C3004A47F5 /* bn_fast_s_mp_sqr.c in Sources */,
				F96D48E708F272C3004A47F5 /* bn_mp_add.c in Sources */,
				F96D48E808F272C3004A47F5 /* bn_mp_add_d.c in Sources */,
				F9E61D2B090A48A4002B3151 /* bn_mp_and.c in Sources */,
				F96D48EB08F272C3004A47F5 /* bn_mp_clamp.c in Sources */,
				F96D48EC08F272C3004A47F5 /* bn_mp_clear.c in Sources */,
				F96D48ED08F272C3004A47F5 /* bn_mp_clear_multi.c in Sources */,
				F96D48EE08F272C3004A47F5 /* bn_mp_cmp.c in Sources */,
				F9E61D28090A481F002B3151 /* bn_mp_cmp_d.c in Sources */,
				F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */,
				F96D48F208F272C3004A47F5 /* bn_mp_cnt_lsb.c in Sources */,
				F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */,
				F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */,
				F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */,
				F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */,
				F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */,
				F96D48F708F272C3004A47F5 /* bn_mp_div_3.c in Sources */,
				F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */,
				F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */,
				F9E61D2C090A48AC002B3151 /* bn_mp_expt_u32.c in Sources */,
				F9E61D2C090A48AC002B3151 /* bn_mp_expt_d_ex.c in Sources */,
				F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */,
				F96D490608F272C3004A47F5 /* bn_mp_init.c in Sources */,
				F96D490708F272C3004A47F5 /* bn_mp_init_copy.c in Sources */,
				F96D490808F272C3004A47F5 /* bn_mp_init_multi.c in Sources */,
				F96D490908F272C3004A47F5 /* bn_mp_init_set.c in Sources */,
				F96D490B08F272C3004A47F5 /* bn_mp_init_size.c in Sources */,
				F96D491008F272C3004A47F5 /* bn_mp_karatsuba_mul.c in Sources */,
				F96D491108F272C3004A47F5 /* bn_mp_karatsuba_sqr.c in Sources */,
				F96D491308F272C3004A47F5 /* bn_mp_lshd.c in Sources */,
				F96D491408F272C3004A47F5 /* bn_mp_mod.c in Sources */,
				F96D491508F272C3004A47F5 /* bn_mp_mod_2d.c in Sources */,
				F96D491A08F272C3004A47F5 /* bn_mp_mul.c in Sources */,
				F96D491B08F272C3004A47F5 /* bn_mp_mul_2.c in Sources */,
				F96D491C08F272C3004A47F5 /* bn_mp_mul_2d.c in Sources */,
				F96D491D08F272C3004A47F5 /* bn_mp_mul_d.c in Sources */,
				F9E61D29090A486C002B3151 /* bn_mp_neg.c in Sources */,
				F9E61D2E090A48BF002B3151 /* bn_mp_or.c in Sources */,
				F96D492908F272C3004A47F5 /* bn_mp_radix_size.c in Sources */,
				F96D492A08F272C3004A47F5 /* bn_mp_radix_smap.c in Sources */,
				F96D492C08F272C3004A47F5 /* bn_mp_read_radix.c in Sources */,
				F96D493708F272C3004A47F5 /* bn_mp_rshd.c in Sources */,
				F96D493808F272C3004A47F5 /* bn_mp_set.c in Sources */,
				F9E61D2F090A48C7002B3151 /* bn_mp_shrink.c in Sources */,
				F96D493C08F272C3004A47F5 /* bn_mp_sqr.c in Sources */,
				F9E61D2A090A4891002B3151 /* bn_mp_sqrt.c in Sources */,
				F96D493F08F272C3004A47F5 /* bn_mp_sub.c in Sources */,
				F96D494008F272C3004A47F5 /* bn_mp_sub_d.c in Sources */,
				F9E61D31090A48F9002B3151 /* bn_mp_to_ubin.c in Sources */,
				F96D494608F272C3004A47F5 /* bn_mp_toom_mul.c in Sources */,
				F96D494708F272C3004A47F5 /* bn_mp_toom_sqr.c in Sources */,
				F96D494908F272C3004A47F5 /* bn_mp_to_radix.c in Sources */,
				F9E61D32090A48FA002B3151 /* bn_mp_ubin_size.c in Sources */,
				F9E61D2D090A48BB002B3151 /* bn_mp_xor.c in Sources */,
				F96D494C08F272C3004A47F5 /* bn_mp_zero.c in Sources */,
				F96D494F08F272C3004A47F5 /* bn_s_mp_add.c in Sources */,
				F96D495108F272C3004A47F5 /* bn_s_mp_mul_digs.c in Sources */,
				F96D495308F272C3004A47F5 /* bn_s_mp_sqr.c in Sources */,
				F96D495408F272C3004A47F5 /* bn_s_mp_sub.c in Sources */,
				F96D49A908F272C4004A47F5 /* tclMacOSXBundle.c in Sources */,
				F96D49AD08F272C4004A47F5 /* tclMacOSXFCmd.c in Sources */,
				F96D49AE08F272C4004A47F5 /* tclMacOSXNotify.c in Sources */,
				F90509300913A72400327603 /* tclAppInit.c in Sources */,
				F96D4AC608F272C9004A47F5 /* tclLoadDyld.c in Sources */,
				F96D4ACA08F272C9004A47F5 /* tclUnixChan.c in Sources */,
				F9FC77B80AB29E9100B7077D /* tclUnixCompat.c in Sources */,
				F96D4ACB08F272C9004A47F5 /* tclUnixEvent.c in Sources */,
				F96D4ACC08F272C9004A47F5 /* tclUnixFCmd.c in Sources */,
				F96D4ACD08F272C9004A47F5 /* tclUnixFile.c in Sources */,
				F96D4ACE08F272C9004A47F5 /* tclUnixInit.c in Sources */,
				F96D4ACF08F272C9004A47F5 /* tclUnixNotfy.c in Sources */,
				F96D4AD008F272C9004A47F5 /* tclUnixPipe.c in Sources */,
				F96D4AD208F272CA004A47F5 /* tclUnixSock.c in Sources */,
				F96D4AD308F272CA004A47F5 /* tclUnixTest.c in Sources */,
				F96D4AD408F272CA004A47F5 /* tclUnixThrd.c in Sources */,
				F96D4AD608F272CA004A47F5 /* tclUnixTime.c in Sources */,
				F9F4415E0C8BAE6F00BCCD67 /* tclDTrace.d in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin PBXTargetDependency section */
		F97258D30A868C6F00096C78 /* PBXTargetDependency */ = {
			isa = PBXTargetDependency;
			target = 8DD76FA90486AB0100D96B5E /* tcltest */;
			targetProxy = F97258D20A868C6F00096C78 /* PBXContainerItemProxy */;
		};
/* End PBXTargetDependency section */

/* Begin XCBuildConfiguration section */
		F91BCC4F093152310042A6BF /* ReleaseUniversal */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = ReleaseUniversal;
		};
		F91BCC50093152310042A6BF /* ReleaseUniversal */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = ReleaseUniversal;
		};
		F91BCC51093152310042A6BF /* ReleaseUniversal */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
			buildSettings = {
				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
				CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.5;
				PREBINDING = NO;
			};
			name = ReleaseUniversal;
		};
		F93084370BB93D2800CD0B9E /* DebugMemCompile */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = DebugMemCompile;
		};
		F93084380BB93D2800CD0B9E /* DebugMemCompile */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = DebugMemCompile;
		};
		F93084390BB93D2800CD0B9E /* DebugMemCompile */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = DebugMemCompile;
		};
		F930843A0BB93D2800CD0B9E /* DebugMemCompile */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --enable-symbols=all";
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.5;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = DebugMemCompile;
		};
		F9359B250DF212DA00E04F67 /* DebugGCov */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				GCC_GENERATE_TEST_COVERAGE_FILES = YES;
				GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES;
				MACOSX_DEPLOYMENT_TARGET = 10.5;
				ONLY_ACTIVE_ARCH = YES;
				OTHER_LDFLAGS = (
					"$(OTHER_LDFLAGS)",
					"-lgcov",
				);
				PREBINDING = NO;
			};
			name = DebugGCov;
		};
		F9359B260DF212DA00E04F67 /* DebugGCov */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = DebugGCov;
		};
		F9359B270DF212DA00E04F67 /* DebugGCov */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = DebugGCov;
		};
		F9359B280DF212DA00E04F67 /* DebugGCov */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = DebugGCov;
		};
		F95CC8AC09158F3100EA5ACE /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = Debug;
		};
		F95CC8AD09158F3100EA5ACE /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = Release;
		};
		F95CC8AE09158F3100EA5ACE /* DebugNoFixAndContinue */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = DebugNoFixAndContinue;
		};
		F95CC8B109158F3100EA5ACE /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_ENABLE_FIX_AND_CONTINUE = YES;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"__private_extern__=extern",
					"$(GCC_PREPROCESSOR_DEFINITIONS)",
				);
				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
				PRODUCT_NAME = tcltest;
			};
			name = Debug;
		};
		F95CC8B209158F3100EA5ACE /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = Release;
		};
		F95CC8B309158F3100EA5ACE /* DebugNoFixAndContinue */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = DebugNoFixAndContinue;
		};
		F95CC8B609158F3100EA5ACE /* Debug */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.5;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = Debug;
		};
		F95CC8B709158F3100EA5ACE /* Release */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.5;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = Release;
		};
		F95CC8B809158F3100EA5ACE /* DebugNoFixAndContinue */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.5;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = DebugNoFixAndContinue;
		};
		F97258A90A86873D00096C78 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = Debug;
		};
		F97258AA0A86873D00096C78 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = Release;
		};
		F97258AB0A86873D00096C78 /* DebugNoFixAndContinue */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = DebugNoFixAndContinue;
		};
		F97258AC0A86873D00096C78 /* ReleaseUniversal */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = ReleaseUniversal;
		};
		F97AED1B0B660B2100310EA2 /* Debug64bit */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = Debug64bit;
		};
		F97AED1C0B660B2100310EA2 /* Debug64bit */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = Debug64bit;
		};
		F97AED1D0B660B2100310EA2 /* Debug64bit */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = Debug64bit;
		};
		F97AED1E0B660B2100310EA2 /* Debug64bit */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = "$(NATIVE_ARCH_64_BIT)";
				CONFIGURE_ARGS = "--enable-64bit $(CONFIGURE_ARGS)";
				CPPFLAGS = "-arch $(NATIVE_ARCH_64_BIT) $(CPPFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.5;
				PREBINDING = NO;
			};
			name = Debug64bit;
		};
		F987512F0DE7B57E00B1C9EC /* DebugNoCF */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-corefoundation";
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.5;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = DebugNoCF;
		};
		F98751300DE7B57E00B1C9EC /* DebugNoCF */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = DebugNoCF;
		};
		F98751310DE7B57E00B1C9EC /* DebugNoCF */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = DebugNoCF;
		};
		F98751320DE7B57E00B1C9EC /* DebugNoCF */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = DebugNoCF;
		};
		F98751330DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-threads --disable-corefoundation";
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.5;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = DebugNoCFUnthreaded;
		};
		F98751340DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = DebugNoCFUnthreaded;
		};
		F98751350DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = DebugNoCFUnthreaded;
		};
		F98751360DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = DebugNoCFUnthreaded;
		};
		F9988AB10D814C6500B6B03B /* Debug gcc40 */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				GCC_VERSION = 4.0;
				MACOSX_DEPLOYMENT_TARGET = 10.5;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = "Debug gcc40";
		};
		F9988AB20D814C6500B6B03B /* Debug gcc40 */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = "Debug gcc40";
		};
		F9988AB30D814C6500B6B03B /* Debug gcc40 */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_ENABLE_FIX_AND_CONTINUE = YES;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"__private_extern__=extern",
					"$(GCC_PREPROCESSOR_DEFINITIONS)",
				);
				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
				PRODUCT_NAME = tcltest;
			};
			name = "Debug gcc40";
		};
		F9988AB40D814C6500B6B03B /* Debug gcc40 */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = "Debug gcc40";
		};
		F9988AB50D814C7500B6B03B /* Debug llvm-gcc */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				GCC = "llvm-gcc";
				GCC_VERSION = com.apple.compilers.llvmgcc42;
				MACOSX_DEPLOYMENT_TARGET = 10.5;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = "Debug llvm-gcc";
		};
		F9988AB60D814C7500B6B03B /* Debug llvm-gcc */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = "Debug llvm-gcc";
		};
		F9988AB70D814C7500B6B03B /* Debug llvm-gcc */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_ENABLE_FIX_AND_CONTINUE = YES;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"__private_extern__=extern",
					"$(GCC_PREPROCESSOR_DEFINITIONS)",
				);
				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
				PRODUCT_NAME = tcltest;
			};
			name = "Debug llvm-gcc";
		};
		F9988AB80D814C7500B6B03B /* Debug llvm-gcc */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = "Debug llvm-gcc";
		};
		F9988BB10D81586D00B6B03B /* ReleaseUniversal gcc40 */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
			buildSettings = {
				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
				CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
				GCC_VERSION = 4.0;
				MACOSX_DEPLOYMENT_TARGET = 10.5;
				PREBINDING = NO;
			};
			name = "ReleaseUniversal gcc40";
		};
		F9988BB20D81586D00B6B03B /* ReleaseUniversal gcc40 */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = "ReleaseUniversal gcc40";
		};
		F9988BB30D81586D00B6B03B /* ReleaseUniversal gcc40 */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = "ReleaseUniversal gcc40";
		};
		F9988BB40D81586D00B6B03B /* ReleaseUniversal gcc40 */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = "ReleaseUniversal gcc40";
		};
		F9988BB50D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
			buildSettings = {
				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
				CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
				DEBUG_INFORMATION_FORMAT = dwarf;
				GCC = "llvm-gcc";
				GCC_OPTIMIZATION_LEVEL = 4;
				GCC_VERSION = com.apple.compilers.llvmgcc42;
				MACOSX_DEPLOYMENT_TARGET = 10.5;
				PREBINDING = NO;
			};
			name = "ReleaseUniversal llvm-gcc";
		};
		F9988BB60D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = "ReleaseUniversal llvm-gcc";
		};
		F9988BB70D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = "ReleaseUniversal llvm-gcc";
		};
		F9988BB80D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = "ReleaseUniversal llvm-gcc";
		};
		F99EE73B0BE835310060D4AF /* DebugUnthreaded */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = DebugUnthreaded;
		};
		F99EE73C0BE835310060D4AF /* DebugLeaks */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = DebugLeaks;
		};
		F99EE73D0BE835310060D4AF /* DebugUnthreaded */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = DebugUnthreaded;
		};
		F99EE73E0BE835310060D4AF /* DebugLeaks */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = DebugLeaks;
		};
		F99EE73F0BE835310060D4AF /* DebugUnthreaded */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = DebugUnthreaded;
		};
		F99EE7400BE835310060D4AF /* DebugLeaks */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = DebugLeaks;
		};
		F99EE7410BE835310060D4AF /* DebugUnthreaded */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-threads";
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.5;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = DebugUnthreaded;
		};
		F99EE7420BE835310060D4AF /* DebugLeaks */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				GCC_PREPROCESSOR_DEFINITIONS = (
					PURIFY,
					"$(GCC_PREPROCESSOR_DEFINITIONS)",
				);
				MACOSX_DEPLOYMENT_TARGET = 10.5;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = DebugLeaks;
		};
		F9EEED960C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = ReleaseUniversal10.5SDK;
		};
		F9EEED970C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = ReleaseUniversal10.5SDK;
		};
		F9EEED980C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = ReleaseUniversal10.5SDK;
		};
		F9EEED990C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
			buildSettings = {
				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
				CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
				CPPFLAGS = "-isysroot $(SDKROOT) $(CPPFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.5;
				PREBINDING = NO;
				SDKROOT = macosx10.5;
			};
			name = ReleaseUniversal10.5SDK;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		F95CC8AB09158F3100EA5ACE /* Build configuration list for PBXNativeTarget "Tcl" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				F95CC8AC09158F3100EA5ACE /* Debug */,
				F9988AB60D814C7500B6B03B /* Debug llvm-gcc */,
				F9988AB20D814C6500B6B03B /* Debug gcc40 */,
				F95CC8AE09158F3100EA5ACE /* DebugNoFixAndContinue */,
				F99EE73B0BE835310060D4AF /* DebugUnthreaded */,
				F98751300DE7B57E00B1C9EC /* DebugNoCF */,
				F98751340DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
				F93084370BB93D2800CD0B9E /* DebugMemCompile */,
				F99EE73C0BE835310060D4AF /* DebugLeaks */,
				F9359B260DF212DA00E04F67 /* DebugGCov */,
				F97AED1B0B660B2100310EA2 /* Debug64bit */,
				F95CC8AD09158F3100EA5ACE /* Release */,
				F91BCC4F093152310042A6BF /* ReleaseUniversal */,
				F9988BB60D81587400B6B03B /* ReleaseUniversal llvm-gcc */,
				F9988BB20D81586D00B6B03B /* ReleaseUniversal gcc40 */,
				F9EEED960C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Debug;
		};
		F95CC8B009158F3100EA5ACE /* Build configuration list for PBXNativeTarget "tcltest" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				F95CC8B109158F3100EA5ACE /* Debug */,
				F9988AB70D814C7500B6B03B /* Debug llvm-gcc */,
				F9988AB30D814C6500B6B03B /* Debug gcc40 */,
				F95CC8B309158F3100EA5ACE /* DebugNoFixAndContinue */,
				F99EE73D0BE835310060D4AF /* DebugUnthreaded */,
				F98751310DE7B57E00B1C9EC /* DebugNoCF */,
				F98751350DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
				F93084380BB93D2800CD0B9E /* DebugMemCompile */,
				F99EE73E0BE835310060D4AF /* DebugLeaks */,
				F9359B270DF212DA00E04F67 /* DebugGCov */,
				F97AED1C0B660B2100310EA2 /* Debug64bit */,
				F95CC8B209158F3100EA5ACE /* Release */,
				F91BCC50093152310042A6BF /* ReleaseUniversal */,
				F9988BB70D81587400B6B03B /* ReleaseUniversal llvm-gcc */,
				F9988BB30D81586D00B6B03B /* ReleaseUniversal gcc40 */,
				F9EEED970C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Debug;
		};
		F95CC8B509158F3100EA5ACE /* Build configuration list for PBXProject "Tcl" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				F95CC8B609158F3100EA5ACE /* Debug */,
				F9988AB50D814C7500B6B03B /* Debug llvm-gcc */,
				F9988AB10D814C6500B6B03B /* Debug gcc40 */,
				F95CC8B809158F3100EA5ACE /* DebugNoFixAndContinue */,
				F99EE7410BE835310060D4AF /* DebugUnthreaded */,
				F987512F0DE7B57E00B1C9EC /* DebugNoCF */,
				F98751330DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
				F930843A0BB93D2800CD0B9E /* DebugMemCompile */,
				F99EE7420BE835310060D4AF /* DebugLeaks */,
				F9359B250DF212DA00E04F67 /* DebugGCov */,
				F97AED1E0B660B2100310EA2 /* Debug64bit */,
				F95CC8B709158F3100EA5ACE /* Release */,
				F91BCC51093152310042A6BF /* ReleaseUniversal */,
				F9988BB50D81587400B6B03B /* ReleaseUniversal llvm-gcc */,
				F9988BB10D81586D00B6B03B /* ReleaseUniversal gcc40 */,
				F9EEED990C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Debug;
		};
		F97258A80A86873D00096C78 /* Build configuration list for PBXNativeTarget "tests" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				F97258A90A86873D00096C78 /* Debug */,
				F9988AB80D814C7500B6B03B /* Debug llvm-gcc */,
				F9988AB40D814C6500B6B03B /* Debug gcc40 */,
				F97258AB0A86873D00096C78 /* DebugNoFixAndContinue */,
				F99EE73F0BE835310060D4AF /* DebugUnthreaded */,
				F98751320DE7B57E00B1C9EC /* DebugNoCF */,
				F98751360DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
				F93084390BB93D2800CD0B9E /* DebugMemCompile */,
				F99EE7400BE835310060D4AF /* DebugLeaks */,
				F9359B280DF212DA00E04F67 /* DebugGCov */,
				F97AED1D0B660B2100310EA2 /* Debug64bit */,
				F97258AA0A86873D00096C78 /* Release */,
				F97258AC0A86873D00096C78 /* ReleaseUniversal */,
				F9988BB80D81587400B6B03B /* ReleaseUniversal llvm-gcc */,
				F9988BB40D81586D00B6B03B /* ReleaseUniversal gcc40 */,
				F9EEED980C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Debug;
		};
/* End XCConfigurationList section */
	};
	rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
}

Deleted macosx/Tcl.xcodeproj/default.pbxuser.

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
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



















































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
// !$*UTF8*$!
{
	08FB7793FE84155DC02AAC07 /* Project object */ = {
		activeBuildConfigurationName = Debug;
		activeExecutable = F9E61D1C090A4282002B3151 /* tclsh */;
		activeTarget = F9E61D16090A3E94002B3151 /* Tcl */;
		codeSenseManager = F944EB9D08F798180049FDD4 /* Code sense */;
		executables = (
			F9E61D1C090A4282002B3151 /* tclsh */,
			F944EB8F08F798100049FDD4 /* tcltest */,
		);
		perUserDictionary = {
			com.apple.ide.smrt.PBXUserSmartGroupsKey.Rev10 = <040b73747265616d747970656481e8038401408484840e4e534d757461626c654172726179008484074e534172726179008484084e534f626a65637400858401690192848484134e534d757461626c6544696374696f6e6172790084840c4e5344696374696f6e6172790095960792848484084e53537472696e67019584012b046e616d658692849a9a14496d706c656d656e746174696f6e2046696c65738692849a9a195042585472616e7369656e744c6f636174696f6e4174546f708692849a9a06626f74746f6d8692849a9a0b707265666572656e63657386928497960892849a9a0669734c6561668692848484084e534e756d626572008484074e5356616c7565009584012a849696008692849a9a04726f6f748692849a9a093c50524f4a4543543e8692849a9a09726563757273697665869284a29da496018692849a9a05696d6167658692849a9a0b536d617274466f6c6465728692849a9a0763616e536176658692a892849a9a1250425850726f6a65637453636f70654b65798692849a9a035945538692849a9a0572656765788692849a9a065c2e286329248692849a9a07666e6d617463688692849a9a00868692849a9a146162736f6c75746550617468546f42756e646c658692849a9a008692849a9a0b6465736372697074696f6e8692849a9a103c6e6f206465736372697074696f6e3e8692849a9a08676c6f62616c49448692849a9a183143433045413430303433353045463930303434343130428692849a9a03636c7a8692849a9a1550425846696c656e616d65536d61727447726f7570868686>;
		};
		sourceControlManager = F944EB9C08F798180049FDD4 /* Source Control */;
		userBuildSettings = {
			SYMROOT = "${SRCROOT}/../../build/tcl";
			TCL_SRCROOT = "${SRCROOT}/../../tcl";
		};
	};
	8DD76FA90486AB0100D96B5E /* tcltest */ = {
		activeExec = 0;
		executables = (
			F944EB8F08F798100049FDD4 /* tcltest */,
		);
	};
	F944EB8F08F798100049FDD4 /* tcltest */ = {
		isa = PBXExecutable;
		activeArgIndices = (
			NO,
			NO,
			NO,
		);
		argumentStrings = (
			"${TCL_SRCROOT}/tests/all.tcl",
			"-singleproc 1",
			"-verbose \"bet\"",
		);
		autoAttachOnCrash = 1;
		breakpointsEnabled = 1;
		configStateDict = {
			"PBXLSLaunchAction-0" = {
				PBXLSLaunchAction = 0;
				PBXLSLaunchStartAction = 1;
				PBXLSLaunchStdioStyle = 2;
				PBXLSLaunchStyle = 0;
				class = PBXLSRunLaunchConfig;
				displayName = "Executable Runner";
				identifier = com.apple.Xcode.launch.runConfig;
				remoteHostInfo = "";
				startActionInfo = "";
			};
			"PBXLSLaunchAction-1" = {
				PBXLSLaunchAction = 1;
				PBXLSLaunchStartAction = 1;
				PBXLSLaunchStdioStyle = 2;
				PBXLSLaunchStyle = 0;
				class = PBXGDB_LaunchConfig;
				displayName = GDB;
				identifier = com.apple.Xcode.launch.GDBMI_Config;
				remoteHostInfo = "";
				startActionInfo = "";
			};
		};
		customDataFormattersEnabled = 1;
		dataTipCustomDataFormattersEnabled = 1;
		dataTipShowTypeColumn = 1;
		dataTipSortType = 0;
		debuggerPlugin = GDBDebugging;
		disassemblyDisplayState = 0;
		dylibVariantSuffix = "";
		enableDebugStr = 0;
		environmentEntries = (
			{
				active = YES;
				name = TCL_LIBRARY;
				value = "${TCL_SRCROOT}/library";
			},
			{
				active = YES;
				name = TCLLIBPATH;
				value = /Library/Tcl;
			},
			{
				active = NO;
				name = DYLD_PRINT_LIBRARIES;
			},
			{
				active = NO;
				name = MallocBadFreeAbort;
				value = 1;
			},
			{
				active = NO;
				name = MallocLogFile;
				value = /tmp/malloc.log;
			},
			{
				active = NO;
				name = MallocStackLogging;
				value = 1;
			},
			{
				active = NO;
				name = MallocStackLoggingNoCompact;
				value = 1;
			},
			{
				active = NO;
				name = MallocPreScribble;
				value = 1;
			},
			{
				active = NO;
				name = MallocScribble;
				value = 1;
			},
		);
		executableSystemSymbolLevel = 0;
		executableUserSymbolLevel = 0;
		libgmallocEnabled = 0;
		name = tcltest;
		showTypeColumn = 0;
		sourceDirectories = (
		);
	};
	F944EB9C08F798180049FDD4 /* Source Control */ = {
		isa = PBXSourceControlManager;
		fallbackIsa = XCSourceControlManager;
		isSCMEnabled = 0;
		repositoryNamesForRoots = {
			.. = "";
		};
		scmConfiguration = {
			CVSToolPath = /usr/bin/cvs;
			CVSUseSSH = NO;
			SubversionToolPath = /usr/bin/svn;
			repositoryNamesForRoots = {
				.. = "";
			};
		};
		scmType = scm.cvs;
	};
	F944EB9D08F798180049FDD4 /* Code sense */ = {
		isa = PBXCodeSenseManager;
		indexTemplatePath = "";
	};
	F97258A50A86873C00096C78 /* tests */ = {
		activeExec = 0;
	};
	F9E61D16090A3E94002B3151 /* Tcl */ = {
		activeExec = 0;
		executables = (
			F9E61D1C090A4282002B3151 /* tclsh */,
		);
	};
	F9E61D1C090A4282002B3151 /* tclsh */ = {
		isa = PBXExecutable;
		activeArgIndices = (
		);
		argumentStrings = (
		);
		autoAttachOnCrash = 1;
		breakpointsEnabled = 1;
		configStateDict = {
			"PBXLSLaunchAction-0" = {
				PBXLSLaunchAction = 0;
				PBXLSLaunchStartAction = 1;
				PBXLSLaunchStdioStyle = 2;
				PBXLSLaunchStyle = 0;
				class = PBXLSRunLaunchConfig;
				displayName = "Executable Runner";
				identifier = com.apple.Xcode.launch.runConfig;
				remoteHostInfo = "";
				startActionInfo = "";
			};
			"PBXLSLaunchAction-1" = {
				PBXLSLaunchAction = 1;
				PBXLSLaunchStartAction = 1;
				PBXLSLaunchStdioStyle = 2;
				PBXLSLaunchStyle = 0;
				class = PBXGDB_LaunchConfig;
				displayName = GDB;
				identifier = com.apple.Xcode.launch.GDBMI_Config;
				remoteHostInfo = "";
				startActionInfo = "";
			};
		};
		customDataFormattersEnabled = 1;
		dataTipCustomDataFormattersEnabled = 1;
		dataTipShowTypeColumn = 1;
		dataTipSortType = 0;
		debuggerPlugin = GDBDebugging;
		disassemblyDisplayState = 0;
		dylibVariantSuffix = _debug;
		enableDebugStr = 0;
		environmentEntries = (
			{
				active = NO;
				name = DYLD_PRINT_LIBRARIES;
			},
		);
		executableSystemSymbolLevel = 0;
		executableUserSymbolLevel = 0;
		libgmallocEnabled = 0;
		name = tclsh;
		showTypeColumn = 0;
		sourceDirectories = (
		);
	};
}

Deleted macosx/Tcl.xcodeproj/project.pbxproj.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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




































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 46;
	objects = {

/* Begin PBXBuildFile section */
		F90509300913A72400327603 /* tclAppInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445508F272B9004A47F5 /* tclAppInit.c */; settings = {COMPILER_FLAGS = "-DTCL_TEST -DTCL_BUILDTIME_LIBRARY=\\\"$(TCL_SRCROOT)/library\\\""; }; };
		F93599B30DF1F75400E04F67 /* tclOO.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B20DF1F75400E04F67 /* tclOO.c */; };
		F93599B70DF1F76100E04F67 /* tclOOBasic.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B60DF1F76100E04F67 /* tclOOBasic.c */; };
		F93599B90DF1F76600E04F67 /* tclOOCall.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B80DF1F76600E04F67 /* tclOOCall.c */; };
		F93599BC0DF1F77000E04F67 /* tclOODefineCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */; };
		F93599BE0DF1F77400E04F67 /* tclOOInfo.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599BD0DF1F77400E04F67 /* tclOOInfo.c */; };
		F93599C20DF1F78300E04F67 /* tclOOMethod.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C10DF1F78300E04F67 /* tclOOMethod.c */; };
		F93599C40DF1F78800E04F67 /* tclOOStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C30DF1F78800E04F67 /* tclOOStubInit.c */; };
		F93599C60DF1F78D00E04F67 /* tclOOStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */; };
		F95D77EA0DFD820D00A8BF6F /* tclIORTrans.c in Sources */ = {isa = PBXBuildFile; fileRef = F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */; };
		F96437CA0EF0D4B2003F468E /* tclZlib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96437C90EF0D4B2003F468E /* tclZlib.c */; };
		F96437E70EF0D652003F468E /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F96437E60EF0D652003F468E /* libz.dylib */; };
		F966C07508F2820D005CB29B /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F966C07408F2820D005CB29B /* CoreFoundation.framework */; };
		F96D456F08F272BB004A47F5 /* regcomp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED008F272A7004A47F5 /* regcomp.c */; };
		F96D457208F272BB004A47F5 /* regerror.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED308F272A7004A47F5 /* regerror.c */; };
		F96D457508F272BB004A47F5 /* regexec.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED608F272A7004A47F5 /* regexec.c */; };
		F96D457608F272BB004A47F5 /* regfree.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED708F272A7004A47F5 /* regfree.c */; };
		F96D457B08F272BB004A47F5 /* tclAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDC08F272A7004A47F5 /* tclAlloc.c */; settings = {COMPILER_FLAGS = "-DUSE_TCLALLOC=0"; }; };
		F96D457C08F272BB004A47F5 /* tclAsync.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDD08F272A7004A47F5 /* tclAsync.c */; };
		F96D457D08F272BB004A47F5 /* tclBasic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDE08F272A7004A47F5 /* tclBasic.c */; };
		F96D457E08F272BC004A47F5 /* tclBinary.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDF08F272A7004A47F5 /* tclBinary.c */; };
		F96D457F08F272BC004A47F5 /* tclCkalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE008F272A7004A47F5 /* tclCkalloc.c */; };
		F96D458008F272BC004A47F5 /* tclClock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE108F272A7004A47F5 /* tclClock.c */; };
		F96D458108F272BC004A47F5 /* tclCmdAH.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE208F272A7004A47F5 /* tclCmdAH.c */; };
		F96D458208F272BC004A47F5 /* tclCmdIL.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE308F272A7004A47F5 /* tclCmdIL.c */; };
		F96D458308F272BC004A47F5 /* tclCmdMZ.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */; };
		F96D458408F272BC004A47F5 /* tclCompCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE508F272A7004A47F5 /* tclCompCmds.c */; };
		F96D458508F272BC004A47F5 /* tclCompExpr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE608F272A7004A47F5 /* tclCompExpr.c */; };
		F96D458608F272BC004A47F5 /* tclCompile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE708F272A7004A47F5 /* tclCompile.c */; };
		F96D458808F272BC004A47F5 /* tclConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE908F272A7004A47F5 /* tclConfig.c */; };
		F96D458908F272BC004A47F5 /* tclDate.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEA08F272A7004A47F5 /* tclDate.c */; };
		F96D458B08F272BC004A47F5 /* tclDictObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEC08F272A7004A47F5 /* tclDictObj.c */; };
		F96D458C08F272BC004A47F5 /* tclEncoding.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EED08F272A7004A47F5 /* tclEncoding.c */; };
		F96D458D08F272BC004A47F5 /* tclEnv.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEE08F272A7004A47F5 /* tclEnv.c */; };
		F96D458E08F272BC004A47F5 /* tclEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEF08F272A7004A47F5 /* tclEvent.c */; };
		F96D458F08F272BC004A47F5 /* tclExecute.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF008F272A7004A47F5 /* tclExecute.c */; };
		F96D459008F272BC004A47F5 /* tclFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF108F272A7004A47F5 /* tclFCmd.c */; };
		F96D459108F272BC004A47F5 /* tclFileName.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF208F272A7004A47F5 /* tclFileName.c */; };
		F96D459308F272BC004A47F5 /* tclGet.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF408F272A7004A47F5 /* tclGet.c */; };
		F96D459508F272BC004A47F5 /* tclHash.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF608F272A7004A47F5 /* tclHash.c */; };
		F96D459608F272BC004A47F5 /* tclHistory.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF708F272A7004A47F5 /* tclHistory.c */; };
		F96D459708F272BC004A47F5 /* tclIndexObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF808F272A7004A47F5 /* tclIndexObj.c */; };
		F96D459B08F272BC004A47F5 /* tclInterp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFC08F272A7004A47F5 /* tclInterp.c */; };
		F96D459D08F272BC004A47F5 /* tclIO.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFE08F272A7004A47F5 /* tclIO.c */; };
		F96D459F08F272BC004A47F5 /* tclIOCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0008F272A7004A47F5 /* tclIOCmd.c */; };
		F96D45A008F272BC004A47F5 /* tclIOGT.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0108F272A7004A47F5 /* tclIOGT.c */; };
		F96D45A108F272BC004A47F5 /* tclIORChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0208F272A7004A47F5 /* tclIORChan.c */; };
		F96D45A208F272BC004A47F5 /* tclIOSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0308F272A7004A47F5 /* tclIOSock.c */; };
		F96D45A308F272BC004A47F5 /* tclIOUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0408F272A7004A47F5 /* tclIOUtil.c */; };
		F96D45A408F272BC004A47F5 /* tclLink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0508F272A7004A47F5 /* tclLink.c */; };
		F96D45A508F272BC004A47F5 /* tclListObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0608F272A7004A47F5 /* tclListObj.c */; };
		F96D45A608F272BC004A47F5 /* tclLiteral.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0708F272A7004A47F5 /* tclLiteral.c */; };
		F96D45A708F272BC004A47F5 /* tclLoad.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0808F272A7004A47F5 /* tclLoad.c */; };
		F96D45A908F272BC004A47F5 /* tclMain.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0A08F272A7004A47F5 /* tclMain.c */; };
		F96D45AA08F272BC004A47F5 /* tclNamesp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0B08F272A7004A47F5 /* tclNamesp.c */; };
		F96D45AB08F272BC004A47F5 /* tclNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0C08F272A7004A47F5 /* tclNotify.c */; };
		F96D45AC08F272BC004A47F5 /* tclObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0D08F272A7004A47F5 /* tclObj.c */; };
		F96D45AD08F272BC004A47F5 /* tclPanic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0E08F272A7004A47F5 /* tclPanic.c */; };
		F96D45AE08F272BC004A47F5 /* tclParse.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0F08F272A7004A47F5 /* tclParse.c */; };
		F96D45B008F272BC004A47F5 /* tclPathObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1108F272A7004A47F5 /* tclPathObj.c */; };
		F96D45B108F272BC004A47F5 /* tclPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1208F272A7004A47F5 /* tclPipe.c */; };
		F96D45B208F272BC004A47F5 /* tclPkg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1308F272A7004A47F5 /* tclPkg.c */; };
		F96D45B308F272BC004A47F5 /* tclPkgConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */; settings = {COMPILER_FLAGS = "-DCFG_INSTALL_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_INSTALL_BINDIR=\\\"$(BINDIR)\\\" -DCFG_INSTALL_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_INSTALL_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_INSTALL_DOCDIR=\\\"$(MANDIR)\\\" -DCFG_RUNTIME_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_RUNTIME_BINDIR=\\\"$(BINDIR)\\\" -DCFG_RUNTIME_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_RUNTIME_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_RUNTIME_DOCDIR=\\\"$(MANDIR)\\\""; }; };
		F96D45B608F272BC004A47F5 /* tclPosixStr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1708F272A7004A47F5 /* tclPosixStr.c */; };
		F96D45B708F272BC004A47F5 /* tclPreserve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1808F272A7004A47F5 /* tclPreserve.c */; };
		F96D45B808F272BC004A47F5 /* tclProc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1908F272A7004A47F5 /* tclProc.c */; };
		F96D45B908F272BC004A47F5 /* tclRegexp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1A08F272A7004A47F5 /* tclRegexp.c */; };
		F96D45BB08F272BC004A47F5 /* tclResolve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1C08F272A7004A47F5 /* tclResolve.c */; };
		F96D45BC08F272BC004A47F5 /* tclResult.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1D08F272A7004A47F5 /* tclResult.c */; };
		F96D45BD08F272BC004A47F5 /* tclScan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1E08F272A7004A47F5 /* tclScan.c */; };
		F96D45BE08F272BC004A47F5 /* tclStringObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1F08F272A7004A47F5 /* tclStringObj.c */; };
		F96D45C308F272BC004A47F5 /* tclStrToD.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2408F272A7004A47F5 /* tclStrToD.c */; };
		F96D45C408F272BC004A47F5 /* tclStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2508F272A7004A47F5 /* tclStubInit.c */; };
		F96D45C508F272BC004A47F5 /* tclStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2608F272A7004A47F5 /* tclStubLib.c */; };
		F96D45C608F272BC004A47F5 /* tclTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2708F272A7004A47F5 /* tclTest.c */; };
		F96D45C708F272BC004A47F5 /* tclTestObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2808F272A7004A47F5 /* tclTestObj.c */; };
		F96D45C808F272BC004A47F5 /* tclTestProcBodyObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */; };
		F96D45C908F272BC004A47F5 /* tclThread.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2A08F272A7004A47F5 /* tclThread.c */; };
		F96D45CA08F272BC004A47F5 /* tclThreadAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */; };
		F96D45CB08F272BC004A47F5 /* tclThreadJoin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */; };
		F96D45CC08F272BC004A47F5 /* tclThreadStorage.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */; };
		F96D45CD08F272BC004A47F5 /* tclThreadTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */; };
		F96D45CE08F272BC004A47F5 /* tclTimer.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2F08F272A7004A47F5 /* tclTimer.c */; };
		F96D45D008F272BC004A47F5 /* tclTomMathInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */; };
		F96D45D108F272BC004A47F5 /* tclTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3208F272A7004A47F5 /* tclTrace.c */; };
		F96D45D308F272BC004A47F5 /* tclUtf.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3408F272A7004A47F5 /* tclUtf.c */; };
		F96D45D408F272BC004A47F5 /* tclUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3508F272A7004A47F5 /* tclUtil.c */; };
		F96D45D508F272BC004A47F5 /* tclVar.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3608F272A7004A47F5 /* tclVar.c */; };
		F96D48E208F272C3004A47F5 /* bn_fast_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */; };
		F96D48E408F272C3004A47F5 /* bn_fast_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */; };
		F96D48E708F272C3004A47F5 /* bn_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426908F272B3004A47F5 /* bn_mp_add.c */; };
		F96D48E808F272C3004A47F5 /* bn_mp_add_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */; };
		F96D48EB08F272C3004A47F5 /* bn_mp_clamp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */; };
		F96D48EC08F272C3004A47F5 /* bn_mp_clear.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426E08F272B3004A47F5 /* bn_mp_clear.c */; };
		F96D48ED08F272C3004A47F5 /* bn_mp_clear_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */; };
		F96D48EE08F272C3004A47F5 /* bn_mp_cmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427008F272B3004A47F5 /* bn_mp_cmp.c */; };
		F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */; };
		F96D48F208F272C3004A47F5 /* bn_mp_cnt_lsb.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_cnt_lsb.c */; };
		F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_copy.c */; };
		F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */; };
		F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427608F272B3004A47F5 /* bn_mp_div.c */; };
		F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427708F272B3004A47F5 /* bn_mp_div_2.c */; };
		F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */; };
		F96D48F708F272C3004A47F5 /* bn_mp_div_3.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427908F272B3004A47F5 /* bn_mp_div_3.c */; };
		F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */; };
		F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427E08F272B3004A47F5 /* bn_mp_exch.c */; };
		F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428708F272B3004A47F5 /* bn_mp_grow.c */; };
		F96D490608F272C3004A47F5 /* bn_mp_init.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428808F272B3004A47F5 /* bn_mp_init.c */; };
		F96D490708F272C3004A47F5 /* bn_mp_init_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */; };
		F96D490808F272C3004A47F5 /* bn_mp_init_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */; };
		F96D490908F272C3004A47F5 /* bn_mp_init_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */; };
		F96D490B08F272C3004A47F5 /* bn_mp_init_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */; };
		F96D491008F272C3004A47F5 /* bn_mp_karatsuba_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */; };
		F96D491108F272C3004A47F5 /* bn_mp_karatsuba_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */; };
		F96D491308F272C3004A47F5 /* bn_mp_lshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429508F272B3004A47F5 /* bn_mp_lshd.c */; };
		F96D491408F272C3004A47F5 /* bn_mp_mod.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429608F272B3004A47F5 /* bn_mp_mod.c */; };
		F96D491508F272C3004A47F5 /* bn_mp_mod_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */; };
		F96D491A08F272C3004A47F5 /* bn_mp_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429C08F272B3004A47F5 /* bn_mp_mul.c */; };
		F96D491B08F272C3004A47F5 /* bn_mp_mul_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */; };
		F96D491C08F272C3004A47F5 /* bn_mp_mul_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */; };
		F96D491D08F272C3004A47F5 /* bn_mp_mul_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */; };
		F96D492908F272C3004A47F5 /* bn_mp_radix_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */; };
		F96D492A08F272C3004A47F5 /* bn_mp_radix_smap.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */; };
		F96D492C08F272C3004A47F5 /* bn_mp_read_radix.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */; };
		F96D493708F272C3004A47F5 /* bn_mp_rshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */; };
		F96D493808F272C3004A47F5 /* bn_mp_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BA08F272B3004A47F5 /* bn_mp_set.c */; };
		F96D493C08F272C3004A47F5 /* bn_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */; };
		F96D493F08F272C3004A47F5 /* bn_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C108F272B3004A47F5 /* bn_mp_sub.c */; };
		F96D494008F272C3004A47F5 /* bn_mp_sub_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */; };
		F96D494608F272C3004A47F5 /* bn_mp_toom_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */; };
		F96D494708F272C3004A47F5 /* bn_mp_toom_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */; };
		F96D494908F272C3004A47F5 /* bn_mp_to_radix.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CB08F272B3004A47F5 /* bn_mp_to_radix.c */; };
		F96D494C08F272C3004A47F5 /* bn_mp_zero.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */; };
		F96D494F08F272C3004A47F5 /* bn_s_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */; };
		F96D495108F272C3004A47F5 /* bn_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */; };
		F96D495308F272C3004A47F5 /* bn_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */; };
		F96D495408F272C3004A47F5 /* bn_s_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */; };
		F96D49A908F272C4004A47F5 /* tclMacOSXBundle.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */; };
		F96D49AD08F272C4004A47F5 /* tclMacOSXFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */; };
		F96D49AE08F272C4004A47F5 /* tclMacOSXNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */; };
		F96D4AC608F272C9004A47F5 /* tclLoadDyld.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445B08F272B9004A47F5 /* tclLoadDyld.c */; settings = {COMPILER_FLAGS = "-Wno-deprecated-declarations"; }; };
		F96D4ACA08F272C9004A47F5 /* tclUnixChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445F08F272B9004A47F5 /* tclUnixChan.c */; };
		F96D4ACB08F272C9004A47F5 /* tclUnixEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446008F272B9004A47F5 /* tclUnixEvent.c */; };
		F96D4ACC08F272C9004A47F5 /* tclUnixFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446108F272B9004A47F5 /* tclUnixFCmd.c */; };
		F96D4ACD08F272C9004A47F5 /* tclUnixFile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446208F272B9004A47F5 /* tclUnixFile.c */; };
		F96D4ACE08F272C9004A47F5 /* tclUnixInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446308F272B9004A47F5 /* tclUnixInit.c */; settings = {COMPILER_FLAGS = "-DTCL_LIBRARY=\\\"$(TCL_LIBRARY)\\\" -DTCL_PACKAGE_PATH=\\\"$(TCL_PACKAGE_PATH)\\\""; }; };
		F96D4ACF08F272C9004A47F5 /* tclUnixNotfy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446408F272B9004A47F5 /* tclUnixNotfy.c */; };
		F96D4AD008F272C9004A47F5 /* tclUnixPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446508F272B9004A47F5 /* tclUnixPipe.c */; };
		F96D4AD208F272CA004A47F5 /* tclUnixSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446708F272B9004A47F5 /* tclUnixSock.c */; };
		F96D4AD308F272CA004A47F5 /* tclUnixTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446808F272B9004A47F5 /* tclUnixTest.c */; };
		F96D4AD408F272CA004A47F5 /* tclUnixThrd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446908F272B9004A47F5 /* tclUnixThrd.c */; };
		F96D4AD608F272CA004A47F5 /* tclUnixTime.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446B08F272B9004A47F5 /* tclUnixTime.c */; };
		F9E61D28090A481F002B3151 /* bn_mp_cmp_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */; };
		F9E61D29090A486C002B3151 /* bn_mp_neg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A208F272B3004A47F5 /* bn_mp_neg.c */; };
		F9E61D2A090A4891002B3151 /* bn_mp_sqrt.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */; };
		F9E61D2B090A48A4002B3151 /* bn_mp_and.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426C08F272B3004A47F5 /* bn_mp_and.c */; };
		F9E61D2C090A48AC002B3151 /* bn_mp_expt_u32.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427F08F272B3004A47F5 /* bn_mp_expt_u32.c */; };
		F9E61D2D090A48BB002B3151 /* bn_mp_xor.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */; };
		F9E61D2E090A48BF002B3151 /* bn_mp_or.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A308F272B3004A47F5 /* bn_mp_or.c */; };
		F9E61D2F090A48C7002B3151 /* bn_mp_shrink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */; };
		F9E61D31090A48F9002B3151 /* bn_mp_to_ubin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C608F272B3004A47F5 /* bn_mp_to_ubin.c */; };
		F9E61D32090A48FA002B3151 /* bn_mp_ubin_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CC08F272B3004A47F5 /* bn_mp_ubin_size.c */; };
		F9F4415E0C8BAE6F00BCCD67 /* tclDTrace.d in Sources */ = {isa = PBXBuildFile; fileRef = F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */; };
		F9FC77B80AB29E9100B7077D /* tclUnixCompat.c in Sources */ = {isa = PBXBuildFile; fileRef = F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
		F97258D20A868C6F00096C78 /* PBXContainerItemProxy */ = {
			isa = PBXContainerItemProxy;
			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
			proxyType = 1;
			remoteGlobalIDString = 8DD76FA90486AB0100D96B5E;
			remoteInfo = tcltest;
		};
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
		8DD76FB20486AB0100D96B5E /* tcltest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tcltest; sourceTree = BUILT_PRODUCTS_DIR; };
		F915432A0EF201CF0032D1E8 /* zlib.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = zlib.test; sourceTree = "<group>"; };
		F915432D0EF201EE0032D1E8 /* zlib.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = zlib.n; sourceTree = "<group>"; };
		F9183E640EFC80CD0030B814 /* throw.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = throw.n; sourceTree = "<group>"; };
		F9183E650EFC80D70030B814 /* try.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = try.n; sourceTree = "<group>"; };
		F9183E6A0EFC81560030B814 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F9183E8F0EFC817B0030B814 /* tdbc */ = {isa = PBXFileReference; lastKnownFileType = folder; path = tdbc; sourceTree = "<group>"; };
		F91DC23C0E44C51B002CB8D1 /* nre.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = nre.test; sourceTree = "<group>"; };
		F91E62260C1AE686006C9D96 /* Tclsh-Info.plist.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "Tclsh-Info.plist.in"; sourceTree = "<group>"; };
		F92D7F100DE777240033A13A /* tsdPerf.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tsdPerf.tcl; sourceTree = "<group>"; };
		F93599B20DF1F75400E04F67 /* tclOO.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOO.c; sourceTree = "<group>"; };
		F93599B40DF1F75900E04F67 /* tclOO.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclOO.decls; sourceTree = "<group>"; };
		F93599B50DF1F75D00E04F67 /* tclOO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOO.h; sourceTree = "<group>"; };
		F93599B60DF1F76100E04F67 /* tclOOBasic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOBasic.c; sourceTree = "<group>"; };
		F93599B80DF1F76600E04F67 /* tclOOCall.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOCall.c; sourceTree = "<group>"; };
		F93599BA0DF1F76A00E04F67 /* tclOODecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOODecls.h; sourceTree = "<group>"; };
		F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOODefineCmds.c; sourceTree = "<group>"; };
		F93599BD0DF1F77400E04F67 /* tclOOInfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOInfo.c; sourceTree = "<group>"; };
		F93599BF0DF1F77900E04F67 /* tclOOInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOOInt.h; sourceTree = "<group>"; };
		F93599C00DF1F77D00E04F67 /* tclOOIntDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOOIntDecls.h; sourceTree = "<group>"; };
		F93599C10DF1F78300E04F67 /* tclOOMethod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOMethod.c; sourceTree = "<group>"; };
		F93599C30DF1F78800E04F67 /* tclOOStubInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOStubInit.c; sourceTree = "<group>"; };
		F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOStubLib.c; sourceTree = "<group>"; };
		F93599C80DF1F81900E04F67 /* oo.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = oo.test; sourceTree = "<group>"; };
		F93599CF0DF1F87F00E04F67 /* Class.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Class.3; sourceTree = "<group>"; };
		F93599D00DF1F89E00E04F67 /* class.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = class.n; sourceTree = "<group>"; };
		F93599D20DF1F8DF00E04F67 /* copy.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = copy.n; sourceTree = "<group>"; };
		F93599D30DF1F8F500E04F67 /* define.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = define.n; sourceTree = "<group>"; };
		F93599D40DF1F91900E04F67 /* Method.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Method.3; sourceTree = "<group>"; };
		F93599D50DF1F93700E04F67 /* my.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = my.n; sourceTree = "<group>"; };
		F93599D60DF1F95000E04F67 /* next.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = next.n; sourceTree = "<group>"; };
		F93599D70DF1F96800E04F67 /* object.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = object.n; sourceTree = "<group>"; };
		F93599D80DF1F98300E04F67 /* self.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = self.n; sourceTree = "<group>"; };
		F946FB8B0FBE3AED00CD6495 /* itcl */ = {isa = PBXFileReference; lastKnownFileType = folder; path = itcl; sourceTree = "<group>"; };
		F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIORTrans.c; sourceTree = "<group>"; };
		F95FAFF90B34F1130072E431 /* macOSXLoad.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = macOSXLoad.test; sourceTree = "<group>"; };
		F96437C90EF0D4B2003F468E /* tclZlib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclZlib.c; sourceTree = "<group>"; };
		F96437E60EF0D652003F468E /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = "<absolute>"; };
		F966C07408F2820D005CB29B /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
		F96D3DFA08F272A4004A47F5 /* ChangeLog */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = ChangeLog; sourceTree = "<group>"; };
		F96D3DFB08F272A4004A47F5 /* changes */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = changes; sourceTree = "<group>"; };
		F96D3DFD08F272A4004A47F5 /* Access.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Access.3; sourceTree = "<group>"; };
		F96D3DFE08F272A4004A47F5 /* AddErrInfo.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AddErrInfo.3; sourceTree = "<group>"; };
		F96D3DFF08F272A4004A47F5 /* after.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = after.n; sourceTree = "<group>"; };
		F96D3E0008F272A4004A47F5 /* Alloc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Alloc.3; sourceTree = "<group>"; };
		F96D3E0108F272A4004A47F5 /* AllowExc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AllowExc.3; sourceTree = "<group>"; };
		F96D3E0208F272A4004A47F5 /* append.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = append.n; sourceTree = "<group>"; };
		F96D3E0308F272A4004A47F5 /* AppInit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AppInit.3; sourceTree = "<group>"; };
		F96D3E0408F272A5004A47F5 /* array.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = array.n; sourceTree = "<group>"; };
		F96D3E0508F272A5004A47F5 /* AssocData.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AssocData.3; sourceTree = "<group>"; };
		F96D3E0608F272A5004A47F5 /* Async.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Async.3; sourceTree = "<group>"; };
		F96D3E0708F272A5004A47F5 /* BackgdErr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = BackgdErr.3; sourceTree = "<group>"; };
		F96D3E0808F272A5004A47F5 /* Backslash.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Backslash.3; sourceTree = "<group>"; };
		F96D3E0908F272A5004A47F5 /* bgerror.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = bgerror.n; sourceTree = "<group>"; };
		F96D3E0A08F272A5004A47F5 /* binary.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = binary.n; sourceTree = "<group>"; };
		F96D3E0B08F272A5004A47F5 /* BoolObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = BoolObj.3; sourceTree = "<group>"; };
		F96D3E0C08F272A5004A47F5 /* break.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = break.n; sourceTree = "<group>"; };
		F96D3E0D08F272A5004A47F5 /* ByteArrObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ByteArrObj.3; sourceTree = "<group>"; };
		F96D3E0E08F272A5004A47F5 /* CallDel.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CallDel.3; sourceTree = "<group>"; };
		F96D3E0F08F272A5004A47F5 /* case.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = case.n; sourceTree = "<group>"; };
		F96D3E1008F272A5004A47F5 /* catch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = catch.n; sourceTree = "<group>"; };
		F96D3E1108F272A5004A47F5 /* cd.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = cd.n; sourceTree = "<group>"; };
		F96D3E1208F272A5004A47F5 /* chan.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = chan.n; sourceTree = "<group>"; };
		F96D3E1308F272A5004A47F5 /* ChnlStack.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ChnlStack.3; sourceTree = "<group>"; };
		F96D3E1408F272A5004A47F5 /* clock.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = clock.n; sourceTree = "<group>"; };
		F96D3E1508F272A5004A47F5 /* close.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = close.n; sourceTree = "<group>"; };
		F96D3E1608F272A5004A47F5 /* CmdCmplt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CmdCmplt.3; sourceTree = "<group>"; };
		F96D3E1708F272A5004A47F5 /* Concat.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Concat.3; sourceTree = "<group>"; };
		F96D3E1808F272A5004A47F5 /* concat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = concat.n; sourceTree = "<group>"; };
		F96D3E1908F272A5004A47F5 /* continue.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = continue.n; sourceTree = "<group>"; };
		F96D3E1A08F272A5004A47F5 /* CrtChannel.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtChannel.3; sourceTree = "<group>"; };
		F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtChnlHdlr.3; sourceTree = "<group>"; };
		F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCloseHdlr.3; sourceTree = "<group>"; };
		F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCommand.3; sourceTree = "<group>"; };
		F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtFileHdlr.3; sourceTree = "<group>"; };
		F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtInterp.3; sourceTree = "<group>"; };
		F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtMathFnc.3; sourceTree = "<group>"; };
		F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtObjCmd.3; sourceTree = "<group>"; };
		F96D3E2208F272A5004A47F5 /* CrtAlias.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtAlias.3; sourceTree = "<group>"; };
		F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTimerHdlr.3; sourceTree = "<group>"; };
		F96D3E2408F272A5004A47F5 /* CrtTrace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTrace.3; sourceTree = "<group>"; };
		F96D3E2508F272A5004A47F5 /* dde.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dde.n; sourceTree = "<group>"; };
		F96D3E2608F272A5004A47F5 /* DetachPids.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DetachPids.3; sourceTree = "<group>"; };
		F96D3E2708F272A5004A47F5 /* dict.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dict.n; sourceTree = "<group>"; };
		F96D3E2808F272A5004A47F5 /* DictObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DictObj.3; sourceTree = "<group>"; };
		F96D3E2908F272A5004A47F5 /* DoOneEvent.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoOneEvent.3; sourceTree = "<group>"; };
		F96D3E2A08F272A5004A47F5 /* DoubleObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoubleObj.3; sourceTree = "<group>"; };
		F96D3E2B08F272A5004A47F5 /* DoWhenIdle.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoWhenIdle.3; sourceTree = "<group>"; };
		F96D3E2C08F272A5004A47F5 /* DString.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DString.3; sourceTree = "<group>"; };
		F96D3E2D08F272A5004A47F5 /* DumpActiveMemory.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DumpActiveMemory.3; sourceTree = "<group>"; };
		F96D3E2E08F272A5004A47F5 /* Encoding.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Encoding.3; sourceTree = "<group>"; };
		F96D3E2F08F272A5004A47F5 /* encoding.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = encoding.n; sourceTree = "<group>"; };
		F96D3E3008F272A5004A47F5 /* Ensemble.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Ensemble.3; sourceTree = "<group>"; };
		F96D3E3108F272A5004A47F5 /* Environment.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Environment.3; sourceTree = "<group>"; };
		F96D3E3208F272A5004A47F5 /* eof.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = eof.n; sourceTree = "<group>"; };
		F96D3E3308F272A5004A47F5 /* error.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = error.n; sourceTree = "<group>"; };
		F96D3E3408F272A5004A47F5 /* Eval.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Eval.3; sourceTree = "<group>"; };
		F96D3E3508F272A5004A47F5 /* eval.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = eval.n; sourceTree = "<group>"; };
		F96D3E3608F272A5004A47F5 /* exec.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = exec.n; sourceTree = "<group>"; };
		F96D3E3708F272A5004A47F5 /* Exit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Exit.3; sourceTree = "<group>"; };
		F96D3E3808F272A5004A47F5 /* exit.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = exit.n; sourceTree = "<group>"; };
		F96D3E3908F272A5004A47F5 /* expr.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = expr.n; sourceTree = "<group>"; };
		F96D3E3A08F272A5004A47F5 /* ExprLong.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ExprLong.3; sourceTree = "<group>"; };
		F96D3E3B08F272A5004A47F5 /* ExprLongObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ExprLongObj.3; sourceTree = "<group>"; };
		F96D3E3C08F272A5004A47F5 /* fblocked.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fblocked.n; sourceTree = "<group>"; };
		F96D3E3D08F272A5004A47F5 /* fconfigure.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fconfigure.n; sourceTree = "<group>"; };
		F96D3E3E08F272A5004A47F5 /* fcopy.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fcopy.n; sourceTree = "<group>"; };
		F96D3E3F08F272A5004A47F5 /* file.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = file.n; sourceTree = "<group>"; };
		F96D3E4008F272A5004A47F5 /* fileevent.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fileevent.n; sourceTree = "<group>"; };
		F96D3E4108F272A5004A47F5 /* filename.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = filename.n; sourceTree = "<group>"; };
		F96D3E4208F272A5004A47F5 /* FileSystem.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FileSystem.3; sourceTree = "<group>"; };
		F96D3E4308F272A5004A47F5 /* FindExec.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FindExec.3; sourceTree = "<group>"; };
		F96D3E4408F272A5004A47F5 /* flush.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = flush.n; sourceTree = "<group>"; };
		F96D3E4508F272A5004A47F5 /* for.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = for.n; sourceTree = "<group>"; };
		F96D3E4608F272A5004A47F5 /* foreach.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = foreach.n; sourceTree = "<group>"; };
		F96D3E4708F272A5004A47F5 /* format.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = format.n; sourceTree = "<group>"; };
		F96D3E4808F272A5004A47F5 /* GetCwd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetCwd.3; sourceTree = "<group>"; };
		F96D3E4908F272A5004A47F5 /* GetHostName.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetHostName.3; sourceTree = "<group>"; };
		F96D3E4A08F272A5004A47F5 /* GetIndex.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetIndex.3; sourceTree = "<group>"; };
		F96D3E4B08F272A5004A47F5 /* GetInt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetInt.3; sourceTree = "<group>"; };
		F96D3E4C08F272A5004A47F5 /* GetOpnFl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetOpnFl.3; sourceTree = "<group>"; };
		F96D3E4D08F272A5004A47F5 /* gets.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = gets.n; sourceTree = "<group>"; };
		F96D3E4E08F272A5004A47F5 /* GetStdChan.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetStdChan.3; sourceTree = "<group>"; };
		F96D3E4F08F272A5004A47F5 /* GetTime.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetTime.3; sourceTree = "<group>"; };
		F96D3E5008F272A5004A47F5 /* GetVersion.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetVersion.3; sourceTree = "<group>"; };
		F96D3E5108F272A5004A47F5 /* glob.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = glob.n; sourceTree = "<group>"; };
		F96D3E5208F272A6004A47F5 /* global.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = global.n; sourceTree = "<group>"; };
		F96D3E5308F272A6004A47F5 /* Hash.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Hash.3; sourceTree = "<group>"; };
		F96D3E5408F272A6004A47F5 /* history.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = history.n; sourceTree = "<group>"; };
		F96D3E5508F272A6004A47F5 /* http.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = http.n; sourceTree = "<group>"; };
		F96D3E5608F272A6004A47F5 /* if.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = if.n; sourceTree = "<group>"; };
		F96D3E5708F272A6004A47F5 /* incr.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = incr.n; sourceTree = "<group>"; };
		F96D3E5808F272A6004A47F5 /* info.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = info.n; sourceTree = "<group>"; };
		F96D3E5908F272A6004A47F5 /* Init.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Init.3; sourceTree = "<group>"; };
		F96D3E5A08F272A6004A47F5 /* InitStubs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = InitStubs.3; sourceTree = "<group>"; };
		F96D3E5B08F272A6004A47F5 /* Interp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Interp.3; sourceTree = "<group>"; };
		F96D3E5C08F272A6004A47F5 /* interp.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = interp.n; sourceTree = "<group>"; };
		F96D3E5D08F272A6004A47F5 /* IntObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = IntObj.3; sourceTree = "<group>"; };
		F96D3E5E08F272A6004A47F5 /* join.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = join.n; sourceTree = "<group>"; };
		F96D3E5F08F272A6004A47F5 /* lappend.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lappend.n; sourceTree = "<group>"; };
		F96D3E6008F272A6004A47F5 /* lassign.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lassign.n; sourceTree = "<group>"; };
		F96D3E6108F272A6004A47F5 /* library.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = library.n; sourceTree = "<group>"; };
		F96D3E6208F272A6004A47F5 /* Limit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Limit.3; sourceTree = "<group>"; };
		F96D3E6308F272A6004A47F5 /* lindex.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lindex.n; sourceTree = "<group>"; };
		F96D3E6408F272A6004A47F5 /* LinkVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = LinkVar.3; sourceTree = "<group>"; };
		F96D3E6508F272A6004A47F5 /* linsert.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = linsert.n; sourceTree = "<group>"; };
		F96D3E6608F272A6004A47F5 /* list.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = list.n; sourceTree = "<group>"; };
		F96D3E6708F272A6004A47F5 /* ListObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ListObj.3; sourceTree = "<group>"; };
		F96D3E6808F272A6004A47F5 /* llength.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = llength.n; sourceTree = "<group>"; };
		F96D3E6908F272A6004A47F5 /* load.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = load.n; sourceTree = "<group>"; };
		F96D3E6A08F272A6004A47F5 /* lrange.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lrange.n; sourceTree = "<group>"; };
		F96D3E6B08F272A6004A47F5 /* lrepeat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lrepeat.n; sourceTree = "<group>"; };
		F96D3E6C08F272A6004A47F5 /* lreplace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lreplace.n; sourceTree = "<group>"; };
		F96D3E6D08F272A6004A47F5 /* lsearch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lsearch.n; sourceTree = "<group>"; };
		F96D3E6E08F272A6004A47F5 /* lset.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lset.n; sourceTree = "<group>"; };
		F96D3E6F08F272A6004A47F5 /* lsort.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lsort.n; sourceTree = "<group>"; };
		F96D3E7008F272A6004A47F5 /* man.macros */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = man.macros; sourceTree = "<group>"; };
		F96D3E7108F272A6004A47F5 /* mathfunc.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = mathfunc.n; sourceTree = "<group>"; };
		F96D3E7208F272A6004A47F5 /* memory.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = memory.n; sourceTree = "<group>"; };
		F96D3E7308F272A6004A47F5 /* msgcat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = msgcat.n; sourceTree = "<group>"; };
		F96D3E7408F272A6004A47F5 /* Namespace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Namespace.3; sourceTree = "<group>"; };
		F96D3E7508F272A6004A47F5 /* namespace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = namespace.n; sourceTree = "<group>"; };
		F96D3E7608F272A6004A47F5 /* Notifier.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Notifier.3; sourceTree = "<group>"; };
		F96D3E7708F272A6004A47F5 /* Object.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Object.3; sourceTree = "<group>"; };
		F96D3E7808F272A6004A47F5 /* ObjectType.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ObjectType.3; sourceTree = "<group>"; };
		F96D3E7908F272A6004A47F5 /* open.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = open.n; sourceTree = "<group>"; };
		F96D3E7A08F272A6004A47F5 /* OpenFileChnl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = OpenFileChnl.3; sourceTree = "<group>"; };
		F96D3E7B08F272A6004A47F5 /* OpenTcp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = OpenTcp.3; sourceTree = "<group>"; };
		F96D3E7C08F272A6004A47F5 /* package.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = package.n; sourceTree = "<group>"; };
		F96D3E7D08F272A6004A47F5 /* packagens.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = packagens.n; sourceTree = "<group>"; };
		F96D3E7E08F272A6004A47F5 /* Panic.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Panic.3; sourceTree = "<group>"; };
		F96D3E7F08F272A6004A47F5 /* ParseCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ParseCmd.3; sourceTree = "<group>"; };
		F96D3E8008F272A6004A47F5 /* pid.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pid.n; sourceTree = "<group>"; };
		F96D3E8108F272A6004A47F5 /* pkgMkIndex.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pkgMkIndex.n; sourceTree = "<group>"; };
		F96D3E8208F272A6004A47F5 /* PkgRequire.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = PkgRequire.3; sourceTree = "<group>"; };
		F96D3E8308F272A6004A47F5 /* Preserve.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Preserve.3; sourceTree = "<group>"; };
		F96D3E8408F272A6004A47F5 /* PrintDbl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = PrintDbl.3; sourceTree = "<group>"; };
		F96D3E8508F272A6004A47F5 /* proc.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = proc.n; sourceTree = "<group>"; };
		F96D3E8608F272A6004A47F5 /* puts.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = puts.n; sourceTree = "<group>"; };
		F96D3E8708F272A6004A47F5 /* pwd.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pwd.n; sourceTree = "<group>"; };
		F96D3E8808F272A6004A47F5 /* re_syntax.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = re_syntax.n; sourceTree = "<group>"; };
		F96D3E8908F272A6004A47F5 /* read.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = read.n; sourceTree = "<group>"; };
		F96D3E8A08F272A6004A47F5 /* RecEvalObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RecEvalObj.3; sourceTree = "<group>"; };
		F96D3E8B08F272A6004A47F5 /* RecordEval.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RecordEval.3; sourceTree = "<group>"; };
		F96D3E8C08F272A6004A47F5 /* RegConfig.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RegConfig.3; sourceTree = "<group>"; };
		F96D3E8D08F272A6004A47F5 /* RegExp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RegExp.3; sourceTree = "<group>"; };
		F96D3E8E08F272A6004A47F5 /* regexp.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = regexp.n; sourceTree = "<group>"; };
		F96D3E8F08F272A6004A47F5 /* registry.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = registry.n; sourceTree = "<group>"; };
		F96D3E9008F272A6004A47F5 /* regsub.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = regsub.n; sourceTree = "<group>"; };
		F96D3E9108F272A6004A47F5 /* rename.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = rename.n; sourceTree = "<group>"; };
		F96D3E9208F272A6004A47F5 /* return.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = return.n; sourceTree = "<group>"; };
		F96D3E9308F272A6004A47F5 /* safe.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = safe.n; sourceTree = "<group>"; };
		F96D3E9408F272A6004A47F5 /* SaveResult.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SaveResult.3; sourceTree = "<group>"; };
		F96D3E9508F272A6004A47F5 /* scan.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = scan.n; sourceTree = "<group>"; };
		F96D3E9608F272A6004A47F5 /* seek.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = seek.n; sourceTree = "<group>"; };
		F96D3E9708F272A6004A47F5 /* set.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = set.n; sourceTree = "<group>"; };
		F96D3E9808F272A6004A47F5 /* SetChanErr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetChanErr.3; sourceTree = "<group>"; };
		F96D3E9908F272A6004A47F5 /* SetErrno.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetErrno.3; sourceTree = "<group>"; };
		F96D3E9A08F272A6004A47F5 /* SetRecLmt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetRecLmt.3; sourceTree = "<group>"; };
		F96D3E9B08F272A7004A47F5 /* SetResult.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetResult.3; sourceTree = "<group>"; };
		F96D3E9C08F272A7004A47F5 /* SetVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetVar.3; sourceTree = "<group>"; };
		F96D3E9D08F272A7004A47F5 /* Signal.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Signal.3; sourceTree = "<group>"; };
		F96D3E9E08F272A7004A47F5 /* Sleep.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Sleep.3; sourceTree = "<group>"; };
		F96D3E9F08F272A7004A47F5 /* socket.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = socket.n; sourceTree = "<group>"; };
		F96D3EA008F272A7004A47F5 /* source.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = source.n; sourceTree = "<group>"; };
		F96D3EA108F272A7004A47F5 /* SourceRCFile.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SourceRCFile.3; sourceTree = "<group>"; };
		F96D3EA208F272A7004A47F5 /* split.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = split.n; sourceTree = "<group>"; };
		F96D3EA308F272A7004A47F5 /* SplitList.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitList.3; sourceTree = "<group>"; };
		F96D3EA408F272A7004A47F5 /* SplitPath.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitPath.3; sourceTree = "<group>"; };
		F96D3EA508F272A7004A47F5 /* StaticPkg.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StaticPkg.3; sourceTree = "<group>"; };
		F96D3EA608F272A7004A47F5 /* StdChannels.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StdChannels.3; sourceTree = "<group>"; };
		F96D3EA708F272A7004A47F5 /* string.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = string.n; sourceTree = "<group>"; };
		F96D3EA808F272A7004A47F5 /* StringObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StringObj.3; sourceTree = "<group>"; };
		F96D3EA908F272A7004A47F5 /* StrMatch.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StrMatch.3; sourceTree = "<group>"; };
		F96D3EAA08F272A7004A47F5 /* subst.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = subst.n; sourceTree = "<group>"; };
		F96D3EAB08F272A7004A47F5 /* SubstObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SubstObj.3; sourceTree = "<group>"; };
		F96D3EAC08F272A7004A47F5 /* switch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = switch.n; sourceTree = "<group>"; };
		F96D3EAD08F272A7004A47F5 /* Tcl.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tcl.n; sourceTree = "<group>"; };
		F96D3EAE08F272A7004A47F5 /* Tcl_Main.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tcl_Main.3; sourceTree = "<group>"; };
		F96D3EAF08F272A7004A47F5 /* TCL_MEM_DEBUG.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TCL_MEM_DEBUG.3; sourceTree = "<group>"; };
		F96D3EB008F272A7004A47F5 /* tclsh.1 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tclsh.1; sourceTree = "<group>"; };
		F96D3EB108F272A7004A47F5 /* tcltest.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tcltest.n; sourceTree = "<group>"; };
		F96D3EB208F272A7004A47F5 /* tclvars.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tclvars.n; sourceTree = "<group>"; };
		F96D3EB308F272A7004A47F5 /* tell.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tell.n; sourceTree = "<group>"; };
		F96D3EB408F272A7004A47F5 /* Thread.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Thread.3; sourceTree = "<group>"; };
		F96D3EB508F272A7004A47F5 /* time.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = time.n; sourceTree = "<group>"; };
		F96D3EB608F272A7004A47F5 /* tm.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tm.n; sourceTree = "<group>"; };
		F96D3EB708F272A7004A47F5 /* ToUpper.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ToUpper.3; sourceTree = "<group>"; };
		F96D3EB808F272A7004A47F5 /* trace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = trace.n; sourceTree = "<group>"; };
		F96D3EB908F272A7004A47F5 /* TraceCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TraceCmd.3; sourceTree = "<group>"; };
		F96D3EBA08F272A7004A47F5 /* TraceVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TraceVar.3; sourceTree = "<group>"; };
		F96D3EBB08F272A7004A47F5 /* Translate.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Translate.3; sourceTree = "<group>"; };
		F96D3EBC08F272A7004A47F5 /* UniCharIsAlpha.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = UniCharIsAlpha.3; sourceTree = "<group>"; };
		F96D3EBD08F272A7004A47F5 /* unknown.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unknown.n; sourceTree = "<group>"; };
		F96D3EBE08F272A7004A47F5 /* unload.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unload.n; sourceTree = "<group>"; };
		F96D3EBF08F272A7004A47F5 /* unset.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unset.n; sourceTree = "<group>"; };
		F96D3EC008F272A7004A47F5 /* update.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = update.n; sourceTree = "<group>"; };
		F96D3EC108F272A7004A47F5 /* uplevel.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = uplevel.n; sourceTree = "<group>"; };
		F96D3EC208F272A7004A47F5 /* UpVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = UpVar.3; sourceTree = "<group>"; };
		F96D3EC308F272A7004A47F5 /* upvar.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = upvar.n; sourceTree = "<group>"; };
		F96D3EC408F272A7004A47F5 /* Utf.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Utf.3; sourceTree = "<group>"; };
		F96D3EC508F272A7004A47F5 /* variable.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = variable.n; sourceTree = "<group>"; };
		F96D3EC608F272A7004A47F5 /* vwait.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = vwait.n; sourceTree = "<group>"; };
		F96D3EC708F272A7004A47F5 /* while.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = while.n; sourceTree = "<group>"; };
		F96D3EC808F272A7004A47F5 /* WrongNumArgs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = WrongNumArgs.3; sourceTree = "<group>"; };
		F96D3ECA08F272A7004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D3ECB08F272A7004A47F5 /* regc_color.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_color.c; sourceTree = "<group>"; };
		F96D3ECC08F272A7004A47F5 /* regc_cvec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_cvec.c; sourceTree = "<group>"; };
		F96D3ECD08F272A7004A47F5 /* regc_lex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_lex.c; sourceTree = "<group>"; };
		F96D3ECE08F272A7004A47F5 /* regc_locale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_locale.c; sourceTree = "<group>"; };
		F96D3ECF08F272A7004A47F5 /* regc_nfa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_nfa.c; sourceTree = "<group>"; };
		F96D3ED008F272A7004A47F5 /* regcomp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regcomp.c; sourceTree = "<group>"; };
		F96D3ED108F272A7004A47F5 /* regcustom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regcustom.h; sourceTree = "<group>"; };
		F96D3ED208F272A7004A47F5 /* rege_dfa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rege_dfa.c; sourceTree = "<group>"; };
		F96D3ED308F272A7004A47F5 /* regerror.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regerror.c; sourceTree = "<group>"; };
		F96D3ED408F272A7004A47F5 /* regerrs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regerrs.h; sourceTree = "<group>"; };
		F96D3ED508F272A7004A47F5 /* regex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regex.h; sourceTree = "<group>"; };
		F96D3ED608F272A7004A47F5 /* regexec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regexec.c; sourceTree = "<group>"; };
		F96D3ED708F272A7004A47F5 /* regfree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regfree.c; sourceTree = "<group>"; };
		F96D3ED808F272A7004A47F5 /* regfronts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regfronts.c; sourceTree = "<group>"; };
		F96D3ED908F272A7004A47F5 /* regguts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regguts.h; sourceTree = "<group>"; };
		F96D3EDA08F272A7004A47F5 /* tcl.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcl.decls; sourceTree = "<group>"; };
		F96D3EDB08F272A7004A47F5 /* tcl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tcl.h; sourceTree = "<group>"; };
		F96D3EDC08F272A7004A47F5 /* tclAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAlloc.c; sourceTree = "<group>"; };
		F96D3EDD08F272A7004A47F5 /* tclAsync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAsync.c; sourceTree = "<group>"; };
		F96D3EDE08F272A7004A47F5 /* tclBasic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclBasic.c; sourceTree = "<group>"; };
		F96D3EDF08F272A7004A47F5 /* tclBinary.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclBinary.c; sourceTree = "<group>"; };
		F96D3EE008F272A7004A47F5 /* tclCkalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCkalloc.c; sourceTree = "<group>"; };
		F96D3EE108F272A7004A47F5 /* tclClock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclClock.c; sourceTree = "<group>"; };
		F96D3EE208F272A7004A47F5 /* tclCmdAH.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdAH.c; sourceTree = "<group>"; };
		F96D3EE308F272A7004A47F5 /* tclCmdIL.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdIL.c; sourceTree = "<group>"; };
		F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdMZ.c; sourceTree = "<group>"; };
		F96D3EE508F272A7004A47F5 /* tclCompCmds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompCmds.c; sourceTree = "<group>"; };
		F96D3EE608F272A7004A47F5 /* tclCompExpr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompExpr.c; sourceTree = "<group>"; };
		F96D3EE708F272A7004A47F5 /* tclCompile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompile.c; sourceTree = "<group>"; };
		F96D3EE808F272A7004A47F5 /* tclCompile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclCompile.h; sourceTree = "<group>"; };
		F96D3EE908F272A7004A47F5 /* tclConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclConfig.c; sourceTree = "<group>"; };
		F96D3EEA08F272A7004A47F5 /* tclDate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclDate.c; sourceTree = "<group>"; };
		F96D3EEB08F272A7004A47F5 /* tclDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclDecls.h; sourceTree = "<group>"; };
		F96D3EEC08F272A7004A47F5 /* tclDictObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclDictObj.c; sourceTree = "<group>"; };
		F96D3EED08F272A7004A47F5 /* tclEncoding.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEncoding.c; sourceTree = "<group>"; };
		F96D3EEE08F272A7004A47F5 /* tclEnv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEnv.c; sourceTree = "<group>"; };
		F96D3EEF08F272A7004A47F5 /* tclEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEvent.c; sourceTree = "<group>"; };
		F96D3EF008F272A7004A47F5 /* tclExecute.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclExecute.c; sourceTree = "<group>"; };
		F96D3EF108F272A7004A47F5 /* tclFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclFCmd.c; sourceTree = "<group>"; };
		F96D3EF208F272A7004A47F5 /* tclFileName.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclFileName.c; sourceTree = "<group>"; };
		F96D3EF308F272A7004A47F5 /* tclFileSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclFileSystem.h; sourceTree = "<group>"; };
		F96D3EF408F272A7004A47F5 /* tclGet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclGet.c; sourceTree = "<group>"; };
		F96D3EF508F272A7004A47F5 /* tclGetDate.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; path = tclGetDate.y; sourceTree = "<group>"; };
		F96D3EF608F272A7004A47F5 /* tclHash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclHash.c; sourceTree = "<group>"; };
		F96D3EF708F272A7004A47F5 /* tclHistory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclHistory.c; sourceTree = "<group>"; };
		F96D3EF808F272A7004A47F5 /* tclIndexObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIndexObj.c; sourceTree = "<group>"; };
		F96D3EF908F272A7004A47F5 /* tclInt.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclInt.decls; sourceTree = "<group>"; };
		F96D3EFA08F272A7004A47F5 /* tclInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclInt.h; sourceTree = "<group>"; };
		F96D3EFB08F272A7004A47F5 /* tclIntDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIntDecls.h; sourceTree = "<group>"; };
		F96D3EFC08F272A7004A47F5 /* tclInterp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclInterp.c; sourceTree = "<group>"; };
		F96D3EFD08F272A7004A47F5 /* tclIntPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIntPlatDecls.h; sourceTree = "<group>"; };
		F96D3EFE08F272A7004A47F5 /* tclIO.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIO.c; sourceTree = "<group>"; };
		F96D3EFF08F272A7004A47F5 /* tclIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIO.h; sourceTree = "<group>"; };
		F96D3F0008F272A7004A47F5 /* tclIOCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOCmd.c; sourceTree = "<group>"; };
		F96D3F0108F272A7004A47F5 /* tclIOGT.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOGT.c; sourceTree = "<group>"; };
		F96D3F0208F272A7004A47F5 /* tclIORChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIORChan.c; sourceTree = "<group>"; };
		F96D3F0308F272A7004A47F5 /* tclIOSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOSock.c; sourceTree = "<group>"; };
		F96D3F0408F272A7004A47F5 /* tclIOUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOUtil.c; sourceTree = "<group>"; };
		F96D3F0508F272A7004A47F5 /* tclLink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLink.c; sourceTree = "<group>"; };
		F96D3F0608F272A7004A47F5 /* tclListObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclListObj.c; sourceTree = "<group>"; };
		F96D3F0708F272A7004A47F5 /* tclLiteral.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLiteral.c; sourceTree = "<group>"; };
		F96D3F0808F272A7004A47F5 /* tclLoad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoad.c; sourceTree = "<group>"; };
		F96D3F0908F272A7004A47F5 /* tclLoadNone.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadNone.c; sourceTree = "<group>"; };
		F96D3F0A08F272A7004A47F5 /* tclMain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMain.c; sourceTree = "<group>"; };
		F96D3F0B08F272A7004A47F5 /* tclNamesp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclNamesp.c; sourceTree = "<group>"; };
		F96D3F0C08F272A7004A47F5 /* tclNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclNotify.c; sourceTree = "<group>"; };
		F96D3F0D08F272A7004A47F5 /* tclObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclObj.c; sourceTree = "<group>"; };
		F96D3F0E08F272A7004A47F5 /* tclPanic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPanic.c; sourceTree = "<group>"; };
		F96D3F0F08F272A7004A47F5 /* tclParse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclParse.c; sourceTree = "<group>"; };
		F96D3F1108F272A7004A47F5 /* tclPathObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPathObj.c; sourceTree = "<group>"; };
		F96D3F1208F272A7004A47F5 /* tclPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPipe.c; sourceTree = "<group>"; };
		F96D3F1308F272A7004A47F5 /* tclPkg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPkg.c; sourceTree = "<group>"; };
		F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPkgConfig.c; sourceTree = "<group>"; };
		F96D3F1508F272A7004A47F5 /* tclPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclPlatDecls.h; sourceTree = "<group>"; };
		F96D3F1608F272A7004A47F5 /* tclPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclPort.h; sourceTree = "<group>"; };
		F96D3F1708F272A7004A47F5 /* tclPosixStr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPosixStr.c; sourceTree = "<group>"; };
		F96D3F1808F272A7004A47F5 /* tclPreserve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPreserve.c; sourceTree = "<group>"; };
		F96D3F1908F272A7004A47F5 /* tclProc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclProc.c; sourceTree = "<group>"; };
		F96D3F1A08F272A7004A47F5 /* tclRegexp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclRegexp.c; sourceTree = "<group>"; };
		F96D3F1B08F272A7004A47F5 /* tclRegexp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclRegexp.h; sourceTree = "<group>"; };
		F96D3F1C08F272A7004A47F5 /* tclResolve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclResolve.c; sourceTree = "<group>"; };
		F96D3F1D08F272A7004A47F5 /* tclResult.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclResult.c; sourceTree = "<group>"; };
		F96D3F1E08F272A7004A47F5 /* tclScan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclScan.c; sourceTree = "<group>"; };
		F96D3F1F08F272A7004A47F5 /* tclStringObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStringObj.c; sourceTree = "<group>"; };
		F96D3F2408F272A7004A47F5 /* tclStrToD.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStrToD.c; sourceTree = "<group>"; };
		F96D3F2508F272A7004A47F5 /* tclStubInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStubInit.c; sourceTree = "<group>"; };
		F96D3F2608F272A7004A47F5 /* tclStubLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStubLib.c; sourceTree = "<group>"; };
		F96D3F2708F272A7004A47F5 /* tclTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTest.c; sourceTree = "<group>"; };
		F96D3F2808F272A7004A47F5 /* tclTestObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTestObj.c; sourceTree = "<group>"; };
		F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTestProcBodyObj.c; sourceTree = "<group>"; };
		F96D3F2A08F272A7004A47F5 /* tclThread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThread.c; sourceTree = "<group>"; };
		F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadAlloc.c; sourceTree = "<group>"; };
		F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadJoin.c; sourceTree = "<group>"; };
		F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadStorage.c; sourceTree = "<group>"; };
		F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadTest.c; sourceTree = "<group>"; };
		F96D3F2F08F272A7004A47F5 /* tclTimer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTimer.c; sourceTree = "<group>"; };
		F96D3F3008F272A7004A47F5 /* tclTomMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMath.h; sourceTree = "<group>"; };
		F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTomMathInterface.c; sourceTree = "<group>"; };
		F96D3F3208F272A7004A47F5 /* tclTrace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTrace.c; sourceTree = "<group>"; };
		F96D3F3308F272A7004A47F5 /* tclUniData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUniData.c; sourceTree = "<group>"; };
		F96D3F3408F272A7004A47F5 /* tclUtf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUtf.c; sourceTree = "<group>"; };
		F96D3F3508F272A7004A47F5 /* tclUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUtil.c; sourceTree = "<group>"; };
		F96D3F3608F272A7004A47F5 /* tclVar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclVar.c; sourceTree = "<group>"; };
		F96D3F3908F272A8004A47F5 /* auto.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = auto.tcl; sourceTree = "<group>"; };
		F96D3F3A08F272A8004A47F5 /* clock.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clock.tcl; sourceTree = "<group>"; };
		F96D3F3C08F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
		F96D3F8C08F272A8004A47F5 /* history.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = history.tcl; sourceTree = "<group>"; };
		F96D3F8E08F272A8004A47F5 /* http.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.tcl; sourceTree = "<group>"; };
		F96D3F8F08F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
		F96D3F9108F272A8004A47F5 /* http.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.tcl; sourceTree = "<group>"; };
		F96D3F9208F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
		F96D3F9308F272A8004A47F5 /* init.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = init.tcl; sourceTree = "<group>"; };
		F96D3F9508F272A8004A47F5 /* msgcat.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgcat.tcl; sourceTree = "<group>"; };
		F96D3F9608F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
		F96D401808F272AA004A47F5 /* optparse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = optparse.tcl; sourceTree = "<group>"; };
		F96D401908F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
		F96D401A08F272AA004A47F5 /* package.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = package.tcl; sourceTree = "<group>"; };
		F96D401B08F272AA004A47F5 /* parray.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parray.tcl; sourceTree = "<group>"; };
		F96D401D08F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
		F96D401E08F272AA004A47F5 /* safe.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safe.tcl; sourceTree = "<group>"; };
		F96D401F08F272AA004A47F5 /* tclIndex */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclIndex; sourceTree = "<group>"; };
		F96D402108F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
		F96D402208F272AA004A47F5 /* tcltest.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcltest.tcl; sourceTree = "<group>"; };
		F96D402308F272AA004A47F5 /* tm.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tm.tcl; sourceTree = "<group>"; };
		F96D425B08F272B2004A47F5 /* word.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = word.tcl; sourceTree = "<group>"; };
		F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_s_mp_mul_digs.c; sourceTree = "<group>"; };
		F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_s_mp_sqr.c; sourceTree = "<group>"; };
		F96D426908F272B3004A47F5 /* bn_mp_add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_add.c; sourceTree = "<group>"; };
		F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_add_d.c; sourceTree = "<group>"; };
		F96D426C08F272B3004A47F5 /* bn_mp_and.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_and.c; sourceTree = "<group>"; };
		F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clamp.c; sourceTree = "<group>"; };
		F96D426E08F272B3004A47F5 /* bn_mp_clear.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clear.c; sourceTree = "<group>"; };
		F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clear_multi.c; sourceTree = "<group>"; };
		F96D427008F272B3004A47F5 /* bn_mp_cmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp.c; sourceTree = "<group>"; };
		F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_d.c; sourceTree = "<group>"; };
		F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_mag.c; sourceTree = "<group>"; };
		F96D427408F272B3004A47F5 /* bn_mp_copy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_copy.c; sourceTree = "<group>"; };
		F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_count_bits.c; sourceTree = "<group>"; };
		F96D427608F272B3004A47F5 /* bn_mp_div.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div.c; sourceTree = "<group>"; };
		F96D427708F272B3004A47F5 /* bn_mp_div_2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2.c; sourceTree = "<group>"; };
		F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2d.c; sourceTree = "<group>"; };
		F96D427908F272B3004A47F5 /* bn_mp_div_3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_3.c; sourceTree = "<group>"; };
		F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_d.c; sourceTree = "<group>"; };
		F96D427E08F272B3004A47F5 /* bn_mp_exch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_exch.c; sourceTree = "<group>"; };
		F96D427F08F272B3004A47F5 /* bn_mp_expt_u32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_expt_u32.c; sourceTree = "<group>"; };
		F96D427F08F272B3004A47F5 /* bn_mp_expt_d_ex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_expt_d_ex.c; sourceTree = "<group>"; };
		F96D428708F272B3004A47F5 /* bn_mp_grow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_grow.c; sourceTree = "<group>"; };
		F96D428808F272B3004A47F5 /* bn_mp_init.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init.c; sourceTree = "<group>"; };
		F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_copy.c; sourceTree = "<group>"; };
		F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_multi.c; sourceTree = "<group>"; };
		F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_set.c; sourceTree = "<group>"; };
		F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_size.c; sourceTree = "<group>"; };
		F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_karatsuba_mul.c; sourceTree = "<group>"; };
		F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_karatsuba_sqr.c; sourceTree = "<group>"; };
		F96D429508F272B3004A47F5 /* bn_mp_lshd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_lshd.c; sourceTree = "<group>"; };
		F96D429608F272B3004A47F5 /* bn_mp_mod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mod.c; sourceTree = "<group>"; };
		F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mod_2d.c; sourceTree = "<group>"; };
		F96D429C08F272B3004A47F5 /* bn_mp_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul.c; sourceTree = "<group>"; };
		F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_2.c; sourceTree = "<group>"; };
		F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_2d.c; sourceTree = "<group>"; };
		F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_d.c; sourceTree = "<group>"; };
		F96D42A208F272B3004A47F5 /* bn_mp_neg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_neg.c; sourceTree = "<group>"; };
		F96D42A308F272B3004A47F5 /* bn_mp_or.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_or.c; sourceTree = "<group>"; };
		F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_radix_size.c; sourceTree = "<group>"; };
		F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_radix_smap.c; sourceTree = "<group>"; };
		F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_read_radix.c; sourceTree = "<group>"; };
		F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_rshd.c; sourceTree = "<group>"; };
		F96D42BA08F272B3004A47F5 /* bn_mp_set.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_set.c; sourceTree = "<group>"; };
		F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_shrink.c; sourceTree = "<group>"; };
		F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sqr.c; sourceTree = "<group>"; };
		F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sqrt.c; sourceTree = "<group>"; };
		F96D42C108F272B3004A47F5 /* bn_mp_sub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sub.c; sourceTree = "<group>"; };
		F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sub_d.c; sourceTree = "<group>"; };
		F96D42C608F272B3004A47F5 /* bn_mp_to_ubin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_ubin.c; sourceTree = "<group>"; };
		F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toom_mul.c; sourceTree = "<group>"; };
		F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toom_sqr.c; sourceTree = "<group>"; };
		F96D42CB08F272B3004A47F5 /* bn_mp_to_radix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_radix.c; sourceTree = "<group>"; };
		F96D42CC08F272B3004A47F5 /* bn_mp_ubin_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_ubin_size.c; sourceTree = "<group>"; };
		F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_xor.c; sourceTree = "<group>"; };
		F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_zero.c; sourceTree = "<group>"; };
		F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_add.c; sourceTree = "<group>"; };
		F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_mul_digs.c; sourceTree = "<group>"; };
		F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_sqr.c; sourceTree = "<group>"; };
		F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_sub.c; sourceTree = "<group>"; };
		F96D432908F272B4004A47F5 /* tommath_class.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath_class.h; sourceTree = "<group>"; };
		F96D432A08F272B4004A47F5 /* tommath_superclass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath_superclass.h; sourceTree = "<group>"; };
		F96D432B08F272B4004A47F5 /* license.terms */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = license.terms; sourceTree = "<group>"; };
		F96D432E08F272B5004A47F5 /* configure.ac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure.ac; sourceTree = "<group>"; };
		F96D432F08F272B5004A47F5 /* GNUmakefile */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = GNUmakefile; sourceTree = "<group>"; };
		F96D433108F272B5004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D433208F272B5004A47F5 /* Tcl-Info.plist.in */ = {isa = PBXFileReference; explicitFileType = text.plist; fileEncoding = 4; path = "Tcl-Info.plist.in"; sourceTree = "<group>"; };
		F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXBundle.c; sourceTree = "<group>"; };
		F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXFCmd.c; sourceTree = "<group>"; };
		F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXNotify.c; sourceTree = "<group>"; };
		F96D434308F272B5004A47F5 /* README */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = README; sourceTree = "<group>"; };
		F96D434508F272B5004A47F5 /* all.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = all.tcl; sourceTree = "<group>"; };
		F96D434608F272B5004A47F5 /* append.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = append.test; sourceTree = "<group>"; };
		F96D434708F272B5004A47F5 /* appendComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = appendComp.test; sourceTree = "<group>"; };
		F96D434808F272B5004A47F5 /* assocd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = assocd.test; sourceTree = "<group>"; };
		F96D434908F272B5004A47F5 /* async.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = async.test; sourceTree = "<group>"; };
		F96D434A08F272B5004A47F5 /* autoMkindex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = autoMkindex.test; sourceTree = "<group>"; };
		F96D434B08F272B5004A47F5 /* basic.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = basic.test; sourceTree = "<group>"; };
		F96D434C08F272B5004A47F5 /* binary.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = binary.test; sourceTree = "<group>"; };
		F96D434D08F272B5004A47F5 /* case.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = case.test; sourceTree = "<group>"; };
		F96D434E08F272B5004A47F5 /* chan.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = chan.test; sourceTree = "<group>"; };
		F96D434F08F272B5004A47F5 /* clock.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clock.test; sourceTree = "<group>"; };
		F96D435008F272B5004A47F5 /* cmdAH.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdAH.test; sourceTree = "<group>"; };
		F96D435108F272B5004A47F5 /* cmdIL.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdIL.test; sourceTree = "<group>"; };
		F96D435208F272B5004A47F5 /* cmdInfo.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdInfo.test; sourceTree = "<group>"; };
		F96D435308F272B5004A47F5 /* cmdMZ.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdMZ.test; sourceTree = "<group>"; };
		F96D435408F272B5004A47F5 /* compExpr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "compExpr-old.test"; sourceTree = "<group>"; };
		F96D435508F272B5004A47F5 /* compExpr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = compExpr.test; sourceTree = "<group>"; };
		F96D435608F272B5004A47F5 /* compile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = compile.test; sourceTree = "<group>"; };
		F96D435708F272B5004A47F5 /* concat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = concat.test; sourceTree = "<group>"; };
		F96D435808F272B5004A47F5 /* config.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = config.test; sourceTree = "<group>"; };
		F96D435908F272B5004A47F5 /* dcall.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dcall.test; sourceTree = "<group>"; };
		F96D435A08F272B5004A47F5 /* dict.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dict.test; sourceTree = "<group>"; };
		F96D435C08F272B5004A47F5 /* dstring.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dstring.test; sourceTree = "<group>"; };
		F96D435E08F272B5004A47F5 /* encoding.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = encoding.test; sourceTree = "<group>"; };
		F96D435F08F272B5004A47F5 /* env.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = env.test; sourceTree = "<group>"; };
		F96D436008F272B5004A47F5 /* error.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = error.test; sourceTree = "<group>"; };
		F96D436108F272B5004A47F5 /* eval.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = eval.test; sourceTree = "<group>"; };
		F96D436208F272B5004A47F5 /* event.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = event.test; sourceTree = "<group>"; };
		F96D436308F272B5004A47F5 /* exec.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = exec.test; sourceTree = "<group>"; };
		F96D436408F272B5004A47F5 /* execute.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = execute.test; sourceTree = "<group>"; };
		F96D436508F272B5004A47F5 /* expr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "expr-old.test"; sourceTree = "<group>"; };
		F96D436608F272B5004A47F5 /* expr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = expr.test; sourceTree = "<group>"; };
		F96D436708F272B6004A47F5 /* fCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fCmd.test; sourceTree = "<group>"; };
		F96D436808F272B6004A47F5 /* fileName.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fileName.test; sourceTree = "<group>"; };
		F96D436908F272B6004A47F5 /* fileSystem.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fileSystem.test; sourceTree = "<group>"; };
		F96D436A08F272B6004A47F5 /* for-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "for-old.test"; sourceTree = "<group>"; };
		F96D436B08F272B6004A47F5 /* for.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = for.test; sourceTree = "<group>"; };
		F96D436C08F272B6004A47F5 /* foreach.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = foreach.test; sourceTree = "<group>"; };
		F96D436D08F272B6004A47F5 /* format.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = format.test; sourceTree = "<group>"; };
		F96D436E08F272B6004A47F5 /* get.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = get.test; sourceTree = "<group>"; };
		F96D436F08F272B6004A47F5 /* history.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = history.test; sourceTree = "<group>"; };
		F96D437008F272B6004A47F5 /* http.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.test; sourceTree = "<group>"; };
		F96D437108F272B6004A47F5 /* httpd */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpd; sourceTree = "<group>"; };
		F96D437208F272B6004A47F5 /* httpold.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpold.test; sourceTree = "<group>"; };
		F96D437308F272B6004A47F5 /* if-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "if-old.test"; sourceTree = "<group>"; };
		F96D437408F272B6004A47F5 /* if.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = if.test; sourceTree = "<group>"; };
		F96D437508F272B6004A47F5 /* incr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "incr-old.test"; sourceTree = "<group>"; };
		F96D437608F272B6004A47F5 /* incr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = incr.test; sourceTree = "<group>"; };
		F96D437708F272B6004A47F5 /* indexObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = indexObj.test; sourceTree = "<group>"; };
		F96D437808F272B6004A47F5 /* info.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = info.test; sourceTree = "<group>"; };
		F96D437908F272B6004A47F5 /* init.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = init.test; sourceTree = "<group>"; };
		F96D437A08F272B6004A47F5 /* interp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = interp.test; sourceTree = "<group>"; };
		F96D437B08F272B6004A47F5 /* io.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = io.test; sourceTree = "<group>"; };
		F96D437C08F272B6004A47F5 /* ioCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ioCmd.test; sourceTree = "<group>"; };
		F96D437D08F272B6004A47F5 /* iogt.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = iogt.test; sourceTree = "<group>"; };
		F96D437F08F272B6004A47F5 /* join.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = join.test; sourceTree = "<group>"; };
		F96D438008F272B6004A47F5 /* lindex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lindex.test; sourceTree = "<group>"; };
		F96D438108F272B6004A47F5 /* link.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = link.test; sourceTree = "<group>"; };
		F96D438208F272B6004A47F5 /* linsert.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = linsert.test; sourceTree = "<group>"; };
		F96D438308F272B6004A47F5 /* list.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = list.test; sourceTree = "<group>"; };
		F96D438408F272B6004A47F5 /* listObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = listObj.test; sourceTree = "<group>"; };
		F96D438508F272B6004A47F5 /* llength.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = llength.test; sourceTree = "<group>"; };
		F96D438608F272B6004A47F5 /* load.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = load.test; sourceTree = "<group>"; };
		F96D438708F272B6004A47F5 /* lrange.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lrange.test; sourceTree = "<group>"; };
		F96D438808F272B6004A47F5 /* lrepeat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lrepeat.test; sourceTree = "<group>"; };
		F96D438908F272B6004A47F5 /* lreplace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lreplace.test; sourceTree = "<group>"; };
		F96D438A08F272B6004A47F5 /* lsearch.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lsearch.test; sourceTree = "<group>"; };
		F96D438B08F272B6004A47F5 /* lset.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lset.test; sourceTree = "<group>"; };
		F96D438C08F272B6004A47F5 /* lsetComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lsetComp.test; sourceTree = "<group>"; };
		F96D438D08F272B6004A47F5 /* macOSXFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = macOSXFCmd.test; sourceTree = "<group>"; };
		F96D438E08F272B6004A47F5 /* main.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = main.test; sourceTree = "<group>"; };
		F96D438F08F272B6004A47F5 /* misc.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = misc.test; sourceTree = "<group>"; };
		F96D439008F272B6004A47F5 /* msgcat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgcat.test; sourceTree = "<group>"; };
		F96D439108F272B6004A47F5 /* namespace-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "namespace-old.test"; sourceTree = "<group>"; };
		F96D439208F272B7004A47F5 /* namespace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = namespace.test; sourceTree = "<group>"; };
		F96D439308F272B7004A47F5 /* notify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = notify.test; sourceTree = "<group>"; };
		F96D439408F272B7004A47F5 /* obj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = obj.test; sourceTree = "<group>"; };
		F96D439508F272B7004A47F5 /* opt.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = opt.test; sourceTree = "<group>"; };
		F96D439608F272B7004A47F5 /* package.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = package.test; sourceTree = "<group>"; };
		F96D439708F272B7004A47F5 /* parse.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parse.test; sourceTree = "<group>"; };
		F96D439808F272B7004A47F5 /* parseExpr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parseExpr.test; sourceTree = "<group>"; };
		F96D439908F272B7004A47F5 /* parseOld.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parseOld.test; sourceTree = "<group>"; };
		F96D439A08F272B7004A47F5 /* pid.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pid.test; sourceTree = "<group>"; };
		F96D439B08F272B7004A47F5 /* pkg.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkg.test; sourceTree = "<group>"; };
		F96D439C08F272B7004A47F5 /* pkgMkIndex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgMkIndex.test; sourceTree = "<group>"; };
		F96D439D08F272B7004A47F5 /* platform.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = platform.test; sourceTree = "<group>"; };
		F96D439E08F272B7004A47F5 /* proc-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "proc-old.test"; sourceTree = "<group>"; };
		F96D439F08F272B7004A47F5 /* proc.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = proc.test; sourceTree = "<group>"; };
		F96D43A008F272B7004A47F5 /* pwd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pwd.test; sourceTree = "<group>"; };
		F96D43A108F272B7004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D43A208F272B7004A47F5 /* reg.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = reg.test; sourceTree = "<group>"; };
		F96D43A308F272B7004A47F5 /* regexp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexp.test; sourceTree = "<group>"; };
		F96D43A408F272B7004A47F5 /* regexpComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexpComp.test; sourceTree = "<group>"; };
		F96D43A508F272B7004A47F5 /* registry.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = registry.test; sourceTree = "<group>"; };
		F96D43A608F272B7004A47F5 /* remote.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = remote.tcl; sourceTree = "<group>"; };
		F96D43A708F272B7004A47F5 /* rename.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = rename.test; sourceTree = "<group>"; };
		F96D43A808F272B7004A47F5 /* result.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = result.test; sourceTree = "<group>"; };
		F96D43A908F272B7004A47F5 /* safe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safe.test; sourceTree = "<group>"; };
		F96D43AA08F272B7004A47F5 /* scan.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scan.test; sourceTree = "<group>"; };
		F96D43AB08F272B7004A47F5 /* security.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = security.test; sourceTree = "<group>"; };
		F96D43AC08F272B7004A47F5 /* set-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "set-old.test"; sourceTree = "<group>"; };
		F96D43AD08F272B7004A47F5 /* set.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = set.test; sourceTree = "<group>"; };
		F96D43AE08F272B7004A47F5 /* socket.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = socket.test; sourceTree = "<group>"; };
		F96D43AF08F272B7004A47F5 /* source.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = source.test; sourceTree = "<group>"; };
		F96D43B008F272B7004A47F5 /* split.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = split.test; sourceTree = "<group>"; };
		F96D43B108F272B7004A47F5 /* stack.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stack.test; sourceTree = "<group>"; };
		F96D43B208F272B7004A47F5 /* string.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = string.test; sourceTree = "<group>"; };
		F96D43B308F272B7004A47F5 /* stringComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stringComp.test; sourceTree = "<group>"; };
		F96D43B408F272B7004A47F5 /* stringObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stringObj.test; sourceTree = "<group>"; };
		F96D43B508F272B7004A47F5 /* subst.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = subst.test; sourceTree = "<group>"; };
		F96D43B608F272B7004A47F5 /* switch.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = switch.test; sourceTree = "<group>"; };
		F96D43B708F272B7004A47F5 /* tcltest.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcltest.test; sourceTree = "<group>"; };
		F96D43B808F272B7004A47F5 /* thread.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = thread.test; sourceTree = "<group>"; };
		F96D43B908F272B7004A47F5 /* timer.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = timer.test; sourceTree = "<group>"; };
		F96D43BA08F272B7004A47F5 /* tm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tm.test; sourceTree = "<group>"; };
		F96D43BB08F272B7004A47F5 /* trace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = trace.test; sourceTree = "<group>"; };
		F96D43BC08F272B7004A47F5 /* unixFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixFCmd.test; sourceTree = "<group>"; };
		F96D43BD08F272B7004A47F5 /* unixFile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixFile.test; sourceTree = "<group>"; };
		F96D43BE08F272B7004A47F5 /* unixInit.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixInit.test; sourceTree = "<group>"; };
		F96D43BF08F272B7004A47F5 /* unixNotfy.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixNotfy.test; sourceTree = "<group>"; };
		F96D43C008F272B7004A47F5 /* unknown.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unknown.test; sourceTree = "<group>"; };
		F96D43C108F272B7004A47F5 /* unload.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unload.test; sourceTree = "<group>"; };
		F96D43C208F272B7004A47F5 /* uplevel.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uplevel.test; sourceTree = "<group>"; };
		F96D43C308F272B7004A47F5 /* upvar.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = upvar.test; sourceTree = "<group>"; };
		F96D43C408F272B7004A47F5 /* utf.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = utf.test; sourceTree = "<group>"; };
		F96D43C508F272B7004A47F5 /* util.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = util.test; sourceTree = "<group>"; };
		F96D43C608F272B7004A47F5 /* var.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = var.test; sourceTree = "<group>"; };
		F96D43C708F272B7004A47F5 /* while-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "while-old.test"; sourceTree = "<group>"; };
		F96D43C808F272B7004A47F5 /* while.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = while.test; sourceTree = "<group>"; };
		F96D43C908F272B7004A47F5 /* winConsole.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winConsole.test; sourceTree = "<group>"; };
		F96D43CA08F272B7004A47F5 /* winDde.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winDde.test; sourceTree = "<group>"; };
		F96D43CB08F272B7004A47F5 /* winFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFCmd.test; sourceTree = "<group>"; };
		F96D43CC08F272B7004A47F5 /* winFile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFile.test; sourceTree = "<group>"; };
		F96D43CD08F272B7004A47F5 /* winNotify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winNotify.test; sourceTree = "<group>"; };
		F96D43CE08F272B7004A47F5 /* winPipe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winPipe.test; sourceTree = "<group>"; };
		F96D43CF08F272B7004A47F5 /* winTime.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winTime.test; sourceTree = "<group>"; };
		F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = checkLibraryDoc.tcl; sourceTree = "<group>"; };
		F96D43D208F272B8004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F96D43D308F272B8004A47F5 /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = "<group>"; };
		F96D442508F272B8004A47F5 /* genStubs.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = genStubs.tcl; sourceTree = "<group>"; };
		F96D442708F272B8004A47F5 /* index.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = index.tcl; sourceTree = "<group>"; };
		F96D442808F272B8004A47F5 /* installData.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = installData.tcl; sourceTree = "<group>"; };
		F96D442908F272B8004A47F5 /* loadICU.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = loadICU.tcl; sourceTree = "<group>"; };
		F96D442A08F272B8004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F96D442B08F272B8004A47F5 /* makeTestCases.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = makeTestCases.tcl; sourceTree = "<group>"; };
		F96D442C08F272B8004A47F5 /* man2help.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2help.tcl; sourceTree = "<group>"; };
		F96D442D08F272B8004A47F5 /* man2help2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2help2.tcl; sourceTree = "<group>"; };
		F96D442E08F272B8004A47F5 /* man2html.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html.tcl; sourceTree = "<group>"; };
		F96D442F08F272B8004A47F5 /* man2html1.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html1.tcl; sourceTree = "<group>"; };
		F96D443008F272B8004A47F5 /* man2html2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html2.tcl; sourceTree = "<group>"; };
		F96D443108F272B8004A47F5 /* man2tcl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = man2tcl.c; sourceTree = "<group>"; };
		F96D443208F272B8004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D443308F272B8004A47F5 /* regexpTestLib.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexpTestLib.tcl; sourceTree = "<group>"; };
		F96D443508F272B8004A47F5 /* tcl.hpj.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.hpj.in; sourceTree = "<group>"; };
		F96D443908F272B9004A47F5 /* tcltk-man2html.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "tcltk-man2html.tcl"; sourceTree = "<group>"; };
		F96D443A08F272B9004A47F5 /* tclZIC.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclZIC.tcl; sourceTree = "<group>"; };
		F96D443B08F272B9004A47F5 /* uniClass.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniClass.tcl; sourceTree = "<group>"; };
		F96D443C08F272B9004A47F5 /* uniParse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniParse.tcl; sourceTree = "<group>"; };
		F96D444008F272B9004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
		F96D444108F272B9004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F96D444208F272B9004A47F5 /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = "<group>"; };
		F96D444408F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F96D444508F272B9004A47F5 /* pkga.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkga.c; sourceTree = "<group>"; };
		F96D444608F272B9004A47F5 /* pkgb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgb.c; sourceTree = "<group>"; };
		F96D444708F272B9004A47F5 /* pkgc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgc.c; sourceTree = "<group>"; };
		F96D444808F272B9004A47F5 /* pkgd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgd.c; sourceTree = "<group>"; };
		F96D444908F272B9004A47F5 /* pkge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkge.c; sourceTree = "<group>"; };
		F96D444B08F272B9004A47F5 /* pkgua.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgua.c; sourceTree = "<group>"; };
		F96D444C08F272B9004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D444D08F272B9004A47F5 /* install-sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "install-sh"; sourceTree = "<group>"; };
		F96D444E08F272B9004A47F5 /* installManPage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = installManPage; sourceTree = "<group>"; };
		F96D444F08F272B9004A47F5 /* ldAix */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ldAix; sourceTree = "<group>"; };
		F96D445008F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F96D445208F272B9004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D445308F272B9004A47F5 /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
		F96D445408F272B9004A47F5 /* tcl.spec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.spec; sourceTree = "<group>"; };
		F96D445508F272B9004A47F5 /* tclAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAppInit.c; sourceTree = "<group>"; };
		F96D445608F272B9004A47F5 /* tclConfig.h.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = tclConfig.h.in; sourceTree = "<group>"; };
		F96D445708F272B9004A47F5 /* tclConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tclConfig.sh.in; sourceTree = "<group>"; };
		F96D445808F272B9004A47F5 /* tclLoadAix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadAix.c; sourceTree = "<group>"; };
		F96D445908F272B9004A47F5 /* tclLoadDl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadDl.c; sourceTree = "<group>"; };
		F96D445B08F272B9004A47F5 /* tclLoadDyld.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadDyld.c; sourceTree = "<group>"; };
		F96D445C08F272B9004A47F5 /* tclLoadNext.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadNext.c; sourceTree = "<group>"; };
		F96D445D08F272B9004A47F5 /* tclLoadOSF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadOSF.c; sourceTree = "<group>"; };
		F96D445E08F272B9004A47F5 /* tclLoadShl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadShl.c; sourceTree = "<group>"; };
		F96D445F08F272B9004A47F5 /* tclUnixChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixChan.c; sourceTree = "<group>"; };
		F96D446008F272B9004A47F5 /* tclUnixEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixEvent.c; sourceTree = "<group>"; };
		F96D446108F272B9004A47F5 /* tclUnixFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixFCmd.c; sourceTree = "<group>"; };
		F96D446208F272B9004A47F5 /* tclUnixFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixFile.c; sourceTree = "<group>"; };
		F96D446308F272B9004A47F5 /* tclUnixInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixInit.c; sourceTree = "<group>"; };
		F96D446408F272B9004A47F5 /* tclUnixNotfy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixNotfy.c; sourceTree = "<group>"; };
		F96D446508F272B9004A47F5 /* tclUnixPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixPipe.c; sourceTree = "<group>"; };
		F96D446608F272B9004A47F5 /* tclUnixPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclUnixPort.h; sourceTree = "<group>"; };
		F96D446708F272B9004A47F5 /* tclUnixSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixSock.c; sourceTree = "<group>"; };
		F96D446808F272B9004A47F5 /* tclUnixTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTest.c; sourceTree = "<group>"; };
		F96D446908F272B9004A47F5 /* tclUnixThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixThrd.c; sourceTree = "<group>"; };
		F96D446B08F272B9004A47F5 /* tclUnixTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTime.c; sourceTree = "<group>"; };
		F96D446C08F272B9004A47F5 /* tclXtNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtNotify.c; sourceTree = "<group>"; };
		F96D446D08F272B9004A47F5 /* tclXtTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtTest.c; sourceTree = "<group>"; };
		F96D447008F272BA004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
		F96D447108F272BA004A47F5 /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = "<group>"; };
		F96D447208F272BA004A47F5 /* cat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cat.c; sourceTree = "<group>"; };
		F96D447308F272BA004A47F5 /* coffbase.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = coffbase.txt; sourceTree = "<group>"; };
		F96D447408F272BA004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
		F96D447508F272BA004A47F5 /* configure.ac */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.ac; sourceTree = "<group>"; };
		F96D447708F272BA004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
		F96D447808F272BA004A47F5 /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = "<group>"; };
		F96D447908F272BA004A47F5 /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = "<group>"; };
		F96D447A08F272BA004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
		F96D447C08F272BA004A47F5 /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = "<group>"; };
		F96D447D08F272BA004A47F5 /* stub16.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stub16.c; sourceTree = "<group>"; };
		F96D447E08F272BA004A47F5 /* tcl.dsp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.dsp; sourceTree = "<group>"; };
		F96D447F08F272BA004A47F5 /* tcl.dsw */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.dsw; sourceTree = "<group>"; };
		F96D448008F272BA004A47F5 /* tcl.hpj.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.hpj.in; sourceTree = "<group>"; };
		F96D448108F272BA004A47F5 /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
		F96D448208F272BA004A47F5 /* tcl.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.rc; sourceTree = "<group>"; };
		F96D448308F272BA004A47F5 /* tclAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAppInit.c; sourceTree = "<group>"; };
		F96D448408F272BA004A47F5 /* tclConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tclConfig.sh.in; sourceTree = "<group>"; };
		F96D448608F272BA004A47F5 /* tclsh.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tclsh.rc; sourceTree = "<group>"; };
		F96D448708F272BA004A47F5 /* tclWin32Dll.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWin32Dll.c; sourceTree = "<group>"; };
		F96D448808F272BA004A47F5 /* tclWinChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinChan.c; sourceTree = "<group>"; };
		F96D448908F272BA004A47F5 /* tclWinConsole.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinConsole.c; sourceTree = "<group>"; };
		F96D448A08F272BA004A47F5 /* tclWinDde.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinDde.c; sourceTree = "<group>"; };
		F96D448B08F272BA004A47F5 /* tclWinError.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinError.c; sourceTree = "<group>"; };
		F96D448C08F272BA004A47F5 /* tclWinFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinFCmd.c; sourceTree = "<group>"; };
		F96D448D08F272BA004A47F5 /* tclWinFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinFile.c; sourceTree = "<group>"; };
		F96D448E08F272BA004A47F5 /* tclWinInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinInit.c; sourceTree = "<group>"; };
		F96D448F08F272BA004A47F5 /* tclWinInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinInt.h; sourceTree = "<group>"; };
		F96D449008F272BA004A47F5 /* tclWinLoad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinLoad.c; sourceTree = "<group>"; };
		F96D449108F272BA004A47F5 /* tclWinNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinNotify.c; sourceTree = "<group>"; };
		F96D449208F272BA004A47F5 /* tclWinPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinPipe.c; sourceTree = "<group>"; };
		F96D449308F272BA004A47F5 /* tclWinPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinPort.h; sourceTree = "<group>"; };
		F96D449408F272BA004A47F5 /* tclWinReg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinReg.c; sourceTree = "<group>"; };
		F96D449508F272BA004A47F5 /* tclWinSerial.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSerial.c; sourceTree = "<group>"; };
		F96D449608F272BA004A47F5 /* tclWinSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSock.c; sourceTree = "<group>"; };
		F96D449708F272BA004A47F5 /* tclWinTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTest.c; sourceTree = "<group>"; };
		F96D449808F272BA004A47F5 /* tclWinThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinThrd.c; sourceTree = "<group>"; };
		F96D449A08F272BA004A47F5 /* tclWinTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTime.c; sourceTree = "<group>"; };
		F974D56C0FBE7D6300BF728B /* http11.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http11.test; sourceTree = "<group>"; };
		F974D56D0FBE7D6300BF728B /* httpd11.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpd11.tcl; sourceTree = "<group>"; };
		F974D5720FBE7DC600BF728B /* coroutine.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = coroutine.n; sourceTree = "<group>"; };
		F974D5760FBE7E1900BF728B /* tailcall.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tailcall.n; sourceTree = "<group>"; };
		F974D5770FBE7E6100BF728B /* coroutine.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = coroutine.test; sourceTree = "<group>"; };
		F974D5780FBE7E6100BF728B /* tailcall.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tailcall.test; sourceTree = "<group>"; };
		F974D5790FBE7E9C00BF728B /* tcl.pc.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.pc.in; sourceTree = "<group>"; };
		F97AE7F10B65C1E900310EA2 /* Tcl-Common.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Common.xcconfig"; sourceTree = "<group>"; };
		F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Release.xcconfig"; sourceTree = "<group>"; };
		F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Debug.xcconfig"; sourceTree = "<group>"; };
		F9903CAF094FAADA004613E9 /* tclTomMath.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclTomMath.decls; sourceTree = "<group>"; };
		F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMathDecls.h; sourceTree = "<group>"; };
		F99D61180EF5573A00BBFE01 /* TclZlib.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TclZlib.3; sourceTree = "<group>"; };
		F9A3084B08F2D4CE00BAE1AB /* tclsh */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tclsh; sourceTree = BUILT_PRODUCTS_DIR; };
		F9A3084E08F2D4F400BAE1AB /* Tcl.framework */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.framework; path = Tcl.framework; sourceTree = BUILT_PRODUCTS_DIR; };
		F9A493240CEBF38300B78AE2 /* chanio.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = chanio.test; sourceTree = "<group>"; };
		F9ECB1120B26521500A28025 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
		F9ECB1130B26521500A28025 /* platform.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = platform.tcl; sourceTree = "<group>"; };
		F9ECB1140B26521500A28025 /* shell.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = shell.tcl; sourceTree = "<group>"; };
		F9ECB1CA0B2652D300A28025 /* apply.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = apply.test; sourceTree = "<group>"; };
		F9ECB1CB0B26534C00A28025 /* mathop.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = mathop.test; sourceTree = "<group>"; };
		F9ECB1E10B26543C00A28025 /* platform_shell.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = platform_shell.n; sourceTree = "<group>"; };
		F9ECB1E20B26543C00A28025 /* platform.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = platform.n; sourceTree = "<group>"; };
		F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = tclDTrace.d; sourceTree = "<group>"; };
		F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixCompat.c; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		8DD76FAD0486AB0100D96B5E /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
				F966C07508F2820D005CB29B /* CoreFoundation.framework in Frameworks */,
				F96437E70EF0D652003F468E /* libz.dylib in Frameworks */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
		08FB7794FE84155DC02AAC07 /* Tcl */ = {
			isa = PBXGroup;
			children = (
				F96D3DF608F27169004A47F5 /* Tcl Sources */,
				F966C06F08F281DC005CB29B /* Frameworks */,
				1AB674ADFE9D54B511CA2CBB /* Products */,
			);
			comments = "Copyright (c) 2004-2009 Daniel A. Steffen <das@users.sourceforge.net>\nCopyright 2008-2009, Apple Inc.\n\nSee the file \"license.terms\" for information on usage and redistribution of\nthis file, and for a DISCLAIMER OF ALL WARRANTIES.\n\n";
			name = Tcl;
			path = .;
			sourceTree = SOURCE_ROOT;
		};
		1AB674ADFE9D54B511CA2CBB /* Products */ = {
			isa = PBXGroup;
			children = (
				F9A3084B08F2D4CE00BAE1AB /* tclsh */,
				8DD76FB20486AB0100D96B5E /* tcltest */,
				F9A3084E08F2D4F400BAE1AB /* Tcl.framework */,
			);
			includeInIndex = 0;
			name = Products;
			sourceTree = "<group>";
		};
		F9183E690EFC81560030B814 /* pkgs */ = {
			isa = PBXGroup;
			children = (
				F9183E6A0EFC81560030B814 /* README */,
				F946FB8B0FBE3AED00CD6495 /* itcl */,
				F9183E8F0EFC817B0030B814 /* tdbc */,
			);
			path = pkgs;
			sourceTree = "<group>";
		};
		F966C06F08F281DC005CB29B /* Frameworks */ = {
			isa = PBXGroup;
			children = (
				F966C07408F2820D005CB29B /* CoreFoundation.framework */,
				F96437E60EF0D652003F468E /* libz.dylib */,
			);
			name = Frameworks;
			sourceTree = "<group>";
		};
		F96D3DF608F27169004A47F5 /* Tcl Sources */ = {
			isa = PBXGroup;
			children = (
				F96D3EC908F272A7004A47F5 /* generic */,
				F96D432C08F272B4004A47F5 /* macosx */,
				F96D443E08F272B9004A47F5 /* unix */,
				F96D425C08F272B2004A47F5 /* libtommath */,
				F96D446E08F272B9004A47F5 /* win */,
				F96D3F3808F272A7004A47F5 /* library */,
				F96D434408F272B5004A47F5 /* tests */,
				F96D3DFC08F272A4004A47F5 /* doc */,
				F96D43D008F272B8004A47F5 /* tools */,
				F9183E690EFC81560030B814 /* pkgs */,
				F96D3DFA08F272A4004A47F5 /* ChangeLog */,
				F96D3DFB08F272A4004A47F5 /* changes */,
				F96D434308F272B5004A47F5 /* README */,
				F96D432B08F272B4004A47F5 /* license.terms */,
			);
			name = "Tcl Sources";
			sourceTree = TCL_SRCROOT;
		};
		F96D3DFC08F272A4004A47F5 /* doc */ = {
			isa = PBXGroup;
			children = (
				F96D3DFD08F272A4004A47F5 /* Access.3 */,
				F96D3DFE08F272A4004A47F5 /* AddErrInfo.3 */,
				F96D3DFF08F272A4004A47F5 /* after.n */,
				F96D3E0008F272A4004A47F5 /* Alloc.3 */,
				F96D3E0108F272A4004A47F5 /* AllowExc.3 */,
				F96D3E0208F272A4004A47F5 /* append.n */,
				F96D3E0308F272A4004A47F5 /* AppInit.3 */,
				F96D3E0408F272A5004A47F5 /* array.n */,
				F96D3E0508F272A5004A47F5 /* AssocData.3 */,
				F96D3E0608F272A5004A47F5 /* Async.3 */,
				F96D3E0708F272A5004A47F5 /* BackgdErr.3 */,
				F96D3E0808F272A5004A47F5 /* Backslash.3 */,
				F96D3E0908F272A5004A47F5 /* bgerror.n */,
				F96D3E0A08F272A5004A47F5 /* binary.n */,
				F96D3E0B08F272A5004A47F5 /* BoolObj.3 */,
				F96D3E0C08F272A5004A47F5 /* break.n */,
				F96D3E0D08F272A5004A47F5 /* ByteArrObj.3 */,
				F96D3E0E08F272A5004A47F5 /* CallDel.3 */,
				F96D3E0F08F272A5004A47F5 /* case.n */,
				F96D3E1008F272A5004A47F5 /* catch.n */,
				F96D3E1108F272A5004A47F5 /* cd.n */,
				F96D3E1208F272A5004A47F5 /* chan.n */,
				F96D3E1308F272A5004A47F5 /* ChnlStack.3 */,
				F93599CF0DF1F87F00E04F67 /* Class.3 */,
				F93599D00DF1F89E00E04F67 /* class.n */,
				F96D3E1408F272A5004A47F5 /* clock.n */,
				F96D3E1508F272A5004A47F5 /* close.n */,
				F96D3E1608F272A5004A47F5 /* CmdCmplt.3 */,
				F96D3E1708F272A5004A47F5 /* Concat.3 */,
				F96D3E1808F272A5004A47F5 /* concat.n */,
				F96D3E1908F272A5004A47F5 /* continue.n */,
				F93599D20DF1F8DF00E04F67 /* copy.n */,
				F974D5720FBE7DC600BF728B /* coroutine.n */,
				F96D3E1A08F272A5004A47F5 /* CrtChannel.3 */,
				F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */,
				F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */,
				F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */,
				F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */,
				F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */,
				F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */,
				F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */,
				F96D3E2208F272A5004A47F5 /* CrtAlias.3 */,
				F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */,
				F96D3E2408F272A5004A47F5 /* CrtTrace.3 */,
				F96D3E2508F272A5004A47F5 /* dde.n */,
				F93599D30DF1F8F500E04F67 /* define.n */,
				F96D3E2608F272A5004A47F5 /* DetachPids.3 */,
				F96D3E2708F272A5004A47F5 /* dict.n */,
				F96D3E2808F272A5004A47F5 /* DictObj.3 */,
				F96D3E2908F272A5004A47F5 /* DoOneEvent.3 */,
				F96D3E2A08F272A5004A47F5 /* DoubleObj.3 */,
				F96D3E2B08F272A5004A47F5 /* DoWhenIdle.3 */,
				F96D3E2C08F272A5004A47F5 /* DString.3 */,
				F96D3E2D08F272A5004A47F5 /* DumpActiveMemory.3 */,
				F96D3E2E08F272A5004A47F5 /* Encoding.3 */,
				F96D3E2F08F272A5004A47F5 /* encoding.n */,
				F96D3E3008F272A5004A47F5 /* Ensemble.3 */,
				F96D3E3108F272A5004A47F5 /* Environment.3 */,
				F96D3E3208F272A5004A47F5 /* eof.n */,
				F96D3E3308F272A5004A47F5 /* error.n */,
				F96D3E3408F272A5004A47F5 /* Eval.3 */,
				F96D3E3508F272A5004A47F5 /* eval.n */,
				F96D3E3608F272A5004A47F5 /* exec.n */,
				F96D3E3708F272A5004A47F5 /* Exit.3 */,
				F96D3E3808F272A5004A47F5 /* exit.n */,
				F96D3E3908F272A5004A47F5 /* expr.n */,
				F96D3E3A08F272A5004A47F5 /* ExprLong.3 */,
				F96D3E3B08F272A5004A47F5 /* ExprLongObj.3 */,
				F96D3E3C08F272A5004A47F5 /* fblocked.n */,
				F96D3E3D08F272A5004A47F5 /* fconfigure.n */,
				F96D3E3E08F272A5004A47F5 /* fcopy.n */,
				F96D3E3F08F272A5004A47F5 /* file.n */,
				F96D3E4008F272A5004A47F5 /* fileevent.n */,
				F96D3E4108F272A5004A47F5 /* filename.n */,
				F96D3E4208F272A5004A47F5 /* FileSystem.3 */,
				F96D3E4308F272A5004A47F5 /* FindExec.3 */,
				F96D3E4408F272A5004A47F5 /* flush.n */,
				F96D3E4508F272A5004A47F5 /* for.n */,
				F96D3E4608F272A5004A47F5 /* foreach.n */,
				F96D3E4708F272A5004A47F5 /* format.n */,
				F96D3E4808F272A5004A47F5 /* GetCwd.3 */,
				F96D3E4908F272A5004A47F5 /* GetHostName.3 */,
				F96D3E4A08F272A5004A47F5 /* GetIndex.3 */,
				F96D3E4B08F272A5004A47F5 /* GetInt.3 */,
				F96D3E4C08F272A5004A47F5 /* GetOpnFl.3 */,
				F96D3E4D08F272A5004A47F5 /* gets.n */,
				F96D3E4E08F272A5004A47F5 /* GetStdChan.3 */,
				F96D3E4F08F272A5004A47F5 /* GetTime.3 */,
				F96D3E5008F272A5004A47F5 /* GetVersion.3 */,
				F96D3E5108F272A5004A47F5 /* glob.n */,
				F96D3E5208F272A6004A47F5 /* global.n */,
				F96D3E5308F272A6004A47F5 /* Hash.3 */,
				F96D3E5408F272A6004A47F5 /* history.n */,
				F96D3E5508F272A6004A47F5 /* http.n */,
				F96D3E5608F272A6004A47F5 /* if.n */,
				F96D3E5708F272A6004A47F5 /* incr.n */,
				F96D3E5808F272A6004A47F5 /* info.n */,
				F96D3E5908F272A6004A47F5 /* Init.3 */,
				F96D3E5A08F272A6004A47F5 /* InitStubs.3 */,
				F96D3E5B08F272A6004A47F5 /* Interp.3 */,
				F96D3E5C08F272A6004A47F5 /* interp.n */,
				F96D3E5D08F272A6004A47F5 /* IntObj.3 */,
				F96D3E5E08F272A6004A47F5 /* join.n */,
				F96D3E5F08F272A6004A47F5 /* lappend.n */,
				F96D3E6008F272A6004A47F5 /* lassign.n */,
				F96D3E6108F272A6004A47F5 /* library.n */,
				F96D3E6208F272A6004A47F5 /* Limit.3 */,
				F96D3E6308F272A6004A47F5 /* lindex.n */,
				F96D3E6408F272A6004A47F5 /* LinkVar.3 */,
				F96D3E6508F272A6004A47F5 /* linsert.n */,
				F96D3E6608F272A6004A47F5 /* list.n */,
				F96D3E6708F272A6004A47F5 /* ListObj.3 */,
				F96D3E6808F272A6004A47F5 /* llength.n */,
				F96D3E6908F272A6004A47F5 /* load.n */,
				F96D3E6A08F272A6004A47F5 /* lrange.n */,
				F96D3E6B08F272A6004A47F5 /* lrepeat.n */,
				F96D3E6C08F272A6004A47F5 /* lreplace.n */,
				F96D3E6D08F272A6004A47F5 /* lsearch.n */,
				F96D3E6E08F272A6004A47F5 /* lset.n */,
				F96D3E6F08F272A6004A47F5 /* lsort.n */,
				F96D3E7008F272A6004A47F5 /* man.macros */,
				F96D3E7108F272A6004A47F5 /* mathfunc.n */,
				F96D3E7208F272A6004A47F5 /* memory.n */,
				F93599D40DF1F91900E04F67 /* Method.3 */,
				F96D3E7308F272A6004A47F5 /* msgcat.n */,
				F93599D50DF1F93700E04F67 /* my.n */,
				F96D3E7408F272A6004A47F5 /* Namespace.3 */,
				F96D3E7508F272A6004A47F5 /* namespace.n */,
				F93599D60DF1F95000E04F67 /* next.n */,
				F96D3E7608F272A6004A47F5 /* Notifier.3 */,
				F96D3E7708F272A6004A47F5 /* Object.3 */,
				F93599D70DF1F96800E04F67 /* object.n */,
				F96D3E7808F272A6004A47F5 /* ObjectType.3 */,
				F96D3E7908F272A6004A47F5 /* open.n */,
				F96D3E7A08F272A6004A47F5 /* OpenFileChnl.3 */,
				F96D3E7B08F272A6004A47F5 /* OpenTcp.3 */,
				F96D3E7C08F272A6004A47F5 /* package.n */,
				F96D3E7D08F272A6004A47F5 /* packagens.n */,
				F96D3E7E08F272A6004A47F5 /* Panic.3 */,
				F96D3E7F08F272A6004A47F5 /* ParseCmd.3 */,
				F96D3E8008F272A6004A47F5 /* pid.n */,
				F96D3E8108F272A6004A47F5 /* pkgMkIndex.n */,
				F96D3E8208F272A6004A47F5 /* PkgRequire.3 */,
				F9ECB1E10B26543C00A28025 /* platform_shell.n */,
				F9ECB1E20B26543C00A28025 /* platform.n */,
				F96D3E8308F272A6004A47F5 /* Preserve.3 */,
				F96D3E8408F272A6004A47F5 /* PrintDbl.3 */,
				F96D3E8508F272A6004A47F5 /* proc.n */,
				F96D3E8608F272A6004A47F5 /* puts.n */,
				F96D3E8708F272A6004A47F5 /* pwd.n */,
				F96D3E8808F272A6004A47F5 /* re_syntax.n */,
				F96D3E8908F272A6004A47F5 /* read.n */,
				F96D3E8A08F272A6004A47F5 /* RecEvalObj.3 */,
				F96D3E8B08F272A6004A47F5 /* RecordEval.3 */,
				F96D3E8C08F272A6004A47F5 /* RegConfig.3 */,
				F96D3E8D08F272A6004A47F5 /* RegExp.3 */,
				F96D3E8E08F272A6004A47F5 /* regexp.n */,
				F96D3E8F08F272A6004A47F5 /* registry.n */,
				F96D3E9008F272A6004A47F5 /* regsub.n */,
				F96D3E9108F272A6004A47F5 /* rename.n */,
				F96D3E9208F272A6004A47F5 /* return.n */,
				F96D3E9308F272A6004A47F5 /* safe.n */,
				F96D3E9408F272A6004A47F5 /* SaveResult.3 */,
				F96D3E9508F272A6004A47F5 /* scan.n */,
				F96D3E9608F272A6004A47F5 /* seek.n */,
				F93599D80DF1F98300E04F67 /* self.n */,
				F96D3E9708F272A6004A47F5 /* set.n */,
				F96D3E9808F272A6004A47F5 /* SetChanErr.3 */,
				F96D3E9908F272A6004A47F5 /* SetErrno.3 */,
				F96D3E9A08F272A6004A47F5 /* SetRecLmt.3 */,
				F96D3E9B08F272A7004A47F5 /* SetResult.3 */,
				F96D3E9C08F272A7004A47F5 /* SetVar.3 */,
				F96D3E9D08F272A7004A47F5 /* Signal.3 */,
				F96D3E9E08F272A7004A47F5 /* Sleep.3 */,
				F96D3E9F08F272A7004A47F5 /* socket.n */,
				F96D3EA008F272A7004A47F5 /* source.n */,
				F96D3EA108F272A7004A47F5 /* SourceRCFile.3 */,
				F96D3EA208F272A7004A47F5 /* split.n */,
				F96D3EA308F272A7004A47F5 /* SplitList.3 */,
				F96D3EA408F272A7004A47F5 /* SplitPath.3 */,
				F96D3EA508F272A7004A47F5 /* StaticPkg.3 */,
				F96D3EA608F272A7004A47F5 /* StdChannels.3 */,
				F96D3EA708F272A7004A47F5 /* string.n */,
				F96D3EA808F272A7004A47F5 /* StringObj.3 */,
				F96D3EA908F272A7004A47F5 /* StrMatch.3 */,
				F96D3EAA08F272A7004A47F5 /* subst.n */,
				F96D3EAB08F272A7004A47F5 /* SubstObj.3 */,
				F96D3EAC08F272A7004A47F5 /* switch.n */,
				F974D5760FBE7E1900BF728B /* tailcall.n */,
				F96D3EAD08F272A7004A47F5 /* Tcl.n */,
				F99D61180EF5573A00BBFE01 /* TclZlib.3 */,
				F96D3EAE08F272A7004A47F5 /* Tcl_Main.3 */,
				F96D3EAF08F272A7004A47F5 /* TCL_MEM_DEBUG.3 */,
				F96D3EB008F272A7004A47F5 /* tclsh.1 */,
				F96D3EB108F272A7004A47F5 /* tcltest.n */,
				F96D3EB208F272A7004A47F5 /* tclvars.n */,
				F96D3EB308F272A7004A47F5 /* tell.n */,
				F96D3EB408F272A7004A47F5 /* Thread.3 */,
				F9183E640EFC80CD0030B814 /* throw.n */,
				F96D3EB508F272A7004A47F5 /* time.n */,
				F96D3EB608F272A7004A47F5 /* tm.n */,
				F96D3EB708F272A7004A47F5 /* ToUpper.3 */,
				F96D3EB808F272A7004A47F5 /* trace.n */,
				F96D3EB908F272A7004A47F5 /* TraceCmd.3 */,
				F96D3EBA08F272A7004A47F5 /* TraceVar.3 */,
				F96D3EBB08F272A7004A47F5 /* Translate.3 */,
				F9183E650EFC80D70030B814 /* try.n */,
				F96D3EBC08F272A7004A47F5 /* UniCharIsAlpha.3 */,
				F96D3EBD08F272A7004A47F5 /* unknown.n */,
				F96D3EBE08F272A7004A47F5 /* unload.n */,
				F96D3EBF08F272A7004A47F5 /* unset.n */,
				F96D3EC008F272A7004A47F5 /* update.n */,
				F96D3EC108F272A7004A47F5 /* uplevel.n */,
				F96D3EC208F272A7004A47F5 /* UpVar.3 */,
				F96D3EC308F272A7004A47F5 /* upvar.n */,
				F96D3EC408F272A7004A47F5 /* Utf.3 */,
				F96D3EC508F272A7004A47F5 /* variable.n */,
				F96D3EC608F272A7004A47F5 /* vwait.n */,
				F96D3EC708F272A7004A47F5 /* while.n */,
				F96D3EC808F272A7004A47F5 /* WrongNumArgs.3 */,
				F915432D0EF201EE0032D1E8 /* zlib.n */,
			);
			path = doc;
			sourceTree = "<group>";
		};
		F96D3EC908F272A7004A47F5 /* generic */ = {
			isa = PBXGroup;
			children = (
				F96D3ECA08F272A7004A47F5 /* README */,
				F96D3ECB08F272A7004A47F5 /* regc_color.c */,
				F96D3ECC08F272A7004A47F5 /* regc_cvec.c */,
				F96D3ECD08F272A7004A47F5 /* regc_lex.c */,
				F96D3ECE08F272A7004A47F5 /* regc_locale.c */,
				F96D3ECF08F272A7004A47F5 /* regc_nfa.c */,
				F96D3ED008F272A7004A47F5 /* regcomp.c */,
				F96D3ED108F272A7004A47F5 /* regcustom.h */,
				F96D3ED208F272A7004A47F5 /* rege_dfa.c */,
				F96D3ED308F272A7004A47F5 /* regerror.c */,
				F96D3ED408F272A7004A47F5 /* regerrs.h */,
				F96D3ED508F272A7004A47F5 /* regex.h */,
				F96D3ED608F272A7004A47F5 /* regexec.c */,
				F96D3ED708F272A7004A47F5 /* regfree.c */,
				F96D3ED808F272A7004A47F5 /* regfronts.c */,
				F96D3ED908F272A7004A47F5 /* regguts.h */,
				F96D3EDA08F272A7004A47F5 /* tcl.decls */,
				F96D3EDB08F272A7004A47F5 /* tcl.h */,
				F96D3EDC08F272A7004A47F5 /* tclAlloc.c */,
				F96D3EDD08F272A7004A47F5 /* tclAsync.c */,
				F96D3EDE08F272A7004A47F5 /* tclBasic.c */,
				F96D3EDF08F272A7004A47F5 /* tclBinary.c */,
				F96D3EE008F272A7004A47F5 /* tclCkalloc.c */,
				F96D3EE108F272A7004A47F5 /* tclClock.c */,
				F96D3EE208F272A7004A47F5 /* tclCmdAH.c */,
				F96D3EE308F272A7004A47F5 /* tclCmdIL.c */,
				F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */,
				F96D3EE508F272A7004A47F5 /* tclCompCmds.c */,
				F96D3EE608F272A7004A47F5 /* tclCompExpr.c */,
				F96D3EE708F272A7004A47F5 /* tclCompile.c */,
				F96D3EE808F272A7004A47F5 /* tclCompile.h */,
				F96D3EE908F272A7004A47F5 /* tclConfig.c */,
				F96D3EEA08F272A7004A47F5 /* tclDate.c */,
				F96D3EEB08F272A7004A47F5 /* tclDecls.h */,
				F96D3EEC08F272A7004A47F5 /* tclDictObj.c */,
				F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */,
				F96D3EED08F272A7004A47F5 /* tclEncoding.c */,
				F96D3EEE08F272A7004A47F5 /* tclEnv.c */,
				F96D3EEF08F272A7004A47F5 /* tclEvent.c */,
				F96D3EF008F272A7004A47F5 /* tclExecute.c */,
				F96D3EF108F272A7004A47F5 /* tclFCmd.c */,
				F96D3EF208F272A7004A47F5 /* tclFileName.c */,
				F96D3EF308F272A7004A47F5 /* tclFileSystem.h */,
				F96D3EF408F272A7004A47F5 /* tclGet.c */,
				F96D3EF508F272A7004A47F5 /* tclGetDate.y */,
				F96D3EF608F272A7004A47F5 /* tclHash.c */,
				F96D3EF708F272A7004A47F5 /* tclHistory.c */,
				F96D3EF808F272A7004A47F5 /* tclIndexObj.c */,
				F96D3EF908F272A7004A47F5 /* tclInt.decls */,
				F96D3EFA08F272A7004A47F5 /* tclInt.h */,
				F96D3EFB08F272A7004A47F5 /* tclIntDecls.h */,
				F96D3EFC08F272A7004A47F5 /* tclInterp.c */,
				F96D3EFD08F272A7004A47F5 /* tclIntPlatDecls.h */,
				F96D3EFE08F272A7004A47F5 /* tclIO.c */,
				F96D3EFF08F272A7004A47F5 /* tclIO.h */,
				F96D3F0008F272A7004A47F5 /* tclIOCmd.c */,
				F96D3F0108F272A7004A47F5 /* tclIOGT.c */,
				F96D3F0208F272A7004A47F5 /* tclIORChan.c */,
				F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */,
				F96D3F0308F272A7004A47F5 /* tclIOSock.c */,
				F96D3F0408F272A7004A47F5 /* tclIOUtil.c */,
				F96D3F0508F272A7004A47F5 /* tclLink.c */,
				F96D3F0608F272A7004A47F5 /* tclListObj.c */,
				F96D3F0708F272A7004A47F5 /* tclLiteral.c */,
				F96D3F0808F272A7004A47F5 /* tclLoad.c */,
				F96D3F0908F272A7004A47F5 /* tclLoadNone.c */,
				F96D3F0A08F272A7004A47F5 /* tclMain.c */,
				F96D3F0B08F272A7004A47F5 /* tclNamesp.c */,
				F96D3F0C08F272A7004A47F5 /* tclNotify.c */,
				F96D3F0D08F272A7004A47F5 /* tclObj.c */,
				F93599B20DF1F75400E04F67 /* tclOO.c */,
				F93599B40DF1F75900E04F67 /* tclOO.decls */,
				F93599B50DF1F75D00E04F67 /* tclOO.h */,
				F93599B60DF1F76100E04F67 /* tclOOBasic.c */,
				F93599B80DF1F76600E04F67 /* tclOOCall.c */,
				F93599BA0DF1F76A00E04F67 /* tclOODecls.h */,
				F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */,
				F93599BD0DF1F77400E04F67 /* tclOOInfo.c */,
				F93599BF0DF1F77900E04F67 /* tclOOInt.h */,
				F93599C00DF1F77D00E04F67 /* tclOOIntDecls.h */,
				F93599C10DF1F78300E04F67 /* tclOOMethod.c */,
				F93599C30DF1F78800E04F67 /* tclOOStubInit.c */,
				F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */,
				F96D3F0E08F272A7004A47F5 /* tclPanic.c */,
				F96D3F0F08F272A7004A47F5 /* tclParse.c */,
				F96D3F1108F272A7004A47F5 /* tclPathObj.c */,
				F96D3F1208F272A7004A47F5 /* tclPipe.c */,
				F96D3F1308F272A7004A47F5 /* tclPkg.c */,
				F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */,
				F96D3F1508F272A7004A47F5 /* tclPlatDecls.h */,
				F96D3F1608F272A7004A47F5 /* tclPort.h */,
				F96D3F1708F272A7004A47F5 /* tclPosixStr.c */,
				F96D3F1808F272A7004A47F5 /* tclPreserve.c */,
				F96D3F1908F272A7004A47F5 /* tclProc.c */,
				F96D3F1A08F272A7004A47F5 /* tclRegexp.c */,
				F96D3F1B08F272A7004A47F5 /* tclRegexp.h */,
				F96D3F1C08F272A7004A47F5 /* tclResolve.c */,
				F96D3F1D08F272A7004A47F5 /* tclResult.c */,
				F96D3F1E08F272A7004A47F5 /* tclScan.c */,
				F96D3F1F08F272A7004A47F5 /* tclStringObj.c */,
				F96D3F2408F272A7004A47F5 /* tclStrToD.c */,
				F96D3F2508F272A7004A47F5 /* tclStubInit.c */,
				F96D3F2608F272A7004A47F5 /* tclStubLib.c */,
				F96D3F2708F272A7004A47F5 /* tclTest.c */,
				F96D3F2808F272A7004A47F5 /* tclTestObj.c */,
				F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */,
				F96D3F2A08F272A7004A47F5 /* tclThread.c */,
				F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */,
				F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */,
				F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */,
				F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */,
				F96D3F2F08F272A7004A47F5 /* tclTimer.c */,
				F9903CAF094FAADA004613E9 /* tclTomMath.decls */,
				F96D3F3008F272A7004A47F5 /* tclTomMath.h */,
				F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */,
				F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */,
				F96D3F3208F272A7004A47F5 /* tclTrace.c */,
				F96D3F3308F272A7004A47F5 /* tclUniData.c */,
				F96D3F3408F272A7004A47F5 /* tclUtf.c */,
				F96D3F3508F272A7004A47F5 /* tclUtil.c */,
				F96D3F3608F272A7004A47F5 /* tclVar.c */,
				F96437C90EF0D4B2003F468E /* tclZlib.c */,
			);
			path = generic;
			sourceTree = "<group>";
		};
		F96D3F3808F272A7004A47F5 /* library */ = {
			isa = PBXGroup;
			children = (
				F96D3F3908F272A8004A47F5 /* auto.tcl */,
				F96D3F3A08F272A8004A47F5 /* clock.tcl */,
				F96D3F3B08F272A8004A47F5 /* dde */,
				F96D3F8C08F272A8004A47F5 /* history.tcl */,
				F96D3F8D08F272A8004A47F5 /* http */,
				F96D3F9308F272A8004A47F5 /* init.tcl */,
				F96D3F9408F272A8004A47F5 /* msgcat */,
				F96D401708F272AA004A47F5 /* opt */,
				F96D401A08F272AA004A47F5 /* package.tcl */,
				F96D401B08F272AA004A47F5 /* parray.tcl */,
				F9ECB1110B26521500A28025 /* platform */,
				F96D401C08F272AA004A47F5 /* reg */,
				F96D401E08F272AA004A47F5 /* safe.tcl */,
				F96D401F08F272AA004A47F5 /* tclIndex */,
				F96D402008F272AA004A47F5 /* tcltest */,
				F96D402308F272AA004A47F5 /* tm.tcl */,
				F96D425B08F272B2004A47F5 /* word.tcl */,
			);
			path = library;
			sourceTree = "<group>";
		};
		F96D3F3B08F272A8004A47F5 /* dde */ = {
			isa = PBXGroup;
			children = (
				F96D3F3C08F272A8004A47F5 /* pkgIndex.tcl */,
			);
			path = dde;
			sourceTree = "<group>";
		};
		F96D3F8D08F272A8004A47F5 /* http */ = {
			isa = PBXGroup;
			children = (
				F96D3F8E08F272A8004A47F5 /* http.tcl */,
				F96D3F8F08F272A8004A47F5 /* pkgIndex.tcl */,
			);
			path = http;
			sourceTree = "<group>";
		};
		F96D3F9408F272A8004A47F5 /* msgcat */ = {
			isa = PBXGroup;
			children = (
				F96D3F9508F272A8004A47F5 /* msgcat.tcl */,
				F96D3F9608F272A8004A47F5 /* pkgIndex.tcl */,
			);
			path = msgcat;
			sourceTree = "<group>";
		};
		F96D401708F272AA004A47F5 /* opt */ = {
			isa = PBXGroup;
			children = (
				F96D401808F272AA004A47F5 /* optparse.tcl */,
				F96D401908F272AA004A47F5 /* pkgIndex.tcl */,
			);
			path = opt;
			sourceTree = "<group>";
		};
		F96D401C08F272AA004A47F5 /* reg */ = {
			isa = PBXGroup;
			children = (
				F96D401D08F272AA004A47F5 /* pkgIndex.tcl */,
			);
			path = reg;
			sourceTree = "<group>";
		};
		F96D402008F272AA004A47F5 /* tcltest */ = {
			isa = PBXGroup;
			children = (
				F96D402108F272AA004A47F5 /* pkgIndex.tcl */,
				F96D402208F272AA004A47F5 /* tcltest.tcl */,
			);
			path = tcltest;
			sourceTree = "<group>";
		};
		F96D425C08F272B2004A47F5 /* libtommath */ = {
			isa = PBXGroup;
			children = (
				F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */,
				F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */,
				F96D426908F272B3004A47F5 /* bn_mp_add.c */,
				F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */,
				F96D426C08F272B3004A47F5 /* bn_mp_and.c */,
				F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */,
				F96D426E08F272B3004A47F5 /* bn_mp_clear.c */,
				F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */,
				F96D427008F272B3004A47F5 /* bn_mp_cmp.c */,
				F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */,
				F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */,
				F96D427408F272B3004A47F5 /* bn_mp_copy.c */,
				F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */,
				F96D427608F272B3004A47F5 /* bn_mp_div.c */,
				F96D427708F272B3004A47F5 /* bn_mp_div_2.c */,
				F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */,
				F96D427908F272B3004A47F5 /* bn_mp_div_3.c */,
				F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */,
				F96D427E08F272B3004A47F5 /* bn_mp_exch.c */,
				F96D427F08F272B3004A47F5 /* bn_mp_expt_u32.c */,
				F96D427F08F272B3004A47F5 /* bn_mp_expt_d_ex.c */,
				F96D428708F272B3004A47F5 /* bn_mp_grow.c */,
				F96D428808F272B3004A47F5 /* bn_mp_init.c */,
				F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */,
				F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */,
				F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */,
				F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */,
				F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */,
				F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */,
				F96D429508F272B3004A47F5 /* bn_mp_lshd.c */,
				F96D429608F272B3004A47F5 /* bn_mp_mod.c */,
				F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */,
				F96D429C08F272B3004A47F5 /* bn_mp_mul.c */,
				F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */,
				F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */,
				F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */,
				F96D42A208F272B3004A47F5 /* bn_mp_neg.c */,
				F96D42A308F272B3004A47F5 /* bn_mp_or.c */,
				F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */,
				F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */,
				F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */,
				F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */,
				F96D42BA08F272B3004A47F5 /* bn_mp_set.c */,
				F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */,
				F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */,
				F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */,
				F96D42C108F272B3004A47F5 /* bn_mp_sub.c */,
				F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */,
				F96D42C608F272B3004A47F5 /* bn_mp_to_ubin.c */,
				F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */,
				F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */,
				F96D42CB08F272B3004A47F5 /* bn_mp_to_radix.c */,
				F96D42CC08F272B3004A47F5 /* bn_mp_ubin_size.c */,
				F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */,
				F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */,
				F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */,
				F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */,
				F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */,
				F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */,
				F96D432908F272B4004A47F5 /* tommath_class.h */,
				F96D432A08F272B4004A47F5 /* tommath_superclass.h */,
			);
			path = libtommath;
			sourceTree = "<group>";
		};
		F96D432C08F272B4004A47F5 /* macosx */ = {
			isa = PBXGroup;
			children = (
				F96D432E08F272B5004A47F5 /* configure.ac */,
				F96D432F08F272B5004A47F5 /* GNUmakefile */,
				F96D433108F272B5004A47F5 /* README */,
				F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */,
				F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */,
				F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */,
				F96D433208F272B5004A47F5 /* Tcl-Info.plist.in */,
				F91E62260C1AE686006C9D96 /* Tclsh-Info.plist.in */,
				F97AE7F10B65C1E900310EA2 /* Tcl-Common.xcconfig */,
				F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */,
				F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */,
			);
			path = macosx;
			sourceTree = "<group>";
		};
		F96D434408F272B5004A47F5 /* tests */ = {
			isa = PBXGroup;
			children = (
				F96D434508F272B5004A47F5 /* all.tcl */,
				F96D434608F272B5004A47F5 /* append.test */,
				F96D434708F272B5004A47F5 /* appendComp.test */,
				F9ECB1CA0B2652D300A28025 /* apply.test */,
				F96D434808F272B5004A47F5 /* assocd.test */,
				F96D434908F272B5004A47F5 /* async.test */,
				F96D434A08F272B5004A47F5 /* autoMkindex.test */,
				F96D434B08F272B5004A47F5 /* basic.test */,
				F96D434C08F272B5004A47F5 /* binary.test */,
				F96D434D08F272B5004A47F5 /* case.test */,
				F96D434E08F272B5004A47F5 /* chan.test */,
				F9A493240CEBF38300B78AE2 /* chanio.test */,
				F96D434F08F272B5004A47F5 /* clock.test */,
				F96D435008F272B5004A47F5 /* cmdAH.test */,
				F96D435108F272B5004A47F5 /* cmdIL.test */,
				F96D435208F272B5004A47F5 /* cmdInfo.test */,
				F96D435308F272B5004A47F5 /* cmdMZ.test */,
				F96D435408F272B5004A47F5 /* compExpr-old.test */,
				F96D435508F272B5004A47F5 /* compExpr.test */,
				F96D435608F272B5004A47F5 /* compile.test */,
				F96D435708F272B5004A47F5 /* concat.test */,
				F96D435808F272B5004A47F5 /* config.test */,
				F974D5770FBE7E6100BF728B /* coroutine.test */,
				F96D435908F272B5004A47F5 /* dcall.test */,
				F96D435A08F272B5004A47F5 /* dict.test */,
				F96D435C08F272B5004A47F5 /* dstring.test */,
				F96D435E08F272B5004A47F5 /* encoding.test */,
				F96D435F08F272B5004A47F5 /* env.test */,
				F96D436008F272B5004A47F5 /* error.test */,
				F96D436108F272B5004A47F5 /* eval.test */,
				F96D436208F272B5004A47F5 /* event.test */,
				F96D436308F272B5004A47F5 /* exec.test */,
				F96D436408F272B5004A47F5 /* execute.test */,
				F96D436508F272B5004A47F5 /* expr-old.test */,
				F96D436608F272B5004A47F5 /* expr.test */,
				F96D436708F272B6004A47F5 /* fCmd.test */,
				F96D436808F272B6004A47F5 /* fileName.test */,
				F96D436908F272B6004A47F5 /* fileSystem.test */,
				F96D436A08F272B6004A47F5 /* for-old.test */,
				F96D436B08F272B6004A47F5 /* for.test */,
				F96D436C08F272B6004A47F5 /* foreach.test */,
				F96D436D08F272B6004A47F5 /* format.test */,
				F96D436E08F272B6004A47F5 /* get.test */,
				F96D436F08F272B6004A47F5 /* history.test */,
				F96D437008F272B6004A47F5 /* http.test */,
				F974D56C0FBE7D6300BF728B /* http11.test */,
				F96D437108F272B6004A47F5 /* httpd */,
				F974D56D0FBE7D6300BF728B /* httpd11.tcl */,
				F96D437208F272B6004A47F5 /* httpold.test */,
				F96D437308F272B6004A47F5 /* if-old.test */,
				F96D437408F272B6004A47F5 /* if.test */,
				F96D437508F272B6004A47F5 /* incr-old.test */,
				F96D437608F272B6004A47F5 /* incr.test */,
				F96D437708F272B6004A47F5 /* indexObj.test */,
				F96D437808F272B6004A47F5 /* info.test */,
				F96D437908F272B6004A47F5 /* init.test */,
				F96D437A08F272B6004A47F5 /* interp.test */,
				F96D437B08F272B6004A47F5 /* io.test */,
				F96D437C08F272B6004A47F5 /* ioCmd.test */,
				F96D437D08F272B6004A47F5 /* iogt.test */,
				F96D437F08F272B6004A47F5 /* join.test */,
				F96D438008F272B6004A47F5 /* lindex.test */,
				F96D438108F272B6004A47F5 /* link.test */,
				F96D438208F272B6004A47F5 /* linsert.test */,
				F96D438308F272B6004A47F5 /* list.test */,
				F96D438408F272B6004A47F5 /* listObj.test */,
				F96D438508F272B6004A47F5 /* llength.test */,
				F96D438608F272B6004A47F5 /* load.test */,
				F96D438708F272B6004A47F5 /* lrange.test */,
				F96D438808F272B6004A47F5 /* lrepeat.test */,
				F96D438908F272B6004A47F5 /* lreplace.test */,
				F96D438A08F272B6004A47F5 /* lsearch.test */,
				F96D438B08F272B6004A47F5 /* lset.test */,
				F96D438C08F272B6004A47F5 /* lsetComp.test */,
				F96D438D08F272B6004A47F5 /* macOSXFCmd.test */,
				F95FAFF90B34F1130072E431 /* macOSXLoad.test */,
				F96D438E08F272B6004A47F5 /* main.test */,
				F9ECB1CB0B26534C00A28025 /* mathop.test */,
				F96D438F08F272B6004A47F5 /* misc.test */,
				F96D439008F272B6004A47F5 /* msgcat.test */,
				F96D439108F272B6004A47F5 /* namespace-old.test */,
				F96D439208F272B7004A47F5 /* namespace.test */,
				F96D439308F272B7004A47F5 /* notify.test */,
				F91DC23C0E44C51B002CB8D1 /* nre.test */,
				F96D439408F272B7004A47F5 /* obj.test */,
				F93599C80DF1F81900E04F67 /* oo.test */,
				F96D439508F272B7004A47F5 /* opt.test */,
				F96D439608F272B7004A47F5 /* package.test */,
				F96D439708F272B7004A47F5 /* parse.test */,
				F96D439808F272B7004A47F5 /* parseExpr.test */,
				F96D439908F272B7004A47F5 /* parseOld.test */,
				F96D439A08F272B7004A47F5 /* pid.test */,
				F96D439B08F272B7004A47F5 /* pkg.test */,
				F96D439C08F272B7004A47F5 /* pkgMkIndex.test */,
				F96D439D08F272B7004A47F5 /* platform.test */,
				F96D439E08F272B7004A47F5 /* proc-old.test */,
				F96D439F08F272B7004A47F5 /* proc.test */,
				F96D43A008F272B7004A47F5 /* pwd.test */,
				F96D43A108F272B7004A47F5 /* README */,
				F96D43A208F272B7004A47F5 /* reg.test */,
				F96D43A308F272B7004A47F5 /* regexp.test */,
				F96D43A408F272B7004A47F5 /* regexpComp.test */,
				F96D43A508F272B7004A47F5 /* registry.test */,
				F96D43A608F272B7004A47F5 /* remote.tcl */,
				F96D43A708F272B7004A47F5 /* rename.test */,
				F96D43A808F272B7004A47F5 /* result.test */,
				F96D43A908F272B7004A47F5 /* safe.test */,
				F96D43AA08F272B7004A47F5 /* scan.test */,
				F96D43AB08F272B7004A47F5 /* security.test */,
				F96D43AC08F272B7004A47F5 /* set-old.test */,
				F96D43AD08F272B7004A47F5 /* set.test */,
				F96D43AE08F272B7004A47F5 /* socket.test */,
				F96D43AF08F272B7004A47F5 /* source.test */,
				F96D43B008F272B7004A47F5 /* split.test */,
				F96D43B108F272B7004A47F5 /* stack.test */,
				F96D43B208F272B7004A47F5 /* string.test */,
				F96D43B308F272B7004A47F5 /* stringComp.test */,
				F96D43B408F272B7004A47F5 /* stringObj.test */,
				F96D43B508F272B7004A47F5 /* subst.test */,
				F96D43B608F272B7004A47F5 /* switch.test */,
				F974D5780FBE7E6100BF728B /* tailcall.test */,
				F96D43B708F272B7004A47F5 /* tcltest.test */,
				F96D43B808F272B7004A47F5 /* thread.test */,
				F96D43B908F272B7004A47F5 /* timer.test */,
				F96D43BA08F272B7004A47F5 /* tm.test */,
				F96D43BB08F272B7004A47F5 /* trace.test */,
				F96D43BC08F272B7004A47F5 /* unixFCmd.test */,
				F96D43BD08F272B7004A47F5 /* unixFile.test */,
				F96D43BE08F272B7004A47F5 /* unixInit.test */,
				F96D43BF08F272B7004A47F5 /* unixNotfy.test */,
				F96D43C008F272B7004A47F5 /* unknown.test */,
				F96D43C108F272B7004A47F5 /* unload.test */,
				F96D43C208F272B7004A47F5 /* uplevel.test */,
				F96D43C308F272B7004A47F5 /* upvar.test */,
				F96D43C408F272B7004A47F5 /* utf.test */,
				F96D43C508F272B7004A47F5 /* util.test */,
				F96D43C608F272B7004A47F5 /* var.test */,
				F96D43C708F272B7004A47F5 /* while-old.test */,
				F96D43C808F272B7004A47F5 /* while.test */,
				F96D43C908F272B7004A47F5 /* winConsole.test */,
				F96D43CA08F272B7004A47F5 /* winDde.test */,
				F96D43CB08F272B7004A47F5 /* winFCmd.test */,
				F96D43CC08F272B7004A47F5 /* winFile.test */,
				F96D43CD08F272B7004A47F5 /* winNotify.test */,
				F96D43CE08F272B7004A47F5 /* winPipe.test */,
				F96D43CF08F272B7004A47F5 /* winTime.test */,
				F915432A0EF201CF0032D1E8 /* zlib.test */,
			);
			path = tests;
			sourceTree = "<group>";
		};
		F96D43D008F272B8004A47F5 /* tools */ = {
			isa = PBXGroup;
			children = (
				F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */,
				F96D43D208F272B8004A47F5 /* configure */,
				F96D43D308F272B8004A47F5 /* configure.ac */,
				F96D442508F272B8004A47F5 /* genStubs.tcl */,
				F96D442708F272B8004A47F5 /* index.tcl */,
				F96D442808F272B8004A47F5 /* installData.tcl */,
				F96D442908F272B8004A47F5 /* loadICU.tcl */,
				F96D442A08F272B8004A47F5 /* Makefile.in */,
				F96D442B08F272B8004A47F5 /* makeTestCases.tcl */,
				F96D442C08F272B8004A47F5 /* man2help.tcl */,
				F96D442D08F272B8004A47F5 /* man2help2.tcl */,
				F96D442E08F272B8004A47F5 /* man2html.tcl */,
				F96D442F08F272B8004A47F5 /* man2html1.tcl */,
				F96D443008F272B8004A47F5 /* man2html2.tcl */,
				F96D443108F272B8004A47F5 /* man2tcl.c */,
				F96D443208F272B8004A47F5 /* README */,
				F96D443308F272B8004A47F5 /* regexpTestLib.tcl */,
				F96D443508F272B8004A47F5 /* tcl.hpj.in */,
				F96D443908F272B9004A47F5 /* tcltk-man2html.tcl */,
				F96D443A08F272B9004A47F5 /* tclZIC.tcl */,
				F92D7F100DE777240033A13A /* tsdPerf.tcl */,
				F96D443B08F272B9004A47F5 /* uniClass.tcl */,
				F96D443C08F272B9004A47F5 /* uniParse.tcl */,
			);
			path = tools;
			sourceTree = "<group>";
		};
		F96D443E08F272B9004A47F5 /* unix */ = {
			isa = PBXGroup;
			children = (
				F96D444008F272B9004A47F5 /* aclocal.m4 */,
				F96D444108F272B9004A47F5 /* configure */,
				F96D444208F272B9004A47F5 /* configure.ac */,
				F96D444308F272B9004A47F5 /* dltest */,
				F96D444D08F272B9004A47F5 /* install-sh */,
				F96D444E08F272B9004A47F5 /* installManPage */,
				F96D444F08F272B9004A47F5 /* ldAix */,
				F96D445008F272B9004A47F5 /* Makefile.in */,
				F96D445208F272B9004A47F5 /* README */,
				F96D445308F272B9004A47F5 /* tcl.m4 */,
				F974D5790FBE7E9C00BF728B /* tcl.pc.in */,
				F96D445408F272B9004A47F5 /* tcl.spec */,
				F96D445508F272B9004A47F5 /* tclAppInit.c */,
				F96D445608F272B9004A47F5 /* tclConfig.h.in */,
				F96D445708F272B9004A47F5 /* tclConfig.sh.in */,
				F96D445808F272B9004A47F5 /* tclLoadAix.c */,
				F96D445908F272B9004A47F5 /* tclLoadDl.c */,
				F96D445B08F272B9004A47F5 /* tclLoadDyld.c */,
				F96D445C08F272B9004A47F5 /* tclLoadNext.c */,
				F96D445D08F272B9004A47F5 /* tclLoadOSF.c */,
				F96D445E08F272B9004A47F5 /* tclLoadShl.c */,
				F96D445F08F272B9004A47F5 /* tclUnixChan.c */,
				F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */,
				F96D446008F272B9004A47F5 /* tclUnixEvent.c */,
				F96D446108F272B9004A47F5 /* tclUnixFCmd.c */,
				F96D446208F272B9004A47F5 /* tclUnixFile.c */,
				F96D446308F272B9004A47F5 /* tclUnixInit.c */,
				F96D446408F272B9004A47F5 /* tclUnixNotfy.c */,
				F96D446508F272B9004A47F5 /* tclUnixPipe.c */,
				F96D446608F272B9004A47F5 /* tclUnixPort.h */,
				F96D446708F272B9004A47F5 /* tclUnixSock.c */,
				F96D446808F272B9004A47F5 /* tclUnixTest.c */,
				F96D446908F272B9004A47F5 /* tclUnixThrd.c */,
				F96D446B08F272B9004A47F5 /* tclUnixTime.c */,
				F96D446C08F272B9004A47F5 /* tclXtNotify.c */,
				F96D446D08F272B9004A47F5 /* tclXtTest.c */,
			);
			path = unix;
			sourceTree = "<group>";
		};
		F96D444308F272B9004A47F5 /* dltest */ = {
			isa = PBXGroup;
			children = (
				F96D444408F272B9004A47F5 /* Makefile.in */,
				F96D444508F272B9004A47F5 /* pkga.c */,
				F96D444608F272B9004A47F5 /* pkgb.c */,
				F96D444708F272B9004A47F5 /* pkgc.c */,
				F96D444808F272B9004A47F5 /* pkgd.c */,
				F96D444908F272B9004A47F5 /* pkge.c */,
				F96D444B08F272B9004A47F5 /* pkgua.c */,
				F96D444C08F272B9004A47F5 /* README */,
			);
			path = dltest;
			sourceTree = "<group>";
		};
		F96D446E08F272B9004A47F5 /* win */ = {
			isa = PBXGroup;
			children = (
				F96D447008F272BA004A47F5 /* aclocal.m4 */,
				F96D447108F272BA004A47F5 /* buildall.vc.bat */,
				F96D447208F272BA004A47F5 /* cat.c */,
				F96D447308F272BA004A47F5 /* coffbase.txt */,
				F96D447408F272BA004A47F5 /* configure */,
				F96D447508F272BA004A47F5 /* configure.ac */,
				F96D447708F272BA004A47F5 /* Makefile.in */,
				F96D447808F272BA004A47F5 /* makefile.vc */,
				F96D447908F272BA004A47F5 /* nmakehlp.c */,
				F96D447A08F272BA004A47F5 /* README */,
				F96D447C08F272BA004A47F5 /* rules.vc */,
				F96D447D08F272BA004A47F5 /* stub16.c */,
				F96D447E08F272BA004A47F5 /* tcl.dsp */,
				F96D447F08F272BA004A47F5 /* tcl.dsw */,
				F96D448008F272BA004A47F5 /* tcl.hpj.in */,
				F96D448108F272BA004A47F5 /* tcl.m4 */,
				F96D448208F272BA004A47F5 /* tcl.rc */,
				F96D448308F272BA004A47F5 /* tclAppInit.c */,
				F96D448408F272BA004A47F5 /* tclConfig.sh.in */,
				F96D448608F272BA004A47F5 /* tclsh.rc */,
				F96D448708F272BA004A47F5 /* tclWin32Dll.c */,
				F96D448808F272BA004A47F5 /* tclWinChan.c */,
				F96D448908F272BA004A47F5 /* tclWinConsole.c */,
				F96D448A08F272BA004A47F5 /* tclWinDde.c */,
				F96D448B08F272BA004A47F5 /* tclWinError.c */,
				F96D448C08F272BA004A47F5 /* tclWinFCmd.c */,
				F96D448D08F272BA004A47F5 /* tclWinFile.c */,
				F96D448E08F272BA004A47F5 /* tclWinInit.c */,
				F96D448F08F272BA004A47F5 /* tclWinInt.h */,
				F96D449008F272BA004A47F5 /* tclWinLoad.c */,
				F96D449108F272BA004A47F5 /* tclWinNotify.c */,
				F96D449208F272BA004A47F5 /* tclWinPipe.c */,
				F96D449308F272BA004A47F5 /* tclWinPort.h */,
				F96D449408F272BA004A47F5 /* tclWinReg.c */,
				F96D449508F272BA004A47F5 /* tclWinSerial.c */,
				F96D449608F272BA004A47F5 /* tclWinSock.c */,
				F96D449708F272BA004A47F5 /* tclWinTest.c */,
				F96D449808F272BA004A47F5 /* tclWinThrd.c */,
				F96D449A08F272BA004A47F5 /* tclWinTime.c */,
			);
			path = win;
			sourceTree = "<group>";
		};
		F9ECB1110B26521500A28025 /* platform */ = {
			isa = PBXGroup;
			children = (
				F9ECB1120B26521500A28025 /* pkgIndex.tcl */,
				F9ECB1130B26521500A28025 /* platform.tcl */,
				F9ECB1140B26521500A28025 /* shell.tcl */,
			);
			path = platform;
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
		8DD76FA90486AB0100D96B5E /* tcltest */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = F95CC8B009158F3100EA5ACE /* Build configuration list for PBXNativeTarget "tcltest" */;
			buildPhases = (
				F9A5C5F508F651A2008AE941 /* Configure Tcl */,
				8DD76FAB0486AB0100D96B5E /* Sources */,
				8DD76FAD0486AB0100D96B5E /* Frameworks */,
				F95FA74C0B32CE190072E431 /* Build dltest */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = tcltest;
			productInstallPath = "$(BINDIR)";
			productName = tcltest;
			productReference = 8DD76FB20486AB0100D96B5E /* tcltest */;
			productType = "com.apple.product-type.tool";
		};
		F97258A50A86873C00096C78 /* tests */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = F97258A80A86873D00096C78 /* Build configuration list for PBXNativeTarget "tests" */;
			buildPhases = (
				F97258A40A86873C00096C78 /* Run Testsuite */,
			);
			buildRules = (
			);
			dependencies = (
				F97258D30A868C6F00096C78 /* PBXTargetDependency */,
			);
			name = tests;
			productName = tests;
			productType = "com.apple.product-type.bundle";
		};
		F9E61D16090A3E94002B3151 /* Tcl */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = F95CC8AB09158F3100EA5ACE /* Build configuration list for PBXNativeTarget "Tcl" */;
			buildPhases = (
				F97AF02F0B665DA900310EA2 /* Build Tcl */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = Tcl;
			productName = tclsh;
			productReference = F9A3084B08F2D4CE00BAE1AB /* tclsh */;
			productType = "com.apple.product-type.tool";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		08FB7793FE84155DC02AAC07 /* Project object */ = {
			isa = PBXProject;
			attributes = {
				BuildIndependentTargetsInParallel = YES;
			};
			buildConfigurationList = F95CC8B509158F3100EA5ACE /* Build configuration list for PBXProject "Tcl" */;
			compatibilityVersion = "Xcode 3.2";
			hasScannedForEncodings = 1;
			mainGroup = 08FB7794FE84155DC02AAC07 /* Tcl */;
			projectDirPath = "";
			projectRoot = ..;
			targets = (
				F9E61D16090A3E94002B3151 /* Tcl */,
				8DD76FA90486AB0100D96B5E /* tcltest */,
				F97258A50A86873C00096C78 /* tests */,
			);
		};
/* End PBXProject section */

/* Begin PBXShellScriptBuildPhase section */
		F95FA74C0B32CE190072E431 /* Build dltest */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
				"$(DERIVED_FILE_DIR)/tcl/tclConfig.sh",
				"$(TCL_SRCROOT)/generic/tclStubLib.c",
				"$(TCL_SRCROOT)/unix/dltest/pkga.c",
				"$(TCL_SRCROOT)/unix/dltest/pkgb.c",
				"$(TCL_SRCROOT)/unix/dltest/pkgc.c",
				"$(TCL_SRCROOT)/unix/dltest/pkgd.c",
				"$(TCL_SRCROOT)/unix/dltest/pkge.c",
				"$(TCL_SRCROOT)/unix/dltest/pkgua.c",
			);
			name = "Build dltest";
			outputPaths = (
				"$(DERIVED_FILE_DIR)/tcl/dltest.marker",
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/bash;
			shellScript = "## dltest build script phase\n\nrm -f \"${DERIVED_FILE_DIR}/tcl/dltest.marker\"\nmake -C \"${DERIVED_FILE_DIR}/tcl\" dltest.marker\nln -fsh \"${DERIVED_FILE_DIR}/tcl/dltest\" \"${CONFIGURATION_BUILD_DIR}\"\n";
			showEnvVarsInLog = 0;
		};
		F97258A40A86873C00096C78 /* Run Testsuite */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "Run Testsuite";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/bash;
			shellScript = "if [ \"${ACTION:-build}\" == \"build\" ]; then\nif [ -z \"${HOME}\" ]; then export HOME=\"$(echo ~)\"; fi\ncd \"${TARGET_TEMP_DIR}\"; rm -rf \"${DERIVED_FILE_DIR}\"; mkdir -p \"${DERIVED_FILE_DIR}\"\nprintf '%s%s%s%s%s' '\npackage require tcltest 2.5\nnamespace import tcltest::*\nconfigure -testdir [file normalize {' \"${TCL_SRCROOT}\" '/tests}]\nconfigure -tmpdir [file normalize {' \"${DERIVED_FILE_DIR}\" '}]\nconfigure -verbose [concat [configure -verbose] line]\nrunAllTests\n' | \"${TEST_RIG}\"; TEST_RIG_RESULT=$?\n[ ${TEST_RIG_RESULT} -ne 0 ] && echo \"tcltest:0: error: tcltest exited abnormally with code ${TEST_RIG_RESULT}.\"\nexit ${TEST_RIG_RESULT}\nfi";
			showEnvVarsInLog = 0;
		};
		F97AF02F0B665DA900310EA2 /* Build Tcl */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
				"${TARGET_TEMP_DIR}/.none",
			);
			name = "Build Tcl";
			outputPaths = (
				"${TARGET_BUILD_DIR}/${EXECUTABLE_NAME}",
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/bash;
			shellScript = "if [ -e \"${TARGET_BUILD_DIR}/tclsh\" ]; then\n    mv -f \"${TARGET_BUILD_DIR}/tclsh\" \"${TARGET_BUILD_DIR}/tclsh${VERSION}\"\nfi\nexport CC=$(xcrun -find ${GCC} || echo ${GCC}); export LD=${CC}\ngnumake -C \"${TCL_SRCROOT}/macosx\" -j \"$(sysctl -n hw.activecpu)\" \"$(echo \"${ACTION}\" | sed -e s/build// -e s/clean/distclean/ -e s/..\\*/\\&-/)${MAKE_TARGET}\" CFLAGS_WARNING=\"${WARNING_CFLAGS}\" CFLAGS_OPTIMIZE=\"-O${GCC_OPTIMIZATION_LEVEL}\" SYMROOT=\"${BUILT_PRODUCTS_DIR}\" OBJ_DIR=\"${OBJECT_FILE_DIR}\" INSTALL_ROOT=\"${DSTROOT}\" PREFIX=\"${PREFIX}\" BINDIR=\"${BINDIR}\" LIBDIR=\"${FRAMEWORK_INSTALL_PATH}\" MANDIR=\"${MANDIR}\" EXTRA_CONFIGURE_ARGS=\"${CONFIGURE_ARGS}\" ${EXTRA_MAKE_FLAGS}\nresult=$?\nif [ -e \"${TARGET_BUILD_DIR}/tclsh${VERSION}\" ]; then\n    mv -f \"${TARGET_BUILD_DIR}/tclsh${VERSION}\" \"${TARGET_BUILD_DIR}/tclsh\"\nfi\nif [ -e \"${BUILT_PRODUCTS_DIR}/tcltest\" ]; then\n\trm -f \"${BUILT_PRODUCTS_DIR}/tcltest\"\nfi\necho \"Done\"\nrm -f \"${SCRIPT_INPUT_FILE_0}\"\nexit ${result}\n";
			showEnvVarsInLog = 0;
		};
		F9A5C5F508F651A2008AE941 /* Configure Tcl */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
				"$(TCL_SRCROOT)/macosx/configure.ac",
				"$(TCL_SRCROOT)/unix/configure.ac",
				"$(TCL_SRCROOT)/unix/tcl.m4",
				"$(TCL_SRCROOT)/unix/aclocal.m4",
				"$(TCL_SRCROOT)/unix/tclConfig.sh.in",
				"$(TCL_SRCROOT)/unix/Makefile.in",
				"$(TCL_SRCROOT)/unix/dltest/Makefile.in",
			);
			name = "Configure Tcl";
			outputPaths = (
				"$(DERIVED_FILE_DIR)/tcl/tclConfig.sh",
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/bash;
			shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.ac -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n    echo \"Running autoconf & autoheader in tcl/macosx\"\n    rm -rf autom4te.cache\n    ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n    rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n    echo \"Configuring Tcl\"\n    CC=$(xcrun -find ${GCC} || echo ${GCC})\n    \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n    ./config.status\nfi\n";
			showEnvVarsInLog = 0;
		};
/* End PBXShellScriptBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		8DD76FAB0486AB0100D96B5E /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				F96D456F08F272BB004A47F5 /* regcomp.c in Sources */,
				F96D457208F272BB004A47F5 /* regerror.c in Sources */,
				F96D457508F272BB004A47F5 /* regexec.c in Sources */,
				F96D457608F272BB004A47F5 /* regfree.c in Sources */,
				F96D457B08F272BB004A47F5 /* tclAlloc.c in Sources */,
				F96D457C08F272BB004A47F5 /* tclAsync.c in Sources */,
				F96D457D08F272BB004A47F5 /* tclBasic.c in Sources */,
				F96D457E08F272BC004A47F5 /* tclBinary.c in Sources */,
				F96D457F08F272BC004A47F5 /* tclCkalloc.c in Sources */,
				F96D458008F272BC004A47F5 /* tclClock.c in Sources */,
				F96D458108F272BC004A47F5 /* tclCmdAH.c in Sources */,
				F96D458208F272BC004A47F5 /* tclCmdIL.c in Sources */,
				F96D458308F272BC004A47F5 /* tclCmdMZ.c in Sources */,
				F96D458408F272BC004A47F5 /* tclCompCmds.c in Sources */,
				F96D458508F272BC004A47F5 /* tclCompExpr.c in Sources */,
				F96D458608F272BC004A47F5 /* tclCompile.c in Sources */,
				F96D458808F272BC004A47F5 /* tclConfig.c in Sources */,
				F96D458908F272BC004A47F5 /* tclDate.c in Sources */,
				F96D458B08F272BC004A47F5 /* tclDictObj.c in Sources */,
				F96D458C08F272BC004A47F5 /* tclEncoding.c in Sources */,
				F96D458D08F272BC004A47F5 /* tclEnv.c in Sources */,
				F96D458E08F272BC004A47F5 /* tclEvent.c in Sources */,
				F96D458F08F272BC004A47F5 /* tclExecute.c in Sources */,
				F96D459008F272BC004A47F5 /* tclFCmd.c in Sources */,
				F96D459108F272BC004A47F5 /* tclFileName.c in Sources */,
				F96D459308F272BC004A47F5 /* tclGet.c in Sources */,
				F96D459508F272BC004A47F5 /* tclHash.c in Sources */,
				F96D459608F272BC004A47F5 /* tclHistory.c in Sources */,
				F96D459708F272BC004A47F5 /* tclIndexObj.c in Sources */,
				F96D459B08F272BC004A47F5 /* tclInterp.c in Sources */,
				F96D459D08F272BC004A47F5 /* tclIO.c in Sources */,
				F96D459F08F272BC004A47F5 /* tclIOCmd.c in Sources */,
				F96D45A008F272BC004A47F5 /* tclIOGT.c in Sources */,
				F96D45A108F272BC004A47F5 /* tclIORChan.c in Sources */,
				F95D77EA0DFD820D00A8BF6F /* tclIORTrans.c in Sources */,
				F96D45A208F272BC004A47F5 /* tclIOSock.c in Sources */,
				F96D45A308F272BC004A47F5 /* tclIOUtil.c in Sources */,
				F96D45A408F272BC004A47F5 /* tclLink.c in Sources */,
				F96D45A508F272BC004A47F5 /* tclListObj.c in Sources */,
				F96D45A608F272BC004A47F5 /* tclLiteral.c in Sources */,
				F96D45A708F272BC004A47F5 /* tclLoad.c in Sources */,
				F96D45A908F272BC004A47F5 /* tclMain.c in Sources */,
				F96D45AA08F272BC004A47F5 /* tclNamesp.c in Sources */,
				F96D45AB08F272BC004A47F5 /* tclNotify.c in Sources */,
				F96D45AC08F272BC004A47F5 /* tclObj.c in Sources */,
				F93599B30DF1F75400E04F67 /* tclOO.c in Sources */,
				F93599B70DF1F76100E04F67 /* tclOOBasic.c in Sources */,
				F93599B90DF1F76600E04F67 /* tclOOCall.c in Sources */,
				F93599BC0DF1F77000E04F67 /* tclOODefineCmds.c in Sources */,
				F93599BE0DF1F77400E04F67 /* tclOOInfo.c in Sources */,
				F93599C20DF1F78300E04F67 /* tclOOMethod.c in Sources */,
				F93599C40DF1F78800E04F67 /* tclOOStubInit.c in Sources */,
				F93599C60DF1F78D00E04F67 /* tclOOStubLib.c in Sources */,
				F96D45AD08F272BC004A47F5 /* tclPanic.c in Sources */,
				F96D45AE08F272BC004A47F5 /* tclParse.c in Sources */,
				F96D45B008F272BC004A47F5 /* tclPathObj.c in Sources */,
				F96D45B108F272BC004A47F5 /* tclPipe.c in Sources */,
				F96D45B208F272BC004A47F5 /* tclPkg.c in Sources */,
				F96D45B308F272BC004A47F5 /* tclPkgConfig.c in Sources */,
				F96D45B608F272BC004A47F5 /* tclPosixStr.c in Sources */,
				F96D45B708F272BC004A47F5 /* tclPreserve.c in Sources */,
				F96D45B808F272BC004A47F5 /* tclProc.c in Sources */,
				F96D45B908F272BC004A47F5 /* tclRegexp.c in Sources */,
				F96D45BB08F272BC004A47F5 /* tclResolve.c in Sources */,
				F96D45BC08F272BC004A47F5 /* tclResult.c in Sources */,
				F96D45BD08F272BC004A47F5 /* tclScan.c in Sources */,
				F96D45BE08F272BC004A47F5 /* tclStringObj.c in Sources */,
				F96D45C308F272BC004A47F5 /* tclStrToD.c in Sources */,
				F96D45C408F272BC004A47F5 /* tclStubInit.c in Sources */,
				F96D45C508F272BC004A47F5 /* tclStubLib.c in Sources */,
				F96D45C608F272BC004A47F5 /* tclTest.c in Sources */,
				F96D45C708F272BC004A47F5 /* tclTestObj.c in Sources */,
				F96D45C808F272BC004A47F5 /* tclTestProcBodyObj.c in Sources */,
				F96D45C908F272BC004A47F5 /* tclThread.c in Sources */,
				F96D45CA08F272BC004A47F5 /* tclThreadAlloc.c in Sources */,
				F96D45CB08F272BC004A47F5 /* tclThreadJoin.c in Sources */,
				F96D45CC08F272BC004A47F5 /* tclThreadStorage.c in Sources */,
				F96D45CD08F272BC004A47F5 /* tclThreadTest.c in Sources */,
				F96D45CE08F272BC004A47F5 /* tclTimer.c in Sources */,
				F96D45D008F272BC004A47F5 /* tclTomMathInterface.c in Sources */,
				F96D45D108F272BC004A47F5 /* tclTrace.c in Sources */,
				F96D45D308F272BC004A47F5 /* tclUtf.c in Sources */,
				F96D45D408F272BC004A47F5 /* tclUtil.c in Sources */,
				F96D45D508F272BC004A47F5 /* tclVar.c in Sources */,
				F96437CA0EF0D4B2003F468E /* tclZlib.c in Sources */,
				F96D48E208F272C3004A47F5 /* bn_fast_s_mp_mul_digs.c in Sources */,
				F96D48E408F272C3004A47F5 /* bn_fast_s_mp_sqr.c in Sources */,
				F96D48E708F272C3004A47F5 /* bn_mp_add.c in Sources */,
				F96D48E808F272C3004A47F5 /* bn_mp_add_d.c in Sources */,
				F9E61D2B090A48A4002B3151 /* bn_mp_and.c in Sources */,
				F96D48EB08F272C3004A47F5 /* bn_mp_clamp.c in Sources */,
				F96D48EC08F272C3004A47F5 /* bn_mp_clear.c in Sources */,
				F96D48ED08F272C3004A47F5 /* bn_mp_clear_multi.c in Sources */,
				F96D48EE08F272C3004A47F5 /* bn_mp_cmp.c in Sources */,
				F9E61D28090A481F002B3151 /* bn_mp_cmp_d.c in Sources */,
				F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */,
				F96D48F208F272C3004A47F5 /* bn_mp_cnt_lsb.c in Sources */,
				F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */,
				F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */,
				F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */,
				F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */,
				F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */,
				F96D48F708F272C3004A47F5 /* bn_mp_div_3.c in Sources */,
				F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */,
				F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */,
				F9E61D2C090A48AC002B3151 /* bn_mp_expt_u32.c in Sources */,
				F9E61D2C090A48AC002B3151 /* bn_mp_expt_d_ex.c in Sources */,
				F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */,
				F96D490608F272C3004A47F5 /* bn_mp_init.c in Sources */,
				F96D490708F272C3004A47F5 /* bn_mp_init_copy.c in Sources */,
				F96D490808F272C3004A47F5 /* bn_mp_init_multi.c in Sources */,
				F96D490908F272C3004A47F5 /* bn_mp_init_set.c in Sources */,
				F96D490B08F272C3004A47F5 /* bn_mp_init_size.c in Sources */,
				F96D491008F272C3004A47F5 /* bn_mp_karatsuba_mul.c in Sources */,
				F96D491108F272C3004A47F5 /* bn_mp_karatsuba_sqr.c in Sources */,
				F96D491308F272C3004A47F5 /* bn_mp_lshd.c in Sources */,
				F96D491408F272C3004A47F5 /* bn_mp_mod.c in Sources */,
				F96D491508F272C3004A47F5 /* bn_mp_mod_2d.c in Sources */,
				F96D491A08F272C3004A47F5 /* bn_mp_mul.c in Sources */,
				F96D491B08F272C3004A47F5 /* bn_mp_mul_2.c in Sources */,
				F96D491C08F272C3004A47F5 /* bn_mp_mul_2d.c in Sources */,
				F96D491D08F272C3004A47F5 /* bn_mp_mul_d.c in Sources */,
				F9E61D29090A486C002B3151 /* bn_mp_neg.c in Sources */,
				F9E61D2E090A48BF002B3151 /* bn_mp_or.c in Sources */,
				F96D492908F272C3004A47F5 /* bn_mp_radix_size.c in Sources */,
				F96D492A08F272C3004A47F5 /* bn_mp_radix_smap.c in Sources */,
				F96D492C08F272C3004A47F5 /* bn_mp_read_radix.c in Sources */,
				F96D493708F272C3004A47F5 /* bn_mp_rshd.c in Sources */,
				F96D493808F272C3004A47F5 /* bn_mp_set.c in Sources */,
				F9E61D2F090A48C7002B3151 /* bn_mp_shrink.c in Sources */,
				F96D493C08F272C3004A47F5 /* bn_mp_sqr.c in Sources */,
				F9E61D2A090A4891002B3151 /* bn_mp_sqrt.c in Sources */,
				F96D493F08F272C3004A47F5 /* bn_mp_sub.c in Sources */,
				F96D494008F272C3004A47F5 /* bn_mp_sub_d.c in Sources */,
				F9E61D31090A48F9002B3151 /* bn_mp_to_ubin.c in Sources */,
				F96D494608F272C3004A47F5 /* bn_mp_toom_mul.c in Sources */,
				F96D494708F272C3004A47F5 /* bn_mp_toom_sqr.c in Sources */,
				F96D494908F272C3004A47F5 /* bn_mp_to_radix.c in Sources */,
				F9E61D32090A48FA002B3151 /* bn_mp_ubin_size.c in Sources */,
				F9E61D2D090A48BB002B3151 /* bn_mp_xor.c in Sources */,
				F96D494C08F272C3004A47F5 /* bn_mp_zero.c in Sources */,
				F96D494F08F272C3004A47F5 /* bn_s_mp_add.c in Sources */,
				F96D495108F272C3004A47F5 /* bn_s_mp_mul_digs.c in Sources */,
				F96D495308F272C3004A47F5 /* bn_s_mp_sqr.c in Sources */,
				F96D495408F272C3004A47F5 /* bn_s_mp_sub.c in Sources */,
				F96D49A908F272C4004A47F5 /* tclMacOSXBundle.c in Sources */,
				F96D49AD08F272C4004A47F5 /* tclMacOSXFCmd.c in Sources */,
				F96D49AE08F272C4004A47F5 /* tclMacOSXNotify.c in Sources */,
				F90509300913A72400327603 /* tclAppInit.c in Sources */,
				F96D4AC608F272C9004A47F5 /* tclLoadDyld.c in Sources */,
				F96D4ACA08F272C9004A47F5 /* tclUnixChan.c in Sources */,
				F9FC77B80AB29E9100B7077D /* tclUnixCompat.c in Sources */,
				F96D4ACB08F272C9004A47F5 /* tclUnixEvent.c in Sources */,
				F96D4ACC08F272C9004A47F5 /* tclUnixFCmd.c in Sources */,
				F96D4ACD08F272C9004A47F5 /* tclUnixFile.c in Sources */,
				F96D4ACE08F272C9004A47F5 /* tclUnixInit.c in Sources */,
				F96D4ACF08F272C9004A47F5 /* tclUnixNotfy.c in Sources */,
				F96D4AD008F272C9004A47F5 /* tclUnixPipe.c in Sources */,
				F96D4AD208F272CA004A47F5 /* tclUnixSock.c in Sources */,
				F96D4AD308F272CA004A47F5 /* tclUnixTest.c in Sources */,
				F96D4AD408F272CA004A47F5 /* tclUnixThrd.c in Sources */,
				F96D4AD608F272CA004A47F5 /* tclUnixTime.c in Sources */,
				F9F4415E0C8BAE6F00BCCD67 /* tclDTrace.d in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin PBXTargetDependency section */
		F97258D30A868C6F00096C78 /* PBXTargetDependency */ = {
			isa = PBXTargetDependency;
			target = 8DD76FA90486AB0100D96B5E /* tcltest */;
			targetProxy = F97258D20A868C6F00096C78 /* PBXContainerItemProxy */;
		};
/* End PBXTargetDependency section */

/* Begin XCBuildConfiguration section */
		F91BCC4F093152310042A6BF /* ReleaseUniversal */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = ReleaseUniversal;
		};
		F91BCC50093152310042A6BF /* ReleaseUniversal */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = ReleaseUniversal;
		};
		F91BCC51093152310042A6BF /* ReleaseUniversal */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
			buildSettings = {
				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
				CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				PREBINDING = NO;
			};
			name = ReleaseUniversal;
		};
		F93084370BB93D2800CD0B9E /* DebugMemCompile */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = DebugMemCompile;
		};
		F93084380BB93D2800CD0B9E /* DebugMemCompile */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = DebugMemCompile;
		};
		F93084390BB93D2800CD0B9E /* DebugMemCompile */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = DebugMemCompile;
		};
		F930843A0BB93D2800CD0B9E /* DebugMemCompile */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --enable-symbols=all";
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = DebugMemCompile;
		};
		F9359B250DF212DA00E04F67 /* DebugGCov */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				GCC_GENERATE_TEST_COVERAGE_FILES = YES;
				GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES;
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				ONLY_ACTIVE_ARCH = YES;
				OTHER_LDFLAGS = (
					"$(OTHER_LDFLAGS)",
					"-lgcov",
				);
				PREBINDING = NO;
			};
			name = DebugGCov;
		};
		F9359B260DF212DA00E04F67 /* DebugGCov */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = DebugGCov;
		};
		F9359B270DF212DA00E04F67 /* DebugGCov */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = DebugGCov;
		};
		F9359B280DF212DA00E04F67 /* DebugGCov */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = DebugGCov;
		};
		F95CC8AC09158F3100EA5ACE /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = Debug;
		};
		F95CC8AD09158F3100EA5ACE /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = Release;
		};
		F95CC8AE09158F3100EA5ACE /* DebugNoFixAndContinue */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = DebugNoFixAndContinue;
		};
		F95CC8B109158F3100EA5ACE /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_ENABLE_FIX_AND_CONTINUE = YES;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"__private_extern__=extern",
					"$(GCC_PREPROCESSOR_DEFINITIONS)",
				);
				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
				PRODUCT_NAME = tcltest;
			};
			name = Debug;
		};
		F95CC8B209158F3100EA5ACE /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = Release;
		};
		F95CC8B309158F3100EA5ACE /* DebugNoFixAndContinue */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = DebugNoFixAndContinue;
		};
		F95CC8B609158F3100EA5ACE /* Debug */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = Debug;
		};
		F95CC8B709158F3100EA5ACE /* Release */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = Release;
		};
		F95CC8B809158F3100EA5ACE /* DebugNoFixAndContinue */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = DebugNoFixAndContinue;
		};
		F97258A90A86873D00096C78 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = Debug;
		};
		F97258AA0A86873D00096C78 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = Release;
		};
		F97258AB0A86873D00096C78 /* DebugNoFixAndContinue */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = DebugNoFixAndContinue;
		};
		F97258AC0A86873D00096C78 /* ReleaseUniversal */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = ReleaseUniversal;
		};
		F97AED1B0B660B2100310EA2 /* Debug64bit */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = Debug64bit;
		};
		F97AED1C0B660B2100310EA2 /* Debug64bit */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = Debug64bit;
		};
		F97AED1D0B660B2100310EA2 /* Debug64bit */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = Debug64bit;
		};
		F97AED1E0B660B2100310EA2 /* Debug64bit */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = "$(NATIVE_ARCH_64_BIT)";
				CONFIGURE_ARGS = "--enable-64bit $(CONFIGURE_ARGS)";
				CPPFLAGS = "-arch $(NATIVE_ARCH_64_BIT) $(CPPFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				PREBINDING = NO;
			};
			name = Debug64bit;
		};
		F987512F0DE7B57E00B1C9EC /* DebugNoCF */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-corefoundation";
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = DebugNoCF;
		};
		F98751300DE7B57E00B1C9EC /* DebugNoCF */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = DebugNoCF;
		};
		F98751310DE7B57E00B1C9EC /* DebugNoCF */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = DebugNoCF;
		};
		F98751320DE7B57E00B1C9EC /* DebugNoCF */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = DebugNoCF;
		};
		F98751330DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-threads --disable-corefoundation";
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = DebugNoCFUnthreaded;
		};
		F98751340DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = DebugNoCFUnthreaded;
		};
		F98751350DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = DebugNoCFUnthreaded;
		};
		F98751360DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = DebugNoCFUnthreaded;
		};
		F9988AB10D814C6500B6B03B /* Debug gcc40 */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				GCC_VERSION = 4.0;
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = "Debug gcc40";
		};
		F9988AB20D814C6500B6B03B /* Debug gcc40 */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = "Debug gcc40";
		};
		F9988AB30D814C6500B6B03B /* Debug gcc40 */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_ENABLE_FIX_AND_CONTINUE = YES;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"__private_extern__=extern",
					"$(GCC_PREPROCESSOR_DEFINITIONS)",
				);
				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
				PRODUCT_NAME = tcltest;
			};
			name = "Debug gcc40";
		};
		F9988AB40D814C6500B6B03B /* Debug gcc40 */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = "Debug gcc40";
		};
		F9988AB50D814C7500B6B03B /* Debug llvm-gcc */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				GCC = "llvm-gcc";
				GCC_VERSION = com.apple.compilers.llvmgcc42;
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = "Debug llvm-gcc";
		};
		F9988AB60D814C7500B6B03B /* Debug llvm-gcc */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = "Debug llvm-gcc";
		};
		F9988AB70D814C7500B6B03B /* Debug llvm-gcc */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_ENABLE_FIX_AND_CONTINUE = YES;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"__private_extern__=extern",
					"$(GCC_PREPROCESSOR_DEFINITIONS)",
				);
				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
				PRODUCT_NAME = tcltest;
			};
			name = "Debug llvm-gcc";
		};
		F9988AB80D814C7500B6B03B /* Debug llvm-gcc */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = "Debug llvm-gcc";
		};
		F9988BB10D81586D00B6B03B /* ReleaseUniversal gcc40 */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
			buildSettings = {
				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
				CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
				GCC_VERSION = 4.0;
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				PREBINDING = NO;
			};
			name = "ReleaseUniversal gcc40";
		};
		F9988BB20D81586D00B6B03B /* ReleaseUniversal gcc40 */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = "ReleaseUniversal gcc40";
		};
		F9988BB30D81586D00B6B03B /* ReleaseUniversal gcc40 */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = "ReleaseUniversal gcc40";
		};
		F9988BB40D81586D00B6B03B /* ReleaseUniversal gcc40 */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = "ReleaseUniversal gcc40";
		};
		F9988BB50D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
			buildSettings = {
				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
				CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
				DEBUG_INFORMATION_FORMAT = dwarf;
				GCC = "llvm-gcc";
				GCC_OPTIMIZATION_LEVEL = 4;
				"GCC_OPTIMIZATION_LEVEL[arch=ppc]" = s;
				GCC_VERSION = com.apple.compilers.llvmgcc42;
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				PREBINDING = NO;
			};
			name = "ReleaseUniversal llvm-gcc";
		};
		F9988BB60D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = "ReleaseUniversal llvm-gcc";
		};
		F9988BB70D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = "ReleaseUniversal llvm-gcc";
		};
		F9988BB80D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = "ReleaseUniversal llvm-gcc";
		};
		F99EE73B0BE835310060D4AF /* DebugUnthreaded */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = DebugUnthreaded;
		};
		F99EE73C0BE835310060D4AF /* DebugLeaks */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = DebugLeaks;
		};
		F99EE73D0BE835310060D4AF /* DebugUnthreaded */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = DebugUnthreaded;
		};
		F99EE73E0BE835310060D4AF /* DebugLeaks */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = DebugLeaks;
		};
		F99EE73F0BE835310060D4AF /* DebugUnthreaded */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = DebugUnthreaded;
		};
		F99EE7400BE835310060D4AF /* DebugLeaks */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = DebugLeaks;
		};
		F99EE7410BE835310060D4AF /* DebugUnthreaded */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-threads";
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = DebugUnthreaded;
		};
		F99EE7420BE835310060D4AF /* DebugLeaks */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				GCC_PREPROCESSOR_DEFINITIONS = (
					PURIFY,
					"$(GCC_PREPROCESSOR_DEFINITIONS)",
				);
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
				RUN_CLANG_STATIC_ANALYZER = YES;
			};
			name = DebugLeaks;
		};
		F9A9D1EF0FC77787002A2BE3 /* Debug clang */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)";
				GCC = clang;
				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				ONLY_ACTIVE_ARCH = YES;
				PREBINDING = NO;
			};
			name = "Debug clang";
		};
		F9A9D1F00FC77787002A2BE3 /* Debug clang */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = "Debug clang";
		};
		F9A9D1F10FC77787002A2BE3 /* Debug clang */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_ENABLE_FIX_AND_CONTINUE = YES;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"__private_extern__=extern",
					"$(GCC_PREPROCESSOR_DEFINITIONS)",
				);
				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
				PRODUCT_NAME = tcltest;
			};
			name = "Debug clang";
		};
		F9A9D1F20FC77787002A2BE3 /* Debug clang */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = "Debug clang";
		};
		F9A9D1F30FC77799002A2BE3 /* ReleaseUniversal clang */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
				);
				CFLAGS = "-arch i386 -arch x86_64 $(CFLAGS)";
				DEBUG_INFORMATION_FORMAT = dwarf;
				GCC = clang;
				GCC_OPTIMIZATION_LEVEL = 4;
				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				PREBINDING = NO;
			};
			name = "ReleaseUniversal clang";
		};
		F9A9D1F40FC77799002A2BE3 /* ReleaseUniversal clang */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = "ReleaseUniversal clang";
		};
		F9A9D1F50FC77799002A2BE3 /* ReleaseUniversal clang */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = "ReleaseUniversal clang";
		};
		F9A9D1F60FC77799002A2BE3 /* ReleaseUniversal clang */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = "ReleaseUniversal clang";
		};
		F9EEED960C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = ReleaseUniversal10.5SDK;
		};
		F9EEED970C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = ReleaseUniversal10.5SDK;
		};
		F9EEED980C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_IDENTITY = "";
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = ReleaseUniversal10.5SDK;
		};
		F9EEED990C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
			buildSettings = {
				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
				CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)";
				CPPFLAGS = "-isysroot $(SDKROOT) $(CPPFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.5;
				PREBINDING = NO;
				SDKROOT = macosx10.5;
			};
			name = ReleaseUniversal10.5SDK;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		F95CC8AB09158F3100EA5ACE /* Build configuration list for PBXNativeTarget "Tcl" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				F95CC8AC09158F3100EA5ACE /* Debug */,
				F9A9D1F00FC77787002A2BE3 /* Debug clang */,
				F9988AB60D814C7500B6B03B /* Debug llvm-gcc */,
				F9988AB20D814C6500B6B03B /* Debug gcc40 */,
				F95CC8AE09158F3100EA5ACE /* DebugNoFixAndContinue */,
				F99EE73B0BE835310060D4AF /* DebugUnthreaded */,
				F98751300DE7B57E00B1C9EC /* DebugNoCF */,
				F98751340DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
				F93084370BB93D2800CD0B9E /* DebugMemCompile */,
				F99EE73C0BE835310060D4AF /* DebugLeaks */,
				F9359B260DF212DA00E04F67 /* DebugGCov */,
				F97AED1B0B660B2100310EA2 /* Debug64bit */,
				F95CC8AD09158F3100EA5ACE /* Release */,
				F91BCC4F093152310042A6BF /* ReleaseUniversal */,
				F9A9D1F40FC77799002A2BE3 /* ReleaseUniversal clang */,
				F9988BB60D81587400B6B03B /* ReleaseUniversal llvm-gcc */,
				F9988BB20D81586D00B6B03B /* ReleaseUniversal gcc40 */,
				F9EEED960C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Debug;
		};
		F95CC8B009158F3100EA5ACE /* Build configuration list for PBXNativeTarget "tcltest" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				F95CC8B109158F3100EA5ACE /* Debug */,
				F9A9D1F10FC77787002A2BE3 /* Debug clang */,
				F9988AB70D814C7500B6B03B /* Debug llvm-gcc */,
				F9988AB30D814C6500B6B03B /* Debug gcc40 */,
				F95CC8B309158F3100EA5ACE /* DebugNoFixAndContinue */,
				F99EE73D0BE835310060D4AF /* DebugUnthreaded */,
				F98751310DE7B57E00B1C9EC /* DebugNoCF */,
				F98751350DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
				F93084380BB93D2800CD0B9E /* DebugMemCompile */,
				F99EE73E0BE835310060D4AF /* DebugLeaks */,
				F9359B270DF212DA00E04F67 /* DebugGCov */,
				F97AED1C0B660B2100310EA2 /* Debug64bit */,
				F95CC8B209158F3100EA5ACE /* Release */,
				F91BCC50093152310042A6BF /* ReleaseUniversal */,
				F9A9D1F50FC77799002A2BE3 /* ReleaseUniversal clang */,
				F9988BB70D81587400B6B03B /* ReleaseUniversal llvm-gcc */,
				F9988BB30D81586D00B6B03B /* ReleaseUniversal gcc40 */,
				F9EEED970C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Debug;
		};
		F95CC8B509158F3100EA5ACE /* Build configuration list for PBXProject "Tcl" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				F95CC8B609158F3100EA5ACE /* Debug */,
				F9A9D1EF0FC77787002A2BE3 /* Debug clang */,
				F9988AB50D814C7500B6B03B /* Debug llvm-gcc */,
				F9988AB10D814C6500B6B03B /* Debug gcc40 */,
				F95CC8B809158F3100EA5ACE /* DebugNoFixAndContinue */,
				F99EE7410BE835310060D4AF /* DebugUnthreaded */,
				F987512F0DE7B57E00B1C9EC /* DebugNoCF */,
				F98751330DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
				F930843A0BB93D2800CD0B9E /* DebugMemCompile */,
				F99EE7420BE835310060D4AF /* DebugLeaks */,
				F9359B250DF212DA00E04F67 /* DebugGCov */,
				F97AED1E0B660B2100310EA2 /* Debug64bit */,
				F95CC8B709158F3100EA5ACE /* Release */,
				F91BCC51093152310042A6BF /* ReleaseUniversal */,
				F9A9D1F30FC77799002A2BE3 /* ReleaseUniversal clang */,
				F9988BB50D81587400B6B03B /* ReleaseUniversal llvm-gcc */,
				F9988BB10D81586D00B6B03B /* ReleaseUniversal gcc40 */,
				F9EEED990C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Debug;
		};
		F97258A80A86873D00096C78 /* Build configuration list for PBXNativeTarget "tests" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				F97258A90A86873D00096C78 /* Debug */,
				F9A9D1F20FC77787002A2BE3 /* Debug clang */,
				F9988AB80D814C7500B6B03B /* Debug llvm-gcc */,
				F9988AB40D814C6500B6B03B /* Debug gcc40 */,
				F97258AB0A86873D00096C78 /* DebugNoFixAndContinue */,
				F99EE73F0BE835310060D4AF /* DebugUnthreaded */,
				F98751320DE7B57E00B1C9EC /* DebugNoCF */,
				F98751360DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
				F93084390BB93D2800CD0B9E /* DebugMemCompile */,
				F99EE7400BE835310060D4AF /* DebugLeaks */,
				F9359B280DF212DA00E04F67 /* DebugGCov */,
				F97AED1D0B660B2100310EA2 /* Debug64bit */,
				F97258AA0A86873D00096C78 /* Release */,
				F97258AC0A86873D00096C78 /* ReleaseUniversal */,
				F9A9D1F60FC77799002A2BE3 /* ReleaseUniversal clang */,
				F9988BB80D81587400B6B03B /* ReleaseUniversal llvm-gcc */,
				F9988BB40D81586D00B6B03B /* ReleaseUniversal gcc40 */,
				F9EEED980C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Debug;
		};
/* End XCConfigurationList section */
	};
	rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
}

Changes to macosx/tclMacOSXBundle.c.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







/*
 * tclMacOSXBundle.c --
 *
 *	This file implements functions that inspect CFBundle structures on
 *	MacOS X.
 *
 * Copyright 2001-2009, Apple Inc.
 * Copyright (c) 2003-2009 Daniel A. Steffen <das@users.sourceforge.net>
 * Copyright © 2001-2009 Apple Inc.
 * Copyright © 2003-2009 Daniel A. Steffen <das@users.sourceforge.net>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclPort.h"
#include "tclInt.h"
166
167
168
169
170
171
172
173

174
175
176
177
178
179
180
166
167
168
169
170
171
172

173
174
175
176
177
178
179
180







-
+








int
Tcl_MacOSXOpenVersionedBundleResources(
    TCL_UNUSED(Tcl_Interp *),
    const char *bundleName,
    const char *bundleVersion,
    int hasResourceFile,
    size_t maxPathLen,
    Tcl_Size maxPathLen,
    char *libraryPath)
{
#ifdef HAVE_COREFOUNDATION
    CFBundleRef bundleRef, versionedBundleRef = NULL;
    CFStringRef bundleNameRef;
    CFURLRef libURL;

Changes to macosx/tclMacOSXFCmd.c.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tclMacOSXFCmd.c
 *
 *	This file implements the MacOSX specific portion of file manipulation
 *	subcommands of the "file" command.
 *
 * Copyright (c) 2003-2007 Daniel A. Steffen <das@users.sourceforge.net>
 * Copyright © 2003-2007 Daniel A. Steffen <das@users.sourceforge.net>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

84
85
86
87
88
89
90
91


92
93
94
95
96
97
98
84
85
86
87
88
89
90

91
92
93
94
95
96
97
98
99







-
+
+







static void		UpdateStringOfOSType(Tcl_Obj *objPtr);

static const Tcl_ObjType tclOSTypeType = {
    "osType",				/* name */
    NULL,				/* freeIntRepProc */
    NULL,				/* dupIntRepProc */
    UpdateStringOfOSType,		/* updateStringProc */
    SetOSTypeFromAny			/* setFromAnyProc */
    SetOSTypeFromAny,			/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

enum {
    kIsInvisible = 0x4000,
};

#define kFinfoIsInvisible	(OSSwapHostToBigConstInt16(kIsInvisible))
198
199
200
201
202
203
204
205
206


207
208
209
210
211
212
213
199
200
201
202
203
204
205


206
207
208
209
210
211
212
213
214







-
-
+
+







    case MACOSX_RSRCLENGTH_ATTRIBUTE:
	TclNewIntObj(*attributePtrPtr, *rsrcForkSize);
	break;
    }
    return TCL_OK;
#else
    Tcl_SetObjResult(interp, Tcl_NewStringObj(
	    "Mac OS X file attributes not supported", -1));
    Tcl_SetErrorCode(interp, "TCL", "UNSUPPORTED", NULL);
	    "Mac OS X file attributes not supported", TCL_INDEX_NONE));
    Tcl_SetErrorCode(interp, "TCL", "UNSUPPORTED", (char *)NULL);
    return TCL_ERROR;
#endif /* HAVE_GETATTRLIST */
}

/*
 *---------------------------------------------------------------------------
 *
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
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







-
-
+
+








-
-
+
+







	    /*
	     * Only setting rsrclength to 0 to strip a file's resource fork is
	     * supported.
	     */

	    if (newRsrcForkSize != 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"setting nonzero rsrclength not supported", -1));
		Tcl_SetErrorCode(interp, "TCL", "UNSUPPORTED", NULL);
			"setting nonzero rsrclength not supported", TCL_INDEX_NONE));
		Tcl_SetErrorCode(interp, "TCL", "UNSUPPORTED", (char *)NULL);
		return TCL_ERROR;
	    }

	    /*
	     * Construct path to resource fork.
	     */

	    Tcl_DStringInit(&ds);
	    Tcl_DStringAppend(&ds, native, -1);
	    Tcl_DStringAppend(&ds, _PATH_RSRCFORKSPEC, -1);
	    Tcl_DStringAppend(&ds, native, TCL_INDEX_NONE);
	    Tcl_DStringAppend(&ds, _PATH_RSRCFORKSPEC, TCL_INDEX_NONE);

	    result = truncate(Tcl_DStringValue(&ds), 0);
	    if (result != 0) {
		/*
		 * truncate() on a valid resource fork path may fail with a
		 * permission error in some OS releases, try truncating with
		 * open() instead:
371
372
373
374
375
376
377
378
379


380
381
382
383
384
385
386
372
373
374
375
376
377
378


379
380
381
382
383
384
385
386
387







-
-
+
+







		return TCL_ERROR;
	    }
	}
    }
    return TCL_OK;
#else
    Tcl_SetObjResult(interp, Tcl_NewStringObj(
	    "Mac OS X file attributes not supported", -1));
    Tcl_SetErrorCode(interp, "TCL", "UNSUPPORTED", NULL);
	    "Mac OS X file attributes not supported", TCL_INDEX_NONE));
    Tcl_SetErrorCode(interp, "TCL", "UNSUPPORTED", (char *)NULL);
    return TCL_ERROR;
#endif
}

/*
 *---------------------------------------------------------------------------
 *
455
456
457
458
459
460
461
462
463


464
465
466


467
468
469
470
471
472
473
456
457
458
459
460
461
462


463
464
465


466
467
468
469
470
471
472
473
474







-
-
+
+

-
-
+
+







	}

	/*
	 * Construct paths to resource forks.
	 */

	Tcl_DStringInit(&srcBuf);
	Tcl_DStringAppend(&srcBuf, src, -1);
	Tcl_DStringAppend(&srcBuf, _PATH_RSRCFORKSPEC, -1);
	Tcl_DStringAppend(&srcBuf, src, TCL_INDEX_NONE);
	Tcl_DStringAppend(&srcBuf, _PATH_RSRCFORKSPEC, TCL_INDEX_NONE);
	Tcl_DStringInit(&dstBuf);
	Tcl_DStringAppend(&dstBuf, dst, -1);
	Tcl_DStringAppend(&dstBuf, _PATH_RSRCFORKSPEC, -1);
	Tcl_DStringAppend(&dstBuf, dst, TCL_INDEX_NONE);
	Tcl_DStringAppend(&dstBuf, _PATH_RSRCFORKSPEC, TCL_INDEX_NONE);

	/*
	 * Do the copy.
	 */

	result = TclUnixCopyFile(Tcl_DStringValue(&srcBuf),
		Tcl_DStringValue(&dstBuf), statBufPtr, 1);
487
488
489
490
491
492
493
494

495
496
497
498
499
500
501
488
489
490
491
492
493
494

495
496
497
498
499
500
501
502







-
+







 * TclMacOSXMatchType --
 *
 *	This routine is used by the globbing code to check if a file matches a
 *	given mac type and/or creator code.
 *
 * Results:
 *	The return value is 1, 0 or -1 indicating whether the file matches the
 *	given criteria, does not match them, or an error occurred (in wich
 *	given criteria, does not match them, or an error occurred (in which
 *	case an error is left in interp).
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
573
574
575
576
577
578
579
580

581
582
583
584
585
586
587
574
575
576
577
578
579
580

581
582
583
584
585
586
587
588







-
+







GetOSTypeFromObj(
    Tcl_Interp *interp,		/* Used for error reporting if not NULL. */
    Tcl_Obj *objPtr,		/* The object from which to get an OSType. */
    OSType *osTypePtr)		/* Place to store resulting OSType. */
{
    int result = TCL_OK;

    if (!TclHasIntRep(objPtr, &tclOSTypeType)) {
    if (!TclHasInternalRep(objPtr, &tclOSTypeType)) {
	result = SetOSTypeFromAny(interp, objPtr);
    }
    *osTypePtr = (OSType) objPtr->internalRep.wideValue;
    return result;
}

/*
635
636
637
638
639
640
641
642

643
644
645

646
647
648
649
650
651

652
653
654
655
656
657
658
659
660
661
662
663

664
665
666
667
668
669
670
636
637
638
639
640
641
642

643
644
645

646
647
648
649
650
651

652
653
654
655
656
657
658
659
660
661
662
663

664
665
666
667
668
669
670
671







-
+


-
+





-
+











-
+







    Tcl_Interp *interp,		/* Tcl interpreter */
    Tcl_Obj *objPtr)		/* Pointer to the object to convert */
{
    const char *string;
    int result = TCL_OK;
    Tcl_DString ds;
    Tcl_Encoding encoding = Tcl_GetEncoding(NULL, "macRoman");
    size_t length;
    Tcl_Size length;

    string = TclGetStringFromObj(objPtr, &length);
    Tcl_UtfToExternalDString(encoding, string, length, &ds);
    Tcl_UtfToExternalDStringEx(NULL, encoding, string, length, TCL_ENCODING_PROFILE_TCL8, &ds, NULL);

    if (Tcl_DStringLength(&ds) > 4) {
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "expected Macintosh OS type but got \"%s\": ", string));
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "MAC_OSTYPE", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "MAC_OSTYPE", (char *)NULL);
	}
	result = TCL_ERROR;
    } else {
	OSType osType;
	char bytes[4] = {'\0','\0','\0','\0'};

	memcpy(bytes, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
	osType = (OSType) bytes[0] << 24 |
		 (OSType) bytes[1] << 16 |
		 (OSType) bytes[2] <<  8 |
		 (OSType) bytes[3];
	TclFreeIntRep(objPtr);
	TclFreeInternalRep(objPtr);
	objPtr->internalRep.wideValue = (Tcl_WideInt) osType;
	objPtr->typePtr = &tclOSTypeType;
    }
    Tcl_DStringFree(&ds);
    Tcl_FreeEncoding(encoding);
    return result;
}
705
706
707
708
709
710
711
712

713
714
715
716
717
718
719
706
707
708
709
710
711
712

713
714
715
716
717
718
719
720







-
+







    src[0] = (char) (osType >> 24);
    src[1] = (char) (osType >> 16);
    src[2] = (char) (osType >>  8);
    src[3] = (char) (osType);
    src[4] = '\0';

    encoding = Tcl_GetEncoding(NULL, "macRoman");
    Tcl_ExternalToUtf(NULL, encoding, src, -1, /* flags */ 0,
    Tcl_ExternalToUtf(NULL, encoding, src, TCL_INDEX_NONE, /* flags */ 0,
	    /* statePtr */ NULL, dst, size, /* srcReadPtr */ NULL,
	    /* dstWrotePtr */ &written, /* dstCharsPtr */ NULL);
    Tcl_FreeEncoding(encoding);

    (void)Tcl_InitStringRep(objPtr, NULL, written);
}


Changes to macosx/tclMacOSXNotify.c.

1
2
3
4
5
6
7
8
9
10



11
12
13
14
15
16
17
1
2
3
4
5
6
7



8
9
10
11
12
13
14
15
16
17







-
-
-
+
+
+







/*
 * tclMacOSXNotify.c --
 *
 *	This file contains the implementation of a merged CFRunLoop/select()
 *	based notifier, which is the lowest-level part of the Tcl event loop.
 *	This file works together with generic/tclNotify.c.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright 2001-2009, Apple Inc.
 * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2001-2009, Apple Inc.
 * Copyright © 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

235
236
237
238
239
240
241
242

243
244
245
246
247
248
249
235
236
237
238
239
240
241

242
243
244
245
246
247
248
249







-
+








/*
 * Debug version of SpinLockLock that logs the time spent waiting for the lock
 */

#define SpinLockLockDbg(p) \
    if (!SpinLockTry(p)) {						\
	Tcl_WideInt s = TclpGetWideClicks(), e;				\
	long long s = TclpGetWideClicks(), e;				\
									\
	SpinLockLock(p);						\
	e = TclpGetWideClicks();					\
	TclMacOSXNotifierDbgMsg("waited on %s for %8.0f ns",		\
		#p, TclpWideClicksToNanoseconds(e-s));			\
    }
#undef LOCK_NOTIFIER_INIT
307
308
309
310
311
312
313
314

315
316
317
318
319
320
321
307
308
309
310
311
312
313

314
315
316
317
318
319
320
321







-
+







    int mask;			/* Mask of desired events: TCL_READABLE,
				 * etc. */
    int readyMask;		/* Mask of events that have been seen since
				 * the last time file handlers were invoked
				 * for this file. */
    Tcl_FileProc *proc;		/* Function to call, in the style of
				 * Tcl_CreateFileHandler. */
    ClientData clientData;	/* Argument to pass to proc. */
    void *clientData;	/* Argument to pass to proc. */
    struct FileHandler *nextPtr;/* Next in list of all files we care about. */
} FileHandler;

/*
 * The following structure is what is added to the Tcl event queue when file
 * handlers are ready to fire.
 */
453
454
455
456
457
458
459














460
461
462
463
464
465
466
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480







+
+
+
+
+
+
+
+
+
+
+
+
+
+







 * The following static indicates if the notifier thread is running.
 *
 * You must hold the notifierInitLock before accessing this variable.
 */

static int notifierThreadRunning;

/*
 * The following static flag indicates that async handlers are pending.
 */

#if TCL_THREADS
static int asyncPending = 0;
#endif

/*
 * Signal mask information for notifier thread.
 */
static sigset_t notifierSigMask;
static sigset_t allSigMask;

/*
 * This is the thread ID of the notifier thread that does select. Only valid
 * when notifierThreadRunning is non-zero.
 *
 * You must hold the notifierInitLock before accessing this variable.
 */

487
488
489
490
491
492
493
494

495
496
497
498
499
500
501
501
502
503
504
505
506
507

508
509
510
511
512
513
514
515







-
+







#define CF_TIMEINTERVAL_FOREVER 5.05e8

/*
 * Static routines defined in this file.
 */

static void		StartNotifierThread(void);
static TCL_NORETURN void NotifierThreadProc(ClientData clientData);
static TCL_NORETURN void NotifierThreadProc(void *clientData);
static int		FileHandlerEventProc(Tcl_Event *evPtr, int flags);
static void		TimerWakeUp(CFRunLoopTimerRef timer, void *info);
static void		QueueFileEvents(void *info);
static void		UpdateWaitingListAndServiceEvents(
			    CFRunLoopObserverRef observer,
			    CFRunLoopActivity activity, void *info);
static int		OnOffWaitingList(ThreadSpecificData *tsdPtr,
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
558
559
560
561
562
563
564
565
566

567
568
569
570
571
572
573
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601

602
603
604
605
606
607
608
609
610
611
612
613
614


615
616
617

618






619
620
621
622
623
624

625
626
627
628
629
630
631
632







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+












-
-
+
+

-
+
-
-
-
-
-
-






-
+







#define noCFafterFork	1
#endif /* MAC_OS_X_VERSION_MIN_REQUIRED */
#endif /* HAVE_PTHREAD_ATFORK */

/*
 *----------------------------------------------------------------------
 *
 * LookUpFileHandler --
 *
 *	Look up the file handler structure (and optionally the previous one in
 *	the chain) associated with a file descriptor.
 *
 * Returns:
 *	A pointer to the file handler, or NULL if it can't be found.
 *
 * Side effects:
 *	If prevPtrPtr is non-NULL, it will be written to if the file handler
 *	is found.
 *
 *----------------------------------------------------------------------
 */

static inline FileHandler *
LookUpFileHandler(
    ThreadSpecificData *tsdPtr,	/* Where to look things up. */
    int fd,			/* What we are looking for. */
    FileHandler **prevPtrPtr)	/* If non-NULL, where to report the previous
				 * pointer. */
{
    FileHandler *filePtr, *prevPtr;

    /*
     * Find the entry for the given file (and return if there isn't one).
     */

    for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
	    prevPtr = filePtr, filePtr = filePtr->nextPtr) {
	if (filePtr == NULL) {
	    return NULL;
	}
	if (filePtr->fd == fd) {
	    break;
	}
    }

    /*
     * Report what we've found to our caller.
     */

    if (prevPtrPtr) {
	*prevPtrPtr = prevPtr;
    }
    return filePtr;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_InitNotifier --
 * TclpInitNotifier --
 *
 *	Initializes the platform specific notifier state.
 *
 * Results:
 *	Returns a handle to the notifier state for this thread.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

ClientData
Tcl_InitNotifier(void)
void *
TclpInitNotifier(void)
{
    ThreadSpecificData *tsdPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (tclNotifierHooks.initNotifierProc) {
	return tclNotifierHooks.initNotifierProc();
    }

    tsdPtr = TCL_TSD_INIT(&dataKey);

#ifdef WEAK_IMPORT_SPINLOCKLOCK
    /*
     * Initialize support for weakly imported spinlock API.
     */
    if (pthread_once(&spinLockLockInitControl, SpinLockLockInit)) {
	Tcl_Panic("Tcl_InitNotifier: pthread_once failed");
	Tcl_Panic("Tcl_InitNotifier: %s", "pthread_once failed");
    }
#endif

#ifndef __CONSTANT_CFSTRINGS__
    if (!tclEventsOnlyRunLoopMode) {
	tclEventsOnlyRunLoopMode = CFSTR(TCL_EVENTS_ONLY_RUN_LOOP_MODE);
    }
586
587
588
589
590
591
592
593


594
595
596
597
598
599
600
601
602
603
604
605
606


607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624


625
626
627
628
629
630
631
645
646
647
648
649
650
651

652
653
654
655
656
657
658
659
660
661
662
663
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







-
+
+











-
-
+
+
















-
-
+
+








	bzero(&runLoopSourceContext, sizeof(CFRunLoopSourceContext));
	runLoopSourceContext.info = tsdPtr;
	runLoopSourceContext.perform = QueueFileEvents;
	runLoopSource = CFRunLoopSourceCreate(NULL, LONG_MIN,
		&runLoopSourceContext);
	if (!runLoopSource) {
	    Tcl_Panic("Tcl_InitNotifier: could not create CFRunLoopSource");
	    Tcl_Panic("Tcl_InitNotifier: %s",
		    "could not create CFRunLoopSource");
	}
	CFRunLoopAddSource(runLoop, runLoopSource, kCFRunLoopCommonModes);
	CFRunLoopAddSource(runLoop, runLoopSource, tclEventsOnlyRunLoopMode);

	bzero(&runLoopObserverContext, sizeof(CFRunLoopObserverContext));
	runLoopObserverContext.info = tsdPtr;
	runLoopObserver = CFRunLoopObserverCreate(NULL,
		kCFRunLoopEntry|kCFRunLoopExit, TRUE,
		LONG_MIN, UpdateWaitingListAndServiceEvents,
		&runLoopObserverContext);
	if (!runLoopObserver) {
	    Tcl_Panic("Tcl_InitNotifier: could not create "
		    "CFRunLoopObserver");
	    Tcl_Panic("Tcl_InitNotifier: %s",
		    "could not create CFRunLoopObserver");
	}
	CFRunLoopAddObserver(runLoop, runLoopObserver, kCFRunLoopCommonModes);

	/*
	 * Create a second CFRunLoopObserver with the same callback as above
	 * for the tclEventsOnlyRunLoopMode to ensure that the callback can be
	 * re-entered via Tcl_ServiceAll() in the kCFRunLoopBeforeWaiting case
	 * (CFRunLoop prevents observer callback re-entry of a given observer
	 * instance).
	 */

	runLoopObserverTcl = CFRunLoopObserverCreate(NULL,
		kCFRunLoopEntry|kCFRunLoopExit, TRUE,
		LONG_MIN, UpdateWaitingListAndServiceEvents,
		&runLoopObserverContext);
	if (!runLoopObserverTcl) {
	    Tcl_Panic("Tcl_InitNotifier: could not create "
		    "CFRunLoopObserver");
	    Tcl_Panic("Tcl_InitNotifier: %s",
		    "could not create CFRunLoopObserver");
	}
	CFRunLoopAddObserver(runLoop, runLoopObserverTcl,
		tclEventsOnlyRunLoopMode);

	tsdPtr->runLoop = runLoop;
	tsdPtr->runLoopSource = runLoopSource;
	tsdPtr->runLoopObserver = runLoopObserver;
646
647
648
649
650
651
652
653

654
655
656
657
658
659
660
661
662
663
664
665
666

667
668
669
670
671
672
673


674
675
676
677
678
679


680
681
682
683
684
685
686
706
707
708
709
710
711
712

713
714
715
716
717
718
719
720
721
722
723
724
725

726
727
728
729
730
731


732
733
734
735
736
737


738
739
740
741
742
743
744
745
746







-
+












-
+





-
-
+
+




-
-
+
+







     * child of a fork.
     */

    if (MayUsePthreadAtfork() && !atForkInit) {
	int result = pthread_atfork(AtForkPrepare, AtForkParent, AtForkChild);

	if (result) {
	    Tcl_Panic("Tcl_InitNotifier: pthread_atfork failed");
	    Tcl_Panic("Tcl_InitNotifier: %s", "pthread_atfork failed");
	}
	atForkInit = 1;
    }
#endif /* HAVE_PTHREAD_ATFORK */
    if (notifierCount == 0) {
	int fds[2], status;

	/*
	 * Initialize trigger pipe.
	 */

	if (pipe(fds) != 0) {
	    Tcl_Panic("Tcl_InitNotifier: could not create trigger pipe");
	    Tcl_Panic("Tcl_InitNotifier: %s", "could not create trigger pipe");
	}

	status = fcntl(fds[0], F_GETFL);
	status |= O_NONBLOCK;
	if (fcntl(fds[0], F_SETFL, status) < 0) {
	    Tcl_Panic("Tcl_InitNotifier: could not make receive pipe non "
		    "blocking");
	    Tcl_Panic("Tcl_InitNotifier: %s",
		    "could not make receive pipe non-blocking");
	}
	status = fcntl(fds[1], F_GETFL);
	status |= O_NONBLOCK;
	if (fcntl(fds[1], F_SETFL, status) < 0) {
	    Tcl_Panic("Tcl_InitNotifier: could not make trigger pipe non "
		    "blocking");
	    Tcl_Panic("Tcl_InitNotifier: %s",
		    "could not make trigger pipe non-blocking");
	}

	receivePipe = fds[0];
	triggerPipe = fds[1];

	/*
	 * Create notifier thread lazily in Tcl_WaitForEvent() to avoid
696
697
698
699
700
701
702
703

704
705
706
707
708
709
710
711
712
713
714
715
716
717
718

719
720
721
722
723
724
725
756
757
758
759
760
761
762

763
764
765
766
767
768
769
770
771
772
773
774
775
776
777

778
779
780
781
782
783
784
785







-
+














-
+







    UNLOCK_NOTIFIER_INIT;
    return tsdPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TclMacOSXNotifierAddRunLoopMode --
 * Tcl_MacOSXNotifierAddRunLoopMode --
 *
 *	Add the tcl notifier RunLoop source, observer and timer (if any)
 *	to the given RunLoop mode.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TclMacOSXNotifierAddRunLoopMode(
Tcl_MacOSXNotifierAddRunLoopMode(
    const void *runLoopMode)
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    CFStringRef mode = (CFStringRef) runLoopMode;

    if (tsdPtr->runLoop) {
	CFRunLoopAddSource(tsdPtr->runLoop, tsdPtr->runLoopSource, mode);
753
754
755
756
757
758
759









760
761
762
763
764
765

766
767
768
769
770






771
772
773
774
775
776
777
778
779

780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

796
797
798
799

800
801
802
803
804
805


806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833

834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

849
850
851
852

853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868

869




870






871
872
873
874
875
876
877
878
879







+
+
+
+
+
+
+
+
+





-
+





+
+
+
+
+
+



-




-
+















-
+
-
-
-
-
+
-
-
-
-
-
-
+
+







    if (!notifierCount) {
	Tcl_Panic("StartNotifierThread: notifier not initialized");
    }
    if (!notifierThreadRunning) {
	int result;
	pthread_attr_t attr;

	/*
	 * Arrange for the notifier thread to start with all
	 * signals blocked. In its mainloop it unblocks the
	 * signals at safe points.
	 */

	sigfillset(&allSigMask);
	pthread_sigmask(SIG_BLOCK, &allSigMask, &notifierSigMask);

	pthread_attr_init(&attr);
	pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
	pthread_attr_setstacksize(&attr, 60 * 1024);
	result = pthread_create(&notifierThread, &attr,
		(void * (*)(void *))NotifierThreadProc, NULL);
		(void * (*)(void *)) NotifierThreadProc, NULL);
	pthread_attr_destroy(&attr);
	if (result) {
	    Tcl_Panic("StartNotifierThread: unable to start notifier thread");
	}
	notifierThreadRunning = 1;

	/*
	 * Restore original signal mask.
	 */

	pthread_sigmask(SIG_SETMASK, &notifierSigMask, NULL);
    }
    UNLOCK_NOTIFIER_INIT;
}


/*
 *----------------------------------------------------------------------
 *
 * Tcl_FinalizeNotifier --
 * TclpFinalizeNotifier --
 *
 *	This function is called to cleanup the notifier state before a thread
 *	is terminated.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	May terminate the background notifier thread if this is the last
 *	notifier instance.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_FinalizeNotifier(
TclpFinalizeNotifier(
    ClientData clientData)
{
    ThreadSpecificData *tsdPtr;

    TCL_UNUSED(void *))
    if (tclNotifierHooks.finalizeNotifierProc) {
	tclNotifierHooks.finalizeNotifierProc(clientData);
	return;
    }

    tsdPtr = TCL_TSD_INIT(&dataKey);
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    LOCK_NOTIFIER_INIT;
    notifierCount--;
    DISABLE_ASL;

    /*
     * If this is the last thread to use the notifier, close the notifier pipe
833
834
835
836
837
838
839








840
841
842
843
844
845
846
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921







+
+
+
+
+
+
+
+







		int result = pthread_join(notifierThread, NULL);

		if (result) {
		    Tcl_Panic("Tcl_FinalizeNotifier: unable to join notifier "
			    "thread");
		}
		notifierThreadRunning = 0;

		/*
		 * If async marks are outstanding, perform actions now.
		 */
		if (asyncPending) {
		    asyncPending = 0;
		    TclAsyncMarkFromNotifier();
		}
	    }

	    close(receivePipe);
	    triggerPipe = -1;
	}
	CLOSE_NOTIFIER_LOG;
    }
872
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


898
899

900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917

918
919
920
921
922
923
924
925
926
927
928
929
930
931

932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952

953
954
955
956
957
958
959
947
948
949
950
951
952
953

954
955
956
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
1016

1017
1018
1019
1020
1021
1022
1023
1024







-
+
















-
-
+
+

-
+
-
-
-
-
-












-
+













-
+






-
-
-
-
-









-
+







    }
    UNLOCK_NOTIFIER_TSD;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AlertNotifier --
 * TclpAlertNotifier --
 *
 *	Wake up the specified notifier from any thread. This routine is called
 *	by the platform independent notifier code whenever the Tcl_ThreadAlert
 *	routine is called. This routine is guaranteed not to be called on a
 *	given notifier after Tcl_FinalizeNotifier is called for that notifier.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Signals the notifier condition variable for the specified notifier.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_AlertNotifier(
    ClientData clientData)
TclpAlertNotifier(
    void *clientData)
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)clientData;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;

    if (tclNotifierHooks.alertNotifierProc) {
	tclNotifierHooks.alertNotifierProc(clientData);
	return;
    }

    LOCK_NOTIFIER_TSD;
    if (tsdPtr->runLoop) {
	CFRunLoopSourceSignal(tsdPtr->runLoopSource);
	CFRunLoopWakeUp(tsdPtr->runLoop);
    }
    UNLOCK_NOTIFIER_TSD;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetTimer --
 * TclpSetTimer --
 *
 *	This function sets the current notifier timer value.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Replaces any previous timer.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetTimer(
TclpSetTimer(
    const Tcl_Time *timePtr)		/* Timeout value, may be NULL. */
{
    ThreadSpecificData *tsdPtr;
    CFRunLoopTimerRef runLoopTimer;
    CFTimeInterval waitTime;

    if (tclNotifierHooks.setTimerProc) {
	tclNotifierHooks.setTimerProc(timePtr);
	return;
    }

    tsdPtr = TCL_TSD_INIT(&dataKey);
    runLoopTimer = tsdPtr->runLoopTimer;
    if (!runLoopTimer) {
	return;
    }
    if (timePtr) {
	Tcl_Time vTime = *timePtr;

	if (vTime.sec != 0 || vTime.usec != 0) {
	    tclScaleTimeProcPtr(&vTime, tclTimeClientData);
	    TclScaleTime(&vTime);
	    waitTime = vTime.sec + 1.0e-6 * vTime.usec;
	} else {
	    waitTime = 0;
	}
    } else {
	waitTime = CF_TIMEINTERVAL_FOREVER;
    }
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
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
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

1116
1117


1118
1119
1120













1121

1122
1123
1124
1125
1126
1127
1128
1129







-
+






-
+













-
+



-
+
-
-
-
-
-
-
-



















-
+

-
+











-
+







-
+

-
-
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-

-
+







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

static void
TimerWakeUp(
    TCL_UNUSED(CFRunLoopTimerRef),
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ServiceModeHook --
 * TclpServiceModeHook --
 *
 *	This function is invoked whenever the service mode changes.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_ServiceModeHook(
TclpServiceModeHook(
    int mode)			/* Either TCL_SERVICE_ALL, or
				 * TCL_SERVICE_NONE. */
{
    ThreadSpecificData *tsdPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (tclNotifierHooks.serviceModeHookProc) {
	tclNotifierHooks.serviceModeHookProc(mode);
	return;
    }

    tsdPtr = TCL_TSD_INIT(&dataKey);

    if (mode == TCL_SERVICE_ALL && !tsdPtr->runLoopTimer) {
	if (!tsdPtr->runLoop) {
	    Tcl_Panic("Tcl_ServiceModeHook: Notifier not initialized");
	}
	tsdPtr->runLoopTimer = CFRunLoopTimerCreate(NULL,
		CFAbsoluteTimeGetCurrent() + CF_TIMEINTERVAL_FOREVER,
		CF_TIMEINTERVAL_FOREVER, 0, 0, TimerWakeUp, NULL);
	if (tsdPtr->runLoopTimer) {
	    CFRunLoopAddTimer(tsdPtr->runLoop, tsdPtr->runLoopTimer,
		    kCFRunLoopCommonModes);
	    StartNotifierThread();
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_CreateFileHandler --
 * TclpCreateFileHandler --
 *
 *	This function registers a file handler with the select notifier.
 *	This function registers a file handler with the notifier.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Creates a new file handler structure.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_CreateFileHandler(
TclpCreateFileHandler(
    int fd,			/* Handle of stream to watch. */
    int mask,			/* OR'ed combination of TCL_READABLE,
				 * TCL_WRITABLE, and TCL_EXCEPTION: indicates
				 * conditions under which proc should be
				 * called. */
    Tcl_FileProc *proc,		/* Function to call for each selected
				 * event. */
    ClientData clientData)	/* Arbitrary data to pass to proc. */
    void *clientData)	/* Arbitrary data to pass to proc. */
{
    ThreadSpecificData *tsdPtr;
    FileHandler *filePtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    FileHandler *filePtr = LookUpFileHandler(tsdPtr, fd, NULL);

    if (tclNotifierHooks.createFileHandlerProc) {
	tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData);
	return;
    }

    tsdPtr = TCL_TSD_INIT(&dataKey);

    for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
	    filePtr = filePtr->nextPtr) {
	if (filePtr->fd == fd) {
	    break;
	}
    }
    if (filePtr == NULL) {
	filePtr = (FileHandler *)Tcl_Alloc(sizeof(FileHandler));
	filePtr = (FileHandler *) Tcl_Alloc(sizeof(FileHandler));
	filePtr->fd = fd;
	filePtr->readyMask = 0;
	filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
	tsdPtr->firstFileHandlerPtr = filePtr;
    }
    filePtr->proc = proc;
    filePtr->clientData = clientData;
1109
1110
1111
1112
1113
1114
1115
1116

1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130

1131
1132
1133
1134
1135
1136


1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153



1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164

1165
1166

1167
1168
1169
1170

1171
1172
1173
1174
1175
1176
1177
1154
1155
1156
1157
1158
1159
1160

1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174

1175
1176
1177
1178
1179


1180
1181








1182
1183
1184
1185
1186




1187
1188
1189




1190
1191
1192
1193
1194
1195

1196
1197

1198
1199
1200
1201

1202
1203
1204
1205
1206
1207
1208
1209







-
+













-
+




-
-
+
+
-
-
-
-
-
-
-
-





-
-
-
-
+
+
+
-
-
-
-






-
+

-
+



-
+







    }
    UNLOCK_NOTIFIER_TSD;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DeleteFileHandler --
 * TclpDeleteFileHandler --
 *
 *	Cancel a previously-arranged callback arrangement for a file.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	If a callback was previously registered on file, remove it.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_DeleteFileHandler(
TclpDeleteFileHandler(
    int fd)			/* Stream id for which to remove callback
				 * function. */
{
    FileHandler *filePtr, *prevPtr;
    int i, numFdBits;
    ThreadSpecificData *tsdPtr;
    int i, numFdBits = -1;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (tclNotifierHooks.deleteFileHandlerProc) {
	tclNotifierHooks.deleteFileHandlerProc(fd);
	return;
    }

    tsdPtr = TCL_TSD_INIT(&dataKey);
    numFdBits = -1;

    /*
     * Find the entry for the given file (and return if there isn't one).
     */

    for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
	    prevPtr = filePtr, filePtr = filePtr->nextPtr) {
	if (filePtr == NULL) {
	    return;
    filePtr = LookUpFileHandler(tsdPtr, fd, &prevPtr);
    if (filePtr == NULL) {
	return;
	}
	if (filePtr->fd == fd) {
	    break;
	}
    }

    /*
     * Find current max fd.
     */

    if (fd+1 == tsdPtr->numFdBits) {
    if (fd + 1 == tsdPtr->numFdBits) {
	numFdBits = 0;
	for (i = fd-1; i >= 0; i--) {
	for (i = fd - 1; i >= 0; i--) {
	    if (FD_ISSET(i, &tsdPtr->checkMasks.readable)
		    || FD_ISSET(i, &tsdPtr->checkMasks.writable)
		    || FD_ISSET(i, &tsdPtr->checkMasks.exceptional)) {
		numFdBits = i+1;
		numFdBits = i + 1;
		break;
	    }
	}
    }

    LOCK_NOTIFIER_TSD;
    if (numFdBits != -1) {
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255


1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1278
1279
1280
1281
1282
1283
1284



1285
1286



1287
1288
1289
1290
1291
1292
1293







-
-
-
+
+
-
-
-







     * Search through the file handlers to find the one whose handle matches
     * the event. We do this rather than keeping a pointer to the file handler
     * directly in the event, so that the handler can be deleted while the
     * event is queued without leaving a dangling pointer.
     */

    tsdPtr = TCL_TSD_INIT(&dataKey);
    for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
	    filePtr = filePtr->nextPtr) {
	if (filePtr->fd != fileEvPtr->fd) {
    filePtr = LookUpFileHandler(tsdPtr, fileEvPtr->fd, NULL);
    if (filePtr != NULL) {
	    continue;
	}

	/*
	 * The code is tricky for two reasons:
	 * 1. The file handler's desired events could have changed since the
	 *    time when the event was queued, so AND the ready mask with the
	 *    desired mask.
	 * 2. The file could have been closed and re-opened since the time
	 *    when the event was queued. This is why the ready mask is stored
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
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
1354
1355
1356
1357
1358
1359
1360
1361

1362
1363
1364
1365
1366
1367
1368
1369



1370
1371
1372
1373
1374
1375
1376







-







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+






-
+









-
+







-
-
-







	    }
	    if (mask & TCL_EXCEPTION) {
		FD_CLR(filePtr->fd, &tsdPtr->readyMasks.exceptional);
	    }
	    UNLOCK_NOTIFIER_TSD;
	    filePtr->proc(filePtr->clientData, mask);
	}
	break;
    }
    return 1;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpNotifierData --
 *
 *	This function returns a void pointer to be associated
 *	with a Tcl_AsyncHandler.
 *
 * Results:
 *	On MacOSX, returns always NULL.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void *
TclpNotifierData(void)
{
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_WaitForEvent --
 * TclpWaitForEvent --
 *
 *	This function is called by Tcl_DoOneEvent to wait for new events on
 *	the message queue. If the block time is 0, then Tcl_WaitForEvent just
 *	polls without blocking.
 *
 * Results:
 *	Returns 0 if a tcl event or timeout ocurred and 1 if a non-tcl
 *	Returns 0 if a tcl event or timeout occurred and 1 if a non-tcl
 *	CFRunLoop source was processed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_WaitForEvent(
TclpWaitForEvent(
    const Tcl_Time *timePtr)		/* Maximum block time, or NULL. */
{
    int result, polling, runLoopRunning;
    CFTimeInterval waitTime;
    SInt32 runLoopStatus;
    ThreadSpecificData *tsdPtr;

    if (tclNotifierHooks.waitForEventProc) {
	return tclNotifierHooks.waitForEventProc(timePtr);
    }
    result = -1;
    polling = 0;
    waitTime = CF_TIMEINTERVAL_FOREVER;
    tsdPtr = TCL_TSD_INIT(&dataKey);

    if (!tsdPtr->runLoop) {
	Tcl_Panic("Tcl_WaitForEvent: Notifier not initialized");
1339
1340
1341
1342
1343
1344
1345
1346

1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361


1362
1363
1364
1365
1366
1367
1368
1386
1387
1388
1389
1390
1391
1392

1393
1394
1395

1396
1397
1398
1399
1400
1401
1402
1403
1404
1405


1406
1407
1408
1409
1410
1411
1412
1413
1414







-
+


-










-
-
+
+







	/*
	 * TIP #233 (Virtualized Time). Is virtual time in effect? And do we
	 * actually have something to scale? If yes to both then we call the
	 * handler to do this scaling.
	 */

	if (vTime.sec != 0 || vTime.usec != 0) {
	    tclScaleTimeProcPtr(&vTime, tclTimeClientData);
	    TclScaleTime(&vTime);
	    waitTime = vTime.sec + 1.0e-6 * vTime.usec;
	} else {

	    /*
	     * The max block time was set to 0.
	     *
	     * If we set the waitTime to 0, then the call to CFRunLoopInMode
	     * may return without processing all of its sources.  The Apple
	     * documentation says that if the waitTime is 0 "only one pass is
	     * made through the run loop before returning; if multiple sources
	     * or timers are ready to fire immediately, only one (possibly two
	     * if one is a version 0 source) will be fired, regardless of the
	     * value of returnAfterSourceHandled."  This can cause some chanio
	     * tests to fail.  So we use a small positive waitTime unless there
	     * is another RunLoop running.
	     * tests to fail.  So we use a small positive waitTime unless
	     * there is another RunLoop running.
	     */

	    polling = 1;
	    waitTime = tsdPtr->runLoopRunning ? 0 : 0.0001;
	}
    }

1427
1428
1429
1430
1431
1432
1433
1434

1435
1436
1437
1438
1439
1440
1441
1473
1474
1475
1476
1477
1478
1479

1480
1481
1482
1483
1484
1485
1486
1487







-
+








static void
QueueFileEvents(
    void *info)
{
    SelectMasks readyMasks;
    FileHandler *filePtr;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)info;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) info;

    /*
     * Queue all detected file events.
     */

    LOCK_NOTIFIER_TSD;
    FD_COPY(&tsdPtr->readyMasks.readable, &readyMasks.readable);
1466
1467
1468
1469
1470
1471
1472
1473


1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489


1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506


1507
1508
1509
1510
1511
1512
1513
1512
1513
1514
1515
1516
1517
1518

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


1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552

1553
1554
1555
1556
1557
1558
1559
1560
1561







-
+
+














-
-
+
+
















-
+
+








	/*
	 * Don't bother to queue an event if the mask was previously non-zero
	 * since an event must still be on the queue.
	 */

	if (filePtr->readyMask == 0) {
	    FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)Tcl_Alloc(sizeof(FileHandlerEvent));
	    FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)
		    Tcl_Alloc(sizeof(FileHandlerEvent));

	    fileEvPtr->header.proc = FileHandlerEventProc;
	    fileEvPtr->fd = filePtr->fd;
	    Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
	}
	filePtr->readyMask = mask;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * UpdateWaitingListAndServiceEvents --
 *
 *	CFRunLoopObserver callback for updating waitingList and
 *	servicing Tcl events.
 *	CFRunLoopObserver callback for updating waitingList and servicing Tcl
 *	events.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
UpdateWaitingListAndServiceEvents(
    TCL_UNUSED(CFRunLoopObserverRef),
    CFRunLoopActivity activity,
    void *info)
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)info;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) info;

    if (tsdPtr->sleeping) {
	return;
    }
    switch (activity) {
    case kCFRunLoopEntry:
	tsdPtr->runLoopNestingLevel++;
	if (tsdPtr->numFdBits > 0 || tsdPtr->polling) {
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
1670
1671
1672
1673
1674
1675
1676


1677
1678
1679
1680
1681
1682
1683
1684
1685

1686
1687
1688
1689
1690
1691
1692
1693







-
-
+








-
+








    /*
     * TIP #233: Scale from virtual time to real-time.
     */

    vdelay.sec = ms / 1000;
    vdelay.usec = (ms % 1000) * 1000;
    tclScaleTimeProcPtr(&vdelay, tclTimeClientData);

    TclScaleTime(&vdelay);

    if (tsdPtr->runLoop) {
	CFTimeInterval waitTime;
	CFRunLoopTimerRef runLoopTimer = tsdPtr->runLoopTimer;
	CFAbsoluteTime nextTimerFire = 0, waitEnd, now;
	SInt32 runLoopStatus;

	waitTime = vdelay.sec + 1.0e-6 * vdelay.usec;
 	now = CFAbsoluteTimeGetCurrent();
	now = CFAbsoluteTimeGetCurrent();
	waitEnd = now + waitTime;

	if (runLoopTimer) {
	    nextTimerFire = CFRunLoopTimerGetNextFireDate(runLoopTimer);
	    if (nextTimerFire < waitEnd) {
		CFRunLoopTimerSetNextFireDate(runLoopTimer, now +
			CF_TIMEINTERVAL_FOREVER);
1662
1663
1664
1665
1666
1667
1668
1669

1670
1671
1672
1673
1674
1675
1676
1709
1710
1711
1712
1713
1714
1715

1716
1717
1718
1719
1720
1721
1722
1723







-
+







		break;
	    case kCFRunLoopRunTimedOut:
		waitTime = 0;
		break;
	    }
	} while (waitTime > 0);
	tsdPtr->sleeping = 0;
 	if (runLoopTimer) {
	if (runLoopTimer) {
	    CFRunLoopTimerSetNextFireDate(runLoopTimer, nextTimerFire);
	}
    } else {
	struct timespec waitTime;

	waitTime.tv_sec = vdelay.sec;
	waitTime.tv_nsec = vdelay.usec * 1000;
1725
1726
1727
1728
1729
1730
1731
1732

1733
1734
1735
1736
1737
1738
1739
1772
1773
1774
1775
1776
1777
1778

1779
1780
1781
1782
1783
1784
1785
1786







-
+








#ifndef _DARWIN_C_SOURCE
    /*
     * Sanity check fd.
     */

    if (fd >= FD_SETSIZE) {
	Tcl_Panic("TclUnixWaitForFile can't handle file id %d", fd);
	Tcl_Panic("TclUnixWaitForFile cannot handle file id %d", fd);
	/* must never get here, or select masks overrun will occur below */
    }
#endif

    /*
     * If there is a non-zero finite timeout, compute the time when we give
     * up.
1837
1838
1839
1840
1841
1842
1843























































1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856

1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867

1868
1869
1870
1871

1872
1873
1874
1875
1876
1877
1878
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

1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968

1969
1970
1971
1972

1973
1974
1975
1976
1977
1978
1979
1980







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












-
+










-
+



-
+







    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TclAsyncNotifier --
 *
 *	This procedure sets the async mark of an async handler to a
 *	given value, if it is called from the notifier thread.
 *
 * Result:
 *	True, when the handler will be marked, false otherwise.
 *
 * Side effetcs:
 *	The trigger pipe is written when called from the notifier
 *	thread.
 *
 *----------------------------------------------------------------------
 */

int
TclAsyncNotifier(
    int sigNumber,		/* Signal number. */
    TCL_UNUSED(Tcl_ThreadId),	/* Target thread. */
    TCL_UNUSED(void *),	/* Notifier data. */
    int *flagPtr,		/* Flag to mark. */
    int value)			/* Value of mark. */
{
#if TCL_THREADS
    /*
     * WARNING:
     * This code most likely runs in a signal handler. Thus,
     * only few async-signal-safe system calls are allowed,
     * e.g. pthread_self(), sem_post(), write().
     */

    if (pthread_equal(pthread_self(), (pthread_t) notifierThread)) {
	if (notifierThreadRunning) {
	    *flagPtr = value;
	    if (!asyncPending) {
		asyncPending = 1;
		write(triggerPipe, "S", 1);
	    }
	    return 1;
	}
	return 0;
    }

    /*
     * Re-send the signal to the notifier thread.
     */

    pthread_kill((pthread_t) notifierThread, sigNumber);
#endif
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * NotifierThreadProc --
 *
 *	This routine is the initial (and only) function executed by the
 *	special notifier thread. Its job is to wait for file descriptors to
 *	become readable or writable or to have an exception condition and then
 *	to notify other threads who are interested in this information by
 *	signalling a condition variable. Other threads can signal this
 *	notifier thread of a change in their interests by writing a single
 *	byte to a special pipe that the notifier thread is monitoring.
 *
 * Result:
 *	None. Once started, this routine never exits. It dies with the overall
 *	process.
 *	process or terminates its own thread (on notifier termination).
 *
 * Side effects:
 *	The trigger pipe used to signal the notifier thread is created when
 *	the notifier thread first starts.
 *
 *----------------------------------------------------------------------
 */

static TCL_NORETURN void
NotifierThreadProc(
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    ThreadSpecificData *tsdPtr;
    fd_set readableMask, writableMask, exceptionalMask;
    int i, numFdBits = 0, polling;
    int i, ret, numFdBits = 0, polling;
    struct timeval poll = {0., 0.}, *timePtr;
    char buf[2];

    /*
     * Look for file events and report them to interested threads.
     */

1917
1918
1919
1920
1921
1922
1923





1924
1925














1926
1927
1928
1929
1930
1931
1932
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030


2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051







+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	 */

	if (receivePipe >= numFdBits) {
	    numFdBits = receivePipe + 1;
	}
	FD_SET(receivePipe, &readableMask);

	/*
	 * Signals are unblocked only during select().
	 */

	pthread_sigmask(SIG_SETMASK, &notifierSigMask, NULL);
	if (select(numFdBits, &readableMask, &writableMask, &exceptionalMask,
		timePtr) == -1) {
	ret = select(numFdBits, &readableMask, &writableMask, &exceptionalMask,
		    timePtr);
	pthread_sigmask(SIG_BLOCK, &allSigMask, NULL);

	if (ret == -1) {
	    /*
	     * In case a signal was caught during select(),
	     * perform work on async handlers now.
	     */
	    if (errno == EINTR && asyncPending) {
		asyncPending = 0;
		TclAsyncMarkFromNotifier();
	    }

	    /*
	     * Try again immediately on an error.
	     */

	    continue;
	}

2006
2007
2008
2009
2010
2011
2012





2013
2014
2015
2016
2017
2018
2019
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143







+
+
+
+
+







		 * Someone closed the write end of the pipe or sent us a Quit
		 * message [Bug: 4139] and then closed the write end of the
		 * pipe so we need to shut down the notifier thread.
		 */

		break;
	    }

	    if (asyncPending) {
		asyncPending = 0;
		TclAsyncMarkFromNotifier();
	    }
	}
    }
    pthread_exit(0);
}

#ifdef HAVE_PTHREAD_ATFORK
/*
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095



2096
2097
2098
2099



2100
2101
2102
2103



2104



2105
2106
2107
2108
2109
2110
2111
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







-
-
-
+
+
+



-
+
+
+

-
-
-
+
+
+

+
+
+








static void
AtForkChild(void)
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    /*
     * If a child process unlocks an os_unfair_lock that was created in its parent
     * the child will exit with an illegal instruction error.  So we reinitialize
     * the lock in the child rather than attempt to unlock it.
     * If a child process unlocks an os_unfair_lock that was created in its
     * parent the child will exit with an illegal instruction error.  So we
     * reinitialize the lock in the child rather than attempt to unlock it.
     */

#if defined(USE_OS_UNFAIR_LOCK)
    tsdPtr->tsdLock = OS_UNFAIR_LOCK_INIT;
    notifierInitLock = OS_UNFAIR_LOCK_INIT;
    notifierLock     = OS_UNFAIR_LOCK_INIT;
    tsdPtr->tsdLock  = OS_UNFAIR_LOCK_INIT;
#else
       UNLOCK_NOTIFIER_TSD;
       UNLOCK_NOTIFIER;
       UNLOCK_NOTIFIER_INIT;
    UNLOCK_NOTIFIER_TSD;
    UNLOCK_NOTIFIER;
    UNLOCK_NOTIFIER_INIT;
#endif

    asyncPending = 0;

    if (tsdPtr->runLoop) {
	tsdPtr->runLoop = NULL;
	if (!noCFafterFork) {
	    CFRunLoopSourceInvalidate(tsdPtr->runLoopSource);
	    CFRelease(tsdPtr->runLoopSource);
	    if (tsdPtr->runLoopTimer) {
		CFRunLoopTimerInvalidate(tsdPtr->runLoopTimer);
2127
2128
2129
2130
2131
2132
2133






2134
2135
2136
2137
2138
2139
2140
2141

2142
2143
2144

2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275

2276
2277
2278

2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291







+
+
+
+
+
+







-
+


-
+












	 * executed in the main thread of the parent, otherwise
	 * Tcl_AlertNotifier may break in the child.
	 */

	if (!noCFafterFork) {
	    Tcl_InitNotifier();
	}

	/*
	 * Restart the notifier thread for signal handling.
	 */

	StartNotifierThread();
    }
}
#endif /* HAVE_PTHREAD_ATFORK */

#else /* HAVE_COREFOUNDATION */

void
TclMacOSXNotifierAddRunLoopMode(
Tcl_MacOSXNotifierAddRunLoopMode(
    const void *runLoopMode)
{
    Tcl_Panic("TclMacOSXNotifierAddRunLoopMode: "
    Tcl_Panic("Tcl_MacOSXNotifierAddRunLoopMode: "
	    "Tcl not built with CoreFoundation support");
}

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

Added tests-perf/chan.perf.tcl.






























































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#!/usr/bin/tclsh

# ------------------------------------------------------------------------
#
# chan.perf.tcl --
#
#  This file provides performance tests for comparison of tcl-speed
#  of channel subsystem.
#
# ------------------------------------------------------------------------
#
# Copyright (c) 2024 Serg G. Brester (aka sebres)
#
# See the file "license.terms" for information on usage and redistribution
# of this file.
#


if {![namespace exists ::tclTestPerf]} {
  source [file join [file dirname [info script]] test-performance.tcl]
}


namespace eval ::tclTestPerf-Chan {

namespace path {::tclTestPerf}

proc _get_test_chan {{bufSize 4096}} {
  lassign [chan pipe] ch wch;
  fconfigure $ch -translation lf -encoding utf-8 -buffersize $bufSize -buffering full
  fconfigure $wch -translation lf -encoding utf-8 -buffersize $bufSize -buffering full

  exec [info nameofexecutable] -- $bufSize >@$wch << {
    set bufSize [lindex $::argv end]
    fconfigure stdout -translation lf -encoding utf-8 -buffersize $bufSize -buffering full
    set buf [string repeat test 1000]; # 4K
    # write ~ 10*1M + 10*2M + 10*10M + 1*20M:
    set i 0; while {$i < int((10*1e6 + 10*2e6 + 10*10e6 + 1*20e6)/4e3)} {
      #puts -nonewline stdout $i\t
      puts stdout $buf
      #flush stdout; # don't flush to use full buffer
      incr i
    }
  } &
  close $wch
  return $ch
}

# regression tests for [bug-da16d15574] (fix for [db4f2843cd]):
proc test-read-regress {{reptime {50000 10}}} {
  _test_run -no-result $reptime {
    # with 4KB buffersize:
    setup   { set ch [::tclTestPerf-Chan::_get_test_chan 4096]; fconfigure $ch -buffersize }
    # 10 * 1M:
    {read $ch [expr {int(1e6)}]}
    # 10 * 2M:
    {read $ch [expr {int(2e6)}]}
    # 10 * 10M:
    {read $ch [expr {int(10e6)}]}
    #  1 * 20M:
    {read $ch; break}
    cleanup { close $ch }

    # with 1MB buffersize:
    setup   { set ch [::tclTestPerf-Chan::_get_test_chan 1048576]; fconfigure $ch -buffersize }
    # 10 * 1M:
    {read $ch [expr {int(1e6)}]}
    # 10 * 2M:
    {read $ch [expr {int(2e6)}]}
    # 10 * 10M:
    {read $ch [expr {int(10e6)}]}
    #  1 * 20M:
    {read $ch; break}
    cleanup { close $ch }
  }
}

proc test {{reptime 1000}} {
  test-read-regress

  puts \n**OK**
}

}; # end of ::tclTestPerf-Chan

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

# if calling direct:
if {[info exists ::argv0] && [file tail $::argv0] eq [file tail [info script]]} {
  array set in {-time 500}
  array set in $argv
  ::tclTestPerf-Chan::test $in(-time)
}

Changes to tests-perf/clock.perf.tcl.

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







#!/usr/bin/tclsh
# ------------------------------------------------------------------------
#
# test-performance.tcl --
#
#  This file provides common performance tests for comparison of tcl-speed
#  degradation by switching between branches.
#  (currently for clock ensemble only)
#
# ------------------------------------------------------------------------
#
# Copyright (c) 2014 Serg G. Brester (aka sebres)
# Copyright © 2014 Serg G. Brester (aka sebres)
#
# See the file "license.terms" for information on usage and redistribution
# of this file.
#

array set in {-time 500}
if {[info exists ::argv0] && [file tail $::argv0] eq [file tail [info script]]} {
28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
28
29
30
31
32
33
34

35
36
37
38
39
40
41
42







-
+







namespace eval ::tclTestPerf-TclClock {

namespace path {::tclTestPerf}

## set testing defaults:
set ::env(TCL_TZ) :CET

# warm-up interpeter compiler env, clock platform-related features:
# warm-up interpreter compiler env, clock platform-related features:

## warm-up test-related features (load clock.tcl, system zones, locales, etc.):
clock scan "" -gmt 1
clock scan ""
clock scan "" -timezone :CET
clock scan "" -format "" -locale en
clock scan "" -format "" -locale de
351
352
353
354
355
356
357
358


359

360

361

362



363
364
365
366
367
368
369
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








+
+

+
-
+

+
-
+
+
+







proc test-other {{reptime 1000}} {
  _test_run $reptime {
    # Bad zone
    {catch {clock scan "1 day" -timezone BAD_ZONE -locale en}}

    # Scan : julian day (overflow)
    {catch {clock scan 5373485 -format %J}}

    setup {set _(org-reptime) $_(reptime); lset _(reptime) 1 50}

    # Scan : test rotate of GC objects (format is dynamic, so tcl-obj removed with last reference)
    setup {set i -1}
    {set i 0; time { clock scan "[incr i] - 25.11.2015" -format "$i - %d.%m.%Y" -base 0 -gmt 1 } 50}
    {clock scan "[incr i] - 25.11.2015" -format "$i - %d.%m.%Y" -base 0 -gmt 1}
    # Scan : test reusability of GC objects (format is dynamic, so tcl-obj removed with last reference)
    setup {incr i; set j $i}
    {set i 50; time { clock scan "[incr i -1] - 25.11.2015" -format "$i - %d.%m.%Y" -base 0 -gmt 1 } 50}
    {clock scan "[incr j -1] - 25.11.2015" -format "$j - %d.%m.%Y" -base 0 -gmt 1}
    setup {set _(reptime) $_(org-reptime); set j $i}
    {clock scan "[incr j -1] - 25.11.2015" -format "$j - %d.%m.%Y" -base 0 -gmt 1; if {!$j} {set j $i}}
  }
}

proc test-ensemble-perf {{reptime 1000}} {
  _test_run $reptime {
    # Clock clicks (ensemble)
    {clock clicks}

Added tests-perf/comparePerf.tcl.




















































































































































































































































































































































































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
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
366
367
368
369
370
371
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#!/usr/bin/tclsh
# ------------------------------------------------------------------------
#
# comparePerf.tcl --
#
#  Script to compare performance data from multiple runs.
#
# ------------------------------------------------------------------------
#
# See the file "license.terms" for information on usage and redistribution
# of this file.
#
# Usage:
#   tclsh comparePerf.tcl [--regexp RE] [--ratio time|rate] [--combine] [--base BASELABEL] PERFFILE ...
#
# The test data from each input file is tabulated so as to compare the results
# of test runs. If a PERFFILE does not exist, it is retried by adding the
# .perf extension. If the --regexp is specified, only test results whose
# id matches RE are examined.
#
# If the --combine option is specified, results of test sets with the same
# label are combined and averaged in the output.
#
# If the --base option is specified, the BASELABEL is used as the label to use
# the base timing. Otherwise, the label of the first data file is used.
#
# If --ratio option is "time" the ratio of test timing vs base test timing
# is shown. If "rate" (default) the inverse is shown.
#
# If --no-header is specified, the header describing test configuration is
# not output.
#
# The format of input files is as follows:
#
# Each line must begin with one of the characters below followed by a space
# followed by a string whose semantics depend on the initial character.
# E - Full path to the Tcl executable that was used to generate the file
# V - The Tcl patchlevel of the implementation
# D - A description for the test run for human consumption
# L - A label used to identify run environment. The --combine option will
#     average all measuremets that have the same label. An input file without
#     a label is treated as having a unique label and not combined with any other.
# P - A test measurement (see below)
# R - The number of runs made for the each test
# # - A comment, may be an arbitrary string. Usually included in performance
#     data to describe the test. This is silently ignored
#
# Any lines not matching one of the above are ignored with a warning to stderr.
#
# A line beginning with the "P" marker is a test measurement. The first word
# following is a floating point number representing the test runtime.
# The remaining line (after trimming of whitespace) is the id of the test.
# Test generators are encouraged to make the id a well-defined machine-parseable
# as well human readable description of the test. The id must not appear more
# than once. An example test measurement line:
# P    2.32280 linsert in unshared L[10000] 1 elems 10000 times at 0 (var)
# Note here the iteration count is not present.
#

namespace eval perf::compare {
    # List of dictionaries, one per input file
    variable PerfData
}

proc perf::compare::warn {message} {
    puts stderr "Warning: $message"
}
proc perf::compare::print {text} {
    puts stdout $text
}
proc perf::compare::slurp {testrun_path} {
    variable PerfData

    set runtimes [dict create]

    set path [file normalize $testrun_path]
    set fd [open $path]
    array set header {}
    while {[gets $fd line] >= 0} {
	set line [regsub -all {\s+} [string trim $line] " "]
	switch -glob -- $line {
	    "#*" {
		# Skip comments
	    }
	    "R *" -
	    "L *" -
	    "D *" -
	    "V *" -
	    "T *" -
	    "E *" {
		set marker [lindex $line 0]
		if {[info exists header($marker)]} {
		    warn "Ignoring $marker record (duplicate): \"$line\""
		}
		set header($marker) [string range $line 2 end]
	    }
	    "P *" {
		if {[scan $line "P %f %n" runtime id_start] == 2} {
		    set id [string range $line $id_start end]
		    if {[dict exists $runtimes $id]} {
			warn "Ignoring duplicate test id \"$id\""
		    } else {
			dict set runtimes $id $runtime
		    }
		} else {
		    warn "Invalid test result line format: \"$line\""
		}
	    }
	    default {
		puts stderr "Warning: ignoring unrecognized line \"$line\""
	    }
	}
    }
    close $fd

    set result [dict create Input $path Runtimes $runtimes]
    foreach {c k} {
	L Label
	V Version
	E Executable
	D Description
    } {
	if {[info exists header($c)]} {
	    dict set result $k $header($c)
	}
    }

    return $result
}

proc perf::compare::burp {test_sets} {
    variable Options

    # Print the key for each test run
    set header "           "
    set separator "           "
    foreach test_set $test_sets {
	set test_set_key "\[[incr test_set_num]\]"
	if {! $Options(--no-header)} {
	    print "$test_set_key"
	    foreach k {Label Executable Version Input Description} {
		if {[dict exists $test_set $k]} {
		    print "$k: [dict get $test_set $k]"
		}
	    }
	}
	append header $test_set_key $separator
	set separator "                 "; # Expand because later columns have ratio
    }
    set header [string trimright $header]

    if {! $Options(--no-header)} {
	print ""
	if {$Options(--ratio) eq "rate"} {
	    set ratio_description "ratio of baseline to the measurement (higher is faster)."
	} else {
	    set ratio_description "ratio of measurement to the baseline (lower is faster)."
	}
	print "The first column \[1\] is the baseline measurement."
	print "Subsequent columns are pairs of the additional measurement and "
	print $ratio_description
	print ""
    }

    # Print the actual test run data

    print $header
    set test_sets [lassign $test_sets base_set]
    set fmt {%#10.5f}
    set fmt_ratio {%-6.2f}
    foreach {id base_runtime} [dict get $base_set Runtimes] {
	if {[info exists Options(--regexp)]} {
	    if {![regexp $Options(--regexp) $id]} {
		continue
	    }
	}
	if {$Options(--print-test-number)} {
	    set line "[format %-4s [incr counter].]"
	} else {
	    set line ""
	}
	append line [format $fmt $base_runtime]
	foreach test_set $test_sets {
	    if {[dict exists $test_set Runtimes $id]} {
		set runtime [dict get $test_set Runtimes $id]
		if {$Options(--ratio) eq "time"} {
		    if {$base_runtime != 0} {
			set ratio [format $fmt_ratio [expr {$runtime/$base_runtime}]]
		    } else {
			if {$runtime == 0} {
			    set ratio "NaN   "
			} else {
			    set ratio "Inf   "
			}
		    }
		} else {
		    if {$runtime != 0} {
			set ratio [format $fmt_ratio [expr {$base_runtime/$runtime}]]
		    } else {
			if {$base_runtime == 0} {
			    set ratio "NaN   "
			} else {
			    set ratio "Inf   "
			}
		    }
		}
		append line "|" [format $fmt $runtime] "|" $ratio
	    } else {
		append line [string repeat { } 11]
	    }
	}
	append line "|" $id
	print $line
    }
}

proc perf::compare::chew {test_sets} {
    variable Options

    # Combine test sets that have the same label, averaging the values
    set unlabeled_sets {}
    array set labeled_sets {}

    foreach test_set $test_sets {
	# If there is no label, treat as independent set
	if {![dict exists $test_set Label]} {
	    lappend unlabeled_sets $test_set
	} else {
	    lappend labeled_sets([dict get $test_set Label]) $test_set
	}
    }

    foreach label [array names labeled_sets] {
	set combined_set [lindex $labeled_sets($label) 0]
	set runtimes [dict get $combined_set Runtimes]
	foreach test_set [lrange $labeled_sets($label) 1 end] {
	    dict for {id timing} [dict get $test_set Runtimes] {
		dict lappend runtimes $id $timing
	    }
	}
	dict for {id timings} $runtimes {
	    set total [tcl::mathop::+ {*}$timings]
	    dict set runtimes $id [expr {$total/[llength $timings]}]
	}
	dict set combined_set Runtimes $runtimes
	set labeled_sets($label) $combined_set
    }

    # Choose the "base" test set
    if {![info exists Options(--base)]} {
	set first_set [lindex $test_sets 0]
	if {[dict exists $first_set Label]} {
	    # Use label of first as the base
	    set Options(--base) [dict get $first_set Label]
	}
    }

    if {[info exists Options(--base)] && $Options(--base) ne ""} {
	lappend combined_sets $labeled_sets($Options(--base));# Will error if no such
	unset labeled_sets($Options(--base))
    } else {
	lappend combined_sets [lindex $unlabeled_sets 0]
	set unlabeled_sets [lrange $unlabeled_sets 1 end]
    }
    foreach label [array names labeled_sets] {
	lappend combined_sets $labeled_sets($label)
    }
    lappend combined_sets {*}$unlabeled_sets

    return $combined_sets
}

proc perf::compare::setup {argv} {
    variable Options

    array set Options {
	--ratio rate
	--combine 0
	--print-test-number 0
	--no-header 0
    }
    while {[llength $argv]} {
	set argv [lassign $argv arg]
	switch -glob -- $arg {
	    -r -
	    --regexp {
		if {[llength $argv] == 0} {
		    error "Missing value for option $arg"
		}
		set argv [lassign $argv val]
		set Options(--regexp) $val
	    }
	    --ratio {
		if {[llength $argv] == 0} {
		    error "Missing value for option $arg"
		}
		set argv [lassign $argv val]
		if {$val ni {time rate}} {
		    error "Value for option $arg must be either \"time\" or \"rate\""
		}
		set Options(--ratio) $val
	    }
	    --print-test-number -
	    --combine -
	    --no-header {
		set Options($arg) 1
	    }
	    --base {
		if {[llength $argv] == 0} {
		    error "Missing value for option $arg"
		}
		set argv [lassign $argv val]
		set Options($arg) $val
	    }
	    -- {
		# Remaining will be passed back to the caller
		break
	    }
	    --* {
		error "Unknown option $arg"
	    }
	    -* {
		error "Unknown option -[lindex $arg 0]"
	    }
	    default {
		# Remaining will be passed back to the caller
		set argv [linsert $argv 0 $arg]
		break;
	    }
	}
    }

    set paths {}
    foreach path $argv {
	set path [file join $path]; # Convert from native else glob fails
	if {[file isfile $path]} {
	    lappend paths $path
	    continue
	}
	if {[file isfile $path.perf]} {
	    lappend paths $path.perf
	    continue
	}
	lappend paths {*}[glob -nocomplain $path]
    }
    return $paths
}
proc perf::compare::main {} {
    variable Options

    set paths [setup $::argv]
    if {[llength $paths] == 0} {
	error "No test data files specified."
    }
    set test_data [list ]
    set seen [dict create]
    foreach path $paths {
	if {![dict exists $seen $path]} {
	    lappend test_data [slurp $path]
	    dict set seen $path ""
	}
    }

    if {$Options(--combine)} {
	set test_data [chew $test_data]
    }

    burp $test_data
}

perf::compare::main

Added tests-perf/file.perf.tcl.














































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#!/usr/bin/tclsh

# ------------------------------------------------------------------------
#
# file.perf.tcl --
#
#  This file provides performance tests for comparison of tcl-speed
#  of file commands and subsystem.
#
# ------------------------------------------------------------------------
#
# Copyright (c) 2024 Serg G. Brester (aka sebres)
#
# See the file "license.terms" for information on usage and redistribution
# of this file.
#


if {![namespace exists ::tclTestPerf]} {
  source -encoding utf-8 [file join [file dirname [info script]] test-performance.tcl]
}


namespace eval ::tclTestPerf-File {

namespace path {::tclTestPerf}

proc _get_new_file_path_obj [list [list p [info script]]] {
  # always generate new string object here (ensure it is not a "cached" object of type path):
  string trimright "$p "; # costs of object "creation" smaller than 1 microsecond
}

# regression tests for bug-02d5d65d70adab97 (fix for [02d5d65d70adab97]):
proc test-file-access-regress {{reptime 1000}} {
  _test_run -no-result $reptime {
    setup   { set fn [::tclTestPerf-File::_get_new_file_path_obj] }
    # file exists on "cached" file path:
    { file exists $fn }
    # file exists on not "cached" (fresh generated) file path:
    { set fn [::tclTestPerf-File::_get_new_file_path_obj]; file exists $fn }

    setup   { set fn [::tclTestPerf-File::_get_new_file_path_obj] }
    # file attributes on "cached" file path:
    { file attributes $fn -readonly }
    # file attributes on not "cached" (fresh generated) file path:
    { set fn [::tclTestPerf-File::_get_new_file_path_obj]; file attributes $fn -readonly }

    setup   { set fn [::tclTestPerf-File::_get_new_file_path_obj] }
    # file stat on "cached" file path:
    { file stat $fn st }
    # file stat on not "cached" (fresh generated) file path:
    { set fn [::tclTestPerf-File::_get_new_file_path_obj]; file stat $fn st }

    setup   { set fn [::tclTestPerf-File::_get_new_file_path_obj] }
    # touch on "cached" file path:
    { close [open $fn rb] }
    # touch on not "cached" (fresh generated) file path:
    { set fn [::tclTestPerf-File::_get_new_file_path_obj]; close [open $fn rb] }
  }
}

proc test {{reptime 1000}} {
  test-file-access-regress $reptime

  puts \n**OK**
}

}; # end of ::tclTestPerf-File

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

# if calling direct:
if {[info exists ::argv0] && [file tail $::argv0] eq [file tail [info script]]} {
  array set in {-time 500}
  array set in $argv
  ::tclTestPerf-File::test $in(-time)
}

Added tests-perf/list.perf.tcl.

























































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#!/usr/bin/tclsh

# ------------------------------------------------------------------------
#
# list.perf.tcl --
#
#  This file provides performance tests for comparison of tcl-speed
#  of list facilities.
#
# ------------------------------------------------------------------------
#
# Copyright (c) 2024 Serg G. Brester (aka sebres)
#
# See the file "license.terms" for information on usage and redistribution
# of this file.
#


if {![namespace exists ::tclTestPerf]} {
  source [file join [file dirname [info script]] test-performance.tcl]
}


namespace eval ::tclTestPerf-List {

namespace path {::tclTestPerf}

proc test-lsearch-regress {{reptime 1000}} {
  _test_run -no-result $reptime {
    # found-first immediately, list with 5000 strings with ca. 50 chars elements:
    setup   { set str [join [lrepeat 13 "XXX"] /]; set l [lrepeat 5000 $str]; llength $l }

    { lsearch $l $str }
    { lsearch -glob $l $str }
    { lsearch -exact $l $str }
    { lsearch -dictionary $l $str }
    { lsearch -exact -dictionary $l $str }

    { lsearch -nocase $l $str }
    { lsearch -nocase -glob $l $str }
    { lsearch -nocase -exact $l $str }
    { lsearch -nocase -dictionary $l $str }
    { lsearch -nocase -exact -dictionary $l $str }
  }
}

proc test-lsearch-nf-regress {{reptime 1000}} {
  _test_run -no-result $reptime {
    # not-found, list with 5000 strings with ca. 50 chars elements:
    setup   { set str [join [lrepeat 13 "XXX"] /]; set sNF $str/NF; set l [lrepeat 5000 $str]; llength $l }

    { lsearch $l $sNF }
    { lsearch -glob $l $sNF }
    { lsearch -exact $l $sNF }
    { lsearch -dictionary $l $sNF }
    { lsearch -exact -dictionary $l $sNF }
    { lsearch -sorted $l $sNF }
    { lsearch -bisect $l $sNF }

    { lsearch -nocase $l $sNF }
    { lsearch -nocase -glob $l $sNF }
    { lsearch -nocase -exact $l $sNF }
    { lsearch -nocase -dictionary $l $sNF }
    { lsearch -nocase -exact -dictionary $l $sNF }
    { lsearch -nocase -sorted $l $sNF }
    { lsearch -nocase -bisect $l $sNF }
  }
}

proc test-lsearch-nf-non-opti-fast {{reptime 1000}} {
  _test_run -no-result $reptime {
    # not-found, list with 5000 strings with ca. 50 chars elements:
    setup   { set str [join [lrepeat 13 "XXX"] /]; set sNF "$str/*"; set l [lrepeat 5000 $str]; llength $l }

    { lsearch -sorted -dictionary $l $sNF }
    { lsearch -bisect -dictionary $l $sNF }

    { lsearch -sorted -nocase -dictionary $l $sNF }
    { lsearch -bisect -nocase -dictionary $l $sNF }

  }
}

proc test-lsearch-nf-non-opti-slow {{reptime 1000}} {
  _test_run -no-result $reptime {
    # not-found, list with 5000 strings with ca. 50 chars elements:
    setup   { set str [join [lrepeat 13 "XXX"] /]; set sNF "$str/*"; set l [lrepeat 5000 $str]; llength $l }

    { lsearch $l $sNF }
    { lsearch -glob $l $sNF }

    { lsearch -nocase $l $sNF }
    { lsearch -nocase -glob $l $sNF }

  }
}

proc test-lseq {{reptime 1000}} {
  _test_run $reptime {
    setup   { set i 0 }
    { lseq 10 }
    { lseq 0 count 10 }
    { lseq 0 count 10 by 1 }
    { lseq 0 9 }
    { lseq 0 to 9 }
    { lseq 0 9 1 }
    { lseq 0 to 9 by 1 }
  }
}

proc test-lseq-expr {{reptime 1000}} {
  _test_run $reptime {
    setup   { set i 0 }
    { lseq [expr {$i+10}] }
    { lseq {$i+10} }
    { lseq [expr {$i+0}] count [expr {$i+10}] }
    { lseq {$i+0} count {$i+10} }
    { lseq [expr {$i+0}] count [expr {$i+10}] by [expr {$i+1}] }
    { lseq {$i+0} count {$i+10} by {$i+1} }
    { lseq [expr {$i+0}] [expr {$i+9}] }
    { lseq {$i+0} {$i+9} }
    { lseq [expr {$i+0}] to [expr {$i+9}] }
    { lseq {$i+0} to {$i+9} }
    { lseq [expr {$i+0}] [expr {$i+9}] [expr {$i+1}] }
    { lseq {$i+0} {$i+9} {$i+1} }
    { lseq [expr {$i+0}] to [expr {$i+9}] by [expr {$i+1}] }
    { lseq {$i+0} to {$i+9} by {$i+1} }
  }
}

proc test {{reptime 1000}} {
  test-lsearch-regress $reptime
  test-lsearch-nf-regress $reptime
  test-lsearch-nf-non-opti-fast $reptime
  test-lsearch-nf-non-opti-slow $reptime

  test-lseq [expr {$reptime/2}]
  test-lseq-expr [expr {$reptime/2}]

  puts \n**OK**
}

}; # end of ::tclTestPerf-List

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

# if calling direct:
if {[info exists ::argv0] && [file tail $::argv0] eq [file tail [info script]]} {
  array set in {-time 500}
  array set in $argv
  ::tclTestPerf-List::test $in(-time)
}

Added tests-perf/listPerf.tcl.
















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#!/usr/bin/tclsh
# ------------------------------------------------------------------------
#
# listPerf.tcl --
#
#  This file provides performance tests for list operations. Run
#     tclsh listPerf.tcl help
#  for options.
# ------------------------------------------------------------------------
#
# See the file "license.terms" for information on usage and redistribution
# of this file.
#
# Note: this file does not use the test-performance.tcl framework as we want
# more direct control over timerate options.

catch {package require twapi}

namespace eval perf::list {
    variable perfScript [file normalize [info script]]

    # Test for each of these lengths
    variable Lengths {10 100 1000 10000}

    variable RunTimes
    set RunTimes(command) 0.0
    set RunTimes(total) 0.0

    variable Options
    array set Options {
	--print-comments   0
	--print-iterations 0
    }

    # Procs used for calibrating overhead
    proc proc2args {a b} {}
    proc proc3args {a b c} {}

    proc print {s} {
	puts $s
    }
    proc print_usage {} {
	puts stderr "Usage: [file tail [info nameofexecutable]] $::argv0 \[options\] \[command ...\]"
	puts stderr "\t--description DESC\tHuman readable description of test run"
	puts stderr "\t--label LABEL\tA label used to identify test environment"
	puts stderr "\t--print-comments\tPrint comment for each test"
	puts stderr "\t--print-iterations\tPrint number of iterations run for each test"
    }

    proc setup {argv} {
	variable Options
	variable Lengths

	while {[llength $argv]} {
	    set argv [lassign $argv arg]
	    switch -glob -- $arg {
		--print-comments -
		--print-iterations {
		    set Options($arg) 1
		}
		--label -
		--description {
		    if {[llength $argv] == 0} {
			error "Missing value for option $arg"
		    }
		    set argv [lassign $argv val]
		    set Options($arg) $val
		}
		--lengths {
		    if {[llength $argv] == 0} {
			error "Missing value for option $arg"
		    }
		    set argv [lassign $argv val]
		    set Lengths $val
		}
		-- {
		    # Remaining will be passed back to the caller
		    break
		}
		--* {
		    puts stderr "Unknown option $arg"
		    print_usage
		    exit 1
		}
		default {
		    # Remaining will be passed back to the caller
		    set argv [linsert $argv 0 $arg]
		    break;
		}
	    }
	}

	return $argv
    }
    proc format_timings {us iters} {
	variable Options
	if {!$Options(--print-iterations)} {
	    return "[format {%#10.4f} $us]"
	}
	return "[format {%#10.4f} $us] [format {%8d} $iters]"
    }
    proc measure {id script args} {
	variable NullOverhead
	variable RunTimes
	variable Options

	set opts(-overhead) ""
	set opts(-runs) 5
	while {[llength $args]} {
	    set args [lassign $args opt]
	    if {[llength $args] == 0} {
		error "No argument supplied for $opt option. Test: $id"
	    }
	    set args [lassign $args val]
	    switch $opt {
		-setup -
		-cleanup -
		-overhead -
		-time -
		-runs -
		-reps {
		    set opts($opt) $val
		}
		default {
		    error "Unknown option $opt. Test: $id"
		}
	    }
	}

	set timerate_args {}
	if {[info exists opts(-time)]} {
	    lappend timerate_args $opts(-time)
	}
	if {[info exists opts(-reps)]} {
	    if {[info exists opts(-time)]} {
		set timerate_args [list $opts(-time) $opts(-reps)]
	    } else {
		# Force the default for first time option
		set timerate_args [list 1000 $opts(-reps)]
	    }
	} elseif {[info exists opts(-time)]} {
	    set timerate_args [list $opts(-time)]
	}
	if {[info exists opts(-setup)]} {
	    uplevel 1 $opts(-setup)
	}
	# Cache the empty overhead to prevent unnecessary delays. Note if you modify
	# to cache other scripts, the cache key must be AFTER substituting the
	# overhead script in the caller's context.
	if {$opts(-overhead) eq ""} {
	    if {![info exists NullOverhead]} {
		set NullOverhead [lindex [timerate {}] 0]
	    }
	    set overhead_us $NullOverhead
	} else {
	    # The overhead measurements might use setup so we need to setup
	    # first and then cleanup in preparation for setting up again for
	    # the script to be measured
	    if {[info exists opts(-setup)]} {
		uplevel 1 $opts(-setup)
	    }
	    set overhead_us [lindex [uplevel 1 [list timerate $opts(-overhead)]] 0]
	    if {[info exists opts(-cleanup)]} {
		uplevel 1 $opts(-cleanup)
	    }
	}
	set timings {}
	for {set i 0} {$i < $opts(-runs)} {incr i} {
	    if {[info exists opts(-setup)]} {
		uplevel 1 $opts(-setup)
	    }
	    lappend timings [uplevel 1 [list timerate -overhead $overhead_us $script {*}$timerate_args]]
	    if {[info exists opts(-cleanup)]} {
		uplevel 1 $opts(-cleanup)
	    }
	}
	set timings [lsort -real -index 0 $timings]
	if {$opts(-runs) > 15} {
	    set ignore [expr {$opts(-runs)/8}]
	} elseif {$opts(-runs) >= 5} {
	    set ignore 2
	} else {
	    set ignore 0
	}
	# Ignore highest and lowest
	set timings [lrange $timings 0 end-$ignore]
	# Average it out
	set us 0
	set iters 0
	foreach timing $timings {
	    set us [expr {$us + [lindex $timing 0]}]
	    set iters [expr {$iters + [lindex $timing 2]}]
	}
	set us [expr {$us/[llength $timings]}]
	set iters [expr {$iters/[llength $timings]}]

	set RunTimes(command) [expr {$RunTimes(command) + $us}]
	print "P [format_timings $us $iters] $id"
    }
    proc comment {args} {
	variable Options
	if {$Options(--print-comments)} {
	    print "# [join $args { }]"
	}
    }
    proc spanned_list {len} {
	# Note - for small len, this will not create a spanned list
	set delta [expr {$len/8}]
	return [lrange [lrepeat [expr {$len+(2*$delta)}] a] $delta [expr {$delta+$len-1}]]
    }
    proc print_separator {command} {
	comment [string repeat = 80]
	comment Command: $command
    }

    oo::class create ListPerf {
	constructor {args} {
	    my variable Opts
	    # Note default Opts can be overridden in construct as well as in measure
	    set Opts [dict merge {
		-setup {
		    set L [lrepeat $len a]
		    set Lspan [perf::list::spanned_list $len]
		} -cleanup {
		    unset -nocomplain L
		    unset -nocomplain Lspan
		    unset -nocomplain L2
		}
	    } $args]
	}
	method measure {comment script locals args} {
	    my variable Opts
	    dict with locals {}
	    ::perf::list::measure $comment $script {*}[dict merge $Opts $args]
	}
	method option {opt val} {
	    my variable Opts
	    dict set Opts $opt $val
	}
	method option_unset {opt} {
	    my variable Opts
	    unset -nocomplain Opts($opt)
	}
    }

    proc linsert_describe {share_mode len at num iters} {
	return "linsert L\[$len\] $share_mode $num elems $iters times at $at"
    }
    proc linsert_perf {} {
	variable Lengths

	print_separator linsert

	ListPerf create perf -overhead {set L {}} -time 1000

	# Note: Const indices take different path through bytecode than variable
	# indices hence separate cases below


	# Var case
	foreach share_mode {shared unshared} {
	    set idx 0
	    if {$share_mode eq "shared"} {
		comment == Insert into empty lists
		comment Insert one element into empty list
		measure [linsert_describe shared 0 "0 (var)" 1 1] {linsert $L $idx ""} -setup {set idx 0; set L {}}
	    } else {
		comment == Insert into empty lists
		comment Insert one element into empty list
		measure [linsert_describe unshared 0 "0 (var)" 1 1] {linsert {} $idx ""} -setup {set idx 0}
	    }
	    foreach idx_str [list 0 1 mid end-1 end] {
		foreach len $Lengths {
		    if {$idx_str eq "mid"} {
			set idx [expr {$len/2}]
		    } else {
			set idx $idx_str
		    }
		    # perf option -reps $reps
		    set reps 1000
		    if {$share_mode eq "shared"} {
			comment Insert once to shared list with variable index
			perf measure [linsert_describe shared $len "$idx (var)" 1 1] \
			    {linsert $L $idx x} [list len $len idx $idx] -overhead {} -reps 100000

			comment Insert multiple times to shared list with variable index
			perf measure [linsert_describe shared $len "$idx (var)" 1 $reps] {
			    set L [linsert $L $idx X]
			} [list len $len idx $idx] -reps $reps

			comment Insert multiple items multiple times to shared list with variable index
			perf measure [linsert_describe shared $len "$idx (var)" 5 $reps] {
			    set L [linsert $L $idx X X X X X]
			} [list len $len idx $idx] -reps $reps
		    } else {
			# NOTE : the Insert once case is left out for unshared lists
			# because it requires re-init on every iteration resulting
			# in a lot of measurement noise
			comment Insert multiple times to unshared list with variable index
			perf measure [linsert_describe unshared $len "$idx (var)" 1 $reps] {
			    set L [linsert $L[set L {}] $idx X]
			} [list len $len idx $idx] -reps $reps
			comment Insert multiple items multiple times to unshared list with variable index
			perf measure [linsert_describe unshared $len "$idx (var)" 5 $reps] {
			    set L [linsert $L[set L {}] $idx X X X X X]
			} [list len $len idx $idx] -reps $reps
		    }
		}
	    }
	}

	# Const index
	foreach share_mode {shared unshared} {
	    if {$share_mode eq "shared"} {
		comment == Insert into empty lists
		comment Insert one element into empty list
		measure [linsert_describe shared 0 "0 (const)" 1 1] {linsert $L 0 ""} -setup {set L {}}
	    } else {
		comment == Insert into empty lists
		comment Insert one element into empty list
		measure [linsert_describe unshared 0 "0 (const)" 1 1] {linsert {} 0 ""}
	    }
	    foreach idx_str [list 0 1 mid end end-1] {
		foreach len $Lengths {
		    # Note end, end-1 explicitly calculated as otherwise they
		    # are not treated as const
		    if {$idx_str eq "mid"} {
			set idx [expr {$len/2}]
		    } elseif {$idx_str eq "end"} {
			set idx [expr {$len-1}]
		    } elseif {$idx_str eq "end-1"} {
			set idx [expr {$len-2}]
		    } else {
			set idx $idx_str
		    }
		    #perf option -reps $reps
		    set reps 100
		    if {$share_mode eq "shared"} {
			comment Insert once to shared list with const index
			perf measure [linsert_describe shared $len "$idx (const)" 1 1] \
			    "linsert \$L $idx x" [list len $len] -overhead {} -reps 10000

			comment Insert multiple times to shared list with const index
			perf measure [linsert_describe shared $len "$idx (const)" 1 $reps] \
			    "set L \[linsert \$L $idx X\]" [list len $len] -reps $reps

			comment Insert multiple items multiple times to shared list with const index
			perf measure [linsert_describe shared $len "$idx (const)" 5 $reps] \
			    "set L \[linsert \$L $idx X X X X X\]" [list len $len] -reps $reps
		    } else {
			comment Insert multiple times to unshared list with const index
			perf measure [linsert_describe unshared $len "$idx (const)" 1 $reps] \
			    "set L \[linsert \$L\[set L {}\] $idx X]" [list len $len] -reps $reps

			comment Insert multiple items multiple times to unshared list with const index
			perf measure [linsert_describe unshared $len "$idx (const)" 5 $reps] \
			    "set L \[linsert \$L\[set L {}\] $idx X X X X X]" [list len $len] -reps $reps
		    }
		}
	    }
	}

	# Note: no span tests because the inserts above will themselves create
	# spanned lists

	perf destroy
    }

    proc list_describe {len text} {
	return "list L\[$len\] $text"
    }
    proc list_perf {} {
	variable Lengths

	print_separator list

	ListPerf create perf
	foreach len $Lengths {
	    set s [join [lrepeat $len x]]
	    comment Create a list from a string
	    perf measure [list_describe $len "from a string"] {list $s} [list s $s len $len]
	}
	foreach len $Lengths {
	    comment Create a list from expansion - single list (special optimal case)
	    perf measure [list_describe $len "from a {*}list"] {list {*}$L} [list len $len]
	    comment Create a list from two lists - real test of expansion speed
	    perf measure [list_describe $len "from a {*}list {*}list"] {list {*}$L {*}$L} [list len [expr {$len/2}]]
	}

	perf destroy
    }

    proc lappend_describe {share_mode len num iters} {
	return "lappend L\[$len\] $share_mode $num elems $iters times"
    }
    proc lappend_perf {} {
	variable Lengths

	print_separator lappend

	ListPerf create perf -setup {set L [lrepeat [expr {$len/4}] x]}

	# Shared
	foreach len $Lengths {
	    comment Append to a shared list variable multiple times
	    perf measure [lappend_describe shared [expr {$len/2}] 1 $len] {
		set L2 $L; # Make shared
		lappend L x
	    } [list len $len] -reps $len -overhead {set L2 $L}
	}

	# Unshared
	foreach len $Lengths {
	    comment Append to a unshared list variable multiple times
	    perf measure [lappend_describe unshared [expr {$len/2}] 1 $len] {
		lappend L x
	    } [list len $len] -reps $len
	}

	# Span
	foreach len $Lengths {
	    comment Append to a unshared-span list variable multiple times
	    perf measure [lappend_describe unshared-span [expr {$len/2}] 1 $len] {
		lappend Lspan x
	    } [list len $len] -reps $len
	}

	perf destroy
    }

    proc lpop_describe {share_mode len at reps} {
	return "lpop L\[$len\] $share_mode at $at $reps times"
    }
    proc lpop_perf {} {
	variable Lengths

	print_separator lpop

	ListPerf create perf

	# Shared
	perf option -overhead {set L2 $L}
	foreach len $Lengths {
	    set reps [expr {($len >= 1000 ? ($len/2) : $len) - 2}]
	    foreach idx {0 1 end-1 end}  {
		comment Pop element at position $idx from a shared list variable
		perf measure [lpop_describe shared $len $idx $reps] {
		    set L2 $L
		    lpop L $idx
		} [list len $len idx $idx] -reps $reps
	    }
	}

	# Unshared
	perf option -overhead {}
	foreach len $Lengths {
	    set reps [expr {($len >= 1000 ? ($len/2) : $len) - 2}]
	    foreach idx {0 1 end-1 end}  {
		comment Pop element at position $idx from an unshared list variable
		perf measure [lpop_describe unshared $len $idx $reps] {
		    lpop L $idx
		} [list len $len idx $idx] -reps $reps
	    }
	}

	perf destroy

	# Nested
	ListPerf create perf -setup {
	    set L [lrepeat $len [list a b]]
	}

	# Shared, nested index
	perf option -overhead {set L2 $L; set L L2}
	foreach len $Lengths {
	    set reps [expr {($len >= 1000 ? ($len/2) : $len) - 2}]
	    foreach idx {0 1 end-1 end}  {
		perf measure [lpop_describe shared $len "{$idx 0}" $reps] {
		    set L2 $L
		    lpop L $idx 0
		    set L $L2
		} [list len $len idx $idx] -reps $reps
	    }
	}

	# TODO - Nested Unshared
	# Not sure how to measure performance. When unshared there is no copy
	# so deleting a nested index repeatedly is not feasible

	perf destroy
    }

    proc lassign_describe {share_mode len num reps} {
	return "lassign L\[$len\] $share_mode $num elems $reps times"
    }
    proc lassign_perf {} {
	variable Lengths

	print_separator lassign

	ListPerf create perf

	foreach share_mode {shared unshared} {
	    foreach len $Lengths {
		if {$share_mode eq "shared"} {
		    set reps 1000
		    comment Reflexive lassign - shared
		    perf measure [lassign_describe shared $len 1 $reps] {
			set L2 $L
			set L2 [lassign $L2 v]
		    } [list len $len] -overhead {set L2 $L} -reps $reps

		    comment Reflexive lassign - shared, multiple
		    perf measure [lassign_describe shared $len 5 $reps] {
			set L2 $L
			set L2 [lassign $L2 a b c d e]
		    } [list len $len] -overhead {set L2 $L} -reps $reps
		} else {
		    set reps [expr {($len >= 1000 ? ($len/2) : $len) - 2}]
		    comment Reflexive lassign - unshared
		    perf measure [lassign_describe unshared $len 1 $reps] {
			set L [lassign $L v]
		    } [list len $len] -reps $reps
		}
	    }
	}
	perf destroy
    }

    proc lrepeat_describe {len num} {
	return "lrepeat L\[$len\] $num elems at a time"
    }
    proc lrepeat_perf {} {
	variable Lengths

	print_separator lrepeat

	ListPerf create perf -reps 100000
	foreach len $Lengths {
	    comment Generate a list from a single repeated element
	    perf measure [lrepeat_describe $len 1] {
		lrepeat $len a
	    } [list len $len]

	    comment Generate a list from multiple repeated elements
	    perf measure [lrepeat_describe $len 5] {
		lrepeat $len a b c d e
	    } [list len $len]
	}

	perf destroy
    }

    proc lreverse_describe {share_mode len} {
	return "lreverse L\[$len\] $share_mode"
    }
    proc lreverse_perf {} {
	variable Lengths

	print_separator lreverse

	ListPerf create perf -reps 10000

	foreach share_mode {shared unshared} {
	    foreach len $Lengths {
		if {$share_mode eq "shared"} {
		    comment Reverse a shared list
		    perf measure [lreverse_describe shared $len] {
			lreverse $L
		    } [list len $len]

		    if {$len > 100} {
			comment Reverse a shared-span list
			perf measure [lreverse_describe shared-span $len] {
			    lreverse $Lspan
			} [list len $len]
		    }
		} else {
		    comment Reverse a unshared list
		    perf measure [lreverse_describe unshared $len] {
			set L [lreverse $L[set L {}]]
		    } [list len $len] -overhead {set L $L; set L {}}

		    if {$len >= 100} {
			comment Reverse a unshared-span list
			perf measure [lreverse_describe unshared-span $len] {
			    set Lspan [lreverse $Lspan[set Lspan {}]]
			} [list len $len] -overhead {set Lspan $Lspan; set Lspan {}}
		    }
		}
	    }
	}

	perf destroy
    }

    proc llength_describe {share_mode len} {
	return "llength L\[$len\] $share_mode"
    }
    proc llength_perf {} {
	variable Lengths

	print_separator llength

	ListPerf create perf -reps 100000

	foreach len $Lengths {
	    comment Length of a list
	    perf measure [llength_describe shared $len] {
		llength $L
	    } [list len $len]

	    if {$len >= 100} {
		comment Length of a span list
		perf measure [llength_describe shared-span $len] {
		    llength $Lspan
		} [list len $len]
	    }
	}

	perf destroy
    }

    proc lindex_describe {share_mode len at} {
	return "lindex L\[$len\] $share_mode at $at"
    }
    proc lindex_perf {} {
	variable Lengths

	print_separator lindex

	ListPerf create perf -reps 100000

	foreach len $Lengths {
	    comment Index into a list
	    set idx [expr {$len/2}]
	    perf measure [lindex_describe shared $len $idx] {
		lindex $L $idx
	    } [list len $len idx $idx]

	    if {$len >= 100} {
		comment Index into a span list
		perf measure [lindex_describe shared-span $len $idx] {
		    lindex $Lspan $idx
		} [list len $len idx $idx]
	    }
	}

	perf destroy
    }

    proc lrange_describe {share_mode len range} {
	return "lrange L\[$len\] $share_mode range $range"
    }

    proc lrange_perf {} {
	variable Lengths

	print_separator lrange

	ListPerf create perf -time 1000 -reps 100000

	foreach share_mode {shared unshared} {
	    foreach len $Lengths {
		set eighth [expr {$len/8}]
		set ranges [list \
				[list 0 0]  [list 0 end-1] \
				[list $eighth [expr {3*$eighth}]] \
				[list $eighth [expr {7*$eighth}]] \
				[list 1 end] [list end-1 end] \
			       ]
		foreach range $ranges {
		    comment Range $range in $share_mode list of length $len
		    if {$share_mode eq "shared"} {
			perf measure [lrange_describe shared $len $range] \
			    "lrange \$L $range" [list len $len range $range]
		    } else {
			perf measure [lrange_describe unshared $len $range] \
			    "lrange \[lrepeat \$len\ a] $range" \
			    [list len $len range $range] -overhead {lrepeat $len a}
		    }
		}

		if {$len >= 100} {
		    foreach range $ranges {
			comment Range $range in ${share_mode}-span list of length $len
			if {$share_mode eq "shared"} {
			    perf measure [lrange_describe shared-span $len $range] \
				"lrange \$Lspan {*}$range" [list len $len range $range]
			} else {
			    perf measure [lrange_describe unshared-span $len $range] \
				"lrange \[perf::list::spanned_list \$len\] $range" \
				[list len $len range $range] -overhead {perf::list::spanned_list $len}
			}
		    }
		}
	    }
	}

	perf destroy
    }

    proc lset_describe {share_mode len at} {
	return "lset L\[$len\] $share_mode at $at"
    }
    proc lset_perf {} {
	variable Lengths

	print_separator lset

	ListPerf create perf -reps 10000

	# Shared
	foreach share_mode {shared unshared} {
	    foreach len $Lengths {
		foreach idx {0 1 end-1 end end+1}  {
		    comment lset at position $idx in a $share_mode list variable
		    if {$share_mode eq "shared"} {
			perf measure [lset_describe shared $len $idx] {
			    set L2 $L
			    lset L $idx X
			} [list len $len idx $idx] -overhead {set L2 $L}
		    } else {
			perf measure [lset_describe unshared $len $idx] {
			    lset L $idx X
			} [list len $len idx $idx]
		    }
		}
	    }
	}

	perf destroy

	# Nested
	ListPerf create perf -setup {
	    set L [lrepeat $len [list a b]]
	}

	foreach share_mode {shared unshared} {
	    foreach len $Lengths {
		foreach idx {0 1 end-1 end}  {
		    comment lset at position $idx in a $share_mode list variable
		    if {$share_mode eq "shared"} {
			perf measure [lset_describe shared $len "{$idx 0}"] {
			    set L2 $L
			    lset L $idx 0 X
			} [list len $len idx $idx] -overhead {set L2 $L}
		    } else {
			perf measure [lset_describe unshared $len "{$idx 0}"] {
			    lset L $idx 0 {X Y}
			} [list len $len idx $idx]
		    }
		}
	    }
	}

	perf destroy
    }

    proc lremove_describe {share_mode len at nremoved} {
	return "lremove L\[$len\] $share_mode $nremoved elements at $at"
    }
    proc lremove_perf {} {
	variable Lengths

	print_separator lremove

	ListPerf create perf -reps 10000

	foreach share_mode {shared unshared} {
	    foreach len $Lengths {
		foreach idx [list 0 1 [expr {$len/2}] end-1 end] {
		    if {$share_mode eq "shared"} {
			comment Remove one element from shared list
			perf measure [lremove_describe shared $len $idx 1] \
			    {lremove $L $idx} [list len $len idx $idx]

		    } else {
			comment Remove one element from unshared list
			set reps [expr {$len >= 1000 ? ($len/8) : ($len-2)}]
			perf measure [lremove_describe unshared $len $idx 1] \
			    {set L [lremove $L[set L {}] $idx]} [list len $len idx $idx] \
			    -overhead {set L $L; set L {}} -reps $reps
		    }
		}
		if {$share_mode eq "shared"} {
		    comment Remove multiple elements from shared list
		    perf measure [lremove_describe shared $len [list 0 1 [expr {$len/2}] end-1 end] 5] {
			lremove $L 0 1 [expr {$len/2}] end-1 end
		    } [list len $len]
		}
	    }
	    # Span
	    foreach len $Lengths {
		foreach idx [list 0 1 [expr {$len/2}] end-1 end] {
		    if {$share_mode eq "shared"} {
			comment Remove one element from shared-span list
			perf measure [lremove_describe shared-span $len $idx 1] \
			    {lremove $Lspan $idx} [list len $len idx $idx]
		    } else {
			comment Remove one element from unshared-span list
			set reps [expr {$len >= 1000 ? ($len/8) : ($len-2)}]
			perf measure [lremove_describe unshared-span $len $idx 1] \
			    {set Lspan [lremove $Lspan[set Lspan {}] $idx]} [list len $len idx $idx] \
			    -overhead {set Lspan $Lspan; set Lspan {}} -reps $reps
		    }
		}
		if {$share_mode eq "shared"} {
		    comment Remove multiple elements from shared-span list
		    perf measure [lremove_describe shared-span $len [list 0 1 [expr {$len/2}] end-1 end] 5] {
			lremove $Lspan 0 1 [expr {$len/2}] end-1 end
		    } [list len $len]
		}
	    }
	}

	perf destroy
    }

    proc lreplace_describe {share_mode len first last ninsert {times 1}} {
	if {$last < $first} {
	    return "lreplace L\[$len\] $share_mode 0 ($first:$last) elems at $first with $ninsert elems $times times."
	}
	return "lreplace L\[$len\] $share_mode $first:$last with $ninsert elems $times times."
    }
    proc lreplace_perf {} {
	variable Lengths

	print_separator lreplace

	set default_reps 10000
	ListPerf create perf -reps $default_reps

	foreach share_mode {shared unshared} {
	    # Insert only
	    foreach len $Lengths {
		set reps [expr {$len <= 100 ? ($len-2) : ($len/8)}]
		foreach first [list 0 1 [expr {$len/2}] end-1 end] {
		    if {$share_mode eq "shared"} {
			comment Insert one to shared list
			perf measure [lreplace_describe shared $len $first -1 1] {
			    lreplace $L $first -1 x
			} [list len $len first $first]

			comment Insert multiple to shared list
			perf measure [lreplace_describe shared $len $first -1 10] {
			    lreplace $L $first -1 X X X X X X X X X X
			} [list len $len first $first]

			comment Insert one to shared list repeatedly
			perf measure [lreplace_describe shared $len $first -1 1 $reps] {
			    set L [lreplace $L $first -1 x]
			} [list len $len first $first] -reps $reps

			comment Insert multiple to shared list repeatedly
			perf measure [lreplace_describe shared $len $first -1 10 $reps] {
			    set L [lreplace $L $first -1 X X X X X X X X X X]
			} [list len $len first $first] -reps $reps

		    } else {
			comment Insert one to unshared list
			perf measure [lreplace_describe unshared $len $first -1 1] {
			    set L [lreplace $L[set L {}] $first -1 x]
			} [list len $len first $first] -overhead {
			    set L $L; set L {}
			} -reps $reps

			comment Insert multiple to unshared list
			perf measure [lreplace_describe unshared $len $first -1 10] {
			    set L [lreplace $L[set L {}] $first -1 X X X X X X X X X X]
			} [list len $len first $first] -overhead {
			    set L $L; set L {}
			} -reps $reps
		    }
		}
	    }

	    # Delete only
	    foreach len $Lengths {
		set reps [expr {$len <= 100 ? ($len-2) : ($len/8)}]
		foreach first [list 0 1 [expr {$len/2}] end-1 end] {
		    if {$share_mode eq "shared"} {
			comment Delete one from shared list
			perf measure [lreplace_describe shared $len $first $first 0] {
			    lreplace $L $first $first
			} [list len $len first $first]
		    } else {
			comment Delete one from unshared list
			perf measure [lreplace_describe unshared $len $first $first 0] {
			    set L [lreplace $L[set L {}] $first $first x]
			} [list len $len first $first] -overhead {
			    set L $L; set L {}
			} -reps $reps
		    }
		}
	    }

	    # Insert + delete
	    foreach len $Lengths {
		set reps [expr {$len <= 100 ? ($len-2) : ($len/8)}]
		foreach range [list {0 1} {1 2} {end-2 end-1} {end-1 end}] {
		    lassign $range first last
		    if {$share_mode eq "shared"} {
			comment Insertions more than deletions from shared list
			perf measure [lreplace_describe shared $len $first $last 3] {
			    lreplace $L $first $last X Y Z
			} [list len $len first $first last $last]

			comment Insertions same as deletions from shared list
			perf measure [lreplace_describe shared $len $first $last 2] {
			    lreplace $L $first $last X Y
			} [list len $len first $first last $last]

			comment Insertions fewer than deletions from shared list
			perf measure [lreplace_describe shared $len $first $last 1] {
			    lreplace $L $first $last X
			} [list len $len first $first last $last]
		    } else {
			comment Insertions more than deletions from unshared list
			perf measure [lreplace_describe unshared $len $first $last 3] {
			    set L [lreplace $L[set L {}] $first $last X Y Z]
			} [list len $len first $first last $last] -overhead {
			    set L $L; set L {}
			} -reps $reps

			comment Insertions same as deletions from unshared list
			perf measure [lreplace_describe unshared $len $first $last 2] {
			    set L [lreplace $L[set L {}] $first $last X Y ]
			} [list len $len first $first last $last] -overhead {
			    set L $L; set L {}
			} -reps $reps

			comment Insertions fewer than deletions from unshared list
			perf measure [lreplace_describe unshared $len $first $last 1] {
			    set L [lreplace $L[set L {}] $first $last X]
			} [list len $len first $first last $last] -overhead {
			    set L $L; set L {}
			} -reps $reps
		    }
		}
	    }
	    # Spanned Insert + delete
	    foreach len $Lengths {
		set reps [expr {$len <= 100 ? ($len-2) : ($len/8)}]
		foreach range [list {0 1} {1 2} {end-2 end-1} {end-1 end}] {
		    lassign $range first last
		    if {$share_mode eq "shared"} {
			comment Insertions more than deletions from shared-span list
			perf measure [lreplace_describe shared-span $len $first $last 3] {
			    lreplace $Lspan $first $last X Y Z
			} [list len $len first $first last $last]

			comment Insertions same as deletions from shared-span list
			perf measure [lreplace_describe shared-span $len $first $last 2] {
			    lreplace $Lspan $first $last X Y
			} [list len $len first $first last $last]

			comment Insertions fewer than deletions from shared-span list
			perf measure [lreplace_describe shared-span $len $first $last 1] {
			    lreplace $Lspan $first $last X
			} [list len $len first $first last $last]
		    } else {
			comment Insertions more than deletions from unshared-span list
			perf measure [lreplace_describe unshared-span $len $first $last 3] {
			    set Lspan [lreplace $Lspan[set Lspan {}] $first $last X Y Z]
			} [list len $len first $first last $last] -overhead {
			    set Lspan $Lspan; set Lspan {}
			} -reps $reps

			comment Insertions same as deletions from unshared-span list
			perf measure [lreplace_describe unshared-span $len $first $last 2] {
			    set Lspan [lreplace $Lspan[set Lspan {}] $first $last X Y ]
			} [list len $len first $first last $last] -overhead {
			    set Lspan $Lspan; set Lspan {}
			} -reps $reps

			comment Insertions fewer than deletions from unshared-span list
			perf measure [lreplace_describe unshared-span $len $first $last 1] {
			    set Lspan [lreplace $Lspan[set Lspan {}] $first $last X]
			} [list len $len first $first last $last] -overhead {
			    set Lspan $Lspan; set Lspan {}
			} -reps $reps
		    }
		}
	    }
	}

	perf destroy
    }

    proc split_describe {len} {
	return "split L\[$len\]"
    }
    proc split_perf {} {
	variable Lengths
	print_separator split

	ListPerf create perf -setup {set S [string repeat "x " $len]}
	foreach len $Lengths {
	    comment Split a string
	    perf measure [split_describe $len] {
		split $S " "
	    } [list len $len]
	}
    }

    proc join_describe {share_mode len} {
	return "join L\[$len\] $share_mode"
    }
    proc join_perf {} {
	variable Lengths

	print_separator join

	ListPerf create perf -reps 10000
	foreach len $Lengths {
	    comment Join a list
	    perf measure [join_describe shared $len] {
		join $L
	    } [list len $len]
	}
	foreach len $Lengths {
	    comment Join a spanned list
	    perf measure [join_describe shared-span $len] {
		join $Lspan
	    } [list len $len]
	}
	perf destroy
    }

    proc lsearch_describe {share_mode len} {
	return "lsearch L\[$len\] $share_mode"
    }
    proc lsearch_perf {} {
	variable Lengths

	print_separator lsearch

	ListPerf create perf -reps 100000
	foreach len $Lengths {
	    comment Search a list
	    perf measure [lsearch_describe shared $len] {
		lsearch $L needle
	    } [list len $len]
	}
	foreach len $Lengths {
	    comment Search a spanned list
	    perf measure [lsearch_describe shared-span $len] {
		lsearch $Lspan needle
	    } [list len $len]
	}
	perf destroy
    }

    proc foreach_describe {share_mode len} {
	return "foreach L\[$len\] $share_mode"
    }
    proc foreach_perf {} {
	variable Lengths

	print_separator foreach

	ListPerf create perf -reps 10000
	foreach len $Lengths {
	    comment Iterate through a list
	    perf measure [foreach_describe shared $len] {
		foreach e $L {}
	    } [list len $len]
	}
	foreach len $Lengths {
	    comment Iterate a spanned list
	    perf measure [foreach_describe shared-span $len] {
		foreach e $Lspan {}
	    } [list len $len]
	}
	perf destroy
    }

    proc lmap_describe {share_mode len} {
	return "lmap L\[$len\] $share_mode"
    }
    proc lmap_perf {} {
	variable Lengths

	print_separator lmap

	ListPerf create perf -reps 10000
	foreach len $Lengths {
	    comment Iterate through a list
	    perf measure [lmap_describe shared $len] {
		lmap e $L {}
	    } [list len $len]
	}
	foreach len $Lengths {
	    comment Iterate a spanned list
	    perf measure [lmap_describe shared-span $len] {
		lmap e $Lspan {}
	    } [list len $len]
	}
	perf destroy
    }

    proc get_sort_sample {{spanned 0}} {
	variable perfScript
	variable sortSampleText

	if {![info exists sortSampleText]} {
	    set fd [open $perfScript]
	    set sortSampleText [split [read $fd] ""]
	    close $fd
	}
	set sortSampleText [string range $sortSampleText 0 9999]

	# NOTE: do NOT cache list result in a variable as we need it unshared
	if {$spanned} {
	    return [lrange [split $sortSampleText ""] 1 end-1]
	} else {
	    return [split $sortSampleText ""]
	}
    }
    proc lsort_describe {share_mode len} {
	return "lsort L\[$len] $share_mode"
    }
    proc lsort_perf {} {
	print_separator lsort

	ListPerf create perf -setup {}

	comment Sort a shared list
	perf measure [lsort_describe shared [llength [perf::list::get_sort_sample]]] {
	    lsort $L
	} {} -setup {set L [perf::list::get_sort_sample]}

	comment Sort a shared-span list
	perf measure [lsort_describe shared-span [llength [perf::list::get_sort_sample 1]]] {
	    lsort $L
	} {} -setup {set L [perf::list::get_sort_sample 1]}

	comment Sort an unshared list
	perf measure [lsort_describe unshared [llength [perf::list::get_sort_sample]]] {
	    lsort [perf::list::get_sort_sample]
	} {} -overhead {perf::list::get_sort_sample}

	comment Sort an unshared-span list
	perf measure [lsort_describe unshared-span [llength [perf::list::get_sort_sample 1]]] {
	    lsort [perf::list::get_sort_sample 1]
	} {} -overhead {perf::list::get_sort_sample 1}

	perf destroy
    }

    proc concat_describe {canonicality len elemlen} {
	return "concat L\[$len\] $canonicality with elements of length $elemlen"
    }
    proc concat_perf {} {
	variable Lengths

	print_separator concat

	ListPerf create perf -reps 100000

	foreach len $Lengths {
	    foreach elemlen {1 100} {
		comment Pure lists (no string representation)
		perf measure [concat_describe "pure lists" $len $elemlen] {
		    concat $L $L
		} [list len $len elemlen $elemlen] -setup {
		    set L [lrepeat $len [string repeat a $elemlen]]
		}

		comment Canonical lists (with string representation)
		perf measure [concat_describe "canonical lists" $len $elemlen] {
		    concat $L $L
		} [list len $len elemlen $elemlen] -setup {
		    set L [lrepeat $len [string repeat a $elemlen]]
		    append x x $L; # Generate string while keeping internal rep list
		    unset x
		}

		comment Non-canonical lists
		perf measure [concat_describe "non-canonical lists" $len $elemlen] {
		    concat $L $L
		} [list len $len elemlen $elemlen] -setup {
		    set L [string repeat "[string repeat a $elemlen] " $len]
		    llength $L
		}
	    }
	}

	# Span version
	foreach len $Lengths {
	    foreach elemlen {1 100} {
		comment Pure span lists (no string representation)
		perf measure [concat_describe "pure spanned lists" $len $elemlen] {
		    concat $L $L
		} [list len $len elemlen $elemlen] -setup {
		    set L [lrange [lrepeat [expr {$len+2}] [string repeat a $elemlen]] 1 end-1]
		}

		comment Canonical span lists (with string representation)
		perf measure [concat_describe "canonical spanned lists" $len $elemlen] {
		    concat $L $L
		} [list len $len elemlen $elemlen] -setup {
		    set L [lrange [lrepeat [expr {$len+2}] [string repeat a $elemlen]] 1 end-1]
		    append x x $L; # Generate string while keeping internal rep list
		    unset x
		}
	    }
	}

	perf destroy
    }

    proc test {} {
	variable RunTimes
	variable Options

	set selections [perf::list::setup $::argv]
	if {[llength $selections] == 0} {
	    set commands [info commands ::perf::list::*_perf]
	} else {
	    set commands [lmap sel $selections {
		if {$sel eq "help"} {
		    print_usage
		    exit 0
		}
		set cmd ::perf::list::${sel}_perf
		if {$cmd ni [info commands ::perf::list::*_perf]} {
		    puts stderr "Error: command $sel is not known or supported. Skipping."
		    continue
		}
		set cmd
	    }]
	}
	comment Setting up
	timerate -calibrate {}
	if {[info exists Options(--label)]} {
	    print "L $Options(--label)"
	}
	print "V [info patchlevel]"
	print "E [info nameofexecutable]"
	if {[info exists Options(--description)]} {
	    print "D $Options(--description)"
	}
	set twapi_keys {-privatebytes -workingset -workingsetpeak}
	if {[info commands ::twapi::get_process_memory_info] ne ""} {
	    set twapi_vm_pre [::twapi::get_process_memory_info]
	}
	foreach cmd [lsort -dictionary $commands] {
	    set RunTimes(command) 0.0
	    $cmd
	    set RunTimes(total) [expr {$RunTimes(total)+$RunTimes(command)}]
	    print "P [format_timings $RunTimes(command) 1] [string range $cmd 14 end-5] total run time"
	}
	# Print total runtime in same format as timerate output
	print "P [format_timings $RunTimes(total) 1] Total run time"

	if {[info exists twapi_vm_pre]} {
	    set twapi_vm_post [::twapi::get_process_memory_info]
	    set MB 1048576.0
	    foreach key $twapi_keys {
		set pre [expr {[dict get $twapi_vm_pre $key]/$MB}]
		set post [expr {[dict get $twapi_vm_post $key]/$MB}]
		print "P [format_timings $pre 1] Memory (MB) $key pre-test"
		print "P [format_timings $post 1] Memory (MB) $key post-test"
		print "P [format_timings [expr {$post-$pre}] 1] Memory (MB) delta $key"
	    }
	}
	if {[info commands memory] ne ""} {
	    foreach line [split [memory info] \n] {
		if {$line eq ""} continue
		set line [split $line]
		set val [expr {[lindex $line end]/1000.0}]
		set line [string trim [join [lrange $line 0 end-1]]]
		print "P [format_timings $val 1] memdbg $line (in thousands)"
	    }
	    print "# Allocations not freed on exit written to the lost-memory.tmp file."
	    print "# These will have to be manually compared."
	    # env TCL_FINALIZE_ON_EXIT must be set to 1 for this.
	    # DO NOT SET HERE - set ::env(TCL_FINALIZE_ON_EXIT) 1
	    # Must be set in environment before starting tclsh else bogus results
	    if {[info exists Options(--label)]} {
		set dump_file list-memory-$Options(--label).memdmp
	    } else {
		set dump_file list-memory-[pid].memdmp
	    }
	    memory onexit $dump_file
	}
    }
}


if {[info exists ::argv0] && [file tail $::argv0] eq [file tail [info script]]} {
    ::perf::list::test
}

Changes to tests-perf/test-performance.tcl.

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
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











-
+






-
+







# ------------------------------------------------------------------------
#
# test-performance.tcl --
#
#  This file provides common performance tests for comparison of tcl-speed
#  degradation or regression by switching between branches.
#
#  To execute test case evaluate direct corresponding file "tests-perf\*.perf.tcl".
#
# ------------------------------------------------------------------------
#
# Copyright (c) 2014 Serg G. Brester (aka sebres)
# Copyright © 2014 Serg G. Brester (aka sebres)
#
# See the file "license.terms" for information on usage and redistribution
# of this file.
#

namespace eval ::tclTestPerf {
# warm-up interpeter compiler env, calibrate timerate measurement functionality:
# warm-up interpreter compiler env, calibrate timerate measurement functionality:

# if no timerate here - import from unsupported:
if {[namespace which -command timerate] eq {}} {
  namespace inscope ::tcl::unsupported {namespace export timerate}
  namespace import ::tcl::unsupported::timerate
}

133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
133
134
135
136
137
138
139

140
141
142
143
144
145
146
147







-
+







      break
    }
    if {[string is boolean -strict $_($o)]} {
      set _($o) [expr {! $_($o)}]
      set args [lrange $args 1 end]
    } else {
      if {[llength $args] <= 2} {
        return -code error "value expected for option $o"
	return -code error "value expected for option $o"
      }
      set _($o) [lindex $args 1]
      set args [lrange $args 2 end]
    }
  }
  unset -nocomplain o
  if {[llength $args] < 2 || [llength $args] > 3} {
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
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







-
+














-
+












  # process measurement:
  foreach _(c) [_test_get_commands $lst] {
    {*}$_(outcmd) "% [regsub -all {\n[ \t]*} $_(c) {; }]"
    if {[regexp {^\s*\#} $_(c)]} continue
    if {[regexp {^\s*(?:setup|cleanup)\s+} $_(c)]} {
      set _(c) [lindex $_(c) 1]
      if {$_(-uplevel)} {
        set _(c) [list uplevel 1 $_(c)]
	set _(c) [list uplevel 1 $_(c)]
      }
      {*}$_(outcmd) [if 1 $_(c)]
      continue
    }
    if {$_(-uplevel)} {
      set _(c) [list uplevel 1 $_(c)]
    }
    set _(ittime) $_(reptime)
    # if output result (and not once):
    if {!$_(-no-result)} {
      set _(r) [if 1 $_(c)]
      if {$_(-convert-result) ne ""} { set _(r) [if 1 $_(-convert-result)] }
      {*}$_(outcmd) $_(r)
      if {[llength $_(ittime)] > 1} { # decrement max-count
        lset _(ittime) 1 [expr {[lindex $_(ittime) 1] - 1}]
	lset _(ittime) 1 [expr {[lindex $_(ittime) 1] - 1}]
      }
    }
    {*}$_(outcmd) [set _(m) [timerate $_(c) {*}$_(ittime)]]
    lappend _(itm) $_(m)
    {*}$_(outcmd) ""
  }
  if {$_(-from-run)} {
    _test_out_total
  }
}

}; # end of namespace ::tclTestPerf

Changes to tests-perf/timer-event.perf.tcl.

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







#!/usr/bin/tclsh

# ------------------------------------------------------------------------
#
# timer-event.perf.tcl --
#
#  This file provides performance tests for comparison of tcl-speed
#  of timer events (event-driven tcl-handling).
#
# ------------------------------------------------------------------------
#
# Copyright (c) 2014 Serg G. Brester (aka sebres)
# Copyright © 2014 Serg G. Brester (aka sebres)
#
# See the file "license.terms" for information on usage and redistribution
# of this file.
#


if {![namespace exists ::tclTestPerf]} {

Changes to tests/aaa_exit.test.

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
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
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
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






-
-
-
+
+
+










-
-
-
-
-
-
+
+
+
+
+
+

-
+



-
-
+
+



-
-
-
-
-
-
+
+
+
+
+
+

-
+



-
-
+
+






# Commands covered:  exit, emphasis on finalization hangs
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
}

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

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


# cleanup
::tcltest::cleanupTests
return

Added tests/abstractlist.test.




























































































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# Exercise AbstractList via the "lstring" command defined in tclTestABSList.c
#
# Copyright © 2022 Brian Griffin
#
# 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::*
}

catch {
    ::tcltest::loadTestedCommands
    package require -exact tcl::test [info patchlevel]
}

testConstraint testevalex [llength [info commands testevalex]]
testConstraint testobj [llength [info commands testobj]]
testConstraint lstring [llength [info commands lstring]]
testConstraint lgen [llength [info commands lgegenn]]

set abstractlisttestvars [info var *]

proc value-cmp {vara varb} {
    upvar $vara a
    upvar $varb b
    set ta [tcl::unsupported::representation $a]
    set tb [tcl::unsupported::representation $b]
    return [string compare $ta $tb]
}

set str "If you can keep your head when all about you Are losing theirs and blaming it on you,"
set str2 "If you can trust yourself when all men doubt you, But make allowance for their doubting, too."

test abstractlist-1.0 {error cases} -constraints lstring -body {
    lstring
} \
    -returnCodes 1 \
    -result {wrong # args: should be "lstring string"}

test abstractlist-1.1 {error cases} -constraints lstring -body {
    lstring a b c
} -returnCodes 1 \
    -result {wrong # args: should be "lstring string"}

test abstractlist-2.0 {no shimmer llength} -constraints {testobj lstring} -body {
    set l [lstring $str]
    set l-isa [testobj objtype $l]
    set len [llength $l]
    set l-isa2 [testobj objtype $l]
    list $l ${l-isa} ${len} ${l-isa2}
} -cleanup {
unset l
} -result {{I f { } y o u { } c a n { } k e e p { } y o u r { } h e a d { } w h e n { } a l l { } a b o u t { } y o u { } A r e { } l o s i n g { } t h e i r s { } a n d { } b l a m i n g { } i t { } o n { } y o u ,} lstring 85 lstring}

test abstractlist-2.1 {no shimmer lindex} {testobj lstring} {
    set l [lstring $str]
    set l-isa [testobj objtype $l]
    set ele [lindex $l 22]
    set l-isa2 [testobj objtype $l]
    list $l ${l-isa} ${ele} ${l-isa2}
} {{I f { } y o u { } c a n { } k e e p { } y o u r { } h e a d { } w h e n { } a l l { } a b o u t { } y o u { } A r e { } l o s i n g { } t h e i r s { } a n d { } b l a m i n g { } i t { } o n { } y o u ,} lstring e lstring}

test abstractlist-2.2 {no shimmer lreverse} {testobj lstring} {
    set l [lstring $str]
    set l-isa [testobj objtype $l]
    set r [lreverse $l]
    set r-isa [testobj objtype $r]
    set l-isa2 [testobj objtype $l]
    list $r ${l-isa} ${r-isa} ${l-isa2}
} {{, u o y { } n o { } t i { } g n i m a l b { } d n a { } s r i e h t { } g n i s o l { } e r A { } u o y { } t u o b a { } l l a { } n e h w { } d a e h { } r u o y { } p e e k { } n a c { } u o y { } f I} lstring lstring lstring}

test abstractlist-2.3 {no shimmer lrange} {testobj lstring} {
    set l [lstring $str]
    set l-isa [testobj objtype $l]
    set il [lsearch -all [lstring $str] { }]
    set l-isa2 [testobj objtype $l]
    lappend il [llength $l]
    set start 0
    set words [lmap i $il {
	set w [join [lrange $l $start $i-1] {} ]
	set start [expr {$i+1}]
	set w
    }]
    set l-isa3 [testobj objtype $l]
    list ${l-isa} $il ${l-isa2} ${l-isa3} $words
} {lstring {2 6 10 15 20 25 30 34 40 44 48 55 62 66 74 77 80 85} lstring lstring {If you can keep your head when all about you Are losing theirs and blaming it on you,}}

test abstractlist-2.4 {no shimmer foreach} {testobj lstring} {
    set l [lstring $str]
    set l-isa [testobj objtype $l]
    set word {}
    set words {}
    foreach c $l {
	if {$c eq { }} {
	    lappend words $word
	    set word {}
	} else {
	    append word $c
	}
    }
    if {$word ne ""} {
	lappend words $word
    }
    set l-isa2 [testobj objtype $l]
    list ${l-isa} ${l-isa2} $words
} {lstring lstring {If you can keep your head when all about you Are losing theirs and blaming it on you,}}

#
# The TBCE implements lreplace as a lrange + lappend operation, so, in this case, $m list, not an lstring.
#
test abstractlist-2.5 {!no shimmer lreplace} {testobj lstring} {
    set l [lstring $str2]
    set l-isa [testobj objtype $l]
    set m [lreplace $l 78 86 { } f a i l i n g]
    set m-isa [testobj objtype $m]
    set l-isa1 [testobj objtype $l]
    list ${l-isa} $m ${m-isa} ${l-isa1}
} {lstring {I f { } y o u { } c a n { } t r u s t { } y o u r s e l f { } w h e n { } a l l { } m e n { } d o u b t { } y o u , { } B u t { } m a k e { } a l l o w a n c e { } f o r { } t h e i r { } f a i l i n g , { } t o o .} lstring lstring}

test abstractlist-2.6 {no shimmer ledit} {testobj lstring} {
    # "ledit m 9 8 S"
    set l [lstring $str2]
    set l-isa [testobj objtype $l]
    set e [ledit l 68 67 s]
    set e-isa [testobj objtype $e]
    list ${l-isa} $e ${e-isa}
} {lstring {I f { } y o u { } c a n { } t r u s t { } y o u r s e l f { } w h e n { } a l l { } m e n { } d o u b t { } y o u , { } B u t { } m a k e { } a l l o w a n c e s { } f o r { } t h e i r { } d o u b t i n g , { } t o o .} lstring}

test abstractlist-2.7 {no shimmer linsert} -constraints {testobj lstring} -body {
    # "ledit m 9 8 S"
    set l [lstring $str2]
    set l-isa [testobj objtype $l]
    set i [linsert $l 11 {*}[split "truly " {}]]
    set i-isa [testobj objtype $i]
    set res [list ${l-isa} $i ${i-isa}]
    set p [lpop i 23]
    set p-isa [testobj objtype $p]
    set i-isa2 [testobj objtype $i]
    lappend res $p ${p-isa} $i ${i-isa2}
} -cleanup {
unset l i l-isa i-isa res p p-isa
} -result {lstring {I f { } y o u { } c a n { } t r u l y { } t r u s t { } y o u r s e l f { } w h e n { } a l l { } m e n { } d o u b t { } y o u , { } B u t { } m a k e { } a l l o w a n c e { } f o r { } t h e i r { } d o u b t i n g , { } t o o .} lstring y none {I f { } y o u { } c a n { } t r u l y { } t r u s t { } o u r s e l f { } w h e n { } a l l { } m e n { } d o u b t { } y o u , { } B u t { } m a k e { } a l l o w a n c e { } f o r { } t h e i r { } d o u b t i n g , { } t o o .} lstring}

test abstractlist-2.8 {shimmer lassign} {testobj lstring} {
    set l [lstring Inconceivable]
    set l-isa [testobj objtype $l]
    set l2 [lassign $l i n c]
    set l-isa2 [testobj objtype $l]
    set l2-isa [testobj objtype $l2]
    list $l ${l-isa} $l2 ${l-isa2} ${l2-isa}
} {{I n c o n c e i v a b l e} lstring {o n c e i v a b l e} lstring lstring}

test abstractlist-2.9 {no shimmer lremove} {testobj lstring} {
    set l [lstring Inconceivable]
    set l-isa [testobj objtype $l]
    set l2 [lremove $l 0 1]
    set l-isa2 [testobj objtype $l]
    set l2-isa [testobj objtype $l2]
    list $l ${l-isa} $l2 ${l-isa2} ${l2-isa}
} {{I n c o n c e i v a b l e} lstring {c o n c e i v a b l e} lstring lstring}

test abstractlist-2.10 {shimmer lreverse} {testobj lstring} {
    set l [lstring Inconceivable]
    set l-isa [testobj objtype $l]
    set l2 [lreverse $l]
    set l-isa2 [testobj objtype $l]
    set l2-isa [testobj objtype $l2]
    list $l ${l-isa} $l2 ${l-isa2} ${l2-isa}
} {{I n c o n c e i v a b l e} lstring {e l b a v i e c n o c n I} lstring lstring}

test abstractlist-2.11 {shimmer lset} {testobj lstring} {
    set l [lstring Inconceivable]
    set l-isa [testobj objtype $l]
    set m [lset l 2 k]
    set m-isa [testobj objtype $m]
    list $l ${l-isa} $m ${m-isa} [value-cmp l m]
} {{I n k o n c e i v a b l e} lstring {I n k o n c e i v a b l e} lstring 0}

# lrepeat
test abstractlist-2.12 {shimmer lrepeat} {testobj lstring} {
    set l [lstring Inconceivable]
    set l-isa [testobj objtype $l]
    set m [lrepeat 3 $l]
    set m-isa [testobj objtype $m]
    set n [lindex $m 1]
    list $l ${l-isa} $m ${m-isa} [testobj objtype $n] [value-cmp l n]
} {{I n c o n c e i v a b l e} lstring {{I n c o n c e i v a b l e} {I n c o n c e i v a b l e} {I n c o n c e i v a b l e}} list lstring 0}

test abstractlist-2.13 {no shimmer join llength==1} {testobj lstring} {
    set l [lstring G]
    set l-isa [testobj objtype $l]
    set j [join $l :]
    set j-isa [testobj objtype $j]
    list ${l-isa} $l ${j-isa} $j
} {lstring G none G}

test abstractlist-2.14 {error case lset multiple indicies} -constraints {testobj lstring} -body {
    set l [lstring Inconceivable]
    set l-isa [testobj objtype $l]
    set m [lset l 2 0 1 k]
    set m-isa [testobj objtype $m]
    list $l ${l-isa} $m ${m-isa} [value-cmp l m]
} -returnCodes 1 \
    -result {Multiple indicies not supported by lstring.}

# lsort

test abstractlist-3.0 {no shimmer llength} {testobj lstring} {
    set l [lstring -not SLICE $str]
    set l-isa [testobj objtype $l]
    set len [llength $l]
    set l-isa2 [testobj objtype $l]
    list $l ${l-isa} ${len} ${l-isa2}
} {{I f { } y o u { } c a n { } k e e p { } y o u r { } h e a d { } w h e n { } a l l { } a b o u t { } y o u { } A r e { } l o s i n g { } t h e i r s { } a n d { } b l a m i n g { } i t { } o n { } y o u ,} lstring 85 lstring}

test abstractlist-3.1 {no shimmer lindex} {testobj lstring} {
    set l [lstring -not SLICE $str]
    set l-isa [testobj objtype $l]
    set n 22
    set ele [lindex $l $n] ;# exercise INST_LIST_INDEX
    set l-isa2 [testobj objtype $l]
    list $l ${l-isa} ${ele} ${l-isa2}
} {{I f { } y o u { } c a n { } k e e p { } y o u r { } h e a d { } w h e n { } a l l { } a b o u t { } y o u { } A r e { } l o s i n g { } t h e i r s { } a n d { } b l a m i n g { } i t { } o n { } y o u ,} lstring e lstring}

test abstractlist-3.2 {no shimmer lreverse} {testobj lstring} {
    set l [lstring -not SLICE $str]
    set l-isa [testobj objtype $l]
    set r [lreverse $l]
    set r-isa [testobj objtype $r]
    set l-isa2 [testobj objtype $l]
    list $r ${l-isa} ${r-isa} ${l-isa2}
} {{, u o y { } n o { } t i { } g n i m a l b { } d n a { } s r i e h t { } g n i s o l { } e r A { } u o y { } t u o b a { } l l a { } n e h w { } d a e h { } r u o y { } p e e k { } n a c { } u o y { } f I} lstring lstring lstring}

test abstractlist-3.3 {shimmer lrange} {testobj lstring} {
    set l [lstring -not SLICE $str]
    set l-isa [testobj objtype $l]
    set il [lsearch -all [lstring -not SLICE $str] { }]
    set l-isa2 [testobj objtype $l]
    lappend il [llength $l]
    set start 0
    set words [lmap i $il {
	set w [join [lrange $l $start $i-1] {} ]
	set start [expr {$i+1}]
	set w
    }]
    set l-isa3 [testobj objtype $l]; # lrange defaults to list behavior
    list ${l-isa} $il ${l-isa2} ${l-isa3} $words
} {lstring {2 6 10 15 20 25 30 34 40 44 48 55 62 66 74 77 80 85} lstring list {If you can keep your head when all about you Are losing theirs and blaming it on you,}}

test abstractlist-3.4 {no shimmer foreach} {testobj lstring} {
    set l [lstring -not SLICE $str]
    set l-isa [testobj objtype $l]
    set word {}
    set words {}
    foreach c $l {
	if {$c eq { }} {
	    lappend words $word
	    set word {}
	} else {
	    append word $c
	}
    }
    if {$word ne ""} {
	lappend words $word
    }
    set l-isa2 [testobj objtype $l]
    list ${l-isa} ${l-isa2} $words
} {lstring lstring {If you can keep your head when all about you Are losing theirs and blaming it on you,}}

#
# The TBCE implements lreplace as a lrange + lappend operation, so, in this case, $m list, not an lstring.
#
test abstractlist-3.5 {!no shimmer lreplace} {testobj lstring} {
    set l [lstring -not SLICE $str2]
    set l-isa [testobj objtype $l]
    set m [lreplace $l 79 86 f a i l i n g]
    set m-isa [testobj objtype $m]
    set l-isa1 [testobj objtype $l]
    list ${l-isa} $m ${m-isa} ${l-isa1}
} {lstring {I f { } y o u { } c a n { } t r u s t { } y o u r s e l f { } w h e n { } a l l { } m e n { } d o u b t { } y o u , { } B u t { } m a k e { } a l l o w a n c e { } f o r { } t h e i r { } f a i l i n g , { } t o o .} lstring lstring}

test abstractlist-3.6 {no shimmer ledit} {testobj lstring} {
    # "ledit m 9 8 S"
    set l [lstring -not SLICE $str2]
    set l-isa [testobj objtype $l]
    set e [ledit l 68 67 s]
    set e-isa [testobj objtype $e]
    list ${l-isa} $e ${e-isa}
} {lstring {I f { } y o u { } c a n { } t r u s t { } y o u r s e l f { } w h e n { } a l l { } m e n { } d o u b t { } y o u , { } B u t { } m a k e { } a l l o w a n c e s { } f o r { } t h e i r { } d o u b t i n g , { } t o o .} lstring}

test abstractlist-3.7 {no shimmer linsert} {testobj lstring} {
    # "ledit m 9 8 S"
    set res {}
    set l [lstring -not SLICE $str2]
    set l-isa [testobj objtype $l]
    set i [linsert $l 35 {*}[split "wo" {}]]
    set i-isa [testobj objtype $i]
    set res [list ${l-isa} $i ${i-isa}]
    set p [lpop i 23]
    set p-isa [testobj objtype $p]
    set i-isa2 [testobj objtype $i]
    lappend res $p ${p-isa} $i ${i-isa2}
} {lstring {I f { } y o u { } c a n { } t r u s t { } y o u r s e l f { } w h e n { } a l l { } w o m e n { } d o u b t { } y o u , { } B u t { } m a k e { } a l l o w a n c e { } f o r { } t h e i r { } d o u b t i n g , { } t o o .} lstring l none {I f { } y o u { } c a n { } t r u s t { } y o u r s e f { } w h e n { } a l l { } w o m e n { } d o u b t { } y o u , { } B u t { } m a k e { } a l l o w a n c e { } f o r { } t h e i r { } d o u b t i n g , { } t o o .} lstring}

test abstractlist-3.8 {shimmer lassign} {testobj lstring} {
    set l [lstring -not SLICE Inconceivable]
    set l-isa [testobj objtype $l]
    set l2 [lassign $l i n c] ;# must be using lrange internally
    set l-isa2 [testobj objtype $l]
    set l2-isa [testobj objtype $l2]
    list $l ${l-isa} $l2 ${l-isa2} ${l2-isa}
} {{I n c o n c e i v a b l e} lstring {o n c e i v a b l e} list list}

test abstractlist-3.9 {no shimmer lremove} {testobj lstring} {
    set l [lstring -not SLICE Inconceivable]
    set l-isa [testobj objtype $l]
    set l2 [lremove $l 0 1]
    set l-isa2 [testobj objtype $l]
    set l2-isa [testobj objtype $l2]
    list $l ${l-isa} $l2 ${l-isa2} ${l2-isa}
} {{I n c o n c e i v a b l e} lstring {c o n c e i v a b l e} lstring lstring}

test abstractlist-3.10 {shimmer lreverse} {testobj lstring} {
    set l [lstring -not SLICE Inconceivable]
    set l-isa [testobj objtype $l]
    set l2 [lreverse $l]
    set l-isa2 [testobj objtype $l]
    set l2-isa [testobj objtype $l2]
    list $l ${l-isa} $l2 ${l-isa2} ${l2-isa}
} {{I n c o n c e i v a b l e} lstring {e l b a v i e c n o c n I} lstring lstring}

test abstractlist-3.11 {shimmer lset} {testobj lstring} {
    set l [lstring -not SLICE Inconceivable]
    set l-isa [testobj objtype $l]
    set four 4
    set m [lset l $four-2 k]
    set m-isa [testobj objtype $m]
    list $l ${l-isa} $m ${m-isa} [value-cmp l m]
} {{I n k o n c e i v a b l e} lstring {I n k o n c e i v a b l e} lstring 0}

# lrepeat
test abstractlist-3.12 {shimmer lrepeat} {testobj lstring} {
    set l [lstring -not SLICE Inconceivable]
    set l-isa [testobj objtype $l]
    set m [lrepeat 3 $l]
    set m-isa [testobj objtype $m]
    set n [lindex $m 1]
    list $l ${l-isa} $m ${m-isa} [testobj objtype $n] [value-cmp l n]
} {{I n c o n c e i v a b l e} lstring {{I n c o n c e i v a b l e} {I n c o n c e i v a b l e} {I n c o n c e i v a b l e}} list lstring 0}

# lsort
foreach not {{} REVERSE SLICE SETELEMENT REPLACE GETELEMENTS} {

    testConstraint [format "%sShimmer" [string totitle $not]] [expr {$not eq ""}]
    set options [expr {$not ne "" ? "-not $not" : ""}]

test abstractlist-$not-4.0 {no shimmer llength} {testobj lstring} {
    set l [lstring {*}$options $str]
    set l-isa [testobj objtype $l]
    set len [llength $l]
    set l-isa2 [testobj objtype $l]
    list $l ${l-isa} ${len} ${l-isa2}
} {{I f { } y o u { } c a n { } k e e p { } y o u r { } h e a d { } w h e n { } a l l { } a b o u t { } y o u { } A r e { } l o s i n g { } t h e i r s { } a n d { } b l a m i n g { } i t { } o n { } y o u ,} lstring 85 lstring}

test abstractlist-$not-4.1 {no shimmer lindex} {testobj lstring} {
    set l [lstring {*}$options $str]
    set l-isa [testobj objtype $l]
    set ele [lindex $l 22]
    set l-isa2 [testobj objtype $l]
    list $l ${l-isa} ${ele} ${l-isa2}
} {{I f { } y o u { } c a n { } k e e p { } y o u r { } h e a d { } w h e n { } a l l { } a b o u t { } y o u { } A r e { } l o s i n g { } t h e i r s { } a n d { } b l a m i n g { } i t { } o n { } y o u ,} lstring e lstring}

test abstractlist-$not-4.2 {lreverse} {ReverseShimmer testobj lstring} {
    set l [lstring {*}$options $str]
    set l-isa [testobj objtype $l]
    set r [lreverse $l]
    set r-isa [testobj objtype $r]
    set l-isa2 [testobj objtype $l]
    list $r ${l-isa} ${r-isa} ${l-isa2}
} {{, u o y { } n o { } t i { } g n i m a l b { } d n a { } s r i e h t { } g n i s o l { } e r A { } u o y { } t u o b a { } l l a { } n e h w { } d a e h { } r u o y { } p e e k { } n a c { } u o y { } f I} lstring lstring lstring}

test abstractlist-$not-4.3 {no shimmer lrange} {RangeShimmer testobj lstring} {
    set l [lstring {*}$options $str]
    set l-isa [testobj objtype $l]
    set il [lsearch -all [lstring {*}$options $str] { }]
    set l-isa2 [testobj objtype $l]
    lappend il [llength $l]
    set start 0
    set words [lmap i $il {
	set w [join [lrange $l $start $i-1] {} ]
	set start [expr {$i+1}]
	set w
    }]
    set l-isa3 [testobj objtype $l]
    list ${l-isa} $il ${l-isa2} ${l-isa3} $words
} {lstring {2 7 10 16 25 29 36 39 47 55 58 63} lstring lstring {If you can keep your head when all about you Are losing theirs and blaming it on you,}}

test abstractlist-$not-4.4 {no shimmer foreach} {testobj lstring} {
    set l [lstring {*}$options $str]
    set l-isa [testobj objtype $l]
    set word {}
    set words {}
    foreach c $l {
	if {$c eq { }} {
	    lappend words $word
	    set word {}
	} else {
	    append word $c
	}
    }
    if {$word ne ""} {
	lappend words $word
    }
    set l-isa2 [testobj objtype $l]
    list ${l-isa} ${l-isa2} $words
} {lstring lstring {If you can keep your head when all about you Are losing theirs and blaming it on you,}}

#
# The TBCE implements lreplace as a lrange + lappend operation, so, in this case, $m list, not an lstring.
#
test abstractlist-$not-4.5 {!no shimmer lreplace} {RangeShimmer testobj lstring} {
    set l [lstring {*}$options $str2]
    set l-isa [testobj objtype $l]
    set m [lreplace $l 18 23 { } f a i l ?]
    set m-isa [testobj objtype $m]
    set l-isa1 [testobj objtype $l]
    list ${l-isa} $m ${m-isa} ${l-isa1}
} {lstring {} list lstring}

test abstractlist-$not-4.6 {no shimmer ledit} {SetelementShimmer ReplaceShimmer testobj lstring} {
    set l [lstring {*}$options $str2]
    set l-isa [testobj objtype $l]
    set e [ledit l 68 67 s]
    set e-isa [testobj objtype $e]
    list ${l-isa} $e ${e-isa}
} {lstring {I f { } y o u { } c a n { } t r u s t { } y o u r s e l f { } w h e n { } a l l { } m e n { } d o u b t { } y o u , { } B u t { } m a k e { } a l l o w a n c e s { } f o r { } t h e i r { } d o u b t i n g , { } t o o .} lstring}

test abstractlist-$not-4.7 {no shimmer linsert} {ReplaceShimmer GetelementsShimmer testobj lstring}  {
    set l [lstring {*}$options $str2]
    set l-isa [testobj objtype $l]
    set i [linsert $l 12 {*}[split "almost " {}]]
    set i-isa [testobj objtype $i]
    set res [list ${l-isa} $i ${i-isa}]
    set p [lpop i 23]
    set p-isa [testobj objtype $p]
    set i-isa2 [testobj objtype $i]
    lappend res $p ${p-isa} $i ${i-isa2}
} {lstring {I f { } y o u { } c a n { } t r u s t { } y o u r s e l f { } w h e n { } a l l { } m e n { } d o u b t { } y o u , { } B u t { } m a k e { } a l l o w a n c e { } f o r { } t h e i r { } d o u b t i n g , { } t o o .} lstring}

# lassign probably uses lrange internally
test abstractlist-$not-4.8 {shimmer lassign} {RangeShimmer testobj lstring} {
    set l [lstring {*}$options Inconceivable]
    set l-isa [testobj objtype $l]
    set l2 [lassign $l i n c]
    set l-isa2 [testobj objtype $l]
    set l2-isa [testobj objtype $l2]
    list $l ${l-isa} $l2 ${l-isa2} ${l2-isa}
} {{I n c o n c e i v a b l e} lstring {o n c e i v a b l e} lstring lstring}

test abstractlist-$not-4.9 {no shimmer lremove} {ReplaceShimmer testobj lstring} {
    set l [lstring {*}$options Inconceivable]
    set l-isa [testobj objtype $l]
    set l2 [lremove $l 0 1]
    set l-isa2 [testobj objtype $l]
    set l2-isa [testobj objtype $l2]
    list $l ${l-isa} $l2 ${l-isa2} ${l2-isa}
} {{I n c o n c e i v a b l e} lstring {c o n c e i v a b l e} lstring lstring}

test abstractlist-$not-4.10 {shimmer lreverse} {ReverseShimmer testobj lstring} {
    set l [lstring {*}$options Inconceivable]
    set l-isa [testobj objtype $l]
    set l2 [lreverse $l]
    set l-isa2 [testobj objtype $l]
    set l2-isa [testobj objtype $l2]
    list $l ${l-isa} $l2 ${l-isa2} ${l2-isa}
} {{I n c o n c e i v a b l e} lstring {e l b a v i e c n o c n I} lstring lstring}

test abstractlist-$not-4.11 {shimmer lset} {SetelementShimmer testobj lstring} {
    set l [lstring {*}$options Inconceivable]
    set l-isa [testobj objtype $l]
    set m [lset l 2 k]
    set m-isa [testobj objtype $m]
    list $l ${l-isa} $m ${m-isa} [value-cmp l m]
} {{I n k o n c e i v a b l e} lstring {I n k o n c e i v a b l e} lstring 0}

test abstractlist-$not-4.11x {lset not compiled} {SetelementShimmer testobj lstring testevalex} {
    set l [lstring {*}$options Inconceivable]
    set l-isa [testobj objtype $l]
    set m [testevalex {lset l 2 k}]
    set m-isa [testobj objtype $m]
    list $l ${l-isa} $m ${m-isa} [value-cmp l m]
} {{I n k o n c e i v a b l e} lstring {I n k o n c e i v a b l e} lstring 0}

test abstractlist-$not-4.11e {error case lset multiple indicies} \
    -constraints {SetelementShimmer testobj lstring testevalex} -body {
    set l [lstring Inconceivable]
    set l-isa [testobj objtype $l]
    set m [testevalex {lset l 2 0 1 k}]
    set m-isa [testobj objtype $m]
    list $l ${l-isa} $m ${m-isa} [value-cmp l m]
} -returnCodes 1 \
    -result {Multiple indicies not supported by lstring.}

# lrepeat
test abstractlist-$not-4.12 {shimmer lrepeat} -constraints {testobj lstring} -body {
    set l [lstring {*}$options Inconceivable]
    set l-isa [testobj objtype $l]
    set m [lrepeat 3 $l]
    set m-isa [testobj objtype $m]
    set n [lindex $m 1]
    list $l ${l-isa} $m ${m-isa} [testobj objtype $n] [value-cmp l n]
} -cleanup {
} -result {{I n c o n c e i v a b l e} lstring {{I n c o n c e i v a b l e} {I n c o n c e i v a b l e} {I n c o n c e i v a b l e}} list lstring 0}

# Disable constraint
testConstraint [format "%sShimmer" [string totitle $not]] 1

}

#
# Test fix for bug in TEBC for STR CONCAT, and LIST INDEX
# instructions.
# This example abstract list (lgen) causes a rescursive call in TEBC,
# stack management was not included for these instructions in TEBC.
#
test abstractlist-lgen-bug {bug in str concat and list operations} -constraints lgen -setup {
    set lgenfile [makeFile {
	# Test TIP 192 - Lazy Lists

	set res {}
	set cntr 0

	# Fatal error here when [source]'d -- It is a refcounting problem...
	lappend res Index*2:[lgen 1 expr 2* ]:--
	set x [lseq 17]
	set y [lgen 17 apply {{index} {expr {$index * 6}}}] ;# expr * 6
	foreach i $x n $y {
	    lappend res "$i -> $n"
	}
	proc my_expr {offset index} {
	    expr {$index + $offset}
	}
	lappend res my_expr(3):[my_expr 3 0]

	lappend res [set ss [lgen 15 my_expr 7]]
	lappend res s2:[list "Index+7:" $ss ":--"]

	lappend res  foo:[list "Index-8:" [lgen 15 my_expr -8] ":--"]

	set 9 [lgen 15 my_expr 7]
	lappend res 9len=[llength $9]
	lappend res 9(3)=[lindex $9 3]
	lappend res bar:[list "Index+7:" $9 ":--"]

	lappend res Index+7:$9:--

	lappend res Index+7:[lgen 15 my_expr 7]:--

	proc fib {phi n} {
	    set d [expr {round(pow($phi, $n) / sqrt(5.0))}]
	    return $d
	}
	set phi [expr {(1 + sqrt(5.0)) / 2.0}]

	lappend res fib:[lmap n [lseq 5] {fib $phi $n}]

	set x [lgen 20 fib $phi]
	lappend res "First 20 fibbinacci:[lgen 20 fib $phi]"
	lappend res "First 20 fibbinacci from x :$x"
	unset x
	lappend res Good-Bye!
	set res
    } source.file]
} -body {
    set tcl_traceExec 0
    set tcl_traceCompile 0
    set f $lgenfile
    #set script [format "puts ====-%s-====\nsource %s\nputs ====-done-====\n" $f $f]
    set script [format "source %s" $f]
    #puts stderr "eval $script"
    eval $script
} -cleanup {
    removeFile source.file
    unset res
} -result {Index*2:0:-- {0 -> 0} {1 -> 6} {2 -> 12} {3 -> 18} {4 -> 24} {5 -> 30} {6 -> 36} {7 -> 42} {8 -> 48} {9 -> 54} {10 -> 60} {11 -> 66} {12 -> 72} {13 -> 78} {14 -> 84} {15 -> 90} {16 -> 96} my_expr(3):3 {7 8 9 10 11 12 13 14 15 16 17 18 19 20 21} {s2:Index+7: {7 8 9 10 11 12 13 14 15 16 17 18 19 20 21} :--} {foo:Index-8: {-8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6} :--} 9len=15 9(3)=10 {bar:Index+7: {7 8 9 10 11 12 13 14 15 16 17 18 19 20 21} :--} {Index+7:7 8 9 10 11 12 13 14 15 16 17 18 19 20 21:--} {Index+7:7 8 9 10 11 12 13 14 15 16 17 18 19 20 21:--} {fib:0 1 1 2 3} {First 20 fibbinacci:0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181} {First 20 fibbinacci from x :0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181} Good-Bye!}

test abstractlist-lgen-bug2 {bug in foreach} -constraints lgen -body {

    set x [lseq 17]
    set y [lgen 17 expr 6*]

    lappend res x-[lrange [tcl::unsupported::representation $x] 0 3]
    lappend res y-[lrange [tcl::unsupported::representation $y] 0 3]
    foreach i $x n $y {
	lappend res "$i -> $n"
    }
    lappend res x-[lrange [tcl::unsupported::representation $x] 0 3]
    lappend res y-[lrange [tcl::unsupported::representation $y] 0 3]

} -cleanup {
    unset res
} -result {{x-value is a arithseries} {y-value is a lgenseries} {0 -> 0} {1 -> 6} {2 -> 12} {3 -> 18} {4 -> 24} {5 -> 30} {6 -> 36} {7 -> 42} {8 -> 48} {9 -> 54} {10 -> 60} {11 -> 66} {12 -> 72} {13 -> 78} {14 -> 84} {15 -> 90} {16 -> 96} {x-value is a arithseries} {y-value is a lgenseries}}

# scalar values
test abstractlist-int {TclLengthOne: anti-shimmer of boolean, int, double, bignum} testobj {
    set res {}
    foreach i [list [expr {1+0}] [expr {true}] [expr {3.141592}] [expr {round(double(0x7fffffffffffffff))}]] {
	lappend res [testobj objtype $i]
	lappend res [llength $i]
	lappend res [testobj objtype $i]
    }
#set w [expr {3.141592}]
#lappend res [testobj objtype $w] [llength $w] [testobj objtype $w]
    set res
} {int 1 int boolean 1 boolean double 1 double bignum 1 bignum}

# lsort

# cleanup
::tcltest::cleanupTests

proc my_abstl_cleanup {vars} {
    set nowvars [uplevel info vars]
    foreach var $nowvars {
	if {$var ni $vars} {
	    uplevel unset $var
	    lappend clean-list $var
	}
    }
    return ${clean-list}
}

my_abstl_cleanup $abstractlisttestvars

Changes to tests/all.tcl.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20
21
1
2
3
4
5
6


7
8
9
10
11
12
13

14
15
16
17
18
19
20






-
-
+
+





-







# all.tcl --
#
# This file contains a top-level script to run all of the Tcl
# tests.  Execute it by invoking "source all.tcl" when running tcltest
# in this directory.
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2000 by Ajuba Solutions
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2000 Ajuba Solutions
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

package prefer latest
package require Tcl 8.5-
package require tcltest 2.5
namespace import ::tcltest::*

configure {*}$argv -testdir [file dirname [file dirname [file normalize [
    info script]/...]]]

if {[singleProcess]} {

Changes to tests/append.test.

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
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
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
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






-
-
-
+
+
+








+

+

+
+















-
+




















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







# Commands covered:  append lappend
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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
unset -nocomplain x
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testbytestring [llength [info commands testbytestring]]

test append-1.1 {append command} {
    unset -nocomplain x
    list [append x 1 2 abc "long string"] $x
} {{12abclong string} {12abclong string}}
test append-1.2 {append command} {
    set x ""
    list [append x first] [append x second] [append x third] $x
} {first firstsecond firstsecondthird firstsecondthird}
test append-1.3 {append command} {
    set x "abcd"
    append x
} abcd

test append-2.1 {long appends} {
    set x ""
    for {set i 0} {$i < 1000} {set i [expr $i+1]} {
    for {set i 0} {$i < 1000} {incr i} {
	append x "foobar "
    }
    set y "foobar"
    set y "$y $y $y $y $y $y $y $y $y $y"
    set y "$y $y $y $y $y $y $y $y $y $y"
    set y "$y $y $y $y $y $y $y $y $y $y "
    expr {$x == $y}
} 1

test append-3.1 {append errors} -returnCodes error -body {
    append
} -result {wrong # args: should be "append varName ?value ...?"}
test append-3.2 {append errors} -returnCodes error -body {
    set x ""
    append x(0) 44
} -result {can't set "x(0)": variable isn't array}
test append-3.3 {append errors} -returnCodes error -body {
    unset -nocomplain x
    append x
} -result {can't read "x": no such variable}
test append-3.4 {append surrogates} -body {
    set x \uD83D
    append x \uDE02
} -result \uD83D\uDE02
test append-3.5 {append surrogates} -body {
    set x \uD83D
    set x $x\uDE02
} -result \uD83D\uDE02
test append-3.6 {append surrogates} -body {
    set x \uDE02
    set x \uD83D$x
} -result \uD83D\uDE02
test append-3.7 {append \xC0 \x80} -constraints testbytestring -body {
    set x [testbytestring \xC0]
    string length [append x [testbytestring \x80]]
} -result 2
test append-3.8 {append \xC0 \x80} -constraints testbytestring -body {
    set x [testbytestring \xC0]
    string length $x[testbytestring \x80]
} -result 2
test append-3.9 {append \xC0 \x80} -constraints testbytestring -body {
    set x [testbytestring \x80]
    string length [testbytestring \xC0]$x
} -result 2
test append-3.10 {append surrogates} -body {
    set x \uD83D
    string range $x 0 end
    append x \uDE02
} -result [string range \uD83D\uDE02 0 end]

test append-4.1 {lappend command} {
    unset -nocomplain x
    list [lappend x 1 2 abc "long string"] $x
} {{1 2 abc {long string}} {1 2 abc {long string}}}
test append-4.2 {lappend command} {
    set x ""
154
155
156
157
158
159
160
161

162
163
164
165
166
167
168
187
188
189
190
191
192
193

194
195
196
197
198
199
200
201







-
+







test append-5.1 {long lappends} -setup {
    unset -nocomplain x
    proc check {var size} {
	set l [llength $var]
	if {$l != $size} {
	    return "length mismatch: should have been $size, was $l"
	}
	for {set i 0} {$i < $size} {set i [expr $i+1]} {
	for {set i 0} {$i < $size} {incr i} {
	    set j [lindex $var $i]
	    if {$j ne "item $i"} {
		return "element $i should have been \"item $i\", was \"$j\""
	    }
	}
	return ok
    }
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
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







-
+












-
+



-
+






-
+



-
+





-
+



-
+




-
+







    lappend x(0) 44
} -result {can't set "x(0)": variable isn't array}

test append-7.1 {lappend-created var and error in trace on that var} -setup {
    catch {rename foo ""}
    unset -nocomplain x
} -body {
    trace variable x w foo
    trace add variable x write foo
    proc foo {} {global x; unset x}
    catch {lappend x 1}
    proc foo {args} {global x; unset x}
    info exists x
    set x
    lappend x 1
    list [info exists x] [catch {set x} msg] $msg
} -result {0 1 {can't read "x": no such variable}}
test append-7.2 {lappend var triggers read trace} -setup {
    unset -nocomplain myvar
    unset -nocomplain ::result
} -body {
    trace variable myvar r foo
    trace add variable myvar read foo
    proc foo {args} {append ::result $args}
    lappend myvar a
    return $::result
} -result {myvar {} r}
} -result {myvar {} read}
test append-7.3 {lappend var triggers read trace, array var} -setup {
    unset -nocomplain myvar
    unset -nocomplain ::result
} -body {
    # The behavior of read triggers on lappend changed in 8.0 to not trigger
    # them, and was changed back in 8.4.
    trace variable myvar r foo
    trace add variable myvar read foo
    proc foo {args} {append ::result $args}
    lappend myvar(b) a
    return $::result
} -result {myvar b r}
} -result {myvar b read}
test append-7.4 {lappend var triggers read trace, array var exists} -setup {
    unset -nocomplain myvar
    unset -nocomplain ::result
} -body {
    set myvar(0) 1
    trace variable myvar r foo
    trace add variable myvar read foo
    proc foo {args} {append ::result $args}
    lappend myvar(b) a
    return $::result
} -result {myvar b r}
} -result {myvar b read}
test append-7.5 {append var does not trigger read trace} -setup {
    unset -nocomplain myvar
    unset -nocomplain ::result
} -body {
    trace variable myvar r foo
    trace add variable myvar read foo
    proc foo {args} {append ::result $args}
    append myvar a
    info exists ::result
} -result {0}

# THERE ARE NO append-8.* TESTS

Changes to tests/appendComp.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  append lappend
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
37
38
39
40
41
42
43
44

45
46
47
48
49
50
51
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51







-
+







    }
    foo
} abcd

test appendComp-2.1 {long appends} {
    proc foo {} {
	set x ""
	for {set i 0} {$i < 1000} {set i [expr $i+1]} {
	for {set i 0} {$i < 1000} {incr i} {
	    append x "foobar "
	}
	set y "foobar"
	set y "$y $y $y $y $y $y $y $y $y $y"
	set y "$y $y $y $y $y $y $y $y $y $y"
	set y "$y $y $y $y $y $y $y $y $y $y "
	expr {$x == $y}
219
220
221
222
223
224
225
226

227
228
229
230
231
232
233
219
220
221
222
223
224
225

226
227
228
229
230
231
232
233







-
+







		return "element $i should have been \"item $i\", was \"$j\""
	    }
	}
	return ok
    }
} -body {
    set x ""
    for {set i 0} {$i < 300} {set i [expr $i+1]} {
    for {set i 0} {$i < 300} {incr i} {
	lappend x "item $i"
    }
    check $x 300
} -cleanup {
    unset -nocomplain x
    catch {rename check ""}
} -result ok
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
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







-
+














-
+





-
+





-
+












-
+





-
+






-
+





-
+





-
+





-
+





-
+





-
+





-
+





-
+




-
+








test appendComp-7.1 {lappendComp-created var and error in trace on that var} -setup {
    catch {rename foo ""}
    unset -nocomplain x
} -body {
    proc bar {} {
	global x
	trace variable x w foo
	trace add variable x write foo
	proc foo {} {global x; unset x}
	catch {lappend x 1}
	proc foo {args} {global x; unset x}
	info exists x
	set x
	lappend x 1
	list [info exists x] [catch {set x} msg] $msg
    }
    bar
} -result {0 1 {can't read "x": no such variable}}
test appendComp-7.2 {lappend var triggers read trace, index var} -setup {
    unset -nocomplain ::result
} -body {
    proc bar {} {
	trace variable myvar r foo
	trace add variable myvar read foo
	proc foo {args} {append ::result $args}
	lappend myvar a
	return $::result
    }
    bar
} -result {myvar {} r} -constraints {bug-3057639}
} -result {myvar {} read} -constraints {bug-3057639}
test appendComp-7.3 {lappend var triggers read trace, stack var} -setup {
    unset -nocomplain ::result
    unset -nocomplain ::myvar
} -body {
    proc bar {} {
	trace variable ::myvar r foo
	trace add variable ::myvar read foo
	proc foo {args} {append ::result $args}
	lappend ::myvar a
	return $::result
    }
    bar
} -result {::myvar {} r} -constraints {bug-3057639}
test appendComp-7.4 {lappend var triggers read trace, array var} -setup {
    unset -nocomplain ::result
} -body {
    # The behavior of read triggers on lappend changed in 8.0 to not trigger
    # them. Maybe not correct, but been there a while.
    proc bar {} {
	trace variable myvar r foo
	trace add variable myvar read foo
	proc foo {args} {append ::result $args}
	lappend myvar(b) a
	return $::result
    }
    bar
} -result {myvar b r} -constraints {bug-3057639}
} -result {myvar b read} -constraints {bug-3057639}
test appendComp-7.5 {lappend var triggers read trace, array var} -setup {
    unset -nocomplain ::result
} -body {
    # The behavior of read triggers on lappend changed in 8.0 to not trigger
    # them. Maybe not correct, but been there a while.
    proc bar {} {
	trace variable myvar r foo
	trace add variable myvar read foo
	proc foo {args} {append ::result $args}
	lappend myvar(b) a b
	return $::result
    }
    bar
} -result {myvar b r}
} -result {myvar b read}
test appendComp-7.6 {lappend var triggers read trace, array var exists} -setup {
    unset -nocomplain ::result
} -body {
    proc bar {} {
	set myvar(0) 1
	trace variable myvar r foo
	trace add variable myvar read foo
	proc foo {args} {append ::result $args}
	lappend myvar(b) a
	return $::result
    }
    bar
} -result {myvar b r} -constraints {bug-3057639}
} -result {myvar b read} -constraints {bug-3057639}
test appendComp-7.7 {lappend var triggers read trace, array stack var} -setup {
    unset -nocomplain ::myvar
    unset -nocomplain ::result
} -body {
    proc bar {} {
	trace variable ::myvar r foo
	trace add variable ::myvar read foo
	proc foo {args} {append ::result $args}
	lappend ::myvar(b) a
	return $::result
    }
    bar
} -result {::myvar b r} -constraints {bug-3057639}
} -result {::myvar b read} -constraints {bug-3057639}
test appendComp-7.8 {lappend var triggers read trace, array stack var} -setup {
    unset -nocomplain ::myvar
    unset -nocomplain ::result
} -body {
    proc bar {} {
	trace variable ::myvar r foo
	trace add variable ::myvar read foo
	proc foo {args} {append ::result $args}
	lappend ::myvar(b) a b
	return $::result
    }
    bar
} -result {::myvar b r}
} -result {::myvar b read}
test appendComp-7.9 {append var does not trigger read trace} -setup {
    unset -nocomplain ::result
} -body {
    proc bar {} {
	trace variable myvar r foo
	trace add variable myvar read foo
	proc foo {args} {append ::result $args}
	append myvar a
	info exists ::result
    }
    bar
} -result {0}

380
381
382
383
384
385
386
387

388
389
390
391
392
393
394
380
381
382
383
384
385
386

387
388
389
390
391
392
393
394







-
+







# Note also the tests above now constrained by bug-3057639, these changed
# behaviour with the triggering of read traces in bc mode gone.

# Going back to the tests below. The direct-eval tests are ok before and after
# patch (no read traces run for lappend, append). The compiled tests are
# failing for lappend (9.0/1) before the patch, showing how it invokes read
# traces in the compiled path. The append tests are good (9.2/3). After the
# patch the failues are gone.
# patch the failures are gone.

test appendComp-9.0 {bug 3057639, lappend compiled, read trace on non-existing array variable element} -setup {
    unset -nocomplain myvar
    array set myvar {}
} -body {
    proc nonull {var key val} {
	upvar 1 $var lvar

Changes to tests/apply.test.

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
30
31
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
30
31
32
33
34
35






-
-
-
-
+
+
+
+








+
+






+
+







# Commands covered:  apply
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2005-2006 Miguel Sofer
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2005-2006 Miguel Sofer
#
# 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]]

if {[info commands ::apply] eq {}} {
    return
}

testConstraint memory [llength [info commands memory]]
testConstraint applylambda [llength [info commands testapplylambda]]


# Tests for wrong number of arguments

test apply-1.1 {not enough arguments} -returnCodes error -body {
    apply
} -result {wrong # args: should be "apply lambdaExpr ?arg ...?"}

301
302
303
304
305
306
307







308
309
310
311
312
313
314
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325







+
+
+
+
+
+
+







	set end [getbytes]
    }
    set leakedBytes [expr {$end - $tmp}]
} -cleanup {
    rename getbytes {}
    unset -nocomplain end i x tmp leakedBytes
} -result 0

# Tests for specific bugs
test apply-10.1 {Test for precompiled bytecode body} -constraints {
    applylambda
} -body {
    testapplylambda
} -result 42

# Tests for the avoidance of recompilation

# cleanup

namespace delete testApply

Changes to tests/assemble.test.

1
2
3
4
5
6


7
8
9
10
11
12
13
1
2
3
4


5
6
7
8
9
10
11
12
13




-
-
+
+







# assemble.test --
#
#	Test suite for the 'tcl::unsupported::assemble' command
#
# Copyright (c) 2010 by Ozgur Dogan Ugurlu.
# Copyright (c) 2010 by Kevin B. Kenny.
# Copyright © 2010 Ozgur Dogan Ugurlu.
# Copyright © 2010 Kevin B. Kenny.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#-----------------------------------------------------------------------------

# Commands covered: assemble

137
138
139
140
141
142
143

144
145
146
147
148
149
150
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151







+







	    assemble
	}
	x
    }
    -returnCodes error
    -match glob
    -result {wrong # args:*}
    -cleanup {rename x {}}
}
test assemble-3.2 {wrong # args, compiled path} {
    -body {
	proc x {} {
	    assemble too many
	}
	x
231
232
233
234
235
236
237

238
239
240
241
242
243
244
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246







+







	    assemble {
		[x]
	    }
	}
	list [catch {x} result] $result $::errorCode
    }
    -result {1 {assembly code may not contain substitutions} {TCL ASSEM NOSUBST}}
    -cleanup {rename x {}}
}
test assemble-5.4 {backslash substitution} {
    -body {
	proc x {} {
	    assemble {
		p\x75sh\
		    hello\ world
275
276
277
278
279
280
281
282
283
284



285
286
287
288
289
290
291
277
278
279
280
281
282
283



284
285
286
287
288
289
290
291
292
293







-
-
-
+
+
+







	eval [list assemble {push hello}]
    }
    -result hello
}
test assemble-6.4 {push4} {
    -body {
	proc x {} "
            [fillTables]
            assemble {push hello}
        "
	    [fillTables]
	    assemble {push hello}
	"
	x
    }
    -cleanup {
	rename x {}
    }
    -result hello
}
618
619
620
621
622
623
624

625
626
627
628
629
630
631
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634







+







	    assemble {
		push {2 1}; push i; load l; lsetList
	    }
	}
	x
    }
    -result {{a b} {c d} {e i} {g h}}
    -cleanup {rename x {}}
}
test assemble-7.25 {lshift} {
    -body {
	assemble {push 16; push 4; lshift}
    }
    -result 256
}
765
766
767
768
769
770
771
772

773
774
775
776
777
778
779
768
769
770
771
772
773
774

775
776
777
778
779
780
781
782







-
+







test assemble-7.43 {uplus} {
    -body {
	assemble {
	    push NaN; uplus
	}
    }
    -returnCodes error
    -result {can't use non-numeric floating-point value "NaN" as operand of "+"}
    -result {cannot use non-numeric floating-point value "NaN" as operand of "+"}
}
test assemble-7.43.1 {tryCvtToNumeric} {
    -body {
	assemble {
	    push NaN; tryCvtToNumeric
	}
    }
859
860
861
862
863
864
865
866
867
868



869
870
871
872
873
874
875
862
863
864
865
866
867
868



869
870
871
872
873
874
875
876
877
878







-
-
-
+
+
+







    -result able
    -cleanup {rename x {}}
}
test assemble-8.7 {load4} {
    -body {
	proc x {a} "
	    [fillTables]
            set b \$a
            assemble {load b}
        "
	    set b \$a
	    assemble {load b}
	"
	x able
    }
    -result able
    -cleanup {rename x {}}
}
test assemble-8.8 {loadArray1} {
    -body {
884
885
886
887
888
889
890
891

892
893
894
895
896
897
898
887
888
889
890
891
892
893

894
895
896
897
898
899
900
901







-
+







    }
    -result charlie
    -cleanup {rename x {}}
}
test assemble-8.9 {loadArray4} {
    -body "
	proc x {} {
            [fillTables]
	    [fillTables]
	    set able(baker) charlie
	    assemble {
		push baker
		loadArray able
	    }
	}
	x
912
913
914
915
916
917
918
919

920
921
922
923
924
925
926
915
916
917
918
919
920
921

922
923
924
925
926
927
928
929







-
+







    }
    -result {hello, world}
    -cleanup {rename x {}}
}
test assemble-8.11 {append4} {
    -body {
	proc x {} "
            [fillTables]
	    [fillTables]
	    set y {hello, }
	    assemble {
		push world; append y
	    }
	"
	x
    }
939
940
941
942
943
944
945
946

947
948
949
950
951
952
953
942
943
944
945
946
947
948

949
950
951
952
953
954
955
956







-
+







    }
    -result {hello, world}
    -cleanup {rename x {}}
}
test assemble-8.13 {appendArray4} {
    -body {
	proc x {} "
            [fillTables]
	    [fillTables]
	    set y(z) {hello, }
	    assemble {
		push z; push world; appendArray y
	    }
	"
	x
    }
966
967
968
969
970
971
972
973

974
975
976
977
978
979
980
969
970
971
972
973
974
975

976
977
978
979
980
981
982
983







-
+







    }
    -result {hello, world}
    -cleanup {rename x {}}
}
test assemble-8.15 {lappend4} {
    -body {
	proc x {} "
            [fillTables]
	    [fillTables]
	    set y {hello,}
	    assemble {
		push world; lappend y
	    }
	"
	x
    }
993
994
995
996
997
998
999
1000

1001
1002
1003
1004
1005
1006
1007
996
997
998
999
1000
1001
1002

1003
1004
1005
1006
1007
1008
1009
1010







-
+







    }
    -result {hello, world}
    -cleanup {rename x {}}
}
test assemble-8.17 {lappendArray4} {
    -body {
	proc x {} "
            [fillTables]
	    [fillTables]
	    set y(z) {hello,}
	    assemble {
		push z; push world; lappendArray y
	    }
	"
	x
    }
1020
1021
1022
1023
1024
1025
1026
1027

1028
1029
1030
1031

1032
1033
1034
1035
1036
1037
1038
1023
1024
1025
1026
1027
1028
1029

1030
1031
1032
1033

1034
1035
1036
1037
1038
1039
1040
1041







-
+



-
+







    }
    -result {test}
    -cleanup {rename x {}}
}
test assemble-8.19 {store4} {
    -body {
	proc x {} "
            [fillTables]
	    [fillTables]
	    assemble {
		push test; store y
	    }
            set y
	    set y
	"
	x
    }
    -result test
    -cleanup {rename x {}}
}
test assemble-8.20 {storeArray1} {
1047
1048
1049
1050
1051
1052
1053
1054

1055
1056
1057
1058
1059
1060
1061
1050
1051
1052
1053
1054
1055
1056

1057
1058
1059
1060
1061
1062
1063
1064







-
+







    }
    -result test
    -cleanup {rename x {}}
}
test assemble-8.21 {storeArray4} {
    -body {
	proc x {} "
            [fillTables]
	    [fillTables]
	    assemble {
		push z; push test; storeArray y
	    }
	"
	x
    }
    -result test
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354



1355
1356
1357
1358
1359
1360
1361
1348
1349
1350
1351
1352
1353
1354



1355
1356
1357
1358
1359
1360
1361
1362
1363
1364







-
-
-
+
+
+







    -result 8
    -cleanup {rename x {}}
}
test assemble-12.6 {incr, stupid stack restriction} {
    -body {
	proc x {} "
	    [fillTables]
            set y 5
            assemble {push 3; incr y}
        "
	    set y 5
	    assemble {push 3; incr y}
	"
	list [catch {x} result] $result $errorCode
    }
    -result {1 {operand does not fit in one byte} {TCL ASSEM 1BYTE}}
    -cleanup {unset result; rename x {}}
}

# assemble-13 -- ASSEM_LVT1_SINT1 - incrImm and incrArrayImm
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445



1446
1447
1448
1449
1450
1451
1452
1439
1440
1441
1442
1443
1444
1445



1446
1447
1448
1449
1450
1451
1452
1453
1454
1455







-
-
-
+
+
+







    -result 8
    -cleanup {rename x {}}
}
test assemble-13.9 {incrImm, stupid stack restriction} {
    -body {
	proc x {} "
	    [fillTables]
            set y 5
            assemble {incrImm y 3}
        "
	    set y 5
	    assemble {incrImm y 3}
	"
	list [catch {x} result] $result $errorCode
    }
    -result {1 {operand does not fit in one byte} {TCL ASSEM 1BYTE}}
    -cleanup {unset result; rename x {}}
}

# assemble-14 -- ASSEM_SINT1 (incrArrayStkImm and incrStkImm)
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
3134
3135
3136
3137
3138
3139
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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145







+


















+



















+







	}
	catch {x 1}
	set errorInfo
    }
    -match glob
    -result {inconsistent stack depths on two execution paths
    ("assemble" body, line 10)*}
    -cleanup {rename x {}}
}
test assemble-41.2 {Inconsistent stack, jumptable and default} {
    -body {
	proc x {y} {
	    assemble {
		load y
		jumpTable {0 else}
		push 0
	      label else
		pop
	    }
	}
	catch {x 1}
	set errorInfo
    }
    -match glob
    -result {inconsistent stack depths on two execution paths
    ("assemble" body, line 6)*}
    -cleanup {rename x {}}
}
test assemble-41.3 {Inconsistent stack, two legs of jumptable} {
    -body {
	proc x {y} {
	    assemble {
		load y
		jumpTable {0 no 1 yes}
		label no
		push 0
		label yes
		pop
	    }
	}
	catch {x 1}
	set errorInfo
    }
    -match glob
    -result {inconsistent stack depths on two execution paths
    ("assemble" body, line 7)*}
    -cleanup {rename x {}}
}

test assemble-50.1 {Ulam's 3n+1 problem, TAL implementation} {
    -body {
	proc ulam {n} {
	    assemble {
		load n;		# max
3178
3179
3180
3181
3182
3183
3184

3185
3186
3187
3188
3189
3190
3191
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198







+







	set result {}
	for {set i 1} {$i < 30} {incr i} {
	    lappend result [ulam $i]
	}
	set result
    }
    -result {1 2 16 4 16 16 52 8 52 16 52 16 40 52 160 16 52 52 88 20 64 52 160 24 88 40 9232 52 88}
    -cleanup {rename ulam {}}
}

test assemble-51.1 {memory leak testing} memory {
    leaktest {
	apply {{} {assemble {push hello}}}
    }
} 0
3333
3334
3335
3336
3337
3338
3339




3340
3341
3342
3343
3344
3345
3346
3347
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358







+
+
+
+








	    pop
	}
    }}
} {};				# must not crash

rename fillTables {}
rename assemble {}
if {[testConstraint memory]} {
    rename getbytes {}
    rename leaktest {}
}

::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:

Changes to tests/assocd.test.

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
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






-
-
-
+
+
+










-
+







# This file tests the AssocData facility of Tcl
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1994 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1994 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testgetassocdata [llength [info commands testgetassocdata]]
testConstraint testsetassocdata [llength [info commands testsetassocdata]]
testConstraint testdelassocdata [llength [info commands testdelassocdata]]

test assocd-1.1 {testing setting assoc data} testsetassocdata {
   testsetassocdata a 1

Changes to tests/async.test.

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
30
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
30
31






-
-
-
+
+
+










-
+

+

-
+







# Commands covered:  none
#
# This file contains a collection of tests for Tcl_AsyncCreate and related
# library procedures.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint thread [expr {0 == [catch {package require Thread 2.7-}]}]
testConstraint testasync [llength [info commands testasync]]
testConstraint knownMsvcBug [expr {![info exists ::env(TRAVIS_OS_NAME)] || ![string match windows $::env(TRAVIS_OS_NAME)]}]
testConstraint knownMsvcBug [string match msvc-* [tcl::build-info compiler]]

proc async1 {result code} {
    global aresult acode
    set aresult $result
    set acode $code
    return "new result"
}
145
146
147
148
149
150
151
152

153
154
155
156
157
158
159
146
147
148
149
150
151
152

153
154
155
156
157
158
159
160







-
+








test async-3.1 {deleting handlers} testasync {
    set x {}
    list [catch {testasync mark $hm2 "foobar" 5} msg] $msg $x
} {3 del2 {0 0 0 del1 del2}}

test async-4.1 {async interrupting bytecode sequence} -constraints {
    testasync
    testasync thread
} -setup {
    set hm [testasync create async3]
    proc nothing {} {
	# empty proc
    }
} -body {
    apply {{handle} {
174
175
176
177
178
179
180
181

182
183
184
185
186
187
188
175
176
177
178
179
180
181

182
183
184
185
186
187
188
189







-
+







} -result {test pattern} -cleanup {
    # give other threads some time to go way so that valgrind doesn't pick up
    # "still reachable" cases from early thread termination
    after 100
    testasync delete $hm
}
test async-4.2 {async interrupting straight bytecode sequence} -constraints {
    testasync
    testasync thread
} -setup {
    set hm [testasync create async3]
} -body {
    apply {{handle} {
	global aresult
	set aresult {Async event not delivered}
	testasync marklater $handle
199
200
201
202
203
204
205
206

207
208
209
210
211
212
213
200
201
202
203
204
205
206

207
208
209
210
211
212
213
214







-
+







} -result {test pattern} -cleanup {
    # give other threads some time to go way so that valgrind doesn't pick up
    # "still reachable" cases from early thread termination
    after 100
    testasync delete $hm
}
test async-4.3 {async interrupting loop-less bytecode sequence} -constraints {
    testasync knownMsvcBug
    testasync thread knownMsvcBug
} -setup {
    set hm [testasync create async3]
} -body {
    apply [list {handle} [concat {
	global aresult
	set aresult {Async event not delivered}
	testasync marklater $handle

Changes to tests/autoMkindex.test.

1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







# Commands covered:  auto_mkindex auto_import
#
# This file contains tests related to autoloading and generating the
# autoloading index.
#
# Copyright (c) 1998  Lucent Technologies, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1998  Lucent Technologies, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
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
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







-
+







-
-
+
+
















-
+


-
-
-
+
+
+







#           proc another {args} { ... }
#       }
#   }
#
# Note that procedures and itcl class definitions can be nested inside of
# namespaces.
#
# Copyright (c) 1993-1998  Lucent Technologies, Inc.
# Copyright © 1993-1998  Lucent Technologies, Inc.

# This shouldn't cause any problems
namespace import -force blt::*

# Should be able to handle "proc" definitions, even if they are preceded by
# white space.

proc normal {x y} {return [expr $x+$y]}
  proc indented {x y} {return [expr $x+$y]}
proc normal {x y} {return [expr {$x+$y}]}
  proc indented {x y} {return [expr {$x+$y}]}

#
# Should be able to handle proc declarations within namespaces, even if they
# have explicit namespace paths.
#
namespace eval buried {
    proc inside {args} {return "inside: $args"}

    namespace export pub_*
    proc pub_one {args} {return "one: $args"}
    proc pub_two {args} {return "two: $args"}
}
proc buried::within {args} {return "within: $args"}

namespace eval buried {
    namespace eval under {
        proc neath {args} {return "neath: $args"}
	proc neath {args} {return "neath: $args"}
    }
    namespace eval ::buried {
        proc relative {args} {return "relative: $args"}
        proc ::top {args} {return "top: $args"}
        proc ::buried::explicit {args} {return "explicit: $args"}
	proc relative {args} {return "relative: $args"}
	proc ::top {args} {return "top: $args"}
	proc ::buried::explicit {args} {return "explicit: $args"}
    }
}

# With proper hooks, we should be able to support other commands that create
# procedures

proc buried::myproc {name body args} {
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
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







-
+





-
-
-
-
-
-
-
+
+
+
+
+
+
+












-
-
-
-
-
-
-
+
+
+
+
+
+
+







    file delete tclIndex
    file exists tclIndex
} {0}
test autoMkindex-1.2 {build tclIndex based on a test file} {
    auto_mkindex . autoMkindex.tcl
    file exists tclIndex
} {1}
set element "{source [file join . autoMkindex.tcl]}"
set element "{source -encoding utf-8 [file join . autoMkindex.tcl]}"
test autoMkindex-1.3 {examine tclIndex} -setup {
    file delete tclIndex
} -body {
    auto_mkindex . autoMkindex.tcl
    namespace eval tcl_autoMkindex_tmp {
        set dir "."
        variable auto_index
        source tclIndex
        set ::result ""
        foreach elem [lsort [array names auto_index]] {
            lappend ::result [list $elem $auto_index($elem)]
        }
	set dir "."
	variable auto_index
	source tclIndex
	set ::result ""
	foreach elem [lsort [array names auto_index]] {
	    lappend ::result [list $elem $auto_index($elem)]
	}
    }
    return $result
} -cleanup {
    namespace delete tcl_autoMkindex_tmp
} -result "{::buried::explicit $element} {::buried::inside $element} {{::buried::my proc} $element} {::buried::mycmd1 $element} {::buried::mycmd4 $element} {::buried::myproc $element} {::buried::pub_one $element} {::buried::pub_two $element} {::buried::relative $element} {::buried::under::neath $element} {::buried::within $element} {::parent::child::test $element} {indented $element} {normal $element} {top $element}"

test autoMkindex-2.1 {commands on the autoload path can be imported} -setup {
    file delete tclIndex
    interp create child
} -body {
    auto_mkindex . autoMkindex.tcl
    child eval {
        namespace eval blt {}
        set auto_path [linsert $auto_path 0 .]
        set info [list [catch {namespace import buried::*} result] $result]
        foreach name [lsort [info commands pub_*]] {
            lappend info $name [namespace origin $name]
        }
        return $info
	namespace eval blt {}
	set auto_path [linsert $auto_path 0 .]
	set info [list [catch {namespace import buried::*} result] $result]
	foreach name [lsort [info commands pub_*]] {
	    lappend info $name [namespace origin $name]
	}
	return $info
    }
} -cleanup {
    interp delete child
} -result "0 {} pub_one ::buried::pub_one pub_two ::buried::pub_two"

# Test auto_mkindex hooks

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
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







-
+



-
-
-
-
-
-
-
+
+
+
+
+
+
+















-
+



-
-
-
-
-
-
-
+
+
+
+
+
+
+







test autoMkindex-3.2 {auto_mkindex_parser::command} -setup {
    file delete tclIndex
} -body {
    auto_mkindex_parser::command buried::myproc {name args} {
	variable index
	variable scriptFile
	append index [list set auto_index([fullname $name])] \
		" \[list source \[file join \$dir [list $scriptFile]\]\]\n"
		" \[list source -encoding utf-8 \[file join \$dir [list $scriptFile]\]\]\n"
    }
    auto_mkindex . autoMkindex.tcl
    namespace eval tcl_autoMkindex_tmp {
        set dir "."
        variable auto_index
        source tclIndex
        set ::result ""
        foreach elem [lsort [array names auto_index]] {
            lappend ::result [list $elem $auto_index($elem)]
        }
	set dir "."
	variable auto_index
	source tclIndex
	set ::result ""
	foreach elem [lsort [array names auto_index]] {
	    lappend ::result [list $elem $auto_index($elem)]
	}
	return $::result
    }
} -cleanup {
    namespace delete tcl_autoMkindex_tmp
    # Reset initCommands to avoid trashing other tests
    AutoMkindexTestReset
} -result "{::buried::explicit $element} {::buried::inside $element} {{::buried::my proc} $element} {::buried::mycmd1 $element} {::buried::mycmd2 $element} {::buried::mycmd4 $element} {::buried::myproc $element} {::buried::pub_one $element} {::buried::pub_two $element} {::buried::relative $element} {::buried::under::neath $element} {::buried::within $element} {::parent::child::test $element} {indented $element} {mycmd3 $element} {normal $element} {top $element}"
test autoMkindex-3.3 {auto_mkindex_parser::command} -setup {
    file delete tclIndex
} -constraints {knownBug} -body {
    auto_mkindex_parser::command {buried::my proc} {name args} {
	variable index
	variable scriptFile
	puts "my proc $name"
	append index [list set auto_index([fullname $name])] \
		" \[list source \[file join \$dir [list $scriptFile]\]\]\n"
		" \[list source -encoding utf-8 \[file join \$dir [list $scriptFile]\]\]\n"
    }
    auto_mkindex . autoMkindex.tcl
    namespace eval tcl_autoMkindex_tmp {
        set dir "."
        variable auto_index
        source tclIndex
        set ::result ""
        foreach elem [lsort [array names auto_index]] {
            lappend ::result [list $elem $auto_index($elem)]
        }
	set dir "."
	variable auto_index
	source tclIndex
	set ::result ""
	foreach elem [lsort [array names auto_index]] {
	    lappend ::result [list $elem $auto_index($elem)]
	}
    }
    list [lsearch -inline $::result *mycmd4*] \
	[lsearch -inline $::result *mycmd5*] \
	[lsearch -inline $::result *mycmd6*]
} -cleanup {
    namespace delete tcl_autoMkindex_tmp
    # Reset initCommands to avoid trashing other tests
262
263
264
265
266
267
268
269

270
271
272
273
274
275
276
262
263
264
265
266
267
268

269
270
271
272
273
274
275
276







-
+







	if {[string match {set auto_index*} $r]} {
	    lappend dat $r
	}
    }
    set result [lsort $dat]
    close $f
    set result
} {{set auto_index(::wok::commands) [list source [file join $dir ensemblecommands.tcl]]} {set auto_index(::wok::vars) [list source [file join $dir ensemblecommands.tcl]]} {set auto_index(wok) [list source [file join $dir ensemblecommands.tcl]]}}
} {{set auto_index(::wok::commands) [list source -encoding utf-8 [file join $dir ensemblecommands.tcl]]} {set auto_index(::wok::vars) [list source -encoding utf-8 [file join $dir ensemblecommands.tcl]]} {set auto_index(wok) [list source -encoding utf-8 [file join $dir ensemblecommands.tcl]]}}
removeFile ensemblecommands.tcl

test autoMkindex-4.1 {platform independent source commands} -setup {
    file delete tclIndex
    makeDirectory pkg
    makeFile {
	package provide football 1.0
299
300
301
302
303
304
305
306

307
308
309
310
311
312
313
299
300
301
302
303
304
305

306
307
308
309
310
311
312
313







-
+







    auto_mkindex . pkg/samename.tcl
    set f [open tclIndex r]
    lsort [lrange [split [string trim [read $f]] "\n"] end-1 end]
} -cleanup {
    catch {close $f}
    removeFile [file join pkg samename.tcl]
    removeDirectory pkg
} -result {{set auto_index(::college::team) [list source [file join $dir pkg samename.tcl]]} {set auto_index(::pro::team) [list source [file join $dir pkg samename.tcl]]}}
} -result {{set auto_index(::college::team) [list source -encoding utf-8 [file join $dir pkg samename.tcl]]} {set auto_index(::pro::team) [list source -encoding utf-8 [file join $dir pkg samename.tcl]]}}

test autoMkindex-5.1 {escape magic tcl chars in general code} -setup {
    file delete tclIndex
    makeDirectory pkg
    makeFile {
	set dollar1 "this string contains an unescaped dollar sign -> \\$foo"
	set dollar2 \
323
324
325
326
327
328
329
330

331
332
333
334
335
336
337
323
324
325
326
327
328
329

330
331
332
333
334
335
336
337







-
+







    auto_mkindex . pkg/magicchar.tcl
    set f [open tclIndex r]
    lindex [split [string trim [read $f]] "\n"] end
} -cleanup {
    catch {close $f}
    removeFile [file join pkg magicchar.tcl]
    removeDirectory pkg
} -result {set auto_index(testProc) [list source [file join $dir pkg magicchar.tcl]]}
} -result {set auto_index(testProc) [list source -encoding utf-8 [file join $dir pkg magicchar.tcl]]}
test autoMkindex-5.2 {correctly locate auto loaded procs with []} -setup {
    file delete tclIndex
    makeDirectory pkg
    makeFile {
	proc {[magic mojo proc]} {} {}
    } [file join pkg magicchar2.tcl]
    set result {}

Changes to tests/basic.test.

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
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
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
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











-
-
+
+










-
+

















-
-
-
-
-
+
+
+
+
+


-
+







# This file contains tests for the tclBasic.c source file. Tests appear in
# the same order as the C code that they test. The set of tests is
# currently incomplete since it currently includes only new tests for
# code changed for the addition of Tcl namespaces. Other variable-
# related tests appear in several other test files including
# assocd.test, cmdInfo.test, eval.test, expr.test, interp.test,
# and trace.test.
#
# Sourcing this file into Tcl runs the tests and generates output for
# errors. No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testevalex [llength [info commands testevalex]]
testConstraint testcmdtoken [llength [info commands testcmdtoken]]
testConstraint testcreatecommand [llength [info commands testcreatecommand]]
testConstraint exec [llength [info commands exec]]

catch {namespace delete test_ns_basic}
catch {interp delete test_interp}
catch {rename p ""}
catch {rename q ""}
catch {rename cmd ""}
unset -nocomplain x

test basic-1.1 {Tcl_CreateInterp, creates interp's global namespace} {
    catch {interp delete test_interp}
    interp create test_interp
    interp eval test_interp {
        namespace eval test_ns_basic {
            proc p {} {
                return [namespace current]
            }
        }
	namespace eval test_ns_basic {
	    proc p {} {
		return [namespace current]
	    }
	}
    }
    list [interp eval test_interp {test_ns_basic::p}] \
         [interp delete test_interp]
	 [interp delete test_interp]
} {::test_ns_basic {}}

test basic-2.1 {TclHideUnsafeCommands} {emptyTest} {
} {}

test basic-3.1 {Tcl_CallWhenDeleted: see dcall.test} {emptyTest} {
} {}
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
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
442
443
444
445
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
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
442
443
444
445







-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
+
+
+






-
-
-
+
+
+



-
-
-
-
-
+
+
+
+
+








-
-
-
-
-
+
+
+
+
+



-
+






-
+


-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+


-
-
-
-
-
+
+
+
+
+






-
+


-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+


-
-
-
-
-
+
+
+
+
+





-
+


-
+


-
-
-
-
-
-
+
+
+
+
+
+




















-
+


-
+



-
+


-
+










-
+


-
+






-
-
-
+
+
+


-
-
+
+








-
-
-
+
+
+


-
-
+
+




-
-
-
+
+
+





-
-
-
-
-
-
-
+
+
+
+
+
+
+



-
-
-
+
+
+








-
+


-
+


-
-
-
+
+
+


-
-
+
+











-
-
+
+


-
-
+
+





-
-
+
+




-
+








-
-
-
+
+
+


-
-
-
+
+
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+











-
-
-
+
+
+



-
-
-
-
+
+
+
+


-
-
+
+





-
+


-
-
-
-
-
-
+
+
+
+
+
+


-
-
+
+





-
-
+
+


-
-
-
-
+
+
+
+


-
-
-
-
+
+
+
+







test basic-9.1 {Tcl_DeleteInterp: see interp.test} {emptyTest} {
} {}

test basic-10.1 {DeleteInterpProc, destroys interp's global namespace} {
    catch {interp delete test_interp}
    interp create test_interp
    interp eval test_interp {
        namespace eval test_ns_basic {
            namespace export p
            proc p {} {
                return [namespace current]
            }
        }
        namespace eval test_ns_2 {
            namespace import ::test_ns_basic::p
            variable v 27
            proc q {} {
                variable v
                return "[p] $v"
            }
        }
	namespace eval test_ns_basic {
	    namespace export p
	    proc p {} {
		return [namespace current]
	    }
	}
	namespace eval test_ns_2 {
	    namespace import ::test_ns_basic::p
	    variable v 27
	    proc q {} {
		variable v
		return "[p] $v"
	    }
	}
    }
    list [interp eval test_interp {test_ns_2::q}] \
         [interp eval test_interp {namespace delete ::}] \
         [catch {interp eval test_interp {set a 123}} msg] $msg \
         [interp delete test_interp]
	 [interp eval test_interp {namespace delete ::}] \
	 [catch {interp eval test_interp {set a 123}} msg] $msg \
	 [interp delete test_interp]
} {{::test_ns_basic 27} {} 1 {invalid command name "set"} {}}

test basic-11.1 {HiddenCmdsDeleteProc, invalidate cached refs to deleted hidden cmd} {
    catch {interp delete test_interp}
    interp create test_interp
    interp eval test_interp {
        proc p {} {
            return 27
        }
	proc p {} {
	    return 27
	}
    }
    interp alias {} localP test_interp p
    list [interp eval test_interp {p}] \
         [localP] \
         [test_interp hide p] \
         [catch {localP} msg] $msg \
         [interp delete test_interp] \
         [catch {localP} msg] $msg
	 [localP] \
	 [test_interp hide p] \
	 [catch {localP} msg] $msg \
	 [interp delete test_interp] \
	 [catch {localP} msg] $msg
} {27 27 {} 1 {invalid command name "p"} {} 1 {invalid command name "localP"}}

# NB: More tests about hide/expose are found in interp.test

test basic-12.1 {Tcl_HideCommand, names of hidden cmds can't have namespace qualifiers} {
    catch {interp delete test_interp}
    interp create test_interp
    interp eval test_interp {
        namespace eval test_ns_basic {
            proc p {} {
                return [namespace current]
            }
        }
	namespace eval test_ns_basic {
	    proc p {} {
		return [namespace current]
	    }
	}
    }
    list [catch {test_interp hide test_ns_basic::p x} msg] $msg \
	 [catch {test_interp hide x test_ns_basic::p} msg1] $msg1 \
         [interp delete test_interp]
	 [interp delete test_interp]
} {1 {can only hide global namespace commands (use rename then hide)} 1 {cannot use namespace qualifiers in hidden command token (rename)} {}}

test basic-12.2 {Tcl_HideCommand, a hidden cmd remembers its containing namespace} {
    catch {namespace delete test_ns_basic}
    catch {rename cmd ""}
    proc cmd {} {   ;# note that this is global
        return [namespace current]
	return [namespace current]
    }
    namespace eval test_ns_basic {
        proc hideCmd {} {
            interp hide {} cmd
        }
        proc exposeCmd {} {
            interp expose {} cmd
        }
        proc callCmd {} {
            cmd
        }
	proc hideCmd {} {
	    interp hide {} cmd
	}
	proc exposeCmd {} {
	    interp expose {} cmd
	}
	proc callCmd {} {
	    cmd
	}
    }
    list [test_ns_basic::callCmd] \
         [test_ns_basic::hideCmd] \
         [catch {cmd} msg] $msg \
         [test_ns_basic::exposeCmd] \
         [test_ns_basic::callCmd] \
         [namespace delete test_ns_basic]
	 [test_ns_basic::hideCmd] \
	 [catch {cmd} msg] $msg \
	 [test_ns_basic::exposeCmd] \
	 [test_ns_basic::callCmd] \
	 [namespace delete test_ns_basic]
} {:: {} 1 {invalid command name "cmd"} {} :: {}}

test basic-13.1 {Tcl_ExposeCommand, a command stays in the global namespace and cannot go to another namespace} {
    catch {namespace delete test_ns_basic}
    catch {rename cmd ""}
    proc cmd {} {   ;# note that this is global
        return [namespace current]
	return [namespace current]
    }
    namespace eval test_ns_basic {
        proc hideCmd {} {
            interp hide {} cmd
        }
        proc exposeCmdFailing {} {
            interp expose {} cmd ::test_ns_basic::newCmd
        }
        proc exposeCmdWorkAround {} {
            interp expose {} cmd;
	proc hideCmd {} {
	    interp hide {} cmd
	}
	proc exposeCmdFailing {} {
	    interp expose {} cmd ::test_ns_basic::newCmd
	}
	proc exposeCmdWorkAround {} {
	    interp expose {} cmd;
	    rename cmd ::test_ns_basic::newCmd;
        }
        proc callCmd {} {
            cmd
        }
	}
	proc callCmd {} {
	    cmd
	}
    }
    list [test_ns_basic::callCmd] \
         [test_ns_basic::hideCmd] \
         [catch {test_ns_basic::exposeCmdFailing} msg] $msg \
         [test_ns_basic::exposeCmdWorkAround] \
         [test_ns_basic::newCmd] \
         [namespace delete test_ns_basic]
	 [test_ns_basic::hideCmd] \
	 [catch {test_ns_basic::exposeCmdFailing} msg] $msg \
	 [test_ns_basic::exposeCmdWorkAround] \
	 [test_ns_basic::newCmd] \
	 [namespace delete test_ns_basic]
} {:: {} 1 {cannot expose to a namespace (use expose to toplevel, then rename)} {} ::test_ns_basic {}}
test basic-13.2 {Tcl_ExposeCommand, invalidate cached refs to cmd now being exposed} {
    catch {rename p ""}
    catch {rename cmd ""}
    proc p {} {
        cmd
	cmd
    }
    proc cmd {} {
        return 42
	return 42
    }
    list [p] \
         [interp hide {} cmd] \
         [proc cmd {} {return Hello}] \
         [cmd] \
         [rename cmd ""] \
         [interp expose {} cmd] \
         [p]
	 [interp hide {} cmd] \
	 [proc cmd {} {return Hello}] \
	 [cmd] \
	 [rename cmd ""] \
	 [interp expose {} cmd] \
	 [p]
} {42 {} {} Hello {} {} 42}

test basic-14.1 {Tcl_CreateCommand, new cmd goes into a namespace specified in its name, if any} {testcreatecommand} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    list [testcreatecommand create] \
	 [test_ns_basic::createdcommand] \
	 [testcreatecommand delete]
} {{} {CreatedCommandProc in ::test_ns_basic} {}}
test basic-14.2 {Tcl_CreateCommand, namespace code ignore single ":"s in middle or end of names} {testcreatecommand} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    catch {rename value:at: ""}
    list [testcreatecommand create2] \
	 [value:at:] \
	 [testcreatecommand delete2]
} {{} {CreatedCommandProc2 in ::} {}}

test basic-15.1 {Tcl_CreateObjCommand, new cmd goes into a namespace specified in its name, if any} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_basic {}
    proc test_ns_basic::cmd {} {  ;# proc requires that ns already exist
        return [namespace current]
	return [namespace current]
    }
    list [test_ns_basic::cmd] \
         [namespace delete test_ns_basic]
	 [namespace delete test_ns_basic]
} {::test_ns_basic {}}
test basic-15.2 {Tcl_CreateObjCommand, Bug 0e4d88b650} -setup {
    proc deleter {ns args} {
        namespace delete $ns
	namespace delete $ns
    }
    namespace eval n {
        proc p {} {}
	proc p {} {}
    }
    trace add command n::p delete [list [namespace which deleter] [namespace current]::n]
} -body {
    proc n::p {} {}
} -cleanup {
    namespace delete n
    rename deleter {}
}


test basic-16.1 {TclInvokeStringCommand} {emptyTest} {
test basic-16.1 {InvokeStringCommand} {emptyTest} {
} {}

test basic-17.1 {TclInvokeObjCommand} {emptyTest} {
test basic-17.1 {InvokeObjCommand} {emptyTest} {
} {}

test basic-18.1 {TclRenameCommand, name of existing cmd can have namespace qualifiers} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    catch {rename cmd ""}
    namespace eval test_ns_basic {
        proc p {} {
            return "p in [namespace current]"
        }
	proc p {} {
	    return "p in [namespace current]"
	}
    }
    list [test_ns_basic::p] \
         [rename test_ns_basic::p test_ns_basic::q] \
         [test_ns_basic::q]
	 [rename test_ns_basic::p test_ns_basic::q] \
	 [test_ns_basic::q]
} {{p in ::test_ns_basic} {} {p in ::test_ns_basic}}
test basic-18.2 {TclRenameCommand, existing cmd must be found} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    list [catch {rename test_ns_basic::p test_ns_basic::q} msg] $msg
} {1 {can't rename "test_ns_basic::p": command doesn't exist}}
test basic-18.3 {TclRenameCommand, delete cmd if new name is empty} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_basic {
        proc p {} {
            return "p in [namespace current]"
        }
	proc p {} {
	    return "p in [namespace current]"
	}
    }
    list [info commands test_ns_basic::*] \
         [rename test_ns_basic::p ""] \
         [info commands test_ns_basic::*]
	 [rename test_ns_basic::p ""] \
	 [info commands test_ns_basic::*]
} {::test_ns_basic::p {} {}}
test basic-18.4 {TclRenameCommand, bad new name} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_basic {
        proc p {} {
            return "p in [namespace current]"
        }
	proc p {} {
	    return "p in [namespace current]"
	}
    }
    rename test_ns_basic::p :::george::martha
} {}
test basic-18.5 {TclRenameCommand, new name must not already exist} -setup {
    if {![llength [info commands :::george::martha]]} {
        catch {namespace delete {*}[namespace children :: test_ns_*]}
        namespace eval test_ns_basic {
            proc p {} {
                return "p in [namespace current]"
            }
        }
        rename test_ns_basic::p :::george::martha
	catch {namespace delete {*}[namespace children :: test_ns_*]}
	namespace eval test_ns_basic {
	    proc p {} {
		return "p in [namespace current]"
	    }
	}
	rename test_ns_basic::p :::george::martha
    }
} -body {
    namespace eval test_ns_basic {
        proc q {} {
            return 42
        }
	proc q {} {
	    return 42
	}
    }
    list [catch {rename test_ns_basic::q :::george::martha} msg] $msg
} -result {1 {can't rename to ":::george::martha": command already exists}}
test basic-18.6 {TclRenameCommand, check for command shadowing by newly renamed cmd} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    catch {rename p ""}
    catch {rename q ""}
    proc p {} {
        return "p in [namespace current]"
	return "p in [namespace current]"
    }
    proc q {} {
        return "q in [namespace current]"
	return "q in [namespace current]"
    }
    namespace eval test_ns_basic {
        proc callP {} {
            p
        }
	proc callP {} {
	    p
	}
    }
    list [test_ns_basic::callP] \
         [rename q test_ns_basic::p] \
         [test_ns_basic::callP]
	 [rename q test_ns_basic::p] \
	 [test_ns_basic::callP]
} {{p in ::} {} {q in ::test_ns_basic}}

test basic-19.1 {Tcl_SetCommandInfo} {emptyTest} {
} {}

test basic-20.1 {Tcl_GetCommandInfo, names for commands created inside namespaces} {testcmdtoken} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    catch {rename p ""}
    catch {rename q ""}
    unset -nocomplain x
    set x [namespace eval test_ns_basic::test_ns_basic2 {
        # the following creates a cmd in the global namespace
        testcmdtoken create p
	# the following creates a cmd in the global namespace
	testcmdtoken create p
    }]
    list [testcmdtoken name $x] \
         [rename ::p q] \
         [testcmdtoken name $x]
	 [rename ::p q] \
	 [testcmdtoken name $x]
} {{p ::p} {} {q ::q}}
test basic-20.2 {Tcl_GetCommandInfo, names for commands created outside namespaces} {testcmdtoken} {
    catch {rename q ""}
    set x [testcmdtoken create test_ns_basic::test_ns_basic2::p]
    list [testcmdtoken name $x] \
         [rename test_ns_basic::test_ns_basic2::p q] \
         [testcmdtoken name $x]
	 [rename test_ns_basic::test_ns_basic2::p q] \
	 [testcmdtoken name $x]
} {{p ::test_ns_basic::test_ns_basic2::p} {} {q ::q}}
test basic-20.3 {Tcl_GetCommandInfo, #-quoting} testcmdtoken {
    catch {rename \# ""}
    set x [testcmdtoken create \#]
    testcmdtoken name $x
    return [testcmdtoken name $x]
} {{#} ::#}

test basic-21.1 {Tcl_GetCommandName} {emptyTest} {
} {}

test basic-22.1 {Tcl_GetCommandFullName} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_basic1 {
        namespace export cmd*
        proc cmd1 {} {}
        proc cmd2 {} {}
	namespace export cmd*
	proc cmd1 {} {}
	proc cmd2 {} {}
    }
    namespace eval test_ns_basic2 {
        namespace export *
        namespace import ::test_ns_basic1::*
        proc p {} {}
	namespace export *
	namespace import ::test_ns_basic1::*
	proc p {} {}
    }
    namespace eval test_ns_basic3 {
        namespace import ::test_ns_basic2::*
        proc q {} {}
        list [namespace which -command foreach] \
             [namespace which -command q] \
             [namespace which -command p] \
             [namespace which -command cmd1] \
             [namespace which -command ::test_ns_basic2::cmd2]
	namespace import ::test_ns_basic2::*
	proc q {} {}
	list [namespace which -command foreach] \
	     [namespace which -command q] \
	     [namespace which -command p] \
	     [namespace which -command cmd1] \
	     [namespace which -command ::test_ns_basic2::cmd2]
    }
} {::foreach ::test_ns_basic3::q ::test_ns_basic3::p ::test_ns_basic3::cmd1 ::test_ns_basic2::cmd2}

test basic-23.1 {Tcl_DeleteCommand} {emptyTest} {
} {}

test basic-24.1 {Tcl_DeleteCommandFromToken, invalidate all compiled code if cmd has compile proc} {
    catch {interp delete test_interp}
    unset -nocomplain x
    interp create test_interp
    interp eval test_interp {
        proc useSet {} {
            return [set a 123]
        }
	proc useSet {} {
	    return [set a 123]
	}
    }
    set x [interp eval test_interp {useSet}]
    interp eval test_interp {
        rename set ""
        proc set {args} {
            return "set called with $args"
        }
	rename set ""
	proc set {args} {
	    return "set called with $args"
	}
    }
    list $x \
         [interp eval test_interp {useSet}] \
         [interp delete test_interp]
	 [interp eval test_interp {useSet}] \
	 [interp delete test_interp]
} {123 {set called with a 123} {}}
test basic-24.2 {Tcl_DeleteCommandFromToken, deleting commands changes command epoch} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    catch {rename p ""}
    proc p {} {
        return "global p"
	return "global p"
    }
    namespace eval test_ns_basic {
        proc p {} {
            return "namespace p"
        }
        proc callP {} {
            p
        }
	proc p {} {
	    return "namespace p"
	}
	proc callP {} {
	    p
	}
    }
    list [test_ns_basic::callP] \
         [rename test_ns_basic::p ""] \
         [test_ns_basic::callP]
	 [rename test_ns_basic::p ""] \
	 [test_ns_basic::callP]
} {{namespace p} {} {global p}}
test basic-24.3 {Tcl_DeleteCommandFromToken, delete imported cmds that refer to a deleted cmd} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    catch {rename p ""}
    namespace eval test_ns_basic {
        namespace export p
        proc p {} {return 42}
	namespace export p
	proc p {} {return 42}
    }
    namespace eval test_ns_basic2 {
        namespace import ::test_ns_basic::*
        proc callP {} {
            p
        }
	namespace import ::test_ns_basic::*
	proc callP {} {
	    p
	}
    }
    list [test_ns_basic2::callP] \
         [info commands test_ns_basic2::*] \
         [rename test_ns_basic::p ""] \
         [catch {test_ns_basic2::callP} msg] $msg \
         [info commands test_ns_basic2::*]
	 [info commands test_ns_basic2::*] \
	 [rename test_ns_basic::p ""] \
	 [catch {test_ns_basic2::callP} msg] $msg \
	 [info commands test_ns_basic2::*]
} {42 {::test_ns_basic2::callP ::test_ns_basic2::p} {} 1 {invalid command name "p"} ::test_ns_basic2::callP}

test basic-25.1 {TclCleanupCommand} {emptyTest} {
} {}

test basic-26.1 {Tcl_EvalObj: preserve object while evaling it} -setup {
    proc myHandler {msg options} {
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
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







-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+


-
-
+
+







} {}

test basic-36.1 {Tcl_EvalObjv, lookup of "unknown" command} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    catch {interp delete test_interp}
    interp create test_interp
    interp eval test_interp {
        proc unknown {args} {
            return "global unknown"
        }
        namespace eval test_ns_basic {
            proc unknown {args} {
                return "namespace unknown"
            }
        }
	proc unknown {args} {
	    return "global unknown"
	}
	namespace eval test_ns_basic {
	    proc unknown {args} {
		return "namespace unknown"
	    }
	}
    }
    list [interp alias test_interp newAlias test_interp doesntExist] \
         [catch {interp eval test_interp {newAlias}} msg] $msg \
         [interp delete test_interp]
	 [catch {interp eval test_interp {newAlias}} msg] $msg \
	 [interp delete test_interp]
} {newAlias 0 {global unknown} {}}

test basic-37.1 {Tcl_ExprString: see expr.test} {emptyTest} {
} {}

test basic-38.1 {Tcl_ExprObj} {emptyTest} {
} {}
670
671
672
673
674
675
676
677

678
679
680
681
682
683
684
670
671
672
673
674
675
676

677
678
679
680
681
682
683
684







-
+







proc l3 {} {
    list i j k {l l}
}

# Do all tests once byte compiled and once with direct string evaluation
foreach noComp {0 1} {

if $noComp {
if {$noComp} {
    interp alias {} run {} testevalex
    set constraints testevalex
} else {
    interp alias {} run {} if 1
    set constraints {}
}

756
757
758
759
760
761
762
763

764
765
766
767

768
769
770
771
772
773
774
775





776
777
778
779
780
781
782
783
784
785
786
787

788
789
790
791

792
793
794
795

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812


813
814

815
816
817
818
819
820
821
822
823
824
825
826
827
828
829


830
831

832
833
834
835
836
837
838
839
840




841
842

843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906








907
908

909
910
911
912
913
914
915
916
917






918
919
920
921
922
923
924
925
926
927





928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949





950
951
952
953
954
955





956
957
958


959
960
961
962
963
964
965
756
757
758
759
760
761
762

763
764
765
766

767
768
769
770





771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786

787
788
789
790

791
792
793
794

795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810


811
812
813

814
815
816
817
818
819
820
821
822
823
824
825
826
827


828
829
830

831
832
833
834
835
836




837
838
839
840
841

842
843
844
845
846
847
848






























849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898








899
900
901
902
903
904
905
906
907

908
909
910
911






912
913
914
915
916
917
918
919
920
921
922





923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944





945
946
947
948
949
950





951
952
953
954
955
956


957
958
959
960
961
962
963
964
965







-
+



-
+



-
-
-
-
-
+
+
+
+
+











-
+



-
+



-
+















-
-
+
+

-
+













-
-
+
+

-
+





-
-
-
-
+
+
+
+

-
+






-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+







-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
+



-
-
-
-
-
-
+
+
+
+
+
+





-
-
-
-
-
+
+
+
+
+

















-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
+
+







			3   {*}$::l1

		# Comment again
	}
} {1 2 3 a {b b} c d}

test basic-48.2.$noComp {no expansion} $constraints {
        run {list $::l1 $::l2 [l3]}
	run {list $::l1 $::l2 [l3]}
} {{a {b b} c d} {e f {g g} h} {i j k {l l}}}

test basic-48.3.$noComp {expansion} $constraints {
        run {list {*}$::l1 $::l2 {*}[l3]}
	run {list {*}$::l1 $::l2 {*}[l3]}
} {a {b b} c d {e f {g g} h} i j k {l l}}

test basic-48.4.$noComp {expansion: really long cmd} $constraints {
        set cmd [list list]
        for {set t 0} {$t < 500} {incr t} {
            lappend cmd {{*}$::l1}
        }
        llength [run [join $cmd]]
	set cmd [list list]
	for {set t 0} {$t < 500} {incr t} {
	    lappend cmd {{*}$::l1}
	}
	llength [run [join $cmd]]
} 2000

test basic-48.5.$noComp {expansion: error detection} -setup {
	set l "a {a b}x y"
} -constraints $constraints -body {
	run {list $::l1 {*}$l}
} -cleanup {
	unset l
} -returnCodes 1 -result {list element in braces followed by "x" instead of space}

test basic-48.6.$noComp {expansion: odd usage} $constraints {
        run {list {*}$::l1$::l2}
	run {list {*}$::l1$::l2}
} {a {b b} c de f {g g} h}

test basic-48.7.$noComp {expansion: odd usage} -constraints $constraints -body {
        run {list {*}[l3]$::l1}
	run {list {*}[l3]$::l1}
} -returnCodes 1 -result {list element in braces followed by "a" instead of space}

test basic-48.8.$noComp {expansion: odd usage} $constraints {
        run {list {*}hej$::l1}
	run {list {*}hej$::l1}
} {heja {b b} c d}

test basic-48.9.$noComp {expansion: Not all {*} should trigger} $constraints {
	run {list {*}$::l1 \{*\}$::l2 "{*}$::l1" {{*} i j k}}
} {a {b b} c d {{*}e f {g g} h} {{*}a {b b} c d} {{*} i j k}}

test basic-48.10.$noComp {expansion: expansion of command word} -setup {
	set cmd [list string range jultomte]
} -constraints $constraints -body {
	run {{*}$cmd 2 6}
} -cleanup {
	unset cmd
} -result ltomt

test basic-48.11.$noComp {expansion: expansion into nothing} -setup {
        set cmd {}
        set bar {}
	set cmd {}
	set bar {}
} -constraints $constraints -body {
        run {{*}$cmd {*}$bar}
	run {{*}$cmd {*}$bar}
} -cleanup {
	unset cmd bar
} -result {}

test basic-48.12.$noComp {expansion: odd usage} $constraints {
	run {list {*}$::l1 {*}"hej hopp" {*}$::l2}
} {a {b b} c d hej hopp e f {g g} h}

test basic-48.13.$noComp {expansion: odd usage} $constraints {
	run {list {*}$::l1 {*}{hej hopp} {*}$::l2}
} {a {b b} c d hej hopp e f {g g} h}

test basic-48.14.$noComp {expansion: hash command} -setup {
        catch {rename \# ""}
        set cmd "#"
	catch {rename \# ""}
	set cmd "#"
    } -constraints $constraints -body {
           run { {*}$cmd apa bepa }
	   run { {*}$cmd apa bepa }
    } -cleanup {
	unset cmd
} -returnCodes 1 -result {invalid command name "#"}

test basic-48.15.$noComp {expansion: complex words} -setup {
            set a(x) [list a {b c} d e]
            set b x
            set c [list {f\ g h\ i j k} x y]
            set d {0\ 1 2 3}
	    set a(x) [list a {b c} d e]
	    set b x
	    set c [list {f\ g h\ i j k} x y]
	    set d {0\ 1 2 3}
    } -constraints $constraints -body {
            run { lappend d {*}$a($b) {*}[lindex $c 0] }
	    run { lappend d {*}$a($b) {*}[lindex $c 0] }
    } -cleanup {
	unset a b c d
} -result {{0 1} 2 3 a {b c} d e {f g} {h i} j k}

testConstraint memory [llength [info commands memory]]
test basic-48.16.$noComp {expansion: testing for leaks} -setup {
        proc getbytes {} {
            set lines [split [memory info] "\n"]
            lindex [lindex $lines 3] 3
        }
        # This test is made to stress the allocation, reallocation and
        # object reference management in Tcl_EvalEx.
        proc stress {} {
            set a x
            # Create free objects that should disappear
            set l [list 1$a 2$a 3$a 4$a 5$a 6$a 7$a]
            # A short number of words and a short result (8)
            set l [run {list {*}$l $a$a}]
            # A short number of words and a longer result (27)
            set l [run {list {*}$l $a$a {*}$l $a$a {*}$l $a$a}]
            # A short number of words and a longer result, with an error
            # This is to stress the cleanup in the error case
            if {![catch {run {_moo_ {*}$l $a$a {*}$l $a$a {*}$l}}]} {
                error "An error was expected in the previous statement"
            }
            # Many words
            set l [run {list {*}$l $a$a {*}$l $a$a \
                                 {*}$l $a$a {*}$l $a$a \
                                 {*}$l $a$a {*}$l $a$a \
                                 {*}$l $a$a {*}$l $a$a \
                                 {*}$l $a$a {*}$l $a$a \
                                 {*}$l $a$a {*}$l $a$a \
                                 {*}$l $a$a {*}$l $a$a \
                                 {*}$l $a$a {*}$l $a$a \
                                 {*}$l $a$a {*}$l $a$a \
                                 {*}$l $a$a}]
	proc getbytes {} {
	    set lines [split [memory info] "\n"]
	    lindex [lindex $lines 3] 3
	}
	# This test is made to stress the allocation, reallocation and
	# object reference management in Tcl_EvalEx.
	proc stress {} {
	    set a x
	    # Create free objects that should disappear
	    set l [list 1$a 2$a 3$a 4$a 5$a 6$a 7$a]
	    # A short number of words and a short result (8)
	    set l [run {list {*}$l $a$a}]
	    # A short number of words and a longer result (27)
	    set l [run {list {*}$l $a$a {*}$l $a$a {*}$l $a$a}]
	    # A short number of words and a longer result, with an error
	    # This is to stress the cleanup in the error case
	    if {![catch {run {_moo_ {*}$l $a$a {*}$l $a$a {*}$l}}]} {
		error "An error was expected in the previous statement"
	    }
	    # Many words
	    set l [run {list {*}$l $a$a {*}$l $a$a \
				 {*}$l $a$a {*}$l $a$a \
				 {*}$l $a$a {*}$l $a$a \
				 {*}$l $a$a {*}$l $a$a \
				 {*}$l $a$a {*}$l $a$a \
				 {*}$l $a$a {*}$l $a$a \
				 {*}$l $a$a {*}$l $a$a \
				 {*}$l $a$a {*}$l $a$a \
				 {*}$l $a$a {*}$l $a$a \
				 {*}$l $a$a}]

            if {[llength $l] != 19*28} {
                error "Bad Length: [llength $l] should be [expr {19*28}]"
            }
        }
	    if {[llength $l] != 19*28} {
		error "Bad Length: [llength $l] should be [expr {19*28}]"
	    }
	}
    } -constraints [linsert $constraints 0 memory] -body {
        set end [getbytes]
        for {set i 0} {$i < 5} {incr i} {
            stress
            set tmp $end
            set end [getbytes]
        }
        set leak [expr {$end - $tmp}]
	set end [getbytes]
	for {set i 0} {$i < 5} {incr i} {
	    stress
	    set tmp $end
	    set end [getbytes]
	}
	set leak [expr {$end - $tmp}]
    } -cleanup {
	unset end i tmp
	rename getbytes {}
	rename stress {}
} -result 0

test basic-48.17.$noComp {expansion: object safety} -constraints $constraints -body {
            set third [expr {1.0/3.0}]
            set l [list $third $third]
            set x [run {list $third {*}$l $third}]
            set res [list]
            foreach t $x {
                lappend res [expr {$t * 3.0}]
            }
            set res
	    set third [expr {1.0/3.0}]
	    set l [list $third $third]
	    set x [run {list $third {*}$l $third}]
	    set res [list]
	    foreach t $x {
		lappend res [expr {$t * 3.0}]
	    }
	    set res
    } -cleanup {
        unset res t l x third
	unset res t l x third
} -result {1.0 1.0 1.0 1.0}

test basic-48.18.$noComp {expansion: list semantics} -constraints $constraints -body {
        set badcmd {
            list a b
            set apa 10
        }
        set apa 0
        list [llength [run { {*}$badcmd }]] $apa
	set badcmd {
	    list a b
	    set apa 10
	}
	set apa 0
	list [llength [run { {*}$badcmd }]] $apa
    } -cleanup {
	unset apa badcmd
} -result {5 0}

test basic-48.19.$noComp {expansion: error checking order} -body {
        set badlist "a {}x y"
        set a 0
        set b 0
        catch {run {list [incr a] {*}$badlist [incr b]}}
        list $a $b
	set badlist "a {}x y"
	set a 0
	set b 0
	catch {run {list [incr a] {*}$badlist [incr b]}}
	list $a $b
    } -constraints $constraints -cleanup {
	unset badlist a b
} -result {1 0}

test basic-48.20.$noComp {expansion: odd case with word boundaries} $constraints {
    run {list {*}$::l1 {*}"hej hopp" {*}$::l2}
} {a {b b} c d hej hopp e f {g g} h}

test basic-48.21.$noComp {expansion: odd case with word boundaries} $constraints {
    run {list {*}$::l1 {*}{hej hopp} {*}$::l2}
} {a {b b} c d hej hopp e f {g g} h}

test basic-48.22.$noComp {expansion: odd case with word boundaries} -body {
    run {list {*}$::l1 {*}"hej hopp {*}$::l2}
} -constraints $constraints -returnCodes error -result {missing "}

test basic-48.23.$noComp {expansion: handle return codes} -constraints $constraints -body {
        set res {}
        for {set t 0} {$t < 10} {incr t} {
            run { {*}break }
        }
        lappend res $t
	set res {}
	for {set t 0} {$t < 10} {incr t} {
	    run { {*}break }
	}
	lappend res $t

        for {set t 0} {$t < 10} {incr t} {
            run { {*}continue }
            set t 20
        }
        lappend res $t
	for {set t 0} {$t < 10} {incr t} {
	    run { {*}continue }
	    set t 20
	}
	lappend res $t

        lappend res [catch { run { {*}{error Hejsan} } } err]
        lappend res $err
	lappend res [catch { run { {*}{error Hejsan} } } err]
	lappend res $err
    } -cleanup {
	unset res t
} -result {0 10 1 Hejsan}

test basic-48.24.$noComp {expansion: empty not canonical list, regression test, bug [cc1e91552c]} -constraints $constraints -setup {
    unset -nocomplain a
} -body {

Added tests/bigdata.test.































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# Test cases for large sized data
#
# Copyright © 2023 Ashok P. Nadkarni
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

# These are very rudimentary tests for large size arguments to commands.
# They do not exercise all possible code paths such as shared/unshared Tcl_Objs,
# literal/variable arguments etc.
# They do however test compiled and uncompiled execution.

if {"::tcltest" ni [namespace children]} {
    package require tcltest

    namespace import -force ::tcltest::*
}

::tcltest::loadTestedCommands
catch [list package require -exact tcl::test [info patchlevel]]
source [file join [file dirname [info script]] tcltests.tcl]

#
# bigtest and bigtestRO (RO->read only) generate compiled and uncompiled
# versions of the given test script. The difference between the two is
# that bigtest generates separate test instances for the two cases while
# bigtestRO generates a single test case covering both. The latter can
# only be used when operands are not modified and when combining tests
# does not consume too much additional memory.

# Wrapper to generate compiled and uncompiled cases for a test. If $args does
# not contain a -body key, $comment is treated as the test body
proc bigtest {id comment result args} {
    if {[dict exists $args -body]} {
	set body [dict get $args -body]
	dict unset args -body
    } else {
	set body $comment
    }
    dict lappend args -constraints bigdata

    uplevel 1 [list test $id.uncompiled "$comment (uncompiled)" \
		   -body [list testevalex $body] \
		   -result $result \
		   {*}$args]

    uplevel 1 [list test $id.compiled-script "$comment (compiled script)" \
		   -body [list try $body] \
		   -result $result \
		   {*}$args]

    return

    # TODO - is this proc compilation required separately from the compile-script above?
    dict append args -setup \n[list proc testxproc {} $body]
    dict append args -cleanup "\nrename testxproc {}"
    uplevel 1 [list test $id.compiled-proc "$comment (compiled proc)" \
		   -body {testxproc} \
		   -result $result \
		   {*}$args]
}

# Like bigtest except that both compiled and uncompiled are combined into one
# test using the same inout argument. This saves time but for obvious reasons
# should only be used when the input argument is not modified.
proc bigtestRO {id comment result args} {
    if {[dict exists $args -body]} {
	set body [dict get $args -body]
	dict unset args -body
    } else {
	set body $comment
    }
    dict lappend args -constraints bigdata

    set wrapper ""
    set body "{$body}"
    append wrapper "set uncompiled_result \[testevalex $body]" \n
    append wrapper "set compiled_result \[try $body]" \n
    append wrapper {list $uncompiled_result $compiled_result}
    uplevel 1 [list test $id.uncompiled,compiled {$comment} \
		   -body $wrapper \
		   -result [list $result $result] \
		   {*}$args]
    return
}

interp alias {} bigClean {} unset -nocomplain s s1 s2 bin bin1 bin2 l l1 l2

interp alias {} bigString {} testbigdata string
interp alias {} bigBinary {} testbigdata bytearray
interp alias {} bigList {} testbigdata list
proc bigPatLen {} {
    proc bigPatLen {} "return [string length [testbigdata string]]"
    bigPatLen
}

# Returns list of expected elements at the indices specified
proc bigStringIndices {indices} {
    set pat [testbigdata string]
    set patlen [string length $pat]
    lmap idx $indices {
	string index $pat [expr {$idx%$patlen}]
    }
}

# Returns the largest multiple of the pattern length that is less than $limit
proc bigPatlenMultiple {limit} {
    set patlen [bigPatLen]
    return [expr {($limit/$patlen)*$patlen}]
}

set ::bigLengths(intmax) 0x7fffffff
set ::bigLengths(uintmax) 0xffffffff
# Some tests are more convenient if operands are multiple of pattern length
if {[testConstraint bigdata]} {
set ::bigLengths(patlenmultiple) [bigPatlenMultiple $::bigLengths(intmax)]
set ::bigLengths(upatlenmultiple) [bigPatlenMultiple $::bigLengths(uintmax)]
}

#
# script limits
bigtestRO script-length-bigdata-1 {Test script length limit} b -body {
    try [string cat [string repeat " " 0x7ffffff7] "set a b"]
}
# TODO - different behaviour between compiled and uncompiled
test script-length-bigdata-2.compiled {Test script length limit} -body {
    try [string cat [string repeat " " 0x7ffffff8] "set a b"]
} -constraints {
    bigdata
} -result {Script length 2147483647 exceeds max permitted length 2147483646.} -returnCodes error
test script-length-bigdata-2.uncompiled {Test script length limit} -body {
    testevalex [string cat [string repeat " " 0x7ffffff8] "set a b"]
} -constraints {
    bigdata
 } -result b
test script-bytecode-length-bigdata-1 {Test bytecode length limit} -body {
    # Note we need to exceed bytecode limit without exceeding script char limit
    set s [string repeat {{*}$x;} [expr 0x7fffffff/6]]
    catch $s r e
} -cleanup {
    bigClean
} -constraints panic-in-EnterCmdStartData

#
# string cat
bigtest string-cat-bigdata-1 "string cat large small result > INT_MAX" 1 -body {
    string equal \
	[string cat [bigString $::bigLengths(patlenmultiple)] [bigString]] \
	[bigString [expr {[bigPatLen]+$::bigLengths(patlenmultiple)}]]
}
bigtest string-cat-bigdata-2 "string cat small large result > INT_MAX" 1 -body {
    string equal \
	[string cat [bigString] [bigString $::bigLengths(patlenmultiple)]] \
	[bigString [expr {[bigPatLen]+$::bigLengths(patlenmultiple)}]]
}
bigtest string-cat-bigdata-3 "string cat result > UINT_MAX" 1 -body {
    set s [bigString $::bigLengths(patlenmultiple)]
    string equal \
	[string cat $s [bigString] $s] \
	[bigString [expr {[bigPatLen]+2*$::bigLengths(patlenmultiple)}]]
}

#
# string compare/equal
bigtestRO string-equal/compare-bigdata-1 "string compare/equal equal strings" {0 1} -body {
    list [string compare $s1 $s2] [string equal $s1 $s2]
} -setup {
    set s1 [bigString 0x100000000]
    set s2 [bigString 0x100000000]; # Separate so Tcl_Obj is not the same
} -cleanup {
    bigClean
}
bigtestRO string-equal/compare-bigdata-2 "string compare/equal -length unequal strings" {-1 0 0 1} -body {
    # Also tests lengths do not wrap
    set result {}
    lappend result [string compare $s1 $s2]
    lappend result [string equal $s1 $s2]
    # Check lengths > UINT_MAX
    # Also that lengths do not truncate to sizeof(int)
    lappend result [string compare -length 0x100000000 $s1 $s2]
    lappend result [string equal -length 0x100000000 $s1 $s2]
} -setup {
    set s1 [bigString 0x100000001]
    set s2 [bigString 0x100000001 0x100000000]; # Differs in last char
} -cleanup {
    bigClean
}

#
# string first
bigtestRO string-first-bigdata-1 "string first > INT_MAX" {2147483648 -1 2147483650 1} -body {
    list \
	[string first X $s] \
	[string first Y $s] \
	[string first 0 $s 0x80000000] \
	[string first 1 $s end-0x80000010]
} -setup {
    set s [bigString 0x8000000a 0x80000000]
} -cleanup {
    bigClean
}

bigtestRO string-first-bigdata-2 "string first > UINT_MAX" {4294967296 -1 4294967300 1} -body {
    list \
	[string first X $s] \
	[string first Y $s] \
	[string first 0 $s 0x100000000] \
	[string first 1 $s end-0x100000010]
} -setup {
    set s [bigString 0x10000000a 0x100000000]
} -cleanup {
    bigClean
}

bigtestRO string-first-bigdata-3 "string first - long needle" 10 -body {
    string first $needle $s
} -setup {
    set s [bigString 0x10000000a 0]
    set needle [bigString 0x100000000]
} -cleanup {
   bigClean needle
}

#
# string index
bigtestRO string-index-bigdata-1 "string index" {6 7 5 {} 5 4 {} 9 {}} -body {
    list \
	[string index $s 0x100000000] \
	[string index $s 0x100000000+1] \
	[string index $s 0x100000000-1] \
	[string index $s 0x10000000a] \
	[string index $s end] \
	[string index $s end-1] \
	[string index $s end+1] \
	[string index $s end-0x100000000] \
	[string index $s end-0x10000000a]
} -setup {
    set s [bigString 0x10000000a]
} -cleanup {
    bigClean
}

#
# string insert
bigtestRO string-insert-bigdata-1 "string insert" 1 -body {
    # Note insert at multiple of 10 to enable comparison against generated string
    string equal [string insert [bigString 4294967312] 4294967310 "0123456789"] [bigString 4294967322]
}
bigtestRO string-insert-bigdata-2 "string insert" 1 -body {
    string equal [string insert [bigString 4294967312] 10 "0123456789"] [bigString 4294967322]
}

#
# string is
bigtestRO string-is-bigdata-1 "string is" {1 0 0 4294967296} -body {
    # TODO - add the other "is" classes
    unset -nocomplain failat result
    lappend result [string is alnum -failindex failat $s] [info exists failat]
    lappend result [string is digit -failindex failat $s] $failat
} -setup {
    set s [bigString 0x10000000a 0x100000000]
} -cleanup {
    bigClean failat
}

#
# string last
bigtestRO string-last-bigdata-1 "string last > INT_MAX" {2 -1 2147483640 11} -body {
    set s [bigString 0x80000010 2]
    list \
	[string last X $s] \
	[string last Y $s] \
	[string last 0 $s 0x80000000] \
	[string last 1 $s end-0x80000000]
} -setup {
    set s [bigString 0x80000010 2]
} -cleanup {
    bigClean
}
bigtestRO string-last-bigdata-2 "string last > UINT_MAX" {4294967320 -1 4294967290 1} -body {
    list \
	[string last 0 $s] \
	[string last Y $s] \
	[string last 0 $s 0x100000000] \
	[string last 1 $s end-0x100000010]
} -setup {
    set s [bigString 0x10000001a 2]
} -cleanup {
    bigClean
}
bigtestRO string-last-bigdata-3 "string last - long needle" 0 -body {
    string last $needle $s
} -setup {
    set s [bigString 0x10000000a 0x10000000a]
    set needle [bigString 0x100000000]
} -cleanup {
    bigClean needle
}

#
# string length
bigtestRO string-length-bigdata-1 {string length $s} 4294967296 -setup {
    set s [bigString 0x100000000]
} -cleanup {
    bigClean
}

#
# string map
bigtestRO string-map-bigdata-1 {string map} {5 0 0 5} -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain s2
    set s2 [string map {0 5 5 0} $s]
    list \
	[string index $s2 0] \
	[string index $s2 5] \
	[string index $s2 end] \
	[string index $s2 end-5]
} -setup {
    set s [bigString 0x100000000]
} -cleanup {
    bigClean
} -constraints bug-takesTooLong

#
# string match
bigtestRO string-match-bigdata-1 {string match} {1 0 1} -body {
    list \
	[string match 0*5 $s] \
	[string match 0*4 $s] \
	[string match $s $s]
} -setup {
    set s [bigString 0x100000000]
} -cleanup {
    bigClean
}

#
# string range
bigtestRO string-range-bigdata-1 "string range" {6 7 5 {} 5 4 {} 9 {}} -body {
    list \
	[string range $s 0x100000000 0x100000000] \
	[string range $s 0x100000000+1 0x100000000+1] \
	[string range $s 0x100000000-1 0x100000000-1] \
	[string range $s 0x10000000a 0x10000000a] \
	[string range $s end end] \
	[string range $s end-1 end-1] \
	[string range $s end+1 end+1] \
	[string range $s end-0x100000000 end-0x100000000] \
	[string range $s end-0x10000000a end-0x10000000a]
} -setup {
    set s [bigString 0x10000000a]
} -cleanup {
    bigClean
}
bigtestRO string-range-bigdata-2 "bug ad9361fd20 case 1" aXaaaa -body {
    string range [string insert [string repeat a 0x80000000] end-0x7fffffff X] 0 5
}
bigtestRO string-range-bigdata-3 "bug ad9361fd20 case 2" 2 -body {
    string length [string range $s end-0x7fffffff end-0x7ffffffe]
} -setup {
    set s [string repeat a 0xffffffff]
} -cleanup {
    bigClean
}
# TODO - add tests for large result range

#
# string repeat - use bigtest, not bigtestRO !!
bigtest string-repeat-bigdata-1 "string repeat single char length > UINT_MAX" 4294967296 -body {
    string length [string repeat x 0x100000000]
}
bigtest string-repeat-bigdata-2 "string repeat multiple char" {4294967296 0123456789abcdef 0123456789abcdef} -body {
    set s [string repeat 0123456789abcdef [expr 0x100000000/16]]
    list \
	[string length $s] \
	[string range $s 0 15] \
	[string range $s end-15 end]
} -cleanup {
    bigClean
}

#
# string replace
bigtestRO string-replace-bigdata-1 "string replace" {789012345 012345678 XYZ789012345 012345678XYZ} -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain result
    lappend result [string replace $s 0 0x100000000]
    lappend result [string replace $s end-0x100000000 end]
    lappend result [string replace $s 0 0x100000000 XYZ]
    lappend result [string replace $s end-0x100000000 end XYZ]
} -setup {
    set s [bigString 0x10000000a]
} -cleanup {
    bigClean
}
# TODO -
# - replacements string is large
# - replace in the middle - string length grows, shrinks
# - last < first

#
# string reverse
bigtestRO string-reverse-bigdata-1 "string reverse" {5432109876 9876543210} -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain s2 result
    set s2 [string reverse $s]
    list [string range $s2 0 9] [string range $s2 end-9 end]
} -setup {
    set s [bigString 0x10000000a]
} -cleanup {
    bigClean
}

#
# string tolower
bigtestRO string-tolower-bigdata-1 "string tolower" 1 -body {
    string equal [string tolower $s] [string repeat abcd $repts]
} -setup {
    set repts [expr 0x100000010/4]
    set s [string repeat ABCD $repts]
} -cleanup {
    bigClean repts
}
bigtestRO string-tolower-bigdata-2 "string tolower first last" {4294967312 ABCDabcdABCD 4294967312 ABCDabcdABCD 4294967312 ABCDabcdABCD} -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain s2 result
    set s2 [string tolower $s 4 7]
    lappend result [string length $s2] [string range $s2 0 11]

    unset s2; #Explicit free to reduce total memory
    set s2 [string tolower $s 0x100000008 0x10000000b]
    lappend result [string length $s2] [string range $s2 0x100000004 end]

    unset s2; #Explicit free to reduce total memory
    set s2 [string tolower $s end-7 end-4]
    lappend result [string length $s2] [string range $s2 0x100000004 end]
} -setup {
    set repts [expr 0x100000010/4]
    set s [string repeat ABCD $repts]
} -cleanup {
    bigClean repts
}

#
# string totitle
bigtestRO string-totitle-bigdata-1 "string totitle first last" {4294967312 aBcDAbcdaBcD 4294967312 aBcDAbcdaBcD 4294967312 aBcDAbcdaBcD} -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain s2 result
    set s2 [string totitle $s 4 7]
    lappend result [string length $s2] [string range $s2 0 11]
    unset s2; #Explicit free to reduce total memory
    set s2 [string totitle $s 0x100000008 0x10000000b]
    lappend result [string length $s2] [string range $s2 0x100000004 0x10000000f]
    unset s2; #Explicit free to reduce total memory
    set s2 [string totitle $s end-7 end-4]
    lappend result [string length $s2] [string range $s2 0x100000004 0x10000000f]
} -setup {
    set repts [expr 0x100000010/4]
    set s [string repeat aBcD $repts]
} -cleanup {
    bigClean repts
}

#
# string toupper
bigtestRO string-toupper-bigdata-1 "string toupper" 1 -body {
    string equal [string toupper $s] [string repeat ABCD $repts]
} -setup {
    set repts [expr 0x100000010/4]
    set s [string repeat abcd $repts]
} -cleanup {
    bigClean repts
}
bigtestRO string-toupper-bigdata-2 "string toupper first last" {4294967312 abcdABCDabcd 4294967312 abcdABCDabcd 4294967312 abcdABCDabcd} -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain s2 result
    set s2 [string toupper $s 4 7]
    lappend result [string length $s2] [string range $s2 0 11]
    unset s2; #Explicit free to reduce total memory
    set s2 [string toupper $s 0x100000008 0x10000000b]
    lappend result [string length $s2] [string range $s2 0x100000004 0x10000000f]
    unset s2; #Explicit free to reduce total memory
    set s2 [string toupper $s end-7 end-4]
    lappend result [string length $s2] [string range $s2 0x100000004 0x10000000f]
} -setup {
    set repts [expr 0x100000010/4]
    set s [string repeat abcd $repts]
} -cleanup {
    bigClean repts
}

#
# string trim
bigtestRO string-trim-bigdata-1 "string trim" {abcdyxxy yxxyabcd} -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain s2
    set s2 [string trim $s xy]
    list [string range $s2 0 7] [string range $s2 end-7 end]
} -setup {
    set repts [expr 0x100000010/8]
    set s [string repeat xyabcdyx $repts]
} -cleanup {
    bigClean
}

#
# string trimleft
bigtestRO string-trimleft-bigdata-1 "string trimleft" {abcdyxxy xyabcdyx} -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain s2
    set s2 [string trimleft $s xy]
    list [string range $s2 0 7] [string range $s2 end-7 end]
} -setup {
    set repts [expr 0x100000010/8]
    set s [string repeat xyabcdyx $repts]
} -cleanup {
    bigClean
}

#
# string trimright
bigtestRO string-trimright-bigdata-1 "string trimright" {xyabcdyx yxxyabcd} -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain s2
    set s2 [string trimright $s xy]
    list [string range $s2 0 7] [string range $s2 end-7 end]
} -setup {
    set repts [expr 0x100000010/8]
    set s [string repeat xyabcdyx $repts]
} -cleanup {
    bigClean
}

#
# append
bigtestRO append-bigdata-1 "append large to small" 1 -body {
    set s 0123456789
    append s [bigString 0x100000000]
    string equal $s [bigString 0x10000000a]
} -cleanup {
    bigClean
}
bigtest append-bigdata-2 "append small to cross UINT_MAX boundary" 1 -body {
    append s 0123456789
    string equal $s [bigString 4294967300]
} -setup {
    set s [bigString 4294967290]
} -cleanup {
    bigClean
}
bigtest append-bigdata-3 "append small to cross UINT_MAX boundary" 1 -body {
    set s2 ""
    append s2 $s $s $s $s
    string equal $s2 [bigString 4294967320]
} -setup {
    # Make length multiple of 4 AND 10 since the bigString pattern length is 10
    set len [expr 4294967320/4]
    set s [bigString $len]
} -cleanup {
    bigClean
}

#
# format
bigtestRO format-bigdata-1 "format %s" 1 -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain s2
    set s2 [format %s $s]
    string equal $s $s2
} -setup {
    set s [bigString 0x100000000]
} -cleanup {
    bigClean
}
bigtest format-bigdata-2 "format bigstring%s" 1 -body {
    set s [format $s X]
    string equal $s [bigString 0x100000001 0x100000000]
} -setup {
    set s [bigString 0x100000000]
    append s %s
} -cleanup {
    bigClean
}
bigtest format-bigdata-3 "format big width" {4294967300 {    } {   a}} -body {
    set s [format %4294967300s a]
    list [string length $s] [string range $s 0 3] [string range $s end-3 end]
} -cleanup {
    bigClean
}
bigtest format-bigdata-4 "format big negative width" {4294967300 {a   } {    }} -body {
    set s [format %-4294967300s a]
    list [string length $s] [string range $s 0 3] [string range $s end-3 end]
} -cleanup {
    bigClean
}
bigtest format-bigdata-5 "format big * width" {4294967300 {    } {   a}} -body {
    set s [format %*s 4294967300 a]
    list [string length $s] [string range $s 0 3] [string range $s end-3 end]
} -cleanup {
    bigClean
}
bigtest format-bigdata-6 "format big negative * width" {4294967300 {a   } {    }} -body {
    set s [format %*s -4294967300 a]
    list [string length $s] [string range $s 0 3] [string range $s end-3 end]
} -cleanup {
    bigClean
}
bigtestRO format-bigdata-7 "format big precision" {4294967300 0123 6789} -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain s2
    set s2 [format %.4294967300s $s]
    list [string length $s2] [string range $s2 0 3] [string range $s2 end-3 end]
} -setup {
    set s [testbigdata string 4294967310]
} -cleanup {
    bigClean
}
bigtestRO format-bigdata-8 "format big * precision" {4294967300 0123 6789} -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain s2
    set s2 [format %.*s 4294967300 $s]
    list [string length $s2] [string range $s2 0 3] [string range $s2 end-3 end]
} -setup {
    set s [testbigdata string 4294967310]
} -cleanup {
    bigClean
}

#
# scan
bigtestRO scan-bigdata-1 "scan %s" {1 1 2 X 1 2 4294967300 01234X} -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain result digits x
    lappend result [string equal [scan $s %s] $s]
    lappend result [string equal [scan $s {%[0-9X]}] $s]
    lappend result [scan $s {%[0-9]%s} digits x] $x
    lappend result [string equal $digits [bigString 0x100000009]]
    lappend result [scan $s %4294967300s%s x y]
    lappend result [string length $x] $y
} -setup {
    set s [bigString 0x10000000a 0x100000009]
} -cleanup {
    bigClean digits
}

#
# regexp
bigtestRO regexp-bigdata-1 "regexp" 1 -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain result digits
    lappend result [regexp {[[:digit:]]*X} $s]
} -setup {
    set s [bigString 0x100000000 0x100000000]
} -cleanup {
    bigClean digits
}
bigtestRO regexp-bigdata-2 "regexp with capture" 1 -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain result digits match
    lappend result [regexp {([[:digit:]])*X} $s match digits] [string equal $match $s]
    puts B
    unset match; # Free up memory
    lappend result [string equal $digits [bigString 0x100000009]]
} -setup {
    set s [bigString 0x10000000a 0x100000009]
} -cleanup {
    bigClean digits match
} -constraints bug-takesTooLong

#
# regsub
bigtestRO regsub-bigdata-1 "regsub" X -body {
    regsub -all \\d $s {}
} -setup {
    set s [bigString 0x100000001 0x100000000]
} -cleanup {
    bigClean
} -constraints bug-takesTooLong
bigtestRO regsub-bigdata-2 "regsub" 1 -body {
    string equal [regsub -all \\d $s x] [string cat [string repeat x 0x100000000] X]
} -setup {
    set s [bigString 0x100000001 0x100000000]
} -cleanup {
    bigClean
} -constraints bug-takesTooLong

#
# subst
bigtestRO subst-bigdata-1 "subst" {1 1} -body {
    unset -nocomplain result
    lappend result [string equal [subst $s] $s]
    lappend result [string equal [subst {$s}] $s]
} -setup {
    set s [bigString 0x10000000a]
} -cleanup {
    bigClean
}

#
# binary format
bigtestRO binary-format-bigdata-1 "binary format aN" [list 4294967296  X\0\0\0 \0\0\0\0] -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain bin
    set bin [binary format a4294967296 X]
    list [string length $bin] [string range $bin 0 3] [string range $bin end-3 end]
} -cleanup {
    bigClean
}
# TODO - do string compare and add other format specifiers

bigtestRO binary-format-bigdata-2 "binary format a*" 1 -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain bin2
    set bin2 [binary format a* $bin]
    string equal $bin $bin2
} -setup {
    set bin [bigBinary 4294967296]
} -cleanup {
    bigClean
}

#
# binary scan
bigtestRO binary-scan-bigdata-1 "binary scan aN" {4294967296 0123 2345} -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain bin2
    binary scan $bin a4294967296 bin2
    list [string length $bin2] [string range $bin2 0 3] [string range $bin2 end-3 end]
} -setup {
    set bin [bigBinary 4294967296]
} -cleanup {
    bigClean
}
# TODO - do string compare and add other format specifiers once above bug is fixed

bigtestRO binary-scan-bigdata-2 "binary scan a*" 1 -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain bin2
    binary scan $bin a* bin2
    string equal $bin $bin2
} -setup {
    set bin [bigBinary 4294967296]
} -cleanup {
    bigClean
}
# TODO - do string compare and add other format specifiers once above bug is fixed

#
# binary encode / decode base64
bigtestRO binary-encode/decode-base64-bigdata-1 "binary encode/decode base64" 1 -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    string equal $bin [binary decode base64 [binary encode base64 $bin]]
} -setup {
    set bin [bigBinary 4294967296]
} -cleanup {
    bigClean
}

#
# binary encode / decode hex
bigtestRO binary-encode/decode-hex-bigdata-1 "binary encode/decode hex" 1 -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    string equal $bin [binary decode hex [binary encode hex $bin]]
} -setup {
    set bin [bigBinary 4294967296]
} -cleanup {
    bigClean
}

#
# binary encode / decode uuencode
bigtestRO binary-encode/decode-uuencode-bigdata-1 "binary encode/decode uuencode" 1 -body {
    string equal $bin [binary decode uuencode [binary encode uuencode $bin]]
} -setup {
    set bin [bigBinary 4294967296]
} -cleanup {
    bigClean
}

################################################################
# List commands

#
# foreach
bigtestRO foreach-bigdata-1 "foreach" 1 -body {
    # Unset explicitly before setting as bigtestRO runs the script twice.
    unset -nocomplain l2
    foreach x $l {
	lappend l2 $x
    }
    testlutil equal $l $l2
} -setup {
    set l [bigList 0x100000000]
} -cleanup {
    bigClean
}

#
# lappend
bigtest lappend-bigdata-1 "lappend" {4294967300 4294967300 {1 2 3 4 5 a b c d}} -body {
    # Do NOT initialize l in a -setup block. That requires more memory and fails.
    # Do not have enough memory for a full compare.
    # Just check end
    set l [bigList 0x100000000]
    list [llength [lappend l a b c d]] [llength $l] [lrange $l end-8 end]
} -cleanup {
    bigClean
}

#
# lassign
bigtestRO lassign-bigdata-1 "lassign" {0 1 2 3 4 5 6 7 8 {9 0 1 2 3 4 5 6 7 8} {6 7 8 9 0 1 2 3 4 5}} -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain l2
    set l2 [lassign $l a b c d e f g h i]
    list $a $b $c $d $e $f $g $h $i [lrange $l2 0 9] [lrange $l2 end-9 end]
} -setup {
    set l [bigList 0x10000000a]
} -cleanup {
    bigClean
}

#
# ledit
bigtest ledit-bigdata-1 "ledit - small result" {{0 X Y Z 8} {0 X Y Z 8}} -body {
    list [ledit l 1 0x100000001 X Y Z] $l
} -setup {
    set l [bigList 0x100000003]
} -cleanup {
    bigClean
}

bigtest ledit-bigdata-2 "ledit - large result" {4294967304 4294967304 {a b c d e f g 7}} -body {
    # Do NOT initialize l in a -setup block. That requires more memory and fails.
    set l [bigList 0x100000002]
    list [llength [ledit l 0x100000000 0x100000000 a b c d e f g]] [llength $l] [lrange $l 0x100000000 end]
} -cleanup {
    bigClean
}

bigtest ledit-bigdata-3 "ledit - small -> large result" {2147483650 2147483650 {a b 0 1 2 3 4 5} {0 1 e f g h i j}} -body {
    set l2 {a b c d e f g h i j}
    list [llength [ledit l2 2 3 {*}$l]] [llength $l2] [lrange $l2 0 7] [lrange $l2 end-7 end]
} -setup {
    # Note total number of arguments has to be less than INT_MAX
    set l [bigList 2147483642]
} -cleanup {
    bigClean
} -constraints memory-allocation-panic

#
# lindex
bigtestRO lindex-bigdata-1 "lindex" {6 7 5 {} 5 4 {} 9 {}} -body {
    list \
	[lindex $l 0x100000000] \
	[lindex $l 0x100000000+1] \
	[lindex $l 0x100000000-1] \
	[lindex $l 0x10000000a] \
	[lindex $l end] \
	[lindex $l end-1] \
	[lindex $l end+1] \
	[lindex $l end-0x100000000] \
	[lindex $l end-0x10000000a]
} -setup {
    set l [bigList 0x10000000a]
} -cleanup {
    bigClean
}
# TODO nested index

#
# linsert
# Cannot use bigtestRO here because 16GB memory not enough to have two 4G sized lists
# Have to throw away source list every time. Also means we cannot compare entire lists
# and instead just compare the affected range
bigtest linsert-bigdata-1 "linsert" {4294967330 1} -body {
    # Note insert at multiple of 10 to enable comparison against generated string
    set ins [split abcdefghij ""]
    set pat [split 0123456789 ""]
    set insidx 2000000000
    set l [linsert [bigList 4294967320] $insidx {*}$ins]
    list \
	[llength $l] \
	[testlutil equal [lrange $l $insidx-10 $insidx+19] [concat $pat $ins $pat]]
} -cleanup {
    bigClean
}

#
# list and {*}
# TODO - compiled and uncompiled behave differently so tested separately
test list-bigdata-1.compiled {list {*}}  -body {
    set l [bigList 0x100000000]
    set l2 [list {*}$l]
    unset l
    list [llength $l2] [lindex $l2 0] [lindex $l2 end]
} -cleanup {
    bigClean
} -constraints {
    bigdata
} -result {4294967296 0 5}
test list-bigdata-1.uncompiled {list {*}}  -body {
    set l [bigList 0x7fffffff]
    testevalex {set l2 [list {*}$l]}
} -cleanup {
    bigClean
} -constraints {
    bigdata
} -result {Number of words in command exceeds limit 2147483647.} -returnCodes error

#
# llength
bigtestRO llength-bigdata-1 {llength} 4294967296 -body {
    llength $l
} -setup {
    set l [bigList 0x100000000]
} -cleanup {
    bigClean
}

#
# lmap
bigtestRO lmap-bigdata-1 "lmap" 4294967296 -body {
    set n 0
    if {0} {
	# TODO - This is the right test but runs out of memory
	testlutil equal $l [lmap e $l {set e}]
    } else {
	lmap e $l {incr n; continue}
    }
    set n
} -setup {
    set l [bigList 0x100000000]
} -cleanup {
    bigClean
    puts ""
}

#
# lrange
bigtestRO lrange-bigdata-1 "lrange" {6 {6 7} 7 5 {} 5 4 {} 9 {8 9} {}} -body {
    list \
	[lrange $l 0x100000000 0x100000000] \
	[lrange $l 0x100000000 0x100000001] \
	[lrange $l 0x100000000+1 0x100000000+1] \
	[lrange $l 0x100000000-1 0x100000000-1] \
	[lrange $l 0x10000000a 0x10000000a] \
	[lrange $l end end] \
	[lrange $l end-1 end-1] \
	[lrange $l end+1 end+1] \
	[lrange $l end-0x100000000 end-0x100000000] \
	[lrange $l end-0x100000001 end-0x100000000] \
	[lrange $l end-0x10000000a end-0x10000000a]
} -setup {
    set l [bigList 0x10000000a]
} -cleanup {
    bigClean
}
# TODO - add tests for large result range

#
# lrepeat - use bigtest, not bigtestRO !!
bigtest lrepeat-bigdata-1 "lrepeat single element length > UINT_MAX" 4294967296 -body {
    # Just to test long lengths are accepted as arguments
    llength [lrepeat 0x100000000 x]
}

bigtest lrepeat-bigdata-2 "string repeat multiple char" {4294967400 {0 1 2 3 4 5 6 7}} -body {
    set len [expr 4294967400/8]
    set l [lrepeat $len 0 1 2 3 4 5 6 7]
    list [llength $l] [lrange $l end-7 end]
} -cleanup {
    bigClean
}

#
# lreplace
bigtestRO lreplace-bigdata-1 "lreplace - small result" [list \
					     [split 789012345 ""] \
					     [split 012345678 ""] \
					     [split XYZ789012345 ""] \
					     [split 012345678XYZ ""] \
					    ] -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain result
    lappend result [lreplace $l 0 0x100000000]
    lappend result [lreplace $l end-0x100000000 end]
    lappend result [lreplace $l 0 0x100000000 X Y Z]
    lappend result [lreplace $l end-0x100000000 end X Y Z]
} -setup {
    set l [bigList 0x10000000a]
} -cleanup {
    bigClean
}

bigtest lreplace-bigdata-2 "lreplace - large result" {4294967301 {a b c d e 0 1 2 3 4 5 6}} -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain l2
    set l2 [lreplace [bigList 4294967296] 4294967290 0 a b c d e]
    lrange $l2 4294967290 end
} -setup {
    #set l [bigList 4294967296]
} -cleanup {
    bigClean
} -constraints bug-outofmemorypanic

#
# lsearch
bigtestRO lsearch-bigdata-1 "lsearch" {4294967300 4294967310 -1}  -body {
    list \
	[lsearch -exact $l X] \
	[lsearch -exact -start 4294967291 $l 0] \
	[lsearch -exact $l Y]
} -setup {
    set l [bigList 0x100000010 4294967300]
} -cleanup {
    bigClean
}
# TODO - stride, inline, all

#
# lseq
bigtest lseq-bigdata-1 "lseq" {4294967297 4294967296} -body {
    list [llength $l] [lindex $l 0x100000000]
} -setup {
    set l [lseq 0x100000001]
} -cleanup {
    bigClean
}
bigtest lseq-bigdata-2 "lseq" {9223372036854775807 9223372036854775799} -body {
    list [llength $l] [lindex $l 9223372036854775800]
} -setup {
    set l [lseq 0x7fffffffffffffff]; llength $l
} -cleanup {
    bigClean
} -constraints bug-fa00fbbbab

#
# lset
bigtest lset-bigdata-1 "lset" {4294967297 4294967297 {1 2 3 4 5 X}} -body {
    # Do NOT initialize l in a -setup block. That requires more memory and fails.
    set l [bigList 0x100000001]
    list [llength [lset l 0x100000000 X]] [llength $l] [lrange $l end-5 end]
} -cleanup {
    bigClean
}

#
# lsort
bigtestRO lsort-bigdata-1 "lsort" [list 4294967296 [lrepeat 10 0] [lrepeat 10 9]] -body {
    # Unset explicitly before setting to save memory as bigtestRO runs the
    # script below twice.
    unset -nocomplain l2
    set l2 [lsort $l]
    list [llength $l2] [lrange $l2 0 9] [lrange $l2 end-9 end]
} -setup {
    set l [bigList 0x100000000]
} -cleanup {
    bigClean
} -constraints notenoughmemoryexception

#
# join
bigtestRO join-bigdata-1 "join" [list 0123456789 6789012345] -body {
    set s [join $l ""]
    list [string range $s 0 9] [string range $s end-9 end]
} -setup {
    set l [bigList 0x100000000]
} -cleanup {
    bigClean
}

bigtest split-bigdata-1 "split" {4294967296 {0 1 2 3 4} {1 2 3 4 5}} -body {
    # Fill list compare needs too much memory
    set l [split $s ""]
    list [llength $l] [lrange 0 4] [lrange end-4 end]
} -setup {
    set s [bigString 0x100000000]
} -cleanup {
    bigClean
} -constraints bug-takesTooLong

bigtestRO concat-bigdata-1 "concat" {4294967296 {0 1 2 3 4} {6 7 0 1 2} {3 4 5 6 7}} -body {
    unset -nocomplain l2
    set l2 [concat $l $l]
    list [llength $l2] [lrange $l2 0 4] [lrange $l2 0x80000000-2 0x80000000+2] [lrange $l2 end-4 end]
} -setup {
    set l [bigList 0x80000000]
}

test puts-bigdata-1 "puts" -setup {
    set fpath [makeFile {} bug-0306a5563.data]
} -constraints {
    bigdata
} -body {
    set fd [open $fpath w]
    puts -nonewline $fd [testbigdata string 0x80000001]
    close $fd
    set fd [open $fpath]
    seek $fd 0x7FFFFFFA
    set written [read $fd]
    close $fd
    set written
} -result {2345678}

test puts-bigdata-2 "puts" -setup {
    set fpath [tcltest::makeFile {} bug-0306a5563.data]
} -constraints {
    bigdata
} -body {
    set fd [open $fpath w]
    set s [testbigdata string 0x7FFFFFFE]
    # The character to append in the next line is —, EM DASH,
    # code point 0x2014 (decimal 8212, UTF-8 #xE2 #x80 #x94)
    append s \u2014
    puts -nonewline $fd $s
    close $fd
    set fd [open $fpath]
    seek $fd 0x7FFFFFFA
    set written [read $fd]
    close $fd
    set written
} -result {2345—}

test source-bigdata-1 "source" -setup {
    # This test crashes because the frame linenumber tracking
    # wraps around at INT_MAX
    set fpath [tcltest::makeFile {} source-bigdata-1.tcl]
    set fd [open $fpath w]
    fconfigure $fd -translation lf
    puts -nonewline $fd [string repeat \n 4294967296]
    puts $fd {dict get [info frame 0] line}
    close $fd
} -constraints {
    bigdata knownBug
} -body {
    set line [source $fpath]
} -result 4294967297

#
# TODO
# lremove
# lreverse
# encoding convertfrom
# encoding convertto
# dict *



# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:

Changes to tests/binary.test.

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
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
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
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






-
-
+
+








+
+
+
+
+



+








-
+

-
+









-
+

-
+

-
+





-
+

-
+









-
+

-
+

-
+







# This file tests the tclBinary.c file and the "binary" Tcl command.
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1997 by Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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
source [file join [file dirname [info script]] tcltests.tcl]

catch [list package require -exact tcl::test [info patchlevel]]

testConstraint bigEndian [expr {$tcl_platform(byteOrder) eq "bigEndian"}]
testConstraint littleEndian [expr {$tcl_platform(byteOrder) eq "littleEndian"}]
testConstraint testbytestring [llength [info commands testbytestring]]
testConstraint pointerIs64bit [expr {$tcl_platform(pointerSize) >= 8}]

# Big test for correct ordering of data in [expr]
proc testIEEE {} {
    variable ieeeValues
    binary scan [binary format dd -1.0 1.0] c* c
    switch -exact -- $c {
	{0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
	    # little endian
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\xFF d \
		ieeeValues(-Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\xBF d \
		ieeeValues(-Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
		ieeeValues(-Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x3F d \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \
		ieeeValues(+Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF8\x7F d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 1
	    return 1
	}
	{-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
	    binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \xFF\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Infinity)
	    binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \xBF\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Normal)
	    binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Subnormal)
	    binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x3F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Normal)
	    binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x7F\xF8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 0
	}
156
157
158
159
160
161
162
163

164
165
166

167
168
169

170
171
172

173
174
175
176
177
178
179
162
163
164
165
166
167
168

169
170
171

172
173
174

175
176
177

178
179
180
181
182
183
184
185







-
+


-
+


-
+


-
+







    binary format B0 1
} {}
test binary-4.3 {Tcl_BinaryObjCmd: format} {
    binary format B 1
} \x80
test binary-4.4 {Tcl_BinaryObjCmd: format} {
    binary format B* 010011
} \x4c
} \x4C
test binary-4.5 {Tcl_BinaryObjCmd: format} {
    binary format B8 01001101
} \x4d
} \x4D
test binary-4.6 {Tcl_BinaryObjCmd: format} {
    binary format A2X2B9 oo 01001101
} \x4d\x00
} \x4D\x00
test binary-4.7 {Tcl_BinaryObjCmd: format} {
    binary format B9 010011011010
} \x4d\x80
} \x4D\x80
test binary-4.8 {Tcl_BinaryObjCmd: format} {
    binary format B2B3 10 010
} \x80\x40
test binary-4.9 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format B1B5 1 foo
} -result {expected binary string but got "foo" instead}

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
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







-
+


-
+


-
+


-
+


















-
+


-
+


-
+


-
+


-
+







    binary format b 1
} \x01
test binary-5.4 {Tcl_BinaryObjCmd: format} {
    binary format b* 010011
} 2
test binary-5.5 {Tcl_BinaryObjCmd: format} {
    binary format b8 01001101
} \xb2
} \xB2
test binary-5.6 {Tcl_BinaryObjCmd: format} {
    binary format A2X2b9 oo 01001101
} \xb2\x00
} \xB2\x00
test binary-5.7 {Tcl_BinaryObjCmd: format} {
    binary format b9 010011011010
} \xb2\x01
} \xB2\x01
test binary-5.8 {Tcl_BinaryObjCmd: format} {
    binary format b17 1
} \x01\00\00
} \x01\x00\x00
test binary-5.9 {Tcl_BinaryObjCmd: format} {
    binary format b2b3 10 010
} \x01\x02
test binary-5.10 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format b1b5 1 foo
} -result {expected binary string but got "foo" instead}

test binary-6.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format h
} -result {not enough arguments for all format specifiers}
test binary-6.2 {Tcl_BinaryObjCmd: format} {
    binary format h0 1
} {}
test binary-6.3 {Tcl_BinaryObjCmd: format} {
    binary format h 1
} \x01
test binary-6.4 {Tcl_BinaryObjCmd: format} {
    binary format h c
} \x0c
} \x0C
test binary-6.5 {Tcl_BinaryObjCmd: format} {
    binary format h* baadf00d
} \xab\xda\x0f\xd0
} \xAB\xDA\x0F\xD0
test binary-6.6 {Tcl_BinaryObjCmd: format} {
    binary format h4 c410
} \x4c\x01
} \x4C\x01
test binary-6.7 {Tcl_BinaryObjCmd: format} {
    binary format h6 c4102
} \x4c\x01\x02
} \x4C\x01\x02
test binary-6.8 {Tcl_BinaryObjCmd: format} {
    binary format h5 c41020304
} \x4c\x01\x02
} \x4C\x01\x02
test binary-6.9 {Tcl_BinaryObjCmd: format} {
    binary format a3X3h5 foo 2
} \x02\x00\x00
test binary-6.10 {Tcl_BinaryObjCmd: format} {
    binary format h2h3 23 456
} \x32\x54\x06
test binary-6.11 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
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
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







-
+


-
+


-
+


-
+


-
+







    binary format H0 1
} {}
test binary-7.3 {Tcl_BinaryObjCmd: format} {
    binary format H 1
} \x10
test binary-7.4 {Tcl_BinaryObjCmd: format} {
    binary format H c
} \xc0
} \xC0
test binary-7.5 {Tcl_BinaryObjCmd: format} {
    binary format H* baadf00d
} \xba\xad\xf0\x0d
} \xBA\xAD\xF0\x0D
test binary-7.6 {Tcl_BinaryObjCmd: format} {
    binary format H4 c410
} \xc4\x10
} \xC4\x10
test binary-7.7 {Tcl_BinaryObjCmd: format} {
    binary format H6 c4102
} \xc4\x10\x20
} \xC4\x10\x20
test binary-7.8 {Tcl_BinaryObjCmd: format} {
    binary format H5 c41023304
} \xc4\x10\x20
} \xC4\x10\x20
test binary-7.9 {Tcl_BinaryObjCmd: format} {
    binary format a3X3H5 foo 2
} \x20\x00\x00
test binary-7.10 {Tcl_BinaryObjCmd: format} {
    binary format H2H3 23 456
} \x23\x45\x60
test binary-7.11 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
302
303
304
305
306
307
308
309

310
311
312
313
314
315
316
308
309
310
311
312
313
314

315
316
317
318
319
320
321
322







-
+







} PR
test binary-8.9 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format c2 {0x50}
} -result {number of elements in list does not match count}
test binary-8.10 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    set a {0x50 0x51}
    binary format c $a
} -result "expected integer but got \"0x50 0x51\""
} -result "expected integer but got a list"
test binary-8.11 {Tcl_BinaryObjCmd: format} {
    set a {0x50 0x51}
    binary format c1 $a
} P

test binary-9.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format s
341
342
343
344
345
346
347
348

349
350
351
352
353
354
355
347
348
349
350
351
352
353

354
355
356
357
358
359
360
361







-
+







} P\x00R\x00
test binary-9.10 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format s2 {0x50}
} -result {number of elements in list does not match count}
test binary-9.11 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    set a {0x50 0x51}
    binary format s $a
} -result "expected integer but got \"0x50 0x51\""
} -result "expected integer but got a list"
test binary-9.12 {Tcl_BinaryObjCmd: format} {
    set a {0x50 0x51}
    binary format s1 $a
} P\x00

test binary-10.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format S
380
381
382
383
384
385
386
387

388
389
390
391
392
393
394
386
387
388
389
390
391
392

393
394
395
396
397
398
399
400







-
+







} \x00P\x00R
test binary-10.10 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format S2 {0x50}
} -result {number of elements in list does not match count}
test binary-10.11 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    set a {0x50 0x51}
    binary format S $a
} -result "expected integer but got \"0x50 0x51\""
} -result "expected integer but got a list"
test binary-10.12 {Tcl_BinaryObjCmd: format} {
    set a {0x50 0x51}
    binary format S1 $a
} \x00P

test binary-11.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format i
422
423
424
425
426
427
428
429

430
431
432
433
434
435
436
428
429
430
431
432
433
434

435
436
437
438
439
440
441
442







-
+







} SRQPR\x00\x00\x00
test binary-11.11 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format i2 {0x50}
} -result {number of elements in list does not match count}
test binary-11.12 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    set a {0x50 0x51}
    binary format i $a
} -result "expected integer but got \"0x50 0x51\""
} -result "expected integer but got a list"
test binary-11.13 {Tcl_BinaryObjCmd: format} {
    set a {0x50 0x51}
    binary format i1 $a
} P\x00\x00\x00

test binary-12.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format I
464
465
466
467
468
469
470
471

472
473
474
475
476
477
478
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
558

559
560
561

562
563
564

565
566
567

568
569
570

571
572
573
574
575
576
577

578
579
580
581

582
583
584
585

586
587
588
589
590
591
592
470
471
472
473
474
475
476

477
478
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
558
559
560
561
562
563
564
565
566

567
568
569

570
571
572

573
574
575

576
577
578

579
580
581

582
583
584

585
586
587

588
589
590
591
592
593
594

595
596
597
598

599
600
601
602

603
604
605
606
607
608
609
610







-
+
















-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+












-
+



-
+



-
+
+
+
+
+
+
+
+
+
+
+
+
+












-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+






-
+



-
+



-
+







} PQRS\x00\x00\x00R
test binary-12.11 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format i2 {0x50}
} -result {number of elements in list does not match count}
test binary-12.12 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    set a {0x50 0x51}
    binary format I $a
} -result "expected integer but got \"0x50 0x51\""
} -result "expected integer but got a list"
test binary-12.13 {Tcl_BinaryObjCmd: format} {
    set a {0x50 0x51}
    binary format I1 $a
} \x00\x00\x00P

test binary-13.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format f
} -result {not enough arguments for all format specifiers}
test binary-13.2 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format f blat
} -result {expected floating-point number but got "blat"}
test binary-13.3 {Tcl_BinaryObjCmd: format} {
    binary format f0 1.6
} {}
test binary-13.4 {Tcl_BinaryObjCmd: format} bigEndian {
    binary format f 1.6
} \x3f\xcc\xcc\xcd
} \x3F\xCC\xCC\xCD
test binary-13.5 {Tcl_BinaryObjCmd: format} littleEndian {
    binary format f 1.6
} \xcd\xcc\xcc\x3f
} \xCD\xCC\xCC\x3F
test binary-13.6 {Tcl_BinaryObjCmd: format} bigEndian {
    binary format f* {1.6 3.4}
} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a
} \x3F\xCC\xCC\xCD\x40\x59\x99\x9A
test binary-13.7 {Tcl_BinaryObjCmd: format} littleEndian {
    binary format f* {1.6 3.4}
} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40
} \xCD\xCC\xCC\x3F\x9A\x99\x59\x40
test binary-13.8 {Tcl_BinaryObjCmd: format} bigEndian {
    binary format f2 {1.6 3.4}
} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a
} \x3F\xCC\xCC\xCD\x40\x59\x99\x9A
test binary-13.9 {Tcl_BinaryObjCmd: format} littleEndian {
    binary format f2 {1.6 3.4}
} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40
} \xCD\xCC\xCC\x3F\x9A\x99\x59\x40
test binary-13.10 {Tcl_BinaryObjCmd: format} bigEndian {
    binary format f2 {1.6 3.4 5.6}
} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a
} \x3F\xCC\xCC\xCD\x40\x59\x99\x9A
test binary-13.11 {Tcl_BinaryObjCmd: format} littleEndian {
    binary format f2 {1.6 3.4 5.6}
} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40
} \xCD\xCC\xCC\x3F\x9A\x99\x59\x40
test binary-13.12 {Tcl_BinaryObjCmd: float overflow} bigEndian {
    binary format f -3.402825e+38
} \xff\x7f\xff\xff
} \xFF\x80\x00\x00
test binary-13.13 {Tcl_BinaryObjCmd: float overflow} littleEndian {
    binary format f -3.402825e+38
} \xff\xff\x7f\xff
} \x00\x00\x80\xFF
test binary-13.14 {Tcl_BinaryObjCmd: float underflow} bigEndian {
    binary format f -3.402825e-100
} \x80\x00\x00\x00
test binary-13.15 {Tcl_BinaryObjCmd: float underflow} littleEndian {
    binary format f -3.402825e-100
} \x00\x00\x00\x80
test binary-13.16 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format f2 {1.6}
} -result {number of elements in list does not match count}
test binary-13.17 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    set a {1.6 3.4}
    binary format f $a
} -result "expected floating-point number but got \"1.6 3.4\""
} -result "expected floating-point number but got a list"
test binary-13.18 {Tcl_BinaryObjCmd: format} bigEndian {
    set a {1.6 3.4}
    binary format f1 $a
} \x3f\xcc\xcc\xcd
} \x3F\xCC\xCC\xCD
test binary-13.19 {Tcl_BinaryObjCmd: format} littleEndian {
    set a {1.6 3.4}
    binary format f1 $a
} \xcd\xcc\xcc\x3f
} \xCD\xCC\xCC\x3F
test binary-13.20 {Tcl_BinaryObjCmd: format float Inf} bigEndian {
    binary format f Inf
} \x7F\x80\x00\x00
test binary-13.21 {Tcl_BinaryObjCmd: format float Inf} littleEndian {
    binary format f Inf
} \x00\x00\x80\x7F
test binary-13.22 {Tcl_BinaryObjCmd: format float -Inf} bigEndian {
    binary format f -Inf
} \xFF\x80\x00\x00
test binary-13.23 {Tcl_BinaryObjCmd: format float -Inf} littleEndian {
    binary format f -Inf
} \x00\x00\x80\xFF

test binary-14.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format d
} -result {not enough arguments for all format specifiers}
test binary-14.2 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format d blat
} -result {expected floating-point number but got "blat"}
test binary-14.3 {Tcl_BinaryObjCmd: format} {
    binary format d0 1.6
} {}
test binary-14.4 {Tcl_BinaryObjCmd: format} bigEndian {
    binary format d 1.6
} \x3f\xf9\x99\x99\x99\x99\x99\x9a
} \x3F\xF9\x99\x99\x99\x99\x99\x9A
test binary-14.5 {Tcl_BinaryObjCmd: format} littleEndian {
    binary format d 1.6
} \x9a\x99\x99\x99\x99\x99\xf9\x3f
} \x9A\x99\x99\x99\x99\x99\xF9\x3F
test binary-14.6 {Tcl_BinaryObjCmd: format} bigEndian {
    binary format d* {1.6 3.4}
} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33
} \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33
test binary-14.7 {Tcl_BinaryObjCmd: format} littleEndian {
    binary format d* {1.6 3.4}
} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40
} \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40
test binary-14.8 {Tcl_BinaryObjCmd: format} bigEndian {
    binary format d2 {1.6 3.4}
} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33
} \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33
test binary-14.9 {Tcl_BinaryObjCmd: format} littleEndian {
    binary format d2 {1.6 3.4}
} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40
} \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40
test binary-14.10 {Tcl_BinaryObjCmd: format} bigEndian {
    binary format d2 {1.6 3.4 5.6}
} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33
} \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33
test binary-14.11 {Tcl_BinaryObjCmd: format} littleEndian {
    binary format d2 {1.6 3.4 5.6}
} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40
} \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40
test binary-14.14 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format d2 {1.6}
} -result {number of elements in list does not match count}
test binary-14.15 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    set a {1.6 3.4}
    binary format d $a
} -result "expected floating-point number but got \"1.6 3.4\""
} -result "expected floating-point number but got a list"
test binary-14.16 {Tcl_BinaryObjCmd: format} bigEndian {
    set a {1.6 3.4}
    binary format d1 $a
} \x3f\xf9\x99\x99\x99\x99\x99\x9a
} \x3F\xF9\x99\x99\x99\x99\x99\x9A
test binary-14.17 {Tcl_BinaryObjCmd: format} littleEndian {
    set a {1.6 3.4}
    binary format d1 $a
} \x9a\x99\x99\x99\x99\x99\xf9\x3f
} \x9A\x99\x99\x99\x99\x99\xF9\x3F
test binary-14.18 {FormatNumber: Bug 1116542} {
    binary scan [binary format d 1.25] d w
    set w
} 1.25

test binary-15.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format ax*a "y" "z"
755
756
757
758
759
760
761
762










763
764
765
766
767
768
769
773
774
775
776
777
778
779

780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796







-
+
+
+
+
+
+
+
+
+
+







    list [binary scan "abc def \x00  " A* arg1] $arg1
} -result {1 {abc def}}
test binary-21.12 {Tcl_BinaryObjCmd: scan} -setup {
    unset -nocomplain arg1
} -body {
    list [binary scan "abc def \x00ghi  " A* arg1] $arg1
} -result [list 1 "abc def \x00ghi"]

test binary-21.13 {Tcl_BinaryObjCmd: scan} -setup {
    unset -nocomplain arg1
} -body {
    list [binary scan "abc def \x00  " C* arg1] $arg1
} -result {1 {abc def }}
test binary-21.14 {Tcl_BinaryObjCmd: scan} -setup {
    unset -nocomplain arg1
} -body {
    list [binary scan "abc def \x00ghi" C* arg1] $arg1
} -result {1 {abc def }}
test binary-22.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
    binary scan abc b
} -result {not enough arguments for all format specifiers}
test binary-22.2 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\x53 b* arg1] $arg1
} {1 0100101011001010}
861
862
863
864
865
866
867
868

869
870
871
872

873
874
875
876
877
878
879
880
881
882
883
884

885
886
887
888
889
890
891
888
889
890
891
892
893
894

895
896
897
898

899
900
901
902
903
904
905
906
907
908
909
910

911
912
913
914
915
916
917
918







-
+



-
+











-
+







} -result {2 01110 1000011100000101}

test binary-24.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
    binary scan abc h
} -result {not enough arguments for all format specifiers}
test binary-24.2 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3 h* arg1] $arg1
    list [binary scan \x52\xA3 h* arg1] $arg1
} {1 253a}
test binary-24.3 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \xc2\xa3 h arg1] $arg1
    list [binary scan \xC2\xA3 h arg1] $arg1
} {1 2}
test binary-24.4 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x82\x53 h1 arg1] $arg1
} {1 2}
test binary-24.5 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\x53 h0 arg1] $arg1
} {1 {}}
test binary-24.6 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \xf2\x53 h2 arg1] $arg1
    list [binary scan \xF2\x53 h2 arg1] $arg1
} {1 2f}
test binary-24.7 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\x53 h3 arg1] $arg1
} {1 253}
test binary-24.8 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
907
908
909
910
911
912
913
914

915
916
917
918

919
920
921
922
923
924
925
926
927
928
929
930

931
932
933
934
935
936
937
934
935
936
937
938
939
940

941
942
943
944

945
946
947
948
949
950
951
952
953
954
955
956

957
958
959
960
961
962
963
964







-
+



-
+











-
+







} -result {2 07 7850}

test binary-25.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
    binary scan abc H
} -result {not enough arguments for all format specifiers}
test binary-25.2 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3 H* arg1] $arg1
    list [binary scan \x52\xA3 H* arg1] $arg1
} {1 52a3}
test binary-25.3 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \xc2\xa3 H arg1] $arg1
    list [binary scan \xC2\xA3 H arg1] $arg1
} {1 c}
test binary-25.4 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x82\x53 H1 arg1] $arg1
} {1 8}
test binary-25.5 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\x53 H0 arg1] $arg1
} {1 {}}
test binary-25.6 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \xf2\x53 H2 arg1] $arg1
    list [binary scan \xF2\x53 H2 arg1] $arg1
} {1 f2}
test binary-25.7 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\x53 H3 arg1] $arg1
} {1 525}
test binary-25.8 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
952
953
954
955
956
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
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
1116
1117
1118

1119
1120
1121
1122

1123
1124
1125
1126

1127
1128
1129
1130
1131
1132
1133
1134

1135
1136
1137
1138

1139
1140
1141
1142

1143
1144
1145
1146

1147
1148
1149
1150

1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167

1168
1169
1170
1171

1172
1173
1174
1175

1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187

1188
1189
1190
1191

1192
1193
1194
1195

1196
1197
1198
1199

1200
1201
1202
1203

1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220

1221
1222
1223
1224

1225
1226
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
1354

1355
1356
1357
1358
1359
1360

1361
1362
1363
1364
1365
1366

1367
1368
1369
1370
1371
1372
1373
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
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

1116
1117
1118
1119

1120
1121
1122
1123

1124
1125
1126
1127

1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144

1145
1146
1147
1148

1149
1150
1151
1152

1153
1154
1155
1156
1157
1158
1159
1160

1161
1162
1163
1164

1165
1166
1167
1168

1169
1170
1171
1172

1173
1174
1175
1176

1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197

1198
1199
1200
1201

1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213

1214
1215
1216
1217

1218
1219
1220
1221

1222
1223
1224
1225

1226
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

1354
1355
1356
1357

1358
1359
1360
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

1387
1388
1389
1390
1391
1392

1393
1394
1395
1396
1397
1398
1399
1400







-
+



-
+



-
+



-
+



-
+



-
+




















-
+



-
+



-
+



















-
+



-
+



-
+



-
+



-
+
















-
+



-
+





-
+





-
+







-
+



-
+



-
+



-
+



-
+
















-
+



-
+



-
+







-
+



-
+



-
+



-
+



-
+
















-
+



-
+



-
+











-
+



-
+



-
+



-
+



-
+
















-
+



-
+



-
+











-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+










-
+





-
+





-
+







-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+










-
+





-
+





-
+







} {2 70 8705}

test binary-26.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
    binary scan abc c
} -result {not enough arguments for all format specifiers}
test binary-26.2 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3 c* arg1] $arg1
    list [binary scan \x52\xA3 c* arg1] $arg1
} {1 {82 -93}}
test binary-26.3 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3 c arg1] $arg1
    list [binary scan \x52\xA3 c arg1] $arg1
} {1 82}
test binary-26.4 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3 c1 arg1] $arg1
    list [binary scan \x52\xA3 c1 arg1] $arg1
} {1 82}
test binary-26.5 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3 c0 arg1] $arg1
    list [binary scan \x52\xA3 c0 arg1] $arg1
} {1 {}}
test binary-26.6 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3 c2 arg1] $arg1
    list [binary scan \x52\xA3 c2 arg1] $arg1
} {1 {82 -93}}
test binary-26.7 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \xff c arg1] $arg1
    list [binary scan \xFF c arg1] $arg1
} {1 -1}
test binary-26.8 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    set arg1 foo
    list [binary scan \x52 c3 arg1] $arg1
} {0 foo}
test binary-26.9 {Tcl_BinaryObjCmd: scan} -setup {
    unset -nocomplain arg1
} -returnCodes error -body {
    set arg1 1
    binary scan \x52\x53 c1 arg1(a)
} -result {can't set "arg1(a)": variable isn't array}
test binary-26.10 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x70\x87\x05 c2c* arg1 arg2] $arg1 $arg2
} {2 {112 -121} 5}
test binary-26.11 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3 cu* arg1] $arg1
    list [binary scan \x52\xA3 cu* arg1] $arg1
} {1 {82 163}}
test binary-26.12 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3 cu arg1] $arg1
    list [binary scan \x52\xA3 cu arg1] $arg1
} {1 82}
test binary-26.13 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \xff cu arg1] $arg1
    list [binary scan \xFF cu arg1] $arg1
} {1 255}
test binary-26.14 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x80\x80 cuc arg1 arg2] $arg1 $arg2
} {2 128 -128}
test binary-26.15 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x80\x80 ccu arg1 arg2] $arg1 $arg2
} {2 -128 128}

test binary-27.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
    binary scan abc s
} -result {not enough arguments for all format specifiers}
test binary-27.2 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54 s* arg1] $arg1
    list [binary scan \x52\xA3\x53\x54 s* arg1] $arg1
} {1 {-23726 21587}}
test binary-27.3 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54 s arg1] $arg1
    list [binary scan \x52\xA3\x53\x54 s arg1] $arg1
} {1 -23726}
test binary-27.4 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3 s1 arg1] $arg1
    list [binary scan \x52\xA3 s1 arg1] $arg1
} {1 -23726}
test binary-27.5 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3 s0 arg1] $arg1
    list [binary scan \x52\xA3 s0 arg1] $arg1
} {1 {}}
test binary-27.6 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54 s2 arg1] $arg1
    list [binary scan \x52\xA3\x53\x54 s2 arg1] $arg1
} {1 {-23726 21587}}
test binary-27.7 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    set arg1 foo
    list [binary scan \x52 s1 arg1] $arg1
} {0 foo}
test binary-27.8 {Tcl_BinaryObjCmd: scan} -setup {
    unset -nocomplain arg1
} -returnCodes error -body {
    set arg1 1
    binary scan \x52\x53 s1 arg1(a)
} -result {can't set "arg1(a)": variable isn't array}
test binary-27.9 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x52\xa3\x53\x54\x05 s2c* arg1 arg2] $arg1 $arg2
    list [binary scan \x52\xA3\x53\x54\x05 s2c* arg1 arg2] $arg1 $arg2
} {2 {-23726 21587} 5}
test binary-27.10 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54 su* arg1] $arg1
    list [binary scan \x52\xA3\x53\x54 su* arg1] $arg1
} {1 {41810 21587}}
test binary-27.11 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \xff\xff\xff\xff sus arg1 arg2] $arg1 $arg2
    list [binary scan \xFF\xFF\xFF\xFF sus arg1 arg2] $arg1 $arg2
} {2 65535 -1}
test binary-27.12 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \xff\xff\xff\xff ssu arg1 arg2] $arg1 $arg2
    list [binary scan \xFF\xFF\xFF\xFF ssu arg1 arg2] $arg1 $arg2
} {2 -1 65535}

test binary-28.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
    binary scan abc S
} -result {not enough arguments for all format specifiers}
test binary-28.2 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54 S* arg1] $arg1
    list [binary scan \x52\xA3\x53\x54 S* arg1] $arg1
} {1 {21155 21332}}
test binary-28.3 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54 S arg1] $arg1
    list [binary scan \x52\xA3\x53\x54 S arg1] $arg1
} {1 21155}
test binary-28.4 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3 S1 arg1] $arg1
    list [binary scan \x52\xA3 S1 arg1] $arg1
} {1 21155}
test binary-28.5 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3 S0 arg1] $arg1
    list [binary scan \x52\xA3 S0 arg1] $arg1
} {1 {}}
test binary-28.6 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54 S2 arg1] $arg1
    list [binary scan \x52\xA3\x53\x54 S2 arg1] $arg1
} {1 {21155 21332}}
test binary-28.7 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    set arg1 foo
    list [binary scan \x52 S1 arg1] $arg1
} {0 foo}
test binary-28.8 {Tcl_BinaryObjCmd: scan} -setup {
    unset -nocomplain arg1
} -returnCodes error -body {
    set arg1 1
    binary scan \x52\x53 S1 arg1(a)
} -result {can't set "arg1(a)": variable isn't array}
test binary-28.9 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x52\xa3\x53\x54\x05 S2c* arg1 arg2] $arg1 $arg2
    list [binary scan \x52\xA3\x53\x54\x05 S2c* arg1 arg2] $arg1 $arg2
} {2 {21155 21332} 5}
test binary-28.10 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54 Su* arg1] $arg1
    list [binary scan \x52\xA3\x53\x54 Su* arg1] $arg1
} {1 {21155 21332}}
test binary-28.11 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \xa3\x52\x54\x53 Su* arg1] $arg1
    list [binary scan \xA3\x52\x54\x53 Su* arg1] $arg1
} {1 {41810 21587}}

test binary-29.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
    binary scan abc i
} -result {not enough arguments for all format specifiers}
test binary-29.2 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 i* arg1] $arg1
    list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 i* arg1] $arg1
} {1 {1414767442 67305985}}
test binary-29.3 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 i arg1] $arg1
    list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 i arg1] $arg1
} {1 1414767442}
test binary-29.4 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54 i1 arg1] $arg1
    list [binary scan \x52\xA3\x53\x54 i1 arg1] $arg1
} {1 1414767442}
test binary-29.5 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53 i0 arg1] $arg1
    list [binary scan \x52\xA3\x53 i0 arg1] $arg1
} {1 {}}
test binary-29.6 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 i2 arg1] $arg1
    list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 i2 arg1] $arg1
} {1 {1414767442 67305985}}
test binary-29.7 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    set arg1 foo
    list [binary scan \x52 i1 arg1] $arg1
} {0 foo}
test binary-29.8 {Tcl_BinaryObjCmd: scan} -setup {
    unset -nocomplain arg1
} -returnCodes error -body {
    set arg1 1
    binary scan \x52\x53\x53\x54 i1 arg1(a)
} -result {can't set "arg1(a)": variable isn't array}
test binary-29.9 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04\x05 i2c* arg1 arg2] $arg1 $arg2
    list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04\x05 i2c* arg1 arg2] $arg1 $arg2
} {2 {1414767442 67305985} 5}
test binary-29.10 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1 arg2
    list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff iui arg1 arg2] $arg1 $arg2
    list [binary scan \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF iui arg1 arg2] $arg1 $arg2
} {2 4294967295 -1}
test binary-29.11 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1 arg2
    list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff iiu arg1 arg2] $arg1 $arg2
    list [binary scan \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF iiu arg1 arg2] $arg1 $arg2
} {2 -1 4294967295}
test binary-29.12 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1 arg2
    list [binary scan \x80\x00\x00\x00\x00\x00\x00\x80 iuiu arg1 arg2] $arg1 $arg2
} {2 128 2147483648}

test binary-30.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
    binary scan abc I
} -result {not enough arguments for all format specifiers}
test binary-30.2 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 I* arg1] $arg1
    list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 I* arg1] $arg1
} {1 {1386435412 16909060}}
test binary-30.3 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 I arg1] $arg1
    list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 I arg1] $arg1
} {1 1386435412}
test binary-30.4 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54 I1 arg1] $arg1
    list [binary scan \x52\xA3\x53\x54 I1 arg1] $arg1
} {1 1386435412}
test binary-30.5 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53 I0 arg1] $arg1
    list [binary scan \x52\xA3\x53 I0 arg1] $arg1
} {1 {}}
test binary-30.6 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 I2 arg1] $arg1
    list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 I2 arg1] $arg1
} {1 {1386435412 16909060}}
test binary-30.7 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    set arg1 foo
    list [binary scan \x52 I1 arg1] $arg1
} {0 foo}
test binary-30.8 {Tcl_BinaryObjCmd: scan} -setup {
    unset -nocomplain arg1
} -returnCodes error -body {
    set arg1 1
    binary scan \x52\x53\x53\x54 I1 arg1(a)
} -result {can't set "arg1(a)": variable isn't array}
test binary-30.9 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04\x05 I2c* arg1 arg2] $arg1 $arg2
    list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04\x05 I2c* arg1 arg2] $arg1 $arg2
} {2 {1386435412 16909060} 5}
test binary-30.10 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1 arg2
    list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff IuI arg1 arg2] $arg1 $arg2
    list [binary scan \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF IuI arg1 arg2] $arg1 $arg2
} {2 4294967295 -1}
test binary-30.11 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1 arg2
    list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff IIu arg1 arg2] $arg1 $arg2
    list [binary scan \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF IIu arg1 arg2] $arg1 $arg2
} {2 -1 4294967295}
test binary-30.12 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1 arg2
    list [binary scan \x80\x00\x00\x00\x00\x00\x00\x80 IuIu arg1 arg2] $arg1 $arg2
} {2 2147483648 128}

test binary-31.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
    binary scan abc f
} -result {not enough arguments for all format specifiers}
test binary-31.2 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a f* arg1] $arg1
    list [binary scan \x3F\xCC\xCC\xCD\x40\x59\x99\x9A f* arg1] $arg1
} {1 {1.600000023841858 3.4000000953674316}}
test binary-31.3 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 f* arg1] $arg1
    list [binary scan \xCD\xCC\xCC\x3F\x9A\x99\x59\x40 f* arg1] $arg1
} {1 {1.600000023841858 3.4000000953674316}}
test binary-31.4 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a f arg1] $arg1
    list [binary scan \x3F\xCC\xCC\xCD\x40\x59\x99\x9A f arg1] $arg1
} {1 1.600000023841858}
test binary-31.5 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 f arg1] $arg1
    list [binary scan \xCD\xCC\xCC\x3F\x9A\x99\x59\x40 f arg1] $arg1
} {1 1.600000023841858}
test binary-31.6 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xcc\xcc\xcd f1 arg1] $arg1
    list [binary scan \x3F\xCC\xCC\xCD f1 arg1] $arg1
} {1 1.600000023841858}
test binary-31.7 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \xcd\xcc\xcc\x3f f1 arg1] $arg1
    list [binary scan \xCD\xCC\xCC\x3F f1 arg1] $arg1
} {1 1.600000023841858}
test binary-31.8 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xcc\xcc\xcd f0 arg1] $arg1
    list [binary scan \x3F\xCC\xCC\xCD f0 arg1] $arg1
} {1 {}}
test binary-31.9 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \xcd\xcc\xcc\x3f f0 arg1] $arg1
    list [binary scan \xCD\xCC\xCC\x3F f0 arg1] $arg1
} {1 {}}
test binary-31.10 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a f2 arg1] $arg1
    list [binary scan \x3F\xCC\xCC\xCD\x40\x59\x99\x9A f2 arg1] $arg1
} {1 {1.600000023841858 3.4000000953674316}}
test binary-31.11 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 f2 arg1] $arg1
    list [binary scan \xCD\xCC\xCC\x3F\x9A\x99\x59\x40 f2 arg1] $arg1
} {1 {1.600000023841858 3.4000000953674316}}
test binary-31.12 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    set arg1 foo
    list [binary scan \x52 f1 arg1] $arg1
} {0 foo}
test binary-31.13 {Tcl_BinaryObjCmd: scan} -setup {
    unset -nocomplain arg1
} -returnCodes error -body {
    set arg1 1
    binary scan \x3f\xcc\xcc\xcd f1 arg1(a)
    binary scan \x3F\xCC\xCC\xCD f1 arg1(a)
} -result {can't set "arg1(a)": variable isn't array}
test binary-31.14 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a\x05 f2c* arg1 arg2] $arg1 $arg2
    list [binary scan \x3F\xCC\xCC\xCD\x40\x59\x99\x9A\x05 f2c* arg1 arg2] $arg1 $arg2
} {2 {1.600000023841858 3.4000000953674316} 5}
test binary-31.15 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40\x05 f2c* arg1 arg2] $arg1 $arg2
    list [binary scan \xCD\xCC\xCC\x3F\x9A\x99\x59\x40\x05 f2c* arg1 arg2] $arg1 $arg2
} {2 {1.600000023841858 3.4000000953674316} 5}

test binary-32.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
    binary scan abc d
} -result {not enough arguments for all format specifiers}
test binary-32.2 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 d* arg1] $arg1
    list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33 d* arg1] $arg1
} {1 {1.6 3.4}}
test binary-32.3 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 d* arg1] $arg1
    list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40 d* arg1] $arg1
} {1 {1.6 3.4}}
test binary-32.4 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 d arg1] $arg1
    list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33 d arg1] $arg1
} {1 1.6}
test binary-32.5 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 d arg1] $arg1
    list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40 d arg1] $arg1
} {1 1.6}
test binary-32.6 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a d1 arg1] $arg1
    list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A d1 arg1] $arg1
} {1 1.6}
test binary-32.7 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f d1 arg1] $arg1
    list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F d1 arg1] $arg1
} {1 1.6}
test binary-32.8 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a d0 arg1] $arg1
    list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A d0 arg1] $arg1
} {1 {}}
test binary-32.9 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f d0 arg1] $arg1
    list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F d0 arg1] $arg1
} {1 {}}
test binary-32.10 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 d2 arg1] $arg1
    list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33 d2 arg1] $arg1
} {1 {1.6 3.4}}
test binary-32.11 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 d2 arg1] $arg1
    list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40 d2 arg1] $arg1
} {1 {1.6 3.4}}
test binary-32.12 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    set arg1 foo
    list [binary scan \x52 d1 arg1] $arg1
} {0 foo}
test binary-32.13 {Tcl_BinaryObjCmd: scan} -setup {
    unset -nocomplain arg1
} -returnCodes error -body {
    set arg1 1
    binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a d1 arg1(a)
    binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A d1 arg1(a)
} -result {can't set "arg1(a)": variable isn't array}
test binary-32.14 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33\x05 d2c* arg1 arg2] $arg1 $arg2
    list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33\x05 d2c* arg1 arg2] $arg1 $arg2
} {2 {1.6 3.4} 5}
test binary-32.15 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40\x05 d2c* arg1 arg2] $arg1 $arg2
    list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40\x05 d2c* arg1 arg2] $arg1 $arg2
} {2 {1.6 3.4} 5}

test binary-33.1 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    unset -nocomplain arg2
    list [binary scan abcdefg a2xa3 arg1 arg2] $arg1 $arg2
} {2 ab def}
1530
1531
1532
1533
1534
1535
1536
1537

1538
1539
1540

1541
1542
1543

1544
1545
1546

1547
1548
1549
1550

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
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







-
+


-
+


-
+


-
+



-
+



















-
+




















-
+



-
+







    set x [binary format c1i1 1 1]
} \x01\x01\x00\x00\x00
test binary-38.4 {FormatNumber: word alignment} {
    set x [binary format c1I1 1 1]
} \x01\x00\x00\x00\x01
test binary-38.5 {FormatNumber: word alignment} bigEndian {
    set x [binary format c1d1 1 1.6]
} \x01\x3f\xf9\x99\x99\x99\x99\x99\x9a
} \x01\x3F\xF9\x99\x99\x99\x99\x99\x9A
test binary-38.6 {FormatNumber: word alignment} littleEndian {
    set x [binary format c1d1 1 1.6]
} \x01\x9a\x99\x99\x99\x99\x99\xf9\x3f
} \x01\x9A\x99\x99\x99\x99\x99\xF9\x3F
test binary-38.7 {FormatNumber: word alignment} bigEndian {
    set x [binary format c1f1 1 1.6]
} \x01\x3f\xcc\xcc\xcd
} \x01\x3F\xCC\xCC\xCD
test binary-38.8 {FormatNumber: word alignment} littleEndian {
    set x [binary format c1f1 1 1.6]
} \x01\xcd\xcc\xcc\x3f
} \x01\xCD\xCC\xCC\x3F

test binary-39.1 {ScanNumber: sign extension} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3 c2 arg1] $arg1
    list [binary scan \x52\xA3 c2 arg1] $arg1
} {1 {82 -93}}
test binary-39.2 {ScanNumber: sign extension} {
    unset -nocomplain arg1
    list [binary scan \x01\x02\x01\x81\x82\x01\x81\x82 s4 arg1] $arg1
} {1 {513 -32511 386 -32127}}
test binary-39.3 {ScanNumber: sign extension} {
    unset -nocomplain arg1
    list [binary scan \x01\x02\x01\x81\x82\x01\x81\x82 S4 arg1] $arg1
} {1 {258 385 -32255 -32382}}
test binary-39.4 {ScanNumber: sign extension} {
    unset -nocomplain arg1
    list [binary scan \x01\x01\x01\x02\x81\x01\x01\x01\x01\x82\x01\x01\x01\x01\x82\x01\x01\x01\x01\x81 i5 arg1] $arg1
} {1 {33620225 16843137 16876033 25297153 -2130640639}}
test binary-39.5 {ScanNumber: sign extension} {
    unset -nocomplain arg1
    list [binary scan \x01\x01\x01\x02\x81\x01\x01\x01\x01\x82\x01\x01\x01\x01\x82\x01\x01\x01\x01\x81 I5 arg1] $arg1
} {1 {16843010 -2130640639 25297153 16876033 16843137}}
test binary-39.6 {ScanNumber: no sign extension} {
    unset -nocomplain arg1
    list [binary scan \x52\xa3 cu2 arg1] $arg1
    list [binary scan \x52\xA3 cu2 arg1] $arg1
} {1 {82 163}}
test binary-39.7 {ScanNumber: no sign extension} {
    unset -nocomplain arg1
    list [binary scan \x01\x02\x01\x81\x82\x01\x81\x82 su4 arg1] $arg1
} {1 {513 33025 386 33409}}
test binary-39.8 {ScanNumber: no sign extension} {
    unset -nocomplain arg1
    list [binary scan \x01\x02\x01\x81\x82\x01\x81\x82 Su4 arg1] $arg1
} {1 {258 385 33281 33154}}
test binary-39.9 {ScanNumber: no sign extension} {
    unset -nocomplain arg1
    list [binary scan \x01\x01\x01\x02\x81\x01\x01\x01\x01\x82\x01\x01\x01\x01\x82\x01\x01\x01\x01\x81 iu5 arg1] $arg1
} {1 {33620225 16843137 16876033 25297153 2164326657}}
test binary-39.10 {ScanNumber: no sign extension} {
    unset -nocomplain arg1
    list [binary scan \x01\x01\x01\x02\x81\x01\x01\x01\x01\x82\x01\x01\x01\x01\x82\x01\x01\x01\x01\x81 Iu5 arg1] $arg1
} {1 {16843010 2164326657 25297153 16876033 16843137}}

test binary-40.3 {ScanNumber: NaN} -body {
    unset -nocomplain arg1
    list [binary scan \xff\xff\xff\xff f1 arg1] $arg1
    list [binary scan \xFF\xFF\xFF\xFF f1 arg1] $arg1
} -match glob -result {1 -NaN*}
test binary-40.4 {ScanNumber: NaN} -body {
    unset -nocomplain arg1
    list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff d arg1] $arg1
    list [binary scan \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF d arg1] $arg1
} -match glob -result {1 -NaN*}

test binary-41.1 {ScanNumber: word alignment} -setup {
    unset -nocomplain arg1 arg2
} -body {
    list [binary scan \x01\x01\x00 c1s1 arg1 arg2] $arg1 $arg2
} -result {2 1 1}
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
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







-
+




-
+




-
+




-
+







    unset -nocomplain arg1 arg2
} -body {
    list [binary scan \x01\x00\x00\x00\x01 c1I1 arg1 arg2] $arg1 $arg2
} -result {2 1 1}
test binary-41.5 {ScanNumber: word alignment} -setup {
    unset -nocomplain arg1 arg2
} -constraints bigEndian -body {
    list [binary scan \x01\x3f\xcc\xcc\xcd c1f1 arg1 arg2] $arg1 $arg2
    list [binary scan \x01\x3F\xCC\xCC\xCD c1f1 arg1 arg2] $arg1 $arg2
} -result {2 1 1.600000023841858}
test binary-41.6 {ScanNumber: word alignment} -setup {
    unset -nocomplain arg1 arg2
} -constraints littleEndian -body {
    list [binary scan \x01\xcd\xcc\xcc\x3f c1f1 arg1 arg2] $arg1 $arg2
    list [binary scan \x01\xCD\xCC\xCC\x3F c1f1 arg1 arg2] $arg1 $arg2
} -result {2 1 1.600000023841858}
test binary-41.7 {ScanNumber: word alignment} -setup {
    unset -nocomplain arg1 arg2
} -constraints bigEndian -body {
    list [binary scan \x01\x3f\xf9\x99\x99\x99\x99\x99\x9a c1d1 arg1 arg2] $arg1 $arg2
    list [binary scan \x01\x3F\xF9\x99\x99\x99\x99\x99\x9A c1d1 arg1 arg2] $arg1 $arg2
} -result {2 1 1.6}
test binary-41.8 {ScanNumber: word alignment} -setup {
    unset -nocomplain arg1 arg2
} -constraints littleEndian -body {
    list [binary scan \x01\x9a\x99\x99\x99\x99\x99\xf9\x3f c1d1 arg1 arg2] $arg1 $arg2
    list [binary scan \x01\x9A\x99\x99\x99\x99\x99\xF9\x3F c1d1 arg1 arg2] $arg1 $arg2
} -result {2 1 1.6}

test binary-42.1 {Tcl_BinaryObjCmd: bad arguments} -constraints {} -body {
    binary ?
} -returnCodes error -match glob -result {unknown or ambiguous subcommand "?": *}

# Wide int (guaranteed at least 64-bit) handling
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
1727
1728
1729
1730
1731
1732
1733


1734
1735
1736

1737
1738
1739
1740
1741
1742


1743
1744
1745

1746
1747
1748

1749
1750

1751
1752

1753
1754
1755
1756
1757
1758
1759
1760







-
-
+
+

-
+





-
-
+
+

-
+


-
+

-
+

-
+







} {66 64 -1 -1 -1 -1 -1 -1 -1 -1 65 76}
test binary-45.2 {Tcl_BinaryObjCmd: combined wide int handling} {
    binary scan [binary format sWs 16450 0x7fffffff 19521] c* x
    set x
} {66 64 0 0 0 0 127 -1 -1 -1 65 76}

test binary-46.1 {Tcl_BinaryObjCmd: handling of non-ISO8859-1 chars} {
    binary format a* \u20ac
} \u00ac
    binary format a* €
} \xAC
test binary-46.2 {Tcl_BinaryObjCmd: handling of non-ISO8859-1 chars} {
    list [binary scan [binary format a* \u20ac\u20bd] s x] $x
    list [binary scan [binary format a* €₽] s x] $x
} {1 -16980}
test binary-46.3 {Tcl_BinaryObjCmd: handling of non-ISO8859-1 chars} {
    set x {}
    set y {}
    set z {}
    list [binary scan [binary format a* \u20ac\u20bd] aaa x y z] $x $y $z
} "2 \u00ac \u00bd {}"
    list [binary scan [binary format a* €₽] aaa x y z] $x $y $z
} "2 \xAC \xBD {}"
test binary-46.4 {Tcl_BinaryObjCmd: handling of non-ISO8859-1 chars} {
    set x [encoding convertto iso8859-15 \u20ac]
    set x [encoding convertto iso8859-15 €]
    set y [binary format a* $x]
    list $x $y
} "\u00a4 \u00a4"
} "\xA4 \xA4"
test binary-46.5 {Tcl_BinaryObjCmd: handling of non-ISO8859-1 chars} {
    set x [binary scan \u00a4 a* y]
    set x [binary scan \xA4 a* y]
    list $x $y [encoding convertfrom iso8859-15 $y]
} "1 \u00a4 \u20ac"
} "1 \xA4 €"

test binary-47.1 {Tcl_BinaryObjCmd: number cache reference count handling} {
    # This test is only reliable when memory debugging is turned on, but
    # without even memory debugging it should still generate the expected
    # answers and might therefore still pick up memory corruption caused by
    # [Bug 851747].
    list [binary scan aba ccc x x x] $x
1783
1784
1785
1786
1787
1788
1789
1790

1791
1792
1793
1794
1795
1796
1797
1810
1811
1812
1813
1814
1815
1816

1817
1818
1819
1820
1821
1822
1823
1824







-
+







} P\x00R\x00
test binary-48.16 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format t2 {0x50}
} -result {number of elements in list does not match count}
test binary-48.17 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    set a {0x50 0x51}
    binary format t $a
} -result "expected integer but got \"0x50 0x51\""
} -result "expected integer but got a list"
test binary-48.18 {Tcl_BinaryObjCmd: format} bigEndian {
    set a {0x50 0x51}
    binary format t1 $a
} \x00P
test binary-48.19 {Tcl_BinaryObjCmd: format} littleEndian {
    set a {0x50 0x51}
    binary format t1 $a
1830
1831
1832
1833
1834
1835
1836
1837

1838
1839
1840
1841
1842
1843
1844
1857
1858
1859
1860
1861
1862
1863

1864
1865
1866
1867
1868
1869
1870
1871







-
+







} SRQPR\x00\x00\x00
test binary-49.11 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format n2 {0x50}
} -result {number of elements in list does not match count}
test binary-49.12 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    set a {0x50 0x51}
    binary format n $a
} -result "expected integer but got \"0x50 0x51\""
} -result "expected integer but got a list"
test binary-49.13 {Tcl_BinaryObjCmd: format} littleEndian {
    set a {0x50 0x51}
    binary format n1 $a
} P\x00\x00\x00
test binary-49.14 {Tcl_BinaryObjCmd: format} bigEndian {
    binary format n 0x50
} \x00\x00\x00P
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

1958
1959
1960

1961
1962
1963

1964
1965
1966

1967
1968
1969

1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982

1983
1984
1985
1986

1987
1988
1989
1990


































1991
1992
1993
1994
1995
1996
1997
1998

1999
2000
2001
2002

2003
2004
2005
2006

2007
2008
2009
2010

2011
2012
2013
2014

2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031

2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106

2107
2108
2109
2110

2111
2112
2113
2114

2115
2116
2117
2118

2119
2120
2121
2122

2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139

2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160

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
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
2273

2274
2275
2276
2277
2278
2279
2280
2281
2282

2283
2284
2285
2286

2287
2288
2289
2290

2291
2292
2293
2294

2295
2296
2297
2298

2299
2300
2301
2302

2303
2304
2305
2306

2307
2308
2309
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
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968

1969
1970
1971

1972
1973
1974

1975
1976
1977

1978
1979
1980

1981
1982
1983

1984
1985
1986

1987
1988
1989

1990
1991
1992

1993
1994
1995

1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008

2009
2010
2011
2012

2013
2014
2015
2016

2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111

2112
2113
2114
2115

2116
2117
2118
2119

2120
2121
2122
2123

2124
2125
2126
2127

2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144

2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273

2274
2275
2276
2277

2278
2279
2280
2281

2282
2283
2284
2285

2286
2287
2288
2289

2290
2291
2292
2293

2294
2295
2296
2297

2298
2299
2300
2301

2302
2303
2304
2305

2306
2307
2308
2309

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
2390
2391
2392
2393
2394

2395
2396
2397
2398
2399
2400

2401
2402
2403
2404
2405
2406
2407
2408







-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+






-
+



-
+



-
+













-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+












-
+



-
+



-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+



-
+



-
+



-
+



-
+
















-
+




















-
+



-
+



-
+



-
+



-
+
















-
+




















-
+



-
+



-
+



-
+



-
+
















-
+




















-
+



-
+



-
+



-
+



-
+
















-
+




















-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+










-
+





-
+





-
+








-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+










-
+





-
+





-
+







    binary format q blat
} -result {expected floating-point number but got "blat"}
test binary-51.3 {Tcl_BinaryObjCmd: format} {
    binary format q0 1.6
} {}
test binary-51.4 {Tcl_BinaryObjCmd: format} {} {
    binary format Q 1.6
} \x3f\xf9\x99\x99\x99\x99\x99\x9a
} \x3F\xF9\x99\x99\x99\x99\x99\x9A
test binary-51.5 {Tcl_BinaryObjCmd: format} {} {
    binary format q 1.6
} \x9a\x99\x99\x99\x99\x99\xf9\x3f
} \x9A\x99\x99\x99\x99\x99\xF9\x3F
test binary-51.6 {Tcl_BinaryObjCmd: format} {} {
    binary format Q* {1.6 3.4}
} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33
} \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33
test binary-51.7 {Tcl_BinaryObjCmd: format} {} {
    binary format q* {1.6 3.4}
} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40
} \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40
test binary-51.8 {Tcl_BinaryObjCmd: format} {} {
    binary format Q2 {1.6 3.4}
} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33
} \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33
test binary-51.9 {Tcl_BinaryObjCmd: format} {} {
    binary format q2 {1.6 3.4}
} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40
} \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40
test binary-51.10 {Tcl_BinaryObjCmd: format} {} {
    binary format Q2 {1.6 3.4 5.6}
} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33
} \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33
test binary-51.11 {Tcl_BinaryObjCmd: format} {} {
    binary format q2 {1.6 3.4 5.6}
} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40
} \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40
test binary-51.14 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format q2 {1.6}
} -result {number of elements in list does not match count}
test binary-51.15 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    set a {1.6 3.4}
    binary format q $a
} -result "expected floating-point number but got \"1.6 3.4\""
} -result "expected floating-point number but got a list"
test binary-51.16 {Tcl_BinaryObjCmd: format} {} {
    set a {1.6 3.4}
    binary format Q1 $a
} \x3f\xf9\x99\x99\x99\x99\x99\x9a
} \x3F\xF9\x99\x99\x99\x99\x99\x9A
test binary-51.17 {Tcl_BinaryObjCmd: format} {} {
    set a {1.6 3.4}
    binary format q1 $a
} \x9a\x99\x99\x99\x99\x99\xf9\x3f
} \x9A\x99\x99\x99\x99\x99\xF9\x3F

# format R/r
test binary-53.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format r
} -result {not enough arguments for all format specifiers}
test binary-53.2 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format r blat
} -result {expected floating-point number but got "blat"}
test binary-53.3 {Tcl_BinaryObjCmd: format} {
    binary format f0 1.6
} {}
test binary-53.4 {Tcl_BinaryObjCmd: format} {} {
    binary format R 1.6
} \x3f\xcc\xcc\xcd
} \x3F\xCC\xCC\xCD
test binary-53.5 {Tcl_BinaryObjCmd: format} {} {
    binary format r 1.6
} \xcd\xcc\xcc\x3f
} \xCD\xCC\xCC\x3F
test binary-53.6 {Tcl_BinaryObjCmd: format} {} {
    binary format R* {1.6 3.4}
} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a
} \x3F\xCC\xCC\xCD\x40\x59\x99\x9A
test binary-53.7 {Tcl_BinaryObjCmd: format} {} {
    binary format r* {1.6 3.4}
} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40
} \xCD\xCC\xCC\x3F\x9A\x99\x59\x40
test binary-53.8 {Tcl_BinaryObjCmd: format} {} {
    binary format R2 {1.6 3.4}
} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a
} \x3F\xCC\xCC\xCD\x40\x59\x99\x9A
test binary-53.9 {Tcl_BinaryObjCmd: format} {} {
    binary format r2 {1.6 3.4}
} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40
} \xCD\xCC\xCC\x3F\x9A\x99\x59\x40
test binary-53.10 {Tcl_BinaryObjCmd: format} {} {
    binary format R2 {1.6 3.4 5.6}
} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a
} \x3F\xCC\xCC\xCD\x40\x59\x99\x9A
test binary-53.11 {Tcl_BinaryObjCmd: format} {} {
    binary format r2 {1.6 3.4 5.6}
} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40
} \xCD\xCC\xCC\x3F\x9A\x99\x59\x40
test binary-53.12 {Tcl_BinaryObjCmd: float overflow} {} {
    binary format R -3.402825e+38
} \xff\x7f\xff\xff
} \xFF\x80\x00\x00
test binary-53.13 {Tcl_BinaryObjCmd: float overflow} {} {
    binary format r -3.402825e+38
} \xff\xff\x7f\xff
} \x00\x00\x80\xFF
test binary-53.14 {Tcl_BinaryObjCmd: float underflow} {} {
    binary format R -3.402825e-100
} \x80\x00\x00\x00
test binary-53.15 {Tcl_BinaryObjCmd: float underflow} {} {
    binary format r -3.402825e-100
} \x00\x00\x00\x80
test binary-53.16 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    binary format r2 {1.6}
} -result {number of elements in list does not match count}
test binary-53.17 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
    set a {1.6 3.4}
    binary format r $a
} -result "expected floating-point number but got \"1.6 3.4\""
} -result "expected floating-point number but got a list"
test binary-53.18 {Tcl_BinaryObjCmd: format} {} {
    set a {1.6 3.4}
    binary format R1 $a
} \x3f\xcc\xcc\xcd
} \x3F\xCC\xCC\xCD
test binary-53.19 {Tcl_BinaryObjCmd: format} {} {
    set a {1.6 3.4}
    binary format r1 $a
} \xcd\xcc\xcc\x3f
} \xCD\xCC\xCC\x3F
test binary-53.20 {Tcl_BinaryObjCmd: float Inf} {} {
    binary format R Inf
} \x7F\x80\x00\x00
test binary-53.21 {Tcl_BinaryObjCmd: float Inf} {} {
    binary format r Inf
} \x00\x00\x80\x7F
test binary-53.22 {Binary float Inf round trip} -body {
    binary scan [binary format R Inf] R inf
    binary scan [binary format R -Inf] R inf_
    list $inf $inf_
} -result {Inf -Inf}
test binary-53.23 {Binary float round to FLT_MAX} -body {
    binary scan [binary format H* 7f7fffff] R fltmax
    binary scan [binary format H* 47effffff0000000] Q round_to_fltmax
    binary scan [binary format R $round_to_fltmax] R fltmax1
    expr {$fltmax eq $fltmax1}
} -result 1
test binary-53.24 {Binary float round to -FLT_MAX} -body {
    binary scan [binary format H* ff7fffff] R fltmax
    binary scan [binary format H* c7effffff0000000] Q round_to_fltmax
    binary scan [binary format R $round_to_fltmax] R fltmax1
    expr {$fltmax eq $fltmax1}
} -result 1
test binary-53.25 {Binary float round to Inf} -body {
    binary scan [binary format H* 47effffff0000001] Q round_to_inf
    binary scan [binary format R $round_to_inf] R inf1
    expr {$inf1 eq Inf}
} -result 1
test binary-53.26 {Binary float round to -Inf} -body {
    binary scan [binary format H* c7effffff0000001] Q round_to_inf
    binary scan [binary format R $round_to_inf] R inf1
    expr {$inf1 eq -Inf}
} -result 1

# scan t (s)
test binary-54.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
    binary scan abc t
} -result {not enough arguments for all format specifiers}
test binary-54.2 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54 t* arg1] $arg1
    list [binary scan \x52\xA3\x53\x54 t* arg1] $arg1
} {1 {-23726 21587}}
test binary-54.3 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54 t arg1] $arg1
    list [binary scan \x52\xA3\x53\x54 t arg1] $arg1
} {1 -23726}
test binary-54.4 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3 t1 arg1] $arg1
    list [binary scan \x52\xA3 t1 arg1] $arg1
} {1 -23726}
test binary-54.5 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3 t0 arg1] $arg1
    list [binary scan \x52\xA3 t0 arg1] $arg1
} {1 {}}
test binary-54.6 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54 t2 arg1] $arg1
    list [binary scan \x52\xA3\x53\x54 t2 arg1] $arg1
} {1 {-23726 21587}}
test binary-54.7 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    set arg1 foo
    list [binary scan \x52 t1 arg1] $arg1
} {0 foo}
test binary-54.8 {Tcl_BinaryObjCmd: scan} -setup {
    unset -nocomplain arg1
} -returnCodes error -body {
    set arg1 1
    binary scan \x52\x53 t1 arg1(a)
} -result {can't set "arg1(a)": variable isn't array}
test binary-54.9 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x52\xa3\x53\x54\x05 t2c* arg1 arg2] $arg1 $arg2
    list [binary scan \x52\xA3\x53\x54\x05 t2c* arg1 arg2] $arg1 $arg2
} {2 {-23726 21587} 5}
test binary-54.10 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x00\x80\x00\x80 tut arg1 arg2] $arg1 $arg2
} {2 32768 -32768}
test binary-54.11 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x00\x80\x00\x80 ttu arg1 arg2] $arg1 $arg2
} {2 -32768 32768}

# scan t (b)
test binary-55.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
    binary scan abc t
} -result {not enough arguments for all format specifiers}
test binary-55.2 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54 t* arg1] $arg1
    list [binary scan \x52\xA3\x53\x54 t* arg1] $arg1
} {1 {21155 21332}}
test binary-55.3 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54 t arg1] $arg1
    list [binary scan \x52\xA3\x53\x54 t arg1] $arg1
} {1 21155}
test binary-55.4 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3 t1 arg1] $arg1
    list [binary scan \x52\xA3 t1 arg1] $arg1
} {1 21155}
test binary-55.5 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3 t0 arg1] $arg1
    list [binary scan \x52\xA3 t0 arg1] $arg1
} {1 {}}
test binary-55.6 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54 t2 arg1] $arg1
    list [binary scan \x52\xA3\x53\x54 t2 arg1] $arg1
} {1 {21155 21332}}
test binary-55.7 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    set arg1 foo
    list [binary scan \x52 t1 arg1] $arg1
} {0 foo}
test binary-55.8 {Tcl_BinaryObjCmd: scan} -setup {
    unset -nocomplain arg1
} -returnCodes error -body {
    set arg1 1
    binary scan \x52\x53 t1 arg1(a)
} -result {can't set "arg1(a)": variable isn't array}
test binary-55.9 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x52\xa3\x53\x54\x05 t2c* arg1 arg2] $arg1 $arg2
    list [binary scan \x52\xA3\x53\x54\x05 t2c* arg1 arg2] $arg1 $arg2
} {2 {21155 21332} 5}
test binary-55.10 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x80\x00\x80\x00 tut arg1 arg2] $arg1 $arg2
} {2 32768 -32768}
test binary-55.11 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x80\x00\x80\x00 ttu arg1 arg2] $arg1 $arg2
} {2 -32768 32768}

# scan n (s)
test binary-56.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
    binary scan abc n
} -result {not enough arguments for all format specifiers}
test binary-56.2 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n* arg1] $arg1
    list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 n* arg1] $arg1
} {1 {1414767442 67305985}}
test binary-56.3 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n arg1] $arg1
    list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 n arg1] $arg1
} {1 1414767442}
test binary-56.4 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54 n1 arg1] $arg1
    list [binary scan \x52\xA3\x53\x54 n1 arg1] $arg1
} {1 1414767442}
test binary-56.5 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53 n0 arg1] $arg1
    list [binary scan \x52\xA3\x53 n0 arg1] $arg1
} {1 {}}
test binary-56.6 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n2 arg1] $arg1
    list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 n2 arg1] $arg1
} {1 {1414767442 67305985}}
test binary-56.7 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    set arg1 foo
    list [binary scan \x52 n1 arg1] $arg1
} {0 foo}
test binary-56.8 {Tcl_BinaryObjCmd: scan} -setup {
    unset -nocomplain arg1
} -returnCodes error -body {
    set arg1 1
    binary scan \x52\x53\x53\x54 n1 arg1(a)
} -result {can't set "arg1(a)": variable isn't array}
test binary-56.9 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04\x05 n2c* arg1 arg2] $arg1 $arg2
    list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04\x05 n2c* arg1 arg2] $arg1 $arg2
} {2 {1414767442 67305985} 5}
test binary-56.10 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x80\x00\x00\x00\x80\x00\x00\x00 nun arg1 arg2] $arg1 $arg2
} {2 128 128}
test binary-56.11 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x00\x00\x00\x80\x00\x00\x00\x80 nun arg1 arg2] $arg1 $arg2
} {2 2147483648 -2147483648}

# scan n (b)
test binary-57.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
    binary scan abc n
} -result {not enough arguments for all format specifiers}
test binary-57.2 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n* arg1] $arg1
    list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 n* arg1] $arg1
} {1 {1386435412 16909060}}
test binary-57.3 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n arg1] $arg1
    list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 n arg1] $arg1
} {1 1386435412}
test binary-57.4 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54 n1 arg1] $arg1
    list [binary scan \x52\xA3\x53\x54 n1 arg1] $arg1
} {1 1386435412}
test binary-57.5 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53 n0 arg1] $arg1
    list [binary scan \x52\xA3\x53 n0 arg1] $arg1
} {1 {}}
test binary-57.6 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n2 arg1] $arg1
    list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 n2 arg1] $arg1
} {1 {1386435412 16909060}}
test binary-57.7 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    set arg1 foo
    list [binary scan \x52 n1 arg1] $arg1
} {0 foo}
test binary-57.8 {Tcl_BinaryObjCmd: scan} -setup {
    unset -nocomplain arg1
} -returnCodes error -body {
    set arg1 1
    binary scan \x52\x53\x53\x54 n1 arg1(a)
} -result {can't set "arg1(a)": variable isn't array}
test binary-57.9 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04\x05 n2c* arg1 arg2] $arg1 $arg2
    list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04\x05 n2c* arg1 arg2] $arg1 $arg2
} {2 {1386435412 16909060} 5}
test binary-57.10 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x80\x00\x00\x00\x80\x00\x00\x00 nun arg1 arg2] $arg1 $arg2
} {2 2147483648 -2147483648}
test binary-57.11 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x00\x00\x00\x80\x00\x00\x00\x80 nun arg1 arg2] $arg1 $arg2
} {2 128 128}

# scan Q/q
test binary-58.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
    binary scan abc q
} -result {not enough arguments for all format specifiers}
test binary-58.2 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 Q* arg1] $arg1
    list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33 Q* arg1] $arg1
} {1 {1.6 3.4}}
test binary-58.3 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 q* arg1] $arg1
    list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40 q* arg1] $arg1
} {1 {1.6 3.4}}
test binary-58.4 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 Q arg1] $arg1
    list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33 Q arg1] $arg1
} {1 1.6}
test binary-58.5 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 q arg1] $arg1
    list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40 q arg1] $arg1
} {1 1.6}
test binary-58.6 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a Q1 arg1] $arg1
    list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A Q1 arg1] $arg1
} {1 1.6}
test binary-58.7 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f q1 arg1] $arg1
    list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F q1 arg1] $arg1
} {1 1.6}
test binary-58.8 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a Q0 arg1] $arg1
    list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A Q0 arg1] $arg1
} {1 {}}
test binary-58.9 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f q0 arg1] $arg1
    list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F q0 arg1] $arg1
} {1 {}}
test binary-58.10 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 Q2 arg1] $arg1
    list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33 Q2 arg1] $arg1
} {1 {1.6 3.4}}
test binary-58.11 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 q2 arg1] $arg1
    list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40 q2 arg1] $arg1
} {1 {1.6 3.4}}
test binary-58.12 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    set arg1 foo
    list [binary scan \x52 q1 arg1] $arg1
} {0 foo}
test binary-58.13 {Tcl_BinaryObjCmd: scan} -setup {
    unset -nocomplain arg1
} -returnCodes error -body {
    set arg1 1
    binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a q1 arg1(a)
    binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A q1 arg1(a)
} -result {can't set "arg1(a)": variable isn't array}
test binary-58.14 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33\x05 Q2c* arg1 arg2] $arg1 $arg2
    list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33\x05 Q2c* arg1 arg2] $arg1 $arg2
} {2 {1.6 3.4} 5}
test binary-58.15 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40\x05 q2c* arg1 arg2] $arg1 $arg2
    list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40\x05 q2c* arg1 arg2] $arg1 $arg2
} {2 {1.6 3.4} 5}

# scan R/r
test binary-59.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body {
    binary scan abc r
} -result {not enough arguments for all format specifiers}
test binary-59.2 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a R* arg1] $arg1
    list [binary scan \x3F\xCC\xCC\xCD\x40\x59\x99\x9A R* arg1] $arg1
} {1 {1.600000023841858 3.4000000953674316}}
test binary-59.3 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 r* arg1] $arg1
    list [binary scan \xCD\xCC\xCC\x3F\x9A\x99\x59\x40 r* arg1] $arg1
} {1 {1.600000023841858 3.4000000953674316}}
test binary-59.4 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a R arg1] $arg1
    list [binary scan \x3F\xCC\xCC\xCD\x40\x59\x99\x9A R arg1] $arg1
} {1 1.600000023841858}
test binary-59.5 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 r arg1] $arg1
    list [binary scan \xCD\xCC\xCC\x3F\x9A\x99\x59\x40 r arg1] $arg1
} {1 1.600000023841858}
test binary-59.6 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xcc\xcc\xcd R1 arg1] $arg1
    list [binary scan \x3F\xCC\xCC\xCD R1 arg1] $arg1
} {1 1.600000023841858}
test binary-59.7 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \xcd\xcc\xcc\x3f r1 arg1] $arg1
    list [binary scan \xCD\xCC\xCC\x3F r1 arg1] $arg1
} {1 1.600000023841858}
test binary-59.8 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xcc\xcc\xcd R0 arg1] $arg1
    list [binary scan \x3F\xCC\xCC\xCD R0 arg1] $arg1
} {1 {}}
test binary-59.9 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \xcd\xcc\xcc\x3f r0 arg1] $arg1
    list [binary scan \xCD\xCC\xCC\x3F r0 arg1] $arg1
} {1 {}}
test binary-59.10 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1
    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a R2 arg1] $arg1
    list [binary scan \x3F\xCC\xCC\xCD\x40\x59\x99\x9A R2 arg1] $arg1
} {1 {1.600000023841858 3.4000000953674316}}
test binary-59.11 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1
    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 r2 arg1] $arg1
    list [binary scan \xCD\xCC\xCC\x3F\x9A\x99\x59\x40 r2 arg1] $arg1
} {1 {1.600000023841858 3.4000000953674316}}
test binary-59.12 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain arg1
    set arg1 foo
    list [binary scan \x52 r1 arg1] $arg1
} {0 foo}
test binary-59.13 {Tcl_BinaryObjCmd: scan} -setup {
    unset -nocomplain arg1
} -returnCodes error -body {
    set arg1 1
    binary scan \x3f\xcc\xcc\xcd r1 arg1(a)
    binary scan \x3F\xCC\xCC\xCD r1 arg1(a)
} -result {can't set "arg1(a)": variable isn't array}
test binary-59.14 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a\x05 R2c* arg1 arg2] $arg1 $arg2
    list [binary scan \x3F\xCC\xCC\xCD\x40\x59\x99\x9A\x05 R2c* arg1 arg2] $arg1 $arg2
} {2 {1.600000023841858 3.4000000953674316} 5}
test binary-59.15 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain arg1 arg2
    set arg1 foo
    set arg2 bar
    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40\x05 r2c* arg1 arg2] $arg1 $arg2
    list [binary scan \xCD\xCC\xCC\x3F\x9A\x99\x59\x40\x05 r2c* arg1 arg2] $arg1 $arg2
} {2 {1.600000023841858 3.4000000953674316} 5}

test binary-60.1 {[binary format] with NaN} -body {
    binary scan [binary format dqQfrR NaN NaN NaN NaN NaN NaN] dqQfrR \
	v1 v2 v3 v4 v5 v6
    list $v1 $v2 $v3 $v4 $v5 $v6
} -match regexp -result {NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))?}
2380
2381
2382
2383
2384
2385
2386
2387

2388
2389
2390
2391

















2392
2393
2394
2395
2396
2397
2398
2399

2400
2401
2402
2403

2404
2405
2406
2407

2408
2409
2410
2411

2412
2413
2414
2415
2416
2417
2418
2440
2441
2442
2443
2444
2445
2446

2447
2448
2449
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
2489
2490
2491
2492
2493
2494







-
+



-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+



-
+



-
+



-
+







    format 0x%016lx $w
} 0x7ff0000000000000
test binary-62.4 {infinity} ieeeFloatingPoint {
    binary scan [binary format q -Infinity] w w
    format 0x%016lx $w
} 0xfff0000000000000
test binary-62.5 {infinity} ieeeFloatingPoint {
    binary scan [binary format w 0x7ff0000000000000] q d
    binary scan [binary format w 0x7FF0000000000000] q d
    set d
} Inf
test binary-62.6 {infinity} ieeeFloatingPoint {
    binary scan [binary format w 0xfff0000000000000] q d
    binary scan [binary format w 0xFFF0000000000000] q d
    set d
} -Inf
test binary-62.7 {infinity} ieeeFloatingPoint {
    binary scan [binary format r Inf] iu i
    format 0x%08x $i
} 0x7f800000
test binary-62.8 {infinity} ieeeFloatingPoint {
    binary scan [binary format r -Inf] iu i
    format 0x%08x $i
} 0xff800000
test binary-62.9 {infinity} ieeeFloatingPoint {
    binary scan [binary format i 0x7F800000] r d
    set d
} Inf
test binary-62.10 {infinity} ieeeFloatingPoint {
    binary scan [binary format i 0xFF800000] r d
    set d
} -Inf

# scan/format Not-a-Number

test binary-63.1 {NaN} ieeeFloatingPoint {
    binary scan [binary format q NaN] w w
    format 0x%016lx [expr {$w & 0xfff3ffffffffffff}]
    format 0x%016lx [expr {$w & 0xFFF3FFFFFFFFFFFF}]
} 0x7ff0000000000000
test binary-63.2 {NaN} ieeeFloatingPoint {
    binary scan [binary format q -NaN] w w
    format 0x%016lx [expr {$w & 0xfff3ffffffffffff}]
    format 0x%016lx [expr {$w & 0xFFF3FFFFFFFFFFFF}]
} 0xfff0000000000000
test binary-63.3 {NaN} ieeeFloatingPoint {
    binary scan [binary format q NaN(3123456789aBc)] w w
    format 0x%016lx [expr {$w & 0xfff3ffffffffffff}]
    format 0x%016lx [expr {$w & 0xFFF3FFFFFFFFFFFF}]
} 0x7ff3123456789abc
test binary-63.4 {NaN} ieeeFloatingPoint {
    binary scan [binary format q {NaN( 3123456789aBc)}] w w
    format 0x%016lx [expr {$w & 0xfff3ffffffffffff}]
    format 0x%016lx [expr {$w & 0xFFF3FFFFFFFFFFFF}]
} 0x7ff3123456789abc

# Make sure TclParseNumber() rejects invalid nan-hex formats [Bug 3402540]
test binary-63.5 {NaN} -constraints ieeeFloatingPoint -body {
    binary format q Nan(
} -returnCodes error -match glob -result {expected floating-point number*}
test binary-63.6 {NaN} -constraints ieeeFloatingPoint -body {
2483
2484
2485
2486
2487
2488
2489
2490

2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507

2508
2509
2510
2511
2512
2513
2514
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







-
+
















-
+







test binary-70.3 {binary encode hex} -body {
    binary encode hex {}
} -result {}
test binary-70.4 {binary encode hex} -body {
    binary encode hex [string repeat a 20]
} -result [string repeat 61 20]
test binary-70.5 {binary encode hex} -body {
    binary encode hex \0\1\2\3\4\0\1\2\3\4
    binary encode hex \x00\x01\x02\x03\x04\x00\x01\x02\x03\x04
} -result {00010203040001020304}

test binary-71.1 {binary decode hex} -body {
    binary decode hex
} -returnCodes error -match glob -result "wrong # args: *"
test binary-71.2 {binary decode hex} -body {
    binary decode hex 61
} -result {a}
test binary-71.3 {binary decode hex} -body {
    binary decode hex {}
} -result {}
test binary-71.4 {binary decode hex} -body {
    binary decode hex [string repeat 61 20]
} -result [string repeat a 20]
test binary-71.5 {binary decode hex} -body {
    binary decode hex 00010203040001020304
} -result "\0\1\2\3\4\0\1\2\3\4"
} -result "\x00\x01\x02\x03\x04\x00\x01\x02\x03\x04"
test binary-71.6 {binary decode hex} -body {
    binary decode hex "61 61"
} -result {aa}
test binary-71.7 {binary decode hex} -body {
    binary decode hex "61\n\n\n61"
} -result {aa}
test binary-71.8 {binary decode hex} -match glob -body {
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
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







-
+


-
+


-
+


-
+


-
+







test binary-72.3 {binary encode base64} -body {
    binary encode base64 {}
} -result {}
test binary-72.4 {binary encode base64} -body {
    binary encode base64 [string repeat abc 20]
} -result [string repeat YWJj 20]
test binary-72.5 {binary encode base64} -body {
    binary encode base64 \0\1\2\3\4\0\1\2\3
    binary encode base64 \x00\x01\x02\x03\x04\x00\x01\x02\x03
} -result {AAECAwQAAQID}
test binary-72.6 {binary encode base64} -body {
    binary encode base64 \0
    binary encode base64 \x00
} -result {AA==}
test binary-72.7 {binary encode base64} -body {
    binary encode base64 \0\0
    binary encode base64 \x00\x00
} -result {AAA=}
test binary-72.8 {binary encode base64} -body {
    binary encode base64 \0\0\0
    binary encode base64 \x00\x00\x00
} -result {AAAA}
test binary-72.9 {binary encode base64} -body {
    binary encode base64 \0\0\0\0
    binary encode base64 \x00\x00\x00\x00
} -result {AAAAAA==}
test binary-72.10 {binary encode base64} -body {
    binary encode base64 -maxlen 0 -wrapchar : abcabcabc
} -result {YWJjYWJjYWJj}
test binary-72.11 {binary encode base64} -body {
    binary encode base64 -maxlen 1 -wrapchar : abcabcabc
} -result {Y:W:J:j:Y:W:J:j:Y:W:J:j}
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
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







-
+

+
+
+
+
+
+















-
+


-
+


-
+


-
+


-
+







test binary-72.27 {binary encode base64} -body {
    binary encode base64 -maxlen 4 -wrapchar -*- abcabcabc
} -result {YWJj-*-YWJj-*-YWJj}
test binary-72.28 {binary encode base64} -body {
    binary encode base64 -maxlen 6 -wrapchar 0123456789 abcabcabc
} -result {YWJjYW0123456789JjYWJj}
test binary-72.29 {binary encode base64} {
    string length [binary encode base64 -maxlen 3 -wrapchar \xca abc]
    string length [binary encode base64 -maxlen 3 -wrapchar \xCA abc]
} 5
test binary-72.30 {binary encode base64} {
    string length [binary encode base64 -maxlen 4294967296 abc]
} 4
test binary-72.31 {binary encode base64} -body {
    string length [binary encode base64 -maxlen 18446744073709551616 abc]
} -returnCodes 1 -result {integer value too large to represent}

test binary-73.1 {binary decode base64} -body {
    binary decode base64
} -returnCodes error -match glob -result "wrong # args: *"
test binary-73.2 {binary decode base64} -body {
    binary decode base64 YWJj
} -result {abc}
test binary-73.3 {binary decode base64} -body {
    binary decode base64 {}
} -result {}
test binary-73.4 {binary decode base64} -body {
    binary decode base64 [string repeat YWJj 20]
} -result [string repeat abc 20]
test binary-73.5 {binary decode base64} -body {
    binary decode base64 AAECAwQAAQID
} -result "\0\1\2\3\4\0\1\2\3"
} -result "\x00\x01\x02\x03\x04\x00\x01\x02\x03"
test binary-73.6 {binary decode base64} -body {
    binary decode base64 AA==
} -result "\0"
} -result "\x00"
test binary-73.7 {binary decode base64} -body {
    binary decode base64 AAA=
} -result "\0\0"
} -result "\x00\x00"
test binary-73.8 {binary decode base64} -body {
    binary decode base64 AAAA
} -result "\0\0\0"
} -result "\x00\x00\x00"
test binary-73.9 {binary decode base64} -body {
    binary decode base64 AAAAAA==
} -result "\0\0\0\0"
} -result "\x00\x00\x00\x00"
test binary-73.10 {binary decode base64} -body {
    set s "[string repeat YWJj 10]\n[string repeat YWJj 10]"
    binary decode base64 $s
} -result [string repeat abc 20]
test binary-73.11 {binary decode base64} -body {
    set s "[string repeat YWJj 10]\n    [string repeat YWJj 10]"
    binary decode base64 $s
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
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







-
+






-
+



-
+



-
+







test binary-74.3 {binary encode uuencode} -body {
    binary encode uuencode {}
} -result {}
test binary-74.4 {binary encode uuencode} -body {
    binary encode uuencode [string repeat abc 20]
} -result "M[string repeat 86)C 15]\n/[string repeat 86)C 5]\n"
test binary-74.5 {binary encode uuencode} -body {
    binary encode uuencode \0\1\2\3\4\0\1\2\3
    binary encode uuencode \x00\x01\x02\x03\x04\x00\x01\x02\x03
} -result ")``\$\"`P0``0(#\n"
test binary-74.6 {binary encode uuencode} -body {
    binary encode uuencode \0
} -result {!``
}
test binary-74.7 {binary encode uuencode} -body {
    binary encode uuencode \0\0
    binary encode uuencode \x00\x00
} -result "\"```
"
test binary-74.8 {binary encode uuencode} -body {
    binary encode uuencode \0\0\0
    binary encode uuencode \x00\x00\x00
} -result {#````
}
test binary-74.9 {binary encode uuencode} -body {
    binary encode uuencode \0\0\0\0
    binary encode uuencode \x00\x00\x00\x00
} -result {$``````
}
test binary-74.10 {binary encode uuencode} -returnCodes error -body {
    binary encode uuencode -foo 30 abcabcabc
} -result {bad option "-foo": must be -maxlen or -wrapchar}
test binary-74.11 {binary encode uuencode} -returnCodes error -body {
    binary encode uuencode -maxlen 4 abcabcabc
2829
2830
2831
2832
2833
2834
2835
2836

2837
2838
2839
2840
2841
2842
2843
2911
2912
2913
2914
2915
2916
2917

2918
2919
2920
2921
2922
2923
2924
2925







-
+







    binary decode uuencode `\n
} -result {}
test binary-75.4 {binary decode uuencode} -body {
    binary decode uuencode "M[string repeat 86)C 15]\n/[string repeat 86)C 5]\n"
} -result [string repeat abc 20]
test binary-75.5 {binary decode uuencode} -body {
    binary decode uuencode ")``\$\"`P0``0(#"
} -result "\0\1\2\3\4\0\1\2\3"
} -result "\x00\x01\x02\x03\x04\x00\x01\x02\x03"
test binary-75.6 {binary decode uuencode} -body {
    string length [binary decode uuencode "`\n"]
} -result 0
test binary-75.7 {binary decode uuencode} -body {
    string length [binary decode uuencode "!`\n"]
} -result 1
test binary-75.8 {binary decode uuencode} -body {
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
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







-
+








-
-
+
+
+
+
+
+
+
+

+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
+
+

-
-
+
+


+
+
+
+
+










} [binary format H* abcd]

test binary-78.1 {unicode (out of BMP) to byte-array conversion, bug-[bd94500678]} -body {
    # just test for BO-segfault (high surrogate w/o advance source pointer for out of BMP char if TCL_UTF_MAX == 3):
    binary encode hex \U0001f415
    binary scan \U0001f415 a* v; set v
    set str {}
} -result {}
} -result * -match glob -returnCodes error


testConstraint testsetbytearraylength \
		[expr {"testsetbytearraylength" in [info commands]}]

test binary-79.1 {Tcl_SetByteArrayLength} testsetbytearraylength {
    testsetbytearraylength [string cat A B C] 1
} A
test binary-79.2 {Tcl_SetByteArrayLength} testsetbytearraylength {
    testsetbytearraylength [string cat \u0141 B C] 1
test binary-79.2 {Tcl_SetByteArrayLength} -body {
    testsetbytearraylength [string cat Å B C] 1
} -constraints testsetbytearraylength -returnCodes error -match glob -result *
test binary-79.3 {Tcl_SetByteArrayLength} testsetbytearraylength {
    testsetbytearraylength [string cat A B \u0141] 0
} {}
test binary-79.4 {Tcl_SetByteArrayLength} testsetbytearraylength {
    testsetbytearraylength [string cat A B \u0141] 1
} A
test binary-79.5 {Tcl_SetByteArrayLength} testsetbytearraylength {
    testsetbytearraylength [string cat A B \u0141] 2
} AB
test binary-79.6 {Tcl_SetByteArrayLength} -body {
    testsetbytearraylength [string cat A B \u0141] 3
} -constraints testsetbytearraylength -returnCodes error -match glob -result *

test binary-80.1 {TclGetBytesFromObj} -constraints testbytestring -returnCodes 1 -body {
    testbytestring "\u4E4E"
} -result "expected byte sequence but character 0 was '\u4E4E' (U+004E4E)"
test binary-80.2 {TclGetBytesFromObj} -constraints testbytestring -returnCodes 1 -body {
test binary-80.1 {Tcl_GetBytesFromObj} -constraints testbytestring -returnCodes 1 -body {
    testbytestring "乎"
} -result "expected byte sequence but character 0 was '乎' (U+004E4E)"
test binary-80.2 {Tcl_GetBytesFromObj} -constraints testbytestring -returnCodes 1 -body {
    testbytestring [testbytestring "\x00\xA0\xA0\xA0\xE4\xB9\x8E"]
} -result "expected byte sequence but character 4 was '\u4E4E' (U+004E4E)"
test binary-80.3 {TclGetBytesFromObj} -constraints testbytestring -returnCodes 1 -body {
} -result "expected byte sequence but character 4 was '乎' (U+004E4E)"
test binary-80.3 {Tcl_GetBytesFromObj} -constraints testbytestring -returnCodes 1 -body {
    testbytestring [testbytestring "\xC0\x80\xA0\xA0\xA0\xE4\xB9\x8E"]
} -result "expected byte sequence but character 4 was '\u4E4E' (U+004E4E)"
test binary-80.4 {TclGetBytesFromObj} -constraints testbytestring -returnCodes 1 -body {
} -result "expected byte sequence but character 4 was '乎' (U+004E4E)"
test binary-80.4 {Tcl_GetBytesFromObj} -constraints testbytestring -returnCodes 1 -body {
    testbytestring [testbytestring "\xC0\x80\xA0\xA0\xA0\xF0\x9F\x98\x81"]
} -result "expected byte sequence but character 4 was '\U01F601' (U+01F601)"
test binary-80.5 {Tcl_GetBytesFromObj} -constraints {
	bigmem testbytestring pointerIs64bit deprecated
} -body {
    testbytestring [string repeat A [expr 2**31]]
} -returnCodes 1 -result "byte sequence length exceeds INT_MAX"

# ----------------------------------------------------------------------
# cleanup

::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/chan.test.

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

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
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
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




-
+








+
+
+















-
+


-
+
















-
+

-
-
+
+

-
-
-
+
+
+

-
+


-
+


-
+







-
+



-
+



-
+



-
+







-
+



-
+



-
+



-
+



-
+














+
+
+
+
+
+
+
+
+
+




-
+


-
+


-
+







# This file contains a collection of tests for the Tcl built-in 'chan'
# command. Sourcing this file into Tcl runs the tests and generates
# output for errors. No output means no errors were found.
#
# Copyright (c) 2005 Donal K. Fellows
# Copyright © 2005 Donal K. Fellows
#
# 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::*
}
source [file join [file dirname [info script]] tcltests.tcl]

package require tcltests

#
# Note: The tests for the chan methods "create" and "postevent"
# currently reside in the file "ioCmd.test".
#

test chan-1.1 {chan command general syntax} -body {
    chan
} -returnCodes error -result "wrong # args: should be \"chan subcommand ?arg ...?\""
test chan-1.2 {chan command general syntax} -body {
    chan FOOBAR
} -returnCodes error -match glob -result "unknown or ambiguous subcommand \"FOOBAR\": must be *"

test chan-2.1 {chan command: blocked subcommand} -body {
    chan blocked foo bar
} -returnCodes error -result "wrong # args: should be \"chan blocked channelId\""
} -returnCodes error -result "wrong # args: should be \"chan blocked channel\""
test chan-3.1 {chan command: close subcommand} -body {
    chan close foo bar zet
} -returnCodes error -result "wrong # args: should be \"chan close channelId ?direction?\""
} -returnCodes error -result "wrong # args: should be \"chan close channel ?direction?\""
test chan-3.2 {chan command: close subcommand} -setup {
    set chan [open [info script] r]
} -body {
    chan close $chan bar
} -cleanup {
    close $chan
} -returnCodes error -result "bad direction \"bar\": must be read or write"
test chan-3.3 {chan command: close subcommand} -setup {
    set chan [open [info script] r]
} -body {
    chan close $chan write
} -cleanup {
    close $chan
} -returnCodes error -result "Half-close of write-side not possible, side not opened or already closed"
test chan-4.1 {chan command: configure subcommand} -body {
    chan configure
} -returnCodes error -result "wrong # args: should be \"chan configure channelId ?-option value ...?\""
} -returnCodes error -result "wrong # args: should be \"chan configure channel ?-option value ...?\""
test chan-4.2 {chan command: [Bug 800753]} -body {
    chan configure stdout -eofchar \u0100
} -returnCodes error -match glob -result {bad value*}
    chan configure stdout -eofchar Ā
} -returnCodes error -result {bad value for -eofchar: must be non-NUL ASCII character}
test chan-4.3 {chan command: [Bug 800753]} -body {
    chan configure stdout -eofchar \u0000
} -returnCodes error -match glob -result {bad value*}
test chan-4.4 {chan command: check valid inValue, no outValue} -body {
    chan configure stdout -eofchar \x00
} -returnCodes error -result {bad value for -eofchar: must be non-NUL ASCII character}
test chan-4.4 {chan command: check valid inValue, no outValue} -constraints deprecated -body {
    chan configure stdout -eofchar [list \x27 {}]
} -returnCodes ok -result {}
} -result {}
test chan-4.5 {chan command: check valid inValue, invalid outValue} -body {
    chan configure stdout -eofchar [list \x27 \x80]
} -returnCodes error -match glob -result {bad value for -eofchar:*}
} -returnCodes error -result {bad value for -eofchar: must be non-NUL ASCII character}
test chan-4.6 {chan command: check no inValue, valid outValue} -body {
    chan configure stdout -eofchar [list {} \x27]
} -returnCodes ok -result {} -cleanup {chan configure stdout -eofchar [list {} {}]}
} -returnCodes error -result {bad value for -eofchar: must be non-NUL ASCII character}

test chan-5.1 {chan command: copy subcommand} -body {
    chan copy foo
} -returnCodes error -result "wrong # args: should be \"chan copy input output ?-size size? ?-command callback?\""

test chan-6.1 {chan command: eof subcommand} -body {
    chan eof foo bar
} -returnCodes error -result "wrong # args: should be \"chan eof channelId\""
} -returnCodes error -result "wrong # args: should be \"chan eof channel\""

test chan-7.1 {chan command: event subcommand} -body {
    chan event foo
} -returnCodes error -result "wrong # args: should be \"chan event channelId event ?script?\""
} -returnCodes error -result "wrong # args: should be \"chan event channel event ?script?\""

test chan-8.1 {chan command: flush subcommand} -body {
    chan flush foo bar
} -returnCodes error -result "wrong # args: should be \"chan flush channelId\""
} -returnCodes error -result "wrong # args: should be \"chan flush channel\""

test chan-9.1 {chan command: gets subcommand} -body {
    chan gets
} -returnCodes error -result "wrong # args: should be \"chan gets channelId ?varName?\""
} -returnCodes error -result "wrong # args: should be \"chan gets channel ?varName?\""

test chan-10.1 {chan command: names subcommand} -body {
    chan names foo bar
} -returnCodes error -result "wrong # args: should be \"chan names ?pattern?\""

test chan-11.1 {chan command: puts subcommand} -body {
    chan puts foo bar foo bar
} -returnCodes error -result "wrong # args: should be \"chan puts ?-nonewline? ?channelId? string\""
} -returnCodes error -result "wrong # args: should be \"chan puts ?-nonewline? ?channel? string\""

test chan-12.1 {chan command: read subcommand} -body {
    chan read
} -returnCodes error -result "wrong # args: should be \"chan read channelId ?numChars?\" or \"chan read ?-nonewline? channelId\""
} -returnCodes error -result "wrong # args: should be \"chan read channel ?numChars?\" or \"chan read ?-nonewline? channel\""

test chan-13.1 {chan command: seek subcommand} -body {
    chan seek foo bar foo bar
} -returnCodes error -result "wrong # args: should be \"chan seek channelId offset ?origin?\""
} -returnCodes error -result "wrong # args: should be \"chan seek channel offset ?origin?\""

test chan-14.1 {chan command: tell subcommand} -body {
    chan tell foo bar
} -returnCodes error -result "wrong # args: should be \"chan tell channelId\""
} -returnCodes error -result "wrong # args: should be \"chan tell channel\""

test chan-15.1 {chan command: truncate subcommand} -body {
    chan truncate foo bar foo bar
} -returnCodes error -result "wrong \# args: should be \"chan truncate channelId ?length?\""
} -returnCodes error -result "wrong \# args: should be \"chan truncate channel ?length?\""
test chan-15.2 {chan command: truncate subcommand} -setup {
    set file [makeFile {} testTruncate]
    set f [open $file w+]
    fconfigure $f -translation binary
} -body {
    seek $f 0
    puts -nonewline $f 12345
    seek $f 0
    chan truncate $f 2
    read $f
} -result 12 -cleanup {
    catch {close $f}
    catch {removeFile $file}
}
test chan-15.3 {chan command: isbinary subcommand} -setup {
    set file [makeFile {} testIsBinary]
    set f [open $file w+]
    fconfigure $f -translation binary
} -body {
    chan isbinary $f
} -result 1 -cleanup {
    catch {close $f}
    catch {removeFile $file}
}

# TIP 287: chan pending
test chan-16.1 {chan command: pending subcommand} -body {
    chan pending
} -returnCodes error -result "wrong # args: should be \"chan pending mode channelId\""
} -returnCodes error -result "wrong # args: should be \"chan pending mode channel\""
test chan-16.2 {chan command: pending subcommand} -body {
    chan pending stdin
} -returnCodes error -result "wrong # args: should be \"chan pending mode channelId\""
} -returnCodes error -result "wrong # args: should be \"chan pending mode channel\""
test chan-16.3 {chan command: pending subcommand} -body {
    chan pending stdin stdout stderr
} -returnCodes error -result "wrong # args: should be \"chan pending mode channelId\""
} -returnCodes error -result "wrong # args: should be \"chan pending mode channel\""
test chan-16.4 {chan command: pending subcommand} -body {
    chan pending {input output} stdout
} -returnCodes error -result "bad mode \"input output\": must be input or output"
test chan-16.5 {chan command: pending input subcommand} -body {
    chan pending input stdout
} -result -1
test chan-16.6 {chan command: pending input subcommand} -body {
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
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







-
-
+
+



-
-
-
-
-
+
+
+
+
+

-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+





-
-
+
+







    chan pending input $f
} -result 8 -cleanup {
    catch {chan close $f}
    catch {removeFile $file}
}
test chan-16.9 {chan command: pending input subcommand} -setup {
    proc chan-16.9-accept {sock addr port} {
        chan configure $sock -blocking 0 -buffering line -buffersize 32
        chan event $sock readable [list chan-16.9-readable $sock]
	chan configure $sock -blocking 0 -buffering line -buffersize 32
	chan event $sock readable [list chan-16.9-readable $sock]
    }

    proc chan-16.9-readable {sock} {
        set r [chan gets $sock line]
        set l [string length $line]
        set e [chan eof $sock]
        set b [chan blocked $sock]
        set i [chan pending input $sock]
	set r [chan gets $sock line]
	set l [string length $line]
	set e [chan eof $sock]
	set b [chan blocked $sock]
	set i [chan pending input $sock]

        lappend ::chan-16.9-data $r $l $e $b $i
	lappend ::chan-16.9-data $r $l $e $b $i

        if {$r >= 0 || $e || $l || !$b || $i > 128} {
            set data [read $sock $i]
            lappend ::chan-16.9-data [string range $data 0 2]
            lappend ::chan-16.9-data [string range $data end-2 end]
            set ::chan-16.9-done 1
            chan event $sock readable {}
        } else {
	if {$r >= 0 || $e || $l || !$b || $i > 128} {
	    set data [read $sock $i]
	    lappend ::chan-16.9-data [string range $data 0 2]
	    lappend ::chan-16.9-data [string range $data end-2 end]
	    set ::chan-16.9-done 1
	    chan event $sock readable {}
	} else {
	    after idle chan-16.9-client
	}
    }

    proc chan-16.9-client {} {
        chan puts -nonewline $::client ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890
        chan flush $::client
	chan puts -nonewline $::client ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890
	chan flush $::client
    }

    set ::server [socket -server chan-16.9-accept -myaddr 127.0.0.1 0]
    set ::client [socket 127.0.0.1 [lindex [fconfigure $::server -sockname] 2]]
    set ::chan-16.9-data [list]
    set ::chan-16.9-done 0
} -body {

Changes to tests/chanio.test.

1
2
3
4
5
6
7
8
9
10
11



12
13
14
15
16
17
18
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
16
17
18








-
-
-
+
+
+







# -*- tcl -*-
# Functionality covered: operation of all IO commands, and all procedures
# defined in generic/tclIO.c.
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1991-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
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
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







-
-
+
+

-
+







+
-
+

+
+
+










-
+





-
+












-
-
+
+







    variable n
    variable v
    variable msg
    variable expected

    catch {
	::tcltest::loadTestedCommands
	package require -exact Tcltest [info patchlevel]
	set ::tcltestlib [lindex [package ifneeded Tcltest [info patchlevel]] 1]
	package require -exact tcl::test [info patchlevel]
	set ::tcltestlib [info loaded {} Tcltest]
    }
    package require tcltests
    source [file join [file dirname [info script]] tcltests.tcl]

    testConstraint testbytestring   [llength [info commands testbytestring]]
    testConstraint testchannel      [llength [info commands testchannel]]
    testConstraint testfevent       [llength [info commands testfevent]]
    testConstraint testchannelevent [llength [info commands testchannelevent]]
    testConstraint testmainthread   [llength [info commands testmainthread]]
    testConstraint testservicemode  [llength [info commands testservicemode]]
    testConstraint notWinCI       [expr {
    testConstraint knownMsvcBug [expr {![info exists ::env(TRAVIS_OS_NAME)] || ![string match windows $::env(TRAVIS_OS_NAME)]}]
	$::tcl_platform(platform) ne "windows" || ![info exists ::env(CI)]}]
    testConstraint notOSX [expr {$::tcl_platform(os) ne "Darwin"}]
    # File permissions broken on wsl without some "exotic" wsl configuration
    testConstraint notWsl [expr {[llength [array names ::env *WSL*]] == 0}]
    testConstraint specialfiles  [expr {[file exists /dev/zero] || [file exists NUL]}]

    # You need a *very* special environment to do some tests.  In particular,
    # many file systems do not support large-files...
    testConstraint largefileSupport [expr {$::tcl_platform(os) ne "Darwin"}]

    # some tests can only be run is umask is 2 if "umask" cannot be run, the
    # tests will be skipped.
    set umaskValue 0
    testConstraint umask [expr {![catch {set umaskValue [scan [exec /bin/sh -c umask] %o]}]}]

    testConstraint makeFileInHome [expr {![file exists ~/_test_] && [file writable ~]}]
    testConstraint makeFileInHome [expr {![file exists $::env(HOME)/_test_] && [file writable $::env(HOME)]}]

    # set up a long data file for some of the following tests

    set path(longfile) [makeFile {} longfile]
    set f [open $path(longfile) w]
    chan configure $f -eofchar {} -translation lf
    chan configure $f -translation lf
    for { set i 0 } { $i < 100 } { incr i} {
	chan puts $f "#123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
\#123456789abcdef01
\#"
    }
    chan close $f

    set path(cat) [makeFile {
	set f stdin
	if {$argv != ""} {
	    set f [open [lindex $argv 0]]
	}
	chan configure $f -encoding binary -translation lf -blocking 0 -eofchar \x1a
	chan configure stdout -encoding binary -translation lf -buffering none
	chan configure $f -translation binary -blocking 0 -eofchar \x1A
	chan configure stdout -translation binary -buffering none
	chan event $f readable "foo $f"
	proc foo {f} {
	    set x [chan read $f]
	    catch {chan puts -nonewline $x}
	    if {[chan eof $f]} {
		chan close $f
		exit 0
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
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







-
-
+
+


-
+



-
+


-
+












-
+








test chan-io-1.5 {Tcl_WriteChars: CheckChannelErrors} {emptyTest} {
    # no test, need to cause an async error.
} {}
set path(test1) [makeFile {} test1]
test chan-io-1.6 {Tcl_WriteChars: WriteBytes} {
    set f [open $path(test1) w]
    chan configure $f -encoding binary
    chan puts -nonewline $f "a\u4e4d\0"
    chan configure $f -translation binary
    chan puts -nonewline $f "a\x4D\x00"
    chan close $f
    contents $path(test1)
} "a\x4d\x00"
} aM\x00
test chan-io-1.7 {Tcl_WriteChars: WriteChars} {
    set f [open $path(test1) w]
    chan configure $f -encoding shiftjis
    chan puts -nonewline $f "a\u4e4d\0"
    chan puts -nonewline $f "aä¹\x00"
    chan close $f
    contents $path(test1)
} "a\x93\xe1\x00"
} "a\x93\xE1\x00"
set path(test2) [makeFile {} test2]
test chan-io-1.8 {Tcl_WriteChars: WriteChars} {
    # This test written for SF bug #506297.
    #
    # Executing this test without the fix for the referenced bug applied to
    # tcl will cause tcl, more specifically WriteChars, to go into an infinite
    # loop.
    set f [open $path(test2) w]
    chan configure      $f -encoding iso2022-jp
    chan puts -nonewline $f [format %s%c [string repeat " " 4] 12399]
    chan close           $f
    contents $path(test2)
} "    \x1b\$B\$O\x1b(B"
} "    \x1B\$B\$O\x1B(B"
test chan-io-1.9 {Tcl_WriteChars: WriteChars} {
    # When closing a channel with an encoding that appends escape bytes, check
    # for the case where the escape bytes overflow the current IO buffer. The
    # bytes should be moved into a new buffer.
    set data "1234567890 [format %c 12399]"
    set sizes [list]
    # With default buffer size
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
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







-
+








-
+










-
+







-
+
-







    chan close           $f
    lappend sizes [file size $path(test2)]
} {19 19 19 19 19}

test chan-io-2.1 {WriteBytes} {
    # loop until all bytes are written
    set f [open $path(test1) w]
    chan configure $f  -encoding binary -buffersize 16 -translation crlf
    chan configure $f  -translation binary -buffersize 16 -translation crlf
    chan puts $f "abcdefghijklmnopqrstuvwxyz"
    chan close $f
    contents $path(test1)
} "abcdefghijklmnopqrstuvwxyz\r\n"
test chan-io-2.2 {WriteBytes: savedLF > 0} {
    # After flushing buffer, there was a \n left over from the last
    # \n -> \r\n expansion.  It gets stuck at beginning of this buffer.
    set f [open $path(test1) w]
    chan configure $f -encoding binary -buffersize 16 -translation crlf
    chan configure $f -translation binary -buffersize 16 -translation crlf
    chan puts -nonewline $f "123456789012345\n12"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "123456789012345\r" "123456789012345\r\n12"]
test chan-io-2.3 {WriteBytes: flush on line} -body {
    # Tcl "line" buffering has weird behavior: if current buffer contains a
    # \n, entire buffer gets flushed.  Logical behavior would be to flush only
    # up to the \n.
    set f [open $path(test1) w]
    chan configure $f -encoding binary -buffering line -translation crlf
    chan configure $f -translation binary -buffering line -translation crlf
    chan puts -nonewline $f "\n12"
    contents $path(test1)
} -cleanup {
    chan close $f
} -result "\r\n12"
test chan-io-2.4 {WriteBytes: reset sawLF after each buffer} {
    set f [open $path(test1) w]
     chan configure $f -encoding binary -buffering line -translation lf \
     chan configure $f -translation binary -buffering line -buffersize 16
	     -buffersize 16
    chan puts -nonewline $f "abcdefg\nhijklmnopqrstuvwxyz"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "abcdefg\nhijklmno" "abcdefg\nhijklmnopqrstuvwxyz"]

test chan-io-3.1 {WriteChars: compatibility with WriteBytes} {
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
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







-
+


-
+




+
+
-
-
+
+




-
+


+
+
+
-
+
-
-
-
+
+




-
+


-
+


-
+



+
+
-
-
+
+






-
+




+
+
-
-
+
+







+
+
-
+







    set f [open $path(test1) w]
    chan configure $f -encoding ascii -buffering line -translation crlf
    chan puts -nonewline $f "\n12"
    contents $path(test1)
} -cleanup {
    chan close $f
} -result "\r\n12"
test chan-io-3.4 {WriteChars: loop over stage buffer} {
test chan-io-3.4 {WriteChars: loop over stage buffer} -body {
    # stage buffer maps to more than can be queued at once.
    set f [open $path(test1) w]
    chan configure $f -encoding jis0208 -buffersize 16
    chan configure $f -encoding jis0208 -buffersize 16 -profile tcl8
    chan puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} -cleanup {
    catch {chan close $f}
} [list "!)!)!)!)!)!)!)!)" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test chan-io-3.5 {WriteChars: saved != 0} {
} -result [list "!)!)!)!)!)!)!)!)" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test chan-io-3.5 {WriteChars: saved != 0} -body {
    # Bytes produced by UtfToExternal from end of last channel buffer had to
    # be moved to beginning of next channel buffer to preserve requested
    # buffersize.
    set f [open $path(test1) w]
    chan configure $f -encoding jis0208 -buffersize 17
    chan configure $f -encoding jis0208 -buffersize 17 -profile tcl8
    chan puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} -cleanup {
    chan close $f
    catch {chan close $f}
    lappend x [contents $path(test1)]
} [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test chan-io-3.6 {WriteChars: (stageRead + dstWrote == 0)} {
} -result [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test chan-io-3.6 {WriteChars: (stageRead + dstWrote == 0)} -body {
    # One incomplete UTF-8 character at end of staging buffer. Backup in src
    # to the beginning of that UTF-8 character and try again.
    #
    # Translate the first 16 bytes, produce 14 bytes of output, 2 left over
    # (first two bytes of \uff21 in UTF-8). Given those two bytes try
    # (first two bytes of A in UTF-8). Given those two bytes try
    # translating them again, find that no bytes are read produced, and break
    # to outer loop where those two bytes will have the remaining 4 bytes (the
    # last byte of \uff21 plus the all of \uff22) appended.
    # last byte of A plus the all of B) appended.
    set f [open $path(test1) w]
    chan configure $f -encoding shiftjis -buffersize 16
    chan puts -nonewline $f "12345678901234\uff21\uff22"
    chan puts -nonewline $f 12345678901234AB
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} -cleanup {
    catch {chan close $f}
} [list "12345678901234\x82\x60" "12345678901234\x82\x60\x82\x61"]
test chan-io-3.7 {WriteChars: (bufPtr->nextAdded > bufPtr->length)} {
} -result [list "12345678901234\x82\x60" "12345678901234\x82\x60\x82\x61"]
test chan-io-3.7 {WriteChars: (bufPtr->nextAdded > bufPtr->length)} -body {
    # When translating UTF-8 to external, the produced bytes went past end of
    # the channel buffer. This is done on purpose - we then truncate the bytes
    # at the end of the partial character to preserve the requested blocksize
    # on flush. The truncated bytes are moved to the beginning of the next
    # channel buffer.
    set f [open $path(test1) w]
    chan configure $f -encoding jis0208 -buffersize 17
    chan configure $f -encoding jis0208 -buffersize 17 -profile tcl8
    chan puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} -cleanup {
    catch {chan close $f}
} [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test chan-io-3.8 {WriteChars: reset sawLF after each buffer} {
} -result [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test chan-io-3.8 {WriteChars: reset sawLF after each buffer} -body {
    set f [open $path(test1) w]
    chan configure $f -encoding ascii -buffering line -translation lf \
	     -buffersize 16
    chan puts -nonewline $f "abcdefg\nhijklmnopqrstuvwxyz"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} -cleanup {
    catch {chan close $f}
} [list "abcdefg\nhijklmno" "abcdefg\nhijklmnopqrstuvwxyz"]
} -result [list "abcdefg\nhijklmno" "abcdefg\nhijklmnopqrstuvwxyz"]

test chan-io-4.1 {TranslateOutputEOL: lf} {
    # search for \n
    set f [open $path(test1) w]
    chan configure $f -buffering line -translation lf
    chan puts $f "abcde"
    set x [list [contents $path(test1)]]
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
364
365
366
367
368
369
370

371
372
373
374
375
376
377







-







    chan puts -nonewline $f "12345678901\n456789012345678901234"
    chan close $f
    set x [contents $path(test1)]
} "12345678901\r\n456789012345678901234"

test chan-io-5.1 {CheckFlush: not full} {
    set f [open $path(test1) w]
    chan configure $f
    chan puts -nonewline $f "12345678901234567890"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} [list "" "12345678901234567890"]
test chan-io-5.2 {CheckFlush: full} {
    set f [open $path(test1) w]
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
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







-
+










-
+






-
+







    list [chan tell $f] [chan gets $f line] [chan tell $f] [chan gets $f line] $line
} -cleanup {
    chan close $f
} -result {0 3 5 4 defg}
test chan-io-6.4 {Tcl_GetsObj: encoding == NULL} -body {
    set f [open $path(test1) w]
    chan configure $f -translation binary
    chan puts $f "\x81\u1234\0"
    chan puts $f "\x81\x34\x00"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation binary
    list [chan gets $f line] $line
} -cleanup {
    chan close $f
} -result [list 3 "\x81\x34\x00"]
test chan-io-6.5 {Tcl_GetsObj: encoding != NULL} -body {
    set f [open $path(test1) w]
    chan configure $f -translation binary
    chan puts $f "\x88\xea\x92\x9a"
    chan puts $f "\x88\xEA\x92\x9A"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -encoding shiftjis
    list [chan gets $f line] $line
} -cleanup {
    chan close $f
} -result [list 2 "\u4e00\u4e01"]
} -result [list 2 "一ä¸"]
set a "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
append a $a
append a $a
test chan-io-6.6 {Tcl_GetsObj: loop test} -body {
    # if (dst >= dstEnd)
    set f [open $path(test1) w]
    chan puts $f $a
462
463
464
465
466
467
468
469

470
471
472

473
474
475
476
477
478
479

480
481
482

483
484
485
486
487
488
489
474
475
476
477
478
479
480

481
482
483

484
485
486
487
488
489
490

491
492
493

494
495
496
497
498
499
500
501







-
+


-
+






-
+


-
+







    chan configure $f -blocking 0
    chan gets $f line
} -cleanup {
    chan close $f
} -result {-1}
test chan-io-6.8 {Tcl_GetsObj: remember if EOF is seen} -body {
    set f [open $path(test1) w]
    chan puts $f "abcdef\x1aghijk\nwombat"
    chan puts $f "abcdef\x1Aghijk\nwombat"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -eofchar \x1a
    chan configure $f -eofchar \x1A
    list [chan gets $f line] $line [chan gets $f line] $line
} -cleanup {
    chan close $f
} -result {6 abcdef -1 {}}
test chan-io-6.9 {Tcl_GetsObj: remember if EOF is seen} -body {
    set f [open $path(test1) w]
    chan puts $f "abcdefghijk\nwom\u001abat"
    chan puts $f "abcdefghijk\nwom\x1Abat"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -eofchar \x1a
    chan configure $f -eofchar \x1A
    list [chan gets $f line] $line [chan gets $f line] $line
} -cleanup {
    chan close $f
} -result {11 abcdefghijk 3 wom}
# Comprehensive tests
test chan-io-6.10 {Tcl_GetsObj: lf mode: no chars} -body {
    set f [open $path(test1) w]
860
861
862
863
864
865
866
867

868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885

886
887
888
889
890
891
892
872
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
898
899
900
901
902
903
904







-
+

















-
+







    chan configure $f -translation {auto lf} -buffering none
    chan puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
    chan configure $f -buffersize 16
    lappend x [chan gets $f]
    chan configure $f -blocking 0
    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
    chan configure $f -blocking 1
    chan puts -nonewline $f "\nabcd\refg\x1a"
    chan puts -nonewline $f "\nabcd\refg\x1A"
    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
    lappend x [chan gets $f line] $line
} -cleanup {
    chan close $f
} -result {bbbbbbbbbbbbbbb 15 123456789abcdef 1 4 abcd 0 3 efg}
test chan-io-6.44 {Tcl_GetsObj: input saw cr, not followed by cr} -setup {
    set x ""
} -constraints {stdio testchannel fileevent} -body {
    # not (*eol == '\n')
    set f [openpipe w+ $path(cat)]
    chan configure $f -translation {auto lf} -buffering none
    chan puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
    chan configure $f -buffersize 16
    lappend x [chan gets $f]
    chan configure $f -blocking 0
    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
    chan configure $f -blocking 1
    chan puts -nonewline $f "abcd\refg\x1a"
    chan puts -nonewline $f "abcd\refg\x1A"
    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
    lappend x [chan gets $f line] $line
} -cleanup {
    chan close $f
} -result {bbbbbbbbbbbbbbb 15 123456789abcdef 1 4 abcd 0 3 efg}
test chan-io-6.45 {Tcl_GetsObj: input saw cr, skip right number of bytes} -setup {
    set x ""
914
915
916
917
918
919
920
921

922
923
924
925
926
927
928
926
927
928
929
930
931
932

933
934
935
936
937
938
939
940







-
+







    chan configure $f -translation {auto lf} -buffering none
    chan puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
    chan configure $f -buffersize 16
    chan gets $f
    chan configure $f -blocking 0
    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
    chan configure $f -blocking 1
    chan puts -nonewline $f "\n\x1a"
    chan puts -nonewline $f "\n\x1A"
    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
} -cleanup {
    chan close $f
} -result {15 123456789abcdef 1 -1 {} 0}
test chan-io-6.47 {Tcl_GetsObj: auto mode: \r at end of buffer, peek for \n} -constraints {testchannel} -body {
    # (eol == dstEnd)
    set f [open $path(test1) w]
980
981
982
983
984
985
986
987

988
989
990

991
992
993
994
995
996
997
992
993
994
995
996
997
998

999
1000
1001

1002
1003
1004
1005
1006
1007
1008
1009







-
+


-
+







} -cleanup {
    chan close $f
} -result {123456 7 78901}
test chan-io-6.52 {Tcl_GetsObj: saw EOF character} -constraints {testchannel} -body {
    # if (eof != NULL)
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "123456\x1ak9012345\r"
    chan puts -nonewline $f "123456\x1Ak9012345\r"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -eofchar \x1a
    chan configure $f -eofchar \x1A
    list [chan gets $f] [testchannel queuedcr $f] [chan tell $f] [chan gets $f]
} -cleanup {
    chan close $f
} -result {123456 0 6 {}}
test chan-io-6.53 {Tcl_GetsObj: device EOF} -body {
    # didn't produce any bytes
    set f [open $path(test1) w]
1011
1012
1013
1014
1015
1016
1017
1018

1019
1020
1021
1022
1023
1024
1025

1026
1027
1028
1029
1030
1031
1032
1023
1024
1025
1026
1027
1028
1029

1030
1031
1032
1033
1034
1035
1036

1037
1038
1039
1040
1041
1042
1043
1044







-
+






-
+







} -cleanup {
    chan close $f
} -result {3 abc 1}
test chan-io-6.55 {Tcl_GetsObj: overconverted} -body {
    # Tcl_ExternalToUtf(), make sure state updated
    set f [open $path(test1) w]
    chan configure $f -encoding iso2022-jp
    chan puts $f "there\u4e00ok\n\u4e01more bytes\nhere"
    chan puts $f "there一ok\nä¸more bytes\nhere"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -encoding iso2022-jp
    list [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line
} -cleanup {
    chan close $f
} -result [list 8 "there\u4e00ok" 11 "\u4e01more bytes" 4 "here"]
} -result [list 8 "there一ok" 11 "ä¸more bytes" 4 "here"]
test chan-io-6.56 {Tcl_GetsObj: incomplete lines should disable file events} -setup {
    update
    variable x {}
} -constraints {stdio fileevent} -body {
    set f [openpipe w+ $path(cat)]
    chan configure $f -buffering none
    chan puts -nonewline $f "foobar"
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
1116
1117
1118
1119
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
1116

1117
1118
1119
1120
1121
1122
1123

1124
1125
1126
1127
1128
1129
1130
1131







-
+






-
+



-
-
+
+











-
-
+
+


-
+





-
+




-
-
+
+





-
+






-
+







    chan close $f
} -result {{} timeout foobarbaz timeout}

test chan-io-7.1 {FilterInputBytes: split up character at end of buffer} -body {
    # (result == TCL_CONVERT_MULTIBYTE)
    set f [open $path(test1) w]
    chan configure $f -encoding shiftjis
    chan puts $f "1234567890123\uff10\uff11\uff12\uff13\uff14\nend"
    chan puts $f "1234567890123ï¼ï¼‘234\nend"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -encoding shiftjis -buffersize 16
    chan gets $f
} -cleanup {
    chan close $f
} -result "1234567890123\uff10\uff11\uff12\uff13\uff14"
} -result "1234567890123ï¼ï¼‘234"
test chan-io-7.2 {FilterInputBytes: split up character in middle of buffer} -body {
    # (bufPtr->nextAdded < bufPtr->bufLength)
    set f [open $path(test1) w]
    chan configure $f -encoding binary
    chan puts -nonewline $f "1234567890\n123\x82\x4f\x82\x50\x82"
    chan configure $f -translation binary
    chan puts -nonewline $f "1234567890\n123\x82\x4F\x82\x50\x82"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -encoding shiftjis
    list [chan gets $f line] $line [chan eof $f]
} -cleanup {
    chan close $f
} -result {10 1234567890 0}
test chan-io-7.3 {FilterInputBytes: split up character at EOF} -setup {
    set x ""
} -constraints {testchannel} -body {
    set f [open $path(test1) w]
    chan configure $f -encoding binary
    chan puts -nonewline $f "1234567890123\x82\x4f\x82\x50\x82"
    chan configure $f -translation binary
    chan puts -nonewline $f "1234567890123\x82\x4F\x82\x50\x82"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -encoding shiftjis
    chan configure $f -encoding shiftjis -profile tcl8
    lappend x [chan gets $f line] $line
    lappend x [chan tell $f] [testchannel inputbuffered $f] [chan eof $f]
    lappend x [chan gets $f line] $line
} -cleanup {
    chan close $f
} -result [list 15 "1234567890123\uff10\uff11" 18 0 1 -1 ""]
} -result [list 16 "1234567890123ï¼ï¼‘\x82" 18 0 1 -1 ""]
test chan-io-7.4 {FilterInputBytes: recover from split up character} -setup {
    variable x ""
} -constraints {stdio fileevent} -body {
    set f [openpipe w+ $path(cat)]
    chan configure $f -encoding binary -buffering none
    chan puts -nonewline $f "1234567890123\x82\x4f\x82\x50\x82"
    chan configure $f -translation binary -buffering none
    chan puts -nonewline $f "1234567890123\x82\x4F\x82\x50\x82"
    chan configure $f -encoding shiftjis -blocking 0
    chan event $f read [namespace code {
	lappend x [chan gets $f line] $line [chan blocked $f]
    }]
    vwait [namespace which -variable x]
    chan configure $f -encoding binary -blocking 1
    chan configure $f -translation binary -blocking 1
    chan puts $f "\x51\x82\x52"
    chan configure $f -encoding shiftjis
    vwait [namespace which -variable x]
    return $x
} -cleanup {
    chan close $f
} -result [list -1 "" 1 17 "1234567890123\uff10\uff11\uff12\uff13" 0]
} -result [list -1 "" 1 17 "1234567890123ï¼ï¼‘23" 0]

test chan-io-8.1 {PeekAhead: only go to device if no more cached data} -constraints {testchannel} -body {
    # (bufPtr->nextPtr == NULL)
    set f [open $path(test1) w]
    chan configure $f -encoding ascii -translation lf
    chan puts -nonewline $f "123456789012345\r\n2345678"
    chan close $f
1160
1161
1162
1163
1164
1165
1166
1167

1168
1169
1170
1171
1172
1173
1174
1172
1173
1174
1175
1176
1177
1178

1179
1180
1181
1182
1183
1184
1185
1186







-
+







test chan-io-8.4 {PeekAhead: cached data available in this buffer} -body {
    # not (bytesLeft == 0)
    set f [open $path(test1) w+]
    chan configure $f -translation binary
    chan puts $f "${a}\r\nabcdef"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -encoding binary -translation auto
    chan configure $f -translation binary -translation auto
    # "${a}\r" was converted in one operation (because ENCODING_LINESIZE is
    # 30). To check if "\n" follows, calls PeekAhead and determines that
    # cached data is available in buffer w/o having to call driver.
    chan gets $f
} -cleanup {
    chan close $f
} -result $a
1200
1201
1202
1203
1204
1205
1206
1207

1208
1209
1210
1211
1212
1213
1214
1212
1213
1214
1215
1216
1217
1218

1219
1220
1221
1222
1223
1224
1225
1226







-
+







} -constraints {stdio testchannel fileevent} -body {
    # Make sure bytes are removed from buffer.
    set f [openpipe w+ $path(cat)]
    chan configure $f -translation {auto binary} -buffering none
    chan puts -nonewline $f "abcdefghijklmno\r"
    # here
    lappend x [chan gets $f line] $line [testchannel queuedcr $f]
    chan puts -nonewline $f "\x1a"
    chan puts -nonewline $f \x1A
    lappend x [chan gets $f line] $line
} -cleanup {
    chan close $f
} -result {15 abcdefghijklmno 1 -1 {}}

test chan-io-9.1 {CommonGetsCleanup} emptyTest {
} {}
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
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







-
+











-
+











-
+











-
+








test chan-io-11.1 {ReadBytes: want to read a lot} -body {
    # ((unsigned) toRead > (unsigned) srcLen)
    set f [open $path(test1) w]
    chan puts -nonewline $f abcdefghijkl
    chan close $f
    set f [open $path(test1)]
    chan configure $f -encoding binary
    chan configure $f -translation binary
    # here
    chan read $f 1000
} -cleanup {
    chan close $f
} -result {abcdefghijkl}
test chan-io-11.2 {ReadBytes: want to read all} -body {
    # ((unsigned) toRead > (unsigned) srcLen)
    set f [open $path(test1) w]
    chan puts -nonewline $f abcdefghijkl
    chan close $f
    set f [open $path(test1)]
    chan configure $f -encoding binary
    chan configure $f -translation binary
    # here
    chan read $f
} -cleanup {
    chan close $f
} -result {abcdefghijkl}
test chan-io-11.3 {ReadBytes: allocate more space} -body {
    # (toRead > length - offset - 1)
    set f [open $path(test1) w]
    chan puts -nonewline $f abcdefghijklmnopqrstuvwxyz
    chan close $f
    set f [open $path(test1)]
    chan configure $f -buffersize 16 -encoding binary
    chan configure $f -buffersize 16 -translation binary
    # here
    chan read $f
} -cleanup {
    chan close $f
} -result {abcdefghijklmnopqrstuvwxyz}
test chan-io-11.4 {ReadBytes: EOF char found} -body {
    # (TranslateInputEOL() != 0)
    set f [open $path(test1) w]
    chan puts $f abcdefghijklmnopqrstuvwxyz
    chan close $f
    set f [open $path(test1)]
    chan configure $f -eofchar m -encoding binary
    chan configure $f -translation binary -eofchar m
    # here
    list [chan read $f] [chan eof $f] [chan read $f] [chan eof $f]
} -cleanup {
    chan close $f
} -result {abcdefghijkl 1 {} 1}

test chan-io-12.1 {ReadChars: want to read a lot} -body {
1347
1348
1349
1350
1351
1352
1353
1354

1355
1356
1357
1358
1359
1360
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
1359
1360
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




1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397







-
+







-
-
+
+






-
+




-
-
-
-
+
+
+
+







    chan close $f
} -result {abcdefghijklmnopqrstuvwxyz}
test chan-io-12.4 {ReadChars: split-up char} -setup {
    variable x {}
} -constraints {stdio testchannel fileevent} -body {
    # (srcRead == 0)
    set f [openpipe w+ $path(cat)]
    chan configure $f -encoding binary -buffering none -buffersize 16
    chan configure $f -translation binary -buffering none -buffersize 16
    chan puts -nonewline $f "123456789012345\x96"
    chan configure $f -encoding shiftjis -blocking 0
    chan event $f read [namespace code {
	lappend x [chan read $f] [testchannel inputbuffered $f]
    }]
    chan configure $f -encoding shiftjis
    vwait [namespace which -variable x]
    chan configure $f -encoding binary -blocking 1
    chan puts -nonewline $f "\x7b"
    chan configure $f -translation binary -blocking 1
    chan puts -nonewline $f \x7B
    after 500			;# Give the cat process time to catch up
    chan configure $f -encoding shiftjis -blocking 0
    vwait [namespace which -variable x]
    return $x
} -cleanup {
    chan close $f
} -result [list "123456789012345" 1 "\u672c" 0]
} -result [list "123456789012345" 1 本 0]
test chan-io-12.5 {ReadChars: chan events on partial characters} -setup {
    variable x {}
} -constraints {stdio fileevent} -body {
    set path(test1) [makeFile {
	chan configure stdout -encoding binary -buffering none
	chan gets stdin; chan puts -nonewline "\xe7"
	chan gets stdin; chan puts -nonewline "\x89"
	chan gets stdin; chan puts -nonewline "\xa6"
	chan configure stdout -translation binary -buffering none
	chan gets stdin; chan puts -nonewline \xE7
	chan gets stdin; chan puts -nonewline \x89
	chan gets stdin; chan puts -nonewline \xA6
    } test1]
    set f [openpipe r+ $path(test1)]
    chan event $f readable [namespace code {
	lappend x [chan read $f]
	if {[chan eof $f]} {
	    lappend x eof
	}
1396
1397
1398
1399
1400
1401
1402
1403

1404
1405
1406
1407
1408
1409
1410
1408
1409
1410
1411
1412
1413
1414

1415
1416
1417
1418
1419
1420
1421
1422







-
+







    after 500 [namespace code { lappend x timeout }]
    vwait [namespace which -variable x]
    chan puts $f "go3"
    chan flush $f
    vwait [namespace which -variable x]
    vwait [namespace which -variable x]
    lappend x [catch {chan close $f} msg] $msg
} -result "{} timeout {} timeout \u7266 {} eof 0 {}"
} -result "{} timeout {} timeout 牦 {} eof 0 {}"

test chan-io-13.1 {TranslateInputEOL: cr mode} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "abcd\rdef\r"
    chan close $f
    set f [open $path(test1)]
1525
1526
1527
1528
1529
1530
1531
1532

1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544

1545
1546
1547
1548
1549
1550
1551
1537
1538
1539
1540
1541
1542
1543

1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555

1556
1557
1558
1559
1560
1561
1562
1563







-
+











-
+







    set f [open $path(test1)]
    chan configure $f -translation auto
    chan read $f
} -cleanup {
    chan close $f
} -result "abcd\ndef"
test chan-io-13.11 {TranslateInputEOL: EOF char} -body {
    # (*chanPtr->inEofChar != '\0')
    # (*chanPtr->inEofChar != '\x00')
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "abcd\ndefgh"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation auto -eofchar e
    chan read $f
} -cleanup {
    chan close $f
} -result "abcd\nd"
test chan-io-13.12 {TranslateInputEOL: find EOF char in src} -body {
    # (*chanPtr->inEofChar != '\0')
    # (*chanPtr->inEofChar != '\x00')
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f "\r\n\r\n\r\nab\r\n\r\ndef\r\n\r\n\r\n"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -translation auto -eofchar e
    chan read $f
1701
1702
1703
1704
1705
1706
1707
1708

1709
1710
1711
1712
1713
1714
1715
1713
1714
1715
1716
1717
1718
1719

1720
1721
1722
1723
1724
1725
1726
1727







-
+







} -result hello
test chan-io-14.9 {reuse of stdio special channels} -setup {
    file delete $path(script)
    file delete $path(test1)
} -constraints {stdio fileevent} -body {
    set f [open $path(script) w]
    chan puts $f {
        array set path [lindex $argv 0]
	array set path [lindex $argv 0]
	set f [open $path(test1) w]
	chan puts $f hello
	chan close $f
	chan close stderr
	set f [open "|[list [info nameofexecutable] $path(cat) $path(test1)]" r]
	chan puts [chan gets $f]
    }
1873
1874
1875
1876
1877
1878
1879
1880

1881
1882
1883
1884
1885
1886

1887
1888
1889

1890
1891
1892
1893
1894
1895
1896
1885
1886
1887
1888
1889
1890
1891

1892
1893
1894
1895
1896
1897

1898
1899
1900

1901
1902
1903
1904
1905
1906
1907
1908







-
+





-
+


-
+







    chan close $a
} -result {ascii}
test chan-io-20.2 {Tcl_CreateChannel: initial settings} -constraints {win} -body {
    set f [open $path(test1) w+]
    list [chan configure $f -eofchar] [chan configure $f -translation]
} -cleanup {
    chan close $f
} -result [list [list \x1a ""] {auto crlf}]
} -result {{} {auto crlf}}
test chan-io-20.3 {Tcl_CreateChannel: initial settings} -constraints {unix} -body {
    set f [open $path(test1) w+]
    list [chan configure $f -eofchar] [chan configure $f -translation]
} -cleanup {
    chan close $f
} -result {{{} {}} {auto lf}}
} -result {{} {auto lf}}
test chan-io-20.5 {Tcl_CreateChannel: install channel in empty slot} -setup {
    set path(stdout) [makeFile {} stdout]
} -constraints {stdio knownMsvcBug} -body {
} -constraints {stdio notWinCI} -body {
    set f [open $path(script) w]
    chan puts -nonewline $f {
	chan close stdout
	set f1 [}
    chan puts $f [list open $path(stdout) w]]
    chan puts $f {
	chan configure $f1 -buffersize 777
1935
1936
1937
1938
1939
1940
1941
1942

1943
1944
1945
1946
1947
1948
1949
1947
1948
1949
1950
1951
1952
1953

1954
1955
1956
1957
1958
1959
1960
1961







-
+







    chan close $f
} -result "file"

test chan-io-25.1 {Tcl_GetChannelHandle, input} -setup {
    set l ""
} -constraints {testchannel} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    chan puts $f "1234567890\n098765432"
    chan close $f
    set f [open $path(test1) r]
    chan gets $f
    lappend l [testchannel inputbuffered $f]
    lappend l [chan tell $f]
} -cleanup {
1987
1988
1989
1990
1991
1992
1993
1994

1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007

2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018

2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035

2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
1999
2000
2001
2002
2003
2004
2005

2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018

2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029

2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046

2047
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
2095
2096
2097
2098







-
+












-
+










-
+
















-
+

















-
+









-
+













-
+

-
+







    chan close $f
} -result 0
test chan-io-27.2 {FlushChannel, some output buffered} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    chan puts $f hello
    lappend l [file size $path(test1)]
    chan flush $f
    lappend l [file size $path(test1)]
    chan close $f
    lappend l [file size $path(test1)]
} -result {0 6 6}
test chan-io-27.3 {FlushChannel, implicit flush on chan close} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    chan puts $f hello
    lappend l [file size $path(test1)]
    chan close $f
    lappend l [file size $path(test1)]
} -result {0 6}
test chan-io-27.4 {FlushChannel, implicit flush when buffer fills} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    chan configure $f -buffersize 60
    lappend l [file size $path(test1)]
    for {set i 0} {$i < 12} {incr i} {
	chan puts $f hello
    }
    lappend l [file size $path(test1)]
    chan flush $f
    lappend l [file size $path(test1)]
} -cleanup {
    chan close $f
} -result {0 60 72}
test chan-io-27.5 {FlushChannel, implicit flush when buffer fills and on chan close} -setup {
    file delete $path(test1)
    set l ""
} -constraints {unixOrWin} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf -buffersize 60 -eofchar {}
    chan configure $f -translation lf -buffersize 60
    lappend l [file size $path(test1)]
    for {set i 0} {$i < 12} {incr i} {
	chan puts $f hello
    }
    lappend l [file size $path(test1)]
    chan close $f
    lappend l [file size $path(test1)]
} -result {0 60 72}
set path(pipe)   [makeFile {} pipe]
set path(output) [makeFile {} output]
test chan-io-27.6 {FlushChannel, async flushing, async chan close} -setup {
    file delete $path(pipe)
    file delete $path(output)
} -constraints {stdio asyncPipeChan Close} -body {
    set f [open $path(pipe) w]
    chan puts $f "set f \[[list open $path(output) w]]"
    chan puts $f {
	chan configure $f -translation lf -buffering none -eofchar {}
	chan configure $f -translation lf -buffering none
	while {![chan eof stdin]} {
	    after 20
	    chan puts -nonewline $f [chan read stdin 1024]
	}
	chan close $f
    }
    chan close $f
    set x 01234567890123456789012345678901
    for {set i 0} {$i < 11} {incr i} {
        set x "$x$x"
	set x "$x$x"
    }
    set f [open $path(output) w]
    chan close $f
    set f [openpipe w $path(pipe)]
    chan configure $f -blocking off
    chan puts -nonewline $f $x
    chan close $f
    set counter 0
    while {([file size $path(output)] < 65536) && ($counter < 1000)} {
	after 20 [list incr [namespace which -variable counter]]
	vwait [namespace which -variable counter]
    }
    if {$counter == 1000} {
        set result "file size only [file size $path(output)]"
	set result "file size only [file size $path(output)]"
    } else {
        set result ok
	set result ok
    }
} -result ok

# Tests closing a channel. The functions tested are Chan CloseChannel and
# Tcl_Chan Close.

test chan-io-28.1 {Chan CloseChannel called when all references are dropped} -setup {
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138

2139
2140
2141
2142
2143

2144
2145
2146
2147
2148
2149
2150
2151
2152

2153
2154

2155
2156
2157
2158
2159
2160
2161
2127
2128
2129
2130
2131
2132
2133





2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144

2145
2146
2147
2148
2149

2150
2151
2152
2153
2154
2155
2156
2157
2158

2159
2160

2161
2162
2163
2164
2165
2166
2167
2168







-
-
-
-
-











-
+




-
+








-
+

-
+







} -result abcdef
test chan-io-28.3 {Chan CloseChannel, not called before output queue is empty} -setup {
    file delete $path(pipe)
    file delete $path(output)
} -constraints {stdio asyncPipeChan Close nonPortable} -body {
    set f [open $path(pipe) w]
    chan puts $f {
	# Need to not have eof char appended on chan close, because the other
	# side of the pipe already chan closed, so that writing would cause an
	# error "invalid file".
	chan configure stdout -eofchar {}
	chan configure stderr -eofchar {}
	set f [open $path(output) w]
	chan configure $f -translation lf -buffering none
	for {set x 0} {$x < 20} {incr x} {
	    after 20
	    chan puts -nonewline $f [chan read stdin 1024]
	}
	chan close $f
    }
    chan close $f
    set x 01234567890123456789012345678901
    for {set i 0} {$i < 11} {incr i} {
        set x "$x$x"
	set x "$x$x"
    }
    set f [open $path(output) w]
    chan close $f
    set f [openpipe r+ $path(pipe)]
    chan configure $f -blocking off -eofchar {}
    chan configure $f -blocking off
    chan puts -nonewline $f $x
    chan close $f
    set counter 0
    while {([file size $path(output)] < 20480) && ($counter < 1000)} {
	after 20 [list incr [namespace which -variable counter]]
	vwait [namespace which -variable counter]
    }
    if {$counter == 1000} {
        set result probably_broken
	set result probably_broken
    } else {
        set result ok
	set result ok
    }
} -result ok
test chan-io-28.4 {Tcl_Chan Close} -constraints {testchannel} -setup {
    file delete $path(test1)
    set l ""
} -body {
    lappend l [lsort [testchannel open]]
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279

2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294

2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309

2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324

2325
2326
2327
2328
2329
2330
2331
2260
2261
2262
2263
2264
2265
2266

2267
2268
2269
2270
2271
2272
2273
2274

2275
2276
2277
2278
2279
2280
2281
2282
2283

2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298

2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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







-








-









-
+














-
+














-
+














-
+







test chan-io-29.1 {Tcl_WriteChars, channel not writable} -body {
    chan puts stdin hello
} -returnCodes error -result {channel "stdin" wasn't opened for writing}
test chan-io-29.2 {Tcl_WriteChars, empty string} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -eofchar {}
    chan puts -nonewline $f ""
    chan close $f
    file size $path(test1)
} -result 0
test chan-io-29.3 {Tcl_WriteChars, nonempty string} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -eofchar {}
    chan puts -nonewline $f hello
    chan close $f
    file size $path(test1)
} -result 5
test chan-io-29.4 {Tcl_WriteChars, buffering in full buffering mode} -setup {
    file delete $path(test1)
    set l ""
} -constraints {testchannel} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf -buffering full -eofchar {}
    chan configure $f -translation lf -buffering full
    chan puts $f hello
    lappend l [testchannel outputbuffered $f]
    lappend l [file size $path(test1)]
    chan flush $f
    lappend l [testchannel outputbuffered $f]
    lappend l [file size $path(test1)]
} -cleanup {
    chan close $f
} -result {6 0 0 6}
test chan-io-29.5 {Tcl_WriteChars, buffering in line buffering mode} -setup {
    file delete $path(test1)
    set l ""
} -constraints {testchannel} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf -buffering line -eofchar {}
    chan configure $f -translation lf -buffering line
    chan puts -nonewline $f hello
    lappend l [testchannel outputbuffered $f]
    lappend l [file size $path(test1)]
    chan puts $f hello
    lappend l [testchannel outputbuffered $f]
    lappend l [file size $path(test1)]
} -cleanup {
    chan close $f
} -result {5 0 0 11}
test chan-io-29.6 {Tcl_WriteChars, buffering in no buffering mode} -setup {
    file delete $path(test1)
    set l ""
} -constraints {testchannel} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf -buffering none -eofchar {}
    chan configure $f -translation lf -buffering none
    chan puts -nonewline $f hello
    lappend l [testchannel outputbuffered $f]
    lappend l [file size $path(test1)]
    chan puts $f hello
    lappend l [testchannel outputbuffered $f]
    lappend l [file size $path(test1)]
} -cleanup {
    chan close $f
} -result {0 5 0 11}
test chan-io-29.7 {Tcl_Flush, full buffering} -setup {
    file delete $path(test1)
    set l ""
} -constraints {testchannel} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf -buffering full -eofchar {}
    chan configure $f -translation lf -buffering full
    chan puts -nonewline $f hello
    lappend l [testchannel outputbuffered $f]
    lappend l [file size $path(test1)]
    chan puts $f hello
    lappend l [testchannel outputbuffered $f]
    lappend l [file size $path(test1)]
    chan flush $f
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
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







-
+












-







test chan-io-29.9 {Tcl_Flush, channel not writable} -body {
    chan flush stdin
} -returnCodes error -result {channel "stdin" wasn't opened for writing}
test chan-io-29.10 {Tcl_WriteChars, looping and buffering} -setup {
    file delete $path(test1)
} -body {
    set f1 [open $path(test1) w]
    chan configure $f1 -translation lf -eofchar {}
    chan configure $f1 -translation lf
    set f2 [open $path(longfile) r]
    for {set x 0} {$x < 10} {incr x} {
	chan puts $f1 [chan gets $f2]
    }
    chan close $f2
    chan close $f1
    file size $path(test1)
} -result 387
test chan-io-29.11 {Tcl_WriteChars, no newline, implicit flush} -setup {
    file delete $path(test1)
} -body {
    set f1 [open $path(test1) w]
    chan configure $f1 -eofchar {}
    set f2 [open $path(longfile) r]
    for {set x 0} {$x < 10} {incr x} {
	chan puts -nonewline $f1 [chan gets $f2]
    }
    chan close $f1
    chan close $f2
    file size $path(test1)
2505
2506
2507
2508
2509
2510
2511
2512

2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530

2531
2532
2533
2534
2535
2536
2537
2509
2510
2511
2512
2513
2514
2515

2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533

2534
2535
2536
2537
2538
2539
2540
2541







-
+

















-
+







} -cleanup {
    chan close $f1
} -result {18 24 30}
test chan-io-29.19 {Explicit and implicit flushes} -setup {
    file delete $path(test1)
} -body {
    set f1 [open $path(test1) w]
    chan configure $f1 -translation lf -eofchar {}
    chan configure $f1 -translation lf
    set x ""
    chan puts $f1 hello
    chan puts $f1 hello
    chan puts $f1 hello
    chan flush $f1
    lappend x [file size $path(test1)]
    chan puts $f1 hello
    chan flush $f1
    lappend x [file size $path(test1)]
    chan puts $f1 hello
    chan close $f1
    lappend x [file size $path(test1)]
} -result {18 24 30}
test chan-io-29.20 {Implicit flush when buffer is full} -setup {
    file delete $path(test1)
} -body {
    set f1 [open $path(test1) w]
    chan configure $f1 -translation lf -eofchar {}
    chan configure $f1 -translation lf
    set line "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    for {set x 0} {$x < 100} {incr x} {
      chan puts $f1 $line
    }
    set z ""
    lappend z [file size $path(test1)]
    for {set x 0} {$x < 100} {incr x} {
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
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







-
+










-
+








-
+







    }
    string tolower $x
} -match glob -result {1 {error flushing "*": broken pipe} {posix epipe {broken pipe}}}
test chan-io-29.28 {Tcl_WriteChars, lf mode} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    chan puts $f hello\nthere\nand\nhere
    chan flush $f
    file size $path(test1)
} -cleanup {
    chan close $f
} -result 21
test chan-io-29.29 {Tcl_WriteChars, cr mode} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation cr -eofchar {}
    chan configure $f -translation cr
    chan puts $f hello\nthere\nand\nhere
    chan close $f
    file size $path(test1)
} -result 21
test chan-io-29.30 {Tcl_WriteChars, crlf mode} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation crlf -eofchar {}
    chan configure $f -translation crlf
    chan puts $f hello\nthere\nand\nhere
    chan close $f
    file size $path(test1)
} -result 25
test chan-io-29.31 {Tcl_WriteChars, background flush} -setup {
    file delete $path(pipe)
    file delete $path(output)
2792
2793
2794
2795
2796
2797
2798
2799

2800
2801
2802
2803
2804
2805
2806
2796
2797
2798
2799
2800
2801
2802

2803
2804
2805
2806
2807
2808
2809
2810







-
+







    variable x running
    set l abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
    proc writelots {s l} {
	for {set i 0} {$i < 2000} {incr i} {
	    chan puts $s $l
	}
    }
} -constraints {socket tempNotMac fileevent knownMsvcBug} -body {
} -constraints {socket tempNotMac fileevent notWinCI} -body {
    proc accept {s a p} {
	variable x
	chan event $s readable [namespace code [list readit $s]]
	chan configure $s -blocking off
	set x accepted
    }
    proc readit {s} {
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
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







-
+
















-
+







    }
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation auto
    string length [chan read $f]
} -cleanup {
    chan close $f
} -result [expr 700*15+1]
} -result [expr {700*15 + 1}]
test chan-io-30.14 {Tcl_Write crlf on block boundary, Tcl_Read crlf} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation crlf
    set line "123456789ABCDE"	;# 14 char plus crlf
    chan puts -nonewline $f x	;# shift crlf across block boundary
    for {set i 0} {$i < 700} {incr i} {
	chan puts $f $line
    }
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation crlf
    string length [chan read $f]
} -cleanup {
    chan close $f
} -result [expr 700*15+1]
} -result [expr {700*15 + 1}]
test chan-io-30.15 {Tcl_Write mixed, Tcl_Read auto} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts $f hello\nthere\nand\rhere
    chan close $f
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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152

3153
3154
3155
3156
3157
3158
3159
3160
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
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209

3210
3211
3212
3213

3214
3215

3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230

3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244

3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258

3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272

3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286

3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300

3301
3302
3303
3304
3305
3306
3307
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
3134

3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155

3156
3157
3158
3159
3160
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

3199
3200

3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212

3213
3214
3215
3216

3217
3218

3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233

3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247

3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261

3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275

3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289

3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303

3304
3305
3306
3307
3308
3309
3310
3311







-
+


-
+












-
+



-
+

















-
+




















-
+
















-
+



-
+











-
+





-
+



-
+

-
+











-
+



-
+

-
+














-
+













-
+













-
+













-
+













-
+













-
+







here
}
test chan-io-30.16 {Tcl_Write ^Z at end, Tcl_Read auto} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f hello\nthere\nand\rhere\n\x1a
    chan puts -nonewline $f hello\nthere\nand\rhere\n\x1A
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -eofchar \x1a -translation auto
    chan configure $f -translation auto -eofchar \x1A
    chan read $f
} -cleanup {
    chan close $f
} -result {hello
there
and
here
}
test chan-io-30.17 {Tcl_Write, implicit ^Z at end, Tcl_Read auto} -setup {
    file delete $path(test1)
} -constraints {win} -body {
    set f [open $path(test1) w]
    chan configure $f -eofchar \x1a -translation lf
    chan configure $f -translation lf -eofchar \x1A
    chan puts $f hello\nthere\nand\rhere
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -eofchar \x1a -translation auto
    chan configure $f -translation auto -eofchar \x1A
    chan read $f
} -cleanup {
    chan close $f
} -result {hello
there
and
here
}
test chan-io-30.18 {Tcl_Write, ^Z in middle, Tcl_Read auto} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf
    set s [format "abc\ndef\n%cghi\nqrs" 26]
    chan puts $f $s
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -eofchar \x1a -translation auto
    chan configure $f -translation auto -eofchar \x1A
    set l ""
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
} -cleanup {
    chan close $f
} -result {abc def 0 {} 1 {} 1}
test chan-io-30.19 {Tcl_Write, ^Z no newline in middle, Tcl_Read auto} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf
    set s [format "abc\ndef\n%cghi\nqrs" 26]
    chan puts $f $s
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -eofchar \x1a -translation auto
    chan configure $f -translation auto -eofchar \x1A
    set l ""
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
} -cleanup {
    chan close $f
} -result {abc def 0 {} 1 {} 1}
test chan-io-30.20 {Tcl_Write, ^Z in middle ignored, Tcl_Read lf} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    chan puts $f [format "abc\ndef\n%cghi\nqrs" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
} -cleanup {
    chan close $f
} -result "abc def 0 \x1aghi 0 qrs 0 {} 1"
} -result "abc def 0 \x1Aghi 0 qrs 0 {} 1"
test chan-io-30.21 {Tcl_Write, ^Z in middle ignored, Tcl_Read cr} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    chan puts $f [format "abc\ndef\n%cghi\nqrs" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation cr -eofchar {}
    chan configure $f -translation cr
    set x [chan gets $f]
    lappend l [string equal $x "abc\ndef\n\x1aghi\nqrs\n"]
    lappend l [string equal $x "abc\ndef\n\x1Aghi\nqrs\n"]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
} -cleanup {
    chan close $f
} -result {1 1 {} 1}
test chan-io-30.22 {Tcl_Write, ^Z in middle ignored, Tcl_Read crlf} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    chan puts $f [format "abc\ndef\n%cghi\nqrs" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation crlf -eofchar {}
    chan configure $f -translation crlf
    set x [chan gets $f]
    lappend l [string equal $x "abc\ndef\n\x1aghi\nqrs\n"]
    lappend l [string equal $x "abc\ndef\n\x1Aghi\nqrs\n"]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
} -cleanup {
    chan close $f
} -result {1 1 {} 1}
test chan-io-30.23 {Tcl_Write lf, ^Z in middle, Tcl_Read auto} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts $f [format abc\ndef\n%cqrs\ntuv 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation auto -eofchar \x1a
    chan configure $f -translation auto -eofchar \x1A
    list [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {8 1}
test chan-io-30.24 {Tcl_Write lf, ^Z in middle, Tcl_Read lf} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf
    set c [format abc\ndef\n%cqrs\ntuv 26]
    chan puts $f $c
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation lf -eofchar \x1a
    chan configure $f -translation lf -eofchar \x1A
    list [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {8 1}
test chan-io-30.25 {Tcl_Write cr, ^Z in middle, Tcl_Read auto} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation cr
    set c [format abc\ndef\n%cqrs\ntuv 26]
    chan puts $f $c
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation auto -eofchar \x1a
    chan configure $f -translation auto -eofchar \x1A
    list [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {8 1}
test chan-io-30.26 {Tcl_Write cr, ^Z in middle, Tcl_Read cr} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation cr
    set c [format abc\ndef\n%cqrs\ntuv 26]
    chan puts $f $c
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation cr -eofchar \x1a
    chan configure $f -translation cr -eofchar \x1A
    list [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {8 1}
test chan-io-30.27 {Tcl_Write crlf, ^Z in middle, Tcl_Read auto} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation crlf
    set c [format abc\ndef\n%cqrs\ntuv 26]
    chan puts $f $c
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation auto -eofchar \x1a
    chan configure $f -translation auto -eofchar \x1A
    list [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {8 1}
test chan-io-30.28 {Tcl_Write crlf, ^Z in middle, Tcl_Read crlf} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation crlf
    set c [format abc\ndef\n%cqrs\ntuv 26]
    chan puts $f $c
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation crlf -eofchar \x1a
    chan configure $f -translation crlf -eofchar \x1A
    list [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {8 1}

# Test end of line translations. Functions tested are Tcl_Write and
# Tcl_Gets.
3554
3555
3556
3557
3558
3559
3560
3561

3562
3563
3564
3565
3566
3567
3568
3558
3559
3560
3561
3562
3563
3564

3565
3566
3567
3568
3569
3570
3571
3572







-
+







    chan configure $f -translation binary
    chan configure $f -translation
} -cleanup {
    chan close $f
} -result lf
#
# Test chan-io-9.14 has been removed because "auto" output translation mode is
# not supoprted.
# not supported.
#
test chan-io-31.14 {Tcl_Write mixed, Tcl_Gets auto} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf
3644
3645
3646
3647
3648
3649
3650
3651

3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667

3668
3669
3670
3671

3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692

3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710

3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724

3725
3726
3727
3728

3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740

3741
3742
3743
3744
3745
3746

3747
3748
3749
3750

3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762

3763
3764
3765
3766
3767
3768

3769
3770
3771
3772

3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784

3785
3786
3787
3788
3789
3790
3791
3792
3793
3794

3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812

3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826

3827
3828
3829
3830

3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844

3845
3846
3847
3848

3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862

3863
3864
3865
3866

3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880

3881
3882
3883
3884

3885
3886
3887
3888
3889
3890
3891
3648
3649
3650
3651
3652
3653
3654

3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670

3671
3672
3673
3674

3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694


3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712

3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726

3727
3728
3729
3730

3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742

3743
3744
3745
3746
3747
3748

3749
3750
3751
3752

3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764

3765
3766
3767
3768
3769
3770

3771
3772
3773
3774

3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786

3787
3788
3789
3790
3791
3792
3793
3794
3795
3796

3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814

3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828

3829
3830
3831
3832

3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846

3847
3848
3849
3850

3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864

3865
3866
3867
3868

3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882

3883
3884
3885
3886

3887
3888
3889
3890
3891
3892
3893
3894







-
+















-
+



-
+



















-
-
+

















-
+













-
+



-
+











-
+





-
+



-
+











-
+





-
+



-
+











-
+









-
+

















-
+













-
+



-
+













-
+



-
+













-
+



-
+













-
+



-
+







    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts $f [format "hello\nthere\nand\rhere\n\%c" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -eofchar \x1a -translation auto
    chan configure $f -translation auto -eofchar \x1A
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
} -cleanup {
    chan close $f
} -result {hello there and here 0 {} 1}
test chan-io-31.19 {Tcl_Write, implicit ^Z at end, Tcl_Gets auto} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -eofchar \x1a -translation lf
    chan configure $f -translation lf -eofchar \x1A
    chan puts $f hello\nthere\nand\rhere
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -eofchar \x1a -translation auto
    chan configure $f -translation auto -eofchar \x1A
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
} -cleanup {
    chan close $f
} -result {hello there and here 0 {} 1}
test chan-io-31.20 {Tcl_Write, ^Z in middle, Tcl_Gets auto, eofChar} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -eofchar \x1a
    chan configure $f -translation auto
    chan configure $f -translation auto -eofchar \x1A
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
} -cleanup {
    chan close $f
} -result {abc def 0 {} 1}
test chan-io-31.21 {Tcl_Write, no newline ^Z in middle, Tcl_Gets auto, eofChar} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -eofchar \x1a -translation auto
    chan configure $f -translation auto -eofchar \x1A
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
} -cleanup {
    chan close $f
} -result {abc def 0 {} 1}
test chan-io-31.22 {Tcl_Write, ^Z in middle ignored, Tcl_Gets lf} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
} -cleanup {
    chan close $f
} -result "abc def 0 \x1aqrs 0 tuv 0 {} 1"
} -result "abc def 0 \x1Aqrs 0 tuv 0 {} 1"
test chan-io-31.23 {Tcl_Write, ^Z in middle ignored, Tcl_Gets cr} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation cr -eofchar {}
    chan configure $f -translation cr
    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation cr -eofchar {}
    chan configure $f -translation cr
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
} -cleanup {
    chan close $f
} -result "abc def 0 \x1aqrs 0 tuv 0 {} 1"
} -result "abc def 0 \x1Aqrs 0 tuv 0 {} 1"
test chan-io-31.24 {Tcl_Write, ^Z in middle ignored, Tcl_Gets crlf} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation crlf -eofchar {}
    chan configure $f -translation crlf
    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation crlf -eofchar {}
    chan configure $f -translation crlf
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
} -cleanup {
    chan close $f
} -result "abc def 0 \x1aqrs 0 tuv 0 {} 1"
} -result "abc def 0 \x1Aqrs 0 tuv 0 {} 1"
test chan-io-31.25 {Tcl_Write lf, ^Z in middle, Tcl_Gets auto} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation auto -eofchar \x1a
    chan configure $f -translation auto -eofchar \x1A
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
} -cleanup {
    chan close $f
} -result {abc def 0 {} 1}
test chan-io-31.26 {Tcl_Write lf, ^Z in middle, Tcl_Gets lf} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation lf -eofchar \x1a
    chan configure $f -translation lf -eofchar \x1A
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
} -cleanup {
    chan close $f
} -result {abc def 0 {} 1}
test chan-io-31.27 {Tcl_Write cr, ^Z in middle, Tcl_Gets auto} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation cr -eofchar {}
    chan configure $f -translation cr
    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation auto -eofchar \x1a
    chan configure $f -translation auto -eofchar \x1A
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
} -cleanup {
    chan close $f
} -result {abc def 0 {} 1}
test chan-io-31.28 {Tcl_Write cr, ^Z in middle, Tcl_Gets cr} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation cr -eofchar {}
    chan configure $f -translation cr
    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation cr -eofchar \x1a
    chan configure $f -translation cr -eofchar \x1A
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
} -cleanup {
    chan close $f
} -result {abc def 0 {} 1}
test chan-io-31.29 {Tcl_Write crlf, ^Z in middle, Tcl_Gets auto} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation crlf -eofchar {}
    chan configure $f -translation crlf
    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation auto -eofchar \x1a
    chan configure $f -translation auto -eofchar \x1A
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
} -cleanup {
    chan close $f
} -result {abc def 0 {} 1}
test chan-io-31.30 {Tcl_Write crlf, ^Z in middle, Tcl_Gets crlf} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation crlf -eofchar {}
    chan configure $f -translation crlf
    chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation crlf -eofchar \x1a
    chan configure $f -translation crlf -eofchar \x1A
    lappend l [chan gets $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
    lappend l [chan gets $f]
    lappend l [chan eof $f]
} -cleanup {
    chan close $f
3905
3906
3907
3908
3909
3910
3911
3912

3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932

3933
3934
3935
3936
3937
3938
3939
3908
3909
3910
3911
3912
3913
3914

3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934

3935
3936
3937
3938
3939
3940
3941
3942







-
+



















-
+







    set f [open $path(test1) r]
    chan configure $f -translation crlf
    while {[chan gets $f line] >= 0} {
	append c $line\n
    }
    chan close $f
    string length $c
} -result [expr 700*15+1]
} -result [expr {700*15 + 1}]
test chan-io-31.32 {Tcl_Write crlf on block boundary, Tcl_Gets auto} -setup {
    file delete $path(test1)
    set c ""
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation crlf
    set line "123456789ABCDE"	;# 14 char plus crlf
    chan puts -nonewline $f x	;# shift crlf across block boundary
    for {set i 0} {$i < 700} {incr i} {
	chan puts $f $line
    }
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation auto
    while {[chan gets $f line] >= 0} {
	append c $line\n
    }
    chan close $f
    string length $c
} -result [expr 700*15+1]
} -result [expr {700*15 + 1}]

# Test Tcl_Read and buffering.

test chan-io-32.1 {Tcl_Read, channel not readable} -body {
    read stdout
} -returnCodes error -result {channel "stdout" wasn't opened for reading}
test chan-io-32.2 {Tcl_Read, zero byte count} {
4204
4205
4206
4207
4208
4209
4210
4211

4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224

4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237

4238
4239
4240
4241
4242
4243
4244
4207
4208
4209
4210
4211
4212
4213

4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226

4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239

4240
4241
4242
4243
4244
4245
4246
4247







-
+












-
+












-
+







    set x 24
    chan gets $f x(0)
} -returnCodes error -cleanup {
    chan close $f
} -result {can't set "x(0)": variable isn't array}
test chan-io-33.8 {Tcl_Gets, exercising double buffering} {
    set f [open $path(test3) w]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    set x ""
    for {set y 0} {$y < 99} {incr y} {set x "a$x"}
    for {set y 0} {$y < 100} {incr y} {chan puts $f $x}
    chan close $f
    set f [open $path(test3) r]
    chan configure $f -translation lf
    for {set y 0} {$y < 100} {incr y} {chan gets $f}
    chan close $f
    set y
} 100
test chan-io-33.9 {Tcl_Gets, exercising double buffering} {
    set f [open $path(test3) w]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    set x ""
    for {set y 0} {$y < 99} {incr y} {set x "a$x"}
    for {set y 0} {$y < 200} {incr y} {chan puts $f $x}
    chan close $f
    set f [open $path(test3) r]
    chan configure $f -translation lf
    for {set y 0} {$y < 200} {incr y} {chan gets $f}
    chan close $f
    set y
} 200
test chan-io-33.10 {Tcl_Gets, exercising double buffering} {
    set f [open $path(test3) w]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    set x ""
    for {set y 0} {$y < 99} {incr y} {set x "a$x"}
    for {set y 0} {$y < 300} {incr y} {chan puts $f $x}
    chan close $f
    set f [open $path(test3) r]
    chan configure $f -translation lf
    for {set y 0} {$y < 300} {incr y} {chan gets $f}
4255
4256
4257
4258
4259
4260
4261
4262

4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276

4277
4278
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
4258
4259
4260
4261
4262
4263
4264

4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278

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







-
+













-
+













-
+













-
+














-
+














-
+







} -cleanup {
    chan close $f1
} -result 0
test chan-io-34.2 {Tcl_Seek to offset from start} -setup {
    file delete $path(test1)
} -body {
    set f1 [open $path(test1) w]
    chan configure $f1 -translation lf -eofchar {}
    chan configure $f1 -translation lf
    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
    chan close $f1
    set f1 [open $path(test1) r]
    chan seek $f1 10 start
    chan tell $f1
} -cleanup {
    chan close $f1
} -result 10
test chan-io-34.3 {Tcl_Seek to end of file} -setup {
    file delete $path(test1)
} -body {
    set f1 [open $path(test1) w]
    chan configure $f1 -translation lf -eofchar {}
    chan configure $f1 -translation lf
    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
    chan close $f1
    set f1 [open $path(test1) r]
    chan seek $f1 0 end
    chan tell $f1
} -cleanup {
    chan close $f1
} -result 54
test chan-io-34.4 {Tcl_Seek to offset from end of file} -setup {
    file delete $path(test1)
} -body {
    set f1 [open $path(test1) w]
    chan configure $f1 -translation lf -eofchar {}
    chan configure $f1 -translation lf
    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
    chan close $f1
    set f1 [open $path(test1) r]
    chan seek $f1 -10 end
    chan tell $f1
} -cleanup {
    chan close $f1
} -result 44
test chan-io-34.5 {Tcl_Seek to offset from current position} -setup {
    file delete $path(test1)
} -body {
    set f1 [open $path(test1) w]
    chan configure $f1 -translation lf -eofchar {}
    chan configure $f1 -translation lf
    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
    chan close $f1
    set f1 [open $path(test1) r]
    chan seek $f1 10 current
    chan seek $f1 10 current
    chan tell $f1
} -cleanup {
    chan close $f1
} -result 20
test chan-io-34.6 {Tcl_Seek to offset from end of file} -setup {
    file delete $path(test1)
} -body {
    set f1 [open $path(test1) w]
    chan configure $f1 -translation lf -eofchar {}
    chan configure $f1 -translation lf
    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
    chan close $f1
    set f1 [open $path(test1) r]
    chan seek $f1 -10 end
    list [chan tell $f1] [chan read $f1]
} -cleanup {
    chan close $f1
} -result {44 {rstuvwxyz
}}
test chan-io-34.7 {Tcl_Seek to offset from end of file, then to current position} -setup {
    file delete $path(test1)
} -body {
    set f1 [open $path(test1) w]
    chan configure $f1 -translation lf -eofchar {}
    chan configure $f1 -translation lf
    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
    chan close $f1
    set f1 [open $path(test1) r]
    chan seek $f1 -10 end
    set c1 [chan tell $f1]
    set r1 [chan read $f1 5]
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4354
4355
4356
4357
4358
4359
4360

4361
4362
4363
4364
4365
4366
4367







-







} -returnCodes error -cleanup {
    chan close $pipe
} -match glob -result {error during seek on "*": invalid argument}
test chan-io-34.9 {Tcl_Seek, testing buffered input flushing} -setup {
    file delete $path(test3)
} -body {
    set f [open $path(test3) w]
    chan configure $f -eofchar {}
    chan puts -nonewline $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    chan close $f
    set f [open $path(test3) RDWR]
    set x [chan read $f 1]
    chan seek $f 3
    lappend x [chan read $f 1]
    chan seek $f 0 start
4399
4400
4401
4402
4403
4404
4405
4406

4407
4408
4409
4410

4411
4412
4413
4414
4415
4416
4417
4401
4402
4403
4404
4405
4406
4407

4408
4409
4410
4411

4412
4413
4414
4415
4416
4417
4418
4419







-
+



-
+







    chan seek $f 2
    set x [chan gets $f]
    chan close $f
    list $x [viewFile test3]
} "zzy xyzzy"
test chan-io-34.12 {Tcl_Seek testing combination of write, seek back and read} {
    set f [open $path(test3) w]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    chan puts $f xyz\n123
    chan close $f
    set f [open $path(test3) a+]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    chan puts $f xyzzy
    chan flush $f
    set x [chan tell $f]
    chan seek $f -4 cur
    set y [chan gets $f]
    chan close $f
    list $x [viewFile test3] $y
4426
4427
4428
4429
4430
4431
4432
4433

4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447

4448
4449
4450
4451
4452
4453
4454
4428
4429
4430
4431
4432
4433
4434

4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448

4449
4450
4451
4452
4453
4454
4455
4456







-
+













-
+







} -cleanup {
    chan close $f1
} -result 0
test chan-io-34.14 {Tcl_Tell after seek to end of file} -setup {
    file delete $path(test1)
} -body {
    set f1 [open $path(test1) w]
    chan configure $f1 -translation lf -eofchar {}
    chan configure $f1 -translation lf
    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
    chan close $f1
    set f1 [open $path(test1) r]
    chan seek $f1 0 end
    chan tell $f1
} -cleanup {
    chan close $f1
} -result 54
test chan-io-34.15 {Tcl_Tell combined with seeking} -setup {
    file delete $path(test1)
} -body {
    set f1 [open $path(test1) w]
    chan configure $f1 -translation lf -eofchar {}
    chan configure $f1 -translation lf
    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
    chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
    chan close $f1
    set f1 [open $path(test1) r]
    chan seek $f1 10 start
    set c1 [chan tell $f1]
    chan seek $f1 10 current
4471
4472
4473
4474
4475
4476
4477
4478

4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497

4498
4499
4500
4501
4502
4503
4504
4473
4474
4475
4476
4477
4478
4479

4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498

4499
4500
4501
4502
4503
4504
4505
4506







-
+


















-
+







    chan close $f1
    set c
} -1
test chan-io-34.18 {Tcl_Tell combined with seeking and reading} -setup {
    file delete $path(test2)
} -body {
    set f [open $path(test2) w]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    chan puts -nonewline $f "line1\nline2\nline3\nline4\nline5\n"
    chan close $f
    set f [open $path(test2)]
    chan configure $f -translation lf
    set x [chan tell $f]
    chan read $f 3
    lappend x [chan tell $f]
    chan seek $f 2
    lappend x [chan tell $f]
    chan seek $f 10 current
    lappend x [chan tell $f]
    chan seek $f 0 end
    lappend x [chan tell $f]
} -cleanup {
    chan close $f
} -result {0 3 2 12 30}
test chan-io-34.19 {Tcl_Tell combined with opening in append mode} -body {
    set f [open $path(test3) w]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    chan puts $f "abcdefghijklmnopqrstuvwxyz"
    chan puts $f "abcdefghijklmnopqrstuvwxyz"
    chan close $f
    set f [open $path(test3) a]
    chan tell $f
} -cleanup {
    chan close $f
4518
4519
4520
4521
4522
4523
4524
4525

4526
4527

4528
4529
4530
4531
4532
4533
4534
4520
4521
4522
4523
4524
4525
4526

4527
4528

4529
4530
4531
4532
4533
4534
4535
4536







-
+

-
+







    lappend l [chan tell $f]
} -cleanup {
    chan close $f
} -result {29 39 40 447}
test chan-io-34.21 {Tcl_Seek and Tcl_Tell on large files} -setup {
    file delete $path(test3)
    set l ""
} -constraints {largefileSupport} -body {
} -constraints {largefileSupport extensive} -body {
    set f [open $path(test3) w]
    chan configure $f -encoding binary
    chan configure $f -translation binary
    lappend l [chan tell $f]
    chan puts -nonewline $f abcdef
    lappend l [chan tell $f]
    chan flush $f
    lappend l [chan tell $f]
    # 4GB offset!
    chan seek $f 0x100000000
4633
4634
4635
4636
4637
4638
4639
4640

4641
4642
4643
4644
4645

4646
4647
4648
4649

4650
4651
4652
4653
4654

4655
4656
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

4688
4689
4690
4691

4692
4693
4694
4695
4696

4697
4698
4699
4700
4701

4702
4703
4704
4705

4706
4707
4708
4709
4710

4711
4712
4713
4714
4715

4716
4717
4718
4719

4720
4721
4722
4723
4724

4725
4726
4727
4728
4729

4730
4731
4732
4733
4734
4735
4736
4737
4738

4739
4740
4741
4742
4743

4744
4745
4746
4747
4748
4749
4750
4751
4752

4753
4754
4755
4756
4757

4758
4759
4760
4761
4762
4763
4764
4765
4766

4767
4768
4769
4770
4771

4772
4773
4774
4775
4776
4777
4778
4779
4780

4781
4782
4783
4784
4785

4786
4787
4788
4789
4790
4791
4792
4793
4794

4795
4796
4797
4798
4799

4800
4801
4802
4803
4804
4805
4806
4635
4636
4637
4638
4639
4640
4641

4642
4643
4644
4645
4646

4647
4648
4649
4650

4651
4652
4653
4654
4655

4656
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
4688

4689
4690
4691
4692

4693
4694
4695
4696
4697

4698
4699
4700
4701
4702

4703
4704
4705
4706

4707
4708
4709
4710
4711

4712
4713
4714
4715
4716

4717
4718
4719
4720

4721
4722
4723
4724
4725

4726
4727
4728
4729
4730

4731
4732
4733
4734
4735
4736
4737
4738
4739

4740
4741
4742
4743
4744

4745
4746
4747
4748
4749
4750
4751
4752
4753

4754
4755
4756
4757
4758

4759
4760
4761
4762
4763
4764
4765
4766
4767

4768
4769
4770
4771
4772

4773
4774
4775
4776
4777
4778
4779
4780
4781

4782
4783
4784
4785
4786

4787
4788
4789
4790
4791
4792
4793
4794
4795

4796
4797
4798
4799
4800

4801
4802
4803
4804
4805
4806
4807
4808







-
+




-
+



-
+




-
+




-
+



-
+




-
+




-
+



-
+




-
+




-
+



-
+




-
+




-
+



-
+




-
+




-
+



-
+




-
+




-
+








-
+




-
+








-
+




-
+








-
+




-
+








-
+




-
+








-
+




-
+







} -cleanup {
    chan close $f
} -result {{} 1}
test chan-io-35.6 {Tcl_Eof, eof char, lf write, auto read} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf -eofchar \x1a
    chan configure $f -translation lf -eofchar \x1A
    chan puts $f abc\ndef
    chan close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    chan configure $f -translation auto -eofchar \x1a
    chan configure $f -translation auto -eofchar \x1A
    list $s [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {9 8 1}
} -result {8 8 1}
test chan-io-35.7 {Tcl_Eof, eof char, lf write, lf read} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf -eofchar \x1a
    chan configure $f -translation lf -eofchar \x1A
    chan puts $f abc\ndef
    chan close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    chan configure $f -translation lf -eofchar \x1a
    chan configure $f -translation lf -eofchar \x1A
    list $s [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {9 8 1}
} -result {8 8 1}
test chan-io-35.8 {Tcl_Eof, eof char, cr write, auto read} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation cr -eofchar \x1a
    chan configure $f -translation cr -eofchar \x1A
    chan puts $f abc\ndef
    chan close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    chan configure $f -translation auto -eofchar \x1a
    chan configure $f -translation auto -eofchar \x1A
    list $s [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {9 8 1}
} -result {8 8 1}
test chan-io-35.9 {Tcl_Eof, eof char, cr write, cr read} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation cr -eofchar \x1a
    chan configure $f -translation cr -eofchar \x1A
    chan puts $f abc\ndef
    chan close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    chan configure $f -translation cr -eofchar \x1a
    chan configure $f -translation cr -eofchar \x1A
    list $s [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {9 8 1}
} -result {8 8 1}
test chan-io-35.10 {Tcl_Eof, eof char, crlf write, auto read} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation crlf -eofchar \x1a
    chan configure $f -translation crlf -eofchar \x1A
    chan puts $f abc\ndef
    chan close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    chan configure $f -translation auto -eofchar \x1a
    chan configure $f -translation auto -eofchar \x1A
    list $s [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {11 8 1}
} -result {10 8 1}
test chan-io-35.11 {Tcl_Eof, eof char, crlf write, crlf read} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation crlf -eofchar \x1a
    chan configure $f -translation crlf -eofchar \x1A
    chan puts $f abc\ndef
    chan close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    chan configure $f -translation crlf -eofchar \x1a
    chan configure $f -translation crlf -eofchar \x1A
    list $s [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {11 8 1}
} -result {10 8 1}
test chan-io-35.12 {Tcl_Eof, eof char in middle, lf write, auto read} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    chan puts $f [format abc\ndef\n%cqrs\nuvw 26]
    chan close $f
    set c [file size $path(test1)]
    set f [open $path(test1) r]
    chan configure $f -translation auto -eofchar \x1a
    chan configure $f -translation auto -eofchar \x1A
    list $c [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {17 8 1}
test chan-io-35.13 {Tcl_Eof, eof char in middle, lf write, lf read} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    chan puts $f [format abc\ndef\n%cqrs\nuvw 26]
    chan close $f
    set c [file size $path(test1)]
    set f [open $path(test1) r]
    chan configure $f -translation lf -eofchar \x1a
    chan configure $f -translation lf -eofchar \x1A
    list $c [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {17 8 1}
test chan-io-35.14 {Tcl_Eof, eof char in middle, cr write, auto read} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation cr -eofchar {}
    chan configure $f -translation cr
    chan puts $f [format abc\ndef\n%cqrs\nuvw 26]
    chan close $f
    set c [file size $path(test1)]
    set f [open $path(test1) r]
    chan configure $f -translation auto -eofchar \x1a
    chan configure $f -translation auto -eofchar \x1A
    list $c [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {17 8 1}
test chan-io-35.15 {Tcl_Eof, eof char in middle, cr write, cr read} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation cr -eofchar {}
    chan configure $f -translation cr
    chan puts $f [format abc\ndef\n%cqrs\nuvw 26]
    chan close $f
    set c [file size $path(test1)]
    set f [open $path(test1) r]
    chan configure $f -translation cr -eofchar \x1a
    chan configure $f -translation cr -eofchar \x1A
    list $c [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {17 8 1}
test chan-io-35.16 {Tcl_Eof, eof char in middle, crlf write, auto read} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation crlf -eofchar {}
    chan configure $f -translation crlf
    chan puts $f [format abc\ndef\n%cqrs\nuvw 26]
    chan close $f
    set c [file size $path(test1)]
    set f [open $path(test1) r]
    chan configure $f -translation auto -eofchar \x1a
    chan configure $f -translation auto -eofchar \x1A
    list $c [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {21 8 1}
test chan-io-35.17 {Tcl_Eof, eof char in middle, crlf write, crlf read} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -translation crlf -eofchar {}
    chan configure $f -translation crlf
    chan puts $f [format abc\ndef\n%cqrs\nuvw 26]
    chan close $f
    set c [file size $path(test1)]
    set f [open $path(test1) r]
    chan configure $f -translation crlf -eofchar \x1a
    chan configure $f -translation crlf -eofchar \x1A
    list $c [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {21 8 1}

# Test Tcl_InputBlocked

4965
4966
4967
4968
4969
4970
4971
4972

4973
4974
4975
4976
4977
4978
4979
4967
4968
4969
4970
4971
4972
4973

4974
4975
4976
4977
4978
4979
4980
4981







-
+







    lappend l [chan configure $f -buffersize]
} -cleanup {
    chan close $f
} -result {4096 10000 1 1 1 100000 1048576}
test chan-io-38.3 {Tcl_SetChannelBufferSize, changing buffersize between reads} {
    # This test crashes the interp if Bug #427196 is not fixed
    set chan [open [info script] r]
    chan configure $chan -buffersize 10
    chan configure $chan -buffersize 10 -encoding utf-8
    set var [chan read $chan 2]
    chan configure $chan -buffersize 32
    append var [chan read $chan]
    chan close $chan
} {}

# Test Tcl_SetChannelOption, Tcl_GetChannelOption
5061
5062
5063
5064
5065
5066
5067
5068

5069
5070
5071
5072
5073
5074
5075
5063
5064
5065
5066
5067
5068
5069

5070
5071
5072
5073
5074
5075
5076
5077







-
+







    chan close $f1
} -result {0 21}
test chan-io-39.8 {Tcl_SetChannelOption, different buffering options} -setup {
    file delete $path(test1)
    set l ""
} -body {
    set f1 [open $path(test1) w]
    chan configure $f1 -translation lf -buffering none -eofchar {}
    chan configure $f1 -translation lf -buffering none
    chan puts -nonewline $f1 hello
    lappend l [file size $path(test1)]
    chan puts -nonewline $f1 hello
    lappend l [file size $path(test1)]
    chan configure $f1 -buffering full
    chan puts -nonewline $f1 hello
    lappend l [file size $path(test1)]
5161
5162
5163
5164
5165
5166
5167
5168
5169


5170
5171
5172
5173
5174
5175
5176

5177
5178
5179
5180
5181
5182


5183
5184
5185
5186
5187
5188
5189

5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203


5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214

5215
5216
5217
5218
5219
5220
5221

5222
5223
5224
5225
5226
5227
5228
5163
5164
5165
5166
5167
5168
5169


5170
5171
5172
5173
5174
5175
5176
5177

5178
5179
5180
5181
5182


5183
5184
5185
5186
5187
5188
5189
5190

5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203


5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215

5216
5217
5218
5219
5220
5221
5222

5223
5224
5225
5226
5227
5228
5229
5230







-
-
+
+






-
+




-
-
+
+






-
+












-
-
+
+










-
+






-
+







} -cleanup {
    chan close $f
} -result 40000
test chan-io-39.14 {Tcl_SetChannelOption: -encoding, binary & utf-8} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -encoding {}
    chan puts -nonewline $f \xe7\x89\xa6
    chan configure $f -translation binary
    chan puts -nonewline $f \xE7\x89\xA6
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -encoding utf-8
    chan read $f
} -cleanup {
    chan close $f
} -result \u7266
} -result 牦
test chan-io-39.15 {Tcl_SetChannelOption: -encoding, binary & utf-8} -setup {
    file delete $path(test1)
} -body {
    set f [open $path(test1) w]
    chan configure $f -encoding binary
    chan puts -nonewline $f \xe7\x89\xa6
    chan configure $f -translation binary
    chan puts -nonewline $f \xE7\x89\xA6
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -encoding utf-8
    chan read $f
} -cleanup {
    chan close $f
} -result \u7266
} -result 牦
test chan-io-39.16 {Tcl_SetChannelOption: -encoding, errors} -setup {
    file delete $path(test1)
    set f [open $path(test1) w]
} -body {
    chan configure $f -encoding foobar
} -returnCodes error -cleanup {
    chan close $f
} -result {unknown encoding "foobar"}
test chan-io-39.17 {Tcl_SetChannelOption: -encoding, clearing CHANNEL_NEED_MORE_DATA} -setup {
    variable x {}
} -constraints {stdio fileevent} -body {
    set f [openpipe r+ $path(cat)]
    chan configure $f -encoding binary
    chan puts -nonewline $f "\xe7"
    chan configure $f -encoding iso8859-1
    chan puts -nonewline $f \xE7
    chan flush $f
    chan configure $f -encoding utf-8 -blocking 0
    chan event $f readable [namespace code { lappend x [chan read $f] }]
    vwait [namespace which -variable x]
    after 300 [namespace code { lappend x timeout }]
    vwait [namespace which -variable x]
    chan configure $f -encoding utf-8
    vwait [namespace which -variable x]
    after 300 [namespace code { lappend x timeout }]
    vwait [namespace which -variable x]
    chan configure $f -encoding binary
    chan configure $f -encoding iso8859-1
    vwait [namespace which -variable x]
    after 300 [namespace code { lappend x timeout }]
    vwait [namespace which -variable x]
    return $x
} -cleanup {
    chan close $f
} -result "{} timeout {} timeout \xe7 timeout"
} -result "{} timeout {} timeout \xE7 timeout"
test chan-io-39.18 {Tcl_SetChannelOption, setting read mode independently} \
	-constraints {socket} -body {
    proc accept {s a p} {chan close $s}
    set s1 [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
    set port [lindex [chan configure $s1 -sockname] 2]
    set s2 [socket 127.0.0.1 $port]
    update
5270
5271
5272
5273
5274
5275
5276
5277

5278
5279
5280

5281
5282
5283
5284
5285
5286
5287


5288
5289
5290
5291
5292

5293
5294
5295
5296
5297
5298
5299
5300
5301





5302
5303
5304
5305
5306
5307
5308
5309

5310
5311

5312
5313
5314
5315
5316
5317
5318
5319
5320

5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341


5342
5343

5344
5345
5346
5347
5348
5349
5350
5351
5352
5353

5354
5355
5356
5357
5358


5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380

5381
5382
5383
5384
5385
5386
5387
5272
5273
5274
5275
5276
5277
5278

5279
5280
5281

5282
5283
5284
5285
5286
5287


5288
5289
5290
5291
5292
5293

5294
5295
5296
5297
5298
5299
5300



5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312

5313
5314

5315
5316
5317
5318
5319
5320
5321
5322
5323

5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343


5344
5345
5346

5347
5348
5349
5350
5351
5352
5353
5354
5355
5356

5357
5358
5359
5360


5361
5362
5363
5364
5365
5366

5367
5368
5369

5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381

5382
5383
5384
5385
5386
5387
5388
5389







-
+


-
+





-
-
+
+




-
+






-
-
-
+
+
+
+
+







-
+

-
+








-
+



















-
-
+
+

-
+









-
+



-
-
+
+




-



-












-
+







} -cleanup {
    chan close $s1
    chan close $s2
} -result {auto crlf}
test chan-io-39.22 {Tcl_SetChannelOption, invariance} -setup {
    file delete $path(test1)
    set l ""
} -constraints {unix} -body {
} -constraints {unix deprecated} -body {
    set f1 [open $path(test1) w+]
    lappend l [chan configure $f1 -eofchar]
    chan configure $f1 -eofchar {ON GO}
    chan configure $f1 -eofchar {O {}}
    lappend l [chan configure $f1 -eofchar]
    chan configure $f1 -eofchar D
    lappend l [chan configure $f1 -eofchar]
} -cleanup {
    chan close $f1
} -result {{{} {}} {O G} {D D}}
test chan-io-39.22a {Tcl_SetChannelOption, invariance} -setup {
} -result {{} O D}
test chan-io-39.22a {Tcl_SetChannelOption, invariance} -constraints deprecated -setup {
    file delete $path(test1)
    set l [list]
} -body {
    set f1 [open $path(test1) w+]
    chan configure $f1 -eofchar {ON GO}
    chan configure $f1 -eofchar {O {}}
    lappend l [chan configure $f1 -eofchar]
    chan configure $f1 -eofchar D
    lappend l [chan configure $f1 -eofchar]
    lappend l [list [catch {chan configure $f1 -eofchar {1 2 3}} msg] $msg]
} -cleanup {
    chan close $f1
} -result {{O G} {D D} {1 {bad value for -eofchar: should be a list of zero, one, or two elements}}}
test chan-io-39.23 {Tcl_GetChannelOption, server socket is not readable or\
        writeable, it should still have valid -eofchar and -translation options} -setup {
} -result {O D {1 {bad value for -eofchar: must be non-NUL ASCII character}}}
test chan-io-39.23 {
	Tcl_GetChannelOption, server socket is not readable or writable, but should
	still have valid -eofchar and -translation options.
} -setup {
    set l [list]
} -body {
    set sock [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
    lappend l [chan configure $sock -eofchar] \
	[chan configure $sock -translation]
} -cleanup {
    chan close $sock
} -result {{{}} auto}
} -result {{} auto}
test chan-io-39.24 {Tcl_SetChannelOption, server socket is not readable or\
        writable so we can't change -eofchar or -translation} -setup {
	writable so we can't change -eofchar or -translation} -setup {
    set l [list]
} -body {
    set sock [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
    chan configure $sock -eofchar D -translation lf
    lappend l [chan configure $sock -eofchar] \
	[chan configure $sock -translation]
} -cleanup {
    chan close $sock
} -result {{{}} auto}
} -result {{} auto}

test chan-io-40.1 {POSIX open access modes: RDWR} -setup {
    file delete $path(test3)
} -body {
    set f [open $path(test3) w]
    chan puts $f xyzzy
    chan close $f
    set f [open $path(test3) RDWR]
    chan puts -nonewline $f "ab"
    chan seek $f 0 current
    set x [chan gets $f]
    chan close $f
    set f [open $path(test3) r]
    lappend x [chan gets $f]
} -cleanup {
    chan close $f
} -result {zzy abzzy}
test chan-io-40.2 {POSIX open access modes: CREAT} -setup {
    file delete $path(test3)
} -constraints {unix} -body {
    set f [open $path(test3) {WRONLY CREAT} 0600]
} -constraints {unix notWsl} -body {
    set f [open $path(test3) {WRONLY CREAT} 0o600]
    file stat $path(test3) stats
    set x [format "%#o" [expr $stats(mode)&0o777]]
    set x [format 0o%03o [expr {$stats(mode) & 0o777}]]
    chan puts $f "line 1"
    chan close $f
    set f [open $path(test3) r]
    lappend x [chan gets $f]
} -cleanup {
    chan close $f
} -result {0o600 {line 1}}
test chan-io-40.3 {POSIX open access modes: CREAT} -setup {
    file delete $path(test3)
} -constraints {unix umask} -body {
} -constraints {unix umask notWsl} -body {
    # This test only works if your umask is 2, like ouster's.
    chan close [open $path(test3) {WRONLY CREAT}]
    file stat $path(test3) stats
    format "%#o" [expr $stats(mode)&0o777]
} -result [format %#5o [expr {0o666 & ~ $umaskValue}]]
    format 0o%03o [expr {$stats(mode) & 0o777}]
} -result [format 0o%03o [expr {0o666 & ~ $umaskValue}]]
test chan-io-40.4 {POSIX open access modes: CREAT} -setup {
    file delete $path(test3)
} -body {
    set f [open $path(test3) w]
    chan configure $f -eofchar {}
    chan puts $f xyzzy
    chan close $f
    set f [open $path(test3) {WRONLY CREAT}]
    chan configure $f -eofchar {}
    chan puts -nonewline $f "ab"
    chan close $f
    set f [open $path(test3) r]
    chan gets $f
} -cleanup {
    chan close $f
} -result abzzy
test chan-io-40.5 {POSIX open access modes: APPEND} -setup {
    file delete $path(test3)
    set x ""
} -body {
    set f [open $path(test3) w]
    chan configure $f -translation lf -eofchar {}
    chan configure $f -translation lf
    chan puts $f xyzzy
    chan close $f
    set f [open $path(test3) {WRONLY APPEND}]
    chan configure $f -translation lf
    chan puts $f "new line"
    chan seek $f 0
    chan puts $f "abc"
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5404
5405
5406
5407
5408
5409
5410

5411
5412
5413
5414
5415
5416
5417







-







    chan close $f
    open $path(test3) {WRONLY CREAT EXCL}
} -returnCodes error -result {(?i)couldn't open ".*test3": file (already )?exists}
test chan-io-40.7 {POSIX open access modes: EXCL} -setup {
    file delete $path(test3)
} -body {
    set f [open $path(test3) {WRONLY CREAT EXCL}]
    chan configure $f -eofchar {}
    chan puts $f "A test line"
    chan close $f
    viewFile test3
} -result {A test line}
test chan-io-40.8 {POSIX open access modes: TRUNC} -setup {
    file delete $path(test3)
} -body {
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481



5482

5483

5484
5485


5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498

5499
5500
5501

5502
5503
5504
5505
5506
5507
5508
5509
5510
5511






















































5512
5513
5514
5515
5516
5517
5518
5454
5455
5456
5457
5458
5459
5460

5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479


5480
5481
5482
5483
5484

5485
5486

5487
5488
5489








5490
5491
5492

5493
5494
5495

5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567







-



















-
-
+
+
+

+
-
+

-
+
+

-
-
-
-
-
-
-
-



-
+


-
+










+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







test chan-io-40.12 {POSIX open access modes: WRONLY} -match regexp -body {
    file delete $path(test3)
    open $path(test3) WRONLY
} -returnCodes error -result {(?i)couldn't open ".*test3": no such file or directory}
test chan-io-40.13 {POSIX open access modes: WRONLY} -body {
    makeFile xyzzy test3
    set f [open $path(test3) WRONLY]
    chan configure $f -eofchar {}
    chan puts -nonewline $f "ab"
    chan seek $f 0 current
    set x [list [catch {chan gets $f} msg] $msg]
    chan close $f
    lappend x [viewFile test3]
} -match glob -result {1 {channel "*" wasn't opened for reading} abzzy}
test chan-io-40.14 {POSIX open access modes: RDWR} -match regexp -body {
    file delete $path(test3)
    open $path(test3) RDWR
} -returnCodes error -result {(?i)couldn't open ".*test3": no such file or directory}
test chan-io-40.15 {POSIX open access modes: RDWR} {
    makeFile xyzzy test3
    set f [open $path(test3) RDWR]
    chan puts -nonewline $f "ab"
    chan seek $f 0 current
    set x [chan gets $f]
    chan close $f
    lappend x [viewFile test3]
} {zzy abzzy}
test chan-io-40.16 {tilde substitution in open} -constraints makeFileInHome -setup {
    makeFile {Some text} _test_ ~
test chan-io-40.16 {verify no tilde substitution in open} -setup {
    set curdir [pwd]
    cd [temporaryDirectory]
} -body {
    close [open ~ w]
    file exists [file join $::env(HOME) _test_]
    list [file isfile ~]
} -cleanup {
    removeFile _test_ ~
    file delete ./~ ;# ./ because don't want to delete home in case of bugs!
    cd $curdir
} -result 1
test chan-io-40.17 {tilde substitution in open} -setup {
    set home $::env(HOME)
} -body {
    unset ::env(HOME)
    open ~/foo
} -returnCodes error -cleanup {
    set ::env(HOME) $home
} -result {couldn't find HOME environment variable to expand path}

test chan-io-41.1 {Tcl_FileeventCmd: errors} -constraints fileevent -body {
    chan event foo
} -returnCodes error -result {wrong # args: should be "chan event channelId event ?script?"}
} -returnCodes error -result {wrong # args: should be "chan event channel event ?script?"}
test chan-io-41.2 {Tcl_FileeventCmd: errors} -constraints fileevent -body {
    chan event foo bar baz q
} -returnCodes error -result {wrong # args: should be "chan event channelId event ?script?"}
} -returnCodes error -result {wrong # args: should be "chan event channel event ?script?"}
test chan-io-41.3 {Tcl_FileeventCmd: errors} -constraints fileevent -body {
    chan event gorp readable
} -returnCodes error -result {can not find channel named "gorp"}
test chan-io-41.4 {Tcl_FileeventCmd: errors} -constraints fileevent -body {
    chan event gorp writable
} -returnCodes error -result {can not find channel named "gorp"}
test chan-io-41.5 {Tcl_FileeventCmd: errors} -constraints fileevent -body {
    chan event gorp who-knows
} -returnCodes error -result {bad event name "who-knows": must be readable or writable}


test chan-io-41.6 {Tcl_FileeventCmd: directory} -constraints {fileevent unix} -setup {
    set tempdir [::tcltests::tempdir]
} -body {
    set chan [open $tempdir]
    chan event $chan readable [list ::apply [list {} {
	variable success
	set success 1
    } [namespace current]]]
    vwait [namespace current]::success
    return $success
} -cleanup {
    close $chan
    file delete -force tempdir
} -result 1


test chan-io-41.7 {Tcl_FileeventCmd: special} -constraints {
    fileevent specialfiles
} -body {
    set special /dev/zero
    if {![file exists $special]} {
	set special NUL
    }
    set chan [open $special]
    chan event $chan readable [list ::apply [list {} {
	variable success
	set success 1
    } [namespace current]]]
    vwait [namespace current]::success
    return $success
} -cleanup {
    close $chan
} -result 1


test chan-io-41.8 {Tcl_FileeventCmd: symbolic link} -constraints {fileevent unix} -setup {
    set tempdir [::tcltests::tempdir]
} -body {
    set target [makeFile {not again} thefile $tempdir]
    set link [file join $tempdir thelin]
    file link -symbolic $link $target
    set chan [open $link]
    chan event $chan readable [list ::apply [list {} {
	variable success
	set success 1
    } [namespace current]]]
    vwait [namespace current]::success
    return $success
} -cleanup {
    close $chan
    file delete -force $tempdir
} -result 1

#
# Test chan event on a file
#

set path(foo) [makeFile {} foo]
set f [open $path(foo) w+]

5528
5529
5530
5531
5532
5533
5534
5535

5536
5537

5538
5539

5540
5541
5542
5543
5544
5545
5546
5577
5578
5579
5580
5581
5582
5583

5584
5585

5586
5587

5588
5589
5590
5591
5592
5593
5594
5595







-
+

-
+

-
+







    chan event $f r "yet another"
    lappend result [chan event $f readable]
    chan event $f r ""
    lappend result [chan event $f readable]
} {{first script} {new script} {yet another} {}}
test chan-io-42.3 {Tcl_FileeventCmd: replacing, with NULL chars in script} {fileevent} {
    set result {}
    chan event $f r "first scr\0ipt"
    chan event $f r "first scr\x00ipt"
    lappend result [string length [chan event $f readable]]
    chan event $f r "new scr\0ipt"
    chan event $f r "new scr\x00ipt"
    lappend result [string length [chan event $f readable]]
    chan event $f r "yet ano\0ther"
    chan event $f r "yet ano\x00ther"
    lappend result [string length [chan event $f readable]]
    chan event $f r ""
    lappend result [chan event $f readable]
} {13 11 12 {}}

test chan-io-43.1 {Tcl_FileeventCmd: creating, deleting, querying} {stdio unixExecs fileevent} {
    set result {}
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752




5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765








5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783

5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800

5801
5802
5803
5804
5805
5806
5807
5791
5792
5793
5794
5795
5796
5797




5798
5799
5800
5801
5802
5803
5804
5805
5806








5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831

5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848

5849
5850
5851
5852
5853
5854
5855
5856







-
-
-
-
+
+
+
+





-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

















-
+
















-
+







    after cancel $timer
    testfevent cmd {chan close $f}
    list [testfevent cmd {set x}] [testfevent cmd {info commands after}]
} {{f triggered: foo bar} after}
test chan-io-46.2 {Tcl event loop vs multiple interpreters} testfevent {
    testfevent create
    testfevent cmd {
        variable x 0
        after 100 {set x triggered}
        vwait [namespace which -variable x]
        set x
	variable x 0
	after 100 {set x triggered}
	vwait [namespace which -variable x]
	set x
    }
} {triggered}
test chan-io-46.3 {Tcl event loop vs multiple interpreters} testfevent {
    testfevent create
    testfevent cmd {
        set x 0
        after 10 {lappend x timer}
        after 30
        set result $x
        update idletasks
        lappend result $x
        update
        lappend result $x
	set x 0
	after 10 {lappend x timer}
	after 30
	set result $x
	update idletasks
	lappend result $x
	update
	lappend result $x
    }
} {0 0 {0 timer}}

test chan-io-47.1 {chan event vs multiple interpreters} -setup {
    set f  [open $path(foo) r]
    set f2 [open $path(foo) r]
    set f3 [open $path(foo) r]
    set x {}
} -constraints {testfevent fileevent} -body {
    chan event $f readable {script 1}
    testfevent create
    testfevent share $f2
    testfevent cmd "chan event $f2 readable {script 2}"
    chan event $f3 readable {sript 3}
    lappend x [chan event $f2 readable]
    testfevent delete
    lappend x [chan event $f readable] [chan event $f2 readable] \
        [chan event $f3 readable]
	[chan event $f3 readable]
} -cleanup {
    chan close $f
    chan close $f2
    chan close $f3
} -result {{} {script 1} {} {sript 3}}
test chan-io-47.2 {deleting chan event on interpreter delete} -setup {
    set f  [open $path(foo) r]
    set f2 [open $path(foo) r]
    set f3 [open $path(foo) r]
    set f4 [open $path(foo) r]
} -constraints {testfevent fileevent} -body {
    chan event $f readable {script 1}
    testfevent create
    testfevent share $f2
    testfevent share $f3
    testfevent cmd "chan event $f2 readable {script 2}
        chan event $f3 readable {script 3}"
	chan event $f3 readable {script 3}"
    chan event $f4 readable {script 4}
    testfevent delete
    list [chan event $f readable] [chan event $f2 readable] \
	[chan event $f3 readable] [chan event $f4 readable]
} -cleanup {
    chan close $f
    chan close $f2
5978
5979
5980
5981
5982
5983
5984
5985

5986
5987
5988
5989
5990
5991
5992
6027
6028
6029
6030
6031
6032
6033

6034
6035
6036
6037
6038
6039
6040
6041







-
+







    set l ""
} -constraints {fileevent} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f [format "abc\ndef\n%c" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation auto -eofchar \x1a
    chan configure $f -translation auto -eofchar \x1A
    chan event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c
6002
6003
6004
6005
6006
6007
6008
6009

6010
6011
6012
6013
6014
6015
6016
6051
6052
6053
6054
6055
6056
6057

6058
6059
6060
6061
6062
6063
6064
6065







-
+







    set l ""
} -constraints {fileevent} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f [format "abc\ndef\n%cfoo\nbar\n" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -eofchar \x1a -translation auto
    chan configure $f -translation auto -eofchar \x1A
    chan event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c
6026
6027
6028
6029
6030
6031
6032
6033

6034
6035
6036
6037
6038
6039
6040
6075
6076
6077
6078
6079
6080
6081

6082
6083
6084
6085
6086
6087
6088
6089







-
+







    set l ""
} -constraints {fileevent} -body {
    set f [open $path(test1) w]
    chan configure $f -translation cr
    chan puts -nonewline $f [format "abc\ndef\n%c" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation auto -eofchar \x1a
    chan configure $f -translation auto -eofchar \x1A
    chan event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c
6050
6051
6052
6053
6054
6055
6056
6057

6058
6059
6060
6061
6062
6063
6064
6099
6100
6101
6102
6103
6104
6105

6106
6107
6108
6109
6110
6111
6112
6113







-
+







    set l ""
} -constraints {fileevent} -body {
    set f [open $path(test1) w]
    chan configure $f -translation cr
    chan puts -nonewline $f [format "abc\ndef\n%cfoo\nbar\n" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -eofchar \x1a -translation auto
    chan configure $f -translation auto -eofchar \x1A
    chan event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c
6074
6075
6076
6077
6078
6079
6080
6081

6082
6083
6084
6085
6086
6087
6088
6123
6124
6125
6126
6127
6128
6129

6130
6131
6132
6133
6134
6135
6136
6137







-
+







    set l ""
} -constraints {fileevent} -body {
    set f [open $path(test1) w]
    chan configure $f -translation crlf
    chan puts -nonewline $f [format "abc\ndef\n%c" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation auto -eofchar \x1a
    chan configure $f -translation auto -eofchar \x1A
    chan event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c
6098
6099
6100
6101
6102
6103
6104
6105

6106
6107
6108
6109
6110
6111
6112
6147
6148
6149
6150
6151
6152
6153

6154
6155
6156
6157
6158
6159
6160
6161







-
+







    set l ""
} -constraints {fileevent} -body {
    set f [open $path(test1) w]
    chan configure $f -translation crlf
    chan puts -nonewline $f [format "abc\ndef\n%cfoo\nbar\n" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -eofchar \x1a -translation auto
    chan configure $f -translation auto -eofchar \x1A
    chan event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c
6122
6123
6124
6125
6126
6127
6128
6129

6130
6131
6132
6133
6134
6135
6136
6171
6172
6173
6174
6175
6176
6177

6178
6179
6180
6181
6182
6183
6184
6185







-
+







    set l ""
} -constraints {fileevent} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f [format "abc\ndef\n%cfoo\nbar\n" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -eofchar \x1a -translation lf
    chan configure $f -translation lf -eofchar \x1A
    chan event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c
6146
6147
6148
6149
6150
6151
6152
6153

6154
6155
6156
6157
6158
6159
6160
6195
6196
6197
6198
6199
6200
6201

6202
6203
6204
6205
6206
6207
6208
6209







-
+







    set l ""
} -constraints {fileevent} -body {
    set f [open $path(test1) w]
    chan configure $f -translation lf
    chan puts -nonewline $f [format "abc\ndef\n%c" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation lf -eofchar \x1a
    chan configure $f -translation lf -eofchar \x1A
    chan event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c
6170
6171
6172
6173
6174
6175
6176
6177

6178
6179
6180
6181
6182
6183
6184
6219
6220
6221
6222
6223
6224
6225

6226
6227
6228
6229
6230
6231
6232
6233







-
+







    set l ""
} -constraints {fileevent} -body {
    set f [open $path(test1) w]
    chan configure $f -translation cr
    chan puts -nonewline $f [format "abc\ndef\n%cfoo\nbar\n" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -eofchar \x1a -translation cr
    chan configure $f -translation cr -eofchar \x1A
    chan event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c
6194
6195
6196
6197
6198
6199
6200
6201

6202
6203
6204
6205
6206
6207
6208
6243
6244
6245
6246
6247
6248
6249

6250
6251
6252
6253
6254
6255
6256
6257







-
+







    set l ""
} -constraints {fileevent} -body {
    set f [open $path(test1) w]
    chan configure $f -translation cr
    chan puts -nonewline $f [format "abc\ndef\n%c" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation cr -eofchar \x1a
    chan configure $f -translation cr -eofchar \x1A
    chan event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c
6218
6219
6220
6221
6222
6223
6224
6225

6226
6227
6228
6229
6230
6231
6232
6267
6268
6269
6270
6271
6272
6273

6274
6275
6276
6277
6278
6279
6280
6281







-
+







    set l ""
} -constraints {fileevent} -body {
    set f [open $path(test1) w]
    chan configure $f -translation crlf
    chan puts -nonewline $f [format "abc\ndef\n%cfoo\nbar\n" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -eofchar \x1a -translation crlf
    chan configure $f -translation crlf -eofchar \x1A
    chan event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c
6242
6243
6244
6245
6246
6247
6248
6249

6250
6251
6252
6253
6254
6255
6256
6291
6292
6293
6294
6295
6296
6297

6298
6299
6300
6301
6302
6303
6304
6305







-
+







    set l ""
} -constraints {fileevent} -body {
    set f [open $path(test1) w]
    chan configure $f -translation crlf
    chan puts -nonewline $f [format "abc\ndef\n%c" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation crlf -eofchar \x1a
    chan configure $f -translation crlf -eofchar \x1A
    chan event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c
6497
6498
6499
6500
6501
6502
6503
6504

6505
6506
6507

6508
6509
6510
6511
6512
6513
6514
6546
6547
6548
6549
6550
6551
6552

6553
6554
6555

6556
6557
6558
6559
6560
6561
6562
6563







-
+


-
+







	    testchannelevent $f delete 0
	    lappend z "del deleted notcalled"
	    lappend z "del deleted myself"
	} else {
	    set u recursive
	    lappend z "del calling recursive"
	    set timer [after 50 lappend z timeout]
	    set mode [test servicemode 1]
	    set mode [testservicemode 1]
	    vwait z
	    after cancel $timer
	    test servicemode $mode
	    testservicemode $mode
	    lappend z "del after update"
	}
    }
    set z ""
    set u toplevel
    set timer [after 50 lappend z timeout]
    testservicemode 0
6636
6637
6638
6639
6640
6641
6642
6643
6644


6645
6646
6647
6648
6649
6650
6651
6652

6653
6654
6655
6656
6657
6658
6659
6685
6686
6687
6688
6689
6690
6691


6692
6693
6694
6695
6696
6697
6698
6699
6700

6701
6702
6703
6704
6705
6706
6707
6708







-
-
+
+







-
+







    chan close $f3
} -match glob -result {channel "*" is busy}
test chan-io-52.3 {TclCopyChannel} -constraints {fcopy} -setup {
    file delete $path(test1)
} -body {
    set f1 [open $thisScript]
    set f2 [open $path(test1) w]
    chan configure $f1 -translation lf -blocking 0
    chan configure $f2 -translation cr -blocking 0
    chan configure $f1 -translation lf -encoding iso8859-1 -blocking 0
    chan configure $f2 -translation cr -encoding iso8859-1 -blocking 0
    set s0 [chan copy $f1 $f2]
    set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
    chan close $f1
    chan close $f2
    set s1 [file size $thisScript]
    set s2 [file size $path(test1)]
    if {($s1 == $s2) && ($s0 == $s1)} {
        lappend result ok
	lappend result ok
    }
    return $result
} -result {0 0 ok}
test chan-io-52.4 {TclCopyChannel} -constraints {fcopy} -setup {
    file delete $path(test1)
} -body {
    set f1 [open $thisScript]
6667
6668
6669
6670
6671
6672
6673
6674
6675


6676
6677
6678
6679
6680
6681

6682
6683
6684
6685
6686
6687
6688
6689
6690
6691


6692
6693
6694
6695
6696
6697

6698
6699
6700
6701
6702
6703
6704
6705
6706
6707


6708
6709
6710
6711
6712
6713

6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724



6725
6726
6727
6728
6729
6730
6731

6732
6733
6734
6735
6736
6737
6738
6739
6740
6741


6742
6743
6744
6745

6746
6747
6748
6749
6750
6751
6752
6716
6717
6718
6719
6720
6721
6722


6723
6724
6725
6726
6727
6728
6729

6730
6731
6732
6733
6734
6735
6736
6737
6738


6739
6740
6741
6742
6743
6744
6745

6746
6747
6748
6749
6750
6751
6752
6753
6754


6755
6756
6757
6758
6759
6760
6761

6762
6763
6764
6765
6766
6767
6768
6769
6770



6771
6772
6773
6774
6775
6776
6777
6778
6779

6780
6781
6782
6783
6784
6785
6786
6787
6788


6789
6790
6791
6792
6793

6794
6795
6796
6797
6798
6799
6800
6801







-
-
+
+





-
+








-
-
+
+





-
+








-
-
+
+





-
+








-
-
-
+
+
+






-
+








-
-
+
+



-
+







    lappend result [file size $path(test1)]
} -result {0 0 40}
test chan-io-52.5 {TclCopyChannel, all} -constraints {fcopy} -setup {
    file delete $path(test1)
} -body {
    set f1 [open $thisScript]
    set f2 [open $path(test1) w]
    chan configure $f1 -translation lf -blocking 0
    chan configure $f2 -translation lf -blocking 0
    chan configure $f1 -translation binary -blocking 0
    chan configure $f2 -translation binary -blocking 0
    chan copy $f1 $f2 -size -1 ;# -1 means 'copy all', same as if no -size specified.
    set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
    chan close $f1
    chan close $f2
    if {[file size $thisScript] == [file size $path(test1)]} {
        lappend result ok
	lappend result ok
    }
    return $result
} -result {0 0 ok}
test chan-io-52.5a {TclCopyChannel, all, other negative value} -setup {
    file delete $path(test1)
} -constraints {fcopy} -body {
    set f1 [open $thisScript]
    set f2 [open $path(test1) w]
    chan configure $f1 -translation lf -blocking 0
    chan configure $f2 -translation lf -blocking 0
    chan configure $f1 -translation binary -blocking 0
    chan configure $f2 -translation binary -blocking 0
    chan copy $f1 $f2 -size -2 ;# < 0 behaves like -1, copy all
    set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
    chan close $f1
    chan close $f2
    if {[file size $thisScript] == [file size $path(test1)]} {
        lappend result ok
	lappend result ok
    }
    return $result
} -result {0 0 ok}
test chan-io-52.5b {TclCopyChannel, all, wrap to negative value} -setup {
    file delete $path(test1)
} -constraints {fcopy} -body {
    set f1 [open $thisScript]
    set f2 [open $path(test1) w]
    chan configure $f1 -translation lf -blocking 0
    chan configure $f2 -translation lf -blocking 0
    chan configure $f1 -translation binary -blocking 0
    chan configure $f2 -translation binary -blocking 0
    chan copy $f1 $f2 -size 3221176172 ;# Wrapped to < 0, behaves like -1, copy all
    set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
    chan close $f1
    chan close $f2
    if {[file size $thisScript] ==  [file size $path(test1)]} {
        lappend result ok
	lappend result ok
    }
    return $result
} -result {0 0 ok}
test chan-io-52.6 {TclCopyChannel} -setup {
    file delete $path(test1)
} -constraints {fcopy} -body {
    set f1 [open $thisScript]
    set f2 [open $path(test1) w]
    chan configure $f1 -translation lf -blocking 0
    chan configure $f2 -translation lf -blocking 0
    set s0 [chan copy $f1 $f2 -size [expr [file size $thisScript] + 5]]
    chan configure $f1 -translation binary -blocking 0
    chan configure $f2 -translation binary -blocking 0
    set s0 [chan copy $f1 $f2 -size [expr {[file size $thisScript] + 5}]]
    set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
    chan close $f1
    chan close $f2
    set s1 [file size $thisScript]
    set s2 [file size $path(test1)]
    if {($s1 == $s2) && ($s0 == $s1)} {
        lappend result ok
	lappend result ok
    }
    return $result
} -result {0 0 ok}
test chan-io-52.7 {TclCopyChannel} -constraints {fcopy} -setup {
    file delete $path(test1)
} -body {
    set f1 [open $thisScript]
    set f2 [open $path(test1) w]
    chan configure $f1 -translation lf -blocking 0
    chan configure $f2 -translation lf -blocking 0
    chan configure $f1 -translation binary -blocking 0
    chan configure $f2 -translation binary -blocking 0
    chan copy $f1 $f2
    set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
    if {[file size $thisScript] == [file size $path(test1)]} {
        lappend result ok
	lappend result ok
    }
    return $result
} -cleanup {
    chan close $f1
    chan close $f2
} -result {0 0 ok}
test chan-io-52.8 {TclCopyChannel} -setup {
6779
6780
6781
6782
6783
6784
6785
6786

6787
6788
6789
6790
6791
6792
6793
6828
6829
6830
6831
6832
6833
6834

6835
6836
6837
6838
6839
6840
6841
6842







-
+







# Empty files, to register them with the test facility
set path(kyrillic.txt)   [makeFile {} kyrillic.txt]
set path(utf8-fcopy.txt) [makeFile {} utf8-fcopy.txt]
set path(utf8-rp.txt)    [makeFile {} utf8-rp.txt]
# Create kyrillic file, use lf translation to avoid os eol issues
set out [open $path(kyrillic.txt) w]
chan configure $out -encoding koi8-r -translation lf
chan puts       $out "\u0410\u0410"
chan puts       $out ÐÐ
chan close      $out
test chan-io-52.9 {TclCopyChannel & encodings} {fcopy} {
    # Copy kyrillic to UTF-8, using chan copy.
    set in  [open $path(kyrillic.txt) r]
    set out [open $path(utf8-fcopy.txt) w]
    chan configure $in  -encoding koi8-r -translation lf
    chan configure $out -encoding utf-8 -translation lf
6802
6803
6804
6805
6806
6807
6808
6809

6810
6811
6812
6813
6814
6815
6816


6817
6818
6819
6820



6821
6822
6823
6824

6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836









6837
6838




6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859


6860
6861
6862
6863
6864
6865
6866
6867
6868
6869

6870
6871
6872
6873
6874
6875
6876
6851
6852
6853
6854
6855
6856
6857

6858

6859
6860
6861

6862
6863
6864
6865
6866
6867


6868
6869
6870
6871
6872
6873

6874
6875
6876


6877
6878

6879




6880
6881
6882
6883
6884
6885
6886
6887
6888


6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911


6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922

6923
6924
6925
6926
6927
6928
6929
6930







-
+
-



-


+
+


-
-
+
+
+



-
+


-
-


-

-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+



















-
-
+
+









-
+







    chan puts -nonewline $out [chan read $in]
    chan close $in
    chan close $out
    list [file size $path(kyrillic.txt)] \
	    [file size $path(utf8-fcopy.txt)] \
	    [file size $path(utf8-rp.txt)]
} {3 5 5}
test chan-io-52.10 {TclCopyChannel & encodings} {fcopy} {
test chan-io-52.10 {TclCopyChannel & encodings} -constraints {fcopy} -body {
    # encoding to binary (=> implies that the internal utf-8 is written)
    set in  [open $path(kyrillic.txt) r]
    set out [open $path(utf8-fcopy.txt) w]
    chan configure $in  -encoding koi8-r -translation lf
    # -translation binary is also -encoding binary
    chan configure $out -translation binary
    chan copy $in $out
    file size $path(utf8-fcopy.txt)
} -cleanup {
    chan close $in
    chan close $out
    file size $path(utf8-fcopy.txt)
} 5
    unset in out
} -returnCodes 1 -match glob -result {error writing "*":\
	invalid or incomplete multibyte or wide character}
test chan-io-52.11 {TclCopyChannel & encodings} -setup {
    set f [open $path(utf8-fcopy.txt) w]
    fconfigure $f -encoding utf-8 -translation lf
    puts $f "\u0410\u0410"
    puts $f ÐÐ
    close $f
} -constraints {fcopy} -body {
    # binary to encoding => the input has to be in utf-8 to make sense to the
    # encoder
    set in  [open $path(utf8-fcopy.txt) r]
    set out [open $path(kyrillic.txt) w]
    # -translation binary is also -encoding binary
    chan configure $in  -translation binary
    chan configure $out -encoding koi8-r -translation lf
    chan copy $in $out
    chan close $in
    chan close $out
    chan configure $out -encoding koi8-r -translation lf -profile strict
    catch {chan copy $in $out} cres copts
    return $cres
} -cleanup {
    if {$in in [chan names]} {
	close $in
    }
    if {$out in [chan names]} {
	close $out
    file size $path(kyrillic.txt)
} -result 3
    }
    catch {unset cres}
} -match glob -result  {error writing "*": invalid or incomplete\
	multibyte or wide character}

test chan-io-53.1 {CopyData} -setup {
    file delete $path(test1)
} -constraints {fcopy} -body {
    set f1 [open $thisScript]
    set f2 [open $path(test1) w]
    chan configure $f1 -translation lf -blocking 0
    chan configure $f2 -translation cr -blocking 0
    chan copy $f1 $f2 -size 0
    set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
    chan close $f1
    chan close $f2
    lappend result [file size $path(test1)]
} -result {0 0 0}
test chan-io-53.2 {CopyData} -setup {
    file delete $path(test1)
} -constraints {fcopy} -body {
    set f1 [open $thisScript]
    set f2 [open $path(test1) w]
    chan configure $f1 -translation lf -blocking 0
    chan configure $f2 -translation cr -blocking 0
    chan configure $f1 -translation lf -encoding iso8859-1 -blocking 0
    chan configure $f2 -translation cr -encoding iso8859-1 -blocking 0
    chan copy $f1 $f2 -command [namespace code {set s0}]
    set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
    variable s0
    vwait [namespace which -variable s0]
    chan close $f1
    chan close $f2
    set s1 [file size $thisScript]
    set s2 [file size $path(test1)]
    if {($s1 == $s2) && ($s0 == $s1)} {
        lappend result ok
	lappend result ok
    }
    return $result
} -result {0 0 ok}
test chan-io-53.3 {CopyData: background read underflow} -setup {
    file delete $path(test1)
    file delete $path(pipe)
} -constraints {stdio unix fcopy} -body {
6959
6960
6961
6962
6963
6964
6965
6966

6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986

6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004


7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020

7021
7022

7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039

7040
7041
7042
7043
7044
7045
7046
7013
7014
7015
7016
7017
7018
7019

7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039

7040
7041
7042
7043
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056


7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072
7073

7074
7075

7076
7077
7078
7079
7080
7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091
7092

7093
7094
7095
7096
7097
7098
7099
7100







-
+



















-
+
















-
-
+
+















-
+

-
+
















-
+







    set listen [socket -server [namespace code FcopyTestAccept] -myaddr 127.0.0.1 0]
    set in [open $thisScript]	;# 126 K
    set out [socket 127.0.0.1 [lindex [chan configure $listen -sockname] 2]]
    catch {unset fcopyTestDone}
    chan close $listen	;# This means the socket open never really succeeds
    chan copy $in $out -command [namespace code FcopyTestDone]
    variable fcopyTestDone
    if ![info exists fcopyTestDone] {
    if {![info exists fcopyTestDone]} {
	vwait [namespace which -variable fcopyTestDone]		;# The error occurs here in the b.g.
    }
    chan close $in
    chan close $out
    set fcopyTestDone	;# 1 for error condition
} 1
test chan-io-53.6 {CopyData: error during chan copy} -setup {
    variable fcopyTestDone
    file delete $path(pipe)
    file delete $path(test1)
    catch {unset fcopyTestDone}
} -constraints {stdio fcopy} -body {
    set f1 [open $path(pipe) w]
    chan puts $f1 "exit 1"
    chan close $f1
    set in [openpipe r+ $path(pipe)]
    set out [open $path(test1) w]
    chan copy $in $out -command [namespace code FcopyTestDone]
    variable fcopyTestDone
    if ![info exists fcopyTestDone] {
    if {![info exists fcopyTestDone]} {
	vwait [namespace which -variable fcopyTestDone]
    }
    return $fcopyTestDone	;# 0 for plain end of file
} -cleanup {
    catch {chan close $in}
    chan close $out
} -result 0
proc doFcopy {in out {bytes 0} {error {}}} {
    variable fcopyTestDone
    variable fcopyTestCount
    incr fcopyTestCount $bytes
    if {[string length $error]} {
	set fcopyTestDone 1
    } elseif {[chan eof $in]} {
	set fcopyTestDone 0
    } else {
        # Delay next chan copy to wait for size>0 input bytes
        after 100 [list chan copy $in $out -size 1000 \
	# Delay next chan copy to wait for size>0 input bytes
	after 100 [list chan copy $in $out -size 1000 \
		-command [namespace code [list doFcopy $in $out]]]
    }
}
test chan-io-53.7 {CopyData: Flooding chan copy from pipe} -setup {
    variable fcopyTestDone
    file delete $path(pipe)
    catch {unset fcopyTestDone}
} -constraints {stdio fcopy} -body {
    set fcopyTestCount 0
    set f1 [open $path(pipe) w]
    chan puts $f1 {
	# Write  10 bytes / 10 msec
	proc Write {count} {
	    chan puts -nonewline "1234567890"
	    if {[incr count -1]} {
	        after 10 [list Write $count]
		after 10 [list Write $count]
	    } else {
	        set ::ready 1
		set ::ready 1
	    }
	}
	chan configure stdout -buffering none
	Write 345 ;# 3450 bytes ~3.45 sec
	vwait ready
	exit 0
    }
    chan close $f1
    set in [openpipe r+ $path(pipe) &]
    set out [open $path(test1) w]
    doFcopy $in $out
    variable fcopyTestDone
    if {![info exists fcopyTestDone]} {
	vwait [namespace which -variable fcopyTestDone]
    }
    # -1=error 0=script error N=number of bytes
    expr ($fcopyTestDone == 0) ? $fcopyTestCount : -1
    expr {($fcopyTestDone == 0) ? $fcopyTestCount : -1}
} -cleanup {
    catch {chan close $in}
    chan close $out
} -result {3450}
test chan-io-53.8 {CopyData: async callback and error handling, Bug 1932639} -setup {
    # copy progress callback. errors out intentionally
    proc cmd args {
7166
7167
7168
7169
7170
7171
7172
7173

7174
7175
7176
7177
7178
7179
7180
7220
7221
7222
7223
7224
7225
7226

7227
7228
7229
7230
7231
7232
7233
7234







-
+







    catch {after cancel $token}
    set ::forever
} -cleanup {
    chan close $pipe
    rename ::done {}
    if {[testConstraint win]} {
	after 1000;		# Allow Windows time to figure out that the
                                # process is gone
				# process is gone
    }
    catch {close $out}
    catch {removeFile out}
    catch {removeFile err}
    catch {unset ::forever}
} -result OK
test chan-io-53.10 {Bug 1350564, multi-directional fcopy} -setup {
7206
7207
7208
7209
7210
7211
7212
7213


7214
7215
7216

7217
7218
7219
7220

7221
7222
7223
7224
7225
7226
7227
7228


7229
7230
7231
7232
7233
7234
7235
7260
7261
7262
7263
7264
7265
7266

7267
7268
7269
7270

7271
7272
7273
7274

7275
7276
7277
7278
7279
7280
7281


7282
7283
7284
7285
7286
7287
7288
7289
7290







-
+
+


-
+



-
+






-
-
+
+







		chan copy $b $a -command [list geof $b]
		chan puts stderr 2COPY
	    }
	    chan puts stderr ...
	}
	chan puts stderr SRV
	set l {}
	set srv [socket -server new 9999]
	set srv [socket -server new -myaddr 127.0.0.1 0]
	set port [lindex [chan configure $srv -sockname] 2]
	chan puts stderr WAITING
	chan event stdin readable bye
	chan puts OK
	puts "OK $port"
	vwait forever
    }
    # wait for OK from server.
    chan gets $pipe
    lassign [chan gets $pipe] ok port
    # Now the two clients.
    proc done {sock} {
	if {[chan eof $sock]} { chan close $sock ; return }
	lappend ::forever [chan gets $sock]
	return
    }
    set a [socket 127.0.0.1 9999]
    set b [socket 127.0.0.1 9999]
    set a [socket 127.0.0.1 $port]
    set b [socket 127.0.0.1 $port]
    chan configure $a -translation binary -buffering none
    chan configure $b -translation binary -buffering none
    chan event  $a readable [namespace code "done $a"]
    chan event  $b readable [namespace code "done $b"]
} -constraints {stdio fcopy} -body {
    # Now pass data through the server in both directions.
    set ::forever {}
7491
7492
7493
7494
7495
7496
7497
7498

7499
7500
7501
7502
7503
7504
7505
7546
7547
7548
7549
7550
7551
7552

7553
7554
7555
7556
7557
7558
7559
7560







-
+







} {1}

test chan-io-60.1 {writing illegal utf sequences} {fileevent testbytestring} {
    # This test will hang in older revisions of the core.
    set out [open $path(script) w]
    chan puts $out "catch {load $::tcltestlib Tcltest}"
    chan puts $out {
	chan puts [testbytestring \xe2]
	chan puts [testbytestring \xE2]
	exit 1
    }
    proc readit {pipe} {
	variable x
	variable result
	if {[chan eof $pipe]} {
	    set x [catch {chan close $pipe} line]
7514
7515
7516
7517
7518
7519
7520
7521

7522
7523
7524
7525
7526
7527
7528
7569
7570
7571
7572
7573
7574
7575

7576
7577
7578
7579
7580
7581
7582
7583







-
+







    chan event $pipe readable [namespace code [list readit $pipe]]
    variable x ""
    set result ""
    vwait [namespace which -variable x]
    # cut of the remainder of the error stack, especially the filename
    set result [lreplace $result 3 3 [lindex [split [lindex $result 3] \n] 0]]
    list $x $result
} {1 {gets {} catch {error writing "stdout": invalid argument}}}
} {1 {gets {} catch {error writing "stdout": invalid or incomplete multibyte or wide character}}}

test chan-io-61.1 {Reset eof state after changing the eof char} -setup {
    set datafile [makeFile {} eofchar]
    set f [open $datafile w]
    chan configure $f -translation binary
    chan puts -nonewline $f [string repeat "Ho hum\n" 11]
    chan puts $f =
7542
7543
7544
7545
7546
7547
7548
7549

7550
7551
7552
7553
7554
7555
7556
7597
7598
7599
7600
7601
7602
7603

7604
7605
7606
7607
7608
7609
7610
7611







-
+







    #chan seek $f 0 current
    #lappend res [chan read $f; chan tell $f]
} -cleanup {
    chan close $f
    removeFile eofchar
} -result {77 = 23431}

# Test the cutting and splicing of channels, this is incidentially the
# Test the cutting and splicing of channels, this is incidentally the
# attach/detach facility of package Thread, but __without any safeguards__. It
# can also be used to emulate transfer of channels between threads, and is
# used for that here.

test chan-io-70.0 {Cutting & Splicing channels} -setup {
    set f [makeFile {... dummy ...} cutsplice]
    set res {}

Added tests/clock-ivm.test.









1
2
3
4
5
6
7
8
+
+
+
+
+
+
+
+
# clock-ivm.test --
#
# This test file covers the 'clock' command using inverted validity mode.
#
# See the file "clock.test" for more information.

::tcl::unsupported::clock::configure -valid [expr {![::tcl::unsupported::clock::configure -valid]}]
source [file join [file dirname [info script]] clock.test]

Changes to tests/clock.test.

more than 10,000 changes

Changes to tests/cmdAH.test.

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



30
31
32
33
34
35
36
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
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






-
-
+
+










-
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+
+
+







# The file tests the tclCmdAH.c file.
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1996-1998 by Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996-1998 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testchmod       [llength [info commands testchmod]]
testConstraint testsetplatform [llength [info commands testsetplatform]]
testConstraint testvolumetype  [llength [info commands testvolumetype]]
testConstraint testbytestring [llength [info commands testbytestring]]
testConstraint time64bit [expr {
    ([llength [info command testsize]] ?
	[testsize st_mtime] : $::tcl_platform(pointerSize)) >= 8
}]
testConstraint filetime64bit [expr {
    [testConstraint time64bit] && (
	![testConstraint unix] || [apply {{} {
	  # check whether disk may have 2038 problem, see [fd91b0ca09cb171f]:
	  set fn [makeFile "" foo.text]
	  if {[catch {
	    exec sh -c "TZ=:UTC LC_TIME=en_US touch -ma -t '207006290000' '$fn' && TZ=:UTC LC_TIME=en_US ls -l '$fn'"
	  } res]} {
	    #puts "Check constraint failed:\t$res"
	    set res {}
	  }
	  removeFile $fn
	  regexp {\mJun\s+29\s+2070\M} $res
	}}]
    )
}]
testConstraint linkDirectory [expr {
    ![testConstraint win] ||
    ($::tcl_platform(osVersion) >= 5.0
     && [lindex [file system [temporaryDirectory]] 1] eq "NTFS")
}]
testConstraint notWine [expr {$::tcl_platform(platform) ne "windows" || ![info exists ::env(TRAVIS_OS_NAME)] || ![string match linux $::env(TRAVIS_OS_NAME)]}]
testConstraint notWine [expr {![info exists ::env(CI_USING_WINE)]}]
# File permissions broken on wsl without some "exotic" wsl configuration
testConstraint notWsl [expr {[llength [array names ::env *WSL*]] == 0}]

global env
set cmdAHwd [pwd]
catch {set platform [testgetplatform]}

proc waitForEvenSecondForFAT {} {
    # Windows 9x uses filesystems (the FAT* family of FSes) without enough
96
97
98
99
100
101
102
103

104
105
106
107
108
109
110
119
120
121
122
123
124
125

126
127
128
129
130
131
132
133







-
+







    set oldpwd [pwd]
    set temp $env(HOME)
    file delete -force $foodir
} -body {
    set env(HOME) $oldpwd
    file mkdir $foodir
    cd $foodir
    cd ~
    cd [file home]
    string equal [pwd] $oldpwd
} -cleanup {
    cd $oldpwd
    file delete $foodir
    set env(HOME) $temp
} -result 1
test cmdAH-2.4 {Tcl_CdObjCmd} -setup {
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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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







-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

















-
+


-
+

















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+


-
+

-
-
+
+
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+







    string equal [pwd] $oldpwd
} -cleanup {
    cd $oldpwd
    file delete $foodir
    set env(HOME) $temp
} -result 1
test cmdAH-2.5 {Tcl_CdObjCmd} -returnCodes error -body {
    cd ~~
} -result {user "~" doesn't exist}
    cd ~
} -result {couldn't change working directory to "~": no such file or directory}
test cmdAH-2.5.1 {Tcl_CdObjCmd} -setup {
    set oldpwd [pwd]
    cd [temporaryDirectory]
    file delete ./~
    file mkdir ~
} -body {
    cd ~
    pwd
} -cleanup {
    cd [temporaryDirectory]
    file delete ./~
    cd $oldpwd
} -result [file join [temporaryDirectory] ~]
test cmdAH-2.6 {Tcl_CdObjCmd} -returnCodes error -body {
    cd _foobar
} -result {couldn't change working directory to "_foobar": no such file or directory}
test cmdAH-2.6.1 {Tcl_CdObjCmd} -returnCodes error -body {
    cd ""
} -result {couldn't change working directory to "": no such file or directory}
test cmdAH-2.6.2 {cd} -constraints {unix nonPortable} -setup {
    set dir [pwd]
} -body {
    cd /
    pwd
} -cleanup {
    cd $dir
} -result {/}
test cmdAH-2.6.3 {Tcl_CdObjCmd, bug #3118489} -setup {
    set dir [pwd]
} -returnCodes error -body {
    cd .\0
    cd .\x00
} -cleanup {
    cd $dir
} -match glob -result "couldn't change working directory to \".\0\": *"
} -match glob -result "couldn't change working directory to \".\x00\": *"
test cmdAH-2.7 {Tcl_ConcatObjCmd} {
    concat
} {}
test cmdAH-2.8 {Tcl_ConcatObjCmd} {
    concat a
} a
test cmdAH-2.9 {Tcl_ConcatObjCmd} {
    concat a {b c}
} {a b c}

test cmdAH-3.1 {Tcl_ContinueObjCmd, errors} -returnCodes error -body {
    continue foo
} -result {wrong # args: should be "continue"}
test cmdAH-3.2 {Tcl_ContinueObjCmd, success} {
    list [catch {continue} msg] $msg
} {4 {}}

###
# encoding command

set "numargErrors(encoding system)" {^wrong # args: should be "(encoding |::tcl::encoding::)system \?encoding\?"$}
set "numargErrors(encoding convertfrom)" {wrong # args: should be "(encoding |::tcl::encoding::)convertfrom \?-profile profile\? \?-failindex var\? encoding data" or "(encoding |::tcl::encoding::)convertfrom data"}
set "numargErrors(encoding convertto)" {wrong # args: should be "(encoding |::tcl::encoding::)convertto \?-profile profile\? \?-failindex var\? encoding data" or "(encoding |::tcl::encoding::)convertto data"}
set "numargErrors(encoding names)" {wrong # args: should be "encoding names"}
set "numargErrors(encoding profiles)" {wrong # args: should be "encoding profiles"}

source [file join [file dirname [info script]] encodingVectors.tcl]


# Maps utf-{16,32}{le,be} to utf-16, utf-32 and
# others to "". Used to test utf-16, utf-32 based
# on system endianness
proc endianUtf {enc} {
    if {$::tcl_platform(byteOrder) eq "littleEndian"} {
	set endian le
    } else {
	set endian be
    }
    if {$enc eq "utf-16$endian" || $enc eq "utf-32$endian"} {
	return [string range $enc 0 5]
    }
    return ""
}

#
# Check errors for invalid number of arguments
proc badnumargs {id cmd cmdargs} {
    variable numargErrors
    test $id.a "Syntax error: $cmd $cmdargs" \
	-body [list {*}$cmd {*}$cmdargs] \
	-result $numargErrors($cmd) \
	-match regexp \
	-returnCodes error
    test $id.b "Syntax error: $cmd (byte compiled)" \
	-setup [list proc compiled_proc {} [list {*}$cmd {*}$cmdargs]] \
	-body {compiled_proc} \
	-cleanup {rename compiled_proc {}} \
	-result $numargErrors($cmd) \
	-match regexp \
	-returnCodes error
}

# Wraps tests resulting in unknown encoding errors
proc unknownencodingtest {id cmd} {
    set result "unknown encoding \"[lindex $cmd end-1]\""
    test $id.a "Unknown encoding error: $cmd" \
	-body [list encoding {*}$cmd] \
	-result $result \
	-returnCodes error
    test $id.b "Syntax error: $cmd (byte compiled)" \
	-setup [list proc encoding_test {} [list encoding {*}$cmd]] \
	-body {encoding_test} \
	-cleanup {rename encoding_test {}} \
	-result $result \
	-returnCodes error
}

# Wraps tests for conversion, successful or not.
# Really more general than just for encoding conversion.
proc testconvert {id body result args} {
    test $id.a $body \
	-body $body \
	-result $result \
	{*}$args
    dict append args -setup \n[list proc compiled_script {} $body]
    dict append args -cleanup "\nrename compiled_script {}"
    test $id.b "$body (byte compiled)" \
	-body {compiled_script} \
	-result $result \
	{*}$args
}

# Wrapper to verify encoding convert{to,from} ?-profile?
# Generates tests for compiled and uncompiled implementation.
# Also generates utf-{16,32} tests if passed encoding is utf-{16,32}{le,be}
# The enc and profile are appended to id to generate the test id
proc testprofile {id converter enc profile data result args} {
    testconvert $id.$enc.$profile [list encoding $converter -profile $profile $enc $data] $result {*}$args
    if {[set enc2 [endianUtf $enc]] ne ""} {
	# If utf{16,32}-{le,be}, also do utf{16,32}
	testconvert $id.$enc2.$profile [list encoding $converter -profile $profile $enc2 $data] $result {*}$args
    }

    # If this is the default profile, generate a test without specifying profile
    if {$profile eq $::encDefaultProfile} {
	testconvert $id.$enc.default [list encoding $converter $enc $data] $result {*}$args
	if {[set enc2 [endianUtf $enc]] ne ""} {
	    # If utf{16,32}-{le,be}, also do utf{16,32}
	    testconvert $id.$enc2.default [list encoding $converter $enc2 $data] $result {*}$args
	}
    }
}


# Wrapper to verify encoding convert{to,from} -failindex ?-profile?
# Generates tests for compiled and uncompiled implementation.
# Also generates utf-{16,32} tests if passed encoding is utf-{16,32}{le,be}
# The enc and profile are appended to id to generate the test id
proc testfailindex {id converter enc data result failidx {profile default}} {
    testconvert $id.$enc.$profile "list \[encoding $converter -profile $profile -failindex idx $enc [list $data]\] \[set idx\]" [list $result $failidx]
    if {[set enc2 [endianUtf $enc]] ne ""} {
	# If utf{16,32}-{le,be}, also do utf{16,32}
	testconvert $id.$enc2.$profile "list \[encoding $converter -profile $profile -failindex idx $enc2 [list $data]\] \[set idx]" [list $result $failidx]
    }

    # If this is the default profile, generate a test without specifying profile
    if {$profile eq $::encDefaultProfile} {
	testconvert $id.$enc.default "list \[encoding $converter -failindex idx $enc [list $data]\] \[set idx]" [list $result $failidx]
	if {[set enc2 [endianUtf $enc]] ne ""} {
	    # If utf{16,32}-{le,be}, also do utf{16,32}
	    testconvert $id.$enc2.default "list \[encoding $converter -failindex idx $enc2 [list $data]\] \[set idx]" [list $result $failidx]
	}
    }
}

test cmdAH-4.1 {Tcl_EncodingObjCmd} -returnCodes error -body {
test cmdAH-4.1.1 {encoding} -returnCodes error -body {
    encoding
} -result {wrong # args: should be "encoding subcommand ?arg ...?"}
test cmdAH-4.2 {Tcl_EncodingObjCmd} -returnCodes error -body {
test cmdAH-4.1.2 {Tcl_EncodingObjCmd} -returnCodes error -body {
    encoding foo
} -result {unknown or ambiguous subcommand "foo": must be convertfrom, convertto, dirs, names, or system}
test cmdAH-4.3 {Tcl_EncodingObjCmd} -returnCodes error -body {
} -result {unknown or ambiguous subcommand "foo": must be convertfrom, convertto, dirs, names, profiles, or system}

    encoding convertto
} -result {wrong # args: should be "encoding convertto ?encoding? data"}
test cmdAH-4.4 {Tcl_EncodingObjCmd} -returnCodes error -body {
    encoding convertto foo bar
} -result {unknown encoding "foo"}
test cmdAH-4.5 {Tcl_EncodingObjCmd} -setup {
    set system [encoding system]
} -body {
    encoding system jis0208
#
# encoding system 4.2.*
    encoding convertto \u4e4e
} -cleanup {
    encoding system $system
badnumargs cmdAH-4.2.1 {encoding system} {ascii ascii}
} -result 8C
test cmdAH-4.6 {Tcl_EncodingObjCmd} -setup {
test cmdAH-4.2.2 {Tcl_EncodingObjCmd} -setup {
    set system [encoding system]
} -body {
    encoding system iso8859-1
    encoding convertto jis0208 \u4e4e
} -cleanup {
    encoding system $system
} -result 8C
test cmdAH-4.7 {Tcl_EncodingObjCmd} -returnCodes error -body {
    encoding convertfrom
} -result {wrong # args: should be "encoding convertfrom ?encoding? data"}
test cmdAH-4.8 {Tcl_EncodingObjCmd} -returnCodes error -body {
    encoding convertfrom foo bar
} -result {unknown encoding "foo"}
test cmdAH-4.9 {Tcl_EncodingObjCmd} -setup {
    set system [encoding system]
} -body {
    encoding system jis0208
    encoding convertfrom 8C
} -cleanup {
    encoding system $system
} -result \u4e4e
test cmdAH-4.10 {Tcl_EncodingObjCmd} -setup {
    set system [encoding system]
} -body {
    encoding system iso8859-1
    encoding convertfrom jis0208 8C
} -cleanup {
    encoding system $system
} -result \u4e4e
test cmdAH-4.11 {Tcl_EncodingObjCmd} -returnCodes error -body {
    encoding names foo
} -result {wrong # args: should be "encoding names"}
test cmdAH-4.12 {Tcl_EncodingObjCmd} -returnCodes error -body {
    encoding system foo bar
} -result {wrong # args: should be "encoding system ?encoding?"}
test cmdAH-4.13 {Tcl_EncodingObjCmd} -setup {
    set system [encoding system]
} -body {
    encoding system iso8859-1
    encoding system
} -cleanup {
    encoding system $system
} -result iso8859-1

#
# encoding convertfrom 4.3.*

# Odd number of args is always invalid since last two args
# are ENCODING DATA and all options take a value
badnumargs cmdAH-4.3.1 {encoding convertfrom} {}
badnumargs cmdAH-4.3.2 {encoding convertfrom} {-failindex VAR ABC}
badnumargs cmdAH-4.3.3 {encoding convertfrom} {-profile VAR ABC}
badnumargs cmdAH-4.3.4 {encoding convertfrom} {-failindex VAR -profile strict ABC}
badnumargs cmdAH-4.3.5 {encoding convertfrom} {-profile strict -failindex VAR ABC}

# Test that last two args always treated as ENCODING DATA
unknownencodingtest cmdAH-4.3.6 {convertfrom -failindex ABC}
unknownencodingtest cmdAH-4.3.7 {convertfrom -profile ABC}
unknownencodingtest cmdAH-4.3.8 {convertfrom nosuchencoding ABC}
unknownencodingtest cmdAH-4.3.9 {convertfrom -failindex VAR -profile ABC}
unknownencodingtest cmdAH-4.3.10 {convertfrom -profile strict -failindex ABC}
testconvert cmdAH-4.3.11 {
    encoding convertfrom jis0208 \x38\x43
} 乎 -setup {
    set system [encoding system]
    encoding system iso8859-1
} -cleanup {
    encoding system $system
}

# Verify single arg defaults to system encoding
testconvert cmdAH-4.3.12 {
    encoding convertfrom \x38\x43
} 乎 -setup {
    set system [encoding system]
    encoding system jis0208
} -cleanup {
    encoding system $system
}

# convertfrom ?-profile? : valid byte sequences
foreach {enc str hex ctrl comment} $encValidStrings {
    if {"knownBug" in $ctrl} continue
    set bytes [binary decode hex $hex]
    set prefix A
    set suffix B
    set prefix_bytes [encoding convertto $enc A]
    set suffix_bytes [encoding convertto $enc B]
    foreach profile $encProfiles {
	testprofile cmdAH-4.3.13.$hex.solo convertfrom $enc $profile $bytes $str
	testprofile cmdAH-4.3.13.$hex.lead convertfrom $enc $profile $bytes$suffix_bytes $str$suffix
	testprofile cmdAH-4.3.13.$hex.tail convertfrom $enc $profile $prefix_bytes$bytes $prefix$str
	testprofile cmdAH-4.3.13.$hex.middle convertfrom $enc $profile $prefix_bytes$bytes$suffix_bytes $prefix$str$suffix
    }
}

# convertfrom ?-profile? : invalid byte sequences
foreach {enc hex profile str failidx ctrl comment} $encInvalidBytes {
    if {"knownBug" in $ctrl} continue
    set bytes [binary format H* $hex]
    set prefix A
    set suffix B
    set prefix_bytes [encoding convertto $enc $prefix]
    set suffix_bytes [encoding convertto $enc $suffix]
    set prefixLen [string length $prefix_bytes]
    set result [list $str]
    # TODO - if the bad byte is unprintable, tcltest errors out when printing a mismatch
    # so glob it out in error message pattern for now.
    set errorWithoutPrefix [list "unexpected byte sequence starting at index $failidx: *" -returnCodes error -match glob]
    set errorWithPrefix [list "unexpected byte sequence starting at index [expr {$failidx+$prefixLen}]: *" -returnCodes error -match glob]
    if {$ctrl eq {} || "solo" in $ctrl} {
	if {$failidx == -1} {
	    set result [list $str]
	} else {
	    set result $errorWithoutPrefix
	}
	testprofile cmdAH-4.3.13.$hex.solo convertfrom $enc $profile $bytes {*}$result
    }
    if {$ctrl eq {} || "lead" in $ctrl} {
	if {$failidx == -1} {
	    set result [list $str$suffix]
	} else {
	    set result $errorWithoutPrefix
	}
	testprofile cmdAH-4.3.13.$hex.lead convertfrom $enc $profile $bytes$suffix_bytes {*}$result
    }
    if {$ctrl eq {} || "tail" in $ctrl} {
	if {$failidx == -1} {
	    set result [list $prefix$str]
	} else {
	    set result $errorWithPrefix
	}
	testprofile cmdAH-4.3.13.$hex.tail convertfrom $enc $profile $prefix_bytes$bytes {*}$result
    }
    if {$ctrl eq {} || "middle" in $ctrl} {
	if {$failidx == -1} {
	    set result [list $prefix$str$suffix]
	} else {
	    set result $errorWithPrefix
	}
	testprofile cmdAH-4.3.13.$hex.middle convertfrom $enc $profile $prefix_bytes$bytes$suffix_bytes {*}$result
    }
}

# convertfrom -failindex ?-profile? - valid data
foreach {enc str hex ctrl comment} $encValidStrings {
    if {"knownBug" in $ctrl} continue
    set bytes [binary decode hex $hex]
    set prefix A
    set suffix B
    set prefix_bytes [encoding convertto $enc $prefix]
    set suffix_bytes [encoding convertto $enc $suffix]
    foreach profile $encProfiles {
	testfailindex cmdAH-4.3.14.$hex.solo convertfrom $enc $bytes $str -1 $profile
	testfailindex cmdAH-4.3.14.$hex.lead convertfrom $enc $bytes$suffix_bytes $str$suffix -1 $profile
	testfailindex cmdAH-4.3.14.$hex.tail convertfrom $enc $prefix_bytes$bytes $prefix$str -1 $profile
	testfailindex cmdAH-4.3.14.$hex.middle convertfrom $enc $prefix_bytes$bytes$suffix_bytes $prefix$str$suffix -1 $profile
    }
}

# convertfrom -failindex ?-profile? - invalid data
foreach {enc hex profile str failidx ctrl comment} $encInvalidBytes {
    if {"knownBug" in $ctrl} continue
    # There are multiple test cases based on location of invalid bytes
    set bytes [binary decode hex $hex]
    set prefix A
    set suffix B
    set prefix_bytes [encoding convertto $enc $prefix]
    set suffix_bytes [encoding convertto $enc $suffix]
    set prefixLen [string length $prefix_bytes]
    if {$ctrl eq {} || "solo" in $ctrl} {
	testfailindex cmdAH-4.3.14.$hex.solo convertfrom $enc $bytes $str $failidx $profile
    }
    if {$ctrl eq {} || "lead" in $ctrl} {
	if {$failidx == -1} {
	    # If success expected
	    set result $str$suffix
	} else {
	    # Failure expected
	    set result ""
	}
	testfailindex cmdAH-4.3.14.$hex.lead convertfrom $enc $bytes$suffix_bytes $result $failidx $profile
    }
    if {$ctrl eq {} || "tail" in $ctrl} {
	set expected_failidx $failidx
	if {$failidx == -1} {
	    # If success expected
	    set result $prefix$str
	} else {
	    # Failure expected
	    set result $prefix
	    incr expected_failidx $prefixLen
	}
	testfailindex cmdAH-4.3.14.$hex.tail convertfrom $enc $prefix_bytes$bytes $result $expected_failidx $profile
    }
    if {$ctrl eq {} || "middle" in $ctrl} {
	set expected_failidx $failidx
	if {$failidx == -1} {
	    # If success expected
	    set result $prefix$str$suffix
	} else {
	    # Failure expected
	    set result $prefix
	    incr expected_failidx $prefixLen
	}
	testfailindex cmdAH-4.3.14.$hex.middle convertfrom $enc $prefix_bytes$bytes$suffix_bytes $result $expected_failidx $profile
    }
}

#
# encoding convertto 4.4.*

badnumargs cmdAH-4.4.1 {encoding convertto} {}
badnumargs cmdAH-4.4.2 {encoding convertto} {-failindex VAR ABC}
badnumargs cmdAH-4.4.3 {encoding convertto} {-profile VAR ABC}
badnumargs cmdAH-4.4.4 {encoding convertto} {-failindex VAR -profile strict ABC}
badnumargs cmdAH-4.4.5 {encoding convertto} {-profile strict -failindex VAR ABC}

# Test that last two args always treated as ENCODING DATA
unknownencodingtest cmdAH-4.4.6 {convertto -failindex ABC}
unknownencodingtest cmdAH-4.4.7 {convertto -profile ABC}
unknownencodingtest cmdAH-4.4.8 {convertto nosuchencoding ABC}
unknownencodingtest cmdAH-4.4.9 {convertto -failindex VAR -profile ABC}
unknownencodingtest cmdAH-4.4.10 {convertto -profile strict -failindex ABC}
testconvert cmdAH-4.4.11 {
    encoding convertto jis0208 乎
} \x38\x43 -setup {
    set system [encoding system]
    encoding system iso8859-1
} -cleanup {
    encoding system $system
}

# Verify single arg defaults to system encoding
testconvert cmdAH-4.4.12 {
    encoding convertto 乎
} \x38\x43 -setup {
    set system [encoding system]
    encoding system jis0208
} -cleanup {
    encoding system $system
}

# convertto ?-profile? : valid byte sequences

foreach {enc str hex ctrl comment} $encValidStrings {
    if {"knownBug" in $ctrl} continue
    set bytes [binary decode hex $hex]
    set printable [tcltest::Asciify $str]
    set prefix A
    set suffix B
    set prefix_bytes [encoding convertto $enc A]
    set suffix_bytes [encoding convertto $enc B]
    foreach profile $encProfiles {
	testprofile cmdAH-4.4.13.$printable.solo convertto $enc $profile $str $bytes
	testprofile cmdAH-4.4.13.$printable.lead convertto $enc $profile $str$suffix $bytes$suffix_bytes
	testprofile cmdAH-4.4.13.$printable.tail convertto $enc $profile $prefix$str $prefix_bytes$bytes
	testprofile cmdAH-4.4.13.$printable.middle convertto $enc $profile $prefix$str$suffix $prefix_bytes$bytes$suffix_bytes
    }
}

# convertto ?-profile? : invalid byte sequences
foreach {enc str profile hex failidx ctrl comment} $encUnencodableStrings {
    if {"knownBug" in $ctrl} continue
    set bytes [binary decode hex $hex]
    set printable [tcltest::Asciify $str]
    set prefix A
    set suffix B
    set prefix_bytes [encoding convertto $enc $prefix]
    set suffix_bytes [encoding convertto $enc $suffix]
    set prefixLen [string length $prefix_bytes]
    set result [list $bytes]
    # TODO - if the bad byte is unprintable, tcltest errors out when printing a mismatch
    # so glob it out in error message pattern for now.
    set errorWithoutPrefix [list "unexpected character at index $failidx: *" -returnCodes error -match glob]
    set errorWithPrefix [list "unexpected character at index [expr {$failidx+$prefixLen}]: *" -returnCodes error -match glob]
    if {$ctrl eq {} || "solo" in $ctrl} {
	if {$failidx == -1} {
	    set result [list $bytes]
	} else {
	    set result $errorWithoutPrefix
	}
	testprofile cmdAH-4.4.13.$printable.solo convertto $enc $profile $str {*}$result
    }
    if {$ctrl eq {} || "lead" in $ctrl} {
	if {$failidx == -1} {
	    set result [list $bytes$suffix_bytes]
	} else {
	    set result $errorWithoutPrefix
	}
	testprofile cmdAH-4.4.13.$printable.lead convertto $enc $profile $str$suffix {*}$result
    }
    if {$ctrl eq {} || "tail" in $ctrl} {
	if {$failidx == -1} {
	    set result [list $prefix_bytes$bytes]
	} else {
	    set result $errorWithPrefix
	}
	testprofile cmdAH-4.4.13.$printable.tail convertto $enc $profile $prefix$str {*}$result
    }
    if {$ctrl eq {} || "middle" in $ctrl} {
	if {$failidx == -1} {
	    set result [list $prefix_bytes$bytes$suffix_bytes]
	} else {
	    set result $errorWithPrefix
	}
	testprofile cmdAH-4.4.13.$printable.middle convertto $enc $profile $prefix$str$suffix {*}$result
    }
}

# convertto -failindex ?-profile? - valid data
foreach {enc str hex ctrl comment} $encValidStrings {
    if {"knownBug" in $ctrl} continue
    set bytes [binary decode hex $hex]
    set printable [tcltest::Asciify $str]
    set prefix A
    set suffix B
    set prefix_bytes [encoding convertto $enc A]
    set suffix_bytes [encoding convertto $enc B]
    foreach profile $encProfiles {
	testfailindex cmdAH-4.4.14.$enc.$printable.solo convertto $enc $str $bytes -1 $profile
	testfailindex cmdAH-4.4.14.$enc.$printable.lead convertto $enc $str$suffix $bytes$suffix_bytes -1 $profile
	testfailindex cmdAH-4.4.14.$enc.$printable.tail convertto $enc $prefix$str $prefix_bytes$bytes -1 $profile
	testfailindex cmdAH-4.4.14.$enc.$printable.middle convertto $enc $prefix$str$suffix $prefix_bytes$bytes$suffix_bytes -1 $profile
    }
}

# convertto -failindex ?-profile? - invalid data
foreach {enc str profile hex failidx ctrl comment} $encUnencodableStrings {
    if {"knownBug" in $ctrl} continue
    set bytes [binary decode hex $hex]
    set printable [tcltest::Asciify $str]
    set prefix A
    set suffix B
    set prefixLen [string length [encoding convertto $enc $prefix]]
    if {$ctrl eq {} || "solo" in $ctrl} {
	testfailindex cmdAH-4.4.14.$printable.solo convertto $enc $str $bytes $failidx $profile
    }
    if {$ctrl eq {} || "lead" in $ctrl} {
	if {$failidx == -1} {
	    # If success expected
	    set result $bytes$suffix
	} else {
	    # Failure expected
	    set result ""
	}
	testfailindex cmdAH-4.4.14.$printable.lead convertto $enc $str$suffix $result $failidx $profile
    }
    if {$ctrl eq {} || "tail" in $ctrl} {
	set expected_failidx $failidx
	if {$failidx == -1} {
	    # If success expected
	    set result $prefix$bytes
	} else {
	    # Failure expected
	    set result $prefix
	    incr expected_failidx $prefixLen
	}
	testfailindex cmdAH-4.4.14.$printable.tail convertto $enc $prefix$str $result $expected_failidx $profile
    }
    if {$ctrl eq {} || "middle" in $ctrl} {
	set expected_failidx $failidx
	if {$failidx == -1} {
	    # If success expected
	    set result $prefix$bytes$suffix
	} else {
	    # Failure expected
	    set result $prefix
	    incr expected_failidx $prefixLen
	}
	testfailindex cmdAH-4.4.14.$printable.middle convertto $enc $prefix$str$suffix $result $expected_failidx $profile
    }
}

test cmdAH-4.4.xx {convertto -profile strict} -constraints {testbytestring knownBug} -body {
    # TODO - what does testbytestring even test? Invalid UTF8 in the Tcl_Obj bytes field
    encoding convertto -profile strict utf-8 A[testbytestring \x80]B
} -returnCodes error -result {unexpected byte sequence starting at index 1: '\x80'}

#
# encoding names 4.5.*
badnumargs cmdAH-4.5.1 {encoding names} {foo}
test cmdAH-4.5.2 {encoding names should include at least utf-8 and iso8859-1 and at least one more} -body {
    set names [encoding names]
    list [expr {"utf-8" in $names}] [expr {"iso8859-1" in $names}] [expr {[llength $names] > 2}]
} -result {1 1 1}

#
# encoding profiles 4.6.*
badnumargs cmdAH-4.6.1 {encoding profiles} {foo}
test cmdAH-4.6.2 {encoding profiles} -body {
    lsort [encoding profiles]
} -result {replace strict tcl8}

#
# file command

test cmdAH-5.1 {Tcl_FileObjCmd} -returnCodes error -body {
    file
} -result {wrong # args: should be "file subcommand ?arg ...?"}
test cmdAH-5.2 {Tcl_FileObjCmd} -returnCodes error -body {
    file x
} -result {unknown or ambiguous subcommand "x": must be atime, attributes, channels, copy, delete, dirname, executable, exists, extension, isdirectory, isfile, join, link, lstat, mkdir, mtime, nativename, normalize, owned, pathtype, readable, readlink, rename, rootname, separator, size, split, stat, system, tail, tempdir, tempfile, type, volumes, or writable}
} -result {unknown or ambiguous subcommand "x": must be atime, attributes, channels, copy, delete, dirname, executable, exists, extension, home, isdirectory, isfile, join, link, lstat, mkdir, mtime, nativename, normalize, owned, pathtype, readable, readlink, rename, rootname, separator, size, split, stat, system, tail, tempdir, tempfile, tildeexpand, type, volumes, or writable}
test cmdAH-5.3 {Tcl_FileObjCmd} -returnCodes error -body {
    file exists
} -result {wrong # args: should be "file exists name"}
test cmdAH-5.4 {Tcl_FileObjCmd} {
    file exists ""
} 0

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
775
776
777
778
779
780
781

782
783
784
785

786
787
788
789

790
791
792
793

794
795
796
797
798
799
800
801







-
+



-
+



-
+



-
+







test cmdAH-8.13 {Tcl_FileObjCmd: dirname} testsetplatform {
    testsetplatform unix
    file dirname /foo
} /
test cmdAH-8.14 {Tcl_FileObjCmd: dirname} testsetplatform {
    testsetplatform unix
    file dirname //foo
} /
} //foo
test cmdAH-8.15 {Tcl_FileObjCmd: dirname} testsetplatform {
    testsetplatform unix
    file dirname //foo/bar
} /foo
} //foo
test cmdAH-8.16 {Tcl_FileObjCmd: dirname} testsetplatform {
    testsetplatform unix
    file dirname {//foo\/bar/baz}
} {/foo\/bar}
} {//foo\/bar}
test cmdAH-8.17 {Tcl_FileObjCmd: dirname} testsetplatform {
    testsetplatform unix
    file dirname {//foo\/bar/baz/blat}
} {/foo\/bar/baz}
} {//foo\/bar/baz}
test cmdAH-8.18 {Tcl_FileObjCmd: dirname} testsetplatform {
    testsetplatform unix
    file dirname /foo//
} /
test cmdAH-8.19 {Tcl_FileObjCmd: dirname} testsetplatform {
    testsetplatform unix
    file dirname ./a
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
838
839
840
841
842
843
844

845
846
847
848
849
850
851
852
853
854

855
856
857


858
859




860



861
862
863
864
865
866
867
868







-
+









-
+


-
-
+
+
-
-
-
-

-
-
-
+







} ~bar
test cmdAH-8.43 {Tcl_FileObjCmd: dirname} -setup {
    global env
    set temp $env(HOME)
} -constraints testsetplatform -body {
    set env(HOME) "/homewontexist/test"
    testsetplatform unix
    file dirname ~
    file dirname [file home]
} -cleanup {
    set env(HOME) $temp
} -result /homewontexist
test cmdAH-8.44 {Tcl_FileObjCmd: dirname} -setup {
    global env
    set temp $env(HOME)
} -constraints testsetplatform -body {
    set env(HOME) "~"
    testsetplatform unix
    file dirname ~
    file dirname [file home]
} -cleanup {
    set env(HOME) $temp
} -result ~
test cmdAH-8.45 {Tcl_FileObjCmd: dirname} -setup {
} -result .
test cmdAH-8.45 {Tcl_FileObjCmd: dirname ~} -body {
    set temp $::env(HOME)
} -constraints {win testsetplatform} -match regexp -body {
    set ::env(HOME) "/homewontexist/test"
    testsetplatform windows
    file dirname ~
} -cleanup {
    set ::env(HOME) $temp
} -result {([a-zA-Z]:?)/homewontexist}
} -result .
test cmdAH-8.46 {Tcl_FileObjCmd: dirname} {
    set f [file normalize [info nameof]]
    file exists $f
    set res1 [file dirname [file join $f foo/bar]]
    set res2 [file dirname "${f}/foo/bar"]
    if {$res1 eq $res2} {
	return "ok"
458
459
460
461
462
463
464
465

466
467
468
469
470
471
472
913
914
915
916
917
918
919

920
921
922
923
924
925
926
927







-
+







test cmdAH-9.13 {Tcl_FileObjCmd: tail} testsetplatform {
    testsetplatform unix
    file tail /foo
} foo
test cmdAH-9.14 {Tcl_FileObjCmd: tail} testsetplatform {
    testsetplatform unix
    file tail //foo
} foo
} {}
test cmdAH-9.15 {Tcl_FileObjCmd: tail} testsetplatform {
    testsetplatform unix
    file tail //foo/bar
} bar
test cmdAH-9.16 {Tcl_FileObjCmd: tail} testsetplatform {
    testsetplatform unix
    file tail {//foo\/bar/baz}
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
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







-
+
-
-
-
-
-

-
-
-
+






-
+


-
+
-
-
-
-
-
-
-
-
-
-







    testsetplatform windows
    file tail {//foo/bar/baz}
} baz
test cmdAH-9.26 {Tcl_FileObjCmd: tail} testsetplatform {
    testsetplatform windows
    file tail {//foo/bar}
} {}
test cmdAH-9.42 {Tcl_FileObjCmd: tail} -constraints testsetplatform -setup {
test cmdAH-9.42 {Tcl_FileObjCmd: tail ~} -body {
    global env
    set temp $env(HOME)
} -body {
    set env(HOME) "/home/test"
    testsetplatform unix
    file tail ~
} -cleanup {
    set env(HOME) $temp
} -result test
} -result ~
test cmdAH-9.43 {Tcl_FileObjCmd: tail} -constraints testsetplatform -setup {
    global env
    set temp $env(HOME)
} -body {
    set env(HOME) "~"
    testsetplatform unix
    file tail ~
    file tail [file home]
} -cleanup {
    set env(HOME) $temp
} -result {}
} -result ~
test cmdAH-9.44 {Tcl_FileObjCmd: tail} -constraints testsetplatform -setup {
    global env
    set temp $env(HOME)
} -body {
    set env(HOME) "/home/test"
    testsetplatform windows
    file tail ~
} -cleanup {
    set env(HOME) $temp
} -result test
test cmdAH-9.46 {Tcl_FileObjCmd: tail} testsetplatform {
    testsetplatform unix
    file tail {f.oo\bar/baz.bat}
} baz.bat
test cmdAH-9.47 {Tcl_FileObjCmd: tail} testsetplatform {
    testsetplatform windows
    file tail c:foo
567
568
569
570
571
572
573
574

575
576
577
578
579
580
581
1005
1006
1007
1008
1009
1010
1011

1012
1013
1014
1015
1016
1017
1018
1019







-
+







} bar
test cmdAH-9.52 {Tcl_FileObjCmd: tail / normalize, bug 7a9dc52b29} {
    list \
	[file tail {~/~foo}] \
	[file tail {~/test/~foo}] \
	[file tail [file normalize {~/~foo}]] \
	[file tail [file normalize {~/test/~foo}]]
} [lrepeat 4 ./~foo]
} [lrepeat 4 ~foo]

# rootname
test cmdAH-10.1 {Tcl_FileObjCmd: rootname} -returnCodes error -body {
    file rootname a b
} -result {wrong # args: should be "file rootname name"}
test cmdAH-10.2 {Tcl_FileObjCmd: rootname} testsetplatform {
    testsetplatform unix
821
822
823
824
825
826
827
828

829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844



845
846
847
848
849
850




851
852
853
854
855
856
857
858
859
860
861
862
863



864
865
866
867
868
869



870
871
872
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




898
899
900
901
902

903
904
905
906
907
908
909
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







-
+













-
-
-
+
+
+


-
-
-
-
+
+
+
+










-
-
-
+
+
+



-
-
-
+
+
+










-
+













-
-
-
-
+
+
+
+




-
+







    file join a b c d
} a/b/c/d

# error handling of Tcl_TranslateFileName
test cmdAH-15.1 {Tcl_FileObjCmd} -constraints testsetplatform -body {
    testsetplatform unix
    file atime ~_bad_user
} -returnCodes error -result {user "_bad_user" doesn't exist}
} -returnCodes error -result {could not read "~_bad_user": no such file or directory}

catch {testsetplatform $platform}

# readable
set gorpfile [makeFile abcde gorp.file]
set dirfile [makeDirectory dir.file]
test cmdAH-16.1 {Tcl_FileObjCmd: readable} {
    -returnCodes error
    -body   {file readable a b}
    -result {wrong # args: should be "file readable name"}
}
test cmdAH-16.2 {Tcl_FileObjCmd: readable} {
    -constraints testchmod
    -setup  	 {testchmod 0o444 $gorpfile}
    -body   	 {file readable $gorpfile}
    -result 	 1
    -setup	 {testchmod 0o444 $gorpfile}
    -body	 {file readable $gorpfile}
    -result	 1
}
test cmdAH-16.3 {Tcl_FileObjCmd: readable} {
    -constraints {unix notRoot testchmod}
    -setup  	 {testchmod 0o333 $gorpfile}
    -body   	 {file readable $gorpfile}
    -result 	 0
    -constraints {unix notRoot testchmod notWsl}
    -setup	 {testchmod 0o333 $gorpfile}
    -body	 {file readable $gorpfile}
    -result	 0
}

# writable
test cmdAH-17.1 {Tcl_FileObjCmd: writable} {
    -returnCodes error
    -body   {file writable a b}
    -result {wrong # args: should be "file writable name"}
}
test cmdAH-17.2 {Tcl_FileObjCmd: writable} {
    -constraints {notRoot testchmod}
    -setup  	 {testchmod 0o555 $gorpfile}
    -body   	 {file writable $gorpfile}
    -result 	 0
    -setup	 {testchmod 0o555 $gorpfile}
    -body	 {file writable $gorpfile}
    -result	 0
}
test cmdAH-17.3 {Tcl_FileObjCmd: writable} {
    -constraints testchmod
    -setup  	 {testchmod 0o222 $gorpfile}
    -body   	 {file writable $gorpfile}
    -result 	 1
    -setup	 {testchmod 0o222 $gorpfile}
    -body	 {file writable $gorpfile}
    -result	 1
}

# executable
removeFile $gorpfile
removeDirectory $dirfile
set dirfile [makeDirectory dir.file]
set gorpfile [makeFile abcde gorp.file]
test cmdAH-18.1 {Tcl_FileObjCmd: executable} -returnCodes error -body {
    file executable a b
} -result {wrong # args: should be "file executable name"}
test cmdAH-18.2 {Tcl_FileObjCmd: executable} {notRoot} {
test cmdAH-18.2 {Tcl_FileObjCmd: executable} {notRoot notWsl} {
    file executable $gorpfile
} 0
test cmdAH-18.3 {Tcl_FileObjCmd: executable} {unix testchmod} {
    # Only on unix will setting the execute bit on a regular file cause that
    # file to be executable.
    testchmod 0o775 $gorpfile
    file exe $gorpfile
} 1
test cmdAH-18.5 {Tcl_FileObjCmd: executable} -constraints {win} -body {
    # On windows, must be a .exe, .com, etc.
    set x {}
    set gorpexes {}
    foreach ext {exe com cmd bat} {
        lappend x [file exe nosuchfile.$ext]
        set gorpexe [makeFile foo gorp.$ext]
        lappend gorpexes $gorpexe
        lappend x [file exe $gorpexe] [file exe [string toupper $gorpexe]]
	lappend x [file exe nosuchfile.$ext]
	set gorpexe [makeFile foo gorp.$ext]
	lappend gorpexes $gorpexe
	lappend x [file exe $gorpexe] [file exe [string toupper $gorpexe]]
    }
    set x
} -cleanup {
    foreach gorpexe $gorpexes {
        removeFile $gorpexe
	removeFile $gorpexe
    }
} -result {0 1 1 0 1 1 0 1 1 0 1 1}
test cmdAH-18.6 {Tcl_FileObjCmd: executable} {} {
    # Directories are always executable.
    file exe $dirfile
} 1

944
945
946
947
948
949
950
951
952
953

954
955
956
957
958
959
960
961
962
963

964
965
966

967
968
969
970
971
972
973
1382
1383
1384
1385
1386
1387
1388

1389

1390
1391
1392
1393
1394
1395
1396
1397
1398
1399

1400
1401
1402

1403
1404
1405
1406
1407
1408
1409
1410







-

-
+









-
+


-
+







} -constraints testsetplatform -cleanup {
    testsetplatform $platform
} -result {a\b}
test cmdAH-19.9 {Tcl_FileObjCmd: ~ : exists} {
    file exists ~nOsUcHuSeR
} 0
test cmdAH-19.10 {Tcl_FileObjCmd: ~ : nativename} -body {
    # should probably be a non-error in fact...
    file nativename ~nOsUcHuSeR
} -returnCodes error -match glob -result *
} -result ~nOsUcHuSeR
# The test below has to be done in /tmp rather than the current directory in
# order to guarantee (?) a local file system: some NFS file systems won't do
# the stuff below correctly.
test cmdAH-19.11 {Tcl_FileObjCmd: exists} -constraints {unix notRoot} -setup {
    file delete -force /tmp/tcl.foo.dir/file
    file delete -force /tmp/tcl.foo.dir
} -body {
    makeDirectory /tmp/tcl.foo.dir
    makeFile 12345 /tmp/tcl.foo.dir/file
    file attributes /tmp/tcl.foo.dir -permissions 0000
    file attributes /tmp/tcl.foo.dir -permissions 0
    file exists /tmp/tcl.foo.dir/file
} -cleanup {
    file attributes /tmp/tcl.foo.dir -permissions 0775
    file attributes /tmp/tcl.foo.dir -permissions 0o775
    removeFile /tmp/tcl.foo.dir/file
    removeDirectory /tmp/tcl.foo.dir
} -result 0
test cmdAH-19.12 {Bug 3608360: [file exists] mustn't do globbing} -setup {
    set newdirfile [makeDirectory newdir.file]
    set cwd [pwd]
    cd $newdirfile
982
983
984
985
986
987
988
989

990
991
992
993
994
995
996
1419
1420
1421
1422
1423
1424
1425

1426
1427
1428
1429
1430
1431
1432
1433







-
+







} -result {1 0}

# Stat related commands

catch {testsetplatform $platform}
removeFile $gorpfile
set gorpfile [makeFile "Test string" gorp.file]
catch {file attributes $gorpfile -permissions 0765}
catch {file attributes $gorpfile -permissions 0o765}

# avoid problems with non-local filesystems
if {[testConstraint unix] && [file exists /tmp]} {
    set file [makeFile "data" touch.me /tmp]
} else {
    set file [makeFile "data" touch.me]
}
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
1506
1507
1508
1509
1510
1511
1512

1513
1514
1515

1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526

1527
1528
1529
1530
1531
1532
1533
1534







-
+


-
+










-
+







test cmdAH-22.3 {Tcl_FileObjCmd: isfile} {file isfile $dirfile} 0

# lstat and readlink: don't run these tests everywhere, since not all sites
# will have symbolic links
catch {file link -symbolic $linkfile $gorpfile}
test cmdAH-23.1 {Tcl_FileObjCmd: lstat} -returnCodes error -body {
    file lstat a
} -result {wrong # args: should be "file lstat name varName"}
} -result {could not read "a": no such file or directory}
test cmdAH-23.2 {Tcl_FileObjCmd: lstat} -returnCodes error -body {
    file lstat a b c
} -result {wrong # args: should be "file lstat name varName"}
} -result {wrong # args: should be "file lstat name ?varName?"}
test cmdAH-23.3 {Tcl_FileObjCmd: lstat} -setup {
    unset -nocomplain stat
} -constraints {unix nonPortable} -body {
    file lstat $linkfile stat
    lsort [array names stat]
} -result {atime ctime dev gid ino mode mtime nlink size type uid}
test cmdAH-23.4 {Tcl_FileObjCmd: lstat} -setup {
    unset -nocomplain stat
} -constraints {unix nonPortable} -body {
    file lstat $linkfile stat
    list $stat(nlink) [expr $stat(mode)&0777] $stat(type)
    list $stat(nlink) [expr {$stat(mode) & 0o777}] $stat(type)
} -result {1 511 link}
test cmdAH-23.5 {Tcl_FileObjCmd: lstat errors} {nonPortable} {
    list [catch {file lstat _bogus_ stat} msg] [string tolower $msg] \
	$errorCode
} {1 {could not read "_bogus_": no such file or directory} {POSIX ENOENT {no such file or directory}}}
test cmdAH-23.6 {Tcl_FileObjCmd: lstat errors} -setup {
    unset -nocomplain x
1211
1212
1213
1214
1215
1216
1217
1218

1219
1220
1221
1222
1223
1224
1225
1648
1649
1650
1651
1652
1653
1654

1655
1656
1657
1658
1659
1660
1661
1662







-
+







    set modmtime [file mtime $file $newmtime]
    expr {$newmtime == $modmtime ? 1 : "$newmtime != $modmtime"}
} 1
test cmdAH-24.9 {Tcl_FileObjCmd: mtime touch with non-ascii chars} -setup {
    set oldfile $file
} -constraints unix -body {
    # introduce some non-ascii characters.
    append file \u2022
    append file •
    file delete -force $file
    file rename $oldfile $file
    set mtime [file mtime $file]
    after 1100; # pause a sec to notice change in mtime
    set newmtime [clock seconds]
    set modmtime [file mtime $file $newmtime]
    expr {$newmtime == $modmtime ? 1 : "$newmtime != $modmtime"}
1236
1237
1238
1239
1240
1241
1242
1243

1244
1245
1246
1247
1248
1249
1250
1673
1674
1675
1676
1677
1678
1679

1680
1681
1682
1683
1684
1685
1686
1687







-
+







    expr {$newmtime == $modmtime ? 1 : "$newmtime != $modmtime"}
} -result 1
test cmdAH-24.11 {Tcl_FileObjCmd: mtime touch with non-ascii chars} -setup {
    waitForEvenSecondForFAT
    set oldfile $file
} -constraints win -body {
    # introduce some non-ascii characters.
    append file \u2022
    append file •
    file delete -force $file
    file rename $oldfile $file
    set mtime [file mtime $file]
    after 2100; # pause two secs to notice change in mtime on FAT fs'es
    set newmtime [clock seconds]
    set modmtime [file mtime $file $newmtime]
    expr {$newmtime == $modmtime ? 1 : "$newmtime != $modmtime"}
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
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
1749
1750
1751
1752
1753
1754
1755
1756
1757

1758
1759
1760
1761
1762
1763
1764
1765







-
-
+
+


+
+




-
+


+
+














-
+







} -result "could not get modification time for file \"con\"" -returnCodes error
test cmdAH-24.14.1 {
    Tcl_FileObjCmd: mtime (built-in Windows names with dir path and extension)
} -constraints {win} -body {
    file mtime [file join [temporaryDirectory] CON.txt]
} -match regexp -result {could not (?:get modification time|read)} -returnCodes error

# 3155760000 is 64-bit unix time, Wed Jan 01 00:00:00 GMT 2070:
test cmdAH-24.20.1 {Tcl_FileObjCmd: atime 64-bit time_t, bug [4718b41c56]} -setup {
# 3155760000 is 64-bit Unix time, Wed Jan 01 00:00:00 GMT 2070:
test cmdAH-24.20.1 {Tcl_FileObjCmd: atime 64-bit time_t, bug [4718b41c56]} -constraints {time64bit filetime64bit} -setup {
    set filename [makeFile "" foo.text]
} -body {
    # This test may fail if your system does not have a 64-bit time_t.
    # That is to be expected and is not a problem with Tcl.
    list [file atime $filename 3155760000] [file atime $filename]
} -cleanup {
    removeFile $filename
} -result {3155760000 3155760000}
test cmdAH-24.20.2 {Tcl_FileObjCmd: mtime 64-bit time_t, bug [4718b41c56]} -setup {
test cmdAH-24.20.2 {Tcl_FileObjCmd: mtime 64-bit time_t, bug [4718b41c56]} -constraints {time64bit filetime64bit} -setup {
    set filename [makeFile "" foo.text]
} -body {
    # This test may fail if your system does not have a 64-bit time_t.
    # That is to be expected and is not a problem with Tcl.
    list [file mtime $filename 3155760000] [file mtime $filename]
} -cleanup {
    file delete -force $filename
} -result {3155760000 3155760000}

# owned
test cmdAH-25.1 {Tcl_FileObjCmd: owned} -returnCodes error -body {
    file owned a b
} -result {wrong # args: should be "file owned name"}
test cmdAH-25.2 {Tcl_FileObjCmd: owned} -constraints win -setup {
    set fn $gorpfile
    # prefer temp file to check owner (try to avoid bug [7de2d722bd]):
    if {
	[info exists ::env(TEMP)] && [file isdirectory $::env(TEMP)] &&
        [file dirname $fn] ne [file normalize $::env(TEMP)]
	[file dirname $fn] ne [file normalize $::env(TEMP)]
    } {
	set fn [file join $::env(TEMP)/test-owner-from-tcl.txt]
	set fn [makeFile "data" test-owner-from-tcl.txt $::env(TEMP)]
    }
    # be sure we have really owned this file before trying to check that
    # (avoid dependency on admin with UAC and the setting "System objects:
    # Default owner for objects created by members of the Administrators group"):
1371
1372
1373
1374
1375
1376
1377
1378

1379
1380
1381
1382
1383
1384
1385
1812
1813
1814
1815
1816
1817
1818

1819
1820
1821
1822
1823
1824
1825
1826







-
+







# size
test cmdAH-27.1 {Tcl_FileObjCmd: size} -returnCodes error -body {
    file size a b
} -result {wrong # args: should be "file size name"}
test cmdAH-27.2 {Tcl_FileObjCmd: size} {
    set oldsize [file size $gorpfile]
    set f [open $gorpfile a]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    puts $f "More text"
    close $f
    expr {[file size $gorpfile] - $oldsize}
} {10}
test cmdAH-27.3 {Tcl_FileObjCmd: size} {
    list [catch {file size _bogus_} msg] [string tolower $msg] $errorCode
} {1 {could not read "_bogus_": no such file or directory} {POSIX ENOENT {no such file or directory}}}
1398
1399
1400
1401
1402
1403
1404
1405

1406
1407
1408
1409
1410


1411
1412
1413

1414
1415
1416

1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428

1429
1430
1431
1432
1433


1434
1435
1436
1437
1438
1439
1440
1839
1840
1841
1842
1843
1844
1845

1846
1847
1848
1849


1850
1851
1852
1853

1854
1855
1856

1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868

1869
1870
1871
1872


1873
1874
1875
1876
1877
1878
1879
1880
1881







-
+



-
-
+
+


-
+


-
+











-
+



-
-
+
+







    }
    set res
} -result 0

catch {testsetplatform $platform}
removeFile $gorpfile
set gorpfile [makeFile "Test string" gorp.file]
catch {file attributes $gorpfile -permissions 0765}
catch {file attributes $gorpfile -permissions 0o765}

# stat
test cmdAH-28.1 {Tcl_FileObjCmd: stat} -returnCodes error -body {
    file stat _bogus_
} -result {wrong # args: should be "file stat name varName"}
    file stat
} -result {wrong # args: should be "file stat name ?varName?"}
test cmdAH-28.2 {Tcl_FileObjCmd: stat} -returnCodes error -body {
    file stat _bogus_ a b
} -result {wrong # args: should be "file stat name varName"}
} -result {wrong # args: should be "file stat name ?varName?"}
test cmdAH-28.3 {Tcl_FileObjCmd: stat} -setup {
    unset -nocomplain stat
    set stat(blocks) [set stat(blksize) {}]
    array set stat {blocks {} blksize {}}
} -body {
    file stat $gorpfile stat
    unset stat(blocks) stat(blksize); # Ignore these fields; not always set
    lsort [array names stat]
} -result {atime ctime dev gid ino mode mtime nlink size type uid}
test cmdAH-28.4 {Tcl_FileObjCmd: stat} -setup {
    unset -nocomplain stat
} -body {
    file stat $gorpfile stat
    list $stat(nlink) $stat(size) $stat(type)
} -result {1 12 file}
test cmdAH-28.5 {Tcl_FileObjCmd: stat} -constraints {unix} -setup {
test cmdAH-28.5 {Tcl_FileObjCmd: stat} -constraints {unix notWsl} -setup {
    unset -nocomplain stat
} -body {
    file stat $gorpfile stat
    expr {$stat(mode) & 0o777}
} -result {501}
    format 0o%03o [expr {$stat(mode) & 0o777}]
} -result 0o765
test cmdAH-28.6 {Tcl_FileObjCmd: stat} {
    list [catch {file stat _bogus_ stat} msg] [string tolower $msg] $errorCode
} {1 {could not read "_bogus_": no such file or directory} {POSIX ENOENT {no such file or directory}}}
test cmdAH-28.7 {Tcl_FileObjCmd: stat} -setup {
    unset -nocomplain x
} -returnCodes error -body {
    set x 44
1502
1503
1504
1505
1506
1507
1508










1509
1510
1511
1512
1513
1514
1515
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966







+
+
+
+
+
+
+
+
+
+







	file stat [file join [temporaryDirectory] CON.txt] stat
	set res [lmap elem {atime ctime dev gid ino mode mtime nlink size type uid} {set stat($elem)}]
    } trap {POSIX ENOENT} {} {
	set res {0 0 -1 0 0 8630 0 0 0 characterSpecial 0}
    }
    set res
} -result {0 0 -1 0 0 8630 0 0 0 characterSpecial 0}
test cmdAH-28.14 {Tcl_FileObjCmd: stat} -setup {
    unset -nocomplain stat
} -body {
    file stat $gorpfile stat
    expr {
		[lsort -stride 2 [array get stat]]
		eq
		[lsort -stride 2 [file stat $gorpfile]]
	}
} -result {1}
unset -nocomplain stat

# type
test cmdAH-29.1 {Tcl_FileObjCmd: type} -returnCodes error -body {
    file type a b
} -result {wrong # args: should be "file type name"}
test cmdAH-29.2 {Tcl_FileObjCmd: type} {
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
2012
2013
2014
2015
2016
2017
2018

2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037



2038
2039
2040
2041
2042
2043
2044







-
+


















-
-
-







    }
    set res
} -result "characterSpecial"

# Error conditions
test cmdAH-30.1 {Tcl_FileObjCmd: error conditions} -returnCodes error -body {
    file gorp x
} -result {unknown or ambiguous subcommand "gorp": must be atime, attributes, channels, copy, delete, dirname, executable, exists, extension, isdirectory, isfile, join, link, lstat, mkdir, mtime, nativename, normalize, owned, pathtype, readable, readlink, rename, rootname, separator, size, split, stat, system, tail, tempdir, tempfile, type, volumes, or writable}
} -result {unknown or ambiguous subcommand "gorp": must be atime, attributes, channels, copy, delete, dirname, executable, exists, extension, home, isdirectory, isfile, join, link, lstat, mkdir, mtime, nativename, normalize, owned, pathtype, readable, readlink, rename, rootname, separator, size, split, stat, system, tail, tempdir, tempfile, tildeexpand, type, volumes, or writable}
test cmdAH-30.2 {Tcl_FileObjCmd: error conditions} -returnCodes error -body {
    file ex x
} -match glob -result {unknown or ambiguous subcommand "ex": must be *}
test cmdAH-30.3 {Tcl_FileObjCmd: error conditions} -returnCodes error -body {
    file is x
} -match glob -result {unknown or ambiguous subcommand "is": must be *}
test cmdAH-30.4 {Tcl_FileObjCmd: error conditions} -returnCodes error -body {
    file z x
} -match glob -result {unknown or ambiguous subcommand "z": must be *}
test cmdAH-30.5 {Tcl_FileObjCmd: error conditions} -returnCodes error -body {
    file read x
} -match glob -result {unknown or ambiguous subcommand "read": must be *}
test cmdAH-30.6 {Tcl_FileObjCmd: error conditions} -returnCodes error -body {
    file s x
} -match glob -result {unknown or ambiguous subcommand "s": must be *}
test cmdAH-30.7 {Tcl_FileObjCmd: error conditions} -returnCodes error -body {
    file t x
} -match glob -result {unknown or ambiguous subcommand "t": must be *}
test cmdAH-30.8 {Tcl_FileObjCmd: error conditions} -returnCodes error -body {
    file dirname ~woohgy
} -result {user "woohgy" doesn't exist}

# channels
# In testing 'file channels', we need to make sure that a channel created in
# one interp isn't visible in another.

interp create simpleInterp
interp create -safe safeInterp
1684
1685
1686
1687
1688
1689
1690
1691

1692
1693
1694
1695
1696
1697
1698
2132
2133
2134
2135
2136
2137
2138

2139
2140
2141
2142
2143
2144
2145
2146







-
+







test cmdAH-32.5 {file tempfile - templates} -constraints unix -body {
    set template [file join $dirfile foo]
    close [file tempfile name $template]
    expr {[string match $template* $name] ? "ok" : "$template produced $name"}
} -cleanup {
    catch {file delete $name}
} -result ok
# Not portable; not all unix systems have mkstemps()
# Not portable; not all Unix systems have mkstemps()
test cmdAH-32.6 {file tempfile - templates} -body {
    set template [file join $dirfile foo]
    close [file tempfile name $template.bar]
    expr {[string match $template*.bar $name] ? "ok" :
	  "$template.bar produced $name"}
} -constraints {unix nonPortable} -cleanup {
    catch {file delete $name}
1762
1763
1764
1765
1766
1767
1768
1769

1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
2210
2211
2212
2213
2214
2215
2216

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







-
+














# cleanup
catch {testsetplatform $platform}
unset -nocomplain platform

# Tcl_ForObjCmd is tested in for.test

catch {file attributes $dirfile -permissions 0777}
catch {file attributes $dirfile -permissions 0o777}
removeDirectory $dirfile
removeFile $gorpfile
# No idea how well [removeFile] copes with links...
file delete $linkfile

cd $cmdAHwd

::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/cmdIL.test.

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
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
30
31
32
33
34
35
36
37
38
39
40




-
-
+
+











-
+



+
+
+
+
+
+
+
+
+
+
+
+







# This file contains a collection of tests for the procedures in the file
# tclCmdIL.c. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

# Used for constraining memory leak tests
testConstraint memory [llength [info commands memory]]
proc memusage {} {
    set fd [open /proc/[pid]/statm]
    set line [gets $fd]
    if {[llength $line] != 7} {
	error "Unexpected /proc/pid/statm format"
    }
    set result [lindex $line 5]
    close $fd
    return $result
}
testConstraint hasMemUsage [expr {![catch {memusage}]}]

testConstraint testobj [llength [info commands testobj]]
source [file join [file dirname [info script]] internals.tcl]
namespace import -force ::tcltest::internals::*

test cmdIL-1.1 {Tcl_LsortObjCmd procedure} -returnCodes error -body {
    lsort
} -result {wrong # args: should be "lsort ?-option value ...? list"}
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
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







-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+






+
+
+









-
+







test cmdIL-1.36 {lsort -stride and -index: Bug 2918962} {
    lsort -stride 2 -index {0 1} {
	{{c o d e} 54321} {{b l a h} 94729}
	{{b i g} 12345} {{d e m o} 34512}
    }
} {{{b i g} 12345} {{d e m o} 34512} {{c o d e} 54321} {{b l a h} 94729}}
test cmdIL-1.37 {Tcl_LsortObjCmd procedure, Bug 8e1e31eac0fd6b6c} {
    lsort -ascii [list \0 \x7f \x80 \uffff]
} [list \0 \x7f \x80 \uffff]
    lsort -ascii [list \x00 \x7F \x80 \uFFFF]
} [list \x00 \x7F \x80 \uFFFF]
test cmdIL-1.38 {Tcl_LsortObjCmd procedure, Bug 8e1e31eac0fd6b6c} {
    lsort -ascii -nocase [list \0 \x7f \x80 \uffff]
} [list \0 \x7f \x80 \uffff]
    lsort -ascii -nocase [list \x00 \x7F \x80 \uFFFF]
} [list \x00 \x7F \x80 \uFFFF]
test cmdIL-1.39 {Tcl_LsortObjCmd procedure, Bug 8e1e31eac0fd6b6c} {
    lsort -ascii [list \0 \x7f \x80 \U01ffff \uffff]
} [list \0 \x7f \x80 \uffff \U01ffff]
    lsort -ascii [list \x00 \x7F \x80 \U01ffff \uFFFF]
} [list \x00 \x7F \x80 \uFFFF \U01ffff]
test cmdIL-1.40 {Tcl_LsortObjCmd procedure, Bug 8e1e31eac0fd6b6c} {
    lsort -ascii -nocase [list \0 \x7f \x80 \U01ffff \uffff]
} [list \0 \x7f \x80 \uffff \U01ffff]
    lsort -ascii -nocase [list \x00 \x7F \x80 \U01ffff \uFFFF]
} [list \x00 \x7F \x80 \uFFFF \U01FFFF]
test cmdIL-1.41 {lsort -stride and -index} -body {
    lsort -stride 2 -index -2 {a 2 b 1}
} -returnCodes error -result {index "-2" out of range}
test cmdIL-1.42 {lsort -stride and-index} -body {
    lsort -stride 2 -index -1-1 {a 2 b 1}
} -returnCodes error -result {index "-1-1" out of range}
test cmdIL-1.43 {lsort -stride errors} -returnCodes error -body {
    lsort -stride 4294967296 bar
} -result {list size must be a multiple of the stride length}

# Can't think of any good tests for the MergeSort and MergeLists procedures,
# except a bunch of random lists to sort.

test cmdIL-2.1 {MergeSort and MergeLists procedures} -setup {
    set result {}
    set r 1435753299
    proc rand {} {
	global r
	set r [expr {(16807 * $r) % (0x7fffffff)}]
	set r [expr {(16807 * $r) % (0x7FFFFFFF)}]
    }
} -body {
    for {set i 0} {$i < 150} {incr i} {
	set x {}
	for {set j 0} {$j < $i} {incr j} {
	    lappend x [expr {[rand] & 0xfff}]
	}
392
393
394
395
396
397
398
399

400
401
402

403
404
405

406
407
408

409
410
411
412
413
414
415
407
408
409
410
411
412
413

414
415
416

417
418
419

420
421
422

423
424
425
426
427
428
429
430







-
+


-
+


-
+


-
+







    lsort -dictionary {ABcd aBCd}
} {ABcd aBCd}
test cmdIL-4.23 {DictionaryCompare procedure, case} {
    lsort -dictionary {ABcd AbCd}
} {ABcd AbCd}
test cmdIL-4.24 {DictionaryCompare procedure, international characters} {hasIsoLocale} {
    ::tcltest::set_iso8859_1_locale
    set result [lsort -dictionary "a b c A B C \xe3 \xc4"]
    set result [lsort -dictionary "a b c A B C ã Ä"]
    ::tcltest::restore_locale
    set result
} "A a B b C c \xe3 \xc4"
} "A a B b C c ã Ä"
test cmdIL-4.25 {DictionaryCompare procedure, international characters} {hasIsoLocale} {
    ::tcltest::set_iso8859_1_locale
    set result [lsort -dictionary "a23\xe3 a23\xc5 a23\xe4"]
    set result [lsort -dictionary "a23ã a23Å a23ä"]
    ::tcltest::restore_locale
    set result
} "a23\xe3 a23\xe4 a23\xc5"
} "a23ã a23ä a23Å"
test cmdIL-4.26 {DefaultCompare procedure, signed characters} {
    set l [lsort [list "abc\200" "abc"]]
    set viewlist {}
    foreach s $l {
	set viewelem ""
	set len [string length $s]
	for {set i 0} {$i < $len} {incr i} {
468
469
470
471
472
473
474
475

476
477
478

479
480
481
482
483
484
485
483
484
485
486
487
488
489

490
491
492

493
494
495
496
497
498
499
500







-
+


-
+







test cmdIL-4.35 {SortCompare procedure, -ascii option with -nocase option} {
    lsort -ascii -nocase {d E c B a D35 d300 100 20}
} {100 20 a B c d d300 D35 E}
test cmdIL-4.36 {SortCompare procedure, UTF-8 with -nocase option} {
    scan [lsort -ascii -nocase [list \u101 \u100]] %c%c%c
} {257 32 256}
test cmdIL-4.37 {SortCompare procedure, UTF-8 with -nocase option} {
    scan [lsort -ascii -nocase [list a\u0000a a]] %c%c%c%c%c
    scan [lsort -ascii -nocase [list a\x00a a]] %c%c%c%c%c
} {97 32 97 0 97}
test cmdIL-4.38 {SortCompare procedure, UTF-8 with -nocase option} {
    scan [lsort -ascii -nocase [list a a\u0000a]] %c%c%c%c%c
    scan [lsort -ascii -nocase [list a a\x00a]] %c%c%c%c%c
} {97 32 97 0 97}

test cmdIL-5.1 {lsort with list style index} {
    lsort -ascii -decreasing -index {0 1} {
	{{Jim Alpha} 20000410}
	{{Joe Bravo} 19990320}
	{{Jacky Charlie} 19390911}
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







-
+







} {{dogs {0 1}} {the {0 1 2} lazy} {jumps {30 31 2 33} over} {brown {0 1 2 3 4} fox} {the {0 1 2 3 4 5} quick}}
test cmdIL-5.5 {lsort with list style index and sharing} -body {
    proc test_lsort {l} {
	set n $l
	foreach e $l {lappend n [list [expr {rand()}] $e]}
	lindex [lsort -real -index $l $n] 1 1
    }
    expr srand(1)
    expr {srand(1)}
    test_lsort 0
} -result 0 -cleanup {
    rename test_lsort ""
}
test cmdIL-5.6 {lsort with multiple list-style index options} {
    lsort -index {1 2 3} -index 0 {{a b} {c d} {b e}}
} {{a b} {b e} {c d}}
605
606
607
608
609
610
611
612
613


614
615
616
617
618
619
620
620
621
622
623
624
625
626


627
628
629
630
631
632
633
634
635







-
-
+
+







    }}
} -result {1 {can't set "x": variable is array} a}
test cmdIL-6.12 {lassign command - memory leak testing} -setup {
    unset -nocomplain x y
    set x(x) {}
    set y FAIL
    proc getbytes {} {
        set lines [split [memory info] "\n"]
        lindex [lindex $lines 3] 3
	set lines [split [memory info] "\n"]
	lindex [lindex $lines 3] 3
    }
    proc stress {} {
	global x y
	lassign {} y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y
	catch {lassign {} y y y y y y y y y y y y y y y y y y y y y y y y y x}
	catch {lassign {} x}
    }
712
713
714
715
716
717
718
719
720


721
722
723
724
725
726
727
727
728
729
730
731
732
733


734
735
736
737
738
739
740
741
742







-
-
+
+







	list [catch {$lassign a y x} msg] $msg $y
    }}
} -result {1 {can't set "x": variable is array} a}
test cmdIL-6.24 {lassign command - memory leak testing} -setup {
    set x(x) {}
    set y FAIL
    proc getbytes {} {
        set lines [split [memory info] "\n"]
        lindex [lindex $lines 3] 3
	set lines [split [memory info] "\n"]
	lindex [lindex $lines 3] 3
    }
    proc stress {} {
	global x y
	set lassign lassign
	$lassign {} y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y
	catch {$lassign {} y y y y y y y y y y y y y y y y y y y y y y y y y x}
	catch {$lassign {} x}
736
737
738
739
740
741
742
743

744
745
746
747
748
749

750
751
752
753
754
755












756
757
758
759
760
761
762
751
752
753
754
755
756
757

758
759
760
761
762
763

764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789







-
+





-
+






+
+
+
+
+
+
+
+
+
+
+
+







    expr {$end - $tmp}
} -result 0 -cleanup {
    unset -nocomplain x y i tmp end
    rename getbytes {}
    rename stress {}
}
# Assorted shimmering problems
test cmdIL-6.25 {lassign command - shimmering protection} -body {
test cmdIL-6.25 {lassign command (compiled) - shimmering protection} -body {
    apply {{} {
	set x {a b c}
	list [lassign $x $x y] $x [set $x] $y
    }}
} -result {c {a b c} a b}
test cmdIL-6.26 {lassign command - shimmering protection} -body {
test cmdIL-6.26 {lassign command (uncompiled) - shimmering protection} -body {
    apply {{} {
	set x {a b c}
	set lassign lassign
	list [$lassign $x $x y] $x [set $x] $y
    }}
} -result {c {a b c} a b}
test cmdIL-6.27 {bug-f5e36eb588 - uncompiled lassign on lseq does not bloat memory} -constraints {
    hasMemUsage
} -body {
    set l [lseq 1000000]
    lassign $l x
    set premem [memusage]
    set lassign lassign
    $lassign $l x
    set postmem [memusage]
    expr {($postmem-$premem) < 100}
} -result 1


test cmdIL-7.1 {lreverse command} -body {
    lreverse
} -returnCodes error -result "wrong # args: should be \"lreverse list\""
test cmdIL-7.2 {lreverse command} -body {
    lreverse a b
} -returnCodes error -result "wrong # args: should be \"lreverse list\""
772
773
774
775
776
777
778
779

780
781
782
783
784
785
786
799
800
801
802
803
804
805

806
807
808
809
810
811
812
813







-
+







} {f e {c d} b a}
test cmdIL-7.6 {lreverse command - unshared object [Bug 1672585]} {
    lreverse [set x {1 2 3}][unset x]
} {3 2 1}
test cmdIL-7.7 {lreverse command - empty object [Bug 1876793]} {
    lreverse [list]
} {}
test cmdIL-7.8 {lreverse command - shared intrep [Bug 1675044]} -setup {
test cmdIL-7.8 {lreverse command - shared internalrep [Bug 1675044]} -setup {
    teststringobj set 1 {1 2 3}
    testobj convert 1 list
    testobj duplicate 1 2
    variable x [teststringobj get 1]
    variable y [teststringobj get 2]
    testobj freeallvars
    proc K {a b} {return $a}
838
839
840
841
842
843
844
845

846
847
848
849
850
851
852
853
854
855
856
865
866
867
868
869
870
871

872
873
874
875
876
877
878
879
880
881
882
883







-
+











    lremove {a b c d e} 1 3 1 4 0
} -result {c}

# This belongs in info test, but adding tests there breaks tests
# that compute source file line numbers.
test info-20.6 {Bug 3587651} -setup {
    namespace eval my {namespace eval tcl {namespace eval mathfunc {
        proc demo x {return 42}
	proc demo x {return 42}
    }}}} -body {    namespace eval my {expr {"demo" in [info functions]}}} -cleanup {
    namespace delete my
} -result 1

# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/cmdInfo.test.

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
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








-
-
-
+
+
+










-
+







# Commands covered:  none
#
# This file contains a collection of tests for Tcl_GetCommandInfo,
# Tcl_SetCommandInfo, Tcl_CreateCommand, Tcl_DeleteCommand, and
# Tcl_NameOfCommand.  Sourcing this file into Tcl runs the tests
# and generates output for errors.  No output means no errors were
# found.
#
# Copyright (c) 1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testcmdinfo  [llength [info commands testcmdinfo]]
testConstraint testcmdtoken [llength [info commands testcmdtoken]]

test cmdinfo-1.1 {command procedure and clientData} {testcmdinfo} {
    testcmdinfo create x1
    testcmdinfo get x1
78
79
80
81
82
83
84
85
86


87
88
89
90
91
92
93
78
79
80
81
82
83
84


85
86
87
88
89
90
91
92
93







-
-
+
+








test cmdinfo-5.1 {Names for commands created when inside namespaces} \
	{testcmdtoken} {
    # create namespace cmdInfoNs1
    namespace eval cmdInfoNs1 {}   ;# creates namespace cmdInfoNs1
    # create namespace cmdInfoNs1::cmdInfoNs2 and execute a script in it
    set x [namespace eval cmdInfoNs1::cmdInfoNs2 {
        # the following creates a cmd in the global namespace
        testcmdtoken create testCmd
	# the following creates a cmd in the global namespace
	testcmdtoken create testCmd
    }]
    set y [testcmdtoken name $x]
    rename ::testCmd newTestCmd
    lappend y {*}[testcmdtoken name $x]
} {testCmd ::testCmd newTestCmd ::newTestCmd}

test cmdinfo-6.1 {Names for commands created when outside namespaces} \

Changes to tests/cmdMZ.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# The tests in this file cover the procedures in tclCmdMZ.c.
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
51
52
53
54
55
56
57
58
59


60
61
62

63
64
65
66
67
68
69
51
52
53
54
55
56
57


58
59
60
61

62
63
64
65
66
67
68
69







-
-
+
+


-
+







} -match glob -result {?*}
test cmdMZ-1.4 {Tcl_PwdObjCmd: failure} -setup {
    set cwd [pwd]
    set foodir [file join [temporaryDirectory] foo]
    file delete -force $foodir
    file mkdir $foodir
    cd $foodir
} -constraints {unix nonPortable} -body {
    # This test fails on various unix platforms (eg Linux) where permissions
} -constraints {Unix nonPortable} -body {
    # This test fails on various Unix platforms (eg Linux) where permissions
    # caching causes this to fail. The caching is strictly incorrect, but we
    # have no control over that.
    file attr . -permissions 000
    file attr . -permissions 0
    pwd
} -returnCodes error -cleanup {
    cd $cwd
    file delete -force $foodir
} -result {error getting working directory name: permission denied}

# The tests for Tcl_RegexpObjCmd, Tcl_RegsubObjCmd are in regexp.test
154
155
156
157
158
159
160
161

162
163
164
165
166
167
168
154
155
156
157
158
159
160

161
162
163
164
165
166
167
168







-
+







    while executing
"return -level 0 -code error"} -errorline 1 -errorstack * -level 0}}
test cmdMZ-return-2.11 {return option handling} {
    list [catch {return -level 0 -code break} -> foo] [dictSort $foo]
} {3 {-code 3 -level 0}}
test cmdMZ-return-2.12 {return option handling} -body {
    return -level 0 -code error -options {-code ok}
} -returnCodes ok -result {}
} -result {}
test cmdMZ-return-2.13 {return option handling} -body {
    return -level 0 -code error -options {-code err}
} -returnCodes error -match glob -result {bad completion code "err": must be ok, error, return, break, continue*, or an integer}
test cmdMZ-return-2.14 {return option handling} -body {
    return -level 0 -code error -options {-code foo -options {-code break}}
} -returnCodes break -result {}
test cmdMZ-return-2.15 {return opton handling} {
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
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







-
-
-
-
-
+
+
+
+
+




-
-
+
+

-
+



-
+


-
-
-
+
+
+








+

-
-
-
-
+
+
+
+
+
+
+







    split {}
} {}
test cmdMZ-4.9 {Tcl_SplitObjCmd: basic split commands} {
    split {   }
} {{} {} {} {}}
test cmdMZ-4.10 {Tcl_SplitObjCmd: basic split commands} {
    apply {{} {
        set x {}
        foreach f [split {]\n} {}] {
            append x $f
        }
        return $x
	set x {}
	foreach f [split {]\n} {}] {
	    append x $f
	}
	return $x
    }}
} {]\n}
test cmdMZ-4.11 {Tcl_SplitObjCmd: basic split commands} {
    apply {{} {
        set x ab\000c
        set y [split $x {}]
	set x ab\x00c
	set y [split $x {}]
	binary scan $y c* z
        return $z
	return $z
    }}
} {97 32 98 32 0 32 99}
test cmdMZ-4.12 {Tcl_SplitObjCmd: basic split commands} {
    split "a0ab1b2bbb3\000c4" ab\000c
    split "a0ab1b2bbb3\x00c4" ab\x00c
} {{} 0 {} 1 2 {} {} 3 {} 4}
test cmdMZ-4.13 {Tcl_SplitObjCmd: basic split commands} {
    # if not UTF-8 aware, result is "a {} {} b qw\xe5 {} N wq"
    split "a\u4e4eb qw\u5e4e\x4e wq" " \u4e4e"
} "a b qw\u5e4eN wq"
    # if not UTF-8 aware, result is "a {} {} b qwå {} N wq"
    split "a乎b qw幎N wq" " 乎"
} "a b qw幎N wq"

# The tests for Tcl_StringObjCmd are in string.test
# The tests for Tcl_SubstObjCmd are in subst.test
# The tests for Tcl_SwitchObjCmd are in switch.test

# todo: rewrite this if monotonic clock is provided resp. command "after"
# gets microsecond accuracy (RFE [fdfbd5e10] gets merged):
proc _nrt_sleep {msec} {
    set stime [clock microseconds]
    set usec [expr {$msec * 1000}]
    set stime [clock microseconds]
    while {abs([clock microseconds] - $stime) < $usec} {
      # don't use after 0 unless it's NRT-capable, so yes - busy-wait (but it's more precise):
      # after 0
    set etime [expr {$stime + $usec}]
    while {[set tm [clock microseconds]] < $etime} {
	# don't use after 0 unless it's NRT-capable, so yes - busy-wait (but it's more precise):
	# after 0
	if {$tm < $stime} { # avoid too long delays by backwards time jumps, simply skip test
	    tcltest::Skip "time-jump?"
	}
    }
}
_nrt_sleep 0; # warm up (clock, compile, etc)

test cmdMZ-5.1 {Tcl_TimeObjCmd: basic format of command} -body {
    time
} -returnCodes error -result {wrong # args: should be "time command ?count?"}
397
398
399
400
401
402
403
404

405
406



407
408
409
410
411
412
413
401
402
403
404
405
406
407

408
409
410
411
412
413
414
415
416
417
418
419
420







-
+


+
+
+







} {1 {missing close-brace}}
test cmdMZ-6.5a {Tcl_TimeRateObjCmd: result format and one iteration} {
    regexp {^\d+(?:\.\d+)? \ws/# 1 # \d+(?:\.\d+)? #/sec \d+(?:\.\d+)? net-ms$} [timerate {} 0]
} 1
test cmdMZ-6.5b {Tcl_TimeRateObjCmd: result format without iterations} {
    regexp {^0 \ws/# 0 # 0 #/sec 0 net-ms$} [timerate {} 0 0]
} 1
test cmdMZ-6.6 {Tcl_TimeRateObjCmd: slower commands take longer, but it remains almost the same time of measument} -body {
test cmdMZ-6.6 {Tcl_TimeRateObjCmd: slower commands take longer, but it remains almost the same time of measurement} -body {
    set m1 [timerate {_nrt_sleep 0.01} 50]
    set m2 [timerate {_nrt_sleep 1.00} 50]
    if {[testConstraint valgrind] && ([lindex $m1 0] >= 100 || [lindex $m1 2] <= 500)} {
	tcltest::Skip "too-slow-by-valgrind"
    }
    list [list \
	[expr {[lindex $m1 0] < [lindex $m2 0]}] \
	[expr {[lindex $m1 0] < 100}] \
	[expr {[lindex $m2 0] > 100}] \
	[expr {[lindex $m1 2] > 500}] \
	[expr {[lindex $m2 2] < 500}] \
	[expr {[lindex $m1 4] > 10000}] \

Changes to tests/compExpr-old.test.

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
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
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
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








-
-
+
+




















-
+

-
+









-
+

-
+

-
+





-
+

-
+









-
+

-
+

-
+











-
-
-












-
-
-
-
-
-
+
+
+
+
+
+







# Commands covered: expr
#
# This file contains the original set of tests for the compilation (and
# indirectly execution) of Tcl's expr command. A new set of tests covering
# the new implementation are in the files "parseExpr.test" and
# "compExpr.test". Sourcing this file into Tcl runs the tests and generates
# output for errors. No output means no errors were found.
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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

# Big test for correct ordering of data in [expr]

proc testIEEE {} {
    variable ieeeValues
    binary scan [binary format dd -1.0 1.0] c* c
    switch -exact -- $c {
	{0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
	    # little endian
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\xFF d \
		ieeeValues(-Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\xBF d \
		ieeeValues(-Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
		ieeeValues(-Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x3F d \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \
		ieeeValues(+Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF8\x7F d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 1
	    return 1
	}
	{-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
	    binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \xFF\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Infinity)
	    binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \xBF\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Normal)
	    binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Subnormal)
	    binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x3F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Normal)
	    binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x7F\xF8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 0
	}
    }
}
testConstraint ieeeFloatingPoint [testIEEE]

testConstraint longIs32bit [expr {$tcl_platform(wordSize) == 4}]
testConstraint longIs64bit [expr {$tcl_platform(wordSize) == 8}]

# procedures used below

proc put_hello_char {c} {
    global a
    append a [format %c $c]
    return $c
}
proc hello_world {} {
    global a
    set a ""
    set L1 [set l0 [set h_1 [set q 0]]]
    for {put_hello_char [expr [put_hello_char [expr [set h 7]*10+2]]+29]} {$l0?[put_hello_char $l0]
        :!$h_1} {put_hello_char $ll;expr {$L1==2?[set ll [expr 32+0-0+[set bar 0]]]:0}} {expr {[incr L1]==[expr 1+([string length "abc"]-[string length "abc"])]
        ?[set ll [set l0 [expr 54<<1]]]:$ll==108&&$L1<3?
        [incr ll [expr 1|1<<1]; set ll $ll; set ll $ll; set ll $ll; set ll $ll; set l0 [expr ([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])]; set l0; set l0 $l0; set l0; set l0]:$L1==4&&$ll==32?[set ll [expr 19+$h1+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])+[set foo [expr ([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])]]]]
        :[set q [expr $q-$h1+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])]]};expr {$L1==5?[incr ll -8; set ll $ll; set ll]:$q&&$h1&&1};expr {$L1==4+2
        ?[incr ll 3]:[expr ([string length "abc"]-[string length "abc"])+1]};expr {$ll==($h<<4)+2+0&&$L1!=6?[incr ll -6]:[set h1 [expr 100+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])]]}
        expr {$L1!=1<<3?[incr q [expr ([string length "abc"]-[string length "abc"])-1]]:[set h_1 [set ll $h1]]}
	:!$h_1} {put_hello_char $ll;expr {$L1==2?[set ll [expr 32+0-0+[set bar 0]]]:0}} {expr {[incr L1]==[expr 1+([string length "abc"]-[string length "abc"])]
	?[set ll [set l0 [expr 54<<1]]]:$ll==108&&$L1<3?
	[incr ll [expr 1|1<<1]; set ll $ll; set ll $ll; set ll $ll; set ll $ll; set l0 [expr ([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])]; set l0; set l0 $l0; set l0; set l0]:$L1==4&&$ll==32?[set ll [expr 19+$h1+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])+[set foo [expr ([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])]]]]
	:[set q [expr $q-$h1+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])]]};expr {$L1==5?[incr ll -8; set ll $ll; set ll]:$q&&$h1&&1};expr {$L1==4+2
	?[incr ll 3]:[expr ([string length "abc"]-[string length "abc"])+1]};expr {$ll==($h<<4)+2+0&&$L1!=6?[incr ll -6]:[set h1 [expr 100+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])]]}
	expr {$L1!=1<<3?[incr q [expr ([string length "abc"]-[string length "abc"])-1]]:[set h_1 [set ll $h1]]}
    }
    set a
}

proc 12days {a b c} {
    global xxx
    expr {1<$a?[expr {$a<3?[12days -79 -13 [string range $c [12days -87 \
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
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







-
+


-
+




















-
+


-
+







    expr 2***3|6
} -returnCodes error -match glob -result *
test compExpr-old-6.8 {CompileBitXorExpr: error compiling bitxor arm} -body {
    expr 2^x
} -returnCodes error -match glob -result *
test compExpr-old-6.9 {CompileBitXorExpr: runtime error in bitxor arm} {
    list [catch {expr {24.0^3}} msg] $msg
} {1 {can't use floating-point value "24.0" as operand of "^"}}
} {1 {cannot use floating-point value "24.0" as left operand of "^"}}
test compExpr-old-6.10 {CompileBitXorExpr: runtime error in bitxor arm} {
    list [catch {expr {"a"^"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "^"}}
} {1 {cannot use non-numeric string "a" as left operand of "^"}}

test compExpr-old-7.1 {CompileBitAndExpr: just equality expr} {expr 3==2} 0
test compExpr-old-7.2 {CompileBitAndExpr: just equality expr} {expr 2.0==2} 1
test compExpr-old-7.3 {CompileBitAndExpr: just equality expr} {expr 3.2!=2.2} 1
test compExpr-old-7.4 {CompileBitAndExpr: just equality expr} {expr {"abc" == "abd"}} 0
test compExpr-old-7.5 {CompileBitAndExpr: error in equality expr} -body {
    expr x==3
} -returnCodes error -match glob -result *
test compExpr-old-7.6 {CompileBitAndExpr: simple bitand exprs} {expr 7&0x13} 3
test compExpr-old-7.7 {CompileBitAndExpr: simple bitand exprs} {expr 0xf2&0x53} 82
test compExpr-old-7.8 {CompileBitAndExpr: simple bitand exprs} {expr 3&6} 2
test compExpr-old-7.9 {CompileBitAndExpr: simple bitand exprs} {expr -1&-7} -7
test compExpr-old-7.10 {CompileBitAndExpr: error compiling bitand arm} -body {
    expr 2***3&6
} -returnCodes error -match glob -result *
test compExpr-old-7.11 {CompileBitAndExpr: error compiling bitand arm} -body {
    expr 2&x
} -returnCodes error -match glob -result *
test compExpr-old-7.12 {CompileBitAndExpr: runtime error in bitand arm} {
    list [catch {expr {24.0&3}} msg] $msg
} {1 {can't use floating-point value "24.0" as operand of "&"}}
} {1 {cannot use floating-point value "24.0" as left operand of "&"}}
test compExpr-old-7.13 {CompileBitAndExpr: runtime error in bitand arm} {
    list [catch {expr {"a"&"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "&"}}
} {1 {cannot use non-numeric string "a" as left operand of "&"}}

test compExpr-old-8.1 {CompileEqualityExpr: just relational expr} {expr 3>=2} 1
test compExpr-old-8.2 {CompileEqualityExpr: just relational expr} {expr 2<=2.1} 1
test compExpr-old-8.3 {CompileEqualityExpr: just relational expr} {expr 3.2>"2.2"} 1
test compExpr-old-8.4 {CompileEqualityExpr: just relational expr} {expr {"0y"<"0x12"}} 0
test compExpr-old-8.5 {CompileEqualityExpr: error in relational expr} -body {
    expr x>3
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
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







-
+


-
+


















-
+


-
+







    expr 2***3>>6
} -returnCodes error -match glob -result *
test compExpr-old-10.9 {CompileShiftExpr: error compiling shift arm} -body {
    expr 2<<x
} -returnCodes error -match glob -result *
test compExpr-old-10.10 {CompileShiftExpr: runtime error} {
    list [catch {expr {24.0>>43}} msg] $msg
} {1 {can't use floating-point value "24.0" as operand of ">>"}}
} {1 {cannot use floating-point value "24.0" as left operand of ">>"}}
test compExpr-old-10.11 {CompileShiftExpr: runtime error} {
    list [catch {expr {"a"<<"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "<<"}}
} {1 {cannot use non-numeric string "a" as left operand of "<<"}}

test compExpr-old-11.1 {CompileAddExpr: just multiply expr} {expr 4*-2} -8
test compExpr-old-11.2 {CompileAddExpr: just multiply expr} {expr 0xff%2} 1
test compExpr-old-11.3 {CompileAddExpr: just multiply expr} {expr -1/2} -1
test compExpr-old-11.4 {CompileAddExpr: just multiply expr} {expr 7891%0o123} 6
test compExpr-old-11.5 {CompileAddExpr: error in multiply expr} -body {
    expr x*3
} -returnCodes error -match glob -result *
test compExpr-old-11.6 {CompileAddExpr: simple add exprs} {expr 0xff++0x3} 258
test compExpr-old-11.7 {CompileAddExpr: simple add exprs} {expr -0xf2--0x3} -239
test compExpr-old-11.8 {CompileAddExpr: error compiling add arm} -body {
    expr 2***3+6
} -returnCodes error -match glob -result *
test compExpr-old-11.9 {CompileAddExpr: error compiling add arm} -body {
    expr 2-x
} -returnCodes error -match glob -result *
test compExpr-old-11.10 {CompileAddExpr: runtime error} {
    list [catch {expr {24.0+"xx"}} msg] $msg
} {1 {can't use non-numeric string "xx" as operand of "+"}}
} {1 {cannot use non-numeric string "xx" as right operand of "+"}}
test compExpr-old-11.11 {CompileAddExpr: runtime error} {
    list [catch {expr {"a"-"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "-"}}
} {1 {cannot use non-numeric string "a" as left operand of "-"}}
test compExpr-old-11.12 {CompileAddExpr: runtime error} {
    list [catch {expr {3/0}} msg] $msg
} {1 {divide by zero}}
test compExpr-old-11.13a {CompileAddExpr: runtime error} ieeeFloatingPoint {
    list [catch {expr {2.3/0.0}} msg] $msg
} {0 Inf}
test compExpr-old-11.13b {CompileAddExpr: runtime error} !ieeeFloatingPoint {
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
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







-
+


-
+

















-
+


-
+







    expr 2*3%%6
} -returnCodes error -match glob -result *
test compExpr-old-12.9 {CompileMultiplyExpr: error compiling multiply arm} -body {
    expr 2*x
} -returnCodes error -match glob -result *
test compExpr-old-12.10 {CompileMultiplyExpr: runtime error} {
    list [catch {expr {24.0*"xx"}} msg] $msg
} {1 {can't use non-numeric string "xx" as operand of "*"}}
} {1 {cannot use non-numeric string "xx" as right operand of "*"}}
test compExpr-old-12.11 {CompileMultiplyExpr: runtime error} {
    list [catch {expr {"a"/"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "/"}}
} {1 {cannot use non-numeric string "a" as left operand of "/"}}

test compExpr-old-13.1 {CompileUnaryExpr: unary exprs} {expr -0xff} -255
test compExpr-old-13.2 {CompileUnaryExpr: unary exprs} {expr +0o00123} 83
test compExpr-old-13.3 {CompileUnaryExpr: unary exprs} {expr +--++36} 36
test compExpr-old-13.4 {CompileUnaryExpr: unary exprs} {expr !2} 0
test compExpr-old-13.5 {CompileUnaryExpr: unary exprs} {expr +--+-62.0} -62.0
test compExpr-old-13.6 {CompileUnaryExpr: unary exprs} {expr !0.0} 1
test compExpr-old-13.7 {CompileUnaryExpr: unary exprs} {expr !0xef} 0
test compExpr-old-13.8 {CompileUnaryExpr: error compiling unary expr} -body {
    expr ~x
} -returnCodes error -match glob -result *
test compExpr-old-13.9 {CompileUnaryExpr: error compiling unary expr} -body {
    expr !1.x
    set msg
} -returnCodes error -match glob -result *
test compExpr-old-13.10 {CompileUnaryExpr: runtime error} {
    list [catch {expr {~"xx"}} msg] $msg
} {1 {can't use non-numeric string "xx" as operand of "~"}}
} {1 {cannot use non-numeric string "xx" as operand of "~"}}
test compExpr-old-13.11 {CompileUnaryExpr: runtime error} {
    list [catch {expr ~4.0} msg] $msg
} {1 {can't use floating-point value "4.0" as operand of "~"}}
} {1 {cannot use floating-point value "4.0" as operand of "~"}}
test compExpr-old-13.12 {CompileUnaryExpr: just primary expr} {expr 0x123} 291
test compExpr-old-13.13 {CompileUnaryExpr: just primary expr} {
    set a 27
    expr $a
} 27
test compExpr-old-13.14 {CompileUnaryExpr: just primary expr} {
    expr double(27)
591
592
593
594
595
596
597
598

599
600
601
602
603
604
605
588
589
590
591
592
593
594

595
596
597
598
599
600
601
602







-
+







} -returnCodes error -match glob -result *

test compExpr-old-16.1 {GetToken: checks whether integer token starting with "0x" (e.g., "0x$") is invalid} {
    catch {unset a}
    set a(VALUE) ff15
    set i 123
    if {[expr 0x$a(VALUE)] & 16} {
        set i {}
	set i {}
    }
    set i
} {}
test compExpr-old-16.2 {GetToken: check for string literal in braces} {
    expr {{1}}
} {1}

622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639











640
641
642
643
644
645
646
647
648
649
619
620
621
622
623
624
625











626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646







-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+










} 11

# Check "expr" and interpreter result object resetting before appending
# an error msg during evaluation of exprs not in {}s

test compExpr-old-19.1 {expr and interpreter result object resetting} {
    proc p {} {
        set t  10.0
        set x  2.0
        set dx 0.2
        set f  {$dx-$x/10}
        set g  {-$x/5}
        set center 1.0
        set x  [expr $x-$center]
        set dx [expr $dx+$g]
        set x  [expr $x+$f+$center]
        set x  [expr $x+$f+$center]
        set y  [expr round($x)]
	set t  10.0
	set x  2.0
	set dx 0.2
	set f  {$dx-$x/10}
	set g  {-$x/5}
	set center 1.0
	set x  [expr $x-$center]
	set dx [expr $dx+$g]
	set x  [expr $x+$f+$center]
	set x  [expr $x+$f+$center]
	set y  [expr round($x)]
    }
    p
} 3

# cleanup
if {[info exists a]} {
    unset a
}
::tcltest::cleanupTests
return

Changes to tests/compExpr.test.

1
2
3
4
5
6


7
8
9
10
11
12
13
1
2
3
4


5
6
7
8
9
10
11
12
13




-
-
+
+







# This file contains a collection of tests for the procedures in the file
# tclCompExpr.c.  Sourcing this file into Tcl runs the tests and generates
# output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
303
304
305
306
307
308
309
310

311
312
313
314
315
316
317
318
319

320
321
322
323
324
325
326
303
304
305
306
307
308
309

310
311
312
313
314
315
316
317
318

319
320
321
322
323
324
325
326







-
+








-
+







    expr {0? 42 : $a}
} -result 83
test compExpr-4.9 {CompileCondExpr procedure, error in "false" clause} {
    list [catch {expr {1? 15 : [expr *2]}} msg] $msg
} {0 15}

test compExpr-5.1 {CompileMathFuncCall procedure, math function found} {
    format %.6g [expr atan2(1.0, 2.0)]
    format %.6g [expr {atan2(1.0, 2.0)}]
} 0.463648
test compExpr-5.2 {CompileMathFuncCall procedure, math function not found} -body {
    expr {do_it()}
} -returnCodes error -match glob -result {* "*do_it"}
test compExpr-5.5 {CompileMathFuncCall procedure, not enough arguments} -body {
    expr {atan2(1.0)}
} -returnCodes error -match glob -result {not enough arguments for math function*}
test compExpr-5.6 {CompileMathFuncCall procedure, complex argument} {
    format %.6g [expr pow(2.1, 27.5-(24.4*(5%2)))]
    format %.6g [expr {pow(2.1, 27.5-(24.4*(5%2)))}]
} 9.97424
test compExpr-5.7 {CompileMathFuncCall procedure, error in argument} -body {
    expr {sinh(2.*)}
} -returnCodes error -match glob -result *
test compExpr-5.8 {CompileMathFuncCall procedure, too many arguments} -body {
    expr {sinh(2.0, 3.0)}
} -returnCodes error -match glob -result {too many arguments for math function*}
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
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







-
-
+
+





-
-
-
+
+
+






-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



+







} -cleanup {
    unset end i tmp
    rename getbytes {}
} -result 0

test compExpr-7.2 {[Bug 1869989]: expr parser memleak} -constraints memory -setup {
    proc getbytes {} {
        set lines [split [memory info] \n]
        lindex $lines 3 3
	set lines [split [memory info] \n]
	lindex $lines 3 3
    }
} -body {
    set i 5
    set end [getbytes]
    while {[incr i -1]} {
        expr ${i}000
        set tmp $end
        set end [getbytes]
	expr ${i}000
	set tmp $end
	set end [getbytes]
    }
    set leakedBytes [expr {$end - $tmp}]
} -cleanup {
    unset end i tmp
    rename getbytes {}
} -result 0


proc extract {opcodes descriptor} {
    set instructions [dict values [dict get $descriptor instructions]]
    return [lmap i $instructions {
	if {[lindex $i 0] in $opcodes} {string cat $i} else continue
    }]
}

test compExpr-8.1 {TIP 582: expression comments} -setup {} -body {
    extract {loadStk add} [tcl::unsupported::getbytecode script {expr {
	$abc
	# + $def
	+ $ghi
    }}]
} -result {loadStk loadStk add}
test compExpr-8.2 {TIP 582: expression comments} -setup {} -body {
    extract {loadStk add} [tcl::unsupported::getbytecode script {expr {
	$abc
	# + $def
	# + $ghi }}]
} -result loadStk
test compExpr-8.3 {TIP 582: expression comments} -setup {} -body {
    extract {loadStk add} [tcl::unsupported::getbytecode script {expr {
	$abc
	# + $def\
	+ $ghi
    }}]
} -result loadStk
test compExpr-8.4 {TIP 582: expression comments} -setup {} -body {
    extract {loadStk add} [tcl::unsupported::getbytecode script {expr {
	$abc
	# + $def\\
	+ $ghi
    }}]
} -result {loadStk loadStk add}

# cleanup
catch {unset a}
catch {unset b}
catch {rename extract ""}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:

Changes to tests/compile.test.

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
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
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
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







-
-
+
+











-
+




















-
-
-
-
-
-
-
+
+
+
+
+
+
+


















-
-
+
+













-
-
+
+








-
-
+
+









-
-
+
+







# This file contains tests for the files tclCompile.c, tclCompCmds.c and
# tclLiteral.c
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1997 by Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint exec       [llength [info commands exec]]
testConstraint memory     [llength [info commands memory]]
testConstraint testevalex [llength [info commands testevalex]]

# The following tests are very incomplete, although the rest of the
# test suite covers this file fairly well.

catch {rename p ""}
catch {namespace delete test_ns_compile}
catch {unset x}
catch {unset y}
catch {unset a}

test compile-1.1 {TclCompileString: look up cmds in proc ns, not current ns} -setup {
    catch {namespace delete test_ns_compile}
    catch {unset x}
} -body {
    set x 123
    namespace eval test_ns_compile {
        proc set {args} {
            global x
            lappend x test_ns_compile::set
        }
        proc p {} {
            set 0
        }
	proc set {args} {
	    global x
	    lappend x test_ns_compile::set
	}
	proc p {} {
	    set 0
	}
    }
    list [test_ns_compile::p] [set x]
} -result {{123 test_ns_compile::set} {123 test_ns_compile::set}}
test compile-1.2 {TclCompileString, error result is reset if TclGetLong determines word isn't an integer} {
    proc p {x} {info commands 3m}
    list [catch {p} msg] $msg
} {1 {wrong # args: should be "p x"}}

test compile-2.1 {TclCompileDollarVar: global scalar name with ::s} -setup {
    catch {unset x}
} -body {
    set x 123
    list $::x [expr {"x" in [info globals]}]
} -result {123 1}
test compile-2.2 {TclCompileDollarVar: global scalar name with ::s} -setup {
    catch {unset y}
} -body {
    proc p {} {
        set ::y 789
        return $::y
	set ::y 789
	return $::y
    }
    list [p] $::y [expr {"y" in [info globals]}]
} -result {789 789 1}
test compile-2.3 {TclCompileDollarVar: global array name with ::s} -setup {
    catch {unset a}
} -body {
    set ::a(1) 2
    list $::a(1) [set ::a($::a(1)) 3] $::a(2) [expr {"a" in [info globals]}]
} -result {2 3 3 1}
test compile-2.4 {TclCompileDollarVar: global scalar name with ::s} -setup {
    catch {unset a}
} -body {
    proc p {} {
        set ::a(1) 1
        return $::a($::a(1))
	set ::a(1) 1
	return $::a($::a(1))
    }
    list [p] $::a(1) [expr {"a" in [info globals]}]
} -result {1 1 1}
test compile-2.5 {TclCompileDollarVar: global array, called as ${arrName(0)}} -setup {
    catch {unset a}
} -body {
    proc p {} {
	global a
        set a(1) 1
        return ${a(1)}$::a(1)$a(1)
	set a(1) 1
	return ${a(1)}$::a(1)$a(1)
    }
    list [p] $::a(1) [expr {"a" in [info globals]}]
} -result {111 1 1}

test compile-3.1 {TclCompileCatchCmd: only catch cmds with scalar vars are compiled inline} -setup {
    catch {unset a}
} -body {
    set a(1) xyzzyx
    proc p {} {
        global a
        catch {set x 123} a(1)
	global a
	catch {set x 123} a(1)
    }
    list [p] $a(1)
} -result {0 123}
test compile-3.2 {TclCompileCatchCmd: non-local variables} {
    set ::foo 1
    proc catch-test {} {
	catch {set x 3} ::foo
200
201
202
203
204
205
206
207

208
209
210
211
212
213
214
200
201
202
203
204
205
206

207
208
209
210
211
212
213
214







-
+







    -cleanup {namespace delete catchtest}
}

test compile-4.1 {TclCompileForCmd: command substituted test expression} {
    set i 0
    set j 0
    # Should be "forever"
    for {} [expr $i < 3] {} {
    for {} [expr {$i < 3}] {} {
	set j [incr i]
	if {$j > 3} break
    }
    set j
} {4}

test compile-5.1 {TclCompileForeachCmd: exception stack} {
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
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







-
-
+
+


-
+






-
-
+
+








-
-
-
+
+
+









-
+







-
+


-
+







-
-
-
-
+
+
+
+








test compile-6.1 {TclCompileSetCmd: global scalar names with ::s} -setup {
    catch {unset x}
    catch {unset y}
} -body {
    set x 123
    proc p {} {
        set ::y 789
        return $::y
	set ::y 789
	return $::y
    }
    list $::x [expr {"x" in [info globals]}] \
         [p] $::y [expr {"y" in [info globals]}]
	 [p] $::y [expr {"y" in [info globals]}]
} -result {123 1 789 789 1}
test compile-6.2 {TclCompileSetCmd: global array names with ::s} -setup {
    catch {unset a}
} -body {
    set ::a(1) 2
    proc p {} {
        set ::a(1) 1
        return $::a($::a(1))
	set ::a(1) 1
	return $::a($::a(1))
    }
    list $::a(1) [p] [set ::a($::a(1)) 3] $::a(1) [expr {"a" in [info globals]}]
} -result {2 1 3 3 1}
test compile-6.3 {TclCompileSetCmd: namespace var names with ::s} -setup {
    catch {namespace delete test_ns_compile}
    catch {unset x}
} -body {
    namespace eval test_ns_compile {
        variable v hello
        variable arr
        set ::x $::test_ns_compile::v
	variable v hello
	variable arr
	set ::x $::test_ns_compile::v
	set ::test_ns_compile::arr(1) 123
    }
    list $::x $::test_ns_compile::arr(1)
} -result {hello 123}

test compile-7.1 {TclCompileWhileCmd: command substituted test expression} {
    set i 0
    set j 0
    # Should be "forever"
    while [expr $i < 3] {
    while [expr {$i < 3}] {
	set j [incr i]
	if {$j > 3} break
    }
    set j
} {4}

test compile-8.1 {CollectArgInfo: binary data} {
    list [catch "string length \000foo" msg] $msg
    list [catch "string length \x00foo" msg] $msg
} {0 4}
test compile-8.2 {CollectArgInfo: binary data} {
    list [catch "string length foo\000" msg] $msg
    list [catch "string length foo\x00" msg] $msg
} {0 4}
test compile-8.3 {CollectArgInfo: handle "]" at end of command properly} {
    set x ]
} {]}

test compile-9.1 {UpdateStringOfByteCode: called for duplicate of compiled empty object} {
    proc p {} {
        set x {}
        eval $x
        append x { }
        eval $x
	set x {}
	eval $x
	append x { }
	eval $x
    }
    p
} {}

test compile-10.1 {BLACKBOX: exception stack overflow} {
    set x {{0}}
    set y 0
333
334
335
336
337
338
339
340

341
342
343
344
345
346
347
333
334
335
336
337
338
339

340
341
342
343
344
345
346
347







-
+







test compile-11.5 {Tcl_Append*: ensure Tcl_ResetResult is used properly} -body {
    apply {{} { set r [list foobar] ; incr foo bar baz}}
} -returnCodes error -result {wrong # args: should be "incr varName ?increment?"}
test compile-11.6 {Tcl_Append*: ensure Tcl_ResetResult is used properly} -body {
    apply {{} { set r [list foobar] ; incr}}
} -returnCodes error -result {wrong # args: should be "incr varName ?increment?"}
test compile-11.7 {Tcl_Append*: ensure Tcl_ResetResult is used properly} -body {
    apply {{} { set r [list foobar] ; expr !a }}
    apply {{} { set r [list foobar] ; expr [concat !a] }}
} -returnCodes error -match glob -result *
test compile-11.8 {Tcl_Append*: ensure Tcl_ResetResult is used properly} -body {
    apply {{} { set r [list foobar] ; expr {!a} }}
} -returnCodes error -match glob -result *
test compile-11.9 {Tcl_Append*: ensure Tcl_ResetResult is used properly} -body {
    apply {{} { set r [list foobar] ; llength "\{" }}
    list [catch {p} msg] $msg
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
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







+
+
+
+
+
+
+
+






-
+

-
+



















-
+







	    append code "\}$e"
	}
	#puts [format "%% %.40s ... %d bytes" $code [string length $code]]
	return $code
    }}
}
test compile-13.2 {TclCompileScript: testing expected nested scripts compilation} -setup {
    # dynamic constraint - ensure the stack is large enough on this box for this test:
    if {
      [testConstraint unix] &&
      ![catch { exec sh -c {ulimit -s} } stsz] &&
      $stsz ne "unlimited" && $stsz <= 2048
    } {
	tcltest::Skip "too small stack limit ($stsz <= 2048)"
    }
    _ti_gencode
    interp recursionlimit ti [expr {10000+50}]
    ti eval {set result {}}
} -body {
    # Test different compilation variants (instructions evalStk, invokeStk, etc),
    # with 1500 (1000 in debug) nested scripts (bodies). If you get SO/SF exceptions on some low-stack
    # boxes or systems, please don't decrease it (either provide a constraint)
    # boxes or systems, please don't decrease it (either provide new or extend a constraint above)
    ti eval {foreach cmd {eval "if 1" try catch} {
	set c [gencode [expr {![::tcl::pkgconfig get debug] ? 1500 : 1000}] $cmd]
	set c [gencode [expr {[tcl::build-info debug] ? 1500 : 1000}] $cmd]
	if 1 $c
    }}
    ti eval {set result}
} -result {1 1 1 1}
test compile-13.3 {TclCompileScript: testing check of max depth by nested scripts compilation} -setup {
    _ti_gencode
    interp recursionlimit ti 100
    ti eval {set result {}}
} -body {
    # Test different compilation variants (instructions evalStk, invokeStk, etc),
    # with 500 nested scripts (bodies). It must generate "too many nested compilations"
    # error for any variant we're testing here:
    ti eval {foreach cmd {eval "if 1" try catch} {
	set c [gencode 500 $cmd]
	lappend errors [catch $c e] $e
    }}
    #puts $errors
    # all of nested calls exceed the limit, so must end with "too many nested compilations"
    # (or evaluations, depending on compile method/instruction and "mixed" compile within
    # evaliation), so no one succeeds, the result must be empty:
    # evaluation), so no one succeeds, the result must be empty:
    ti eval {set result}
} -result {}
#
# clean up:
if {[interp exists ti]} {
    interp delete ti
}
562
563
564
565
566
567
568
569

570
571
572
573
574
575
576
570
571
572
573
574
575
576

577
578
579
580
581
582
583
584







-
+







test compile-15.5 {proper TCL_RETURN code from [return]} {
    apply {{} {catch {set a 1}; return}}
} ""

# Do all tests once byte compiled and once with direct string evaluation
foreach noComp {0 1} {

if $noComp {
if {$noComp} {
    interp alias {} run {} testevalex
    set constraints testevalex
} else {
    interp alias {} run {} if 1
    set constraints {}
}

648
649
650
651
652
653
654
655

656
657
658
659
660
661

662
663
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
656
657
658
659
660
661
662

663
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
707
708
709
710







-
+





-
+





-
+






-
+








-
+











-
+







# suite.
#
test compile-16.18.$noComp {TclCompileScript: word expansion} -body {
    proc LongList {} {return [lrepeat [expr {1<<10}] x]}
    llength [run "list [string repeat {{*}[LongList] } [expr {1<<10}]]"]
} -constraints [linsert $constraints 0 knownBug] -cleanup {
    rename LongList {}
} -returnCodes ok  -result [expr {1<<20}]
}  -result [expr {1<<20}]
test compile-16.19.$noComp {TclCompileScript: word expansion} -body {
    proc LongList {} {return [lrepeat [expr {1<<11}] x]}
    llength [run "list [string repeat {{*}[LongList] } [expr {1<<11}]]"]
} -constraints [linsert $constraints 0 knownBug] -cleanup {
    rename LongList {}
} -returnCodes ok  -result [expr {1<<22}]
}  -result [expr {1<<22}]
test compile-16.20.$noComp {TclCompileScript: word expansion} -body {
    proc LongList {} {return [lrepeat [expr {1<<12}] x]}
    llength [run "list [string repeat {{*}[LongList] } [expr {1<<12}]]"]
} -constraints [linsert $constraints 0 knownBug] -cleanup {
    rename LongList {}
} -returnCodes ok  -result [expr {1<<24}]
}  -result [expr {1<<24}]
# This is the one that should cause overflow
test compile-16.21.$noComp {TclCompileScript: word expansion} -body {
    proc LongList {} {return [lrepeat [expr {1<<16}] x]}
    llength [run "list [string repeat {{*}[LongList] } [expr {1<<16}]]"]
} -constraints [linsert $constraints 0 knownBug] -cleanup {
    rename LongList {}
} -returnCodes ok  -result [expr {wide(1)<<32}]
}  -result [expr {wide(1)<<32}]
test compile-16.22.$noComp {
    Bug 845412: TclCompileScript: word expansion not mandatory
} -body {
    # This test may crash and will fail unless Bug 845412 is fixed.
    proc ReturnResults args {return $args}
    run "ReturnResults [string repeat {x } 260]"
} -constraints $constraints -cleanup {
    rename ReturnResults {}
} -returnCodes ok -result [string trim [string repeat {x } 260]]
} -result [string trim [string repeat {x } 260]]
test compile-16.23.$noComp {
    Bug 1032805: defer parse error until run time
} -constraints $constraints -body {
    namespace eval x {
	run {
	    proc if {a b} {uplevel 1 [list set $a $b]}
	    if 1 {syntax {}{}}
	}
    }
} -cleanup {
    namespace delete x
} -returnCodes ok -result {syntax {}{}}
} -result {syntax {}{}}
test compile-16.24.$noComp {
    Bug 1638414: bad list constant as first expanded term
} -constraints $constraints -body {
    run "{*}\"\{foo bar\""
} -returnCodes error -result {unmatched open brace in list}
test compile-16.25.$noComp {TclCompileScript: word expansion, naked backslashes} $constraints {
    run {list {*}{a \n b}}
823
824
825
826
827
828
829

830
831
832
833
834
835
836
837
838
839
840
841
842
843
844

845
846
847
848
849
850
851
852
853
854
855
856
857

858
859
860
861
862
863
864
865
866
867
868
869
870
871

872
873
874
875
876
877
878
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852

853
854
855
856
857
858
859
860
861
862
863
864
865

866
867
868
869
870
871
872
873
874
875
876
877
878
879

880
881
882
883
884
885
886
887







+














-
+












-
+













-
+







    tcl::unsupported::disassemble objmethod foo bar
} -cleanup {
    foo destroy
} -match glob -result *
# There never was a compile-18.20.
# The keys of the dictionary produced by [getbytecode] are defined.
set bytecodekeys {literals variables exception instructions auxiliary commands script namespace stackdepth exceptdepth}
set allbytecodekeys [list {*}$bytecodekeys initiallinenumber sourcefile]
test compile-18.21 {disassembler - basics} -returnCodes error -body {
    tcl::unsupported::getbytecode
} -match glob -result {wrong # args: should be "*"}
test compile-18.22 {disassembler - basics} -returnCodes error -body {
    tcl::unsupported::getbytecode ?
} -result "bad type \"?\": must be $disassemblables"
test compile-18.23 {disassembler - basics} -returnCodes error -body {
    tcl::unsupported::getbytecode lambda
} -match glob -result {wrong # args: should be "* lambda lambdaTerm"}
test compile-18.24 {disassembler - basics} -returnCodes error -body {
    tcl::unsupported::getbytecode lambda \{
} -result "can't interpret \"\{\" as a lambda expression"
test compile-18.25 {disassembler - basics} -body {
    dict keys [tcl::unsupported::getbytecode lambda {{} {}}]
} -result "$bytecodekeys initiallinenumber sourcefile"
} -result $allbytecodekeys
test compile-18.26 {disassembler - basics} -returnCodes error -body {
    tcl::unsupported::getbytecode proc
} -match glob -result {wrong # args: should be "* proc procName"}
test compile-18.27 {disassembler - basics} -returnCodes error -body {
    tcl::unsupported::getbytecode proc nosuchproc
} -result {"nosuchproc" isn't a procedure}
test compile-18.28 {disassembler - basics} -setup {
    proc chewonthis {} {}
} -body {
    dict keys [tcl::unsupported::getbytecode proc chewonthis]
} -cleanup {
    rename chewonthis {}
} -result "$bytecodekeys initiallinenumber sourcefile"
} -result $allbytecodekeys
test compile-18.28.1 {disassembler - tricky bit} -setup {
    eval [list proc chewonthis {} {}]
} -body {
    dict keys [tcl::unsupported::getbytecode proc chewonthis]
} -cleanup {
    rename chewonthis {}
} -result $bytecodekeys
test compile-18.28.2 {disassembler - tricky bit} -setup {
    eval {proc chewonthis {} {}}
} -body {
    dict keys [tcl::unsupported::getbytecode proc chewonthis]
} -cleanup {
    rename chewonthis {}
} -result "$bytecodekeys initiallinenumber sourcefile"
} -result $allbytecodekeys
test compile-18.28.3 {disassembler - tricky bit} -setup {
    proc Proc {n a b} {
	proc $n $a $b
    }
    Proc chewonthis {} {}
} -body {
    dict keys [tcl::unsupported::getbytecode proc chewonthis]
886
887
888
889
890
891
892
893

894
895
896
897
898
899
900
895
896
897
898
899
900
901

902
903
904
905
906
907
908
909







-
+







    }
    Proc chewonthis {} {}
} -body {
    dict keys [tcl::unsupported::getbytecode proc chewonthis]
} -cleanup {
    rename Proc {}
    rename chewonthis {}
} -result "$bytecodekeys initiallinenumber sourcefile"
} -result $allbytecodekeys
test compile-18.29 {disassembler - basics} -returnCodes error -body {
    tcl::unsupported::getbytecode script
} -match glob -result {wrong # args: should be "* script script"}
test compile-18.30 {disassembler - basics} -body {
    dict keys [tcl::unsupported::getbytecode script {}]
} -result $bytecodekeys
test compile-18.31 {disassembler - basics} -returnCodes error -body {
915
916
917
918
919
920
921
922

923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939

940
941
942
943
944
945
946
924
925
926
927
928
929
930

931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947

948
949
950
951
952
953
954
955







-
+
















-
+







} -result {unknown method "nosuchmethod"}
test compile-18.35 {disassembler - basics} -setup {
    oo::class create foo {method bar {} {}}
} -body {
    dict keys [tcl::unsupported::getbytecode method foo bar]
} -cleanup {
    foo destroy
} -result "$bytecodekeys initiallinenumber sourcefile"
} -result $allbytecodekeys
test compile-18.36 {disassembler - basics} -returnCodes error -body {
    tcl::unsupported::getbytecode objmethod
} -match glob -result {wrong # args: should be "* objmethod objectName methodName"}
test compile-18.37 {disassembler - basics} -returnCodes error -body {
    tcl::unsupported::getbytecode objmethod nosuchobject foo
} -result {nosuchobject does not refer to an object}
test compile-18.38 {disassembler - basics} -returnCodes error -body {
    tcl::unsupported::getbytecode objmethod oo::object nosuchmethod
} -result {unknown method "nosuchmethod"}
test compile-18.39 {disassembler - basics} -setup {
    oo::object create foo
    oo::objdefine foo {method bar {} {}}
} -body {
    dict keys [tcl::unsupported::getbytecode objmethod foo bar]
} -cleanup {
    foo destroy
} -result "$bytecodekeys initiallinenumber sourcefile"
} -result $allbytecodekeys
test compile-18.40 {disassembler - basics} -returnCodes error -body {
    tcl::unsupported::disassemble constructor
} -match glob -result {wrong # args: should be "* constructor className"}
test compile-18.41 {disassembler - basics} -returnCodes error -body {
    tcl::unsupported::disassemble constructor nosuchclass
} -result {nosuchclass does not refer to an object}
test compile-18.42 {disassembler - basics} -returnCodes error -setup {
980
981
982
983
984
985
986
987

988
989
990
991
992
993
994
989
990
991
992
993
994
995

996
997
998
999
1000
1001
1002
1003







-
+







} -result {"constructorless" has no defined constructor}
test compile-18.48 {disassembler - basics} -setup {
    oo::class create foo {constructor {} {set x 1}}
} -body {
    dict keys [tcl::unsupported::getbytecode constructor foo]
} -cleanup {
    foo destroy
} -result "$bytecodekeys"
} -result $allbytecodekeys
# There is no compile-18.49
test compile-18.50 {disassembler - basics} -returnCodes error -body {
    tcl::unsupported::disassemble destructor
} -match glob -result {wrong # args: should be "* destructor className"}
test compile-18.51 {disassembler - basics} -returnCodes error -body {
    tcl::unsupported::disassemble destructor nosuchclass
} -result {nosuchclass does not refer to an object}
1029
1030
1031
1032
1033
1034
1035
1036

1037
1038
1039
1040
1041
1042
1043
1038
1039
1040
1041
1042
1043
1044

1045
1046
1047
1048
1049
1050
1051
1052







-
+







} -result {"constructorless" has no defined destructor}
test compile-18.58 {disassembler - basics} -setup {
    oo::class create foo {destructor {set x 1}}
} -body {
    dict keys [tcl::unsupported::getbytecode destructor foo]
} -cleanup {
    foo destroy
} -result "$bytecodekeys"
} -result $allbytecodekeys

test compile-19.0 {Bug 3614102: reset stack housekeeping} -body {
    # This will panic in a --enable-symbols=compile build, unless bug is fixed.
    apply {{} {list [if 1]}}
} -returnCodes error -match glob -result *

test compile-20.1 {ensure there are no infinite loops in optimizing} {

Changes to tests/concat.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  concat
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands.  Sourcing this file into Tcl runs the tests and generates output
# for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*

Changes to tests/config.test.

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
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







-
-
-
+
+
+









-
+

-
+







# -*- tcl -*-
# Commands covered:  pkgconfig
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
}

test pkgconfig-1.1 {query keys} {
test pkgconfig-1.1 {query keys} -body {
    lsort [::tcl::pkgconfig list]
} {64bit bindir,install bindir,runtime compile_debug compile_stats debug dllfile,runtime docdir,install docdir,runtime includedir,install includedir,runtime libdir,install libdir,runtime mem_debug optimized profiled scriptdir,install scriptdir,runtime threaded zipfile,runtime}
} -match glob -result {*bindir,install bindir,runtime*docdir,install docdir,runtime includedir,install includedir,runtime libdir,install libdir,runtime*scriptdir,install scriptdir,runtime*}
test pkgconfig-1.2 {query keys multiple times} {
    string compare [::tcl::pkgconfig list] [::tcl::pkgconfig list]
} 0
test pkgconfig-1.3 {query value multiple times} {
    string compare \
	    [::tcl::pkgconfig get bindir,install] \
	    [::tcl::pkgconfig get bindir,install]

Changes to tests/coroutine.test.

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
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






-
+










-
+







# Commands covered:  coroutine, yield, yieldto, [info coroutine]
#
# This file contains a collection of tests for experimental commands that are
# found in ::tcl::unsupported. The tests will migrate to normal test files
# if/when the commands find their way into the core.
#
# Copyright (c) 2008 by Miguel Sofer.
# Copyright © 2008 Miguel Sofer.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testnrelevels [llength [info commands testnrelevels]]
testConstraint memory [llength [info commands memory]]

set lambda [list {{start 0} {stop 10}} {
    # init
    set i    $start
751
752
753
754
755
756
757

758
759
760
761
762
763
764
765
766
767
768
769
770
771
772





































































773
774
775
776
777
778

779
780
781
782
783
784
785
786
787

788
789
790
791
792
793
794


795
796
797
798
799
800
801
751
752
753
754
755
756
757
758















759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832

833
834
835
836
837
838
839
840
841

842
843
844
845
846
847
848

849
850
851
852
853
854
855
856
857







+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+








-
+






-
+
+







    }
    boom   ; # does not crash: the coro floor is a good insulator
    list
} -cleanup {
    rename boom {}; rename cc {}; rename c {}
} -result {}


test coroutine-8.0.0 {coro inject executed} -body {
    coroutine demo apply {{} { foreach i {1 2} yield }}
    demo
    set ::result none
    tcl::unsupported::inject demo set ::result inject-executed
    demo
    set ::result
} -result {inject-executed}
test coroutine-8.0.1 {coro inject after error} -body {
    coroutine demo apply {{} { foreach i {1 2} yield; error test }}
    demo
    set ::result none
    tcl::unsupported::inject demo set ::result inject-executed
    lappend ::result [catch {demo} err] $err
} -result {inject-executed 1 test}
test coroutine-7.13 {
	issue f9800d52bd61f240

	vwait is not NRE-enabled, and yieldto cannot find the right splicing spot
} -body {
	coroutine c0 apply [list {} {
		variable done
		yield
		yieldto c1
		after 0 c2
		vwait [namespace current]::done
	} [namespace current]]

	coroutine c1 apply [list {} {
		yield
		tailcall c0
	} [namespace current]]

	coroutine c2 apply [list {} {
		variable done
		yield
		yieldto try {yieldto c1} on error {} [list after 0 [list [info coroutine]]]
		yieldto try {yieldto c1} on error {} [list after 0 [list [info coroutine]]]
		set done 1
	} [namespace current]]

	after 0 [list [namespace which c0]]
	vwait [namespace current]::done
	return $done
} -result 1


test coroutine-7.14 {
	issue 5106fddd4400e5b9

	failure to yieldto is not the same thing as not calling yieldto in the
	first place
} -body {
	variable done
	variable done1

	coroutine c0 ::apply [list {} {
		yield
		after 0 [list [namespace which c1]]
		vwait [namespace current]::done1
	} [namespace current]]

	coroutine c1 ::apply [list {} {
		variable done1
		yield
		yieldto try "yieldto [list [info coroutine]]" on error {} "
			::set [list [namespace current]]::done1 failure
			::set [list [namespace current]]::done0 failure
		"
		set done1 success

	} [namespace current]]
	after 1 [list [namespace which c0]]
	vwait [namespace current]::done0
	if {[namespace which [namespace current]::c1] ne {}} {
		# prior to the fix for 5106fddd4400e5b9, the nested yieldto turned into a
		# tailcall which was eventutally activated, causing control to return to
		# c1.  After the fix, that doesn't happen, so if c1 still exists call it
		# one final time to allow it to finish and clean up
		rename c1 {}
	}
	return [list $done0 $done1]
} -result {failure failure}

test coroutine-8.1.1 {coro inject, ticket 42202ba1e5ff566e} -body {
    interp create child
    child eval {
	coroutine demo apply {{} { while {1} yield }}
	demo
	tcl::unsupported::inject demo set ::result inject-executed
	coroinject demo set ::result inject-executed
    }
    interp delete child
} -result {}
test coroutine-8.1.2 {coro inject with result, ticket 42202ba1e5ff566e} -body {
    interp create child
    child eval {
	coroutine demo apply {{} { while {1} yield }}
	demo
	tcl::unsupported::inject demo set ::result inject-executed
	coroinject demo lappend ::result inject-executed
    }
    child eval demo
    set result [child eval {set ::result}]

    interp delete child
    set result
} -result {inject-executed}
} -result {inject-executed yield {}}


test coroutine-9.1 {coroprobe with yield} -body {
    coroutine demo apply {{} { foreach i {1 2} yield }}
    list [coroprobe demo set i] [demo] [coroprobe demo set i] [demo]
} -cleanup {
    catch {rename demo {}}
} -result {1 {} 2 {}}
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
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







-
+











-
+








test coroutine-12.1 {coroutine general introspection} -setup {
    set i [interp create]
} -body {
    $i eval {
	# Make the introspection code
	namespace path tcl::unsupported
	proc probe {type var} {
	proc probe {var type args} {
	    upvar 1 $var v
	    set f [info frame]
	    incr f -1
	    set result [list $v [dict get [info frame $f] proc]]
	    if {$type eq "yield"} {
		tailcall yield $result
	    } else {
		tailcall yieldto string cat $result
	    }
	}
	proc pokecoro {c var} {
	    inject $c probe [corotype $c] $var
	    coroinject $c probe $var
	    $c
	}

	# Coroutine implementations
	proc cbody1 {} {
	    set val [info coroutine]
	    set accum {}

Changes to tests/dcall.test.

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
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






-
-
-
+
+
+










-
+







# Commands covered:  none
#
# This file contains a collection of tests for Tcl_CallWhenDeleted.
# Sourcing this file into Tcl runs the tests and generates output for
# errors.  No output means no errors were found.
#
# Copyright (c) 1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testdcall [llength [info commands testdcall]]

test dcall-1.1 {deletion callbacks} testdcall {
    lsort -increasing [testdcall 1 2 3]
} {1 2 3}
test dcall-1.2 {deletion callbacks} testdcall {

Changes to tests/dict.test.

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

30
31
32
33
34
35
36
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44







-
+








+
+
+
+
+
+
+













+







# This test file covers the dictionary object type and the dict command used
# to work with values of that type.
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors.  No output means no errors were found.
#
# Copyright (c) 2003-2009 Donal K. Fellows
# Copyright © 2003-2009 Donal K. Fellows
# 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::*
}

catch {
    ::tcltest::loadTestedCommands
    package require -exact tcl::test [info patchlevel]
}

testConstraint testobj [llength [info commands testobj]]

# Used for constraining memory leak tests
testConstraint memory [llength [info commands memory]]
if {[testConstraint memory]} {
    proc memtest script {
	set end [lindex [split [memory info] \n] 3 3]
	for {set i 0} {$i < 5} {incr i} {
	    uplevel 1 $script
	    set tmp $end
	    set end [lindex [split [memory info] \n] 3 3]
	}
	expr {$end - $tmp}
    }
}


test dict-1.1 {dict command basic syntax} -returnCodes error -body {
    dict
} -result {wrong # args: should be "dict subcommand ?arg ...?"}
test dict-1.2 {dict command basic syntax} -returnCodes error -body {
    dict ?
} -match glob -result {unknown or ambiguous subcommand "?": must be *}
134
135
136
137
138
139
140
141
142





143
144
145
146
147
148
149
142
143
144
145
146
147
148


149
150
151
152
153
154
155
156
157
158
159
160







-
-
+
+
+
+
+







} -result {missing value to go with key}
test dict-3.15 {compiled dict get error cleanliness - Bug 2431847} -body {
    apply {{} {
	dict set a(z) b c
	dict get $a(z) d
    }}
} -returnCodes error -result {key "d" not known in dictionary}
test dict-3.16 {dict/list shimmering - Bug 3004007} {set l [list p 1 p 2 q 3];dict get $l q;set l} {p 1 p 2 q 3}
test dict-3.17 {dict/list shimmering - Bug 3004007} {set l [list p 1 p 2 q 3];dict get $l q;llength $l} 6
test dict-3.16 {dict/list shimmering - Bug 3004007} testobj {
    set l [list p 1 p 2 q 3]
    dict get $l q
    list $l [testobj objtype $l]
} {{p 1 p 2 q 3} dict}

test dict-4.1 {dict replace command} {
    dict replace {a b c d}
} {a b c d}
test dict-4.2 {dict replace command} {
    dict replace {a b c d} e f
} {a b c d e f}
653
654
655
656
657
658
659
660

661
662
663
664
665

666
667
668
669
670

671
672
673

674
675
676
677
678
679
680
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







-
+




-
+




-
+


-
+







	dict for {k v} {a b} {
	    return ok,$k,$v
	    error "skipped return completely"
	}
	error "return didn't go far enough"
    }}
} ok,a,b
test dict-14.14 {dict for command: handle representation loss} -body {
test dict-14.14 {dict for command: handle representation loss} -constraints testobj -body {
    set dictVar {a b c d e f g h}
    set keys {}
    set values {}
    dict for {k v} $dictVar {
	if {[llength $dictVar]} {
	if {[string length $dictVar]} {
	    lappend keys $k
	    lappend values $v
	}
    }
    list [lsort $keys] [lsort $values]
    list [lsort $keys] [lsort $values] [testobj objtype $dictVar]
} -cleanup {
    unset dictVar keys values k v
} -result {{a c e g} {b d f h}}
} -result {{a c e g} {b d f h} string}
test dict-14.15 {dict for command: keys are unique and iterated over once only} -setup {
    unset -nocomplain accum
    array set accum {}
} -body {
    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
    dict for {k v} $dictVar {
	append accum($k) $v,
989
990
991
992
993
994
995
996

997
998
999
1000
1001
1002
1003
1000
1001
1002
1003
1004
1005
1006

1007
1008
1009
1010
1011
1012
1013
1014







-
+







} -result {{foo bar bar foo} 6}
test dict-17.12 {dict filter command: script} -returnCodes error -body {
    dict filter {a b} script {k v} {
	concat $k $v
    }
} -cleanup {
    unset k v
} -result {expected boolean value but got "a b"}
} -result {expected boolean value but got a list}
test dict-17.13 {dict filter command: script} -body {
    list [catch {dict filter {a b} script {k v} {error x}} msg] $msg \
	    $::errorInfo
} -cleanup {
    unset k v msg
} -result {1 x {x
    while executing
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105



1106
1107
1108
1109
1110
1111
1112

1113
1114
1115
1116
1117
1118
1119
1107
1108
1109
1110
1111
1112
1113



1114
1115
1116
1117
1118
1119
1120
1121
1122

1123
1124
1125
1126
1127
1128
1129
1130







-
-
-
+
+
+






-
+







    unset ld
} -result {8 3 8}

# This is a test for a specific bug.
# It shows a bad ref counter when running with memdebug on.
test dict-19.1 {memory bug} {
    apply {{} {
        set successors [dict create x {c d}]
        dict set successors x a b
        dict get $successors x
	set successors [dict create x {c d}]
	dict set successors x a b
	dict get $successors x
    }}
} [dict create c d a b]
test dict-19.2 {dict: testing for leaks} -constraints memory -body {
    # This test is made to stress object reference management
    memtest {
	apply {{} {
	    # A shared invalid dictinary
	    # A shared invalid dictionary
	    set apa {a {}b c d}
	    set bepa $apa
	    catch {dict replace $apa e f}
	    catch {dict remove  $apa c d}
	    catch {dict incr    apa  a 5}
	    catch {dict lappend apa  a 5}
	    catch {dict append  apa  a 5}
1798
1799
1800
1801
1802
1803
1804
1805

1806
1807
1808
1809
1810
1811

1812
1813
1814
1815
1816

1817
1818
1819
1820


1821
1822
1823
1824

1825
1826
1827
1828
1829

1830
1831

1832
1833
1834
1835
1836
1837
1838
1809
1810
1811
1812
1813
1814
1815

1816
1817
1818
1819
1820
1821

1822
1823
1824
1825
1826

1827
1828
1829


1830
1831
1832
1833
1834

1835
1836
1837
1838
1839

1840
1841

1842
1843
1844
1845
1846
1847
1848
1849







-
+





-
+




-
+


-
-
+
+



-
+




-
+

-
+







	dict map {k v} {a b} {
	    return ok,$k,$v
	    error "skipped return completely"
	}
	error "return didn't go far enough"
    }}
} ok,a,b
test dict-24.14 {dict map command: handle representation loss} -setup {
test dict-24.14 {dict map command: handle representation loss} -constraints testobj -setup {
    set keys {}
    set values {}
} -body {
    set dictVar {a b c d e f g h}
    list [dict size [dict map {k v} $dictVar {
	if {[llength $dictVar]} {
	if {[string length $dictVar]} {
	    lappend keys $k
	    lappend values $v
	    return -level 0 $k
	}
    }]] [lsort $keys] [lsort $values]
    }]] [lsort $keys] [lsort $values] [testobj objtype $dictVar]
} -cleanup {
    unset dictVar keys values k v
} -result {4 {a c e g} {b d f h}}
test dict-24.14a {dict map command: handle representation loss} -body {
} -result {4 {a c e g} {b d f h} string}
test dict-24.14a {dict map command: handle representation loss} -constraints testobj -body {
    apply {{} {
	set dictVar {a b c d e f g h}
	list [dict size [dict map {k v} $dictVar {
	    if {[llength $dictVar]} {
	    if {[string length $dictVar]} {
		lappend keys $k
		lappend values $v
		return -level 0 $k
	    }
	}]] [lsort $keys] [lsort $values]
	}]] [lsort $keys] [lsort $values] [testobj objtype $dictVar]
    }}
} -result {4 {a c e g} {b d f h}}
} -result {4 {a c e g} {b d f h} string}
test dict-24.15 {dict map command: keys are unique and iterated over once only} -setup {
    unset -nocomplain accum
    array set accum {}
} -body {
    set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
    dict map {k v} $dictVar {
	append accum($k) $v,

Changes to tests/dstring.test.

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
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






-
-
-
+
+
+










-
+







# Commands covered:  none
#
# This file contains a collection of tests for Tcl's dynamic string library
# procedures. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testdstring [llength [info commands testdstring]]
if {[testConstraint testdstring]} {
    testdstring free
}

test dstring-1.1 {appending and retrieving} -constraints testdstring -setup {
207
208
209
210
211
212
213
































214
215
216
217
218
219
220
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    # decision about whether #-quoting can be disabled.
    testdstring append "x  " -1
    testdstring element #
    testdstring get
} -cleanup {
    testdstring free
} -result {x  #}
test dstring-2.16 {appending list elements - bug [46dda6fc29] segfault} -constraints testdstring -setup {
    testdstring free
} -body {
    testdstring element "\\\n"; # Will setfault
    testdstring get
} -cleanup {
    testdstring free
} -result \\\\\\n
test dstring-2.17 {appending list elements - bug [46dda6fc29] segfault} -constraints testdstring -setup {
    testdstring free
} -body {
    testdstring element "\\\{"; # Will setfault
    testdstring get
} -cleanup {
    testdstring free
} -result [list [list \{]]
test dstring-2.18 {appending list elements - bug [46dda6fc29] segfault} -constraints testdstring -setup {
    testdstring free
} -body {
    testdstring element "\\\}"; # Will setfault
    testdstring get
} -cleanup {
    testdstring free
} -result [list [list \}]]
test dstring-2.19 {appending list elements - bug [46dda6fc29] segfault} -constraints testdstring -setup {
    testdstring free
} -body {
    testdstring element "\\\\"; # Will setfault
    testdstring get
} -cleanup {
    testdstring free
} -result [list [list \\]]

test dstring-3.1 {nested sublists} -constraints testdstring -setup {
    testdstring free
} -body {
    testdstring start
    testdstring element foo
    testdstring element bar
382
383
384
385
386
387
388


















389
390
391
392
393
394
395
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







} -body {
    testdstring append "xyzzy" -1
    testdstring trunc 0
    list [testdstring get] [testdstring length]
} -cleanup {
    testdstring free
} -result {{} 0}
test dstring-4.3 {truncation} -constraints testdstring -setup {
    testdstring free
} -body {
    testdstring append "xwvut" -1
    # Pass a negative length to Tcl_DStringSetLength();
    # if not caught, causing '\0' to be written out-of-bounds,
    # try corrupting dsPtr->length which begins
    # 2*sizeof(Tcl_Size) bytes before dsPtr->staticSpace[],
    # so that the result is -256 (on little endian systems)
    # rather than e.g. -8 or -16.
    # (sizeof(Tcl_Size) does not seem to be available via Tcl,
    # so assume sizeof(Tcl_Size) == sizeof(void*) for Tcl 9.)
    testdstring trunc [expr {-2*([package vsatisfies $tcl_version 9.0-]
	? $tcl_platform(pointerSize) : 4)}]
    list [testdstring get] [testdstring length]
} -cleanup {
    testdstring free
} -result {{} 0}

test dstring-5.1 {copying to result} -constraints testdstring -setup {
    testdstring free
} -body {
    testdstring append xyz -1
    testdstring result
} -cleanup {
469
470
471
472
473
474
475







































476
477
478
479
480
481
482
483
484
485
486
487
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












    set result {}
    lappend result [testdstring gresult special]
    testdstring append z 1
    lappend result [testdstring get]
} -cleanup {
    testdstring free
} -result {{} {This is a specially-allocated stringz}}

test dstring-7.1 {copying to Tcl_Obj} -constraints testdstring -setup {
    testdstring free
} -body {
    testdstring append xyz -1
    list [testdstring toobj] [testdstring length]
} -cleanup {
    testdstring free
} -result {xyz 0}
test dstring-7.2 {copying to a Tcl_Obj} -constraints testdstring -setup {
    testdstring free
    unset -nocomplain a
} -body {
    foreach l {a b c d e f g h i j k l m n o p} {
	testdstring append $l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l\n -1
    }
    set a [testdstring toobj]
    testdstring append abc -1
    list $a [testdstring get]
} -cleanup {
    testdstring free
} -result {{aaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbb
ccccccccccccccccccccc
ddddddddddddddddddddd
eeeeeeeeeeeeeeeeeeeee
fffffffffffffffffffff
ggggggggggggggggggggg
hhhhhhhhhhhhhhhhhhhhh
iiiiiiiiiiiiiiiiiiiii
jjjjjjjjjjjjjjjjjjjjj
kkkkkkkkkkkkkkkkkkkkk
lllllllllllllllllllll
mmmmmmmmmmmmmmmmmmmmm
nnnnnnnnnnnnnnnnnnnnn
ooooooooooooooooooooo
ppppppppppppppppppppp
} abc}


# cleanup
if {[testConstraint testdstring]} {
    testdstring free
}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:

Changes to tests/encoding.test.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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
30
31
32
33
34
35
36
37
38
39
40
41

42
43
44
45
46
47
48




-
-
+
+















-
+



















-







# This file contains a collection of tests for tclEncoding.c
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
}


namespace eval ::tcl::test::encoding {
    variable x

catch {
    ::tcltest::loadTestedCommands
    package require -exact Tcltest [info patchlevel]
    package require -exact tcl::test [info patchlevel]
}

proc toutf {args} {
    variable x
    lappend x "toutf $args"
}
proc fromutf {args} {
    variable x
    lappend x "fromutf $args"
}

proc runtests {} {
    variable x

# Some tests require the testencoding command
testConstraint testencoding [llength [info commands testencoding]]
testConstraint testbytestring [llength [info commands testbytestring]]
testConstraint teststringbytes [llength [info commands teststringbytes]]
testConstraint exec [llength [info commands exec]]
testConstraint testgetencpath [llength [info commands testgetencpath]]

# TclInitEncodingSubsystem is tested by the rest of this file
# TclFinalizeEncodingSubsystem is not currently tested

test encoding-1.1 {Tcl_GetEncoding: system encoding} -setup {
    set old [encoding system]
} -constraints {testencoding} -body {
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
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







-
+

-
+


-
+







-
+


-
+




-
+

















+
+
+
+
+
+
+
+







    testencoding create foo [namespace origin toutf] [namespace origin fromutf]
    set x {}
    encoding convertto foo abcd
    testencoding delete foo
    return $x
} {{fromutf }}
test encoding-1.3 {Tcl_GetEncoding: load encoding} {
    list [encoding convertto jis0208 \u4e4e] \
    list [encoding convertto jis0208 乎] \
	[encoding convertfrom jis0208 8C]
} "8C \u4e4e"
} "8C 乎"

test encoding-2.1 {Tcl_FreeEncoding: refcount == 0} {
    encoding convertto jis0208 \u4e4e
    encoding convertto jis0208 乎
} {8C}
test encoding-2.2 {Tcl_FreeEncoding: refcount != 0} -setup {
    set system [encoding system]
    set path [encoding dirs]
} -constraints {testencoding} -body {
    encoding system shiftjis		;# incr ref count
    encoding dirs [list [pwd]]
    set x [encoding convertto shiftjis \u4e4e]	;# old one found
    set x [encoding convertto shiftjis 乎]	;# old one found
    encoding system iso8859-1
    llength shiftjis		;# Shimmer away any cache of Tcl_Encoding
    lappend x [catch {encoding convertto shiftjis \u4e4e} msg] $msg
    lappend x [catch {encoding convertto shiftjis 乎} msg] $msg
} -cleanup {
    encoding system iso8859-1
    encoding dirs $path
    encoding system $system
} -result "\u008c\u00c1 1 {unknown encoding \"shiftjis\"}"
} -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
} -cleanup {
    encoding system $old
} -result {shiftjis}
test encoding-3.2 {Tcl_GetEncodingName, non-null} -setup {
    set old [fconfigure stdout -encoding]
} -body {
    fconfigure stdout -encoding jis0208
    fconfigure stdout -encoding
} -cleanup {
    fconfigure stdout -encoding $old
} -result {jis0208}
test encoding-3.3 {fconfigure -profile} -setup {
    set old [fconfigure stdout -profile]
} -body {
    fconfigure stdout -profile replace
    fconfigure stdout -profile
} -cleanup {
    fconfigure stdout -profile $old
} -result replace

test encoding-4.1 {Tcl_GetEncodingNames} -constraints {testencoding} -setup {
    cd [makeDirectory tmp]
    makeDirectory [file join tmp encoding]
    set path [encoding dirs]
    encoding dirs {}
    catch {unset encodings}
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
140
141
142
143
144
145
146

147
148
149
150
151
152
153
154







-
+







    removeDirectory tmp
} -result {junk junk2}

test encoding-5.1 {Tcl_SetSystemEncoding} -setup {
    set old [encoding system]
} -body {
    encoding system jis0208
    encoding convertto \u4e4e
    encoding convertto 乎
} -cleanup {
    encoding system iso8859-1
    encoding system $old
} -result {8C}
test encoding-5.2 {Tcl_SetSystemEncoding: test ref count} {
    set old [encoding system]
    encoding system $old
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
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
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
467



468

469
470
471
472

473
474
475
476
477
478
479
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478

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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591



592
593
594
595





596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625


626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644


645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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







-
+








-
+



-
-
+
+


-
+




-
+


-
+


-
+












-
-
+
+


-
+




-
+
-
-
-
-
-
-
-
-
-
-
-
-







-
+


-
+


-
-
+
+


-
+

-
-
+
+

-
-
+
+

-
-
+
+













-
+








-
+
+
+
+
+
+
+
+
+
+
+
+



-
-
-
-
+
+
+
+

-
-
-
+
+
+

-
-
-
+
+
+

-
+

-
+

-
-
-
-
+
+
+
+


-
-
+
+


-
-
+
+

-
+



-
+





-
+

-
+




-
+


-
+


-
+


-
+




-
-
+
+





-
+




-
-
+
+




-
-
+
+





-
+





-
+





-
+





-
+





-
+



-
-
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+





-
+





-
-
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
-
+
+
+

-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










-
-
-
-
-
+
+
+
+
+


-
+
-
-
-
+
+
+
-
+



-
+







    encoding convertto foo abcd
    testencoding delete foo
    return $x
} {{toutf a} {fromutf b}}

test encoding-7.1 {Tcl_ExternalToUtfDString: small buffer} {
    encoding convertfrom jis0208 8c8c8c8c
} "\u543e\u543e\u543e\u543e"
} å¾å¾å¾å¾
test encoding-7.2 {Tcl_UtfToExternalDString: big buffer} {
    set a 8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C
    append a $a
    append a $a
    append a $a
    append a $a
    set x [encoding convertfrom jis0208 $a]
    list [string length $x] [string index $x 0]
} "512 \u4e4e"
} "512 乎"

test encoding-8.1 {Tcl_ExternalToUtf} {
    set f [open [file join [temporaryDirectory] dummy] w]
    fconfigure $f -translation binary -encoding iso8859-1
    puts -nonewline $f "ab\x8c\xc1g"
    fconfigure $f -translation binary
    puts -nonewline $f "ab\x8C\xC1g"
    close $f
    set f [open [file join [temporaryDirectory] dummy] r]
    fconfigure $f -translation binary -encoding shiftjis
    fconfigure $f -translation lf -encoding shiftjis
    set x [read $f]
    close $f
    file delete [file join [temporaryDirectory] dummy]
    return $x
} "ab\u4e4eg"
} ab乎g

test encoding-9.1 {Tcl_UtfToExternalDString: small buffer} {
    encoding convertto jis0208 "\u543e\u543e\u543e\u543e"
    encoding convertto jis0208 "å¾å¾å¾å¾"
} {8c8c8c8c}
test encoding-9.2 {Tcl_UtfToExternalDString: big buffer} {
    set a \u4e4e\u4e4e\u4e4e\u4e4e\u4e4e\u4e4e\u4e4e\u4e4e
    set a 乎乎乎乎乎乎乎乎
    append a $a
    append a $a
    append a $a
    append a $a
    append a $a
    append a $a
    set x [encoding convertto jis0208 $a]
    list [string length $x] [string range $x 0 1]
} "1024 8C"

test encoding-10.1 {Tcl_UtfToExternal} {
    set f [open [file join [temporaryDirectory] dummy] w]
    fconfigure $f -translation binary -encoding shiftjis
    puts -nonewline $f "ab\u4e4eg"
    fconfigure $f -translation lf -encoding shiftjis
    puts -nonewline $f ab乎g
    close $f
    set f [open [file join [temporaryDirectory] dummy] r]
    fconfigure $f -translation binary -encoding iso8859-1
    fconfigure $f -translation binary
    set x [read $f]
    close $f
    file delete [file join [temporaryDirectory] dummy]
    return $x
} "ab\x8c\xc1g"
} "ab\x8C\xC1g"

proc viewable {str} {
    set res ""
    foreach c [split $str {}] {
	if {[string is print $c] && [string is ascii $c]} {
	    append res $c
	} else {
	    append res "\\u[format %4.4x [scan $c %c]]"
	}
    }
    return "$str ($res)"
}

test encoding-11.1 {LoadEncodingFile: unknown encoding} {testencoding} {
    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 \u4e4e} msg] $msg]
    set x [list [catch {encoding convertto jis0208 乎} msg] $msg]
    encoding dirs $path
    encoding system $system
    lappend x [encoding convertto jis0208 \u4e4e]
    lappend x [encoding convertto jis0208 乎]
} {1 {unknown encoding "jis0208"} 8C}
test encoding-11.2 {LoadEncodingFile: single-byte} {
    encoding convertfrom jis0201 \xa1
} "\uff61"
    encoding convertfrom jis0201 \xA1
} 。
test encoding-11.3 {LoadEncodingFile: double-byte} {
    encoding convertfrom jis0208 8C
} "\u4e4e"
} 乎
test encoding-11.4 {LoadEncodingFile: multi-byte} {
    encoding convertfrom shiftjis \x8c\xc1
} "\u4e4e"
    encoding convertfrom shiftjis \x8C\xC1
} 乎
test encoding-11.5 {LoadEncodingFile: escape file} {
    viewable [encoding convertto iso2022 \u4e4e]
} [viewable "\x1b\$B8C\x1b(B"]
    encoding convertto iso2022 乎
} \x1B\$B8C\x1B(B
test encoding-11.5.1 {LoadEncodingFile: escape file} {
    viewable [encoding convertto iso2022-jp \u4e4e]
} [viewable "\x1b\$B8C\x1b(B"]
    encoding convertto iso2022-jp 乎
} \x1B\$B8C\x1B(B
test encoding-11.6 {LoadEncodingFile: invalid file} -constraints {testencoding} -setup {
    set system [encoding system]
    set path [encoding dirs]
    encoding system iso8859-1
} -body {
    cd [temporaryDirectory]
    encoding dirs [file join tmp encoding]
    makeDirectory tmp
    makeDirectory [file join tmp encoding]
    set f [open [file join tmp encoding splat.enc] w]
    fconfigure $f -translation binary
    puts $f "abcdefghijklmnop"
    close $f
    encoding convertto splat \u4e4e
    encoding convertto splat 乎
} -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
test encoding-11.10 {encoding: extended Unicode UTF-32} {
    encoding convertto utf-32le 😹
} 9\xF6\x01\x00
test encoding-11.11 {encoding: extended Unicode UTF-32} {
    encoding convertto utf-32be 😹
} \x00\x01\xF69
# OpenEncodingFile is fully tested by the rest of the tests in this file.

test encoding-12.1 {LoadTableEncoding: normal encoding} {
    set x [encoding convertto iso8859-3 \u0120]
    append x [encoding convertto iso8859-3 \xD5]
    append x [encoding convertfrom iso8859-3 \xD5]
} "\xd5?\u120"
    set x [encoding convertto iso8859-3 Ä ]
    append x [encoding convertto -profile tcl8 iso8859-3 Õ]
    append x [encoding convertfrom iso8859-3 Õ]
} "Õ?Ġ"
test encoding-12.2 {LoadTableEncoding: single-byte encoding} {
    set x [encoding convertto iso8859-3 ab\u0120g]
    append x [encoding convertfrom iso8859-3 ab\xD5g]
} "ab\xd5gab\u120g"
    set x [encoding convertto iso8859-3 abÄ g]
    append x [encoding convertfrom iso8859-3 abÕg]
} "abÕgabĠg"
test encoding-12.3 {LoadTableEncoding: multi-byte encoding} {
    set x [encoding convertto shiftjis ab\u4E4Eg]
    append x [encoding convertfrom shiftjis ab\x8c\xc1g]
} "ab\x8c\xc1gab\u4e4eg"
    set x [encoding convertto shiftjis ab乎g]
    append x [encoding convertfrom shiftjis ab\x8C\xC1g]
} "ab\x8C\xC1gab乎g"
test encoding-12.4 {LoadTableEncoding: double-byte encoding} {
    set x [encoding convertto jis0208 \u4e4e\u3b1]
    set x [encoding convertto jis0208 乎α]
    append x [encoding convertfrom jis0208 8C&A]
} "8C&A\u4e4e\u3b1"
} "8C&A乎α"
test encoding-12.5 {LoadTableEncoding: symbol encoding} {
    set x [encoding convertto symbol \u3b3]
    append x [encoding convertto symbol \u67]
    append x [encoding convertfrom symbol \x67]
} "\x67\x67\u3b3"
    set x [encoding convertto symbol γ]
    append x [encoding convertto symbol g]
    append x [encoding convertfrom symbol g]
} "ggγ"

test encoding-13.1 {LoadEscapeTable} {
    viewable [set x [encoding convertto iso2022 ab\u4e4e\u68d9g]]
} [viewable "ab\x1b\$B8C\x1b\$\(DD%\x1b(Bg"]
    encoding convertto iso2022 ab乎棙g
} ab\x1B\$B8C\x1B\$\(DD%\x1B(Bg

test encoding-15.1 {UtfToUtfProc} {
    encoding convertto utf-8 \xa3
} "\xc2\xa3"
    encoding convertto utf-8 £
} "\xC2\xA3"
test encoding-15.2 {UtfToUtfProc null character output} testbytestring {
    binary scan [testbytestring [encoding convertto utf-8 \u0000]] H* z
    binary scan [testbytestring [encoding convertto utf-8 \x00]] H* z
    set z
} 00
test encoding-15.3 {UtfToUtfProc null character input} teststringbytes {
    set y [encoding convertfrom utf-8 [encoding convertto utf-8 \u0000]]
    set y [encoding convertfrom utf-8 [encoding convertto utf-8 \x00]]
    binary scan [teststringbytes $y] H* z
    set z
} c080
test encoding-15.4 {UtfToUtfProc emoji character input} -body {
    set x \xED\xA0\xBD\xED\xB8\x82
    set y [encoding convertfrom utf-8 \xED\xA0\xBD\xED\xB8\x82]
    set y [encoding convertfrom -profile tcl8 utf-8 \xED\xA0\xBD\xED\xB8\x82]
    list [string length $x] $y
} -result "6 \U1F602"
} -result "6 \uD83D\uDE02"
test encoding-15.5 {UtfToUtfProc emoji character input} {
    set x \xF0\x9F\x98\x82
    set y [encoding convertfrom utf-8 \xF0\x9F\x98\x82]
    list [string length $x] $y
} "4 \U1F602"
} "4 😂"
test encoding-15.6 {UtfToUtfProc emoji character output} {
    set x \uDE02\uD83D\uDE02\uD83D
    set y [encoding convertto utf-8 \uDE02\uD83D\uDE02\uD83D]
    set y [encoding convertto -profile tcl8 utf-8 \uDE02\uD83D\uDE02\uD83D]
    binary scan $y H* z
    list [string length $y] $z
} {10 edb882f09f9882eda0bd}
} {12 edb882eda0bdedb882eda0bd}
test encoding-15.7 {UtfToUtfProc emoji character output} {
    set x \uDE02\uD83D\uD83D
    set y [encoding convertto utf-8 \uDE02\uD83D\uD83D]
    set y [encoding convertto -profile tcl8 utf-8 \uDE02\uD83D\uD83D]
    binary scan $y H* z
    list [string length $x] [string length $y] $z
} {3 9 edb882eda0bdeda0bd}
test encoding-15.8 {UtfToUtfProc emoji character output} {
    set x \uDE02\uD83D\xE9
    set y [encoding convertto utf-8 \uDE02\uD83D\xE9]
    set x \uDE02\uD83Dé
    set y [encoding convertto -profile tcl8 utf-8 \uDE02\uD83Dé]
    binary scan $y H* z
    list [string length $x] [string length $y] $z
} {3 8 edb882eda0bdc3a9}
test encoding-15.9 {UtfToUtfProc emoji character output} {
    set x \uDE02\uD83DX
    set y [encoding convertto utf-8 \uDE02\uD83DX]
    set y [encoding convertto -profile tcl8 utf-8 \uDE02\uD83DX]
    binary scan $y H* z
    list [string length $x] [string length $y] $z
} {3 7 edb882eda0bd58}
test encoding-15.10 {UtfToUtfProc high surrogate character output} {
    set x \uDE02\xE9
    set y [encoding convertto utf-8 \uDE02\xE9]
    set x \uDE02é
    set y [encoding convertto -profile tcl8 utf-8 \uDE02é]
    binary scan $y H* z
    list [string length $x] [string length $y] $z
} {2 5 edb882c3a9}
test encoding-15.11 {UtfToUtfProc low surrogate character output} {
    set x \uDA02\xE9
    set y [encoding convertto utf-8 \uDA02\xE9]
    set x \uDA02é
    set y [encoding convertto -profile tcl8 utf-8 \uDA02é]
    binary scan $y H* z
    list [string length $x] [string length $y] $z
} {2 5 eda882c3a9}
test encoding-15.12 {UtfToUtfProc high surrogate character output} {
    set x \uDE02Y
    set y [encoding convertto utf-8 \uDE02Y]
    set y [encoding convertto -profile tcl8 utf-8 \uDE02Y]
    binary scan $y H* z
    list [string length $x] [string length $y] $z
} {2 4 edb88259}
test encoding-15.13 {UtfToUtfProc low surrogate character output} {
    set x \uDA02Y
    set y [encoding convertto utf-8 \uDA02Y]
    set y [encoding convertto -profile tcl8 utf-8 \uDA02Y]
    binary scan $y H* z
    list [string length $x] [string length $y] $z
} {2 4 eda88259}
test encoding-15.14 {UtfToUtfProc high surrogate character output} {
    set x \uDE02
    set y [encoding convertto utf-8 \uDE02]
    set y [encoding convertto -profile tcl8 utf-8 \uDE02]
    binary scan $y H* z
    list [string length $x] [string length $y] $z
} {1 3 edb882}
test encoding-15.15 {UtfToUtfProc low surrogate character output} {
    set x \uDA02
    set y [encoding convertto utf-8 \uDA02]
    set y [encoding convertto -profile tcl8 utf-8 \uDA02]
    binary scan $y H* z
    list [string length $x] [string length $y] $z
} {1 3 eda882}
test encoding-15.16 {UtfToUtfProc: Invalid 4-byte UTF-8, see [ed29806ba]} {
    set x \xF0\xA0\xA1\xC2
    set y [encoding convertfrom utf-8 \xF0\xA0\xA1\xC2]
    set y [encoding convertfrom -profile tcl8 utf-8 \xF0\xA0\xA1\xC2]
    list [string length $x] $y
} "4 \xF0\xA0\xA1\xC2"
test encoding-15.17 {UtfToUtfProc emoji character output} {
    set x \U1F602
    set y [encoding convertto utf-8 \U1F602]
    set x 😂
    set y [encoding convertto utf-8 😂]
    binary scan $y H* z
    list [string length $y] $z
} {4 f09f9882}
test encoding-15.18 {UtfToUtfProc CESU-8 6-byte sequence} {
    set y [encoding convertto cesu-8 \U10000]
    binary scan $y H* z
    list [string length $y] $z
} {6 eda080edb080}
test encoding-15.19 {UtfToUtfProc CESU-8 upper surrogate} {
    set y [encoding convertto cesu-8 \uD800]
    binary scan $y H* z
    list [string length $y] $z
} {3 eda080}
test encoding-15.20 {UtfToUtfProc CESU-8 lower surrogate} {
    set y [encoding convertto cesu-8 \uDC00]
    binary scan $y H* z
    list [string length $y] $z
} {3 edb080}
test encoding-15.21 {UtfToUtfProc CESU-8 noncharacter} {
    set y [encoding convertto cesu-8 \uFFFF]
    binary scan $y H* z
    list [string length $y] $z
} {3 efbfbf}
test encoding-15.22 {UtfToUtfProc CESU-8 bug [048dd20b4171c8da]} {
    set y [encoding convertto cesu-8 \x80]
    binary scan $y H* z
    list [string length $y] $z
} {2 c280}
test encoding-15.23 {UtfToUtfProc CESU-8 bug [048dd20b4171c8da]} {
    set y [encoding convertto cesu-8 \u100]
    binary scan $y H* z
    list [string length $y] $z
} {2 c480}
test encoding-15.24 {UtfToUtfProc CESU-8 bug [048dd20b4171c8da]} {
    set y [encoding convertto cesu-8 \u3FF]
    binary scan $y H* z
    list [string length $y] $z
} {2 cfbf}
test encoding-15.25 {UtfToUtfProc CESU-8} {
    encoding convertfrom cesu-8 \x00
} \x00
test encoding-15.26 {UtfToUtfProc CESU-8} {
    encoding convertfrom -profile tcl8 cesu-8 \xC0\x80
} \x00
test encoding-15.27 {UtfToUtfProc -profile strict CESU-8} {
    encoding convertfrom -profile strict cesu-8 \x00
} \x00
test encoding-15.28 {UtfToUtfProc -profile strict CESU-8} -body {
    encoding convertfrom -profile strict cesu-8 \xC0\x80
} -returnCodes 1 -result {unexpected byte sequence starting at index 0: '\xC0'}
test encoding-15.29 {UtfToUtfProc CESU-8} {
    encoding convertto cesu-8 \x00
} \x00
test encoding-15.30 {UtfToUtfProc -profile strict CESU-8} {
    encoding convertto -profile strict cesu-8 \x00
} \x00
test encoding-15.31 {UtfToUtfProc -profile strict CESU-8 (bytes F0-F4 are invalid)} -body {
    encoding convertfrom -profile strict cesu-8 \xF1\x86\x83\x9C
} -returnCodes 1 -result {unexpected byte sequence starting at index 0: '\xF1'}
test encoding-15.32 {UtfToUtfProc CESU-8 [2f22a7364d]} -body {
    encoding convertto cesu-8 \U1f600
} -result \xED\xA0\xBD\xED\xB8\x80
test encoding-15.33 {UtfToUtfProc CESU-8 [63325009a8]} -body {
    encoding convertto cesu-8 \u0400
} -result \xD0\x80

test encoding-16.1 {Utf16ToUtfProc} -body {
    set val [encoding convertfrom utf-16 NN]
    list $val [format %x [scan $val %c]]
} -result "\u4E4E 4e4e"
} -result "乎 4e4e"
test encoding-16.2 {Utf16ToUtfProc} -body {
    set val [encoding convertfrom utf-16 "\xD8\xD8\xDC\xDC"]
    list $val [format %x [scan $val %c]]
} -result "\U460DC 460dc"
test encoding-16.3 {Utf16ToUtfProc} -body {
    set val [encoding convertfrom utf-16 "\xDC\xDC"]
    set val [encoding convertfrom -profile tcl8 utf-16 "\xDC\xDC"]
    list $val [format %x [scan $val %c]]
} -result "\uDCDC dcdc"
test encoding-16.4 {Ucs2ToUtfProc} -body {
    set val [encoding convertfrom ucs-2 NN]
    list $val [format %x [scan $val %c]]
} -result "\u4E4E 4e4e"
test encoding-16.4 {Ucs2ToUtfProc} -body {
} -result "乎 4e4e"
test encoding-16.5 {Ucs2ToUtfProc} -body {
    set val [encoding convertfrom ucs-2 "\xD8\xD8\xDC\xDC"]
    list $val [format %x [scan $val %c]]
} -result "\U460DC 460dc"
test encoding-16.6 {Utf32ToUtfProc} -body {
    set val [encoding convertfrom utf-32le NN\0\0]
    list $val [format %x [scan $val %c]]
} -result "乎 4e4e"
test encoding-16.7 {Utf32ToUtfProc} -body {
    set val [encoding convertfrom utf-32be \0\0NN]
    list $val [format %x [scan $val %c]]
} -result "乎 4e4e"
test encoding-16.8 {Utf32ToUtfProc} -body {
    set val [encoding convertfrom -profile tcl8 utf-32 \x41\x00\x00\x41]
    list $val [format %x [scan $val %c]]
} -result "\uFFFD fffd"
test encoding-16.9 {Utf32ToUtfProc} -body {
    encoding convertfrom -profile tcl8 utf-32le \x00\xD8\x00\x00
} -result \uD800
test encoding-16.10 {Utf32ToUtfProc} -body {
    encoding convertfrom -profile tcl8 utf-32le \x00\xDC\x00\x00
} -result \uDC00
test encoding-16.11 {Utf32ToUtfProc} -body {
    encoding convertfrom -profile tcl8 utf-32le \x00\xD8\x00\x00\x00\xDC\x00\x00
} -result \uD800\uDC00
test encoding-16.12 {Utf32ToUtfProc} -body {
    encoding convertfrom -profile tcl8 utf-32le \x00\xDC\x00\x00\x00\xD8\x00\x00
} -result \uDC00\uD800
test encoding-16.13 {Utf16ToUtfProc} -body {
    encoding convertfrom -profile tcl8 utf-16le \x00\xD8
} -result \uD800
test encoding-16.14 {Utf16ToUtfProc} -body {
    encoding convertfrom -profile tcl8 utf-16le \x00\xDC
} -result \uDC00
test encoding-16.15 {Utf16ToUtfProc} -body {
    encoding convertfrom utf-16le \x00\xD8\x00\xDC
} -result \U010000
test encoding-16.16 {Utf16ToUtfProc} -body {
    encoding convertfrom -profile tcl8 utf-16le \x00\xDC\x00\xD8
} -result \uDC00\uD800
test encoding-16.17 {Utf32ToUtfProc} -body {
    list [encoding convertfrom -profile strict -failindex  idx utf-32le \x41\x00\x00\x00\x00\xD8\x00\x00\x42\x00\x00\x00] [set idx]
} -result {A 4}

test encoding-16.18 {
    Utf16ToUtfProc, Tcl_UniCharToUtf, surrogate pairs in utf-16
} -body {
    apply [list {} {
	for {set i 0xD800} {$i < 0xDBFF} {incr i} {
	    for {set j 0xDC00} {$j < 0xDFFF} {incr j} {
		set string [binary format S2 [list $i $j]]
		set status [catch {
		    set decoded [encoding convertfrom utf-16be $string]
		    set encoded [encoding convertto utf-16be $decoded]
		}]
		if {$status || ( $encoded ne $string )} {
		    return [list [format %x $i] [format %x $j]]
		}
	    }
	}
	return done
    } [namespace current]]
} -result done
test encoding-16.19.strict {Utf16ToUtfProc, bug [d19fe0a5b]} -body {
    encoding convertfrom -profile strict utf-16 "\x41\x41\x41"
} -returnCodes 1 -result {unexpected byte sequence starting at index 2: '\x41'}
test encoding-16.19.tcl8 {Utf16ToUtfProc, bug [d19fe0a5b]} -body {
    encoding convertfrom -profile tcl8 utf-16 "\x41\x41\x41"
} -result \u4141\uFFFD
test encoding-16.20.tcl8 {Utf16ToUtfProc, bug [d19fe0a5b]} -body {
    encoding convertfrom -profile tcl8 utf-16 "\xD8\xD8"
} -result \uD8D8
test encoding-16.20.strict {Utf16ToUtfProc, bug [d19fe0a5b]} -body {
    encoding convertfrom -profile strict utf-16 "\xD8\xD8"
} -returnCodes 1 -result {unexpected byte sequence starting at index 0: '\xD8'}
test encoding-16.21.tcl8 {Utf32ToUtfProc, bug [d19fe0a5b]} -body {
    encoding convertfrom -profile tcl8 utf-32 "\x00\x00\x00\x00\x41\x41"
} -result \x00\uFFFD
test encoding-16.21.strict {Utf32ToUtfProc, bug [d19fe0a5b]} -body {
    encoding convertfrom -profile strict utf-32 "\x00\x00\x00\x00\x41\x41"
} -returnCodes 1 -result {unexpected byte sequence starting at index 4: '\x41'}
test encoding-16.22 {Utf16ToUtfProc, strict, bug [db7a085bd9]} -body {
    encoding convertfrom -profile strict utf-16le \x00\xD8
} -returnCodes 1 -result {unexpected byte sequence starting at index 0: '\x00'}
test encoding-16.23 {Utf16ToUtfProc, strict, bug [db7a085bd9]} -body {
    encoding convertfrom -profile strict utf-16le \x00\xDC
} -returnCodes 1 -result {unexpected byte sequence starting at index 0: '\x00'}
test encoding-16.24 {Utf32ToUtfProc} -body {
    encoding convertfrom -profile tcl8 utf-32 "\xFF\xFF\xFF\xFF"
} -result \uFFFD
test encoding-16.25.strict {Utf32ToUtfProc} -body {
    encoding convertfrom -profile strict utf-32 "\x01\x00\x00\x01"
} -returnCodes 1 -result {unexpected byte sequence starting at index 0: '\x01'}
test encoding-16.25.tcl8 {Utf32ToUtfProc} -body {
    encoding convertfrom -profile tcl8 utf-32 "\x01\x00\x00\x01"
} -result \uFFFD

test encoding-17.1 {UtfToUtf16Proc} -body {
    encoding convertto utf-16 "\U460DC"
} -result "\xD8\xD8\xDC\xDC"
test encoding-17.2 {UtfToUtf16Proc} -body {
    encoding convertto utf-16 "\uDCDC"
} -result "\xDC\xDC"
test encoding-17.2 {UtfToUcs2Proc} -body {
    encoding convertfrom utf-16 \xD8\xD8\xDC\xDC
} -result "\U460DC"
test encoding-17.3 {UtfToUtf16Proc} -body {
    encoding convertto utf-16 "\uD8D8"
} -result "\xD8\xD8"
test encoding-17.4 {UtfToUcs2Proc} -body {
    encoding convertfrom utf-16 [encoding convertto ucs-2 "\U460DC"]
} -result "\uFFFD"
    encoding convertto -profile tcl8 utf-16be "\uDCDC"
} -result "\xDC\xDC"
test encoding-17.4 {UtfToUtf16Proc} -body {
    encoding convertto -profile tcl8 utf-16le "\uD8D8"
} -result "\xD8\xD8"
test encoding-17.5 {UtfToUtf32Proc} -body {
    encoding convertto utf-32le "\U460DC"
} -result "\xDC\x60\x04\x00"
test encoding-17.6 {UtfToUtf32Proc} -body {
    encoding convertto utf-32be "\U460DC"
} -result "\x00\x04\x60\xDC"
test encoding-17.7 {UtfToUtf16Proc} -body {
    encoding convertto -profile strict utf-16be "\uDCDC"
} -returnCodes error -result {unexpected character at index 0: 'U+00DCDC'}
test encoding-17.8 {UtfToUtf16Proc} -body {
    encoding convertto -profile strict utf-16le "\uD8D8"
} -returnCodes error -result {unexpected character at index 0: 'U+00D8D8'}
test encoding-17.9 {Utf32ToUtfProc} -body {
    encoding convertfrom -profile strict utf-32 "\xFF\xFF\xFF\xFF"
} -returnCodes error -result {unexpected byte sequence starting at index 0: '\xFF'}
test encoding-17.10 {Utf32ToUtfProc} -body {
    encoding convertfrom -profile tcl8 utf-32 "\xFF\xFF\xFF\xFF"
} -result \uFFFD
test encoding-17.11 {Utf32ToUtfProc} -body {
    encoding convertfrom -profile strict utf-32le "\x00\xD8\x00\x00"
} -returnCodes error -result {unexpected byte sequence starting at index 0: '\x00'}
test encoding-17.12 {Utf32ToUtfProc} -body {
    encoding convertfrom -profile strict utf-32le "\x00\xDC\x00\x00"
} -returnCodes error -result {unexpected byte sequence starting at index 0: '\x00'}

test encoding-18.1 {TableToUtfProc} {
} {}
test encoding-18.1 {TableToUtfProc on invalid input} -body {
	list [catch {encoding convertto -profile tcl8 jis0208 \\} res] $res
} -result {0 !)}
test encoding-18.2 {TableToUtfProc on invalid input with -profile strict} -body {
	list [catch {encoding convertto -profile strict jis0208 \\} res] $res
} -result {1 {unexpected character at index 0: 'U+00005C'}}
test encoding-18.3 {TableToUtfProc on invalid input with -profile strict -failindex} -body {
	list [catch {encoding convertto -profile strict -failindex pos jis0208 \\} res] $res $pos
} -result {0 {} 0}
test encoding-18.4 {TableToUtfProc on invalid input with -failindex -profile strict} -body {
	list [catch {encoding convertto -failindex pos -profile strict jis0208 \\} res] $res $pos
} -result {0 {} 0}
test encoding-18.5 {TableToUtfProc on invalid input with -failindex} -body {
	list [catch {encoding convertto -profile tcl8 -failindex pos jis0208 \\} res] $res $pos
} -result {0 !) -1}
test encoding-18.6 {TableToUtfProc on invalid input with -profile tcl8} -body {
	list [catch {encoding convertto -profile tcl8 jis0208 \\} res] $res
} -result {0 !)}

test encoding-19.1 {TableFromUtfProc} {
} {}
test encoding-19.1 {TableFromUtfProc} -body {
    encoding convertfrom -profile tcl8 ascii AÃ
} -result AÃ
test encoding-19.2 {TableFromUtfProc} -body {
    encoding convertfrom -profile tcl8 ascii AÃ
} -result AÃ
test encoding-19.3 {TableFromUtfProc} -body {
    encoding convertfrom -profile strict ascii AÃ
} -returnCodes 1 -result {unexpected byte sequence starting at index 1: '\xC1'}
test encoding-19.4 {TableFromUtfProc} -body {
    list [encoding convertfrom -profile tcl8 -failindex idx ascii AÃ] [set idx]
} -result [list A\xC1 -1]
test encoding-19.5 {TableFromUtfProc} -body {
    list [encoding convertfrom -failindex idx -profile strict ascii A\xC1] [set idx]
} -result {A 1}
test encoding-19.6 {TableFromUtfProc} -body {
    list [encoding convertfrom -failindex idx -profile strict ascii AÃB] [set idx]
} -result {A 1}

test encoding-20.1 {TableFreefProc} {
} {}

test encoding-21.1 {EscapeToUtfProc} {
} {}

test encoding-22.1 {EscapeFromUtfProc} {
} {}

set iso2022encData "\u001b\$B;d\$I\$b\$G\$O!\"%A%C%W\$49XF~;~\$K\$4EPO?\$\$\$?\$@\$\$\$?\$4=;=j\$r%-%c%C%7%e%\"%&%H\$N:]\$N\u001b(B
\u001b\$B>.@Z<jAwIU@h\$H\$7\$F;HMQ\$7\$F\$*\$j\$^\$9!#62\$lF~\$j\$^\$9\$,!\"@5\$7\$\$=;=j\$r\$4EPO?\$7\$J\$*\u001b(B
\u001b\$B\$*4j\$\$\$\$\$?\$7\$^\$9!#\$^\$?!\"BgJQ62=L\$G\$9\$,!\"=;=jJQ99\$N\$\"\$H!\"F|K\\8l%5!<%S%9It!J\u001b(B
casino_japanese@___.com \u001b\$B!K\$^\$G\$4=;=jJQ99:Q\$NO\"Mm\$r\$\$\$?\$@\$1\$J\$\$\$G\u001b(B
\u001b\$B\$7\$g\$&\$+!)\u001b(B"
set iso2022encData "\x1B\$B;d\$I\$b\$G\$O!\"%A%C%W\$49XF~;~\$K\$4EPO?\$\$\$?\$@\$\$\$?\$4=;=j\$r%-%c%C%7%e%\"%&%H\$N:]\$N\x1B(B
\x1B\$B>.@Z<jAwIU@h\$H\$7\$F;HMQ\$7\$F\$*\$j\$^\$9!#62\$lF~\$j\$^\$9\$,!\"@5\$7\$\$=;=j\$r\$4EPO?\$7\$J\$*\x1B(B
\x1B\$B\$*4j\$\$\$\$\$?\$7\$^\$9!#\$^\$?!\"BgJQ62=L\$G\$9\$,!\"=;=jJQ99\$N\$\"\$H!\"F|K\\8l%5!<%S%9It!J\x1B(B
casino_japanese@___.com \x1B\$B!K\$^\$G\$4=;=jJQ99:Q\$NO\"Mm\$r\$\$\$?\$@\$1\$J\$\$\$G\x1B(B
\x1B\$B\$7\$g\$&\$+!)\x1B(B"

set iso2022uniData [encoding convertfrom iso2022-jp $iso2022encData]
set iso2022uniData2 "\u79c1\u3069\u3082\u3067\u306f\u3001\u30c1\u30c3\u30d7\u3054\u8cfc\u5165\u6642\u306b\u3054\u767b\u9332\u3044\u305f\u3060\u3044\u305f\u3054\u4f4f\u6240\u3092\u30ad\u30e3\u30c3\u30b7\u30e5\u30a2\u30a6\u30c8\u306e\u969b\u306e
set iso2022uniData2 "ç§ã©ã‚‚ã§ã¯ã€ãƒãƒƒãƒ—ã”購入時ã«ã”登録ã„ãŸã ã„ãŸã”ä½æ‰€ã‚’キャッシュアウトã®éš›ã®
\u5c0f\u5207\u624b\u9001\u4ed8\u5148\u3068\u3057\u3066\u4f7f\u7528\u3057\u3066\u304a\u308a\u307e\u3059\u3002\u6050\u308c\u5165\u308a\u307e\u3059\u304c\u3001\u6b63\u3057\u3044\u4f4f\u6240\u3092\u3054\u767b\u9332\u3057\u306a\u304a
\u304a\u9858\u3044\u3044\u305f\u3057\u307e\u3059\u3002\u307e\u305f\u3001\u5927\u5909\u6050\u7e2e\u3067\u3059\u304c\u3001\u4f4f\u6240\u5909\u66f4\u306e\u3042\u3068\u3001\u65e5\u672c\u8a9e\u30b5\u30fc\u30d3\u30b9\u90e8\uff08
\u0063\u0061\u0073\u0069\u006e\u006f\u005f\u006a\u0061\u0070\u0061\u006e\u0065\u0073\u0065\u0040\u005f\u005f\u005f\u002e\u0063\u006f\u006d\u0020\uff09\u307e\u3067\u3054\u4f4f\u6240\u5909\u66f4\u6e08\u306e\u9023\u7d61\u3092\u3044\u305f\u3060\u3051\u306a\u3044\u3067
å°åˆ‡æ‰‹é€ä»˜å…ˆã¨ã—ã¦ä½¿ç”¨ã—ã¦ãŠã‚Šã¾ã™ã€‚æれ入りã¾ã™ãŒã€æ­£ã—ã„ä½æ‰€ã‚’ã”登録ã—ãªãŠ
ãŠé¡˜ã„ã„ãŸã—ã¾ã™ã€‚ã¾ãŸã€å¤§å¤‰æ縮ã§ã™ãŒã€ä½æ‰€å¤‰æ›´ã®ã‚ã¨ã€æ—¥æœ¬èªžã‚µãƒ¼ãƒ“ス部(
casino_japanese@___.com )ã¾ã§ã”ä½æ‰€å¤‰æ›´æ¸ˆã®é€£çµ¡ã‚’ã„ãŸã ã‘ãªã„ã§
\u3057\u3087\u3046\u304b\uff1f"
ã—ょã†ã‹ï¼Ÿ"

cd [temporaryDirectory]
set fid [open iso2022.txt w]
fconfigure $fid -encoding binary
fconfigure $fid -translation binary
puts -nonewline $fid $iso2022encData
close $fid

test encoding-23.1 {iso2022-jp escape encoding test} {
    string equal $iso2022uniData $iso2022uniData2
} 1
test encoding-23.2 {iso2022-jp escape encoding test} {
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
558

559
560
561

562
563
564

565
566
567

568
569
570

571
572
573

574
575
576

577





















































































































578
579
580
581
582
583
584
739
740
741
742
743
744
745

746
747
748

749
750
751


752
753
754
755
756
757
758

759
760
761
762
763
764
765
766


767
768
769
770
771
772



773
774
775
776

777
778
779

780
781
782

783
784
785

786
787
788

789
790
791

792
793
794

795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920







-
+


-
+


-
-
+
+





-
+







-
-
+
+

+
+
+
-
-
-
+
+
+

-
+


-
+


-
+


-
+


-
+


-
+


-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	set f [open [file join [file dirname [info script]] iso2022.txt]]
	fconfigure $f -encoding iso2022-jp
	gets $f
    }
} {}
test encoding-24.2 {EscapeFreeProc on open channels} {exec} {
    # Bug #524674 output
    viewable [runInSubprocess {
    runInSubprocess {
	encoding system cp1252;	# Bug #2891556 crash revelator
	fconfigure stdout -encoding iso2022-jp
	puts ab\u4e4e\u68d9g
	puts ab乎棙g
	set env(TCL_FINALIZE_ON_EXIT) 1
	exit
    }]
} "ab\x1b\$B8C\x1b\$(DD%\x1b(Bg (ab\\u001b\$B8C\\u001b\$(DD%\\u001b(Bg)"
    }
} "ab\x1B\$B8C\x1B\$(DD%\x1B(Bg"
test encoding-24.3 {EscapeFreeProc on open channels} {stdio} {
    # Bug #219314 - if we don't free escape encodings correctly on channel
    # closure, we go boom
    set file [makeFile {
	encoding system iso2022-jp
	set a "\u4e4e\u4e5e\u4e5f"; # 3 Japanese Kanji letters
	set a "乎乞也"; # 3 Japanese Kanji letters
	puts $a
    } iso2022.tcl]
    set f [open "|[list [interpreter] $file]"]
    fconfigure $f -encoding iso2022-jp
    set count [gets $f line]
    close $f
    removeFile iso2022.tcl
    list $count [viewable $line]
} [list 3 "\u4e4e\u4e5e\u4e5f (\\u4e4e\\u4e5e\\u4e5f)"]
    list $count $line
} [list 3 乎乞也]

test encoding-24.4.strict {Parse invalid utf-8, strict} -body {
    encoding convertfrom -profile strict utf-8 "\xC0\x80"
} -returnCodes 1 -result {unexpected byte sequence starting at index 0: '\xC0'}
test encoding-24.4 {Parse valid or invalid utf-8} {
    string length [encoding convertfrom utf-8 "\xc0\x80"]
} 1
test encoding-24.4.tcl8 {UtfToUtfProc utf-8} {
    encoding convertfrom -profile tcl8 utf-8 \xC0\x80
} \x00
test encoding-24.5 {Parse valid or invalid utf-8} {
    string length [encoding convertfrom utf-8 "\xc0\x81"]
    string length [encoding convertfrom -profile tcl8 utf-8 "\xC0\x81"]
} 2
test encoding-24.6 {Parse valid or invalid utf-8} {
    string length [encoding convertfrom utf-8 "\xc1\xbf"]
    string length [encoding convertfrom -profile tcl8 utf-8 "\xC1\xBF"]
} 2
test encoding-24.7 {Parse valid or invalid utf-8} {
    string length [encoding convertfrom utf-8 "\xc2\x80"]
    string length [encoding convertfrom utf-8 "\xC2\x80"]
} 1
test encoding-24.8 {Parse valid or invalid utf-8} {
    string length [encoding convertfrom utf-8 "\xe0\x80\x80"]
    string length [encoding convertfrom -profile tcl8 utf-8 "\xE0\x80\x80"]
} 3
test encoding-24.9 {Parse valid or invalid utf-8} {
    string length [encoding convertfrom utf-8 "\xe0\x9f\xbf"]
    string length [encoding convertfrom -profile tcl8 utf-8 "\xE0\x9F\xBF"]
} 3
test encoding-24.10 {Parse valid or invalid utf-8} {
    string length [encoding convertfrom utf-8 "\xe0\xa0\x80"]
    string length [encoding convertfrom utf-8 "\xE0\xA0\x80"]
} 1
test encoding-24.11 {Parse valid or invalid utf-8} {
    string length [encoding convertfrom utf-8 "\xef\xbf\xbf"]
    string length [encoding convertfrom -profile tcl8 utf-8 "\xEF\xBF\xBF"]
} 1
test encoding-24.12 {Parse invalid utf-8} -body {
    encoding convertfrom -profile tcl8 utf-8 "\xC0\x81"
} -result \xC0\x81
test encoding-24.12.1 {Parse invalid utf-8} -body {
    encoding convertfrom -profile strict utf-8 "\xC0\x81"
} -returnCodes 1 -result {unexpected byte sequence starting at index 0: '\xC0'}
test encoding-24.13 {Parse invalid utf-8} -body {
    encoding convertfrom -profile tcl8 utf-8 "\xC1\xBF"
} -result \xC1\xBF
test encoding-24.13.1 {Parse invalid utf-8} -body {
    encoding convertfrom -profile strict utf-8 "\xC1\xBF"
} -returnCodes 1 -result {unexpected byte sequence starting at index 0: '\xC1'}
test encoding-24.14 {Parse valid utf-8} {
    encoding convertfrom utf-8 "\xC2\x80"
} \x80
test encoding-24.15.strict {Parse invalid utf-8, -profile strict} -body {
    encoding convertfrom -profile strict utf-8 "Z\xE0\x80"
} -returnCodes 1 -result "unexpected byte sequence starting at index 1: '\\xE0'"
test encoding-24.15.tcl8 {Parse invalid utf-8, -profile tcl8} -body {
    encoding convertfrom -profile tcl8 utf-8 "Z\xE0\x80"
} -result Z\xE0\u20AC
test encoding-24.16 {Parse valid or invalid utf-8} -constraints testbytestring -body {
    encoding convertto utf-8 [testbytestring "Z\u4343\x80"]
} -returnCodes 1 -result {expected byte sequence but character 1 was 'äƒÂ€' (U+004343)}
test encoding-24.17 {Parse valid or invalid utf-8} -constraints testbytestring -body {
    encoding convertto utf-8 [testbytestring "Z\xE0\x80"]
} -result "Z\xC3\xA0\xE2\x82\xAC"
test encoding-24.18 {Parse valid or invalid utf-8} -constraints testbytestring -body {
    encoding convertto utf-8 [testbytestring "Z\xE0\x80xxxxxx"]
} -result "Z\xC3\xA0\xE2\x82\xACxxxxxx"
test encoding-24.19.1 {Parse valid or invalid utf-8} -body {
    encoding convertto -profile tcl8 utf-8 "ZX\uD800"
} -result ZX\xED\xA0\x80
test encoding-24.19.2 {Parse valid or invalid utf-8} -body {
    encoding convertto -profile strict utf-8 "ZX\uD800"
} -returnCodes 1 -match glob -result "unexpected character at index 2: 'U+00D800'"
test encoding-24.20 {Parse with -profile tcl8 but without providing encoding} -body {
    encoding convertfrom -profile tcl8 "\x20"
} -result {wrong # args: should be "::tcl::encoding::convertfrom ?-profile profile? ?-failindex var? encoding data" or "::tcl::encoding::convertfrom data"} -returnCodes error
test encoding-24.21 {Parse with -profile tcl8 but without providing encoding} -body {
    string length [encoding convertto -profile tcl8 "\x20"]
} -result {wrong # args: should be "::tcl::encoding::convertto ?-profile profile? ?-failindex var? encoding data" or "::tcl::encoding::convertto data"} -returnCodes error
test encoding-24.22 {Syntax error, two encodings} -body {
    encoding convertfrom iso8859-1 utf-8 "ZX\uD800"
} -result {bad option "iso8859-1": must be -profile or -failindex} -returnCodes error
test encoding-24.23 {Syntax error, two encodings} -body {
    encoding convertto iso8859-1 utf-8 "ZX\uD800"
} -result {bad option "iso8859-1": must be -profile or -failindex} -returnCodes error
test encoding-24.24 {Parse invalid utf-8 with -profile strict} -body {
    encoding convertfrom -profile strict utf-8 "\xC0\x80\x00\x00"
} -returnCodes 1 -result {unexpected byte sequence starting at index 0: '\xC0'}
test encoding-24.25 {Parse invalid utf-8 with -profile strict} -body {
    encoding convertfrom -profile strict utf-8 "\x40\x80\x00\x00"
} -returnCodes 1 -result {unexpected byte sequence starting at index 1: '\x80'}
test encoding-24.26 {Parse valid utf-8 with -profile strict} -body {
    encoding convertfrom -profile strict utf-8 "\xF1\x80\x80\x80"
} -result \U40000
test encoding-24.27 {Parse invalid utf-8 with -profile strict} -body {
    encoding convertfrom -profile strict utf-8 "\xF0\x80\x80\x80"
} -returnCodes 1 -result {unexpected byte sequence starting at index 0: '\xF0'}
test encoding-24.28 {Parse invalid utf-8 with -profile strict} -body {
    encoding convertfrom -profile strict utf-8 "\xFF\x00\x00"
} -returnCodes 1 -result {unexpected byte sequence starting at index 0: '\xFF'}
test encoding-24.29 {Parse invalid utf-8} -body {
    encoding convertfrom utf-8 \xEF\xBF\xBF
} -result \uFFFF
test encoding-24.30 {Parse noncharacter with -profile strict} -body {
    encoding convertfrom -profile strict utf-8 \xEF\xBF\xBF
} -result \uFFFF
test encoding-24.31 {Parse invalid utf-8 with -profile tcl8} -body {
    encoding convertfrom -profile tcl8 utf-8 \xEF\xBF\xBF
} -result \uFFFF
test encoding-24.32 {Try to generate invalid utf-8} -body {
    encoding convertto utf-8 \uFFFF
} -result \xEF\xBF\xBF
test encoding-24.33 {Try to generate invalid utf-8} -body {
    encoding convertto -profile strict utf-8 \uFFFF
} -result \xEF\xBF\xBF
test encoding-24.34 {Try to generate invalid utf-8 with -profile tcl8} -body {
    encoding convertto -profile tcl8 utf-8 \uFFFF
} -result \xEF\xBF\xBF
test encoding-24.35 {Parse invalid utf-8} -body {
    encoding convertfrom -profile tcl8 utf-8 \xED\xA0\x80
} -result \uD800
test encoding-24.36 {Parse invalid utf-8 with -profile strict} -body {
    encoding convertfrom -profile strict utf-8 \xED\xA0\x80
} -returnCodes 1 -result {unexpected byte sequence starting at index 0: '\xED'}
test encoding-24.37 {Parse invalid utf-8 with -profile tcl8} -body {
    encoding convertfrom -profile tcl8 utf-8 \xED\xA0\x80
} -result \uD800
test encoding-24.38.1 {Try to generate invalid utf-8} -body {
    encoding convertto -profile tcl8 utf-8 \uD800
} -result \xED\xA0\x80
test encoding-24.38.2 {Try to generate invalid utf-8 - default profile} -body {
    encoding convertto utf-8 \uD800
} -returnCodes 1 -result {unexpected character at index 0: 'U+00D800'}
test encoding-24.39 {Try to generate invalid utf-8 with -profile strict} -body {
    encoding convertto -profile strict utf-8 \uD800
} -returnCodes 1 -result {unexpected character at index 0: 'U+00D800'}
test encoding-24.40 {Try to generate invalid utf-8 with -profile tcl8} -body {
    encoding convertto -profile tcl8 utf-8 \uD800
} -result \xED\xA0\x80
test encoding-24.41 {Parse invalid utf-8 with -profile strict} -body {
    encoding convertfrom -profile strict utf-8 \xED\xA0\x80\xED\xB0\x80
} -returnCodes 1 -result {unexpected byte sequence starting at index 0: '\xED'}
test encoding-24.42 {Parse invalid utf-8, fallback to cp1252 [885c86a9a0]} -body {
    encoding convertfrom -profile tcl8 utf-8 \xF0\x80\x80\x80
} -result \xF0\u20AC\u20AC\u20AC
test encoding-24.43 {Parse invalid utf-8, fallback to cp1252 [885c86a9a0]} -body {
    encoding convertfrom -profile tcl8 utf-8 \x80
} -result \u20AC
test encoding-24.44 {Try to generate invalid ucs-2 with -profile strict} -body {
    encoding convertto -profile strict ucs-2 \uD800
} -returnCodes 1 -result {unexpected character at index 0: 'U+00D800'}
test encoding-24.45 {Try to generate invalid ucs-2 with -profile strict} -body {
    encoding convertto -profile strict ucs-2 \U10000
} -returnCodes 1 -result {unexpected character at index 0: 'U+010000'}

file delete [file join [temporaryDirectory] iso2022.txt]

#
# Begin jajp encoding round-trip conformity tests
#
proc foreach-jisx0208 {varName command} {
623
624
625
626
627
628
629
630

631
632
633
634

635
636
637
638
639
640
641


642
643

644
645
646
647
648
649
650
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







-
+



-
+





-
-
+
+

-
+







	} else {
	    error "really?"
	}
    }
}
proc gen-jisx0208-euc-jp {code} {
    binary format cc \
	[expr {($code >> 8) | 0x80}] [expr {($code & 0xff) | 0x80}]
	[expr {($code >> 8) | 0x80}] [expr {($code & 0xFF) | 0x80}]
}
proc gen-jisx0208-iso2022-jp {code} {
    binary format a3cca3 \
	"\x1b\$B" [expr {$code >> 8}] [expr {$code & 0xff}] "\x1b(B"
	"\x1B\$B" [expr {$code >> 8}] [expr {$code & 0xFF}] "\x1B(B"
}
proc gen-jisx0208-cp932 {code} {
    set c1 [expr {($code >> 8) | 0x80}]
    set c2 [expr {($code & 0xff)| 0x80}]
    if {$c1 % 2} {
	set c1 [expr {($c1 >> 1) + ($c1 < 0xdf ? 0x31 : 0x71)}]
	incr c2 [expr {- (0x60 + ($c2 < 0xe0))}]
	set c1 [expr {($c1 >> 1) + ($c1 < 0xDF ? 0x31 : 0x71)}]
	incr c2 [expr {- (0x60 + ($c2 < 0xE0))}]
    } else {
	set c1 [expr {($c1 >> 1) + ($c1 < 0xdf ? 0x30 : 0x70)}]
	set c1 [expr {($c1 >> 1) + ($c1 < 0xDF ? 0x30 : 0x70)}]
	incr c2 -2
    }
    binary format cc $c1 $c2
}
proc channel-diff {fa fb} {
    set diff {}
    while {[gets $fa la] >= 0 && [gets $fb lb] >= 0} {
660
661
662
663
664
665
666
667

668
669
670
671
672
673
674
996
997
998
999
1000
1001
1002

1003
1004
1005
1006
1007
1008
1009
1010







-
+







    return $diff
}

# Create char tables.
cd [temporaryDirectory]
foreach enc {cp932 euc-jp iso2022-jp} {
    set f [open $enc.chars w]
    fconfigure $f -encoding binary
    fconfigure $f -encoding iso8859-1
    foreach-jisx0208 code {
	puts $f [format "%04X %s" $code [gen-jisx0208-$enc $code]]
    }
    close $f
}
# shiftjis == cp932 for jisx0208.
file copy -force cp932.chars shiftjis.chars
694
695
696
697
698
699
700
701

702
703
704
705


706
707

708
709

710
711
712
713
714
715
716
1030
1031
1032
1033
1034
1035
1036

1037




1038
1039
1040

1041
1042

1043
1044
1045
1046
1047
1048
1049
1050







-
+
-
-
-
-
+
+

-
+

-
+







	} -cleanup {
	    close $fa
	    close $fb
	} -result {}
    }
}

test encoding-26.0 {Tcl_GetEncodingSearchPath} -constraints {
test encoding-26.0 {Tcl_GetEncodingSearchPath} -setup {
    testgetencpath
} -setup {
    set origPath [testgetencpath]
    testsetencpath slappy
    set origPath [encoding dirs]
    encoding dirs slappy
} -body {
    testgetencpath
    encoding dirs
} -cleanup {
    testsetencpath $origPath
    encoding dirs $origPath
} -result slappy

file delete {*}[glob -directory [temporaryDirectory] *.chars *.tcltestout]
# ===> Cut here <===

# EscapeFreeProc, GetTableEncoding, unilen are fully tested by the rest of
# this file.
728
729
730
731
732
733
734
735

736
737
738
739
740
741
742

743
744
745






746














































































































747
748
749
750
751
752
753
754
755
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204







-
+






-
+



+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










test encoding-28.0 {all encodings load} -body {
	set string hello
	foreach name [encoding names] {
		if {$name ne "unicode"} {
		    incr count
		}
		encoding convertto $name $string
		encoding convertto -profile tcl8 $name $string

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

runtests

test encoding-bug-183a1adcc0-1 {Bug [183a1adcc0] Buffer overflow Tcl_UtfToExternal} -constraints {
    testencoding
} -body {
    # Note - buffers are initialized to \xFF
    list [catch {testencoding Tcl_UtfToExternal utf-16 A {start end} {} 1} result] $result
} -result [list 0 [list nospace {} \xFF]]
}

test encoding-bug-183a1adcc0-2 {Bug [183a1adcc0] Buffer overflow Tcl_UtfToExternal} -constraints {
    testencoding
} -body {
    # Note - buffers are initialized to \xFF
    list [catch {testencoding Tcl_UtfToExternal utf-16 A {start end} {} 0} result] $result
} -result [list 0 [list nospace {} {}]]

test encoding-bug-183a1adcc0-3 {Bug [183a1adcc0] Buffer overflow Tcl_UtfToExternal} -constraints {
    testencoding
} -body {
    # Note - buffers are initialized to \xFF
    list [catch {testencoding Tcl_UtfToExternal utf-16 A {start end} {} 2} result] $result
} -result [list 0 [list nospace {} \x00\x00]]

test encoding-bug-183a1adcc0-4 {Bug [183a1adcc0] Buffer overflow Tcl_UtfToExternal} -constraints {
    testencoding
} -body {
    # Note - buffers are initialized to \xFF
    list [catch {testencoding Tcl_UtfToExternal utf-16 A {start end} {} 3} result] $result
} -result [list 0 [list nospace {} \x00\x00\xFF]]

test encoding-bug-183a1adcc0-5 {Bug [183a1adcc0] Buffer overflow Tcl_UtfToExternal} -constraints {
    testencoding
} -body {
    list [catch {testencoding Tcl_UtfToExternal utf-16 A {start end} {} 4} result] $result
} -result [list 0 [list ok {} [expr {$::tcl_platform(byteOrder) eq "littleEndian" ? "\x41\x00" : "\x00\x41"}]\x00\x00]]

}

test encoding-29.0 {get encoding nul terminator lengths} -constraints {
    testencoding
} -body {
    list \
	[testencoding nullength ascii] \
	[testencoding nullength utf-16] \
	[testencoding nullength utf-32] \
	[testencoding nullength gb12345] \
	[testencoding nullength ksc5601]
} -result {1 2 4 2 2}

test encoding-30.0 {encoding convertto large strings UINT_MAX} -constraints {
    perf
} -body {
    # Test to ensure not misinterpreted as -1
    list [string length [set s [string repeat A 0xFFFFFFFF]]] [string equal $s [encoding convertto ascii $s]]
} -result {4294967295 1}

test encoding-30.1 {encoding convertto large strings > 4GB} -constraints {
    perf
} -body {
    list [string length [set s [string repeat A 0x100000000]]] [string equal $s [encoding convertto ascii $s]]
} -result {4294967296 1}

test encoding-30.2 {encoding convertfrom large strings UINT_MAX} -constraints {
    perf
} -body {
    # Test to ensure not misinterpreted as -1
    list [string length [set s [string repeat A 0xFFFFFFFF]]] [string equal $s [encoding convertfrom ascii $s]]
} -result {4294967295 1}

test encoding-30.3 {encoding convertfrom large strings > 4GB} -constraints {
    perf
} -body {
    list [string length [set s [string repeat A 0x100000000]]] [string equal $s [encoding convertfrom ascii $s]]
} -result {4294967296 1}

test encoding-bug-6a3e2cb0f0-1 {Bug [6a3e2cb0f0] - invalid bytes in escape encodings} -body {
    encoding convertfrom -profile tcl8 iso2022-jp x\x1B\x7Aaby
} -result x\uFFFDy
test encoding-bug-6a3e2cb0f0-2 {Bug [6a3e2cb0f0] - invalid bytes in escape encodings} -body {
    encoding convertfrom -profile strict iso2022-jp x\x1B\x7Aaby
} -returnCodes error -result {unexpected byte sequence starting at index 1: '\x1B'}
test encoding-bug-6a3e2cb0f0-3 {Bug [6a3e2cb0f0] - invalid bytes in escape encodings} -body {
    encoding convertfrom -profile replace iso2022-jp x\x1B\x7Aaby
} -result x\uFFFDy

test encoding-bug-66ffafd309-1-tcl8 {Bug [66ffafd309] - truncated DBCS} -body {
    encoding convertfrom -profile tcl8 gb12345 x
} -result x
test encoding-bug-66ffafd309-1-strict {Bug [66ffafd309] - truncated DBCS} -body {
    encoding convertfrom -profile strict gb12345 x
} -result {unexpected byte sequence starting at index 0: '\x78'} -returnCodes error
test encoding-bug-66ffafd309-1-replace {Bug [66ffafd309] - truncated DBCS} -body {
    encoding convertfrom -profile replace gb12345 x
} -result \uFFFD
test encoding-bug-66ffafd309-2-tcl8 {Bug [66ffafd309] - invalid DBCS} -body {
    # Not truncated but invalid
    encoding convertfrom -profile tcl8 jis0208 \x78\x79
} -result \x78\x79
test encoding-bug-66ffafd309-2-strict {Bug [66ffafd309] - invalid DBCS} -body {
    # Not truncated but invalid
    encoding convertfrom -profile strict jis0208 \x78\x79
} -result {unexpected byte sequence starting at index 1: '\x79'} -returnCodes error
test encoding-bug-66ffafd309-2-replace {Bug [66ffafd309] - invalid DBCS} -body {
    # Not truncated but invalid
    encoding convertfrom -profile replace jis0208 \x78\x79
} -result \uFFFD\uFFFD

test encoding-bug-201c7a3aa6-strict {Crash encoding non-BMP to iso2022} -body {
    encoding convertto -profile strict iso2022 \U1f600
} -result {unexpected character at index 0: 'U+01F600'} -returnCodes error

test encoding-bug-201c7a3aa6-replace {Crash encoding non-BMP to iso2022} -body {
    encoding convertto -profile replace iso2022 \U1f600
} -result ?

test encoding-bug-201c7a3aa6-tcl8 {Crash encoding non-BMP to iso2022} -body {
    encoding convertto -profile tcl8 iso2022 \U1f600
} -result ?

# cleanup
namespace delete ::tcl::test::encoding
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Added tests/encodingVectors.tcl.


















































































































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# This file contains test vectors for verifying various encodings. They are
# stored in a common file so that they can be sourced into the various test
# modules that are dependent on encodings. This file contains statically defined
# test vectors. In addition, it sources the ICU-generated test vectors from
# icuUcmTests.tcl.
#
# Note that sourcing the file will reinitialize any existing encoding test
# vectors.
#

# List of defined encoding profiles
set encProfiles {tcl8 strict replace}
set encDefaultProfile strict; # Should reflect the default from implementation

# encValidStrings - Table of valid strings.
#
# Each row is <ENCODING STR BYTES CTRL COMMENT>
# The pair <ENCODING,STR> should be unique for generated test ids to be unique.
# STR is a string that can be encoded in the encoding ENCODING resulting
# in the byte sequence BYTES. The CTRL field is a list that controls test
# generation. It may contain zero or more of `solo`, `lead`, `tail` and
# `middle` indicating that the generated tests should include the string
# by itself, as the lead of a longer string, as the tail of a longer string
# and in the middle of a longer string. If CTRL is empty, it is treated as
# containing all four of the above. The CTRL field may also contain the
# words knownBug or knownW3C which will cause the test generation for that
# vector to be skipped.
#
# utf-16, utf-32 missing because they are automatically
# generated based on le/be versions.
set encValidStrings {}; # Reset the table

lappend encValidStrings {*}{
    ascii    \u0000 00 {} {Lowest ASCII}
    ascii    \u007F 7F {} {Highest ASCII}
    ascii    \u007D 7D {} {Brace - just to verify test scripts are escaped correctly}
    ascii    \u007B 7B {} {Terminating brace - just to verify test scripts are escaped correctly}

    utf-8    \u0000 00 {} {Unicode Table 3.7 Row 1}
    utf-8    \u007F 7F {} {Unicode Table 3.7 Row 1}
    utf-8    \u0080 C280 {} {Unicode Table 3.7 Row 2}
    utf-8    \u07FF DFBF {} {Unicode Table 3.7 Row 2}
    utf-8    \u0800 E0A080 {} {Unicode Table 3.7 Row 3}
    utf-8    \u0FFF E0BFBF {} {Unicode Table 3.7 Row 3}
    utf-8    \u1000 E18080 {} {Unicode Table 3.7 Row 4}
    utf-8    \uCFFF ECBFBF {} {Unicode Table 3.7 Row 4}
    utf-8    \uD000 ED8080 {} {Unicode Table 3.7 Row 5}
    utf-8    \uD7FF ED9FBF {} {Unicode Table 3.7 Row 5}
    utf-8    \uE000 EE8080 {} {Unicode Table 3.7 Row 6}
    utf-8    \uFFFF EFBFBF {} {Unicode Table 3.7 Row 6}
    utf-8    \U10000 F0908080 {} {Unicode Table 3.7 Row 7}
    utf-8    \U3FFFF F0BFBFBF {} {Unicode Table 3.7 Row 7}
    utf-8    \U40000 F1808080 {} {Unicode Table 3.7 Row 8}
    utf-8    \UFFFFF F3BFBFBF {} {Unicode Table 3.7 Row 8}
    utf-8    \U100000 F4808080 {} {Unicode Table 3.7 Row 9}
    utf-8    \U10FFFF F48FBFBF {} {Unicode Table 3.7 Row 9}
    utf-8    A\u03A9\u8A9E\U00010384 41CEA9E8AA9EF0908E84 {} {Unicode 2.5}

    utf-16le \u0000 0000 {} {Lowest code unit}
    utf-16le \uD7FF FFD7 {} {Below high surrogate range}
    utf-16le \uE000 00E0 {} {Above low surrogate range}
    utf-16le \uFFFF FFFF {} {Highest code unit}
    utf-16le \U010000 00D800DC {} {First surrogate pair}
    utf-16le \U10FFFF FFDBFFDF {} {First surrogate pair}
    utf-16le A\u03A9\u8A9E\U00010384 4100A9039E8A00D884DF {} {Unicode 2.5}

    utf-16be \u0000 0000 {} {Lowest code unit}
    utf-16be \uD7FF D7FF {} {Below high surrogate range}
    utf-16be \uE000 E000 {} {Above low surrogate range}
    utf-16be \uFFFF FFFF {} {Highest code unit}
    utf-16be \U010000 D800DC00 {} {First surrogate pair}
    utf-16be \U10FFFF DBFFDFFF {} {First surrogate pair}
    utf-16be A\u03A9\u8A9E\U00010384 004103A98A9ED800DF84 {} {Unicode 2.5}

    utf-32le \u0000 00000000 {} {Lowest code unit}
    utf-32le \uFFFF FFFF0000 {} {Highest BMP}
    utf-32le \U010000 00000100 {} {First supplementary}
    utf-32le \U10FFFF ffff1000 {} {Last supplementary}
    utf-32le A\u03A9\u8A9E\U00010384 41000000A90300009E8A000084030100 {} {Unicode 2.5}

    utf-32be \u0000 00000000 {} {Lowest code unit}
    utf-32be \uFFFF 0000FFFF {} {Highest BMP}
    utf-32be \U010000 00010000 {} {First supplementary}
    utf-32be \U10FFFF 0010FFFF {} {Last supplementary}
    utf-32be A\u03A9\u8A9E\U00010384 00000041000003A900008A9E00010384 {} {Unicode 2.5}
}

# encInvalidBytes - Table of invalid byte sequences
# These are byte sequences that should appear for an encoding. Each row is
# of the form
#    <ENCODING BYTES PROFILE EXPECTEDRESULT EXPECTEDFAILINDEX CTRL COMMENT>
# The triple <ENCODING,BYTES,PROFILE> should be unique for test ids to be
# unique. BYTES is a byte sequence that is invalid. EXPECTEDRESULT is the
# expected string when the bytes are decoded using the PROFILE profile.
# FAILINDEX gives the expected index of the invalid byte under that profile. The
# CTRL field is a list that controls test generation. It may contain zero or
# more of `solo`, `lead`, `tail` and `middle` indicating that the generated the
# tail of a longer and in the middle of a longer string. If empty, it is treated
# as containing all four of the above. The CTRL field may also contain the words
# knownBug or knownW3C which will cause the test generation for that vector to
# be skipped.
#
# utf-32 missing because they are automatically generated based on le/be
# versions.
set encInvalidBytes {}; # Reset the table

# ascii - Any byte above 127 is invalid and is mapped
# to the same numeric code point except for the range
# 80-9F which is treated as cp1252.
# This tests the TableToUtfProc code path.
lappend encInvalidBytes {*}{
    ascii 80 tcl8    \u20AC -1 {} {map to cp1252}
    ascii 80 replace \uFFFD -1 {} {Smallest invalid byte}
    ascii 80 strict  {}      0 {} {Smallest invalid byte}
    ascii 81 tcl8    \u0081 -1 {} {map to cp1252}
    ascii 82 tcl8    \u201A -1 {} {map to cp1252}
    ascii 83 tcl8    \u0192 -1 {} {map to cp1252}
    ascii 84 tcl8    \u201E -1 {} {map to cp1252}
    ascii 85 tcl8    \u2026 -1 {} {map to cp1252}
    ascii 86 tcl8    \u2020 -1 {} {map to cp1252}
    ascii 87 tcl8    \u2021 -1 {} {map to cp1252}
    ascii 88 tcl8    \u02C6 -1 {} {map to cp1252}
    ascii 89 tcl8    \u2030 -1 {} {map to cp1252}
    ascii 8A tcl8    \u0160 -1 {} {map to cp1252}
    ascii 8B tcl8    \u2039 -1 {} {map to cp1252}
    ascii 8C tcl8    \u0152 -1 {} {map to cp1252}
    ascii 8D tcl8    \u008D -1 {} {map to cp1252}
    ascii 8E tcl8    \u017D -1 {} {map to cp1252}
    ascii 8F tcl8    \u008F -1 {} {map to cp1252}
    ascii 90 tcl8    \u0090 -1 {} {map to cp1252}
    ascii 91 tcl8    \u2018 -1 {} {map to cp1252}
    ascii 92 tcl8    \u2019 -1 {} {map to cp1252}
    ascii 93 tcl8    \u201C -1 {} {map to cp1252}
    ascii 94 tcl8    \u201D -1 {} {map to cp1252}
    ascii 95 tcl8    \u2022 -1 {} {map to cp1252}
    ascii 96 tcl8    \u2013 -1 {} {map to cp1252}
    ascii 97 tcl8    \u2014 -1 {} {map to cp1252}
    ascii 98 tcl8    \u02DC -1 {} {map to cp1252}
    ascii 99 tcl8    \u2122 -1 {} {map to cp1252}
    ascii 9A tcl8    \u0161 -1 {} {map to cp1252}
    ascii 9B tcl8    \u203A -1 {} {map to cp1252}
    ascii 9C tcl8    \u0153 -1 {} {map to cp1252}
    ascii 9D tcl8    \u009D -1 {} {map to cp1252}
    ascii 9E tcl8    \u017E -1 {} {map to cp1252}
    ascii 9F tcl8    \u0178 -1 {} {map to cp1252}

    ascii FF tcl8    \u00FF -1 {} {Largest invalid byte}
    ascii FF replace \uFFFD -1 {} {Largest invalid byte}
    ascii FF strict  {}      0 {} {Largest invalid byte}
}

# utf-8 - valid sequences based on Table 3.7 in the Unicode
# standard.
#
# Code Points        First   Second  Third   Fourth Byte
# U+0000..U+007F     00..7F
# U+0080..U+07FF     C2..DF  80..BF
# U+0800..U+0FFF     E0      A0..BF  80..BF
# U+1000..U+CFFF     E1..EC  80..BF  80..BF
# U+D000..U+D7FF     ED      80..9F  80..BF
# U+E000..U+FFFF     EE..EF  80..BF  80..BF
# U+10000..U+3FFFF   F0      90..BF  80..BF  80..BF
# U+40000..U+FFFFF   F1..F3  80..BF  80..BF  80..BF
# U+100000..U+10FFFF F4      80..8F  80..BF  80..BF
#
# Tests below are based on the "gaps" in the above table. Note ascii test
# values are repeated because internally a different code path is used
# (UtfToUtfProc).
# Note C0, C1, F5:FF are invalid bytes ANYWHERE. Exception is C080
lappend encInvalidBytes {*}{
    utf-8 80 tcl8    \u20AC -1 {} {map to cp1252}
    utf-8 80 replace \uFFFD -1 {} {Smallest invalid byte}
    utf-8 80 strict  {}      0 {} {Smallest invalid byte}
    utf-8 81 tcl8    \u0081 -1 {} {map to cp1252}
    utf-8 82 tcl8    \u201A -1 {} {map to cp1252}
    utf-8 83 tcl8    \u0192 -1 {} {map to cp1252}
    utf-8 84 tcl8    \u201E -1 {} {map to cp1252}
    utf-8 85 tcl8    \u2026 -1 {} {map to cp1252}
    utf-8 86 tcl8    \u2020 -1 {} {map to cp1252}
    utf-8 87 tcl8    \u2021 -1 {} {map to cp1252}
    utf-8 88 tcl8    \u02C6 -1 {} {map to cp1252}
    utf-8 89 tcl8    \u2030 -1 {} {map to cp1252}
    utf-8 8A tcl8    \u0160 -1 {} {map to cp1252}
    utf-8 8B tcl8    \u2039 -1 {} {map to cp1252}
    utf-8 8C tcl8    \u0152 -1 {} {map to cp1252}
    utf-8 8D tcl8    \u008D -1 {} {map to cp1252}
    utf-8 8E tcl8    \u017D -1 {} {map to cp1252}
    utf-8 8F tcl8    \u008F -1 {} {map to cp1252}
    utf-8 90 tcl8    \u0090 -1 {} {map to cp1252}
    utf-8 91 tcl8    \u2018 -1 {} {map to cp1252}
    utf-8 92 tcl8    \u2019 -1 {} {map to cp1252}
    utf-8 93 tcl8    \u201C -1 {} {map to cp1252}
    utf-8 94 tcl8    \u201D -1 {} {map to cp1252}
    utf-8 95 tcl8    \u2022 -1 {} {map to cp1252}
    utf-8 96 tcl8    \u2013 -1 {} {map to cp1252}
    utf-8 97 tcl8    \u2014 -1 {} {map to cp1252}
    utf-8 98 tcl8    \u02DC -1 {} {map to cp1252}
    utf-8 99 tcl8    \u2122 -1 {} {map to cp1252}
    utf-8 9A tcl8    \u0161 -1 {} {map to cp1252}
    utf-8 9B tcl8    \u203A -1 {} {map to cp1252}
    utf-8 9C tcl8    \u0153 -1 {} {map to cp1252}
    utf-8 9D tcl8    \u009D -1 {} {map to cp1252}
    utf-8 9E tcl8    \u017E -1 {} {map to cp1252}
    utf-8 9F tcl8    \u0178 -1 {} {map to cp1252}

    utf-8 C0 tcl8    \u00C0 -1 {} {C0 is invalid anywhere}
    utf-8 C0 strict  {}      0 {} {C0 is invalid anywhere}
    utf-8 C0 replace \uFFFD -1 {} {C0 is invalid anywhere}
    utf-8 C080 tcl8    \u0000 -1 {} {C080 -> U+0 in Tcl's internal modified UTF8}
    utf-8 C080 strict  {}      0 {} {C080 -> invalid}
    utf-8 C080 replace \uFFFD -1 {} {C080 -> single replacement char}
    utf-8 C0A2 tcl8    \u00C0\u00A2 -1 {} {websec.github.io - A}
    utf-8 C0A2 replace \uFFFD\uFFFD -1 {} {websec.github.io - A}
    utf-8 C0A2 strict  {}            0 {} {websec.github.io - A}
    utf-8 C0A7 tcl8    \u00C0\u00A7 -1 {} {websec.github.io - double quote}
    utf-8 C0A7 replace \uFFFD\uFFFD -1 {} {websec.github.io - double quote}
    utf-8 C0A7 strict  {}            0 {} {websec.github.io - double quote}
    utf-8 C0AE tcl8    \u00C0\u00AE -1 {} {websec.github.io - full stop}
    utf-8 C0AE replace \uFFFD\uFFFD -1 {} {websec.github.io - full stop}
    utf-8 C0AE strict  {}            0 {} {websec.github.io - full stop}
    utf-8 C0AF tcl8    \u00C0\u00AF -1 {} {websec.github.io - solidus}
    utf-8 C0AF replace \uFFFD\uFFFD -1 {} {websec.github.io - solidus}
    utf-8 C0AF strict  {}            0 {} {websec.github.io - solidus}

    utf-8 C1 tcl8    \u00C1 -1 {} {C1 is invalid everywhere}
    utf-8 C1 replace \uFFFD -1 {} {C1 is invalid everywhere}
    utf-8 C1 strict  {}      0 {} {C1 is invalid everywhere}
    utf-8 C181 tcl8    \u00C1\u0081 -1 {} {websec.github.io - base test (A)}
    utf-8 C181 replace \uFFFD\uFFFD -1 {} {websec.github.io - base test (A)}
    utf-8 C181 strict  {}            0 {} {websec.github.io - base test (A)}
    utf-8 C19C tcl8    \u00C1\u0153 -1 {} {websec.github.io - reverse solidus}
    utf-8 C19C replace \uFFFD\uFFFD -1 {} {websec.github.io - reverse solidus}
    utf-8 C19C strict  {}            0 {} {websec.github.io - reverse solidus}

    utf-8 C2 tcl8      \u00C2     -1 {} {Missing trail byte}
    utf-8 C2 replace   \uFFFD     -1 {} {Missing trail byte}
    utf-8 C2 strict    {}          0 {} {Missing trail byte}
    utf-8 C27F tcl8    \u00C2\x7F -1 {} {Trail byte must be 80:BF}
    utf-8 C27F replace \uFFFD\x7F -1 {} {Trail byte must be 80:BF}
    utf-8 C27F strict  {}          0 {} {Trail byte must be 80:BF}
    utf-8 DF tcl8      \u00DF     -1 {} {Missing trail byte}
    utf-8 DF replace   \uFFFD     -1 {} {Missing trail byte}
    utf-8 DF strict    {}          0 {} {Missing trail byte}
    utf-8 DF7F tcl8    \u00DF\x7F -1 {} {Trail byte must be 80:BF}
    utf-8 DF7F replace \uFFFD\x7F -1 {} {Trail byte must be 80:BF}
    utf-8 DF7F strict  {}          0 {} {Trail byte must be 80:BF}
    utf-8 DFE0A080 tcl8    \u00DF\u0800 -1 {} {Invalid trail byte is start of valid sequence}
    utf-8 DFE0A080 replace \uFFFD\u0800 -1 {} {Invalid trail byte is start of valid sequence}
    utf-8 DFE0A080 strict  {}            0 {} {Invalid trail byte is start of valid sequence}

    utf-8 E0 tcl8      \u00E0     -1 {} {Missing trail byte}
    utf-8 E0 replace   \uFFFD     -1 {} {Missing trail byte}
    utf-8 E0 strict    {}          0 {} {Missing trail byte}
    utf-8 E080 tcl8      \u00E0\u20AC   -1 {} {First trail byte must be A0:BF}
    utf-8 E080 replace   \uFFFD\uFFFD   -1 {} {First trail byte must be A0:BF}
    utf-8 E080 strict    {}              0 {} {First trail byte must be A0:BF}
    utf-8 E0819C tcl8    \u00E0\u0081\u0153 -1 {} {websec.github.io - reverse solidus}
    utf-8 E0819C replace \uFFFD\uFFFD\uFFFD -1 {} {websec.github.io - reverse solidus}
    utf-8 E0819C strict  {}                  0 {} {websec.github.io - reverse solidus}
    utf-8 E09F tcl8      \u00E0\u0178   -1 {} {First trail byte must be A0:BF}
    utf-8 E09F replace   \uFFFD\uFFFD   -1 {} {First trail byte must be A0:BF}
    utf-8 E09F strict    {}              0 {} {First trail byte must be A0:BF}
    utf-8 E0A0 tcl8      \u00E0\u00A0   -1 {} {Missing second trail byte}
    utf-8 E0A0 replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 E0A0 strict    {}              0 {} {Missing second trail byte}
    utf-8 E0BF tcl8      \u00E0\u00BF   -1 {} {Missing second trail byte}
    utf-8 E0BF replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 E0BF strict    {}              0 {} {Missing second trail byte}
    utf-8 E0A07F tcl8    \u00E0\u00A0\x7F   -1 {}     {Second trail byte must be 80:BF}
    utf-8 E0A07F replace \uFFFD\u7F         -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 E0A07F strict  {}                  0 {}         {Second trail byte must be 80:BF}
    utf-8 E0BF7F tcl8    \u00E0\u00BF\x7F   -1 {}         {Second trail byte must be 80:BF}
    utf-8 E0BF7F replace \uFFFD\u7F         -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 E0BF7F strict  {}                  0 {}         {Second trail byte must be 80:BF}

    utf-8 E1 tcl8      \u00E1     -1 {} {Missing trail byte}
    utf-8 E1 replace   \uFFFD     -1 {} {Missing trail byte}
    utf-8 E1 strict    {}          0 {} {Missing trail byte}
    utf-8 E17F tcl8    \u00E1\x7F -1 {} {Trail byte must be 80:BF}
    utf-8 E17F replace \uFFFD\x7F -1 {} {Trail byte must be 80:BF}
    utf-8 E17F strict  {}          0 {} {Trail byte must be 80:BF}
    utf-8 E181 tcl8      \u00E1\u0081   -1 {} {Missing second trail byte}
    utf-8 E181 replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 E181 strict    {}              0 {} {Missing second trail byte}
    utf-8 E1BF tcl8      \u00E1\u00BF   -1 {} {Missing second trail byte}
    utf-8 E1BF replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 E1BF strict    {}              0 {} {Missing second trail byte}
    utf-8 E1807F tcl8    \u00E1\u20AC\x7F   -1 {} {Second trail byte must be 80:BF}
    utf-8 E1807F replace \uFFFD\u7F         -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 E1807F strict  {}                  0 {}         {Second trail byte must be 80:BF}
    utf-8 E1BF7F tcl8    \u00E1\u00BF\x7F   -1 {}         {Second trail byte must be 80:BF}
    utf-8 E1BF7F replace \uFFFD\u7F         -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 E1BF7F strict  {}                  0 {}         {Second trail byte must be 80:BF}
    utf-8 EC tcl8      \u00EC     -1 {} {Missing trail byte}
    utf-8 EC replace   \uFFFD     -1 {} {Missing trail byte}
    utf-8 EC strict    {}          0 {} {Missing trail byte}
    utf-8 EC7F tcl8    \u00EC\x7F -1 {} {Trail byte must be 80:BF}
    utf-8 EC7F replace \uFFFD\x7F -1 {} {Trail byte must be 80:BF}
    utf-8 EC7F strict  {}          0 {} {Trail byte must be 80:BF}
    utf-8 EC81 tcl8      \u00EC\u0081   -1 {} {Missing second trail byte}
    utf-8 EC81 replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 EC81 strict    {}              0 {} {Missing second trail byte}
    utf-8 ECBF tcl8      \u00EC\u00BF   -1 {} {Missing second trail byte}
    utf-8 ECBF replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 ECBF strict    {}              0 {} {Missing second trail byte}
    utf-8 EC807F tcl8    \u00EC\u20AC\x7F   -1 {} {Second trail byte must be 80:BF}
    utf-8 EC807F replace \uFFFD\u7F         -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 EC807F strict  {}                  0 {}         {Second trail byte must be 80:BF}
    utf-8 ECBF7F tcl8    \u00EC\u00BF\x7F   -1 {}         {Second trail byte must be 80:BF}
    utf-8 ECBF7F replace \uFFFD\u7F         -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 ECBF7F strict  {}                  0 {}         {Second trail byte must be 80:BF}

    utf-8 ED tcl8       \u00ED        -1 {} {Missing trail byte}
    utf-8 ED replace    \uFFFD        -1 {} {Missing trail byte}
    utf-8 ED strict     {}             0 {} {Missing trail byte}
    utf-8 ED7F tcl8     \u00ED\u7F    -1 {} {First trail byte must be 80:9F}
    utf-8 ED7F replace  \uFFFD\u7F    -1 {} {First trail byte must be 80:9F}
    utf-8 ED7F strict   {}             0 {} {First trail byte must be 80:9F}
    utf-8 EDA0 tcl8     \u00ED\u00A0  -1 {} {First trail byte must be 80:9F}
    utf-8 EDA0 replace  \uFFFD\uFFFD  -1 {} {First trail byte must be 80:9F}
    utf-8 EDA0 strict   {}             0 {} {First trail byte must be 80:9F}
    utf-8 ED81 tcl8      \u00ED\u0081   -1 {} {Missing second trail byte}
    utf-8 ED81 replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 ED81 strict    {}              0 {} {Missing second trail byte}
    utf-8 EDBF tcl8      \u00ED\u00BF   -1 {} {Missing second trail byte}
    utf-8 EDBF replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 EDBF strict    {}              0 {} {Missing second trail byte}
    utf-8 ED807F tcl8      \u00ED\u20AC\x7F -1 {} {Second trail byte must be 80:BF}
    utf-8 ED807F replace   \uFFFD\u7F       -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 ED807F strict    {}                0 {}  {Second trail byte must be 80:BF}
    utf-8 ED9F7F tcl8      \u00ED\u0178\x7F -1 {} {Second trail byte must be 80:BF}
    utf-8 ED9F7F replace   \uFFFD\u7F       -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 ED9F7F strict    {}                0 {}  {Second trail byte must be 80:BF}
    utf-8 EDA080 tcl8       \uD800          -1 {}  {High surrogate}
    utf-8 EDA080 replace    \uFFFD          -1 {}  {High surrogate}
    utf-8 EDA080 strict     {}               0 {}  {High surrogate}
    utf-8 EDAFBF tcl8       \uDBFF          -1 {}  {High surrogate}
    utf-8 EDAFBF replace    \uFFFD          -1 {}  {High surrogate}
    utf-8 EDAFBF strict     {}               0 {}  {High surrogate}
    utf-8 EDB080 tcl8       \uDC00          -1 {}  {Low surrogate}
    utf-8 EDB080 replace    \uFFFD          -1 {}  {Low surrogate}
    utf-8 EDB080 strict     {}               0 {}  {Low surrogate}
    utf-8 EDBFBF tcl8       \uDFFF          -1 {}  {Low surrogate}
    utf-8 EDBFBF replace    \uFFFD          -1 {}  {Low surrogate}
    utf-8 EDBFBF strict     {}               0 {}  {Low surrogate}
    utf-8 EDA080EDB080 tcl8 \uD800\uDC00    -1 {}  {High low surrogate pair}
    utf-8 EDA080EDB080 replace \uFFFD\uFFFD -1 {}  {High low surrogate pair}
    utf-8 EDA080EDB080 strict {}             0 {}  {High low surrogate pair}
    utf-8 EDAFBFEDBFBF tcl8 \uDBFF\uDFFF    -1 {}  {High low surrogate pair}
    utf-8 EDAFBFEDBFBF replace \uFFFD\uFFFD -1 {}  {High low surrogate pair}
    utf-8 EDAFBFEDBFBF strict {}             0 {}  {High low surrogate pair}

    utf-8 EE tcl8       \u00EE        -1 {} {Missing trail byte}
    utf-8 EE replace    \uFFFD        -1 {} {Missing trail byte}
    utf-8 EE strict     {}             0 {} {Missing trail byte}
    utf-8 EE7F tcl8     \u00EE\u7F    -1 {} {First trail byte must be 80:BF}
    utf-8 EE7F replace  \uFFFD\u7F    -1 {} {First trail byte must be 80:BF}
    utf-8 EE7F strict   {}             0 {} {First trail byte must be 80:BF}
    utf-8 EED0 tcl8     \u00EE\u00D0  -1 {} {First trail byte must be 80:BF}
    utf-8 EED0 replace  \uFFFD\uFFFD  -1 {} {First trail byte must be 80:BF}
    utf-8 EED0 strict   {}             0 {} {First trail byte must be 80:BF}
    utf-8 EE81 tcl8      \u00EE\u0081   -1 {} {Missing second trail byte}
    utf-8 EE81 replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 EE81 strict    {}              0 {} {Missing second trail byte}
    utf-8 EEBF tcl8      \u00EE\u00BF   -1 {} {Missing second trail byte}
    utf-8 EEBF replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 EEBF strict    {}              0 {} {Missing second trail byte}
    utf-8 EE807F tcl8      \u00EE\u20AC\x7F -1 {} {Second trail byte must be 80:BF}
    utf-8 EE807F replace   \uFFFD\u7F       -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 EE807F strict    {}                0 {}  {Second trail byte must be 80:BF}
    utf-8 EEBF7F tcl8      \u00EE\u00BF\x7F -1 {} {Second trail byte must be 80:BF}
    utf-8 EEBF7F replace   \uFFFD\u7F       -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 EEBF7F strict    {}                0 {}  {Second trail byte must be 80:BF}
    utf-8 EF tcl8       \u00EF        -1 {} {Missing trail byte}
    utf-8 EF replace    \uFFFD        -1 {} {Missing trail byte}
    utf-8 EF strict     {}             0 {} {Missing trail byte}
    utf-8 EF7F tcl8     \u00EF\u7F    -1 {} {First trail byte must be 80:BF}
    utf-8 EF7F replace  \uFFFD\u7F    -1 {} {First trail byte must be 80:BF}
    utf-8 EF7F strict   {}             0 {} {First trail byte must be 80:BF}
    utf-8 EFD0 tcl8     \u00EF\u00D0  -1 {} {First trail byte must be 80:BF}
    utf-8 EFD0 replace  \uFFFD\uFFFD  -1 {} {First trail byte must be 80:BF}
    utf-8 EFD0 strict   {}             0 {} {First trail byte must be 80:BF}
    utf-8 EF81 tcl8      \u00EF\u0081   -1 {} {Missing second trail byte}
    utf-8 EF81 replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 EF81 strict    {}              0 {} {Missing second trail byte}
    utf-8 EFBF tcl8      \u00EF\u00BF   -1 {} {Missing second trail byte}
    utf-8 EFBF replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 EFBF strict    {}              0 {} {Missing second trail byte}
    utf-8 EF807F tcl8      \u00EF\u20AC\x7F -1 {} {Second trail byte must be 80:BF}
    utf-8 EF807F replace   \uFFFD\u7F       -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 EF807F strict    {}                0 {}  {Second trail byte must be 80:BF}
    utf-8 EFBF7F tcl8      \u00EF\u00BF\x7F -1 {} {Second trail byte must be 80:BF}
    utf-8 EFBF7F replace   \uFFFD\u7F       -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 EFBF7F strict    {}                0 {}  {Second trail byte must be 80:BF}

    utf-8 F0 tcl8       \u00F0        -1 {} {Missing trail byte}
    utf-8 F0 replace    \uFFFD        -1 {} {Missing trail byte}
    utf-8 F0 strict     {}             0 {} {Missing trail byte}
    utf-8 F080 tcl8     \u00F0\u20AC  -1 {} {First trail byte must be 90:BF}
    utf-8 F080 replace  \uFFFD        -1 {knownW3C} {First trail byte must be 90:BF}
    utf-8 F080 strict   {}             0 {} {First trail byte must be 90:BF}
    utf-8 F08F tcl8     \u00F0\u8F    -1 {} {First trail byte must be 90:BF}
    utf-8 F08F replace  \uFFFD        -1 {knownW3C} {First trail byte must be 90:BF}
    utf-8 F08F strict   {}             0 {} {First trail byte must be 90:BF}
    utf-8 F0D0 tcl8     \u00F0\u00D0  -1 {} {First trail byte must be 90:BF}
    utf-8 F0D0 replace  \uFFFD\uFFFD  -1 {} {First trail byte must be 90:BF}
    utf-8 F0D0 strict   {}             0 {} {First trail byte must be 90:BF}
    utf-8 F090 tcl8      \u00F0\u0090   -1 {} {Missing second trail byte}
    utf-8 F090 replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 F090 strict    {}              0 {} {Missing second trail byte}
    utf-8 F0BF tcl8      \u00F0\u00BF   -1 {} {Missing second trail byte}
    utf-8 F0BF replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 F0BF strict    {}              0 {} {Missing second trail byte}
    utf-8 F0907F tcl8      \u00F0\u0090\x7F -1 {} {Second trail byte must be 80:BF}
    utf-8 F0907F replace   \uFFFD\u7F       -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 F0907F strict    {}                0 {}  {Second trail byte must be 80:BF}
    utf-8 F0BF7F tcl8      \u00F0\u00BF\x7F -1 {} {Second trail byte must be 80:BF}
    utf-8 F0BF7F replace   \uFFFD\u7F       -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 F0BF7F strict    {}                0 {}  {Second trail byte must be 80:BF}
    utf-8 F090BF tcl8      \u00F0\u0090\u00BF   -1 {} {Missing third trail byte}
    utf-8 F090BF replace   \uFFFD         -1 {knownW3C} {Missing third trail byte}
    utf-8 F090BF strict    {}              0 {} {Missing third trail byte}
    utf-8 F0BF81 tcl8      \u00F0\u00BF\u0081   -1 {} {Missing third trail byte}
    utf-8 F0BF81 replace   \uFFFD         -1 {knownW3C} {Missing third trail byte}
    utf-8 F0BF81 strict    {}              0 {} {Missing third trail byte}
    utf-8 F0BF807F tcl8      \u00F0\u00BF\u20AC\x7F   -1 {} {Third trail byte must be 80:BF}
    utf-8 F0BF817F replace   \uFFFD\x7F           -1 {knownW3C} {Third trail byte must be 80:BF}
    utf-8 F0BF817F strict    {}              0 {} {Third trail byte must be 80:BF}
    utf-8 F090BFD0 tcl8      \u00F0\u0090\u00BF\u00D0   -1 {} {Third trail byte must be 80:BF}
    utf-8 F090BFD0 replace   \uFFFD         -1 {knownW3C} {Third trail byte must be 80:BF}
    utf-8 F090BFD0 strict    {}              0 {} {Third trail byte must be 80:BF}

    utf-8 F1 tcl8       \u00F1        -1 {} {Missing trail byte}
    utf-8 F1 replace    \uFFFD        -1 {} {Missing trail byte}
    utf-8 F1 strict     {}             0 {} {Missing trail byte}
    utf-8 F17F tcl8     \u00F1\u7F    -1 {} {First trail byte must be 80:BF}
    utf-8 F17F replace  \uFFFD        -1 {knownW3C} {First trail byte must be 80:BF}
    utf-8 F17F strict   {}             0 {} {First trail byte must be 80:BF}
    utf-8 F1D0 tcl8     \u00F1\u00D0  -1 {} {First trail byte must be 80:BF}
    utf-8 F1D0 replace  \uFFFD\uFFFD  -1 {} {First trail byte must be 80:BF}
    utf-8 F1D0 strict   {}             0 {} {First trail byte must be 80:BF}
    utf-8 F180 tcl8      \u00F1\u20AC   -1 {} {Missing second trail byte}
    utf-8 F180 replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 F180 strict    {}              0 {} {Missing second trail byte}
    utf-8 F1BF tcl8      \u00F1\u00BF   -1 {} {Missing second trail byte}
    utf-8 F1BF replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 F1BF strict    {}              0 {} {Missing second trail byte}
    utf-8 F1807F tcl8      \u00F1\u20AC\x7F -1 {} {Second trail byte must be 80:BF}
    utf-8 F1807F replace   \uFFFD\u7F       -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 F1807F strict    {}                0 {}  {Second trail byte must be 80:BF}
    utf-8 F1BF7F tcl8      \u00F1\u00BF\x7F -1 {} {Second trail byte must be 80:BF}
    utf-8 F1BF7F replace   \uFFFD\u7F       -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 F1BF7F strict    {}                0 {}  {Second trail byte must be 80:BF}
    utf-8 F180BF tcl8      \u00F1\u20AC\u00BF   -1 {} {Missing third trail byte}
    utf-8 F180BF replace   \uFFFD         -1 {knownW3C} {Missing third trail byte}
    utf-8 F180BF strict    {}              0 {} {Missing third trail byte}
    utf-8 F1BF81 tcl8      \u00F1\u00BF\u0081   -1 {} {Missing third trail byte}
    utf-8 F1BF81 replace   \uFFFD         -1 {knownW3C} {Missing third trail byte}
    utf-8 F1BF81 strict    {}              0 {} {Missing third trail byte}
    utf-8 F1BF807F tcl8      \u00F1\u00BF\u20AC\x7F   -1 {} {Third trail byte must be 80:BF}
    utf-8 F1BF817F replace   \uFFFD\x7F           -1 {knownW3C} {Third trail byte must be 80:BF}
    utf-8 F1BF817F strict    {}              0 {} {Third trail byte must be 80:BF}
    utf-8 F180BFD0 tcl8      \u00F1\u20AC\u00BF\u00D0   -1 {} {Third trail byte must be 80:BF}
    utf-8 F180BFD0 replace   \uFFFD         -1 {knownW3C} {Third trail byte must be 80:BF}
    utf-8 F180BFD0 strict    {}              0 {} {Third trail byte must be 80:BF}
    utf-8 F3 tcl8       \u00F3        -1 {} {Missing trail byte}
    utf-8 F3 replace    \uFFFD        -1 {} {Missing trail byte}
    utf-8 F3 strict     {}             0 {} {Missing trail byte}
    utf-8 F37F tcl8     \u00F3\x7F    -1 {} {First trail byte must be 80:BF}
    utf-8 F37F replace  \uFFFD        -1 {knownW3C} {First trail byte must be 80:BF}
    utf-8 F37F strict   {}             0 {} {First trail byte must be 80:BF}
    utf-8 F3D0 tcl8     \u00F3\u00D0  -1 {} {First trail byte must be 80:BF}
    utf-8 F3D0 replace  \uFFFD\uFFFD  -1 {} {First trail byte must be 80:BF}
    utf-8 F3D0 strict   {}             0 {} {First trail byte must be 80:BF}
    utf-8 F380 tcl8      \u00F3\u20AC   -1 {} {Missing second trail byte}
    utf-8 F380 replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 F380 strict    {}              0 {} {Missing second trail byte}
    utf-8 F3BF tcl8      \u00F3\u00BF   -1 {} {Missing second trail byte}
    utf-8 F3BF replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 F3BF strict    {}              0 {} {Missing second trail byte}
    utf-8 F3807F tcl8      \u00F3\u20AC\x7F -1 {} {Second trail byte must be 80:BF}
    utf-8 F3807F replace   \uFFFD\u7F       -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 F3807F strict    {}                0 {}  {Second trail byte must be 80:BF}
    utf-8 F3BF7F tcl8      \u00F3\u00BF\x7F -1 {} {Second trail byte must be 80:BF}
    utf-8 F3BF7F replace   \uFFFD\u7F       -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 F3BF7F strict    {}                0 {}  {Second trail byte must be 80:BF}
    utf-8 F380BF tcl8      \u00F3\u20AC\u00BF   -1 {} {Missing third trail byte}
    utf-8 F380BF replace   \uFFFD         -1 {knownW3C} {Missing third trail byte}
    utf-8 F380BF strict    {}              0 {} {Missing third trail byte}
    utf-8 F3BF81 tcl8      \u00F3\u00BF\u0081   -1 {} {Missing third trail byte}
    utf-8 F3BF81 replace   \uFFFD         -1 {knownW3C} {Missing third trail byte}
    utf-8 F3BF81 strict    {}              0 {} {Missing third trail byte}
    utf-8 F3BF807F tcl8      \u00F3\u00BF\u20AC\x7F   -1 {} {Third trail byte must be 80:BF}
    utf-8 F3BF817F replace   \uFFFD\x7F           -1 {knownW3C} {Third trail byte must be 80:BF}
    utf-8 F3BF817F strict    {}              0 {} {Third trail byte must be 80:BF}
    utf-8 F380BFD0 tcl8      \u00F3\u20AC\u00BF\u00D0   -1 {} {Third trail byte must be 80:BF}
    utf-8 F380BFD0 replace   \uFFFD         -1 {knownW3C} {Third trail byte must be 80:BF}
    utf-8 F380BFD0 strict    {}              0 {} {Third trail byte must be 80:BF}

    utf-8 F4 tcl8       \u00F4        -1 {} {Missing trail byte}
    utf-8 F4 replace    \uFFFD        -1 {} {Missing trail byte}
    utf-8 F4 strict     {}             0 {} {Missing trail byte}
    utf-8 F47F tcl8     \u00F4\u7F    -1 {} {First trail byte must be 80:8F}
    utf-8 F47F replace  \uFFFD\u7F    -1 {knownW3C} {First trail byte must be 80:8F}
    utf-8 F47F strict   {}             0 {} {First trail byte must be 80:8F}
    utf-8 F490 tcl8     \u00F4\u0090  -1 {} {First trail byte must be 80:8F}
    utf-8 F490 replace  \uFFFD\uFFFD  -1 {} {First trail byte must be 80:8F}
    utf-8 F490 strict   {}             0 {} {First trail byte must be 80:8F}
    utf-8 F480 tcl8      \u00F4\u20AC   -1 {} {Missing second trail byte}
    utf-8 F480 replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 F480 strict    {}              0 {} {Missing second trail byte}
    utf-8 F48F tcl8      \u00F4\u008F   -1 {} {Missing second trail byte}
    utf-8 F48F replace   \uFFFD         -1 {knownW3C} {Missing second trail byte}
    utf-8 F48F strict    {}              0 {} {Missing second trail byte}
    utf-8 F4807F tcl8      \u00F4\u20AC\x7F -1 {} {Second trail byte must be 80:BF}
    utf-8 F4807F replace   \uFFFD\u7F       -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 F4807F strict    {}                0 {}  {Second trail byte must be 80:BF}
    utf-8 F48F7F tcl8      \u00F4\u008F\x7F -1 {} {Second trail byte must be 80:BF}
    utf-8 F48F7F replace   \uFFFD\u7F       -1 {knownW3C} {Second trail byte must be 80:BF}
    utf-8 F48F7F strict    {}                0 {}  {Second trail byte must be 80:BF}
    utf-8 F48081 tcl8      \u00F4\u20AC\u0081   -1 {} {Missing third trail byte}
    utf-8 F48081 replace   \uFFFD         -1 {knownW3C} {Missing third trail byte}
    utf-8 F48081 strict    {}              0 {} {Missing third trail byte}
    utf-8 F48F81 tcl8      \u00F4\u008F\u0081   -1 {} {Missing third trail byte}
    utf-8 F48F81 replace   \uFFFD         -1 {knownW3C} {Missing third trail byte}
    utf-8 F48F81 strict    {}              0 {} {Missing third trail byte}
    utf-8 F481817F tcl8      \u00F4\u0081\u0081\x7F   -1 {} {Third trail byte must be 80:BF}
    utf-8 F480817F replace   \uFFFD\x7F           -1 {knownW3C} {Third trail byte must be 80:BF}
    utf-8 F480817F strict    {}              0 {} {Third trail byte must be 80:BF}
    utf-8 F48FBFD0 tcl8      \u00F4\u008F\u00BF\u00D0   -1 {} {Third trail byte must be 80:BF}
    utf-8 F48FBFD0 replace   \uFFFD         -1 {knownW3C} {Third trail byte must be 80:BF}
    utf-8 F48FBFD0 strict    {}              0 {} {Third trail byte must be 80:BF}

    utf-8 F5 tcl8    \u00F5 -1 {} {F5:FF are invalid everywhere}
    utf-8 F5 replace \uFFFD -1 {} {F5:FF are invalid everywhere}
    utf-8 F5 strict  {}      0 {} {F5:FF are invalid everywhere}
    utf-8 FF tcl8    \u00FF -1 {} {F5:FF are invalid everywhere}
    utf-8 FF replace \uFFFD -1 {} {F5:FF are invalid everywhere}
    utf-8 FF strict  {}      0 {} {F5:FF are invalid everywhere}

    utf-8 C0AFE080BFF0818130 replace \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\x30 -1 {} {Unicode Table 3-8}
    utf-8 EDA080EDBFBFEDAF30 replace \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\x30 -1 {knownW3C} {Unicode Table 3-9}
    utf-8 F4919293FF4180BF30 replace \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u0041\uFFFD\uFFFD\x30 -1 {} {Unicode Table 3-10}
    utf-8 E180E2F09192F1BF30 replace \uFFFD\uFFFD\uFFFD\uFFFD\x30                         -1 {knownW3C} {Unicode Table 3.11}
}

# utf16-le and utf16-be test cases. Note utf16 cases are automatically generated
# based on these depending on platform endianness. Note truncated tests can only
# happen when the sequence is at the end (including by itself) Thus {solo tail}
# in some cases.
lappend encInvalidBytes {*}{
    utf-16le 41      tcl8      \uFFFD -1 {solo tail} {Truncated}
    utf-16le 41      replace   \uFFFD -1 {solo tail} {Truncated}
    utf-16le 41      strict    {}      0 {solo tail} {Truncated}
    utf-16le 00D8    tcl8      \uD800 -1 {} {Missing low surrogate}
    utf-16le 00D8    replace   \uFFFD -1 {} {Missing low surrogate}
    utf-16le 00D8    strict    {}      0 {} {Missing low surrogate}
    utf-16le 00DC    tcl8      \uDC00 -1 {} {Missing high surrogate}
    utf-16le 00DC    replace   \uFFFD -1 {} {Missing high surrogate}
    utf-16le 00DC    strict    {}      0 {} {Missing high surrogate}

    utf-16be 41      tcl8      \uFFFD -1 {solo tail} {Truncated}
    utf-16be 41      replace   \uFFFD -1 {solo tail} {Truncated}
    utf-16be 41      strict    {}      0 {solo tail} {Truncated}
    utf-16be D800    tcl8      \uD800 -1 {} {Missing low surrogate}
    utf-16be D800    replace   \uFFFD -1 {} {Missing low surrogate}
    utf-16be D800    strict    {}      0 {} {Missing low surrogate}
    utf-16be DC00    tcl8      \uDC00 -1 {} {Missing high surrogate}
    utf-16be DC00    replace   \uFFFD -1 {} {Missing high surrogate}
    utf-16be DC00    strict    {}      0 {} {Missing high surrogate}
}

# utf32-le and utf32-be test cases. Note utf32 cases are automatically generated
# based on these depending on platform endianness. Note truncated tests can only
# happen when the sequence is at the end (including by itself) Thus {solo tail}
# in some cases.
lappend encInvalidBytes {*}{
    utf-32le 41      tcl8      \uFFFD  -1 {solo tail} {Truncated}
    utf-32le 41      replace   \uFFFD  -1 {solo} {Truncated}
    utf-32le 41      strict    {}   0 {solo tail} {Truncated}
    utf-32le 4100    tcl8      \uFFFD  -1 {solo tail} {Truncated}
    utf-32le 4100    replace   \uFFFD  -1 {solo} {Truncated}
    utf-32le 4100    strict    {}   0 {solo tail} {Truncated}
    utf-32le 410000  tcl8      \uFFFD  -1 {solo tail} {Truncated}
    utf-32le 410000  replace   \uFFFD  -1 {solo} {Truncated}
    utf-32le 410000  strict    {}       0 {solo tail} {Truncated}
    utf-32le 00D80000 tcl8     \uD800   -1 {} {High-surrogate}
    utf-32le 00D80000 replace  \uFFFD   -1 {} {High-surrogate}
    utf-32le 00D80000 strict   {}        0 {} {High-surrogate}
    utf-32le 00DC0000 tcl8     \uDC00   -1 {} {Low-surrogate}
    utf-32le 00DC0000 replace  \uFFFD   -1 {} {Low-surrogate}
    utf-32le 00DC0000 strict   {}        0 {} {Low-surrogate}
    utf-32le 00D8000000DC0000 tcl8 \uD800\uDC00    -1 {} {High-low-surrogate-pair}
    utf-32le 00D8000000DC0000 replace \uFFFD\uFFFD -1 {} {High-low-surrogate-pair}
    utf-32le 00D8000000DC0000 strict  {}            0 {} {High-low-surrogate-pair}
    utf-32le 00001100 tcl8 \uFFFD    -1 {} {Out of range}
    utf-32le 00001100 replace \uFFFD -1 {} {Out of range}
    utf-32le 00001100 strict {}       0 {} {Out of range}
    utf-32le FFFFFFFF tcl8 \uFFFD    -1 {} {Out of range}
    utf-32le FFFFFFFF replace \uFFFD -1 {} {Out of range}
    utf-32le FFFFFFFF strict {}       0 {} {Out of range}

    utf-32be 41      tcl8      \uFFFD  -1 {solo tail} {Truncated}
    utf-32be 41      replace   \uFFFD  -1 {solo tail} {Truncated}
    utf-32be 41      strict    {}       0 {solo tail} {Truncated}
    utf-32be 0041    tcl8      \uFFFD  -1 {solo tail} {Truncated}
    utf-32be 0041    replace   \uFFFD  -1 {solo} {Truncated}
    utf-32be 0041    strict    {}   0 {solo tail} {Truncated}
    utf-32be 000041  tcl8      \uFFFD  -1 {solo tail} {Truncated}
    utf-32be 000041  replace   \uFFFD  -1 {solo} {Truncated}
    utf-32be 000041  strict    {}       0 {solo tail} {Truncated}
    utf-32be 0000D800 tcl8     \uD800   -1 {} {High-surrogate}
    utf-32be 0000D800 replace  \uFFFD   -1 {} {High-surrogate}
    utf-32be 0000D800 strict   {}        0 {} {High-surrogate}
    utf-32be 0000DC00 tcl8     \uDC00   -1 {} {Low-surrogate}
    utf-32be 0000DC00 replace  \uFFFD   -1 {} {Low-surrogate}
    utf-32be 0000DC00 strict   {}        0 {} {Low-surrogate}
    utf-32be 0000D8000000DC00 tcl8 \uD800\uDC00    -1 {} {High-low-surrogate-pair}
    utf-32be 0000D8000000DC00 replace \uFFFD\uFFFD -1 {} {High-low-surrogate-pair}
    utf-32be 0000D8000000DC00 strict  {}            0 {} {High-low-surrogate-pair}
    utf-32be 00110000 tcl8 \uFFFD    -1 {} {Out of range}
    utf-32be 00110000 replace \uFFFD -1 {} {Out of range}
    utf-32be 00110000 strict {}       0 {} {Out of range}
    utf-32be FFFFFFFF tcl8 \uFFFD    -1 {} {Out of range}
    utf-32be FFFFFFFF replace \uFFFD -1 {} {Out of range}
    utf-32be FFFFFFFF strict {}       0 {} {Out of range}
}

# Strings that cannot be encoded for specific encoding / profiles
# <ENCODING STRING PROFILE EXPECTEDRESULT EXPECTEDFAILINDEX CTRL COMMENT>
# <ENCODING,STRING,PROFILE> should be unique for test ids to be unique.
# See earlier comments about CTRL field.
#
# Note utf-16, utf-32 missing because they are automatically
# generated based on le/be versions.
# TODO - out of range code point (note cannot be generated by \U notation)
lappend encUnencodableStrings {*}{
    ascii \u00e0 tcl8    3f -1 {} {unencodable}
    ascii \u00e0 strict  {}  0 {} {unencodable}

    iso8859-1 \u0141 tcl8    3f -1 {} unencodable
    iso8859-1 \u0141 strict  {}  0 {} unencodable

    utf-8 \uD800 tcl8    eda080 -1 {} Low-surrogate
    utf-8 \uD800 replace efbfbd -1 {} Low-surrogate
    utf-8 \uD800 strict  {}      0 {} Low-surrogate
    utf-8 \uDC00 tcl8    edb080 -1 {} High-surrogate
    utf-8 \uDC00 strict  {}      0 {} High-surrogate
    utf-8 \uDC00 replace efbfbd -1 {} High-surrogate
}


# The icuUcmTests.tcl is generated by the tools/ucm2tests.tcl script
# and generates test vectors for the above tables for various encodings
# based on ICU UCM files.
# TODO - commented out for now as generating a lot of mismatches.
# source [file join [file dirname [info script]] icuUcmTests.tcl]

Changes to tests/env.test.

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
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
30
31






-
-
-
+
+
+









-
-
-
+
+
+
+
+
+







# Commands covered:  none (tests environment variable implementation)
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
}

loadTestedCommands
catch [list package require -exact Tcltest [info patchlevel]]
package require tcltests
source [file join [file dirname [info script]] tcltests.tcl]

testConstraint utf8system [string equal [encoding system] utf-8]
if {[llength [auto_execok bash]]} {
    testConstraint haveBash 1
}

# [exec] is required here to see the actual environment received by child
# processes.
proc getenv {} {
    global printenvScript
    catch {exec [interpreter] $printenvScript} out
    if {$out eq "child process exited abnormally"} {
98
99
100
101
102
103
104
105

106
107
108

109
110
111
112
113
114
115
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115
116
117
118
119







-
+



+







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

variable printenvScript [makeFile [string map [list @keep@ [list $keep]] {
    encoding system iso8859-1
    proc lrem {listname name} {
	upvar $listname list
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
131
132
133
134
135
136
137

138
139
140
141
142
143
144
145







-
+







    proc manglechar c {
	return [format {\u%04x} [scan $c %c]]
    }

    set names [lsort [array names env]]
    if {$tcl_platform(platform) eq "windows"} {
	lrem names HOME
        lrem names COMSPEC
	lrem names COMSPEC
	lrem names ComSpec
	lrem names ""
    }
    foreach name @keep@ {
	lrem names $name
    }
    foreach p $names {
218
219
220
221
222
223
224
225

226
227

228
229
230
231
232
233
234
222
223
224
225
226
227
228

229
230

231
232
233
234
235
236
237
238







-
+

-
+







    getenv
} -cleanup { cleanup1
} -result {NAME1=test string
NAME2=more
XYZZY=garbage}

test env-2.5 {different encoding (wide chars)} -constraints {win exec} -setup {
    # be sure set of (unicode) environment occurs if single-byte encoding is used:
    # be sure set of (Unicode) environment occurs if single-byte encoding is used:
    encodingswitch cp1252
    # german (cp1252) and russian (cp1251) characters together encoded as utf-8:
    # German (cp1252) and Russian (cp1251) characters together encoded as utf-8:
    set val 2d2dc3a4c3b6c3bcc39f2dd182d0b5d181d1822d2d
    set env(XYZZY) [encoding convertfrom utf-8 [binary decode hex $val]]
    # now switch to utf-8 (to see correct values from test):
    encoding system utf-8
} -body {
    exec [interpreter] << [string map [list \$val $val] {
	encoding system utf-8; fconfigure stdout -encoding utf-8
300
301
302
303
304
305
306
307

308
309
310
311
312
313
314
304
305
306
307
308
309
310

311
312
313
314
315
316
317
318







-
+







} -cleanup cleanup1 -result a


test env-5.1 {
    corner cases - remove one elem at a time
} -setup setup1 -body {
    # When no environment variables exist, the env var will contain no
    # entries. The "array names" call synchs up the C-level environ array with
    # entries. The "array names" call syncs up the C-level environ array with
    # the Tcl level env array. Make sure an empty Tcl array is created.
    foreach e [array names env] {
	unset env($e)
    }
    array size env
} -cleanup cleanup1 -result 0

344
345
346
347
348
349
350
351

352
353
354
355
356
357
358
348
349
350
351
352
353
354

355
356
357
358
359
360
361
362







-
+







} -result {a 1}


test env-5.4 {corner cases - unset the env array} -setup {
    setup1
    interp create i
} -body {
    # The info exists command should be in synch with the env array.
    # The info exists command should be in sync with the env array.
    # Know Bug: 1737
    i eval {set env(THIS_SHOULD_EXIST) a}
    set     result [info exists env(THIS_SHOULD_EXIST)]
    lappend result [set env(THIS_SHOULD_EXIST)]
    lappend result [info exists env(THIS_SHOULD_EXIST)]
} -cleanup {
    cleanup1
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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







-
+







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








test env-7.3 {
    [9b4702]: testing existence of env(some_thing) should not destroy trace
} -setup setup1 -body {
    apply {{} {
      catch {unset ::env(test7_3)}
      proc foo args {
        set ::env(test7_3) ok
	set ::env(test7_3) ok
      }
      trace add variable ::env(not_yet_existent) write foo
      info exists ::env(not_yet_existent)
      set ::env(not_yet_existent) "Now I'm here";
      return [info exists ::env(test7_3)]
    }}
} -cleanup cleanup1 -result 1


test env-7.4 {
    get env variable through upvar
} -setup setup1 -body {
    apply {{} {
	set ::env(test7_4) origvalue
	upvar #0 env(test7_4) var
	return $var
    }}
} -cleanup cleanup1 -result origvalue

test env-7.5 {
    set env variable through upvar
} -setup setup1 -body {
    apply {{} {
	set ::env(test7_5) origvalue
	upvar #0 env(test7_5) var
	set var newvalue
	return $::env(test7_5)
    }}
} -cleanup cleanup1 -result newvalue

test env-7.6 {
    unset env variable through upvar
} -setup setup1 -body {
    apply {{} {
	set ::env(test7_6) origvalue
	upvar #0 env(test7_6) var
	unset var
	return [array get env test7_6]
    }}
} -cleanup cleanup1 -result {}

test env-7.7 {
    create new (unset) env variable through upvar
} -setup setup1 -body {
    apply {{} {
	unset -nocomplain ::env(test7_7)
	upvar #0 env(test7_7) var
	interp create interp1
	set var newvalue
	set result [interp1 eval {info exists ::env(test7_7)}]
	if {$result} {
	    lappend result [interp1 eval {set ::env(test7_7)}]
	}
	interp delete interp1
	return $result
    }}
} -cleanup cleanup1 -result {1 newvalue}


test env-8.0 {
    memory usage - valgrind does not report reachable memory
} -body {
    set res [set env(__DUMMY__) {i'm with dummy}]
    unset env(__DUMMY__)
    return $res
} -result {i'm with dummy}


test env-9.0 {
    Initialization of HOME from HOMEDRIVE and HOMEPATH
} -constraints win -setup {
    setup1
    unset -nocomplain ::env(HOME)
    set ::env(HOMEDRIVE) X:
    set ::env(HOMEPATH) \\home\\path
} -cleanup {
    cleanup1
} -body {
    set pipe [open |[list [interpreter]] r+]
    puts $pipe {puts $::env(HOME); flush stdout; exit}
    flush $pipe
    set result [gets $pipe]
    close $pipe
    set result
} -result {X:\home\path}

test env-9.1 {
    Initialization of HOME from USERPROFILE
} -constraints win -setup {
    setup1
    unset -nocomplain ::env(HOME)
    unset -nocomplain ::env(HOMEDRIVE)
    unset -nocomplain ::env(HOMEPATH)
} -cleanup {
    cleanup1
} -body {
    set pipe [open |[list [interpreter]] r+]
    puts $pipe {puts $::env(HOME); flush stdout; exit}
    flush $pipe
    set result [gets $pipe]
    close $pipe
    if {$result ne $::env(USERPROFILE)} {
	list ERROR $result ne $::env(USERPROFILE)
    }
} -result {}

test env-10.0 {
    Unequal environment strings test should test unequal
} -constraints {unix haveBash utf8system knownBug} -setup {
    set tclScript [makeFile {
	puts [string equal $env(XX) $env(YY)]
    } tclScript]
    set shellCode {
	export XX=$'\351'
	export YY=$'\303\251'
    }
    append shellCode "[info nameofexecutable] $tclScript\n"
    set shScript [makeFile $shellCode shScript]
} -body {
    exec {*}[auto_execok bash] $shScript
} -result 0



# cleanup
rename getenv {}
rename envrestore {}
rename envprep {}
rename encodingrestore {}
rename encodingswitch {}

Changes to tests/error.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  error, catch, throw, try
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
84
85
86
87
88
89
90
91

92
93
94
95
96
97
98
84
85
86
87
88
89
90

91
92
93
94
95
96
97
98







-
+







    # This test is non-portable: it generates a memory fault on machines like
    # DEC Alphas (infinite recursion overflows stack?)
    #
    # That claims sounds like a bug to be fixed rather than a portability
    # problem. Anyhow, I believe it's out of date (bug's been fixed) so this
    # test is re-enabled.
    proc p {} {
        uplevel 1 catch p error
	uplevel 1 catch p error
    }
    p
} 0

# Check errors nested in procedures. Also check the optional argument to
# "error" to generate a new error trace.

347
348
349
350
351
352
353







354
355
356
357
358
359
360
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367







+
+
+
+
+
+
+







} {a b c}
test error-9.4 {try (ok, non-empty result) with on handler} {
    try { list a b c } on break {} { list d e f }
} {a b c}
test error-9.5 {try (ok, non-empty result) with on ok handler} {
    try { list a b c } on ok {} { list d e f }
} {d e f}
test error-9.6 {try (compilation of simple finaly token only, bug [27520c9b17])} -body {
    set b {}; set l {}
    try {lappend l error} finally [lappend l set b]
    list $l $b
} -cleanup {
    unset -nocomplain b l
} -result {{set b error} {}}

# simple try tests - "on" handler matching

test error-10.1 {try with on ok} {
    try { list a b c } on ok {} { list d e f }
} {d e f}
test error-10.2 {try with on 0} {
913
914
915
916
917
918
919
920

921
922
923
924
925
926
927
920
921
922
923
924
925
926

927
928
929
930
931
932
933
934







-
+







	} finally {
	    throw BAR baz
	}
    }
    list $em [dict get $opts -errorcode]
} {bar FOO}

# try tests - fallthough body cases
# try tests - fall-through body cases

test error-19.1 {try with fallthrough body #1} {
    set RES {}
    try { list a b c } on ok { set RES 0 } - on error {} { set RES 1 }
    set RES
} {1}
test error-19.2 {try with fallthrough body #2} {

Changes to tests/eval.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  eval
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands.  Sourcing this file into Tcl runs the tests and generates output
# for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74

75
76
77
78
79
80
81
82







-
+







-
+







    eval [list list 1 2 3 4 5]
} {1 2 3 4 5}
test eval-3.2 {concatenating eval and pure lists} {
    eval [list list 1] [list 2 3 4 5]
} {1 2 3 4 5}
test eval-3.3 {eval and canonical lists} {
    set cmd [list list 1 2 3 4 5]
    # Force existance of utf-8 rep
    # Force existence of utf-8 rep
    set dummy($cmd) $cmd
    unset dummy
    eval $cmd
} {1 2 3 4 5}
test eval-3.4 {concatenating eval and canonical lists} {
    set cmd  [list list 1]
    set cmd2 [list 2 3 4 5]
    # Force existance of utf-8 rep
    # Force existence of utf-8 rep
    set dummy($cmd) $cmd
    set dummy($cmd2) $cmd2
    unset dummy
    eval $cmd $cmd2
} {1 2 3 4 5}

# cleanup

Changes to tests/event.test.

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
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





-
-
+
+









-
-
+
+







# This file contains a collection of tests for the procedures in the file
# tclEvent.c, which includes the "update", and "vwait" Tcl commands.  Sourcing
# this file into Tcl runs the tests and generates output for errors.  No
# output means no errors were found.
#
# Copyright (c) 1995-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require tcltest 2.5
namespace import -force ::tcltest::*

catch {
    ::tcltest::loadTestedCommands
    package require -exact Tcltest [info patchlevel]
    set ::tcltestlib [lindex [package ifneeded Tcltest [info patchlevel]] 1]
    package require -exact tcl::test [info patchlevel]
    set ::tcltestlib [info loaded {} Tcltest]
}


testConstraint testfilehandler [llength [info commands testfilehandler]]
testConstraint testexithandler [llength [info commands testexithandler]]
testConstraint testfilewait [llength [info commands testfilewait]]
testConstraint exec [llength [info commands exec]]
423
424
425
426
427
428
429
430

431
432
433
434
435
436
437
423
424
425
426
427
428
429

430
431
432
433
434
435
436
437







-
+







    while executing
"error foo"
    ("after" script)
}

# someday : add a test checking that when there is no bgerror, an error msg
# goes to stderr ideally one would use sub interp and transfer a fake stderr
# to it, unfortunatly the current interp tcl API does not allow that. The
# to it, unfortunately the current interp tcl API does not allow that. The
# other option would be to use fork a test but it then becomes more a
# file/exec test than a bgerror test.

# end of bgerror tests
catch {rename bgerror {}}

test event-8.1 {Tcl_CreateExitHandler procedure} {stdio testexithandler} {
502
503
504
505
506
507
508
509

510
511
512

513
514

515
516
517
518
519
520
521
522
523
524
502
503
504
505
506
507
508

509
510
511

512
513

514



515
516
517
518
519
520
521







-
+


-
+

-
+
-
-
-







} {even 16
}

test event-10.1 {Tcl_Exit procedure} {stdio} {
    set child [open |[list [interpreter]] r+]
    puts $child "exit 3"
    list [catch {close $child} msg] $msg [lindex $::errorCode 0] \
        [lindex $::errorCode 2]
	[lindex $::errorCode 2]
} {1 {child process exited abnormally} CHILDSTATUS 3}

test event-11.1 {Tcl_VwaitCmd procedure} -returnCodes error -body {
test event-11.1 {Tcl_VwaitCmd procedure} -body {
    vwait
} -result {wrong # args: should be "vwait name"}
} -result {}
test event-11.2 {Tcl_VwaitCmd procedure} -returnCodes error -body {
    vwait a b
} -result {wrong # args: should be "vwait name"}
test event-11.3 {Tcl_VwaitCmd procedure} -setup {
    catch {unset x}
} -body {
    set x 1
    vwait x(1)
} -returnCodes error -result {can't trace "x(1)": variable isn't array}
test event-11.4 {Tcl_VwaitCmd procedure} -setup {
595
596
597
598
599
600
601
602

603
604
605


606
607
608

609
610
611
612
613
614
615
592
593
594
595
596
597
598

599
600


601
602
603
604

605
606
607
608
609
610
611
612







-
+

-
-
+
+


-
+







    }
} {}
test event-11.8 {Bug 16828b3744} -setup {
    oo::class create A {
	variable continue

	method start {} {
           after idle [self] destroy
	   after idle [self] destroy

           set continue 0
           vwait [namespace current]::continue
	   set continue 0
	   vwait [namespace current]::continue
	}
	destructor {
           set continue 1
	   set continue 1
	}
    }
} -body {
    [A new] start
} -cleanup {
    A destroy
} -result {}

Changes to tests/exec.test.

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


30
31
32
33

34
35
36
37
38
39
40
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
30
31
32
33
34
35






-
-
-
+
+
+











-
+
-
-
-

-
-
-
-
+
+



-
+







# Commands covered:  exec
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1991-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

# There is no point in running Valgrind on cases where [exec] forks but then
# fails and the child process doesn't go through full cleanup.

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

source [file join [file dirname [info script]] tcltests.tcl]
loadTestedCommands
catch [list package require -exact Tcltest [info patchlevel]]
package require tcltests

# All tests require the "exec" command.
# Skip them if exec is not defined.
testConstraint exec [llength [info commands exec]]
testConstraint noosx [expr {![info exists ::env(TRAVIS_OSX_IMAGE)] || ![string match xcode* $::env(TRAVIS_OSX_IMAGE)]}]
# Some skips when running in a macOS CI environment
testConstraint noosxCI [expr {![info exists ::env(MAC_CI)]}]

unset -nocomplain path

# Utilities that are like bourne shell stalwarts, but cross-platform.
# Utilities that are like Bourne shell stalwarts, but cross-platform.
set path(echo) [makeFile {
    puts -nonewline [lindex $argv 0]
    foreach str [lrange $argv 1 end] {
	puts -nonewline " $str"
    }
    puts {}
    exit
108
109
110
111
112
113
114
115

116
117
118
119
120
121
122
103
104
105
106
107
108
109

110
111
112
113
114
115
116
117







-
+







	    continue
	}
	lappend newcmd $arg
    }
    exit
} sh2]
set path(sleep) [makeFile {
    after [expr $argv*1000]
    after [expr {$argv*1000}]
    exit
} sleep]
set path(exit) [makeFile {
    exit $argv
} exit]

proc readfile filename {
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
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







-
-
+
+



-
+


-
+



-
+







    exec [interpreter] $path(cat) "<<Joined to arrows"
} {Joined to arrows}
test exec-2.6 {redirecting input from immediate source, with UTF} -setup {
    set sysenc [encoding system]
    encoding system iso8859-1
    proc quotenonascii s {
	regsub -all {\[|\\|\]} $s {\\&} s
	regsub -all "\[\u007f-\uffff\]" $s \
	    {[apply {c {format {\u%04x} [scan $c %c]}} &]} s
	regsub -all "\[\x7F-\xFF\]" $s \
	    {[apply {c {format {\x%02X} [scan $c %c]}} &]} s
	return [subst -novariables $s]
    }
} -constraints {exec} -body {
    # If this fails, it may give back: "\uC3\uA9\uC3\uA0\uC3\uBC\uC3\uB1"
    # If this fails, it may give back: "\xC3\xA9\xC3\xA0\xC3\xBC\xC3\xB1"
    # If it does, this means that the UTF -> external conversion did not occur
    # before writing out the temp file.
    quotenonascii [exec [interpreter] $path(cat) << "\uE9\uE0\uFC\uF1"]
    quotenonascii [exec [interpreter] $path(cat) << "\xE9\xE0\xFC\xF1"]
} -cleanup {
    encoding system $sysenc
    rename quotenonascii {}
} -result {\u00e9\u00e0\u00fc\u00f1}
} -result {\xE9\xE0\xFC\xF1}

# I/O redirection: output to file.

set path(gorp.file) [makeFile {} gorp.file]
file delete $path(gorp.file)

test exec-3.1 {redirecting output to file} {exec} {
435
436
437
438
439
440
441
442

443






444
445


446
447

448
449
450

451
452
453
454
455
456
457
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







-
+

+
+
+
+
+
+
-
-
+
+

-
+


-
+







} -returnCodes error -result "channel \"$f\" wasn't opened for reading"
close $f
set f [open $path(gorp.file) r]
test exec-10.19 {errors in exec invocation} -constraints {exec} -body {
    exec cat >@ $f
} -returnCodes error -result "channel \"$f\" wasn't opened for writing"
close $f
test exec-10.20 {errors in exec invocation} -constraints {exec notValgrind} -body {
test exec-10.20.1 {errors in exec invocation} -constraints {unix exec notValgrind} -body {
    exec ~non_existent_user/foo/bar
} -returnCodes error -result {couldn't execute "~non_existent_user/foo/bar": no such file or directory}
test exec-10.20.2 {errors in exec invocation} -constraints {win exec notValgrind} -body {
    exec ~non_existent_user/foo/bar
} -returnCodes error -result {couldn't execute "~non_existent_user\foo\bar": no such file or directory}
test exec-10.21.1 {errors in exec invocation} -constraints {unix exec notValgrind} -body {
    exec [interpreter] true | ~xyzzy_bad_user/x | false
} -returnCodes error -result {user "non_existent_user" doesn't exist}
test exec-10.21 {errors in exec invocation} -constraints {exec notValgrind} -body {
} -returnCodes error -result {couldn't execute "~xyzzy_bad_user/x": no such file or directory}
test exec-10.21.2 {errors in exec invocation} -constraints {win exec notValgrind} -body {
    exec [interpreter] true | ~xyzzy_bad_user/x | false
} -returnCodes error -result {user "xyzzy_bad_user" doesn't exist}
} -returnCodes error -result {couldn't execute "~xyzzy_bad_user\x": no such file or directory}
test exec-10.22 {errors in exec invocation} -constraints {exec notValgrind} -body {
    exec echo test > ~non_existent_user/foo/bar
} -returnCodes error -result {user "non_existent_user" doesn't exist}
} -returnCodes error -result {couldn't write file "~non_existent_user/foo/bar": no such file or directory}
# Commands in background.

test exec-11.1 {commands in background} {exec} {
    set time [time {exec [interpreter] $path(sleep) 2 &}]
    expr {[lindex $time 0] < 1000000}
} 1
test exec-11.2 {commands in background} -constraints {exec} -body {
635
636
637
638
639
640
641
642

643
644
645
646
647
648
649
636
637
638
639
640
641
642

643
644
645
646
647
648
649
650







-
+







Third line}

test exec-17.1 {inheriting standard I/O} -constraints {exec} -setup {
    set path(script) [makeFile {} script]
    set f [open $path(script) w]
    puts $f [list lassign [list \
	    [info nameofexecutable] $path(gorp.file) $path(echo) $path(sleep) \
        ] exe file echo sleep]
	] exe file echo sleep]
    puts $f {
	close stdout
	set f [open $file w]
	catch {exec $exe $echo foobar &}
	exec $exe $sleep 2
	close $f
    }
669
670
671
672
673
674
675


676

677
678
679
680
681
682
683
670
671
672
673
674
675
676
677
678

679
680
681
682
683
684
685
686







+
+
-
+







} -constraints {exec tempNotWin} -cleanup {
    removeFile $path(fooblah)
} -result contents

# Note that this test cannot be adapted to work on Windows; that platform has
# no kernel support for an analog of O_APPEND. OTOH, that means we can assume
# that there is a POSIX shell...
#
# This test also fails in some cases when building with macOS
test exec-19.1 {exec >> uses O_APPEND} -constraints {exec unix notValgrind noosx} -setup {
test exec-19.1 {exec >> uses O_APPEND} -constraints {exec unix notValgrind noosxCI} -setup {
    set tmpfile [makeFile {0} tmpfile.exec-19.1]
} -body {
    # Note that we have to allow for the current contents of the temporary
    # file, which is why the result is 14 and not 12
    exec /bin/sh -c \
	    {for a in 1 2 3; do sleep 1; echo $a; done} >>$tmpfile &
    exec /bin/sh -c \
705
706
707
708
709
710
711





























712
713
714
715
716
717
718
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    viewFile $log
} -result "\"Testing exec-20.0\""
test exec-20.1 {exec .CMD file} -constraints {win} -body {
    set log [makeFile {} exec201.log]
    exec [makeFile "echo %1> $log" exec201.CMD] "Testing exec-20.1"
    viewFile $log
} -result "\"Testing exec-20.1\""

# Test with encoding mismatches (Bug 0f1ddc0df7fb7)
test exec-21.1 {exec encoding mismatch on stdout} -setup {
    set path(script) [makeFile {
	fconfigure stdout -translation binary
	puts a\xe9b
    } script]
    set enc [encoding system]
    encoding system utf-8
} -cleanup {
    removeFile $path(script)
    encoding system $enc
} -body {
    exec [info nameofexecutable] $path(script)
} -result a\uFFFDb
test exec-21.2 {exec encoding mismatch on stderr} -setup {
    set path(script) [makeFile {
	fconfigure stderr -translation binary
	puts stderr a\xe9b
    } script]
    set enc [encoding system]
    encoding system utf-8
} -cleanup {
    removeFile $path(script)
    encoding system $enc
} -body {
    list [catch {exec [info nameofexecutable] $path(script)} r] $r
} -result [list 1 a\uFFFDb]


# ----------------------------------------------------------------------
# cleanup

foreach file {gorp.file gorp.file2 echo echo2 cat wc sh sh2 sleep exit err} {
    removeFile $file
}

Changes to tests/execute.test.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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
30
31
32
33
34
35
36

37
38
39
40
41
42
43










-
-
+
+










-
+













-







# This file contains tests for the tclExecute.c source file. Tests appear in
# the same order as the C code that they test. The set of tests is currently
# incomplete since it currently includes only new tests for code changed for
# the addition of Tcl namespaces. Other execution-related tests appear in
# several other test files including namespace.test, basic.test, eval.test,
# for.test, etc.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename foo ""}
catch {unset x}
catch {unset y}
catch {unset msg}

testConstraint testobj [expr {
    [llength [info commands testobj]]
    && [llength [info commands testdoubleobj]]
    && [llength [info commands teststringobj]]
}]

testConstraint longIs32bit [expr {$tcl_platform(wordSize) == 4}]
testConstraint testexprlongobj [llength [info commands testexprlongobj]]


if {[namespace which -command testbumpinterpepoch] eq ""} {
  proc testbumpinterpepoch {} { rename ::set ::dummy; rename ::dummy ::set }
}

175
176
177
178
179
180
181
182

183
184
185
186
187
188
189
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188







-
+







test execute-3.5 {TclExecuteByteCode, INST_ADD, op1 is string double} {testobj} {
    set x [teststringobj set 0 1.0]
    expr {$x + 1}
} 2.0
test execute-3.6 {TclExecuteByteCode, INST_ADD, op1 is non-numeric} {testobj} {
    set x [teststringobj set 0 foo]
    list [catch {expr {$x + 1}} msg] $msg
} {1 {can't use non-numeric string "foo" as operand of "+"}}
} {1 {cannot use non-numeric string "foo" as left operand of "+"}}
test execute-3.7 {TclExecuteByteCode, INST_ADD, op2 is int} {testobj} {
    set x [testintobj set 0 1]
    expr {1 + $x}
} 2
test execute-3.8 {TclExecuteByteCode, INST_ADD, op2 is double} {testobj} {
    set x [testdoubleobj set 0 1]
    expr {1 + $x}
200
201
202
203
204
205
206
207

208
209
210
211
212
213
214
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213







-
+







test execute-3.11 {TclExecuteByteCode, INST_ADD, op2 is string double} {testobj} {
    set x [teststringobj set 0 1.0]
    expr {1 + $x}
} 2.0
test execute-3.12 {TclExecuteByteCode, INST_ADD, op2 is non-numeric} {testobj} {
    set x [teststringobj set 0 foo]
    list [catch {expr {1 + $x}} msg] $msg
} {1 {can't use non-numeric string "foo" as operand of "+"}}
} {1 {cannot use non-numeric string "foo" as right operand of "+"}}

# INST_SUB is partially tested:
test execute-3.13 {TclExecuteByteCode, INST_SUB, op1 is int} {testobj} {
    set x [testintobj set 0 1]
    expr {$x - 1}
} 0
test execute-3.14 {TclExecuteByteCode, INST_SUB, op1 is double} {testobj} {
227
228
229
230
231
232
233
234

235
236
237
238
239
240
241
226
227
228
229
230
231
232

233
234
235
236
237
238
239
240







-
+







test execute-3.17 {TclExecuteByteCode, INST_SUB, op1 is string double} {testobj} {
    set x [teststringobj set 0 1.0]
    expr {$x - 1}
} 0.0
test execute-3.18 {TclExecuteByteCode, INST_SUB, op1 is non-numeric} {testobj} {
    set x [teststringobj set 0 foo]
    list [catch {expr {$x - 1}} msg] $msg
} {1 {can't use non-numeric string "foo" as operand of "-"}}
} {1 {cannot use non-numeric string "foo" as left operand of "-"}}
test execute-3.19 {TclExecuteByteCode, INST_SUB, op2 is int} {testobj} {
    set x [testintobj set 0 1]
    expr {1 - $x}
} 0
test execute-3.20 {TclExecuteByteCode, INST_SUB, op2 is double} {testobj} {
    set x [testdoubleobj set 0 1]
    expr {1 - $x}
252
253
254
255
256
257
258
259

260
261
262
263
264
265
266
251
252
253
254
255
256
257

258
259
260
261
262
263
264
265







-
+







test execute-3.23 {TclExecuteByteCode, INST_SUB, op2 is string double} {testobj} {
    set x [teststringobj set 0 1.0]
    expr {1 - $x}
} 0.0
test execute-3.24 {TclExecuteByteCode, INST_SUB, op2 is non-numeric} {testobj} {
    set x [teststringobj set 0 foo]
    list [catch {expr {1 - $x}} msg] $msg
} {1 {can't use non-numeric string "foo" as operand of "-"}}
} {1 {cannot use non-numeric string "foo" as right operand of "-"}}

# INST_MULT is partially tested:
test execute-3.25 {TclExecuteByteCode, INST_MULT, op1 is int} {testobj} {
    set x [testintobj set 1 1]
    expr {$x * 1}
} 1
test execute-3.26 {TclExecuteByteCode, INST_MULT, op1 is double} {testobj} {
279
280
281
282
283
284
285
286

287
288
289
290
291
292
293
278
279
280
281
282
283
284

285
286
287
288
289
290
291
292







-
+







test execute-3.29 {TclExecuteByteCode, INST_MULT, op1 is string double} {testobj} {
    set x [teststringobj set 1 1.0]
    expr {$x * 1}
} 1.0
test execute-3.30 {TclExecuteByteCode, INST_MULT, op1 is non-numeric} {testobj} {
    set x [teststringobj set 1 foo]
    list [catch {expr {$x * 1}} msg] $msg
} {1 {can't use non-numeric string "foo" as operand of "*"}}
} {1 {cannot use non-numeric string "foo" as left operand of "*"}}
test execute-3.31 {TclExecuteByteCode, INST_MULT, op2 is int} {testobj} {
    set x [testintobj set 1 1]
    expr {1 * $x}
} 1
test execute-3.32 {TclExecuteByteCode, INST_MULT, op2 is double} {testobj} {
    set x [testdoubleobj set 1 2.0]
    expr {1 * $x}
304
305
306
307
308
309
310
311

312
313
314
315
316
317
318
303
304
305
306
307
308
309

310
311
312
313
314
315
316
317







-
+







test execute-3.35 {TclExecuteByteCode, INST_MULT, op2 is string double} {testobj} {
    set x [teststringobj set 1 1.0]
    expr {1 * $x}
} 1.0
test execute-3.36 {TclExecuteByteCode, INST_MULT, op2 is non-numeric} {testobj} {
    set x [teststringobj set 1 foo]
    list [catch {expr {1 * $x}} msg] $msg
} {1 {can't use non-numeric string "foo" as operand of "*"}}
} {1 {cannot use non-numeric string "foo" as right operand of "*"}}

# INST_DIV is partially tested:
test execute-3.37 {TclExecuteByteCode, INST_DIV, op1 is int} {testobj} {
    set x [testintobj set 1 1]
    expr {$x / 1}
} 1
test execute-3.38 {TclExecuteByteCode, INST_DIV, op1 is double} {testobj} {
331
332
333
334
335
336
337
338

339
340
341
342
343
344
345
330
331
332
333
334
335
336

337
338
339
340
341
342
343
344







-
+







test execute-3.41 {TclExecuteByteCode, INST_DIV, op1 is string double} {testobj} {
    set x [teststringobj set 1 1.0]
    expr {$x / 1}
} 1.0
test execute-3.42 {TclExecuteByteCode, INST_DIV, op1 is non-numeric} {testobj} {
    set x [teststringobj set 1 foo]
    list [catch {expr {$x / 1}} msg] $msg
} {1 {can't use non-numeric string "foo" as operand of "/"}}
} {1 {cannot use non-numeric string "foo" as left operand of "/"}}
test execute-3.43 {TclExecuteByteCode, INST_DIV, op2 is int} {testobj} {
    set x [testintobj set 1 1]
    expr {2 / $x}
} 2
test execute-3.44 {TclExecuteByteCode, INST_DIV, op2 is double} {testobj} {
    set x [testdoubleobj set 1 1.0]
    expr {2 / $x}
356
357
358
359
360
361
362
363

364
365
366
367
368
369
370
355
356
357
358
359
360
361

362
363
364
365
366
367
368
369







-
+







test execute-3.47 {TclExecuteByteCode, INST_DIV, op2 is string double} {testobj} {
    set x [teststringobj set 1 1.0]
    expr {2 / $x}
} 2.0
test execute-3.48 {TclExecuteByteCode, INST_DIV, op2 is non-numeric} {testobj} {
    set x [teststringobj set 1 foo]
    list [catch {expr {1 / $x}} msg] $msg
} {1 {can't use non-numeric string "foo" as operand of "/"}}
} {1 {cannot use non-numeric string "foo" as right operand of "/"}}

# INST_UPLUS is partially tested:
test execute-3.49 {TclExecuteByteCode, INST_UPLUS, op is int} {testobj} {
    set x [testintobj set 1 1]
    expr {+ $x}
} 1
test execute-3.50 {TclExecuteByteCode, INST_UPLUS, op is double} {testobj} {
383
384
385
386
387
388
389
390

391
392
393
394
395
396
397
382
383
384
385
386
387
388

389
390
391
392
393
394
395
396







-
+







test execute-3.53 {TclExecuteByteCode, INST_UPLUS, op is string double} {testobj} {
    set x [teststringobj set 1 1.0]
    expr {+ $x}
} 1.0
test execute-3.54 {TclExecuteByteCode, INST_UPLUS, op is non-numeric} {testobj} {
    set x [teststringobj set 1 foo]
    list [catch {expr {+ $x}} msg] $msg
} {1 {can't use non-numeric string "foo" as operand of "+"}}
} {1 {cannot use non-numeric string "foo" as operand of "+"}}

# INST_UMINUS is partially tested:
test execute-3.55 {TclExecuteByteCode, INST_UMINUS, op is int} {testobj} {
    set x [testintobj set 1 1]
    expr {- $x}
} -1
test execute-3.56 {TclExecuteByteCode, INST_UMINUS, op is double} {testobj} {
410
411
412
413
414
415
416
417

418
419
420
421
422
423
424
409
410
411
412
413
414
415

416
417
418
419
420
421
422
423







-
+







test execute-3.59 {TclExecuteByteCode, INST_UMINUS, op is string double} {testobj} {
    set x [teststringobj set 1 1.0]
    expr {- $x}
} -1.0
test execute-3.60 {TclExecuteByteCode, INST_UMINUS, op is non-numeric} {testobj} {
    set x [teststringobj set 1 foo]
    list [catch {expr {- $x}} msg] $msg
} {1 {can't use non-numeric string "foo" as operand of "-"}}
} {1 {cannot use non-numeric string "foo" as operand of "-"}}

# INST_LNOT is partially tested:
test execute-3.61 {TclExecuteByteCode, INST_LNOT, op is int} {testobj} {
    set x [testintobj set 1 2]
    expr {! $x}
} 0
test execute-3.62 {TclExecuteByteCode, INST_LNOT, op is int} {testobj} {
458
459
460
461
462
463
464
465

466
467
468
469
470
471
472
457
458
459
460
461
462
463

464
465
466
467
468
469
470
471







-
+







test execute-3.70 {TclExecuteByteCode, INST_LNOT, op is string double} {testobj} {
    set x [teststringobj set 1 0.0]
    expr {! $x}
} 1
test execute-3.71 {TclExecuteByteCode, INST_LNOT, op is non-numeric} {testobj} {
    set x [teststringobj set 1 foo]
    list [catch {expr {! $x}} msg] $msg
} {1 {can't use non-numeric string "foo" as operand of "!"}}
} {1 {cannot use non-numeric string "foo" as operand of "!"}}

# INST_TRY_CVT_TO_NUMERIC is partially tested:
test execute-3.72 {TclExecuteByteCode, INST_TRY_CVT_TO_NUMERIC, op is int} {testobj} {
    set x [testintobj set 1 1]
    expr {$x}
} 1
test execute-3.73 {TclExecuteByteCode, INST_TRY_CVT_TO_NUMERIC, op is double} {testobj} {
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
558
559
560


561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581




582
583
584
585
586
587
588
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


558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576




577
578
579
580
581
582
583
584
585
586
587







-
-
-
+
+
+


-
+




-
-
+
+







-
+


-
-
-
+
+
+




-
-
-
+
+
+








-
-
-
+
+
+


-
-
-
+
+
+


-
-
+
+

















-
-
-
-
+
+
+
+








test execute-4.1 {Tcl_GetCommandFromObj, convert to tclCmdNameType} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    unset -nocomplain x
    unset -nocomplain y
} -body {
    namespace eval test_ns_1 {
        namespace export cmd1
        proc cmd1 {args} {return "cmd1: $args"}
        proc cmd2 {args} {return "cmd2: $args"}
	namespace export cmd1
	proc cmd1 {args} {return "cmd1: $args"}
	proc cmd2 {args} {return "cmd2: $args"}
    }
    namespace eval test_ns_1::test_ns_2 {
        namespace import ::test_ns_1::*
	namespace import ::test_ns_1::*
    }
    set x "test_ns_1::"
    set y "test_ns_2::"
    list [namespace which -command ${x}${y}cmd1] \
         [catch {namespace which -command ${x}${y}cmd2} msg] $msg \
         [catch {namespace which -command ${x}${y}:cmd2} msg] $msg
	 [catch {namespace which -command ${x}${y}cmd2} msg] $msg \
	 [catch {namespace which -command ${x}${y}:cmd2} msg] $msg
} -result {::test_ns_1::test_ns_2::cmd1 0 {} 0 {}}
test execute-4.2 {Tcl_GetCommandFromObj, check if cached tclCmdNameType is invalid} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    catch {rename foo ""}
    unset -nocomplain l
} -body {
    proc foo {} {
        return "global foo"
	return "global foo"
    }
    namespace eval test_ns_1 {
        proc whichFoo {} {
            return [namespace which -command foo]
        }
	proc whichFoo {} {
	    return [namespace which -command foo]
	}
    }
    set l ""
    lappend l [test_ns_1::whichFoo]
    namespace eval test_ns_1 {
        proc foo {} {
            return "namespace foo"
        }
	proc foo {} {
	    return "namespace foo"
	}
    }
    lappend l [test_ns_1::whichFoo]
} -result {::foo ::test_ns_1::foo}
test execute-4.3 {Tcl_GetCommandFromObj, command never found} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    catch {rename foo ""}
} -body {
    namespace eval test_ns_1 {
        proc foo {} {
            return "namespace foo"
        }
	proc foo {} {
	    return "namespace foo"
	}
    }
    namespace eval test_ns_1 {
        proc foo {} {
            return "namespace foo"
        }
	proc foo {} {
	    return "namespace foo"
	}
    }
    list [namespace eval test_ns_1 {namespace which -command foo}] \
         [rename test_ns_1::foo ""] \
         [catch {namespace eval test_ns_1 {namespace which -command foo}} msg] $msg
	 [rename test_ns_1::foo ""] \
	 [catch {namespace eval test_ns_1 {namespace which -command foo}} msg] $msg
} -result {::test_ns_1::foo {} 0 {}}

test execute-5.1 {SetCmdNameFromAny, set cmd name to empty heap string if NULL} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    unset -nocomplain l
} -body {
    proc {} {} {return {}}
    {}
    set l {}
    lindex {} 0
    {}
} -result {}

test execute-6.1 {UpdateStringOfCmdName: called for duplicate of empty cmdName object} {
    proc {} {} {}
    proc { } {} {}
    proc p {} {
        set x {}
        $x
        append x { }
        $x
	set x {}
	$x
	append x { }
	$x
    }
    p
} {}
test execute-6.2 {Evaluate an expression in a variable; compile the first time, do not the second} {
    set w {3*5}
    proc a {obj} {expr $obj}
    set res "[a $w]:[a $w]"
813
814
815
816
817
818
819
820

821
822
823

824
825
826

827
828
829

830
831
832

833
834
835

836
837
838

839
840
841

842
843
844

845
846
847

848
849
850

851
852
853

854
855
856

857
858
859

860
861
862

863
864
865
866
867
868
869
812
813
814
815
816
817
818

819
820
821

822
823
824

825
826
827

828
829
830

831
832
833

834
835
836

837
838
839

840
841
842

843
844
845

846
847
848

849
850
851

852
853
854

855
856
857

858
859
860

861
862
863
864
865
866
867
868







-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+







test execute-7.9 {Wide int handling in INST_MOD} {
    expr {(wide(1)<<60) % ((wide(47)<<45)-1)}
} 316659348800185
test execute-7.10 {Wide int handling in INST_MOD} {
    expr {((wide(1)<<60)-1) % 0x400000000}
} 17179869183
test execute-7.11 {Wide int handling in INST_LSHIFT} {
    expr wide(42)<<30
    expr {wide(42) << 30}
} 45097156608
test execute-7.12 {Wide int handling in INST_LSHIFT} {
    expr 12345678901<<3
    expr {12345678901 << 3}
} 98765431208
test execute-7.13 {Wide int handling in INST_RSHIFT} {
    expr 0x543210febcda9876>>7
    expr {0x543210febcda9876 >> 7}
} 47397893236700464
test execute-7.14 {Wide int handling in INST_RSHIFT} {
    expr wide(0x9876543210febcda)>>7
    expr {wide(0x9876543210febcda) >> 7}
} -58286587177206407
test execute-7.15 {Wide int handling in INST_BITOR} {
    expr wide(0x9876543210febcda) | 0x543210febcda9876
    expr {wide(0x9876543210febcda) | 0x543210febcda9876}
} -2560765885044310786
test execute-7.16 {Wide int handling in INST_BITXOR} {
    expr wide(0x9876543210febcda) ^ 0x543210febcda9876
    expr {wide(0x9876543210febcda) ^ 0x543210febcda9876}
} -3727778945703861076
test execute-7.17 {Wide int handling in INST_BITAND} {
    expr wide(0x9876543210febcda) & 0x543210febcda9876
    expr {wide(0x9876543210febcda) & 0x543210febcda9876}
} 1167013060659550290
test execute-7.18 {Wide int handling in INST_ADD} {
    expr wide(0x7fffffff)+wide(0x7fffffff)
    expr {wide(0x7fffffff) + wide(0x7fffffff)}
} 4294967294
test execute-7.19 {Wide int handling in INST_ADD} {
    expr 0x7fffffff+wide(0x7fffffff)
    expr {0x7fffffff + wide(0x7fffffff)}
} 4294967294
test execute-7.20 {Wide int handling in INST_ADD} {
    expr wide(0x7fffffff)+0x7fffffff
    expr {wide(0x7fffffff) + 0x7fffffff}
} 4294967294
test execute-7.21 {Wide int handling in INST_ADD} {
    expr double(0x7fffffff)+wide(0x7fffffff)
    expr {double(0x7fffffff) + wide(0x7fffffff)}
} 4294967294.0
test execute-7.22 {Wide int handling in INST_ADD} {
    expr wide(0x7fffffff)+double(0x7fffffff)
    expr {wide(0x7fffffff) + double(0x7fffffff)}
} 4294967294.0
test execute-7.23 {Wide int handling in INST_SUB} {
    expr 0x123456789a-0x20406080a
    expr {0x123456789a - 0x20406080a}
} 69530054800
test execute-7.24 {Wide int handling in INST_MULT} {
    expr 0x123456789a*193
    expr {0x123456789a * 193}
} 15090186251290
test execute-7.25 {Wide int handling in INST_DIV} {
    expr 0x123456789a/193
    expr {0x123456789a / 193}
} 405116546
test execute-7.26 {Wide int handling in INST_UPLUS} {
    set x 0x123456871234568
    expr {+ $x}
} 81985533099853160
test execute-7.27 {Wide int handling in INST_UMINUS} {
    set x 0x123456871234568
977
978
979
980
981
982
983
984

985
986
987
988
989
990
991
976
977
978
979
980
981
982

983
984
985
986
987
988
989
990







-
+







    invoked from within
"catch \[list error FOO\] m o"} -errorline 2}

test execute-8.6 {Compile epoch bump in global level (bug [fa6bf38d07])} -setup {
    interp create child
    child eval {
	package require tcltest 2.5
	catch [list package require -exact Tcltest [info patchlevel]]
	catch [list package require -exact tcl::test [info patchlevel]]
	::tcltest::loadTestedCommands
	if {[namespace which -command testbumpinterpepoch] eq ""} {
	  proc testbumpinterpepoch {} { rename ::set ::dummy; rename ::dummy ::set }
	}
    }
} -body {
    child eval {
1010
1011
1012
1013
1014
1015
1016
1017

1018
1019
1020
1021
1022
1023
1024
1009
1010
1011
1012
1013
1014
1015

1016
1017
1018
1019
1020
1021
1022
1023







-
+







} -cleanup {
    interp delete child
} -result [lrepeat 4 A B]
test execute-8.7 {Compile epoch bump in global level (bug [fa6bf38d07]), exception case} -setup {
    interp create child
    child eval {
	package require tcltest 2.5
	catch [list package require -exact Tcltest [info patchlevel]]
	catch [list package require -exact tcl::test [info patchlevel]]
	::tcltest::loadTestedCommands
	if {[namespace which -command testbumpinterpepoch] eq ""} {
	  proc testbumpinterpepoch {} { rename ::set ::dummy; rename ::dummy ::set }
	}
    }
} -body {
    set res {}
1058
1059
1060
1061
1062
1063
1064
1065

1066
1067
1068
1069
1070
1071
1072
1057
1058
1059
1060
1061
1062
1063

1064
1065
1066
1067
1068
1069
1070
1071







-
+







    } else {
	set result SUCCESS
    }
    set result
} SUCCESS

test execute-10.1 {TclExecuteByteCode, INST_CONCAT1, bytearrays} {
    apply {s {binary scan $s c x; list $x [scan $s$s %c%c]}} \u0130
    apply {s {binary scan [binary format a $s] c x; list $x [scan $s$s %c%c]}} Ä°
} {48 {304 304}}
test execute-10.2 {Bug 2802881} -setup {
    interp create child
} -body {
    # If [Bug 2802881] is not fixed, this will segfault
    child eval {
	trace add variable ::errorInfo write {expr {$foo} ;#}

Changes to tests/expr-old.test.

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
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
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
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








-
-
-
+
+
+










-
+





-









-
+

-
+









-
+

-
+

-
+





-
+

-
+









-
+

-
+

-
+







# Commands covered: expr
#
# This file contains the original set of tests for Tcl's expr command.
# Since the expr command is now compiled, a new set of tests covering
# the new implementation are in the files "parseExpr.test" and
# "compExpr.test". Sourcing this file into Tcl runs the tests and generates
# output for errors. No output means no errors were found.
#
# Copyright (c) 1991-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 by Scriptics Corporation.
# Copyright © 1991-1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-2000 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testexprlong   [llength [info commands testexprlong]]
testConstraint testexprdouble [llength [info commands testexprdouble]]
testConstraint testexprstring [llength [info commands testexprstring]]
testConstraint longIs32bit [expr {$tcl_platform(wordSize) == 4}]
testConstraint longIs64bit [expr {$tcl_platform(wordSize) == 8}]

# Big test for correct ordering of data in [expr]

proc testIEEE {} {
    variable ieeeValues
    binary scan [binary format dd -1.0 1.0] c* c
    switch -exact -- $c {
	{0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
	    # little endian
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\xFF d \
		ieeeValues(-Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\xBF d \
		ieeeValues(-Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
		ieeeValues(-Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x3F d \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \
		ieeeValues(+Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF8\x7F d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 1
	    return 1
	}
	{-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
	    binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \xFF\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Infinity)
	    binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \xBF\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Normal)
	    binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Subnormal)
	    binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x3F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Normal)
	    binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x7F\xF8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 0
	}
139
140
141
142
143
144
145
146

147
148
149
150
151
152
153
138
139
140
141
142
143
144

145
146
147
148
149
150
151
152







-
+







test expr-old-1.50 {integer operators} {expr +36} 36
test expr-old-1.51 {integer operators} {expr +--++36} 36
test expr-old-1.52 {integer operators} {expr +36%+5} 1
test expr-old-1.53 {integer operators} {
    unset -nocomplain x
    set x yes
    list [expr {1 && $x}] [expr {$x && 1}] \
         [expr {0 || $x}] [expr {$x || 0}]
	 [expr {0 || $x}] [expr {$x || 0}]
} {1 1 1 1}

# Check the floating-point operators individually, along with
# automatic conversion to integers where needed.

test expr-old-2.1 {floating-point operators} {expr -4.2} -4.2
test expr-old-2.2 {floating-point operators} {expr -(1.125+4.25)} -5.375
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
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







-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+







    list [catch {expr 028.1 + 09.2} msg] $msg
} {0 37.3}

# Operators that aren't legal on floating-point numbers

test expr-old-3.1 {illegal floating-point operations} {
    list [catch {expr ~4.0} msg] $msg
} {1 {can't use floating-point value "4.0" as operand of "~"}}
} {1 {cannot use floating-point value "4.0" as operand of "~"}}
test expr-old-3.2 {illegal floating-point operations} {
    list [catch {expr 27%4.0} msg] $msg
} {1 {can't use floating-point value "4.0" as operand of "%"}}
} {1 {cannot use floating-point value "4.0" as right operand of "%"}}
test expr-old-3.3 {illegal floating-point operations} {
    list [catch {expr 27.0%4} msg] $msg
} {1 {can't use floating-point value "27.0" as operand of "%"}}
} {1 {cannot use floating-point value "27.0" as left operand of "%"}}
test expr-old-3.4 {illegal floating-point operations} {
    list [catch {expr 1.0<<3} msg] $msg
} {1 {can't use floating-point value "1.0" as operand of "<<"}}
} {1 {cannot use floating-point value "1.0" as left operand of "<<"}}
test expr-old-3.5 {illegal floating-point operations} {
    list [catch {expr 3<<1.0} msg] $msg
} {1 {can't use floating-point value "1.0" as operand of "<<"}}
} {1 {cannot use floating-point value "1.0" as right operand of "<<"}}
test expr-old-3.6 {illegal floating-point operations} {
    list [catch {expr 24.0>>3} msg] $msg
} {1 {can't use floating-point value "24.0" as operand of ">>"}}
} {1 {cannot use floating-point value "24.0" as left operand of ">>"}}
test expr-old-3.7 {illegal floating-point operations} {
    list [catch {expr 24>>3.0} msg] $msg
} {1 {can't use floating-point value "3.0" as operand of ">>"}}
} {1 {cannot use floating-point value "3.0" as right operand of ">>"}}
test expr-old-3.8 {illegal floating-point operations} {
    list [catch {expr 24&3.0} msg] $msg
} {1 {can't use floating-point value "3.0" as operand of "&"}}
} {1 {cannot use floating-point value "3.0" as right operand of "&"}}
test expr-old-3.9 {illegal floating-point operations} {
    list [catch {expr 24.0|3} msg] $msg
} {1 {can't use floating-point value "24.0" as operand of "|"}}
} {1 {cannot use floating-point value "24.0" as left operand of "|"}}
test expr-old-3.10 {illegal floating-point operations} {
    list [catch {expr 24.0^3} msg] $msg
} {1 {can't use floating-point value "24.0" as operand of "^"}}
} {1 {cannot use floating-point value "24.0" as left operand of "^"}}

# Check the string operators individually.

test expr-old-4.1 {string operators} {expr {"abc" > "def"}} 0
test expr-old-4.2 {string operators} {expr {"def" > "def"}} 0
test expr-old-4.3 {string operators} {expr {"g" > "def"}} 1
test expr-old-4.4 {string operators} {expr {"abc" < "abd"}} 1
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
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







-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+







test expr-old-4.31 {string operators} {expr {1?"foo":"bar"}} foo
test expr-old-4.32 {string operators} {expr {0?"foo":"bar"}} bar

# Operators that aren't legal on string operands.

test expr-old-5.1 {illegal string operations} {
    list [catch {expr {-"a"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "-"}}
} {1 {cannot use non-numeric string "a" as operand of "-"}}
test expr-old-5.2 {illegal string operations} {
    list [catch {expr {+"a"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "+"}}
} {1 {cannot use non-numeric string "a" as operand of "+"}}
test expr-old-5.3 {illegal string operations} {
    list [catch {expr {~"a"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "~"}}
} {1 {cannot use non-numeric string "a" as operand of "~"}}
test expr-old-5.4 {illegal string operations} {
    list [catch {expr {!"a"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "!"}}
} {1 {cannot use non-numeric string "a" as operand of "!"}}
test expr-old-5.5 {illegal string operations} {
    list [catch {expr {"a"*"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "*"}}
} {1 {cannot use non-numeric string "a" as left operand of "*"}}
test expr-old-5.6 {illegal string operations} {
    list [catch {expr {"a"/"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "/"}}
} {1 {cannot use non-numeric string "a" as left operand of "/"}}
test expr-old-5.7 {illegal string operations} {
    list [catch {expr {"a"%"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "%"}}
} {1 {cannot use non-numeric string "a" as left operand of "%"}}
test expr-old-5.8 {illegal string operations} {
    list [catch {expr {"a"+"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "+"}}
} {1 {cannot use non-numeric string "a" as left operand of "+"}}
test expr-old-5.9 {illegal string operations} {
    list [catch {expr {"a"-"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "-"}}
} {1 {cannot use non-numeric string "a" as left operand of "-"}}
test expr-old-5.10 {illegal string operations} {
    list [catch {expr {"a"<<"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "<<"}}
} {1 {cannot use non-numeric string "a" as left operand of "<<"}}
test expr-old-5.11 {illegal string operations} {
    list [catch {expr {"a">>"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of ">>"}}
} {1 {cannot use non-numeric string "a" as left operand of ">>"}}
test expr-old-5.12 {illegal string operations} {
    list [catch {expr {"a"&"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "&"}}
} {1 {cannot use non-numeric string "a" as left operand of "&"}}
test expr-old-5.13 {illegal string operations} {
    list [catch {expr {"a"^"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "^"}}
} {1 {cannot use non-numeric string "a" as left operand of "^"}}
test expr-old-5.14 {illegal string operations} {
    list [catch {expr {"a"|"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "|"}}
} {1 {cannot use non-numeric string "a" as left operand of "|"}}
test expr-old-5.15 {illegal string operations} {
    list [catch {expr {"a"&&"b"}} msg] $msg
} {1 {expected boolean value but got "a"}}
test expr-old-5.16 {illegal string operations} {
    list [catch {expr {"a"||"b"}} msg] $msg
} {1 {expected boolean value but got "a"}}
test expr-old-5.17 {illegal string operations} {
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
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







-
+













-
+


-
+
















-
+






-
+







test expr-old-25.19 {type conversions} {expr 2.0e15} 2000000000000000.0
test expr-old-25.20 {type conversions} {expr 10.0} 10.0

# Various error conditions.

test expr-old-26.1 {error conditions} {
    list [catch {expr 2+"a"} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "+"}}
} {1 {cannot use non-numeric string "a" as right operand of "+"}}
test expr-old-26.2 {error conditions} -body {
    expr 2+4*
} -returnCodes error -match glob -result *
test expr-old-26.3 {error conditions} -body {
    expr 2+4*(
} -returnCodes error -match glob -result *
unset -nocomplain _non_existent_
test expr-old-26.4 {error conditions} {
    list [catch {expr 2+$_non_existent_} msg] $msg
} {1 {can't read "_non_existent_": no such variable}}
set a xx
test expr-old-26.5 {error conditions} {
    list [catch {expr {2+$a}} msg] $msg
} {1 {can't use non-numeric string "xx" as operand of "+"}}
} {1 {cannot use non-numeric string "xx" as right operand of "+"}}
test expr-old-26.6 {error conditions} {
    list [catch {expr {2+[set a]}} msg] $msg
} {1 {can't use non-numeric string "xx" as operand of "+"}}
} {1 {cannot use non-numeric string "xx" as right operand of "+"}}
test expr-old-26.7 {error conditions} -body {
    expr {2+(4}
} -returnCodes error -match glob -result *
test expr-old-26.8 {error conditions} {
    list [catch {expr 2/0} msg] $msg $errorCode
} {1 {divide by zero} {ARITH DIVZERO {divide by zero}}}
test expr-old-26.9 {error conditions} {
    list [catch {expr 2%0} msg] $msg $errorCode
} {1 {divide by zero} {ARITH DIVZERO {divide by zero}}}
test expr-old-26.10a {error conditions} !ieeeFloatingPoint {
    list [catch {expr 2.0/0.0} msg] $msg $errorCode
} {1 {divide by zero} {ARITH DIVZERO {divide by zero}}}
test expr-old-26.10b {error conditions} ieeeFloatingPoint {
    list [catch {expr 2.0/0.0} msg] $msg
} {0 Inf}
test expr-old-26.11 {error conditions} -body {
    expr 2#
    expr 2`
} -returnCodes error -match glob -result *
test expr-old-26.12 {error conditions} -body {
    expr a.b
} -returnCodes error -match glob -result *
test expr-old-26.13 {error conditions} {
    list [catch {expr {"a"/"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "/"}}
} {1 {cannot use non-numeric string "a" as left operand of "/"}}
test expr-old-26.14 {error conditions} -body {
    expr 2:3
} -returnCodes error -match glob -result *
test expr-old-26.15 {error conditions} -body {
    expr a@b
} -returnCodes error -match glob -result *
test expr-old-26.16 {error conditions} {
893
894
895
896
897
898
899
900

901
902
903
904
905
906
907
892
893
894
895
896
897
898

899
900
901
902
903
904
905
906







-
+







    list [catch {expr func_2(1.0)} msg] $msg
} -match glob -result {1 {* "*func_2"}}
test expr-old-34.2 {errors in math functions} -body {
    expr func|(1.0)
} -returnCodes error -match glob -result *
test expr-old-34.3 {errors in math functions} {
    list [catch {expr {hypot("a b", 2.0)}} msg] $msg
} {1 {expected floating-point number but got "a b"}}
} {1 {expected floating-point number but got a list}}
test expr-old-34.4 {errors in math functions} -body {
    expr hypot(1.0 2.0)
} -returnCodes error -match glob -result *
test expr-old-34.5 {errors in math functions} -body {
    expr hypot(1.0, 2.0
} -returnCodes error -match glob -result *
test expr-old-34.6 {errors in math functions} -body {
946
947
948
949
950
951
952
953

954
955
956
957
958
959
960
945
946
947
948
949
950
951

952
953
954
955
956
957
958
959







-
+








test expr-old-36.1 {ExprLooksLikeInt procedure} -body {
    expr 0o289
} -returnCodes error -match glob -result {*invalid octal number*}
test expr-old-36.2 {ExprLooksLikeInt procedure} {
    set x 0o289
    list [catch {expr {$x+1}} msg] $msg
} {1 {can't use non-numeric string "0o289" as operand of "+"}}
} {1 {cannot use non-numeric string "0o289" as left operand of "+"}}
test expr-old-36.3 {ExprLooksLikeInt procedure} {
    list [catch {expr 0289.1} msg] $msg
} {0 289.1}
test expr-old-36.4 {ExprLooksLikeInt procedure} {
    set x 0289.1
    list [catch {expr {$x+1}} msg] $msg
} {0 290.1}
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
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







-
+



-
+







-
+







    expr {$x+1}
} 665802003400000000000001

# tests for [Bug #587140]
test expr-old-36.12 {ExprLooksLikeInt procedure} {
    set x "10;"
    list [catch {expr {$x+1}} msg] $msg
} {1 {can't use non-numeric string "10;" as operand of "+"}}
} {1 {cannot use non-numeric string "10;" as left operand of "+"}}
test expr-old-36.13 {ExprLooksLikeInt procedure} {
    set x " +"
    list [catch {expr {$x+1}} msg] $msg
} {1 {can't use non-numeric string " +" as operand of "+"}}
} {1 {cannot use non-numeric string " +" as left operand of "+"}}
test expr-old-36.14 {ExprLooksLikeInt procedure} {
    set x "123456789012345678901234567890 "
    expr {$x+1}
} 123456789012345678901234567891
test expr-old-36.15 {ExprLooksLikeInt procedure} {
    set x "0o99 "
    list [catch {expr {$x+1}} msg] $msg
} {1 {can't use non-numeric string "0o99 " as operand of "+"}}
} {1 {cannot use non-numeric string "0o99 " as left operand of "+"}}
test expr-old-36.16 {ExprLooksLikeInt procedure} {
    set x " 0xffffffffffffffffffffffffffffffffffffff  "
    expr {$x+1}
} [expr 0x100000000000000000000000000000000000000]

test expr-old-37.1 {Check that Tcl_ExprLong doesn't modify interpreter result if no error} testexprlong {
    testexprlong 4+1

Changes to tests/expr.test.

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
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
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
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






-
-
+
+















-










-
+

-
+









-
+

-
+

-
+

-
+





-
+

-
+









-
+

-
+

-
+

-
+







# Commands covered: expr
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands. Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 by Scriptics Corporation.
# Copyright © 1996-1997 Sun Microsystems, Inc.
# Copyright © 1998-2000 Scriptics Corporation.
#
# 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

# Determine if "long int" type is a 32 bit number and if the wide
# type is a 64 bit number on this machine.

testConstraint longIs32bit [expr {$tcl_platform(wordSize) == 4}]
testConstraint longIs64bit [expr {$tcl_platform(wordSize) == 8}]
testConstraint wideIs64bit [expr {wide(0x8000000000000000) < 0}]

# Big test for correct ordering of data in [expr]

proc testIEEE {} {
    variable ieeeValues
    binary scan [binary format dd -1.0 1.0] c* c
    switch -exact -- $c {
	{0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
	    # little endian
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\xFF d \
		ieeeValues(-Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\xBF d \
		ieeeValues(-Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
		ieeeValues(-Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x3F d \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \
		ieeeValues(+Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF8\x7F d \
		ieeeValues(NaN)
	    binary scan \x00\x00\x00\x00\x00\x00\xf8\xff d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF8\xFF d \
		ieeeValues(-NaN)
	    set ieeeValues(littleEndian) 1
	    return 1
	}
	{-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
	    binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \xFF\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Infinity)
	    binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \xBF\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Normal)
	    binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Subnormal)
	    binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x3F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Normal)
	    binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x7F\xF8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    binary scan \xff\xf8\x00\x00\x00\x00\x00\x00 d \
	    binary scan \xFF\xF8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-NaN)
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 0
	}
94
95
96
97
98
99
100
101
102
103
104
105
106






107
108
109
110
111
112
113
93
94
95
96
97
98
99






100
101
102
103
104
105
106
107
108
109
110
111
112







-
-
-
-
-
-
+
+
+
+
+
+







    return $c
}
proc hello_world {} {
    global a
    set a ""
    set L1 [set l0 [set h_1 [set q 0]]]
    for {put_hello_char [expr [put_hello_char [expr [set h 7]*10+2]]+29]} {$l0?[put_hello_char $l0]
        :!$h_1} {put_hello_char $ll;expr {$L1==2?[set ll [expr 32+0-0+[set bar 0]]]:0}} {expr {[incr L1]==[expr 1+([string length "abc"]-[string length "abc"])]
        ?[set ll [set l0 [expr 54<<1]]]:$ll==108&&$L1<3?
        [incr ll [expr 1|1<<1]; set ll $ll; set ll $ll; set ll $ll; set ll $ll; set l0 [expr ([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])]; set l0; set l0 $l0; set l0; set l0]:$L1==4&&$ll==32?[set ll [expr 19+$h1+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])+[set foo [expr ([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])]]]]
        :[set q [expr $q-$h1+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])]]};expr {$L1==5?[incr ll -8; set ll $ll; set ll]:$q&&$h1&&1};expr {$L1==4+2
        ?[incr ll 3]:[expr ([string length "abc"]-[string length "abc"])+1]};expr {$ll==($h<<4)+2+0&&$L1!=6?[incr ll -6]:[set h1 [expr 100+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])]]}
        expr {$L1!=1<<3?[incr q [expr ([string length "abc"]-[string length "abc"])-1]]:[set h_1 [set ll $h1]]}
	:!$h_1} {put_hello_char $ll;expr {$L1==2?[set ll [expr 32+0-0+[set bar 0]]]:0}} {expr {[incr L1]==[expr 1+([string length "abc"]-[string length "abc"])]
	?[set ll [set l0 [expr 54<<1]]]:$ll==108&&$L1<3?
	[incr ll [expr 1|1<<1]; set ll $ll; set ll $ll; set ll $ll; set ll $ll; set l0 [expr ([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])]; set l0; set l0 $l0; set l0; set l0]:$L1==4&&$ll==32?[set ll [expr 19+$h1+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])+[set foo [expr ([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])+([string length "abc"]-[string length "abc"])]]]]
	:[set q [expr $q-$h1+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])]]};expr {$L1==5?[incr ll -8; set ll $ll; set ll]:$q&&$h1&&1};expr {$L1==4+2
	?[incr ll 3]:[expr ([string length "abc"]-[string length "abc"])+1]};expr {$ll==($h<<4)+2+0&&$L1!=6?[incr ll -6]:[set h1 [expr 100+([string length "abc"]-[string length "abc"])-([string length "abc"]-[string length "abc"])]]}
	expr {$L1!=1<<3?[incr q [expr ([string length "abc"]-[string length "abc"])-1]]:[set h_1 [set ll $h1]]}
    }
    set a
}

proc 12days {a b c} {
    global xxx
    expr {1<$a?[expr {$a<3?[12days -79 -13 [string range $c [12days -87 \
133
134
135
136
137
138
139
140
141
142



143
144
145
146
147
148
149
132
133
134
135
136
137
138



139
140
141
142
143
144
145
146
147
148







-
-
-
+
+
+







    return $result
}

# start of tests

catch {unset a b i x}

test expr-1.1 {TclCompileExprCmd: no expression} {
    list [catch {expr  } msg] $msg
} {1 {wrong # args: should be "expr arg ?arg ...?"}}
test expr-1.1 {TclCompileExprCmd: no expression} -body {
    expr
} -returnCodes error -result {wrong # args: should be "expr arg ?arg ...?"}
test expr-1.2 {TclCompileExprCmd: one expression word} {
    expr -25
} -25
test expr-1.3 {TclCompileExprCmd: two expression words} {
    expr -8.2   -6
} -14.2
test expr-1.4 {TclCompileExprCmd: five expression words} {
182
183
184
185
186
187
188
189

190
191
192
193
194

195
196
197
198
199
200
201
181
182
183
184
185
186
187

188
189
190
191
192

193
194
195
196
197
198
199
200







-
+




-
+







test expr-1.13 {TclCompileExprCmd: second level of substitutions in expr not in braces with single var reference} {
    set a xxx
    set x 27;  set bool {$x};  if $bool {set a foo}
    set a
} foo
test expr-1.14 {TclCompileExprCmd: second level of substitutions in expr with comparison as top-level operator} {
    set a xxx
    set x 2;  set b {$x};  set a [expr $b == 2]
    set x 2;  set b {$x};  set a [expr $b==2]
    set a
} 1
test expr-1.15 {TclCompileExprCmd: second level of substitutions in expr with comparison as top-level operator} {
    set a xxx
    set x 2;  set b {$x};  set a [expr $b eq 2]
    set x 2;  set b {$x};  set a [expr "$b eq 2"]
    set a
} 1

test expr-2.1 {TclCompileExpr: are builtin functions registered?} {
    expr double(5*[llength "6 2"])
} 10.0
test expr-2.2 {TclCompileExpr: error in expr} -body {
247
248
249
250
251
252
253
254

255
256
257
258
259
260
261
246
247
248
249
250
251
252

253
254
255
256
257
258
259
260







-
+







test expr-4.9 {CompileLorExpr: long lor arm} {
    set a "abcdefghijkl"
    set i 7
    expr {[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]}
} 1
test expr-4.10 {CompileLorExpr: error compiling ! operand} {
    list [catch {expr {!"a"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "!"}}
} {1 {cannot use non-numeric string "a" as operand of "!"}}
test expr-4.11 {CompileLorExpr: error compiling land arms} {
    list [catch {expr {"a"||0}} msg] $msg
} {1 {expected boolean value but got "a"}}
test expr-4.12 {CompileLorExpr: error compiling land arms} {
    list [catch {expr {0||"a"}} msg] $msg
} {1 {expected boolean value but got "a"}}

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
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







-
+


-
+




















-
+


-
+







    expr 2***3|6
} -returnCodes error -match glob -result *
test expr-6.8 {CompileBitXorExpr: error compiling bitxor arm} -body {
    expr 2^x
} -returnCodes error -match glob -result *
test expr-6.9 {CompileBitXorExpr: runtime error in bitxor arm} {
    list [catch {expr {24.0^3}} msg] $msg
} {1 {can't use floating-point value "24.0" as operand of "^"}}
} {1 {cannot use floating-point value "24.0" as left operand of "^"}}
test expr-6.10 {CompileBitXorExpr: runtime error in bitxor arm} {
    list [catch {expr {"a"^"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "^"}}
} {1 {cannot use non-numeric string "a" as left operand of "^"}}

test expr-7.1 {CompileBitAndExpr: just equality expr} {expr 3==2} 0
test expr-7.2 {CompileBitAndExpr: just equality expr} {expr 2.0==2} 1
test expr-7.3 {CompileBitAndExpr: just equality expr} {expr 3.2!=2.2} 1
test expr-7.4 {CompileBitAndExpr: just equality expr} {expr {"abc" == "abd"}} 0
test expr-7.5 {CompileBitAndExpr: error in equality expr} -body {
    expr x==3
} -returnCodes error -match glob -result *
test expr-7.6 {CompileBitAndExpr: simple bitand exprs} {expr 7&0x13} 3
test expr-7.7 {CompileBitAndExpr: simple bitand exprs} {expr 0xf2&0x53} 82
test expr-7.8 {CompileBitAndExpr: simple bitand exprs} {expr 3&6} 2
test expr-7.9 {CompileBitAndExpr: simple bitand exprs} {expr -1&-7} -7
test expr-7.10 {CompileBitAndExpr: error compiling bitand arm} -body {
    expr 2***3&6
} -returnCodes error -match glob -result *
test expr-7.11 {CompileBitAndExpr: error compiling bitand arm} -body {
    expr 2&x
} -returnCodes error -match glob -result *
test expr-7.12 {CompileBitAndExpr: runtime error in bitand arm} {
    list [catch {expr {24.0&3}} msg] $msg
} {1 {can't use floating-point value "24.0" as operand of "&"}}
} {1 {cannot use floating-point value "24.0" as left operand of "&"}}
test expr-7.13 {CompileBitAndExpr: runtime error in bitand arm} {
    list [catch {expr {"a"&"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "&"}}
} {1 {cannot use non-numeric string "a" as left operand of "&"}}
test expr-7.14 {CompileBitAndExpr: equality expr} {expr 3eq2} 0
test expr-7.18 {CompileBitAndExpr: equality expr} {expr {"abc" eq "abd"}} 0
test expr-7.20 {CompileBitAndExpr: error in equality expr} -body {
    expr xne3
} -returnCodes error -match glob -result *

test expr-8.1 {CompileEqualityExpr: just relational expr} {expr 3>=2} 1
346
347
348
349
350
351
352
353

354
355
356
357
358
359
360
345
346
347
348
349
350
351

352
353
354
355
356
357
358
359







-
+







test expr-8.10 {CompileEqualityExpr: error compiling equality arm} -body {
    expr 2***3==6
} -returnCodes error -match glob -result *
test expr-8.11 {CompileEqualityExpr: error compiling equality arm} -body {
    expr 2!=x
} -returnCodes error -match glob -result *
test expr-8.12 {CompileBitAndExpr: equality expr} {expr {"a"eq"a"}} 1
test expr-8.13 {CompileBitAndExpr: equality expr} {expr {"\374" eq [set s \u00fc]}} 1
test expr-8.13 {CompileBitAndExpr: equality expr} {expr {"\374" eq [set s \xFC]}} 1
test expr-8.14 {CompileBitAndExpr: equality expr} {expr 3eq2} 0
test expr-8.15 {CompileBitAndExpr: equality expr} {expr 2.0eq2} 0
test expr-8.16 {CompileBitAndExpr: equality expr} {expr 3.2ne2.2} 1
test expr-8.17 {CompileBitAndExpr: equality expr} {expr 01eq1} 0
test expr-8.18 {CompileBitAndExpr: equality expr} {expr {"abc" eq "abd"}} 0
test expr-8.19 {CompileBitAndExpr: equality expr} {expr {"abc" ne "abd"}} 1
test expr-8.20 {CompileBitAndExpr: error in equality expr} -body {
463
464
465
466
467
468
469
470

471
472
473

474
475
476
477
478
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
462
463
464
465
466
467
468

469
470
471

472
473
474
475
476
477
478
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
558
559
560
561







-
+


-
+


















-
+


-
+









+
+
+
+
+
+
+
+
+


















-
+


-
+
















-
+


-
+







    expr 2***3>>6
} -returnCodes error -match glob -result *
test expr-10.9 {CompileShiftExpr: error compiling shift arm} -body {
    expr 2<<x
} -returnCodes error -match glob -result *
test expr-10.10 {CompileShiftExpr: runtime error} {
    list [catch {expr {24.0>>43}} msg] $msg
} {1 {can't use floating-point value "24.0" as operand of ">>"}}
} {1 {cannot use floating-point value "24.0" as left operand of ">>"}}
test expr-10.11 {CompileShiftExpr: runtime error} {
    list [catch {expr {"a"<<"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "<<"}}
} {1 {cannot use non-numeric string "a" as left operand of "<<"}}

test expr-11.1 {CompileAddExpr: just multiply expr} {expr 4*-2} -8
test expr-11.2 {CompileAddExpr: just multiply expr} {expr 0xff%2} 1
test expr-11.3 {CompileAddExpr: just multiply expr} {expr -1/2} -1
test expr-11.4 {CompileAddExpr: just multiply expr} {expr 7891%0o123} 6
test expr-11.5 {CompileAddExpr: error in multiply expr} -body {
    expr x*3
} -returnCodes error -match glob -result *
test expr-11.6 {CompileAddExpr: simple add exprs} {expr 0xff++0x3} 258
test expr-11.7 {CompileAddExpr: simple add exprs} {expr -0xf2--0x3} -239
test expr-11.8 {CompileAddExpr: error compiling add arm} -body {
    expr 2***3+6
} -returnCodes error -match glob -result *
test expr-11.9 {CompileAddExpr: error compiling add arm} -body {
    expr 2-x
} -returnCodes error -match glob -result *
test expr-11.10 {CompileAddExpr: runtime error} {
    list [catch {expr {24.0+"xx"}} msg] $msg
} {1 {can't use non-numeric string "xx" as operand of "+"}}
} {1 {cannot use non-numeric string "xx" as right operand of "+"}}
test expr-11.11 {CompileAddExpr: runtime error} {
    list [catch {expr {"a"-"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "-"}}
} {1 {cannot use non-numeric string "a" as left operand of "-"}}
test expr-11.12 {CompileAddExpr: runtime error} {
    list [catch {expr {3/0}} msg] $msg
} {1 {divide by zero}}
test expr-11.13a {CompileAddExpr: runtime error} !ieeeFloatingPoint {
    list [catch {expr {2.3/0.0}} msg] $msg
} {1 {divide by zero}}
test expr-11.13b {CompileAddExpr: runtime error} ieeeFloatingPoint {
    list [catch {expr {2.3/0.0}} msg] $msg
} {0 Inf}
test expr-11.14 {CompileAddExpr: runtime error} {
    list [catch {expr {24.0+[lseq 2 4]}} msg] $msg
} {1 {cannot use a list as right operand of "+"}}
test expr-11.15 {CompileAddExpr: runtime error} {
    list [catch {expr {{1 2 "}+24.0}} msg] $msg
} {1 {cannot use non-numeric string "1 2 "" as left operand of "+"}}
test expr-11.16 {CompileAddExpr: runtime error} {
    list [catch {expr {~[dict create foo bar]}} msg] $msg
} {1 {cannot use a list as operand of "~"}}

test expr-12.1 {CompileMultiplyExpr: just unary expr} {expr ~4} -5
test expr-12.2 {CompileMultiplyExpr: just unary expr} {expr --5} 5
test expr-12.3 {CompileMultiplyExpr: just unary expr} {expr !27} 0
test expr-12.4 {CompileMultiplyExpr: just unary expr} {expr ~0xff00ff} -16711936
test expr-12.5 {CompileMultiplyExpr: error in unary expr} -body {
    expr ~x
} -returnCodes error -match glob -result *
test expr-12.6 {CompileMultiplyExpr: simple multiply exprs} {expr 0xff*0x3} 765
test expr-12.7 {CompileMultiplyExpr: simple multiply exprs} {expr -0xf2%-0x3} -2
test expr-12.8 {CompileMultiplyExpr: error compiling multiply arm} -body {
    expr 2*3%%6
} -returnCodes error -match glob -result *
test expr-12.9 {CompileMultiplyExpr: error compiling multiply arm} -body {
    expr 2*x
} -returnCodes error -match glob -result *
test expr-12.10 {CompileMultiplyExpr: runtime error} {
    list [catch {expr {24.0*"xx"}} msg] $msg
} {1 {can't use non-numeric string "xx" as operand of "*"}}
} {1 {cannot use non-numeric string "xx" as right operand of "*"}}
test expr-12.11 {CompileMultiplyExpr: runtime error} {
    list [catch {expr {"a"/"b"}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "/"}}
} {1 {cannot use non-numeric string "a" as left operand of "/"}}

test expr-13.1 {CompileUnaryExpr: unary exprs} {expr -0xff} -255
test expr-13.2 {CompileUnaryExpr: unary exprs} {expr +0o00123} 83
test expr-13.3 {CompileUnaryExpr: unary exprs} {expr +--++36} 36
test expr-13.4 {CompileUnaryExpr: unary exprs} {expr !2} 0
test expr-13.5 {CompileUnaryExpr: unary exprs} {expr +--+-62.0} -62.0
test expr-13.6 {CompileUnaryExpr: unary exprs} {expr !0.0} 1
test expr-13.7 {CompileUnaryExpr: unary exprs} {expr !0xef} 0
test expr-13.8 {CompileUnaryExpr: error compiling unary expr} -body {
    expr ~x
} -returnCodes error -match glob -result *
test expr-13.9 {CompileUnaryExpr: error compiling unary expr} -body {
    expr !1.x
} -returnCodes error -match glob -result *
test expr-13.10 {CompileUnaryExpr: runtime error} {
    list [catch {expr {~"xx"}} msg] $msg
} {1 {can't use non-numeric string "xx" as operand of "~"}}
} {1 {cannot use non-numeric string "xx" as operand of "~"}}
test expr-13.11 {CompileUnaryExpr: runtime error} {
    list [catch {expr ~4.0} msg] $msg
} {1 {can't use floating-point value "4.0" as operand of "~"}}
} {1 {cannot use floating-point value "4.0" as operand of "~"}}
test expr-13.12 {CompileUnaryExpr: just primary expr} {expr 0x123} 291
test expr-13.13 {CompileUnaryExpr: just primary expr} {
    set a 27
    expr $a
} 27
test expr-13.14 {CompileUnaryExpr: just primary expr} {
    expr double(27)
699
700
701
702
703
704
705
706

707
708
709
710
711
712
713
707
708
709
710
711
712
713

714
715
716
717
718
719
720
721







-
+









test expr-16.1 {GetToken: checks whether integer token starting with "0x" (e.g., "0x$") is invalid} {
    catch {unset a}
    set a(VALUE) ff15
    set i 123
    if {[expr 0x$a(VALUE)] & 16} {
        set i {}
	set i {}
    }
    set i
} {}
test expr-16.2 {GetToken: check for string literal in braces} {
    expr {{1}}
} {1}

733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750











751
752
753
754
755
756
757
741
742
743
744
745
746
747











748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765







-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+







} { }

# Check "expr" and interpreter result object resetting before appending
# an error msg during evaluation of exprs not in {}s

test expr-19.1 {expr and interpreter result object resetting} {
    proc p {} {
        set t  10.0
        set x  2.0
        set dx 0.2
        set f  {$dx-$x/10}
        set g  {-$x/5}
        set center 1.0
        set x  [expr $x-$center]
        set dx [expr $dx+$g]
        set x  [expr $x+$f+$center]
        set x  [expr $x+$f+$center]
        set y  [expr round($x)]
	set t  10.0
	set x  2.0
	set dx 0.2
	set f  {$dx-$x/10}
	set g  {-$x/5}
	set center 1.0
	set x  [expr $x-$center]
	set dx [expr $dx+$g]
	set x  [expr $x+$f+$center]
	set x  [expr $x+$f+$center]
	set y  [expr round($x)]
    }
    p
} 3

# Test for incorrect "double evaluation" semantics

test expr-20.1 {wrong brace matching} {
769
770
771
772
773
774
775
776

777
778

779
780
781

782
783
784


785
786
787
788
789
790
791
777
778
779
780
781
782
783

784
785

786
787
788

789
790


791
792
793
794
795
796
797
798
799







-
+

-
+


-
+

-
-
+
+







    proc exprtraceproc {args} {
       upvar #0 exprtracecounter counter
       set argc [llength $args]
       set extraargs [lrange $args 0 [expr {$argc - 4}]]
       set name [lindex $args [expr {$argc - 3}]]
       upvar 1 $name var
       if {[incr counter] % 2 == 1} {
           set var "$counter oops [concat $extraargs]"
	   set var "$counter oops [concat $extraargs]"
       } else {
           set var "$counter + [concat $extraargs]"
	   set var "$counter + [concat $extraargs]"
       }
    }
    trace variable exprtracevar r [list exprtraceproc 10]
    trace add variable exprtracevar read [list exprtraceproc 10]
    list [catch {expr "$exprtracevar + 20"} a] $a \
        [catch {expr "$exprtracevar + 20"} b] $b \
        [unset exprtracevar exprtracecounter]
	[catch {expr "$exprtracevar + 20"} b] $b \
	[unset exprtracevar exprtracecounter]
} -match glob -result {1 * 0 32 {}}
test expr-20.3 {broken substitution of integer digits} {
    # fails with 8.0.x, but not 8.1b2
    list [set a 000; expr 0x1$a] [set a 1; expr ${a}000]
} {4096 1000}
test expr-20.4 {proper double evaluation compilation, error case} {
    catch {unset a}; # make sure $a doesn't exist
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814









815
816
817
818
819
820
821
822
823

824
825
826
827

828
829
830
831

832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851

852
853
854
855

856
857
858
859
860

861
862
863
864
865
866
867

868
869
870
871
872
873
874
875
876
877
878
879
880

881
882
883
884
885
886
887
807
808
809
810
811
812
813









814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830

831
832
833
834

835
836
837
838

839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858

859
860
861
862

863
864
865
866
867

868
869
870
871
872
873
874

875
876
877
878
879
880
881
882
883
884
885
886
887

888
889
890
891
892
893
894
895







-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+








-
+



-
+



-
+



















-
+



-
+




-
+






-
+












-
+







    list [catch {expr + {[incr]}} msg] $msg
} {1 {wrong # args: should be "incr varName ?increment?"}}
test expr-20.7 {handling of compile error in runtime case} {
    list [catch {expr + {[error foo]}} msg] $msg
} {1 foo}

# Test for non-numeric boolean literal handling
test expr-21.1 	{non-numeric boolean literals} {expr false } false
test expr-21.2 	{non-numeric boolean literals} {expr true  } true
test expr-21.3 	{non-numeric boolean literals} {expr off   } off
test expr-21.4 	{non-numeric boolean literals} {expr on    } on
test expr-21.5 	{non-numeric boolean literals} {expr no    } no
test expr-21.6 	{non-numeric boolean literals} {expr yes   } yes
test expr-21.7 	{non-numeric boolean literals} {expr !false} 1
test expr-21.8 	{non-numeric boolean literals} {expr !true } 0
test expr-21.9 	{non-numeric boolean literals} {expr !off  } 1
test expr-21.1	{non-numeric boolean literals} {expr false } false
test expr-21.2	{non-numeric boolean literals} {expr true  } true
test expr-21.3	{non-numeric boolean literals} {expr off   } off
test expr-21.4	{non-numeric boolean literals} {expr on    } on
test expr-21.5	{non-numeric boolean literals} {expr no    } no
test expr-21.6	{non-numeric boolean literals} {expr yes   } yes
test expr-21.7	{non-numeric boolean literals} {expr !false} 1
test expr-21.8	{non-numeric boolean literals} {expr !true } 0
test expr-21.9	{non-numeric boolean literals} {expr !off  } 1
test expr-21.10 {non-numeric boolean literals} {expr !on   } 0
test expr-21.11 {non-numeric boolean literals} {expr !no   } 1
test expr-21.12 {non-numeric boolean literals} {expr !yes  } 0
test expr-21.13 {non-numeric boolean literals} -body {
    expr !truef
} -returnCodes error -match glob -result *
test expr-21.14 {non-numeric boolean literals} {
    list [catch {expr !"truef"} err] $err
} {1 {can't use non-numeric string "truef" as operand of "!"}}
} {1 {cannot use non-numeric string "truef" as operand of "!"}}
test expr-21.15 {non-numeric boolean variables} {
    set v truef
    list [catch {expr {!$v}} err] $err
} {1 {can't use non-numeric string "truef" as operand of "!"}}
} {1 {cannot use non-numeric string "truef" as operand of "!"}}
test expr-21.16 {non-numeric boolean variables} {
    set v "true "
    list [catch {expr {!$v}} err] $err
} {1 {can't use non-numeric string "true " as operand of "!"}}
} {1 {cannot use non-numeric string "true " as operand of "!"}}
test expr-21.17 {non-numeric boolean variables} {
    set v "tru"
    list [catch {expr {!$v}} err] $err
} {0 0}
test expr-21.18 {non-numeric boolean variables} {
    set v "fal"
    list [catch {expr {!$v}} err] $err
} {0 1}
test expr-21.19 {non-numeric boolean variables} {
    set v "y"
    list [catch {expr {!$v}} err] $err
} {0 0}
test expr-21.20 {non-numeric boolean variables} {
    set v "of"
    list [catch {expr {!$v}} err] $err
} {0 1}
test expr-21.21 {non-numeric boolean variables} {
    set v "o"
    list [catch {expr {!$v}} err] $err
} {1 {can't use non-numeric string "o" as operand of "!"}}
} {1 {cannot use non-numeric string "o" as operand of "!"}}
test expr-21.22 {non-numeric boolean variables} {
    set v ""
    list [catch {expr {!$v}} err] $err
} {1 {can't use non-numeric string "" as operand of "!"}}
} {1 {cannot use non-numeric string "" as operand of "!"}}

# Test for non-numeric float handling.
test expr-22.1 {non-numeric floats} {
    list [catch {expr {NaN + 1}} msg] $msg
} {1 {can't use non-numeric floating-point value "NaN" as operand of "+"}}
} {1 {cannot use non-numeric floating-point value "NaN" as left operand of "+"}}
test expr-22.2 {non-numeric floats} !ieeeFloatingPoint {
    list [catch {expr {Inf + 1}} msg] $msg
} {1 {can't use infinite floating-point value as operand of "+"}}
test expr-22.3 {non-numeric floats} {
    set nan NaN
    list [catch {expr {$nan + 1}} msg] $msg
} {1 {can't use non-numeric floating-point value "NaN" as operand of "+"}}
} {1 {cannot use non-numeric floating-point value "NaN" as left operand of "+"}}
test expr-22.4 {non-numeric floats} !ieeeFloatingPoint {
    set inf Inf
    list [catch {expr {$inf + 1}} msg] $msg
} {1 {can't use infinite floating-point value as operand of "+"}}
test expr-22.5 {non-numeric floats} {
    list [catch {expr NaN} msg] $msg
} {1 {domain error: argument not in valid range}}
test expr-22.6 {non-numeric floats} !ieeeFloatingPoint {
    list [catch {expr Inf} msg] $msg
} {1 {floating-point value too large to represent}}
test expr-22.7 {non-numeric floats} {
    list [catch {expr {1 / NaN}} msg] $msg
} {1 {can't use non-numeric floating-point value "NaN" as operand of "/"}}
} {1 {cannot use non-numeric floating-point value "NaN" as right operand of "/"}}
test expr-22.8 {non-numeric floats} !ieeeFloatingPoint {
    list [catch {expr {1 / Inf}} msg] $msg
} {1 {can't use infinite floating-point value as operand of "/"}}
# Make sure [Bug 761471] stays fixed.
test expr-22.9 {non-numeric floats: shared object equality and NaN} {
    set x NaN
    expr {$x == $x}
909
910
911
912
913
914
915
916

917
918
919

920
921
922
923
924
925
926
917
918
919
920
921
922
923

924
925
926

927
928
929
930
931
932
933
934







-
+


-
+







    expr (-3-)**6
} -returnCodes error -match glob -result *
test expr-23.8 {CompileExponentialExpr: error compiling expo arm} -body {
    expr 2**x
} -returnCodes error -match glob -result *
test expr-23.9 {CompileExponentialExpr: runtime error} {
    list [catch {expr {24.0**"xx"}} msg] $msg
} {1 {can't use non-numeric string "xx" as operand of "**"}}
} {1 {cannot use non-numeric string "xx" as right operand of "**"}}
test expr-23.10 {CompileExponentialExpr: runtime error} {
    list [catch {expr {"a"**2}} msg] $msg
} {1 {can't use non-numeric string "a" as operand of "**"}}
} {1 {cannot use non-numeric string "a" as left operand of "**"}}
test expr-23.11 {CompileExponentialExpr: runtime error} {
    list [catch {expr {0**-1}} msg] $msg
} {1 {exponentiation of zero by negative power}}
test expr-23.12 {CompileExponentialExpr: runtime error} {
    list [catch {expr {0.0**-1.0}} msg] $msg
} {1 {exponentiation of zero by negative power}}
test expr-23.13 {CompileExponentialExpr: runtime error} {
1423
1424
1425
1426
1427
1428
1429


1430
1431
1432
1433
1434
1435
1436
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446







+
+







test expr-24.5 {expr edge cases; shifting} {expr int(5<<32)} 21474836480
test expr-24.6 {expr edge cases; shifting} {expr int(5<<63)} 46116860184273879040
test expr-24.7 {expr edge cases; shifting} {expr wide(5)<<32} 21474836480
test expr-24.8 {expr edge cases; shifting} {expr wide(10<<63)} 0
test expr-24.9 {expr edge cases; shifting} {expr 5>>32} 0

test expr-24.10 {INST_LSHIFT: Bug 1567222} {expr 500000000000000<<28} 134217728000000000000000
test expr-24.11 {INST_LSHIFT: Bug 84a5355235} {expr -549755813888>>32} -128
test expr-24.12 {INST_LSHIFT: Bug 920e393634} {expr 7244019458077122840<<1} 14488038916154245680

# List membership tests
test expr-25.1 {'in' operator} {expr {"a" in "a b c"}} 1
test expr-25.2 {'in' operator} {expr {"a" in "b a c"}} 1
test expr-25.3 {'in' operator} {expr {"a" in "b c a"}} 1
test expr-25.4 {'in' operator} {expr {"a" in ""}} 0
test expr-25.5 {'in' operator} {expr {"" in {a b c ""}}} 1
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742














5743
5744
5745
5746
5747



5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781














5782
5783
5784
5785
5786



5787
5788
5789
5790
5791
5792
5793
5732
5733
5734
5735
5736
5737
5738














5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754



5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777














5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793



5794
5795
5796
5797
5798
5799
5800
5801
5802
5803







-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
+
+
+




















-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
+
+
+







test expr-31.14 {boolean conversion} {expr bool(wide(5))} 1
test expr-31.15 {boolean conversion} -body {
    expr bool("fred")
} -returnCodes error -match glob -result *

test expr-32.1 {expr mod basics} {
    set mod_nums [list \
        {-3 1} {-3 2} {-3 3} {-3 4} {-3 5} \
        {-3 -1} {-3 -2} {-3 -3} {-3 -4} {-3 -5} \
        {-2 1} {-2 2} {-2 3} {-2 4} {-2 5} \
        {-2 -1} {-2 -2} {-2 -3} {-2 -4} {-2 -5} \
        {-1 1} {-1 2} {-1 3} {-1 4} {-1 5} \
        {-1 -1} {-1 -2} {-1 -3} {-1 -4} {-1 -5} \
        {0 -100} {0 -1} {0 1} {0 100} \
        {1 1} {1 2} {1 3} {1 4} {1 5} \
        {1 -1} {1 -2} {1 -3} {1 -4} {1 -5} \
        {2 1} {2 2} {2 3} {2 4} {2 5} \
        {2 -1} {2 -2} {2 -3} {2 -4} {2 -5} \
        {3 1} {3 2} {3 3} {3 4} {3 5} \
        {3 -1} {3 -2} {3 -3} {3 -4} {3 -5} \
        ]
	{-3 1} {-3 2} {-3 3} {-3 4} {-3 5} \
	{-3 -1} {-3 -2} {-3 -3} {-3 -4} {-3 -5} \
	{-2 1} {-2 2} {-2 3} {-2 4} {-2 5} \
	{-2 -1} {-2 -2} {-2 -3} {-2 -4} {-2 -5} \
	{-1 1} {-1 2} {-1 3} {-1 4} {-1 5} \
	{-1 -1} {-1 -2} {-1 -3} {-1 -4} {-1 -5} \
	{0 -100} {0 -1} {0 1} {0 100} \
	{1 1} {1 2} {1 3} {1 4} {1 5} \
	{1 -1} {1 -2} {1 -3} {1 -4} {1 -5} \
	{2 1} {2 2} {2 3} {2 4} {2 5} \
	{2 -1} {2 -2} {2 -3} {2 -4} {2 -5} \
	{3 1} {3 2} {3 3} {3 4} {3 5} \
	{3 -1} {3 -2} {3 -3} {3 -4} {3 -5} \
	]
    set results [list]
    foreach pair $mod_nums {
        set dividend [lindex $pair 0]
        set divisor [lindex $pair 1]
        lappend results [expr {$dividend % $divisor}]
	set dividend [lindex $pair 0]
	set divisor [lindex $pair 1]
	lappend results [expr {$dividend % $divisor}]
    }
    set results
} [list \
    0 1 0 1 2 \
    0 -1 0 -3 -3 \
    0 0 1 2 3 \
    0 0 -2 -2 -2 \
    0 1 2 3 4 \
    0 -1 -1 -1 -1 \
    0 0 0 0 \
    0 1 1 1 1 \
    0 -1 -2 -3 -4 \
    0 0 2 2 2 \
    0 0 -1 -2 -3 \
    0 1 0 3 3 \
    0 -1 0 -1 -2 \
    ]

test expr-32.2 {expr div basics} {
    set mod_nums [list \
        {-3 1} {-3 2} {-3 3} {-3 4} {-3 5} \
        {-3 -1} {-3 -2} {-3 -3} {-3 -4} {-3 -5} \
        {-2 1} {-2 2} {-2 3} {-2 4} {-2 5} \
        {-2 -1} {-2 -2} {-2 -3} {-2 -4} {-2 -5} \
        {-1 1} {-1 2} {-1 3} {-1 4} {-1 5} \
        {-1 -1} {-1 -2} {-1 -3} {-1 -4} {-1 -5} \
        {0 -100} {0 -1} {0 1} {0 100} \
        {1 1} {1 2} {1 3} {1 4} {1 5} \
        {1 -1} {1 -2} {1 -3} {1 -4} {1 -5} \
        {2 1} {2 2} {2 3} {2 4} {2 5} \
        {2 -1} {2 -2} {2 -3} {2 -4} {2 -5} \
        {3 1} {3 2} {3 3} {3 4} {3 5} \
        {3 -1} {3 -2} {3 -3} {3 -4} {3 -5} \
        ]
	{-3 1} {-3 2} {-3 3} {-3 4} {-3 5} \
	{-3 -1} {-3 -2} {-3 -3} {-3 -4} {-3 -5} \
	{-2 1} {-2 2} {-2 3} {-2 4} {-2 5} \
	{-2 -1} {-2 -2} {-2 -3} {-2 -4} {-2 -5} \
	{-1 1} {-1 2} {-1 3} {-1 4} {-1 5} \
	{-1 -1} {-1 -2} {-1 -3} {-1 -4} {-1 -5} \
	{0 -100} {0 -1} {0 1} {0 100} \
	{1 1} {1 2} {1 3} {1 4} {1 5} \
	{1 -1} {1 -2} {1 -3} {1 -4} {1 -5} \
	{2 1} {2 2} {2 3} {2 4} {2 5} \
	{2 -1} {2 -2} {2 -3} {2 -4} {2 -5} \
	{3 1} {3 2} {3 3} {3 4} {3 5} \
	{3 -1} {3 -2} {3 -3} {3 -4} {3 -5} \
	]
    set results [list]
    foreach pair $mod_nums {
        set dividend [lindex $pair 0]
        set divisor [lindex $pair 1]
        lappend results [expr {$dividend / $divisor}]
	set dividend [lindex $pair 0]
	set divisor [lindex $pair 1]
	lappend results [expr {$dividend / $divisor}]
    }
    set results
} [list \
    -3 -2 -1 -1 -1 \
    3 1 1 0 0 \
    -2 -1 -1 -1 -1 \
    2 1 0 0 0 \
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841






5842
5843
5844

5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861






5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878






5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898






5899
5900
5901
5902
5903
5904
5905
5839
5840
5841
5842
5843
5844
5845






5846
5847
5848
5849
5850
5851
5852
5853

5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865






5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882






5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902






5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915







-
-
-
-
-
-
+
+
+
+
+
+


-
+











-
-
-
-
-
-
+
+
+
+
+
+











-
-
-
-
-
-
+
+
+
+
+
+














-
-
-
-
-
-
+
+
+
+
+
+







    set max_long_hex "0x7FFFFFFF "

    # Convert to integer (long, not wide) internal rep
    set max_long 2147483647
    string is integer $max_long

    list \
        [expr {" $max_long_str "}] \
        [expr {$max_long_str + 0}] \
        [expr {$max_long + 0}] \
        [expr {2147483647 + 0}] \
        [expr {$max_long == $max_long_hex}] \
        [expr {int(2147483647 + 1) > 0}] \
	[expr {" $max_long_str "}] \
	[expr {$max_long_str + 0}] \
	[expr {$max_long + 0}] \
	[expr {2147483647 + 0}] \
	[expr {$max_long == $max_long_hex}] \
	[expr {int(2147483647 + 1) > 0}] \

} {2147483647 2147483647 2147483647 2147483647 1 1}
test expr-33.2 {parse smallest long value} longIs32bit {
test expr-33.2 {parse smallest long value} {
    set min_long_str -2147483648
    set min_long_hex "-0x80000000 "

    set min_long -2147483648
    # This will convert to integer (not wide) internal rep
    string is integer $min_long

    # Note: If the final expression returns 0 then the
    # expression literal is being promoted to a wide type
    # when it should be parsed as a long type.
    list \
        [expr {" $min_long_str "}] \
        [expr {$min_long_str + 0}] \
        [expr {$min_long + 0}] \
        [expr {-2147483648 + 0}] \
        [expr {$min_long == $min_long_hex}] \
        [expr {int(-2147483648 - 1) == -0x80000001}] \
	[expr {" $min_long_str "}] \
	[expr {$min_long_str + 0}] \
	[expr {$min_long + 0}] \
	[expr {-2147483648 + 0}] \
	[expr {$min_long == $min_long_hex}] \
	[expr {int(-2147483648 - 1) == -0x80000001}] \

} {-2147483648 -2147483648 -2147483648 -2147483648 1 1}
test expr-33.3 {parse largest wide value} wideIs64bit {
    set max_wide_str 9223372036854775807
    set max_wide_hex "0x7FFFFFFFFFFFFFFF "

    # Convert to wide integer
    set max_wide 9223372036854775807
    string is integer $max_wide

    list \
        [expr {" $max_wide_str "}] \
        [expr {$max_wide_str + 0}] \
        [expr {$max_wide + 0}] \
        [expr {9223372036854775807 + 0}] \
        [expr {$max_wide == $max_wide_hex}] \
        [expr {wide(9223372036854775807 + 1) < 0}] \
	[expr {" $max_wide_str "}] \
	[expr {$max_wide_str + 0}] \
	[expr {$max_wide + 0}] \
	[expr {9223372036854775807 + 0}] \
	[expr {$max_wide == $max_wide_hex}] \
	[expr {wide(9223372036854775807 + 1) < 0}] \

} {9223372036854775807 9223372036854775807 9223372036854775807 9223372036854775807 1 1}
test expr-33.4 {parse smallest wide value} wideIs64bit {
    set min_wide_str -9223372036854775808
    set min_wide_hex "-0x8000000000000000 "

    set min_wide -9223372036854775808
    # Convert to wide integer
    string is integer $min_wide

    # Note: If the final expression returns 0 then the
    # wide integer is not being parsed correctly with
    # the leading - sign.
    list \
        [expr {" $min_wide_str "}] \
        [expr {$min_wide_str + 0}] \
        [expr {$min_wide + 0}] \
        [expr {-9223372036854775808 + 0}] \
        [expr {$min_wide == $min_wide_hex}] \
        [expr {wide(-9223372036854775808 - 1) == 0x7FFFFFFFFFFFFFFF}] \
	[expr {" $min_wide_str "}] \
	[expr {$min_wide_str + 0}] \
	[expr {$min_wide + 0}] \
	[expr {-9223372036854775808 + 0}] \
	[expr {$min_wide == $min_wide_hex}] \
	[expr {wide(-9223372036854775808 - 1) == 0x7FFFFFFFFFFFFFFF}] \

} {-9223372036854775808 -9223372036854775808 -9223372036854775808 -9223372036854775808 1 1}

set min -2147483648
set max 2147483647

test expr-34.1 {expr edge cases} {
6694
6695
6696
6697
6698
6699
6700






6701
6702
6703
6704
6705
6706
6707
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723







+
+
+
+
+
+







} { 	0x0}
test expr-38.12 {abs and -0x0 [Bug 2954959]} {
    ::tcl::mathfunc::abs { 	-0x0}
} 0
test expr-38.13 {abs and 0.0 [Bug 2954959]} {
    ::tcl::mathfunc::abs 1e-324
} 1e-324
test expr-38.14 {abs and INT64_MIN special-case} {
    ::tcl::mathfunc::abs -9223372036854775808
} 9223372036854775808
test expr-38.15 {abs and INT128_MIN special-case} {
    ::tcl::mathfunc::abs -170141183460469231731687303715884105728
} 170141183460469231731687303715884105728

testConstraint testexprlongobj   [llength [info commands testexprlongobj]]
testConstraint testexprdoubleobj [llength [info commands testexprdoubleobj]]

test expr-39.1 {Check that Tcl_ExprLongObj doesn't modify interpreter result if no error} testexprlongobj {
    testexprlongobj 4+1
} {This is a result: 5}
7216
7217
7218
7219
7220
7221
7222









7223
7224
7225
7226
7227
7228
7229
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254







+
+
+
+
+
+
+
+
+







	if {$k != (1<<28)+1} {
	    append trouble "i = $i, k = $k\n"
	    incr faults
	}
    }
    set trouble
} {}
test expr-47.14 {isqrt() - lseq} {
    list [catch {expr {isqrt([lseq 1 3])}} result] $result
} {1 {expected number but got a list}}
test expr-47.15 {isqrt() - lseq} {
    list [catch {expr {isqrt({1 2 "})}} result] $result
} {1 {expected number but got "1 2 ""}}
test expr-47.16 {isqrt() - lseq} {
    list [catch {expr {isqrt([dict create foo bar])}} result] $result
} {1 {expected number but got a list}}

test expr-48.1 {Bug 1770224} {
    expr {-0x8000000000000001 >> 0x8000000000000000}
} -1

test expr-49.1 {Bug 2823282} {
    coroutine foo apply {{} {set expr expr; $expr {[yield]}}}
7379
7380
7381
7382
7383
7384
7385
7386






































































































7387
7388
7389
7390

7391
7392
7393
7394
7395
7396
7404
7405
7406
7407
7408
7409
7410

7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468
7469
7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499
7500
7501
7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520
7521
7522
7523







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+






    foreach v2 $values r2 $results {
	test expr-61.[incr ctr] "float classification: isunordered($v1,$v2)" {
	    expr {isunordered($v1, $v2)}
	} [expr {$r1 || $r2}]
    }
}
unset -nocomplain values results ctr


test expr-62.1 {TIP 582: comments} -body {
    expr {1 # + 2}
} -result 1
test expr-62.2 {TIP 582: comments} -body {
    expr "1 #\n+ 2"
} -result 3
test expr-62.3 {TIP 582: comments} -setup {
    set ctr 0
} -body {
    expr {
	# This is a demonstration of a comment
	1 + 2 + 3
	# and another comment
	+ 4 + 5
	# + [incr ctr]
	+ [incr ctr]
    }
} -result 16
# Buggy because line breaks aren't tracked inside expressions at all
test expr-62.4 {TIP 582: comments don't hide line breaks} -setup {
    proc getline {} {
	dict get [info frame -1] line
    }
    set base [getline]
} -constraints knownBug -body {
    expr {
	0
	# a comment
	+ [getline] - $base
    }
} -cleanup {
    rename getline ""
} -result 5
test expr-62.5 {TIP 582: comments don't splice tokens} {
    set a False
    expr {$a#don't splice
ne#don't splice
false}
} 1
test expr-62.6 {TIP 582: comments don't splice tokens} {
    expr {0x2#don't splice
ne#don't splice
2}
} 1
test expr-62.7 {TIP 582: comments can go inside function calls} {
    expr {max(1,# comment
	      2)}
} 2
test expr-62.8 {TIP 582: comments can go inside function calls} {
    expr {max(1# comment
	      ,2)}
} 2
test expr-62.9 {TIP 582: comments can go inside function calls} {
    expr {max(# comment
	      1,2)}
} 2
test expr-62.10 {TIP 582: comments can go inside function calls} {
    expr {max# comment
	     (1,2)}
} 2

# Bug e3dcab1d14 TODO: Need to work out a test case that fails
# without tcl_precision, which has been eliminated in 9.0

# proc do-one-test-expr-63 {e p float athreshold} {
#     # e - power of 2 to test
#     # p - tcl_precision to test wuth
#     # float - floating point value 2**-$p
#     # athreshold - tolerable absolute error (1/2 decimal digit in
#     #              least significant place plus 1/2 least significant bit)
#     set trouble {}
#     set ::tcl_precision $p
#     set xfmt x[expr $float]
#     set ::tcl_precision 0
#     set fmt [string range $xfmt 1 end]
#     set aerror [expr {abs($fmt - $float)}]
#     if {$aerror > $athreshold} {
#         return "Result $fmt is more than $athreshold away from $float"
#     } else {
#         return {}
#     }
# }

# proc run-test-expr-63 {} {
#     for {set e 0} {$e <= 1023} {incr e} {
#         set pt [expr {floor($e*log(2)/log(10))}]
#         for {set p 6} {$p <= 17} {incr p} {
#             set athreshold [expr {0.5*10.0**-($pt+$p) + 2.0**-($e+53)}]
#             set numer [expr {5**$e}]
#             set xfloat x[expr {2.**-$e}]
#             set float [string range $xfloat 1 end]
#             test expr-63.$p.$e "convert 2**-$e to decimal at precision $p" {
#                 do-one-test-expr-63 $e $p $float $athreshold
#             } {}
#         }
#     }
#     rename do-one-test-expr-63 {}
#     rename run-test-expr-63 {}
# }
# run-test-expr-63

# cleanup
unset -nocomplain a
unset -nocomplain min
unset -nocomplain max

::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/fCmd.test.

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
30
31

32
33
34
35
36
37
38
39
40
41


42
43
44





45
46
47
48
49
50
51
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

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






-
-
+
+










-
+





-
+
-




-
+










+
+


-
+
+
+
+
+







# This file tests the tclFCmd.c file.
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright (c) 1999 by Scriptics Corporation.
# Copyright © 1996-1997 Sun Microsystems, Inc.
# Copyright © 1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

cd [temporaryDirectory]

testConstraint testsetplatform [llength [info commands testsetplatform]]
testConstraint testchmod [llength [info commands testchmod]]
testConstraint winVista 0
testConstraint winLessThan10 0
testConstraint winXP 0
# Don't know how to determine this constraint correctly
testConstraint notNetworkFilesystem 0
testConstraint reg 0
if {[testConstraint win]} {
    catch {
    if {[catch {
	# Is the registry extension already static to this shell?
	try {
	    load {} Registry
	    set ::reglib {}
	} on error {} {
	    # try the location given to use on the commandline to tcltest
	    ::tcltest::loadTestedCommands
	    load $::reglib Registry
	}
	testConstraint reg 1
    } regError]} {
	catch {package require registry; testConstraint reg 1}
    }
}
testConstraint notWine [expr {$::tcl_platform(platform) ne "windows" || ![info exists ::env(TRAVIS_OS_NAME)] || ![string match linux $::env(TRAVIS_OS_NAME)]}]

testConstraint notInCIenv [expr {![info exists ::env(CI)] || !$::env(CI)}]

# File permissions broken on wsl without some "exotic" wsl configuration
testConstraint notWsl [expr {[llength [array names ::env *WSL*]] == 0}]

set tmpspace /tmp;# default value
# Find a group that exists on this Unix system, or else skip tests that
# require Unix groups.
testConstraint foundGroup [expr {![testConstraint unix]}]
if {[testConstraint unix]} {
    catch {
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
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







-
+
-
-
+
-
-
-








+





+

-
+














+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








    if {[catch {makeDirectory tcl[pid] /tmp} tmpspace] == 0} {
	testConstraint xdev [expr {([dev .] != [dev $tmpspace])}]
    }
}

# Also used in winFCmd...
if {[testConstraint win]} {
if {[testConstraint win] && $::tcl_platform(osVersion) < 10.0} {
    if {$::tcl_platform(osVersion) >= 5.0} {
	testConstraint winVista 1
    testConstraint winLessThan10 1
    } else {
	testConstraint winXP 1
    }
}

testConstraint darwin9 [expr {
    [testConstraint unix]
    && $tcl_platform(os) eq "Darwin"
    && [package vsatisfies 1.$::tcl_platform(osVersion) 1.9]
}]
testConstraint notDarwin9 [expr {![testConstraint darwin9]}]
testConstraint notContinuousIntegration [expr {![info exists ::env(CI)]}]

testConstraint fileSharing 0
testConstraint notFileSharing 1
testConstraint linkFile 1
testConstraint linkDirectory 1
testConstraint testfstildeexpand [llength [info commands testfstildeexpand]]

# Several tests require need to match results against the unix username
# Several tests require need to match results against the Unix username
set user {}
if {[testConstraint unix]} {
    catch {
	set user [exec whoami]
    }
    if {$user eq ""} {
	catch {
	    regexp {^[^(]*\(([^)]*)\)} [exec id] -> user
	}
    }
    if {$user eq ""} {
	set user "root"
    }
}
if {[testConstraint win]} {
    catch {
	set user $::env(USERNAME)
    }
    if {$user eq ""} {
	set user Administrator
    }
}

# Try getting a lower case glob pattern that will match the home directory of
# a given user to test ~user and [file tildeexpand ~user]. Note this may not
# be the same as ~ even when "user" is current user. For example, on Unix
# platforms ~ will return HOME envvar, but ~user will lookup password file
# bypassing HOME. If home directory not found, returns *$user* so caller can
# succeed by using glob matching under the hope that the path contains
# the user name.
proc gethomedirglob {user} {
    if {[testConstraint unix]} {
	if {![catch {
	    exec {*}[auto_execok sh] -c "echo ~$user"
	} home]} {
	    set home [string trim $home]
	    if {$home ne ""} {
		# Expect exact match (except case), no glob * added
		return [string tolower $home]
	    }
	}
    } elseif {[testConstraint reg]} {
	# Windows with registry extension loaded
	if {![catch {
	    set sid [exec {*}[auto_execok powershell] -Command "(Get-LocalUser -Name '$user')\[0\].sid.Value"]
	    set sid [string trim $sid]
	    # Get path from the Windows registry
	    set home [registry get "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\$sid" ProfileImagePath]
	    set home [string trim [string tolower $home]]
	} result]} {
	    if {$home ne ""} {
		# file join for \ -> /
		return [file join [string tolower $home]]
	    }
	}
    }

    # Caller will need to use glob matching and hope user
    # name is in the home directory path
    return *[string tolower $user]*
}

proc createfile {file {string a}} {
    set f [open $file w]
    puts -nonewline $f $string
    close $f
    return $string
}
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
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







+
+
+
+















-
+


+
+
+
+







    } on error {} {
	return 0
    }
    return [string match $matchString $fileString]
}

proc openup {path} {
    # Double check for inadvertent ~ -> home directory mapping
    if {[string match ~* $path]} {
	set file ./$path
    }
    testchmod 0o777 $path
    if {[file isdirectory $path]} {
	catch {
	    foreach p [glob -directory $path *] {
		openup $p
	    }
	}
    }
}

proc cleanup {args} {
    set wd [list .]
    foreach p [concat $wd $args] {
	set x ""
	catch {
	    set x [glob -directory $p tf* td*]
	    set x [glob -directory $p tf* td* ~*]
	}
	foreach file $x {
	    # Double check for inadvertent ~ -> home directory mapping
	    if {[string match ~* $file]} {
		set file ./$file
	    }
	    if {
		[catch {file delete -force -- $file}]
		&& [testConstraint testchmod]
	    } then {
		catch {openup $file}
		catch {file delete -force -- $file}
	    }
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+







test fCmd-1.1 {TclFileRenameCmd} -constraints {notRoot} -setup {
    cleanup
} -body {
    createfile tf1
    file rename tf1 tf2
    glob tf*
} -result {tf2}
test fCmd-1.2 {TclFileRenameCmd when target is ~} -setup {
    cleanup
    createfile tf1
} -cleanup {
    file delete ./~
} -body {
    file rename tf1 ~
    file isfile ~
} -result 1
test fCmd-1.3 {TclFileRenameCmd when target is ~user} -setup {
    cleanup
    createfile tf1
} -cleanup {
    file delete ./~$user
} -body {
    file rename tf1 ~$user
    file isfile ~$user
} -result 1
test fCmd-1.4 {TclFileRenameCmd when source is ~} -setup {
    cleanup
    createfile ./~
} -cleanup {
    file delete ./~
} -body {
    file rename ~ tf1
    list [file exists ~] [file exists tf1]
} -result {0 1}
test fCmd-1.5 {TclFileRenameCmd when source is ~user} -setup {
    cleanup
    createfile ./~$user
} -cleanup {
    file delete ./~$user
} -body {
    file rename ~$user tf1
    list [file exists ~$user] [file exists tf1]
} -result {0 1}


test fCmd-2.1 {TclFileCopyCmd} -constraints {notRoot} -setup {
    cleanup
} -body {
    createfile tf1
    file copy tf1 tf2
    lsort [glob tf*]
} -result {tf1 tf2}
test fCmd-2.2 {TclFileCopyCmd when target is ~} -setup {
    cleanup
    createfile tf1
} -cleanup {
    file delete ./~
} -body {
    file copy tf1 ~
    list [file exists tf1] [file exists ~]
} -result {1 1}
test fCmd-2.3 {TclFileCopyCmd when target is ~user} -setup {
    cleanup
    createfile tf1
} -cleanup {
    file delete ./~$user
} -body {
    file copy tf1 ~$user
    list [file exists tf1] [file exists ~$user]
} -result {1 1}
test fCmd-2.4 {TclFileCopyCmd when source is ~} -setup {
    cleanup
    createfile ./~
} -cleanup {
    file delete ./~
} -body {
    file copy ~ tf1
    list [file exists ~] [file exists tf1]
} -result {1 1}
test fCmd-2.5 {TclFileCopyCmd when source is ~user} -setup {
    cleanup
    createfile ./~$user
} -cleanup {
    file delete ./~$user
} -body {
    file copy ~$user tf1
    list [file exists ~$user] [file exists tf1]
} -result {1 1}

test fCmd-3.1 {FileCopyRename: FileForceOption fails} -constraints {notRoot} -body {
    file rename -xyz
} -returnCodes error -result {bad option "-xyz": must be -force or --}
test fCmd-3.2 {FileCopyRename: not enough args} -constraints {notRoot} -body {
    file rename xyz
} -returnCodes error -result {wrong # args: should be "file rename ?-option value ...? source ?source ...? target"}
test fCmd-3.3 {FileCopyRename: Tcl_TranslateFileName fails} -constraints {notRoot} -body {
    file rename xyz ~_totally_bogus_user
} -returnCodes error -result {user "_totally_bogus_user" doesn't exist}
} -returnCodes error -result {error renaming "xyz": no such file or directory}
test fCmd-3.4 {FileCopyRename: Tcl_TranslateFileName passes} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file copy tf1 ~
} -result {error copying "tf1": no such file or directory}
test fCmd-3.5 {FileCopyRename: target doesn't exist: stat(target) != 0} -setup {
    cleanup
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
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
442
443
444
445

446
447

448
449
450
451
452
453
454
455


456
457
458
459
460
461
462
463
464







-
-
+
+




-
+










-
+




















-
+

-
+
+
+
+
+
+

+
-
-
+
+







	[contents [file join td1 tf3]] [contents [file join td1 tf4]]
} -result {tf1 tf2 tf3 tf4}
test fCmd-3.14 {FileCopyRename: FileBasename fails} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file mkdir td1
    file rename ~_totally_bogus_user td1
} -result {user "_totally_bogus_user" doesn't exist}
test fCmd-3.15 {FileCopyRename: source[0] == '\0'} -setup {
} -result {error renaming "~_totally_bogus_user": no such file or directory}
test fCmd-3.15 {FileCopyRename: source[0] == '\x00'} -setup {
    cleanup
} -constraints {notRoot unixOrWin} -returnCodes error -body {
    file mkdir td1
    file rename / td1
} -result {error renaming "/" to "td1": file already exists}
} -result {error renaming "/" to "td1": file exists}
test fCmd-3.16 {FileCopyRename: break on first error} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    createfile tf1
    createfile tf2
    createfile tf3
    createfile tf4
    file mkdir td1
    createfile [file join td1 tf3]
    file rename tf1 tf2 tf3 tf4 td1
} -result [subst {error renaming "tf3" to "[file join td1 tf3]": file already exists}]
} -result [subst {error renaming "tf3" to "[file join td1 tf3]": file exists}]

test fCmd-4.1 {TclFileMakeDirsCmd: make each dir: 1 dir} -setup {
    cleanup
} -constraints {notRoot} -body {
    file mkdir td1
    glob td*
} -result {td1}
test fCmd-4.2 {TclFileMakeDirsCmd: make each dir: multiple dirs} -setup {
    cleanup
} -constraints {notRoot} -body {
    file mkdir td1 td2 td3
    lsort [glob td*]
} -result {td1 td2 td3}
test fCmd-4.3 {TclFileMakeDirsCmd: stops on first error} -setup {
    cleanup
} -constraints {notRoot} -body {
    createfile tf1
    catch {file mkdir td1 td2 tf1 td3 td4}
    glob td1 td2 tf1 td3 td4
} -result {td1 td2 tf1}
test fCmd-4.4 {TclFileMakeDirsCmd: Tcl_TranslateFileName fails} -setup {
test fCmd-4.4 {TclFileMakeDirsCmd: Tcl_TranslateFileName treats ~ as normal char} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
} -constraints {notRoot} -body {
    list [file isdir ~] [file mkdir ~] [file isdir ~]
} -result {0 {} 1}
test fCmd-4.4.1 {TclFileMakeDirsCmd: Tcl_TranslateFileName treats ~ as normal char} -setup {
    cleanup
} -constraints {notRoot} -body {
    file mkdir ~_totally_bogus_user
    file isdir ~_totally_bogus_user
} -result {user "_totally_bogus_user" doesn't exist}
test fCmd-4.5 {TclFileMakeDirsCmd: Tcl_SplitPath returns 0: *name == '\0'} -setup {
} -result 1
test fCmd-4.5 {TclFileMakeDirsCmd: Tcl_SplitPath returns 0: *name == '\x00'} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file mkdir ""
} -result {can't create directory "": no such file or directory}
test fCmd-4.6 {TclFileMakeDirsCmd: one level deep} -setup {
    cleanup
} -constraints {notRoot} -body {
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
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







-
+










-
+

















-
+

-
+









-
+







    list $x [file exists td1]
} -result {1 1}
test fCmd-4.9 {TclFileMakeDirsCmd: exists, not dir} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    createfile tf1
    file mkdir tf1
} -result [subst {can't create directory "[file join tf1]": file already exists}]
} -result [subst {can't create directory "[file join tf1]": file exists}]
test fCmd-4.10 {TclFileMakeDirsCmd: exists, is dir} -setup {
    cleanup
} -constraints {notRoot} -body {
    file mkdir td1
    set x [file exists td1]
    file mkdir td1
    list $x [file exists td1]
} -result {1 1}
test fCmd-4.11 {TclFileMakeDirsCmd: doesn't exist: errno != ENOENT} -setup {
    cleanup
} -constraints {unix notRoot testchmod} -returnCodes error -body {
} -constraints {unix notRoot testchmod notWsl} -returnCodes error -body {
    file mkdir td1/td2/td3
    testchmod 0 td1/td2
    file mkdir td1/td2/td3/td4
} -cleanup {
    testchmod 0o755 td1/td2
    cleanup
} -result {can't create directory "td1/td2/td3": permission denied}
test fCmd-4.13 {TclFileMakeDirsCmd: doesn't exist: errno == ENOENT} -setup {
    cleanup
} -constraints {notRoot} -body {
    set x [file exists td1]
    file mkdir td1
    list $x [file exists td1]
} -result {0 1}
test fCmd-4.14 {TclFileMakeDirsCmd: TclpCreateDirectory fails} -setup {
    cleanup
    file delete -force foo
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
    file mkdir foo
    file attr foo -perm 040000
    file attr foo -perm 0o40000
    file mkdir foo/tf1
} -returnCodes error -cleanup {
    file delete -force foo
} -result {can't create directory "foo/tf1": permission denied}
test fCmd-4.16 {TclFileMakeDirsCmd: TclpCreateDirectory succeeds} -setup {
    cleanup
} -constraints {notRoot} -body {
    file mkdir tf1
    file exists tf1
} -result {1}
} -result 1

test fCmd-5.1 {TclFileDeleteCmd: FileForceOption fails} -constraints {notRoot} -body {
    file delete -xyz
} -returnCodes error -result {bad option "-xyz": must be -force or --}
test fCmd-5.2 {TclFileDeleteCmd: accept 0 files (TIP 323)} -body {
    file delete -force -force
} -result {}
420
421
422
423
424
425
426


427

428
429
430



431
432
433
434
435

436
437
438
439
440
441
442
557
558
559
560
561
562
563
564
565

566
567


568
569
570

571
572


573
574
575
576
577
578
579
580







+
+
-
+

-
-
+
+
+
-


-
-
+







} -constraints {notRoot unixOrWin notWine} -body {
    createfile tf1
    createfile tf2
    file mkdir td1
    catch {file delete tf1 td1 $root tf2}
    list [file exists tf1] [file exists tf2] [file exists td1]
} -cleanup {cleanup} -result {0 1 0}
test fCmd-5.6 {
    TclFileDeleteCmd: Tcl_TranslateFileName treats ~user as normal char
test fCmd-5.6 {TclFileDeleteCmd: Tcl_TranslateFileName fails} -constraints {notRoot} -body {
} -constraints {notRoot} -body {
    file delete ~_totally_bogus_user
} -returnCodes error -result {user "_totally_bogus_user" doesn't exist}
test fCmd-5.7 {TclFileDeleteCmd: Tcl_TranslateFileName succeeds} -setup {
} -result {}
test fCmd-5.7 {
    TclFileDeleteCmd: Tcl_TranslateFileName treats ~ as normal char
    catch {file delete ~/tf1}
} -constraints {notRoot} -body {
    createfile ~/tf1
    file delete ~/tf1
} -result {}
} -returnCodes error -result {couldn't open "~/tf1": no such file or directory}
test fCmd-5.8 {TclFileDeleteCmd: file doesn't exist: lstat(name) != 0} -setup {
    cleanup
} -constraints {notRoot} -body {
    set x [file exists tf1]
    file delete tf1
    list $x [file exists tf1]
} -result {0 0}
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
635
636
637
638
639
640
641

642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662

663
664
665
666
667
668
669

670
671
672
673
674
675
676
677







-
+




















-
+






-
+







} -constraints {notRoot} -body {
    createfile tf1
    file rename tf1 tf2
    glob tf*
} -result {tf2}
test fCmd-6.6 {CopyRenameOneFile: errno != ENOENT} -setup {
    cleanup
} -constraints {unix notRoot testchmod} -body {
} -constraints {unix notRoot testchmod notWsl} -body {
    file mkdir td1
    testchmod 0 td1
    createfile tf1
    file rename tf1 td1
} -returnCodes error -cleanup {
    testchmod 0o755 td1
} -result {error renaming "tf1" to "td1/tf1": permission denied}
test fCmd-6.9 {CopyRenameOneFile: errno == ENOENT} -setup {
    cleanup
} -constraints {unix notRoot} -body {
    createfile tf1
    file rename tf1 tf2
    glob tf*
} -result {tf2}
test fCmd-6.10 {CopyRenameOneFile: lstat(target) == 0} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    createfile tf1
    createfile tf2
    file rename tf1 tf2
} -result {error renaming "tf1" to "tf2": file already exists}
} -result {error renaming "tf1" to "tf2": file exists}
test fCmd-6.11 {CopyRenameOneFile: force == 0} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    createfile tf1
    createfile tf2
    file rename tf1 tf2
} -result {error renaming "tf1" to "tf2": file already exists}
} -result {error renaming "tf1" to "tf2": file exists}
test fCmd-6.12 {CopyRenameOneFile: force != 0} -setup {
    cleanup
} -constraints {notRoot} -body {
    createfile tf1
    createfile tf2
    file rename -force tf1 tf2
    glob tf*
616
617
618
619
620
621
622
623

624
625

626
627
628

629
630
631
632
633
634
635
636
637




638
639
640
641



642
643
644
645
646
647
648
649




650
651
652
653



654
655
656
657
658
659
660




661
662
663
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
754
755
756
757
758
759
760

761
762

763
764
765

766
767
768
769
770
771




772
773
774
775
776



777
778
779
780
781
782
783




784
785
786
787
788



789
790
791
792
793
794




795
796
797
798
799



800
801
802
803
804
805
806
807
808
809

810
811
812

813
814

815
816
817

818
819
820
821
822
823
824
825
826
827
828
829

830
831

832
833
834
835

836
837
838
839
840
841
842
843







-
+

-
+


-
+





-
-
-
-
+
+
+
+

-
-
-
+
+
+




-
-
-
-
+
+
+
+

-
-
-
+
+
+



-
-
-
-
+
+
+
+

-
-
-
+
+
+







-
+


-
+

-
+


-
+











-
+

-
+



-
+







} -constraints {unix notRoot} -body {
    createfile tf1
    file rename tf1 $tmpspace
    glob -nocomplain tf* [file join $tmpspace tf*]
} -result [file join $tmpspace tf1]
test fCmd-6.23 {CopyRenameOneFile: TclpCopyDirectory failed} -setup {
    cleanup $tmpspace
} -constraints {xdev notRoot} -body {
} -constraints {xdev notRoot notWsl} -body {
    file mkdir td1/td2/td3
    file attributes td1 -permissions 0000
    file attributes td1 -permissions 0
    file rename td1 $tmpspace
} -returnCodes error -cleanup {
    file attributes td1 -permissions 0755
    file attributes td1 -permissions 0o755
    cleanup
} -match regexp -result {^error renaming "td1"( to "/tmp/tcl\d+/td1")?: permission denied$}
test fCmd-6.24 {CopyRenameOneFile: error uses original name} -setup {
    cleanup
} -constraints {unix notRoot} -body {
    file mkdir ~/td1/td2
    set td1name [file join [file dirname ~] [file tail ~] td1]
    file attributes $td1name -permissions 0000
    file copy ~/td1 td1
    file mkdir [file home]/td1/td2
    set td1name [file join [file dirname [file home]] [file tail [file home]] td1]
    file attributes $td1name -permissions 0
    file copy [file home]/td1 td1
} -returnCodes error -cleanup {
    file attributes $td1name -permissions 0755
    file delete -force ~/td1
} -result {error copying "~/td1": permission denied}
    file attributes $td1name -permissions 0o755
    file delete -force [file home]/td1
} -result "error copying \"[file home]/td1\": permission denied"
test fCmd-6.25 {CopyRenameOneFile: error uses original name} -setup {
    cleanup
} -constraints {unix notRoot} -body {
    file mkdir td2
    file mkdir ~/td1
    set td1name [file join [file dirname ~] [file tail ~] td1]
    file attributes $td1name -permissions 0000
    file copy td2 ~/td1
    file mkdir [file home]/td1
    set td1name [file join [file dirname [file home]] [file tail [file home]] td1]
    file attributes $td1name -permissions 0
    file copy td2 [file home]/td1
} -returnCodes error -cleanup {
    file attributes $td1name -permissions 0755
    file delete -force ~/td1
} -result {error copying "td2" to "~/td1/td2": permission denied}
    file attributes $td1name -permissions 0o755
    file delete -force [file home]/td1
} -result "error copying \"td2\" to \"[file home]/td1/td2\": permission denied"
test fCmd-6.26 {CopyRenameOneFile: doesn't use original name} -setup {
    cleanup
} -constraints {unix notRoot} -body {
    file mkdir ~/td1/td2
    set td2name [file join [file dirname ~] [file tail ~] td1 td2]
    file attributes $td2name -permissions 0000
    file copy ~/td1 td1
    file mkdir [file home]/td1/td2
    set td2name [file join [file dirname [file home]] [file tail [file home]] td1 td2]
    file attributes $td2name -permissions 0
    file copy [file home]/td1 td1
} -returnCodes error -cleanup {
    file attributes $td2name -permissions 0755
    file delete -force ~/td1
} -result "error copying \"~/td1\" to \"td1\": \"[file join $::env(HOME) td1 td2]\": permission denied"
    file attributes $td2name -permissions 0o755
    file delete -force [file home]/td1
} -result "error copying \"[file home]/td1\" to \"td1\": \"[file join $::env(HOME) td1 td2]\": permission denied"
test fCmd-6.27 {CopyRenameOneFile: TclpCopyDirectory failed} -setup {
    cleanup $tmpspace
} -constraints {notRoot xdev} -returnCodes error -body {
    file mkdir td1/td2/td3
    file mkdir [file join $tmpspace td1]
    createfile [file join $tmpspace td1 tf1]
    file rename -force td1 $tmpspace
} -match glob -result {error renaming "td1" to "/tmp/tcl*/td1": file already exists}
} -match glob -result {error renaming "td1" to "/tmp/tcl*/td1": file exists}
test fCmd-6.28 {CopyRenameOneFile: TclpCopyDirectory failed} -setup {
    cleanup $tmpspace
} -constraints {notRoot xdev} -body {
} -constraints {notRoot xdev notWsl} -body {
    file mkdir td1/td2/td3
    file attributes td1/td2/td3 -permissions 0000
    file attributes td1/td2/td3 -permissions 0
    file rename td1 $tmpspace
} -returnCodes error -cleanup {
    file attributes td1/td2/td3 -permissions 0755
    file attributes td1/td2/td3 -permissions 0o755
    cleanup $tmpspace
} -match glob -result {error renaming "td1" to "/tmp/tcl*/td1": "td1/td2/td3": permission denied}
test fCmd-6.29 {CopyRenameOneFile: TclpCopyDirectory passed} -setup {
    cleanup $tmpspace
} -constraints {notRoot xdev} -body {
    file mkdir td1/td2/td3
    file rename td1 $tmpspace
    glob td* [file join $tmpspace td1 t*]
} -result [file join $tmpspace td1 td2]
test fCmd-6.30 {CopyRenameOneFile: TclpRemoveDirectory failed} -setup {
    cleanup $tmpspace
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
    file mkdir foo/bar
    file attr foo -perm 040555
    file attr foo -perm 0o40555
    file rename foo/bar $tmpspace
} -returnCodes error -cleanup {
    catch {file delete [file join $tmpspace bar]}
    catch {file attr foo -perm 040777}
    catch {file attr foo -perm 0o40777}
    catch {file delete -force foo}
} -match glob -result {*: permission denied}
test fCmd-6.31 {CopyRenameOneFile: TclpDeleteFile passed} -setup {
    cleanup $tmpspace
} -constraints {notRoot xdev} -body {
    file mkdir [file join $tmpspace td1]
    createfile [file join $tmpspace td1 tf1]
733
734
735
736
737
738
739
740

741
742
743
744
745

746
747
748
749


750
751

752
753
754
755
756
757
758
759

760
761

762
763

764
765
766
767

768
769
770

771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791

792
793
794
795
796
797
798
799
800
801
802
803
804

805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823

824
825
826
827
828
829
830
831
832
833
834
835

836
837
838
839
840
841
842
871
872
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
898

899
900

901
902
903
904

905
906
907

908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928

929
930












931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949

950
951











952
953
954
955
956
957
958
959







-
+




-
+


-
-
+
+

-
+







-
+

-
+

-
+



-
+


-
+




















-
+

-
-
-
-
-
-
-
-
-
-
-
-
+


















-
+

-
-
-
-
-
-
-
-
-
-
-
+







} -body {
    file delete -tf1
} -returnCodes error -cleanup {
    file delete -- -tf1
} -result {bad option "-tf1": must be -force or --}
test fCmd-7.5 {FileForceOption: multiple times through loop} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
} -constraints {notRoot} -body {
    createfile --
    createfile -force
    file delete -force -force -- -- -force
    glob -- -- -force
} -result {no files matched glob patterns "-- -force"}
} -result {}

test fCmd-8.1 {FileBasename: basename of ~user: argc == 1 && *path == ~} \
    -constraints {unix notRoot knownBug} -body {
    # Labelled knownBug because it is dangerous [Bug: 3881]
    -constraints {unix notRoot knownBug tildeexpansion} -body {
    # Labeled knownBug because it is dangerous [Bug: 3881]
    file mkdir td1
    file attr td1 -perm 040000
    file attr td1 -perm 0o40000
    file rename ~$user td1
} -returnCodes error -cleanup {
    file delete -force td1
} -result "error renaming \"~$user\" to \"td1/[file tail ~$user]\": permission denied"
test fCmd-8.2 {FileBasename: basename of ~user: argc == 1 && *path == ~} \
	-constraints {unix notRoot} -body {
    string equal [file tail ~$user] ~$user
} -result 0
} -result 1
test fCmd-8.3 {file copy and path translation: ensure correct error} -body {
    file copy ~ [file join this file doesnt exist]
    file copy [file home] [file join this file doesnt exist]
} -returnCodes error -result [subst \
	{error copying "~" to "[file join this file doesnt exist]": no such file or directory}]
   {error copying "[file home]" to "[file join this file doesnt exist]": no such file or directory}]

test fCmd-9.1 {file rename: comprehensive: EACCES} -setup {
    cleanup
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
    file mkdir td1
    file mkdir td2
    file attr td2 -perm 040000
    file attr td2 -perm 0o40000
    file rename td1 td2/
} -returnCodes error -cleanup {
    file delete -force td2
    file delete -force td1
} -result {error renaming "td1" to "td2/td1": permission denied}
test fCmd-9.2 {file rename: comprehensive: source doesn't exist} -setup {
    cleanup
} -constraints {notRoot} -returnCodes error -body {
    file rename tf1 tf2
} -result {error renaming "tf1": no such file or directory}
test fCmd-9.3 {file rename: comprehensive: file to new name} -setup {
    cleanup
} -constraints {notRoot testchmod} -body {
    createfile tf1
    createfile tf2
    testchmod 0o444 tf2
    file rename tf1 tf3
    file rename tf2 tf4
    list [lsort [glob tf*]] [file writable tf3] [file writable tf4]
} -result {{tf3 tf4} 1 0}
test fCmd-9.4.a {file rename: comprehensive: dir to new name} -setup {
test fCmd-9.4 {file rename: comprehensive: dir to new name} -setup {
    cleanup
} -constraints {win winXP testchmod} -body {
    file mkdir td1 td2
    testchmod 0o555 td2
    file rename td1 td3
    file rename td2 td4
    list [lsort [glob td*]] [file writable td3] [file writable td4]
} -cleanup {
    cleanup
} -result {{td3 td4} 1 0}
test fCmd-9.4.b {file rename: comprehensive: dir to new name} -setup {
    cleanup
} -constraints {unix notRoot testchmod notDarwin9} -body {
} -constraints {unix notRoot testchmod notDarwin9 notWsl} -body {
    file mkdir td1 td2
    testchmod 0o555 td2
    file rename td1 td3
    file rename td2 td4
    list [lsort [glob td*]] [file writable td3] [file writable td4]
} -cleanup {
    cleanup
} -result {{td3 td4} 1 0}
test fCmd-9.5 {file rename: comprehensive: file to self} -setup {
    cleanup
} -constraints {notRoot testchmod notWine} -body {
    createfile tf1 tf1
    createfile tf2 tf2
    testchmod 0o444 tf2
    file rename -force tf1 tf1
    file rename -force tf2 tf2
    list [contents tf1] [contents tf2] [file writable tf1] [file writable tf2]
} -result {tf1 tf2 1 0}
test fCmd-9.6.a {file rename: comprehensive: dir to self} -setup {
test fCmd-9.6 {file rename: comprehensive: dir to self} -setup {
    cleanup
} -constraints {win winXP testchmod} -body {
    file mkdir td1
    file mkdir td2
    testchmod 0o555 td2
    file rename -force td1 .
    file rename -force td2 .
    list [lsort [glob td*]] [file writable td1] [file writable td2]
} -result {{td1 td2} 1 0}
test fCmd-9.6.b {file rename: comprehensive: dir to self} -setup {
    cleanup
} -constraints {unix notRoot testchmod} -body {
} -constraints {unix notRoot testchmod notWsl} -body {
    file mkdir td1
    file mkdir td2
    testchmod 0o555 td2
    file rename -force td1 .
    file rename -force td2 .
    list [lsort [glob td*]] [file writable td1] [file writable td2]
} -result {{td1 td2} 1 0}
859
860
861
862
863
864
865
866

867
868
869
870

871
872
873
874
875
876
877
976
977
978
979
980
981
982

983
984
985
986

987
988
989
990
991
992
993
994







-
+



-
+







    testchmod 0o444 tfd4
    set msg [list [catch {file rename tf1 tf2} msg] $msg]
    file rename -force tfs1 tfd1
    file rename -force tfs2 tfd2
    file rename -force tfs3 tfd3
    file rename -force tfs4 tfd4
    list [lsort [glob tf*]] $msg [file writable tfd1] [file writable tfd2] [file writable tfd3] [file writable tfd4]
} -result {{tf1 tf2 tfd1 tfd2 tfd3 tfd4} {1 {error renaming "tf1" to "tf2": file already exists}} 1 1 0 0}
} -result {{tf1 tf2 tfd1 tfd2 tfd3 tfd4} {1 {error renaming "tf1" to "tf2": file exists}} 1 1 0 0}
test fCmd-9.8 {file rename: comprehensive: dir to empty dir} -setup {
    cleanup
} -constraints {notRoot testchmod notNetworkFilesystem} -body {
    # Under unix, you can rename a read-only directory, but you can't move it
    # Under Unix you can rename a read-only directory, but you can't move it
    # into another directory.
    file mkdir td1
    file mkdir [file join td2 td1]
    file mkdir tds1
    file mkdir tds2
    file mkdir tds3
    file mkdir tds4
895
896
897
898
899
900
901
902

903
904
905
906
907
908
909
910
911
912
913
914
915
916
917

918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933

934
935

936
937
938
939
940
941
942
943
944
945
946
947
948

949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966

967
968
969
970
971
972
973
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







-
+








-
-
-


-
-
+
-
-
-












-
+

-
+






-
-
-


-
-
+
-
-
-














-
+







	set w4 0
    } else {
	set w3 [file writable [file join tdd3 tds3]]
	set w4 [file writable [file join tdd4 tds4]]
    }
    list [lsort [glob td*]] $msg [file writable [file join tdd1 tds1]] \
    [file writable [file join tdd2 tds2]] $w3 $w4
} -result [subst {{td1 td2 tdd1 tdd2 tdd3 tdd4} {1 {error renaming "td1" to "[file join td2 td1]": file already exists}} 1 1 0 0}]
} -result [subst {{td1 td2 tdd1 tdd2 tdd3 tdd4} {1 {error renaming "td1" to "[file join td2 td1]": file exists}} 1 1 0 0}]
# Test can hit EEXIST or EBUSY, depending on underlying filesystem
test fCmd-9.9 {file rename: comprehensive: dir to non-empty dir} -setup {
    cleanup
} -constraints {notRoot testchmod notWine} -body {
    file mkdir tds1
    file mkdir tds2
    file mkdir [file join tdd1 tds1 xxx]
    file mkdir [file join tdd2 tds2 xxx]
    if {!([testConstraint unix] || [testConstraint winVista])} {
	testchmod 0o555 tds2
    }
    set a1 [list [catch {file rename -force tds1 tdd1} msg] $msg]
    set a2 [list [catch {file rename -force tds2 tdd2} msg] $msg]
    if {[testConstraint unix] || [testConstraint winVista]} {
	set w2 0
    set w2 0
    } else {
	set w2 [file writable tds2]
    }
    list [lsort [glob td*]] $a1 $a2 [file writable tds1] $w2
} -match glob -result \
    [subst {{tdd1 tdd2 tds1 tds2} {1 {error renaming "tds1" to "[file join tdd1 tds1]": file *}} {1 {error renaming "tds2" to "[file join tdd2 tds2]": file *}} 1 0}]
test fCmd-9.10 {file rename: comprehensive: file to new name and dir} -setup {
    cleanup
} -constraints {notRoot testchmod} -body {
    createfile tf1
    createfile tf2
    file mkdir td1
    testchmod 0o444 tf2
    file rename tf1 [file join td1 tf3]
    file rename tf2 [file join td1 tf4]
    list [catch {glob tf*}] [lsort [glob -directory td1 t*]] \
    list [glob tf*] [lsort [glob -directory td1 t*]] \
    [file writable [file join td1 tf3]] [file writable [file join td1 tf4]]
} -result [subst {1 {[file join td1 tf3] [file join td1 tf4]} 1 0}]
} -result [subst {{} {[file join td1 tf3] [file join td1 tf4]} 1 0}]
test fCmd-9.11 {file rename: comprehensive: dir to new name and dir} -setup {
    cleanup
} -constraints {notRoot testchmod} -body {
    file mkdir td1
    file mkdir td2
    file mkdir td3
    if {!([testConstraint unix] || [testConstraint winVista])} {
	testchmod 0o555 td2
    }
    file rename td1 [file join td3 td3]
    file rename td2 [file join td3 td4]
    if {[testConstraint unix] || [testConstraint winVista]} {
        set w4 0
    set w4 0
    } else {
	set w4 [file writable [file join td3 td4]]
    }
    list [lsort [glob td*]] [lsort [glob -directory td3 t*]] \
    [file writable [file join td3 td3]] $w4
} -result [subst {td3 {[file join td3 td3] [file join td3 td4]} 1 0}]
test fCmd-9.12 {file rename: comprehensive: target exists} -setup {
    cleanup
} -constraints {notRoot testchmod notNetworkFilesystem} -body {
    file mkdir [file join td1 td2] [file join td2 td1]
    testchmod 0o555 [file join td2 td1]
    file mkdir [file join td3 td4] [file join td4 td3]
    file rename -force td3 td4
    list [file exists td3] [file exists [file join td4 td3 td4]] \
	[catch {file rename td1 td2} msg] $msg
} -cleanup {
    testchmod 0o755 [file join td2 td1]
} -result [subst {0 1 1 {error renaming "td1" to "[file join td2 td1]": file already exists}}]
} -result [subst {0 1 1 {error renaming "td1" to "[file join td2 td1]": file exists}}]
# Test can hit EEXIST or EBUSY, depending on underlying filesystem
test fCmd-9.13 {file rename: comprehensive: can't overwrite target} -setup {
    cleanup
} -constraints {notRoot notWine} -body {
    file mkdir [file join td1 td2] [file join td2 td1 td4]
    file rename -force td1 td2
} -returnCodes error -match glob -result \
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
1139
1140
1141
1142
1143
1144
1145

1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172







-
+


















+







    testchmod 0o444 tf2
    file copy tf1 tf3
    file copy tf2 tf4
    list [lsort [glob tf*]] [contents tf3] [contents tf4] [file writable tf3] [file writable tf4]
} -result {{tf1 tf2 tf3 tf4} tf1 tf2 1 0}
test fCmd-10.3 {file copy: comprehensive: dir to new name} -setup {
    cleanup
} -constraints {unix notRoot testchmod} -body {
} -constraints {unix notRoot testchmod notWsl} -body {
    file mkdir [file join td1 tdx]
    file mkdir [file join td2 tdy]
    testchmod 0o555 td2
    file copy td1 td3
    file copy td2 td4
    list [lsort [glob td*]] [glob -directory td3 t*] \
	    [glob -directory td4 t*] [file writable td3] [file writable td4]
} -cleanup {
    testchmod 0o755 td2
    testchmod 0o755 td4
} -result [list {td1 td2 td3 td4} [file join td3 tdx] [file join td4 tdy] 1 0]
test fCmd-10.3.1 {file copy: comprehensive: dir to new name} -setup {
    cleanup
} -constraints {win notRoot testchmod} -body {
    # On Windows with ACLs, copying a directory is defined like this
    file mkdir [file join td1 tdx]
    file mkdir [file join td2 tdy]
    testchmod 0o555 td2
    testchmod 0o555 td2/tdy; # Above line removes inherited perms. So restore.
    file copy td1 td3
    file copy td2 td4
    list [lsort [glob td*]] [glob -directory td3 t*] \
	    [glob -directory td4 t*] [file writable td3] [file writable td4]
} -cleanup {
    testchmod 0o755 td2
    testchmod 0o755 td4
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
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194




1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205

1206
1207
1208
1209
1210
1211
1212
1213







+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+






-
+







    createfile tfs2
    createfile tfs3
    createfile tfs4
    createfile tfd1
    createfile tfd2
    createfile tfd3
    createfile tfd4
    if {$::tcl_platform(platform) eq "windows"} {
	# On Windows testchmode will attach an ACL which file copy cannot handle
	# so use good old attributes which file copy does understand
	file attribute tfs3 -readonly 1
	file attribute tfs4 -readonly 1
	file attribute tfd2 -readonly 1
	file attribute tfd4 -readonly 1
    } else {
    testchmod 0o444 tfs3
    testchmod 0o444 tfs4
    testchmod 0o444 tfd2
    testchmod 0o444 tfd4
	testchmod 0o444 tfs3
	testchmod 0o444 tfs4
	testchmod 0o444 tfd2
	testchmod 0o444 tfd4
    }
    set msg [list [catch {file copy tf1 tf2} msg] $msg]
    file copy -force tfs1 tfd1
    file copy -force tfs2 tfd2
    file copy -force tfs3 tfd3
    file copy -force tfs4 tfd4
    list [lsort [glob tf*]] $msg [file writable tfd1] [file writable tfd2] [file writable tfd3] [file writable tfd4]
} -result {{tf1 tf2 tfd1 tfd2 tfd3 tfd4 tfs1 tfs2 tfs3 tfs4} {1 {error copying "tf1" to "tf2": file already exists}} 1 1 0 0}
} -result {{tf1 tf2 tfd1 tfd2 tfd3 tfd4 tfs1 tfs2 tfs3 tfs4} {1 {error copying "tf1" to "tf2": file exists}} 1 1 0 0}
test fCmd-10.5 {file copy: comprehensive: dir to empty dir} -setup {
    cleanup
} -constraints {notRoot testchmod} -body {
    file mkdir td1
    file mkdir [file join td2 td1]
    file mkdir tds1
    file mkdir tds2
1110
1111
1112
1113
1114
1115
1116
1117

1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
1128
1129

1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144

1145
1146
1147
1148
1149
1150
1151
1223
1224
1225
1226
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







-
+


-
+








-
+














-
+







    testchmod 0o555 [file join tdd4 tds4]
    set a1 [list [catch {file copy td1 td2} msg] $msg]
    set a2 [list [catch {file copy -force tds1 tdd1} msg] $msg]
    set a3 [catch {file copy -force tds2 tdd2}]
    set a4 [catch {file copy -force tds3 tdd3}]
    set a5 [catch {file copy -force tds4 tdd4}]
    list [lsort [glob td*]] $a1 $a2 $a3 $a4 $a5
} -result [subst {{td1 td2 tdd1 tdd2 tdd3 tdd4 tds1 tds2 tds3 tds4} {1 {error copying "td1" to "[file join td2 td1]": file already exists}} {1 {error copying "tds1" to "[file join tdd1 tds1]": file already exists}} 1 1 1}]
} -result [subst {{td1 td2 tdd1 tdd2 tdd3 tdd4 tds1 tds2 tds3 tds4} {1 {error copying "td1" to "[file join td2 td1]": file exists}} {1 {error copying "tds1" to "[file join tdd1 tds1]": file exists}} 1 1 1}]
test fCmd-10.6 {file copy: comprehensive: dir to non-empty dir} -setup {
    cleanup
} -constraints {notRoot unixOrWin testchmod} -body {
} -constraints {notRoot unixOrWin testchmod notWsl} -body {
    file mkdir tds1
    file mkdir tds2
    file mkdir [file join tdd1 tds1 xxx]
    file mkdir [file join tdd2 tds2 xxx]
    testchmod 0o555 tds2
    set a1 [list [catch {file copy -force tds1 tdd1} msg] $msg]
    set a2 [list [catch {file copy -force tds2 tdd2} msg] $msg]
    list [lsort [glob td*]] $a1 $a2 [file writable tds1] [file writable tds2]
} -result [subst {{tdd1 tdd2 tds1 tds2} {1 {error copying "tds1" to "[file join tdd1 tds1]": file already exists}} {1 {error copying "tds2" to "[file join tdd2 tds2]": file already exists}} 1 0}]
} -result [subst {{tdd1 tdd2 tds1 tds2} {1 {error copying "tds1" to "[file join tdd1 tds1]": file exists}} {1 {error copying "tds2" to "[file join tdd2 tds2]": file exists}} 1 0}]
test fCmd-10.7 {file rename: comprehensive: file to new name and dir} -setup {
    cleanup
} -constraints {notRoot testchmod} -body {
    createfile tf1
    createfile tf2
    file mkdir td1
    testchmod 0o444 tf2
    file copy tf1 [file join td1 tf3]
    file copy tf2 [file join td1 tf4]
    list [lsort [glob tf*]] [lsort [glob -directory td1 t*]] \
    [file writable [file join td1 tf3]] [file writable [file join td1 tf4]]
} -result [subst {{tf1 tf2} {[file join td1 tf3] [file join td1 tf4]} 1 0}]
test fCmd-10.8 {file rename: comprehensive: dir to new name and dir} -setup {
    cleanup
} -constraints {unix notRoot testchmod} -body {
} -constraints {unix notRoot testchmod notWsl} -body {
    file mkdir td1
    file mkdir td2
    file mkdir td3
    testchmod 0o555 td2
    file copy td1 [file join td3 td3]
    file copy td2 [file join td3 td4]
    list [lsort [glob td*]] [lsort [glob -directory td3 t*]] \
1229
1230
1231
1232
1233
1234
1235
1236

1237
1238
1239
1240
1241
1242
1243
1342
1343
1344
1345
1346
1347
1348

1349
1350
1351
1352
1353
1354
1355
1356







-
+







} -constraints {notRoot} -body {
    createfile tfa1
    createfile tfa2
    createfile tfa3
    catch {file rename tfa1 tfa2 tfa3}
} -cleanup {
    file delete tfa1 tfa2 tfa3
} -result {1}
} -result 1
test fCmd-11.6 {TclFileRenameCmd: : single file into directory} -setup {
    catch {file delete -force -- tfa1 tfad}
} -constraints {notRoot} -body {
    set s [createfile tfa1]
    file mkdir tfad
    file rename tfa1 tfad
    list [checkcontent tfad/tfa1 $s] [file exists tfa1]
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
1387
1388
1389
1390
1391
1392
1393

1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405

1406
1407
1408
1409
1410
1411
1412
1413







-
+











-
+







    set temp $::env(HOME)
} -constraints {notRoot} -body {
    global env
    unset env(HOME)
    catch {file rename ~/tfa1 tfa2}
} -cleanup {
    set ::env(HOME) $temp
} -result {1}
} -result 1
test fCmd-12.2 {renamefile: src filename translation failing} -setup {
    set temp $::env(HOME)
} -constraints {notRoot} -body {
    global env
    unset env(HOME)
    set s [createfile tfa1]
    file mkdir tfad
    catch {file rename tfa1 ~/tfa2 tfad}
} -cleanup {
    set ::env(HOME) $temp
    file delete -force tfad
} -result {1}
} -result 1
test fCmd-12.3 {renamefile: stat failing on source} -setup {
    catch {file delete -force -- tfa1 tfa2}
} -constraints {notRoot} -body {
    list [catch {file rename tfa1 tfa2}] [file exists tfa1] [file exists tfa2]
} -result {1 0 0}
test fCmd-12.4 {renamefile: error renaming file to directory} -setup {
    catch {file delete -force -- tfa tfad}
1331
1332
1333
1334
1335
1336
1337
1338

1339
1340
1341

1342
1343
1344

1345
1346
1347

1348
1349

1350
1351
1352
1353
1354
1355
1356
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







-
+


-
+


-
+


-
+

-
+







    catch {file delete -force -- tfad}
} -constraints {notRoot} -body {
    file mkdir tfad
    file mkdir tfad/dir
    catch {file rename tfad tfad/dir}
} -cleanup {
    file delete -force tfad
} -result {1}
} -result 1
test fCmd-12.8 {renamefile: generic error} -setup {
    catch {file delete -force -- tfa}
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
    file mkdir tfa
    file mkdir tfa/dir
    file attributes tfa -permissions 0555
    file attributes tfa -permissions 0o555
    catch {file rename tfa/dir tfa2}
} -cleanup {
    catch {file attributes tfa -permissions 0777}
    catch {file attributes tfa -permissions 0o777}
    file delete -force tfa
} -result {1}
} -result 1
test fCmd-12.9 {renamefile: moving a file across volumes} -setup {
    cleanup $tmpspace
} -constraints {unix notRoot} -body {
    set s [createfile tfa]
    file rename tfa $tmpspace
    list [checkcontent [file join $tmpspace tfa] $s] [file exists tfa]
} -cleanup {
1404
1405
1406
1407
1408
1409
1410
1411

1412
1413
1414
1415
1416
1417
1418
1419
1420
1421

1422
1423
1424
1425
1426
1427
1428
1517
1518
1519
1520
1521
1522
1523

1524
1525
1526
1527
1528
1529
1530
1531
1532
1533

1534
1535
1536
1537
1538
1539
1540
1541







-
+









-
+







    set temp $::env(HOME)
} -body {
    global env
    unset env(HOME)
    catch { file copy tfa ~/foobar }
} -cleanup {
    set ::env(HOME) $temp
} -result {1}
} -result 1
test fCmd-13.6 {TclCopyFilesCmd: > 1 source & target is not a dir} -setup {
    catch {file delete -force -- tfa1 tfa2 tfa3}
} -constraints {notRoot} -body {
    createfile tfa1
    createfile tfa2
    createfile tfa3
    catch {file copy tfa1 tfa2 tfa3}
} -cleanup {
    file delete tfa1 tfa2 tfa3
} -result {1}
} -result 1
test fCmd-13.7 {TclCopyFilesCmd: single file into directory} -setup {
    catch {file delete -force -- tfa1 tfad}
} -constraints {notRoot} -body {
    set s [createfile tfa1]
    file mkdir tfad
    file copy tfa1 tfad
    list [checkcontent tfad/tfa1 $s] [checkcontent tfa1 $s]
1460
1461
1462
1463
1464
1465
1466
1467

1468
1469
1470
1471
1472
1473
1474
1573
1574
1575
1576
1577
1578
1579

1580
1581
1582
1583
1584
1585
1586
1587







-
+







    set temp $::env(HOME)
} -constraints {notRoot} -body {
    global env
    unset env(HOME)
    catch {file copy ~/tfa1 tfa2}
} -cleanup {
    set ::env(HOME) $temp
} -result {1}
} -result 1
test fCmd-14.2 {copyfile: dst filename translation failing} -setup {
    set temp $::env(HOME)
} -constraints {notRoot} -body {
    global env
    unset env(HOME)
    set s [createfile tfa1]
    file mkdir tfad
1521
1522
1523
1524
1525
1526
1527
1528

1529
1530

1531
1532
1533

1534
1535

1536
1537
1538
1539


1540
1541
1542

1543
1544
1545
1546
1547
1548

1549
1550
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
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







-
+

-
+


-
+

-
+




+
+


-
+





-
+










-
+













-
+


-
+

-
+







-
+







    file copy tfa tfa2
    list [checkcontent tfa/file $s] [checkcontent tfa2/file $s]
} -cleanup {
    file delete -force tfa tfa2
} -result {1 1}
test fCmd-14.8 {copyfile: copy directory failing} -setup {
    catch {file delete -force -- tfa}
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
    file mkdir tfa/dir/a/b/c
    file attributes tfa/dir -permissions 0000
    file attributes tfa/dir -permissions 0
    catch {file copy tfa tfa2}
} -cleanup {
    file attributes tfa/dir -permissions 0777
    file attributes tfa/dir -permissions 0o777
    file delete -force tfa tfa2
} -result {1}
} -result 1

#
# Coverage tests for TclMkdirCmd()
#

# ~ is no longer a special char. Need a test case where translation fails.
test fCmd-15.1 {TclMakeDirsCmd: target filename translation failing} -setup {
    set temp $::env(HOME)
} -constraints {notRoot} -body {
} -constraints {notRoot TODO} -body {
    global env
    unset env(HOME)
    catch {file mkdir ~/tfa}
} -cleanup {
    set ::env(HOME) $temp
} -result {1}
} -result 1
#
# Can Tcl_SplitPath return argc == 0? If so them we need a test for that code.
#
test fCmd-15.2 {TclMakeDirsCmd - one directory} -setup {
    catch {file delete -force -- tfa}
} -constraints {notRoot} -body {
    file mkdir tfa
    file isdirectory tfa
} -cleanup {
    file delete tfa
} -result {1}
} -result 1
test fCmd-15.3 {TclMakeDirsCmd: - two directories} -setup {
    catch {file delete -force -- tfa1 tfa2}
} -constraints {notRoot} -body {
    file mkdir tfa1 tfa2
    list [file isdirectory tfa1] [file isdirectory tfa2]
} -cleanup {
    file delete tfa1 tfa2
} -result {1 1}
test fCmd-15.4 {TclMakeDirsCmd - stat failing} -setup {
    catch {file delete -force -- tfa}
} -constraints {unix notRoot} -body {
    file mkdir tfa
    createfile tfa/file
    file attributes tfa -permissions 0000
    file attributes tfa -permissions 0
    catch {file mkdir tfa/file}
} -cleanup {
    file attributes tfa -permissions 0777
    file attributes tfa -permissions 0o777
    file delete -force tfa
} -result {1}
} -result 1
test fCmd-15.5 {TclMakeDirsCmd: - making a directory several levels deep} -setup {
    catch {file delete -force -- tfa}
} -constraints {notRoot} -body {
    file mkdir tfa/a/b/c
    file isdir tfa/a/b/c
} -cleanup {
    file delete -force tfa
} -result {1}
} -result 1
test fCmd-15.6 {TclMakeDirsCmd: - trying to overwrite a file} -setup {
    catch {file delete -force -- tfa}
} -constraints {notRoot} -body {
    set s [createfile tfa]
    list [catch {file mkdir tfa}] [file isdir tfa] [file exists tfa] \
	[checkcontent tfa $s]
} -cleanup {
1603
1604
1605
1606
1607
1608
1609
1610

1611
1612
1613
1614
1615
1616
1617
1718
1719
1720
1721
1722
1723
1724

1725
1726
1727
1728
1729
1730
1731
1732







-
+







} -result {1 1}
test fCmd-15.8 {TclFileMakeDirsCmd: trying to create an existing dir} -body {
    file mkdir tfa
    file mkdir tfa
    file isdir tfa
} -constraints {notRoot} -cleanup {
    file delete tfa
} -result {1}
} -result 1

# Coverage tests for TclDeleteFilesCommand()
test fCmd-16.1 {test the -- argument} -constraints {notRoot} -setup {
    catch {file delete -force -- tfa}
} -body {
    createfile tfa
    file delete -- tfa
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
1742
1743
1744
1745
1746
1747
1748

1749
1750
1751
1752
1753
1754
1755
1756
1757
1758

1759
1760
1761
1762
1763
1764

1765
1766
1767
1768
1769
1770
1771
1772
1773

1774
1775
1776
1777
1778
1779
1780
1781
1782

1783
1784
1785

1786
1787
1788

1789
1790
1791
1792
1793
1794
1795
1796

1797
1798

1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816

1817
1818

1819
1820
1821

1822
1823

1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840

1841
1842
1843
1844
1845
1846
1847
1848







-
+






+


-
+





-
+








-
+








-
+


-
+


-
+







-
+

-
+

















-
+

-
+


-
+

-
+
















-
+







test fCmd-16.3 {test bad option} -constraints {notRoot} -setup {
    catch {file delete -force -- tfa}
} -body {
    createfile tfa
    catch {file delete -dog tfa}
} -cleanup {
    file delete tfa
} -result {1}
} -result 1
test fCmd-16.4 {accept zero files (TIP 323)} -body {
    file delete
} -result {}
test fCmd-16.5 {accept zero files (TIP 323)} -body {
    file delete --
} -result {}
# ~ is no longer a special char. Need a test case where translation fails.
test fCmd-16.6 {delete: source filename translation failing} -setup {
    set temp $::env(HOME)
} -constraints {notRoot} -body {
} -constraints {notRoot TODO} -body {
    global env
    unset env(HOME)
    catch {file delete ~/tfa}
} -cleanup {
    set ::env(HOME) $temp
} -result {1}
} -result 1
test fCmd-16.7 {remove a non-empty directory without -force} -setup {
    catch {file delete -force -- tfa}
} -constraints {notRoot} -body {
    file mkdir tfa
    createfile tfa/a
    catch {file delete tfa}
} -cleanup {
    file delete -force tfa
} -result {1}
} -result 1
test fCmd-16.8 {remove a normal file} -constraints {notRoot} -setup {
    catch {file delete -force -- tfa}
} -body {
    file mkdir tfa
    createfile tfa/a
    catch {file delete tfa}
} -cleanup {
    file delete -force tfa
} -result {1}
} -result 1
test fCmd-16.9 {error while deleting file} -setup {
    catch {file delete -force -- tfa}
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
    file mkdir tfa
    createfile tfa/a
    file attributes tfa -permissions 0555
    file attributes tfa -permissions 0o555
    catch {file delete tfa/a}
    #######
    #######  If any directory in a tree that is being removed does not have
    #######  write permission, the process will fail! This is also the case
    #######  with "rm -rf"
    #######
} -cleanup {
    file attributes tfa -permissions 0777
    file attributes tfa -permissions 0o777
    file delete -force tfa
} -result {1}
} -result 1
test fCmd-16.10 {deleting multiple files} -constraints {notRoot} -setup {
    catch {file delete -force -- tfa1 tfa2}
} -body {
    createfile tfa1
    createfile tfa2
    file delete tfa1 tfa2
    list [file exists tfa1] [file exists tfa2]
} -result {0 0}
test fCmd-16.11 {TclFileDeleteCmd: removing a nonexistant file} -setup {
    catch {file delete -force -- tfa}
} -constraints {notRoot} -body {
    file delete tfa
} -result {}

# More coverage tests for mkpath()
test fCmd-17.1 {mkdir stat failing on target but not ENOENT} -setup {
     catch {file delete -force -- tfa1}
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
     file mkdir tfa1
     file attributes tfa1 -permissions 0555
     file attributes tfa1 -permissions 0o555
     catch {file mkdir tfa1/tfa2}
} -cleanup {
     file attributes tfa1 -permissions 0777
     file attributes tfa1 -permissions 0o777
     file delete -force tfa1
} -result {1}
} -result 1
test fCmd-17.2 {mkdir several levels deep - relative} -setup {
    catch {file delete -force -- tfa}
} -constraints {notRoot} -body {
    file mkdir tfa/a/b
    file isdir tfa/a/b
} -cleanup {
    file delete tfa/a/b tfa/a tfa
} -result 1
test fCmd-17.3 {mkdir several levels deep - absolute} -setup {
    catch {file delete -force -- tfa}
} -constraints {notRoot} -body {
    set f [file join [pwd] tfa a]
    file mkdir $f
    file isdir $f
} -cleanup {
    file delete $f [file join [pwd] tfa]
} -result {1}
} -result 1

#
# Functionality tests for TclFileRenameCmd()
#
test fCmd-18.1 {TclFileRenameCmd: rename (first form) in the same directory} \
	-setup {
    catch {file delete -force -- tfad}
1879
1880
1881
1882
1883
1884
1885
1886

1887
1888
1889
1890
1891
1892
1893
1995
1996
1997
1998
1999
2000
2001

2002
2003
2004
2005
2006
2007
2008
2009







-
+







    file mkdir tfa1
    set s [createfile tfa2]
    file link -symbolic tfalink tfa1
    file rename tfa2 tfalink
    checkcontent tfa1/tfa2 $s
} -cleanup {
    file delete -force tfa1 tfalink
} -result {1}
} -result 1
test fCmd-18.16 {TclFileRenameCmd: rename a dangling symlink} -setup {
    catch {file delete -force -- tfa1 tfalink}
} -constraints {unix notRoot} -body {
    file mkdir tfa1
    file link -symbolic tfalink tfa1
    file delete tfa1
    file rename tfalink tfa2
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
2020
2021
2022
2023
2024
2025
2026

2027
2028
2029

2030
2031
2032

2033
2034

2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054

2055
2056
2057

2058
2059
2060

2061
2062

2063
2064
2065
2066
2067
2068
2069
2070







-
+


-
+


-
+

-
+



















-
+


-
+


-
+

-
+







} -body {
    file mkdir tfa
    file delete tfa
    file exists tfa
} -result {0}
test fCmd-19.2 {rmdir error besides EEXIST} -setup {
    catch {file delete -force -- tfa}
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
    file mkdir tfa
    file mkdir tfa/a
    file attributes tfa -permissions 0555
    file attributes tfa -permissions 0o555
    catch {file delete tfa/a}
} -cleanup {
    file attributes tfa -permissions 0777
    file attributes tfa -permissions 0o777
    file delete -force tfa
} -result {1}
} -result 1
test fCmd-19.3 {recursive remove} -constraints {notRoot} -setup {
    catch {file delete -force -- tfa}
} -body {
    file mkdir tfa
    file mkdir tfa/a
    file delete -force tfa
    file exists tfa
} -result {0}

#
# TclUnixDeleteFile and TraversalDelete are covered by tests from the
# TclDeleteFilesCmd suite
#

#
# Coverage tests for TraverseUnixTree(), called from TclDeleteFilesCmd
#
test fCmd-20.1 {TraverseUnixTree : failure opening a subdirectory directory} -setup {
    catch {file delete -force -- tfa}
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
    file mkdir tfa
    file mkdir tfa/a
    file attributes tfa/a -permissions 0000
    file attributes tfa/a -permissions 00000
    catch {file delete -force tfa}
} -cleanup {
    file attributes tfa/a -permissions 0777
    file attributes tfa/a -permissions 0o777
    file delete -force tfa
} -result {1}
} -result 1
test fCmd-20.2 {TraverseUnixTree : recursive delete of large directory: Bug 1034337} -setup {
    catch {file delete -force -- tfa}
} -constraints {unix notRoot} -body {
    file mkdir tfa
    for {set i 1} {$i <= 300} {incr i} {
	createfile tfa/testfile_$i
    }
1993
1994
1995
1996
1997
1998
1999
2000

2001
2002
2003
2004
2005
2006
2007
2109
2110
2111
2112
2113
2114
2115

2116
2117
2118
2119
2120
2121
2122
2123







-
+







} -constraints {notRoot} -body {
    createfile tfa1
    createfile tfa2
    createfile tfa3
    catch {file copy tfa1 tfa2 tfa3}
} -cleanup {
    file delete tfa1 tfa2 tfa3
} -result {1}
} -result 1
test fCmd-21.5 {copy : multiple files into directory} -constraints {notRoot} -setup {
    catch {file delete -force -- tfa1 tfa2 tfad}
} -body {
    set s1 [createfile tfa1]
    set s2 [createfile tfa2]
    file mkdir tfad
    file copy tfa1 tfa2 tfad
2118
2119
2120
2121
2122
2123
2124
2125

2126
2127
2128
2129
2130
2131
2132
2234
2235
2236
2237
2238
2239
2240

2241
2242
2243
2244
2245
2246
2247
2248







-
+







    catch {file delete -force -- tfa1}
} -constraints {unix notRoot} -body {
    set s [createfile tfa1]
    file rename -force tfa1 tfa1
    checkcontent tfa1 $s
} -cleanup {
    file delete tfa1
} -result {1}
} -result 1
test fCmd-22.3 {TclpRenameFile: rename dir to existing dir} -setup {
    catch {file delete -force -- d1 tfad}
} -constraints {notRoot} -body {
    file mkdir d1 [file join tfad d1]
    list [catch {file rename d1 tfad}] [file isdir d1] \
	[file isdir [file join tfad d1]]
} -cleanup {
2262
2263
2264
2265
2266
2267
2268
2269

2270
2271
2272
2273
2274
2275
2276
2378
2379
2380
2381
2382
2383
2384

2385
2386
2387
2388
2389
2390
2391
2392







-
+







test fCmd-27.2 {TclFileAttrsCmd - Tcl_TranslateFileName fails} -setup {
    set platform [testgetplatform]
} -constraints {testsetplatform} -body {
    testsetplatform unix
    file attributes ~_totally_bogus_user
} -returnCodes error -cleanup {
    testsetplatform $platform
} -result {user "_totally_bogus_user" doesn't exist}
} -result {could not read "~_totally_bogus_user": no such file or directory}
test fCmd-27.3 {TclFileAttrsCmd - all attributes} -setup {
    catch {file delete -force -- foo.tmp}
} -body {
    createfile foo.tmp
    file attributes foo.tmp
    # Must be non-empty result
} -cleanup {
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
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







-
+







+
-
+



-
+
+

-
+







} -result {could not create new link "abc.dir": that path already exists}
test fCmd-28.6 {file link: unsupported operation} -setup {
    cd [temporaryDirectory]
} -constraints {linkDirectory win} -body {
    file link -hard abc.link abc.dir
} -returnCodes error -cleanup {
    cd [workingDirectory]
} -result {could not create new link "abc.link" pointing to "abc.dir": illegal operation on a directory}
} -result {could not create new link "abc.link" pointing to "abc.dir": is a directory}
test fCmd-28.7 {file link: source already exists} -setup {
    cd [temporaryDirectory]
} -constraints {linkFile} -body {
    file link abc.file abc2.file
} -returnCodes error -cleanup {
    cd [workingDirectory]
} -result {could not create new link "abc.file": that path already exists}
# In Windows 10 developer mode, we _can_ create symbolic links to files!
test fCmd-28.8 {file link} -constraints {linkFile win} -setup {
test fCmd-28.8 {file link} -constraints {linkFile winLessThan10} -setup {
    cd [temporaryDirectory]
} -body {
    file link -symbolic abc.link abc.file
} -returnCodes error -cleanup {
} -cleanup {
    file delete -force abc.link
    cd [workingDirectory]
} -result {could not create new link "abc.link" pointing to "abc.file": not a directory}
} -returnCodes error -result {could not create new link "abc.link" pointing to "abc.file": invalid argument}
test fCmd-28.9 {file link: success with file} -constraints {linkFile} -setup {
    cd [temporaryDirectory]
    file delete -force abc.link
} -body {
    file link abc.link abc.file
} -cleanup {
    cd [workingDirectory]
2416
2417
2418
2419
2420
2421
2422
2423

2424
2425
2426
2427
2428
2429
2430
2534
2535
2536
2537
2538
2539
2540

2541
2542
2543
2544
2545
2546
2547
2548







-
+







    cd abc.link
    set dir [pwd]
    cd ..
    set up [pwd]
    cd $orig
    # Now '$up' should be either $orig or [file dirname abc.dir], depending on
    # whether 'cd' actually moves to the destination of a link, or simply
    # treats the link as a directory. (On windows the former, on unix the
    # treats the link as a directory. (On windows the former, on Unix the
    # latter, I believe)
    if {
	([file normalize $up] ne [file normalize $orig]) &&
	([file normalize $up] ne [file normalize [file dirname abc.dir]])
    } then {
	return "wrong directory with 'cd abc.link ; cd ..': \
		\"[file normalize $up]\" should be \"[file normalize $orig]\"\
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
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







-
-
-
-
+
+
+
+
+
+


-
-
-
-
+
+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













    # Get the localized version of the folder name by looking in the registry.
    set mydocsname [registry get {HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders} Personal]
} -constraints {win reg} -body {
    file writable $mydocsname
} -result 1
test fCmd-30.2 {file readable on 'NTUSER.DAT'} -constraints {win notWine} -body {
    expr {[info exists env(USERPROFILE)]
          && [file exists $env(USERPROFILE)/NTUSER.DAT]
          && [file readable $env(USERPROFILE)/NTUSER.DAT]}
} -result {1}
test fCmd-30.3 {file readable on 'pagefile.sys'} -constraints {win notWine} -body {
	  && [file exists $env(USERPROFILE)/NTUSER.DAT]
	  && [file readable $env(USERPROFILE)/NTUSER.DAT]}
} -result 1
# At least one CI environment (GitHub Actions) is set up with the page file in
# an unusual location; skip the test if that is so.
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
	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 {
    set ::env(HOME) $saved
} -body {
    file tildeexpand ~
} -returnCodes error -result {couldn't find HOME environment variable to expand path}
test fCmd-32.3.1 {Tcl_FSTildeExpand ~ - error} -setup {
    set saved $::env(HOME)
    unset ::env(HOME)
} -cleanup {
    set ::env(HOME) $saved
} -constraints testfstildeexpand -body {
    testfstildeexpand ~
} -returnCodes error -result {couldn't find HOME environment variable to expand path}
test fCmd-32.4 {
    file tildeexpand ~ - 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 tildeexpand ~
} -result relative/path
test fCmd-32.4.1 {
    Tcl_FSTildeExpand ~ - 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
} -constraints testfstildeexpand -body {
    testfstildeexpand ~
} -result relative/path
test fCmd-32.5 {file tildeexpand ~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 tildeexpand ~$::tcl_platform(user)]
} -match glob -result [gethomedirglob $::tcl_platform(user)]
test fCmd-32.5.1 {Tcl_FSTildeExpand ~USER} -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)]
} -match glob -result [gethomedirglob $::tcl_platform(user)]
test fCmd-32.6 {file tildeexpand ~UNKNOWNUSER} -body {
    file tildeexpand ~nosuchuser
} -returnCodes error -result {user "nosuchuser" doesn't exist}
test fCmd-32.6.1 {Tcl_FSTildeExpand ~UNKNOWNUSER} -constraints testfstildeexpand -body {
    testfstildeexpand ~nosuchuser
} -returnCodes error -result {user "nosuchuser" doesn't exist}
test fCmd-32.7 {file tildeexpand ~extra arg} -body {
    file tildeexpand ~ arg
} -returnCodes error -result {wrong # args: should be "file tildeexpand path"}
test fCmd-32.7.1 {Tcl_FSTildeExpand ~extra arg} -constraints testfstildeexpand -body {
    testfstildeexpand ~ arg
} -returnCodes error -result {wrong # args: should be "testfstildeexpand PATH"}
test fCmd-32.8 {file tildeexpand ~/path} -body {
    file tildeexpand ~/foo
} -result [file join $::env(HOME)/foo]
test fCmd-32.8.1 {Tcl_FSTildeExpand ~/path} -constraints testfstildeexpand -body {
    testfstildeexpand ~/foo
} -result [file join $::env(HOME)/foo]
test fCmd-32.9 {file tildeexpand ~USER/bar} -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 tildeexpand ~$::tcl_platform(user)/bar]
} -match glob -result [file join [gethomedirglob $::tcl_platform(user)] bar]
test fCmd-32.9.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]
} -match glob -result [file join [gethomedirglob $::tcl_platform(user)] bar]
test fCmd-32.10 {file tildeexpand ~UNKNOWNUSER} -body {
    file tildeexpand ~nosuchuser/foo
} -returnCodes error -result {user "nosuchuser" doesn't exist}
test fCmd-32.10.1 {Tcl_FSTildeExpand ~UNKNOWNUSER} -constraints testfstildeexpand -body {
    testfstildeexpand ~nosuchuser/foo
} -returnCodes error -result {user "nosuchuser" doesn't exist}
test fCmd-32.11 {file tildeexpand /~/path} -body {
    file tildeexpand /~/foo
} -result /~/foo
test fCmd-32.11.1 {Tcl_FSTildeExpand /~/path} -constraints testfstildeexpand -body {
    testfstildeexpand /~/foo
} -result /~/foo
test fCmd-32.12 {file tildeexpand /~user/path} -body {
    file tildeexpand /~$::tcl_platform(user)/foo
} -result /~$::tcl_platform(user)/foo
test fCmd-32.12.1 {Tcl_FSTildeExpand /~user/path} -constraints testfstildeexpand -body {
    testfstildeexpand /~$::tcl_platform(user)/foo
} -result /~$::tcl_platform(user)/foo
test fCmd-32.13 {file tildeexpand ./~} -body {
    file tildeexpand ./~
} -result ./~
test fCmd-32.13.1 {Tcl_FSTildeExpand ./~} -constraints testfstildeexpand -body {
    testfstildeexpand ./~
} -result ./~
test fCmd-32.14 {file tildeexpand relative/path} -body {
    file tildeexpand relative/path
} -result relative/path
test fCmd-32.14.1 {Tcl_FSTildeExpand relative/path} -constraints testfstildeexpand -body {
    testfstildeexpand relative/path
} -result relative/path
test fCmd-32.15 {file tildeexpand ~\\path} -body {
    file tildeexpand ~\\foo
} -constraints win -result [file join $::env(HOME)/foo]
test fCmd-32.15.1 {Tcl_FSTildeExpand ~\\path} -constraints testfstildeexpand -body {
    testfstildeexpand ~\\foo
} -constraints win -result [file join $::env(HOME)/foo]
test fCmd-32.16 {file tildeexpand ~USER\\bar} -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 tildeexpand ~$::tcl_platform(user)\\bar]
} -constraints win -match glob -result [file join [gethomedirglob $::tcl_platform(user)] bar]
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
if {[testConstraint unix]} {
    removeDirectory tcl[pid] /tmp
}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:

Changes to tests/fileName.test.

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
30
31
32
33
34

35
36
37
38
39
40
41
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
30
31
32
33
34

35
36
37
38
39
40
41
42






-
-
+
+











-
+
+













-
+







# This file tests the filename manipulation routines.
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1999 by Scriptics Corporation.
# Copyright © 1995-1996 Sun Microsystems, Inc.
# Copyright © 1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
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]]
testConstraint linkDirectory 1
testConstraint symbolicLinkFile 1
if {[testConstraint win]} {
    if {$::tcl_platform(osVersion) < 5.0 \
	    || [lindex [file system [temporaryDirectory]] 1] ne "NTFS"} {
	testConstraint linkDirectory 0
    }
    testConstraint symbolicLinkFile 0
    testConstraint sharedCdrive [expr {![catch {cd //[info hostname]/c}]}]
}
testConstraint notWine [expr {$::tcl_platform(platform) ne "windows" || ![info exists ::env(TRAVIS_OS_NAME)] || ![string match linux $::env(TRAVIS_OS_NAME)]}]
testConstraint notWine [expr {![info exists ::env(CI_USING_WINE)]}]
# This match compares the first two words of the result. If the wanted result
# is "equal", then this is successful if the words are equal. If the wanted
# result is "not equal", then this is successful if the words are different.
customMatch compareWords {apply {{a b} {
    lassign $b w1 w2
    expr {$a eq "equal" ? $w1 eq $w2 : $w1 ne $w2}
}}}
67
68
69
70
71
72
73
74

75
76
77
78

79
80
81
82

83
84
85
86
87
88
89
68
69
70
71
72
73
74

75
76
77
78

79
80
81
82

83
84
85
86
87
88
89
90







-
+



-
+



-
+







test filename-1.4 {Tcl_GetPathType: unix} {testsetplatform} {
    testsetplatform unix
    file pathtype c:/foo
} relative
test filename-1.5 {Tcl_GetPathType: unix} {testsetplatform} {
    testsetplatform unix
    file pathtype ~
} absolute
} relative
test filename-1.6 {Tcl_GetPathType: unix} {testsetplatform} {
    testsetplatform unix
    file pathtype ~/foo
} absolute
} relative
test filename-1.7 {Tcl_GetPathType: unix} {testsetplatform} {
    testsetplatform unix
    file pathtype ~foo
} absolute
} relative
test filename-1.8 {Tcl_GetPathType: unix} {testsetplatform} {
    testsetplatform unix
    file pathtype ./~foo
} relative

test filename-3.1 {Tcl_GetPathType: windows} {testsetplatform} {
    testsetplatform windows
132
133
134
135
136
137
138
139

140
141
142
143

144
145
146
147

148
149
150
151
152
153
154
133
134
135
136
137
138
139

140
141
142
143

144
145
146
147

148
149
150
151
152
153
154
155







-
+



-
+



-
+







test filename-3.12 {Tcl_GetPathType: windows} {testsetplatform} {
    testsetplatform windows
    file pathtype //foo/bar
} absolute
test filename-3.13 {Tcl_GetPathType: windows} {testsetplatform} {
    testsetplatform windows
    file pathtype ~foo
} absolute
} relative
test filename-3.14 {Tcl_GetPathType: windows} {testsetplatform} {
    testsetplatform windows
    file pathtype ~
} absolute
} relative
test filename-3.15 {Tcl_GetPathType: windows} {testsetplatform} {
    testsetplatform windows
    file pathtype ~/foo
} absolute
} relative
test filename-3.16 {Tcl_GetPathType: windows} {testsetplatform} {
    testsetplatform windows
    file pathtype ./~foo
} relative

test filename-4.1 {Tcl_SplitPath: unix} {testsetplatform} {
    testsetplatform unix
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
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







-
+











-
+



-
+







test filename-4.12 {Tcl_SplitPath: unix} {testsetplatform} {
    testsetplatform unix
    file split ../..
} {.. ..}
test filename-4.13 {Tcl_SplitPath: unix} {testsetplatform} {
    testsetplatform unix
    file split //foo
} "/ foo"
} "//foo"
test filename-4.14 {Tcl_SplitPath: unix} {testsetplatform} {
    testsetplatform unix
    file split foo//bar
} {foo bar}
test filename-4.15 {Tcl_SplitPath: unix} {testsetplatform} {
    testsetplatform unix
    file split ~foo
} {~foo}
test filename-4.16 {Tcl_SplitPath: unix} {testsetplatform} {
    testsetplatform unix
    file split ~foo/~bar
} {~foo ./~bar}
} {~foo ~bar}
test filename-4.17 {Tcl_SplitPath: unix} {testsetplatform} {
    testsetplatform unix
    file split ~foo/~bar/~baz
} {~foo ./~bar ./~baz}
} {~foo ~bar ~baz}
test filename-4.18 {Tcl_SplitPath: unix} {testsetplatform} {
    testsetplatform unix
    file split foo/bar~/baz
} {foo bar~ baz}
if {[testConstraint testsetplatform]} {
    testsetplatform $platform
}
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
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







-
+



-
+







-
+







test filename-6.26 {Tcl_SplitPath: win} {testsetplatform} {
    testsetplatform win
    file split ~foo
} {~foo}
test filename-6.27 {Tcl_SplitPath: win} {testsetplatform} {
    testsetplatform win
    file split ~foo/~bar
} {~foo ./~bar}
} {~foo ~bar}
test filename-6.28 {Tcl_SplitPath: win} {testsetplatform} {
    testsetplatform win
    file split ~foo/~bar/~baz
} {~foo ./~bar ./~baz}
} {~foo ~bar ~baz}
test filename-6.29 {Tcl_SplitPath: win} {testsetplatform} {
    testsetplatform win
    file split foo/bar~/baz
} {foo bar~ baz}
test filename-6.30 {Tcl_SplitPath: win} {testsetplatform} {
    testsetplatform win
    file split c:~foo
} {c: ./~foo}
} {c: ~foo}

test filename-7.1 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    file join / a
} {/a}
test filename-7.2 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
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
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







-
+







-
+



-
+







-
+



-
+






-
+







test filename-7.10 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    file join ~ a
} {~/a}
test filename-7.11 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    file join ~a ~b
} {~b}
} {~a/~b}
test filename-7.12 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    file join ./~a b
} {./~a/b}
test filename-7.13 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    file join ./~a ~b
} {~b}
} {./~a/~b}
test filename-7.14 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    file join ./~a ./~b
} {./~a/~b}
} {./~a/./~b}
test filename-7.15 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    file join a . b
} {a/./b}
test filename-7.16 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    file join a . ./~b
} {a/./~b}
} {a/././~b}
test filename-7.17 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    file join //a b
} "/a/b"
} "//a/b"
test filename-7.18 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    file join /// a b
} "/a/b"
test filename-7.19 {[Bug f34cf83dd0]} {
    file join foo //bar
} /bar
} //bar

test filename-9.1 {Tcl_JoinPath: win} {testsetplatform} {
    testsetplatform win
    file join a b
} {a/b}
test filename-9.2 {Tcl_JoinPath: win} {testsetplatform} {
    testsetplatform win
486
487
488
489
490
491
492
493

494
495
496
497

498
499
500
501
502
503
504
487
488
489
490
491
492
493

494
495
496
497

498
499
500
501
502
503
504
505







-
+



-
+







test filename-9.10 {Tcl_JoinPath: win} {testsetplatform} {
    testsetplatform win
    file join ~/~foo
} {~/~foo}
test filename-9.11 {Tcl_JoinPath: win} {testsetplatform} {
    testsetplatform win
    file join ~ ./~foo
} {~/~foo}
} {~/./~foo}
test filename-9.12 {Tcl_JoinPath: win} {testsetplatform} {
    testsetplatform win
    file join / ~foo
} {~foo}
} {/~foo}
test filename-9.13 {Tcl_JoinPath: win} {testsetplatform} {
    testsetplatform win
    file join ./a/ b c
} {./a/b/c}
test filename-9.14 {Tcl_JoinPath: win} {testsetplatform} {
    testsetplatform win
    file join ./~a/ b c
596
597
598
599
600
601
602
603

604
605
606
607
608
609
610
611

612
613

614
615
616
617
618
619
620
621
622
623

624
625
626
627
628
629
630
631
632
633

634
635
636
637
638
639
640
641
642
643

644
645
646
647
648
649
650
651
652
653

654
655
656
657
658
659
660
661
662
663

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

707
708
709
710
711
712
713
714
715
716
717
718
719





720
721
722


723
724

725
726
727
728
729
730
731

732
733
734
735

736
737
738
739

740
741
742
743
744
745
746

747
748

749
750
751
752

753
754

755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772

773
774
775


776
777

778
779
780
781
782
783
784
597
598
599
600
601
602
603

604
605
606
607
608
609
610
611

612
613

614
615
616
617
618
619
620
621
622
623

624
625
626
627
628
629
630
631
632
633

634
635
636
637
638
639
640
641
642
643

644
645
646
647
648
649
650
651
652
653

654
655
656
657
658
659
660
661
662
663

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

707
708
709
710
711
712
713
714
715
716




717
718
719
720
721
722


723
724
725

726
727
728
729
730
731
732

733
734
735
736

737
738
739
740

741
742
743
744
745
746
747

748
749

750
751
752
753

754
755

756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773

774
775


776
777
778

779
780
781
782
783
784
785
786







-
+







-
+

-
+









-
+









-
+









-
+









-
+









-
+









-
-
+
+


-
+









-
+
















-
+

-
+









-
-
-
-
+
+
+
+
+

-
-
+
+

-
+






-
+



-
+



-
+






-
+

-
+



-
+

-
+

















-
+

-
-
+
+

-
+







    set temp $env(HOME)
} -constraints {testsetplatform testtranslatefilename} -body {
    set env(HOME) "/home/test"
    testsetplatform unix
    testtranslatefilename ~/foo
} -cleanup {
    set env(HOME) $temp
} -result {/home/test/foo}
} -result {~/foo}
test filename-10.7 {Tcl_TranslateFileName} -setup {
    global env
    set temp $env(HOME)
} -constraints {testsetplatform testtranslatefilename} -body {
    unset env(HOME)
    testsetplatform unix
    testtranslatefilename ~/foo
} -returnCodes error -cleanup {
} -cleanup {
    set env(HOME) $temp
} -result {couldn't find HOME environment variable to expand path}
} -result {~/foo}
test filename-10.8 {Tcl_TranslateFileName} -setup {
    global env
    set temp $env(HOME)
} -constraints {testsetplatform testtranslatefilename} -body {
    set env(HOME) "/home/test"
    testsetplatform unix
    testtranslatefilename ~
} -cleanup {
    set env(HOME) $temp
} -result {/home/test}
} -result {~}
test filename-10.9 {Tcl_TranslateFileName} -setup {
    global env
    set temp $env(HOME)
} -constraints {testsetplatform testtranslatefilename} -body {
    set env(HOME) "/home/test/"
    testsetplatform unix
    testtranslatefilename ~
} -cleanup {
    set env(HOME) $temp
} -result {/home/test}
} -result {~}
test filename-10.10 {Tcl_TranslateFileName} -setup {
    global env
    set temp $env(HOME)
} -constraints {testsetplatform testtranslatefilename} -body {
    set env(HOME) "/home/test/"
    testsetplatform unix
    testtranslatefilename ~/foo
} -cleanup {
    set env(HOME) $temp
} -result {/home/test/foo}
} -result {~/foo}
test filename-10.17 {Tcl_TranslateFileName} -setup {
    global env
    set temp $env(HOME)
} -constraints {testsetplatform testtranslatefilename} -body {
    set env(HOME) "\\home\\"
    testsetplatform windows
    testtranslatefilename ~/foo
} -cleanup {
    set env(HOME) $temp
} -result {\home\foo}
} -result {~\foo}
test filename-10.18 {Tcl_TranslateFileName} -setup {
    global env
    set temp $env(HOME)
} -constraints {testsetplatform testtranslatefilename} -body {
    set env(HOME) "\\home\\"
    testsetplatform windows
    testtranslatefilename ~/foo\\bar
} -cleanup {
    set env(HOME) $temp
} -result {\home\foo\bar}
} -result {~\foo\bar}
test filename-10.19 {Tcl_TranslateFileName} -setup {
    global env
    set temp $env(HOME)
} -constraints {testsetplatform testtranslatefilename} -body {
    set env(HOME) "c:"
    testsetplatform windows
    testtranslatefilename ~/foo
} -cleanup {
    set env(HOME) $temp
} -result {c:foo}
test filename-10.20 {Tcl_TranslateFileName} -returnCodes error -body {
} -result {~\foo}
test filename-10.20 {Tcl_TranslateFileName} -body {
    testtranslatefilename ~blorp/foo
} -constraints {testtranslatefilename testtranslatefilename} \
    -result {user "blorp" doesn't exist}
    -result {~blorp\foo}
test filename-10.21 {Tcl_TranslateFileName} -setup {
    global env
    set temp $env(HOME)
} -constraints {testsetplatform testtranslatefilename} -body {
    set env(HOME) "c:\\"
    testsetplatform windows
    testtranslatefilename ~/foo
} -cleanup {
    set env(HOME) $temp
} -result {c:\foo}
} -result {~\foo}
test filename-10.22 {Tcl_TranslateFileName} -body {
    testsetplatform windows
    testtranslatefilename foo//bar
} -constraints {testsetplatform testtranslatefilename} -result {foo\bar}
if {[testConstraint testsetplatform]} {
    testsetplatform $platform
}
test filename-10.23 {Tcl_TranslateFileName} -body {
    # this test fails if ~ouster is not /home/ouster
    testtranslatefilename ~ouster
} -constraints {nonPortable testtranslatefilename} -result {/home/ouster}
test filename-10.24 {Tcl_TranslateFileName} -body {
    # this test fails if ~ouster is not /home/ouster
    testtranslatefilename ~ouster/foo
} -result {/home/ouster/foo} -constraints {nonPortable testtranslatefilename}

test filename-11.1 {Tcl_GlobCmd} -returnCodes error -body {
test filename-11.1 {Tcl_GlobCmd} -body {
    glob
} -result {no files matched glob patterns ""}
} -result {}
test filename-11.2 {Tcl_GlobCmd} -returnCodes error -body {
    glob -gorp
} -result {bad option "-gorp": must be -directory, -join, -nocomplain, -path, -tails, -types, or --}
test filename-11.3 {Tcl_GlobCmd} -body {
    glob -nocomplai
} -result {}
test filename-11.4 {Tcl_GlobCmd} -body {
    glob -nocomplain
} -result {}
test filename-11.5 {Tcl_GlobCmd} -returnCodes error -body {
    glob -nocomplain * ~xyqrszzz
} -result {user "xyqrszzz" doesn't exist}
test filename-11.6 {Tcl_GlobCmd} -returnCodes error -body {
test filename-11.5 {Tcl_GlobCmd} -body {
    # Should not error out because of ~
    catch {glob -nocomplain * ~xyqrszzz}
} -result 0
test filename-11.6 {Tcl_GlobCmd} -body {
    glob ~xyqrszzz
} -result {user "xyqrszzz" doesn't exist}
test filename-11.7 {Tcl_GlobCmd} -returnCodes error -body {
} -result {}
test filename-11.7 {Tcl_GlobCmd} -body {
    glob -- -nocomplain
} -result {no files matched glob pattern "-nocomplain"}
} -result {}
test filename-11.8 {Tcl_GlobCmd} -body {
    glob -nocomplain -- -nocomplain
} -result {}
test filename-11.9 {Tcl_GlobCmd} -constraints {testsetplatform} -body {
    testsetplatform unix
    glob ~\\xyqrszzz/bar
} -returnCodes error -result {user "\xyqrszzz" doesn't exist}
} -result {}
test filename-11.10 {Tcl_GlobCmd} -constraints {testsetplatform} -body {
    testsetplatform unix
    glob -nocomplain ~\\xyqrszzz/bar
} -returnCodes error -result {user "\xyqrszzz" doesn't exist}
} -result {}
test filename-11.11 {Tcl_GlobCmd} -constraints {testsetplatform} -body {
    testsetplatform unix
    glob ~xyqrszzz\\/\\bar
} -returnCodes error -result {user "xyqrszzz" doesn't exist}
} -result {}
test filename-11.12 {Tcl_GlobCmd} -constraints {testsetplatform} -setup {
    testsetplatform unix
    set home $env(HOME)
} -body {
    unset env(HOME)
    glob ~/*
} -returnCodes error -cleanup {
} -cleanup {
    set env(HOME) $home
} -result {couldn't find HOME environment variable to expand path}
} -result {}
if {[testConstraint testsetplatform]} {
    testsetplatform $platform
}
test filename-11.13 {Tcl_GlobCmd} {
test filename-11.13 {Tcl_GlobCmd} -body {
    file join [lindex [glob ~] 0]
} [file join $env(HOME)]
} -result {}
set oldpwd [pwd]
set oldhome $env(HOME)
catch {cd [makeDirectory tcl[pid]]}
set env(HOME) [pwd]
file delete -force globTest
file mkdir globTest/a1/b1
file mkdir globTest/a1/b2
file mkdir globTest/a2/b3
file mkdir globTest/a3
touch globTest/x1.c
touch globTest/y1.c
touch globTest/z1.c
touch "globTest/weird name.c"
touch globTest/a1/b1/x2.c
touch globTest/a1/b2/y2.c
touch globTest/.1
touch globTest/x,z1.c
test filename-11.14 {Tcl_GlobCmd} {
test filename-11.14 {Tcl_GlobCmd} -body {
    glob ~/globTest
} [list [file join $env(HOME) globTest]]
test filename-11.15 {Tcl_GlobCmd} {
} -result {}
test filename-11.15 {Tcl_GlobCmd} -body {
    glob ~\\/globTest
} [list [file join $env(HOME) globTest]]
} -result {}
test filename-11.16 {Tcl_GlobCmd} {
    glob globTest
} {globTest}
set globname "globTest"
set horribleglobname "glob\[\{Test"
set tildeglobname "./~test.txt"

1059
1060
1061
1062
1063
1064
1065
1066

1067
1068
1069

1070
1071
1072
1073
1074
1075
1076
1061
1062
1063
1064
1065
1066
1067

1068
1069
1070

1071
1072
1073
1074
1075
1076
1077
1078







-
+


-
+







} -result {"-directory" cannot be used with "-path"}
test filename-11.45 {Tcl_GlobCmd on root volume} -setup {
    set res1 ""
    set res2 ""
    set tmpd [pwd]
} -body {
    catch {
	set res1 [glob -dir [lindex [file volumes] 0] -tails *]
	set res1 [glob -dir [lindex [file volumes] end] -tails *]
    }
    catch {
	cd [lindex [file volumes] 0]
	cd [lindex [file volumes] end]
	set res2 [glob *]
    }
    list $res1 $res2
} -cleanup {
    cd $tmpd
} -match compareWords -result equal
test filename-11.46 {Tcl_GlobCmd} -returnCodes error -body {
1093
1094
1095
1096
1097
1098
1099
1100

1101
1102

1103
1104
1105
1106


1107
1108
1109


1110
1111

1112
1113
1114

1115
1116
1117
1118


1119
1120
1121


1122
1123

1124
1125
1126
1127

1128
1129
1130


1131
1132
1133


1134
1135

1136
1137
1138
1139
1140
1141
1142
1095
1096
1097
1098
1099
1100
1101

1102
1103

1104
1105
1106


1107
1108
1109


1110
1111
1112

1113
1114
1115

1116
1117
1118


1119
1120
1121


1122
1123
1124

1125
1126
1127
1128

1129
1130


1131
1132
1133


1134
1135
1136

1137
1138
1139
1140
1141
1142
1143
1144







-
+

-
+


-
-
+
+

-
-
+
+

-
+


-
+


-
-
+
+

-
-
+
+

-
+



-
+

-
-
+
+

-
-
+
+

-
+







} -result {"-directory" may only be used once}

file rename $horribleglobname globTest
file delete -force $tildeglobname
set globname globTest
unset horribleglobname tildeglobname

test filename-12.1 {simple globbing} {unixOrWin} {
test filename-12.1 {simple globbing} -constraints {unixOrWin} -body {
    glob {}
} {.}
} -result {.}
test filename-12.1.1 {simple globbing} -constraints {unixOrWin} -body {
    glob -types f {}
} -returnCodes error -result {no files matched glob pattern ""}
test filename-12.1.2 {simple globbing} {unixOrWin} {
} -result {}
test filename-12.1.2 {simple globbing} -constraints {unixOrWin} -body {
    glob -types d {}
} {.}
test filename-12.1.3 {simple globbing} {unix} {
} -result {.}
test filename-12.1.3 {simple globbing} -constraints {unix} -body {
    glob -types hidden {}
} {.}
} -result {.}
test filename-12.1.4 {simple globbing} -constraints {win} -body {
    glob -types hidden {}
} -returnCodes error -result {no files matched glob pattern ""}
} -result {}
test filename-12.1.5 {simple globbing} -constraints {win} -body {
    glob -types hidden c:/
} -returnCodes error -result {no files matched glob pattern "c:/"}
test filename-12.1.6 {simple globbing} {win} {
} -result {}
test filename-12.1.6 {simple globbing} -constraints {win} -body {
    glob c:/
} {c:/}
test filename-12.3 {simple globbing} {
} -result {c:/}
test filename-12.3 {simple globbing} -body {
    glob -nocomplain \{a1,a2\}
} {}
} -result {}
set globPreResult globTest/
set x1 x1.c
set y1 y1.c
test filename-12.4 {simple globbing} {unixOrWin} {
test filename-12.4 {simple globbing} -constraints {unixOrWin} -body {
    lsort [glob globTest/x1.c globTest/y1.c globTest/foo]
} "$globPreResult$x1 $globPreResult$y1"
test filename-12.5 {simple globbing} {
} -result "$globPreResult$x1 $globPreResult$y1"
test filename-12.5 {simple globbing} -body {
    glob globTest\\/x1.c
} "$globPreResult$x1"
test filename-12.6 {simple globbing} {
} -result "$globPreResult$x1"
test filename-12.6 {simple globbing} -body {
    glob globTest\\/\\x1.c
} "$globPreResult$x1"
} -result "$globPreResult$x1"
test filename-12.7 {globbing at filesystem root} -constraints {unix} -body {
    list [glob -nocomplain /*] [glob -path / *]
} -match compareWords -result equal
test filename-12.8 {globbing at filesystem root} -constraints {unix} -body {
    set first [string range [lindex [glob -type d /*] 0] 0 1]
    list [glob -nocomplain ${first}*] [glob -path $first *]
} -match compareWords -result equal
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
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







-
+











-
+


-
+







    lsort [glob globTest/*/]
} {globTest/a1/ globTest/a2/ globTest/a3/}
test filename-14.17 {asterisks, question marks, and brackets} -setup {
    global env
    set temp $env(HOME)
} -body {
    set env(HOME) [file join $env(HOME) globTest]
    glob ~/z*
    glob [file home]/z*
} -cleanup {
    set env(HOME) $temp
} -result [list [file join $env(HOME) globTest z1.c]]
test filename-14.18 {asterisks, question marks, and brackets} {unixOrWin} {
    lsort [glob globTest/*.c goo/*]
} {{globTest/weird name.c} globTest/x,z1.c globTest/x1.c globTest/y1.c globTest/z1.c}
test filename-14.20 {asterisks, question marks, and brackets} {
    glob -nocomplain goo/*
} {}
test filename-14.21 {asterisks, question marks, and brackets} -body {
    glob globTest/*/gorp
} -returnCodes error -result {no files matched glob pattern "globTest/*/gorp"}
} -result {}
test filename-14.22 {asterisks, question marks, and brackets} -body {
    glob goo/* x*z foo?q
} -returnCodes error -result {no files matched glob patterns "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} {
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
1354
1355
1356

1357
1358
1359
1360
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
1387
1388
1389
1390

1391
1392
1393
1394
1395
1396
1397
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

1354

1355
1356

1357
1358
1359
1360
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
1387
1388
1389
1390







-
-
+
+














-
+











-
+



-
+



-
+
-


-
+









-
+
-
-
+
-
-
-
-
+
-
-
-
-
-
+

-
+










-
+







} globTest/a1/

test filename-14.31 {Bug 2918610} -setup {
    set d [makeDirectory foo]
    makeFile {} bar.soom $d
} -body {
    foreach fn [glob $d/bar.soom] {
        set root [file rootname $fn]
        close [open $root {WRONLY CREAT}]
	set root [file rootname $fn]
	close [open $root {WRONLY CREAT}]
    }
    llength [glob -directory $d *]
} -cleanup {
    file delete -force $d/bar
    removeFile bar.soom $d
    removeDirectory foo
} -result 2

unset globname

# The following tests are only valid for Unix systems. On some systems, like
# AFS, "000" protection doesn't prevent access by owner, so the following test
# is not portable.

catch {file attributes globTest/a1 -permissions 0000}
catch {file attributes globTest/a1 -permissions 0}
test filename-15.1 {unix specific globbing} {unix nonPortable} {
    string tolower [list [catch {glob globTest/a1/*} msg] $msg $errorCode]
} {1 {couldn't read directory "globtest/a1": permission denied} {posix eacces {permission denied}}}
test filename-15.2 {unix specific no complain: no errors} {unix nonPortable} {
    glob -nocomplain globTest/a1/*
} {}
test filename-15.3 {unix specific no complain: no errors, good result} \
	{unix nonPortable} {
    # test fails because if an error occurs, the interp's result is reset...
    glob -nocomplain globTest/a2 globTest/a1/* globTest/a3
} {globTest/a2 globTest/a3}
catch {file attributes globTest/a1 -permissions 0755}
catch {file attributes globTest/a1 -permissions 0o755}
test filename-15.4 {unix specific no complain: no errors, good result} \
	{unix nonPortable} {
    # test fails because if an error occurs, the interp's result is reset...
    # or you don't run at scriptics where the outser and welch users exists
    # or you don't run at scriptics where the ouster and welch users exists
    glob -nocomplain ~ouster ~foo ~welch
} {/home/ouster /home/welch}
test filename-15.4.1 {no complain: errors, sequencing} {
    # test used to fail because if an error occurs, the interp's result is
    # ~xxx no longer expanded so errors about unknown users should not occur
    # reset... But, the sequence means we throw a different error first.
    list [catch {glob -nocomplain ~wontexist ~blahxyz ~} res1] $res1 \
	[catch {glob -nocomplain ~ ~blahxyz ~wontexist} res2] $res2
} {1 {user "wontexist" doesn't exist} 1 {user "blahxyz" doesn't exist}}
} {0 {} 0 {}}
test filename-15.4.2 {no complain: errors, sequencing} -body {
    # test used to fail because if an error occurs, the interp's result is
    # reset...
    list [list [catch {glob -nocomplain ~wontexist *} res1] $res1] \
	[list [catch {glob -nocomplain * ~wontexist} res2] $res2]
} -match compareWords -result equal
test filename-15.5 {unix specific globbing} {unix nonPortable} {
    glob ~ouster/.csh*
} "/home/ouster/.cshrc"
touch globTest/odd\\\[\]*?\{\}name
# 15.6 removed. It checked if glob ~ returned valid information if
test filename-15.6 {unix specific globbing} -constraints {unix} -setup {
    global env
# home directory contained glob chars. Since ~ expansion is no longer
    set temp $env(HOME)
} -body {
    set env(HOME) $env(HOME)/globTest/odd\\\[\]*?\{\}name
    glob ~
# supported, the test was meaningless
} -cleanup {
    set env(HOME) $temp
} -result [list [lindex [glob ~] 0]/globTest/odd\\\[\]*?\{\}name]
catch {file delete -force globTest/odd\\\[\]*?\{\}name}
test filename-15.7 {win specific globbing} -constraints {win} -body {
test filename-15.7 {glob tilde} -body {
    glob ~
} -match regexp -result {[^/]$}
} -result {}
test filename-15.8 {win and unix specific globbing} -constraints {unixOrWin} -setup {
    global env
    set temp $env(HOME)
} -body {
    touch $env(HOME)/globTest/anyname
    set env(HOME) $env(HOME)/globTest/anyname
    glob ~
} -cleanup {
    set env(HOME) $temp
    catch {file delete -force $env(HOME)/globTest/anyname}
} -result [list [lindex [glob ~] 0]/globTest/anyname]
} -result {}

# The following tests are only valid for Windows systems.
set oldDir [pwd]
if {[testConstraint win]} {
    cd c:/
    file delete -force globTest
    file mkdir globTest
1482
1483
1484
1485
1486
1487
1488
1489

1490
1491
1492
1493
1494

1495
1496
1497
1498
1499
1500
1501
1475
1476
1477
1478
1479
1480
1481

1482
1483
1484
1485
1486

1487
1488
1489
1490
1491
1492
1493
1494







-
+




-
+







} {absolute absolute absolute absolute absolute absolute relative}
if {[testConstraint testsetplatform]} {
    testsetplatform $platform
}
test filename-17.2 {windows specific glob with executable} -body {
    makeDirectory execglob
    foreach ext {exe com cmd bat notexecutable} {
        makeFile contents execglob/abc.$ext
	makeFile contents execglob/abc.$ext
    }
    lsort [glob -nocomplain -dir [temporaryDirectory]/execglob -tails -types x *]
} -constraints {win} -cleanup {
    foreach ext {exe com cmd bat ps1 notexecutable} {
        removeFile execglob/abc.$ext
	removeFile execglob/abc.$ext
    }
    removeDirectory execglob
} -result {abc.bat abc.cmd abc.com abc.exe}
test filename-17.3 {Bug 2571597} win {
    set p /a
    file pathtype $p
    file normalize $p
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
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







-
+










-
+







    removeFile test $d
    removeDirectory ./~foo $dd
    removeDirectory isolate
} -result ~foo/test
test fileName-20.6 {Bug 2837800} -setup {
    # Recall that we have $env(HOME) set so that references
    # to ~ point to [temporaryDirectory]
    makeFile {} test ~
    makeFile {} test [file home]
    set dd [makeDirectory isolate]
    set d [makeDirectory ./~ $dd]
    set savewd [pwd]
    cd $dd
} -body {
    glob -nocomplain */test
} -cleanup {
    cd $savewd
    removeDirectory ./~ $dd
    removeDirectory isolate
    removeFile test ~
    removeFile test [file home]
} -result {}
test fileName-20.7 {Bug 2806250} -setup {
    set savewd [pwd]
    cd [temporaryDirectory]
    set d [makeDirectory isolate]
    makeFile {} ./~test $d
} -body {
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
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







-
+
-
-
-
-
-
-
-
-
-
-
-
-

-
+





-
+




-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    makeFile {} ./~test $d
} -body {
    file tail [lindex [glob -nocomplain isolate/*] 0]
} -cleanup {
    removeFile ./~test $d
    removeDirectory isolate
    cd $savewd
} -result ./~test
} -result ~test
test fileName-20.9 {globbing for special chars} -setup {
    makeFile {} test ~
    set d [makeDirectory isolate]
    set savewd [pwd]
    cd $d
} -body {
   glob -nocomplain -directory ~ test
} -cleanup {
    cd $savewd
    removeDirectory isolate
    removeFile test ~
} -result ~/test
test fileName-20.10 {globbing for special chars} -setup {
    set s [makeDirectory sub ~]
    set s [makeDirectory sub [file home]]
    makeFile {} fileName-20.10 $s
    set d [makeDirectory isolate]
    set savewd [pwd]
    cd $d
} -body {
   glob -nocomplain -directory ~ -join * fileName-20.10
    glob -nocomplain -directory [file home] -join * fileName-20.10
} -cleanup {
    cd $savewd
    removeDirectory isolate
    removeFile fileName-20.10 $s
    removeDirectory sub ~
} -result ~/sub/fileName-20.10
    removeDirectory sub [file home]
} -result [file home]/sub/fileName-20.10
test fileName-20.11 {glob dir with undecodable file names} -setup {
    # Specifically use /tmp as on WSL [temporaryDirectory]
    # on NTFS prevents creation of arbitrary byte sequences in names.
    set prevDir [pwd]
    set testDir /tmp/tcltest/fileName-20.11
    file delete -force $testDir; # Clear it
    file mkdir $testDir
    cd $testDir
    set prevEnc [encoding system]
    # Create a file name that is invalid if interpreted as utf-8
    encoding system iso8859-1
    close [open \xe9 w]
} -cleanup {
    encoding system $prevEnc
    cd $prevDir
    file delete -force $testDir
} -constraints {unix knownBug} -body {
    set result [file exists [lindex [glob *] 0]]
    encoding system utf-8
    lappend result [file exists [lindex [glob *] 0]]
} -result {1 1}

apply [list {} {
    test fileName-6d4e9d1af5bf5b7d {
	memory leak in SetFsPathFromAny

	Runs under both a TCL_DEBUG_MEM build and a -DPURIFY build for
	valgrind, which is useful since Valgrind provides information about the
	error location, but [memory] doesn't.
    } -setup {
	if {[namespace which ::memory] eq {}} {
	    set memcheckcmd [list ::apply [list script {
		uplevel 1 $script
		return 0
	    } [namespace current]]]
	} else {
	    set memcheckcmd ::tcltests::scriptmemcheck
	}
    } -body {
	{*}$memcheckcmd {
	    set interp [interp create]
	    interp eval $interp {
		apply [list {} {
		    upvar 1 f f

		    # A unique name so that no internal representation of this
		    # literal value has been picked up from any other script
		    # that has alredy been sourced into this interpreter.
		    set variableUniqueInTheEntireTclCodebase a
		    set name variableUniqueInTheEntireTclCodebase

		    # give the Tcl_Obj for "var1" an internal representation of
		    # type 'localVarNameType'.
		    set $name

		    set f [open variableUniqueInTheEntireTclCodebase w]
			try {
				puts $f {some data}
			} finally {
				close $f
			}

		    set f [open variableUniqueInTheEntireTclCodebase]
			try {
				read $f
			} finally {
				catch {file delete variableUniqueInTheEntireTclCodebase}
				close $f
			}
		} [namespace current]]
	    }
	    interp delete $interp
	}
    } -result 0
} [namespace current]]

# cleanup
catch {file delete -force C:/globTest}
cd [temporaryDirectory]
file delete -force globTest
cd $oldpwd
catch {removeDirectory tcl[pid]}

Changes to tests/fileSystem.test.

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
30

31
32
33


34
35
36
37
38



39


40

41
42
43
44
45
46
47
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

30
31


32
33
34
35



36
37
38
39
40
41

42
43
44
45
46
47
48
49






-
+




















-
+

-
+

-
-
+
+


-
-
-
+
+
+

+
+
-
+







# This file tests the filesystem and vfs internals.
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 2002 Vincent Darley.
# Copyright © 2002 Vincent Darley.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

namespace eval ::tcl::test::fileSystem {

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

    catch {
	file delete -force link.file
	file delete -force dir.link
	file delete -force [file join dir.dir linkinside.file]
    }

testConstraint loaddll 0
catch {
    ::tcltest::loadTestedCommands
    package require -exact Tcltest [info patchlevel]
    package require -exact tcl::test [info patchlevel]
    set ::ddever [package require dde]
    set ::ddelib [lindex [package ifneeded dde $::ddever] 1]
    set ::ddelib [info loaded {} Dde]
    set ::regver  [package require registry]
    set ::reglib [lindex [package ifneeded registry $::regver] 1]
    testConstraint loaddll 1
    set ::reglib [info loaded {} Registry]
    testConstraint loaddll [expr {$::ddelib ne "" && $::reglib ne ""}]
}

# Test for commands defined in Tcltest executable
testConstraint testfilesystem  	    [llength [info commands ::testfilesystem]]
testConstraint testsetplatform 	    [llength [info commands ::testsetplatform]]
# Test for commands defined in tcl::test package
testConstraint testfilesystem	    [llength [info commands ::testfilesystem]]
testConstraint testsetplatform	    [llength [info commands ::testsetplatform]]
testConstraint testsimplefilesystem [llength [info commands ::testsimplefilesystem]]
# Some things fail under all Continuous Integration systems for subtle reasons
# such as CI often running with elevated privileges in a container.
testConstraint knownMsvcBug [expr {![info exists ::env(TRAVIS_OS_NAME)] || ![string match windows $::env(TRAVIS_OS_NAME)]}]
testConstraint notInCIenv           [expr {![info exists ::env(CI)]}]

cd [tcltest::temporaryDirectory]
makeFile "test file" gorp.file
makeDirectory dir.dir
makeDirectory [file join dir.dir dirinside.dir]
makeFile "test file in directory" [file join dir.dir inside.file]

58
59
60
61
62
63
64
65
66
67



68

69
70


71
72
73
74
75
76
77
60
61
62
63
64
65
66



67
68
69
70
71


72
73
74
75
76
77
78
79
80







-
-
-
+
+
+

+
-
-
+
+







		testConstraint unusedDrive 1
		break
	    }
	}

	set dir [pwd]
	try {
	    foreach vol [file volumes] {
		if {![catch {cd $vol}]} {
		    lappend drives $vol
	    set drives [lmap vol [file volumes] {
		if {$vol eq [zipfs root] || [catch {cd $vol}]} {
		    continue
		}
		set vol
	    }
	    testConstraint moreThanOneDrive [llength $drives]
	    }]
	    testConstraint moreThanOneDrive [expr {[llength $drives] > 1}]
	} finally {
	    cd $dir
	}
    }
} ::tcl::test::fileSystem}

proc testPathEqual {one two} {
161
162
163
164
165
166
167
168

169
170
171
172
173
174
175
164
165
166
167
168
169
170

171
172
173
174
175
176
177
178







-
+







test filesystem-1.12 {file new native path} {} {
    for {set i 0} {$i < 10} {incr i} {
	foreach f [lsort [glob -nocomplain -type l *]] {
	    catch {file readlink $f}
	}
    }
    # If we reach here we've succeeded. We used to crash above.
    expr 1
    expr {1}
} {1}
test filesystem-1.13 {file normalisation} {win} {
    # This used to be broken
    file normalize C:/thislongnamedoesntexist
} {C:/thislongnamedoesntexist}
test filesystem-1.14 {file normalisation} {win} {
    # This used to be broken
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
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







-
+
+
+

-
+

-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+












-
+







file delete -force dir2.link
file delete -force link.file dir.link
file delete -force dir2
file delete -force [file join dir.dir dirinside.link]
removeFile [file join dir.dir inside.file]
removeDirectory [file join dir.dir dirinside.dir]
removeDirectory dir.dir
test filesystem-1.30 {normalisation of nonexistent user} -body {
test filesystem-1.30 {
    normalisation of nonexistent user - verify no tilde expansion
} -body {
    file normalize ~noonewiththisname
} -returnCodes error -result {user "noonewiththisname" doesn't exist}
} -result [file join [pwd] ~noonewiththisname]
test filesystem-1.30.1 {normalisation of existing user} -body {
    catch {file normalize ~$::tcl_platform(user)}
} -result {0}
test filesystem-1.30.2 {normalisation of nonexistent user specified as user@domain} -body {
    file normalize ~nonexistentuser@nonexistentdomain
} -returnCodes error -result {user "nonexistentuser@nonexistentdomain" doesn't exist}
    file normalize ~$::tcl_platform(user)
} -result [file join [pwd] ~$::tcl_platform(user)]
test filesystem-1.30.3 {file normalization should distinguish between ~ and ~user} -setup {
    set oldhome $::env(HOME)
    set olduserhome [file home $::tcl_platform(user)]
    set ::env(HOME) [file join $oldhome temp]
} -cleanup {
    set ::env(HOME) $oldhome
} -body {
    list [string equal [file home] $::env(HOME)] \
	[string equal $olduserhome [file home $::tcl_platform(user)]]
} -result {1 1}
test filesystem-1.31 {link normalisation: link near filesystem root} {testsetplatform} {
    testsetplatform unix
    file normalize /foo/../bar
} {/bar}
test filesystem-1.32 {link normalisation: link near filesystem root} {testsetplatform} {
    testsetplatform unix
    file normalize /../bar
} {/bar}
test filesystem-1.33 {link normalisation: link near filesystem root} {testsetplatform} {
    testsetplatform windows
    set res [file normalize C:/../bar]
    if {[testConstraint unix]} {
	# Some unices go further in normalizing this -- not really a problem
	# Some Unices go further in normalizing this -- not really a problem
	# since this is a Windows test.
	regexp {C:/bar$} $res res
    }
    set res
} {C:/bar}
if {[testConstraint testsetplatform]} {
    testsetplatform $platform
312
313
314
315
316
317
318
319

320
321
322
323
324
325
326
324
325
326
327
328
329
330

331
332
333
334
335
336
337
338







-
+







} 1
test filesystem-1.37 {file normalisation with '/./'} -body {
    set fname "/abc/./def/./ghi/./asda/.././.././asd/x/../../../../....."
    file norm $fname
} -match regexp -result {^(?:[^/]|/(?:[^/]|$))+$}
test filesystem-1.38 {file normalisation with volume relative} -setup {
    set dir [pwd]
} -constraints {win moreThanOneDrive knownMsvcBug} -body {
} -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 {
373
374
375
376
377
378
379
380
381


382
383
384
385
386

387
388
389
390
391
392
393
385
386
387
388
389
390
391


392
393
394
395
396
397

398
399
400
401
402
403
404
405







-
-
+
+




-
+







} ok
test filesystem-1.51 {file normalisation .. beyond root (Bug 1379287)} {
    testPathEqual [file norm /../..] [file norm /]
} ok
test filesystem-1.51.1 {file normalisation .. beyond root (Bug 1379287)} {
    testPathEqual [file norm /../../] [file norm /]
} ok
test filesystem-1.52 {bug f9f390d0fa: file join where strep is not canonical} -constraints unix -body {
    set x //foo
test filesystem-1.52 {bug f9f390d0fa: file join where strep is not canonical} -body {
    set x ///foo
    file normalize $x
    file join $x bar
} -result /foo/bar
test filesystem-1.52.1 {bug f9f390d0fa: file join where strep is not canonical} -body {
    set x //foo
    set x ///foo
    file normalize $x
    file join $x
} -result /foo
test filesystem-1.53 {[Bug 3559678] - normalize when tail is empty} {
  string match */ [file normalize [lindex [glob -dir [pwd] {{}}] 0]]
} 0
test filesystem-1.54 {[Bug ce3a211dcb] - normalize when tail is empty} -setup {
467
468
469
470
471
472
473

474



475
476
477
478
479
480
481
479
480
481
482
483
484
485
486

487
488
489
490
491
492
493
494
495
496







+
-
+
+
+







    testfilesystem 1
    set filesystemReport {}
    catch {glob *}
    testfilesystem 0
    return $filesystemReport
} -match glob -result {*{matchindirectory *}*}

# This test is meaningless if there is no tilde expansion
test filesystem-5.1 {cache and ~} -constraints testfilesystem -setup {
test filesystem-5.1 {cache and ~} -constraints {
    testfilesystem tildeexpansion
} -setup {
    set orig $::env(HOME)
} -body {
    set ::env(HOME) /foo/bar/blah
    set testdir ~
    set res1 "Parent of ~ (/foo/bar/blah) is [file dirname $testdir]"
    set ::env(HOME) /a/b/c
    set res2 "Parent of ~ (/a/b/c) is [file dirname $testdir]"
558
559
560
561
562
563
564

565







566
567
568

569
570
571
572
573
574
575
576
577
578

579







580
581
582
583
584
585
586
573
574
575
576
577
578
579
580

581
582
583
584
585
586
587
588
589

590
591
592
593
594
595
596
597
598
599
600
601

602
603
604
605
606
607
608
609
610
611
612
613
614
615







+
-
+
+
+
+
+
+
+


-
+










+
-
+
+
+
+
+
+
+







    while {![catch {testfilesystem 0}]} {}
}

test filesystem-7.1.1 {load from vfs} -setup {
    set dir [pwd]
} -constraints {win testsimplefilesystem loaddll} -body {
    # This may cause a crash on exit
    if {[file dirname $::ddelib] ne "."} {
    cd [file dirname $::ddelib]
	cd [file dirname $::ddelib]
    } else {
	cd [file dirname [info nameofexecutable]]
    }
    if {![file exists [file tail $::ddelib]]} {
	::tcltest::Skip "no-ddelib"
    }
    testsimplefilesystem 1
    # This loads dde via a complex copy-to-temp operation
    load simplefs:/[file tail $::ddelib] dde
    load simplefs:/[file tail $::ddelib] Dde
    testsimplefilesystem 0
    return ok
    # The real result of this test is what happens when Tcl exits.
} -cleanup {
    cd $dir
} -result ok
test filesystem-7.1.2 {load from vfs, and then unload again} -setup {
    set dir [pwd]
} -constraints {win testsimplefilesystem loaddll} -body {
    # This may cause a crash on exit
    if {[file dirname $::reglib] ne "."} {
    cd [file dirname $::reglib]
	cd [file dirname $::reglib]
    } else {
	cd [file dirname [info nameofexecutable]]
    }
    if {![file exists [file tail $::reglib]]} {
	::tcltest::Skip "no-reglib"
    }
    testsimplefilesystem 1
    # This loads reg via a complex copy-to-temp operation
    load simplefs:/[file tail $::reglib] Registry
    unload simplefs:/[file tail $::reglib]
    testsimplefilesystem 0
    return ok
    # The real result of this test is what happens when Tcl exits.
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
707
708

709
710
711
712
713
714
715
705
706
707
708
709
710
711

712
713
714
715
716
717
718
719
720
721
722
723

724
725
726
727
728
729
730
731
732
733
734
735
736

737
738
739
740
741
742
743
744







-
+











-
+












-
+







    lappend res $err
    lappend res [file exists file2]
} -cleanup {
    catch {testsimplefilesystem 0}
    file delete -force simplefile
    file delete -force file2
    cd $dir
} -result {0 {} 1 {error copying "simplefs:/simplefile" to "file2": file already exists} 0 {} 1}
} -result {0 {} 1 {error copying "simplefs:/simplefile" to "file2": file exists} 0 {} 1}
test filesystem-7.5 {cross-filesystem file copy with -force} -setup {
    set dir [pwd]
    cd [tcltest::temporaryDirectory]
    set fout [open [file join simplefile] w]
    puts -nonewline $fout "1234567890"
    close $fout
    testsimplefilesystem 1
} -constraints {testsimplefilesystem unix} -body {
    # First copy should succeed
    set res [catch {file copy simplefs:/simplefile file2} err]
    lappend res $err
    file attributes file2 -permissions 0000
    file attributes file2 -permissions 0
    # Second copy should fail (no -force)
    lappend res [catch {file copy simplefs:/simplefile file2} err]
    lappend res $err
    # Third copy should succeed (-force)
    lappend res [catch {file copy -force simplefs:/simplefile file2} err]
    lappend res $err
    lappend res [file exists file2]
} -cleanup {
    testsimplefilesystem 0
    file delete -force simplefile
    file delete -force file2
    cd $dir
} -result {0 {} 1 {error copying "simplefs:/simplefile" to "file2": file already exists} 0 {} 1}
} -result {0 {} 1 {error copying "simplefs:/simplefile" to "file2": file exists} 0 {} 1}
test filesystem-7.6 {cross-filesystem dir copy with -force} -setup {
    set dir [pwd]
    cd [tcltest::temporaryDirectory]
    file delete -force simpledir
    file mkdir simpledir
    file mkdir dir2
    set fout [open [file join simpledir simplefile] w]
729
730
731
732
733
734
735
736

737
738
739
740
741
742
743
758
759
760
761
762
763
764

765
766
767
768
769
770
771
772







-
+







    lappend res [file exists [file join dir2 simpledir]] \
	    [file exists [file join dir2 simpledir simplefile]]
} -cleanup {
    testsimplefilesystem 0
    file delete -force simpledir
    file delete -force dir2
    cd $dir
} -result {0 {} 1 {error copying "simplefs:/simpledir" to "dir2/simpledir": file already exists} 0 {} 1 1}
} -result {0 {} 1 {error copying "simplefs:/simpledir" to "dir2/simpledir": file exists} 0 {} 1 1}
test filesystem-7.7 {cross-filesystem dir copy with -force} -setup {
    set dir [pwd]
    cd [tcltest::temporaryDirectory]
    file delete -force simpledir
    file mkdir simpledir
    file mkdir dir2
    set fout [open [file join simpledir simplefile] w]
759
760
761
762
763
764
765
766

767
768
769
770
771
772
773
788
789
790
791
792
793
794

795
796
797
798
799
800
801
802







-
+







    lappend res [file exists [file join dir2 simpledir]] \
	    [file exists [file join dir2 simpledir simplefile]]
} -cleanup {
    testsimplefilesystem 0
    file delete -force simpledir
    file delete -force dir2
    cd $dir
} -result {0 {} 1 {error copying "simplefs:/simpledir" to "dir2/simpledir": file already exists} 0 {} 1 1}
} -result {0 {} 1 {error copying "simplefs:/simpledir" to "dir2/simpledir": file exists} 0 {} 1 1}
removeFile gorp.file
test filesystem-7.8 {vfs cd} -setup {
    set dir [pwd]
    cd [tcltest::temporaryDirectory]
    file delete -force simpledir
    file mkdir simpledir
    testsimplefilesystem 1
933
934
935
936
937
938
939
940

941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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







-
+

















-
+

















-
+







    lappend res $file
    lappend res [file exists $file] [catch {file tail $file} r] $r
    lappend res [catch {file tail $file} r] $r
} -cleanup {
    cd [tcltest::temporaryDirectory]
    file delete -force tilde
    cd $origdir
} -result {0 1 {user "testNotExist" doesn't exist} ~testNotExist 0 1 {user "testNotExist" doesn't exist} 1 {user "testNotExist" doesn't exist}}
} -result {1 0 ~testNotExist ~testNotExist 1 0 ~testNotExist 0 ~testNotExist}
test filesystem-9.8 {path objects and glob and file tail and tilde} -setup {
    set res {}
    set origdir [pwd]
    cd [tcltest::temporaryDirectory]
} -body {
    file mkdir tilde
    close [open tilde/~testNotExist w]
    cd tilde
    set file1 [lindex [glob *test*] 0]
    set file2 "~testNotExist"
    lappend res $file1 $file2
    lappend res [catch {file tail $file1} r] $r
    lappend res [catch {file tail $file2} r] $r
} -cleanup {
    cd [tcltest::temporaryDirectory]
    file delete -force tilde
    cd $origdir
} -result {~testNotExist ~testNotExist 1 {user "testNotExist" doesn't exist} 1 {user "testNotExist" doesn't exist}}
} -result {~testNotExist ~testNotExist 0 ~testNotExist 0 ~testNotExist}
test filesystem-9.9 {path objects and glob and file tail and tilde} -setup {
    set res {}
    set origdir [pwd]
    cd [tcltest::temporaryDirectory]
} -body {
    file mkdir tilde
    close [open tilde/~testNotExist w]
    cd tilde
    set file1 [lindex [glob *test*] 0]
    set file2 "~testNotExist"
    lappend res [catch {file exists $file1} r] $r
    lappend res [catch {file exists $file2} r] $r
    lappend res [string equal $file1 $file2]
} -cleanup {
    cd [tcltest::temporaryDirectory]
    file delete -force tilde
    cd $origdir
} -result {0 0 0 0 1}
} -result {0 1 0 1 1}

# ----------------------------------------------------------------------

test filesystem-10.1 {Bug 3414754} {
    string match */ [file join [pwd] foo/]
} 0

Changes to tests/fileSystemEncoding.test.

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
30

31
32
33
34
35
36
37
38
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


-
+












-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
-







#!  /usr/bin/env tclsh

# Copyright (c) 2019 Poor Yorick
# Copyright © 2019 Poor Yorick

if {[string equal $::tcl_platform(os) "Windows NT"]} {
    return
}

namespace eval ::tcl::test::fileSystemEncoding {

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

    variable fname1 \u767b\u9e1b\u9d72\u6a13
    variable fname1 登鸛鵲樓

    proc autopath {} {
	global auto_path
	set scriptpath [info script]
	set scriptpathnorm [file dirname [file normalize $scriptpath/...]]
	set dirnorm [file dirname $scriptpathnorm]
	set idx [lsearch -exact $auto_path $dirnorm]
	if {$idx >= 0} {
	    set auto_path [lreplace $auto_path[set auto_path {}] $idx $idx {}]
	}
	set auto_path [linsert $auto_path[set auto_path {}] 0 0 $dirnorm]
    }
    autopath

    source [file join [file dirname [info script]] tcltests.tcl]
    package require tcltests

    test filesystemEncoding-1.0 {
	issue bcd100410465
    } -body {
	set dir [tcltests::tempdir]
	set saved [encoding system]
	encoding system iso8859-1

Changes to tests/for-old.test.

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
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
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
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








-
-
+
+














-
+






-
-
+
+






-
-
+
+
















-
+




-
+








# Commands covered:  for, continue, break
#
# This file contains the original set of tests for Tcl's for command.
# Since the for command is now compiled, a new set of tests covering
# the new implementation is in the file "for.test". Sourcing this file
# into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
#
# 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::*
}

# Check "for" and its use of continue and break.

catch {unset a i}
test for-old-1.1 {for tests} {
    set a {}
    for {set i 1} {$i<6} {set i [expr $i+1]} {
    for {set i 1} {$i<6} {incr i} {
	set a [concat $a $i]
    }
    set a
} {1 2 3 4 5}
test for-old-1.2 {for tests} {
    set a {}
    for {set i 1} {$i<6} {set i [expr $i+1]} {
	if $i==4 continue
    for {set i 1} {$i<6} {incr i} {
	if {$i==4} continue
	set a [concat $a $i]
    }
    set a
} {1 2 3 5}
test for-old-1.3 {for tests} {
    set a {}
    for {set i 1} {$i<6} {set i [expr $i+1]} {
	if $i==4 break
    for {set i 1} {$i<6} {incr i} {
	if {$i==4} break
	set a [concat $a $i]
    }
    set a
} {1 2 3}
test for-old-1.4 {for tests} {catch {for 1 2 3} msg} 1
test for-old-1.5 {for tests} {
    catch {for 1 2 3} msg
    set msg
} {wrong # args: should be "for start test next command"}
test for-old-1.6 {for tests} {catch {for 1 2 3 4 5} msg} 1
test for-old-1.7 {for tests} {
    catch {for 1 2 3 4 5} msg
    set msg
} {wrong # args: should be "for start test next command"}
test for-old-1.8 {for tests} {
    set a {xyz}
    for {set i 1} {$i<6} {set i [expr $i+1]} {}
    for {set i 1} {$i<6} {incr i} {}
    set a
} xyz
test for-old-1.9 {for tests} {
    set a {}
    for {set i 1} {$i<6} {set i [expr $i+1]; if $i==4 break} {
    for {set i 1} {$i<6} {incr i; if {$i==4} break} {
	set a [concat $a $i]
    }
    set a
} {1 2 3}

# cleanup
::tcltest::cleanupTests
return

Changes to tests/for.test.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







# Commands covered:  for, continue, break
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1996 Sun Microsystems, Inc.
# Copyright © 1996 Sun Microsystems, Inc.
#
# 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::*
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
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







-
-
+
+






-
+










-
+










-
-
-
+
+
+







    set ::errorInfo
} -match glob -result {wrong # args: should be "set varName ?newValue?"
    while *ing
"set"*}
catch {unset a}
test for-1.9 {TclCompileForCmd: simple command body} {
    set a {}
    for {set i 1} {$i<6} {set i [expr $i+1]} {
	if $i==4 break
    for {set i 1} {$i<6} {incr i} {
	if {$i==4} break
	set a [concat $a $i]
    }
    set a
} {1 2 3}
test for-1.10 {TclCompileForCmd: command body in quotes} {
    set a {}
    for {set i 1} {$i<6} {set i [expr $i+1]} "append a x"
    for {set i 1} {$i<6} {incr i} "append a x"
    set a
} {xxxxx}
test for-1.11 {TclCompileForCmd: computed command body} {
    catch {unset x1}
    catch {unset bb}
    catch {unset x2}
    set x1 {append a x1; }
    set bb {break}
    set x2 {; append a x2}
    set a {}
    for {set i 1} {$i<6} {set i [expr $i+1]} $x1$bb$x2
    for {set i 1} {$i<6} {incr i} $x1$bb$x2
    set a
} {x1}
test for-1.12 {TclCompileForCmd: error in "next" command} -body {
    catch {for {set i 0} {$i < 5} {set} {format $i}} msg
    set ::errorInfo
} -match glob -result {wrong # args: should be "set varName ?newValue?"
    while *ing
"set"*}
test for-1.13 {TclCompileForCmd: long command body} {
    set a {}
    for {set i 1} {$i<6} {set i [expr $i+1]} {
	if $i==4 break
	if $i>5 continue
    for {set i 1} {$i<6} {incr i} {
	if {$i==4} break
	if {$i>5} continue
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
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
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







-
+














-
+







-
+









-
-
-
+
+
+





-
-
-
-
+
+
+
+







    set a
} {1 2 3}
test for-1.14 {TclCompileForCmd: for command result} {
    set a [for {set i 0} {$i < 5} {incr i} {}]
    set a
} {}
test for-1.15 {TclCompileForCmd: for command result} {
    set a [for {set i 0} {$i < 5} {incr i} {if $i==3 break}]
    set a [for {set i 0} {$i < 5} {incr i} {if {$i==3} break}]
    set a
} {}

# Check "for" and "continue".

test for-2.1 {TclCompileContinueCmd: arguments after "continue"} {
    catch {continue foo} msg
    set msg
} {wrong # args: should be "continue"}
test for-2.2 {TclCompileContinueCmd: continue result} {
    catch continue
} 4
test for-2.3 {continue tests} {
    set a {}
    for {set i 1} {$i <= 4} {set i [expr $i+1]} {
    for {set i 1} {$i <= 4} {incr i} {
	if {$i == 2} continue
	set a [concat $a $i]
    }
    set a
} {1 3 4}
test for-2.4 {continue tests} {
    set a {}
    for {set i 1} {$i <= 4} {set i [expr $i+1]} {
    for {set i 1} {$i <= 4} {incr i} {
	if {$i != 2} continue
	set a [concat $a $i]
    }
    set a
} {2}
test for-2.5 {continue tests, nested loops} {
    set msg {}
    for {set i 1} {$i <= 4} {incr i} {
	for {set a 1} {$a <= 2} {incr a} {
            if {$i>=2 && $a>=2} continue
            set msg [concat $msg "$i.$a"]
        }
	    if {$i>=2 && $a>=2} continue
	    set msg [concat $msg "$i.$a"]
	}
    }
    set msg
} {1.1 1.2 2.1 3.1 4.1}
test for-2.6 {continue tests, long command body} {
    set a {}
    for {set i 1} {$i<6} {set i [expr $i+1]} {
	if $i==2 continue
	if $i==4 break
	if $i>5 continue
    for {set i 1} {$i<6} {incr i} {
	if {$i==2} continue
	if {$i==4} break
	if {$i>5} continue
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
201
202
203
204
205
206
207
208

209
210
211
212
213
214
215
201
202
203
204
205
206
207

208
209
210
211
212
213
214
215







-
+







	}
	set a [concat $a $i]
    }
    set a
} {1 3}
test for-2.7 {continue tests, uncompiled [for]} -body {
    set file [makeFile {
    	set guard 0
	set guard 0
	for {set i 20} {$i > 0} {incr i -1} {
	    if {[incr guard]>30} {return BAD}
	    continue
	}
	return GOOD
    } source.file]
    source $file
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
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







-
-
-
+
+
+





-
-
-
-
+
+
+
+















-
+


















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    }
    set a
} {1 2}
test for-3.4 {break tests, nested loops} {
    set msg {}
    for {set i 1} {$i <= 4} {incr i} {
	for {set a 1} {$a <= 2} {incr a} {
            if {$i>=2 && $a>=2} break
            set msg [concat $msg "$i.$a"]
        }
	    if {$i>=2 && $a>=2} break
	    set msg [concat $msg "$i.$a"]
	}
    }
    set msg
} {1.1 1.2 2.1 3.1 4.1}
test for-3.5 {break tests, long command body} {
    set a {}
    for {set i 1} {$i<6} {set i [expr $i+1]} {
	if $i==2 continue
	if $i==5 break
	if $i>5 continue
    for {set i 1} {$i<6} {incr i} {
	if {$i==2} continue
	if {$i==5} break
	if {$i>5} continue
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	if $i==4 break
	if {$i==4} break
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	set a [concat $a $i]
    }
    set a
} {1 3}
# A simplified version of exmh's mail formatting routine to stress "for",
# "break", "while", and "if".
proc formatMail {} {
    array set lines {
        0 {Return-path: george@tcl} \
        1 {Return-path: <george@tcl>} \
        2 {Received: from tcl by tcl.Somewhere.COM (SMI-8.6/SMI-SVR4)} \
        3 {	id LAA10027; Wed, 11 Sep 1996 11:14:53 -0700} \
        4 {Message-id: <199609111814.LAA10027@tcl.Somewhere.COM>} \
        5 {X-mailer: exmh version 1.6.9 8/22/96} \
        6 {Mime-version: 1.0} \
        7 {Content-type: text/plain; charset=iso-8859-1} \
        8 {Content-transfer-encoding: quoted-printable} \
        9 {Content-length: 2162} \
        10 {To: fred} \
        11 {Subject: tcl7.6} \
        12 {Date: Wed, 11 Sep 1996 11:14:53 -0700} \
        13 {From: George <george@tcl>} \
        14 {The Tcl 7.6 and Tk 4.2 releases} \
        15 {} \
        16 {This page contains information about Tcl 7.6 and Tk4.2, which are the most recent} \
        17 {releases of the Tcl scripting language and the Tk toolkit. The first beta versions of these} \
        18 {releases were released on August 30, 1996. These releases contain only minor changes,} \
        19 {so we hope to have only a single beta release and to go final in early October, 1996.} \
        20 {} \
        21 {} \
        22 {What's new} \
        23 {} \
        24 {The most important changes in the releases are summarized below. See the README} \
        25 {and changes files in the distributions for more complete information on what has} \
        26 {changed, including both feature changes and bug fixes.} \
        27 {} \
        28 {     There are new options to the file command for copying files (file copy),} \
        29 {     deleting files and directories (file delete), creating directories (file} \
        30 {     mkdir), and renaming files (file rename).} \
        31 {     The implementation of exec has been improved greatly for Windows 95 and} \
        32 {     Windows NT.} \
        33 {     There is a new memory allocator for the Macintosh version, which should be} \
        34 {     more efficient than the old one.} \
        35 {     Tk's grid geometry manager has been completely rewritten. The layout} \
        36 {     algorithm produces much better layouts than before, especially where rows or} \
        37 {     columns were stretchable.} \
        38 {     There are new commands for creating common dialog boxes:} \
        39 {     tk_chooseColor, tk_getOpenFile, tk_getSaveFile and} \
        40 {     tk_messageBox. These use native dialog boxes if they are available.} \
        41 {     There is a new virtual event mechanism for handling events in a more portable} \
        42 {     way. See the new command event. It also allows events (both physical and} \
        43 {     virtual) to be generated dynamically.} \
        44 {} \
        45 {Tcl 7.6 and Tk 4.2 are backwards-compatible with Tcl 7.5 and Tk 4.1 except for} \
        46 {changes in the C APIs for custom channel drivers. Scripts written for earlier releases} \
        47 {should work on these new releases as well.} \
        48 {} \
        49 {Obtaining The Releases} \
        50 {} \
        51 {Binary Releases} \
        52 {} \
        53 {Pre-compiled releases are available for the following platforms: } \
        54 {} \
        55 {     Windows 3.1, Windows 95, and Windows NT: Fetch} \
        56 {     ftp://ftp.sunlabs.com/pub/tcl/win42b1.exe, then execute it. The file is a} \
        57 {     self-extracting executable. It will install the Tcl and Tk libraries, the wish and} \
        58 {     tclsh programs, and documentation.} \
        59 {     Macintosh (both 68K and PowerPC): Fetch} \
        60 {     ftp://ftp.sunlabs.com/pub/tcl/mactk4.2b1.sea.hqx. The file is in binhex format,} \
        61 {     which is understood by Fetch, StuffIt, and many other Mac utilities. The} \
        62 {     unpacked file is a self-installing executable: double-click on it and it will create a} \
        63 {     folder containing all that you need to run Tcl and Tk. } \
        64 {        UNIX (Solaris 2.* and SunOS, other systems soon to follow). Easy to install} \
        65 {     binary packages are now for sale at the Sun Labs Tcl/Tk Shop. Check it out!} \
	0 {Return-path: george@tcl} \
	1 {Return-path: <george@tcl>} \
	2 {Received: from tcl by tcl.Somewhere.COM (SMI-8.6/SMI-SVR4)} \
	3 {	id LAA10027; Wed, 11 Sep 1996 11:14:53 -0700} \
	4 {Message-id: <199609111814.LAA10027@tcl.Somewhere.COM>} \
	5 {X-mailer: exmh version 1.6.9 8/22/96} \
	6 {Mime-version: 1.0} \
	7 {Content-type: text/plain; charset=iso-8859-1} \
	8 {Content-transfer-encoding: quoted-printable} \
	9 {Content-length: 2162} \
	10 {To: fred} \
	11 {Subject: tcl7.6} \
	12 {Date: Wed, 11 Sep 1996 11:14:53 -0700} \
	13 {From: George <george@tcl>} \
	14 {The Tcl 7.6 and Tk 4.2 releases} \
	15 {} \
	16 {This page contains information about Tcl 7.6 and Tk4.2, which are the most recent} \
	17 {releases of the Tcl scripting language and the Tk toolkit. The first beta versions of these} \
	18 {releases were released on August 30, 1996. These releases contain only minor changes,} \
	19 {so we hope to have only a single beta release and to go final in early October, 1996.} \
	20 {} \
	21 {} \
	22 {What's new} \
	23 {} \
	24 {The most important changes in the releases are summarized below. See the README} \
	25 {and changes files in the distributions for more complete information on what has} \
	26 {changed, including both feature changes and bug fixes.} \
	27 {} \
	28 {     There are new options to the file command for copying files (file copy),} \
	29 {     deleting files and directories (file delete), creating directories (file} \
	30 {     mkdir), and renaming files (file rename).} \
	31 {     The implementation of exec has been improved greatly for Windows 95 and} \
	32 {     Windows NT.} \
	33 {     There is a new memory allocator for the Macintosh version, which should be} \
	34 {     more efficient than the old one.} \
	35 {     Tk's grid geometry manager has been completely rewritten. The layout} \
	36 {     algorithm produces much better layouts than before, especially where rows or} \
	37 {     columns were stretchable.} \
	38 {     There are new commands for creating common dialog boxes:} \
	39 {     tk_chooseColor, tk_getOpenFile, tk_getSaveFile and} \
	40 {     tk_messageBox. These use native dialog boxes if they are available.} \
	41 {     There is a new virtual event mechanism for handling events in a more portable} \
	42 {     way. See the new command event. It also allows events (both physical and} \
	43 {     virtual) to be generated dynamically.} \
	44 {} \
	45 {Tcl 7.6 and Tk 4.2 are backwards-compatible with Tcl 7.5 and Tk 4.1 except for} \
	46 {changes in the C APIs for custom channel drivers. Scripts written for earlier releases} \
	47 {should work on these new releases as well.} \
	48 {} \
	49 {Obtaining The Releases} \
	50 {} \
	51 {Binary Releases} \
	52 {} \
	53 {Precompiled releases are available for the following platforms: } \
	54 {} \
	55 {     Windows 3.1, Windows 95, and Windows NT: Fetch} \
	56 {     ftp://ftp.sunlabs.com/pub/tcl/win42b1.exe, then execute it. The file is a} \
	57 {     self-extracting executable. It will install the Tcl and Tk libraries, the wish and} \
	58 {     tclsh programs, and documentation.} \
	59 {     Macintosh (both 68K and PowerPC): Fetch} \
	60 {     ftp://ftp.sunlabs.com/pub/tcl/mactk4.2b1.sea.hqx. The file is in binhex format,} \
	61 {     which is understood by Fetch, StuffIt, and many other Mac utilities. The} \
	62 {     unpacked file is a self-installing executable: double-click on it and it will create a} \
	63 {     folder containing all that you need to run Tcl and Tk. } \
	64 {        UNIX (Solaris 2.* and SunOS, other systems soon to follow). Easy to install} \
	65 {     binary packages are now for sale at the Sun Labs Tcl/Tk Shop. Check it out!} \
    }
    set result ""
    set NL "
"
    set tag {level= type=text/plain part=0 sel Charset}
    set ix [lsearch -regexp $tag text/enriched]
    if {$ix < 0} {
382
383
384
385
386
387
388
389

390
391
392
393
394
395
396
382
383
384
385
386
387
388

389
390
391
392
393
394
395
396







-
+







	    if {[regexp {^[ 	]*$} $line] || [regexp {^--+} $line]} {
		set inheaders 0
	    }
	    if {[regexp -nocase {^x-mailer:} $line]} {
		continue
	    }
	}
	if $inheaders {
	if {$inheaders} {
	    set limit 55
	} else {
	    set limit 55
	    # Decide whether or not to break the body line
	    if {$plen > 0} {
		if {[string first {> } $line] == 0} {
		    # This is quoted text from previous message, don't reformat
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
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







-
+




-
+










-
+







		append result $line $NL
		if {[string length $F1] == 0} {
		    set F1 -1
		}
		continue
	    }
	}
	set climit [expr $limit-1]
	set climit [expr {$limit-1}]
	set cutoff 50
	set continuation 0

	while {[string length $line] > $limit} {
	    for {set c [expr $limit-1]} {$c >= $cutoff} {incr c -1} {
	    for {set c [expr {$limit-1}]} {$c >= $cutoff} {incr c -1} {
		set char [string index $line $c]
		if {$char == " " || $char == "\t"} {
		    break
		}
		if {$char == ">"} {	;# Hack for enriched formatting
		    break
		}
	    }
	    if {$c < $cutoff} {
		if {! $inheaders} {
		    set c [expr $limit-1]
		    set c [expr {$limit-1}]
		} else {
		    set c [string length $line]
		}
	    }
	    set newline [string trimright [string range $line 0 $c]]
	    if {! $continuation} {
		append result $newline $NL
552
553
554
555
556
557
558
559

560
561
562
563
564
565
566
552
553
554
555
556
557
558

559
560
561
562
563
564
565
566







-
+







ts written for earlier releases
should work on these new releases as well.

Obtaining The Releases

Binary Releases

Pre-compiled releases are available for the following
Precompiled releases are available for the following
platforms:

     Windows 3.1, Windows 95, and Windows NT: Fetch
     ftp://ftp.sunlabs.com/pub/tcl/win42b1.exe, then
execute it. The file is a
     self-extracting executable. It will install the
Tcl and Tk libraries, the wish and
580
581
582
583
584
585
586
587
588
589
590




591
592
593
594
595
596
597
580
581
582
583
584
585
586




587
588
589
590
591
592
593
594
595
596
597







-
-
-
-
+
+
+
+







Tcl/Tk Shop. Check it out!
}

# Check that "break" resets the interpreter's result

test for-4.1 {break must reset the interp result} {
    catch {
        set z GLOBTESTDIR/dir2/file2.c
        if [string match GLOBTESTDIR/dir2/* $z] {
            break
        }
	set z GLOBTESTDIR/dir2/file2.c
	if {[string match GLOBTESTDIR/dir2/* $z]} {
	    break
	}
    } j
    set j
} {}

# Test for incorrect "double evaluation" semantics

test for-5.1 {possible delayed substitution of increment command} {
692
693
694
695
696
697
698
699
700


701
702
703
704
705
706
707
708

709
710
711
712
713
714
715
716
717
718
719
720

721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738



739
740
741
742
743
744
745
692
693
694
695
696
697
698


699
700
701
702
703
704
705
706
707

708
709
710
711
712
713
714
715
716
717
718
719

720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735



736
737
738
739
740
741
742
743
744
745







-
-
+
+







-
+











-
+















-
-
-
+
+
+







"set"
    ("for" body line 1)
    invoked from within
"$z {set i 0} {$i < 5} {incr i} {set}"}
test for-6.10 {Tcl_ForObjCmd: simple command body} {
    set z for
    set a {}
    $z {set i 1} {$i<6} {set i [expr $i+1]} {
	if $i==4 break
    $z {set i 1} {$i<6} {incr i} {
	if {$i==4} break
	set a [concat $a $i]
    }
    set a
} {1 2 3}
test for-6.11 {Tcl_ForObjCmd: command body in quotes} {
    set z for
    set a {}
    $z {set i 1} {$i<6} {set i [expr $i+1]} "append a x"
    $z {set i 1} {$i<6} {incr i} "append a x"
    set a
} {xxxxx}
test for-6.12 {Tcl_ForObjCmd: computed command body} {
    set z for
    catch {unset x1}
    catch {unset bb}
    catch {unset x2}
    set x1 {append a x1; }
    set bb {break}
    set x2 {; append a x2}
    set a {}
    $z {set i 1} {$i<6} {set i [expr $i+1]} $x1$bb$x2
    $z {set i 1} {$i<6} {incr i} $x1$bb$x2
    set a
} {x1}
test for-6.13 {Tcl_ForObjCmd: error in "next" command} -body {
    set z for
    catch {$z {set i 0} {$i < 5} {set} {set j 4}} msg
    set ::errorInfo
} -match glob -result {wrong # args: should be "set varName ?newValue?"
    while *ing
"set"
    ("for" loop-end command)
    invoked from within
"$z {set i 0} {$i < 5} {set} {set j 4}"}
test for-6.14 {Tcl_ForObjCmd: long command body} {
    set z for
    set a {}
    $z {set i 1} {$i<6} {set i [expr $i+1]} {
	if $i==4 break
	if $i>5 continue
    $z {set i 1} {$i<6} {incr i} {
	if {$i==4} break
	if {$i>5} continue
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
773
774
775
776
777
778
779
780
781
782
783
784
785






786
787
788
789
790
791
792
793
794
795
796

797
798
799

800
801
802

803
804
805

806
807
808

809
810
811

812
813
814
815
816
817
818
819






820
821
822
823
824
825
826
773
774
775
776
777
778
779






780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

796
797
798

799
800
801

802
803
804

805
806
807

808
809
810

811
812
813






814
815
816
817
818
819
820
821
822
823
824
825
826







-
-
-
-
-
-
+
+
+
+
+
+










-
+


-
+


-
+


-
+


-
+


-
+


-
-
-
-
-
-
+
+
+
+
+
+







test for-6.16 {Tcl_ForObjCmd: for command result} {
    set z for
    set a [$z {set i 0} {$i < 5} {incr i} {if $i==3 break}]
    set a
} {}
test for-6.17 {Tcl_ForObjCmd: for command result} {
    list \
        [catch {for {break} {1} {} {}} err] $err \
        [catch {for {continue} {1} {} {}} err] $err \
        [catch {for {} {[break]} {} {}} err] $err \
        [catch {for {} {[continue]} {} {}} err] $err \
        [catch {for {} {1} {break} {}} err] $err \
        [catch {for {} {1} {continue} {}} err] $err \
	[catch {for {break} {1} {} {}} err] $err \
	[catch {for {continue} {1} {} {}} err] $err \
	[catch {for {} {[break]} {} {}} err] $err \
	[catch {for {} {[continue]} {} {}} err] $err \
	[catch {for {} {1} {break} {}} err] $err \
	[catch {for {} {1} {continue} {}} err] $err \
} [list \
    3 {} \
    4 {} \
    3 {} \
    4 {} \
    0 {} \
    4 {} \
    ]
test for-6.18 {Tcl_ForObjCmd: for command result} {
    proc p6181 {} {
        for {break} {1} {} {}
	for {break} {1} {} {}
    }
    proc p6182 {} {
        for {continue} {1} {} {}
	for {continue} {1} {} {}
    }
    proc p6183 {} {
        for {} {[break]} {} {}
	for {} {[break]} {} {}
    }
    proc p6184 {} {
        for {} {[continue]} {} {}
	for {} {[continue]} {} {}
    }
    proc p6185 {} {
        for {} {1} {break} {}
	for {} {1} {break} {}
    }
    proc p6186 {} {
        for {} {1} {continue} {}
	for {} {1} {continue} {}
    }
    list \
        [catch {p6181} err] $err \
        [catch {p6182} err] $err \
        [catch {p6183} err] $err \
        [catch {p6184} err] $err \
        [catch {p6185} err] $err \
        [catch {p6186} err] $err
	[catch {p6181} err] $err \
	[catch {p6182} err] $err \
	[catch {p6183} err] $err \
	[catch {p6184} err] $err \
	[catch {p6185} err] $err \
	[catch {p6186} err] $err
} [list \
    1 {invoked "break" outside of a loop} \
    1 {invoked "continue" outside of a loop} \
    1 {invoked "break" outside of a loop} \
    1 {invoked "continue" outside of a loop} \
    0 {} \
    1 {invoked "continue" outside of a loop} \

Changes to tests/foreach.test.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







# Commands covered:  foreach, continue, break
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
#
# 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::*
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
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







-
-
-
+
+
+





-
-
-
+
+
+







-
-
-
-
-
-
+
+
+
+
+
+








-
-
+
+







    foreach a {} b {1 2 3} c {1 2} d {1 2 3 4} e {{1 2}} {
	append x $a $b $c $d $e
    }
    set x
} {1111 2222334}
test foreach-2.8 {foreach only sets vars if repeating loop} {
    proc foo {} {
        set rgb {65535 0 0}
        foreach {r g b} [set rgb] {}
        return "r=$r, g=$g, b=$b"
	set rgb {65535 0 0}
	foreach {r g b} [set rgb] {}
	return "r=$r, g=$g, b=$b"
    }
    foo
} {r=65535, g=0, b=0}
test foreach-2.9 {foreach only supports local scalar variables} {
    proc foo {} {
        set x {}
        foreach {a(3)} {1 2 3 4} {lappend x [set {a(3)}]}
        set x
	set x {}
	foreach {a(3)} {1 2 3 4} {lappend x [set {a(3)}]}
	set x
    }
    foo
} {1 2 3 4}

test foreach-3.1 {compiled foreach backward jump works correctly} {
    catch {unset x}
    proc foo {arrayName} {
        upvar 1 $arrayName a
        set l {}
        foreach member [array names a] {
            lappend l [list $member [set a($member)]]
        }
        return $l
	upvar 1 $arrayName a
	set l {}
	foreach member [array names a] {
	    lappend l [list $member [set a($member)]]
	}
	return $l
    }
    array set x {0 zero 1 one 2 two 3 three}
    lsort [foo x]
} [lsort {{0 zero} {1 one} {2 two} {3 three}}]

test foreach-4.1 {noncompiled foreach and shared variable or value list objects that are converted to another type} {
    catch {unset x}
    foreach {12.0} {a b c} {
        set x 12.0
        set x [expr $x + 1]
	set x 12.0
	set x [expr {$x + 1}]
    }
    set x
} 13.0

# Check "continue".

test foreach-5.1 {continue tests} {catch continue} 4
224
225
226
227
228
229
230
231

232
233
234
235
236
237
238
224
225
226
227
228
229
230

231
232
233
234
235
236
237
238







-
+







} -result {2}

# Test for incorrect "double evaluation" semantics
test foreach-7.1 {delayed substitution of body} {
    proc foo {} {
       set a 0
       foreach a [list 1 2 3] "
           set x $a
	   set x $a
       "
       set x
    }
    foo
} {0}

# Test for [Bug 1189274]; crash on failure
256
257
258
259
260
261
262
263
264


265
266
267
268
269
270
271
256
257
258
259
260
261
262


263
264
265
266
267
268
269
270
271







-
-
+
+







    list [catch { foo } msg] $msg
} {1 {foreach varlist is empty}}

test foreach-9.2 {line numbers} -setup {
    proc linenumber {} {dict get [info frame -1] line}
} -body {
    apply {n {
        foreach x y {*}{
        } {return [incr n -[linenumber]]}
	foreach x y {*}{
	} {return [incr n -[linenumber]]}
    }} [linenumber]
} -cleanup {
    rename linenumber {}
} -result 1

test foreach-10.1 {foreach: [Bug 1671087]} -setup {
    proc demo {} {

Changes to tests/format.test.

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
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
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
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






-
-
+
+









-
+
-
-
-

+
+
+
-
-
+
+






-
+


-
-
-











-
+


-
-
-
-
+


-
-
-
-
+


-
-
-
-
+


-
-
-
-
+


-
-
-





-
+


-
+


-
+















-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+







# Commands covered:  format
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1994 The Regents of the University of California.
# Copyright (c) 1994-1998 Sun Microsystems, Inc.
# Copyright © 1991-1994 The Regents of the University of California.
# Copyright © 1994-1998 Sun Microsystems, Inc.
#
# 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::*
}

# %u output depends on word length, so this test is not portable.
# %z/%t/%p output depends on pointerSize, so some tests are not portable.
testConstraint longIs32bit [expr {$tcl_platform(wordSize) == 4}]
testConstraint longIs64bit [expr {$tcl_platform(wordSize) == 8}]
testConstraint wideIs64bit [expr {wide(0x8000000000000000) < 0}]
testConstraint pointerIs64bit [expr {$tcl_platform(pointerSize) >= 8}]
# MSVC uses a broken libc that gets sprintf("%g") wrong. This is a pain
# particularly in Continuous Integration, and there isn't anything much we can
# do about it.
testConstraint knownMsvcBug [expr {![info exists ::env(TRAVIS_OS_NAME)] || ![string match windows $::env(TRAVIS_OS_NAME)]}]

testConstraint knownMsvcBug [expr {![string match msvc-* [tcl::build-info compiler]]}]

test format-1.1 {integer formatting} {
    format "%*d %d %d %d" 6 34 16923 -12 -1
} {    34 16923 -12 -1}
test format-1.2 {integer formatting} {
    format "%4d %4d %4d %4d %d %#x %#X" 6 34 16923 -12 -1 14 12
} {   6   34 16923  -12 -1 0xe 0xC}
test format-1.3 {integer formatting} longIs32bit {
test format-1.3 {integer formatting} {
    format "%4u %4u %4u %4u %d %#o" 6 34 16923 -12 -1 0
} {   6   34 16923 4294967284 -1 0}
test format-1.3.1 {integer formatting} longIs64bit {
    format "%4u %4u %4u %4u %d %#o" 6 34 16923 -12 -1 0
} {   6   34 16923 18446744073709551604 -1 0}
test format-1.4 {integer formatting} {
    format "%-4d %-4i %-4d %-4ld" 6 34 16923 -12 -1
} {6    34   16923 -12 }
test format-1.5 {integer formatting} {
    format "%04d %04d %04d %04i" 6 34 16923 -12 -1
} {0006 0034 16923 -012}
test format-1.6 {integer formatting} {
    format "%00*d" 6 34
} {000034}
# Printing negative numbers in hex or octal format depends on word
# length, so these tests are not portable.
test format-1.7 {integer formatting} longIs32bit {
test format-1.7 {integer formatting} {
    format "%4x %4x %4x %4x" 6 34 16923 -12 -1
} {   6   22 421b fffffff4}
test format-1.7.1 {integer formatting} longIs64bit {
    format "%4x %4x %4x %4x" 6 34 16923 -12 -1
} {   6   22 421b fffffffffffffff4}
test format-1.8 {integer formatting} longIs32bit {
test format-1.8 {integer formatting} {
    format "%#x %#x %#X %#X %#x" 0 6 34 16923 -12 -1
} {0 0x6 0x22 0x421B 0xfffffff4}
test format-1.8.1 {integer formatting} longIs64bit {
    format "%#x %#x %#X %#X %#x" 0 6 34 16923 -12 -1
} {0 0x6 0x22 0x421B 0xfffffffffffffff4}
test format-1.9 {integer formatting} longIs32bit {
test format-1.9 {integer formatting} {
    format "%#5x %#20x %#20x %#20x %#20x" 0 6 34 16923 -12 -1
} {    0                  0x6                 0x22               0x421b           0xfffffff4}
test format-1.9.1 {integer formatting} longIs64bit {
    format "%#5x %#20x %#20x %#20x %#20x" 0 6 34 16923 -12 -1
} {    0                  0x6                 0x22               0x421b   0xfffffffffffffff4}
test format-1.10 {integer formatting} longIs32bit {
test format-1.10 {integer formatting} {
    format "%-#5x %-#20x %-#20x %-#20x %-#20x" 0 6 34 16923 -12 -1
} {0     0x6                  0x22                 0x421b               0xfffffff4          }
test format-1.10.1 {integer formatting} longIs64bit {
    format "%-#5x %-#20x %-#20x %-#20x %-#20x" 0 6 34 16923 -12 -1
} {0     0x6                  0x22                 0x421b               0xfffffffffffffff4  }
test format-1.11 {integer formatting} longIs32bit {
test format-1.11 {integer formatting} {
    format "%-#5o %-#20o %#-20o %#-20o %#-20o" 0 6 34 16923 -12 -1
} {0     0o6                  0o42                 0o41033              0o37777777764       }
test format-1.11.1 {integer formatting} longIs64bit {
    format "%-#5o %-#20o %#-20o %#-20o %#-20o" 0 6 34 16923 -12 -1
} {0     0o6                  0o42                 0o41033              0o1777777777777777777764}
test format-1.12 {integer formatting} {
    format "%b %#b %#b %llb" 5 0 5 [expr {2**100}]
} {101 0 0b101 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}
test format-1.13 {integer formatting} {
    format "%#0d %#0d %#0d %#0d %#0d" 0 6 34 16923 -12 -1
} {0 6 34 16923 -12}
} {0 0d6 0d34 0d16923 -0d12}
test format-1.14 {integer formatting} {
    format "%#05d %#020d %#020d %#020d %#020d" 0 6 34 16923 -12 -1
} {00000 00000000000000000006 00000000000000000034 00000000000000016923 -0000000000000000012}
} {00000 0d000000000000000006 0d000000000000000034 0d000000000000016923 -0d00000000000000012}
test format-1.15 {integer formatting} {
    format "%-#05d %-#020d %-#020d %-#020d %-#020d" 0 6 34 16923 -12 -1
} {00000 00000000000000000006 00000000000000000034 00000000000000016923 -0000000000000000012}
} {00000 0d000000000000000006 0d000000000000000034 0d000000000000016923 -0d00000000000000012}


test format-2.1 {string formatting} {
    format "%s %s %c %s" abcd {This is a very long test string.} 120 x
} {abcd This is a very long test string. x x}
test format-2.2 {string formatting} {
    format "%20s %20s %20c %20s" abcd {This is a very long test string.} 120 x
} {                abcd This is a very long test string.                    x                    x}
test format-2.3 {string formatting} {
    format "%.10s %.10s %c %.10s" abcd {This is a very long test string.} 120 x
} {abcd This is a  x x}
test format-2.4 {string formatting} {
    format "%s %s %% %c %s" abcd {This is a very long test string.} 120 x
} {abcd This is a very long test string. % x x}
test format-2.5 {string formatting, embedded nulls} {
    format "%10s" abc\0def
} "   abc\0def"
    format "%10s" abc\x00def
} "   abc\x00def"
test format-2.6 {string formatting, international chars} {
    format "%10s" abc\ufeffdef
} "   abc\ufeffdef"
    format "%10s" abc\uFEFFdef
} "   abc\uFEFFdef"
test format-2.7 {string formatting, international chars} {
    format "%.5s" abc\ufeffdef
} "abc\ufeffd"
    format "%.5s" abc\uFEFFdef
} "abc\uFEFFd"
test format-2.8 {string formatting, international chars} {
    format "foo\ufeffbar%s" baz
} "foo\ufeffbarbaz"
    format "foo\uFEFFbar%s" baz
} "foo\uFEFFbarbaz"
test format-2.9 {string formatting, width} {
    format "a%5sa" f
} "a    fa"
test format-2.10 {string formatting, width} {
    format "a%-5sa" f
} "af    a"
test format-2.11 {string formatting, width} {
136
137
138
139
140
141
142






143
144
145
146
147
148
149


150
151
152
153
154
155
156
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







+
+
+
+
+
+





-
-
+
+







} {1 {bad field specifier "-"}}
test format-2.16 {string formatting, width and precision} {
    format "a%5.2sa" foobarbaz
} "a   foa"
test format-2.17 {string formatting, width and precision} {
    format "a%5.7sa" foobarbaz
} "afoobarba"
test format-2.18 {string formatting, surrogates} {
    format "\uD83D%s" \uDE02
} \uD83D\uDE02
test format-2.19 {string formatting, surrogates} {
    format "%s\uDE02" \uD83D
} \uD83D\uDE02

test format-3.1 {Tcl_FormatObjCmd: character formatting} {
    format "|%c|%0c|%-1c|%1c|%-6c|%6c|%*c|%*c|" 65 65 65 65 65 65 3 65 -4 65
} "|A|A|A|A|A     |     A|  A|A   |"
test format-3.2 {Tcl_FormatObjCmd: international character formatting} {
    format "|%c|%0c|%-1c|%1c|%-6c|%6c|%*c|%*c|" 0xa2 0x4e4e 0x25a 0xc3 0xff08 0 3 0x6575 -4 0x4e4f
} "|\ua2|\u4e4e|\u25a|\uc3|\uff08     |     \0|  \u6575|\u4e4f   |"
    format "|%c|%0c|%-1c|%1c|%-6c|%6c|%*c|%*c|" 0xA2 0x4E4E 0x25A 0xC3 0xFF08 0 3 0x6575 -4 0x4E4F
} "|¢|乎|Éš|Ã|(     |     \x00|  敵|ä¹   |"

test format-4.1 {e and f formats} {eformat} {
    format "%e %e %e %e" 34.2e12 68.514 -.125 -16000. .000053
} {3.420000e+13 6.851400e+01 -1.250000e-01 -1.600000e+04}
test format-4.2 {e and f formats} {eformat} {
    format "%20e %20e %20e %20e" 34.2e12 68.514 -.125 -16000. .000053
} {        3.420000e+13         6.851400e+01        -1.250000e-01        -1.600000e+04}
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
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







-
-
-
-
-
-
+
+

-
-
+
+

-
-
-
-
-
-
+
+

-
-
+
+

+
+
+







    catch {format %d} msg
    set msg
} {not enough arguments for all format specifiers}
test format-8.23 {error conditions} {
    catch {format "%d %d" 24 xyz} msg
    set msg
} {expected integer but got "xyz"}
# Since "%zd" and "%td" are equivalent to "%lld" in 64-bit platforms and
# equivalent to "%d" in 32-bit platforms, they are really not useful in
# scripts, therefore they are not documented. It's intended use is through
# the function Tcl_AppendPrintfToObj (et al).
test format-8.24 {Undocumented formats} -body {
    format "%zd %td %d" [expr 2**30] [expr 2**30] [expr 2**30]
test format-8.24 {Other formats} -body {
    format "%zd %td %d" [expr {2**30}] [expr {2**30}] [expr {2**30}]
} -result {1073741824 1073741824 1073741824}
test format-8.25 {Undocumented formats} -constraints pointerIs64bit -body {
    format "%zd %td %lld" [expr 2**33] [expr 2**33] [expr 2**33]
test format-8.25 {Other formats} -constraints pointerIs64bit -body {
    format "%zd %td %lld" [expr {2**33}] [expr {2**33}] [expr {2**33}]
} -result {8589934592 8589934592 8589934592}
# Since "%p" is equivalent to "%#llx" in 64-bit platforms and equivalent
# to "%#x" in 32-bit platforms, it are really not useful in scripts,
# therefore they are not documented. It's intended use is through the
# function Tcl_AppendPrintfToObj (et al).
test format-8.26 {Undocumented formats} -body {
    format "%p %#x" [expr 2**31] [expr 2**31]
test format-8.26 {Other formats} -body {
    format "%p %#x" [expr {2**31}] [expr {2**31}]
} -result {0x80000000 0x80000000}
test format-8.27 {Undocumented formats} -constraints pointerIs64bit -body {
    format "%p %#llx" [expr 2**33] [expr 2**33]
test format-8.27 {Other formats} -constraints pointerIs64bit -body {
    format "%p %#llx" [expr {2**33}] [expr {2**33}]
} -result {0x200000000 0x200000000}
test format-8.28 {Internal use of TCL_COMBINE flag should not be visible at script level} {
    format %c 0x10000041
} \uFFFD

test format-9.1 {long result} {
    set a {1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z}
    format {1111 2222 3333 4444 5555 6666 7777 8888 9999 aaaa bbbb cccc dddd eeee ffff gggg hhhh iiii jjjj kkkk llll mmmm nnnn oooo pppp qqqq rrrr ssss tttt uuuu vvvv wwww xxxx yyyy zzzz AAAA BBBB CCCC DDDD EEEE FFFF GGGG %s %s} $a $a
} {1111 2222 3333 4444 5555 6666 7777 8888 9999 aaaa bbbb cccc dddd eeee ffff gggg hhhh iiii jjjj kkkk llll mmmm nnnn oooo pppp qqqq rrrr ssss tttt uuuu vvvv wwww xxxx yyyy zzzz AAAA BBBB CCCC DDDD EEEE FFFF GGGG 1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z}

test format-10.1 {"h" format specifier} {
449
450
451
452
453
454
455






456
457
458
459
460
461
462
463
464
465
466
467
468
469

470
471
472
473
474
475
476
477
478
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
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
467
468

469
470
471
472
473
474
475
476
477

478
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







+
+
+
+
+
+













-
+










-
+








-
+








-
+








-
+







} {1 {"%n$" argument index out of range}}
test format-11.11 {XPG3 %$n specifiers} {
    list [catch {format {%2$*d} 4 5} msg] $msg
} {1 {"%n$" argument index out of range}}
test format-11.12 {XPG3 %$n specifiers} {
    list [catch {format {%2$*d} 4 5 6} msg] $msg
} {0 {    6}}
test format-11.13 {XPG3 %$n specifiers} {
    format {%2$.*s %4$d} 1 -4294967298 abcdefghijklmnop 44
} { 44}
test format-11.14 {XPG3 %$n specifiers} {
    format {%2$.*s %4$d} 1 4294967298 abcdefghijklmnop 44
} {abcdefghijklmnop 44}

test format-12.1 {negative width specifiers} {
    format "%*d" -47 25
} {25                                             }

test format-13.1 {tcl_precision fuzzy comparison} {
    catch {unset a}
    catch {unset b}
    catch {unset c}
    catch {unset d}
    set a 0.0000000000001
    set b 0.00000000000001
    set c 0.00000000000000001
    set d [expr $a + $b + $c]
    set d [expr {$a + $b + $c}]
    format {%0.10f %0.12f %0.15f %0.17f} $d $d $d $d
} {0.0000000000 0.000000000000 0.000000000000110 0.00000000000011001}
test format-13.2 {tcl_precision fuzzy comparison} {
    catch {unset a}
    catch {unset b}
    catch {unset c}
    catch {unset d}
    set a 0.000000000001
    set b 0.000000000000005
    set c 0.0000000000000008
    set d [expr $a + $b + $c]
    set d [expr {$a + $b + $c}]
    format {%0.10f %0.12f %0.15f %0.17f} $d $d $d $d
} {0.0000000000 0.000000000001 0.000000000001006 0.00000000000100580}
test format-13.3 {tcl_precision fuzzy comparison} {
    catch {unset a}
    catch {unset b}
    catch {unset c}
    set a 0.00000000000099
    set b 0.000000000000011
    set c [expr $a + $b]
    set c [expr {$a + $b}]
    format {%0.10f %0.12f %0.15f %0.17f} $c $c $c $c
} {0.0000000000 0.000000000001 0.000000000001001 0.00000000000100100}
test format-13.4 {tcl_precision fuzzy comparison} {
    catch {unset a}
    catch {unset b}
    catch {unset c}
    set a 0.444444444444
    set b 0.33333333333333
    set c [expr $a + $b]
    set c [expr {$a + $b}]
    format {%0.10f %0.12f %0.15f %0.16f} $c $c $c $c
} {0.7777777778 0.777777777777 0.777777777777330 0.7777777777773300}
test format-13.5 {tcl_precision fuzzy comparison} {
    catch {unset a}
    catch {unset b}
    catch {unset c}
    set a 0.444444444444
    set b 0.99999999999999
    set c [expr $a + $b]
    set c [expr {$a + $b}]
    format {%0.10f %0.12f %0.15f} $c $c $c
} {1.4444444444 1.444444444444 1.444444444443990}

test format-14.1 {testing MAX_FLOAT_SIZE for 0 and 1} {
    format {%s} ""
} {}
test format-14.2 {testing MAX_FLOAT_SIZE for 0 and 1} {
536
537
538
539
540
541
542
543
544


545
546
547
548
549

550
551
552

553
554
555

556
557
558
559
560
561
562
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







-
-
+
+




-
+


-
+


-
+








set a "0123456789"
set b ""
for {set i 0} {$i < 290} {incr i} {
    append b $a
}
for {set i 290} {$i < 400} {incr i} {
    test format-16.[expr $i -289] {testing MAX_FLOAT_SIZE} {
        format {%s} $b
    test format-16.[expr {$i -289}] {testing MAX_FLOAT_SIZE} {
	format {%s} $b
    } $b
    append b "x"
}

test format-17.1 {testing %d with wide} {longIs32bit wideIs64bit} {
test format-17.1 {testing %d with wide} {
    format %d 7810179016327718216
} 1819043144
test format-17.2 {testing %ld with wide} {wideIs64bit} {
test format-17.2 {testing %ld with wide} {
    format %ld 7810179016327718216
} 7810179016327718216
test format-17.3 {testing %ld with non-wide} {wideIs64bit} {
test format-17.3 {testing %ld with non-wide} {
    format %ld 42
} 42
test format-17.4 {testing %l with non-integer} {
    format %lf 1
} 1.000000
test format-17.5 {testing %llu with positive bignum} -body {
    format %llu 0xabcdef0123456789abcdef
575
576
577
578
579
580
581
582

583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607
608
609
610
611
612
613
614

615
616
617
618
619

620
621
622
623
624
625
626
564
565
566
567
568
569
570

571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587

588

589
590
591
592
593
594
595
596
597
598
599
600
601

602
603
604
605
606

607
608
609
610
611
612
613
614







-
+
















-
+
-













-
+




-
+







    lappend result [expr {$a == $b}]
    set b 0xaaaa
    append b aaaa
    lappend result [expr {$a == $b}]
    format %08x $b
    lappend result [expr {$a == $b}]
} {1 1 1 1}
test format-18.2 {do not demote existing numeric values} {longIs32bit wideIs64bit} {
test format-18.2 {do not demote existing numeric values} {
    set a [expr {0xaaaaaaaaaa + 1}]
    set b 0xaaaaaaaaab
    list [format %08x $a] [expr {$a == $b}]
} {aaaaaaab 1}

test format-19.1 {regression test - tcl-core message by Brian Griffin on 26 0ctober 2004} -body {
    set x 0x8fedc654
    list [expr { ~ $x }] [format %08x [expr { ~$x }]]
} -match regexp -result {-2414724693 f*701239ab}
test format-19.2 {Bug 1867855} {
    format %llx 0
} 0
test format-19.3 {Bug 2830354} {
    string length [format %340f 0]
} 340

test format-19.4.1 {Bug d498578df4: width overflow should cause limit exceeded} \
test format-19.4.1 {Bug d498578df4: width overflow should cause limit exceeded} -body {
-constraints {longIs32bit} -body {
    # in case of overflow into negative, it produces width -2 (and limit exceeded),
    # in case of width will be unsigned, it will be outside limit (2GB for 32bit)...
    # and it don't throw an error in case the bug is not fixed (and probably no segfault).
    format %[expr {0xffffffff - 1}]g 0
} -returnCodes error -result "max size for a Tcl value exceeded"

test format-19.4.2 {Bug d498578df4: width overflow should cause limit exceeded} -body {
    # limit should exceeds in any case,
    # and it don't throw an error in case the bug is not fixed (and probably no segfault).
    format %[expr {0xffffffffffffffff - 1}]g 0
} -returnCodes error -result "max size for a Tcl value exceeded"

# Note that this test may fail in future versions
test format-20.1 {Bug 2932421: plain %s caused intrep change of args} -body {
test format-20.1 {Bug 2932421: plain %s caused internalrep change of args} -body {
    set x [dict create a b c d]
    format %s $x
    # After this, obj in $x should be a dict
    # We are testing to make sure it has not been shimmered to a
    # different intrep when that is not necessary.
    # different internalrep when that is not necessary.
    # Whether or not there is a string rep - we should not care!
    tcl::unsupported::representation $x
} -match glob -result {value is a dict *}

# cleanup
catch {unset a}
catch {unset b}

Changes to tests/get.test.

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
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
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
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






-
-
+
+










-
+
+
+



-



















-
-
+
+








-
+


-
+


-
+


-
+


-
+







# Commands covered:  none
#
# This file contains a collection of tests for the procedures in the
# file tclGet.c.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

source [file join [file dirname [info script]] tcltests.tcl]

testConstraint testgetint [llength [info commands testgetint]]
testConstraint testdoubleobj [llength [info commands testdoubleobj]]
testConstraint longIs32bit [expr {$tcl_platform(wordSize) == 4}]
testConstraint longIs64bit [expr {$tcl_platform(wordSize) == 8}]

test get-1.1 {Tcl_GetInt procedure} testgetint {
    testgetint 44 { 	  22}
} {66}
test get-1.2 {Tcl_GetInt procedure} testgetint {
    testgetint 44 -3
} {41}
test get-1.3 {Tcl_GetInt procedure} testgetint {
    testgetint 44 +8
} {52}
test get-1.4 {Tcl_GetInt procedure} testgetint {
    list [catch {testgetint 44 foo} msg] $msg
} {1 {expected integer but got "foo"}}
test get-1.5 {Tcl_GetInt procedure} testgetint {
    list [catch {testgetint 44 {16	 }} msg] $msg
} {0 60}
test get-1.6 {Tcl_GetInt procedure} testgetint {
    list [catch {testgetint 44 {16	 x}} msg] $msg
} {1 {expected integer but got "16	 x"}}
test get-1.7 {Tcl_GetInt procedure} {testgetint longIs64bit} {
} {1 {expected integer but got a list}}
test get-1.7 {Tcl_GetInt procedure} testgetint {
    list [catch {testgetint 44 18446744073709551616} msg] $msg $errorCode
} {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}}
test get-1.8 {Tcl_GetInt procedure} {testgetint longIs64bit} {
    testgetint 18446744073709551614
} {-2}
test get-1.9 {Tcl_GetInt procedure} {testgetint longIs64bit} {
    testgetint +18446744073709551614
} {-2}
test get-1.10 {Tcl_GetInt procedure} {testgetint longIs64bit} {
test get-1.10 {Tcl_GetInt procedure} testgetint {
    list [catch {testgetint -18446744073709551614} msg] $msg $errorCode
} {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}}
test get-1.11 {Tcl_GetInt procedure} {testgetint longIs32bit} {
test get-1.11 {Tcl_GetInt procedure} testgetint {
    list [catch {testgetint 44 4294967296} msg] $msg $errorCode
} {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}}
test get-1.12 {Tcl_GetInt procedure} {testgetint longIs32bit} {
test get-1.12 {Tcl_GetInt procedure} testgetint {
    list [catch {testgetint 4294967294} msg] $msg
} {0 -2}
test get-1.13 {Tcl_GetInt procedure} {testgetint longIs32bit} {
test get-1.13 {Tcl_GetInt procedure} testgetint {
    list [catch {testgetint +4294967294} msg] $msg
} {0 -2}
test get-1.14 {Tcl_GetInt procedure} {testgetint longIs32bit} {
test get-1.14 {Tcl_GetInt procedure} testgetint {
    list [catch {testgetint -4294967294} msg] $msg
} {1 {integer value too large to represent}}

test get-2.1 {Tcl_GetInt procedure} {
    format %g 1.23
} {1.23}
test get-2.2 {Tcl_GetInt procedure} {
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
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







-
+







-
+







+

-
+



-
+
+

-
+



-
+








    # SF bug #634856
    set result ""
    set numbers [list 1 +1 ++1 +-1 -+1 -1 --1 "- +1" "+12345678987654321" "++12345678987654321"]
    foreach num $numbers {
	lappend result [catch {format %ld $num} msg] $msg
    }
    set result
} {0 1 0 1 1 {expected integer but got "++1"} 1 {expected integer but got "+-1"} 1 {expected integer but got "-+1"} 0 -1 1 {expected integer but got "--1"} 1 {expected integer but got "- +1"} 0 12345678987654321 1 {expected integer but got "++12345678987654321"}}
} {0 1 0 1 1 {expected integer but got "++1"} 1 {expected integer but got "+-1"} 1 {expected integer but got "-+1"} 0 -1 1 {expected integer but got "--1"} 1 {expected integer but got a list} 0 12345678987654321 1 {expected integer but got "++12345678987654321"}}
test get-3.2 {Tcl_GetDouble(FromObj), bad numbers} {
    set result ""
    set numbers [list 1.0 +1.0 ++1.0 +-1.0 -+1.0 -1.0 --1.0 "- +1.0"]
    foreach num $numbers {
	lappend result [catch {format %g $num} msg] $msg
    }
    set result
} {0 1 0 1 1 {expected floating-point number but got "++1.0"} 1 {expected floating-point number but got "+-1.0"} 1 {expected floating-point number but got "-+1.0"} 0 -1 1 {expected floating-point number but got "--1.0"} 1 {expected floating-point number but got "- +1.0"}}
} {0 1 0 1 1 {expected floating-point number but got "++1.0"} 1 {expected floating-point number but got "+-1.0"} 1 {expected floating-point number but got "-+1.0"} 0 -1 1 {expected floating-point number but got "--1.0"} 1 {expected floating-point number but got a list}}
# Bug 7114ac6141
test get-3.3 {tcl_GetInt with iffy numbers} testgetint {
    lmap x {0 " 0" "0 " " 0 " " 0xa " " 010 " " 0o10 " " 0b10 "} {
	catch {testgetint 44 $x} x
	set x
    }
} {44 44 44 44 54 54 52 46}

test get-3.4 {Tcl_GetDouble with iffy numbers} testdoubleobj {
    lmap x {0 0.0 " .0" ".0 " " 0e0 " "09" "- 0" "-0" "0o12" "0b10"} {
    lmap x {0 0.0 " .0" ".0 " " 0e0 " "09" "- 0" "-0" "0o12" "0b10" "2_0.3_4e+1_5" _1.0e+2 1_.0e+2 1._0e+2 1.0_e+2 1.0e_+2 1.0e+_2 1.0e+2_ 1_1.0e+0_2 2__2.0e+2__2 54321________} {
	catch {testdoubleobj set 1 $x} x
	set x
    }
} {0.0 0.0 0.0 0.0 0.0 9.0 {expected floating-point number but got "- 0"} 0.0 10.0 2.0}
} {0.0 0.0 0.0 0.0 0.0 9.0 {expected floating-point number but got a list} 0.0 10.0 2.0 20340000000000000.0 {expected floating-point number but got "_1.0e+2"} {expected floating-point number but got "1_.0e+2"} {expected floating-point number but got "1._0e+2"} {expected floating-point number but got "1.0_e+2"} {expected floating-point number but got "1.0e_+2"} {expected floating-point number but got "1.0e+_2"} {expected floating-point number but got "1.0e+2_"} 1100.0 2.2e+23 {expected floating-point number but got "54321________"}}

test get-3.5 {tcl_GetInt with numeric whitespace (i.e. '_')} testgetint {
    lmap x {0_0 " 1_0" "0_2 " " 3_3 " 14__23__32___4 " 0x_a " " 0_07 " " 0o_1_0 " " 0_b1_0 " _33 42_ 0_x15 0_o17 0_d19 } {
    lmap x {0_0 " 1_0" "0_2 " " 3_3 " 14__23__32___4 " 0x0_a " 0b1111_1111 " 0_07 " " 0o1_0 " " 0b_1_0 " " 0_b1_0 " _33 42_ 0_x15 0_o17 0_d19 0x_b 0o_2_0 0o2__3_4} {
	catch {testgetint $x} x
	set x
    }
} {0 10 2 33 1423324 10 7 8 {expected integer but got " 0_b1_0 "} {expected integer but got "_33"} {expected integer but got "42_"} {expected integer but got "0_x15"} {expected integer but got "0_o17"} {expected integer but got "0_d19"}}
} {0 10 2 33 1423324 10 255 7 8 {expected integer but got " 0b_1_0 "} {expected integer but got " 0_b1_0 "} {expected integer but got "_33"} {expected integer but got "42_"} {expected integer but got "0_x15"} {expected integer but got "0_o17"} {expected integer but got "0_d19"} {expected integer but got "0x_b"} {expected integer but got "0o_2_0"} 156}

# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/history.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  history
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands.  Sourcing this file into Tcl runs the tests and generates output
# for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
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
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







-
+













-
+


-
+














-
+


-
+








# "history event"

test history-1.1 {event option} history {history event -1} \
	{set b [format {A test %s} string]}
test history-1.2 {event option} history {history event $num} \
	{set a 12345}
test history-1.3 {event option} history {history event [expr $num+2]} \
test history-1.3 {event option} history {history event [expr {$num+2}]} \
	{Another test}
test history-1.4 {event option} history {history event set} \
	{set b [format {A test %s} string]}
test history-1.5 {event option} history {history e "* a*"} \
	{set a 12345}
test history-1.6 {event option} history {catch {history event *gorp} msg} 1
test history-1.7 {event option} history {
    catch {history event *gorp} msg
    set msg
} {no event matches "*gorp"}
test history-1.8 {event option} history {history event} \
	{set b [format {A test %s} string]}
test history-1.9 {event option} history {catch {history event 123 456} msg} 1
test history-1.10 {event option} history {
test history-1.10 {event option} -constraints history -body {
    catch {history event 123 456} msg
    set msg
} {wrong # args: should be "history event ?event?"}
} -match glob -result {wrong # args: should be "*history event \?event\?"}

# "history redo"

if {[testConstraint history]} {
    set a 0
    history redo -2
}
test history-2.1 {redo option} history {set a} 12345
if {[testConstraint history]} {
    set b 0
    history redo
}
test history-2.2 {redo option} history {set b} {A test string}
test history-2.3 {redo option} history {catch {history redo -3 -4}} 1
test history-2.4 {redo option} history {
test history-2.4 {redo option} -constraints history -body {
    catch {history redo -3 -4} msg
    set msg
} {wrong # args: should be "history redo ?event?"}
} -match glob -result {wrong # args: should be "*history redo \?event\?"}

# "history add"

if {[testConstraint history]} {
    history add "set a 444" exec
}
test history-3.1 {add option} history {set a} 444
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
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







-
+


-
+















-
+


-
+







}
test history-3.6 {add option} history {set a} 555
if {[testConstraint history]} {
    history add "set a 666"
}
test history-3.7 {add option} history {set a} 555
test history-3.8 {add option} history {catch {history add "set a 666" e f} msg} 1
test history-3.9 {add option} history {
test history-3.9 {add option} -constraints history -body {
    catch {history add "set a 666" e f} msg
    set msg
} {wrong # args: should be "history add event ?exec?"}
} -match glob -result {wrong # args: should be "*history add event \?exec\?"}

# "history change"

if {[testConstraint history]} {
    history change "A test value"
}
test history-4.1 {change option} history {history event [expr {[history n]-1}]} \
	"A test value"
if {[testConstraint history]} {
    history ch "Another test" -1
}
test history-4.2 {change option} history {history e} "Another test"
test history-4.3 {change option} history {history event [expr {[history n]-1}]} \
	"A test value"
test history-4.4 {change option} history {catch {history change Foo 4 10}} 1
test history-4.5 {change option} history {
test history-4.5 {change option} -constraints history -body {
    catch {history change Foo 4 10} msg
    set msg
} {wrong # args: should be "history change newValue ?event?"}
} -match glob -result {wrong # args: should be "*history change newValue \?event\?"}
test history-4.6 {change option} history {
    catch {history change Foo [expr {[history n]-4}]}
} 1
if {[testConstraint history]} {
    set num [expr {[history n]-4}]
}
test history-4.7 {change option} history {
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
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







-
+



-
+

-
+


-
+





-
+









-
+
+
+















-
+


-
+







    history add set\ c\ {a\nb\nc}
}
test history-5.1 {info option} history {history info} [format {%6d  set a {b
	c d e}
%6d  set b 1234
%6d  set c {a
	b
	c}} $num [expr $num+1] [expr $num+2]]
	c}} $num [expr {$num+1}] [expr {$num+2}]]
test history-5.2 {info option} history {history i 2} [format {%6d  set b 1234
%6d  set c {a
	b
	c}} [expr $num+1] [expr $num+2]]
	c}} [expr {$num+1}] [expr {$num+2}]]
test history-5.3 {info option} history {catch {history i 2 3}} 1
test history-5.4 {info option} history {
test history-5.4 {info option} -constraints history -body {
    catch {history i 2 3} msg
    set msg
} {wrong # args: should be "history info ?count?"}
} -match glob -result {wrong # args: should be "*history info \?count\?"}
test history-5.5 {info option} history {history} [format {%6d  set a {b
	c d e}
%6d  set b 1234
%6d  set c {a
	b
	c}} $num [expr $num+1] [expr $num+2]]
	c}} $num [expr {$num+1}] [expr {$num+2}]]

# "history keep"

if {[testConstraint history]} {
    history add "foo1"
    history add "foo2"
    history add "foo3"
    history keep 2
}
test history-6.1 {keep option} history {history event [expr [history n]-1]} foo3
test history-6.1 {keep option} history {
    history event [expr {[history n]-1}]
} foo3
test history-6.2 {keep option} history {history event -1} foo2
test history-6.3 {keep option} history {catch {history event -3}} 1
test history-6.4 {keep option} history {
    catch {history event -3} msg
    set msg
} {event "-3" is too far in the past}
if {[testConstraint history]} {
    history k 5
}
test history-6.5 {keep option} history {history event -1} foo2
test history-6.6 {keep option} history {history event -2} {}
test history-6.7 {keep option} history {history event -3} {}
test history-6.8 {keep option} history {history event -4} {}
test history-6.9 {keep option} history {catch {history event -5}} 1
test history-6.10 {keep option} history {catch {history keep 4 6}} 1
test history-6.11 {keep option} history {
test history-6.11 {keep option} -constraints history -body {
    catch {history keep 4 6} msg
    set msg
} {wrong # args: should be "history keep ?count?"}
} -match glob -result {wrong # args: should be "*history keep \?count\?"}
test history-6.12 {keep option} history {catch {history keep}} 0
test history-6.13 {keep option} history {
    history keep
} {5}
test history-6.14 {keep option} history {catch {history keep -3}} 1
test history-6.15 {keep option} history {
    catch {history keep -3} msg
212
213
214
215
216
217
218
219

220
221

222
223
224

225
226
227
228
229
230
231
214
215
216
217
218
219
220

221
222

223
224
225

226
227
228
229
230
231
232
233







-
+

-
+


-
+








if {[testConstraint history]} {
    set num [history n]
    history add "Testing"
    history add "Testing2"
}
test history-7.1 {nextid option} history {history event} "Testing"
test history-7.2 {nextid option} history {history next} [expr $num+2]
test history-7.2 {nextid option} history {history next} [expr {$num+2}]
test history-7.3 {nextid option} history {catch {history nextid garbage}} 1
test history-7.4 {nextid option} history {
test history-7.4 {nextid option} -constraints history -body {
    catch {history nextid garbage} msg
    set msg
} {wrong # args: should be "history nextid"}
} -match glob -result {wrong # args: should be "*history nextid"}

# "history clear"

if {[testConstraint history]} {
    set num [history n]
    history add "Testing"
    history add "Testing2"
258
259
260
261
262
263
264
265

266
267
268
269
270
271
272
260
261
262
263
264
265
266

267
268
269
270
271
272
273
274







-
+







	    # Ignore the references due to calling this procedure
	    return [expr {$rc - 3}]
	}
    }
} -body {
    histtest eval {
	# A fresh object, refcount 1 from the variable we write it to
	set obj [expr rand()]
	set obj [expr {rand()}]
	set baseline [refcount $obj]
	lappend result [refcount $obj]
	history add [list list $obj]
	lappend result [refcount $obj]
	history clear
	lappend result [refcount $obj]
    }
284
285
286
287
288
289
290
291

292
293
294
295
296
297
298
286
287
288
289
290
291
292

293
294
295
296
297
298
299
300







-
+







	    # Ignore the references due to calling this procedure
	    return [expr {$rc - 3}]
	}
    }
} -body {
    histtest eval {
	# A fresh object, refcount 1 from the variable we write it to
	set obj [expr rand()]
	set obj [expr {rand()}]
	set baseline [refcount $obj]
	lappend result [refcount $obj]
	history add [list list $obj]
	lappend result [refcount $obj]
	rename history {}
	lappend result [refcount $obj]
    }

Changes to tests/http.test.

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
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
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

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
467

468
469
470
471

472
473

474
475
476
477
478
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
558
559
560
561

562

563
564

565
566
567
568
569

570

571
572
573

574
575
576
577
578

579

580
581
582

583
584
585
586
587
588
589
590
591


592
593
594
595
596





















597


598

599
600
601
602
603



604
605
606
607
608
609
610
611
612
613
614
615
616
617
618

619
620
621
622

623
624
625
626


627
628

629
630
631

632
633
634
635
636

637
638
639
640
641
642
643
644

645
646
647
648
649
650

651
652
653

654
655
656

657
658

659
660
661

662
663

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
707

708
709
710

711
712
713

714
715
716
717

718
719
720
721


722
723

724
725
726
727


728
729

730
731
732
733


734
735

736
737
738
739


740
741

742
743
744
745


746
747

748
749
750
751


752
753

754
755
756

757
758
759
760
761
762

763
764
765
766
767

768
769
770
771
772

773
774
775
776
777
778
779

780
781
782
783
784
785
786

787
788
789
790
791
792
793
794

795
796
797
798
799
800

801
802
803
804
805
806
807

808
809
810
811
812
813
814
815

816
817
818
819
820
821
822
823
824

825
826
827
828
829
830
831
832

833
834
835
836
837

838
839
840
841
842
843
844

845
846
847
848
849
850
851

852
853
854
855
856

857
858
859
860
861
862

863
864
865
866
867

868
869
870
871
872

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

898
899
900


901
902
903

904
905
906


907
908
909

910
911
912


913
914
915

916
917
918


919
920
921
922

923
924
925

926
927
928
929

930
931
932
933
934

935
936
937
938
939
940

941
942
943

944
945
946

947
948
949
950
951
952
953

954
955
956
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
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

1116
1117
1118

1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129


1130
1131
1132
1133
1134
1135
1136
1137
1138


1139


1140
1141
1142
1143
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
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
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
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
467
468
469

470
471
472

473
474
475
476
477

478
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
558
559
560
561
562
563
564

565
566
567
568
569
570
571
572
573

574
575
576
577

578
579
580
581

582
583

584
585
586
587

588
589

590
591
592
593

594
595

596
597
598
599

600
601
602
603
604
605

606
607
608
609
610

611
612
613
614

615
616
617
618
619

620
621
622
623
624

625
626
627
628
629

630
631
632
633
634

635
636
637
638
639
640
641
642
643

644
645
646




647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709

710
711
712
713
714
715
716
717

718
719
720
721
722
723

724
725
726

727
728
729

730
731

732
733
734

735
736

737
738
739


740
741
742
743
744
745
746

747
748
749

750
751
752

753
754
755
756

757
758
759

760
761
762

763
764
765

766
767
768

769
770
771

772
773
774

775
776
777

778
779
780

781
782
783

784
785
786

787
788
789

790
791
792
793

794
795
796


797
798
799

800
801
802


803
804
805

806
807
808


809
810
811

812
813
814


815
816
817

818
819
820


821
822
823

824
825
826


827
828
829

830
831
832

833
834
835
836
837
838

839
840
841
842
843

844
845
846
847
848

849
850
851
852
853
854
855

856
857
858
859
860
861
862

863
864
865
866
867
868
869
870

871
872
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
898
899
900

901
902
903
904
905
906
907
908

909
910
911
912
913

914
915
916
917
918
919
920

921
922
923
924
925
926
927

928
929
930
931
932

933
934
935
936
937
938

939
940
941
942
943

944
945
946
947
948

949
950
951
952

953
954
955

956
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
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

1116
1117
1118

1119
1120
1121
1122
1123

1124
1125
1126


1127
1128
1129


1130
1131
1132

1133
1134
1135


1136
1137
1138

1139
1140
1141
1142

1143
1144
1145

1146
1147
1148
1149

1150
1151
1152
1153
1154
1155
1156
1157

1158
1159
1160

1161
1162
1163
1164
1165


1166
1167
1168
1169

1170
1171
1172

1173
1174
1175
1176

1177
1178
1179
1180

1181
1182
1183
1184

1185
1186
1187

1188
1189
1190
1191

1192
1193
1194

1195
1196
1197
1198
1199
1200
1201
1202
1203
1204


1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217

1218
1219
1220
1221
1222
1223






-
-
-
+
+
+









-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
-
+
+








-
-
-
+
+
+
+
-
-
-
-
-
+
















+

















+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
+
+


-
+


-
+







-
-
+
+

-
-
+
+









-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
-
+
+
+


+

-
-
+
+



-
+




+









+
-
+



-
+








-
+





-
+




-
+





-
+




-
+



-
+




-
+



-
+









-
+



-
+

-
+










-
+




-
+

-
-
+
+

-
+

-
+












-
+

-
+


-
-
-
+
+
+

-
+


-
+

-
+

-
+


-
+






-
+












-
+

-
+

-
+







-
+

-
-
+
+




-
+


-
+

-
+







-
+



-
+

-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+






-
+

-
-
+
+






-
+

-
-
+
+




-
+


-



+

-
+




-
+


-



+

-
+







-
+



-
+

-
+



-
+

-
+



-
+


-
+




-
+


-


+



-
+



-
+

-
-
-
+
+
+
+
+
+

-
+



-
+

-
+

-
+



-
+

-
+

-
+



-
+

-
+











-
+




-
+










-
+

-
+












-
+








-
+



-
+



-
+

-
+



-
+

-
+



-
+

-
+



-
+

+



-
+




-
+

+

-
+




-
+

+


-
+




-
+

+


-
+








-
+
+

-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
-
+



-
-
+
+
+














-
+



-
+


-
-
+
+

-
+


-
+




-
+







-
+





-
+


-
+


-
+

-
+


-
+

-
+


-
-
+
+

+
+


-
+
+

-
+


-
+



-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+



-
+


-
-
+
+

-
+


-
-
+
+

-
+


-
-
+
+

-
+


-
-
+
+

-
+


-
-
+
+

-
+


-
-
+
+

-
+


-
+





-
+




-
+




-
+






-
+






-
+







-
+





-
+






-
+







-
+








-
+







-
+




-
+






-
+






-
+




-
+





-
+




-
+




-
+



-
+


-
+

-
-
+
+


-
+

-
-
+
+

-
-
+
+

-
-
+
+


-
+

-
-
+
+


-
+

-
-
+
+


-
+

-
-
+
+


-
+

-
-
+
+



-
+


-
+



-
+




-
+





-
+


-
+


-
+






-
+






-
+








-
+





-
+







-
+







-
+









-
+








-
+


-
+






-
+






-
+


-
+





-
+


-
+


-
+




-
+


-
-
+
+

-
-
+
+

-
+


-
-
+
+

-
+



-
+


-
+



-
+







-
+


-
+




-
-
+
+


-
+


-
+



-
+



-
+



-
+


-
+



-
+


-
+









-
-
+
+









+
+
-
+
+




# Commands covered:  http::config, http::geturl, http::wait, http::reset
#
# This file contains a collection of tests for the http script library.
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 by Ajuba Solutions.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-2000 Ajuba Solutions.
#
# 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::*
}

if {[catch {package require http 2} version]} {
    if {[info exists http2]} {
package require http 2.10
#http::register http 80 ::socket
	catch {puts "Cannot load http 2.* package"}
	return
    } else {
	catch {puts "Running http 2.* tests in child interp"}
	set interp [interp create http2]
	$interp eval [list set http2 "running"]
	$interp eval [list set argv $argv]
	$interp eval [list source [info script]]
	interp delete $interp
	return
    }

}
# To write a separate summary for each value of ThreadLevel, set constraint ThreadLevelSummary.
#testConstraint ThreadLevelSummary 0

proc bgerror {args} {
    global errorInfo
    puts stderr "http.test bgerror"
    puts stderr [join $args]
    puts stderr $errorInfo
}

if {$::tcl_platform(os) eq "Darwin"} {
    # Name resolution often a problem on OSX; not focus of HTTP package anyway
    set HOST localhost
# Do not use [info hostname].
# Name resolution is often a problem on OSX; not focus of HTTP package anyway.
# Also a problem on other platforms for http-4.14 (test with bad port number).
set HOST localhost
} else {
    set HOST [info hostname]
}

set bindata "This is binary data\x0d\x0amore\x0dmore\x0amore\x00null"
set bindata "This is binary data\x0D\x0Amore\x0Dmore\x0Amore\x00null"
catch {unset data}

# Ensure httpd file exists

set origFile [file join [pwd] [file dirname [info script]] httpd]
set httpdFile [file join [temporaryDirectory] httpd_[pid]]
if {![file exists $httpdFile]} {
    makeFile "" $httpdFile
    file delete $httpdFile
    file copy $origFile $httpdFile
    set removeHttpd 1
}

catch {package require Thread 2.7-}
if {[catch {package present Thread}] == 0 && [file exists $httpdFile]} {
    set httpthread [thread::create -preserved]
    lappend threadStack [list thread::release $httpthread]
    thread::send $httpthread [list source $httpdFile]
    thread::send $httpthread [list set bindata $bindata]
    thread::send $httpthread {httpd_init 0; set port} port
    puts "Running httpd in thread $httpthread"
} else {
    if {![file exists $httpdFile]} {
	puts "Cannot read $httpdFile script, http test skipped"
	unset port
	return
    }
    source $httpdFile
    # Let the OS pick the port; that's much more flexible
    if {[catch {httpd_init 0} listen]} {
	puts "Cannot start http server, http test skipped"
	catch {unset port}
	return
    }
    set threadStack {}
}

test http-1.1 {http::config} {

if 0 {
    # For debugging: run with a single value of ThreadLevel: 0|1|2
    set ThreadLevel 0
    testConstraint ThreadLevelSummary 1
}
if {![info exists ThreadLevel]} {
    if {[catch {package require Thread}] == 0} {
	set ValueRange {0 1 2}
    } else {
	set ValueRange {0 1}
    }

    # For each value of ThreadLevel, source this file recursively in the
    # same interpreter.
    foreach ThreadLevel $ValueRange {
	source [info script]
    }
    if {[llength $threadStack]} {
	eval [lpop threadStack]
    }
    catch {unset ThreadLevel}
    catch {unset ValueRange}
    if {![testConstraint ThreadLevelSummary]} {
	::tcltest::cleanupTests
    }
    return
}

catch {puts "==== Test with ThreadLevel $ThreadLevel ===="}
http::config -threadlevel $ThreadLevel

test http-1.1.$ThreadLevel {http::config} {
    http::config -useragent UserAgent
    http::config
} [list -accept */* -cookiejar {} -pipeline 1 -postfresh 0 -proxyfilter http::ProxyRequired -proxyhost {} -proxyport {} -repost 0 -urlencoding utf-8 -useragent UserAgent -zip 1]
test http-1.2 {http::config} {
} [list -accept */* -cookiejar {} -pipeline 1 -postfresh 0 -proxyauth {} -proxyfilter http::ProxyRequired -proxyhost {} -proxynot {} -proxyport {} -repost 0 -threadlevel $ThreadLevel -urlencoding utf-8 -useragent UserAgent -zip 1]
test http-1.2.$ThreadLevel {http::config} {
    http::config -proxyfilter
} http::ProxyRequired
test http-1.3 {http::config} {
test http-1.3.$ThreadLevel {http::config} {
    catch {http::config -junk}
} 1
test http-1.4 {http::config} {
test http-1.4.$ThreadLevel {http::config} {
    set savedconf [http::config]
    http::config -proxyhost nowhere.come -proxyport 8080 \
	-proxyfilter myFilter -useragent "Tcl Test Suite" \
	-urlencoding iso8859-1
    set x [http::config]
    http::config {*}$savedconf
    set x
} {-accept */* -cookiejar {} -pipeline 1 -postfresh 0 -proxyfilter myFilter -proxyhost nowhere.come -proxyport 8080 -repost 0 -urlencoding iso8859-1 -useragent {Tcl Test Suite} -zip 1}
test http-1.5 {http::config} -returnCodes error -body {
} [list -accept */* -cookiejar {} -pipeline 1 -postfresh 0 -proxyauth {} -proxyfilter myFilter -proxyhost nowhere.come -proxynot {} -proxyport 8080 -repost 0 -threadlevel $ThreadLevel -urlencoding iso8859-1 -useragent {Tcl Test Suite} -zip 1]
test http-1.5.$ThreadLevel {http::config} -returnCodes error -body {
    http::config -proxyhost {} -junk 8080
} -result {Unknown option -junk, must be: -accept, -cookiejar, -pipeline, -postfresh, -proxyfilter, -proxyhost, -proxyport, -repost, -urlencoding, -useragent, -zip}
test http-1.6 {http::config} -setup {
} -result {Unknown option -junk, must be: -accept, -cookiejar, -pipeline, -postfresh, -proxyauth, -proxyfilter, -proxyhost, -proxynot, -proxyport, -repost, -threadlevel, -urlencoding, -useragent, -zip}
test http-1.6.$ThreadLevel {http::config} -setup {
    set oldenc [http::config -urlencoding]
} -body {
    set enc [list [http::config -urlencoding]]
    http::config -urlencoding iso8859-1
    lappend enc [http::config -urlencoding]
} -cleanup {
    http::config -urlencoding $oldenc
} -result {utf-8 iso8859-1}

test http-2.1 {http::reset} {
test http-2.1.$ThreadLevel {http::reset} {
    catch {http::reset http#1}
} 0
test http-2.2.$ThreadLevel {http::CharsetToEncoding} {
    http::CharsetToEncoding iso-8859-11
} iso8859-11
test http-2.3.$ThreadLevel {http::CharsetToEncoding} {
    http::CharsetToEncoding iso-2022-kr
} iso2022-kr
test http-2.4.$ThreadLevel {http::CharsetToEncoding} {
    http::CharsetToEncoding shift-jis
} shiftjis
test http-2.5.$ThreadLevel {http::CharsetToEncoding} {
    http::CharsetToEncoding windows-437
} cp437
test http-2.6.$ThreadLevel {http::CharsetToEncoding} {
    http::CharsetToEncoding latin5
} iso8859-9
test http-2.7.$ThreadLevel {http::CharsetToEncoding} {
    http::CharsetToEncoding latin1
} iso8859-1
test http-2.8.$ThreadLevel {http::CharsetToEncoding} {
    http::CharsetToEncoding latin4
} binary

test http-3.1 {http::geturl} -returnCodes error -body {
test http-3.1.$ThreadLevel {http::geturl} -returnCodes error -body {
    http::geturl -bogus flag
} -result {Unknown option flag, can be: -binary, -blocksize, -channel, -command, -handler, -headers, -keepalive, -method, -myaddr, -progress, -protocol, -query, -queryblocksize, -querychannel, -queryprogress, -strict, -timeout, -type, -validate}
test http-3.2 {http::geturl} -returnCodes error -body {
} -result {Unknown option flag, can be: -binary, -blocksize, -channel, -command, -guesstype, -handler, -headers, -keepalive, -method, -myaddr, -progress, -protocol, -query, -queryblocksize, -querychannel, -queryprogress, -strict, -timeout, -type, -validate}

test http-3.2.$ThreadLevel {http::geturl} -returnCodes error -body {
    http::geturl http:junk
} -result {Unsupported URL: http:junk}

set url //${::HOST}:$port
set badurl //${::HOST}:[expr $port+1]
test http-3.3 {http::geturl} -body {
set badurl //${::HOST}:[expr {$port+1}]
test http-3.3.$ThreadLevel {http::geturl} -body {
    set token [http::geturl $url]
    http::data $token
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
} -result "<html><head><title>HTTP/1.0 TEST</title></head><body>
<h1>Hello, World!</h1>
<h2>GET /</h2>
</body></html>"

set tail /a/b/c
set url //${::HOST}:$port/a/b/c
set fullurl HTTP://user:pass@${::HOST}:$port/a/b/c
set binurl //${::HOST}:$port/binary
set xmlurl //${::HOST}:$port/xml
set posturl //${::HOST}:$port/post
set badposturl //${::HOST}:$port/droppost
set authorityurl //${::HOST}:$port
set ipv6url http://\[::1\]:$port/

test http-3.4 {http::geturl} -body {
test http-3.4.$ThreadLevel {http::geturl} -body {
    set token [http::geturl $url]
    http::data $token
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
} -result "<html><head><title>HTTP/1.0 TEST</title></head><body>
<h1>Hello, World!</h1>
<h2>GET $tail</h2>
</body></html>"
proc selfproxy {host} {
    global port
    return [list ${::HOST} $port]
}
test http-3.5 {http::geturl} -body {
test http-3.5.$ThreadLevel {http::geturl} -body {
    http::config -proxyfilter selfproxy
    set token [http::geturl $url]
    http::data $token
} -cleanup {
    http::config -proxyfilter http::ProxyRequired
    http::cleanup $token
    catch {http::cleanup $token}
} -result "<html><head><title>HTTP/1.0 TEST</title></head><body>
<h1>Hello, World!</h1>
<h2>GET http:$url</h2>
</body></html>"
test http-3.6 {http::geturl} -body {
test http-3.6.$ThreadLevel {http::geturl} -body {
    http::config -proxyfilter bogus
    set token [http::geturl $url]
    http::data $token
} -cleanup {
    http::config -proxyfilter http::ProxyRequired
    http::cleanup $token
    catch {http::cleanup $token}
} -result "<html><head><title>HTTP/1.0 TEST</title></head><body>
<h1>Hello, World!</h1>
<h2>GET $tail</h2>
</body></html>"
test http-3.7 {http::geturl} -body {
test http-3.7.$ThreadLevel {http::geturl} -body {
    set token [http::geturl $url -headers {Pragma no-cache}]
    http::data $token
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
} -result "<html><head><title>HTTP/1.0 TEST</title></head><body>
<h1>Hello, World!</h1>
<h2>GET $tail</h2>
</body></html>"
test http-3.8 {http::geturl} -body {
test http-3.8.$ThreadLevel {http::geturl} -body {
    set token [http::geturl $url -query Name=Value&Foo=Bar -timeout 3000]
    http::data $token
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
} -result "<html><head><title>HTTP/1.0 TEST</title></head><body>
<h1>Hello, World!</h1>
<h2>POST $tail</h2>
<h2>Query</h2>
<dl>
<dt>Name<dd>Value
<dt>Foo<dd>Bar
</dl>
</body></html>"
test http-3.9 {http::geturl} -body {
test http-3.9.$ThreadLevel {http::geturl} -body {
    set token [http::geturl $url -validate 1]
    http::code $token
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
} -result "HTTP/1.0 200 OK"
test http-3.10 {http::geturl queryprogress} -setup {
test http-3.10.$ThreadLevel {http::geturl queryprogress} -setup {
    set query foo=bar
    set sep ""
    set i 0
    # Create about 120K of query data
    while {$i < 14} {
	incr i
	append query $sep$query
	set sep &
    }
} -body {
    proc postProgress {token x y} {
    proc postProgress {tok x y} {
	global postProgress
	lappend postProgress $y
    }
    set postProgress {}
    set t [http::geturl $posturl -keepalive 0 -query $query \
    set token [http::geturl $posturl -keepalive 0 -query $query \
	    -queryprogress postProgress -queryblocksize 16384]
    http::wait $t
    list [http::status $t] [string length $query] $postProgress [http::data $t]
    http::wait $token
    list [http::status $token] [string length $query] $postProgress [http::data $token]
} -cleanup {
    http::cleanup $t
    catch {http::cleanup $token}
} -result {ok 122879 {16384 32768 49152 65536 81920 98304 114688 122879} {Got 122879 bytes}}
test http-3.11 {http::geturl querychannel with -command} -setup {
test http-3.11.$ThreadLevel {http::geturl querychannel with -command} -setup {
    set query foo=bar
    set sep ""
    set i 0
    # Create about 120K of query data
    while {$i < 14} {
	incr i
	append query $sep$query
	set sep &
    }
    set file [makeFile $query outdata]
} -body {
    set fp [open $file]
    proc asyncCB {token} {
    proc asyncCB {tok} {
	global postResult
	lappend postResult [http::data $token]
	lappend postResult [http::data $tok]
    }
    set postResult [list ]
    set t [http::geturl $posturl -querychannel $fp]
    http::wait $t
    set testRes [list [http::status $t] [string length $query] [http::data $t]]
    set token [http::geturl $posturl -querychannel $fp]
    http::wait $token
    set testRes [list [http::status $token] [string length $query] [http::data $token]]
    # Now do async
    http::cleanup $t
    http::cleanup $token
    close $fp
    set fp [open $file]
    set t [http::geturl $posturl -querychannel $fp -command asyncCB]
    set token [http::geturl $posturl -querychannel $fp -command asyncCB]
    set postResult [list PostStart]
    http::wait $t
    http::wait $token
    close $fp
    lappend testRes [http::status $t] $postResult
    lappend testRes [http::status $token] $postResult
} -cleanup {
    removeFile outdata
    http::cleanup $t
    catch {http::cleanup $token}
} -result {ok 122879 {Got 122880 bytes} ok {PostStart {Got 122880 bytes}}}
# On Linux platforms when the client and server are on the same host, the
# client is unable to read the server's response one it hits the write error.
# The status is "eof".
# On Windows, the http::wait procedure gets a "connection reset by peer" error
# while reading the reply.
test http-3.12 {http::geturl querychannel with aborted request} -setup {
test http-3.12.$ThreadLevel {http::geturl querychannel with aborted request} -setup {
    set query foo=bar
    set sep ""
    set i 0
    # Create about 120K of query data
    while {$i < 14} {
	incr i
	append query $sep$query
	set sep &
    }
    set file [makeFile $query outdata]
} -constraints {nonPortable} -body {
    set fp [open $file]
    proc asyncCB {token} {
    proc asyncCB {tok} {
	global postResult
	lappend postResult [http::data $token]
	lappend postResult [http::data $tok]
    }
    proc postProgress {token x y} {
    proc postProgress {tok x y} {
	global postProgress
	lappend postProgress $y
    }
    set postProgress {}
    # Now do async
    set postResult [list PostStart]
    if {[catch {
	set t [http::geturl $badposturl -querychannel $fp -command asyncCB \
	set token [http::geturl $badposturl -querychannel $fp -command asyncCB \
		-queryprogress postProgress]
	http::wait $t
	upvar #0 $t state
	http::wait $token
	upvar #0 $token state
    } err]} {
	puts $::errorInfo
	error $err
    }
    list [http::status $t] [http::code $t]
    list [http::status $token] [http::code $token]
} -cleanup {
    removeFile outdata
    http::cleanup $t
    catch {http::cleanup $token}
} -result {ok {HTTP/1.0 200 Data follows}}
test http-3.13 {http::geturl socket leak test} {
test http-3.13.$ThreadLevel {http::geturl socket leak test} {
    set chanCount [llength [file channels]]
    for {set i 0} {$i < 3} {incr i} {
	catch {http::geturl $badurl -timeout 5000}
    }
    # No extra channels should be taken
    expr {[llength [file channels]] == $chanCount}
} 1
test http-3.14 "http::geturl $fullurl" -body {
test http-3.14.$ThreadLevel "http::geturl $fullurl" -body {
    set token [http::geturl $fullurl -validate 1]
    http::code $token
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
} -result "HTTP/1.0 200 OK"
test http-3.15 {http::geturl parse failures} -body {
test http-3.15.$ThreadLevel {http::geturl parse failures} -body {
    http::geturl "{invalid}:url"
} -returnCodes error -result {Unsupported URL: {invalid}:url}
test http-3.16 {http::geturl parse failures} -body {
test http-3.16.$ThreadLevel {http::geturl parse failures} -body {
    http::geturl http:relative/url
} -returnCodes error -result {Unsupported URL: http:relative/url}
test http-3.17 {http::geturl parse failures} -body {
test http-3.17.$ThreadLevel {http::geturl parse failures} -body {
    http::geturl /absolute/url
} -returnCodes error -result {Missing host part: /absolute/url}
test http-3.18 {http::geturl parse failures} -body {
test http-3.18.$ThreadLevel {http::geturl parse failures} -body {
    http::geturl http://somewhere:123456789/
} -returnCodes error -result {Invalid port number: 123456789}
test http-3.19 {http::geturl parse failures} -body {
test http-3.19.$ThreadLevel {http::geturl parse failures} -body {
    http::geturl http://{user}@somewhere
} -returnCodes error -result {Illegal characters in URL user}
test http-3.20 {http::geturl parse failures} -body {
test http-3.20.$ThreadLevel {http::geturl parse failures} -body {
    http::geturl http://%user@somewhere
} -returnCodes error -result {Illegal encoding character usage "%us" in URL user}
test http-3.21 {http::geturl parse failures} -body {
test http-3.21.$ThreadLevel {http::geturl parse failures} -body {
    http::geturl http://somewhere/{path}
} -returnCodes error -result {Illegal characters in URL path}
test http-3.22 {http::geturl parse failures} -body {
test http-3.22.$ThreadLevel {http::geturl parse failures} -body {
    http::geturl http://somewhere/%path
} -returnCodes error -result {Illegal encoding character usage "%pa" in URL path}
test http-3.23 {http::geturl parse failures} -body {
test http-3.23.$ThreadLevel {http::geturl parse failures} -body {
    http::geturl http://somewhere/path?{query}?
} -returnCodes error -result {Illegal characters in URL path}
test http-3.24 {http::geturl parse failures} -body {
test http-3.24.$ThreadLevel {http::geturl parse failures} -body {
    http::geturl http://somewhere/path?%query
} -returnCodes error -result {Illegal encoding character usage "%qu" in URL path}
test http-3.25 {http::meta} -setup {
test http-3.25.$ThreadLevel {http::meta} -setup {
    unset -nocomplain m token
} -body {
    set token [http::geturl $url -timeout 3000]
    array set m [http::meta $token]
    lsort [array names m]
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
    unset -nocomplain m token
} -result {Content-Length Content-Type Date}
test http-3.26 {http::meta} -setup {
} -result {content-length content-type date}
test http-3.26.$ThreadLevel {http::meta} -setup {
    unset -nocomplain m token
} -body {
    set token [http::geturl $url -headers {X-Check 1} -timeout 3000]
    array set m [http::meta $token]
    lsort [array names m]
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
    unset -nocomplain m token
} -result {Content-Length Content-Type Date X-Check}
test http-3.27 {http::geturl: -headers override -type} -body {
} -result {content-length content-type date x-check}
test http-3.27.$ThreadLevel {http::geturl: -headers override -type} -body {
    set token [http::geturl $url/headers -type "text/plain" -query dummy \
	    -headers [list "Content-Type" "text/plain;charset=utf-8"]]
    http::data $token
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
} -match regexp -result {(?n)Host .*
User-Agent .*
Connection close
Content-Type {text/plain;charset=utf-8}
Accept \*/\*
Accept-Encoding .*
Connection close
Content-Length 5}
test http-3.28 {http::geturl: -headers override -type default} -body {
test http-3.28.$ThreadLevel {http::geturl: -headers override -type default} -body {
    set token [http::geturl $url/headers -query dummy \
	    -headers [list "Content-Type" "text/plain;charset=utf-8"]]
    http::data $token
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
} -match regexp -result {(?n)Host .*
User-Agent .*
Connection close
Content-Type {text/plain;charset=utf-8}
Accept \*/\*
Accept-Encoding .*
Connection close
Content-Length 5}
test http-3.29 {http::geturl IPv6 address} -body {
test http-3.29.$ThreadLevel {http::geturl IPv6 address} -body {
    # We only want to see if the URL gets parsed correctly. This is
    # the case if http::geturl succeeds or returns a socket related
    # error. If the parsing is wrong, we'll get a parse error.
    # It'd be better to separate the URL parser from http::geturl, so
    # that it can be tested without also trying to make a connection.
    set error [catch {http::geturl $ipv6url -validate 1} token]
    if {$error && [string match "couldn't open socket: *" $token]} {
            set error 0
	set error 0
    }
    set error
} -cleanup {
    catch { http::cleanup $token }
    catch {http::cleanup $token}
} -result 0
test http-3.30 {http::geturl query without path} -body {
test http-3.30.$ThreadLevel {http::geturl query without path} -body {
    set token [http::geturl $authorityurl?var=val]
    http::ncode $token
} -cleanup {
    catch { http::cleanup $token }
    catch {http::cleanup $token}
} -result 200
test http-3.31 {http::geturl fragment without path} -body {
test http-3.31.$ThreadLevel {http::geturl fragment without path} -body {
    set token [http::geturl "$authorityurl#fragment42"]
    http::ncode $token
} -cleanup {
    catch { http::cleanup $token }
    catch {http::cleanup $token}
} -result 200
# Bug c11a51c482
test http-3.32 {http::geturl: -headers override -accept default} -body {
test http-3.32.$ThreadLevel {http::geturl: -headers override -accept default} -body {
    set token [http::geturl $url/headers -query dummy \
	    -headers [list "Accept" "text/plain,application/tcl-test-value"]]
    http::data $token
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
} -match regexp -result {(?n)Host .*
User-Agent .*
Connection close
Accept text/plain,application/tcl-test-value
Accept-Encoding .*
Connection close
Content-Type application/x-www-form-urlencoded
Content-Length 5}
# Bug 838e99a76d
test http-3.33 {http::geturl application/xml is text} -body {
test http-3.33.$ThreadLevel {http::geturl application/xml is text} -body {
    set token [http::geturl "$xmlurl"]
    scan [http::data $token] "<%\[^>]>%c<%\[^>]>"
} -cleanup {
    catch { http::cleanup $token }
    catch {http::cleanup $token}
} -result {test 4660 /test}
test http-3.34 {http::geturl -headers not a dict} -returnCodes error -body {
    http::geturl http://test/t -headers NoDict
} -result {Bad value for -headers (NoDict), must be dict}
test http-3.34.$ThreadLevel {http::geturl -headers not a list} -returnCodes error -body {
    http::geturl http://test/t -headers \"
} -result "Bad value for -headers (\"), must be list"
test http-3.35.$ThreadLevel {http::geturl -headers not even number of elements} -returnCodes error -body {
    http::geturl http://test/t -headers {List Length 3}
} -result {Bad value for -headers (List Length 3), number of list elements must be even}

test http-4.1 {http::Event} -body {
test http-4.1.$ThreadLevel {http::Event} -body {
    set token [http::geturl $url -keepalive 0]
    upvar #0 $token data
    array set meta $data(meta)
    expr {($data(totalsize) == $meta(Content-Length))}
    expr {($data(totalsize) == $meta(content-length))}
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
} -result 1
test http-4.2 {http::Event} -body {
test http-4.2.$ThreadLevel {http::Event} -body {
    set token [http::geturl $url]
    upvar #0 $token data
    array set meta $data(meta)
    string compare $data(type) [string trim $meta(Content-Type)]
    string compare $data(type) [string trim $meta(content-type)]
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
} -result 0
test http-4.3 {http::Event} -body {
test http-4.3.$ThreadLevel {http::Event} -body {
    set token [http::geturl $url]
    http::code $token
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
} -result {HTTP/1.0 200 Data follows}
test http-4.4 {http::Event} -setup {
test http-4.4.$ThreadLevel {http::Event} -setup {
    set testfile [makeFile "" testfile]
} -body {
    set out [open $testfile w]
    set token [http::geturl $url -channel $out]
    close $out
    set in [open $testfile]
    set x [read $in]
} -cleanup {
    catch {close $in}
    catch {close $out}
    removeFile $testfile
    http::cleanup $token
    catch {http::cleanup $token}
} -result "<html><head><title>HTTP/1.0 TEST</title></head><body>
<h1>Hello, World!</h1>
<h2>GET $tail</h2>
</body></html>"
test http-4.5 {http::Event} -setup {
test http-4.5.$ThreadLevel {http::Event} -setup {
    set testfile [makeFile "" testfile]
} -body {
    set out [open $testfile w]
    fconfigure $out -translation lf
    set token [http::geturl $url -channel $out]
    close $out
    upvar #0 $token data
    expr {$data(currentsize) == $data(totalsize)}
} -cleanup {
    removeFile $testfile
    http::cleanup $token
    catch {http::cleanup $token}
} -result 1
test http-4.6 {http::Event} -setup {
test http-4.6.$ThreadLevel {http::Event} -setup {
    set testfile [makeFile "" testfile]
} -body {
    set out [open $testfile w]
    set token [http::geturl $binurl -channel $out]
    close $out
    set in [open $testfile]
    fconfigure $in -translation binary
    read $in
} -cleanup {
    catch {close $in}
    catch {close $out}
    removeFile $testfile
    http::cleanup $token
    catch {http::cleanup $token}
} -result "$bindata[string trimleft $binurl /]"
proc myProgress {token total current} {
    global progress httpLog
    if {[info exists httpLog] && $httpLog} {
	puts "progress $total $current"
    }
    set progress [list $total $current]
}
test http-4.6.1 {http::Event} knownBug {
test http-4.6.1.$ThreadLevel {http::Event} knownBug {
    set token [http::geturl $url -blocksize 50 -progress myProgress]
    return $progress
} {111 111}
test http-4.7 {http::Event} -body {
test http-4.7.$ThreadLevel {http::Event} -body {
    set token [http::geturl $url -keepalive 0 -progress myProgress]
    return $progress
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
} -result {111 111}
test http-4.8 {http::Event} -body {
test http-4.8.$ThreadLevel {http::Event} -body {
    set token [http::geturl $url]
    http::status $token
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
} -result {ok}
test http-4.9 {http::Event} -body {
test http-4.9.$ThreadLevel {http::Event} -body {
    set token [http::geturl $url -progress myProgress]
    http::code $token
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
} -result {HTTP/1.0 200 Data follows}
test http-4.10 {http::Event} -body {
test http-4.10.$ThreadLevel {http::Event} -body {
    set token [http::geturl $url -progress myProgress]
    http::size $token
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
} -result {111}

# Timeout cases
#	Short timeout to working server (the test server). This lets us try a
#	reset during the connection.
test http-4.11 {http::Event} -body {
test http-4.11.$ThreadLevel {http::Event} -body {
    set token [http::geturl $url -timeout 1 -keepalive 0 -command \#]
    http::reset $token
    http::status $token
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
} -result {reset}

#	Longer timeout with reset.
test http-4.12 {http::Event} -body {
test http-4.12.$ThreadLevel {http::Event} -body {
    set token [http::geturl $url/?timeout=10 -keepalive 0 -command \#]
    http::reset $token
    http::status $token
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
} -result {reset}

#	Medium timeout to working server that waits even longer. The timeout
#	hits while waiting for a reply.
test http-4.13 {http::Event} -body {
test http-4.13.$ThreadLevel {http::Event} -body {
    set token [http::geturl $url?timeout=30 -keepalive 0 -timeout 10 -command \#]
    http::wait $token
    http::status $token
} -cleanup {
    http::cleanup $token
    catch {http::cleanup $token}
} -result {timeout}

#	Longer timeout to good host, bad port, gets an error after the
#	connection "completes" but the socket is bad.
test http-4.14 {http::Event} -body {
test http-4.14.$ThreadLevel {http::Event} -body {
    set token [http::geturl $badurl/?timeout=10 -timeout 10000 -command \#]
    if {$token eq ""} {
	error "bogus return from http::geturl"
    }
    http::wait $token
    lindex [http::error $token] 0
} -cleanup {
    catch {http::cleanup $token}
} -result {connect failed connection refused}
} -result {connect failed: connection refused}

# Bogus host
test http-4.15 {http::Event} -body {
    # This test may fail if you use a proxy server. That is to be
    # expected and is not a problem with Tcl.
    set token [http::geturl //not_a_host.tcl.tk -timeout 3000 -command \#]
test http-4.15.$ThreadLevel {http::Event} -body {
    # 1. The test assumes that http is not using a proxy server.
    #    If http is using a proxy server, the latter is responsible for the DNS
    #    lookup of the non-existent host. Squid responds with
    #    "503 Service Unavailable" and an explanatory response body; but other
    #    proxies may respond differently.
    # 2. The [socket] command blocks during the DNS lookup.
    #    - When [socket] runs in the main thread (i.e. when -threadlevel is 0 or
    #      (if Thread package not available) 1), the script cannot time out
    #      during a prolonged DNS lookup.
    #    - When [socket] runs in a separate thread (i.e. when the Thread package
    #      is available and [http::config -threadlevel] is 1 or 2), the main
    #      thread enters the event loop and has the opportunity to time out
    #      during the DNS lookup.  This causes the test to fail.
    #    - The test uses a long -timeout so that it is not confounded by a slow
    #      DNS lookup.
    #    - If the error result is "timeout", this suggests a problem with
    #      negative DNS lookups on the test host.  Compare the timings for
    #      different values of threadLevel.
    # set t0 [clock milliseconds]
    set token [http::geturl //not-a-host.nodns. -timeout 30000 -command \#]
    http::wait $token
    # set t1 [clock milliseconds]
    # puts "Test http-4.15.$ThreadLevel - time taken: [expr {$t1 - $t0}] ms"
    http::status $token
    set result "[http::status $token] -- [lindex [http::error $token] 0]"
    # error codes vary among platforms.
} -cleanup {
    catch {http::cleanup $token}
} -returnCodes 1 -match glob -result "couldn't open socket*"
test http-4.16 {Leak with Close vs Keepalive (bug [6ca52aec14]} -setup {
} -match glob -result "error -- couldn't open socket*"

test http-4.16.$ThreadLevel {Leak with Close vs Keepalive (bug [6ca52aec14]} -setup {
    proc list-difference {l1 l2} {
	lmap item $l2 {if {$item in $l1} continue; set item}
    }
} -body {
    set before [chan names]
    set token [http::geturl $url -headers {X-Connection keep-alive}]
    http::cleanup $token
    update
    # Compute what channels have been unexpectedly leaked past cleanup
    list-difference $before [chan names]
} -cleanup {
    rename list-difference {}
} -result {}

test http-5.1 {http::formatQuery} {
test http-5.1.$ThreadLevel {http::formatQuery} {
    http::formatQuery name1 value1 name2 "value two"
} {name1=value1&name2=value%20two}
# test http-5.2 obsoleted by 5.4 and 5.5 with http 2.5
test http-5.3 {http::formatQuery} {
test http-5.3.$ThreadLevel {http::formatQuery} {
    http::formatQuery lines "line1\nline2\nline3"
} {lines=line1%0D%0Aline2%0D%0Aline3}
test http-5.4 {http::formatQuery} {
    http::formatQuery name1 ~bwelch name2 \xa1\xa2\xa2
test http-5.4.$ThreadLevel {http::formatQuery} {
    http::formatQuery name1 ~bwelch name2 ¡¢¢
} {name1=~bwelch&name2=%C2%A1%C2%A2%C2%A2}
test http-5.5 {http::formatQuery} {
test http-5.5.$ThreadLevel {http::formatQuery} {
    set enc [http::config -urlencoding]
    http::config -urlencoding iso8859-1
    set res [http::formatQuery name1 ~bwelch name2 \xa1\xa2\xa2]
    set res [http::formatQuery name1 ~bwelch name2 ¡¢¢]
    http::config -urlencoding $enc
    set res
} {name1=~bwelch&name2=%A1%A2%A2}

test http-6.1 {http::ProxyRequired} -body {
test http-6.1.$ThreadLevel {http::ProxyRequired} -body {
    http::config -proxyhost ${::HOST} -proxyport $port
    set token [http::geturl $url]
    http::wait $token
    upvar #0 $token data
    set data(body)
} -cleanup {
    http::config -proxyhost {} -proxyport {}
    http::cleanup $token
    catch {http::cleanup $token}
} -result "<html><head><title>HTTP/1.0 TEST</title></head><body>
<h1>Hello, World!</h1>
<h2>GET http:$url</h2>
</body></html>"

test http-7.1 {http::mapReply} {
test http-7.1.$ThreadLevel {http::mapReply} {
    http::mapReply "abc\$\[\]\"\\()\}\{"
} {abc%24%5B%5D%22%5C%28%29%7D%7B}
test http-7.2 {http::mapReply} {
test http-7.2.$ThreadLevel {http::mapReply} {
    # RFC 2718 specifies that we pass urlencoding on utf-8 chars by default,
    # so make sure this gets converted to utf-8 then urlencoded.
    http::mapReply "\u2208"
    http::mapReply "∈"
} {%E2%88%88}
test http-7.3 {http::formatQuery} -setup {
test http-7.3.$ThreadLevel {http::formatQuery} -setup {
    set enc [http::config -urlencoding]
} -returnCodes error -body {
    # this would be reverting to http <=2.4 behavior
    # -urlencoding "" no longer supported. Use "iso8859-1".
    http::config -urlencoding ""
    http::mapReply "\u2208"
    http::mapReply "∈"
} -cleanup {
    http::config -urlencoding $enc
} -result "can't read \"formMap(\u2208)\": no such element in array"
test http-7.4 {http::formatQuery} -setup {
} -result {unknown encoding ""}
test http-7.4.$ThreadLevel {http::formatQuery} -setup {
    set enc [http::config -urlencoding]
} -constraints {
    knownProfileBug
} -body {
    # this would be reverting to http <=2.4 behavior w/o errors
    # (unknown chars become '?')
    # with Tcl 8.x (unknown chars become '?'), generating a
    # proper exception with Tcl 9.0
    http::config -urlencoding "iso8859-1"
    http::mapReply "\u2208"
    http::mapReply "∈"
} -cleanup {
    http::config -urlencoding $enc
} -result {%3F}
} -errorCode {TCL ENCODING ILLEGALSEQUENCE 0} -result {unexpected character at index 0: 'U+002208'}

package require tcl::idna 1.0

test http-idna-1.1 {IDNA package: basics} -returnCodes error -body {
test http-idna-1.1.$ThreadLevel {IDNA package: basics} -returnCodes error -body {
    ::tcl::idna
} -result {wrong # args: should be "::tcl::idna subcommand ?arg ...?"}
test http-idna-1.2 {IDNA package: basics} -returnCodes error -body {
test http-idna-1.2.$ThreadLevel {IDNA package: basics} -returnCodes error -body {
    ::tcl::idna ?
} -result {unknown or ambiguous subcommand "?": must be decode, encode, puny, or version}
test http-idna-1.3 {IDNA package: basics} -body {
test http-idna-1.3.$ThreadLevel {IDNA package: basics} -body {
    ::tcl::idna version
} -result 1.0.1
test http-idna-1.4 {IDNA package: basics} -returnCodes error -body {
test http-idna-1.4.$ThreadLevel {IDNA package: basics} -returnCodes error -body {
    ::tcl::idna version what
} -result {wrong # args: should be "::tcl::idna version"}
test http-idna-1.5 {IDNA package: basics} -returnCodes error -body {
test http-idna-1.5.$ThreadLevel {IDNA package: basics} -returnCodes error -body {
    ::tcl::idna puny
} -result {wrong # args: should be "::tcl::idna puny subcommand ?arg ...?"}
test http-idna-1.6 {IDNA package: basics} -returnCodes error -body {
test http-idna-1.6.$ThreadLevel {IDNA package: basics} -returnCodes error -body {
    ::tcl::idna puny ?
} -result {unknown or ambiguous subcommand "?": must be decode, or encode}
test http-idna-1.7 {IDNA package: basics} -returnCodes error -body {
test http-idna-1.7.$ThreadLevel {IDNA package: basics} -returnCodes error -body {
    ::tcl::idna puny encode
} -result {wrong # args: should be "::tcl::idna puny encode string ?case?"}
test http-idna-1.8 {IDNA package: basics} -returnCodes error -body {
test http-idna-1.8.$ThreadLevel {IDNA package: basics} -returnCodes error -body {
    ::tcl::idna puny encode a b c
} -result {wrong # args: should be "::tcl::idna puny encode string ?case?"}
test http-idna-1.9 {IDNA package: basics} -returnCodes error -body {
test http-idna-1.9.$ThreadLevel {IDNA package: basics} -returnCodes error -body {
    ::tcl::idna puny decode
} -result {wrong # args: should be "::tcl::idna puny decode string ?case?"}
test http-idna-1.10 {IDNA package: basics} -returnCodes error -body {
test http-idna-1.10.$ThreadLevel {IDNA package: basics} -returnCodes error -body {
    ::tcl::idna puny decode a b c
} -result {wrong # args: should be "::tcl::idna puny decode string ?case?"}
test http-idna-1.11 {IDNA package: basics} -returnCodes error -body {
test http-idna-1.11.$ThreadLevel {IDNA package: basics} -returnCodes error -body {
    ::tcl::idna decode
} -result {wrong # args: should be "::tcl::idna decode hostname"}
test http-idna-1.12 {IDNA package: basics} -returnCodes error -body {
test http-idna-1.12.$ThreadLevel {IDNA package: basics} -returnCodes error -body {
    ::tcl::idna encode
} -result {wrong # args: should be "::tcl::idna encode hostname"}

test http-idna-2.1 {puny encode: functional test} {
test http-idna-2.1.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode abc
} abc-
test http-idna-2.2 {puny encode: functional test} {
    ::tcl::idna puny encode a\u20acb\u20acc
test http-idna-2.2.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode a€b€c
} abc-k50ab
test http-idna-2.3 {puny encode: functional test} {
test http-idna-2.3.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode ABC
} ABC-
test http-idna-2.4 {puny encode: functional test} {
    ::tcl::idna puny encode A\u20ACB\u20ACC
test http-idna-2.4.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode A€B€C
} ABC-k50ab
test http-idna-2.5 {puny encode: functional test} {
test http-idna-2.5.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode ABC 0
} abc-
test http-idna-2.6 {puny encode: functional test} {
    ::tcl::idna puny encode A\u20ACB\u20ACC 0
test http-idna-2.6.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode A€B€C 0
} abc-k50ab
test http-idna-2.7 {puny encode: functional test} {
test http-idna-2.7.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode ABC 1
} ABC-
test http-idna-2.8 {puny encode: functional test} {
    ::tcl::idna puny encode A\u20ACB\u20ACC 1
test http-idna-2.8.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode A€B€C 1
} ABC-k50ab
test http-idna-2.9 {puny encode: functional test} {
test http-idna-2.9.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode abc 0
} abc-
test http-idna-2.10 {puny encode: functional test} {
    ::tcl::idna puny encode a\u20ACb\u20ACc 0
test http-idna-2.10.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode a€b€c 0
} abc-k50ab
test http-idna-2.11 {puny encode: functional test} {
test http-idna-2.11.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode abc 1
} ABC-
test http-idna-2.12 {puny encode: functional test} {
    ::tcl::idna puny encode a\u20ACb\u20ACc 1
test http-idna-2.12.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode a€b€c 1
} ABC-k50ab
test http-idna-2.13 {puny encode: edge cases} {
test http-idna-2.13.$ThreadLevel {puny encode: edge cases} {
    ::tcl::idna puny encode ""
} ""
test http-idna-2.14-A {puny encode: examples from RFC 3492} {
test http-idna-2.14-A.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode [join [subst [string map {u+ \\u} {
	u+0644 u+064A u+0647 u+0645 u+0627 u+0628 u+062A u+0643 u+0644
	u+0645 u+0648 u+0634 u+0639 u+0631 u+0628 u+064A u+061F
    }]] ""]
} egbpdaj6bu4bxfgehfvwxn
test http-idna-2.14-B {puny encode: examples from RFC 3492} {
test http-idna-2.14-B.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode [join [subst [string map {u+ \\u} {
	u+4ED6 u+4EEC u+4E3A u+4EC0 u+4E48 u+4E0D u+8BF4 u+4E2D u+6587
    }]] ""]
} ihqwcrb4cv8a8dqg056pqjye
test http-idna-2.14-C {puny encode: examples from RFC 3492} {
test http-idna-2.14-C.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode [join [subst [string map {u+ \\u} {
	u+4ED6 u+5011 u+7232 u+4EC0 u+9EBD u+4E0D u+8AAA u+4E2D u+6587
    }]] ""]
} ihqwctvzc91f659drss3x8bo0yb
test http-idna-2.14-D {puny encode: examples from RFC 3492} {
test http-idna-2.14-D.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode [join [subst [string map {u+ \\u} {
	u+0050 u+0072 u+006F u+010D u+0070 u+0072 u+006F u+0073 u+0074
	u+011B u+006E u+0065 u+006D u+006C u+0075 u+0076 u+00ED u+010D
	u+0065 u+0073 u+006B u+0079
    }]] ""]
} Proprostnemluvesky-uyb24dma41a
test http-idna-2.14-E {puny encode: examples from RFC 3492} {
test http-idna-2.14-E.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode [join [subst [string map {u+ \\u} {
	u+05DC u+05DE u+05D4 u+05D4 u+05DD u+05E4 u+05E9 u+05D5 u+05D8
	u+05DC u+05D0 u+05DE u+05D3 u+05D1 u+05E8 u+05D9 u+05DD u+05E2
	u+05D1 u+05E8 u+05D9 u+05EA
    }]] ""]
} 4dbcagdahymbxekheh6e0a7fei0b
test http-idna-2.14-F {puny encode: examples from RFC 3492} {
test http-idna-2.14-F.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode [join [subst [string map {u+ \\u} {
	u+092F u+0939 u+0932 u+094B u+0917 u+0939 u+093F u+0928 u+094D
	u+0926 u+0940 u+0915 u+094D u+092F u+094B u+0902 u+0928 u+0939
	u+0940 u+0902 u+092C u+094B u+0932 u+0938 u+0915 u+0924 u+0947
	u+0939 u+0948 u+0902
    }]] ""]
} i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd
test http-idna-2.14-G {puny encode: examples from RFC 3492} {
test http-idna-2.14-G.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode [join [subst [string map {u+ \\u} {
	u+306A u+305C u+307F u+3093 u+306A u+65E5 u+672C u+8A9E u+3092
	u+8A71 u+3057 u+3066 u+304F u+308C u+306A u+3044 u+306E u+304B
    }]] ""]
} n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa
test http-idna-2.14-H {puny encode: examples from RFC 3492} {
test http-idna-2.14-H.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode [join [subst [string map {u+ \\u} {
	u+C138 u+ACC4 u+C758 u+BAA8 u+B4E0 u+C0AC u+B78C u+B4E4 u+C774
	u+D55C u+AD6D u+C5B4 u+B97C u+C774 u+D574 u+D55C u+B2E4 u+BA74
	u+C5BC u+B9C8 u+B098 u+C88B u+C744 u+AE4C
    }]] ""]
} 989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5jpsd879ccm6fea98c
test http-idna-2.14-I {puny encode: examples from RFC 3492} {
test http-idna-2.14-I.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode [join [subst [string map {u+ \\u} {
	u+043F u+043E u+0447 u+0435 u+043C u+0443 u+0436 u+0435 u+043E
	u+043D u+0438 u+043D u+0435 u+0433 u+043E u+0432 u+043E u+0440
	u+044F u+0442 u+043F u+043E u+0440 u+0443 u+0441 u+0441 u+043A
	u+0438
    }]] ""]
} b1abfaaepdrnnbgefbadotcwatmq2g4l
test http-idna-2.14-J {puny encode: examples from RFC 3492} {
test http-idna-2.14-J.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode [join [subst [string map {u+ \\u} {
	u+0050 u+006F u+0072 u+0071 u+0075 u+00E9 u+006E u+006F u+0070
	u+0075 u+0065 u+0064 u+0065 u+006E u+0073 u+0069 u+006D u+0070
	u+006C u+0065 u+006D u+0065 u+006E u+0074 u+0065 u+0068 u+0061
	u+0062 u+006C u+0061 u+0072 u+0065 u+006E u+0045 u+0073 u+0070
	u+0061 u+00F1 u+006F u+006C
    }]] ""]
} PorqunopuedensimplementehablarenEspaol-fmd56a
test http-idna-2.14-K {puny encode: examples from RFC 3492} {
test http-idna-2.14-K.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode [join [subst [string map {u+ \\u} {
	u+0054 u+1EA1 u+0069 u+0073 u+0061 u+006F u+0068 u+1ECD u+006B
	u+0068 u+00F4 u+006E u+0067 u+0074 u+0068 u+1EC3 u+0063 u+0068
	u+1EC9 u+006E u+00F3 u+0069 u+0074 u+0069 u+1EBF u+006E u+0067
	u+0056 u+0069 u+1EC7 u+0074
    }]] ""]
} TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g
test http-idna-2.14-L {puny encode: examples from RFC 3492} {
test http-idna-2.14-L.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode [join [subst [string map {u+ \\u} {
	u+0033 u+5E74 u+0042 u+7D44 u+91D1 u+516B u+5148 u+751F
    }]] ""]
} 3B-ww4c5e180e575a65lsy2b
test http-idna-2.14-M {puny encode: examples from RFC 3492} {
test http-idna-2.14-M.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode [join [subst [string map {u+ \\u} {
	u+5B89 u+5BA4 u+5948 u+7F8E u+6075 u+002D u+0077 u+0069 u+0074
	u+0068 u+002D u+0053 u+0055 u+0050 u+0045 u+0052 u+002D u+004D
	u+004F u+004E u+004B u+0045 u+0059 u+0053
    }]] ""]
} -with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n
test http-idna-2.14-N {puny encode: examples from RFC 3492} {
test http-idna-2.14-N.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode [join [subst [string map {u+ \\u} {
	u+0048 u+0065 u+006C u+006C u+006F u+002D u+0041 u+006E u+006F
	u+0074 u+0068 u+0065 u+0072 u+002D u+0057 u+0061 u+0079 u+002D
	u+305D u+308C u+305E u+308C u+306E u+5834 u+6240
    }]] ""]
} Hello-Another-Way--fc4qua05auwb3674vfr0b
test http-idna-2.14-O {puny encode: examples from RFC 3492} {
test http-idna-2.14-O.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode [join [subst [string map {u+ \\u} {
	u+3072 u+3068 u+3064 u+5C4B u+6839 u+306E u+4E0B u+0032
    }]] ""]
} 2-u9tlzr9756bt3uc0v
test http-idna-2.14-P {puny encode: examples from RFC 3492} {
test http-idna-2.14-P.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode [join [subst [string map {u+ \\u} {
	u+004D u+0061 u+006A u+0069 u+3067 u+004B u+006F u+0069 u+3059
	u+308B u+0035 u+79D2 u+524D
    }]] ""]
} MajiKoi5-783gue6qz075azm5e
test http-idna-2.14-Q {puny encode: examples from RFC 3492} {
test http-idna-2.14-Q.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode [join [subst [string map {u+ \\u} {
	u+30D1 u+30D5 u+30A3 u+30FC u+0064 u+0065 u+30EB u+30F3 u+30D0
    }]] ""]
} de-jg4avhby1noc0d
test http-idna-2.14-R {puny encode: examples from RFC 3492} {
test http-idna-2.14-R.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode [join [subst [string map {u+ \\u} {
	u+305D u+306E u+30B9 u+30D4 u+30FC u+30C9 u+3067
    }]] ""]
} d9juau41awczczp
test http-idna-2.14-S {puny encode: examples from RFC 3492} {
test http-idna-2.14-S.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode {-> $1.00 <-}
} {-> $1.00 <--}

test http-idna-3.1 {puny decode: functional test} {
test http-idna-3.1.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode abc-
} abc
test http-idna-3.2 {puny decode: functional test} {
test http-idna-3.2.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode abc-k50ab
} a\u20acb\u20acc
test http-idna-3.3 {puny decode: functional test} {
} a€b€c
test http-idna-3.3.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode ABC-
} ABC
test http-idna-3.4 {puny decode: functional test} {
test http-idna-3.4.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode ABC-k50ab
} A\u20ACB\u20ACC
test http-idna-3.5 {puny decode: functional test} {
} A€B€C
test http-idna-3.5.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode ABC-K50AB
} A\u20ACB\u20ACC
test http-idna-3.6 {puny decode: functional test} {
} A€B€C
test http-idna-3.6.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode abc-K50AB
} a\u20ACb\u20ACc
test http-idna-3.7 {puny decode: functional test} {
} a€b€c
test http-idna-3.7.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode ABC- 0
} abc
test http-idna-3.8 {puny decode: functional test} {
test http-idna-3.8.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode ABC-K50AB 0
} a\u20ACb\u20ACc
test http-idna-3.9 {puny decode: functional test} {
} a€b€c
test http-idna-3.9.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode ABC- 1
} ABC
test http-idna-3.10 {puny decode: functional test} {
test http-idna-3.10.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode ABC-K50AB 1
} A\u20ACB\u20ACC
test http-idna-3.11 {puny decode: functional test} {
} A€B€C
test http-idna-3.11.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode abc- 0
} abc
test http-idna-3.12 {puny decode: functional test} {
test http-idna-3.12.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode abc-k50ab 0
} a\u20ACb\u20ACc
test http-idna-3.13 {puny decode: functional test} {
} a€b€c
test http-idna-3.13.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode abc- 1
} ABC
test http-idna-3.14 {puny decode: functional test} {
test http-idna-3.14.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode abc-k50ab 1
} A\u20ACB\u20ACC
test http-idna-3.15 {puny decode: edge cases and errors} {
} A€B€C
test http-idna-3.15.$ThreadLevel {puny decode: edge cases and errors} {
    # Is this case actually correct?
    binary encode hex [encoding convertto utf-8 [::tcl::idna puny decode abc]]
} c282c281c280
test http-idna-3.16 {puny decode: edge cases and errors} -returnCodes error -body {
test http-idna-3.16.$ThreadLevel {puny decode: edge cases and errors} -returnCodes error -body {
    ::tcl::idna puny decode abc!
} -result {bad decode character "!"}
test http-idna-3.17 {puny decode: edge cases and errors} {
test http-idna-3.17.$ThreadLevel {puny decode: edge cases and errors} {
    catch {::tcl::idna puny decode abc!} -> opt
    dict get $opt -errorcode
} {PUNYCODE BAD_INPUT CHAR}
test http-idna-3.18 {puny decode: edge cases and errors} {
test http-idna-3.18.$ThreadLevel {puny decode: edge cases and errors} {
    ::tcl::idna puny decode ""
} {}
# A helper so we don't get lots of crap in failures
proc hexify s {lmap c [split $s ""] {format u+%04X [scan $c %c]}}
test http-idna-3.19-A {puny decode: examples from RFC 3492} {
test http-idna-3.19-A.$ThreadLevel {puny decode: examples from RFC 3492} {
    hexify [::tcl::idna puny decode egbpdaj6bu4bxfgehfvwxn]
} [list {*}{
    u+0644 u+064A u+0647 u+0645 u+0627 u+0628 u+062A u+0643 u+0644
    u+0645 u+0648 u+0634 u+0639 u+0631 u+0628 u+064A u+061F
}]
test http-idna-3.19-B {puny decode: examples from RFC 3492} {
test http-idna-3.19-B.$ThreadLevel {puny decode: examples from RFC 3492} {
    hexify [::tcl::idna puny decode ihqwcrb4cv8a8dqg056pqjye]
} {u+4ED6 u+4EEC u+4E3A u+4EC0 u+4E48 u+4E0D u+8BF4 u+4E2D u+6587}
test http-idna-3.19-C {puny decode: examples from RFC 3492} {
test http-idna-3.19-C.$ThreadLevel {puny decode: examples from RFC 3492} {
    hexify [::tcl::idna puny decode ihqwctvzc91f659drss3x8bo0yb]
} {u+4ED6 u+5011 u+7232 u+4EC0 u+9EBD u+4E0D u+8AAA u+4E2D u+6587}
test http-idna-3.19-D {puny decode: examples from RFC 3492} {
test http-idna-3.19-D.$ThreadLevel {puny decode: examples from RFC 3492} {
    hexify [::tcl::idna puny decode Proprostnemluvesky-uyb24dma41a]
} [list {*}{
    u+0050 u+0072 u+006F u+010D u+0070 u+0072 u+006F u+0073 u+0074
    u+011B u+006E u+0065 u+006D u+006C u+0075 u+0076 u+00ED u+010D
    u+0065 u+0073 u+006B u+0079
}]
test http-idna-3.19-E {puny decode: examples from RFC 3492} {
test http-idna-3.19-E.$ThreadLevel {puny decode: examples from RFC 3492} {
    hexify [::tcl::idna puny decode 4dbcagdahymbxekheh6e0a7fei0b]
} [list {*}{
    u+05DC u+05DE u+05D4 u+05D4 u+05DD u+05E4 u+05E9 u+05D5 u+05D8
    u+05DC u+05D0 u+05DE u+05D3 u+05D1 u+05E8 u+05D9 u+05DD u+05E2
    u+05D1 u+05E8 u+05D9 u+05EA
}]
test http-idna-3.19-F {puny decode: examples from RFC 3492} {
test http-idna-3.19-F.$ThreadLevel {puny decode: examples from RFC 3492} {
    hexify [::tcl::idna puny decode \
	i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd]
} [list {*}{
    u+092F u+0939 u+0932 u+094B u+0917 u+0939 u+093F u+0928 u+094D
    u+0926 u+0940 u+0915 u+094D u+092F u+094B u+0902 u+0928 u+0939
    u+0940 u+0902 u+092C u+094B u+0932 u+0938 u+0915 u+0924 u+0947
    u+0939 u+0948 u+0902
}]
test http-idna-3.19-G {puny decode: examples from RFC 3492} {
test http-idna-3.19-G.$ThreadLevel {puny decode: examples from RFC 3492} {
    hexify [::tcl::idna puny decode n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa]
} [list {*}{
    u+306A u+305C u+307F u+3093 u+306A u+65E5 u+672C u+8A9E u+3092
    u+8A71 u+3057 u+3066 u+304F u+308C u+306A u+3044 u+306E u+304B
}]
test http-idna-3.19-H {puny decode: examples from RFC 3492} {
test http-idna-3.19-H.$ThreadLevel {puny decode: examples from RFC 3492} {
    hexify [::tcl::idna puny decode \
	989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5jpsd879ccm6fea98c]
} [list {*}{
    u+C138 u+ACC4 u+C758 u+BAA8 u+B4E0 u+C0AC u+B78C u+B4E4 u+C774
    u+D55C u+AD6D u+C5B4 u+B97C u+C774 u+D574 u+D55C u+B2E4 u+BA74
    u+C5BC u+B9C8 u+B098 u+C88B u+C744 u+AE4C
}]
test http-idna-3.19-I {puny decode: examples from RFC 3492} {
test http-idna-3.19-I.$ThreadLevel {puny decode: examples from RFC 3492} {
    hexify [::tcl::idna puny decode b1abfaaepdrnnbgefbadotcwatmq2g4l]
} [list {*}{
    u+043F u+043E u+0447 u+0435 u+043C u+0443 u+0436 u+0435 u+043E
    u+043D u+0438 u+043D u+0435 u+0433 u+043E u+0432 u+043E u+0440
    u+044F u+0442 u+043F u+043E u+0440 u+0443 u+0441 u+0441 u+043A
    u+0438
}]
test http-idna-3.19-J {puny decode: examples from RFC 3492} {
test http-idna-3.19-J.$ThreadLevel {puny decode: examples from RFC 3492} {
    hexify [::tcl::idna puny decode \
	PorqunopuedensimplementehablarenEspaol-fmd56a]
} [list {*}{
    u+0050 u+006F u+0072 u+0071 u+0075 u+00E9 u+006E u+006F u+0070
    u+0075 u+0065 u+0064 u+0065 u+006E u+0073 u+0069 u+006D u+0070
    u+006C u+0065 u+006D u+0065 u+006E u+0074 u+0065 u+0068 u+0061
    u+0062 u+006C u+0061 u+0072 u+0065 u+006E u+0045 u+0073 u+0070
    u+0061 u+00F1 u+006F u+006C
}]
test http-idna-3.19-K {puny decode: examples from RFC 3492} {
test http-idna-3.19-K.$ThreadLevel {puny decode: examples from RFC 3492} {
    hexify [::tcl::idna puny decode \
	TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g]
} [list {*}{
    u+0054 u+1EA1 u+0069 u+0073 u+0061 u+006F u+0068 u+1ECD u+006B
    u+0068 u+00F4 u+006E u+0067 u+0074 u+0068 u+1EC3 u+0063 u+0068
    u+1EC9 u+006E u+00F3 u+0069 u+0074 u+0069 u+1EBF u+006E u+0067
    u+0056 u+0069 u+1EC7 u+0074
}]
test http-idna-3.19-L {puny decode: examples from RFC 3492} {
test http-idna-3.19-L.$ThreadLevel {puny decode: examples from RFC 3492} {
    hexify [::tcl::idna puny decode 3B-ww4c5e180e575a65lsy2b]
} {u+0033 u+5E74 u+0042 u+7D44 u+91D1 u+516B u+5148 u+751F}
test http-idna-3.19-M {puny decode: examples from RFC 3492} {
test http-idna-3.19-M.$ThreadLevel {puny decode: examples from RFC 3492} {
    hexify [::tcl::idna puny decode -with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n]
} [list {*}{
    u+5B89 u+5BA4 u+5948 u+7F8E u+6075 u+002D u+0077 u+0069 u+0074
    u+0068 u+002D u+0053 u+0055 u+0050 u+0045 u+0052 u+002D u+004D
    u+004F u+004E u+004B u+0045 u+0059 u+0053
}]
test http-idna-3.19-N {puny decode: examples from RFC 3492} {
test http-idna-3.19-N.$ThreadLevel {puny decode: examples from RFC 3492} {
    hexify [::tcl::idna puny decode Hello-Another-Way--fc4qua05auwb3674vfr0b]
} [list {*}{
    u+0048 u+0065 u+006C u+006C u+006F u+002D u+0041 u+006E u+006F
    u+0074 u+0068 u+0065 u+0072 u+002D u+0057 u+0061 u+0079 u+002D
    u+305D u+308C u+305E u+308C u+306E u+5834 u+6240
}]
test http-idna-3.19-O {puny decode: examples from RFC 3492} {
test http-idna-3.19-O.$ThreadLevel {puny decode: examples from RFC 3492} {
    hexify [::tcl::idna puny decode 2-u9tlzr9756bt3uc0v]
} {u+3072 u+3068 u+3064 u+5C4B u+6839 u+306E u+4E0B u+0032}
test http-idna-3.19-P {puny decode: examples from RFC 3492} {
test http-idna-3.19-P.$ThreadLevel {puny decode: examples from RFC 3492} {
    hexify [::tcl::idna puny decode MajiKoi5-783gue6qz075azm5e]
} [list {*}{
    u+004D u+0061 u+006A u+0069 u+3067 u+004B u+006F u+0069 u+3059
    u+308B u+0035 u+79D2 u+524D
}]
test http-idna-3.19-Q {puny decode: examples from RFC 3492} {
test http-idna-3.19-Q.$ThreadLevel {puny decode: examples from RFC 3492} {
    hexify [::tcl::idna puny decode de-jg4avhby1noc0d]
} {u+30D1 u+30D5 u+30A3 u+30FC u+0064 u+0065 u+30EB u+30F3 u+30D0}
test http-idna-3.19-R {puny decode: examples from RFC 3492} {
test http-idna-3.19-R.$ThreadLevel {puny decode: examples from RFC 3492} {
    hexify [::tcl::idna puny decode d9juau41awczczp]
} {u+305D u+306E u+30B9 u+30D4 u+30FC u+30C9 u+3067}
test http-idna-3.19-S {puny decode: examples from RFC 3492} {
test http-idna-3.19-S.$ThreadLevel {puny decode: examples from RFC 3492} {
    ::tcl::idna puny decode {-> $1.00 <--}
} {-> $1.00 <-}
rename hexify ""

test http-idna-4.1 {IDNA encoding} {
test http-idna-4.1.$ThreadLevel {IDNA encoding} {
    ::tcl::idna encode abc.def
} abc.def
test http-idna-4.2 {IDNA encoding} {
    ::tcl::idna encode a\u20acb\u20acc.def
test http-idna-4.2.$ThreadLevel {IDNA encoding} {
    ::tcl::idna encode a€b€c.def
} xn--abc-k50ab.def
test http-idna-4.3 {IDNA encoding} {
    ::tcl::idna encode def.a\u20acb\u20acc
test http-idna-4.3.$ThreadLevel {IDNA encoding} {
    ::tcl::idna encode def.a€b€c
} def.xn--abc-k50ab
test http-idna-4.4 {IDNA encoding} {
test http-idna-4.4.$ThreadLevel {IDNA encoding} {
    ::tcl::idna encode ABC.DEF
} ABC.DEF
test http-idna-4.5 {IDNA encoding} {
    ::tcl::idna encode A\u20acB\u20acC.def
test http-idna-4.5.$ThreadLevel {IDNA encoding} {
    ::tcl::idna encode A€B€C.def
} xn--ABC-k50ab.def
test http-idna-4.6 {IDNA encoding: invalid edge case} {
test http-idna-4.6.$ThreadLevel {IDNA encoding: invalid edge case} {
    # Should this be an error?
    ::tcl::idna encode abc..def
} abc..def
test http-idna-4.7 {IDNA encoding: invalid char} -returnCodes error -body {
test http-idna-4.7.$ThreadLevel {IDNA encoding: invalid char} -returnCodes error -body {
    ::tcl::idna encode abc.$.def
} -result {bad character "$" in DNS name}
test http-idna-4.7.1 {IDNA encoding: invalid char} {
test http-idna-4.7.1.$ThreadLevel {IDNA encoding: invalid char} {
    catch {::tcl::idna encode abc.$.def} -> opt
    dict get $opt -errorcode
} {IDNA INVALID_NAME_CHARACTER {$}}
test http-idna-4.8 {IDNA encoding: empty} {
test http-idna-4.8.$ThreadLevel {IDNA encoding: empty} {
    ::tcl::idna encode ""
} {}
set overlong www.[join [subst [string map {u+ \\u} {
    u+C138 u+ACC4 u+C758 u+BAA8 u+B4E0 u+C0AC u+B78C u+B4E4 u+C774
    u+D55C u+AD6D u+C5B4 u+B97C u+C774 u+D574 u+D55C u+B2E4 u+BA74
    u+C5BC u+B9C8 u+B098 u+C88B u+C744 u+AE4C
}]] ""].com
test http-idna-4.9 {IDNA encoding: max lengths from RFC 5890} -body {
test http-idna-4.9.$ThreadLevel {IDNA encoding: max lengths from RFC 5890} -body {
    ::tcl::idna encode $overlong
} -returnCodes error -result "hostname part too long"
test http-idna-4.9.1 {IDNA encoding: max lengths from RFC 5890} {
test http-idna-4.9.1.$ThreadLevel {IDNA encoding: max lengths from RFC 5890} {
    catch {::tcl::idna encode $overlong} -> opt
    dict get $opt -errorcode
} {IDNA OVERLONG_PART xn--989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5jpsd879ccm6fea98c}
unset overlong
test http-idna-4.10 {IDNA encoding: edge cases} {
    ::tcl::idna encode pass\u00e9.example.com
test http-idna-4.10.$ThreadLevel {IDNA encoding: edge cases} {
    ::tcl::idna encode passé.example.com
} xn--pass-epa.example.com

test http-idna-5.1 {IDNA decoding} {
test http-idna-5.1.$ThreadLevel {IDNA decoding} {
    ::tcl::idna decode abc.def
} abc.def
test http-idna-5.2 {IDNA decoding} {
test http-idna-5.2.$ThreadLevel {IDNA decoding} {
    # Invalid entry that's just a wrapper
    ::tcl::idna decode xn--abc-.def
} abc.def
test http-idna-5.3 {IDNA decoding} {
test http-idna-5.3.$ThreadLevel {IDNA decoding} {
    # Invalid entry that's just a wrapper
    ::tcl::idna decode xn--abc-.xn--def-
} abc.def
test http-idna-5.4 {IDNA decoding} {
test http-idna-5.4.$ThreadLevel {IDNA decoding} {
    # Invalid entry that's just a wrapper
    ::tcl::idna decode XN--abc-.XN--def-
} abc.def
test http-idna-5.5 {IDNA decoding: error cases} -returnCodes error -body {
test http-idna-5.5.$ThreadLevel {IDNA decoding: error cases} -returnCodes error -body {
    ::tcl::idna decode xn--$$$.example.com
} -result {bad decode character "$"}
test http-idna-5.5.1 {IDNA decoding: error cases} {
test http-idna-5.5.1.$ThreadLevel {IDNA decoding: error cases} {
    catch {::tcl::idna decode xn--$$$.example.com} -> opt
    dict get $opt -errorcode
} {PUNYCODE BAD_INPUT CHAR}
test http-idna-5.6 {IDNA decoding: error cases} -returnCodes error -body {
test http-idna-5.6.$ThreadLevel {IDNA decoding: error cases} -returnCodes error -body {
    ::tcl::idna decode xn--a-zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.def
} -result {exceeded input data}
test http-idna-5.6.1 {IDNA decoding: error cases} {
test http-idna-5.6.1.$ThreadLevel {IDNA decoding: error cases} {
    catch {::tcl::idna decode xn--a-zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.def} -> opt
    dict get $opt -errorcode
} {PUNYCODE BAD_INPUT LENGTH}

# cleanup
catch {unset url}
catch {unset badurl}
catch {unset port}
catch {unset data}
if {[info exists httpthread]} {
    thread::release $httpthread
if {[llength $threadStack]} {
    eval [lpop threadStack]
} else {
    close $listen
}

if {[info exists removeHttpd]} {
    removeFile $httpdFile
}

rename bgerror {}

if {[testConstraint ThreadLevelSummary]} {
::tcltest::cleanupTests
    ::tcltest::cleanupTests
}

# Local variables:
# mode: tcl
# End:

Changes to tests/http11.test.

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
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
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
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
467

468
469
470
471
472

473
474
475
476
477
478
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
558
559
560



561
562

563
564
565
566
567
568

569
570
571
572
573
574


575
576
577
578
579
580


581
582

583
584
585
586
587
588

589
590
591
592
593

594
595
596
597
598
599
600



601
602

603
604
605
606

607
608
609
610
611
612
613
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
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

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
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
467


468
469
470
471
472
473


474
475
476

477
478
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
558
559


560
561
562
563
564
565


566
567
568

569
570
571
572
573
574

575
576
577
578
579

580
581
582
583
584



585
586
587
588

589
590
591
592
593
594

595
596
597
598
599

600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627



628
629
630
631

632
633
634
635
636
637

638
639
640
641
642
643
644

645
646
647
648
649



650
651
652
653

654
655
656
657
658
659

660
661
662
663
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
707
708
709
710
711



712
713
714
715

716
717
718
719
720
721

722
723
724
725
726


727
728
729
730
731
732


733
734
735

736
737
738
739
740
741

742
743
744
745
746

747
748
749
750
751



752
753
754
755

756
757
758
759

760
761
762
763
764
765
766
767




-
+









-
+
+





-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+















-
-
-
+
+
+





-
-
+
-
-
-
-
-
+
+
+
+
-
-





-
-
-
-
-
+
+
+
+
+











-
+





-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+






-
+



-
+



-
+


-
+
+

-
+

-
+

-
+



-
+


-
+

-
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+
+
+



-
+


-
+

-
+



-
+



-
+


-
+

-
+



-
+



-
+


-
+

-
+



-
+



-
+


-
+
+

-
+

-
+

-
+



-
+


-
+

-
+



-
+



-
+


-
+

-
+



-
+



-
+


-
+

-
+



-
+



-
+


-
+

-
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+
+
+



-
+


-
+

-
+



-
+



-
+


-
+

-
+



-
+





-
+


-
+

-
+


-
+


-
-
+
+




















-
+




-
+




-
+

-
+





-
+




-
+



+

-
-
+
+

-
+



-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+




-
+




-
-
+
+

-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+
+
+




-
-
+
+




-
-
+
+

-
+





-
+




-
-
+
+




-
-
+
+

-
+





-
+





-
-
-
+
+
+





-
-
-
-
+
+
+
+

-
+






-
+





-
-
-
+
+
+





-
-
-
-
+
+
+
+

-
+






-
+




-
-
+
+




-
-
+
+

-
+





-
+




-
+




-
-
-
+
+
+

-
+





-
+




-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
-
+
+
+

-
+





-
+
+
+




-
+




-
-
-
+
+
+

-
+





-
+




-
+




-
-
-
+
+
+

-
+





-
+




-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
-
-
+
+
+

-
+





-
+




-
-
+
+




-
-
+
+

-
+





-
+




-
+




-
-
-
+
+
+

-
+



-
+







# http11.test --                                                -*- tcl-*-
#
#	Test HTTP/1.1 features.
#
# Copyright (C) 2009 Pat Thoyts <patthoyts@users.sourceforge.net>
# Copyright © 2009 Pat Thoyts <patthoyts@users.sourceforge.net>
#
# 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::*
}

package require http 2.9
package require http 2.10
#http::register http 80 ::socket

# start the server
variable httpd_output
proc create_httpd {} {
    proc httpd_read {chan} {
        variable httpd_output
        if {[gets $chan line] >= 0} {
            #puts stderr "read '$line'"
            set httpd_output $line
        }
        if {[eof $chan]} {
            puts stderr "eof from httpd"
            fileevent $chan readable {}
            close $chan
        }
	variable httpd_output
	if {[gets $chan line] >= 0} {
	    #puts stderr "read '$line'"
	    set httpd_output $line
	}
	if {[eof $chan]} {
	    puts stderr "eof from httpd"
	    fileevent $chan readable {}
	    close $chan
	}
    }
    variable httpd_output
    set httpd_script [file join [pwd] [file dirname [info script]] httpd11.tcl]
    set httpd [open "|[list [interpreter] -encoding utf-8 $httpd_script]" r+]
    fconfigure $httpd -buffering line -blocking 0
    fileevent $httpd readable [list httpd_read $httpd]
    vwait httpd_output
    variable httpd_port [lindex $httpd_output 2]
    return $httpd
}

proc halt_httpd {} {
    variable httpd_output
    variable httpd
    if {[info exists httpd]} {
        puts $httpd "quit"
        vwait httpd_output
        close $httpd
	puts $httpd "quit"
	vwait httpd_output
	close $httpd
    }
    unset -nocomplain httpd_output httpd
}

proc meta {tok {key ""}} {
    set meta [http::meta $tok]
    if {$key ne ""} {
    if {$key eq ""} {
        if {[dict exists $meta $key]} {
            return [dict get $meta $key]
        } else {
            return ""
        }
	return [http::meta $tok]
    } else {
	return [http::metaValue $tok $key]
    }
    }
    return $meta
}

proc state {tok {key ""}} {
    upvar 1 $tok state
    if {$key ne ""} {
        if {[array names state -exact $key] ne {}} {
            return $state($key)
        } else {
            return ""
        }
	if {[array names state -exact $key] ne {}} {
	    return $state($key)
	} else {
	    return ""
	}
    }
    set res [array get state]
    dict set res body <elided>
    return $res
}

proc check_crc {tok args} {
    set crc [meta $tok x-crc32]
    set data [expr {[llength $args] ? [lindex $args 0] : [http::data $tok]}]
    set chk [format %x [zlib crc32 $data]]
    if {$crc ne $chk} {
        return  "crc32 mismatch: $crc ne $chk"
	return  "crc32 mismatch: $crc ne $chk"
    }
    return "ok"
}

makeFile "<html><head><title>test</title></head><body><p>this is a test</p>\n[string repeat {<p>This is a tcl test file.</p>} 4192]\n</body></html>" testdoc.html


makeFile "<html><head><title>test</title></head><body><p>this is a test</p>\n[string repeat {<p>This is a tcl test file.</p>} 5000]\n</body></html>" largedoc.html

# To write a separate summary for each value of ThreadLevel, set constraint ThreadLevelSummary.
#testConstraint ThreadLevelSummary 0

if 0 {
    # For debugging: run with a single value of ThreadLevel: 0|1|2
    set ThreadLevel 0
    testConstraint ThreadLevelSummary 1
}
if {![info exists ThreadLevel]} {
    if {[catch {package require Thread}] == 0} {
	set ValueRange {0 1 2}
    } else {
	set ValueRange {0 1}
    }

    # For each value of ThreadLevel, source this file recursively in the
    # same interpreter.
    foreach ThreadLevel $ValueRange {
	source [info script]
    }
    catch {unset ThreadLevel}
    catch {unset ValueRange}
    if {![testConstraint ThreadLevelSummary]} {
	::tcltest::cleanupTests
    }
    return
}

catch {puts "==== Test with ThreadLevel $ThreadLevel ===="}
http::config -threadlevel $ThreadLevel

# -------------------------------------------------------------------------

test http11-1.0 "normal request for document " -setup {
test http11-1.0.$ThreadLevel "normal request for document " -setup {
    variable httpd [create_httpd]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html -timeout 10000]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] [meta $tok connection]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close}

test http11-1.1 "normal,gzip,non-chunked" -setup {
test http11-1.1.$ThreadLevel "normal,gzip,non-chunked" -setup {
    variable httpd [create_httpd]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1 \
                 -timeout 10000 -headers {accept-encoding gzip}]
		 -timeout 10000 -headers {accept-encoding gzip}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok content-encoding] [meta $tok transfer-encoding]
	[meta $tok content-encoding] [meta $tok transfer-encoding] \
	[http::meta $tok content-encoding] [http::meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok gzip {}}
} -result {ok {HTTP/1.1 200 OK} ok gzip {} {content-encoding gzip} {}}

test http11-1.2 "normal,deflated,non-chunked" -setup {
test http11-1.2.$ThreadLevel "normal,deflated,non-chunked" -setup {
    variable httpd [create_httpd]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1 \
                 -timeout 10000 -headers {accept-encoding deflate}]
		 -timeout 10000 -headers {accept-encoding deflate}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok content-encoding] [meta $tok transfer-encoding]
	[meta $tok content-encoding] [meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok deflate {}}

test http11-1.2.1.$ThreadLevel "normal,deflated,non-chunked,msdeflate" -setup {
    variable httpd [create_httpd]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1&msdeflate=1 \
		 -timeout 10000 -headers {accept-encoding deflate}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
	[meta $tok content-encoding] [meta $tok transfer-encoding]
} -cleanup {
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok deflate {}}

test http11-1.3 "normal,compressed,non-chunked" -setup {
test http11-1.3.$ThreadLevel "normal,compressed,non-chunked" -constraints badCompress -setup {
    # The Tcl "compress" algorithm appears to be incorrect and has been removed.
    # Bug [a13b9d0ce1].
    variable httpd [create_httpd]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1 \
                 -timeout 10000 -headers {accept-encoding compress}]
		 -timeout 10000 -headers {accept-encoding compress}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok content-encoding] [meta $tok transfer-encoding]
	[meta $tok content-encoding] [meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok compress {}}

test http11-1.4 "normal,identity,non-chunked" -setup {
test http11-1.4.$ThreadLevel "normal,identity,non-chunked" -setup {
    variable httpd [create_httpd]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1 \
                 -timeout 10000 -headers {accept-encoding identity}]
		 -timeout 10000 -headers {accept-encoding identity}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok content-encoding] [meta $tok transfer-encoding]
	[meta $tok content-encoding] [meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok {} {}}

test http11-1.5 "normal request for document, unsupported coding" -setup {
test http11-1.5.$ThreadLevel "normal request for document, unsupported coding" -setup {
    variable httpd [create_httpd]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -timeout 10000 -headers {accept-encoding unsupported}]
		 -timeout 10000 -headers {accept-encoding unsupported}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok content-encoding]
	[meta $tok content-encoding]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok {}}

test http11-1.6 "normal, specify 1.1 " -setup {
test http11-1.6.$ThreadLevel "normal, specify 1.1 " -setup {
    variable httpd [create_httpd]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -protocol 1.1 -timeout 10000]
		 -protocol 1.1 -timeout 10000]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok connection] [meta $tok transfer-encoding]
	[meta $tok connection] [meta $tok transfer-encoding] \
	[http::meta $tok connection] [http::meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close chunked}
} -result {ok {HTTP/1.1 200 OK} ok close chunked {connection close} {transfer-encoding chunked}}

test http11-1.7 "normal, 1.1 and keepalive " -setup {
test http11-1.7.$ThreadLevel "normal, 1.1 and keepalive " -setup {
    variable httpd [create_httpd]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -protocol 1.1 -keepalive 1 -timeout 10000]
		 -protocol 1.1 -keepalive 1 -timeout 10000]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok connection] [meta $tok transfer-encoding]
	[meta $tok connection] [meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok {} chunked}

test http11-1.8 "normal, 1.1 and keepalive, server close" -setup {
test http11-1.8.$ThreadLevel "normal, 1.1 and keepalive, server close" -setup {
    variable httpd [create_httpd]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1 \
                 -protocol 1.1 -keepalive 1 -timeout 10000]
		 -protocol 1.1 -keepalive 1 -timeout 10000]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok connection] [meta $tok transfer-encoding]
	[meta $tok connection] [meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close {}}

test http11-1.9 "normal,gzip,chunked" -setup {
test http11-1.9.$ThreadLevel "normal,gzip,chunked" -setup {
    variable httpd [create_httpd]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -timeout 10000 -headers {accept-encoding gzip}]
		 -timeout 10000 -headers {accept-encoding gzip}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok content-encoding] [meta $tok transfer-encoding]
	[meta $tok content-encoding] [meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok gzip chunked}

test http11-1.10 "normal,deflate,chunked" -setup {
test http11-1.10.$ThreadLevel "normal,deflate,chunked" -setup {
    variable httpd [create_httpd]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -timeout 10000 -headers {accept-encoding deflate}]
		 -timeout 10000 -headers {accept-encoding deflate}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok content-encoding] [meta $tok transfer-encoding]
	[meta $tok content-encoding] [meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok deflate chunked}

test http11-1.10.1.$ThreadLevel "normal,deflate,chunked,msdeflate" -setup {
    variable httpd [create_httpd]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?msdeflate=1 \
		 -timeout 10000 -headers {accept-encoding deflate}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
	[meta $tok content-encoding] [meta $tok transfer-encoding]
} -cleanup {
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok deflate chunked}

test http11-1.11 "normal,compress,chunked" -setup {
test http11-1.11.$ThreadLevel "normal,compress,chunked" -constraints badCompress -setup {
    # The Tcl "compress" algorithm appears to be incorrect and has been removed.
    # Bug [a13b9d0ce1].
    variable httpd [create_httpd]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -timeout 10000 -headers {accept-encoding compress}]
		 -timeout 10000 -headers {accept-encoding compress}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok content-encoding] [meta $tok transfer-encoding]
	[meta $tok content-encoding] [meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok compress chunked}

test http11-1.12 "normal,identity,chunked" -setup {
test http11-1.12.$ThreadLevel "normal,identity,chunked" -setup {
    variable httpd [create_httpd]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -timeout 10000 -headers {accept-encoding identity}]
		 -timeout 10000 -headers {accept-encoding identity}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok content-encoding] [meta $tok transfer-encoding]
	[meta $tok content-encoding] [meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok {} chunked}

test http11-1.13 "normal, 1.1 and keepalive as server default, no zip" -setup {
test http11-1.13.$ThreadLevel "normal, 1.1 and keepalive as server default, no zip" -setup {
    variable httpd [create_httpd]
    set zipTmp [http::config -zip]
    http::config -zip 0
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?transfer= \
                 -protocol 1.1 -keepalive 1 -timeout 10000]
		 -protocol 1.1 -keepalive 1 -timeout 10000]
    http::wait $tok
    set res1 [list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok connection] [meta $tok transfer-encoding] [state $tok reusing] [state $tok connection]]
	[meta $tok connection] [meta $tok transfer-encoding] [state $tok reusing] [state $tok connection]]
    set toj [http::geturl http://localhost:$httpd_port/testdoc.html?transfer= \
                 -protocol 1.1 -keepalive 1 -timeout 10000]
		 -protocol 1.1 -keepalive 1 -timeout 10000]
    http::wait $toj
    set res2 [list [http::status $toj] [http::code $toj] [check_crc $toj] \
        [meta $toj connection] [meta $toj transfer-encoding] [state $toj reusing] [state $toj connection]]
	[meta $toj connection] [meta $toj transfer-encoding] [state $toj reusing] [state $toj connection]]
    concat $res1 -- $res2
} -cleanup {
    http::cleanup $tok
    http::cleanup $toj
    catch {http::cleanup $tok}
    catch {http::cleanup $toj}
    halt_httpd
    http::config -zip $zipTmp
} -result {ok {HTTP/1.1 200 OK} ok {} {} 0 keep-alive -- ok {HTTP/1.1 200 OK} ok {} {} 1 keep-alive}

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

proc progress {var token total current} {
    upvar #0 $var log
    set log [list $current $total]
    return
}

proc progressPause {var token total current} {
    upvar #0 $var log
    set log [list $current $total]
    after 100 set ::WaitHere 0
    vwait ::WaitHere
    return
}

test http11-2.0 "-channel" -setup {
test http11-2.0.$ThreadLevel "-channel" -setup {
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -timeout 5000 -channel $chan]
		 -timeout 5000 -channel $chan]
    http::wait $tok
    seek $chan 0
    set data [read $chan]
    list [http::status $tok] [http::code $tok] [check_crc $tok $data]\
        [meta $tok connection] [meta $tok transfer-encoding]
	[meta $tok connection] [meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close chunked}

test http11-2.1 "-channel, encoding gzip" -setup {
test http11-2.1.$ThreadLevel "-channel, encoding gzip" -setup {
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -timeout 5000 -channel $chan -headers {accept-encoding gzip}]
		 -timeout 5000 -channel $chan -headers {accept-encoding gzip}]
    http::wait $tok
    seek $chan 0
    set data [read $chan]
    set diff [expr {[file size testdoc.html] - [file size testfile.tmp]}]
    list [http::status $tok] [http::code $tok] [check_crc $tok $data]\
        [meta $tok connection] [meta $tok content-encoding]\
        [meta $tok transfer-encoding]
	[meta $tok connection] [meta $tok content-encoding]\
	[meta $tok transfer-encoding] -- $diff bytes lost
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close gzip chunked}
} -result {ok {HTTP/1.1 200 OK} ok close gzip chunked -- 0 bytes lost}

# Cf. Bug [3610253] "CopyChunk does not drain decompressor(s)"
# This test failed before the bugfix.
# The pass/fail depended on file size.
test http11-2.1.1.$ThreadLevel "-channel, encoding gzip" -setup {
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
    set fileName largedoc.html
} -body {
    set tok [http::geturl http://localhost:$httpd_port/$fileName \
		 -timeout 5000 -channel $chan -headers {accept-encoding gzip}]
    http::wait $tok
    seek $chan 0
    set data [read $chan]
    set diff [expr {[file size $fileName] - [file size testfile.tmp]}]
    list [http::status $tok] [http::code $tok] [check_crc $tok $data]\
	[meta $tok connection] [meta $tok content-encoding]\
	[meta $tok transfer-encoding] -- $diff bytes lost
} -cleanup {
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close gzip chunked -- 0 bytes lost}

test http11-2.2 "-channel, encoding deflate" -setup {
test http11-2.2.$ThreadLevel "-channel, encoding deflate" -setup {
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -timeout 5000 -channel $chan -headers {accept-encoding deflate}]
		 -timeout 5000 -channel $chan -headers {accept-encoding deflate}]
    http::wait $tok
    seek $chan 0
    set data [read $chan]
    list [http::status $tok] [http::code $tok] [check_crc $tok $data]\
        [meta $tok connection] [meta $tok content-encoding]\
        [meta $tok transfer-encoding]
	[meta $tok connection] [meta $tok content-encoding]\
	[meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close deflate chunked}

test http11-2.2.1.$ThreadLevel "-channel, encoding deflate,msdeflate" -setup {
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?msdeflate=1 \
		 -timeout 5000 -channel $chan -headers {accept-encoding deflate}]
    http::wait $tok
    seek $chan 0
    set data [read $chan]
    list [http::status $tok] [http::code $tok] [check_crc $tok $data]\
	[meta $tok connection] [meta $tok content-encoding]\
	[meta $tok transfer-encoding]
} -cleanup {
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close deflate chunked}

test http11-2.3 "-channel,encoding compress" -setup {
test http11-2.3.$ThreadLevel "-channel,encoding compress" -constraints badCompress -setup {
    # The Tcl "compress" algorithm appears to be incorrect and has been removed.
    # Bug [a13b9d0ce1].
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -timeout 5000 -channel $chan \
                 -headers {accept-encoding compress}]
		 -timeout 5000 -channel $chan \
		 -headers {accept-encoding compress}]
    http::wait $tok
    seek $chan 0
    set data [read $chan]
    list [http::status $tok] [http::code $tok] [check_crc $tok $data]\
        [meta $tok connection] [meta $tok content-encoding]\
        [meta $tok transfer-encoding]
	[meta $tok connection] [meta $tok content-encoding]\
	[meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close compress chunked}

test http11-2.4 "-channel,encoding identity" -setup {
test http11-2.4.$ThreadLevel "-channel,encoding identity" -setup {
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -timeout 5000 -channel $chan \
                 -headers {accept-encoding identity}]
		 -timeout 5000 -channel $chan \
		 -headers {accept-encoding identity}]
    http::wait $tok
    seek $chan 0
    set data [read $chan]
    list [http::status $tok] [http::code $tok] [check_crc $tok $data]\
        [meta $tok connection] [meta $tok content-encoding]\
        [meta $tok transfer-encoding]
	[meta $tok connection] [meta $tok content-encoding]\
	[meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close {} chunked}

test http11-2.4.1 "-channel,encoding identity with -progress" -setup {
test http11-2.4.1.$ThreadLevel "-channel,encoding identity with -progress" -setup {
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
    set logdata ""
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -timeout 5000 -channel $chan \
                 -headers {accept-encoding identity} \
                 -progress [namespace code [list progress logdata]]]
		 -timeout 5000 -channel $chan \
		 -headers {accept-encoding identity} \
		 -progress [namespace code [list progress logdata]]]

    http::wait $tok
    seek $chan 0
    set data [read $chan]
    list [http::status $tok] [http::code $tok] [check_crc $tok $data]\
        [meta $tok connection] [meta $tok content-encoding]\
        [meta $tok transfer-encoding] \
        [expr {[lindex $logdata 0] - [lindex $logdata 1]}] \
        [expr {[lindex $logdata 0] - [string length $data]}]
	[meta $tok connection] [meta $tok content-encoding]\
	[meta $tok transfer-encoding] \
	[expr {[lindex $logdata 0] - [lindex $logdata 1]}] \
	[expr {[lindex $logdata 0] - [string length $data]}]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
    unset -nocomplain logdata data
} -result {ok {HTTP/1.1 200 OK} ok close {} chunked 0 0}

test http11-2.4.2 "-channel,encoding identity with -progress progressPause enters event loop" -constraints knownBug -setup {
test http11-2.4.2.$ThreadLevel "-channel,encoding identity with -progress progressPause enters event loop" -constraints knownBug -setup {
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
    set logdata ""
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -timeout 5000 -channel $chan \
                 -headers {accept-encoding identity} \
                 -progress [namespace code [list progressPause logdata]]]
		 -timeout 5000 -channel $chan \
		 -headers {accept-encoding identity} \
		 -progress [namespace code [list progressPause logdata]]]

    http::wait $tok
    seek $chan 0
    set data [read $chan]
    list [http::status $tok] [http::code $tok] [check_crc $tok $data]\
        [meta $tok connection] [meta $tok content-encoding]\
        [meta $tok transfer-encoding] \
        [expr {[lindex $logdata 0] - [lindex $logdata 1]}] \
        [expr {[lindex $logdata 0] - [string length $data]}]
	[meta $tok connection] [meta $tok content-encoding]\
	[meta $tok transfer-encoding] \
	[expr {[lindex $logdata 0] - [lindex $logdata 1]}] \
	[expr {[lindex $logdata 0] - [string length $data]}]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
    unset -nocomplain logdata data ::WaitHere
} -result {ok {HTTP/1.1 200 OK} ok close {} chunked 0 0}

test http11-2.5 "-channel,encoding unsupported" -setup {
test http11-2.5.$ThreadLevel "-channel,encoding unsupported" -setup {
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -timeout 5000 -channel $chan \
                 -headers {accept-encoding unsupported}]
		 -timeout 5000 -channel $chan \
		 -headers {accept-encoding unsupported}]
    http::wait $tok
    seek $chan 0
    set data [read $chan]
    list [http::status $tok] [http::code $tok] [check_crc $tok $data]\
        [meta $tok connection] [meta $tok content-encoding]\
        [meta $tok transfer-encoding]
	[meta $tok connection] [meta $tok content-encoding]\
	[meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close {} chunked}

test http11-2.6 "-channel,encoding gzip,non-chunked" -setup {
test http11-2.6.$ThreadLevel "-channel,encoding gzip,non-chunked" -setup {
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1 \
                 -timeout 5000 -channel $chan -headers {accept-encoding gzip}]
		 -timeout 5000 -channel $chan -headers {accept-encoding gzip}]
    http::wait $tok
    seek $chan 0
    set data [read $chan]
    list [http::status $tok] [http::code $tok] [check_crc $tok $data]\
        [meta $tok connection] [meta $tok content-encoding]\
        [meta $tok transfer-encoding]\
        [expr {[file size testdoc.html]-[file size testfile.tmp]}]
	[meta $tok connection] [meta $tok content-encoding]\
	[meta $tok transfer-encoding]\
	[expr {[file size testdoc.html]-[file size testfile.tmp]}]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close gzip {} 0}

test http11-2.7 "-channel,encoding deflate,non-chunked" -setup {
test http11-2.7.$ThreadLevel "-channel,encoding deflate,non-chunked" -setup {
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1 \
                 -timeout 5000 -channel $chan -headers {accept-encoding deflate}]
		 -timeout 5000 -channel $chan -headers {accept-encoding deflate}]
    http::wait $tok
    seek $chan 0
    set data [read $chan]
    list [http::status $tok] [http::code $tok] [check_crc $tok $data]\
	[meta $tok connection] [meta $tok content-encoding]\
	[meta $tok transfer-encoding]\
	[expr {[file size testdoc.html]-[file size testfile.tmp]}]
} -cleanup {
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close deflate {} 0}

test http11-2.7.1.$ThreadLevel "-channel,encoding deflate,non-chunked,msdeflate" -constraints knownBug -setup {
    # Test fails because a -channel can only try one un-deflate algorithm, and the
    # compliant "decompress" is tried, not the non-compliant "inflate" of
    # the MS browser implementation.
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1&msdeflate=1 \
		 -timeout 5000 -channel $chan -headers {accept-encoding deflate}]
    http::wait $tok
    seek $chan 0
    set data [read $chan]
    list [http::status $tok] [http::code $tok] [check_crc $tok $data]\
        [meta $tok connection] [meta $tok content-encoding]\
        [meta $tok transfer-encoding]\
        [expr {[file size testdoc.html]-[file size testfile.tmp]}]
	[meta $tok connection] [meta $tok content-encoding]\
	[meta $tok transfer-encoding]\
	[expr {[file size testdoc.html]-[file size testfile.tmp]}]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close deflate {} 0}

test http11-2.8 "-channel,encoding compress,non-chunked" -setup {
test http11-2.8.$ThreadLevel "-channel,encoding compress,non-chunked" -constraints badCompress -setup {
    # The Tcl "compress" algorithm appears to be incorrect and has been removed.
    # Bug [a13b9d0ce1].
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1 \
                 -timeout 5000 -channel $chan -headers {accept-encoding compress}]
		 -timeout 5000 -channel $chan -headers {accept-encoding compress}]
    http::wait $tok
    seek $chan 0
    set data [read $chan]
    list [http::status $tok] [http::code $tok] [check_crc $tok $data]\
        [meta $tok connection] [meta $tok content-encoding]\
        [meta $tok transfer-encoding]\
        [expr {[file size testdoc.html]-[file size testfile.tmp]}]
	[meta $tok connection] [meta $tok content-encoding]\
	[meta $tok transfer-encoding]\
	[expr {[file size testdoc.html]-[file size testfile.tmp]}]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close compress {} 0}

test http11-2.9 "-channel,encoding identity,non-chunked" -setup {
test http11-2.9.$ThreadLevel "-channel,encoding identity,non-chunked" -setup {
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1 \
                 -timeout 5000 -channel $chan -headers {accept-encoding identity}]
		 -timeout 5000 -channel $chan -headers {accept-encoding identity}]
    http::wait $tok
    seek $chan 0
    set data [read $chan]
    list [http::status $tok] [http::code $tok] [check_crc $tok $data]\
        [meta $tok connection] [meta $tok content-encoding]\
        [meta $tok transfer-encoding]\
        [expr {[file size testdoc.html]-[file size testfile.tmp]}]
	[meta $tok connection] [meta $tok content-encoding]\
	[meta $tok transfer-encoding]\
	[expr {[file size testdoc.html]-[file size testfile.tmp]}]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close {} {} 0}

test http11-2.10 "-channel,deflate,keepalive" -setup {
test http11-2.10.$ThreadLevel "-channel,deflate,keepalive" -setup {
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -timeout 5000 -channel $chan -keepalive 1 \
		 -timeout 5000 -channel $chan -keepalive 1 \
		 -headers {accept-encoding deflate}]
    http::wait $tok
    seek $chan 0
    set data [read $chan]
    list [http::status $tok] [http::code $tok] [check_crc $tok $data]\
	[meta $tok connection] [meta $tok content-encoding]\
	[meta $tok transfer-encoding]\
	[expr {[file size testdoc.html]-[file size testfile.tmp]}]
} -cleanup {
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok {} deflate chunked 0}

test http11-2.10.1.$ThreadLevel "-channel,deflate,keepalive,msdeflate" -setup {
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?msdeflate=1 \
		 -timeout 5000 -channel $chan -keepalive 1 \
		 -headers {accept-encoding deflate}]
    http::wait $tok
    seek $chan 0
    set data [read $chan]
    list [http::status $tok] [http::code $tok] [check_crc $tok $data]\
        [meta $tok connection] [meta $tok content-encoding]\
        [meta $tok transfer-encoding]\
        [expr {[file size testdoc.html]-[file size testfile.tmp]}]
	[meta $tok connection] [meta $tok content-encoding]\
	[meta $tok transfer-encoding]\
	[expr {[file size testdoc.html]-[file size testfile.tmp]}]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok {} deflate chunked 0}

test http11-2.11 "-channel,identity,keepalive" -setup {
test http11-2.11.$ThreadLevel "-channel,identity,keepalive" -setup {
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -headers {accept-encoding identity} \
                 -timeout 5000 -channel $chan -keepalive 1]
		 -headers {accept-encoding identity} \
		 -timeout 5000 -channel $chan -keepalive 1]
    http::wait $tok
    seek $chan 0
    set data [read $chan]
    list [http::status $tok] [http::code $tok] [check_crc $tok $data]\
        [meta $tok connection] [meta $tok content-encoding]\
        [meta $tok transfer-encoding]
	[meta $tok connection] [meta $tok content-encoding]\
	[meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok {} {} chunked}

test http11-2.12 "-channel,negotiate,keepalive" -setup {
test http11-2.12.$ThreadLevel "-channel,negotiate,keepalive" -setup {
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -timeout 5000 -channel $chan -keepalive 1]
		 -timeout 5000 -channel $chan -keepalive 1]
    http::wait $tok
    seek $chan 0
    set data [read $chan]
    list [http::status $tok] [http::code $tok] [check_crc $tok $data]\
        [meta $tok connection] [meta $tok content-encoding]\
        [meta $tok transfer-encoding] [meta $tok x-requested-encodings]\
        [expr {[file size testdoc.html]-[file size testfile.tmp]}]
	[meta $tok connection] [meta $tok content-encoding]\
	[meta $tok transfer-encoding] [meta $tok x-requested-encodings]\
	[expr {[file size testdoc.html]-[file size testfile.tmp]}]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok {} gzip chunked gzip,deflate,compress 0}
} -result {ok {HTTP/1.1 200 OK} ok {} gzip chunked gzip,deflate 0}


# -------------------------------------------------------------------------
#
# The following tests for the -handler option will require changes in
# the future. At the moment we cannot handler chunked data with this
# option. Therefore we currently force HTTP/1.0 protocol version.
629
630
631
632
633
634
635
636

637
638
639
640
641

642
643
644
645
646



647
648

649
650
651
652
653

654
655
656
657
658
659


660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717

718
719
720
721
722

723
724
725
726
727



728
729

730
731
732
733
734
735

736
737
738
739
740

741
742
743
744
745



746
747

748
749
750
751
752

753
754
755
756
757
758
759


760
761
762
763
764
765
766





767
768

769
770
771
772
773

774
775
776
777
778
779
780


781
782
783
784
785
786
787





788
789

790
791
792
793
794

795
796
797
798
799
800
801



802
803
804
805
806
807
808





809
810

811
812
813
814
815

816
817
818
819
820
821
822



823
824
825
826
827
828
829





830
831

832
833
834
835
836

837
838
839
840
841

842
843
844
845
846



847
848

849
850
851
852

853
854
855
856
857
858


859
860
861
862
863



864
865

866
867
868
869

870
871
872
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
898
899
900



901
902

903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920

921
922

923


783
784
785
786
787
788
789

790
791
792
793
794

795
796
797



798
799
800
801

802
803
804
805
806

807
808
809
810
811


812
813
814
815



816
817
818
819

820
821
822
823
824

825
826
827
828
829


830
831
832
833



834
835
836
837

838
839
840
841
842

843
844
845
846
847


848
849
850
851



852
853
854
855

856
857
858
859
860
861
862
863
864
865
866
867
868
869
870

871
872
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
898
899
900

901
902
903
904
905

906
907
908
909
910
911


912
913
914
915





916
917
918
919
920
921

922
923
924
925
926

927
928
929
930
931
932


933
934
935
936





937
938
939
940
941
942

943
944
945
946
947

948
949
950
951
952



953
954
955
956
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
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







-
+




-
+


-
-
-
+
+
+

-
+




-
+




-
-
+
+


-
-
-
+
+
+

-
+




-
+




-
-
+
+


-
-
-
+
+
+

-
+




-
+




-
-
+
+


-
-
-
+
+
+

-
+














-
+




-
+


-
-
-
+
+
+

-
+





-
+




-
+


-
-
-
+
+
+

-
+




-
+





-
-
+
+


-
-
-
-
-
+
+
+
+
+

-
+




-
+





-
-
+
+


-
-
-
-
-
+
+
+
+
+

-
+




-
+




-
-
-
+
+
+


-
-
-
-
-
+
+
+
+
+

-
+




-
+




-
-
-
+
+
+


-
-
-
-
-
+
+
+
+
+

-
+




-
+




-
+


-
-
-
+
+
+

-
+



-
+




-
-
+
+


-
-
-
+
+
+

-
+



-
+




-
-
+
+


-
-
-
+
+
+

-
+



-
+







-
-
+
+


-
-
-
+
+
+

-
+


















+


+
-
+
+
    append data $chunk
    #::http::Log "handler read [string length $chunk] ([chan configure $sock -buffersize])"
    after 100 set ::WaitHere 0
    vwait ::WaitHere
    return [string length $chunk]
}

test http11-3.0 "-handler,close,identity" -setup {
test http11-3.0.$ThreadLevel "-handler,close,identity" -setup {
    variable httpd [create_httpd]
    set testdata ""
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1 \
                 -timeout 10000 -handler [namespace code [list handler testdata]]]
		 -timeout 10000 -handler [namespace code [list handler testdata]]]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok $testdata]\
        [meta $tok connection] [meta $tok content-encoding] \
        [meta $tok transfer-encoding] \
        [expr {[file size testdoc.html]-[string length $testdata]}]
	[meta $tok connection] [meta $tok content-encoding] \
	[meta $tok transfer-encoding] \
	[expr {[file size testdoc.html]-[string length $testdata]}]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    unset -nocomplain testdata
    halt_httpd
} -result {ok {HTTP/1.0 200 OK} ok close {} {} 0}

test http11-3.1 "-handler,protocol1.0" -setup {
test http11-3.1.$ThreadLevel "-handler,protocol1.0" -setup {
    variable httpd [create_httpd]
    set testdata ""
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1 \
                 -timeout 10000 -protocol 1.0 \
                 -handler [namespace code [list handler testdata]]]
		 -timeout 10000 -protocol 1.0 \
		 -handler [namespace code [list handler testdata]]]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok $testdata]\
        [meta $tok connection] [meta $tok content-encoding] \
        [meta $tok transfer-encoding] \
        [expr {[file size testdoc.html]-[string length $testdata]}]
	[meta $tok connection] [meta $tok content-encoding] \
	[meta $tok transfer-encoding] \
	[expr {[file size testdoc.html]-[string length $testdata]}]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    unset -nocomplain testdata
    halt_httpd
} -result {ok {HTTP/1.0 200 OK} ok close {} {} 0}

test http11-3.2 "-handler,close,chunked" -setup {
test http11-3.2.$ThreadLevel "-handler,close,chunked" -setup {
    variable httpd [create_httpd]
    set testdata ""
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -timeout 10000 -keepalive 0 -binary 1\
                 -handler [namespace code [list handler testdata]]]
		 -timeout 10000 -keepalive 0 -binary 1\
		 -handler [namespace code [list handler testdata]]]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok $testdata]\
        [meta $tok connection] [meta $tok content-encoding] \
        [meta $tok transfer-encoding] \
        [expr {[file size testdoc.html]-[string length $testdata]}]
	[meta $tok connection] [meta $tok content-encoding] \
	[meta $tok transfer-encoding] \
	[expr {[file size testdoc.html]-[string length $testdata]}]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    unset -nocomplain testdata
    halt_httpd
} -result {ok {HTTP/1.0 200 OK} ok close {} {} 0}

test http11-3.3 "-handler,keepalive,chunked" -setup {
test http11-3.3.$ThreadLevel "-handler,keepalive,chunked" -setup {
    variable httpd [create_httpd]
    set testdata ""
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -timeout 10000 -keepalive 1 -binary 1\
                 -handler [namespace code [list handler testdata]]]
		 -timeout 10000 -keepalive 1 -binary 1\
		 -handler [namespace code [list handler testdata]]]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok $testdata]\
        [meta $tok connection] [meta $tok content-encoding] \
        [meta $tok transfer-encoding] \
        [expr {[file size testdoc.html]-[string length $testdata]}]
	[meta $tok connection] [meta $tok content-encoding] \
	[meta $tok transfer-encoding] \
	[expr {[file size testdoc.html]-[string length $testdata]}]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    unset -nocomplain testdata
    halt_httpd
} -result {ok {HTTP/1.0 200 OK} ok close {} {} 0}

# http11-3.4
# This test is a blatant attempt to confuse the client by instructing the server
# to send neither "Connection: close" nor "Content-Length" when in non-chunked
# mode.
# The client has no way to know the response-body is complete unless the
# server signals this by closing the connection.
# In an HTTP/1.1 response the absence of "Connection: close" means
# "Connection: keep-alive", i.e. the server will keep the connection
# open.  In HTTP/1.0 this is not the case, and this is a test that
# the Tcl client assumes "Connection: close" by default in HTTP/1.0.
test http11-3.4 "-handler,close,identity; HTTP/1.0 server does not send Connection: close header or Content-Length" -setup {
test http11-3.4.$ThreadLevel "-handler,close,identity; HTTP/1.0 server does not send Connection: close header or Content-Length" -setup {
    variable httpd [create_httpd]
    set testdata ""
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1&nosendclose=any \
                 -timeout 10000 -handler [namespace code [list handler testdata]]]
		 -timeout 10000 -handler [namespace code [list handler testdata]]]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok $testdata]\
        [meta $tok connection] [meta $tok content-encoding] \
        [meta $tok transfer-encoding] \
        [expr {[file size testdoc.html]-[string length $testdata]}]
	[meta $tok connection] [meta $tok content-encoding] \
	[meta $tok transfer-encoding] \
	[expr {[file size testdoc.html]-[string length $testdata]}]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    unset -nocomplain testdata
    halt_httpd
} -result {ok {HTTP/1.0 200 OK} ok {} {} {} 0}

# It is not forbidden for a handler to enter the event loop.
test http11-3.5 "-handler,close,identity as http11-3.0 but handlerPause enters event loop" -setup {
test http11-3.5.$ThreadLevel "-handler,close,identity as http11-3.0 but handlerPause enters event loop" -setup {
    variable httpd [create_httpd]
    set testdata ""
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1 \
                 -timeout 10000 -handler [namespace code [list handlerPause testdata]]]
		 -timeout 10000 -handler [namespace code [list handlerPause testdata]]]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok $testdata]\
        [meta $tok connection] [meta $tok content-encoding] \
        [meta $tok transfer-encoding] \
        [expr {[file size testdoc.html]-[string length $testdata]}]
	[meta $tok connection] [meta $tok content-encoding] \
	[meta $tok transfer-encoding] \
	[expr {[file size testdoc.html]-[string length $testdata]}]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    unset -nocomplain testdata ::WaitHere
    halt_httpd
} -result {ok {HTTP/1.0 200 OK} ok close {} {} 0}

test http11-3.6 "-handler,close,identity as http11-3.0 but with -progress" -setup {
test http11-3.6.$ThreadLevel "-handler,close,identity as http11-3.0 but with -progress" -setup {
    variable httpd [create_httpd]
    set testdata ""
    set logdata ""
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1 \
                 -timeout 10000 -handler [namespace code [list handler testdata]] \
                 -progress [namespace code [list progress logdata]]]
		 -timeout 10000 -handler [namespace code [list handler testdata]] \
		 -progress [namespace code [list progress logdata]]]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok $testdata]\
        [meta $tok connection] [meta $tok content-encoding] \
        [meta $tok transfer-encoding] \
        [expr {[file size testdoc.html]-[string length $testdata]}] \
        [expr {[lindex $logdata 0] - [lindex $logdata 1]}] \
        [expr {[lindex $logdata 0] - [string length $testdata]}]
	[meta $tok connection] [meta $tok content-encoding] \
	[meta $tok transfer-encoding] \
	[expr {[file size testdoc.html]-[string length $testdata]}] \
	[expr {[lindex $logdata 0] - [lindex $logdata 1]}] \
	[expr {[lindex $logdata 0] - [string length $testdata]}]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    unset -nocomplain testdata logdata ::WaitHere
    halt_httpd
} -result {ok {HTTP/1.0 200 OK} ok close {} {} 0 0 0}

test http11-3.7 "-handler,close,identity as http11-3.0 but with -progress progressPause enters event loop" -setup {
test http11-3.7.$ThreadLevel "-handler,close,identity as http11-3.0 but with -progress progressPause enters event loop" -setup {
    variable httpd [create_httpd]
    set testdata ""
    set logdata ""
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1 \
                 -timeout 10000 -handler [namespace code [list handler testdata]] \
                 -progress [namespace code [list progressPause logdata]]]
		 -timeout 10000 -handler [namespace code [list handler testdata]] \
		 -progress [namespace code [list progressPause logdata]]]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok $testdata]\
        [meta $tok connection] [meta $tok content-encoding] \
        [meta $tok transfer-encoding] \
        [expr {[file size testdoc.html]-[string length $testdata]}] \
        [expr {[lindex $logdata 0] - [lindex $logdata 1]}] \
        [expr {[lindex $logdata 0] - [string length $testdata]}]
	[meta $tok connection] [meta $tok content-encoding] \
	[meta $tok transfer-encoding] \
	[expr {[file size testdoc.html]-[string length $testdata]}] \
	[expr {[lindex $logdata 0] - [lindex $logdata 1]}] \
	[expr {[lindex $logdata 0] - [string length $testdata]}]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    unset -nocomplain testdata logdata ::WaitHere
    halt_httpd
} -result {ok {HTTP/1.0 200 OK} ok close {} {} 0 0 0}

test http11-3.8 "close,identity no -handler but with -progress" -setup {
test http11-3.8.$ThreadLevel "close,identity no -handler but with -progress" -setup {
    variable httpd [create_httpd]
    set logdata ""
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1 \
                 -timeout 10000 \
                 -progress [namespace code [list progress logdata]] \
                 -headers {accept-encoding {}}]
		 -timeout 10000 \
		 -progress [namespace code [list progress logdata]] \
		 -headers {accept-encoding {}}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok]\
        [meta $tok connection] [meta $tok content-encoding] \
        [meta $tok transfer-encoding] \
        [expr {[file size testdoc.html]-[string length [http::data $tok]]}] \
        [expr {[lindex $logdata 0] - [lindex $logdata 1]}] \
        [expr {[lindex $logdata 0] - [string length [http::data $tok]]}]
	[meta $tok connection] [meta $tok content-encoding] \
	[meta $tok transfer-encoding] \
	[expr {[file size testdoc.html]-[string length [http::data $tok]]}] \
	[expr {[lindex $logdata 0] - [lindex $logdata 1]}] \
	[expr {[lindex $logdata 0] - [string length [http::data $tok]]}]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    unset -nocomplain logdata ::WaitHere
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close {} {} 0 0 0}

test http11-3.9 "close,identity no -handler but with -progress progressPause enters event loop" -setup {
test http11-3.9.$ThreadLevel "close,identity no -handler but with -progress progressPause enters event loop" -setup {
    variable httpd [create_httpd]
    set logdata ""
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1 \
                 -timeout 10000 \
                 -progress [namespace code [list progressPause logdata]] \
                 -headers {accept-encoding {}}]
		 -timeout 10000 \
		 -progress [namespace code [list progressPause logdata]] \
		 -headers {accept-encoding {}}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok]\
        [meta $tok connection] [meta $tok content-encoding] \
        [meta $tok transfer-encoding] \
        [expr {[file size testdoc.html]-[string length [http::data $tok]]}] \
        [expr {[lindex $logdata 0] - [lindex $logdata 1]}] \
        [expr {[lindex $logdata 0] - [string length [http::data $tok]]}]
	[meta $tok connection] [meta $tok content-encoding] \
	[meta $tok transfer-encoding] \
	[expr {[file size testdoc.html]-[string length [http::data $tok]]}] \
	[expr {[lindex $logdata 0] - [lindex $logdata 1]}] \
	[expr {[lindex $logdata 0] - [string length [http::data $tok]]}]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    unset -nocomplain logdata ::WaitHere
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close {} {} 0 0 0}

test http11-4.0 "normal post request" -setup {
test http11-4.0.$ThreadLevel "normal post request" -setup {
    variable httpd [create_httpd]
} -body {
    set query [http::formatQuery q 1 z 2]
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -query $query -timeout 10000]
		 -query $query -timeout 10000]
    http::wait $tok
    list status [http::status $tok] code [http::code $tok]\
        crc [check_crc $tok]\
        connection [meta $tok connection]\
        query-length [meta $tok x-query-length]
	crc [check_crc $tok]\
	connection [meta $tok connection]\
	query-length [meta $tok x-query-length]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    halt_httpd
} -result {status ok code {HTTP/1.1 200 OK} crc ok connection close query-length 7}

test http11-4.1 "normal post request, check query length" -setup {
test http11-4.1.$ThreadLevel "normal post request, check query length" -setup {
    variable httpd [create_httpd]
} -body {
    set query [http::formatQuery q 1 z 2]
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -headers [list x-check-query yes] \
                 -query $query -timeout 10000]
		 -headers [list x-check-query yes] \
		 -query $query -timeout 10000]
    http::wait $tok
    list status [http::status $tok] code [http::code $tok]\
        crc [check_crc $tok]\
        connection [meta $tok connection]\
        query-length [meta $tok x-query-length]
	crc [check_crc $tok]\
	connection [meta $tok connection]\
	query-length [meta $tok x-query-length]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    halt_httpd
} -result {status ok code {HTTP/1.1 200 OK} crc ok connection close query-length 7}

test http11-4.2 "normal post request, check long query length" -setup {
test http11-4.2.$ThreadLevel "normal post request, check long query length" -setup {
    variable httpd [create_httpd]
} -body {
    set query [string repeat a 24576]
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html\
                 -headers [list x-check-query yes]\
                 -query $query -timeout 10000]
		 -headers [list x-check-query yes]\
		 -query $query -timeout 10000]
    http::wait $tok
    list status [http::status $tok] code [http::code $tok]\
        crc [check_crc $tok]\
        connection [meta $tok connection]\
        query-length [meta $tok x-query-length]
	crc [check_crc $tok]\
	connection [meta $tok connection]\
	query-length [meta $tok x-query-length]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    halt_httpd
} -result {status ok code {HTTP/1.1 200 OK} crc ok connection close query-length 24576}

test http11-4.3 "normal post request, check channel query length" -setup {
test http11-4.3.$ThreadLevel "normal post request, check channel query length" -setup {
    variable httpd [create_httpd]
    set chan [open [makeFile {} testfile.tmp] wb+]
    puts -nonewline $chan [string repeat [encoding convertto utf-8 "This is a test\n"] 8192]
    flush $chan
    seek $chan 0
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html\
                 -headers [list x-check-query yes]\
                 -querychannel $chan -timeout 10000]
		 -headers [list x-check-query yes]\
		 -querychannel $chan -timeout 10000]
    http::wait $tok
    list status [http::status $tok] code [http::code $tok]\
        crc [check_crc $tok]\
        connection [meta $tok connection]\
        query-length [meta $tok x-query-length]
	crc [check_crc $tok]\
	connection [meta $tok connection]\
	query-length [meta $tok x-query-length]
} -cleanup {
    http::cleanup $tok
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {status ok code {HTTP/1.1 200 OK} crc ok connection close query-length 122880}

# -------------------------------------------------------------------------

# Eliminate valgrind "still reachable" reports on outstanding "Detached"
# structures in the detached list which stem from PipeClose2Proc not waiting
# around for background processes to complete, meaning that previous calls to
# Tcl_ReapDetachedProcs might not have had a chance to reap all processes.
after 10
exec [info nameofexecutable] << {}

foreach p {create_httpd httpd_read halt_httpd meta check_crc} {
    if {[llength [info proc $p]]} {rename $p {}}
}
removeFile testdoc.html
removeFile largedoc.html
unset -nocomplain httpd_port httpd p

if {[testConstraint ThreadLevelSummary]} {
::tcltest::cleanupTests
    ::tcltest::cleanupTests
}

Changes to tests/httpPipeline.test.

1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16




































17
18
19
20
21
22
23
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
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





-
+









-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







# httpPipeline.test
#
#	Test HTTP/1.1 concurrent requests including
#	queueing, pipelining and retries.
#
# Copyright (C) 2018 Keith Nash <kjnash@users.sourceforge.net>
# Copyright © 2018 Keith Nash <kjnash@users.sourceforge.net>
#
# 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::*
}

package require http 2.9
package require http 2.10

# ------------------------------------------------------------------------------
# (0) Socket Creation in Thread, which triples the number of tests.
# ------------------------------------------------------------------------------

# To write a separate summary for each value of ThreadLevel, set constraint ThreadLevelSummary.
#testConstraint ThreadLevelSummary 0

if 0 {
    # For debugging: run with a single value of ThreadLevel: 0|1|2
    set ThreadLevel 0
    testConstraint ThreadLevelSummary 1
}
if {![info exists ThreadLevel]} {
    if {[catch {package require Thread}] == 0} {
	set ValueRange {0 1 2}
    } else {
	set ValueRange {0 1}
    }

    # For each value of ThreadLevel, source this file recursively in the
    # same interpreter.
    foreach ThreadLevel $ValueRange {
	source [info script]
    }
    catch {unset ThreadLevel}
    catch {unset ValueRange}
    if {![testConstraint ThreadLevelSummary]} {
	::tcltest::cleanupTests
    }
    return
}

catch {puts "==== Test with ThreadLevel $ThreadLevel ===="}
http::config -threadlevel $ThreadLevel

set sourcedir [file normalize [file dirname [info script]]]
source [file join $sourcedir httpTest.tcl]
source [file join $sourcedir httpTestScript.tcl]

# ------------------------------------------------------------------------------
# (1) Define the test scripts that will be used to generate logs for analysis -
444
445
446
447
448
449
450
451

452
453
454
455
456
457




458
459
460
461
462
463
464





465
466
467
468
469
470
471
472

473
474
475
476
477
478

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
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
558
559
560
561

562
563
564
565
566
567
568
569







-
+


-
-
-
-
+
+
+
+


-
-
-
-
-
+
+
+
+
+







-
+





-
+














-
+










-
+













-
+








-
+







	    return -code error {no matching script}
	}
    }


    if {$ca < 3} {
	# Not Keep-Alive.
        set result "Passed all sanity checks."
	set result "Passed all sanity checks."

    } elseif {$ca == 3} {
        # Keep-Alive, not pipelined.
        set result {}
        append result "Passed all sanity checks.\n"
        append result "Have overlaps including response body:\n"
	# Keep-Alive, not pipelined.
	set result {}
	append result "Passed all sanity checks.\n"
	append result "Have overlaps including response body:\n"

    } else {
        # Keep-Alive, pipelined: ($ca == 4)
        set result {}
        append result "Passed all sanity checks.\n"
        append result "Overlap-free without response body:\n"
        append result "$resShort"
	# Keep-Alive, pipelined: ($ca == 4)
	set result {}
	append result "Passed all sanity checks.\n"
	append result "Overlap-free without response body:\n"
	append result "$resShort"
    }

    # - The special case of test *.18*-testEof needs test results to be
    #   individually written.
    # - These test -repost 0 when there is a POST to apply it to, and the server
    #   timeout has not been detected.
    if {($cb == 18) && ($te == 1)} {
        if {$ca < 3} {
	if {$ca < 3} {
	    # Not Keep-Alive.
	    set result "Passed all sanity checks."

	} elseif {$ca == 3 && $delay == 0} {
	    # Keep-Alive, not pipelined.
            set result [MakeMessage {
	    set result [MakeMessage {
		|Problems with sanity checks:
		|Wrong sequence for token ::http::2 - {A B C D X X X}
		|- and error(s) X
		|Wrong sequence for token ::http::3 - {A X X}
		|- and error(s) X
		|Wrong sequence for token ::http::4 - {A X X X}
		|- and error(s) X
		|
		|Have overlaps including response body:
		|
	    }]

	} elseif {$ca == 3} {
	    # Keep-Alive, not pipelined.
            set result [MakeMessage {
	    set result [MakeMessage {
		|Problems with sanity checks:
		|Wrong sequence for token ::http::2 - {A B C D X X X}
		|- and error(s) X
		|
		|Have overlaps including response body:
		|
	    }]

	} elseif {$delay == 0} {
	    # Keep-Alive, pipelined: ($ca == 4)
            set result [MakeMessage {
	    set result [MakeMessage {
		|Problems with sanity checks:
		|Wrong sequence for token ::http::2 - {A B C D X X X}
		|- and error(s) X
		|Wrong sequence for token ::http::3 - {A X X}
		|- and error(s) X
		|Wrong sequence for token ::http::4 - {A X X X}
		|- and error(s) X
		|
		|Overlap-free without response body:
		|
	    }]

	} else {
            set result [MakeMessage {
	    set result [MakeMessage {
		|Problems with sanity checks:
		|Wrong sequence for token ::http::2 - {A B C D X X X}
		|- and error(s) X
		|
		|Overlap-free without response body:
		|
	    }]

        }
	}
    }

    return [list "$start$middle$end" $result]
}

# ------------------------------------------------------------------------------
#  Proc MakeMessage
578
579
580
581
582
583
584
585
586


587
588

589
590
591


592
593
594
595
596

597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617

618
619

620
621
622
623
624
625
626
627





628
629
630
631
632


633
634
635


636
637
638
639



640
641
642
643
644
645
646
613
614
615
616
617
618
619


620
621
622

623
624


625
626
627
628
629
630

631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651

652
653

654
655
656
657





658
659
660
661
662
663
664
665


666
667
668


669
670
671



672
673
674
675
676
677
678
679
680
681







-
-
+
+

-
+

-
-
+
+




-
+




















-
+

-
+



-
-
-
-
-
+
+
+
+
+



-
-
+
+

-
-
+
+

-
-
-
+
+
+







    set notPiped    {}
    set notIncluded {}

    # --------------------------------------------------------------------------
    # Custom code for specific tests
    # --------------------------------------------------------------------------
    if {$header < 3} {
        set skipOverlaps 1
        for {set i 1} {$i <= $num} {incr i} {
	set skipOverlaps 1
	for {set i 1} {$i <= $num} {incr i} {
	    lappend notPiped $i
        }
	}
    } elseif {$header > 2 && $footer == 18 && $te == 1} {
        set skipOverlaps 1
        if {$delay == 0} {
	set skipOverlaps 1
	if {$delay == 0} {
	    # Transaction 1 is conventional.
	    # Check that transactions 2,3,4 are cancelled.
	    set notPiped {1}
	    set notIncluded $notPiped
        } else {
	} else {
	    # Transaction 1 is conventional.
	    # Check that transaction 2 is cancelled.
	    # The timing of transactions 3 and 4 is uncertain.
	    set notPiped {1 3 4}
	    set notIncluded $notPiped
	}
    } elseif {$footer in {20 22 23 24 25}} {
	# Transaction 2 uses its own socket.
	set notPiped    2
	set notIncluded $notPiped
    } else {
    }
    # --------------------------------------------------------------------------
    # End of custom code for specific tests
    # --------------------------------------------------------------------------


    set Results [logAnalyse $num $skipOverlaps $notIncluded $notPiped]
    lassign $Results msg cleanE cleanF dirtyE dirtyF
    if {$msg eq {}} {
        set msg "Passed all sanity checks."
	set msg "Passed all sanity checks."
    } else {
        set msg "Problems with sanity checks:\n$msg"
	set msg "Problems with sanity checks:\n$msg"
    }

    if 0 {
        puts $msg
        puts "Overlap-free including response body:\n$cleanF"
        puts "Have overlaps including response body:\n$dirtyF"
        puts "Overlap-free without response body:\n$cleanE"
        puts "Have overlaps without response body:\n$dirtyE"
	puts $msg
	puts "Overlap-free including response body:\n$cleanF"
	puts "Have overlaps including response body:\n$dirtyF"
	puts "Overlap-free without response body:\n$cleanE"
	puts "Have overlaps without response body:\n$dirtyE"
    }

    if {$header < 3} {
        # No ordering, just check that transactions all finish
        set result $msg
	# No ordering, just check that transactions all finish
	set result $msg
    } elseif {$header == 3} {
        # Not pipelined - check overlaps with response body.
        set result "$msg\nHave overlaps including response body:\n$dirtyF"
	# Not pipelined - check overlaps with response body.
	set result "$msg\nHave overlaps including response body:\n$dirtyF"
    } else {
        # Pipelined - check overlaps without response body.  Check that the
        # first request, the first requests after replay, and POSTs are clean.
        set result "$msg\nOverlap-free without response body:\n$cleanE"
	# Pipelined - check overlaps without response body.  Check that the
	# first request, the first requests after replay, and POSTs are clean.
	set result "$msg\nOverlap-free without response body:\n$cleanE"
    }
    set ::nTokens $num
    return $result
}


# ------------------------------------------------------------------------------
671
672
673
674
675
676
677
678
679
680



681
682
683
684
685
686
687
706
707
708
709
710
711
712



713
714
715
716
717
718
719
720
721
722







-
-
-
+
+
+







#     connection ater the current request.
# - Any other variables should be ignored.
# ------------------------------------------------------------------------------

namespace eval ::httpTestScript {
    variable URL
    array set URL {
        a  http://test-tcl-http.kerlin.org/index.html?page=privacy
        b  http://test-tcl-http.kerlin.org/index.html?page=conditions
        c  http://test-tcl-http.kerlin.org/index.html?page=welcome
	a  http://test-tcl-http.kerlin.org/index.html?page=privacy
	b  http://test-tcl-http.kerlin.org/index.html?page=conditions
	c  http://test-tcl-http.kerlin.org/index.html?page=welcome
    }
}


# ------------------------------------------------------------------------------
# (5) Define the tests
# ------------------------------------------------------------------------------
720
721
722
723
724
725
726
727

728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743

744
745

746
747
748
749

750
751
752
753
754
755
756
757
758
759
760
761
762
763

764
765

766
767
768
769
770
771
772
755
756
757
758
759
760
761

762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777

778
779

780
781
782
783

784
785
786
787
788
789
790
791
792
793
794
795
796
797

798
799

800
801
802
803
804
805
806
807







-
+















-
+

-
+



-
+













-
+

-
+







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

proc SetTestEof {test} {
    set body [info body ::http::KeepSocket]
    set subs "    set TEST_EOF $test"
    set count [regsub -line -all -- {^\s*set TEST_EOF .*$} $body $subs newBody]
    if {$count != 1} {
        return -code error {proc ::http::KeepSocket has unexpected form}
	return -code error {proc ::http::KeepSocket has unexpected form}
    }
    proc ::http::KeepSocket {token} $newBody
    return
}

for {set header 1} {$header <= 4} {incr header} {
    if {$header == 4} {
	setHttpTestOptions -dotted 1
	set match glob
    } else {
	setHttpTestOptions -dotted 0
	set match exact
    }

    if {$header == 2} {
        set cons0 {serverNeeded duplicate}
	set cons0 {serverNeeded duplicate}
    } else {
        set cons0 serverNeeded
	set cons0 serverNeeded
    }

    for {set footer 1} {$footer <= 25} {incr footer} {
        foreach {delay label} {
	foreach {delay label} {
	       0 a
	       1 b
	       2 c
	       3 d
	       5 e
	       8 f
	      12 g
	     100 h
	     500 i
	    2000 j
	} {
	  foreach te {0 1} {
	    if {$te} {
	        set tag testEof
		set tag testEof
	    } else {
	        set tag normal
		set tag normal
	    }
	    set suffix {}
	    set cons $cons0

	    # ------------------------------------------------------------------
	    # Custom code for individual tests
	    # ------------------------------------------------------------------
807
808
809
810
811
812
813
814

815
816
817
818
819
820



821
822
823
824


825
826
827
828
829
830
831
842
843
844
845
846
847
848

849
850
851
852



853
854
855
856
857


858
859
860
861
862
863
864
865
866







-
+



-
-
-
+
+
+


-
-
+
+







		# Test use WAIT and depend on server timeout before this time.
		lappend cons timeout1s
	    }
	    # ------------------------------------------------------------------
	    # End of custom code.
	    # ------------------------------------------------------------------

            set name "pipeline test header $header footer $footer delay $delay $tag$suffix"
	    set name "pipeline test header $header footer $footer delay $delay $tag$suffix"


	    # Here's the test:
            test httpPipeline-${header}.${footer}${label}-${tag} $name \
            -constraints $cons \
            -setup [string map [list TE $te] {
	    test httpPipeline-${header}.${footer}${label}-${tag}-$ThreadLevel $name \
	    -constraints $cons \
	    -setup [string map [list TE $te] {
		# Restore default values for tests:
		http::config -pipeline 1 -postfresh 0 -repost 1
                http::init
                set http::http(uid) 0
		http::init
		set http::http(uid) 0
		SetTestEof {TE}
	    }] -body [list RunTest $header $footer $delay $te] -cleanup {
		# Restore default values for tests:
		http::config -pipeline 1 -postfresh 0 -repost 1
		cleanupHttpTestScript
		SetTestEof 0
		cleanupHttpTest
861
862
863
864
865
866
867

868


896
897
898
899
900
901
902
903

904
905







+
-
+
+
# ------------------------------------------------------------------------------


unset header footer delay label suffix match cons name te
namespace delete ::httpTest
namespace delete ::httpTestScript

if {[testConstraint ThreadLevelSummary]} {
::tcltest::cleanupTests
    ::tcltest::cleanupTests
}

Added tests/httpProxy.test.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# Commands covered: http::geturl when using a proxy server.
#
# This file contains a collection of tests for the http script library.
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-2000 Ajuba Solutions.
# Copyright © 2022-2023 Keith Nash.
#
# 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::*
}

package require http 2.10

# To write a separate summary for each value of ThreadLevel, set constraint ThreadLevelSummary.
#testConstraint ThreadLevelSummary 0
#testConstraint needsSquidNoAuth   0
#testConstraint needsSquidAuth     0
#testConstraint needsTclTls        0
#testConstraint needsTwapi         0
#testConstraint needsTwapiFull     0
#testConstraint knownBug           0
#
# The values of constraints needsTls, knownTwapiFullBugThreadlevelAny, knownTwapiFullBugThreadUsed are always generated by this script.

proc bgerror {args} {
    global errorInfo
    puts stderr "httpProxy.test bgerror"
    puts stderr [join $args]
    puts stderr $errorInfo
}

proc stopMe {token} {
    set ${token}(z) done
}
proc putsBlurb {} {
    puts {}
    puts {- Constraints needsTls, knownTwapiFullBugThreadlevelAny, knownTwapiFullBugThreadUsed are}
    puts {  always set by the script, not by the caller.}
    puts {- Set one of needsTclTls, needsTwapi, needsTwapiFull instead of needsTls.}
    puts {- Set knownBug instead of knownTwapiFullBugThreadlevelAny, knownTwapiFullBugThreadUsed.}
    puts {- If the caller sets constraint needsTwapi, the script forces needsSquidNoAuth and needsSquidAuth to 0.}
    puts {}
    return
}

if 0 {
    # For debugging: run with a single value of ThreadLevel: 0|1|2
    set ThreadLevel 0
    testConstraint ThreadLevelSummary 1
}
if {![info exists ThreadLevel]} {
    if {[catch {package require Thread}] == 0} {
	set ValueRange {0 1 2}
    } else {
	set ValueRange {0 1}
    }

    # For each value of ThreadLevel, source this file recursively in the
    # same interpreter.
    foreach ThreadLevel $ValueRange {
	source [info script]
    }
    catch {unset ThreadLevel}
    catch {unset ValueRange}
    if {![testConstraint ThreadLevelSummary]} {
	putsBlurb
	::tcltest::cleanupTests
    }
    return
}

catch {puts "==== Test with ThreadLevel $ThreadLevel ===="}
http::config -threadlevel $ThreadLevel

testConstraint needsTls         [expr {    [testConstraint needsTclTls]
					|| [testConstraint needsTwapi]
					|| [testConstraint needsTwapiFull]
				}]

if {[testConstraint needsTclTls]} {
    package require tls
    http::register https 443 [list ::tls::socket -ssl2 0 -ssl3 0 \
	    -tls1 0 -tls1.1 0 -tls1.2 1 -tls1.3 0 -autoservername 1] ::tls::socketCmd 1 1
    testConstraint knownTwapiFullBugThreadlevelAny 1
    testConstraint knownTwapiFullBugThreadUsed 1
} elseif {[testConstraint needsTwapi]} {
    # "Original" http::register with 3 arguments has the same capabilities as
    # in http 2.9 and earlier.  This means that:
    # (1) it cannot open a socket in a background thread (this option stops a
    #     slow DNS lookup from blocking a [socket -async] command); and
    # (2) it cannot use a https proxy.
    #
    testConstraint needsSquidNoAuth 0
    testConstraint needsSquidAuth   0
    package require twapi
    http::register https 443 ::twapi::tls_socket
    testConstraint knownTwapiFullBugThreadlevelAny 1
    testConstraint knownTwapiFullBugThreadUsed 1
} elseif {[testConstraint needsTwapiFull]} {
    # (Any revisions to TWAPI, and the contents/existence of the twapiTlsPlus
    # wrapper, can be negotiated if the bugs listed below can be fixed.)
    # Use a temporary wrapper package twapiTlsPlus to present a suitable API.
    #
    # N.B. MUST EDIT twapi*/tls.tcl so that
    #-        set so [$socketcmd {*}$socket_args {*}$args]
    #+        set so [{*}$socketcmd {*}$socket_args {*}$args]
    #
    # Bug with https, threadLevel 1,2, no proxy: try test 'httpProxy-2.2.*'
    # Bug with https, threadLevel 0, with proxy: try test 'httpProxy-3.4.0'
    # In both cases (using TWAPI 4.7.2 25d8bc), the result is:
    # ---- Test generated error; Return code was: 1
    # ---- Return code should have been one of: 0 2
    # ---- errorInfo: cannot yield: C stack busy
    #     while executing
    # "http::geturl https://www.google.com/"
    #
    source [file join [file dirname [info script]] twapiTlsPlus.tcl]
    package require twapiTlsPlus
    http::register https 443 ::twapiTlsPlus::socket ::twapiTlsPlus::socketCmd 1 1
    testConstraint knownTwapiFullBugThreadlevelAny [testConstraint knownBug]

    if {($ThreadLevel == 1)} {
	if {[catch {package require Thread}]} {
	    set usingThread 0
	} else {
	    set usingThread 2
	}
    } else {
	set usingThread $ThreadLevel
    }
    if {$usingThread} {
	testConstraint knownTwapiFullBugThreadUsed [testConstraint knownBug]
    } else {
	testConstraint knownTwapiFullBugThreadUsed 1
    }
} else {
}

# Testing with Squid
# - Example Squid configuration for Enterprise Linux 8 (Red Hat, Oracle, Rocky,
#   Alma, ...) is in file tests/httpProxySquidConfigForEL8.tar.gz.
# - Example Squid configuration for Diladele Squid on Windows is in
#   file tests/httpProxySquidConfigForWindowsDiladele.zip.
#
# - Two instances of Squid are launched, one that needs authentication and one
#   that does not.
# - Each instance of Squid listens on IPv4 and IPv6, on different ports.
# - If only one instance of Squid can be launched at a time, use the separate
#   constraints needsSquidNoAuth, needsSquidAuth when testing.

# Instance of Squid that does not need authentication.
set n4host 127.0.0.1
set n6host ::1
set n4port 3128
set n6port 3130

# Instance of Squid that needs authentication.
set a4host 127.0.0.1
set a6host ::1
set a4port 3129
set a6port 3131

# concat Basic [base64::encode alice:alicia]
set aliceCreds {Basic YWxpY2U6YWxpY2lh}

# concat Basic [base64::encode intruder:intruder]
set badCreds {Basic aW50cnVkZXI6aW50cnVkZXI=}

# For the benefit of the target server, have a short delay between tests.
set fetchPause 200

foreach constr {
    ThreadLevelSummary
    needsSquidNoAuth
    needsSquidAuth
    needsTclTls
    needsTwapi
    needsTwapiFull
    needsTls
    knownTwapiFullBugThreadlevelAny
    knownTwapiFullBugThreadUsed
} {
    # For debugging.
    # puts [list testConstraint $constr [testConstraint $constr]]
}
#putsBlurb

test httpProxy-1.1.$ThreadLevel {squid is running - ipv4 no-auth} -constraints {needsSquidNoAuth} -setup {
} -body {
    after $fetchPause

    set token [http::geturl http://$n4host:$n4port/]
    set ri [http::responseInfo $token]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed]"
} -result {complete ok 400 -- none} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res
}

test httpProxy-1.2.$ThreadLevel {squid is running - ipv6 no-auth} -constraints {needsSquidNoAuth} -setup {
} -body {
    after $fetchPause

    set token [http::geturl http://\[$n6host\]:$n6port/]
    set ri [http::responseInfo $token]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed]"
} -result {complete ok 400 -- none} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res
}

test httpProxy-1.3.$ThreadLevel {squid is running - ipv4 with-auth} -constraints {needsSquidAuth} -setup {
} -body {
    after $fetchPause

    set token [http::geturl http://$a4host:$a4port/]
    set ri [http::responseInfo $token]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed]"
} -result {complete ok 400 -- none} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res
}

test httpProxy-1.4.$ThreadLevel {squid is running - ipv6 with-auth} -constraints {needsSquidAuth} -setup {
} -body {
    after $fetchPause

    set token [http::geturl http://\[$a6host\]:$a6port/]
    set ri [http::responseInfo $token]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed]"
} -result {complete ok 400 -- none} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res
}

test httpProxy-2.1.$ThreadLevel {http no-proxy no-auth} -constraints {} -setup {
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
} -body {
    after $fetchPause

    set token [http::geturl http://www.google.com/]
    set ri [http::responseInfo $token]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 200 -- none -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res
}

test httpProxy-2.2.$ThreadLevel {https no-proxy no-auth} -constraints {needsTls knownTwapiFullBugThreadUsed} -setup {
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
} -body {
    after $fetchPause

    set token [http::geturl https://www.google.com/]
    set ri [http::responseInfo $token]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 200 -- none -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res
}

test httpProxy-2.3.$ThreadLevel {http with-proxy ipv4 no-auth} -constraints {needsSquidNoAuth} -setup {
   http::config -proxyhost $n4host -proxyport $n4port -proxynot {127.0.0.1 localhost} -proxyauth {}
} -body {
    after $fetchPause

    set token [http::geturl http://www.google.com/]
    set ri [http::responseInfo $token]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 200 -- HttpProxy -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res
    http::config -proxyhost {} -proxyport {} -proxynot {}
}

test httpProxy-2.4.$ThreadLevel {https with-proxy ipv4 no-auth} -constraints {needsSquidNoAuth needsTls knownTwapiFullBugThreadlevelAny} -setup {
   http::config -proxyhost $n4host -proxyport $n4port -proxynot {127.0.0.1 localhost} -proxyauth {}
} -body {
    after $fetchPause

    set token [http::geturl https://www.google.com/]
    set ri [http::responseInfo $token]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 200 -- SecureProxy -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res
    http::config -proxyhost {} -proxyport {} -proxynot {}
}

test httpProxy-2.5.$ThreadLevel {http with-proxy ipv6 no-auth} -constraints {needsSquidNoAuth} -setup {
   http::config -proxyhost $n6host -proxyport $n6port -proxynot {::1 localhost} -proxyauth {}
} -body {
    after $fetchPause

    set token [http::geturl http://www.google.com/]
    set ri [http::responseInfo $token]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 200 -- HttpProxy -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res
    http::config -proxyhost {} -proxyport {} -proxynot {}
}

test httpProxy-2.6.$ThreadLevel {https with-proxy ipv6 no-auth} -constraints {needsSquidNoAuth needsTls knownTwapiFullBugThreadlevelAny} -setup {
   http::config -proxyhost $n6host -proxyport $n6port -proxynot {::1 localhost} -proxyauth {}
} -body {
    after $fetchPause

    set token [http::geturl https://www.google.com/]
    set ri [http::responseInfo $token]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 200 -- SecureProxy -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res
    http::config -proxyhost {} -proxyport {} -proxynot {}
}

test httpProxy-3.1.$ThreadLevel {http no-proxy with-auth valid-creds-provided} -constraints {} -setup {
   http::config -proxyhost {} -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $aliceCreds
} -body {
    after $fetchPause

    set token [http::geturl http://www.google.com/]
    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 200 -- none 0 0 -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res pos1 pos2
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-3.2.$ThreadLevel {https no-proxy with-auth valid-creds-provided} -constraints {needsTls knownTwapiFullBugThreadUsed} -setup {
   http::config -proxyhost {} -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $aliceCreds
} -body {
    after $fetchPause

    set token [http::geturl https://www.google.com/]
    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 200 -- none 0 0 -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res pos1 pos2
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-3.3.$ThreadLevel {http with-proxy ipv4 with-auth valid-creds-provided} -constraints {needsSquidAuth} -setup {
   http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $aliceCreds
} -body {
    after $fetchPause

    set token [http::geturl http://www.google.com/]
    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 200 -- HttpProxy 1 1 -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res pos1 pos2
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-3.4.$ThreadLevel {https with-proxy ipv4 with-auth valid-creds-provided} -constraints {needsSquidAuth needsTls knownTwapiFullBugThreadlevelAny} -setup {
   http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $aliceCreds
} -body {
    after $fetchPause

    set token [http::geturl https://www.google.com/]
    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 200 -- SecureProxy 0 0 -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res pos1 pos2
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-3.5.$ThreadLevel {http with-proxy ipv6 with-auth valid-creds-provided} -constraints {needsSquidAuth} -setup {
   http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $aliceCreds
} -body {
    after $fetchPause

    set token [http::geturl http://www.google.com/]
    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 200 -- HttpProxy 1 1 -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res pos1 pos2
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-3.6.$ThreadLevel {https with-proxy ipv6 with-auth valid-creds-provided} -constraints {needsSquidAuth needsTls knownTwapiFullBugThreadlevelAny} -setup {
   http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $aliceCreds
} -body {
    after $fetchPause

    set token [http::geturl https://www.google.com/]
    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 200 -- SecureProxy 0 0 -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res pos1 pos2
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-3.7.$ThreadLevel {http with-proxy ipv4 with-auth valid-creds-provided; check that 2nd valid request with creds is possible, and keep-alive works} -constraints {needsSquidAuth} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $aliceCreds
    after $fetchPause
    set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000]
} -body {
    after $fetchPause

    # Use the same caution as for the corresponding https test.
    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 200 -- HttpProxy 1 1 -- -1 done 1} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-3.7x.$ThreadLevel {http with-proxy ipv4 with-auth 1st request no-creds-provided; check that 2nd request with creds is possible} -constraints {needsSquidAuth} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth {}
    after $fetchPause
    set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000]

    http::config -proxyauth $aliceCreds
} -body {
    after $fetchPause

    # Use the same caution as for the corresponding https test.
    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 200 -- HttpProxy 1 1 -- -1 done 1} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-3.8.$ThreadLevel {https with-proxy ipv4 with-auth valid-creds-provided; check that 2nd valid request with creds is possible, and keep-alive works} -constraints {needsSquidAuth needsTls knownTwapiFullBugThreadlevelAny} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $aliceCreds
    after $fetchPause
    set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000]
} -body {
    after $fetchPause

    # If a bug passes the socket of a failed CONNECT to the main request, an infinite
    # wait can occur despite -timeout.  Fix this with http::reset; to do this the call
    # to http::geturl must be async so we have $token for use as argument of reset.
    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 200 -- SecureProxy 0 0 -- -1 done 1} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-3.8x.$ThreadLevel {https with-proxy ipv4 with-auth 1st request no-creds-provided; check that 2nd request with creds is possible} -constraints {needsSquidAuth needsTls knownTwapiFullBugThreadlevelAny} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth {}
    after $fetchPause
    set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000]

    http::config -proxyauth $aliceCreds
} -body {
    after $fetchPause

    # If a bug passes the socket of a failed CONNECT to the main request, an infinite
    # wait can occur despite -timeout.  Fix this with http::reset; to do this the call
    # to http::geturl must be async so we have $token for use as argument of reset.
    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 200 -- SecureProxy 0 0 -- -1 done 0} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-3.9.$ThreadLevel {http with-proxy ipv6 with-auth valid-creds-provided; check that 2nd valid request with creds is possible, and keep-alive works} -constraints {needsSquidAuth} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $aliceCreds
    after $fetchPause
    set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000]
} -body {
    after $fetchPause

    # Use the same caution as for the corresponding https test.
    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 200 -- HttpProxy 1 1 -- -1 done 1} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-3.9p.$ThreadLevel {http with-proxy ipv6 with-auth valid-creds-provided; check that 2nd valid request with creds is possible, and keep-alive works, pipelining requested and possible} -constraints {needsSquidAuth} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $aliceCreds
} -body {
    after $fetchPause

    set can0 [after 6000 {http::reset $token0; set ${token0}(z) timeout}]
    set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
after idle {
    after $fetchPause

    # Use the same caution as for the corresponding https test.
    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can
}
    vwait ${token0}(z)
    after cancel $can0

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 200 -- HttpProxy 1 1 -- -1 done 1} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can0 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-3.9x.$ThreadLevel {http with-proxy ipv6 with-auth 1st request no-creds-provided; check that 2nd request with creds is possible} -constraints {needsSquidAuth} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth {}
    after $fetchPause
    set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000]

    http::config -proxyauth $aliceCreds
} -body {
    after $fetchPause

    # Use the same caution as for the corresponding https test.
    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 200 -- HttpProxy 1 1 -- -1 done 1} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-3.10.$ThreadLevel {https with-proxy ipv6 with-auth valid-creds-provided; check that 2nd valid request with creds is possible, and keep-alive works} -constraints {needsSquidAuth needsTls knownTwapiFullBugThreadlevelAny} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $aliceCreds
    after $fetchPause
    set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000]
} -body {
    after $fetchPause

    # If a bug passes the socket of a failed CONNECT to the main request, an infinite
    # wait can occur despite -timeout.  Fix this with http::reset; to do this the call
    # to http::geturl must be async so we have $token for use as argument of reset.
    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 200 -- SecureProxy 0 0 -- -1 done 1} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-3.10p.$ThreadLevel {https with-proxy ipv6 with-auth valid-creds-provided; check that 2nd valid request with creds is possible, and keep-alive works, pipelining requested and possible} -constraints {needsSquidAuth needsTls knownTwapiFullBugThreadlevelAny} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $aliceCreds
} -body {
    after $fetchPause

    set can0 [after 6000 {http::reset $token0; set ${token0}(z) timeout}]
    set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
after idle {
    after $fetchPause

    # If a bug passes the socket of a failed CONNECT to the main request, an infinite
    # wait can occur despite -timeout.  Fix this with http::reset; to do this the call
    # to http::geturl must be async so we have $token for use as argument of reset.
    set can [after 6000 {http::reset $token0; set ${token}(z) timeout}]
    set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can
}
    vwait ${token0}(z)
    after cancel $can0

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 200 -- SecureProxy 0 0 -- -1 done 1} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can0 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-3.10x.$ThreadLevel {https with-proxy ipv6 with-auth 1st request no-creds-provided; check that 2nd request with creds is possible} -constraints {needsSquidAuth needsTls knownTwapiFullBugThreadlevelAny} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth {}
    after $fetchPause

    set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000]

    http::config -proxyauth $aliceCreds
} -body {
    after $fetchPause

    # If a bug passes the socket of a failed CONNECT to the main request, an infinite
    # wait can occur despite -timeout.  Fix this with http::reset; to do this the call
    # to http::geturl must be async so we have $token for use as argument of reset.
    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 200 -- SecureProxy 0 0 -- -1 done 0} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-4.1.$ThreadLevel {http no-proxy with-auth no-creds-provided} -constraints {} -setup {
   http::config -proxyhost {} -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth {}
} -body {
    after $fetchPause

    set token [http::geturl http://www.google.com/]
    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 200 -- none 0 0 -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res pos1 pos2
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-4.2.$ThreadLevel {https no-proxy with-auth no-creds-provided} -constraints {needsTls knownTwapiFullBugThreadUsed} -setup {
   http::config -proxyhost {} -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth {}
} -body {
    after $fetchPause

    set token [http::geturl https://www.google.com/]
    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 200 -- none 0 0 -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res pos1 pos2
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-4.3.$ThreadLevel {http with-proxy ipv4 with-auth no-creds-provided} -constraints {needsSquidAuth} -setup {
   http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth {}
} -body {
    after $fetchPause

    set token [http::geturl http://www.google.com/]
    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 407 -- HttpProxy 0 0 -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res pos1 pos2
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-4.4.$ThreadLevel {https with-proxy ipv4 with-auth no-creds-provided} -constraints {needsSquidAuth needsTls knownTwapiFullBugThreadlevelAny} -setup {
   http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth {}
} -body {
    after $fetchPause

    set token [http::geturl https://www.google.com/]
    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 407 -- SecureProxyFailed 0 0 -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res pos1 pos2
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-4.5.$ThreadLevel {http with-proxy ipv6 with-auth no-creds-provided} -constraints {needsSquidAuth} -setup {
   http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth {}
} -body {
    after $fetchPause

    set token [http::geturl http://www.google.com/]
    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 407 -- HttpProxy 0 0 -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res pos1 pos2
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-4.6.$ThreadLevel {https with-proxy ipv6 with-auth no-creds-provided} -constraints {needsSquidAuth needsTls knownTwapiFullBugThreadlevelAny} -setup {
   http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth {}
} -body {
    after $fetchPause

    set token [http::geturl https://www.google.com/]
    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 407 -- SecureProxyFailed 0 0 -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res pos1 pos2
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-4.7.$ThreadLevel {http with-proxy ipv4 with-auth no-creds-provided; check that 2nd request is possible} -constraints {needsSquidAuth} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth {}
    after $fetchPause
    set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000]
} -body {
    after $fetchPause

    # Use the same caution as for the corresponding https test.
    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 407 -- HttpProxy 0 0 -- -1 done 1} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-4.8.$ThreadLevel {https with-proxy ipv4 with-auth no-creds-provided; check that 2nd request is possible} -constraints {needsSquidAuth needsTls knownTwapiFullBugThreadlevelAny} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth {}
    after $fetchPause
    set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000]
} -body {
    after $fetchPause

    # If a bug passes the socket of a failed CONNECT to the main request, an infinite
    # wait can occur despite -timeout.  Fix this with http::reset; to do this the call
    # to http::geturl must be async so we have $token for use as argument of reset.
    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 407 -- SecureProxyFailed 0 0 -- -1 done 0} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-4.9.$ThreadLevel {http with-proxy ipv6 with-auth no-creds-provided; check that 2nd request is possible} -constraints {needsSquidAuth} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth {}
    after $fetchPause
    set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000]
} -body {
    after $fetchPause

    # Use the same caution as for the corresponding https test.
    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 407 -- HttpProxy 0 0 -- -1 done 1} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-4.9p.$ThreadLevel {http with-proxy ipv6 with-auth no-creds-provided; check that 2nd request is possible, pipelining requested and possible} -constraints {needsSquidAuth} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth {}
} -body {
    after $fetchPause

    set can0 [after 6000 {http::reset $token0; set ${token0}(z) timeout}]
    set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
after idle {
    after $fetchPause

    # Use the same caution as for the corresponding https test.
    set can [after 6000 {http::reset $token0; set ${token}(z) timeout}]
    set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can
}
    vwait ${token0}(z)
    after cancel $can0

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 407 -- HttpProxy 0 0 -- -1 done 1} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can0 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-4.10.$ThreadLevel {https with-proxy ipv6 with-auth no-creds-provided; check that 2nd request is possible} -constraints {needsSquidAuth needsTls knownTwapiFullBugThreadlevelAny} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth {}
    after $fetchPause
    set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000]
} -body {
    after $fetchPause

    # If a bug passes the socket of a failed CONNECT to the main request, an infinite
    # wait can occur despite -timeout.  Fix this with http::reset; to do this the call
    # to http::geturl must be async so we have $token for use as argument of reset.
    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 407 -- SecureProxyFailed 0 0 -- -1 done 0} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-4.10p.$ThreadLevel {https with-proxy ipv6 with-auth no-creds-provided; check that 2nd request is possible, pipelining requested but not possible} -constraints {needsSquidAuth needsTls knownTwapiFullBugThreadlevelAny} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth {}
} -body {
    after $fetchPause

    set can0 [after 6000 {http::reset $token0; set ${token0}(z) timeout}]
    set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
after idle {
    after $fetchPause

    # If a bug passes the socket of a failed CONNECT to the main request, an infinite
    # wait can occur despite -timeout.  Fix this with http::reset; to do this the call
    # to http::geturl must be async so we have $token for use as argument of reset.
    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can
}
    vwait ${token0}(z)
    after cancel $can0

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 407 -- SecureProxyFailed 0 0 -- -1 done 0} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can0 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-5.1.$ThreadLevel {http no-proxy with-auth bad-creds-provided} -constraints {} -setup {
   http::config -proxyhost {} -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $badCreds
} -body {
    after $fetchPause

    set token [http::geturl http://www.google.com/]
    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 200 -- none 0 0 -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res pos1 pos2
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-5.2.$ThreadLevel {https no-proxy with-auth bad-creds-provided} -constraints {needsTls knownTwapiFullBugThreadUsed} -setup {
   http::config -proxyhost {} -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $badCreds
} -body {
    after $fetchPause

    set token [http::geturl https://www.google.com/]
    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 200 -- none 0 0 -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res pos1 pos2
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-5.3.$ThreadLevel {http with-proxy ipv4 with-auth bad-creds-provided} -constraints {needsSquidAuth} -setup {
   http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $badCreds
} -body {
    after $fetchPause

    set token [http::geturl http://www.google.com/]
    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 407 -- HttpProxy 1 1 -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res pos1 pos2
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-5.4.$ThreadLevel {https with-proxy ipv4 with-auth bad-creds-provided} -constraints {needsSquidAuth needsTls knownTwapiFullBugThreadlevelAny} -setup {
   http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $badCreds
} -body {
    after $fetchPause

    set token [http::geturl https://www.google.com/]
    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 407 -- SecureProxyFailed 1 1 -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res pos1 pos2
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-5.5.$ThreadLevel {http with-proxy ipv6 with-auth bad-creds-provided} -constraints {needsSquidAuth} -setup {
   http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $badCreds
} -body {
    after $fetchPause

    set token [http::geturl http://www.google.com/]
    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 407 -- HttpProxy 1 1 -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res pos1 pos2
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-5.6.$ThreadLevel {https with-proxy ipv6 with-auth bad-creds-provided} -constraints {needsSquidAuth needsTls knownTwapiFullBugThreadlevelAny} -setup {
   http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $badCreds
} -body {
    after $fetchPause

    set token [http::geturl https://www.google.com/]
    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
} -result {complete ok 407 -- SecureProxyFailed 1 1 -- -1} -cleanup {
    catch {http::cleanup $token}
    unset -nocomplain token ri res pos1 pos2
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-5.7.$ThreadLevel {http with-proxy ipv4 with-auth bad-creds-provided; check that 2nd request is possible} -constraints {needsSquidAuth} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $badCreds
    after $fetchPause
    set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000]
} -body {
    after $fetchPause

    # Use the same caution as for the corresponding https test.
    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 407 -- HttpProxy 1 1 -- -1 done 1} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-5.7p.$ThreadLevel {http with-proxy ipv4 with-auth bad-creds-provided; check that 2nd request is possible, pipelining requested and possible} -constraints {needsSquidAuth} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $badCreds
} -body {
    after $fetchPause

    set can0 [after 6000 {http::reset $token0; set ${token0}(z) timeout}]
    set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    # Use the same caution as for the corresponding https test.
after idle {
    after $fetchPause

    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can
}
    vwait ${token0}(z)
    after cancel $can0

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 407 -- HttpProxy 1 1 -- -1 done 1} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can0 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-5.8.$ThreadLevel {https with-proxy ipv4 with-auth bad-creds-provided; check that 2nd request is possible} -constraints {needsSquidAuth needsTls knownTwapiFullBugThreadlevelAny} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $badCreds
    after $fetchPause
    set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000]
} -body {
    after $fetchPause

    # If a bug passes the socket of a failed CONNECT to the main request, an infinite
    # wait can occur despite -timeout.  Fix this with http::reset; to do this the call
    # to http::geturl must be async so we have $token for use as argument of reset.
    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 407 -- SecureProxyFailed 1 1 -- -1 done 0} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-5.8p.$ThreadLevel {https with-proxy ipv4 with-auth bad-creds-provided; check that 2nd request is possible, pipelining requested but not possible} -constraints {needsSquidAuth needsTls knownTwapiFullBugThreadlevelAny} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $badCreds
} -body {
    after $fetchPause

    set can0 [after 6000 {http::reset $token0; set ${token0}(z) timeout}]
    set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    # If a bug passes the socket of a failed CONNECT to the main request, an infinite
    # wait can occur despite -timeout.  Fix this with http::reset; to do this the call
    # to http::geturl must be async so we have $token for use as argument of reset.
after idle {
    after $fetchPause

    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can
}
    vwait ${token0}(z)
    after cancel $can0

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 407 -- SecureProxyFailed 1 1 -- -1 done 0} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can0 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-5.9.$ThreadLevel {http with-proxy ipv6 with-auth bad-creds-provided; check that 2nd request is possible} -constraints {needsSquidAuth} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $badCreds
    after $fetchPause
    set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000]
} -body {
    after $fetchPause

    # Use the same caution as for the corresponding https test.
    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 407 -- HttpProxy 1 1 -- -1 done 1} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

test httpProxy-5.10.$ThreadLevel {https with-proxy ipv6 with-auth bad-creds-provided; check that 2nd request is possible} -constraints {needsSquidAuth needsTls knownTwapiFullBugThreadlevelAny} -setup {
    array unset ::http::socketMapping
    http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $badCreds
    after $fetchPause
    set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000]
} -body {
    after $fetchPause

    # If a bug passes the socket of a failed CONNECT to the main request, an infinite
    # wait can occur despite -timeout.  Fix this with http::reset; to do this the call
    # to http::geturl must be async so we have $token for use as argument of reset.
    set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
    set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
    vwait ${token}(z)
    after cancel $can

    set ri [http::responseInfo $token]
    set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
    set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
    set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
    set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
	     [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
	     [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
} -result {complete ok 407 -- SecureProxyFailed 1 1 -- -1 done 0} -cleanup {
    catch {http::cleanup $token0}
    catch {http::cleanup $token}
    unset -nocomplain token0 token ri res pos1 pos2 can same
    array unset ::http::socketMapping
    http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}

# cleanup
unset -nocomplain n4host n6host n4port n6port a4host a6host a4port a6port aliceCreds badCreds fetchPause

rename bgerror {}
rename stopMe {}

if {[testConstraint ThreadLevelSummary]} {
    putsBlurb
    ::tcltest::cleanupTests
    rename putsBlurb {}
}

# Local variables:
# mode: tcl
# End:

Added tests/httpProxySquidConfigForEL8.tar.gz.

cannot compute difference between binary files

Added tests/httpProxySquidConfigForWindowsDiladele.zip.

cannot compute difference between binary files

Changes to tests/httpTest.tcl.

1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







# httpTest.tcl
#
#	Test HTTP/1.1 concurrent requests including
#	queueing, pipelining and retries.
#
# Copyright (C) 2018 Keith Nash <kjnash@users.sourceforge.net>
# Copyright © 2018 Keith Nash <kjnash@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

# ------------------------------------------------------------------------------
# "Package" httpTest for analysis of Log output of http requests.
# ------------------------------------------------------------------------------
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
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







-
-
+
+








-
-
+
+

















-
-
+
+

-
+

















-
-
+
+

-
+

-
+

-
-
-
-
+
+
+
+







#    catch {puts stdout "Start time (zero ms) is $TestStartTimeInMs"}
}

namespace eval ::httpTest {
    variable testResults {}
    variable testOptions
    array set testOptions {
        -verbose 0
        -dotted  1
	-verbose 0
	-dotted  1
    }
    # -verbose - 0 quiet 1 write to stdout 2 write more
    # -dotted  - (boolean) use dots for absences in lists of transactions
}

proc httpTest::Puts {txt} {
    variable testOptions
    if {$testOptions(-verbose) > 0} {
        puts stdout $txt
        flush stdout
	puts stdout $txt
	flush stdout
    }
    return
}

# http::Log
#
# A special-purpose logger used for running tests.
# - Processes Log calls that have "^" in their arguments, and records them in
#   variable ::httpTest::testResults.
# - Also writes them to stdout (using Puts) if ($testOptions(-verbose) > 0).
# - Also writes Log calls that do not have "^", if ($testOptions(-verbose) > 1).

proc http::Log {args} {
    variable TestStartTimeInMs
    set time [expr {[clock milliseconds] - $TestStartTimeInMs}]
    set txt [list $time {*}$args]
    if {[string first ^ $txt] >= 0} {
        ::httpTest::LogRecord $txt
        ::httpTest::Puts $txt
	::httpTest::LogRecord $txt
	::httpTest::Puts $txt
    } elseif {$::httpTest::testOptions(-verbose) > 1} {
        ::httpTest::Puts $txt
	::httpTest::Puts $txt
    }
    return
}
# The http::Log routine above needs the variable ::httpTest::testOptions
# Set up to destroy it when that variable goes away.
trace add variable ::httpTest::testOptions unset {apply {args {
    proc ::http::Log args {}
}}}

# Called by http::Log (the "testing" version) to record logs for later analysis.

proc httpTest::LogRecord {txt} {
    variable testResults

    set pos [string first ^ $txt]
    set len [string length  $txt]
    if {$pos > $len - 3} {
        puts stdout "Logging Error: $txt"
        puts stdout "Fix this call to Log in http-*.tm so it has ^ then\
	puts stdout "Logging Error: $txt"
	puts stdout "Fix this call to Log in http-*.tm so it has ^ then\
		a letter then a numeral."
        flush stdout
	flush stdout
    } elseif {$pos < 0} {
        # Called by mistake.
	# Called by mistake.
    } else {
        set letter [string index $txt [incr pos]]
        set number [string index $txt [incr pos]]
        # Max 9 requests!
        lappend testResults [list $letter $number]
	set letter [string index $txt [incr pos]]
	set number [string index $txt [incr pos]]
	# Max 9 requests!
	lappend testResults [list $letter $number]
    }

    return
}


# ------------------------------------------------------------------------------
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
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







-
-
-
-
-
+
+
+
+
+

-
-
+
+


-
+









-
+








-
+








-
+







proc httpTest::TestOverlaps {someResults n term msg badTrans notPiped} {
    variable testOptions

    # Check whether transactions overlap:
    set clean {}
    set dirty {}
    for {set i 1} {$i <= $n} {incr i} {
        if {$i in $badTrans} {
            continue
        }
        set myStart   [lsearch -exact $someResults [list B $i]]
        set myEnd     [lsearch -exact $someResults [list $term $i]]
	if {$i in $badTrans} {
	    continue
	}
	set myStart   [lsearch -exact $someResults [list B $i]]
	set myEnd     [lsearch -exact $someResults [list $term $i]]

        if {($myStart < 0 || $myEnd < 0)} {
            set res "Cannot find positions of transaction $i"
	if {($myStart < 0 || $myEnd < 0)} {
	    set res "Cannot find positions of transaction $i"
	    append msg $res \n
	    Puts $res
        }
	}

	set overlaps {}
	for {set j $myStart} {$j <= $myEnd} {incr j} {
	    lassign [lindex $someResults $j] letter number
	    if {$number != $i && $letter ne "A" && $number ni $notPiped} {
		lappend overlaps $number
	    }
	}

        if {[llength $overlaps] == 0} {
	if {[llength $overlaps] == 0} {
	    set res "Transaction $i has no overlaps"
	    Puts $res
	    lappend clean $i
	    if {$testOptions(-dotted)} {
		# N.B. results from different segments are concatenated.
		lappend dirty .
	    } else {
	    }
        } else {
	} else {
	    set res "Transaction $i overlaps with [join $overlaps { }]"
	    Puts $res
	    lappend dirty $i
	    if {$testOptions(-dotted)} {
		# N.B. results from different segments are concatenated.
		lappend clean .
	    } else {
	    }
        }
	}
    }
    return [list $msg $clean $dirty]
}

# httpTest::PipelineNext --
#
# Test whether prevPair, pair are valid as consecutive elements of a pipelined
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
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







-
+







-
+


-
+

















-
-
-
-
+
+
+
+


-
-
-
+
+
+



-
-
-
+
+
+














-
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+


-
-
+
+


-
-
-
+
+
+


-
-
+
+







# any          - (boolean) iff true, accept any increasing sequence of integers.
#                If false, integers must increase by 1.
#
# Return value - boolean, true iff the two pairs are valid consecutive elements.

proc httpTest::PipelineNext {Start End prevPair pair any} {
    if {$prevPair eq {}} {
        return 1
	return 1
    }

    lassign $prevPair letter number
    lassign $pair newLetter newNumber
    if {$letter eq $Start} {
	return [expr {($newLetter eq $End) && ($newNumber == $number)}]
    } elseif {$any} {
        set nxt [list $Start [expr {$number + 1}]]
	set nxt [list $Start [expr {$number + 1}]]
	return [expr {($newLetter eq $Start) && ($newNumber > $number)}]
    } else {
        set nxt [list $Start [expr {$number + 1}]]
	set nxt [list $Start [expr {$number + 1}]]
	return [expr {($newLetter eq $Start) && ($newNumber == $number + 1)}]
    }
}

# httpTest::TestPipeline --
#
# Given a sequence of "pair" elements, check that the elements whose string is
# $Start or $End form a valid pipeline. Ignore other elements.
#
# Return value: {} if valid pipeline, otherwise a non-empty error message.

proc httpTest::TestPipeline {someResults n Start End msg desc badTrans} {
    set sequence {}
    set prevPair {}
    set ok 1
    set any [llength $badTrans]
    foreach pair $someResults {
        lassign $pair letter number
        if {($letter in [list $Start $End]) && ($number ni $badTrans)} {
            lappend sequence $pair
            if {![PipelineNext $Start $End $prevPair $pair $any]} {
	lassign $pair letter number
	if {($letter in [list $Start $End]) && ($number ni $badTrans)} {
	    lappend sequence $pair
	    if {![PipelineNext $Start $End $prevPair $pair $any]} {
		set ok 0
		break
            }
            set prevPair $pair
        }
	    }
	    set prevPair $pair
	}
    }

    if {!$ok} {
        set res "$desc are not pipelined: {$sequence}"
        append msg $res \n
        Puts $res
	set res "$desc are not pipelined: {$sequence}"
	append msg $res \n
	Puts $res
    }
    return $msg
}

# httpTest::TestSequence --
#
# Examine each transaction from 1 to $n, ignoring any that are listed
# in $badTrans.
# Check that each transaction has elements A to F, in alphabetical order.

proc httpTest::TestSequence {someResults n msg badTrans} {
    variable testOptions

    for {set i 1} {$i <= $n} {incr i} {
        if {$i in $badTrans} {
	if {$i in $badTrans} {
	    continue
        }
        set sequence {}
        foreach pair $someResults {
            lassign $pair letter number
            if {$number == $i} {
                lappend sequence $letter
            }
        }
        if {$sequence eq {A B C D E F}} {
        } else {
            set res "Wrong sequence for token ::http::$i - {$sequence}"
	}
	set sequence {}
	foreach pair $someResults {
	    lassign $pair letter number
	    if {$number == $i} {
		lappend sequence $letter
	    }
	}
	if {$sequence eq {A B C D E F}} {
	} else {
	    set res "Wrong sequence for token ::http::$i - {$sequence}"
	    append msg $res \n
	    Puts $res
            if {"X" in $sequence} {
                set res "- and error(s) X"
	    if {"X" in $sequence} {
		set res "- and error(s) X"
		append msg $res \n
		Puts $res
            }
            if {"Y" in $sequence} {
                set res "- and warnings(s) Y"
	    }
	    if {"Y" in $sequence} {
		set res "- and warnings(s) Y"
		append msg $res \n
		Puts $res
            }
        }
	    }
	}
    }
    return $msg
}

#
# Arguments:
# someResults  - list of elements, each a list of a letter and a number
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
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







-
+













-
-
-
+
+
+








-
+






-
+







-
+







# MostAnalysis for processing.

proc httpTest::ProcessRetries {someResults n msg skipOverlaps notIncluded notPiped} {
    variable testOptions

    set nextRetry [lsearch -glob -index 0 $someResults {[PQR]}]
    if {$nextRetry < 0} {
        return [MostAnalysis $someResults $n $msg $skipOverlaps $notIncluded $notPiped]
	return [MostAnalysis $someResults $n $msg $skipOverlaps $notIncluded $notPiped]
    }
    set badTrans $notIncluded
    set tryCount 0
    set try $nextRetry
    incr tryCount
    lassign [lindex $someResults $try] letter number
    Puts "Processing retry [lindex $someResults $try]"
    set beforeTry [lrange $someResults 0 $try-1]
    Puts [join $beforeTry \n]
    set afterTry [lrange $someResults $try+1 end]

    set dummyTry   {}
    for {set i 1} {$i <= $n} {incr i} {
        set first [lsearch -exact $beforeTry [list A $i]]
        set last  [lsearch -exact $beforeTry [list F $i]]
        if {$first < 0} {
	set first [lsearch -exact $beforeTry [list A $i]]
	set last  [lsearch -exact $beforeTry [list F $i]]
	if {$first < 0} {
	    set res "Transaction $i was not started in connection number $tryCount"
	    # So lappend it to badTrans and don't include it in the call below of MostAnalysis.
	    # append msg $res \n
	    Puts $res
	    if {$i ni $badTrans} {
		lappend badTrans $i
	    } else {
	    }
        } elseif {$last < 0} {
	} elseif {$last < 0} {
	    set res "Transaction $i was started but unfinished in connection number $tryCount"
	    # So lappend it to badTrans and don't include it in the call below of MostAnalysis.
	    # append msg $res \n
	    Puts $res
	    lappend badTrans $i
	    lappend dummyTry [list A $i]
        } else {
	} else {
	    set res "Transaction $i was started and finished in connection number $tryCount"
	    # So include it in the call below of MostAnalysis.
	    # So lappend it to notIncluded and don't include it in the recursive call of
	    # ProcessRetries which handles the later connections.
	    # append msg $res \n
	    Puts $res
	    lappend notIncluded $i
        }
	}
    }

    # Analyse the part of the results before the first replay:
    set HeadResults [MostAnalysis $beforeTry $n $msg $skipOverlaps $badTrans $notPiped]
    lassign $HeadResults msg cleanE1 cleanF1 dirtyE1 dirtyF1

    # Pass the rest of the results to be processed recursively.
495
496
497
498
499
500
501
502

503
504
505
506
507
508
509
495
496
497
498
499
500
501

502
503
504
505
506
507
508
509







-
+







    set testResults {}
    return
}

proc httpTest::setHttpTestOptions {key args} {
    variable testOptions
    if {$key ni {-dotted -verbose}} {
        return -code error {valid options are -dotted, -verbose}
	return -code error {valid options are -dotted, -verbose}
    }
    set testOptions($key) {*}$args
}

namespace eval httpTest {
    namespace export cleanupHttpTest logAnalyse setHttpTestOptions
}

Changes to tests/httpTestScript.tcl.

1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







# httpTestScript.tcl
#
#	Test HTTP/1.1 concurrent requests including
#	queueing, pipelining and retries.
#
# Copyright (C) 2018 Keith Nash <kjnash@users.sourceforge.net>
# Copyright © 2018 Keith Nash <kjnash@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

# ------------------------------------------------------------------------------
# "Package" httpTestScript for executing test scripts written in a convenient
# shorthand.
98
99
100
101
102
103
104
105
106


107
108
109
110
111
112
113
98
99
100
101
102
103
104


105
106
107
108
109
110
111
112
113







-
-
+
+







    variable CountFinishedSoFar
    variable RequestList
    variable RequestsMade
    variable ExtraTime
    variable ActualKeepAlive

    if {[info exists StartDone] && ($StartDone == 1)} {
        set msg {START has been called twice without an intervening STOP}
        return -code error $msg
	set msg {START has been called twice without an intervening STOP}
	return -code error $msg
    }

    set StartDone 1
    set StopDone 0
    set TimeOutDone 0
    set CountFinishedSoFar 0
    set CountRequestedSoFar 0
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
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







-
-
+
+



-
+








-
-
-
-
+
+
+
+













-
+



-
+
















-
+



-
+
















-
+



-
+



-
+















-
+



-
+















-
+



-
+















-
+



-
+







    variable RequestsWhenStopped
    variable TimeOutCode
    variable StartDone
    variable StopDone
    variable RequestsMade

    if {$StopDone} {
        # Don't do anything on a second call.
        return
	# Don't do anything on a second call.
	return
    }

    if {![info exists StartDone]} {
        return -code error {initialise the script by calling command START}
	return -code error {initialise the script by calling command START}
    }

    set StopDone 1
    set StartDone 0
    set RequestsWhenStopped $CountRequestedSoFar
    unset -nocomplain StartDone

    if {$CountFinishedSoFar == $RequestsWhenStopped} {
        if {[info exists TimeOutCode]} {
            after cancel $TimeOutCode
        }
        set ::httpTestScript::FOREVER 0
	if {[info exists TimeOutCode]} {
	    after cancel $TimeOutCode
	}
	set ::httpTestScript::FOREVER 0
    }
    return
}

# httpTestScript::DELAY --
# If there are no WAIT commands, this sets the delay in ms between subsequent
# calls to http::geturl.  Default 500ms.

proc httpTestScript::DELAY {t} {
    variable StartDone
    variable StopDone

    if {$StopDone} {
        return
	return
    }

    if {![info exists StartDone]} {
        return -code error {initialise the script by calling command START}
	return -code error {initialise the script by calling command START}
    }

    variable Delay

    set Delay $t
    return
}

# httpTestScript::KEEPALIVE --
# Set the value passed to http::geturl for the -keepalive option.  Default 1.

proc httpTestScript::KEEPALIVE {b} {
    variable StartDone
    variable StopDone

    if {$StopDone} {
        return
	return
    }

    if {![info exists StartDone]} {
        return -code error {initialise the script by calling command START}
	return -code error {initialise the script by calling command START}
    }

    variable KeepAlive
    set KeepAlive $b
    return
}

# httpTestScript::WAIT --
# Pause for a time in ms before processing any more commands.

proc httpTestScript::WAIT {t} {
    variable StartDone
    variable StopDone
    variable ExtraTime

    if {$StopDone} {
        return
	return
    }

    if {![info exists StartDone]} {
        return -code error {initialise the script by calling command START}
	return -code error {initialise the script by calling command START}
    }

    if {(![string is integer -strict $t]) || $t < 0} {
        return -code error {argument to WAIT must be a non-negative integer}
	return -code error {argument to WAIT must be a non-negative integer}
    }

    incr ExtraTime $t

    return
}

# httpTestScript::PIPELINE --
# Pass a value to http::config -pipeline.

proc httpTestScript::PIPELINE {b} {
    variable StartDone
    variable StopDone

    if {$StopDone} {
        return
	return
    }

    if {![info exists StartDone]} {
        return -code error {initialise the script by calling command START}
	return -code error {initialise the script by calling command START}
    }

    ::http::config -pipeline $b
    ##::http::Log http(-pipeline) is now [::http::config -pipeline]
    return
}

# httpTestScript::POSTFRESH --
# Pass a value to http::config -postfresh.

proc httpTestScript::POSTFRESH {b} {
    variable StartDone
    variable StopDone

    if {$StopDone} {
        return
	return
    }

    if {![info exists StartDone]} {
        return -code error {initialise the script by calling command START}
	return -code error {initialise the script by calling command START}
    }

    ::http::config -postfresh $b
    ##::http::Log http(-postfresh) is now [::http::config -postfresh]
    return
}

# httpTestScript::REPOST --
# Pass a value to http::config -repost.

proc httpTestScript::REPOST {b} {
    variable StartDone
    variable StopDone

    if {$StopDone} {
        return
	return
    }

    if {![info exists StartDone]} {
        return -code error {initialise the script by calling command START}
	return -code error {initialise the script by calling command START}
    }

    ::http::config -repost $b
    ##::http::Log http(-repost) is now [::http::config -repost]
    return
}

343
344
345
346
347
348
349
350

351
352
353
354

355
356
357
358
359
360
361
343
344
345
346
347
348
349

350
351
352
353

354
355
356
357
358
359
360
361







-
+



-
+







    variable Delay
    variable ExtraTime
    variable StartDone
    variable StopDone
    variable KeepAlive

    if {$StopDone} {
        return
	return
    }

    if {![info exists StartDone]} {
        return -code error {initialise the script by calling command START}
	return -code error {initialise the script by calling command START}
    }

    incr CountRequestedSoFar
    set idelay [expr {($CountRequestedSoFar - 1) * $Delay + 10 + $ExtraTime}]

    # Could pass values of -pipeline, -postfresh, -repost if it were
    # useful to change these mid-script.
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
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







-
+





-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
+
+
+

-
+







    set absUrl $URL($uriCode)
    if {$query eq {}} {
	if {$args ne {}} {
	    append absUrl & [join $args &]
	}
	set queryArgs {}
    } elseif {$validate} {
        return -code error {cannot have both -validate (HEAD) and -query (POST)}
	return -code error {cannot have both -validate (HEAD) and -query (POST)}
    } else {
	set queryArgs [list -query [join $args &]]
    }

    if {[catch {
        ::http::geturl     $absUrl        \
                -validate  $validate      \
                -timeout   10000          \
                {*}$queryArgs             \
                -keepalive $keepAlive     \
                -command   ::httpTestScript::WhenFinished
	::http::geturl     $absUrl        \
		-validate  $validate      \
		-timeout   10000          \
		{*}$queryArgs             \
		-keepalive $keepAlive     \
		-command   ::httpTestScript::WhenFinished
    } token]} {
        set msg $token
        catch {puts stdout "Error: $msg"}
        return
	set msg $token
	catch {puts stdout "Error: $msg"}
	return
    } else {
        # Request will begin.
	# Request will begin.
    }

    return

}

proc httpTestScript::TimeOutNow {} {
459
460
461
462
463
464
465
466
467
468
469




470
471
472


473
474
475
476
477
478
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
459
460
461
462
463
464
465




466
467
468
469
470


471
472
473
474
475
476
477
478
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







-
-
-
-
+
+
+
+

-
-
+
+
















-
+















-
+




	}
    } err]} {
	::http::Log ^X$tk httpTestScript::WhenFinished failed with error status: $err - token $hToken
    }

    incr CountFinishedSoFar
    if {$StopDone && ($CountFinishedSoFar == $RequestsWhenStopped)} {
        if {[info exists TimeOutCode]} {
            after cancel $TimeOutCode
        }
        if {$RequestsMade ne $RequestList && $ActualKeepAlive} {
	if {[info exists TimeOutCode]} {
	    after cancel $TimeOutCode
	}
	if {$RequestsMade ne $RequestList && $ActualKeepAlive} {
	    ::http::Log ^X$tk unexpected result - Script asked for "{$RequestList}" but got "{$RequestsMade}" - token $hToken
        }
        set ::httpTestScript::FOREVER 0
	}
	set ::httpTestScript::FOREVER 0
    }

    return
}


proc httpTestScript::runHttpTestScript {scr} {
    variable TimeOutDone
    variable RequestsWhenStopped

    after idle [list namespace eval ::httpTestScript $scr]
    vwait ::httpTestScript::FOREVER
    # N.B. does not automatically execute in this namespace, unlike some other events.
    # Release when all requests have been served or have timed out.

    if {$TimeOutDone} {
        return -code error {test script timed out}
	return -code error {test script timed out}
    }

    return $RequestsWhenStopped
}


proc httpTestScript::cleanupHttpTestScript {} {
    variable TimeOutDone
    variable RequestsWhenStopped

    if {![info exists RequestsWhenStopped]} {
	return -code error {Cleanup Failed: RequestsWhenStopped is undefined}
    }

    for {set i 1} {$i <= $RequestsWhenStopped} {incr i} {
        http::cleanup ::http::$i
	http::cleanup ::http::$i
    }

    return
}

Changes to tests/httpcookie.test.

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
30
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






-
+











-
+
-
-
-
-
+







# Commands covered:  http::cookiejar
#
# This file contains a collection of tests for the cookiejar package.
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2014 Donal K. Fellows.
# Copyright © 2014 Donal K. Fellows.
#
# 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

testConstraint notOSXtravis [apply {{} {
testConstraint notMacCI [expr {![info exists ::env(MAC_CI)]}]
    upvar 1 env(TRAVIS_OSX_IMAGE) travis
    return [expr {![info exists travis] || ![string match xcode* $travis]}]
}}]
testConstraint sqlite3 [expr {[testConstraint notOSXtravis] && ![catch {
testConstraint sqlite3 [expr {[testConstraint notMacCI] && ![catch {
    package require sqlite3
}]}]
testConstraint cookiejar [expr {[testConstraint sqlite3] && ![catch {
    package require cookiejar
}]}]

set COOKIEJAR_VERSION 0.2.0

Changes to tests/httpd.

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
1
2
3
4


5
6
7
8
9
10
11
12



13
14
15
16



17
18
19
20
21
22
23




-
-
+
+






-
-
-
+
+
+
+
-
-
-







# -*- tcl -*-
#
# The httpd_ procedures implement a stub http server.
#
# Copyright (c) 1997-1998 Sun Microsystems, Inc.
# Copyright (c) 1999-2000 Scriptics Corporation
# Copyright © 1997-1998 Sun Microsystems, Inc.
# Copyright © 1999-2000 Scriptics Corporation
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

#set httpLog 1

if {$::tcl_platform(os) eq "Darwin"} {
    # Name resolution often a problem on OSX; not focus of HTTP package anyway
    set HOST localhost
# Do not use [info hostname].
# Name resolution is often a problem on OSX; not focus of HTTP package anyway.
# Also a problem on other platforms for http-4.14 (test with bad port number).
set HOST localhost
} else {
    set HOST [info hostname]
}

proc httpd_init {{port 8015}} {
    set s [socket -server httpdAccept $port]
    # Save the actual port number in a global variable.
    # This is important when we're called with port 0
    # for picking an unused port at random.
    set ::port [lindex [chan configure $s -sockname] 2]
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
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







-
+


















+
+
+
+











-
-
-
+
+
+







proc httpdAccept {newsock ipaddr port} {
    global httpd
    upvar #0 httpd$newsock data

    fconfigure $newsock -blocking 0 -translation {auto crlf}
    httpd_log $newsock Connect $ipaddr $port
    set data(ipaddr) $ipaddr
    after 50 [list fileevent $newsock readable [list httpdRead $newsock]]
    fileevent $newsock readable [list httpdRead $newsock]
}

# read data from a client request

proc httpdRead { sock } {
    upvar #0 httpd$sock data

    if {[eof $sock]} {
	set readCount -1
    } elseif {![info exists data(state)]} {

	# Read the protocol line and parse out the URL and query

	set readCount [gets $sock line]
	if {[regexp {(POST|GET|HEAD) ([^?]+)\??([^ ]*) HTTP/(1.[01])} $line \
		-> data(proto) data(url) data(query) data(httpversion)]} {
	    set data(state) mime
	    httpd_log $sock Query $line
	    if {[regexp {(?:^|[\?&])delay=([^&]+)} $data(query) {} val]} {
		fileevent $sock readable {}
		after $val [list fileevent $sock readable [list httpdRead $sock]]
	    }
	} else {
	    httpdError $sock 400
	    httpd_log $sock Error "bad first line:$line"
	    httpdSockDone $sock
	}
	return
    } elseif {$data(state) == "mime"} {

	# Read the HTTP headers

	set readCount [gets $sock line]
        if {[regexp {^([^:]+):(.*)$} $line -> key val]} {
            lappend data(meta) $key [string trim $val]
        }
	if {[regexp {^([^:]+):(.*)$} $line -> key val]} {
	    lappend data(meta) $key [string trim $val]
	}

    } elseif {$data(state) == "query"} {

	# Read the query data

	if {![info exists data(length_orig)]} {
	    set data(length_orig) $data(length)
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
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







-
+

-
-
+
+


-
+


-
-
-
-
-
+
+
+
+
+











    # Catch errors from premature client closes

    catch {
	if {$data(proto) == "HEAD"} {
	    puts $sock "HTTP/1.0 200 OK"
	} else {
            # Split the response to test for [Bug 26245326]
	    # Split the response to test for [Bug 26245326]
	    puts -nonewline $sock "HT"
            flush $sock
            puts $sock "TP/1.0 200 Data follows"
	    flush $sock
	    puts $sock "TP/1.0 200 Data follows"
	}
	puts $sock "Date: [clock format [clock seconds] \
                              -format {%a, %d %b %Y %H:%M:%S %Z}]"
			      -format {%a, %d %b %Y %H:%M:%S %Z}]"
	puts $sock "Content-Type: $type"
	puts $sock "Content-Length: [string length $html]"
        foreach {key val} $data(meta) {
            if {[string match "X-*" $key]} {
                puts $sock "$key: $val"
            }
        }
	foreach {key val} $data(meta) {
	    if {[string match "X-*" $key]} {
		puts $sock "$key: $val"
	    }
	}
	puts $sock ""
	flush $sock
	if {$data(proto) != "HEAD"} {
	    fconfigure $sock -translation binary
	    puts -nonewline $sock $html
	}
    }
    httpd_log $sock Done ""
    httpdSockDone $sock
}

Changes to tests/httpd11.tcl.

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
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
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
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





-
+




-
+



-
+










-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+








-
-
-
+
+
+



-
+

-
+






-
-
-
+
+
+


-
+

-
+






-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+









-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+


+
+
+
+
+
+





-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+










-
-
-
+
+
+


-
+







# httpd11.tcl --                                                -*- tcl -*-
#
#	A simple httpd for testing HTTP/1.1 client features.
#	Not suitable for use on a internet connected port.
#
# Copyright (C) 2009 Pat Thoyts <patthoyts@users.sourceforge.net>
# Copyright © 2009 Pat Thoyts <patthoyts@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require Tcl 8.6-
package require Tcl

proc ::tcl::dict::get? {dict key} {
    if {[dict exists $dict $key]} {
        return [dict get $dict $key]
	return [dict get $dict $key]
    }
    return
}
namespace ensemble configure dict \
    -map [linsert [namespace ensemble configure dict -map] end get? ::tcl::dict::get?]

proc make-chunk-generator {data {size 4096}} {
    variable _chunk_gen_uid
    if {![info exists _chunk_gen_uid]} {set _chunk_gen_uid 0}
    set lambda {{data size} {
        set pos 0
        yield
        while {1} {
            set payload [string range $data $pos [expr {$pos + $size - 1}]]
            incr pos $size
            set chunk [format %x [string length $payload]]\r\n$payload\r\n
            yield $chunk
            if {![string length $payload]} {return}
        }
	set pos 0
	yield
	while {1} {
	    set payload [string range $data $pos [expr {$pos + $size - 1}]]
	    incr pos $size
	    set chunk [format %x [string length $payload]]\r\n$payload\r\n
	    yield $chunk
	    if {![string length $payload]} {return}
	}
    }}
    set name chunker[incr _chunk_gen_uid]
    coroutine $name ::apply $lambda $data $size
    return $name
}

proc get-chunks {data {compression gzip}} {
    switch -exact -- $compression {
        gzip     { set data [zlib gzip $data] }
        deflate  { set data [zlib deflate $data] }
        compress { set data [zlib compress $data] }
	gzip     { set data [zlib gzip $data] }
	deflate  { set data [zlib deflate $data] }
	compress { set data [zlib compress $data] }
    }

    set data ""
    set chunker [make-chunk-generator $data 512]
    set chunker [make-chunk-generator $data 671]
    while {[string length [set chunk [$chunker]]]} {
        append data $chunk
	append data $chunk
    }
    return $data
}

proc blow-chunks {data {ochan stdout} {compression gzip}} {
    switch -exact -- $compression {
        gzip     { set data [zlib gzip $data] }
        deflate  { set data [zlib deflate $data] }
        compress { set data [zlib compress $data] }
	gzip     { set data [zlib gzip $data] }
	deflate  { set data [zlib deflate $data] }
	compress { set data [zlib compress $data] }
    }

    set chunker [make-chunk-generator $data 512]
    set chunker [make-chunk-generator $data 671]
    while {[string length [set chunk [$chunker]]]} {
        puts -nonewline $ochan $chunk
	puts -nonewline $ochan $chunk
    }
    return
}

proc mime-type {filename} {
    switch -exact -- [file extension $filename] {
        .htm - .html { return {text text/html}}
        .png { return {binary image/png} }
        .jpg { return {binary image/jpeg} }
        .gif { return {binary image/gif} }
        .css { return {text   text/css} }
        .xml { return {text   text/xml} }
        .xhtml {return {text  application/xml+html} }
        .svg { return {text image/svg+xml} }
        .txt - .tcl - .c - .h { return {text text/plain}}
	.htm - .html { return {text text/html}}
	.png { return {binary image/png} }
	.jpg { return {binary image/jpeg} }
	.gif { return {binary image/gif} }
	.css { return {text   text/css} }
	.xml { return {text   text/xml} }
	.xhtml {return {text  application/xml+html} }
	.svg { return {text image/svg+xml} }
	.txt - .tcl - .c - .h { return {text text/plain}}
    }
    return {binary text/plain}
}

proc Puts {chan s} {puts $chan $s; puts $s}

proc Service {chan addr port} {
    chan event $chan readable [info coroutine]
    while {1} {
        set meta {}
        chan configure $chan -buffering line -encoding iso8859-1 -translation crlf
        chan configure $chan -blocking 0
        yield
        while {[gets $chan line] < 0} {
            if {[eof $chan]} {chan event $chan readable {}; close $chan; return}
            yield
        }
        if {[eof $chan]} {chan event $chan readable {}; close $chan; return}
        foreach {req url protocol} {GET {} HTTP/1.1} break
        regexp {^(\S+)\s+(.*)\s(\S+)?$} $line -> req url protocol
	set meta {}
	chan configure $chan -buffering line -encoding iso8859-1 -translation crlf
	chan configure $chan -blocking 0
	yield
	while {[gets $chan line] < 0} {
	    if {[eof $chan]} {chan event $chan readable {}; close $chan; return}
	    yield
	}
	if {[eof $chan]} {chan event $chan readable {}; close $chan; return}
	foreach {req url protocol} {GET {} HTTP/1.1} break
	regexp {^(\S+)\s+(.*)\s(\S+)?$} $line -> req url protocol

        puts $line
        while {[gets $chan line] > 0} {
            if {[regexp {^([^:]+):(.*)$} $line -> key val]} {
                puts [list $key [string trim $val]]
                lappend meta [string tolower $key] [string trim $val]
            }
            yield
        }
	puts $line
	while {[gets $chan line] > 0} {
	    if {[regexp {^([^:]+):(.*)$} $line -> key val]} {
		puts [list $key [string trim $val]]
		lappend meta [string tolower $key] [string trim $val]
	    }
	    yield
	}

        set encoding identity
        set transfer ""
        set close 1
        set type text/html
        set code "404 Not Found"
        set data "<html><head><title>Error 404</title></head>"
        append data "<body><h1>Not Found</h1><p>Try again.</p></body></html>"
	set encoding identity
	set transfer ""
	set close 1
	set type text/html
	set code "404 Not Found"
	set data "<html><head><title>Error 404</title></head>"
	append data "<body><h1>Not Found</h1><p>Try again.</p></body></html>"

        if {[scan $url {%[^?]?%s} path query] < 2} {
            set query ""
        }
	if {[scan $url {%[^?]?%s} path query] < 2} {
	    set query ""
	}

        switch -exact -- $req {
            GET - HEAD {
            }
            POST {
                # Read the query.
                set qlen [dict get? $meta content-length]
                if {[string is integer -strict $qlen]} {
                    chan configure $chan -buffering none -translation binary
                    while {[string length $query] < $qlen} {
                        append query [read $chan $qlen]
                        if {[string length $query] < $qlen} {yield}
                    }
                    # Check for excess query bytes [Bug 2715421]
                    if {[dict get? $meta x-check-query] eq "yes"} {
                        chan configure $chan -blocking 0
                        append query [read $chan]
                    }
                }
            }
            default {
                # invalid request error 5??
            }
        }
        if {$query ne ""} {puts $query}
	switch -exact -- $req {
	    GET - HEAD {
	    }
	    POST {
		# Read the query.
		set qlen [dict get? $meta content-length]
		if {[string is integer -strict $qlen]} {
		    chan configure $chan -buffering none -translation binary
		    while {[string length $query] < $qlen} {
			append query [read $chan $qlen]
			if {[string length $query] < $qlen} {yield}
		    }
		    # Check for excess query bytes [Bug 2715421]
		    if {[dict get? $meta x-check-query] eq "yes"} {
			chan configure $chan -blocking 0
			append query [read $chan]
		    }
		}
	    }
	    default {
		# invalid request error 5??
	    }
	}
	if {$query ne ""} {puts $query}

        set path [string trimleft $path /]
        set path [file join [pwd] $path]
        if {[file exists $path] && [file isfile $path]} {
            foreach {what type} [mime-type $path] break
            set f [open $path r]
            if {$what eq "binary"} {chan configure $f -translation binary}
            set data [read $f]
            close $f
            set code "200 OK"
            set close [expr {[dict get? $meta connection] eq "close"}]
        }
	set path [string trimleft $path /]
	set path [file join [pwd] $path]
	if {[file exists $path] && [file isfile $path]} {
	    foreach {what type} [mime-type $path] break
	    set f [open $path r]
	    if {$what eq "binary"} {
		chan configure $f -translation binary
	    } else {
		chan configure $f -encoding utf-8
	    }
	    set data [read $f]
	    close $f
	    set code "200 OK"
	    set close [expr {[dict get? $meta connection] eq "close"}]
	}

        if {$protocol eq "HTTP/1.1"} {
	if {$protocol eq "HTTP/1.1"} {
	    foreach enc [split [dict get? $meta accept-encoding] ,] {
		set enc [string trim $enc]
		# The current implementation of "compress" appears to be
		# incorrect (bug [a13b9d0ce1]).  Keep it here for
		# experimentation only.  The tests that use it have the
		# constraint "badCompress".  The client code in http has
		# been removed, but can be restored from comments if
		# experimentation is desired.
		if {$enc in {deflate gzip compress}} {
		    set encoding $enc
		    break
		}
	    }
            set transfer chunked
        } else {
            set close 1
        }
	    set transfer chunked
	} else {
	    set close 1
	}

        set nosendclose 0
        foreach pair [split $query &] {
            if {[scan $pair {%[^=]=%s} key val] != 2} {set val ""}
            switch -exact -- $key {
                nosendclose  {set nosendclose 1}
                close        {set close 1 ; set transfer 0}
                transfer     {set transfer $val}
                content-type {set type $val}
            }
        }
        if {$protocol eq "HTTP/1.1"} {
            set nosendclose 0
        }
	set nosendclose 0
	set msdeflate 0
	foreach pair [split $query &] {
	    if {[scan $pair {%[^=]=%s} key val] != 2} {set val ""}
	    switch -exact -- $key {
		nosendclose  {set nosendclose 1}
		close        {set close 1 ; set transfer 0}
		transfer     {set transfer $val}
		content-type {set type $val}
		msdeflate    {set msdeflate $val}
	    }
	}
	if {$protocol eq "HTTP/1.1"} {
	    set nosendclose 0
	}

        chan configure $chan -buffering line -encoding iso8859-1 -translation crlf
        Puts $chan "$protocol $code"
        Puts $chan "content-type: $type"
        Puts $chan [format "x-crc32: %08x" [zlib crc32 $data]]
        if {$req eq "POST"} {
            Puts $chan [format "x-query-length: %d" [string length $query]]
        }
        if {$close && (!$nosendclose)} {
            Puts $chan "connection: close"
        }
	chan configure $chan -buffering line -encoding iso8859-1 -translation crlf
	Puts $chan "$protocol $code"
	Puts $chan "content-type: $type"
	Puts $chan [format "x-crc32: %08x" [zlib crc32 $data]]
	if {$req eq "POST"} {
	    Puts $chan [format "x-query-length: %d" [string length $query]]
	}
	if {$close && (!$nosendclose)} {
	    Puts $chan "connection: close"
	}
	Puts $chan "x-requested-encodings: [dict get? $meta accept-encoding]"
        if {$encoding eq "identity" && (!$nosendclose)} {
            Puts $chan "content-length: [string length $data]"
        } elseif {$encoding eq "identity"} {
            # This is a blatant attempt to confuse the client by sending neither
            # "Connection: close" nor "Content-Length" when in non-chunked mode.
            # See test http11-3.4.
        } else {
            Puts $chan "content-encoding: $encoding"
        }
        if {$transfer eq "chunked"} {
            Puts $chan "transfer-encoding: chunked"
        }
        puts $chan ""
        flush $chan
	if {$encoding eq "identity" && (!$nosendclose)} {
	    Puts $chan "content-length: [string length $data]"
	} elseif {$encoding eq "identity"} {
	    # This is a blatant attempt to confuse the client by sending neither
	    # "Connection: close" nor "Content-Length" when in non-chunked mode.
	    # See test http11-3.4.
	} else {
	    Puts $chan "content-encoding: $encoding"
	}
	if {$transfer eq "chunked"} {
	    Puts $chan "transfer-encoding: chunked"
	}
	puts $chan ""
	flush $chan

        chan configure $chan -buffering full -translation binary
        if {$transfer eq "chunked"} {
            blow-chunks $data $chan $encoding
        } elseif {$encoding ne "identity"} {
            puts -nonewline $chan [zlib $encoding $data]
        } else {
            puts -nonewline $chan $data
        }
	chan configure $chan -buffering full -translation binary
	if {$encoding eq {deflate}} {
	    # When http.tcl uses the correct decoder (bug [a13b9d0ce1]) for
	    # "accept-encoding deflate", i.e. "zlib decompress", this choice of
	    # encoding2 allows the tests to pass.  It appears to do "deflate"
	    # correctly, but this has not been verified with a non-Tcl client.
	    set encoding2 compress
	} else {
	    set encoding2 $encoding
	}
	if {$transfer eq "chunked"} {
	    blow-chunks $data $chan $encoding2
	} elseif {$encoding2 ne "identity" && $msdeflate eq {1}} {
	    puts -nonewline $chan [string range [zlib $encoding2 $data] 2 end-4]
	    # Used in some tests of "deflate" to produce the non-RFC-compliant
	    # Microsoft version of "deflate".
	} elseif {$encoding2 ne "identity"} {
	    puts -nonewline $chan [zlib $encoding2 $data]
	} else {
	    puts -nonewline $chan $data
	}

        if {$close} {
            chan event $chan readable {}
            close $chan
            puts "close $chan"
            return
        } else {
            flush $chan
        }
        puts "pipeline $chan"
	if {$close} {
	    chan event $chan readable {}
	    close $chan
	    puts "close $chan"
	    return
	} else {
	    flush $chan
	}
	puts "pipeline $chan"
    }
}

proc Accept {chan addr port} {
    coroutine client$chan Service $chan $addr $port
    return
}

proc Control {chan} {
    if {[gets $chan line] >= 0} {
        if {[string trim $line] eq "quit"} {
            set ::forever 1
        }
	if {[string trim $line] eq "quit"} {
	    set ::forever 1
	}
    }
    if {[eof $chan]} {
        chan event $chan readable {}
	chan event $chan readable {}
    }
}

proc Main {{port 0}} {
    set server [socket -server Accept -myaddr localhost $port]
    puts [chan configure $server -sockname]
    flush stdout

Added tests/icu.test.

























































































































































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# Tests for tcl::unsupported::icu
# Contains basic sanity checks only! Commands are not intended for
# production use.

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

# Force late loading of ICU if present
catch {::tcl::unsupported::icu}
testConstraint icu [llength [info commands ::tcl::unsupported::icu::detect]]

namespace eval icu {
    namespace path {::tcl::unsupported ::tcl::mathop}

    test icu-detect-0 {Return list of ICU encodings} -constraints icu -body {
	set encoders [icu detect]
	list [in UTF-8 $encoders] [in ISO-8859-1 $encoders]
    } -result {1 1}

    test icu-detect-1 {Guess encoding} -constraints icu -body {
	icu detect [readFile [info script]]
    } -result ISO-8859-1
    test icu-detect-2 {Get all possible encodings} -constraints icu -body {
	set encodings [icu detect [readFile [info script]] -all]
	list [in UTF-8 $encodings] [in ISO-8859-1 $encodings]
    } -result {1 1}
    test icu-detect-3 {error case} -constraints icu -returnCodes error -body {
	icu detect gorp gorp gorp
    } -result {wrong # args: should be "icu detect ?bytes ?-all??"}

    test icu-tclToIcu-0 {Map Tcl encoding} -constraints icu -body {
	# tis-620 because it is ambiguous in ICU on some platforms
	# but should return the preferred encoding
	lmap enc {utf-8 tis-620 shiftjis} {
	    icu tclToIcu $enc
	}
    } -result {UTF-8 TIS-620 ibm-943_P15A-2003}
    test icu-tclToIcu-1 {Map Tcl encoding - no map} -constraints icu -body {
	# Should not raise an error
	icu tclToIcu dummy
    } -result {}
    test icu-tclToIcu-2 {error case} -constraints icu -returnCodes error -body {
	icu tclToIcu gorp gorp
    } -result {wrong # args: should be "icu tclToIcu tclName"}

    test icu-icuToTcl-0 {Map ICU encoding} -constraints icu -body {
	lmap enc {UTF-8 TIS-620 ibm-943_P15A-2003} {
	    icu icuToTcl $enc
	}
    } -result {utf-8 tis-620 cp932}
    test icu-icuToTcl-1 {Map ICU encoding - no map} -constraints icu -body {
	# Should not raise an error
	icu icuToTcl dummy
    } -result {}
    test icu-icuToTcl-2 {error case} -constraints icu -returnCodes error -body {
	icu icuToTcl gorp gorp
    } -result {wrong # args: should be "icu icuToTcl icuName"}

    ###
    # icu convertfrom syntax and arg checks
    # These tests are NOT for testing encodings, that's elsewhere.

    test icu-convertfrom-error-0 {no args} -constraints icu -body {
	icu convertfrom
    } -result {wrong # args: should be "icu convertfrom ?-profile PROFILE? ICUENCNAME STRING"} -returnCodes error

    test icu-convertfrom-error-1 {one arg} -constraints icu -body {
	icu convertfrom ASCII
    } -result {wrong # args: should be "icu convertfrom ?-profile PROFILE? ICUENCNAME STRING"} -returnCodes error

    test icu-convertfrom-error-2 {missing option value} -constraints icu -body {
	icu convertfrom -profile strict ASCII
    } -result {Missing value for option -profile.} -returnCodes error

    test icu-convertfrom-error-3 {-failindex} -constraints icu -body {
	icu convertfrom -failindex failindex ASCII abc
    } -result {Option -failindex not implemented.} -returnCodes error

    test icu-convertfrom-error-4 {extra arg} -constraints icu -body {
	icu convertfrom -profile strict extra ASCII abc
    } -result {bad option "extra": must be -profile or -failindex} -returnCodes error

    test icu-convertfrom-error-5 {invalid profile} -constraints icu -body {
	icu convertfrom -profile tcl8 ASCII abc
    } -result {Invalid value "tcl8" supplied for option "-profile". Must be "strict" or "replace".} -returnCodes error

    test icu-convertfrom-error-6 {invalid encoding} -constraints icu -body {
	icu convertfrom nosuchencoding abc
    } -result {Could not get encoding converter.*} -match glob -returnCodes error

    test icu-convertfrom-0 {default success} -constraints icu -body {
	icu convertfrom UTF-8 \xf0\x9f\x98\x80
    } -result \U1F600

    test icu-convertfrom-1 {-profile strict success} -constraints icu -body {
	icu convertfrom -profile strict UTF-8 \xf0\x9f\x98\x80
    } -result \U1F600

    test icu-convertfrom-2 {-profile replace success} -constraints icu -body {
	icu convertfrom -profile replace UTF-8 \xf0\x9f\x98\x80
    } -result \U1F600

    test icu-convertfrom-3 {default invalid encoding} -constraints icu -body {
	icu convertfrom UTF-8 \xC0\x80
    } -result {ICU error while decoding. ICU error (12): U_ILLEGAL_CHAR_FOUND} -returnCodes error

    test icu-convertfrom-4 {-profile strict invalid encoding} -constraints icu -body {
	icu convertfrom -profile strict UTF-8 \xC0\x80
    } -result {ICU error while decoding. ICU error (12): U_ILLEGAL_CHAR_FOUND} -returnCodes error

    test icu-convertfrom-5 {-profile replace invalid encoding} -constraints icu -body {
	icu convertfrom -profile replace UTF-8 \xC0\x80
    } -result \UFFFD\uFFFD

    ###
    # icu convertto syntax and arg checks
    # These tests are NOT for testing encodings, that's elsewhere.

    test icu-convertto-error-0 {no args} -constraints icu -body {
	icu convertto
    } -result {wrong # args: should be "icu convertto ?-profile PROFILE? ICUENCNAME STRING"} -returnCodes error

    test icu-convertto-error-1 {one arg} -constraints icu -body {
	icu convertto ASCII
    } -result {wrong # args: should be "icu convertto ?-profile PROFILE? ICUENCNAME STRING"} -returnCodes error

    test icu-convertto-error-2 {missing option value} -constraints icu -body {
	icu convertto -profile strict ASCII
    } -result {Missing value for option -profile.} -returnCodes error

    test icu-convertto-error-3 {-failindex} -constraints icu -body {
	icu convertto -failindex failindex ASCII abc
    } -result {Option -failindex not implemented.} -returnCodes error

    test icu-convertto-error-4 {extra arg} -constraints icu -body {
	icu convertto -profile strict extra ASCII abc
    } -result {bad option "extra": must be -profile or -failindex} -returnCodes error

    test icu-convertto-error-5 {invalid profile} -constraints icu -body {
	icu convertto -profile tcl8 ASCII abc
    } -result {Invalid value "tcl8" supplied for option "-profile". Must be "strict" or "replace".} -returnCodes error

    test icu-convertto-error-6 {invalid encoding} -constraints icu -body {
	icu convertto nosuchencoding abc
    } -result {Could not get encoding converter.*} -match glob -returnCodes error

    test icu-convertto-0 {default success} -constraints icu -body {
	icu convertto UTF-8 \U1F600
    } -result \xf0\x9f\x98\x80

    test icu-convertto-1 {-profile strict success} -constraints icu -body {
	icu convertto -profile strict UTF-8 \U1F600
    } -result \xf0\x9f\x98\x80

    test icu-convertto-2 {-profile replace success} -constraints icu -body {
	icu convertto -profile replace UTF-8 \U1F600
    } -result \xf0\x9f\x98\x80

    test icu-convertto-3 {default unencodable character} -constraints icu -body {
	icu convertto ISO-8859-2 \U1F600
    } -result {ICU error while encoding. ICU error (10): U_INVALID_CHAR_FOUND} -returnCodes error

    test icu-convertto-4 {-profile strict unencodable character} -constraints icu -body {
	icu convertto -profile strict ISO-8859-2 \U1F600
    } -result {ICU error while encoding. ICU error (10): U_INVALID_CHAR_FOUND} -returnCodes error

    test icu-convertto-5 {-profile replace unencodable character} -constraints icu -body {
	icu convertto -profile replace ISO-8859-2 \U1F600
    } -result \x1A

    ###
    # Basic tests for normalization

    test icu-normalize-error-0 {no args} -constraints icu -body {
	icu normalize
    } -result {wrong # args: should be "icu normalize ?-profile PROFILE? ?-mode MODE? STRING"} -returnCodes error

    test icu-normalize-error-1 {missing -profile arg} -constraints icu -body {
	icu normalize -profile STRING
    } -result {Missing value for option -profile.} -returnCodes error

    test icu-normalize-error-2 {missing -mode arg} -constraints icu -body {
	icu normalize -mode STRING
    } -result {Missing value for option -mode.} -returnCodes error

    test icu-normalize-error-3 {extra arg} -constraints icu -body {
	icu normalize -profile strict STRING arg
    } -result {bad option "STRING": must be -profile or -mode} -returnCodes error

    test icu-normalize-error-4 {invalid profile} -constraints icu -body {
	icu normalize -profile tcl8 ASCII abc
    } -result {Invalid value "tcl8" supplied for option "-profile". Must be "strict" or "replace".} -returnCodes error

    test icu-normalize-error-6 {invalid mode} -constraints icu -body {
	icu normalize -mode xxx ASCII abc
    } -result {bad normalization mode "xxx": must be nfc, nfd, nfkc, or nfkd} -returnCodes error

    # Source is composed
    set s \uFB01anc\u00e9
    test icu-normalize-0 {Default normalization} -constraints icu -body {
	icu normalize $s
    } -result \uFB01anc\u00e9
    test icu-normalize-nfc-0 {NFC normalization} -constraints icu -body {
	icu normalize -mode nfc $s
    } -result \uFB01anc\u00e9
    test icu-normalize-nfd-0 {NFD normalization} -constraints icu -body {
	icu normalize -mode nfd $s
    } -result \uFB01ance\u0301
    test icu-normalize-nfkc-0 {NFKC normalization} -constraints icu -body {
	icu normalize -mode nfkc $s
    } -result fianc\u00e9
    test icu-normalize-nfkd-0 {NFKD normalization} -constraints icu -body {
	icu normalize -mode nfkd $s
    } -result fiance\u0301

    # Source is decomposed
    set s \uFB01ance\u0301
    test icu-normalize-1 {Default normalization} -constraints icu -body {
	icu normalize $s
    } -result \uFB01anc\u00e9
    test icu-normalize-nfc-0 {NFC normalization} -constraints icu -body {
	icu normalize -mode nfc $s
    } -result \uFB01anc\u00e9
    test icu-normalize-nfd-1 {NFD normalization} -constraints icu -body {
	icu normalize -mode nfd $s
    } -result \uFB01ance\u0301
    test icu-normalize-nfkc-1 {NFKC normalization} -constraints icu -body {
	icu normalize -mode nfkc $s
    } -result fianc\u00e9
    test icu-normalize-nfkd-1 {NFKD normalization} -constraints icu -body {
	icu normalize -mode nfkd $s
    } -result fiance\u0301

    # Source has multiple diacritics with different canonical ordering
    foreach s [list \u1EC7 e\u0302\u0323 e\u0323\u0302] {
	test icu-normalize-nfc-2 {fully composed} -constraints icu -body {
	    icu normalize -mode nfc $s
	} -result \u1EC7
	test icu-normalize-nfc-2 {fully decomposed} -constraints icu -body {
	    icu normalize -mode nfd $s
	} -result e\u0323\u0302
    }
}

namespace delete icu
::tcltest::cleanupTests

Added tests/icuUcmTests.tcl.




































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

# This file is automatically generated by ucm2tests.tcl.
# Edits will be overwritten on next generation.
#
# Tests comparing Tcl encodings to ICU.
# This file is NOT standalone. It should be sourced into a test script.

proc ucmConvertfromMismatches {enc map} {
    set mismatches {}
    foreach {unihex hex} $map {
	set unihex [string range 00000000$unihex end-7 end]; # Make 8 digits
	set unich [subst "\\U$unihex"]
	if {[encoding convertfrom -profile strict $enc [binary decode hex $hex]] ne $unich} {
	    lappend mismatches "<[printable $unich],$hex>"
	}
    }
    return $mismatches
}
proc ucmConverttoMismatches {enc map} {
    set mismatches {}
    foreach {unihex hex} $map {
	set unihex [string range 00000000$unihex end-7 end]; # Make 8 digits
	set unich [subst "\\U$unihex"]
	if {[encoding convertto -profile strict $enc $unich] ne [binary decode hex $hex]} {
	    lappend mismatches "<[printable $unich],$hex>"
	}
    }
    return $mismatches
}
if {[info commands printable] eq ""} {
    proc printable {s} {
	set print ""
	foreach c [split $s ""] {
	    set i [scan $c %c]
	    if {[string is print $c] && ($i <= 127)} {
		append print $c
	    } elseif {$i <= 0xff} {
		append print \\x[format %02X $i]
	    } elseif {$i <= 0xffff} {
		append print \\u[format %04X $i]
	    } else {
		append print \\U[format %08X $i]
	    }
	}
	return $print
    }
}


#
# cp1250 (generated from glibc-CP1250-2.1.2)

test encoding-convertfrom-ucmCompare-cp1250 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches cp1250 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 00A0 A0 00A4 A4 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AB AB 00AC AC 00AD AD 00AE AE 00B0 B0 00B1 B1 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 B8 00BB BB 00C1 C1 00C2 C2 00C4 C4 00C7 C7 00C9 C9 00CB CB 00CD CD 00CE CE 00D3 D3 00D4 D4 00D6 D6 00D7 D7 00DA DA 00DC DC 00DD DD 00DF DF 00E1 E1 00E2 E2 00E4 E4 00E7 E7 00E9 E9 00EB EB 00ED ED 00EE EE 00F3 F3 00F4 F4 00F6 F6 00F7 F7 00FA FA 00FC FC 00FD FD 0102 C3 0103 E3 0104 A5 0105 B9 0106 C6 0107 E6 010C C8 010D E8 010E CF 010F EF 0110 D0 0111 F0 0118 CA 0119 EA 011A CC 011B EC 0139 C5 013A E5 013D BC 013E BE 0141 A3 0142 B3 0143 D1 0144 F1 0147 D2 0148 F2 0150 D5 0151 F5 0154 C0 0155 E0 0158 D8 0159 F8 015A 8C 015B 9C 015E AA 015F BA 0160 8A 0161 9A 0162 DE 0163 FE 0164 8D 0165 9D 016E D9 016F F9 0170 DB 0171 FB 0179 8F 017A 9F 017B AF 017C BF 017D 8E 017E 9E 02C7 A1 02D8 A2 02D9 FF 02DB B2 02DD BD 2013 96 2014 97 2018 91 2019 92 201A 82 201C 93 201D 94 201E 84 2020 86 2021 87 2022 95 2026 85 2030 89 2039 8B 203A 9B 20AC 80 2122 99}
} -result {}

test encoding-convertto-ucmCompare-cp1250 {Compare against ICU UCM} -body {
    ucmConverttoMismatches cp1250 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 00A0 A0 00A4 A4 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AB AB 00AC AC 00AD AD 00AE AE 00B0 B0 00B1 B1 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 B8 00BB BB 00C1 C1 00C2 C2 00C4 C4 00C7 C7 00C9 C9 00CB CB 00CD CD 00CE CE 00D3 D3 00D4 D4 00D6 D6 00D7 D7 00DA DA 00DC DC 00DD DD 00DF DF 00E1 E1 00E2 E2 00E4 E4 00E7 E7 00E9 E9 00EB EB 00ED ED 00EE EE 00F3 F3 00F4 F4 00F6 F6 00F7 F7 00FA FA 00FC FC 00FD FD 0102 C3 0103 E3 0104 A5 0105 B9 0106 C6 0107 E6 010C C8 010D E8 010E CF 010F EF 0110 D0 0111 F0 0118 CA 0119 EA 011A CC 011B EC 0139 C5 013A E5 013D BC 013E BE 0141 A3 0142 B3 0143 D1 0144 F1 0147 D2 0148 F2 0150 D5 0151 F5 0154 C0 0155 E0 0158 D8 0159 F8 015A 8C 015B 9C 015E AA 015F BA 0160 8A 0161 9A 0162 DE 0163 FE 0164 8D 0165 9D 016E D9 016F F9 0170 DB 0171 FB 0179 8F 017A 9F 017B AF 017C BF 017D 8E 017E 9E 02C7 A1 02D8 A2 02D9 FF 02DB B2 02DD BD 2013 96 2014 97 2018 91 2019 92 201A 82 201C 93 201D 94 201E 84 2020 86 2021 87 2022 95 2026 85 2030 89 2039 8B 203A 9B 20AC 80 2122 99}
} -result {}

# cp1250 - invalid byte sequences
lappend encInvalidBytes {*}{
    cp1250 81 tcl8    \U00000081 -1 {} {}
    cp1250 81 replace \uFFFD -1 {} {}
    cp1250 81 strict  {}       0 {} {}
    cp1250 83 tcl8    \U00000083 -1 {} {}
    cp1250 83 replace \uFFFD -1 {} {}
    cp1250 83 strict  {}       0 {} {}
    cp1250 88 tcl8    \U00000088 -1 {} {}
    cp1250 88 replace \uFFFD -1 {} {}
    cp1250 88 strict  {}       0 {} {}
    cp1250 90 tcl8    \U00000090 -1 {} {}
    cp1250 90 replace \uFFFD -1 {} {}
    cp1250 90 strict  {}       0 {} {}
    cp1250 98 tcl8    \U00000098 -1 {} {}
    cp1250 98 replace \uFFFD -1 {} {}
    cp1250 98 strict  {}       0 {} {}
}; # cp1250

# cp1250 - invalid byte sequences
lappend encUnencodableStrings {*}{
    cp1250 \U00000080 tcl8    1A -1 {} {}
    cp1250 \U00000080 replace 1A -1 {} {}
    cp1250 \U00000080 strict  {}                      0 {} {}
    cp1250 \U00000400 tcl8    1A -1 {} {}
    cp1250 \U00000400 replace 1A -1 {} {}
    cp1250 \U00000400 strict  {}                      0 {} {}
    cp1250 \U0000D800 tcl8    1A -1 {} {}
    cp1250 \U0000D800 replace 1A -1 {} {}
    cp1250 \U0000D800 strict  {}                      0 {} {}
    cp1250 \U0000DC00 tcl8    1A -1 {} {}
    cp1250 \U0000DC00 replace 1A -1 {} {}
    cp1250 \U0000DC00 strict  {}                      0 {} {}
    cp1250 \U00010000 tcl8    1A -1 {} {}
    cp1250 \U00010000 replace 1A -1 {} {}
    cp1250 \U00010000 strict  {}                      0 {} {}
    cp1250 \U0010FFFF tcl8    1A -1 {} {}
    cp1250 \U0010FFFF replace 1A -1 {} {}
    cp1250 \U0010FFFF strict  {}                      0 {} {}
}; # cp1250

#
# cp1251 (generated from glibc-CP1251-2.1.2)

test encoding-convertfrom-ucmCompare-cp1251 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches cp1251 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 00A0 A0 00A4 A4 00A6 A6 00A7 A7 00A9 A9 00AB AB 00AC AC 00AD AD 00AE AE 00B0 B0 00B1 B1 00B5 B5 00B6 B6 00B7 B7 00BB BB 0401 A8 0402 80 0403 81 0404 AA 0405 BD 0406 B2 0407 AF 0408 A3 0409 8A 040A 8C 040B 8E 040C 8D 040E A1 040F 8F 0410 C0 0411 C1 0412 C2 0413 C3 0414 C4 0415 C5 0416 C6 0417 C7 0418 C8 0419 C9 041A CA 041B CB 041C CC 041D CD 041E CE 041F CF 0420 D0 0421 D1 0422 D2 0423 D3 0424 D4 0425 D5 0426 D6 0427 D7 0428 D8 0429 D9 042A DA 042B DB 042C DC 042D DD 042E DE 042F DF 0430 E0 0431 E1 0432 E2 0433 E3 0434 E4 0435 E5 0436 E6 0437 E7 0438 E8 0439 E9 043A EA 043B EB 043C EC 043D ED 043E EE 043F EF 0440 F0 0441 F1 0442 F2 0443 F3 0444 F4 0445 F5 0446 F6 0447 F7 0448 F8 0449 F9 044A FA 044B FB 044C FC 044D FD 044E FE 044F FF 0451 B8 0452 90 0453 83 0454 BA 0455 BE 0456 B3 0457 BF 0458 BC 0459 9A 045A 9C 045B 9E 045C 9D 045E A2 045F 9F 0490 A5 0491 B4 2013 96 2014 97 2018 91 2019 92 201A 82 201C 93 201D 94 201E 84 2020 86 2021 87 2022 95 2026 85 2030 89 2039 8B 203A 9B 20AC 88 2116 B9 2122 99}
} -result {}

test encoding-convertto-ucmCompare-cp1251 {Compare against ICU UCM} -body {
    ucmConverttoMismatches cp1251 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 00A0 A0 00A4 A4 00A6 A6 00A7 A7 00A9 A9 00AB AB 00AC AC 00AD AD 00AE AE 00B0 B0 00B1 B1 00B5 B5 00B6 B6 00B7 B7 00BB BB 0401 A8 0402 80 0403 81 0404 AA 0405 BD 0406 B2 0407 AF 0408 A3 0409 8A 040A 8C 040B 8E 040C 8D 040E A1 040F 8F 0410 C0 0411 C1 0412 C2 0413 C3 0414 C4 0415 C5 0416 C6 0417 C7 0418 C8 0419 C9 041A CA 041B CB 041C CC 041D CD 041E CE 041F CF 0420 D0 0421 D1 0422 D2 0423 D3 0424 D4 0425 D5 0426 D6 0427 D7 0428 D8 0429 D9 042A DA 042B DB 042C DC 042D DD 042E DE 042F DF 0430 E0 0431 E1 0432 E2 0433 E3 0434 E4 0435 E5 0436 E6 0437 E7 0438 E8 0439 E9 043A EA 043B EB 043C EC 043D ED 043E EE 043F EF 0440 F0 0441 F1 0442 F2 0443 F3 0444 F4 0445 F5 0446 F6 0447 F7 0448 F8 0449 F9 044A FA 044B FB 044C FC 044D FD 044E FE 044F FF 0451 B8 0452 90 0453 83 0454 BA 0455 BE 0456 B3 0457 BF 0458 BC 0459 9A 045A 9C 045B 9E 045C 9D 045E A2 045F 9F 0490 A5 0491 B4 2013 96 2014 97 2018 91 2019 92 201A 82 201C 93 201D 94 201E 84 2020 86 2021 87 2022 95 2026 85 2030 89 2039 8B 203A 9B 20AC 88 2116 B9 2122 99}
} -result {}

# cp1251 - invalid byte sequences
lappend encInvalidBytes {*}{
    cp1251 98 tcl8    \U00000098 -1 {} {}
    cp1251 98 replace \uFFFD -1 {} {}
    cp1251 98 strict  {}       0 {} {}
}; # cp1251

# cp1251 - invalid byte sequences
lappend encUnencodableStrings {*}{
    cp1251 \U00000080 tcl8    1A -1 {} {}
    cp1251 \U00000080 replace 1A -1 {} {}
    cp1251 \U00000080 strict  {}                      0 {} {}
    cp1251 \U00000400 tcl8    1A -1 {} {}
    cp1251 \U00000400 replace 1A -1 {} {}
    cp1251 \U00000400 strict  {}                      0 {} {}
    cp1251 \U0000D800 tcl8    1A -1 {} {}
    cp1251 \U0000D800 replace 1A -1 {} {}
    cp1251 \U0000D800 strict  {}                      0 {} {}
    cp1251 \U0000DC00 tcl8    1A -1 {} {}
    cp1251 \U0000DC00 replace 1A -1 {} {}
    cp1251 \U0000DC00 strict  {}                      0 {} {}
    cp1251 \U00010000 tcl8    1A -1 {} {}
    cp1251 \U00010000 replace 1A -1 {} {}
    cp1251 \U00010000 strict  {}                      0 {} {}
    cp1251 \U0010FFFF tcl8    1A -1 {} {}
    cp1251 \U0010FFFF replace 1A -1 {} {}
    cp1251 \U0010FFFF strict  {}                      0 {} {}
}; # cp1251

#
# cp1252 (generated from glibc-CP1252-2.1.2)

test encoding-convertfrom-ucmCompare-cp1252 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches cp1252 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 00A0 A0 00A1 A1 00A2 A2 00A3 A3 00A4 A4 00A5 A5 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AA AA 00AB AB 00AC AC 00AD AD 00AE AE 00AF AF 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 B8 00B9 B9 00BA BA 00BB BB 00BC BC 00BD BD 00BE BE 00BF BF 00C0 C0 00C1 C1 00C2 C2 00C3 C3 00C4 C4 00C5 C5 00C6 C6 00C7 C7 00C8 C8 00C9 C9 00CA CA 00CB CB 00CC CC 00CD CD 00CE CE 00CF CF 00D0 D0 00D1 D1 00D2 D2 00D3 D3 00D4 D4 00D5 D5 00D6 D6 00D7 D7 00D8 D8 00D9 D9 00DA DA 00DB DB 00DC DC 00DD DD 00DE DE 00DF DF 00E0 E0 00E1 E1 00E2 E2 00E3 E3 00E4 E4 00E5 E5 00E6 E6 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00EC EC 00ED ED 00EE EE 00EF EF 00F0 F0 00F1 F1 00F2 F2 00F3 F3 00F4 F4 00F5 F5 00F6 F6 00F7 F7 00F8 F8 00F9 F9 00FA FA 00FB FB 00FC FC 00FD FD 00FE FE 00FF FF 0152 8C 0153 9C 0160 8A 0161 9A 0178 9F 017D 8E 017E 9E 0192 83 02C6 88 02DC 98 2013 96 2014 97 2018 91 2019 92 201A 82 201C 93 201D 94 201E 84 2020 86 2021 87 2022 95 2026 85 2030 89 2039 8B 203A 9B 20AC 80 2122 99}
} -result {}

test encoding-convertto-ucmCompare-cp1252 {Compare against ICU UCM} -body {
    ucmConverttoMismatches cp1252 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 00A0 A0 00A1 A1 00A2 A2 00A3 A3 00A4 A4 00A5 A5 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AA AA 00AB AB 00AC AC 00AD AD 00AE AE 00AF AF 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 B8 00B9 B9 00BA BA 00BB BB 00BC BC 00BD BD 00BE BE 00BF BF 00C0 C0 00C1 C1 00C2 C2 00C3 C3 00C4 C4 00C5 C5 00C6 C6 00C7 C7 00C8 C8 00C9 C9 00CA CA 00CB CB 00CC CC 00CD CD 00CE CE 00CF CF 00D0 D0 00D1 D1 00D2 D2 00D3 D3 00D4 D4 00D5 D5 00D6 D6 00D7 D7 00D8 D8 00D9 D9 00DA DA 00DB DB 00DC DC 00DD DD 00DE DE 00DF DF 00E0 E0 00E1 E1 00E2 E2 00E3 E3 00E4 E4 00E5 E5 00E6 E6 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00EC EC 00ED ED 00EE EE 00EF EF 00F0 F0 00F1 F1 00F2 F2 00F3 F3 00F4 F4 00F5 F5 00F6 F6 00F7 F7 00F8 F8 00F9 F9 00FA FA 00FB FB 00FC FC 00FD FD 00FE FE 00FF FF 0152 8C 0153 9C 0160 8A 0161 9A 0178 9F 017D 8E 017E 9E 0192 83 02C6 88 02DC 98 2013 96 2014 97 2018 91 2019 92 201A 82 201C 93 201D 94 201E 84 2020 86 2021 87 2022 95 2026 85 2030 89 2039 8B 203A 9B 20AC 80 2122 99}
} -result {}

# cp1252 - invalid byte sequences
lappend encInvalidBytes {*}{
    cp1252 81 tcl8    \U00000081 -1 {} {}
    cp1252 81 replace \uFFFD -1 {} {}
    cp1252 81 strict  {}       0 {} {}
    cp1252 8D tcl8    \U0000008D -1 {} {}
    cp1252 8D replace \uFFFD -1 {} {}
    cp1252 8D strict  {}       0 {} {}
    cp1252 8F tcl8    \U0000008F -1 {} {}
    cp1252 8F replace \uFFFD -1 {} {}
    cp1252 8F strict  {}       0 {} {}
    cp1252 90 tcl8    \U00000090 -1 {} {}
    cp1252 90 replace \uFFFD -1 {} {}
    cp1252 90 strict  {}       0 {} {}
    cp1252 9D tcl8    \U0000009D -1 {} {}
    cp1252 9D replace \uFFFD -1 {} {}
    cp1252 9D strict  {}       0 {} {}
}; # cp1252

# cp1252 - invalid byte sequences
lappend encUnencodableStrings {*}{
    cp1252 \U00000080 tcl8    1A -1 {} {}
    cp1252 \U00000080 replace 1A -1 {} {}
    cp1252 \U00000080 strict  {}                      0 {} {}
    cp1252 \U00000400 tcl8    1A -1 {} {}
    cp1252 \U00000400 replace 1A -1 {} {}
    cp1252 \U00000400 strict  {}                      0 {} {}
    cp1252 \U0000D800 tcl8    1A -1 {} {}
    cp1252 \U0000D800 replace 1A -1 {} {}
    cp1252 \U0000D800 strict  {}                      0 {} {}
    cp1252 \U0000DC00 tcl8    1A -1 {} {}
    cp1252 \U0000DC00 replace 1A -1 {} {}
    cp1252 \U0000DC00 strict  {}                      0 {} {}
    cp1252 \U00010000 tcl8    1A -1 {} {}
    cp1252 \U00010000 replace 1A -1 {} {}
    cp1252 \U00010000 strict  {}                      0 {} {}
    cp1252 \U0010FFFF tcl8    1A -1 {} {}
    cp1252 \U0010FFFF replace 1A -1 {} {}
    cp1252 \U0010FFFF strict  {}                      0 {} {}
}; # cp1252

#
# cp1253 (generated from glibc-CP1253-2.1.2)

test encoding-convertfrom-ucmCompare-cp1253 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches cp1253 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 00A0 A0 00A3 A3 00A4 A4 00A5 A5 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AB AB 00AC AC 00AD AD 00AE AE 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B5 B5 00B6 B6 00B7 B7 00BB BB 00BD BD 0192 83 0384 B4 0385 A1 0386 A2 0388 B8 0389 B9 038A BA 038C BC 038E BE 038F BF 0390 C0 0391 C1 0392 C2 0393 C3 0394 C4 0395 C5 0396 C6 0397 C7 0398 C8 0399 C9 039A CA 039B CB 039C CC 039D CD 039E CE 039F CF 03A0 D0 03A1 D1 03A3 D3 03A4 D4 03A5 D5 03A6 D6 03A7 D7 03A8 D8 03A9 D9 03AA DA 03AB DB 03AC DC 03AD DD 03AE DE 03AF DF 03B0 E0 03B1 E1 03B2 E2 03B3 E3 03B4 E4 03B5 E5 03B6 E6 03B7 E7 03B8 E8 03B9 E9 03BA EA 03BB EB 03BC EC 03BD ED 03BE EE 03BF EF 03C0 F0 03C1 F1 03C2 F2 03C3 F3 03C4 F4 03C5 F5 03C6 F6 03C7 F7 03C8 F8 03C9 F9 03CA FA 03CB FB 03CC FC 03CD FD 03CE FE 2013 96 2014 97 2015 AF 2018 91 2019 92 201A 82 201C 93 201D 94 201E 84 2020 86 2021 87 2022 95 2026 85 2030 89 2039 8B 203A 9B 20AC 80 2122 99}
} -result {}

test encoding-convertto-ucmCompare-cp1253 {Compare against ICU UCM} -body {
    ucmConverttoMismatches cp1253 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 00A0 A0 00A3 A3 00A4 A4 00A5 A5 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AB AB 00AC AC 00AD AD 00AE AE 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B5 B5 00B6 B6 00B7 B7 00BB BB 00BD BD 0192 83 0384 B4 0385 A1 0386 A2 0388 B8 0389 B9 038A BA 038C BC 038E BE 038F BF 0390 C0 0391 C1 0392 C2 0393 C3 0394 C4 0395 C5 0396 C6 0397 C7 0398 C8 0399 C9 039A CA 039B CB 039C CC 039D CD 039E CE 039F CF 03A0 D0 03A1 D1 03A3 D3 03A4 D4 03A5 D5 03A6 D6 03A7 D7 03A8 D8 03A9 D9 03AA DA 03AB DB 03AC DC 03AD DD 03AE DE 03AF DF 03B0 E0 03B1 E1 03B2 E2 03B3 E3 03B4 E4 03B5 E5 03B6 E6 03B7 E7 03B8 E8 03B9 E9 03BA EA 03BB EB 03BC EC 03BD ED 03BE EE 03BF EF 03C0 F0 03C1 F1 03C2 F2 03C3 F3 03C4 F4 03C5 F5 03C6 F6 03C7 F7 03C8 F8 03C9 F9 03CA FA 03CB FB 03CC FC 03CD FD 03CE FE 2013 96 2014 97 2015 AF 2018 91 2019 92 201A 82 201C 93 201D 94 201E 84 2020 86 2021 87 2022 95 2026 85 2030 89 2039 8B 203A 9B 20AC 80 2122 99}
} -result {}

# cp1253 - invalid byte sequences
lappend encInvalidBytes {*}{
    cp1253 81 tcl8    \U00000081 -1 {} {}
    cp1253 81 replace \uFFFD -1 {} {}
    cp1253 81 strict  {}       0 {} {}
    cp1253 88 tcl8    \U00000088 -1 {} {}
    cp1253 88 replace \uFFFD -1 {} {}
    cp1253 88 strict  {}       0 {} {}
    cp1253 8A tcl8    \U0000008A -1 {} {}
    cp1253 8A replace \uFFFD -1 {} {}
    cp1253 8A strict  {}       0 {} {}
    cp1253 8C tcl8    \U0000008C -1 {} {}
    cp1253 8C replace \uFFFD -1 {} {}
    cp1253 8C strict  {}       0 {} {}
    cp1253 8D tcl8    \U0000008D -1 {} {}
    cp1253 8D replace \uFFFD -1 {} {}
    cp1253 8D strict  {}       0 {} {}
    cp1253 8E tcl8    \U0000008E -1 {} {}
    cp1253 8E replace \uFFFD -1 {} {}
    cp1253 8E strict  {}       0 {} {}
    cp1253 8F tcl8    \U0000008F -1 {} {}
    cp1253 8F replace \uFFFD -1 {} {}
    cp1253 8F strict  {}       0 {} {}
    cp1253 90 tcl8    \U00000090 -1 {} {}
    cp1253 90 replace \uFFFD -1 {} {}
    cp1253 90 strict  {}       0 {} {}
    cp1253 98 tcl8    \U00000098 -1 {} {}
    cp1253 98 replace \uFFFD -1 {} {}
    cp1253 98 strict  {}       0 {} {}
    cp1253 9A tcl8    \U0000009A -1 {} {}
    cp1253 9A replace \uFFFD -1 {} {}
    cp1253 9A strict  {}       0 {} {}
    cp1253 9C tcl8    \U0000009C -1 {} {}
    cp1253 9C replace \uFFFD -1 {} {}
    cp1253 9C strict  {}       0 {} {}
    cp1253 9D tcl8    \U0000009D -1 {} {}
    cp1253 9D replace \uFFFD -1 {} {}
    cp1253 9D strict  {}       0 {} {}
    cp1253 9E tcl8    \U0000009E -1 {} {}
    cp1253 9E replace \uFFFD -1 {} {}
    cp1253 9E strict  {}       0 {} {}
    cp1253 9F tcl8    \U0000009F -1 {} {}
    cp1253 9F replace \uFFFD -1 {} {}
    cp1253 9F strict  {}       0 {} {}
    cp1253 AA tcl8    \U000000AA -1 {} {}
    cp1253 AA replace \uFFFD -1 {} {}
    cp1253 AA strict  {}       0 {} {}
    cp1253 D2 tcl8    \U000000D2 -1 {} {}
    cp1253 D2 replace \uFFFD -1 {} {}
    cp1253 D2 strict  {}       0 {} {}
    cp1253 FF tcl8    \U000000FF -1 {} {}
    cp1253 FF replace \uFFFD -1 {} {}
    cp1253 FF strict  {}       0 {} {}
}; # cp1253

# cp1253 - invalid byte sequences
lappend encUnencodableStrings {*}{
    cp1253 \U00000080 tcl8    1A -1 {} {}
    cp1253 \U00000080 replace 1A -1 {} {}
    cp1253 \U00000080 strict  {}                      0 {} {}
    cp1253 \U00000400 tcl8    1A -1 {} {}
    cp1253 \U00000400 replace 1A -1 {} {}
    cp1253 \U00000400 strict  {}                      0 {} {}
    cp1253 \U0000D800 tcl8    1A -1 {} {}
    cp1253 \U0000D800 replace 1A -1 {} {}
    cp1253 \U0000D800 strict  {}                      0 {} {}
    cp1253 \U0000DC00 tcl8    1A -1 {} {}
    cp1253 \U0000DC00 replace 1A -1 {} {}
    cp1253 \U0000DC00 strict  {}                      0 {} {}
    cp1253 \U00010000 tcl8    1A -1 {} {}
    cp1253 \U00010000 replace 1A -1 {} {}
    cp1253 \U00010000 strict  {}                      0 {} {}
    cp1253 \U0010FFFF tcl8    1A -1 {} {}
    cp1253 \U0010FFFF replace 1A -1 {} {}
    cp1253 \U0010FFFF strict  {}                      0 {} {}
}; # cp1253

#
# cp1254 (generated from glibc-CP1254-2.1.2)

test encoding-convertfrom-ucmCompare-cp1254 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches cp1254 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 00A0 A0 00A1 A1 00A2 A2 00A3 A3 00A4 A4 00A5 A5 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AA AA 00AB AB 00AC AC 00AD AD 00AE AE 00AF AF 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 B8 00B9 B9 00BA BA 00BB BB 00BC BC 00BD BD 00BE BE 00BF BF 00C0 C0 00C1 C1 00C2 C2 00C3 C3 00C4 C4 00C5 C5 00C6 C6 00C7 C7 00C8 C8 00C9 C9 00CA CA 00CB CB 00CC CC 00CD CD 00CE CE 00CF CF 00D1 D1 00D2 D2 00D3 D3 00D4 D4 00D5 D5 00D6 D6 00D7 D7 00D8 D8 00D9 D9 00DA DA 00DB DB 00DC DC 00DF DF 00E0 E0 00E1 E1 00E2 E2 00E3 E3 00E4 E4 00E5 E5 00E6 E6 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00EC EC 00ED ED 00EE EE 00EF EF 00F1 F1 00F2 F2 00F3 F3 00F4 F4 00F5 F5 00F6 F6 00F7 F7 00F8 F8 00F9 F9 00FA FA 00FB FB 00FC FC 00FF FF 011E D0 011F F0 0130 DD 0131 FD 0152 8C 0153 9C 015E DE 015F FE 0160 8A 0161 9A 0178 9F 0192 83 02C6 88 02DC 98 2013 96 2014 97 2018 91 2019 92 201A 82 201C 93 201D 94 201E 84 2020 86 2021 87 2022 95 2026 85 2030 89 2039 8B 203A 9B 20AC 80 2122 99}
} -result {}

test encoding-convertto-ucmCompare-cp1254 {Compare against ICU UCM} -body {
    ucmConverttoMismatches cp1254 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 00A0 A0 00A1 A1 00A2 A2 00A3 A3 00A4 A4 00A5 A5 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AA AA 00AB AB 00AC AC 00AD AD 00AE AE 00AF AF 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 B8 00B9 B9 00BA BA 00BB BB 00BC BC 00BD BD 00BE BE 00BF BF 00C0 C0 00C1 C1 00C2 C2 00C3 C3 00C4 C4 00C5 C5 00C6 C6 00C7 C7 00C8 C8 00C9 C9 00CA CA 00CB CB 00CC CC 00CD CD 00CE CE 00CF CF 00D1 D1 00D2 D2 00D3 D3 00D4 D4 00D5 D5 00D6 D6 00D7 D7 00D8 D8 00D9 D9 00DA DA 00DB DB 00DC DC 00DF DF 00E0 E0 00E1 E1 00E2 E2 00E3 E3 00E4 E4 00E5 E5 00E6 E6 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00EC EC 00ED ED 00EE EE 00EF EF 00F1 F1 00F2 F2 00F3 F3 00F4 F4 00F5 F5 00F6 F6 00F7 F7 00F8 F8 00F9 F9 00FA FA 00FB FB 00FC FC 00FF FF 011E D0 011F F0 0130 DD 0131 FD 0152 8C 0153 9C 015E DE 015F FE 0160 8A 0161 9A 0178 9F 0192 83 02C6 88 02DC 98 2013 96 2014 97 2018 91 2019 92 201A 82 201C 93 201D 94 201E 84 2020 86 2021 87 2022 95 2026 85 2030 89 2039 8B 203A 9B 20AC 80 2122 99}
} -result {}

# cp1254 - invalid byte sequences
lappend encInvalidBytes {*}{
    cp1254 81 tcl8    \U00000081 -1 {} {}
    cp1254 81 replace \uFFFD -1 {} {}
    cp1254 81 strict  {}       0 {} {}
    cp1254 8D tcl8    \U0000008D -1 {} {}
    cp1254 8D replace \uFFFD -1 {} {}
    cp1254 8D strict  {}       0 {} {}
    cp1254 8E tcl8    \U0000008E -1 {} {}
    cp1254 8E replace \uFFFD -1 {} {}
    cp1254 8E strict  {}       0 {} {}
    cp1254 8F tcl8    \U0000008F -1 {} {}
    cp1254 8F replace \uFFFD -1 {} {}
    cp1254 8F strict  {}       0 {} {}
    cp1254 90 tcl8    \U00000090 -1 {} {}
    cp1254 90 replace \uFFFD -1 {} {}
    cp1254 90 strict  {}       0 {} {}
    cp1254 9D tcl8    \U0000009D -1 {} {}
    cp1254 9D replace \uFFFD -1 {} {}
    cp1254 9D strict  {}       0 {} {}
    cp1254 9E tcl8    \U0000009E -1 {} {}
    cp1254 9E replace \uFFFD -1 {} {}
    cp1254 9E strict  {}       0 {} {}
}; # cp1254

# cp1254 - invalid byte sequences
lappend encUnencodableStrings {*}{
    cp1254 \U00000080 tcl8    1A -1 {} {}
    cp1254 \U00000080 replace 1A -1 {} {}
    cp1254 \U00000080 strict  {}                      0 {} {}
    cp1254 \U00000400 tcl8    1A -1 {} {}
    cp1254 \U00000400 replace 1A -1 {} {}
    cp1254 \U00000400 strict  {}                      0 {} {}
    cp1254 \U0000D800 tcl8    1A -1 {} {}
    cp1254 \U0000D800 replace 1A -1 {} {}
    cp1254 \U0000D800 strict  {}                      0 {} {}
    cp1254 \U0000DC00 tcl8    1A -1 {} {}
    cp1254 \U0000DC00 replace 1A -1 {} {}
    cp1254 \U0000DC00 strict  {}                      0 {} {}
    cp1254 \U00010000 tcl8    1A -1 {} {}
    cp1254 \U00010000 replace 1A -1 {} {}
    cp1254 \U00010000 strict  {}                      0 {} {}
    cp1254 \U0010FFFF tcl8    1A -1 {} {}
    cp1254 \U0010FFFF replace 1A -1 {} {}
    cp1254 \U0010FFFF strict  {}                      0 {} {}
}; # cp1254

#
# cp1255 (generated from glibc-CP1255-2.1.2)

test encoding-convertfrom-ucmCompare-cp1255 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches cp1255 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 00A0 A0 00A1 A1 00A2 A2 00A3 A3 00A5 A5 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AB AB 00AC AC 00AD AD 00AE AE 00AF AF 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 B8 00B9 B9 00BB BB 00BC BC 00BD BD 00BE BE 00BF BF 00D7 AA 00F7 BA 0192 83 02C6 88 02DC 98 05B0 C0 05B1 C1 05B2 C2 05B3 C3 05B4 C4 05B5 C5 05B6 C6 05B7 C7 05B8 C8 05B9 C9 05BB CB 05BC CC 05BD CD 05BE CE 05BF CF 05C0 D0 05C1 D1 05C2 D2 05C3 D3 05D0 E0 05D1 E1 05D2 E2 05D3 E3 05D4 E4 05D5 E5 05D6 E6 05D7 E7 05D8 E8 05D9 E9 05DA EA 05DB EB 05DC EC 05DD ED 05DE EE 05DF EF 05E0 F0 05E1 F1 05E2 F2 05E3 F3 05E4 F4 05E5 F5 05E6 F6 05E7 F7 05E8 F8 05E9 F9 05EA FA 05F0 D4 05F1 D5 05F2 D6 05F3 D7 05F4 D8 200E FD 200F FE 2013 96 2014 97 2018 91 2019 92 201A 82 201C 93 201D 94 201E 84 2020 86 2021 87 2022 95 2026 85 2030 89 2039 8B 203A 9B 20AA A4 20AC 80 2122 99}
} -result {}

test encoding-convertto-ucmCompare-cp1255 {Compare against ICU UCM} -body {
    ucmConverttoMismatches cp1255 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 00A0 A0 00A1 A1 00A2 A2 00A3 A3 00A5 A5 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AB AB 00AC AC 00AD AD 00AE AE 00AF AF 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 B8 00B9 B9 00BB BB 00BC BC 00BD BD 00BE BE 00BF BF 00D7 AA 00F7 BA 0192 83 02C6 88 02DC 98 05B0 C0 05B1 C1 05B2 C2 05B3 C3 05B4 C4 05B5 C5 05B6 C6 05B7 C7 05B8 C8 05B9 C9 05BB CB 05BC CC 05BD CD 05BE CE 05BF CF 05C0 D0 05C1 D1 05C2 D2 05C3 D3 05D0 E0 05D1 E1 05D2 E2 05D3 E3 05D4 E4 05D5 E5 05D6 E6 05D7 E7 05D8 E8 05D9 E9 05DA EA 05DB EB 05DC EC 05DD ED 05DE EE 05DF EF 05E0 F0 05E1 F1 05E2 F2 05E3 F3 05E4 F4 05E5 F5 05E6 F6 05E7 F7 05E8 F8 05E9 F9 05EA FA 05F0 D4 05F1 D5 05F2 D6 05F3 D7 05F4 D8 200E FD 200F FE 2013 96 2014 97 2018 91 2019 92 201A 82 201C 93 201D 94 201E 84 2020 86 2021 87 2022 95 2026 85 2030 89 2039 8B 203A 9B 20AA A4 20AC 80 2122 99}
} -result {}

# cp1255 - invalid byte sequences
lappend encInvalidBytes {*}{
    cp1255 81 tcl8    \U00000081 -1 {} {}
    cp1255 81 replace \uFFFD -1 {} {}
    cp1255 81 strict  {}       0 {} {}
    cp1255 8A tcl8    \U0000008A -1 {} {}
    cp1255 8A replace \uFFFD -1 {} {}
    cp1255 8A strict  {}       0 {} {}
    cp1255 8C tcl8    \U0000008C -1 {} {}
    cp1255 8C replace \uFFFD -1 {} {}
    cp1255 8C strict  {}       0 {} {}
    cp1255 8D tcl8    \U0000008D -1 {} {}
    cp1255 8D replace \uFFFD -1 {} {}
    cp1255 8D strict  {}       0 {} {}
    cp1255 8E tcl8    \U0000008E -1 {} {}
    cp1255 8E replace \uFFFD -1 {} {}
    cp1255 8E strict  {}       0 {} {}
    cp1255 8F tcl8    \U0000008F -1 {} {}
    cp1255 8F replace \uFFFD -1 {} {}
    cp1255 8F strict  {}       0 {} {}
    cp1255 90 tcl8    \U00000090 -1 {} {}
    cp1255 90 replace \uFFFD -1 {} {}
    cp1255 90 strict  {}       0 {} {}
    cp1255 9A tcl8    \U0000009A -1 {} {}
    cp1255 9A replace \uFFFD -1 {} {}
    cp1255 9A strict  {}       0 {} {}
    cp1255 9C tcl8    \U0000009C -1 {} {}
    cp1255 9C replace \uFFFD -1 {} {}
    cp1255 9C strict  {}       0 {} {}
    cp1255 9D tcl8    \U0000009D -1 {} {}
    cp1255 9D replace \uFFFD -1 {} {}
    cp1255 9D strict  {}       0 {} {}
    cp1255 9E tcl8    \U0000009E -1 {} {}
    cp1255 9E replace \uFFFD -1 {} {}
    cp1255 9E strict  {}       0 {} {}
    cp1255 9F tcl8    \U0000009F -1 {} {}
    cp1255 9F replace \uFFFD -1 {} {}
    cp1255 9F strict  {}       0 {} {}
    cp1255 CA tcl8    \U000000CA -1 {} {}
    cp1255 CA replace \uFFFD -1 {} {}
    cp1255 CA strict  {}       0 {} {}
    cp1255 D9 tcl8    \U000000D9 -1 {} {}
    cp1255 D9 replace \uFFFD -1 {} {}
    cp1255 D9 strict  {}       0 {} {}
    cp1255 DA tcl8    \U000000DA -1 {} {}
    cp1255 DA replace \uFFFD -1 {} {}
    cp1255 DA strict  {}       0 {} {}
    cp1255 DB tcl8    \U000000DB -1 {} {}
    cp1255 DB replace \uFFFD -1 {} {}
    cp1255 DB strict  {}       0 {} {}
    cp1255 DC tcl8    \U000000DC -1 {} {}
    cp1255 DC replace \uFFFD -1 {} {}
    cp1255 DC strict  {}       0 {} {}
    cp1255 DD tcl8    \U000000DD -1 {} {}
    cp1255 DD replace \uFFFD -1 {} {}
    cp1255 DD strict  {}       0 {} {}
    cp1255 DE tcl8    \U000000DE -1 {} {}
    cp1255 DE replace \uFFFD -1 {} {}
    cp1255 DE strict  {}       0 {} {}
    cp1255 DF tcl8    \U000000DF -1 {} {}
    cp1255 DF replace \uFFFD -1 {} {}
    cp1255 DF strict  {}       0 {} {}
    cp1255 FB tcl8    \U000000FB -1 {} {}
    cp1255 FB replace \uFFFD -1 {} {}
    cp1255 FB strict  {}       0 {} {}
    cp1255 FC tcl8    \U000000FC -1 {} {}
    cp1255 FC replace \uFFFD -1 {} {}
    cp1255 FC strict  {}       0 {} {}
    cp1255 FF tcl8    \U000000FF -1 {} {}
    cp1255 FF replace \uFFFD -1 {} {}
    cp1255 FF strict  {}       0 {} {}
}; # cp1255

# cp1255 - invalid byte sequences
lappend encUnencodableStrings {*}{
    cp1255 \U00000080 tcl8    1A -1 {} {}
    cp1255 \U00000080 replace 1A -1 {} {}
    cp1255 \U00000080 strict  {}                      0 {} {}
    cp1255 \U00000400 tcl8    1A -1 {} {}
    cp1255 \U00000400 replace 1A -1 {} {}
    cp1255 \U00000400 strict  {}                      0 {} {}
    cp1255 \U0000D800 tcl8    1A -1 {} {}
    cp1255 \U0000D800 replace 1A -1 {} {}
    cp1255 \U0000D800 strict  {}                      0 {} {}
    cp1255 \U0000DC00 tcl8    1A -1 {} {}
    cp1255 \U0000DC00 replace 1A -1 {} {}
    cp1255 \U0000DC00 strict  {}                      0 {} {}
    cp1255 \U00010000 tcl8    1A -1 {} {}
    cp1255 \U00010000 replace 1A -1 {} {}
    cp1255 \U00010000 strict  {}                      0 {} {}
    cp1255 \U0010FFFF tcl8    1A -1 {} {}
    cp1255 \U0010FFFF replace 1A -1 {} {}
    cp1255 \U0010FFFF strict  {}                      0 {} {}
}; # cp1255

#
# cp1256 (generated from glibc-CP1256-2.1.2)

test encoding-convertfrom-ucmCompare-cp1256 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches cp1256 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 00A0 A0 00A2 A2 00A3 A3 00A4 A4 00A5 A5 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AB AB 00AC AC 00AD AD 00AE AE 00AF AF 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 B8 00B9 B9 00BB BB 00BC BC 00BD BD 00BE BE 00D7 D7 00E0 E0 00E2 E2 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00EE EE 00EF EF 00F4 F4 00F7 F7 00F9 F9 00FB FB 00FC FC 0152 8C 0153 9C 0192 83 02C6 88 060C A1 061B BA 061F BF 0621 C1 0622 C2 0623 C3 0624 C4 0625 C5 0626 C6 0627 C7 0628 C8 0629 C9 062A CA 062B CB 062C CC 062D CD 062E CE 062F CF 0630 D0 0631 D1 0632 D2 0633 D3 0634 D4 0635 D5 0636 D6 0637 D8 0638 D9 0639 DA 063A DB 0640 DC 0641 DD 0642 DE 0643 DF 0644 E1 0645 E3 0646 E4 0647 E5 0648 E6 0649 EC 064A ED 064B F0 064C F1 064D F2 064E F3 064F F5 0650 F6 0651 F8 0652 FA 0679 8A 067E 81 0686 8D 0688 8F 0691 9A 0698 8E 06A9 98 06AF 90 06BA 9F 06BE AA 06C1 C0 06D2 FF 200C 9D 200D 9E 200E FD 200F FE 2013 96 2014 97 2018 91 2019 92 201A 82 201C 93 201D 94 201E 84 2020 86 2021 87 2022 95 2026 85 2030 89 2039 8B 203A 9B 20AC 80 2122 99}
} -result {}

test encoding-convertto-ucmCompare-cp1256 {Compare against ICU UCM} -body {
    ucmConverttoMismatches cp1256 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 00A0 A0 00A2 A2 00A3 A3 00A4 A4 00A5 A5 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AB AB 00AC AC 00AD AD 00AE AE 00AF AF 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 B8 00B9 B9 00BB BB 00BC BC 00BD BD 00BE BE 00D7 D7 00E0 E0 00E2 E2 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00EE EE 00EF EF 00F4 F4 00F7 F7 00F9 F9 00FB FB 00FC FC 0152 8C 0153 9C 0192 83 02C6 88 060C A1 061B BA 061F BF 0621 C1 0622 C2 0623 C3 0624 C4 0625 C5 0626 C6 0627 C7 0628 C8 0629 C9 062A CA 062B CB 062C CC 062D CD 062E CE 062F CF 0630 D0 0631 D1 0632 D2 0633 D3 0634 D4 0635 D5 0636 D6 0637 D8 0638 D9 0639 DA 063A DB 0640 DC 0641 DD 0642 DE 0643 DF 0644 E1 0645 E3 0646 E4 0647 E5 0648 E6 0649 EC 064A ED 064B F0 064C F1 064D F2 064E F3 064F F5 0650 F6 0651 F8 0652 FA 0679 8A 067E 81 0686 8D 0688 8F 0691 9A 0698 8E 06A9 98 06AF 90 06BA 9F 06BE AA 06C1 C0 06D2 FF 200C 9D 200D 9E 200E FD 200F FE 2013 96 2014 97 2018 91 2019 92 201A 82 201C 93 201D 94 201E 84 2020 86 2021 87 2022 95 2026 85 2030 89 2039 8B 203A 9B 20AC 80 2122 99}
} -result {}

# cp1256 - invalid byte sequences
lappend encInvalidBytes {*}{
}; # cp1256

# cp1256 - invalid byte sequences
lappend encUnencodableStrings {*}{
    cp1256 \U00000080 tcl8    1A -1 {} {}
    cp1256 \U00000080 replace 1A -1 {} {}
    cp1256 \U00000080 strict  {}                      0 {} {}
    cp1256 \U00000400 tcl8    1A -1 {} {}
    cp1256 \U00000400 replace 1A -1 {} {}
    cp1256 \U00000400 strict  {}                      0 {} {}
    cp1256 \U0000D800 tcl8    1A -1 {} {}
    cp1256 \U0000D800 replace 1A -1 {} {}
    cp1256 \U0000D800 strict  {}                      0 {} {}
    cp1256 \U0000DC00 tcl8    1A -1 {} {}
    cp1256 \U0000DC00 replace 1A -1 {} {}
    cp1256 \U0000DC00 strict  {}                      0 {} {}
    cp1256 \U00010000 tcl8    1A -1 {} {}
    cp1256 \U00010000 replace 1A -1 {} {}
    cp1256 \U00010000 strict  {}                      0 {} {}
    cp1256 \U0010FFFF tcl8    1A -1 {} {}
    cp1256 \U0010FFFF replace 1A -1 {} {}
    cp1256 \U0010FFFF strict  {}                      0 {} {}
}; # cp1256

#
# cp1257 (generated from glibc-CP1257-2.1.2)

test encoding-convertfrom-ucmCompare-cp1257 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches cp1257 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 00A0 A0 00A2 A2 00A3 A3 00A4 A4 00A6 A6 00A7 A7 00A8 8D 00A9 A9 00AB AB 00AC AC 00AD AD 00AE AE 00AF 9D 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 8F 00B9 B9 00BB BB 00BC BC 00BD BD 00BE BE 00C4 C4 00C5 C5 00C6 AF 00C9 C9 00D3 D3 00D5 D5 00D6 D6 00D7 D7 00D8 A8 00DC DC 00DF DF 00E4 E4 00E5 E5 00E6 BF 00E9 E9 00F3 F3 00F5 F5 00F6 F6 00F7 F7 00F8 B8 00FC FC 0100 C2 0101 E2 0104 C0 0105 E0 0106 C3 0107 E3 010C C8 010D E8 0112 C7 0113 E7 0116 CB 0117 EB 0118 C6 0119 E6 0122 CC 0123 EC 012A CE 012B EE 012E C1 012F E1 0136 CD 0137 ED 013B CF 013C EF 0141 D9 0142 F9 0143 D1 0144 F1 0145 D2 0146 F2 014C D4 014D F4 0156 AA 0157 BA 015A DA 015B FA 0160 D0 0161 F0 016A DB 016B FB 0172 D8 0173 F8 0179 CA 017A EA 017B DD 017C FD 017D DE 017E FE 02C7 8E 02D9 FF 02DB 9E 2013 96 2014 97 2018 91 2019 92 201A 82 201C 93 201D 94 201E 84 2020 86 2021 87 2022 95 2026 85 2030 89 2039 8B 203A 9B 20AC 80 2122 99}
} -result {}

test encoding-convertto-ucmCompare-cp1257 {Compare against ICU UCM} -body {
    ucmConverttoMismatches cp1257 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 00A0 A0 00A2 A2 00A3 A3 00A4 A4 00A6 A6 00A7 A7 00A8 8D 00A9 A9 00AB AB 00AC AC 00AD AD 00AE AE 00AF 9D 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 8F 00B9 B9 00BB BB 00BC BC 00BD BD 00BE BE 00C4 C4 00C5 C5 00C6 AF 00C9 C9 00D3 D3 00D5 D5 00D6 D6 00D7 D7 00D8 A8 00DC DC 00DF DF 00E4 E4 00E5 E5 00E6 BF 00E9 E9 00F3 F3 00F5 F5 00F6 F6 00F7 F7 00F8 B8 00FC FC 0100 C2 0101 E2 0104 C0 0105 E0 0106 C3 0107 E3 010C C8 010D E8 0112 C7 0113 E7 0116 CB 0117 EB 0118 C6 0119 E6 0122 CC 0123 EC 012A CE 012B EE 012E C1 012F E1 0136 CD 0137 ED 013B CF 013C EF 0141 D9 0142 F9 0143 D1 0144 F1 0145 D2 0146 F2 014C D4 014D F4 0156 AA 0157 BA 015A DA 015B FA 0160 D0 0161 F0 016A DB 016B FB 0172 D8 0173 F8 0179 CA 017A EA 017B DD 017C FD 017D DE 017E FE 02C7 8E 02D9 FF 02DB 9E 2013 96 2014 97 2018 91 2019 92 201A 82 201C 93 201D 94 201E 84 2020 86 2021 87 2022 95 2026 85 2030 89 2039 8B 203A 9B 20AC 80 2122 99}
} -result {}

# cp1257 - invalid byte sequences
lappend encInvalidBytes {*}{
    cp1257 81 tcl8    \U00000081 -1 {} {}
    cp1257 81 replace \uFFFD -1 {} {}
    cp1257 81 strict  {}       0 {} {}
    cp1257 83 tcl8    \U00000083 -1 {} {}
    cp1257 83 replace \uFFFD -1 {} {}
    cp1257 83 strict  {}       0 {} {}
    cp1257 88 tcl8    \U00000088 -1 {} {}
    cp1257 88 replace \uFFFD -1 {} {}
    cp1257 88 strict  {}       0 {} {}
    cp1257 8A tcl8    \U0000008A -1 {} {}
    cp1257 8A replace \uFFFD -1 {} {}
    cp1257 8A strict  {}       0 {} {}
    cp1257 8C tcl8    \U0000008C -1 {} {}
    cp1257 8C replace \uFFFD -1 {} {}
    cp1257 8C strict  {}       0 {} {}
    cp1257 90 tcl8    \U00000090 -1 {} {}
    cp1257 90 replace \uFFFD -1 {} {}
    cp1257 90 strict  {}       0 {} {}
    cp1257 98 tcl8    \U00000098 -1 {} {}
    cp1257 98 replace \uFFFD -1 {} {}
    cp1257 98 strict  {}       0 {} {}
    cp1257 9A tcl8    \U0000009A -1 {} {}
    cp1257 9A replace \uFFFD -1 {} {}
    cp1257 9A strict  {}       0 {} {}
    cp1257 9C tcl8    \U0000009C -1 {} {}
    cp1257 9C replace \uFFFD -1 {} {}
    cp1257 9C strict  {}       0 {} {}
    cp1257 9F tcl8    \U0000009F -1 {} {}
    cp1257 9F replace \uFFFD -1 {} {}
    cp1257 9F strict  {}       0 {} {}
    cp1257 A1 tcl8    \U000000A1 -1 {} {}
    cp1257 A1 replace \uFFFD -1 {} {}
    cp1257 A1 strict  {}       0 {} {}
    cp1257 A5 tcl8    \U000000A5 -1 {} {}
    cp1257 A5 replace \uFFFD -1 {} {}
    cp1257 A5 strict  {}       0 {} {}
}; # cp1257

# cp1257 - invalid byte sequences
lappend encUnencodableStrings {*}{
    cp1257 \U00000080 tcl8    1A -1 {} {}
    cp1257 \U00000080 replace 1A -1 {} {}
    cp1257 \U00000080 strict  {}                      0 {} {}
    cp1257 \U00000400 tcl8    1A -1 {} {}
    cp1257 \U00000400 replace 1A -1 {} {}
    cp1257 \U00000400 strict  {}                      0 {} {}
    cp1257 \U0000D800 tcl8    1A -1 {} {}
    cp1257 \U0000D800 replace 1A -1 {} {}
    cp1257 \U0000D800 strict  {}                      0 {} {}
    cp1257 \U0000DC00 tcl8    1A -1 {} {}
    cp1257 \U0000DC00 replace 1A -1 {} {}
    cp1257 \U0000DC00 strict  {}                      0 {} {}
    cp1257 \U00010000 tcl8    1A -1 {} {}
    cp1257 \U00010000 replace 1A -1 {} {}
    cp1257 \U00010000 strict  {}                      0 {} {}
    cp1257 \U0010FFFF tcl8    1A -1 {} {}
    cp1257 \U0010FFFF replace 1A -1 {} {}
    cp1257 \U0010FFFF strict  {}                      0 {} {}
}; # cp1257

#
# cp1258 (generated from glibc-CP1258-2.1.2)

test encoding-convertfrom-ucmCompare-cp1258 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches cp1258 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 00A0 A0 00A1 A1 00A2 A2 00A3 A3 00A4 A4 00A5 A5 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AA AA 00AB AB 00AC AC 00AD AD 00AE AE 00AF AF 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 B8 00B9 B9 00BA BA 00BB BB 00BC BC 00BD BD 00BE BE 00BF BF 00C0 C0 00C1 C1 00C2 C2 00C4 C4 00C5 C5 00C6 C6 00C7 C7 00C8 C8 00C9 C9 00CA CA 00CB CB 00CD CD 00CE CE 00CF CF 00D1 D1 00D3 D3 00D4 D4 00D6 D6 00D7 D7 00D8 D8 00D9 D9 00DA DA 00DB DB 00DC DC 00DF DF 00E0 E0 00E1 E1 00E2 E2 00E4 E4 00E5 E5 00E6 E6 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00ED ED 00EE EE 00EF EF 00F1 F1 00F3 F3 00F4 F4 00F6 F6 00F7 F7 00F8 F8 00F9 F9 00FA FA 00FB FB 00FC FC 00FF FF 0102 C3 0103 E3 0110 D0 0111 F0 0152 8C 0153 9C 0178 9F 0192 83 01A0 D5 01A1 F5 01AF DD 01B0 FD 02C6 88 02DC 98 0300 CC 0303 DE 0309 D2 0323 F2 2013 96 2014 97 2018 91 2019 92 201A 82 201C 93 201D 94 201E 84 2020 86 2021 87 2022 95 2026 85 2030 89 2039 8B 203A 9B 20AB FE 20AC 80 2122 99}
} -result {}

test encoding-convertto-ucmCompare-cp1258 {Compare against ICU UCM} -body {
    ucmConverttoMismatches cp1258 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 00A0 A0 00A1 A1 00A2 A2 00A3 A3 00A4 A4 00A5 A5 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AA AA 00AB AB 00AC AC 00AD AD 00AE AE 00AF AF 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 B8 00B9 B9 00BA BA 00BB BB 00BC BC 00BD BD 00BE BE 00BF BF 00C0 C0 00C1 C1 00C2 C2 00C4 C4 00C5 C5 00C6 C6 00C7 C7 00C8 C8 00C9 C9 00CA CA 00CB CB 00CD CD 00CE CE 00CF CF 00D1 D1 00D3 D3 00D4 D4 00D6 D6 00D7 D7 00D8 D8 00D9 D9 00DA DA 00DB DB 00DC DC 00DF DF 00E0 E0 00E1 E1 00E2 E2 00E4 E4 00E5 E5 00E6 E6 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00ED ED 00EE EE 00EF EF 00F1 F1 00F3 F3 00F4 F4 00F6 F6 00F7 F7 00F8 F8 00F9 F9 00FA FA 00FB FB 00FC FC 00FF FF 0102 C3 0103 E3 0110 D0 0111 F0 0152 8C 0153 9C 0178 9F 0192 83 01A0 D5 01A1 F5 01AF DD 01B0 FD 02C6 88 02DC 98 0300 CC 0303 DE 0309 D2 0323 F2 2013 96 2014 97 2018 91 2019 92 201A 82 201C 93 201D 94 201E 84 2020 86 2021 87 2022 95 2026 85 2030 89 2039 8B 203A 9B 20AB FE 20AC 80 2122 99}
} -result {}

# cp1258 - invalid byte sequences
lappend encInvalidBytes {*}{
    cp1258 81 tcl8    \U00000081 -1 {} {}
    cp1258 81 replace \uFFFD -1 {} {}
    cp1258 81 strict  {}       0 {} {}
    cp1258 8A tcl8    \U0000008A -1 {} {}
    cp1258 8A replace \uFFFD -1 {} {}
    cp1258 8A strict  {}       0 {} {}
    cp1258 8D tcl8    \U0000008D -1 {} {}
    cp1258 8D replace \uFFFD -1 {} {}
    cp1258 8D strict  {}       0 {} {}
    cp1258 8E tcl8    \U0000008E -1 {} {}
    cp1258 8E replace \uFFFD -1 {} {}
    cp1258 8E strict  {}       0 {} {}
    cp1258 8F tcl8    \U0000008F -1 {} {}
    cp1258 8F replace \uFFFD -1 {} {}
    cp1258 8F strict  {}       0 {} {}
    cp1258 90 tcl8    \U00000090 -1 {} {}
    cp1258 90 replace \uFFFD -1 {} {}
    cp1258 90 strict  {}       0 {} {}
    cp1258 9A tcl8    \U0000009A -1 {} {}
    cp1258 9A replace \uFFFD -1 {} {}
    cp1258 9A strict  {}       0 {} {}
    cp1258 9D tcl8    \U0000009D -1 {} {}
    cp1258 9D replace \uFFFD -1 {} {}
    cp1258 9D strict  {}       0 {} {}
    cp1258 9E tcl8    \U0000009E -1 {} {}
    cp1258 9E replace \uFFFD -1 {} {}
    cp1258 9E strict  {}       0 {} {}
    cp1258 EC tcl8    \U000000EC -1 {} {}
    cp1258 EC replace \uFFFD -1 {} {}
    cp1258 EC strict  {}       0 {} {}
}; # cp1258

# cp1258 - invalid byte sequences
lappend encUnencodableStrings {*}{
    cp1258 \U00000080 tcl8    1A -1 {} {}
    cp1258 \U00000080 replace 1A -1 {} {}
    cp1258 \U00000080 strict  {}                      0 {} {}
    cp1258 \U00000400 tcl8    1A -1 {} {}
    cp1258 \U00000400 replace 1A -1 {} {}
    cp1258 \U00000400 strict  {}                      0 {} {}
    cp1258 \U0000D800 tcl8    1A -1 {} {}
    cp1258 \U0000D800 replace 1A -1 {} {}
    cp1258 \U0000D800 strict  {}                      0 {} {}
    cp1258 \U0000DC00 tcl8    1A -1 {} {}
    cp1258 \U0000DC00 replace 1A -1 {} {}
    cp1258 \U0000DC00 strict  {}                      0 {} {}
    cp1258 \U00010000 tcl8    1A -1 {} {}
    cp1258 \U00010000 replace 1A -1 {} {}
    cp1258 \U00010000 strict  {}                      0 {} {}
    cp1258 \U0010FFFF tcl8    1A -1 {} {}
    cp1258 \U0010FFFF replace 1A -1 {} {}
    cp1258 \U0010FFFF strict  {}                      0 {} {}
}; # cp1258

#
# gb1988 (generated from glibc-GB_1988_80-2.3.3)

test encoding-convertfrom-ucmCompare-gb1988 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches gb1988 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007F 7F 00A5 24 203E 7E}
} -result {}

test encoding-convertto-ucmCompare-gb1988 {Compare against ICU UCM} -body {
    ucmConverttoMismatches gb1988 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007F 7F 00A5 24 203E 7E}
} -result {}

# gb1988 - invalid byte sequences
lappend encInvalidBytes {*}{
    gb1988 80 tcl8    \U00000080 -1 {} {}
    gb1988 80 replace \uFFFD -1 {} {}
    gb1988 80 strict  {}       0 {} {}
    gb1988 81 tcl8    \U00000081 -1 {} {}
    gb1988 81 replace \uFFFD -1 {} {}
    gb1988 81 strict  {}       0 {} {}
    gb1988 82 tcl8    \U00000082 -1 {} {}
    gb1988 82 replace \uFFFD -1 {} {}
    gb1988 82 strict  {}       0 {} {}
    gb1988 83 tcl8    \U00000083 -1 {} {}
    gb1988 83 replace \uFFFD -1 {} {}
    gb1988 83 strict  {}       0 {} {}
    gb1988 84 tcl8    \U00000084 -1 {} {}
    gb1988 84 replace \uFFFD -1 {} {}
    gb1988 84 strict  {}       0 {} {}
    gb1988 85 tcl8    \U00000085 -1 {} {}
    gb1988 85 replace \uFFFD -1 {} {}
    gb1988 85 strict  {}       0 {} {}
    gb1988 86 tcl8    \U00000086 -1 {} {}
    gb1988 86 replace \uFFFD -1 {} {}
    gb1988 86 strict  {}       0 {} {}
    gb1988 87 tcl8    \U00000087 -1 {} {}
    gb1988 87 replace \uFFFD -1 {} {}
    gb1988 87 strict  {}       0 {} {}
    gb1988 88 tcl8    \U00000088 -1 {} {}
    gb1988 88 replace \uFFFD -1 {} {}
    gb1988 88 strict  {}       0 {} {}
    gb1988 89 tcl8    \U00000089 -1 {} {}
    gb1988 89 replace \uFFFD -1 {} {}
    gb1988 89 strict  {}       0 {} {}
    gb1988 8A tcl8    \U0000008A -1 {} {}
    gb1988 8A replace \uFFFD -1 {} {}
    gb1988 8A strict  {}       0 {} {}
    gb1988 8B tcl8    \U0000008B -1 {} {}
    gb1988 8B replace \uFFFD -1 {} {}
    gb1988 8B strict  {}       0 {} {}
    gb1988 8C tcl8    \U0000008C -1 {} {}
    gb1988 8C replace \uFFFD -1 {} {}
    gb1988 8C strict  {}       0 {} {}
    gb1988 8D tcl8    \U0000008D -1 {} {}
    gb1988 8D replace \uFFFD -1 {} {}
    gb1988 8D strict  {}       0 {} {}
    gb1988 8E tcl8    \U0000008E -1 {} {}
    gb1988 8E replace \uFFFD -1 {} {}
    gb1988 8E strict  {}       0 {} {}
    gb1988 8F tcl8    \U0000008F -1 {} {}
    gb1988 8F replace \uFFFD -1 {} {}
    gb1988 8F strict  {}       0 {} {}
    gb1988 90 tcl8    \U00000090 -1 {} {}
    gb1988 90 replace \uFFFD -1 {} {}
    gb1988 90 strict  {}       0 {} {}
    gb1988 91 tcl8    \U00000091 -1 {} {}
    gb1988 91 replace \uFFFD -1 {} {}
    gb1988 91 strict  {}       0 {} {}
    gb1988 92 tcl8    \U00000092 -1 {} {}
    gb1988 92 replace \uFFFD -1 {} {}
    gb1988 92 strict  {}       0 {} {}
    gb1988 93 tcl8    \U00000093 -1 {} {}
    gb1988 93 replace \uFFFD -1 {} {}
    gb1988 93 strict  {}       0 {} {}
    gb1988 94 tcl8    \U00000094 -1 {} {}
    gb1988 94 replace \uFFFD -1 {} {}
    gb1988 94 strict  {}       0 {} {}
    gb1988 95 tcl8    \U00000095 -1 {} {}
    gb1988 95 replace \uFFFD -1 {} {}
    gb1988 95 strict  {}       0 {} {}
    gb1988 96 tcl8    \U00000096 -1 {} {}
    gb1988 96 replace \uFFFD -1 {} {}
    gb1988 96 strict  {}       0 {} {}
    gb1988 97 tcl8    \U00000097 -1 {} {}
    gb1988 97 replace \uFFFD -1 {} {}
    gb1988 97 strict  {}       0 {} {}
    gb1988 98 tcl8    \U00000098 -1 {} {}
    gb1988 98 replace \uFFFD -1 {} {}
    gb1988 98 strict  {}       0 {} {}
    gb1988 99 tcl8    \U00000099 -1 {} {}
    gb1988 99 replace \uFFFD -1 {} {}
    gb1988 99 strict  {}       0 {} {}
    gb1988 9A tcl8    \U0000009A -1 {} {}
    gb1988 9A replace \uFFFD -1 {} {}
    gb1988 9A strict  {}       0 {} {}
    gb1988 9B tcl8    \U0000009B -1 {} {}
    gb1988 9B replace \uFFFD -1 {} {}
    gb1988 9B strict  {}       0 {} {}
    gb1988 9C tcl8    \U0000009C -1 {} {}
    gb1988 9C replace \uFFFD -1 {} {}
    gb1988 9C strict  {}       0 {} {}
    gb1988 9D tcl8    \U0000009D -1 {} {}
    gb1988 9D replace \uFFFD -1 {} {}
    gb1988 9D strict  {}       0 {} {}
    gb1988 9E tcl8    \U0000009E -1 {} {}
    gb1988 9E replace \uFFFD -1 {} {}
    gb1988 9E strict  {}       0 {} {}
    gb1988 9F tcl8    \U0000009F -1 {} {}
    gb1988 9F replace \uFFFD -1 {} {}
    gb1988 9F strict  {}       0 {} {}
    gb1988 A0 tcl8    \U000000A0 -1 {} {}
    gb1988 A0 replace \uFFFD -1 {} {}
    gb1988 A0 strict  {}       0 {} {}
    gb1988 A1 tcl8    \U000000A1 -1 {} {}
    gb1988 A1 replace \uFFFD -1 {} {}
    gb1988 A1 strict  {}       0 {} {}
    gb1988 A2 tcl8    \U000000A2 -1 {} {}
    gb1988 A2 replace \uFFFD -1 {} {}
    gb1988 A2 strict  {}       0 {} {}
    gb1988 A3 tcl8    \U000000A3 -1 {} {}
    gb1988 A3 replace \uFFFD -1 {} {}
    gb1988 A3 strict  {}       0 {} {}
    gb1988 A4 tcl8    \U000000A4 -1 {} {}
    gb1988 A4 replace \uFFFD -1 {} {}
    gb1988 A4 strict  {}       0 {} {}
    gb1988 A5 tcl8    \U000000A5 -1 {} {}
    gb1988 A5 replace \uFFFD -1 {} {}
    gb1988 A5 strict  {}       0 {} {}
    gb1988 A6 tcl8    \U000000A6 -1 {} {}
    gb1988 A6 replace \uFFFD -1 {} {}
    gb1988 A6 strict  {}       0 {} {}
    gb1988 A7 tcl8    \U000000A7 -1 {} {}
    gb1988 A7 replace \uFFFD -1 {} {}
    gb1988 A7 strict  {}       0 {} {}
    gb1988 A8 tcl8    \U000000A8 -1 {} {}
    gb1988 A8 replace \uFFFD -1 {} {}
    gb1988 A8 strict  {}       0 {} {}
    gb1988 A9 tcl8    \U000000A9 -1 {} {}
    gb1988 A9 replace \uFFFD -1 {} {}
    gb1988 A9 strict  {}       0 {} {}
    gb1988 AA tcl8    \U000000AA -1 {} {}
    gb1988 AA replace \uFFFD -1 {} {}
    gb1988 AA strict  {}       0 {} {}
    gb1988 AB tcl8    \U000000AB -1 {} {}
    gb1988 AB replace \uFFFD -1 {} {}
    gb1988 AB strict  {}       0 {} {}
    gb1988 AC tcl8    \U000000AC -1 {} {}
    gb1988 AC replace \uFFFD -1 {} {}
    gb1988 AC strict  {}       0 {} {}
    gb1988 AD tcl8    \U000000AD -1 {} {}
    gb1988 AD replace \uFFFD -1 {} {}
    gb1988 AD strict  {}       0 {} {}
    gb1988 AE tcl8    \U000000AE -1 {} {}
    gb1988 AE replace \uFFFD -1 {} {}
    gb1988 AE strict  {}       0 {} {}
    gb1988 AF tcl8    \U000000AF -1 {} {}
    gb1988 AF replace \uFFFD -1 {} {}
    gb1988 AF strict  {}       0 {} {}
    gb1988 B0 tcl8    \U000000B0 -1 {} {}
    gb1988 B0 replace \uFFFD -1 {} {}
    gb1988 B0 strict  {}       0 {} {}
    gb1988 B1 tcl8    \U000000B1 -1 {} {}
    gb1988 B1 replace \uFFFD -1 {} {}
    gb1988 B1 strict  {}       0 {} {}
    gb1988 B2 tcl8    \U000000B2 -1 {} {}
    gb1988 B2 replace \uFFFD -1 {} {}
    gb1988 B2 strict  {}       0 {} {}
    gb1988 B3 tcl8    \U000000B3 -1 {} {}
    gb1988 B3 replace \uFFFD -1 {} {}
    gb1988 B3 strict  {}       0 {} {}
    gb1988 B4 tcl8    \U000000B4 -1 {} {}
    gb1988 B4 replace \uFFFD -1 {} {}
    gb1988 B4 strict  {}       0 {} {}
    gb1988 B5 tcl8    \U000000B5 -1 {} {}
    gb1988 B5 replace \uFFFD -1 {} {}
    gb1988 B5 strict  {}       0 {} {}
    gb1988 B6 tcl8    \U000000B6 -1 {} {}
    gb1988 B6 replace \uFFFD -1 {} {}
    gb1988 B6 strict  {}       0 {} {}
    gb1988 B7 tcl8    \U000000B7 -1 {} {}
    gb1988 B7 replace \uFFFD -1 {} {}
    gb1988 B7 strict  {}       0 {} {}
    gb1988 B8 tcl8    \U000000B8 -1 {} {}
    gb1988 B8 replace \uFFFD -1 {} {}
    gb1988 B8 strict  {}       0 {} {}
    gb1988 B9 tcl8    \U000000B9 -1 {} {}
    gb1988 B9 replace \uFFFD -1 {} {}
    gb1988 B9 strict  {}       0 {} {}
    gb1988 BA tcl8    \U000000BA -1 {} {}
    gb1988 BA replace \uFFFD -1 {} {}
    gb1988 BA strict  {}       0 {} {}
    gb1988 BB tcl8    \U000000BB -1 {} {}
    gb1988 BB replace \uFFFD -1 {} {}
    gb1988 BB strict  {}       0 {} {}
    gb1988 BC tcl8    \U000000BC -1 {} {}
    gb1988 BC replace \uFFFD -1 {} {}
    gb1988 BC strict  {}       0 {} {}
    gb1988 BD tcl8    \U000000BD -1 {} {}
    gb1988 BD replace \uFFFD -1 {} {}
    gb1988 BD strict  {}       0 {} {}
    gb1988 BE tcl8    \U000000BE -1 {} {}
    gb1988 BE replace \uFFFD -1 {} {}
    gb1988 BE strict  {}       0 {} {}
    gb1988 BF tcl8    \U000000BF -1 {} {}
    gb1988 BF replace \uFFFD -1 {} {}
    gb1988 BF strict  {}       0 {} {}
    gb1988 C0 tcl8    \U000000C0 -1 {} {}
    gb1988 C0 replace \uFFFD -1 {} {}
    gb1988 C0 strict  {}       0 {} {}
    gb1988 C1 tcl8    \U000000C1 -1 {} {}
    gb1988 C1 replace \uFFFD -1 {} {}
    gb1988 C1 strict  {}       0 {} {}
    gb1988 C2 tcl8    \U000000C2 -1 {} {}
    gb1988 C2 replace \uFFFD -1 {} {}
    gb1988 C2 strict  {}       0 {} {}
    gb1988 C3 tcl8    \U000000C3 -1 {} {}
    gb1988 C3 replace \uFFFD -1 {} {}
    gb1988 C3 strict  {}       0 {} {}
    gb1988 C4 tcl8    \U000000C4 -1 {} {}
    gb1988 C4 replace \uFFFD -1 {} {}
    gb1988 C4 strict  {}       0 {} {}
    gb1988 C5 tcl8    \U000000C5 -1 {} {}
    gb1988 C5 replace \uFFFD -1 {} {}
    gb1988 C5 strict  {}       0 {} {}
    gb1988 C6 tcl8    \U000000C6 -1 {} {}
    gb1988 C6 replace \uFFFD -1 {} {}
    gb1988 C6 strict  {}       0 {} {}
    gb1988 C7 tcl8    \U000000C7 -1 {} {}
    gb1988 C7 replace \uFFFD -1 {} {}
    gb1988 C7 strict  {}       0 {} {}
    gb1988 C8 tcl8    \U000000C8 -1 {} {}
    gb1988 C8 replace \uFFFD -1 {} {}
    gb1988 C8 strict  {}       0 {} {}
    gb1988 C9 tcl8    \U000000C9 -1 {} {}
    gb1988 C9 replace \uFFFD -1 {} {}
    gb1988 C9 strict  {}       0 {} {}
    gb1988 CA tcl8    \U000000CA -1 {} {}
    gb1988 CA replace \uFFFD -1 {} {}
    gb1988 CA strict  {}       0 {} {}
    gb1988 CB tcl8    \U000000CB -1 {} {}
    gb1988 CB replace \uFFFD -1 {} {}
    gb1988 CB strict  {}       0 {} {}
    gb1988 CC tcl8    \U000000CC -1 {} {}
    gb1988 CC replace \uFFFD -1 {} {}
    gb1988 CC strict  {}       0 {} {}
    gb1988 CD tcl8    \U000000CD -1 {} {}
    gb1988 CD replace \uFFFD -1 {} {}
    gb1988 CD strict  {}       0 {} {}
    gb1988 CE tcl8    \U000000CE -1 {} {}
    gb1988 CE replace \uFFFD -1 {} {}
    gb1988 CE strict  {}       0 {} {}
    gb1988 CF tcl8    \U000000CF -1 {} {}
    gb1988 CF replace \uFFFD -1 {} {}
    gb1988 CF strict  {}       0 {} {}
    gb1988 D0 tcl8    \U000000D0 -1 {} {}
    gb1988 D0 replace \uFFFD -1 {} {}
    gb1988 D0 strict  {}       0 {} {}
    gb1988 D1 tcl8    \U000000D1 -1 {} {}
    gb1988 D1 replace \uFFFD -1 {} {}
    gb1988 D1 strict  {}       0 {} {}
    gb1988 D2 tcl8    \U000000D2 -1 {} {}
    gb1988 D2 replace \uFFFD -1 {} {}
    gb1988 D2 strict  {}       0 {} {}
    gb1988 D3 tcl8    \U000000D3 -1 {} {}
    gb1988 D3 replace \uFFFD -1 {} {}
    gb1988 D3 strict  {}       0 {} {}
    gb1988 D4 tcl8    \U000000D4 -1 {} {}
    gb1988 D4 replace \uFFFD -1 {} {}
    gb1988 D4 strict  {}       0 {} {}
    gb1988 D5 tcl8    \U000000D5 -1 {} {}
    gb1988 D5 replace \uFFFD -1 {} {}
    gb1988 D5 strict  {}       0 {} {}
    gb1988 D6 tcl8    \U000000D6 -1 {} {}
    gb1988 D6 replace \uFFFD -1 {} {}
    gb1988 D6 strict  {}       0 {} {}
    gb1988 D7 tcl8    \U000000D7 -1 {} {}
    gb1988 D7 replace \uFFFD -1 {} {}
    gb1988 D7 strict  {}       0 {} {}
    gb1988 D8 tcl8    \U000000D8 -1 {} {}
    gb1988 D8 replace \uFFFD -1 {} {}
    gb1988 D8 strict  {}       0 {} {}
    gb1988 D9 tcl8    \U000000D9 -1 {} {}
    gb1988 D9 replace \uFFFD -1 {} {}
    gb1988 D9 strict  {}       0 {} {}
    gb1988 DA tcl8    \U000000DA -1 {} {}
    gb1988 DA replace \uFFFD -1 {} {}
    gb1988 DA strict  {}       0 {} {}
    gb1988 DB tcl8    \U000000DB -1 {} {}
    gb1988 DB replace \uFFFD -1 {} {}
    gb1988 DB strict  {}       0 {} {}
    gb1988 DC tcl8    \U000000DC -1 {} {}
    gb1988 DC replace \uFFFD -1 {} {}
    gb1988 DC strict  {}       0 {} {}
    gb1988 DD tcl8    \U000000DD -1 {} {}
    gb1988 DD replace \uFFFD -1 {} {}
    gb1988 DD strict  {}       0 {} {}
    gb1988 DE tcl8    \U000000DE -1 {} {}
    gb1988 DE replace \uFFFD -1 {} {}
    gb1988 DE strict  {}       0 {} {}
    gb1988 DF tcl8    \U000000DF -1 {} {}
    gb1988 DF replace \uFFFD -1 {} {}
    gb1988 DF strict  {}       0 {} {}
    gb1988 E0 tcl8    \U000000E0 -1 {} {}
    gb1988 E0 replace \uFFFD -1 {} {}
    gb1988 E0 strict  {}       0 {} {}
    gb1988 E1 tcl8    \U000000E1 -1 {} {}
    gb1988 E1 replace \uFFFD -1 {} {}
    gb1988 E1 strict  {}       0 {} {}
    gb1988 E2 tcl8    \U000000E2 -1 {} {}
    gb1988 E2 replace \uFFFD -1 {} {}
    gb1988 E2 strict  {}       0 {} {}
    gb1988 E3 tcl8    \U000000E3 -1 {} {}
    gb1988 E3 replace \uFFFD -1 {} {}
    gb1988 E3 strict  {}       0 {} {}
    gb1988 E4 tcl8    \U000000E4 -1 {} {}
    gb1988 E4 replace \uFFFD -1 {} {}
    gb1988 E4 strict  {}       0 {} {}
    gb1988 E5 tcl8    \U000000E5 -1 {} {}
    gb1988 E5 replace \uFFFD -1 {} {}
    gb1988 E5 strict  {}       0 {} {}
    gb1988 E6 tcl8    \U000000E6 -1 {} {}
    gb1988 E6 replace \uFFFD -1 {} {}
    gb1988 E6 strict  {}       0 {} {}
    gb1988 E7 tcl8    \U000000E7 -1 {} {}
    gb1988 E7 replace \uFFFD -1 {} {}
    gb1988 E7 strict  {}       0 {} {}
    gb1988 E8 tcl8    \U000000E8 -1 {} {}
    gb1988 E8 replace \uFFFD -1 {} {}
    gb1988 E8 strict  {}       0 {} {}
    gb1988 E9 tcl8    \U000000E9 -1 {} {}
    gb1988 E9 replace \uFFFD -1 {} {}
    gb1988 E9 strict  {}       0 {} {}
    gb1988 EA tcl8    \U000000EA -1 {} {}
    gb1988 EA replace \uFFFD -1 {} {}
    gb1988 EA strict  {}       0 {} {}
    gb1988 EB tcl8    \U000000EB -1 {} {}
    gb1988 EB replace \uFFFD -1 {} {}
    gb1988 EB strict  {}       0 {} {}
    gb1988 EC tcl8    \U000000EC -1 {} {}
    gb1988 EC replace \uFFFD -1 {} {}
    gb1988 EC strict  {}       0 {} {}
    gb1988 ED tcl8    \U000000ED -1 {} {}
    gb1988 ED replace \uFFFD -1 {} {}
    gb1988 ED strict  {}       0 {} {}
    gb1988 EE tcl8    \U000000EE -1 {} {}
    gb1988 EE replace \uFFFD -1 {} {}
    gb1988 EE strict  {}       0 {} {}
    gb1988 EF tcl8    \U000000EF -1 {} {}
    gb1988 EF replace \uFFFD -1 {} {}
    gb1988 EF strict  {}       0 {} {}
    gb1988 F0 tcl8    \U000000F0 -1 {} {}
    gb1988 F0 replace \uFFFD -1 {} {}
    gb1988 F0 strict  {}       0 {} {}
    gb1988 F1 tcl8    \U000000F1 -1 {} {}
    gb1988 F1 replace \uFFFD -1 {} {}
    gb1988 F1 strict  {}       0 {} {}
    gb1988 F2 tcl8    \U000000F2 -1 {} {}
    gb1988 F2 replace \uFFFD -1 {} {}
    gb1988 F2 strict  {}       0 {} {}
    gb1988 F3 tcl8    \U000000F3 -1 {} {}
    gb1988 F3 replace \uFFFD -1 {} {}
    gb1988 F3 strict  {}       0 {} {}
    gb1988 F4 tcl8    \U000000F4 -1 {} {}
    gb1988 F4 replace \uFFFD -1 {} {}
    gb1988 F4 strict  {}       0 {} {}
    gb1988 F5 tcl8    \U000000F5 -1 {} {}
    gb1988 F5 replace \uFFFD -1 {} {}
    gb1988 F5 strict  {}       0 {} {}
    gb1988 F6 tcl8    \U000000F6 -1 {} {}
    gb1988 F6 replace \uFFFD -1 {} {}
    gb1988 F6 strict  {}       0 {} {}
    gb1988 F7 tcl8    \U000000F7 -1 {} {}
    gb1988 F7 replace \uFFFD -1 {} {}
    gb1988 F7 strict  {}       0 {} {}
    gb1988 F8 tcl8    \U000000F8 -1 {} {}
    gb1988 F8 replace \uFFFD -1 {} {}
    gb1988 F8 strict  {}       0 {} {}
    gb1988 F9 tcl8    \U000000F9 -1 {} {}
    gb1988 F9 replace \uFFFD -1 {} {}
    gb1988 F9 strict  {}       0 {} {}
    gb1988 FA tcl8    \U000000FA -1 {} {}
    gb1988 FA replace \uFFFD -1 {} {}
    gb1988 FA strict  {}       0 {} {}
    gb1988 FB tcl8    \U000000FB -1 {} {}
    gb1988 FB replace \uFFFD -1 {} {}
    gb1988 FB strict  {}       0 {} {}
    gb1988 FC tcl8    \U000000FC -1 {} {}
    gb1988 FC replace \uFFFD -1 {} {}
    gb1988 FC strict  {}       0 {} {}
    gb1988 FD tcl8    \U000000FD -1 {} {}
    gb1988 FD replace \uFFFD -1 {} {}
    gb1988 FD strict  {}       0 {} {}
    gb1988 FE tcl8    \U000000FE -1 {} {}
    gb1988 FE replace \uFFFD -1 {} {}
    gb1988 FE strict  {}       0 {} {}
    gb1988 FF tcl8    \U000000FF -1 {} {}
    gb1988 FF replace \uFFFD -1 {} {}
    gb1988 FF strict  {}       0 {} {}
}; # gb1988

# gb1988 - invalid byte sequences
lappend encUnencodableStrings {*}{
    gb1988 \U00000024 tcl8    1A -1 {} {}
    gb1988 \U00000024 replace 1A -1 {} {}
    gb1988 \U00000024 strict  {}                      0 {} {}
    gb1988 \U00000400 tcl8    1A -1 {} {}
    gb1988 \U00000400 replace 1A -1 {} {}
    gb1988 \U00000400 strict  {}                      0 {} {}
    gb1988 \U0000D800 tcl8    1A -1 {} {}
    gb1988 \U0000D800 replace 1A -1 {} {}
    gb1988 \U0000D800 strict  {}                      0 {} {}
    gb1988 \U0000DC00 tcl8    1A -1 {} {}
    gb1988 \U0000DC00 replace 1A -1 {} {}
    gb1988 \U0000DC00 strict  {}                      0 {} {}
    gb1988 \U00010000 tcl8    1A -1 {} {}
    gb1988 \U00010000 replace 1A -1 {} {}
    gb1988 \U00010000 strict  {}                      0 {} {}
    gb1988 \U0010FFFF tcl8    1A -1 {} {}
    gb1988 \U0010FFFF replace 1A -1 {} {}
    gb1988 \U0010FFFF strict  {}                      0 {} {}
}; # gb1988

#
# iso8859-1 (generated from glibc-ISO_8859_1-2.1.2)

test encoding-convertfrom-ucmCompare-iso8859-1 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches iso8859-1 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A1 A1 00A2 A2 00A3 A3 00A4 A4 00A5 A5 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AA AA 00AB AB 00AC AC 00AD AD 00AE AE 00AF AF 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 B8 00B9 B9 00BA BA 00BB BB 00BC BC 00BD BD 00BE BE 00BF BF 00C0 C0 00C1 C1 00C2 C2 00C3 C3 00C4 C4 00C5 C5 00C6 C6 00C7 C7 00C8 C8 00C9 C9 00CA CA 00CB CB 00CC CC 00CD CD 00CE CE 00CF CF 00D0 D0 00D1 D1 00D2 D2 00D3 D3 00D4 D4 00D5 D5 00D6 D6 00D7 D7 00D8 D8 00D9 D9 00DA DA 00DB DB 00DC DC 00DD DD 00DE DE 00DF DF 00E0 E0 00E1 E1 00E2 E2 00E3 E3 00E4 E4 00E5 E5 00E6 E6 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00EC EC 00ED ED 00EE EE 00EF EF 00F0 F0 00F1 F1 00F2 F2 00F3 F3 00F4 F4 00F5 F5 00F6 F6 00F7 F7 00F8 F8 00F9 F9 00FA FA 00FB FB 00FC FC 00FD FD 00FE FE 00FF FF}
} -result {}

test encoding-convertto-ucmCompare-iso8859-1 {Compare against ICU UCM} -body {
    ucmConverttoMismatches iso8859-1 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A1 A1 00A2 A2 00A3 A3 00A4 A4 00A5 A5 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AA AA 00AB AB 00AC AC 00AD AD 00AE AE 00AF AF 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 B8 00B9 B9 00BA BA 00BB BB 00BC BC 00BD BD 00BE BE 00BF BF 00C0 C0 00C1 C1 00C2 C2 00C3 C3 00C4 C4 00C5 C5 00C6 C6 00C7 C7 00C8 C8 00C9 C9 00CA CA 00CB CB 00CC CC 00CD CD 00CE CE 00CF CF 00D0 D0 00D1 D1 00D2 D2 00D3 D3 00D4 D4 00D5 D5 00D6 D6 00D7 D7 00D8 D8 00D9 D9 00DA DA 00DB DB 00DC DC 00DD DD 00DE DE 00DF DF 00E0 E0 00E1 E1 00E2 E2 00E3 E3 00E4 E4 00E5 E5 00E6 E6 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00EC EC 00ED ED 00EE EE 00EF EF 00F0 F0 00F1 F1 00F2 F2 00F3 F3 00F4 F4 00F5 F5 00F6 F6 00F7 F7 00F8 F8 00F9 F9 00FA FA 00FB FB 00FC FC 00FD FD 00FE FE 00FF FF}
} -result {}

# iso8859-1 - invalid byte sequences
lappend encInvalidBytes {*}{
}; # iso8859-1

# iso8859-1 - invalid byte sequences
lappend encUnencodableStrings {*}{
    iso8859-1 \U00000400 tcl8    1A -1 {} {}
    iso8859-1 \U00000400 replace 1A -1 {} {}
    iso8859-1 \U00000400 strict  {}                      0 {} {}
    iso8859-1 \U0000D800 tcl8    1A -1 {} {}
    iso8859-1 \U0000D800 replace 1A -1 {} {}
    iso8859-1 \U0000D800 strict  {}                      0 {} {}
    iso8859-1 \U0000DC00 tcl8    1A -1 {} {}
    iso8859-1 \U0000DC00 replace 1A -1 {} {}
    iso8859-1 \U0000DC00 strict  {}                      0 {} {}
    iso8859-1 \U00010000 tcl8    1A -1 {} {}
    iso8859-1 \U00010000 replace 1A -1 {} {}
    iso8859-1 \U00010000 strict  {}                      0 {} {}
    iso8859-1 \U0010FFFF tcl8    1A -1 {} {}
    iso8859-1 \U0010FFFF replace 1A -1 {} {}
    iso8859-1 \U0010FFFF strict  {}                      0 {} {}
}; # iso8859-1

#
# iso8859-2 (generated from glibc-ISO_8859_2-2.1.2)

test encoding-convertfrom-ucmCompare-iso8859-2 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches iso8859-2 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A4 A4 00A7 A7 00A8 A8 00AD AD 00B0 B0 00B4 B4 00B8 B8 00C1 C1 00C2 C2 00C4 C4 00C7 C7 00C9 C9 00CB CB 00CD CD 00CE CE 00D3 D3 00D4 D4 00D6 D6 00D7 D7 00DA DA 00DC DC 00DD DD 00DF DF 00E1 E1 00E2 E2 00E4 E4 00E7 E7 00E9 E9 00EB EB 00ED ED 00EE EE 00F3 F3 00F4 F4 00F6 F6 00F7 F7 00FA FA 00FC FC 00FD FD 0102 C3 0103 E3 0104 A1 0105 B1 0106 C6 0107 E6 010C C8 010D E8 010E CF 010F EF 0110 D0 0111 F0 0118 CA 0119 EA 011A CC 011B EC 0139 C5 013A E5 013D A5 013E B5 0141 A3 0142 B3 0143 D1 0144 F1 0147 D2 0148 F2 0150 D5 0151 F5 0154 C0 0155 E0 0158 D8 0159 F8 015A A6 015B B6 015E AA 015F BA 0160 A9 0161 B9 0162 DE 0163 FE 0164 AB 0165 BB 016E D9 016F F9 0170 DB 0171 FB 0179 AC 017A BC 017B AF 017C BF 017D AE 017E BE 02C7 B7 02D8 A2 02D9 FF 02DB B2 02DD BD}
} -result {}

test encoding-convertto-ucmCompare-iso8859-2 {Compare against ICU UCM} -body {
    ucmConverttoMismatches iso8859-2 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A4 A4 00A7 A7 00A8 A8 00AD AD 00B0 B0 00B4 B4 00B8 B8 00C1 C1 00C2 C2 00C4 C4 00C7 C7 00C9 C9 00CB CB 00CD CD 00CE CE 00D3 D3 00D4 D4 00D6 D6 00D7 D7 00DA DA 00DC DC 00DD DD 00DF DF 00E1 E1 00E2 E2 00E4 E4 00E7 E7 00E9 E9 00EB EB 00ED ED 00EE EE 00F3 F3 00F4 F4 00F6 F6 00F7 F7 00FA FA 00FC FC 00FD FD 0102 C3 0103 E3 0104 A1 0105 B1 0106 C6 0107 E6 010C C8 010D E8 010E CF 010F EF 0110 D0 0111 F0 0118 CA 0119 EA 011A CC 011B EC 0139 C5 013A E5 013D A5 013E B5 0141 A3 0142 B3 0143 D1 0144 F1 0147 D2 0148 F2 0150 D5 0151 F5 0154 C0 0155 E0 0158 D8 0159 F8 015A A6 015B B6 015E AA 015F BA 0160 A9 0161 B9 0162 DE 0163 FE 0164 AB 0165 BB 016E D9 016F F9 0170 DB 0171 FB 0179 AC 017A BC 017B AF 017C BF 017D AE 017E BE 02C7 B7 02D8 A2 02D9 FF 02DB B2 02DD BD}
} -result {}

# iso8859-2 - invalid byte sequences
lappend encInvalidBytes {*}{
}; # iso8859-2

# iso8859-2 - invalid byte sequences
lappend encUnencodableStrings {*}{
    iso8859-2 \U000000A1 tcl8    1A -1 {} {}
    iso8859-2 \U000000A1 replace 1A -1 {} {}
    iso8859-2 \U000000A1 strict  {}                      0 {} {}
    iso8859-2 \U00000400 tcl8    1A -1 {} {}
    iso8859-2 \U00000400 replace 1A -1 {} {}
    iso8859-2 \U00000400 strict  {}                      0 {} {}
    iso8859-2 \U0000D800 tcl8    1A -1 {} {}
    iso8859-2 \U0000D800 replace 1A -1 {} {}
    iso8859-2 \U0000D800 strict  {}                      0 {} {}
    iso8859-2 \U0000DC00 tcl8    1A -1 {} {}
    iso8859-2 \U0000DC00 replace 1A -1 {} {}
    iso8859-2 \U0000DC00 strict  {}                      0 {} {}
    iso8859-2 \U00010000 tcl8    1A -1 {} {}
    iso8859-2 \U00010000 replace 1A -1 {} {}
    iso8859-2 \U00010000 strict  {}                      0 {} {}
    iso8859-2 \U0010FFFF tcl8    1A -1 {} {}
    iso8859-2 \U0010FFFF replace 1A -1 {} {}
    iso8859-2 \U0010FFFF strict  {}                      0 {} {}
}; # iso8859-2

#
# iso8859-3 (generated from glibc-ISO_8859_3-2.1.2)

test encoding-convertfrom-ucmCompare-iso8859-3 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches iso8859-3 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A3 A3 00A4 A4 00A7 A7 00A8 A8 00AD AD 00B0 B0 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B7 B7 00B8 B8 00BD BD 00C0 C0 00C1 C1 00C2 C2 00C4 C4 00C7 C7 00C8 C8 00C9 C9 00CA CA 00CB CB 00CC CC 00CD CD 00CE CE 00CF CF 00D1 D1 00D2 D2 00D3 D3 00D4 D4 00D6 D6 00D7 D7 00D9 D9 00DA DA 00DB DB 00DC DC 00DF DF 00E0 E0 00E1 E1 00E2 E2 00E4 E4 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00EC EC 00ED ED 00EE EE 00EF EF 00F1 F1 00F2 F2 00F3 F3 00F4 F4 00F6 F6 00F7 F7 00F9 F9 00FA FA 00FB FB 00FC FC 0108 C6 0109 E6 010A C5 010B E5 011C D8 011D F8 011E AB 011F BB 0120 D5 0121 F5 0124 A6 0125 B6 0126 A1 0127 B1 0130 A9 0131 B9 0134 AC 0135 BC 015C DE 015D FE 015E AA 015F BA 016C DD 016D FD 017B AF 017C BF 02D8 A2 02D9 FF}
} -result {}

test encoding-convertto-ucmCompare-iso8859-3 {Compare against ICU UCM} -body {
    ucmConverttoMismatches iso8859-3 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A3 A3 00A4 A4 00A7 A7 00A8 A8 00AD AD 00B0 B0 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B7 B7 00B8 B8 00BD BD 00C0 C0 00C1 C1 00C2 C2 00C4 C4 00C7 C7 00C8 C8 00C9 C9 00CA CA 00CB CB 00CC CC 00CD CD 00CE CE 00CF CF 00D1 D1 00D2 D2 00D3 D3 00D4 D4 00D6 D6 00D7 D7 00D9 D9 00DA DA 00DB DB 00DC DC 00DF DF 00E0 E0 00E1 E1 00E2 E2 00E4 E4 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00EC EC 00ED ED 00EE EE 00EF EF 00F1 F1 00F2 F2 00F3 F3 00F4 F4 00F6 F6 00F7 F7 00F9 F9 00FA FA 00FB FB 00FC FC 0108 C6 0109 E6 010A C5 010B E5 011C D8 011D F8 011E AB 011F BB 0120 D5 0121 F5 0124 A6 0125 B6 0126 A1 0127 B1 0130 A9 0131 B9 0134 AC 0135 BC 015C DE 015D FE 015E AA 015F BA 016C DD 016D FD 017B AF 017C BF 02D8 A2 02D9 FF}
} -result {}

# iso8859-3 - invalid byte sequences
lappend encInvalidBytes {*}{
    iso8859-3 A5 tcl8    \U000000A5 -1 {} {}
    iso8859-3 A5 replace \uFFFD -1 {} {}
    iso8859-3 A5 strict  {}       0 {} {}
    iso8859-3 AE tcl8    \U000000AE -1 {} {}
    iso8859-3 AE replace \uFFFD -1 {} {}
    iso8859-3 AE strict  {}       0 {} {}
    iso8859-3 BE tcl8    \U000000BE -1 {} {}
    iso8859-3 BE replace \uFFFD -1 {} {}
    iso8859-3 BE strict  {}       0 {} {}
    iso8859-3 C3 tcl8    \U000000C3 -1 {} {}
    iso8859-3 C3 replace \uFFFD -1 {} {}
    iso8859-3 C3 strict  {}       0 {} {}
    iso8859-3 D0 tcl8    \U000000D0 -1 {} {}
    iso8859-3 D0 replace \uFFFD -1 {} {}
    iso8859-3 D0 strict  {}       0 {} {}
    iso8859-3 E3 tcl8    \U000000E3 -1 {} {}
    iso8859-3 E3 replace \uFFFD -1 {} {}
    iso8859-3 E3 strict  {}       0 {} {}
    iso8859-3 F0 tcl8    \U000000F0 -1 {} {}
    iso8859-3 F0 replace \uFFFD -1 {} {}
    iso8859-3 F0 strict  {}       0 {} {}
}; # iso8859-3

# iso8859-3 - invalid byte sequences
lappend encUnencodableStrings {*}{
    iso8859-3 \U000000A1 tcl8    1A -1 {} {}
    iso8859-3 \U000000A1 replace 1A -1 {} {}
    iso8859-3 \U000000A1 strict  {}                      0 {} {}
    iso8859-3 \U00000400 tcl8    1A -1 {} {}
    iso8859-3 \U00000400 replace 1A -1 {} {}
    iso8859-3 \U00000400 strict  {}                      0 {} {}
    iso8859-3 \U0000D800 tcl8    1A -1 {} {}
    iso8859-3 \U0000D800 replace 1A -1 {} {}
    iso8859-3 \U0000D800 strict  {}                      0 {} {}
    iso8859-3 \U0000DC00 tcl8    1A -1 {} {}
    iso8859-3 \U0000DC00 replace 1A -1 {} {}
    iso8859-3 \U0000DC00 strict  {}                      0 {} {}
    iso8859-3 \U00010000 tcl8    1A -1 {} {}
    iso8859-3 \U00010000 replace 1A -1 {} {}
    iso8859-3 \U00010000 strict  {}                      0 {} {}
    iso8859-3 \U0010FFFF tcl8    1A -1 {} {}
    iso8859-3 \U0010FFFF replace 1A -1 {} {}
    iso8859-3 \U0010FFFF strict  {}                      0 {} {}
}; # iso8859-3

#
# iso8859-4 (generated from glibc-ISO_8859_4-2.1.2)

test encoding-convertfrom-ucmCompare-iso8859-4 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches iso8859-4 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A4 A4 00A7 A7 00A8 A8 00AD AD 00AF AF 00B0 B0 00B4 B4 00B8 B8 00C1 C1 00C2 C2 00C3 C3 00C4 C4 00C5 C5 00C6 C6 00C9 C9 00CB CB 00CD CD 00CE CE 00D4 D4 00D5 D5 00D6 D6 00D7 D7 00D8 D8 00DA DA 00DB DB 00DC DC 00DF DF 00E1 E1 00E2 E2 00E3 E3 00E4 E4 00E5 E5 00E6 E6 00E9 E9 00EB EB 00ED ED 00EE EE 00F4 F4 00F5 F5 00F6 F6 00F7 F7 00F8 F8 00FA FA 00FB FB 00FC FC 0100 C0 0101 E0 0104 A1 0105 B1 010C C8 010D E8 0110 D0 0111 F0 0112 AA 0113 BA 0116 CC 0117 EC 0118 CA 0119 EA 0122 AB 0123 BB 0128 A5 0129 B5 012A CF 012B EF 012E C7 012F E7 0136 D3 0137 F3 0138 A2 013B A6 013C B6 0145 D1 0146 F1 014A BD 014B BF 014C D2 014D F2 0156 A3 0157 B3 0160 A9 0161 B9 0166 AC 0167 BC 0168 DD 0169 FD 016A DE 016B FE 0172 D9 0173 F9 017D AE 017E BE 02C7 B7 02D9 FF 02DB B2}
} -result {}

test encoding-convertto-ucmCompare-iso8859-4 {Compare against ICU UCM} -body {
    ucmConverttoMismatches iso8859-4 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A4 A4 00A7 A7 00A8 A8 00AD AD 00AF AF 00B0 B0 00B4 B4 00B8 B8 00C1 C1 00C2 C2 00C3 C3 00C4 C4 00C5 C5 00C6 C6 00C9 C9 00CB CB 00CD CD 00CE CE 00D4 D4 00D5 D5 00D6 D6 00D7 D7 00D8 D8 00DA DA 00DB DB 00DC DC 00DF DF 00E1 E1 00E2 E2 00E3 E3 00E4 E4 00E5 E5 00E6 E6 00E9 E9 00EB EB 00ED ED 00EE EE 00F4 F4 00F5 F5 00F6 F6 00F7 F7 00F8 F8 00FA FA 00FB FB 00FC FC 0100 C0 0101 E0 0104 A1 0105 B1 010C C8 010D E8 0110 D0 0111 F0 0112 AA 0113 BA 0116 CC 0117 EC 0118 CA 0119 EA 0122 AB 0123 BB 0128 A5 0129 B5 012A CF 012B EF 012E C7 012F E7 0136 D3 0137 F3 0138 A2 013B A6 013C B6 0145 D1 0146 F1 014A BD 014B BF 014C D2 014D F2 0156 A3 0157 B3 0160 A9 0161 B9 0166 AC 0167 BC 0168 DD 0169 FD 016A DE 016B FE 0172 D9 0173 F9 017D AE 017E BE 02C7 B7 02D9 FF 02DB B2}
} -result {}

# iso8859-4 - invalid byte sequences
lappend encInvalidBytes {*}{
}; # iso8859-4

# iso8859-4 - invalid byte sequences
lappend encUnencodableStrings {*}{
    iso8859-4 \U000000A1 tcl8    1A -1 {} {}
    iso8859-4 \U000000A1 replace 1A -1 {} {}
    iso8859-4 \U000000A1 strict  {}                      0 {} {}
    iso8859-4 \U00000400 tcl8    1A -1 {} {}
    iso8859-4 \U00000400 replace 1A -1 {} {}
    iso8859-4 \U00000400 strict  {}                      0 {} {}
    iso8859-4 \U0000D800 tcl8    1A -1 {} {}
    iso8859-4 \U0000D800 replace 1A -1 {} {}
    iso8859-4 \U0000D800 strict  {}                      0 {} {}
    iso8859-4 \U0000DC00 tcl8    1A -1 {} {}
    iso8859-4 \U0000DC00 replace 1A -1 {} {}
    iso8859-4 \U0000DC00 strict  {}                      0 {} {}
    iso8859-4 \U00010000 tcl8    1A -1 {} {}
    iso8859-4 \U00010000 replace 1A -1 {} {}
    iso8859-4 \U00010000 strict  {}                      0 {} {}
    iso8859-4 \U0010FFFF tcl8    1A -1 {} {}
    iso8859-4 \U0010FFFF replace 1A -1 {} {}
    iso8859-4 \U0010FFFF strict  {}                      0 {} {}
}; # iso8859-4

#
# iso8859-5 (generated from glibc-ISO_8859_5-2.1.2)

test encoding-convertfrom-ucmCompare-iso8859-5 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches iso8859-5 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A7 FD 00AD AD 0401 A1 0402 A2 0403 A3 0404 A4 0405 A5 0406 A6 0407 A7 0408 A8 0409 A9 040A AA 040B AB 040C AC 040E AE 040F AF 0410 B0 0411 B1 0412 B2 0413 B3 0414 B4 0415 B5 0416 B6 0417 B7 0418 B8 0419 B9 041A BA 041B BB 041C BC 041D BD 041E BE 041F BF 0420 C0 0421 C1 0422 C2 0423 C3 0424 C4 0425 C5 0426 C6 0427 C7 0428 C8 0429 C9 042A CA 042B CB 042C CC 042D CD 042E CE 042F CF 0430 D0 0431 D1 0432 D2 0433 D3 0434 D4 0435 D5 0436 D6 0437 D7 0438 D8 0439 D9 043A DA 043B DB 043C DC 043D DD 043E DE 043F DF 0440 E0 0441 E1 0442 E2 0443 E3 0444 E4 0445 E5 0446 E6 0447 E7 0448 E8 0449 E9 044A EA 044B EB 044C EC 044D ED 044E EE 044F EF 0451 F1 0452 F2 0453 F3 0454 F4 0455 F5 0456 F6 0457 F7 0458 F8 0459 F9 045A FA 045B FB 045C FC 045E FE 045F FF 2116 F0}
} -result {}

test encoding-convertto-ucmCompare-iso8859-5 {Compare against ICU UCM} -body {
    ucmConverttoMismatches iso8859-5 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A7 FD 00AD AD 0401 A1 0402 A2 0403 A3 0404 A4 0405 A5 0406 A6 0407 A7 0408 A8 0409 A9 040A AA 040B AB 040C AC 040E AE 040F AF 0410 B0 0411 B1 0412 B2 0413 B3 0414 B4 0415 B5 0416 B6 0417 B7 0418 B8 0419 B9 041A BA 041B BB 041C BC 041D BD 041E BE 041F BF 0420 C0 0421 C1 0422 C2 0423 C3 0424 C4 0425 C5 0426 C6 0427 C7 0428 C8 0429 C9 042A CA 042B CB 042C CC 042D CD 042E CE 042F CF 0430 D0 0431 D1 0432 D2 0433 D3 0434 D4 0435 D5 0436 D6 0437 D7 0438 D8 0439 D9 043A DA 043B DB 043C DC 043D DD 043E DE 043F DF 0440 E0 0441 E1 0442 E2 0443 E3 0444 E4 0445 E5 0446 E6 0447 E7 0448 E8 0449 E9 044A EA 044B EB 044C EC 044D ED 044E EE 044F EF 0451 F1 0452 F2 0453 F3 0454 F4 0455 F5 0456 F6 0457 F7 0458 F8 0459 F9 045A FA 045B FB 045C FC 045E FE 045F FF 2116 F0}
} -result {}

# iso8859-5 - invalid byte sequences
lappend encInvalidBytes {*}{
}; # iso8859-5

# iso8859-5 - invalid byte sequences
lappend encUnencodableStrings {*}{
    iso8859-5 \U000000A1 tcl8    1A -1 {} {}
    iso8859-5 \U000000A1 replace 1A -1 {} {}
    iso8859-5 \U000000A1 strict  {}                      0 {} {}
    iso8859-5 \U00000400 tcl8    1A -1 {} {}
    iso8859-5 \U00000400 replace 1A -1 {} {}
    iso8859-5 \U00000400 strict  {}                      0 {} {}
    iso8859-5 \U0000D800 tcl8    1A -1 {} {}
    iso8859-5 \U0000D800 replace 1A -1 {} {}
    iso8859-5 \U0000D800 strict  {}                      0 {} {}
    iso8859-5 \U0000DC00 tcl8    1A -1 {} {}
    iso8859-5 \U0000DC00 replace 1A -1 {} {}
    iso8859-5 \U0000DC00 strict  {}                      0 {} {}
    iso8859-5 \U00010000 tcl8    1A -1 {} {}
    iso8859-5 \U00010000 replace 1A -1 {} {}
    iso8859-5 \U00010000 strict  {}                      0 {} {}
    iso8859-5 \U0010FFFF tcl8    1A -1 {} {}
    iso8859-5 \U0010FFFF replace 1A -1 {} {}
    iso8859-5 \U0010FFFF strict  {}                      0 {} {}
}; # iso8859-5

#
# iso8859-6 (generated from glibc-ISO_8859_6-2.1.2)

test encoding-convertfrom-ucmCompare-iso8859-6 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches iso8859-6 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A4 A4 00AD AD 060C AC 061B BB 061F BF 0621 C1 0622 C2 0623 C3 0624 C4 0625 C5 0626 C6 0627 C7 0628 C8 0629 C9 062A CA 062B CB 062C CC 062D CD 062E CE 062F CF 0630 D0 0631 D1 0632 D2 0633 D3 0634 D4 0635 D5 0636 D6 0637 D7 0638 D8 0639 D9 063A DA 0640 E0 0641 E1 0642 E2 0643 E3 0644 E4 0645 E5 0646 E6 0647 E7 0648 E8 0649 E9 064A EA 064B EB 064C EC 064D ED 064E EE 064F EF 0650 F0 0651 F1 0652 F2}
} -result {}

test encoding-convertto-ucmCompare-iso8859-6 {Compare against ICU UCM} -body {
    ucmConverttoMismatches iso8859-6 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A4 A4 00AD AD 060C AC 061B BB 061F BF 0621 C1 0622 C2 0623 C3 0624 C4 0625 C5 0626 C6 0627 C7 0628 C8 0629 C9 062A CA 062B CB 062C CC 062D CD 062E CE 062F CF 0630 D0 0631 D1 0632 D2 0633 D3 0634 D4 0635 D5 0636 D6 0637 D7 0638 D8 0639 D9 063A DA 0640 E0 0641 E1 0642 E2 0643 E3 0644 E4 0645 E5 0646 E6 0647 E7 0648 E8 0649 E9 064A EA 064B EB 064C EC 064D ED 064E EE 064F EF 0650 F0 0651 F1 0652 F2}
} -result {}

# iso8859-6 - invalid byte sequences
lappend encInvalidBytes {*}{
    iso8859-6 A1 tcl8    \U000000A1 -1 {} {}
    iso8859-6 A1 replace \uFFFD -1 {} {}
    iso8859-6 A1 strict  {}       0 {} {}
    iso8859-6 A2 tcl8    \U000000A2 -1 {} {}
    iso8859-6 A2 replace \uFFFD -1 {} {}
    iso8859-6 A2 strict  {}       0 {} {}
    iso8859-6 A3 tcl8    \U000000A3 -1 {} {}
    iso8859-6 A3 replace \uFFFD -1 {} {}
    iso8859-6 A3 strict  {}       0 {} {}
    iso8859-6 A5 tcl8    \U000000A5 -1 {} {}
    iso8859-6 A5 replace \uFFFD -1 {} {}
    iso8859-6 A5 strict  {}       0 {} {}
    iso8859-6 A6 tcl8    \U000000A6 -1 {} {}
    iso8859-6 A6 replace \uFFFD -1 {} {}
    iso8859-6 A6 strict  {}       0 {} {}
    iso8859-6 A7 tcl8    \U000000A7 -1 {} {}
    iso8859-6 A7 replace \uFFFD -1 {} {}
    iso8859-6 A7 strict  {}       0 {} {}
    iso8859-6 A8 tcl8    \U000000A8 -1 {} {}
    iso8859-6 A8 replace \uFFFD -1 {} {}
    iso8859-6 A8 strict  {}       0 {} {}
    iso8859-6 A9 tcl8    \U000000A9 -1 {} {}
    iso8859-6 A9 replace \uFFFD -1 {} {}
    iso8859-6 A9 strict  {}       0 {} {}
    iso8859-6 AA tcl8    \U000000AA -1 {} {}
    iso8859-6 AA replace \uFFFD -1 {} {}
    iso8859-6 AA strict  {}       0 {} {}
    iso8859-6 AB tcl8    \U000000AB -1 {} {}
    iso8859-6 AB replace \uFFFD -1 {} {}
    iso8859-6 AB strict  {}       0 {} {}
    iso8859-6 AE tcl8    \U000000AE -1 {} {}
    iso8859-6 AE replace \uFFFD -1 {} {}
    iso8859-6 AE strict  {}       0 {} {}
    iso8859-6 AF tcl8    \U000000AF -1 {} {}
    iso8859-6 AF replace \uFFFD -1 {} {}
    iso8859-6 AF strict  {}       0 {} {}
    iso8859-6 B0 tcl8    \U000000B0 -1 {} {}
    iso8859-6 B0 replace \uFFFD -1 {} {}
    iso8859-6 B0 strict  {}       0 {} {}
    iso8859-6 B1 tcl8    \U000000B1 -1 {} {}
    iso8859-6 B1 replace \uFFFD -1 {} {}
    iso8859-6 B1 strict  {}       0 {} {}
    iso8859-6 B2 tcl8    \U000000B2 -1 {} {}
    iso8859-6 B2 replace \uFFFD -1 {} {}
    iso8859-6 B2 strict  {}       0 {} {}
    iso8859-6 B3 tcl8    \U000000B3 -1 {} {}
    iso8859-6 B3 replace \uFFFD -1 {} {}
    iso8859-6 B3 strict  {}       0 {} {}
    iso8859-6 B4 tcl8    \U000000B4 -1 {} {}
    iso8859-6 B4 replace \uFFFD -1 {} {}
    iso8859-6 B4 strict  {}       0 {} {}
    iso8859-6 B5 tcl8    \U000000B5 -1 {} {}
    iso8859-6 B5 replace \uFFFD -1 {} {}
    iso8859-6 B5 strict  {}       0 {} {}
    iso8859-6 B6 tcl8    \U000000B6 -1 {} {}
    iso8859-6 B6 replace \uFFFD -1 {} {}
    iso8859-6 B6 strict  {}       0 {} {}
    iso8859-6 B7 tcl8    \U000000B7 -1 {} {}
    iso8859-6 B7 replace \uFFFD -1 {} {}
    iso8859-6 B7 strict  {}       0 {} {}
    iso8859-6 B8 tcl8    \U000000B8 -1 {} {}
    iso8859-6 B8 replace \uFFFD -1 {} {}
    iso8859-6 B8 strict  {}       0 {} {}
    iso8859-6 B9 tcl8    \U000000B9 -1 {} {}
    iso8859-6 B9 replace \uFFFD -1 {} {}
    iso8859-6 B9 strict  {}       0 {} {}
    iso8859-6 BA tcl8    \U000000BA -1 {} {}
    iso8859-6 BA replace \uFFFD -1 {} {}
    iso8859-6 BA strict  {}       0 {} {}
    iso8859-6 BC tcl8    \U000000BC -1 {} {}
    iso8859-6 BC replace \uFFFD -1 {} {}
    iso8859-6 BC strict  {}       0 {} {}
    iso8859-6 BD tcl8    \U000000BD -1 {} {}
    iso8859-6 BD replace \uFFFD -1 {} {}
    iso8859-6 BD strict  {}       0 {} {}
    iso8859-6 BE tcl8    \U000000BE -1 {} {}
    iso8859-6 BE replace \uFFFD -1 {} {}
    iso8859-6 BE strict  {}       0 {} {}
    iso8859-6 C0 tcl8    \U000000C0 -1 {} {}
    iso8859-6 C0 replace \uFFFD -1 {} {}
    iso8859-6 C0 strict  {}       0 {} {}
    iso8859-6 DB tcl8    \U000000DB -1 {} {}
    iso8859-6 DB replace \uFFFD -1 {} {}
    iso8859-6 DB strict  {}       0 {} {}
    iso8859-6 DC tcl8    \U000000DC -1 {} {}
    iso8859-6 DC replace \uFFFD -1 {} {}
    iso8859-6 DC strict  {}       0 {} {}
    iso8859-6 DD tcl8    \U000000DD -1 {} {}
    iso8859-6 DD replace \uFFFD -1 {} {}
    iso8859-6 DD strict  {}       0 {} {}
    iso8859-6 DE tcl8    \U000000DE -1 {} {}
    iso8859-6 DE replace \uFFFD -1 {} {}
    iso8859-6 DE strict  {}       0 {} {}
    iso8859-6 DF tcl8    \U000000DF -1 {} {}
    iso8859-6 DF replace \uFFFD -1 {} {}
    iso8859-6 DF strict  {}       0 {} {}
    iso8859-6 F3 tcl8    \U000000F3 -1 {} {}
    iso8859-6 F3 replace \uFFFD -1 {} {}
    iso8859-6 F3 strict  {}       0 {} {}
    iso8859-6 F4 tcl8    \U000000F4 -1 {} {}
    iso8859-6 F4 replace \uFFFD -1 {} {}
    iso8859-6 F4 strict  {}       0 {} {}
    iso8859-6 F5 tcl8    \U000000F5 -1 {} {}
    iso8859-6 F5 replace \uFFFD -1 {} {}
    iso8859-6 F5 strict  {}       0 {} {}
    iso8859-6 F6 tcl8    \U000000F6 -1 {} {}
    iso8859-6 F6 replace \uFFFD -1 {} {}
    iso8859-6 F6 strict  {}       0 {} {}
    iso8859-6 F7 tcl8    \U000000F7 -1 {} {}
    iso8859-6 F7 replace \uFFFD -1 {} {}
    iso8859-6 F7 strict  {}       0 {} {}
    iso8859-6 F8 tcl8    \U000000F8 -1 {} {}
    iso8859-6 F8 replace \uFFFD -1 {} {}
    iso8859-6 F8 strict  {}       0 {} {}
    iso8859-6 F9 tcl8    \U000000F9 -1 {} {}
    iso8859-6 F9 replace \uFFFD -1 {} {}
    iso8859-6 F9 strict  {}       0 {} {}
    iso8859-6 FA tcl8    \U000000FA -1 {} {}
    iso8859-6 FA replace \uFFFD -1 {} {}
    iso8859-6 FA strict  {}       0 {} {}
    iso8859-6 FB tcl8    \U000000FB -1 {} {}
    iso8859-6 FB replace \uFFFD -1 {} {}
    iso8859-6 FB strict  {}       0 {} {}
    iso8859-6 FC tcl8    \U000000FC -1 {} {}
    iso8859-6 FC replace \uFFFD -1 {} {}
    iso8859-6 FC strict  {}       0 {} {}
    iso8859-6 FD tcl8    \U000000FD -1 {} {}
    iso8859-6 FD replace \uFFFD -1 {} {}
    iso8859-6 FD strict  {}       0 {} {}
    iso8859-6 FE tcl8    \U000000FE -1 {} {}
    iso8859-6 FE replace \uFFFD -1 {} {}
    iso8859-6 FE strict  {}       0 {} {}
    iso8859-6 FF tcl8    \U000000FF -1 {} {}
    iso8859-6 FF replace \uFFFD -1 {} {}
    iso8859-6 FF strict  {}       0 {} {}
}; # iso8859-6

# iso8859-6 - invalid byte sequences
lappend encUnencodableStrings {*}{
    iso8859-6 \U000000A1 tcl8    1A -1 {} {}
    iso8859-6 \U000000A1 replace 1A -1 {} {}
    iso8859-6 \U000000A1 strict  {}                      0 {} {}
    iso8859-6 \U00000400 tcl8    1A -1 {} {}
    iso8859-6 \U00000400 replace 1A -1 {} {}
    iso8859-6 \U00000400 strict  {}                      0 {} {}
    iso8859-6 \U0000D800 tcl8    1A -1 {} {}
    iso8859-6 \U0000D800 replace 1A -1 {} {}
    iso8859-6 \U0000D800 strict  {}                      0 {} {}
    iso8859-6 \U0000DC00 tcl8    1A -1 {} {}
    iso8859-6 \U0000DC00 replace 1A -1 {} {}
    iso8859-6 \U0000DC00 strict  {}                      0 {} {}
    iso8859-6 \U00010000 tcl8    1A -1 {} {}
    iso8859-6 \U00010000 replace 1A -1 {} {}
    iso8859-6 \U00010000 strict  {}                      0 {} {}
    iso8859-6 \U0010FFFF tcl8    1A -1 {} {}
    iso8859-6 \U0010FFFF replace 1A -1 {} {}
    iso8859-6 \U0010FFFF strict  {}                      0 {} {}
}; # iso8859-6

#
# iso8859-7 (generated from glibc-ISO_8859_7-2.3.3)

test encoding-convertfrom-ucmCompare-iso8859-7 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches iso8859-7 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A3 A3 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AB AB 00AC AC 00AD AD 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B7 B7 00BB BB 00BD BD 037A AA 0384 B4 0385 B5 0386 B6 0388 B8 0389 B9 038A BA 038C BC 038E BE 038F BF 0390 C0 0391 C1 0392 C2 0393 C3 0394 C4 0395 C5 0396 C6 0397 C7 0398 C8 0399 C9 039A CA 039B CB 039C CC 039D CD 039E CE 039F CF 03A0 D0 03A1 D1 03A3 D3 03A4 D4 03A5 D5 03A6 D6 03A7 D7 03A8 D8 03A9 D9 03AA DA 03AB DB 03AC DC 03AD DD 03AE DE 03AF DF 03B0 E0 03B1 E1 03B2 E2 03B3 E3 03B4 E4 03B5 E5 03B6 E6 03B7 E7 03B8 E8 03B9 E9 03BA EA 03BB EB 03BC EC 03BD ED 03BE EE 03BF EF 03C0 F0 03C1 F1 03C2 F2 03C3 F3 03C4 F4 03C5 F5 03C6 F6 03C7 F7 03C8 F8 03C9 F9 03CA FA 03CB FB 03CC FC 03CD FD 03CE FE 2015 AF 2018 A1 2019 A2 20AC A4 20AF A5}
} -result {}

test encoding-convertto-ucmCompare-iso8859-7 {Compare against ICU UCM} -body {
    ucmConverttoMismatches iso8859-7 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A3 A3 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AB AB 00AC AC 00AD AD 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B7 B7 00BB BB 00BD BD 037A AA 0384 B4 0385 B5 0386 B6 0388 B8 0389 B9 038A BA 038C BC 038E BE 038F BF 0390 C0 0391 C1 0392 C2 0393 C3 0394 C4 0395 C5 0396 C6 0397 C7 0398 C8 0399 C9 039A CA 039B CB 039C CC 039D CD 039E CE 039F CF 03A0 D0 03A1 D1 03A3 D3 03A4 D4 03A5 D5 03A6 D6 03A7 D7 03A8 D8 03A9 D9 03AA DA 03AB DB 03AC DC 03AD DD 03AE DE 03AF DF 03B0 E0 03B1 E1 03B2 E2 03B3 E3 03B4 E4 03B5 E5 03B6 E6 03B7 E7 03B8 E8 03B9 E9 03BA EA 03BB EB 03BC EC 03BD ED 03BE EE 03BF EF 03C0 F0 03C1 F1 03C2 F2 03C3 F3 03C4 F4 03C5 F5 03C6 F6 03C7 F7 03C8 F8 03C9 F9 03CA FA 03CB FB 03CC FC 03CD FD 03CE FE 2015 AF 2018 A1 2019 A2 20AC A4 20AF A5}
} -result {}

# iso8859-7 - invalid byte sequences
lappend encInvalidBytes {*}{
    iso8859-7 AE tcl8    \U000000AE -1 {} {}
    iso8859-7 AE replace \uFFFD -1 {} {}
    iso8859-7 AE strict  {}       0 {} {}
    iso8859-7 D2 tcl8    \U000000D2 -1 {} {}
    iso8859-7 D2 replace \uFFFD -1 {} {}
    iso8859-7 D2 strict  {}       0 {} {}
    iso8859-7 FF tcl8    \U000000FF -1 {} {}
    iso8859-7 FF replace \uFFFD -1 {} {}
    iso8859-7 FF strict  {}       0 {} {}
}; # iso8859-7

# iso8859-7 - invalid byte sequences
lappend encUnencodableStrings {*}{
    iso8859-7 \U000000A1 tcl8    1A -1 {} {}
    iso8859-7 \U000000A1 replace 1A -1 {} {}
    iso8859-7 \U000000A1 strict  {}                      0 {} {}
    iso8859-7 \U00000400 tcl8    1A -1 {} {}
    iso8859-7 \U00000400 replace 1A -1 {} {}
    iso8859-7 \U00000400 strict  {}                      0 {} {}
    iso8859-7 \U0000D800 tcl8    1A -1 {} {}
    iso8859-7 \U0000D800 replace 1A -1 {} {}
    iso8859-7 \U0000D800 strict  {}                      0 {} {}
    iso8859-7 \U0000DC00 tcl8    1A -1 {} {}
    iso8859-7 \U0000DC00 replace 1A -1 {} {}
    iso8859-7 \U0000DC00 strict  {}                      0 {} {}
    iso8859-7 \U00010000 tcl8    1A -1 {} {}
    iso8859-7 \U00010000 replace 1A -1 {} {}
    iso8859-7 \U00010000 strict  {}                      0 {} {}
    iso8859-7 \U0010FFFF tcl8    1A -1 {} {}
    iso8859-7 \U0010FFFF replace 1A -1 {} {}
    iso8859-7 \U0010FFFF strict  {}                      0 {} {}
}; # iso8859-7

#
# iso8859-8 (generated from glibc-ISO_8859_8-2.3.3)

test encoding-convertfrom-ucmCompare-iso8859-8 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches iso8859-8 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A2 A2 00A3 A3 00A4 A4 00A5 A5 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AB AB 00AC AC 00AD AD 00AE AE 00AF AF 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 B8 00B9 B9 00BB BB 00BC BC 00BD BD 00BE BE 00D7 AA 00F7 BA 05D0 E0 05D1 E1 05D2 E2 05D3 E3 05D4 E4 05D5 E5 05D6 E6 05D7 E7 05D8 E8 05D9 E9 05DA EA 05DB EB 05DC EC 05DD ED 05DE EE 05DF EF 05E0 F0 05E1 F1 05E2 F2 05E3 F3 05E4 F4 05E5 F5 05E6 F6 05E7 F7 05E8 F8 05E9 F9 05EA FA 200E FD 200F FE 2017 DF}
} -result {}

test encoding-convertto-ucmCompare-iso8859-8 {Compare against ICU UCM} -body {
    ucmConverttoMismatches iso8859-8 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A2 A2 00A3 A3 00A4 A4 00A5 A5 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AB AB 00AC AC 00AD AD 00AE AE 00AF AF 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 B8 00B9 B9 00BB BB 00BC BC 00BD BD 00BE BE 00D7 AA 00F7 BA 05D0 E0 05D1 E1 05D2 E2 05D3 E3 05D4 E4 05D5 E5 05D6 E6 05D7 E7 05D8 E8 05D9 E9 05DA EA 05DB EB 05DC EC 05DD ED 05DE EE 05DF EF 05E0 F0 05E1 F1 05E2 F2 05E3 F3 05E4 F4 05E5 F5 05E6 F6 05E7 F7 05E8 F8 05E9 F9 05EA FA 200E FD 200F FE 2017 DF}
} -result {}

# iso8859-8 - invalid byte sequences
lappend encInvalidBytes {*}{
    iso8859-8 A1 tcl8    \U000000A1 -1 {} {}
    iso8859-8 A1 replace \uFFFD -1 {} {}
    iso8859-8 A1 strict  {}       0 {} {}
    iso8859-8 BF tcl8    \U000000BF -1 {} {}
    iso8859-8 BF replace \uFFFD -1 {} {}
    iso8859-8 BF strict  {}       0 {} {}
    iso8859-8 C0 tcl8    \U000000C0 -1 {} {}
    iso8859-8 C0 replace \uFFFD -1 {} {}
    iso8859-8 C0 strict  {}       0 {} {}
    iso8859-8 C1 tcl8    \U000000C1 -1 {} {}
    iso8859-8 C1 replace \uFFFD -1 {} {}
    iso8859-8 C1 strict  {}       0 {} {}
    iso8859-8 C2 tcl8    \U000000C2 -1 {} {}
    iso8859-8 C2 replace \uFFFD -1 {} {}
    iso8859-8 C2 strict  {}       0 {} {}
    iso8859-8 C3 tcl8    \U000000C3 -1 {} {}
    iso8859-8 C3 replace \uFFFD -1 {} {}
    iso8859-8 C3 strict  {}       0 {} {}
    iso8859-8 C4 tcl8    \U000000C4 -1 {} {}
    iso8859-8 C4 replace \uFFFD -1 {} {}
    iso8859-8 C4 strict  {}       0 {} {}
    iso8859-8 C5 tcl8    \U000000C5 -1 {} {}
    iso8859-8 C5 replace \uFFFD -1 {} {}
    iso8859-8 C5 strict  {}       0 {} {}
    iso8859-8 C6 tcl8    \U000000C6 -1 {} {}
    iso8859-8 C6 replace \uFFFD -1 {} {}
    iso8859-8 C6 strict  {}       0 {} {}
    iso8859-8 C7 tcl8    \U000000C7 -1 {} {}
    iso8859-8 C7 replace \uFFFD -1 {} {}
    iso8859-8 C7 strict  {}       0 {} {}
    iso8859-8 C8 tcl8    \U000000C8 -1 {} {}
    iso8859-8 C8 replace \uFFFD -1 {} {}
    iso8859-8 C8 strict  {}       0 {} {}
    iso8859-8 C9 tcl8    \U000000C9 -1 {} {}
    iso8859-8 C9 replace \uFFFD -1 {} {}
    iso8859-8 C9 strict  {}       0 {} {}
    iso8859-8 CA tcl8    \U000000CA -1 {} {}
    iso8859-8 CA replace \uFFFD -1 {} {}
    iso8859-8 CA strict  {}       0 {} {}
    iso8859-8 CB tcl8    \U000000CB -1 {} {}
    iso8859-8 CB replace \uFFFD -1 {} {}
    iso8859-8 CB strict  {}       0 {} {}
    iso8859-8 CC tcl8    \U000000CC -1 {} {}
    iso8859-8 CC replace \uFFFD -1 {} {}
    iso8859-8 CC strict  {}       0 {} {}
    iso8859-8 CD tcl8    \U000000CD -1 {} {}
    iso8859-8 CD replace \uFFFD -1 {} {}
    iso8859-8 CD strict  {}       0 {} {}
    iso8859-8 CE tcl8    \U000000CE -1 {} {}
    iso8859-8 CE replace \uFFFD -1 {} {}
    iso8859-8 CE strict  {}       0 {} {}
    iso8859-8 CF tcl8    \U000000CF -1 {} {}
    iso8859-8 CF replace \uFFFD -1 {} {}
    iso8859-8 CF strict  {}       0 {} {}
    iso8859-8 D0 tcl8    \U000000D0 -1 {} {}
    iso8859-8 D0 replace \uFFFD -1 {} {}
    iso8859-8 D0 strict  {}       0 {} {}
    iso8859-8 D1 tcl8    \U000000D1 -1 {} {}
    iso8859-8 D1 replace \uFFFD -1 {} {}
    iso8859-8 D1 strict  {}       0 {} {}
    iso8859-8 D2 tcl8    \U000000D2 -1 {} {}
    iso8859-8 D2 replace \uFFFD -1 {} {}
    iso8859-8 D2 strict  {}       0 {} {}
    iso8859-8 D3 tcl8    \U000000D3 -1 {} {}
    iso8859-8 D3 replace \uFFFD -1 {} {}
    iso8859-8 D3 strict  {}       0 {} {}
    iso8859-8 D4 tcl8    \U000000D4 -1 {} {}
    iso8859-8 D4 replace \uFFFD -1 {} {}
    iso8859-8 D4 strict  {}       0 {} {}
    iso8859-8 D5 tcl8    \U000000D5 -1 {} {}
    iso8859-8 D5 replace \uFFFD -1 {} {}
    iso8859-8 D5 strict  {}       0 {} {}
    iso8859-8 D6 tcl8    \U000000D6 -1 {} {}
    iso8859-8 D6 replace \uFFFD -1 {} {}
    iso8859-8 D6 strict  {}       0 {} {}
    iso8859-8 D7 tcl8    \U000000D7 -1 {} {}
    iso8859-8 D7 replace \uFFFD -1 {} {}
    iso8859-8 D7 strict  {}       0 {} {}
    iso8859-8 D8 tcl8    \U000000D8 -1 {} {}
    iso8859-8 D8 replace \uFFFD -1 {} {}
    iso8859-8 D8 strict  {}       0 {} {}
    iso8859-8 D9 tcl8    \U000000D9 -1 {} {}
    iso8859-8 D9 replace \uFFFD -1 {} {}
    iso8859-8 D9 strict  {}       0 {} {}
    iso8859-8 DA tcl8    \U000000DA -1 {} {}
    iso8859-8 DA replace \uFFFD -1 {} {}
    iso8859-8 DA strict  {}       0 {} {}
    iso8859-8 DB tcl8    \U000000DB -1 {} {}
    iso8859-8 DB replace \uFFFD -1 {} {}
    iso8859-8 DB strict  {}       0 {} {}
    iso8859-8 DC tcl8    \U000000DC -1 {} {}
    iso8859-8 DC replace \uFFFD -1 {} {}
    iso8859-8 DC strict  {}       0 {} {}
    iso8859-8 DD tcl8    \U000000DD -1 {} {}
    iso8859-8 DD replace \uFFFD -1 {} {}
    iso8859-8 DD strict  {}       0 {} {}
    iso8859-8 DE tcl8    \U000000DE -1 {} {}
    iso8859-8 DE replace \uFFFD -1 {} {}
    iso8859-8 DE strict  {}       0 {} {}
    iso8859-8 FB tcl8    \U000000FB -1 {} {}
    iso8859-8 FB replace \uFFFD -1 {} {}
    iso8859-8 FB strict  {}       0 {} {}
    iso8859-8 FC tcl8    \U000000FC -1 {} {}
    iso8859-8 FC replace \uFFFD -1 {} {}
    iso8859-8 FC strict  {}       0 {} {}
    iso8859-8 FF tcl8    \U000000FF -1 {} {}
    iso8859-8 FF replace \uFFFD -1 {} {}
    iso8859-8 FF strict  {}       0 {} {}
}; # iso8859-8

# iso8859-8 - invalid byte sequences
lappend encUnencodableStrings {*}{
    iso8859-8 \U000000A1 tcl8    1A -1 {} {}
    iso8859-8 \U000000A1 replace 1A -1 {} {}
    iso8859-8 \U000000A1 strict  {}                      0 {} {}
    iso8859-8 \U00000400 tcl8    1A -1 {} {}
    iso8859-8 \U00000400 replace 1A -1 {} {}
    iso8859-8 \U00000400 strict  {}                      0 {} {}
    iso8859-8 \U0000D800 tcl8    1A -1 {} {}
    iso8859-8 \U0000D800 replace 1A -1 {} {}
    iso8859-8 \U0000D800 strict  {}                      0 {} {}
    iso8859-8 \U0000DC00 tcl8    1A -1 {} {}
    iso8859-8 \U0000DC00 replace 1A -1 {} {}
    iso8859-8 \U0000DC00 strict  {}                      0 {} {}
    iso8859-8 \U00010000 tcl8    1A -1 {} {}
    iso8859-8 \U00010000 replace 1A -1 {} {}
    iso8859-8 \U00010000 strict  {}                      0 {} {}
    iso8859-8 \U0010FFFF tcl8    1A -1 {} {}
    iso8859-8 \U0010FFFF replace 1A -1 {} {}
    iso8859-8 \U0010FFFF strict  {}                      0 {} {}
}; # iso8859-8

#
# iso8859-9 (generated from glibc-ISO_8859_9-2.1.2)

test encoding-convertfrom-ucmCompare-iso8859-9 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches iso8859-9 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A1 A1 00A2 A2 00A3 A3 00A4 A4 00A5 A5 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AA AA 00AB AB 00AC AC 00AD AD 00AE AE 00AF AF 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 B8 00B9 B9 00BA BA 00BB BB 00BC BC 00BD BD 00BE BE 00BF BF 00C0 C0 00C1 C1 00C2 C2 00C3 C3 00C4 C4 00C5 C5 00C6 C6 00C7 C7 00C8 C8 00C9 C9 00CA CA 00CB CB 00CC CC 00CD CD 00CE CE 00CF CF 00D1 D1 00D2 D2 00D3 D3 00D4 D4 00D5 D5 00D6 D6 00D7 D7 00D8 D8 00D9 D9 00DA DA 00DB DB 00DC DC 00DF DF 00E0 E0 00E1 E1 00E2 E2 00E3 E3 00E4 E4 00E5 E5 00E6 E6 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00EC EC 00ED ED 00EE EE 00EF EF 00F1 F1 00F2 F2 00F3 F3 00F4 F4 00F5 F5 00F6 F6 00F7 F7 00F8 F8 00F9 F9 00FA FA 00FB FB 00FC FC 00FF FF 011E D0 011F F0 0130 DD 0131 FD 015E DE 015F FE}
} -result {}

test encoding-convertto-ucmCompare-iso8859-9 {Compare against ICU UCM} -body {
    ucmConverttoMismatches iso8859-9 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A1 A1 00A2 A2 00A3 A3 00A4 A4 00A5 A5 00A6 A6 00A7 A7 00A8 A8 00A9 A9 00AA AA 00AB AB 00AC AC 00AD AD 00AE AE 00AF AF 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B4 B4 00B5 B5 00B6 B6 00B7 B7 00B8 B8 00B9 B9 00BA BA 00BB BB 00BC BC 00BD BD 00BE BE 00BF BF 00C0 C0 00C1 C1 00C2 C2 00C3 C3 00C4 C4 00C5 C5 00C6 C6 00C7 C7 00C8 C8 00C9 C9 00CA CA 00CB CB 00CC CC 00CD CD 00CE CE 00CF CF 00D1 D1 00D2 D2 00D3 D3 00D4 D4 00D5 D5 00D6 D6 00D7 D7 00D8 D8 00D9 D9 00DA DA 00DB DB 00DC DC 00DF DF 00E0 E0 00E1 E1 00E2 E2 00E3 E3 00E4 E4 00E5 E5 00E6 E6 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00EC EC 00ED ED 00EE EE 00EF EF 00F1 F1 00F2 F2 00F3 F3 00F4 F4 00F5 F5 00F6 F6 00F7 F7 00F8 F8 00F9 F9 00FA FA 00FB FB 00FC FC 00FF FF 011E D0 011F F0 0130 DD 0131 FD 015E DE 015F FE}
} -result {}

# iso8859-9 - invalid byte sequences
lappend encInvalidBytes {*}{
}; # iso8859-9

# iso8859-9 - invalid byte sequences
lappend encUnencodableStrings {*}{
    iso8859-9 \U000000D0 tcl8    1A -1 {} {}
    iso8859-9 \U000000D0 replace 1A -1 {} {}
    iso8859-9 \U000000D0 strict  {}                      0 {} {}
    iso8859-9 \U00000400 tcl8    1A -1 {} {}
    iso8859-9 \U00000400 replace 1A -1 {} {}
    iso8859-9 \U00000400 strict  {}                      0 {} {}
    iso8859-9 \U0000D800 tcl8    1A -1 {} {}
    iso8859-9 \U0000D800 replace 1A -1 {} {}
    iso8859-9 \U0000D800 strict  {}                      0 {} {}
    iso8859-9 \U0000DC00 tcl8    1A -1 {} {}
    iso8859-9 \U0000DC00 replace 1A -1 {} {}
    iso8859-9 \U0000DC00 strict  {}                      0 {} {}
    iso8859-9 \U00010000 tcl8    1A -1 {} {}
    iso8859-9 \U00010000 replace 1A -1 {} {}
    iso8859-9 \U00010000 strict  {}                      0 {} {}
    iso8859-9 \U0010FFFF tcl8    1A -1 {} {}
    iso8859-9 \U0010FFFF replace 1A -1 {} {}
    iso8859-9 \U0010FFFF strict  {}                      0 {} {}
}; # iso8859-9

#
# iso8859-10 (generated from glibc-ISO_8859_10-2.1.2)

test encoding-convertfrom-ucmCompare-iso8859-10 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches iso8859-10 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A7 A7 00AD AD 00B0 B0 00B7 B7 00C1 C1 00C2 C2 00C3 C3 00C4 C4 00C5 C5 00C6 C6 00C9 C9 00CB CB 00CD CD 00CE CE 00CF CF 00D0 D0 00D3 D3 00D4 D4 00D5 D5 00D6 D6 00D8 D8 00DA DA 00DB DB 00DC DC 00DD DD 00DE DE 00DF DF 00E1 E1 00E2 E2 00E3 E3 00E4 E4 00E5 E5 00E6 E6 00E9 E9 00EB EB 00ED ED 00EE EE 00EF EF 00F0 F0 00F3 F3 00F4 F4 00F5 F5 00F6 F6 00F8 F8 00FA FA 00FB FB 00FC FC 00FD FD 00FE FE 0100 C0 0101 E0 0104 A1 0105 B1 010C C8 010D E8 0110 A9 0111 B9 0112 A2 0113 B2 0116 CC 0117 EC 0118 CA 0119 EA 0122 A3 0123 B3 0128 A5 0129 B5 012A A4 012B B4 012E C7 012F E7 0136 A6 0137 B6 0138 FF 013B A8 013C B8 0145 D1 0146 F1 014A AF 014B BF 014C D2 014D F2 0160 AA 0161 BA 0166 AB 0167 BB 0168 D7 0169 F7 016A AE 016B BE 0172 D9 0173 F9 017D AC 017E BC 2015 BD}
} -result {}

test encoding-convertto-ucmCompare-iso8859-10 {Compare against ICU UCM} -body {
    ucmConverttoMismatches iso8859-10 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A7 A7 00AD AD 00B0 B0 00B7 B7 00C1 C1 00C2 C2 00C3 C3 00C4 C4 00C5 C5 00C6 C6 00C9 C9 00CB CB 00CD CD 00CE CE 00CF CF 00D0 D0 00D3 D3 00D4 D4 00D5 D5 00D6 D6 00D8 D8 00DA DA 00DB DB 00DC DC 00DD DD 00DE DE 00DF DF 00E1 E1 00E2 E2 00E3 E3 00E4 E4 00E5 E5 00E6 E6 00E9 E9 00EB EB 00ED ED 00EE EE 00EF EF 00F0 F0 00F3 F3 00F4 F4 00F5 F5 00F6 F6 00F8 F8 00FA FA 00FB FB 00FC FC 00FD FD 00FE FE 0100 C0 0101 E0 0104 A1 0105 B1 010C C8 010D E8 0110 A9 0111 B9 0112 A2 0113 B2 0116 CC 0117 EC 0118 CA 0119 EA 0122 A3 0123 B3 0128 A5 0129 B5 012A A4 012B B4 012E C7 012F E7 0136 A6 0137 B6 0138 FF 013B A8 013C B8 0145 D1 0146 F1 014A AF 014B BF 014C D2 014D F2 0160 AA 0161 BA 0166 AB 0167 BB 0168 D7 0169 F7 016A AE 016B BE 0172 D9 0173 F9 017D AC 017E BC 2015 BD}
} -result {}

# iso8859-10 - invalid byte sequences
lappend encInvalidBytes {*}{
}; # iso8859-10

# iso8859-10 - invalid byte sequences
lappend encUnencodableStrings {*}{
    iso8859-10 \U000000A1 tcl8    1A -1 {} {}
    iso8859-10 \U000000A1 replace 1A -1 {} {}
    iso8859-10 \U000000A1 strict  {}                      0 {} {}
    iso8859-10 \U00000400 tcl8    1A -1 {} {}
    iso8859-10 \U00000400 replace 1A -1 {} {}
    iso8859-10 \U00000400 strict  {}                      0 {} {}
    iso8859-10 \U0000D800 tcl8    1A -1 {} {}
    iso8859-10 \U0000D800 replace 1A -1 {} {}
    iso8859-10 \U0000D800 strict  {}                      0 {} {}
    iso8859-10 \U0000DC00 tcl8    1A -1 {} {}
    iso8859-10 \U0000DC00 replace 1A -1 {} {}
    iso8859-10 \U0000DC00 strict  {}                      0 {} {}
    iso8859-10 \U00010000 tcl8    1A -1 {} {}
    iso8859-10 \U00010000 replace 1A -1 {} {}
    iso8859-10 \U00010000 strict  {}                      0 {} {}
    iso8859-10 \U0010FFFF tcl8    1A -1 {} {}
    iso8859-10 \U0010FFFF replace 1A -1 {} {}
    iso8859-10 \U0010FFFF strict  {}                      0 {} {}
}; # iso8859-10

#
# iso8859-11 (generated from glibc-ISO_8859_11-2.1.2)

test encoding-convertfrom-ucmCompare-iso8859-11 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches iso8859-11 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 0E01 A1 0E02 A2 0E03 A3 0E04 A4 0E05 A5 0E06 A6 0E07 A7 0E08 A8 0E09 A9 0E0A AA 0E0B AB 0E0C AC 0E0D AD 0E0E AE 0E0F AF 0E10 B0 0E11 B1 0E12 B2 0E13 B3 0E14 B4 0E15 B5 0E16 B6 0E17 B7 0E18 B8 0E19 B9 0E1A BA 0E1B BB 0E1C BC 0E1D BD 0E1E BE 0E1F BF 0E20 C0 0E21 C1 0E22 C2 0E23 C3 0E24 C4 0E25 C5 0E26 C6 0E27 C7 0E28 C8 0E29 C9 0E2A CA 0E2B CB 0E2C CC 0E2D CD 0E2E CE 0E2F CF 0E30 D0 0E31 D1 0E32 D2 0E33 D3 0E34 D4 0E35 D5 0E36 D6 0E37 D7 0E38 D8 0E39 D9 0E3A DA 0E3F DF 0E40 E0 0E41 E1 0E42 E2 0E43 E3 0E44 E4 0E45 E5 0E46 E6 0E47 E7 0E48 E8 0E49 E9 0E4A EA 0E4B EB 0E4C EC 0E4D ED 0E4E EE 0E4F EF 0E50 F0 0E51 F1 0E52 F2 0E53 F3 0E54 F4 0E55 F5 0E56 F6 0E57 F7 0E58 F8 0E59 F9 0E5A FA 0E5B FB}
} -result {}

test encoding-convertto-ucmCompare-iso8859-11 {Compare against ICU UCM} -body {
    ucmConverttoMismatches iso8859-11 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 0E01 A1 0E02 A2 0E03 A3 0E04 A4 0E05 A5 0E06 A6 0E07 A7 0E08 A8 0E09 A9 0E0A AA 0E0B AB 0E0C AC 0E0D AD 0E0E AE 0E0F AF 0E10 B0 0E11 B1 0E12 B2 0E13 B3 0E14 B4 0E15 B5 0E16 B6 0E17 B7 0E18 B8 0E19 B9 0E1A BA 0E1B BB 0E1C BC 0E1D BD 0E1E BE 0E1F BF 0E20 C0 0E21 C1 0E22 C2 0E23 C3 0E24 C4 0E25 C5 0E26 C6 0E27 C7 0E28 C8 0E29 C9 0E2A CA 0E2B CB 0E2C CC 0E2D CD 0E2E CE 0E2F CF 0E30 D0 0E31 D1 0E32 D2 0E33 D3 0E34 D4 0E35 D5 0E36 D6 0E37 D7 0E38 D8 0E39 D9 0E3A DA 0E3F DF 0E40 E0 0E41 E1 0E42 E2 0E43 E3 0E44 E4 0E45 E5 0E46 E6 0E47 E7 0E48 E8 0E49 E9 0E4A EA 0E4B EB 0E4C EC 0E4D ED 0E4E EE 0E4F EF 0E50 F0 0E51 F1 0E52 F2 0E53 F3 0E54 F4 0E55 F5 0E56 F6 0E57 F7 0E58 F8 0E59 F9 0E5A FA 0E5B FB}
} -result {}

# iso8859-11 - invalid byte sequences
lappend encInvalidBytes {*}{
    iso8859-11 DB tcl8    \U000000DB -1 {} {}
    iso8859-11 DB replace \uFFFD -1 {} {}
    iso8859-11 DB strict  {}       0 {} {}
    iso8859-11 DC tcl8    \U000000DC -1 {} {}
    iso8859-11 DC replace \uFFFD -1 {} {}
    iso8859-11 DC strict  {}       0 {} {}
    iso8859-11 DD tcl8    \U000000DD -1 {} {}
    iso8859-11 DD replace \uFFFD -1 {} {}
    iso8859-11 DD strict  {}       0 {} {}
    iso8859-11 DE tcl8    \U000000DE -1 {} {}
    iso8859-11 DE replace \uFFFD -1 {} {}
    iso8859-11 DE strict  {}       0 {} {}
    iso8859-11 FC tcl8    \U000000FC -1 {} {}
    iso8859-11 FC replace \uFFFD -1 {} {}
    iso8859-11 FC strict  {}       0 {} {}
    iso8859-11 FD tcl8    \U000000FD -1 {} {}
    iso8859-11 FD replace \uFFFD -1 {} {}
    iso8859-11 FD strict  {}       0 {} {}
    iso8859-11 FE tcl8    \U000000FE -1 {} {}
    iso8859-11 FE replace \uFFFD -1 {} {}
    iso8859-11 FE strict  {}       0 {} {}
    iso8859-11 FF tcl8    \U000000FF -1 {} {}
    iso8859-11 FF replace \uFFFD -1 {} {}
    iso8859-11 FF strict  {}       0 {} {}
}; # iso8859-11

# iso8859-11 - invalid byte sequences
lappend encUnencodableStrings {*}{
    iso8859-11 \U000000A1 tcl8    1A -1 {} {}
    iso8859-11 \U000000A1 replace 1A -1 {} {}
    iso8859-11 \U000000A1 strict  {}                      0 {} {}
    iso8859-11 \U00000400 tcl8    1A -1 {} {}
    iso8859-11 \U00000400 replace 1A -1 {} {}
    iso8859-11 \U00000400 strict  {}                      0 {} {}
    iso8859-11 \U0000D800 tcl8    1A -1 {} {}
    iso8859-11 \U0000D800 replace 1A -1 {} {}
    iso8859-11 \U0000D800 strict  {}                      0 {} {}
    iso8859-11 \U0000DC00 tcl8    1A -1 {} {}
    iso8859-11 \U0000DC00 replace 1A -1 {} {}
    iso8859-11 \U0000DC00 strict  {}                      0 {} {}
    iso8859-11 \U00010000 tcl8    1A -1 {} {}
    iso8859-11 \U00010000 replace 1A -1 {} {}
    iso8859-11 \U00010000 strict  {}                      0 {} {}
    iso8859-11 \U0010FFFF tcl8    1A -1 {} {}
    iso8859-11 \U0010FFFF replace 1A -1 {} {}
    iso8859-11 \U0010FFFF strict  {}                      0 {} {}
}; # iso8859-11

#
# iso8859-13 (generated from glibc-ISO_8859_13-2.3.3)

test encoding-convertfrom-ucmCompare-iso8859-13 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches iso8859-13 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A2 A2 00A3 A3 00A4 A4 00A6 A6 00A7 A7 00A9 A9 00AB AB 00AC AC 00AD AD 00AE AE 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B5 B5 00B6 B6 00B7 B7 00B9 B9 00BB BB 00BC BC 00BD BD 00BE BE 00C4 C4 00C5 C5 00C6 AF 00C9 C9 00D3 D3 00D5 D5 00D6 D6 00D7 D7 00D8 A8 00DC DC 00DF DF 00E4 E4 00E5 E5 00E6 BF 00E9 E9 00F3 F3 00F5 F5 00F6 F6 00F7 F7 00F8 B8 00FC FC 0100 C2 0101 E2 0104 C0 0105 E0 0106 C3 0107 E3 010C C8 010D E8 0112 C7 0113 E7 0116 CB 0117 EB 0118 C6 0119 E6 0122 CC 0123 EC 012A CE 012B EE 012E C1 012F E1 0136 CD 0137 ED 013B CF 013C EF 0141 D9 0142 F9 0143 D1 0144 F1 0145 D2 0146 F2 014C D4 014D F4 0156 AA 0157 BA 015A DA 015B FA 0160 D0 0161 F0 016A DB 016B FB 0172 D8 0173 F8 0179 CA 017A EA 017B DD 017C FD 017D DE 017E FE 2019 FF 201C B4 201D A1 201E A5}
} -result {}

test encoding-convertto-ucmCompare-iso8859-13 {Compare against ICU UCM} -body {
    ucmConverttoMismatches iso8859-13 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A2 A2 00A3 A3 00A4 A4 00A6 A6 00A7 A7 00A9 A9 00AB AB 00AC AC 00AD AD 00AE AE 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B5 B5 00B6 B6 00B7 B7 00B9 B9 00BB BB 00BC BC 00BD BD 00BE BE 00C4 C4 00C5 C5 00C6 AF 00C9 C9 00D3 D3 00D5 D5 00D6 D6 00D7 D7 00D8 A8 00DC DC 00DF DF 00E4 E4 00E5 E5 00E6 BF 00E9 E9 00F3 F3 00F5 F5 00F6 F6 00F7 F7 00F8 B8 00FC FC 0100 C2 0101 E2 0104 C0 0105 E0 0106 C3 0107 E3 010C C8 010D E8 0112 C7 0113 E7 0116 CB 0117 EB 0118 C6 0119 E6 0122 CC 0123 EC 012A CE 012B EE 012E C1 012F E1 0136 CD 0137 ED 013B CF 013C EF 0141 D9 0142 F9 0143 D1 0144 F1 0145 D2 0146 F2 014C D4 014D F4 0156 AA 0157 BA 015A DA 015B FA 0160 D0 0161 F0 016A DB 016B FB 0172 D8 0173 F8 0179 CA 017A EA 017B DD 017C FD 017D DE 017E FE 2019 FF 201C B4 201D A1 201E A5}
} -result {}

# iso8859-13 - invalid byte sequences
lappend encInvalidBytes {*}{
}; # iso8859-13

# iso8859-13 - invalid byte sequences
lappend encUnencodableStrings {*}{
    iso8859-13 \U000000A1 tcl8    1A -1 {} {}
    iso8859-13 \U000000A1 replace 1A -1 {} {}
    iso8859-13 \U000000A1 strict  {}                      0 {} {}
    iso8859-13 \U00000400 tcl8    1A -1 {} {}
    iso8859-13 \U00000400 replace 1A -1 {} {}
    iso8859-13 \U00000400 strict  {}                      0 {} {}
    iso8859-13 \U0000D800 tcl8    1A -1 {} {}
    iso8859-13 \U0000D800 replace 1A -1 {} {}
    iso8859-13 \U0000D800 strict  {}                      0 {} {}
    iso8859-13 \U0000DC00 tcl8    1A -1 {} {}
    iso8859-13 \U0000DC00 replace 1A -1 {} {}
    iso8859-13 \U0000DC00 strict  {}                      0 {} {}
    iso8859-13 \U00010000 tcl8    1A -1 {} {}
    iso8859-13 \U00010000 replace 1A -1 {} {}
    iso8859-13 \U00010000 strict  {}                      0 {} {}
    iso8859-13 \U0010FFFF tcl8    1A -1 {} {}
    iso8859-13 \U0010FFFF replace 1A -1 {} {}
    iso8859-13 \U0010FFFF strict  {}                      0 {} {}
}; # iso8859-13

#
# iso8859-14 (generated from glibc-ISO_8859_14-2.1.2)

test encoding-convertfrom-ucmCompare-iso8859-14 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches iso8859-14 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A3 A3 00A7 A7 00A9 A9 00AD AD 00AE AE 00B6 B6 00C0 C0 00C1 C1 00C2 C2 00C3 C3 00C4 C4 00C5 C5 00C6 C6 00C7 C7 00C8 C8 00C9 C9 00CA CA 00CB CB 00CC CC 00CD CD 00CE CE 00CF CF 00D1 D1 00D2 D2 00D3 D3 00D4 D4 00D5 D5 00D6 D6 00D8 D8 00D9 D9 00DA DA 00DB DB 00DC DC 00DD DD 00DF DF 00E0 E0 00E1 E1 00E2 E2 00E3 E3 00E4 E4 00E5 E5 00E6 E6 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00EC EC 00ED ED 00EE EE 00EF EF 00F1 F1 00F2 F2 00F3 F3 00F4 F4 00F5 F5 00F6 F6 00F8 F8 00F9 F9 00FA FA 00FB FB 00FC FC 00FD FD 00FF FF 010A A4 010B A5 0120 B2 0121 B3 0174 D0 0175 F0 0176 DE 0177 FE 0178 AF 1E02 A1 1E03 A2 1E0A A6 1E0B AB 1E1E B0 1E1F B1 1E40 B4 1E41 B5 1E56 B7 1E57 B9 1E60 BB 1E61 BF 1E6A D7 1E6B F7 1E80 A8 1E81 B8 1E82 AA 1E83 BA 1E84 BD 1E85 BE 1EF2 AC 1EF3 BC}
} -result {}

test encoding-convertto-ucmCompare-iso8859-14 {Compare against ICU UCM} -body {
    ucmConverttoMismatches iso8859-14 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A3 A3 00A7 A7 00A9 A9 00AD AD 00AE AE 00B6 B6 00C0 C0 00C1 C1 00C2 C2 00C3 C3 00C4 C4 00C5 C5 00C6 C6 00C7 C7 00C8 C8 00C9 C9 00CA CA 00CB CB 00CC CC 00CD CD 00CE CE 00CF CF 00D1 D1 00D2 D2 00D3 D3 00D4 D4 00D5 D5 00D6 D6 00D8 D8 00D9 D9 00DA DA 00DB DB 00DC DC 00DD DD 00DF DF 00E0 E0 00E1 E1 00E2 E2 00E3 E3 00E4 E4 00E5 E5 00E6 E6 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00EC EC 00ED ED 00EE EE 00EF EF 00F1 F1 00F2 F2 00F3 F3 00F4 F4 00F5 F5 00F6 F6 00F8 F8 00F9 F9 00FA FA 00FB FB 00FC FC 00FD FD 00FF FF 010A A4 010B A5 0120 B2 0121 B3 0174 D0 0175 F0 0176 DE 0177 FE 0178 AF 1E02 A1 1E03 A2 1E0A A6 1E0B AB 1E1E B0 1E1F B1 1E40 B4 1E41 B5 1E56 B7 1E57 B9 1E60 BB 1E61 BF 1E6A D7 1E6B F7 1E80 A8 1E81 B8 1E82 AA 1E83 BA 1E84 BD 1E85 BE 1EF2 AC 1EF3 BC}
} -result {}

# iso8859-14 - invalid byte sequences
lappend encInvalidBytes {*}{
}; # iso8859-14

# iso8859-14 - invalid byte sequences
lappend encUnencodableStrings {*}{
    iso8859-14 \U000000A1 tcl8    1A -1 {} {}
    iso8859-14 \U000000A1 replace 1A -1 {} {}
    iso8859-14 \U000000A1 strict  {}                      0 {} {}
    iso8859-14 \U00000400 tcl8    1A -1 {} {}
    iso8859-14 \U00000400 replace 1A -1 {} {}
    iso8859-14 \U00000400 strict  {}                      0 {} {}
    iso8859-14 \U0000D800 tcl8    1A -1 {} {}
    iso8859-14 \U0000D800 replace 1A -1 {} {}
    iso8859-14 \U0000D800 strict  {}                      0 {} {}
    iso8859-14 \U0000DC00 tcl8    1A -1 {} {}
    iso8859-14 \U0000DC00 replace 1A -1 {} {}
    iso8859-14 \U0000DC00 strict  {}                      0 {} {}
    iso8859-14 \U00010000 tcl8    1A -1 {} {}
    iso8859-14 \U00010000 replace 1A -1 {} {}
    iso8859-14 \U00010000 strict  {}                      0 {} {}
    iso8859-14 \U0010FFFF tcl8    1A -1 {} {}
    iso8859-14 \U0010FFFF replace 1A -1 {} {}
    iso8859-14 \U0010FFFF strict  {}                      0 {} {}
}; # iso8859-14

#
# iso8859-15 (generated from glibc-ISO_8859_15-2.1.2)

test encoding-convertfrom-ucmCompare-iso8859-15 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches iso8859-15 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A1 A1 00A2 A2 00A3 A3 00A5 A5 00A7 A7 00A9 A9 00AA AA 00AB AB 00AC AC 00AD AD 00AE AE 00AF AF 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B5 B5 00B6 B6 00B7 B7 00B9 B9 00BA BA 00BB BB 00BF BF 00C0 C0 00C1 C1 00C2 C2 00C3 C3 00C4 C4 00C5 C5 00C6 C6 00C7 C7 00C8 C8 00C9 C9 00CA CA 00CB CB 00CC CC 00CD CD 00CE CE 00CF CF 00D0 D0 00D1 D1 00D2 D2 00D3 D3 00D4 D4 00D5 D5 00D6 D6 00D7 D7 00D8 D8 00D9 D9 00DA DA 00DB DB 00DC DC 00DD DD 00DE DE 00DF DF 00E0 E0 00E1 E1 00E2 E2 00E3 E3 00E4 E4 00E5 E5 00E6 E6 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00EC EC 00ED ED 00EE EE 00EF EF 00F0 F0 00F1 F1 00F2 F2 00F3 F3 00F4 F4 00F5 F5 00F6 F6 00F7 F7 00F8 F8 00F9 F9 00FA FA 00FB FB 00FC FC 00FD FD 00FE FE 00FF FF 0152 BC 0153 BD 0160 A6 0161 A8 0178 BE 017D B4 017E B8 20AC A4}
} -result {}

test encoding-convertto-ucmCompare-iso8859-15 {Compare against ICU UCM} -body {
    ucmConverttoMismatches iso8859-15 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A1 A1 00A2 A2 00A3 A3 00A5 A5 00A7 A7 00A9 A9 00AA AA 00AB AB 00AC AC 00AD AD 00AE AE 00AF AF 00B0 B0 00B1 B1 00B2 B2 00B3 B3 00B5 B5 00B6 B6 00B7 B7 00B9 B9 00BA BA 00BB BB 00BF BF 00C0 C0 00C1 C1 00C2 C2 00C3 C3 00C4 C4 00C5 C5 00C6 C6 00C7 C7 00C8 C8 00C9 C9 00CA CA 00CB CB 00CC CC 00CD CD 00CE CE 00CF CF 00D0 D0 00D1 D1 00D2 D2 00D3 D3 00D4 D4 00D5 D5 00D6 D6 00D7 D7 00D8 D8 00D9 D9 00DA DA 00DB DB 00DC DC 00DD DD 00DE DE 00DF DF 00E0 E0 00E1 E1 00E2 E2 00E3 E3 00E4 E4 00E5 E5 00E6 E6 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00EC EC 00ED ED 00EE EE 00EF EF 00F0 F0 00F1 F1 00F2 F2 00F3 F3 00F4 F4 00F5 F5 00F6 F6 00F7 F7 00F8 F8 00F9 F9 00FA FA 00FB FB 00FC FC 00FD FD 00FE FE 00FF FF 0152 BC 0153 BD 0160 A6 0161 A8 0178 BE 017D B4 017E B8 20AC A4}
} -result {}

# iso8859-15 - invalid byte sequences
lappend encInvalidBytes {*}{
}; # iso8859-15

# iso8859-15 - invalid byte sequences
lappend encUnencodableStrings {*}{
    iso8859-15 \U000000A4 tcl8    1A -1 {} {}
    iso8859-15 \U000000A4 replace 1A -1 {} {}
    iso8859-15 \U000000A4 strict  {}                      0 {} {}
    iso8859-15 \U00000400 tcl8    1A -1 {} {}
    iso8859-15 \U00000400 replace 1A -1 {} {}
    iso8859-15 \U00000400 strict  {}                      0 {} {}
    iso8859-15 \U0000D800 tcl8    1A -1 {} {}
    iso8859-15 \U0000D800 replace 1A -1 {} {}
    iso8859-15 \U0000D800 strict  {}                      0 {} {}
    iso8859-15 \U0000DC00 tcl8    1A -1 {} {}
    iso8859-15 \U0000DC00 replace 1A -1 {} {}
    iso8859-15 \U0000DC00 strict  {}                      0 {} {}
    iso8859-15 \U00010000 tcl8    1A -1 {} {}
    iso8859-15 \U00010000 replace 1A -1 {} {}
    iso8859-15 \U00010000 strict  {}                      0 {} {}
    iso8859-15 \U0010FFFF tcl8    1A -1 {} {}
    iso8859-15 \U0010FFFF replace 1A -1 {} {}
    iso8859-15 \U0010FFFF strict  {}                      0 {} {}
}; # iso8859-15

#
# iso8859-16 (generated from glibc-ISO_8859_16-2.3.3)

test encoding-convertfrom-ucmCompare-iso8859-16 {Compare against ICU UCM} -body {
    ucmConvertfromMismatches iso8859-16 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A7 A7 00A9 A9 00AB AB 00AD AD 00B0 B0 00B1 B1 00B6 B6 00B7 B7 00BB BB 00C0 C0 00C1 C1 00C2 C2 00C4 C4 00C6 C6 00C7 C7 00C8 C8 00C9 C9 00CA CA 00CB CB 00CC CC 00CD CD 00CE CE 00CF CF 00D2 D2 00D3 D3 00D4 D4 00D6 D6 00D9 D9 00DA DA 00DB DB 00DC DC 00DF DF 00E0 E0 00E1 E1 00E2 E2 00E4 E4 00E6 E6 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00EC EC 00ED ED 00EE EE 00EF EF 00F2 F2 00F3 F3 00F4 F4 00F6 F6 00F9 F9 00FA FA 00FB FB 00FC FC 00FF FF 0102 C3 0103 E3 0104 A1 0105 A2 0106 C5 0107 E5 010C B2 010D B9 0110 D0 0111 F0 0118 DD 0119 FD 0141 A3 0142 B3 0143 D1 0144 F1 0150 D5 0151 F5 0152 BC 0153 BD 015A D7 015B F7 0160 A6 0161 A8 0170 D8 0171 F8 0178 BE 0179 AC 017A AE 017B AF 017C BF 017D B4 017E B8 0218 AA 0219 BA 021A DE 021B FE 201D B5 201E A5 20AC A4}
} -result {}

test encoding-convertto-ucmCompare-iso8859-16 {Compare against ICU UCM} -body {
    ucmConverttoMismatches iso8859-16 {0000 00 0001 01 0002 02 0003 03 0004 04 0005 05 0006 06 0007 07 0008 08 0009 09 000A 0A 000B 0B 000C 0C 000D 0D 000E 0E 000F 0F 0010 10 0011 11 0012 12 0013 13 0014 14 0015 15 0016 16 0017 17 0018 18 0019 19 001A 1A 001B 1B 001C 1C 001D 1D 001E 1E 001F 1F 0020 20 0021 21 0022 22 0023 23 0024 24 0025 25 0026 26 0027 27 0028 28 0029 29 002A 2A 002B 2B 002C 2C 002D 2D 002E 2E 002F 2F 0030 30 0031 31 0032 32 0033 33 0034 34 0035 35 0036 36 0037 37 0038 38 0039 39 003A 3A 003B 3B 003C 3C 003D 3D 003E 3E 003F 3F 0040 40 0041 41 0042 42 0043 43 0044 44 0045 45 0046 46 0047 47 0048 48 0049 49 004A 4A 004B 4B 004C 4C 004D 4D 004E 4E 004F 4F 0050 50 0051 51 0052 52 0053 53 0054 54 0055 55 0056 56 0057 57 0058 58 0059 59 005A 5A 005B 5B 005C 5C 005D 5D 005E 5E 005F 5F 0060 60 0061 61 0062 62 0063 63 0064 64 0065 65 0066 66 0067 67 0068 68 0069 69 006A 6A 006B 6B 006C 6C 006D 6D 006E 6E 006F 6F 0070 70 0071 71 0072 72 0073 73 0074 74 0075 75 0076 76 0077 77 0078 78 0079 79 007A 7A 007B 7B 007C 7C 007D 7D 007E 7E 007F 7F 0080 80 0081 81 0082 82 0083 83 0084 84 0085 85 0086 86 0087 87 0088 88 0089 89 008A 8A 008B 8B 008C 8C 008D 8D 008E 8E 008F 8F 0090 90 0091 91 0092 92 0093 93 0094 94 0095 95 0096 96 0097 97 0098 98 0099 99 009A 9A 009B 9B 009C 9C 009D 9D 009E 9E 009F 9F 00A0 A0 00A7 A7 00A9 A9 00AB AB 00AD AD 00B0 B0 00B1 B1 00B6 B6 00B7 B7 00BB BB 00C0 C0 00C1 C1 00C2 C2 00C4 C4 00C6 C6 00C7 C7 00C8 C8 00C9 C9 00CA CA 00CB CB 00CC CC 00CD CD 00CE CE 00CF CF 00D2 D2 00D3 D3 00D4 D4 00D6 D6 00D9 D9 00DA DA 00DB DB 00DC DC 00DF DF 00E0 E0 00E1 E1 00E2 E2 00E4 E4 00E6 E6 00E7 E7 00E8 E8 00E9 E9 00EA EA 00EB EB 00EC EC 00ED ED 00EE EE 00EF EF 00F2 F2 00F3 F3 00F4 F4 00F6 F6 00F9 F9 00FA FA 00FB FB 00FC FC 00FF FF 0102 C3 0103 E3 0104 A1 0105 A2 0106 C5 0107 E5 010C B2 010D B9 0110 D0 0111 F0 0118 DD 0119 FD 0141 A3 0142 B3 0143 D1 0144 F1 0150 D5 0151 F5 0152 BC 0153 BD 015A D7 015B F7 0160 A6 0161 A8 0170 D8 0171 F8 0178 BE 0179 AC 017A AE 017B AF 017C BF 017D B4 017E B8 0218 AA 0219 BA 021A DE 021B FE 201D B5 201E A5 20AC A4}
} -result {}

# iso8859-16 - invalid byte sequences
lappend encInvalidBytes {*}{
}; # iso8859-16

# iso8859-16 - invalid byte sequences
lappend encUnencodableStrings {*}{
    iso8859-16 \U000000A1 tcl8    1A -1 {} {}
    iso8859-16 \U000000A1 replace 1A -1 {} {}
    iso8859-16 \U000000A1 strict  {}                      0 {} {}
    iso8859-16 \U00000400 tcl8    1A -1 {} {}
    iso8859-16 \U00000400 replace 1A -1 {} {}
    iso8859-16 \U00000400 strict  {}                      0 {} {}
    iso8859-16 \U0000D800 tcl8    1A -1 {} {}
    iso8859-16 \U0000D800 replace 1A -1 {} {}
    iso8859-16 \U0000D800 strict  {}                      0 {} {}
    iso8859-16 \U0000DC00 tcl8    1A -1 {} {}
    iso8859-16 \U0000DC00 replace 1A -1 {} {}
    iso8859-16 \U0000DC00 strict  {}                      0 {} {}
    iso8859-16 \U00010000 tcl8    1A -1 {} {}
    iso8859-16 \U00010000 replace 1A -1 {} {}
    iso8859-16 \U00010000 strict  {}                      0 {} {}
    iso8859-16 \U0010FFFF tcl8    1A -1 {} {}
    iso8859-16 \U0010FFFF replace 1A -1 {} {}
    iso8859-16 \U0010FFFF strict  {}                      0 {} {}
}; # iso8859-16

Changes to tests/if-old.test.

1
2
3
4
5
6
7
8
9
10
11



12
13
14
15
16
17
18
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
16
17
18








-
-
-
+
+
+







# Commands covered:  if
#
# This file contains the original set of tests for Tcl's if command.
# Since the if command is now compiled, a new set of tests covering
# the new implementation is in the file "if.test". Sourcing this file
# into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*

Changes to tests/if.test.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







# Commands covered:  if
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
138
139
140
141
142
143
144
145

146
147
148
149
150
151
152
138
139
140
141
142
143
144

145
146
147
148
149
150
151
152







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		if {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 2
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		if {[string compare $a "bar"] < 0} {
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
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







-
+















-
+







		    set i $i
		    set i [lindex $s $i]
		}
		if {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 3
    }
    return $a
} -cleanup {
    unset a
    unset -nocomplain i
} -result 3
test if-1.17 {TclCompileIfCmd: if/elseif test in quotes} -setup {
    set a {}
} -body {
    if {"0 < 3"} {set a 1}
} -returnCodes error -cleanup {
    unset a
} -result {expected boolean value but got "0 < 3"}
} -result {expected boolean value but got a list}

test if-2.1 {TclCompileIfCmd: "elseif" after if/elseif test} -setup {
    set a {}
} -body {
    if 3>4 {set a 1} elseif 1 {set a 2}
    return $a
} -cleanup {
235
236
237
238
239
240
241
242

243
244
245
246
247
248
249
235
236
237
238
239
240
241

242
243
244
245
246
247
248
249







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		if {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 2
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		if {[string compare $a "bar"] < 0} {
258
259
260
261
262
263
264
265

266
267
268
269
270
271
272
258
259
260
261
262
263
264

265
266
267
268
269
270
271
272







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		if {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 3
    } elseif 1<2 then { #; this if arm should be taken
	set a 4
	while {$a != "xxx"} {
	    break;
283
284
285
286
287
288
289
290

291
292
293
294
295
296
297
283
284
285
286
287
288
289

290
291
292
293
294
295
296
297







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		if {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 5
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		if {[string compare $a "bar"] < 0} {
306
307
308
309
310
311
312
313

314
315
316
317
318
319
320
306
307
308
309
310
311
312

313
314
315
316
317
318
319
320







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		if {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 6
    }
    return $a
} -cleanup {
    unset a
385
386
387
388
389
390
391
392

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

392
393
394
395
396
397
398
399







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		if {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 2
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		if {[string compare $a "bar"] < 0} {
408
409
410
411
412
413
414
415

416
417
418
419
420
421
422
408
409
410
411
412
413
414

415
416
417
418
419
420
421
422







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		if {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 3
    } elseif 1==2 then { #; this if arm should be taken
	set a 4
	while {$a != "xxx"} {
	    break;
433
434
435
436
437
438
439
440

441
442
443
444
445
446
447
433
434
435
436
437
438
439

440
441
442
443
444
445
446
447







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		if {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 5
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		if {[string compare $a "bar"] < 0} {
456
457
458
459
460
461
462
463

464
465
466
467
468
469
470
456
457
458
459
460
461
462

463
464
465
466
467
468
469
470







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		if {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 6
    } else {
	set a 7
	while {$a != "xxx"} {
	    break;
481
482
483
484
485
486
487
488

489
490
491
492
493
494
495
481
482
483
484
485
486
487

488
489
490
491
492
493
494
495







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		if {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 8
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		if {[string compare $a "bar"] < 0} {
504
505
506
507
508
509
510
511

512
513
514
515
516
517
518
504
505
506
507
508
509
510

511
512
513
514
515
516
517
518







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		if {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 9
    }
    return $a
} -cleanup {
    unset a
709
710
711
712
713
714
715
716

717
718
719
720
721
722
723
709
710
711
712
713
714
715

716
717
718
719
720
721
722
723







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		$z {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 2
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		$z {[string compare $a "bar"] < 0} {
732
733
734
735
736
737
738
739

740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756

757
758
759
760
761
762
763
732
733
734
735
736
737
738

739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755

756
757
758
759
760
761
762
763







-
+
















-
+







		    set i $i
		    set i [lindex $s $i]
		}
		$z {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 3
    }
    return $a
} -cleanup {
    unset a z
    unset -nocomplain i
} -result 3
test if-5.17 {if cmd with computed command names: if/elseif test in quotes} -setup {
    set a {}
} -body {
    set z if
    $z {"0 < 3"} {set a 1}
} -returnCodes error -cleanup {
    unset a z
} -result {expected boolean value but got "0 < 3"}
} -result {expected boolean value but got a list}

test if-6.1 {if cmd with computed command names: "elseif" after if/elseif test} -setup {
    set a {}
} -body {
    set z if
    $z 3>4 {set a 1} elseif 1 {set a 2}
    return $a
812
813
814
815
816
817
818
819

820
821
822
823
824
825
826
812
813
814
815
816
817
818

819
820
821
822
823
824
825
826







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		$z {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 2
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		$z {[string compare $a "bar"] < 0} {
835
836
837
838
839
840
841
842

843
844
845
846
847
848
849
835
836
837
838
839
840
841

842
843
844
845
846
847
848
849







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		$z {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 3
    } elseif 1<2 then { #; this if arm should be taken
	set a 4
	while {$a != "xxx"} {
	    break;
860
861
862
863
864
865
866
867

868
869
870
871
872
873
874
860
861
862
863
864
865
866

867
868
869
870
871
872
873
874







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		$z {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 5
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		$z {[string compare $a "bar"] < 0} {
883
884
885
886
887
888
889
890

891
892
893
894
895
896
897
883
884
885
886
887
888
889

890
891
892
893
894
895
896
897







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		$z {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 6
    }
    return $a
} -cleanup {
    unset a z
971
972
973
974
975
976
977
978

979
980
981
982
983
984
985
971
972
973
974
975
976
977

978
979
980
981
982
983
984
985







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		$z {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 2
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		$z {[string compare $a "bar"] < 0} {
994
995
996
997
998
999
1000
1001

1002
1003
1004
1005
1006
1007
1008
994
995
996
997
998
999
1000

1001
1002
1003
1004
1005
1006
1007
1008







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		$z {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 3
    } elseif 1==2 then { #; this if arm should be taken
	set a 4
	while {$a != "xxx"} {
	    break;
1019
1020
1021
1022
1023
1024
1025
1026

1027
1028
1029
1030
1031
1032
1033
1019
1020
1021
1022
1023
1024
1025

1026
1027
1028
1029
1030
1031
1032
1033







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		$z {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 5
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		$z {[string compare $a "bar"] < 0} {
1042
1043
1044
1045
1046
1047
1048
1049

1050
1051
1052
1053
1054
1055
1056
1042
1043
1044
1045
1046
1047
1048

1049
1050
1051
1052
1053
1054
1055
1056







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		$z {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 6
    } else {
	set a 7
	while {$a != "xxx"} {
	    break;
1067
1068
1069
1070
1071
1072
1073
1074

1075
1076
1077
1078
1079
1080
1081
1067
1068
1069
1070
1071
1072
1073

1074
1075
1076
1077
1078
1079
1080
1081







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		$z {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 8
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		$z {[string compare $a "bar"] < 0} {
1090
1091
1092
1093
1094
1095
1096
1097

1098
1099
1100
1101
1102
1103
1104
1090
1091
1092
1093
1094
1095
1096

1097
1098
1099
1100
1101
1102
1103
1104







-
+







		    set i $i
		    set i [lindex $s $i]
		}
		$z {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		set i [expr $i-1]
		incr i -1
	    }
	}
	set a 9
    }
    return $a
} -cleanup {
    unset a z
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
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







-
+

-
+


-
+

-
+












    proc iftraceproc {args} {
       upvar #0 iftracecounter counter
       set argc [llength $args]
       set extraargs [lrange $args 0 [expr {$argc - 4}]]
       set name [lindex $args [expr {$argc - 3}]]
       upvar 1 $name var
       if {[incr counter] % 2 == 1} {
           set var "$counter oops [concat $extraargs]"
	   set var "$counter oops [concat $extraargs]"
       } else {
           set var "$counter + [concat $extraargs]"
	   set var "$counter + [concat $extraargs]"
       }
    }
    trace variable iftracevar r [list iftraceproc 10]
    trace add variable iftracevar read [list iftraceproc 10]
    list [catch {if "$iftracevar + 20" {}} a] $a \
        [catch {if "$iftracevar + 20" {}} b] $b
	[catch {if "$iftracevar + 20" {}} b] $b
} -cleanup {
    unset iftracevar iftracecounter a b
} -match glob -result {1 {*} 0 {}}

# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:

Changes to tests/incr-old.test.

1
2
3
4
5
6
7
8
9
10
11



12
13
14
15
16
17
18
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
16
17
18








-
-
-
+
+
+







# Commands covered:  incr
#
# This file contains the original set of tests for Tcl's incr command.
# Since the incr command is now compiled, a new set of tests covering
# the new implementation is in the file "incr.test". Sourcing this file
# into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73







-
+







} {1 {expected integer but got "1a"} {expected integer but got "1a"
    (reading increment)
    invoked from within
"incr x 1a"}}
test incr-old-2.6 {incr errors} -body {
    proc readonly args {error "variable is read-only"}
    set x 123
    trace var x w readonly
    trace add var x write readonly
    list [catch {incr x 1} msg] $msg $::errorInfo
} -match glob -result {1 {can't set "x": variable is read-only} {*variable is read-only
    while executing
*
"incr x 1"}}
catch {unset x}
test incr-old-2.7 {incr errors} {
81
82
83
84
85
86
87
88

89
90
91
92
81
82
83
84
85
86
87

88
89
90
91
92







-
+




test incr-old-2.9 {incr errors} {
    set x +
    list [catch {incr x 1} msg] $msg
} {1 {expected integer but got "+"}}
test incr-old-2.10 {incr errors} {
    set x {20 x}
    list [catch {incr x 1} msg] $msg
} {1 {expected integer but got "20 x"}}
} {1 {expected integer but got a list}}

# cleanup
::tcltest::cleanupTests
return

Changes to tests/incr.test.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







# Commands covered:  incr
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
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
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







-
-
-
+
+
+





-
-
+
+





-
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







} {17 17}
test incr-1.10 {TclCompileIncrCmd: no increment given} {
    set i 10
    list [incr i] $i
} {11 11}
test incr-1.11 {TclCompileIncrCmd: simple global name} {
    proc p {} {
        global i
        set i 54
        incr i
	global i
	set i 54
	incr i
    }
    p
} {55}
test incr-1.12 {TclCompileIncrCmd: simple local name} {
    proc p {} {
        set foo 100
        incr foo
	set foo 100
	incr foo
    }
    p
} {101}
test incr-1.13 {TclCompileIncrCmd: simple but new (unknown) local name} {
    proc p {} {
        incr bar
	incr bar
    }
    p
} 1
test incr-1.14 {TclCompileIncrCmd: simple local name, >255 locals} {
    proc 260locals {} {
        # create 260 locals
        set a0 0; set a1 0; set a2 0; set a3 0; set a4 0
        set a5 0; set a6 0; set a7 0; set a8 0; set a9 0
        set b0 0; set b1 0; set b2 0; set b3 0; set b4 0
        set b5 0; set b6 0; set b7 0; set b8 0; set b9 0
        set c0 0; set c1 0; set c2 0; set c3 0; set c4 0
        set c5 0; set c6 0; set c7 0; set c8 0; set c9 0
        set d0 0; set d1 0; set d2 0; set d3 0; set d4 0
        set d5 0; set d6 0; set d7 0; set d8 0; set d9 0
        set e0 0; set e1 0; set e2 0; set e3 0; set e4 0
        set e5 0; set e6 0; set e7 0; set e8 0; set e9 0
        set f0 0; set f1 0; set f2 0; set f3 0; set f4 0
        set f5 0; set f6 0; set f7 0; set f8 0; set f9 0
        set g0 0; set g1 0; set g2 0; set g3 0; set g4 0
        set g5 0; set g6 0; set g7 0; set g8 0; set g9 0
        set h0 0; set h1 0; set h2 0; set h3 0; set h4 0
        set h5 0; set h6 0; set h7 0; set h8 0; set h9 0
        set i0 0; set i1 0; set i2 0; set i3 0; set i4 0
        set i5 0; set i6 0; set i7 0; set i8 0; set i9 0
        set j0 0; set j1 0; set j2 0; set j3 0; set j4 0
        set j5 0; set j6 0; set j7 0; set j8 0; set j9 0
        set k0 0; set k1 0; set k2 0; set k3 0; set k4 0
        set k5 0; set k6 0; set k7 0; set k8 0; set k9 0
        set l0 0; set l1 0; set l2 0; set l3 0; set l4 0
        set l5 0; set l6 0; set l7 0; set l8 0; set l9 0
        set m0 0; set m1 0; set m2 0; set m3 0; set m4 0
        set m5 0; set m6 0; set m7 0; set m8 0; set m9 0
        set n0 0; set n1 0; set n2 0; set n3 0; set n4 0
        set n5 0; set n6 0; set n7 0; set n8 0; set n9 0
        set o0 0; set o1 0; set o2 0; set o3 0; set o4 0
        set o5 0; set o6 0; set o7 0; set o8 0; set o9 0
        set p0 0; set p1 0; set p2 0; set p3 0; set p4 0
        set p5 0; set p6 0; set p7 0; set p8 0; set p9 0
        set q0 0; set q1 0; set q2 0; set q3 0; set q4 0
        set q5 0; set q6 0; set q7 0; set q8 0; set q9 0
        set r0 0; set r1 0; set r2 0; set r3 0; set r4 0
        set r5 0; set r6 0; set r7 0; set r8 0; set r9 0
        set s0 0; set s1 0; set s2 0; set s3 0; set s4 0
        set s5 0; set s6 0; set s7 0; set s8 0; set s9 0
        set t0 0; set t1 0; set t2 0; set t3 0; set t4 0
        set t5 0; set t6 0; set t7 0; set t8 0; set t9 0
        set u0 0; set u1 0; set u2 0; set u3 0; set u4 0
        set u5 0; set u6 0; set u7 0; set u8 0; set u9 0
        set v0 0; set v1 0; set v2 0; set v3 0; set v4 0
        set v5 0; set v6 0; set v7 0; set v8 0; set v9 0
        set w0 0; set w1 0; set w2 0; set w3 0; set w4 0
        set w5 0; set w6 0; set w7 0; set w8 0; set w9 0
        set x0 0; set x1 0; set x2 0; set x3 0; set x4 0
        set x5 0; set x6 0; set x7 0; set x8 0; set x9 0
        set y0 0; set y1 0; set y2 0; set y3 0; set y4 0
        set y5 0; set y6 0; set y7 0; set y8 0; set y9 0
        set z0 0; set z1 0; set z2 0; set z3 0; set z4 0
        set z5 0; set z6 0; set z7 0; set z8 0; set z9 0
        # now increment the last one (local var index > 255)
        incr z9
	# create 260 locals
	set a0 0; set a1 0; set a2 0; set a3 0; set a4 0
	set a5 0; set a6 0; set a7 0; set a8 0; set a9 0
	set b0 0; set b1 0; set b2 0; set b3 0; set b4 0
	set b5 0; set b6 0; set b7 0; set b8 0; set b9 0
	set c0 0; set c1 0; set c2 0; set c3 0; set c4 0
	set c5 0; set c6 0; set c7 0; set c8 0; set c9 0
	set d0 0; set d1 0; set d2 0; set d3 0; set d4 0
	set d5 0; set d6 0; set d7 0; set d8 0; set d9 0
	set e0 0; set e1 0; set e2 0; set e3 0; set e4 0
	set e5 0; set e6 0; set e7 0; set e8 0; set e9 0
	set f0 0; set f1 0; set f2 0; set f3 0; set f4 0
	set f5 0; set f6 0; set f7 0; set f8 0; set f9 0
	set g0 0; set g1 0; set g2 0; set g3 0; set g4 0
	set g5 0; set g6 0; set g7 0; set g8 0; set g9 0
	set h0 0; set h1 0; set h2 0; set h3 0; set h4 0
	set h5 0; set h6 0; set h7 0; set h8 0; set h9 0
	set i0 0; set i1 0; set i2 0; set i3 0; set i4 0
	set i5 0; set i6 0; set i7 0; set i8 0; set i9 0
	set j0 0; set j1 0; set j2 0; set j3 0; set j4 0
	set j5 0; set j6 0; set j7 0; set j8 0; set j9 0
	set k0 0; set k1 0; set k2 0; set k3 0; set k4 0
	set k5 0; set k6 0; set k7 0; set k8 0; set k9 0
	set l0 0; set l1 0; set l2 0; set l3 0; set l4 0
	set l5 0; set l6 0; set l7 0; set l8 0; set l9 0
	set m0 0; set m1 0; set m2 0; set m3 0; set m4 0
	set m5 0; set m6 0; set m7 0; set m8 0; set m9 0
	set n0 0; set n1 0; set n2 0; set n3 0; set n4 0
	set n5 0; set n6 0; set n7 0; set n8 0; set n9 0
	set o0 0; set o1 0; set o2 0; set o3 0; set o4 0
	set o5 0; set o6 0; set o7 0; set o8 0; set o9 0
	set p0 0; set p1 0; set p2 0; set p3 0; set p4 0
	set p5 0; set p6 0; set p7 0; set p8 0; set p9 0
	set q0 0; set q1 0; set q2 0; set q3 0; set q4 0
	set q5 0; set q6 0; set q7 0; set q8 0; set q9 0
	set r0 0; set r1 0; set r2 0; set r3 0; set r4 0
	set r5 0; set r6 0; set r7 0; set r8 0; set r9 0
	set s0 0; set s1 0; set s2 0; set s3 0; set s4 0
	set s5 0; set s6 0; set s7 0; set s8 0; set s9 0
	set t0 0; set t1 0; set t2 0; set t3 0; set t4 0
	set t5 0; set t6 0; set t7 0; set t8 0; set t9 0
	set u0 0; set u1 0; set u2 0; set u3 0; set u4 0
	set u5 0; set u6 0; set u7 0; set u8 0; set u9 0
	set v0 0; set v1 0; set v2 0; set v3 0; set v4 0
	set v5 0; set v6 0; set v7 0; set v8 0; set v9 0
	set w0 0; set w1 0; set w2 0; set w3 0; set w4 0
	set w5 0; set w6 0; set w7 0; set w8 0; set w9 0
	set x0 0; set x1 0; set x2 0; set x3 0; set x4 0
	set x5 0; set x6 0; set x7 0; set x8 0; set x9 0
	set y0 0; set y1 0; set y2 0; set y3 0; set y4 0
	set y5 0; set y6 0; set y7 0; set y8 0; set y9 0
	set z0 0; set z1 0; set z2 0; set z3 0; set z4 0
	set z5 0; set z6 0; set z7 0; set z8 0; set z9 0
	# now increment the last one (local var index > 255)
	incr z9
    }
    260locals
} {1}
test incr-1.15 {TclCompileIncrCmd: variable is array} -setup {
    unset -nocomplain a
} -body {
    set a(foo) 27
231
232
233
234
235
236
237

























































238
239
240
241
242
243
244
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







} -returnCodes error -result {expected integer but got "  -  "}
test incr-1.30 {TclCompileIncrCmd: array var, braced (no subs)} -setup {
    catch {unset array}
} -body {
    set array(\$foo) 4
    incr {array($foo)}
} -result 5

test incr-1.31 {no overflow in TclCompileIncrCmd and Tcl_IncrObjCmd, bug [7179c6724cd38271]} {
    set res [list]
    # TclCompileIncrCmd: compiled incr TEBC with immutable constant offs (INST_INCR_*_IMM instructions):
    lappend res [set i 0; incr i 0x7FFFFFFF]
    lappend res [set i 0; incr i 0xFFFFFF80]
    lappend res [set i 0; incr i 0xFFFFFF81]
    lappend res [set i 0; incr i 0xFFFFFFFF]
    lappend res [set i 0; incr i 0x10000007F]
    lappend res [set i 0; incr i 0x100000080]
    lappend res [set i 0; incr i 0x7FFFFFFFFFFFFFFF]
    lappend res [set i 0; incr i 0xFFFFFFFFFFFFFF80]
    lappend res [set i 0; incr i 0xFFFFFFFFFFFFFF81]
    lappend res [set i 0; incr i 0xFFFFFFFFFFFFFFFF]
    lappend res [set i 0; incr i 0x1000000000000007F]
    lappend res [set i 0; incr i 0x10000000000000080]
    # TclCompileIncrCmd: compiled incr TEBC with dynamic offs (INST_INCR_* instructions without _IMM):
    lappend res [set i 0; incr i [set x 0x7FFFFFFF]]
    lappend res [set i 0; incr i [set x 0xFFFFFF80]]
    lappend res [set i 0; incr i [set x 0xFFFFFF81]]
    lappend res [set i 0; incr i [set x 0xFFFFFFFF]]
    lappend res [set i 0; incr i [set x 0x10000007F]]
    lappend res [set i 0; incr i [set x 0x100000080]]
    lappend res [set i 0; incr i [set x 0x7FFFFFFFFFFFFFFF]]
    lappend res [set i 0; incr i [set x 0xFFFFFFFFFFFFFF80]]
    lappend res [set i 0; incr i [set x 0xFFFFFFFFFFFFFF81]]
    lappend res [set i 0; incr i [set x 0xFFFFFFFFFFFFFFFF]]
    lappend res [set i 0; incr i [set x 0x1000000000000007F]]
    lappend res [set i 0; incr i [set x 0x10000000000000080]]
    # Tcl_IncrObjCmd: non-compiled incr command (or NRE):
    set cmd incr
    lappend res [set i 0; $cmd i 0x7FFFFFFF]
    lappend res [set i 0; $cmd i 0xFFFFFF80]
    lappend res [set i 0; $cmd i 0xFFFFFF81]
    lappend res [set i 0; $cmd i 0xFFFFFFFF]
    lappend res [set i 0; $cmd i 0x10000007F]
    lappend res [set i 0; $cmd i 0x100000080]
    lappend res [set i 0; $cmd i 0x7FFFFFFFFFFFFFFF]
    lappend res [set i 0; $cmd i 0xFFFFFFFFFFFFFF80]
    lappend res [set i 0; $cmd i 0xFFFFFFFFFFFFFF81]
    lappend res [set i 0; $cmd i 0xFFFFFFFFFFFFFFFF]
    lappend res [set i 0; $cmd i 0x1000000000000007F]
    lappend res [set i 0; $cmd i 0x10000000000000080]
} [lrepeat 3 \
    [expr 0x7FFFFFFF] \
    [expr 0xFFFFFF80] \
    [expr 0xFFFFFF81] \
    [expr 0xFFFFFFFF] \
    [expr 0x10000007F] \
    [expr 0x100000080] \
    [expr 0x7FFFFFFFFFFFFFFF] \
    [expr 0xFFFFFFFFFFFFFF80] \
    [expr 0xFFFFFFFFFFFFFF81] \
    [expr 0xFFFFFFFFFFFFFFFF] \
    [expr 0x1000000000000007F] \
    [expr 0x10000000000000080] \
]

# Check "incr" and computed command names.

unset -nocomplain x i
test incr-2.0 {incr and computed command names} {
    set i 5
    set z incr
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
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
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
442
443
444
445
446
447
448







-
-
-
+
+
+






-
-
+
+






-
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    set z incr
    set i 10
    list [$z i] $i
} {11 11}
test incr-2.11 {incr command (not compiled): simple global name} {
    proc p {} {
	set z incr
        global i
        set i 54
        $z i
	global i
	set i 54
	$z i
    }
    p
} {55}
test incr-2.12 {incr command (not compiled): simple local name} {
    proc p {} {
	set z incr
        set foo 100
        $z foo
	set foo 100
	$z foo
    }
    p
} {101}
test incr-2.13 {incr command (not compiled): simple but new (unknown) local name} {
    proc p {} {
	set z incr
        $z bar
	$z bar
    }
    p
} 1
test incr-2.14 {incr command (not compiled): simple local name, >255 locals} {
   proc 260locals {} {
        set z incr
        # create 260 locals
        set a0 0; set a1 0; set a2 0; set a3 0; set a4 0
        set a5 0; set a6 0; set a7 0; set a8 0; set a9 0
        set b0 0; set b1 0; set b2 0; set b3 0; set b4 0
        set b5 0; set b6 0; set b7 0; set b8 0; set b9 0
        set c0 0; set c1 0; set c2 0; set c3 0; set c4 0
        set c5 0; set c6 0; set c7 0; set c8 0; set c9 0
        set d0 0; set d1 0; set d2 0; set d3 0; set d4 0
        set d5 0; set d6 0; set d7 0; set d8 0; set d9 0
        set e0 0; set e1 0; set e2 0; set e3 0; set e4 0
        set e5 0; set e6 0; set e7 0; set e8 0; set e9 0
        set f0 0; set f1 0; set f2 0; set f3 0; set f4 0
        set f5 0; set f6 0; set f7 0; set f8 0; set f9 0
        set g0 0; set g1 0; set g2 0; set g3 0; set g4 0
        set g5 0; set g6 0; set g7 0; set g8 0; set g9 0
        set h0 0; set h1 0; set h2 0; set h3 0; set h4 0
        set h5 0; set h6 0; set h7 0; set h8 0; set h9 0
        set i0 0; set i1 0; set i2 0; set i3 0; set i4 0
        set i5 0; set i6 0; set i7 0; set i8 0; set i9 0
        set j0 0; set j1 0; set j2 0; set j3 0; set j4 0
        set j5 0; set j6 0; set j7 0; set j8 0; set j9 0
        set k0 0; set k1 0; set k2 0; set k3 0; set k4 0
        set k5 0; set k6 0; set k7 0; set k8 0; set k9 0
        set l0 0; set l1 0; set l2 0; set l3 0; set l4 0
        set l5 0; set l6 0; set l7 0; set l8 0; set l9 0
        set m0 0; set m1 0; set m2 0; set m3 0; set m4 0
        set m5 0; set m6 0; set m7 0; set m8 0; set m9 0
        set n0 0; set n1 0; set n2 0; set n3 0; set n4 0
        set n5 0; set n6 0; set n7 0; set n8 0; set n9 0
        set o0 0; set o1 0; set o2 0; set o3 0; set o4 0
        set o5 0; set o6 0; set o7 0; set o8 0; set o9 0
        set p0 0; set p1 0; set p2 0; set p3 0; set p4 0
        set p5 0; set p6 0; set p7 0; set p8 0; set p9 0
        set q0 0; set q1 0; set q2 0; set q3 0; set q4 0
        set q5 0; set q6 0; set q7 0; set q8 0; set q9 0
        set r0 0; set r1 0; set r2 0; set r3 0; set r4 0
        set r5 0; set r6 0; set r7 0; set r8 0; set r9 0
        set s0 0; set s1 0; set s2 0; set s3 0; set s4 0
        set s5 0; set s6 0; set s7 0; set s8 0; set s9 0
        set t0 0; set t1 0; set t2 0; set t3 0; set t4 0
        set t5 0; set t6 0; set t7 0; set t8 0; set t9 0
        set u0 0; set u1 0; set u2 0; set u3 0; set u4 0
        set u5 0; set u6 0; set u7 0; set u8 0; set u9 0
        set v0 0; set v1 0; set v2 0; set v3 0; set v4 0
        set v5 0; set v6 0; set v7 0; set v8 0; set v9 0
        set w0 0; set w1 0; set w2 0; set w3 0; set w4 0
        set w5 0; set w6 0; set w7 0; set w8 0; set w9 0
        set x0 0; set x1 0; set x2 0; set x3 0; set x4 0
        set x5 0; set x6 0; set x7 0; set x8 0; set x9 0
        set y0 0; set y1 0; set y2 0; set y3 0; set y4 0
        set y5 0; set y6 0; set y7 0; set y8 0; set y9 0
        set z0 0; set z1 0; set z2 0; set z3 0; set z4 0
        set z5 0; set z6 0; set z7 0; set z8 0; set z9 0
        # now increment the last one (local var index > 255)
        $z z9
	set z incr
	# create 260 locals
	set a0 0; set a1 0; set a2 0; set a3 0; set a4 0
	set a5 0; set a6 0; set a7 0; set a8 0; set a9 0
	set b0 0; set b1 0; set b2 0; set b3 0; set b4 0
	set b5 0; set b6 0; set b7 0; set b8 0; set b9 0
	set c0 0; set c1 0; set c2 0; set c3 0; set c4 0
	set c5 0; set c6 0; set c7 0; set c8 0; set c9 0
	set d0 0; set d1 0; set d2 0; set d3 0; set d4 0
	set d5 0; set d6 0; set d7 0; set d8 0; set d9 0
	set e0 0; set e1 0; set e2 0; set e3 0; set e4 0
	set e5 0; set e6 0; set e7 0; set e8 0; set e9 0
	set f0 0; set f1 0; set f2 0; set f3 0; set f4 0
	set f5 0; set f6 0; set f7 0; set f8 0; set f9 0
	set g0 0; set g1 0; set g2 0; set g3 0; set g4 0
	set g5 0; set g6 0; set g7 0; set g8 0; set g9 0
	set h0 0; set h1 0; set h2 0; set h3 0; set h4 0
	set h5 0; set h6 0; set h7 0; set h8 0; set h9 0
	set i0 0; set i1 0; set i2 0; set i3 0; set i4 0
	set i5 0; set i6 0; set i7 0; set i8 0; set i9 0
	set j0 0; set j1 0; set j2 0; set j3 0; set j4 0
	set j5 0; set j6 0; set j7 0; set j8 0; set j9 0
	set k0 0; set k1 0; set k2 0; set k3 0; set k4 0
	set k5 0; set k6 0; set k7 0; set k8 0; set k9 0
	set l0 0; set l1 0; set l2 0; set l3 0; set l4 0
	set l5 0; set l6 0; set l7 0; set l8 0; set l9 0
	set m0 0; set m1 0; set m2 0; set m3 0; set m4 0
	set m5 0; set m6 0; set m7 0; set m8 0; set m9 0
	set n0 0; set n1 0; set n2 0; set n3 0; set n4 0
	set n5 0; set n6 0; set n7 0; set n8 0; set n9 0
	set o0 0; set o1 0; set o2 0; set o3 0; set o4 0
	set o5 0; set o6 0; set o7 0; set o8 0; set o9 0
	set p0 0; set p1 0; set p2 0; set p3 0; set p4 0
	set p5 0; set p6 0; set p7 0; set p8 0; set p9 0
	set q0 0; set q1 0; set q2 0; set q3 0; set q4 0
	set q5 0; set q6 0; set q7 0; set q8 0; set q9 0
	set r0 0; set r1 0; set r2 0; set r3 0; set r4 0
	set r5 0; set r6 0; set r7 0; set r8 0; set r9 0
	set s0 0; set s1 0; set s2 0; set s3 0; set s4 0
	set s5 0; set s6 0; set s7 0; set s8 0; set s9 0
	set t0 0; set t1 0; set t2 0; set t3 0; set t4 0
	set t5 0; set t6 0; set t7 0; set t8 0; set t9 0
	set u0 0; set u1 0; set u2 0; set u3 0; set u4 0
	set u5 0; set u6 0; set u7 0; set u8 0; set u9 0
	set v0 0; set v1 0; set v2 0; set v3 0; set v4 0
	set v5 0; set v6 0; set v7 0; set v8 0; set v9 0
	set w0 0; set w1 0; set w2 0; set w3 0; set w4 0
	set w5 0; set w6 0; set w7 0; set w8 0; set w9 0
	set x0 0; set x1 0; set x2 0; set x3 0; set x4 0
	set x5 0; set x6 0; set x7 0; set x8 0; set x9 0
	set y0 0; set y1 0; set y2 0; set y3 0; set y4 0
	set y5 0; set y6 0; set y7 0; set y8 0; set y9 0
	set z0 0; set z1 0; set z2 0; set z3 0; set z4 0
	set z5 0; set z6 0; set z7 0; set z8 0; set z9 0
	# now increment the last one (local var index > 255)
	$z z9
    }
    260locals
} {1}
test incr-2.15 {incr command (not compiled): variable is array} -setup {
    unset -nocomplain a
} -body {
    set z incr
492
493
494
495
496
497
498
499

500
501
502
503
504
505

506
507
508
509
510
511
512
549
550
551
552
553
554
555

556
557
558
559
560
561

562
563
564
565
566
567
568
569







-
+





-
+







    list [catch {incr x 1a} msg] $msg $::errorInfo
} {1 {expected integer but got "1a"} {expected integer but got "1a"
    (reading increment)
    invoked from within
"incr x 1a"}}
test incr-2.32 {incr command (compiled): bad pure list increment} {
    list [catch {incr x [list 1 2]} msg] $msg $::errorInfo
} {1 {expected integer but got "1 2"} {expected integer but got "1 2"
} {1 {expected integer but got a list} {expected integer but got a list
    (reading increment)
    invoked from within
"incr x [list 1 2]"}}
test incr-2.33 {incr command (compiled): bad pure dict increment} {
    list [catch {incr x [dict create 1 2]} msg] $msg $::errorInfo
} {1 {expected integer but got "1 2"} {expected integer but got "1 2"
} {1 {expected integer but got a list} {expected integer but got a list
    (reading increment)
    invoked from within
"incr x [dict create 1 2]"}}

test incr-3.1 {increment by wide amount: bytecode route} {
    set x 0
    incr x 123123123123

Changes to tests/indexObj.test.

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

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
-
+



-
-
+
+










-
+


+

+







# This file is a Tcl script to test out the the procedures in file
# This file is a Tcl script to test out the procedures in file
# tkIndexObj.c, which implement indexed table lookups.  The tests here are
# organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testindexobj [llength [info commands testindexobj]]
testConstraint testgetintforindex [llength [info commands testgetintforindex]]
testConstraint testparseargs [llength [info commands testparseargs]]
testConstraint has64BitLengths [expr {$tcl_platform(pointerSize) == 8}]

test indexObj-1.1 {exact match} testindexobj {
    testindexobj 1 1 xyz abc def xyz alm
} {2}
test indexObj-1.2 {exact match} testindexobj {
    testindexobj 1 1 abc abc def xyz alm
} {0}
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
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







-
+


-
+


-
+


-
+


-
+


-
+




-
+




-
+




-
+



-
+




+
+
+
+
+
+
+
+
+
+
+
+
-
+



-
+


-
+


-
+


-
+



-
-
-
+
+
+
+
+


-
+


-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    set x {a b}
    lindex $x 1
    testindexobj 1 1 $x abc def {a b} zzz
} {2}

test indexObj-5.1 {Tcl_WrongNumArgs} testindexobj {
    testwrongnumargs 1 "?-switch?" mycmd
} "wrong # args: should be \"mycmd ?-switch?\""
} {wrong # args: should be "mycmd ?-switch?"}
test indexObj-5.2 {Tcl_WrongNumArgs} testindexobj {
    testwrongnumargs 2 "bar" mycmd foo
} "wrong # args: should be \"mycmd foo bar\""
} {wrong # args: should be "mycmd foo bar"}
test indexObj-5.3 {Tcl_WrongNumArgs} testindexobj {
    testwrongnumargs 0 "bar" mycmd foo
} "wrong # args: should be \"bar\""
} {wrong # args: should be "bar"}
test indexObj-5.4 {Tcl_WrongNumArgs} testindexobj {
    testwrongnumargs 0 "" mycmd foo
} "wrong # args: should be \"\""
} {wrong # args: should be ""}
test indexObj-5.5 {Tcl_WrongNumArgs} testindexobj {
    testwrongnumargs 1 "" mycmd foo
} "wrong # args: should be \"mycmd\""
} {wrong # args: should be "mycmd"}
test indexObj-5.6 {Tcl_WrongNumArgs} testindexobj {
    testwrongnumargs 2 "" mycmd foo
} "wrong # args: should be \"mycmd foo\""
} {wrong # args: should be "mycmd foo"}
# Contrast this with test proc-3.6; they have to be like this because
# of [Bug 1066837] so Itcl won't break.
test indexObj-5.7 {Tcl_WrongNumArgs} {testindexobj obsolete} {
    testwrongnumargs 2 "fee fi" "fo fum" foo bar
} "wrong # args: should be \"fo fum foo fee fi\""
} {wrong # args: should be "fo fum foo fee fi"}

test indexObj-6.1 {Tcl_GetIndexFromObjStruct} testindexobj {
    set x a
    testgetindexfromobjstruct $x 0
} "wrong # args: should be \"testgetindexfromobjstruct a 0\""
} {wrong # args: should be "testgetindexfromobjstruct a 0"}
test indexObj-6.2 {Tcl_GetIndexFromObjStruct} testindexobj {
    set x a
    testgetindexfromobjstruct $x 0
    testgetindexfromobjstruct $x 0
} "wrong # args: should be \"testgetindexfromobjstruct a 0\""
} {wrong # args: should be "testgetindexfromobjstruct a 0"}
test indexObj-6.3 {Tcl_GetIndexFromObjStruct} testindexobj {
    set x c
    testgetindexfromobjstruct $x 1
} "wrong # args: should be \"testgetindexfromobjstruct c 1\""
} {wrong # args: should be "testgetindexfromobjstruct c 1"}
test indexObj-6.4 {Tcl_GetIndexFromObjStruct} testindexobj {
    set x c
    testgetindexfromobjstruct $x 1
    testgetindexfromobjstruct $x 1
} {wrong # args: should be "testgetindexfromobjstruct c 1"}
test indexObj-6.5 {Tcl_GetIndexFromObjStruct with TCL_EXACT flag} -constraints testindexobj -body {
    set x e
    testgetindexfromobjstruct $x 0 1
} -returnCodes error -result {bad dummy "e": must be a, c, or ee}
test indexObj-6.6 {Tcl_GetIndexFromObjStruct with NULL input} -constraints testindexobj -body {
    set x ""
    testgetindexfromobjstruct $x 0
} -returnCodes error -result {ambiguous dummy "": must be a, c, or ee}
test indexObj-6.7 {Tcl_GetIndexFromObjStruct} testindexobj {
    set x ""
    testgetindexfromobjstruct $x -1 32
} "wrong # args: should be \"testgetindexfromobjstruct c 1\""
} "wrong # args: should be \"testgetindexfromobjstruct {} -1 32\""

test indexObj-7.1 {Tcl_ParseArgsObjv} testparseargs {
    testparseargs
} {0 1 testparseargs}
} {0 1 testparseargs NULL NULL}
test indexObj-7.2 {Tcl_ParseArgsObjv} testparseargs {
    testparseargs -bool
} {1 1 testparseargs}
} {1 1 testparseargs NULL NULL}
test indexObj-7.3 {Tcl_ParseArgsObjv} testparseargs {
    testparseargs -bool bar
} {1 2 {testparseargs bar}}
} {1 2 {testparseargs bar} NULL NULL}
test indexObj-7.4 {Tcl_ParseArgsObjv} testparseargs {
    testparseargs bar
} {0 2 {testparseargs bar}}
} {0 2 {testparseargs bar} NULL NULL}
test indexObj-7.5 {Tcl_ParseArgsObjv} -constraints testparseargs -body {
    testparseargs -help
} -returnCodes error -result {Command-specific options:
 -bool: booltest
 --:    Marks the end of the options
 -help: Print summary of command-line options and abort}
 -bool:      booltest
 -colormode: color mode
 -media:     media page size
 --:         Marks the end of the options
 -help:      Print summary of command-line options and abort}
test indexObj-7.6 {Tcl_ParseArgsObjv} testparseargs {
    testparseargs -- -bool -help
} {0 3 {testparseargs -bool -help}}
} {0 3 {testparseargs -bool -help} NULL NULL}
test indexObj-7.7 {Tcl_ParseArgsObjv memory management} testparseargs {
    testparseargs 1 2 3 4 5 6 7 8 9 0 -bool 1 2 3 4 5 6 7 8 9 0
} {1 21 {testparseargs 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0}}

} {1 21 {testparseargs 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0} NULL NULL}
test indexObj-7.8 {Tcl_ParseArgsObjv} testparseargs {
    testparseargs -color Nothing
} {0 1 testparseargs Nothing NULL}
test indexObj-7.9 {Tcl_ParseArgsObjv} testparseargs {
    testparseargs -media A4
} {0 1 testparseargs NULL {Paper size is ISO A4}}
test indexObj-7.10 {Tcl_ParseArgsObjv} testparseargs {
    testparseargs -media A4 -color Somecolor
} {0 1 testparseargs Somecolor {Paper size is ISO A4}}
test indexObj-7.11 {Tcl_ParseArgsObjv} testparseargs {
    testparseargs -color othercolor -media Letter
} {0 1 testparseargs othercolor {Paper size is US Letter}}
test indexObj-7.12 {Tcl_ParseArgsObjv} -constraints testparseargs -body {
    testparseargs -color othercolor -media Nosuchmedia
} -returnCodes error -result {bad media "Nosuchmedia": must be A4, Legal, or Letter}

test indexObj-8.1 {Tcl_GetIntForIndex integer} testgetintforindex {
    testgetintforindex 0 0
} 0
test indexObj-8.2 {Tcl_GetIntForIndex integer} testgetintforindex {
    testgetintforindex -1 0
} -1
test indexObj-8.3 {Tcl_GetIntForIndex integer} testgetintforindex {
    testgetintforindex -2 0
} -1
test indexObj-8.4 {Tcl_GetIntForIndex INT_MAX} testgetintforindex {
    testgetintforindex 2147483647 0
} 2147483647
test indexObj-8.5 {Tcl_GetIntForIndex INT_MAX+1} testgetintforindex {
    testgetintforindex 2147483648 0
} [expr {[testConstraint has64BitLengths] ? 2147483648 : 2147483647}]
test indexObj-8.6 {Tcl_GetIntForIndex end-1} testgetintforindex {
    testgetintforindex end-1 2147483646
} 2147483645
test indexObj-8.7 {Tcl_GetIntForIndex end-1} testgetintforindex {
    testgetintforindex end-1 2147483647
} 2147483646
test indexObj-8.8 {Tcl_GetIntForIndex end} testgetintforindex {
    testgetintforindex end 2147483646
} 2147483646
test indexObj-8.9 {Tcl_GetIntForIndex end} testgetintforindex {
    testgetintforindex end 2147483647
} 2147483647
test indexObj-8.10 {Tcl_GetIntForIndex end-1} testgetintforindex {
    testgetintforindex end-1 -1
} -2
test indexObj-8.11 {Tcl_GetIntForIndex end-1} testgetintforindex {
    testgetintforindex end-1 -2
} -3
test indexObj-8.12 {Tcl_GetIntForIndex end} testgetintforindex {
    testgetintforindex end -1
} -1
test indexObj-8.13 {Tcl_GetIntForIndex end} testgetintforindex {
    testgetintforindex end -2
} -2
test indexObj-8.14 {Tcl_GetIntForIndex end+1} testgetintforindex {
    testgetintforindex end+1 -1
} [expr {[testConstraint has64BitLengths] ? 9223372036854775807 : 2147483647}]
test indexObj-8.15 {Tcl_GetIntForIndex end+1} testgetintforindex {
    testgetintforindex end+1 -2
} -1
test indexObj-8.16 {Tcl_GetIntForIndex integer} testgetintforindex {
    testgetintforindex -1 -1
} [expr {[testConstraint has64BitLengths] ? -9223372036854775808 : -2147483648}]
test indexObj-8.17 {Tcl_GetIntForIndex integer} testgetintforindex {
    testgetintforindex -2 -1
} [expr {[testConstraint has64BitLengths] ? -9223372036854775808 : -2147483648}]
test indexObj-8.18 {Tcl_GetIntForIndex n-m} testgetintforindex {
    testgetintforindex 2-3 -1
} [expr {[testConstraint has64BitLengths] ? -9223372036854775808 : -2147483648}]
test indexObj-8.19 {Tcl_GetIntForIndex n-m} testgetintforindex {
    testgetintforindex 2-3 0
} -1

# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/info.test.

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
30
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
30







-
-
-
-
+
+
+
+











-
+







# -*- tcl -*-
# Commands covered:  info
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2006      ActiveState
# Copyright © 1991-1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2006 ActiveState
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# DO NOT DELETE THIS LINE

if {{::tcltest} ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}
::tcltest::loadTestedCommands
catch [list package require -exact Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]
testConstraint zlib [llength [info commands zlib]]

# Set up namespaces needed to test operation of "info args", "info body",
# "info default", and "info procs" with imported procedures.

catch {namespace delete test_ns_info1 test_ns_info2}

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
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







-
-
+
+
















-
-
+
+







    proc t1 {a b} {set c 123; set d $c}
    t1 1 2
    info args t1
} {a b}
test info-1.7 {info args option} {
    catch {namespace delete test_ns_info2}
    namespace eval test_ns_info2 {
        namespace import ::test_ns_info1::*
        list [info args p] [info args q]
	namespace import ::test_ns_info1::*
	list [info args p] [info args q]
    }
} {x {y z}}

test info-2.1 {info body option} {
    proc t1 {} {body of t1}
    info body t1
} {body of t1}
test info-2.2 {info body option} -body {
    info body set
} -returnCodes error -result {"set" isn't a procedure}
test info-2.3 {info body option} -body {
    info args set 1
} -returnCodes error -result {wrong # args: should be "info args procname"}
test info-2.4 {info body option} {
    catch {namespace delete test_ns_info2}
    namespace eval test_ns_info2 {
        namespace import ::test_ns_info1::*
        list [info body p] [info body q]
	namespace import ::test_ns_info1::*
	list [info body p] [info body q]
    }
} {{return "x=$x"} {return "y=$y"}}
# Prior to 8.3.0 this would cause a crash because [info body]
# would return the bytecompiled version of foo, which the catch
# would then try and eval out of the foo context, accessing
# compiled local indices
test info-2.5 {info body option, returning bytecompiled bodies} -body {
99
100
101
102
103
104
105
106
107


108
109
110
111
112
113
114
99
100
101
102
103
104
105


106
107
108
109
110
111
112
113
114







-
-
+
+







    eval [info body foo]
} -returnCodes error -result {can't read "args": no such variable}
# Fix for problem tested for in info-2.5 caused problems when
# procedure body had no string rep (i.e. was not yet bytecode)
# causing an empty string to be returned [Bug #545644]
test info-2.6 {info body option, returning list bodies} {
    proc foo args [list subst bar]
    list [string bytelength [info body foo]] \
	    [foo; string bytelength [info body foo]]
    list [string length [info body foo]] \
	    [foo; string length [info body foo]]
} {9 9}

proc testinfocmdcount {} {
    set x [info cmdcount]
    set y 12345
    set z [info cmdc]
    expr {$z-$x}
128
129
130
131
132
133
134
135

136
137
138
139
140
141
142
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142







-
+







} -returnCodes error -result {wrong # args: should be "info cmdcount"}

test info-4.1 {info commands option} -body {
    proc t1 {} {}
    proc t2 {} {}
    set x " [info commands] "
    list [string match {* t1 *} $x] [string match {* t2 *} $x] \
            [string match {* set *} $x] [string match {* list *} $x]
	    [string match {* set *} $x] [string match {* list *} $x]
} -cleanup {unset x} -result {1 1 1 1}
test info-4.2 {info commands option} -body {
    proc t1 {} {}
    rename t1 {}
    string match {* t1 *} \
	[info comm]
} -result 0
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
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







-
-
+
+

















-
-
+
+





-
-
+
+







    set a(0) 88
    proc t1 {{a 18} b} {}
    info default t1 a a
} -returnCodes error -result {can't set "a": variable is array}
test info-6.11 {info default option} {
    catch {namespace delete test_ns_info2}
    namespace eval test_ns_info2 {
        namespace import ::test_ns_info1::*
        list [info default p x foo] $foo [info default q y bar] $bar
	namespace import ::test_ns_info1::*
	list [info default p x foo] $foo [info default q y bar] $bar
    }
} {0 {} 1 27}

test info-7.1 {info exists option} -body {
    set value foo
    info exists value
} -cleanup {unset value} -result 1

test info-7.2 {info exists option} -setup {catch {unset _nonexistent_}} -body {
    info exists _nonexistent_
} -result 0
test info-7.3 {info exists option} {
    proc t1 {x} {return [info exists x]}
    t1 2
} 1
test info-7.4 {info exists option} -body {
    proc t1 {x} {
        global _nonexistent_
        return [info exists _nonexistent_]
	global _nonexistent_
	return [info exists _nonexistent_]
    }
    t1 2
} -setup {unset -nocomplain _nonexistent_} -result 0
test info-7.5 {info exists option} {
    proc t1 {x} {
        set y 47
        return [info exists y]
	set y 47
	return [info exists y]
    }
    t1 2
} 1
test info-7.6 {info exists option} {
    proc t1 {x} {return [info exists value]}
    t1 2
} 0
280
281
282
283
284
285
286
287

288
289
290
291
292
293
294
280
281
282
283
284
285
286

287
288
289
290
291
292
293
294







-
+








test info-8.1 {info globals option} -body {
    set x 1
    set y 2
    set value 23
    set a " [info globals] "
    list [string match {* x *} $a] [string match {* y *} $a] \
            [string match {* value *} $a] [string match {* _foobar_ *} $a]
	    [string match {* value *} $a] [string match {* _foobar_ *} $a]
} -cleanup {unset x y value a} -result {1 1 1 0}
test info-8.2 {info globals option} -body {
    set _xxx1 1
    set _xxx2 2
    lsort [info g _xxx*]
} -cleanup {unset _xxx1 _xxx2} -result {_xxx1 _xxx2}
test info-8.3 {info globals option} -returnCodes error -body {
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
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







-
-
-
+
+
+





-
+


-
-
+
+





-
-
-
+
+
+







}

test info-9.1 {info level option} {
    info level
} 0
test info-9.2 {info level option} {
    proc t1 {a b} {
        set x [info le]
        set y [info level 1]
        list $x $y
	set x [info le]
	set y [info level 1]
	list $x $y
    }
    t1 146 testString
} {1 {t1 146 testString}}
test info-9.3 {info level option} {
    proc t1 {a b} {
        t2 [expr $a*2] $b
	t2 [expr {$a*2}] $b
    }
    proc t2 {x y} {
        list [info level] [info level 1] [info level 2] [info level -1] \
                [info level 0]
	list [info level] [info level 1] [info level 2] [info level -1] \
		[info level 0]
    }
    t1 146 {a {b c} {{{c}}}}
} {2 {t1 146 {a {b c} {{{c}}}}} {t2 292 {a {b c} {{{c}}}}} {t1 146 {a {b c} {{{c}}}}} {t2 292 {a {b c} {{{c}}}}}}
test info-9.4 {info level option} {
    proc t1 {} {
        set x [info level]
        set y [info level 1]
        list $x $y
	set x [info level]
	set y [info level 1]
	list $x $y
    }
    t1
} {1 t1}
test info-9.5 {info level option} -body {
    info level 1 2
} -returnCodes error -result {wrong # args: should be "info level ?number?"}
test info-9.6 {info level option} -body {
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



442
443
444
445
446
447
448


449
450
451
452
453
454
455
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
442
443
444
445
446


447
448
449
450
451
452
453
454
455







-
+







-
-
-
+
+
+


-
+





-
-
-
-
+
+
+
+















-
-
-
+
+
+





-
-
+
+







    unset tcl_library
    info library
} -returnCodes error -result {no library has been specified for Tcl}
set tcl_library $savedLibrary; unset savedLibrary

test info-11.1 {info loaded option} -body {
    info loaded a b c
} -returnCodes error -result {wrong # args: should be "info loaded ?interp? ?packageName?"}
} -returnCodes error -result {wrong # args: should be "info loaded ?interp? ?prefix?"}
test info-11.2 {info loaded option} -body {
    info loaded {}; info loaded gorp
} -returnCodes error -result {could not find interpreter "gorp"}

test info-12.1 {info locals option} -body {
    set a 22
    proc t1 {x y} {
        set b 13
        set c testing
        global a
	set b 13
	set c testing
	global a
	global aa
	set aa 23
        return [info locals]
	return [info locals]
    }
    lsort [t1 23 24]
} -cleanup {unset a aa} -result {b c x y}
test info-12.2 {info locals option} {
    proc t1 {x y} {
        set xx1 2
        set xx2 3
        set y 4
        return [info loc x*]
	set xx1 2
	set xx2 3
	set y 4
	return [info loc x*]
    }
    lsort [t1 2 3]
} {x xx1 xx2}
test info-12.3 {info locals option} -body {
    info locals 1 2
} -returnCodes error -result {wrong # args: should be "info locals ?pattern?"}
test info-12.4 {info locals option} {
    info locals
} {}
test info-12.5 {info locals option} {
    proc t1 {} {return [info locals]}
    t1
} {}
test info-12.6 {info locals vs unset compiled locals} {
    proc t1 {lst} {
        foreach $lst $lst {}
        unset lst
        return [info locals]
	foreach $lst $lst {}
	unset lst
	return [info locals]
    }
    lsort [t1 {a b c c d e f}]
} {a b c d e f}
test info-12.7 {info locals with temporary variables} {
    proc t1 {} {
        foreach a {b c} {}
        info locals
	foreach a {b c} {}
	info locals
    }
    t1
} {a}

test info-13.1 {info nameofexecutable option} -returnCodes error -body {
    info nameofexecutable foo
} -result {wrong # args: should be "info nameofexecutable"}
471
472
473
474
475
476
477
478

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
558
559
560
561
562
563
471
472
473
474
475
476
477

478
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
558
559
560
561
562
563







-
+















-
-
-
+
+
+









-
+












-
+









-
+















-
+


-
+







-
+







} -returnCodes error -result {can't read "tcl_patchLevel": no such variable}

test info-15.1 {info procs option} -body {
    proc t1 {} {}
    proc t2 {} {}
    set x " [info procs] "
    list [string match {* t1 *} $x] [string match {* t2 *} $x] \
            [string match {* _undefined_ *} $x]
	    [string match {* _undefined_ *} $x]
} -cleanup {unset x} -result {1 1 0}
test info-15.2 {info procs option} {
    proc _tt1 {} {}
    proc _tt2 {} {}
    lsort [info pr _tt*]
} {_tt1 _tt2}
catch {rename _tt1 {}}
catch {rename _tt2 {}}
test info-15.3 {info procs option} -body {
    info procs 2 3
} -returnCodes error -result {wrong # args: should be "info procs ?pattern?"}
test info-15.4 {info procs option} -setup {
    catch {namespace delete test_ns_info2}
} -body {
    namespace eval test_ns_info2 {
        namespace import ::test_ns_info1::*
        proc r {} {}
        list [lsort [info procs]] [info procs p*]
	namespace import ::test_ns_info1::*
	proc r {} {}
	list [lsort [info procs]] [info procs p*]
    }
} -result {{p q r} p}
test info-15.5 {info procs option with a proc in a namespace} -setup {
    catch {namespace delete test_ns_info2}
} -body {
    namespace eval test_ns_info2 {
	proc p1 { arg } {
	    puts cmd
	}
        proc p2 { arg } {
	proc p2 { arg } {
	    puts cmd
	}
    }
    info procs ::test_ns_info2::p1
} -result {::test_ns_info2::p1}
test info-15.6 {info procs option with a pattern in a namespace} -setup {
    catch {namespace delete test_ns_info2}
} -body {
    namespace eval test_ns_info2 {
	proc p1 { arg } {
	    puts cmd
	}
        proc p2 { arg } {
	proc p2 { arg } {
	    puts cmd
	}
    }
    lsort [info procs ::test_ns_info2::p*]
} -result [lsort [list ::test_ns_info2::p1 ::test_ns_info2::p2]]
test info-15.7 {info procs option with a global shadowing proc} -setup {
    catch {namespace delete test_ns_info2}
} -body {
    proc string_cmd { arg } {
        puts cmd
	puts cmd
    }
    namespace eval test_ns_info2 {
	proc string_cmd { arg } {
	    puts cmd
	}
    }
    info procs test_ns_info2::string*
} -result {::test_ns_info2::string_cmd}
# This regression test is currently commented out because it requires
# that the implementation of "info procs" looks into the global namespace,
# which it does not (in contrast to "info commands")
test info-15.8 {info procs option with a global shadowing proc} -setup {
    catch {namespace delete test_ns_info2}
} -constraints knownBug -body {
    proc string_cmd { arg } {
        puts cmd
	puts cmd
    }
    proc string_cmd2 { arg } {
        puts cmd
	puts cmd
    }
    namespace eval test_ns_info2 {
	proc string_cmd { arg } {
	    puts cmd
	}
    }
    namespace eval test_ns_info2 {
        lsort [info procs string*]
	lsort [info procs string*]
    }
} -result [lsort [list string_cmd string_cmd2]]

test info-16.1 {info script option} -returnCodes error -body {
    info script x x
} -result {wrong # args: should be "info script ?filename?"}
test info-16.2 {info script option} {
613
614
615
616
617
618
619
620
621
622



623
624
625
626
627
628
629
630
631
632



633
634
635
636
637
638
639
640
641
642
643
644
645


646
647
648
649
650
651
652
653
654
655
656
657
658
659
660

661
662
663
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
613
614
615
616
617
618
619



620
621
622
623
624
625
626
627
628
629



630
631
632
633
634
635
636
637
638
639
640
641
642
643


644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659

660
661
662
663
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







-
-
-
+
+
+







-
-
-
+
+
+











-
-
+
+














-
+




















-
+


-
+


-
+


-
+







    set tcl_version $t; unset t
} -result {can't read "tcl_version": no such variable}

test info-19.1 {info vars option} -body {
    set a 1
    set b 2
    proc t1 {x y} {
        global a b
        set c 33
        return [info vars]
	global a b
	set c 33
	return [info vars]
    }
    lsort [t1 18 19]
} -cleanup {unset a b} -result {a b c x y}
test info-19.2 {info vars option} -body {
    set xxx1 1
    set xxx2 2
    proc t1 {xxa y} {
        global xxx1 xxx2
        set c 33
        return [info vars x*]
	global xxx1 xxx2
	set c 33
	return [info vars x*]
    }
    lsort [t1 18 19]
} -cleanup {unset xxx1 xxx2} -result {xxa xxx1 xxx2}
test info-19.3 {info vars option} {
    lsort [info vars]
} [lsort [info globals]]
test info-19.4 {info vars option} -returnCodes error -body {
    info vars a b
} -result {wrong # args: should be "info vars ?pattern?"}
test info-19.5 {info vars with temporary variables} {
    proc t1 {} {
        foreach a {b c} {}
        info vars
	foreach a {b c} {}
	info vars
    }
    t1
} {a}
test info-19.6 {info vars: Bug 1072654} -setup {
    namespace eval :: unset -nocomplain foo
    catch {namespace delete x}
} -body {
    namespace eval x info vars foo
} -cleanup {
    namespace delete x
} -result {}

set functions {abs acos asin atan atan2 bool ceil cos cosh double entier exp floor fmod hypot int isfinite isinf isnan isnormal isqrt issubnormal isunordered log log10 max min pow rand round sin sinh sqrt srand tan tanh wide}
# Check whether the extra testing functions are defined...
if {!([catch {expr T1()} msg] && ($msg eq {invalid command name "tcl::mathfunc::T1"}))} {
if {!([catch {expr {T1()}} msg] && ($msg eq {invalid command name "tcl::mathfunc::T1"}))} {
    set functions "T1 T2 T3 $functions"  ;# A lazy way of prepending!
}
test info-20.1 {info functions option} {info functions sin} sin
test info-20.2 {info functions option} {lsort [info functions]} $functions
test info-20.3 {info functions option} {
    lsort [info functions a*]
} {abs acos asin atan atan2}
test info-20.4 {info functions option} {
    lsort [info functions *tan*]
} {atan atan2 tan tanh}
test info-20.5 {info functions option} -returnCodes error -body {
    info functions raise an error
} -result {wrong # args: should be "info functions ?pattern?"}
unset functions msg

test info-21.1 {miscellaneous error conditions} -returnCodes error -body {
    info
} -result {wrong # args: should be "info subcommand ?arg ...?"}
test info-21.2 {miscellaneous error conditions} -returnCodes error -body {
    info gorp
} -result {unknown or ambiguous subcommand "gorp": must be args, body, class, cmdcount, cmdtype, commands, complete, coroutine, default, errorstack, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
} -result {unknown or ambiguous subcommand "gorp": must be args, body, class, cmdcount, cmdtype, commands, complete, constant, consts, coroutine, default, errorstack, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
test info-21.3 {miscellaneous error conditions} -returnCodes error -body {
    info c
} -result {unknown or ambiguous subcommand "c": must be args, body, class, cmdcount, cmdtype, commands, complete, coroutine, default, errorstack, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
} -result {unknown or ambiguous subcommand "c": must be args, body, class, cmdcount, cmdtype, commands, complete, constant, consts, coroutine, default, errorstack, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
test info-21.4 {miscellaneous error conditions} -returnCodes error -body {
    info l
} -result {unknown or ambiguous subcommand "l": must be args, body, class, cmdcount, cmdtype, commands, complete, coroutine, default, errorstack, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
} -result {unknown or ambiguous subcommand "l": must be args, body, class, cmdcount, cmdtype, commands, complete, constant, consts, coroutine, default, errorstack, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
test info-21.5 {miscellaneous error conditions} -returnCodes error -body {
    info s
} -result {unknown or ambiguous subcommand "s": must be args, body, class, cmdcount, cmdtype, commands, complete, coroutine, default, errorstack, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
} -result {unknown or ambiguous subcommand "s": must be args, body, class, cmdcount, cmdtype, commands, complete, constant, consts, coroutine, default, errorstack, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}

##
# ### ### ### ######### ######### #########
## info frame

## Helper
# For the more complex results we cut the file name down to remove path
1595
1596
1597
1598
1599
1600
1601
1602
1603


1604
1605
1606
1607
1608
1609
1610
1595
1596
1597
1598
1599
1600
1601


1602
1603
1604
1605
1606
1607
1608
1609
1610







-
-
+
+







} {
type source line 1587 file info.test cmd {info frame 0} proc ::a level 0
type source line 1589 file info.test cmd {info frame 0} proc ::a level 0}

test info-30.17 {bs+nl in multi-body switch, direct} {
    switch -regexp -- {key    } \
	^key     { reduce [info frame 0] ;# 1601 } \
        \t###    { } \
        {[0-9]*} { }
	\t###    { } \
	{[0-9]*} { }
} {type source line 1601 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.18 {bs+nl, literal word, uplevel through proc, appended, loss of primary tracking data} {
    proc abra {script} {
	append script "\n# end of script"
	uplevel 1 $script
    }
1638
1639
1640
1641
1642
1643
1644
1645

1646
1647
1648
1649
1650
1651
1652
1638
1639
1640
1641
1642
1643
1644

1645
1646
1647
1648
1649
1650
1651
1652







-
+








test info-30.20 {bs+nl in single-body switch, direct} {
    switch -regexp -- {key    } { \

	^key     { reduce \
		       [info frame 0] }
	\t###    { }
        {[0-9]*} { }
	{[0-9]*} { }
    }
} {type source line 1643 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.21 {bs+nl in if, full compiled} {
    proc a {value} {
	if {$value} \
	    {info frame 0} \
2392
2393
2394
2395
2396
2397
2398

2399
2400
2401
2402
2403
2404
2405
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406







+







test info-33.35 {{*}, literal, simple, bytecompiled} -body {
    reduce [foo::bar]
} -cleanup {
    namespace delete foo
} -result {type source line 2389 file info.test cmd {info frame 0} proc ::foo::bar level 0}

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

namespace eval ::testinfocmdtype {
    apply {cmds {
	foreach c $cmds {rename $c {}}
    } ::testinfocmdtype} [info commands ::testinfocmdtype::*]
}
test info-40.1 {info cmdtype: syntax} -body {
    info cmdtype
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





} -returnCodes error -cleanup {
    interp delete $safe
} -result {not allowed to invoke subcommand cmdtype of info}
namespace delete ::testinfocmdtype

# -------------------------------------------------------------------------
unset -nocomplain res

test info-19.7 {info vars: bug [0e4b7fce57], TIP #278 - no global vars resolve} -setup {
    catch {namespace delete x}
} -body {
    namespace eval x {info vars}
} -cleanup {
    namespace delete x
} -result {}
test info-19.8 {info vars: bug [0e4b7fce57], TIP #278 - no global vars resolve} -setup {
    catch {namespace delete x}
} -body {
    namespace eval x {info vars tcl_platform}
} -cleanup {
    namespace delete x
} -result {}
test info-19.9 {info vars: global vars resolved by pattern} -setup {
    catch {namespace delete x}
} -body {
    namespace eval x {info vars ::tcl_platform}
} -cleanup {
    namespace delete x
} -result {::tcl_platform}

test info-39.2 {Bug 4b61afd660} -setup {
    proc probe {} {
	return [dict get [info frame -1] line]
    }
    set body {
	set cmd probe
	$cmd
    }
    proc demo {} $body
} -body {
    demo
} -cleanup {
    unset -nocomplain body
    rename demo {}
    rename probe {}
} -result 3

test info-41.0 {Bug 0de6c1d79c crash} -setup {
    interp create child
    child hide info
} -body {
    list [child invokehidden info frame] \
	[child invokehidden info frame 0] \
	[child invokehidden info frame 1] \
	[catch {child invokehidden info frame -1} msg] $msg \
	[catch {child invokehidden info frame 2} msg] $msg
} -cleanup {
    interp delete child
    unset -nocomplain msg
} -result {1 {type precompiled} {type precompiled} 1 {bad level "-1"} 1 {bad level "2"}}

test info-41.1 {Bug 0de6c1d79c crash} -setup {
    interp create child
    child hide info
} -cleanup {
    interp delete child
} -body {
    child invokehidden info frame
} -result 1

# cleanup
catch {namespace delete test_ns_info1 test_ns_info2}
::tcltest::cleanupTests
return

Changes to tests/init.test.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







# Functionality covered: this file contains a collection of tests for the auto
# loading and namespaces.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
26
27
28
29
30
31
32

































33
34
35
36
37
38
39
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







		[if {$v} {set ::errorInfo}] \
	     [set v [info exists ::errorCode]] \
		[if {$v} {set ::errorCode}]
    }
} -cleanup {
    interp delete child
} -result {0 {} 0 {}}

test init-0.2 {no init.tcl from empty tcl_library, bug [43c94f95988f3057]} -setup {
    cd [makeDirectory tmp]
    set fn [makeFile {set ::TEST_INIT 1} init.tcl .]
    unset -nocomplain org_tcl_lib
    if {[info exists ::env(TCL_LIBRARY)]} {
    set org_tcl_lib $::env(TCL_LIBRARY)
    }
    set res [file exists [file join [pwd] init.tcl]]
} -body {
    # first without tcl_library set:
    interp create child
    lappend res [child eval {info exists ::TEST_INIT}]; # must be 0
    interp delete child
    # then with current directory as tcl_library:
    set ::env(TCL_LIBRARY) .
    interp create child
    lappend res [child eval {info exists ::TEST_INIT}]; # must be 1
    interp delete child
    set res
} -cleanup {
    if {[info exists org_tcl_lib]} {
    set ::env(TCL_LIBRARY) $org_tcl_lib
    unset org_tcl_lib
    } else {
    unset -nocomplain ::env(TCL_LIBRARY)
    }
    removeFile $fn
    cd [workingDirectory]
    removeDirectory tmp
    unset -nocomplain res
    catch { interp delete child }
} -result {1 0 1}

# Six cases - white box testing

test init-1.1 {auto_qualify - absolute cmd - namespace} {
    auto_qualify ::foo::bar ::blue
} ::foo::bar
test init-1.2 {auto_qualify - absolute cmd - global} {
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
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







-
+












-
-
+
+


-
+

-
-
+
+









-
+














-
+







    tcl:::HistAdd
} -returnCodes error -cleanup {
    rename ::tcl::HistAdd {}
} -result {wrong # args: should be "tcl:::HistAdd event ?exec?"}

test init-3.0 {random stuff in the auto_index, should still work} {
    set auto_index(foo:::bar::blah) {
        namespace eval foo {namespace eval bar {proc blah {} {return 1}}}
	namespace eval foo {namespace eval bar {proc blah {} {return 1}}}
    }
    foo:::bar::blah
} 1

# Tests that compare the error stack trace generated when autoloading with
# that generated when no autoloading is necessary.  Ideally they should be the
# same.

set count 0
foreach arg [subst -nocommands -novariables {
    c
    {argument
                which spans
                multiple lines}
		which spans
		multiple lines}
    {argument which is all on one line but which is of such great length that the Tcl C library will truncate it when appending it onto the global error stack}
    {argument which spans multiple lines
                and is long enough to be truncated and
		and is long enough to be truncated and
"               <- includes a false lead in the prune point search
                and must be longer still to force truncation}
                {contrived example: rare circumstance
		and must be longer still to force truncation}
		{contrived example: rare circumstance
		where the point at which to prune the
		error stack cannot be uniquely determined.
		foo bar foo
"}
    {contrived example: rare circumstance
		where the point at which to prune the
		error stack cannot be uniquely determined.
		foo bar
"}
    {argument that contains non-ASCII character, \u20ac, and which is of such great length that it will be longer than 150 bytes so it will be truncated by the Tcl C library}
    {argument that contains non-ASCII character, €, and which is of such great length that it will be longer than 150 bytes so it will be truncated by the Tcl C library}
	}] {    ;# emacs needs -> "

    test init-4.$count.0 {::errorInfo produced by [unknown]} -setup {
	auto_reset
    } -body {
	catch {parray a b $arg}
	set first $::errorInfo
	catch {parray a b $arg}
	list $first $::errorInfo
    } -match pairwise -result equal
    test init-4.$count.1 {::errorInfo produced by [unknown]} -setup {
	auto_reset
    } -body {
	namespace eval junk [list array set $arg [list 1 2 3 4]]
	trace variable ::junk::$arg r \
	trace add variable ::junk::$arg read \
		"[list error [subst {Variable \"$arg\" is write-only}]] ;# "
	catch {parray ::junk::$arg}
	set first $::errorInfo
	catch {parray ::junk::$arg}
	list $first $::errorInfo
    } -match pairwise -result equal

Changes to tests/internals.tcl.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







# This file contains internal facilities for Tcl tests.
#
# Source this file in the related tests to include from tcl-tests:
#
#   source [file join [file dirname [info script]] internals.tcl]
#
# Copyright (c) 2020 Sergey G. Brester (sebres).
# Copyright © 2020 Sergey G. Brester (sebres).
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {[namespace which -command ::tcltest::internals::scriptpath] eq ""} {namespace eval ::tcltest::internals {

namespace path ::tcltest
32
33
34
35
36
37
38
39

40
41
42
43
44
45
46
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46







-
+







	set pipe [open |[list [interpreter]] r+]
	set ppid [pid $pipe]
	# create prlimit args:
	set args {}
	# with limited address space:
	if {[info exists in(-addmem)] || [info exists in(-maxmem)]} {
	    if {[info exists in(-addmem)]} {
		# as differnce to normal usage, so try to retrieve current memory usage:
		# as difference to normal usage, so try to retrieve current memory usage:
		if {[catch {
		    # using ps (vsz is in KB):
		    incr in(-addmem) [expr {[lindex [exec ps -hq $ppid -o vsz] end] * 1024}]
		}]} {
		    # ps failed, use default size 20MB:
		    incr in(-addmem) 20000000
		    # + size of locale-archive (may be up to 100MB):
74
75
76
77
78
79
80
81
82


83
84
85
86
87
88
89
74
75
76
77
78
79
80


81
82
83
84
85
86
87
88
89







-
-
+
+







	set result
    } result opt]
    if {$pipe ne ""} { catch { close $pipe } }
    if {$ret && [dict get $opt -errorcode] eq "BYPASS-SKIPPED-TEST"} {
	return {*}$opt $result
    }
    if { ( [info exists in(-warn-on-code)] && $ret in $in(-warn-on-code) )
      || ( $ret && [info exists in(-warn-on-alloc-error)] && $in(-warn-on-alloc-error)
      	    && [regexp {\munable to (?:re)?alloc\M} $result] )
	|| ( $ret && [info exists in(-warn-on-alloc-error)] && $in(-warn-on-alloc-error)
	&& [regexp {\munable to (?:re)?alloc\M} $result] )
    } {
	tcltest::Warn "testWithLimit: wrong limit, result: $result"
	tcltest::Skip testWithLimit
    }
    return {*}$opt $result
}

Changes to tests/interp.test.

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
30
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
30
31
32
33
34
35
36






-
-
+
+










-
+



-
+
+
+
+
+
+
+







# This file tests the multiple interpreter facility of Tcl
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testinterpdelete [llength [info commands testinterpdelete]]

set hidden_cmds {cd encoding exec exit fconfigure file glob load open pwd socket source tcl:encoding:dirs tcl:encoding:system tcl:file:atime tcl:file:attributes tcl:file:copy tcl:file:delete tcl:file:dirname tcl:file:executable tcl:file:exists tcl:file:extension tcl:file:isdirectory tcl:file:isfile tcl:file:link tcl:file:lstat tcl:file:mkdir tcl:file:mtime tcl:file:nativename tcl:file:normalize tcl:file:owned tcl:file:readable tcl:file:readlink tcl:file:rename tcl:file:rootname tcl:file:size tcl:file:stat tcl:file:tail tcl:file:tempdir tcl:file:tempfile tcl:file:type tcl:file:volumes tcl:file:writable tcl:info:cmdtype tcl:info:nameofexecutable tcl:process:autopurge tcl:process:list tcl:process:purge tcl:process:status tcl:zipfs:lmkimg tcl:zipfs:lmkzip tcl:zipfs:mkimg tcl:zipfs:mkkey tcl:zipfs:mkzip tcl:zipfs:mount tcl:zipfs:mount_data tcl:zipfs:unmount unload}
set hidden_cmds {cd encoding exec exit fconfigure file glob load open pwd socket source tcl:encoding:dirs tcl:encoding:system tcl:file:atime tcl:file:attributes tcl:file:copy tcl:file:delete tcl:file:dirname tcl:file:executable tcl:file:exists tcl:file:extension tcl:file:home tcl:file:isdirectory tcl:file:isfile tcl:file:link tcl:file:lstat tcl:file:mkdir tcl:file:mtime tcl:file:nativename tcl:file:normalize tcl:file:owned tcl:file:readable tcl:file:readlink tcl:file:rename tcl:file:rootname tcl:file:size tcl:file:stat tcl:file:tail tcl:file:tempdir tcl:file:tempfile tcl:file:tildeexpand tcl:file:type tcl:file:volumes tcl:file:writable tcl:info:cmdtype tcl:info:nameofexecutable tcl:process:autopurge tcl:process:list tcl:process:purge tcl:process:status tcl:zipfs:canonical tcl:zipfs:exists tcl:zipfs:info tcl:zipfs:list tcl:zipfs:lmkimg tcl:zipfs:lmkzip tcl:zipfs:mkimg tcl:zipfs:mkkey tcl:zipfs:mkzip tcl:zipfs:mount tcl:zipfs:mountdata tcl:zipfs:root tcl:zipfs:unmount unload zipfs}

proc _ms_limit_args {ms {t0 {}}} {
    if {$t0 eq {}} { set t0 [clock milliseconds] }
    incr t0 $ms
    list -seconds [expr {$t0 / 1000}] -milliseconds [expr {$t0 % 1000}]
}

foreach i [interp children] {
  interp delete $i
}

# Part 0: Check out options for interp command
test interp-1.1 {options for interp command} -returnCodes error -body {
101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
116
117

118
119
120
121
122
123
124
107
108
109
110
111
112
113

114
115
116
117
118
119
120
121
122

123
124
125
126
127
128
129
130







-
+








-
+







test interp-2.11 {anonymous interps vs existing procs} {
    set x [interp create]
    regexp "interp(\[0-9]+)" $x dummy thenum
    interp delete $x
    proc interp$thenum {} {}
    set x [interp create]
    regexp "interp(\[0-9]+)" $x dummy anothernum
    expr $anothernum > $thenum
    expr {$anothernum > $thenum}
} 1
test interp-2.12 {anonymous interps vs existing procs} {
    set x [interp create -safe]
    regexp "interp(\[0-9]+)" $x dummy thenum
    interp delete $x
    proc interp$thenum {} {}
    set x [interp create -safe]
    regexp "interp(\[0-9]+)" $x dummy anothernum
    expr $anothernum - $thenum
    expr {$anothernum - $thenum}
} 1
test interp-2.13 {correct default when no $path arg is given} -body {
    interp create --
} -match regexp -result {interp[0-9]+}

foreach i [interp children] {
    interp delete $i
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
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







-
+





-
+


-
+





-
+







} 0

# Recreate interpreter "a"
interp create a

# Part 5: Testing eval in interpreter object command and with interp command
test interp-6.1 {testing eval} {
    a eval expr 3 + 5
    a eval expr {{3 + 5}}
} 8
test interp-6.2 {testing eval} -returnCodes error -body {
    a eval foo
} -result {invalid command name "foo"}
test interp-6.3 {testing eval} {
    a eval {proc foo {} {expr 3 + 5}}
    a eval {proc foo {} {expr {3 + 5}}}
    a eval foo
} 8
catch {a eval {proc foo {} {expr 3 + 5}}}
catch {a eval {proc foo {} {expr {3 + 5}}}}
test interp-6.4 {testing eval} {
    interp eval a foo
} 8
test interp-6.5 {testing eval} {
    interp create {a x2}
    interp eval {a x2} {proc frob {} {expr 4 * 9}}
    interp eval {a x2} {proc frob {} {expr {4 * 9}}}
    interp eval {a x2} frob
} 36
catch {interp create {a x2}}
test interp-6.6 {testing eval} -returnCodes error -body {
    interp eval {a x2} foo
} -result {invalid command name "foo"}

742
743
744
745
746
747
748
749

750
751
752
753
754
755
756
748
749
750
751
752
753
754

755
756
757
758
759
760
761
762







-
+







} ""
test interp-16.5 {testing deletion order, bgerror} {
    catch {interp delete xxx}
    interp create xxx
    xxx eval {proc bgerror {args} {exit}}
    xxx alias exit kill xxx
    proc kill {i} {interp delete $i}
    xxx eval after 100 expr a + b
    xxx eval after 100 expr {a + b}
    after 200
    update
    interp exists xxx
} 0

#
# Alias loop prevention testing.
962
963
964
965
966
967
968
969

970
971
972
973
974
975
976
968
969
970
971
972
973
974

975
976
977
978
979
980
981
982







-
+







    set l
} {foo {}}
test interp-19.9 {alias deletion, renaming} {
    catch {interp delete a}
    interp create a
    interp alias a foo a bar
    interp eval a rename foo blotz
    interp eval a {proc foo {} {expr 34 * 34}}
    interp eval a {proc foo {} {expr {34 * 34}}}
    interp alias a foo {}
    set l [interp eval a foo]
    interp delete a
    set l
} 1156

test interp-20.1 {interp hide, interp expose and interp invokehidden} {
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
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







-
+










-
+




















-
+







    interp delete a
    list $r $msg
} {0 91}
test interp-20.45 {interp hide vs namespaces} {
    catch {interp delete a}
    interp create a
    a eval {
        namespace eval foo {}
	namespace eval foo {}
	proc foo::x {} {}
    }
    set l [list [catch {interp hide a foo::x} msg] $msg]
    interp delete a
    set l
} {1 {cannot use namespace qualifiers in hidden command token (rename)}}
test interp-20.46 {interp hide vs namespaces} {
    catch {interp delete a}
    interp create a
    a eval {
        namespace eval foo {}
	namespace eval foo {}
	proc foo::x {} {}
    }
    set l [list [catch {interp hide a foo::x x} msg] $msg]
    interp delete a
    set l
} {1 {can only hide global namespace commands (use rename then hide)}}
test interp-20.47 {interp hide vs namespaces} {
    catch {interp delete a}
    interp create a
    a eval {
	proc x {} {}
    }
    set l [list [catch {interp hide a x foo::x} msg] $msg]
    interp delete a
    set l
} {1 {cannot use namespace qualifiers in hidden command token (rename)}}
test interp-20.48 {interp hide vs namespaces} {
    catch {interp delete a}
    interp create a
    a eval {
        namespace eval foo {}
	namespace eval foo {}
	proc foo::x {} {}
    }
    set l [list [catch {interp hide a foo::x bar::x} msg] $msg]
    interp delete a
    set l
} {1 {cannot use namespace qualifiers in hidden command token (rename)}}
test interp-20.49 {interp invokehidden -namespace} -setup {
1636
1637
1638
1639
1640
1641
1642
1643

1644
1645
1646
1647
1648
1649
1650
1642
1643
1644
1645
1646
1647
1648

1649
1650
1651
1652
1653
1654
1655
1656







-
+







} -body {
    child hide coroutine
    catch {child invokehidden coroutine} m o
    dict get $o -errorinfo
} -cleanup {
    unset -nocomplain m 0
    interp delete child
} -returnCodes ok -result {wrong # args: should be "coroutine name cmd ?arg ...?"
} -result {wrong # args: should be "coroutine name cmd ?arg ...?"
    while executing
"coroutine"
    invoked from within
"child invokehidden coroutine"}

test interp-21.1 {interp hidden} {
    interp hidden {}
2137
2138
2139
2140
2141
2142
2143
2144

2145
2146
2147
2148
2149
2150
2151
2143
2144
2145
2146
2147
2148
2149

2150
2151
2152
2153
2154
2155
2156
2157







-
+







    proc MyTestAlias {interp args} {
	global aliasTrace
	lappend aliasTrace $args
	interp invokehidden $interp {*}$args
    }
    foreach c {return} {
	interp hide $interp  $c
        interp alias $interp $c {} MyTestAlias $interp $c
	interp alias $interp $c {} MyTestAlias $interp $c
    }
    interp eval $interp {proc ret {code} {return -code $code ret$code}}
    set res {}
    set aliasTrace {}
    for {set code -1} {$code<=5} {incr code} {
	lappend res [catch {interp eval $interp ret $code} msg] $msg
    }
2357
2358
2359
2360
2361
2362
2363
2364

2365
2366
2367
2368
2369
2370
2371
2363
2364
2365
2366
2367
2368
2369

2370
2371
2372
2373
2374
2375
2376
2377







-
+








test interp-28.1 {getting fooled by child's namespace ?} -setup {
    set i [interp create -safe]
    proc parent {interp args} {interp hide $interp list}
} -body {
    $i alias parent parent $i
    set r [interp eval $i {
        namespace eval foo {
	namespace eval foo {
	    proc list {args} {
		return "dummy foo::list"
	    }
	    parent
	}
	info commands list
    }]
2410
2411
2412
2413
2414
2415
2416
2417

2418
2419
2420
2421
2422
2423


2424
2425
2426
2427
2428

2429
2430
2431

2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447

2448
2449
2450
2451
2452
2453


2454
2455
2456
2457
2458

2459
2460
2461

2462
2463
2464
2465
2466
2467
2468
2416
2417
2418
2419
2420
2421
2422

2423
2424
2425
2426
2427


2428
2429
2430
2431
2432
2433

2434
2435
2436

2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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







-
+




-
-
+
+




-
+


-
+















-
+




-
-
+
+




-
+


-
+







} {1 {wrong # args: should be "interp recursionlimit path ?newlimit?"}}
test interp-29.1.4 {interp recursionlimit argument checking} {
    interp create moo
    set result [catch {interp recursionlimit moo bar} msg]
    interp delete moo
    list $result $msg
} {1 {expected integer but got "bar"}}
test interp-29.1.5 {interp recursionlimit argument checking} {
test interp-29.1.5 {interp recursionlimit argument checking} -body {
    interp create moo
    set result [catch {interp recursionlimit moo 0} msg]
    interp delete moo
    list $result $msg
} {1 {recursion limit must be > 0}}
test interp-29.1.6 {interp recursionlimit argument checking} {
} -match glob -result {1 {recursion limit must be > 0}}
test interp-29.1.6 {interp recursionlimit argument checking} -body {
    interp create moo
    set result [catch {interp recursionlimit moo -1} msg]
    interp delete moo
    list $result $msg
} {1 {recursion limit must be > 0}}
} -match glob -result {1 {recursion limit must be > 0}}
test interp-29.1.7 {interp recursionlimit argument checking} {
    interp create moo
    set result [catch {interp recursionlimit moo [expr {wide(1)<<32}]} msg]
    set result [catch {interp recursionlimit moo [expr {wide(1)<<64}]} msg]
    interp delete moo
    list $result [string range $msg 0 35]
} {1 {integer value too large to represent}}
test interp-29.1.8 {child recursionlimit argument checking} {
    interp create moo
    set result [catch {moo recursionlimit foo bar} msg]
    interp delete moo
    list $result $msg
} {1 {wrong # args: should be "moo recursionlimit ?newlimit?"}}
test interp-29.1.9 {child recursionlimit argument checking} {
    interp create moo
    set result [catch {moo recursionlimit foo} msg]
    interp delete moo
    list $result $msg
} {1 {expected integer but got "foo"}}
test interp-29.1.10 {child recursionlimit argument checking} {
test interp-29.1.10 {child recursionlimit argument checking} -body {
    interp create moo
    set result [catch {moo recursionlimit 0} msg]
    interp delete moo
    list $result $msg
} {1 {recursion limit must be > 0}}
test interp-29.1.11 {child recursionlimit argument checking} {
} -match glob -result {1 {recursion limit must be > 0}}
test interp-29.1.11 {child recursionlimit argument checking} -body {
    interp create moo
    set result [catch {moo recursionlimit -1} msg]
    interp delete moo
    list $result $msg
} {1 {recursion limit must be > 0}}
} -match glob -result {1 {recursion limit must be > 0}}
test interp-29.1.12 {child recursionlimit argument checking} {
    interp create moo
    set result [catch {moo recursionlimit [expr {wide(1)<<32}]} msg]
    set result [catch {moo recursionlimit [expr {wide(1)<<64}]} msg]
    interp delete moo
    list $result [string range $msg 0 35]
} {1 {integer value too large to represent}}
test interp-29.2.1 {query recursion limit} {
    interp recursionlimit {}
} 1000
test interp-29.2.2 {query recursion limit} {
2547
2548
2549
2550
2551
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
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







-
+

-
+

-
+















-
+

-
+

-
+















-
+

-
+

-
+




















-
+

-
+

-
+
















-
+

-
+


-
+















-
+

-
+

-
+

















-
+

-
+

-
+
















-
+

-
+


-
+















-
+

-
+

-
+
















-
+

-
+

-
+
















-
+

-
+

-
+
















-
+

-
+


-
+















-
+

-
+

-
+
















-
+

-
+

-
+

















-
+

-
+

-
+
















-
+

-
+

-
+







    }]
   interp delete $i
   set r
} {1 {too many nested evaluations (infinite loop?)} 49}
test interp-29.3.4 {recursion limit error reporting} {
    interp create child
    set r1 [child eval {
        catch { 		# nesting level 1
	catch {			# nesting level 1
	    eval {		# 2
	        eval {		# 3
		eval {		# 3
		    eval {	# 4
		        eval {	# 5
			eval {	# 5
			     interp recursionlimit {} 5
			     set x ok
			}
		    }
		}
	    }
	} msg
    }]
    set r2 [child eval { set msg }]
    interp delete child
    list $r1 $r2
} {1 {falling back due to new recursion limit}}
test interp-29.3.5 {recursion limit error reporting} {
    interp create child
    set r1 [child eval {
        catch {			# nesting level 1
	catch {			# nesting level 1
	    eval {		# 2
	        eval {		# 3
		eval {		# 3
		    eval {	# 4
		        eval {	# 5
			eval {	# 5
			    interp recursionlimit {} 4
			    set x ok
			}
		    }
		}
	    }
	} msg
    }]
    set r2 [child eval { set msg }]
    interp delete child
    list $r1 $r2
} {1 {falling back due to new recursion limit}}
test interp-29.3.6 {recursion limit error reporting} {
    interp create child
    set r1 [child eval {
        catch {			# nesting level 1
	catch {			# nesting level 1
	    eval {		# 2
	        eval {		# 3
		eval {		# 3
		    eval {	# 4
		        eval {	# 5
			eval {	# 5
			    interp recursionlimit {} 6
			    set x ok
			}
		    }
		}
	    }
	} msg
    }]
    set r2 [child eval { set msg }]
    interp delete child
    list $r1 $r2
} {0 ok}
#
# Note that TEBC does not verify the interp's nesting level itself; the nesting
# level will only be verified when it invokes a non-bcc'd command.
#
test interp-29.3.7a {recursion limit error reporting} {
    interp create child
    after 0 {interp recursionlimit child 5}
    set r1 [child eval {
        catch { 		# nesting level 1
	catch {			# nesting level 1
	    eval {		# 2
	        eval {		# 3
		eval {		# 3
		    eval {	# 4
		        eval {	# 5
			eval {	# 5
			    update
			    set x ok
			}
		    }
		}
	    }
	} msg
    }]
    set r2 [child eval { set msg }]
    interp delete child
    list $r1 $r2
} {0 ok}
test interp-29.3.7b {recursion limit error reporting} {
    interp create child
    after 0 {interp recursionlimit child 5}
    set r1 [child eval {
        catch { 		# nesting level 1
	catch {			# nesting level 1
	    eval {		# 2
	        eval {		# 3
		eval {		# 3
		    eval {	# 4
			update
		        eval {	# 5
			eval {	# 5
			    set x ok
			}
		    }
		}
	    }
	} msg
    }]
    set r2 [child eval { set msg }]
    interp delete child
    list $r1 $r2
} {0 ok}
test interp-29.3.7c {recursion limit error reporting} {
    interp create child
    after 0 {interp recursionlimit child 5}
    set r1 [child eval {
        catch { 		# nesting level 1
	catch {			# nesting level 1
	    eval {		# 2
	        eval {		# 3
		eval {		# 3
		    eval {	# 4
		        eval {	# 5
			eval {	# 5
			    update
			    set set set
			    $set x ok
			}
		    }
		}
	    }
	} msg
    }]
    set r2 [child eval { set msg }]
    interp delete child
    list $r1 $r2
} {1 {too many nested evaluations (infinite loop?)}}
test interp-29.3.8a {recursion limit error reporting} {
    interp create child
    after 0 {interp recursionlimit child 4}
    set r1 [child eval {
        catch { 		# nesting level 1
	catch {			# nesting level 1
	    eval {		# 2
	        eval {		# 3
		eval {		# 3
		    eval {	# 4
		        eval {	# 5
			eval {	# 5
			    update
			    set x ok
			}
		    }
		}
	    }
	} msg
    }]
    set r2 [child eval { set msg }]
    interp delete child
    list $r1 $r2
} {0 ok}
test interp-29.3.8b {recursion limit error reporting} {
    interp create child
    after 0 {interp recursionlimit child 4}
    set r1 [child eval {
        catch { 		# nesting level 1
	catch {			# nesting level 1
	    eval {		# 2
	        eval {		# 3
		eval {		# 3
		    eval {	# 4
			update
		        eval {	# 5
			eval {	# 5
			    set x ok
			}
		    }
		}
	    }
	} msg
    }]
    set r2 [child eval { set msg }]
    interp delete child
    list $r1 $r2
} {1 {too many nested evaluations (infinite loop?)}}
test interp-29.3.9a {recursion limit error reporting} {
    interp create child
    after 0 {interp recursionlimit child 6}
    set r1 [child eval {
        catch { 		# nesting level 1
	catch {			# nesting level 1
	    eval {		# 2
	        eval {		# 3
		eval {		# 3
		    eval {	# 4
		        eval {	# 5
			eval {	# 5
			    update
			    set x ok
			}
		    }
		}
	    }
	} msg
    }]
    set r2 [child eval { set msg }]
    interp delete child
    list $r1 $r2
} {0 ok}
test interp-29.3.9b {recursion limit error reporting} {
    interp create child
    after 0 {interp recursionlimit child 6}
    set r1 [child eval {
        catch { 		# nesting level 1
	catch {			# nesting level 1
	    eval {		# 2
	        eval {		# 3
		eval {		# 3
		    eval {	# 4
		        eval {	# 5
			eval {	# 5
			    set set set
			    $set x ok
			}
		    }
		}
	    }
	} msg
    }]
    set r2 [child eval { set msg }]
    interp delete child
    list $r1 $r2
} {0 ok}
test interp-29.3.10a {recursion limit error reporting} {
    interp create child
    after 0 {child recursionlimit 4}
    set r1 [child eval {
        catch { 		# nesting level 1
	catch {			# nesting level 1
	    eval {		# 2
	        eval {		# 3
		eval {		# 3
		    eval {	# 4
		        eval {	# 5
			eval {	# 5
			     update
			     set x ok
			}
		    }
		}
	    }
	} msg
    }]
    set r2 [child eval { set msg }]
    interp delete child
    list $r1 $r2
} {0 ok}
test interp-29.3.10b {recursion limit error reporting} {
    interp create child
    after 0 {child recursionlimit 4}
    set r1 [child eval {
        catch { 		# nesting level 1
	catch {			# nesting level 1
	    eval {		# 2
	        eval {		# 3
		eval {		# 3
		    eval {	# 4
			update
		        eval {	# 5
			eval {	# 5
			    set x ok
			}
		    }
		}
	    }
	} msg
    }]
    set r2 [child eval { set msg }]
    interp delete child
    list $r1 $r2
} {1 {too many nested evaluations (infinite loop?)}}
test interp-29.3.11a {recursion limit error reporting} {
    interp create child
    after 0 {child recursionlimit 5}
    set r1 [child eval {
        catch { 		# nesting level 1
	catch {			# nesting level 1
	    eval {		# 2
	        eval {		# 3
		eval {		# 3
		    eval {	# 4
		        eval {	# 5
			eval {	# 5
			    update
			    set x ok
			}
		    }
		}
	    }
	} msg
    }]
    set r2 [child eval { set msg }]
    interp delete child
    list $r1 $r2
} {0 ok}
test interp-29.3.11b {recursion limit error reporting} {
    interp create child
    after 0 {child recursionlimit 5}
    set r1 [child eval {
        catch { 		# nesting level 1
	catch {			# nesting level 1
	    eval {		# 2
	        eval {		# 3
		eval {		# 3
		    eval {	# 4
		        eval {	# 5
			eval {	# 5
			    update
			    set set set
			    $set x ok
			}
		    }
		}
	    }
	} msg
    }]
    set r2 [child eval { set msg }]
    interp delete child
    list $r1 $r2
} {1 {too many nested evaluations (infinite loop?)}}
test interp-29.3.12a {recursion limit error reporting} {
    interp create child
    after 0 {child recursionlimit 6}
    set r1 [child eval {
        catch { 		# nesting level 1
	catch {			# nesting level 1
	    eval {		# 2
	        eval {		# 3
		eval {		# 3
		    eval {	# 4
		        eval {	# 5
			eval {	# 5
			    update
			    set x ok
			}
		    }
		}
	    }
	} msg
    }]
    set r2 [child eval { set msg }]
    interp delete child
    list $r1 $r2
} {0 ok}
test interp-29.3.12b {recursion limit error reporting} {
    interp create child
    after 0 {child recursionlimit 6}
    set r1 [child eval {
        catch { 		# nesting level 1
	catch {			# nesting level 1
	    eval {		# 2
	        eval {		# 3
		eval {		# 3
		    eval {	# 4
		        eval {	# 5
			eval {	# 5
			    update
			    set set set
			    $set x ok
			}
		    }
		}
	    }
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
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







-
-
-
-
+
+
+
+







-
+


-
-
-
-
+
+
+
+







} {1 {permission denied: safe interpreters cannot change recursion limit}}
test interp-29.6.9 {safe interpreter recursion limit} {
    interp create child -safe
    set result [
	child eval {
	    interp create child2 -safe
	    set n [catch {
	        interp recursionlimit child2 42
            } msg]
            list $n $msg
        }
		interp recursionlimit child2 42
	    } msg]
	    list $n $msg
	}
    ]
    interp delete child
    set result
} {1 {permission denied: safe interpreters cannot change recursion limit}}
test interp-29.6.10 {safe interpreter recursion limit} {
    interp create child -safe
    set result [
        child eval {
	child eval {
	    interp create child2 -safe
	    set n [catch {
	        child2 recursionlimit 42
            } msg]
            list $n $msg
        }
		child2 recursionlimit 42
	    } msg]
	    list $n $msg
	}
    ]
    interp delete child
    set result
} {1 {permission denied: safe interpreters cannot change recursion limit}}


#    # Deep recursion (into interps when the regular one fails):
3096
3097
3098
3099
3100
3101
3102
3103

3104
3105
3106
3107
3108
3109
3110
3102
3103
3104
3105
3106
3107
3108

3109
3110
3111
3112
3113
3114
3115
3116







-
+







    lappend parent [pwd]
    set i [interp create]
    lappend child [$i eval pwd]
    cd ..
    file delete cwd_test
    interp delete $i
    expr {[string equal $parent $child] ? 1 :
             "\{$parent\} != \{$child\}"}
	     "\{$parent\} != \{$child\}"}
} -cleanup {
    cd [workingDirectory]
} -result 1

test interp-33.1 {refCounting for target words of alias [Bug 730244]} {
    # This test will panic if Bug 730244 is not fixed.
    set i [interp create]
3151
3152
3153
3154
3155
3156
3157
3158

3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174

3175
3176
3177
3178
3179
3180
3181
3157
3158
3159
3160
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







-
+















-
+







	proc foobar {} {
	    while {1} {
		# No bytecode at all here...
	    }
	}
    }
    # We use a time limit here; command limits don't trap this case
    $i limit time -seconds [expr {[clock seconds]+2}]
    $i limit time {*}[_ms_limit_args 50]
    $i eval foobar
} -returnCodes error -result {time limit exceeded} -cleanup {
    interp delete $i
}
test interp-34.3.1 {basic test of limits - pure inside-command loop} -body {
    set i [interp create]
    $i eval {
	proc foobar {} {
	    set while while
	    $while {1} {
		# No bytecode at all here...
	    }
	}
    }
    # We use a time limit here; command limits don't trap this case
    $i limit time -seconds [expr {[clock seconds]+2}]
    $i limit time {*}[_ms_limit_args 50]
    $i eval foobar
} -returnCodes error -result {time limit exceeded} -cleanup {
    interp delete $i
}
test interp-34.4 {limits with callbacks: extending limits} -setup {
    set i [interp create]
    set a 0
3189
3190
3191
3192
3193
3194
3195
3196
3197


3198
3199
3200
3201
3202
3203
3204
3195
3196
3197
3198
3199
3200
3201


3202
3203
3204
3205
3206
3207
3208
3209
3210







-
-
+
+







	global c i
	set c b
	$i limit command -value $newlimit
    }
} -body {
    interp alias $i foo {} cb1
    set curlim [$i eval info cmdcount]
    $i limit command -command "cb2 [expr $curlim+100]" \
	    -value [expr {$curlim+10}]
    $i limit command -command "cb2 [expr {$curlim + 100}]" \
	    -value [expr {$curlim + 10}]
    $i eval {for {set i 0} {$i<10} {incr i} {foo}}
    list $a $b $c
} -result {6 4 b} -cleanup {
    interp delete $i
    rename cb1 {}
    rename cb2 {}
}
3218
3219
3220
3221
3222
3223
3224
3225

3226
3227
3228
3229
3230
3231
3232
3224
3225
3226
3227
3228
3229
3230

3231
3232
3233
3234
3235
3236
3237
3238







-
+







	global c i
	set c b
	$i limit command -value $newlimit
    }
} -body {
    interp alias $i foo {} cb1
    set curlim [$i eval info cmdcount]
    $i limit command -command "cb2 {}" -value [expr {$curlim+10}]
    $i limit command -command "cb2 {}" -value [expr {$curlim + 10}]
    $i eval {for {set i 0} {$i<10} {incr i} {foo}}
    list $a $b $c
} -result {6 4 b} -cleanup {
    interp delete $i
    rename cb1 {}
    rename cb2 {}
}
3243
3244
3245
3246
3247
3248
3249
3250

3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269

3270
3271
3272
3273
3274
3275
3276
3249
3250
3251
3252
3253
3254
3255

3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274

3275
3276
3277
3278
3279
3280
3281
3282







-
+


















-
+







	global c i
	set c b
	$i limit command -value {} -command {}
    }
} -body {
    interp alias $i foo {} cb1
    set curlim [$i eval info cmdcount]
    $i limit command -command cb2 -value [expr {$curlim+10}]
    $i limit command -command cb2 -value [expr {$curlim + 10}]
    $i eval {for {set i 0} {$i<10} {incr i} {foo}}
    list $a $b $c
} -result {6 4 b} -cleanup {
    interp delete $i
    rename cb1 {}
    rename cb2 {}
}
test interp-34.7 {limits with callbacks: deleting the handler interp} -setup {
    set i [interp create]
    $i eval {
	set i [interp create]
	proc cb1 {} {
	    global c
	    incr ::$c
	}
	proc cb2 {args} {
	    global c i curlim
	    set c b
	    $i limit command -value [expr {$curlim+1000}]
	    $i limit command -value [expr {$curlim + 1000}]
	    trapToParent
	}
    }
    proc cb3 {} {
	global i subi
	interp alias [list $i $subi] foo {} cb4
	interp delete $i
3285
3286
3287
3288
3289
3290
3291
3292

3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307

3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318


3319
3320
3321
3322

3323
3324

3325
3326
3327
3328
3329
3330
3331

3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343


3344
3345
3346

3347
3348
3349
3350
3351
3352
3353
3354
3355
3356



3357
3358
3359
3360
3361
3362
3363
3364
3365
3366


3367
3368
3369
3370
3371
3372
3373
3374

3375
3376
3377
3378

3379
3380
3381
3382
3383
3384



3385
3386
3387
3388
3389


3390
3391
3392
3393
3394


3395
3396
3397
3398
3399
3400
3401
3402
3403

3404
3405
3406
3407
3408
3409
3410
3411














3412
3413
3414
3415
3416
3417
3418
3291
3292
3293
3294
3295
3296
3297

3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312

3313
3314
3315
3316
3317
3318
3319
3320
3321
3322


3323
3324
3325
3326
3327

3328
3329

3330
3331
3332
3333


3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346


3347
3348
3349
3350

3351
3352
3353
3354
3355
3356
3357
3358



3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369


3370
3371
3372
3373
3374
3375
3376
3377
3378

3379
3380
3381
3382

3383
3384
3385
3386



3387
3388
3389
3390
3391
3392


3393
3394
3395
3396
3397


3398
3399
3400
3401
3402
3403
3404
3405
3406
3407

3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437







-
+














-
+









-
-
+
+



-
+

-
+



-
-


+










-
-
+
+


-
+







-
-
-
+
+
+








-
-
+
+







-
+



-
+



-
-
-
+
+
+



-
-
+
+



-
-
+
+








-
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+







    set n 0
    $i eval {
	set a 0
	set b 0
	set c a
	interp alias $i foo {} cb1
	set curlim [$i eval info cmdcount]
	$i limit command -command cb2 -value [expr {$curlim+10}]
	$i limit command -command cb2 -value [expr {$curlim + 10}]
    }
    $i eval {
	$i eval {
	    for {set i 0} {$i<10} {incr i} {foo}
	}
    }
    list $n [interp exists $i]
} -result {4 0} -cleanup {
    rename cb3 {}
    rename cb4 {}
}
# Bug 1085023
test interp-34.8 {time limits trigger in vwaits} -body {
    set i [interp create]
    interp limit $i time -seconds [expr {[clock seconds]+1}] -granularity 1
    interp limit $i time {*}[_ms_limit_args 50] -granularity 1
    $i eval {
	set x {}
	vwait x
    }
} -cleanup {
    interp delete $i
} -returnCodes error -result {limit exceeded}
test interp-34.9 {time limits trigger in blocking after} {
    set i [interp create]
    set t0 [clock seconds]
    interp limit $i time -seconds [expr {$t0 + 1}] -granularity 1
    set t0 [clock milliseconds]
    interp limit $i time {*}[_ms_limit_args 50 $t0] -granularity 1
    set code [catch {
	$i eval {after 10000}
    } msg]
    set t1 [clock seconds]
    set t1 [clock milliseconds]
    interp delete $i
    list $code $msg [expr {($t1-$t0) < 3 ? "OK" : $t1-$t0}]
    list $code $msg [expr {($t1-$t0) < 1000 ? "OK" : $t1-$t0}]
} {1 {time limit exceeded} OK}
test interp-34.10 {time limits trigger in vwaits: Bug 1221395} -body {
    set i [interp create]
    # Assume someone hasn't set the clock to early 1970!
    $i limit time -seconds 1 -granularity 4
    interp alias $i log {} lappend result
    set result {}
    $i limit time {*}[_ms_limit_args 50] -granularity 4
    catch {
	$i eval {
	    log 1
	    after 100
	    log 2
	}
    } msg
    interp delete $i
    lappend result $msg
} -result {1 {time limit exceeded}}
test interp-34.11 {time limit extension in callbacks} -setup {
    proc cb1 {i t} {
test interp-34.11 {time limit extension in callbacks} -constraints knownBug -setup {
    proc cb1 {i args} {
	global result
	lappend result cb1
	$i limit time -seconds $t -command cb2
	$i limit time {*}[_ms_limit_args {*}$args] -command cb2
    }
    proc cb2 {} {
	global result
	lappend result cb2
    }
} -body {
    set i [interp create]
    set t0 [clock seconds]
    $i limit time -seconds [expr {$t0+1}] -granularity 1 \
	-command "cb1 $i [expr {$t0+2}]"
    set t0 [clock milliseconds]
    $i limit time {*}[_ms_limit_args 50 $t0] \
	-command "cb1 $i 100 $t0"
    set ::result {}
    lappend ::result [catch {
	$i eval {
	    for {set i 0} {$i<30} {incr i} {
		after 100
	    }
	}
    } msg] $msg
    set t1 [clock seconds]
    lappend ::result [expr {$t1-$t0>=2 ? "ok" : "$t0,$t1"}]
    set t1 [clock milliseconds]
    lappend ::result [expr {$t1-$t0>=100 ? "ok" : "$t0,$t1"}]
    interp delete $i
    return $::result
} -result {cb1 cb2 1 {time limit exceeded} ok} -cleanup {
    rename cb1 {}
    rename cb2 {}
}
test interp-34.12 {time limit extension in callbacks} -setup {
    proc cb1 {i} {
    proc cb1 {i t0} {
	global result times
	lappend result cb1
	set times [lassign $times t]
	$i limit time -seconds $t
	$i limit time {*}[_ms_limit_args $t $t0]
    }
} -body {
    set i [interp create]
    set t0 [clock seconds]
    set ::times "[expr {$t0+2}] [expr {$t0+100}]"
    $i limit time -seconds [expr {$t0+1}] -granularity 1 -command "cb1 $i"
    set t0 [clock milliseconds]
    set ::times {100 10000}
    $i limit time {*}[_ms_limit_args 50] -granularity 1 -command "cb1 $i $t0"
    set ::result {}
    lappend ::result [catch {
	$i eval {
	    for {set i 0} {$i<30} {incr i} {
		after 100
	    for {set i 0} {$i<5} {incr i} {
		after 50
	    }
	}
    } msg] $msg
    set t1 [clock seconds]
    lappend ::result [expr {$t1-$t0>=2 ? "ok" : "$t0,$t1"}]
    set t1 [clock milliseconds]
    lappend ::result [expr {$t1-$t0>=100 ? "ok" : "$t0,$t1"}]
    interp delete $i
    return $::result
} -result {cb1 cb1 0 {} ok} -cleanup {
    rename cb1 {}
}
test interp-34.13 {time limit granularity and vwait: Bug 2891362} -setup {
    set i [interp create -safe]
} -body {
    $i limit time -seconds [clock add [clock seconds] 1 second]
    $i limit time {*}[_ms_limit_args 50]
    $i eval {
	after 2000 set x timeout
	vwait x
	return $x
    }
} -cleanup {
    interp delete $i
} -returnCodes error -result {limit exceeded}
test interp-34.14 {[Bug e3f4a8b78d]: interp limit and interp eval} -setup {
    set i [interp create]
    set result {}
} -body {
    $i limit command -value [$i eval {info cmdcount}] -granularity 1
    lappend result [catch {$i eval [list expr 1+3]} msg] $msg
    lappend result [catch {$i eval [list expr 1+3]} msg] $msg
    lappend result [catch {$i eval {set cmd expr; $cmd 1+3}} msg] $msg
    lappend result [catch {$i eval {expr 1+3}} msg] $msg
    lappend result [catch {$i eval expr 1+3} msg] $msg
    lappend result [catch {interp eval $i [list expr 1+3]} msg] $msg
} -cleanup {
    interp delete $i
} -result [lrepeat 6 1 {command count limit exceeded}]

test interp-35.1 {interp limit syntax} -body {
    interp limit
} -returnCodes error -result {wrong # args: should be "interp limit path limitType ?-option value ...?"}
test interp-35.2 {interp limit syntax} -body {
    interp limit {}
} -returnCodes error -result {wrong # args: should be "interp limit path limitType ?-option value ...?"}
3520
3521
3522
3523
3524
3525
3526
3527

3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539

3540
3541
3542
3543
3544
3545
3546
3539
3540
3541
3542
3543
3544
3545

3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557

3558
3559
3560
3561
3562
3563
3564
3565







-
+











-
+







    interp delete $i
} -returnCodes error -result {expected integer but got "foobar"}
test interp-35.19 {interp limit syntax} -body {
    set i [interp create]
    interp limit $i time -seconds -1
} -cleanup {
    interp delete $i
} -returnCodes error -result {seconds must be at least 0}
} -returnCodes error -result {seconds must be non-negative}
test interp-35.20 {interp limit syntax} -body {
    set i [interp create]
    interp limit $i time -millis foobar
} -cleanup {
    interp delete $i
} -returnCodes error -result {expected integer but got "foobar"}
test interp-35.21 {interp limit syntax} -body {
    set i [interp create]
    interp limit $i time -millis -1
} -cleanup {
    interp delete $i
} -returnCodes error -result {milliseconds must be at least 0}
} -returnCodes error -result {milliseconds must be non-negative}
test interp-35.22 {interp time limits normalize milliseconds} -body {
    set i [interp create]
    interp limit $i time -seconds 1 -millis 1500
    list [$i limit time -seconds] [$i limit time -millis]
} -cleanup {
    interp delete $i
} -result {2 500}
3588
3589
3590
3591
3592
3593
3594
3595
3596


3597
3598
3599
3600
3601
3602
3603




3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619


3620
3621
3622
3623
3624
3625
3626
3607
3608
3609
3610
3611
3612
3613


3614
3615
3616
3617
3618




3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636


3637
3638
3639
3640
3641
3642
3643
3644
3645







-
-
+
+



-
-
-
-
+
+
+
+














-
-
+
+







} -result {foo bar soom}
test interp-36.7 {ChildBgerror sets error handler of child [1999035]} -setup {
    interp create child
    child alias handler handler
    child bgerror handler
    variable result {untouched}
    proc handler {args} {
        variable result
        set result [lindex $args 0]
	variable result
	set result [lindex $args 0]
    }
} -body {
    child eval {
        variable done {}
        after 0 error foo
        after 10 [list ::set [namespace which -variable done] {}]
        vwait [namespace which -variable done]
	variable done {}
	after 0 error foo
	after 10 [list ::set [namespace which -variable done] {}]
	vwait [namespace which -variable done]
    }
    set result
} -cleanup {
    variable result {}
    unset -nocomplain result
    interp delete child
} -result foo

test interp-37.1 {safe interps and min() and max(): Bug 2895741} -setup {
    catch {interp delete a}
    interp create a
    set result {}
} -body {
    interp create {a b} -safe
    lappend result [interp eval a {expr min(5,2,3)*max(7,13,11)}]
    lappend result [interp eval {a b} {expr min(5,2,3)*max(7,13,11)}]
    lappend result [interp eval a {expr {min(5,2,3)*max(7,13,11)}}]
    lappend result [interp eval {a b} {expr {min(5,2,3)*max(7,13,11)}}]
} -cleanup {
    unset -nocomplain result
    interp delete a
} -result {26 26}

test interp-38.1 {interp debug one-way switch} -setup {
    catch {interp delete a}
3666
3667
3668
3669
3670
3671
3672

3673
3674
3675
3676
3677
3678
3679
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699







+







} -result {wrong # args: should be "interp debug path ?-frame ?bool??"}

# cleanup
unset -nocomplain hidden_cmds
foreach i [interp children] {
    interp delete $i
}
rename _ms_limit_args {}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:

Changes to tests/io.test.

1
2
3
4
5
6
7
8
9
10
11



12
13
14
15
16
17
18
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
16
17
18








-
-
-
+
+
+







# -*- tcl -*-
# Functionality covered: operation of all IO commands, and all procedures
# defined in generic/tclIO.c.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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
}
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
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







-
-
+
+

-
+

+







+
+
+
-
+

+
+
















-
+












-
-
+
+







    variable n
    variable v
    variable msg
    variable expected

    catch {
	::tcltest::loadTestedCommands
	package require -exact Tcltest [info patchlevel]
	set ::tcltestlib [lindex [package ifneeded Tcltest [info patchlevel]] 1]
	package require -exact tcl::test [info patchlevel]
	set ::tcltestlib [info loaded {} Tcltest]
    }
    package require tcltests
    source [file join [file dirname [info script]] tcltests.tcl]

testConstraint pointerIs64bit [expr {$::tcl_platform(pointerSize) >= 8}]
testConstraint testbytestring [llength [info commands testbytestring]]
testConstraint testchannel      [llength [info commands testchannel]]
testConstraint testfevent       [llength [info commands testfevent]]
testConstraint testchannelevent [llength [info commands testchannelevent]]
testConstraint testmainthread   [llength [info commands testmainthread]]
testConstraint testobj		[llength [info commands testobj]]
testConstraint testservicemode  [llength [info commands testservicemode]]
# Some things fail under Windows in Continuous Integration systems for subtle
# reasons such as CI often running with elevated privileges in a container.
testConstraint notWinCI [expr {
testConstraint knownMsvcBug [expr {![info exists ::env(TRAVIS_OS_NAME)] || ![string match windows $::env(TRAVIS_OS_NAME)]}]
    $::tcl_platform(platform) ne "windows" || ![info exists ::env(CI)]}]
testConstraint notOSX [expr {$::tcl_platform(os) ne "Darwin"}]
# File permissions broken on wsl without some "exotic" wsl configuration
testConstraint notWsl [expr {[llength [array names ::env *WSL*]] == 0}]

# You need a *very* special environment to do some tests.  In
# particular, many file systems do not support large-files...
testConstraint largefileSupport [expr {$::tcl_platform(os) ne "Darwin"}]

# some tests can only be run is umask is 2
# if "umask" cannot be run, the tests will be skipped.
set umaskValue 0
testConstraint umask [expr {![catch {set umaskValue [scan [exec /bin/sh -c umask] %o]}]}]

testConstraint makeFileInHome [expr {![file exists ~/_test_] && [file writable ~]}]

# set up a long data file for some of the following tests

set path(longfile) [makeFile {} longfile]
set f [open $path(longfile) w]
fconfigure $f -eofchar {} -translation lf
fconfigure $f -translation lf
for { set i 0 } { $i < 100 } { incr i} {
    puts $f "#123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
\#123456789abcdef01
\#"
    }
close $f

set path(cat) [makeFile {
    set f stdin
    if {$argv != ""} {
	set f [open [lindex $argv 0]]
    }
    fconfigure $f -encoding binary -translation lf -blocking 0 -eofchar \x1a
    fconfigure stdout -encoding binary -translation lf -buffering none
    fconfigure $f -translation binary -blocking 0 -eofchar \x1A
    fconfigure stdout -translation binary -buffering none
    fileevent $f readable "foo $f"
    proc foo {f} {
	set x [read $f]
	catch {puts -nonewline $x}
	if {[eof $f]} {
	    close $f
	    exit 0
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
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







-
-
+
+


-
+



-
+


-
+













-
+








test io-1.5 {Tcl_WriteChars: CheckChannelErrors} {emptyTest} {
    # no test, need to cause an async error.
} {}
set path(test1) [makeFile {} test1]
test io-1.6 {Tcl_WriteChars: WriteBytes} {
    set f [open $path(test1) w]
    fconfigure $f -encoding binary
    puts -nonewline $f "a\u4e4d\0"
    fconfigure $f -translation binary
    puts -nonewline $f "a\x4D\x00"
    close $f
    contents $path(test1)
} "a\x4d\x00"
} "a\x4D\x00"
test io-1.7 {Tcl_WriteChars: WriteChars} {
    set f [open $path(test1) w]
    fconfigure $f -encoding shiftjis
    puts -nonewline $f "a\u4e4d\0"
    puts -nonewline $f "aä¹\x00"
    close $f
    contents $path(test1)
} "a\x93\xe1\x00"
} "a\x93\xE1\x00"
set path(test2) [makeFile {} test2]
test io-1.8 {Tcl_WriteChars: WriteChars} {
    # This test written for SF bug #506297.
    #
    # Executing this test without the fix for the referenced bug
    # applied to tcl will cause tcl, more specifically WriteChars, to
    # go into an infinite loop.

    set f [open $path(test2) w]
    fconfigure      $f -encoding iso2022-jp
    puts -nonewline $f [format %s%c [string repeat " " 4] 12399]
    close           $f
    contents $path(test2)
} "    \x1b\$B\$O\x1b(B"
} "    \x1B\$B\$O\x1B(B"

test io-1.9 {Tcl_WriteChars: WriteChars} {
    # When closing a channel with an encoding that appends
    # escape bytes, check for the case where the escape
    # bytes overflow the current IO buffer. The bytes
    # should be moved into a new buffer.

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
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+









-
+











-
+







-
+
-





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    fconfigure      $f -encoding iso2022-jp -buffersize 19
    puts -nonewline $f $data
    close           $f
    lappend sizes [file size $path(test2)]

    set sizes
} {19 19 19 19 19}

proc testreadwrite {size {mode ""} args} {
    set tmpfile [file join [temporaryDirectory] io-1.10.tmp]
    set w [string repeat A $size]
    try {
	set fd [open $tmpfile w$mode]
	try {
	    if {[llength $args]} {
		fconfigure $fd {*}$args
	    }
	    puts -nonewline $fd $w
	} finally {
	    close $fd
	}
	set fd [open $tmpfile r$mode]
	try {
	    if {[llength $args]} {
		fconfigure $fd {*}$args
	    }
	    set r [read $fd]
	} finally {
	    close $fd
	}
    } finally {
	file delete $tmpfile
    }
    string equal $w $r
}

test io-1.10 {WriteChars: large file (> INT_MAX). Bug 3d01d51bc4} -constraints {
    pointerIs64bit perf
} -body {
    testreadwrite 0x80000000
} -result 1
test io-1.11 {WriteChars: large file (> UINT_MAX). Bug 3d01d51bc4} -constraints {
    pointerIs64bit perf
} -body {
    testreadwrite 0x100000000 "" -buffersize 1000000
} -result 1
test io-1.12 {WriteChars: large file (== UINT_MAX). Bug 90ff9b7f73} -constraints {
    pointerIs64bit perf
} -body {
    # *Exactly* UINT_MAX - separate bug from the general large file tests
    testreadwrite 0xffffffff
} -result 1

test io-2.1 {WriteBytes} {
    # loop until all bytes are written

    set f [open $path(test1) w]
    fconfigure $f  -encoding binary -buffersize 16 -translation crlf
    fconfigure $f  -translation binary -buffersize 16 -translation crlf
    puts $f "abcdefghijklmnopqrstuvwxyz"
    close $f
    contents $path(test1)
} "abcdefghijklmnopqrstuvwxyz\r\n"
test io-2.2 {WriteBytes: savedLF > 0} {
    # After flushing buffer, there was a \n left over from the last
    # \n -> \r\n expansion.  It gets stuck at beginning of this buffer.

    set f [open $path(test1) w]
    fconfigure $f -encoding binary -buffersize 16 -translation crlf
    fconfigure $f -translation binary -buffersize 16 -translation crlf
    puts -nonewline $f "123456789012345\n12"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} [list "123456789012345\r" "123456789012345\r\n12"]
test io-2.3 {WriteBytes: flush on line} {
    # Tcl "line" buffering has weird behavior: if current buffer contains
    # a \n, entire buffer gets flushed.  Logical behavior would be to flush
    # only up to the \n.

    set f [open $path(test1) w]
    fconfigure $f -encoding binary -buffering line -translation crlf
    fconfigure $f -translation binary -buffering line -translation crlf
    puts -nonewline $f "\n12"
    set x [contents $path(test1)]
    close $f
    set x
} "\r\n12"
test io-2.4 {WriteBytes: reset sawLF after each buffer} {
    set f [open $path(test1) w]
     fconfigure $f -encoding binary -buffering line -translation lf \
     fconfigure $f -translation binary -buffering line -buffersize 16
	     -buffersize 16
    puts -nonewline $f "abcdefg\nhijklmnopqrstuvwxyz"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} [list "abcdefg\nhijklmno" "abcdefg\nhijklmnopqrstuvwxyz"]
test io-2.5 {WriteBytes: large file (> INT_MAX). Bug 3d01d51bc4} -constraints {
    pointerIs64bit perf
} -body {
    # Binary mode
    testreadwrite 0x80000000 b
} -result 1
test io-2.6 {WriteBytes: large file (> UINT_MAX). Bug 3d01d51bc4} -constraints {
    pointerIs64bit perf
} -body {
    # Binary mode
    testreadwrite 0x100000000 b -buffersize 1000000
} -result 1
test io-2.7 {WriteBytes: large file (== UINT_MAX). Bug 90ff9b7f73} -constraints {
    pointerIs64bit perf
} -body {
    # *Exactly* UINT_MAX - separate bug from the general large file tests
    testreadwrite 0xffffffff b
} -result 1


test io-3.1 {WriteChars: compatibility with WriteBytes} {
    # loop until all bytes are written

    set f [open $path(test1) w]
    fconfigure $f -encoding ascii -buffersize 16 -translation crlf
    puts $f "abcdefghijklmnopqrstuvwxyz"
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
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
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







-
+



-
+




+
+
-
-
+
+





-
+




+
+
-
+





-
+


-
+



-
+




-
+







-
+




+
+
-
+









+
+
+
+
+
+
+
+
+







    set f [open $path(test1) w]
    fconfigure $f -encoding ascii -buffering line -translation crlf
    puts -nonewline $f "\n12"
    set x [contents $path(test1)]
    close $f
    set x
} "\r\n12"
test io-3.4 {WriteChars: loop over stage buffer} {
test io-3.4 {WriteChars: loop over stage buffer} -body {
    # stage buffer maps to more than can be queued at once.

    set f [open $path(test1) w]
    fconfigure $f -encoding jis0208 -buffersize 16
    fconfigure $f -encoding jis0208 -buffersize 16 -profile tcl8
    puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} -cleanup {
    catch {close $f}
} [list "!)!)!)!)!)!)!)!)" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test io-3.5 {WriteChars: saved != 0} {
} -result [list "!)!)!)!)!)!)!)!)" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test io-3.5 {WriteChars: saved != 0} -body {
    # Bytes produced by UtfToExternal from end of last channel buffer
    # had to be moved to beginning of next channel buffer to preserve
    # requested buffersize.

    set f [open $path(test1) w]
    fconfigure $f -encoding jis0208 -buffersize 17
    fconfigure $f -encoding jis0208 -buffersize 17 -profile tcl8
    puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} -cleanup {
    catch {close $f}
} [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
} -result [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test io-3.6 {WriteChars: (stageRead + dstWrote == 0)} {
    # One incomplete UTF-8 character at end of staging buffer.  Backup
    # in src to the beginning of that UTF-8 character and try again.
    #
    # Translate the first 16 bytes, produce 14 bytes of output, 2 left over
    # (first two bytes of \uff21 in UTF-8).  Given those two bytes try
    # (first two bytes of A in UTF-8).  Given those two bytes try
    # translating them again, find that no bytes are read produced, and break
    # to outer loop where those two bytes will have the remaining 4 bytes
    # (the last byte of \uff21 plus the all of \uff22) appended.
    # (the last byte of A plus the all of B) appended.

    set f [open $path(test1) w]
    fconfigure $f -encoding shiftjis -buffersize 16
    puts -nonewline $f "12345678901234\uff21\uff22"
    puts -nonewline $f "12345678901234AB"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} [list "12345678901234\x82\x60" "12345678901234\x82\x60\x82\x61"]
test io-3.7 {WriteChars: (bufPtr->nextAdded > bufPtr->length)} {
test io-3.7 {WriteChars: (bufPtr->nextAdded > bufPtr->length)} -body {
    # When translating UTF-8 to external, the produced bytes went past end
    # of the channel buffer.  This is done purpose -- we then truncate the
    # bytes at the end of the partial character to preserve the requested
    # blocksize on flush.  The truncated bytes are moved to the beginning
    # of the next channel buffer.

    set f [open $path(test1) w]
    fconfigure $f -encoding jis0208 -buffersize 17
    fconfigure $f -encoding jis0208 -buffersize 17 -profile tcl8
    puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} -cleanup {
    catch {close $f}
} [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
} -result [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test io-3.8 {WriteChars: reset sawLF after each buffer} {
    set f [open $path(test1) w]
    fconfigure $f -encoding ascii -buffering line -translation lf \
	     -buffersize 16
    puts -nonewline $f "abcdefg\nhijklmnopqrstuvwxyz"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} [list "abcdefg\nhijklmno" "abcdefg\nhijklmnopqrstuvwxyz"]
test io-3.9 {Write: flush line-buffered channels when crlf is split over two buffers} -body {
    # https://core.tcl-lang.org/tcllib/tktedit?name=c9d8a52fe
    set f [open $path(test1) w]
    fconfigure $f -buffering line -translation crlf -buffersize 8
    puts $f "1234567"
    string map {"\r" "<cr>" "\n" "<lf>"} [contents $path(test1)]
} -cleanup {
    close $f
} -result "1234567<cr><lf>"

test io-4.1 {TranslateOutputEOL: lf} {
    # search for \n

    set f [open $path(test1) w]
    fconfigure $f -buffering line -translation lf
    puts $f "abcde"
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
462
463
464
465
466
467
468

469
470
471
472
473
474
475







-







    puts -nonewline $f "12345678901\n456789012345678901234"
    close $f
    set x [contents $path(test1)]
} "12345678901\r\n456789012345678901234"

test io-5.1 {CheckFlush: not full} {
    set f [open $path(test1) w]
    fconfigure $f
    puts -nonewline $f "12345678901234567890"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} [list "" "12345678901234567890"]
test io-5.2 {CheckFlush: full} {
    set f [open $path(test1) w]
444
445
446
447
448
449
450
451

452
453
454
455
456
457
458
459
460
461
462

463
464
465
466
467
468
469

470
471
472
473
474
475
476
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
558
559







-
+










-
+






-
+







    set x [list [tell $f] [gets $f line] [tell $f] [gets $f line] $line]
    close $f
    set x
} {0 3 5 4 defg}
test io-6.4 {Tcl_GetsObj: encoding == NULL} {
    set f [open $path(test1) w]
    fconfigure $f -translation binary
    puts $f "\x81\u1234\0"
    puts $f "\x81\x34\x00"
    close $f
    set f [open $path(test1)]
    fconfigure $f -translation binary
    set x [list [gets $f line] $line]
    close $f
    set x
} [list 3 "\x81\x34\x00"]
test io-6.5 {Tcl_GetsObj: encoding != NULL} {
    set f [open $path(test1) w]
    fconfigure $f -translation binary
    puts $f "\x88\xea\x92\x9a"
    puts $f "\x88\xEA\x92\x9A"
    close $f
    set f [open $path(test1)]
    fconfigure $f -encoding shiftjis
    set x [list [gets $f line] $line]
    close $f
    set x
} [list 2 "\u4e00\u4e01"]
} [list 2 "一ä¸"]
set a "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
append a $a
append a $a
test io-6.6 {Tcl_GetsObj: loop test} {
    # if (dst >= dstEnd)

    set f [open $path(test1) w]
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
575
576
577
578
579
580
581

582
583
584

585
586
587
588
589
590
591

592
593
594

595
596
597
598
599
600
601
602







-
+


-
+






-
+


-
+







    fconfigure $f -blocking 0
    set x [gets $f line]
    close $f
    set x
} {-1}
test io-6.8 {Tcl_GetsObj: remember if EOF is seen} {
    set f [open $path(test1) w]
    puts $f "abcdef\x1aghijk\nwombat"
    puts $f "abcdef\x1Aghijk\nwombat"
    close $f
    set f [open $path(test1)]
    fconfigure $f -eofchar \x1a
    fconfigure $f -eofchar \x1A
    set x [list [gets $f line] $line [gets $f line] $line]
    close $f
    set x
} {6 abcdef -1 {}}
test io-6.9 {Tcl_GetsObj: remember if EOF is seen} {
    set f [open $path(test1) w]
    puts $f "abcdefghijk\nwom\u001abat"
    puts $f "abcdefghijk\nwom\x1Abat"
    close $f
    set f [open $path(test1)]
    fconfigure $f -eofchar \x1a
    fconfigure $f -eofchar \x1A
    set x [list [gets $f line] $line [gets $f line] $line]
    close $f
    set x
} {11 abcdefghijk 3 wom}
# Comprehensive tests
test io-6.10 {Tcl_GetsObj: lf mode: no chars} {
    set f [open $path(test1) w]
888
889
890
891
892
893
894
895

896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912

913
914
915
916
917
918
919
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







-
+
















-
+







    fconfigure $f -translation {auto lf} -buffering none
    puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
    fconfigure $f -buffersize 16
    set x [list [gets $f]]
    fconfigure $f -blocking 0
    lappend x [gets $f line] $line [testchannel queuedcr $f]
    fconfigure $f -blocking 1
    puts -nonewline $f "\nabcd\refg\x1a"
    puts -nonewline $f "\nabcd\refg\x1A"
    lappend x [gets $f line] $line [testchannel queuedcr $f]
    lappend x [gets $f line] $line
    close $f
    set x
} [list "bbbbbbbbbbbbbbb" 15 "123456789abcdef" 1 4 "abcd" 0 3 "efg"]
test io-6.44 {Tcl_GetsObj: input saw cr, not followed by cr} {stdio testchannel fileevent} {
    # not (*eol == '\n')

    set f [open "|[list [interpreter] $path(cat)]" w+]
    fconfigure $f -translation {auto lf} -buffering none
    puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
    fconfigure $f -buffersize 16
    set x [list [gets $f]]
    fconfigure $f -blocking 0
    lappend x [gets $f line] $line [testchannel queuedcr $f]
    fconfigure $f -blocking 1
    puts -nonewline $f "abcd\refg\x1a"
    puts -nonewline $f "abcd\refg\x1A"
    lappend x [gets $f line] $line [testchannel queuedcr $f]
    lappend x [gets $f line] $line
    close $f
    set x
} [list "bbbbbbbbbbbbbbb" 15 "123456789abcdef" 1 4 "abcd" 0 3 "efg"]
test io-6.45 {Tcl_GetsObj: input saw cr, skip right number of bytes} {stdio testchannel fileevent} {
    # Tcl_ExternalToUtf()
939
940
941
942
943
944
945
946

947
948
949
950
951
952
953
1022
1023
1024
1025
1026
1027
1028

1029
1030
1031
1032
1033
1034
1035
1036







-
+







    fconfigure $f -translation {auto lf} -buffering none
    puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
    fconfigure $f -buffersize 16
    gets $f
    fconfigure $f -blocking 0
    set x [list [gets $f line] $line [testchannel queuedcr $f]]
    fconfigure $f -blocking 1
    puts -nonewline $f "\n\x1a"
    puts -nonewline $f "\n\x1A"
    lappend x [gets $f line] $line [testchannel queuedcr $f]
    close $f
    set x
} [list 15 "123456789abcdef" 1 -1 "" 0]
test io-6.47 {Tcl_GetsObj: auto mode: \r at end of buffer, peek for \n} {testchannel} {
    # (eol == dstEnd)

1011
1012
1013
1014
1015
1016
1017
1018

1019
1020
1021

1022
1023
1024
1025
1026
1027
1028
1094
1095
1096
1097
1098
1099
1100

1101
1102
1103

1104
1105
1106
1107
1108
1109
1110
1111







-
+


-
+







    set x
} [list "123456" 7 "78901"]
test io-6.52 {Tcl_GetsObj: saw EOF character} {testchannel} {
    # if (eof != NULL)

    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "123456\x1ak9012345\r"
    puts -nonewline $f "123456\x1Ak9012345\r"
    close $f
    set f [open $path(test1)]
    fconfigure $f -eofchar \x1a
    fconfigure $f -eofchar \x1A
    set x [list [gets $f] [testchannel queuedcr $f] [tell $f] [gets $f]]
    close $f
    set x
} [list "123456" 0 6 ""]
test io-6.53 {Tcl_GetsObj: device EOF} {
    # didn't produce any bytes

1045
1046
1047
1048
1049
1050
1051
1052

1053
1054
1055
1056
1057
1058
1059

1060
1061
1062
1063
1064
1065
1066
1128
1129
1130
1131
1132
1133
1134

1135
1136
1137
1138
1139
1140
1141

1142
1143
1144
1145
1146
1147
1148
1149







-
+






-
+







    set x
} {3 abc 1}
test io-6.55 {Tcl_GetsObj: overconverted} {
    # Tcl_ExternalToUtf(), make sure state updated

    set f [open $path(test1) w]
    fconfigure $f -encoding iso2022-jp
    puts $f "there\u4e00ok\n\u4e01more bytes\nhere"
    puts $f "there一ok\nä¸more bytes\nhere"
    close $f
    set f [open $path(test1)]
    fconfigure $f -encoding iso2022-jp
    set x [list [gets $f line] $line [gets $f line] $line [gets $f line] $line]
    close $f
    set x
} [list 8 "there\u4e00ok" 11 "\u4e01more bytes" 4 "here"]
} [list 8 "there一ok" 11 "ä¸more bytes" 4 "here"]
test io-6.56 {Tcl_GetsObj: incomplete lines should disable file events} {stdio fileevent} {
    update
    set f [open "|[list [interpreter] $path(cat)]" w+]
    fconfigure $f -buffering none
    puts -nonewline $f "foobar"
    fconfigure $f -blocking 0
    variable x {}
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
1116
1117
1118
1119

1120
1121
1122
1123


1124
1125
1126
1127
1128
1129
1130
1131
1132

1133
1134
1135
1136
1137
1138

1139
1140
1141
1142
1143
1144
1145
1162
1163
1164
1165
1166
1167
1168

1169
1170
1171
1172
1173
1174
1175

1176
1177
1178
1179
1180


1181
1182
1183
1184

1185
1186
1187
1188
1189
1190
1191


1192
1193
1194
1195

1196
1197
1198
1199
1200
1201

1202
1203
1204


1205
1206
1207
1208
1209
1210
1211
1212
1213
1214

1215
1216
1217
1218
1219
1220

1221
1222
1223
1224
1225
1226
1227
1228







-
+






-
+




-
-
+
+


-
+






-
-
+
+


-
+





-
+


-
-
+
+








-
+





-
+







} {{} timeout foobarbaz timeout}

test io-7.1 {FilterInputBytes: split up character at end of buffer} {
    # (result == TCL_CONVERT_MULTIBYTE)

    set f [open $path(test1) w]
    fconfigure $f -encoding shiftjis
    puts $f "1234567890123\uff10\uff11\uff12\uff13\uff14\nend"
    puts $f "1234567890123ï¼ï¼‘234\nend"
    close $f
    set f [open $path(test1)]
    fconfigure $f -encoding shiftjis -buffersize 16
    set x [gets $f]
    close $f
    set x
} "1234567890123\uff10\uff11\uff12\uff13\uff14"
} "1234567890123ï¼ï¼‘234"
test io-7.2 {FilterInputBytes: split up character in middle of buffer} {
    # (bufPtr->nextAdded < bufPtr->bufLength)

    set f [open $path(test1) w]
    fconfigure $f -encoding binary
    puts -nonewline $f "1234567890\n123\x82\x4f\x82\x50\x82"
    fconfigure $f -translation binary
    puts -nonewline $f "1234567890\n123\x82\x4F\x82\x50\x82"
    close $f
    set f [open $path(test1)]
    fconfigure $f -encoding shiftjis
    fconfigure $f -encoding shiftjis -profile tcl8
    set x [list [gets $f line] $line [eof $f]]
    close $f
    set x
} [list 10 "1234567890" 0]
test io-7.3 {FilterInputBytes: split up character at EOF} {testchannel} {
    set f [open $path(test1) w]
    fconfigure $f -encoding binary
    puts -nonewline $f "1234567890123\x82\x4f\x82\x50\x82"
    fconfigure $f -translation binary
    puts -nonewline $f "1234567890123\x82\x4F\x82\x50\x82"
    close $f
    set f [open $path(test1)]
    fconfigure $f -encoding shiftjis
    fconfigure $f -encoding shiftjis -profile tcl8
    set x [list [gets $f line] $line]
    lappend x [tell $f] [testchannel inputbuffered $f] [eof $f]
    lappend x [gets $f line] $line
    close $f
    set x
} [list 15 "1234567890123\uff10\uff11" 18 0 1 -1 ""]
} [list 16 "1234567890123ï¼ï¼‘\x82" 18 0 1 -1 ""]
test io-7.4 {FilterInputBytes: recover from split up character} {stdio fileevent} {
    set f [open "|[list [interpreter] $path(cat)]" w+]
    fconfigure $f -encoding binary -buffering none
    puts -nonewline $f "1234567890123\x82\x4f\x82\x50\x82"
    fconfigure $f -translation binary -buffering none
    puts -nonewline $f "1234567890123\x82\x4F\x82\x50\x82"
    fconfigure $f -encoding shiftjis -blocking 0
    fileevent $f read [namespace code "ready $f"]
    variable x {}
    proc ready {f} {
	variable x
	lappend x [gets $f line] $line [fblocked $f]
    }
    vwait [namespace which -variable x]
    fconfigure $f -encoding binary -blocking 1
    fconfigure $f -translation binary -blocking 1
    puts $f "\x51\x82\x52"
    fconfigure $f -encoding shiftjis
    vwait [namespace which -variable x]
    close $f
    set x
} [list -1 "" 1 17 "1234567890123\uff10\uff11\uff12\uff13" 0]
} [list -1 "" 1 17 "1234567890123ï¼ï¼‘23" 0]

test io-8.1 {PeekAhead: only go to device if no more cached data} {testchannel} {
    # (bufPtr->nextPtr == NULL)

    set f [open $path(test1) w]
    fconfigure $f -encoding ascii -translation lf
    puts -nonewline $f "123456789012345\r\n2345678"
1190
1191
1192
1193
1194
1195
1196
1197

1198
1199
1200
1201
1202
1203
1204
1273
1274
1275
1276
1277
1278
1279

1280
1281
1282
1283
1284
1285
1286
1287







-
+







    # not (bytesLeft == 0)

    set f [open $path(test1) w+]
    fconfigure $f -translation binary
    puts $f "${a}\r\nabcdef"
    close $f
    set f [open $path(test1)]
    fconfigure $f -encoding binary -translation auto
    fconfigure $f -translation binary -translation auto

    # "${a}\r" was converted in one operation (because ENCODING_LINESIZE
    # is 30).  To check if "\n" follows, calls PeekAhead and determines
    # that cached data is available in buffer w/o having to call driver.

    set x [gets $f]
    close $f
1233
1234
1235
1236
1237
1238
1239
1240

1241
1242
1243
1244
1245
1246
1247
1316
1317
1318
1319
1320
1321
1322

1323
1324
1325
1326
1327
1328
1329
1330







-
+







    # Make sure bytes are removed from buffer.

    set f [open "|[list [interpreter] $path(cat)]" w+]
    fconfigure $f -translation {auto binary} -buffering none
    puts -nonewline $f "abcdefghijklmno\r"
    # here
    set x [list [gets $f line] $line [testchannel queuedcr $f]]
    puts -nonewline $f "\x1a"
    puts -nonewline $f "\x1A"
    lappend x [gets $f line] $line
    close $f
    set x
} {15 abcdefghijklmno 1 -1 {}}

test io-9.1 {CommonGetsCleanup} emptyTest {
} {}
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

1354
1355
1356
1357
1358
1359
1360
1390
1391
1392
1393
1394
1395
1396

1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409

1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422

1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435

1436
1437
1438
1439
1440
1441
1442
1443







-
+












-
+












-
+












-
+







test io-11.1 {ReadBytes: want to read a lot} {
    # ((unsigned) toRead > (unsigned) srcLen)

    set f [open $path(test1) w]
    puts -nonewline $f abcdefghijkl
    close $f
    set f [open $path(test1)]
    fconfigure $f -encoding binary
    fconfigure $f -translation binary
    # here
    set x [read $f 1000]
    close $f
    set x
} {abcdefghijkl}
test io-11.2 {ReadBytes: want to read all} {
    # ((unsigned) toRead > (unsigned) srcLen)

    set f [open $path(test1) w]
    puts -nonewline $f abcdefghijkl
    close $f
    set f [open $path(test1)]
    fconfigure $f -encoding binary
    fconfigure $f -translation binary
    # here
    set x [read $f]
    close $f
    set x
} {abcdefghijkl}
test io-11.3 {ReadBytes: allocate more space} {
    # (toRead > length - offset - 1)

    set f [open $path(test1) w]
    puts -nonewline $f abcdefghijklmnopqrstuvwxyz
    close $f
    set f [open $path(test1)]
    fconfigure $f -buffersize 16 -encoding binary
    fconfigure $f -buffersize 16 -translation binary
    # here
    set x [read $f]
    close $f
    set x
} {abcdefghijklmnopqrstuvwxyz}
test io-11.4 {ReadBytes: EOF char found} {
    # (TranslateInputEOL() != 0)

    set f [open $path(test1) w]
    puts $f abcdefghijklmnopqrstuvwxyz
    close $f
    set f [open $path(test1)]
    fconfigure $f -eofchar m -encoding binary
    fconfigure $f -translation binary -eofchar m
    # here
    set x [list [read $f] [eof $f] [read $f] [eof $f]]
    close $f
    set x
} [list "abcdefghijkl" 1 "" 1]

test io-12.1 {ReadChars: want to read a lot} {
1394
1395
1396
1397
1398
1399
1400
1401

1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415


1416
1417
1418
1419
1420
1421

1422
1423
1424
1425


1426
1427

1428
1429
1430
1431
1432
1433
1434
1477
1478
1479
1480
1481
1482
1483

1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496


1497
1498
1499
1500
1501
1502
1503

1504
1505
1506


1507
1508
1509

1510
1511
1512
1513
1514
1515
1516
1517







-
+












-
-
+
+





-
+


-
-
+
+

-
+







    close $f
    set x
} {abcdefghijklmnopqrstuvwxyz}
test io-12.4 {ReadChars: split-up char} {stdio testchannel fileevent} {
    # (srcRead == 0)

    set f [open "|[list [interpreter] $path(cat)]" w+]
    fconfigure $f -encoding binary -buffering none -buffersize 16
    fconfigure $f -translation binary -buffering none -buffersize 16
    puts -nonewline $f "123456789012345\x96"
    fconfigure $f -encoding shiftjis -blocking 0

    fileevent $f read [namespace code "ready $f"]
    proc ready {f} {
	variable x
	lappend x [read $f] [testchannel inputbuffered $f]
    }
    variable x {}

    fconfigure $f -encoding shiftjis
    vwait [namespace which -variable x]
    fconfigure $f -encoding binary -blocking 1
    puts -nonewline $f "\x7b"
    fconfigure $f -translation binary -blocking 1
    puts -nonewline $f "\x7B"
    after 500			;# Give the cat process time to catch up
    fconfigure $f -encoding shiftjis -blocking 0
    vwait [namespace which -variable x]
    close $f
    set x
} [list "123456789012345" 1 "\u672c" 0]
} [list "123456789012345" 1 "本" 0]
test io-12.5 {ReadChars: fileevents on partial characters} {stdio fileevent} {
    set path(test1) [makeFile {
	fconfigure stdout -encoding binary -buffering none
	gets stdin; puts -nonewline "\xe7"
	fconfigure stdout -translation binary -buffering none
	gets stdin; puts -nonewline "\xE7"
	gets stdin; puts -nonewline "\x89"
	gets stdin; puts -nonewline "\xa6"
	gets stdin; puts -nonewline "\xA6"
    } test1]
    set f [open "|[list [interpreter] $path(test1)]" r+]
    fileevent $f readable [namespace code {
	lappend x [read $f]
	if {[eof $f]} {
	    lappend x eof
	}
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
1474
1475
1476
1477
1478
1479























1480
1481
1482
1483
1484

1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512























1513
1514
1515
1516
1517

1518
1519
1520
1521
1522
1523
1524

1525
1526
1527
1528
1529
1530
1531
1532

1533
1534
1535

1536
1537
1538

1539









1540




1541
1542
1543





1544
1545
1546

1547
1548
1549

1550
1551
1552
1553



1554
1555
1556
1557
1558
1559
1560
1530
1531
1532
1533
1534
1535
1536

1537
1538
1539























1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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







-
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+






-
+







-
+


-
+


-
+

+
+
+
+
+
+
+
+
+

+
+
+
+

-
-
+
+
+
+
+


-
+


-
+



-
+
+
+







    vwait [namespace which -variable x]
    puts $f "go3"
    flush $f
    vwait [namespace which -variable x]
    vwait [namespace which -variable x]
    lappend x [catch {close $f} msg] $msg
    set x
} "{} timeout {} timeout \u7266 {} eof 0 {}"
} "{} timeout {} timeout 牦 {} eof 0 {}"
test io-12.6 {ReadChars: too many chars read} {
    proc driver {cmd args} {
        variable buffer
        variable index
        set chan [lindex $args 0]
        switch -- $cmd {
            initialize {
                set index($chan) 0
                set buffer($chan) [encoding convertto utf-8 \
                        [string repeat \uBEEF 20][string repeat . 20]]
                return {initialize finalize watch read}
            }
            finalize {
                unset index($chan) buffer($chan)
                return
            }
            watch {}
            read {
                set n [lindex $args 1]
                set new [expr {$index($chan) + $n}]
                set result [string range $buffer($chan) $index($chan) $new-1]
                set index($chan) $new
                return $result
            }
        }
	variable buffer
	variable index
	set chan [lindex $args 0]
	switch -- $cmd {
	    initialize {
		set index($chan) 0
		set buffer($chan) [encoding convertto utf-8 \
			[string repeat 뻯 20][string repeat . 20]]
		return {initialize finalize watch read}
	    }
	    finalize {
		unset index($chan) buffer($chan)
		return
	    }
	    watch {}
	    read {
		set n [lindex $args 1]
		set new [expr {$index($chan) + $n}]
		set result [string range $buffer($chan) $index($chan) $new-1]
		set index($chan) $new
		return $result
	    }
	}
    }
    set c [chan create read [namespace which driver]]
    chan configure $c -encoding utf-8
    while {![eof $c]} {
        read $c 15
	read $c 15
    }
    close $c
} {}
test io-12.7 {ReadChars: too many chars read [bc5b790099]} {
    proc driver {cmd args} {
        variable buffer
        variable index
        set chan [lindex $args 0]
        switch -- $cmd {
            initialize {
                set index($chan) 0
                set buffer($chan) [encoding convertto utf-8 \
                        [string repeat \uBEEF 10]....\uBEEF]
                return {initialize finalize watch read}
            }
            finalize {
                unset index($chan) buffer($chan)
                return
            }
            watch {}
            read {
                set n [lindex $args 1]
                set new [expr {$index($chan) + $n}]
                set result [string range $buffer($chan) $index($chan) $new-1]
                set index($chan) $new
                return $result
            }
        }
	variable buffer
	variable index
	set chan [lindex $args 0]
	switch -- $cmd {
	    initialize {
		set index($chan) 0
		set buffer($chan) [encoding convertto utf-8 \
			[string repeat 뻯 10]....뻯]
		return {initialize finalize watch read}
	    }
	    finalize {
		unset index($chan) buffer($chan)
		return
	    }
	    watch {}
	    read {
		set n [lindex $args 1]
		set new [expr {$index($chan) + $n}]
		set result [string range $buffer($chan) $index($chan) $new-1]
		set index($chan) $new
		return $result
	    }
	}
    }
    set c [chan create read [namespace which driver]]
    chan configure $c -encoding utf-8
    while {![eof $c]} {
        read $c 7
	read $c 7
    }
    close $c
} {}
test io-12.8 {ReadChars: multibyte chars split} {
    set f [open $path(test1) w]
    fconfigure $f -translation binary
    puts -nonewline $f [string repeat a 9]\xc2\xa0
    puts -nonewline $f [string repeat a 9]\xC2\xA0
    close $f
    set f [open $path(test1)]
    fconfigure $f -encoding utf-8 -buffersize 10
    set in [read $f]
    close $f
    scan [string index $in end] %c
} 160
test io-12.9 {ReadChars: multibyte chars split} {
test io-12.9 {ReadChars: multibyte chars split} -body {
    set f [open $path(test1) w]
    fconfigure $f -translation binary
    puts -nonewline $f [string repeat a 9]\xc2
    puts -nonewline $f [string repeat a 9]\xC2
    close $f
    set f [open $path(test1)]
    fconfigure $f -encoding utf-8 -buffersize 10
    fconfigure $f -encoding utf-8 -profile tcl8 -buffersize 10
    set in [read $f]
    read $f
    scan [string index $in end] %c
} -cleanup {
    catch {close $f}
} -result 194
test io-12.10 {ReadChars: multibyte chars split} -body {
    set f [open $path(test1) w]
    fconfigure $f -translation binary
    puts -nonewline $f [string repeat a 9]\xC2
    close $f
    set f [open $path(test1)]
    fconfigure $f -encoding utf-8 -profile strict -buffersize 10
    set in [read $f]
    close $f
    scan [string index $in end] %c
} 194
test io-12.10 {ReadChars: multibyte chars split} {
} -cleanup {
    catch {close $f}
} -returnCodes 1 -match glob -result {error reading "file*":\
	invalid or incomplete multibyte or wide character}
test io-12.11 {ReadChars: multibyte chars split} -body {
    set f [open $path(test1) w]
    fconfigure $f -translation binary
    puts -nonewline $f [string repeat a 9]\xc2
    puts -nonewline $f [string repeat a 9]\xC2
    close $f
    set f [open $path(test1)]
    fconfigure $f -encoding utf-8 -buffersize 11
    fconfigure $f -encoding utf-8 -profile tcl8 -buffersize 10
    set in [read $f]
    close $f
    scan [string index $in end] %c
} 194
} -cleanup {
    catch {close $f}
} -result 194

test io-13.1 {TranslateInputEOL: cr mode} {} {
    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "abcd\rdef\r"
    close $f
    set f [open $path(test1)]
1725
1726
1727
1728
1729
1730
1731
1732

1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745

1746
1747
1748
1749
1750
1751
1752
1826
1827
1828
1829
1830
1831
1832

1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845

1846
1847
1848
1849
1850
1851
1852
1853







-
+












-
+







    set f [open $path(test1)]
    fconfigure $f -translation auto
    set x [read $f]
    close $f
    set x
} "abcd\ndef"
test io-13.11 {TranslateInputEOL: EOF char} {
    # (*chanPtr->inEofChar != '\0')
    # (*chanPtr->inEofChar != '\x00')

    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "abcd\ndefgh"
    close $f
    set f [open $path(test1)]
    fconfigure $f -translation auto -eofchar e
    set x [read $f]
    close $f
    set x
} "abcd\nd"
test io-13.12 {TranslateInputEOL: find EOF char in src} {
    # (*chanPtr->inEofChar != '\0')
    # (*chanPtr->inEofChar != '\x00')

    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f "\r\n\r\n\r\nab\r\n\r\ndef\r\n\r\n\r\n"
    close $f
    set f [open $path(test1)]
    fconfigure $f -translation auto -eofchar e
1897
1898
1899
1900
1901
1902
1903
1904

1905
1906
1907
1908
1909
1910
1911
1998
1999
2000
2001
2002
2003
2004

2005
2006
2007
2008
2009
2010
2011
2012







-
+







    set c
} hello
test io-14.9 {reuse of stdio special channels} {stdio fileevent} {
    file delete $path(script)
    file delete $path(test1)
    set f [open $path(script) w]
    puts $f {
        array set path [lindex $argv 0]
	array set path [lindex $argv 0]
	set f [open $path(test1) w]
	puts $f hello
	close $f
	close stderr
	set f [open "|[list [info nameofexecutable] $path(cat) $path(test1)]" r]
	puts [gets $f]
    }
1936
1937
1938
1939
1940
1941
1942
1943

1944
1945

1946
1947

1948
1949
1950
1951
1952
1953
1954
1955

1956
1957

1958
1959

1960
1961
1962
1963
1964
1965
1966
1967

1968
1969

1970
1971

1972
1973
1974
1975
1976
1977
1978
2037
2038
2039
2040
2041
2042
2043

2044
2045

2046
2047

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







-
+

-
+

-
+







-
+

-
+

-
+







-
+

-
+

-
+







# channels are added to the channel table of the interpreter.

test io-17.1 {GetChannelTable, DeleteChannelTable on std handles} {testchannel} {
    set l1 [testchannel refcount stdin]
    eof stdin
    interp create x
    set l ""
    lappend l [expr [testchannel refcount stdin] - $l1]
    lappend l [expr {[testchannel refcount stdin] - $l1}]
    x eval {eof stdin}
    lappend l [expr [testchannel refcount stdin] - $l1]
    lappend l [expr {[testchannel refcount stdin] - $l1}]
    interp delete x
    lappend l [expr [testchannel refcount stdin] - $l1]
    lappend l [expr {[testchannel refcount stdin] - $l1}]
    set l
} {0 1 0}
test io-17.2 {GetChannelTable, DeleteChannelTable on std handles} {testchannel} {
    set l1 [testchannel refcount stdout]
    eof stdin
    interp create x
    set l ""
    lappend l [expr [testchannel refcount stdout] - $l1]
    lappend l [expr {[testchannel refcount stdout] - $l1}]
    x eval {eof stdout}
    lappend l [expr [testchannel refcount stdout] - $l1]
    lappend l [expr {[testchannel refcount stdout] - $l1}]
    interp delete x
    lappend l [expr [testchannel refcount stdout] - $l1]
    lappend l [expr {[testchannel refcount stdout] - $l1}]
    set l
} {0 1 0}
test io-17.3 {GetChannelTable, DeleteChannelTable on std handles} {testchannel} {
    set l1 [testchannel refcount stderr]
    eof stdin
    interp create x
    set l ""
    lappend l [expr [testchannel refcount stderr] - $l1]
    lappend l [expr {[testchannel refcount stderr] - $l1}]
    x eval {eof stderr}
    lappend l [expr [testchannel refcount stderr] - $l1]
    lappend l [expr {[testchannel refcount stderr] - $l1}]
    interp delete x
    lappend l [expr [testchannel refcount stderr] - $l1]
    lappend l [expr {[testchannel refcount stderr] - $l1}]
    set l
} {0 1 0}

test io-18.1 {Tcl_RegisterChannel, Tcl_UnregisterChannel} {testchannel} {
    file delete -force $path(test1)
    set l ""
    set f [open $path(test1) w]
2067
2068
2069
2070
2071
2072
2073
2074

2075
2076
2077
2078
2079
2080

2081
2082
2083
2084
2085
2086
2087
2168
2169
2170
2171
2172
2173
2174

2175
2176
2177
2178
2179
2180

2181
2182
2183
2184
2185
2186
2187
2188







-
+





-
+







    set x
} {ascii}
test io-20.2 {Tcl_CreateChannel: initial settings} {win} {
    set f [open $path(test1) w+]
    set x [list [fconfigure $f -eofchar] [fconfigure $f -translation]]
    close $f
    set x
} [list [list \x1a ""] {auto crlf}]
} {{} {auto crlf}}
test io-20.3 {Tcl_CreateChannel: initial settings} {unix} {
    set f [open $path(test1) w+]
    set x [list [fconfigure $f -eofchar] [fconfigure $f -translation]]
    close $f
    set x
} {{{} {}} {auto lf}}
} {{} {auto lf}}
set path(stdout) [makeFile {} stdout]
test io-20.5 {Tcl_CreateChannel: install channel in empty slot} stdio {
    set f [open $path(script) w]
    puts -nonewline $f {
	close stdout
	set f1 [}
    puts $f [list open $path(stdout) w]]
2122
2123
2124
2125
2126
2127
2128
2129

2130
2131
2132
2133
2134
2135
2136
2223
2224
2225
2226
2227
2228
2229

2230
2231
2232
2233
2234
2235
2236
2237







-
+







    set t [testchannel type $f]
    close $f
    string compare $t file
} 0

test io-25.1 {Tcl_GetChannelHandle, input} {testchannel} {
    set f [open $path(test1) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    puts $f "1234567890\n098765432"
    close $f
    set f [open $path(test1) r]
    gets $f
    set l ""
    lappend l [testchannel inputbuffered $f]
    lappend l [tell $f]
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2255
2256
2257
2258
2259
2260
2261

2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278

2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291

2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302

2303
2304
2305
2306
2307
2308
2309
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







-
+
















-
+












-
+










-
+
















-
+













-
+







-
+









-
+













-
+

-
+







} {6 6 0 6}

test io-26.1 {Tcl_GetChannelInstanceData} stdio {
    # "pid" command uses Tcl_GetChannelInstanceData
    # Don't care what pid is (but must be a number), just want to exercise it.

    set f [open "|[list [interpreter] << exit]"]
    expr [pid $f]
    expr {[pid $f]}
    close $f
} {}

# Test flushing. The functions tested here are FlushChannel.

test io-27.1 {FlushChannel, no output buffered} {
    file delete $path(test1)
    set f [open $path(test1) w]
    flush $f
    set s [file size $path(test1)]
    close $f
    set s
} 0
test io-27.2 {FlushChannel, some output buffered} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    set l ""
    puts $f hello
    lappend l [file size $path(test1)]
    flush $f
    lappend l [file size $path(test1)]
    close $f
    lappend l [file size $path(test1)]
    set l
} {0 6 6}
test io-27.3 {FlushChannel, implicit flush on close} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    set l ""
    puts $f hello
    lappend l [file size $path(test1)]
    close $f
    lappend l [file size $path(test1)]
    set l
} {0 6}
test io-27.4 {FlushChannel, implicit flush when buffer fills} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    fconfigure $f -buffersize 60
    set l ""
    lappend l [file size $path(test1)]
    for {set i 0} {$i < 12} {incr i} {
	puts $f hello
    }
    lappend l [file size $path(test1)]
    flush $f
    lappend l [file size $path(test1)]
    close $f
    set l
} {0 60 72}
test io-27.5 {FlushChannel, implicit flush when buffer fills and on close} \
	{unixOrWin} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf -buffersize 60 -eofchar {}
    fconfigure $f -translation lf -buffersize 60
    set l ""
    lappend l [file size $path(test1)]
    for {set i 0} {$i < 12} {incr i} {
	puts $f hello
    }
    lappend l [file size $path(test1)]
    close $f
    lappend l [file size $path(test1)]
    set l
} {0 60 72}
set path(pipe)   [makeFile {} pipe]
set path(output) [makeFile {} output]
test io-27.6 {FlushChannel, async flushing, async close} \
	{stdio asyncPipeClose knownMsvcBug} {
	{stdio asyncPipeClose notWinCI} {
    # This test may fail on old Unix systems (seen on IRIX64 6.5) with
    # obsolete gettimeofday() calls.  See Tcl Bugs 3530533, 1942197.
    file delete $path(pipe)
    file delete $path(output)
    set f [open $path(pipe) w]
    puts $f "set f \[[list open $path(output) w]]"
    puts $f {
	fconfigure $f -translation lf -buffering none -eofchar {}
	fconfigure $f -translation lf -buffering none
	while {![eof stdin]} {
	    after 20
	    puts -nonewline $f [read stdin 1024]
	}
	close $f
    }
    close $f
    set x 01234567890123456789012345678901
    for {set i 0} {$i < 11} {incr i} {
        set x "$x$x"
	set x "$x$x"
    }
    set f [open $path(output) w]
    close $f
    set f [open "|[list [interpreter] $path(pipe)]" w]
    fconfigure $f -blocking off
    puts -nonewline $f $x
    close $f
    set counter 0
    while {([file size $path(output)] < 65536) && ($counter < 1000)} {
	after 20 [list incr [namespace which -variable counter]]
	vwait [namespace which -variable counter]
    }
    if {$counter == 1000} {
        set result "file size only [file size $path(output)]"
	set result "file size only [file size $path(output)]"
    } else {
        set result ok
	set result ok
    }
} ok

# Tests closing a channel. The functions tested are CloseChannel and Tcl_Close.

test io-28.1 {CloseChannel called when all references are dropped} {testchannel} {
    file delete $path(test1)
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2402
2403
2404
2405
2406
2407
2408







2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419

2420
2421
2422
2423
2424

2425
2426
2427
2428
2429
2430
2431
2432
2433
2434

2435
2436

2437
2438
2439

2440
2441

2442
2443
2444
2445
2446
2447
2448
2449







-
-
-
-
-
-
-











-
+




-
+









-
+

-
+


-
+

-
+







test io-28.3 {CloseChannel, not called before output queue is empty} \
	{stdio asyncPipeClose nonPortable} {
    file delete $path(pipe)
    file delete $path(output)
    set f [open $path(pipe) w]
    puts $f {

	# Need to not have eof char appended on close, because the other
	# side of the pipe already closed, so that writing would cause an
	# error "invalid file".

	fconfigure stdout -eofchar {}
	fconfigure stderr -eofchar {}

	set f [open $path(output) w]
	fconfigure $f -translation lf -buffering none
	for {set x 0} {$x < 20} {incr x} {
	    after 20
	    puts -nonewline $f [read stdin 1024]
	}
	close $f
    }
    close $f
    set x 01234567890123456789012345678901
    for {set i 0} {$i < 11} {incr i} {
        set x "$x$x"
	set x "$x$x"
    }
    set f [open $path(output) w]
    close $f
    set f [open "|[list [interpreter] pipe]" r+]
    fconfigure $f -blocking off -eofchar {}
    fconfigure $f -blocking off

    puts -nonewline $f $x
    close $f
    set counter 0
    while {([file size $path(output)] < 20480) && ($counter < 1000)} {
	after 20 [list incr [namespace which -variable counter]]
	vwait [namespace which -variable counter]
    }
    if {$counter == 1000} {
        set result probably_broken
	set result probably_broken
    } else {
        set result ok
	set result ok
    }
} ok
test io-28.4 {Tcl_Close} {testchannel} {
test io-28.4 Tcl_Close testchannel {
    file delete $path(test1)
    set l ""
    set l {}
    lappend l [lsort [testchannel open]]
    set f [open $path(test1) w]
    lappend l [lsort [testchannel open]]
    close $f
    lappend l [lsort [testchannel open]]
    set x [list $consoleFileNames \
		[lsort [list {*}$consoleFileNames $f]] \
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
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409

2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423

2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437

2438
2439
2440
2441
2442
2443
2444
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-







-







-
+













-
+













-
+













-
+







    close $f
    set f [open "|[list [interpreter] $path(script)]" r]
    set l [gets $f]
    close $f
    lsort $l
} {file1 file2}


test io-28.6 {
	close channel in write event handler

	Should not produce a segmentation fault in a Tcl built with
	--enable-symbols and -DPURIFY
} -body {
    variable done
    variable res
    # Not a complete / correct channel implementation. Just enough
    # to exercise the crash - closing from a write handler
    after 0 [list coroutine c1 apply [list {} {
	variable done
	set chan [chan create w {apply {{cmd chan args} {
	    switch $cmd {
		blocking - finalize {
		}
		watch {
		    lappend ::timers286 [after 0 chan postevent $chan write]
		}
		initialize {
		    list initialize finalize watch read write configure blocking
		}
		default {
		    error [list {unexpected command} $cmd]
		}
	    }
	}}}]
	chan configure $chan -blocking 0
	while 1 {
	    chan event $chan writable [list [info coroutine]]
	    yield
	    close $chan
	    set done 1
	    return
	}
    } [namespace current]]]
    vwait [namespace current]::done
    return success
} -cleanup {
    foreach timer $::timers286 {after cancel $timer}
} -result success

test io-28.7 {
    close channel in read event handler

	Should not produce a segmentation fault in a Tcl built with
	--enable-symbols and -DPURIFY
} -body  {
    variable done
    variable res
    after 0 [list coroutine c1 apply [list {} {
	variable done
	# Not a complete / correct channel implementation. Just enough
	# to exercise the crash - closing from a read handler
	set chan [chan create r {apply {{cmd chan args} {
	    switch $cmd {
		blocking - finalize {
		}
		watch {
		    lappend ::timers287 [after 0 chan postevent $chan read]
		}
		initialize {
		    list initialize finalize watch read write configure blocking
		}
		default {
		    error [list {unexpected command} $cmd]
		}
	    }
	}}}]
	chan configure $chan -blocking 0
	while 1 {
	    chan event $chan readable [list [info coroutine]]
	    yield
	    close $chan
	    set done 1
	    return
	}
    } [namespace current]]]
    vwait [namespace current]::done
    return success
} -cleanup {
    foreach timer $::timers287 {after cancel $timer}
} -result success

test io-29.1 {Tcl_WriteChars, channel not writable} {
    list [catch {puts stdin hello} msg] $msg
} {1 {channel "stdin" wasn't opened for writing}}
test io-29.2 {Tcl_WriteChars, empty string} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -eofchar {}
    puts -nonewline $f ""
    close $f
    file size $path(test1)
} 0
test io-29.3 {Tcl_WriteChars, nonempty string} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -eofchar {}
    puts -nonewline $f hello
    close $f
    file size $path(test1)
} 5
test io-29.4 {Tcl_WriteChars, buffering in full buffering mode} {testchannel} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf -buffering full -eofchar {}
    fconfigure $f -translation lf -buffering full
    puts $f hello
    set l ""
    lappend l [testchannel outputbuffered $f]
    lappend l [file size $path(test1)]
    flush $f
    lappend l [testchannel outputbuffered $f]
    lappend l [file size $path(test1)]
    close $f
    set l
} {6 0 0 6}
test io-29.5 {Tcl_WriteChars, buffering in line buffering mode} {testchannel} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf -buffering line -eofchar {}
    fconfigure $f -translation lf -buffering line
    puts -nonewline $f hello
    set l ""
    lappend l [testchannel outputbuffered $f]
    lappend l [file size $path(test1)]
    puts $f hello
    lappend l [testchannel outputbuffered $f]
    lappend l [file size $path(test1)]
    close $f
    set l
} {5 0 0 11}
test io-29.6 {Tcl_WriteChars, buffering in no buffering mode} {testchannel} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf -buffering none -eofchar {}
    fconfigure $f -translation lf -buffering none
    puts -nonewline $f hello
    set l ""
    lappend l [testchannel outputbuffered $f]
    lappend l [file size $path(test1)]
    puts $f hello
    lappend l [testchannel outputbuffered $f]
    lappend l [file size $path(test1)]
    close $f
    set l
} {0 5 0 11}
test io-29.7 {Tcl_Flush, full buffering} {testchannel} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf -buffering full -eofchar {}
    fconfigure $f -translation lf -buffering full
    puts -nonewline $f hello
    set l ""
    lappend l [testchannel outputbuffered $f]
    lappend l [file size $path(test1)]
    puts $f hello
    lappend l [testchannel outputbuffered $f]
    lappend l [file size $path(test1)]
2470
2471
2472
2473
2474
2475
2476
2477

2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
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







-
+











-







} {5 0 0 5 0 11 0 11}
test io-29.9 {Tcl_Flush, channel not writable} {
    list [catch {flush stdin} msg] $msg
} {1 {channel "stdin" wasn't opened for writing}}
test io-29.10 {Tcl_WriteChars, looping and buffering} {
    file delete $path(test1)
    set f1 [open $path(test1) w]
    fconfigure $f1 -translation lf -eofchar {}
    fconfigure $f1 -translation lf
    set f2 [open $path(longfile) r]
    for {set x 0} {$x < 10} {incr x} {
	puts $f1 [gets $f2]
    }
    close $f2
    close $f1
    file size $path(test1)
} 387
test io-29.11 {Tcl_WriteChars, no newline, implicit flush} {
    file delete $path(test1)
    set f1 [open $path(test1) w]
    fconfigure $f1 -eofchar {}
    set f2 [open $path(longfile) r]
    for {set x 0} {$x < 10} {incr x} {
	puts -nonewline $f1 [gets $f2]
    }
    close $f1
    close $f2
    file size $path(test1)
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
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







-
+

















-
+







    lappend x [file size $path(test1)]
    close $f1
    set x
} {18 24 30}
test io-29.19 {Explicit and implicit flushes} {
    file delete $path(test1)
    set f1 [open $path(test1) w]
    fconfigure $f1 -translation lf -eofchar {}
    fconfigure $f1 -translation lf
    set x ""
    puts $f1 hello
    puts $f1 hello
    puts $f1 hello
    flush $f1
    lappend x [file size $path(test1)]
    puts $f1 hello
    flush $f1
    lappend x [file size $path(test1)]
    puts $f1 hello
    close $f1
    lappend x [file size $path(test1)]
    set x
} {18 24 30}
test io-29.20 {Implicit flush when buffer is full} {
    file delete $path(test1)
    set f1 [open $path(test1) w]
    fconfigure $f1 -translation lf -eofchar {}
    fconfigure $f1 -translation lf
    set line "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    for {set x 0} {$x < 100} {incr x} {
      puts $f1 $line
    }
    set z ""
    lappend z [file size $path(test1)]
    for {set x 0} {$x < 100} {incr x} {
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
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







-
+









-
+







-
+







    }
    regsub {".*":} $x {"":} x
    string tolower $x
} {1 {error flushing "": broken pipe} {posix epipe {broken pipe}}}
test io-29.28 {Tcl_WriteChars, lf mode} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    puts $f hello\nthere\nand\nhere
    flush $f
    set s [file size $path(test1)]
    close $f
    set s
} 21
test io-29.29 {Tcl_WriteChars, cr mode} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation cr -eofchar {}
    fconfigure $f -translation cr
    puts $f hello\nthere\nand\nhere
    close $f
    file size $path(test1)
} 21
test io-29.30 {Tcl_WriteChars, crlf mode} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation crlf -eofchar {}
    fconfigure $f -translation crlf
    puts $f hello\nthere\nand\nhere
    close $f
    file size $path(test1)
} 25
test io-29.31 {Tcl_WriteChars, background flush} stdio {
    # This test may fail on old Unix systems (seen on IRIX64 6.5) with
    # obsolete gettimeofday() calls.  See Tcl Bugs 3530533, 1942197.
2830
2831
2832
2833
2834
2835
2836
2837

2838
2839
2840
2841
2842
2843
2844
3006
3007
3008
3009
3010
3011
3012

3013
3014
3015
3016
3017
3018
3019
3020







-
+







    # allow a little time for the background process to close.
    # otherwise, the following test fails on the [file delete $path(output)]
    # on Windows because a process still has the file open.
    after 100 set v 1; vwait v
    set result
} ok
test io-29.32 {Tcl_WriteChars, background flush to slow reader} \
	{stdio asyncPipeClose knownMsvcBug} {
	{stdio asyncPipeClose notWinCI} {
    # This test may fail on old Unix systems (seen on IRIX64 6.5) with
    # obsolete gettimeofday() calls.  See Tcl Bugs 3530533, 1942197.
    file delete $path(pipe)
    file delete $path(output)
    set f [open $path(pipe) w]
    puts $f "set f \[[list open $path(output) w]]"
    puts $f {fconfigure $f -translation lf}
2981
2982
2983
2984
2985
2986
2987





























































































2988
2989
2990
2991
2992
2993
2994
3157
3158
3159
3160
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
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    y eval "fileevent $c readable \{readit $c\}"
    y eval [list close $c]
    update
    close $s
    interp delete x
    interp delete y
} ""

test io-29.36.1 {gets on translation auto with "\r" in QA communication mode, possible regression, bug [b3977d199b]} -constraints {
    socket tempNotMac fileevent
} -setup {
    set s [open "|[list [interpreter] << {
    proc accept {so args} {
	fconfigure $so -translation binary
	puts -nonewline $so "who are you?\r"; flush $so
	set a [gets $so]
	puts -nonewline $so "really $a?\r"; flush $so
	set a [gets $so]
	close $so
	set ::done $a
    }
    set s [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
    puts [lindex [fconfigure $s -sockname] 2]
    foreach c {1 2} {
	vwait ::done
	puts $::done
    }
    }]" r]
    set c {}
    set result {}
} -body {
    set port [gets $s]
    foreach t {{cr lf} {auto lf}} {
	set c [socket 127.0.0.1 $port]
	fconfigure $c -buffering line -translation $t
	lappend result $t
	while {1} {
	    set q [gets $c]
	    switch -- $q {
		"who are you?"   {puts $c "client"}
		"really client?" {puts $c "yes"; lappend result $q; break}
		default {puts $c "wrong"; lappend result "unexpected input \"$q\""; break}
	    }
	}
	lappend result [gets $s]
	close $c; set c {}
    }
    set result
} -cleanup {
    close $s
    if {$c ne {}} { close $c }
    unset -nocomplain s c port t q
} -result [list {cr lf} "really client?" yes {auto lf} "really client?" yes]
test io-29.36.2 {gets on translation auto with "\r\n" in different buffers, bug [b3977d199b]} -constraints {
    socket tempNotMac fileevent
} -setup {
    set s [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
    set c {}
} -body {
    set ::cnt 0
    proc accept {so args} {
	fconfigure $so -translation binary
	puts -nonewline $so "1 line\r"
	puts -nonewline $so "\n2 li"
	flush $so
	# now force separate packets
	puts -nonewline $so "ne\r"
	flush $so
	if {$::cnt & 1} {
	    vwait ::cli; # simulate short delay (so client can process events, just wait for it)
	} else {
	    # we don't have a delay, so client would get the lines as single chunk
	}
	# we'll try with "\r" and without "\r" (to cover both branches, where "\r" and "eof" causes exit from [gets] by 3rd line)
	puts -nonewline $so "\n3 line"
	if {!($::cnt % 3)} {
	    puts -nonewline $so "\r"
	}
	flush $so
	close $so
    }
    while {$::cnt < 6} { incr ::cnt
	set c [socket 127.0.0.1 [lindex [fconfigure $s -sockname] 2]]
	fconfigure $c -blocking 0 -buffering line -translation auto
	fileevent $c readable [list apply {c {
	    if {[gets $c line] >= 0} {
		lappend ::cli <$line>
	    } elseif {[eof $c]} {
		set ::done 1
	    }
	}} $c]
	vwait ::done
	close $c; set c {}
    }
    set ::cli
} -cleanup {
    close $s
    if {$c ne {}} { close $c }
    unset -nocomplain ::done ::cli ::cnt s c
} -result [lrepeat 6 {<1 line>} {<2 line>} {<3 line>}]

# Test end of line translations. Procedures tested are Tcl_Write, Tcl_Read.

test io-30.1 {Tcl_Write lf, Tcl_Read lf} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf
3155
3156
3157
3158
3159
3160
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
3199

3200
3201
3202

3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214

3215
3216
3217
3218

3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235

3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255

3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270

3271
3272
3273
3274
3275

3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288

3289
3290
3291
3292

3293
3294
3295
3296
3297

3298
3299
3300

3301
3302
3303
3304
3305
3306
3307
3308
3309
3310

3311
3312
3313
3314
3315

3316
3317
3318

3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333

3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347

3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361

3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375

3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389

3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403

3404
3405
3406
3407
3408
3409
3410
3424
3425
3426
3427
3428
3429
3430

3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446

3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467

3468
3469
3470

3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482

3483
3484
3485
3486

3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503

3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523

3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538

3539
3540
3541
3542
3543

3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556

3557
3558
3559
3560

3561
3562
3563
3564
3565

3566
3567
3568

3569
3570
3571
3572
3573
3574
3575
3576
3577
3578

3579
3580
3581
3582
3583

3584
3585
3586

3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601

3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615

3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629

3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643

3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657

3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671

3672
3673
3674
3675
3676
3677
3678
3679







-
+















-
+




















-
+


-
+











-
+



-
+
















-
+



















-
+














-
+




-
+












-
+



-
+




-
+


-
+









-
+




-
+


-
+














-
+













-
+













-
+













-
+













-
+













-
+







    }
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation auto
    set c [read $f]
    close $f
    string length $c
} [expr 700*15+1]
} [expr {700*15+1}]
test io-30.14 {Tcl_Write crlf on block boundary, Tcl_Read crlf} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation crlf
    set line "123456789ABCDE"	;# 14 char plus crlf
    puts -nonewline $f x	;# shift crlf across block boundary
    for {set i 0} {$i < 700} {incr i} {
	puts $f $line
    }
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation crlf
    set c [read $f]
    close $f
    string length $c
} [expr 700*15+1]
} [expr {700*15+1}]
test io-30.15 {Tcl_Write mixed, Tcl_Read auto} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts $f hello\nthere\nand\rhere
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation auto
    set c [read $f]
    close $f
    set c
} {hello
there
and
here
}
test io-30.16 {Tcl_Write ^Z at end, Tcl_Read auto} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts -nonewline $f hello\nthere\nand\rhere\n\x1a
    puts -nonewline $f hello\nthere\nand\rhere\n\x1A
    close $f
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation auto
    fconfigure $f -translation auto -eofchar \x1A
    set c [read $f]
    close $f
    set c
} {hello
there
and
here
}
test io-30.17 {Tcl_Write, implicit ^Z at end, Tcl_Read auto} {win} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -eofchar \x1a -translation lf
    fconfigure $f -translation lf -eofchar \x1A
    puts $f hello\nthere\nand\rhere
    close $f
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation auto
    fconfigure $f -translation auto -eofchar \x1A
    set c [read $f]
    close $f
    set c
} {hello
there
and
here
}
test io-30.18 {Tcl_Write, ^Z in middle, Tcl_Read auto} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf
    set s [format "abc\ndef\n%cghi\nqrs" 26]
    puts $f $s
    close $f
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation auto
    fconfigure $f -translation auto -eofchar \x1A
    set l ""
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f
    set l
} {abc def 0 {} 1 {} 1}
test io-30.19 {Tcl_Write, ^Z no newline in middle, Tcl_Read auto} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf
    set s [format "abc\ndef\n%cghi\nqrs" 26]
    puts $f $s
    close $f
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation auto
    fconfigure $f -translation auto -eofchar \x1A
    set l ""
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f
    set l
} {abc def 0 {} 1 {} 1}
test io-30.20 {Tcl_Write, ^Z in middle ignored, Tcl_Read lf} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    set s [format "abc\ndef\n%cghi\nqrs" 26]
    puts $f $s
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    set l ""
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f
    set l
} "abc def 0 \x1aghi 0 qrs 0 {} 1"
} "abc def 0 \x1Aghi 0 qrs 0 {} 1"
test io-30.21 {Tcl_Write, ^Z in middle ignored, Tcl_Read cr} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    set s [format "abc\ndef\n%cghi\nqrs" 26]
    puts $f $s
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation cr -eofchar {}
    fconfigure $f -translation cr
    set l ""
    set x [gets $f]
    lappend l [string compare $x "abc\ndef\n\x1aghi\nqrs\n"]
    lappend l [string compare $x "abc\ndef\n\x1Aghi\nqrs\n"]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f
    set l
} {0 1 {} 1}
test io-30.22 {Tcl_Write, ^Z in middle ignored, Tcl_Read crlf} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    set s [format "abc\ndef\n%cghi\nqrs" 26]
    puts $f $s
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation crlf -eofchar {}
    fconfigure $f -translation crlf
    set l ""
    set x [gets $f]
    lappend l [string compare $x "abc\ndef\n\x1aghi\nqrs\n"]
    lappend l [string compare $x "abc\ndef\n\x1Aghi\nqrs\n"]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f
    set l
} {0 1 {} 1}
test io-30.23 {Tcl_Write lf, ^Z in middle, Tcl_Read auto} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf
    set c [format abc\ndef\n%cqrs\ntuv 26]
    puts $f $c
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation auto -eofchar \x1a
    fconfigure $f -translation auto -eofchar \x1A
    set c [string length [read $f]]
    set e [eof $f]
    close $f
    list $c $e
} {8 1}
test io-30.24 {Tcl_Write lf, ^Z in middle, Tcl_Read lf} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf
    set c [format abc\ndef\n%cqrs\ntuv 26]
    puts $f $c
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation lf -eofchar \x1a
    fconfigure $f -translation lf -eofchar \x1A
    set c [string length [read $f]]
    set e [eof $f]
    close $f
    list $c $e
} {8 1}
test io-30.25 {Tcl_Write cr, ^Z in middle, Tcl_Read auto} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation cr
    set c [format abc\ndef\n%cqrs\ntuv 26]
    puts $f $c
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation auto -eofchar \x1a
    fconfigure $f -translation auto -eofchar \x1A
    set c [string length [read $f]]
    set e [eof $f]
    close $f
    list $c $e
} {8 1}
test io-30.26 {Tcl_Write cr, ^Z in middle, Tcl_Read cr} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation cr
    set c [format abc\ndef\n%cqrs\ntuv 26]
    puts $f $c
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation cr -eofchar \x1a
    fconfigure $f -translation cr -eofchar \x1A
    set c [string length [read $f]]
    set e [eof $f]
    close $f
    list $c $e
} {8 1}
test io-30.27 {Tcl_Write crlf, ^Z in middle, Tcl_Read auto} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation crlf
    set c [format abc\ndef\n%cqrs\ntuv 26]
    puts $f $c
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation auto -eofchar \x1a
    fconfigure $f -translation auto -eofchar \x1A
    set c [string length [read $f]]
    set e [eof $f]
    close $f
    list $c $e
} {8 1}
test io-30.28 {Tcl_Write crlf, ^Z in middle, Tcl_Read crlf} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation crlf
    set c [format abc\ndef\n%cqrs\ntuv 26]
    puts $f $c
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation crlf -eofchar \x1a
    fconfigure $f -translation crlf -eofchar \x1A
    set c [string length [read $f]]
    set e [eof $f]
    close $f
    list $c $e
} {8 1}

# Test end of line translations. Functions tested are Tcl_Write and Tcl_Gets.
3644
3645
3646
3647
3648
3649
3650
3651

3652
3653
3654
3655
3656
3657
3658
3913
3914
3915
3916
3917
3918
3919

3920
3921
3922
3923
3924
3925
3926
3927







-
+







    fconfigure $f -translation binary
    set x [fconfigure $f -translation]
    close $f
    set x
} lf
#
# Test io-9.14 has been removed because "auto" output translation mode is
# not supoprted.
# not supported.
#
test io-31.14 {Tcl_Write mixed, Tcl_Gets auto} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf
    puts $f hello\nthere\rand\r\nhere
    close $f
3729
3730
3731
3732
3733
3734
3735
3736

3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751

3752
3753
3754
3755

3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776

3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794

3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807

3808
3809
3810
3811
3812

3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825

3826
3827
3828
3829

3830
3831
3832
3833
3834

3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847

3848
3849
3850
3851

3852
3853
3854
3855
3856

3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869

3870
3871
3872
3873
3874
3875
3876
3877
3878

3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896

3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909

3910
3911
3912
3913
3914

3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927

3928
3929
3930
3931
3932

3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945

3946
3947
3948
3949
3950

3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963

3964
3965
3966
3967
3968

3969
3970
3971
3972
3973
3974
3975
3998
3999
4000
4001
4002
4003
4004

4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019

4020
4021
4022
4023

4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043


4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061

4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074

4075
4076
4077
4078
4079

4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092

4093
4094
4095
4096

4097
4098
4099
4100
4101

4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114

4115
4116
4117
4118

4119
4120
4121
4122
4123

4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136

4137
4138
4139
4140
4141
4142
4143
4144
4145

4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163

4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176

4177
4178
4179
4180
4181

4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194

4195
4196
4197
4198
4199

4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212

4213
4214
4215
4216
4217

4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230

4231
4232
4233
4234
4235

4236
4237
4238
4239
4240
4241
4242
4243







-
+














-
+



-
+



















-
-
+

















-
+












-
+




-
+












-
+



-
+




-
+












-
+



-
+




-
+












-
+








-
+

















-
+












-
+




-
+












-
+




-
+












-
+




-
+












-
+




-
+







    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf
    set s [format "hello\nthere\nand\rhere\n\%c" 26]
    puts $f $s
    close $f
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation auto
    fconfigure $f -translation auto -eofchar \x1A
    set l ""
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f
    set l
} {hello there and here 0 {} 1}
test io-31.19 {Tcl_Write, implicit ^Z at end, Tcl_Gets auto} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -eofchar \x1a -translation lf
    fconfigure $f -translation lf -eofchar \x1A
    puts $f hello\nthere\nand\rhere
    close $f
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation auto
    fconfigure $f -translation auto -eofchar \x1A
    set l ""
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f
    set l
} {hello there and here 0 {} 1}
test io-31.20 {Tcl_Write, ^Z in middle, Tcl_Gets auto, eofChar} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf
    set s [format "abc\ndef\n%cqrs\ntuv" 26]
    puts $f $s
    close $f
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a
    fconfigure $f -translation auto
    fconfigure $f -translation auto -eofchar \x1A
    set l ""
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f
    set l
} {abc def 0 {} 1}
test io-31.21 {Tcl_Write, no newline ^Z in middle, Tcl_Gets auto, eofChar} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf
    set s [format "abc\ndef\n%cqrs\ntuv" 26]
    puts $f $s
    close $f
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation auto
    fconfigure $f -translation auto -eofchar \x1A
    set l ""
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f
    set l
} {abc def 0 {} 1}
test io-31.22 {Tcl_Write, ^Z in middle ignored, Tcl_Gets lf} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    set s [format "abc\ndef\n%cqrs\ntuv" 26]
    puts $f $s
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    set l ""
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f
    set l
} "abc def 0 \x1aqrs 0 tuv 0 {} 1"
} "abc def 0 \x1Aqrs 0 tuv 0 {} 1"
test io-31.23 {Tcl_Write, ^Z in middle ignored, Tcl_Gets cr} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation cr -eofchar {}
    fconfigure $f -translation cr
    set s [format "abc\ndef\n%cqrs\ntuv" 26]
    puts $f $s
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation cr -eofchar {}
    fconfigure $f -translation cr
    set l ""
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f
    set l
} "abc def 0 \x1aqrs 0 tuv 0 {} 1"
} "abc def 0 \x1Aqrs 0 tuv 0 {} 1"
test io-31.24 {Tcl_Write, ^Z in middle ignored, Tcl_Gets crlf} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation crlf -eofchar {}
    fconfigure $f -translation crlf
    set s [format "abc\ndef\n%cqrs\ntuv" 26]
    puts $f $s
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation crlf -eofchar {}
    fconfigure $f -translation crlf
    set l ""
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f
    set l
} "abc def 0 \x1aqrs 0 tuv 0 {} 1"
} "abc def 0 \x1Aqrs 0 tuv 0 {} 1"
test io-31.25 {Tcl_Write lf, ^Z in middle, Tcl_Gets auto} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf
    set s [format "abc\ndef\n%cqrs\ntuv" 26]
    puts $f $s
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation auto -eofchar \x1a
    fconfigure $f -translation auto -eofchar \x1A
    set l ""
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f
    set l
} {abc def 0 {} 1}
test io-31.26 {Tcl_Write lf, ^Z in middle, Tcl_Gets lf} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf
    set s [format "abc\ndef\n%cqrs\ntuv" 26]
    puts $f $s
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation lf -eofchar \x1a
    fconfigure $f -translation lf -eofchar \x1A
    set l ""
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f
    set l
} {abc def 0 {} 1}
test io-31.27 {Tcl_Write cr, ^Z in middle, Tcl_Gets auto} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation cr -eofchar {}
    fconfigure $f -translation cr
    set s [format "abc\ndef\n%cqrs\ntuv" 26]
    puts $f $s
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation auto -eofchar \x1a
    fconfigure $f -translation auto -eofchar \x1A
    set l ""
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f
    set l
} {abc def 0 {} 1}
test io-31.28 {Tcl_Write cr, ^Z in middle, Tcl_Gets cr} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation cr -eofchar {}
    fconfigure $f -translation cr
    set s [format "abc\ndef\n%cqrs\ntuv" 26]
    puts $f $s
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation cr -eofchar \x1a
    fconfigure $f -translation cr -eofchar \x1A
    set l ""
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f
    set l
} {abc def 0 {} 1}
test io-31.29 {Tcl_Write crlf, ^Z in middle, Tcl_Gets auto} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation crlf -eofchar {}
    fconfigure $f -translation crlf
    set s [format "abc\ndef\n%cqrs\ntuv" 26]
    puts $f $s
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation auto -eofchar \x1a
    fconfigure $f -translation auto -eofchar \x1A
    set l ""
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f
    set l
} {abc def 0 {} 1}
test io-31.30 {Tcl_Write crlf, ^Z in middle, Tcl_Gets crlf} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation crlf -eofchar {}
    fconfigure $f -translation crlf
    set s [format "abc\ndef\n%cqrs\ntuv" 26]
    puts $f $s
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation crlf -eofchar \x1a
    fconfigure $f -translation crlf -eofchar \x1A
    set l ""
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f
3989
3990
3991
3992
3993
3994
3995
3996

3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015

4016
4017
4018
4019
4020
4021
4022
4257
4258
4259
4260
4261
4262
4263

4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282

4283
4284
4285
4286
4287
4288
4289
4290







-
+


















-
+







    fconfigure $f -translation crlf
    set c ""
    while {[gets $f line] >= 0} {
	append c $line\n
    }
    close $f
    string length $c
} [expr 700*15+1]
} [expr {700*15+1}]
test io-31.32 {Tcl_Write crlf on block boundary, Tcl_Gets auto} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation crlf
    set line "123456789ABCDE"	;# 14 char plus crlf
    puts -nonewline $f x	;# shift crlf across block boundary
    for {set i 0} {$i < 700} {incr i} {
	puts $f $line
    }
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation auto
    set c ""
    while {[gets $f line] >= 0} {
	append c $line\n
    }
    close $f
    string length $c
} [expr 700*15+1]
} [expr {700*15+1}]

# Test Tcl_Read and buffering.

test io-32.1 {Tcl_Read, channel not readable} {
    list [catch {read stdout} msg] $msg
} {1 {channel "stdout" wasn't opened for reading}}
test io-32.2 {Tcl_Read, zero byte count} {
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
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
























4463
4464
4465
4466
4467
4468
4469
4593
4594
4595
4596
4597
4598
4599

4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612

4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625

4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
















4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655






4656
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
4688
4689






4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
























4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737







-
+












-
+












-
+












-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+











-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+











-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    set f [open $path(test3) r]
    set result [list [catch {gets $f x(0)} msg] $msg]
    close $f
    set result
} {1 {can't set "x(0)": variable isn't array}}
test io-33.8 {Tcl_Gets, exercising double buffering} {
    set f [open $path(test3) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    set x ""
    for {set y 0} {$y < 99} {incr y} {set x "a$x"}
    for {set y 0} {$y < 100} {incr y} {puts $f $x}
    close $f
    set f [open $path(test3) r]
    fconfigure $f -translation lf
    for {set y 0} {$y < 100} {incr y} {gets $f}
    close $f
    set y
} 100
test io-33.9 {Tcl_Gets, exercising double buffering} {
    set f [open $path(test3) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    set x ""
    for {set y 0} {$y < 99} {incr y} {set x "a$x"}
    for {set y 0} {$y < 200} {incr y} {puts $f $x}
    close $f
    set f [open $path(test3) r]
    fconfigure $f -translation lf
    for {set y 0} {$y < 200} {incr y} {gets $f}
    close $f
    set y
} 200
test io-33.10 {Tcl_Gets, exercising double buffering} {
    set f [open $path(test3) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    set x ""
    for {set y 0} {$y < 99} {incr y} {set x "a$x"}
    for {set y 0} {$y < 300} {incr y} {puts $f $x}
    close $f
    set f [open $path(test3) r]
    fconfigure $f -translation lf
    for {set y 0} {$y < 300} {incr y} {gets $f}
    close $f
    set y
} 300
test io-33.11 {TclGetsObjBinary, [10dc6daa37]} -setup {
    proc driver {cmd args} {
        variable buffer
        variable index
        set chan [lindex $args 0]
        switch -- $cmd {
            initialize {
                set index($chan) 0
                set buffer($chan) .......
                return {initialize finalize watch read}
            }
            finalize {
                unset index($chan) buffer($chan)
                return
            }
            watch {}
            read {
                set n [lindex $args 1]
	variable buffer
	variable index
	set chan [lindex $args 0]
	switch -- $cmd {
	    initialize {
		set index($chan) 0
		set buffer($chan) .......
		return {initialize finalize watch read}
	    }
	    finalize {
		unset index($chan) buffer($chan)
		return
	    }
	    watch {}
	    read {
		set n [lindex $args 1]
		if {$n > 3} {set n 3}
                set new [expr {$index($chan) + $n}]
                set result [string range $buffer($chan) $index($chan) $new-1]
                set index($chan) $new
                return $result
            }
        }
		set new [expr {$index($chan) + $n}]
		set result [string range $buffer($chan) $index($chan) $new-1]
		set index($chan) $new
		return $result
	    }
	}
    }
} -body {
    set c [chan create read [namespace which driver]]
    chan configure $c -translation binary -blocking 0
    list [gets $c] [gets $c] [gets $c] [gets $c]
} -cleanup {
    close $c
    rename driver {}
} -result {{} {} {} .......}
test io-33.12 {Tcl_GetsObj, [10dc6daa37]} -setup {
    proc driver {cmd args} {
        variable buffer
        variable index
        set chan [lindex $args 0]
        switch -- $cmd {
            initialize {
                set index($chan) 0
                set buffer($chan) .......
                return {initialize finalize watch read}
            }
            finalize {
                unset index($chan) buffer($chan)
                return
            }
            watch {}
            read {
                set n [lindex $args 1]
	variable buffer
	variable index
	set chan [lindex $args 0]
	switch -- $cmd {
	    initialize {
		set index($chan) 0
		set buffer($chan) .......
		return {initialize finalize watch read}
	    }
	    finalize {
		unset index($chan) buffer($chan)
		return
	    }
	    watch {}
	    read {
		set n [lindex $args 1]
		if {$n > 3} {set n 3}
                set new [expr {$index($chan) + $n}]
                set result [string range $buffer($chan) $index($chan) $new-1]
                set index($chan) $new
                return $result
            }
        }
		set new [expr {$index($chan) + $n}]
		set result [string range $buffer($chan) $index($chan) $new-1]
		set index($chan) $new
		return $result
	    }
	}
    }
} -body {
    set c [chan create read [namespace which driver]]
    chan configure $c -blocking 0
    list [gets $c] [gets $c] [gets $c] [gets $c]
} -cleanup {
    close $c
    rename driver {}
} -result {{} {} {} .......}
test io-33.13 {Tcl_GetsObj, [10dc6daa37]} -setup {
    proc driver {cmd args} {
        variable buffer
        variable index
        set chan [lindex $args 0]
        switch -- $cmd {
            initialize {
                set index($chan) 0
                set buffer($chan) [string repeat \
                        [string repeat . 64]\n[string repeat . 25] 2]
                return {initialize finalize watch read}
            }
            finalize {
                unset index($chan) buffer($chan)
                return
            }
            watch {}
            read {
                set n [lindex $args 1]
                if {$n > 65} {set n 65}
                set new [expr {$index($chan) + $n}]
                set result [string range $buffer($chan) $index($chan) $new-1]
                set index($chan) $new
                return $result
            }
        }
	variable buffer
	variable index
	set chan [lindex $args 0]
	switch -- $cmd {
	    initialize {
		set index($chan) 0
		set buffer($chan) [string repeat \
			[string repeat . 64]\n[string repeat . 25] 2]
		return {initialize finalize watch read}
	    }
	    finalize {
		unset index($chan) buffer($chan)
		return
	    }
	    watch {}
	    read {
		set n [lindex $args 1]
		if {$n > 65} {set n 65}
		set new [expr {$index($chan) + $n}]
		set result [string range $buffer($chan) $index($chan) $new-1]
		set index($chan) $new
		return $result
	    }
	}
    }
} -body {
    set c [chan create read [namespace which driver]]
    chan configure $c -blocking 0
    list [gets $c] [gets $c] [gets $c] [gets $c] [gets $c]
} -cleanup {
    close $c
4479
4480
4481
4482
4483
4484
4485
4486

4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499

4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512

4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525

4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539

4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554

4555
4556
4557
4558
4559
4560
4561
4747
4748
4749
4750
4751
4752
4753

4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766

4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779

4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792

4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806

4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821

4822
4823
4824
4825
4826
4827
4828
4829







-
+












-
+












-
+












-
+













-
+














-
+







    set c [tell $f1]
    close $f1
    set c
} 0
test io-34.2 {Tcl_Seek to offset from start} {
    file delete $path(test1)
    set f1 [open $path(test1) w]
    fconfigure $f1 -translation lf -eofchar {}
    fconfigure $f1 -translation lf
    puts $f1 "abcdefghijklmnopqrstuvwxyz"
    puts $f1 "abcdefghijklmnopqrstuvwxyz"
    close $f1
    set f1 [open $path(test1) r]
    seek $f1 10 start
    set c [tell $f1]
    close $f1
    set c
} 10
test io-34.3 {Tcl_Seek to end of file} {
    file delete $path(test1)
    set f1 [open $path(test1) w]
    fconfigure $f1 -translation lf -eofchar {}
    fconfigure $f1 -translation lf
    puts $f1 "abcdefghijklmnopqrstuvwxyz"
    puts $f1 "abcdefghijklmnopqrstuvwxyz"
    close $f1
    set f1 [open $path(test1) r]
    seek $f1 0 end
    set c [tell $f1]
    close $f1
    set c
} 54
test io-34.4 {Tcl_Seek to offset from end of file} {
    file delete $path(test1)
    set f1 [open $path(test1) w]
    fconfigure $f1 -translation lf -eofchar {}
    fconfigure $f1 -translation lf
    puts $f1 "abcdefghijklmnopqrstuvwxyz"
    puts $f1 "abcdefghijklmnopqrstuvwxyz"
    close $f1
    set f1 [open $path(test1) r]
    seek $f1 -10 end
    set c [tell $f1]
    close $f1
    set c
} 44
test io-34.5 {Tcl_Seek to offset from current position} {
    file delete $path(test1)
    set f1 [open $path(test1) w]
    fconfigure $f1 -translation lf -eofchar {}
    fconfigure $f1 -translation lf
    puts $f1 "abcdefghijklmnopqrstuvwxyz"
    puts $f1 "abcdefghijklmnopqrstuvwxyz"
    close $f1
    set f1 [open $path(test1) r]
    seek $f1 10 current
    seek $f1 10 current
    set c [tell $f1]
    close $f1
    set c
} 20
test io-34.6 {Tcl_Seek to offset from end of file} {
    file delete $path(test1)
    set f1 [open $path(test1) w]
    fconfigure $f1 -translation lf -eofchar {}
    fconfigure $f1 -translation lf
    puts $f1 "abcdefghijklmnopqrstuvwxyz"
    puts $f1 "abcdefghijklmnopqrstuvwxyz"
    close $f1
    set f1 [open $path(test1) r]
    seek $f1 -10 end
    set c [tell $f1]
    set r [read $f1]
    close $f1
    list $c $r
} {44 {rstuvwxyz
}}
test io-34.7 {Tcl_Seek to offset from end of file, then to current position} {
    file delete $path(test1)
    set f1 [open $path(test1) w]
    fconfigure $f1 -translation lf -eofchar {}
    fconfigure $f1 -translation lf
    puts $f1 "abcdefghijklmnopqrstuvwxyz"
    puts $f1 "abcdefghijklmnopqrstuvwxyz"
    close $f1
    set f1 [open $path(test1) r]
    seek $f1 -10 end
    set c1 [tell $f1]
    set r1 [read $f1 5]
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4838
4839
4840
4841
4842
4843
4844

4845
4846
4847
4848
4849
4850
4851







-







    close $f1
    regsub {".*":} $x {"":} x
    string tolower $x
} {1 {error during seek on "": invalid argument}}
test io-34.9 {Tcl_Seek, testing buffered input flushing} {
    file delete $path(test3)
    set f [open $path(test3) w]
    fconfigure $f -eofchar {}
    puts -nonewline $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    close $f
    set f [open $path(test3) RDWR]
    set x [read $f 1]
    seek $f 3
    lappend x [read $f 1]
    seek $f 0 start
4618
4619
4620
4621
4622
4623
4624
4625

4626
4627
4628
4629

4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650

4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663

4664
4665
4666
4667
4668
4669
4670
4885
4886
4887
4888
4889
4890
4891

4892
4893
4894
4895

4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916

4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929

4930
4931
4932
4933
4934
4935
4936
4937







-
+



-
+




















-
+












-
+







    seek $f 2
    set x [gets $f]
    close $f
    list $x [viewFile test3]
} "zzy xyzzy"
test io-34.12 {Tcl_Seek testing combination of write, seek back and read} {
    set f [open $path(test3) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    puts $f xyz\n123
    close $f
    set f [open $path(test3) a+]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    puts $f xyzzy
    flush $f
    set x [tell $f]
    seek $f -4 cur
    set y [gets $f]
    close $f
    list $x [viewFile test3] $y
} {14 {xyz
123
xyzzy} zzy}
test io-34.13 {Tcl_Tell at start of file} {
    file delete $path(test1)
    set f1 [open $path(test1) w]
    set p [tell $f1]
    close $f1
    set p
} 0
test io-34.14 {Tcl_Tell after seek to end of file} {
    file delete $path(test1)
    set f1 [open $path(test1) w]
    fconfigure $f1 -translation lf -eofchar {}
    fconfigure $f1 -translation lf
    puts $f1 "abcdefghijklmnopqrstuvwxyz"
    puts $f1 "abcdefghijklmnopqrstuvwxyz"
    close $f1
    set f1 [open $path(test1) r]
    seek $f1 0 end
    set c1 [tell $f1]
    close $f1
    set c1
} 54
test io-34.15 {Tcl_Tell combined with seeking} {
    file delete $path(test1)
    set f1 [open $path(test1) w]
    fconfigure $f1 -translation lf -eofchar {}
    fconfigure $f1 -translation lf
    puts $f1 "abcdefghijklmnopqrstuvwxyz"
    puts $f1 "abcdefghijklmnopqrstuvwxyz"
    close $f1
    set f1 [open $path(test1) r]
    seek $f1 10 start
    set c1 [tell $f1]
    seek $f1 10 current
4686
4687
4688
4689
4690
4691
4692
4693

4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712

4713
4714
4715
4716
4717
4718
4719
4953
4954
4955
4956
4957
4958
4959

4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978

4979
4980
4981
4982
4983
4984
4985
4986







-
+


















-
+







    gets $f1
    close $f1
    set c
} -1
test io-34.18 {Tcl_Tell combined with seeking and reading} {
    file delete $path(test2)
    set f [open $path(test2) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    puts -nonewline $f "line1\nline2\nline3\nline4\nline5\n"
    close $f
    set f [open $path(test2)]
    fconfigure $f -translation lf
    set x [tell $f]
    read $f 3
    lappend x [tell $f]
    seek $f 2
    lappend x [tell $f]
    seek $f 10 current
    lappend x [tell $f]
    seek $f 0 end
    lappend x [tell $f]
    close $f
    set x
} {0 3 2 12 30}
test io-34.19 {Tcl_Tell combined with opening in append mode} {
    set f [open $path(test3) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    puts $f "abcdefghijklmnopqrstuvwxyz"
    puts $f "abcdefghijklmnopqrstuvwxyz"
    close $f
    set f [open $path(test3) a]
    set c [tell $f]
    close $f
    set c
4729
4730
4731
4732
4733
4734
4735
4736

4737
4738
4739

4740
4741
4742
4743
4744
4745
4746
4996
4997
4998
4999
5000
5001
5002

5003
5004
5005

5006
5007
5008
5009
5010
5011
5012
5013







-
+


-
+







    puts -nonewline $f a
    lappend l [tell $f]
    seek $f 407 end
    lappend l [tell $f]
    close $f
    set l
} {29 39 40 447}
test io-34.21 {Tcl_Seek and Tcl_Tell on large files} {largefileSupport} {
test io-34.21 {Tcl_Seek and Tcl_Tell on large files} {largefileSupport extensive} {
    file delete $path(test3)
    set f [open $path(test3) w]
    fconfigure $f -encoding binary
    fconfigure $f -translation binary
    set l ""
    lappend l [tell $f]
    puts -nonewline $f abcdef
    lappend l [tell $f]
    flush $f
    lappend l [tell $f]
    # 4GB offset!
4842
4843
4844
4845
4846
4847
4848
4849

4850
4851
4852
4853
4854

4855
4856
4857
4858
4859

4860
4861
4862
4863

4864
4865
4866
4867
4868

4869
4870
4871
4872
4873

4874
4875
4876
4877

4878
4879
4880
4881
4882

4883
4884
4885
4886
4887

4888
4889
4890
4891

4892
4893
4894
4895
4896

4897
4898
4899
4900
4901

4902
4903
4904
4905

4906
4907
4908
4909
4910

4911
4912
4913
4914
4915

4916
4917
4918
4919

4920
4921
4922
4923
4924

4925
4926
4927
4928
4929

4930
4931
4932
4933

4934
4935
4936
4937
4938
4939

4940
4941
4942
4943
4944
4945
4946
4947
4948

4949
4950
4951
4952
4953
4954

4955
4956
4957
4958
4959
4960
4961
4962
4963

4964
4965
4966
4967
4968
4969

4970
4971
4972
4973
4974
4975
4976
4977
4978

4979
4980
4981
4982
4983
4984

4985
4986
4987
4988
4989
4990
4991
4992
4993

4994
4995
4996
4997
4998
4999

5000
5001
5002
5003
5004
5005
5006
5007
5008

5009
5010
5011
5012
5013
5014

5015
5016
5017
5018
5019
5020
5021
5109
5110
5111
5112
5113
5114
5115

5116
5117
5118
5119
5120

5121
5122
5123
5124
5125

5126
5127
5128
5129

5130
5131
5132
5133
5134

5135
5136
5137
5138
5139

5140
5141
5142
5143

5144
5145
5146
5147
5148

5149
5150
5151
5152
5153

5154
5155
5156
5157

5158
5159
5160
5161
5162

5163
5164
5165
5166
5167

5168
5169
5170
5171

5172
5173
5174
5175
5176

5177
5178
5179
5180
5181

5182
5183
5184
5185

5186
5187
5188
5189
5190

5191
5192
5193
5194
5195

5196
5197
5198
5199

5200
5201
5202
5203
5204
5205

5206
5207
5208
5209
5210
5211
5212
5213
5214

5215
5216
5217
5218
5219
5220

5221
5222
5223
5224
5225
5226
5227
5228
5229

5230
5231
5232
5233
5234
5235

5236
5237
5238
5239
5240
5241
5242
5243
5244

5245
5246
5247
5248
5249
5250

5251
5252
5253
5254
5255
5256
5257
5258
5259

5260
5261
5262
5263
5264
5265

5266
5267
5268
5269
5270
5271
5272
5273
5274

5275
5276
5277
5278
5279
5280

5281
5282
5283
5284
5285
5286
5287
5288







-
+




-
+




-
+



-
+




-
+




-
+



-
+




-
+




-
+



-
+




-
+




-
+



-
+




-
+




-
+



-
+




-
+




-
+



-
+





-
+








-
+





-
+








-
+





-
+








-
+





-
+








-
+





-
+








-
+





-
+







    lappend l [eof $f]
    close $f
    set l
} {{} 1}
test io-35.6 {Tcl_Eof, eof char, lf write, auto read} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf -eofchar \x1a
    fconfigure $f -translation lf -eofchar \x1A
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation auto -eofchar \x1a
    fconfigure $f -translation auto -eofchar \x1A
    set l [string length [read $f]]
    set e [eof $f]
    close $f
    list $s $l $e
} {9 8 1}
} {8 8 1}
test io-35.7 {Tcl_Eof, eof char, lf write, lf read} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf -eofchar \x1a
    fconfigure $f -translation lf -eofchar \x1A
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation lf -eofchar \x1a
    fconfigure $f -translation lf -eofchar \x1A
    set l [string length [read $f]]
    set e [eof $f]
    close $f
    list $s $l $e
} {9 8 1}
} {8 8 1}
test io-35.8 {Tcl_Eof, eof char, cr write, auto read} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation cr -eofchar \x1a
    fconfigure $f -translation cr -eofchar \x1A
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation auto -eofchar \x1a
    fconfigure $f -translation auto -eofchar \x1A
    set l [string length [read $f]]
    set e [eof $f]
    close $f
    list $s $l $e
} {9 8 1}
} {8 8 1}
test io-35.9 {Tcl_Eof, eof char, cr write, cr read} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation cr -eofchar \x1a
    fconfigure $f -translation cr -eofchar \x1A
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation cr -eofchar \x1a
    fconfigure $f -translation cr -eofchar \x1A
    set l [string length [read $f]]
    set e [eof $f]
    close $f
    list $s $l $e
} {9 8 1}
} {8 8 1}
test io-35.10 {Tcl_Eof, eof char, crlf write, auto read} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation crlf -eofchar \x1a
    fconfigure $f -translation crlf -eofchar \x1A
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation auto -eofchar \x1a
    fconfigure $f -translation auto -eofchar \x1A
    set l [string length [read $f]]
    set e [eof $f]
    close $f
    list $s $l $e
} {11 8 1}
} {10 8 1}
test io-35.11 {Tcl_Eof, eof char, crlf write, crlf read} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation crlf -eofchar \x1a
    fconfigure $f -translation crlf -eofchar \x1A
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation crlf -eofchar \x1a
    fconfigure $f -translation crlf -eofchar \x1A
    set l [string length [read $f]]
    set e [eof $f]
    close $f
    list $s $l $e
} {11 8 1}
} {10 8 1}
test io-35.12 {Tcl_Eof, eof char in middle, lf write, auto read} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    set i [format abc\ndef\n%cqrs\nuvw 26]
    puts $f $i
    close $f
    set c [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation auto -eofchar \x1a
    fconfigure $f -translation auto -eofchar \x1A
    set l [string length [read $f]]
    set e [eof $f]
    close $f
    list $c $l $e
} {17 8 1}
test io-35.13 {Tcl_Eof, eof char in middle, lf write, lf read} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    set i [format abc\ndef\n%cqrs\nuvw 26]
    puts $f $i
    close $f
    set c [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation lf -eofchar \x1a
    fconfigure $f -translation lf -eofchar \x1A
    set l [string length [read $f]]
    set e [eof $f]
    close $f
    list $c $l $e
} {17 8 1}
test io-35.14 {Tcl_Eof, eof char in middle, cr write, auto read} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation cr -eofchar {}
    fconfigure $f -translation cr
    set i [format abc\ndef\n%cqrs\nuvw 26]
    puts $f $i
    close $f
    set c [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation auto -eofchar \x1a
    fconfigure $f -translation auto -eofchar \x1A
    set l [string length [read $f]]
    set e [eof $f]
    close $f
    list $c $l $e
} {17 8 1}
test io-35.15 {Tcl_Eof, eof char in middle, cr write, cr read} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation cr -eofchar {}
    fconfigure $f -translation cr
    set i [format abc\ndef\n%cqrs\nuvw 26]
    puts $f $i
    close $f
    set c [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation cr -eofchar \x1a
    fconfigure $f -translation cr -eofchar \x1A
    set l [string length [read $f]]
    set e [eof $f]
    close $f
    list $c $l $e
} {17 8 1}
test io-35.16 {Tcl_Eof, eof char in middle, crlf write, auto read} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation crlf -eofchar {}
    fconfigure $f -translation crlf
    set i [format abc\ndef\n%cqrs\nuvw 26]
    puts $f $i
    close $f
    set c [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation auto -eofchar \x1a
    fconfigure $f -translation auto -eofchar \x1A
    set l [string length [read $f]]
    set e [eof $f]
    close $f
    list $c $l $e
} {21 8 1}
test io-35.17 {Tcl_Eof, eof char in middle, crlf write, crlf read} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation crlf -eofchar {}
    fconfigure $f -translation crlf
    set i [format abc\ndef\n%cqrs\nuvw 26]
    puts $f $i
    close $f
    set c [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation crlf -eofchar \x1a
    fconfigure $f -translation crlf -eofchar \x1A
    set l [string length [read $f]]
    set e [eof $f]
    close $f
    list $c $l $e
} {21 8 1}
test io-35.18 {Tcl_Eof, eof char, cr write, crlf read} -body {
    file delete $path(test1)
5030
5031
5032
5033
5034
5035
5036
5037

5038
5039
5040
5041
5042

5043
5044
5045
5046
5047

5048
5049
5050
5051

5052
5053
5054
5055
5056

5057
5058
5059
5060
5061

5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079

5080
5081
5082
5083
5084
5085

5086
5087
5088
5089
5090
5091
5092
5093
5094

5095
5096
5097
5098
5099
5100

5101
5102
5103
5104
5105
5106
5107
5297
5298
5299
5300
5301
5302
5303

5304
5305
5306
5307
5308

5309
5310
5311
5312
5313

5314
5315
5316
5317

5318
5319
5320
5321
5322

5323
5324
5325
5326
5327

5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345

5346
5347
5348
5349
5350
5351

5352
5353
5354
5355
5356
5357
5358
5359
5360

5361
5362
5363
5364
5365
5366

5367
5368
5369
5370
5371
5372
5373
5374







-
+




-
+




-
+



-
+




-
+




-
+

















-
+





-
+








-
+





-
+







    set e [eof $f]
    close $f
    list $s $l $e [scan [string index $in end] %c]
} -result {8 8 1 13}
test io-35.18a {Tcl_Eof, eof char, cr write, crlf read} -body {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation cr -eofchar \x1a
    fconfigure $f -translation cr -eofchar \x1A
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation crlf -eofchar \x1a
    fconfigure $f -translation crlf -eofchar \x1A
    set l [string length [set in [read $f]]]
    set e [eof $f]
    close $f
    list $s $l $e [scan [string index $in end] %c]
} -result {9 8 1 13}
} -result {8 8 1 13}
test io-35.18b {Tcl_Eof, eof char, cr write, crlf read} -body {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation cr -eofchar \x1a
    fconfigure $f -translation cr -eofchar \x1A
    puts $f {}
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation crlf -eofchar \x1a
    fconfigure $f -translation crlf -eofchar \x1A
    set l [string length [set in [read $f]]]
    set e [eof $f]
    close $f
    list $s $l $e [scan [string index $in end] %c]
} -result {2 1 1 13}
} -result {1 1 1 13}
test io-35.18c {Tcl_Eof, eof char, cr write, crlf read} -body {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation cr
    puts $f {}
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation crlf
    set l [string length [set in [read $f]]]
    set e [eof $f]
    close $f
    list $s $l $e [scan [string index $in end] %c]
} -result {1 1 1 13}
test io-35.19 {Tcl_Eof, eof char in middle, cr write, crlf read} -body {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation cr -eofchar {}
    fconfigure $f -translation cr
    set i [format abc\ndef\n%cqrs\nuvw 26]
    puts $f $i
    close $f
    set c [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation crlf -eofchar \x1a
    fconfigure $f -translation crlf -eofchar \x1A
    set l [string length [set in [read $f]]]
    set e [eof $f]
    close $f
    list $c $l $e [scan [string index $in end] %c]
} -result {17 8 1 13}
test io-35.20 {Tcl_Eof, eof char in middle, cr write, crlf read} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -translation cr -eofchar {}
    fconfigure $f -translation cr
    set i [format \n%cqrsuvw 26]
    puts $f $i
    close $f
    set c [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation crlf -eofchar \x1a
    fconfigure $f -translation crlf -eofchar \x1A
    set l [string length [set in [read $f]]]
    set e [eof $f]
    close $f
    list $c $l $e [scan [string index $in end] %c]
} {9 1 1 13}

# Test Tcl_InputBlocked
5123
5124
5125
5126
5127
5128
5129
5130

5131
5132

5133
5134
5135
5136
5137
5138
5139
5390
5391
5392
5393
5394
5395
5396

5397
5398

5399
5400
5401
5402
5403
5404
5405
5406







-
+

-
+







    lappend x [gets $f1]
    lappend x [fblocked $f1]
    close $f1
    set x
} {{} 1 hello 0 {} 1}
test io-36.1.1 {Tcl_InputBlocked on nonblocking binary pipe} stdio {
    set f1 [open "|[list [interpreter]]" r+]
    chan configure $f1 -encoding binary -translation lf -eofchar {}
    chan configure $f1 -translation binary
    puts $f1 {
	chan configure stdout -encoding binary -translation lf -eofchar {}
	chan configure stdout -translation binary
	puts hello_from_pipe
    }
    flush $f1
    gets $f1
    fconfigure $f1 -blocking off -buffering full
    puts $f1 {puts hello}
    set x ""
5176
5177
5178
5179
5180
5181
5182
5183
5184


5185
5186
5187
5188
5189
5190
5191
5443
5444
5445
5446
5447
5448
5449


5450
5451
5452
5453
5454
5455
5456
5457
5458







-
-
+
+







    lappend l [fblocked $f]
    lappend l [eof $f]
    close $f
    set l
} {0 abc 0 defghijklmnop 0 1}
test io-36.4 {Tcl_InputBlocked vs files, event driven read} {fileevent} {
    proc in {f} {
        variable l
        variable x
	variable l
	variable x
	lappend l [read $f 3]
	if {[eof $f]} {lappend l eof; close $f; set x done}
    }
    file delete $path(test1)
    set f [open $path(test1) w]
    puts $f abcdefghijklmnop
    close $f
5212
5213
5214
5215
5216
5217
5218
5219
5220


5221
5222
5223
5224
5225
5226
5227
5479
5480
5481
5482
5483
5484
5485


5486
5487
5488
5489
5490
5491
5492
5493
5494







-
-
+
+







    lappend l [fblocked $f]
    lappend l [eof $f]
    close $f
    set l
} {0 abc 0 defghijklmnop 0 1}
test io-36.6 {Tcl_InputBlocked vs files, event driven read} {nonBlockFiles fileevent} {
    proc in {f} {
        variable l
        variable x
	variable l
	variable x
	lappend l [read $f 3]
	if {[eof $f]} {lappend l eof; close $f; set x done}
    }
    file delete $path(test1)
    set f [open $path(test1) w]
    puts $f abcdefghijklmnop
    close $f
5288
5289
5290
5291
5292
5293
5294
5295

5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5555
5556
5557
5558
5559
5560
5561

5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577



5578
5579
5580
5581
5582
5583
5584







-
+















-
-
-







    close $f
    set l
} {4096 10000 1 1 1 100000 1048576}
test io-38.3 {Tcl_SetChannelBufferSize, changing buffersize between reads} {
    # This test crashes the interp if Bug #427196 is not fixed

    set chan [open [info script] r]
    fconfigure $chan -buffersize 10
    fconfigure $chan -buffersize 10 -encoding utf-8
    set var [read $chan 2]
    fconfigure $chan -buffersize 32
    append var [read $chan]
    close $chan
} {}

# Test Tcl_SetChannelOption, Tcl_GetChannelOption

test io-39.1 {Tcl_GetChannelOption} {
    file delete $path(test1)
    set f1 [open $path(test1) w]
    set x [fconfigure $f1 -blocking]
    close $f1
    set x
} 1
#
# Test 17.2 was removed.
#
test io-39.2 {Tcl_GetChannelOption} {
    file delete $path(test1)
    set f1 [open $path(test1) w]
    set x [fconfigure $f1 -buffering]
    close $f1
    set x
} full
5376
5377
5378
5379
5380
5381
5382
5383

5384
5385
5386
5387
5388
5389
5390
5640
5641
5642
5643
5644
5645
5646

5647
5648
5649
5650
5651
5652
5653
5654







-
+







    close $f1
    set x
} {0 21}
test io-39.8 {Tcl_SetChannelOption, different buffering options} {
    file delete $path(test1)
    set f1 [open $path(test1) w]
    set l ""
    fconfigure $f1 -translation lf -buffering none -eofchar {}
    fconfigure $f1 -translation lf -buffering none
    puts -nonewline $f1 hello
    lappend l [file size $path(test1)]
    puts -nonewline $f1 hello
    lappend l [file size $path(test1)]
    fconfigure $f1 -buffering full
    puts -nonewline $f1 hello
    lappend l [file size $path(test1)]
5471
5472
5473
5474
5475
5476
5477
5478
5479


5480
5481
5482
5483
5484
5485
5486

5487
5488
5489
5490
5491


5492
5493
5494
5495
5496
5497
5498
5499


5500
5501
5502


5503
5504
5505








5506
5507
5508
5509


5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521

5522
5523
5524
5525
5526
5527

5528
5529
5530
5531
5532
5533
5534
5735
5736
5737
5738
5739
5740
5741


5742
5743
5744
5745
5746
5747
5748
5749

5750
5751
5752
5753


5754
5755
5756
5757
5758
5759
5760
5761


5762
5763
5764
5765

5766
5767
5768


5769
5770
5771
5772
5773
5774
5775
5776
5777
5778


5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791

5792
5793
5794
5795
5796
5797

5798
5799
5800
5801
5802
5803
5804
5805







-
-
+
+






-
+



-
-
+
+






-
-
+
+


-
+
+

-
-
+
+
+
+
+
+
+
+


-
-
+
+











-
+





-
+







    set x [fconfigure $f -buffersize]
    close $f
    set x
} 40000
test io-39.14 {Tcl_SetChannelOption: -encoding, binary & utf-8} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -encoding {}
    puts -nonewline $f \xe7\x89\xa6
    fconfigure $f -translation binary
    puts -nonewline $f \xE7\x89\xA6
    close $f
    set f [open $path(test1) r]
    fconfigure $f -encoding utf-8
    set x [read $f]
    close $f
    set x
} \u7266
} 牦
test io-39.15 {Tcl_SetChannelOption: -encoding, binary & utf-8} {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -encoding binary
    puts -nonewline $f \xe7\x89\xa6
    fconfigure $f -translation binary
    puts -nonewline $f \xE7\x89\xA6
    close $f
    set f [open $path(test1) r]
    fconfigure $f -encoding utf-8
    set x [read $f]
    close $f
    set x
} \u7266
test io-39.16 {Tcl_SetChannelOption: -encoding, errors} {
} 牦
test io-39.16 {Tcl_SetChannelOption: -encoding (shortened to "-en"), errors} -body {
    file delete $path(test1)
    set f [open $path(test1) w]
    set result [list [catch {fconfigure $f -encoding foobar} msg] $msg]
    fconfigure $f -en foobar
} -cleanup {
    close $f
    set result
} {1 {unknown encoding "foobar"}}
} -returnCodes 1 -result {unknown encoding "foobar"}
test io-39.16a {Tcl_SetChannelOption: -encoding (invalid shortening to "-e"), errors} -body {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -e foobar
} -cleanup {
    close $f
} -returnCodes 1 -match glob -result {bad option "-e": should be one of *}
test io-39.17 {Tcl_SetChannelOption: -encoding, clearing CHANNEL_NEED_MORE_DATA} {stdio fileevent} {
    set f [open "|[list [interpreter] $path(cat)]" r+]
    fconfigure $f -encoding binary
    puts -nonewline $f "\xe7"
    fconfigure $f -encoding iso8859-1
    puts -nonewline $f "\xE7"
    flush $f
    fconfigure $f -encoding utf-8 -blocking 0
    variable x {}
    fileevent $f readable [namespace code { lappend x [read $f] }]
    vwait [namespace which -variable x]
    after 300 [namespace code { lappend x timeout }]
    vwait [namespace which -variable x]
    fconfigure $f -encoding utf-8
    vwait [namespace which -variable x]
    after 300 [namespace code { lappend x timeout }]
    vwait [namespace which -variable x]
    fconfigure $f -encoding binary
    fconfigure $f -translation binary
    vwait [namespace which -variable x]
    after 300 [namespace code { lappend x timeout }]
    vwait [namespace which -variable x]
    close $f
    set x
} "{} timeout {} timeout \xe7 timeout"
} "{} timeout {} timeout \xE7 timeout"
test io-39.18 {Tcl_SetChannelOption, setting read mode independently} \
	{socket} {
    proc accept {s a p} {close $s}
    set s1 [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
    set port [lindex [fconfigure $s1 -sockname] 2]
    set s2 [socket 127.0.0.1 $port]
    update
5573
5574
5575
5576
5577
5578
5579
5580

5581
5582
5583
5584
5585

5586
5587
5588
5589
5590
5591
5592


5593
5594
5595
5596

5597
5598
5599
5600
5601
5602
5603

5604
5605

5606
5607
5608
5609
5610
5611

5612
5613

5614
5615
5616
5617
5618
5619
5620

5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637

5638
5639
5640
5641

5642
5643
5644
5645
5646
5647
5648
5649

5650
5651
5652
5653
5654
5655
5656


5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675

5676
5677
5678
5679
5680
5681
5682
5844
5845
5846
5847
5848
5849
5850

5851
5852
5853
5854
5855

5856
5857
5858
5859
5860
5861


5862
5863
5864
5865
5866

5867
5868
5869
5870
5871
5872
5873

5874
5875

5876
5877
5878
5879
5880
5881

5882
5883

5884
5885
5886
5887
5888
5889
5890

5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907

5908
5909
5910
5911

5912
5913
5914
5915
5916
5917
5918
5919

5920
5921
5922
5923
5924
5925


5926
5927
5928
5929
5930

5931
5932
5933

5934
5935
5936
5937
5938
5939
5940
5941
5942
5943

5944
5945
5946
5947
5948
5949
5950
5951







-
+




-
+





-
-
+
+



-
+






-
+

-
+





-
+

-
+






-
+
















-
+



-
+







-
+





-
-
+
+



-



-










-
+







    update
    fconfigure $s2 -translation {auto auto}
    set modes [fconfigure $s2 -translation]
    close $s1
    close $s2
    set modes
} {auto crlf}
test io-39.22 {Tcl_SetChannelOption, invariance} {unix} {
test io-39.22 {Tcl_SetChannelOption, invariance} -constraints {unix deprecated} -body {
    file delete $path(test1)
    set f1 [open $path(test1) w+]
    set l ""
    lappend l [fconfigure $f1 -eofchar]
    fconfigure $f1 -eofchar {ON GO}
    fconfigure $f1 -eofchar {O {}}
    lappend l [fconfigure $f1 -eofchar]
    fconfigure $f1 -eofchar D
    lappend l [fconfigure $f1 -eofchar]
    close $f1
    set l
} {{{} {}} {O G} {D D}}
test io-39.22a {Tcl_SetChannelOption, invariance} {
} -result {{} O D}
test io-39.22a {Tcl_SetChannelOption, invariance} -constraints deprecated -body {
    file delete $path(test1)
    set f1 [open $path(test1) w+]
    set l [list]
    fconfigure $f1 -eofchar {ON GO}
    fconfigure $f1 -eofchar {O {}}
    lappend l [fconfigure $f1 -eofchar]
    fconfigure $f1 -eofchar D
    lappend l [fconfigure $f1 -eofchar]
    lappend l [list [catch {fconfigure $f1 -eofchar {1 2 3}} msg] $msg]
    close $f1
    set l
} {{O G} {D D} {1 {bad value for -eofchar: should be a list of zero, one, or two elements}}}
} -result {O D {1 {bad value for -eofchar: must be non-NUL ASCII character}}}
test io-39.23 {Tcl_GetChannelOption, server socket is not readable or
        writeable, it should still have valid -eofchar and -translation options } {
	writable, it should still have valid -eofchar and -translation options } {
    set l [list]
    set sock [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
    lappend l [fconfigure $sock -eofchar] [fconfigure $sock -translation]
    close $sock
    set l
} {{{}} auto}
} {{} auto}
test io-39.24 {Tcl_SetChannelOption, server socket is not readable or
        writable so we can't change -eofchar or -translation } {
	writable so we can't change -eofchar or -translation } {
    set l [list]
    set sock [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
    fconfigure $sock -eofchar D -translation lf
    lappend l [fconfigure $sock -eofchar] [fconfigure $sock -translation]
    close $sock
    set l
} {{{}} auto}
} {{} auto}

test io-40.1 {POSIX open access modes: RDWR} {
    file delete $path(test3)
    set f [open $path(test3) w]
    puts $f xyzzy
    close $f
    set f [open $path(test3) RDWR]
    puts -nonewline $f "ab"
    seek $f 0 current
    set x [gets $f]
    close $f
    set f [open $path(test3) r]
    lappend x [gets $f]
    close $f
    set x
} {zzy abzzy}
test io-40.2 {POSIX open access modes: CREAT} {unix} {
test io-40.2 {POSIX open access modes: CREAT} {unix notWsl} {
    file delete $path(test3)
    set f [open $path(test3) {WRONLY CREAT} 0o600]
    file stat $path(test3) stats
    set x [format "%#o" [expr $stats(mode)&0o777]]
    set x [format "%#o" [expr {$stats(mode)&0o777}]]
    puts $f "line 1"
    close $f
    set f [open $path(test3) r]
    lappend x [gets $f]
    close $f
    set x
} {0o600 {line 1}}
test io-40.3 {POSIX open access modes: CREAT} {unix umask} {
test io-40.3 {POSIX open access modes: CREAT} {unix umask notWsl} {
    # This test only works if your umask is 2, like ouster's.
    file delete $path(test3)
    set f [open $path(test3) {WRONLY CREAT}]
    close $f
    file stat $path(test3) stats
    format "%#o" [expr $stats(mode)&0o777]
} [format %#5o [expr {0o666 & ~ $umaskValue}]]
    format 0o%03o [expr {$stats(mode)&0o777}]
} [format 0o%03o [expr {0o666 & ~ $umaskValue}]]
test io-40.4 {POSIX open access modes: CREAT} {
    file delete $path(test3)
    set f [open $path(test3) w]
    fconfigure $f -eofchar {}
    puts $f xyzzy
    close $f
    set f [open $path(test3) {WRONLY CREAT}]
    fconfigure $f -eofchar {}
    puts -nonewline $f "ab"
    close $f
    set f [open $path(test3) r]
    set x [gets $f]
    close $f
    set x
} abzzy
test io-40.5 {POSIX open access modes: APPEND} {
    file delete $path(test3)
    set f [open $path(test3) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    puts $f xyzzy
    close $f
    set f [open $path(test3) {WRONLY APPEND}]
    fconfigure $f -translation lf
    puts $f "new line"
    seek $f 0
    puts $f "abc"
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5965
5966
5967
5968
5969
5970
5971

5972
5973
5974
5975
5976
5977
5978







-







    puts $f xyzzy
    close $f
    open $path(test3) {WRONLY CREAT EXCL}
} -returnCodes error -result {(?i)couldn't open ".*test3": file (already )?exists}
test io-40.7 {POSIX open access modes: EXCL} {
    file delete $path(test3)
    set f [open $path(test3) {WRONLY CREAT EXCL}]
    fconfigure $f -eofchar {}
    puts $f "A test line"
    close $f
    viewFile test3
} {A test line}
test io-40.8 {POSIX open access modes: TRUNC} {
    file delete $path(test3)
    set f [open $path(test3) w]
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
6015
6016
6017
6018
6019
6020
6021

6022
6023
6024
6025
6026
6027
6028







-







test io-40.12 {POSIX open access modes: WRONLY} -match regexp -body {
    file delete $path(test3)
    open $path(test3) WRONLY
} -returnCodes error -result {(?i)couldn't open ".*test3": no such file or directory}
test io-40.13 {POSIX open access modes: WRONLY} {
    makeFile xyzzy test3
    set f [open $path(test3) WRONLY]
    fconfigure $f -eofchar {}
    puts -nonewline $f "ab"
    seek $f 0 current
    set x [list [catch {gets $f} msg] $msg]
    close $f
    lappend x [viewFile test3]
    string compare [string tolower $x] \
	[list 1 "channel \"$f\" wasn't opened for reading" abzzy]
5782
5783
5784
5785
5786
5787
5788
5789

5790
5791
5792
5793

5794
5795
5796

5797
5798
5799
5800
5801
5802
5803
6049
6050
6051
6052
6053
6054
6055

6056
6057
6058
6059

6060
6061
6062

6063
6064
6065
6066
6067
6068
6069
6070







-
+



-
+


-
+







} -result 1
test io-40.17 {tilde substitution in open} {
    set home $::env(HOME)
    unset ::env(HOME)
    set x [list [catch {open ~/foo} msg] $msg]
    set ::env(HOME) $home
    set x
} {1 {couldn't find HOME environment variable to expand path}}
} {1 {couldn't open "~/foo": no such file or directory}}

test io-41.1 {Tcl_FileeventCmd: errors} {fileevent} {
    list [catch {fileevent foo} msg] $msg
} {1 {wrong # args: should be "fileevent channelId event ?script?"}}
} {1 {wrong # args: should be "fileevent channel event ?script?"}}
test io-41.2 {Tcl_FileeventCmd: errors} {fileevent} {
    list [catch {fileevent foo bar baz q} msg] $msg
} {1 {wrong # args: should be "fileevent channelId event ?script?"}}
} {1 {wrong # args: should be "fileevent channel event ?script?"}}
test io-41.3 {Tcl_FileeventCmd: errors} {fileevent} {
    list [catch {fileevent gorp readable} msg] $msg
} {1 {can not find channel named "gorp"}}
test io-41.4 {Tcl_FileeventCmd: errors} {fileevent} {
    list [catch {fileevent gorp writable} msg] $msg
} {1 {can not find channel named "gorp"}}
test io-41.5 {Tcl_FileeventCmd: errors} {fileevent} {
5823
5824
5825
5826
5827
5828
5829
5830

5831
5832

5833
5834

5835
5836
5837
5838
5839
5840
5841
6090
6091
6092
6093
6094
6095
6096

6097
6098

6099
6100

6101
6102
6103
6104
6105
6106
6107
6108







-
+

-
+

-
+







    fileevent $f r "yet another"
    lappend result [fileevent $f readable]
    fileevent $f r ""
    lappend result [fileevent $f readable]
} {{first script} {new script} {yet another} {}}
test io-42.3 {Tcl_FileeventCmd: replacing, with NULL chars in script} {fileevent} {
    set result {}
    fileevent $f r "first scr\0ipt"
    fileevent $f r "first scr\x00ipt"
    lappend result [string length [fileevent $f readable]]
    fileevent $f r "new scr\0ipt"
    fileevent $f r "new scr\x00ipt"
    lappend result [string length [fileevent $f readable]]
    fileevent $f r "yet ano\0ther"
    fileevent $f r "yet ano\x00ther"
    lappend result [string length [fileevent $f readable]]
    fileevent $f r ""
    lappend result [fileevent $f readable]
} {13 11 12 {}}


test io-43.1 {Tcl_FileeventCmd: creating, deleting, querying} {stdio unixExecs fileevent} {
5965
5966
5967
5968
5969
5970
5971



5972
5973

5974
5975
5976
5977
5978


5979
5980


5981
5982
5983
5984
5985
5986

5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003

6004
6005


6006
6007
6008





















6009
6010


6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023

6024

6025
6026
6027
6028
6029
6030
6031
6032
6033










































6034
6035
6036
6037
6038
6039
6040
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242

6243
6244
6245
6246
6247

6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258

6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272

6273
6274
6275
6276
6277
6278
6279
6280



6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301


6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317

6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376







+
+
+

-
+




-
+
+


+
+





-
+













-



+


+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+













+
-
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    set x
} -cleanup {
    close $f4
} -result {initial foo eof}

close $f

# Bug https://core.tcl-lang.org/tcl/info/de232b49f26da1c1 with a corrected
# refchan implementation. refchans should be responsible for their own
# event generation and the one in the bug report was not doing so.
test io-44.6 {FileEventProc procedure: write-only non-blocking channel} -setup {
} -constraints {stdio fileevent openpipe} -body {
} -constraints {stdio fileevent} -body {

    namespace eval refchan {
	namespace ensemble create
	namespace export *

	# Change to taste depending on how much CPU you want to hog
	variable delay 0

	proc finalize {chan args} {
	    namespace upvar c_$chan timer timer
	    catch {after cancel $timer}
	    namespace delete c_$chan
	}

	proc initialize {chan args} {
	    namespace eval c_$chan {}
	    namespace upvar c_$chan watching watching
	    namespace upvar c_$chan watching watching timer timer
	    set watching {}
	    list finalize initialize seek watch write
	}


	proc watch {chan args} {
	    namespace upvar c_$chan watching watching
	    foreach arg $args {
		switch $arg {
		    write {
			if {$arg ni $watching} {
			    lappend watching $arg
			}
			chan postevent $chan $arg
		    }
		}
	    }
	    update $chan
	}

	proc write {chan args} {
	    return 1

	proc write {chan args} {
	    chan postevent $chan write
	}

	# paraphrased from tcllib
	proc update {chan} {
	    namespace upvar c_$chan watching watching timer timer
	    variable delay
	    catch {after cancel $timer}
	    if {"write" in $watching} {
		set timer [after idle after $delay \
			       [namespace code [list post $chan]]]
	    }
	}

	# paraphrased from tcllib
	proc post {chan} {
	    variable delay
	    namespace upvar c_$chan watching watching timer timer
	    if {"write" in $watching} {
		set timer [after idle after $delay \
			       [namespace code [list post $chan]]]
		chan postevent $chan write
	    return 1
	}
	    }
	}
    }
    set f [chan create w [namespace which refchan]]
    chan configure $f -blocking 0
    set data "some data"
    set x 0
    chan event $f writable [namespace code {
	puts $f $data
	incr count [string length $data]
	if {$count > 262144} {
	    chan event $f writable {}
	    set x done
	}
    }]
    # Note: timeout needs to be very long under valgrind
    set token [after 10000 [namespace code {
    set token [after 240000 [namespace code {
	set x timeout
    }]]
    vwait [namespace which -variable x]
    return $x
} -cleanup {
    after cancel $token
    catch {chan close $f}
} -result done

# Bug https://core.tcl-lang.org/tcl/info/67a5eabbd3d1 with a corrected
# refchan implementation. refchans that are not reentrant should use
# event loop to post events and the script in the bug report was not
# doing so.
test io-44.7 {refchan + coroutine yield error } -setup {
    set bghandler [interp bgerror {}]
    namespace eval schan {
	namespace ensemble create
	namespace export *
	proc open {} {
	    set chan [chan create read [namespace current]]

	}
	proc initialize {chan mode} {
	    return [list initialize finalize read watch]
	}
	proc finalize args {}
	proc read {chan count} {}
	proc watch {chan eventspec} {
	    foreach event $eventspec {
		after idle after 0 chan postevent $chan $event
	    }
	}
    }
} -cleanup {
    interp bgerror {} $bghandler
    unset -nocomplain ::io-44.7-result
    namespace delete schan
} -body {
    interp bgerror {} [list apply {{res opts} {
	set ::io-44.7-result [dict get $opts -errorinfo]
    }}]
    coroutine c1 apply [list {} {
	set chan [schan::open]
	chan event $chan readable [list [info coroutine]]
	yield
	close $chan
	set ::io-44.7-result success
    } [namespace current]]
    vwait ::io-44.7-result
    set ::io-44.7-result
} -result success

makeFile "foo bar" foo

test io-45.1 {DeleteFileEvent, cleanup on close} {fileevent} {
    set f [open $path(foo) r]
    fileevent $f readable [namespace code {
	lappend x "binding triggered: \"[gets $f]\""
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114




6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127








6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144

6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160

6161
6162
6163
6164

6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182

6183
6184
6185

6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202


6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216

6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229

6230
6231
6232
6233
6234
6235
6236
6440
6441
6442
6443
6444
6445
6446




6447
6448
6449
6450
6451
6452
6453
6454
6455








6456
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
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517

6518
6519
6520

6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536


6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551

6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564

6565
6566
6567
6568
6569
6570
6571
6572







-
-
-
-
+
+
+
+





-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
















-
+















-
+



-
+

















-
+


-
+















-
-
+
+













-
+












-
+







    after cancel $timer
    testfevent cmd {close $f}
    list [testfevent cmd {set x}] [testfevent cmd {info commands after}]
} {{f triggered: foo bar} after}
test io-46.2 {Tcl event loop vs multiple interpreters} testfevent {
    testfevent create
    testfevent cmd {
        variable x 0
        after 100 {set x triggered}
        vwait [namespace which -variable x]
        set x
	variable x 0
	after 100 {set x triggered}
	vwait [namespace which -variable x]
	set x
    }
} {triggered}
test io-46.3 {Tcl event loop vs multiple interpreters} testfevent {
    testfevent create
    testfevent cmd {
        set x 0
        after 10 {lappend x timer}
        after 30
        set result $x
        update idletasks
        lappend result $x
        update
        lappend result $x
	set x 0
	after 10 {lappend x timer}
	after 30
	set result $x
	update idletasks
	lappend result $x
	update
	lappend result $x
    }
} {0 0 {0 timer}}

test io-47.1 {fileevent vs multiple interpreters} {testfevent fileevent} {
    set f  [open $path(foo) r]
    set f2 [open $path(foo) r]
    set f3 [open $path(foo) r]
    fileevent $f readable {script 1}
    testfevent create
    testfevent share $f2
    testfevent cmd "fileevent $f2 readable {script 2}"
    fileevent $f3 readable {sript 3}
    set x {}
    lappend x [fileevent $f2 readable]
    testfevent delete
    lappend x [fileevent $f readable] [fileevent $f2 readable] \
        [fileevent $f3 readable]
	[fileevent $f3 readable]
    close $f
    close $f2
    close $f3
    set x
} {{} {script 1} {} {sript 3}}
test io-47.2 {deleting fileevent on interpreter delete} {testfevent fileevent} {
    set f  [open $path(foo) r]
    set f2 [open $path(foo) r]
    set f3 [open $path(foo) r]
    set f4 [open $path(foo) r]
    fileevent $f readable {script 1}
    testfevent create
    testfevent share $f2
    testfevent share $f3
    testfevent cmd "fileevent $f2 readable {script 2}
        fileevent $f3 readable {script 3}"
	fileevent $f3 readable {script 3}"
    fileevent $f4 readable {script 4}
    testfevent delete
    set x [list [fileevent $f readable] [fileevent $f2 readable] \
                [fileevent $f3 readable] [fileevent $f4 readable]]
		[fileevent $f3 readable] [fileevent $f4 readable]]
    close $f
    close $f2
    close $f3
    close $f4
    set x
} {{script 1} {} {} {script 4}}
test io-47.3 {deleting fileevent on interpreter delete} {testfevent fileevent} {
    set f  [open $path(foo) r]
    set f2 [open $path(foo) r]
    set f3 [open $path(foo) r]
    set f4 [open $path(foo) r]
    testfevent create
    testfevent share $f3
    testfevent share $f4
    fileevent $f readable {script 1}
    fileevent $f2 readable {script 2}
    testfevent cmd "fileevent $f3 readable {script 3}
      fileevent $f4 readable {script 4}"
    fileevent $f4 readable {script 4}"
    testfevent delete
    set x [list [fileevent $f readable] [fileevent $f2 readable] \
                [fileevent $f3 readable] [fileevent $f4 readable]]
		[fileevent $f3 readable] [fileevent $f4 readable]]
    close $f
    close $f2
    close $f3
    close $f4
    set x
} {{script 1} {script 2} {} {}}
test io-47.4 {file events on shared files and multiple interpreters} {testfevent fileevent} {
    set f  [open $path(foo) r]
    set f2 [open $path(foo) r]
    testfevent create
    testfevent share $f
    testfevent cmd "fileevent $f readable {script 1}"
    fileevent $f readable {script 2}
    fileevent $f2 readable {script 3}
    set x [list [fileevent $f2 readable] \
                [testfevent cmd "fileevent $f readable"] \
                [fileevent $f readable]]
		[testfevent cmd "fileevent $f readable"] \
		[fileevent $f readable]]
    testfevent delete
    close $f
    close $f2
    set x
} {{script 3} {script 1} {script 2}}
test io-47.5 {file events on shared files, deleting file events} {testfevent fileevent} {
    set f [open $path(foo) r]
    testfevent create
    testfevent share $f
    testfevent cmd "fileevent $f readable {script 1}"
    fileevent $f readable {script 2}
    testfevent cmd "fileevent $f readable {}"
    set x [list [testfevent cmd "fileevent $f readable"] \
                [fileevent $f readable]]
		[fileevent $f readable]]
    testfevent delete
    close $f
    set x
} {{} {script 2}}
test io-47.6 {file events on shared files, deleting file events} {testfevent fileevent} {
    set f [open $path(foo) r]
    testfevent create
    testfevent share $f
    testfevent cmd "fileevent $f readable {script 1}"
    fileevent $f readable {script 2}
    fileevent $f readable {}
    set x [list [testfevent cmd "fileevent $f readable"] \
                [fileevent $f readable]]
		[fileevent $f readable]]
    testfevent delete
    close $f
    set x
} {{script 1} {}}
unset path(foo)
removeFile foo

6356
6357
6358
6359
6360
6361
6362
6363

6364
6365
6366
6367
6368
6369
6370
6692
6693
6694
6695
6696
6697
6698

6699
6700
6701
6702
6703
6704
6705
6706







-
+







	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    fconfigure $f -translation auto -eofchar \x1a
    fconfigure $f -translation auto -eofchar \x1A
    fileevent $f readable [namespace code [list consume $f]]
    variable x
    vwait [namespace which -variable x]
    list $c $l
} {3 {abc def {}}}
test io-48.5 {lf write, testing readability, ^Z in middle, auto read mode} {fileevent} {
    file delete $path(test1)
6384
6385
6386
6387
6388
6389
6390
6391

6392
6393
6394
6395
6396
6397
6398
6720
6721
6722
6723
6724
6725
6726

6727
6728
6729
6730
6731
6732
6733
6734







-
+







	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation auto
    fconfigure $f -translation auto -eofchar \x1A
    fileevent $f readable [namespace code [list consume $f]]
    variable x
    vwait [namespace which -variable x]
    list $c $l
} {3 {abc def {}}}
test io-48.6 {cr write, testing readability, ^Z termination, auto read mode} {fileevent} {
    file delete $path(test1)
6412
6413
6414
6415
6416
6417
6418
6419

6420
6421
6422
6423
6424
6425
6426
6748
6749
6750
6751
6752
6753
6754

6755
6756
6757
6758
6759
6760
6761
6762







-
+







	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    fconfigure $f -translation auto -eofchar \x1a
    fconfigure $f -translation auto -eofchar \x1A
    fileevent $f readable [namespace code [list consume $f]]
    variable x
    vwait [namespace which -variable x]
    list $c $l
} {3 {abc def {}}}
test io-48.7 {cr write, testing readability, ^Z in middle, auto read mode} {fileevent} {
    file delete $path(test1)
6440
6441
6442
6443
6444
6445
6446
6447

6448
6449
6450
6451
6452
6453
6454
6776
6777
6778
6779
6780
6781
6782

6783
6784
6785
6786
6787
6788
6789
6790







-
+







	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation auto
    fconfigure $f -translation auto -eofchar \x1A
    fileevent $f readable [namespace code [list consume $f]]
    variable x
    vwait [namespace which -variable x]
    list $c $l
} {3 {abc def {}}}
test io-48.8 {crlf write, testing readability, ^Z termination, auto read mode} {fileevent} {
    file delete $path(test1)
6468
6469
6470
6471
6472
6473
6474
6475

6476
6477
6478
6479
6480
6481
6482
6804
6805
6806
6807
6808
6809
6810

6811
6812
6813
6814
6815
6816
6817
6818







-
+







	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    fconfigure $f -translation auto -eofchar \x1a
    fconfigure $f -translation auto -eofchar \x1A
    fileevent $f readable [namespace code [list consume $f]]
    variable x
    vwait [namespace which -variable x]
    list $c $l
} {3 {abc def {}}}
test io-48.9 {crlf write, testing readability, ^Z in middle, auto read mode} {fileevent} {
    file delete $path(test1)
6496
6497
6498
6499
6500
6501
6502
6503

6504
6505
6506
6507
6508
6509
6510
6832
6833
6834
6835
6836
6837
6838

6839
6840
6841
6842
6843
6844
6845
6846







-
+







	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation auto
    fconfigure $f -translation auto -eofchar \x1A
    fileevent $f readable [namespace code [list consume $f]]
    variable x
    vwait [namespace which -variable x]
    list $c $l
} {3 {abc def {}}}
test io-48.10 {lf write, testing readability, ^Z in middle, lf read mode} {fileevent} {
    file delete $path(test1)
6524
6525
6526
6527
6528
6529
6530
6531

6532
6533
6534
6535
6536
6537
6538
6860
6861
6862
6863
6864
6865
6866

6867
6868
6869
6870
6871
6872
6873
6874







-
+







	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation lf
    fconfigure $f -translation lf -eofchar \x1A
    fileevent $f readable [namespace code [list consume $f]]
    variable x
    vwait [namespace which -variable x]
    list $c $l
} {3 {abc def {}}}
test io-48.11 {lf write, testing readability, ^Z termination, lf read mode} {fileevent} {
    file delete $path(test1)
6552
6553
6554
6555
6556
6557
6558
6559

6560
6561
6562
6563
6564
6565
6566
6888
6889
6890
6891
6892
6893
6894

6895
6896
6897
6898
6899
6900
6901
6902







-
+







	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    fconfigure $f -translation lf -eofchar \x1a
    fconfigure $f -translation lf -eofchar \x1A
    fileevent $f readable [namespace code [list consume $f]]
    variable x
    vwait [namespace which -variable x]
    list $c $l
} {3 {abc def {}}}
test io-48.12 {cr write, testing readability, ^Z in middle, cr read mode} {fileevent} {
    file delete $path(test1)
6580
6581
6582
6583
6584
6585
6586
6587

6588
6589
6590
6591
6592
6593
6594
6916
6917
6918
6919
6920
6921
6922

6923
6924
6925
6926
6927
6928
6929
6930







-
+







	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation cr
    fconfigure $f -translation cr -eofchar \x1A
    fileevent $f readable [namespace code [list consume $f]]
    variable x
    vwait [namespace which -variable x]
    list $c $l
} {3 {abc def {}}}
test io-48.13 {cr write, testing readability, ^Z termination, cr read mode} {fileevent} {
    file delete $path(test1)
6608
6609
6610
6611
6612
6613
6614
6615

6616
6617
6618
6619
6620
6621
6622
6944
6945
6946
6947
6948
6949
6950

6951
6952
6953
6954
6955
6956
6957
6958







-
+







	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    fconfigure $f -translation cr -eofchar \x1a
    fconfigure $f -translation cr -eofchar \x1A
    fileevent $f readable [namespace code [list consume $f]]
    variable x
    vwait [namespace which -variable x]
    list $c $l
} {3 {abc def {}}}
test io-48.14 {crlf write, testing readability, ^Z in middle, crlf read mode} {fileevent} {
    file delete $path(test1)
6636
6637
6638
6639
6640
6641
6642
6643

6644
6645
6646
6647
6648
6649
6650
6972
6973
6974
6975
6976
6977
6978

6979
6980
6981
6982
6983
6984
6985
6986







-
+







	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation crlf
    fconfigure $f -translation crlf -eofchar \x1A
    fileevent $f readable [namespace code [list consume $f]]
    variable x
    vwait [namespace which -variable x]
    list $c $l
} {3 {abc def {}}}
test io-48.15 {crlf write, testing readability, ^Z termi, crlf read mode} {fileevent} {
    file delete $path(test1)
6664
6665
6666
6667
6668
6669
6670
6671

6672
6673
6674
6675
6676
6677
6678
7000
7001
7002
7003
7004
7005
7006

7007
7008
7009
7010
7011
7012
7013
7014







-
+







	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    fconfigure $f -translation crlf -eofchar \x1a
    fconfigure $f -translation crlf -eofchar \x1A
    fileevent $f readable [namespace code [list consume $f]]
    variable x
    vwait [namespace which -variable x]
    list $c $l
} {3 {abc def {}}}

test io-49.1 {testing crlf reading, leftover cr disgorgment} {
7056
7057
7058
7059
7060
7061
7062
7063
7064


7065
7066
7067
7068
7069
7070
7071
7072

7073
7074
7075
7076
7077
7078
7079
7392
7393
7394
7395
7396
7397
7398


7399
7400
7401
7402
7403
7404
7405
7406
7407

7408
7409
7410
7411
7412
7413
7414
7415







-
-
+
+







-
+







    close $f3
    string compare $msg "channel \"$f2\" is busy"
} {0}
test io-52.3 {TclCopyChannel} {fcopy} {
    file delete $path(test1)
    set f1 [open $thisScript]
    set f2 [open $path(test1) w]
    fconfigure $f1 -translation lf -blocking 0
    fconfigure $f2 -translation cr -blocking 0
    fconfigure $f1 -translation lf -encoding iso8859-1 -blocking 0
    fconfigure $f2 -translation cr -encoding iso8859-1 -blocking 0
    set s0 [fcopy $f1 $f2]
    set result [list [fconfigure $f1 -blocking] [fconfigure $f2 -blocking]]
    close $f1
    close $f2
    set s1 [file size $thisScript]
    set s2 [file size $path(test1)]
    if {("$s1" == "$s2") && ($s0 == $s1)} {
        lappend result ok
	lappend result ok
    }
    set result
} {0 0 ok}
test io-52.4 {TclCopyChannel} {fcopy} {
    file delete $path(test1)
    set f1 [open $thisScript]
    set f2 [open $path(test1) w]
7097
7098
7099
7100
7101
7102
7103
7104
7105


7106
7107
7108
7109
7110
7111
7112
7113

7114
7115
7116
7117
7118
7119
7120
7121
7122


7123
7124
7125
7126
7127
7128
7129
7130

7131
7132
7133
7134
7135
7136
7137
7138
7139


7140
7141
7142
7143
7144
7145
7146
7147

7148
7149
7150
7151
7152
7153
7154
7155
7156
7157



7158
7159
7160
7161
7162
7163
7164

7165
7166
7167
7168
7169
7170
7171
7172
7173


7174
7175
7176
7177
7178
7179
7180
7181

7182
7183
7184
7185
7186
7187
7188
7433
7434
7435
7436
7437
7438
7439


7440
7441
7442
7443
7444
7445
7446
7447
7448

7449
7450
7451
7452
7453
7454
7455
7456


7457
7458
7459
7460
7461
7462
7463
7464
7465

7466
7467
7468
7469
7470
7471
7472
7473


7474
7475
7476
7477
7478
7479
7480
7481
7482

7483
7484
7485
7486
7487
7488
7489
7490



7491
7492
7493
7494
7495
7496
7497
7498
7499

7500
7501
7502
7503
7504
7505
7506
7507


7508
7509
7510
7511
7512
7513
7514
7515
7516

7517
7518
7519
7520
7521
7522
7523
7524







-
-
+
+







-
+







-
-
+
+







-
+







-
-
+
+







-
+







-
-
-
+
+
+






-
+







-
-
+
+







-
+







    close $f2
    lappend result [file size $path(test1)]
} {0 0 0 40}
test io-52.5 {TclCopyChannel, all} {fcopy} {
    file delete $path(test1)
    set f1 [open $thisScript]
    set f2 [open $path(test1) w]
    fconfigure $f1 -translation lf -blocking 0
    fconfigure $f2 -translation lf -blocking 0
    fconfigure $f1 -translation lf -encoding iso8859-1 -blocking 0
    fconfigure $f2 -translation lf -encoding iso8859-1 -blocking 0
    fcopy $f1 $f2 -size -1 ;# -1 means 'copy all', same as if no -size specified.
    set result [list [fconfigure $f1 -blocking] [fconfigure $f2 -blocking]]
    close $f1
    close $f2
    set s1 [file size $thisScript]
    set s2 [file size $path(test1)]
    if {"$s1" == "$s2"} {
        lappend result ok
	lappend result ok
    }
    set result
} {0 0 ok}
test io-52.5a {TclCopyChannel, all, other negative value} {fcopy} {
    file delete $path(test1)
    set f1 [open $thisScript]
    set f2 [open $path(test1) w]
    fconfigure $f1 -translation lf -blocking 0
    fconfigure $f2 -translation lf -blocking 0
    fconfigure $f1 -translation lf -encoding iso8859-1 -blocking 0
    fconfigure $f2 -translation lf -encoding iso8859-1 -blocking 0
    fcopy $f1 $f2 -size -2 ;# < 0 behaves like -1, copy all
    set result [list [fconfigure $f1 -blocking] [fconfigure $f2 -blocking]]
    close $f1
    close $f2
    set s1 [file size $thisScript]
    set s2 [file size $path(test1)]
    if {"$s1" == "$s2"} {
        lappend result ok
	lappend result ok
    }
    set result
} {0 0 ok}
test io-52.5b {TclCopyChannel, all, wrap to negative value} {fcopy} {
    file delete $path(test1)
    set f1 [open $thisScript]
    set f2 [open $path(test1) w]
    fconfigure $f1 -translation lf -blocking 0
    fconfigure $f2 -translation lf -blocking 0
    fconfigure $f1 -translation lf -encoding iso8859-1 -blocking 0
    fconfigure $f2 -translation lf -encoding iso8859-1 -blocking 0
    fcopy $f1 $f2 -size 3221176172 ;# Wrapped to < 0, behaves like -1, copy all
    set result [list [fconfigure $f1 -blocking] [fconfigure $f2 -blocking]]
    close $f1
    close $f2
    set s1 [file size $thisScript]
    set s2 [file size $path(test1)]
    if {"$s1" == "$s2"} {
        lappend result ok
	lappend result ok
    }
    set result
} {0 0 ok}
test io-52.6 {TclCopyChannel} {fcopy} {
    file delete $path(test1)
    set f1 [open $thisScript]
    set f2 [open $path(test1) w]
    fconfigure $f1 -translation lf -blocking 0
    fconfigure $f2 -translation lf -blocking 0
    set s0 [fcopy $f1 $f2 -size [expr [file size $thisScript] + 5]]
    fconfigure $f1 -translation lf -encoding iso8859-1 -blocking 0
    fconfigure $f2 -translation lf -encoding iso8859-1 -blocking 0
    set s0 [fcopy $f1 $f2 -size [expr {[file size $thisScript] + 5}]]
    set result [list [fconfigure $f1 -blocking] [fconfigure $f2 -blocking]]
    close $f1
    close $f2
    set s1 [file size $thisScript]
    set s2 [file size $path(test1)]
    if {("$s1" == "$s2") && ($s0 == $s1)} {
        lappend result ok
	lappend result ok
    }
    set result
} {0 0 ok}
test io-52.7 {TclCopyChannel} {fcopy} {
    file delete $path(test1)
    set f1 [open $thisScript]
    set f2 [open $path(test1) w]
    fconfigure $f1 -translation lf -blocking 0
    fconfigure $f2 -translation lf -blocking 0
    fconfigure $f1 -translation lf -encoding iso8859-1 -blocking 0
    fconfigure $f2 -translation lf -encoding iso8859-1 -blocking 0
    fcopy $f1 $f2
    set result [list [fconfigure $f1 -blocking] [fconfigure $f2 -blocking]]
    set s1 [file size $thisScript]
    set s2 [file size $path(test1)]
    close $f1
    close $f2
    if {"$s1" == "$s2"} {
        lappend result ok
	lappend result ok
    }
    set result
} {0 0 ok}
test io-52.8 {TclCopyChannel} {stdio fcopy} {
    file delete $path(test1)
    file delete $path(pipe)
    set f1 [open $path(pipe) w]
7211
7212
7213
7214
7215
7216
7217
7218

7219
7220
7221
7222
7223
7224
7225
7547
7548
7549
7550
7551
7552
7553

7554
7555
7556
7557
7558
7559
7560
7561







-
+







# Empty files, to register them with the test facility
set path(kyrillic.txt)   [makeFile {} kyrillic.txt]
set path(utf8-fcopy.txt) [makeFile {} utf8-fcopy.txt]
set path(utf8-rp.txt)    [makeFile {} utf8-rp.txt]
# Create kyrillic file, use lf translation to avoid os eol issues
set out [open $path(kyrillic.txt) w]
fconfigure $out -encoding koi8-r -translation lf
puts       $out "\u0410\u0410"
puts       $out "ÐÐ"
close      $out
test io-52.9 {TclCopyChannel & encodings} {fcopy} {
    # Copy kyrillic to UTF-8, using fcopy.

    set in  [open $path(kyrillic.txt) r]
    set out [open $path(utf8-fcopy.txt) w]

7243
7244
7245
7246
7247
7248
7249
7250

7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261



7262
7263
7264

7265
7266

7267
7268
7269
7270


7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281

7282
7283
7284
7285
7286









7287
7288



7289
7290
7291
7292
7293
7294
7295
7579
7580
7581
7582
7583
7584
7585

7586



7587
7588
7589
7590

7591
7592
7593
7594
7595
7596
7597
7598

7599


7600
7601
7602


7603
7604
7605
7606



7607
7608


7609

7610





7611
7612
7613
7614
7615
7616
7617
7618
7619


7620
7621
7622
7623
7624
7625
7626
7627
7628
7629







-
+
-
-
-




-



+
+
+


-
+
-
-
+


-
-
+
+


-
-
-


-
-

-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
+
+







    close $in
    close $out

    list [file size $path(kyrillic.txt)] \
	    [file size $path(utf8-fcopy.txt)] \
	    [file size $path(utf8-rp.txt)]
} {3 5 5}
test io-52.10 {TclCopyChannel & encodings} {fcopy} {
test io-52.10 {TclCopyChannel & encodings} -constraints fcopy -body {
    # encoding to binary (=> implies that the
    # internal utf-8 is written)

    set in  [open $path(kyrillic.txt) r]
    set out [open $path(utf8-fcopy.txt) w]

    fconfigure $in  -encoding koi8-r -translation lf
    # -translation binary is also -encoding binary
    fconfigure $out -translation binary

    fcopy $in $out

    file size $path(utf8-fcopy.txt)
} -cleanup {
    close $in
    close $out

} -returnCodes 1 -match glob -result {error writing "*":\
    file size $path(utf8-fcopy.txt)
} 5
    invalid or incomplete multibyte or wide character}
test io-52.11 {TclCopyChannel & encodings} -setup {
    set out [open $path(utf8-fcopy.txt) w]
    fconfigure $out -encoding utf-8 -translation lf
    puts $out "\u0410\u0410"
    fconfigure $out -encoding utf-8 -translation lf -profile strict
    puts $out ÐÐ
    close $out
} -constraints {fcopy} -body {
    # binary to encoding => the input has to be
    # in utf-8 to make sense to the encoder

    set in  [open $path(utf8-fcopy.txt) r]
    set out [open $path(kyrillic.txt) w]

    # -translation binary is also -encoding binary
    fconfigure $in  -translation binary
    fconfigure $out -encoding koi8-r -translation lf
    fconfigure $out -encoding koi8-r -translation lf -profile strict

    fcopy $in $out
    close $in
    close $out

    catch {fcopy $in $out} cres copts
	return $cres
} -cleanup {
	if {$in in [chan names]} {
		close $in
	}
	if {$out in [chan names]} {
		close $out
	}
    file size $path(kyrillic.txt)
} -result 3
    catch {unset cres}
} -match glob -result  {error writing "*": invalid or incomplete\
	multibyte or wide character}

test io-52.12 {coverage of -translation auto} {
    file delete $path(test1) $path(test2)
    set out [open $path(test1) wb]
    chan configure $out -translation lf
    puts -nonewline $out abcdefg\rhijklmn\nopqrstu\r\nvwxyz
    close $out
7426
7427
7428
7429
7430
7431
7432












































































































































































7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449
7450
7451


7452
7453
7454
7455
7456
7457
7458
7459
7460
7461

7462
7463
7464
7465
7466
7467
7468
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952
7953
7954
7955


7956
7957
7958
7959
7960
7961
7962
7963
7964
7965
7966

7967
7968
7969
7970
7971
7972
7973
7974







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

















-
-
+
+









-
+







    chan configure $in -buffersize 10 -translation crlf -eofchar h
    set out [open $path(test2) w]
    fcopy $in $out
    close $in
    close $out
    file size $path(test2)
} 8
test io-52.20 {TclCopyChannel & encodings} -setup {
    set out [open $path(utf8-fcopy.txt) w]
    fconfigure $out -encoding utf-8 -translation lf
    puts $out "Ã"
    close $out
} -constraints {fcopy} -body {
    # binary to encoding => the input has to be
    # in utf-8 to make sense to the encoder

    set in  [open $path(utf8-fcopy.txt) r]
    set out [open $path(kyrillic.txt) w]

    # Using "-encoding ascii" means reading the "Ã" gives an error
    fconfigure $in  -encoding ascii -profile strict
    fconfigure $out -encoding koi8-r -translation lf

    fcopy $in $out
} -cleanup {
    close $in
    close $out
} -returnCodes 1 -match glob -result {error reading "file*": invalid or incomplete multibyte or wide character}

test io-52.20.2 {TclCopyChannel & encoding error on same encoding} -setup {
    set out [open $path(utf8-fcopy.txt) w]
    fconfigure $out -encoding utf-8 -translation lf
    puts $out "AÃ"
    close $out
} -constraints {fcopy} -body {
    # binary to encoding => the input has to be
    # in utf-8 to make sense to the encoder

    set in  [open $path(utf8-fcopy.txt) r]
    set out [open $path(kyrillic.txt) w]

    # Using "-encoding ascii" means reading the "Ã" gives an error
    fconfigure $in  -encoding ascii -profile strict
    fconfigure $out -encoding ascii -translation lf

    fcopy $in $out
} -cleanup {
    close $in
    close $out
} -returnCodes 1 -match glob -result {error reading "file*": invalid or incomplete multibyte or wide character}

test io-52.21 {TclCopyChannel & encodings} -setup {
    set out [open $path(utf8-fcopy.txt) w]
    fconfigure $out -encoding utf-8 -translation lf
    puts $out "Ã"
    close $out
} -constraints {fcopy} -body {
    # binary to encoding => the input has to be
    # in utf-8 to make sense to the encoder

    set in  [open $path(utf8-fcopy.txt) r]
    set out [open $path(kyrillic.txt) w]

    # Using "-encoding ascii" means writing the "Ã" gives an error
    fconfigure $in  -encoding utf-8
    fconfigure $out -encoding ascii -translation lf -profile strict

    fcopy $in $out
} -cleanup {
    close $in
    close $out
} -returnCodes 1 -match glob -result {error writing "file*": invalid or incomplete multibyte or wide character}

test io-52.22 {TclCopyChannel & encodings} -setup {
    set out [open $path(utf8-fcopy.txt) w]
    fconfigure $out -encoding utf-8 -translation lf
    puts $out "Ã"
    close $out
} -constraints {fcopy} -body {
    # binary to encoding => the input has to be
    # in utf-8 to make sense to the encoder

    set in  [open $path(utf8-fcopy.txt) r]
    set out [open $path(kyrillic.txt) w]

    # Using "-encoding ascii" means reading the "Ã" gives an error
    fconfigure $in  -encoding ascii -profile strict
    fconfigure $out -encoding koi8-r -translation lf
    proc ::xxx args {
	set ::s0 $args
    }

    fcopy $in $out -command ::xxx
    vwait ::s0
    set ::s0
} -cleanup {
    close $in
    close $out
    unset ::s0
} -match glob -result {0 {error reading "file*": invalid or incomplete multibyte or wide character}}

test io-52.22.1 {TclCopyChannel & encodings & tell position} -setup {
    set out [open $path(utf8-fcopy.txt) w]
    fconfigure $out -encoding utf-8 -translation lf
    puts $out "AÃ"
    close $out
} -constraints {fcopy} -body {
    # binary to encoding => the input has to be
    # in utf-8 to make sense to the encoder

    set in  [open $path(utf8-fcopy.txt) r]
    set out [open $path(kyrillic.txt) w]

    # Using "-encoding ascii" means reading the "Ã" gives an error
    fconfigure $in  -encoding ascii -profile strict
    fconfigure $out -encoding koi8-r -translation lf
    proc ::xxx args {
	set ::s0 $args
    }

    fcopy $in $out -command ::xxx
    vwait ::s0
    list [tell $in] [tell $out] {*}[set ::s0]
} -cleanup {
    close $in
    close $out
    unset ::s0
} -match glob -result {1 1 1 {error reading "file*": invalid or incomplete multibyte or wide character}}

test io-52.23 {TclCopyChannel & encodings} -setup {
    set out [open $path(utf8-fcopy.txt) w]
    fconfigure $out -encoding utf-8 -translation lf
    puts $out "Ã"
    close $out
} -constraints {fcopy} -body {
    # binary to encoding => the input has to be
    # in utf-8 to make sense to the encoder

    set in  [open $path(utf8-fcopy.txt) r]
    set out [open $path(kyrillic.txt) w]

    # Using "-encoding ascii" means writing the "Ã" gives an error
    fconfigure $in  -encoding utf-8
    fconfigure $out -encoding ascii -translation lf -profile strict
    proc ::xxx args {
	set ::s0 $args
    }

    fcopy $in $out -command ::xxx
    vwait ::s0
    set ::s0
} -cleanup {
    close $in
    close $out
    unset ::s0
} -match glob -result {0 {error writing "file*": invalid or incomplete multibyte or wide character}}

test io-52.24 {fcopy -size should always be characters} -setup {
    set out [open utf8-fcopy-52.24.txt w]
    fconfigure $out -encoding utf-8 -translation lf
    puts $out "Ã"
    close $out
} -constraints {fcopy} -body {
    set in  [open utf8-fcopy-52.24.txt r]
    set out [open utf8-fcopy-52.24.out.txt w+]

    fconfigure $in  -encoding utf-8 -profile tcl8
    fconfigure $out -encoding utf-8 -profile tcl8
    fcopy $in $out -size 1
	seek $out 0
	# a result of \xc3 means that only the first byte of the utf-8 encoding of
	# Ã made it into to the output file.
	read $out
} -cleanup {
    close $in
    close $out
	catch {file delete utf8-fcopy-52.24.txt}
    catch {file delete utf8-fcopy-52.24.out.txt}
} -result Ã

test io-53.1 {CopyData} {fcopy} {
    file delete $path(test1)
    set f1 [open $thisScript]
    set f2 [open $path(test1) w]
    fconfigure $f1 -translation lf -blocking 0
    fconfigure $f2 -translation cr -blocking 0
    fcopy $f1 $f2 -size 0
    set result [list [fconfigure $f1 -blocking] [fconfigure $f2 -blocking]]
    close $f1
    close $f2
    lappend result [file size $path(test1)]
} {0 0 0}
test io-53.2 {CopyData} {fcopy} {
    file delete $path(test1)
    set f1 [open $thisScript]
    set f2 [open $path(test1) w]
    fconfigure $f1 -translation lf -blocking 0
    fconfigure $f2 -translation cr -blocking 0
    fconfigure $f1 -translation lf -encoding iso8859-1 -blocking 0
    fconfigure $f2 -translation cr -encoding iso8859-1 -blocking 0
    fcopy $f1 $f2 -command [namespace code {set s0}]
    set result [list [fconfigure $f1 -blocking] [fconfigure $f2 -blocking]]
    variable s0
    vwait [namespace which -variable s0]
    close $f1
    close $f2
    set s1 [file size $thisScript]
    set s2 [file size $path(test1)]
    if {("$s1" == "$s2") && ($s0 == $s1)} {
        lappend result ok
	lappend result ok
    }
    set result
} {0 0 ok}
test io-53.3 {CopyData: background read underflow} {stdio unix fcopy} {
    file delete $path(test1)
    file delete $path(pipe)
    set f1 [open $path(pipe) w]
7572
7573
7574
7575
7576
7577
7578


7579
7580
7581

7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600

7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617


7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632

7633
7634

7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647

7648
7649
7650
7651
7652
7653

7654
7655
7656
7657
7658
7659
7660
8078
8079
8080
8081
8082
8083
8084
8085
8086
8087
8088

8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107

8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123


8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139

8140
8141

8142
8143
8144
8145
8146
8147
8148
8149
8150
8151
8152
8153
8154

8155
8156
8157
8158
8159
8160

8161
8162
8163
8164
8165
8166
8167
8168







+
+


-
+


















-
+















-
-
+
+














-
+

-
+












-
+





-
+







test io-53.5 {CopyData: error during fcopy} {socket fcopy} {
    variable fcopyTestDone
    set listen [socket -server [namespace code FcopyTestAccept] -myaddr 127.0.0.1 0]
    set in [open $thisScript]	;# 126 K
    set out [socket 127.0.0.1 [lindex [fconfigure $listen -sockname] 2]]
    catch {unset fcopyTestDone}
    close $listen	;# This means the socket open never really succeeds
    fconfigure $in -encoding utf-8
    fconfigure $out -encoding utf-8
    fcopy $in $out -command [namespace code FcopyTestDone]
    variable fcopyTestDone
    if ![info exists fcopyTestDone] {
    if {![info exists fcopyTestDone]} {
	vwait [namespace which -variable fcopyTestDone]		;# The error occurs here in the b.g.
    }
    close $in
    close $out
    set fcopyTestDone	;# 1 for error condition
} 1
test io-53.6 {CopyData: error during fcopy} {stdio fcopy} {
    variable fcopyTestDone
    file delete $path(pipe)
    file delete $path(test1)
    catch {unset fcopyTestDone}
    set f1 [open $path(pipe) w]
    puts $f1 "exit 1"
    close $f1
    set in [open "|[list [interpreter] $path(pipe)]" r+]
    set out [open $path(test1) w]
    fcopy $in $out -command [namespace code FcopyTestDone]
    variable fcopyTestDone
    if ![info exists fcopyTestDone] {
    if {![info exists fcopyTestDone]} {
	vwait [namespace which -variable fcopyTestDone]
    }
    catch {close $in}
    close $out
    set fcopyTestDone	;# 0 for plain end of file
} {0}
proc doFcopy {in out {bytes 0} {error {}}} {
    variable fcopyTestDone
    variable fcopyTestCount
    incr fcopyTestCount $bytes
    if {[string length $error]} {
	set fcopyTestDone 1
    } elseif {[eof $in]} {
	set fcopyTestDone 0
    } else {
        # Delay next fcopy to wait for size>0 input bytes
        after 100 [list fcopy $in $out -size 1000 \
	# Delay next fcopy to wait for size>0 input bytes
	after 100 [list fcopy $in $out -size 1000 \
		-command [namespace code [list doFcopy $in $out]]]
    }
}
test io-53.7 {CopyData: Flooding fcopy from pipe} {stdio fcopy} {
    variable fcopyTestDone
    file delete $path(pipe)
    catch {unset fcopyTestDone}
    set fcopyTestCount 0
    set f1 [open $path(pipe) w]
    puts $f1 {
	# Write  10 bytes / 10 msec
	proc Write {count} {
	    puts -nonewline "1234567890"
	    if {[incr count -1]} {
	        after 10 [list Write $count]
		after 10 [list Write $count]
	    } else {
	        set ::ready 1
		set ::ready 1
	    }
	}
	fconfigure stdout -buffering none
	Write 345 ;# 3450 bytes ~3.45 sec
	vwait ready
	exit 0
    }
    close $f1
    set in [open "|[list [interpreter] $path(pipe) &]" r+]
    set out [open $path(test1) w]
    doFcopy $in $out
    variable fcopyTestDone
    if ![info exists fcopyTestDone] {
    if {![info exists fcopyTestDone]} {
	vwait [namespace which -variable fcopyTestDone]
    }
    catch {close $in}
    close $out
    # -1=error 0=script error N=number of bytes
    expr ($fcopyTestDone == 0) ? $fcopyTestCount : -1
    expr {($fcopyTestDone == 0) ? $fcopyTestCount : -1}
} {3450}
test io-53.8 {CopyData: async callback and error handling, Bug 1932639} -setup {
    # copy progress callback. errors out intentionally
    proc ::cmd args {
	lappend ::RES "CMD $args"
	error !STOP
    }
7854
7855
7856
7857
7858
7859
7860
7861


7862
7863
7864

7865
7866
7867
7868

7869
7870
7871
7872
7873
7874
7875
7876


7877
7878
7879
7880
7881
7882
7883
8362
8363
8364
8365
8366
8367
8368

8369
8370
8371
8372

8373
8374
8375
8376

8377
8378
8379
8380
8381
8382
8383


8384
8385
8386
8387
8388
8389
8390
8391
8392







-
+
+


-
+



-
+






-
-
+
+







		fcopy $b $a -command [list geof $b]
		puts stderr 2COPY
	    }
	    puts stderr ...
	}
	puts stderr SRV
	set l {}
	set srv [socket -server new 9999]
	set srv [socket -server new -myaddr 127.0.0.1 0]
	set port [lindex [fconfigure $srv -sockname] 2]
	puts stderr WAITING
	fileevent stdin readable bye
	puts OK
	puts "OK $port"
	vwait forever
    }
    # wait for OK from server.
    gets $pipe
    lassign [gets $pipe] ok port
    # Now the two clients.
    proc ::done {sock} {
	if {[eof $sock]} { close $sock ; return }
	lappend ::forever [gets $sock]
	return
    }
    set a [socket 127.0.0.1 9999]
    set b [socket 127.0.0.1 9999]
    set a [socket 127.0.0.1 $port]
    set b [socket 127.0.0.1 $port]
    fconfigure $a -translation binary -buffering none
    fconfigure $b -translation binary -buffering none
    fileevent  $a readable [list ::done $a]
    fileevent  $b readable [list ::done $b]
} -constraints {stdio fcopy} -body {
    # Now pass data through the server in both directions.
    set ::forever {}
7922
7923
7924
7925
7926
7927
7928
7929

7930
7931
7932
7933
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946
7947


























7948
7949
7950
7951
7952
7953
7954
7955
7956
7957
7958
7959
7960
7961












7962
7963
7964


7965
7966
7967
7968
7969
7970
7971
7972
7973
7974
7975
7976
7977

7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994















7995
7996
7997
7998
7999
8000
8001
8002
8003
8004
8005
8006
8007
8008
8009
8010
8011
8012
8013
8014
8015
8016
8017
8018
8019
8020
8021
8022
8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038





























8039
8040
8041
8042
8043
8044
8045
8046
8047
8048
8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
8077
8078
8079
8080
8081
8082





























8083
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
8120























8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135

8136
8137
8138
8139
8140
8141
8142
8431
8432
8433
8434
8435
8436
8437

8438
8439
8440
8441
8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452
8453
8454
8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484












8485
8486
8487
8488
8489
8490
8491
8492
8493
8494
8495
8496
8497


8498
8499
8500
8501
8502
8503
8504
8505
8506
8507
8508
8509
8510
8511

8512
8513
8514















8515
8516
8517
8518
8519
8520
8521
8522
8523
8524
8525
8526
8527
8528
8529
8530
8531
8532
8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544





























8545
8546
8547
8548
8549
8550
8551
8552
8553
8554
8555
8556
8557
8558
8559
8560
8561
8562
8563
8564
8565
8566
8567
8568
8569
8570
8571
8572
8573
8574
8575
8576
8577
8578
8579
8580
8581
8582
8583
8584
8585
8586
8587
8588





























8589
8590
8591
8592
8593
8594
8595
8596
8597
8598
8599
8600
8601
8602
8603
8604
8605
8606
8607
8608
8609
8610
8611
8612
8613
8614
8615
8616
8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628
8629
8630
8631
8632























8633
8634
8635
8636
8637
8638
8639
8640
8641
8642
8643
8644
8645
8646
8647
8648
8649
8650
8651
8652
8653
8654
8655
8656
8657
8658
8659
8660
8661
8662
8663
8664
8665
8666
8667
8668
8669

8670
8671
8672
8673
8674
8675
8676
8677







-
+


















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+












-
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














-
+







    set done
} -cleanup {
    close $outChan
    close $inChan
    removeFile out
    removeFile in
} -result {40 bytes copied}
test io-53.12 {CopyData: foreground short reads, aka bug 3096275} {stdio unix fcopy} {
test io-53.12.0 {CopyData: foreground short reads, aka bug 3096275} {stdio unix fcopy} {
    file delete $path(pipe)
    set f1 [open $path(pipe) w]
    puts -nonewline $f1 {
	fconfigure stdin -translation binary -blocking 0
	fconfigure stdout -buffering none -translation binary
	fcopy stdin stdout
    }
    close $f1
    set f1 [open "|[list [interpreter] $path(pipe)]" r+]
    fconfigure $f1 -translation binary -buffering none
    puts -nonewline $f1 A
    after 2000 {set ::done timeout}
    fileevent $f1 readable {set ::done ok}
    vwait ::done
    set ch [read $f1 1]
    close $f1
    list $::done $ch
} {ok A}
test io-53.12.1 {
    Issue 9ca87e6286262a62.
    CopyData: foreground short reads via ReadChars().
    Related to report 3096275 for ReadBytes().

    Prior to the fix this test waited forever for read() to return.
} {stdio unix fcopy} {
    file delete $path(output)
    set f1 [open $path(output) w]
    puts -nonewline $f1 {
	chan configure stdin -encoding iso8859-1 -translation lf -buffering none
	fcopy stdin stdout
    }
    close $f1
    set f1 [open "|[list [info nameofexecutable] $path(output)]" r+]
    try {
	chan configure $f1 -encoding utf-8  -buffering none
	puts -nonewline $f1 A
	set ch [read $f1 1]
    } finally {
	if {$f1 in [chan names]} {
	    close $f1
	}
    }
    lindex $ch
} A
test io-53.13 {TclCopyChannel: read error reporting} -setup {
    proc driver {cmd args} {
        variable buffer
        variable index
        set chan [lindex $args 0]
        switch -- $cmd {
            initialize {
                return {initialize finalize watch read}
            }
            finalize {
                return
            }
            watch {}
            read {
	variable buffer
	variable index
	set chan [lindex $args 0]
	switch -- $cmd {
	    initialize {
		return {initialize finalize watch read}
	    }
	    finalize {
		return
	    }
	    watch {}
	    read {
		error FAIL
            }
        }
	    }
	}
    }
    set outFile [makeFile {} out]
} -body {
    set in [chan create read [namespace which driver]]
    chan configure $in -translation binary
    set out [open $outFile wb]
    chan copy $in $out
} -cleanup {
    catch {close $in}
    catch {close $out}
    removeFile out
    rename driver {}
} -result {error reading "*": *} -returnCodes error -match glob
} -result {error reading "rc*": *} -returnCodes error -match glob
test io-53.14 {TclCopyChannel: write error reporting} -setup {
    proc driver {cmd args} {
        variable buffer
        variable index
        set chan [lindex $args 0]
        switch -- $cmd {
            initialize {
                return {initialize finalize watch write}
            }
            finalize {
                return
            }
            watch {}
            write {
                error FAIL
            }
        }
	variable buffer
	variable index
	set chan [lindex $args 0]
	switch -- $cmd {
	    initialize {
		return {initialize finalize watch write}
	    }
	    finalize {
		return
	    }
	    watch {}
	    write {
		error FAIL
	    }
	}
    }
    set inFile [makeFile {aaa} in]
} -body {
    set in [open $inFile rb]
    set out [chan create write [namespace which driver]]
    chan configure $out -translation binary
    chan copy $in $out
} -cleanup {
    catch {close $in}
    catch {close $out}
    removeFile in
    rename driver {}
} -result {error writing "*": *} -returnCodes error -match glob
test io-53.15 {[ed29c4da21] DoRead: fblocked seen as error} -setup {
    proc driver {cmd args} {
        variable buffer
        variable index
        variable blocked
        set chan [lindex $args 0]
        switch -- $cmd {
            initialize {
                set index($chan) 0
                set buffer($chan) [encoding convertto utf-8 \
                        [string repeat a 100]]
                set blocked($chan) 1
                return {initialize finalize watch read}
            }
            finalize {
                unset index($chan) buffer($chan) blocked($chan)
                return
            }
            watch {}
            read {
                if {$blocked($chan)} {
                    set blocked($chan) [expr {!$blocked($chan)}]
                    return -code error EAGAIN
                }
                set n [lindex $args 1]
                set new [expr {$index($chan) + $n}]
                set result [string range $buffer($chan) $index($chan) $new-1]
                set index($chan) $new
                return $result
            }
        }
	variable buffer
	variable index
	variable blocked
	set chan [lindex $args 0]
	switch -- $cmd {
	    initialize {
		set index($chan) 0
		set buffer($chan) [encoding convertto utf-8 \
			[string repeat a 100]]
		set blocked($chan) 1
		return {initialize finalize watch read}
	    }
	    finalize {
		unset index($chan) buffer($chan) blocked($chan)
		return
	    }
	    watch {}
	    read {
		if {$blocked($chan)} {
		    set blocked($chan) [expr {!$blocked($chan)}]
		    return -code error EAGAIN
		}
		set n [lindex $args 1]
		set new [expr {$index($chan) + $n}]
		set result [string range $buffer($chan) $index($chan) $new-1]
		set index($chan) $new
		return $result
	    }
	}
    }
    set c [chan create read [namespace which driver]]
    chan configure $c -encoding utf-8
    set out [makeFile {} out]
    set outChan [open $out w]
    chan configure $outChan -encoding utf-8
} -body {
    chan copy $c $outChan
} -cleanup {
    close $outChan
    close $c
    removeFile out
} -result 100
test io-53.16 {[ed29c4da21] MBRead: fblocked seen as error} -setup {
    proc driver {cmd args} {
        variable buffer
        variable index
        variable blocked
        set chan [lindex $args 0]
        switch -- $cmd {
            initialize {
                set index($chan) 0
                set buffer($chan) [encoding convertto utf-8 \
                        [string repeat a 100]]
                set blocked($chan) 1
                return {initialize finalize watch read}
            }
            finalize {
                unset index($chan) buffer($chan) blocked($chan)
                return
            }
            watch {}
            read {
                if {$blocked($chan)} {
                    set blocked($chan) [expr {!$blocked($chan)}]
                    return -code error EAGAIN
                }
                set n [lindex $args 1]
                set new [expr {$index($chan) + $n}]
                set result [string range $buffer($chan) $index($chan) $new-1]
                set index($chan) $new
                return $result
            }
        }
	variable buffer
	variable index
	variable blocked
	set chan [lindex $args 0]
	switch -- $cmd {
	    initialize {
		set index($chan) 0
		set buffer($chan) [encoding convertto utf-8 \
			[string repeat a 100]]
		set blocked($chan) 1
		return {initialize finalize watch read}
	    }
	    finalize {
		unset index($chan) buffer($chan) blocked($chan)
		return
	    }
	    watch {}
	    read {
		if {$blocked($chan)} {
		    set blocked($chan) [expr {!$blocked($chan)}]
		    return -code error EAGAIN
		}
		set n [lindex $args 1]
		set new [expr {$index($chan) + $n}]
		set result [string range $buffer($chan) $index($chan) $new-1]
		set index($chan) $new
		return $result
	    }
	}
    }
    set c [chan create read [namespace which driver]]
    chan configure $c -encoding utf-8 -translation lf
    set out [makeFile {} out]
    set outChan [open $out w]
    chan configure $outChan -encoding utf-8 -translation lf
} -body {
    chan copy $c $outChan
} -cleanup {
    close $outChan
    close $c
    removeFile out
} -result 100
test io-53.17 {[7c187a3773] MBWrite: proper inQueueTail handling} -setup {
    proc driver {cmd args} {
        variable buffer
        variable index
        set chan [lindex $args 0]
        switch -- $cmd {
            initialize {
                set index($chan) 0
                set buffer($chan) [encoding convertto utf-8 \
                        line\n[string repeat a 100]line\n]
                return {initialize finalize watch read}
            }
            finalize {
                unset index($chan) buffer($chan)
                return
            }
            watch {}
            read {
                set n [lindex $args 1]
                set new [expr {$index($chan) + $n}]
                set result [string range $buffer($chan) $index($chan) $new-1]
                set index($chan) $new
                return $result
            }
        }
	variable buffer
	variable index
	set chan [lindex $args 0]
	switch -- $cmd {
	    initialize {
		set index($chan) 0
		set buffer($chan) [encoding convertto utf-8 \
			line\n[string repeat a 100]line\n]
		return {initialize finalize watch read}
	    }
	    finalize {
		unset index($chan) buffer($chan)
		return
	    }
	    watch {}
	    read {
		set n [lindex $args 1]
		set new [expr {$index($chan) + $n}]
		set result [string range $buffer($chan) $index($chan) $new-1]
		set index($chan) $new
		return $result
	    }
	}
    }
    set c [chan create read [namespace which driver]]
    chan configure $c -encoding utf-8 -translation lf -buffersize 107
    set out [makeFile {} out]
    set outChan [open $out w]
    chan configure $outChan -encoding utf-8 -translation lf
} -body {
    list [gets $c] [chan copy $c $outChan -size 100] [gets $c]
} -cleanup {
    close $outChan
    close $c
    removeFile out
} -result {line 100 line}

test io-54.1 {Recursive channel events} {socket fileevent knownMsvcBug} {
test io-54.1 {Recursive channel events} {socket fileevent notWinCI} {
    # This test checks to see if file events are delivered during recursive
    # event loops when there is buffered data on the channel.

    proc accept {s a p} {
	variable as
	fconfigure $s -translation lf
	puts $s "line 1\nline2\nline3"
8383
8384
8385
8386
8387
8388
8389
8390

8391
8392
8393
8394
8395
8396
8397
8918
8919
8920
8921
8922
8923
8924

8925
8926
8927
8928
8929
8930
8931
8932







-
+








test io-60.1 {writing illegal utf sequences} {fileevent testbytestring} {
    # This test will hang in older revisions of the core.

    set out [open $path(script) w]
    puts $out "catch {load $::tcltestlib Tcltest}"
    puts $out {
	puts [testbytestring \xe2]
	puts ABC[testbytestring \xE2]
	exit 1
    }
    proc readit {pipe} {
	variable x
	variable result
	if {[eof $pipe]} {
	    set x [catch {close $pipe} line]
8407
8408
8409
8410
8411
8412
8413
8414

8415
8416
8417
8418
8419
8420
8421
8942
8943
8944
8945
8946
8947
8948

8949
8950
8951
8952
8953
8954
8955
8956







-
+







    variable x ""
    set result ""
    vwait [namespace which -variable x]

    # cut of the remainder of the error stack, especially the filename
    set result [lreplace $result 3 3 [lindex [split [lindex $result 3] \n] 0]]
    list $x $result
} {1 {gets {} catch {error writing "stdout": invalid argument}}}
} {1 {gets ABC catch {error writing "stdout": invalid or incomplete multibyte or wide character}}}

test io-61.1 {Reset eof state after changing the eof char} -setup {
    set datafile [makeFile {} eofchar]
    set f [open $datafile w]
    fconfigure $f -translation binary
    puts -nonewline $f [string repeat "Ho hum\n" 11]
    puts $f =
8437
8438
8439
8440
8441
8442
8443
8444

8445
8446
8447
8448
8449
8450
8451
8972
8973
8974
8975
8976
8977
8978

8979
8980
8981
8982
8983
8984
8985
8986







-
+







    close $f
    set res
} -cleanup {
    removeFile eofchar
} -result {77 = 23431}


# Test the cutting and splicing of channels, this is incidentially the
# Test the cutting and splicing of channels, this is incidentally the
# attach/detach facility of package Thread, but __without any
# safeguards__. It can also be used to emulate transfer of channels
# between threads, and is used for that here.

test io-70.0 {Cutting & Splicing channels} {testchannel} {
    set f [makeFile {... dummy ...} cutsplice]
    set c [open $f r]
8681
8682
8683
8684
8685
8686
8687
8688

8689
8690
8691
8692
8693
8694
8695
9216
9217
9218
9219
9220
9221
9222

9223
9224
9225
9226
9227
9228
9229
9230







-
+








test io-73.1 {channel Tcl_Obj SetChannelFromAny} {} {
    # Test for Bug 1847044 - don't spoil type unless we have a valid channel
    catch {close [lreplace [list a] 0 end]}
} {1}

test io-73.2 {channel Tcl_Obj SetChannelFromAny, bug 2407783} -setup {
    # Invalidate intrep of 'channel' Tcl_Obj when transiting between interpreters.
    # Invalidate internalrep of 'channel' Tcl_Obj when transiting between interpreters.
    set f [open [info script] r]
} -body {
    interp create foo
    seek $f 0
    set code [catch {interp eval foo [list seek $f 0]} msg]
    # The string map converts the changing channel handle to a fixed string
    list $code [string map [list $f @@] $msg]
8741
8742
8743
8744
8745
8746
8747
8748

8749
8750
8751
8752
8753
8754
8755
8756

8757
8758
8759
8760
8761
8762
8763
8764
8765
8766
8767
8768
8769
8770
8771
8772
8773
8774
8775











































































































































































































































































































































































































































































8776



























































































































































8777
8778
8779

8780
8781
8782
8783
8784
8785
8786
9276
9277
9278
9279
9280
9281
9282

9283
9284
9285
9286
9287
9288
9289
9290

9291
9292
9293
9294
9295
9296
9297
9298
9299
9300
9301
9302
9303
9304
9305
9306
9307
9308
9309
9310
9311
9312
9313
9314
9315
9316
9317
9318
9319
9320
9321
9322
9323
9324
9325
9326
9327
9328
9329
9330
9331
9332
9333
9334
9335
9336
9337
9338
9339
9340
9341
9342
9343
9344
9345
9346
9347
9348
9349
9350
9351
9352
9353
9354
9355
9356
9357
9358
9359
9360
9361
9362
9363
9364
9365
9366
9367
9368
9369
9370
9371
9372
9373
9374
9375
9376
9377
9378
9379
9380
9381
9382
9383
9384
9385
9386
9387
9388
9389
9390
9391
9392
9393
9394
9395
9396
9397
9398
9399
9400
9401
9402
9403
9404
9405
9406
9407
9408
9409
9410
9411
9412
9413
9414
9415
9416
9417
9418
9419
9420
9421
9422
9423
9424
9425
9426
9427
9428
9429
9430
9431
9432
9433
9434
9435
9436
9437
9438
9439
9440
9441
9442
9443
9444
9445
9446
9447
9448
9449
9450
9451
9452
9453
9454
9455
9456
9457
9458
9459
9460
9461
9462
9463
9464
9465
9466
9467
9468
9469
9470
9471
9472
9473
9474
9475
9476
9477
9478
9479
9480
9481
9482
9483
9484
9485
9486
9487
9488
9489
9490
9491
9492
9493
9494
9495
9496
9497
9498
9499
9500
9501
9502
9503
9504
9505
9506
9507
9508
9509
9510
9511
9512
9513
9514
9515
9516
9517
9518
9519
9520
9521
9522
9523
9524
9525
9526
9527
9528
9529
9530
9531
9532
9533
9534
9535
9536
9537
9538
9539
9540
9541
9542
9543
9544
9545
9546
9547
9548
9549
9550
9551
9552
9553
9554
9555
9556
9557
9558
9559
9560
9561
9562
9563
9564
9565
9566
9567
9568
9569
9570
9571
9572
9573
9574
9575
9576
9577
9578
9579
9580
9581
9582
9583
9584
9585
9586
9587
9588
9589
9590
9591
9592
9593
9594
9595
9596
9597
9598
9599
9600
9601
9602
9603
9604
9605
9606
9607
9608
9609
9610
9611
9612
9613
9614
9615
9616
9617
9618
9619
9620
9621
9622
9623
9624
9625
9626
9627
9628
9629
9630
9631
9632
9633
9634
9635
9636
9637
9638
9639
9640
9641
9642
9643
9644
9645
9646
9647
9648
9649
9650
9651
9652
9653
9654
9655
9656
9657
9658
9659
9660
9661
9662
9663
9664
9665
9666
9667
9668
9669
9670
9671
9672
9673
9674
9675
9676
9677
9678
9679
9680
9681
9682
9683
9684
9685
9686
9687
9688
9689
9690
9691
9692
9693
9694
9695
9696
9697
9698
9699
9700
9701
9702
9703
9704
9705
9706
9707
9708
9709
9710
9711
9712
9713
9714
9715
9716
9717
9718
9719
9720
9721
9722
9723
9724
9725
9726
9727
9728
9729
9730
9731
9732
9733
9734
9735
9736
9737
9738
9739
9740
9741
9742
9743
9744
9745
9746
9747
9748
9749
9750
9751
9752
9753
9754
9755
9756
9757
9758
9759
9760
9761
9762
9763
9764
9765
9766
9767
9768
9769
9770
9771
9772
9773
9774
9775
9776
9777
9778
9779
9780
9781
9782
9783
9784
9785
9786
9787
9788
9789
9790
9791
9792
9793
9794
9795
9796
9797
9798
9799
9800
9801
9802
9803
9804
9805
9806
9807
9808
9809
9810
9811
9812
9813
9814
9815
9816
9817
9818
9819
9820
9821
9822
9823
9824
9825
9826
9827
9828
9829
9830
9831
9832
9833
9834
9835
9836
9837
9838
9839
9840
9841
9842
9843
9844
9845
9846
9847
9848
9849
9850
9851
9852
9853
9854
9855
9856
9857
9858
9859
9860
9861
9862
9863
9864
9865
9866
9867
9868
9869
9870
9871
9872
9873
9874
9875
9876
9877
9878
9879
9880
9881
9882
9883
9884
9885
9886
9887
9888
9889
9890
9891
9892
9893
9894
9895
9896
9897
9898
9899
9900
9901
9902
9903
9904
9905
9906
9907
9908
9909
9910
9911
9912
9913
9914
9915
9916
9917
9918
9919
9920
9921
9922
9923
9924
9925
9926
9927

9928
9929
9930
9931
9932
9933
9934
9935







-
+







-
+



















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+







    set rfd [open $fn r]
    set wfd [open $fn a]
    chan configure $wfd -buffering none -translation binary
    chan configure $rfd -buffersize 5 -encoding utf-8
    read $rfd
} -body {
    set result [eof $rfd]
    puts -nonewline $wfd "more\u00c2\u00a0data"
    puts -nonewline $wfd more\xC2\xA0data
    lappend result [eof $rfd]
    lappend result [read $rfd]
    lappend result [eof $rfd]
} -cleanup {
    close $wfd
    close $rfd
    removeFile io-73.5
} -result [list 1 1 more\u00a0data 1]
} -result [list 1 1 more\xA0data 1]

test io-74.1 {[104f2885bb] improper cache validity check} -setup {
    set fn [makeFile {} io-74.1]
    set rfd [open $fn r]
    testobj freeallvars
    interp create child
} -constraints testobj -body {
    teststringobj set 1 [string range $rfd 0 end]
    read [teststringobj get 1]
    testobj duplicate 1 2
    interp transfer {} $rfd child
    catch {read [teststringobj get 1]}
    read [teststringobj get 2]
} -cleanup {
    interp delete child
    testobj freeallvars
    removeFile io-74.1
} -returnCodes error -match glob -result {can not find channel named "*"}

test io-75.1 {multibyte encoding error read results in raw bytes (-profile tcl8)} -setup {
    set fn [makeFile {} io-75.1]
    set f [open $fn w+]
    fconfigure $f -translation binary
    # In UTF-8, a byte 0xCx starts a multibyte sequence and must be followed
    # by a byte > 0x7F. This is violated to get an invalid sequence.
    puts -nonewline $f A\xC0\x40
    flush $f
    seek $f 0
    fconfigure $f -encoding utf-8 -profile tcl8 -buffering none
} -body {
    set d [read $f]
    binary scan $d H* hd
    set hd
} -cleanup {
    close $f
    removeFile io-75.1
} -result 41c040

test io-75.2 {unrepresentable character write passes and is replaced by ? (-profile tcl8)} -setup {
    set fn [makeFile {} io-75.2]
    set f [open $fn w+]
    fconfigure $f -encoding iso8859-1 -profile tcl8
} -body {
    puts -nonewline $f A\u2022
    flush $f
    seek $f 0
    read $f
} -cleanup {
    close $f
    removeFile io-75.2
} -result A?

# Incomplete sequence test.
# This error may IMHO only be detected with the close.
# But the read already returns the incomplete sequence.
test io-75.3 {incomplete multibyte encoding read is ignored (-profile tcl8)} -setup {
    set fn [makeFile {} io-75.3]
    set f [open $fn w+]
    fconfigure $f -translation binary
    puts -nonewline $f "A\xC0"
    flush $f
    seek $f 0
    fconfigure $f -encoding utf-8 -buffering none -profile tcl8
} -body {
    set d [read $f]
    binary scan $d H* hd
    set hd
} -cleanup {
    close $f
    removeFile io-75.3
} -result 41c0

# As utf-8 has a special treatment in multi-byte decoding, also test another
# one.
test io-75.4 {shiftjis encoding error read results in raw bytes (-profile tcl8)} -setup {
    set fn [makeFile {} io-75.4]
    set f [open $fn w+]
    fconfigure $f -translation binary
    # In shiftjis, \x81 starts a two-byte sequence.
    # But 2nd byte \xFF is not allowed
    puts -nonewline $f A\x81\xFFA
    flush $f
    seek $f 0
    fconfigure $f -encoding shiftjis -buffering none -eofchar "" -translation lf -profile tcl8
} -body {
    set d [read $f]
    binary scan $d H* hd
    set hd
} -cleanup {
    close $f
    removeFile io-75.4
} -result 4181ff41

test io-75.5 {invalid utf-8 encoding read is ignored (-profile tcl8)} -setup {
    set fn [makeFile {} io-75.5]
    set f [open $fn w+]
    fconfigure $f -translation binary
    puts -nonewline $f A\x81
    flush $f
    seek $f 0
    fconfigure $f -encoding utf-8 -buffering none -eofchar "" -translation lf -profile tcl8
} -body {
    set d [read $f]
    binary scan $d H* hd
    set hd
} -cleanup {
    close $f
    removeFile io-75.5
} -result 4181

test io-75.6 {incomplete utf-8 encoding, blocking gets is not ignored (-profile strict)} -setup {
    set fn [makeFile {} io-75.6]
    set f [open $fn w+]
    fconfigure $f -translation binary
    # \x81 is an incomplete byte sequence in utf-8
    puts -nonewline $f A\x81
    flush $f
    seek $f 0
    fconfigure $f -encoding utf-8 -buffering none \
	    -translation lf -profile strict
} -body {
    gets $f
} -cleanup {
    close $f
    removeFile io-75.6
} -match glob -returnCodes 1 -result {error reading "file*":\
	invalid or incomplete multibyte or wide character}

test io-75.6.1 {invalid utf-8 encoding, blocking gets is not ignored (-profile strict)} -setup {
    set fn [makeFile {} io-75.6.1]
    set f [open $fn w+]
    fconfigure $f -translation binary
    # utf-8: \xC3 requires a 2nd byte > x80, but <x80 is delivered
    puts -nonewline $f A\xC3B
    flush $f
    seek $f 0
    fconfigure $f -encoding utf-8 -buffering none \
	    -translation lf -profile strict
} -body {
    gets $f
} -cleanup {
    close $f
    removeFile io-75.6.1
} -match glob -returnCodes 1 -result {error reading "file*":\
	invalid or incomplete multibyte or wide character}

test io-75.6.2 {invalid utf-8 encoding, blocking gets is not ignored (-profile strict), recover functionality} -setup {
    set fn [makeFile {} io-75.6.2]
    set f [open $fn w+]
    fconfigure $f -translation binary
    # utf-8: \xC3 requires a 2nd byte > x80, but <x80 is delivered
    puts -nonewline $f A\xC3B
    flush $f
    seek $f 0
    fconfigure $f -encoding utf-8 -buffering none \
	    -translation lf -profile strict
} -body {
    set l {}
    lappend l [catch {gets $f}]
    lappend l [tell $f]
    fconfigure $f -translation binary
    lappend l [expr {[gets $f] eq "A\xC3B"}]
} -cleanup {
    close $f
    removeFile io-75.6.2
} -match glob -returnCodes 0 -result {1 0 1}

# TCL ticket c4eb46a196: non blocking case had endless loop, so test it
test io-75.6.3 {invalid utf-8 encoding, non blocking gets is not ignored (-profile strict)} -setup {
    set fn [makeFile {} io-75.6.3]
    set f [open $fn w+]
    fconfigure $f -translation binary
    # utf-8: \xC3 requires a 2nd byte > x80, but <x80 is delivered
    puts -nonewline $f A\xC3B
    flush $f
    seek $f 0
    fconfigure $f -encoding utf-8 -buffering none \
	    -translation lf -profile strict -blocking 0
} -body {
    gets $f
} -cleanup {
    close $f
    removeFile io-75.6.3
} -match glob -returnCodes 1 -result {error reading "file*":\
	invalid or incomplete multibyte or wide character}

test io-75.6.4 {incomplete utf-8 encoding, non blocking gets is not ignored (-profile strict)} -setup {
    set fn [makeFile {} io-75.6.4]
    set f [open $fn w+]
    fconfigure $f -translation binary
    # \x81 is an incomplete byte sequence in utf-8
    puts -nonewline $f A\x81
    flush $f
    seek $f 0
    fconfigure $f -encoding utf-8 -buffering none \
	    -translation lf -profile strict -blocking 0
} -body {
    gets $f
	# only the 2nd gets returns the error
	gets $f
} -cleanup {
    close $f
    removeFile io-75.6.4
} -match glob -returnCodes 1 -result {error reading "file*":\
	invalid or incomplete multibyte or wide character}

test io-75.7 {
    invalid utf-8 encoding read is not ignored (-profile strict)
} -setup {
    set fn [makeFile {} io-75.7]
    set f [open $fn w+]
    fconfigure $f -translation binary
    # \x81 is invalid in utf-8
    puts -nonewline $f A\x81
    flush $f
    seek $f 0
    fconfigure $f -encoding utf-8 -buffering none -translation lf \
	    -profile strict
} -body {
    list [catch {read $f} msg data] $msg [dict get $data -data]
} -cleanup {
    close $f
    removeFile io-75.7
    unset msg data f fn
} -match glob -result {1 {error reading "file*":\
    invalid or incomplete multibyte or wide character} A}

test io-75.8 {invalid utf-8 encoding eof first handling (-profile strict)} -setup {
    set fn [makeFile {} io-75.8]
    set f [open $fn w+]
    fconfigure $f -translation binary
    # \x81 is invalid in utf-8, but since \x1A comes first, -eofchar takes
    # precedence.
    puts -nonewline $f A\x1A\x81
    flush $f
    seek $f 0
    fconfigure $f -encoding utf-8 -buffering none -eofchar \x1A \
	-translation lf -profile strict
} -body {
    set d [read $f]
    binary scan $d H* hd
    lappend hd [eof $f]
    lappend hd [read $f]
    set hd
} -cleanup {
    close $f
    removeFile io-75.8
    unset f d hd
} -result {41 1 {}}

test io-75.8.eoflater {invalid utf-8 encoding eof after handling (-profile strict)} -setup {
    set fn [makeFile {} io-75.8]
    set f [open $fn w+]
    # This also configures the channel encoding profile as strict.
    fconfigure $f -translation binary
    # \x81 is invalid in utf-8. -eofchar is not detected, because it comes later.
    puts -nonewline $f A\x81\x81\x1A
    flush $f
    seek $f 0
    fconfigure $f -encoding utf-8 -buffering none -eofchar \x1A \
	-translation lf -profile strict
} -body {
    set res [list [catch {read $f} msg data] [eof $f] [dict get $data -data]]
    chan configure $f -encoding iso8859-1
    lappend res [read $f 1]
    chan configure $f -encoding utf-8
    lappend res [catch {read $f 1} msg data] $msg [dict get $data -data]
} -cleanup {
    close $f
    removeFile io-75.8
    unset res msg data fn f
} -match glob -result "1 0 A \x81 1 {error reading \"*\":\
    invalid or incomplete multibyte or wide character} {}"


test io-strict-multibyte-eof {
    incomplete utf-8 sequence immediately prior to eof character

    See issue 25cdcb7e8fb381fb
} -setup {
    set chan [file tempfile];
    fconfigure $chan -translation binary
    puts -nonewline $chan \x81\x1A
    flush $chan
    seek $chan 0
    chan configure $chan -encoding utf-8 -profile strict
} -body {
    list [catch {read $chan 1} msg data] $msg [dict get $data -data]
} -cleanup {
    close $chan
    unset msg chan data
} -match glob -result {1 {error reading "*":\
    invalid or incomplete multibyte or wide character} {}}

test io-75.9 {unrepresentable character write throws error in strict profile} -setup {
    set fn [makeFile {} io-75.9]
    set f [open $fn w+]
    fconfigure $f -encoding iso8859-1 -profile strict
} -body {
    catch {puts -nonewline $f "A\u2022"} msg
    flush $f
    seek $f 0
    list [read $f] $msg
} -cleanup {
    close $f
    removeFile io-75.9
    unset f
} -match glob -result [list {A} {error writing "*":\
    invalid or incomplete multibyte or wide character}]

test io-75.10 {
    incomplete multibyte encoding read is not ignored because "binary" sets
    profile to strict
} -setup {
    set res {}
    set fn [makeFile {} io-75.10]
    set f [open $fn w+]
    fconfigure $f -translation binary
    puts -nonewline $f A\xC0
    flush $f
    seek $f 0
    fconfigure $f -encoding utf-8 -buffering none
} -body {
    catch {read $f} errmsg
    lappend res $errmsg
    seek $f 0
    chan configure $f -profile tcl8
    set d [read $f]
    binary scan $d H* hd
    lappend res $hd
    return $res
} -cleanup {
    close $f
    removeFile io-75.10
    unset result
} -match glob -result {{error reading "file*":\
    invalid or incomplete multibyte or wide character} 41c0}

# The current result returns the orphan byte as byte.
# This may be expected due to special utf-8 handling.

# As utf-8 has a special treatment in multi-byte decoding, also test another
# one.
test io-75.11 {shiftjis encoding error read results in error (strict profile)} -setup {
    set fn [makeFile {} io-75.11]
    set f [open $fn w+]
    fconfigure $f -translation binary
    # In shiftjis, \x81 starts a two-byte sequence.
    # But 2nd byte \xFF is not allowed
    puts -nonewline $f A\x81\xFFA
    flush $f
    seek $f 0
    fconfigure $f -encoding shiftjis -blocking 0 -translation lf \
	-profile strict
} -body {
    set d [read $f]
    binary scan $d H* hd
    lappend hd [catch {set d [read $f]} msg data] $msg [dict exists $data -data]
} -cleanup {
    close $f
    removeFile io-75.11
    unset d hd msg data f
} -match glob -result {41 1 {error reading "file*":\
    invalid or incomplete multibyte or wide character} 0}

test io-75.12 {
    invalid utf-8 encoding read is not ignored because setting the encoding to
    "binary" also set the profile to strict
} -setup {
    set res {}
    set fn [makeFile {} io-75.12]
    set f [open $fn w+]
    fconfigure $f -translation binary
    puts -nonewline $f A\x81
    flush $f
    seek $f 0
    fconfigure $f -encoding utf-8 -buffering none -translation lf
} -body {
    catch {read $f} errmsg
    lappend res $errmsg
    chan configure $f -profile tcl8
    seek $f 0
    set d [read $f]
    binary scan $d H* hd
    lappend res $hd
    return $res
} -cleanup {
    close $f
    removeFile io-75.12
    unset res
} -match glob -result {{error reading "file*":\
    invalid or incomplete multibyte or wide character} 4181}
test io-75.13 {
    In nonblocking mode when there is an encoding error the data that has been
    successfully read so far is returned first and then the error is returned
    on the next call to [read].
} -setup {
    set fn [makeFile {} io-75.13]
    set f [open $fn w+]
    fconfigure $f -translation binary
    # \x81 is invalid in utf-8
    puts -nonewline $f A\x81
    flush $f
    seek $f 0
    fconfigure $f -encoding utf-8 -blocking 0 -translation lf \
	-profile strict
} -body {
    set d [read $f]
    binary scan $d H* hd
    lappend hd [catch {read $f} msg data] $msg [dict exists $data -data]
} -cleanup {
    close $f
    removeFile io-75.13
    unset d hd msg data f fn
} -match glob -result {41 1 {error reading "file*":\
    invalid or incomplete multibyte or wide character} 0}

test io-75.14 {
	[gets] succesfully returns lines prior to error

	invalid utf-8 encoding [gets] continues in non-strict mode after error
} -setup {
    set chan [file tempfile]
    fconfigure $chan -translation binary
    # \xC0\n is an invalid utf-8 sequence
    puts -nonewline $chan a\nb\nc\xC0\nd\n
    flush $chan
    seek $chan 0
    fconfigure $chan -encoding utf-8 -buffering none \
	-translation auto -profile strict
} -body {
    set res [gets $chan]
    lappend res [gets $chan]
    lappend res [catch {gets $chan} msg data] $msg [dict exists $data -data]
    chan configure $chan -profile tcl8
    lappend res [gets $chan]
    lappend res [gets $chan]
    return $res
} -cleanup {
    close $chan
    unset chan res msg data
} -match glob -result {a b 1 {error reading "*":\
    invalid or incomplete multibyte or wide character} 0 cÀ d}

test io-75.15 {
    invalid utf-8 encoding strict
    gets does not hang
    gets succeeds for the first two lines
} -setup {
    set res {}
    set chan [file tempfile]
    fconfigure $chan -translation binary
    # \xC0\x40 is an invalid utf-8 sequence
    puts $chan hello\nAB\nCD\xC0\x40EF\nGHI
	seek $chan 0
} -body {
    #Now try to read it with [gets]
    fconfigure $chan -encoding utf-8 -profile strict
    lappend res [gets $chan]
    lappend res [gets $chan]
    lappend res [catch {gets $chan} msg data] $msg [dict exists $data -data]
    lappend res [catch {gets $chan} msg data] $msg [dict exists $data -data]
	chan configure $chan -translation binary
	set data [read $chan 4]
	foreach char [split $data {}] {
		scan $char %c ord
		lappend res [format %x $ord]
	}
    fconfigure $chan -encoding utf-8 -profile strict -translation auto
	lappend res [gets $chan]
	lappend res [gets $chan]
    return $res
} -cleanup {
    close $chan
    unset chan res msg data
} -match glob -result {hello AB 1 {error reading "*": invalid or incomplete multibyte or wide character}\
    0 1 {error reading "*": invalid or incomplete multibyte or wide character} 0 43 44 c0 40 EF GHI}

# ### ### ### ######### ######### #########



test io-76.0 {channel modes} -setup {
    set datafile [makeFile {some characters} dummy]
    set f [open $datafile r]
} -constraints testchannel -body {
    testchannel mode $f
} -cleanup {
    close $f
    removeFile dummy
} -result {read {}}

test io-76.1 {channel modes} -setup {
    set datafile [makeFile {some characters} dummy]
    set f [open $datafile w]
} -constraints testchannel -body {
    testchannel mode $f
} -cleanup {
    close $f
    removeFile dummy
} -result {{} write}

test io-76.2 {channel modes} -setup {
    set datafile [makeFile {some characters} dummy]
    set f [open $datafile r+]
} -constraints testchannel -body {
    testchannel mode $f
} -cleanup {
    close $f
    removeFile dummy
} -result {read write}

test io-76.3 {channel mode dropping} -setup {
    set datafile [makeFile {some characters} dummy]
    set f [open $datafile r]
} -constraints testchannel -body {
    testchannel mremove-wr $f
    list [testchannel mode $f] [testchannel maxmode $f]
} -cleanup {
    close $f
    removeFile dummy
} -result {{read {}} {read {}}}

test io-76.4 {channel mode dropping} -setup {
    set datafile [makeFile {some characters} dummy]
    set f [open $datafile r]
} -constraints testchannel -body {
    testchannel mremove-rd $f
} -returnCodes error -cleanup {
    close $f
    removeFile dummy
} -match glob -result {Tcl_RemoveChannelMode error:\
    Bad mode, would make channel inacessible. Channel: "*"}

test io-76.5 {channel mode dropping} -setup {
    set datafile [makeFile {some characters} dummy]
    set f [open $datafile w]
} -constraints testchannel -body {
    testchannel mremove-rd $f
    list [testchannel mode $f] [testchannel maxmode $f]
} -cleanup {
    close $f
    removeFile dummy
} -result {{{} write} {{} write}}

test io-76.6 {channel mode dropping} -setup {
    set datafile [makeFile {some characters} dummy]
    set f [open $datafile w]
} -constraints testchannel -body {
    testchannel mremove-wr $f
} -returnCodes error -cleanup {
    close $f
    removeFile dummy
} -match glob -result {Tcl_RemoveChannelMode error:\
    Bad mode, would make channel inacessible. Channel: "*"}

test io-76.7 {channel mode dropping} -setup {
    set datafile [makeFile {some characters} dummy]
    set f [open $datafile r+]
} -constraints testchannel -body {
    testchannel mremove-rd $f
    list [testchannel mode $f] [testchannel maxmode $f]
} -cleanup {
    close $f
    removeFile dummy
} -result {{{} write} {read write}}

test io-76.8 {channel mode dropping} -setup {
    set datafile [makeFile {some characters} dummy]
    set f [open $datafile r+]
} -constraints testchannel -body {
    testchannel mremove-wr $f
    list [testchannel mode $f] [testchannel maxmode $f]
} -cleanup {
    close $f
    removeFile dummy
} -result {{read {}} {read write}}

test io-76.9 {channel mode dropping} -setup {
    set datafile [makeFile {some characters} dummy]
    set f [open $datafile r+]
} -constraints testchannel -body {
    testchannel mremove-wr $f
    testchannel mremove-rd $f
} -returnCodes error -cleanup {
    close $f
    removeFile dummy
} -match glob -result {Tcl_RemoveChannelMode error:\
    Bad mode, would make channel inacessible. Channel: "*"}

test io-76.10 {channel mode dropping} -setup {
    set datafile [makeFile {some characters} dummy]
    set f [open $datafile r+]
} -constraints testchannel -body {
    testchannel mremove-rd $f
    testchannel mremove-wr $f
} -returnCodes error -cleanup {
    close $f
    removeFile dummy
} -match glob -result {Tcl_RemoveChannelMode error:\
    Bad mode, would make channel inacessible. Channel: "*"}

# Encoding errors on pipeline
# Ensures fix for exec bug [0f1ddc0df7] does not affect open
# It should still fail unless -profile is explicitly set to replace
test io-77.1 {open pipe encoding mismatch} -setup {
    set scriptFile [makeFile {
	fconfigure stdout -translation binary
	puts -nonewline a\xe9b
	flush stdout
    } script]
} -cleanup {
    close $fd
    removeFile $scriptFile
} -body {
    set fd [open |[list [info nameofexecutable] $scriptFile r+]]
    fconfigure $fd -encoding utf-8
    list [catch {read $fd} result opts] [string match {error reading "*": invalid or incomplete multibyte or wide character} $result] [dict get $opts -errorcode]
} -result [list 1 1 {POSIX EILSEQ {invalid or incomplete multibyte or wide character}}]
test io-77.2 {open pipe encoding mismatch - use replace profile} -setup {
    set scriptFile [makeFile {
	fconfigure stdout -translation binary
	puts -nonewline a\xe9b
	flush stdout
    } script]
} -cleanup {
    close $fd
    removeFile $scriptFile
} -body {
    set fd [open |[list [info nameofexecutable] $scriptFile r+]]
    fconfigure $fd -encoding utf-8 -profile replace
    read $fd
} -result a\uFFFDb


# cleanup
foreach file [list fooBar longfile script script2 output test1 pipe my_script \
foreach file [list fooBar longfile script2 output test1 pipe my_script \
	test2 test3 cat stdout kyrillic.txt utf8-fcopy.txt utf8-rp.txt] {
    removeFile $file
}
cleanupTests
}
namespace delete ::tcl::test::io
return

Changes to tests/ioCmd.test.

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
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
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
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


-
+
+





-
-
-
+
+
+








+


-
+
-
-








-
+


-
+


-
+











-
+






-
+






-
+







-
+


-
+









-
+


-
+




















-
+


-
+





-
+



















-
+







# -*- tcl -*-
# Commands covered: open, close, gets, read, puts, seek, tell, eof, flush,
#		    fblocked, fconfigure, open, channel, fcopy
#		    fblocked, fconfigure, open, channel, fcopy,
#		    readFile, writeFile, foreachLine
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1994 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1994 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
}
source [file join [file dirname [info script]] tcltests.tcl]

::tcltest::loadTestedCommands
catch [list package require -exact Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

package require tcltests

# Custom constraints used in this file
testConstraint testchannel	[llength [info commands testchannel]]

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

test iocmd-1.1 {puts command} {
   list [catch {puts} msg] $msg
} {1 {wrong # args: should be "puts ?-nonewline? ?channelId? string"}}
} {1 {wrong # args: should be "puts ?-nonewline? ?channel? string"}}
test iocmd-1.2 {puts command} {
   list [catch {puts a b c d e f g} msg] $msg
} {1 {wrong # args: should be "puts ?-nonewline? ?channelId? string"}}
} {1 {wrong # args: should be "puts ?-nonewline? ?channel? string"}}
test iocmd-1.3 {puts command} {
   list [catch {puts froboz -nonewline kablooie} msg] $msg
} {1 {wrong # args: should be "puts ?-nonewline? ?channelId? string"}}
} {1 {wrong # args: should be "puts ?-nonewline? ?channel? string"}}
test iocmd-1.4 {puts command} {
   list [catch {puts froboz hello} msg] $msg
} {1 {can not find channel named "froboz"}}
test iocmd-1.5 {puts command} {
   list [catch {puts stdin hello} msg] $msg
} {1 {channel "stdin" wasn't opened for writing}}

set path(test1) [makeFile {} test1]

test iocmd-1.6 {puts command} {
    set f [open $path(test1) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    puts -nonewline $f foobar
    close $f
    file size $path(test1)
} 6
test iocmd-1.7 {puts command} {
    set f [open $path(test1) w]
    fconfigure $f -translation lf -eofchar {}
    fconfigure $f -translation lf
    puts $f foobar
    close $f
    file size $path(test1)
} 7
test iocmd-1.8 {puts command} {
    set f [open $path(test1) w]
    fconfigure $f -translation lf -eofchar {} -encoding iso8859-1
    fconfigure $f -translation binary
    puts -nonewline $f [binary format a4a5 foo bar]
    close $f
    file size $path(test1)
} 9

test iocmd-2.1 {flush command} {
   list [catch {flush} msg] $msg
} {1 {wrong # args: should be "flush channelId"}}
} {1 {wrong # args: should be "flush channel"}}
test iocmd-2.2 {flush command} {
   list [catch {flush a b c d e} msg] $msg
} {1 {wrong # args: should be "flush channelId"}}
} {1 {wrong # args: should be "flush channel"}}
test iocmd-2.3 {flush command} {
   list [catch {flush foo} msg] $msg
} {1 {can not find channel named "foo"}}
test iocmd-2.4 {flush command} {
   list [catch {flush stdin} msg] $msg
} {1 {channel "stdin" wasn't opened for writing}}

test iocmd-3.1 {gets command} {
   list [catch {gets} msg] $msg
} {1 {wrong # args: should be "gets channelId ?varName?"}}
} {1 {wrong # args: should be "gets channel ?varName?"}}
test iocmd-3.2 {gets command} {
   list [catch {gets a b c d e f g} msg] $msg
} {1 {wrong # args: should be "gets channelId ?varName?"}}
} {1 {wrong # args: should be "gets channel ?varName?"}}
test iocmd-3.3 {gets command} {
   list [catch {gets aaa} msg] $msg
} {1 {can not find channel named "aaa"}}
test iocmd-3.4 {gets command} {
   list [catch {gets stdout} msg] $msg
} {1 {channel "stdout" wasn't opened for reading}}
test iocmd-3.5 {gets command} {
    set f [open $path(test1) w]
    puts $f [binary format a4a5 foo bar]
    close $f
    set f [open $path(test1) r]
    set result [gets $f]
    close $f
    set x foo\x00
    set x "${x}bar\x00\x00"
    string compare $x $result
} 0

test iocmd-4.1 {read command} {
   list [catch {read} msg] $msg
} {1 {wrong # args: should be "read channelId ?numChars?" or "read ?-nonewline? channelId"}}
} {1 {wrong # args: should be "read channel ?numChars?" or "read ?-nonewline? channel"}}
test iocmd-4.2 {read command} {
   list [catch {read a b c d e f g h} msg] $msg
} {1 {wrong # args: should be "read channelId ?numChars?" or "read ?-nonewline? channelId"}}
} {1 {wrong # args: should be "read channel ?numChars?" or "read ?-nonewline? channel"}}
test iocmd-4.3 {read command} {
   list [catch {read aaa} msg] $msg
} {1 {can not find channel named "aaa"}}
test iocmd-4.4 {read command} {
   list [catch {read -nonewline} msg] $msg
} {1 {wrong # args: should be "read channelId ?numChars?" or "read ?-nonewline? channelId"}}
} {1 {wrong # args: should be "read channel ?numChars?" or "read ?-nonewline? channel"}}
test iocmd-4.5 {read command} {
   list [catch {read -nonew file4} msg] $msg $::errorCode
} {1 {can not find channel named "-nonew"} {TCL LOOKUP CHANNEL -nonew}}
test iocmd-4.6 {read command} {
   list [catch {read stdout} msg] $msg
} {1 {channel "stdout" wasn't opened for reading}}
test iocmd-4.7 {read command} {
   list [catch {read -nonewline stdout} msg] $msg
} {1 {channel "stdout" wasn't opened for reading}}
test iocmd-4.8 {read command with incorrect combination of arguments} {
    file delete $path(test1)
    set f [open $path(test1) w]
    puts $f "Two lines: this one"
    puts $f "and this one"
    close $f
    set f [open $path(test1)]
    set x [list [catch {read -nonewline $f 20 z} msg] $msg $::errorCode]
    close $f
    set x
} {1 {wrong # args: should be "read channelId ?numChars?" or "read ?-nonewline? channelId"} {TCL WRONGARGS}}
} {1 {wrong # args: should be "read channel ?numChars?" or "read ?-nonewline? channel"} {TCL WRONGARGS}}
test iocmd-4.9 {read command} {
    list [catch {read stdin foo} msg] $msg $::errorCode
} {1 {expected non-negative integer but got "foo"} {TCL VALUE NUMBER}}
test iocmd-4.10 {read command} {
    list [catch {read file107} msg] $msg $::errorCode
} {1 {can not find channel named "file107"} {TCL LOOKUP CHANNEL file107}}
set path(test3) [makeFile {} test3]
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
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







-
+


-
+









-
+


-
+






-
+


-
+




















-
+







-
+


-
+










-
+










-
+



-
+






-
+




-
+




-
+
-



-
+







    read $f 12z
} -cleanup {
    close $f
} -result {expected non-negative integer but got "12z"} -errorCode {TCL VALUE NUMBER}

test iocmd-5.1 {seek command} -returnCodes error -body {
    seek
} -result {wrong # args: should be "seek channelId offset ?origin?"}
} -result {wrong # args: should be "seek channel offset ?origin?"}
test iocmd-5.2 {seek command} -returnCodes error -body {
    seek a b c d e f g
} -result {wrong # args: should be "seek channelId offset ?origin?"}
} -result {wrong # args: should be "seek channel offset ?origin?"}
test iocmd-5.3 {seek command} -returnCodes error -body {
    seek stdin gugu
} -result {expected integer but got "gugu"}
test iocmd-5.4 {seek command} -returnCodes error -body {
    seek stdin 100 gugu
} -result {bad origin "gugu": must be start, current, or end}

test iocmd-6.1 {tell command} {
    list [catch {tell} msg] $msg
} {1 {wrong # args: should be "tell channelId"}}
} {1 {wrong # args: should be "tell channel"}}
test iocmd-6.2 {tell command} {
    list [catch {tell a b c d e} msg] $msg
} {1 {wrong # args: should be "tell channelId"}}
} {1 {wrong # args: should be "tell channel"}}
test iocmd-6.3 {tell command} {
    list [catch {tell aaa} msg] $msg
} {1 {can not find channel named "aaa"}}

test iocmd-7.1 {close command} {
    list [catch {close} msg] $msg
} {1 {wrong # args: should be "close channelId ?direction?"}}
} {1 {wrong # args: should be "close channel ?direction?"}}
test iocmd-7.2 {close command} {
    list [catch {close a b c d e} msg] $msg
} {1 {wrong # args: should be "close channelId ?direction?"}}
} {1 {wrong # args: should be "close channel ?direction?"}}
test iocmd-7.3 {close command} {
    list [catch {close aaa} msg] $msg
} {1 {can not find channel named "aaa"}}
test iocmd-7.4 {close command} -setup {
    set chan [open [info script] r]
} -body {
    chan close $chan bar
} -cleanup {
    close $chan
} -returnCodes error -result "bad direction \"bar\": must be read or write"
test iocmd-7.5 {close command} -setup {
    set chan [open [info script] r]
} -body {
    chan close $chan write
} -cleanup {
    close $chan
} -returnCodes error -result "Half-close of write-side not possible, side not opened or already closed"

proc expectedOpts {got extra} {
    set basicOpts {
	-blocking -buffering -buffersize -encoding -eofchar -translation
	-blocking -buffering -buffersize -encoding -eofchar -profile -translation
    }
    set opts [list {*}$basicOpts {*}$extra]
    lset opts end [string cat "or " [lindex $opts end]]
    return [format {bad option "%s": should be one of %s} $got [join $opts ", "]]
}
test iocmd-8.1 {fconfigure command} -returnCodes error -body {
    fconfigure
} -result {wrong # args: should be "fconfigure channelId ?-option value ...?"}
} -result {wrong # args: should be "fconfigure channel ?-option value ...?"}
test iocmd-8.2 {fconfigure command} -returnCodes error -body {
    fconfigure a b c d e f
} -result {wrong # args: should be "fconfigure channelId ?-option value ...?"}
} -result {wrong # args: should be "fconfigure channel ?-option value ...?"}
test iocmd-8.3 {fconfigure command} -returnCodes error -body {
    fconfigure a b
} -result {can not find channel named "a"}
test iocmd-8.4 {fconfigure command} -setup {
    file delete $path(test1)
    set f1 [open $path(test1) w]
} -body {
    fconfigure $f1 froboz
} -returnCodes error -cleanup {
    close $f1
} -result [expectedOpts "froboz" {}]
} -result [expectedOpts "froboz" -stat]
test iocmd-8.5 {fconfigure command} -returnCodes error -body {
    fconfigure stdin -buffering froboz
} -result {bad value for -buffering: must be one of full, line, or none}
test iocmd-8.6 {fconfigure command} -returnCodes error -body {
    fconfigure stdin -translation froboz
} -result {bad value for -translation: must be one of auto, binary, cr, lf, crlf, or platform}
test iocmd-8.7 {fconfigure command} -setup {
    file delete $path(test1)
} -body {
    set f1 [open $path(test1) w]
    fconfigure $f1 -translation lf -eofchar {} -encoding utf-16
    fconfigure $f1 -translation lf -encoding utf-16
    fconfigure $f1
} -cleanup {
    catch {close $f1}
} -result {-blocking 1 -buffering full -buffersize 4096 -encoding utf-16 -eofchar {} -translation lf}
} -result {-blocking 1 -buffering full -buffersize 4096 -encoding utf-16 -eofchar {} -profile strict -translation lf}
test iocmd-8.8 {fconfigure command} -setup {
    file delete $path(test1)
    set x {}
} -body {
    set f1 [open $path(test1) w]
    fconfigure $f1 -translation lf -buffering line -buffersize 3030 \
		-eofchar {} -encoding utf-16
		-encoding utf-16 -profile tcl8
    lappend x [fconfigure $f1 -buffering]
    lappend x [fconfigure $f1]
} -cleanup {
    catch {close $f1}
} -result {line {-blocking 1 -buffering line -buffersize 3030 -encoding utf-16 -eofchar {} -translation lf}}
} -result {line {-blocking 1 -buffering line -buffersize 3030 -encoding utf-16 -eofchar {} -profile tcl8 -translation lf}}
test iocmd-8.9 {fconfigure command} -setup {
    file delete $path(test1)
} -body {
    set f1 [open $path(test1) w]
    fconfigure $f1 -translation binary -buffering none -buffersize 4040 \
    fconfigure $f1 -translation binary -buffering none -buffersize 4040
		-eofchar {} -encoding binary
    fconfigure $f1
} -cleanup {
    catch {close $f1}
} -result {-blocking 1 -buffering none -buffersize 4040 -encoding binary -eofchar {} -translation lf}
} -result {-blocking 1 -buffering none -buffersize 4040 -encoding iso8859-1 -eofchar {} -profile strict -translation lf}
test iocmd-8.10 {fconfigure command} -returnCodes error -body {
    fconfigure a b
} -result {can not find channel named "a"}
set path(fconfigure.dummy) [makeFile {} fconfigure.dummy]
test iocmd-8.11 {fconfigure command} -body {
    set chan [open $path(fconfigure.dummy) r]
    fconfigure $chan -froboz blarfo
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
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







-
+











-
+







} -returnCodes error -cleanup {
    catch {close $chan}
} -result [expectedOpts "-buffer" {}]
removeFile fconfigure.dummy
test iocmd-8.14 {fconfigure command} {
    fconfigure stdin -buffers
} 4096
test iocmd-8.15.1 {fconfigure command / tcp channel} -constraints {socket unixOrWin} -setup {
test iocmd-8.15 {fconfigure command / tcp channel} -constraints {socket unixOrWin} -setup {
    set srv [socket -server iocmdSRV -myaddr 127.0.0.1 0]
    set port [lindex [fconfigure $srv -sockname] 2]
    proc iocmdSRV {sock ip port} {close $sock}
    set cli [socket 127.0.0.1 $port]
} -body {
    fconfigure $cli -blah
} -cleanup {
    close $cli
    close $srv
    unset cli srv port
    rename iocmdSRV {}
} -returnCodes error -result [expectedOpts "-blah" {-connecting -peername -sockname}]
} -returnCodes error -result [expectedOpts "-blah" {-connecting -keepalive -nodelay -peername -sockname}]
test iocmd-8.16 {fconfigure command / tcp channel} -constraints socket -setup {
    set srv [socket -server iocmdSRV -myaddr 127.0.0.1 0]
    set port [lindex [fconfigure $srv -sockname] 2]
    proc iocmdSRV {sock ip port} {close $sock}
    set cli [socket 127.0.0.1 $port]
} -body {
    expr {[lindex [fconfigure $cli -peername] 2] == $port}
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
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







+
+
+
+


-
+


-
+









-
+


-
+







    set console stdin
} -body {
    fconfigure $console -blah blih
} -returnCodes error -result [expectedOpts "-blah" {-inputmode}]
# TODO: Test parsing of serial channel options (nonPortable, since requires an
# open channel to work with).

test iocmd-8.23 {fconfigure -profile badprofile} -body {
    fconfigure stdin -profile froboz
} -returnCodes error -result {bad profile name "froboz": must be replace, strict, or tcl8}

test iocmd-9.1 {eof command} {
    list [catch {eof} msg] $msg $::errorCode
} {1 {wrong # args: should be "eof channelId"} {TCL WRONGARGS}}
} {1 {wrong # args: should be "eof channel"} {TCL WRONGARGS}}
test iocmd-9.2 {eof command} {
    list [catch {eof a b} msg] $msg $::errorCode
} {1 {wrong # args: should be "eof channelId"} {TCL WRONGARGS}}
} {1 {wrong # args: should be "eof channel"} {TCL WRONGARGS}}
test iocmd-9.3 {eof command} {
    catch {close file100}
    list [catch {eof file100} msg] $msg $::errorCode
} {1 {can not find channel named "file100"} {TCL LOOKUP CHANNEL file100}}

# The tests for Tcl_ExecObjCmd are in exec.test

test iocmd-10.1 {fblocked command} {
    list [catch {fblocked} msg] $msg
} {1 {wrong # args: should be "fblocked channelId"}}
} {1 {wrong # args: should be "fblocked channel"}}
test iocmd-10.2 {fblocked command} {
    list [catch {fblocked a b c d e f g} msg] $msg
} {1 {wrong # args: should be "fblocked channelId"}}
} {1 {wrong # args: should be "fblocked channel"}}
test iocmd-10.3 {fblocked command} {
    list [catch {fblocked file1000} msg] $msg
} {1 {can not find channel named "file1000"}}
test iocmd-10.4 {fblocked command} {
    list [catch {fblocked stdout} msg] $msg
} {1 {channel "stdout" wasn't opened for reading}}
test iocmd-10.5 {fblocked command} {
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
467
468
469
470
471
472
473
474
475

476
477
478

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
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
467
468
469
470
471
472
473
474

475
476
477

478
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







-



-





-


















-
+


-
+



-
+












+
+
+
+
+
+
+


-
+






-
+
+
+
+
+
+
+
+
+
+







} -returnCodes error -result {(?i)couldn't open ".*test3": no such file or directory}
#
# Test 13.4 relies on assigning the same channel name twice.
#
test iocmd-12.4 {POSIX open access modes: WRONLY} {unix} {
    file delete $path(test3)
    set f [open $path(test3) w]
    fconfigure $f -eofchar {}
    puts $f xyzzy
    close $f
    set f [open $path(test3) WRONLY]
    fconfigure $f -eofchar {}
    puts -nonewline $f "ab"
    seek $f 0 current
    set x [list [catch {gets $f} msg] $msg]
    close $f
    set f [open $path(test3) r]
    fconfigure $f -eofchar {}
    lappend x [gets $f]
    close $f
    set y [list 1 [format "channel \"%s\" wasn't opened for reading" $f] abzzy]
    string compare $x $y
} 0
test iocmd-12.5 {POSIX open access modes: RDWR} -match regexp -body {
    file delete $path(test3)
    open $path(test3) RDWR
} -returnCodes error -result {(?i)couldn't open ".*test3": no such file or directory}
test iocmd-12.6 {POSIX open access modes: errors} {
    concat [catch {open $path(test3) "FOO \{BAR BAZ"} msg] $msg\n$::errorInfo
} "1 unmatched open brace in list
unmatched open brace in list
    while processing open access modes \"FOO {BAR BAZ\"
    invoked from within
\"open \$path(test3) \"FOO \\{BAR BAZ\"\""
test iocmd-12.7 {POSIX open access modes: errors} {
  list [catch {open $path(test3) {FOO BAR BAZ}} msg] $msg
} {1 {invalid access mode "FOO": must be RDONLY, WRONLY, RDWR, APPEND, BINARY, CREAT, EXCL, NOCTTY, NONBLOCK, or TRUNC}}
} {1 {invalid access mode "FOO": must be APPEND, BINARY, CREAT, EXCL, NOCTTY, NONBLOCK, RDONLY, RDWR, TRUNC, or WRONLY}}
test iocmd-12.8 {POSIX open access modes: errors} {
    list [catch {open $path(test3) {TRUNC CREAT}} msg] $msg
} {1 {access mode must include either RDONLY, WRONLY, or RDWR}}
} {1 {access mode must include either RDONLY, RDWR, or WRONLY}}
close [open $path(test3) w]
test iocmd-12.9 {POSIX open access modes: BINARY} {
    list [catch {open $path(test1) BINARY} msg] $msg
} {1 {access mode must include either RDONLY, WRONLY, or RDWR}}
} {1 {access mode must include either RDONLY, RDWR, or WRONLY}}
test iocmd-12.10 {POSIX open access modes: BINARY} {
    set f [open $path(test1) {WRONLY BINARY TRUNC}]
    puts $f a
    puts $f b
    puts -nonewline $f c	;# contents are now 5 bytes: a\nb\nc
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation binary
    set result [string length [read $f]]
    close $f
    set result
} 5
test iocmd-12.10.1 {POSIX open access modes: BINARY} -body {
    after 100
    set f [open $path(test1) {WRONLY BINARY TRUNC}]
    puts $f Ɉ		;# throws an exception
} -cleanup {
    close $f
} -returnCodes 1 -match glob -result {error writing "*": invalid or incomplete multibyte or wide character}
test iocmd-12.11 {POSIX open access modes: BINARY} {
    set f [open $path(test1) {WRONLY BINARY TRUNC}]
    puts $f \u0248		;# gets truncated to \u0048
    puts $f H
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation binary
    set result [read -nonewline $f]
    close $f
    set result
} \u0048
} H
test iocmd-12.12 {POSIX open access modes: errors} {
  list [catch {open $path(test3) {RDWR WRONLY}} msg] $msg
} {1 {invalid access mode "WRONLY": modes RDONLY, RDWR, and WRONLY cannot be combined}}
test iocmd-12.13 {POSIX open access modes: errors} {
  list [catch {open $path(test3) {BINARY BINARY}} msg] $msg
} {1 {access mode "BINARY" repeated}}
test iocmd-12.14 {POSIX open access modes: errors} {
  list [catch {open $path(test3) {TRUNC}} msg] $msg
} {1 {access mode must include either RDONLY, RDWR, or WRONLY}}

test iocmd-13.1 {errors in open command} {
    list [catch {open} msg] $msg
} {1 {wrong # args: should be "open fileName ?access? ?permissions?"}}
test iocmd-13.2 {errors in open command} {
    list [catch {open a b c d} msg] $msg
} {1 {wrong # args: should be "open fileName ?access? ?permissions?"}}
578
579
580
581
582
583
584
585






















586
587
588
589
590
591
592
594
595
596
597
598
599
600

601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    set fid [open $f rb]
    append d [read $fid]
    close $fid
    return $d
} -cleanup {
    removeFile $f
} -result 341234x6

test ioCmd-13.12 {open file produces something that has fconfigure -stat} -setup {
    set f [makeFile {} iocmd13_12]
    set result {}
} -body {
    set fd [open $f wb]
    set result [dict get [fconfigure $fd -stat] type]
    fconfigure $fd -buffering none
    puts -nonewline $fd abc
    # Three ways of getting the size; all should agree!
    lappend result [tell $fd] [file size $f] \
	[dict get [fconfigure $fd -stat] size]
    puts -nonewline $fd def
    lappend result [tell $fd] [file size $f] \
	[dict get [fconfigure $fd -stat] size]
    puts -nonewline $fd ghi
    lappend result [tell $fd] [file size $f] \
	[dict get [fconfigure $fd -stat] size]
    close $fd
    return $result
} -cleanup {
    removeFile $f
} -result {file 3 3 3 6 6 6 9 9 9}

test iocmd-14.1 {file id parsing errors} {
    list [catch {eof gorp} msg] $msg $::errorCode
} {1 {can not find channel named "gorp"} {TCL LOOKUP CHANNEL gorp}}
test iocmd-14.2 {file id parsing errors} {
    list [catch {eof filex} msg] $msg
} {1 {can not find channel named "filex"}}
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
712
713
714
715
716
717
718

719
720
721
722
723
724
725
726
727
728



729
730
731
732
733

734

735
736
737
738
739
740
741







-
+









-
-
-
+
+
+
+

-
+
-







    set msg
} {wrong # args: should be "chan subcommand ?arg ...?"}
test iocmd-20.1 {chan, unknown method} -body {
    chan foo
} -returnCodes error -match glob -result {unknown or ambiguous subcommand "foo": must be *}

# --- --- --- --------- --------- ---------
# chan create, and method "initalize"
# chan create, and method "initialize"

test iocmd-21.0 {chan create, wrong#args, not enough} {
    catch {chan create} msg
    set msg
} {wrong # args: should be "chan create mode cmdprefix"}
test iocmd-21.1 {chan create, wrong#args, too many} {
    catch {chan create a b c} msg
    set msg
} {wrong # args: should be "chan create mode cmdprefix"}
test iocmd-21.2 {chan create, invalid r/w mode, empty} {
    proc foo {} {}
    catch {chan create {} foo} msg
test iocmd-21.2 {chan create, r/w mode empty} {
    proc foo {cmd args} { return {initialize finalize watch} }
    set chan [chan create {} foo]
    close $chan
    rename foo {}
    set msg
} {}
} {bad mode list: is empty}
test iocmd-21.3 {chan create, invalid r/w mode, bad string} {
    proc foo {} {}
    catch {chan create {c} foo} msg
    rename foo {}
    set msg
} {bad mode "c": must be read or write}
test iocmd-21.4 {chan create, bad handler, not a list} {
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
963
964
965
966
967
968
969











970
971
972
973
974
975
976







-
-
-
-
-
-
-
-
-
-
-







    return -code return $args
}
proc onfinal {} {
    upvar args hargs
    if {[lindex $hargs 0] ne "finalize"} {return}
    return -code return ""
}

proc onwatch {} {
    upvar args hargs
    lassign $hargs watch chan eventspec
    if {$watch ne "watch"} return
    foreach spec $eventspec {
	chan postevent $chan $spec
    }
    return
}

}

# Set everything up in the main thread.
eval $helperscript

# --- --- --- --------- --------- ---------
# method finalize
1044
1045
1046
1047
1048
1049
1050
1051

1052
1053
1054
1055
1056
1057
1058
1070
1071
1072
1073
1074
1075
1076

1077
1078
1079
1080
1081
1082
1083
1084







-
+







    }
    set c [chan create {r w} foo]
    note [read $c 10]
    close $c
    rename foo {}
    set res
} -result {{read rc* 4096} {read rc* 4096} snarfsnarf}
test iocmd-23.2 {chan read, bad data return, to much} -match glob -body {
test iocmd-23.2 {chan read, bad data return, too much} -match glob -body {
    set res {}
    proc foo {args} {
	oninit; onfinal; track
	return [string repeat snarf 1000]
    }
    set c [chan create {r w} foo]
    note [catch {read $c 2} msg]; note $msg
1353
1354
1355
1356
1357
1358
1359
1360

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
1387

1388
1389
1390
1391
1392
1393
1394
1379
1380
1381
1382
1383
1384
1385

1386
1387
1388
1389
1390
1391

1392
1393
1394

1395
1396
1397
1398
1399
1400

1401
1402
1403

1404
1405

1406
1407
1408
1409
1410
1411
1412

1413
1414
1415
1416
1417
1418
1419
1420







-
+





-
+


-
+





-
+


-
+

-
+






-
+







} -result {{write rc* ABC} {watch rc* write} {}}

# --- === *** ###########################
# method cgetall

test iocmd-25.1 {chan configure, cgetall, standard options} -match glob -body {
    set res {}
    proc foo {args} {oninit; onfinal; track; note MUST_NOT_HAPPEN; return}
    proc foo args {oninit; onfinal; track; note MUST_NOT_HAPPEN; return}
    set c [chan create {r w} foo]
    note [fconfigure $c]
    close $c
    rename foo {}
    set res
} -result {{-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {{} {}} -translation {auto *}}}
} -result {{-blocking 1 -buffering full -buffersize 4096 -encoding * -profile * -translation {auto *}}}
test iocmd-25.2 {chan configure, cgetall, no options} -match glob -body {
    set res {}
    proc foo {args} {oninit cget cgetall; onfinal; track; return ""}
    proc foo args {oninit cget cgetall; onfinal; track; return ""}
    set c [chan create {r w} foo]
    note [fconfigure $c]
    close $c
    rename foo {}
    set res
} -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {{} {}} -translation {auto *}}}
} -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * -profile * -translation {auto *}}}
test iocmd-25.3 {chan configure, cgetall, regular result} -match glob -body {
    set res {}
    proc foo {args} {
    proc foo args {
	oninit cget cgetall; onfinal; track
	return "-bar foo -snarf x"
	return {-bar foo -snarf x}
    }
    set c [chan create {r w} foo]
    note [fconfigure $c]
    close $c
    rename foo {}
    set res
} -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {{} {}} -translation {auto *} -bar foo -snarf x}}
} -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * -profile * -translation {auto *} -bar foo -snarf x}}
test iocmd-25.4 {chan configure, cgetall, bad result, list of uneven length} -match glob -body {
    set res {}
    proc foo {args} {
	oninit cget cgetall; onfinal; track
	return "-bar"
    }
    set c [chan create {r w} foo]
2018
2019
2020
2021
2022
2023
2024
2025

2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038

2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2044
2045
2046
2047
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







-
+












-
+












-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    set stop [after 15000 {lappend res TIMEOUT; set tock 1}]
    after  1000 {note [chan postevent $c r]}
    vwait ::tock
    catch {after cancel $stop}
    close $c
    rename foo {}
    set res
} -result {{watch rc* read} {} {} TOCK {watch rc* {}}}
} -result {{watch rc* read} {} TOCK {} {watch rc* {}}}
test iocmd-31.7 {chan postevent, posted events do happen} -match glob -body {
    set res {}
    proc foo {args} {oninit; onfinal; track; return}
    set c [chan create {r w} foo]
    note [fileevent $c writable {lappend res TOCK; set tock 1}]
    set stop [after 15000 {lappend res TIMEOUT; set tock 1}]
    after  1000 {note [chan postevent $c w]}
    vwait ::tock
    catch {after cancel $stop}
    close $c
    rename foo {}
    set res
} -result {{watch rc* write} {} {} TOCK {watch rc* {}}}
} -result {{watch rc* write} {} TOCK {} {watch rc* {}}}
test iocmd-31.8 {chan postevent after close throws error} -match glob -setup {
    proc foo {args} {oninit; onfinal; track; return}
    proc dummy args { return }
    set c [chan create {r w} foo]
    fileevent $c readable dummy
} -body {
    close $c
    chan postevent $c read
} -cleanup {
    rename foo   {}
    rename dummy {}
} -returnCodes error -result {can not find reflected channel named "rc*"}
test iocmd-31.9 {
    chan postevent

    call to current coroutine

    see 67a5eabbd3d1
} -match glob -body {
    set res {}
    proc foo {args} {oninit; onwatch; onfinal; track; return}
    set c [chan create {r w} foo]
    after 0 [list ::apply [list c {
	coroutine c1 ::apply [list c {
	    chan event $c readable [list [info coroutine]]
	    yield
	    set ::done READING
	} [namespace current]] $c
    } [namespace current]] $c]
    set stop [after 10000 {set done TIMEOUT}]
    vwait ::done
    catch {after cancel $stop}
    lappend res $done
    close $c
    rename foo {}
    set res
} -result {{watch rc* read} READING {watch rc* {}}}

# --- === *** ###########################
# 'Pull the rug' tests. Create channel in a interpreter A, move to
# other interpreter B, destroy the origin interpreter (A) before or
# during access from B. Must not crash, must return proper errors.

test iocmd-32.0 {origin interpreter of moved channel gone} -match glob -body {
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171



2172
2173
2174




































































2175
2176
2177
2178
2179
2180
2181
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
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







-
-
-
+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








test iocmd-32.2 {delete interp of reflected chan} {
    # Bug 3034840
    # Run this test in an interp with memory debugging to panic
    # on the double free
    interp create child
    child eval {
        proc no-op args {}
        proc driver {sub args} {return {initialize finalize watch read}}
        chan event [chan create read driver] readable no-op
	proc no-op args {}
	proc driver {sub args} {return {initialize finalize watch read}}
	chan event [chan create read driver] readable no-op
    }
    interp delete child
} {}

# 1st attempt without error in write, another with error in write:
foreach ::writeErr {0 1} {
test iocmd-32.3.$::writeErr {prevent copy-state against segfault by finalize, bug [79474c58800cdf94]} -setup {
    proc test_chan {args} {
      set rest [lassign $args mode chan]
      lappend ::ret $mode
      switch -exact $mode {
	read {puts $chan "Test" ; close $chan}
	write {if {$::writeErr} {return "boom"}; set data [lindex $rest 0]; string length $data}
	finalize {after 20 {set ::done done}}
	initialize {return "initialize watch finalize read write"}
      }
    }
    set clchlst {}
    set toev [after 5000 {set ::done tout}]
} -body {
    set ::ret {}
    set ch [chan create "read write" test_chan]
    lappend clchlst $ch

    lassign [chan pipe] in1 out1
    lappend clchlst $in1 $out1
    lassign [chan pipe] in2 out2
    lappend clchlst $in2 $out2
    lassign [chan pipe] in3 out3
    lappend clchlst $in3 $out3

    # simulate exec: echo test >@ $out2 2>@ $out3 <@ $in1 &:
    fileevent $out2 writable [list apply {{cho che} {
	puts $cho test; close $cho; close $che
    }} $out2 $out3]
    # recopy to given chans in handler
    fileevent $in2 readable [list apply {{in out} {
	if {[catch {
	    chan copy $in $out
	} msg]} {
	    #puts err:$msg
	    fileevent $in readable {}
	}
    }} $in2 $ch]
    fileevent $in3 readable [list apply {{in out} {
	if {[catch {
	    chan copy $in $out
	} msg]} {
	    #puts err:$msg
	    fileevent $in readable {}
	}
    }} $in3 $ch]
    fileevent $out1 writable [list apply {{in out} {
	if {[catch {
	    chan copy $in $out
	} msg]} {
	    #puts err:$msg
	    fileevent $out writable {}
	}
    }} $ch $out1]

    vwait ::done
    lappend ::ret $::done
} -cleanup {
    foreach ch $clchlst {
	catch {close $ch}
    }
    after cancel $toev
    unset -nocomplain ::done ::ret ch in1 in2 in3 out1 out2 out3 toev clchlst
} -result {initialize read write finalize done}
}; unset ::writeErr

# ### ### ### ######### ######### #########
## Same tests as above, but exercising the code forwarding and
## receiving driver operations to the originator thread.

# -*- tcl -*-
# ### ### ### ######### ######### #########
2355
2356
2357
2358
2359
2360
2361
2362

2363
2364
2365
2366
2367
2368
2369
2424
2425
2426
2427
2428
2429
2430

2431
2432
2433
2434
2435
2436
2437
2438







-
+







	note [read $c 10]
	close $c
	notes
    } c]
    rename foo {}
    set res
} -constraints {testchannel thread} -result {{read rc* 4096} {read rc* 4096} snarfsnarf}
test iocmd.tf-23.2 {chan read, bad data return, to much} -match glob -body {
test iocmd.tf-23.2 {chan read, bad data return, too much} -match glob -body {
    set res {}
    proc foo {args} {
	oninit; onfinal; track
	return [string repeat snarf 1000]
    }
    set c [chan create {r w} foo]
    notes [inthread $c {
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
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







-
+












-
+















-
+







	note [fconfigure $c]
	close $c
	notes
    } c]
    rename foo {}
    set res
} -constraints {testchannel thread} \
    -result {{-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {{} {}} -translation {auto *}}}
    -result {{-blocking 1 -buffering full -buffersize 4096 -encoding * * -translation {auto *}}}
test iocmd.tf-25.2 {chan configure, cgetall, no options} -match glob -body {
    set res {}
    proc foo {args} {oninit cget cgetall; onfinal; track; return ""}
    set c [chan create {r w} foo]
    notes [inthread $c {
	note [fconfigure $c]
	close $c
	notes
    } c]
    rename foo {}
    set res
} -constraints {testchannel thread} \
    -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {{} {}} -translation {auto *}}}
    -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * * -translation {auto *}}}
test iocmd.tf-25.3 {chan configure, cgetall, regular result} -match glob -body {
    set res {}
    proc foo {args} {
	oninit cget cgetall; onfinal; track
	return "-bar foo -snarf x"
    }
    set c [chan create {r w} foo]
    notes [inthread $c {
	note [fconfigure $c]
	close $c
	notes
    } c]
    rename foo {}
    set res
} -constraints {testchannel thread} \
    -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {{} {}} -translation {auto *} -bar foo -snarf x}}
    -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * * -translation {auto *} -bar foo -snarf x}}
test iocmd.tf-25.4 {chan configure, cgetall, bad result, list of uneven length} -match glob -body {
    set res {}
    proc foo {args} {
	oninit cget cgetall; onfinal; track
	return "-bar"
    }
    set c [chan create {r w} foo]
3878
3879
3880
3881
3882
3883
3884











































































































































































































3885
3886
3887
3888
3889
3890
3891
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








    catch {thread::release $tida}
    thread::release $tidb
    set res
} -constraints {testchannel thread notValgrind} \
    -result {Owner lost}

# Tests of readFile

set BIN_DATA "\u0000\u0001\u0002\u0003\u0004\u001a\u001b\u000d\u000a\u0000"

test iocmd.readFile-1.1 "readFile procedure: syntax" -body {
    readFile
} -returnCodes error -result {wrong # args: should be "readFile filename ?mode?"}
test iocmd.readFile-1.2 "readFile procedure: syntax" -body {
    readFile a b c
} -returnCodes error -result {wrong # args: should be "readFile filename ?mode?"}
test iocmd.readFile-1.3 "readFile procedure: syntax" -body {
    readFile gorp gorp2
} -returnCodes error -result {bad mode "gorp2": must be binary or text}

test iocmd.readFile-2.1 "readFile procedure: behaviour" -setup {
    set f [makeFile "File\nContents" readFile21.txt]
} -body {
    readFile $f
} -cleanup {
    removeFile $f
} -result "File\nContents\n"
test iocmd.readFile-2.2 "readFile procedure: behaviour" -setup {
    set f [makeFile "File\nContents" readFile22.txt]
} -body {
    readFile $f text
} -cleanup {
    removeFile $f
} -result "File\nContents\n"
test iocmd.readFile-2.3 "readFile procedure: behaviour" -setup {
    set f [makeFile "" readFile23.bindata]
    apply {filename {
	global BIN_DATA
	set ff [open $filename wb]
	puts -nonewline $ff $BIN_DATA
	close $ff
    }} $f
} -body {
    list [binary scan [readFile $f binary] c* x] $x
} -cleanup {
    removeFile $f
} -result {1 {0 1 2 3 4 26 27 13 10 0}}
# Need to set up ahead of the test
set f [makeFile "" readFile24.txt]
removeFile $f
test iocmd.readFile-2.4 "readFile procedure: behaviour" -body {
    readFile $f
} -returnCodes error -result "couldn't open \"$f\": no such file or directory"

# Tests of writeFile

test iocmd.writeFile-1.1 "writeFile procedure: syntax" -body {
    writeFile
} -returnCodes error -result {wrong # args: should be "writeFile filename ?mode? data"}
test iocmd.writeFile-1.2 "writeFile procedure: syntax" -body {
    writeFile a b c d
} -returnCodes error -result {wrong # args: should be "writeFile filename ?mode? data"}
test iocmd.writeFile-1.3 "writeFile procedure: syntax" -body {
    writeFile gorp gorp2 gorp3
} -returnCodes error -result {bad mode "gorp2": must be binary or text}

test iocmd.writeFile-2.1 "readFile procedure: behaviour" -setup {
    set f [makeFile "" writeFile21.txt]
    removeFile $f
} -body {
    list [writeFile $f "File\nContents\n"] [apply {filename {
	set f [open $filename]
	set text [read $f]
	close $f
	return $text
    }} $f]
} -cleanup {
    file delete $f
} -result [list {} "File\nContents\n"]
test iocmd.writeFile-2.2 "readFile procedure: behaviour" -setup {
    set f [makeFile "" writeFile22.txt]
    removeFile $f
} -body {
    writeFile $f text "File\nContents\n"
    apply {filename {
	set f [open $filename]
	set text [read $f]
	close $f
	return $text
    }} $f
} -cleanup {
    file delete $f
} -result "File\nContents\n"
test iocmd.writeFile-2.3 "readFile procedure: behaviour" -setup {
    set f [makeFile "" writeFile23.txt]
    removeFile $f
} -body {
    writeFile $f binary $BIN_DATA
    apply {filename {
	set f [open $filename rb]
	set bytes [read $f]
	close $f
	binary scan $bytes c* x
	return $x
    }} $f
} -cleanup {
    file delete $f
} -result {0 1 2 3 4 26 27 13 10 0}

# Tests of foreachLine

test iocmd.foreachLine-1.1 "foreachLine procedure: syntax" -returnCodes error -body {
    foreachLine
} -result {wrong # args: should be "foreachLine varName filename body"}
test iocmd.foreachLine-1.2 "foreachLine procedure: syntax" -returnCodes error -body {
    foreachLine a b c d
} -result {wrong # args: should be "foreachLine varName filename body"}
test iocmd.foreachLine-1.3 "foreachLine procedure: basic errors" -setup {
    set f [makeFile "" foreachLine13.txt]
} -body {
    apply {filename {
	array set b {1 1}
	foreachLine b $filename {}
    }} $f
} -cleanup {
    removeFile $f
} -returnCodes error -result {can't set "line": variable is array}
set f [makeFile "" foreachLine14.txt]
removeFile $f
test iocmd.foreachLine-1.4 "foreachLine procedure: basic errors" -body {
    apply {filename {
	foreachLine var $filename {}
    }} $f
} -returnCodes error -result "couldn't open \"$f\": no such file or directory"

test iocmd.foreachLine-2.1 "foreachLine procedure: behaviour" -setup {
    set f [makeFile "a\nb\nc" foreachLine21.txt]
} -body {
    apply {filename {
	set lines {}
	foreachLine var $filename {
	    lappend lines $var
	}
	return $lines
    }} $f
} -cleanup {
    removeFile $f
} -result {a b c}
test iocmd.foreachLine-2.2 "foreachLine procedure: behaviour" -setup {
    set f [makeFile "a\nbb\nc\ndd" foreachLine22.txt]
} -body {
    apply {filename {
	set lines {}
	foreachLine var $filename {
	    if {[string length $var] == 1} continue
	    lappend lines $var
	}
	return $lines
    }} $f
} -cleanup {
    removeFile $f
} -result {bb dd}
test iocmd.foreachLine-2.3 "foreachLine procedure: behaviour" -setup {
    set f [makeFile "a\nbb\nccc\ndd\ne" foreachLine23.txt]
} -body {
    apply {filename {
	set lines {}
	foreachLine var $filename {
	    if {[string length $var] > 2} break
	    lappend lines $var
	}
	return $lines
    }} $f
} -cleanup {
    removeFile $f
} -result {a bb}
test iocmd.foreachLine-2.4 "foreachLine procedure: behaviour" -setup {
    set f [makeFile "a\nbb\nccc\ndd\ne" foreachLine24.txt]
} -body {
    apply {filename {
	set lines {}
	foreachLine var $filename {
	    if {[string length $var] > 2} {
		return $var
	    }
	    lappend lines $var
	}
	return $lines
    }} $f
} -cleanup {
    removeFile $f
} -result {ccc}
test iocmd.foreachLine-2.5 "foreachLine procedure: behaviour" -setup {
    set f [makeFile "a\nbb\nccc\ndd\ne" foreachLine25.txt]
} -body {
    apply {filename {
	set lines {}
	foreachLine var $filename {
	    if {[string length $var] > 2} {
		error "line too long"
	    }
	    lappend lines $var
	}
	return $lines
    }} $f
} -cleanup {
    removeFile $f
} -returnCodes error -result {line too long}

# ### ### ### ######### ######### #########

# ### ### ### ######### ######### #########

rename track {}
# cleanup

Changes to tests/ioTrans.test.

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
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







-
+











-
+







# -*- tcl -*-
# Functionality covered: operation of the reflected transformation
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 2007 Andreas Kupries <andreask@activestate.com>
# Copyright © 2007 Andreas Kupries <andreask@activestate.com>
#                                    <akupries@shaw.ca>
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

# Custom constraints used in this file
testConstraint testchannel [llength [info commands testchannel]]
testConstraint thread [expr {0 == [catch {package require Thread 2.7-}]}]

# testchannel cut|splice  Both needed to test the reflection in threads.
# thread::send
110
111
112
113
114
115
116
117

118
119
120
121
122
123
124
110
111
112
113
114
115
116

117
118
119
120
121
122
123
124







-
+







    chan
} -result {wrong # args: should be "chan subcommand ?arg ...?"}
test iortrans-1.1 {chan, unknown method} -returnCodes error -body {
    chan foo
} -match glob -result {unknown or ambiguous subcommand "foo": must be*}

# --- --- --- --------- --------- ---------
# chan push, and method "initalize"
# chan push, and method "initialize"

test iortrans-2.0 {chan push, wrong#args, not enough} -returnCodes error -body {
    chan push
} -result {wrong # args: should be "chan push channel cmdprefix"}
test iortrans-2.1 {chan push, wrong#args, too many} -returnCodes error -body {
    chan push a b c
} -result {wrong # args: should be "chan push channel cmdprefix"}
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615












616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634

















635























































636
637
638
639
640
641
642
643
644
645
646
647
648
649










650
651
652
653
654
655
656
657
658

659
660
661
662
663
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
707
708
709
710
711
712
713
714
715

716
717
718
719
720
721
722
723

724
725
726
727
728
729
730
731

732
733
734
735
736
737
738
739
740
741
742

743
744
745
746



747
748
749
750
751




752
753
754
755


756
757
758
759
760
761
762
763
764
765

766
767
768
769
770
771
772
597
598
599
600
601
602
603












604
605
606
607
608
609
610
611
612
613
614
615
616
617

















618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712

713
714
715
716
717
718
719
720

721
722
723
724
725
726
727
728

729
730
731
732
733
734
735
736
737
738
739

740
741



742
743
744
745




746
747
748
749
750
751
752
753
754
755
756


757
758
759
760
761
762
763
764
765
766
767
768
769

770
771
772
773
774
775
776
777

778
779
780
781
782
783
784
785

786
787
788
789
790
791
792
793
794
795
796

797
798



799
800
801
802




803
804
805
806
807
808


809
810
811
812
813
814
815
816
817
818
819

820
821
822
823
824
825
826
827







-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+








-
+







-
+







-
+










-
+

-
-
-
+
+
+

-
-
-
-
+
+
+
+







-
-
+
+











-
+







-
+







-
+










-
+

-
-
-
+
+
+

-
-
-
-
+
+
+
+


-
-
+
+









-
+







    rename foo {}
} -result {{read rt* {test data
}} {}}

# Driver for a base channel that emits several short "files"
# with each terminated by a fleeting EOF
    proc driver {cmd args} {
        variable ::tcl::buffer
        variable ::tcl::index
        set chan [lindex $args 0]
        switch -- $cmd {
            initialize {
                set index($chan) 0
                set buffer($chan) .....
                return {initialize finalize watch read}
            }
            finalize {
                if {![info exists index($chan)]} {return}
                unset index($chan) buffer($chan)
	variable ::tcl::buffer
	variable ::tcl::index
	set chan [lindex $args 0]
	switch -- $cmd {
	    initialize {
		set index($chan) 0
		set buffer($chan) .....
		return {initialize finalize watch read}
	    }
	    finalize {
		if {![info exists index($chan)]} {return}
		unset index($chan) buffer($chan)
		array unset index
		array unset buffer
                return
            }
            watch {}
            read {
                set n [lindex $args 1]
                if {![info exists index($chan)]} {
                    driver initialize $chan
                }
                set new [expr {$index($chan) + $n}]
                set result [string range $buffer($chan) $index($chan) $new-1]
                set index($chan) $new
                if {[string length $result] == 0} {
                    driver finalize $chan
                }
                return $result
            }
        }
		return
	    }
	    watch {}
	    read {
		set n [lindex $args 1]
		if {![info exists index($chan)]} {
		    driver initialize $chan
		}
		set new [expr {$index($chan) + $n}]
		set result [string range $buffer($chan) $index($chan) $new-1]
		set index($chan) $new
		if {[string length $result] == 0} {
		    driver finalize $chan
		}
		return $result
	    }
	}
    }



namespace eval reflector {
    proc initialize {_ chan mode} {
	return {initialize finalize watch read}
    }


    proc finalize {_ chan} {
	foreach id [after info] {
	    after cancel $id
	}
	namespace delete $_
    }


    proc read {_ chan count} {
	namespace upvar $_ source source
	set res [string range $source 0 $count-1]
	set source [string range $source $count end]
	return $res
    }


    proc watch {_ chan events} {
	after 0 [list chan postevent $chan read]
	return read
    }

    namespace ensemble create -parameters _
    namespace export *
}




namespace eval inputfilter {
    proc initialize {chan mode} {
	return {initialize finalize read}
    }

    proc read {chan buffer} {
	return $buffer
    }

    proc finalize chan {
	namespace delete $chan
    }

    namespace ensemble create
    namespace export *
}



# Channel read transform that is just the identity - pass all through
    proc idxform {cmd handle args} {
      switch -- $cmd {
        initialize {
            return {initialize finalize read}
        }
        finalize {
            return
        }
        read {
            lassign $args buffer
            return $buffer
        }
	initialize {
	    return {initialize finalize read}
	}
	finalize {
	    return
	}
	read {
	    lassign $args buffer
	    return $buffer
	}
      }
    }

# Test that all EOFs pass through full xform stack.  Proper data boundaries.
# Check robustness against buffer sizes.
test iortrans-4.10 {[5adbc350683] chan read, handle fleeting EOF} -body {
    set chan [chan push [chan create read driver] idxform]
    list [eof $chan] [read $chan] [eof $chan] [read $chan 0] [eof $chan] \
        [read $chan] [eof $chan]
	[read $chan] [eof $chan]
} -cleanup {
    close $chan
} -result {0 ..... 1 {} 0 ..... 1}
test iortrans-4.10.1 {[5adbc350683] chan read, handle fleeting EOF} -body {
    set chan [chan push [chan create read driver] idxform]
    chan configure $chan -buffersize 3
    list [eof $chan] [read $chan] [eof $chan] [read $chan 0] [eof $chan] \
        [read $chan] [eof $chan]
	[read $chan] [eof $chan]
} -cleanup {
    close $chan
} -result {0 ..... 1 {} 0 ..... 1}
test iortrans-4.10.2 {[5adbc350683] chan read, handle fleeting EOF} -body {
    set chan [chan push [chan create read driver] idxform]
    chan configure $chan -buffersize 5
    list [eof $chan] [read $chan] [eof $chan] [read $chan 0] [eof $chan] \
        [read $chan] [eof $chan]
	[read $chan] [eof $chan]
} -cleanup {
    close $chan
} -result {0 ..... 1 {} 0 ..... 1}

rename idxform {}

# Channel read transform that delays the data and always returns something
    proc delayxform {cmd handle args} {
      variable store
      switch -- $cmd {
        initialize {
	initialize {
	    set store($handle) {}
            return {initialize finalize read drain}
        }
        finalize {
	    return {initialize finalize read drain}
	}
	finalize {
	    unset store($handle)
            return
        }
        read {
            lassign $args buffer
	    return
	}
	read {
	    lassign $args buffer
	    if {$store($handle) eq {}} {
		set reply [string index $buffer 0]
		set store($handle) [string range $buffer 1 end]
	    } else {
		set reply $store($handle)
		set store($handle) $buffer
	    }
            return $reply
        }
	    return $reply
	}
	drain {
	    delayxform read $handle {}
	}
      }
    }

# Test that all EOFs pass through full xform stack.  Proper data boundaries.
# Check robustness against buffer sizes.
test iortrans-4.11 {[5adbc350683] chan read, handle fleeting EOF} -body {
    set chan [chan push [chan create read driver] delayxform]
    list [eof $chan] [read $chan] [eof $chan] [read $chan 0] [eof $chan] \
        [read $chan] [eof $chan]
	[read $chan] [eof $chan]
} -cleanup {
    close $chan
} -result {0 ..... 1 {} 0 ..... 1}
test iortrans-4.11.1 {[5adbc350683] chan read, handle fleeting EOF} -body {
    set chan [chan push [chan create read driver] delayxform]
    chan configure $chan -buffersize 3
    list [eof $chan] [read $chan] [eof $chan] [read $chan 0] [eof $chan] \
        [read $chan] [eof $chan]
	[read $chan] [eof $chan]
} -cleanup {
    close $chan
} -result {0 ..... 1 {} 0 ..... 1}
test iortrans-4.11.2 {[5adbc350683] chan read, handle fleeting EOF} -body {
    set chan [chan push [chan create read driver] delayxform]
    chan configure $chan -buffersize 5
    list [eof $chan] [read $chan] [eof $chan] [read $chan 0] [eof $chan] \
        [read $chan] [eof $chan]
	[read $chan] [eof $chan]
} -cleanup {
    close $chan
} -result {0 ..... 1 {} 0 ..... 1}

    rename delayxform {}

# Channel read transform that delays the data and may return {}
    proc delay2xform {cmd handle args} {
      variable store
      switch -- $cmd {
        initialize {
	initialize {
	    set store($handle) {}
            return {initialize finalize read drain}
        }
        finalize {
	    return {initialize finalize read drain}
	}
	finalize {
	    unset store($handle)
            return
        }
        read {
            lassign $args buffer
	    return
	}
	read {
	    lassign $args buffer
		set reply $store($handle)
		set store($handle) $buffer
            return $reply
        }
	    return $reply
	}
	drain {
	    delay2xform read $handle {}
	}
      }
    }

test iortrans-4.12 {[5adbc350683] chan read, handle fleeting EOF} -body {
    set chan [chan push [chan create read driver] delay2xform]
    list [eof $chan] [read $chan] [eof $chan] [read $chan 0] [eof $chan] \
        [read $chan] [eof $chan]
	[read $chan] [eof $chan]
} -cleanup {
    close $chan
} -result {0 ..... 1 {} 0 ..... 1}

    rename delay2xform {}
    rename driver {}

1275
1276
1277
1278
1279
1280
1281
1282

1283
1284
1285
1286
1287
1288
1289
1330
1331
1332
1333
1334
1335
1336

1337
1338
1339
1340
1341
1342
1343
1344







-
+







#
## The id numbers refer to the original test without thread forwarding, and
## gaps due to tests not applicable to forwarding are left to keep this
## association.

# ### ### ### ######### ######### #########
## Helper command. Runs a script in a separate thread and returns the result.
## A channel is transfered into the thread as well, and a list of configuation
## A channel is transferred into the thread as well, and a list of configuration
## variables

proc inthread {chan script args} {
    # Test thread.
    set tid [thread::create -preserved]
    thread::send $tid {load {} Tcltest}

1954
1955
1956
1957
1958
1959
1960
1961

1962
1963
1964
1965
1966
1967
1968
2009
2010
2011
2012
2013
2014
2015

2016
2017
2018
2019
2020
2021
2022
2023







-
+







    set c [chan push [tempchan] foo]
    lappend res {*}[inthread $c {
	# Flush, no writing
	seek $c 2
	# The close flushes again, this modifies the file!
	lappend notes | [close $c] |
	# NOTE: The flush generated by the close is recorded immediately, the
	# other note's here are defered until after the thread is done. This
	# other note's here are deferred until after the thread is done. This
	# changes the order of the result a bit from the non-threaded case
	# (The first | moves one to the right). This is an artifact of the
	# 'inthread' framework, not of the transformation itself.
	notes
    } c]
    lappend res [tempview]
} -cleanup {
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2092
2093
2094
2095
2096
2097
2098


2099
2100
2101
2102
2103
2104
2105







-
-







    # The 'tell' is ok, as it passed through the transform to the base
    # channel without invoking the transform handler.
} -cleanup {
    thread::send $tidb tempdone
    thread::release $tidb
} -result {1 {Owner lost} 0 0 1 {Owner lost} 1 {Owner lost} 1 {Owner lost}}

testConstraint notValgrind [expr {![testConstraint valgrind]}]

test iortrans.tf-11.1 {origin thread of moved transform destroyed during access} -setup {
    #puts <<$tcltest::mainThread>>main
    set tida [thread::create -preserved];	#puts <<$tida>>
    thread::send $tida {load {} Tcltest}
    set tidb [thread::create -preserved];	#puts <<$tidb>>
    thread::send $tidb {load {} Tcltest}
} -constraints {testchannel thread notValgrind} -match glob -body {
2085
2086
2087
2088
2089
2090
2091
2092



2093






























2094
2095
2138
2139
2140
2141
2142
2143
2144

2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180







-
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


    vwait ::res
    set res
} -cleanup {
    thread::send $tidb tempdone
    thread::release $tidb
} -result {Owner lost}

# ### ### ### ######### ######### #########

test iortrans-ea69b0258a9833cb {
    Crash when using a channel transformation on TCP client socket

    "line two" does not make it into result.  This issue should probably be
    addressed, but it is outside the scope of this test.
} -setup {
    set res {}
    set read 0
} -body {
    namespace eval reflector1 {
	variable source "line one\nline two"
	interp alias {} [namespace current]::dispatch {} [
	    namespace parent]::reflector [namespace current]
    }
    set chan [chan create read [namespace which reflector1::dispatch]]
    chan configure $chan -blocking 0
    chan push $chan inputfilter
    chan event $chan read [list ::apply [list chan {
	variable res
	variable read
	set gets [gets $chan]
	append res $gets
	incr read
    } [namespace current]] $chan]
    vwait [namespace current]::read
    chan pop $chan
    vwait [namespace current]::read
    return $res
} -cleanup {
    catch {unset read}
    close $chan
} -result {line one}

cleanupTests
return

Changes to tests/iogt.test.

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
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








-
-
+
+








-
+







# -*- tcl -*-
# Commands covered:  transform, and stacking in general
#
# This file contains a collection of tests for Giot
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# Copyright (c) 2000 Ajuba Solutions.
# Copyright (c) 2000 Andreas Kupries.
# Copyright © 2000 Ajuba Solutions.
# Copyright © 2000 Andreas Kupries.
# All rights reserved.

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

::tcltest::loadTestedCommands
catch [list package require -exact Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

namespace eval ::tcl::test::iogt {
    namespace import ::tcltest::*

testConstraint testchannel [llength [info commands testchannel]]

set path(dummy) [makeFile {abcdefghijklmnopqrstuvwxyz0123456789,./?><;'\|":[]\}\{`~!@#$%^&*()_+-=
545
546
547
548
549
550
551
552
553


554
555
556
557
558
559
560
545
546
547
548
549
550
551


552
553
554
555
556
557
558
559
560







-
-
+
+







delete/write {} *ignored*}
test iogt-2.3 {basic I/O, mixed trail} {testchannel unix} {
    set fin [open $path(dummy) r]
    set fout [open $path(dummyout) w]
    set trail [list]
    audit_flow trail -attach $fin
    audit_flow trail -attach $fout
    fconfigure $fin -buffersize 20
    fconfigure $fout -buffersize 10
    fconfigure $fin -buffersize 20 -profile tcl8
    fconfigure $fout -buffersize 10 -profile tcl8
    fcopy $fin $fout
    close $fin
    close $fout
    join $trail \n
} {create/read {} *ignored*
create/write {} *ignored*
query/maxRead {} -1
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668













669
670
671
672
673
674
675
649
650
651
652
653
654
655













656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675







-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+







    close $fin
    set trail [list]
    set got [list]
    proc Done {args} {
	variable stop 1
    }
    proc Get {sock} {
        variable trail
        variable got
        if {[eof $sock]} {
            Done
            lappend trail "xxxxxxxxxxxxx"
            close $sock
            return
        }
        lappend trail "vvvvvvvvvvvvv"
        lappend trail "\tgot: [lappend got "\[\[[read $sock]\]\]"]"
        lappend trail "============="
        #puts stdout $__ ; flush stdout
        #read $sock
	variable trail
	variable got
	if {[eof $sock]} {
	    Done
	    lappend trail "xxxxxxxxxxxxx"
	    close $sock
	    return
	}
	lappend trail "vvvvvvvvvvvvv"
	lappend trail "\tgot: [lappend got "\[\[[read $sock]\]\]"]"
	lappend trail "============="
	#puts stdout $__ ; flush stdout
	#read $sock
    }

} -constraints {testchannel knownBug} -body {
    fevent 1000 500 {20 20 20 10 1} {
	variable stop
	audit_flow trail -attach $sock
	rblocks_t rbuf trail 23 -attach $sock
839
840
841
842
843
844
845
846

847
848
849
850
851
852
853
839
840
841
842
843
844
845

846
847
848
849
850
851
852
853







-
+







    set f [open $path(dummy) r]
    # contents of dummy = "abcdefghi..."
    read $f 3;		# skip behind "abc"
    constx -attach $f
    # expect to get "xxx" from the transform because of unread "def" input to
    # transform which returns "xxx".
    #
    # Actually the IO layer pre-read the whole file and will read "def"
    # Actually the IO layer preread the whole file and will read "def"
    # directly from the buffer without bothering to consult the newly stacked
    # transformation. This is wrong.
    read $f 3
} -cleanup {
    close $f
} -result {xxx}
test iogt-6.1 {Push back and up} -constraints {testchannel knownBug} -body {
871
872
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
898
899
900
901
902
903
904
905
906





























907
908
909
910
911
912
913

914
915
916
917
918
919
920
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912

913
914
915
916
917
918
919
920







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+







    close $f
} -result {xxxghi}


# Driver for a base channel that emits several short "files"
# with each terminated by a fleeting EOF
    proc driver {cmd args} {
        variable buffer
        variable index
        set chan [lindex $args 0]
        switch -- $cmd {
            initialize {
                set index($chan) 0
                set buffer($chan) .....
                return {initialize finalize watch read}
            }
            finalize {
                if {![info exists index($chan)]} {return}
                unset index($chan) buffer($chan)
                return
            }
            watch {}
            read {
                set n [lindex $args 1]
                if {![info exists index($chan)]} {
                    driver initialize $chan
                }
                set new [expr {$index($chan) + $n}]
                set result [string range $buffer($chan) $index($chan) $new-1]
                set index($chan) $new
                if {[string length $result] == 0} {
                    driver finalize $chan
                }
                return $result
            }
        }
	variable buffer
	variable index
	set chan [lindex $args 0]
	switch -- $cmd {
	    initialize {
		set index($chan) 0
		set buffer($chan) .....
		return {initialize finalize watch read}
	    }
	    finalize {
		if {![info exists index($chan)]} {return}
		unset index($chan) buffer($chan)
		return
	    }
	    watch {}
	    read {
		set n [lindex $args 1]
		if {![info exists index($chan)]} {
		    driver initialize $chan
		}
		set new [expr {$index($chan) + $n}]
		set result [string range $buffer($chan) $index($chan) $new-1]
		set index($chan) $new
		if {[string length $result] == 0} {
		    driver finalize $chan
		}
		return $result
	    }
	}
    }

test iogt-7.0 {Handle fleeting EOF} -constraints {testchannel} -body {
    set chan [chan create read [namespace which driver]]
    identity -attach $chan
    list [eof $chan] [read $chan] [eof $chan] [read $chan 0] [eof $chan] \
        [read $chan] [eof $chan]
	[read $chan] [eof $chan]
} -cleanup {
    close $chan
} -result {0 ..... 1 {} 0 ..... 1}

proc delay {op data} {
    variable store
    switch -- $op {
933
934
935
936
937
938
939
940

941
942
943
944
945
946
947
933
934
935
936
937
938
939

940
941
942
943
944
945
946
947







-
+







    }
}

test iogt-7.1 {Handle fleeting EOF} -constraints {testchannel} -body {
    set chan [chan create read [namespace which driver]]
    testchannel transform $chan -command [namespace code delay]
    list [eof $chan] [read $chan] [eof $chan] [read $chan 0] [eof $chan] \
        [read $chan] [eof $chan]
	[read $chan] [eof $chan]
} -cleanup {
    close $chan
} -result {0 ..... 1 {} 0 ..... 1}

rename delay {}
rename driver {}

Changes to tests/join.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  join
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*

Changes to tests/lindex.test.

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
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






-
-
-
-
+
+
+
+










-
+







# Commands covered:  lindex
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2001 Kevin B. Kenny.  All rights reserved.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

set minus -
testConstraint testevalex [llength [info commands testevalex]]

# Tests of Tcl_LindexObjCmd, NOT COMPILED

test lindex-1.1 {wrong # args} testevalex {

Changes to tests/link.test.

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
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






-
-
-
+
+
+










-
+







# Commands covered:  none
#
# This file contains a collection of tests for Tcl_LinkVar and related library
# procedures. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testlink [llength [info commands testlink]]
testConstraint testlinkarray [llength [info commands testlinkarray]]

foreach i {int real bool string} {
    unset -nocomplain $i
}
65
66
67
68
69
70
71
72

73
74

75
76
77
78
79
80
81
65
66
67
68
69
70
71

72
73

74
75
76
77
78
79
80
81







-
+

-
+







    set uchar 161
    set short 8000
    set ushort 40000
    set uint 0xc001babe
    set long 34543
    set ulong 567890
    set float 1.0987654321
    set uwide 357357357357
    set uwide 12345678901234567890
    concat [testlink get] | $int $real $bool $string $wide $char $uchar $short $ushort $uint $long $ulong $float $uwide
} -result {465 -10.5 1 abcdef 135135 79 161 8000 40000 -1073628482 34543 567890 1.0987653732299805 357357357357 | 0o0721 -10.5 true abcdef 135135 79 161 8000 40000 0xc001babe 34543 567890 1.0987654321 357357357357}
} -result {465 -10.5 1 abcdef 135135 79 161 8000 40000 -1073628482 34543 567890 1.0987653732299805 12345678901234567890 | 0o0721 -10.5 true abcdef 135135 79 161 8000 40000 0xc001babe 34543 567890 1.0987654321 12345678901234567890}
test link-2.2 {writing bad values into variables} -setup {
    testlink delete
} -constraints {testlink} -body {
    testlink set 43 1.23 4 - 56785678 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
    testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
    list [catch {set int 09a} msg] $msg $int
} -result {1 {can't set "int": variable must have integer value} 43}
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
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







-
+

-
+

-
+









-
+

-
+







    proc x args {
	global x int real bool string wide
	lappend x $args $int $real $bool $string $wide
    }
    set x {}
    testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
    testlink set 14 -2.0 0 xyzzy 995511 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
    trace var int w x
    trace add var int write x
    testlink update 32 4.0 3 abcd 113355 65 251 30001 60001 0xbabebeef 12322 32124 3.125 12312312340
    trace vdelete int w x
    trace remove variable int write x
    return $x
} {{int {} w} 32 -2.0 0 xyzzy 995511}
} {{int {} write} 32 -2.0 0 xyzzy 995511}
test link-8.2 {Tcl_UpdateLinkedVar procedure} {testlink} {
    proc x args {
	global x int real bool string wide
	lappend x $args $int $real $bool $string $wide
    }
    set x {}
    testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
    testlink set 14 -2.0 0 xyzzy 995511 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
    testlink delete
    trace var int w x
    trace add var int write x
    testlink update 32 4.0 6 abcd 113355 65 251 30001 60001 0xbabebeef 12322 32124 3.125 12312312340
    trace vdelete int w x
    trace remove variable int write x
    return $x
} {}
test link-8.3 {Tcl_UpdateLinkedVar procedure, read-only variable} {testlink} {
    testlink create 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    list [catch {
	testlink update 47 {} {} {} {} {} {} {} {} {} {} {} {} {}
    } msg] $msg $int

Changes to tests/linsert.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  linsert
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
97
98
99
100
101
102
103
104
105


106
107
108
109
110
111
112
97
98
99
100
101
102
103


104
105
106
107
108
109
110
111
112







-
-
+
+







} [list a b c]
test linsert-2.6 {syntax (TIP 323)} {
    linsert "a\nb\nc" 0
} [list a b c]

test linsert-3.1 {linsert won't modify shared argument objects} {
    proc p {} {
        linsert "a b c" 1 "x y"
        return "a b c"
	linsert "a b c" 1 "x y"
	return "a b c"
    }
    p
} "a b c"
test linsert-3.2 {linsert won't modify shared argument objects} {
    catch {unset lis}
    set lis [format "a \"%s\" c" "b"]
    linsert $lis 0 [string length $lis]

Changes to tests/list.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  list
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
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
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







-
-
+
+



-
+

-
+

-
+





-
-
+
+


+
+
+
+
+
+
+
+
+
+







test list-1.21 {basic tests} {list a b c\\\nd} "a b c\\\\\\nd"
test list-1.22 {basic tests} {list "{ab}\\"} \\{ab\\}\\\\
test list-1.23 {basic tests} {list \{} "\\{"
test list-1.24 {basic tests} {list} {}
test list-1.25 {basic tests} {list # #} {{#} #}
test list-1.26 {basic tests} {list #\{ #\{} {\#\{ #\{}
test list-1.27 {basic null treatment} {
    set l [list "" "\0" "\0\0"]
    set e "{} \0 \0\0"
    set l [list "" "\x00" "\x00\x00"]
    set e "{} \x00 \x00\x00"
    string equal $l $e
} 1
test list-1.28 {basic null treatment} {
    set result "\0a\0b"
    set result "\x00a\x00b"
    list $result [string length $result]
} "\0a\0b 4"
} "\x00a\x00b 4"
test list-1.29 {basic null treatment} {
    set result "\0a\0b"
    set result "\x00a\x00b"
    set srep "$result 4"
    set lrep [list $result [string length $result]]
    string equal $srep $lrep
} 1
test list-1.30 {basic null treatment} {
    set l [list "\0abc" "xyz"]
    set e "\0abc xyz"
    set l [list "\x00abc" "xyz"]
    set e "\x00abc xyz"
    string equal $l $e
} 1
test list-1.31 {bug [e38dce74e2]} {
    set l #foo
    set e {}
    list {*}$l {*}$e
} {{#foo}}
test list-1.32 {bug [e38dce74e2]} {
    set l " #foo"
    set e {}
    list {*}$l {*}$e
} {{#foo}}

# For the next round of tests create a list and then pick it apart
# with "index" to make sure that we get back exactly what went in.

set num 0
proc lcheck {testid a b c} {
    global num d
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
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







-
+

-
+

-
+





-
+





-
-
+
+

-
+







concat {}

# Check that tclListObj.c's SetListFromAny handles possible overlarge
# string rep lengths in the source object.

proc slowsort list {
    set result {}
    set last [expr [llength $list] - 1]
    set last [expr {[llength $list] - 1}]
    while {$last > 0} {
	set minIndex [expr [llength $list] - 1]
	set minIndex [expr {[llength $list] - 1}]
	set min [lindex $list $last]
	set i [expr $minIndex-1]
	set i [expr {$minIndex - 1}]
	while {$i >= 0} {
	    if {[string compare [lindex $list $i] $min] < 0} {
		set minIndex $i
		set min [lindex $list $i]
	    }
	    set i [expr $i-1]
	    incr i -1
	}
	set result [concat $result [list $min]]
	if {$minIndex == 0} {
	    set list [lrange $list 1 end]
	} else {
	    set list [concat [lrange $list 0 [expr $minIndex-1]] \
			  [lrange $list [expr $minIndex+1] end]]
	    set list [concat [lrange $list 0 [expr {$minIndex - 1}]] \
			  [lrange $list [expr {$minIndex + 1}] end]]
	}
	set last [expr $last-1]
	set last [expr {$last - 1}]
    }
    return [concat $result $list]
}
test list-3.1 {SetListFromAny and lrange/concat results} {
    slowsort {fred julie alex carol bill annie}
} {alex annie bill carol fred julie}

Changes to tests/listObj.test.

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
30
31
32
33
34
35
36

37
38
39
40
41
42
43
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
30
31
32
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47







-
-
+
+










-
+


+
+
+
+













-
+







# Functionality covered: operation of the procedures in tclListObj.c that
# implement the Tcl type manager for the list object type.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands. Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testobj [llength [info commands testobj]]
testConstraint memory [llength [info commands memory]]

set INT_MAX 0x7fffffff; # Assumes sizeof(int) == 4
set SIZE_MAX [expr {(1 << (8*$::tcl_platform(pointerSize) - 1)) - 1}]

catch {unset x}
test listobj-1.1 {Tcl_GetListObjType} emptyTest {
    # Test removed; tested an internal detail
    # that's no longer correct, and duplicated test obj-1.1
} {}

test listobj-2.1 {Tcl_SetListObj, use in lappend} {
    catch {unset x}
    list [lappend x 1 abc def] [lappend x 1 ghi jkl] $x
} {{1 abc def} {1 abc def 1 ghi jkl} {1 abc def 1 ghi jkl}}
test listobj-2.2 {Tcl_SetListObj, use in ObjInterpProc} {
    proc return_args {args} {
        return $args
	return $args
    }
    list [return_args] [return_args x] [return_args x y]
} {{} x {x y}}
test listobj-2.3 {Tcl_SetListObj, zero element count} {
    list
} {}

56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74







-
+







test listobj-3.4 {Tcl_ListObjAppend, error in conversion} {
    set x " \{"
    list [catch {lappend x abc def} msg] $msg
} {1 {unmatched open brace in list}}
test listobj-3.5 {Tcl_ListObjAppend, force internal rep array to grow} {
    set x ""
    list [lappend x 1 1] [lappend x 2 2] [lappend x 3 3] [lappend x 4 4] \
        [lappend x 5 5] [lappend x 6 6] [lappend x 7 7] [lappend x 8 8] $x
	[lappend x 5 5] [lappend x 6 6] [lappend x 7 7] [lappend x 8 8] $x
} {{1 1} {1 1 2 2} {1 1 2 2 3 3} {1 1 2 2 3 3 4 4} {1 1 2 2 3 3 4 4 5 5} {1 1 2 2 3 3 4 4 5 5 6 6} {1 1 2 2 3 3 4 4 5 5 6 6 7 7} {1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8} {1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8}}

test listobj-4.1 {Tcl_ListObjAppendElement, list conversion} {
    catch {unset x}
    list [lappend x 1] $x
} {1 1}
test listobj-4.2 {Tcl_ListObjAppendElement, list conversion} {
78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
82
83
84
85
86
87
88

89
90
91
92
93
94
95
96







-
+







test listobj-4.4 {Tcl_ListObjAppendElement, error in conversion} {
    set x " \{"
    list [catch {lappend x abc} msg] $msg
} {1 {unmatched open brace in list}}
test listobj-4.5 {Tcl_ListObjAppendElement, force internal rep array to grow} {
    set x ""
    list [lappend x 1] [lappend x 2] [lappend x 3] [lappend x 4] \
        [lappend x 5] [lappend x 6] [lappend x 7] [lappend x 8] $x
	[lappend x 5] [lappend x 6] [lappend x 7] [lappend x 8] $x
} {1 {1 2} {1 2 3} {1 2 3 4} {1 2 3 4 5} {1 2 3 4 5 6} {1 2 3 4 5 6 7} {1 2 3 4 5 6 7 8} {1 2 3 4 5 6 7 8}}

test listobj-5.1 {Tcl_ListObjIndex, basic tests} {
    lindex {a b c} 0
} a
test listobj-5.2 {Tcl_ListObjIndex, basic tests} {
    lindex a 0
191
192
193
194
195
196
197




















198
199
200
201







































































































202
203
204
205
206
207
208
209
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








	    [testlistobj get 1]
    }
    -cleanup {
	testobj freeallvars
    }
    -result {{a b c d e} {} {a b c d e f}}
}
test listobj-10.2 {Tcl_ListObjReplace with negative start value} testobj {
    testlistobj set 1 a b c d e
    testlistobj replace 1 -1 2 f
    testlistobj get 1
} {f c d e}
test listobj-10.3 {Tcl_ListObjReplace with negative count value} testobj {
    testlistobj set 1 a b c d e
    testlistobj replace 1 1 -1 f
    testlistobj get 1
} {a f b c d e}
test listobj-10.4 {Tcl_ListObjReplace with $SIZE_MAX count value} testobj {
    testlistobj set 1 a b c d e
    testlistobj replace 1 1 $SIZE_MAX f
    testlistobj get 1
} {a f}
test listobj-10.5 {Tcl_ListObjReplace with SIZE_MAX-1 count value} testobj {
    testlistobj set 1 a b c d e
    testlistobj replace 1 1 [expr {$SIZE_MAX -1}] f
    testlistobj get 1
} {a f}

test listobj-11.1 {Bug 3598580: Tcl_ListObjReplace refcount management} testobj {
    testobj bug3598580
} 123
test listobj-11.2 {Bug e58d7e19e9: Upwards compatibility of TclObjTypeHasProc()} testobj {
    set l [testobj buge58d7e19e9 "a x c"]
    # Since $l is a V1 objType, it's lengthProc will be accessed, but not its indexProc.
    list [llength $l] [lindex $l 2]
} {100 c}

# Stolen from dict.test
proc listobjmemcheck script {
    set end [lindex [split [memory info] \n] 3 3]
    for {set i 0} {$i < 5} {incr i} {
	uplevel 1 $script
	set tmp $end
	set end [lindex [split [memory info] \n] 3 3]
    }
    expr {$end - $tmp}
}

test listobj-12.1 {Tcl_ListObjIndex memory leaks for native lists} -constraints {
    testobj memory
} -body {
    list [listobjmemcheck {
	testobj set 1 [lrepeat 1000 x]
	set errorMessage [testlistobj indexmemcheck 1]
	testobj freeallvars
    }] $errorMessage
} -result {0 {}}
test listobj-12.2 {Tcl_ListObjIndex memory leaks for native lists with spans} -constraints {
    testobj memory
} -body {
    list [listobjmemcheck {
	testobj set 1 [testlistrep new 1000 100 100]
	set errorMessage [testlistobj indexmemcheck 1]
	testobj freeallvars
    }] $errorMessage
} -result {0 {}}
test listobj-12.3 {Tcl_ListObjIndex memory leaks for lseq} -constraints {
    testobj memory
} -body {
    list [listobjmemcheck {
	testobj set 1 [lseq 1000]
	set errorMessage [testlistobj indexmemcheck 1]
	testobj freeallvars
    }] $errorMessage
} -result {0 {}}

test listobj-13.1 {Tcl_ListObjGetElements memory leaks for native lists} -constraints {
    testobj memory
} -body {
    list [listobjmemcheck {
	testobj set 1 [lrepeat 1000 x]
	set errorMessage [testlistobj getelementsmemcheck 1]
	testobj freeallvars
    }] $errorMessage
} -result {0 {}}
test listobj-13.2 {Tcl_ListObjElements memory leaks for native lists with spans} -constraints {
    testobj memory
} -body {
    list [listobjmemcheck {
	testobj set 1 [testlistrep new 1000 100 100]
	set errorMessage [testlistobj getelementsmemcheck 1]
	testobj freeallvars
    }] $errorMessage
} -result {0 {}}
test listobj-13.3 {Tcl_ListObjElements memory leaks for lseq} -constraints {
    testobj memory
} -body {
    list [listobjmemcheck {
	testobj set 1 [lseq 1000]
	set errorMessage [testlistobj getelementsmemcheck 1]
	testobj freeallvars
    }] $errorMessage
} -result {0 {}}

# Tests for Tcl_ListObjIndex as sematics are different from lindex for
# out of bounds indices. Out of bounds should return a null pointer and
# not empty string.
test listobj-14.1 {Tcl_ListObjIndex out-of-bounds index for native lists} -constraints {
    testobj
} -setup {
    testobj set 1 [list a b c]
} -cleanup {
    testobj freeallvars
} -body {
    list [testlistobj index 1 -1] [testlistobj index 1 3]
} -result {null null}

test listobj-14.2 {Tcl_ListObjIndex out-of-bounds index for native lists with spans} -constraints {
    testobj
} -setup {
    testobj set 1 [testlistrep new 1000 100 100]
} -cleanup {
    testobj freeallvars
} -body {
    list [testlistobj index 1 -1] [testlistobj index 1 1000]
} -result {null null}

test listobj-14.3 {Tcl_ListObjIndex out-of-bounds index for lseq} -constraints {bug-30e4e9102f testobj} -setup {
    testobj set 1 [lseq 3]
} -cleanup {
    testobj freeallvars
} -body {
    list [testlistobj index 1 -1] [testlistobj index 1 3]
} -result {null null}

# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Added tests/listRep.test.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# This file contains tests that specifically exercise the internal representation
# of a list.
#
# Copyright © 2022 Ashok P. Nadkarni
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

# Unlike the other files related to list commands which for the most part do
# black box testing focusing on functionality, this file does more of white box
# testing to exercise code paths that implement different list representations
# (with spans, leading free space etc., shared/unshared etc.) In addition to
# functional correctness, the tests also check for the expected internal
# representation as that pertains to performance heuristics. Generally speaking,
# combinations of the following need to be tested,
# - free space in front, back, neither, both of list representation
# - shared Tcl_Objs
# - shared internal reps (independent of shared Tcl_Objs)
# - byte-compiled vs non-compiled
#
# Being white box tests, they are sensitive to changes to further optimizations
# and changes in heuristics. That cannot be helped.

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]]

testConstraint testlistrep [llength [info commands testlistrep]]

proc describe {l args} {dict get [testlistrep describe $l] {*}$args}

proc irange {first last} {
    set l {}
    while {$first <= $last} {
	lappend l $first
	incr first
    }
    return $l
}
proc leadSpace {l} {
    # Returns the leading space in a list store
    return [dict get [describe $l] store firstUsed]
}
proc tailSpace {l} {
    # Returns the trailing space in a list store
    array set rep [describe $l]
    dict with rep(store) {
	return [expr {$numAllocated - ($firstUsed + $numUsed)}]
    }
}
proc allocated {l} {
    # Returns the allocated space in a list store
    return [dict get [describe $l] store numAllocated]
}
proc repStoreRefCount {l} {
    # Returns the ref count for the list store
    return [dict get [describe $l] store refCount]
}
proc validate {l} {
    # Panics if internal listrep structures are not valid
    testlistrep validate $l
}
proc leadSpaceMore {l} {
    set leadSpace [leadSpace $l]
    expr {$leadSpace > 0 && $leadSpace >= 2*[tailSpace $l]}
}
proc tailSpaceMore {l} {
    set tailSpace [tailSpace $l]
    expr {$tailSpace > 0 && $tailSpace >= 2*[leadSpace $l]}
}
proc spaceEqual {l} {
    # 1 if lead and tail space shared (diff of 1 at most) and more than 0
    set leadSpace [leadSpace $l]
    set tailSpace [tailSpace $l]
    if {$leadSpace == 0 && $tailSpace == 0} {
	# At least one must be positive
	return 0
    }
    set diff [expr {$leadSpace - $tailSpace}]
    return [expr {$diff >= -1 && $diff <= 1}]
}
proc storeAddress {l} {
    return [describe $l store memoryAddress]
}
proc sameStore {l1 l2} {
    expr {[storeAddress $l1] == [storeAddress $l2]}
}
proc hasSpan {l args} {
    # Returns 1 if list has a span. If args are specified, they are checked with
    # span values (start and length)
    array set rep [describe $l]
    if {![info exists rep(span)]} {
	return 0
    }
    if {[llength $args] == 0} {
	return 1; # No need to check values
    }
    lassign $args start len
    if {[dict get $rep(span) spanStart] == $start &&
	[dict get $rep(span) spanLength] == $len} {
	return 1
    }
    return 0
}
proc checkListrep {l listLen numAllocated leadSpace tailSpace {refCount 0}} {
    # Checks if the internal representation of $l match
    # passed arguments. Return "" if yes, else error messages.
    array set rep [testlistrep describe $l]

    set rep(leadSpace) [dict get $rep(store) firstUsed]
    set rep(numAllocated) [dict get $rep(store) numAllocated]
    set rep(tailSpace) [expr {
			      $rep(numAllocated) - ($rep(leadSpace) + [dict get $rep(store) numUsed])
			  }]
    set rep(refCount) [dict get $rep(store) refCount]

    if {[info exists rep(span)]} {
	set rep(listLen) [dict get $rep(span) spanLength]
    } else {
	set rep(listLen) [dict get $rep(store) numUsed]
    }

    set errors [list]
    foreach arg {listLen numAllocated leadSpace tailSpace} {
	if {$rep($arg) != [set $arg]} {
	    lappend errors "$arg in list representation ($rep($arg)) is not expected value ([set $arg])."
	}
    }
    # Check refCount only if caller has specified it as non-0
    if {$refCount && $refCount != $rep(refCount)} {
	lappend errors "refCount in list representation ($rep(refCount)) is not expected value ($refCount)."
    }
    return $errors
}

proc assertListrep {l listLen numAllocated leadSpace tailSpace {refCount 0}} {
    # Like check_listrep but raises error
    set errors [checkListrep $l $listLen $numAllocated $leadSpace $tailSpace $refCount]
    if {[llength $errors]} {
	error [join $errors \n]
    }
    return
}

# The default length should be large enough that doubling the allocation will
# clearly distinguish free space allocation difference between front and back.
# (difference in the two should at least be 2 else we cannot tell if front
# or back was favored appropriately)
proc freeSpaceNone {{len 8}} {return [testlistrep new $len 0 0]}
proc freeSpaceLead {{len 8} {lead 3}} {return [testlistrep new $len $lead 0]}
proc freeSpaceTail {{len 8} {tail 3}} {return [testlistrep new $len 0 $tail]}
proc freeSpaceBoth {{len 8} {lead 3} {tail 3}} {
    return [testlistrep new $len $lead $tail]
}
proc zombieSample {{len 1000} {leadzombies 100} {tailzombies 100}} {
    # returns an unshared listrep with zombies in front and back

    # don't combine freespacenone and lrange else zombies are freed
    set l [freeSpaceNone [expr {$len+$leadzombies+$tailzombies}]]
    return [lrange $l $leadzombies [expr {$leadzombies+$len-1}]]
}

# Just ensure above stubs return what's expected
if {[testConstraint testlistrep]} {
    assertListrep [freeSpaceNone] 8 8 0 0 1
    assertListrep [freeSpaceLead] 8 11 3 0 1
    assertListrep [freeSpaceTail] 8 11 0 3 1
    assertListrep [freeSpaceBoth] 8 14 3 3 1
    assertListrep [zombieSample] 1000 1200 0 0 1
    if {![hasSpan [zombieSample]] || [dict get [testlistrep describe [zombieSample]] span spanStart] == 0} {
	error "zombieSample span missing or span start is at 0."
    }
}

# Define some variables for some indices because the Tcl compiler will do some
# operations completely in byte code if indices are literals
set zero 0
set one 1
set two 2
set four 4
set end end

#
# Test sets:
# 1.* - unshared internal rep, no spans, with no free space
# 2.* - shared internal rep, no spans, with no free space
# 3.* - unshared internal rep, spanned
# 4.* - shared internal rep, spanned
# 5.* - shared Tcl_Obj
# 6.* - lists with zombie Tcl_Obj's

#
# listrep-1.* tests all operate on unshared listreps with no free space

test listrep-1.1 {
    Inserts in front of unshared list with no free space should reallocate with
    equal free space at front and back -- linsert version
} -constraints testlistrep -body {
    set l [linsert [freeSpaceNone] $zero 99]
    validate $l
    list $l [spaceEqual $l]
} -result [list {99 0 1 2 3 4 5 6 7} 1]

test listrep-1.1.1 {
    Inserts in front of unshared list with no free space should reallocate with
    equal free space at front and back -- lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceNone] $zero -1 99]
    validate $l
    list $l [spaceEqual $l]
} -result [list {99 0 1 2 3 4 5 6 7} 1]

test listrep-1.2 {
    Inserts at back of unshared list with no free space should allocate all
    space at back -- linsert version
} -constraints testlistrep -body {
    set l [linsert [freeSpaceNone] $end 99]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 3 4 5 6 7 99} 0 4]

test listrep-1.2.1 {
    Inserts at back of unshared list with no free space should allocate all
    space at back -- lset version
} -constraints testlistrep -body {
    set l [freeSpaceNone]
    lset l $end+1 99
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 3 4 5 6 7 99} 0 4]

test listrep-1.2.2 {
    Inserts at back of unshared list with no free space should allocate all
    space at back -- lappend version
} -constraints testlistrep -body {
    set l [freeSpaceNone]
    lappend l 99
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 3 4 5 6 7 99} 0 4]

test listrep-1.3 {
    Inserts in middle of unshared list with no free space should reallocate with
    equal free space at front and back - linsert version
} -constraints testlistrep -body {
    set l [linsert [freeSpaceNone] $four 99]
    validate $l
    list $l [spaceEqual $l]
} -result [list {0 1 2 3 99 4 5 6 7} 1]

test listrep-1.3.1 {
    Inserts in middle of unshared list with no free space should reallocate with
    equal free space at front and back - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceNone] $four $four-1 99]
    validate $l
    list $l [spaceEqual $l]
} -result [list {0 1 2 3 99 4 5 6 7} 1]

test listrep-1.4 {
    Deletes from front of small unshared list with no free space should
    just shift up leaving room at back - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceNone] $zero $zero]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {1 2 3 4 5 6 7} 0 1]

test listrep-1.4.1 {
    Deletes from front of small unshared list with no free space should
    just shift up leaving room at back - lassign version
} -constraints testlistrep -body {
    set l [lassign [freeSpaceNone] e]
    validate $l
    list $e $l [leadSpace $l] [tailSpace $l]
} -result [list 0 {1 2 3 4 5 6 7} 0 1]

test listrep-1.4.2 {
    Deletes from front of small unshared list with no free space should
    just shift up leaving room at back - lpop version
} -constraints testlistrep -body {
    set l [freeSpaceNone]
    set e [lpop l $zero]
    validate $l
    list $e $l [leadSpace $l] [tailSpace $l]
} -result [list 0 {1 2 3 4 5 6 7} 0 1]

test listrep-1.4.3 {
    Deletes from front of small unshared list with no free space should
    just shift up leaving room at back - lrange version
} -constraints testlistrep -body {
    set l [lrange [freeSpaceNone] $one $end]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {1 2 3 4 5 6 7} 0 1]

test listrep-1.4.4 {
    Deletes from front of small unshared list with no free space should
    just shift up leaving room at back - lremove version
} -constraints testlistrep -body {
    set l [lremove [freeSpaceNone] $zero]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {1 2 3 4 5 6 7} 0 1]

test listrep-1.5 {
    Deletes from front of large unshared list with no free space should
    create a span - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceNone 1000] $zero $one]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 2 998]
} -result [list [irange 2 999] 2 0 1]

test listrep-1.5.1 {
    Deletes from front of large unshared list with no free space should
    create a span - lassign version
} -constraints testlistrep -body {
    set l [lassign [freeSpaceNone 1000] e]
    validate $l
    list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l 1 999]
} -result [list 0 [irange 1 999] 1 0 1]

test listrep-1.5.2 {
    Deletes from front of large unshared list with no free space should
    create a span - lrange version
} -constraints testlistrep -body {
    set l [lrange [freeSpaceNone 1000] $two end]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 2 998]
} -result [list [irange 2 999] 2 0 1]

test listrep-1.5.3 {
    Deletes from front of large unshared list with no free space should
    create a span - lremove version
} -constraints testlistrep -body {
    set l [lremove [freeSpaceNone 1000] $zero]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 1 999]
} -result [list [irange 1 999] 1 0 1]

test listrep-1.5.4 {
    Deletes from front of large unshared list with no free space should
    create a span - lpop version
} -constraints testlistrep -body {
    set l [freeSpaceNone 1000]
    set e [lpop l 0]
    validate $l
    list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l 1 999]
} -result [list 0 [irange 1 999] 1 0 1]

test listrep-1.6 {
    Deletes closer to front of large list should move (smaller) front segment
    -- lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceNone 1000] $four $four]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 1 999]
} -result [list [concat [irange 0 3] [irange 5 999]] 1 0 1]

test listrep-1.6.1 {
    Deletes closer to front of large list should move (smaller) front segment
    -- lpop version
} -constraints testlistrep -body {
    set l [freeSpaceNone 1000]
    set e [lpop l $four]
    validate $l
    list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l 1 999]
} -result [list 4 [concat [irange 0 3] [irange 5 999]] 1 0 1]

test listrep-1.7 {
    Deletes closer to back of large list should move (smaller) back segment
    and will not need a span - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceNone 1000] end-$four end-$four]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
} -result [list [concat [irange 0 994] [irange 996 999]] 0 1 0]

test listrep-1.7.1 {
    Deletes closer to back of large list should move (smaller) back segment
    and will not need a span - lpop version
} -constraints testlistrep -body {
    set l [freeSpaceNone 1000]
    set e [lpop l $end-4]
    validate $l
    list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
} -result [list 995 [concat [irange 0 994] [irange 996 999]] 0 1 0]

test listrep-1.8 {
    Deletes at back of small unshared list should not need a span - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceNone] end-$one end]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
} -result [list {0 1 2 3 4 5} 0 2 0]

test listrep-1.8.1 {
    Deletes at back of small unshared list should not need a span - lrange version
} -constraints testlistrep -body {
    set l [lrange [freeSpaceNone] $zero end-$two]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
} -result [list {0 1 2 3 4 5} 0 2 0]

test listrep-1.8.2 {
    Deletes at back of small unshared list should not need a span - lremove version
} -constraints testlistrep -body {
    set l [lremove [freeSpaceNone] $end-1 $end]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
} -result [list {0 1 2 3 4 5} 0 2 0]

test listrep-1.8.3 {
    Deletes at back of small unshared list should not need a span - lpop version
} -constraints testlistrep -body {
    set l [freeSpaceNone]
    set e [lpop l $end]
    validate $l
    list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
} -result [list 7 {0 1 2 3 4 5 6} 0 1 0]

test listrep-1.9 {
    Deletes at back of large unshared list should not need a span - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceNone 1000] end-$four end]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
} -result [list [irange 0 994] 0 5 0]

test listrep-1.9.1 {
    Deletes at back of large unshared list should not need a span - lrange version
} -constraints testlistrep -body {
    set l [lrange [freeSpaceNone 1000] 0 $end-5]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
} -result [list [irange 0 994] 0 5 0]

test listrep-1.9.2 {
    Deletes at back of large unshared list should not need a span - lremove version
} -constraints testlistrep -body {
    set l [lremove [freeSpaceNone 1000] end-$four $end-3 end-$two $end-1 $end]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
} -result [list [irange 0 994] 0 5 0]

test listrep-1.9.3 {
    Deletes at back of large unshared list should not need a span - lpop version
} -constraints testlistrep -body {
    set l [freeSpaceNone 1000]
    set e [lpop l $end]
    validate $l
    list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
} -result [list 999 [irange 0 998] 0 1 0]

test listrep-1.10 {
    no-op on unshared list should force a canonical list string - lreplace version
} -body {
    lreplace {    1 2   3 4   } $zero -1
} -result {1 2 3 4}

test listrep-1.10.1 {
    no-op on unshared list should force a canonical list string - lrange version
} -body {
    lrange {    1 2   3 4   } $zero $end
} -result {1 2 3 4}

test listrep-1.11 {
    Append elements to large unshared list is optimized as lappend
    so no free space in front - lreplace version
} -constraints testlistrep -body {
    # Note $end, not end else byte code compiler short-cuts
    set l [lreplace [freeSpaceNone 1000] $end+1 $end+1 1000]
    validate $l
    list $l [leadSpace $l] [expr {[tailSpace $l] > 0}] [hasSpan $l]
} -result [list [irange 0 1000] 0 1 0]

test listrep-1.11.1 {
    Append elements to large unshared list is optimized as lappend
    so no free space in front - linsert version
} -constraints testlistrep -body {
    # Note $end, not end else byte code compiler short-cuts
    set l [linsert [freeSpaceNone 1000] $end+1 1000]
    validate $l
    list $l [leadSpace $l] [expr {[tailSpace $l] > 0}] [hasSpan $l]
} -result [list [irange 0 1000] 0 1 0]

test listrep-1.11.2 {
    Append elements to large unshared list leaves no free space in front
    - lappend version
} -constraints testlistrep -body {
    # Note $end, not end else byte code compiler short-cuts
    set l [freeSpaceNone 1000]
    lappend l 1000 1001
    validate $l
    list $l [leadSpace $l] [expr {[tailSpace $l] > 0}] [hasSpan $l]
} -result [list [irange 0 1001] 0 1 0]


test listrep-1.12 {
    Replacement of elements at front with same number elements in unshared list
    is in-place - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceNone] $zero $one 10 11]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {10 11 2 3 4 5 6 7} 0 0]

test listrep-1.12.1 {
    Replacement of elements at front with same number elements in unshared list
    is in-place - lset version
} -constraints testlistrep -body {
    set l [freeSpaceNone]
    lset l 0 -1
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {-1 1 2 3 4 5 6 7} 0 0]

test listrep-1.13 {
    Replacement of elements at front with fewer elements in unshared list
    results in a spanned list with space only in front
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceNone] $zero $four 10]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {10 5 6 7} 4 0]

test listrep-1.14 {
    Replacement of elements at front with more elements in unshared list
    results in a reallocated spanned list with space at front and back
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceNone] $zero $one 10 11 12]
    validate $l
    list $l [spaceEqual $l]
} -result [list {10 11 12 2 3 4 5 6 7} 1]

test listrep-1.15 {
    Replacement of elements in middle with same number elements in unshared list
    is in-place - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceNone] $one $two 10 11]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 10 11 3 4 5 6 7} 0 0]

test listrep-1.15.1 {
    Replacement of elements in middle with same number elements in unshared list
    is in-place - lset version
} -constraints testlistrep -body {
    set l [freeSpaceNone]
    lset l $two -1
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 -1 3 4 5 6 7} 0 0]

test listrep-1.16 {
    Replacement of elements in front half with fewer elements in unshared list
    results in a spanned list with space only in front since smaller segment moved
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceNone] $one $four 10]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 10 5 6 7} 3 0]

test listrep-1.17 {
    Replacement of elements in back half with fewer elements in unshared list
    results in a spanned list with space only at back
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceNone] end-$four end-$one 10]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 10 7} 0 3]

test listrep-1.18 {
    Replacement of elements in middle more elements in unshared list
    results in a reallocated spanned list with space at front and back
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceNone] $one $two 10 11 12]
    validate $l
    list $l [spaceEqual $l]
} -result [list {0 10 11 12 3 4 5 6 7} 1]

test listrep-1.19 {
    Replacement of elements at back with same number elements in unshared list
    is in-place - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceNone] $end-1 $end 10 11]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 3 4 5 10 11} 0 0]

test listrep-1.19.1 {
    Replacement of elements at back with same number elements in unshared list
    is in-place - lset version
} -constraints testlistrep -body {
    set l [freeSpaceNone]
    lset l $end 10
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 3 4 5 6 10} 0 0]

test listrep-1.20 {
    Replacement of elements at back with fewer elements in unshared list
    is in-place with space only at the back
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceNone] $end-2 $end 10]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 3 4 10} 0 2]

test listrep-1.21 {
    Replacement of elements at back with more elements in unshared list
    allocates new representation with equal space at front and back
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceNone] $end-1 $end 10 11 12]
    validate $l
    list $l [spaceEqual $l]
} -result [list {0 1 2 3 4 5 10 11 12} 1]

#
# listrep-2.* tests all operate on shared list reps with no free space. Note the
# *list internal rep* must be shared, not only the Tcl_Obj so just assigning to
# another variable does not suffice. The lrange construct on an variable's value
# will do the needful.

test listrep-2.1 {
    Inserts in front of shared list with no free space should reallocate with
    more leading space in front - linsert version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [linsert $b $zero 99]
    validate $l
    list [repStoreRefCount $b] $l [leadSpaceMore $l] [repStoreRefCount $l]
} -result [list 2 {99 0 1 2 3 4 5 6 7} 1 1]

test listrep-2.1.1 {
    Inserts in front of shared list with no free space should reallocate with
    more leading space in front - lreplace version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lreplace $b $zero -1 99]
    validate $l
    list [repStoreRefCount $b] $l [leadSpaceMore $l] [repStoreRefCount $l]
} -result [list 2 {99 0 1 2 3 4 5 6 7} 1 1]

test listrep-2.2 {
    Inserts at back of shared list with no free space should reallocate with
    more leading space in back - linsert version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [linsert $b $end 99]
    validate $l
    list [repStoreRefCount $b] $l [tailSpaceMore $l] [repStoreRefCount $l]
} -result [list 2 {0 1 2 3 4 5 6 7 99} 1 1]

test listrep-2.2.1 {
    Inserts at back of shared list with no free space should reallocate with
    more leading space in back - lreplace version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lreplace $b $end+1 end+$one 99]
    validate $l
    list [repStoreRefCount $b] $l [tailSpaceMore $l] [repStoreRefCount $l]
} -result [list 2 {0 1 2 3 4 5 6 7 99} 1 1]

test listrep-2.2.2 {
    Inserts at back of shared list with no free space should reallocate with
    more leading space in back - lappend version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lappend b 99]
    validate $l
    list [repStoreRefCount $b] $l [tailSpaceMore $l] [repStoreRefCount $l]
} -result [list 1 {0 1 2 3 4 5 6 7 99} 1 1]

test listrep-2.2.3 {
    Inserts at back of shared list with no free space should reallocate with
    more leading space in back - lset version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lset b $end+1 99]
    validate $l
    list [repStoreRefCount $b] $l [tailSpaceMore $l] [repStoreRefCount $l]
} -result [list 1 {0 1 2 3 4 5 6 7 99} 1 1]

test listrep-2.3 {
    Inserts in middle of shared list with no free space should reallocate with
    equal spacing - linsert version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [linsert $b $four 99]
    validate $l
    list [repStoreRefCount $b] $l [spaceEqual $l] [repStoreRefCount $l]
} -result [list 2 {0 1 2 3 99 4 5 6 7} 1 1]

test listrep-2.3.1 {
    Inserts in middle of shared list with no free space should reallocate with
    equal spacing - lreplace version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lreplace $b $four $four-1 99]
    validate $l
    list [repStoreRefCount $b] $l [spaceEqual $l] [repStoreRefCount $l]
} -result [list 2 {0 1 2 3 99 4 5 6 7} 1 1]

test listrep-2.4 {
    Deletes from front of small shared list with no free space should
    allocate new list of exact size - lreplace version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lreplace $b $zero $zero]
    validate $l
    list [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 2 {1 2 3 4 5 6 7} 0 0 1]

test listrep-2.4.1 {
    Deletes from front of small shared list with no free space should
    allocate new list of exact size - lremove version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lremove $b $zero $one]
    validate $l
    list [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 2 {2 3 4 5 6 7} 0 0 1]

test listrep-2.4.2 {
    Deletes from front of small shared list with no free space should
    allocate new list of exact size - lrange version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lrange $b $one $end]
    validate $l
    list [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 2 {1 2 3 4 5 6 7} 0 0 1]

test listrep-2.4.3 {
    Deletes from front of small shared list with no free space should
    allocate new list of exact size - lassign version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lassign $b e]
    validate $l
    list $e [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 0 2 {1 2 3 4 5 6 7} 0 0 1]

test listrep-2.4.4 {
    Deletes from front of small shared list with no free space should
    allocate new list of exact size - lpop version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set l [lrange $a $zero end]; # Ensure shared listrep
    set e [lpop l $zero]
    validate $l
    list $e $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 0 {1 2 3 4 5 6 7} 0 0 1]

test listrep-2.5 {
    Deletes from front of large shared list with no free space should
    create span - lreplace version
} -constraints testlistrep -body {
    set a [freeSpaceNone 1000]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lreplace $b $zero $zero]
    validate $l
    # The listrep store should be shared among a, b, l (3 refs)
    list [sameStore $b $l] [repStoreRefCount $b] $l [hasSpan $l] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 1 3 [irange 1 999] 1 0 0 3]

test listrep-2.5.1 {
    Deletes from front of large shared list with no free space should
    create span - lremove version
} -constraints testlistrep -body {
    set a [freeSpaceNone 1000]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lremove $b $zero $one]
    validate $l
    # The listrep store should be shared among a, b, l (3 refs)
    list [sameStore $b $l] [repStoreRefCount $b] $l [hasSpan $l] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 1 3 [irange 2 999] 1 0 0 3]

test listrep-2.5.2 {
    Deletes from front of large shared list with no free space should
    create span - lrange version
} -constraints testlistrep -body {
    set a [freeSpaceNone 1000]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lrange $b $two $end]
    validate $l
    # The listrep store should be shared among a, b, l (3 refs)
    list [sameStore $b $l] [repStoreRefCount $b] $l [hasSpan $l] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 1 3 [irange 2 999] 1 0 0 3]

test listrep-2.5.3 {
    Deletes from front of large shared list with no free space should
    create span - lassign version
} -constraints testlistrep -body {
    set a [freeSpaceNone 1000]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lassign $b e]
    validate $l
    # The listrep store should be shared among a, b, l (3 refs)
    list $e [sameStore $b $l] [repStoreRefCount $b] $l [hasSpan $l] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 0 1 3 [irange 1 999] 1 0 0 3]

test listrep-2.5.4 {
    Deletes from front of large shared list with no free space should
    create span - lpop version
} -constraints testlistrep -body {
    set a [freeSpaceNone 1000]
    set l [lrange $a $zero end]; # Ensure shared listrep
    set e [lpop l $zero]
    validate $l
    # The listrep store should be shared among a, b, l (3 refs)
    list $e $l [hasSpan $l] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 0 [irange 1 999] 1 0 0 2]

test listrep-2.6 {
    Deletes from back of small shared list with no free space should
    allocate new list of exact size - lreplace version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lreplace $b $end $end]
    validate $l
    list [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 2 {0 1 2 3 4 5 6} 0 0 1]

test listrep-2.6.1 {
    Deletes from back of small shared list with no free space should
    allocate new list of exact size - lremove version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lremove $b $end $end-1]
    validate $l
    list [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 2 {0 1 2 3 4 5} 0 0 1]

test listrep-2.6.2 {
    Deletes from back of small shared list with no free space should
    allocate new list of exact size - lrange version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lrange $b $zero $end-1]
    validate $l
    list [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 2 {0 1 2 3 4 5 6} 0 0 1]

test listrep-2.6.3 {
    Deletes from back of small shared list with no free space should
    allocate new list of exact size - lpop version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set l [lrange $a $zero end]; # Ensure shared listrep
    set e [lpop l]
    validate $l
    list $e $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 7 {0 1 2 3 4 5 6} 0 0 1]

test listrep-2.7 {
    Deletes from back of large shared list with no free space should
    use a span - lreplace version
} -constraints testlistrep -body {
    set a [freeSpaceNone 1000]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lreplace $b $end $end]
    validate $l
    # Note lead and tail space is 0 because original list store in a,b is used
    list [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 3 [irange 0 998] 0 0 3]

test listrep-2.7.1 {
    Deletes from back of large shared list with no free space should
    use a span - lremove version
} -constraints testlistrep -body {
    set a [freeSpaceNone 1000]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lremove $b $end-1 $end]
    validate $l
    # Note lead and tail space is 0 because original list store in a,b is used
    list [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 3 [irange 0 997] 0 0 3]

test listrep-2.7.2 {
    Deletes from back of large shared list with no free space should
    use a span - lrange version
} -constraints testlistrep -body {
    set a [freeSpaceNone 1000]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lrange $b $zero $end-1]
    validate $l
    # Note lead and tail space is 0 because original list store in a,b is used
    list [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 3 [irange 0 998] 0 0 3]

test listrep-2.7.3 {
    Deletes from back of large shared list with no free space should
    use a span - lpop version
} -constraints testlistrep -body {
    set a [freeSpaceNone 1000]
    set l [lrange $a $zero end]; # Ensure shared listrep
    set e [lpop l]
    validate $l
    # Note lead and tail space is 0 because original list store in a,b is used
    list $e $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 999 [irange 0 998] 0 0 2]

test listrep-2.8 {
    no-op on shared list should force a canonical list representation
    with original unchanged - lreplace version
} -body {
    set l {     1 2   3 4   }
    list [lreplace $l $zero -1] $l
} -result [list {1 2 3 4} {     1 2   3 4   }]

test listrep-2.8.1 {
    no-op on shared list should force a canonical list representation
    with original unchanged - lrange version
} -body {
    set l {     1 2   3 4   }
    list [lrange $l $zero end] $l
} -result [list {1 2 3 4} {     1 2   3 4   }]

test listrep-2.9 {
    Appends to back of large shared list with no free space allocates new
    list with space only at the back - lreplace version
} -constraints testlistrep -body {
    set a [freeSpaceNone 1000]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lreplace $b $end+1 $end+1 1000]
    validate $l
    list [repStoreRefCount $b] $l [leadSpace $l] [expr {[tailSpace $l]>0}] [repStoreRefCount $l]
} -result [list 2 [irange 0 1000] 0 1 1]

test listrep-2.9.1 {
    Appends to back of large shared list with no free space allocates new
    list with space only at the back - linsert version
} -constraints testlistrep -body {
    set a [freeSpaceNone 1000]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [linsert $b $end+1 1000 1001]
    validate $l
    list [repStoreRefCount $b] $l [leadSpace $l] [expr {[tailSpace $l]>0}] [repStoreRefCount $l]
} -result [list 2 [irange 0 1001] 0 1 1]

test listrep-2.9.2 {
    Appends to back of large shared list with no free space allocates new
    list with space only at the back - lappend version
} -constraints testlistrep -body {
    set a [freeSpaceNone 1000]
    set l [lrange $a $zero end]; # Ensure shared listrep
    lappend l 1000
    validate $l
    list $l [leadSpace $l] [expr {[tailSpace $l]>0}] [repStoreRefCount $l]
} -result [list [irange 0 1000] 0 1 1]

test listrep-2.9.3 {
    Appends to back of large shared list with no free space allocates new
    list with space only at the back - lset version
} -constraints testlistrep -body {
    set a [freeSpaceNone 1000]
    set l [lrange $a $zero end]; # Ensure shared listrep
    lset l $end+1 1000
    validate $l
    list $l [leadSpace $l] [expr {[tailSpace $l]>0}] [repStoreRefCount $l]
} -result [list [irange 0 1000] 0 1 1]

test listrep-2.10 {
    Replacement of elements at front with same number in shared list results
    in a new list store with more space in front than back - lreplace version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lreplace $b $zero $one 10 11]
    validate $l
    list [repStoreRefCount $b] $l [leadSpaceMore $l] [repStoreRefCount $l]
} -result [list 2 {10 11 2 3 4 5 6 7} 1 1]

test listrep-2.10.1 {
    Replacement of elements at front with same number in shared list results
    in a new list store with no extra space - lset version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set l [lrange $a $zero end]; # Ensure shared listrep
    lset l $zero 10
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {10 1 2 3 4 5 6 7} 0 0 1]

test listrep-2.11 {
    Replacement of elements at front with fewer elements in shared list
    results in a new list store with more space in front than back
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lreplace $b $zero $four 10]
    validate $l
    list [repStoreRefCount $b] $l [leadSpaceMore $l] [repStoreRefCount $l]
} -result [list 2 {10 5 6 7} 1 1]

test listrep-2.12 {
    Replacement of elements at front with more elements in shared list
    results in a new spanned list with more space in front
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lreplace $b $zero $one 10 11 12]
    validate $l
    list [repStoreRefCount $b] $l [leadSpaceMore $l] [repStoreRefCount $l]
} -result [list 2 {10 11 12 2 3 4 5 6 7} 1 1]

test listrep-2.13 {
    Replacement of elements in middle with same number in shared list results
    in a new list store with equal space in front and back - lreplace version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lreplace $b $one $two 10 11]
    validate $l
    list [repStoreRefCount $b] $l [spaceEqual $l] [repStoreRefCount $l]
} -result [list 2 {0 10 11 3 4 5 6 7} 1 1]

test listrep-2.13.1 {
    Replacement of elements in middle with same number in shared list results
    in a new list store with exact allocation - lset version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set l [lrange $a $zero end]; # Ensure shared listrep
    lset l $one 10
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 10 2 3 4 5 6 7} 0 0 1]

test listrep-2.14 {
    Replacement of elements in middle with fewer elements in shared list
    results in a new list store with equal space
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lreplace $b $one 5 10]
    validate $l
    list [repStoreRefCount $b] $l [spaceEqual $l] [repStoreRefCount $l]
} -result [list 2 {0 10 6 7} 1 1]

test listrep-2.15 {
    Replacement of elements in middle with more elements in shared list
    results in a new spanned list with space in front and back
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lreplace $b $one $two 10 11 12]
    validate $l
    list [repStoreRefCount $b] $l [spaceEqual $l] [repStoreRefCount $l]
} -result [list 2 {0 10 11 12 3 4 5 6 7} 1 1]

test listrep-2.16 {
    Replacement of elements at back with same number in shared list results
    in a new list store with more space in back than front - lreplace version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lreplace $b end-$one $end 10 11]
    validate $l
    list [repStoreRefCount $b] $l [tailSpaceMore $l] [repStoreRefCount $l]
} -result [list 2 {0 1 2 3 4 5 10 11} 1 1]

test listrep-2.16.1 {
    Replacement of elements at back with same number in shared list results
    in a new list store with no extra - lreplace version
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set l [lrange $a $zero end]; # Ensure shared listrep
    lset l $end 10
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 1 2 3 4 5 6 10} 0 0 1]

test listrep-2.17 {
    Replacement of elements at back with fewer elements in shared list
    results in a new list store with more space in back than front
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lreplace $b end-$four $end 10]
    validate $l
    list [repStoreRefCount $b] $l [tailSpaceMore $l] [repStoreRefCount $l]
} -result [list 2 {0 1 2 10} 1 1]

test listrep-2.18 {
    Replacement of elements at back with more elements in shared list
    results in a new list store with more space in back than front
} -constraints testlistrep -body {
    set a [freeSpaceNone]
    set b [lrange $a $zero end]; # Ensure shared listrep
    set l [lreplace $b end-$four $end 10]
    validate $l
    list [repStoreRefCount $b] $l [tailSpaceMore $l] [repStoreRefCount $l]
} -result [list 2 {0 1 2 10} 1 1]

#
# listrep-3.* - tests on unshared spanned listreps

test listrep-3.1 {
    Inserts in front of unshared spanned list with room in front should just
    shrink the lead space - linsert version
} -constraints testlistrep -body {
    set l [linsert [freeSpaceBoth] $zero -2 -1]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange -2 7] 1 3 1]

test listrep-3.1.1 {
    Inserts in front of unshared spanned list with room in front should just
    shrink the lead space - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth] $zero -1 -2 -1]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange -2 7] 1 3 1]

test listrep-3.2 {
    Inserts in front of unshared spanned list with insufficient room in front
    but enough total freespace should redistribute free space - linsert version
} -constraints testlistrep -body {
    set l [linsert [freeSpaceBoth 8 1 10] $zero -2 -1]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange -2 7] 5 4 1]

test listrep-3.2.1 {
    Inserts in front of unshared spanned list with insufficient room in front
    but enough total freespace should redistribute free space - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 8 1 10] $zero -1 -2 -1]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange -2 7] 5 4 1]

test listrep-3.3 {
    Inserts in front of unshared spanned list with insufficient total freespace
    should reallocate with equal free space - linsert version
} -constraints testlistrep -body {
    set l [linsert [freeSpaceBoth 8 1 1] $zero -3 -2 -1]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange -3 7] 3 2 1]

test listrep-3.3.1 {
    Inserts in front of unshared spanned list with insufficient total freespace
    should reallocate with equal free space - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 8 1 1] $zero -1 -3 -2 -1]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange -3 7] 3 2 1]

test listrep-3.4 {
    Inserts at back of unshared spanned list with room at back should not
    reallocate - linsert version
} -constraints testlistrep -body {
    set l [linsert [freeSpaceBoth] $end 8]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 0 8] 3 2 1]

test listrep-3.4.1 {
    Inserts at back of unshared spanned list with room at back should not
    reallocate - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth] $end+1 $end+1 8 9]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 0 9] 3 1 1]

test listrep-3.4.2 {
    Inserts at back of unshared spanned list with room at back should not
    reallocate - lappend version
} -constraints testlistrep -body {
    set l [freeSpaceBoth]
    lappend l 8 9 10
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 0 10] 3 0 1]

test listrep-3.4.3 {
    Inserts at back of unshared spanned list with room at back should not
    reallocate - lset version
} -constraints testlistrep -body {
    set l [freeSpaceBoth]
    lset l $end+1 8
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 0 8] 3 2 1]

test listrep-3.5 {
    Inserts at back of unshared spanned list with insufficient room in back
    but enough total freespace should redistribute free space - linsert version
} -constraints testlistrep -body {
    set l [linsert [freeSpaceBoth 8 10 1] $end 8 9]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 0 9] 5 4 1]

test listrep-3.5.1 {
    Inserts at back of unshared spanned list with insufficient room in back
    but enough total freespace should redistribute free space - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 8 10 1] $end+1 $end+1 8 9]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 0 9] 5 4 1]

test listrep-3.5.2 {
    Inserts at back of unshared spanned list with insufficient room in back
    but enough total freespace should redistribute free space - lappend version
} -constraints testlistrep -body {
    set l [freeSpaceBoth 8 10 1]
    lappend l 8 9
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 0 9] 5 4 1]

test listrep-3.5.3 {
    Inserts at back of unshared spanned list with insufficient room in back
    but enough total freespace should redistribute free space - lset version
} -constraints testlistrep -body {
    set l [freeSpaceBoth 8 10 0]
    lset l $end+1 8
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 0 8] 5 4 1]

test listrep-3.6 {
    Inserts in back of unshared spanned list with insufficient total freespace
    should reallocate with all *additional* space at back. Note this differs
    from the insert in front case because here we realloc(). - linsert version
} -constraints testlistrep -body {
    set l [linsert [freeSpaceBoth 8 1 1] $end 8 9 10]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 0 10] 1 4 1]

test listrep-3.6.1 {
    Inserts in back of unshared spanned list with insufficient total freespace
    should reallocate with all *additional* space at back. Note this differs
    from the insert in front case because here we realloc() - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 8 1 1] $end+1 $end+1 8 9 10]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 0 10] 1 4 1]

test listrep-3.6.2 {
    Inserts in back of unshared spanned list with insufficient total freespace
    should reallocate with all *additional* space at back. Note this differs
    from the insert in front case because here we realloc() - lappend version
} -constraints testlistrep -body {
    set l [freeSpaceBoth 8 1 1]
    lappend l 8 9 10
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 0 10] 1 4 1]

test listrep-3.6.3 {
    Inserts in back of unshared spanned list with insufficient total freespace
    should reallocate with all *additional* space at back. Note this differs
    from the insert in front case because here we realloc() - lset version
} -constraints testlistrep -body {
    set l [freeSpaceNone]
    lset l $end+1 8
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 0 8] 0 4 1]

test listrep-3.7 {
    Inserts in front half of unshared spanned list with room in front should not
    reallocate and should move front segment
} -constraints testlistrep -body {
    set l [linsert [freeSpaceBoth] $one -2 -1]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 -2 -1 1 2 3 4 5 6 7} 1 3 1]

test listrep-3.8 {
    Inserts in front half of unshared spanned list with insufficient leading
    space but with enough tail space - linsert version
} -constraints testlistrep -body {
    set l [linsert [freeSpaceBoth 8 1 5] $one -2 -1]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 -2 -1 1 2 3 4 5 6 7} 1 3 1]

test listrep-3.8.1 {
    Inserts in front half of unshared spanned list with insufficient leading
    space but with enough tail space - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 8 1 5] $one -1 -2 -1]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 -2 -1 1 2 3 4 5 6 7} 1 3 1]

test listrep-3.9 {
    Inserts in front half of unshared spanned list with sufficient total
    free space - linsert version
} -constraints testlistrep -body {
    set l [linsert [freeSpaceBoth 8 2 2] $one -3 -2 -1]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 -3 -2 -1 1 2 3 4 5 6 7} 0 1 1]

test listrep-3.9.1 {
    Inserts in front half of unshared spanned list with sufficient total
    free space - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 8 2 2] $one -1 -3 -2 -1]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 -3 -2 -1 1 2 3 4 5 6 7} 0 1 1]

test listrep-3.10 {
    Inserts in front half of unshared spanned list with insufficient total space.
    Note use of realloc() means new space will be at the back - linsert version
} -constraints testlistrep -body {
    set l [linsert [freeSpaceBoth 8 1 1] $one -3 -2 -1]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 -3 -2 -1 1 2 3 4 5 6 7} 1 4 1]

test listrep-3.10.1 {
    Inserts in front half of unshared spanned list with insufficient total space.
    Note use of realloc() means new space will be at the back - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 8 1 1] $one -1 -3 -2 -1]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 -3 -2 -1 1 2 3 4 5 6 7} 1 4 1]

test listrep-3.11 {
    Inserts in back half of unshared spanned list with room in back should not
    reallocate and should move back segment - linsert version
} -constraints testlistrep -body {
    set l [linsert [freeSpaceBoth] $end-$one 8 9]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 1 2 3 4 5 6 8 9 7} 3 1 1]

test listrep-3.11.1 {
    Inserts in back half of unshared spanned list with room in back should not
    reallocate and should move back segment - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth] $end -1 8 9]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 1 2 3 4 5 6 8 9 7} 3 1 1]

test listrep-3.12 {
    Inserts in back half of unshared spanned list with insufficient tail
    space but with enough leading space - linsert version
} -constraints testlistrep -body {
    set l [linsert [freeSpaceBoth 8 5 1] $end-$one 8 9]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 1 2 3 4 5 6 8 9 7} 3 1 1]

test listrep-3.12.1 {
    Inserts in back half of unshared spanned list with insufficient tail
    space but with enough leading space - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 8 5 1] $end -1 8 9]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 1 2 3 4 5 6 8 9 7} 3 1 1]

test listrep-3.13 {
    Inserts in back half of unshared spanned list with sufficient total
    free space - linsert version
} -constraints testlistrep -body {
    set l [linsert [freeSpaceBoth 8 2 2] $end-$one 8 9 10]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 1 2 3 4 5 6 8 9 10 7} 0 1 1]

test listrep-3.13.1 {
    Inserts in back half of unshared spanned list with sufficient total
    free space - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 8 2 2] $end -1 8 9 10]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 1 2 3 4 5 6 8 9 10 7} 0 1 1]

test listrep-3.14 {
    Inserts in back half of unshared spanned list with insufficient
    total space. Note use of realloc() means new space will be at the
    back - linsert version
} -constraints testlistrep -body {
    set l [linsert [freeSpaceBoth 8 1 1] $end-$one 8 9 10]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 1 2 3 4 5 6 8 9 10 7} 1 4 1]

test listrep-3.14.1 {
    Inserts in back half of unshared spanned list with insufficient
    total space. Note use of realloc() means new space will be at the
    back - lrepalce version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 8 1 1] $end -1 8 9 10]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {0 1 2 3 4 5 6 8 9 10 7} 1 4 1]

test listrep-3.15 {
    Deletes from front of small unshared span list results in elements
    moved up front and span removal - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth] $zero $zero]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
} -result [list {1 2 3 4 5 6 7} 0 7 0]

test listrep-3.15.1 {
    Deletes from front of small unshared span list results in elements
    moved up front and span removal - lremove version
} -constraints testlistrep -body {
    set l [lremove [freeSpaceBoth] $zero $one]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
} -result [list {2 3 4 5 6 7} 0 8 0]

test listrep-3.15.2 {
    Deletes from front of small unshared span list results in elements
    moved up front and span removal - lrange version
} -constraints testlistrep -body {
    set l [lrange [freeSpaceBoth] $one $end]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
} -result [list {1 2 3 4 5 6 7} 0 7 0]

test listrep-3.15.3 {
    Deletes from front of small unshared span list results in elements
    moved up front and span removal - lassign version
} -constraints testlistrep -body {
    set l [lassign [freeSpaceBoth] e]
    validate $l
    list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
} -result [list 0 {1 2 3 4 5 6 7} 0 7 0]

test listrep-3.15.4 {
    Deletes from front of small unshared span list results in elements
    moved up front and span removal - lpop version
} -constraints testlistrep -body {
    set l [freeSpaceBoth]
    set e [lpop l $zero]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
} -result [list {1 2 3 4 5 6 7} 0 7 0]

test listrep-3.16 {
    Deletes from front of large unshared span list results in another
    span - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 1000 10 10] $zero $one]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 12 998]
} -result [list [irange 2 999] 12 10 1]

test listrep-3.16.1 {
    Deletes from front of large unshared span list results in another
    span - lremove version
} -constraints testlistrep -body {
    set l [lremove [freeSpaceBoth 1000 10 10] $zero $one]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 12 998]
} -result [list [irange 2 999] 12 10 1]

test listrep-3.16.2 {
    Deletes from front of large unshared span list results in another
    span - lrange version
} -constraints testlistrep -body {
    set l [lrange [freeSpaceBoth 1000 10 10] $two $end]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 12 998]
} -result [list [irange 2 999] 12 10 1]

test listrep-3.16.3 {
    Deletes from front of large unshared span list results in another
    span - lassign version
} -constraints testlistrep -body {
    set l [lassign [freeSpaceBoth 1000 10 10] e]
    validate $l
    list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l 11 999]
} -result [list 0 [irange 1 999] 11 10 1]

test listrep-3.16.4 {
    Deletes from front of large unshared span list results in another
    span - lpop version
} -constraints testlistrep -body {
    set l [freeSpaceBoth 1000 10 10]
    set e [lpop l $zero]
    validate $l
    list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l 11 999]
} -result [list 0 [irange 1 999] 11 10 1]

test listrep-3.17 {
    Deletes from back of small unshared span list results in new store
    without span - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth] $end $end]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
} -result [list {0 1 2 3 4 5 6} 0 7 0]

test listrep-3.17.1 {
    Deletes from back of small unshared span list results in new store
    without span - lremove version
} -constraints testlistrep -body {
    set l [lremove [freeSpaceBoth] $end]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
} -result [list {0 1 2 3 4 5 6} 0 7 0]

test listrep-3.17.2 {
    Deletes from back of small unshared span list results in new store
    without span - lrange version
} -constraints testlistrep -body {
    set l [lrange [freeSpaceBoth] $zero $end-1]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
} -result [list {0 1 2 3 4 5 6} 0 7 0]

test listrep-3.17.3 {
    Deletes from back of small unshared span list results in new store
    without span - lpop version
} -constraints testlistrep -body {
    set l [freeSpaceBoth]
    set e [lpop l]
    validate $l
    list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
} -result [list 7 {0 1 2 3 4 5 6} 0 7 0]

test listrep-3.18 {
    Deletes from back of large unshared span list results in another
    span - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 1000 10 10] $end-1 $end]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 10 998]
} -result [list [irange 0 997] 10 12 1]

test listrep-3.18.1 {
    Deletes from back of large unshared span list results in another
    span - lremove version
} -constraints testlistrep -body {
    set l [lremove [freeSpaceBoth 1000 10 10] $end-1 $end]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 10 998]
} -result [list [irange 0 997] 10 12 1]

test listrep-3.18.2 {
    Deletes from back of large unshared span list results in another
    span - lrange version
} -constraints testlistrep -body {
    set l [lrange [freeSpaceBoth 1000 10 10] $zero $end-2]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 10 998]
} -result [list [irange 0 997] 10 12 1]

test listrep-3.18.3 {
    Deletes from back of large unshared span list results in another
    span - lpop version
} -constraints testlistrep -body {
    set l [freeSpaceBoth 1000 10 10]
    set e [lpop l]
    validate $l
    list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l 10 999]
} -result [list 999 [irange 0 998] 10 11 1]

test listrep-3.19 {
    Deletes from front half of small unshared span list results in
    movement of smaller front segment - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth] $one $two]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 5 6]
} -result [list {0 3 4 5 6 7} 5 3 1]

test listrep-3.19.1 {
    Deletes from front half of small unshared span list results in
    movement of smaller front segment - lremove version
} -constraints testlistrep -body {
    set l [lremove [freeSpaceBoth] $one $two]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 5 6]
} -result [list {0 3 4 5 6 7} 5 3 1]

test listrep-3.20 {
    Deletes from front half of large unshared span list results in
    movement of smaller front segment - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 1000 10 10] $one $two]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 12 998]
} -result [list [list 0 {*}[irange 3 999]] 12 10 1]

test listrep-3.20.1 {
    Deletes from front half of large unshared span list results in
    movement of smaller front segment - lremove version
} -constraints testlistrep -body {
    set l [lremove [freeSpaceBoth 1000 10 10] $one $two]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 12 998]
} -result [list [list 0 {*}[irange 3 999]] 12 10 1]

test listrep-3.21 {
    Deletes from back half of small unshared span list results in
    movement of smaller back segment - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth] $end-2 $end-1]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 3 6]
} -result [list {0 1 2 3 4 7} 3 5 1]

test listrep-3.21.1 {
    Deletes from back half of small unshared span list results in
    movement of smaller back segment - lremove version
} -constraints testlistrep -body {
    set l [lremove [freeSpaceBoth] $end-2 $end-1]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 3 6]
} -result [list {0 1 2 3 4 7} 3 5 1]

test listrep-3.22 {
    Deletes from back half of large unshared span list results in
    movement of smaller back segment - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 1000 10 10] $end-2 $end-1]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 10 998]
} -result [list [list {*}[irange 0 996] 999] 10 12 1]

test listrep-3.22.1 {
    Deletes from back half of large unshared span list results in
    movement of smaller back segment - lremove version
} -constraints testlistrep -body {
    set l [lremove [freeSpaceBoth 1000 10 10] $end-2 $end-1]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 10 998]
} -result [list [list {*}[irange 0 996] 999] 10 12 1]

test listrep-3.23 {
    Replacement of elements at front with same number elements in unshared
    spanned list is in-place - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth] $zero $one 10 11]
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {10 11 2 3 4 5 6 7} 3 3]

test listrep-3.23.1 {
    Replacement of elements at front with same number elements in unshared
    spanned list is in-place - lset version
} -constraints testlistrep -body {
    set l [freeSpaceBoth]
    lset l $zero 10
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {10 1 2 3 4 5 6 7} 3 3]

test listrep-3.24 {
    Replacement of elements at front with fewer elements in unshared
    spanned list expands leading space - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth] $zero $four 10]
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {10 5 6 7} 7 3]

test listrep-3.25 {
    Replacement of elements at front with more elements in unshared
    spanned list with sufficient leading space shrinks leading space
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth] $zero $one 10 11 12]
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {10 11 12 2 3 4 5 6 7} 2 3]

test listrep-3.26 {
    Replacement of elements at front with more elements in unshared
    spanned list with insufficient leading space but sufficient total
    free space
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 8 1 10] $zero $one 10 11 12 13]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {10 11 12 13 2 3 4 5 6 7} 5 4 1]

test listrep-3.27 {
    Replacement of elements at front in unshared spanned list with insufficient
    total freespace should reallocate with equal free space
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 8 1 1] $zero $one 10 11 12 13 14]
    validate $l
    list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list {10 11 12 13 14 2 3 4 5 6 7} 3 2 1]

test listrep-3.28 {
    Replacement of elements at back with same number of elements in unshared
    spanned list is in-place - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth] $end-1 $end 10 11]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 3 4 5 10 11} 3 3]

test listrep-3.28.1 {
    Replacement of elements at back with same number of elements in unshared
    spanned list is in-place - lset version
} -constraints testlistrep -body {
    set l [freeSpaceBoth]
    lset l $end 10
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 3 4 5 6 10} 3 3]

test listrep-3.29 {
    Replacement of elements at back with fewer elements in unshared
    spanned list expands tail space
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth] $end-2 $end 10]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 3 4 10} 3 5]

test listrep-3.30 {
    Replacement of elements at back with more elements in unshared
    spanned list with sufficient tail space shrinks tailspace
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth] $end-1 $end 10 11 12]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 3 4 5 10 11 12} 3 2]

test listrep-3.31 {
    Replacement of elements at back with more elements in unshared spanned list
    with insufficient tail space but enough total free space moves up the span
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 8 2 2] $end-1 $end 10 11 12 13 14]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 3 4 5 10 11 12 13 14} 0 1]

test listrep-3.32 {
    Replacement of elements at back with more elements in unshared spanned list
    with insufficient total space reallocates with more room in the tail because
    of realloc()
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 8 1 1] $end-1 $end 10 11 12 13 14]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 3 4 5 10 11 12 13 14} 1 4]

test listrep-3.33 {
    Replacement of elements in the middle in an unshared spanned list with
    the same number of elements - lreplace version
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth] $two $four 10 11 12]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 10 11 12 5 6 7} 3 3]

test listrep-3.33.1 {
    Replacement of elements in the middle in an unshared spanned list with
    the same number of elements - lset version
} -constraints testlistrep -body {
    set l [freeSpaceBoth]
    lset l $two 10
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 10 3 4 5 6 7} 3 3]

test listrep-3.34 {
    Replacement of elements in an unshared spanned list with fewer elements
    in the front half moves the front (smaller) segment
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth] $two $four 10 11]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 10 11 5 6 7} 4 3]

test listrep-3.35 {
    Replacement of elements in an unshared spanned list with fewer elements
    in the back half moves the tail (smaller) segment
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth] $end-2 $end-1 10]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 3 4 10 7} 3 4]

test listrep-3.36 {
    Replacement of elements in an unshared spanned list with more elements
    when both front and back have room should move the smaller segment
    (front case)
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth] $one $two 8 9 10]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 8 9 10 3 4 5 6 7} 2 3]

test listrep-3.37 {
    Replacement of elements in an unshared spanned list with more elements
    when both front and back have room should move the smaller segment
    (back case)
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth] $end-2 $end-1 8 9 10]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 3 4 8 9 10 7} 3 2]

test listrep-3.38 {
    Replacement of elements in an unshared spanned list with more elements
    when only front has room
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 8 3 1] $end-1 $end-1 8 9 10]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 1 2 3 4 5 8 9 10 7} 1 1]

test listrep-3.39 {
    Replacement of elements in an unshared spanned list with more elements
    when only back has room
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 8 1 3] $one $one 8 9 10]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 8 9 10 2 3 4 5 6 7} 1 1]

test listrep-3.40 {
    Replacement of elements in an unshared spanned list with more elements
    when neither send has enough room by itself
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth] $one $one 8 9 10 11 12]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 8 9 10 11 12 2 3 4 5 6 7} 1 1]

test listrep-3.41 {
    Replacement of elements in an unshared spanned list with more elements
    when there is not enough free space results in new allocation. The back
    end has more space because of realloc()
} -constraints testlistrep -body {
    set l [lreplace [freeSpaceBoth 8 1 1] $one $one 8 9 10 11 12]
    validate $l
    list $l [leadSpace $l] [tailSpace $l]
} -result [list {0 8 9 10 11 12 2 3 4 5 6 7} 1 5]

#
# 4.* - tests on shared spanned lists

test listrep-4.1 {
    Inserts in front of shared spanned list with used elements in lead space
    creates new list rep with more lead than tail space - linsert version
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set l [linsert $spanl $zero -1]
    validate $l
    list $master $spanl $l [leadSpaceMore $l] [hasSpan $l] [repStoreRefCount $master] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 0 999] [irange 2 997] [list -1 {*}[irange 2 997]] 1 1 2 2 1]

test listrep-4.1.1 {
    Inserts in front of shared spanned list with used elements in lead space
    creates new list rep with more lead than tail space - lreplace version
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set l [lreplace $spanl $zero -1 -2]
    validate $l
    list $master $spanl $l [leadSpaceMore $l] [hasSpan $l] [repStoreRefCount $master] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 0 999] [irange 2 997] [list -2 {*}[irange 2 997]] 1 1 2 2 1]

test listrep-4.2 {
    Inserts in front of shared spanned list with orphaned leading elements
    allocate a new list rep with more lead than tail space - linsert version
    TODO - ideally this should garbage collect the orphans and reuse the lead space
    but that needs a "lprepend" command else the listrep operand is shared and hence
    orphans cannot be freed
} -constraints testlistrep -body {
    set master [freeSpaceLead 1000 100]
    set spanl [lrange $master $two $end-2]
    unset master; # So elements at 0, 1 are not used
    set l [linsert $spanl $zero -1]
    validate $l
    list $spanl $l [sameStore $spanl $l] [leadSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [list -1 {*}[irange 2 997]] 0 1 1 1 1]

test listrep-4.2.1 {
    Inserts in front of shared spanned list with orphaned leading elements
    allocate a new list rep with more lead than tail space - lreplace version
    TODO - ideally this should garbage collect the orphans and reuse the lead space
    but that needs a "lprepend" command else the listrep operand is shared and hence
    orphans cannot be freed
} -constraints testlistrep -body {
    set master [freeSpaceLead 1000 100]
    set spanl [lrange $master $two $end-2]
    unset master; # So elements at 0, 1 are not used
    set l [lreplace $spanl $zero -1 -2]
    validate $l
    list $spanl $l [sameStore $spanl $l] [leadSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [list -2 {*}[irange 2 997]] 0 1 1 1 1]

test listrep-4.3 {
    Inserts in front of shared spanned list where span is at front of used
    space reuses the same list store - linsert version
} -constraints testlistrep -body {
    set master [freeSpaceLead 1000 100]
    set spanl [lrange $master $zero $end-2]
    set l [linsert $spanl $zero -1]
    validate $l
    list $spanl $l [sameStore $spanl $l] [leadSpace $l] [tailSpace $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 0 997] [irange -1 997] 1 99 0 1 3 3]

test listrep-4.3.1 {
    Inserts in front of shared spanned list where span is at front of used
    space reuses the same list store - lreplace version
} -constraints testlistrep -body {
    set master [freeSpaceLead 1000 100]
    set spanl [lrange $master $zero $end-2]
    set l [lreplace $spanl $zero -1 -1]
    validate $l
    list $spanl $l [sameStore $spanl $l] [leadSpace $l] [tailSpace $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 0 997] [irange -1 997] 1 99 0 1 3 3]

test listrep-4.4 {
    Inserts in front of shared spanned list where span is at front of used
    space allocates new listrep if lead space insufficient even if total free space
    is sufficient. New listrep should have more lead space than tail space.
    - linsert version
} -constraints testlistrep -body {
    set master [freeSpaceBoth 1000 2]
    set spanl [lrange $master $zero $end-2]
    set l [linsert $spanl $zero -3 -2 -1]
    validate $l
    list $spanl $l [sameStore $spanl $l] [leadSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 0 997] [irange -3 997] 0 1 1 2 1]

test listrep-4.4.1 {
    Inserts in front of shared spanned list where span is at front of used
    space allocates new listrep if lead space insufficient even if total free space
    is sufficient. New listrep should have more lead space than tail space.
    - lreplace version
} -constraints testlistrep -body {
    set master [freeSpaceBoth 1000 2]
    set spanl [lrange $master $zero $end-2]
    set l [lreplace $spanl $zero -1 -3 -2 -1]
    validate $l
    list $spanl $l [sameStore $spanl $l] [leadSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 0 997] [irange -3 997] 0 1 1 2 1]

test listrep-4.5 {
    Inserts in back of shared spanned list where span is at end of used space
    still allocates a new listrep and trailing space is more than leading space
    - linsert version
} -constraints testlistrep -body {
    set master [freeSpaceBoth 1000 2]
    set spanl [lrange $master $two $end]
    set l [linsert $spanl $end 1000]
    validate $l
    list $spanl $l [sameStore $spanl $l] [tailSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 999] [irange 2 1000] 0 1 1 2 1]

test listrep-4.5.1 {
    Inserts in back of shared spanned list where span is at end of used space
    still allocates a new listrep and trailing space is more than leading space
    - lreplace version
} -constraints testlistrep -body {
    set master [freeSpaceBoth 1000 2]
    set spanl [lrange $master $two $end]
    set l [lreplace $spanl $end+1 $end+1 1000]
    validate $l
    list $spanl $l [sameStore $spanl $l] [tailSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 999] [irange 2 1000] 0 1 1 2 1]

test listrep-4.5.2 {
    Inserts in back of shared spanned list where span is at end of used space
    still allocates a new listrep and trailing space is more than leading space
    - lappend version
} -constraints testlistrep -body {
    set master [freeSpaceBoth 1000 2]
    set l [lrange $master $two $end]
    lappend l 1000
    validate $l
    list $l [sameStore $master $l] [tailSpaceMore $l] [hasSpan $l] [repStoreRefCount $l]
} -result [list  [irange 2 1000] 0 1 1 1]

test listrep-4.5.3 {
    Inserts in back of shared spanned list where span is at end of used space
    still allocates a new listrep and trailing space is more than leading space
    - lset version
} -constraints testlistrep -body {
    set master [freeSpaceBoth 1000 2]
    set l [lrange $master $two $end]
    lset l $end+1 1000
    validate $l
    list $l [sameStore $master $l] [tailSpaceMore $l] [hasSpan $l] [repStoreRefCount $l]
} -result [list  [irange 2 1000] 0 1 1 1]


test listrep-4.6 {
    Inserts in middle of shared spanned list allocates a new listrep with equal
    lead and tail space - linsert version
} -constraints testlistrep -body {
    set master [freeSpaceBoth 1000 2]
    set spanl [lrange $master $two $end-2]
    set i 200
    set l [linsert $spanl $i 1000]
    validate $l
    list $spanl $l [sameStore $spanl $l] [spaceEqual $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [concat [irange 2 201] 1000 [irange 202 997]] 0 1 1 2 1]

test listrep-4.6.1 {
    Inserts in middle of shared spanned list allocates a new listrep with equal
    lead and tail space - lreplace version
} -constraints testlistrep -body {
    set master [freeSpaceBoth 1000 2]
    set spanl [lrange $master $two $end-2]
    set i 200
    set l [lreplace $spanl $i -1 1000]
    validate $l
    list $spanl $l [sameStore $spanl $l] [spaceEqual $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [concat [irange 2 201] 1000 [irange 202 997]] 0 1 1 2 1]

test listrep-4.7 {
    Deletes from front of shared spanned list do not create a new allocation
    - lreplace version
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set l [lreplace $spanl $zero $one]
    validate $l
    list $spanl $l [sameStore $spanl $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [irange 4 997] 1 1 3 3]

test listrep-4.7.1 {
    Deletes from front of shared spanned list do not create a new allocation
    - lremove version
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set l [lremove $spanl $zero $one]
    validate $l
    list $spanl $l [sameStore $spanl $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [irange 4 997] 1 1 3 3]

test listrep-4.7.2 {
    Deletes from front of shared spanned list do not create a new allocation
    - lrange version
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set l [lrange $spanl $two $end]
    validate $l
    list $spanl $l [sameStore $spanl $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [irange 4 997] 1 1 3 3]

test listrep-4.7.3 {
    Deletes from front of shared spanned list do not create a new allocation
    - lassign version
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set l [lassign $spanl e]
    validate $l
    list $e $spanl $l [sameStore $spanl $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list 2 [irange 2 997] [irange 3 997] 1 1 3 3]

test listrep-4.7.4 {
    Deletes from front of shared spanned list do not create a new allocation
    - lpop version
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set l [lrange $master $two $end-2]
    set e [lpop l $zero]
    validate $l
    list $e $l [sameStore $master $l] [hasSpan $l] [repStoreRefCount $l]
} -result [list 2 [irange 3 997] 1 1 2]

test listrep-4.8 {
    Deletes from end of shared spanned list do not create a new allocation
    - lreplace version
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set l [lreplace $spanl $end-1 $end]
    validate $l
    list $spanl $l [sameStore $spanl $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [irange 2 995] 1 1 3 3]

test listrep-4.8.1 {
    Deletes from end of shared spanned list do not create a new allocation
    - lremove version
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set l [lremove $spanl $end-1 $end]
    validate $l
    list $spanl $l [sameStore $spanl $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [irange 2 995] 1 1 3 3]

test listrep-4.8.2 {
    Deletes from end of shared spanned list do not create a new allocation
    - lrange version
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set l [lrange $spanl 0 $end-2]
    validate $l
    list $spanl $l [sameStore $spanl $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [irange 2 995] 1 1 3 3]

test listrep-4.8.3 {
    Deletes from end of shared spanned list do not create a new allocation
    - lpop version
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set l [lrange $master $two $end-2]
    set e [lpop l]
    validate $l
    list $e $l [sameStore $master $l] [hasSpan $l] [repStoreRefCount $l]
} -result [list 997 [irange 2 996] 1 1 2]

test listrep-4.9 {
    Deletes from middle of shared spanned list creates a new allocation with
    equal free space at front and back - lreplace version
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set i 500
    set l [lreplace $spanl $i $i]
    validate $l
    list $spanl $l [sameStore $spanl $l] [hasSpan $l] [spaceEqual $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [concat [irange 2 501] [irange 503 997]] 0 1 1 2 1]

test listrep-4.9.1 {
    Deletes from middle of shared spanned list creates a new allocation with
    equal free space at front and back - lremove version
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set i 500
    set l [lremove $spanl $i $i]
    validate $l
    list $spanl $l [sameStore $spanl $l] [hasSpan $l] [spaceEqual $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [concat [irange 2 501] [irange 503 997]] 0 1 1 2 1]

test listrep-4.9.2 {
    Deletes from middle of shared spanned list creates a new allocation with
    equal free space at front and back - lpop version
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set l [lrange $master $two $end-2]
    set i 500
    set e [lpop l $i]
    validate $l
    list $e $l [sameStore $master $l] [hasSpan $l] [spaceEqual $l] [repStoreRefCount $l]
} -result [list 502 [concat [irange 2 501] [irange 503 997]] 0 1 1 1]

test listrep-4.10 {
    Replacements with same number of elements at front of shared spanned list
    create a new allocation with more space in front - lreplace version
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set l [lreplace $spanl $zero $one -2 -1]
    validate $l
    list $spanl $l [sameStore $spanl $l] [leadSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [concat {-2 -1} [irange 4 997]] 0 1 1 2 1]

test listrep-4.10.1 {
    Replacements with same number of elements at front of shared spanned list
    create a new allocation with exact size
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set l [lrange $master $two $end-2]
    lset l $zero -1
    validate $l
    list $l [sameStore $master $l] [hasSpan $l] [repStoreRefCount $l]
} -result [list [concat {-1} [irange 3 997]] 0 0 1]

test listrep-4.11 {
    Replacements with fewer elements at front of shared spanned list
    create a new allocation with more space in front
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set l [lreplace $spanl $zero $one -1]
    validate $l
    list $spanl $l [sameStore $spanl $l] [leadSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [concat {-1} [irange 4 997]] 0 1 1 2 1]

test listrep-4.12 {
    Replacements with more elements at front of shared spanned list
    create a new allocation with more space in front
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set l [lreplace $spanl $zero $one -3 -2 -1]
    validate $l
    list $spanl $l [sameStore $spanl $l] [leadSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [concat {-3 -2 -1} [irange 4 997]] 0 1 1 2 1]

test listrep-4.13 {
    Replacements with same number of elements at back of shared spanned list
    create a new allocation with more space in back - lreplace version
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set l [lreplace $spanl $end-1 $end 1000 1001]
    validate $l
    list $spanl $l [sameStore $spanl $l] [tailSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [concat [irange 2 995] {1000 1001}] 0 1 1 2 1]

test listrep-4.13.1 {
    Replacements with same number of elements at back of shared spanned list
    create a new exact allocation with no span - lset version
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set l [lrange $master $two $end-2]
    lset l $end 1000
    validate $l
    list $l [sameStore $master $l] [tailSpace $l] [hasSpan $l] [repStoreRefCount $l]
} -result [list [concat [irange 2 996] {1000}] 0 0 0 1]

test listrep-4.14 {
    Replacements with fewer elements at back of shared spanned list
    create a new allocation with more space in back
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set l [lreplace $spanl $end-1 $end 1000]
    validate $l
    list $spanl $l [sameStore $spanl $l] [tailSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [concat [irange 2 995] {1000}] 0 1 1 2 1]

test listrep-4.15 {
    Replacements with more elements at back of shared spanned list
    create a new allocation with more space in back
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set l [lreplace $spanl $end-1 $end 1000 1001 1002]
    validate $l
    list $spanl $l [sameStore $spanl $l] [tailSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [concat [irange 2 995] {1000 1001 1002}] 0 1 1 2 1]

test listrep-4.16 {
    Replacements with same number of elements in middle of shared spanned list
    create a new allocation with equal lead and tail sapce
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set l [lreplace $spanl $one $two -2 -1]
    validate $l
    list $spanl $l [sameStore $spanl $l] [spaceEqual $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [concat {2 -2 -1} [irange 5 997]] 0 1 1 2 1]

test listrep-4.16.1 {
    Replacements with same number of elements in middle of shared spanned list
    create a new exact allocation - lset version
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set l [lrange $master $two $end-2]
    lset l $one -2
    validate $l
    list $l [sameStore $master $l] [hasSpan $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [concat {2 -2} [irange 4 997]] 0 0 0 1]

test listrep-4.17 {
    Replacements with fewer elements in middle of shared spanned list
    create a new allocation with equal lead and tail sapce
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set l [lreplace $spanl $end-2 $end-1 1000]
    validate $l
    list $spanl $l [sameStore $spanl $l] [spaceEqual $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [concat [irange 2 994] {1000 997}] 0 1 1 2 1]

test listrep-4.18 {
    Replacements with more elements in middle of shared spanned list
    create a new allocation with equal lead and tail sapce
} -constraints testlistrep -body {
    set master [freeSpaceNone 1000]
    set spanl [lrange $master $two $end-2]
    set l [lreplace $spanl $end-2 $end-1 1000 1001 1002]
    validate $l
    list $spanl $l [sameStore $spanl $l] [spaceEqual $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
} -result [list [irange 2 997] [concat [irange 2 994] {1000 1001 1002 997}] 0 1 1 2 1]

# 5.* - tests on shared Tcl_Obj
# Tests when Tcl_Obj is shared but listrep is not. This is to ensure that
# checks for shared values check the Tcl_Obj reference counts in addition to
# the list internal representation reference counts. Probably some or all
# cases are already covered elsewhere but easier to just test than look.
test listrep-5.1 {
    Verify that operation on a shared Tcl_Obj with a single-ref, spanless
    list representation only modifies the target object - lappend version
} -constraints testlistrep -body {
    set l [freeSpaceNone]
    set l2 $l
    set same [sameStore $l $l2]
    lappend l 8
    list $same $l $l2 [sameStore $l $l2]
} -result [list 1 [irange 0 8] [irange 0 7] 0]

test listrep-5.1.1 {
    Verify that operation on a shared Tcl_Obj with a single-ref, spanless
    list representation only modifies the target object - lset version
} -constraints testlistrep -body {
    set l [freeSpaceNone]
    set l2 $l
    set same [sameStore $l $l2]
    lset l $end+1 8
    list $same $l $l2 [sameStore $l $l2]
} -result [list 1 [irange 0 8] [irange 0 7] 0]

test listrep-5.1.2 {
    Verify that operation on a shared Tcl_Obj with a single-ref, spanless
    list representation only modifies the target object - lpop version
} -constraints testlistrep -body {
    set l [freeSpaceNone]
    set l2 $l
    set same [sameStore $l $l2]
    lpop l
    list $same $l $l2 [sameStore $l $l2] [hasSpan $l]
} -result [list 1 [irange 0 6] [irange 0 7] 0 0]

test listrep-5.2 {
    Verify that operation on a shared Tcl_Obj with a single-ref, spanned
    list representation only modifies the target object - lappend version
} -constraints testlistrep -body {
    set l [freeSpaceBoth 1000 10 10]
    set l2 $l
    set same [sameStore $l $l2]
    lappend l 1000
    list $same $l $l2 [sameStore $l $l2] [hasSpan $l] [hasSpan $l2]
} -result [list 1 [irange 0 1000] [irange 0 999] 0 1 1]

test listrep-5.2.1 {
    Verify that operation on a shared Tcl_Obj with a single-ref, spanned
    list representation only modifies the target object - lset version
} -constraints testlistrep -body {
    set l [freeSpaceBoth 1000 10 10]
    set l2 $l
    set same [sameStore $l $l2]
    lset l $end+1 1000
    list $same $l $l2 [sameStore $l $l2] [hasSpan $l] [hasSpan $l2]
} -result [list 1 [irange 0 1000] [irange 0 999] 0 1 1]

test listrep-5.2.2 {
    Verify that operation on a shared Tcl_Obj with a single-ref, spanned
    list representation only modifies the target object - lpop version
} -constraints testlistrep -body {
    set l [freeSpaceNone 1000]
    set l2 $l
    set same [sameStore $l $l2]
    lpop l
    list $same $l $l2 [sameStore $l $l2] [hasSpan $l] [hasSpan $l2]
} -result [list 1 [irange 0 998] [irange 0 999] 1 1 0]

#
# 6.* - tests when lists contain zombies.
# The list implementation does lazy freeing in some cases so the list store
# contain Tcl_Obj's that are not actually referenced by any list (zombies).
# These are to be freed next time the list store is modified by a list
# operation as long as it is no longer shared.
test listrep-6.1 {
    Verify that zombies are freed up - linsert at front
} -constraints testlistrep -body {
    set l [zombieSample 200 10 10]
    set addr [storeAddress $l]
    # set l {} is for reference counts to drop to 1
    set l [linsert $l[set l {}] $zero -1]
    list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [list -1 {*}[irange 10 209]] 1 9 10 1]

test listrep-6.1.1 {
    Verify that zombies are freed up - linsert in middle
} -constraints testlistrep -body {
    set l [zombieSample 200 10 10]
    set addr [storeAddress $l]
    # set l {} is for reference counts to drop to 1
    set l [linsert $l[set l {}] $one -1]
    list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [list 10 -1 {*}[irange 11 209]] 1 9 10 1]

test listrep-6.1.2 {
    Verify that zombies are freed up - linsert at end
} -constraints testlistrep -body {
    set l [zombieSample 200 10 10]
    set addr [storeAddress $l]
    # set l {} is for reference counts to drop to 1
    set l [linsert $l[set l {}] $end 210]
    list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 10 210] 1 10 9 1]

test listrep-6.2 {
    Verify that zombies are freed up - lrange version (whole)
} -constraints testlistrep -body {
    set l [zombieSample 200 10 10]
    set addr [storeAddress $l]
    # set l {} is for reference counts to drop to 1
    set l [lrange $l[set l {}] $zero $end]
    list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 10 209] 1 10 10 1]

test listrep-6.2.1 {
    Verify that zombies are freed up - lrange version (subrange)
} -constraints testlistrep -body {
    set l [zombieSample 200 10 10]
    set addr [storeAddress $l]
    # set l {} is for reference counts to drop to 1
    set l [lrange $l[set l {}] $one $end-1]
    list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 11 208] 1 11 11 1]

test listrep-6.3 {
    Verify that zombies are freed up - lassign version
} -constraints testlistrep -body {
    set l [zombieSample 200 10 10]
    set addr [storeAddress $l]
    # set l {} is for reference counts to drop to 1
    set l [lassign $l[set l {}] e]
    list $e $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 10 [irange 11 209] 1 11 10 1]

test listrep-6.4 {
    Verify that zombies are freed up - lremove version (front)
} -constraints testlistrep -body {
    set l [zombieSample 200 10 10]
    set addr [storeAddress $l]
    # set l {} is for reference counts to drop to 1
    set l [lremove $l[set l {}] $zero]
    list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 11 209] 1 11 10 1]

test listrep-6.4.1 {
    Verify that zombies are freed up - lremove version (back)
} -constraints testlistrep -body {
    set l [zombieSample 200 10 10]
    set addr [storeAddress $l]
    # set l {} is for reference counts to drop to 1
    set l [lremove $l[set l {}] $end]
    list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 10 208] 1 10 11 1]

test listrep-6.5 {
    Verify that zombies are freed up - lreplace at front
} -constraints testlistrep -body {
    set l [zombieSample 200 10 10]
    set addr [storeAddress $l]
    # set l {} is for reference counts to drop to 1
    set l [lreplace $l[set l {}] $zero $one -3 -2 -1]
    list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [list -3 -2 -1 {*}[irange 12 209]] 1 9 10 1]

test listrep-6.5.1 {
    Verify that zombies are freed up - lreplace at back
} -constraints testlistrep -body {
    set l [zombieSample 200 10 10]
    set addr [storeAddress $l]
    # set l {} is for reference counts to drop to 1
    set l [lreplace $l[set l {}] $end-1 $end -1 -2 -3]
    list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [list {*}[irange 10 207] -1 -2 -3] 1 10 9 1]

test listrep-6.6 {
    Verify that zombies are freed up - lappend
} -constraints testlistrep -body {
    set l [zombieSample 200 10 10]
    set addr [storeAddress $l]
    lappend l 210
    list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 10 210] 1 10 9 1]

test listrep-6.7 {
    Verify that zombies are freed up - lpop version (front)
} -constraints testlistrep -body {
    set l [zombieSample 200 10 10]
    set addr [storeAddress $l]
    set e [lpop l $zero]
    list $e $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 10 [irange 11 209] 1 11 10 1]

test listrep-6.7.1 {
    Verify that zombies are freed up - lpop version (back)
} -constraints testlistrep -body {
    set l [zombieSample 200 10 10]
    set addr [storeAddress $l]
    set e [lpop l]
    list $e $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list 209 [irange 10 208] 1 10 11 1]

test listrep-6.8 {
    Verify that zombies are freed up - lset version
} -constraints testlistrep -body {
    set l [zombieSample 200 10 10]
    set addr [storeAddress $l]
    lset l $zero -1
    list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [list -1 {*}[irange 11 209]] 1 10 10 1]

test listrep-6.8.1 {
    Verify that zombies are freed up - lset version (back)
} -constraints testlistrep -body {
    set l [zombieSample 200 10 10]
    set addr [storeAddress $l]
    lset l $end+1 210
    list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
} -result [list [irange 10 210] 1 10 9 1]


# All done
::tcltest::cleanupTests

return

Changes to tests/llength.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  llength
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*

Changes to tests/lmap.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  lmap, continue, break
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 2011 Trevor Davel
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 2011 Trevor Davel
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: $

if {"::tcltest" ni [namespace children]} {
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
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







-
-
-
+
+
+






-
-
+
+







	if {[string compare $i "b"] == 0} continue
	set i
    }
} {a c d}
test lmap-3.2 {continue tests} {
    set x 0
    list [lmap i {a b c d} {
    	incr x
    	if {[string compare $i "b"] != 0} continue
    	set i
	incr x
	if {[string compare $i "b"] != 0} continue
	set i
    }] $x
} {b 4}
test lmap-3.3 {break tests} {
    set x 0
    list [lmap i {a b c d} {
	incr x
    	if {[string compare $i "c"] == 0} break
    	set i
	if {[string compare $i "c"] == 0} break
	set i
    }] $x
} {{a b} 3}
# Check for bug similar to #406709
test lmap-3.4 {break tests} {
    set a 1
    lmap b b {list [concat a; break]; incr a}
    incr a
289
290
291
292
293
294
295
296
297
298



299
300
301
302
303

304
305
306
307
308
309
310
289
290
291
292
293
294
295



296
297
298
299
300
301
302

303
304
305
306
307
308
309
310







-
-
-
+
+
+




-
+







	lmap a {} b {1 2 3} c {1 2} d {1 2 3 4} e {{1 2}} {
	    join [list $a $b $c $d $e] .
	}
    }}
} {{.1.1.1.1 2} .2.2.2. .3..3. ...4.}
test lmap-5.9 {lmap only sets vars if repeating loop} {
    apply {{} {
        set rgb {65535 0 0}
        lmap {r g b} [set rgb] {}
        return "r=$r, g=$g, b=$b"
	set rgb {65535 0 0}
	lmap {r g b} [set rgb] {}
	return "r=$r, g=$g, b=$b"
    }}
} {r=65535, g=0, b=0}
test lmap-5.10 {lmap only supports local scalar variables} {
    apply {{} {
        lmap {a(3)} {1 2 3 4} {set {a(3)}}
	lmap {a(3)} {1 2 3 4} {set {a(3)}}
    }}
} {1 2 3 4}

# "lmap" with "continue" and "break" (compiled)
test lmap-6.1 {continue tests} {
    apply {{} {
	lmap i {a b c d} {
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
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







-
-
-
-
+
+
+
+






-
-
+
+







-
+








# ----- Special cases and bugs -----------------------------------------------
test lmap-7.1 {compiled lmap backward jump works correctly} -setup {
    unset -nocomplain x
} -body {
    array set x {0 zero 1 one 2 two 3 three}
    lsort [apply {{arrayName} {
        upvar 1 $arrayName a
        lmap member [array names a] {
            list $member [set a($member)]
        }
	upvar 1 $arrayName a
	lmap member [array names a] {
	    list $member [set a($member)]
	}
    }} x]
} -result [lsort {{0 zero} {1 one} {2 two} {3 three}}]
test lmap-7.2 {noncompiled lmap and shared variable or value list objects that are converted to another type} -setup {
    unset -nocomplain x
} -body {
    lmap {12.0} {a b c} {
        set x 12.0
        set x [expr $x + 1]
	set x 12.0
	set x [expr {$x + 1}]
    }
} -result {13.0 13.0 13.0}
# Test for incorrect "double evaluation" semantics
test lmap-7.3 {delayed substitution of body} {
    apply {{} {
       set a 0
       lmap a [list 1 2 3] "
           set x $a
	   set x $a
       "
       return $x
    }}
} {0}
# Related to "foreach" test for [Bug 1189274]; crash on failure
test lmap-7.4 {empty list handling} {
    proc crash {} {

Changes to tests/load.test.

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
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
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
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






-
-
+
+










-
+








-
+





-
+




-
+

-
+






-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+





-
+





-
+




-
-
+
+



-
+







-
+






-
+









-
+


-
+


-
+

-
-
+
+

-
+
-


+
-
-
-
+
+
+
+

-
-
+
-
-
-
-
-





-
+

-
+




-
+

-
+




-
-
+
+

-
+



-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
+

-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
-
-
-
-
+
+
+
+

-
-
+
+


-
+

-
-
+
+

-
-
-
+
+
+

-
+


-
+
-
-
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
+
-

-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+


-
+







# Commands covered:  load
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1995 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

# Figure out what extension is used for shared libraries on this
# platform.
if {![info exists ext]} {
    set ext [info sharedlibextension]
}
# Tests require the existence of one of the DLLs in the dltest directory.
set testDir [file join [file dirname [info nameofexecutable]] dltest]
set x [file join $testDir pkga$ext]
set x [file join $testDir tcl9pkga$ext]
set dll "[file tail $x]Required"
testConstraint $dll [file readable $x]

# Tests also require that this DLL has not already been loaded.
set loaded "[file tail $x]Loaded"
set alreadyLoaded [info loaded]
set alreadyLoaded [info loaded {}]
testConstraint $loaded [expr {![string match *pkga* $alreadyLoaded]}]

set alreadyTotalLoaded [info loaded]

# Certain tests require the 'teststaticpkg' command from tcltest
# Certain tests require the 'teststaticlibrary' command from tcltest

testConstraint teststaticpkg [llength [info commands teststaticpkg]]
testConstraint teststaticlibrary [llength [info commands teststaticlibrary]]

# Test load-10.1 requires the 'testsimplefilesystem' command from tcltest

testConstraint testsimplefilesystem \
	[llength [info commands testsimplefilesystem]]

test load-1.1 {basic errors} {} {
    list [catch {load} msg] $msg
} "1 {wrong \# args: should be \"load ?-global? ?-lazy? ?--? fileName ?packageName? ?interp?\"}"
test load-1.2 {basic errors} {} {
    list [catch {load a b c d} msg] $msg
} "1 {wrong \# args: should be \"load ?-global? ?-lazy? ?--? fileName ?packageName? ?interp?\"}"
test load-1.3 {basic errors} {} {
    list [catch {load a b foobar} msg] $msg
} {1 {could not find interpreter "foobar"}}
test load-1.4 {basic errors} {} {
    list [catch {load -global {}} msg] $msg
} {1 {must specify either file name or package name}}
test load-1.5 {basic errors} {} {
    list [catch {load -lazy {} {}} msg] $msg
} {1 {must specify either file name or package name}}
test load-1.6 {basic errors} {} {
    list [catch {load {} Unknown} msg] $msg
} {1 {package "Unknown" isn't loaded statically}}
test load-1.7 {basic errors} {} {
    list [catch {load -abc foo} msg] $msg
} "1 {bad option \"-abc\": must be -global, -lazy, or --}"
test load-1.8 {basic errors} {} {
    list [catch {load -global} msg] $msg
} "1 {couldn't figure out package name for -global}"
test load-1.1 {basic errors} -returnCodes error -body {
    load
} -result {wrong # args: should be "load ?-global? ?-lazy? ?--? fileName ?prefix? ?interp?"}
test load-1.2 {basic errors} -returnCodes error -body {
    load a b c d
} -result {wrong # args: should be "load ?-global? ?-lazy? ?--? fileName ?prefix? ?interp?"}
test load-1.3 {basic errors} -returnCodes error -body {
    load a b foobar
} -result {could not find interpreter "foobar"}
test load-1.4 {basic errors} -returnCodes error -body {
    load -global {}
} -result {must specify either file name or prefix}
test load-1.5 {basic errors} -returnCodes error -body {
    load -lazy {} {}
} -result {must specify either file name or prefix}
test load-1.6 {basic errors} -returnCodes error -body {
    load {} Unknown
} -result {no library with prefix "Unknown" is loaded statically}
test load-1.7 {basic errors} -returnCodes error -body {
    load -abc foo
} -result {bad option "-abc": must be -global, -lazy, or --}
test load-1.8 {basic errors} -returnCodes error -body {
    load -global
} -result {cannot figure out prefix for -global}

test load-2.1 {basic loading, with guess for package name} \
	[list $dll $loaded] {
    load -global [file join $testDir pkga$ext]
    load -global [file join $testDir tcl9pkga$ext]
    list [pkga_eq abc def] [lsort [info commands pkga_*]]
} {0 {pkga_eq pkga_quote}}
interp create -safe child
test load-2.2 {loading into a safe interpreter, with package name conversion} \
	[list $dll $loaded] {
    load -lazy [file join $testDir pkgb$ext] pKgB child
    load -lazy [file join $testDir tcl9pkgb$ext] Pkgb child
    list [child eval pkgb_sub 44 13] [catch {child eval pkgb_unsafe} msg] $msg \
	    [catch {pkgb_sub 12 10} msg2] $msg2
} {31 1 {invalid command name "pkgb_unsafe"} 1 {invalid command name "pkgb_sub"}}
test load-2.3 {loading with no _Init procedure} -constraints [list $dll $loaded] \
-body {
    list [catch {load [file join $testDir pkgc$ext] foo} msg] $msg $errorCode
    list [catch {load [file join $testDir tcl9pkgc$ext] Foo} msg] $msg $errorCode
} -match glob \
    -result [list 1 {cannot find symbol "Foo_Init"*} \
		 {TCL LOOKUP LOAD_SYMBOL *Foo_Init}]
test load-2.4 {loading with no _SafeInit procedure} [list $dll $loaded] {
    list [catch {load [file join $testDir pkga$ext] {} child} msg] $msg
} {1 {can't use package in a safe interpreter: no Pkga_SafeInit procedure}}
    list [catch {load [file join $testDir tcl9pkga$ext] {} child} msg] $msg
} {1 {cannot use library in a safe interpreter: no Pkga_SafeInit procedure}}

test load-3.1 {error in _Init procedure, same interpreter} \
	[list $dll $loaded] {
    list [catch {load [file join $testDir pkge$ext] pkge} msg] \
    list [catch {load [file join $testDir tcl9pkge$ext] Pkge} msg] \
	    $msg $::errorInfo $::errorCode
} {1 {couldn't open "non_existent": no such file or directory} {couldn't open "non_existent": no such file or directory
    while executing
"open non_existent"
    invoked from within
"if 44 {open non_existent}"
    invoked from within
"load [file join $testDir pkge$ext] pkge"} {POSIX ENOENT {no such file or directory}}}
"load [file join $testDir tcl9pkge$ext] Pkge"} {POSIX ENOENT {no such file or directory}}}
test load-3.2 {error in _Init procedure, child interpreter} \
	[list $dll $loaded] {
    catch {interp delete x}
    interp create x
    set ::errorCode foo
    set ::errorInfo bar
    set result [list [catch {load [file join $testDir pkge$ext] pkge x} msg] \
    set result [list [catch {load [file join $testDir tcl9pkge$ext] Pkge x} msg] \
	    $msg $::errorInfo $::errorCode]
    interp delete x
    set result
} {1 {couldn't open "non_existent": no such file or directory} {couldn't open "non_existent": no such file or directory
    while executing
"open non_existent"
    invoked from within
"if 44 {open non_existent}"
    invoked from within
"load [file join $testDir pkge$ext] pkge x"} {POSIX ENOENT {no such file or directory}}}
"load [file join $testDir tcl9pkge$ext] Pkge x"} {POSIX ENOENT {no such file or directory}}}

test load-4.1 {reloading package into same interpreter} [list $dll $loaded] {
    list [catch {load [file join $testDir pkga$ext] pkga} msg] $msg
    list [catch {load [file join $testDir tcl9pkga$ext] Pkga} msg] $msg
} {0 {}}
test load-4.2 {reloading package into same interpreter} -setup {
    catch {load [file join $testDir pkga$ext] pkga}
    catch {load [file join $testDir tcl9pkga$ext] Pkga}
} -constraints [list $dll $loaded] -returnCodes error -body {
    load [file join $testDir pkga$ext] pkgb
} -result "file \"[file join $testDir pkga$ext]\" is already loaded for package \"Pkga\""
    load [file join $testDir tcl9pkga$ext] Pkgb
} -result "file \"[file join $testDir tcl9pkga$ext]\" is already loaded for prefix \"Pkga\""

test load-5.1 {file name not specified and no static package: pick default} \
test load-5.1 {file name not specified and no static package: pick default} -setup {
	[list $dll $loaded] {
    catch {interp delete x}
    interp create x
} -constraints [list $dll $loaded] -body {
    load -global [file join $testDir pkga$ext] pkga
    load {} pkga x
    set result [info loaded x]
    load -global [file join $testDir tcl9pkga$ext] Pkga
    load {} Pkga x
    info loaded x
} -cleanup {
    interp delete x
    set result
} [list [list [file join $testDir pkga$ext] Pkga]]
} -result [list [list [file join $testDir tcl9pkga$ext] Pkga]]

# On some platforms, like SunOS 4.1.3, these tests can't be run because
# they cause the process to exit.
#
# As of 2005, such ancient broken systems no longer matter.

test load-6.1 {errors loading file} [list $dll $loaded] {
    catch {load foo foo}
} {1}

test load-7.1 {Tcl_StaticPackage procedure} [list teststaticpkg] {
test load-7.1 {Tcl_StaticLibrary procedure} [list teststaticlibrary] {
    set x "not loaded"
    teststaticpkg Test 1 0
    teststaticlibrary Test 1 0
    load {} Test
    load {} Test child
    list [set x] [child eval set x]
} {loaded loaded}
test load-7.2 {Tcl_StaticPackage procedure} [list teststaticpkg] {
test load-7.2 {Tcl_StaticLibrary procedure} [list teststaticlibrary] {
    set x "not loaded"
    teststaticpkg Another 0 0
    teststaticlibrary Another 0 0
    load {} Another
    child eval {set x "not loaded"}
    list [catch {load {} Another child} msg] $msg \
	[child eval set x] [set x]
} {1 {can't use package in a safe interpreter: no Another_SafeInit procedure} {not loaded} loaded}
test load-7.3 {Tcl_StaticPackage procedure} [list teststaticpkg] {
} {1 {cannot use library in a safe interpreter: no Another_SafeInit procedure} {not loaded} loaded}
test load-7.3 {Tcl_StaticLibrary procedure} [list teststaticlibrary] {
    set x "not loaded"
    teststaticpkg More 0 1
    teststaticlibrary More 0 1
    load {} More
    set x
} {not loaded}
catch {load [file join $testDir pkga$ext] pkga}
catch {load [file join $testDir pkgb$ext] pkgb}
catch {load [file join $testDir pkge$ext] pkge}
set currentRealPackages [list [list [file join $testDir pkge$ext] Pkge] [list [file join $testDir pkgb$ext] Pkgb] [list [file join $testDir pkga$ext] Pkga]]
test load-7.4 {Tcl_StaticPackage procedure, redundant calls} -setup {
    teststaticpkg Test 1 0
    teststaticpkg Another 0 0
    teststaticpkg More 0 1
} -constraints [list teststaticpkg $dll $loaded] -body {
    teststaticpkg Double 0 1
    teststaticpkg Double 0 1
catch {load [file join $testDir tcl9pkga$ext] Pkga}
catch {load [file join $testDir tcl9pkgb$ext] Pkgb}
catch {load [file join $testDir tcl9pkge$ext] Pkge}
set currentRealLibraries [list [list [file join $testDir tcl9pkge$ext] Pkge] [list [file join $testDir tcl9pkgb$ext] Pkgb] [list [file join $testDir tcl9pkga$ext] Pkga]]
test load-7.4 {Tcl_StaticLibrary procedure, redundant calls} -setup {
    teststaticlibrary Test 1 0
    teststaticlibrary Another 0 0
    teststaticlibrary More 0 1
} -constraints [list teststaticlibrary $dll $loaded] -body {
    teststaticlibrary Double 0 1
    teststaticlibrary Double 0 1
    info loaded
} -result [list {{} Double} {{} More} {{} Another} {{} Test} {*}$currentRealPackages {*}$alreadyTotalLoaded]
} -result [list {{} Double} {{} More} {{} Another} {{} Test} {*}$currentRealLibraries {*}$alreadyTotalLoaded]

testConstraint teststaticpkg_8.x \
    [if {[testConstraint teststaticpkg]} {
	teststaticpkg Test 1 1
	teststaticpkg Another 0 1
	teststaticpkg More 0 1
	teststaticpkg Double 0 1
testConstraint teststaticlibrary_8.x 0
if {[testConstraint teststaticlibrary]} {
    catch {
	teststaticlibrary Test 1 1
	teststaticlibrary Another 0 1
	teststaticlibrary More 0 1
	teststaticlibrary Double 0 1
	expr 1
    } else {
	testConstraint teststaticlibrary_8.x 1
	expr 0
    }]

test load-8.1 {TclGetLoadedPackages procedure} [list teststaticpkg_8.x $dll $loaded] {
    }
}

test load-8.1 {TclGetLoadedLibraries procedure} [list teststaticlibrary_8.x $dll $loaded] {
    lsort -index 1 [info loaded]
} [lsort -index 1 [list {{} Double} {{} More} {{} Another} {{} Test} {*}$currentRealPackages {*}$alreadyTotalLoaded]]
test load-8.2 {TclGetLoadedPackages procedure} -constraints {teststaticpkg_8.x} -body {
} [lsort -index 1 [list {{} Double} {{} More} {{} Another} {{} Test} {*}$currentRealLibraries {*}$alreadyTotalLoaded]]
test load-8.2 {TclGetLoadedLibraries procedure} -constraints {teststaticlibrary_8.x} -body {
    info loaded gorp
} -returnCodes error -result {could not find interpreter "gorp"}
test load-8.3a {TclGetLoadedPackages procedure} [list teststaticpkg_8.x $dll $loaded] {
test load-8.3a {TclGetLoadedLibraries procedure} [list teststaticlibrary_8.x $dll $loaded] {
    lsort -index 1 [info loaded {}]
} [lsort -index 1 [list {{} Double} {{} More} {{} Another} {{} Test} [list [file join $testDir pkga$ext] Pkga] [list [file join $testDir pkgb$ext] Pkgb] {*}$alreadyLoaded]]
test load-8.3b {TclGetLoadedPackages procedure} [list teststaticpkg_8.x $dll $loaded] {
} [lsort -index 1 [list {{} Double} {{} More} {{} Another} {{} Test} [list [file join $testDir tcl9pkga$ext] Pkga] [list [file join $testDir tcl9pkgb$ext] Pkgb] {*}$alreadyLoaded]]
test load-8.3b {TclGetLoadedLibraries procedure} [list teststaticlibrary_8.x $dll $loaded] {
    lsort -index 1 [info loaded child]
} [lsort -index 1 [list {{} Test} [list [file join $testDir pkgb$ext] Pkgb]]]
test load-8.4 {TclGetLoadedPackages procedure} [list teststaticpkg_8.x $dll $loaded] {
    load [file join $testDir pkgb$ext] pkgb
} [lsort -index 1 [list {{} Test} [list [file join $testDir tcl9pkgb$ext] Pkgb]]]
test load-8.4 {TclGetLoadedLibraries procedure} [list teststaticlibrary_8.x $dll $loaded] {
    load [file join $testDir tcl9pkgb$ext] Pkgb
    list [lsort -index 1 [info loaded {}]] [lsort [info commands pkgb_*]]
} [list [lsort -index 1 [concat [list [list [file join $testDir pkgb$ext] Pkgb] {{} Double} {{} More} {{} Another} {{} Test} [list [file join $testDir pkga$ext] Pkga]] $alreadyLoaded]] {pkgb_demo pkgb_sub pkgb_unsafe}]
} [list [lsort -index 1 [concat [list [list [file join $testDir tcl9pkgb$ext] Pkgb] {{} Double} {{} More} {{} Another} {{} Test} [list [file join $testDir tcl9pkga$ext] Pkga]] $alreadyLoaded]] {pkgb_demo pkgb_sub pkgb_unsafe}]
interp delete child

test load-9.1 {Tcl_StaticPackage, load already-loaded package into another interp} \
test load-9.1 {Tcl_StaticLibrary, load already-loaded package into another interp} -setup {
    -constraints {teststaticpkg} \
    -setup {
	interp create child1
	interp create child2
	load {} Tcltest child1
	load {} Tcltest child2
    interp create child1
    interp create child2
    load {} Tcltest child1
    load {} Tcltest child2
    } \
    -body {
	child1 eval { teststaticpkg Loadninepointone 0 1 }
	child2 eval { teststaticpkg Loadninepointone 0 1 }
} -constraints {teststaticlibrary} -body {
    child1 eval { teststaticlibrary Loadninepointone 0 1 }
    child2 eval { teststaticlibrary Loadninepointone 0 1 }
	list \
	    [child1 eval { info loaded {} }] \
	    [child2 eval { info loaded {} }]
    } \
    -match glob -result {{{{} Loadninepointone} {* Tcltest}} {{{} Loadninepointone} {* Tcltest}}} \
    list [child1 eval { info loaded {} }] \
	[child2 eval { info loaded {} }]
} -match glob -cleanup {
    interp delete child1
    interp delete child2
} -result {{{{} Loadninepointone} {* Tcltest}} {{{} Loadninepointone} {* Tcltest}}}
    -cleanup { interp delete child1 ; interp delete child2 }

test load-10.1 {load from vfs} \
    -constraints [list $dll $loaded testsimplefilesystem] \
test load-10.1 {load from vfs} -setup {
    set dir [pwd]
    cd $testDir
    testsimplefilesystem 1
} -constraints [list $dll $loaded testsimplefilesystem] -body {
    -setup {set dir [pwd]; cd $testDir; testsimplefilesystem 1} \
    -body {list [catch {load simplefs:/pkgd$ext pkgd} msg] $msg} \
    -result {0 {}} \
    -cleanup {testsimplefilesystem 0; cd $dir; unset dir}

    list [catch {load simplefs:/tcl9pkgd$ext Pkgd} msg] $msg
} -result {0 {}} -cleanup {
    testsimplefilesystem 0
    cd $dir
    unset dir
}

test load-11.1 {Load TclOO extension using Stubs (Bug [f51efe99a7])} \
	[list $dll $loaded] {
    load [file join $testDir pkgooa$ext]
    load [file join $testDir tcl9pkgooa$ext]
    list [pkgooa_stubsok] [lsort [info commands pkgooa_*]]
} {1 pkgooa_stubsok}

# cleanup
unset ext
::tcltest::cleanupTests
return

Changes to tests/lpop.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  lpop
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
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
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







-
-
-
+
+
+




-
-
-
+
+
+












-
-
-
+
+
+




-
-
-
+
+
+










test lpop-99.1 {performance} -constraints perf -body {
    set l [lrepeat 10000 x]
    set l2 $l
    set t1 [time {
        while {[llength $l] >= 2} {
            lpop l end
        }
	while {[llength $l] >= 2} {
	    lpop l end
	}
    }]
    set l [lrepeat 30000 x]
    set l2 $l
    set t2 [time {
        while {[llength $l] >= 2} {
            lpop l end
        }
	while {[llength $l] >= 2} {
	    lpop l end
	}
    }]
    regexp {\d+} $t1 ms1
    regexp {\d+} $t2 ms2
    set ratio [expr {double($ms2)/$ms1}]
    # Deleting from end should have linear performance
    expr {$ratio > 4 ? $ratio : 4}
} -result {4}

test lpop-99.2 {performance} -constraints perf -body {
    set l [lrepeat 10000 x]
    set l2 $l
    set t1 [time {
        while {[llength $l] >= 2} {
            lpop l 1
        }
	while {[llength $l] >= 2} {
	    lpop l 1
	}
    }]
    set l [lrepeat 30000 x]
    set l2 $l
    set t2 [time {
        while {[llength $l] >= 2} {
            lpop l 1
        }
	while {[llength $l] >= 2} {
	    lpop l 1
	}
    }]
    regexp {\d+} $t1 ms1
    regexp {\d+} $t2 ms2
    set ratio [expr {double($ms2)/$ms1}]
    expr {$ratio > 10 ? $ratio : 10}
} -result {10}

Changes to tests/lrange.test.

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
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






-
-
-
+
+
+










-
+







# Commands covered:  lrange
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testpurebytesobj [llength [info commands testpurebytesobj]]

test lrange-1.1 {range of list elements} {
    lrange {a b c d} 1 2
} {b c}
test lrange-1.2 {range of list elements} {
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
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







-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+













    set lss     {{} {a} {a b c} {a b c d}}
    set idxs    {-2 -1 0 1 2 3 end-3 end-2 end-1 end end+1 end+2}
    set lrange  lrange

    foreach ls $lss {
	foreach a $idxs {
	    foreach b $idxs {
                # Shared, uncompiled
                set ls2 $ls
                set expected [list [catch {$lrange $ls $a $b} m] $m]
                # Shared, compiled
                set tester [list lrange $ls $a $b]
                set script [list catch $tester m]
                set script "list \[$script\] \$m"
                test lrange-5.[incr n].1 {lrange shared compiled} -body \
		# Shared, uncompiled
		set ls2 $ls
		set expected [list [catch {$lrange $ls $a $b} m] $m]
		# Shared, compiled
		set tester [list lrange $ls $a $b]
		set script [list catch $tester m]
		set script "list \[$script\] \$m"
		test lrange-5.[incr n].1 {lrange shared compiled} -body \
			[list apply [list {} $script]] -result $expected
                # Unshared, uncompiled
                set tester [string map [list %l [list $ls] %a $a %b $b] {
                    [string cat l range] [lrange %l 0 end] %a %b
                }]
                set script [list catch $tester m]
                set script "list \[$script\] \$m"
                test lrange-5.$n.2 {lrange unshared uncompiled} -body \
		# Unshared, uncompiled
		set tester [string map [list %l [list $ls] %a $a %b $b] {
		    [string cat l range] [lrange %l 0 end] %a %b
		}]
		set script [list catch $tester m]
		set script "list \[$script\] \$m"
		test lrange-5.$n.2 {lrange unshared uncompiled} -body \
			[list apply [list {} $script]] -result $expected
                # Unshared, compiled
                set tester [string map [list %l [list $ls] %a $a %b $b] {
                    lrange [lrange %l 0 end] %a %b
                }]
                set script [list catch $tester m]
                set script "list \[$script\] \$m"
                test lrange-5.$n.3 {lrange unshared compiled} -body \
		# Unshared, compiled
		set tester [string map [list %l [list $ls] %a $a %b $b] {
		    lrange [lrange %l 0 end] %a %b
		}]
		set script [list catch $tester m]
		set script "list \[$script\] \$m"
		test lrange-5.$n.3 {lrange unshared compiled} -body \
			[list apply [list {} $script]] -result $expected
	    }
	}
    }
}}

# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/lrepeat.test.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







# Commands covered:  lrepeat
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 2003 by Simon Geard.
# Copyright © 2003 Simon Geard.
#
# 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::*
57
58
59
60
61
62
63
64

65
66
67
68
69
70
71
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71







-
+







}
test lrepeat-1.7 {Accept zero repetitions (TIP 323)} {
    -body {
	lrepeat 0 a b c
    }
    -result {}
}
test lrepeat-1.8 {Do not build enormous lists - Bug 2130992} -body {
test lrepeat-1.8 {Do not build enormous lists - Bug 2130992} -constraints knownBug -body {
     lrepeat 0x10000000 a b c d e f g h
} -returnCodes error -match glob -result *

## Okay
test lrepeat-2.1 {normal cases} {
    lrepeat 10 a
} {a a a a a a a a a a}

Changes to tests/lreplace.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  lreplace
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
91
92
93
94
95
96
97
98
99


100
101
102
103
104
105
106
91
92
93
94
95
96
97


98
99
100
101
102
103
104
105
106







-
-
+
+







test lreplace-1.25 {lreplace command} {
    concat \"[lreplace {\}\     hello} end end]\"
} {"\}\ "}
test lreplace-1.26 {lreplace command} {
    catch {unset foo}
    set foo {a b}
    list [set foo [lreplace $foo end end]] \
        [set foo [lreplace $foo end end]] \
        [set foo [lreplace $foo end end]]
	[set foo [lreplace $foo end end]] \
	[set foo [lreplace $foo end end]]
} {a {} {}}
test lreplace-1.27 {lreplace command} -body {
    lreplace x 1 1
} -result x
test lreplace-1.28 {lreplace command} -body {
    lreplace x 1 1 y
} -result {x y}
131
132
133
134
135
136
137
138
139


140
141
142
143
144
145
146
131
132
133
134
135
136
137


138
139
140
141
142
143
144
145
146







-
-
+
+







} -result {0 x}
test lreplace-2.7 {lreplace errors} -body {
    list [catch {lreplace x 2 2} msg] $msg
} -result {0 x}

test lreplace-3.1 {lreplace won't modify shared argument objects} {
    proc p {} {
        lreplace "a b c" 1 1 "x y"
        return "a b c"
	lreplace "a b c" 1 1 "x y"
	return "a b c"
    }
    p
} "a b c"

test lreplace-4.1 {Bug ccc2c2cc98: lreplace edge case} {
    lreplace {} 1 1
} {}
229
230
231
232
233
234
235
















































































































































































































































































































236
237
238
239
240
241
242
243
244
245
246
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











		    set script [list catch $tester m]
		    set script "list \[$script\] \$m"
		    test lreplace-6.[incr n] {lreplace battery} -body \
			[list apply [list {} $script]] -result $expected
		}
	    }
	}
    }
}}

# Essentially same tests as above but for ledit
test ledit-1.1 {ledit command} {
    set l {1 2 3 4 5}
    list [ledit l 0 0 a] $l
} {{a 2 3 4 5} {a 2 3 4 5}}
test ledit-1.2 {ledit command} {
    set l {1 2 3 4 5}
    list [ledit l 1 1 a] $l
} {{1 a 3 4 5} {1 a 3 4 5}}
test ledit-1.3 {ledit command} {
    set l {1 2 3 4 5}
    list [ledit l 2 2 a] $l
} {{1 2 a 4 5} {1 2 a 4 5}}
test ledit-1.4 {ledit command} {
    set l {1 2 3 4 5}
    list [ledit l 3 3 a] $l
} {{1 2 3 a 5} {1 2 3 a 5}}
test ledit-1.5 {ledit command} {
    set l {1 2 3 4 5}
    list [ledit l 4 4 a] $l
} {{1 2 3 4 a} {1 2 3 4 a}}
test ledit-1.6 {ledit command} {
    set l {1 2 3 4 5}
    list [ledit l 4 5 a] $l
} {{1 2 3 4 a} {1 2 3 4 a}}
test ledit-1.7 {ledit command} {
    set l {1 2 3 4 5}
    list [ledit l -1 -1 a] $l
} {{a 1 2 3 4 5} {a 1 2 3 4 5}}
test ledit-1.8 {ledit command} {
    set l {1 2 3 4 5}
    list [ledit l 2 end a b c d] $l
} {{1 2 a b c d} {1 2 a b c d}}
test ledit-1.9 {ledit command} {
    set l {1 2 3 4 5}
    list [ledit l 0 3] $l
} {5 5}
test ledit-1.10 {ledit command} {
    set l {1 2 3 4 5}
    list [ledit l 0 4] $l
} {{} {}}
test ledit-1.11 {ledit command} {
    set l {1 2 3 4 5}
    list [ledit l 0 1] $l
} {{3 4 5} {3 4 5}}
test ledit-1.12 {ledit command} {
    set l {1 2 3 4 5}
    list [ledit l 2 3] $l
} {{1 2 5} {1 2 5}}
test ledit-1.13 {ledit command} {
    set l {1 2 3 4 5}
    list [ledit l 3 end] $l
} {{1 2 3} {1 2 3}}
test ledit-1.14 {ledit command} {
    set l {1 2 3 4 5}
    list [ledit l -1 4 a b c] $l
} {{a b c} {a b c}}
test ledit-1.15 {ledit command} {
    set l {a b "c c" d e f}
    list [ledit l 3 3] $l
} {{a b {c c} e f} {a b {c c} e f}}
test ledit-1.16 {ledit command} {
    set l { 1 2 3 4 5}
    list [ledit l 0 0 a] $l
} {{a 2 3 4 5} {a 2 3 4 5}}
test ledit-1.17 {ledit command} {
    set l {1 2 3 4 "5 6"}
    list [ledit l 4 4 a] $l
} {{1 2 3 4 a} {1 2 3 4 a}}
test ledit-1.18 {ledit command} {
    set l {1 2 3 4 {5 6}}
    list [ledit l 4 4 a] $l
} {{1 2 3 4 a} {1 2 3 4 a}}
test ledit-1.19 {ledit command} {
    set l {1 2 3 4}
    list [ledit l 2 end x y z] $l
} {{1 2 x y z} {1 2 x y z}}
test ledit-1.20 {ledit command} {
    set l {1 2 3 4}
    list [ledit l end end a] $l
} {{1 2 3 a} {1 2 3 a}}
test ledit-1.21 {ledit command} {
    set l {1 2 3 4}
    list [ledit l end 3 a] $l
} {{1 2 3 a} {1 2 3 a}}
test ledit-1.22 {ledit command} {
    set l {1 2 3 4}
    list [ledit l end end] $l
} {{1 2 3} {1 2 3}}
test ledit-1.23 {ledit command} {
    set l {1 2 3 4}
    list [ledit l 2 -1 xy] $l
} {{1 2 xy 3 4} {1 2 xy 3 4}}
test ledit-1.24 {ledit command} {
    set l {1 2 3 4}
    list [ledit l end -1 z] $l
} {{1 2 3 z 4} {1 2 3 z 4}}
test ledit-1.25 {ledit command} {
    set l {\}\     hello}
    concat \"[ledit l end end]\" $l
} {"\}\ " \}\ }
test ledit-1.26 {ledit command} {
    catch {unset foo}
    set foo {a b}
    list [ledit foo end end] $foo \
	[ledit foo end end] $foo \
	[ledit foo end end] $foo
} {a a {} {} {} {}}
test ledit-1.27 {lsubset command} -body {
    set l x
    list [ledit l 1 1] $l
} -result {x x}
test ledit-1.28 {ledit command} -body {
    set l x
    list [ledit l 1 1 y] $l
} -result {{x y} {x y}}
test ledit-1.29 {ledit command} -body {
    set l x
    ledit l 1 1 [error foo]
} -returnCodes 1 -result {foo}
test ledit-1.30 {ledit command} -body {
    set l {not {}alist}
    ledit l 0 0 [error foo]
} -returnCodes 1 -result {foo}
test ledit-1.31 {ledit command} -body {
    unset -nocomplain arr
    set arr(x) {a b}
    list [ledit arr(x) 0 0 c] $arr(x)
} -result {{c b} {c b}}

test ledit-2.1 {ledit errors} -body {
    list [catch ledit msg] $msg
} -result {1 {wrong # args: should be "ledit listVar first last ?element ...?"}}
test ledit-2.2 {ledit errors} -body {
    unset -nocomplain x
    list [catch {ledit l b} msg] $msg
} -result {1 {wrong # args: should be "ledit listVar first last ?element ...?"}}
test ledit-2.3 {ledit errors} -body {
    set x {}
    list [catch {ledit x a 10} msg] $msg
} -result {1 {bad index "a": must be integer?[+-]integer? or end?[+-]integer?}}
test ledit-2.4 {ledit errors} -body {
    set l {}
    list [catch {ledit l 10 x} msg] $msg
} -result {1 {bad index "x": must be integer?[+-]integer? or end?[+-]integer?}}
test ledit-2.5 {ledit errors} -body {
    set l {}
    list [catch {ledit l 10 1x} msg] $msg
} -result {1 {bad index "1x": must be integer?[+-]integer? or end?[+-]integer?}}
test ledit-2.6 {ledit errors} -body {
    set l x
    list [catch {ledit l 3 2} msg] $msg
} -result {0 x}
test ledit-2.7 {ledit errors} -body {
    set l x
    list [catch {ledit l 2 2} msg] $msg
} -result {0 x}
test ledit-2.8 {ledit errors} -body {
    unset -nocomplain l
    ledit l 0 0 x
} -returnCodes error -result {can't read "l": no such variable}
test ledit-2.9 {ledit errors} -body {
    unset -nocomplain arr
    ledit arr(x) 0 0 x
} -returnCodes error -result {can't read "arr(x)": no such variable}
test ledit-2.10 {ledit errors} -body {
    unset -nocomplain arr
    set arr(y) y
    ledit arr(x) 0 0 x
} -returnCodes error -result {can't read "arr(x)": no such element in array}

test ledit-3.1 {ledit won't modify shared argument objects} {
    proc p {} {
	set l "a b c"
	ledit l 1 1 "x y"
	# The literal in locals table should be unmodified
	return [list "a b c" $l]
    }
    p
} {{a b c} {a {x y} c}}

# Following bugs were in lreplace. Make sure ledit does not have them
test ledit-4.1 {Bug ccc2c2cc98: lreplace edge case} {
    set l {}
    list [ledit l 1 1] $l
} {{} {}}
test ledit-4.2 {Bug ccc2c2cc98: lreplace edge case} {
    set l { }
    list [ledit l 1 1] $l
} {{} {}}
test ledit-4.3 {lreplace edge case} {
    set l {1 2 3}
    ledit l 2 0
} {1 2 3}
test ledit-4.4 {ledit edge case} {
    set l {1 2 3 4 5}
    list [ledit l 3 1] $l
} {{1 2 3 4 5} {1 2 3 4 5}}
test ledit-4.5 {ledit edge case} {
    lreplace {1 2 3 4 5} 3 0 _
} {1 2 3 _ 4 5}
test ledit-4.6 {ledit end-x: bug a4cb3f06c4} {
    set l {0 1 2 3 4}
    list [ledit l 0 end-2] $l
} {{3 4} {3 4}}
test ledit-4.6.1 {ledit end-x: bug a4cb3f06c4} {
    set l {0 1 2 3 4}
    list [ledit l 0 end-2 a b c] $l
} {{a b c 3 4} {a b c 3 4}}
test ledit-4.7 {ledit with two end-indexes: increasing} {
    set l {0 1 2 3 4}
    list [ledit l end-2 end-1] $l
} {{0 1 4} {0 1 4}}
test ledit-4.7.1 {ledit with two end-indexes: increasing} {
    set l {0 1 2 3 4}
    list [ledit l end-2 end-1 a b c] $l
} {{0 1 a b c 4} {0 1 a b c 4}}
test ledit-4.8 {ledit with two end-indexes: equal} {
    set l {0 1 2 3 4}
    list [ledit l end-2 end-2] $l
} {{0 1 3 4} {0 1 3 4}}
test ledit-4.8.1 {ledit with two end-indexes: equal} {
    set l {0 1 2 3 4}
    list [ledit l end-2 end-2 a b c] $l
} {{0 1 a b c 3 4} {0 1 a b c 3 4}}
test ledit-4.9 {ledit with two end-indexes: decreasing} {
    set l {0 1 2 3 4}
    list [ledit l end-2 end-3] $l
} {{0 1 2 3 4} {0 1 2 3 4}}
test ledit-4.9.1 {ledit with two end-indexes: decreasing} {
    set l {0 1 2 3 4}
    list [ledit l end-2 end-3 a b c] $l
} {{0 1 a b c 2 3 4} {0 1 a b c 2 3 4}}
test ledit-4.10 {ledit with two equal indexes} {
    set l {0 1 2 3 4}
    list [ledit l 2 2] $l
} {{0 1 3 4} {0 1 3 4}}
test ledit-4.10.1 {ledit with two equal indexes} {
    set l {0 1 2 3 4}
    list [ledit l 2 2 a b c] $l
} {{0 1 a b c 3 4} {0 1 a b c 3 4}}
test ledit-4.11 {ledit end index first} {
    set l {0 1 2 3 4}
    list [ledit l end-2 1 a b c] $l
} {{0 1 a b c 2 3 4} {0 1 a b c 2 3 4}}
test ledit-4.12 {ledit end index first} {
    set l {0 1 2 3 4}
    list [ledit l end-2 2 a b c] $l
} {{0 1 a b c 3 4} {0 1 a b c 3 4}}
test ledit-4.13 {ledit empty list} {
    set l {}
    list [ledit l 1 1 1] $l
} {1 1}
test ledit-4.14 {ledit empty list} {
    set l {}
    list [ledit l 2 2 2] $l
} {2 2}

test ledit-5.1 {compiled lreplace: Bug 47ac84309b} {
    apply {x {
	ledit x end 0
    }} {a b c}
} {a b c}
test ledit-5.2 {compiled lreplace: Bug 47ac84309b} {
    apply {x {
	ledit x end 0 A
    }} {a b c}
} {a b A c}

test ledit-bug-a366c6efee {Bug [a366c6efee]} -body {
    apply {{} {
	set l { }
	string length [ledit l 1 1]; # Force string generation
	set result foo
	append result " " bar
    }}
} -result "foo bar"

# Testing for compiled behaviour. Far too many variations to check with
# spelt-out tests. Note that this *just* checks whether the compiled version
# and the interpreted version are the same, not whether the interpreted
# version is correct.
apply {{} {
    set lss     {{} {a} {a b c} {a b c d}}
    set ins     {{} A {A B}}
    set idxs    {-2 -1 0 1 2 3 end-3 end-2 end-1 end end+1 end+2}
    set lreplace lreplace

    foreach ls $lss {
	foreach a $idxs {
	    foreach b $idxs {
		foreach i $ins {
		    set expected [list [catch {$lreplace $ls $a $b {*}$i} m] $m]
		    set tester [list ledit ls $a $b {*}$i]
		    set script [list catch $tester m]
		    set script "list \[$script\] \$m"
		    test ledit-6.[incr n] {ledit battery} -body \
			[list apply [list {ls} $script] $ls] -result $expected
		}
	    }
	}
    }
}}

# cleanup
catch {unset foo}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/lsearch.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  lsearch
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands.  Sourcing this file into Tcl runs the tests and generates output
# for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57







-
+







    lsearch -exact {foo bar cat} bart
} -1
test lsearch-2.5 {search modes} {
    lsearch -exact {foo bar cat} bar
} 1
test lsearch-2.6 {search modes} -returnCodes error -body {
    lsearch -regexp {xyz bbcc *bc*} *bc*
} -result {couldn't compile regular expression pattern: quantifier operand invalid}
} -result {cannot compile regular expression pattern: invalid quantifier operand}
test lsearch-2.7 {search modes} {
    lsearch -regexp {b.x ^bc xy bcx} ^bc
} 3
test lsearch-2.8 {search modes} {
    lsearch -glob {xyz bbcc *bc*} *bc*
} 1
test lsearch-2.9 {search modes} {
98
99
100
101
102
103
104
105

106
107
108
109
110
111

112
113
114
115
116
117
118
98
99
100
101
102
103
104

105
106
107
108
109
110

111
112
113
114
115
116
117
118







-
+





-
+







    lsearch -index a b
} -result {"-index" option must be followed by list index}
test lsearch-3.7 {lsearch errors} -returnCodes error -body {
    lsearch -subindices -exact a b
} -result {-subindices cannot be used without -index option}

test lsearch-4.1 {binary data} {
    lsearch -exact [list foo one\000two bar] bar
    lsearch -exact [list foo one\x00two bar] bar
} 2
test lsearch-4.2 {binary data} {
    set x one
    append x \x00
    append x two
    lsearch -exact [list foo one\000two bar] $x
    lsearch -exact [list foo one\x00two bar] $x
} 1

# Make a sorted list
set l {}
set l2 {}
for {set i 0} {$i < 100} {incr i} {
    lappend l $i
380
381
382
383
384
385
386
387

388
389
390
391
392
393
394
380
381
382
383
384
385
386

387
388
389
390
391
392
393
394







-
+







    lsearch -start 2 -all -not -glob {a1 b2 a3 c4 a5 d6} a*
} {3 5}
test lsearch-14.8 {combinations: -start, -inline and -not} {
    lsearch -start 2 -inline -not -glob {a1 b2 a3 c4 a5 d6} a*
} {c4}

test lsearch-15.1 {make sure no shimmering occurs} {
    set x [expr int(sin(0))]
    set x [expr {int(sin(0))}]
    lsearch -start $x $x $x
} 0

test lsearch-16.1 {lsearch -regexp shared object} {
    set str a
    lsearch -regexp $str $str
} 0
684
685
686
687
688
689
690



691
692
693
694
695
696
697
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700







+
+
+







} -result 4
test lsearch-28.8 {lsearch -sorted with -stride} -body {
    lsearch -sorted -stride 2 -index 1 -subindices {3 5 8 7 2 9} 9
} -result 5
test lsearch-28.9 {lsearch -sorted with -stride} -body {
    lsearch -sorted -stride 2 -index 1 -subindices -inline {3 5 8 7 2 9} 9
} -result 9
test lsearch-28.10 {lsearch -sorted with -stride} -body {
    lsearch -sorted -stride 4294967296 -index 1 -subindices -inline {3 5 8 7 2 9} 9
} -returnCodes 1 -result {list size must be a multiple of the stride length}


# cleanup
catch {unset res}
catch {unset increasingIntegers}
catch {unset decreasingIntegers}
catch {unset increasingDoubles}

Added tests/lseq.test.












































































































































































































































































































































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# Commands covered:  lseq
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright © 2003 Simon Geard.
#
# 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::*
}

testConstraint arithSeriesDouble 1
testConstraint arithSeriesShimmer 1
testConstraint arithSeriesShimmerOk 1
testConstraint knownBug 0
testConstraint has64BitLengths [expr {$tcl_platform(pointerSize) == 8}]
testConstraint has32BitLengths [expr {$tcl_platform(pointerSize) == 4}]

proc memusage {} {
    set fd [open /proc/[pid]/statm]
    set line [gets $fd]
    if {[llength $line] != 7} {
	error "Unexpected /proc/pid/statm format"
    }
    return [lindex $line 5]
}
testConstraint hasMemUsage [expr {![catch {memusage}]}]

# Arg errors
test lseq-1.1 {error cases} -body {
    lseq
} \
    -returnCodes 1 \
    -result {wrong # args: should be "lseq n ??op? n ??by? n??"}


test lseq-1.2 {step magnitude} {
    lseq 10 .. 1 by -2 ;# or this could be an error - or not
} {10 8 6 4 2}

test lseq-1.3 {synergy between int and double} -body {
    set rl [lseq 25. to 5. by -5]
    set il [lseq 25  to 5  by -5]
    lmap r $rl i $il { if {$r ne "" && $i ne ""} {expr {int($r) == $i}} else {list $r $i} }
} -cleanup {
    unset rl il
} -result {1 1 1 1 1}

test lseq-1.4 {integer decreasing} {
    lseq 10 .. 1
} {10 9 8 7 6 5 4 3 2 1}

test lseq-1.5 {integer increasing} {
    lseq 1 .. 10
} {1 2 3 4 5 6 7 8 9 10}

test lseq-1.6 {integer decreasing with step} {
    lseq 10 .. 1 by -2
} {10 8 6 4 2}

test lseq-1.7 {real increasing lseq} arithSeriesDouble {
    lseq 5.0 to 15.
} {5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0}

test lseq-1.8 {real increasing lseq with step} arithSeriesDouble {
    lseq 5.0 to 25. by 5
} {5.0 10.0 15.0 20.0 25.0}

test lseq-1.9 {real decreasing with step} arithSeriesDouble {
    lseq 25. to 5. by -5
} {25.0 20.0 15.0 10.0 5.0}

# note, 10 cannot be in such a list, but allowed
test lseq-1.10 {integer lseq with step} {
    lseq 1 to 10 by 2
} {1 3 5 7 9}

test lseq-1.11 {error case: increasing wrong step direction} {
    lseq 1 to 10 by -2
} {}

test lseq-1.12 {decreasing lseq with step} arithSeriesDouble {
    lseq 25. to -25. by -5
} {25.0 20.0 15.0 10.0 5.0 0.0 -5.0 -10.0 -15.0 -20.0 -25.0}

test lseq-1.13 {count operation} {
    -body {
	lseq 5 count 5
    }
    -result {5 6 7 8 9}
}

test lseq-1.14 {count with step} {
    -body {
	lseq 5 count 5 by 2
    }
    -result {5 7 9 11 13}
}

test lseq-1.15 {count with decreasing step} {
    -body {
	lseq 5 count 5 by -2
    }
    -result {5 3 1 -1 -3}
}

test lseq-1.16 {large doubles} {
    -body {
	lseq [expr {int(1e6)}] [expr {int(2e6)}] [expr {int(1e5)}]
    }
    -result {1000000 1100000 1200000 1300000 1400000 1500000 1600000 1700000 1800000 1900000 2000000}
}

test lseq-1.16.2 {large numbers (bigints are not supported yet)} -body {
    lseq 0xfffffffffffffffe 0xffffffffffffffff
} -returnCodes 1 -result {integer value too large to represent}

test lseq-1.17 {too many arguments} -body {
    lseq 12 to 24 by 2 with feeling
} -returnCodes 1 -result {wrong # args: should be "lseq n ??op? n ??by? n??"}

test lseq-1.18 {too many arguments extra valid keyword} -body {
    lseq 12 to 24 by 2 count
} -returnCodes 1 -result {wrong # args: should be "lseq n ??op? n ??by? n??"}

test lseq-1.19 {too many arguments extra numeric value} -body {
    lseq 12 to 24 by 2 7
} -returnCodes 1 -result {wrong # args: should be "lseq n ??op? n ??by? n??"}

test lseq-1.20 {bug: wrong length computed} {
    lseq 1 to 10 -1
} {}

test lseq-1.21 {n n by n} {
    lseq 66 84 by 3
} {66 69 72 75 78 81 84}

test lseq-1.22 {n n by -n} {
    lseq 84 66 by -3
} {84 81 78 75 72 69 66}

test lseq-1.23 {consistence, accept double count representable as integer (but use double in series when arguments other than count value are of type double)} {
    list [lseq 0.0 2.0] [lseq 3.0] [lseq 0 count 3.0] \
	 [lseq 0.0 count 3.0] [lseq 0 count 3.0 by 1.0]
} {{0.0 1.0 2.0} {0 1 2} {0 1 2} {0.0 1.0 2.0} {0.0 1.0 2.0}}

test lseq-1.24 {consistence, use double (even if representable as integer) in all variants, if contains a double somewhere} {
    list [lseq 0.0 2] [lseq 0 2.0] [lseq 0.0 count 3] \
	 [lseq 0 count 3 by 1.0] [lseq 0 .. 2.0] [lseq 0 to 2 by 1.0]
} [lrepeat 6 {0.0 1.0 2.0}]
test lseq-1.25 {consistence, use double (even if representable as integer) in all variants, if contains a double somewhere} {
    list [lseq double(0) 2] [lseq 0 double(2)] [lseq double(0) count 3] \
	 [lseq 0 count 3 by double(1)] [lseq 0 .. double(2)] [lseq 0 to 2 by double(1)]
} [lrepeat 6 {0.0 1.0 2.0}]
test lseq-1.26 {consistence, double always remains double} {
    list [lseq        1              3.0      ] \
	 [lseq        1       [expr {3.0+0}]  ] \
	 [lseq        1             {3.0+0}   ] \
	 [lseq        1.0            3.0     1] \
	 [lseq [expr {1.0+0}] [expr {3.0+0}] 1] \
	 [lseq       {1.0+0}        {3.0+0}  1]
} [lrepeat 6 {1.0 2.0 3.0}]
test lseq-1.27 {consistence, double always remains double} {
    list [lseq        1e50     [expr {1e50+1}]  ] \
	 [lseq        1e50           {1e50+1}   ] \
	 [lseq [expr {1e50+0}] [expr {1e50+1}] 1] \
	 [lseq       {1e50+0}        {1e50+1}  1] \
	 [lseq [expr {1e50+0}] count 1 1] \
	 [lseq       {1e50+0}  count 1 1]
} [lrepeat 6 [expr {1e50}]]

#
# Short-hand use cases
#
test lseq-2.2 {step magnitude} {
    lseq 10 1 2 ;# this is an empty case since step has wrong sign
} {}

test lseq-2.3 {step wrong sign} arithSeriesDouble {
    lseq 25. 5. 5 ;# ditto - empty list
} {}

test lseq-2.4 {integer decreasing} {
    lseq 10 1
} {10 9 8 7 6 5 4 3 2 1}

test lseq-2.5 {integer increasing} {
    lseq 1 10
} {1 2 3 4 5 6 7 8 9 10}

test lseq-2.6 {integer decreasing with step} {
    lseq 10 1 by -2
} {10 8 6 4 2}

test lseq-2.7 {real increasing lseq} arithSeriesDouble {
    lseq 5.0 15.
} {5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0}


test lseq-2.8 {real increasing lseq with step} arithSeriesDouble {
    lseq 5.0 25. 5
} {5.0 10.0 15.0 20.0 25.0}


test lseq-2.9 {real decreasing with step} arithSeriesDouble {
    lseq 25. 5. -5
} {25.0 20.0 15.0 10.0 5.0}

test lseq-2.10 {integer lseq with step} {
    lseq 1 10 2
} {1 3 5 7 9}

test lseq-2.11 {error case: increasing wrong step direction} {
    lseq 1 10 -2
} {}

test lseq-2.12 {decreasing lseq with step} arithSeriesDouble {
    lseq 25. -25. -5
} {25.0 20.0 15.0 10.0 5.0 0.0 -5.0 -10.0 -15.0 -20.0 -25.0}

test lseq-2.13 {count only operation} {
    lseq 5
} {0 1 2 3 4}

test lseq-2.14 {count with step} {
    lseq 5 count 5 2
} {5 7 9 11 13}

test lseq-2.15 {count with decreasing step} {
    lseq 5 count 5 -2
} {5 3 1 -1 -3}

test lseq-2.16 {large numbers} {
    lseq 1e6 2e6 1e5
} {1000000.0 1100000.0 1200000.0 1300000.0 1400000.0 1500000.0 1600000.0 1700000.0 1800000.0 1900000.0 2000000.0}

test lseq-2.17 {large numbers} arithSeriesDouble {
    lseq 1e6 2e6 1e5
} {1000000.0 1100000.0 1200000.0 1300000.0 1400000.0 1500000.0 1600000.0 1700000.0 1800000.0 1900000.0 2000000.0}

# Covered: {10 1 2 } {1 10 2} {1 10 -2} {1 1 1} {1 1 1} {-5 17 3}
# Missing: {- - +} {- - -} {- + -} {+ - -} {- - +} {+ + -}
test lseq-2.18 {signs} {
    list [lseq -10 -1 2] \
	[lseq -10 -1 -1] \
	[lseq -10 1 -3] \
	[lseq 10 -1 -4] \
	[lseq -10 -1 3] \
	[lseq 10 1 -5]

} {{-10 -8 -6 -4 -2} {} {} {10 6 2} {-10 -7 -4 -1} {10 5}}

test lseq-2.19 {expressions as indices} {
    list [lseq {1+1}] \
	 [lseq {1+1} {2+2}] \
	 [lseq {1+1} count {2+2}] \
	 [lseq {1+1} {5+5} {2+2}] \
	 [lseq {1+1} count {2+2} by {2+2}]
} {{0 1} {2 3 4} {2 3 4 5} {2 6 10} {2 6 10 14}}

test lseq-2.20 {expressions as indices, no duplicative eval of expr} {
    set i 1
    list [lseq {[incr i]}] $i [lseq {0 + [incr i]}] $i [lseq {0.0 + [incr i]}] $i
} {{0 1} 2 {0 1 2} 3 {0 1 2 3} 4}

test lseq-3.0 {expr error: don't swalow expr error (here: divide by zero)} -body {
    set i 0; lseq {3/$i}
} -returnCodes [catch {expr {3/0}} res] -result $res

test lseq-3.1 {experiement} -body {
    set ans {}
    foreach factor [lseq 2.0 10.0] {
	set start 1
	set end 10
	for {set step 1} {$step < 1e8} {} {
	    set l [lseq $start to $end by $step]
	    if {[llength $l] != 10} {
		lappend ans $factor $step [llength $l] $l
	    }
	    set step [expr {$step * $factor}]
	    set end [expr {$end * $factor}]
	}
    }
    if {$ans eq {}} {
	set ans OK
    }
    set ans
} -cleanup {
    unset ans step end start factor l
} -result {OK}

test lseq-3.2 {error case} -body {
    lseq foo
} -returnCodes 1 -match glob -result {invalid bareword "foo"*}

test lseq-3.3 {error case} -body {
    lseq 10 foo
} -returnCodes 1 -match glob -result {invalid bareword "foo"*}

test lseq-3.4 {error case} -body {
    lseq 25 or 6
} -returnCodes 1 -match glob -result {invalid bareword "or"*}

test lseq-3.5 {simple count and step arguments} -body {
    set s [lseq 25 by 6]
    list $s length=[llength $s]
} -cleanup {
    unset s
} -result {{0 6 12 18 24 30 36 42 48 54 60 66 72 78 84 90 96 102 108 114 120 126 132 138 144} length=25}

test lseq-3.6 {error case} -body {
    lseq 1 7 or 3
} -returnCodes 1  -result {bad operation "or": must be .., to, count, or by}
test lseq-3.6b {error case} -body {
    lseq 1 to 7 or 3
} -returnCodes 1  -result {bad operation "or": must be .., to, count, or by}

test lseq-3.7 {lmap lseq} -body {
    lmap x [lseq 5] { expr {$x * $x} }
} -cleanup {unset x} -result {0 1 4 9 16}

test lseq-3.8 {lrange lseq} -body {
    set r [lrange [lseq 1 100] 10 20]
    set empty [lrange [lseq 1 100] 20 10]
    list $r $empty [lindex [tcl::unsupported::representation $r] 3]
} -cleanup {
    unset r empty
} -result {{11 12 13 14 15 16 17 18 19 20 21} {} arithseries}

test lseq-3.9 {lassign lseq} -constraints arithSeriesShimmer -body {
    set r [lseq 15]
    set r2 [lassign $r a b]
    list [lindex [tcl::unsupported::representation $r] 3] $a $b \
	[lindex [tcl::unsupported::representation $r2] 3]
} -cleanup {unset r r2 a b} -result {arithseries 0 1 arithseries}

test lseq-3.10 {lsearch lseq must shimmer?} -constraints arithSeriesShimmer -body {
    set r [lseq 15 0]
    set a [lsearch $r 9]
    list [lindex [tcl::unsupported::representation $r] 3] $a
} -cleanup {unset r a} -result {arithseries 6}

test lseq-3.11 {lreverse lseq} -body {
    set r [lseq 15 0]
    set a [lreverse $r]
    join [list \
	      [lindex [tcl::unsupported::representation $r] 3] \
	      $r \
	      [lindex [tcl::unsupported::representation $a] 3] \
	      $a] \n
} -cleanup {unset r a} -result {arithseries
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
arithseries
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15}

test lseq-3.12 {in operator} -body {
    set r [lseq 9]
    set i [expr {7 in $r}]
    set j [expr {10 ni $r}]
    set k [expr {-1 in $r}]
    set l [expr {4 ni $r}]
    list $i $j $k $l [lindex [tcl::unsupported::representation $r] 3]
} -cleanup {
    unset r i j k l
} -result {1 1 0 0 arithseries}

test lseq-3.13 {lmap lseq shimmer} -constraints arithSeriesShimmer -body {
    set r [lseq 15]
    set rep-before [lindex [tcl::unsupported::representation $r] 3]
    set m [lmap i $r { expr {$i * 7} }]
    set rep-after [lindex [tcl::unsupported::representation $r] 3]
    set rep-m [lindex [tcl::unsupported::representation $m] 3]
    list $r ${rep-before} ${rep-after} ${rep-m} $m
} -cleanup {
    unset r rep-before m rep-after rep-m
} -result {{0 1 2 3 4 5 6 7 8 9 10 11 12 13 14} arithseries arithseries list {0 7 14 21 28 35 42 49 56 63 70 77 84 91 98}}

test lseq-3.14 {array for shimmer} -constraints arithSeriesShimmerOk -body {
    array set testarray {a Test for This great Function}
    set vars [lseq 2]
    set vars-rep [lindex [tcl::unsupported::representation $vars] 3]
    array for $vars testarray {
	lappend keys $0
	lappend vals $1
    }
    # Since hash order is not guaranteed, have to validate content ignoring order
    set valk [lmap k $keys {expr {$k in {a for great}}}]
    set valv [lmap v $vals {expr {$v in {Test This Function}}}]
    set vars-after [lindex [tcl::unsupported::representation $vars] 3]
    list ${vars-rep} $valk $valv ${vars-after}
} -cleanup {
    unset testarray vars vars-rep 0 valk k  valv v vars-after
} -result {arithseries {1 1 1} {1 1 1} arithseries}

test lseq-3.15 {join for shimmer} -constraints arithSeriesShimmer -body {
    set r [lseq 3]
    set rep-before [lindex [tcl::unsupported::representation $r] 3]
    set str [join $r :]
    set rep-after [lindex [tcl::unsupported::representation $r] 3]
    list ${rep-before} $str ${rep-after}
} -cleanup {
    unset r rep-before str rep-after
} -result {arithseries 0:1:2 arithseries}

test lseq-3.16 {error case} -body {
    lseq 16 to
} -returnCodes 1 -result {missing "to" value.}

test lseq-3.17 {error case} -body {
    lseq 17 to 13 by
} -returnCodes 1 -result {missing "by" value.}

test lseq-3.18 {error case} -body {
    lseq 18 count
} -returnCodes 1 -result {missing "count" value.}

test lseq-3.19 {edge case} -body {
    lseq 1 count 5 by 0
} -result {}
# 1 1 1 1 1

# My thought is that this is likely a user error, since they can always use lrepeat for this.

test lseq-3.20 {edge case} -body {
    lseq 1 to 1 by 0
} -result {}

# hmmm, I guess this is right, in a way, so...

test lseq-3.21 {edge case} {
    lseq 1 to 1 by 1
} {1}

test lseq-3.22 {edge case} {
    lseq 1 1 1
} {1}

test lseq-3.23 {edge case} {
    llength [lseq 1 1 1]
} {1}

test lseq-3.24 {edge case} {
    llength [lseq 1 to 1 1]
} {1}

test lseq-3.25 {edge case} {
    llength [lseq 1 to 1 by 1]
} {1}

test lseq-3.26 {lsort shimmer} -constraints arithSeriesShimmer -body {
    set r [lseq 15 0]
    set rep-before [lindex [tcl::unsupported::representation $r] 3]
    set lexical_sort [lsort $r]
    set rep-after [lindex [tcl::unsupported::representation $r] 3]
    list ${rep-before} $lexical_sort ${rep-after}
} -cleanup {
    unset r rep-before lexical_sort rep-after
} -result {arithseries {0 1 10 11 12 13 14 15 2 3 4 5 6 7 8 9} arithseries}

test lseq-3.27 {lreplace shimmer} -constraints arithSeriesShimmer -body {
    set r [lseq 15 0]
    set rep-before [lindex [tcl::unsupported::representation $r] 3]
    set lexical_sort [lreplace $r 3 5 A B C]
    set rep-after [lindex [tcl::unsupported::representation $r] 3]
    list ${rep-before} $lexical_sort ${rep-after}
} -cleanup {
    unset r
    unset rep-before
    unset lexical_sort
    unset rep-after
} -result {arithseries {15 14 13 A B C 9 8 7 6 5 4 3 2 1 0} arithseries}

test lseq-3.28 {lreverse bug in ArithSeries} -body {
    set r [lseq -5 17 3]
    set rr [lreverse $r]
    list $r $rr [string equal $r [lreverse $rr]]
} -cleanup {
    unset r rr
} -result {{-5 -2 1 4 7 10 13 16} {16 13 10 7 4 1 -2 -5} 1}

test lseq-3.29 {edge case: negative count} {
    lseq -15
} {}

test lseq-3.30 {lreverse with double values} -constraints arithSeriesDouble -body {
    set r [lseq 3.5 18.5 1.5]
    set a [lreverse $r]
    join [list \
	      [lindex [tcl::unsupported::representation $r] 3] \
	      $r \
	      [lindex [tcl::unsupported::representation $a] 3] \
	      $a] \n
} -cleanup {
    unset r a
} -result {arithseries
3.5 5.0 6.5 8.0 9.5 11.0 12.5 14.0 15.5 17.0 18.5
arithseries
18.5 17.0 15.5 14.0 12.5 11.0 9.5 8.0 6.5 5.0 3.5}

test lseq-3.31 {lreverse inplace with doubles} {arithSeriesDouble} {
    lreverse [lseq 1.1 29.9 0.3]
} {29.9 29.6 29.3 29.0 28.7 28.4 28.1 27.8 27.5 27.2 26.9 26.6 26.3 26.0 25.7 25.4 25.1 24.8 24.5 24.2 23.9 23.6 23.3 23.0 22.7 22.4 22.1 21.8 21.5 21.2 20.9 20.6 20.3 20.0 19.7 19.4 19.1 18.8 18.5 18.2 17.9 17.6 17.3 17.0 16.7 16.4 16.1 15.8 15.5 15.2 14.9 14.6 14.3 14.0 13.7 13.4 13.1 12.8 12.5 12.2 11.9 11.6 11.3 11.0 10.7 10.4 10.1 9.8 9.5 9.2 8.9 8.6 8.3 8.0 7.7 7.4 7.1 6.8 6.5 6.2 5.9 5.6 5.3 5.0 4.7 4.4 4.1 3.8 3.5 3.2 2.9 2.6 2.3 2.0 1.7 1.4 1.1}

# lsearch -
#  -- should not shimmer lseq  list
#  -- should not leak lseq elements
test lseq-3.32 {lsearch nested lists of lseq} -constraints arithSeriesShimmer -body {
    set srchlist {}
    for {set i 5} {$i < 25} {incr i} {
	lappend srchlist [lseq $i count 7 by 3]
    }
    set a [lsearch -all -inline -index 1 $srchlist 23]
    set b [lmap i $a {lindex [tcl::unsupported::representation $i] 3}]
    list [lindex [tcl::unsupported::representation $a] 3] $a $b \
	[lindex [tcl::unsupported::representation [lindex $srchlist 15]] 3]
} -cleanup {
    unset a b srchlist i
} -result {list {{20 23 26 29 32 35 38}} arithseries arithseries}


# lsearch -
#  -- should not shimmer lseq  list
#  -- should not leak lseq elements
test lseq-3.33 {lsearch nested lists of lseq} -constraints arithSeriesShimmer -body {
    set srchlist {}
    for {set i 5} {$i < 25} {incr i} {
	lappend srchlist [lseq $i count 7 by 3]
    }
    set a [lsearch -all -inline -index 1 $srchlist 23]
    set b [lmap i $a {lindex [tcl::unsupported::representation $i] 3}]
    list [lindex [tcl::unsupported::representation $a] 3] $a $b \
	[lindex [tcl::unsupported::representation [lindex $srchlist 15]] 3]
} -cleanup {
    unset srchlist i a b
} -result {list {{20 23 26 29 32 35 38}} arithseries arithseries}

test lseq-3.34 {"in" operator} -body {
    set seq [lseq 0.3 15e4 0.1]
    set inlist {}
    set nilist {}
    foreach y [lseq 3012.0 3013.0 0.03] {
	if {$y in $seq} {
	    lappend inlist $y
	} else {
	    lappend nilist $y
	}
    }
    list $inlist $nilist
} -cleanup {
    unset seq inlist nilist y
} -result {{3012.0 3012.3 3012.6 3012.9} {3012.03 3012.06 3012.09 3012.12 3012.15 3012.18 3012.21 3012.24 3012.27 3012.33 3012.36 3012.39 3012.42 3012.45 3012.48 3012.51 3012.54 3012.57 3012.63 3012.66 3012.69 3012.72 3012.75 3012.78 3012.81 3012.84 3012.87 3012.93 3012.96 3012.99}}

test lseq-3.35 {"in" operator integer} -body {
    set seq [lseq 3 int(15e4) 5]
    set inlist {}
    set nilist {}
    foreach y [lseq 3012 3213 3] {
	if {$y in $seq} {
	    lappend inlist $y
	} else {
	    lappend nilist $y
	}
    }
    list $inlist $nilist
} -cleanup {
    unset seq inlist nilist y
} -result {{3018 3033 3048 3063 3078 3093 3108 3123 3138 3153 3168 3183 3198 3213} {3012 3015 3021 3024 3027 3030 3036 3039 3042 3045 3051 3054 3057 3060 3066 3069 3072 3075 3081 3084 3087 3090 3096 3099 3102 3105 3111 3114 3117 3120 3126 3129 3132 3135 3141 3144 3147 3150 3156 3159 3162 3165 3171 3174 3177 3180 3186 3189 3192 3195 3201 3204 3207 3210}}

test lseq-3.36 {"in" non-numeric case} -body {
    if {"barney" in [lseq 15]} {
	set res found
    } else {
	set res not-found
    }
    set res
} -cleanup {
    unset res
} -result {not-found}

test lseq-4.1 {end expressions} -body {
    set start 7
    lseq $start $start+11
} -cleanup {unset start} -result {7 8 9 10 11 12 13 14 15 16 17 18}

test lseq-4.2 {start expressions} -body {
    set base [clock seconds]
    set tl [lseq $base-60 $base 10]
    lmap t $tl {expr {$t - $base + 60}}
} -cleanup {unset base tl t} -result {0 10 20 30 40 50 60}

##	lseq 1 to 10 by -2
##	# -> lseq: invalid step = -2 with a = 1 and b = 10

test lseq-4.3 {TIP examples} -body {
    set examples {# Examples from TIP-629
	# --- Begin ---
	lseq 10 .. 1
	# -> 10 9 8 7 6 5 4 3 2 1
	lseq 1 .. 10
	# -> 1 2 3 4 5 6 7 8 9 10
	lseq 10 .. 1 by 2
	# ->
	lseq 10 .. 1 by -2
	# -> 10 8 6 4 2
	lseq 5.0 to 15.
	# -> 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0
	lseq 5.0 to 25. by 5
	# -> 5.0 10.0 15.0 20.0 25.0
	lseq 25. to 5. by 5
	# ->
	lseq 25. to 5. by -5
	# -> 25.0 20.0 15.0 10.0 5.0
	lseq 1 to 10 by 2
	# -> 1 3 5 7 9
	lseq 25. to -25. by -5
	# -> 25.0 20.0 15.0 10.0 5.0 0.0 -5.0 -10.0 -15.0 -20.0 -25.0
	lseq 5 5
	# -> 5
	lseq 5 5 2
	# -> 5
	lseq 5 5 -2
	# -> 5
    }
    set res {}
    foreach {cmd expect} [split $examples \n] {
	if {[string trim $cmd] ne ""} {
	    set cmd [string trimleft $cmd]
	    if {[string match {\#*} $cmd]} continue
	    set status [catch $cmd ans]
	    lappend res $ans
	    if {[regexp {\# -> (.*)$} $expect -> expected]} {
		if {$expected ne $ans} {
		    lappend res [list Mismatch: $cmd -> $ans ne $expected]
		}
	    }
	}
    }
    set res
} -cleanup {
    unset res cmd status ans expect expected examples
} -result {{10 9 8 7 6 5 4 3 2 1} {1 2 3 4 5 6 7 8 9 10} {} {10 8 6 4 2} {5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0} {5.0 10.0 15.0 20.0 25.0} {} {25.0 20.0 15.0 10.0 5.0} {1 3 5 7 9} {25.0 20.0 15.0 10.0 5.0 0.0 -5.0 -10.0 -15.0 -20.0 -25.0} 5 5 5}

#
# Ticket 9933cc4d88697f05976accebd31c1e3ba6efe9c6 - lseq corner case
test lseq-4.4 {lseq corner case} -constraints has64BitLengths -body {
    set tcmd {
	set res {}
	set s [catch {lindex [lseq 10 100] 0} e]
	lappend res $s $e
	set s [catch {lindex [lseq 10 9223372036854775000] 0} e]
	lappend res $s $e
	set s [catch {llength [lseq 10 9223372036854775000]} e]
	lappend res $s $e
	set s [catch {lindex [lseq 10 2147483647] 0} e]
	lappend res $s $e
	set s [catch {llength [lseq 10 2147483647]} e]
	lappend res $s $e
    }
    eval $tcmd
} -cleanup {
    unset res s e tcmd
} -result {0 10 0 10 0 9223372036854774991 0 10 0 2147483638}

test lseq-4.4.32 {lseq corner case} -constraints has32BitLengths -body {
    set tcmd {
	set res {}
	set s [catch {lindex [lseq 10 100] 0} e]
	lappend res $s $e
	set s [catch {lindex [lseq 10 9223372036854775000] 0} e]
	lappend res $s $e
	set s [catch {llength [lseq 10 9223372036854775000]} e]
	lappend res $s $e
	set s [catch {lindex [lseq 10 2147483647] 0} e]
	lappend res $s $e
	set s [catch {llength [lseq 10 2147483647]} e]
	lappend res $s $e
    }
    eval $tcmd
} -cleanup {
    unset res s e tcmd
} -result {0 10 1 {max length of a Tcl list exceeded} 1 {max length of a Tcl list exceeded} 0 10 0 2147483638}

# Ticket 99e834bf33 - lseq, lindex end off by one

test lseq-4.5 {lindex off by one} -body {
    lappend res [eval {lindex [lseq 1 4] end}]
    lappend res [eval {lindex [lseq 1 4] end-1}]
} -cleanup {
    unset res
} -result {4 3}

# Bad refcount on ResultObj
test lseq-4.6 {lindex flat} -body {
    set l [lseq 2 10]
    set cmd lindex
    set i 4
    set c [lindex $l $i]
    set d [$cmd $l $i]
    set e [lindex [lseq 2 10] $i]
    set f [$cmd [lseq 2 10] $i]
    list $c $d $e $f
} -cleanup {
    unset l cmd i c d e f
} -result [lrepeat 4 6]

test lseq-4.7 {empty list} {
    list [lseq 0] [join [lseq 0] {}] [join [lseq 1] {}]
} {{} {} 0}

test lseq-4.8 {error case lrange} -body {
    lrange [lseq 1 5] fred ginger
} -cleanup {
    unset -nocomplain fred ginger
} -returnCodes 1 -result {bad index "fred": must be integer?[+-]integer? or end?[+-]integer?}

test lseq-4.9 {lrange empty/partial sets} -body {
    set res {}
    foreach {fred ginger} {7 8 4 9 0 15 9 9 4 2} {
	lappend res [lrange [lseq 1 5] $fred $ginger]
    }
    set res
} -cleanup {unset res fred ginger} -result {{} 5 {1 2 3 4 5} {} {}}

# Panic when using variable value?
test lseq-4.10 {panic using variable index} -body {
    set i 0
    lindex [lseq 10] $i
} -cleanup {unset i} -result {0}

test lseq-4.11 {bug lseq / lindex discrepancies} -body {
    lindex [lseq 0x7fffffff] 0x80000000
} -result {}

test lseq-4.12 {bug lseq} -constraints has64BitLengths -body {
    llength [lseq 0x100000000]
} -result {4294967296}

test lseq-4.12.32 {bug lseq} -constraints has32BitLengths -body {
    llength [lseq 0x100000000]
} -returnCodes 1 -result {max length of a Tcl list exceeded}

test lseq-4.13 {bug lseq} -constraints has64BitLengths -body {
    set l [lseq 0x7fffffffffffffff]
    list \
    [llength $l] \
    [lindex $l end] \
	[lindex $l 9223372036854775800]
} -cleanup {unset l} -result {9223372036854775807 9223372036854775806 9223372036854775800}


test lseq-4.14 {bug lseq - inconsistent rounding} {
    # using a non-integer increment, [lseq] rounding seems to be not consistent:
    lseq 4 40 0.1
} {4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7.0 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 8.0 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 9.0 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 10.0 10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 11.0 11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9 12.0 12.1 12.2 12.3 12.4 12.5 12.6 12.7 12.8 12.9 13.0 13.1 13.2 13.3 13.4 13.5 13.6 13.7 13.8 13.9 14.0 14.1 14.2 14.3 14.4 14.5 14.6 14.7 14.8 14.9 15.0 15.1 15.2 15.3 15.4 15.5 15.6 15.7 15.8 15.9 16.0 16.1 16.2 16.3 16.4 16.5 16.6 16.7 16.8 16.9 17.0 17.1 17.2 17.3 17.4 17.5 17.6 17.7 17.8 17.9 18.0 18.1 18.2 18.3 18.4 18.5 18.6 18.7 18.8 18.9 19.0 19.1 19.2 19.3 19.4 19.5 19.6 19.7 19.8 19.9 20.0 20.1 20.2 20.3 20.4 20.5 20.6 20.7 20.8 20.9 21.0 21.1 21.2 21.3 21.4 21.5 21.6 21.7 21.8 21.9 22.0 22.1 22.2 22.3 22.4 22.5 22.6 22.7 22.8 22.9 23.0 23.1 23.2 23.3 23.4 23.5 23.6 23.7 23.8 23.9 24.0 24.1 24.2 24.3 24.4 24.5 24.6 24.7 24.8 24.9 25.0 25.1 25.2 25.3 25.4 25.5 25.6 25.7 25.8 25.9 26.0 26.1 26.2 26.3 26.4 26.5 26.6 26.7 26.8 26.9 27.0 27.1 27.2 27.3 27.4 27.5 27.6 27.7 27.8 27.9 28.0 28.1 28.2 28.3 28.4 28.5 28.6 28.7 28.8 28.9 29.0 29.1 29.2 29.3 29.4 29.5 29.6 29.7 29.8 29.9 30.0 30.1 30.2 30.3 30.4 30.5 30.6 30.7 30.8 30.9 31.0 31.1 31.2 31.3 31.4 31.5 31.6 31.7 31.8 31.9 32.0 32.1 32.2 32.3 32.4 32.5 32.6 32.7 32.8 32.9 33.0 33.1 33.2 33.3 33.4 33.5 33.6 33.7 33.8 33.9 34.0 34.1 34.2 34.3 34.4 34.5 34.6 34.7 34.8 34.9 35.0 35.1 35.2 35.3 35.4 35.5 35.6 35.7 35.8 35.9 36.0 36.1 36.2 36.3 36.4 36.5 36.6 36.7 36.8 36.9 37.0 37.1 37.2 37.3 37.4 37.5 37.6 37.7 37.8 37.9 38.0 38.1 38.2 38.3 38.4 38.5 38.6 38.7 38.8 38.9 39.0 39.1 39.2 39.3 39.4 39.5 39.6 39.7 39.8 39.9 40.0}

test lseq-4.15 {bug lseq - inconsistent rounding} {
    # using a non-integer increment, [lseq] rounding seems to be not consistent:
    lseq 6 40 0.1
} {6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7.0 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 8.0 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 9.0 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 10.0 10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 11.0 11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9 12.0 12.1 12.2 12.3 12.4 12.5 12.6 12.7 12.8 12.9 13.0 13.1 13.2 13.3 13.4 13.5 13.6 13.7 13.8 13.9 14.0 14.1 14.2 14.3 14.4 14.5 14.6 14.7 14.8 14.9 15.0 15.1 15.2 15.3 15.4 15.5 15.6 15.7 15.8 15.9 16.0 16.1 16.2 16.3 16.4 16.5 16.6 16.7 16.8 16.9 17.0 17.1 17.2 17.3 17.4 17.5 17.6 17.7 17.8 17.9 18.0 18.1 18.2 18.3 18.4 18.5 18.6 18.7 18.8 18.9 19.0 19.1 19.2 19.3 19.4 19.5 19.6 19.7 19.8 19.9 20.0 20.1 20.2 20.3 20.4 20.5 20.6 20.7 20.8 20.9 21.0 21.1 21.2 21.3 21.4 21.5 21.6 21.7 21.8 21.9 22.0 22.1 22.2 22.3 22.4 22.5 22.6 22.7 22.8 22.9 23.0 23.1 23.2 23.3 23.4 23.5 23.6 23.7 23.8 23.9 24.0 24.1 24.2 24.3 24.4 24.5 24.6 24.7 24.8 24.9 25.0 25.1 25.2 25.3 25.4 25.5 25.6 25.7 25.8 25.9 26.0 26.1 26.2 26.3 26.4 26.5 26.6 26.7 26.8 26.9 27.0 27.1 27.2 27.3 27.4 27.5 27.6 27.7 27.8 27.9 28.0 28.1 28.2 28.3 28.4 28.5 28.6 28.7 28.8 28.9 29.0 29.1 29.2 29.3 29.4 29.5 29.6 29.7 29.8 29.9 30.0 30.1 30.2 30.3 30.4 30.5 30.6 30.7 30.8 30.9 31.0 31.1 31.2 31.3 31.4 31.5 31.6 31.7 31.8 31.9 32.0 32.1 32.2 32.3 32.4 32.5 32.6 32.7 32.8 32.9 33.0 33.1 33.2 33.3 33.4 33.5 33.6 33.7 33.8 33.9 34.0 34.1 34.2 34.3 34.4 34.5 34.6 34.7 34.8 34.9 35.0 35.1 35.2 35.3 35.4 35.5 35.6 35.7 35.8 35.9 36.0 36.1 36.2 36.3 36.4 36.5 36.6 36.7 36.8 36.9 37.0 37.1 37.2 37.3 37.4 37.5 37.6 37.7 37.8 37.9 38.0 38.1 38.2 38.3 38.4 38.5 38.6 38.7 38.8 38.9 39.0 39.1 39.2 39.3 39.4 39.5 39.6 39.7 39.8 39.9 40.0}

test lseq-4.16 {bug lseq - inconsistent rounding} {
    # using a non-integer increment, [lseq] rounding seems to be not consistent:
    set res {}
    lappend res [lseq 4.07 6 0.1]
    lappend res [lseq 4.03 4.208 0.013]
} {{4.07 4.17 4.27 4.37 4.47 4.57 4.67 4.77 4.87 4.97 5.07 5.17 5.27 5.37 5.47 5.57 5.67 5.77 5.87 5.97} {4.03 4.043 4.056 4.069 4.082 4.095 4.108 4.121 4.134 4.147 4.16 4.173 4.186 4.199}}

# Test abstract list in a concat
#  -- lseq list should not shimmer
#  -- lseq elements should not leak
test lseq-4.17 {concat shimmer} -body {
    set rng [lseq 8 15 2]
    set pre [list A b C]
    set pst [list x Y z]
    list [concat $pre $rng $pst] \
	 [lindex [tcl::unsupported::representation $pre] 3] \
	 [lindex [tcl::unsupported::representation $rng] 3] \
	 [lindex [tcl::unsupported::representation $pst] 3]
} -cleanup {unset rng pre pst} -result  {{A b C 8 10 12 14 x Y z} list arithseries list}

test lseq-4.18 {concat shimmer} -body {
    set rng [lseq 8 15 2]
    set pre [list A b C]
    set pst [list x Y z]
    list [concat $rng $pre $pst] \
	 [lindex [tcl::unsupported::representation $rng] 3] \
	 [lindex [tcl::unsupported::representation $pre] 3] \
	 [lindex [tcl::unsupported::representation $pst] 3]
} -cleanup {unset rng pre pst} -result {{8 10 12 14 A b C x Y z} arithseries list list}

# Test lseq elements as var names
test lseq-4.19 {varnames} -body {
    set plist {}
    foreach v {auto_execok auto_load auto_qualify} {
	lappend plist proc $v [info args $v] [info body $v]
    }
    set res {}
    set varlist [lseq 1 to 4]
    foreach $varlist $plist {
	lappend res $2 [llength $3]
    }
    lappend res [lindex [tcl::unsupported::representation $varlist] 3]
} -cleanup {
    unset {*}$varlist res varlist v plist
} -result {auto_execok 1 auto_load 2 auto_qualify 2 arithseries}

test lseq-4.20 {lindex on lseq without index args, bug a9625d1f53554f9d} -body {
    set res [lindex [lseq 1000]]
    list [llength $res] [lindex $res 0] [lindex $res end]
} -cleanup {
    unset -nocomplain res
} -result {1000 0 999}

test lseq-convertToList {does not result in a memory error} -body {
	trace add variable var1 write [list ::apply [list args {
		error {this is an error}
	} [namespace current]]]
	list [catch {set var1 [lindex [lreplace [lseq 1 2] 1 1 hello] 0]} cres] $cres
} -cleanup {unset var1 cres} -result {1 {can't set "var1": this is an error}}

test lseq-bug-54329e39c7 {does not cause memory bloat} -constraints {
    hasMemUsage
} -body {
    set l [lseq 1000000]
    proc p l {foreach x $l {}}
    set premem [memusage]
    p $l
    set postmem [memusage]
    expr {[string match *purify* [tcl::build-info]] || ($postmem - $premem < 10) ? 1 : ($postmem - $premem)}
} -result 1

test lseq-bug-578b7e273c03-1 {Arithmetic Series Objects get wrong precision when end value is not specified} -body {
    set bl [expr {2.8 in [lseq 0 count 100 by .1]}]
    lappend bl [expr {2.8 in [lseq 0 count 200 by .1]}]
    lappend bl [expr {0.28 in [lseq 0 count 100 by .01]}]
    lappend bl [expr {0.28 in [lseq 0 count 200 by .01]}]
    lappend bl [expr {0.286 in [lseq 0 count 100 by .011]}]
    lappend bl [expr {0.286 in [lseq 0 count 200 by .011]}]
} -result {1 1 1 1 1 1}

test lseq-bug-578b7e273c03-2 {Arithmetic Series Objects get wrong precision when end value is not specified} -body {
    set ll [llength [lseq 0 count 100 by .1]]
    lappend ll [llength [lseq 0 count 200 by .1]]
    lappend ll [llength [lseq 0 count 100 by .01]]
    lappend ll [llength [lseq 0 count 200 by .01]]
    lappend ll [llength [lseq 0 count 100 by .011]]
    lappend ll [llength [lseq 0 count 200 by .011]]
} -result {100 200 100 200 100 200}

test lseq-bug-f4a4bd7f1070-1 {} -body {
    set result {}
    lappend result [catch {lseq 3.1} msg]
    lappend result $msg
    lappend result [catch {lseq 5 count 3.0} msg]
    lappend result $msg
    lappend result [lseq 3]
    lappend result [lseq 3.0]
    lappend result [lseq 5.1e1]
    lappend result [string compare [lseq 3] [lseq 3.0]]
    set result
} -result {1 {expected integer but got "3.1"} 0 {5 6 7} {0 1 2} {0 1 2} {0 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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50} 0}

# cleanup
::tcltest::cleanupTests

return

# Local Variables:
# mode: tcl
# End:

Changes to tests/lset.test.

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
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








-
+










-
+







# This file is a -*- tcl -*- test script

# Commands covered: lset
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
# Copyright © 2001 Kevin B. Kenny.  All rights reserved.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

proc failTrace {name1 name2 op} {
    error "trace failed"
}

testConstraint testevalex [llength [info commands testevalex]]

408
409
410
411
412
413
414
415

416
417
418
419
420
421
422
408
409
410
411
412
413
414

415
416
417
418
419
420
421
422







-
+







test lset-14.2 {lset, not compiled, flat args, is string rep preserved?} testevalex {
    set a { { 1 2 } { 3 4 } }
    catch { testevalex {lset a 1 5 5} }
    list $a [lindex $a 1]
} "{ { 1 2 } { 3 4 } } { 3 4 }"

testConstraint testobj [llength [info commands testobj]]
test lset-15.1 {lset: shared intrep [Bug 1677512]} -setup {
test lset-15.1 {lset: shared internalrep [Bug 1677512]} -setup {
    teststringobj set 1 {{1 2} 3}
    testobj convert 1 list
    testobj duplicate 1 2
    variable x [teststringobj get 1]
    variable y [teststringobj get 2]
    testobj freeallvars
    set l [list $y z]

Changes to tests/lsetComp.test.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







# This file is a -*- tcl -*- test script

# Commands covered: lset
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
# Copyright © 2001 Kevin B. Kenny.  All rights reserved.
#
# 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::*

Changes to tests/macOSXFCmd.test.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







# This file tests the tclMacOSXFCmd.c file.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 2003 Tcl Core Team.
# Copyright © 2003 Tcl Core Team.
#
# 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::*
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
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







-
+
















-
+







	    [file delete -force -- foo.test]
} {0 {} 0 1 {}}
test macOSXFCmd-2.7 {MacOSXSetFileAttribute - rsrclength} {macosxFileAttr notRoot nonPortable} {
    catch {file delete -force -- foo.test}
    close [open foo.test w]
    catch {
	set f [open foo.test/..namedfork/rsrc w]
	fconfigure $f -translation lf -eofchar {}
	fconfigure $f -translation lf
	puts -nonewline $f "foo"
	close $f
    }
    list [catch {file attributes foo.test -rsrclength} msg] $msg \
	    [catch {file attributes foo.test -rsrclength 0} msg] $msg \
	    [catch {file attributes foo.test -rsrclength} msg] $msg \
	    [file delete -force -- foo.test]
} {0 3 0 {} 0 0 {}}

test macOSXFCmd-3.1 {MacOSXCopyFileAttributes} {macosxFileAttr notRoot} {
    catch {file delete -force -- foo.test}
    catch {file delete -force -- bar.test}
    close [open foo.test w]
    catch {
	file attributes foo.test -creator FOOC -type FOOT -hidden 1
	set f [open foo.test/..namedfork/rsrc w]
	fconfigure $f -translation lf -eofchar {}
	fconfigure $f -translation lf
	puts -nonewline $f "foo"
	close $f
	file copy foo.test bar.test
    }
    list [catch {file attributes bar.test -creator} msg] $msg \
	    [catch {file attributes bar.test -type} msg] $msg \
	    [catch {file attributes bar.test -hidden} msg] $msg \

Changes to tests/macOSXLoad.test.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







# Commands covered:  load unload
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1995 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*

Changes to tests/main.test.

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
30
31
32
33
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
30
31













-
+
-
-
-
-
-
+
+
+





-
-
+
+







# This file contains a collection of tests for generic/tclMain.c.

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

namespace eval ::tcl::test::main {
    namespace import ::tcltest::*

    # Is [exec] defined?
    testConstraint exec [llength [info commands exec]]

    # Is the Tcltest package loaded?
    # Is the tcl::test package loaded?
    #	- that is, the special C-coded testing commands in tclTest.c
    #   - tests use testing commands introduced in Tcltest 8.4
    testConstraint Tcltest [expr {
	[llength [package provide Tcltest]]
	&& [package vsatisfies [package provide Tcltest] 8.5-]}]
    testConstraint tcl::test [expr {
	[llength [package provide tcl::test]]
	&& [package vsatisfies [package provide tcl::test] 8.5-]}]

    # Procedure to simulate interactive typing of commands, line by line
    proc type {chan script} {
	foreach line [split $script \n] {
	    if {[catch {
	        puts $chan $line
	        flush $chan
		puts $chan $line
		flush $chan
	    }]} {
		return
	    }
	    # Grrr... Behavior depends on this value.
	    after 1000
	}
    }
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
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







-
+






-
+






-
+






-
+





-
-
+
+




-
+

-
+





-
-
+
+




-
+

-
+











-
-
+
+




















-
+

-
+


















-
+

















-
+















-
+












-
+















-
+













-
+







    } -result [list [interpreter] -script 0]\n

    test Tcl_Main-1.3 {
    } -constraints {
	stdio
    } -setup {
	makeFile {puts [list $argv0 $argv $tcl_interactive]} script
	catch {set f [open "|[list [interpreter] script \u00c0]" r]}
	catch {set f [open "|[list [interpreter] script À]" r]}
    } -body {
	read $f
    } -cleanup {
	close $f
	removeFile script
    } -result [list script [list [encoding convertfrom [encoding system] \
	[encoding convertto [encoding system] \u00c0]]] 0]\n
	[encoding convertto [encoding system] À]]] 0]\n

    test Tcl_Main-1.4 {
    } -constraints {
	stdio
    } -setup {
	makeFile {puts [list $argv0 $argv $tcl_interactive]} script
	catch {set f [open "|[list [interpreter] script \u20ac]" r]}
	catch {set f [open "|[list [interpreter] script €]" r]}
    } -body {
	read $f
    } -cleanup {
	close $f
	removeFile script
    } -result [list script [list [encoding convertfrom [encoding system] \
	[encoding convertto [encoding system] \u20ac]]] 0]\n
	[encoding convertto [encoding system] €]]] 0]\n

    test Tcl_Main-1.5 {
    } -constraints {
	stdio
    } -setup {
	makeFile {puts [list $argv0 $argv $tcl_interactive]} \u00c0
	catch {set f [open "|[list [interpreter] \u00c0]" r]}
	makeFile {puts [list $argv0 $argv $tcl_interactive]} À
	catch {set f [open "|[list [interpreter] À]" r]}
    } -body {
	read $f
    } -cleanup {
	close $f
	removeFile \u00c0
	removeFile À
    } -result [list [list [encoding convertfrom [encoding system] \
	[encoding convertto [encoding system] \u00c0]]] {} 0]\n
	[encoding convertto [encoding system] À]]] {} 0]\n

    test Tcl_Main-1.6 {
    } -constraints {
	stdio
    } -setup {
	makeFile {puts [list $argv0 $argv $tcl_interactive]} \u20ac
	catch {set f [open "|[list [interpreter] \u20ac]" r]}
	makeFile {puts [list $argv0 $argv $tcl_interactive]} €
	catch {set f [open "|[list [interpreter] €]" r]}
    } -body {
	read $f
    } -cleanup {
	close $f
	removeFile \u20ac
	removeFile €
    } -result [list [list [encoding convertfrom [encoding system] \
	[encoding convertto [encoding system] \u20ac]]] {} 0]\n
	[encoding convertto [encoding system] €]]] {} 0]\n

    test Tcl_Main-1.7 {
	Tcl_Main: startup script - -encoding option
    } -constraints {
	stdio
    } -setup {
	set script [makeFile {} script]
	file delete $script
	set f [open $script w]
	chan configure $f -encoding utf-8
	puts $f {puts [list $argv0 $argv $tcl_interactive]}
	puts -nonewline $f {puts [string equal \u20ac }
	puts $f "\u20ac]"
	puts -nonewline $f {puts [string equal € }
	puts $f "€]"
	close $f
	catch {set f [open "|[list [interpreter] -encoding utf-8 script]" r]}
    } -body {
	read $f
    } -cleanup {
	close $f
	removeFile script
    } -result [list script {} 0]\n1\n

    test Tcl_Main-1.8 {
	Tcl_Main: startup script - -encoding option - mismatched encodings
    } -constraints {
	stdio
    } -setup {
	set script [makeFile {} script]
	file delete $script
	set f [open $script w]
	chan configure $f -encoding utf-8
	puts $f {puts [list $argv0 $argv $tcl_interactive]}
	puts -nonewline $f {puts [string equal \u20ac }
	puts $f "\u20ac]"
	puts $f "€]"
	close $f
	catch {set f [open "|[list [interpreter] -encoding ascii script]" r]}
	catch {set f [open "|[list [interpreter] -encoding iso8859-1 script]" r]}
    } -body {
	read $f
    } -cleanup {
	close $f
	removeFile script
    } -result [list script {} 0]\n0\n

    test Tcl_Main-1.9 {
	Tcl_Main: startup script - -encoding option - no abbrevation
    } -constraints {
	stdio
    } -setup {
	set script [makeFile {} script]
	file delete $script
	set f [open $script w]
	chan configure $f -encoding utf-8
	puts $f {puts [list $argv0 $argv $tcl_interactive]}
	puts -nonewline $f {puts [string equal \u20ac }
	puts $f "\u20ac]"
	puts $f "€]"
	close $f
	catch {set f [open "|[list [interpreter] -enc utf-8 script]" r+]}
    } -body {
	type $f {
	    puts $argv
	}
	list [catch {gets $f} line] $line
    } -cleanup {
	close $f
	removeFile script
    } -result {0 {-enc utf-8 script}}

    # Tests Tcl_Main-2.*: application-initialization procedure

    test Tcl_Main-2.1 {
	Tcl_Main: appInitProc returns error
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -setup {
	makeFile {puts "In script"} script
    } -body {
	exec [interpreter] script -appinitprocerror >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result
	removeFile script
    } -result "application-specific initialization failed: \nIn script\n"

    test Tcl_Main-2.2 {
	Tcl_Main: appInitProc returns error
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {puts "In script"} -appinitprocerror >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result
    } -result "application-specific initialization failed: \nIn script\n"

    test Tcl_Main-2.3 {
	Tcl_Main: appInitProc deletes interp
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -setup {
	makeFile {puts "In script"} script
    } -body {
	exec [interpreter] script -appinitprocdeleteinterp >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result
	removeFile script
    } -result "application-specific initialization failed: \n"

    test Tcl_Main-2.4 {
	Tcl_Main: appInitProc deletes interp
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {puts "In script"} \
		-appinitprocdeleteinterp >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result
    } -result "application-specific initialization failed: \n"

    test Tcl_Main-2.5 {
	Tcl_Main: appInitProc closes stderr
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {puts "In script"} \
		-appinitprocclosestderr >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
332
333
334
335
336
337
338
339

340
341
342
343
344
345
346
330
331
332
333
334
335
336

337
338
339
340
341
342
343
344







-
+







	removeFile script
    } -match glob -result [join [list 1 {child process exited abnormally}\
	"missing close-brace\n    while executing*"] \n]

    test Tcl_Main-3.5 {
	Tcl_Main: startup script sets main loop
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -setup {
	makeFile {
		rename exit _exit
		proc exit {code} {
		    puts "In exit"
		    _exit $code
		}
360
361
362
363
364
365
366
367

368
369
370
371
372
373
374
358
359
360
361
362
363
364

365
366
367
368
369
370
371
372







-
+







	file delete result
	removeFile script
    } -result "event\nExit MainLoop\nIn exit\neven 0\n"

    test Tcl_Main-3.6 {
	Tcl_Main: startup script sets main loop and closes stdin
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -setup {
	makeFile {
		close stdin
		testsetmainloop
		rename exit _exit
		proc exit {code} {
		    puts "In exit"
389
390
391
392
393
394
395
396

397
398
399
400
401
402
403
387
388
389
390
391
392
393

394
395
396
397
398
399
400
401







-
+







	file delete result
	removeFile script
    } -result "event\nExit MainLoop\nIn exit\neven 0\n"

    test Tcl_Main-3.7 {
	Tcl_Main: startup script deletes interp
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -setup {
	makeFile {
		rename exit _exit
		proc exit {code} {
		    puts "In exit"
		    _exit $code
		}
413
414
415
416
417
418
419
420

421
422
423
424
425
426
427
411
412
413
414
415
416
417

418
419
420
421
422
423
424
425







-
+







	file delete result
	removeFile script
    } -result "even 0\n"

    test Tcl_Main-3.8 {
	Tcl_Main: startup script deletes interp and sets mainloop
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -setup {
	makeFile {
		testsetmainloop
		rename exit _exit
		proc exit {code} {
		    puts "In exit"
		    _exit $code
457
458
459
460
461
462
463
464

465
466
467
468
469
470
471
472
473
474
475
476
477
478
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
455
456
457
458
459
460
461

462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478

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







-
+
















-
+
















-
+







    } -result {}

    # Tests Tcl_Main-4.*: rc file evaluation

    test Tcl_Main-4.1 {
	Tcl_Main: rcFile evaluation deletes interp
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -setup {
	set rc [makeFile {testinterpdelete {}} rc]
    } -body {
	exec [interpreter] << {puts "In script"} \
		-appinitprocsetrcfile $rc >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result
	removeFile rc
    } -result "application-specific initialization failed: \n"

    test Tcl_Main-4.2 {
	Tcl_Main: rcFile evaluation closes stdin
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -setup {
	set rc [makeFile {close stdin} rc]
    } -body {
	exec [interpreter] << {puts "In script"} \
		-appinitprocsetrcfile $rc >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result
	removeFile rc
    } -result "application-specific initialization failed: \n"

    test Tcl_Main-4.3 {
	Tcl_Main: rcFile evaluation closes stdin and sets main loop
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -setup {
	set rc [makeFile {
		close stdin
		testsetmainloop
		after 0 testexitmainloop
		testexithandler create 0
		rename exit _exit
519
520
521
522
523
524
525
526

527
528
529
530
531
532
533
517
518
519
520
521
522
523

524
525
526
527
528
529
530
531







-
+







	removeFile rc
    } -result "application-specific initialization failed:\
	\nExit MainLoop\nIn exit\neven 0\n"

    test Tcl_Main-4.4 {
	Tcl_Main: rcFile evaluation sets main loop
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -setup {
	set rc [makeFile {
		testsetmainloop
		after 0 testexitmainloop
		testexithandler create 0
		rename exit _exit
		proc exit code {
544
545
546
547
548
549
550
551

552
553

554
555
556
557
558




559
560
561
562
563
564
565






566
567
568


569
570
571
572
573
574
575
542
543
544
545
546
547
548

549
550

551
552




553
554
555
556
557






558
559
560
561
562
563
564


565
566
567
568
569
570
571
572
573







-
+

-
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
+
+







	close $f
	file delete result
	removeFile rc
    } -result "application-specific initialization failed:\
	\nExit MainLoop\nIn exit\neven 0\n"

    test Tcl_Main-4.5 {
        Tcl_Main: Bug 1481986
	Tcl_Main: Bug 1481986
    } -constraints {
        exec Tcltest
	exec tcl::test
    } -setup {
        set rc [makeFile {
                testsetmainloop
                after 0 {puts "Event callback"}
        } rc]
	set rc [makeFile {
		testsetmainloop
		after 0 {puts "Event callback"}
	} rc]
    } -body {
        set f [open "|[list [interpreter] -appinitprocsetrcfile $rc]" w+]
        after 1000
        type $f {puts {Interactive output}
            exit
        }
        read $f
	set f [open "|[list [interpreter] -appinitprocsetrcfile $rc]" w+]
	after 1000
	type $f {puts {Interactive output}
	    exit
	}
	read $f
    } -cleanup {
        catch {close $f}
        removeFile rc
	catch {close $f}
	removeFile rc
    } -result "Event callback\nInteractive output\n"

    # Tests Tcl_Main-5.*: interactive operations

    test Tcl_Main-5.1 {
	Tcl_Main: tcl_interactive must be boolean
    } -constraints {
604
605
606
607
608
609
610
611
612


613
614
615
616
617
618
619
602
603
604
605
606
607
608


609
610
611
612
613
614
615
616
617







-
-
+
+







	Tcl_Main handles stdin EOF in mid-command
    } -constraints {
	exec
    } -setup {
	catch {set f [open "|[list [interpreter]]" w+]}
	catch {chan configure $f -blocking 0}
    } -body {
	type $f "chan configure stdin -eofchar \\032
	    if 1 \{\n\032"
	type $f "chan configure stdin -eofchar \\x1A
	    if 1 \{\n\x1A"
	variable wait
	chan event $f readable \
		[list set [namespace which -variable wait] "child exit"]
	set id [after 5000 [list set [namespace which -variable wait] timeout]]
	vwait [namespace which -variable wait]
	after cancel $id
	set wait
694
695
696
697
698
699
700
701

702
703
704
705
706
707
708
692
693
694
695
696
697
698

699
700
701
702
703
704
705
706







-
+







	file delete result
    } -result "bar\n"

    test Tcl_Main-5.8 {
	Tcl_Main: interactive mode: close stdin
		-> main loop & [exit] & exit handlers
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		rename exit _exit
		proc exit code {
		    puts "In exit"
		    _exit $code
		}
718
719
720
721
722
723
724
725

726
727
728
729
730
731
732
716
717
718
719
720
721
722

723
724
725
726
727
728
729
730







-
+







	file delete result
    } -result "Exit MainLoop\nIn exit\neven 0\n"

    test Tcl_Main-5.9 {
	Tcl_Main: interactive mode: delete interp
		-> main loop & exit handlers, but no [exit]
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		rename exit _exit
		proc exit code {
		    puts "In exit"
		    _exit $code
		}
741
742
743
744
745
746
747
748

749
750
751
752
753
754
755


756
757
758
759
760
761
762
763
764
765
766
767
768
769

770
771
772
773
774
775
776
739
740
741
742
743
744
745

746
747
748
749
750
751


752
753
754
755
756
757
758
759
760
761
762
763
764
765
766

767
768
769
770
771
772
773
774







-
+





-
-
+
+













-
+







	close $f
	file delete result
    } -result "Exit MainLoop\neven 0\n"

    test Tcl_Main-5.10 {
	Tcl_Main: exit main loop in mid-interactive command
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -setup {
	catch {set f [open "|[list [interpreter]]" w+]}
	catch {chan configure $f -blocking 0}
    } -body {
	type $f "testsetmainloop
	         after 2000 testexitmainloop
	         puts \{1 2"
		 after 2000 testexitmainloop
		 puts \{1 2"
	after 4000
	type $f "3 4\}"
	set code1 [catch {gets $f} line1]
	set code2 [catch {gets $f} line2]
	set code3 [catch {gets $f} line3]
	list $code1 $line1 $code2 $line2 $code3 $line3
    } -cleanup {
	close $f
    } -result [list 0 {Exit MainLoop} 0 {1 2} 0 {3 4}]

    test Tcl_Main-5.11 {
	Tcl_Main: EOF in interactive main loop
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		rename exit _exit
		proc exit code {
		    puts "In exit"
		    _exit $code
		}
784
785
786
787
788
789
790
791

792
793
794
795
796
797
798
782
783
784
785
786
787
788

789
790
791
792
793
794
795
796







-
+







	close $f
	file delete result
    } -result "Exit MainLoop\nIn exit\neven 0\n"

    test Tcl_Main-5.12 {
	Tcl_Main: close stdin in interactive main loop
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		rename exit _exit
		proc exit code {
		    puts "In exit"
		    _exit $code
		}
837
838
839
840
841
842
843
844

845
846
847
848
849
850
851
835
836
837
838
839
840
841

842
843
844
845
846
847
848
849







-
+







	close $f
	file delete result
    } -result "1\n% "

    test Tcl_Main-6.2 {
	Tcl_Main: prompt deletes interp
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		set tcl_prompt1 {testinterpdelete {}}
		set tcl_interactive 1
		puts "not reached"
	} >& result
	set f [open result]
889
890
891
892
893
894
895
896

897
898
899
900
901
902
903
887
888
889
890
891
892
893

894
895
896
897
898
899
900
901







-
+







	close $f
	file delete result
    } -result "1\n% YES\n"

    test Tcl_Main-6.5 {
	Tcl_Main: interactive entry to main loop
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		set tcl_interactive 1
		testsetmainloop
		testexitmainloop} >& result
	set f [open result]
	read $f
939
940
941
942
943
944
945
946

947
948
949
950
951
952
953
954
955
956
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
937
938
939
940
941
942
943

944
945
946
947
948
949
950
951
952
953
954
955
956
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







-
+















-
+



















-
+
















-
+







    } -result "1\n% % "

    # Tests Tcl_Main-7.*: exiting

    test Tcl_Main-7.1 {
	Tcl_Main: [exit] defined as no-op -> still have exithandlers
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		proc exit args {}
		testexithandler create 0
	} >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result
    } -result "even 0\n"

    test Tcl_Main-7.2 {
	Tcl_Main: [exit] defined as no-op -> still have exithandlers
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		proc exit args {}
		testexithandler create 0
		after 0 testexitmainloop
		testsetmainloop
	} >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result
    } -result "Exit MainLoop\neven 0\n"

    # Tests Tcl_Main-8.*: StdinProc operations

    test Tcl_Main-8.1 {
	StdinProc: handles non-blocking stdin
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		testsetmainloop
		chan configure stdin -blocking 0
		testexitmainloop
	} >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result
    } -result "Exit MainLoop\n"

    test Tcl_Main-8.2 {
	StdinProc: handles stdin EOF
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		testsetmainloop
		testexithandler create 0
		rename exit _exit
		proc exit code {
		    puts "In exit"
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
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







-
+




















-
+







	close $f
	file delete result
    } -result "Exit MainLoop\nIn exit\neven 0\n"

    test Tcl_Main-8.3 {
	StdinProc: handles interactive stdin EOF
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		testsetmainloop
		testexithandler create 0
		rename exit _exit
		proc exit code {
		    puts "In exit"
		    _exit $code
		}
		set tcl_interactive 1} >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result
    } -result "1\n% even 0\n"

    test Tcl_Main-8.4 {
	StdinProc: handles stdin close
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		testsetmainloop
		rename exit _exit
		proc exit code {
		    puts "In exit"
		    _exit $code
1058
1059
1060
1061
1062
1063
1064
1065

1066
1067
1068
1069
1070
1071
1072
1056
1057
1058
1059
1060
1061
1062

1063
1064
1065
1066
1067
1068
1069
1070







-
+







	close $f
	file delete result
    } -result "1\nExit MainLoop\nIn exit\n"

    test Tcl_Main-8.5 {
	StdinProc: handles interactive stdin close
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		testsetmainloop
		set tcl_interactive 1
		rename exit _exit
		proc exit code {
		    puts "In exit"
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125

1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143

1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159

1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177

1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212

1213
1214
1215
1216
1217
1218
1219
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
1116
1117
1118
1119
1120
1121
1122

1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140

1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156

1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174

1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190

1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209

1210
1211
1212
1213
1214
1215
1216
1217







-
+


















-
+
















-
+

















-
+















-
+

















-
+















-
+


















-
+







	close $f
	file delete result
    } -result "1\n% % % after#0\n% after#1\n% 1\nExit MainLoop\nIn exit\n"

    test Tcl_Main-8.6 {
	StdinProc: handles event loop re-entry
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		testsetmainloop
		after 100 {puts 1; set delay 1}
		vwait delay
		puts 2
		testexitmainloop
	} >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result
    } -result "1\n2\nExit MainLoop\n"

    test Tcl_Main-8.7 {
	StdinProc: handling of errors
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		testsetmainloop
		error foo
		testexitmainloop
	} >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result
    } -result "foo\nExit MainLoop\n"

    test Tcl_Main-8.8 {
	StdinProc: handling of errors, closed stderr
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		testsetmainloop
		close stderr
		error foo
		testexitmainloop
	} >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result
    } -result "Exit MainLoop\n"

    test Tcl_Main-8.9 {
	StdinProc: interactive output
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		testsetmainloop
		set tcl_interactive 1
		testexitmainloop} >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result
    } -result "1\n% % Exit MainLoop\n"

    test Tcl_Main-8.10 {
	StdinProc: interactive output, closed stdout
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		testsetmainloop
		close stdout
		set tcl_interactive 1
		testexitmainloop
	} >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result
    } -result {}

    test Tcl_Main-8.11 {
	StdinProc: prompt deletes interp
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		testsetmainloop
		set tcl_prompt1 {testinterpdelete {}}
		set tcl_interactive 1} >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result
    } -result "1\n"

    test Tcl_Main-8.12 {
	StdinProc: prompt closes stdin
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << {
		testsetmainloop
		set tcl_prompt1 {close stdin}
		after 100 testexitmainloop
		set tcl_interactive 1
		puts "not reached"
	} >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result
    } -result "1\nExit MainLoop\n"

    test Tcl_Main-8.13 {
	Bug 1775878
    } -constraints {
	exec Tcltest
	exec tcl::test
    } -body {
	exec [interpreter] << "testsetmainloop\nputs \\\npwd\ntestexitmainloop" >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result

Changes to tests/mathop.test.

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
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
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
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






-
-
+
+
















-
+








-
+






-
+


-
+





-
+








-
-
-
+
+
+










-
+





-
+




-
+






-
-
-
-
-
+
+
+
+
+







# Commands covered: ::tcl::mathop::...
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 2006 Donal K. Fellows
# Copyright (c) 2006 Peter Spjuth
# Copyright © 2006 Donal K. Fellows
# Copyright © 2006 Peter Spjuth
#
# 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::*
}

# A namespace to test that operators are exported and that they
# work when imported
namespace eval ::testmathop2 {
    namespace import ::tcl::mathop::*
}

# Helper to test math ops.
# Test different invokation variants and see that they do the same thing.
# Test different invocation variants and see that they do the same thing.
# Byte compiled / non byte compiled version
# Shared / unshared arguments
# Original / imported
proc TestOp {op args} {
    set results {}

    # Non byte compiled version, shared args
    if {[catch {::tcl::mathop::$op {*}$args} res]} {
        append res " $::errorCode"
	append res " $::errorCode"
    }
    lappend results $res

    # Non byte compiled version, unshared args
    set cmd ::tcl::mathop::\$op
    foreach arg $args {
        append cmd " \[format %s [list $arg]\]"
	append cmd " \[format %s [list $arg]\]"
    }
    if {[catch $cmd res]} {
        append res " $::errorCode"
	append res " $::errorCode"
    }
    lappend results $res

    # Non byte compiled imported
    if {[catch {::testmathop2::$op {*}$args} res]} {
        append res " $::errorCode"
	append res " $::errorCode"
    }
    lappend results [string map {testmathop2 tcl::mathop} $res]

    # BC version
    set argList1 {}
    set argList2 {}
    set argList3 {}
    for {set t 0} {$t < [llength $args]} {incr t} {
        lappend argList1 a$t
        lappend argList2 \$a$t
        lappend argList3 "\[format %s \$a$t\]"
	lappend argList1 a$t
	lappend argList2 \$a$t
	lappend argList3 "\[format %s \$a$t\]"
    }
    # Shared args
    proc _TestOp  $argList1 "::tcl::mathop::$op [join $argList2]"
    # Unshared args
    proc _TestOp2 $argList1 "::tcl::mathop::$op [join $argList3]"
    # Imported
    proc _TestOp3 $argList1 "::testmathop2::$op [join $argList2]"

    set ::tcl_traceCompile 0  ;# Set to 2 to help with debug
    if {[catch {_TestOp {*}$args} res]} {
        append res " $::errorCode"
	append res " $::errorCode"
    }
    set ::tcl_traceCompile 0
    lappend results $res

    if {[catch {_TestOp2 {*}$args} res]} {
        append res " $::errorCode"
	append res " $::errorCode"
    }
    lappend results $res

    if {[catch {_TestOp3 {*}$args} res]} {
        append res " $::errorCode"
	append res " $::errorCode"
    }
    lappend results [string map {testmathop2 tcl::mathop} $res]

    # Check that they do the same
    set len [llength $results]
    for {set i 0} {$i < ($len - 1)} {incr i} {
        set res1 [lindex $results $i]
        set res2 [lindex $results $i+1]
        if {$res1 ne $res2} {
            return "$i:($res1 != $res2)"
        }
	set res1 [lindex $results $i]
	set res2 [lindex $results $i+1]
	if {$res1 ne $res2} {
	    return "$i:($res1 != $res2)"
	}
    }
    return [lindex $results 0]
}

# start of tests

namespace eval ::testmathop {
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
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







-
+


-
+


-
+


-
+


-
+


-
+







    test mathop-1.6 {compiled +} { + 1 2 3.0 } 6.0
    test mathop-1.7 {compiled +} { + 100000000000 2 3 } 100000000005
    test mathop-1.8 {compiled +} { + 1 2 300000000000 } 300000000003
    test mathop-1.9 {compiled +} { + 1000000000000000000000 2 3 } 1000000000000000000005
    test mathop-1.10 {compiled +} { + 1 2 3000000000000000000000 } 3000000000000000000003
    test mathop-1.11 {compiled +: errors} -returnCodes error -body {
	+ x 0
    } -result {can't use non-numeric string "x" as operand of "+"}
    } -result {cannot use non-numeric string "x" as left operand of "+"}
    test mathop-1.12 {compiled +: errors} -returnCodes error -body {
	+ nan 0
    } -result {can't use non-numeric floating-point value "nan" as operand of "+"}
    } -result {cannot use non-numeric floating-point value "nan" as left operand of "+"}
    test mathop-1.13 {compiled +: errors} -returnCodes error -body {
	+ 0 x
    } -result {can't use non-numeric string "x" as operand of "+"}
    } -result {cannot use non-numeric string "x" as right operand of "+"}
    test mathop-1.14 {compiled +: errors} -returnCodes error -body {
	+ 0 nan
    } -result {can't use non-numeric floating-point value "nan" as operand of "+"}
    } -result {cannot use non-numeric floating-point value "nan" as right operand of "+"}
    test mathop-1.15 {compiled +: errors} -returnCodes error -body {
	+ 0o8 0
    } -result {can't use non-numeric string "0o8" as operand of "+"}
    } -result {cannot use non-numeric string "0o8" as left operand of "+"}
    test mathop-1.16 {compiled +: errors} -returnCodes error -body {
	+ 0 0o8
    } -result {can't use non-numeric string "0o8" as operand of "+"}
    } -result {cannot use non-numeric string "0o8" as right operand of "+"}
    test mathop-1.17 {compiled +: errors} -returnCodes error -body {
	+ 0 [error expectedError]
    } -result expectedError
    test mathop-1.18 {compiled +: argument processing order} -body {
	# Bytecode compilation known hard for 3+ arguments
	list [catch {
	    + [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
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
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







-
+


-
+


-
+


-
+


-
+


-
+







    test mathop-1.24 {interpreted +} { $op 1 2 3.0 } 6.0
    test mathop-1.25 {interpreted +} { $op 100000000000 2 3 } 100000000005
    test mathop-1.26 {interpreted +} { $op 1 2 300000000000 } 300000000003
    test mathop-1.27 {interpreted +} { $op 1000000000000000000000 2 3 } 1000000000000000000005
    test mathop-1.28 {interpreted +} { $op 1 2 3000000000000000000000 } 3000000000000000000003
    test mathop-1.29 {interpreted +: errors} -returnCodes error -body {
	$op x 0
    } -result {can't use non-numeric string "x" as operand of "+"}
    } -result {cannot use non-numeric string "x" as left operand of "+"}
    test mathop-1.30 {interpreted +: errors} -returnCodes error -body {
	$op nan 0
    } -result {can't use non-numeric floating-point value "nan" as operand of "+"}
    } -result {cannot use non-numeric floating-point value "nan" as left operand of "+"}
    test mathop-1.31 {interpreted +: errors} -returnCodes error -body {
	$op 0 x
    } -result {can't use non-numeric string "x" as operand of "+"}
    } -result {cannot use non-numeric string "x" as right operand of "+"}
    test mathop-1.32 {interpreted +: errors} -returnCodes error -body {
	$op 0 nan
    } -result {can't use non-numeric floating-point value "nan" as operand of "+"}
    } -result {cannot use non-numeric floating-point value "nan" as right operand of "+"}
    test mathop-1.33 {interpreted +: errors} -returnCodes error -body {
	$op 0o8 0
    } -result {can't use non-numeric string "0o8" as operand of "+"}
    } -result {cannot use non-numeric string "0o8" as left operand of "+"}
    test mathop-1.34 {interpreted +: errors} -returnCodes error -body {
	$op 0 0o8
    } -result {can't use non-numeric string "0o8" as operand of "+"}
    } -result {cannot use non-numeric string "0o8" as right operand of "+"}
    test mathop-1.35 {interpreted +: errors} -returnCodes error -body {
	$op 0 [error expectedError]
    } -result expectedError
    test mathop-1.36 {interpreted +: argument processing order} -body {
	list [catch {
	    $op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
	} msg] $msg $x
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
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







-
+


-
+


-
+


-
+


-
+


-
+







    test mathop-2.6 {compiled *} { * 1 2 3.0 } 6.0
    test mathop-2.7 {compiled *} { * 100000000000 2 3 } 600000000000
    test mathop-2.8 {compiled *} { * 1 2 300000000000 } 600000000000
    test mathop-2.9 {compiled *} { * 1000000000000000000000 2 3 } 6000000000000000000000
    test mathop-2.10 {compiled *} { * 1 2 3000000000000000000000 } 6000000000000000000000
    test mathop-2.11 {compiled *: errors} -returnCodes error -body {
	* x 0
    } -result {can't use non-numeric string "x" as operand of "*"}
    } -result {cannot use non-numeric string "x" as left operand of "*"}
    test mathop-2.12 {compiled *: errors} -returnCodes error -body {
	* nan 0
    } -result {can't use non-numeric floating-point value "nan" as operand of "*"}
    } -result {cannot use non-numeric floating-point value "nan" as left operand of "*"}
    test mathop-2.13 {compiled *: errors} -returnCodes error -body {
	* 0 x
    } -result {can't use non-numeric string "x" as operand of "*"}
    } -result {cannot use non-numeric string "x" as right operand of "*"}
    test mathop-2.14 {compiled *: errors} -returnCodes error -body {
	* 0 nan
    } -result {can't use non-numeric floating-point value "nan" as operand of "*"}
    } -result {cannot use non-numeric floating-point value "nan" as right operand of "*"}
    test mathop-2.15 {compiled *: errors} -returnCodes error -body {
	* 0o8 0
    } -result {can't use non-numeric string "0o8" as operand of "*"}
    } -result {cannot use non-numeric string "0o8" as left operand of "*"}
    test mathop-2.16 {compiled *: errors} -returnCodes error -body {
	* 0 0o8
    } -result {can't use non-numeric string "0o8" as operand of "*"}
    } -result {cannot use non-numeric string "0o8" as right operand of "*"}
    test mathop-2.17 {compiled *: errors} -returnCodes error -body {
	* 0 [error expectedError]
    } -result expectedError
    test mathop-2.18 {compiled *: argument processing order} -body {
	# Bytecode compilation known hard for 3+ arguments
	list [catch {
	    * [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
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
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







-
+


-
+


-
+


-
+


-
+


-
+


















-
+
















-
+








-
+


-
+










-
+








-
+


-
+










-
+








-
+


-
+







    test mathop-2.24 {interpreted *} { $op 1 2 3.0 } 6.0
    test mathop-2.25 {interpreted *} { $op 100000000000 2 3 } 600000000000
    test mathop-2.26 {interpreted *} { $op 1 2 300000000000 } 600000000000
    test mathop-2.27 {interpreted *} { $op 1000000000000000000000 2 3 } 6000000000000000000000
    test mathop-2.28 {interpreted *} { $op 1 2 3000000000000000000000 } 6000000000000000000000
    test mathop-2.29 {interpreted *: errors} -returnCodes error -body {
	$op x 0
    } -result {can't use non-numeric string "x" as operand of "*"}
    } -result {cannot use non-numeric string "x" as left operand of "*"}
    test mathop-2.30 {interpreted *: errors} -returnCodes error -body {
	$op nan 0
    } -result {can't use non-numeric floating-point value "nan" as operand of "*"}
    } -result {cannot use non-numeric floating-point value "nan" as left operand of "*"}
    test mathop-2.31 {interpreted *: errors} -returnCodes error -body {
	$op 0 x
    } -result {can't use non-numeric string "x" as operand of "*"}
    } -result {cannot use non-numeric string "x" as right operand of "*"}
    test mathop-2.32 {interpreted *: errors} -returnCodes error -body {
	$op 0 nan
    } -result {can't use non-numeric floating-point value "nan" as operand of "*"}
    } -result {cannot use non-numeric floating-point value "nan" as right operand of "*"}
    test mathop-2.33 {interpreted *: errors} -returnCodes error -body {
	$op 0o8 0
    } -result {can't use non-numeric string "0o8" as operand of "*"}
    } -result {cannot use non-numeric string "0o8" as left operand of "*"}
    test mathop-2.34 {interpreted *: errors} -returnCodes error -body {
	$op 0 0o8
    } -result {can't use non-numeric string "0o8" as operand of "*"}
    } -result {cannot use non-numeric string "0o8" as right operand of "*"}
    test mathop-2.35 {interpreted *: errors} -returnCodes error -body {
	$op 0 [error expectedError]
    } -result expectedError
    test mathop-2.36 {interpreted *: argument processing order} -body {
	list [catch {
	    $op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
	} msg] $msg $x
    } -result {1 expected 2}

    test mathop-3.1 {compiled !} {! 0} 1
    test mathop-3.2 {compiled !} {! 1} 0
    test mathop-3.3 {compiled !} {! false} 1
    test mathop-3.4 {compiled !} {! true} 0
    test mathop-3.5 {compiled !} {! 0.0} 1
    test mathop-3.6 {compiled !} {! 10000000000} 0
    test mathop-3.7 {compiled !} {! 10000000000000000000000000} 0
    test mathop-3.8 {compiled !: errors} -body {
	! foobar
    } -returnCodes error -result {can't use non-numeric string "foobar" as operand of "!"}
    } -returnCodes error -result {cannot use non-numeric string "foobar" as operand of "!"}
    test mathop-3.9 {compiled !: errors} -body {
	! 0 0
    } -returnCodes error -result "wrong # args: should be \"! boolean\""
    test mathop-3.10 {compiled !: errors} -body {
	!
    } -returnCodes error -result "wrong # args: should be \"! boolean\""
    set op !
    test mathop-3.11 {interpreted !} {$op 0} 1
    test mathop-3.12 {interpreted !} {$op 1} 0
    test mathop-3.13 {interpreted !} {$op false} 1
    test mathop-3.14 {interpreted !} {$op true} 0
    test mathop-3.15 {interpreted !} {$op 0.0} 1
    test mathop-3.16 {interpreted !} {$op 10000000000} 0
    test mathop-3.17 {interpreted !} {$op 10000000000000000000000000} 0
    test mathop-3.18 {interpreted !: errors} -body {
	$op foobar
    } -returnCodes error -result {can't use non-numeric string "foobar" as operand of "!"}
    } -returnCodes error -result {cannot use non-numeric string "foobar" as operand of "!"}
    test mathop-3.19 {interpreted !: errors} -body {
	$op 0 0
    } -returnCodes error -result "wrong # args: should be \"! boolean\""
    test mathop-3.20 {interpreted !: errors} -body {
	$op
    } -returnCodes error -result "wrong # args: should be \"! boolean\""
    test mathop-3.21 {compiled !: error} -returnCodes error -body {
	! NaN
    } -result {can't use non-numeric floating-point value "NaN" as operand of "!"}
    } -result {cannot use non-numeric floating-point value "NaN" as operand of "!"}
    test mathop-3.22 {interpreted !: error} -returnCodes error -body {
	$op NaN
    } -result {can't use non-numeric floating-point value "NaN" as operand of "!"}
    } -result {cannot use non-numeric floating-point value "NaN" as operand of "!"}

    test mathop-4.1 {compiled ~} {~ 0} -1
    test mathop-4.2 {compiled ~} {~ 1} -2
    test mathop-4.3 {compiled ~} {~ 31} -32
    test mathop-4.4 {compiled ~} {~ -127} 126
    test mathop-4.5 {compiled ~} {~ -0} -1
    test mathop-4.6 {compiled ~} {~ 10000000000} -10000000001
    test mathop-4.7 {compiled ~} {~ 10000000000000000000000000} -10000000000000000000000001
    test mathop-4.8 {compiled ~: errors} -body {
	~ foobar
    } -returnCodes error -result {can't use non-numeric string "foobar" as operand of "~"}
    } -returnCodes error -result {cannot use non-numeric string "foobar" as operand of "~"}
    test mathop-4.9 {compiled ~: errors} -body {
	~ 0 0
    } -returnCodes error -result "wrong # args: should be \"~ integer\""
    test mathop-4.10 {compiled ~: errors} -body {
	~
    } -returnCodes error -result "wrong # args: should be \"~ integer\""
    test mathop-4.11 {compiled ~: errors} -returnCodes error -body {
	~ 0.0
    } -result {can't use floating-point value "0.0" as operand of "~"}
    } -result {cannot use floating-point value "0.0" as operand of "~"}
    test mathop-4.12 {compiled ~: errors} -returnCodes error -body {
	~ NaN
    } -result {can't use non-numeric floating-point value "NaN" as operand of "~"}
    } -result {cannot use non-numeric floating-point value "NaN" as operand of "~"}
    set op ~
    test mathop-4.13 {interpreted ~} {$op 0} -1
    test mathop-4.14 {interpreted ~} {$op 1} -2
    test mathop-4.15 {interpreted ~} {$op 31} -32
    test mathop-4.16 {interpreted ~} {$op -127} 126
    test mathop-4.17 {interpreted ~} {$op -0} -1
    test mathop-4.18 {interpreted ~} {$op 10000000000} -10000000001
    test mathop-4.19 {interpreted ~} {$op 10000000000000000000000000} -10000000000000000000000001
    test mathop-4.20 {interpreted ~: errors} -body {
	$op foobar
    } -returnCodes error -result {can't use non-numeric string "foobar" as operand of "~"}
    } -returnCodes error -result {cannot use non-numeric string "foobar" as operand of "~"}
    test mathop-4.21 {interpreted ~: errors} -body {
	$op 0 0
    } -returnCodes error -result "wrong # args: should be \"~ integer\""
    test mathop-4.22 {interpreted ~: errors} -body {
	$op
    } -returnCodes error -result "wrong # args: should be \"~ integer\""
    test mathop-4.23 {interpreted ~: errors} -returnCodes error -body {
	$op 0.0
    } -result {can't use floating-point value "0.0" as operand of "~"}
    } -result {cannot use floating-point value "0.0" as operand of "~"}
    test mathop-4.24 {interpreted ~: errors} -returnCodes error -body {
	$op NaN
    } -result {can't use non-numeric floating-point value "NaN" as operand of "~"}
    } -result {cannot use non-numeric floating-point value "NaN" as operand of "~"}

    test mathop-5.1 {compiled eq} {eq {} a} 0
    test mathop-5.2 {compiled eq} {eq a a} 1
    test mathop-5.3 {compiled eq} {eq a {}} 0
    test mathop-5.4 {compiled eq} {eq a b} 0
    test mathop-5.5 {compiled eq} { eq } 1
    test mathop-5.6 {compiled eq} {eq a} 1
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

442
443
444

445
446
447

448
449
450
451
452
453
454
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
442
443

444
445
446

447
448
449
450
451
452
453
454







-
+


-
+






-
+


-
+


-
+


-
+


-
+


-
+
















-
+


-
+






-
+


-
+


-
+


-
+


-
+


-
+








    test mathop-6.1 {compiled &} { & } -1
    test mathop-6.2 {compiled &} { & 1 } 1
    test mathop-6.3 {compiled &} { & 1 2 } 0
    test mathop-6.4 {compiled &} { & 3 7 6 } 2
    test mathop-6.5 {compiled &} -returnCodes error -body {
	& 1.0 2 3
    } -result {can't use floating-point value "1.0" as operand of "&"}
    } -result {cannot use floating-point value "1.0" as right operand of "&"}
    test mathop-6.6 {compiled &} -returnCodes error -body {
	& 1 2 3.0
    } -result {can't use floating-point value "3.0" as operand of "&"}
    } -result {cannot use floating-point value "3.0" as left operand of "&"}
    test mathop-6.7 {compiled &} { & 100000000002 18 -126 } 2
    test mathop-6.8 {compiled &} { & 0xff 0o377 333333333333 } 85
    test mathop-6.9 {compiled &} { & 1000000000000000000002 18 -126 } 2
    test mathop-6.10 {compiled &} { & 0xff 0o377 3333333333333333333333 } 85
    test mathop-6.11 {compiled &: errors} -returnCodes error -body {
	& x 0
    } -result {can't use non-numeric string "x" as operand of "&"}
    } -result {cannot use non-numeric string "x" as left operand of "&"}
    test mathop-6.12 {compiled &: errors} -returnCodes error -body {
	& nan 0
    } -result {can't use non-numeric floating-point value "nan" as operand of "&"}
    } -result {cannot use non-numeric floating-point value "nan" as left operand of "&"}
    test mathop-6.13 {compiled &: errors} -returnCodes error -body {
	& 0 x
    } -result {can't use non-numeric string "x" as operand of "&"}
    } -result {cannot use non-numeric string "x" as right operand of "&"}
    test mathop-6.14 {compiled &: errors} -returnCodes error -body {
	& 0 nan
    } -result {can't use non-numeric floating-point value "nan" as operand of "&"}
    } -result {cannot use non-numeric floating-point value "nan" as right operand of "&"}
    test mathop-6.15 {compiled &: errors} -returnCodes error -body {
	& 0o8 0
    } -result {can't use non-numeric string "0o8" as operand of "&"}
    } -result {cannot use non-numeric string "0o8" as left operand of "&"}
    test mathop-6.16 {compiled &: errors} -returnCodes error -body {
	& 0 0o8
    } -result {can't use non-numeric string "0o8" as operand of "&"}
    } -result {cannot use non-numeric string "0o8" as right operand of "&"}
    test mathop-6.17 {compiled &: errors} -returnCodes error -body {
	& 0 [error expectedError]
    } -result expectedError
    test mathop-6.18 {compiled &: argument processing order} -body {
	# Bytecode compilation known hard for 3+ arguments
	list [catch {
	    & [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
	} msg] $msg $x
    } -result {1 expected 2}
    set op &
    test mathop-6.19 {interpreted &} { $op } -1
    test mathop-6.20 {interpreted &} { $op 1 } 1
    test mathop-6.21 {interpreted &} { $op 1 2 } 0
    test mathop-6.22 {interpreted &} { $op 3 7 6 } 2
    test mathop-6.23 {interpreted &} -returnCodes error -body {
	$op 1.0 2 3
    } -result {can't use floating-point value "1.0" as operand of "&"}
    } -result {cannot use floating-point value "1.0" as left operand of "&"}
    test mathop-6.24 {interpreted &} -returnCodes error -body {
	$op 1 2 3.0
    } -result {can't use floating-point value "3.0" as operand of "&"}
    } -result {cannot use floating-point value "3.0" as right operand of "&"}
    test mathop-6.25 {interpreted &} { $op 100000000002 18 -126 } 2
    test mathop-6.26 {interpreted &} { $op 0xff 0o377 333333333333 } 85
    test mathop-6.27 {interpreted &} { $op 1000000000000000000002 18 -126 } 2
    test mathop-6.28 {interpreted &} { $op 0xff 0o377 3333333333333333333333 } 85
    test mathop-6.29 {interpreted &: errors} -returnCodes error -body {
	$op x 0
    } -result {can't use non-numeric string "x" as operand of "&"}
    } -result {cannot use non-numeric string "x" as left operand of "&"}
    test mathop-6.30 {interpreted &: errors} -returnCodes error -body {
	$op nan 0
    } -result {can't use non-numeric floating-point value "nan" as operand of "&"}
    } -result {cannot use non-numeric floating-point value "nan" as left operand of "&"}
    test mathop-6.31 {interpreted &: errors} -returnCodes error -body {
	$op 0 x
    } -result {can't use non-numeric string "x" as operand of "&"}
    } -result {cannot use non-numeric string "x" as right operand of "&"}
    test mathop-6.32 {interpreted &: errors} -returnCodes error -body {
	$op 0 nan
    } -result {can't use non-numeric floating-point value "nan" as operand of "&"}
    } -result {cannot use non-numeric floating-point value "nan" as right operand of "&"}
    test mathop-6.33 {interpreted &: errors} -returnCodes error -body {
	$op 0o8 0
    } -result {can't use non-numeric string "0o8" as operand of "&"}
    } -result {cannot use non-numeric string "0o8" as left operand of "&"}
    test mathop-6.34 {interpreted &: errors} -returnCodes error -body {
	$op 0 0o8
    } -result {can't use non-numeric string "0o8" as operand of "&"}
    } -result {cannot use non-numeric string "0o8" as right operand of "&"}
    test mathop-6.35 {interpreted &: errors} -returnCodes error -body {
	$op 0 [error expectedError]
    } -result expectedError
    test mathop-6.36 {interpreted &: argument processing order} -body {
	list [catch {
	    $op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
	} msg] $msg $x
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

558
559
560
561
562
563
564
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
558
559
560
561
562
563
564







-
+


-
+






-
+


-
+


-
+


-
+


-
+


-
+
















-
+


-
+






-
+


-
+


-
+


-
+


-
+


-
+








    test mathop-7.1 {compiled |} { | } 0
    test mathop-7.2 {compiled |} { | 1 } 1
    test mathop-7.3 {compiled |} { | 1 2 } 3
    test mathop-7.4 {compiled |} { | 3 7 6 } 7
    test mathop-7.5 {compiled |} -returnCodes error -body {
	| 1.0 2 3
    } -result {can't use floating-point value "1.0" as operand of "|"}
    } -result {cannot use floating-point value "1.0" as right operand of "|"}
    test mathop-7.6 {compiled |} -returnCodes error -body {
	| 1 2 3.0
    } -result {can't use floating-point value "3.0" as operand of "|"}
    } -result {cannot use floating-point value "3.0" as left operand of "|"}
    test mathop-7.7 {compiled |} { | 100000000002 18 -126 } -110
    test mathop-7.8 {compiled |} { | 0xff 0o377 333333333333 } 333333333503
    test mathop-7.9 {compiled |} { | 1000000000000000000002 18 -126 } -110
    test mathop-7.10 {compiled |} { | 0xff 0o377 3333333333333333333333 } 3333333333333333333503
    test mathop-7.11 {compiled |: errors} -returnCodes error -body {
	| x 0
    } -result {can't use non-numeric string "x" as operand of "|"}
    } -result {cannot use non-numeric string "x" as left operand of "|"}
    test mathop-7.12 {compiled |: errors} -returnCodes error -body {
	| nan 0
    } -result {can't use non-numeric floating-point value "nan" as operand of "|"}
    } -result {cannot use non-numeric floating-point value "nan" as left operand of "|"}
    test mathop-7.13 {compiled |: errors} -returnCodes error -body {
	| 0 x
    } -result {can't use non-numeric string "x" as operand of "|"}
    } -result {cannot use non-numeric string "x" as right operand of "|"}
    test mathop-7.14 {compiled |: errors} -returnCodes error -body {
	| 0 nan
    } -result {can't use non-numeric floating-point value "nan" as operand of "|"}
    } -result {cannot use non-numeric floating-point value "nan" as right operand of "|"}
    test mathop-7.15 {compiled |: errors} -returnCodes error -body {
	| 0o8 0
    } -result {can't use non-numeric string "0o8" as operand of "|"}
    } -result {cannot use non-numeric string "0o8" as left operand of "|"}
    test mathop-7.16 {compiled |: errors} -returnCodes error -body {
	| 0 0o8
    } -result {can't use non-numeric string "0o8" as operand of "|"}
    } -result {cannot use non-numeric string "0o8" as right operand of "|"}
    test mathop-7.17 {compiled |: errors} -returnCodes error -body {
	| 0 [error expectedError]
    } -result expectedError
    test mathop-7.18 {compiled |: argument processing order} -body {
	# Bytecode compilation known hard for 3+ arguments
	list [catch {
	    | [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
	} msg] $msg $x
    } -result {1 expected 2}
    set op |
    test mathop-7.19 {interpreted |} { $op } 0
    test mathop-7.20 {interpreted |} { $op 1 } 1
    test mathop-7.21 {interpreted |} { $op 1 2 } 3
    test mathop-7.22 {interpreted |} { $op 3 7 6 } 7
    test mathop-7.23 {interpreted |} -returnCodes error -body {
	$op 1.0 2 3
    } -result {can't use floating-point value "1.0" as operand of "|"}
    } -result {cannot use floating-point value "1.0" as left operand of "|"}
    test mathop-7.24 {interpreted |} -returnCodes error -body {
	$op 1 2 3.0
    } -result {can't use floating-point value "3.0" as operand of "|"}
    } -result {cannot use floating-point value "3.0" as right operand of "|"}
    test mathop-7.25 {interpreted |} { $op 100000000002 18 -126 } -110
    test mathop-7.26 {interpreted |} { $op 0xff 0o377 333333333333 } 333333333503
    test mathop-7.27 {interpreted |} { $op 1000000000000000000002 18 -126 } -110
    test mathop-7.28 {interpreted |} { $op 0xff 0o377 3333333333333333333333 } 3333333333333333333503
    test mathop-7.29 {interpreted |: errors} -returnCodes error -body {
	$op x 0
    } -result {can't use non-numeric string "x" as operand of "|"}
    } -result {cannot use non-numeric string "x" as left operand of "|"}
    test mathop-7.30 {interpreted |: errors} -returnCodes error -body {
	$op nan 0
    } -result {can't use non-numeric floating-point value "nan" as operand of "|"}
    } -result {cannot use non-numeric floating-point value "nan" as left operand of "|"}
    test mathop-7.31 {interpreted |: errors} -returnCodes error -body {
	$op 0 x
    } -result {can't use non-numeric string "x" as operand of "|"}
    } -result {cannot use non-numeric string "x" as right operand of "|"}
    test mathop-7.32 {interpreted |: errors} -returnCodes error -body {
	$op 0 nan
    } -result {can't use non-numeric floating-point value "nan" as operand of "|"}
    } -result {cannot use non-numeric floating-point value "nan" as right operand of "|"}
    test mathop-7.33 {interpreted |: errors} -returnCodes error -body {
	$op 0o8 0
    } -result {can't use non-numeric string "0o8" as operand of "|"}
    } -result {cannot use non-numeric string "0o8" as left operand of "|"}
    test mathop-7.34 {interpreted |: errors} -returnCodes error -body {
	$op 0 0o8
    } -result {can't use non-numeric string "0o8" as operand of "|"}
    } -result {cannot use non-numeric string "0o8" as right operand of "|"}
    test mathop-7.35 {interpreted |: errors} -returnCodes error -body {
	$op 0 [error expectedError]
    } -result expectedError
    test mathop-7.36 {interpreted |: argument processing order} -body {
	list [catch {
	    $op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
	} msg] $msg $x
593
594
595
596
597
598
599
600

601
602
603

604
605
606
607
608
609
610

611
612
613

614
615
616

617
618
619

620
621
622

623
624
625

626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642

643
644
645

646
647
648
649
650
651
652

653
654
655

656
657
658

659
660
661

662
663
664

665
666
667

668
669
670
671
672
673
674
593
594
595
596
597
598
599

600
601
602

603
604
605
606
607
608
609

610
611
612

613
614
615

616
617
618

619
620
621

622
623
624

625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641

642
643
644

645
646
647
648
649
650
651

652
653
654

655
656
657

658
659
660

661
662
663

664
665
666

667
668
669
670
671
672
673
674







-
+


-
+






-
+


-
+


-
+


-
+


-
+


-
+
















-
+


-
+






-
+


-
+


-
+


-
+


-
+


-
+








    test mathop-8.1 {compiled ^} { ^ } 0
    test mathop-8.2 {compiled ^} { ^ 1 } 1
    test mathop-8.3 {compiled ^} { ^ 1 2 } 3
    test mathop-8.4 {compiled ^} { ^ 3 7 6 } 2
    test mathop-8.5 {compiled ^} -returnCodes error -body {
	^ 1.0 2 3
    } -result {can't use floating-point value "1.0" as operand of "^"}
    } -result {cannot use floating-point value "1.0" as right operand of "^"}
    test mathop-8.6 {compiled ^} -returnCodes error -body {
	^ 1 2 3.0
    } -result {can't use floating-point value "3.0" as operand of "^"}
    } -result {cannot use floating-point value "3.0" as left operand of "^"}
    test mathop-8.7 {compiled ^} { ^ 100000000002 18 -126 } -100000000110
    test mathop-8.8 {compiled ^} { ^ 0xff 0o377 333333333333 } 333333333333
    test mathop-8.9 {compiled ^} { ^ 1000000000000000000002 18 -126 } -1000000000000000000110
    test mathop-8.10 {compiled ^} { ^ 0xff 0o377 3333333333333333333333 } 3333333333333333333333
    test mathop-8.11 {compiled ^: errors} -returnCodes error -body {
	^ x 0
    } -result {can't use non-numeric string "x" as operand of "^"}
    } -result {cannot use non-numeric string "x" as left operand of "^"}
    test mathop-8.12 {compiled ^: errors} -returnCodes error -body {
	^ nan 0
    } -result {can't use non-numeric floating-point value "nan" as operand of "^"}
    } -result {cannot use non-numeric floating-point value "nan" as left operand of "^"}
    test mathop-8.13 {compiled ^: errors} -returnCodes error -body {
	^ 0 x
    } -result {can't use non-numeric string "x" as operand of "^"}
    } -result {cannot use non-numeric string "x" as right operand of "^"}
    test mathop-8.14 {compiled ^: errors} -returnCodes error -body {
	^ 0 nan
    } -result {can't use non-numeric floating-point value "nan" as operand of "^"}
    } -result {cannot use non-numeric floating-point value "nan" as right operand of "^"}
    test mathop-8.15 {compiled ^: errors} -returnCodes error -body {
	^ 0o8 0
    } -result {can't use non-numeric string "0o8" as operand of "^"}
    } -result {cannot use non-numeric string "0o8" as left operand of "^"}
    test mathop-8.16 {compiled ^: errors} -returnCodes error -body {
	^ 0 0o8
    } -result {can't use non-numeric string "0o8" as operand of "^"}
    } -result {cannot use non-numeric string "0o8" as right operand of "^"}
    test mathop-8.17 {compiled ^: errors} -returnCodes error -body {
	^ 0 [error expectedError]
    } -result expectedError
    test mathop-8.18 {compiled ^: argument processing order} -body {
	# Bytecode compilation known hard for 3+ arguments
	list [catch {
	    ^ [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
	} msg] $msg $x
    } -result {1 expected 2}
    set op ^
    test mathop-8.19 {interpreted ^} { $op } 0
    test mathop-8.20 {interpreted ^} { $op 1 } 1
    test mathop-8.21 {interpreted ^} { $op 1 2 } 3
    test mathop-8.22 {interpreted ^} { $op 3 7 6 } 2
    test mathop-8.23 {interpreted ^} -returnCodes error -body {
	$op 1.0 2 3
    } -result {can't use floating-point value "1.0" as operand of "^"}
    } -result {cannot use floating-point value "1.0" as left operand of "^"}
    test mathop-8.24 {interpreted ^} -returnCodes error -body {
	$op 1 2 3.0
    } -result {can't use floating-point value "3.0" as operand of "^"}
    } -result {cannot use floating-point value "3.0" as right operand of "^"}
    test mathop-8.25 {interpreted ^} { $op 100000000002 18 -126 } -100000000110
    test mathop-8.26 {interpreted ^} { $op 0xff 0o377 333333333333 } 333333333333
    test mathop-8.27 {interpreted ^} { $op 1000000000000000000002 18 -126 } -1000000000000000000110
    test mathop-8.28 {interpreted ^} { $op 0xff 0o377 3333333333333333333333 } 3333333333333333333333
    test mathop-8.29 {interpreted ^: errors} -returnCodes error -body {
	$op x 0
    } -result {can't use non-numeric string "x" as operand of "^"}
    } -result {cannot use non-numeric string "x" as left operand of "^"}
    test mathop-8.30 {interpreted ^: errors} -returnCodes error -body {
	$op nan 0
    } -result {can't use non-numeric floating-point value "nan" as operand of "^"}
    } -result {cannot use non-numeric floating-point value "nan" as left operand of "^"}
    test mathop-8.31 {interpreted ^: errors} -returnCodes error -body {
	$op 0 x
    } -result {can't use non-numeric string "x" as operand of "^"}
    } -result {cannot use non-numeric string "x" as right operand of "^"}
    test mathop-8.32 {interpreted ^: errors} -returnCodes error -body {
	$op 0 nan
    } -result {can't use non-numeric floating-point value "nan" as operand of "^"}
    } -result {cannot use non-numeric floating-point value "nan" as right operand of "^"}
    test mathop-8.33 {interpreted ^: errors} -returnCodes error -body {
	$op 0o8 0
    } -result {can't use non-numeric string "0o8" as operand of "^"}
    } -result {cannot use non-numeric string "0o8" as left operand of "^"}
    test mathop-8.34 {interpreted ^: errors} -returnCodes error -body {
	$op 0 0o8
    } -result {can't use non-numeric string "0o8" as operand of "^"}
    } -result {cannot use non-numeric string "0o8" as right operand of "^"}
    test mathop-8.35 {interpreted ^: errors} -returnCodes error -body {
	$op 0 [error expectedError]
    } -result expectedError
    test mathop-8.36 {interpreted ^: argument processing order} -body {
	list [catch {
	    $op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
	} msg] $msg $x
702
703
704
705
706
707
708
709

710
711
712
713
714
715
716

717
718
719
720
721
722
723
724

725
726
727
728
729
730
731
732
733
734
735
736






737
738
739
740
741
742
743
744
745



746
747
748
749

750
751
752
753
754
755



756
757
758
759
760
761
762
763
764
765
766
767






768
769
770
771
772
773
774
775
776
777
778
779
780






781
782
783
784

785
786
787

788
789
790
791
792
793
794



795
796
797
798
799
800
801
802
803
804



805
806
807
808
809
810
811
702
703
704
705
706
707
708

709
710
711
712
713
714
715

716
717
718
719
720
721
722
723

724
725
726
727
728
729
730






731
732
733
734
735
736
737
738
739
740
741
742



743
744
745
746
747
748

749
750
751
752



753
754
755
756
757
758
759
760
761






762
763
764
765
766
767
768
769
770
771
772
773
774






775
776
777
778
779
780
781
782
783

784
785
786

787
788
789
790
791



792
793
794
795
796
797
798
799
800
801



802
803
804
805
806
807
808
809
810
811







-
+






-
+







-
+






-
-
-
-
-
-
+
+
+
+
+
+






-
-
-
+
+
+



-
+



-
-
-
+
+
+






-
-
-
-
-
-
+
+
+
+
+
+







-
-
-
-
-
-
+
+
+
+
+
+



-
+


-
+




-
-
-
+
+
+







-
-
-
+
+
+







    } {70720 70720}

    # TODO: % ** << >>  - /  == != < <= > >=  ne  in ni

    test mathop-13.100 {compiled -: argument processing order} -body {
      # Bytecode compilation known hard for 3+ arguments
      list [catch {
          - [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
	  - [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
      } msg] $msg $x
    } -result {1 expected 2}

    test mathop-14.100 {compiled /: argument processing order} -body {
      # Bytecode compilation known hard for 3+ arguments
      list [catch {
          / [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
	  / [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
      } msg] $msg $x
    } -result {1 expected 2}
}

test mathop-20.1 { zero args, return unit } {
    set res {}
    foreach op {+ * & ^ | ** < <= > >= == eq} {
        lappend res [TestOp $op]
	lappend res [TestOp $op]
    }
    set res
} {0 1 -1 0 0 1 1 1 1 1 1 1}
test mathop-20.2 { zero args, not allowed } {
    set exp {}
    foreach op {~ ! << >> % != ne in ni - /} {
        set res [TestOp $op]
        if {[string match "wrong # args: should be * TCL WRONGARGS" $res]} {
            lappend exp 0
        } else {
            lappend exp $res
        }
	set res [TestOp $op]
	if {[string match "wrong # args: should be * TCL WRONGARGS" $res]} {
	    lappend exp 0
	} else {
	    lappend exp $res
	}
    }
    set exp
} {0 0 0 0 0 0 0 0 0 0 0}
test mathop-20.3 { one arg } {
    set res {}
    foreach val {7 8.3} {
        foreach op {+ ** - * / < <= > >= == eq !} {
            lappend res [TestOp $op $val]
        }
	foreach op {+ ** - * / < <= > >= == eq !} {
	    lappend res [TestOp $op $val]
	}
    }
    set res
} [list 7   7   -7   7   [expr {1.0/7.0}] 1 1 1 1 1 1 0 \
        8.3 8.3 -8.3 8.3 [expr {1.0/8.3}] 1 1 1 1 1 1 0]
	8.3 8.3 -8.3 8.3 [expr {1.0/8.3}] 1 1 1 1 1 1 0]
test mathop-20.4 { one arg, integer only ops } {
    set res {}
    foreach val {23} {
        foreach op {& | ^ ~} {
            lappend res [TestOp $op $val]
        }
	foreach op {& | ^ ~} {
	    lappend res [TestOp $op $val]
	}
    }
    set res
} [list 23 23 23 -24]
test mathop-20.5 { one arg, not allowed } {
    set exp {}
    foreach op {% != ne in ni << >>} {
        set res [TestOp $op 1]
        if {[string match "wrong # args: should be * TCL WRONGARGS" $res]} {
            lappend exp 0
        } else {
            lappend exp $res
        }
	set res [TestOp $op 1]
	if {[string match "wrong # args: should be * TCL WRONGARGS" $res]} {
	    lappend exp 0
	} else {
	    lappend exp $res
	}
    }
    set exp
} {0 0 0 0 0 0 0}
test mathop-20.6 { one arg, error } {
    set res {}
    set exp {}
    foreach vals {x {1 x} {1 1 x} {1 x 1}} {
        # skipping - for now, knownbug...
        foreach op {+ * / & | ^ **} {
            lappend res [TestOp $op {*}$vals]
            lappend exp "can't use non-numeric string \"x\" as operand of \"$op\"\
		ARITH DOMAIN {non-numeric string}"
        }
	# skipping - for now, knownbug...
	foreach op {+ * / & | ^ **} {
	    #lappend res [TestOp $op {*}$vals]
	    #lappend exp "cannot use non-numeric string \"x\" as right operand of \"$op\"\
		#ARITH DOMAIN {non-numeric string}"
	}
    }
    foreach op {+ * / & | ^ **} {
	lappend res [TestOp $op NaN 1]
	lappend exp "can't use non-numeric floating-point value \"NaN\" as operand of \"$op\"\
	lappend exp "cannot use non-numeric floating-point value \"NaN\" as left operand of \"$op\"\
	    ARITH DOMAIN {non-numeric floating-point value}"
    }
    expr {$res eq $exp ? 0 : $res}
    expr {$res eq $exp ? 0 : "$res\n$exp"}
} 0
test mathop-20.7 { multi arg } {
    set res {}
    foreach vals {{1 2} {3 4 5} {4 3 2 1}} {
        foreach op {+ - * /} {
            lappend res [TestOp $op {*}$vals]
        }
	foreach op {+ - * /} {
	    lappend res [TestOp $op {*}$vals]
	}
    }
    set res
} [list 3 -1 2 0  12 -6 60 0  10 -2 24 0]
test mathop-20.8 { multi arg, double } {
    set res {}
    foreach vals {{1.0 2} {3.0 4 5} {4 3.0 2 1}
	    {1.0 -1.0 1e-18} {1.0 1.0 1e-18}} {
        foreach op {+ - * /} {
            lappend res [TestOp $op {*}$vals]
        }
	foreach op {+ - * /} {
	    lappend res [TestOp $op {*}$vals]
	}
    }
    set res
} [list 3.0 -1.0 2.0 0.5  12.0 -6.0 60.0 0.15  10.0 -2.0 24.0 [expr {2.0/3}] 1e-18 2.0 -1e-18 [expr {-1.0/1e-18}] 2.0 -1e-18 1e-18 [expr {1.0/1e-18}]]

test mathop-21.1 { unary ops, bitnot } {
    set res {}
    lappend res [TestOp ~ 7]
830
831
832
833
834
835
836
837

838
839
840
841
842
843
844
845
846
847
848

849
850
851
852
853
854
855



856
857

858
859

860
861
862


863
864
865
866
867
868
869
870
871
872






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
898
899




900
901
902
903
904
905
906
907
908
909







910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931









932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
830
831
832
833
834
835
836

837
838
839
840
841
842
843
844
845
846
847

848
849
850
851
852



853
854
855
856

857
858

859
860


861
862
863
864
865
866






867
868
869
870
871
872
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
898
899
900
901
902







903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922









923
924
925
926
927
928
929
930
931
932
933
934




























935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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







-
+










-
+




-
-
-
+
+
+

-
+

-
+

-
-
+
+




-
-
-
-
-
-
+
+
+
+
+
+







-
-
-
+
+
+













-
-
-
-
+
+
+
+



-
-
-
-
-
-
-
+
+
+
+
+
+
+













-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
-
-
+
+
+
+

-
+











-
+



-
-
-
+
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+







-
-
-
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+




-
-
-
+
+
+







-
-
-
-
+
+
+
+



-
-
+
+







    lappend res [TestOp - -5]
    lappend res [TestOp - -2147483648]                  ;# -2**31
    lappend res [TestOp - -9223372036854775808]         ;# -2**63
    lappend res [TestOp -  354657483923456]             ;# wide
    lappend res [TestOp -  123456789123456789123456789] ;# big
    set res
} [list -7.2 5 2147483648 9223372036854775808 -354657483923456 \
           -123456789123456789123456789]
	   -123456789123456789123456789]
test mathop-21.4 { unary ops, inversion } {
    set res {}
    lappend res [TestOp / 1]
    lappend res [TestOp / 5]
    lappend res [TestOp / 5.6]
    lappend res [TestOp / -8]
    lappend res [TestOp /  354657483923456]             ;# wide
    lappend res [TestOp /  123456789123456789123456789] ;# big
    set res
} [list 1.0 0.2 0.17857142857142858 -0.125 \
           2.8196218755553604e-15 8.10000006561e-27]
	   2.8196218755553604e-15 8.10000006561e-27]
test mathop-21.5 { unary ops, bad values } {
    set res {}
    set exp {}
    lappend res [TestOp / x]
    lappend exp "can't use non-numeric string \"x\" as operand of \"/\" ARITH DOMAIN {non-numeric string}"
    lappend res [TestOp - x]
    lappend exp "can't use non-numeric string \"x\" as operand of \"-\" ARITH DOMAIN {non-numeric string}"
    lappend exp "cannot use non-numeric string \"x\" as right operand of \"/\" ARITH DOMAIN {non-numeric string}"
    #lappend res [TestOp - x]
    #lappend exp "cannot use non-numeric string \"x\" as operand of \"-\" ARITH DOMAIN {non-numeric string}"
    lappend res [TestOp ~ x]
    lappend exp "can't use non-numeric string \"x\" as operand of \"~\" ARITH DOMAIN {non-numeric string}"
    lappend exp "cannot use non-numeric string \"x\" as operand of \"~\" ARITH DOMAIN {non-numeric string}"
    lappend res [TestOp ! x]
    lappend exp "can't use non-numeric string \"x\" as operand of \"!\" ARITH DOMAIN {non-numeric string}"
    lappend exp "cannot use non-numeric string \"x\" as operand of \"!\" ARITH DOMAIN {non-numeric string}"
    lappend res [TestOp ~ 5.0]
    lappend exp "can't use floating-point value \"5.0\" as operand of \"~\" ARITH DOMAIN {floating-point value}"
    expr {$res eq $exp ? 0 : $res}
    lappend exp "cannot use floating-point value \"5.0\" as operand of \"~\" ARITH DOMAIN {floating-point value}"
    expr {$res eq $exp ? 0 : "$res\n$exp"}
} 0
test mathop-21.6 { unary ops, too many } {
    set exp {}
    foreach op {~ !} {
        set res [TestOp $op 7 8]
        if {[string match "wrong # args: should be * TCL WRONGARGS" $res]} {
            lappend exp 0
        } else {
            lappend exp $res
        }
	set res [TestOp $op 7 8]
	if {[string match "wrong # args: should be * TCL WRONGARGS" $res]} {
	    lappend exp 0
	} else {
	    lappend exp $res
	}
    }
    set exp
} {0 0}

test mathop-22.1 { bitwise ops } {
    set res {}
    foreach vals {5 {1 6} {1 2 3} {1 2 3 4}} {
        foreach op {& | ^} {
            lappend res [TestOp $op {*}$vals]
        }
	foreach op {& | ^} {
	    lappend res [TestOp $op {*}$vals]
	}
    }
    set res
} [list 5 5 5  0 7 7  0 3 0  0 7 4]
test mathop-22.2 { bitwise ops on bignums } {
    set dig 50
    set a 0x[string repeat 5 $dig]
    set b 0x[string repeat 7 $dig]
    set c 0x[string repeat 9 $dig]
    set bn [expr {~$b}]
    set cn [expr {~$c}]

    set res {}
    foreach vals [list [list $a $b] [list $a $c] [list $b $c] \
                          [list $a $bn] [list $bn $c] [list $bn $cn]] {
        foreach op {& | ^} {
            lappend res [TestOp $op {*}$vals]
        }
			  [list $a $bn] [list $bn $c] [list $bn $cn]] {
	foreach op {& | ^} {
	    lappend res [TestOp $op {*}$vals]
	}
    }
    set exp {}
    foreach d {5 7 2  1 D C  1 F E  0 -D -D  8 -9 -1  -0 -E E} {
        if {[string match "-*" $d]} {
            set d [format %X [expr 15-0x[string range $d 1 end]]]
            set val [expr -0x[string repeat $d $dig]-1]
        } else {
            set val [expr 0x[string repeat $d $dig]]
        }
        lappend exp $val
	if {[string match "-*" $d]} {
	    set d [format %X [expr {15-"0x[string range $d 1 end]"}]]
	    set val [expr {-"0x[string repeat $d $dig]"-1}]
	} else {
	    set val [expr {"0x[string repeat $d $dig]"}]
	}
	lappend exp $val
    }
    expr {$exp eq $res ? 1 : "($res != $exp"}
} 1
test mathop-22.3 { bitwise ops } {
    set big1      12135435435354435435342423948763867876
    set big2       2746237174783836746262564892918327847
    set wide1                             12345678912345
    set wide2                             87321847232215
    set small1                                     87345
    set small2                                     16753

    set res {}
    foreach op {& | ^} {
        lappend res [TestOp $op $big1   $big2]
        lappend res [TestOp $op $big1   $wide2]
        lappend res [TestOp $op $big1   $small2]
        lappend res [TestOp $op $wide1  $big2]
        lappend res [TestOp $op $wide1  $wide2]
        lappend res [TestOp $op $wide1  $small2]
        lappend res [TestOp $op $small1 $big2]
        lappend res [TestOp $op $small1 $wide2]
        lappend res [TestOp $op $small1 $small2]
	lappend res [TestOp $op $big1   $big2]
	lappend res [TestOp $op $big1   $wide2]
	lappend res [TestOp $op $big1   $small2]
	lappend res [TestOp $op $wide1  $big2]
	lappend res [TestOp $op $wide1  $wide2]
	lappend res [TestOp $op $wide1  $small2]
	lappend res [TestOp $op $small1 $big2]
	lappend res [TestOp $op $small1 $wide2]
	lappend res [TestOp $op $small1 $small2]
    }
    set res
} [list \
           712439449294653815890598856501796 \
           78521450111684 \
           96 \
           2371422390785 \
           12275881497169 \
           16721 \
           33 \
           87057 \
           16689 \
           14880960170688977527789098242825693927 \
           12135435435354435435342432749160988407 \
           12135435435354435435342423948763884533 \
           2746237174783836746262574867174849407 \
           87391644647391 \
           12345678912377 \
           2746237174783836746262564892918415159 \
           87321847232503 \
           87409 \
           14880247731239682873973207643969192131 \
           12135435435354435435342354227710876723 \
           12135435435354435435342423948763884437 \
           2746237174783836746262572495752458622 \
           75115763150222 \
           12345678895656 \
           2746237174783836746262564892918415126 \
           87321847145446 \
           70720 \
          ]
	   712439449294653815890598856501796 \
	   78521450111684 \
	   96 \
	   2371422390785 \
	   12275881497169 \
	   16721 \
	   33 \
	   87057 \
	   16689 \
	   14880960170688977527789098242825693927 \
	   12135435435354435435342432749160988407 \
	   12135435435354435435342423948763884533 \
	   2746237174783836746262574867174849407 \
	   87391644647391 \
	   12345678912377 \
	   2746237174783836746262564892918415159 \
	   87321847232503 \
	   87409 \
	   14880247731239682873973207643969192131 \
	   12135435435354435435342354227710876723 \
	   12135435435354435435342423948763884437 \
	   2746237174783836746262572495752458622 \
	   75115763150222 \
	   12345678895656 \
	   2746237174783836746262564892918415126 \
	   87321847145446 \
	   70720 \
	  ]
test mathop-22.4 { unary ops, bad values } {
    set res {}
    set exp {}
    foreach op {& | ^} {
        lappend res [TestOp $op x 5]
        lappend exp "can't use non-numeric string \"x\" as operand of \"$op\" ARITH DOMAIN {non-numeric string}"
        lappend res [TestOp $op 5 x]
        lappend exp "can't use non-numeric string \"x\" as operand of \"$op\" ARITH DOMAIN {non-numeric string}"
	lappend res [TestOp $op x 5]
	lappend exp "cannot use non-numeric string \"x\" as left operand of \"$op\" ARITH DOMAIN {non-numeric string}"
	lappend res [TestOp $op 5 x]
	lappend exp "cannot use non-numeric string \"x\" as right operand of \"$op\" ARITH DOMAIN {non-numeric string}"
    }
    expr {$res eq $exp ? 0 : $res}
    expr {$res eq $exp ? 0 : "$res\n$exp"}
} 0

test mathop-23.1 { comparison ops, numerical } {
    set res {}
    set todo {5 {1 6} {1 2 2 3} {4 3 2 1} {5.0 5.0} {6 3 3 1} {5.0 5}}
    lappend todo [list 2342476234762482734623842342 234827463876473 3434]
    lappend todo [list 2653 453735910264536 453735910264537 2384762472634982746239847637]
    lappend todo [list 2653 2384762472634982746239847637]
    lappend todo [list 2653 -2384762472634982746239847637]
    lappend todo [list 3789253678212653 -2384762472634982746239847637]
    lappend todo [list 5.0 6 7.0 8 1e13 1945628567352654 1.1e20 \
                          6734253647589123456784564378 2.3e50]
			  6734253647589123456784564378 2.3e50]
    set a 7
    lappend todo [list $a $a] ;# Same object
    foreach vals $todo {
        foreach op {< <= > >= == eq} {
            lappend res [TestOp $op {*}$vals]
        }
	foreach op {< <= > >= == eq} {
	    lappend res [TestOp $op {*}$vals]
	}
    }
    set res
} [list 1 1 1 1 1 1 \
        1 1 0 0 0 0 \
        0 1 0 0 0 0 \
        0 0 1 1 0 0 \
        0 1 0 1 1 1 \
        0 0 0 1 0 0 \
        0 1 0 1 1 0 \
        0 0 1 1 0 0 \
        1 1 0 0 0 0 \
        1 1 0 0 0 0 \
        0 0 1 1 0 0 \
        0 0 1 1 0 0 \
        1 1 0 0 0 0 \
        0 1 0 1 1 1 \
	1 1 0 0 0 0 \
	0 1 0 0 0 0 \
	0 0 1 1 0 0 \
	0 1 0 1 1 1 \
	0 0 0 1 0 0 \
	0 1 0 1 1 0 \
	0 0 1 1 0 0 \
	1 1 0 0 0 0 \
	1 1 0 0 0 0 \
	0 0 1 1 0 0 \
	0 0 1 1 0 0 \
	1 1 0 0 0 0 \
	0 1 0 1 1 1 \
       ]
test mathop-23.2 { comparison ops, string } {
    set res {}
    set todo {a {a b} {5 b b c} {d c b a} {xy xy} {gy ef ef ab}}
    set a x
    lappend todo [list $a $a]
    foreach vals $todo {
        foreach op {< <= > >= == eq} {
            lappend res [TestOp $op {*}$vals]
        }
	foreach op {< <= > >= == eq} {
	    lappend res [TestOp $op {*}$vals]
	}
    }
    set res
} [list 1 1 1 1 1 1 \
        1 1 0 0 0 0 \
        0 1 0 0 0 0 \
        0 0 1 1 0 0 \
        0 1 0 1 1 1 \
        0 0 0 1 0 0 \
        0 1 0 1 1 1 \
	1 1 0 0 0 0 \
	0 1 0 0 0 0 \
	0 0 1 1 0 0 \
	0 1 0 1 1 1 \
	0 0 0 1 0 0 \
	0 1 0 1 1 1 \
       ]
test mathop-23.3 { comparison ops, nonequal} {
    set res {}
    foreach vals {{a b} {17.0 0x11} {foo foo} {10 10}} {
        foreach op {!= ne} {
            lappend res [TestOp $op {*}$vals]
        }
	foreach op {!= ne} {
	    lappend res [TestOp $op {*}$vals]
	}
    }
    set res
} [list 1 1  0 1  0 0  0 0 ]

test mathop-24.1 { binary ops } {
    set res {}
    foreach vals {{3 5} {17 7} {199 5} {293234675763434238476239486 17} \
                  {5 1} {0 7}} {
        foreach op {% << >> in ni} {
            lappend res [TestOp $op {*}$vals]
        }
		  {5 1} {0 7}} {
	foreach op {% << >> in ni} {
	    lappend res [TestOp $op {*}$vals]
	}
    }
    set res
} [list 3 96 0 0 1  3 2176 0 0 1  4 6368 6 0 1 \
        14 38434855421664852505557661908992 2237203031642412097749 0 1 \
        0 10 2 0 1  0 0 0 0 1]
	14 38434855421664852505557661908992 2237203031642412097749 0 1 \
	0 10 2 0 1  0 0 0 0 1]
test mathop-24.2 { binary ops, modulo } {
    # Test different combinations to get all code paths
    set res {}

    set bigbig 14372423674564535234543545248972634923869
    set big       12135435435354435435342423948763867876
    set wide                              12345678912345
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
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







-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+




-
-
-
-
+
+
+
+


-
-
-
-
+
+
+
+


-
-
+
+









-
+







    lappend res [TestOp % $small   $big]
    lappend res [TestOp % $neg     $big]
    lappend res [TestOp % $small  $wide]
    lappend res [TestOp % $neg    $wide]
    lappend res [TestOp % $wide  $small]
    set res
} [list   4068119104883679098115293636215358685 \
                                 12345678912345 \
         12135435435354435435342411603084955531 \
                                              5 \
         12135435435354435435342423948763867871 \
                                              5 \
                                 12345678912340 \
                                              0 \
          ]
				 12345678912345 \
	 12135435435354435435342411603084955531 \
					      5 \
	 12135435435354435435342423948763867871 \
					      5 \
				 12345678912340 \
					      0 \
	  ]
test mathop-24.3 { binary ops, bad values } {
    set res {}
    set exp {}
    foreach op {% << >>} {
        lappend res [TestOp $op x 1]
        lappend exp "can't use non-numeric string \"x\" as operand of \"$op\" ARITH DOMAIN {non-numeric string}"
        lappend res [TestOp $op 1 x]
        lappend exp "can't use non-numeric string \"x\" as operand of \"$op\" ARITH DOMAIN {non-numeric string}"
	lappend res [TestOp $op x 1]
	lappend exp "cannot use non-numeric string \"x\" as left operand of \"$op\" ARITH DOMAIN {non-numeric string}"
	lappend res [TestOp $op 1 x]
	lappend exp "cannot use non-numeric string \"x\" as right operand of \"$op\" ARITH DOMAIN {non-numeric string}"
    }
    foreach op {% << >>} {
        lappend res [TestOp $op 5.0 1]
        lappend exp "can't use floating-point value \"5.0\" as operand of \"$op\" ARITH DOMAIN {floating-point value}"
        lappend res [TestOp $op 1 5.0]
        lappend exp "can't use floating-point value \"5.0\" as operand of \"$op\" ARITH DOMAIN {floating-point value}"
	lappend res [TestOp $op 5.0 1]
	lappend exp "cannot use floating-point value \"5.0\" as left operand of \"$op\" ARITH DOMAIN {floating-point value}"
	lappend res [TestOp $op 1 5.0]
	lappend exp "cannot use floating-point value \"5.0\" as right operand of \"$op\" ARITH DOMAIN {floating-point value}"
    }
    foreach op {in ni} {
        lappend res [TestOp $op 5 "a b \{ c"]
        lappend exp "unmatched open brace in list TCL VALUE LIST BRACE"
	lappend res [TestOp $op 5 "a b \{ c"]
	lappend exp "unmatched open brace in list TCL VALUE LIST BRACE"
    }
    lappend res [TestOp % 5 0]
    lappend exp "divide by zero ARITH DIVZERO {divide by zero}"
    lappend res [TestOp % 9838923468297346238478737647637375 0]
    lappend exp "divide by zero ARITH DIVZERO {divide by zero}"
    lappend res [TestOp / 5 0]
    lappend exp "divide by zero ARITH DIVZERO {divide by zero}"
    lappend res [TestOp / 9838923468297346238478737647637375 0]
    lappend exp "divide by zero ARITH DIVZERO {divide by zero}"
    expr {$res eq $exp ? 0 : $res}
    expr {$res eq $exp ? 0 : "$res\n$exp"}
} 0
test mathop-24.4 { binary ops, negative shift } {
    set res {}

    set big      -12135435435354435435342423948763867876
    set wide                             -12345678912345
    set small                                         -1
1169
1170
1171
1172
1173
1174
1175
1176
1177


1178
1179
1180
1181
1182
1183
1184



1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196






1197
1198
1199
1200
1201
1202
1203
1169
1170
1171
1172
1173
1174
1175


1176
1177
1178
1179
1180
1181



1182
1183
1184
1185
1186
1187
1188
1189
1190






1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203







-
-
+
+




-
-
-
+
+
+






-
-
-
-
-
-
+
+
+
+
+
+







    set small                                          5
    set neg                                           -5

    lappend res [TestOp << $wide $small]
    lappend res [TestOp >> $wide $small]
    set res
} [list   395061725195040 \
             385802466010 \
          ]
	     385802466010 \
	  ]
test mathop-24.7 { binary ops, list search } {
    set res {}

    foreach op {in ni} {
        lappend res [TestOp $op 5 {7 5 8}]
        lappend res [TestOp $op hej {foo bar hej}]
        lappend res [TestOp $op 5 {7 0x5 8}]
	lappend res [TestOp $op 5 {7 5 8}]
	lappend res [TestOp $op hej {foo bar hej}]
	lappend res [TestOp $op 5 {7 0x5 8}]
    }
    set res
} [list 1 1 0  0 0 1]
test mathop-24.8 { binary ops, too many } {
    set exp {}
    foreach op {<< >> % != ne in ni ~ !} {
        set res [TestOp $op 7 8 9]
        if {[string match "wrong # args: should be * TCL WRONGARGS" $res]} {
            lappend exp 0
        } else {
            lappend exp $res
        }
	set res [TestOp $op 7 8 9]
	if {[string match "wrong # args: should be * TCL WRONGARGS" $res]} {
	    lappend exp 0
	} else {
	    lappend exp $res
	}
    }
    set exp
} {0 0 0 0 0 0 0 0 0}

test mathop-25.1  { exp operator } {TestOp **        } 1
test mathop-25.2  { exp operator } {TestOp **   0    } 0
test mathop-25.3  { exp operator } {TestOp **   0   5} 0
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
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







-
+

-
+

-
+












-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    lappend res [TestOp ** $small $wide]
    lappend exp "exponent too large NONE"
    lappend res [TestOp ** 2 $big]
    lappend exp "exponent too large NONE"
    lappend res [TestOp ** $huge 2.1]
    lappend exp "Inf"
    lappend res [TestOp ** 2 foo]
    lappend exp "can't use non-numeric string \"foo\" as operand of \"**\" ARITH DOMAIN {non-numeric string}"
    lappend exp "cannot use non-numeric string \"foo\" as right operand of \"**\" ARITH DOMAIN {non-numeric string}"
    lappend res [TestOp ** foo 2]
    lappend exp "can't use non-numeric string \"foo\" as operand of \"**\" ARITH DOMAIN {non-numeric string}"
    lappend exp "cannot use non-numeric string \"foo\" as left operand of \"**\" ARITH DOMAIN {non-numeric string}"

    expr {$res eq $exp ? 0 : $res}
    expr {$res eq $exp ? 0 : "$res\n$exp"}
} 0

test mathop-26.1 { misc ops, size combinations } {
    set big1      12135435435354435435342423948763867876
    set big2       2746237174783836746262564892918327847
    set wide1                             87321847232215
    set wide2                             12345678912345
    set small1                                     87345
    set small2                                     16753

    set res {}
    foreach op {+ * - /} {
        lappend res [TestOp $op $big1   $big2]
        lappend res [TestOp $op $big1   $wide2]
        lappend res [TestOp $op $big1   $small2]
        lappend res [TestOp $op $wide1  $big2]
        lappend res [TestOp $op $wide1  $wide2]
        lappend res [TestOp $op $wide1  $small2]
        lappend res [TestOp $op $small1 $big2]
        lappend res [TestOp $op $small1 $wide2]
        lappend res [TestOp $op $small1 $small2]
	lappend res [TestOp $op $big1   $big2]
	lappend res [TestOp $op $big1   $wide2]
	lappend res [TestOp $op $big1   $small2]
	lappend res [TestOp $op $wide1  $big2]
	lappend res [TestOp $op $wide1  $wide2]
	lappend res [TestOp $op $wide1  $small2]
	lappend res [TestOp $op $small1 $big2]
	lappend res [TestOp $op $small1 $wide2]
	lappend res [TestOp $op $small1 $small2]
    }
    set res
} [list \
           14881672610138272181604988841682195723 \
           12135435435354435435342436294442780221 \
           12135435435354435435342423948763884629 \
           2746237174783836746262652214765560062 \
           99667526144560 \
           87321847248968 \
           2746237174783836746262564892918415192 \
           12345678999690 \
           104098 \
           33326783924759424684447891401270222910405366244661685890993770489959542972 \
           149820189346379518024969783068410988366610965329220 \
           203304949848492856848291628413641078526628 \
           239806503039903915972546163440347114360602909991105 \
           1078047487961768329845194175 \
           1462902906681297895 \
           239870086031494220602303730571951345796215 \
           1078333324598774025 \
           1463290785 \
           9389198260570598689079859055845540029 \
           12135435435354435435342411603084955531 \
           12135435435354435435342423948763851123 \
           -2746237174783836746262477571071095632 \
           74976168319870 \
           87321847215462 \
           -2746237174783836746262564892918240502 \
           -12345678825000 \
           70592 \
           4 \
           982970278225822587257201 \
           724373869477373332259441529801460 \
           0 \
           7 \
           5212311062 \
           0 \
           0 \
           5 \
          ]
	   14881672610138272181604988841682195723 \
	   12135435435354435435342436294442780221 \
	   12135435435354435435342423948763884629 \
	   2746237174783836746262652214765560062 \
	   99667526144560 \
	   87321847248968 \
	   2746237174783836746262564892918415192 \
	   12345678999690 \
	   104098 \
	   33326783924759424684447891401270222910405366244661685890993770489959542972 \
	   149820189346379518024969783068410988366610965329220 \
	   203304949848492856848291628413641078526628 \
	   239806503039903915972546163440347114360602909991105 \
	   1078047487961768329845194175 \
	   1462902906681297895 \
	   239870086031494220602303730571951345796215 \
	   1078333324598774025 \
	   1463290785 \
	   9389198260570598689079859055845540029 \
	   12135435435354435435342411603084955531 \
	   12135435435354435435342423948763851123 \
	   -2746237174783836746262477571071095632 \
	   74976168319870 \
	   87321847215462 \
	   -2746237174783836746262564892918240502 \
	   -12345678825000 \
	   70592 \
	   4 \
	   982970278225822587257201 \
	   724373869477373332259441529801460 \
	   0 \
	   7 \
	   5212311062 \
	   0 \
	   0 \
	   5 \
	  ]
test mathop-26.2 { misc ops, corner cases } {
    set res {}
    lappend res [TestOp - 0 -2147483648]                  ;# -2**31
    lappend res [TestOp - 0 -9223372036854775808]         ;# -2**63
    lappend res [TestOp / -9223372036854775808 -1]
    lappend res [TestOp * 2147483648 2]
    lappend res [TestOp * 9223372036854775808 2]
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391



1392
1393
1394
1395
1396
1397
1398
1382
1383
1384
1385
1386
1387
1388



1389
1390
1391
1392
1393
1394
1395
1396
1397
1398







-
-
-
+
+
+







test mathop-30.8 {ge operator} {::tcl::mathop::ge a c b} 0
test mathop-30.9 {ge operator} {::tcl::mathop::ge 0x0 012} 1

if 0 {
    # Compare ops to expr bytecodes
    namespace import ::tcl::mathop::*
    proc _X {a b c} {
        set x [+ $a [- $b $c]]
        set y [expr {$a + ($b - $c)}]
        set z [< $a $b $c]
	set x [+ $a [- $b $c]]
	set y [expr {$a + ($b - $c)}]
	set z [< $a $b $c]
    }
    set ::tcl_traceCompile 2
    _X 3 4 5
    set ::tcl_traceCompile 0
}

# cleanup

Changes to tests/misc.test.

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
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







-
-
-
+
+
+










-
+







# Commands covered:  various
#
# This file contains a collection of miscellaneous Tcl tests that
# don't fit naturally in any of the other test files.  Many of these
# tests are pathological cases that caused bugs in earlier Tcl
# releases.
#
# Copyright (c) 1992-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1992-1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testhashsystemhash [llength [info commands testhashsystemhash]]

test misc-1.1 {error in variable ref. in command in array reference} {
    proc tstProc {} {
	global a

Changes to tests/msgcat.test.

1
2
3
4
5
6


7
8
9
10
11
12
13
1
2
3
4


5
6
7
8
9
10
11
12
13




-
-
+
+







# This file contains a collection of tests for the msgcat package.
# Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1998 Mark Harrison.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1998 Mark Harrison.
# Copyright © 1998-1999 Scriptics Corporation.
# Contributions from Don Porter, NIST, 2002.  (not subject to US copyright)
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# Note that after running these tests, entries will be left behind in the
# message catalogs for locales foo, foo_BAR, and foo_BAR_baz.
255
256
257
258
259
260
261
262
263


264
265
266
267
268
269
270
255
256
257
258
259
260
261


262
263
264
265
266
267
268
269
270







-
-
+
+







    } -body {
	namespace eval baz {::msgcat::mc con1}
    } -result con1baz

    test msgcat-2.5 {mcmset, global scope} -setup {
	namespace eval :: {
	    ::msgcat::mcmset  foo_BAR {
	        src1 trans1
	        src2 trans2
		src1 trans1
		src2 trans2
	    }
	}
	variable locale [mclocale]
	mclocale foo_BAR
    } -cleanup {
	mclocale $locale
    } -body {
317
318
319
320
321
322
323
324

325
326
327
328



329
330
331
332
333
334
335
317
318
319
320
321
322
323

324
325



326
327
328
329
330
331
332
333
334
335







-
+

-
-
-
+
+
+







    #     ov1 should resolve to foo in foo_BAR, foo_BAR_baz
    #     ov4 should be resolved in none, and call mcunknown
    #
    variable count 2
    variable result
    array set result {
	foo,ov0 ov0_ROOT foo,ov1 ov1_foo foo,ov2 ov2_foo
        foo,ov3 ov3_foo foo,ov4 ov4
	foo,ov3 ov3_foo foo,ov4 ov4
	foo_BAR,ov0 ov0_ROOT foo_BAR,ov1 ov1_foo foo_BAR,ov2 ov2_foo_BAR
        foo_BAR,ov3 ov3_foo_BAR	foo_BAR,ov4 ov4
        foo_BAR_baz,ov0 ov0_ROOT foo_BAR_baz,ov1 ov1_foo
        foo_BAR_baz,ov2 ov2_foo_BAR
	foo_BAR,ov3 ov3_foo_BAR	foo_BAR,ov4 ov4
	foo_BAR_baz,ov0 ov0_ROOT foo_BAR_baz,ov1 ov1_foo
	foo_BAR_baz,ov2 ov2_foo_BAR
	foo_BAR_baz,ov3 ov3_foo_BAR_baz foo_BAR_baz,ov4 ov4
    }
    variable loc
    variable string
    foreach loc {foo foo_BAR foo_BAR_baz} {
	foreach string {ov0 ov1 ov2 ov3 ov4} {
	    test msgcat-3.$count {mcset, overlap} -setup {
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
442
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
442







-
+















-
+















-
+



















-
+







    } -body {
	mc unk2
    } -result unk2

    test msgcat-4.4 {mcunknown, overridden} -setup {
	rename ::msgcat::mcunknown SavedMcunknown
	proc ::msgcat::mcunknown {dom s} {
            return unknown:$dom:$s
	    return unknown:$dom:$s
	}
	mcset foo unk1 "unknown 1"
	variable locale [mclocale]
	mclocale foo
    } -cleanup {
	mclocale $locale
	rename ::msgcat::mcunknown {}
	rename SavedMcunknown ::msgcat::mcunknown
    } -body {
	mc unk1
    } -result {unknown 1}

    test msgcat-4.5 {mcunknown, overridden} -setup {
	rename ::msgcat::mcunknown SavedMcunknown
	proc ::msgcat::mcunknown {dom s} {
            return unknown:$dom:$s
	    return unknown:$dom:$s
	}
	mcset foo unk1 "unknown 1"
	variable locale [mclocale]
	mclocale foo
    } -cleanup {
	mclocale $locale
	rename ::msgcat::mcunknown {}
	rename SavedMcunknown ::msgcat::mcunknown
    } -body {
	mc unk2
    } -result {unknown:foo:unk2}

    test msgcat-4.6 {mcunknown, uplevel context} -setup {
	rename ::msgcat::mcunknown SavedMcunknown
	proc ::msgcat::mcunknown {dom s} {
            return "unknown:$dom:$s:[expr {[info level] - 1}]"
	    return "unknown:$dom:$s:[expr {[info level] - 1}]"
	}
	mcset foo unk1 "unknown 1"
	variable locale [mclocale]
	mclocale foo
    } -cleanup {
	mclocale $locale
	rename ::msgcat::mcunknown {}
	rename SavedMcunknown ::msgcat::mcunknown
    } -body {
	mc unk2
    } -result unknown:foo:unk2:[info level]

    # Tests msgcat-5.*: [mcload]

    variable locales {{} foo foo_BAR foo_BAR_baz}
    set msgdir [makeDirectory msgdir]
    foreach loc $locales {
	if { $loc eq {} } {
	    set msg ROOT
        } else {
	} else {
	    set msg [string tolower $loc]
	}
	makeFile [list ::msgcat::mcset $loc abc abc-$loc] $msg.msg $msgdir
    }
    variable count 1
    foreach loc {foo foo_BAR foo_BAR_baz} {
	test msgcat-5.$count {mcload} -setup {
548
549
550
551
552
553
554
555

556
557
558
559
560
561
562
548
549
550
551
552
553
554

555
556
557
558
559
560
561
562







-
+







	    mclocale foo
	    mcpackageconfig set mcfolder $msgdir
	} -result 2

    foreach loc $locales {
	if { $loc eq {} } {
	    set msg ROOT
        } else {
	} else {
	    set msg [string tolower $loc]
	}
	removeFile $msg.msg $msgdir
    }
    removeDirectory msgdir

    # Tests msgcat-6.*: [mcset], [mc] namespace inheritance
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
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140

1141
1142
1143
1144
1145
1146
1147
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
1116
1117
1118
1119

1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139

1140
1141
1142
1143
1144
1145
1146
1147







-
+

-
+











-
+

-
+















-
+

-
+










-
+

-
+














-
+



















-
+







    }
    set bgerrorsaved [interp bgerror {}]
    interp bgerror {} [namespace code callbackproc]

    variable locale
    if {![info exist locale]} { set locale [mclocale] }

	test msgcat-14.1 {invokation loadcmd} -setup {
	test msgcat-14.1 {invocation loadcmd} -setup {
	    mcforgetpackage
    	    mclocale $locale
	    mclocale $locale
	    mclocale ""
	    mcloadedlocales clear
	    set resultvariable ""
	} -cleanup {
	    mcforgetpackage
	} -body {
	    mcpackageconfig set loadcmd [namespace code callbackproc]
	    mclocale foo_bar
	    lsort $resultvariable
	} -result {foo foo_bar}

	test msgcat-14.2 {invokation failed in loadcmd} -setup {
	test msgcat-14.2 {invocation failed in loadcmd} -setup {
	    mcforgetpackage
    	    mclocale $locale
	    mclocale $locale
	    mclocale ""
	    mcloadedlocales clear
	} -cleanup {
	    mcforgetpackage
	    after cancel set [namespace current]::resultvariable timeout
	} -body {
	    mcpackageconfig set loadcmd [namespace code callbackfailproc]
	    mclocale foo_bar
	    # let the bgerror run
	    after 100 set [namespace current]::resultvariable timeout
	    vwait [namespace current]::resultvariable
	    lassign $resultvariable err errdict
	    list $err [dict get $errdict -code]
	} -result {fail 1}

	test msgcat-14.3 {invokation changecmd} -setup {
	test msgcat-14.3 {invocation changecmd} -setup {
	    mcforgetpackage
    	    mclocale $locale
	    mclocale $locale
	    mclocale ""
	    set resultvariable ""
	} -cleanup {
	    mcforgetpackage
	} -body {
	    mcpackageconfig set changecmd [namespace code callbackproc]
	    mclocale foo_bar
	    set resultvariable
	} -result {foo_bar foo {}}

	test msgcat-14.4 {invokation unknowncmd} -setup {
	test msgcat-14.4 {invocation unknowncmd} -setup {
	    mcforgetpackage
    	    mclocale $locale
	    mclocale $locale
	    mclocale ""
	    mcloadedlocales clear
	    set resultvariable ""
	} -cleanup {
	    mcforgetpackage
	} -body {
	    mcpackageconfig set unknowncmd [namespace code callbackproc]
	    mclocale foo_bar
	    mc k1 p1
	    set resultvariable
	} -result {foo_bar k1 p1}

	test msgcat-14.5 {disable global unknowncmd} -setup {
	    mcforgetpackage
    	    mclocale $locale
	    mclocale $locale
	    mclocale ""
	    mcloadedlocales clear
	    set resultvariable ""
	    rename ::msgcat::mcunknown SavedMcunknown
	    proc ::msgcat::mcunknown {dom s} {
		return unknown:$dom:$s
	    }
	} -cleanup {
	    mcforgetpackage
	    rename ::msgcat::mcunknown {}
	    rename SavedMcunknown ::msgcat::mcunknown
	} -body {
	    mcpackageconfig set unknowncmd ""
	    mclocale foo_bar
	    mc k1%s p1
	} -result {k1p1}

	test msgcat-14.6 {unknowncmd failing} -setup {
	    mcforgetpackage
    	    mclocale $locale
	    mclocale $locale
	    mclocale ""
	    mcloadedlocales clear
	    set resultvariable ""
	} -cleanup {
	    mcforgetpackage
	} -body {
	    mcpackageconfig set unknowncmd [namespace code callbackfailproc]
1177
1178
1179
1180
1181
1182
1183
1184

1185
1186
1187
1188
1189
1190
1191
1177
1178
1179
1180
1181
1182
1183

1184
1185
1186
1187
1188
1189
1190
1191







-
+







	namespace eval bar {
	    ::msgcat::mcset foo_BAR con2 con2bar
	    oo::class create ClassCur
	    oo::define ClassCur method method1 {} {::msgcat::mc con2}
	}
	# full namespace is ::msgcat::test:baz
	namespace eval baz {
            set ObjCur [::msgcat::test::bar::ClassCur new]
	    set ObjCur [::msgcat::test::bar::ClassCur new]
	}
	variable locale [mclocale]
	mclocale foo_BAR
    } -cleanup {
	mclocale $locale
	namespace eval bar {::msgcat::mcforgetpackage}
	namespace delete bar baz
1232
1233
1234
1235
1236
1237
1238
























1239
1240
1241
1242
1243
1244
1245
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	namespace eval bar {::msgcat::mcforgetpackage}
	namespace eval baz {::msgcat::mcforgetpackage}
	namespace delete bar baz
    } -body {
	bar::ObjCur method1
    } -result con2baz

    # HaO 2024-07-15 fix me
    # Ticket 91b3a5bb: I have no idea what the following case should do.
    # But currently, it raises an error and that should not happen.
    # The background is the tklib tooltip package.
    # This package captures the caller namespace to later invoke msgcat with current data.
    # If the caller namespace is a method, it currently fails.
    test msgcat-15.5 {ticket 91b3a5bb: method namespace recorded and evaluated gives error}\
    -setup {
	oo::class create App {}
	oo::define App {
	    constructor {} { my add_one }
	    method add_one {} { recordMsgcat }
	}
	proc ::recordMsgcat {} { set ::nscaller [uplevel 1 {namespace current}] }
	set application [App new]
} -cleanup {
	$application destroy
	App destroy
	unset -nocomplain ::nscaller
	rename ::recordMsgcat ""
    } -body {
	namespace eval $::nscaller [list ::msgcat::mc "Test"]
    } -returnCodes ok -result Test

    # Test msgcat-16.*: command mcpackagenamespaceget

    test msgcat-16.1 {mcpackagenamespaceget in namespace procedure} -body {
	namespace eval baz {msgcat::mcpackagenamespaceget}
    } -result ::msgcat::test::baz

    test msgcat-16.2 {mcpackagenamespaceget in class setup} -setup {
1255
1256
1257
1258
1259
1260
1261
1262

1263
1264
1265
1266
1267
1268
1269
1279
1280
1281
1282
1283
1284
1285

1286
1287
1288
1289
1290
1291
1292
1293







-
+








    test msgcat-16.3 {mcpackagenamespaceget in class} -setup {
	namespace eval bar {
	    oo::class create ClassCur
	    oo::define ClassCur method method1 {} {msgcat::mcpackagenamespaceget}
	}
	namespace eval baz {
            set ObjCur [::msgcat::test::bar::ClassCur new]
	    set ObjCur [::msgcat::test::bar::ClassCur new]
	}
    } -cleanup {
	namespace delete bar baz
    } -body {
	$baz::ObjCur method1
    } -result ::msgcat::test::bar

Changes to tests/namespace-old.test.

1
2
3
4
5
6
7
8
9
10
11
12



13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
17
18
19









-
-
-
+
+
+







# Functionality covered: this file contains slightly modified versions of
# the original tests written by Mike McLennan of Lucent Technologies for
# the procedures in tclNamesp.c that implement Tcl's basic support for
# namespaces. Other namespace-related tests appear in namespace.test
# and variable.test.
#
# Sourcing this file into Tcl runs the tests and generates output for
# errors. No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1997 Lucent Technologies
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1997 Lucent Technologies
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
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
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







-
+















-
-
-
-
+
+
+
+



















-
-
-
-
+
+
+
+







test namespace-old-1.3 {usage for "namespace eval"} {
    list [catch {namespace eval} msg] $msg
} {1 {wrong # args: should be "namespace eval name arg ?arg...?"}}
test namespace-old-1.4 {create new namespaces} {
    list [lsort [namespace children :: test_ns_simple*]] \
	 [namespace eval test_ns_simple {}] \
	 [namespace eval test_ns_simple2 {}] \
         [lsort [namespace children :: test_ns_simple*]]
	 [lsort [namespace children :: test_ns_simple*]]
} {{} {} {} {::test_ns_simple ::test_ns_simple2}}
test namespace-old-1.5 {access a new namespace} {
    namespace eval test_ns_simple { namespace current }
} {::test_ns_simple}
test namespace-old-1.6 {usage for "namespace eval"} {
    list [catch {namespace eval} msg] $msg
} {1 {wrong # args: should be "namespace eval name arg ?arg...?"}}
test namespace-old-1.7 {usage for "namespace eval"} {
    list [catch {namespace eval test_ns_xyzzy} msg] $msg
} {1 {wrong # args: should be "namespace eval name arg ?arg...?"}}
test namespace-old-1.8 {command "namespace eval" concatenates args} {
    namespace eval test_ns_simple namespace current
} {::test_ns_simple}
test namespace-old-1.9 {add elements to a namespace} {
    namespace eval test_ns_simple {
        variable test_ns_x 0
        proc test {test_ns_x} {
            return "test: $test_ns_x"
        }
	variable test_ns_x 0
	proc test {test_ns_x} {
	    return "test: $test_ns_x"
	}
    }
} {}
namespace eval test_ns_simple {
    variable test_ns_x 0
    proc test {test_ns_x} {
	return "test: $test_ns_x"
    }
}
test namespace-old-1.10 {commands in a namespace} {
    namespace eval test_ns_simple { info commands [namespace current]::*}
} {::test_ns_simple::test}
test namespace-old-1.11 {variables in a namespace} {
    namespace eval test_ns_simple { info vars [namespace current]::* }
} {::test_ns_simple::test_ns_x}
test namespace-old-1.12 {global vars are separate from locals vars} {
    list [test_ns_simple::test 123] [set test_ns_simple::test_ns_x]
} {{test: 123} 0}
test namespace-old-1.13 {add to an existing namespace} {
    namespace eval test_ns_simple {
        variable test_ns_y 123
        proc _backdoor {cmd} {
            eval $cmd
        }
	variable test_ns_y 123
	proc _backdoor {cmd} {
	    eval $cmd
	}
    }
} ""
namespace eval test_ns_simple {
    variable test_ns_y 123
    proc _backdoor {cmd} {
	eval $cmd
    }
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
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







-
+



-
+



-
-
-
+
+
+










-
+







    list [catch "::test_ns_simple::_backdoor {return yes!}" msg] $msg
} {0 yes!}
test namespace-old-1.20 {variables in a namespace are hidden} {
    list [catch "set test_ns_x" msg] $msg [catch "set test_ns_y" msg] $msg
} {1 {can't read "test_ns_x": no such variable} 1 {can't read "test_ns_y": no such variable}}
test namespace-old-1.21 {using namespace qualifiers} {
    list [catch "set test_ns_simple::test_ns_x" msg] $msg \
         [catch "set test_ns_simple::test_ns_y" msg] $msg
	 [catch "set test_ns_simple::test_ns_y" msg] $msg
} {0 0 0 123}
test namespace-old-1.22 {using absolute namespace qualifiers} {
    list [catch "set ::test_ns_simple::test_ns_x" msg] $msg \
         [catch "set ::test_ns_simple::test_ns_y" msg] $msg
	 [catch "set ::test_ns_simple::test_ns_y" msg] $msg
} {0 0 0 123}
test namespace-old-1.23 {variables can be accessed within a namespace} {
    test_ns_simple::_backdoor {
        variable test_ns_x
        variable test_ns_y
        return "$test_ns_x $test_ns_y"
	variable test_ns_x
	variable test_ns_y
	return "$test_ns_x $test_ns_y"
    }
} {0 123}
test namespace-old-1.24 {setting global variables} {
    test_ns_simple::_backdoor {variable test_ns_x;  set test_ns_x "new val"}
    namespace eval test_ns_simple {set test_ns_x}
} {new val}
test namespace-old-1.25 {qualified variables don't need a global declaration} {
    namespace eval test_ns_another { variable test_ns_x 456 }
    set cmd {set ::test_ns_another::test_ns_x}
    list [catch {test_ns_simple::_backdoor "$cmd some-value"} msg] $msg \
         [eval $cmd]
	 [eval $cmd]
} {0 some-value some-value}
test namespace-old-1.26 {namespace qualifiers are okay after $'s} {
    namespace eval test_ns_simple { set test_ns_x 12; set test_ns_y 34 }
    set cmd {list $::test_ns_simple::test_ns_x $::test_ns_simple::test_ns_y}
    list [test_ns_simple::_backdoor $cmd] [eval $cmd]
} {{12 34} {12 34}}
test namespace-old-1.27 {can create commands with null names} {
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
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







-
-
-
-
-
+
+
+
+
+






-
-
-
-
-
+
+
+
+
+







-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+







-
+










-
-
-
-
+
+
+
+











-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
-
+
+
+



-
-
+
+












-
+









-
-
-
+
+
+



-
+



-
+



-
+





-
+







# TEST: namespace qualifiers, namespace tail
# -----------------------------------------------------------------------
test namespace-old-3.1 {usage for "namespace qualifiers"} {
    list [catch "namespace qualifiers" msg] $msg
} {1 {wrong # args: should be "namespace qualifiers string"}}
test namespace-old-3.2 {querying:  namespace qualifiers} {
    list [namespace qualifiers ""] \
         [namespace qualifiers ::] \
         [namespace qualifiers x] \
         [namespace qualifiers ::x] \
         [namespace qualifiers foo::x] \
         [namespace qualifiers ::foo::bar::xyz]
	 [namespace qualifiers ::] \
	 [namespace qualifiers x] \
	 [namespace qualifiers ::x] \
	 [namespace qualifiers foo::x] \
	 [namespace qualifiers ::foo::bar::xyz]
} {{} {} {} {} foo ::foo::bar}
test namespace-old-3.3 {usage for "namespace tail"} {
    list [catch "namespace tail" msg] $msg
} {1 {wrong # args: should be "namespace tail string"}}
test namespace-old-3.4 {querying:  namespace tail} {
    list [namespace tail ""] \
         [namespace tail ::] \
         [namespace tail x] \
         [namespace tail ::x] \
         [namespace tail foo::x] \
         [namespace tail ::foo::bar::xyz]
	 [namespace tail ::] \
	 [namespace tail x] \
	 [namespace tail ::x] \
	 [namespace tail foo::x] \
	 [namespace tail ::foo::bar::xyz]
} {{} {} x x x xyz}

# -----------------------------------------------------------------------
# TEST: delete commands and namespaces
# -----------------------------------------------------------------------
test namespace-old-4.1 {define test namespaces} {
    namespace eval test_ns_delete {
        namespace eval ns1 {
            variable var1 1
            proc cmd1 {} {return "cmd1"}
        }
        namespace eval ns2 {
            variable var2 2
            proc cmd2 {} {return "cmd2"}
        }
        namespace eval another {}
        lsort [namespace children]
	namespace eval ns1 {
	    variable var1 1
	    proc cmd1 {} {return "cmd1"}
	}
	namespace eval ns2 {
	    variable var2 2
	    proc cmd2 {} {return "cmd2"}
	}
	namespace eval another {}
	lsort [namespace children]
    }
} {::test_ns_delete::another ::test_ns_delete::ns1 ::test_ns_delete::ns2}
test namespace-old-4.2 {it's okay to invoke "namespace delete" with no args} {
    list [catch {namespace delete} msg] $msg
} {0 {}}
test namespace-old-4.3 {command "namespace delete" doesn't support patterns} {
    set cmd {
        namespace eval test_ns_delete {namespace delete ns*}
	namespace eval test_ns_delete {namespace delete ns*}
    }
    list [catch $cmd msg] $msg
} {1 {unknown namespace "ns*" in namespace delete command}}
namespace eval test_ns_delete {
    namespace eval ns1 {}
    namespace eval ns2 {}
    namespace eval another {}
}
test namespace-old-4.4 {command "namespace delete" handles multiple args} {
    set cmd {
        namespace eval test_ns_delete {
            namespace delete \
                {*}[namespace children [namespace current] ns?]
        }
	namespace eval test_ns_delete {
	    namespace delete \
		{*}[namespace children [namespace current] ns?]
	}
    }
    list [catch $cmd msg] $msg [namespace children test_ns_delete]
} {0 {} ::test_ns_delete::another}

# -----------------------------------------------------------------------
# TEST: namespace hierarchy
# -----------------------------------------------------------------------
test namespace-old-5.1 {define nested namespaces} {
    set test_ns_var_global "var in ::"
    proc test_ns_cmd_global {} {return "cmd in ::"}
    namespace eval test_ns_hier1 {
        set test_ns_var_hier1 "particular to hier1"
        proc test_ns_cmd_hier1 {} {return "particular to hier1"}
        set test_ns_level 1
        proc test_ns_show {} {return "[namespace current]: 1"}
        namespace eval test_ns_hier2 {
            set test_ns_var_hier2 "particular to hier2"
            proc test_ns_cmd_hier2 {} {return "particular to hier2"}
            set test_ns_level 2
            proc test_ns_show {} {return "[namespace current]: 2"}
            namespace eval test_ns_hier3a {}
            namespace eval test_ns_hier3b {}
        }
        namespace eval test_ns_hier2a {}
        namespace eval test_ns_hier2b {}
	set test_ns_var_hier1 "particular to hier1"
	proc test_ns_cmd_hier1 {} {return "particular to hier1"}
	set test_ns_level 1
	proc test_ns_show {} {return "[namespace current]: 1"}
	namespace eval test_ns_hier2 {
	    set test_ns_var_hier2 "particular to hier2"
	    proc test_ns_cmd_hier2 {} {return "particular to hier2"}
	    set test_ns_level 2
	    proc test_ns_show {} {return "[namespace current]: 2"}
	    namespace eval test_ns_hier3a {}
	    namespace eval test_ns_hier3b {}
	}
	namespace eval test_ns_hier2a {}
	namespace eval test_ns_hier2b {}
    }
} {}
test namespace-old-5.2 {namespaces can be nested} {
    list [namespace eval test_ns_hier1 {namespace current}] \
         [namespace eval test_ns_hier1 {
              namespace eval test_ns_hier2 {namespace current}
          }]
	 [namespace eval test_ns_hier1 {
	      namespace eval test_ns_hier2 {namespace current}
	  }]
} {::test_ns_hier1 ::test_ns_hier1::test_ns_hier2}
test namespace-old-5.3 {namespace qualifiers work in namespace command} {
    list [namespace eval ::test_ns_hier1 {namespace current}] \
         [namespace eval test_ns_hier1::test_ns_hier2 {namespace current}] \
         [namespace eval ::test_ns_hier1::test_ns_hier2 {namespace current}]
	 [namespace eval test_ns_hier1::test_ns_hier2 {namespace current}] \
	 [namespace eval ::test_ns_hier1::test_ns_hier2 {namespace current}]
} {::test_ns_hier1 ::test_ns_hier1::test_ns_hier2 ::test_ns_hier1::test_ns_hier2}
set ::test_ns_var_global "var in ::"
proc test_ns_cmd_global {} {return "cmd in ::"}
namespace eval test_ns_hier1 {
    variable test_ns_var_hier1 "particular to hier1"
    proc test_ns_cmd_hier1 {} {return "particular to hier1"}
    variable test_ns_level 1
    proc test_ns_show {} {return "[namespace current]: 1"}
    namespace eval test_ns_hier2 {
	variable test_ns_var_hier2 "particular to hier2"
	proc test_ns_cmd_hier2 {} {return "particular to hier2"}
	variable test_ns_level 2
        proc test_ns_show {} {return "[namespace current]: 2"}
	proc test_ns_show {} {return "[namespace current]: 2"}
	namespace eval test_ns_hier3a {}
	namespace eval test_ns_hier3b {}
    }
    namespace eval test_ns_hier2a {}
    namespace eval test_ns_hier2b {}
}
# TIP 278: secondary lookup disabled for vars, tests disabled with #
test namespace-old-5.4 {nested namespaces can access global namespace} {
    list [namespace eval test_ns_hier1 {#set test_ns_var_global}] \
         [namespace eval test_ns_hier1 {test_ns_cmd_global}] \
         [namespace eval test_ns_hier1::test_ns_hier2 {#set test_ns_var_global}] \
         [namespace eval test_ns_hier1::test_ns_hier2 {test_ns_cmd_global}]
	 [namespace eval test_ns_hier1 {test_ns_cmd_global}] \
	 [namespace eval test_ns_hier1::test_ns_hier2 {#set test_ns_var_global}] \
	 [namespace eval test_ns_hier1::test_ns_hier2 {test_ns_cmd_global}]
} {{} {cmd in ::} {} {cmd in ::}}
test namespace-old-5.5 {variables in different namespaces don't conflict} {
    list [set test_ns_hier1::test_ns_level] \
         [set test_ns_hier1::test_ns_hier2::test_ns_level]
	 [set test_ns_hier1::test_ns_hier2::test_ns_level]
} {1 2}
test namespace-old-5.6 {commands in different namespaces don't conflict} {
    list [test_ns_hier1::test_ns_show] \
         [test_ns_hier1::test_ns_hier2::test_ns_show]
	 [test_ns_hier1::test_ns_hier2::test_ns_show]
} {{::test_ns_hier1: 1} {::test_ns_hier1::test_ns_hier2: 2}}
test namespace-old-5.7 {nested namespaces don't see variables in parent} {
    set cmd {
        namespace eval test_ns_hier1::test_ns_hier2 {set test_ns_var_hier1}
	namespace eval test_ns_hier1::test_ns_hier2 {set test_ns_var_hier1}
    }
    list [catch $cmd msg] $msg
} {1 {can't read "test_ns_var_hier1": no such variable}}
test namespace-old-5.8 {nested namespaces don't see commands in parent} {
    set cmd {
        namespace eval test_ns_hier1::test_ns_hier2 {test_ns_cmd_hier1}
	namespace eval test_ns_hier1::test_ns_hier2 {test_ns_cmd_hier1}
    }
    list [catch $cmd msg] $msg
} {1 {invalid command name "test_ns_cmd_hier1"}}
test namespace-old-5.9 {usage for "namespace children"} {
    list [catch {namespace children test_ns_hier1 y z} msg] $msg
} {1 {wrong # args: should be "namespace children ?name? ?pattern?"}}
test namespace-old-5.10 {command "namespace children" must get valid namespace} -body {
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
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
467
468

469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570

571
572
573
574
575
576
577
578
579
580

581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598









599
600
601
602
603
604
605
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
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
467

468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569

570
571
572
573
574
575
576
577
578
579

580
581
582
583
584
585
586
587
588
589









590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605







-
-
-
+
+
+



-
-
-
+
+
+












-
+




-
+




-
+





-
+






-
+





-
+








-
+








-
+








-
+








-
-
-
+
+
+


-
-
-
+
+
+


-
-
-
+
+
+











-
+












-
+







-
+








-
+









-
+










-
+


-
-
-
+
+
+







-
+











-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
















-
+









-
+









-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+







    list [catch {namespace parent x y} msg] $msg
} {1 {wrong # args: should be "namespace parent ?name?"}}
test namespace-old-5.19 {command "namespace parent" must get valid namespace} -body {
    namespace parent xyzzy
} -returnCodes error -result {namespace "xyzzy" not found in "::"}
test namespace-old-5.20 {querying namespace parent} {
    list [namespace eval :: {namespace parent}] \
        [namespace eval test_ns_hier1 {namespace parent}] \
        [namespace eval test_ns_hier1::test_ns_hier2 {namespace parent}] \
        [namespace eval test_ns_hier1::test_ns_hier2::test_ns_hier3a {namespace parent}] \
	[namespace eval test_ns_hier1 {namespace parent}] \
	[namespace eval test_ns_hier1::test_ns_hier2 {namespace parent}] \
	[namespace eval test_ns_hier1::test_ns_hier2::test_ns_hier3a {namespace parent}] \
} {{} :: ::test_ns_hier1 ::test_ns_hier1::test_ns_hier2}
test namespace-old-5.21 {querying namespace parent for explicit namespace} {
    list [namespace parent ::] \
         [namespace parent test_ns_hier1] \
         [namespace parent test_ns_hier1::test_ns_hier2] \
         [namespace parent test_ns_hier1::test_ns_hier2::test_ns_hier3a]
	 [namespace parent test_ns_hier1] \
	 [namespace parent test_ns_hier1::test_ns_hier2] \
	 [namespace parent test_ns_hier1::test_ns_hier2::test_ns_hier3a]
} {{} :: ::test_ns_hier1 ::test_ns_hier1::test_ns_hier2}

# -----------------------------------------------------------------------
# TEST: name resolution and caching
# -----------------------------------------------------------------------
set trigger {namespace eval test_ns_cache2 {namespace current}}
set trigger2 {namespace eval test_ns_cache2::test_ns_cache3 {namespace current}}
test namespace-old-6.1 {relative ns names only looked up in current ns} {
    namespace eval test_ns_cache1 {}
    namespace eval test_ns_cache2 {}
    namespace eval test_ns_cache2::test_ns_cache3 {}
    list [namespace eval test_ns_cache1 $trigger] \
         [namespace eval test_ns_cache1 $trigger2]
	 [namespace eval test_ns_cache1 $trigger2]
} {::test_ns_cache1::test_ns_cache2 ::test_ns_cache1::test_ns_cache2::test_ns_cache3}
test namespace-old-6.2 {relative ns names only looked up in current ns} {
    namespace eval test_ns_cache1::test_ns_cache2 {}
    list [namespace eval test_ns_cache1 $trigger] \
         [namespace eval test_ns_cache1 $trigger2]
	 [namespace eval test_ns_cache1 $trigger2]
} {::test_ns_cache1::test_ns_cache2 ::test_ns_cache1::test_ns_cache2::test_ns_cache3}
test namespace-old-6.3 {relative ns names only looked up in current ns} {
    namespace eval test_ns_cache1::test_ns_cache2::test_ns_cache3 {}
    list [namespace eval test_ns_cache1 $trigger] \
         [namespace eval test_ns_cache1 $trigger2]
	 [namespace eval test_ns_cache1 $trigger2]
} {::test_ns_cache1::test_ns_cache2 ::test_ns_cache1::test_ns_cache2::test_ns_cache3}
namespace eval test_ns_cache1::test_ns_cache2 {}
test namespace-old-6.4 {relative ns names only looked up in current ns} {
    namespace delete test_ns_cache1::test_ns_cache2
    list [namespace eval test_ns_cache1 $trigger] \
         [namespace eval test_ns_cache1 $trigger2]
	 [namespace eval test_ns_cache1 $trigger2]
} {::test_ns_cache1::test_ns_cache2 ::test_ns_cache1::test_ns_cache2::test_ns_cache3}
namespace eval test_ns_cache1 {
    proc trigger {} {test_ns_cache_cmd}
}
test namespace-old-6.5 {define test commands} {
    proc test_ns_cache_cmd {} {
        return "global version"
	return "global version"
    }
    test_ns_cache1::trigger
} {global version}
test namespace-old-6.6 {one-level check for command shadowing} {
    proc test_ns_cache1::test_ns_cache_cmd {} {
        return "cache1 version"
	return "cache1 version"
    }
    test_ns_cache1::trigger
} {cache1 version}
proc test_ns_cache_cmd {} {
    return "global version"
}
test namespace-old-6.7 {renaming commands changes command epoch} -setup {
    proc test_ns_cache1::test_ns_cache_cmd {} {
        return "cache1 version"
	return "cache1 version"
    }
} -body {
    list [test_ns_cache1::trigger] \
	[namespace eval test_ns_cache1 {rename test_ns_cache_cmd test_ns_new}]\
	[test_ns_cache1::trigger]
} -result {{cache1 version} {} {global version}}
test namespace-old-6.8 {renaming back handles shadowing} -setup {
    proc test_ns_cache1::test_ns_new {} {
        return "cache1 version"
	return "cache1 version"
    }
} -body {
    list [test_ns_cache1::trigger] \
	[namespace eval test_ns_cache1 {rename test_ns_new test_ns_cache_cmd}]\
	[test_ns_cache1::trigger]
} -result {{global version} {} {cache1 version}}
test namespace-old-6.9 {deleting commands changes command epoch} -setup {
    proc test_ns_cache1::test_ns_cache_cmd {} {
        return "cache1 version"
	return "cache1 version"
    }
} -body {
    list [test_ns_cache1::trigger] \
	[namespace eval test_ns_cache1 {rename test_ns_cache_cmd ""}] \
	[test_ns_cache1::trigger]
} -result {{cache1 version} {} {global version}}
test namespace-old-6.10 {define test namespaces} {
    namespace eval test_ns_cache2 {
        proc test_ns_cache_cmd {} {
            return "global cache2 version"
        }
	proc test_ns_cache_cmd {} {
	    return "global cache2 version"
	}
    }
    namespace eval test_ns_cache1 {
        proc trigger {} {
            test_ns_cache2::test_ns_cache_cmd
        }
	proc trigger {} {
	    test_ns_cache2::test_ns_cache_cmd
	}
    }
    namespace eval test_ns_cache1::test_ns_cache2 {
        proc trigger {} {
            test_ns_cache_cmd
        }
	proc trigger {} {
	    test_ns_cache_cmd
	}
    }
    list [test_ns_cache1::trigger] [test_ns_cache1::test_ns_cache2::trigger]
} {{global cache2 version} {global version}}
namespace eval test_ns_cache1 {
    proc trigger {} { test_ns_cache2::test_ns_cache_cmd }
    namespace eval test_ns_cache2 {
	proc trigger {} { test_ns_cache_cmd }
    }
}
test namespace-old-6.11 {commands affect all parent namespaces} {
    proc test_ns_cache1::test_ns_cache2::test_ns_cache_cmd {} {
        return "cache2 version"
	return "cache2 version"
    }
    list [test_ns_cache1::trigger] [test_ns_cache1::test_ns_cache2::trigger]
} {{cache2 version} {cache2 version}}
# TIP 278: secondary lookup disabled, catch added, result changed from {global version}
test namespace-old-6.12 {define test variables} {
    variable test_ns_cache_var "global version"
    set trigger {set test_ns_cache_var}
    list [catch {namespace eval test_ns_cache1 $trigger} msg] $msg
} {1 {can't read "test_ns_cache_var": no such variable}}
    set trigger {set test_ns_cache_var}
test namespace-old-6.13 {one-level check for variable shadowing} {
    namespace eval test_ns_cache1 {
        variable test_ns_cache_var "cache1 version"
	variable test_ns_cache_var "cache1 version"
    }
    namespace eval test_ns_cache1 $trigger
} {cache1 version}
variable ::test_ns_cache_var "global version"
# TIP 278: secondary lookup disabled, catch added, result changed from {global version}
test namespace-old-6.14 {deleting variables changes variable epoch} {
    namespace eval test_ns_cache1 {
        variable test_ns_cache_var "cache1 version"
	variable test_ns_cache_var "cache1 version"
    }
    list [namespace eval test_ns_cache1 $trigger] \
	[namespace eval test_ns_cache1 {unset test_ns_cache_var}] \
	[catch {namespace eval test_ns_cache1 $trigger}]
} {{cache1 version} {} 1}
# TIP 278: secondary lookup disabled, catch added, result changed
test namespace-old-6.15 {define test namespaces} {
    namespace eval test_ns_cache2 {
        variable test_ns_cache_var "global cache2 version"
	variable test_ns_cache_var "global cache2 version"
    }
    set trigger2 {set test_ns_cache2::test_ns_cache_var}
    catch {list [namespace eval test_ns_cache1 $trigger2] \
	       [namespace eval test_ns_cache1::test_ns_cache2 $trigger]}
} 1
set trigger2 {set test_ns_cache2::test_ns_cache_var}
test namespace-old-6.16 {public variables affect all parent namespaces} {
    variable test_ns_cache1::test_ns_cache2::test_ns_cache_var "cache2 version"
    list [namespace eval test_ns_cache1 $trigger2] \
         [namespace eval test_ns_cache1::test_ns_cache2 $trigger]
	 [namespace eval test_ns_cache1::test_ns_cache2 $trigger]
} {{cache2 version} {cache2 version}}
test namespace-old-6.17 {usage for "namespace which"} {
    list [catch "namespace which -baz x" msg] $msg
} {1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}}
test namespace-old-6.18 {usage for "namespace which"} {
    # Presume no imported command called -command ;^)
    namespace which -command
} {}
test namespace-old-6.19 {querying:  namespace which -command} {
    proc test_ns_cache1::test_ns_cache_cmd {} {
        return "cache1 version"
	return "cache1 version"
    }
    list [namespace eval :: {namespace which test_ns_cache_cmd}] \
         [namespace eval test_ns_cache1 {namespace which test_ns_cache_cmd}] \
         [namespace eval :: {namespace which -command test_ns_cache_cmd}] \
         [namespace eval test_ns_cache1 {namespace which -command test_ns_cache_cmd}]
	 [namespace eval test_ns_cache1 {namespace which test_ns_cache_cmd}] \
	 [namespace eval :: {namespace which -command test_ns_cache_cmd}] \
	 [namespace eval test_ns_cache1 {namespace which -command test_ns_cache_cmd}]
} {::test_ns_cache_cmd ::test_ns_cache1::test_ns_cache_cmd ::test_ns_cache_cmd ::test_ns_cache1::test_ns_cache_cmd}
test namespace-old-6.20 {command "namespace which" may not find commands} {
    namespace eval test_ns_cache1 {namespace which -command xyzzy}
} {}
variable test_ns_cache1::test_ns_cache2::test_ns_cache_var "cache2 version"
test namespace-old-6.21 {querying:  namespace which -variable} {
    namespace eval test_ns_cache1::test_ns_cache2 {
        namespace which -variable test_ns_cache_var
	namespace which -variable test_ns_cache_var
    }
} {::test_ns_cache1::test_ns_cache2::test_ns_cache_var}
test namespace-old-6.22 {command "namespace which" may not find variables} {
    namespace eval test_ns_cache1 {namespace which -variable xyzzy}
} {}

# -----------------------------------------------------------------------
# TEST: uplevel/upvar across namespace boundaries
# -----------------------------------------------------------------------
test namespace-old-7.1 {define test namespace} {
    namespace eval test_ns_uplevel {
        variable x 0
        variable y 1
        proc show_vars {num} {
            return [uplevel $num {info vars}]
        }
        proc test_uplevel {num} {
            set a 0
            set b 1
            namespace eval ::test_ns_uplevel " return \[show_vars $num\] "
        }
	variable x 0
	variable y 1
	proc show_vars {num} {
	    return [uplevel $num {info vars}]
	}
	proc test_uplevel {num} {
	    set a 0
	    set b 1
	    namespace eval ::test_ns_uplevel " return \[show_vars $num\] "
	}
    }
} {}
namespace eval test_ns_uplevel {
    variable x 0
    variable y 1
    proc show_vars {num} {
	return [uplevel $num {info vars}]
    }
    proc test_uplevel {num} {
	set a 0
	set b 1
	namespace eval ::test_ns_uplevel " return \[show_vars $num\] "
    }
}
test namespace-old-7.2 {uplevel can access namespace call frame} {
    list [expr {"x" in [test_ns_uplevel::test_uplevel 1]}] \
         [expr {"y" in [test_ns_uplevel::test_uplevel 1]}]
	 [expr {"y" in [test_ns_uplevel::test_uplevel 1]}]
} {1 1}
test namespace-old-7.3 {uplevel can go beyond namespace call frame} {
    lsort [test_ns_uplevel::test_uplevel 2]
} {a b num}
test namespace-old-7.4 {uplevel can go up to global context} {
    expr {[test_ns_uplevel::test_uplevel 3] == [info globals]}
} {1}
test namespace-old-7.5 {absolute call frame references work too} {
    list [expr {"x" in [test_ns_uplevel::test_uplevel #2]}] \
         [expr {"y" in [test_ns_uplevel::test_uplevel #2]}]
	 [expr {"y" in [test_ns_uplevel::test_uplevel #2]}]
} {1 1}
test namespace-old-7.6 {absolute call frame references work too} {
    lsort [test_ns_uplevel::test_uplevel #1]
} {a b num}
test namespace-old-7.7 {absolute call frame references work too} {
    expr {[test_ns_uplevel::test_uplevel #0] == [info globals]}
} {1}
test namespace-old-7.8 {namespaces are included in the call stack} {
    namespace eval test_ns_upvar {
        variable scope "test_ns_upvar"
        proc show_val {var num} {
            upvar $num $var x
            return $x
        }
        proc test_upvar {num} {
            set scope "test_ns_upvar::test_upvar"
            namespace eval ::test_ns_upvar " return \[show_val scope $num\] "
        }
	variable scope "test_ns_upvar"
	proc show_val {var num} {
	    upvar $num $var x
	    return $x
	}
	proc test_upvar {num} {
	    set scope "test_ns_upvar::test_upvar"
	    namespace eval ::test_ns_upvar " return \[show_val scope $num\] "
	}
    }
} {}
namespace eval test_ns_upvar {
    variable scope "test_ns_upvar"
    proc show_val {var num} {
	upvar $num $var x
	return $x
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638









639
640
641
642
643
644

645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663







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
623
624
625
626
627
628
629









630
631
632
633
634
635
636
637
638
639
640
641
642
643

644
645
646
647
648
649
650
651
652
653
654
655
656







657
658
659
660
661
662
663
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







-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+





-
+












-
-
-
-
-
-
-
+
+
+
+
+
+
+















-
-
+
+


-
+







} {test_ns_upvar::test_upvar}

# -----------------------------------------------------------------------
# TEST: variable traces across namespace boundaries
# -----------------------------------------------------------------------
test namespace-old-8.1 {traces work across namespace boundaries} {
    namespace eval test_ns_trace {
        namespace eval foo {
            variable x ""
        }
        variable status ""
        proc monitor {name1 name2 op} {
            variable status
            lappend status "$op: $name1"
        }
        trace variable foo::x rwu [namespace code monitor]
	namespace eval foo {
	    variable x ""
	}
	variable status ""
	proc monitor {name1 name2 op} {
	    variable status
	    lappend status "$op: $name1"
	}
	trace add variable foo::x {read write unset} [namespace code monitor]
    }
    set test_ns_trace::foo::x "yes!"
    set test_ns_trace::foo::x
    unset test_ns_trace::foo::x
    namespace eval test_ns_trace { set status }
} {{w: test_ns_trace::foo::x} {r: test_ns_trace::foo::x} {u: test_ns_trace::foo::x}}
} {{write: test_ns_trace::foo::x} {read: test_ns_trace::foo::x} {unset: test_ns_trace::foo::x}}

# -----------------------------------------------------------------------
# TEST: imported commands
# -----------------------------------------------------------------------
test namespace-old-9.1 {empty "namespace export" list} {
    list [catch "namespace export" msg] $msg
} {0 {}}
test namespace-old-9.2 {usage for "namespace export" command} {
    list [catch "namespace export test_ns_trace::zzz" msg] $msg
} {1 {invalid export pattern "test_ns_trace::zzz": pattern can't specify a namespace}}
test namespace-old-9.3 {define test namespaces for import} {
    namespace eval test_ns_export {
        namespace export cmd1 cmd2 cmd3
        proc cmd1 {args} {return "cmd1: $args"}
        proc cmd2 {args} {return "cmd2: $args"}
        proc cmd3 {args} {return "cmd3: $args"}
        proc cmd4 {args} {return "cmd4: $args"}
        proc cmd5 {args} {return "cmd5: $args"}
        proc cmd6 {args} {return "cmd6: $args"}
	namespace export cmd1 cmd2 cmd3
	proc cmd1 {args} {return "cmd1: $args"}
	proc cmd2 {args} {return "cmd2: $args"}
	proc cmd3 {args} {return "cmd3: $args"}
	proc cmd4 {args} {return "cmd4: $args"}
	proc cmd5 {args} {return "cmd5: $args"}
	proc cmd6 {args} {return "cmd6: $args"}
    }
    lsort [info commands test_ns_export::*]
} {::test_ns_export::cmd1 ::test_ns_export::cmd2 ::test_ns_export::cmd3 ::test_ns_export::cmd4 ::test_ns_export::cmd5 ::test_ns_export::cmd6}
namespace eval test_ns_export {
    namespace export cmd1 cmd2 cmd3
    proc cmd1 {args} {return "cmd1: $args"}
    proc cmd2 {args} {return "cmd2: $args"}
    proc cmd3 {args} {return "cmd3: $args"}
    proc cmd4 {args} {return "cmd4: $args"}
    proc cmd5 {args} {return "cmd5: $args"}
    proc cmd6 {args} {return "cmd6: $args"}
}
test namespace-old-9.4 {check export status} {
    set x ""
    namespace eval test_ns_import {
        namespace export cmd1 cmd2
        namespace import ::test_ns_export::*
	namespace export cmd1 cmd2
	namespace import ::test_ns_export::*
    }
    foreach cmd [lsort [info commands test_ns_import::*]] {
        lappend x $cmd
	lappend x $cmd
    }
    set x
} {::test_ns_import::cmd1 ::test_ns_import::cmd2 ::test_ns_import::cmd3}
namespace eval test_ns_import {
    namespace export cmd1 cmd2
    namespace import ::test_ns_export::*
}
713
714
715
716
717
718
719
720
721
722
723
724





725
726
727
728
729
730
731
713
714
715
716
717
718
719





720
721
722
723
724
725
726
727
728
729
730
731







-
-
-
-
-
+
+
+
+
+







} {cmd1 cmd2}
namespace import test_ns_import::cmd*
test namespace-old-9.9 {imported commands work just the same as original} {
    list [cmd1 test 1 2 3] [test_ns_import::cmd1 test 4 5 6]
} {{cmd1: test 1 2 3} {cmd1: test 4 5 6}}
test namespace-old-9.10 {commands can be imported from many namespaces} {
    namespace eval test_ns_import2 {
        namespace export ncmd ncmd1 ncmd2
        proc ncmd  {args} {return "ncmd: $args"}
        proc ncmd1 {args} {return "ncmd1: $args"}
        proc ncmd2 {args} {return "ncmd2: $args"}
        proc ncmd3 {args} {return "ncmd3: $args"}
	namespace export ncmd ncmd1 ncmd2
	proc ncmd  {args} {return "ncmd: $args"}
	proc ncmd1 {args} {return "ncmd1: $args"}
	proc ncmd2 {args} {return "ncmd2: $args"}
	proc ncmd3 {args} {return "ncmd3: $args"}
    }
    namespace import test_ns_import2::*
    lsort [concat [info commands cmd*] [info commands ncmd*]]
} {cmd1 cmd2 ncmd ncmd1 ncmd2}
namespace eval test_ns_import2 {
    namespace export ncmd ncmd1 ncmd2
    proc ncmd  {args} {return "ncmd: $args"}
740
741
742
743
744
745
746
747

748
749
750
751
752

753
754
755
756

757
758
759

760
761
762

763
764
765


766
767
768
769
770
771



772
773
774
775
776
777

778
779
780
781
782
783
784



785
786
787
788
789
790
791
792
793
794
795
796
797
798
799








800
801
802
803
804
805
806
807
808
809
810

811
812
813
814
815
816
817
740
741
742
743
744
745
746

747
748
749
750
751

752
753
754
755

756
757
758

759
760
761

762
763


764
765
766
767
768



769
770
771
772
773
774
775
776

777
778
779
780
781



782
783
784
785
786
787
788
789
790
791








792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809

810
811
812
813
814
815
816
817







-
+




-
+



-
+


-
+


-
+

-
-
+
+



-
-
-
+
+
+





-
+




-
-
-
+
+
+







-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+










-
+







} {cmd2 ncmd ncmd1 ncmd2}
catch { rename cmd1 "" }
test namespace-old-9.12 {command "namespace forget" checks for valid namespaces} {
    list [catch {namespace forget xyzzy::*} msg] $msg
} {1 {unknown namespace in namespace forget pattern "xyzzy::*"}}
test namespace-old-9.13 {command "namespace forget" ignores patterns that don't match} {
    list [catch {namespace forget test_ns_import::xy*zzy} msg] $msg \
         [lsort [info commands cmd?]]
	 [lsort [info commands cmd?]]
} {0 {} cmd2}
test namespace-old-9.14 {imported commands can be removed} {
    namespace forget test_ns_import::cmd?
    list [lsort [info commands cmd?]] \
         [catch {cmd1 another test} msg] $msg
	 [catch {cmd1 another test} msg] $msg
} {{} 1 {invalid command name "cmd1"}}
test namespace-old-9.15 {existing commands can't be overwritten} {
    proc cmd1 {x y} {
        return [expr $x+$y]
	return [expr {$x+$y}]
    }
    list [catch {namespace import test_ns_import::cmd?} msg] $msg \
         [cmd1 3 5]
	 [cmd1 3 5]
} {1 {can't import command "cmd1": already exists} 8}
test namespace-old-9.16 {use "-force" option to override existing commands} {
    proc cmd1 {x y} { return [expr $x+$y] }
    proc cmd1 {x y} { return [expr {$x+$y}] }
    list [cmd1 3 5] \
         [namespace import -force test_ns_import::cmd?] \
         [cmd1 3 5]
	 [namespace import -force test_ns_import::cmd?] \
	 [cmd1 3 5]
} {8 {} {cmd1: 3 5}}
test namespace-old-9.17 {commands can be imported into many namespaces} {
    namespace eval test_ns_import_use {
        namespace import ::test_ns_import::* ::test_ns_import2::ncmd?
        lsort [concat [info commands ::test_ns_import_use::cmd*] \
                      [info commands ::test_ns_import_use::ncmd*]]
	namespace import ::test_ns_import::* ::test_ns_import2::ncmd?
	lsort [concat [info commands ::test_ns_import_use::cmd*] \
		      [info commands ::test_ns_import_use::ncmd*]]
    }
} {::test_ns_import_use::cmd1 ::test_ns_import_use::cmd2 ::test_ns_import_use::ncmd1 ::test_ns_import_use::ncmd2}
test namespace-old-9.18 {when command is deleted, imported commands go away} {
    namespace eval test_ns_import { rename cmd1 "" }
    list [info commands cmd1] \
         [namespace eval test_ns_import_use {info commands cmd1}]
	 [namespace eval test_ns_import_use {info commands cmd1}]
} {{} {}}
test namespace-old-9.19 {when namesp is deleted, all imported commands go away} {
    namespace delete test_ns_import test_ns_import2
    list [info commands cmd*] \
         [info commands ncmd*] \
         [namespace eval test_ns_import_use {info commands cmd*}] \
         [namespace eval test_ns_import_use {info commands ncmd*}] \
	 [info commands ncmd*] \
	 [namespace eval test_ns_import_use {info commands cmd*}] \
	 [namespace eval test_ns_import_use {info commands ncmd*}] \
} {{} {} {} {}}

# -----------------------------------------------------------------------
# TEST: scoped values
# -----------------------------------------------------------------------
test namespace-old-10.1 {define namespace for scope test} {
    namespace eval test_ns_inscope {
        variable x "x-value"
        proc show {args} {
            return "show: $args"
        }
        proc do {args} {
            return [eval $args]
        }
        list [set x] [show test]
	variable x "x-value"
	proc show {args} {
	    return "show: $args"
	}
	proc do {args} {
	    return [eval $args]
	}
	list [set x] [show test]
    }
} {x-value {show: test}}
test namespace-old-10.2 {command "namespace code" requires one argument} {
    list [catch {namespace code} msg] $msg
} {1 {wrong # args: should be "namespace code arg"}}
test namespace-old-10.3 {command "namespace code" requires one argument} {
    list [catch {namespace code first "second arg" third} msg] $msg
} {1 {wrong # args: should be "namespace code arg"}}
test namespace-old-10.4 {command "namespace code" gets current namesp context} {
    namespace eval test_ns_inscope {
        namespace code {"1 2 3" "4 5" 6}
	namespace code {"1 2 3" "4 5" 6}
    }
} {::namespace inscope ::test_ns_inscope {"1 2 3" "4 5" 6}}
test namespace-old-10.5 {with one arg, first "scope" sticks} {
    set sval [namespace eval test_ns_inscope {namespace code {one two}}]
    namespace code $sval
} {::namespace inscope ::test_ns_inscope {one two}}
test namespace-old-10.6 {with many args, each "scope" adds new args} {
828
829
830
831
832
833
834
835

836
837
838
839
840
841
842
828
829
830
831
832
833
834

835
836
837
838
839
840
841
842







-
+







    list [eval $cref "a" "b c" "d e f"]
} {{show: a b c d e f}}
namespace eval test_ns_inscope {
    variable x "x-value"
}
test namespace-old-10.8 {scoped commands execute in namespace context} {
    set cref [namespace eval test_ns_inscope {
        namespace code {set x "some new value"}
	namespace code {set x "some new value"}
    }]
    list [set test_ns_inscope::x] [eval $cref] [set test_ns_inscope::x]
} {x-value {some new value} {some new value}}

foreach cmd [info commands test_ns_*] {
    rename $cmd ""
}

Changes to tests/namespace.test.

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
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








-
-
+
+











-
+







# Functionality covered: this file contains a collection of tests for the
# procedures in tclNamesp.c and tclEnsemble.c that implement Tcl's basic
# support for namespaces.  Other namespace-related tests appear in
# variable.test.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-2000 Scriptics Corporation.
#
# 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::*
}
testConstraint memory [llength [info commands memory]]

::tcltest::loadTestedCommands
catch [list package require -exact Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

#
# REMARK: the tests for 'namespace upvar' are not done here. They are to be
# found in the file 'upvar.test'.
#

# Clear out any namespaces called test_ns_*
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
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







-
+





-
-
-
-
+
+
+
+












-
-
-
-
-
+
+
+
+
+






-
-
-
+
+
+










-
+







-
+



-
+

-
-
+
+



-
+







-
-
+
+





-
+










-
-
-
-
+
+
+
+





-
-
-
+
+
+






-
+







-
+







-
+







-
+






-
-
+
+







test namespace-1.1 {TclInitNamespaces, GetNamespaceFromObj, NamespaceChildrenCmd} {
    namespace children :: test_ns_*
} {}

catch {unset l}
test namespace-2.1 {Tcl_GetCurrentNamespace} {
    list [namespace current] [namespace eval {} {namespace current}] \
        [namespace eval {} {namespace current}]
	[namespace eval {} {namespace current}]
} {:: :: ::}
test namespace-2.2 {Tcl_GetCurrentNamespace} {
    set l {}
    lappend l [namespace current]
    namespace eval test_ns_1 {
        lappend ::l [namespace current]
        namespace eval foo {
            lappend ::l [namespace current]
        }
	lappend ::l [namespace current]
	namespace eval foo {
	    lappend ::l [namespace current]
	}
    }
    lappend l [namespace current]
} {:: ::test_ns_1 ::test_ns_1::foo ::}

test namespace-3.1 {Tcl_GetGlobalNamespace} {
    namespace eval test_ns_1 {namespace eval foo {namespace eval bar {} } }
    # namespace children uses Tcl_GetGlobalNamespace
    namespace eval test_ns_1 {namespace children foo b*}
} {::test_ns_1::foo::bar}

test namespace-4.1 {Tcl_PushCallFrame with isProcCallFrame=1} {
    namespace eval test_ns_1 {
        variable v 123
        proc p {} {
            variable v
            return $v
        }
	variable v 123
	proc p {} {
	    variable v
	    return $v
	}
    }
    test_ns_1::p    ;# does Tcl_PushCallFrame to push p's namespace
} {123}
test namespace-4.2 {Tcl_PushCallFrame with isProcCallFrame=0} {
    namespace eval test_ns_1::baz {}  ;# does Tcl_PushCallFrame to create baz
    proc test_ns_1::baz::p {} {
        variable v
        set v 789
        set v}
	variable v
	set v 789
	set v}
    test_ns_1::baz::p
} {789}

test namespace-5.1 {Tcl_PopCallFrame, no vars} {
    namespace eval test_ns_1::blodge {}  ;# pushes then pops frame
} {}
test namespace-5.2 {Tcl_PopCallFrame, local vars must be deleted} -setup {
    namespace eval test_ns_1 {}
} -body {
    proc test_ns_1::r {} {
        set a 123
	set a 123
    }
    test_ns_1::r   ;# pushes then pop's r's frame
} -result {123}

test namespace-6.1 {Tcl_CreateNamespace} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    list [lsort [namespace children :: test_ns_*]] \
        [namespace eval test_ns_1 {namespace current}] \
	[namespace eval test_ns_1 {namespace current}] \
	[namespace eval test_ns_2 {namespace current}] \
	[namespace eval ::test_ns_3 {namespace current}] \
	[namespace eval ::test_ns_4 \
            {namespace eval foo {namespace current}}] \
	    {namespace eval foo {namespace current}}] \
	[namespace eval ::test_ns_5 \
            {namespace eval ::test_ns_6 {namespace current}}] \
        [lsort [namespace children :: test_ns_*]]
	    {namespace eval ::test_ns_6 {namespace current}}] \
	[lsort [namespace children :: test_ns_*]]
} {{} ::test_ns_1 ::test_ns_2 ::test_ns_3 ::test_ns_4::foo ::test_ns_6 {::test_ns_1 ::test_ns_2 ::test_ns_3 ::test_ns_4 ::test_ns_5 ::test_ns_6}}
test namespace-6.2 {Tcl_CreateNamespace, odd number of :'s in name is okay} {
    list [namespace eval :::test_ns_1::::foo {namespace current}] \
         [namespace eval test_ns_2:::::foo {namespace current}]
	 [namespace eval test_ns_2:::::foo {namespace current}]
} {::test_ns_1::foo ::test_ns_2::foo}
test namespace-6.3 {Tcl_CreateNamespace, trailing ::s in ns name are ignored} {
    list [catch {namespace eval test_ns_7::: {namespace current}} msg] $msg
} {0 ::test_ns_7}
test namespace-6.4 {Tcl_CreateNamespace, trailing ::s in ns name are ignored} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_1:: {
        namespace eval test_ns_2:: {}
        namespace eval test_ns_3:: {}
	namespace eval test_ns_2:: {}
	namespace eval test_ns_3:: {}
    }
    lsort [namespace children ::test_ns_1]
} [lsort {::test_ns_1::test_ns_2 ::test_ns_1::test_ns_3}]
test namespace-6.5 {Tcl_CreateNamespace, relative ns names now only looked up in current ns} {
    set trigger {
        namespace eval test_ns_2 {namespace current}
	namespace eval test_ns_2 {namespace current}
    }
    set l {}
    lappend l [namespace eval test_ns_1 $trigger]
    namespace eval test_ns_1::test_ns_2 {}
    lappend l [namespace eval test_ns_1 $trigger]
} {::test_ns_1::test_ns_2 ::test_ns_1::test_ns_2}

test namespace-7.1 {Tcl_DeleteNamespace, active call frames in ns} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_1 {
        proc p {} {
            namespace delete [namespace current]
            return [namespace current]
        }
	proc p {} {
	    namespace delete [namespace current]
	    return [namespace current]
	}
    }
    list [test_ns_1::p] [catch {test_ns_1::p} msg] $msg
} {::test_ns_1 1 {invalid command name "test_ns_1::p"}}
test namespace-7.2 {Tcl_DeleteNamespace, no active call frames in ns} {
    namespace eval test_ns_2 {
        proc p {} {
            return [namespace current]
        }
	proc p {} {
	    return [namespace current]
	}
    }
    list [test_ns_2::p] [namespace delete test_ns_2]
} {::test_ns_2 {}}
test namespace-7.3 {recursive Tcl_DeleteNamespace, active call frames in ns} {
    # [Bug 1355942]
    namespace eval test_ns_2 {
        set x 1
	set x 1
	trace add variable x unset "namespace delete [namespace current];#"
	namespace delete [namespace current]
    }
} {}
test namespace-7.4 {recursive Tcl_DeleteNamespace, active call frames in ns} {
    # [Bug 1355942]
    namespace eval test_ns_2 {
        proc x {} {}
	proc x {} {}
	trace add command x delete "namespace delete [namespace current];#"
	namespace delete [namespace current]
    }
} {}
test namespace-7.5 {recursive Tcl_DeleteNamespace, no active call frames in ns} {
    # [Bug 1355942]
    namespace eval test_ns_2 {
        set x 1
	set x 1
	trace add variable x unset "namespace delete [namespace current];#"
    }
    namespace delete test_ns_2
} {}
test namespace-7.6 {recursive Tcl_DeleteNamespace, no active call frames in ns} {
    # [Bug 1355942]
    namespace eval test_ns_2 {
        proc x {} {}
	proc x {} {}
	trace add command x delete "namespace delete [namespace current];#"
    }
    namespace delete test_ns_2
} {}
test namespace-7.7 {Bug 1655305} -setup {
    interp create child
    # Can't invoke through the ensemble, since deleting the global namespace
    # (indirectly, via deleting ::tcl) deletes the ensemble.
    # Can't invoke through the ensemble, since deleting ::tcl
    # (indirectly, via deleting the global namespace) deletes the ensemble.
    child eval {rename ::tcl::info::commands ::infocommands}
    child hide infocommands
    child eval {
	proc foo {} {
	    namespace delete ::
	}
    }
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
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







-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
+
+
+






-
-
+
+






-
-
-
-
+
+
+
+




-
-
-
+
+
+


-
-
+
+


-
-
+
+







	namespace ensemble create
    }

    trace add command ns1 delete {
	namespace delete ns1
    }
} -body {
    # No segmentation fault given --enable-symbols=mem.
    # No segmentation fault given --enable-symbols.
    namespace delete ns1
} -result {}


test namespace-7.9 {
	Bug e39cb3f462631a99

	A namespace being deleted should not be removed from other namespace paths
	until the contents of the namespace are entirely removed.
} -setup {




} -body {

	variable res {}


	namespace eval ns1 {
		proc p1 caller {
			lappend [namespace parent]::res $caller
		}
	}


	namespace eval ns1a {
		namespace path [namespace parent]::ns1

		proc t1 {old new op} {
			$old t1
		}
	}

	namespace eval ns2 {
		proc p1 caller {
			lappend [namespace parent]::res $caller
		}
	}

	namespace eval ns2a {
		namespace path [namespace parent]::ns2

		proc t1 {old new op} {
			[namespace tail $old] t2
		}
	}


	trace add command ns1::p1 delete ns1a::t1
	namespace delete ns1

	trace add command ns2::p1 delete ns2a::t1
	namespace delete ns2

	return $res

} -cleanup {
	namespace delete ns1a
	namespace delete ns2a
	unset res
} -result {t1 t2}



test namespace-8.1 {TclTeardownNamespace, delete global namespace} {
    catch {interp delete test_interp}
    interp create test_interp
    interp eval test_interp {
        namespace eval test_ns_1 {
            namespace export p
            proc p {} {
                return [namespace current]
            }
        }
        namespace eval test_ns_2 {
            namespace import ::test_ns_1::p
            variable v 27
            proc q {} {
                variable v
                return "[p] $v"
            }
        }
        set x [test_ns_2::q]
        catch {set xxxx}
	namespace eval test_ns_1 {
	    namespace export p
	    proc p {} {
		return [namespace current]
	    }
	}
	namespace eval test_ns_2 {
	    namespace import ::test_ns_1::p
	    variable v 27
	    proc q {} {
		variable v
		return "[p] $v"
	    }
	}
	set x [test_ns_2::q]
	catch {set xxxx}
    }
    list [interp eval test_interp {test_ns_2::q}] \
         [interp eval test_interp {namespace delete ::}] \
         [catch {interp eval test_interp {set a 123}} msg] $msg \
         [interp delete test_interp]
	 [interp eval test_interp {namespace delete ::}] \
	 [catch {interp eval test_interp {set a 123}} msg] $msg \
	 [interp delete test_interp]
} {{::test_ns_1 27} {} 1 {invalid command name "set"} {}}
test namespace-8.2 {TclTeardownNamespace, remove deleted ns from parent} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_1::test_ns_2::test_ns_3a {proc p {} {}}
    namespace eval test_ns_1::test_ns_2::test_ns_3b {proc q {} {}}
    list [namespace children test_ns_1] \
         [namespace delete test_ns_1::test_ns_2] \
         [namespace children test_ns_1]
	 [namespace delete test_ns_1::test_ns_2] \
	 [namespace children test_ns_1]
} {::test_ns_1::test_ns_2 {} {}}
test namespace-8.3 {TclTeardownNamespace, delete child namespaces} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_1::test_ns_2::test_ns_3a {proc p {} {}}
    namespace eval test_ns_1::test_ns_2::test_ns_3b {proc q {} {}}
    list [namespace children test_ns_1] \
         [namespace delete test_ns_1::test_ns_2] \
         [namespace children test_ns_1] \
         [catch {namespace children test_ns_1::test_ns_2} msg] $msg \
         [info commands test_ns_1::test_ns_2::test_ns_3a::*]
	 [namespace delete test_ns_1::test_ns_2] \
	 [namespace children test_ns_1] \
	 [catch {namespace children test_ns_1::test_ns_2} msg] $msg \
	 [info commands test_ns_1::test_ns_2::test_ns_3a::*]
} {::test_ns_1::test_ns_2 {} {} 1 {namespace "test_ns_1::test_ns_2" not found in "::"} {}}
test namespace-8.4 {TclTeardownNamespace, cmds imported from deleted ns go away} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_export {
        namespace export cmd1 cmd2
        proc cmd1 {args} {return "cmd1: $args"}
        proc cmd2 {args} {return "cmd2: $args"}
	namespace export cmd1 cmd2
	proc cmd1 {args} {return "cmd1: $args"}
	proc cmd2 {args} {return "cmd2: $args"}
    }
    namespace eval test_ns_import {
        namespace import ::test_ns_export::*
        proc p {} {return foo}
	namespace import ::test_ns_export::*
	proc p {} {return foo}
    }
    list [lsort [info commands test_ns_import::*]] \
         [namespace delete test_ns_export] \
         [info commands test_ns_import::*]
	 [namespace delete test_ns_export] \
	 [info commands test_ns_import::*]
} [list [lsort {::test_ns_import::p ::test_ns_import::cmd1 ::test_ns_import::cmd2}] {} ::test_ns_import::p]
test namespace-8.5 {TclTeardownNamespace: preserve errorInfo; errorCode values} {
    interp create child
    child eval {trace add execution error leave {namespace delete :: ;#}}
    catch {child eval error foo bar baz}
    interp delete child
    set ::errorInfo
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
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







-
-
-
+
+
+


-
-
+
+












-
+




-
-
+
+





-
-
+
+


-
+


-
-
-
-
-
-
+
+
+
+
+
+







} {1 {unknown namespace in import pattern "fred::x"}}
test namespace-9.3 {Tcl_Import, import ns == export ns} {
    list [catch {namespace eval test_ns_import {namespace import ::test_ns_import::puts}} msg] $msg
} {1 {import pattern "::test_ns_import::puts" tries to import from namespace "test_ns_import" into itself}}
test namespace-9.4 {Tcl_Import, simple import} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_export {
        namespace export cmd1
        proc cmd1 {args} {return "cmd1: $args"}
        proc cmd2 {args} {return "cmd2: $args"}
	namespace export cmd1
	proc cmd1 {args} {return "cmd1: $args"}
	proc cmd2 {args} {return "cmd2: $args"}
    }
    namespace eval test_ns_import {
        namespace import ::test_ns_export::*
        proc p {} {return [cmd1 123]}
	namespace import ::test_ns_export::*
	proc p {} {return [cmd1 123]}
    }
    test_ns_import::p
} {cmd1: 123}
test namespace-9.5 {Tcl_Import, RFE 1230597} -setup {
    namespace eval test_ns_import {}
    namespace eval test_ns_export {}
} -body {
    list [catch {namespace eval test_ns_import {namespace import ::test_ns_export::*}} msg] $msg
} -result {0 {}}
test namespace-9.6 {Tcl_Import, cmd redefinition ok if allowOverwrite!=0} -setup {
    namespace eval test_ns_import {}
    namespace eval ::test_ns_export {
        proc cmd1 {args} {return "cmd1: $args"}
	proc cmd1 {args} {return "cmd1: $args"}
	namespace export cmd1
    }
} -body {
    namespace eval test_ns_import {
        namespace import -force ::test_ns_export::*
        cmd1 555
	namespace import -force ::test_ns_export::*
	cmd1 555
    }
} -result {cmd1: 555}
test namespace-9.7 {Tcl_Import, links are preserved if cmd is redefined} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_export {
        namespace export cmd1
        proc cmd1 {args} {return "cmd1: $args"}
	namespace export cmd1
	proc cmd1 {args} {return "cmd1: $args"}
    }
    namespace eval test_ns_import {
        namespace import -force ::test_ns_export::*
	namespace import -force ::test_ns_export::*
    }
    list [test_ns_import::cmd1 a b c] \
         [test_ns_export::cmd1 d e f] \
         [proc test_ns_export::cmd1 {args} {return "new1: $args"}] \
         [namespace origin test_ns_import::cmd1] \
         [namespace origin test_ns_export::cmd1] \
         [test_ns_import::cmd1 g h i] \
         [test_ns_export::cmd1 j k l]
	 [test_ns_export::cmd1 d e f] \
	 [proc test_ns_export::cmd1 {args} {return "new1: $args"}] \
	 [namespace origin test_ns_import::cmd1] \
	 [namespace origin test_ns_export::cmd1] \
	 [test_ns_import::cmd1 g h i] \
	 [test_ns_export::cmd1 j k l]
} {{cmd1: a b c} {cmd1: d e f} {} ::test_ns_export::cmd1 ::test_ns_export::cmd1 {new1: g h i} {new1: j k l}}
test namespace-9.8 {Tcl_Import: Bug 1017299} -setup {
    namespace eval one {
	namespace export cmd
	proc cmd {} {}
    }
    namespace eval two {
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
461
462
463
464
465
466
467



468
469
470
471
472

473
474
475
476
477



478
479
480
481
482
483







484
485
486
487
488
489
490
491
492
493
494
495
496
497







-
-
-
+
+
+


-
+




-
-
-
+
+
+



-
-
-
-
-
-
-
+
+
+
+
+
+
+








test namespace-10.1 {Tcl_ForgetImport, check for valid namespaces} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    list [catch {namespace forget xyzzy::*} msg] $msg
} {1 {unknown namespace in namespace forget pattern "xyzzy::*"}}
test namespace-10.2 {Tcl_ForgetImport, ignores patterns that don't match} {
    namespace eval test_ns_export {
        namespace export cmd1
        proc cmd1 {args} {return "cmd1: $args"}
        proc cmd2 {args} {return "cmd2: $args"}
	namespace export cmd1
	proc cmd1 {args} {return "cmd1: $args"}
	proc cmd2 {args} {return "cmd2: $args"}
    }
    namespace eval test_ns_import {
        namespace forget ::test_ns_export::wombat
	namespace forget ::test_ns_export::wombat
    }
} {}
test namespace-10.3 {Tcl_ForgetImport, deletes matching imported cmds} -setup {
    namespace eval test_ns_export {
        namespace export cmd1
        proc cmd1 {args} {return "cmd1: $args"}
        proc cmd2 {args} {return "cmd2: $args"}
	namespace export cmd1
	proc cmd1 {args} {return "cmd1: $args"}
	proc cmd2 {args} {return "cmd2: $args"}
    }
} -body {
    namespace eval test_ns_import {
        namespace import ::test_ns_export::*
        proc p {} {return [cmd1 123]}
        set l {}
        lappend l [lsort [info commands ::test_ns_import::*]]
        namespace forget ::test_ns_export::cmd1
        lappend l [info commands ::test_ns_import::*]
        lappend l [catch {cmd1 777} msg] $msg
	namespace import ::test_ns_export::*
	proc p {} {return [cmd1 123]}
	set l {}
	lappend l [lsort [info commands ::test_ns_import::*]]
	namespace forget ::test_ns_export::cmd1
	lappend l [info commands ::test_ns_import::*]
	lappend l [catch {cmd1 777} msg] $msg
    }
} -result [list [lsort {::test_ns_import::p ::test_ns_import::cmd1}] ::test_ns_import::p 1 {invalid command name "cmd1"}]
test namespace-10.4 {Tcl_ForgetImport: Bug 560297} -setup {
    namespace eval origin {
	namespace export cmd
	proc cmd {} {}
    }
537
538
539
540
541
542
543
544
545


546
547
548
549
550
551
552
553


554
555
556
557
558
559



560
561
562
563
564
565
566
567


568
569
570
571
572



573
574
575
576
577


578
579
580
581
582
583
584
585
586


587
588
589

590
591
592
593
594
595
596
597
598


599
600
601

602
603
604
605
606
607
608




609
610
611
612
613
614
615
616

617
618
619
620
621
622
623
624
625

626
627
628

629
630
631
632

633
634
635
636
637
638
639
640

641
642
643

644
645
646
647
648


649
650
651
652
653
654
655
656
657

658
659
660

661
662
663
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
599
600
601
602
603
604
605


606
607
608
609
610
611
612
613


614
615
616
617
618



619
620
621
622
623
624
625
626
627


628
629
630
631



632
633
634
635
636
637


638
639
640
641
642
643
644
645
646


647
648
649
650

651
652
653
654
655
656
657
658


659
660
661
662

663
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
707
708


709
710
711
712
713
714
715
716
717
718

719
720
721

722
723
724
725


726
727
728
729
730
731
732

733
734
735


736
737
738
739
740
741

742
743
744

745
746
747
748
749

750
751
752


753
754
755
756
757
758
759
760
761







-
-
+
+






-
-
+
+



-
-
-
+
+
+






-
-
+
+


-
-
-
+
+
+



-
-
+
+







-
-
+
+


-
+







-
-
+
+


-
+



-
-
-
-
+
+
+
+







-
+








-
+


-
+



-
+







-
+


-
+



-
-
+
+








-
+


-
+



-
-
+
+





-
+


-
-
+
+




-
+


-
+




-
+


-
-
+
+







    namespace delete origin link link2 my
} -returnCodes error -match glob -result *

test namespace-11.1 {TclGetOriginalCommand, check if not imported cmd} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
    namespace eval test_ns_export {
        namespace export cmd1
        proc cmd1 {args} {return "cmd1: $args"}
	namespace export cmd1
	proc cmd1 {args} {return "cmd1: $args"}
    }
    list [namespace origin set] [namespace origin test_ns_export::cmd1]
} -result {::set ::test_ns_export::cmd1}
test namespace-11.2 {TclGetOriginalCommand, directly imported cmd} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_export {
        namespace export cmd1
        proc cmd1 {args} {return "cmd1: $args"}
	namespace export cmd1
	proc cmd1 {args} {return "cmd1: $args"}
    }
} -body {
    namespace eval test_ns_import1 {
        namespace import ::test_ns_export::*
        namespace export *
        proc p {} {namespace origin cmd1}
	namespace import ::test_ns_export::*
	namespace export *
	proc p {} {namespace origin cmd1}
    }
    list [test_ns_import1::p] [namespace origin test_ns_import1::cmd1]
} -result {::test_ns_export::cmd1 ::test_ns_export::cmd1}
test namespace-11.3 {TclGetOriginalCommand, indirectly imported cmd} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_export {
        namespace export cmd1
        proc cmd1 {args} {return "cmd1: $args"}
	namespace export cmd1
	proc cmd1 {args} {return "cmd1: $args"}
    }
    namespace eval test_ns_import1 {
        namespace import ::test_ns_export::*
        namespace export *
        proc p {} {namespace origin cmd1}
	namespace import ::test_ns_export::*
	namespace export *
	proc p {} {namespace origin cmd1}
    }
} -body {
    namespace eval test_ns_import2 {
        namespace import ::test_ns_import1::*
        proc q {} {return [cmd1 123]}
	namespace import ::test_ns_import1::*
	proc q {} {return [cmd1 123]}
    }
    list [test_ns_import2::q] [namespace origin test_ns_import2::cmd1]
} -result {{cmd1: 123} ::test_ns_export::cmd1}

test namespace-12.1 {InvokeImportedCmd} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_export {
        namespace export cmd1
        proc cmd1 {args} {namespace current}
	namespace export cmd1
	proc cmd1 {args} {namespace current}
    }
    namespace eval test_ns_import {
        namespace import ::test_ns_export::*
	namespace import ::test_ns_export::*
    }
    list [test_ns_import::cmd1]
} {::test_ns_export}

test namespace-13.1 {DeleteImportedCmd, deletes imported cmds} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_export {
        namespace export cmd1
        proc cmd1 {args} {namespace current}
	namespace export cmd1
	proc cmd1 {args} {namespace current}
    }
    namespace eval test_ns_import {
        namespace import ::test_ns_export::*
	namespace import ::test_ns_export::*
    }
} -body {
    namespace eval test_ns_import {
        set l {}
        lappend l [info commands ::test_ns_import::*]
        namespace forget ::test_ns_export::cmd1
        lappend l [info commands ::test_ns_import::*]
	set l {}
	lappend l [info commands ::test_ns_import::*]
	namespace forget ::test_ns_export::cmd1
	lappend l [info commands ::test_ns_import::*]
    }
} -result {::test_ns_import::cmd1 {}}
test namespace-13.2 {DeleteImportedCmd, Bug a4494e28ed} {
    # Will panic if still buggy
    namespace eval src {namespace export foo; proc foo {} {}}
    namespace eval dst {namespace import [namespace parent]::src::foo}
    trace add command src::foo delete \
        "[list namespace delete [namespace current]::dst] ;#"
	"[list namespace delete [namespace current]::dst] ;#"
    proc src::foo {} {}
    namespace delete src
} {}

test namespace-14.1 {TclGetNamespaceForQualName, absolute names} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    variable v 10
    namespace eval test_ns_1::test_ns_2 {
        variable v 20
	variable v 20
    }
    namespace eval test_ns_2 {
        variable v 30
	variable v 30
    }
} -body {
    namespace eval test_ns_1 {
        list $::v $::test_ns_2::v $::test_ns_1::test_ns_2::v \
	list $::v $::test_ns_2::v $::test_ns_1::test_ns_2::v \
		[lsort [namespace children :: test_ns_*]]
    }
} -result [list 10 30 20 [lsort {::test_ns_1 ::test_ns_2}]]
test namespace-14.2 {TclGetNamespaceForQualName, invalid absolute names} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    variable v 10
    namespace eval test_ns_1::test_ns_2 {
        variable v 20
	variable v 20
    }
    namespace eval test_ns_2 {
        variable v 30
	variable v 30
    }
} -body {
    namespace eval test_ns_1 {
        list [catch {set ::test_ns_777::v} msg] $msg \
             [catch {namespace children test_ns_777} msg] $msg
	list [catch {set ::test_ns_777::v} msg] $msg \
	     [catch {namespace children test_ns_777} msg] $msg
    }
} -result {1 {can't read "::test_ns_777::v": no such variable} 1 {namespace "test_ns_777" not found in "::test_ns_1"}}

# TIP 278: secondary lookup disabled, results changed from {10 20}
test namespace-14.3 {TclGetNamespaceForQualName, relative names} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    variable v 10
    namespace eval test_ns_1::test_ns_2 {
        variable v 20
	variable v 20
    }
    namespace eval test_ns_2 {
        variable v 30
	variable v 30
    }
} -body {
    namespace eval test_ns_1 {
        # list $v $test_ns_2::v
        list [catch {set v} msg] $msg  [catch {set test_ns_2::v} msg] $msg
	# list $v $test_ns_2::v
	list [catch {set v} msg] $msg  [catch {set test_ns_2::v} msg] $msg
    }
} -result {1 {can't read "v": no such variable} 0 20}

test namespace-14.4 {TclGetNamespaceForQualName, relative ns names looked up only in current ns} {
    namespace eval test_ns_1::test_ns_2 {
        namespace eval foo {}
	namespace eval foo {}
    }
    namespace eval test_ns_1 {
        list [namespace children test_ns_2] \
             [catch {namespace children test_ns_1} msg] $msg
	list [namespace children test_ns_2] \
	     [catch {namespace children test_ns_1} msg] $msg
    }
} {::test_ns_1::test_ns_2::foo 1 {namespace "test_ns_1" not found in "::test_ns_1"}}
test namespace-14.5 {TclGetNamespaceForQualName, relative ns names looked up only in current ns} {
    namespace eval ::test_ns_2 {
        namespace eval bar {}
	namespace eval bar {}
    }
    namespace eval test_ns_1 {
        list [catch {namespace delete test_ns_2::bar} msg] $msg
	list [catch {namespace delete test_ns_2::bar} msg] $msg
    }
} {1 {unknown namespace "test_ns_2::bar" in namespace delete command}}
test namespace-14.6 {TclGetNamespaceForQualName, relative ns names looked up only in current ns} {
    namespace eval test_ns_1::test_ns_2 {
        namespace eval foo {}
	namespace eval foo {}
    }
    namespace eval test_ns_1 {
        list [namespace children test_ns_2] \
             [catch {namespace children test_ns_1} msg] $msg
	list [namespace children test_ns_2] \
	     [catch {namespace children test_ns_1} msg] $msg
    }
} {::test_ns_1::test_ns_2::foo 1 {namespace "test_ns_1" not found in "::test_ns_1"}}
test namespace-14.7 {TclGetNamespaceForQualName, ignore extra :s if ns} -setup {
    namespace eval test_ns_1::test_ns_2::foo {}
} -body {
    namespace children test_ns_1:::
} -result {::test_ns_1::test_ns_2}
728
729
730
731
732
733
734
735
736


737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755


756
757
758

759
760
761
762
763
764
765
766
767
768




769
770
771
772
773
774

775
776
777
778
779
780
781
782
783
784



785
786
787
788
789
790
791


792
793
794
795
796
797
798
799


800
801
802
803
804
805
806
790
791
792
793
794
795
796


797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815


816
817
818
819

820
821
822
823
824
825
826




827
828
829
830
831
832
833
834
835

836
837
838
839
840
841
842
843



844
845
846
847
848
849
850
851


852
853
854
855
856
857
858
859


860
861
862
863
864
865
866
867
868







-
-
+
+

















-
-
+
+


-
+






-
-
-
-
+
+
+
+





-
+







-
-
-
+
+
+





-
-
+
+






-
-
+
+







} -result {1 {invalid command name "test_ns_1::test_ns_2::"} {{}: hello}}

# TIP 278: secondary lookup disabled, added catch, result changed from y
test namespace-14.12 {TclGetNamespaceForQualName, extra ::s are significant for vars} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
    namespace eval test_ns_1 {
        variable {}
        catch {set test_ns_1::(x) y} ::msg
	variable {}
	catch {set test_ns_1::(x) y} ::msg
    }
    list $::msg [catch {set test_ns_1::(x)} msg] $msg
} -result {{can't set "test_ns_1::(x)": parent namespace doesn't exist} 1 {can't read "test_ns_1::(x)": no such variable}}
test namespace-14.13 {TclGetNamespaceForQualName, namespace other than global ns can't have empty name} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -returnCodes error -body {
    namespace eval test_ns_1 {
	proc {} {} {}
	namespace eval {} {}
	{}
    }
} -result {can't create namespace "": only global namespace can have empty name}

test namespace-15.1 {Tcl_FindNamespace, absolute name found} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
    namespace eval test_ns_delete {
        namespace eval test_ns_delete2 {}
        proc cmd {args} {namespace current}
	namespace eval test_ns_delete2 {}
	proc cmd {args} {namespace current}
    }
    list [namespace delete ::test_ns_delete::test_ns_delete2] \
         [namespace children ::test_ns_delete]
	 [namespace children ::test_ns_delete]
} -result {{} {}}
test namespace-15.2 {Tcl_FindNamespace, absolute name not found} -body {
    namespace delete ::test_ns_delete::test_ns_delete2
} -returnCodes error -result {unknown namespace "::test_ns_delete::test_ns_delete2" in namespace delete command}
test namespace-15.3 {Tcl_FindNamespace, relative name found} {
    namespace eval test_ns_delete {
        namespace eval test_ns_delete2 {}
        namespace eval test_ns_delete3 {}
        list [namespace delete test_ns_delete2] \
             [namespace children [namespace current]]
	namespace eval test_ns_delete2 {}
	namespace eval test_ns_delete3 {}
	list [namespace delete test_ns_delete2] \
	     [namespace children [namespace current]]
    }
} {{} ::test_ns_delete::test_ns_delete3}
test namespace-15.4 {Tcl_FindNamespace, relative name not found} {
    namespace eval test_ns_delete2 {}
    namespace eval test_ns_delete {
        list [catch {namespace delete test_ns_delete2} msg] $msg
	list [catch {namespace delete test_ns_delete2} msg] $msg
    }
} {1 {unknown namespace "test_ns_delete2" in namespace delete command}}

test namespace-16.1 {Tcl_FindCommand, absolute name found} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
    namespace eval test_ns_1 {
        proc cmd {args} {return "[namespace current]::cmd: $args"}
        variable v "::test_ns_1::cmd"
        eval $v one
	proc cmd {args} {return "[namespace current]::cmd: $args"}
	variable v "::test_ns_1::cmd"
	eval $v one
    }
} -result {::test_ns_1::cmd: one}
test namespace-16.2 {Tcl_FindCommand, absolute name found} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_1 {
        proc cmd {args} {return "[namespace current]::cmd: $args"}
        variable v "::test_ns_1::cmd"
	proc cmd {args} {return "[namespace current]::cmd: $args"}
	variable v "::test_ns_1::cmd"
    }
} -body {
    eval $test_ns_1::v two
} -result {::test_ns_1::cmd: two}
test namespace-16.3 {Tcl_FindCommand, absolute name not found} {
    namespace eval test_ns_1 {
        variable v2 "::test_ns_1::ladidah"
        list [catch {eval $v2} msg] $msg
	variable v2 "::test_ns_1::ladidah"
	list [catch {eval $v2} msg] $msg
    }
} {1 {invalid command name "::test_ns_1::ladidah"}}

# save the "unknown" proc, which is redefined by the following two tests
catch {rename unknown unknown.old}
proc unknown {args} {
    return "unknown: $args"
820
821
822
823
824
825
826
827

828
829
830
831

832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850






851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867

868
869
870
871
872
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
898
899



900
901
902
903
904
905

906
907
908
909

910
911
912
913
914
915
916
917
918


919
920
921
922
923

924
925
926
927
928

929
930
931
932
933
934
935
882
883
884
885
886
887
888

889
890
891
892

893
894
895
896
897
898
899
900
901
902
903
904
905
906






907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928

929
930
931
932
933
934


935
936
937
938
939
940




941
942
943
944
945
946
947
948




949
950
951
952
953
954
955
956
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







-
+



-
+













-
-
-
-
-
-
+
+
+
+
+
+
















-
+





-
-
+
+




-
-
-
-
+
+
+
+




-
-
-
-
+
+
+
+






-
-
-
+
+
+





-
+



-
+







-
-
+
+




-
+




-
+







# restore the "unknown" proc saved previously
catch {rename unknown {}}
catch {rename unknown.old unknown}

test namespace-16.8 {Tcl_FindCommand, relative name found} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_1 {
        proc cmd {args} {return "[namespace current]::cmd: $args"}
	proc cmd {args} {return "[namespace current]::cmd: $args"}
    }
} -body {
    namespace eval test_ns_1 {
        cmd a b c
	cmd a b c
    }
} -result {::test_ns_1::cmd: a b c}
test namespace-16.9 {Tcl_FindCommand, relative name found} -body {
    proc cmd2 {args} {return "[namespace current]::cmd2: $args"}
    namespace eval test_ns_1 {
       cmd2 a b c
    }
} -cleanup {
    catch {rename cmd2 {}}
} -result {::::cmd2: a b c}
test namespace-16.10 {Tcl_FindCommand, relative name found, only look in current then global ns} -body {
    proc cmd2 {args} {return "[namespace current]::cmd2: $args"}
    namespace eval test_ns_1 {
        proc cmd2 {args} {
            return "[namespace current]::cmd2 in test_ns_1: $args"
        }
        namespace eval test_ns_12 {
            cmd2 a b c
        }
	proc cmd2 {args} {
	    return "[namespace current]::cmd2 in test_ns_1: $args"
	}
	namespace eval test_ns_12 {
	    cmd2 a b c
	}
    }
} -cleanup {
    catch {rename cmd2 {}}
} -result {::::cmd2: a b c}
test namespace-16.11 {Tcl_FindCommand, relative name not found} -body {
    namespace eval test_ns_1 {
       cmd3 a b c
    }
} -returnCodes error -result {invalid command name "cmd3"}

unset -nocomplain x
test namespace-17.1 {Tcl_FindNamespaceVar, absolute name found} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
    set x 314159
    namespace eval test_ns_1 {
        set ::x
	set ::x
    }
} -result {314159}
variable ::x 314159
test namespace-17.2 {Tcl_FindNamespaceVar, absolute name found} {
    namespace eval test_ns_1 {
        variable x 777
        set ::test_ns_1::x
	variable x 777
	set ::test_ns_1::x
    }
} {777}
test namespace-17.3 {Tcl_FindNamespaceVar, absolute name found} {
    namespace eval test_ns_1 {
        namespace eval test_ns_2 {
            variable x 1111
        }
        set ::test_ns_1::test_ns_2::x
	namespace eval test_ns_2 {
	    variable x 1111
	}
	set ::test_ns_1::test_ns_2::x
    }
} {1111}
test namespace-17.4 {Tcl_FindNamespaceVar, absolute name not found} -body {
    namespace eval test_ns_1 {
        namespace eval test_ns_2 {
            variable x 1111
        }
        set ::test_ns_1::test_ns_2::y
	namespace eval test_ns_2 {
	    variable x 1111
	}
	set ::test_ns_1::test_ns_2::y
    }
} -returnCodes error -result {can't read "::test_ns_1::test_ns_2::y": no such variable}
test namespace-17.5 {Tcl_FindNamespaceVar, absolute name and TCL_GLOBAL_ONLY} -setup {
    namespace eval ::test_ns_1::test_ns_2 {}
} -body {
    namespace eval test_ns_1 {
        namespace eval test_ns_3 {
            variable ::test_ns_1::test_ns_2::x 2222
        }
	namespace eval test_ns_3 {
	    variable ::test_ns_1::test_ns_2::x 2222
	}
    }
    set ::test_ns_1::test_ns_2::x
} -result {2222}
test namespace-17.6 {Tcl_FindNamespaceVar, relative name found} -setup {
    namespace eval test_ns_1 {
        variable x 777
	variable x 777
    }
} -body {
    namespace eval test_ns_1 {
        set x
	set x
    }
} -result {777}

# TIP 278: secondary lookup disabled, catch added, result changed from 314159
test namespace-17.7 {Tcl_FindNamespaceVar, relative name found} {
    namespace eval test_ns_1 {
	variable x 777
        unset x
        list [catch {set x} msg] $msg  ;# must not be global x now
	unset x
	list [catch {set x} msg] $msg  ;# must not be global x now
    }
} {1 {can't read "x": no such variable}}
test namespace-17.8 {Tcl_FindNamespaceVar, relative name not found} -body {
    namespace eval test_ns_1 {
        set wuzzat
	set wuzzat
    }
} -returnCodes error -result {can't read "wuzzat": no such variable}
test namespace-17.9 {Tcl_FindNamespaceVar, relative name and TCL_GLOBAL_ONLY} {
    namespace eval test_ns_1 {
        variable a hello
	variable a hello
    }
    set test_ns_1::a
} {hello}

# TIP 278: secondary lookup disabled, result changed from 1
test namespace-17.10 {Tcl_FindNamespaceVar, interference with cached varNames} -setup {
    namespace eval test_ns_1 {}
951
952
953
954
955
956
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
1016
1017
1018
1019
1020
1021
1022




1023
1024
1025
1026
1027
1028
1029
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







-
-
-
+
+
+




-
-
+
+





-
+


-
-
-
-
+
+
+
+




-
-
-
-
+
+
+
+

















-
+






-
+







-
-
-
-
+
+
+
+







catch {unset l}
catch {rename foo {}}
test namespace-18.1 {TclResetShadowedCmdRefs, one-level check for command shadowing} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
    proc foo {} {return "global foo"}
    namespace eval test_ns_1 {
        proc trigger {} {
            return [foo]
        }
	proc trigger {} {
	    return [foo]
	}
    }
    set l ""
    lappend l [test_ns_1::trigger]
    namespace eval test_ns_1 {
        # force invalidation of cached ref to "foo" in proc trigger
        proc foo {} {return "foo in test_ns_1"}
	# force invalidation of cached ref to "foo" in proc trigger
	proc foo {} {return "foo in test_ns_1"}
    }
    lappend l [test_ns_1::trigger]
} -result {{global foo} {foo in test_ns_1}}
test namespace-18.2 {TclResetShadowedCmdRefs, multilevel check for command shadowing} {
    namespace eval test_ns_2 {
        proc foo {} {return "foo in ::test_ns_2"}
	proc foo {} {return "foo in ::test_ns_2"}
    }
    namespace eval test_ns_1 {
        namespace eval test_ns_2 {}
        proc trigger {} {
            return [test_ns_2::foo]
        }
	namespace eval test_ns_2 {}
	proc trigger {} {
	    return [test_ns_2::foo]
	}
    }
    set l ""
    lappend l [test_ns_1::trigger]
    namespace eval test_ns_1 {
        namespace eval test_ns_2 {
            # force invalidation of cached ref to "foo" in proc trigger
            proc foo {} {return "foo in ::test_ns_1::test_ns_2"}
        }
	namespace eval test_ns_2 {
	    # force invalidation of cached ref to "foo" in proc trigger
	    proc foo {} {return "foo in ::test_ns_1::test_ns_2"}
	}
    }
    lappend l [test_ns_1::trigger]
} {{foo in ::test_ns_2} {foo in ::test_ns_1::test_ns_2}}
catch {unset l}
catch {rename foo {}}

test namespace-19.1 {GetNamespaceFromObj, global name found} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
    namespace eval test_ns_1::test_ns_2 {}
    namespace children ::test_ns_1
} -result {::test_ns_1::test_ns_2}
test namespace-19.2 {GetNamespaceFromObj, relative name found} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_1::test_ns_2 {}
} -body {
    namespace eval test_ns_1 {
        namespace children test_ns_2
	namespace children test_ns_2
    }
} -result {}
test namespace-19.3 {GetNamespaceFromObj, name not found} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
    namespace eval test_ns_1 {
        namespace children test_ns_99
	namespace children test_ns_99
    }
} -returnCodes error -result {namespace "test_ns_99" not found in "::test_ns_1"}
test namespace-19.4 {GetNamespaceFromObj, invalidation of cached ns refs} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_1::test_ns_2 {}
} -body {
    namespace eval test_ns_1 {
        proc foo {} {
            return [namespace children test_ns_2]
        }
        list [catch {namespace children test_ns_99} msg] $msg
	proc foo {} {
	    return [namespace children test_ns_2]
	}
	list [catch {namespace children test_ns_99} msg] $msg
    }
    set l {}
    lappend l [test_ns_1::foo]
    namespace delete test_ns_1::test_ns_2
    namespace eval test_ns_1::test_ns_2::test_ns_3 {}
    lappend l [test_ns_1::foo]
} -result {{} ::test_ns_1::test_ns_2::test_ns_3}
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
1108
1109
1110
1111
1112
1113
1114

1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128

1129
1130
1131
1132
1133

1134
1135
1136
1137
1138
1139
1140
1141







-
+













-
+




-
+







    expr {"::test_ns_1" in [namespace children]}
} -result {1}
test namespace-21.2 {NamespaceChildrenCmd, no args} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_1::test_ns_2 {}
} -body {
    namespace eval test_ns_1 {
        namespace children
	namespace children
    }
} -result {::test_ns_1::test_ns_2}
test namespace-21.3 {NamespaceChildrenCmd, ns name given} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_1::test_ns_2 {}
} -body {
    namespace children ::test_ns_1
} -result {::test_ns_1::test_ns_2}
test namespace-21.4 {NamespaceChildrenCmd, ns name given} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_1::test_ns_2 {}
} -body {
    namespace eval test_ns_1 {
        namespace children test_ns_2
	namespace children test_ns_2
    }
} -result {}
test namespace-21.5 {NamespaceChildrenCmd, too many args} {
    namespace eval test_ns_1 {
        list [catch {namespace children test_ns_2 xxx yyy} msg] $msg
	list [catch {namespace children test_ns_2 xxx yyy} msg] $msg
    }
} {1 {wrong # args: should be "namespace children ?name? ?pattern?"}}
test namespace-21.6 {NamespaceChildrenCmd, glob-style pattern given} {
    namespace eval test_ns_1::test_ns_foo {}
    namespace children test_ns_1 *f*
} {::test_ns_1::test_ns_foo}
test namespace-21.7 {NamespaceChildrenCmd, glob-style pattern given} -setup {
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
1116
1117
1149
1150
1151
1152
1153
1154
1155

1156
1157
1158
1159

1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171

1172
1173
1174
1175
1176
1177
1178
1179







-
+



-
+











-
+







    namespace eval test_ns_1 {}
    namespace children [namespace current] [fq test_ns_1]
} [fq test_ns_1]

test namespace-22.1 {NamespaceCodeCmd, bad args} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    list [catch {namespace code} msg] $msg \
         [catch {namespace code xxx yyy} msg] $msg
	 [catch {namespace code xxx yyy} msg] $msg
} {1 {wrong # args: should be "namespace code arg"} 1 {wrong # args: should be "namespace code arg"}}
test namespace-22.2 {NamespaceCodeCmd, arg is already scoped value} {
    namespace eval test_ns_1 {
        proc cmd {} {return "test_ns_1::cmd"}
	proc cmd {} {return "test_ns_1::cmd"}
    }
    namespace code {::namespace inscope ::test_ns_1 cmd}
} {::namespace inscope ::test_ns_1 cmd}
test namespace-22.3 {NamespaceCodeCmd, arg is already scoped value} {
    namespace code {namespace     inscope     ::test_ns_1 cmd}
} {::namespace inscope :: {namespace     inscope     ::test_ns_1 cmd}}
test namespace-22.4 {NamespaceCodeCmd, in :: namespace} {
    namespace code unknown
} {::namespace inscope :: unknown}
test namespace-22.5 {NamespaceCodeCmd, in other namespace} {
    namespace eval test_ns_1 {
        namespace code cmd
	namespace code cmd
    }
} {::namespace inscope ::test_ns_1 cmd}
test namespace-22.6 {NamespaceCodeCmd, in other namespace} {
    namespace eval test_ns_1 {
	variable v 42
    }
    namespace eval test_ns_2 {
1127
1128
1129
1130
1131
1132
1133
1134

1135
1136
1137
1138
1139
1140
1141

1142
1143
1144
1145
1146
1147
1148
1189
1190
1191
1192
1193
1194
1195

1196
1197
1198
1199
1200
1201
1202

1203
1204
1205
1206
1207
1208
1209
1210







-
+






-
+







	::namespace code {namespace inscope foo}
    }
} [list ::namespace inscope [fq demo] {namespace inscope foo}]

test namespace-23.1 {NamespaceCurrentCmd, bad args} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    list [catch {namespace current xxx} msg] $msg \
         [catch {namespace current xxx yyy} msg] $msg
	 [catch {namespace current xxx yyy} msg] $msg
} {1 {wrong # args: should be "namespace current"} 1 {wrong # args: should be "namespace current"}}
test namespace-23.2 {NamespaceCurrentCmd, at global level} {
    namespace current
} {::}
test namespace-23.3 {NamespaceCurrentCmd, in nested ns} {
    namespace eval test_ns_1::test_ns_2 {
        namespace current
	namespace current
    }
} {::test_ns_1::test_ns_2}

test namespace-24.1 {NamespaceDeleteCmd, no args} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace delete
} {}
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176





1177
1178
1179
1180
1181
1182
1183
1184
1185
1186





1187
1188
1189
1190

1191
1192
1193
1194
1195
1196
1197
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







-
-
-
-
-
+
+
+
+
+





-
-
-
-
-
+
+
+
+
+



-
+







test namespace-25.2 {NamespaceEvalCmd, bad args} -body {
    namespace test_ns_1
} -returnCodes error -match glob -result {unknown or ambiguous subcommand "test_ns_1": must be *}
catch {unset v}
test namespace-25.3 {NamespaceEvalCmd, new namespace} {
    set v 123
    namespace eval test_ns_1 {
        variable v 314159
        proc p {} {
            variable v
            return $v
        }
	variable v 314159
	proc p {} {
	    variable v
	    return $v
	}
    }
    test_ns_1::p
} {314159}
test namespace-25.4 {NamespaceEvalCmd, existing namespace} -setup {
    namespace eval test_ns_1 {
        variable v 314159
        proc p {} {
            variable v
            return $v
        }
	variable v 314159
	proc p {} {
	    variable v
	    return $v
	}
    }
} -body {
    namespace eval test_ns_1 {
        proc q {} {return [expr {[p]+1}]}
	proc q {} {return [expr {[p]+1}]}
    }
    test_ns_1::q
} -result {314160}
test namespace-25.5 {NamespaceEvalCmd, multiple args} -setup {
    namespace eval test_ns_1 {variable v 314159}
} -body {
    namespace eval test_ns_1 "set" "v"
1226
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
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
1354
1355

1356
1357
1358

1359
1360
1361
1362
1363
1364
1365
1366







-
+




-
-
-
-
-
+
+
+
+
+


-
+






-
-
-
-
-
+
+
+
+
+



-
+






-
-
-
-
-
+
+
+
+
+



-
+





-
-
-
-
+
+
+
+



-
+


-
+


-
+


-
+







    namespace export
} {}
test namespace-26.2 {NamespaceExportCmd, just -clear arg} {
    namespace export -clear
} {}
test namespace-26.3 {NamespaceExportCmd, pattern can't specify a namespace} {
    namespace eval test_ns_1 {
        list [catch {namespace export ::zzz} msg] $msg
	list [catch {namespace export ::zzz} msg] $msg
    }
} {1 {invalid export pattern "::zzz": pattern can't specify a namespace}}
test namespace-26.4 {NamespaceExportCmd, one pattern} {
    namespace eval test_ns_1 {
        namespace export cmd1
        proc cmd1 {args} {return "cmd1: $args"}
        proc cmd2 {args} {return "cmd2: $args"}
        proc cmd3 {args} {return "cmd3: $args"}
        proc cmd4 {args} {return "cmd4: $args"}
	namespace export cmd1
	proc cmd1 {args} {return "cmd1: $args"}
	proc cmd2 {args} {return "cmd2: $args"}
	proc cmd3 {args} {return "cmd3: $args"}
	proc cmd4 {args} {return "cmd4: $args"}
    }
    namespace eval test_ns_2 {
        namespace import ::test_ns_1::*
	namespace import ::test_ns_1::*
    }
    list [info commands test_ns_2::*] [test_ns_2::cmd1 hello]
} {::test_ns_2::cmd1 {cmd1: hello}}
test namespace-26.5 {NamespaceExportCmd, sequence of patterns, patterns accumulate} -setup {
    catch {namespace delete {*}[namespace children test_ns_*]}
    namespace eval test_ns_1 {
        proc cmd1 {args} {return "cmd1: $args"}
        proc cmd2 {args} {return "cmd2: $args"}
        proc cmd3 {args} {return "cmd3: $args"}
        proc cmd4 {args} {return "cmd4: $args"}
        namespace export cmd1 cmd3
	proc cmd1 {args} {return "cmd1: $args"}
	proc cmd2 {args} {return "cmd2: $args"}
	proc cmd3 {args} {return "cmd3: $args"}
	proc cmd4 {args} {return "cmd4: $args"}
	namespace export cmd1 cmd3
    }
} -body {
    namespace eval test_ns_2 {
        namespace import -force ::test_ns_1::*
	namespace import -force ::test_ns_1::*
    }
    list [lsort [info commands test_ns_2::*]] [test_ns_2::cmd3 hello]
} -result {{::test_ns_2::cmd1 ::test_ns_2::cmd3} {cmd3: hello}}
test namespace-26.6 {NamespaceExportCmd, no patterns means return uniq'ed export list} -setup {
    catch {namespace delete {*}[namespace children test_ns_*]}
    namespace eval test_ns_1 {
        proc cmd1 {args} {return "cmd1: $args"}
        proc cmd2 {args} {return "cmd2: $args"}
        proc cmd3 {args} {return "cmd3: $args"}
        proc cmd4 {args} {return "cmd4: $args"}
        namespace export cmd1 cmd3
	proc cmd1 {args} {return "cmd1: $args"}
	proc cmd2 {args} {return "cmd2: $args"}
	proc cmd3 {args} {return "cmd3: $args"}
	proc cmd4 {args} {return "cmd4: $args"}
	namespace export cmd1 cmd3
    }
} -body {
    namespace eval test_ns_1 {
        namespace export
	namespace export
    }
} -result {cmd1 cmd3}
test namespace-26.7 {NamespaceExportCmd, -clear resets export list} -setup {
    catch {namespace delete {*}[namespace children test_ns_*]}
    namespace eval test_ns_1 {
        proc cmd1 {args} {return "cmd1: $args"}
        proc cmd2 {args} {return "cmd2: $args"}
        proc cmd3 {args} {return "cmd3: $args"}
        proc cmd4 {args} {return "cmd4: $args"}
	proc cmd1 {args} {return "cmd1: $args"}
	proc cmd2 {args} {return "cmd2: $args"}
	proc cmd3 {args} {return "cmd3: $args"}
	proc cmd4 {args} {return "cmd4: $args"}
    }
} -body {
    namespace eval test_ns_1 {
        namespace export cmd1 cmd3
	namespace export cmd1 cmd3
    }
    namespace eval test_ns_2 {
        namespace import ::test_ns_1::*
	namespace import ::test_ns_1::*
    }
    namespace eval test_ns_1 {
        namespace export -clear cmd4
	namespace export -clear cmd4
    }
    namespace eval test_ns_2 {
        namespace import ::test_ns_1::*
	namespace import ::test_ns_1::*
    }
    list [lsort [info commands test_ns_2::*]] [test_ns_2::cmd4 hello]
} -result [list [lsort {::test_ns_2::cmd4 ::test_ns_2::cmd1 ::test_ns_2::cmd3}] {cmd4: hello}]
test namespace-26.8 {NamespaceExportCmd, -clear resets export list} {
    catch {namespace delete foo}
    namespace eval foo {
	namespace export x
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321



1322
1323
1324
1325


1326
1327
1328
1329
1330
1331
1332
1374
1375
1376
1377
1378
1379
1380



1381
1382
1383
1384
1385


1386
1387
1388
1389
1390
1391
1392
1393
1394







-
-
-
+
+
+


-
-
+
+







    namespace forget
} {}
test namespace-27.2 {NamespaceForgetCmd, args must be valid namespaces} {
    list [catch {namespace forget ::test_ns_1::xxx} msg] $msg
} {1 {unknown namespace in namespace forget pattern "::test_ns_1::xxx"}}
test namespace-27.3 {NamespaceForgetCmd, arg is forgotten} {
    namespace eval test_ns_1 {
        namespace export cmd*
        proc cmd1 {args} {return "cmd1: $args"}
        proc cmd2 {args} {return "cmd2: $args"}
	namespace export cmd*
	proc cmd1 {args} {return "cmd1: $args"}
	proc cmd2 {args} {return "cmd2: $args"}
    }
    namespace eval test_ns_2 {
        namespace import ::test_ns_1::*
        namespace forget ::test_ns_1::cmd1
	namespace import ::test_ns_1::*
	namespace forget ::test_ns_1::cmd1
    }
    info commands ::test_ns_2::*
} {::test_ns_2::cmd2}

test namespace-28.1 {NamespaceImportCmd, no args} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354



1355
1356
1357
1358


1359
1360
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
1387
1388
1389





1390
1391
1392
1393

1394
1395
1396
1397
1398
1399
1400
1407
1408
1409
1410
1411
1412
1413



1414
1415
1416
1417
1418


1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436





1437
1438
1439
1440
1441
1442
1443
1444
1445
1446





1447
1448
1449
1450
1451
1452
1453
1454

1455
1456
1457
1458
1459
1460
1461
1462







-
-
-
+
+
+


-
-
+
+
















-
-
-
-
-
+
+
+
+
+





-
-
-
-
-
+
+
+
+
+



-
+







    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -result {bar boo foo}
test namespace-28.2 {NamespaceImportCmd, no args and just "-force"} {
    namespace import -force
} {}
test namespace-28.3 {NamespaceImportCmd, arg is imported} {
    namespace eval test_ns_1 {
        namespace export cmd2
        proc cmd1 {args} {return "cmd1: $args"}
        proc cmd2 {args} {return "cmd2: $args"}
	namespace export cmd2
	proc cmd1 {args} {return "cmd1: $args"}
	proc cmd2 {args} {return "cmd2: $args"}
    }
    namespace eval test_ns_2 {
        namespace import ::test_ns_1::*
        namespace forget ::test_ns_1::cmd1
	namespace import ::test_ns_1::*
	namespace forget ::test_ns_1::cmd1
    }
    info commands test_ns_2::*
} {::test_ns_2::cmd2}

test namespace-29.1 {NamespaceInscopeCmd, bad args} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    list [catch {namespace inscope} msg] $msg
} {1 {wrong # args: should be "namespace inscope name arg ?arg...?"}}
test namespace-29.2 {NamespaceInscopeCmd, bad args} {
    list [catch {namespace inscope ::} msg] $msg
} {1 {wrong # args: should be "namespace inscope name arg ?arg...?"}}
test namespace-29.3 {NamespaceInscopeCmd, specified ns must exist} -body {
    namespace inscope test_ns_1 {set v}
} -returnCodes error -result {namespace "test_ns_1" not found in "::"}
test namespace-29.4 {NamespaceInscopeCmd, simple case} {
    namespace eval test_ns_1 {
        variable v 747
        proc cmd {args} {
            variable v
            return "[namespace current]::cmd: v=$v, args=$args"
        }
	variable v 747
	proc cmd {args} {
	    variable v
	    return "[namespace current]::cmd: v=$v, args=$args"
	}
    }
    namespace inscope test_ns_1 cmd
} {::test_ns_1::cmd: v=747, args=}
test namespace-29.5 {NamespaceInscopeCmd, has lappend semantics} -setup {
    namespace eval test_ns_1 {
        variable v 747
        proc cmd {args} {
            variable v
            return "[namespace current]::cmd: v=$v, args=$args"
        }
	variable v 747
	proc cmd {args} {
	    variable v
	    return "[namespace current]::cmd: v=$v, args=$args"
	}
    }
} -body {
    list [namespace inscope test_ns_1 cmd x y z] \
         [namespace eval test_ns_1 [concat cmd [list x y z]]]
	 [namespace eval test_ns_1 [concat cmd [list x y z]]]
} -result {{::test_ns_1::cmd: v=747, args=x y z} {::test_ns_1::cmd: v=747, args=x y z}}
test namespace-29.6 {NamespaceInscopeCmd, 1400572} -setup {
    namespace eval test_ns_1 {}
} -body {
    namespace inscope test_ns_1 {info level 0}
} -result {namespace inscope test_ns_1 {info level 0}}

1409
1410
1411
1412
1413
1414
1415
1416
1417
1418



1419
1420
1421
1422
1423



1424
1425
1426
1427
1428
1429
1430





1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445



1446
1447
1448
1449


1450
1451
1452
1453
1454
1455
1456
1471
1472
1473
1474
1475
1476
1477



1478
1479
1480
1481
1482



1483
1484
1485
1486
1487





1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504



1505
1506
1507
1508
1509


1510
1511
1512
1513
1514
1515
1516
1517
1518







-
-
-
+
+
+


-
-
-
+
+
+


-
-
-
-
-
+
+
+
+
+












-
-
-
+
+
+


-
-
+
+







    list [catch {namespace origin fred} msg] $msg
} {1 {invalid command name "fred"}}
test namespace-30.4 {NamespaceOriginCmd, command isn't imported} {
    namespace origin set
} {::set}
test namespace-30.5 {NamespaceOriginCmd, imported command} {
    namespace eval test_ns_1 {
        namespace export cmd*
        proc cmd1 {args} {return "cmd1: $args"}
        proc cmd2 {args} {return "cmd2: $args"}
	namespace export cmd*
	proc cmd1 {args} {return "cmd1: $args"}
	proc cmd2 {args} {return "cmd2: $args"}
    }
    namespace eval test_ns_2 {
        namespace export *
        namespace import ::test_ns_1::*
        proc p {} {}
	namespace export *
	namespace import ::test_ns_1::*
	proc p {} {}
    }
    namespace eval test_ns_3 {
        namespace import ::test_ns_2::*
        list [namespace origin foreach] \
             [namespace origin p] \
             [namespace origin cmd1] \
             [namespace origin ::test_ns_2::cmd2]
	namespace import ::test_ns_2::*
	list [namespace origin foreach] \
	     [namespace origin p] \
	     [namespace origin cmd1] \
	     [namespace origin ::test_ns_2::cmd2]
    }
} {::foreach ::test_ns_2::p ::test_ns_1::cmd1 ::test_ns_1::cmd2}

test namespace-31.1 {NamespaceParentCmd, bad args} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    list [catch {namespace parent a b} msg] $msg
} {1 {wrong # args: should be "namespace parent ?name?"}}
test namespace-31.2 {NamespaceParentCmd, no args} {
    namespace parent
} {}
test namespace-31.3 {NamespaceParentCmd, namespace specified} {
    namespace eval test_ns_1 {
        namespace eval test_ns_2 {
            namespace eval test_ns_3 {}
        }
	namespace eval test_ns_2 {
	    namespace eval test_ns_3 {}
	}
    }
    list [namespace parent ::] \
         [namespace parent test_ns_1::test_ns_2] \
         [namespace eval test_ns_1::test_ns_2::test_ns_3 {namespace parent ::test_ns_1::test_ns_2}]
	 [namespace parent test_ns_1::test_ns_2] \
	 [namespace eval test_ns_1::test_ns_2::test_ns_3 {namespace parent ::test_ns_1::test_ns_2}]
} {{} ::test_ns_1 ::test_ns_1}
test namespace-31.4 {NamespaceParentCmd, bad namespace specified} -body {
    namespace parent test_ns_1::test_ns_foo
} -returnCodes error -result {namespace "test_ns_1::test_ns_foo" not found in "::"}

test namespace-32.1 {NamespaceQualifiersCmd, bad args} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526




1527
1528
1529
1530
1531
1532




1533
1534
1535
1536
1537
1538
1539
1540
1541
1542







1543
1544
1545
1546
1547
1548
1549
1550



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
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







-
-
-
-
+
+
+
+


-
-
-
-
+
+
+
+



-
-
-
-
-
-
-
+
+
+
+
+
+
+





-
-
-
+
+
+


-
-
-
+
+
+


-
+



-
-
-
-
+
+
+
+







-
-
-
+
+
+


-
-
-
-
+
+
+
+


-
-
+
+



-
-
-
-
+
+
+
+







-
-
-
-
+
+
+
+





-
-
-
+
+
+


-
-
+
+

















-
+




-
+







-
+







} {}
test namespace-34.4 {NamespaceWhichCmd, bad args} {
    list [catch {namespace which a b} msg] $msg
} {1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}}
test namespace-34.5 {NamespaceWhichCmd, command lookup} -setup {
    catch {namespace delete {*}[namespace children test_ns_*]}
    namespace eval test_ns_1 {
        namespace export cmd*
        variable v1 111
        proc cmd1 {args} {return "cmd1: $args"}
        proc cmd2 {args} {return "cmd2: $args"}
	namespace export cmd*
	variable v1 111
	proc cmd1 {args} {return "cmd1: $args"}
	proc cmd2 {args} {return "cmd2: $args"}
    }
    namespace eval test_ns_2 {
        namespace export *
        namespace import ::test_ns_1::*
        variable v2 222
        proc p {} {}
	namespace export *
	namespace import ::test_ns_1::*
	variable v2 222
	proc p {} {}
    }
} -body {
    namespace eval test_ns_3 {
        namespace import ::test_ns_2::*
        variable v3 333
        list [namespace which -command foreach] \
             [namespace which -command p] \
             [namespace which -command cmd1] \
             [namespace which -command ::test_ns_2::cmd2] \
             [catch {namespace which -command ::test_ns_2::noSuchCmd} msg] $msg
	namespace import ::test_ns_2::*
	variable v3 333
	list [namespace which -command foreach] \
	     [namespace which -command p] \
	     [namespace which -command cmd1] \
	     [namespace which -command ::test_ns_2::cmd2] \
	     [catch {namespace which -command ::test_ns_2::noSuchCmd} msg] $msg
    }
} -result {::foreach ::test_ns_3::p ::test_ns_3::cmd1 ::test_ns_2::cmd2 0 {}}
test namespace-34.6 {NamespaceWhichCmd, -command is default} -setup {
    catch {namespace delete {*}[namespace children test_ns_*]}
    namespace eval test_ns_1 {
        namespace export cmd*
        proc cmd1 {args} {return "cmd1: $args"}
        proc cmd2 {args} {return "cmd2: $args"}
	namespace export cmd*
	proc cmd1 {args} {return "cmd1: $args"}
	proc cmd2 {args} {return "cmd2: $args"}
    }
    namespace eval test_ns_2 {
        namespace export *
        namespace import ::test_ns_1::*
        proc p {} {}
	namespace export *
	namespace import ::test_ns_1::*
	proc p {} {}
    }
    namespace eval test_ns_3 {
        namespace import ::test_ns_2::*
	namespace import ::test_ns_2::*
    }
} -body {
    namespace eval test_ns_3 {
        list [namespace which foreach] \
             [namespace which p] \
             [namespace which cmd1] \
             [namespace which ::test_ns_2::cmd2]
	list [namespace which foreach] \
	     [namespace which p] \
	     [namespace which cmd1] \
	     [namespace which ::test_ns_2::cmd2]
    }
} -result {::foreach ::test_ns_3::p ::test_ns_3::cmd1 ::test_ns_2::cmd2}

# TIP 278: secondary lookup disabled, catch added, result changed
test namespace-34.7 {NamespaceWhichCmd, variable lookup} -setup {
    catch {namespace delete {*}[namespace children test_ns_*]}
    namespace eval test_ns_1 {
        namespace export cmd*
        proc cmd1 {args} {return "cmd1: $args"}
        proc cmd2 {args} {return "cmd2: $args"}
	namespace export cmd*
	proc cmd1 {args} {return "cmd1: $args"}
	proc cmd2 {args} {return "cmd2: $args"}
    }
    namespace eval test_ns_2 {
        namespace export *
        namespace import ::test_ns_1::*
        variable v2 222
        proc p {} {}
	namespace export *
	namespace import ::test_ns_1::*
	variable v2 222
	proc p {} {}
    }
    namespace eval test_ns_3 {
        variable v3 333
        namespace import ::test_ns_2::*
	variable v3 333
	namespace import ::test_ns_2::*
    }
} -body {
    namespace eval test_ns_3 {
        list [catch {namespace which -variable env } msg] $msg \
             [namespace which -variable v3] \
             [namespace which -variable ::test_ns_2::v2] \
             [catch {namespace which -variable ::test_ns_2::noSuchVar} msg] $msg
	list [catch {namespace which -variable env } msg] $msg \
	     [namespace which -variable v3] \
	     [namespace which -variable ::test_ns_2::v2] \
	     [catch {namespace which -variable ::test_ns_2::noSuchVar} msg] $msg
    }
} -result {0 {} ::test_ns_3::v3 ::test_ns_2::v2 0 {}}

test namespace-35.1 {FreeNsNameInternalRep, resulting ref count > 0} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
    namespace eval test_ns_1 {
        proc p {} {
            namespace delete [namespace current]
            return [namespace current]
        }
	proc p {} {
	    namespace delete [namespace current]
	    return [namespace current]
	}
    }
    test_ns_1::p
} -result {::test_ns_1}
test namespace-35.2 {FreeNsNameInternalRep, resulting ref count == 0} {
    namespace eval test_ns_1 {
        proc q {} {
            return [namespace current]
        }
	proc q {} {
	    return [namespace current]
	}
    }
    list [test_ns_1::q] \
         [namespace delete test_ns_1] \
         [catch {test_ns_1::q} msg] $msg
	 [namespace delete test_ns_1] \
	 [catch {test_ns_1::q} msg] $msg
} {::test_ns_1 {} 1 {invalid command name "test_ns_1::q"}}

catch {unset x}
catch {unset y}
test namespace-36.1 {DupNsNameInternalRep} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_1 {}
    set x "::test_ns_1"
    list [namespace parent $x] [set y $x] [namespace parent $y]
} {:: ::test_ns_1 ::}
catch {unset x}
catch {unset y}

test namespace-37.1 {SetNsNameFromAny, ns name found} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval test_ns_1::test_ns_2 {}
    namespace eval test_ns_1 {
        namespace children ::test_ns_1
	namespace children ::test_ns_1
    }
} {::test_ns_1::test_ns_2}
test namespace-37.2 {SetNsNameFromAny, ns name not found} -body {
    namespace eval test_ns_1 {
        namespace children ::test_ns_1::test_ns_foo
	namespace children ::test_ns_1::test_ns_foo
    }
} -returnCodes error -result {namespace "::test_ns_1::test_ns_foo" not found}

test namespace-38.1 {UpdateStringOfNsName} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    ;# Tcl_NamespaceObjCmd calls UpdateStringOfNsName to get subcmd name
    list [namespace eval {} {namespace current}] \
         [namespace eval {} {namespace current}]
	 [namespace eval {} {namespace current}]
} {:: ::}

test namespace-39.1 {NamespaceExistsCmd} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    namespace eval ::test_ns_z::test_me { variable foo }
    list [namespace exists ::] \
	    [namespace exists ::bogus_namespace] \
1853
1854
1855
1856
1857
1858
1859


















1860
1861
1862
1863
1864
1865
1866
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    namespace ensemble configure n -subcommands $lst -map $lst
} -body {
    n one
} -cleanup {
    namespace delete n
    unset -nocomplain lst
} -returnCodes error -match glob -result {invalid command name *three*}


test namespace-42.11 {
	ensembles: prefix matching segmentation fault

	issue ccc448a6bfd59cbd
} -body {
    namespace eval n1 {
	namespace ensemble create
	namespace export *
	proc p1 args {error success}
    }
    # segmentation fault only occurs in the non-byte-compiled path, so avoid
    # byte compilation
    set cmd {namespace eva n1 {[namespace parent]::n1 p1}}
    {*}$cmd
} -returnCodes error -result success


test namespace-43.1 {ensembles: dict-driven} {
    namespace eval ns {
	namespace export x*
	proc x1 {} {format 1}
	proc x2 {} {format 2}
	namespace ensemble create -map {a x1 b x2}
2731
2732
2733
2734
2735
2736
2737
2738





2739
2740
2741
2742
2743
2744
2745
2811
2812
2813
2814
2815
2816
2817

2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829







-
+
+
+
+
+







    }
} -result {2 {} 2} -cleanup {
    catch {namespace delete ::test_ns_1}
    catch {namespace delete ::test_ns_2}
    catch {namespace delete ::test_ns_3}
    catch {namespace delete ::test_ns_4}
}
test namespace-51.13 {name resolution path control} -body {
test namespace-51.13 {
    name resolution path control
    when the trace fires, ns_2 is being deleted but isn't gone yet, and is
    still visible for the trace
} -body {
    set ::result {}
    namespace eval ::test_ns_1 {
	proc foo {} {lappend ::result 1}
    }
    namespace eval ::test_ns_2 {
	proc foo {} {lappend ::result 2}
	trace add command foo delete "namespace eval ::test_ns_3 foo;#"
2754
2755
2756
2757
2758
2759
2760
2761
2762

2763
2764
2765
2766
2767
2768
2769
2838
2839
2840
2841
2842
2843
2844


2845
2846
2847
2848
2849
2850
2851
2852







-
-
+







    namespace eval ::test_ns_4 {
	namespace path {::test_ns_2 ::test_ns_3 ::test_ns_1}
	proc bar {} {
	    list [foo] [namespace delete ::test_ns_2] [foo]
	}
	bar
    }
    # Should the result be "2 {} {2 3 2 1}" instead?
} -result {2 {} {2 3 1 1}} -cleanup {
} -result {2 {} {2 3 2 1}} -cleanup {
    catch {namespace delete ::test_ns_1}
    catch {namespace delete ::test_ns_2}
    catch {namespace delete ::test_ns_3}
    catch {namespace delete ::test_ns_4}
}
test namespace-51.14 {name resolution path control} -setup {
    foreach cmd [info commands foo*] {
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174




3175
3176
3177
3178
3179
3180
3181
3247
3248
3249
3250
3251
3252
3253




3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264







-
-
-
-
+
+
+
+







    0 {x1 x1 x1 x1 x1}}
test namespace-53.8 {ensemble: unknown handler changing -parameters} -setup {
    namespace eval ns {
	namespace export x*
	proc x1 {a1} {list 1 $a1}
	proc Magic {ensemble subcmd args} {
	    namespace ensemble configure $ensemble\
              -parameters [lrange p1 [llength [
                namespace ensemble configure $ensemble -parameters
              ]] 0]
            list
	      -parameters [lrange p1 [llength [
		namespace ensemble configure $ensemble -parameters
	      ]] 0]
	    list
	}
	namespace ensemble create -unknown ::ns::Magic
    }
} -body {
    set result {}
    lappend result [catch {ns x1 x2} msg] $msg [namespace ensemble configure ns -parameters]
    lappend result [catch {ns x2 x1} msg] $msg [namespace ensemble configure ns -parameters]
3189
3190
3191
3192
3193
3194
3195
3196
3197


3198
3199
3200
3201
3202
3203
3204
3272
3273
3274
3275
3276
3277
3278


3279
3280
3281
3282
3283
3284
3285
3286
3287







-
-
+
+







test namespace-53.9 {ensemble: unknown handler changing -parameters,\
  thereby eating all args} -setup {
    namespace eval ns {
	namespace export x*
	proc x1 {args} {list 1 $args}
	proc Magic {ensemble subcmd args} {
	    namespace ensemble configure $ensemble\
              -parameters {p1 p2 p3 p4 p5}
            list
	      -parameters {p1 p2 p3 p4 p5}
	    list
	}
	namespace ensemble create -unknown ::ns::Magic
    }
} -body {
    set result {}
    lappend result [catch {ns x1 x2} msg] $msg [namespace ensemble configure ns -parameters]
    lappend result [catch {ns x2 x1} msg] $msg [namespace ensemble configure ns -parameters]
3283
3284
3285
3286
3287
3288
3289
















3290
3291
3292
3293
3294
3295
3296
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    rename getbytes {}
    unset i ns start end
} -result 0

test namespace-55.1 {compiled ensembles inside compiled ensembles: Bug 6d2f249a01} {
    info class [format %s constructor] oo::object
} ""

test namespace-55.2 {compiled ensembles inside safe interpreters (for safe sub-commands), bug [1095bf7f756f9aed]} -setup {
    interp create -safe si
    set code {
	proc test_comp_dict d { dict for {k v} $d {expr $v} }
	regexp -inline {Command 1:(?:[^\n]*\n){1,5}} [::tcl::unsupported::disassemble proc test_comp_dict]
    }
} -body {
    set a [   eval $code]
    set b [si eval $code]
    list [expr {$a eq $b}] [regexp { dictFirst } $a] [regexp { dictFirst } $b] $a $b
} -cleanup {
    rename test_comp_dict {}
    unset -nocomplain code a b
    interp delete si
} -match glob -result {1 1 1 *}

test namespace-56.1 {bug f97d4ee020: mutually-entangled deletion} {
    namespace eval ::testing {
	proc abc {} {}
	proc def {} {}
	trace add command abc delete "rename ::testing::def {}; #"
	trace add command def delete "rename ::testing::abc {}; #"
3348
3349
3350
3351
3352
3353
3354





































3355
3356
3357
3358
3359
3360
3361
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







} -body {
    namespace-56.5 cmd
} -cleanup {
    namespace delete namespace-56.5
} -result 1


test namespace-56.6 {
	Namespace deletion traces on both the original routine and the imported
	routine should run without any memory error under a debug build.
} -body {
	variable res {}

	proc ondelete {old new op} {
	    variable res
	    set tail [namespace tail $old]
	    set up [namespace tail [namespace qualifiers $old]]
	    lappend res [list $up $tail]
	}


	namespace eval ns1 {} {
		namespace export *
		proc p1 {} {
			namespace upvar [namespace parent] res res
			incr res
		}
		trace add command p1 delete ondelete
	}

	namespace eval ns2 {} {
		namespace import [namespace parent]::ns1::p1
		trace add command p1 delete ondelete
	}

	namespace delete ns1
	namespace delete ns2
	after 1
	return $res
} -cleanup {
	unset res
	rename ondelete {}
} -result {{ns1 p1} {ns2 p1}}


test namespace-57.0 {
    an imported alias should be usable in the deletion trace for the alias

    see 29e8848eb976
} -body {
    variable res {}

Changes to tests/notify.test.

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
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










-
+










-
+







#  -*- tcl -*-
#
# notify.test --
#
# This file tests several functions in the file, 'generic/tclNotify.c'.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 2003 by Kevin B. Kenny.  All rights reserved.
# Copyright © 2003 Kevin B. Kenny.  All rights reserved.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testevent [llength [info commands testevent]]

test notify-1.1 {Tcl_QueueEvent and delivery of a single event} \
    -constraints {testevent} \
    -body {
	set delivered {}

Changes to tests/nre.test.

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

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
-
+





-
+










-
+







# Commands covered:  proc, apply, [interp alias], [namespce import]
# Commands covered:  proc, apply, [interp alias], [namespace import]
#
# This file contains a collection of tests for the non-recursive executor that
# avoids recursive calls to TEBC. Only the NRE behaviour is tested here, the
# actual command functionality is tested in the specific test file.
#
# Copyright (c) 2008 by Miguel Sofer.
# Copyright © 2008 Miguel Sofer.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testnrelevels [llength [info commands testnrelevels]]

#
# The tests that risked blowing the C stack on failure have been removed: we
# can now actually measure using testnrelevels.
#

Changes to tests/obj.test.

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
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
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
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







-
-
+
+










-
+


-





-






-
-
+
+











-
+


-
+







# Functionality covered: this file contains a collection of tests for the
# procedures in tclObj.c that implement Tcl's basic type support and the
# type managers for the types boolean, double, and integer.
#
# Sourcing this file into Tcl runs the tests and generates output for
# errors. No output means no errors were found.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testobj [llength [info commands testobj]]
testConstraint longIs32bit [expr {$tcl_platform(wordSize) == 4}]
testConstraint wideIs64bit [expr {wide(0x8000000000000000) < 0}]

test obj-1.1 {Tcl_AppendAllObjTypes, and InitTypeTable, Tcl_RegisterObjType} testobj {
    set r 1
    foreach {t} {
	bytearray
	bytecode
	cmdName
	dict
	regexp
	string
    } {
        set first [string first $t [testobj types]]
        set r [expr {$r && ($first >= 0)}]
	set first [string first $t [testobj types]]
	set r [expr {$r && ($first >= 0)}]
    }
    set result $r
} {1}

test obj-2.1 {Tcl_GetObjType error} testobj {
    list [testintobj set 1 0] [catch {testobj convert 1 foo} msg] $msg
} {0 1 {no type foo found}}
test obj-2.2 {Tcl_GetObjType and Tcl_ConvertToType} testobj {
    set result ""
    lappend result [testobj freeallvars]
    lappend result [testintobj set 1 12]
    lappend result [testobj convert 1 bytearray]
    lappend result [testobj convert 1 string]
    lappend result [testobj type 1]
    lappend result [testobj refcount 1]
} {{} 12 12 bytearray 3}
} {{} 12 12 string 3}

test obj-4.1 {Tcl_NewObj and AllocateFreeObjects} testobj {
    set result ""
    lappend result [testobj freeallvars]
    lappend result [testobj newobj 1]
    lappend result [testobj type 1]
    lappend result [testobj refcount 1]
215
216
217
218
219
220
221
222
223


224
225
226
227
228
229
230
213
214
215
216
217
218
219


220
221
222
223
224
225
226
227
228







-
-
+
+







    lappend result [testdoubleobj set 1 3.14159]
    lappend result [testbooleanobj not 1]    ;# converts with SetBooleanFromAny
    lappend result [testobj type 1]
} {3.14159 0 int}
test obj-13.3 {SetBooleanFromAny, special case strings representing booleans} testobj {
    set result ""
    foreach s {yes no true false on off} {
        teststringobj set 1 $s
        lappend result [testbooleanobj not 1]
	teststringobj set 1 $s
	lappend result [testbooleanobj not 1]
    }
    lappend result [testobj type 1]
} {0 1 0 1 0 1 int}
test obj-13.4 {SetBooleanFromAny, recompute string rep then parse it} testobj {
    set result ""
    lappend result [testintobj set 1 456]
    lappend result [testintobj div10 1]
247
248
249
250
251
252
253
254

255
256
257

258
259
260
261
262
263
264
245
246
247
248
249
250
251

252
253
254

255
256
257
258
259
260
261
262







-
+


-
+







    set result ""
    lappend result [testobj newobj 1]
    lappend result [catch {testbooleanobj not 1} msg]
    lappend result $msg
} {{} 1 {expected boolean value but got ""}}
test obj-13.8 {SetBooleanFromAny, unicode strings} testobj {
    set result ""
    lappend result [teststringobj set 1 1\u7777]
    lappend result [teststringobj set 1 1ç·]
    lappend result [catch {testbooleanobj not 1} msg]
    lappend result $msg
} "1\u7777 1 {expected boolean value but got \"1\u7777\"}"
} "1ç· 1 {expected boolean value but got \"1ç·\"}"

test obj-14.1 {UpdateStringOfBoolean} testobj {
    set result ""
    lappend result [testbooleanobj set 1 0]
    lappend result [testbooleanobj not 1]
    lappend result [testbooleanobj get 1]    ;# must update string rep
} {0 1 1}
544
545
546
547
548
549
550
551

552
553
554
555

556
557
558
559
560
561
562
563

564
565
566
567

568
569
570
571

572
573
574
575
576
577
578
542
543
544
545
546
547
548

549
550
551
552

553
554
555
556
557
558
559
560

561
562
563
564

565
566
567
568

569
570
571
572
573
574
575
576







-
+



-
+







-
+



-
+



-
+







    set x {}
    for {set i 0} {$i<100000} {incr i} {
	set x [list $x {}]
    }
    unset x
} {}

test obj-33.1 {integer overflow on input} {longIs32bit wideIs64bit} {
test obj-33.1 {integer overflow on input} {wideIs64bit} {
    set x 0x8000; append x 0000
    list [string is integer $x] [expr { wide($x) }]
} {1 2147483648}
test obj-33.2 {integer overflow on input} {longIs32bit wideIs64bit} {
test obj-33.2 {integer overflow on input} {wideIs64bit} {
    set x 0xffff; append x ffff
    list [string is integer $x] [expr { wide($x) }]
} {1 4294967295}
test obj-33.3 {integer overflow on input} {
    set x 0x10000; append x 0000
    list [string is integer $x] [expr { wide($x) }]
} {1 4294967296}
test obj-33.4 {integer overflow on input} {longIs32bit wideIs64bit} {
test obj-33.4 {integer overflow on input} {wideIs64bit} {
    set x -0x8000; append x 0000
    list [string is integer $x] [expr { wide($x) }]
} {1 -2147483648}
test obj-33.5 {integer overflow on input} {longIs32bit wideIs64bit} {
test obj-33.5 {integer overflow on input} {wideIs64bit} {
    set x -0x8000; append x 0001
    list [string is integer $x] [expr { wide($x) }]
} {1 -2147483649}
test obj-33.6 {integer overflow on input} {longIs32bit wideIs64bit} {
test obj-33.6 {integer overflow on input} {wideIs64bit} {
    set x -0xffff; append x ffff
    list [string is integer $x] [expr { wide($x) }]
} {1 -4294967295}
test obj-33.7 {integer overflow on input} {
    set x -0x10000; append x 0000
    list [string is integer $x] [expr { wide($x) }]
} {1 -4294967296}

Changes to tests/oo.test.

1
2
3
4
5

6
7
8
9
10

11
12
13
14














15
16
17
18
19
20
21
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
30
31
32
33
34
35




-
+




-
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+







# This file contains a collection of tests for Tcl's built-in object system.
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2006-2013 Donal K. Fellows
# Copyright © 2006-2013 Donal K. Fellows
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require TclOO 1.0.3
package require tcl::oo 1.3.0
if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}

# A helper for intercepting background errors
proc ::bgerrorIntercept {varName body} {
    set old [interp bgerror {}]
    interp bgerror {} [list apply {{var msg args} {
	upvar #0 $var v
	lappend v $msg
    }} $varName]
    try {
	uplevel 1 $body
    } finally {
	interp bgerror {} $old
    }
}

# The foundational objects oo::object and oo::class are sensitive to reference
# counting errors and are deallocated only when an interp is deleted, so in
# this test suite, interp creation and interp deletion are often used in
# leaktests in order to leverage this sensitivity.

testConstraint memory [llength [info commands memory]]
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
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







-
+






-
+






-
+







	return [expr {$end - $tmp}]
    }
}

test oo-0.1 {basic test of OO's ability to clean up its initial state} {
    interp create t
    t eval {
	package require TclOO
	package require tcl::oo
    }
    interp delete t
} {}
test oo-0.2 {basic test of OO's ability to clean up its initial state} {
    set i [interp create]
    interp eval $i {
	package require TclOO
	package require tcl::oo
	namespace delete ::
    }
    interp delete $i
} {}
test oo-0.3 {basic test of OO's ability to clean up its initial state} -body {
    leaktest {
        [oo::object new] destroy
	[oo::object new] destroy
    }
} -constraints memory -result 0
test oo-0.4 {basic test of OO's ability to clean up its initial state} -body {
    leaktest {
	oo::class create foo
	foo new
	foo destroy
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
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







-
+










-
+


















-
-
-
-
+
+
+
+







	interp delete foo
    }
} 0
test oo-0.6 {cleaning the core class pair; way #1} -setup {
    interp create t
} -body {
    t eval {
	package require TclOO
	package require tcl::oo
	namespace path oo
	list [catch {class destroy} m] $m [catch {object destroy} m] $m
    }
} -cleanup {
    interp delete t
} -result {0 {} 1 {invalid command name "object"}}
test oo-0.7 {cleaning the core class pair; way #2} -setup {
    interp create t
} -body {
    t eval {
	package require TclOO
	package require tcl::oo
	namespace path oo
	list [catch {object destroy} m] $m [catch {class destroy} m] $m
    }
} -cleanup {
    interp delete t
} -result {0 {} 1 {invalid command name "class"}}
test oo-0.8 {leak in variable management} -setup {
    oo::class create foo
} -constraints memory -body {
    oo::define foo {
	constructor {} {
	    variable v 0
	}
    }
    leaktest {[foo new] destroy}
} -cleanup {
    foo destroy
} -result 0
test oo-0.9 {various types of presence of the TclOO package} {
    list [lsearch -nocase -all -inline [package names] tcloo] \
	[package present TclOO] [expr {$::oo::patchlevel in [package versions TclOO]}]
} [list TclOO $::oo::patchlevel 1]
test oo-0.9 {various types of presence of the tcl::oo package} {
    list [lsearch -nocase -all -inline [package names] tcl::oo] \
	[package present tcl::oo] [expr {$::oo::patchlevel in [package versions tcl::oo]}]
} [list tcl::oo $::oo::patchlevel 1]

test oo-1.1 {basic test of OO functionality: no classes} {
    set result {}
    lappend result [oo::object create foo]
    lappend result [oo::objdefine foo {
	method bar args {
	    global result
372
373
374
375
376
377
378
379
380













































































381
382
383
384
385
386

387
388
389
390
391
392
393
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
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
467
468
469
470
471
472
473
474

475
476
477
478
479
480
481
482







-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+







	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::object ::oo::singleton} {::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::abstract ::oo::singleton} {} {} {} {} {} ::oo::object ::oo::object ::oo::class ::oo::class ::oo::class}

} -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}
	method make {i} {set n $i; [self class] create xyz}
	destructor {lappend ::deathOrder $n}
    }
    apply {n {
	set ::deathOrder {}
	# Make some "nested" objects
	set base [abc new]
	for {set i 1; set obj $base} {$i < $n} {incr i} {
	     set obj [$obj make $i]
	}
	# Kill them all in one go; should come apart in right order!
	$base destroy
	return $::deathOrder
    }} 5
} -cleanup {
    parent destroy
} -result {1 2 3 4 0}
test oo-1.23 {basic test of OO functionality: deep nested ownership} -setup {
    oo::class create parent
} -constraints knownBug -body {
    oo::class create abc {
	superclass parent
	method make {} {[self class] create xyz}
	destructor {incr ::count}
    }
    apply {n {
	set ::count 0
	# Make a lot of "nested" objects
	set base [abc new]
	for {set i 1; set obj $base} {$i < $n} {incr i} {
	     set obj [$obj make]
	}
	# Kill them all in one go; should not crash!
	$base destroy
	return [expr {$n - $::count}]
    }} 10000
} -cleanup {
    parent destroy
} -result 0
test oo-1.24 {basic test of OO functionality: deep nested ownership} -setup {
    oo::class create parent
} -constraints knownBug -body {
    oo::class create abc {
	superclass parent
	self method make {} {oo::copy [self] xyz}
    }
    apply {n {
	# Make a lot of "nested" objects
	set base abc
	lappend lst $base [info object namespace $base]
	for {set i 1; set obj $base} {$i < $n} {incr i} {
	     set obj [$obj make]
	     lappend lst $obj [info object namespace $obj]
	}
	# Kill them all in one go; should not crash!
	$base destroy
	# How many classes still there (cnt must remain 0)
	set cnt 0
	foreach {obj ns} $lst {
	    if {[namespace which -command $obj] ne "" || [namespace exists $ns]} {
		incr cnt
	    }
	}
	return $cnt
    }} 10000
} -cleanup {
    parent destroy
} -result 0

test oo-2.1 {basic test of OO functionality: constructor} -setup {
    # This is a bit complex because it needs to run in a sub-interp as
    # we're modifying the root object class's constructor
    interp create subinterp
    subinterp eval {
	package require TclOO
	package require tcl::oo
    }
} -body {
    subinterp eval {
	oo::define oo::object constructor {} {
	    lappend ::result [info level 0]
	}
	lappend result 1
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
599
600
601
602
603
604
605

606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625

626
627
628
629
630
631
632
633







-
+



















-
+







} -result {{in A} ::a 1 {failure in A} {in B ::b} ::b 1 {failure in B}}

test oo-3.1 {basic test of OO functionality: destructor} -setup {
    # This is a bit complex because it needs to run in a sub-interp as we're
    # modifying the root object class's constructor
    interp create subinterp
    subinterp eval {
	package require TclOO
	package require tcl::oo
    }
} -body {
    subinterp eval {
	oo::define oo::object destructor {
	    lappend ::result died
	}
	lappend result 1 [oo::object create foo]
	lappend result 2 [rename foo {}]
	oo::define oo::object destructor {}
	return $result
    }
} -cleanup {
    interp delete subinterp
} -result {1 ::foo died 2 {}}
test oo-3.2 {basic test of OO functionality: destructor} -setup {
    # This is a bit complex because it needs to run in a sub-interp as
    # we're modifying the root object class's constructor
    interp create subinterp
    subinterp eval {
	package require TclOO
	package require tcl::oo
    }
} -body {
    subinterp eval {
	oo::define oo::object destructor {
	    lappend ::result died
	}
	lappend result 1 [oo::object create foo]
663
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
752
753
754
755
756
757
758


759
760

761
762
763



764
765
766
767
768
769
770
771


772
773

774
775
776
777



778
779
780
781
782
783
784
785
786
787
788
789







-
-


-


+
-
-
-
+
+
+
+
+
+


-
-


-


+
+
-
-
-
+
+
+
+
+







    cls destroy
} -body {
    oo::define cls destructor {error foo}
    list [catch {[cls create obj] destroy} msg] $msg [info commands obj]
} -result {1 foo {}}
test oo-3.7 {basic test of OO functionality: errors in destructor} -setup {
    oo::class create cls
    set result {}
    proc bgerror msg {lappend ::result $msg}
} -cleanup {
    cls destroy
    rename bgerror {}
} -body {
    oo::define cls destructor {error foo}
    bgerrorIntercept result {
    list [rename [cls create obj] {}] \
	[update idletasks] $result [info commands obj]
} -result {{} {} foo {}}
	set result [cls create obj]
	lappend result [rename obj {}]
	update idletasks
	lappend result [info commands obj]
    }
} -result {::obj {} foo {}}
test oo-3.8 {basic test of OO functionality: errors in destructor} -setup {
    oo::class create cls
    set result {}
    proc bgerror msg {lappend ::result $msg}
} -cleanup {
    cls destroy
    rename bgerror {}
} -body {
    oo::define cls destructor {error foo}
    bgerrorIntercept result {
	set result [cls create obj]
    list [namespace delete [info object namespace [cls create obj]]] \
	[update idletasks] $result [info commands obj]
} -result {{} {} foo {}}
	lappend result [namespace delete [info object namespace obj]]
	update idletasks
	lappend result [info commands obj]
    }
} -result {::obj {} foo {}}
test oo-3.9 {Bug 2944404: deleting the object in the destructor} -setup {
    oo::class create cls
    set result {}
} -body {
    oo::define cls {
	destructor {
	    lappend ::result in destructor
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464



1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479













1480
1481
1482
1483
1484
1485
1486
1546
1547
1548
1549
1550
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







-
-
-
+
+
+


-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+







	oo::class create spong {superclass boo}
	return
    }
} -result {}
test oo-7.10 {OO: next after object deletion, bug [135804138e]} -setup {
    set ::result ""
    oo::class create c1 {
        method m1 {} {
           lappend ::result c1::m1
        }
	method m1 {} {
	   lappend ::result c1::m1
	}
    }
    oo::class create c2 {
        superclass c1
        destructor {
            lappend ::result c2::destructor
            my m1
            lappend ::result /c2::destructor
        }
        method m1 {} {
            lappend ::result c2::m1
            rename [self] {}
            lappend ::result no-self
            next
            lappend ::result /c2::m1
        }
	superclass c1
	destructor {
	    lappend ::result c2::destructor
	    my m1
	    lappend ::result /c2::destructor
	}
	method m1 {} {
	    lappend ::result c2::m1
	    rename [self] {}
	    lappend ::result no-self
	    next
	    lappend ::result /c2::m1
	}
    }
} -body {
    c2 create o
    lappend ::result [catch {o m1} msg] $msg
} -cleanup {
    c1 destroy
    unset ::result
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
1749
1750
1751
1752
1753
1754
1755
1756






































1757
1758
1759
1760
1761
1762
1763
1772
1773
1774
1775
1776
1777
1778


1779

1780
1781
1782
1783
1784
1785
1786

1787




1788


1789
1790
1791
1792
1793
1794
1795
1796
1797
1798

1799




1800


1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812

1813




1814


1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875







-
-
+
-







-
+
-
-
-
-
+
-
-










-
+
-
-
-
-
+
-
-












-
+
-
-
-
-
+
-
-
















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    }}}

    rename obj1 {}
    # No segmentation fault
    return done
} done

test oo-11.6.1 {
    OO: cleanup of when an class is mixed into itself
test oo-11.6.1 {OO: cleanup of when an class is mixed into itself} -constraints memory -body {
} -constraints memory -body {
    leaktest {
	interp create interp1
	oo::class create obj1
	::oo::define obj1 {self mixin [uplevel 1 {namespace which obj1}]}
	rename obj1 {}
	interp delete interp1
    }
} -result 0 -cleanup {
} -result 0
}

test oo-11.6.2 {
    OO: cleanup ReleaseClassContents() where class is mixed into one of its
test oo-11.6.2 {OO: cleanup ReleaseClassContents() where class is mixed into one of its instances} -constraints memory -body {
    instances
} -constraints memory -body {
    leaktest {
	interp create interp1
	interp1 eval {
	    oo::class create obj1
	    ::oo::copy obj1 obj2
	    rename obj2 {}
	    rename obj1 {}
	}
	interp delete interp1
    }
} -result 0 -cleanup {
} -result 0
}

test oo-11.6.3 {
    OO: cleanup ReleaseClassContents() where class is mixed into one of its
test oo-11.6.3 {OO: cleanup ReleaseClassContents() where class is mixed into one of its instances} -constraints memory -body {
    instances
} -constraints memory -body {
    leaktest {
	interp create interp1
	interp1 eval {
	    oo::class create obj1
	    ::oo::define obj1 {self mixin [uplevel 1 {namespace which obj1}]}

	    ::oo::copy obj1 obj2
	    rename obj2 {}
	    rename obj1 {}
	}
	interp delete interp1
    }
} -result 0 -cleanup {
} -result 0
}

test oo-11.6.4 {
    OO: cleanup ReleaseClassContents() where class is mixed into one of its
test oo-11.6.4 {OO: cleanup ReleaseClassContents() where class is mixed into one of its instances} -body {
    instances
} -body {
    oo::class create obj1
    ::oo::define obj1 {self mixin [self]}

    ::oo::copy obj1 obj2
    ::oo::objdefine obj2 {mixin [self]}

    ::oo::copy obj2 obj3
    rename obj3 {}
    rename obj2 {}

    # No segmentation fault
    return done
} -result done -cleanup {
    rename obj1 {}
}

test oo-11.7 {Bug 154f0982f2: createWithNamespace and an existing namespace} -setup {
    oo::class create Aclass {
	self export createWithNamespace
	method ns {} {namespace current}
    }
} -body {
    namespace eval test_oo117 {variable name [namespace current]}
    list [Aclass createWithNamespace aInstance $test_oo117::name] [aInstance ns]
} -returnCodes error -cleanup {
    Aclass destroy
    catch {namespace delete test_oo117}
} -result {can't create namespace "::test_oo117": already exists}
test oo-11.8 {Bug 708422: unset traces in deletion shouldn't crash} -setup {
    oo::class create foo {
	self export createWithNamespace
	method dummy {} {}
    }
    set result {}
} -body {
    oo::define foo {
	variable x
	constructor {} {
	    trace add variable x unset [list apply {{self ns args} {
		global result
		lappend result [info object isa object $self]
		lappend result [namespace exists $ns]
		# Method dispatch fails; too much gone in this case
		catch {$self dummy} msg
		lappend result $msg
	    }} [self] [self namespace]]
	}
    }
    [foo createWithNamespace bar oo-11.8] destroy
    return $result
} -cleanup {
    foo destroy
} -result {1 0 {impossible to invoke method "dummy": no defined method or unknown method}}

test oo-12.1 {OO: filters} {
    oo::class create Aclass
    Aclass create Aobject
    oo::define Aclass {
	method concatenate args {
	    global result
	    lappend result {*}$args
1963
1964
1965
1966
1967
1968
1969
1970

1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982

1983
1984
1985
1986
1987
1988
1989
2075
2076
2077
2078
2079
2080
2081

2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093

2094
2095
2096
2097
2098
2099
2100
2101







-
+











-
+







test oo-13.5 {OO: changing an object's class: non-class to class} -setup {
    oo::object create fooObj
} -body {
    oo::objdefine fooObj {
	class oo::class
    }
    oo::define fooObj {
	method x {} {expr 1+2+3}
	method x {} {expr {1+2+3}}
    }
    [fooObj new] x
} -cleanup {
    fooObj destroy
} -result 6
test oo-13.6 {OO: changing an object's class: class to non-class} -setup {
    oo::class create foo
    unset -nocomplain ::result
} -body {
    set result dangling
    oo::define foo {
	method x {} {expr 1+2+3}
	method x {} {expr {1+2+3}}
    }
    oo::class create boo {
	superclass foo
	destructor {set ::result "ok"}
    }
    boo new
    foo create bar
1998
1999
2000
2001
2002
2003
2004
2005

2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019

2020
2021
2022
2023
2024
2025
2026
2110
2111
2112
2113
2114
2115
2116

2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130

2131
2132
2133
2134
2135
2136
2137
2138







-
+













-
+







test oo-13.7 {OO: changing an object's class} -setup {
    oo::class create foo
    oo::class create bar
    unset -nocomplain result
} -body {
    oo::define bar method x {} {return ok}
    oo::define foo {
	method x {} {expr 1+2+3}
	method x {} {expr {1+2+3}}
	self mixin foo
    }
    lappend result [foo x]
    oo::objdefine foo class bar
    lappend result [foo x]
} -cleanup {
    foo destroy
    bar destroy
} -result {6 ok}
test oo-13.8 {OO: changing an object's class to itself} -setup {
    oo::class create foo
} -body {
    oo::define foo {
	method x {} {expr 1+2+3}
	method x {} {expr {1+2+3}}
    }
    oo::objdefine foo class foo
} -cleanup {
    foo destroy
} -returnCodes error -result {may not change classes into an instance of themselves}
test oo-13.9 {OO: changing an object's class: roots are special} -setup {
    set i [interp create]
2214
2215
2216
2217
2218
2219
2220

























2221
2222
2223
2224
2225
2226
2227
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    oo::class create cls {
	superclass parent
	mixin mix
	method test {} {lappend ::result cls; next; return $::result}
    }
    [cls new] test
} -result {mix cls}
test oo-14.9 {OO: class mixins must be unique in list} -setup {
    oo::class create parent
} -body {
    oo::class create A {superclass parent}
    oo::class create B {
	superclass parent
	mixin A
    }
    oo::define B mixin -append A
} -returnCodes error -cleanup {
    parent destroy
} -result {class should only be a direct mixin once}
test oo-14.10 {OO: instance mixins must be unique in list} -setup {
    oo::class create parent
} -body {
    oo::class create A {superclass parent}
    oo::class create B {
	superclass parent
	constructor {} {oo::objdefine [self] mixin A}
    }
    B create obj
    oo::objdefine obj {mixin -append A}
} -returnCodes error -cleanup {
    parent destroy
} -result {class should only be a direct mixin once}

test oo-15.1 {OO: object cloning} {
    oo::class create Aclass
    oo::define Aclass method test {} {lappend ::result [self object]->test}
    Aclass create Ainstance
    set result {}
    Ainstance test
2454
2455
2456
2457
2458
2459
2460
2461

2462
2463
2464
2465
2466
2467
2468
2591
2592
2593
2594
2595
2596
2597

2598
2599
2600
2601
2602
2603
2604
2605







-
+







    while executing
\"info object\""
test oo-16.2 {OO: object introspection} -body {
    info object class NOTANOBJECT
} -returnCodes 1 -result {NOTANOBJECT does not refer to an object}
test oo-16.3 {OO: object introspection} -body {
    info object gorp oo::object
} -returnCodes 1 -result {unknown or ambiguous subcommand "gorp": must be call, class, creationid, definition, filters, forward, isa, methods, methodtype, mixins, namespace, variables, or vars}
} -returnCodes 1 -result {unknown or ambiguous subcommand "gorp": must be call, class, creationid, definition, filters, forward, isa, methods, methodtype, mixins, namespace, properties, variables, or vars}
test oo-16.4 {OO: object introspection} -setup {
    oo::class create meta { superclass oo::class }
    [meta create instance1] create instance2
} -body {
    list [list [info object class oo::object] \
	      [info object class oo::class] \
	      [info object class meta] \
2673
2674
2675
2676
2677
2678
2679
2680

2681
2682
2683
2684
2685
2686
2687
2810
2811
2812
2813
2814
2815
2816

2817
2818
2819
2820
2821
2822
2823
2824







-
+







} -body {
    info class superclass foo
} -returnCodes 1 -cleanup {
    foo destroy
} -result {"foo" is not a class}
test oo-17.4 {OO: class introspection} -body {
    info class gorp oo::object
} -returnCodes 1 -result {unknown or ambiguous subcommand "gorp": must be call, constructor, definition, definitionnamespace, destructor, filters, forward, instances, methods, methodtype, mixins, subclasses, superclasses, or variables}
} -returnCodes 1 -result {unknown or ambiguous subcommand "gorp": must be call, constructor, definition, definitionnamespace, destructor, filters, forward, instances, methods, methodtype, mixins, properties, subclasses, superclasses, or variables}
test oo-17.5 {OO: class introspection} -setup {
    oo::class create testClass
} -body {
    testClass create foo
    testClass create bar
    testClass create spong
    lsort [info class instances testClass]
2771
2772
2773
2774
2775
2776
2777
























2778
2779
2780
2781
2782
2783
2784
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    c create o
} -body {
    lsort [info object methods o -all -private]
} -cleanup {
    o destroy
    c destroy
} -result $stdmethods
test oo-17.15 {OO: class method list without -all (bug 36e5517a6850)} -setup {
    oo::class create c
} -body {
    oo::define c {
	method foo {} {}
	method Bar {} {}
	private method gorp {} {}
    }
    list [lsort [info class methods c]] [lsort [info class methods c -private]]
} -cleanup {
    c destroy
} -result {foo {Bar foo}}
test oo-17.16 {OO: instance method list without -all (bug 36e5517a6850)} -setup {
    oo::object create o
} -body {
    oo::objdefine o {
	method foo {} {}
	method Bar {} {}
	private method gorp {} {}
    }
    list [lsort [info object methods o]] [lsort [info object methods o -private]]
} -cleanup {
    o destroy
} -result {foo {Bar foo}}


test oo-18.1 {OO: define command support} {
    list [catch {oo::define oo::object {error foo}} msg] $msg $errorInfo
} {1 foo {foo
    while executing
"error foo"
2930
2931
2932
2933
2934
2935
2936
2937

2938
2939
2940
2941
2942
2943
2944
3091
3092
3093
3094
3095
3096
3097

3098
3099
3100
3101
3102
3103
3104
3105







-
+







"self {error foobar}"
    (in definition script for class "::bar" line 1)
    invoked from within
"oo::define foo {rename ::foo ::bar; self {error foobar}}"}
test oo-18.9 {OO: define/self command support} -setup {
    oo::class create parent
    set c [oo::class create now_this_is_a_very_very_long_class_name_indeed {
        superclass parent
	superclass parent
    }]
} -body {
    catch {oo::define $c {error err}} msg opt
    dict get $opt -errorinfo
} -cleanup {
    parent destroy
} -result {err
2974
2975
2976
2977
2978
2979
2980










2981
2982
2983
2984
2985
2986
2987
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158







+
+
+
+
+
+
+
+
+
+







    parent destroy
} -result {this command cannot be called when the object has been deleted
    while executing
"self {error foobar}"
    (in definition script for class "::foo" line 1)
    invoked from within
"oo::define foo {rename ::foo {}; self {error foobar}}"}
test oo-18.12 {OO: self callable via eval method} -setup {
    oo::class create parent {
	export eval
    }
    parent create ::foo
} -body {
    foo eval { self }
} -cleanup {
    parent destroy
} -result ::foo

test oo-19.1 {OO: varname method} -setup {
    oo::object create inst
    oo::objdefine inst export eval
    set result {}
    inst eval { variable x }
} -body {
3027
3028
3029
3030
3031
3032
3033


























3034
3035
3036
3037
3038
3039
3040
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







} -body {
    testClass create A
    testClass create B
    lsearch [list [A varname foo] [B varname foo]] [B bar A]
} -cleanup {
    testClass destroy
} -result 0
test oo-19.4 {OO: varname ghosts [Bug 74b6110204]} -setup {
    oo::class create testClass {
	export varname
	self export createWithNamespace
    }
    set obj [testClass createWithNamespace testoo19_4 testoo19_4]
    set ns [info object namespace $obj]
} -body {
    set v [$obj varname foo]
    list [namespace which -variable $v] \
	[info exists $v] [namespace which -variable $v]
} -cleanup {
    testClass destroy
} -result {::testoo19_4::foo 0 ::testoo19_4::foo}
test oo-19.5 {OO: varname array elements [Bug 2da1cb0c80]} -setup {
    set obj [oo::object new]
    oo::objdefine $obj export eval varname
} -body {
    $obj eval {
	namespace upvar :: tcl_platform(platform) foo
    }
    $obj varname foo
} -cleanup {
    $obj destroy
} -result ::tcl_platform(platform)
# Test oo-19.5.1 is no longer relevant

test oo-20.1 {OO: variable method} -body {
    oo::class create testClass {
	constructor {} {
	    my variable ok
	    set ok {}
	}
3429
3430
3431
3432
3433
3434
3435

























































































































































































3436
3437
3438
3439
3440
3441
3442
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	lsort {q w e r t y u i o p}; # Overwrite the Tcl stack
	info frame 0
    }
    [c new] test
} -match glob -cleanup {
    c destroy
} -result {* cmd {info frame 0} method test class ::c level 0}
# Common code for oo-22.{3,4,5,6}
oo::class create WorkerBase
oo::class create WorkerSupport {
    superclass oo::class WorkerBase
    variable result stop
    method WithWorkers {nworkers args script} {
	set workers {}
	try {
	    for {set n 1} {$n <= $nworkers} {incr n} {
		lappend workers [set worker [[self] new]]
		$worker schedule {*}$args
	    }
	    return [uplevel 1 $script]
	} finally {
	    foreach worker $workers {$worker destroy}
	}
    }
    method run {nworkers} {
	set result {}
	set stopvar [my varname stop]
	set stop false
	my WithWorkers $nworkers [list my Work [my varname result]] {
	    after idle [namespace code {set stop true}]
	    vwait $stopvar
	}
	return $result
    }
}
oo::class create Worker {
    superclass WorkerBase
    method schedule {args} {
	set coro [namespace current]::coro
	if {![llength [info commands $coro]]} {
	    coroutine $coro {*}$args
	}
    }
    method Work args {error unimplemented}
    method dump {} {
	info frame [expr {[info frame] - 1}]
    }
}
test oo-22.3 {OO and coroutines and info frame: Bug 87271f7cd6} -body {
    # Triggers a crash with incorrectly restored pmPtr->procPtr->cmdPtr
    WorkerSupport create A {
	superclass Worker
	method Work {var} {
	    after 0 [info coroutine]
	    yield
	    lappend $var [my dump]
	}
    }
    A run 2
} -cleanup {
    catch {rename dump {}}
    catch {A destroy}
} -match glob -result {{* method Work class ::A *} {* method Work class ::A *}}
test oo-22.4 {OO and coroutines and info frame: Bug 87271f7cd6} -body {
    # Triggers a crash with incorrectly cloned pmPtr->procPtr->cmdPtr
    WorkerSupport create A {
	superclass Worker
	method Work {var} {
	    after 0 [info coroutine]
	    yield
	    lappend $var [my dump]
	}
    }
    # Copies the methods, changing the declarer
    # Test it works with the source class still around
    oo::copy A B
    B run 2
} -cleanup {
    catch {rename dump {}}
    catch {A destroy}
    catch {B destroy}
} -match glob -result {{* method Work class ::B *} {* method Work class ::B *}}
test oo-22.5 {OO and coroutines and info frame: Bug 87271f7cd6} -body {
    # Triggers a crash with incorrectly cloned pmPtr->procPtr->cmdPtr
    WorkerSupport create A {
	superclass Worker
	method Work {var} {
	    after 0 [info coroutine]
	    yield
	    lappend $var [my dump]
	}
    }
    # Copies the methods, changing the declarer
    # Test it works with the source class deleted
    oo::copy A B
    catch {A destroy}
    B run 2
} -cleanup {
    catch {rename dump {}}
    catch {B destroy}
} -match glob -result {{* method Work class ::B *} {* method Work class ::B *}}
test oo-22.6 {OO and coroutines and info frame: Bug 87271f7cd6} -body {
    # Triggers a crash with incorrectly cloned pmPtr->procPtr->cmdPtr
    WorkerSupport create A {
	superclass Worker
	method Work {var} {
	    after 0 [info coroutine]
	    yield
	    lappend $var [my dump]
	}
    }
    # Copies the methods, changing the declarer
    # Test it works in the original source class with the copy around
    oo::copy A B
    B run 2
    A run 2
} -cleanup {
    catch {rename dump {}}
    catch {A destroy}
    catch {B destroy}
} -match glob -result {{* method Work class ::A *} {* method Work class ::A *}}
WorkerBase destroy
test oo-22.7 {oo::define and info frame: correct argument line} -setup {
    oo::class create C {
	variable base
	constructor {info} {set base [dict get $info line]}
	method Relative {} {
	    set info [next]
	    if {![dict exists $info file]} {
		error "no file-relative line info: $info"
	    }
	    expr {[dict get $info line] - $base}
	}
	filter Relative
    }
} -body {
    C create o [info frame 0]
    oo::define C {
	method line1 {} {info frame 0}
	method line2 {
	} {info frame 0}
	method line3 {
	} {
	    info frame 0
	}
    }
    oo::define C method line4 {} {info frame 0}
    oo::define C method line5 {
    } {info frame 0}
    oo::define C method line6 {
    } {
	info frame 0
    }
    list [o line1] [o line2] [o line3] [o line4] [o line5] [o line6]
} -cleanup {
    C destroy
} -result {2 4 7 10 12 15}
test oo-22.8 {oo::objdefine and info frame: correct argument line} -setup {
    oo::class create C {
	variable base
	constructor {info} {set base [dict get $info line]}
	method Relative {} {
	    set info [next]
	    if {![dict exists $info file]} {
		error "no file-relative line info: $info"
	    }
	    expr {[dict get $info line] - $base}
	}
	filter Relative
    }
} -body {
    C create o [info frame 0]
    oo::objdefine o {
	method line1 {} {info frame 0}
	method line2 {
	} {info frame 0}
	method line3 {
	} {
	    info frame 0
	}
    }
    oo::objdefine o method line4 {} {info frame 0}
    oo::objdefine o method line5 {
    } {info frame 0}
    oo::objdefine o method line6 {
    } {
	info frame 0
    }
    list [o line1] [o line2] [o line3] [o line4] [o line5] [o line6]
} -cleanup {
    C destroy
} -result {2 4 7 10 12 15}

# Prove that the issue in [Bug 1865054] isn't an issue any more
test oo-23.1 {Self-like derivation; complex case!} -setup {
    oo::class create SELF {
	superclass oo::class
	unexport create new
	# Next is just a convenience
4193
4194
4195
4196
4197
4198
4199
4200














4201
4202
4203
4204
4205
4206
4207
4575
4576
4577
4578
4579
4580
4581

4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    set s [SampleSlot new]
}] -body {
    # Method names beginning with "-" are special to slots
    $s -grill q
} -returnCodes error -cleanup [SampleSlotCleanup {
    rename $s {}
}] -result \
    {unknown method "-grill": must be -append, -clear, -prepend, -remove, -set, contents or ops}
    {unknown method "-grill": must be -append, -appendifnew, -clear, -prepend, -remove, -set, contents or ops}
test oo-33.5 {TIP 567: slots -appendifnew} -setup [SampleSlotSetup {
    set s [SampleSlot new]
}] -body {
    list \
	[$s -clear
	 $s contents] \
	[$s -append p q r
	 $s contents] \
	[$s -appendifnew q s r t p
	 $s contents]
} -cleanup [SampleSlotCleanup {
    rename $s {}
}] -result {{} {p q r} {p q r s t}}

test oo-34.1 {TIP 380: slots - presence} -setup {
    set obj [oo::object new]
    set result {}
} -body {
    oo::define oo::object {
	::lappend ::result [::info object class filter]
4216
4217
4218
4219
4220
4221
4222
4223

4224
4225
4226
4227
4228
4229
4230

4231
4232
4233

4234
4235
4236

4237
4238
4239

4240
4241
4242

4243
4244
4245

4246
4247
4248

4249
4250
4251
4252
4253
4254
4255
4611
4612
4613
4614
4615
4616
4617

4618
4619
4620
4621
4622
4623
4624

4625
4626
4627

4628
4629
4630

4631
4632
4633

4634
4635
4636

4637
4638
4639

4640
4641
4642

4643
4644
4645
4646
4647
4648
4649
4650







-
+






-
+


-
+


-
+


-
+


-
+


-
+


-
+







    }
    return $result
} -cleanup {
    $obj destroy
} -result {::oo::Slot ::oo::Slot ::oo::Slot ::oo::Slot ::oo::Slot ::oo::Slot ::oo::Slot}
test oo-34.2 {TIP 380: slots - presence} {
    lsort [info class instances oo::Slot]
} {::oo::define::filter ::oo::define::mixin ::oo::define::superclass ::oo::define::variable ::oo::objdefine::filter ::oo::objdefine::mixin ::oo::objdefine::variable}
} {::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}
proc getMethods obj {
    list [lsort [info object methods $obj -all]] \
	[lsort [info object methods $obj -private]]
}
test oo-34.3 {TIP 380: slots - presence} {
    getMethods oo::define::filter
} {{-append -clear -prepend -remove -set} {Get Set}}
} {{-append -appendifnew -clear -prepend -remove -set} {Get Set}}
test oo-34.4 {TIP 380: slots - presence} {
    getMethods oo::define::mixin
} {{-append -clear -prepend -remove -set} {--default-operation Get Resolve Set}}
} {{-append -appendifnew -clear -prepend -remove -set} {--default-operation Get Resolve Set}}
test oo-34.5 {TIP 380: slots - presence} {
    getMethods oo::define::superclass
} {{-append -clear -prepend -remove -set} {--default-operation Get Resolve Set}}
} {{-append -appendifnew -clear -prepend -remove -set} {--default-operation Get Resolve Set}}
test oo-34.6 {TIP 380: slots - presence} {
    getMethods oo::define::variable
} {{-append -clear -prepend -remove -set} {Get Set}}
} {{-append -appendifnew -clear -prepend -remove -set} {Get Set}}
test oo-34.7 {TIP 380: slots - presence} {
    getMethods oo::objdefine::filter
} {{-append -clear -prepend -remove -set} {Get Set}}
} {{-append -appendifnew -clear -prepend -remove -set} {Get Set}}
test oo-34.8 {TIP 380: slots - presence} {
    getMethods oo::objdefine::mixin
} {{-append -clear -prepend -remove -set} {--default-operation Get Resolve Set}}
} {{-append -appendifnew -clear -prepend -remove -set} {--default-operation Get Resolve Set}}
test oo-34.9 {TIP 380: slots - presence} {
    getMethods oo::objdefine::variable
} {{-append -clear -prepend -remove -set} {Get Set}}
} {{-append -appendifnew -clear -prepend -remove -set} {Get Set}}
test oo-34.10 {TIP 516: slots - resolution} -setup {
    oo::class create parent
    set result {}
    oo::class create 516a { superclass parent }
    oo::class create 516b { superclass parent }
    oo::class create 516c { superclass parent }
    namespace eval 516test {
4377
4378
4379
4380
4381
4382
4383































































































































4384
4385
4386
4387
4388
4389
4390
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    rename obj2 {}
    rename obj1 {}
    # doesn't crash
    return done
} -cleanup {
    rename obj {}
} -result done
test oo-35.7.1 {Bug 7842f33a5c: destructor cascading in stereotypes} -setup {
    oo::class create base
    oo::class create RpcClient {
	superclass base
	method write name {
	    lappend ::result "RpcClient -> $name"
	}
	method create_bug {} {
	    MkObjectRpc create cfg [self] 111
	}
    }
    oo::class create MkObjectRpc {
	superclass base
	variable hdl
	constructor {rpcHdl mqHdl} {
	    set hdl $mqHdl
	    oo::objdefine [self] forward rpc $rpcHdl
	}
	destructor {
	    my rpc write otto-$hdl
	}
    }
    set ::result {}
} -body {
    # In this case, sub-objects are deleted during major object NS cleanup and
    # are trying to call back into the major object (which is mostky gone at
    # this point). Things are messy; error is reported via bgerror as the
    # avenue most likely to reach a user.
    bgerrorIntercept ::result {
	set FH [RpcClient new]
	$FH create_bug
	$FH destroy
	update
    }
    join $result \n
} -cleanup {
    base destroy
} -result {impossible to invoke method "write": no defined method or unknown method}
test oo-35.7.2 {Bug 7842f33a5c: destructor cascading in stereotypes} -setup {
    oo::class create base
    oo::class create RpcClient {
	superclass base
	method write name {
	    lappend ::result "RpcClient -> $name"
	}
	method create_bug {} {
	    MkObjectRpc create cfg [self] 111
	}
	destructor {
	    lappend ::result "Destroyed"
	}
    }
    oo::class create MkObjectRpc {
	superclass base
	variable hdl
	constructor {rpcHdl mqHdl} {
	    set hdl $mqHdl
	    oo::objdefine [self] forward rpc $rpcHdl
	}
	destructor {
	    my rpc write otto-$hdl
	}
    }
    set ::result {}
} -body {
    # In this case, sub-objects are deleted during major object NS cleanup, and
    # we've a destructor on the major class to monitor when it happens. Things
    # are still messy, but the order is clear; error is reported via bgerror as
    # the avenue most likely to reach a user.
    bgerrorIntercept ::result {
	set FH [RpcClient new]
	$FH create_bug
	$FH destroy
	update
    }
    join $result \n
} -cleanup {
    base destroy
} -result {Destroyed
impossible to invoke method "write": no defined method or unknown method}
test oo-35.7.3 {Bug 7842f33a5c: destructor cascading in stereotypes} -setup {
    oo::class create base
    oo::class create RpcClient {
	superclass base
	variable interiorObjects
	method write name {
	    lappend ::result "RpcClient -> $name"
	}
	method create_bug {} {
	    set obj [MkObjectRpc create cfg [self] 111]
	    lappend interiorObjects $obj
	    return $obj
	}
	destructor {
	    lappend ::result "Destroyed"
	    # Explicit destroy of interior objects
	    foreach obj $interiorObjects {
		$obj destroy
	    }
	}
    }
    oo::class create MkObjectRpc {
	superclass base
	variable hdl
	constructor {rpcHdl mqHdl} {
	    set hdl $mqHdl
	    oo::objdefine [self] forward rpc $rpcHdl
	}
	destructor {
	    my rpc write otto-$hdl
	}
    }
    set ::result {}
} -body {
    # In this case, sub-objects are deleted while the destructor is running and
    # the destroy is neat, so things work sanely. Error follows standard Tcl
    # error flow route; bgerror is not used.
    bgerrorIntercept ::result {
	set FH [RpcClient new]
	$FH create_bug
	$FH destroy
	update
    }
    join $result \n
} -cleanup {
    base destroy
} -result "Destroyed\nRpcClient -> otto-111"

test oo-36.1 {TIP #470: introspection within oo::define} {
    oo::define oo::object self
} ::oo::object
test oo-36.2 {TIP #470: introspection within oo::define} -setup {
    oo::class create Cls
} -body {
5479
5480
5481
5482
5483
5484
5485

5486
5487
5488
5489
5490
5491
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014







+






	[oo::define foo definitionnamespace -instance {}] \
	[info class definitionnamespace foo -instance]
} -cleanup {
    parent destroy
    namespace delete foodef
} -result {{} {} ::foodef {} {}}

rename bgerrorIntercept {}
cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/ooNext2.test.

1
2
3
4
5

6
7
8
9
10

11
12
13
14
15
16
17
1
2
3
4

5
6
7
8
9

10
11
12
13
14
15
16
17




-
+




-
+







# This file contains a collection of tests for Tcl's built-in object system.
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2006-2011 Donal K. Fellows
# Copyright © 2006-2011 Donal K. Fellows
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require TclOO 1.0.3
package require tcl::oo 1.3.0
if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}

testConstraint memory [llength [info commands memory]]
if {[testConstraint memory]} {
122
123
124
125
126
127
128
129

130
131
132
133
134
135
136
122
123
124
125
126
127
128

129
130
131
132
133
134
135
136







-
+







	}
    }
    oo::class create C {
	superclass A B
	variable result
	constructor {p q r} {
	    lappend result ==C== p=$p,q=$q,r=$r
	    # Route arguments to superclasses, in non-trival pattern
	    # Route arguments to superclasses, in non-trivial pattern
	    nextto B $q
	    nextto A $p $r
	}
	method result {} {return $result}
    }
    [C new x y z] result
} -cleanup {

Added tests/ooProp.test.






















































































































































































































































































































































































































































































































































































































































































































































































































































































































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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# This file contains a collection of tests for Tcl's built-in object system,
# specifically the parts that support configurable properties on objects.
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright © 2019-2020 Donal K. Fellows
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require tcl::oo 1.0.3
package require tcltest 2
if {"::tcltest" in [namespace children]} {
    namespace import -force ::tcltest::*
}

test ooProp-1.1 {TIP 558: properties: core support} -setup {
    oo::class create parent
    unset -nocomplain result
    set result {}
} -body {
    oo::class create c {superclass parent}
    lappend result [info class properties c] [info class properties c -writable]
    oo::define c ::oo::configuresupport::readableproperties -set a b c
    lappend result [info class properties c] [info class properties c -writable]
    oo::define c ::oo::configuresupport::readableproperties -set f e d
    lappend result [info class properties c] [info class properties c -writable]
    oo::define c ::oo::configuresupport::readableproperties -set a a a
    lappend result [info class properties c] [info class properties c -writable]
    oo::define c ::oo::configuresupport::readableproperties -set
    lappend result [info class properties c] [info class properties c -writable]
} -cleanup {
    parent destroy
} -result {{} {} {a b c} {} {d e f} {} a {} {} {}}
test ooProp-1.2 {TIP 558: properties: core support} -setup {
    oo::class create parent
    unset -nocomplain result
    set result {}
} -body {
    oo::class create c {superclass parent}
    lappend result [info class properties c -all] [info class properties c -writable -all]
    oo::define c ::oo::configuresupport::readableproperties -set a b c
    lappend result [info class properties c -all] [info class properties c -writable -all]
    oo::define c ::oo::configuresupport::readableproperties -set f e d
    lappend result [info class properties c -all] [info class properties c -writable -all]
    oo::define c ::oo::configuresupport::readableproperties -set a a a
    lappend result [info class properties c -all] [info class properties c -writable -all]
    oo::define c ::oo::configuresupport::readableproperties -set
    lappend result [info class properties c -all] [info class properties c -writable -all]
} -cleanup {
    parent destroy
} -result {{} {} {a b c} {} {d e f} {} a {} {} {}}
test ooProp-1.3 {TIP 558: properties: core support} -setup {
    oo::class create parent
    unset -nocomplain result
    set result {}
} -body {
    oo::class create c {superclass parent}
    lappend result [info class properties c] [info class properties c -writable]
    oo::define c ::oo::configuresupport::writableproperties -set a b c
    lappend result [info class properties c] [info class properties c -writable]
    oo::define c ::oo::configuresupport::writableproperties -set f e d
    lappend result [info class properties c] [info class properties c -writable]
    oo::define c ::oo::configuresupport::writableproperties -set a a a
    lappend result [info class properties c] [info class properties c -writable]
    oo::define c ::oo::configuresupport::writableproperties -set
    lappend result [info class properties c] [info class properties c -writable]
} -cleanup {
    parent destroy
} -result {{} {} {} {a b c} {} {d e f} {} a {} {}}
test ooProp-1.4 {TIP 558: properties: core support} -setup {
    oo::class create parent
    unset -nocomplain result
    set result {}
} -body {
    oo::class create c {superclass parent}
    lappend result [info class properties c -all] [info class properties c -writable -all]
    oo::define c ::oo::configuresupport::writableproperties -set a b c
    lappend result [info class properties c -all] [info class properties c -writable -all]
    oo::define c ::oo::configuresupport::writableproperties -set f e d
    lappend result [info class properties c -all] [info class properties c -writable -all]
    oo::define c ::oo::configuresupport::writableproperties -set a a a
    lappend result [info class properties c -all] [info class properties c -writable -all]
    oo::define c ::oo::configuresupport::writableproperties -set
    lappend result [info class properties c -all] [info class properties c -writable -all]
} -cleanup {
    parent destroy
} -result {{} {} {} {a b c} {} {d e f} {} a {} {}}
test ooProp-1.5 {TIP 558: properties: core support} -setup {
    oo::class create parent
    unset -nocomplain result
    set result {}
} -body {
    oo::class create c {superclass parent}
    oo::class create d {superclass c}
    lappend result [info class properties d -all] [info class properties d -writable -all]
    oo::define c ::oo::configuresupport::readableproperties -set a b c
    oo::define d ::oo::configuresupport::readableproperties -set x y z
    lappend result [info class properties d -all] [info class properties d -writable -all]
    oo::define c ::oo::configuresupport::readableproperties -set f e d
    oo::define d ::oo::configuresupport::readableproperties -set r p q
    lappend result [info class properties d -all] [info class properties d -writable -all]
    oo::define c ::oo::configuresupport::readableproperties -set a a h
    oo::define d ::oo::configuresupport::readableproperties -set g h g
    lappend result [info class properties d -all] [info class properties d -writable -all]
    oo::define c ::oo::configuresupport::readableproperties -set
    lappend result [info class properties d -all] [info class properties d -writable -all]
    oo::define d ::oo::configuresupport::readableproperties -set
    lappend result [info class properties d -all] [info class properties d -writable -all]
} -cleanup {
    parent destroy
} -result {{} {} {a b c x y z} {} {d e f p q r} {} {a g h} {} {g h} {} {} {}}
test ooProp-1.6 {TIP 558: properties: core support} -setup {
    oo::class create parent
    unset -nocomplain result
    set result {}
} -body {
    oo::class create c {superclass parent}
    oo::class create d {superclass c}
    lappend result [info class properties d -all] [info class properties d -writable -all]
    oo::define c ::oo::configuresupport::writableproperties -set a b c
    oo::define d ::oo::configuresupport::writableproperties -set x y z
    lappend result [info class properties d -all] [info class properties d -writable -all]
    oo::define c ::oo::configuresupport::writableproperties -set f e d
    oo::define d ::oo::configuresupport::writableproperties -set r p q
    lappend result [info class properties d -all] [info class properties d -writable -all]
    oo::define c ::oo::configuresupport::writableproperties -set a a h
    oo::define d ::oo::configuresupport::writableproperties -set g h g
    lappend result [info class properties d -all] [info class properties d -writable -all]
    oo::define c ::oo::configuresupport::writableproperties -set
    lappend result [info class properties d -all] [info class properties d -writable -all]
    oo::define d ::oo::configuresupport::writableproperties -set
    lappend result [info class properties d -all] [info class properties d -writable -all]
} -cleanup {
    parent destroy
} -result {{} {} {} {a b c x y z} {} {d e f p q r} {} {a g h} {} {g h} {} {}}
test ooProp-1.7 {TIP 558: properties: core support} -setup {
    oo::class create parent
    unset -nocomplain result
    set result {}
} -body {
    oo::class create c {superclass parent}
    c create o
    lappend result [info object properties o] [info object properties o -writable]
    oo::objdefine o ::oo::configuresupport::objreadableproperties -set a b c
    lappend result [info object properties o] [info object properties o -writable]
    oo::objdefine o ::oo::configuresupport::objreadableproperties -set f e d
    lappend result [info object properties o] [info object properties o -writable]
    oo::objdefine o ::oo::configuresupport::objreadableproperties -set a a h
    lappend result [info object properties o] [info object properties o -writable]
    oo::objdefine o ::oo::configuresupport::objreadableproperties -set
    lappend result [info object properties o] [info object properties o -writable]
} -cleanup {
    parent destroy
} -result {{} {} {a b c} {} {d e f} {} {a h} {} {} {}}
test ooProp-1.8 {TIP 558: properties: core support} -setup {
    oo::class create parent
    unset -nocomplain result
    set result {}
} -body {
    oo::class create c {superclass parent}
    c create o
    lappend result [info object properties o] [info object properties o -writable]
    oo::objdefine o ::oo::configuresupport::objwritableproperties -set a b c
    lappend result [info object properties o] [info object properties o -writable]
    oo::objdefine o ::oo::configuresupport::objwritableproperties -set f e d
    lappend result [info object properties o] [info object properties o -writable]
    oo::objdefine o ::oo::configuresupport::objwritableproperties -set a a h
    lappend result [info object properties o] [info object properties o -writable]
    oo::objdefine o ::oo::configuresupport::objwritableproperties -set
    lappend result [info object properties o] [info object properties o -writable]
} -cleanup {
    parent destroy
} -result {{} {} {} {a b c} {} {d e f} {} {a h} {} {}}
test ooProp-1.9 {TIP 558: properties: core support} -setup {
    oo::class create parent
    unset -nocomplain result
    set result {}
} -body {
    oo::class create c {superclass parent}
    oo::class create d {superclass c}
    d create o
    lappend result [info object properties o -all] [info object properties o -writable -all]
    oo::define c ::oo::configuresupport::readableproperties -set a b
    oo::define d ::oo::configuresupport::readableproperties -set c d
    oo::objdefine o ::oo::configuresupport::objreadableproperties -set e f
    lappend result [info object properties o -all] [info object properties o -writable -all]
    oo::objdefine o ::oo::configuresupport::objreadableproperties -set f e d b e
    lappend result [info object properties o -all] [info object properties o -writable -all]
} -cleanup {
    parent destroy
} -result {{} {} {a b c d e f} {} {a b c d e f} {}}
test ooProp-1.10 {TIP 558: properties: core support} -setup {
    oo::class create parent
    unset -nocomplain result
    set result {}
} -body {
    oo::class create c {superclass parent}
    oo::class create d {superclass c}
    d create o
    lappend result [info object properties o -all] [info object properties o -writable -all]
    oo::define c ::oo::configuresupport::writableproperties -set a b
    oo::define d ::oo::configuresupport::writableproperties -set c d
    oo::objdefine o ::oo::configuresupport::objwritableproperties -set e f
    lappend result [info object properties o -all] [info object properties o -writable -all]
    oo::objdefine o ::oo::configuresupport::objwritableproperties -set f e d b e
    lappend result [info object properties o -all] [info object properties o -writable -all]
} -cleanup {
    parent destroy
} -result {{} {} {} {a b c d e f} {} {a b c d e f}}
test ooProp-1.11 {TIP 558: properties: core support cache} -setup {
    oo::class create parent
    unset -nocomplain result
} -body {
    oo::class create m {
	superclass parent
	::oo::configuresupport::readableproperties -set a
	::oo::configuresupport::writableproperties -set c
    }
    oo::class create c {
	superclass parent
	::oo::configuresupport::readableproperties -set b
	::oo::configuresupport::writableproperties -set d
    }
    c create o
    lappend result [info object properties o -all -readable] \
	[info object properties o -all -writable]
    oo::objdefine o mixin m
    lappend result [info object properties o -all -readable] \
	[info object properties o -all -writable]
} -cleanup {
    parent destroy
} -result {b d {a b} {c d}}

test ooProp-2.1 {TIP 558: properties: configurable class system} -setup {
    oo::class create parent
    unset -nocomplain result
    set result {}
} -body {
    oo::configurable create Point {
	superclass parent
	property x y
	constructor args {
	    my configure -x 0 -y 0 {*}$args
	}
	variable x y
	method report {} {
	    lappend ::result "x=$x, y=$y"
	}
    }
    set pt [Point new -x 3]
    $pt report
    $pt configure -y 4
    $pt report
    lappend result [$pt configure -x],[$pt configure -y] [$pt configure]
} -cleanup {
    parent destroy
} -result {{x=3, y=0} {x=3, y=4} 3,4 {-x 3 -y 4}}
test ooProp-2.2 {TIP 558: properties: configurable class system} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property x y
	constructor args {
	    my configure -x 0 -y 0 {*}$args
	}
    }
    oo::configurable create 3DPoint {
	superclass Point
	property z
	constructor args {
	    next -z 0 {*}$args
	}
    }
    set pt [3DPoint new -x 3 -y 4 -z 5]
    list [$pt configure -x],[$pt configure -y],[$pt configure -z] \
	[$pt configure]
} -cleanup {
    parent destroy
} -result {3,4,5 {-x 3 -y 4 -z 5}}
test ooProp-2.3 {TIP 558: properties: configurable class system} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property x y
	constructor args {
	    my configure -x 0 -y 0 {*}$args
	}
    }
    set pt [Point new -x 3 -y 4]
    oo::objdefine $pt property z
    $pt configure -z 5
    list [$pt configure -x],[$pt configure -y],[$pt configure -z] \
	[$pt configure]
} -cleanup {
    parent destroy
} -result {3,4,5 {-x 3 -y 4 -z 5}}
test ooProp-2.4 {TIP 558: properties: configurable class system} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property x y
	constructor args {
	    my configure -x 0 -y 0 {*}$args
	}
    }
    [Point new] configure gorp
} -returnCodes error -cleanup {
    parent destroy
} -result {bad property "gorp": must be -x or -y}
test ooProp-2.5 {TIP 558: properties: configurable class system} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property x y
	constructor args {
	    my configure -x 0 -y 0 {*}$args
	}
    }
    oo::configurable create 3DPoint {
	superclass Point
	property z
	constructor args {
	    next -z 0 {*}$args
	}
    }
    [3DPoint new] configure gorp
} -returnCodes error -cleanup {
    parent destroy
} -result {bad property "gorp": must be -x, -y, or -z}
test ooProp-2.6 {TIP 558: properties: configurable class system} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property x y
	constructor args {
	    my configure -x 0 -y 0 {*}$args
	}
    }
    [Point create p] configure -x 1 -y
} -returnCodes error -cleanup {
    parent destroy
} -result {wrong # args: should be "::p configure ?-option value ...?"}
test ooProp-2.7 {TIP 558: properties: configurable class system} -setup {
    oo::class create parent
    unset -nocomplain msg
} -body {
    oo::configurable create Point {
	superclass parent
	property x y -kind writable
	constructor args {
	    my configure -x 0 -y 0 {*}$args
	}
    }
    Point create p
    list [p configure -y ok] [catch {p configure -y} msg] $msg
} -cleanup {
    parent destroy
} -result {{} 1 {property "-y" is write only}}
test ooProp-2.8 {TIP 558: properties: configurable class system} -setup {
    oo::class create parent
    unset -nocomplain msg
} -body {
    oo::configurable create Point {
	superclass parent
	property x y -kind readable
	constructor args {
	    my configure -x 0 {*}$args
	    variable y 123
	}
    }
    Point create p
    list [p configure] [p configure -y] [catch {p configure -y foo} msg] $msg
} -cleanup {
    parent destroy
} -result {{-x 0 -y 123} 123 1 {property "-y" is read only}}

test ooProp-3.1 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
    unset -nocomplain result
    set result {}
} -body {
    oo::configurable create Point {superclass parent}
    oo::define Point {
	variable xyz
	property x -get {
	    global result
	    lappend result "get"
	    return [lrepeat 3 $xyz]
	} -set {
	    global result
	    lappend result [list set $value]
	    set xyz [expr {$value * 3}]
	}
    }
    Point create pt
    pt configure -x 5
    lappend result >[pt configure -x]<
} -cleanup {
    parent destroy
} -result {{set 5} get {>15 15 15<}}
test ooProp-3.2 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
    unset -nocomplain result
    set result {}
} -body {
    oo::configurable create Point {superclass parent}
    oo::define Point {
	variable xyz
	property x -get {
	    global result
	    lappend result "get"
	    return [lrepeat 3 $xyz]
	} -set {
	    global result
	    lappend result [list set $value]
	    set xyz [expr {$value * 3}]
	} y -kind readable -get {return $xyz}
    }
    Point create pt
    pt configure -x 5
    lappend result >[pt configure -x]< [pt configure -y]
} -cleanup {
    parent destroy
} -result {{set 5} get {>15 15 15<} 15}
test ooProp-3.3 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {superclass parent}
    oo::define Point {
	variable xyz
	property -x -get {return $xyz}
    }
} -returnCodes error -cleanup {
    parent destroy
} -result {bad property name "-x": must not begin with -}
test ooProp-3.4 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {superclass parent}
    oo::define Point {
	property "x y"
    }
} -returnCodes error -cleanup {
    parent destroy
} -result {bad property name "x y": must be a simple word}
test ooProp-3.5 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {superclass parent}
    oo::define Point {
	property ::x
    }
} -returnCodes error -cleanup {
    parent destroy
} -result {bad property name "::x": must not contain namespace separators}
test ooProp-3.6 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {superclass parent}
    oo::define Point {
	property x(
    }
} -returnCodes error -cleanup {
    parent destroy
} -result {bad property name "x(": must not contain parentheses}
test ooProp-3.7 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {superclass parent}
    oo::define Point {
	property x)
    }
} -returnCodes error -cleanup {
    parent destroy
} -result {bad property name "x)": must not contain parentheses}
test ooProp-3.8 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {superclass parent}
    oo::define Point {
	property x -get
    }
} -returnCodes error -cleanup {
    parent destroy
} -result {missing body to go with -get option}
test ooProp-3.9 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {superclass parent}
    oo::define Point {
	property x -set
    }
} -returnCodes error -cleanup {
    parent destroy
} -result {missing body to go with -set option}
test ooProp-3.10 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {superclass parent}
    oo::define Point {
	property x -kind
    }
} -returnCodes error -cleanup {
    parent destroy
} -result {missing kind value to go with -kind option}
test ooProp-3.11 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {superclass parent}
    oo::define Point {
	property x -get {} -set
    }
} -returnCodes error -cleanup {
    parent destroy
} -result {missing body to go with -set option}
test ooProp-3.12 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property x -get {} -get {return ok}
    }
    [Point new] configure -x
} -cleanup {
    parent destroy
} -result ok
test ooProp-3.13 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property x -kind gorp
    }
} -returnCodes error -cleanup {
    parent destroy
} -result {bad kind "gorp": must be readable, readwrite, or writable}
test ooProp-3.14 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property x -k reada -g {return ok}
    }
    [Point new] configure -x
} -cleanup {
    parent destroy
} -result ok
test ooProp-3.15 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property {*}{
	    x -kind writable
	    y -get {return ok}
	}
    }
    [Point new] configure -y
} -cleanup {
    parent destroy
} -result ok
test ooProp-3.16 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
    unset -nocomplain msg
} -body {
    oo::configurable create Point {
	superclass parent
	variable xy
	property x -kind readable -get {return $xy}
	property x -kind writable -set {set xy $value}
    }
    Point create pt
    list [catch {
	pt configure -x ok
    } msg] $msg [catch {
	pt configure -x
    } msg] $msg [catch {
	pt configure -y 1
    } msg] $msg
} -cleanup {
    parent destroy
} -result {0 {} 1 {property "-x" is write only} 1 {bad property "-y": must be -x}}
test ooProp-3.17 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property x -get {return -code break}
    }
    while 1 {
	[Point new] configure -x
	break
    }
} -returnCodes error -cleanup {
    parent destroy
} -result {property getter for -x did a break}
test ooProp-3.18 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property x -get {return -code break}
    }
    while 1 {
	[Point new] configure
	break
    }
} -returnCodes error -cleanup {
    parent destroy
} -result {property getter for -x did a break}
test ooProp-3.19 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property x -get {error "boo"}
    }
    while 1 {
	[Point new] configure -x
	break
    }
} -returnCodes error -cleanup {
    parent destroy
} -result boo
test ooProp-3.20 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property x -get {error "boo"}
    }
    while 1 {
	[Point new] configure
	break
    }
} -returnCodes error -cleanup {
    parent destroy
} -result boo
test ooProp-3.21 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property x -get {return -code continue}
    }
    while 1 {
	[Point new] configure -x
	break
    }
} -returnCodes error -cleanup {
    parent destroy
} -result {property getter for -x did a continue}
test ooProp-3.22 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property x -get {return -level 2 ok}
    }
    apply {{} {
	[Point new] configure
	return bad
    }}
} -cleanup {
    parent destroy
} -result ok
test ooProp-3.23 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property x -get {return -level 2 ok}
    }
    apply {{} {
	[Point new] configure -x
	return bad
    }}
} -cleanup {
    parent destroy
} -result ok
test ooProp-3.24 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property x -set {return -code break}
    }
    while 1 {
	[Point new] configure -x gorp
	break
    }
} -returnCodes error -cleanup {
    parent destroy
} -result {property setter for -x did a break}
test ooProp-3.25 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property x -set {return -code continue}
    }
    while 1 {
	[Point new] configure -x gorp
	break
    }
} -returnCodes error -cleanup {
    parent destroy
} -result {property setter for -x did a continue}
test ooProp-3.26 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property x -set {error "boo"}
    }
    while 1 {
	[Point new] configure -x gorp
	break
    }
} -returnCodes error -cleanup {
    parent destroy
} -result boo
test ooProp-3.27 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	property x -set {return -level 2 ok}
    }
    apply {{} {
	[Point new] configure -x gorp
	return bad
    }}
} -cleanup {
    parent destroy
} -result ok
test ooProp-3.28 {TIP 558: properties: declaration semantics} -setup {
    oo::class create parent
} -body {
    oo::configurable create Point {
	superclass parent
	private property var
    }
    Point create pt
    pt configure -var ok
    pt configure -var
} -cleanup {
    parent destroy
} -result ok

test ooProp-4.1 {TIP 558: properties: error details} -setup {
    oo::class create parent
    unset -nocomplain msg opt
} -body {
    oo::configurable create Point {superclass parent}
    list [catch {oo::define Point {property -x}} msg opt] \
	[dict get $opt -errorinfo] [dict get $opt -errorcode]
} -cleanup {
    parent destroy
} -result {1 {bad property name "-x": must not begin with -
    while executing
"property -x"
    (in definition script for class "::Point" line 1)
    invoked from within
"oo::define Point {property -x}"} {TCL OO PROPERTY_FORMAT}}
test ooProp-4.2 {TIP 558: properties: error details} -setup {
    oo::class create parent
    unset -nocomplain msg opt
} -body {
    oo::configurable create Point {superclass parent}
    list [catch {oo::define Point {property x -get}} msg opt] \
	[dict get $opt -errorinfo] [dict get $opt -errorcode]
} -cleanup {
    parent destroy
} -result {1 {missing body to go with -get option
    while executing
"property x -get"
    (in definition script for class "::Point" line 1)
    invoked from within
"oo::define Point {property x -get}"} {TCL WRONGARGS}}
test ooProp-4.3 {TIP 558: properties: error details} -setup {
    oo::class create parent
    unset -nocomplain msg opt
} -body {
    oo::configurable create Point {superclass parent}
    list [catch {oo::define Point {property x -set}} msg opt] \
	[dict get $opt -errorinfo] [dict get $opt -errorcode]
} -cleanup {
    parent destroy
} -result {1 {missing body to go with -set option
    while executing
"property x -set"
    (in definition script for class "::Point" line 1)
    invoked from within
"oo::define Point {property x -set}"} {TCL WRONGARGS}}
test ooProp-4.4 {TIP 558: properties: error details} -setup {
    oo::class create parent
    unset -nocomplain msg opt
} -body {
    oo::configurable create Point {superclass parent}
    list [catch {oo::define Point {property x -kind}} msg opt] \
	[dict get $opt -errorinfo] [dict get $opt -errorcode]
} -cleanup {
    parent destroy
} -result {1 {missing kind value to go with -kind option
    while executing
"property x -kind"
    (in definition script for class "::Point" line 1)
    invoked from within
"oo::define Point {property x -kind}"} {TCL WRONGARGS}}
test ooProp-4.5 {TIP 558: properties: error details} -setup {
    oo::class create parent
    unset -nocomplain msg opt
} -body {
    oo::configurable create Point {superclass parent}
    list [catch {oo::define Point {property x -kind gorp}} msg opt] \
	[dict get $opt -errorinfo] [dict get $opt -errorcode]
} -cleanup {
    parent destroy
} -result {1 {bad kind "gorp": must be readable, readwrite, or writable
    while executing
"property x -kind gorp"
    (in definition script for class "::Point" line 1)
    invoked from within
"oo::define Point {property x -kind gorp}"} {TCL LOOKUP INDEX kind gorp}}
test ooProp-4.6 {TIP 558: properties: error details} -setup {
    oo::class create parent
    unset -nocomplain msg opt
} -body {
    oo::configurable create Point {superclass parent}
    list [catch {oo::define Point {property x -gorp}} msg opt] \
	[dict get $opt -errorinfo] [dict get $opt -errorcode]
} -cleanup {
    parent destroy
} -result {1 {bad option "-gorp": must be -get, -kind, or -set
    while executing
"property x -gorp"
    (in definition script for class "::Point" line 1)
    invoked from within
"oo::define Point {property x -gorp}"} {TCL LOOKUP INDEX option -gorp}}
test ooProp-4.7 {TIP 558: properties: error details} -setup {
    oo::class create parent
    unset -nocomplain msg opt
} -body {
    oo::configurable create Point {
	superclass parent
	property x
    }
    Point create pt
    list [catch {pt configure -gorp} msg opt] \
	[dict get $opt -errorinfo] [dict get $opt -errorcode]
} -cleanup {
    parent destroy
} -result {1 {bad property "-gorp": must be -x
    while executing
"pt configure -gorp"} {TCL LOOKUP INDEX property -gorp}}
test ooProp-4.8 {TIP 558: properties: error details} -setup {
    oo::class create parent
    unset -nocomplain msg opt
} -body {
    oo::configurable create Point {
	superclass parent
	property x
    }
    Point create pt
    list [catch {pt configure -gorp blarg} msg opt] \
	[dict get $opt -errorinfo] [dict get $opt -errorcode]
} -cleanup {
    parent destroy
} -result {1 {bad property "-gorp": must be -x
    while executing
"pt configure -gorp blarg"} {TCL LOOKUP INDEX property -gorp}}

cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/ooUtil.test.

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
30
31
32
33
34
35
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
30
31
32
33
34
35





-
-
+
+




-
+










-
+




-
+







# This file contains a collection of tests for functionality originally
# sourced from the ooutil package in Tcllib. Sourcing this file into Tcl runs
# the tests and generates output for errors. No output means no errors were
# found.
#
# Copyright (c) 2014-2016 Andreas Kupries
# Copyright (c) 2018 Donal K. Fellows
# Copyright © 2014-2016 Andreas Kupries
# Copyright © 2018 Donal K. Fellows
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require TclOO 1.0.3
package require tcl::oo 1.3.0
if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}

test ooUtil-1.1 {TIP 478: classmethod} -setup {
    oo::class create parent
} -body {
    oo::class create ActiveRecord {
	superclass parent
        classmethod find args {
	classmethod find args {
	    return "[self] called with arguments: $args"
	}
    }
    oo::class create Table {
        superclass ActiveRecord
	superclass ActiveRecord
    }
    Table find foo bar
} -cleanup {
    parent destroy
} -result {::Table called with arguments: foo bar}
test ooUtil-1.2 {TIP 478: classmethod in namespace} -setup {
    namespace eval ::testns {}
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
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







-
-
-
-
+
+
+
+










-
+




-
+


-
+










-
+
















-
+

















-
-
-
-
-
-
-
+
+
+
+
+
+
+


-
-
-
-
+
+
+
+







} -cleanup {
    namespace delete ::testns
} -result {::testns::Table called with arguments: foo bar}
test ooUtil-1.3 {TIP 478: classmethod must not interfere with constructor signatures} -setup {
    oo::class create parent
} -body {
    oo::class create TestClass {
        superclass oo::class parent
        self method create {name ignore body} {
            next $name $body
        }
	superclass oo::class parent
	self method create {name ignore body} {
	    next $name $body
	}
    }
    TestClass create okay {} {}
} -cleanup {
    parent destroy
} -result {::okay}
test ooUtil-1.4 {TIP 478: classmethod with several inheritance levels} -setup {
    oo::class create parent
} -body {
    oo::class create ActiveRecord {
	superclass parent
        classmethod find args {
	classmethod find args {
	    return "[self] called with arguments: $args"
	}
    }
    oo::class create Table {
        superclass ActiveRecord
	superclass ActiveRecord
    }
    oo::class create SubTable {
        superclass Table
	superclass Table
    }
    SubTable find foo bar
} -cleanup {
    parent destroy
} -result {::SubTable called with arguments: foo bar}
test ooUtil-1.5 {TIP 478: classmethod and instances} -setup {
    oo::class create parent
} -body {
    oo::class create ActiveRecord {
	superclass parent
        classmethod find args {
	classmethod find args {
	    return "[self] called with arguments: $args"
	}
    }
    oo::class create Table {
	superclass ActiveRecord
    }
    set t [Table new]
    $t find 1 2 3
} -cleanup {
    parent destroy
} -result {::Table called with arguments: 1 2 3}
test ooUtil-1.6 {TIP 478: classmethod and instances} -setup {
    oo::class create parent
} -body {
    oo::class create ActiveRecord {
	superclass parent
        classmethod find args {
	classmethod find args {
	    return "[self] called with arguments: $args"
	}
    }
    oo::class create Table {
	superclass ActiveRecord
	unexport find
    }
    set t [Table new]
    $t find 1 2 3
} -returnCodes error -cleanup {
    parent destroy
} -match glob -result {unknown method "find": must be *}
test ooUtil-1.7 {} -setup {
    oo::class create parent
} -body {
    oo::class create Foo {
	superclass parent
        classmethod bar {} {
            puts "This is in the class; self is [self]"
            my meee
        }
        classmethod meee {} {
            puts "This is meee"
        }
	classmethod bar {} {
	    puts "This is in the class; self is [self]"
	    my meee
	}
	classmethod meee {} {
	    puts "This is meee"
	}
    }
    oo::class create Grill {
        superclass Foo
        classmethod meee {} {
            puts "This is meee 2"
        }
	superclass Foo
	classmethod meee {} {
	    puts "This is meee 2"
	}
    }
    list [Foo bar] [Grill bar] [[Foo new] bar] [[Grill new] bar]
} -cleanup {
    parent destroy
} -result {{} {} {} {}} -output "This is in the class; self is ::Foo\nThis is meee\nThis is in the class; self is ::Grill\nThis is meee 2\nThis is in the class; self is ::Foo\nThis is meee\nThis is in the class; self is ::Grill\nThis is meee 2\n"
# Two tests to confirm that we correctly initialise the scripted part of TclOO
# in child interpreters. This is slightly tricky at the implementation level
173
174
175
176
177
178
179












180
181
182
183
184
185
186
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







+
+
+
+
+
+
+
+
+
+
+
+







	}
	# This is confirming that this is a (basic) safe interpreter
	list [Table find foo bar] [info commands source]
    }
} -cleanup {
    interp delete $safeinterp
} -result {{::Table called with arguments: foo bar} {}}
test ooUtil-1.10.1 {Bug 680503: classmethod shouldn't require create body} -body {
    oo::class create C
    oo::define C {classmethod cm {} {}}
} -cleanup {
    catch {C destroy}
} -result {}
test ooUtil-1.10.2 {Bug 680503: case that worked} -body {
    oo::class create C {}
    oo::define C {classmethod cm {} {}}
} -cleanup {
    catch {C destroy}
} -result {}

test ooUtil-2.1 {TIP 478: callback generation} -setup {
    oo::class create parent
} -body {
    oo::class create c {
	superclass parent
	method CallMe {} { return ok,[self] }
425
426
427
428
429
430
431
432

433
434
435
436
437
438
439
437
438
439
440
441
442
443

444
445
446
447
448
449
450
451







-
+







    set x [pqr new]
    set y [pqr create ::y]
    lappend codes [$x foo] [$x bar] $y
} -cleanup {
    parent destroy
} -result {1 1 1 123 456 ::y}

test ooUtil-6.1 {TIP 478: classvarable} -setup {
test ooUtil-6.1 {TIP 478: classvariable} -setup {
    oo::class create parent
} -body {
    oo::class create xyz {
	superclass parent
	initialise {
	    variable x 1 y 2
	}
455
456
457
458
459
460
461
462

463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478

479
480
481
482
483
484
485
467
468
469
470
471
472
473

474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489

490
491
492
493
494
495
496
497







-
+















-
+







    set result [list [$p c] [$q c]]
    $p a
    $q b
    lappend result [[xyz new] c]
} -cleanup {
    parent destroy
} -result {{1 2} {1 2} {2 3}}
test ooUtil-6.2 {TIP 478: classvarable error case} -setup {
test ooUtil-6.2 {TIP 478: classvariable error case} -setup {
    oo::class create parent
} -body {
    oo::class create xyz {
	superclass parent
	method a {} {
	    classvariable x(1)
	    incr x(1)
	}
    }
    set p [xyz new]
    set q [xyz new]
    list [$p a] [$q a]
} -returnCodes error -cleanup {
    parent destroy
} -result {bad variable name "x(1)": can't create a scalar variable that looks like an array element}
test ooUtil-6.3 {TIP 478: classvarable error case} -setup {
test ooUtil-6.3 {TIP 478: classvariable error case} -setup {
    oo::class create parent
} -body {
    oo::class create xyz {
	superclass parent
	method a {} {
	    classvariable ::x
	    incr x
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
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580




581
582
583
584
585
586
587
588
589
590
591







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

















-
-
-
-
+
+
+
+







	}
    }
    cls create o pqr
    list [o foo] [pqr] [rename [info object namespace o]::my {}] [catch pqr msg] $msg
} -cleanup {
    parent destroy
} -result {{in foo of ::o} {in foo of ::o} {} 1 {invalid command name "pqr"}}

# Tests a very weird combination of things (with a key problem locus in
# MixinClassDelegates) that TIP 567 fixes
test ooUtil-8.1 {TIP 567: call oo::define twice from metaclass constructor} -setup {
    oo::class create parent
} -body {
    ::oo::class create A {
	superclass parent
    }
    ::oo::class create B {
	superclass ::oo::class parent
	constructor {{definitionScript ""}} {
	    next $definitionScript
	    next {superclass ::A}
	}
    }
    B create C {
	superclass A
    }
    C create instance
} -cleanup {
    parent destroy
} -result ::instance

# Tests that verify issues detected with the tcllib version of the code
test ooUtil-tcllib-ticket-b3577ed586 {test scoping of delegation in oo::class.Delegate } -setup {
    oo::class create animal {}
    namespace eval ::ooutiltest {
	oo::class create pet { superclass animal }
    }
} -body {
    namespace eval ::ooutiltest {
	oo::class create dog { superclass pet }
    }
} -cleanup {
    namespace delete ooutiltest
    rename animal {}
} -result {::ooutiltest::dog}
test ooUtil-tcllib-ticket-fe7a0e0a3a {classmethod must not interfere with constructor signatures} -setup {
    oo::class create TestClass {
        superclass oo::class
        self method create {name ignore body} {
            next $name $body
        }
	superclass oo::class
	self method create {name ignore body} {
	    next $name $body
	}
    }
} -body {
    TestClass create okay {} {}
} -cleanup {
    rename TestClass {}
} -result {::okay}


Changes to tests/opt.test.

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
30
31


32
33
34
35
36
37
38
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


30
31
32
33
34
35
36
37
38






-
-
-
+
+
+










-
+









-
-
+
+







# Package covered:  opt1.0/optparse.tcl
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
}

# the package we are going to test
package require opt 0.4.8
package require opt 0.4.9

# we are using implementation specifics to test the package


#### functions tests #####

set n $::tcl::OptDescN

test opt-1.1 {OptKeyRegister / check that auto allocation is skipping existing keys} {
    list [::tcl::OptKeyRegister {} $n] [::tcl::OptKeyRegister {} [expr $n+1]] [::tcl::OptKeyRegister {}]
} "$n [expr $n+1] [expr $n+2]"
    list [::tcl::OptKeyRegister {} $n] [::tcl::OptKeyRegister {} [expr {$n+1}]] [::tcl::OptKeyRegister {}]
} "$n [expr {$n+1}] [expr {$n+2}]"

test opt-2.1 {OptKeyDelete} {
    list [::tcl::OptKeyRegister {} testkey] \
	    [info exists ::tcl::OptDesc(testkey)] \
	    [::tcl::OptKeyDelete testkey] \
	    [info exists ::tcl::OptDesc(testkey)]
} {testkey 1 {} 0}

Changes to tests/package.test.

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
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







-
-
-
+
+
+










-
+







# This file contains tests for the package and ::pkg::* commands.
# Note that the tests are limited to Tcl scripts only, there are no shared
# libraries against which to test.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2011 Donal K. Fellows
# Copyright © 1995-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2011 Donal K. Fellows
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

# Do all this in a child interp to avoid garbaging the package list
set i [interp create]
tcltest::loadIntoChildInterpreter $i {*}$argv
catch [list load {} Tcltest $i]
interp eval $i {
namespace import -force ::tcltest::*
616
617
618
619
620
621
622
623

624
625
626
627
628
629
630
616
617
618
619
620
621
622

623
624
625
626
627
628
629
630







-
+







} -result {1.3}
test pkg-3.53 {Tcl_PkgRequire procedure, picking best stable version} -constraints testpreferstable -setup {
    testpreferstable
    package forget t
    set x xxx
} -body {
    foreach i {1.2b1 1.1} {
        package ifneeded t $i "set x $i; package provide t $i"
	package ifneeded t $i "set x $i; package provide t $i"
    }
    package require t
    set x
} -result {1.1}
test package-3.54 {Tcl_PkgRequire procedure, coroutine support} -setup {
    package forget t
} -body {
1336
1337
1338
1339
1340
1341
1342
1343

1344
1345
1346
1347
1348
1349
1350
1336
1337
1338
1339
1340
1341
1342

1343
1344
1345
1346
1347
1348
1349
1350







-
+







    } finally {
	interp delete $ip
    }
}

test package-13.0 {package prefer defaults} -body {
    prefer
} -result [expr {[string match {*[ab]*} [package provide Tcl]] ? "latest" : "stable"}]
} -result [expr {[string match {*[ab]*} [package provide tcl]] ? "latest" : "stable"}]
test package-13.1 {package prefer defaults} -body {
    set ::env(TCL_PKG_PREFER_LATEST) stable	;# value not relevant!
    prefer
} -cleanup {
    unset -nocomplain ::env(TCL_PKG_PREFER_LATEST)
} -result latest

Changes to tests/parse.test.

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
30
31
32
33
34

35
36
37
38
39
40
41
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
30
31
32
33

34
35
36
37
38
39
40
41




-
-
+
+













-
+













-
+







# This file contains a collection of tests for the procedures in the
# file tclParse.c.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
}

namespace eval ::tcl::test::parse {
    namespace import ::tcltest::*

::tcltest::loadTestedCommands
catch [list package require -exact Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testparser [llength [info commands testparser]]
testConstraint testbytestring [llength [info commands testbytestring]]
testConstraint testevalobjv [llength [info commands testevalobjv]]
testConstraint testevalex [llength [info commands testevalex]]
testConstraint testparsevarname [llength [info commands testparsevarname]]
testConstraint testparsevar [llength [info commands testparsevar]]
testConstraint testasync [llength [info commands testasync]]
testConstraint testcmdtrace [llength [info commands testcmdtrace]]
testConstraint testevent [llength [info commands testevent]]
testConstraint memory [llength [info commands memory]]

test parse-1.1 {Tcl_ParseCommand procedure, computing string length} {testparser testbytestring} {
    testparser [testbytestring "foo\0 bar"] -1
    testparser [testbytestring "foo\x00 bar"] -1
} {- foo 1 simple foo 1 text foo 0 {}}
test parse-1.2 {Tcl_ParseCommand procedure, computing string length} testparser {
    testparser "foo bar" -1
} {- {foo bar} 2 simple foo 1 text foo 0 simple bar 1 text bar 0 {}}
test parse-1.3 {Tcl_ParseCommand procedure, leading space} testparser {
    testparser "  \n\t   foo" 0
} {- foo 1 simple foo 1 text foo 0 {}}
274
275
276
277
278
279
280
281

282
283
284
285
286
287
288
274
275
276
277
278
279
280

281
282
283
284
285
286
287
288







-
+







    info complete {a [b {}c d]}
} {1}
test parse-6.9 {ParseTokens procedure, error in command substitution} {
    info complete {a [b "c d}
} {0}
test parse-6.10 {ParseTokens procedure, incomplete sub-command} {
    info complete {puts [
	expr 1+1
	expr {1+1}
	#this is a comment ]}
} {0}
test parse-6.11 {ParseTokens procedure, memory allocation for big nested command} testparser {
    testparser {[$a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b)]} 0
} {- {[$a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b)]} 1 word {[$a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b)]} 1 command {[$a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b)]} 0 {}}
test parse-6.12 {ParseTokens procedure, missing close bracket} testparser {
    list [catch {testparser {[foo $x bar} 0} msg] $msg $::errorInfo
296
297
298
299
300
301
302
303
304


305
306
307
308
309
310
311
296
297
298
299
300
301
302


303
304
305
306
307
308
309
310
311







-
-
+
+







test parse-6.14 {ParseTokens procedure, backslash-newline} testparser {
    testparser "b\\\nc" 0
} {- b\\\nc 2 simple b 1 text b 0 simple c 1 text c 0 {}}
test parse-6.15 {ParseTokens procedure, backslash-newline} testparser {
    testparser "\"b\\\nc\"" 0
} {- \"b\\\nc\" 1 word \"b\\\nc\" 3 text b 0 backslash \\\n 0 text c 0 {}}
test parse-6.16 {ParseTokens procedure, backslash substitution} testparser {
    testparser {\n\a\x7f} 0
} {- {\n\a\x7f} 1 word {\n\a\x7f} 3 backslash {\n} 0 backslash {\a} 0 backslash {\x7f} 0 {}}
    testparser {\n\a\x7F} 0
} {- {\n\a\x7F} 1 word {\n\a\x7F} 3 backslash {\n} 0 backslash {\a} 0 backslash {\x7F} 0 {}}
test parse-6.17 {ParseTokens procedure, null characters} {testparser testbytestring} {
    expr {[testparser [testbytestring "foo\0zz"] 0] eq
"- [testbytestring foo\0zz] 1 word [testbytestring foo\0zz] 3 text foo 0 text [testbytestring \0] 0 text zz 0 {}"
	}
} 1
test parse-6.18 {ParseTokens procedure, seek past numBytes for close-bracket} testparser {
    # Test for Bug 681841
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
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







-
+


-
-
-
+
+
+





-
+







    rename ::foo {}
    rename ::unknown {}
    rename unknown.save ::unknown
    set ::info
} [subst {[set level 2; incr level [info level]] global 1 global 1 global}]
test parse-8.12 {Tcl_EvalObjv procedure, TCL_EVAL_INVOKE} {
    set ::auto_index(noSuchCommand) {
        proc noSuchCommand {} {lappend ::info global}
	proc noSuchCommand {} {lappend ::info global}
    }
    set ::auto_index(::[string trimleft [namespace current]::test_ns_1::noSuchCommand :]) [list \
        proc [namespace current]::test_ns_1::noSuchCommand {} {
            lappend ::info ns
        }]
	proc [namespace current]::test_ns_1::noSuchCommand {} {
	    lappend ::info ns
	}]
    catch {rename ::noSuchCommand {}}
    set ::child [interp create]
    $::child alias bar noSuchCommand
    set ::info {}
    namespace eval test_ns_1 {
        $::child eval bar
	$::child eval bar
    }
    namespace delete test_ns_1
    interp delete $::child
    catch {rename ::noSuchCommand {}}
    set ::info
} global

477
478
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
477
478
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







-
+



-
+













-
+


















-
+







test parse-10.1 {Tcl_EvalTokens, simple text} testevalex {
    testevalex {concat test}
} {test}
test parse-10.2 {Tcl_EvalTokens, backslash sequences} testevalex {
    testevalex {concat test\063\062test}
} {test32test}
test parse-10.3 {Tcl_EvalTokens, nested commands} testevalex {
    testevalex {concat [expr 2 + 6]}
    testevalex {concat [expr {2 + 6}]}
} {8}
test parse-10.4 {Tcl_EvalTokens, nested commands} testevalex {
    unset -nocomplain a
    list [catch {testevalex {concat xxx[expr $a]}} msg] $msg
    list [catch {testevalex {concat xxx[expr {$a}]}} msg] $msg
} {1 {can't read "a": no such variable}}
test parse-10.5 {Tcl_EvalTokens, simple variables} testevalex {
    set a hello
    testevalex {concat $a}
} {hello}
test parse-10.6 {Tcl_EvalTokens, array variables} testevalex {
    unset -nocomplain a
    set a(12) 46
    testevalex {concat $a(12)}
} {46}
test parse-10.7 {Tcl_EvalTokens, array variables} testevalex {
    unset -nocomplain a
    set a(12) 46
    testevalex {concat $a(1[expr 3 - 1])}
    testevalex {concat $a(1[expr {3 - 1}])}
} {46}
test parse-10.8 {Tcl_EvalTokens, array variables} testevalex {
    unset -nocomplain a
    list [catch {testevalex {concat $x($a)}} msg] $msg
} {1 {can't read "a": no such variable}}
test parse-10.9 {Tcl_EvalTokens, array variables} testevalex {
    unset -nocomplain a
    list [catch {testevalex {concat xyz$a(1)}} msg] $msg
} {1 {can't read "a(1)": no such variable}}
test parse-10.10 {Tcl_EvalTokens, object values} testevalex {
    set a 123
    testevalex {concat $a}
} {123}
test parse-10.11 {Tcl_EvalTokens, object values} testevalex {
    set a 123
    testevalex {concat $a$a$a}
} {123123123}
test parse-10.12 {Tcl_EvalTokens, object values} testevalex {
    testevalex {concat [expr 2][expr 4][expr 6]}
    testevalex {concat [expr {2}][expr {4}][expr {6}]}
} {246}
test parse-10.13 {Tcl_EvalTokens, string values} testevalex {
    testevalex {concat {a" b"}}
} {a" b"}
test parse-10.14 {Tcl_EvalTokens, string values} testevalex {
    set a 111
    testevalex {concat x$a.$a.$a}
597
598
599
600
601
602
603
604
605


606
607
608
609
610
611
612
597
598
599
600
601
602
603


604
605
606
607
608
609
610
611
612







-
-
+
+







test parse-12.5 {Tcl_ParseVarName procedure, just a dollar sign} testparsevarname {
    testparsevarname {$abcd} 1 0
} {- {} 0 text {$} 0 abcd}
test parse-12.6 {Tcl_ParseVarName procedure, braced variable name} testparser {
    testparser {${..[]b}cd} 0
} {- {${..[]b}cd} 1 word {${..[]b}cd} 3 variable {${..[]b}} 1 text {..[]b} 0 text cd 0 {}}
test parse-12.7 {Tcl_ParseVarName procedure, braced variable name} testparser {
    testparser "\$\{\{\} " 0
} {- \$\{\{\}\  1 word \$\{\{\} 2 variable \$\{\{\} 1 text \{ 0 {}}
    testparser "\$\{\{\\\\\}\} " 0
} {- {${{\\}} } 1 word {${{\\}}} 2 variable {${{\\}}} 1 text {{\\}} 0 {}}
test parse-12.8 {Tcl_ParseVarName procedure, missing close brace} testparser {
    list [catch {testparser "$\{abc" 0} msg] $msg $::errorInfo
} {1 {missing close-brace for variable name} missing\ close-brace\ for\ variable\ name\n\ \ \ \ (remainder\ of\ script:\ \"\{abc\")\n\ \ \ \ invoked\ from\ within\n\"testparser\ \"\$\\\{abc\"\ 0\"}
test parse-12.9 {Tcl_ParseVarName procedure, missing close brace} testparsevarname {
    list [catch {testparsevarname {${bcd}} 4 0} msg] $msg
} {1 {missing close-brace for variable name}}
test parse-12.10 {Tcl_ParseVarName procedure, missing close brace} testparsevarname {
681
682
683
684
685
686
687
688

689
690
691
692
693
694
695
681
682
683
684
685
686
687

688
689
690
691
692
693
694
695







-
+







    unset -nocomplain abc
    list [catch {testparsevar {$abc}} msg] $msg
} {1 {can't read "abc": no such variable}}
test parse-13.5 {Tcl_ParseVar procedure, error looking up variable} testparsevar {
    unset -nocomplain abc
    list [catch {testparsevar {$abc([bogus x y z])}} msg] $msg
} {1 {invalid command name "bogus"}}
test parse-13.6 {Tcl_ParseVar memory leak} -constraints memory -setup {
test parse-13.6 {Tcl_ParseVar memory leak} -constraints {testparsevar memory} -setup {
    proc getbytes {} {
	return [lindex [split [memory info] \n] 3 3]
    }
} -body {
    set a() foo
    set end [getbytes]
    for {set i 0} {$i < 5} {incr i} {
703
704
705
706
707
708
709
710

711
712
713
714
715
716
717
703
704
705
706
707
708
709

710
711
712
713
714
715
716
717







-
+







    expr {$end - $tmp}
} -cleanup {
    unset -nocomplain a end i vn res tmp
    rename getbytes {}
} -result 0

test parse-14.1 {Tcl_ParseBraces procedure, computing string length} {testparser testbytestring} {
    testparser [testbytestring "foo\0 bar"] -1
    testparser [testbytestring "foo\x00 bar"] -1
} {- foo 1 simple foo 1 text foo 0 {}}
test parse-14.2 {Tcl_ParseBraces procedure, computing string length} testparser {
    testparser "foo bar" -1
} {- {foo bar} 2 simple foo 1 text foo 0 simple bar 1 text bar 0 {}}
test parse-14.3 {Tcl_ParseBraces procedure, words in braces} testparser {
    testparser {foo {a $b [concat foo]} {c d}} 0
} {- {foo {a $b [concat foo]} {c d}} 3 simple foo 1 text foo 0 simple {{a $b [concat foo]}} 1 text {a $b [concat foo]} 0 simple {{c d}} 1 text {c d} 0 {}}
740
741
742
743
744
745
746
747

748
749
750
751
752
753
754
740
741
742
743
744
745
746

747
748
749
750
751
752
753
754







-
+







    testparser {foo {}} 0
} {- {foo {}} 2 simple foo 1 text foo 0 simple {{}} 1 text {} 0 {}}
test parse-14.12 {Tcl_ParseBraces procedure, missing close brace} testparser {
    list [catch {testparser "foo \{xy\\\nz" 0} msg] $msg $::errorInfo
} {1 {missing close-brace} missing\ close-brace\n\ \ \ \ (remainder\ of\ script:\ \"\{xy\\\nz\")\n\ \ \ \ invoked\ from\ within\n\"testparser\ \"foo\ \\\{xy\\\\\\nz\"\ 0\"}

test parse-15.1 {Tcl_ParseQuotedString procedure, computing string length} {testparser testbytestring} {
    testparser [testbytestring "foo\0 bar"] -1
    testparser [testbytestring "foo\x00 bar"] -1
} {- foo 1 simple foo 1 text foo 0 {}}
test parse-15.2 {Tcl_ParseQuotedString procedure, computing string length} testparser {
    testparser "foo bar" -1
} {- {foo bar} 2 simple foo 1 text foo 0 simple bar 1 text bar 0 {}}
test parse-15.3 {Tcl_ParseQuotedString procedure, word is quoted string} testparser {
    testparser {foo "a b c" d "efg";} 0
} {- {foo "a b c" d "efg";} 4 simple foo 1 text foo 0 simple {"a b c"} 1 text {a b c} 0 simple d 1 text d 0 simple {"efg"} 1 text efg 0 {}}
793
794
795
796
797
798
799
800

801
802
803
804
805
806
807
793
794
795
796
797
798
799

800
801
802
803
804
805
806
807







-
+







    info complete {a b "cd"xyz}
} 1
test parse-15.16 {CommandComplete procedure} {
    info complete {a b "c $d() d"}
} 1
test parse-15.17 {CommandComplete procedure} {
    info complete {a b "c $dd("}
} 0
} 1
test parse-15.18 {CommandComplete procedure} {
    info complete {a b "c \"}
} 0
test parse-15.19 {CommandComplete procedure} {
    info complete {a b "c [d e f]"}
} 1
test parse-15.20 {CommandComplete procedure} {
906
907
908
909
910
911
912
913

914
915
916

917
918
919
920
921
922
923
906
907
908
909
910
911
912

913
914
915

916
917
918
919
920
921
922
923







-
+


-
+







test parse-15.53 {CommandComplete procedure} "
    info complete \" # \{\"
" 1
test parse-15.54 {CommandComplete procedure} "
    info complete \"foo bar;# \{\"
" 1
test parse-15.55 {CommandComplete procedure} testbytestring {
    info complete "set x [testbytestring \0]; puts hi"
    info complete "set x [testbytestring \x00]; puts hi"
} 1
test parse-15.56 {CommandComplete procedure} testbytestring {
    info complete "set x [testbytestring \0]; \{"
    info complete "set x [testbytestring \x00]; \{"
} 0
test parse-15.57 {CommandComplete procedure} {
    info complete "# Comment should be complete command"
} 1
test parse-15.58 {CommandComplete procedure, memory leaks} {
    info complete "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22"
} 1
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
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







-
+


-
+


-
+





-
+


-
+



-
+







    list [catch "subst \[" msg] $msg
} [list 1 "missing close-bracket"]

test parse-18.14 {Tcl_SubstObj, exception handling} {
    subst {abc,[break],def}
} {abc,}
test parse-18.15 {Tcl_SubstObj, exception handling} {
    subst {abc,[continue; expr 1+2],def}
    subst {abc,[continue; expr {1+2}],def}
} {abc,,def}
test parse-18.16 {Tcl_SubstObj, exception handling} {
    subst {abc,[return foo; expr 1+2],def}
    subst {abc,[return foo; expr {1+2}],def}
} {abc,foo,def}
test parse-18.17 {Tcl_SubstObj, exception handling} {
    subst {abc,[return -code 10 foo; expr 1+2],def}
    subst {abc,[return -code 10 foo; expr {1+2}],def}
} {abc,foo,def}
test parse-18.18 {Tcl_SubstObj, exception handling} {
    subst {abc,[break; set {} {}{}],def}
} {abc,}
test parse-18.19 {Tcl_SubstObj, exception handling} {
    list [catch {subst {abc,[continue; expr 1+2; set {} {}{}],def}} msg] $msg
    list [catch {subst {abc,[continue; expr {1+2}; set {} {}{}],def}} msg] $msg
} [list 1 "extra characters after close-brace"]
test parse-18.20 {Tcl_SubstObj, exception handling} {
    list [catch {subst {abc,[return foo; expr 1+2; set {} {}{}],def}} msg] $msg
    list [catch {subst {abc,[return foo; expr {1+2}; set {} {}{}],def}} msg] $msg
} [list 1 "extra characters after close-brace"]
test parse-18.21 {Tcl_SubstObj, exception handling} {
    list [catch {
	subst {abc,[return -code 10 foo; expr 1+2; set {} {}{}],def}
	subst {abc,[return -code 10 foo; expr {1+2}; set {} {}{}],def}
    } msg] $msg
} [list 1 "extra characters after close-brace"]

test parse-18.22 {Tcl_SubstObj, side effects} {
    set a 0
    list [subst {foo[incr a]bar}] $a
} [list foo1bar 1]

Changes to tests/parseExpr.test.

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
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
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
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




-
-
+
+










-
+

















-
+

-
+









-
+

-
+

-
+





-
+

-
+









-
+

-
+

-
+














-
+









-
+










-
+















-
+









-
+







-
+















-
+







-
+















-
+







-
+















-
+







-
+















-
+







-
+















-
+







-
+


















-
+







-
+







# This file contains a collection of tests for the procedures in the
# file tclCompExpr.c.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

# Note that the Tcl expression parser (tclCompExpr.c) does not check
# the semantic validity of the expressions it parses. It does not check,
# for example, that a math function actually exists, or that the operands
# of "<<" are integers.

testConstraint testexprparser [llength [info commands testexprparser]]
testConstraint testbytestring [llength [info commands testbytestring]]

# Big test for correct ordering of data in [expr]

proc testIEEE {} {
    variable ieeeValues
    binary scan [binary format dd -1.0 1.0] c* c
    switch -exact -- $c {
	{0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
	    # little endian
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\xFF d \
		ieeeValues(-Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\xBF d \
		ieeeValues(-Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
		ieeeValues(-Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x3F d \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \
		ieeeValues(+Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF8\x7F d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 1
	    return 1
	}
	{-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
	    binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \xFF\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Infinity)
	    binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \xBF\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Normal)
	    binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Subnormal)
	    binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x3F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Normal)
	    binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x7F\xF8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 0
	}
    }
}
testConstraint ieeeFloatingPoint [testIEEE]

######################################################################

test parseExpr-1.1 {Tcl_ParseExpr procedure, computing string length} {testexprparser testbytestring} {
    testexprparser [testbytestring "1+2\0 +3"] -1
    testexprparser [testbytestring "1+2\x00 +3"] -1
} {- {} 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
test parseExpr-1.2 {Tcl_ParseExpr procedure, computing string length} testexprparser {
    testexprparser "1  + 2" -1
} {- {} 0 subexpr {1  + 2} 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
test parseExpr-1.3 {Tcl_ParseExpr procedure, error getting initial lexeme} testexprparser {
    testexprparser 12345678901234567890 -1
} {- {} 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
test parseExpr-1.4 {Tcl_ParseExpr procedure, error in conditional expression} \
    -constraints testexprparser -body {
        testexprparser {foo+} -1
	testexprparser {foo+} -1
    } -match glob -returnCodes error -result *
test parseExpr-1.5 {Tcl_ParseExpr procedure, lexemes after the expression} -constraints testexprparser -body {
    testexprparser {1+2 345} -1
} -returnCodes error -match glob -result *

test parseExpr-2.1 {ParseCondExpr procedure, valid test subexpr} testexprparser {
    testexprparser {2>3? 1 : 0} -1
} {- {} 0 subexpr {2>3? 1 : 0} 11 operator ? 0 subexpr 2>3 5 operator > 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-2.2 {ParseCondExpr procedure, error in test subexpr} \
	-constraints testexprparser -body {
            testexprparser {0 || foo} -1
	    testexprparser {0 || foo} -1
    } -match glob -returnCodes error -result *
test parseExpr-2.3 {ParseCondExpr procedure, next lexeme isn't "?"} testexprparser {
    testexprparser {1+2} -1
} {- {} 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
test parseExpr-2.4 {ParseCondExpr procedure, next lexeme is "?"} testexprparser {
    testexprparser {1+2 ? 3 : 4} -1
} {- {} 0 subexpr {1+2 ? 3 : 4} 11 operator ? 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-2.5 {ParseCondExpr procedure, bad lexeme after "?"} testexprparser {
    testexprparser {1+2 ? 12345678901234567890 : 0} -1
} {- {} 0 subexpr {1+2 ? 12345678901234567890 : 0} 11 operator ? 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 subexpr 0 1 text 0 0 {}}
test parseExpr-2.6 {ParseCondExpr procedure, valid "then" subexpression} testexprparser {
    testexprparser {1? 3 : 4} -1
} {- {} 0 subexpr {1? 3 : 4} 7 operator ? 0 subexpr 1 1 text 1 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-2.7 {ParseCondExpr procedure, error in "then" subexpression} \
    -constraints testexprparser -body {
        testexprparser {1? fred : martha} -1
	testexprparser {1? fred : martha} -1
    } -match glob -returnCodes error -result *
test parseExpr-2.8 {ParseCondExpr procedure, lexeme after "then" subexpr isn't ":"} -constraints testexprparser -body {
    testexprparser {1? 2 martha 3} -1
} -returnCodes error -match glob -result *
test parseExpr-2.9 {ParseCondExpr procedure, valid "else" subexpression} testexprparser {
    testexprparser {27||3? 3 : 4&&9} -1
} {- {} 0 subexpr {27||3? 3 : 4&&9} 15 operator ? 0 subexpr 27||3 5 operator || 0 subexpr 27 1 text 27 0 subexpr 3 1 text 3 0 subexpr 3 1 text 3 0 subexpr 4&&9 5 operator && 0 subexpr 4 1 text 4 0 subexpr 9 1 text 9 0 {}}
test parseExpr-2.10 {ParseCondExpr procedure, error in "else" subexpression} \
    -constraints testexprparser -body {
        testexprparser {1? 2 : martha} -1
	testexprparser {1? 2 : martha} -1
    } -match glob -returnCodes error -result *

test parseExpr-3.1 {ParseLorExpr procedure, valid logical and subexpr} testexprparser {
    testexprparser {1&&2 || 3} -1
} {- {} 0 subexpr {1&&2 || 3} 9 operator || 0 subexpr 1&&2 5 operator && 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-3.2 {ParseLorExpr procedure, error in logical and subexpr} \
    -constraints testexprparser -body {
        testexprparser {1&&foo || 3} -1
	testexprparser {1&&foo || 3} -1
    } -match glob -returnCodes error -result *
test parseExpr-3.3 {ParseLorExpr procedure, next lexeme isn't "||"} testexprparser {
    testexprparser {1&&2? 1 : 0} -1
} {- {} 0 subexpr {1&&2? 1 : 0} 11 operator ? 0 subexpr 1&&2 5 operator && 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-3.4 {ParseLorExpr procedure, next lexeme is "||"} testexprparser {
    testexprparser {1&&2 || 3} -1
} {- {} 0 subexpr {1&&2 || 3} 9 operator || 0 subexpr 1&&2 5 operator && 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-3.5 {ParseLorExpr procedure, bad lexeme after "||"} testexprparser {
    testexprparser {1&&2 || 12345678901234567890} -1
} {- {} 0 subexpr {1&&2 || 12345678901234567890} 9 operator || 0 subexpr 1&&2 5 operator && 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
test parseExpr-3.6 {ParseLorExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1&&2 || 3 || 4} -1
} {- {} 0 subexpr {1&&2 || 3 || 4} 13 operator || 0 subexpr {1&&2 || 3} 9 operator || 0 subexpr 1&&2 5 operator && 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-3.7 {ParseLorExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        testexprparser {1&&2 || 3 || martha} -1
	testexprparser {1&&2 || 3 || martha} -1
    } -match glob -returnCodes error -result *

test parseExpr-4.1 {ParseLandExpr procedure, valid LHS "|" subexpr} testexprparser {
    testexprparser {1|2 && 3} -1
} {- {} 0 subexpr {1|2 && 3} 9 operator && 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-4.2 {ParseLandExpr procedure, error in LHS "|" subexpr} \
    -constraints testexprparser -body {
        testexprparser {1&&foo && 3} -1
	testexprparser {1&&foo && 3} -1
    } -match glob -returnCodes error -result *
test parseExpr-4.3 {ParseLandExpr procedure, next lexeme isn't "&&"} testexprparser {
    testexprparser {1|2? 1 : 0} -1
} {- {} 0 subexpr {1|2? 1 : 0} 11 operator ? 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-4.4 {ParseLandExpr procedure, next lexeme is "&&"} testexprparser {
    testexprparser {1|2 && 3} -1
} {- {} 0 subexpr {1|2 && 3} 9 operator && 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-4.5 {ParseLandExpr procedure, bad lexeme after "&&"} testexprparser {
    testexprparser {1|2 && 12345678901234567890} -1
} {- {} 0 subexpr {1|2 && 12345678901234567890} 9 operator && 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
test parseExpr-4.6 {ParseLandExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1|2 && 3 && 4} -1
} {- {} 0 subexpr {1|2 && 3 && 4} 13 operator && 0 subexpr {1|2 && 3} 9 operator && 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-4.7 {ParseLandExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        testexprparser {1|2 && 3 && martha} -1
	testexprparser {1|2 && 3 && martha} -1
    } -match glob -returnCodes error -result *

test parseExpr-5.1 {ParseBitOrExpr procedure, valid LHS "^" subexpr} testexprparser {
    testexprparser {1^2 | 3} -1
} {- {} 0 subexpr {1^2 | 3} 9 operator | 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-5.2 {ParseBitOrExpr procedure, error in LHS "^" subexpr} \
    -constraints testexprparser -body {
        testexprparser {1|foo | 3} -1
	testexprparser {1|foo | 3} -1
    } -match glob -returnCodes error -result *
test parseExpr-5.3 {ParseBitOrExpr procedure, next lexeme isn't "|"} testexprparser {
    testexprparser {1^2? 1 : 0} -1
} {- {} 0 subexpr {1^2? 1 : 0} 11 operator ? 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-5.4 {ParseBitOrExpr procedure, next lexeme is "|"} testexprparser {
    testexprparser {1^2 | 3} -1
} {- {} 0 subexpr {1^2 | 3} 9 operator | 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-5.5 {ParseBitOrExpr procedure, bad lexeme after "|"} testexprparser {
    testexprparser {1^2 | 12345678901234567890} -1
} {- {} 0 subexpr {1^2 | 12345678901234567890} 9 operator | 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
test parseExpr-5.6 {ParseBitOrExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1^2 | 3 | 4} -1
} {- {} 0 subexpr {1^2 | 3 | 4} 13 operator | 0 subexpr {1^2 | 3} 9 operator | 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-5.7 {ParseBitOrExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        testexprparser {1^2 | 3 | martha} -1
	testexprparser {1^2 | 3 | martha} -1
    } -match glob -returnCodes error -result *

test parseExpr-6.1 {ParseBitXorExpr procedure, valid LHS "&" subexpr} testexprparser {
    testexprparser {1&2 ^ 3} -1
} {- {} 0 subexpr {1&2 ^ 3} 9 operator ^ 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-6.2 {ParseBitXorExpr procedure, error in LHS "&" subexpr} \
    -constraints testexprparser -body {
        testexprparser {1^foo ^ 3} -1
	testexprparser {1^foo ^ 3} -1
    } -match glob -returnCodes error -result *
test parseExpr-6.3 {ParseBitXorExpr procedure, next lexeme isn't "^"} testexprparser {
    testexprparser {1&2? 1 : 0} -1
} {- {} 0 subexpr {1&2? 1 : 0} 11 operator ? 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-6.4 {ParseBitXorExpr procedure, next lexeme is "^"} testexprparser {
    testexprparser {1&2 ^ 3} -1
} {- {} 0 subexpr {1&2 ^ 3} 9 operator ^ 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-6.5 {ParseBitXorExpr procedure, bad lexeme after "^"} testexprparser {
    testexprparser {1&2 ^ 12345678901234567890} -1
} {- {} 0 subexpr {1&2 ^ 12345678901234567890} 9 operator ^ 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
test parseExpr-6.6 {ParseBitXorExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1&2 ^ 3 ^ 4} -1
} {- {} 0 subexpr {1&2 ^ 3 ^ 4} 13 operator ^ 0 subexpr {1&2 ^ 3} 9 operator ^ 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-6.7 {ParseBitXorExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        testexprparser {1&2 ^ 3 ^ martha} -1
	testexprparser {1&2 ^ 3 ^ martha} -1
    } -match glob -returnCodes error -result *

test parseExpr-7.1 {ParseBitAndExpr procedure, valid LHS equality subexpr} testexprparser {
    testexprparser {1==2 & 3} -1
} {- {} 0 subexpr {1==2 & 3} 9 operator & 0 subexpr 1==2 5 operator == 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-7.2 {ParseBitAndExpr procedure, error in LHS equality subexpr} \
    -constraints testexprparser -body {
        testexprparser {1!=foo & 3} -1
	testexprparser {1!=foo & 3} -1
    } -match glob -returnCodes error -result *
test parseExpr-7.3 {ParseBitAndExpr procedure, next lexeme isn't "&"} testexprparser {
    testexprparser {1==2? 1 : 0} -1
} {- {} 0 subexpr {1==2? 1 : 0} 11 operator ? 0 subexpr 1==2 5 operator == 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-7.4 {ParseBitAndExpr procedure, next lexeme is "&"} testexprparser {
    testexprparser {1>2 & 3} -1
} {- {} 0 subexpr {1>2 & 3} 9 operator & 0 subexpr 1>2 5 operator > 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-7.5 {ParseBitAndExpr procedure, bad lexeme after "&"} {testexprparser} {
    testexprparser {1==2 & 12345678901234567890} -1
} {- {} 0 subexpr {1==2 & 12345678901234567890} 9 operator & 0 subexpr 1==2 5 operator == 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
test parseExpr-7.6 {ParseBitAndExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1<2 & 3 & 4} -1
} {- {} 0 subexpr {1<2 & 3 & 4} 13 operator & 0 subexpr {1<2 & 3} 9 operator & 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-7.7 {ParseBitAndExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        testexprparser {1==2 & 3>2 & martha} -1
	testexprparser {1==2 & 3>2 & martha} -1
    } -match glob -returnCodes error -result *

test parseExpr-8.1 {ParseEqualityExpr procedure, valid LHS relational subexpr} testexprparser {
    testexprparser {1<2 == 3} -1
} {- {} 0 subexpr {1<2 == 3} 9 operator == 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-8.2 {ParseEqualityExpr procedure, error in LHS relational subexpr} \
    -constraints testexprparser -body {
        testexprparser {1>=foo == 3} -1
	testexprparser {1>=foo == 3} -1
    } -match glob -returnCodes error -result *
test parseExpr-8.3 {ParseEqualityExpr procedure, next lexeme isn't "==" or "!="} testexprparser {
    testexprparser {1<2? 1 : 0} -1
} {- {} 0 subexpr {1<2? 1 : 0} 11 operator ? 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-8.4 {ParseEqualityExpr procedure, next lexeme is "==" or "!="} testexprparser {
    testexprparser {1<2 == 3} -1
} {- {} 0 subexpr {1<2 == 3} 9 operator == 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-8.5 {ParseEqualityExpr procedure, next lexeme is "==" or "!="} testexprparser {
    testexprparser {1<2 != 3} -1
} {- {} 0 subexpr {1<2 != 3} 9 operator != 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-8.6 {ParseEqualityExpr procedure, bad lexeme after "==" or "!="} testexprparser {
    testexprparser {1<2 == 12345678901234567890} -1
} {- {} 0 subexpr {1<2 == 12345678901234567890} 9 operator == 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
test parseExpr-8.7 {ParseEqualityExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1<2 == 3 == 4} -1
} {- {} 0 subexpr {1<2 == 3 == 4} 13 operator == 0 subexpr {1<2 == 3} 9 operator == 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-8.8 {ParseEqualityExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        testexprparser {1<2 == 3 != martha} -1
	testexprparser {1<2 == 3 != martha} -1
    } -match glob -returnCodes error -result *

test parseExpr-9.1 {ParseRelationalExpr procedure, valid LHS shift subexpr} testexprparser {
    testexprparser {1<<2 < 3} -1
} {- {} 0 subexpr {1<<2 < 3} 9 operator < 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-9.2 {ParseRelationalExpr procedure, error in LHS shift subexpr} \
    -constraints testexprparser -body {
        testexprparser {1>=foo < 3} -1
	testexprparser {1>=foo < 3} -1
    } -match glob -returnCodes error -result *
test parseExpr-9.3 {ParseRelationalExpr procedure, next lexeme isn't relational op} testexprparser {
    testexprparser {1<<2? 1 : 0} -1
} {- {} 0 subexpr {1<<2? 1 : 0} 11 operator ? 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-9.4 {ParseRelationalExpr procedure, next lexeme is relational op} testexprparser {
    testexprparser {1<<2 < 3} -1
} {- {} 0 subexpr {1<<2 < 3} 9 operator < 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
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
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
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
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







-
+







-
+


















-
+







-
+


















-
+







-
+


















-
+







    testexprparser {1<<2 < 12345678901234567890} -1
} {- {} 0 subexpr {1<<2 < 12345678901234567890} 9 operator < 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
test parseExpr-9.9 {ParseRelationalExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1<<2 < 3 < 4} -1
} {- {} 0 subexpr {1<<2 < 3 < 4} 13 operator < 0 subexpr {1<<2 < 3} 9 operator < 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-9.10 {ParseRelationalExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        testexprparser {1<<2 < 3 > martha} -1
	testexprparser {1<<2 < 3 > martha} -1
    } -match glob -returnCodes error -result *

test parseExpr-10.1 {ParseShiftExpr procedure, valid LHS add subexpr} testexprparser {
    testexprparser {1+2 << 3} -1
} {- {} 0 subexpr {1+2 << 3} 9 operator << 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-10.2 {ParseShiftExpr procedure, error in LHS add subexpr} \
    -constraints testexprparser -body {
        testexprparser {1-foo << 3} -1
	testexprparser {1-foo << 3} -1
    } -match glob -returnCodes error -result *
test parseExpr-10.3 {ParseShiftExpr procedure, next lexeme isn't "<<" or ">>"} testexprparser {
    testexprparser {1+2? 1 : 0} -1
} {- {} 0 subexpr {1+2? 1 : 0} 11 operator ? 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-10.4 {ParseShiftExpr procedure, next lexeme is "<<" or ">>"} testexprparser {
    testexprparser {1+2 << 3} -1
} {- {} 0 subexpr {1+2 << 3} 9 operator << 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-10.5 {ParseShiftExpr procedure, next lexeme is "<<" or ">>"} testexprparser {
    testexprparser {1+2 >> 3} -1
} {- {} 0 subexpr {1+2 >> 3} 9 operator >> 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-10.6 {ParseShiftExpr procedure, bad lexeme after "<<" or ">>"} testexprparser {
    testexprparser {1+2 << 12345678901234567890} -1
} {- {} 0 subexpr {1+2 << 12345678901234567890} 9 operator << 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
test parseExpr-10.7 {ParseShiftExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1+2 << 3 << 4} -1
} {- {} 0 subexpr {1+2 << 3 << 4} 13 operator << 0 subexpr {1+2 << 3} 9 operator << 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-10.8 {ParseShiftExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        testexprparser {1+2 << 3 >> martha} -1
	testexprparser {1+2 << 3 >> martha} -1
    } -match glob -returnCodes error -result *

test parseExpr-11.1 {ParseAddExpr procedure, valid LHS multiply subexpr} testexprparser {
    testexprparser {1*2 + 3} -1
} {- {} 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-11.2 {ParseAddExpr procedure, error in LHS multiply subexpr} \
    -constraints testexprparser -body {
        testexprparser {1/foo + 3} -1
	testexprparser {1/foo + 3} -1
    } -match glob -returnCodes error -result *
test parseExpr-11.3 {ParseAddExpr procedure, next lexeme isn't "+" or "-"} testexprparser {
    testexprparser {1*2? 1 : 0} -1
} {- {} 0 subexpr {1*2? 1 : 0} 11 operator ? 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-11.4 {ParseAddExpr procedure, next lexeme is "+" or "-"} testexprparser {
    testexprparser {1*2 + 3} -1
} {- {} 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-11.5 {ParseAddExpr procedure, next lexeme is "+" or "-"} testexprparser {
    testexprparser {1*2 - 3} -1
} {- {} 0 subexpr {1*2 - 3} 9 operator - 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-11.6 {ParseAddExpr procedure, bad lexeme after "+" or "-"} testexprparser {
    testexprparser {1*2 + 12345678901234567890} -1
} {- {} 0 subexpr {1*2 + 12345678901234567890} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
test parseExpr-11.7 {ParseAddExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1*2 + 3 + 4} -1
} {- {} 0 subexpr {1*2 + 3 + 4} 13 operator + 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-11.8 {ParseAddExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        testexprparser {1*2 + 3 - martha} -1
	testexprparser {1*2 + 3 - martha} -1
    } -match glob -returnCodes error -result *

test parseExpr-12.1 {ParseAddExpr procedure, valid LHS multiply subexpr} testexprparser {
    testexprparser {1*2 + 3} -1
} {- {} 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-12.2 {ParseAddExpr procedure, error in LHS multiply subexpr} \
    -constraints testexprparser -body {
        testexprparser {1/foo + 3} -1
	testexprparser {1/foo + 3} -1
    } -match glob -returnCodes error -result *
test parseExpr-12.3 {ParseAddExpr procedure, next lexeme isn't "+" or "-"} testexprparser {
    testexprparser {1*2? 1 : 0} -1
} {- {} 0 subexpr {1*2? 1 : 0} 11 operator ? 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-12.4 {ParseAddExpr procedure, next lexeme is "+" or "-"} testexprparser {
    testexprparser {1*2 + 3} -1
} {- {} 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-12.5 {ParseAddExpr procedure, next lexeme is "+" or "-"} testexprparser {
    testexprparser {1*2 - 3} -1
} {- {} 0 subexpr {1*2 - 3} 9 operator - 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-12.6 {ParseAddExpr procedure, bad lexeme after "+" or "-"} testexprparser {
    testexprparser {1*2 + 12345678901234567890} -1
} {- {} 0 subexpr {1*2 + 12345678901234567890} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
test parseExpr-12.7 {ParseAddExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1*2 + 3 + 4} -1
} {- {} 0 subexpr {1*2 + 3 + 4} 13 operator + 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-12.8 {ParseAddExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        testexprparser {1*2 + 3 - martha} -1
	testexprparser {1*2 + 3 - martha} -1
    } -match glob -returnCodes error -result *

test parseExpr-13.1 {ParseMultiplyExpr procedure, valid LHS unary subexpr} testexprparser {
    testexprparser {+2 * 3} -1
} {- {} 0 subexpr {+2 * 3} 7 operator * 0 subexpr +2 3 operator + 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-13.2 {ParseMultiplyExpr procedure, error in LHS unary subexpr} testexprparser {
    testexprparser {-12345678901234567890 * 3} -1
418
419
420
421
422
423
424
425

426
427
428
429
430
431
432
418
419
420
421
422
423
424

425
426
427
428
429
430
431
432







-
+







    testexprparser {--++5 / 12345678901234567890} -1
} {- {} 0 subexpr {--++5 / 12345678901234567890} 13 operator / 0 subexpr --++5 9 operator - 0 subexpr -++5 7 operator - 0 subexpr ++5 5 operator + 0 subexpr +5 3 operator + 0 subexpr 5 1 text 5 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
test parseExpr-13.8 {ParseMultiplyExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {-2 / 3 % 4} -1
} {- {} 0 subexpr {-2 / 3 % 4} 11 operator % 0 subexpr {-2 / 3} 7 operator / 0 subexpr -2 3 operator - 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-13.9 {ParseMultiplyExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        testexprparser {++2 / 3 * martha} -1
	testexprparser {++2 / 3 * martha} -1
    } -match glob -returnCodes error -result *

test parseExpr-14.1 {ParseUnaryExpr procedure, first token is unary operator} testexprparser {
    testexprparser {+2} -1
} {- {} 0 subexpr +2 3 operator + 0 subexpr 2 1 text 2 0 {}}
test parseExpr-14.2 {ParseUnaryExpr procedure, first token is unary operator} testexprparser {
    testexprparser {-2} -1
530
531
532
533
534
535
536
537

538
539
540
541
542
543
544
530
531
532
533
534
535
536

537
538
539
540
541
542
543
544







-
+







    testexprparser {foo(123)} -1
} {- {} 0 subexpr foo(123) 3 operator foo 0 subexpr 123 1 text 123 0 {}}
test parseExpr-15.23 {ParsePrimaryExpr procedure, bad lexeme after function name} -constraints testexprparser -body {
    testexprparser {foo 12345678901234567890 123)} -1
} -returnCodes error -match glob -result *
test parseExpr-15.24 {ParsePrimaryExpr procedure, lexeme after function name isn't "("} \
    -constraints testexprparser -body {
        testexprparser {foo 27.4 123)} -1
	testexprparser {foo 27.4 123)} -1
    } -match glob -returnCodes error -result *
test parseExpr-15.25 {ParsePrimaryExpr procedure, bad lexeme after "("} testexprparser {
    testexprparser {foo(12345678901234567890)} -1
} {- {} 0 subexpr foo(12345678901234567890) 3 operator foo 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
test parseExpr-15.26 {ParsePrimaryExpr procedure, function call, one arg} testexprparser {
    testexprparser {foo(27*4)} -1
} {- {} 0 subexpr foo(27*4) 7 operator foo 0 subexpr 27*4 5 operator * 0 subexpr 27 1 text 27 0 subexpr 4 1 text 4 0 {}}
878
879
880
881
882
883
884
885

886
887

888
889

890
891

892
893

894
895

896
897
898
899
900
901
902
903
904
905

906
907
908
909
910
911

912
913
914
915
916
917
918
919
920
921
922
923


924
925
926
927
928
929
930
878
879
880
881
882
883
884

885
886

887
888

889
890

891
892

893
894

895
896
897
898
899
900
901
902
903
904

905
906
907
908
909
910

911
912
913
914
915
916
917
918
919
920
921


922
923
924
925
926
927
928
929
930







-
+

-
+

-
+

-
+

-
+

-
+









-
+





-
+










-
-
+
+







} -returnCodes error -result {invalid character "@"
in expression "0@"abcdefghijklmnopqrstu..."}
test parseExpr-21.36 {error messages} -body {
    expr {"abcdefghijklmnopqrstuvwxyz"@"abcdefghijklmnopqrstuvwxyz"}
} -returnCodes error -result {invalid character "@"
in expression "...fghijklmnopqrstuvwxyz"@"abcdefghijklmnopqrstu..."}
test parseExpr-21.37 {error messages} -body {
    expr [format {"%s" @ 0} [string repeat \u00a7 25]]
    expr [format {"%s" @ 0} [string repeat \xA7 25]]
} -returnCodes error -result [format {invalid character "@"
in expression "...%s" @ 0"} [string repeat \u00a7 10]]
in expression "...%s" @ 0"} [string repeat \xA7 10]]
test parseExpr-21.38 {error messages} -body {
    expr [format {0 @ "%s"} [string repeat \u00a7 25]]
    expr [format {0 @ "%s"} [string repeat \xA7 25]]
} -returnCodes error -result [format {invalid character "@"
in expression "0 @ "%s..."} [string repeat \u00a7 10]]
in expression "0 @ "%s..."} [string repeat \xA7 10]]
test parseExpr-21.39 {error messages} -body {
    expr [format {"%s" @ "%s"} [string repeat \u00a7 25] [string repeat \u00a7 25]]
    expr [format {"%s" @ "%s"} [string repeat \xA7 25] [string repeat \xA7 25]]
} -returnCodes error -result [format {invalid character "@"
in expression "...%s" @ "%s..."} [string repeat \u00a7 10] [string repeat \u00a7 10]]
in expression "...%s" @ "%s..."} [string repeat \xA7 10] [string repeat \xA7 10]]
test parseExpr-21.40 {error messages} -body {
    catch {expr {"abcdefghijklmnopqrstuvwxyz"@0}} m o
    dict get $o -errorinfo
} -result {invalid character "@"
in expression "...fghijklmnopqrstuvwxyz"@0"
    (parsing expression ""abcdefghijklmnopqrstu...")
    invoked from within
"expr {"abcdefghijklmnopqrstuvwxyz"@0}"}
test parseExpr-21.41 {error messages} -body {
    catch {expr [format {"%s" @ 0} [string repeat \u00a7 25]]} m o
    catch {expr [format {"%s" @ 0} [string repeat \xA7 25]]} m o
    dict get $o -errorinfo
} -result [format {invalid character "@"
in expression "...%s" @ 0"
    (parsing expression ""%s...")
    invoked from within
"expr [format {"%%s" @ 0} [string repeat \u00a7 25]]"} [string repeat \u00a7 10] [string repeat \u00a7 10]]
"expr [format {"%%s" @ 0} [string repeat \xA7 25]]"} [string repeat \xA7 10] [string repeat \xA7 10]]
test parseExpr-21.42 {error message} -body {
    expr {123456789012345678901234567890*"abcdefghijklmnopqrstuvwxyz}
} -returnCodes error -result {missing "
in expression "...012345678901234567890*"abcdefghijklmnopqrstuv..."}
test parseExpr-21.43 {error message} -body {
    expr "123456789012345678901234567890*\"foobar\$\{abcdefghijklmnopqrstuvwxyz\""
} -returnCodes error -result "missing close-brace for variable name
in expression \"...8901234567890*\"foobar\$\{abcdefghijklmnopqrstuv...\""
test parseExpr-21.44 {error message} -body {
    expr {123456789012345678901234567890*"foo$bar(abcdefghijklmnopqrstuvwxyz"}
} -returnCodes error -result {missing )
in expression "...8901234567890*"foo$bar(abcdefghijklmnopqrstuv..."}
} -returnCodes error -result {invalid character in array index
in expression "...8901234567890*"foo$bar(abcdefghijklmnopqrstu..."}
test parseExpr-21.45 {error message} -body {
    expr {123456789012345678901234567890*"foo$bar([{}abcdefghijklmnopqrstuvwxyz])"}
} -returnCodes error -result {extra characters after close-brace
in expression "...234567890*"foo$bar([{}abcdefghijklmnopqrstuv..."}
test parseExpr-21.46 {error message} -body {
    expr {123456789012345678901234567890*"foo$bar([""abcdefghijklmnopqrstuvwxyz])"}
} -returnCodes error -result {extra characters after close-quote
1030
1031
1032
1033
1034
1035
1036
1037

1038
1039
1040
1041
1042
1043
1044
1030
1031
1032
1033
1034
1035
1036

1037
1038
1039
1040
1041
1042
1043
1044







-
+







    testexprparser 1e3_() -1
} -result {- {} 0 subexpr 1e3_() 1 operator 1e3_ 0 {}}
test parseExpr-22.10 {Bug 3401704} -constraints testexprparser -body {
    catch {testexprparser 1.3_() -1} m o
    dict get $o -errorcode
} -result {TCL PARSE EXPR BADCHAR}
test parseExpr-22.11 {Bug 3401704} -constraints testexprparser -body {
    catch {testexprparser 1e-3_() -1} m o
    catch {testexprparser 1e-3`() -1} m o
    dict get $o -errorcode
} -result {TCL PARSE EXPR BADCHAR}
test parseExpr-22.12 {Bug 3401704} -constraints testexprparser -body {
    catch {testexprparser naneq() -1} m o
    dict get $o -errorcode
} -result {TCL PARSE EXPR EMPTY}
test parseExpr-22.13 {Bug 3401704} -constraints testexprparser -body {
1062
1063
1064
1065
1066
1067
1068
1069

1070
1071
1072

1073
1074
1075

1076








1077
1078
1079
1080
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







-
+


-
+


-
+

+
+
+
+
+
+
+
+




} -result {TCL PARSE EXPR BADNUMBER BINARY}
test parseExpr-22.18 {Bug 3401704} -constraints testexprparser -body {
    catch {testexprparser 0b02 -1} m o
    dict get $o -errorcode
} -result {TCL PARSE EXPR BADNUMBER BINARY}

test parseExpr-22.19 {Bug d2ffcca163} -constraints testexprparser -body {
    testexprparser \u0433 -1
    testexprparser г -1
} -returnCodes error -match glob -result {*invalid character*}
test parseExpr-22.20 {Bug d2ffcca163} -constraints testexprparser -body {
    testexprparser \u043f -1
    testexprparser п -1
} -returnCodes error -match glob -result {*invalid character*}
test parseExpr-22.21 {Bug d2ffcca163} -constraints testexprparser -body {
    testexprparser in\u0433(0) -1
    testexprparser inг(0) -1
} -returnCodes error -match glob -result {missing operand*}

test parseExpr-23.1 {TIP 582: comments} -constraints testexprparser -body {
    testexprparser "7 # * 8 " -1
} -result {- {} 0 subexpr 7 1 text 7 0 {}}
test parseExpr-23.2 {TIP 582: comments} -constraints testexprparser -body {
    testexprparser "7 #\n* 8 " -1
} -result {- {} 0 subexpr {7 #
*} 5 operator # 0 subexpr 7 1 text 7 0 subexpr * 1 text * 0 {}}

# cleanup
cleanupTests
return

Changes to tests/parseOld.test.

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
30
31
32

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
30
-
+
-
-
+





-
-
-
+
+
+










-
+


-







# Commands covered:  set (plus basic command syntax).  Also tests the
# Commands covered:  set (plus basic command syntax).  This set
# procedures in the file tclOldParse.c.  This set of tests is an old
# one that predates the new parser in Tcl 8.1.
# of tests is an old one that predates the parser in Tcl 8.1.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testwordend [llength [info commands testwordend]]
testConstraint testbytestring [llength [info commands testbytestring]]

# Save the argv value for restoration later
set savedArgv $argv

proc fourArgs {a b c d} {
    global arg1 arg2 arg3 arg4
    set arg1 $a
131
132
133
134
135
136
137
138

139
140
141
142
143
144
145
129
130
131
132
133
134
135

136
137
138
139
140
141
142
143







-
+







format %s $b

]b
    set a
} a22b
test parseOld-4.4 {command substitution} {
    set a 7.7
    if [catch {expr int($a)}] {set a foo}
    if {[catch {expr {int($a)}}]} {set a foo}
    set a
} 7.7

# Variable substitution.

test parseOld-5.1 {variable substitution} {
    set a 123
260
261
262
263
264
265
266
267
268


269
270
271


272
273
274


275
276
277
278
279
280
281
258
259
260
261
262
263
264


265
266
267


268
269
270


271
272
273
274
275
276
277
278
279







-
-
+
+

-
-
+
+

-
-
+
+







} "x"
test parseOld-7.10 {backslash substitution} {
    eval "list a b\\\nc d"
} {a b c d}
test parseOld-7.11 {backslash substitution} {
    eval "list a \"b c\"\\\nd e"
} {a {b c} d e}
test parseOld-7.12 {backslash substitution} testbytestring {
    expr {[list \ua2] eq [testbytestring "\xc2\xa2"]}
test parseOld-7.12 {backslash substitution} {
    expr {[list \uA2] eq "¢"}
} 1
test parseOld-7.13 {backslash substitution} testbytestring {
    expr {[list \u4e21] eq [testbytestring "\xe4\xb8\xa1"]}
test parseOld-7.13 {backslash substitution} {
    expr {[list \u4E21] eq "両"}
} 1
test parseOld-7.14 {backslash substitution} testbytestring {
    expr {[list \u4e2k] eq [testbytestring "\xd3\xa2k"]}
test parseOld-7.14 {backslash substitution} {
    expr {[list \u4E2k] eq "Ó¢k"}
} 1

# Semi-colon.

test parseOld-8.1 {semi-colons} {
    set b 0
    getArgs a;set b 2
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
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







-
-
-
+
+
+





-
-
-
+
+
+







    while executing
"$x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000..."
    ("eval" body line 1)
    invoked from within
"eval \$x[format "%01000d" 0]("}}
test parseOld-10.15 {syntax errors, missplaced braces} {
    catch {
        proc misplaced_end_brace {} {
            set what foo
            set when [expr ${what}size - [set off$what]}]
	proc misplaced_end_brace {} {
	    set what foo
	    set when [expr ${what}size - [set off$what]}]
    } msg
    set msg
} {extra characters after close-brace}
test parseOld-10.16 {syntax errors, missplaced braces} {
    catch {
        set a {
            set what foo
            set when [expr ${what}size - [set off$what]}]
	set a {
	    set what foo
	    set when [expr ${what}size - [set off$what]}]
    } msg
    set msg
} {extra characters after close-brace}
test parseOld-10.17 {syntax errors, unusual spacing} {
    list [catch {return [ [1]]} msg] $msg
} {1 {invalid command name "1"}}
# Long values (stressing storage management)
451
452
453
454
455
456
457
458

459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
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
449
450
451
452
453
454
455

456
457
458
459
460


































































461
462

463
464
465
466
467
468
469
470







-
+




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


-
+







    set a old
    eval "  # set a new\\\\\nset a new"
    set a
} {new}

test parseOld-13.1 {comments at the end of a bracketed script} {
    set x "[
expr 1+1
expr {1+1}
# skip this!
]"
} {2}

test parseOld-14.1 {TclWordEnd procedure} {testwordend} {
    testwordend " 	\n abc"
} {c}
test parseOld-14.2 {TclWordEnd procedure} {testwordend} {
    testwordend "   \\\n"
} {}
test parseOld-14.3 {TclWordEnd procedure} {testwordend} {
    testwordend "   \\\n "
} { }
test parseOld-14.4 {TclWordEnd procedure} {testwordend} {
    testwordend {"abc"}
} {"}
#" Emacs formatting :^(
test parseOld-14.5 {TclWordEnd procedure} {testwordend} {
    testwordend {{xyz}}
} \}
test parseOld-14.6 {TclWordEnd procedure} {testwordend} {
    testwordend {{a{}b{}\}} xyz}
} "\} xyz"
test parseOld-14.7 {TclWordEnd procedure} {testwordend} {
    testwordend {abc[this is a]def ghi}
} {f ghi}
test parseOld-14.8 {TclWordEnd procedure} {testwordend} {
    testwordend "puts\\\n\n  "
} "s\\\n\n  "
test parseOld-14.9 {TclWordEnd procedure} {testwordend} {
    testwordend "puts\\\n   	"
} "s\\\n   	"
test parseOld-14.10 {TclWordEnd procedure} {testwordend} {
    testwordend "puts\\\n   	xyz"
} "s\\\n   	xyz"
test parseOld-14.11 {TclWordEnd procedure} {testwordend} {
    testwordend {a$x.$y(a long index) foo}
} ") foo"
test parseOld-14.12 {TclWordEnd procedure} {testwordend} {
    testwordend {abc; def}
} {; def}
test parseOld-14.13 {TclWordEnd procedure} {testwordend} {
    testwordend {abc def}
} {c def}
test parseOld-14.14 {TclWordEnd procedure} {testwordend} {
    testwordend {abc	def}
} {c	def}
test parseOld-14.15 {TclWordEnd procedure} {testwordend} {
    testwordend "abc\ndef"
} "c\ndef"
test parseOld-14.16 {TclWordEnd procedure} {testwordend} {
    testwordend "abc"
} {c}
test parseOld-14.17 {TclWordEnd procedure} {testwordend} {
    testwordend "a\000bc"
} {c}
test parseOld-14.18 {TclWordEnd procedure} {testwordend} {
    testwordend \[a\000\]
} {]}
test parseOld-14.19 {TclWordEnd procedure} {testwordend} {
    testwordend \"a\000\"
} {"}
#" Emacs formatting :^(
test parseOld-14.20 {TclWordEnd procedure} {testwordend} {
    testwordend a{\000}b
} {b}
test parseOld-14.21 {TclWordEnd procedure} {testwordend} {
    testwordend "   \000b"
} {b}

test parseOld-15.1 {TclScriptEnd procedure} {
    info complete {puts [
	expr 1+1
	expr {1+1}
	#this is a comment ]}
} {0}
test parseOld-15.2 {TclScriptEnd procedure} {
    info complete "abc\\\n"
} {0}
test parseOld-15.3 {TclScriptEnd procedure} {
    info complete "abc\\\\\n"

Changes to tests/pid.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  pid
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1995 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1995 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57







-
+







    close $f
    set pids
} -cleanup {
    removeFile test1
} -result {}
test pid-1.4 {pid command} pidDefined {
    list [catch {pid a b} msg] $msg
} {1 {wrong # args: should be "pid ?channelId?"}}
} {1 {wrong # args: should be "pid ?channel?"}}
test pid-1.5 {pid command} pidDefined {
    list [catch {pid gorp} msg] $msg
} {1 {can not find channel named "gorp"}}

# cleanup
::tcltest::cleanupTests
return

Changes to tests/pkgMkIndex.test.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







# This file contains tests for the pkg_mkIndex command.
# Note that the tests are limited to Tcl scripts only, there are no shared
# libraries against which to test.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

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

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
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







-
+












-
+







#  This package is split into two files, to test packages that are split over
#  multiple files.
package provide pkg2 1.0
namespace eval pkg2 {
    namespace export p2-1
}
proc pkg2::p2-1 { num } {
    return [expr $num * 2]
    return [expr {$num * 2}]
}
} [file join pkg pkg2_a.tcl]

makeFile {
#  This package is required by pkg1.
#  This package is split into two files, to test packages that are split over
#  multiple files.
package provide pkg2 1.0
namespace eval pkg2 {
    namespace export p2-2
}
proc pkg2::p2-2 { num } {
    return [expr $num * 3]
    return [expr {$num * 3}]
}
} [file join pkg pkg2_b.tcl]

test pkgMkIndex-4.1 {split package} {
    pkgtest::runIndex -lazy $fullPkgPath pkg2_a.tcl pkg2_b.tcl
} {0 {{pkg2:1.0 {tclPkgSetup {pkg2_a.tcl source ::pkg2::p2-1} {pkg2_b.tcl source ::pkg2::p2-2}}}}}

405
406
407
408
409
410
411
412

413
414
415

416
417
418
419
420
421
422
405
406
407
408
409
410
411

412
413
414

415
416
417
418
419
420
421
422







-
+


-
+








makeFile {
package provide pkg3 1.0
namespace eval pkg3 {
    namespace export p3-1 p3-2
}
proc pkg3::p3-1 { num } {
    return {[expr $num * 2]}
    return {[expr {$num * 2}]}
}
proc pkg3::p3-2 { num } {
    return {[expr $num * 3]}
    return {[expr {$num * 3}]}
}
} [file join pkg pkg3.tcl]

test pkgMkIndex-6.1 {pkg1 requires pkg3} {
    pkgtest::runIndex -lazy $fullPkgPath pkg1.tcl pkg3.tcl
} {0 {{pkg1:1.0 {tclPkgSetup {pkg1.tcl source {::pkg1::p1-1 ::pkg1::p1-2}}}} {pkg3:1.0 {tclPkgSetup {pkg3.tcl source {::pkg3::p3-1 ::pkg3::p3-2}}}}}}

486
487
488
489
490
491
492
493

494
495
496
497
498
499
500
486
487
488
489
490
491
492

493
494
495
496
497
498
499
500







-
+








removeFile [file join pkg pkg5.tcl]
removeFile [file join pkg pkg2_a.tcl]
removeFile [file join pkg pkg2_b.tcl]

makeFile {
#  This package requires circ2, and circ2 requires circ3, which in turn
#  requires circ1.  In case of cirularities, pkg_mkIndex should give up when
#  requires circ1.  In case of circularities, pkg_mkIndex should give up when
#  it gets stuck.
package require circ2 1.0
package provide circ1 1.0
namespace eval circ1 {
    namespace export c1-1 c1-2 c1-3 c1-4
}
proc circ1::c1-1 { num } {
516
517
518
519
520
521
522
523

524
525
526

527
528
529
530
531
532
533
516
517
518
519
520
521
522

523
524
525

526
527
528
529
530
531
532
533







-
+


-
+







#  requires circ1 to give us a circularity.
package require circ3 1.0
package provide circ2 1.0
namespace eval circ2 {
    namespace export c2-1 c2-2
}
proc circ2::c2-1 { num } {
    return [expr $num * [circ3::c3-1]]
    return [expr {$num * [circ3::c3-1]}]
}
proc circ2::c2-2 { num } {
    return [expr $num * [circ3::c3-2]]
    return [expr {$num * [circ3::c3-2]}]
}
} [file join pkg circ2.tcl]

makeFile {
#  This package is required by circ2, and in turn requires circ1. This closes
#  the circularity.
package require circ1 1.0
549
550
551
552
553
554
555
556

557
558
559
560
561
562
563


564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579



580
581
582
583
584
585

586
587
588
589
590
591
592

593
594
595
596
597
598
599
549
550
551
552
553
554
555

556
557
558
559
560
561


562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577


578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593

594
595
596
597
598
599
600
601







-
+





-
-
+
+














-
-
+
+
+






+






-
+








removeFile [file join pkg circ1.tcl]
removeFile [file join pkg circ2.tcl]
removeFile [file join pkg circ3.tcl]

# Some tests require the existence of one of the DLLs in the dltest directory
set x [file join [file dirname [info nameofexecutable]] dltest \
	pkga[info sharedlibextension]]
	tcl9pkga[info sharedlibextension]]
set dll "[file tail $x]Required"
testConstraint $dll [file exists $x]

if {[testConstraint $dll]} {
    makeFile {
#  This package provides Pkga, which is also provided by a DLL.
package provide Pkga 1.0
#  This package provides pkga, which is also provided by a DLL.
package provide pkga 1.0
proc pkga_neq { x } {
    return [expr {! [pkgq_eq $x]}]
}
} [file join pkg pkga.tcl]
    file copy -force $x $fullPkgPath
}
testConstraint exec [llength [info commands ::exec]]

test pkgMkIndex-10.1 {package in DLL and script} [list exec $dll] {
    # Do all [load]ing of shared libraries in another process, so we can
    # delete the file and not get stuck because we're holding a reference to
    # it.
    set cmd [list pkg_mkIndex -lazy $fullPkgPath [file tail $x] pkga.tcl]
    exec [interpreter] << $cmd
    pkgtest::runCreatedIndex {0 {}} -lazy $fullPkgPath pkga[info sharedlibextension] pkga.tcl
} "0 {{Pkga:1.0 {tclPkgSetup {pkga[info sharedlibextension] load {pkga_eq pkga_quote}} {pkga.tcl source pkga_neq}}}}"
    pkgtest::runCreatedIndex {0 {}} -lazy $fullPkgPath tcl9pkga[info sharedlibextension] pkga.tcl
} "0 {{pkga:1.0 {tclPkgSetup {tcl9pkga[info sharedlibextension] load {pkga_eq pkga_quote}} {pkga.tcl source pkga_neq}}}}"

test pkgMkIndex-10.2 {package in DLL hidden by -load} [list exec $dll] {
    # Do all [load]ing of shared libraries in another process, so we can
    # delete the file and not get stuck because we're holding a reference to
    # it.
    #
    # This test depends on context from prior test, so repeat it.

    set script \
	"[list pkg_mkIndex -lazy $fullPkgPath [file tail $x] pkga.tcl]"
    append script \n \
	"[list pkg_mkIndex -lazy -load Pkg* $fullPkgPath [file tail $x]]"
    exec [interpreter] << $script
    pkgtest::runCreatedIndex {0 {}} -lazy -load Pkg* -- $fullPkgPath pkga[info sharedlibextension]
} {0 {}}
} "0 {}"

if {[testConstraint $dll]} {
    file delete -force [file join $fullPkgPath [file tail $x]]
    removeFile [file join pkg pkga.tcl]
}

# Tolerate "namespace import" at the global scope
648
649
650
651
652
653
654
655

656
657
658
659
660
661
662
650
651
652
653
654
655
656

657
658
659
660
661
662
663
664







-
+








test pkgMkIndex-12.1 {same name procs in different namespace} {
    pkgtest::runIndex -lazy $fullPkgPath samename.tcl
} {0 {{football:1.0 {tclPkgSetup {samename.tcl source {::college::team ::pro::team}}}}}}

removeFile [file join pkg samename.tcl]

# Proc names with embedded spaces are properly listed (ie, correct number of
# Proc names with embedded spaces are properly listed (i.e. correct number of
# braces) in result
makeFile {
package provide spacename 1.0
proc {a b} {} {}
proc {c d} {} {}
} [file join pkg spacename.tcl]

Changes to tests/platform.test.

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
30
31
32
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
30
31
32






-
+





+











-
+
-







# The file tests the tcl_platform variable and platform package.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1999 by Scriptics Corporation
# Copyright © 1999 Scriptics Corporation
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require tcltest 2.5
source [file join [file dirname [info script]] tcltests.tcl]

namespace eval ::tcl::test::platform {
    namespace import ::tcltest::testConstraint
    namespace import ::tcltest::test
    namespace import ::tcltest::cleanupTests

    # This is not how [variable] works. See TIP 276.
    #variable ::tcl_platform
    namespace upvar :: tcl_platform tcl_platform

::tcltest::loadTestedCommands
catch [list package require -exact Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]
package require tcltests

testConstraint testCPUID [llength [info commands testcpuid]]
testConstraint testlongsize [llength [info commands testlongsize]]

test platform-1.0 {tcl_platform(engine)} {
  set tcl_platform(engine)
} {Tcl}

Changes to tests/proc-old.test.

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
30
31
32
33
34
35
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
30
31
32
33
34
35









-
-
-
+
+
+















-
+







# Commands covered:  proc, return, global
#
# This file, proc-old.test, includes the original set of tests for Tcl's
# proc, return, and global commands. There is now a new file proc.test
# that contains tests for the tclProc.c source file.
#
# Sourcing this file into Tcl runs the tests and generates output for
# errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
}

catch {rename t1 ""}
catch {rename foo ""}

proc tproc {} {return a; return b}
test proc-old-1.1 {simple procedure call and return} {tproc} a
proc tproc x {
    set x [expr $x+1]
    set x [expr {$x + 1}]
    return $x
}
test proc-old-1.2 {simple procedure call and return} {tproc 2} 3
test proc-old-1.3 {simple procedure call and return} {
    proc tproc {} {return foo}
} {}
test proc-old-1.4 {simple procedure call and return} {
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
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







-
+







-
+








-
+








-
+







    set x {}
    proc tproc {} {}   ;# body is shared with x
    list [tproc] [append x foo]
} {{} foo}

test proc-old-2.1 {local and global variables} {
    proc tproc x {
	set x [expr $x+1]
	set x [expr {$x + 1}]
	return $x
    }
    set x 42
    list [tproc 6] $x
} {7 42}
test proc-old-2.2 {local and global variables} {
    proc tproc x {
	set y [expr $x+1]
	set y [expr {$x + 1}]
	return $y
    }
    set y 18
    list [tproc 6] $y
} {7 18}
test proc-old-2.3 {local and global variables} {
    proc tproc x {
	global y
	set y [expr $x+1]
	set y [expr {$x + 1}]
	return $y
    }
    set y 189
    list [tproc 6] $y
} {7 7}
test proc-old-2.4 {local and global variables} {
    proc tproc x {
	global y
	return [expr $x+$y]
	return [expr {$x + $y}]
    }
    set y 189
    list [tproc 6] $y
} {195 189}
catch {unset _undefined_}
test proc-old-2.5 {local and global variables} {
    proc tproc x {
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
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







-
+






-
+

-
+






-
-
-
+
+
+







    do {global a; do {global a; unset a}; set a(z) 22}
    list [catch {array names a} msg] $msg
} {0 z}
test proc-old-3.7 {local and global arrays} {
    proc t1 {args} {global info; set info 1}
    catch {unset a}
    set info {}
    do {global a; trace var a(1) w t1}
    do {global a; trace add var a(1) write t1}
    set a(1) 44
    set info
} 1
test proc-old-3.8 {local and global arrays} {
    proc t1 {args} {global info; set info 1}
    catch {unset a}
    trace var a(1) w t1
    trace add var a(1) write t1
    set info {}
    do {global a; trace vdelete a(1) w t1}
    do {global a; trace remove variable a(1) write t1}
    set a(1) 44
    set info
} {}
test proc-old-3.9 {local and global arrays} {
    proc t1 {args} {global info; set info 1}
    catch {unset a}
    trace var a(1) w t1
    do {global a; trace vinfo a(1)}
} {{w t1}}
    trace add var a(1) write t1
    do {global a; trace info var a(1)}
} {{write t1}}
catch {unset a}

test proc-old-30.1 {arguments and defaults} {
    proc tproc {x y z} {
	return [list $x $y $z]
    }
    tproc 11 12 13
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
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







-
+











-
+







test proc-old-5.16 {error conditions} {
    proc foo args {
	global fooMsg
	set fooMsg "foo was called: $args"
    }
    proc tproc {} {
	set x 44
	trace var x u foo
	trace add var x unset foo
	while {$x < 100} {
	    error "Nested error"
	}
    }
    set fooMsg "foo not called"
    list [catch tproc msg] $msg $::errorInfo $fooMsg
} {1 {Nested error} {Nested error
    while executing
"error "Nested error""
    (procedure "tproc" line 5)
    invoked from within
"tproc"} {foo was called: x {} u}}
"tproc"} {foo was called: x {} unset}}

# The tests below will really only be useful when run under Purify or
# some other system that can detect accesses to freed memory...

test proc-old-6.1 {procedure that redefines itself} {
    proc tproc {} {
	proc tproc {} {
478
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
478
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







-
-
-
-
+
+
+
+







-
+







-
-
-
-
-
+
+
+
+
+









"tproc2"} none}
test proc-old-7.15 {return with special completion code} {
    list [catch {return -badOption foo message} msg] $msg
} {2 message}

test proc-old-8.1 {unset and undefined local arrays} {
    proc t1 {} {
        foreach v {xxx, yyy} {
            catch {unset $v}
        }
        set yyy(foo) bar
	foreach v {xxx, yyy} {
	    catch {unset $v}
	}
	set yyy(foo) bar
    }
    t1
} bar

test proc-old-9.1 {empty command name} {
    catch {rename {} ""}
    proc t1 {args} {
        return
	return
    }
    set v [t1]
    catch {$v}
} 1

test proc-old-10.1 {ByteCode epoch change during recursive proc execution} {
    proc t1 x {
        set y 20
        rename expr expr.old
        rename expr.old expr
        if $x then {t1 0} ;# recursive call after foo's code is invalidated
        return 20
	set y 20
	rename expr expr.old
	rename expr.old expr
	if {$x} then {t1 0} ;# recursive call after foo's code is invalidated
	return 20
    }
    t1 1
} 20

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

Changes to tests/proc.test.

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
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
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
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









-
-
+
+








+

-
+











-
+


-
+


-
-
+
+










-
+


-
+

-
+





-
-
-
-
-
+
+
+
+
+


-
+






-
-
-
+
+
+


-
-
+
+





-
-
+
+


-
-
-
-
-
-
+
+
+
+
+
+





-
+







# This file contains tests for the tclProc.c source file. Tests appear in the
# same order as the C code that they test. The set of tests is currently
# incomplete since it includes only new tests, in particular tests for code
# changed for the addition of Tcl namespaces. Other procedure-related tests
# appear in other test files such as proc-old.test.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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

testConstraint procbodytest [expr {![catch {package require procbodytest}]}]
testConstraint tcl::test [expr {![catch {package require tcl::test}]}]
testConstraint memory	    [llength [info commands memory]]

catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename p ""}
catch {rename {} ""}
catch {unset msg}

test proc-1.1 {Tcl_ProcObjCmd, put proc in namespace specified in name, if any} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
    namespace eval test_ns_1 {
        namespace eval baz {}
	namespace eval baz {}
    }
    proc test_ns_1::baz::p {} {
        return "p in [namespace current]"
	return "p in [namespace current]"
    }
    list [test_ns_1::baz::p] \
         [namespace eval test_ns_1 {baz::p}] \
         [info commands test_ns_1::baz::*]
	 [namespace eval test_ns_1 {baz::p}] \
	 [info commands test_ns_1::baz::*]
} -result {{p in ::test_ns_1::baz} {p in ::test_ns_1::baz} ::test_ns_1::baz::p}
test proc-1.2 {Tcl_ProcObjCmd, namespace specified in proc name must exist} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -returnCodes error -body {
    proc test_ns_1::baz::p {} {}
} -result {can't create procedure "test_ns_1::baz::p": unknown namespace}
test proc-1.3 {Tcl_ProcObjCmd, empty proc name} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
    proc :: {} {
        return "empty called"
	return "empty called"
    }
    list [::] \
         [info body {}]
	 [info body {}]
} -result {{empty called} {
        return "empty called"
	return "empty called"
    }}
test proc-1.4 {Tcl_ProcObjCmd, simple proc name and proc defined in namespace} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
    namespace eval test_ns_1 {
        namespace eval baz {
            proc p {} {
                return "p in [namespace current]"
            }
        }
	namespace eval baz {
	    proc p {} {
		return "p in [namespace current]"
	    }
	}
    }
    list [test_ns_1::baz::p] \
         [info commands test_ns_1::baz::*]
	 [info commands test_ns_1::baz::*]
} -result {{p in ::test_ns_1::baz} ::test_ns_1::baz::p}
test proc-1.5 {Tcl_ProcObjCmd, qualified proc name and proc defined in namespace} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
    namespace eval test_ns_1::baz {}
    namespace eval test_ns_1 {
        proc baz::p {} {
            return "p in [namespace current]"
        }
	proc baz::p {} {
	    return "p in [namespace current]"
	}
    }
    list [test_ns_1::baz::p] \
         [info commands test_ns_1::baz::*] \
         [namespace eval test_ns_1::baz {namespace which p}]
	 [info commands test_ns_1::baz::*] \
	 [namespace eval test_ns_1::baz {namespace which p}]
} -result {{p in ::test_ns_1::baz} ::test_ns_1::baz::p ::test_ns_1::baz::p}
test proc-1.6 {Tcl_ProcObjCmd, namespace code ignores single ":"s in middle or end of command names} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
    namespace eval test_ns_1 {
        proc q: {} {return "q:"}
        proc value:at: {} {return "value:at:"}
	proc q: {} {return "q:"}
	proc value:at: {} {return "value:at:"}
    }
    list [namespace eval test_ns_1 {q:}] \
         [namespace eval test_ns_1 {value:at:}] \
         [test_ns_1::q:] \
         [test_ns_1::value:at:] \
         [lsort [info commands test_ns_1::*]] \
         [namespace eval test_ns_1 {namespace which q:}] \
         [namespace eval test_ns_1 {namespace which value:at:}]
	 [namespace eval test_ns_1 {value:at:}] \
	 [test_ns_1::q:] \
	 [test_ns_1::value:at:] \
	 [lsort [info commands test_ns_1::*]] \
	 [namespace eval test_ns_1 {namespace which q:}] \
	 [namespace eval test_ns_1 {namespace which value:at:}]
} -result {q: value:at: q: value:at: {::test_ns_1::q: ::test_ns_1::value:at:} ::test_ns_1::q: ::test_ns_1::value:at:}
test proc-1.7 {Tcl_ProcObjCmd, check that formal parameter names are not array elements} -setup {
    catch {rename p ""}
} -returnCodes error -body {
    proc p {a(1) a(2)} {
	set z [expr $a(1)+$a(2)]
	set z [expr {$a(1)+$a(2)}]
	puts "$z=z, $a(1)=$a(1)"
    }
} -result {formal parameter "a(1)" is an array element}
test proc-1.8 {Tcl_ProcObjCmd, check that formal parameter names are simple names} -setup {
    catch {rename p ""}
} -body {
    proc p {b:a b::a} {
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
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







-
-
-
+
+
+








-
+







    proc p {} {return "p in [namespace current]"}
    info body p
} -result {return "p in [namespace current]"}
test proc-2.2 {TclFindProc, simple proc name and proc defined in namespace} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
    namespace eval test_ns_1 {
        namespace eval baz {
            proc p {} {return "p in [namespace current]"}
        }
	namespace eval baz {
	    proc p {} {return "p in [namespace current]"}
	}
    }
    namespace eval test_ns_1::baz {info body p}
} -result {return "p in [namespace current]"}
test proc-2.3 {TclFindProc, qualified proc name and proc defined in namespace} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
    namespace eval test_ns_1::baz {}
    namespace eval test_ns_1 {
        proc baz::p {} {return "p in [namespace current]"}
	proc baz::p {} {return "p in [namespace current]"}
    }
    namespace eval test_ns_1 {info body baz::p}
} -result {return "p in [namespace current]"}
test proc-2.4 {TclFindProc, global proc and executing in namespace} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    catch {rename p ""}
} -body {
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
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







-
-
+
+








-
+







-
-
-
+
+
+







    proc p {} {return "p in [namespace current]"}
    p
} -result {p in ::}
test proc-3.2 {TclObjInterpProc, proc defined and executing in same namespace} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
    namespace eval test_ns_1::baz {
        proc p {} {return "p in [namespace current]"}
        p
	proc p {} {return "p in [namespace current]"}
	p
    }
} -result {p in ::test_ns_1::baz}
test proc-3.3 {TclObjInterpProc, proc defined and executing in different namespaces} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    catch {rename p ""}
} -body {
    proc p {} {return "p in [namespace current]"}
    namespace eval test_ns_1::baz {
        p
	p
    }
} -result {p in ::}
test proc-3.4 {TclObjInterpProc, procs execute in the namespace in which they were defined unless renamed into new namespace} -setup {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
    catch {rename p ""}
} -body {
    namespace eval test_ns_1::baz {
        proc p {} {return "p in [namespace current]"}
        rename ::test_ns_1::baz::p ::p
        list [p] [namespace which p]
	proc p {} {return "p in [namespace current]"}
	rename ::test_ns_1::baz::p ::p
	list [p] [namespace which p]
    }
} -result {{p in ::} ::p}
test proc-3.5 {TclObjInterpProc, any old result is reset before appending error msg about missing arguments} -body {
    proc p {x} {info commands 3m}
    p
} -returnCodes error -result {wrong # args: should be "p x"}
test proc-3.6 {TclObjInterpProc, proper quoting of proc name, Bug 942757} -body {
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
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







-
+



-
+


-
+











-
+

-
+









-
+

-
+










-
+

-
+










-
+

-
+










-
+

-
+










-
+

-
+













-
+


-
+








-
-
+
+

+
+
+
+
+
+
+
+
+







catch {rename {a b  c} {}}
catch {unset msg}

catch {rename p ""}
catch {rename t ""}

# Note that the test require that procedures whose body is used to create
# procbody objects must be executed before the procbodytest::proc command is
# procbody objects must be executed before the tcl::procbodytest::proc command is
# executed, so that the Proc struct is populated correctly (CompiledLocals are
# added at compile time).

test proc-4.1 {TclCreateProc, procbody obj} -constraints procbodytest -body {
test proc-4.1 {TclCreateProc, procbody obj} -constraints tcl::test -body {
    proc p x {return "$x:$x"}
    set rv [p P]
    procbodytest::proc t x p
    tcl::procbodytest::proc t x p
    lappend rv [t T]
} -cleanup {
    catch {rename p ""}
    catch {rename t ""}
} -result {P:P T:T}
test proc-4.2 {TclCreateProc, procbody obj, use compiled locals} -body {
    proc p x {
	set y [string tolower $x]
	return "$x:$y"
    }
    set rv [p P]
    procbodytest::proc t x p
    tcl::procbodytest::proc t x p
    lappend rv [t T]
} -constraints procbodytest -cleanup {
} -constraints tcl::test -cleanup {
    catch {rename p ""}
    catch {rename t ""}
} -result {P:p T:t}
test proc-4.3 {TclCreateProc, procbody obj, too many args} -body {
    proc p x {
	set y [string tolower $x]
	return "$x:$y"
    }
    set rv [p P]
    procbodytest::proc t {x x1 x2} p
    tcl::procbodytest::proc t {x x1 x2} p
    lappend rv [t T]
} -constraints procbodytest -returnCodes error -cleanup {
} -constraints tcl::test -returnCodes error -cleanup {
    catch {rename p ""}
    catch {rename t ""}
} -result {procedure "t": arg list contains 3 entries, precompiled header expects 1}
test proc-4.4 {TclCreateProc, procbody obj, inconsistent arg name} -body {
    proc p {x y z} {
	set v [join [list $x $y $z]]
	set w [string tolower $v]
	return "$v:$w"
    }
    set rv [p P Q R]
    procbodytest::proc t {x x1 z} p
    tcl::procbodytest::proc t {x x1 z} p
    lappend rv [t S T U]
} -constraints procbodytest -returnCodes error -cleanup {
} -constraints tcl::test -returnCodes error -cleanup {
    catch {rename p ""}
    catch {rename t ""}
} -result {procedure "t": formal parameter 1 is inconsistent with precompiled body}
test proc-4.5 {TclCreateProc, procbody obj, inconsistent arg default type} -body {
    proc p {x y {z Z}} {
	set v [join [list $x $y $z]]
	set w [string tolower $v]
	return "$v:$w"
    }
    set rv [p P Q R]
    procbodytest::proc t {x y z} p
    tcl::procbodytest::proc t {x y z} p
    lappend rv [t S T U]
} -constraints procbodytest -returnCodes error -cleanup {
} -constraints tcl::test -returnCodes error -cleanup {
    catch {rename p ""}
    catch {rename t ""}
} -result {procedure "t": formal parameter 2 is inconsistent with precompiled body}
test proc-4.6 {TclCreateProc, procbody obj, inconsistent arg default type} -body {
    proc p {x y z} {
	set v [join [list $x $y $z]]
	set w [string tolower $v]
	return "$v:$w"
    }
    set rv [p P Q R]
    procbodytest::proc t {x y {z Z}} p
    tcl::procbodytest::proc t {x y {z Z}} p
    lappend rv [t S T U]
} -returnCodes error -constraints procbodytest -cleanup {
} -returnCodes error -constraints tcl::test -cleanup {
    catch {rename p ""}
    catch {rename t ""}
} -result {procedure "t": formal parameter 2 is inconsistent with precompiled body}
test proc-4.7 {TclCreateProc, procbody obj, inconsistent arg default value} -body {
    proc p {x y {z Z}} {
	set v [join [list $x $y $z]]
	set w [string tolower $v]
	return "$v:$w"
    }
    set rv [p P Q R]
    procbodytest::proc t {x y {z ZZ}} p
    tcl::procbodytest::proc t {x y {z ZZ}} p
    lappend rv [t S T U]
} -constraints procbodytest -returnCodes error -cleanup {
} -constraints tcl::test -returnCodes error -cleanup {
    catch {rename p ""}
    catch {rename t ""}
} -result {procedure "t": formal parameter "z" has default value inconsistent with precompiled body}
test proc-4.8 {TclCreateProc, procbody obj, no leak on multiple iterations} -setup {
    proc getbytes {} {
	set lines [split [memory info] "\n"]
	lindex $lines 3 3
    }
    proc px x {
	set y [string tolower $x]
	return "$x:$y"
    }
    px x
} -constraints {procbodytest memory} -body {
} -constraints {tcl::test memory} -body {
    set end [getbytes]
    for {set i 0} {$i < 5} {incr i} {
	procbodytest::proc tx x px
	tcl::procbodytest::proc tx x px
	set tmp $end
	set end [getbytes]
    }
    set leakedBytes [expr {$end - $tmp}]
} -cleanup {
    rename getbytes {}
    unset -nocomplain end i tmp leakedBytes
} -result 0
test proc-4.9 {[39fed4dae5] Valid Tcl_PkgPresent return} procbodytest {
    procbodytest::check
test proc-4.9 {[39fed4dae5] Valid Tcl_PkgPresent return} tcl::test {
    tcl::procbodytest::check
} 1
test proc-4.10 {
    TclCreateProc, issue a8579d906a28, argument with no name
} -body {
    catch {
	proc p1 [list [list [expr {1 + 2}] default]] {}
    }
} -cleanup {
    catch {rename p1 {}}
} -result 0

test proc-5.1 {Bytecompiling noop; test for correct argument substitution} -body {
    proc p args {} ; # this will be bytecompiled into t
    proc t {} {
	set res {}
	set a 0
	set b 0
397
398
399
400
401
402
403







404
405
406
407
408
409
410
411
412
413
414
415
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







+
+
+
+
+
+
+













test proc-7.5 {[631b4c45df] Crash in argument processing} {
    binary scan A c val
    proc foo [list  [list from $val]] {}
    rename foo {}
    unset -nocomplain val
} {}

test proc-7.6 {[51d5f22997] Crash in argument processing} -cleanup {
    rename foo {}
} -body {
    proc foo {{x {}} {y {}} args} {}
    foo
} -result {}


# cleanup
catch {rename p ""}
catch {rename t ""}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:

Changes to tests/process.test.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







# process.test --
#
# This file contains a collection of tests for the tcl::process ensemble.
# Sourcing this file into Tcl runs the tests and generates output for
# errors.  No output means no errors were found.
#
# Copyright (c) 2017 Frederic Bonnet
# Copyright © 2017 Frederic Bonnet
# 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::*
}
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
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







-
-
-
-
-
+
+
+
+
+















-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+









-
-
-
+
+
+








-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
















-
-
-
-
-
+
+
+
+
+


















-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+











-
-
-
+
+
+









-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

















-
-
+
+







test process-4.1 {exec one child} -body {
    tcl::process autopurge 0
    set pid [exec [interpreter] $path(exit) 0 &]
    set list [tcl::process list]
    set statuses [tcl::process status -wait]
    set status [lindex [tcl::process status $pid] 1]
    expr {
           [llength $list] eq 1
        && [lindex $list 0] eq $pid
        && [dict size $statuses] eq 1
        && [dict get $statuses $pid] eq $status
        && $status eq 0
	   [llength $list] eq 1
	&& [lindex $list 0] eq $pid
	&& [dict size $statuses] eq 1
	&& [dict get $statuses $pid] eq $status
	&& $status eq 0
    }
} -result {1} -cleanup {
    tcl::process purge
    tcl::process autopurge 1
}
# - Two children
test process-4.2 {exec two children in parallel} -body {
    tcl::process autopurge 0
    set pid1 [exec [interpreter] $path(exit) 0 &]
    set pid2 [exec [interpreter] $path(exit) 0 &]
    set list [tcl::process list]
    set statuses [tcl::process status -wait]
    set status1 [lindex [tcl::process status $pid1] 1]
    set status2 [lindex [tcl::process status $pid2] 1]
    expr {
           [llength $list] eq 2
        && [lsearch $list $pid1] >= 0
        && [lsearch $list $pid2] >= 0
        && [dict size $statuses] eq 2
        && [dict get $statuses $pid1] eq $status1
        && [dict get $statuses $pid2] eq $status2
        && $status1 eq 0
        && $status2 eq 0
	   [llength $list] eq 2
	&& [lsearch $list $pid1] >= 0
	&& [lsearch $list $pid2] >= 0
	&& [dict size $statuses] eq 2
	&& [dict get $statuses $pid1] eq $status1
	&& [dict get $statuses $pid2] eq $status2
	&& $status1 eq 0
	&& $status2 eq 0
    }
} -result {1} -cleanup {
    tcl::process purge
    tcl::process autopurge 1
}
# - 3-stage pipe
test process-4.3 {exec 3-stage pipe} -body {
    tcl::process autopurge 0
    set pids [exec \
          [interpreter] $path(exit) 0 \
        | [interpreter] $path(exit) 0 \
        | [interpreter] $path(exit) 0 \
	  [interpreter] $path(exit) 0 \
	| [interpreter] $path(exit) 0 \
	| [interpreter] $path(exit) 0 \
    &]
    lassign $pids pid1 pid2 pid3
    set list [tcl::process list]
    set statuses [tcl::process status -wait]
    set status1 [lindex [tcl::process status $pid1] 1]
    set status2 [lindex [tcl::process status $pid2] 1]
    set status3 [lindex [tcl::process status $pid3] 1]
    expr {
           [llength $pids] eq 3
        && [llength $list] eq 3
        && [lsearch $list $pid1] >= 0
        && [lsearch $list $pid2] >= 0
        && [lsearch $list $pid3] >= 0
        && [dict size $statuses] eq 3
        && [dict get $statuses $pid1] eq $status1
        && [dict get $statuses $pid2] eq $status2
        && [dict get $statuses $pid3] eq $status3
        && $status1 eq 0
        && $status2 eq 0
        && $status3 eq 0
	   [llength $pids] eq 3
	&& [llength $list] eq 3
	&& [lsearch $list $pid1] >= 0
	&& [lsearch $list $pid2] >= 0
	&& [lsearch $list $pid3] >= 0
	&& [dict size $statuses] eq 3
	&& [dict get $statuses $pid1] eq $status1
	&& [dict get $statuses $pid2] eq $status2
	&& [dict get $statuses $pid3] eq $status3
	&& $status1 eq 0
	&& $status2 eq 0
	&& $status3 eq 0
    }
} -result {1} -cleanup {
    tcl::process purge
    tcl::process autopurge 1
}

# Spawn subprocesses using [open "|"]
# - One child
test process-5.1 {exec one child} -body {
    tcl::process autopurge 0
    set f [open "|\"[interpreter]\" \"$path(exit)\" 0"]
    set pid [pid $f]
    set list [tcl::process list]
    set statuses [tcl::process status -wait]
    set status [lindex [tcl::process status $pid] 1]
    expr {
           [llength $list] eq 1
        && [lindex $list 0] eq $pid
        && [dict size $statuses] eq 1
        && [dict get $statuses $pid] eq $status
        && $status eq 0
	   [llength $list] eq 1
	&& [lindex $list 0] eq $pid
	&& [dict size $statuses] eq 1
	&& [dict get $statuses $pid] eq $status
	&& $status eq 0
    }
} -result {1} -cleanup {
    close $f
    tcl::process purge
    tcl::process autopurge 1
}
# - Two children
test process-5.2 {exec two children in parallel} -body {
    tcl::process autopurge 0
    set f1 [open "|\"[interpreter]\" \"$path(exit)\" 0"]
    set f2 [open "|\"[interpreter]\" \"$path(exit)\" 0"]
    set pid1 [pid $f1]
    set pid2 [pid $f2]
    set list [tcl::process list]
    set statuses [tcl::process status -wait]
    set status1 [lindex [tcl::process status $pid1] 1]
    set status2 [lindex [tcl::process status $pid2] 1]
    expr {
           [llength $list] eq 2
        && [lsearch $list $pid1] >= 0
        && [lsearch $list $pid2] >= 0
        && [dict size $statuses] eq 2
        && [dict get $statuses $pid1] eq $status1
        && [dict get $statuses $pid2] eq $status2
        && $status1 eq 0
        && $status2 eq 0
	   [llength $list] eq 2
	&& [lsearch $list $pid1] >= 0
	&& [lsearch $list $pid2] >= 0
	&& [dict size $statuses] eq 2
	&& [dict get $statuses $pid1] eq $status1
	&& [dict get $statuses $pid2] eq $status2
	&& $status1 eq 0
	&& $status2 eq 0
    }
} -result {1} -cleanup {
    close $f1
    close $f2
    tcl::process purge
    tcl::process autopurge 1
}
# - 3-stage pipe
test process-5.3 {exec 3-stage pipe} -body {
    tcl::process autopurge 0
    set f [open "|
          \"[interpreter]\" \"$path(exit)\" 0
        | \"[interpreter]\" \"$path(exit)\" 0
        | \"[interpreter]\" \"$path(exit)\" 0
	  \"[interpreter]\" \"$path(exit)\" 0
	| \"[interpreter]\" \"$path(exit)\" 0
	| \"[interpreter]\" \"$path(exit)\" 0
    "]
    set pids [pid $f]
    lassign $pids pid1 pid2 pid3
    set list [tcl::process list]
    set statuses [tcl::process status -wait]
    set status1 [lindex [tcl::process status $pid1] 1]
    set status2 [lindex [tcl::process status $pid2] 1]
    set status3 [lindex [tcl::process status $pid3] 1]
    expr {
           [llength $pids] eq 3
        && [llength $list] eq 3
        && [lsearch $list $pid1] >= 0
        && [lsearch $list $pid2] >= 0
        && [lsearch $list $pid3] >= 0
        && [dict size $statuses] eq 3
        && [dict get $statuses $pid1] eq $status1
        && [dict get $statuses $pid2] eq $status2
        && [dict get $statuses $pid3] eq $status3
        && $status1 eq 0
        && $status2 eq 0
        && $status3 eq 0
	   [llength $pids] eq 3
	&& [llength $list] eq 3
	&& [lsearch $list $pid1] >= 0
	&& [lsearch $list $pid2] >= 0
	&& [lsearch $list $pid3] >= 0
	&& [dict size $statuses] eq 3
	&& [dict get $statuses $pid1] eq $status1
	&& [dict get $statuses $pid2] eq $status2
	&& [dict get $statuses $pid3] eq $status3
	&& $status1 eq 0
	&& $status2 eq 0
	&& $status3 eq 0
    }
} -result {1} -cleanup {
    close $f
    tcl::process purge
    tcl::process autopurge 1
}

# Async child status
test process-6.1 {async status} -setup {
    signal_exit $path(test-signalfile) 0; # clean signal-file
} -body {
    tcl::process autopurge 0
    set pid [exec [interpreter] $path(sleep) 1 $path(test-signalfile) &]
    set status1 [lindex [tcl::process status $pid] 1]
    signal_exit $path(test-signalfile); # signal exit (stop sleep)
    set status2 [lindex [tcl::process status -wait $pid] 1]
    expr {
           $status1 eq {}
        && $status2 eq 0
	   $status1 eq {}
	&& $status2 eq 0
    }
} -result {1} -cleanup {
    tcl::process purge
    tcl::process autopurge 1
}
test process-6.2 {selective wait} -setup {
    signal_exit $path(test-signalfile)  0; # clean signal-files
290
291
292
293
294
295
296
297
298
299
300
301
302






303
304
305
306
307
308
309
290
291
292
293
294
295
296






297
298
299
300
301
302
303
304
305
306
307
308
309







-
-
-
-
-
-
+
+
+
+
+
+







    set status2_1 [lindex [tcl::process status -wait $pid1] 1]
    set status2_2 [lindex [tcl::process status $pid2] 1]
    # Wait until child 2 termination
    signal_exit $path(test-signalfile2); # signal exit for pid2 (stop sleep)
    set status3_2 [lindex [tcl::process status -wait $pid2] 1]
    set status3_1 [lindex [tcl::process status $pid1] 1]
    expr {
           $status1_1 eq {}
        && $status1_2 eq {}
        && $status2_1 eq 0
        && $status2_2 eq {}
        && $status3_1 eq 0
        && $status3_2 eq 0
	   $status1_1 eq {}
	&& $status1_2 eq {}
	&& $status2_1 eq 0
	&& $status2_2 eq {}
	&& $status3_1 eq 0
	&& $status3_2 eq 0
    }
} -result {1} -cleanup {
    tcl::process purge
    tcl::process autopurge 1
}

# Error codes

Changes to tests/pwd.test.

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
30
31
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
30
31
32






-
-
-
+
+
+













-
+

+
-
+






# Commands covered:  pwd
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
}

test pwd-1.1 {simple pwd} {
    catch pwd
} 0
test pwd-1.2 {simple pwd} {
    expr [string length pwd]>0
    expr {[string length [pwd]]>0}
} 1

test pwd-1.3 {pwd takes no args} -body {
test pwd-2.1 {pwd takes no args} -body {
    pwd foobar
} -returnCodes error -result "wrong \# args: should be \"pwd\""

# cleanup
::tcltest::cleanupTests
return

Changes to tests/reg.test.

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
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









-
+







-
+







# reg.test --
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
# (Don't panic if you are seeing this as part of the reg distribution
# and aren't using Tcl -- reg's own regression tester also knows how
# to read this file, ignoring the Tcl-isms.)
#
# Copyright (c) 1998, 1999 Henry Spencer.  All rights reserved.
# Copyright © 1998, 1999 Henry Spencer.  All rights reserved.

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

::tcltest::loadTestedCommands
catch [list package require -exact Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

# All tests require the testregexp command, return if this
# command doesn't exist

::tcltest::testConstraint testregexp [llength [info commands testregexp]]
::tcltest::testConstraint localeRegexp 0

335
336
337
338
339
340
341
342

343
344
345
346
347
348
349
335
336
337
338
339
340
341

342
343
344
345
346
347
348
349







-
+







######## the tests themselves ########

# support functions and preliminary misc.
# This is sensitive to changes in message wording, but we really have to
# test the code->message expansion at least once.
::tcltest::test reg-0.1 "regexp error reporting" {
    list [catch {regexp (*) ign} msg] $msg
} {1 {couldn't compile regular expression pattern: quantifier operand invalid}}
} {1 {cannot compile regular expression pattern: invalid quantifier operand}}


doing 1 "basic sanity checks"
expectMatch	1.1 &		abc	abc		abc
expectNomatch	1.2 &		abc	def
expectMatch	1.3 &		abc	xyabxabce	abc

510
511
512
513
514
515
516
517
518


519
520
521
522
523
524
525
510
511
512
513
514
515
516


517
518
519
520
521
522
523
524
525







-
-
+
+







expectMatch	9.37 bE		{a[\]]b}	"a\\]b"	"a\\]b"
expectMatch	9.38 eE		{a[\]]b}	"a\\]b"	"a\\]b"
expectMatch	9.39 EP		{a[\\]b}	"a\\b"	"a\\b"
expectMatch	9.40 eE		{a[\\]b}	"a\\b"	"a\\b"
expectMatch	9.41 bE		{a[\\]b}	"a\\b"	"a\\b"
expectError	9.42 -		{a[\Z]b}	EESCAPE
expectMatch	9.43 &		{a[[b]c}	"a\[c"	"a\[c"
expectMatch	9.44 EMP*	{a[\u00fe-\u0507][\u00ff-\u0300]b} \
	"a\u0102\u02ffb"	"a\u0102\u02ffb"
expectMatch	9.44 EMP*	{a[\xFE-\u0507][\xFF-\u0300]b} \
	"a\u0102\u02FFb"	"a\u0102\u02FFb"


doing 10 "anchors and newlines"
expectMatch	10.1  &		^a	a	a
expectNomatch	10.2  &^	^a	a
expectIndices	10.3  &N	^	a	{0 -1}
expectIndices	10.4  &		{a$}	aba	{2 2}
639
640
641
642
643
644
645
646
647


648
649
650
651
652
653
654
639
640
641
642
643
644
645


646
647
648
649
650
651
652
653
654







-
-
+
+







expectMatch	13.26 MP	"a\\010b"	"a\bb"	"a\bb"
expectMatch	13.27 P		"a\\U00001234x"	"a\u1234x"	"a\u1234x"
expectMatch	13.28 P		{a\U00001234x}	"a\u1234x"	"a\u1234x"
expectMatch	13.29 P		"a\\U0001234x"	"a\u1234x"	"a\u1234x"
expectMatch	13.30 P		{a\U0001234x}	"a\u1234x"	"a\u1234x"
expectMatch	13.31 P		"a\\U000012345x"	"a\u12345x"	"a\u12345x"
expectMatch	13.32 P		{a\U000012345x}	"a\u12345x"	"a\u12345x"
expectMatch	13.33 P		"a\\U1000000x"	"a\ufffd0x"	"a\ufffd0x"
expectMatch	13.34 P		{a\U1000000x}	"a\ufffd0x"	"a\ufffd0x"
expectMatch	13.33 P		"a\\U100000x"	"a\U100000x"	"a\U100000x"
expectMatch	13.34 P		{a\U100000x}	"a\U100000x"	"a\U100000x"


doing 14 "back references"
# ugh
expectMatch	14.1  RP	{a(b*)c\1}	abbcbb	abbcbb	bb
expectMatch	14.2  RP	{a(b*)c\1}	ac	ac	""
expectNomatch	14.3  RP	{a(b*)c\1}	abbcb
1217
1218
1219
1220
1221
1222
1223




1224
1225
1226
1227
1228
1229
1230
1231
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235







+
+
+
+








    # This is near the limits of the RE engine
    regexp [string repeat x*y*z* 480] x
} 1

test reg-33.30 {Bug 1080042} {
    regexp {(\Y)+} foo
} 1
test reg-33.31 {Bug 7c64aa5e1a} {
    regexp -inline {(?b).\{1,10\}} {abcdef}
} abcdef


# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/regexp.test.

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
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






-
-
-
+
+
+










-
+







# Commands covered:  regexp, regsub
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1998 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1998 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
}

unset -nocomplain foo

source [file join [file dirname [info script]] tcltests.tcl]
testConstraint exec [llength [info commands exec]]

# Used for constraining memory leak tests
testConstraint memory [llength [info commands memory]]
if {[testConstraint memory]} {
    proc memtest script {
	set end [lindex [split [memory info] \n] 3 3]
50
51
52
53
54
55
56
57
58


59
60
61
62
63
64
65
50
51
52
53
54
55
56


57
58
59
60
61
62
63
64
65







-
-
+
+







    regexp {^([^ ]*)[ ]*([^ ]*)} "" a
} 1
test regexp-1.6 {basic regexp operation} {
    list [catch {regexp {} abc} msg] $msg
} {0 1}
test regexp-1.7 {regexp utf compliance} {
    # if not UTF-8 aware, result is "0 1"
    set foo "\u4e4eb q"
    regexp "\u4e4eb q" "a\u4e4eb qw\u5e4e\x4e wq" bar
    set foo "乎b q"
    regexp "乎b q" "a乎b qw幎N wq" bar
    list [string compare $foo $bar] [regexp 4 $bar]
} {0 0}
test regexp-1.8 {regexp ***= metasyntax} {
    regexp -- "***=o" "aeiou"
} 1
test regexp-1.9 {regexp ***= metasyntax} {
    set string "aeiou"
190
191
192
193
194
195
196
197

198
199
200
201
202

203
204

205
206
207
208
209
210
211
190
191
192
193
194
195
196

197
198
199
200
201

202
203

204
205
206
207
208
209
210
211







-
+




-
+

-
+







} {1 {1 1} {1 1} {-1 -1} {-1 -1}}
test regexp-3.7 {getting substrings back from regexp} {
    set foo 1; set f2 1; set f3 1; set f4 1
    list [regexp -indices (a)(b)?(c) xacy foo f2 f3 f4] $foo $f2 $f3 $f4
} {1 {1 2} {1 1} {-1 -1} {2 2}}
test regexp-3.8a {-indices by multi-byte utf-8} {
    regexp -inline -indices {(\w+)-(\w+)} \
	"gr\u00FC\u00DF-\u043F\u0440\u0438\u0432\u0435\u0442"
	"grüß-привет"
} {{0 10} {0 3} {5 10}}
test regexp-3.8b {-indices by multi-byte utf-8, from -start position} {
    list\
	[regexp -inline -indices -start 3 {(\w+)-(\w+)} \
	"gr\u00FC\u00DF-\u043F\u0440\u0438\u0432\u0435\u0442"] \
	"grüß-привет"] \
	[regexp -inline -indices -start 4 {(\w+)-(\w+)} \
	"gr\u00FC\u00DF-\u043F\u0440\u0438\u0432\u0435\u0442"]
	"grüß-привет"]
} {{{3 10} {3 3} {5 10}} {}}

test regexp-4.1 {-nocase option to regexp} {
    regexp -nocase foo abcFOo
} 1
test regexp-4.2 {-nocase option to regexp} {
    set f1 22
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
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







-
+


-
+

















-
+







    list [catch {regexp -nocase a} msg] $msg
} {1 {wrong # args: should be "regexp ?-option ...? exp string ?matchVar? ?subMatchVar ...?"}}
test regexp-6.3 {regexp errors} {
    list [catch {regexp -gorp a} msg] $msg
} {1 {bad option "-gorp": must be -all, -about, -indices, -inline, -expanded, -line, -linestop, -lineanchor, -nocase, -start, or --}}
test regexp-6.4 {regexp errors} {
    list [catch {regexp a( b} msg] $msg
} {1 {couldn't compile regular expression pattern: parentheses () not balanced}}
} {1 {cannot compile regular expression pattern: parentheses () not balanced}}
test regexp-6.5 {regexp errors} {
    list [catch {regexp a( b} msg] $msg
} {1 {couldn't compile regular expression pattern: parentheses () not balanced}}
} {1 {cannot compile regular expression pattern: parentheses () not balanced}}
test regexp-6.6 {regexp errors} {
    list [catch {regexp a a f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1} msg] $msg
} {0 1}
test regexp-6.7 {regexp errors} {
    list [catch {regexp (x)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.) xyzzy} msg] $msg
} {0 0}
test regexp-6.8 {regexp errors} -setup {
    unset -nocomplain f1
} -body {
    set f1 44
    regexp abc abc f1(f2)
} -returnCodes error -result {can't set "f1(f2)": variable isn't array}
test regexp-6.9 {regexp errors, -start bad int check} {
    list [catch {regexp -start bogus {^$} {}} msg] $msg
} {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}}
test regexp-6.10 {regexp errors} {
    list [catch {regexp {a[} b} msg] $msg
} {1 {couldn't compile regular expression pattern: brackets [] not balanced}}
} {1 {cannot compile regular expression pattern: brackets [] not balanced}}

test regexp-7.1 {basic regsub operation} {
    list [regsub aa+ xaxaaaxaa 111&222 foo] $foo
} {1 xax111aaa222xaa}
test regexp-7.2 {basic regsub operation} {
    list [regsub aa+ aaaxaa &111 foo] $foo
} {1 aaa111xaa}
348
349
350
351
352
353
354
355
356


357
358
359
360
361
362
363
348
349
350
351
352
353
354


355
356
357
358
359
360
361
362
363







-
-
+
+







} {1 {abc111 def}}
test regexp-7.16 {basic regsub operation} {
    set foo xxx
    list [regsub x "" y foo] $foo
} {0 {}}
test regexp-7.17 {regsub utf compliance} {
    # if not UTF-8 aware, result is "0 1"
    set foo "xyz555ijka\u4e4ebpqr"
    regsub a\u4e4eb xyza\u4e4ebijka\u4e4ebpqr 555 bar
    set foo "xyz555ijka乎bpqr"
    regsub a乎b xyza乎bijka乎bpqr 555 bar
    list [string compare $foo $bar] [regexp 4 $bar]
} {0 0}
test regexp-7.18 {basic regsub replacement} {
    list [regsub a+ aaa {&} foo] $foo
} {1 aaa}
test regexp-7.19 {basic regsub replacement} {
    list [regsub a+ aaa {\&} foo] $foo
477
478
479
480
481
482
483
484

485
486
487
488
489
490
491
477
478
479
480
481
482
483

484
485
486
487
488
489
490
491







-
+







    list [catch {regsub a b c d e f} msg] $msg
} {1 {wrong # args: should be "regsub ?-option ...? exp string subSpec ?varName?"}}
test regexp-11.5 {regsub errors} {
    list [catch {regsub -gorp a b c} msg] $msg
} {1 {bad option "-gorp": must be -all, -command, -expanded, -line, -linestop, -lineanchor, -nocase, -start, or --}}
test regexp-11.6 {regsub errors} {
    list [catch {regsub -nocase a( b c d} msg] $msg
} {1 {couldn't compile regular expression pattern: parentheses () not balanced}}
} {1 {cannot compile regular expression pattern: parentheses () not balanced}}
test regexp-11.7 {regsub errors} -setup {
    unset -nocomplain f1
} -body {
    set f1 44
    regsub -nocase aaa aaa xxx f1(f2)
} -returnCodes error -result {can't set "f1(f2)": variable isn't array}
test regexp-11.8 {regsub errors, -start bad int check} {
767
768
769
770
771
772
773
774
775


776
777
778
779
780
781
782
767
768
769
770
771
772
773


774
775
776
777
778
779
780
781
782







-
-
+
+








test regexp-20.1 {regsub shared object shimmering} -body {
    # Bug #461322
    set a abcdefghijklmnopqurstuvwxyz
    set b $a
    set c abcdefghijklmnopqurstuvwxyz0123456789
    regsub $a $c $b d
    list $d [string length $d] [string bytelength $d]
} -result [list abcdefghijklmnopqurstuvwxyz0123456789 37 37]
    list $d [string length $d]
} -result [list abcdefghijklmnopqurstuvwxyz0123456789 37]
test regexp-20.2 {regsub shared object shimmering with -about} -body {
    eval regexp -about abc
} -result {0 {}}

test regexp-21.1 {regsub works with empty string} -body {
    regsub -- ^ {} foo
} -result {foo}
885
886
887
888
889
890
891
892

893
894
895
896
897
898
899
885
886
887
888
889
890
891

892
893
894
895
896
897
898
899







-
+







	[a 667]([a 55])[a 668]([a 55])[a 669]([a 55])[a 668]([a 55]) \
	[a 671]([a 55])[a 669]([a 55])[a 668]([a 55])[a 669]([a 55]) \
	[a 669]([a 55])[a 669]([a 55])[a 668]([a 55])[a 669]([a 55]) \
	[a 668]([a 55])[a 710]([a 55])[a 668]([a 55])[a 668]([a 55]) \
	[a 668]([a 55])[a 668]([a 55])[a 668]([a 55])[a 511]] {}] a
} -cleanup {
    rename a {}
} -returnCodes 1 -match glob -result {couldn't compile regular expression pattern: *}
} -returnCodes 1 -match glob -result {cannot compile regular expression pattern: *}
test regexp-22.5 {Bug 3610026} -setup {
    set e {}
    set cp 99
    while {$cp < 32864} {
	append e [format %c [incr cp]]
    }
} -body {

Changes to tests/regexpComp.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  regexp, regsub
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1998 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1998 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
58
59
60
61
62
63
64
65
66


67
68
69
70
71
72
73
58
59
60
61
62
63
64


65
66
67
68
69
70
71
72
73







-
-
+
+







} 1
test regexpComp-1.6 {basic regexp operation} {
    list [catch {regexp {} abc} msg] $msg
} {0 1}
test regexpComp-1.7 {regexp utf compliance} {
    # if not UTF-8 aware, result is "0 1"
    evalInProc {
	set foo "\u4e4eb q"
	regexp "\u4e4eb q" "a\u4e4eb qw\u5e4e\x4e wq" bar
	set foo "乎b q"
	regexp "乎b q" "a乎b qw幎N wq" bar
	list [string compare $foo $bar] [regexp 4 $bar]
    }
} {0 0}

test regexpComp-1.8 {regexp ***= metasyntax} {
    evalInProc {
	regexp -- "***=o" "aeiou"
327
328
329
330
331
332
333
334

335
336
337
338
339

340
341
342
343
344
345
346
327
328
329
330
331
332
333

334
335
336
337
338

339
340
341
342
343
344
345
346







-
+




-
+







	list [catch {regexp -gorp a} msg] $msg
    }
} {1 {bad option "-gorp": must be -all, -about, -indices, -inline, -expanded, -line, -linestop, -lineanchor, -nocase, -start, or --}}
test regexpComp-6.4 {regexp errors} {
    evalInProc {
	list [catch {regexp a( b} msg] $msg
    }
} {1 {couldn't compile regular expression pattern: parentheses () not balanced}}
} {1 {cannot compile regular expression pattern: parentheses () not balanced}}
test regexpComp-6.5 {regexp errors} {
    evalInProc {
	list [catch {regexp a( b} msg] $msg
    }
} {1 {couldn't compile regular expression pattern: parentheses () not balanced}}
} {1 {cannot compile regular expression pattern: parentheses () not balanced}}
test regexpComp-6.6 {regexp errors} {
    evalInProc {
	list [catch {regexp a a f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1 f1} msg] $msg
    }
} {0 1}
test regexpComp-6.7 {regexp errors} {
    evalInProc {
443
444
445
446
447
448
449
450
451


452
453
454
455
456
457
458
443
444
445
446
447
448
449


450
451
452
453
454
455
456
457
458







-
-
+
+







	set foo xxx
	list [regsub x "" y foo] $foo
    }
} {0 {}}
test regexpComp-7.17 {regsub utf compliance} {
    evalInProc {
	# if not UTF-8 aware, result is "0 1"
	set foo "xyz555ijka\u4e4ebpqr"
	regsub a\u4e4eb xyza\u4e4ebijka\u4e4ebpqr 555 bar
	set foo "xyz555ijka乎bpqr"
	regsub a乎b xyza乎bijka乎bpqr 555 bar
	list [string compare $foo $bar] [regexp 4 $bar]
    }
} {0 0}

test regexpComp-8.1 {case conversion in regsub} {
    evalInProc {
	list [regsub -nocase a(a+) xaAAaAAay & foo] $foo
588
589
590
591
592
593
594
595

596
597
598
599
600
601
602
588
589
590
591
592
593
594

595
596
597
598
599
600
601
602







-
+







	list [catch {regsub -gorp a b c} msg] $msg
    }
} {1 {bad option "-gorp": must be -all, -command, -expanded, -line, -linestop, -lineanchor, -nocase, -start, or --}}
test regexpComp-11.6 {regsub errors} {
    evalInProc {
	list [catch {regsub -nocase a( b c d} msg] $msg
    }
} {1 {couldn't compile regular expression pattern: parentheses () not balanced}}
} {1 {cannot compile regular expression pattern: parentheses () not balanced}}
test regexpComp-11.7 {regsub errors} {
    evalInProc {
	unset -nocomplain f1
	set f1 44
	list [catch {regsub -nocase aaa aaa xxx f1(f2)} msg] $msg
    }
} {1 {can't set "f1(f2)": variable isn't array}}
794
795
796
797
798
799
800
801

802
803

804
805
806
807
808
809
810
794
795
796
797
798
799
800

801
802

803
804
805
806
807
808
809
810







-
+

-
+







test regexpComp-20.1 {regsub shared object shimmering} {
    evalInProc {
	# Bug #461322
	set a abcdefghijklmnopqurstuvwxyz
	set b $a
	set c abcdefghijklmnopqurstuvwxyz0123456789
	regsub $a $c $b d
	list $d [string length $d] [string bytelength $d]
	list $d [string length $d]
    }
} [list abcdefghijklmnopqurstuvwxyz0123456789 37 37]
} [list abcdefghijklmnopqurstuvwxyz0123456789 37]
test regexpComp-20.2 {regsub shared object shimmering with -about} {
    evalInProc {
	eval regexp -about abc
    }
} {0 {}}

test regexpComp-21.1 {regexp command compiling tests} {
966
967
968
969
970
971
972
973

974
975
976
977
978
979
980
966
967
968
969
970
971
972

973
974
975
976
977
978
979
980







-
+







    }
} 0
test regexpComp-24.9 {regexp command compiling tests} {
    evalInProc {
	set re "("
	list [catch {regexp -- $re dogfod} msg] $msg
    }
} {1 {couldn't compile regular expression pattern: parentheses () not balanced}}
} {1 {cannot compile regular expression pattern: parentheses () not balanced}}
test regexpComp-24.10 {regexp command compiling tests} {
    # Bug 1902436 - last * escaped
    evalInProc {
	set text {this is *bold* !}
	set re {\*bold\*}
	regexp -- $re $text
    }

Changes to tests/registry.test.

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
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
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
30
31
32
33
34
35
36

37
38
39
40
41
42
43
44









-
-
+
+










-
+




-
+









-
+







# registry.test --
#
# This file contains a collection of tests for the registry command.
# Sourcing this file into Tcl runs the tests and generates output for
# errors.  No output means no errors were found.
#
# In order for these tests to run, the registry package must be on the
# auto_path or the registry package must have been loaded already.
#
# Copyright (c) 1997 by Sun Microsystems, Inc.  All rights reserved.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.  All rights reserved.
# Copyright © 1998-1999 Scriptics Corporation.

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

testConstraint reg 0
if {[testConstraint win]} {
    if {![catch {
	    ::tcltest::loadTestedCommands
	    set ::regver [package require registry 1.3.5]
	    set ::regver [package require registry 1.3.7]
	}]} {
	testConstraint reg 1
    }
}
testConstraint notWine [expr {$::tcl_platform(platform) ne "windows" || ![info exists ::env(TRAVIS_OS_NAME)] || ![string match linux $::env(TRAVIS_OS_NAME)]}]
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.3.5}
} {1.3.7}
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} {
570
571
572
573
574
575
576
577
578
579



580
581
582
583
584
585
586
570
571
572
573
574
575
576



577
578
579
580
581
582
583
584
585
586







-
-
-
+
+
+







    lsort [registry values HKEY_CURRENT_USER\\TclFoobar b*]
} -cleanup {
    registry delete HKEY_CURRENT_USER\\TclFoobar
} -result {{baz bar} blat}

test registry-8.1 {OpenSubKey} -constraints {win reg nonPortable english} \
    -body {
        # This test will only succeed if the current user does not have
        # registry access on the specified machine.
        registry keys {\\mom\HKEY_LOCAL_MACHINE}
	# This test will only succeed if the current user does not have
	# registry access on the specified machine.
	registry keys {\\mom\HKEY_LOCAL_MACHINE}
    } -returnCodes error -result "unable to open key: Access is denied."
test registry-8.2 {OpenSubKey} -constraints {win reg} -setup {
    registry delete HKEY_CURRENT_USER\\TclFoobar
    registry set HKEY_CURRENT_USER\\TclFoobar
} -body {
    registry keys HKEY_CURRENT_USER TclFoobar
} -cleanup {
640
641
642
643
644
645
646
647

648
649
650


651
652
653
654

655
656
657
658



659
660
661
662
663
664
665



666
667
668
669
670
671
672
640
641
642
643
644
645
646

647
648


649
650
651
652
653

654
655



656
657
658
659
660
661
662



663
664
665
666
667
668
669
670
671
672







-
+

-
-
+
+



-
+

-
-
-
+
+
+




-
-
-
+
+
+







    registry delete HKEY_CURRENT_USER\\TclFoobar\\test2\\test4
} -cleanup {
    registry delete HKEY_CURRENT_USER\\TclFoobar
} -result {}

test registry-11.1 {SetValue: recursive creation} \
    -constraints {win reg} -setup {
        registry delete HKEY_CURRENT_USER\\TclFoobar
	registry delete HKEY_CURRENT_USER\\TclFoobar
    } -body {
        registry set HKEY_CURRENT_USER\\TclFoobar\\baz blat foobar
        set result [registry get HKEY_CURRENT_USER\\TclFoobar\\baz blat]
	registry set HKEY_CURRENT_USER\\TclFoobar\\baz blat foobar
	set result [registry get HKEY_CURRENT_USER\\TclFoobar\\baz blat]
    } -result {foobar}
test registry-11.2 {SetValue: modification} -constraints {win reg} \
    -setup {
        registry delete HKEY_CURRENT_USER\\TclFoobar
	registry delete HKEY_CURRENT_USER\\TclFoobar
    } -body {
        registry set HKEY_CURRENT_USER\\TclFoobar\\baz blat foobar
        registry set HKEY_CURRENT_USER\\TclFoobar\\baz blat frob
        set result [registry get HKEY_CURRENT_USER\\TclFoobar\\baz blat]
	registry set HKEY_CURRENT_USER\\TclFoobar\\baz blat foobar
	registry set HKEY_CURRENT_USER\\TclFoobar\\baz blat frob
	set result [registry get HKEY_CURRENT_USER\\TclFoobar\\baz blat]
    } -result {frob}
test registry-11.3 {SetValue: failure} \
    -constraints {win reg nonPortable english} \
    -body {
        # This test will only succeed if the current user does not have
        # registry access on the specified machine.
        registry set {\\mom\HKEY_CURRENT_USER\TclFoobar} bar foobar
	# This test will only succeed if the current user does not have
	# registry access on the specified machine.
	registry set {\\mom\HKEY_CURRENT_USER\TclFoobar} bar foobar
    } -returnCodes error -result {unable to open key: Access is denied.}

test registry-12.1 {BroadcastValue} -constraints {win reg} -body {
    registry broadcast
} -returnCodes error -result "wrong # args: should be \"registry broadcast keyName ?-timeout milliseconds?\""
test registry-12.2 {BroadcastValue} -constraints {win reg} -body {
    registry broadcast "" -time

Changes to tests/remote.tcl.

1
2
3
4
5
6
7

8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6

7
8
9
10
11

12
13
14
15
16
17
18
19






-
+




-
+







# This file contains Tcl code to implement a remote server that can be
# used during testing of Tcl socket code. This server is used by some
# of the tests in socket.test.
#
# Source this file in the remote server you are using to test Tcl against.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright © 1995-1996 Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

# Initialize message delimitor
# Initialize message delimiter

# Initialize command array
catch {unset command}
set command(0) ""
set callerSocket ""

# Detect whether we should print out connection messages etc.
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
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







-
+

-
+
















-
-
+
+







}

proc __readAndExecute__ {s} {
    global command VERBOSE

    set l [gets $s]
    if {[string compare $l "--Marker--Marker--Marker--"] == 0} {
        puts $s [__doCommands__ $command($s) $s]
	puts $s [__doCommands__ $command($s) $s]
	puts $s "--Marker--Marker--Marker--"
        set command($s) ""
	set command($s) ""
	return
    }
    if {[string compare $l ""] == 0} {
	if {[eof $s]} {
	    if {$VERBOSE} {
		puts "Server closing $s, eof from client"
	    }
	    close $s
	}
	return
    }
    if {[eof $s]} {
	if {$VERBOSE} {
	    puts "Server closing $s, eof from client"
	}
	close $s
        unset command($s)
        return
	unset command($s)
	return
    }
    append command($s) $l "\n"
}

proc __accept__ {s a p} {
    global command VERBOSE

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
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







-
-
+
+

















-
-
+
+







    if {[info exists env(serverPort)]} {
	set serverPort $env(serverPort)
    }
}
if {![info exists serverPort]} {
    for {set i 0} {$i < $argc} {incr i} {
	if {[string compare -port [lindex $argv $i]] == 0} {
	    if {$i < [expr $argc - 1]} {
		set serverPort [lindex $argv [expr $i + 1]]
	    if {$i < $argc - 1} {
		set serverPort [lindex $argv [expr {$i + 1}]]
	    }
	    break
	}
    }
}
if {![info exists serverPort]} {
    set serverPort 2048
}

if {![info exists serverAddress]} {
    if {[info exists env(serverAddress)]} {
	set serverAddress $env(serverAddress)
    }
}
if {![info exists serverAddress]} {
    for {set i 0} {$i < $argc} {incr i} {
	if {[string compare -address [lindex $argv $i]] == 0} {
	    if {$i < [expr $argc - 1]} {
		set serverAddress [lindex $argv [expr $i + 1]]
	    if {$i < $argc - 1} {
		set serverAddress [lindex $argv [expr {$i + 1}]]
	    }
	    break
	}
    }
}
if {![info exists serverAddress]} {
    set serverAddress 0.0.0.0

Changes to tests/rename.test.

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
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






-
-
-
+
+
+










-
+







# Commands covered:  rename
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testdel [llength [info commands testdel]]

# Must eliminate the "unknown" command while the test is running, especially
# if the test is being run in a program with its own special-purpose unknown
# command.
catch {rename unknown unknown.old}
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
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







-
-
-
-
+
+
+
+








-
-
+
+








catch {rename unknown unknown.old}

set SAVED_UNKNOWN "proc unknown "
append SAVED_UNKNOWN [list [info args unknown.old] [info body unknown.old]]
test rename-5.1 {repeated rename deletion and redefinition of same command} {
    for {set i 0} {$i < 10} {incr i} {
        eval $SAVED_UNKNOWN
        tcl_wordBreakBefore "" 0
        rename tcl_wordBreakBefore {}
        rename unknown {}
	eval $SAVED_UNKNOWN
	tcl_wordBreakBefore "" 0
	rename tcl_wordBreakBefore {}
	rename unknown {}
    }
} {}

catch {rename unknown {}}
catch {rename unknown.old unknown}

test rename-6.1 {old code invalidated (epoch incremented) when cmd with compile proc is renamed} -body {
    proc x {} {
        set a 123
        set b [incr a]
	set a 123
	set b [incr a]
    }
    x
    rename incr incr.old
    proc incr {} {puts "new incr called!"}
    x
} -cleanup {
    rename incr {}

Changes to tests/resolver.test.

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
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






-
-
+
+










-
+







# This test collection covers some unwanted interactions between command
# literal sharing and the use of command resolvers (per-interp) which cause
# command literals to be re-used with their command references being invalid
# in the reusing context.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 2011 Gustaf Neumann <gustaf.neumann@wu.ac.at>
# Copyright (c) 2011 Stefan Sobernig <stefan.sobernig@wu.ac.at>
# Copyright © 2011 Gustaf Neumann <gustaf.neumann@wu.ac.at>
# Copyright © 2011 Stefan Sobernig <stefan.sobernig@wu.ac.at>
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testinterpresolver [llength [info commands testinterpresolver]]

test resolver-1.1 {cmdNameObj sharing vs. cmd resolver: namespace import} -setup {
    testinterpresolver up
    namespace eval ::ns1 {
	proc z {} { return Z }
199
200
201
202
203
204
205
206

207
208
209
210
211
212
213
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213







-
+







# The test resolver-3.1* test bad interactions of resolvers on the "global"
# (per interp) literal pools. A resolver might resolve a cmd literal depending
# on a context differently, whereas the cmd literal sharing assumed that the
# namespace containing the literal solely determines the resolved cmd (and is
# resolver-agnostic).
#
# In order to make the test cases for the per-interpreter cmd literal pool
# reproducable and to minimize interactions between test cases, we use a child
# reproducible and to minimize interactions between test cases, we use a child
# interpreter per test-case.
#
#
# Testing resolver in namespace-based context "ctx1"
#
test resolver-3.1a {
    interp command resolver,

Changes to tests/result.test.

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
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






-
-
+
+










-
+







# This file tests the routines in tclResult.c.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 by Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

# Some tests require the testsaveresult command

testConstraint testsaveresult      [llength [info commands testsaveresult]]
testConstraint testsetobjerrorcode [llength [info commands testsetobjerrorcode]]
testConstraint testseterrorcode    [llength [info commands testseterrorcode]]
testConstraint testreturn          [llength [info commands testreturn]]
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
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







-
+






-
+


-
-
-
-
-
+
+
+
+
+







    set errorCode
} {{a b} c}

test result-6.0 {Bug 1209759} -constraints testreturn -body {
    # Might panic if bug is not fixed.
    proc foo {} {testreturn}
    foo
} -returnCodes ok  -result {}
}  -result {}
test result-6.1 {Bug 1209759} -constraints testreturn -body {
    # Might panic if bug is not fixed.
    proc foo {} {catch {return -level 2}; testreturn}
    foo
} -cleanup {
    rename foo {}
} -returnCodes ok -result {}
} -result {}
test result-6.2 {Bug 1649062} -setup {
    proc foo {} {
        if {[catch {
            return -code error -errorinfo custom -errorcode CUSTOM foo
        } err]} {
            return [list $err $::errorCode $::errorInfo]
        }
	if {[catch {
	    return -code error -errorinfo custom -errorcode CUSTOM foo
	} err]} {
	    return [list $err $::errorCode $::errorInfo]
	}
    }
    set ::errorInfo {}
    set ::errorCode {}
} -body {
    foo
} -cleanup {
    rename foo {}

Changes to tests/safe-stock.test.

18
19
20
21
22
23
24
25
26


27
28
29
30
31
32
33
18
19
20
21
22
23
24


25
26
27
28
29
30
31
32
33







-
-
+
+







#   - These are tests 7.1 7.2 7.4 9.11 9.13
#   - Tests 7.[124], 9.1[13] use "package require opt".
#   - Tests 9.1[13] also use "package require tcl::idna".
# - The corresponding tests in safe.test use example packages provided in
#   subdirectory auto0 of the tests directory, which are independent of any
#   changes made to the packages provided with Tcl.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
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
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







-
+






-
+




-
-
+
+


+
+

-
+
+
+
+
+
+











+
+
+

-
+
+
+
+
+
+
+
+














+
+
+

-
-
+
+
+
+
+
+
+
+
+










-
-
+
+



+
+
+

-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
+
+
+
+
+
+


-
-
+
+












-
-
+
+













-
+


+
+
+

-
-
-
-
+
+
+
+
+
+
+
+
+


-
-
+
+







lappend PathMapp [file join [info library] $pkgOptDir] TCLLIB/OPTDIR
lappend PathMapp [file join [info library] $pkgJarDir] TCLLIB/JARDIR
lappend PathMapp $tcl_library TCLLIB $TestsDir TESTSDIR

proc mapList {map listIn} {
    set listOut {}
    foreach element $listIn {
        lappend listOut [string map $map $element]
	lappend listOut [string map $map $element]
    }
    return $listOut
}
proc mapAndSortList {map listIn} {
    set listOut {}
    foreach element $listIn {
        lappend listOut [string map $map $element]
	lappend listOut [string map $map $element]
    }
    lsort $listOut
}

# Force actual loading of the safe package because we use un-exported (and
# thus un-autoindexed) APIs in this test result arguments:
# Force actual loading of the safe package because we use unexported (and
# thus unautoindexed) APIs in this test result arguments:
catch {safe::interpConfigure}

testConstraint AutoSyncDefined 1

# high level general test
test safe-stock-7.1 {tests that everything works at high level, uses pkg opt} -setup {
test safe-stock-7.1 {tests that everything works at high level with conventional AutoPathSync, use pkg opt} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }
    set i [safe::interpCreate]
} -body {
    # no error shall occur:
    # (because the default access_path shall include 1st level sub dirs so
    #  package require in a child works like in the parent)
    set v [interp eval $i {package require opt}]
    # no error shall occur:
    interp eval $i {::tcl::Lempty {a list}}
    set v
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result 0.4.*
test safe-stock-7.2 {tests specific path and interpFind/AddToAccessPath, uses pkg opt} -setup {
test safe-stock-7.2 {tests specific path and interpFind/AddToAccessPath with conventional AutoPathSync, use pkg opt} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    } else {
	set SyncVal_TMP 1
    }
} -body {
    set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]
    # should not add anything (p0)
    set token1 [safe::interpAddToAccessPath $i [info library]]
    # should add as p* (not p1 if parent has a module path)
    set token2 [safe::interpAddToAccessPath $i "/dummy/unixlike/test/path"]
    # an error shall occur (opt is not anymore in the secure 0-level
    # provided deep path)
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    list $token1 $token2 -- \
	    [catch {interp eval $i {package require opt}} msg] $msg -- \
	    $mappA -- [safe::interpDelete $i]
} -cleanup {
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result "{\$p(:0:)} {\$p(:*:)} -- 1 {$pkgOptErrMsg} --\
        {TCLLIB */dummy/unixlike/test/path} -- {}"
test safe-stock-7.4 {tests specific path and positive search, uses pkg opt} -setup {
	{TCLLIB */dummy/unixlike/test/path} -- {}"
test safe-stock-7.4 {tests specific path and positive search with conventional AutoPathSync, use pkg opt} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    } else {
	set SyncVal_TMP 1
    }
} -body {
    set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]
    # should not add anything (p0)
    set token1 [safe::interpAddToAccessPath $i [info library]]
    # should add as p* (not p1 if parent has a module path)
    set token2 [safe::interpAddToAccessPath $i [file join [info library] $pkgOptDir]]
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    # this time, unlike test safe-stock-7.2, opt should be found
    list $token1 $token2 -- \
            [catch {interp eval $i {package require opt}} msg] $msg -- \
            $mappA -- [safe::interpDelete $i]
	    [catch {interp eval $i {package require opt}} msg] $msg -- \
	    $mappA -- [safe::interpDelete $i]
    # Note that the glob match elides directories (those from the module path)
    # other than the first and last in the access path.
} -cleanup {
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:0:)} {$p(:*:)} -- 0 0.4.* --\
        {TCLLIB * TCLLIB/OPTDIR} -- {}}
	{TCLLIB * TCLLIB/OPTDIR} -- {}}
test safe-stock-7.5 {tests positive and negative module loading with conventional AutoPathSync} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }
    set i [safe::interpCreate]
    interp eval $i {
	package forget platform::shell
	package forget platform
	catch {namespace delete ::platform}
    }
} -body {
    # Should raise an error (module ancestor directory issue)
    set code1 [catch {interp eval $i {package require shell}} msg1]
    # Should not raise an error
    set code2 [catch {interp eval $i {package require platform::shell}} msg2]
    return [list $code1 $msg1 $code2]
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {1 {can't find package shell} 0}

# The following test checks whether the definition of tcl_endOfWord can be
# obtained from auto_loading.  It was previously test "safe-5.1".
test safe-stock-9.8 {test auto-loading in safe interpreters, was safe-5.1} -setup {
    catch {safe::interpDelete a}
    safe::interpCreate a
} -body {
    interp eval a {tcl_endOfWord "" 0}
} -cleanup {
    safe::interpDelete a
} -result -1
test safe-stock-9.11 {interpConfigure change the access path; pkgIndex.tcl packages unaffected by token rearrangement, uses pkg opt and tcl::idna} -setup {
test safe-stock-9.11 {interpConfigure change the access path; pkgIndex.tcl packages unaffected by token rearrangement with conventional AutoPathSync, uses pkg opt and tcl::idna} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library \
                                            [file join $tcl_library $pkgOptDir] \
                                            [file join $tcl_library $pkgJarDir]]]
					    [file join $tcl_library $pkgOptDir] \
					    [file join $tcl_library $pkgJarDir]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path1 [::safe::interpFindInAccessPath $i [file join $tcl_library $pkgOptDir]]
    set path2 [::safe::interpFindInAccessPath $i [file join $tcl_library $pkgJarDir]]

    # Load pkgIndex.tcl data.
    catch {interp eval $i {package require NOEXIST}}

    # Rearrange access path.  Swap tokens {$p(:1:)} and {$p(:2:)}.
    # This has no effect because the records in Pkg of these directories were from access as children of {$p(:0:)}.
    safe::interpConfigure $i -accessPath [list $tcl_library \
                                           [file join $tcl_library $pkgJarDir] \
                                           [file join $tcl_library $pkgOptDir]]
					   [file join $tcl_library $pkgJarDir] \
					   [file join $tcl_library $pkgOptDir]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set path3 [::safe::interpFindInAccessPath $i [file join $tcl_library $pkgOptDir]]
    set path4 [::safe::interpFindInAccessPath $i [file join $tcl_library $pkgJarDir]]

    # Try to load the packages and run a command from each one.
    set code3 [catch {interp eval $i {package require tcl::idna}} msg3]
    set code4 [catch {interp eval $i {package require opt}} msg4]
    set code5 [catch {interp eval $i {::tcl::Lempty {a list}}} msg5]
    set code6 [catch {interp eval $i {::tcl::idna::IDNAencode example.com}} msg6]

    list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- \
         $mappA -- $mappB -- $code5 $msg5 $code6 $msg6
	 $mappA -- $mappB -- $code5 $msg5 $code6 $msg6
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:1:)} {$p(:2:)} -- {$p(:2:)} {$p(:1:)} -- 0 1.* 0 0.4.* --\
        {TCLLIB TCLLIB/OPTDIR TCLLIB/JARDIR*} --\
        {TCLLIB TCLLIB/JARDIR TCLLIB/OPTDIR*} --\
        0 0 0 example.com}
test safe-stock-9.13 {interpConfigure change the access path; pkgIndex.tcl packages fail if directory de-listed, uses pkg opt and tcl::idna} -setup {
	{TCLLIB TCLLIB/OPTDIR TCLLIB/JARDIR*} --\
	{TCLLIB TCLLIB/JARDIR TCLLIB/OPTDIR*} --\
	0 0 0 example.com}
test safe-stock-9.13 {interpConfigure change the access path; pkgIndex.tcl packages fail if directory de-listed with conventional AutoPathSync, uses pkg opt and tcl::idna} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library \
                                            [file join $tcl_library $pkgOptDir] \
                                            [file join $tcl_library $pkgJarDir]]]
					    [file join $tcl_library $pkgOptDir] \
					    [file join $tcl_library $pkgJarDir]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path1 [::safe::interpFindInAccessPath $i [file join $tcl_library $pkgOptDir]]
    set path2 [::safe::interpFindInAccessPath $i [file join $tcl_library $pkgJarDir]]

    # Load pkgIndex.tcl data.
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
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
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
442
443
444







-
+


+
+
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












    set code5 [catch {::safe::interpFindInAccessPath $i [file join $tcl_library $pkgJarDir]} path5]

    # Try to load the packages.
    set code3 [catch {interp eval $i {package require opt}} msg3]
    set code6 [catch {interp eval $i {package require tcl::idna}} msg6]

    list $path1 $path2 -- $code4 $path4 -- $code5 $path5 -- $code3 $code6 -- \
            $mappA -- $mappB
	    $mappA -- $mappB
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:1:)} {$p(:2:)} -- 1 {* not found in access path} --\
        1 {* not found in access path} -- 1 1 --\
        {TCLLIB TCLLIB/OPTDIR TCLLIB/JARDIR*} -- {TCLLIB*}}
	1 {* not found in access path} -- 1 1 --\
	{TCLLIB TCLLIB/OPTDIR TCLLIB/JARDIR*} -- {TCLLIB*}}

test safe-stock-18.1 {cf. safe-stock-7.1opt - tests that everything works at high level without conventional AutoPathSync, use pkg opt} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    # Without AutoPathSync, we need a more complete auto_path,
    # because the child will use the same value.
    set lib1        [info library]
    set lib2        [file dirname $lib1]
    set ::auto_TMP  $::auto_path
    set ::auto_path [list $lib1 $lib2]

    set i [safe::interpCreate]
    set ::auto_path $::auto_TMP
} -body {
    # no error shall occur:
    # (because the default access_path shall include 1st level sub dirs so
    #  package require in a child works like in the parent)
    set v [interp eval $i {package require opt}]
    # no error shall occur:
    interp eval $i {::tcl::Lempty {a list}}
    set v
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result 0.4.*
test safe-stock-18.2 {cf. safe-stock-7.2opt - tests specific path and interpFind/AddToAccessPath without conventional AutoPathSync, use pkg opt} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]
    set auto1 [interp eval $i {set ::auto_path}]
    # This will differ from the value -autoPath {}
    interp eval $i {set ::auto_path [list {$p(:0:)}]}
    # should not add anything (p0)
    set token1 [safe::interpAddToAccessPath $i [info library]]
    # should add as p* (not p1 if parent has a module path)
    set token2 [safe::interpAddToAccessPath $i "/dummy/unixlike/test/path"]
    # an error shall occur (opt is not anymore in the secure 0-level
    # provided deep path)
    list $auto1 $token1 $token2 \
	    [catch {interp eval $i {package require opt}} msg] $msg \
	    [safe::interpConfigure $i]\
	    [safe::interpDelete $i]
} -cleanup {
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result "{} {\$p(:0:)} {\$p(:*:)} 1 {$pkgOptErrMsg}\
	{-accessPath {[list $tcl_library */dummy/unixlike/test/path]}\
	-statics 0 -nested 1 -deleteHook {} -autoPath {}} {}"
test safe-stock-18.4 {cf. safe-stock-7.4opt - tests specific path and positive search and auto_path without conventional AutoPathSync, use pkg opt} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]

    # should not have been set by Safe Base:
    set auto1 [interp eval $i {set ::auto_path}]

    # This will differ from the value -autoPath {}
    interp eval $i {set ::auto_path [list {$p(:0:)}]}

    # should not add anything (p0)
    set token1 [safe::interpAddToAccessPath $i [info library]]

    # should add as p* (not p1 if parent has a module path)
    set token2 [safe::interpAddToAccessPath $i [file join [info library] $pkgOptDir]]

    # should not have been changed by Safe Base:
    set auto2 [interp eval $i {set ::auto_path}]

    # This time, unlike test safe-stock-18.2opt and the try above, opt should be found:
    list $auto1 $auto2 $token1 $token2 \
	    [catch {interp eval $i {package require opt}} msg] $msg \
	    [safe::interpConfigure $i]\
	    [safe::interpDelete $i]
} -cleanup {
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result "{} {{\$p(:0:)}} {\$p(:0:)} {\$p(:*:)} 0 0.4.*\
	{-accessPath {[list $tcl_library *$tcl_library/$pkgOptDir]}\
	-statics 0 -nested 1 -deleteHook {} -autoPath {}} {}"
test safe-stock-18.5 {cf. safe-stock-7.5 - tests positive and negative module loading without conventional AutoPathSync} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set i [safe::interpCreate]
    interp eval $i {
	package forget platform::shell
	package forget platform
	catch {namespace delete ::platform}
    }
} -body {
    # Should raise an error (tests module ancestor directory rule)
    set code1 [catch {interp eval $i {package require shell}} msg1]
    # Should not raise an error
    set code2 [catch {interp eval $i {package require platform::shell}} msg2]
    return [list $code1 $msg1 $code2]
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {1 {can't find package shell} 0}

set ::auto_path $SaveAutoPath
unset pkgOptErrMsg pkgOptDir pkgJarDir SaveAutoPath TestsDir PathMapp
rename mapList {}
rename mapAndSortList {}
# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Added tests/safe-stock86.test.

Changes to tests/safe-zipfs.test.

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



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


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
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
467
468
469
470
471
472
473
474
475
476






















477
478
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
558
559












560
561
562
563
564
565
566
567







568
569

570
571
572
573
574
575
576
577
578
579










580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595














596
597
598
599
600
601
602
603







604
605
606
607
608




609
610
611
612



613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716












































































































717
718
719
720
721
722
723
724
725









726
727
728
729
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
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
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
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







467
468
469
470
471
472
473
474

475








476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
















605
606
607
608
609
610
611
612
613
614
615
616
617
618
619







620
621
622
623
624
625
626
627
628
629
630
631
632



633
634
635









636
637
638
639
640
641
642
643
644
645
646
647
648







649
650
651
652
653
654
655
656

657










658
659
660
661
662
663
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







707
708
709
710
711
712
713
714

715


















716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824








825
826
827
828
829
830
831
832
833
834
835
836
837









-
-
+
+




-

+
+
+
-
-
-
-
+
+
+
+

-
-
-
+
+
+

-
-
-
+
+
+

-
-
+
+

-
-
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+

-
-
-
+
-

-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
+
+
+
+
+
+
+
-

-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+

-
-
+
+

-
-
-
-
+
+
+
+

-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+

-
-
-
+
+
+

-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+

-
-
+
+

-
-
+
+

-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+

-
-
-
+
+
+

-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+

-
-
+
+

-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
+
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+

-
-
+
+

-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
+
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+

-
-
+
+

-
-
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
+
+
+

-
+
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+




# safe-zipfs.test --
#
# This file contains tests for safe Tcl that test its compatibility with the
# zipfs facilities introduced in Tcl 8.7.  Test numbering is for comparison
# with similar tests in safe.test that do not use the zipfs file system.
#
# Sourcing this file into tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require Tcl 8.5-

apply [list {} {
    global auto_path
    global tcl_library
if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}
    if {"::tcltest" ni [namespace children]} {
	package require tcltest 2.5
	namespace import -force ::tcltest::*
    }

foreach i [interp children] {
    interp delete $i
}
    foreach i [interp children] {
	interp delete $i
    }

set SaveAutoPath $::auto_path
set ::auto_path [info library]
set TestsDir [file normalize [file dirname [info script]]]
    set SaveAutoPath $::auto_path
    set ::auto_path [info library]
    set TestsDir [file normalize [file dirname [info script]]]

set ZipMountPoint [zipfs root]auto-files
zipfs mount $ZipMountPoint [file join $TestsDir auto-files.zip]
    set ZipMountPoint [zipfs root]auto-files
    zipfs mount [file join $TestsDir auto-files.zip] $ZipMountPoint

set PathMapp {}
lappend PathMapp $tcl_library TCLLIB $TestsDir TESTSDIR $ZipMountPoint ZIPDIR
    set PathMapp {}
    lappend PathMapp $tcl_library TCLLIB $TestsDir TESTSDIR $ZipMountPoint ZIPDIR

proc mapList {map listIn} {
    set listOut {}
    foreach element $listIn {
        lappend listOut [string map $map $element]
    }
    return $listOut
}
proc mapAndSortList {map listIn} {
    set listOut {}
    foreach element $listIn {
        lappend listOut [string map $map $element]
    }
    lsort $listOut
}
    proc mapList {map listIn} {
	set listOut {}
	foreach element $listIn {
	    lappend listOut [string map $map $element]
	}
	return $listOut
    }
    proc mapAndSortList {map listIn} {
	set listOut {}
	foreach element $listIn {
	    lappend listOut [string map $map $element]
	}
	lsort $listOut
    }

# Force actual loading of the safe package because we use un-exported (and
# thus un-autoindexed) APIs in this test result arguments:
catch {safe::interpConfigure}
    # Force actual loading of the safe package because we use un-exported (and
    # thus un-autoindexed) APIs in this test result arguments:
    catch {safe::interpConfigure}

# testing that nested and statics do what is advertised (we use a static
# package - Tcltest - but it might be absent if we're in standard tclsh)

    testConstraint AutoSyncDefined 1
testConstraint TcltestPackage [expr {![catch {package require Tcltest}]}]

# Tests 5.* test the example files before using them to test safe interpreters.
    # Tests 5.* test the example files before using them to test safe interpreters.

test safe-zipfs-5.1 {example tclIndex commands, test in parent interpreter; zipfs} -setup {
    set tmpAutoPath $::auto_path
    lappend ::auto_path [file join $ZipMountPoint auto0 auto1] [file join $ZipMountPoint auto0 auto2]
} -body {
    # Try to load the commands.
    set code3 [catch report1 msg3]
    set code4 [catch report2 msg4]
    list $code3 $msg3 $code4 $msg4
} -cleanup {
    catch {rename report1 {}}
    catch {rename report2 {}}
    set ::auto_path $tmpAutoPath
    auto_reset
} -match glob -result {0 ok1 0 ok2}
test safe-zipfs-5.2 {example tclIndex commands, negative test in parent interpreter; zipfs} -setup {
    set tmpAutoPath $::auto_path
    lappend ::auto_path [file join $ZipMountPoint auto0]
} -body {
    # Try to load the commands.
    set code3 [catch report1 msg3]
    set code4 [catch report2 msg4]
    list $code3 $msg3 $code4 $msg4
} -cleanup {
    catch {rename report1 {}}
    catch {rename report2 {}}
    set ::auto_path $tmpAutoPath
    auto_reset
} -match glob -result {1 {invalid command name "report1"} 1 {invalid command name "report2"}}
test safe-zipfs-5.3 {example pkgIndex.tcl packages, test in parent interpreter, child directories; zipfs} -setup {
    set tmpAutoPath $::auto_path
    lappend ::auto_path [file join $ZipMountPoint auto0]
} -body {
    # Try to load the packages and run a command from each one.
    set code3 [catch {package require SafeTestPackage1} msg3]
    set code4 [catch {package require SafeTestPackage2} msg4]
    set code5 [catch HeresPackage1 msg5]
    set code6 [catch HeresPackage2 msg6]
    list $code3 $msg3 $code4 $msg4 $code5 $msg5 $code6 $msg6
} -cleanup {
    set ::auto_path $tmpAutoPath
    catch {package forget SafeTestPackage1}
    catch {package forget SafeTestPackage2}
    catch {rename HeresPackage1 {}}
    catch {rename HeresPackage2 {}}
} -match glob -result {0 1.2.3 0 2.3.4 0 OK1 0 OK2}
test safe-zipfs-5.4 {example pkgIndex.tcl packages, test in parent interpreter, main directories; zipfs} -setup {
    set tmpAutoPath $::auto_path
    lappend ::auto_path [file join $ZipMountPoint auto0 auto1] \
    test safe-zipfs-5.1 {example tclIndex commands, test in parent interpreter; zipfs} -setup {
	set tmpAutoPath $::auto_path
	lappend ::auto_path [file join $ZipMountPoint auto0 auto1] [file join $ZipMountPoint auto0 auto2]
    } -body {
	# Try to load the commands.
	set code3 [catch report1 msg3]
	set code4 [catch report2 msg4]
	list $code3 $msg3 $code4 $msg4
    } -cleanup {
	catch {rename report1 {}}
	catch {rename report2 {}}
	set ::auto_path $tmpAutoPath
	auto_reset
    } -match glob -result {0 ok1 0 ok2}
    test safe-zipfs-5.2 {example tclIndex commands, negative test in parent interpreter; zipfs} -setup {
	set tmpAutoPath $::auto_path
	lappend ::auto_path [file join $ZipMountPoint auto0]
    } -body {
	# Try to load the commands.
	set code3 [catch report1 msg3]
	set code4 [catch report2 msg4]
	list $code3 $msg3 $code4 $msg4
    } -cleanup {
	catch {rename report1 {}}
	catch {rename report2 {}}
	set ::auto_path $tmpAutoPath
	auto_reset
    } -match glob -result {1 {invalid command name "report1"} 1 {invalid command name "report2"}}
    test safe-zipfs-5.3 {example pkgIndex.tcl packages, test in parent interpreter, child directories; zipfs} -setup {
	set tmpAutoPath $::auto_path
	lappend ::auto_path [file join $ZipMountPoint auto0]
    } -body {
	# Try to load the packages and run a command from each one.
	set code3 [catch {package require SafeTestPackage1} msg3]
	set code4 [catch {package require SafeTestPackage2} msg4]
	set code5 [catch HeresPackage1 msg5]
	set code6 [catch HeresPackage2 msg6]
	list $code3 $msg3 $code4 $msg4 $code5 $msg5 $code6 $msg6
    } -cleanup {
	set ::auto_path $tmpAutoPath
	catch {package forget SafeTestPackage1}
	catch {package forget SafeTestPackage2}
	catch {rename HeresPackage1 {}}
	catch {rename HeresPackage2 {}}
    } -match glob -result {0 1.2.3 0 2.3.4 0 OK1 0 OK2}
    test safe-zipfs-5.4 {example pkgIndex.tcl packages, test in parent interpreter, main directories; zipfs} -setup {
	set tmpAutoPath $::auto_path
	lappend ::auto_path [file join $ZipMountPoint auto0 auto1]  [file join $ZipMountPoint auto0 auto2]
                        [file join $ZipMountPoint auto0 auto2]
} -body {
    # Try to load the packages and run a command from each one.
    set code3 [catch {package require SafeTestPackage1} msg3]
    set code4 [catch {package require SafeTestPackage2} msg4]
    set code5 [catch HeresPackage1 msg5]
    set code6 [catch HeresPackage2 msg6]
    list $code3 $msg3 $code4 $msg4 $code5 $msg5 $code6 $msg6
} -cleanup {
    set ::auto_path $tmpAutoPath
    catch {package forget SafeTestPackage1}
    catch {package forget SafeTestPackage2}
    catch {rename HeresPackage1 {}}
    catch {rename HeresPackage2 {}}
} -match glob -result {0 1.2.3 0 2.3.4 0 OK1 0 OK2}
test safe-zipfs-5.5 {example modules packages, test in parent interpreter, replace path; zipfs} -setup {
    set oldTm [tcl::tm::path list]
    foreach path $oldTm {
        tcl::tm::path remove $path
    }
    tcl::tm::path add [file join $ZipMountPoint auto0 modules]
} -body {
    # Try to load the modules and run a command from each one.
    set code0 [catch {package require test0} msg0]
    set code1 [catch {package require mod1::test1} msg1]
    set code2 [catch {package require mod2::test2} msg2]
    set out0  [test0::try0]
    set out1  [mod1::test1::try1]
    set out2  [mod2::test2::try2]
    list $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $out0 $out1 $out2
} -cleanup {
    tcl::tm::path remove [file join $ZipMountPoint auto0 modules]
    foreach path [lreverse $oldTm] {
        tcl::tm::path add $path
    }
    catch {package forget test0}
    catch {package forget mod1::test1}
    catch {package forget mod2::test2}
    catch {namespace delete ::test0}
    catch {namespace delete ::mod1}
} -match glob -result {0 0.5 0 1.0 0 2.0 -- res0 res1 res2}
test safe-zipfs-5.6 {example modules packages, test in parent interpreter, append to path; zipfs} -setup {
    tcl::tm::path add [file join $ZipMountPoint auto0 modules]
} -body {
    # Try to load the modules and run a command from each one.
    set code0 [catch {package require test0} msg0]
    set code1 [catch {package require mod1::test1} msg1]
    set code2 [catch {package require mod2::test2} msg2]
    set out0  [test0::try0]
    set out1  [mod1::test1::try1]
    set out2  [mod2::test2::try2]
    list $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $out0 $out1 $out2
} -cleanup {
    tcl::tm::path remove [file join $ZipMountPoint auto0 modules]
    catch {package forget test0}
    catch {package forget mod1::test1}
    catch {package forget mod2::test2}
    catch {namespace delete ::test0}
    catch {namespace delete ::mod1}
} -match glob -result {0 0.5 0 1.0 0 2.0 -- res0 res1 res2}
    } -body {
	# Try to load the packages and run a command from each one.
	set code3 [catch {package require SafeTestPackage1} msg3]
	set code4 [catch {package require SafeTestPackage2} msg4]
	set code5 [catch HeresPackage1 msg5]
	set code6 [catch HeresPackage2 msg6]
	list $code3 $msg3 $code4 $msg4 $code5 $msg5 $code6 $msg6
    } -cleanup {
	set ::auto_path $tmpAutoPath
	catch {package forget SafeTestPackage1}
	catch {package forget SafeTestPackage2}
	catch {rename HeresPackage1 {}}
	catch {rename HeresPackage2 {}}
    } -match glob -result {0 1.2.3 0 2.3.4 0 OK1 0 OK2}
    test safe-zipfs-5.5 {example modules packages, test in parent interpreter, replace path; zipfs} -setup {
	set oldTm [tcl::tm::path list]
	foreach path $oldTm {
	    tcl::tm::path remove $path
	}
	tcl::tm::path add [file join $ZipMountPoint auto0 modules]
    } -body {
	# Try to load the modules and run a command from each one.
	set code0 [catch {package require test0} msg0]
	set code1 [catch {package require mod1::test1} msg1]
	set code2 [catch {package require mod2::test2} msg2]
	set out0  [test0::try0]
	set out1  [mod1::test1::try1]
	set out2  [mod2::test2::try2]
	list $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $out0 $out1 $out2
    } -cleanup {
	tcl::tm::path remove [file join $ZipMountPoint auto0 modules]
	foreach path [lreverse $oldTm] {
	    tcl::tm::path add $path
	}
	catch {package forget test0}
	catch {package forget mod1::test1}
	catch {package forget mod2::test2}
	catch {namespace delete ::test0}
	catch {namespace delete ::mod1}
    } -match glob -result {0 0.5 0 1.0 0 2.0 -- res0 res1 res2}
    test safe-zipfs-5.6 {example modules packages, test in parent interpreter, append to path; zipfs} -setup {
	tcl::tm::path add [file join $ZipMountPoint auto0 modules]
    } -body {
	# Try to load the modules and run a command from each one.
	set code0 [catch {package require test0} msg0]
	set code1 [catch {package require mod1::test1} msg1]
	set code2 [catch {package require mod2::test2} msg2]
	set out0  [test0::try0]
	set out1  [mod1::test1::try1]
	set out2  [mod2::test2::try2]
	list $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $out0 $out1 $out2
    } -cleanup {
	tcl::tm::path remove [file join $ZipMountPoint auto0 modules]
	catch {package forget test0}
	catch {package forget mod1::test1}
	catch {package forget mod2::test2}
	catch {namespace delete ::test0}
	catch {namespace delete ::mod1}
    } -match glob -result {0 0.5 0 1.0 0 2.0 -- res0 res1 res2}

# high level general test
# Use zipped example packages not http1.0 etc
test safe-zipfs-7.1 {tests that everything works at high level; zipfs} -setup {
    set tmpAutoPath $::auto_path
    lappend ::auto_path [file join $ZipMountPoint auto0]
    set i [safe::interpCreate]
    set ::auto_path $tmpAutoPath
} -body {
    # no error shall occur:
    # (because the default access_path shall include 1st level sub dirs so
    #  package require in a child works like in the parent)
    set v [interp eval $i {package require SafeTestPackage1}]
    # no error shall occur:
    interp eval $i {HeresPackage1}
    set v
} -cleanup {
    safe::interpDelete $i
} -match glob -result 1.2.3
test safe-zipfs-7.2 {tests specific path and interpFind/AddToAccessPath; zipfs} -setup {
} -body {
    set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]
    # should not add anything (p0)
    set token1 [safe::interpAddToAccessPath $i [info library]]
    # should add as p* (not p1 if parent has a module path)
    set token2 [safe::interpAddToAccessPath $i "/dummy/unixlike/test/path"]
    # should add as p* (not p2 if parent has a module path)
    set token3 [safe::interpAddToAccessPath $i [file join $ZipMountPoint auto0]]
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    # an error shall occur (SafeTestPackage1 is not anymore in the secure 0-level
    # provided deep path)
    # high level general test
    # Use zipped example packages not http1.0 etc
    test safe-zipfs-7.1 {tests that everything works at high level with conventional AutoPathSync; zipfs} -setup {
	set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
	if {$SyncExists} {
	    set SyncVal_TMP [safe::setSyncMode]
	    safe::setSyncMode 1
	}
	set tmpAutoPath $::auto_path
	lappend ::auto_path [file join $ZipMountPoint auto0]
	set i [safe::interpCreate]
	set ::auto_path $tmpAutoPath
    } -body {
	# no error shall occur:
	# (because the default access_path shall include 1st level sub dirs so
	#  package require in a child works like in the parent)
	set v [interp eval $i {package require SafeTestPackage1}]
	# no error shall occur:
	interp eval $i {HeresPackage1}
	set v
    } -cleanup {
	safe::interpDelete $i
	if {$SyncExists} {
	    safe::setSyncMode $SyncVal_TMP
	}
    } -match glob -result 1.2.3
    test safe-zipfs-7.2 {tests specific path and interpFind/AddToAccessPath with conventional AutoPathSync; zipfs} -setup {
	set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
	if {$SyncExists} {
	    set SyncVal_TMP [safe::setSyncMode]
	    safe::setSyncMode 1
	} else {
	    set SyncVal_TMP 1
	}
    } -body {
	set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]
	# should not add anything (p0)
	set token1 [safe::interpAddToAccessPath $i [info library]]
	# should add as p* (not p1 if parent has a module path)
	set token2 [safe::interpAddToAccessPath $i "/dummy/unixlike/test/path"]
	# should add as p* (not p2 if parent has a module path)
	set token3 [safe::interpAddToAccessPath $i [file join $ZipMountPoint auto0]]
	set confA [safe::interpConfigure $i]
	set mappA [mapList $PathMapp [dict get $confA -accessPath]]
	# an error shall occur (SafeTestPackage1 is not anymore in the secure 0-level
	# provided deep path)
    list $token1 $token2 $token3 -- \
            [catch {interp eval $i {package require SafeTestPackage1}} msg] $msg -- \
	list $token1 $token2 $token3 --  [catch {interp eval $i {package require SafeTestPackage1}} msg] $msg --  $mappA -- [safe::interpDelete $i]
            $mappA -- [safe::interpDelete $i]
} -cleanup {
} -match glob -result {{$p(:0:)} {$p(:*:)} {$p(:*:)} --\
    } -cleanup {
	if {$SyncExists} {
	    safe::setSyncMode $SyncVal_TMP
	}
    } -match glob -result {{$p(:0:)} {$p(:*:)} {$p(:*:)} -- 1 {can't find package SafeTestPackage1} -- {TCLLIB */dummy/unixlike/test/path ZIPDIR/auto0} -- {}}
        1 {can't find package SafeTestPackage1} --\
        {TCLLIB */dummy/unixlike/test/path ZIPDIR/auto0} -- {}}
test safe-zipfs-7.4 {tests specific path and positive search; zipfs} -setup {
} -body {
    set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]
    # should not add anything (p0)
    set token1 [safe::interpAddToAccessPath $i [info library]]
    # should add as p* (not p1 if parent has a module path)
    set token2 [safe::interpAddToAccessPath $i [file join $ZipMountPoint auto0 auto1]]
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    # this time, unlike test safe-zipfs-7.2, SafeTestPackage1 should be found
    test safe-zipfs-7.4 {tests specific path and positive search with conventional AutoPathSync; zipfs} -setup {
	set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
	if {$SyncExists} {
	    set SyncVal_TMP [safe::setSyncMode]
	    safe::setSyncMode 1
	} else {
	    set SyncVal_TMP 1
	}
    } -body {
	set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]
	# should not add anything (p0)
	set token1 [safe::interpAddToAccessPath $i [info library]]
	# should add as p* (not p1 if parent has a module path)
	set token2 [safe::interpAddToAccessPath $i [file join $ZipMountPoint auto0 auto1]]
	set confA [safe::interpConfigure $i]
	set mappA [mapList $PathMapp [dict get $confA -accessPath]]
	# this time, unlike test safe-zipfs-7.2, SafeTestPackage1 should be found
    list $token1 $token2 -- \
	    [catch {interp eval $i {package require SafeTestPackage1}} msg] $msg -- \
	list $token1 $token2 --  [catch {interp eval $i {package require SafeTestPackage1}} msg] $msg --  $mappA -- [safe::interpDelete $i]
	    $mappA -- [safe::interpDelete $i]
    # Note that the glob match elides directories (those from the module path)
    # other than the first and last in the access path.
} -cleanup {
} -match glob -result {{$p(:0:)} {$p(:*:)} -- 0 1.2.3 --\
	# Note that the glob match elides directories (those from the module path)
	# other than the first and last in the access path.
    } -cleanup {
	if {$SyncExists} {
	    safe::setSyncMode $SyncVal_TMP
	}
    } -match glob -result {{$p(:0:)} {$p(:*:)} -- 0 1.2.3 -- {TCLLIB * ZIPDIR/auto0/auto1} -- {}}
        {TCLLIB * ZIPDIR/auto0/auto1} -- {}}

test safe-zipfs-9.9 {interpConfigure change the access path; tclIndex commands unaffected by token rearrangement (dummy test of doreset); zipfs} -setup {
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library \
    test safe-zipfs-9.9 {interpConfigure change the access path; tclIndex commands unaffected by token rearrangement (dummy test of doreset) with conventional AutoPathSync; zipfs} -setup {
	set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
	if {$SyncExists} {
	    set SyncVal_TMP [safe::setSyncMode]
	    safe::setSyncMode 1
	}
    } -body {
	set i [safe::interpCreate -accessPath [list $tcl_library  [file join $ZipMountPoint auto0 auto1]  [file join $ZipMountPoint auto0 auto2]]]
                                            [file join $ZipMountPoint auto0 auto1] \
                                            [file join $ZipMountPoint auto0 auto2]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]]
	# Inspect.
	set confA [safe::interpConfigure $i]
	set mappA [mapList $PathMapp [dict get $confA -accessPath]]
	set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]]
	set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]]

    # Load auto_load data.
    interp eval $i {catch nonExistentCommand}
	# Load auto_load data.
	interp eval $i {catch nonExistentCommand}

    # Load and run the commands.
    # This guarantees the test will pass even if the tokens are swapped.
    set code1 [catch {interp eval $i {report1}} msg1]
    set code2 [catch {interp eval $i {report2}} msg2]
	# Load and run the commands.
	# This guarantees the test will pass even if the tokens are swapped.
	set code1 [catch {interp eval $i {report1}} msg1]
	set code2 [catch {interp eval $i {report2}} msg2]

    # Rearrange access path.  Swap tokens {$p(:1:)} and {$p(:2:)}.
    safe::interpConfigure $i -accessPath [list $tcl_library \
	# Rearrange access path.  Swap tokens {$p(:1:)} and {$p(:2:)}.
	safe::interpConfigure $i -accessPath [list $tcl_library  [file join $ZipMountPoint auto0 auto2]  [file join $ZipMountPoint auto0 auto1]]
                                           [file join $ZipMountPoint auto0 auto2] \
                                           [file join $ZipMountPoint auto0 auto1]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set path3 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]]
    set path4 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]]
	# Inspect.
	set confB [safe::interpConfigure $i]
	set mappB [mapList $PathMapp [dict get $confB -accessPath]]
	set path3 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]]
	set path4 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]]

    # Run the commands.
    set code3 [catch {interp eval $i {report1}} msg3]
    set code4 [catch {interp eval $i {report2}} msg4]
	# Run the commands.
	set code3 [catch {interp eval $i {report1}} msg3]
	set code4 [catch {interp eval $i {report2}} msg4]

    list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- $mappA -- $mappB
} -cleanup {
    safe::interpDelete $i
} -match glob -result {{$p(:1:)} {$p(:2:)} -- {$p(:2:)} {$p(:1:)} -- 0 ok1 0 ok2 --\
	list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- $mappA -- $mappB
    } -cleanup {
	safe::interpDelete $i
	if {$SyncExists} {
	    safe::setSyncMode $SyncVal_TMP
	}
    } -match glob -result {{$p(:1:)} {$p(:2:)} -- {$p(:2:)} {$p(:1:)} -- 0 ok1 0 ok2 -- {TCLLIB ZIPDIR/auto0/auto1 ZIPDIR/auto0/auto2*} -- {TCLLIB ZIPDIR/auto0/auto2 ZIPDIR/auto0/auto1*}}
        {TCLLIB ZIPDIR/auto0/auto1 ZIPDIR/auto0/auto2*} --\
        {TCLLIB ZIPDIR/auto0/auto2 ZIPDIR/auto0/auto1*}}
test safe-zipfs-9.10 {interpConfigure change the access path; tclIndex commands unaffected by token rearrangement (actual test of doreset); zipfs} -setup {
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library \
    test safe-zipfs-9.10 {interpConfigure change the access path; tclIndex commands unaffected by token rearrangement (actual test of doreset) with conventional AutoPathSync; zipfs} -setup {
	set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
	if {$SyncExists} {
	    set SyncVal_TMP [safe::setSyncMode]
	    safe::setSyncMode 1
	}
    } -body {
	set i [safe::interpCreate -accessPath [list $tcl_library  [file join $ZipMountPoint auto0 auto1]  [file join $ZipMountPoint auto0 auto2]]]
                                            [file join $ZipMountPoint auto0 auto1] \
                                            [file join $ZipMountPoint auto0 auto2]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]]
	# Inspect.
	set confA [safe::interpConfigure $i]
	set mappA [mapList $PathMapp [dict get $confA -accessPath]]
	set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]]
	set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]]

    # Load auto_load data.
    interp eval $i {catch nonExistentCommand}
	# Load auto_load data.
	interp eval $i {catch nonExistentCommand}

    # Do not load the commands.  With the tokens swapped, the test
    # will pass only if the Safe Base has called auto_reset.
	# Do not load the commands.  With the tokens swapped, the test
	# will pass only if the Safe Base has called auto_reset.

    # Rearrange access path.  Swap tokens {$p(:1:)} and {$p(:2:)}.
    safe::interpConfigure $i -accessPath [list $tcl_library \
	# Rearrange access path.  Swap tokens {$p(:1:)} and {$p(:2:)}.
	safe::interpConfigure $i -accessPath [list $tcl_library  [file join $ZipMountPoint auto0 auto2]  [file join $ZipMountPoint auto0 auto1]]
                                           [file join $ZipMountPoint auto0 auto2] \
                                           [file join $ZipMountPoint auto0 auto1]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set path3 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]]
    set path4 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]]
	# Inspect.
	set confB [safe::interpConfigure $i]
	set mappB [mapList $PathMapp [dict get $confB -accessPath]]
	set path3 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]]
	set path4 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]]

    # Load and run the commands.
    set code3 [catch {interp eval $i {report1}} msg3]
    set code4 [catch {interp eval $i {report2}} msg4]
	# Load and run the commands.
	set code3 [catch {interp eval $i {report1}} msg3]
	set code4 [catch {interp eval $i {report2}} msg4]

    list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- $mappA -- $mappB
} -cleanup {
    safe::interpDelete $i
} -match glob -result {{$p(:1:)} {$p(:2:)} -- {$p(:2:)} {$p(:1:)} --\
	list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- $mappA -- $mappB
    } -cleanup {
	safe::interpDelete $i
	if {$SyncExists} {
	    safe::setSyncMode $SyncVal_TMP
	}
    } -match glob -result {{$p(:1:)} {$p(:2:)} -- {$p(:2:)} {$p(:1:)} -- 0 ok1 0 ok2 -- {TCLLIB ZIPDIR/auto0/auto1 ZIPDIR/auto0/auto2*} -- {TCLLIB ZIPDIR/auto0/auto2 ZIPDIR/auto0/auto1*}}
        0 ok1 0 ok2 --\
        {TCLLIB ZIPDIR/auto0/auto1 ZIPDIR/auto0/auto2*} --\
        {TCLLIB ZIPDIR/auto0/auto2 ZIPDIR/auto0/auto1*}}
test safe-zipfs-9.11 {interpConfigure change the access path; pkgIndex.tcl packages unaffected by token rearrangement; zipfs} -setup {
} -body {
    # For complete correspondence to safe-stock87-9.11, include auto0 in access path.
    set i [safe::interpCreate -accessPath [list $tcl_library \
    test safe-zipfs-9.11 {interpConfigure change the access path; pkgIndex.tcl packages unaffected by token rearrangement with conventional AutoPathSync; zipfs} -setup {
	set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
	if {$SyncExists} {
	    set SyncVal_TMP [safe::setSyncMode]
	    safe::setSyncMode 1
	}
    } -body {
	# For complete correspondence to safe-stock-9.11, include auto0 in access path.
	set i [safe::interpCreate -accessPath [list $tcl_library  [file join $ZipMountPoint auto0]  [file join $ZipMountPoint auto0 auto1]  [file join $ZipMountPoint auto0 auto2]]]
                                            [file join $ZipMountPoint auto0] \
                                            [file join $ZipMountPoint auto0 auto1] \
                                            [file join $ZipMountPoint auto0 auto2]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path0 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0]]
    set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]]
	# Inspect.
	set confA [safe::interpConfigure $i]
	set mappA [mapList $PathMapp [dict get $confA -accessPath]]
	set path0 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0]]
	set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]]
	set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]]

    # Load pkgIndex.tcl data.
    catch {interp eval $i {package require NOEXIST}}
	# Load pkgIndex.tcl data.
	catch {interp eval $i {package require NOEXIST}}

    # Rearrange access path.  Swap tokens {$p(:2:)} and {$p(:3:)}.
    # This would have no effect because the records in Pkg of these directories
    # were from access as children of {$p(:1:)}.
    safe::interpConfigure $i -accessPath [list $tcl_library \
	# Rearrange access path.  Swap tokens {$p(:2:)} and {$p(:3:)}.
	# This would have no effect because the records in Pkg of these directories
	# were from access as children of {$p(:1:)}.
	safe::interpConfigure $i -accessPath [list $tcl_library  [file join $ZipMountPoint auto0]  [file join $ZipMountPoint auto0 auto2]  [file join $ZipMountPoint auto0 auto1]]
                                           [file join $ZipMountPoint auto0] \
                                           [file join $ZipMountPoint auto0 auto2] \
                                           [file join $ZipMountPoint auto0 auto1]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set path3 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]]
    set path4 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]]
	# Inspect.
	set confB [safe::interpConfigure $i]
	set mappB [mapList $PathMapp [dict get $confB -accessPath]]
	set path3 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]]
	set path4 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]]

    # Try to load the packages and run a command from each one.
    set code3 [catch {interp eval $i {package require SafeTestPackage1}} msg3 opts3]
    set code4 [catch {interp eval $i {package require SafeTestPackage2}} msg4 opts4]
    set code5 [catch {interp eval $i {HeresPackage1}} msg5 opts5]
    set code6 [catch {interp eval $i {HeresPackage2}} msg6 opts6]
	# Try to load the packages and run a command from each one.
	set code3 [catch {interp eval $i {package require SafeTestPackage1}} msg3 opts3]
	set code4 [catch {interp eval $i {package require SafeTestPackage2}} msg4 opts4]
	set code5 [catch {interp eval $i {HeresPackage1}} msg5 opts5]
	set code6 [catch {interp eval $i {HeresPackage2}} msg6 opts6]

    list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- \
	list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 --  $mappA -- $mappB -- $code5 $msg5 $code6 $msg6
         $mappA -- $mappB -- $code5 $msg5 $code6 $msg6
} -cleanup {
    safe::interpDelete $i
} -match glob -result {{$p(:2:)} {$p(:3:)} -- {$p(:3:)} {$p(:2:)} -- 0 1.2.3 0 2.3.4 --\
    } -cleanup {
	safe::interpDelete $i
	if {$SyncExists} {
	    safe::setSyncMode $SyncVal_TMP
	}
    } -match glob -result {{$p(:2:)} {$p(:3:)} -- {$p(:3:)} {$p(:2:)} -- 0 1.2.3 0 2.3.4 -- {TCLLIB ZIPDIR/auto0 ZIPDIR/auto0/auto1 ZIPDIR/auto0/auto2*} -- {TCLLIB ZIPDIR/auto0 ZIPDIR/auto0/auto2 ZIPDIR/auto0/auto1*} -- 0 OK1 0 OK2}
        {TCLLIB ZIPDIR/auto0 ZIPDIR/auto0/auto1 ZIPDIR/auto0/auto2*} --\
        {TCLLIB ZIPDIR/auto0 ZIPDIR/auto0/auto2 ZIPDIR/auto0/auto1*} --\
        0 OK1 0 OK2}
test safe-zipfs-9.12 {interpConfigure change the access path; pkgIndex.tcl packages unaffected by token rearrangement, 9.10 without path auto0; zipfs} -setup {
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library \
    test safe-zipfs-9.12 {interpConfigure change the access path; pkgIndex.tcl packages unaffected by token rearrangement, 9.10 without path auto0 with conventional AutoPathSync; zipfs} -setup {
	set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
	if {$SyncExists} {
	    set SyncVal_TMP [safe::setSyncMode]
	    safe::setSyncMode 1
	}
    } -body {
	set i [safe::interpCreate -accessPath [list $tcl_library  [file join $ZipMountPoint auto0 auto1]  [file join $ZipMountPoint auto0 auto2]]]
                                            [file join $ZipMountPoint auto0 auto1] \
                                            [file join $ZipMountPoint auto0 auto2]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]]
	# Inspect.
	set confA [safe::interpConfigure $i]
	set mappA [mapList $PathMapp [dict get $confA -accessPath]]
	set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]]
	set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]]

    # Load pkgIndex.tcl data.
    catch {interp eval $i {package require NOEXIST}}
	# Load pkgIndex.tcl data.
	catch {interp eval $i {package require NOEXIST}}

    # Rearrange access path.  Swap tokens {$p(:1:)} and {$p(:2:)}.
    safe::interpConfigure $i -accessPath [list $tcl_library \
	# Rearrange access path.  Swap tokens {$p(:1:)} and {$p(:2:)}.
	safe::interpConfigure $i -accessPath [list $tcl_library  [file join $ZipMountPoint auto0 auto2]  [file join $ZipMountPoint auto0 auto1]]
                                           [file join $ZipMountPoint auto0 auto2] \
                                           [file join $ZipMountPoint auto0 auto1]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set path3 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]]
    set path4 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]]
	# Inspect.
	set confB [safe::interpConfigure $i]
	set mappB [mapList $PathMapp [dict get $confB -accessPath]]
	set path3 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]]
	set path4 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]]

    # Try to load the packages and run a command from each one.
    set code3 [catch {interp eval $i {package require SafeTestPackage1}} msg3 opts3]
    set code4 [catch {interp eval $i {package require SafeTestPackage2}} msg4 opts4]
    set code5 [catch {interp eval $i {HeresPackage1}} msg5 opts5]
    set code6 [catch {interp eval $i {HeresPackage2}} msg6 opts6]
	# Try to load the packages and run a command from each one.
	set code3 [catch {interp eval $i {package require SafeTestPackage1}} msg3 opts3]
	set code4 [catch {interp eval $i {package require SafeTestPackage2}} msg4 opts4]
	set code5 [catch {interp eval $i {HeresPackage1}} msg5 opts5]
	set code6 [catch {interp eval $i {HeresPackage2}} msg6 opts6]

    list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- \
	list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 --  $mappA -- $mappB -- $code5 $msg5 $code6 $msg6
            $mappA -- $mappB -- $code5 $msg5 $code6 $msg6
} -cleanup {
    safe::interpDelete $i
} -match glob -result {{$p(:1:)} {$p(:2:)} -- {$p(:2:)} {$p(:1:)} --\
    } -cleanup {
	safe::interpDelete $i
	if {$SyncExists} {
	    safe::setSyncMode $SyncVal_TMP
	}
    } -match glob -result {{$p(:1:)} {$p(:2:)} -- {$p(:2:)} {$p(:1:)} -- 0 1.2.3 0 2.3.4 -- {TCLLIB ZIPDIR/auto0/auto1 ZIPDIR/auto0/auto2*} -- {TCLLIB ZIPDIR/auto0/auto2 ZIPDIR/auto0/auto1*} -- 0 OK1 0 OK2}
        0 1.2.3 0 2.3.4 --\
        {TCLLIB ZIPDIR/auto0/auto1 ZIPDIR/auto0/auto2*} --\
        {TCLLIB ZIPDIR/auto0/auto2 ZIPDIR/auto0/auto1*} --\
        0 OK1 0 OK2}
test safe-zipfs-9.13 {interpConfigure change the access path; pkgIndex.tcl packages fail if directory de-listed; zipfs} -setup {
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library \
    test safe-zipfs-9.13 {interpConfigure change the access path; pkgIndex.tcl packages fail if directory de-listed, with conventional AutoPathSync; zipfs} -setup {
	set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
	if {$SyncExists} {
	    set SyncVal_TMP [safe::setSyncMode]
	    safe::setSyncMode 1
	}
    } -body {
	set i [safe::interpCreate -accessPath [list $tcl_library  [file join $ZipMountPoint auto0 auto1]  [file join $ZipMountPoint auto0 auto2]]]
                                            [file join $ZipMountPoint auto0 auto1] \
                                            [file join $ZipMountPoint auto0 auto2]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]]
	# Inspect.
	set confA [safe::interpConfigure $i]
	set mappA [mapList $PathMapp [dict get $confA -accessPath]]
	set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]]
	set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]]

    # Load pkgIndex.tcl data.
    catch {interp eval $i {package require NOEXIST}}
	# Load pkgIndex.tcl data.
	catch {interp eval $i {package require NOEXIST}}

    # Limit access path.  Remove tokens {$p(:1:)} and {$p(:2:)}.
    safe::interpConfigure $i -accessPath [list $tcl_library]
	# Limit access path.  Remove tokens {$p(:1:)} and {$p(:2:)}.
	safe::interpConfigure $i -accessPath [list $tcl_library]

    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set code4 [catch {::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]} path4]
    set code5 [catch {::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]} path5]
	# Inspect.
	set confB [safe::interpConfigure $i]
	set mappB [mapList $PathMapp [dict get $confB -accessPath]]
	set code4 [catch {::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto1]} path4]
	set code5 [catch {::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 auto2]} path5]

    # Try to load the packages.
    set code3 [catch {interp eval $i {package require SafeTestPackage1}} msg3]
    set code6 [catch {interp eval $i {package require SafeTestPackage2}} msg6]
	# Try to load the packages.
	set code3 [catch {interp eval $i {package require SafeTestPackage1}} msg3]
	set code6 [catch {interp eval $i {package require SafeTestPackage2}} msg6]

    list $path1 $path2 -- $code4 $path4 -- $code5 $path5 -- $code3 $code6 -- \
	list $path1 $path2 -- $code4 $path4 -- $code5 $path5 -- $code3 $code6 --  $mappA -- $mappB
            $mappA -- $mappB
} -cleanup {
    safe::interpDelete $i
} -match glob -result {{$p(:1:)} {$p(:2:)} -- 1 {* not found in access path} --\
    } -cleanup {
	safe::interpDelete $i
	if {$SyncExists} {
	    safe::setSyncMode $SyncVal_TMP
	}
    } -match glob -result {{$p(:1:)} {$p(:2:)} -- 1 {* not found in access path} -- 1 {* not found in access path} -- 1 1 -- {TCLLIB ZIPDIR/auto0/auto1 ZIPDIR/auto0/auto2*} -- {TCLLIB*}}
        1 {* not found in access path} -- 1 1 --\
        {TCLLIB ZIPDIR/auto0/auto1 ZIPDIR/auto0/auto2*} -- {TCLLIB*}}
test safe-zipfs-9.20 {check module loading; zipfs} -setup {
    set oldTm [tcl::tm::path list]
    foreach path $oldTm {
        tcl::tm::path remove $path
    }
    tcl::tm::path add [file join $ZipMountPoint auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]
    test safe-zipfs-9.20 {check module loading, with conventional AutoPathSync; zipfs} -setup {
	set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
	if {$SyncExists} {
	    set SyncVal_TMP [safe::setSyncMode]
	    safe::setSyncMode 1
	}
	set oldTm [tcl::tm::path list]
	foreach path $oldTm {
	    tcl::tm::path remove $path
	}
	tcl::tm::path add [file join $ZipMountPoint auto0 modules]
    } -body {
	set i [safe::interpCreate -accessPath [list $tcl_library]]

    # Inspect.
    set confA [safe::interpConfigure $i]
    set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
    set modsA [interp eval $i {tcl::tm::path list}]
    set path0 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules]]
    set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod2]]
	# Inspect.
	set confA [safe::interpConfigure $i]
	set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
	set modsA [interp eval $i {tcl::tm::path list}]
	set path0 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules]]
	set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod1]]
	set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod2]]

    # Try to load the packages and run a command from each one.
    set code0 [catch {interp eval $i {package require test0}} msg0]
    set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
    set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
    set out0  [interp eval $i {test0::try0}]
    set out1  [interp eval $i {mod1::test1::try1}]
    set out2  [interp eval $i {mod2::test2::try2}]
	# Try to load the packages and run a command from each one.
	set code0 [catch {interp eval $i {package require test0}} msg0]
	set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
	set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
	set out0  [interp eval $i {test0::try0}]
	set out1  [interp eval $i {mod1::test1::try1}]
	set out2  [interp eval $i {mod2::test2::try2}]

    list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
	list [lsort [list $path0 $path1 $path2]] -- $modsA --  $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $out0 $out1 $out2
            $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $out0 $out1 $out2
} -cleanup {
    tcl::tm::path remove [file join $ZipMountPoint auto0 modules]
    foreach path [lreverse $oldTm] {
        tcl::tm::path add $path
    }
    safe::interpDelete $i
} -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
    } -cleanup {
	tcl::tm::path remove [file join $ZipMountPoint auto0 modules]
	foreach path [lreverse $oldTm] {
	    tcl::tm::path add $path
	}
	safe::interpDelete $i
	if {$SyncExists} {
	    safe::setSyncMode $SyncVal_TMP
	}
    } -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} -- 0 0.5 0 1.0 0 2.0 -- {TCLLIB ZIPDIR/auto0/modules ZIPDIR/auto0/modules/mod1 ZIPDIR/auto0/modules/mod2} -- res0 res1 res2}
        0 0.5 0 1.0 0 2.0 --\
        {TCLLIB ZIPDIR/auto0/modules ZIPDIR/auto0/modules/mod1\
         ZIPDIR/auto0/modules/mod2} -- res0 res1 res2}
# - The command safe::InterpSetConfig adds the parent's [tcl::tm::list] in
#   tokenized form to the child's access path, and then adds all the
#   descendants, discovered recursively by using glob.
# - The order of the directories in the list returned by glob is system-dependent,
#   and therefore this is true also for (a) the order of token assignment to
#   descendants of the [tcl::tm::list] roots; and (b) the order of those same
#   directories in the access path.  Both those things must be sorted before
#   comparing with expected results.  The test is therefore not totally strict,
#   but will notice missing or surplus directories.
test safe-zipfs-9.21 {interpConfigure change the access path; check module loading; stale data case 1; zipfs} -setup {
    set oldTm [tcl::tm::path list]
    foreach path $oldTm {
        tcl::tm::path remove $path
    }
    tcl::tm::path add [file join $ZipMountPoint auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]
    # - The command safe::InterpSetConfig adds the parent's [tcl::tm::list] in
    #   tokenized form to the child's access path, and then adds all the
    #   descendants, discovered recursively by using glob.
    # - The order of the directories in the list returned by glob is system-dependent,
    #   and therefore this is true also for (a) the order of token assignment to
    #   descendants of the [tcl::tm::list] roots; and (b) the order of those same
    #   directories in the access path.  Both those things must be sorted before
    #   comparing with expected results.  The test is therefore not totally strict,
    #   but will notice missing or surplus directories.
    test safe-zipfs-9.21 {interpConfigure change the access path; check module loading, with conventional AutoPathSync; stale data case 1; zipfs} -setup {
	set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
	if {$SyncExists} {
	    set SyncVal_TMP [safe::setSyncMode]
	    safe::setSyncMode 1
	}
	set oldTm [tcl::tm::path list]
	foreach path $oldTm {
	    tcl::tm::path remove $path
	}
	tcl::tm::path add [file join $ZipMountPoint auto0 modules]
    } -body {
	set i [safe::interpCreate -accessPath [list $tcl_library]]

    # Inspect.
    set confA [safe::interpConfigure $i]
    set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
    set modsA [interp eval $i {tcl::tm::path list}]
    set path0 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules]]
    set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod2]]
	# Inspect.
	set confA [safe::interpConfigure $i]
	set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
	set modsA [interp eval $i {tcl::tm::path list}]
	set path0 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules]]
	set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod1]]
	set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod2]]

    # Add to access path.
    # This injects more tokens, pushing modules to higher token numbers.
    safe::interpConfigure $i -accessPath [list $tcl_library \
	# Add to access path.
	# This injects more tokens, pushing modules to higher token numbers.
	safe::interpConfigure $i -accessPath [list $tcl_library  [file join $ZipMountPoint auto0 auto1]  [file join $ZipMountPoint auto0 auto2]]
                                           [file join $ZipMountPoint auto0 auto1] \
                                           [file join $ZipMountPoint auto0 auto2]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
    set modsB [interp eval $i {tcl::tm::path list}]
    set path3 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules]]
    set path4 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod1]]
    set path5 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod2]]
	# Inspect.
	set confB [safe::interpConfigure $i]
	set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
	set modsB [interp eval $i {tcl::tm::path list}]
	set path3 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules]]
	set path4 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod1]]
	set path5 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod2]]

    # Load pkg data.
    catch {interp eval $i {package require NOEXIST}}
    catch {interp eval $i {package require mod1::NOEXIST}}
    catch {interp eval $i {package require mod2::NOEXIST}}
	# Load pkg data.
	catch {interp eval $i {package require NOEXIST}}
	catch {interp eval $i {package require mod1::NOEXIST}}
	catch {interp eval $i {package require mod2::NOEXIST}}

    # Try to load the packages and run a command from each one.
    set code0 [catch {interp eval $i {package require test0}} msg0]
    set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
    set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
    set out0  [interp eval $i {test0::try0}]
    set out1  [interp eval $i {mod1::test1::try1}]
    set out2  [interp eval $i {mod2::test2::try2}]
	# Try to load the packages and run a command from each one.
	set code0 [catch {interp eval $i {package require test0}} msg0]
	set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
	set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
	set out0  [interp eval $i {test0::try0}]
	set out1  [interp eval $i {mod1::test1::try1}]
	set out2  [interp eval $i {mod2::test2::try2}]

    list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
            [lsort [list $path3 $path4 $path5]] -- $modsB -- \
            $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
            $out0 $out1 $out2
} -cleanup {
    tcl::tm::path remove [file join $ZipMountPoint auto0 modules]
    foreach path [lreverse $oldTm] {
        tcl::tm::path add $path
    }
    safe::interpDelete $i
} -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
	list [lsort [list $path0 $path1 $path2]] -- $modsA --  [lsort [list $path3 $path4 $path5]] -- $modsB --  $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB --  $out0 $out1 $out2
    } -cleanup {
	tcl::tm::path remove [file join $ZipMountPoint auto0 modules]
	foreach path [lreverse $oldTm] {
	    tcl::tm::path add $path
	}
	safe::interpDelete $i
	if {$SyncExists} {
	    safe::setSyncMode $SyncVal_TMP
	}
    } -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} -- {{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} -- 0 0.5 0 1.0 0 2.0 -- {TCLLIB ZIPDIR/auto0/modules ZIPDIR/auto0/modules/mod1 ZIPDIR/auto0/modules/mod2} -- {TCLLIB ZIPDIR/auto0/auto1 ZIPDIR/auto0/auto2 ZIPDIR/auto0/modules ZIPDIR/auto0/modules/mod1 ZIPDIR/auto0/modules/mod2} -- res0 res1 res2}
    # See comments on lsort after test safe-zipfs-9.20.
    test safe-zipfs-9.22 {interpConfigure change the access path; check module loading, with conventional AutoPathSync; stale data case 0; zipfs} -setup {
	set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
	if {$SyncExists} {
	    set SyncVal_TMP [safe::setSyncMode]
	    safe::setSyncMode 1
	}
	set oldTm [tcl::tm::path list]
	foreach path $oldTm {
	    tcl::tm::path remove $path
	}
	tcl::tm::path add [file join $ZipMountPoint auto0 modules]
    } -body {
	set i [safe::interpCreate -accessPath [list $tcl_library]]

	# Inspect.
	set confA [safe::interpConfigure $i]
	set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
	set modsA [interp eval $i {tcl::tm::path list}]
	set path0 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules]]
	set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod1]]
	set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod2]]

	# Add to access path.
	# This injects more tokens, pushing modules to higher token numbers.
	safe::interpConfigure $i -accessPath [list $tcl_library  [file join $ZipMountPoint auto0 auto1]  [file join $ZipMountPoint auto0 auto2]]
	# Inspect.
	set confB [safe::interpConfigure $i]
	set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
	set modsB [interp eval $i {tcl::tm::path list}]
	set path3 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules]]
	set path4 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod1]]
	set path5 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod2]]

	# Try to load the packages and run a command from each one.
	set code0 [catch {interp eval $i {package require test0}} msg0]
	set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
	set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
	set out0  [interp eval $i {test0::try0}]
	set out1  [interp eval $i {mod1::test1::try1}]
	set out2  [interp eval $i {mod2::test2::try2}]

	list [lsort [list $path0 $path1 $path2]] -- $modsA --  [lsort [list $path3 $path4 $path5]] -- $modsB --  $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB --  $out0 $out1 $out2
    } -cleanup {
	tcl::tm::path remove [file join $ZipMountPoint auto0 modules]
	foreach path [lreverse $oldTm] {
	    tcl::tm::path add $path
	}
	safe::interpDelete $i
	if {$SyncExists} {
	    safe::setSyncMode $SyncVal_TMP
	}
    } -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} -- {{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} -- 0 0.5 0 1.0 0 2.0 -- {TCLLIB ZIPDIR/auto0/modules ZIPDIR/auto0/modules/mod1 ZIPDIR/auto0/modules/mod2} -- {TCLLIB ZIPDIR/auto0/auto1 ZIPDIR/auto0/auto2 ZIPDIR/auto0/modules ZIPDIR/auto0/modules/mod1 ZIPDIR/auto0/modules/mod2} -- res0 res1 res2}
        {{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
        0 0.5 0 1.0 0 2.0 --\
        {TCLLIB ZIPDIR/auto0/modules ZIPDIR/auto0/modules/mod1\
         ZIPDIR/auto0/modules/mod2} --\
        {TCLLIB ZIPDIR/auto0/auto1 ZIPDIR/auto0/auto2 ZIPDIR/auto0/modules\
         ZIPDIR/auto0/modules/mod1 ZIPDIR/auto0/modules/mod2} --\
        res0 res1 res2}
# See comments on lsort after test safe-zipfs-9.20.
test safe-zipfs-9.22 {interpConfigure change the access path; check module loading; stale data case 0; zipfs} -setup {
    set oldTm [tcl::tm::path list]
    foreach path $oldTm {
        tcl::tm::path remove $path
    }
    tcl::tm::path add [file join $ZipMountPoint auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]
    # See comments on lsort after test safe-zipfs-9.20.
    test safe-zipfs-9.23 {interpConfigure change the access path; check module loading, with conventional AutoPathSync; stale data case 3; zipfs} -setup {
	set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
	if {$SyncExists} {
	    set SyncVal_TMP [safe::setSyncMode]
	    safe::setSyncMode 1
	}
	set oldTm [tcl::tm::path list]
	foreach path $oldTm {
	    tcl::tm::path remove $path
	}
	tcl::tm::path add [file join $ZipMountPoint auto0 modules]
    } -body {
	set i [safe::interpCreate -accessPath [list $tcl_library]]

    # Inspect.
    set confA [safe::interpConfigure $i]
    set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
    set modsA [interp eval $i {tcl::tm::path list}]
    set path0 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules]]
    set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod2]]
	# Inspect.
	set confA [safe::interpConfigure $i]
	set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
	set modsA [interp eval $i {tcl::tm::path list}]
	set path0 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules]]
	set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod1]]
	set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod2]]

	# Force the interpreter to acquire pkg data which will soon become stale.
	catch {interp eval $i {package require NOEXIST}}
	catch {interp eval $i {package require mod1::NOEXIST}}
	catch {interp eval $i {package require mod2::NOEXIST}}

    # Add to access path.
    # This injects more tokens, pushing modules to higher token numbers.
    safe::interpConfigure $i -accessPath [list $tcl_library \
	# Add to access path.
	# This injects more tokens, pushing modules to higher token numbers.
	safe::interpConfigure $i -accessPath [list $tcl_library  [file join $ZipMountPoint auto0 auto1]  [file join $ZipMountPoint auto0 auto2]]
                                          [file join $ZipMountPoint auto0 auto1] \
                                          [file join $ZipMountPoint auto0 auto2]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
    set modsB [interp eval $i {tcl::tm::path list}]
    set path3 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules]]
    set path4 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod1]]
    set path5 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod2]]
	# Inspect.
	set confB [safe::interpConfigure $i]
	set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
	set modsB [interp eval $i {tcl::tm::path list}]
	set path3 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules]]
	set path4 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod1]]
	set path5 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod2]]

	# Refresh stale pkg data.
	catch {interp eval $i {package require NOEXIST}}
	catch {interp eval $i {package require mod1::NOEXIST}}
	catch {interp eval $i {package require mod2::NOEXIST}}

    # Try to load the packages and run a command from each one.
    set code0 [catch {interp eval $i {package require test0}} msg0]
    set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
    set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
    set out0  [interp eval $i {test0::try0}]
    set out1  [interp eval $i {mod1::test1::try1}]
    set out2  [interp eval $i {mod2::test2::try2}]
	# Try to load the packages and run a command from each one.
	set code0 [catch {interp eval $i {package require test0}} msg0]
	set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
	set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
	set out0  [interp eval $i {test0::try0}]
	set out1  [interp eval $i {mod1::test1::try1}]
	set out2  [interp eval $i {mod2::test2::try2}]

    list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
	list [lsort [list $path0 $path1 $path2]] -- $modsA --  [lsort [list $path3 $path4 $path5]] -- $modsB --  $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB --  $out0 $out1 $out2
            [lsort [list $path3 $path4 $path5]] -- $modsB -- \
            $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
            $out0 $out1 $out2
} -cleanup {
    tcl::tm::path remove [file join $ZipMountPoint auto0 modules]
    foreach path [lreverse $oldTm] {
        tcl::tm::path add $path
    }
    safe::interpDelete $i
} -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
    } -cleanup {
	tcl::tm::path remove [file join $ZipMountPoint auto0 modules]
	foreach path [lreverse $oldTm] {
	    tcl::tm::path add $path
	}
	safe::interpDelete $i
	if {$SyncExists} {
	    safe::setSyncMode $SyncVal_TMP
	}
    } -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} -- {{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} -- 0 0.5 0 1.0 0 2.0 -- {TCLLIB ZIPDIR/auto0/modules ZIPDIR/auto0/modules/mod1 ZIPDIR/auto0/modules/mod2} -- {TCLLIB ZIPDIR/auto0/auto1 ZIPDIR/auto0/auto2 ZIPDIR/auto0/modules ZIPDIR/auto0/modules/mod1 ZIPDIR/auto0/modules/mod2} -- res0 res1 res2}
        {{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
        0 0.5 0 1.0 0 2.0 --\
        {TCLLIB ZIPDIR/auto0/modules ZIPDIR/auto0/modules/mod1\
         ZIPDIR/auto0/modules/mod2} --\
        {TCLLIB ZIPDIR/auto0/auto1 ZIPDIR/auto0/auto2 ZIPDIR/auto0/modules\
         ZIPDIR/auto0/modules/mod1 ZIPDIR/auto0/modules/mod2} --\
        res0 res1 res2}
# See comments on lsort after test safe-zipfs-9.20.
test safe-zipfs-9.23 {interpConfigure change the access path; check module loading; stale data case 3; zipfs} -setup {
    set oldTm [tcl::tm::path list]
    foreach path $oldTm {
        tcl::tm::path remove $path
    }
    tcl::tm::path add [file join $ZipMountPoint auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]
    # See comments on lsort after test safe-zipfs-9.20.
    test safe-zipfs-9.24 {interpConfigure change the access path; check module loading, with conventional AutoPathSync; stale data case 2 (worst case); zipfs} -setup {
	set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
	if {$SyncExists} {
	    set SyncVal_TMP [safe::setSyncMode]
	    safe::setSyncMode 1
	}
	set oldTm [tcl::tm::path list]
	foreach path $oldTm {
	    tcl::tm::path remove $path
	}
	tcl::tm::path add [file join $ZipMountPoint auto0 modules]
    } -body {
	set i [safe::interpCreate -accessPath [list $tcl_library]]

    # Inspect.
    set confA [safe::interpConfigure $i]
    set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
    set modsA [interp eval $i {tcl::tm::path list}]
    set path0 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules]]
    set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod2]]
	# Inspect.
	set confA [safe::interpConfigure $i]
	set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
	set modsA [interp eval $i {tcl::tm::path list}]
	set path0 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules]]
	set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod1]]
	set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod2]]

    # Force the interpreter to acquire pkg data which will soon become stale.
    catch {interp eval $i {package require NOEXIST}}
    catch {interp eval $i {package require mod1::NOEXIST}}
    catch {interp eval $i {package require mod2::NOEXIST}}
	# Force the interpreter to acquire pkg data which will soon become stale.
	catch {interp eval $i {package require NOEXIST}}
	catch {interp eval $i {package require mod1::NOEXIST}}
	catch {interp eval $i {package require mod2::NOEXIST}}

    # Add to access path.
    # This injects more tokens, pushing modules to higher token numbers.
    safe::interpConfigure $i -accessPath [list $tcl_library \
	# Add to access path.
	# This injects more tokens, pushing modules to higher token numbers.
	safe::interpConfigure $i -accessPath [list $tcl_library  [file join $ZipMountPoint auto0 auto1]  [file join $ZipMountPoint auto0 auto2]]
                                           [file join $ZipMountPoint auto0 auto1] \
                                           [file join $ZipMountPoint auto0 auto2]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
    set modsB [interp eval $i {tcl::tm::path list}]
    set path3 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules]]
    set path4 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod1]]
    set path5 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod2]]

    # Refresh stale pkg data.
    catch {interp eval $i {package require NOEXIST}}
    catch {interp eval $i {package require mod1::NOEXIST}}
    catch {interp eval $i {package require mod2::NOEXIST}}

    # Try to load the packages and run a command from each one.
    set code0 [catch {interp eval $i {package require test0}} msg0]
    set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
    set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
    set out0  [interp eval $i {test0::try0}]
    set out1  [interp eval $i {mod1::test1::try1}]
    set out2  [interp eval $i {mod2::test2::try2}]

    list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
            [lsort [list $path3 $path4 $path5]] -- $modsB -- \
            $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
            $out0 $out1 $out2
} -cleanup {
    tcl::tm::path remove [file join $ZipMountPoint auto0 modules]
    foreach path [lreverse $oldTm] {
        tcl::tm::path add $path
    }
    safe::interpDelete $i
} -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
        {{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
        0 0.5 0 1.0 0 2.0 --\
        {TCLLIB ZIPDIR/auto0/modules ZIPDIR/auto0/modules/mod1\
         ZIPDIR/auto0/modules/mod2} --\
        {TCLLIB ZIPDIR/auto0/auto1 ZIPDIR/auto0/auto2 ZIPDIR/auto0/modules\
         ZIPDIR/auto0/modules/mod1 ZIPDIR/auto0/modules/mod2} --\
        res0 res1 res2}
# See comments on lsort after test safe-zipfs-9.20.
test safe-zipfs-9.24 {interpConfigure change the access path; check module loading; stale data case 2 (worst case); zipfs} -setup {
    set oldTm [tcl::tm::path list]
    foreach path $oldTm {
        tcl::tm::path remove $path
    }
    tcl::tm::path add [file join $ZipMountPoint auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]

    # Inspect.
    set confA [safe::interpConfigure $i]
    set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
    set modsA [interp eval $i {tcl::tm::path list}]
    set path0 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules]]
    set path1 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod2]]

    # Force the interpreter to acquire pkg data which will soon become stale.
    catch {interp eval $i {package require NOEXIST}}
    catch {interp eval $i {package require mod1::NOEXIST}}
    catch {interp eval $i {package require mod2::NOEXIST}}

    # Add to access path.
    # This injects more tokens, pushing modules to higher token numbers.
    safe::interpConfigure $i -accessPath [list $tcl_library \
                                           [file join $ZipMountPoint auto0 auto1] \
                                           [file join $ZipMountPoint auto0 auto2]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
    set modsB [interp eval $i {tcl::tm::path list}]
    set path3 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules]]
    set path4 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod1]]
    set path5 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod2]]
	# Inspect.
	set confB [safe::interpConfigure $i]
	set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
	set modsB [interp eval $i {tcl::tm::path list}]
	set path3 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules]]
	set path4 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod1]]
	set path5 [::safe::interpFindInAccessPath $i [file join $ZipMountPoint auto0 modules mod2]]

    # Try to load the packages and run a command from each one.
    set code0 [catch {interp eval $i {package require test0}} msg0]
    set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
    set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
    set out0  [interp eval $i {test0::try0}]
    set out1  [interp eval $i {mod1::test1::try1}]
    set out2  [interp eval $i {mod2::test2::try2}]
	# Try to load the packages and run a command from each one.
	set code0 [catch {interp eval $i {package require test0}} msg0]
	set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
	set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
	set out0  [interp eval $i {test0::try0}]
	set out1  [interp eval $i {mod1::test1::try1}]
	set out2  [interp eval $i {mod2::test2::try2}]

    list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
	list [lsort [list $path0 $path1 $path2]] -- $modsA --  [lsort [list $path3 $path4 $path5]] -- $modsB --  $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB --  $out0 $out1 $out2
            [lsort [list $path3 $path4 $path5]] -- $modsB -- \
            $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
            $out0 $out1 $out2
} -cleanup {
    tcl::tm::path remove [file join $ZipMountPoint auto0 modules]
    foreach path [lreverse $oldTm] {
        tcl::tm::path add $path
    }
    safe::interpDelete $i
} -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
        {{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
        0 0.5 0 1.0 0 2.0 --\
        {TCLLIB ZIPDIR/auto0/modules ZIPDIR/auto0/modules/mod1\
         ZIPDIR/auto0/modules/mod2} --\
        {TCLLIB ZIPDIR/auto0/auto1 ZIPDIR/auto0/auto2 ZIPDIR/auto0/modules\
         ZIPDIR/auto0/modules/mod1 ZIPDIR/auto0/modules/mod2} --\
        res0 res1 res2}
# See comments on lsort after test safe-zipfs-9.20.
    } -cleanup {
	tcl::tm::path remove [file join $ZipMountPoint auto0 modules]
	foreach path [lreverse $oldTm] {
	    tcl::tm::path add $path
	}
	safe::interpDelete $i
	if {$SyncExists} {
	    safe::setSyncMode $SyncVal_TMP
	}
    } -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} -- {{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} -- 0 0.5 0 1.0 0 2.0 -- {TCLLIB ZIPDIR/auto0/modules ZIPDIR/auto0/modules/mod1 ZIPDIR/auto0/modules/mod2} -- {TCLLIB ZIPDIR/auto0/auto1 ZIPDIR/auto0/auto2 ZIPDIR/auto0/modules ZIPDIR/auto0/modules/mod1 ZIPDIR/auto0/modules/mod2} -- res0 res1 res2}
    # See comments on lsort after test safe-zipfs-9.20.

    test safe-zipfs-18.1 {cf. safe-zipfs-7.1 - tests that everything works at high level without conventional AutoPathSync; zipfs} -constraints AutoSyncDefined -setup {
	set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
	if {$SyncExists} {
	    set SyncVal_TMP [safe::setSyncMode]
	    safe::setSyncMode 0
	} else {
	    error {This test is meaningful only if the command ::safe::setSyncMode is defined}
	}
	# Without AutoPathSync, we need a more complete auto_path,
	# because the child will use the same value.
	set lib1        [info library]
	set lib2        [file join $ZipMountPoint auto0]
	set ::auto_TMP  $::auto_path
	set ::auto_path [list $lib1 $lib2]

	set i [safe::interpCreate]
	set ::auto_path $::auto_TMP
    } -body {
	# no error shall occur:
	# (because the default access_path shall include 1st level sub dirs so
	#  package require in a child works like in the parent)
	set v [interp eval $i {package require SafeTestPackage1}]
	# no error shall occur:
	interp eval $i HeresPackage1
	set v
    } -cleanup {
	safe::interpDelete $i
	if {$SyncExists} {
	    safe::setSyncMode $SyncVal_TMP
	}
    } -match glob -result 1.2.3
    test safe-zipfs-18.2 {cf. safe-zipfs-7.2 - tests specific path and interpFind/AddToAccessPath without conventional AutoPathSync; zipfs} -constraints AutoSyncDefined -setup {
	set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
	if {$SyncExists} {
	    set SyncVal_TMP [safe::setSyncMode]
	    safe::setSyncMode 0
	} else {
	    error {This test is meaningful only if the command ::safe::setSyncMode is defined}
	}
    } -body {
	set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]
	set auto1 [interp eval $i {set ::auto_path}]
	interp eval $i {set ::auto_path [list {$p(:0:)}]}
	# should not add anything (p0)
	set token1 [safe::interpAddToAccessPath $i [info library]]
	# should add as p* (not p1 if parent has a module path)
	set token2 [safe::interpAddToAccessPath $i "/dummy/unixlike/test/path"]
	# should add as p* (not p2 if parent has a module path)
	set token3 [safe::interpAddToAccessPath $i [file join $ZipMountPoint auto0]]
	# an error shall occur (SafeTestPackage1 is not anymore in the secure 0-level
	# provided deep path)
	list $auto1 $token1 $token2 $token3  [catch {interp eval $i {package require SafeTestPackage1}} msg] $msg  [safe::interpConfigure $i] [safe::interpDelete $i]
    } -cleanup {
	if {$SyncExists} {
	    safe::setSyncMode $SyncVal_TMP
	}
    } -match glob -result "{} {\$p(:0:)} {\$p(:*:)} {\$p(:*:)} 1 {can't find package SafeTestPackage1} {-accessPath {[list $tcl_library  */dummy/unixlike/test/path  $ZipMountPoint/auto0]} -statics 0 -nested 1 -deleteHook {} -autoPath {}} {}"
    test safe-zipfs-18.4 {cf. safe-zipfs-7.4 - tests specific path and positive search and auto_path without conventional AutoPathSync; zipfs} -constraints AutoSyncDefined -setup {
	set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
	if {$SyncExists} {
	    set SyncVal_TMP [safe::setSyncMode]
	    safe::setSyncMode 0
	} else {
	    error {This test is meaningful only if the command ::safe::setSyncMode is defined}
	}
    } -body {
	set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]

	# should not have been set by Safe Base:
	set auto1 [interp eval $i {set ::auto_path}]

	# This will differ from the value -autoPath {}
	interp eval $i {set ::auto_path [list {$p(:0:)}]}

	# should not add anything (p0)
	set token1 [safe::interpAddToAccessPath $i [info library]]

	# should add as p* (not p1 if parent has a module path)
	set token2 [safe::interpAddToAccessPath $i [file join $ZipMountPoint auto0]]

	# should add as p* (not p2 if parent has a module path)
	set token3 [safe::interpAddToAccessPath $i [file join $ZipMountPoint auto0 auto1]]

	# should not have been changed by Safe Base:
	set auto2 [interp eval $i {set ::auto_path}]

	# This will differ from the value -autoPath {}
	set auto3 [interp eval $i [list set ::auto_path [list {$p(:0:)} $token2]]]

	# This time, unlike test safe-zipfs-18.2 and the try above, SafeTestPackage1 should be found:
	list $auto1 $auto2 $token1 $token2 $token3  [catch {interp eval $i {package require SafeTestPackage1}} msg] $msg  [safe::interpConfigure $i] [safe::interpDelete $i]
    } -cleanup {
	if {$SyncExists} {
	    safe::setSyncMode $SyncVal_TMP
	}
    } -match glob -result "{} {{\$p(:0:)}} {\$p(:0:)} {\$p(:*:)} {\$p(:*:)} 0 1.2.3 {-accessPath {[list $tcl_library *$ZipMountPoint/auto0 $ZipMountPoint/auto0/auto1]} -statics 0 -nested 1 -deleteHook {} -autoPath {}} {}"

# cleanup
set ::auto_path $SaveAutoPath
zipfs unmount ${ZipMountPoint}
unset SaveAutoPath TestsDir ZipMountPoint PathMapp
rename mapList {}
rename mapAndSortList {}
::tcltest::cleanupTests
return
    # cleanup
    set ::auto_path $SaveAutoPath
    zipfs unmount ${ZipMountPoint}
    unset SaveAutoPath TestsDir ZipMountPoint PathMapp
    rename mapList {}
    rename mapAndSortList {}
    ::tcltest::cleanupTests
    return
} [namespace current]]

# Local Variables:
# mode: tcl
# End:

Changes to tests/safe.test.

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
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
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
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










-
+





-
-
+
+








+
+










+
+
+
+
+



-
+






-
+




-
-
+
+



-
+

-
+
+

+
+




-
+
+
+
+
+
+
+
+
+

+
+
+
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+
+







# safe.test --
#
# This file contains a collection of tests for safe Tcl, packages loading, and
# using safe interpreters. Sourcing this file into tcl runs the tests and
# generates output for errors. No output means no errors were found.
#
# The defunct package http 1.0 was convenient for testing package loading.
# - Tests that used http are replaced here with tests that use example packages
#   provided in subdirectory auto0 of the tests directory, which are independent
#   of any changes made to the packages provided with Tcl itself.
#   - These are tests 7.1 7.2 7.4 9.11 9.13
#   - These are tests 7.1 7.2 7.4 9.11 9.13 17.1 17.2 17.4
#   - Tests 5.* test the example packages themselves before they
#     are used to test Safe Base interpreters.
# - Alternative tests using stock packages of Tcl 8.7 are in file
#   safe-stock.test.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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]]

foreach i [interp children] {
    interp delete $i
}

set SaveAutoPath $::auto_path
set ::auto_path [info library]
set TestsDir [file normalize [file dirname [info script]]]
set PathMapp [list $tcl_library TCLLIB $TestsDir TESTSDIR]

proc getAutoPath {child} {
    set ap1 [lrange [lindex [safe::interpConfigure $child -autoPath] 1] 0 end]
    set ap2 [::safe::DetokPath $child [interp eval $child set ::auto_path]]
    list $ap1 -- $ap2
}
proc mapList {map listIn} {
    set listOut {}
    foreach element $listIn {
        lappend listOut [string map $map $element]
	lappend listOut [string map $map $element]
    }
    return $listOut
}
proc mapAndSortList {map listIn} {
    set listOut {}
    foreach element $listIn {
        lappend listOut [string map $map $element]
	lappend listOut [string map $map $element]
    }
    lsort $listOut
}

# Force actual loading of the safe package because we use un-exported (and
# thus un-autoindexed) APIs in this test result arguments:
# Force actual loading of the safe package because we use unexported (and
# thus unautoindexed) APIs in this test result arguments:
catch {safe::interpConfigure}

# testing that nested and statics do what is advertised (we use a static
# package - Tcltest - but it might be absent if we're in standard tclsh)
# package - tcl::test - but it might be absent if we're in standard tclsh)

testConstraint TcltestPackage [expr {![catch {package require Tcltest}]}]
testConstraint tcl::test [expr {![catch {package require tcl::test}]}]
testConstraint AutoSyncDefined 1

###  1. Basic help/error messages.

test safe-1.1 {safe::interpConfigure syntax} -returnCodes error -body {
    safe::interpConfigure
} -result {no value given for parameter "child" (use -help for full usage) :
    child name () name of the child}
test safe-1.2 {safe::interpCreate syntax} -returnCodes error -body {
test safe-1.2 {safe::interpCreate syntax, Sync Mode on} -returnCodes error -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    } else {
	set SyncVal_TMP 1
    }
} -body {
    safe::interpCreate -help
} -cleanup {
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {Usage information:
    Var/FlagName  Type     Value   Help
    ------------  ----     -----   ----
    (-help                         gives this help)
    ?child?       name     ()      name of the child (optional)
    -accessPath   list     ()      access path for the child
    -noStatics    boolflag (false) prevent loading of statically linked pkgs
    -statics      boolean  (true)  loading of statically linked pkgs
    -nestedLoadOk boolflag (false) allow nested loading
    -nested       boolean  (false) nested loading
    -deleteHook   script   ()      delete hook}
test safe-1.2.1 {safe::interpCreate syntax, Sync Mode off} -returnCodes error -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    safe::interpCreate -help
} -cleanup {
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {Usage information:
    Var/FlagName  Type     Value   Help
    ------------  ----     -----   ----
    (-help                         gives this help)
    ?child?       name     ()      name of the child (optional)
    -accessPath   list     ()      access path for the child
    -noStatics    boolflag (false) prevent loading of statically linked pkgs
    -statics      boolean  (true)  loading of statically linked pkgs
    -nestedLoadOk boolflag (false) allow nested loading
    -nested       boolean  (false) nested loading
    -deleteHook   script   ()      delete hook
    -autoPath     list     ()      ::auto_path for the child}
test safe-1.3 {safe::interpInit syntax} -returnCodes error -body {
    safe::interpInit -noStatics
} -result {bad value "-noStatics" for parameter
    child name () name of the child}

###  2. Aliases in a new "interp create" interpreter.

test safe-2.1 {creating interpreters, should have no aliases} emptyTest {
    # Disabled this test.  It tests nothing sensible.  [Bug 999612]
    # interp aliases
} ""
test safe-2.2 {creating interpreters, should have no aliases} -setup {
    catch {safe::interpDelete a}
99
100
101
102
103
104
105



106
107
108
109
110
111
112
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165







+
+
+







} -body {
    interp create a -safe
    lsort [a aliases]
} -cleanup {
    interp delete a
} -result {clock}

###  3. Simple use of interpCreate, interpInit.
###     Aliases in a new "interpCreate/interpInit" interpreter.

test safe-3.1 {calling safe::interpInit is safe} -setup {
    catch {safe::interpDelete a}
    interp create a -safe
} -body {
    safe::interpInit a
    interp eval a exec ls
} -returnCodes error -cleanup {
133
134
135
136
137
138
139


140
141
142
143
144
145
146
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201







+
+







} -body {
    safe::interpCreate a
    interp eval a {source [file join $tcl_library init.tcl]}
} -cleanup {
    safe::interpDelete a
} -result {}

###  4. Testing safe::interpDelete, double interpCreate.

test safe-4.1 {safe::interpDelete} -setup {
    catch {safe::interpDelete a}
} -body {
    interp create a
    safe::interpDelete a
    # This (ab)use of safe::interpDelete to delete non-Safe-Base interpreters
    # is regrettable and should be removed at the next major revision.
165
166
167
168
169
170
171

172
173
174




175
176
177
178
179
180
181
220
221
222
223
224
225
226
227



228
229
230
231
232
233
234
235
236
237
238







+
-
-
-
+
+
+
+







test safe-4.6 {safe::interpDelete, indirectly} -setup {
    catch {safe::interpDelete a}
} -body {
    safe::interpCreate a
    a eval exit
} -result ""

###  5. Test the example files before using them to test safe interpreters.
# The old test "safe-5.1" has been moved to "safe-stock-9.8".
# A replacement test using example files is "safe-9.8".
# Tests 5.* test the example files before using them to test safe interpreters.
###     The old test "safe-5.1" has been moved to "safe-stock-9.8".
###     A replacement test using example files is "safe-9.8".

unset -nocomplain path

test safe-5.1 {example tclIndex commands, test in parent interpreter} -setup {
    set tmpAutoPath $::auto_path
    lappend ::auto_path [file join $TestsDir auto0 auto1] [file join $TestsDir auto0 auto2]
} -body {
    # Try to load the commands.
    set code3 [catch report1 msg3]
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
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







-
+

















-
+














-
+







    catch {package forget SafeTestPackage2}
    catch {rename HeresPackage1 {}}
    catch {rename HeresPackage2 {}}
} -match glob -result {0 1.2.3 0 2.3.4 0 OK1 0 OK2}
test safe-5.4 {example pkgIndex.tcl packages, test in parent interpreter, main directories} -setup {
    set tmpAutoPath $::auto_path
    lappend ::auto_path [file join $TestsDir auto0 auto1] \
                        [file join $TestsDir auto0 auto2]
			[file join $TestsDir auto0 auto2]
} -body {
    # Try to load the packages and run a command from each one.
    set code3 [catch {package require SafeTestPackage1} msg3]
    set code4 [catch {package require SafeTestPackage2} msg4]
    set code5 [catch HeresPackage1 msg5]
    set code6 [catch HeresPackage2 msg6]
    list $code3 $msg3 $code4 $msg4 $code5 $msg5 $code6 $msg6
} -cleanup {
    set ::auto_path $tmpAutoPath
    catch {package forget SafeTestPackage1}
    catch {package forget SafeTestPackage2}
    catch {rename HeresPackage1 {}}
    catch {rename HeresPackage2 {}}
} -match glob -result {0 1.2.3 0 2.3.4 0 OK1 0 OK2}
test safe-5.5 {example modules packages, test in parent interpreter, replace path} -setup {
    set oldTm [tcl::tm::path list]
    foreach path $oldTm {
        tcl::tm::path remove $path
	tcl::tm::path remove $path
    }
    tcl::tm::path add [file join $TestsDir auto0 modules]
} -body {
    # Try to load the modules and run a command from each one.
    set code0 [catch {package require test0} msg0]
    set code1 [catch {package require mod1::test1} msg1]
    set code2 [catch {package require mod2::test2} msg2]
    set out0  [test0::try0]
    set out1  [mod1::test1::try1]
    set out2  [mod2::test2::try2]
    list $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $out0 $out1 $out2
} -cleanup {
    tcl::tm::path remove [file join $TestsDir auto0 modules]
    foreach path [lreverse $oldTm] {
        tcl::tm::path add $path
	tcl::tm::path add $path
    }
    catch {package forget test0}
    catch {package forget mod1::test1}
    catch {package forget mod2::test2}
    catch {namespace delete ::test0}
    catch {namespace delete ::mod1}
} -match glob -result {0 0.5 0 1.0 0 2.0 -- res0 res1 res2}
278
279
280
281
282
283
284
285


286
287
288
289
290
291
292
335
336
337
338
339
340
341

342
343
344
345
346
347
348
349
350







-
+
+







    catch {package forget test0}
    catch {package forget mod1::test1}
    catch {package forget mod2::test2}
    catch {namespace delete ::test0}
    catch {namespace delete ::mod1}
} -match glob -result {0 0.5 0 1.0 0 2.0 -- res0 res1 res2}

# test safe interps 'information leak'
###  6. Test safe interps 'information leak'.

proc SafeEval {script} {
    # Helper procedure that ensures the safe interp is cleaned up even if
    # there is a failure in the script.
    set SafeInterp [interp create -safe]
    catch {$SafeInterp eval $script} msg opts
    interp delete $SafeInterp
    return -options $opts $msg
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

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
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

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
467
468
469
470
471
472
473
474
475
476
477
478
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







-
-
-
+
+
+
+
+
+
+
+
+
+














+
+
+

-
+
+
+
+
+
+
+
+










-
+
-




+
+
+

-
-
+
+



-
+



-
+




-
+





-
+



-
+




-
-
-
+
+
+

-
+
+
+
+
+
+
+
+















+
+
+

-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    lsort $r
} {byteOrder engine pathSeparator platform pointerSize wordSize}

rename SafeEval {}
# More test should be added to check that hostname, nameofexecutable, aren't
# leaking infos, but they still do...

# high level general test
# Use example packages not http1.0 etc
test safe-7.1 {tests that everything works at high level} -setup {
###  7. Test the use of ::auto_path for loading commands (via tclIndex files)
###     and non-module packages (via pkgIndex.tcl files).
###     Corresponding tests with Sync Mode off are 17.*

test safe-7.1 {positive non-module package require, Sync Mode on} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }
    set tmpAutoPath $::auto_path
    lappend ::auto_path [file join $TestsDir auto0]
    set i [safe::interpCreate]
    set ::auto_path $tmpAutoPath
} -body {
    # no error shall occur:
    # (because the default access_path shall include 1st level sub dirs so
    #  package require in a child works like in the parent)
    set v [interp eval $i {package require SafeTestPackage1}]
    # no error shall occur:
    interp eval $i {HeresPackage1}
    set v
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result 1.2.3
test safe-7.2 {tests specific path and interpFind/AddToAccessPath} -setup {
test safe-7.2 {negative non-module package require with specific path and interpAddToAccessPath, Sync Mode on} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    } else {
	set SyncVal_TMP 1
    }
} -body {
    set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]
    # should not add anything (p0)
    set token1 [safe::interpAddToAccessPath $i [info library]]
    # should add as p* (not p1 if parent has a module path)
    set token2 [safe::interpAddToAccessPath $i "/dummy/unixlike/test/path"]
    # should add as p* (not p2 if parent has a module path)
    set token3 [safe::interpAddToAccessPath $i [file join $TestsDir auto0]]
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    # an error shall occur (SafeTestPackage1 is not anymore in the secure 0-level
    # an error shall occur (SafeTestPackage1 is not in auto0 but a subdirectory)
    # provided deep path)
    list $token1 $token2 $token3 -- \
	    [catch {interp eval $i {package require SafeTestPackage1}} msg] $msg -- \
	    $mappA -- [safe::interpDelete $i]
} -cleanup {
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:0:)} {$p(:*:)} {$p(:*:)} --\
        1 {can't find package SafeTestPackage1} --\
        {TCLLIB */dummy/unixlike/test/path TESTSDIR/auto0} -- {}}
	1 {can't find package SafeTestPackage1} --\
	{TCLLIB */dummy/unixlike/test/path TESTSDIR/auto0} -- {}}
test safe-7.3 {check that safe subinterpreters work} {
    set g [interp children]
    if {$g ne {}} {
        append g { -- residue of an earlier test}
	append g { -- residue of an earlier test}
    }
    set h [info vars ::safe::S*]
    if {$h ne {}} {
        append h { -- residue of an earlier test}
	append h { -- residue of an earlier test}
    }
    set i [safe::interpCreate]
    set j [safe::interpCreate [list $i x]]
    list $g $h [interp eval $j {join {o k} ""}] [safe::interpDelete $i] \
            [interp exists $j] [info vars ::safe::S*]
	    [interp exists $j] [info vars ::safe::S*]
} {{} {} ok {} 0 {}}
test safe-7.3.1 {check that safe subinterpreters work with namespace names} -setup {
} -body {
    set g [interp children]
    if {$g ne {}} {
        append g { -- residue of an earlier test}
	append g { -- residue of an earlier test}
    }
    set h [info vars ::safe::S*]
    if {$h ne {}} {
        append h { -- residue of an earlier test}
	append h { -- residue of an earlier test}
    }
    set i [safe::interpCreate foo::bar]
    set j [safe::interpCreate [list $i hello::world]]
    list $g $h [interp eval $j {join {o k} ""}] \
            [foo::bar eval {hello::world eval {join {o k} ""}}] \
            [safe::interpDelete $i] \
            [interp exists $j] [info vars ::safe::S*]
	    [foo::bar eval {hello::world eval {join {o k} ""}}] \
	    [safe::interpDelete $i] \
	    [interp exists $j] [info vars ::safe::S*]
} -match glob -result {{} {} ok ok {} 0 {}}
test safe-7.4 {tests specific path and positive search} -setup {
test safe-7.4 {positive non-module package require with specific path and interpAddToAccessPath, Sync Mode on} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    } else {
	set SyncVal_TMP 1
    }
} -body {
    set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]
    # should not add anything (p0)
    set token1 [safe::interpAddToAccessPath $i [info library]]
    # should add as p* (not p1 if parent has a module path)
    set token2 [safe::interpAddToAccessPath $i [file join $TestsDir auto0 auto1]]
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    # this time, unlike test safe-7.2, SafeTestPackage1 should be found
    list $token1 $token2 -- \
	    [catch {interp eval $i {package require SafeTestPackage1}} msg] $msg -- \
	    $mappA -- [safe::interpDelete $i]
    # Note that the glob match elides directories (those from the module path)
    # other than the first and last in the access path.
} -cleanup {
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:0:)} {$p(:*:)} -- 0 1.2.3 --\
        {TCLLIB * TESTSDIR/auto0/auto1} -- {}}

# test source control on file name
	{TCLLIB * TESTSDIR/auto0/auto1} -- {}}
test safe-7.5 {positive and negative module package require, including ancestor directory issue, Sync Mode on} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }
    tcl::tm::path add [file join $TestsDir auto0 modules]
    set i [safe::interpCreate]
    tcl::tm::path remove [file join $TestsDir auto0 modules]
    interp eval $i {
	package forget mod1::test1
	catch {namespace delete ::mod1}
    }
} -body {
    # Should raise an error (module ancestor directory issue)
    set code1 [catch {interp eval $i {package require test1}} msg1]
    # Should not raise an error
    set code2 [catch {interp eval $i {package require mod1::test1}} msg2]
    return [list $code1 $msg1 $code2]
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {1 {can't find package test1} 0}

###  8. Test source control on file name.

test safe-8.1 {safe source control on file} -setup {
    set i "a"
    catch {safe::interpDelete $i}
} -body {
    safe::interpCreate $i
    $i eval {source}
} -returnCodes error -cleanup {
541
542
543
544
545
546
547



548
549
550
551
552
553
554
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670







+
+
+







    }} $token/[file tail $returnScript]]
} -cleanup {
    catch {safe::interpDelete $i}
    removeFile $returnScript
    unset i
} -result ok

###  9. Assorted options, including changes to option values.
###     If Sync Mode is on, a corresponding test with Sync Mode off is 19.*

test safe-9.1 {safe interps' deleteHook} -setup {
    set i "a"
    catch {safe::interpDelete $i}
    set res {}
} -body {
    proc testDelHook {args} {
	global res
602
603
604
605
606
607
608
609
610


611
612
613
614
615
616
617
618
619
620
621
622
623
624




625
626
627
628
629
630
631
718
719
720
721
722
723
724


725
726
727
728
729
730
731
732
733
734
735
736




737
738
739
740
741
742
743
744
745
746
747







-
-
+
+










-
-
-
-
+
+
+
+







test safe-9.6 {interpConfigure widget like behaviour} -body {
   # this test shall work, don't try to "fix it" unless you *really* know what
   # you are doing (ie you are me :p) -- dl
   list [set i [safe::interpCreate \
		    -noStatics \
		    -nestedLoadOk \
		    -deleteHook {foo bar}]
         safe::interpConfigure $i -accessPath /foo/bar
         safe::interpConfigure $i]\
	 safe::interpConfigure $i -accessPath /foo/bar
	 safe::interpConfigure $i]\
	[safe::interpConfigure $i -aCCess]\
	[safe::interpConfigure $i -nested]\
	[safe::interpConfigure $i -statics]\
	[safe::interpConfigure $i -DEL]\
	[safe::interpConfigure $i -accessPath /blah -statics 1
	 safe::interpConfigure $i]\
	[safe::interpConfigure $i -deleteHook toto -nosta -nested 0
	 safe::interpConfigure $i]
} -cleanup {
    safe::interpDelete $i
} -match glob -result {{-accessPath * -statics 0 -nested 1 -deleteHook {foo bar}}\
        {-accessPath *} {-nested 1} {-statics 0} {-deleteHook {foo bar}}\
        {-accessPath * -statics 1 -nested 1 -deleteHook {foo bar}}\
        {-accessPath * -statics 0 -nested 0 -deleteHook toto}}
} -match glob -result {{-accessPath * -statics 0 -nested 1 -deleteHook {foo bar} -autoPath *}\
	{-accessPath *} {-nested 1} {-statics 0} {-deleteHook {foo bar}}\
	{-accessPath * -statics 1 -nested 1 -deleteHook {foo bar} -autoPath *}\
	{-accessPath * -statics 0 -nested 0 -deleteHook toto -autoPath *}}
test safe-9.7 {interpConfigure widget like behaviour (demystified)} -body {
   # this test shall work, believed equivalent to 9.6
    set i [safe::interpCreate \
	    -noStatics \
	    -nestedLoadOk \
	    -deleteHook {foo bar}]
	   safe::interpConfigure $i -accessPath /foo/bar
639
640
641
642
643
644
645
646
647
648
649
650










651
652
653
654


655
656
657
658
659
660
661
662
663
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
707
708
709








710
711
712
713


714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729


730
731
732
733
734
735
736
737
738
739
740
741
742



743
744
745
746
747









748
749
750
751
752
753



754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770



771
772
773
774
775
776
777
778
779
780
781
782
783
784

785
786



787
788
789
790
791









792
793
794
795


796
797
798
799
800
801
802
803
804
805
806
807
808


809
810
811
812
813
814
815
816
817
818
819
820
821
822
823


824
825



826
827
828
829
830
831










832
833
834
835


836
837
838
839
840
841
842
755
756
757
758
759
760
761





762
763
764
765
766
767
768
769
770
771
772
773


774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792


793
794
795
796
797
798
799
800
801


802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819


820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838



839
840
841
842
843
844
845
846
847
848


849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864


865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912



913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928

929
930
931
932
933
934
935




936
937
938
939
940
941
942
943
944
945
946


947
948
949
950
951
952
953
954
955
956
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







-
-
-
-
-
+
+
+
+
+
+
+
+
+
+


-
-
+
+













+
+
+

-
-
+
+
+
+
+
+
+


-
-
+
+
















-
-
+
+













+
+
+

-
-
-
+
+
+
+
+
+
+
+


-
-
+
+














-
-
+
+













+
+
+

-
-
-
-
+
+
+
+
+
+
+
+
+



-
-
-
+
+
+














-
-
-
+
+
+













-
+


+
+
+

-
-
-
-
+
+
+
+
+
+
+
+
+


-
-
+
+











-
-
+
+













-
-
+
+


+
+
+

-
-
-
-
-
+
+
+
+
+
+
+
+
+
+


-
-
+
+







	   safe::interpConfigure $i -deleteHook toto -nosta -nested 0
    set g [safe::interpConfigure $i]

    list $a $b $c $d $e $f $g
} -cleanup {
    safe::interpDelete $i
    unset -nocomplain a b c d e f g i
} -match glob -result {{-accessPath * -statics 0 -nested 1 -deleteHook {foo bar}}\
        {-accessPath *} {-nested 1} {-statics 0} {-deleteHook {foo bar}}\
        {-accessPath * -statics 1 -nested 1 -deleteHook {foo bar}}\
        {-accessPath * -statics 0 -nested 0 -deleteHook toto}}
test safe-9.8 {test autoloading commands indexed in tclIndex files} -setup {
} -match glob -result {{-accessPath * -statics 0 -nested 1 -deleteHook {foo bar} -autoPath *}\
	{-accessPath *} {-nested 1} {-statics 0} {-deleteHook {foo bar}}\
	{-accessPath * -statics 1 -nested 1 -deleteHook {foo bar} -autoPath *}\
	{-accessPath * -statics 0 -nested 0 -deleteHook toto -autoPath *}}
test safe-9.8 {autoloading commands indexed in tclIndex files, Sync Mode on} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library \
                                            [file join $TestsDir auto0 auto1] \
                                            [file join $TestsDir auto0 auto2]]]
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]

    # Load and run the commands.
    set code1 [catch {interp eval $i {report1}} msg1]
    set code2 [catch {interp eval $i {report2}} msg2]

    list $path1 $path2 -- $code1 $msg1 $code2 $msg2 -- $mappA
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:1:)} {$p(:2:)} -- 0 ok1 0 ok2 --\
        {TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*}}
test safe-9.9 {interpConfigure change the access path; tclIndex commands unaffected by token rearrangement (dummy test of doreset)} -setup {
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*}}
test safe-9.9 {interpConfigure change the access path; tclIndex commands unaffected by token rearrangement (dummy test of doreset), Sync Mode on} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library \
                                            [file join $TestsDir auto0 auto1] \
                                            [file join $TestsDir auto0 auto2]]]
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]

    # Load auto_load data.
    interp eval $i {catch nonExistentCommand}

    # Load and run the commands.
    # This guarantees the test will pass even if the tokens are swapped.
    set code1 [catch {interp eval $i {report1}} msg1]
    set code2 [catch {interp eval $i {report2}} msg2]

    # Rearrange access path.  Swap tokens {$p(:1:)} and {$p(:2:)}.
    safe::interpConfigure $i -accessPath [list $tcl_library \
                                           [file join $TestsDir auto0 auto2] \
                                           [file join $TestsDir auto0 auto1]]
					   [file join $TestsDir auto0 auto2] \
					   [file join $TestsDir auto0 auto1]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]

    # Run the commands.
    set code3 [catch {interp eval $i {report1}} msg3]
    set code4 [catch {interp eval $i {report2}} msg4]

    list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- $mappA -- $mappB
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:1:)} {$p(:2:)} -- {$p(:2:)} {$p(:1:)} -- 0 ok1 0 ok2 --\
        {TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
        {TCLLIB TESTSDIR/auto0/auto2 TESTSDIR/auto0/auto1*}}
test safe-9.10 {interpConfigure change the access path; tclIndex commands unaffected by token rearrangement (actual test of doreset)} -setup {
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
	{TCLLIB TESTSDIR/auto0/auto2 TESTSDIR/auto0/auto1*}}
test safe-9.10 {interpConfigure change the access path; tclIndex commands unaffected by token rearrangement (actual test of doreset), Sync Mode on} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library \
                                            [file join $TestsDir auto0 auto1] \
                                            [file join $TestsDir auto0 auto2]]]
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]

    # Load auto_load data.
    interp eval $i {catch nonExistentCommand}

    # Do not load the commands.  With the tokens swapped, the test
    # will pass only if the Safe Base has called auto_reset.

    # Rearrange access path.  Swap tokens {$p(:1:)} and {$p(:2:)}.
    safe::interpConfigure $i -accessPath [list $tcl_library \
                                           [file join $TestsDir auto0 auto2] \
                                           [file join $TestsDir auto0 auto1]]
					   [file join $TestsDir auto0 auto2] \
					   [file join $TestsDir auto0 auto1]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]

    # Load and run the commands.
    set code3 [catch {interp eval $i {report1}} msg3]
    set code4 [catch {interp eval $i {report2}} msg4]

    list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- $mappA -- $mappB
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:1:)} {$p(:2:)} -- {$p(:2:)} {$p(:1:)} --\
        0 ok1 0 ok2 --\
        {TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
        {TCLLIB TESTSDIR/auto0/auto2 TESTSDIR/auto0/auto1*}}
test safe-9.11 {interpConfigure change the access path; pkgIndex.tcl packages unaffected by token rearrangement} -setup {
	0 ok1 0 ok2 --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
	{TCLLIB TESTSDIR/auto0/auto2 TESTSDIR/auto0/auto1*}}
test safe-9.11 {interpConfigure change the access path; pkgIndex.tcl packages unaffected by token rearrangement, Sync Mode on} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }
} -body {
    # For complete correspondence to safe-9.10opt, include auto0 in access path.
    set i [safe::interpCreate -accessPath [list $tcl_library \
                                            [file join $TestsDir auto0] \
                                            [file join $TestsDir auto0 auto1] \
                                            [file join $TestsDir auto0 auto2]]]
					    [file join $TestsDir auto0] \
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path0 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]

    # Load pkgIndex.tcl data.
    catch {interp eval $i {package require NOEXIST}}

    # Rearrange access path.  Swap tokens {$p(:2:)} and {$p(:3:)}.
    # This would have no effect because the records in Pkg of these directories
    # were from access as children of {$p(:1:)}.
    safe::interpConfigure $i -accessPath [list $tcl_library \
                                           [file join $TestsDir auto0] \
                                           [file join $TestsDir auto0 auto2] \
                                           [file join $TestsDir auto0 auto1]]
					   [file join $TestsDir auto0] \
					   [file join $TestsDir auto0 auto2] \
					   [file join $TestsDir auto0 auto1]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]

    # Try to load the packages and run a command from each one.
    set code3 [catch {interp eval $i {package require SafeTestPackage1}} msg3 opts3]
    set code4 [catch {interp eval $i {package require SafeTestPackage2}} msg4 opts4]
    set code5 [catch {interp eval $i {HeresPackage1}} msg5 opts5]
    set code6 [catch {interp eval $i {HeresPackage2}} msg6 opts6]

    list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- \
         $mappA -- $mappB -- $code5 $msg5 $code6 $msg6
	 $mappA -- $mappB -- $code5 $msg5 $code6 $msg6
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:2:)} {$p(:3:)} -- {$p(:3:)} {$p(:2:)} -- 0 1.2.3 0 2.3.4 --\
        {TCLLIB TESTSDIR/auto0 TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
        {TCLLIB TESTSDIR/auto0 TESTSDIR/auto0/auto2 TESTSDIR/auto0/auto1*} --\
        0 OK1 0 OK2}
test safe-9.12 {interpConfigure change the access path; pkgIndex.tcl packages unaffected by token rearrangement, 9.10 without path auto0} -setup {
	{TCLLIB TESTSDIR/auto0 TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
	{TCLLIB TESTSDIR/auto0 TESTSDIR/auto0/auto2 TESTSDIR/auto0/auto1*} --\
	0 OK1 0 OK2}
test safe-9.12 {interpConfigure change the access path; pkgIndex.tcl packages unaffected by token rearrangement, safe-9.11 without path auto0, Sync Mode on} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library \
                                            [file join $TestsDir auto0 auto1] \
                                            [file join $TestsDir auto0 auto2]]]
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]

    # Load pkgIndex.tcl data.
    catch {interp eval $i {package require NOEXIST}}

    # Rearrange access path.  Swap tokens {$p(:1:)} and {$p(:2:)}.
    safe::interpConfigure $i -accessPath [list $tcl_library \
                                           [file join $TestsDir auto0 auto2] \
                                           [file join $TestsDir auto0 auto1]]
					   [file join $TestsDir auto0 auto2] \
					   [file join $TestsDir auto0 auto1]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]

    # Try to load the packages and run a command from each one.
    set code3 [catch {interp eval $i {package require SafeTestPackage1}} msg3 opts3]
    set code4 [catch {interp eval $i {package require SafeTestPackage2}} msg4 opts4]
    set code5 [catch {interp eval $i {HeresPackage1}} msg5 opts5]
    set code6 [catch {interp eval $i {HeresPackage2}} msg6 opts6]

    list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- \
            $mappA -- $mappB -- \
            $code5 $msg5 $code6 $msg6
	    $mappA -- $mappB -- \
	    $code5 $msg5 $code6 $msg6
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:1:)} {$p(:2:)} -- {$p(:2:)} {$p(:1:)} --\
        0 1.2.3 0 2.3.4 --\
        {TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
        {TCLLIB TESTSDIR/auto0/auto2 TESTSDIR/auto0/auto1*} --\
        0 OK1 0 OK2}
test safe-9.13 {interpConfigure change the access path; pkgIndex.tcl packages fail if directory de-listed} -setup {
	0 1.2.3 0 2.3.4 --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
	{TCLLIB TESTSDIR/auto0/auto2 TESTSDIR/auto0/auto1*} --\
	0 OK1 0 OK2}
test safe-9.13 {interpConfigure change the access path; pkgIndex.tcl packages fail if directory de-listed, Sync Mode on} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library \
                                            [file join $TestsDir auto0 auto1] \
                                            [file join $TestsDir auto0 auto2]]]
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]

    # Load pkgIndex.tcl data.
852
853
854
855
856
857
858
859

860
861



862
863
864
865








866
867
868

869
870
871
872
873
874
875
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







-
+


+
+
+

-
-
-
+
+
+
+
+
+
+
+


-
+







    set code5 [catch {::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]} path5]

    # Try to load the packages.
    set code3 [catch {interp eval $i {package require SafeTestPackage1}} msg3]
    set code6 [catch {interp eval $i {package require SafeTestPackage2}} msg6]

    list $path1 $path2 -- $code4 $path4 -- $code5 $path5 -- $code3 $code6 -- \
            $mappA -- $mappB
	    $mappA -- $mappB
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:1:)} {$p(:2:)} -- 1 {* not found in access path} --\
        1 {* not found in access path} -- 1 1 --\
        {TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} -- {TCLLIB*}}
test safe-9.20 {check module loading} -setup {
	1 {* not found in access path} -- 1 1 --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} -- {TCLLIB*}}
test safe-9.20 {check module loading, Sync Mode on} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }
    set oldTm [tcl::tm::path list]
    foreach path $oldTm {
        tcl::tm::path remove $path
	tcl::tm::path remove $path
    }
    tcl::tm::path add [file join $TestsDir auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]

    # Inspect.
    set confA [safe::interpConfigure $i]
884
885
886
887
888
889
890
891

892
893
894
895

896
897



898
899
900
901



902
903
904
905
906
907
908
909
910
911






912
913
914

915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932


933
934
935
936
937
938
939
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
1116







-
+



-
+


+
+
+

-
-
-
+
+
+









-
+
+
+
+
+
+


-
+
















-
-
+
+







    set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
    set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
    set out0  [interp eval $i {test0::try0}]
    set out1  [interp eval $i {mod1::test1::try1}]
    set out2  [interp eval $i {mod2::test2::try2}]

    list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
            $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $out0 $out1 $out2
	    $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $out0 $out1 $out2
} -cleanup {
    tcl::tm::path remove [file join $TestsDir auto0 modules]
    foreach path [lreverse $oldTm] {
        tcl::tm::path add $path
	tcl::tm::path add $path
    }
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
        0 0.5 0 1.0 0 2.0 --\
        {TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
         TESTSDIR/auto0/modules/mod2} -- res0 res1 res2}
	0 0.5 0 1.0 0 2.0 --\
	{TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
	 TESTSDIR/auto0/modules/mod2} -- res0 res1 res2}
# - The command safe::InterpSetConfig adds the parent's [tcl::tm::list] in
#   tokenized form to the child's access path, and then adds all the
#   descendants, discovered recursively by using glob.
# - The order of the directories in the list returned by glob is system-dependent,
#   and therefore this is true also for (a) the order of token assignment to
#   descendants of the [tcl::tm::list] roots; and (b) the order of those same
#   directories in the access path.  Both those things must be sorted before
#   comparing with expected results.  The test is therefore not totally strict,
#   but will notice missing or surplus directories.
test safe-9.21 {interpConfigure change the access path; check module loading; stale data case 1} -setup {
test safe-9.21 {interpConfigure change the access path; check module loading, Sync Mode on; stale data case 1} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }
    set oldTm [tcl::tm::path list]
    foreach path $oldTm {
        tcl::tm::path remove $path
	tcl::tm::path remove $path
    }
    tcl::tm::path add [file join $TestsDir auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]

    # Inspect.
    set confA [safe::interpConfigure $i]
    set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
    set modsA [interp eval $i {tcl::tm::path list}]
    set path0 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]

    # Add to access path.
    # This injects more tokens, pushing modules to higher token numbers.
    safe::interpConfigure $i -accessPath [list $tcl_library \
                                           [file join $TestsDir auto0 auto1] \
                                           [file join $TestsDir auto0 auto2]]
					   [file join $TestsDir auto0 auto1] \
					   [file join $TestsDir auto0 auto2]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
    set modsB [interp eval $i {tcl::tm::path list}]
    set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
    set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
    set path5 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]
948
949
950
951
952
953
954
955
956
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
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
1125
1126
1127
1128
1129
1130
1131



1132
1133
1134
1135
1136
1137

1138
1139
1140
1141
1142
1143
1144







1145
1146
1147
1148
1149
1150
1151
1152

1153
1154
1155
1156
1157
1158
1159
1160

1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177


1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196



1197
1198
1199
1200
1201
1202

1203
1204
1205
1206
1207
1208
1209







1210
1211
1212
1213
1214
1215
1216
1217

1218
1219
1220
1221
1222
1223
1224
1225

1226
1227
1228
1229
1230
1231
1232
1233







-
-
-
+
+
+



-
+


+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
+
+
+
+
+
+


-
+
















-
-
+
+

















-
-
-
+
+
+



-
+


+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
+
+
+
+
+
+


-
+







    set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
    set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
    set out0  [interp eval $i {test0::try0}]
    set out1  [interp eval $i {mod1::test1::try1}]
    set out2  [interp eval $i {mod2::test2::try2}]

    list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
            [lsort [list $path3 $path4 $path5]] -- $modsB -- \
            $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
            $out0 $out1 $out2
	    [lsort [list $path3 $path4 $path5]] -- $modsB -- \
	    $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
	    $out0 $out1 $out2
} -cleanup {
    tcl::tm::path remove [file join $TestsDir auto0 modules]
    foreach path [lreverse $oldTm] {
        tcl::tm::path add $path
	tcl::tm::path add $path
    }
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
        {{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
        0 0.5 0 1.0 0 2.0 --\
        {TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
         TESTSDIR/auto0/modules/mod2} --\
        {TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2 TESTSDIR/auto0/modules\
         TESTSDIR/auto0/modules/mod1 TESTSDIR/auto0/modules/mod2} --\
        res0 res1 res2}
	{{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
	0 0.5 0 1.0 0 2.0 --\
	{TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
	 TESTSDIR/auto0/modules/mod2} --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2 TESTSDIR/auto0/modules\
	 TESTSDIR/auto0/modules/mod1 TESTSDIR/auto0/modules/mod2} --\
	res0 res1 res2}
# See comments on lsort after test safe-9.20.
test safe-9.22 {interpConfigure change the access path; check module loading; stale data case 0} -setup {
test safe-9.22 {interpConfigure change the access path; check module loading, Sync Mode on; stale data case 0} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }
    set oldTm [tcl::tm::path list]
    foreach path $oldTm {
        tcl::tm::path remove $path
	tcl::tm::path remove $path
    }
    tcl::tm::path add [file join $TestsDir auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]

    # Inspect.
    set confA [safe::interpConfigure $i]
    set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
    set modsA [interp eval $i {tcl::tm::path list}]
    set path0 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]

    # Add to access path.
    # This injects more tokens, pushing modules to higher token numbers.
    safe::interpConfigure $i -accessPath [list $tcl_library \
                                          [file join $TestsDir auto0 auto1] \
                                          [file join $TestsDir auto0 auto2]]
					  [file join $TestsDir auto0 auto1] \
					  [file join $TestsDir auto0 auto2]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
    set modsB [interp eval $i {tcl::tm::path list}]
    set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
    set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
    set path5 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]

    # Try to load the packages and run a command from each one.
    set code0 [catch {interp eval $i {package require test0}} msg0]
    set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
    set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
    set out0  [interp eval $i {test0::try0}]
    set out1  [interp eval $i {mod1::test1::try1}]
    set out2  [interp eval $i {mod2::test2::try2}]

    list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
            [lsort [list $path3 $path4 $path5]] -- $modsB -- \
            $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
            $out0 $out1 $out2
	    [lsort [list $path3 $path4 $path5]] -- $modsB -- \
	    $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
	    $out0 $out1 $out2
} -cleanup {
    tcl::tm::path remove [file join $TestsDir auto0 modules]
    foreach path [lreverse $oldTm] {
        tcl::tm::path add $path
	tcl::tm::path add $path
    }
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
        {{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
        0 0.5 0 1.0 0 2.0 --\
        {TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
         TESTSDIR/auto0/modules/mod2} --\
        {TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2 TESTSDIR/auto0/modules\
         TESTSDIR/auto0/modules/mod1 TESTSDIR/auto0/modules/mod2} --\
        res0 res1 res2}
	{{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
	0 0.5 0 1.0 0 2.0 --\
	{TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
	 TESTSDIR/auto0/modules/mod2} --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2 TESTSDIR/auto0/modules\
	 TESTSDIR/auto0/modules/mod1 TESTSDIR/auto0/modules/mod2} --\
	res0 res1 res2}
# See comments on lsort after test safe-9.20.
test safe-9.23 {interpConfigure change the access path; check module loading; stale data case 3} -setup {
test safe-9.23 {interpConfigure change the access path; check module loading, Sync Mode on; stale data case 3} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }
    set oldTm [tcl::tm::path list]
    foreach path $oldTm {
        tcl::tm::path remove $path
	tcl::tm::path remove $path
    }
    tcl::tm::path add [file join $TestsDir auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]

    # Inspect.
    set confA [safe::interpConfigure $i]
1048
1049
1050
1051
1052
1053
1054
1055
1056


1057
1058
1059
1060
1061
1062
1063
1241
1242
1243
1244
1245
1246
1247


1248
1249
1250
1251
1252
1253
1254
1255
1256







-
-
+
+







    catch {interp eval $i {package require NOEXIST}}
    catch {interp eval $i {package require mod1::NOEXIST}}
    catch {interp eval $i {package require mod2::NOEXIST}}

    # Add to access path.
    # This injects more tokens, pushing modules to higher token numbers.
    safe::interpConfigure $i -accessPath [list $tcl_library \
                                           [file join $TestsDir auto0 auto1] \
                                           [file join $TestsDir auto0 auto2]]
					   [file join $TestsDir auto0 auto1] \
					   [file join $TestsDir auto0 auto2]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
    set modsB [interp eval $i {tcl::tm::path list}]
    set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
    set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
    set path5 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]
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
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







-
-
-
+
+
+



-
+


+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
+
+
+
+
+
+


-
+







    set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
    set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
    set out0  [interp eval $i {test0::try0}]
    set out1  [interp eval $i {mod1::test1::try1}]
    set out2  [interp eval $i {mod2::test2::try2}]

    list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
            [lsort [list $path3 $path4 $path5]] -- $modsB -- \
            $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
            $out0 $out1 $out2
	    [lsort [list $path3 $path4 $path5]] -- $modsB -- \
	    $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
	    $out0 $out1 $out2
} -cleanup {
    tcl::tm::path remove [file join $TestsDir auto0 modules]
    foreach path [lreverse $oldTm] {
        tcl::tm::path add $path
	tcl::tm::path add $path
    }
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
        {{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
        0 0.5 0 1.0 0 2.0 --\
        {TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
         TESTSDIR/auto0/modules/mod2} --\
        {TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2 TESTSDIR/auto0/modules\
         TESTSDIR/auto0/modules/mod1 TESTSDIR/auto0/modules/mod2} --\
        res0 res1 res2}
	{{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
	0 0.5 0 1.0 0 2.0 --\
	{TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
	 TESTSDIR/auto0/modules/mod2} --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2 TESTSDIR/auto0/modules\
	 TESTSDIR/auto0/modules/mod1 TESTSDIR/auto0/modules/mod2} --\
	res0 res1 res2}
# See comments on lsort after test safe-9.20.
test safe-9.24 {interpConfigure change the access path; check module loading; stale data case 2 (worst case)} -setup {
test safe-9.24 {interpConfigure change the access path; check module loading, Sync Mode on; stale data case 2 (worst case)} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }
    set oldTm [tcl::tm::path list]
    foreach path $oldTm {
        tcl::tm::path remove $path
	tcl::tm::path remove $path
    }
    tcl::tm::path add [file join $TestsDir auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]

    # Inspect.
    set confA [safe::interpConfigure $i]
1115
1116
1117
1118
1119
1120
1121
1122
1123


1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143



1144
1145
1146
1147

1148
1149



1150
1151
1152
1153
1154
1155
1156
1157







1158
1159


1160
1161


1162
1163
1164

1165
1166
1167
1168


1169
1170
1171

1172
1173

1174
1175
1176

1177
1178

1179
1180
1181


1182
1183

1184
1185
1186

1187
1188
1189
1190


1191
1192
1193
1194

1195
1196

1197
1198
1199
1200


1201
1202

1203
1204

1205
1206
1207

1208
1209

1210
1211



1212
1213
1214
1215
1216
1217
1218
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
1354







1355
1356
1357
1358
1359
1360
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
1387
1388

1389
1390
1391

1392
1393
1394


1395
1396
1397
1398
1399

1400
1401

1402
1403
1404


1405
1406
1407

1408
1409

1410
1411
1412

1413
1414

1415
1416

1417
1418
1419
1420
1421
1422
1423
1424
1425
1426







-
-
+
+

















-
-
-
+
+
+



-
+


+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+


+
+
-
-
+
+


-
+


-
-
+
+


-
+

-
+


-
+

-
+

-
-
+
+

-
+


-
+


-
-
+
+



-
+

-
+


-
-
+
+

-
+

-
+


-
+

-
+

-
+
+
+







    catch {interp eval $i {package require NOEXIST}}
    catch {interp eval $i {package require mod1::NOEXIST}}
    catch {interp eval $i {package require mod2::NOEXIST}}

    # Add to access path.
    # This injects more tokens, pushing modules to higher token numbers.
    safe::interpConfigure $i -accessPath [list $tcl_library \
                                           [file join $TestsDir auto0 auto1] \
                                           [file join $TestsDir auto0 auto2]]
					   [file join $TestsDir auto0 auto1] \
					   [file join $TestsDir auto0 auto2]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
    set modsB [interp eval $i {tcl::tm::path list}]
    set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
    set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
    set path5 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]

    # Try to load the packages and run a command from each one.
    set code0 [catch {interp eval $i {package require test0}} msg0]
    set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
    set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
    set out0  [interp eval $i {test0::try0}]
    set out1  [interp eval $i {mod1::test1::try1}]
    set out2  [interp eval $i {mod2::test2::try2}]

    list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
            [lsort [list $path3 $path4 $path5]] -- $modsB -- \
            $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
            $out0 $out1 $out2
	    [lsort [list $path3 $path4 $path5]] -- $modsB -- \
	    $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
	    $out0 $out1 $out2
} -cleanup {
    tcl::tm::path remove [file join $TestsDir auto0 modules]
    foreach path [lreverse $oldTm] {
        tcl::tm::path add $path
	tcl::tm::path add $path
    }
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
        {{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
        0 0.5 0 1.0 0 2.0 --\
        {TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
         TESTSDIR/auto0/modules/mod2} --\
        {TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2 TESTSDIR/auto0/modules\
         TESTSDIR/auto0/modules/mod1 TESTSDIR/auto0/modules/mod2} --\
        res0 res1 res2}
	{{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
	0 0.5 0 1.0 0 2.0 --\
	{TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
	 TESTSDIR/auto0/modules/mod2} --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2 TESTSDIR/auto0/modules\
	 TESTSDIR/auto0/modules/mod1 TESTSDIR/auto0/modules/mod2} --\
	res0 res1 res2}
# See comments on lsort after test safe-9.20.

### 10. Test options -statics -nostatics -nested -nestedloadok

catch {teststaticpkg Safepkg1 0 0}
test safe-10.1 {testing statics loading} -constraints TcltestPackage -setup {
catch {teststaticlibrary Safepfx1 0 0}
test safe-10.1 {testing statics loading} -constraints tcl::test -setup {
    set i [safe::interpCreate]
} -body {
    interp eval $i {load {} Safepkg1}
    interp eval $i {load {} Safepfx1}
} -returnCodes error -cleanup {
    safe::interpDelete $i
} -result {load of binary library for package Safepkg1 failed: can't use package in a safe interpreter: no Safepkg1_SafeInit procedure}
test safe-10.1.1 {testing statics loading} -constraints TcltestPackage -setup {
} -result {load of library for prefix Safepfx1 failed: cannot use library in a safe interpreter: no Safepfx1_SafeInit procedure}
test safe-10.1.1 {testing statics loading} -constraints tcl::test -setup {
    set i [safe::interpCreate]
} -body {
    catch {interp eval $i {load {} Safepkg1}} m o
    catch {interp eval $i {load {} Safepfx1}} m o
    dict get $o -errorinfo
} -returnCodes ok -cleanup {
} -cleanup {
    unset -nocomplain m o
    safe::interpDelete $i
} -result {load of binary library for package Safepkg1 failed: can't use package in a safe interpreter: no Safepkg1_SafeInit procedure
} -result {load of library for prefix Safepfx1 failed: cannot use library in a safe interpreter: no Safepfx1_SafeInit procedure
    invoked from within
"load {} Safepkg1"
"load {} Safepfx1"
    invoked from within
"interp eval $i {load {} Safepkg1}"}
test safe-10.2 {testing statics loading / -nostatics} -constraints TcltestPackage -body {
"interp eval $i {load {} Safepfx1}"}
test safe-10.2 {testing statics loading / -nostatics} -constraints tcl::test -body {
    set i [safe::interpCreate -nostatics]
    interp eval $i {load {} Safepkg1}
    interp eval $i {load {} Safepfx1}
} -returnCodes error -cleanup {
    safe::interpDelete $i
} -result {permission denied (static package)}
} -result {permission denied (static library)}
test safe-10.3 {testing nested statics loading / no nested by default} -setup {
    set i [safe::interpCreate]
} -constraints TcltestPackage -body {
    interp eval $i {interp create x; load {} Safepkg1 x}
} -constraints tcl::test -body {
    interp eval $i {interp create x; load {} Safepfx1 x}
} -returnCodes error -cleanup {
    safe::interpDelete $i
} -result {permission denied (nested load)}
test safe-10.4 {testing nested statics loading / -nestedloadok} -constraints TcltestPackage -body {
test safe-10.4 {testing nested statics loading / -nestedloadok} -constraints tcl::test -body {
    set i [safe::interpCreate -nestedloadok]
    interp eval $i {interp create x; load {} Safepkg1 x}
    interp eval $i {interp create x; load {} Safepfx1 x}
} -returnCodes error -cleanup {
    safe::interpDelete $i
} -result {load of binary library for package Safepkg1 failed: can't use package in a safe interpreter: no Safepkg1_SafeInit procedure}
test safe-10.4.1 {testing nested statics loading / -nestedloadok} -constraints TcltestPackage -body {
} -result {load of library for prefix Safepfx1 failed: cannot use library in a safe interpreter: no Safepfx1_SafeInit procedure}
test safe-10.4.1 {testing nested statics loading / -nestedloadok} -constraints tcl::test -body {
    set i [safe::interpCreate -nestedloadok]
    catch {interp eval $i {interp create x; load {} Safepkg1 x}} m o
    catch {interp eval $i {interp create x; load {} Safepfx1 x}} m o
    dict get $o -errorinfo
} -returnCodes ok -cleanup {
} -cleanup {
    unset -nocomplain m o
    safe::interpDelete $i
} -result {load of binary library for package Safepkg1 failed: can't use package in a safe interpreter: no Safepkg1_SafeInit procedure
} -result {load of library for prefix Safepfx1 failed: cannot use library in a safe interpreter: no Safepfx1_SafeInit procedure
    invoked from within
"load {} Safepkg1 x"
"load {} Safepfx1 x"
    invoked from within
"interp eval $i {interp create x; load {} Safepkg1 x}"}
"interp eval $i {interp create x; load {} Safepfx1 x}"}

### 11. Safe encoding.

test safe-11.1 {testing safe encoding} -setup {
    set i [safe::interpCreate]
} -body {
    interp eval $i encoding
} -returnCodes error -cleanup {
    safe::interpDelete $i
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
1469
1470
1471
1472
1473
1474
1475

1476
1477
1478
1479
1480
1481

1482
1483
1484

1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497

1498
1499
1500
1501
1502
1503

1504
1505
1506

1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524







-
+





-
+


-
+












-
+





-
+


-
+







+
+
+







} -result foobar
test safe-11.7 {testing safe encoding} -setup {
    set i [safe::interpCreate]
} -body {
    interp eval $i encoding convertfrom
} -returnCodes error -cleanup {
    safe::interpDelete $i
} -result {wrong # args: should be "encoding convertfrom ?encoding? data"}
} -result {wrong # args: should be "encoding convertfrom ?-profile profile? ?-failindex var? encoding data" or "encoding convertfrom data"}
test safe-11.7.1 {testing safe encoding} -setup {
    set i [safe::interpCreate]
} -body {
    catch {interp eval $i encoding convertfrom} m o
    dict get $o -errorinfo
} -returnCodes ok -match glob -cleanup {
} -match glob -cleanup {
    unset -nocomplain m o
    safe::interpDelete $i
} -result {wrong # args: should be "encoding convertfrom ?encoding? data"
} -result {wrong # args: should be "encoding convertfrom ?-profile profile? ?-failindex var? encoding data" or "encoding convertfrom data"
    while executing
"encoding convertfrom"
    invoked from within
"encoding convertfrom"
    invoked from within
"interp eval $i encoding convertfrom"}
test safe-11.8 {testing safe encoding} -setup {
    set i [safe::interpCreate]
} -body {
    interp eval $i encoding convertto
} -returnCodes error -cleanup {
    safe::interpDelete $i
} -result {wrong # args: should be "encoding convertto ?encoding? data"}
} -result {wrong # args: should be "encoding convertto ?-profile profile? ?-failindex var? encoding data" or "encoding convertto data"}
test safe-11.8.1 {testing safe encoding} -setup {
    set i [safe::interpCreate]
} -body {
    catch {interp eval $i encoding convertto} m o
    dict get $o -errorinfo
} -returnCodes ok -match glob -cleanup {
} -match glob -cleanup {
    unset -nocomplain m o
    safe::interpDelete $i
} -result {wrong # args: should be "encoding convertto ?encoding? data"
} -result {wrong # args: should be "encoding convertto ?-profile profile? ?-failindex var? encoding data" or "encoding convertto data"
    while executing
"encoding convertto"
    invoked from within
"encoding convertto"
    invoked from within
"interp eval $i encoding convertto"}

### 12. Safe glob.
###     More tests of glob in sections 13, 16.

test safe-12.1 {glob is restricted [Bug 2906841]} -setup {
    set i [safe::interpCreate]
} -body {
    $i eval glob ../*
} -returnCodes error -cleanup {
    safe::interpDelete $i
} -result "permission denied"
1350
1351
1352
1353
1354
1355
1356



1357
1358
1359
1360
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
1387

1388
1389

1390
1391
1392
1393
1394
1395
1396
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







+
+
+















-
+














-
+

-
+







    set i [safe::interpCreate]
} -body {
    $i eval glob *
} -returnCodes error -cleanup {
    safe::interpDelete $i
} -result {permission denied}

### 13. More tests for Safe base glob, with patches @ Bug 2964715
###     More tests of glob in sections 12, 16.

proc buildEnvironment {filename} {
    upvar 1 testdir testdir testdir2 testdir2 testfile testfile
    set testdir [makeDirectory deletethisdir]
    set testdir2 [makeDirectory deletemetoo $testdir]
    set testfile [makeFile {} $filename $testdir2]
}
proc buildEnvironment2 {filename} {
    upvar 1 testdir testdir testdir2 testdir2 testfile testfile
    upvar 1 testdir3 testdir3 testfile2 testfile2
    set testdir [makeDirectory deletethisdir]
    set testdir2 [makeDirectory deletemetoo $testdir]
    set testfile [makeFile {} $filename $testdir2]
    set testdir3 [makeDirectory deleteme $testdir]
    set testfile2 [makeFile {} $filename $testdir3]
}
#### New tests for Safe base glob, with patches @ Bug 2964715

test safe-13.1 {glob is restricted [Bug 2964715]} -setup {
    set i [safe::interpCreate]
} -body {
    $i eval glob *
} -returnCodes error -cleanup {
    safe::interpDelete $i
} -result {permission denied}
test safe-13.2 {mimic the valid glob call by ::tcl::tm::UnknownHandler [Bug 2964715]} -setup {
    set i [safe::interpCreate]
    buildEnvironment deleteme.tm
} -body {
    ::safe::interpAddToAccessPath $i $testdir2
    set result [$i eval glob -nocomplain -directory $testdir2 *.tm]
    if {$result eq [list $testfile]} {
        return "glob match"
	return "glob match"
    } else {
        return "no match: $result"
	return "no match: $result"
    }
} -cleanup {
    safe::interpDelete $i
    removeDirectory $testdir
} -result {glob match}
test safe-13.3 {cf 13.2 but test glob failure when -directory is outside access path [Bug 2964715]} -setup {
    set i [safe::interpCreate]
1406
1407
1408
1409
1410
1411
1412
1413

1414
1415

1416
1417
1418
1419
1420
1421
1422
1620
1621
1622
1623
1624
1625
1626

1627
1628

1629
1630
1631
1632
1633
1634
1635
1636







-
+

-
+







    buildEnvironment deleteme.tm
} -body {
    ::safe::interpAddToAccessPath $i $testdir
    ::safe::interpAddToAccessPath $i $testdir2
    set result [$i eval \
	    glob -nocomplain -directory $testdir [file join deletemetoo *.tm]]
    if {$result eq [list $testfile]} {
        return "glob match"
	return "glob match"
    } else {
        return "no match: $result"
	return "no match: $result"
    }
} -cleanup {
    safe::interpDelete $i
    removeDirectory $testdir
} -result {glob match}
test safe-13.5 {as 13.4 but test glob failure when -directory is outside access path [Bug 2964715]} -setup {
    set i [safe::interpCreate]
1481
1482
1483
1484
1485
1486
1487
1488

1489
1490

1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508

1509

1510
1511
1512
1513
1514
1515

1516
1517
1518
1519
1520




















































































































1521
1522
1523
1524
1525
1526
1527
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858







-
+

-
+


















+
-
+





-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    set i [safe::interpCreate]
    buildEnvironment notIndex.tcl
} -body {
    ::safe::interpAddToAccessPath $i $testdir2
    set result [$i eval \
	    glob -directory $testdir -join -nocomplain * notIndex.tcl]
    if {$result eq [list $testfile]} {
        return {glob match}
	return {glob match}
    } else {
        return "no match: $result"
	return "no match: $result"
    }
} -cleanup {
    safe::interpDelete $i
    removeDirectory $testdir
} -result {no match: }
test safe-13.10 {as 13.8 but test silent failure when result is outside access_path [Bug 2964715]} -setup {
    set i [safe::interpCreate]
    buildEnvironment notIndex.tcl
} -body {
    ::safe::interpAddToAccessPath $i $testdir
    $i eval glob -directory $testdir -join -nocomplain * notIndex.tcl
} -cleanup {
    safe::interpDelete $i
    removeDirectory $testdir
} -result {}
rename buildEnvironment {}
rename buildEnvironment2 {}

### 14. Sanity checks on paths - module path, access path, auto_path.
#### Test for the module path

test safe-14.1 {Check that module path is the same as in the parent interpreter [Bug 2964715]} -setup {
    set i [safe::interpCreate]
} -body {
    set tm {}
    foreach token [$i eval ::tcl::tm::path list] {
        lappend tm [dict get [set ::safe::S${i}(access_path,map)] $token]
	lappend tm [dict get [set ::safe::S${i}(access_path,map)] $token]
    }
    return $tm
} -cleanup {
    safe::interpDelete $i
} -result [::tcl::tm::path list]
test safe-14.2 {Check that first element of child auto_path (and access path) is Tcl Library, Sync Mode on} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }

    set lib1        [info library]
    set lib2        [file dirname $lib1]
    set ::auto_TMP  $::auto_path
    set ::auto_path [list $lib1 $lib2]

    set i [safe::interpCreate]
} -body {
    set autoList {}
    set token [lindex [$i eval set ::auto_path] 0]
    set auto0 [dict get [set ::safe::S${i}(access_path,map)] $token]
    set accessList [lindex [safe::interpConfigure $i -accessPath] 1]
    return [list [lindex $accessList 0] $auto0]
} -cleanup {
    set ::auto_path $::auto_TMP
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result [list [info library] [info library]]
test safe-14.2.1 {Check that first element of child auto_path (and access path) is Tcl Library, Sync Mode off} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }

    set lib1        [info library]
    set lib2        [file dirname $lib1]
    set ::auto_TMP  $::auto_path
    set ::auto_path [list $lib1 $lib2]

    set i [safe::interpCreate]
} -body {
    set autoList {}
    set token [lindex [$i eval set ::auto_path] 0]
    set auto0 [dict get [set ::safe::S${i}(access_path,map)] $token]
    set accessList [lindex [safe::interpConfigure $i -accessPath] 1]
    set autoList   [lindex [safe::interpConfigure $i -autoPath] 1]
    return [list [lindex $accessList 0] [lindex $autoList 0] $auto0]
} -cleanup {
    set ::auto_path $::auto_TMP
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result [list [info library] [info library] [info library]]
test safe-14.3 {Check that first element of child auto_path (and access path) is Tcl Library, even if not true for parent, Sync Mode on} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }

    set lib1        [info library]
    set lib2        [file dirname $lib1]
    set ::auto_TMP  $::auto_path
    set ::auto_path [list $lib2 $lib1]
    # Unexpected order, should be reversed in the child

    set i [safe::interpCreate]
} -body {
    set autoList {}
    set token [lindex [$i eval set ::auto_path] 0]
    set auto0 [dict get [set ::safe::S${i}(access_path,map)] $token]
    set accessList [lindex [safe::interpConfigure $i -accessPath] 1]

    return [list [lindex $accessList 0] $auto0]
} -cleanup {
    set ::auto_path $::auto_TMP
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result [list [info library] [info library]]
test safe-14.3.1 {Check that first element of child auto_path (and access path) is Tcl Library, even if not true for parent, Sync Mode off} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }

    set lib1        [info library]
    set lib2        [file dirname $lib1]
    set ::auto_TMP  $::auto_path
    set ::auto_path [list $lib2 $lib1]
    # Unexpected order, should be reversed in the child

    set i [safe::interpCreate]
} -body {
    set autoList {}
    set token [lindex [$i eval set ::auto_path] 0]
    set auto0 [dict get [set ::safe::S${i}(access_path,map)] $token]
    set accessList [lindex [safe::interpConfigure $i -accessPath] 1]
    set autoList   [lindex [safe::interpConfigure $i -autoPath] 1]

    return [list [lindex $accessList 0] [lindex $autoList 0] $auto0]
} -cleanup {
    set ::auto_path $::auto_TMP
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result [list [info library] [info library] [info library]]

### 15. Safe file ensemble.

test safe-15.1 {safe file ensemble does not surprise code} -setup {
    set i [interp create -safe]
} -body {
    set result [expr {"file" in [interp hidden $i]}]
    lappend result [interp eval $i {tcl::file::split a/b/c}]
    lappend result [catch {interp eval $i {tcl::file::isdirectory .}}]
1552
1553
1554
1555
1556
1557
1558
1559




1560
1561
1562
1563
1564
1565
1566
1883
1884
1885
1886
1887
1888
1889

1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900







-
+
+
+
+







    interp delete $i
} -result {1 {a b c} 1 {a b c} 1 {invalid command name "file"} 1 0 {a b c} 1 {not allowed to invoke subcommand isdirectory of file
    while executing
"file isdirectory ."
    invoked from within
"interp eval $i {file isdirectory .}"}}

### ~ should have no special meaning in paths in safe interpreters
### 16. ~ should have no special meaning in paths in safe interpreters.
###     Defang it in glob.
###     More tests of glob in sections 12, 13.

test safe-16.1 {Bug 3529949: defang ~ in paths} -setup {
    set savedHOME $env(HOME)
    set env(HOME) /foo/bar
    set i [safe::interpCreate]
} -body {
    $i eval {
	set d [format %c 126]
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
1947
1948
1949
1950
1951
1952
1953

1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967

1968
1969
1970
1971
1972
1973
1974
1975
1976

1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
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
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565







-
+













-
+








-
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+
+








	set d [format %c 126]
	file join {$p(:0:)} $d
    }
} -cleanup {
    safe::interpDelete $i
    set env(HOME) $savedHOME
    unset savedHOME
} -result {~}
} -result {$p(:0:)/~}
test safe-16.6 {Bug 3529949: defang ~ in paths used by AliasGlob (2)} -setup {
    set savedHOME $env(HOME)
    set env(HOME) /foo/bar
    set i [safe::interpCreate]
} -body {
    $i eval {
	set d [format %c 126]
	file join {$p(:0:)/foo/bar} $d
    }
} -cleanup {
    safe::interpDelete $i
    set env(HOME) $savedHOME
    unset savedHOME
} -result {~}
} -result {$p(:0:)/foo/bar/~}
test safe-16.7 {Bug 3529949: defang ~user in paths used by AliasGlob (1)} -setup {
    set i [safe::interpCreate]
    set user $tcl_platform(user)
} -body {
    string map [list $user USER] [$i eval [list file join {$p(:0:)} ~$user]]
} -cleanup {
    safe::interpDelete $i
    unset user
} -result {~USER}
} -result {$p(:0:)/~USER}
test safe-16.8 {Bug 3529949: defang ~user in paths used by AliasGlob (2)} -setup {
    set i [safe::interpCreate]
    set user $tcl_platform(user)
} -body {
    string map [list $user USER] [$i eval [list file join {$p(:0:)/foo/bar} ~$user]]
} -cleanup {
    safe::interpDelete $i
    unset user
} -result {$p(:0:)/foo/bar/~USER}

### 17. Test the use of ::auto_path for loading commands (via tclIndex files)
###     and non-module packages (via pkgIndex.tcl files).
###     Corresponding tests with Sync Mode on are 7.*

test safe-17.1 {cf. safe-7.1 - positive non-module package require, Sync Mode off} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    # Without AutoPathSync, we need a more complete auto_path,
    # because the child will use the same value.
    set lib1        [info library]
    set lib2        [file join $TestsDir auto0]
    set ::auto_TMP  $::auto_path
    set ::auto_path [list $lib1 $lib2]

    set i [safe::interpCreate]
    set ::auto_path $::auto_TMP
} -body {
    # no error shall occur:
    # (because the default access_path shall include 1st level sub dirs so
    #  package require in a child works like in the parent)
    set v [interp eval $i {package require SafeTestPackage1}]
    # no error shall occur:
    interp eval $i HeresPackage1
    set v
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result 1.2.3
test safe-17.2 {cf. safe-7.2 - negative non-module package require with specific path and interpAddToAccessPath, Sync Mode off} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]
    # should not have been set by Safe Base:
    set auto1 [interp eval $i {set ::auto_path}]
    # This does not change the value of option -autoPath:
    interp eval $i {set ::auto_path [list {$p(:0:)}]}
    # should not add anything (p0)
    set token1 [safe::interpAddToAccessPath $i [info library]]
    # should add as p* (not p1 if parent has a module path)
    set token2 [safe::interpAddToAccessPath $i "/dummy/unixlike/test/path"]
    # should add as p* (not p2 if parent has a module path)
    set token3 [safe::interpAddToAccessPath $i [file join $TestsDir auto0]]
    # an error shall occur (SafeTestPackage1 is not in auto0 but a subdirectory)
    list $auto1 $token1 $token2 $token3 \
	    [catch {interp eval $i {package require SafeTestPackage1}} msg] $msg \
	    [safe::interpConfigure $i]\
	    [safe::interpDelete $i]
} -cleanup {
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result "{} {\$p(:0:)} {\$p(:*:)} {\$p(:*:)}\
	1 {can't find package SafeTestPackage1}\
	{-accessPath {[list $tcl_library \
			    */dummy/unixlike/test/path \
			    $TestsDir/auto0]}\
	-statics 0 -nested 1 -deleteHook {} -autoPath {}} {}"
# (not a counterpart of safe-7.3)
test safe-17.3 {Check that default auto_path is the same as in the parent interpreter, Sync Mode off} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set i [safe::interpCreate]
} -body {
    # This file's header sets auto_path to a single directory [info library],
    # which is the one required by Safe Base to be present & first in the list.
    set ap {}
    foreach token [$i eval set ::auto_path] {
	lappend ap [dict get [set ::safe::S${i}(access_path,map)] $token]
    }
    return [list $ap [lindex [::safe::interpConfigure $i -autoPath] 1]]
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result [list $::auto_path $::auto_path]
test safe-17.4 {cf. safe-7.4 - positive non-module package require with specific path and interpAddToAccessPath, Sync Mode off} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]

    # should not have been set by Safe Base:
    set auto1 [interp eval $i {set ::auto_path}]

    # This does not change the value of option -autoPath.
    interp eval $i {set ::auto_path [list {$p(:0:)}]}

    # should not add anything (p0)
    set token1 [safe::interpAddToAccessPath $i [info library]]

    # should add as p* (not p1 if parent has a module path)
    set token2 [safe::interpAddToAccessPath $i [file join $TestsDir auto0]]

    # should add as p* (not p2 if parent has a module path)
    set token3 [safe::interpAddToAccessPath $i [file join $TestsDir auto0 auto1]]

    # should not have been changed by Safe Base:
    set auto2 [interp eval $i {set ::auto_path}]

    set auto3 [interp eval $i [list set ::auto_path [list {$p(:0:)} $token2]]]

    # This time, unlike test safe-17.2 and the try above, SafeTestPackage1 should be found:
    list $auto1 $auto2 $token1 $token2 $token3 \
	    [catch {interp eval $i {package require SafeTestPackage1}} msg] $msg \
	    [safe::interpConfigure $i]\
	    [safe::interpDelete $i]
} -cleanup {
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result "{} {{\$p(:0:)}} {\$p(:0:)} {\$p(:*:)} {\$p(:*:)} 0 1.2.3\
	{-accessPath {[list $tcl_library *$TestsDir/auto0 $TestsDir/auto0/auto1]}\
	-statics 0 -nested 1 -deleteHook {}\
	-autoPath {}} {}"
test safe-17.5 {cf. safe-7.5 - positive and negative module package require, including ancestor directory issue, Sync Mode off} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    tcl::tm::path add [file join $TestsDir auto0 modules]
    set i [safe::interpCreate]
    tcl::tm::path remove [file join $TestsDir auto0 modules]
    interp eval $i {
	package forget mod1::test1
	catch {namespace delete ::mod1}
    }
} -body {
    # Should raise an error (tests module ancestor directory rule)
    set code1 [catch {interp eval $i {package require test1}} msg1]
    # Should not raise an error
    set code2 [catch {interp eval $i {package require mod1::test1}} msg2]
    return [list $code1 $msg1 $code2]
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {1 {can't find package test1} 0}

### 18. Test tokenization of directories available to a child.

test safe-18.1 {Check that each directory of the default auto_path is a valid token, Sync Mode on} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }
    set i [safe::interpCreate]
} -body {
    set badTokens {}
    foreach dir [$i eval {set ::auto_path}] {
	if {[regexp {^\$p\(:[0-9]+:\)$} $dir]} {
	    # Match - OK - token has expected form
	} else {
	    # No match - possibly an ordinary path has not been tokenized
	    lappend badTokens $dir
	}
    }
    set badTokens
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {}
test safe-18.1.1 {Check that each directory of the default auto_path is a valid token, Sync Mode off} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set i [safe::interpCreate]
} -body {
    set badTokens {}
    foreach dir [$i eval {set ::auto_path}] {
	if {[regexp {^\$p\(:[0-9]+:\)$} $dir]} {
	    # Match - OK - token has expected form
	} else {
	    # No match - possibly an ordinary path has not been tokenized
	    lappend badTokens $dir
	}
    }
    set badTokens
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {}
test safe-18.2 {Check that each directory of the module path is a valid token, Sync Mode on} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 1
    }
    set i [safe::interpCreate]
} -body {
    set badTokens {}
    foreach dir [$i eval {::tcl::tm::path list}] {
	if {[regexp {^\$p\(:[0-9]+:\)$} $dir]} {
	    # Match - OK - token has expected form
	} else {
	    # No match - possibly an ordinary path has not been tokenized
	    lappend badTokens $dir
	}
    }
    set badTokens
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {}
test safe-18.2.1 {Check that each directory of the module path is a valid token, Sync Mode off} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set i [safe::interpCreate]
} -body {
    set badTokens {}
    foreach dir [$i eval {::tcl::tm::path list}] {
	if {[regexp {^\$p\(:[0-9]+:\)$} $dir]} {
	    # Match - OK - token has expected form
	} else {
	    # No match - possibly an ordinary path has not been tokenized
	    lappend badTokens $dir
	}
    }
    set badTokens
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {}

### 19. Assorted options, including changes to option values.
###     Mostly these are changes to access path, auto_path, module path.
###     If Sync Mode is on, a corresponding test with Sync Mode off is 9.*

test safe-19.8 {autoloading commands indexed in tclIndex files, Sync Mode off} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library \
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]] \
			      -autoPath [list $tcl_library \
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
    set mappC [mapList $PathMapp [dict get $confA -autoPath]]
    set toksC [interp eval $i set ::auto_path]

    # Load and run the commands.
    set code1 [catch {interp eval $i {report1}} msg1]
    set code2 [catch {interp eval $i {report2}} msg2]

    list $path1 $path2 -- $code1 $msg1 $code2 $msg2 -- $mappA -- $mappC -- $toksC
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:1:)} {$p(:2:)} -- 0 ok1 0 ok2 --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
	{{$p(:0:)} {$p(:1:)} {$p(:2:)}}}
test safe-19.9 {interpConfigure change the access path; tclIndex commands unaffected by token rearrangement (dummy test of doreset), Sync Mode off} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library \
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]] \
			      -autoPath [list $tcl_library \
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
    set mappC [mapList $PathMapp [dict get $confA -autoPath]]
    set toksC [interp eval $i set ::auto_path]

    # Load auto_load data.
    interp eval $i {catch nonExistentCommand}

    # Load and run the commands.
    # This guarantees the test will pass even if the tokens are swapped.
    set code1 [catch {interp eval $i {report1}} msg1]
    set code2 [catch {interp eval $i {report2}} msg2]

    # Rearrange access path.  Swap tokens {$p(:1:)} and {$p(:2:)}.
    safe::interpConfigure $i -accessPath [list $tcl_library \
					   [file join $TestsDir auto0 auto2] \
					   [file join $TestsDir auto0 auto1]] \
			     -autoPath [list $tcl_library \
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
    set mappD [mapList $PathMapp [dict get $confB -autoPath]]
    set toksD [interp eval $i set ::auto_path]

    # Run the commands.
    set code3 [catch {interp eval $i {report1}} msg3]
    set code4 [catch {interp eval $i {report2}} msg4]

    list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- \
	    $mappA -- $mappB -- $mappC -- $mappD -- $toksC -- $toksD
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:1:)} {$p(:2:)} -- {$p(:2:)} {$p(:1:)} -- 0 ok1 0 ok2 --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
	{TCLLIB TESTSDIR/auto0/auto2 TESTSDIR/auto0/auto1*} --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
	{{$p(:0:)} {$p(:1:)} {$p(:2:)}} -- {{$p(:0:)} {$p(:2:)} {$p(:1:)}}}
test safe-19.10 {interpConfigure change the access path; tclIndex commands unaffected by token rearrangement (actual test of doreset), Sync Mode off} -constraints {AutoSyncDefined} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library \
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]] \
			      -autoPath [list $tcl_library \
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
    set mappC [mapList $PathMapp [dict get $confA -autoPath]]
    set toksC [interp eval $i set ::auto_path]

    # Load auto_load data.
    interp eval $i {catch nonExistentCommand}

    # Do not load the commands.  With the tokens swapped, the test
    # will pass only if the Safe Base has called auto_reset.

    # Rearrange access path.  Swap tokens {$p(:1:)} and {$p(:2:)}.
    safe::interpConfigure $i -accessPath [list $tcl_library \
					   [file join $TestsDir auto0 auto2] \
					   [file join $TestsDir auto0 auto1]] \
			     -autoPath [list $tcl_library \
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
    set mappD [mapList $PathMapp [dict get $confB -autoPath]]
    set toksD [interp eval $i set ::auto_path]

    # Load and run the commands.
    set code3 [catch {interp eval $i {report1}} msg3]
    set code4 [catch {interp eval $i {report2}} msg4]

    list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- \
	    $mappA -- $mappB -- $mappC -- $mappD -- $toksC -- $toksD
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:1:)} {$p(:2:)} -- {$p(:2:)} {$p(:1:)} --\
	0 ok1 0 ok2 --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
	{TCLLIB TESTSDIR/auto0/auto2 TESTSDIR/auto0/auto1*} --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2} --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2} --\
	{{$p(:0:)} {$p(:1:)} {$p(:2:)}} -- {{$p(:0:)} {$p(:2:)} {$p(:1:)}}}
test safe-19.11 {interpConfigure change the access path; pkgIndex.tcl packages unaffected by token rearrangement (1), Sync Mode off} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library \
					    [file join $TestsDir auto0] \
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]] \
			      -autoPath [list $tcl_library \
					    [file join $TestsDir auto0]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path0 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
    set mappC [mapList $PathMapp [dict get $confA -autoPath]]
    set toksC [interp eval $i set ::auto_path]

    # Load pkgIndex.tcl data.
    catch {interp eval $i {package require NOEXIST}}

    # Rearrange access path.  Swap tokens {$p(:2:)} and {$p(:3:)}.
    # This would have no effect because the records in Pkg of these directories
    # were from access as children of {$p(:1:)}.
    safe::interpConfigure $i -accessPath [list $tcl_library \
					   [file join $TestsDir auto0] \
					   [file join $TestsDir auto0 auto2] \
					   [file join $TestsDir auto0 auto1]] \
			      -autoPath [list $tcl_library \
					    [file join $TestsDir auto0]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
    set mappD [mapList $PathMapp [dict get $confB -autoPath]]
    set toksD [interp eval $i set ::auto_path]

    # Try to load the packages and run a command from each one.
    set code3 [catch {interp eval $i {package require SafeTestPackage1}} msg3 opts3]
    set code4 [catch {interp eval $i {package require SafeTestPackage2}} msg4 opts4]
    set code5 [catch {interp eval $i {HeresPackage1}} msg5 opts5]
    set code6 [catch {interp eval $i {HeresPackage2}} msg6 opts6]

    list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- \
	 $mappA -- $mappB -- $mappC -- $mappD -- $toksC -- $toksD -- \
	 $code5 $msg5 $code6 $msg6
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:2:)} {$p(:3:)} -- {$p(:3:)} {$p(:2:)} -- 0 1.2.3 0 2.3.4 --\
	{TCLLIB TESTSDIR/auto0 TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
	{TCLLIB TESTSDIR/auto0 TESTSDIR/auto0/auto2 TESTSDIR/auto0/auto1*} --\
	{TCLLIB TESTSDIR/auto0} -- {TCLLIB TESTSDIR/auto0} --\
	{{$p(:0:)} {$p(:1:)}} -- {{$p(:0:)} {$p(:1:)}} --\
	0 OK1 0 OK2}
test safe-19.12 {interpConfigure change the access path; pkgIndex.tcl packages unaffected by token rearrangement, safe-19.11 without path auto0, Sync Mode off} -constraints {AutoSyncDefined} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    # To manage without path auto0, use an auto_path that is unusual for
    # package discovery.
    set i [safe::interpCreate -accessPath [list $tcl_library \
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]] \
			      -autoPath [list $tcl_library \
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
    set mappC [mapList $PathMapp [dict get $confA -autoPath]]
    set toksC [interp eval $i set ::auto_path]

    # Load pkgIndex.tcl data.
    catch {interp eval $i {package require NOEXIST}}

    # Rearrange access path.  Swap tokens {$p(:2:)} and {$p(:3:)}.
    safe::interpConfigure $i -accessPath [list $tcl_library \
					   [file join $TestsDir auto0 auto2] \
					   [file join $TestsDir auto0 auto1]] \
			      -autoPath [list $tcl_library \
					    [file join $TestsDir auto0 auto2] \
					    [file join $TestsDir auto0 auto1]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
    set mappD [mapList $PathMapp [dict get $confB -autoPath]]
    set toksD [interp eval $i set ::auto_path]

    # Try to load the packages and run a command from each one.
    set code3 [catch {interp eval $i {package require SafeTestPackage1}} msg3 opts3]
    set code4 [catch {interp eval $i {package require SafeTestPackage2}} msg4 opts4]
    set code5 [catch {interp eval $i {HeresPackage1}} msg5 opts5]
    set code6 [catch {interp eval $i {HeresPackage2}} msg6 opts6]

    list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- \
	    $mappA -- $mappB -- $mappC -- $mappD -- $toksC -- $toksD -- \
	    $code5 $msg5 $code6 $msg6
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:1:)} {$p(:2:)} -- {$p(:2:)} {$p(:1:)} --\
	0 1.2.3 0 2.3.4 --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
	{TCLLIB TESTSDIR/auto0/auto2 TESTSDIR/auto0/auto1*} --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2} --\
	{TCLLIB TESTSDIR/auto0/auto2 TESTSDIR/auto0/auto1} --\
	{{$p(:0:)} {$p(:1:)} {$p(:2:)}} -- {{$p(:0:)} {$p(:1:)} {$p(:2:)}} --\
	0 OK1 0 OK2}
test safe-19.13 {interpConfigure change the access path; pkgIndex.tcl packages fail if directory de-listed, Sync Mode off} -constraints {AutoSyncDefined} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    # Path auto0 added (cf. safe-9.3) because it is needed for auto_path.
    set i [safe::interpCreate -accessPath [list $tcl_library \
					    [file join $TestsDir auto0] \
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]] \
			      -autoPath [list $tcl_library \
					    [file join $TestsDir auto0]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
    set mappC [mapList $PathMapp [dict get $confA -autoPath]]
    set toksC [interp eval $i set ::auto_path]

    # Load pkgIndex.tcl data.
    catch {interp eval $i {package require NOEXIST}}

    # Limit access path.  Remove tokens {$p(:2:)} and {$p(:3:)}.
    safe::interpConfigure $i -accessPath [list $tcl_library]

    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set code4 [catch {::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]} path4]
    set code5 [catch {::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]} path5]
    set mappD [mapList $PathMapp [dict get $confB -autoPath]]
    set toksD [interp eval $i set ::auto_path]

    # Try to load the packages.
    set code3 [catch {interp eval $i {package require SafeTestPackage1}} msg3]
    set code6 [catch {interp eval $i {package require SafeTestPackage2}} msg6]

    list $path1 $path2 -- $code4 $path4 -- $code5 $path5 -- $code3 $code6 -- \
	    $mappA -- $mappB -- $mappC -- $mappD -- $toksC -- $toksD
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:2:)} {$p(:3:)} -- 1 {* not found in access path} --\
	1 {* not found in access path} -- 1 1 --\
	{TCLLIB TESTSDIR/auto0 TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
	{TCLLIB*} -- {TCLLIB TESTSDIR/auto0} -- {TCLLIB TESTSDIR/auto0} --\
	{{$p(:0:)} {$p(:1:)}} -- {{$p(:0:)}}}
# (no counterpart safe-9.14)
test safe-19.14 {when interpConfigure changes the access path, ::auto_path uses -autoPath value and new tokens, Sync Mode off} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    # Test that although -autoPath is unchanged, the child's ::auto_path changes to
    # reflect the changes in token mappings.
    set i [safe::interpCreate -accessPath [list $tcl_library \
					    [file join $TestsDir auto0] \
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]] \
			      -autoPath [list $tcl_library \
					    [file join $TestsDir auto0]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path0 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
    set mappC [mapList $PathMapp [dict get $confA -autoPath]]
    set toksC [interp eval $i set ::auto_path]

    # Load pkgIndex.tcl data.
    catch {interp eval $i {package require NOEXIST}}

    # Rearrange access path.  Swap tokens {$p(:1:)} and {$p(:3:)}.
    safe::interpConfigure $i -accessPath [list $tcl_library \
					   [file join $TestsDir auto0 auto2] \
					   [file join $TestsDir auto0 auto1] \
					   [file join $TestsDir auto0]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set path5 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0]]
    set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
    set mappD [mapList $PathMapp [dict get $confA -autoPath]]
    set toksD [interp eval $i set ::auto_path]

    # Try to load the packages and run a command from each one.
    set code3 [catch {interp eval $i {package require SafeTestPackage1}} msg3 opts3]
    set code4 [catch {interp eval $i {package require SafeTestPackage2}} msg4 opts4]
    set code5 [catch {interp eval $i {HeresPackage1}} msg5 opts5]
    set code6 [catch {interp eval $i {HeresPackage2}} msg6 opts6]

    list $path0 $path1 $path2 -- $path5 $path3 $path4 -- $toksC -- $toksD -- \
	 $code3 $msg3 $code4 $msg4 -- \
	 $mappA -- $mappB -- $mappC -- $mappD -- $code5 $msg5 $code6 $msg6
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:1:)} {$p(:2:)} {$p(:3:)} -- {$p(:3:)} {$p(:2:)} {$p(:1:)} -- {{$p(:0:)} {$p(:1:)}} -- {{$p(:0:)} {$p(:3:)}} -- 0 1.2.3 0 2.3.4 --\
	{TCLLIB TESTSDIR/auto0 TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
	{TCLLIB TESTSDIR/auto0/auto2 TESTSDIR/auto0/auto1 TESTSDIR/auto0*} --\
	{TCLLIB TESTSDIR/auto0} --\
	{TCLLIB TESTSDIR/auto0} --\
	0 OK1 0 OK2}
# (no counterpart safe-9.15)
test safe-19.15 {when interpConfigure changes the access path, ::auto_path uses -autoPath value and new tokens, Sync Mode off} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    # Test that although -autoPath is unchanged, the child's ::auto_path changes to
    # reflect the changes in token mappings; and that it is based on the -autoPath
    # value, not the previously restricted child ::auto_path.
    set i [safe::interpCreate -accessPath [list $tcl_library \
					    [file join $TestsDir auto0]] \
			      -autoPath [list $tcl_library \
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path0 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0]]
    set mappC [mapList $PathMapp [dict get $confA -autoPath]]
    set toksC [interp eval $i set ::auto_path]

    # Load pkgIndex.tcl data.
    catch {interp eval $i {package require NOEXIST}}

    # Rearrange access path.  Add more directories.
    safe::interpConfigure $i -accessPath [list $tcl_library \
					    [file join $TestsDir auto0] \
					    [file join $TestsDir auto0 auto1] \
					    [file join $TestsDir auto0 auto2]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set path5 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0]]
    set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
    set mappD [mapList $PathMapp [dict get $confA -autoPath]]
    set toksD [interp eval $i set ::auto_path]

    # Try to load the packages and run a command from each one.
    set code3 [catch {interp eval $i {package require SafeTestPackage1}} msg3 opts3]
    set code4 [catch {interp eval $i {package require SafeTestPackage2}} msg4 opts4]
    set code5 [catch {interp eval $i {HeresPackage1}} msg5 opts5]
    set code6 [catch {interp eval $i {HeresPackage2}} msg6 opts6]

    list $path0 -- $path5 $path3 $path4 -- $toksC -- $toksD -- \
	 $code3 $msg3 $code4 $msg4 -- \
	 $mappA -- $mappB -- $mappC -- $mappD -- $code5 $msg5 $code6 $msg6
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:1:)} -- {$p(:1:)} {$p(:2:)} {$p(:3:)} -- {{$p(:0:)}} -- {{$p(:0:)} {$p(:2:)} {$p(:3:)}} -- 0 1.2.3 0 2.3.4 --\
	{TCLLIB TESTSDIR/auto0*} --\
	{TCLLIB TESTSDIR/auto0 TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2} --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2} --\
	0 OK1 0 OK2}
# (no counterpart safe-9.16)
test safe-19.16 {default value for -accessPath and -autoPath on creation; -autoPath preserved when -accessPath changes, ::auto_path using changed tokens, Sync Mode off} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set tmpAutoPath $::auto_path
    set ::auto_path [list $tcl_library [file join $TestsDir auto0]]
    set i [safe::interpCreate]
    set ::auto_path $tmpAutoPath
} -body {
    # Test that the -autoPath acquires and keeps the parent's value unless otherwise specified.

    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappC [mapList $PathMapp [dict get $confA -autoPath]]
    set toksC [interp eval $i set ::auto_path]

    # Load pkgIndex.tcl data.
    catch {interp eval $i {package require NOEXIST}}

    # Rearrange access path.  Remove a directory.
    safe::interpConfigure $i -accessPath [list $tcl_library \
					    [file join $TestsDir auto0] \
					    [file join $TestsDir auto0 auto1]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set path5 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0]]
    set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
    set mappD [mapList $PathMapp [dict get $confA -autoPath]]
    set toksD [interp eval $i set ::auto_path]

    # Try to load the packages and run a command from each one.
    set code3 [catch {interp eval $i {package require SafeTestPackage1}} msg3]
    set code4 [catch {interp eval $i {package require SafeTestPackage2}} msg4]
    set code5 [catch {interp eval $i {HeresPackage1}} msg5 opts5]
    set code6 [catch {interp eval $i {HeresPackage2}} msg6 opts6]

    list $path5 $path3 -- [lindex $toksC 0] [llength $toksC] -- \
	    $toksD -- $code3 $msg3 $code4 $msg4 -- \
	    $mappB -- $mappC -- $mappD -- $code5 $msg5 $code6 $msg6
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:1:)} {$p(:2:)} -- {$p(:0:)} 2 --\
	{{$p(:0:)} {$p(:1:)}} -- 0 1.2.3 1 {can't find package SafeTestPackage2} --\
	{TCLLIB TESTSDIR/auto0 TESTSDIR/auto0/auto1*} --\
	{TCLLIB TESTSDIR/auto0} -- {TCLLIB TESTSDIR/auto0} --\
	0 OK1 1 {invalid command name "HeresPackage2"}}
test safe-19.20 {check module loading, Sync Mode off} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set oldTm [tcl::tm::path list]
    foreach path $oldTm {
	tcl::tm::path remove $path
    }
    tcl::tm::path add [file join $TestsDir auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]

    # Inspect.
    set confA [safe::interpConfigure $i]
    set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
    set modsA [interp eval $i {tcl::tm::path list}]
    set path0 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]

    # Try to load the packages and run a command from each one.
    set code0 [catch {interp eval $i {package require test0}} msg0]
    set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
    set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
    set out0  [interp eval $i {test0::try0}]
    set out1  [interp eval $i {mod1::test1::try1}]
    set out2  [interp eval $i {mod2::test2::try2}]

    list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
	    $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $out0 $out1 $out2
} -cleanup {
    tcl::tm::path remove [file join $TestsDir auto0 modules]
    foreach path [lreverse $oldTm] {
	tcl::tm::path add $path
    }
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
	0 0.5 0 1.0 0 2.0 --\
	{TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
	 TESTSDIR/auto0/modules/mod2} -- res0 res1 res2}
# See comments on lsort after test safe-9.20.
test safe-19.21 {interpConfigure change the access path; check module loading, Sync Mode off; stale data case 1} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set oldTm [tcl::tm::path list]
    foreach path $oldTm {
	tcl::tm::path remove $path
    }
    tcl::tm::path add [file join $TestsDir auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]

    # Inspect.
    set confA [safe::interpConfigure $i]
    set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
    set modsA [interp eval $i {tcl::tm::path list}]
    set path0 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]

    # Add to access path.
    # This injects more tokens, pushing modules to higher token numbers.
    safe::interpConfigure $i -accessPath [list $tcl_library \
					   [file join $TestsDir auto0 auto1] \
					   [file join $TestsDir auto0 auto2]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
    set modsB [interp eval $i {tcl::tm::path list}]
    set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
    set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
    set path5 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]

    # Load pkg data.
    catch {interp eval $i {package require NOEXIST}}
    catch {interp eval $i {package require mod1::NOEXIST}}
    catch {interp eval $i {package require mod2::NOEXIST}}

    # Try to load the packages and run a command from each one.
    set code0 [catch {interp eval $i {package require test0}} msg0]
    set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
    set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
    set out0  [interp eval $i {test0::try0}]
    set out1  [interp eval $i {mod1::test1::try1}]
    set out2  [interp eval $i {mod2::test2::try2}]

    list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
	    [lsort [list $path3 $path4 $path5]] -- $modsB -- \
	    $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
	    $out0 $out1 $out2
} -cleanup {
    tcl::tm::path remove [file join $TestsDir auto0 modules]
    foreach path [lreverse $oldTm] {
	tcl::tm::path add $path
    }
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
	{{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
	0 0.5 0 1.0 0 2.0 --\
	{TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
	 TESTSDIR/auto0/modules/mod2} --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2 TESTSDIR/auto0/modules\
	 TESTSDIR/auto0/modules/mod1 TESTSDIR/auto0/modules/mod2} --\
	res0 res1 res2}
# See comments on lsort after test safe-9.20.
test safe-19.22 {interpConfigure change the access path; check module loading, Sync Mode off; stale data case 0} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set oldTm [tcl::tm::path list]
    foreach path $oldTm {
	tcl::tm::path remove $path
    }
    tcl::tm::path add [file join $TestsDir auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]

    # Inspect.
    set confA [safe::interpConfigure $i]
    set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
    set modsA [interp eval $i {tcl::tm::path list}]
    set path0 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]

    # Add to access path.
    # This injects more tokens, pushing modules to higher token numbers.
    safe::interpConfigure $i -accessPath [list $tcl_library \
					  [file join $TestsDir auto0 auto1] \
					  [file join $TestsDir auto0 auto2]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
    set modsB [interp eval $i {tcl::tm::path list}]
    set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
    set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
    set path5 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]

    # Try to load the packages and run a command from each one.
    set code0 [catch {interp eval $i {package require test0}} msg0]
    set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
    set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
    set out0  [interp eval $i {test0::try0}]
    set out1  [interp eval $i {mod1::test1::try1}]
    set out2  [interp eval $i {mod2::test2::try2}]

    list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
	    [lsort [list $path3 $path4 $path5]] -- $modsB -- \
	    $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
	    $out0 $out1 $out2
} -cleanup {
    tcl::tm::path remove [file join $TestsDir auto0 modules]
    foreach path [lreverse $oldTm] {
	tcl::tm::path add $path
    }
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
	{{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
	0 0.5 0 1.0 0 2.0 --\
	{TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
	 TESTSDIR/auto0/modules/mod2} --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2 TESTSDIR/auto0/modules\
	 TESTSDIR/auto0/modules/mod1 TESTSDIR/auto0/modules/mod2} --\
	res0 res1 res2}
# See comments on lsort after test safe-9.20.
test safe-19.23 {interpConfigure change the access path; check module loading, Sync Mode off; stale data case 3} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set oldTm [tcl::tm::path list]
    foreach path $oldTm {
	tcl::tm::path remove $path
    }
    tcl::tm::path add [file join $TestsDir auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]

    # Inspect.
    set confA [safe::interpConfigure $i]
    set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
    set modsA [interp eval $i {tcl::tm::path list}]
    set path0 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]

    # Force the interpreter to acquire pkg data which will soon become stale.
    catch {interp eval $i {package require NOEXIST}}
    catch {interp eval $i {package require mod1::NOEXIST}}
    catch {interp eval $i {package require mod2::NOEXIST}}

    # Add to access path.
    # This injects more tokens, pushing modules to higher token numbers.
    safe::interpConfigure $i -accessPath [list $tcl_library \
					   [file join $TestsDir auto0 auto1] \
					   [file join $TestsDir auto0 auto2]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
    set modsB [interp eval $i {tcl::tm::path list}]
    set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
    set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
    set path5 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]

    # Refresh stale pkg data.
    catch {interp eval $i {package require NOEXIST}}
    catch {interp eval $i {package require mod1::NOEXIST}}
    catch {interp eval $i {package require mod2::NOEXIST}}

    # Try to load the packages and run a command from each one.
    set code0 [catch {interp eval $i {package require test0}} msg0]
    set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
    set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
    set out0  [interp eval $i {test0::try0}]
    set out1  [interp eval $i {mod1::test1::try1}]
    set out2  [interp eval $i {mod2::test2::try2}]

    list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
	    [lsort [list $path3 $path4 $path5]] -- $modsB -- \
	    $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
	    $out0 $out1 $out2
} -cleanup {
    tcl::tm::path remove [file join $TestsDir auto0 modules]
    foreach path [lreverse $oldTm] {
	tcl::tm::path add $path
    }
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
	{{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
	0 0.5 0 1.0 0 2.0 --\
	{TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
	 TESTSDIR/auto0/modules/mod2} --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2 TESTSDIR/auto0/modules\
	 TESTSDIR/auto0/modules/mod1 TESTSDIR/auto0/modules/mod2} --\
	res0 res1 res2}
# See comments on lsort after test safe-9.20.
test safe-19.24 {interpConfigure change the access path; check module loading, Sync Mode off; stale data case 2 (worst case)} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set oldTm [tcl::tm::path list]
    foreach path $oldTm {
	tcl::tm::path remove $path
    }
    tcl::tm::path add [file join $TestsDir auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]

    # Inspect.
    set confA [safe::interpConfigure $i]
    set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
    set modsA [interp eval $i {tcl::tm::path list}]
    set path0 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
    set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
    set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]

    # Force the interpreter to acquire pkg data which will soon become stale.
    catch {interp eval $i {package require NOEXIST}}
    catch {interp eval $i {package require mod1::NOEXIST}}
    catch {interp eval $i {package require mod2::NOEXIST}}

    # Add to access path.
    # This injects more tokens, pushing modules to higher token numbers.
    safe::interpConfigure $i -accessPath [list $tcl_library \
					   [file join $TestsDir auto0 auto1] \
					   [file join $TestsDir auto0 auto2]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
    set modsB [interp eval $i {tcl::tm::path list}]
    set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
    set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
    set path5 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]

    # Try to load the packages and run a command from each one.
    set code0 [catch {interp eval $i {package require test0}} msg0]
    set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
    set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
    set out0  [interp eval $i {test0::try0}]
    set out1  [interp eval $i {mod1::test1::try1}]
    set out2  [interp eval $i {mod2::test2::try2}]

    list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
	    [lsort [list $path3 $path4 $path5]] -- $modsB -- \
	    $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
	    $out0 $out1 $out2
} -cleanup {
    tcl::tm::path remove [file join $TestsDir auto0 modules]
    foreach path [lreverse $oldTm] {
	tcl::tm::path add $path
    }
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
	{{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
	0 0.5 0 1.0 0 2.0 --\
	{TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
	 TESTSDIR/auto0/modules/mod2} --\
	{TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2 TESTSDIR/auto0/modules\
	 TESTSDIR/auto0/modules/mod1 TESTSDIR/auto0/modules/mod2} --\
	res0 res1 res2}
# See comments on lsort after test safe-9.20.


### 20. safe::interpCreate with different cases of -accessPath, -autoPath.

set ::auto_path [list $tcl_library [file dirname $tcl_library] [file join $TestsDir auto0]]

test safe-20.1 "create -accessPath NULL -autoPath NULL -> parent's ::auto_path" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate]
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result [list $::auto_path -- $::auto_path]
test safe-20.2 "create -accessPath {} -autoPath NULL -> parent's ::auto_path" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -accessPath {}]
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result [list $::auto_path -- $::auto_path]
test safe-20.3 "create -accessPath path1 -autoPath NULL -> {}" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -accessPath [lrange $::auto_path 0 1]]
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {~USER}
} -result {{} -- {}}
test safe-20.4 "create -accessPath NULL -autoPath {} -> {}" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -autoPath {}]
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {{} -- {}}
test safe-20.5 "create -accessPath {} -autoPath {} -> {}" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -accessPath {} -autoPath {}]
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {{} -- {}}
test safe-20.6 "create -accessPath path1 -autoPath {} -> {}" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -accessPath [lrange $::auto_path 0 1] -autoPath {}]
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {{} -- {}}
test safe-20.7 "create -accessPath NULL -autoPath path2 -> path2" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -autoPath [lrange $::auto_path 0 0]]
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result [list [lrange $::auto_path 0 0] -- [lrange $::auto_path 0 0]]
test safe-20.8 "create -accessPath {} -autoPath path2 -> path2" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -accessPath {} -autoPath [lrange $::auto_path 0 0]]
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result [list [lrange $::auto_path 0 0] -- [lrange $::auto_path 0 0]]
test safe-20.9 "create -accessPath path1 -autoPath path2 -> path2" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -accessPath [lrange $::auto_path 0 1] -autoPath [lrange $::auto_path 0 0]]
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result [list [lrange $::auto_path 0 0] -- [lrange $::auto_path 0 0]]
test safe-20.10 "create -accessPath NULL -autoPath pathX -> pathX" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -autoPath /not/in/access/path]
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {/not/in/access/path -- {}}
test safe-20.11 "create -accessPath {} -autoPath pathX -> pathX" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -accessPath {} -autoPath /not/in/access/path]
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {/not/in/access/path -- {}}
test safe-20.12 "create -accessPath path1 -autoPath pathX -> {pathX}" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -accessPath [lrange $::auto_path 0 1] -autoPath /not/in/access/path]
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {/not/in/access/path -- {}}

### 21. safe::interpConfigure with different cases of -accessPath, -autoPath.

test safe-21.1 "interpConfigure -accessPath NULL -autoPath NULL -> no change" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set i [safe::interpCreate -accessPath [lrange $::auto_path 0 1] -autoPath [lrange $::auto_path 0 0]]
} -body {
    safe::interpConfigure $i -deleteHook {}
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result [list [lrange $::auto_path 0 0] -- [lrange $::auto_path 0 0]]
test safe-21.2 "interpConfigure -accessPath {} -autoPath NULL -> parent's ::auto_path" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set i [safe::interpCreate -accessPath [lrange $::auto_path 0 1] -autoPath [lrange $::auto_path 0 0]]
} -body {
    safe::interpConfigure $i -accessPath {}
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result [list $::auto_path -- $::auto_path]
test safe-21.3 "interpConfigure -accessPath path1 -autoPath NULL -> no change" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set i [safe::interpCreate -accessPath [lrange $::auto_path 0 1] -autoPath [lrange $::auto_path 0 0]]
} -body {
    safe::interpConfigure $i -accessPath [lrange $::auto_path 0 1]
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result [list [lrange $::auto_path 0 0] -- [lrange $::auto_path 0 0]]
test safe-21.4 "interpConfigure -accessPath NULL -autoPath {} -> {}" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set i [safe::interpCreate -accessPath [lrange $::auto_path 0 1] -autoPath [lrange $::auto_path 0 0]]
} -body {
    safe::interpConfigure $i -autoPath {}
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {{} -- {}}
test safe-21.5 "interpConfigure -accessPath {} -autoPath {} -> {}" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set i [safe::interpCreate -accessPath [lrange $::auto_path 0 1] -autoPath [lrange $::auto_path 0 0]]
} -body {
    safe::interpConfigure $i -accessPath {} -autoPath {}
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {{} -- {}}
test safe-21.6 "interpConfigure -accessPath {path1} -autoPath {} -> {}" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set i [safe::interpCreate -accessPath [lrange $::auto_path 0 1] -autoPath [lrange $::auto_path 0 0]]
} -body {
    safe::interpConfigure $i -accessPath [lrange $::auto_path 1 1] -autoPath {}
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {{} -- {}}
test safe-21.7 "interpConfigure -accessPath NULL -autoPath path2 -> path2" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set i [safe::interpCreate -accessPath [lrange $::auto_path 0 1] -autoPath [lrange $::auto_path 0 0]]
} -body {
    safe::interpConfigure $i -autoPath [lrange $::auto_path 1 1]
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result [list [lrange $::auto_path 1 1] -- [lrange $::auto_path 1 1]]
test safe-21.8 "interpConfigure -accessPath {} -autoPath path2 -> path2" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set i [safe::interpCreate -accessPath [lrange $::auto_path 0 1] -autoPath [lrange $::auto_path 0 0]]
} -body {
    safe::interpConfigure $i -accessPath {} -autoPath [lrange $::auto_path 1 1]
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result [list [lrange $::auto_path 1 1] -- [lrange $::auto_path 1 1]]
test safe-21.9 "interpConfigure -accessPath path1 -autoPath path2 -> path2" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set i [safe::interpCreate -accessPath [lrange $::auto_path 0 1] -autoPath [lrange $::auto_path 0 0]]
} -body {
    safe::interpConfigure $i -accessPath [lrange $::auto_path 0 2] -autoPath [lrange $::auto_path 1 1]
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result [list [lrange $::auto_path 1 1] -- [lrange $::auto_path 1 1]]
test safe-21.10 "interpConfigure -accessPath NULL -autoPath pathX -> pathX" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set i [safe::interpCreate -accessPath [lrange $::auto_path 0 1] -autoPath [lrange $::auto_path 0 0]]
} -body {
    safe::interpConfigure $i -autoPath /not/in/access/path
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {/not/in/access/path -- {}}
test safe-21.11 "interpConfigure -accessPath {} -autoPath pathX -> pathX" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set i [safe::interpCreate -accessPath [lrange $::auto_path 0 1] -autoPath [lrange $::auto_path 0 0]]
} -body {
    safe::interpConfigure $i -accessPath {} -autoPath /not/in/access/path
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {/not/in/access/path -- {}}
test safe-21.12 "interpConfigure -accessPath path1 -autoPath pathX -> pathX" -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
	set SyncVal_TMP [safe::setSyncMode]
	safe::setSyncMode 0
    } else {
	error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set i [safe::interpCreate -accessPath [lrange $::auto_path 0 1] -autoPath [lrange $::auto_path 0 0]]
} -body {
    safe::interpConfigure $i -accessPath [lrange $::auto_path 0 2] -autoPath /not/in/access/path
    getAutoPath $i
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -result {/not/in/access/path -- {}}

# cleanup
set ::auto_path $SaveAutoPath
unset SaveAutoPath TestsDir PathMapp
rename getAutoPath {}
unset -nocomplain path
rename mapList {}
rename mapAndSortList {}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/scan.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  scan
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands.  Sourcing this file into Tcl runs the tests and generates output
# for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1994 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
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
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







-
+

-
+









-
+

-
+

-
+





-
+

-
+









-
+

-
+

-
+











-








proc testIEEE {} {
    variable ieeeValues
    binary scan [binary format dd -1.0 1.0] c* c
    switch -exact -- $c {
	{0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
	    # little endian
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\xFF d \
		ieeeValues(-Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\xBF d \
		ieeeValues(-Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
		ieeeValues(-Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x3F d \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \
		ieeeValues(+Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF8\x7F d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 1
	    return 1
	}
	{-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
	    binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \xFF\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Infinity)
	    binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \xBF\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Normal)
	    binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Subnormal)
	    binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x3F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Normal)
	    binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x7F\xF8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 0
	}
    }
}

testConstraint ieeeFloatingPoint [testIEEE]
testConstraint wideIs64bit [expr {wide(0x8000000000000000) < 0}]

test scan-1.1 {BuildCharSet, CharInSet} {
    list [scan foo {%[^o]} x] $x
} {1 f}
test scan-1.2 {BuildCharSet, CharInSet} {
    list [scan \]foo {%[]f]} x] $x
} {1 \]f}
504
505
506
507
508
509
510
511

512
513
514
515
516
517
518
519
520

521
522
523
524
525
526
527
503
504
505
506
507
508
509

510
511
512
513
514
515
516
517
518

519
520
521
522
523
524
525
526







-
+








-
+







} -result {4 12 34 56 78}
test scan-5.10 {integer scanning} -setup {
    set a {}; set b {}; set c {}; set d {}
} -body {
    list [scan "1 2 " "%hd %d %d %d" a b c d] $a $b $c $d
} -result {2 1 2 {} {}}
#
# The behavior for scaning intergers larger than MAX_INT is not defined by the
# The behavior for scanning integers larger than MAX_INT is not defined by the
# ANSI spec.  Some implementations wrap the input (-16) some return MAX_INT.
#
test scan-5.11 {integer scanning} -constraints {nonPortable} -setup {
    set a {}; set b {}
} -body {
    list [scan "4294967280 4294967280" "%u %d" a b] $a \
	    [expr {$b == -16 || $b == 0x7fffffff}]
} -result {2 4294967280 1}
test scan-5.12 {integer scanning} -constraints {wideIs64bit} -setup {
test scan-5.12 {integer scanning} -setup {
    set a {}; set b {}; set c {}
} -body {
    list [scan "7810179016327718216,6c63546f6c6c6548,661432506755433062510" \
	    %ld,%lx,%lo a b c] $a $b $c
} -result {3 7810179016327718216 7810179016327718216 7810179016327718216}
test scan-5.13 {integer scanning and overflow} {
    # This test used to fail on some 64-bit systems. [Bug 1011860]
549
550
551
552
553
554
555
556

557
558
559
560
561
562
563
548
549
550
551
552
553
554

555
556
557
558
559
560
561
562







-
+







    list [scan "-207698809136909011942886895" \
	    %llu a] $a
} -returnCodes 1 -result {unsigned bignum scans are invalid}
test scan-5.19 {bigint scanning invalid} -setup {
    set a {};
} -body {
    list [scan "207698809136909011942886895" \
           %llu a] $a
	   %llu a] $a
} -result {1 207698809136909011942886895}
test scan-5.20 {ignore digit separators} -setup {
    set a {}; set b {}; set c {};
} -body {
    list [scan "10_23_45" %d_%d_%d a b c] $a $b $c
} -result {3 10 23 45}

601
602
603
604
605
606
607
608

609
610
611
612
613
614
615
600
601
602
603
604
605
606

607
608
609
610
611
612
613
614







-
+







    list [scan "4.6abc" "%f %f %f %f" a b c d] $a $b $c $d
} -result {1 4.6 {} {} {}}
test scan-6.8 {floating-point scanning} -setup {
    set a {}; set b {}; set c {}; set d {}
} -body {
    list [scan "4.6 5.2" "%f %f %f %f" a b c d] $a $b $c $d
} -result {2 4.6 5.2 {} {}}
test scan-6.8 {disallow diget separator in floating-point} -setup {
test scan-6.9 {disallow diget separator in floating-point} -setup {
    set a {}; set b {}; set c {};
} -body {
    list [scan "3.14_2.35_98.6" %f_%f_%f a b c ] $a $b $c
} -result {3 3.14 2.35 98.6}

test scan-7.1 {string and character scanning} -setup {
    set a {}; set b {}; set c {}; set d {}
635
636
637
638
639
640
641
642
643


644
645
646
647

648
649
650
651
652
653


654
655
656
657
658
659
660
634
635
636
637
638
639
640


641
642
643
644
645

646
647
648
649
650


651
652
653
654
655
656
657
658
659







-
-
+
+



-
+




-
-
+
+







    set a {}; set b {}; set c {}
} -body {
    list [scan "aaaaaabc aaabcdefg  + +  XYZQR" {%*4[a] %s %*4[a]%s%*4[ +]%c} a b c] $a $b $c
} -result {3 aabc bcdefg 43}
test scan-7.6 {string and character scanning, unicode} -setup {
    set a {}; set b {}; set c {}; set d {}
} -body {
    list [scan "abc d\u00c7fghijk dum " "%s %3s %20s %s" a b c d] $a $b $c $d
} -result "4 abc d\u00c7f ghijk dum"
    list [scan "abc dÇfghijk dum " "%s %3s %20s %s" a b c d] $a $b $c $d
} -result "4 abc dÇf ghijk dum"
test scan-7.7 {string and character scanning, unicode} -setup {
    set a {}; set b {}
} -body {
    list [scan "ab\u00c7cdef" "ab%c%c" a b] $a $b
    list [scan "abÇcdef" "ab%c%c" a b] $a $b
} -result "2 199 99"
test scan-7.8 {string and character scanning, unicode} -setup {
    set a {}; set b {}
} -body {
    list [scan "ab\ufeffdef" "%\[ab\ufeff\]" a] $a
} -result "1 ab\ufeff"
    list [scan "ab\uFEFFdef" "%\[ab\uFEFF\]" a] $a
} -result "1 ab\uFEFF"

test scan-8.1 {error conditions} -body {
    scan a
} -returnCodes error -match glob -result *
test scan-8.2 {error conditions} -returnCodes error -body {
    scan a
} -result {wrong # args: should be "scan string format ?varName ...?"}
854
855
856
857
858
859
860






861
862
863
864
865
866
867
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872







+
+
+
+
+
+







test scan-13.7 {Tcl_ScanObjCmd, inline XPG case lots of arguments} {
    scan "10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200" {%20$d %18$d %17$d %16$d %15$d %14$d %13$d %12$d %11$d %10$d %9$d %8$d %7$d %6$d %5$d %4$d %3$d %2$d %1$d}
} {190 180 170 160 150 140 130 120 110 100 90 80 70 60 50 40 30 20 {} 10}
test scan-13.8 {Tcl_ScanObjCmd, inline XPG case lots of arguments} {
    set msg [scan "10 20 30" {%100$d %5$d %200$d}]
    list [llength $msg] [lindex $msg 99] [lindex $msg 4] [lindex $msg 199]
} {200 10 20 30}
test scan-13.9 {Tcl_ScanObjCmd, inline XPG case limit error} -body {
    # Note this applies to 64-bit builds as well so long as max number of
    # command line arguments allowed for scan command is INT_MAX
    scan abc {%2147483648$s}
} -result {"%n$" argument index out of range} -returnCodes error


# scan infinities - not working

test scan-14.1 {positive infinity} {
    scan Inf %g d
    return $d
} Inf

Changes to tests/security.test.

1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17








-
-
+
+







# security.test --
#
# Functionality covered: this file contains a collection of tests for the auto
# loading and namespaces.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.

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

Changes to tests/set-old.test.

1
2
3
4
5
6
7
8
9
10
11



12
13
14
15
16
17
18
1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
16
17
18








-
-
-
+
+
+







# Commands covered:  set, unset, array
#
# This file includes the original set of tests for Tcl's set command.
# Since the set command is now compiled, a new set of tests covering
# the new implementation is in the file "set.test". Sourcing this file
# into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
165
166
167
168
169
170
171
172

173
174
175
176
177
178
179
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179







-
+







    list [catch {set a} msg] $msg
} {1 {can't read "a": variable is array}}

# Errors and other special cases in writing variables

test set-old-6.1 {creating array during write} {
    catch {unset a}
    trace var a rwu ignore
    trace add var a {read write unset} ignore
    list [catch {set a(14) 186} msg] $msg [array names a]
} {0 186 14}
test set-old-6.2 {errors in writing variables} {
    catch {unset a}
    set a xxx
    list [catch {set a(14) 186} msg] $msg
} {1 {can't set "a(14)": variable isn't array}}
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
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







-
-
-
-
+
+
+
+









-
-
-
-
+
+
+
+

















-
-
-
-
+
+
+
+







} {1 {unknown or ambiguous subcommand "gorp": must be anymore, default, donesearch, exists, for, get, names, nextelement, set, size, startsearch, statistics, or unset}}
test set-old-8.7 {array command, anymore option} {
    catch {unset a}
    list [catch {array anymore a x} msg] $msg
} {1 {"a" isn't an array}}
test set-old-8.8 {array command, anymore option, array doesn't exist yet but has compiler-allocated procedure slot} {
    proc foo {x} {
        if {$x==1} {
            return [array anymore a x]
        }
        set a(x) 123
	if {$x==1} {
	    return [array anymore a x]
	}
	set a(x) 123
    }
    list [catch {foo 1} msg] $msg
} {1 {"a" isn't an array}}
test set-old-8.9 {array command, donesearch option} {
    catch {unset a}
    list [catch {array donesearch a x} msg] $msg
} {1 {"a" isn't an array}}
test set-old-8.10 {array command, donesearch option, array doesn't exist yet but has compiler-allocated procedure slot} {
    proc foo {x} {
        if {$x==1} {
            return [array donesearch a x]
        }
        set a(x) 123
	if {$x==1} {
	    return [array donesearch a x]
	}
	set a(x) 123
    }
    list [catch {foo 1} msg] $msg
} {1 {"a" isn't an array}}
test set-old-8.11 {array command, exists option} {
    list [catch {array exists a b} msg] $msg
} {1 {wrong # args: should be "array exists arrayName"}}
test set-old-8.12 {array command, exists option} {
    catch {unset a}
    array exists a
} {0}
test set-old-8.13 {array command, exists option} {
    catch {unset a}
    set a(0) 1
    array exists a
} {1}
test set-old-8.14 {array command, exists option, array doesn't exist yet but has compiler-allocated procedure slot} {
    proc foo {x} {
        if {$x==1} {
            return [array exists a]
        }
        set a(x) 123
	if {$x==1} {
	    return [array exists a]
	}
	set a(x) 123
    }
    list [catch {foo 1} msg] $msg
} {0 0}
test set-old-8.15 {array command, get option} {
    list [catch {array get} msg] $msg
} {1 {wrong # args: should be "array get arrayName ?pattern?"}}
test set-old-8.16 {array command, get option} {
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
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
467
468
469
470
471




472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487




488
489
490
491
492
493
494
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
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
467




468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483




484
485
486
487
488
489
490
491
492
493
494







-
+













-
-
-
-
+
+
+
+




















-
+





-
+













-
-
-
-
+
+
+
+












-
-
-
-
+
+
+
+







    set a(22) 3
    set {a(long name)} {}
    lsort [array get a]
} {{} 22 3 {long name}}
test set-old-8.19 {array command, get option (unset variable)} {
    catch {unset a}
    set a(x) 3
    trace var a(y) w ignore
    trace add var a(y) write ignore
    array get a
} {x 3}
test set-old-8.20 {array command, get option, with pattern} {
    catch {unset a}
    set a(x1) 3
    set a(x2) 4
    set a(x3) 5
    set a(b1) 24
    set a(b2) 25
    lsort [array get a x*]
} {3 4 5 x1 x2 x3}
test set-old-8.21 {array command, get option, array doesn't exist yet but has compiler-allocated procedure slot} {
    proc foo {x} {
        if {$x==1} {
            return [array get a]
        }
        set a(x) 123
	if {$x==1} {
	    return [array get a]
	}
	set a(x) 123
    }
    list [catch {foo 1} msg] $msg
} {0 {}}
test set-old-8.22 {array command, names option} {
    catch {unset a}
    set a(22) 3
    list [catch {array names a 4 5} msg] $msg
} {1 {bad option "4": must be -exact, -glob, or -regexp}}
test set-old-8.23 {array command, names option} {
    catch {unset a}
    array names a
} {}
test set-old-8.24 {array command, names option} {
    catch {unset a}
    set a(22) 3; set a(Textual_name) 44; set "a(name with spaces)" xxx
    list [catch {lsort [array names a]} msg] $msg
} {0 {22 Textual_name {name with spaces}}}
test set-old-8.25 {array command, names option} {
    catch {unset a}
    set a(22) 3; set a(33) 44;
    trace var a(xxx) w ignore
    trace add var a(xxx) write ignore
    list [catch {lsort [array names a]} msg] $msg
} {0 {22 33}}
test set-old-8.26 {array command, names option} {
    catch {unset a}
    set a(22) 3; set a(33) 44;
    trace var a(xxx) w ignore
    trace add var a(xxx) write ignore
    set a(xxx) value
    list [catch {lsort [array names a]} msg] $msg
} {0 {22 33 xxx}}
test set-old-8.27 {array command, names option} {
    catch {unset a}
    set a(axy) 3
    set a(bxy) 44
    set a(no) yes
    set a(xxx) value
    list [lsort [array names a *xy]] [lsort [array names a]]
} {{axy bxy} {axy bxy no xxx}}
test set-old-8.28 {array command, names option, array doesn't exist yet but has compiler-allocated procedure slot} {
    proc foo {x} {
        if {$x==1} {
            return [array names a]
        }
        set a(x) 123
	if {$x==1} {
	    return [array names a]
	}
	set a(x) 123
    }
    list [catch {foo 1} msg] $msg
} {0 {}}
test set-old-8.29 {array command, nextelement option} {
    list [catch {array nextelement a} msg] $msg
} {1 {wrong # args: should be "array nextelement arrayName searchId"}}
test set-old-8.30 {array command, nextelement option} {
    catch {unset a}
    list [catch {array nextelement a b} msg] $msg
} {1 {"a" isn't an array}}
test set-old-8.31 {array command, nextelement option, array doesn't exist yet but has compiler-allocated procedure slot} {
    proc foo {x} {
        if {$x==1} {
            return [array nextelement a b]
        }
        set a(x) 123
	if {$x==1} {
	    return [array nextelement a b]
	}
	set a(x) 123
    }
    list [catch {foo 1} msg] $msg
} {1 {"a" isn't an array}}
test set-old-8.32 {array command, set option} {
    list [catch {array set a} msg] $msg
} {1 {wrong # args: should be "array set arrayName list"}}
test set-old-8.33 {array command, set option} {
506
507
508
509
510
511
512
513
514
515
516




517
518
519
520
521
522
523
506
507
508
509
510
511
512




513
514
515
516
517
518
519
520
521
522
523







-
-
-
-
+
+
+
+







    catch {unset a}
    set a(xx) yy
    array set a {b c d e}
    lsort [array get a]
} {b c d e xx yy}
test set-old-8.37 {array command, set option, array doesn't exist yet but has compiler-allocated procedure slot} {
    proc foo {x} {
        if {$x==1} {
            return [array set a {x 0}]
        }
        set a(x)
	if {$x==1} {
	    return [array set a {x 0}]
	}
	set a(x)
    }
    list [catch {foo 1} msg] $msg
} {0 {}}
test set-old-8.38 {array command, set option} {
    catch {unset aVaRnAmE}
    array set aVaRnAmE {}
    list [info exists aVaRnAmE] [catch {set aVaRnAmE} msg] $msg
575
576
577
578
579
580
581
582

583
584
585
586
587
588
589
590




591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607




608
609
610
611
612
613
614
575
576
577
578
579
580
581

582
583
584
585
586




587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603




604
605
606
607
608
609
610
611
612
613
614







-
+




-
-
-
-
+
+
+
+













-
-
-
-
+
+
+
+







    set a(22) 3; set a(xx) 44; set a(y) xxx
    unset a(22) a(y) a(xx)
    list [catch {array size a} msg] $msg
} {0 0}
test set-old-8.44 {array command, size option} {
    catch {unset a}
    set a(22) 3;
    trace var a(33) rwu ignore
    trace add var a(33) {read write unset} ignore
    list [catch {array size a} msg] $msg
} {0 1}
test set-old-8.45 {array command, size option, array doesn't exist yet but has compiler-allocated procedure slot} {
    proc foo {x} {
        if {$x==1} {
            return [array size a]
        }
        set a(x) 123
	if {$x==1} {
	    return [array size a]
	}
	set a(x) 123
    }
    list [catch {foo 1} msg] $msg
} {0 0}
test set-old-8.46 {array command, startsearch option} {
    list [catch {array startsearch a b} msg] $msg
} {1 {wrong # args: should be "array startsearch arrayName"}}
test set-old-8.47 {array command, startsearch option} {
    catch {unset a}
    list [catch {array startsearch a} msg] $msg
} {1 {"a" isn't an array}}
test set-old-8.48 {array command, startsearch option, array doesn't exist yet but has compiler-allocated procedure slot} {
    catch {rename p ""}
    proc p {x} {
        if {$x==1} {
            return [array startsearch a]
        }
        set a(x) 123
	if {$x==1} {
	    return [array startsearch a]
	}
	set a(x) 123
    }
    list [catch {p 1} msg] $msg
} {1 {"a" isn't an array}}
test set-old-8.49 {array command, statistics option} {
    catch {unset a}
    set a(abc) 1
    set a(def) 2
782
783
784
785
786
787
788
789

790
791
792
793
794
795
796
797
798

799
800
801
802
803
804
805

806
807
808
809
810
811
812
782
783
784
785
786
787
788

789
790
791
792
793
794
795
796
797

798
799
800
801
802
803
804

805
806
807
808
809
810
811
812







-
+








-
+






-
+







	    [catch {array next a $y} msg2] $msg2
} {0 a 0 a}
test set-old-9.10 {array enumeration: searches automatically stopped} {
    catch {unset a}
    set a(a) 1
    set x [array startsearch a]
    set y [array startsearch a]
    trace var a(b) r {}
    trace add var a(b) read {}
    list [catch {array next a $x} msg] $msg \
	    [catch {array next a $y} msg2] $msg2
} {1 {couldn't find search "s-1-a"} 1 {couldn't find search "s-2-a"}}
test set-old-9.11 {array enumeration: searches automatically stopped} {
    catch {unset a}
    set a(a) 1
    set x [array startsearch a]
    set y [array startsearch a]
    trace var a(a) r {}
    trace add var a(a) read {}
    list [catch {array next a $x} msg] $msg \
	    [catch {array next a $y} msg2] $msg2
} {0 a 0 a}
test set-old-9.12 {array enumeration with traced undefined elements} {
    catch {unset a}
    set a(a) 1
    trace var a(b) r {}
    trace add var a(b) read {}
    set x [array startsearch a]
    lsort [list [array next a $x] [array next a $x]]
} {{} a}

test set-old-10.1 {array enumeration errors} {
    list [catch {array start} msg] $msg
} {1 {wrong # args: should be "array startsearch arrayName"}}

Changes to tests/set.test.

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
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






-
-
+
+










-
+







# Commands covered:  set
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testset2 [llength [info commands testset2]]

catch {unset x}
catch {unset i}

test set-1.1 {TclCompileSetCmd: missing variable name} {
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
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







-
-
-
+
+
+





-
-
+
+





-
+






-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







test set-1.10 {TclCompileSetCmd: only two args => just getting value} {
    set i {one two}
    set i
} {one two}

test set-1.11 {TclCompileSetCmd: simple global name} {
    proc p {} {
        global i
        set i 54
        set i
	global i
	set i 54
	set i
    }
    p
} {54}
test set-1.12 {TclCompileSetCmd: simple local name} {
    proc p {bar} {
        set foo $bar
        set foo
	set foo $bar
	set foo
    }
    p 999
} {999}
test set-1.13 {TclCompileSetCmd: simple but new (unknown) local name} {
    proc p {} {
        set bar
	set bar
    }
    catch {p} msg
    set msg
} {can't read "bar": no such variable}
test set-1.14 {TclCompileSetCmd: simple local name, >255 locals} {
    proc 260locals {} {
        # create 260 locals (the last ones with index > 255)
        set a0 0; set a1 0; set a2 0; set a3 0; set a4 0
        set a5 0; set a6 0; set a7 0; set a8 0; set a9 0
        set b0 0; set b1 0; set b2 0; set b3 0; set b4 0
        set b5 0; set b6 0; set b7 0; set b8 0; set b9 0
        set c0 0; set c1 0; set c2 0; set c3 0; set c4 0
        set c5 0; set c6 0; set c7 0; set c8 0; set c9 0
        set d0 0; set d1 0; set d2 0; set d3 0; set d4 0
        set d5 0; set d6 0; set d7 0; set d8 0; set d9 0
        set e0 0; set e1 0; set e2 0; set e3 0; set e4 0
        set e5 0; set e6 0; set e7 0; set e8 0; set e9 0
        set f0 0; set f1 0; set f2 0; set f3 0; set f4 0
        set f5 0; set f6 0; set f7 0; set f8 0; set f9 0
        set g0 0; set g1 0; set g2 0; set g3 0; set g4 0
        set g5 0; set g6 0; set g7 0; set g8 0; set g9 0
        set h0 0; set h1 0; set h2 0; set h3 0; set h4 0
        set h5 0; set h6 0; set h7 0; set h8 0; set h9 0
        set i0 0; set i1 0; set i2 0; set i3 0; set i4 0
        set i5 0; set i6 0; set i7 0; set i8 0; set i9 0
        set j0 0; set j1 0; set j2 0; set j3 0; set j4 0
        set j5 0; set j6 0; set j7 0; set j8 0; set j9 0
        set k0 0; set k1 0; set k2 0; set k3 0; set k4 0
        set k5 0; set k6 0; set k7 0; set k8 0; set k9 0
        set l0 0; set l1 0; set l2 0; set l3 0; set l4 0
        set l5 0; set l6 0; set l7 0; set l8 0; set l9 0
        set m0 0; set m1 0; set m2 0; set m3 0; set m4 0
        set m5 0; set m6 0; set m7 0; set m8 0; set m9 0
        set n0 0; set n1 0; set n2 0; set n3 0; set n4 0
        set n5 0; set n6 0; set n7 0; set n8 0; set n9 0
        set o0 0; set o1 0; set o2 0; set o3 0; set o4 0
        set o5 0; set o6 0; set o7 0; set o8 0; set o9 0
        set p0 0; set p1 0; set p2 0; set p3 0; set p4 0
        set p5 0; set p6 0; set p7 0; set p8 0; set p9 0
        set q0 0; set q1 0; set q2 0; set q3 0; set q4 0
        set q5 0; set q6 0; set q7 0; set q8 0; set q9 0
        set r0 0; set r1 0; set r2 0; set r3 0; set r4 0
        set r5 0; set r6 0; set r7 0; set r8 0; set r9 0
        set s0 0; set s1 0; set s2 0; set s3 0; set s4 0
        set s5 0; set s6 0; set s7 0; set s8 0; set s9 0
        set t0 0; set t1 0; set t2 0; set t3 0; set t4 0
        set t5 0; set t6 0; set t7 0; set t8 0; set t9 0
        set u0 0; set u1 0; set u2 0; set u3 0; set u4 0
        set u5 0; set u6 0; set u7 0; set u8 0; set u9 0
        set v0 0; set v1 0; set v2 0; set v3 0; set v4 0
        set v5 0; set v6 0; set v7 0; set v8 0; set v9 0
        set w0 0; set w1 0; set w2 0; set w3 0; set w4 0
        set w5 0; set w6 0; set w7 0; set w8 0; set w9 0
        set x0 0; set x1 0; set x2 0; set x3 0; set x4 0
        set x5 0; set x6 0; set x7 0; set x8 0; set x9 0
        set y0 0; set y1 0; set y2 0; set y3 0; set y4 0
        set y5 0; set y6 0; set y7 0; set y8 0; set y9 0
        set z0 0; set z1 0; set z2 0; set z3 0; set z4 0
        set z5 0; set z6 0; set z7 0; set z8 0; set z9 1234
	# create 260 locals (the last ones with index > 255)
	set a0 0; set a1 0; set a2 0; set a3 0; set a4 0
	set a5 0; set a6 0; set a7 0; set a8 0; set a9 0
	set b0 0; set b1 0; set b2 0; set b3 0; set b4 0
	set b5 0; set b6 0; set b7 0; set b8 0; set b9 0
	set c0 0; set c1 0; set c2 0; set c3 0; set c4 0
	set c5 0; set c6 0; set c7 0; set c8 0; set c9 0
	set d0 0; set d1 0; set d2 0; set d3 0; set d4 0
	set d5 0; set d6 0; set d7 0; set d8 0; set d9 0
	set e0 0; set e1 0; set e2 0; set e3 0; set e4 0
	set e5 0; set e6 0; set e7 0; set e8 0; set e9 0
	set f0 0; set f1 0; set f2 0; set f3 0; set f4 0
	set f5 0; set f6 0; set f7 0; set f8 0; set f9 0
	set g0 0; set g1 0; set g2 0; set g3 0; set g4 0
	set g5 0; set g6 0; set g7 0; set g8 0; set g9 0
	set h0 0; set h1 0; set h2 0; set h3 0; set h4 0
	set h5 0; set h6 0; set h7 0; set h8 0; set h9 0
	set i0 0; set i1 0; set i2 0; set i3 0; set i4 0
	set i5 0; set i6 0; set i7 0; set i8 0; set i9 0
	set j0 0; set j1 0; set j2 0; set j3 0; set j4 0
	set j5 0; set j6 0; set j7 0; set j8 0; set j9 0
	set k0 0; set k1 0; set k2 0; set k3 0; set k4 0
	set k5 0; set k6 0; set k7 0; set k8 0; set k9 0
	set l0 0; set l1 0; set l2 0; set l3 0; set l4 0
	set l5 0; set l6 0; set l7 0; set l8 0; set l9 0
	set m0 0; set m1 0; set m2 0; set m3 0; set m4 0
	set m5 0; set m6 0; set m7 0; set m8 0; set m9 0
	set n0 0; set n1 0; set n2 0; set n3 0; set n4 0
	set n5 0; set n6 0; set n7 0; set n8 0; set n9 0
	set o0 0; set o1 0; set o2 0; set o3 0; set o4 0
	set o5 0; set o6 0; set o7 0; set o8 0; set o9 0
	set p0 0; set p1 0; set p2 0; set p3 0; set p4 0
	set p5 0; set p6 0; set p7 0; set p8 0; set p9 0
	set q0 0; set q1 0; set q2 0; set q3 0; set q4 0
	set q5 0; set q6 0; set q7 0; set q8 0; set q9 0
	set r0 0; set r1 0; set r2 0; set r3 0; set r4 0
	set r5 0; set r6 0; set r7 0; set r8 0; set r9 0
	set s0 0; set s1 0; set s2 0; set s3 0; set s4 0
	set s5 0; set s6 0; set s7 0; set s8 0; set s9 0
	set t0 0; set t1 0; set t2 0; set t3 0; set t4 0
	set t5 0; set t6 0; set t7 0; set t8 0; set t9 0
	set u0 0; set u1 0; set u2 0; set u3 0; set u4 0
	set u5 0; set u6 0; set u7 0; set u8 0; set u9 0
	set v0 0; set v1 0; set v2 0; set v3 0; set v4 0
	set v5 0; set v6 0; set v7 0; set v8 0; set v9 0
	set w0 0; set w1 0; set w2 0; set w3 0; set w4 0
	set w5 0; set w6 0; set w7 0; set w8 0; set w9 0
	set x0 0; set x1 0; set x2 0; set x3 0; set x4 0
	set x5 0; set x6 0; set x7 0; set x8 0; set x9 0
	set y0 0; set y1 0; set y2 0; set y3 0; set y4 0
	set y5 0; set y6 0; set y7 0; set y8 0; set y9 0
	set z0 0; set z1 0; set z2 0; set z3 0; set z4 0
	set z5 0; set z6 0; set z7 0; set z8 0; set z9 1234
    }
    260locals
} {1234}
test set-1.15 {TclCompileSetCmd: variable is array} -setup {
    catch {unset a}
} -body {
    set x 27
259
260
261
262
263
264
265
266

267
268
269
270
271
272
273
259
260
261
262
263
264
265

266
267
268
269
270
271
272
273







-
+







    list [catch {set a(18)} msg] $msg
} -result {1 {can't read "a(18)": no such element in array}}
test set-2.4 {set command: runtime error, readonly variable} -setup {
    unset -nocomplain x
} -body {
    proc readonly args {error "variable is read-only"}
    set x 123
    trace var x w readonly
    trace add var x write readonly
    list [catch {set x 1} msg] $msg $::errorInfo
} -match glob -result {1 {can't set "x": variable is read-only} {*variable is read-only
    while executing
*
"set x 1"}}
test set-2.5 {set command: runtime error, basic array operations} -setup {
    unset -nocomplain a
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
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







-
-
-
+
+
+






-
-
+
+







-
+







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    $z i {one two}
    $z i
} {one two}

test set-3.11 {uncompiled set command: simple global name} {
    proc p {} {
	set z set
        global i
        $z i 54
        $z i
	global i
	$z i 54
	$z i
    }
    p
} {54}
test set-3.12 {uncompiled set command: simple local name} {
    proc p {bar} {
	set z set
        $z foo $bar
        $z foo
	$z foo $bar
	$z foo
    }
    p 999
} {999}
test set-3.13 {uncompiled set command: simple but new (unknown) local name} {
    set z set
    proc p {} {
	set z set
        $z bar
	$z bar
    }
    catch {p} msg
    $z msg
} {can't read "bar": no such variable}
test set-3.14 {uncompiled set command: simple local name, >255 locals} {
    proc 260locals {} {
	set z set
        # create 260 locals (the last ones with index > 255)
        $z a0 0; $z a1 0; $z a2 0; $z a3 0; $z a4 0
        $z a5 0; $z a6 0; $z a7 0; $z a8 0; $z a9 0
        $z b0 0; $z b1 0; $z b2 0; $z b3 0; $z b4 0
        $z b5 0; $z b6 0; $z b7 0; $z b8 0; $z b9 0
        $z c0 0; $z c1 0; $z c2 0; $z c3 0; $z c4 0
        $z c5 0; $z c6 0; $z c7 0; $z c8 0; $z c9 0
        $z d0 0; $z d1 0; $z d2 0; $z d3 0; $z d4 0
        $z d5 0; $z d6 0; $z d7 0; $z d8 0; $z d9 0
        $z e0 0; $z e1 0; $z e2 0; $z e3 0; $z e4 0
        $z e5 0; $z e6 0; $z e7 0; $z e8 0; $z e9 0
        $z f0 0; $z f1 0; $z f2 0; $z f3 0; $z f4 0
        $z f5 0; $z f6 0; $z f7 0; $z f8 0; $z f9 0
        $z g0 0; $z g1 0; $z g2 0; $z g3 0; $z g4 0
        $z g5 0; $z g6 0; $z g7 0; $z g8 0; $z g9 0
        $z h0 0; $z h1 0; $z h2 0; $z h3 0; $z h4 0
        $z h5 0; $z h6 0; $z h7 0; $z h8 0; $z h9 0
        $z i0 0; $z i1 0; $z i2 0; $z i3 0; $z i4 0
        $z i5 0; $z i6 0; $z i7 0; $z i8 0; $z i9 0
        $z j0 0; $z j1 0; $z j2 0; $z j3 0; $z j4 0
        $z j5 0; $z j6 0; $z j7 0; $z j8 0; $z j9 0
        $z k0 0; $z k1 0; $z k2 0; $z k3 0; $z k4 0
        $z k5 0; $z k6 0; $z k7 0; $z k8 0; $z k9 0
        $z l0 0; $z l1 0; $z l2 0; $z l3 0; $z l4 0
        $z l5 0; $z l6 0; $z l7 0; $z l8 0; $z l9 0
        $z m0 0; $z m1 0; $z m2 0; $z m3 0; $z m4 0
        $z m5 0; $z m6 0; $z m7 0; $z m8 0; $z m9 0
        $z n0 0; $z n1 0; $z n2 0; $z n3 0; $z n4 0
        $z n5 0; $z n6 0; $z n7 0; $z n8 0; $z n9 0
        $z o0 0; $z o1 0; $z o2 0; $z o3 0; $z o4 0
        $z o5 0; $z o6 0; $z o7 0; $z o8 0; $z o9 0
        $z p0 0; $z p1 0; $z p2 0; $z p3 0; $z p4 0
        $z p5 0; $z p6 0; $z p7 0; $z p8 0; $z p9 0
        $z q0 0; $z q1 0; $z q2 0; $z q3 0; $z q4 0
        $z q5 0; $z q6 0; $z q7 0; $z q8 0; $z q9 0
        $z r0 0; $z r1 0; $z r2 0; $z r3 0; $z r4 0
        $z r5 0; $z r6 0; $z r7 0; $z r8 0; $z r9 0
        $z s0 0; $z s1 0; $z s2 0; $z s3 0; $z s4 0
        $z s5 0; $z s6 0; $z s7 0; $z s8 0; $z s9 0
        $z t0 0; $z t1 0; $z t2 0; $z t3 0; $z t4 0
        $z t5 0; $z t6 0; $z t7 0; $z t8 0; $z t9 0
        $z u0 0; $z u1 0; $z u2 0; $z u3 0; $z u4 0
        $z u5 0; $z u6 0; $z u7 0; $z u8 0; $z u9 0
        $z v0 0; $z v1 0; $z v2 0; $z v3 0; $z v4 0
        $z v5 0; $z v6 0; $z v7 0; $z v8 0; $z v9 0
        $z w0 0; $z w1 0; $z w2 0; $z w3 0; $z w4 0
        $z w5 0; $z w6 0; $z w7 0; $z w8 0; $z w9 0
        $z x0 0; $z x1 0; $z x2 0; $z x3 0; $z x4 0
        $z x5 0; $z x6 0; $z x7 0; $z x8 0; $z x9 0
        $z y0 0; $z y1 0; $z y2 0; $z y3 0; $z y4 0
        $z y5 0; $z y6 0; $z y7 0; $z y8 0; $z y9 0
        $z z0 0; $z z1 0; $z z2 0; $z z3 0; $z z4 0
        $z z5 0; $z z6 0; $z z7 0; $z z8 0; $z z9 1234
	# create 260 locals (the last ones with index > 255)
	$z a0 0; $z a1 0; $z a2 0; $z a3 0; $z a4 0
	$z a5 0; $z a6 0; $z a7 0; $z a8 0; $z a9 0
	$z b0 0; $z b1 0; $z b2 0; $z b3 0; $z b4 0
	$z b5 0; $z b6 0; $z b7 0; $z b8 0; $z b9 0
	$z c0 0; $z c1 0; $z c2 0; $z c3 0; $z c4 0
	$z c5 0; $z c6 0; $z c7 0; $z c8 0; $z c9 0
	$z d0 0; $z d1 0; $z d2 0; $z d3 0; $z d4 0
	$z d5 0; $z d6 0; $z d7 0; $z d8 0; $z d9 0
	$z e0 0; $z e1 0; $z e2 0; $z e3 0; $z e4 0
	$z e5 0; $z e6 0; $z e7 0; $z e8 0; $z e9 0
	$z f0 0; $z f1 0; $z f2 0; $z f3 0; $z f4 0
	$z f5 0; $z f6 0; $z f7 0; $z f8 0; $z f9 0
	$z g0 0; $z g1 0; $z g2 0; $z g3 0; $z g4 0
	$z g5 0; $z g6 0; $z g7 0; $z g8 0; $z g9 0
	$z h0 0; $z h1 0; $z h2 0; $z h3 0; $z h4 0
	$z h5 0; $z h6 0; $z h7 0; $z h8 0; $z h9 0
	$z i0 0; $z i1 0; $z i2 0; $z i3 0; $z i4 0
	$z i5 0; $z i6 0; $z i7 0; $z i8 0; $z i9 0
	$z j0 0; $z j1 0; $z j2 0; $z j3 0; $z j4 0
	$z j5 0; $z j6 0; $z j7 0; $z j8 0; $z j9 0
	$z k0 0; $z k1 0; $z k2 0; $z k3 0; $z k4 0
	$z k5 0; $z k6 0; $z k7 0; $z k8 0; $z k9 0
	$z l0 0; $z l1 0; $z l2 0; $z l3 0; $z l4 0
	$z l5 0; $z l6 0; $z l7 0; $z l8 0; $z l9 0
	$z m0 0; $z m1 0; $z m2 0; $z m3 0; $z m4 0
	$z m5 0; $z m6 0; $z m7 0; $z m8 0; $z m9 0
	$z n0 0; $z n1 0; $z n2 0; $z n3 0; $z n4 0
	$z n5 0; $z n6 0; $z n7 0; $z n8 0; $z n9 0
	$z o0 0; $z o1 0; $z o2 0; $z o3 0; $z o4 0
	$z o5 0; $z o6 0; $z o7 0; $z o8 0; $z o9 0
	$z p0 0; $z p1 0; $z p2 0; $z p3 0; $z p4 0
	$z p5 0; $z p6 0; $z p7 0; $z p8 0; $z p9 0
	$z q0 0; $z q1 0; $z q2 0; $z q3 0; $z q4 0
	$z q5 0; $z q6 0; $z q7 0; $z q8 0; $z q9 0
	$z r0 0; $z r1 0; $z r2 0; $z r3 0; $z r4 0
	$z r5 0; $z r6 0; $z r7 0; $z r8 0; $z r9 0
	$z s0 0; $z s1 0; $z s2 0; $z s3 0; $z s4 0
	$z s5 0; $z s6 0; $z s7 0; $z s8 0; $z s9 0
	$z t0 0; $z t1 0; $z t2 0; $z t3 0; $z t4 0
	$z t5 0; $z t6 0; $z t7 0; $z t8 0; $z t9 0
	$z u0 0; $z u1 0; $z u2 0; $z u3 0; $z u4 0
	$z u5 0; $z u6 0; $z u7 0; $z u8 0; $z u9 0
	$z v0 0; $z v1 0; $z v2 0; $z v3 0; $z v4 0
	$z v5 0; $z v6 0; $z v7 0; $z v8 0; $z v9 0
	$z w0 0; $z w1 0; $z w2 0; $z w3 0; $z w4 0
	$z w5 0; $z w6 0; $z w7 0; $z w8 0; $z w9 0
	$z x0 0; $z x1 0; $z x2 0; $z x3 0; $z x4 0
	$z x5 0; $z x6 0; $z x7 0; $z x8 0; $z x9 0
	$z y0 0; $z y1 0; $z y2 0; $z y3 0; $z y4 0
	$z y5 0; $z y6 0; $z y7 0; $z y8 0; $z y9 0
	$z z0 0; $z z1 0; $z z2 0; $z z3 0; $z z4 0
	$z z5 0; $z z6 0; $z z7 0; $z z8 0; $z z9 1234
    }
    260locals
} {1234}
test set-3.15 {uncompiled set command: variable is array} {
    set z set
    catch {unset a}
    $z x 27
517
518
519
520
521
522
523
524

525
526
527
528
529
530
531
517
518
519
520
521
522
523

524
525
526
527
528
529
530
531







-
+







    $z a(6) 44
    list [catch {$z a(18)} msg] $msg
} -result {1 {can't read "a(18)": no such element in array}}
test set-4.4 {uncompiled set command: runtime error, readonly variable} -body {
    set z set
    proc readonly args {error "variable is read-only"}
    $z x 123
    trace var x w readonly
    trace add var x write readonly
    list [catch {$z x 1} msg] $msg $::errorInfo
} -match glob -result {1 {can't set "x": variable is read-only} {*variable is read-only
    while executing
*
"$z x 1"}}
test set-4.5 {uncompiled set command: runtime error, basic array operations} -setup {
    unset -nocomplain a

Changes to tests/socket.test.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







# Commands tested in this file: socket.
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 Ajuba Solutions.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-2000 Ajuba Solutions.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

# Running socket tests with a remote server:
# ------------------------------------------
#
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
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







-
+


+
+
-
+


-
+




+
-
+








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

::tcltest::loadTestedCommands
catch [list package require -exact Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]
::tcltest::loadTestedCommands

# A bad interaction between socket creation, macOS, and unattended CI
# environments make this whole file impractical to run; too many weird hangs.
if {[expr {[info exists ::env(TRAVIS_OSX_IMAGE)] && [string match xcode* $::env(TRAVIS_OSX_IMAGE)]}]} {
if {[info exists ::env(MAC_CI)]} {
    return
}
testConstraint notWine [expr {$::tcl_platform(platform) ne "windows" || ![info exists ::env(TRAVIS_OS_NAME)] || ![string match linux $::env(TRAVIS_OS_NAME)]}]
testConstraint notWine [expr {![info exists ::env(CI_USING_WINE)]}]

# Some tests require the Thread package or exec command
testConstraint thread [expr {0 == [catch {package require Thread 2.7-}]}]
testConstraint exec [llength [info commands exec]]
testConstraint notWinCI [expr {
testConstraint knownMsvcBug [expr {![info exists ::env(TRAVIS_OS_NAME)] || ![string match windows $::env(TRAVIS_OS_NAME)]}]
     $tcl_platform(platform) ne "windows" || ![info exists ::env(CI)]}]

# Produce a random port number in the Dynamic/Private range
# from 49152 through 65535.
proc randport {} {
    # firstly try dynamic port via server-socket(0):
    set port 0x7fffffff
    catch {
96
97
98
99
100
101
102
103
104
105



106
107
108
109
110
111
112
99
100
101
102
103
104
105



106
107
108
109
110
111
112
113
114
115







-
-
-
+
+
+







	set port [expr {int(rand()*16383+49152)}]
    }
    return $port
}

# Check if testsocket testflags is available
testConstraint testsocket_testflags [expr {![catch {
        set h [socket -async localhost [randport]]
        testsocket testflags $h 0
        close $h
	set h [socket -async localhost [randport]]
	testsocket testflags $h 0
	close $h
    }]}]


# Test the latency of tcp connections over the loopback interface. Some OSes
# (e.g. NetBSD) seem to use the Nagle algorithm and delayed ACKs, so it takes
# up to 200ms for a packet sent to localhost to arrive. We're measuring this
# here, so that OSes that don't have this problem can run the tests at full
120
121
122
123
124
125
126
127

128
129
130
131
132
133
134
123
124
125
126
127
128
129

130
131
132
133
134
135
136
137







-
+







puts $s2 test1; gets $s1
puts $s2 test2; gets $s1
close $s1; close $s2
set t2 [clock milliseconds]
set lat1 [expr {($t2-$t1)*2}]; # doubled as a safety margin

# Test the latency of failed connection attempts over the loopback
# interface. They can take more than a second under Windowos and requres
# interface. They can take more than a second under Windows and requires
# additional [after]s in some tests that are not needed on systems that fail
# immediately.
set t1 [clock milliseconds]
catch {socket 127.0.0.1 [randport]}
set t2 [clock milliseconds]
set lat2 [expr {($t2-$t1)*3}]

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
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







-
+

-
+






-
-
+
+







	set remoteServerIP $env(remoteServerIP)
    }
}
if {![info exists remoteServerPort]} {
    if {[info exists env(remoteServerPort)]} {
	set remoteServerPort $env(remoteServerPort)
    } else {
        if {[info exists remoteServerIP]} {
	if {[info exists remoteServerIP]} {
	    set remoteServerPort 2048
        }
	}
    }
}

if 0 {
    # activate this to time the tests
    proc test {args} {
        set name [lindex $args 0]
        puts "[lindex [time {uplevel [linsert $args 0 tcltest::test]}] 0] @@@ $name"
	set name [lindex $args 0]
	puts "[lindex [time {uplevel [linsert $args 0 tcltest::test]}] 0] @@@ $name"
    }
}

foreach {af localhost} {
    inet 127.0.0.1
    inet6 ::1
} {
182
183
184
185
186
187
188
189

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

192
193
194
195
196
197
198
199







-
+








foreach {af localhost} {
    any 127.0.0.1
    inet 127.0.0.1
    inet6 ::1
} {
    if {![testConstraint supported_$af]} {
        continue
	continue
    }
    set ::tcl::unsupported::socketAF $af
#
# Check if we're supposed to do tests against the remote server
#

set doTestsWithRemoteServer 1
246
247
248
249
250
251
252
253

254
255
256
257
258
259
260
249
250
251
252
253
254
255

256
257
258
259
260
261
262
263







-
+







    }
}

# Some tests are run only if we are doing testing against a remote server.
testConstraint doTestsWithRemoteServer $doTestsWithRemoteServer
if {!$doTestsWithRemoteServer} {
    if {[string first s $::tcltest::verbose] >= 0} {
    	puts "Skipping tests with remote server. See tests/socket.test for"
	puts "Skipping tests with remote server. See tests/socket.test for"
	puts "information on how to run remote server."
	puts "Reason for not doing remote tests: $noRemoteTestReason"
    }
}

#
# If we do the tests, define a command to send a command to the remote server.
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
366
367
368
369
370
371
372
373

374
375
376
377
378
379
380
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
366
367
368
369
370
371
372
373
374
375
376
377

378
379
380
381
382
383
384
385







-
+

-
+











+
+








-
+





-
+








-
+


-
+





-
+


-
+











-
+


-
+





-
+


-
+















-
+







	while {1} {
	    set line [gets $commandSocket]
	    if {[eof $commandSocket]} {
		error "remote server disappaered"
	    }
	    if {$line eq "--Marker--Marker--Marker--"} {
		lassign $result code info value
                return -code $code -errorinfo $info $value
		return -code $code -errorinfo $info $value
	    }
            append result $line "\n"
	    append result $line "\n"
	}
    }
}

proc getPort sock {
    lindex [fconfigure $sock -sockname] 2
}

# Some tests in this file are known to hang *occasionally* on OSX; stop the
# worst offenders.
testConstraint notOSX [expr {$::tcl_platform(os) ne "Darwin"}]
# Here "Windows" means derived platforms as Cygwin or Msys2 too.
testConstraint notWindows [expr {![regexp {^(Windows|MSYS|CYGWIN)} $::tcl_platform(os)]}]

# ----------------------------------------------------------------------

test socket_$af-1.1 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket -server
} -returnCodes error -result {no argument given for -server option}
test socket_$af-1.2 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket -server foo
} -returnCodes error -result {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-reuseaddr boolean? ?-reuseport boolean? ?-myaddr addr? port"}
} -returnCodes error -result {wrong # args: should be "socket ?-async? ?-myaddr addr? ?-myport myport? host port" or "socket -server command ?-backlog count? ?-myaddr addr? ?-reuseaddr boolean? ?-reuseport boolean? port"}
test socket_$af-1.3 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket -myaddr
} -returnCodes error -result {no argument given for -myaddr option}
test socket_$af-1.4 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket -myaddr $localhost
} -returnCodes error -result {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-reuseaddr boolean? ?-reuseport boolean? ?-myaddr addr? port"}
} -returnCodes error -result {wrong # args: should be "socket ?-async? ?-myaddr addr? ?-myport myport? host port" or "socket -server command ?-backlog count? ?-myaddr addr? ?-reuseaddr boolean? ?-reuseport boolean? port"}
test socket_$af-1.5 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket -myport
} -returnCodes error -result {no argument given for -myport option}
test socket_$af-1.6 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket -myport xxxx
} -returnCodes error -result {expected integer but got "xxxx"}
test socket_$af-1.7 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket -myport 2522
} -returnCodes error -result {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-reuseaddr boolean? ?-reuseport boolean? ?-myaddr addr? port"}
} -returnCodes error -result {wrong # args: should be "socket ?-async? ?-myaddr addr? ?-myport myport? host port" or "socket -server command ?-backlog count? ?-myaddr addr? ?-reuseaddr boolean? ?-reuseport boolean? port"}
test socket_$af-1.8 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket -froboz
} -returnCodes error -result {bad option "-froboz": must be -async, -myaddr, -myport, -reuseaddr, -reuseport, or -server}
} -returnCodes error -result {bad option "-froboz": must be -async, -backlog, -myaddr, -myport, -reuseaddr, -reuseport, or -server}
test socket_$af-1.9 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket -server foo -myport 2521 3333
} -returnCodes error -result {option -myport is not valid for servers}
test socket_$af-1.10 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket host 2528 -junk
} -returnCodes error -result {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-reuseaddr boolean? ?-reuseport boolean? ?-myaddr addr? port"}
} -returnCodes error -result {wrong # args: should be "socket ?-async? ?-myaddr addr? ?-myport myport? host port" or "socket -server command ?-backlog count? ?-myaddr addr? ?-reuseaddr boolean? ?-reuseport boolean? port"}
test socket_$af-1.11 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket -server callback 2520 --
} -returnCodes error -result {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-reuseaddr boolean? ?-reuseport boolean? ?-myaddr addr? port"}
} -returnCodes error -result {wrong # args: should be "socket ?-async? ?-myaddr addr? ?-myport myport? host port" or "socket -server command ?-backlog count? ?-myaddr addr? ?-reuseaddr boolean? ?-reuseport boolean? port"}
test socket_$af-1.12 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket foo badport
} -returnCodes error -result {expected integer but got "badport"}
test socket_$af-1.13 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket -async -server
} -returnCodes error -result {cannot set -async option for server sockets}
test socket_$af-1.14 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket -server foo -async
} -returnCodes error -result {cannot set -async option for server sockets}
test socket_$af-1.15 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket -reuseaddr yes 4242
} -returnCodes error -result {options -reuseaddr and -reuseport are only valid for servers}
} -returnCodes error -result {options -backlog, -reuseaddr, and -reuseport are only valid for servers}
test socket_$af-1.16 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket -reuseaddr no 4242
} -returnCodes error -result {options -reuseaddr and -reuseport are only valid for servers}
} -returnCodes error -result {options -backlog, -reuseaddr, and -reuseport are only valid for servers}
test socket_$af-1.17 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket -reuseaddr
} -returnCodes error -result {no argument given for -reuseaddr option}
test socket_$af-1.18 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket -reuseport yes 4242
} -returnCodes error -result {options -reuseaddr and -reuseport are only valid for servers}
} -returnCodes error -result {options -backlog, -reuseaddr, and -reuseport are only valid for servers}
test socket_$af-1.19 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket -reuseport no 4242
} -returnCodes error -result {options -reuseaddr and -reuseport are only valid for servers}
} -returnCodes error -result {options -backlog, -reuseaddr, and -reuseport are only valid for servers}
test socket_$af-1.20 {arg parsing for socket command} -constraints [list socket supported_$af] -body {
    socket -reuseport
} -returnCodes error -result {no argument given for -reuseport option}

set path(script) [makeFile {} script]

test socket_$af-2.1 {tcp connection} -constraints [list socket supported_$af stdio] -setup {
    file delete $path(script)
    set f [open $path(script) w]
    puts $f {
	set timer [after 10000 "set x timed_out"]
	set f [socket -server accept 0]
	proc accept {file addr port} {
	    global x
	    set x done
            close $file
	    close $file
	}
	puts ready
	puts [lindex [fconfigure $f -sockname] 2]
	vwait x
	after cancel $timer
	close $f
	puts $x
394
395
396
397
398
399
400
401

402
403
404
405
406




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

406
407




408
409
410
411
412
413
414
415
416
417
418







-
+

-
-
-
-
+
+
+
+







} -result {ready done {}}
test socket_$af-2.2 {tcp connection with client port specified} -setup {
    set port [randport]
    file delete $path(script)
    set f [open $path(script) w]
    puts $f {
	set timer [after 10000 "set x timeout"]
        set f [socket -server accept 0]
	set f [socket -server accept 0]
	proc accept {file addr port} {
            global x
            puts "[gets $file] $port"
            close $file
            set x done
	    global x
	    puts "[gets $file] $port"
	    close $file
	    set x done
	}
	puts ready
	puts [lindex [fconfigure $f -sockname] 2]
	vwait x
	after cancel $timer
	close $f
    }
428
429
430
431
432
433
434
435

436
437
438
439
440




441
442
443
444
445
446
447
433
434
435
436
437
438
439

440
441




442
443
444
445
446
447
448
449
450
451
452







-
+

-
-
-
-
+
+
+
+







    close $f
} -result {ready 1}
test socket_$af-2.3 {tcp connection with client interface specified} -setup {
    file delete $path(script)
    set f [open $path(script) w]
    puts $f {
	set timer [after 2000 "set x done"]
        set f [socket  -server accept 0]
	set f [socket  -server accept 0]
	proc accept {file addr port} {
            global x
            puts "[gets $file] $addr"
            close $file
            set x done
	    global x
	    puts "[gets $file] $addr"
	    close $file
	    set x done
	}
	puts [lindex [fconfigure $f -sockname] 2]
	puts ready
	vwait x
	after cancel $timer
	close $f
    }
462
463
464
465
466
467
468
469

470
471
472
473
474




475
476
477
478
479
480
481
467
468
469
470
471
472
473

474
475




476
477
478
479
480
481
482
483
484
485
486







-
+

-
-
-
-
+
+
+
+







} -result [list ready [list hello $localhost]]
test socket_$af-2.4 {tcp connection with server interface specified} -setup {
    file delete $path(script)
    set f [open $path(script) w]
    puts $f [list set localhost $localhost]
    puts $f {
	set timer [after 2000 "set x done"]
        set f [socket -server accept -myaddr $localhost 0]
	set f [socket -server accept -myaddr $localhost 0]
	proc accept {file addr port} {
            global x
            puts "[gets $file]"
            close $file
            set x done
	    global x
	    puts "[gets $file]"
	    close $file
	    set x done
	}
	puts ready
	puts [lindex [fconfigure $f -sockname] 2]
	vwait x
	after cancel $timer
	close $f
    }
495
496
497
498
499
500
501
502

503
504
505
506
507




508
509
510
511
512
513
514
500
501
502
503
504
505
506

507
508




509
510
511
512
513
514
515
516
517
518
519







-
+

-
-
-
-
+
+
+
+







    close $f
} -result {ready hello}
test socket_$af-2.5 {tcp connection with redundant server port} -setup {
    file delete $path(script)
    set f [open $path(script) w]
    puts $f {
	set timer [after 10000 "set x timeout"]
        set f [socket -server accept 0]
	set f [socket -server accept 0]
	proc accept {file addr port} {
            global x
            puts "[gets $file]"
            close $file
            set x done
	    global x
	    puts "[gets $file]"
	    close $file
	    set x done
	}
	puts ready
	puts [lindex [fconfigure $f -sockname] 2]
	vwait x
	after cancel $timer
	close $f
    }
540
541
542
543
544
545
546
547

548
549

550
551
552
553
554
555
556
557
558







559
560
561
562
563
564
565
545
546
547
548
549
550
551

552
553

554
555
556







557
558
559
560
561
562
563
564
565
566
567
568
569
570







-
+

-
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+







test socket_$af-2.7 {echo server, one line} -constraints [list socket supported_$af stdio] -setup {
    file delete $path(script)
    set f [open $path(script) w]
    puts $f {
	set timer [after 10000 "set x timeout"]
	set f [socket -server accept 0]
	proc accept {s a p} {
            fileevent $s readable [list echo $s]
	    fileevent $s readable [list echo $s]
	    fconfigure $s -translation lf -buffering line
        }
	}
	proc echo {s} {
	     set l [gets $s]
             if {[eof $s]} {
                 global x
                 close $s
                 set x done
             } else {
                 puts $s $l
             }
	     if {[eof $s]} {
		 global x
		 close $s
		 set x done
	     } else {
		 puts $s $l
	     }
	}
	puts ready
	puts [lindex [fconfigure $f -sockname] 2]
	vwait x
	after cancel $timer
	close $f
	puts $x
579
580
581
582
583
584
585
586
587
588



589
590
591
592
593
594
595
596
597
598
599









600
601
602
603
604
605
606
584
585
586
587
588
589
590



591
592
593
594
595









596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611







-
-
-
+
+
+


-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+







    close $f
} -result {{hello abcdefghijklmnop} done}
removeFile script
test socket_$af-2.8 {echo server, loop 50 times, single connection} -setup {
    set path(script) [makeFile {
	set f [socket -server accept 0]
	proc accept {s a p} {
            fileevent $s readable [list echo $s]
            fconfigure $s -buffering line
        }
	    fileevent $s readable [list echo $s]
	    fconfigure $s -buffering line
	}
	proc echo {s} {
	     global i
             set l [gets $s]
             if {[eof $s]} {
                 global x
                 close $s
                 set x done
             } else {
	         incr i
                 puts $s $l
             }
	     set l [gets $s]
	     if {[eof $s]} {
		 global x
		 close $s
		 set x done
	     } else {
		 incr i
		 puts $s $l
	     }
	}
	set i 0
	puts ready
	puts [lindex [fconfigure $f -sockname] 2]
	set timer [after 20000 "set x done"]
	vwait x
	after cancel $timer
810
811
812
813
814
815
816
817
818
819
820
821
822
823







824
825
826
827
828
829
830
815
816
817
818
819
820
821







822
823
824
825
826
827
828
829
830
831
832
833
834
835







-
-
-
-
-
-
-
+
+
+
+
+
+
+







	set s [socket -server accept -myaddr $localhost 0]
	proc accept {s a p} {
	    fileevent $s readable [list echo $s]
	    fconfigure $s -buffering line
	}
	proc echo {s} {
	     global x
             set l [gets $s]
             if {[eof $s]} {
                 close $s
                 set x done
             } else {
                 puts $s $l
             }
	     set l [gets $s]
	     if {[eof $s]} {
		 close $s
		 set x done
	     } else {
		 puts $s $l
	     }
	}
	puts ready
	puts [lindex [fconfigure $s -sockname] 2]
	vwait x
	after cancel $t1
	vwait x
	after cancel $t2
887
888
889
890
891
892
893
894
895
896
897
898
899
900







901
902
903
904
905
906
907
892
893
894
895
896
897
898







899
900
901
902
903
904
905
906
907
908
909
910
911
912







-
-
-
-
-
-
-
+
+
+
+
+
+
+







} -constraints [list socket supported_$af stdio] -body {
    proc accept {s a p} {
	fconfigure $s -buffering line
	fileevent $s readable [list echo $s]
    }
    proc echo {s} {
	global x
        set l [gets $s]
        if {[eof $s]} {
            close $s
            set x done
        } else {
            puts $s $l
        }
	set l [gets $s]
	if {[eof $s]} {
	    close $s
	    set x done
	} else {
	    puts $s $l
	}
    }
    set t1 [after 30000 "set x timed_out"]
    set t2 [after 31000 "set x timed_out"]
    set t3 [after 32000 "set x timed_out"]
    set s [socket -server accept -myaddr $localhost 0]
    set listen [lindex [fconfigure $s -sockname] 2]
    puts $p1 $listen
930
931
932
933
934
935
936
937

938
939
940

941
942
943
944
945
946
947
948
949
950
951
952
953
954

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972

973
974
975
976
977
978
979
935
936
937
938
939
940
941

942
943
944

945
946
947
948
949
950
951
952
953
954
955
956
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







-
+


-
+













-
+

















-
+







    close [socket -server dodo -myaddr $localhost 0x3000]
    return ok
} -constraints [list socket supported_$af] -result ok

test socket_$af-5.1 {byte order problems, socket numbers, htons} -body {
    if {![catch {socket -server dodo 0x1} msg]} {
	close $msg
        return {htons problem, should be disallowed, are you running as SU?}
	return {htons problem, should be disallowed, are you running as SU?}
    }
    return {couldn't open socket: not owner}
} -constraints [list socket supported_$af unix notRoot notOSX] -result {couldn't open socket: not owner}
} -constraints [list socket supported_$af unix notRoot notOSX notWindows] -result {couldn't open socket: not owner}
test socket_$af-5.2 {byte order problems, socket numbers, htons} -body {
    if {![catch {socket -server dodo 0x10000} msg]} {
	close $msg
	return {port resolution problem, should be disallowed}
    }
    return {couldn't open socket: port number too high}
} -constraints [list socket supported_$af] -result {couldn't open socket: port number too high}
test socket_$af-5.3 {byte order problems, socket numbers, htons} -body {
    if {![catch {socket -server dodo 21} msg]} {
	close $msg
	return {htons problem, should be disallowed, are you running as SU?}
    }
    return {couldn't open socket: not owner}
} -constraints [list socket supported_$af unix notRoot notOSX] -result {couldn't open socket: not owner}
} -constraints [list socket supported_$af unix notRoot notOSX notWindows] -result {couldn't open socket: not owner}

test socket_$af-6.1 {accept callback error} -constraints [list socket supported_$af stdio] -setup {
    proc myHandler {msg options} {
	variable x $msg
    }
    set handler [interp bgerror {}]
    interp bgerror {} [namespace which myHandler]
    file delete $path(script)
} -body {
    set f [open $path(script) w]
    puts $f [list set localhost $localhost]
    puts $f {
	gets stdin port
	socket $localhost $port
    }
    close $f
    set f [open "|[list [interpreter] $path(script)]" r+]
    proc accept {s a p} {expr 10 / 0}
    proc accept {s a p} {expr {10 / 0}}
    set s [socket -server accept -myaddr $localhost 0]
    puts $f [lindex [fconfigure $s -sockname] 2]
    close $f
    set timer [after 10000 "set x timed_out"]
    vwait x
    after cancel $timer
    close $s
1062
1063
1064
1065
1066
1067
1068
1069

1070
1071
1072
1073
1074
1075
1076
1067
1068
1069
1070
1071
1072
1073

1074
1075
1076
1077
1078
1079
1080
1081







-
+







} -result {3 1 0}
test socket_$af-7.3 {testing socket specific options} -constraints [list socket supported_$af] -body {
    set s [socket -server accept -myaddr $localhost 0]
    set l [fconfigure $s]
    close $s
    update
    llength $l
} -result 14
} -result 20
test socket_$af-7.4 {testing socket specific options} -constraints [list socket supported_$af] -setup {
    set timer [after 10000 "set x timed_out"]
    set l ""
} -body {
    set s [socket -server accept -myaddr $localhost 0]
    proc accept {s a p} {
	global x
1101
1102
1103
1104
1105
1106
1107



















1108
1109
1110
1111
1112
1113
1114
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    vwait x
    lappend l [lindex $x 0] [expr {[lindex $x 2] == $listen}] [llength $x]
} -cleanup {
    after cancel $timer
    close $s
    close $s1
} -result [list $localhost 1 3]
test socket_$af-7.6 {testing socket specific options - bug e589d9bdab} -setup {
    set timer [after 10000 "set x timed_out"]
    set l ""
} -constraints [list socket supported_$af unixOrWin] -body {
    set s [socket -server accept 0]
    proc accept {s a p} {
	global x
	set x [fconfigure $s -sockname]
	close $s
    }
    set listen [lindex [fconfigure $s -sockname] 2]
    set s1 [socket $localhost $listen]
    vwait x
    lsort [dict keys [fconfigure $s1]]
} -cleanup {
    after cancel $timer
    close $s
    close $s1
} -result {-blocking -buffering -buffersize -encoding -eofchar -keepalive -nodelay -peername -profile -sockname -translation}

test socket_$af-8.1 {testing -async flag on sockets} -constraints [list socket supported_$af] -body {
    # NOTE: This test may fail on some Solaris 2.4 systems. If it does, check
    # that you have these patches installed (using showrev -p):
    #
    # 101907-05, 101925-02, 101945-14, 101959-03, 101969-05, 101973-03,
    # 101977-03, 101981-02, 101985-01, 102001-03, 102003-01, 102007-01,
1471
1472
1473
1474
1475
1476
1477
1478

1479
1480
1481
1482
1483
1484
1485
1495
1496
1497
1498
1499
1500
1501

1502
1503
1504
1505
1506
1507
1508
1509







-
+







    proc accept {s a p} {expr {10 / 0}}
    sendCommand "set port [getPort $s]"
    if {[catch {
	sendCommand {
	    set peername [fconfigure $callerSocket -peername]
	    set s [socket [lindex $peername 0] $port]
	    close $s
    	 }
	}
    } msg]} then {
	close $s
	error $msg
    }
    vwait x
    return $x
} -cleanup {
1661
1662
1663
1664
1665
1666
1667
1668

1669
1670
1671
1672
1673
1674
1675
1685
1686
1687
1688
1689
1690
1691

1692
1693
1694
1695
1696
1697
1698
1699







-
+







	set f [socket -server accept -myaddr $localhost 0]
	proc accept { file addr port } {
	    close $file
	}
	exec $tcltest $delay &
	puts [lindex [fconfigure $f -sockname] 2]
	close $f
        exit
	exit
    }
    close $f
} -constraints [list socket supported_$af stdio exec] -body {
    # Launch script2 and wait 5 seconds
    ### exec [interpreter] script2 &
    set p [open "|[list [interpreter] $path(script2)]" r]
    # If we can still connect to the server, the socket got inherited.
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
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

1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759

1760
1761
1762
1763
1764
1765
1766
1767







-
+

-
+


-
+















-
+










-
+







    # script1 and exits. If the child process inherited the client socket, the
    # socket will still be open.
    set f [open $path(script2) w]
    puts $f [list set tcltest [interpreter]]
    puts $f [list set delay $path(script1)]
    puts $f [list set localhost $localhost]
    puts $f {
        gets stdin port
	gets stdin port
	set f [socket $localhost $port]
        exec $tcltest $delay &
	exec $tcltest $delay &
	puts $f testing
	flush $f
        exit
	exit
    }
    close $f
    # If the socket doesn't hit end-of-file in 10 seconds, the script1 process
    # must have inherited the client.
    set timeout 0
    set after [after 10000 {set x "client socket was inherited"}]
} -constraints [list socket supported_$af stdio exec] -body {
    # Create the server socket
    set server [socket -server accept -myaddr $localhost 0]
    proc accept { file host port } {
	# When the client connects, establish the read handler
	global server
	close $server
	fileevent $file readable [list getdata $file]
	fconfigure $file -buffering line -blocking 0
        set ::f $file
	set ::f $file
    }
    proc getdata { file } {
	# Read handler on the accepted socket.
	global x
	set status [catch {read $file} data]
	if {$status != 0} {
	    set x "read failed, error was $data"
	} elseif {$data ne ""} {
	} elseif {[fblocked $file]} {
	} elseif {[eof $file]} {
            set x "client socket was not inherited"
	    set x "client socket was not inherited"
	} else {
	    set x "impossible case"
	}
    }
    # Launch the script2 process
    ### exec [interpreter] script2 &
    set p [open "|[list [interpreter] $path(script2)]" w]
1766
1767
1768
1769
1770
1771
1772
1773

1774
1775
1776
1777
1778
1779
1780
1790
1791
1792
1793
1794
1795
1796

1797
1798
1799
1800
1801
1802
1803
1804







-
+







    puts $f [list set localhost $localhost]
    puts $f {
	set server [socket -server accept -myaddr $localhost 0]
	proc accept { file host port } {
	    global tcltest delay
	    puts $file {test data on socket}
	    exec $tcltest $delay &
            after idle exit
	    after idle exit
	}
	puts stdout [lindex [fconfigure $server -sockname] 2]
	vwait forever
    }
    close $f
} -constraints [list socket supported_$af stdio exec] -body {
    # Launch the script2 process and connect to it. See how long the socket
1795
1796
1797
1798
1799
1800
1801
1802

1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840





















1841
1842
1843
1844
1845
1846
1847


1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862

1863
1864
1865
1866
1867

1868
1869
1870

1871
1872
1873
1874
1875
1876

1877
1878
1879
1880
1881
1882
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
1819
1820
1821
1822
1823
1824
1825

1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843





















1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869


1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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

1958
1959
1960
1961
1962
1963
1964
1965







-
+

















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
-
+
+














-
+




-
+


-
+





-
+




-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+



-
+

-
+


-
-
-
+
+
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+







-
-
-
+
+
+


-
+








-
+







	global failed
	set status [catch {read $file} data]
	if {$status != 0} {
	    set x "read failed, error was $data"
	} elseif {[string compare {} $data]} {
	} elseif {[fblocked $file]} {
	} elseif {[eof $file]} {
            set x "accepted socket was not inherited"
	    set x "accepted socket was not inherited"
	} else {
	    set x "impossible case"
	}
	return
    }
    vwait x
    set x
} -cleanup {
    fconfigure $f -blocking 1
    close $f
    after cancel $after
    close $p
} -result {accepted socket was not inherited}

test socket_$af-13.1 {Testing use of shared socket between two threads} -body {
    # create a thread
    set serverthread [thread::create -preserved [string map [list @localhost@ $localhost] {
        set f [socket -server accept -myaddr @localhost@ 0]
        set listen [lindex [fconfigure $f -sockname] 2]
        proc accept {s a p} {
            fileevent $s readable [list echo $s]
            fconfigure $s -buffering line
        }
        proc echo {s} {
             global i
             set l [gets $s]
             if {[eof $s]} {
                 global x
                 close $s
                 set x done
             } else {
                 incr i
                 puts $s $l
             }
        }
        set i 0
        vwait x
        close $f
	set f [socket -server accept -myaddr @localhost@ 0]
	set listen [lindex [fconfigure $f -sockname] 2]
	proc accept {s a p} {
	    fileevent $s readable [list echo $s]
	    fconfigure $s -buffering line
	}
	proc echo {s} {
	     global i
	     set l [gets $s]
	     if {[eof $s]} {
		 global x
		 close $s
		 set x done
	     } else {
		 incr i
		 puts $s $l
	     }
	}
	set i 0
	vwait x
	close $f
    }]]
    set port [thread::send $serverthread {set listen}]
    set s [socket $localhost $port]
    fconfigure $s -buffering line
    catch {
        puts $s "hello"
        gets $s result
	puts $s "hello"
	gets $s result
    }
    close $s
    thread::release $serverthread
    append result " " [llength [thread::names]]
} -result {hello 1} -constraints [list socket supported_$af thread]

proc transf_test {{testmode transfer} {maxIter 1000} {maxTime 10000}} {
  try {
    set ::count 0
    set ::testmode $testmode
    set port 0
    set srvsock {}
    # if binding on port 0 is not possible (system related, blocked on ISPs etc):
    if {[catch {close [socket -async $::localhost $port]}]} {
      # simplest server on random port (immediatelly closing a connect):
      # simplest server on random port (immediately closing a connect):
      set port [randport]
      set srvsock [socket -server {apply {{ch args} {close $ch}}} -myaddr $::localhost $port]
      # socket on windows has some issues yet (e. g. bug [b6d0d8cc2c]), so we simply decrease iteration count (to 1/4):
      if {$::tcl_platform(platform) eq "windows" && $maxIter > 50} {
      	set ::count [expr {$maxIter / 4 * 3 - 1}]; # bypass 3/4 iterations
	set ::count [expr {$maxIter / 4 * 3 - 1}]; # bypass 3/4 iterations
      }
    }
    tcltest::DebugPuts 1 "== test \[$::localhost\]:$port $testmode =="
    tcltest::DebugPuts 2 "== test \[$::localhost\]:$port $testmode =="
    set ::parent [thread::id]
    # helper thread creating async connection and initiating transfer (detach) to parent:
    set ::helper [thread::create]
    thread::send -async $::helper [list \
      lassign [list $::parent $::localhost $port $testmode] \
                     ::parent ::localhost ::port ::testmode
		     ::parent ::localhost ::port ::testmode
    ]
    thread::send -async $::helper {
      set ::helper [thread::id]
      proc iteration {args} {
        set fd [socket -async $::localhost $::port]
        if {"helper-writable" in $::testmode} {;# to test both sides during connect
          fileevent $fd writable [list apply {{fd} {
            if {[thread::id] ne $::helper} {
              thread::send -async $::parent {set ::count "ERROR: invalid thread, $::helper is expecting"}
              close $fd
              return
            }
          }} $fd]
        };#
        thread::detach $fd
        thread::send -async $::parent [list transf_parent $fd {*}$args]
	set fd [socket -async $::localhost $::port]
	if {"helper-writable" in $::testmode} {;# to test both sides during connect
	  fileevent $fd writable [list apply {{fd} {
	    if {[thread::id] ne $::helper} {
	      thread::send -async $::parent {set ::count "ERROR: invalid thread, $::helper is expecting"}
	      close $fd
	      return
	    }
	  }} $fd]
	};#
	thread::detach $fd
	thread::send -async $::parent [list transf_parent $fd {*}$args]
      }
      iteration first
    }
    # parent proc commiting transfer attempt (attach) and checking acquire was successful:
    # parent proc committing transfer attempt (attach) and checking acquire was successful:
    proc transf_parent {fd args} {
      tcltest::DebugPuts 1 "** trma / $::count ** $args **"
      tcltest::DebugPuts 2 "** trma / $::count ** $args **"
      thread::attach $fd
      if {"parent-close" in $::testmode} {;# to test close during connect
        set ::count $::count
        close $fd
        return
	set ::count $::count
	close $fd
	return
      };#
      fileevent $fd writable [list apply {{fd} {
        if {[thread::id] ne $::parent} {
          thread::send -async $::parent {set ::count "ERROR: invalid thread, $::parent is expecting"}
          close $fd
          return
        }
        set ::count $::count
        close $fd
	if {[thread::id] ne $::parent} {
	  thread::send -async $::parent {set ::count "ERROR: invalid thread, $::parent is expecting"}
	  close $fd
	  return
	}
	set ::count $::count
	close $fd
      }} $fd]
    }
    # repeat maxIter times (up to maxTime ms as timeout):
    set tout [after $maxTime {set ::count "TIMEOUT"}]
    while 1 {
      vwait ::count
      if {![string is integer $::count]} {
        # if timeout just skip (test was successful until now):
      	if {$::count eq "TIMEOUT"} {::tcltest::Skip "timing issue"}
        break
	# if timeout just skip (test was successful until now):
	if {$::count eq "TIMEOUT"} {::tcltest::Skip "timing issue"}
	break
      }
      if {[incr ::count] >= $maxIter} break
      tcltest::DebugPuts 1 "** iter / $::count **"
      tcltest::DebugPuts 2 "** iter / $::count **"
      thread::send -async $::helper [list iteration nr $::count]
    }
    update
    set ::count
  } finally {
    catch {after cancel $tout}
    if {$srvsock ne {}} {close $srvsock}
    if {[info exists ::helper]} {thread::release -wait $::helper}
    tcltest::DebugPuts 1 "== stop / $::count =="
    tcltest::DebugPuts 2 "== stop / $::count =="
    unset -nocomplain ::count ::testmode ::parent ::helper
  }
}
test socket_$af-13.2.tr1 {Testing socket transfer between threads during async connect} -body {
    transf_test {transfer} 1000
} -result 1000 -constraints [list socket supported_$af thread]
test socket_$af-13.2.tr2 {Testing socket transfer between threads during async connect} -body {
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976








1977
1978
1979
1980
1981




1982
1983
1984
1985
1986




1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998








1999
2000
2001
2002
2003




2004
2005
2006
2007
2008




2009
2010
2011
2012
2013
2014
2015
2016




2017
2018
2019
2020
2021




2022
2023
2024
2025



2026
2027
2028
2029
2030
2031
2032






2033
2034
2035
2036
2037




2038
2039
2040
2041
2042
2043
2044
2045
2046
2047






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
2095
2096











2097
2098
2099
2100
2101




2102
2103
2104
2105
2106
2107
2108


2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123









2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135










2136
2137
2138
2139
2140



2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154









2155
2156
2157
2158
2159
2160
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



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
2273
2274


2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286







2287
2288
2289


2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303











2304
2305
2306
2307
2308




2309
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


2390
2391
2392
2393

2394
2395
2396
2397
2398
2399
2400






2401
2402
2403
2404



2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419












2420
2421
2422
2423



2424
2425
2426
2427
2428
2429
2430
2431
2432
2433







2434
2435
2436


2437
2438
2439
2440
2441
2442
2443
2444
2445

2446
2447
2448
2449
2450
2451
2452
1986
1987
1988
1989
1990
1991
1992








1993
1994
1995
1996
1997
1998
1999
2000
2001




2002
2003
2004
2005
2006




2007
2008
2009
2010
2011
2012
2013
2014








2015
2016
2017
2018
2019
2020
2021
2022
2023




2024
2025
2026
2027
2028




2029
2030
2031
2032
2033
2034
2035
2036




2037
2038
2039
2040
2041




2042
2043
2044
2045
2046



2047
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
2095
2096
2097
2098
2099
2100
2101







2102
2103
2104
2105
2106
2107
2108
2109











2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121




2122
2123
2124
2125
2126
2127
2128
2129
2130


2131
2132
2133
2134
2135
2136
2137
2138









2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149










2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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










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
2273
2274
2275
2276
2277










2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288







2289
2290
2291
2292
2293
2294
2295
2296


2297
2298
2299
2300
2301
2302
2303







2304
2305
2306
2307
2308
2309
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
2390
2391











2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403







2404
2405
2406
2407
2408
2409
2410
2411


2412
2413
2414
2415
2416

2417
2418






2419
2420
2421
2422
2423
2424
2425



2426
2427
2428
2429
2430
2431












2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444



2445
2446
2447
2448
2449
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







-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+




-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+




-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
+
+
+
+




-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
+
+
+




-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+




-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+





-
-
+
+






-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+


-
-
-
+
+
+





-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+


-
-
-
+
+
+





-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
+
+

-
-
+
+





-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
+
+

-
-
+
+





-
-
-
+
+
+

-
-
+
+



-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+





-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+





-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+



-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
+
+





-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
+
+





-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+





-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+



-
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
+
+
+



-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+



-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+








-
+







catch {close $commandSocket}
catch {close $remoteProcChan}
}
unset ::tcl::unsupported::socketAF
test socket-14.0.0 {[socket -async] when server only listens on IPv4} \
    -constraints {socket supported_inet localhost_v4} \
    -setup {
        proc accept {s a p} {
            global x
            puts $s bye
            close $s
            set x ok
        }
        set server [socket -server accept -myaddr 127.0.0.1 0]
        set port [lindex [fconfigure $server -sockname] 2]
	proc accept {s a p} {
	    global x
	    puts $s bye
	    close $s
	    set x ok
	}
	set server [socket -server accept -myaddr 127.0.0.1 0]
	set port [lindex [fconfigure $server -sockname] 2]
    } -body {
        set client [socket -async localhost $port]
        set after [after $latency {set x [fconfigure $client -error]}]
        vwait x
        set x
	set client [socket -async localhost $port]
	set after [after $latency {set x [fconfigure $client -error]}]
	vwait x
	set x
    } -cleanup {
        after cancel $after
        close $server
        close $client
        unset x
	after cancel $after
	close $server
	close $client
	unset x
    } -result ok
test socket-14.0.1 {[socket -async] when server only listens on IPv6} \
    -constraints {socket supported_inet6 localhost_v6} \
    -setup {
        proc accept {s a p} {
            global x
            puts $s bye
            close $s
            set x ok
        }
        set server [socket -server accept -myaddr ::1 0]
        set port [lindex [fconfigure $server -sockname] 2]
	proc accept {s a p} {
	    global x
	    puts $s bye
	    close $s
	    set x ok
	}
	set server [socket -server accept -myaddr ::1 0]
	set port [lindex [fconfigure $server -sockname] 2]
    } -body {
        set client [socket -async localhost $port]
        set after [after $latency {set x [fconfigure $client -error]}]
        vwait x
        set x
	set client [socket -async localhost $port]
	set after [after $latency {set x [fconfigure $client -error]}]
	vwait x
	set x
    } -cleanup {
        after cancel $after
        close $server
        close $client
        unset x
	after cancel $after
	close $server
	close $client
	unset x
    } -result ok
test socket-14.1 {[socket -async] fileevent while still connecting} \
    -constraints {socket} \
    -setup {
        proc accept {s a p} {
            global x
            puts $s bye
            close $s
	proc accept {s a p} {
	    global x
	    puts $s bye
	    close $s
	    lappend x ok
        }
        set server [socket -server accept -myaddr localhost 0]
        set port [lindex [fconfigure $server -sockname] 2]
        set x ""
	}
	set server [socket -server accept -myaddr localhost 0]
	set port [lindex [fconfigure $server -sockname] 2]
	set x ""
    } -body {
        set client [socket -async localhost $port]
        fileevent $client writable {
            lappend x [fconfigure $client -error]
	set client [socket -async localhost $port]
	fileevent $client writable {
	    lappend x [fconfigure $client -error]
	    fileevent $client writable {}
        }
        set after [after $latency {lappend x timeout}]
        while {[llength $x] < 2 && "timeout" ni $x} {
            vwait x
        }
        lsort $x; # we only want to see both events, the order doesn't matter
	}
	set after [after $latency {lappend x timeout}]
	while {[llength $x] < 2 && "timeout" ni $x} {
	    vwait x
	}
	lsort $x; # we only want to see both events, the order doesn't matter
    } -cleanup {
        after cancel $after
        close $server
        close $client
        unset x
	after cancel $after
	close $server
	close $client
	unset x
    } -result {{} ok}
test socket-14.2 {[socket -async] fileevent connection refused} \
    -constraints {socket} \
    -body {
        set client [socket -async localhost [randport]]
        fileevent $client writable {set x ok}
        set after [after $latency {set x timeout}]
        vwait x
        after cancel $after
        lappend x [fconfigure $client -error]
	set client [socket -async localhost [randport]]
	fileevent $client writable {set x ok}
	set after [after $latency {set x timeout}]
	vwait x
	after cancel $after
	lappend x [fconfigure $client -error]
    } -cleanup {
        after cancel $after
        close $client
        unset x after client
	after cancel $after
	close $client
	unset x after client
    } -result {ok {connection refused}}
test socket-14.3 {[socket -async] when server only listens on IPv6} \
    -constraints {socket supported_inet6 localhost_v6} \
    -setup {
        proc accept {s a p} {
            global x
            puts $s bye
            close $s
            set x ok
        }
        set server [socket -server accept -myaddr ::1 0]
        set port [lindex [fconfigure $server -sockname] 2]
	proc accept {s a p} {
	    global x
	    puts $s bye
	    close $s
	    set x ok
	}
	set server [socket -server accept -myaddr ::1 0]
	set port [lindex [fconfigure $server -sockname] 2]
    } -body {
        set client [socket -async localhost $port]
        set after [after $latency {set x [fconfigure $client -error]}]
        vwait x
        set x
	set client [socket -async localhost $port]
	set after [after $latency {set x [fconfigure $client -error]}]
	vwait x
	set x
    } -cleanup {
        after cancel $after
        close $server
        close $client
        unset x
	after cancel $after
	close $server
	close $client
	unset x
    } -result ok
test socket-14.4 {[socket -async] and both, readdable and writable fileevents} \
    -constraints {socket} \
    -setup {
        proc accept {s a p} {
            puts $s bye
            close $s
        }
        set server [socket -server accept -myaddr localhost 0]
        set port [lindex [fconfigure $server -sockname] 2]
        set x ""
	proc accept {s a p} {
	    puts $s bye
	    close $s
	}
	set server [socket -server accept -myaddr localhost 0]
	set port [lindex [fconfigure $server -sockname] 2]
	set x ""
    } -body {
        set client [socket -async localhost $port]
        fileevent $client writable {
            lappend x [fconfigure $client -error]
            fileevent $client writable {}
        }
        fileevent $client readable {lappend x [gets $client]}
        set after [after $latency {lappend x timeout}]
        while {[llength $x] < 2 && "timeout" ni $x} {
            vwait x
        }
        lsort $x
	set client [socket -async localhost $port]
	fileevent $client writable {
	    lappend x [fconfigure $client -error]
	    fileevent $client writable {}
	}
	fileevent $client readable {lappend x [gets $client]}
	set after [after $latency {lappend x timeout}]
	while {[llength $x] < 2 && "timeout" ni $x} {
	    vwait x
	}
	lsort $x
    } -cleanup {
        after cancel $after
        close $client
        close $server
        unset x
	after cancel $after
	close $client
	close $server
	unset x
    } -result {{} bye}
# FIXME: we should also have an IPv6 counterpart of this
test socket-14.5 {[socket -async] which fails before any connect() can be made} \
    -constraints {socket supported_inet notWine} \
    -body {
        # address from rfc5737
        socket -async -myaddr 192.0.2.42 127.0.0.1 [randport]
	# address from rfc5737
	socket -async -myaddr 192.0.2.42 127.0.0.1 [randport]
    } \
    -returnCodes 1 \
    -result {couldn't open socket: cannot assign requested address}
test socket-14.6.0 {[socket -async] with no event loop and server listening on IPv4} \
    -constraints {socket supported_inet localhost_v4} \
    -setup {
        proc accept {s a p} {
            global x
            puts $s bye
            close $s
            set x ok
        }
        set server [socket -server accept -myaddr 127.0.0.1 0]
        set port [lindex [fconfigure $server -sockname] 2]
        set x ""
	proc accept {s a p} {
	    global x
	    puts $s bye
	    close $s
	    set x ok
	}
	set server [socket -server accept -myaddr 127.0.0.1 0]
	set port [lindex [fconfigure $server -sockname] 2]
	set x ""
    } \
    -body {
        set client [socket -async localhost $port]
        for {set i 0} {$i < 50} {incr i } {
            update
            if {$x ne ""} {
                lappend x [gets $client]
                break
            }
            after 100
        }
        set x
	set client [socket -async localhost $port]
	for {set i 0} {$i < 50} {incr i } {
	    update
	    if {$x ne ""} {
		lappend x [gets $client]
		break
	    }
	    after 100
	}
	set x
    } \
    -cleanup {
        close $server
        close $client
        unset x
	close $server
	close $client
	unset x
    } \
    -result {ok bye}
test socket-14.6.1 {[socket -async] with no event loop and server listening on IPv6} \
    -constraints {socket supported_inet6 localhost_v6} \
    -setup {
        proc accept {s a p} {
            global x
            puts $s bye
            close $s
            set x ok
        }
        set server [socket -server accept -myaddr ::1 0]
        set port [lindex [fconfigure $server -sockname] 2]
        set x ""
	proc accept {s a p} {
	    global x
	    puts $s bye
	    close $s
	    set x ok
	}
	set server [socket -server accept -myaddr ::1 0]
	set port [lindex [fconfigure $server -sockname] 2]
	set x ""
    } \
    -body {
        set client [socket -async localhost $port]
        for {set i 0} {$i < 50} {incr i } {
            update
            if {$x ne ""} {
                lappend x [gets $client]
                break
            }
            after 100
        }
        set x
	set client [socket -async localhost $port]
	for {set i 0} {$i < 50} {incr i } {
	    update
	    if {$x ne ""} {
		lappend x [gets $client]
		break
	    }
	    after 100
	}
	set x
    } \
    -cleanup {
        close $server
        close $client
        unset x
	close $server
	close $client
	unset x
    } \
    -result {ok bye}
test socket-14.7.0 {pending [socket -async] and blocking [gets], server is IPv4} \
    -constraints {socket supported_inet localhost_v4} \
    -setup {
        makeFile {
            fileevent stdin readable exit
            set server [socket -server accept -myaddr 127.0.0.1 0]
            proc accept {s h p} {puts $s ok; close $s; set ::x 1}
            puts [lindex [fconfigure $server -sockname] 2]
            flush stdout
            vwait x
        } script
        set fd [open |[list [interpreter] script] RDWR]
        set port [gets $fd]
	makeFile {
	    fileevent stdin readable exit
	    set server [socket -server accept -myaddr 127.0.0.1 0]
	    proc accept {s h p} {puts $s ok; close $s; set ::x 1}
	    puts [lindex [fconfigure $server -sockname] 2]
	    flush stdout
	    vwait x
	} script
	set fd [open |[list [interpreter] script] RDWR]
	set port [gets $fd]
    } -body {
        set sock [socket -async localhost $port]
        list [fconfigure $sock -error] [gets $sock] [fconfigure $sock -error]
	set sock [socket -async localhost $port]
	list [fconfigure $sock -error] [gets $sock] [fconfigure $sock -error]
    } -cleanup {
        close $fd
        close $sock
	close $fd
	close $sock
	removeFile script
    } -result {{} ok {}}
test socket-14.7.1 {pending [socket -async] and blocking [gets], server is IPv6} \
    -constraints {socket supported_inet6 localhost_v6} \
    -setup {
        makeFile {
            fileevent stdin readable exit
            set server [socket -server accept -myaddr ::1 0]
            proc accept {s h p} {puts $s ok; close $s; set ::x 1}
            puts [lindex [fconfigure $server -sockname] 2]
            flush stdout
            vwait x
        } script
        set fd [open |[list [interpreter] script] RDWR]
        set port [gets $fd]
	makeFile {
	    fileevent stdin readable exit
	    set server [socket -server accept -myaddr ::1 0]
	    proc accept {s h p} {puts $s ok; close $s; set ::x 1}
	    puts [lindex [fconfigure $server -sockname] 2]
	    flush stdout
	    vwait x
	} script
	set fd [open |[list [interpreter] script] RDWR]
	set port [gets $fd]
    } -body {
        set sock [socket -async localhost $port]
        list [fconfigure $sock -error] [gets $sock] [fconfigure $sock -error]
	set sock [socket -async localhost $port]
	list [fconfigure $sock -error] [gets $sock] [fconfigure $sock -error]
    } -cleanup {
        close $fd
        close $sock
	close $fd
	close $sock
	removeFile script
    } -result {{} ok {}}
test socket-14.7.2 {pending [socket -async] and blocking [gets], no listener} \
    -constraints {socket} \
    -body {
        set sock [socket -async localhost [randport]]
        catch {gets $sock} x
        list $x [fconfigure $sock -error] [fconfigure $sock -error]
	set sock [socket -async localhost [randport]]
	catch {gets $sock} x
	list $x [fconfigure $sock -error] [fconfigure $sock -error]
    } -cleanup {
        close $sock
    } -match glob -result {{error reading "sock*": socket is not connected} {connection refused} {}}
	close $sock
    } -match glob -result {{error reading "sock*": transport endpoint is not connected} {connection refused} {}}
test socket-14.8.0 {pending [socket -async] and nonblocking [gets], server is IPv4} \
    -constraints {socket supported_inet localhost_v4} \
    -setup {
        makeFile {
            fileevent stdin readable exit
            set server [socket -server accept -myaddr 127.0.0.1 0]
            proc accept {s h p} {puts $s ok; close $s; set ::x 1}
            puts [lindex [fconfigure $server -sockname] 2]
            flush stdout
            vwait x
        } script
        set fd [open |[list [interpreter] script] RDWR]
        set port [gets $fd]
	makeFile {
	    fileevent stdin readable exit
	    set server [socket -server accept -myaddr 127.0.0.1 0]
	    proc accept {s h p} {puts $s ok; close $s; set ::x 1}
	    puts [lindex [fconfigure $server -sockname] 2]
	    flush stdout
	    vwait x
	} script
	set fd [open |[list [interpreter] script] RDWR]
	set port [gets $fd]
    } -body {
        set sock [socket -async localhost $port]
        fconfigure $sock -blocking 0
        for {set i 0} {$i < 50} {incr i } {
            if {[catch {gets $sock} x] || $x ne "" || ![fblocked $sock]} break
            after 200
        }
        set x
	set sock [socket -async localhost $port]
	fconfigure $sock -blocking 0
	for {set i 0} {$i < 50} {incr i } {
	    if {[catch {gets $sock} x] || $x ne "" || ![fblocked $sock]} break
	    after 200
	}
	set x
    } -cleanup {
        close $fd
        close $sock
	close $fd
	close $sock
	removeFile script
    } -result {ok}
test socket-14.8.1 {pending [socket -async] and nonblocking [gets], server is IPv6} \
    -constraints {socket supported_inet6 localhost_v6} \
    -setup {
        makeFile {
            fileevent stdin readable exit
            set server [socket -server accept -myaddr ::1 0]
            proc accept {s h p} {puts $s ok; close $s; set ::x 1}
            puts [lindex [fconfigure $server -sockname] 2]
            flush stdout
            vwait x
        } script
        set fd [open |[list [interpreter] script] RDWR]
        set port [gets $fd]
	makeFile {
	    fileevent stdin readable exit
	    set server [socket -server accept -myaddr ::1 0]
	    proc accept {s h p} {puts $s ok; close $s; set ::x 1}
	    puts [lindex [fconfigure $server -sockname] 2]
	    flush stdout
	    vwait x
	} script
	set fd [open |[list [interpreter] script] RDWR]
	set port [gets $fd]
    } -body {
        set sock [socket -async localhost $port]
        fconfigure $sock -blocking 0
        for {set i 0} {$i < 50} {incr i } {
            if {[catch {gets $sock} x] || $x ne "" || ![fblocked $sock]} break
            after 200
        }
        set x
	set sock [socket -async localhost $port]
	fconfigure $sock -blocking 0
	for {set i 0} {$i < 50} {incr i } {
	    if {[catch {gets $sock} x] || $x ne "" || ![fblocked $sock]} break
	    after 200
	}
	set x
    } -cleanup {
        close $fd
        close $sock
	close $fd
	close $sock
	removeFile script
    } -result {ok}
test socket-14.8.2 {pending [socket -async] and nonblocking [gets], no listener} \
    -constraints {socket} \
    -body {
        set sock [socket -async localhost [randport]]
        fconfigure $sock -blocking 0
        for {set i 0} {$i < 50} {incr i } {
            if {[catch {gets $sock} x] || $x ne "" || ![fblocked $sock]} break
            after 200
        }
        list $x [fconfigure $sock -error] [fconfigure $sock -error]
	set sock [socket -async localhost [randport]]
	fconfigure $sock -blocking 0
	for {set i 0} {$i < 50} {incr i } {
	    if {[catch {gets $sock} x] || $x ne "" || ![fblocked $sock]} break
	    after 200
	}
	list $x [fconfigure $sock -error] [fconfigure $sock -error]
    } -cleanup {
        close $sock
    } -match glob -result {{error reading "sock*": socket is not connected} {connection refused} {}}
	close $sock
    } -match glob -result {{error reading "sock*": transport endpoint is not connected} {connection refused} {}}
test socket-14.9.0 {pending [socket -async] and blocking [puts], server is IPv4} \
    -constraints {socket supported_inet localhost_v4} \
    -setup {
        makeFile {
            fileevent stdin readable exit
            set server [socket -server accept -myaddr 127.0.0.1 0]
            proc accept {s h p} {set ::x $s}
            puts [lindex [fconfigure $server -sockname] 2]
            flush stdout
            vwait x
            puts [gets $x]
        } script
        set fd [open |[list [interpreter] script] RDWR]
        set port [gets $fd]
	makeFile {
	    fileevent stdin readable exit
	    set server [socket -server accept -myaddr 127.0.0.1 0]
	    proc accept {s h p} {set ::x $s}
	    puts [lindex [fconfigure $server -sockname] 2]
	    flush stdout
	    vwait x
	    puts [gets $x]
	} script
	set fd [open |[list [interpreter] script] RDWR]
	set port [gets $fd]
    } -body {
        set sock [socket -async localhost $port]
        puts $sock ok
        flush $sock
        list [fconfigure $sock -error] [gets $fd]
	set sock [socket -async localhost $port]
	puts $sock ok
	flush $sock
	list [fconfigure $sock -error] [gets $fd]
    } -cleanup {
        close $fd
        close $sock
	close $fd
	close $sock
	removeFile script
    } -result {{} ok}
test socket-14.9.1 {pending [socket -async] and blocking [puts], server is IPv6} \
    -constraints {socket supported_inet6 localhost_v6} \
    -setup {
        makeFile {
            fileevent stdin readable exit
            set server [socket -server accept -myaddr ::1 0]
            proc accept {s h p} {set ::x $s}
            puts [lindex [fconfigure $server -sockname] 2]
            flush stdout
            vwait x
            puts [gets $x]
        } script
        set fd [open |[list [interpreter] script] RDWR]
        set port [gets $fd]
	makeFile {
	    fileevent stdin readable exit
	    set server [socket -server accept -myaddr ::1 0]
	    proc accept {s h p} {set ::x $s}
	    puts [lindex [fconfigure $server -sockname] 2]
	    flush stdout
	    vwait x
	    puts [gets $x]
	} script
	set fd [open |[list [interpreter] script] RDWR]
	set port [gets $fd]
    } -body {
        set sock [socket -async localhost $port]
        puts $sock ok
        flush $sock
        list [fconfigure $sock -error] [gets $fd]
	set sock [socket -async localhost $port]
	puts $sock ok
	flush $sock
	list [fconfigure $sock -error] [gets $fd]
    } -cleanup {
        close $fd
        close $sock
	close $fd
	close $sock
	removeFile script
    } -result {{} ok}
test socket-14.10.0 {pending [socket -async] and nonblocking [puts], server is IPv4} \
    -constraints {socket supported_inet localhost_v4} \
    -setup {
        makeFile {
            fileevent stdin readable exit
            set server [socket -server accept -myaddr 127.0.0.1 0]
            proc accept {s h p} {set ::x $s}
            puts [lindex [fconfigure $server -sockname] 2]
            flush stdout
            vwait x
            puts [gets $x]
        } script
        set fd [open |[list [interpreter] script] RDWR]
        set port [gets $fd]
	makeFile {
	    fileevent stdin readable exit
	    set server [socket -server accept -myaddr 127.0.0.1 0]
	    proc accept {s h p} {set ::x $s}
	    puts [lindex [fconfigure $server -sockname] 2]
	    flush stdout
	    vwait x
	    puts [gets $x]
	} script
	set fd [open |[list [interpreter] script] RDWR]
	set port [gets $fd]
    } -body {
        set sock [socket -async localhost $port]
        fconfigure $sock -blocking 0
        puts $sock ok
        flush $sock
        fileevent $fd readable {set x 1}
        vwait x
        list [fconfigure $sock -error] [gets $fd]
	set sock [socket -async localhost $port]
	fconfigure $sock -blocking 0
	puts $sock ok
	flush $sock
	fileevent $fd readable {set x 1}
	vwait x
	list [fconfigure $sock -error] [gets $fd]
    } -cleanup {
        close $fd
        close $sock
	close $fd
	close $sock
	removeFile script
    } -result {{} ok}
test socket-14.10.1 {pending [socket -async] and nonblocking [puts], server is IPv6} \
    -constraints {socket supported_inet6 localhost_v6} \
    -setup {
        makeFile {
            fileevent stdin readable exit
            set server [socket -server accept -myaddr ::1 0]
            proc accept {s h p} {set ::x $s}
            puts [lindex [fconfigure $server -sockname] 2]
            flush stdout
            vwait x
            puts [gets $x]
        } script
        set fd [open |[list [interpreter] script] RDWR]
        set port [gets $fd]
	makeFile {
	    fileevent stdin readable exit
	    set server [socket -server accept -myaddr ::1 0]
	    proc accept {s h p} {set ::x $s}
	    puts [lindex [fconfigure $server -sockname] 2]
	    flush stdout
	    vwait x
	    puts [gets $x]
	} script
	set fd [open |[list [interpreter] script] RDWR]
	set port [gets $fd]
    } -body {
        set sock [socket -async localhost $port]
        fconfigure $sock -blocking 0
        puts $sock ok
        flush $sock
        fileevent $fd readable {set x 1}
        vwait x
        list [fconfigure $sock -error] [gets $fd]
	set sock [socket -async localhost $port]
	fconfigure $sock -blocking 0
	puts $sock ok
	flush $sock
	fileevent $fd readable {set x 1}
	vwait x
	list [fconfigure $sock -error] [gets $fd]
    } -cleanup {
        close $fd
        close $sock
	close $fd
	close $sock
	removeFile script
    } -result {{} ok}
test socket-14.11.0 {pending [socket -async] and nonblocking [puts], no listener, no flush} \
    -constraints {socket knownMsvcBug} \
    -constraints {socket notWinCI} \
    -body {
        set sock [socket -async localhost [randport]]
        fconfigure $sock -blocking 0
        puts $sock ok
        fileevent $sock writable {set x 1}
        vwait x
        close $sock
	set sock [socket -async localhost [randport]]
	fconfigure $sock -blocking 0
	puts $sock ok
	fileevent $sock writable {set x 1}
	vwait x
	close $sock
    } -cleanup {
        catch {close $sock}
        unset x
    } -result {socket is not connected} -returnCodes 1
	catch {close $sock}
	unset x
    } -result {transport endpoint is not connected} -returnCodes 1
test socket-14.11.1 {pending [socket -async] and nonblocking [puts], no listener, flush} \
    -constraints {socket testsocket_testflags} \
    -body {
        set sock [socket -async localhost [randport]]
        # Set the socket in async test mode.
        # The async connect will not be continued on the following fconfigure
        # and puts/flush. Thus, the connect will fail after them.
        testsocket testflags $sock 1
        fconfigure $sock -blocking 0
        puts $sock ok
        flush $sock
        testsocket testflags $sock 0
        fileevent $sock writable {set x 1}
        vwait x
        close $sock
	set sock [socket -async localhost [randport]]
	# Set the socket in async test mode.
	# The async connect will not be continued on the following fconfigure
	# and puts/flush. Thus, the connect will fail after them.
	testsocket testflags $sock 1
	fconfigure $sock -blocking 0
	puts $sock ok
	flush $sock
	testsocket testflags $sock 0
	fileevent $sock writable {set x 1}
	vwait x
	close $sock
    } -cleanup {
        catch {close $sock}
        catch {unset x}
    } -result {socket is not connected} -returnCodes 1
	catch {close $sock}
	catch {unset x}
    } -result {transport endpoint is not connected} -returnCodes 1
test socket-14.12 {[socket -async] background progress triggered by [fconfigure -error]} \
    -constraints {socket} \
    -body {
        set s [socket -async localhost [randport]]
        for {set i 0} {$i < 50} {incr i} {
            set x [fconfigure $s -error]
            if {$x != ""} break
            after 200
        }
        set x
	set s [socket -async localhost [randport]]
	for {set i 0} {$i < 50} {incr i} {
	    set x [fconfigure $s -error]
	    if {$x != ""} break
	    after 200
	}
	set x
    } -cleanup {
        close $s
        unset x s
	close $s
	unset x s
    } -result {connection refused}

test socket-14.13 {testing writable event when quick failure} \
    -constraints {socket win supported_inet notWine} \
    -body {
    # Test for bug 336441ed59 where a quick background fail was ignored

    # Test only for windows as socket -async 255.255.255.255 fails
    # directly on unix
    # directly on Unix

    # The following connect should fail very quickly
    set a1 [after 2000 {set x timeout}]
    set s [socket -async 255.255.255.255 43434]
    fileevent $s writable {set x writable}
    vwait x
    set x
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478




2479
2480

2481
2482
2483
2484
2485
2486
2487
2488
2489


2490
2491

2492
2493
2494
2495
2496
2497
2498
2499
2500


2501
2502

2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516







2517
2518
2519
2520



2521
2522
2523
2524
2525
2526
2527
2528
2529
2530





2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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
2492
2493
2494
2495
2496
2497
2498




2499
2500
2501
2502
2503

2504
2505
2506
2507
2508
2509
2510
2511


2512
2513
2514

2515
2516
2517
2518
2519
2520
2521
2522


2523
2524
2525

2526
2527
2528
2529
2530
2531
2532
2533







2534
2535
2536
2537
2538
2539
2540
2541



2542
2543
2544
2545
2546
2547
2548
2549





2550
2551
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







-
-
-
-
+
+
+
+

-
+







-
-
+
+

-
+







-
-
+
+

-
+







-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
+
+
+





-
-
-
-
-
+
+
+
+
+















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+









} -cleanup {
    catch {close $s}
    after cancel $a1
} -result readable

test socket-14.15 {blocking read on async socket should not trigger event handlers} \
    -constraints socket -body {
        set s [socket -async localhost [randport]]
        set x ok
        fileevent $s writable {set x fail}
        catch {read $s}
	set s [socket -async localhost [randport]]
	set x ok
	fileevent $s writable {set x fail}
	catch {read $s}
	close $s
        set x
	set x
    } -result ok

# v4 and v6 is required to prevent that the async connect does not terminate
# before the fconfigure command. There is always an additional ip to try.
test socket-14.16 {empty -peername while [socket -async] connecting} \
    -constraints {socket localhost_v4 localhost_v6} \
    -body {
        set client [socket -async localhost [randport]]
        fconfigure $client -peername
	set client [socket -async localhost [randport]]
	fconfigure $client -peername
    } -cleanup {
        catch {close $client}
	catch {close $client}
    } -result {}

# v4 and v6 is required to prevent that the async connect does not terminate
# before the fconfigure command. There is always an additional ip to try.
test socket-14.17 {empty -sockname while [socket -async] connecting} \
    -constraints {socket localhost_v4 localhost_v6} \
    -body {
        set client [socket -async localhost [randport]]
        fconfigure $client -sockname
	set client [socket -async localhost [randport]]
	fconfigure $client -sockname
    } -cleanup {
        catch {close $client}
	catch {close $client}
    } -result {}

# test for bug c6ed4acfd8: running async socket connect with other connect
# established will block tcl as it goes in an infinite loop in vwait
test socket-14.18 {bug c6ed4acfd8: running async socket connect made other connect block} \
    -constraints {socket} \
    -body {
        proc accept {channel address port} {}
        set port [randport]
        set ssock [socket -server accept $port]
        set csock1 [socket -async localhost [randport]]
        set csock2 [socket localhost $port]
        after 1000 {set done ok}
        vwait done
	proc accept {channel address port} {}
	set port [randport]
	set ssock [socket -server accept $port]
	set csock1 [socket -async localhost [randport]]
	set csock2 [socket localhost $port]
	after 1000 {set done ok}
	vwait done
} -cleanup {
        catch {close $ssock}
        catch {close $csock1}
        catch {close $csock2}
	catch {close $ssock}
	catch {close $csock1}
	catch {close $csock2}
    } -result {}

test socket-14.19 {tip 456 -- introduce the -reuseport option} \
    -constraints {socket notWine} \
    -body {
        proc accept {channel address port} {}
        set port [randport]
        set ssock1 [socket -server accept -reuseport yes $port]
        set ssock2 [socket -server accept -reuseport yes $port]
        return ok
	proc accept {channel address port} {}
	set port [randport]
	set ssock1 [socket -server accept -reuseport yes $port]
	set ssock2 [socket -server accept -reuseport yes $port]
	return ok
} -cleanup {
    catch {close $ssock1}
    catch {close $ssock2}
    } -result ok

set num 0

set x {localhost {socket} 127.0.0.1 {supported_inet} ::1 {supported_inet6}}
set resultok {-result "sock*" -match glob}
set resulterr {
    -result {couldn't open socket: connection refused}
    -returnCodes 1
}
foreach {servip sc} $x {
    foreach {cliip cc} $x {
        set constraints socket
        lappend constraints $sc $cc
        set result $resulterr
        switch -- [lsort -unique [list $servip $cliip]] {
            localhost - 127.0.0.1 - ::1 {
                set result $resultok
            }
            {127.0.0.1 localhost} {
                if {[testConstraint localhost_v4]} {
                    set result $resultok
                }
            }
            {::1 localhost} {
                if {[testConstraint localhost_v6]} {
                    set result $resultok
                }
            }
        }
        test socket-15.1.$num "Connect to $servip from $cliip" \
            -constraints $constraints -setup {
                set server [socket -server accept -myaddr $servip 0]
                proc accept {s h p} { close $s }
                set port [lindex [fconfigure $server -sockname] 2]
            } -body {
                set s [socket $cliip $port]
            } -cleanup {
                close $server
                catch {close $s}
            } {*}$result
        incr num
	set constraints socket
	lappend constraints $sc $cc
	set result $resulterr
	switch -- [lsort -unique [list $servip $cliip]] {
	    localhost - 127.0.0.1 - ::1 {
		set result $resultok
	    }
	    {127.0.0.1 localhost} {
		if {[testConstraint localhost_v4]} {
		    set result $resultok
		}
	    }
	    {::1 localhost} {
		if {[testConstraint localhost_v6]} {
		    set result $resultok
		}
	    }
	}
	test socket-15.1.$num "Connect to $servip from $cliip" \
	    -constraints $constraints -setup {
		set server [socket -server accept -myaddr $servip 0]
		proc accept {s h p} { close $s }
		set port [lindex [fconfigure $server -sockname] 2]
	    } -body {
		set s [socket $cliip $port]
	    } -cleanup {
		close $server
		catch {close $s}
	    } {*}$result
	incr num
    }
}

test socket-bug-31fc36fe47 "Crash listening in multiple threads" \
    -constraints thread -body {
	close [socket -server xxx 0]
	set tid [thread::create]
	thread::send $tid {close [socket -server accept 0]}
	thread::release $tid
    } -result 0

::tcltest::cleanupTests
flush stdout
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:

Changes to tests/source.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  source
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-2000 Scriptics Corporation.
# Contributions from Don Porter, NIST, 2003.  (not subject to US copyright)
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {[catch {package require tcltest 2.5}]} {
    puts stderr "Skipping tests in [info script]. tcltest 2.5 required."
53
54
55
56
57
58
59
60

61
62
63
64
65



66
67
68
69
70
71
72
53
54
55
56
57
58
59

60
61
62



63
64
65
66
67
68
69
70
71
72







-
+


-
-
-
+
+
+







    source $sourcefile
} -cleanup {
    removeFile source.file
} -result {a b c d e f}

proc ListGlobMatch {expected actual} {
    if {[llength $expected] != [llength $actual]} {
        return 0
	return 0
    }
    foreach e $expected a $actual {
        if {![string match $e $a]} {
            return 0
        }
	if {![string match $e $a]} {
	    return 0
	}
    }
    return 1
}
customMatch listGlob [namespace which ListGlobMatch]

test source-2.3 {source error conditions} -setup {
    set sourcefile [makeFile {
107
108
109
110
111
112
113
114

115
116
117
118
119
120
121
107
108
109
110
111
112
113

114
115
116
117
118
119
120
121







-
+







} -match glob -result {couldn't read file "*_non_existent_": no such file or directory} \
	-errorCode {POSIX ENOENT {no such file or directory}}
test source-2.7 {utf-8 with BOM} -setup {
    set sourcefile [makeFile {} source.file]
} -body {
    set out [open $sourcefile w]
    fconfigure $out -encoding utf-8
    puts $out "\ufeffset y new-y"
    puts $out "\uFEFFset y new-y"
    close $out
    set y old-y
    source $sourcefile
    return $y
} -cleanup {
    removeFile $sourcefile
} -result {new-y}
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
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







-
+








-
+













-
+










-
+

-
+





-
+







} -cleanup {
    removeFile source.file
} -result {source: 3 4 5}

test source-6.1 {source is binary ok} -setup {
    # Note [makeFile] writes in the system encoding.
    # [source] defaults to reading in the system encoding.
    set sourcefile [makeFile [list set x "a b\0c"] source.file]
    set sourcefile [makeFile [list set x "a b\x00c"] source.file]
} -body {
    set x {}
    source $sourcefile
    string length $x
} -cleanup {
    removeFile source.file
} -result 5
test source-6.2 {source skips everything after Ctrl-Z: Bug 2040} -setup {
    set sourcefile [makeFile "set x ab\32c" source.file]
    set sourcefile [makeFile "set x ab\x1Ac" source.file]
} -body {
    set x {}
    source $sourcefile
    string length $x
} -cleanup {
    removeFile source.file
} -result 2

test source-7.1 {source -encoding test} -setup {
    set sourcefile [makeFile {} source.file]
    file delete $sourcefile
    set f [open $sourcefile w]
    fconfigure $f -encoding utf-8
    puts $f "set symbol(square-root) \u221A; set x correct"
    puts $f "set symbol(square-root) √; set x correct"
    close $f
} -body {
    set x unset
    source $sourcefile
    set x
} -cleanup {
    removeFile source.file
} -result correct
test source-7.2 {source -encoding test} -setup {
    # This tests for bad interactions between [source -encoding]
    # and use of the Control-Z character (\u001A) as a cross-platform
    # and use of the Control-Z character (\x1A) as a cross-platform
    # EOF character by [source].  Here we write out and the [source] a
    # file that contains the byte \x1A, although not the character \u001A in
    # file that contains the byte \x1A, although not the character \x1A in
    # the indicated encoding.
    set sourcefile [makeFile {} source.file]
    file delete $sourcefile
    set f [open $sourcefile w]
    fconfigure $f -encoding utf-16
    puts $f "set symbol(square-root) \u221A; set x correct"
    puts $f "set symbol(square-root) √; set x correct"
    close $f
} -body {
    set x unset
    source -encoding utf-16 $sourcefile
    set x
} -cleanup {
    removeFile source.file
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
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







-
+



-
+


-
+






-
+


-
+
-
+


-
+







    removeFile source.file
} -returnCodes 1 -match glob -result {unknown encoding*}
test source-7.5 {source -encoding: correct operation} -setup {
    set sourcefile [makeFile {} source.file]
    file delete $sourcefile
    set f [open $sourcefile w]
    fconfigure $f -encoding utf-8
    puts $f "proc \u20ac {} {return foo}"
    puts $f "proc € {} {return foo}"
    close $f
} -body {
    source $sourcefile
    \u20ac
    €
} -cleanup {
    removeFile source.file
    rename \u20ac {}
    rename € {}
} -result foo
test source-7.6 {source -encoding: mismatch encoding error} -setup {
    set sourcefile [makeFile {} source.file]
    file delete $sourcefile
    set f [open $sourcefile w]
    fconfigure $f -encoding utf-8
    puts $f "proc \u20ac {} {return foo}"
    puts $f "proc € {} {return foo}"
    close $f
} -body {
    source -encoding ascii $sourcefile
    source -encoding iso8859-1 $sourcefile
    \u20ac
    €
} -cleanup {
    removeFile source.file
} -returnCodes error -match glob -result {invalid command name*}
} -returnCodes error -result {invalid command name "€"}

test source-8.1 {source and coroutine/yield} -setup {
    set sourcefile [makeFile {} source.file]
    file delete $sourcefile
} -body {
    makeFile {yield 1; yield 2; return 3;} $sourcefile
    coroutine coro apply {f {yield;source $f}} $sourcefile

Changes to tests/split.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  split
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
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
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







-
-
-
-
-
+
+
+
+
+





-
-
-
+
+
+


-
+

-
+





-
+








-
-
+
+

-
+







    split {}
} {}
test split-1.7 {basic split commands} {
    split {   }
} {{} {} {} {}}
test split-1.8 {basic split commands} {
    proc foo {} {
        set x {}
        foreach f [split {]\n} {}] {
            append x $f
        }
        return $x
	set x {}
	foreach f [split {]\n} {}] {
	    append x $f
	}
	return $x
    }
    foo
} {]\n}
test split-1.9 {basic split commands} {
    proc foo {} {
        set x ab\000c
        set y [split $x {}]
        return $y
	set x ab\x00c
	set y [split $x {}]
	return $y
    }
    foo
} "a b \000 c"
} "a b \x00 c"
test split-1.10 {basic split commands} {
    split "a0ab1b2bbb3\000c4" ab\000c
    split "a0ab1b2bbb3\x00c4" ab\x00c
} {{} 0 {} 1 2 {} {} 3 {} 4}
test split-1.11 {basic split commands} {
    split "12,3,45" {,}
} {12 3 45}
test split-1.12 {basic split commands} {
    split "\u0001ab\u0001cd\u0001\u0001ef\u0001" \1
    split "\x01ab\x01cd\x01\x01ef\x01" \x01
} {{} ab cd {} ef {}}
test split-1.13 {basic split commands} {
    split "12,34,56," {,}
} {12 34 56 {}}
test split-1.14 {basic split commands} {
    split ",12,,,34,56," {,}
} {{} 12 {} {} 34 56 {}}
test split-1.15 {basic split commands} -body {
    split "a\U1F4A9b" {}
} -result "a \U1F4A9 b"
    split "a💩b" {}
} -result "a 💩 b"
test split-1.16 {basic split commands} -body {
    split "a\U1F4A9b" \U1F4A9
    split "a💩b" 💩
} -result "a b"

test split-2.1 {split errors} {
    list [catch split msg] $msg $errorCode
} {1 {wrong # args: should be "split string ?splitChars?"} {TCL WRONGARGS}}
test split-2.2 {split errors} {
    list [catch {split a b c} msg] $msg $errorCode

Changes to tests/stack.test.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







# Tests that the stack size is big enough for the application.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1998-2000 Ajuba Solutions.
# Copyright © 1998-2000 Ajuba Solutions.
#
# 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::*

Changes to tests/string.test.

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
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
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
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






-
-
-
-
+
+
+
+










-
+
+
+












-






-
-
+
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+







# Commands covered:  string
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2001 Kevin B. Kenny.  All rights reserved.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]
source [file join [file dirname [info script]] tcltests.tcl]


# Helper commands to test various optimizations, code paths, and special cases.
proc makeByteArray {s} {binary format a* $s}
proc makeUnicode {s} {lindex [regexp -inline .* $s] 0}
proc makeList {args} {return $args}
proc makeShared {s} {uplevel 1 [list lappend copy $s]; return $s}

# Some tests require the testobj command

testConstraint testobj [expr {[info commands testobj] ne {}}]
testConstraint testindexobj [expr {[info commands testindexobj] ne {}}]
testConstraint testevalex [expr {[info commands testevalex] ne {}}]
testConstraint fullutf [expr {[string length \U010000] == 1}]
testConstraint testbytestring   [llength [info commands testbytestring]]

# Used for constraining memory leak tests
testConstraint memory [llength [info commands memory]]
if {[testConstraint memory]} {
    proc getbytes {} {
        set lines [split [memory info] \n]
        return [lindex $lines 3 3]
	set lines [split [memory info] \n]
	return [lindex $lines 3 3]
    }
    proc leaktest {script {iterations 3}} {
        set end [getbytes]
        for {set i 0} {$i < $iterations} {incr i} {
            uplevel 1 $script
            set tmp $end
            set end [getbytes]
        }
        return [expr {$end - $tmp}]
	set end [getbytes]
	for {set i 0} {$i < $iterations} {incr i} {
	    uplevel 1 $script
	    set tmp $end
	    set end [getbytes]
	}
	return [expr {$end - $tmp}]
    }
}

proc representationpoke s {
    set r [::tcl::unsupported::representation $s]
    list [lindex $r 3] [string match {*, string representation "*"} $r]
}
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
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







-
+

-
+







-
-
+
+







    set constraints testevalex
} else {
    interp alias {} run {} try
    set constraints {}
}


test string-1.1.$noComp {error conditions} {
test string-1.1.$noComp {error conditions} -body {
    list [catch {run {string gorp a b}} msg] $msg
} {1 {unknown or ambiguous subcommand "gorp": must be bytelength, cat, compare, equal, first, index, insert, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstart}}
} -result {1 {unknown or ambiguous subcommand "gorp": must be cat, compare, equal, first, index, insert, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstart}}
test string-1.2.$noComp {error conditions} {
    list [catch {run {string}} msg] $msg
} {1 {wrong # args: should be "string subcommand ?arg ...?"}}
test stringComp-1.3.$noComp {error condition - undefined method during compile} {
    # We don't want this to complain about 'never' because it may never
    # be called, or string may get redefined.  This must compile OK.
    proc foo {str i} {
        if {"yes" == "no"} { string never called but complains here }
        string index $str $i
	if {"yes" == "no"} { string never called but complains here }
	string index $str $i
    }
    foo abc 0
} a

test string-2.1.$noComp {string compare, not enough args} {
    list [catch {run {string compare a}} msg] $msg
} {1 {wrong # args: should be "string compare ?-nocase? ?-length int? string1 string2"}}
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
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







-
+


-
+


-
+


-
+


-
+




















-
+


-
+
















-
+







test string-2.9.$noComp {string compare with length} {
    run {string compare -length 2 abcde abxyz}
} 0
test string-2.10.$noComp {string compare with special index} {
    list [catch {run {string compare -length end-3 abcde abxyz}} msg] $msg
} {1 {expected integer but got "end-3"}}
test string-2.11.$noComp {string compare, unicode} {
    run {string compare ab\u7266 ab\u7267}
    run {string compare ab牦 ab牧}
} -1
test string-2.11.1.$noComp {string compare, unicode} {
    run {string compare \334 \xDC}
    run {string compare Ü Ü}
} 0
test string-2.11.2.$noComp {string compare, unicode} {
    run {string compare \334 \xFC}
    run {string compare Ü ü}
} -1
test string-2.11.3.$noComp {string compare, unicode} {
    run {string compare \334\334\334\374\374 \334\334\334\334\334}
    run {string compare ÜÜÜüü ÜÜÜÜÜ}
} 1
test string-2.12.$noComp {string compare, high bit} {
    # This test will fail if the underlying comparison
    # This test fails if the underlying comparison
    # is using signed chars instead of unsigned chars.
    # (like SunOS's default memcmp thus the compat/memcmp.c)
    run {string compare "\x80" "@"}
    # Nb this tests works also in utf-8 space because \x80 is
    # translated into a 2 or more bytelength but whose first byte has
    # the high bit set.
} 1
test string-2.13.$noComp {string compare -nocase} {
    run {string compare -nocase abcde abdef}
} -1
test string-2.13.1.$noComp {string compare -nocase} {
    run {string compare -nocase abcde Abdef}
} -1
test string-2.14.$noComp {string compare -nocase} {
    run {string compare -nocase abcde ABCDE}
} 0
test string-2.15.$noComp {string compare -nocase} {
    run {string compare -nocase abcde abcde}
} 0
test string-2.15.1.$noComp {string compare -nocase} {
    run {string compare -nocase \334 \xDC}
    run {string compare -nocase Ü Ü}
} 0
test string-2.15.2.$noComp {string compare -nocase} {
    run {string compare -nocase \334\334\334\374\xFC \334\334\334\334\334}
    run {string compare -nocase ÜÜÜüü ÜÜÜÜÜ}
} 0
test string-2.16.$noComp {string compare -nocase with length} {
    run {string compare -length 2 -nocase abcde Abxyz}
} 0
test string-2.17.$noComp {string compare -nocase with length} {
    run {string compare -nocase -length 3 abcde Abxyz}
} -1
test string-2.18.$noComp {string compare -nocase with length <= 0} {
    run {string compare -nocase -length -1 abcde AbCdEf}
} -1
test string-2.19.$noComp {string compare -nocase with excessive length} {
    run {string compare -nocase -length 50 AbCdEf abcde}
} 1
test string-2.20.$noComp {string compare -len unicode} {
    # These are strings that are 6 BYTELENGTH long, but the length
    # shouldn't make a different because there are actually 3 CHARS long
    run {string compare -len 5 \334\334\334 \334\334\374}
    run {string compare -len 5 ÜÜÜ ÜÜü}
} -1
test string-2.21.$noComp {string compare -nocase with special index} {
    list [catch {run {string compare -nocase -length end-3 Abcde abxyz}} msg] $msg
} {1 {expected integer but got "end-3"}}
test string-2.22.$noComp {string compare, null strings} {
    run {string compare "" ""}
} 0
191
192
193
194
195
196
197
198

199
200
201

202
203
204
205
206
207
208
192
193
194
195
196
197
198

199
200
201

202
203
204
205
206
207
208
209







-
+


-
+







} 0
test string-2.26.$noComp {string compare -nocase, null strings} {
    run {string compare -nocase "" foo}
} -1
test string-2.27.$noComp {string compare -nocase, null strings} {
    run {string compare -nocase foo ""}
} 1
test string-2.28.$noComp {string compare with length, unequal strings} {
test string-2.28.$noComp {string compare with length, unequal strings, partial first string} {
    run {string compare -length 2 abc abde}
} 0
test string-2.29.$noComp {string compare with length, unequal strings} {
test string-2.29.$noComp {string compare with length, unequal strings 2, full first string} {
    run {string compare -length 2 ab abde}
} 0
test string-2.30.$noComp {string compare with NUL character vs. other ASCII} {
    # Be careful here, since UTF-8 rep comparison with memcmp() of
    # these puts chars in the wrong order
    run {string compare \x00 \x01}
} -1
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













-
+







} 0
test string-2.35.$noComp {string compare, binary neq} {
    run {string compare [binary format a100a 0 1] [binary format a100a 0 0]}
} 1
test string-2.36.$noComp {string compare, binary neq unequal length} {
    run {string compare [binary format a20a 0 1] [binary format a100a 0 0]}
} 1
test string-2.37.$noComp {string compare, big -length} {
    if {[package vsatisfies [info patchlevel] 8.7-]} {
      run {string compare -length 0x100000000 ab abde}
    } else {
      run {string compare -length 0x7fffffff ab abde}
    }
} -1
test string-2.38a.$noComp {string compare empty string against byte array} {
    # Bug edb4b065f4
    run {string compare "" [binary decode hex 00]}
} -1
test string-2.38b.$noComp {string compare -length empty string against byte array} {
    # Bug edb4b065f4
    run {string compare -length 1 "" [binary decode hex 00]}
} -1
test string-2.38c.$noComp {string compare -nocase empty string against byte array} {
    # Bug edb4b065f4
    run {string compare -nocase "" [binary decode hex 00]}
} -1
test string-2.38d.$noComp {string compare empty string against byte array} {
    # Bug edb4b065f4
    run {string compare [binary decode hex 00] ""}
} 1
test string-2.38e.$noComp {string compare -length empty string against byte array} {
    # Bug edb4b065f4
    run {string compare -length 1 [binary decode hex 00] ""}
} 1
test string-2.38f.$noComp {string compare -nocase empty string against byte array} {
    # Bug edb4b065f4
    run {string compare -nocase  [binary decode hex 00] ""}
} 1

# only need a few tests on equal, since it uses the same code as
# string compare, but just modifies the return output
test string-3.1.$noComp {string equal} {
    run {string equal abcde abdef}
} 0
test string-3.2.$noComp {string equal} {
    run {string e abcde ABCDE}
} 0
test string-3.3.$noComp {string equal} {
    run {string equal abcde abcde}
} 1
test string-3.4.$noComp {string equal -nocase} {
    run {string equal -nocase \334\334\334\334\374\374\374\374 \334\334\334\334\334\334\334\334}
    run {string equal -nocase ÜÜÜÜüüüü ÜÜÜÜÜÜÜÜ}
} 1
test string-3.5.$noComp {string equal -nocase} {
    run {string equal -nocase abcde abdef}
} 0
test string-3.6.$noComp {string equal -nocase} {
    run {string eq -nocase abcde ABCDE}
} 1
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
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







-
+


-
+


-
+


-
+


-
+











-
+


-
+
















-
+







    run {string equal -length 2 abcde abxyz}
} 1
test string-3.15.$noComp {string equal with special index} {
    list [catch {run {string equal -length end-3 abcde abxyz}} msg] $msg
} {1 {expected integer but got "end-3"}}

test string-3.16.$noComp {string equal, unicode} {
    run {string equal ab\u7266 ab\u7267}
    run {string equal ab牦 ab牧}
} 0
test string-3.17.$noComp {string equal, unicode} {
    run {string equal \334 \xDC}
    run {string equal Ü Ü}
} 1
test string-3.18.$noComp {string equal, unicode} {
    run {string equal \334 \xFC}
    run {string equal Ü ü}
} 0
test string-3.19.$noComp {string equal, unicode} {
    run {string equal \334\334\334\374\374 \334\334\334\334\334}
    run {string equal ÜÜÜüü ÜÜÜÜÜ}
} 0
test string-3.20.$noComp {string equal, high bit} {
    # This test will fail if the underlying comparaison
    # This test fails if the underlying comparison
    # is using signed chars instead of unsigned chars.
    # (like SunOS's default memcmp thus the compat/memcmp.c)
    run {string equal "\x80" "@"}
    # Nb this tests works also in utf8 space because \x80 is
    # translated into a 2 or more bytelength but whose first byte has
    # the high bit set.
} 0
test string-3.21.$noComp {string equal -nocase} {
    run {string equal -nocase abcde Abdef}
} 0
test string-3.22.$noComp {string equal, -nocase unicode} {
    run {string equal -nocase \334 \xDC}
    run {string equal -nocase Ü Ü}
} 1
test string-3.23.$noComp {string equal, -nocase unicode} {
    run {string equal -nocase \334\334\334\374\xFC \334\334\334\334\334}
    run {string equal -nocase ÜÜÜüü ÜÜÜÜÜ}
} 1
test string-3.24.$noComp {string equal -nocase with length} {
    run {string equal -length 2 -nocase abcde Abxyz}
} 1
test string-3.25.$noComp {string equal -nocase with length} {
    run {string equal -nocase -length 3 abcde Abxyz}
} 0
test string-3.26.$noComp {string equal -nocase with length <= 0} {
    run {string equal -nocase -length -1 abcde AbCdEf}
} 0
test string-3.27.$noComp {string equal -nocase with excessive length} {
    run {string equal -nocase -length 50 AbCdEf abcde}
} 0
test string-3.28.$noComp {string equal -len unicode} {
    # These are strings that are 6 BYTELENGTH long, but the length
    # shouldn't make a different because there are actually 3 CHARS long
    run {string equal -len 5 \334\334\334 \334\334\374}
    run {string equal -len 5 ÜÜÜ ÜÜü}
} 0
test string-3.29.$noComp {string equal -nocase with special index} {
    list [catch {run {string equal -nocase -length end-3 Abcde abxyz}} msg] $msg
} {1 {expected integer but got "end-3"}}
test string-3.30.$noComp {string equal, null strings} {
    run {string equal "" ""}
} 1
360
361
362
363
364
365
366


































367
368
369
370
371
372
373
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







} 1
test string-3.41.$noComp {string equal, binary neq} {
    run {string equal [binary format a100a 0 1] [binary format a100a 0 0]}
} 0
test string-3.42.$noComp {string equal, binary neq inequal length} {
    run {string equal [binary format a20a 0 1] [binary format a100a 0 0]}
} 0
test string-3.43.$noComp {string equal, big -length} {
    if {[package vsatisfies [info patchlevel] 8.7-]} {
      run {string equal -length 0x100000000 abc def}
    } else {
      run {string equal -length 0x7fffffff abc def}
    }
} 0
test string-3.44.$noComp {string equal, bigger -length} -body {
    run {string equal -length 18446744073709551616 abc def}
} -returnCodes 1 -result {integer value too large to represent}
test string-3.45a.$noComp {string equal empty string against byte array} {
    # Bug edb4b065f4
    run {string equal "" [binary decode hex 00]}
} 0
test string-3.45b.$noComp {string equal -length empty string against byte array} {
    # Bug edb4b065f4
    run {string equal -length 1 "" [binary decode hex 00]}
} 0
test string-3.45c.$noComp {string equal -nocase empty string against byte array} {
    # Bug edb4b065f4
    run {string equal -nocase "" [binary decode hex 00]}
} 0
test string-3.45d.$noComp {string equal empty string against byte array} {
    # Bug edb4b065f4
    run {string equal [binary decode hex 00] ""}
} 0
test string-3.45e.$noComp {string equal -length empty string against byte array} {
    # Bug edb4b065f4
    run {string equal -length 1 [binary decode hex 00] ""}
} 0
test string-3.45f.$noComp {string equal -nocase empty string against byte array} {
    # Bug edb4b065f4
    run {string equal -nocase  [binary decode hex 00] ""}
} 0


test string-4.1.$noComp {string first, not enough args} {
    list [catch {run {string first a}} msg] $msg
} {1 {wrong # args: should be "string first needleString haystackString ?startIndex?"}}
test string-4.2.$noComp {string first, bad args} {
    list [catch {run {string first a b c}} msg] $msg
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
442

443
444
445
446
447
448
449
453
454
455
456
457
458
459

460
461
462

463
464
465

466
467
468

469
470
471

472
473
474
475
476
477
478
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







-
+


-
+


-
+


-
+


-
+








-
+











-
+


-
+


-
+


-
+


-
+


-
+







test string-4.7.$noComp {string first} {
    run {string first xxx x123xx345xxx789xxx012}
} 9
test string-4.8.$noComp {string first} {
    run {string first "" x123xx345xxx789xxx012}
} -1
test string-4.9.$noComp {string first, unicode} {
    run {string first x abc\u7266x}
    run {string first x abc牦x}
} 4
test string-4.10.$noComp {string first, unicode} {
    run {string first \u7266 abc\u7266x}
    run {string first 牦 abc牦x}
} 3
test string-4.11.$noComp {string first, start index} {
    run {string first \u7266 abc\u7266x 3}
    run {string first 牦 abc牦x 3}
} 3
test string-4.12.$noComp {string first, start index} -body {
    run {string first \u7266 abc\u7266x 4}
    run {string first 牦 abc牦x 4}
} -result -1
test string-4.13.$noComp {string first, start index} -body {
    run {string first \u7266 abc\u7266x end-2}
    run {string first 牦 abc牦x end-2}
} -result 3
test string-4.14.$noComp {string first, negative start index} -body {
    run {string first b abc -1}
} -result 1
test string-4.15.$noComp {string first, ability to two-byte encoded utf-8 chars} -body {
    # Test for a bug in Tcl 8.3 where test for all-single-byte-encoded
    # strings was incorrect, leading to an index returned by [string first]
    # which pointed past the end of the string.
    set uchar \u057E    ;# character with two-byte encoding in utf-8
    set uchar Õ¾    ;# character with two-byte encoding in utf-8
    run {string first % %#$uchar$uchar#$uchar$uchar#% 3}
} -result 8
test string-4.16.$noComp {string first, normal string vs pure unicode string} -body {
    set s hello
    regexp ll $s m
    # Representation checks are canaries
    run {list [representationpoke $s] [representationpoke $m] \
	[string first $m $s]}
} -result {{string 1} {string 0} 2}
test string-4.17.$noComp {string first, corner case} -body {
    run {string first a aaa 4294967295}
} -result {-1}
} -result -1
test string-4.18.$noComp {string first, corner case} -body {
    run {string first a aaa -1}
} -result {0}
} -result 0
test string-4.19.$noComp {string first, corner case} -body {
    run {string first a aaa end-5}
} -result {0}
} -result 0
test string-4.20.$noComp {string last, corner case} -body {
    run {string last a aaa 4294967295}
} -result {2}
} -result 2
test string-4.21.$noComp {string last, corner case} -body {
    run {string last a aaa -1}
} -result {-1}
} -result -1
test string-4.22.$noComp {string last, corner case} {
    run {string last a aaa end-5}
} {-1}
} -1

test string-5.1.$noComp {string index} {
    list [catch {run {string index}} msg] $msg
} {1 {wrong # args: should be "string index string charIndex"}}
test string-5.2.$noComp {string index} {
    list [catch {run {string index a b c}} msg] $msg
} {1 {wrong # args: should be "string index string charIndex"}}
465
466
467
468
469
470
471
472

473
474
475
476


477
478

479
480
481
482
483
484
485
531
532
533
534
535
536
537

538
539
540


541
542
543

544
545
546
547
548
549
550
551







-
+


-
-
+
+

-
+







test string-5.8.$noComp {string index} {
    run {string index abc end}
} c
test string-5.9.$noComp {string index} {
    run {string index abc end-1}
} b
test string-5.10.$noComp {string index, unicode} {
    run {string index abc\u7266d 4}
    run {string index abc牦d 4}
} d
test string-5.11.$noComp {string index, unicode} {
    run {string index abc\u7266d 3}
} \u7266
    run {string index abc牦d 3}
} 牦
test string-5.12.$noComp {string index, unicode over char length, under byte length} -body {
    run {string index \334\374\334\374 6}
    run {string index ÜüÜü 6}
} -result {}
test string-5.13.$noComp {string index, bytearray object} {
    run {string index [binary format a5 fuz] 0}
} f
test string-5.14.$noComp {string index, bytearray object} {
    run {string index [binary format I* {0x50515253 0x52}] 3}
} S
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
562
563
564
565
566
567
568

569
570

571
572
573
574

575
576
577



578
579
580







581
582
583
584
585
586
587
588







-
+

-
+



-
+


-
-
-
+
+
+
-
-
-
-
-
-
-
+







} 0
test string-5.17.$noComp {string index, bad integer} -body {
    list [catch {run {string index "abc" 0o8}} msg] $msg
} -match glob -result {1 {*}}
test string-5.18.$noComp {string index, bad integer} -body {
    list [catch {run {string index "abc" end-0o0289}} msg] $msg
} -match glob -result {1 {*}}
test string-5.19.$noComp {string index, bytearray object out of bounds} -body {
test string-5.19.$noComp {string index, bytearray object out of bounds} {
    run {string index [binary format I* {0x50515253 0x52}] -1}
} -result {}
} {}
test string-5.20.$noComp {string index, bytearray object out of bounds} -body {
    run {string index [binary format I* {0x50515253 0x52}] 20}
} -result {}
test string-5.21.$noComp {string index, surrogates, bug [11ae2be95dac9417]} -constraints fullutf -body {
test string-5.21.$noComp {string index, surrogates, bug [11ae2be95dac9417]} -body {
    run {list [string index a\U100000b 1] [string index a\U100000b 2] [string index a\U100000b 3]}
} -result [list \U100000 b {}]


proc largest_int {} {
test string-5.22.$noComp {string index} -constraints testbytestring -body {
    run {list [scan [string index [testbytestring \xFF] 0] %c var] $var}
} -result {1 255}
    # This will give us what the largest valid int on this machine is,
    # so we can test for overflow properly below on >32 bit systems
    set int 1
    set exp 7; # assume we get at least 8 bits
    while {wide($int) > 0} { set int [expr {wide(1) << [incr exp]}] }
    return [expr {$int-1}]
}


test string-6.1.$noComp {string is, not enough args} {
    list [catch {run {string is}} msg] $msg
} {1 {wrong # args: should be "string is class ?-strict? ?-failindex var? str"}}
test string-6.2.$noComp {string is, not enough args} {
    list [catch {run {string is alpha}} msg] $msg
} {1 {wrong # args: should be "string is class ?-strict? ?-failindex var? str"}}
556
557
558
559
560
561
562
563

564
565
566
567
568
569
570
571

572
573
574
575
576
577
578
616
617
618
619
620
621
622

623
624
625
626
627
628
629
630

631
632
633
634
635
636
637
638







-
+







-
+







} 0
test string-6.12.$noComp {string is alnum, true} {
    run {string is alnum abc123}
} 1
test string-6.13.$noComp {string is alnum, false} {
    list [run {string is alnum -failindex var abc1.23}] $var
} {0 4}
test string-6.14.$noComp {string is alnum, unicode} "run {string is alnum abc\xFC}" 1
test string-6.14.$noComp {string is alnum, unicode} "run {string is alnum abcü}" 1
test string-6.15.$noComp {string is alpha, true} {
    run {string is alpha abc}
} 1
test string-6.16.$noComp {string is alpha, false} {
    list [run {string is alpha -fail var a1bcde}] $var
} {0 1}
test string-6.17.$noComp {string is alpha, unicode} {
    run {string is alpha abc\374}
    run {string is alpha abcü}
} 1
test string-6.18.$noComp {string is ascii, true} {
    run {string is ascii abc\x7Fend\x00}
} 1
test string-6.19.$noComp {string is ascii, false} {
    list [run {string is ascii -fail var abc\x00def\x80more}] $var
} {0 7}
588
589
590
591
592
593
594
595

596
597
598
599
600
601
602
603
604

605
606
607
608
609
610
611
648
649
650
651
652
653
654

655
656
657
658
659
660
661
662
663

664
665
666
667
668
669
670
671







-
+








-
+







test string-6.23.$noComp {string is boolean, false} {
    list [run {string is bool -fail var yada}] $var
} {0 0}
test string-6.24.$noComp {string is digit, true} {
    run {string is digit 0123456789}
} 1
test string-6.25.$noComp {string is digit, false} {
    list [run {string is digit -fail var 0123\xDC567}] $var
    list [run {string is digit -fail var 0123Ü567}] $var
} {0 4}
test string-6.26.$noComp {string is digit, false} {
    list [run {string is digit -fail var +123567}] $var
} {0 0}
test string-6.27.$noComp {string is double, true} {
    run {string is double 1}
} 1
test string-6.28.$noComp {string is double, true} {
    run {string is double [expr double(1)]}
    run {string is double [expr {double(1)}]}
} 1
test string-6.29.$noComp {string is double, true} {
    run {string is double 1.0}
} 1
test string-6.30.$noComp {string is double, true} {
    run {string is double [run {string compare a a}]}
} 1
630
631
632
633
634
635
636
637

638
639
640
641
642
643
644
690
691
692
693
694
695
696

697
698
699
700
701
702
703
704







-
+







test string-6.37.$noComp {string is double, false on int overflow} -setup {
    set var priorValue
} -body {
    # Make it the largest int recognizable, with one more digit for overflow
    # Since bignums arrived in Tcl 8.5, the sense of this test changed.
    # Now integer values that exceed native limits become bignums, and
    # bignums can convert to doubles without error.
    list [run {string is double -fail var [largest_int]0}] $var
    list [run {string is double -fail var 9223372036854775808}] $var
} -result {1 priorValue}
# string-6.38 removed, underflow on input is no longer an error.
test string-6.39.$noComp {string is double, false} {
    # This test is non-portable because IRIX thinks
    # that .e1 is a valid double - this is really a bug
    # on IRIX as .e1 should NOT be a valid double
    #
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
707
708
709
710
711
712
713
714
715
716
717
718

719
720
721
722
723
724
725
726
727

728
729
730
731
732
733
734
732
733
734
735
736
737
738

739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756

757
758
759

760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777

778
779
780
781
782
783
784
785
786

787
788
789
790
791
792
793
794







-
+

















-
+


-
+

















-
+








-
+







    catch {unset var}
    list [run {string is false -fail var offensive}] $var
} {0 0}
test string-6.48.$noComp {string is integer, true} {
    run {string is integer +1234567890}
} 1
test string-6.49.$noComp {string is integer, true on type} {
    run {string is integer [expr int(50.0)]}
    run {string is integer [expr {int(50.0)}]}
} 1
test string-6.50.$noComp {string is integer, true} {
    run {string is integer [list -10]}
} 1
test string-6.51.$noComp {string is integer, true as hex} {
    run {string is integer 0xabcdef}
} 1
test string-6.52.$noComp {string is integer, true as octal} {
    run {string is integer 012345}
} 1
test string-6.53.$noComp {string is integer, true with whitespace} {
    run {string is integer "  \n1234\v"}
} 1
test string-6.54.$noComp {string is integer, false} {
    list [run {string is integer -fail var 123abc}] $var
} {0 3}
test string-6.55.$noComp {string is integer, no overflow possible} {
    run {string is integer +[largest_int]0}
    run {string is integer +9223372036854775808}
} 1
test string-6.56.$noComp {string is integer, false} {
    list [run {string is integer -fail var [expr double(1)]}] $var
    list [run {string is integer -fail var [expr {double(1)}]}] $var
} {0 1}
test string-6.57.$noComp {string is integer, false} {
    list [run {string is integer -fail var "    "}] $var
} {0 0}
test string-6.58.$noComp {string is integer, false on bad octal} {
    list [run {string is integer -fail var 0o36963}] $var
} {0 4}
test string-6.58.1.$noComp {string is integer, false on bad octal} {
    list [run {string is integer -fail var 0o36963}] $var
} {0 4}
test string-6.59.$noComp {string is integer, false on bad hex} {
    list [run {string is integer -fail var 0X345XYZ}] $var
} {0 5}
test string-6.60.$noComp {string is lower, true} {
    run {string is lower abc}
} 1
test string-6.61.$noComp {string is lower, unicode true} {
    run {string is lower abc\xFCue}
    run {string is lower abcüue}
} 1
test string-6.62.$noComp {string is lower, false} {
    list [run {string is lower -fail var aBc}] $var
} {0 1}
test string-6.63.$noComp {string is lower, false} {
    list [run {string is lower -fail var abc1}] $var
} {0 3}
test string-6.64.$noComp {string is lower, unicode false} {
    list [run {string is lower -fail var ab\xDCUE}] $var
    list [run {string is lower -fail var abÃœUE}] $var
} {0 2}
test string-6.65.$noComp {string is space, true} {
    run {string is space " \t\n\v\f"}
} 1
test string-6.66.$noComp {string is space, false} {
    list [run {string is space -fail var " \t\n\v1\f"}] $var
} {0 4}
758
759
760
761
762
763
764
765

766
767
768
769
770
771
772
773
774

775
776
777
778
779
780

781
782
783
784
785
786
787
818
819
820
821
822
823
824

825
826
827
828
829
830
831
832
833

834
835
836
837
838
839

840
841
842
843
844
845
846
847







-
+








-
+





-
+







    catch {unset var}
    list [run {string is true -fail var no}] $var
} {0 0}
test string-6.75.$noComp {string is upper, true} {
    run {string is upper ABC}
} 1
test string-6.76.$noComp {string is upper, unicode true} {
    run {string is upper ABC\xDCUE}
    run {string is upper ABCÃœUE}
} 1
test string-6.77.$noComp {string is upper, false} {
    list [run {string is upper -fail var AbC}] $var
} {0 1}
test string-6.78.$noComp {string is upper, false} {
    list [run {string is upper -fail var AB2C}] $var
} {0 2}
test string-6.79.$noComp {string is upper, unicode false} {
    list [run {string is upper -fail var ABC\xFCue}] $var
    list [run {string is upper -fail var ABCüue}] $var
} {0 3}
test string-6.80.$noComp {string is wordchar, true} {
    run {string is wordchar abc_123}
} 1
test string-6.81.$noComp {string is wordchar, unicode true} {
    run {string is wordchar abc\xFCab\xDCAB\u5001\U1D7CA}
    run {string is wordchar abcüabÃœABå€\U1D7CA}
} 1
test string-6.82.$noComp {string is wordchar, false} {
    list [run {string is wordchar -fail var abcd.ef}] $var
} {0 4}
test string-6.83.$noComp {string is wordchar, unicode false} {
    list [run {string is wordchar -fail var abc\x80def}] $var
} {0 3}
842
843
844
845
846
847
848
849

850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867

868
869
870

871
872
873
874
875
876
877
902
903
904
905
906
907
908

909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926

927
928
929

930
931
932
933
934
935
936
937







-
+

















-
+


-
+







    set x 0x10000000000000000
    run {string is integer [expr {$x}]}
} 1
test string-6.95.$noComp {string is wideinteger, true} {
    run {string is wideinteger +1234567890}
} 1
test string-6.96.$noComp {string is wideinteger, true on type} {
    run {string is wideinteger [expr wide(50.0)]}
    run {string is wideinteger [expr {wide(50.0)}]}
} 1
test string-6.97.$noComp {string is wideinteger, true} {
    run {string is wideinteger [list -10]}
} 1
test string-6.98.$noComp {string is wideinteger, true as hex} {
    run {string is wideinteger 0xabcdef}
} 1
test string-6.99.$noComp {string is wideinteger, true as octal} {
    run {string is wideinteger 0123456}
} 1
test string-6.100.$noComp {string is wideinteger, true with whitespace} {
    run {string is wideinteger "  \n1234\v"}
} 1
test string-6.101.$noComp {string is wideinteger, false} {
    list [run {string is wideinteger -fail var 123abc}] $var
} {0 3}
test string-6.102.$noComp {string is wideinteger, false on overflow} {
    list [run {string is wideinteger -fail var +[largest_int]0}] $var
    list [run {string is wideinteger -fail var +9223372036854775808}] $var
} {0 -1}
test string-6.103.$noComp {string is wideinteger, false} {
    list [run {string is wideinteger -fail var [expr double(1)]}] $var
    list [run {string is wideinteger -fail var [expr {double(1)}]}] $var
} {0 1}
test string-6.104.$noComp {string is wideinteger, false} {
    list [run {string is wideinteger -fail var "    "}] $var
} {0 0}
test string-6.105.$noComp {string is wideinteger, false on bad octal} {
    list [run {string is wideinteger -fail var 0o36963}] $var
} {0 4}
898
899
900
901
902
903
904
905

906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926

927
928
929
930
931
932
933
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







-
+




















-
+







test string-6.109.$noComp {string is double, Bug 1360532} {
    run {string is double 1\xA0}
} 0
test string-6.110.$noComp {string is entier, true} {
    run {string is entier +1234567890}
} 1
test string-6.111.$noComp {string is entier, true on type} {
    run {string is entier [expr wide(50.0)]}
    run {string is entier [expr {wide(50.0)}]}
} 1
test string-6.112.$noComp {string is entier, true} {
    run {string is entier [list -10]}
} 1
test string-6.113.$noComp {string is entier, true as hex} {
    run {string is entier 0xabcdef}
} 1
test string-6.114.$noComp {string is entier, true as octal} {
    run {string is entier 0123456}
} 1
test string-6.115.$noComp {string is entier, true with whitespace} {
    run {string is entier "  \n1234\v"}
} 1
test string-6.116.$noComp {string is entier, false} {
    list [run {string is entier -fail var 123abc}] $var
} {0 3}
test string-6.117.$noComp {string is entier, false} {
    list [run {string is entier -fail var 123123123123123123123123123123123123123123123123123123123123123123123123123123123123abc}] $var
} {0 84}
test string-6.118.$noComp {string is entier, false} {
    list [run {string is entier -fail var [expr double(1)]}] $var
    list [run {string is entier -fail var [expr {double(1)}]}] $var
} {0 1}
test string-6.119.$noComp {string is entier, false} {
    list [run {string is entier -fail var "    "}] $var
} {0 0}
test string-6.120.$noComp {string is entier, false on bad octal} {
    list [run {string is entier -fail var 0o36963}] $var
} {0 4}
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
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
1116
1117
1118
1119
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
1116
1117
1118
1119
1120
1121
1122
1123
1124

1125
1126
1127

1128
1129
1130

1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145

1146
1147


1148
1149
1150


1151
1152
1153
1154
1155
1156
1157

1158
1159
1160

1161
1162
1163

1164
1165
1166
1167
1168
1169
1170
1171







+
+
+
+
+
+

-




















-
+


-
+


-
+


-
+


-
+


-
+










-
+


-
+


-
-
-
-
-
-
-
-
-
-
-
-
-













-
+



















-
+


-
+


-
+














-
+

-
-
+
+

-
-
+
+





-
+


-
+


-
+







} {0 87}
test string-6.130.1.$noComp {string is entier, false on bad octal} {
    list [run {string is entier -fail var 0o1234561123412345612345656234561234561234561234561234561234561234561234561234561234536963}] $var
} {0 87}
test string-6.131.$noComp {string is entier, false on bad hex} {
    list [run {string is entier -fail var 0X12345611234123456123456562345612345612345612345612345612345612345612345612345612345345XYZ}] $var
} {0 88}
test string-6.139.$noComp {string is integer, bug [76ad7aeba3]} {
    run {string is integer 18446744073709551615}
} 1
test string-6.140.$noComp {string is integer, bug [76ad7aeba3]} {
    run {string is integer -18446744073709551615}
} 1

catch {rename largest_int {}}

test string-7.1.$noComp {string last, not enough args} {
    list [catch {run {string last a}} msg] $msg
} {1 {wrong # args: should be "string last needleString haystackString ?lastIndex?"}}
test string-7.2.$noComp {string last, bad args} {
    list [catch {run {string last a b c}} msg] $msg
} {1 {bad index "c": must be integer?[+-]integer? or end?[+-]integer?}}
test string-7.3.$noComp {string last, too many args} {
    list [catch {run {string last a b c d}} msg] $msg
} {1 {wrong # args: should be "string last needleString haystackString ?lastIndex?"}}
test string-7.4.$noComp {string last} {
    run {string la xxx xxxx123xx345x678}
} 1
test string-7.5.$noComp {string last} {
    run {string last xx xxxx123xx345x678}
} 7
test string-7.6.$noComp {string last} {
    run {string las x xxxx123xx345x678}
} 12
test string-7.7.$noComp {string last, unicode} {
    run {string las x xxxx12\u7266xx345x678}
    run {string las x xxxx12牦xx345x678}
} 12
test string-7.8.$noComp {string last, unicode} {
    run {string las \u7266 xxxx12\u7266xx345x678}
    run {string las 牦 xxxx12牦xx345x678}
} 6
test string-7.9.$noComp {string last, stop index} {
    run {string las \u7266 xxxx12\u7266xx345x678}
    run {string las 牦 xxxx12牦xx345x678}
} 6
test string-7.10.$noComp {string last, unicode} {
    run {string las \u7266 xxxx12\u7266xx345x678}
    run {string las 牦 xxxx12牦xx345x678}
} 6
test string-7.11.$noComp {string last, start index} {
    run {string last \u7266 abc\u7266x 3}
    run {string last 牦 abc牦x 3}
} 3
test string-7.12.$noComp {string last, start index} {
    run {string last \u7266 abc\u7266x 2}
    run {string last 牦 abc牦x 2}
} -1
test string-7.13.$noComp {string last, start index} {
    ## Constrain to last 'a' should work
    run {string last ba badbad end-1}
} 3
test string-7.14.$noComp {string last, start index} {
    ## Constrain to last 'b' should skip last 'ba'
    run {string last ba badbad end-2}
} 0
test string-7.15.$noComp {string last, start index} {
    run {string last \334a \334ad\334ad 0}
    run {string last Ãœa ÃœadÃœad 0}
} -1
test string-7.16.$noComp {string last, start index} {
    run {string last \334a \334ad\334ad end-1}
    run {string last Ãœa ÃœadÃœad end-1}
} 3

test string-8.1.$noComp {string bytelength} {
    list [catch {run {string bytelength}} msg] $msg
} {1 {wrong # args: should be "string bytelength string"}}
test string-8.2.$noComp {string bytelength} {
    list [catch {run {string bytelength a b}} msg] $msg
} {1 {wrong # args: should be "string bytelength string"}}
test string-8.3.$noComp {string bytelength} {
    run {string bytelength "\xC7"}
} 2
test string-8.4.$noComp {string bytelength} {
    run {string b ""}
} 0

test string-9.1.$noComp {string length} {
    list [catch {run {string length}} msg] $msg
} {1 {wrong # args: should be "string length string"}}
test string-9.2.$noComp {string length} {
    list [catch {run {string length a b}} msg] $msg
} {1 {wrong # args: should be "string length string"}}
test string-9.3.$noComp {string length} {
    run {string length "a little string"}
} 15
test string-9.4.$noComp {string length} {
    run {string le ""}
} 0
test string-9.5.$noComp {string length, unicode} {
    run {string le "abcd\u7266"}
    run {string le "abcd牦"}
} 5
test string-9.6.$noComp {string length, bytearray object} {
    run {string length [binary format a5 foo]}
} 5
test string-9.7.$noComp {string length, bytearray object} {
    run {string length [binary format I* {0x50515253 0x52}]}
} 8

test string-10.1.$noComp {string map, not enough args} {
    list [catch {run {string map}} msg] $msg
} {1 {wrong # args: should be "string map ?-nocase? charMap string"}}
test string-10.2.$noComp {string map, bad args} {
    list [catch {run {string map {a b} abba oops}} msg] $msg
} {1 {bad option "a b": must be -nocase}}
test string-10.3.$noComp {string map, too many args} {
    list [catch {run {string map -nocase {a b} str1 str2}} msg] $msg
} {1 {wrong # args: should be "string map ?-nocase? charMap string"}}
test string-10.4.$noComp {string map} {
    run {string map {a b} abba}
} {bbbb}
} bbbb
test string-10.5.$noComp {string map} {
    run {string map {a b} a}
} {b}
} b
test string-10.6.$noComp {string map -nocase} {
    run {string map -nocase {a b} Abba}
} {bbbb}
} bbbb
test string-10.7.$noComp {string map} {
    run {string map {abc 321 ab * a A} aabcabaababcab}
} {A321*A*321*}
test string-10.8.$noComp {string map -nocase} {
    run {string map -nocase {aBc 321 Ab * a A} aabcabaababcab}
} {A321*A*321*}
test string-10.9.$noComp {string map -nocase} {
    run {string map -no {abc 321 Ab * a A} aAbCaBaAbAbcAb}
} {A321*A*321*}
test string-10.10.$noComp {string map} {
    list [catch {run {string map {a b c} abba}} msg] $msg
} {1 {char map list unbalanced}}
test string-10.11.$noComp {string map, nulls} {
    run {string map {\x00 NULL blah \x00nix} {qwerty}}
} {qwerty}
} qwerty
test string-10.12.$noComp {string map, unicode} {
    run {string map [list \374 ue UE \334] "a\374ueUE\000EU"}
} aueue\334\0EU
    run {string map [list ü ue UE Ü] "aüueUE\x00EU"}
} aueueÜ\x00EU
test string-10.13.$noComp {string map, -nocase unicode} {
    run {string map -nocase [list \374 ue UE \334] "a\374ueUE\000EU"}
} aue\334\334\0EU
    run {string map -nocase [list ü ue UE Ü] "aüueUE\x00EU"}
} aueÜÜ\x00EU
test string-10.14.$noComp {string map, -nocase null arguments} {
    run {string map -nocase {{} abc} foo}
} foo
test string-10.15.$noComp {string map, one pair case} {
    run {string map -nocase {abc 32} aAbCaBaAbAbcAb}
} {a32aBaAb32Ab}
} a32aBaAb32Ab
test string-10.16.$noComp {string map, one pair case} {
    run {string map -nocase {ab 4321} aAbCaBaAbAbcAb}
} {a4321C4321a43214321c4321}
} a4321C4321a43214321c4321
test string-10.17.$noComp {string map, one pair case} {
    run {string map {Ab 4321} aAbCaBaAbAbcAb}
} {a4321CaBa43214321c4321}
} a4321CaBa43214321c4321
test string-10.18.$noComp {string map, empty argument} {
    run {string map -nocase {{} abc} foo}
} foo
test string-10.19.$noComp {string map, empty arguments} {
    run {string map -nocase {{} abc f bar {} def} foo}
} baroo
test string-10.20.$noComp {string map, dictionaries don't alter map ordering} {
1297
1298
1299
1300
1301
1302
1303
1304

1305
1306
1307
1308
1309
1310
1311
1349
1350
1351
1352
1353
1354
1355

1356
1357
1358
1359
1360
1361
1362
1363







-
+







test string-11.31.$noComp {string match case} {
    run {string match a A}
} 0
test string-11.32.$noComp {string match nocase} {
    run {string match -n a A}
} 1
test string-11.33.$noComp {string match nocase} {
    run {string match -nocase a\334 A\374}
    run {string match -nocase aÜ Aü}
} 1
test string-11.34.$noComp {string match nocase} {
    run {string match -nocase a*f ABCDEf}
} 1
test string-11.35.$noComp {string match case, false hope} {
    # This is true because '_' lies between the A-Z and a-z ranges
    run {string match {[A-z]} _}
1412
1413
1414
1415
1416
1417
1418
1419

1420
1421
1422
1423
1424
1425
1426
1464
1465
1466
1467
1468
1469
1470

1471
1472
1473
1474
1475
1476
1477
1478







-
+







} {0 1 1 1 0 0}
test string-11.55.$noComp {string match, invalid binary optimization} {
    [format string] match \u0141 [binary format c 65]
} 0

test stringComp-12.1.0.$noComp {Bug 3588366: end-offsets before start} {
    apply {s {
        string range $s 0 end-5
	string range $s 0 end-5
    }} 12345
} {}
test string-12.1.$noComp {string range} {
    list [catch {run {string range}} msg] $msg
} {1 {wrong # args: should be "string range string first last"}}
test string-12.2.$noComp {string range} {
    list [catch {run {string range a 1}} msg] $msg
1464
1465
1466
1467
1468
1469
1470
1471

1472
1473
1474
1475


1476
1477
1478
1479
1480
1481
1482
1516
1517
1518
1519
1520
1521
1522

1523
1524
1525


1526
1527
1528
1529
1530
1531
1532
1533
1534







-
+


-
-
+
+







test string-12.15.$noComp {string range} {
    run {string range abcdefghijklmnop end 1000}
} {p}
test string-12.16.$noComp {string range} {
    run {string range abcdefghijklmnop end end-1}
} {}
test string-12.17.$noComp {string range, unicode} {
    run {string range ab\u7266cdefghijklmnop 5 5}
    run {string range ab牦cdefghijklmnop 5 5}
} e
test string-12.18.$noComp {string range, unicode} {
    run {string range ab\u7266cdefghijklmnop 2 3}
} \u7266c
    run {string range ab牦cdefghijklmnop 2 3}
} 牦c
test string-12.19.$noComp {string range, bytearray object} {
    set b [binary format I* {0x50515253 0x52}]
    set r1 [run {string range $b 1 end-1}]
    set r2 [run {string range $b 1 6}]
    run {string equal $r1 $r2}
} 1
test string-12.20.$noComp {string range, out of bounds indices} {
1499
1500
1501
1502
1503
1504
1505
1506

1507
1508
1509
1510
1511
1512
1513
1551
1552
1553
1554
1555
1556
1557

1558
1559
1560
1561
1562
1563
1564
1565







-
+







    list $input_hex $rxBuffer_hex $rxCRC_hex
} {000341 000341 0341}
test string-12.22.$noComp {string range, shimmering binary/index} {
    set s 0000000001
    binary scan $s a* x
    run {string range $s $s end}
} 000000001
test string-12.23.$noComp {string range, surrogates, bug [11ae2be95dac9417]} fullutf {
test string-12.23.$noComp {string range, surrogates, bug [11ae2be95dac9417]} {
    run {list [string range a\U100000b 1 1] [string range a\U100000b 2 2] [string range a\U100000b 3 3]}
} [list \U100000 b {}]
test string-12.24.$noComp {bignum index arithmetic} -setup {
    proc demo {i j} {string range fubar $i $j}
} -cleanup {
    rename demo {}
} -body {
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
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







-
-
+
+





-
-
+
+

















-
+


-
+


-
+


-
+


-
+


-
+







test string-13.10.$noComp {string repeat} {
    run {string repeat def 0}
} {}
test string-13.11.$noComp {string repeat} {
    run {string repeat def 1}
} def
test string-13.12.$noComp {string repeat} {
    run {string repeat ab\u7266cd 3}
} ab\u7266cdab\u7266cdab\u7266cd
    run {string repeat ab牦cd 3}
} ab牦cdab牦cdab牦cd
test string-13.13.$noComp {string repeat} {
    run {string repeat \x00 3}
} \x00\x00\x00
test string-13.14.$noComp {string repeat} {
    # The string range will ensure us that string repeat gets a unicode string
    run {string repeat [run {string range ab\u7266cd 2 3}] 3}
} \u7266c\u7266c\u7266c
    run {string repeat [run {string range ab牦cd 2 3}] 3}
} 牦c牦c牦c

test string-14.1.$noComp {string replace} {
    list [catch {run {string replace}} msg] $msg
} {1 {wrong # args: should be "string replace string first last ?string?"}}
test string-14.2.$noComp {string replace} {
    list [catch {run {string replace a 1}} msg] $msg
} {1 {wrong # args: should be "string replace string first last ?string?"}}
test string-14.3.$noComp {string replace} {
    list [catch {run {string replace a 1 2 3 4}} msg] $msg
} {1 {wrong # args: should be "string replace string first last ?string?"}}
test string-14.4.$noComp {string replace} {
} {}
test string-14.5.$noComp {string replace} {
    run {string replace abcdefghijklmnop 2 14}
} {abp}
test string-14.6.$noComp {string replace} -body {
    run {string replace abcdefghijklmnop 7 1000}
} -result {abcdefg}
} -result abcdefg
test string-14.7.$noComp {string replace} {
    run {string replace abcdefghijklmnop 10 end}
} {abcdefghij}
} abcdefghij
test string-14.8.$noComp {string replace} {
    run {string replace abcdefghijklmnop 10 9}
} {abcdefghijklmnop}
} abcdefghijklmnop
test string-14.9.$noComp {string replace} {
    run {string replace abcdefghijklmnop -3 2}
} {defghijklmnop}
} defghijklmnop
test string-14.10.$noComp {string replace} {
    run {string replace abcdefghijklmnop -3 -2}
} {abcdefghijklmnop}
} abcdefghijklmnop
test string-14.11.$noComp {string replace} -body {
    run {string replace abcdefghijklmnop 1000 1010}
} -result {abcdefghijklmnop}
} -result abcdefghijklmnop
test string-14.12.$noComp {string replace} {
    run {string replace abcdefghijklmnop -100 end}
} {}
test string-14.13.$noComp {string replace} {
    list [catch {run {string replace abc abc 1}} msg] $msg
} {1 {bad index "abc": must be integer?[+-]integer? or end?[+-]integer?}}
test string-14.14.$noComp {string replace} {
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
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







+
+
+
+
+
+
+
+
+
+
+
+




-
-
-
+
+
+





-
-
-
-
-
+
+
+
+
+




-
-
-
-
+
+
+
+




-
-
-
-
-
-
+
+
+
+
+
+







test string-14.19.$noComp {string replace} {
    run {string replace {} -1 0 A}
} A
test string-14.20.$noComp {string replace} {
    run {string replace [makeByteArray abcdefghijklmnop] end-10 end-2\
	    [makeByteArray NEW]}
} {abcdeNEWop}
test string-14.21.$noComp {string replace (surrogates)} {
    run {string replace \uD83D? 1 end \uDE02}
} \uD83D\uDE02
test string-14.22.$noComp {string replace (surrogates)} {
    run {string replace ?\uDE02 0 end-1 \uD83D}
} \uD83D\uDE02
test string-14.23.$noComp {string replace \xC0 \x80} testbytestring {
    run {string length [string replace [testbytestring \xC0]? 1 end [testbytestring \x80]]}
} 2
test string-14.24.$noComp {string replace \xC0 \x80} testbytestring {
    run {string length [string replace ?[testbytestring \x80] 0 end-1 [testbytestring \xC0]]}
} 2


test stringComp-14.21.$noComp {Bug 82e7f67325} {
    apply {x {
        set a [join $x {}]
        lappend b [string length [string replace ___! 0 2 $a]]
        lappend b [string length [string replace ___! 0 2 $a[unset a]]]
	set a [join $x {}]
	lappend b [string length [string replace ___! 0 2 $a]]
	lappend b [string length [string replace ___! 0 2 $a[unset a]]]
    }} {a b}
} {3 3}
test stringComp-14.22.$noComp {Bug 82e7f67325} memory {
    # As in stringComp-14.1, but make sure we don't retain too many refs
    leaktest {
        apply {x {
            set a [join $x {}]
            lappend b [string length [string replace ___! 0 2 $a]]
            lappend b [string length [string replace ___! 0 2 $a[unset a]]]
        }} {a b}
	apply {x {
	    set a [join $x {}]
	    lappend b [string length [string replace ___! 0 2 $a]]
	    lappend b [string length [string replace ___! 0 2 $a[unset a]]]
	}} {a b}
    }
} {0}
test stringComp-14.23.$noComp {Bug 0dca3bfa8f} {
    apply {arg {
        set argCopy $arg
        set arg [string replace $arg 1 2 aa]
        # Crashes in comparison before fix
        expr {$arg ne $argCopy}
	set argCopy $arg
	set arg [string replace $arg 1 2 aa]
	# Crashes in comparison before fix
	expr {$arg ne $argCopy}
    }} abcde
} 1
test stringComp-14.24.$noComp {Bug 1af8de570511} {
    apply {{x y} {
        # Generate an unshared string value
        set val ""
        for { set i 0 } { $i < $x } { incr i } {
            set val [format "0%s" $val]
        }
        string replace $val[unset val] 1 1 $y
	# Generate an unshared string value
	set val ""
	for { set i 0 } { $i < $x } { incr i } {
	    set val [format "0%s" $val]
	}
	string replace $val[unset val] 1 1 $y
    }} 4 x
} 0x00
test stringComp-14.25.$noComp {} {
    string length [string replace [string repeat a\xFE 2] 3 end {}]
} 3
test stringComp-14.26.$noComp {} {
    run {string replace abcd 0x10000000000000000-0xffffffffffffffff 2 e}
1757
1758
1759
1760
1761
1762
1763
1764

1765
1766
1767
1768
1769
1770
1771
1821
1822
1823
1824
1825
1826
1827

1828
1829
1830
1831
1832
1833
1834
1835







-
+







} "Abcabc\xE7\xE7"
test string-17.7.$noComp {string totitle, unicode} {
    run {string totitle \u01F3BCabc\xC7\xE7}
} "\u01F2bcabc\xE7\xE7"
test string-17.8.$noComp {string totitle, compiled} {
    lindex [run {string totitle [list aa bb [list cc]]}] 0
} Aa
test string-17.9.$noComp {string totitle, surrogates, bug [11ae2be95dac9417]} fullutf {
test string-17.9.$noComp {string totitle, surrogates, bug [11ae2be95dac9417]} {
    run {list [string totitle a\U118c0c 1 1] [string totitle a\U118c0c 2 2] \
	[string totitle a\U118c0c 3 3]}
} [list a\U118a0c a\U118c0C a\U118c0c]

test string-18.1.$noComp {string trim} {
    list [catch {run {string trim}} msg] $msg
} {1 {wrong # args: should be "string trim string ?chars?"}}
1812
1813
1814
1815
1816
1817
1818
1819

1820
1821

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

1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847

1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860

1861
1862
1863
1864
1865
1866
1867
1876
1877
1878
1879
1880
1881
1882

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







-
+

-
+












-
+












-
+












-
+







test string-19.3.$noComp {string trimleft, unicode default} {
    run {string trimleft \uFEFF\x85\xA0\x00\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u200B\u2028\u2029\u202F\u205F\u3000\u1361ABC}
} \u1361ABC

test string-20.1.$noComp {string trimright errors} {
    list [catch {run {string trimright}} msg] $msg
} {1 {wrong # args: should be "string trimright string ?chars?"}}
test string-20.2.$noComp {string trimright errors} {
test string-20.2.$noComp {string trimright errors} -body {
    list [catch {run {string trimg a}} msg] $msg
} {1 {unknown or ambiguous subcommand "trimg": must be bytelength, cat, compare, equal, first, index, insert, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstart}}
} -result {1 {unknown or ambiguous subcommand "trimg": must be cat, compare, equal, first, index, insert, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstart}}
test string-20.3.$noComp {string trimright} {
    run {string trimright "    XYZ      "}
} {    XYZ}
test string-20.4.$noComp {string trimright} {
    run {string trimright "   "}
} {}
test string-20.5.$noComp {string trimright} {
    run {string trimright ""}
} {}
test string-20.6.$noComp {string trimright, unicode default} {
    run {string trimright ABC\u1361\x85\x00\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u200B\u2028\u2029\u202F\u205F\u3000}
} ABC\u1361
test string-20.7.$noComp {string trim on not valid utf-8 sequence (consider NTS as continuation char), bug [c61818e4c9]} {testbytestring} {
test string-20.7.$noComp {string trim on not valid utf-8 sequence (consider NTS as continuation char), bug [c61818e4c9]} testbytestring {
    set result {}
    set a [testbytestring \xC0\x80\xA0]
    set b foo$a
    set m [list \x00 U \xA0 V [testbytestring \xA0] W]
    lappend result [string map $m $b]
    lappend result [string map $m [run {string trimright $b x}]]
    lappend result [string map $m [run {string trimright $b \x00}]]
    lappend result [string map $m [run {string trimleft $b fox}]]
    lappend result [string map $m [run {string trimleft $b fo\x00}]]
    lappend result [string map $m [run {string trim $b fox}]]
    lappend result [string map $m [run {string trim $b fo\x00}]]
} [list {*}[lrepeat 3 fooUV] {*}[lrepeat 2 UV V]]
test string-20.8.$noComp {[c61818e4c9] [string trimright] fails when UtfPrev is ok} {testbytestring} {
test string-20.8.$noComp {[c61818e4c9] [string trimright] fails when UtfPrev is ok} testbytestring {
    set result {}
    set a [testbytestring \xE8\xA0]
    set b foo$a
    set m [list \xE8 U \xA0 V [testbytestring \xE8] W [testbytestring \xA0] X]]
    lappend result [string map $m $b]
    lappend result [string map $m [run {string trimright $b x}]]
    lappend result [string map $m [run {string trimright $b \xE8}]]
    lappend result [string map $m [run {string trimright $b [testbytestring \xE8]}]]
    lappend result [string map $m [run {string trimright $b \xA0}]]
    lappend result [string map $m [run {string trimright $b [testbytestring \xA0]}]]
    lappend result [string map $m [run {string trimright $b \xE8\xA0}]]
    lappend result [string map $m [run {string trimright $b [testbytestring \xE8\xA0]}]]
    lappend result [string map $m [run {string trimright $b \u0000}]]
    lappend result [string map $m [run {string trimright $b \x00}]]
} [list {*}[lrepeat 4 fooUV] {*}[lrepeat 2 fooU] {*}[lrepeat 2 foo] fooUV]

test string-21.1.$noComp {string wordend} -body {
    list [catch {run {string wordend a}} msg] $msg
} -result {1 {wrong # args: should be "string wordend string index"}}
test string-21.2.$noComp {string wordend} -body {
    list [catch {run {string wordend a b c}} msg] $msg
1901
1902
1903
1904
1905
1906
1907
1908

1909
1910



























1911
1912
1913
1914

1915
1916
1917
1918
1919
1920
1921
1965
1966
1967
1968
1969
1970
1971

1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004

2005
2006
2007
2008
2009
2010
2011
2012







-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+







} -result 3
test string-21.14.$noComp {string wordend, unicode} -body {
    run {string wordend "\uC700\uC700 abc" 8}
} -result 6
test string-21.15.$noComp {string wordend, unicode} -body {
    run {string wordend "\U1D7CA\U1D7CA abc" 0}
} -result 2
test string-21.16.$noComp {string wordend, unicode} -constraints fullutf -body {
test string-21.16.$noComp {string wordend, unicode} -body {
    run {string wordend "\U1D7CA\U1D7CA abc" 10}
} -result 6
test string-21.17.$noComp {string trim, unicode} {
    run {string trim "\uD83D\uDE02Hello world!\uD83D\uDE02" \uD83D\uDE02}
} "Hello world!"
test string-21.18.$noComp {string trimleft, unicode} {
    run {string trimleft "\uD83D\uDE02Hello world!\uD83D\uDE02" \uD83D\uDE02}
} "Hello world!\uD83D\uDE02"
test string-21.19.$noComp {string trimright, unicode} {
    run {string trimright "\uD83D\uDE02Hello world!\uD83D\uDE02" \uD83D\uDE02}
} "\uD83D\uDE02Hello world!"
test string-21.20.$noComp {string trim, unicode} {
    run {string trim "\uF602Hello world!\uF602" \uD83D\uDE02}
} "\uF602Hello world!\uF602"
test string-21.21.$noComp {string trimleft, unicode} {
    run {string trimleft "\uF602Hello world!\uF602" \uD83D\uDE02}
} "\uF602Hello world!\uF602"
test string-21.22.$noComp {string trimright, unicode} {
    run {string trimright "\uF602Hello world!\uF602" \uD83D\uDE02}
} "\uF602Hello world!\uF602"
test string-21.23.$noComp {string trim, unicode} {
    run {string trim "\uD83D\uDE02Hello world!\uD83D\uDE02" \uD93D}
} "\uD83D\uDE02Hello world!\uD83D\uDE02"
test string-21.24.$noComp {string trimleft, unicode} {
    run {string trimleft "\uD83D\uDE02Hello world!\uD83D\uDE02" \uD93D\uDE02}
} "\uD83D\uDE02Hello world!\uD83D\uDE02"
test string-21.25.$noComp {string trimright, unicode} {
    run {string trimright "\uD83D\uDE02Hello world!\uD83D\uDE02" \uD93D}
} "\uD83D\uDE02Hello world!\uD83D\uDE02"

test string-22.1.$noComp {string wordstart} -body {
    list [catch {run {string word a}} msg] $msg
} -result {1 {unknown or ambiguous subcommand "word": must be bytelength, cat, compare, equal, first, index, insert, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstart}}
} -result {1 {unknown or ambiguous subcommand "word": must be cat, compare, equal, first, index, insert, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstart}}
test string-22.2.$noComp {string wordstart} -body {
    list [catch {run {string wordstart a}} msg] $msg
} -result {1 {wrong # args: should be "string wordstart string index"}}
test string-22.3.$noComp {string wordstart} -body {
    list [catch {run {string wordstart a b c}} msg] $msg
} -result {1 {wrong # args: should be "string wordstart string index"}}
test string-22.4.$noComp {string wordstart} -body {
1952
1953
1954
1955
1956
1957
1958
1959

1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988


















1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011


















2012
2013
2014
2015
2016
2017
2018
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109







-
+











-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    # See Bug c61818e4c9
    set demo [testbytestring "abc def\xE0\xA9ghi"]
    run {string index $demo [string wordstart $demo 10]}
} -result g
test string-22.15.$noComp {string wordstart, unicode} -body {
    run {string wordstart "\U1D7CA\U1D7CA abc" 0}
} -result 0
test string-22.16.$noComp {string wordstart, unicode} -constraints fullutf -body {
test string-22.16.$noComp {string wordstart, unicode} -body {
    run {string wordstart "\U1D7CA\U1D7CA abc" 10}
} -result 3

test string-23.0.$noComp {string is boolean, Bug 1187123} testindexobj {
    set x 5
    catch {testindexobj $x foo bar soom}
    run {string is boolean $x}
} 0
test string-23.1.$noComp {string is command with empty string} {
    set s ""
    list \
        [run {string is alnum $s}] \
        [run {string is alpha $s}] \
        [run {string is ascii $s}] \
        [run {string is control $s}] \
        [run {string is boolean $s}] \
        [run {string is digit $s}] \
        [run {string is double $s}] \
        [run {string is false $s}] \
        [run {string is graph $s}] \
        [run {string is integer $s}] \
        [run {string is lower $s}] \
        [run {string is print $s}] \
        [run {string is punct $s}] \
        [run {string is space $s}] \
        [run {string is true $s}] \
        [run {string is upper $s}] \
        [run {string is wordchar $s}] \
        [run {string is xdigit $s}] \
	[run {string is alnum $s}] \
	[run {string is alpha $s}] \
	[run {string is ascii $s}] \
	[run {string is control $s}] \
	[run {string is boolean $s}] \
	[run {string is digit $s}] \
	[run {string is double $s}] \
	[run {string is false $s}] \
	[run {string is graph $s}] \
	[run {string is integer $s}] \
	[run {string is lower $s}] \
	[run {string is print $s}] \
	[run {string is punct $s}] \
	[run {string is space $s}] \
	[run {string is true $s}] \
	[run {string is upper $s}] \
	[run {string is wordchar $s}] \
	[run {string is xdigit $s}] \

} {1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1}
test string-23.2.$noComp {string is command with empty string} {
    set s ""
    list \
        [run {string is alnum -strict $s}] \
        [run {string is alpha -strict $s}] \
        [run {string is ascii -strict $s}] \
        [run {string is control -strict $s}] \
        [run {string is boolean -strict $s}] \
        [run {string is digit -strict $s}] \
        [run {string is double -strict $s}] \
        [run {string is false -strict $s}] \
        [run {string is graph -strict $s}] \
        [run {string is integer -strict $s}] \
        [run {string is lower -strict $s}] \
        [run {string is print -strict $s}] \
        [run {string is punct -strict $s}] \
        [run {string is space -strict $s}] \
        [run {string is true -strict $s}] \
        [run {string is upper -strict $s}] \
        [run {string is wordchar -strict $s}] \
        [run {string is xdigit -strict $s}] \
	[run {string is alnum -strict $s}] \
	[run {string is alpha -strict $s}] \
	[run {string is ascii -strict $s}] \
	[run {string is control -strict $s}] \
	[run {string is boolean -strict $s}] \
	[run {string is digit -strict $s}] \
	[run {string is double -strict $s}] \
	[run {string is false -strict $s}] \
	[run {string is graph -strict $s}] \
	[run {string is integer -strict $s}] \
	[run {string is lower -strict $s}] \
	[run {string is print -strict $s}] \
	[run {string is punct -strict $s}] \
	[run {string is space -strict $s}] \
	[run {string is true -strict $s}] \
	[run {string is upper -strict $s}] \
	[run {string is wordchar -strict $s}] \
	[run {string is xdigit -strict $s}] \

} {0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}

test string-24.1.$noComp {string reverse command} -body {
    run {string reverse}
} -returnCodes error -result "wrong # args: should be \"string reverse string\""
test string-24.2.$noComp {string reverse command} -body {
2066
2067
2068
2069
2070
2071
2072


















2073
2074
2075
2076
2077
2078
2079
2157
2158
2159
2160
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    binary scan [run {string reverse [binary format H* 010203]}] H* x
    set x
} 030201
test string-24.15.$noComp {string reverse command - pure bytearray} {
    binary scan [run {tcl::string::reverse [binary format H* 010203]}] H* x
    set x
} 030201
test string-24.16.$noComp {string reverse command - surrogates} {
    run {string reverse \u0444bulb\uD83D\uDE02}
} \uDE02\uD83Dblub\u0444
test string-24.17.$noComp {string reverse command - surrogates} {
    run {string reverse \uD83D\uDE02hello\uD83D\uDE02}
} \uDE02\uD83Dolleh\uDE02\uD83D
test string-24.18.$noComp {string reverse command - surrogates} {
    set s \u0444bulb\uD83D\uDE02
    # shim shimmery ...
    string index $s 0
    run {string reverse $s}
} \uDE02\uD83Dblub\u0444
test string-24.19.$noComp {string reverse command - surrogates} {
    set s \uD83D\uDE02hello\uD83D\uDE02
    # shim shimmery ...
    string index $s 0
    run {string reverse $s}
} \uDE02\uD83Dolleh\uDE02\uD83D

test string-25.1.$noComp {string is list} {
    run {string is list {a b c}}
} 1
test string-25.2.$noComp {string is list} {
    run {string is list "a \{b c"}
} 0
2157
2158
2159
2160
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
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
2266
2267
2268
2269
2270
2271
2272






2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293









2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309





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







-
-
-
-
-
-
+
+
+
+
+
+















-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+







-
-
-
-
-
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+








-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+






-
-
-
-
-
-
-
+
+
+
+
+
+
+







    tcl::prefix match -error {} {apa bepa bear depa} be
} -returnCodes 0 -result {}
test string-26.10.$noComp {tcl::prefix} -body {
    tcl::prefix match -error {-level 1} {apa bepa bear depa} be
} -returnCodes 2 -result {ambiguous option "be": must be apa, bepa, bear, or depa}
test string-26.10.1.$noComp {tcl::prefix} -setup {
    proc _testprefix {args} {
        array set opts {-a x -b y -c y}
        foreach {opt val} $args {
            set opt [tcl::prefix match -error {-level 1} {-a -b -c} $opt]
            set opts($opt) $val
        }
        array get opts
	array set opts {-a x -b y -c y}
	foreach {opt val} $args {
	    set opt [tcl::prefix match -error {-level 1} {-a -b -c} $opt]
	    set opts($opt) $val
	}
	array get opts
    }
} -body {
    set a [catch {_testprefix -x u} result options]
    dict get $options -errorinfo
} -cleanup {
    rename _testprefix {}
} -result {bad option "-x": must be -a, -b, or -c
    while executing
"_testprefix -x u"}

# Helper for memory stress tests
# Repeat each body in a local space checking that memory does not increase
proc MemStress {args} {
    set res {}
    foreach body $args {
        set end 0
        for {set i 0} {$i < 5} {incr i} {
            proc MemStress_Body {} $body
            uplevel 1 MemStress_Body
            rename MemStress_Body {}
            set tmp $end
            set end [lindex [lindex [split [memory info] "\n"] 3] 3]
        }
        lappend res [expr {$end - $tmp}]
	set end 0
	for {set i 0} {$i < 5} {incr i} {
	    proc MemStress_Body {} $body
	    uplevel 1 MemStress_Body
	    rename MemStress_Body {}
	    set tmp $end
	    set end [lindex [lindex [split [memory info] "\n"] 3] 3]
	}
	lappend res [expr {$end - $tmp}]
    }
    return $res
}

test string-26.11.$noComp {tcl::prefix: testing for leaks} -body {
    # This test is made to stress object reference management
    MemStress {
        set table {hejj miff gurk}
        set item [lindex $table 1]
        # If not careful, this can cause a circular reference
        # that will cause a leak.
        tcl::prefix match $table $item
	set table {hejj miff gurk}
	set item [lindex $table 1]
	# If not careful, this can cause a circular reference
	# that will cause a leak.
	tcl::prefix match $table $item
    } {
        # A similar case with nested lists
        set table2 {hejj {miff maff} gurk}
        set item [lindex [lindex $table2 1] 0]
        tcl::prefix match $table2 $item
	# A similar case with nested lists
	set table2 {hejj {miff maff} gurk}
	set item [lindex [lindex $table2 1] 0]
	tcl::prefix match $table2 $item
    } {
        # A similar case with dict
        set table3 {hejj {miff maff} gurk2}
        set item [lindex [dict keys [lindex $table3 1]] 0]
        tcl::prefix match $table3 $item
	# A similar case with dict
	set table3 {hejj {miff maff} gurk2}
	set item [lindex [dict keys [lindex $table3 1]] 0]
	tcl::prefix match $table3 $item
    }
} -constraints memory -result {0 0 0}

test string-26.12.$noComp {tcl::prefix: testing for leaks} -body {
    # This is a memory leak test in a form that might actually happen
    # in real code.  The shared literal "miff" causes a connection
    # between the item and the table.
    MemStress {
        proc stress1 {item} {
            set table [list hejj miff gurk]
            tcl::prefix match $table $item
        }
        proc stress2 {} {
            stress1 miff
        }
        stress2
        rename stress1 {}
        rename stress2 {}
	proc stress1 {item} {
	    set table [list hejj miff gurk]
	    tcl::prefix match $table $item
	}
	proc stress2 {} {
	    stress1 miff
	}
	stress2
	rename stress1 {}
	rename stress2 {}
    }
} -constraints memory -result 0

test string-26.13.$noComp {tcl::prefix: testing for leaks} -body {
    # This test is made to stress object reference management
    MemStress {
        set table [list hejj miff]
        set item $table
        set error $table
        # Use the same objects in all places
        catch {
            tcl::prefix match -error $error $table $item
        }
	set table [list hejj miff]
	set item $table
	set error $table
	# Use the same objects in all places
	catch {
	    tcl::prefix match -error $error $table $item
	}
    }
} -constraints memory -result {0}

test string-27.1.$noComp {tcl::prefix all, not enough args} -body {
    tcl::prefix all a
} -returnCodes 1 -result {wrong # args: should be "tcl::prefix all table string"}
test string-27.2.$noComp {tcl::prefix all, bad args} -body {
2362
2363
2364
2365
2366
2367
2368
2369

2370
2371
2372
2373

2374
2375
2376
2377
2378
2379
2380
2471
2472
2473
2474
2475
2476
2477

2478
2479
2480
2481

2482
2483
2484
2485
2486
2487
2488
2489







-
+



-
+







test string-29.11.$noComp {string cat, efficiency} -body {
    tcl::unsupported::representation \
	[run {string cat [list x] [encoding convertto utf-8 {}]}]
} -match glob -result {*no string representation}
test string-29.12.$noComp {string cat, efficiency} -body {
    tcl::unsupported::representation \
	[run {string cat [encoding convertto utf-8 {}] [list x]}]
} -match glob -result {*, string representation "x"}
} -match glob -result {*, no string representation}
test string-29.13.$noComp {string cat, efficiency} -body {
    tcl::unsupported::representation [run {string cat \
	[encoding convertto utf-8 {}] [encoding convertto utf-8 {}] [list x]}]
} -match glob -result {*, string representation "x"}
} -match glob -result {*, no string representation}
test string-29.14.$noComp {string cat, efficiency} -setup {
    set e [encoding convertto utf-8 {}]
} -cleanup {
    unset e
} -body {
    tcl::unsupported::representation [run {string cat $e $e [list x]}]
} -match glob -result {*no string representation}
2441
2442
2443
2444
2445
2446
2447
2448

2449
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
2550
2551
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







-
+



-
+



-
+


















-
+







    run {tcl::string::insert [makeByteArray 0123] 4 [makeByteArray _]}
} 0123_
test string-31.15.$noComp {string insert, pure byte array, neither shared} {
    run {tcl::string::insert [makeByteArray 0123] 2 [makeByteArray _]}
} 01_23
test string-31.16.$noComp {string insert, pure byte array, first shared} {
    run {tcl::string::insert [makeShared [makeByteArray 0123]] 2\
            [makeByteArray _]}
	    [makeByteArray _]}
} 01_23
test string-31.17.$noComp {string insert, pure byte array, second shared} {
    run {tcl::string::insert [makeByteArray 0123] 2\
            [makeShared [makeByteArray _]]}
	    [makeShared [makeByteArray _]]}
} 01_23
test string-31.18.$noComp {string insert, pure byte array, both shared} {
    run {tcl::string::insert [makeShared [makeByteArray 0123]] 2\
            [makeShared [makeByteArray _]]}
	    [makeShared [makeByteArray _]]}
} 01_23
test string-31.19.$noComp {string insert, start of string, pure Unicode} {
    run {tcl::string::insert [makeUnicode 0123] 0 [makeUnicode _]}
} _0123
test string-31.20.$noComp {string insert, middle of string, pure Unicode} {
    run {tcl::string::insert [makeUnicode 0123] 2 [makeUnicode _]}
} 01_23
test string-31.21.$noComp {string insert, end of string, pure Unicode} {
    run {tcl::string::insert [makeUnicode 0123] 4 [makeUnicode _]}
} 0123_
test string-31.22.$noComp {string insert, str start, pure Uni, first shared} {
    run {tcl::string::insert [makeShared [makeUnicode 0123]] 0 [makeUnicode _]}
} _0123
test string-31.23.$noComp {string insert, string mid, pure Uni, 2nd shared} {
    run {tcl::string::insert [makeUnicode 0123] 2 [makeShared [makeUnicode _]]}
} 01_23
test string-31.24.$noComp {string insert, string end, pure Uni, both shared} {
    run {tcl::string::insert [makeShared [makeUnicode 0123]] 4\
            [makeShared [makeUnicode _]]}
	    [makeShared [makeUnicode _]]}
} 0123_
test string-31.25.$noComp {string insert, neither byte array nor Unicode} {
    run {tcl::string::insert [makeList a b c] 1 zzzzzz}
} {azzzzzz b c}
test string-31.26.$noComp {[11229bad5f] string insert, compiler} -setup {
    set i 2
} -body {

Changes to tests/stringObj.test.

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
30
31
32
33



34
35
36
37
38
39
40
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
30
31
32
33
34
35
36
37
38
39
40
41
42








-
-
+
+










-
+




-







+
+
+







# Commands covered: none
#
# This file contains tests for the procedures in tclStringObj.c that implement
# the Tcl type manager for the string type.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1995-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testobj [llength [info commands testobj]]
testConstraint testbytestring [llength [info commands testbytestring]]
testConstraint testdstring [llength [info commands testdstring]]
testConstraint fullutf [expr {[string length \U010000] == 1}]

test stringObj-1.1 {string type registration} testobj {
    set t [testobj types]
    set first [string first "string" $t]
    set result [expr {$first >= 0}]
} 1

set INT_MAX 0x7fffffff; # Assumes sizeof(int) == 4
set SIZE_MAX [expr {(1 << (8*$::tcl_platform(pointerSize) - 1)) - 1}]

test stringObj-2.1 {Tcl_NewStringObj} testobj {
    set result ""
    lappend result [testobj freeallvars]
    lappend result [teststringobj set 1 abcd]
    lappend result [testobj type 1]
    lappend result [testobj refcount 1]
} {{} abcd string 2}
63
64
65
66
67
68
69
70
71


72
73
74
75
76
77
78
79


80
81
82
83
84
85
86
65
66
67
68
69
70
71


72
73
74
75
76
77
78
79


80
81
82
83
84
85
86
87
88







-
-
+
+






-
-
+
+







    list [teststringobj length 1] [teststringobj length2 1] \
	    [teststringobj get 1]
} {3 4 tes}
test stringObj-4.2 {Tcl_SetObjLength procedure, string gets longer} testobj {
    testobj freeallvars
    teststringobj set 1 abcdef
    teststringobj setlength 1 10
    list [teststringobj length 1] [teststringobj length2 1]
} {10 10}
    teststringobj length 1
} 10
test stringObj-4.3 {Tcl_SetObjLength procedure, string gets longer} testobj {
    testobj freeallvars
    teststringobj set 1 abcdef
    teststringobj append 1 xyzq -1
    list [teststringobj length 1] [teststringobj length2 1] \
	    [teststringobj get 1]
} {10 20 abcdefxyzq}
test stringObj-4.4 {Tcl_SetObjLength procedure, "expty string", length 0} testobj {
} {10 15 abcdefxyzq}
test stringObj-4.4 {Tcl_SetObjLength procedure, "empty string", length 0} testobj {
    testobj freeallvars
    testobj newobj 1
    teststringobj setlength 1 0
    list [teststringobj length2 1] [teststringobj get 1]
} {0 {}}

test stringObj-5.1 {Tcl_AppendToObj procedure, type conversion} testobj {
104
105
106
107
108
109
110
111

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

113
114
115
116
117
118
119
120







-
+







    set result {}
    teststringobj append 1 1234567890123 -1
    lappend result [teststringobj length 1] [teststringobj length2 1]
    teststringobj setlength 1 10
    teststringobj append 1 abcdef -1
    lappend result [teststringobj length 1] [teststringobj length2 1] \
	    [teststringobj get 1]
} {15 15 16 32 xy12345678abcdef}
} {15 15 16 24 xy12345678abcdef}

test stringObj-6.1 {Tcl_AppendStringsToObj procedure, type conversion} testobj {
    testobj freeallvars
    teststringobj set2 1 [list a b]
    teststringobj appendstrings 1 xyz { 1234 } foo
    teststringobj get 1
} {a bxyz 1234 foo}
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
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







-
+

















-
+






-
+












-
+







    list [teststringobj length 1] [teststringobj get 1]
} {15 {abc 123 abcdefg}}
test stringObj-6.5 {Tcl_AppendStringsToObj procedure, don't double space if initial string empty} testobj {
    testobj freeallvars
    testobj newobj 1
    teststringobj appendstrings 1 123 abcdefg
    list [teststringobj length 1] [teststringobj length2 1] [teststringobj get 1]
} {10 20 123abcdefg}
} {10 15 123abcdefg}
test stringObj-6.6 {Tcl_AppendStringsToObj procedure, space reallocation} testobj {
    testobj freeallvars
    teststringobj set 1 abc
    teststringobj setlength 1 10
    teststringobj setlength 1 2
    teststringobj appendstrings 1 34567890
    list [teststringobj length 1] [teststringobj length2 1] \
	    [teststringobj get 1]
} {10 10 ab34567890}
test stringObj-6.7 {Tcl_AppendStringsToObj procedure, space reallocation} testobj {
    testobj freeallvars
    teststringobj set 1 abc
    teststringobj setlength 1 10
    teststringobj setlength 1 2
    teststringobj appendstrings 1 34567890x
    list [teststringobj length 1] [teststringobj length2 1] \
	    [teststringobj get 1]
} {11 22 ab34567890x}
} {11 17 ab34567890x}
test stringObj-6.8 {Tcl_AppendStringsToObj procedure, object totally empty} testobj {
    testobj freeallvars
    testobj newobj 1
    teststringobj appendstrings 1 {}
    list [teststringobj length2 1] [teststringobj get 1]
} {0 {}}
test stringObj-6.9 {Tcl_AppendStringToObj, pure unicode} testobj {
test stringObj-6.9 {Tcl_AppendStringsToObj, pure unicode} testobj {
    testobj freeallvars
    teststringobj set2 1 [string replace abc 1 1 d]
    teststringobj appendstrings 1 foo bar soom
    teststringobj get 1
} adcfoobarsoom

test stringObj-7.1 {SetStringFromAny procedure} testobj {
    testobj freeallvars
    teststringobj set2 1 [list a b]
    teststringobj append 1 x -1
    list [teststringobj length 1] [teststringobj length2 1] \
	    [teststringobj get 1]
} {4 8 {a bx}}
} {4 6 {a bx}}
test stringObj-7.2 {SetStringFromAny procedure, null object} testobj {
    testobj freeallvars
    testobj newobj 1
    teststringobj appendstrings 1 {}
    list [teststringobj length 1] [teststringobj length2 1] \
	    [teststringobj get 1]
} {0 0 {}}
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
366
367
368
369
370
371
372
373
374




375
376
377
378
379
380
381
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
366
367
368
369
370
371
372







-
+

-
+


-
+

-
+

-
+


-
+

-
+
















-
+

-
+




-
+

-
+



-
-
+
+




-
+




-
+

















-
+






-
+




















-
+




-
+



-
+


-
+








-
+









-
-
-
-
-

-
+



-
+

-
+
-
-
-



-
+

-
+
-
-
-






-
-
-
-
+
+
+
+







    teststringobj set 1 {}
    teststringobj append 1 abcde -1
    testobj duplicate 1 2
    list [teststringobj length 1] [teststringobj length2 1] \
	    [teststringobj maxchars 1] [teststringobj get 1] \
	    [teststringobj length 2] [teststringobj length2 2] \
	    [teststringobj maxchars 2] [teststringobj get 2]
} {5 10 0 abcde 5 5 0 abcde}
} {5 8 0 abcde 5 5 0 abcde}
test stringObj-8.2 {DupUnicodeInternalRep, mixed width chars} testobj {
    set x abc\u00ef\u00bf\u00aeghi
    set x abc\xEF\xBF\xAEghi
    string length $x
    set y $x
    list [testobj objtype $x] [testobj objtype $y] [append x "\u00ae\u00bf\u00ef"] \
    list [testobj objtype $x] [testobj objtype $y] [append x "\xAE\xBF\xEF"] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} "string string abc\u00ef\u00bf\u00aeghi\u00ae\u00bf\u00ef abc\u00ef\u00bf\u00aeghi string string"
} "string string abc\xEF\xBF\xAEghi\xAE\xBF\xEF abc\xEF\xBF\xAEghi string string"
test stringObj-8.3 {DupUnicodeInternalRep, mixed width chars} testobj {
    set x abc\u00ef\u00bf\u00aeghi
    set x abc\xEF\xBF\xAEghi
    set y $x
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x "\u00ae\u00bf\u00ef"] \
    list [testobj objtype $x] [testobj objtype $y] [append x "\xAE\xBF\xEF"] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} "string string abc\u00ef\u00bf\u00aeghi\u00ae\u00bf\u00ef abc\u00ef\u00bf\u00aeghi string string"
} "string string abc\xEF\xBF\xAEghi\xAE\xBF\xEF abc\xEF\xBF\xAEghi string string"
test stringObj-8.4 {DupUnicodeInternalRep, all byte-size chars} testobj {
    set x abcdefghi
    string length $x
    set y $x
    list [testobj objtype $x] [testobj objtype $y] [append x jkl] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} {string string abcdefghijkl abcdefghi string string}
test stringObj-8.5 {DupUnicodeInternalRep, all byte-size chars} testobj {
    set x abcdefghi
    set y $x
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x jkl] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} {string string abcdefghijkl abcdefghi string string}

test stringObj-9.1 {TclAppendObjToObj, mixed src & dest} {testobj testdstring} {
    set x abc\u00ef\u00bf\u00aeghi
    set x abc\xEF\xBF\xAEghi
    testdstring free
    testdstring append \u00ae\u00bf\u00ef -1
    testdstring append \xAE\xBF\xEF -1
    set y [testdstring get]
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x $y] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} "string none abc\u00ef\u00bf\u00aeghi\u00ae\u00bf\u00ef \u00ae\u00bf\u00ef string none"
} "string none abc\xEF\xBF\xAEghi\xAE\xBF\xEF \xAE\xBF\xEF string none"
test stringObj-9.2 {TclAppendObjToObj, mixed src & dest} testobj {
    set x abc\u00ef\u00bf\u00aeghi
    set x abc\xEF\xBF\xAEghi
    string length $x
    list [testobj objtype $x] [append x $x] [testobj objtype $x] \
	    [append x $x] [testobj objtype $x]
} "string abc\u00ef\u00bf\u00aeghiabc\u00ef\u00bf\u00aeghi string\
abc\u00ef\u00bf\u00aeghiabc\u00ef\u00bf\u00aeghiabc\u00ef\u00bf\u00aeghiabc\u00ef\u00bf\u00aeghi\
} "string abc\xEF\xBF\xAEghiabc\xEF\xBF\xAEghi string\
abc\xEF\xBF\xAEghiabc\xEF\xBF\xAEghiabc\xEF\xBF\xAEghiabc\xEF\xBF\xAEghi\
string"
test stringObj-9.3 {TclAppendObjToObj, mixed src & 1-byte dest} {testobj testdstring} {
    set x abcdefghi
    testdstring free
    testdstring append \u00ae\u00bf\u00ef -1
    testdstring append \xAE\xBF\xEF -1
    set y [testdstring get]
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x $y] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} "string none abcdefghi\u00ae\u00bf\u00ef \u00ae\u00bf\u00ef string none"
} "string none abcdefghi\xAE\xBF\xEF \xAE\xBF\xEF string none"
test stringObj-9.4 {TclAppendObjToObj, 1-byte src & dest} {testobj testdstring} {
    set x abcdefghi
    testdstring free
    testdstring append jkl -1
    set y [testdstring get]
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x $y] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} {string none abcdefghijkl jkl string none}
test stringObj-9.5 {TclAppendObjToObj, 1-byte src & dest} testobj {
    set x abcdefghi
    string length $x
    list [testobj objtype $x] [append x $x] [testobj objtype $x] \
	    [append x $x] [testobj objtype $x]
} {string abcdefghiabcdefghi string abcdefghiabcdefghiabcdefghiabcdefghi\
string}
test stringObj-9.6 {TclAppendObjToObj, 1-byte src & mixed dest} {testobj testdstring} {
    set x abc\u00ef\u00bf\u00aeghi
    set x abc\xEF\xBF\xAEghi
    testdstring free
    testdstring append jkl -1
    set y [testdstring get]
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x $y] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} "string none abc\u00ef\u00bf\u00aeghijkl jkl string none"
} "string none abc\xEF\xBF\xAEghijkl jkl string none"
test stringObj-9.7 {TclAppendObjToObj, integer src & dest} testobj {
    set x [expr {4 * 5}]
    set y [expr {4 + 5}]
    list [testobj objtype $x] [testobj objtype $y] [append x $y] \
	    [testobj objtype $x] [append x $y] [testobj objtype $x] \
	    [testobj objtype $y]
} {int int 209 string 2099 string int}
test stringObj-9.8 {TclAppendObjToObj, integer src & dest} testobj {
    set x [expr {4 * 5}]
    list [testobj objtype $x] [append x $x] [testobj objtype $x] \
	    [append x $x] [testobj objtype $x]
} {int 2020 string 20202020 string}
test stringObj-9.9 {TclAppendObjToObj, integer src & 1-byte dest} testobj {
    set x abcdefghi
    set y [expr {4 + 5}]
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x $y] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} {string int abcdefghi9 9 string int}
test stringObj-9.10 {TclAppendObjToObj, integer src & mixed dest} testobj {
    set x abc\u00ef\u00bf\u00aeghi
    set x abc\xEF\xBF\xAEghi
    set y [expr {4 + 5}]
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x $y] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} "string int abc\u00ef\u00bf\u00aeghi9 9 string int"
} "string int abc\xEF\xBF\xAEghi9 9 string int"
test stringObj-9.11 {TclAppendObjToObj, mixed src & 1-byte dest index check} testobj {
    # bug 2678, in <=8.2.0, the second obj (the one to append) in
    # Tcl_AppendObjToObj was not correctly checked to see if it was all one
    # byte chars, so a unicode string would be added as one byte chars.
    # byte chars, so a Unicode string would be added as one byte chars.
    set x abcdef
    set len [string length $x]
    set y a\u00fcb\u00e5c\u00ef
    set y a\xFCb\xE5c\xEF
    set len [string length $y]
    append x $y
    string length $x
    set q {}
    for {set i 0} {$i < 12} {incr i} {
	lappend q [string index $x $i]
    }
    set q
} "a b c d e f a \u00fc b \u00e5 c \u00ef"
} "a b c d e f a \xFC b \xE5 c \xEF"

test stringObj-10.1 {Tcl_GetRange with all byte-size chars} {testobj testdstring} {
    testdstring free
    testdstring append abcdef -1
    set x [testdstring get]
    list [testobj objtype $x] [set y [string range $x 1 end-1]] \
	    [testobj objtype $x] [testobj objtype $y]
} [list none bcde string string]
test stringObj-10.2 {Tcl_GetRange with some mixed width chars} {testobj testdstring} {
    # Because this test does not use \uXXXX notation below instead of
    # hardcoding the values, it may fail in multibyte locales. However, we
    # need to test that the parser produces untyped objects even when there
    # are high-ASCII characters in the input (like "ï"). I don't know what
    # else to do but inline those characters here.
    testdstring free
    testdstring append "abc\u00ef\u00efdef" -1
    testdstring append "abcïïdef" -1
    set x [testdstring get]
    list [testobj objtype $x] [set y [string range $x 1 end-1]] \
	    [testobj objtype $x] [testobj objtype $y]
} [list none "bc\u00EF\u00EFde" string string]
} [list none "bcïïde" string string]
test stringObj-10.3 {Tcl_GetRange with some mixed width chars} testobj {
    # set x "abcïïdef"
    set x "abcïïdef"
    # Use \uXXXX notation below instead of hardcoding the values, otherwise
    # the test will fail in multibyte locales.
    set x "abc\u00EF\u00EFdef"
    string length $x
    list [testobj objtype $x] [set y [string range $x 1 end-1]] \
	    [testobj objtype $x] [testobj objtype $y]
} [list string "bc\u00EF\u00EFde" string string]
} [list string "bcïïde" string string]
test stringObj-10.4 {Tcl_GetRange with some mixed width chars} testobj {
    # set a "ïa¿b®cï¿d®"
    set a "ïa¿b®cï¿d®"
    # Use \uXXXX notation below instead of hardcoding the values, otherwise
    # the test will fail in multibyte locales.
    set a "\u00EFa\u00BFb\u00AEc\u00EF\u00BFd\u00AE"
    set result [list]
    while {[string length $a] > 0} {
	set a [string range $a 1 end-1]
	lappend result $a
    }
    set result
} [list a\u00BFb\u00AEc\u00EF\u00BFd	\
	\u00BFb\u00AEc\u00EF\u00BF	\
	b\u00AEc\u00EF			\
	\u00AEc				\
} [list a\xBFb\xAEc\xEF\xBFd	\
	\xBFb\xAEc\xEF\xBF	\
	b\xAEc\xEF			\
	\xAEc				\
	{}]

test stringObj-11.1 {UpdateStringOfString} testobj {
    set x 2345
    list [string index $x end] [testobj objtype $x] [incr x] \
	    [testobj objtype $x]
} {5 string 2346 int}
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
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







-
-
+
+

-
+

-
+

-
-
+
+













-
+



-
+

-
+



-
+

-
+







    list [string index $x 3] [string index $x end]
} {d i}
test stringObj-12.3 {Tcl_GetUniChar with byte-size chars} testobj {
    set x "abcdefghi"
    list [string index $x end] [string index $x end-1]
} {i h}
test stringObj-12.4 {Tcl_GetUniChar with mixed width chars} testobj {
    string index "\u00efa\u00bfb\u00aec\u00ae\u00bfd\u00ef" 0
} "\u00ef"
    string index "\xEFa\xBFb\xAEc\xAE\xBFd\xEF" 0
} "\xEF"
test stringObj-12.5 {Tcl_GetUniChar} testobj {
    set x "\u00efa\u00bfb\u00aec\u00ae\u00bfd\u00ef"
    set x "\xEFa\xBFb\xAEc\xAE\xBFd\xEF"
    list [string index $x 4] [string index $x 0]
} "\u00ae \u00ef"
} "\xAE \xEF"
test stringObj-12.6 {Tcl_GetUniChar} testobj {
    string index "\u00efa\u00bfb\u00aec\u00ef\u00bfd\u00ae" end
} "\u00ae"
    string index "\xEFa\xBFb\xAEc\xEF\xBFd\xAE" end
} "\xAE"

test stringObj-13.1 {Tcl_GetCharLength with byte-size chars} testobj {
    set a ""
    list [string length $a] [string length $a]
} {0 0}
test stringObj-13.2 {Tcl_GetCharLength with byte-size chars} testobj {
    string length "a"
} 1
test stringObj-13.3 {Tcl_GetCharLength with byte-size chars} testobj {
    set a "abcdef"
    list [string length $a] [string length $a]
} {6 6}
test stringObj-13.4 {Tcl_GetCharLength with mixed width chars} testobj {
    string length "\u00ae"
    string length "\xAE"
} 1
test stringObj-13.5 {Tcl_GetCharLength with mixed width chars} testobj {
    # string length "○○"
    # Use \uXXXX notation below instead of hardcoding the values, otherwise
    # Use \uXXXX notation below instead of hard-coding the values, otherwise
    # the test will fail in multibyte locales.
    string length "\u00EF\u00BF\u00AE\u00EF\u00BF\u00AE"
    string length "\xEF\xBF\xAE\xEF\xBF\xAE"
} 6
test stringObj-13.6 {Tcl_GetCharLength with mixed width chars} testobj {
    # set a "ïa¿b®cï¿d®"
    # Use \uXXXX notation below instead of hardcoding the values, otherwise
    # Use \uXXXX notation below instead of hard-coding the values, otherwise
    # the test will fail in multibyte locales.
    set a "\u00EFa\u00BFb\u00AEc\u00EF\u00BFd\u00AE"
    set a "\xEFa\xBFb\xAEc\xEF\xBFd\xAE"
    list [string length $a] [string length $a]
} {10 10}
test stringObj-13.7 {Tcl_GetCharLength with identity nulls} {testobj testbytestring} {
    # SF bug #684699
    string length [testbytestring \x00]
} 1
test stringObj-13.8 {Tcl_GetCharLength with identity nulls} {testobj testbytestring} {
461
462
463
464
465
466
467
468

469
470
471
472

473
474
475
476

477
478
479
480

481
482
483























































484
485
486
487
488
489
490
491
492
493
494
495
452
453
454
455
456
457
458

459
460
461
462

463
464
465
466

467
468
469
470

471
472
473
474
475
476
477
478
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







-
+



-
+



-
+



-
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












    teststringobj set 1 foo
    teststringobj appendself 1 2
} fooo
test stringObj-15.4 {Tcl_Append*ToObj: self appends} testobj {
    teststringobj set 1 foo
    teststringobj appendself 1 3
} foo
test stringObj-15.5 {Tcl_Append*ToObj: self appends} {testobj fullutf} {
test stringObj-15.5 {Tcl_Append*ToObj: self appends} testobj {
    teststringobj set 1 foo
    teststringobj appendself2 1 0
} foofoo
test stringObj-15.6 {Tcl_Append*ToObj: self appends} {testobj fullutf} {
test stringObj-15.6 {Tcl_Append*ToObj: self appends} testobj {
    teststringobj set 1 foo
    teststringobj appendself2 1 1
} foooo
test stringObj-15.7 {Tcl_Append*ToObj: self appends} {testobj fullutf} {
test stringObj-15.7 {Tcl_Append*ToObj: self appends} testobj {
    teststringobj set 1 foo
    teststringobj appendself2 1 2
} fooo
test stringObj-15.8 {Tcl_Append*ToObj: self appends} {testobj fullutf} {
test stringObj-15.8 {Tcl_Append*ToObj: self appends} testobj {
    teststringobj set 1 foo
    teststringobj appendself2 1 3
} foo

test stringObj-16.0 {Tcl_GetRange: normal case} testobj {
    teststringobj set 1 abcde
    teststringobj range 1 1 3
} bcd
test stringObj-16.1 {Tcl_GetRange: first > end} testobj {
    teststringobj set 1 abcde
    teststringobj range 1 10 5
} {}
test stringObj-16.2 {Tcl_GetRange: last > end} testobj {
    teststringobj set 1 abcde
    teststringobj range 1 3 13
} de
test stringObj-16.3 {Tcl_GetRange: first = TCL_INDEX_NONE} testobj {
    teststringobj set 1 abcde
    teststringobj range 1 -1 3
} abcd
test stringObj-16.4 {Tcl_GetRange: last = TCL_INDEX_NONE} testobj {
    teststringobj set 1 abcde
    teststringobj range 1 1 -1
} bcde
test stringObj-16.5 {Tcl_GetRange: first = last = TCL_INDEX_NONE} testobj {
    teststringobj set 1 abcde
    teststringobj range 1 -1 -1
} abcde
test stringObj-16.6 {Tcl_GetRange: old anomaly} testobj {
    # Older implementations could return "cde"
    teststringobj set 1 abcde
    teststringobj range 1 2 0
} {}
test stringObj-16.7 {Tcl_GetRange: first = INT_MAX-1} testobj {
    teststringobj set 1 abcde
    teststringobj range 1 [expr {$INT_MAX-1}] 3
} {}
test stringObj-16.8 {Tcl_GetRange: first = SIZE_MAX-1} testobj {
    teststringobj set 1 abcde
    teststringobj range 1 [expr {$SIZE_MAX - 1}] 3
} {}
test stringObj-16.9 {Tcl_GetRange: last = INT_MAX-1} testobj {
    teststringobj set 1 abcde
    teststringobj range 1 1 [expr {$INT_MAX-1}]
} bcde
test stringObj-16.10 {Tcl_GetRange: last = SIZE_MAX-1} testobj {
    teststringobj set 1 abcde
    teststringobj range 1 1 [expr {$SIZE_MAX - 1}]
} bcde
test stringObj-16.11 {Tcl_GetRange: first = last = INT_MAX-1} testobj {
    teststringobj set 1 abcde
    teststringobj range 1 [expr {$INT_MAX-1}] [expr {$INT_MAX-1}]
} {}
test stringObj-16.12 {Tcl_GetRange: first = last = SIZE_MAX-1} testobj {
    teststringobj set 1 abcde
    set i [expr {$SIZE_MAX - 1}]
    teststringobj range 1 $i $i
} {}

if {[testConstraint testobj]} {
    testobj freeallvars
}

# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/subst.test.

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
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






-
-
-
+
+
+









-
+







# Commands covered:  subst
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1994 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 Ajuba Solutions.
# Copyright © 1994 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-2000 Ajuba Solutions.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testbytestring [llength [info commands testbytestring]]

test subst-1.1 {basics} -returnCodes error -body {
    subst
} -result {wrong # args: should be "subst ?-nobackslashes? ?-nocommands? ?-novariables? string"}
test subst-1.2 {basics} -returnCodes error -body {
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58







-
+







test subst-3.1 {backslash substitutions} {
    subst {\x\$x\[foo bar]\\}
} "x\$x\[foo bar]\\"
test subst-3.2 {backslash substitutions with utf chars} {
    # 'j' is just a char that doesn't mean anything, and \344 is 'ä'
    # that also doesn't mean anything, but is multi-byte in UTF-8.
    list [subst \j] [subst \\j] [subst \\344] [subst \\\344]
} "j j \344 \344"
} "j j ä ä"

test subst-4.1 {variable substitutions} {
    set a 44
    subst {$a}
} {44}
test subst-4.2 {variable substitutions} {
    set a 44
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
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







-
+



-
-
+
+


-
+



-
-
+
+







    subst -no bar
} -result {ambiguous option "-no": must be -nobackslashes, -nocommands, or -novariables}
test subst-7.3 {switches} -returnCodes error -body {
    subst -bogus bar
} -result {bad option "-bogus": must be -nobackslashes, -nocommands, or -novariables}
test subst-7.4 {switches} {
    set x 123
    subst -nobackslashes {abc $x [expr 1+2] \\\x41}
    subst -nobackslashes {abc $x [expr {1 + 2}] \\\x41}
} {abc 123 3 \\\x41}
test subst-7.5 {switches} {
    set x 123
    subst -nocommands {abc $x [expr 1+2] \\\x41}
} {abc 123 [expr 1+2] \A}
    subst -nocommands {abc $x [expr {1 + 2}] \\\x41}
} {abc 123 [expr {1 + 2}] \A}
test subst-7.6 {switches} {
    set x 123
    subst -novariables {abc $x [expr 1+2] \\\x41}
    subst -novariables {abc $x [expr {1 + 2}] \\\x41}
} {abc $x 3 \A}
test subst-7.7 {switches} {
    set x 123
    subst -nov -nob -noc {abc $x [expr 1+2] \\\x41}
} {abc $x [expr 1+2] \\\x41}
    subst -nov -nob -noc {abc $x [expr {1 + 2}] \\\x41}
} {abc $x [expr {1 + 2}] \\\x41}

test subst-8.1 {return in a subst} {
    subst {foo [return {x}; bogus code] bar}
} {foo x bar}
test subst-8.2 {return in a subst} {
    subst {foo [return x ; bogus code] bar}
} {foo x bar}

Changes to tests/switch.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  switch
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
188
189
190
191
192
193
194
195

196
197
198
199
200
201
202
188
189
190
191
192
193
194

195
196
197
198
199
200
201
202







-
+








test switch-5.1 {errors in -regexp matching} -returnCodes error -body {
    switch -regexp aaaab {
	*b	{subst glob}
	aaaab	{subst exact}
	default	{subst none}
    }
} -result {couldn't compile regular expression pattern: quantifier operand invalid}
} -result {cannot compile regular expression pattern: invalid quantifier operand}

test switch-6.1 {backslashes in patterns} {
    switch -exact {\a\$\.\[} {
	\a\$\.\[	{subst first}
	\a\\$\.\\[	{subst second}
	\\a\\$\\.\\[	{subst third}
	{\a\\$\.\\[}	{subst fourth}
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
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







-
-
-
+
+
+








-
+





-
+







	c {}
    }
} -returnCodes error -result {invalid command name "-foo"}

test switch-8.1 {empty body} {
    set msg {}
    switch {2} {
    	1 {set msg 1}
        2 {}
        default {set msg 2}
	1 {set msg 1}
	2 {}
	default {set msg 2}
    }
} {}
proc test_switch_body {} {
    return "INVOKED"
}
test switch-8.2 {weird body text, variable} {
    set cmd {test_switch_body}
    switch Foo {
    	Foo $cmd
	Foo $cmd
    }
} {INVOKED}
test switch-8.3 {weird body text, variable} {
    set cmd {test_switch_body}
    switch Foo {
    	Foo {$cmd}
	Foo {$cmd}
    }
} {INVOKED}

test switch-9.1 {empty pattern/body list} -returnCodes error -body {
    switch x
} -result {wrong # args: should be "switch ?-option ...? string ?pattern body ...? ?default body?"}
test switch-9.2 {unpaired pattern} -returnCodes error -body {
741
742
743
744
745
746
747







748
749
750
751
752
753
754
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761







+
+
+
+
+
+
+







	switch -regexp -- {} {
	    {[012]} {return yes}
	    .+ {return yes2}
	    default {return no}
	}
    }}
} no
test switch-14.17 {switch -regexp bug [c0bc269178]} {
    set result {}
    switch -regexp -matchvar m -indexvar i ac {
	{(a)(b)?(c)} {set result $m}
    }
    set result
} {ac a {} c}

test switch-15.1 {coroutine safety of non-bytecoded switch} {*}{
    -body {
	proc coro {} {
	    switch -glob a {
		a {yield ok1}
	    }

Changes to tests/tailcall.test.

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
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






-
+










-
+







# Commands covered:  tailcall
#
# This file contains a collection of tests for experimental commands that are
# found in ::tcl::unsupported. The tests will migrate to normal test files
# if/when the commands find their way into the core.
#
# Copyright (c) 2008 by Miguel Sofer.
# Copyright © 2008 Miguel Sofer.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testnrelevels [llength [info commands testnrelevels]]

#
# The tests that risked blowing the C stack on failure have been removed: we
# can now actually measure using testnrelevels.
#
703
704
705
706
707
708
709







710
711
712
713
714
715
716
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723







+
+
+
+
+
+
+







	proc p args {
	    tailcall [namespace current] {*}$args
	}
	namespace delete [namespace current]
	p
    }
} -returnCodes 1 -result {namespace "::ns" not found}

test tailcall-bug-784befb0ba {tailcall crash with 254 args} -body {
    proc tccrash args {llength $args}
    # Must be EXACTLY 254 for crash
    proc p {} [list tailcall tccrash {*}[lrepeat 254 x]]
    p
} -result 254

# cleanup
::tcltest::cleanupTests

# Local Variables:
# mode: tcl
# End:

Changes to tests/tcltest.test.

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
30
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
30
31
32
33




-
-
+
+

















+
+
+







# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2000 by Ajuba Solutions
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2000 Ajuba Solutions
# All rights reserved.

# Note that there are several places where the value of
# tcltest::currentFailure is stored/reset in the -setup/-cleanup
# of a test that has a body that runs [test] that will fail.
# This is a workaround of using the same tcltest code that we are
# testing to run the test itself.  Ditto on things like [verbose].
#
# It would be better to have the -body of the tests run the tcltest
# commands in a child interp so the [test] being tested would not
# interfere with the [test] doing the testing.
#

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

# File permissions broken on wsl without some "exotic" wsl configuration
testConstraint notWsl [expr {[llength [array names ::env *WSL*]] == 0}]

namespace eval ::tcltest::test {

namespace import ::tcltest::*

makeFile {
    package require tcltest 2.5
302
303
304
305
306
307
308
309

310
311
312
313
314
315
316
305
306
307
308
309
310
311

312
313
314
315
316
317
318
319







-
+







#	set ::tcltest::constraintsSpecified $constraintlist
#	unset ::tcltest::testConstraints(tcltestFakeConstraint1)
#	unset ::tcltest::testConstraints(tcltestFakeConstraint2)
#    }
#}

test tcltest-5.5 {InitConstraints: list of built-in constraints} \
	-constraints {!singleTestInterp} \
	-constraints {!singleTestInterp notWsl} \
	-setup {tcltest::InitConstraints} \
	-body { lsort [array names ::tcltest::testConstraints] } \
	-result [lsort {
    95 98 asyncPipeClose eformat emptyTest exec hasIsoLocale interactive
    knownBug mac macCrash macOnly macOrPc macOrUnix macOrWin nonBlockFiles
    nonPortable notRoot nt pc pcCrash pcOnly root singleTestInterp socket
    stdio tempNotMac tempNotPc tempNotUnix tempNotWin unix unixCrash unixExecs
346
347
348
349
350
351
352
353

354
355
356
357
358
359
360
349
350
351
352
353
354
355

356
357
358
359
360
361
362
363







-
+







    ::tcltest::PrintError "a really short string"
    ::tcltest::PrintError "a really really really really really really long \
	    string containing \"quotes\" and other bad bad stuff"
    ::tcltest::PrintError "a really really long string containing a \
	    \"Path/that/is/really/long/and/contains/no/spaces\""
    ::tcltest::PrintError "a really really long string containing a \
	    \"Really/Long/Path/that/contains/no/spaces/and/is/longer/than/eighty/characters/to/see/what/happens\""
    ::tcltest::PrintError "Problem renaming file: error renaming \"Z:/ws/tcl8.2/win32-ix86/tests/core\" to \"Z:/ws/tcl8.2/win32-ix86/tests/movecore-core\""
    ::tcltest::PrintError "Problem renaming file: error renaming \"Z:/ws/tcl9.0/win32-ix86/tests/core\" to \"Z:/ws/tcl9.0/win32-ix86/tests/movecore-core\""
    exit
} printerror.tcl]

test tcltest-6.1 {tcltest -outfile, -errfile defaults} {
    -constraints unixOrWin
    -body {
	child msg $printerror
535
536
537
538
539
540
541
542

543
544

545
546

547
548
549
550
551


552
553
554
555
556


557
558
559
560

561
562
563
564
565
566
567
568
569
570
571

572
573
574
575
576


577
578

579
580
581

582
583
584
585
586
587
588
538
539
540
541
542
543
544

545
546

547
548

549
550
551
552


553
554
555
556
557


558
559
560
561
562

563
564
565
566
567
568
569
570
571
572
573

574
575
576
577


578
579
580

581
582
583

584
585
586
587
588
589
590
591







-
+

-
+

-
+



-
-
+
+



-
-
+
+



-
+










-
+



-
-
+
+

-
+


-
+







    -body {
	child msg $a -tmpdir $tdiaf
	return $msg
    }
    -result {*not a directory*}
    -match glob
}
# Test non-writeable directories, non-readable directories with directory flags
# Test non-writable directories, non-readable directories with directory flags
set notReadableDir [file join [temporaryDirectory] notreadable]
set notWriteableDir [file join [temporaryDirectory] notwriteable]
set notWritableDir [file join [temporaryDirectory] notwritable]
makeDirectory notreadable
makeDirectory notwriteable
makeDirectory notwritable

switch -- $::tcl_platform(platform) {
    unix {
	file attributes $notReadableDir -permissions 00333
	file attributes $notWriteableDir -permissions 00555
	file attributes $notReadableDir -permissions 0o333
	file attributes $notWritableDir -permissions 0o555
    }
    default {
	# note in FAT/NTFS we won't be able to protect directory with read-only attribute...
	catch {file attributes $notWriteableDir -readonly 1}
	catch {testchmod 0 $notWriteableDir}
	catch {file attributes $notWritableDir -readonly 1}
	catch {testchmod 0o444 $notWritableDir}
    }
}
test tcltest-8.3 {tcltest a.tcl -tmpdir notReadableDir} {
    -constraints {unix notRoot}
    -constraints {unix notRoot notWsl}
    -body {
	child msg $a -tmpdir $notReadableDir
	return $msg
    }
    -result {*not readable*}
    -match glob
}
# This constraint doesn't go at the top of the file so that it doesn't
# interfere with tcltest-5.5
testConstraint notFAT [expr {
       ![regexp {^(FAT\d*|NTFS)$} [lindex [file system $notWriteableDir] 1]]
       ![regexp {^(FAT\d*|NTFS)$} [lindex [file system $notWritableDir] 1]]
    || $::tcl_platform(platform) eq "unix" || [llength [info commands testchmod]]
}]
# FAT/NTFS permissions are fairly hopeless; ignore this test if that FS is used
test tcltest-8.4 {tcltest a.tcl -tmpdir notWriteableDir} {
    -constraints {unixOrWin notRoot notFAT}
test tcltest-8.4 {tcltest a.tcl -tmpdir notWritableDir} {
    -constraints {unixOrWin notRoot notFAT notWsl}
    -body {
	child msg $a -tmpdir $notWriteableDir
	child msg $a -tmpdir $notWritableDir
	return $msg
    }
    -result {*not writeable*}
    -result {*not writable*}
    -match glob
}
test tcltest-8.5 {tcltest a.tcl -tmpdir normaldirectory} {
    -constraints unixOrWin
    -body {
	child msg $a -tmpdir $normaldirectory
	# The join is necessary because the message can be split on multiple
642
643
644
645
646
647
648
649

650
651
652
653
654
655
656
645
646
647
648
649
650
651

652
653
654
655
656
657
658
659







-
+







	child msg $a -testdir $tdiaf
	return $msg
    }
    -match glob
    -result {*not a directory*}
}
test tcltest-8.12 {tcltest a.tcl -testdir notReadableDir} {
    -constraints {unix notRoot}
    -constraints {unix notRoot notWsl}
    -body {
	child msg $a -testdir $notReadableDir
	return $msg
    }
    -match glob
    -result {*not readable*}
}
699
700
701
702
703
704
705
706
707
708
709




710
711
712
713
714
715
716
717
718
719
720
721


722
723
724
725


726
727
728
729

730
731
732
733
734
735
736
702
703
704
705
706
707
708




709
710
711
712
713
714
715
716
717
718
719
720
721
722


723
724
725
726


727
728
729
730
731

732
733
734
735
736
737
738
739







-
-
-
-
+
+
+
+










-
-
+
+


-
-
+
+



-
+







	set f2 [pwd]
	set f3 [workingDirectory $current]
	set f4 [pwd]
	set f5 [workingDirectory]
	list $f1 $f2 $f3 $f4 $f5
    }
    -result "[list $normaldirectory \
                   $normaldirectory \
                   $current \
                   $current \
                   $current]"
		   $normaldirectory \
		   $current \
		   $current \
		   $current]"
    -cleanup {
	set ::tcltest::workingDirectory $old
	cd $current
    }
}

# clean up from directory testing

switch -- $::tcl_platform(platform) {
    unix {
	file attributes $notReadableDir -permissions 777
	file attributes $notWriteableDir -permissions 777
	file attributes $notReadableDir -permissions 0o777
	file attributes $notWritableDir -permissions 0o777
    }
    default {
	catch {testchmod 0o777 $notWriteableDir}
	catch {file attributes $notWriteableDir -readonly 0}
	catch {testchmod 0o777 $notWritableDir}
	catch {file attributes $notWritableDir -readonly 0}
    }
}

file delete -force -- $notReadableDir $notWriteableDir
file delete -force -- $notReadableDir $notWritableDir
removeFile a.tcl
removeFile thisdirectoryisafile
removeDirectory normaldirectory

# -file, -notfile, [matchFiles], [skipFiles]
test tcltest-9.1 {-file d*.tcl} -constraints {unixOrWin} -setup {
    set old [testsDirectory]
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320



1321
1322
1323
1324
1325
1326
1327
1314
1315
1316
1317
1318
1319
1320



1321
1322
1323
1324
1325
1326
1327
1328
1329
1330







-
-
-
+
+
+







	-body {list a b c d e} \
	-result {[ab] b c d e} \
	-match glob

test tcltest-21.8 {force a test command failure} \
    -setup {set fail $::tcltest::currentFailure} \
    -body {
        test tcltest-21.8.0 {
            return 2
        } {1}
	test tcltest-21.8.0 {
	    return 2
	} {1}
    } \
    -returnCodes 1 \
    -cleanup {set ::tcltest::currentFailure $fail} \
    -result {bad option "1": must be -body, -cleanup, -constraints, -errorCode, -errorOutput, -match, -output, -result, -returnCodes, or -setup}

test tcltest-21.9 {test command with setup} \
	-setup {set foo 1} \
1441
1442
1443
1444
1445
1446
1447
1448

1449
1450
1451
1452
1453
1454
1455
1444
1445
1446
1447
1448
1449
1450

1451
1452
1453
1454
1455
1456
1457
1458







-
+







}
test tcltest-23.2 {removeFile} {
    -setup {
	set mfdir [file join [temporaryDirectory] mfdir]
	file mkdir $mfdir
	makeFile {} t1.tmp
	makeFile {} et1.tmp $mfdir
	if  {![file exists [file join [temporaryDirectory] t1.tmp]] || \
	if {![file exists [file join [temporaryDirectory] t1.tmp]] || \
		![file exists [file join $mfdir et1.tmp]]} {
	    error "file creation didn't work"
	}
    }
    -body {
	removeFile t1.tmp
	removeFile et1.tmp $mfdir
1510
1511
1512
1513
1514
1515
1516
1517
1518


1519
1520
1521
1522
1523
1524
1525
1513
1514
1515
1516
1517
1518
1519


1520
1521
1522
1523
1524
1525
1526
1527
1528







-
-
+
+







}

# customMatch
proc matchNegative { expected actual } {
   set match 0
   foreach a $actual e $expected {
      if { $a != $e } {
         set match 1
        break
	 set match 1
	break
      }
   }
   return $match
}

test tcltest-24.0 {
	customMatch: syntax

Changes to tests/tcltests.tcl.

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
30
31
32
33
34
35
36
37
38
39
40
41



















































42
43
44
45
46
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
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


+
+
+


-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+
-















+
+
+
+
+
+
+
+
+
+
+
+

















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





#! /usr/bin/env tclsh

# Don't overwrite tcltests facilities already present
if {[package provide tcltests] ne {}} return

package require tcltest 2.5
namespace import ::tcltest::*
testConstraint exec          [llength [info commands exec]]
testConstraint exec [llength [info commands exec]]
testConstraint deprecated [expr {![tcl::build-info no-deprecate]}]
testConstraint debug [tcl::build-info debug]
testConstraint purify [tcl::build-info purify]
testConstraint debugpurify [
    expr {
	![tcl::build-info memdebug]
	&& [testConstraint debug]
	&& [testConstraint purify]
    }]
testConstraint bigmem [expr {[
	info exists ::env(TCL_TESTCONSTRAINT_BIGMEM)]
		? !!$::env(TCL_TESTCONSTRAINT_BIGMEM)
		: 1
}]
testConstraint fcopy         [llength [info commands fcopy]]
testConstraint fileevent     [llength [info commands fileevent]]
testConstraint thread        [
testConstraint thread        [expr {![catch {package require Thread 2.7-}]}]
    expr {0 == [catch {package require Thread 2.7-}]}]
testConstraint notValgrind   [expr {![testConstraint valgrind]}]


namespace eval ::tcltests {


    proc init {} {
	if {[namespace which ::tcl::file::tempdir] eq {}} {
	    interp alias {} [namespace current]::tempdir {} [
		namespace current]::tempdir_alternate
	} else {
	    interp alias {} [namespace current]::tempdir {} ::tcl::file::tempdir
	}
    }


    # Stolen from dict.test
    proc scriptmemcheck script {
	set end [lindex [split [memory info] \n] 3 3]
	for {set i 0} {$i < 5} {incr i} {
	    uplevel 1 $script
	    set tmp $end
	    set end [lindex [split [memory info] \n] 3 3]
	}
	expr {$end - $tmp}
    }


    proc tempdir_alternate {} {
	close [file tempfile tempfile]
	set tmpdir [file dirname $tempfile]
	set execname [info nameofexecutable]
	regsub -all {[^[:alpha:][:digit:]]} $execname _ execname
	for {set i 0} {$i < 10000} {incr i} {
	    set time [clock milliseconds]
	    set name $tmpdir/${execname}_${time}_$i
	    if {![file exists $name]} {
		file mkdir $name
		return $name
	    }
	}
	error [list {could not create temporary directory}]
    }

    # Generates test cases for 0, min and max number of arguments for a command.
    # Expected result is as generated by Tcl_WrongNumArgs
    # Only works if optional arguments come after fixed arguments
    # E.g.
    #  testnumargs "zipfs mount" "" "?mountpoint? ?zipfile? ?password?"
    #  testnumargs "lappend" "varName" "?value ...?"
    proc testnumargs {cmd {fixed {}} {optional {}} args} {
	variable count
	set minargs [llength $fixed]
	set maxargs [expr {$minargs + [llength $optional]}]
	if {[regexp {\.\.\.\??$} [lindex $optional end]]} {
	    unset maxargs; # No upper limit on num of args
	}
	set message "wrong # args: should be \"$cmd"
	if {[llength $fixed]} {
	    append message " $fixed"
	}
	if {[llength $optional]} {
	    append message " $optional"
	}
	if {[llength $fixed] == 0 && [llength $optional] == 0} {
	    append message " \""
	} else {
	    append message "\""
	}
	set label [join $cmd -]
	if {$minargs > 0} {
	    set arguments [lrepeat [expr {$minargs-1}] x]
	    test $label-minargs-[incr count($label-minargs)] \
		"$label no arguments" \
		-body "$cmd" \
		-result $message -returnCodes error \
		{*}$args
	    if {$minargs > 1} {
		test $label-minargs-[incr count($label-minargs)] \
		    "$label missing arguments" \
		    -body "$cmd $arguments" \
		    -result $message -returnCodes error \
		    {*}$args
	    }
	}
	if {[info exists maxargs]} {
	    set arguments [lrepeat [expr {$maxargs+1}] x]
	    test $label-maxargs-[incr count($label-maxargs)] \
		"$label extra arguments" \
		-body "$cmd $arguments" \
		-result $message -returnCodes error \
		{*}$args
	}
    }

    init

    package provide tcltests 0.1
}

Changes to tests/thread.test.

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
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
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
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






-
-
-
+
+
+












+
+
+

-
+
-


















-
+



-
+






-
-
-
-
+
+
+
+







-
-
-
+
+
+







# Commands covered:  (test)thread
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2006-2008 by Joe Mistachkin.  All rights reserved.
# Copyright © 1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2006-2008 Joe Mistachkin.  All rights reserved.
#
# 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::*
}

#  when thread::release is used, -wait is passed in order allow the thread to
#  be fully finalized, which avoids valgrind "still reachable" reports.

package require tcltest 2.5
source [file join [file dirname [info script]] tcltests.tcl]

::tcltest::loadTestedCommands
catch [list package require -exact Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]
package require tcltests

# Some tests require the testthread command

testConstraint testthread [expr {[info commands testthread] ne {}}]


set threadSuperKillScript {
    rename catch ""
    rename while ""
    rename unknown ""
    rename update ""
    thread::release
}

proc getThreadErrorFromInfo { info } {
    set list [split $info \n]
    set idx [lsearch -glob $list "*eval*unwound*"]
    if {$idx >= 0} then {
        return [lindex $list $idx]
	return [lindex $list $idx]
    }
    set idx [lsearch -glob $list "*eval*canceled*"]
    if {$idx >= 0} then {
        return [lindex $list $idx]
	return [lindex $list $idx]
    }
    return ""; # some other error we do not care about.
}

proc findThreadError { info } {
    foreach error [lreverse $info] {
        set error [getThreadErrorFromInfo $error]
        if {[string length $error] > 0} then {
            return $error
        }
	set error [getThreadErrorFromInfo $error]
	if {[string length $error] > 0} then {
	    return $error
	}
    }
    return ""; # some other error we do not care about.
}

proc ThreadError {id info} {
    global threadSawError
    if {[string length [getThreadErrorFromInfo $info]] > 0} then {
        global threadId threadError
        set threadId $id
        lappend threadError($id) $info
	global threadId threadError
	set threadId $id
	lappend threadError($id) $info
    }
    set threadSawError($id) true; # signal main thread to exit [vwait].
}

proc threadSuperKill id {
    variable threadSuperKillScript
    try {
106
107
108
109
110
111
112
113
114
115
116
117
118
119







120
121
122
123
124
125
126
108
109
110
111
112
113
114







115
116
117
118
119
120
121
122
123
124
125
126
127
128







-
-
-
-
-
-
-
+
+
+
+
+
+
+







    set numthreads [llength [thread::names]]
    thread::release -wait $serverthread
    set numthreads
} 2
test thread-1.5 {Tcl_ThreadObjCmd: thread create one shot} {thread} {
    thread::create {set x 5}
    foreach try {0 1 2 4 5 6} {
        # Try various ways to yield
        update
        after 10
        set l [llength [thread::names]]
        if {$l == 1} {
            break
        }
	# Try various ways to yield
	update
	after 10
	set l [llength [thread::names]]
	if {$l == 1} {
	    break
	}
    }
    set l
} 1
test thread-1.6 {Tcl_ThreadObjCmd: thread exit} {thread} {
    thread::create {{*}{}}
    update
    after 10
275
276
277
278
279
280
281
282
283
284
285




286
287
288
289
290
291
292
277
278
279
280
281
282
283




284
285
286
287
288
289
290
291
292
293
294







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel $serverthread]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval canceled}}
test thread-7.5 {cancel: pure inside-command loop} -constraints {thread drainEventQueue} -setup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -body {
    set serverthread [thread::create -joinable \
307
308
309
310
311
312
313
314
315
316
317




318
319
320
321
322
323
324
309
310
311
312
313
314
315




316
317
318
319
320
321
322
323
324
325
326







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel $serverthread]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval canceled}}
test thread-7.6 {cancel: pure bytecode loop -unwind} -constraints {thread drainEventQueue} -setup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -body {
    set serverthread [thread::create -joinable \
338
339
340
341
342
343
344
345
346
347
348




349
350
351
352
353
354
355
340
341
342
343
344
345
346




347
348
349
350
351
352
353
354
355
356
357







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel -unwind $serverthread]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval unwound}}
test thread-7.7 {cancel: pure inside-command loop -unwind} -constraints {thread drainEventQueue} -setup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -body {
    set serverthread [thread::create -joinable \
370
371
372
373
374
375
376
377
378
379
380




381
382
383
384
385
386
387
372
373
374
375
376
377
378




379
380
381
382
383
384
385
386
387
388
389







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel -unwind $serverthread]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval unwound}}
test thread-7.8 {cancel: pure bytecode loop custom result} -constraints {thread drainEventQueue} -setup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -body {
    set serverthread [thread::create -joinable \
401
402
403
404
405
406
407
408
409
410
411




412
413
414
415
416
417
418
403
404
405
406
407
408
409




410
411
412
413
414
415
416
417
418
419
420







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel $serverthread "the eval was canceled"]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {the eval was canceled}}
test thread-7.9 {cancel: pure inside-command loop custom result} -constraints {
    thread
    drainEventQueue
} -setup {
436
437
438
439
440
441
442
443
444
445
446




447
448
449
450
451
452
453
438
439
440
441
442
443
444




445
446
447
448
449
450
451
452
453
454
455







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel $serverthread "the eval was canceled"]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {the eval was canceled}}
test thread-7.10 {cancel: pure bytecode loop custom result -unwind} -constraints {
    thread
    drainEventQueue
} -setup {
470
471
472
473
474
475
476
477
478
479
480




481
482
483
484
485
486
487
472
473
474
475
476
477
478




479
480
481
482
483
484
485
486
487
488
489







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel -unwind $serverthread "the eval was unwound"]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {the eval was unwound}}
test thread-7.11 {cancel: pure inside-command loop custom result -unwind} -constraints {
    thread
    drainEventQueue
} -setup {
505
506
507
508
509
510
511
512
513
514
515




516
517
518
519
520
521
522
507
508
509
510
511
512
513




514
515
516
517
518
519
520
521
522
523
524







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel -unwind $serverthread "the eval was unwound"]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {the eval was unwound}}
test thread-7.12 {cancel: after} -constraints {thread drainEventQueue} -setup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -body {
    set serverthread [thread::create -joinable \
531
532
533
534
535
536
537
538
539
540
541




542
543
544
545
546
547
548
533
534
535
536
537
538
539




540
541
542
543
544
545
546
547
548
549
550







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel $serverthread]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval canceled}}
test thread-7.13 {cancel: after -unwind} -constraints {thread drainEventQueue} -setup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -body {
    set serverthread [thread::create -joinable \
557
558
559
560
561
562
563
564
565
566
567




568
569
570
571
572
573
574
559
560
561
562
563
564
565




566
567
568
569
570
571
572
573
574
575
576







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel -unwind $serverthread]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval unwound}}
test thread-7.14 {cancel: vwait} -constraints {thread drainEventQueue} -setup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -body {
    set serverthread [thread::create -joinable \
583
584
585
586
587
588
589
590
591
592
593




594
595
596
597
598
599
600
585
586
587
588
589
590
591




592
593
594
595
596
597
598
599
600
601
602







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel $serverthread]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval canceled}}
test thread-7.15 {cancel: vwait -unwind} -constraints {thread drainEventQueue} -setup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -body {
    set serverthread [thread::create -joinable \
609
610
611
612
613
614
615
616
617
618
619




620
621
622
623
624
625
626
611
612
613
614
615
616
617




618
619
620
621
622
623
624
625
626
627
628







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel -unwind $serverthread]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval unwound}}
test thread-7.16 {cancel: expr} -constraints {thread drainEventQueue} -setup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -body {
    set serverthread [thread::create -joinable \
640
641
642
643
644
645
646
647
648
649
650




651
652
653
654
655
656
657
642
643
644
645
646
647
648




649
650
651
652
653
654
655
656
657
658
659







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel $serverthread]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval canceled}}
test thread-7.17 {cancel: expr -unwind} -constraints {thread drainEventQueue} -setup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -body {
    set serverthread [thread::create -joinable \
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
707
708
709
710
711
712
713
714





715
716
717
718
719
720

721
722
723
724
725
726
727
728
729
730
731
732
733
734













735
736
737
738
739
740
741
742
743
744
745
746





747
748
749
750
751
752
753
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
707
708
709
710
711





712
713
714
715
716
717
718
719
720
721

722
723













724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743





744
745
746
747
748
749
750
751
752
753
754
755







-
-
-
-
+
+
+
+







-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+







-
-
-
-
-
+
+
+
+
+





-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+







-
-
-
-
-
+
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel -unwind $serverthread]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval unwound}}
test thread-7.18 {cancel: expr bignum} {thread drainEventQueue knownBug} {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
    set serverthread [thread::create -joinable \
	    [string map [list %ID% [thread::id]] {
        set i [interp create]
	set i [interp create]
	$i eval "package require -exact Thread [package present Thread]"
        $i eval {
            if {![info exists foo]} then {
                # signal the primary thread that we are ready
                # to be canceled now (we are running).
                thread::send %ID% [list set ::threadIdStarted [thread::id]]
                set foo 1
            }
            #
            # BUGBUG: This will not cancel because libtommath
            #         does not check Tcl_Canceled.
            #
            expr {2**99999}
        }
	$i eval {
	    if {![info exists foo]} then {
		# signal the primary thread that we are ready
		# to be canceled now (we are running).
		thread::send %ID% [list set ::threadIdStarted [thread::id]]
		set foo 1
	    }
	    #
	    # BUGBUG: This will not cancel because libtommath
	    #         does not check Tcl_Canceled.
	    #
	    expr {2**99999}
	}
    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted; after 1000
    set res [thread::cancel $serverthread]
    vwait ::threadSawError($serverthread); # WARNING: Never returns (see above).
    thread::join $serverthread; drainEventQueue; # WARNING: Never returns (see above).
    list $res [expr {[info exists ::threadIdStarted] ? \
                  $::threadIdStarted == $serverthread : 0}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
		  $::threadIdStarted == $serverthread : 0}] \
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} {{} 1 0 {}}
test thread-7.19 {cancel: expr bignum -unwind} {thread drainEventQueue knownBug} {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
    set serverthread [thread::create -joinable \
	    [string map [list %ID% [thread::id]] {
        set i [interp create]
	set i [interp create]
	$i eval "package require -exact Thread [package present Thread]"
        $i eval {
            if {![info exists foo]} then {
                # signal the primary thread that we are ready
                # to be canceled now (we are running).
                thread::send %ID% [list set ::threadIdStarted [thread::id]]
                set foo 1
            }
            #
            # BUGBUG: This will not cancel because libtommath
            #         does not check Tcl_Canceled.
            #
            expr {2**99999}
        }
	$i eval {
	    if {![info exists foo]} then {
		# signal the primary thread that we are ready
		# to be canceled now (we are running).
		thread::send %ID% [list set ::threadIdStarted [thread::id]]
		set foo 1
	    }
	    #
	    # BUGBUG: This will not cancel because libtommath
	    #         does not check Tcl_Canceled.
	    #
	    expr {2**99999}
	}
    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted; after 1000
    set res [thread::cancel -unwind $serverthread]
    vwait ::threadSawError($serverthread); # WARNING: Never returns (see above).
    thread::join $serverthread; drainEventQueue; # WARNING: Never returns (see above).
    list $res [expr {[info exists ::threadIdStarted] ? \
                  $::threadIdStarted == $serverthread : 0}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
		  $::threadIdStarted == $serverthread : 0}] \
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} {{} 1 0 {}}
test thread-7.20 {cancel: subst} -constraints {thread drainEventQueue} -setup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -body {
    set serverthread [thread::create -joinable \
	    [string map [list %ID% [thread::id]] {
	set i [interp create]
764
765
766
767
768
769
770
771
772
773
774




775
776
777
778
779
780
781
766
767
768
769
770
771
772




773
774
775
776
777
778
779
780
781
782
783







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel $serverthread]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval canceled}}
test thread-7.21 {cancel: subst -unwind} -constraints {thread drainEventQueue} -setup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -body {
    set serverthread [thread::create -joinable \
794
795
796
797
798
799
800
801
802
803
804




805
806
807
808
809
810
811
796
797
798
799
800
801
802




803
804
805
806
807
808
809
810
811
812
813







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel -unwind $serverthread]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval unwound}}
test thread-7.22 {cancel: child interp} -constraints {thread drainEventQueue} -setup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -body {
    set serverthread [thread::create -joinable \
824
825
826
827
828
829
830
831
832
833
834




835
836
837
838
839
840
841
826
827
828
829
830
831
832




833
834
835
836
837
838
839
840
841
842
843







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel $serverthread]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval canceled}}
test thread-7.23 {cancel: child interp -unwind} -constraints {thread drainEventQueue} -setup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -body {
    set serverthread [thread::create -joinable \
854
855
856
857
858
859
860
861
862
863
864




865
866
867
868
869
870
871
856
857
858
859
860
861
862




863
864
865
866
867
868
869
870
871
872
873







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel -unwind $serverthread]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval unwound}}
test thread-7.24 {cancel: nested catch inside pure bytecode loop} {thread drainEventQueue} {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
    set serverthread [thread::create -joinable \
	    [string map [list %ID% [thread::id]] {
996
997
998
999
1000
1001
1002
1003
1004
1005
1006




1007
1008
1009
1010
1011
1012
1013
998
999
1000
1001
1002
1003
1004




1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::send -async $serverthread {interp cancel -- -unwind}]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval canceled}}
test thread-7.28 {cancel: send async cancel nested catch inside pure bytecode loop} {thread drainEventQueue} {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
    set serverthread [thread::create -joinable \
	    [string map [list %ID% [thread::id]] {
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209




1210
1211
1212
1213
1214
1215
1216
1201
1202
1203
1204
1205
1206
1207




1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel -unwind $serverthread]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval unwound}}
test thread-7.33 {cancel: nested catch inside pure inside-command loop -unwind} -constraints {thread drainEventQueue} -setup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -body {
    set serverthread [thread::create -joinable \
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250




1251
1252
1253
1254
1255
1256
1257
1242
1243
1244
1245
1246
1247
1248




1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::cancel -unwind $serverthread]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval unwound}}
test thread-7.34 {cancel: send async cancel nested catch inside pure bytecode loop -unwind} -constraints {thread drainEventQueue} -setup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -body {
    set serverthread [thread::create -joinable \
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291




1292
1293
1294
1295
1296
1297
1298
1283
1284
1285
1286
1287
1288
1289




1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::send -async $serverthread {interp cancel -unwind}]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval unwound}}
test thread-7.35 {cancel: send async cancel nested catch inside pure inside-command loop -unwind} -constraints {thread drainEventQueue} -setup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -body {
    set serverthread [thread::create -joinable \
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334




1335
1336
1337
1338
1339
1340
1341
1326
1327
1328
1329
1330
1331
1332




1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::send -async $serverthread {interp cancel -unwind}]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval unwound}}
test thread-7.36 {cancel: send async thread cancel nested catch inside pure bytecode loop -unwind} -constraints {thread drainEventQueue} -setup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -body {
    set serverthread [thread::create -joinable \
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375




1376
1377
1378
1379
1380
1381
1382
1367
1368
1369
1370
1371
1372
1373




1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::send -async $serverthread {thread::cancel -unwind [thread::id]}]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval unwound}}
test thread-7.37 {cancel: send async thread cancel nested catch inside pure inside-command loop -unwind} -constraints {thread drainEventQueue} -setup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -body {
    set serverthread [thread::create -joinable \
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418




1419
1420
1421
1422
1423
1424
1425
1410
1411
1412
1413
1414
1415
1416




1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427







-
-
-
-
+
+
+
+







    }]]
    # wait for other thread to signal "ready to cancel"
    vwait ::threadIdStarted
    set res [thread::send -async $serverthread {thread::cancel -unwind [thread::id]}]
    vwait ::threadSawError($serverthread)
    thread::join $serverthread; drainEventQueue
    list $res [expr {$::threadIdStarted == $serverthread}] \
              [expr {[info exists ::threadId] ? \
                  $::threadId == $serverthread : 0}] \
              [expr {[info exists ::threadError($serverthread)] ? \
                  [findThreadError $::threadError($serverthread)] : ""}]
	      [expr {[info exists ::threadId] ? \
		  $::threadId == $serverthread : 0}] \
	      [expr {[info exists ::threadError($serverthread)] ? \
		  [findThreadError $::threadError($serverthread)] : ""}]
} -cleanup {
    unset -nocomplain ::threadSawError ::threadError ::threadId ::threadIdStarted
} -result {{} 1 1 {eval unwound}}

test thread-8.1 {threaded fork stress} -constraints {thread} -setup {
    unset -nocomplain ::threadCount ::execCount ::threads ::thread
    set ::threadCount 10

Changes to tests/timer.test.

1
2
3
4
5
6
7
8
9
10
11


12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
17
18









-
-
+
+







# This file contains a collection of tests for the procedures in the
# file tclTimer.c, which includes the "after" Tcl command.  Sourcing
# this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 by Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
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

442
443
444
445
446
447
448
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
442
443
444
445
446
447
448







-
+










-
+










-
-
+
+












-
-
+
+












-
+









-
+










-
+








test timer-6.23 {Tcl_AfterCmd procedure, no option, script with NUL} -setup {
    foreach i [after info] {
	after cancel $i
    }
} -body {
    set x "hello world"
    after 1 "set x ab\0cd"
    after 1 "set x ab\x00cd"
    after 10
    update
    string length $x
} -result {5}
test timer-6.24 {Tcl_AfterCmd procedure, no option, script with NUL} -setup {
    foreach i [after info] {
	after cancel $i
    }
} -body {
    set x "hello world"
    after 1 set x ab\0cd
    after 1 set x ab\x00cd
    after 10
    update
    string length $x
} -result {5}
test timer-6.25 {Tcl_AfterCmd procedure, cancel option, script with NUL} -setup {
    foreach i [after info] {
	after cancel $i
    }
} -body {
    set x "hello world"
    after 1 set x ab\0cd
    after cancel "set x ab\0ef"
    after 1 set x ab\x00cd
    after cancel "set x ab\x00ef"
    llength [after info]
} -cleanup {
    foreach i [after info] {
	after cancel $i
    }
} -result {1}
test timer-6.26 {Tcl_AfterCmd procedure, cancel option, script with NUL} -setup {
    foreach i [after info] {
	after cancel $i
    }
} -body {
    set x "hello world"
    after 1 set x ab\0cd
    after cancel set x ab\0ef
    after 1 set x ab\x00cd
    after cancel set x ab\x00ef
    llength [after info]
} -cleanup {
    foreach i [after info] {
	after cancel $i
    }
} -result {1}
test timer-6.27 {Tcl_AfterCmd procedure, idle option, script with NUL} -setup {
    foreach i [after info] {
	after cancel $i
    }
} -body {
    set x "hello world"
    after idle "set x ab\0cd"
    after idle "set x ab\x00cd"
    update
    string length $x
} -result {5}
test timer-6.28 {Tcl_AfterCmd procedure, idle option, script with NUL} -setup {
    foreach i [after info] {
	after cancel $i
    }
} -body {
    set x "hello world"
    after idle set x ab\0cd
    after idle set x ab\x00cd
    update
    string length $x
} -result {5}
test timer-6.29 {Tcl_AfterCmd procedure, info option, script with NUL} -setup {
    foreach i [after info] {
	after cancel $i
    }
} -body {
    set x "hello world"
    set id junk
    set id [after 10 set x ab\0cd]
    set id [after 10 set x ab\x00cd]
    update
    string length [lindex [lindex [after info $id] 0] 2]
} -cleanup {
    foreach i [after info] {
	after cancel $i
    }
} -result 5

Changes to tests/tm.test.

1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







# This file contains tests for the ::tcl::tm::* commands.
#
# Sourcing this file into Tcl runs the tests and generates output for
# errors.  No output means no errors were found.
#
# Copyright (c) 2004 by Donal K. Fellows.
# Copyright © 2004 Donal K. Fellows.
# All rights reserved.

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

195
196
197
198
199
200
201
202

203
204
205
206
207
208
209
195
196
197
198
199
200
201

202
203
204
205
206
207
208
209







-
+







    ::tcl::tm::path list
} -result {geode snarf foo}


proc genpaths {base} {
    # Normalizing picks up drive letters on windows [Bug 1053568]
    set base [file normalize $base]
    regexp {^(\d+)\.(\d+)} [package provide Tcl] - major minor
    regexp {^(\d+)\.(\d+)} [package provide tcl] - major minor
    set results {}
    set base [file join $base tcl$major]
    lappend results [file join $base site-tcl]
    for {set i 0} {$i <= $minor} {incr i} {
	lappend results [file join $base ${major}.$i]
    }
    return $results

Changes to tests/trace.test.

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
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






-
-
-
+
+
+










-
+







# Commands covered:  trace
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testcmdtrace [llength [info commands testcmdtrace]]
testConstraint testevalobjv [llength [info commands testevalobjv]]

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

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
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







-
+





-
+





-
+






-
+







test trace-0.0 {memory corruption in trace (Tcl Bug 484339)} {
    # You may need Purify or Electric Fence to reliably
    # see this one fail.
    unset -nocomplain z
    trace add variable z array {set z(foo) 1 ;#}
    set res "names: [array names z]"
    unset -nocomplain ::z
    trace variable ::z w {unset ::z; error "memory corruption";#}
    trace add variable ::z write {unset ::z; error "memory corruption";#}
    list [catch {set ::z 1} msg] $msg
} {1 {can't set "::z": memory corruption}}

# Read-tracing on variables

test trace-1.1 {trace variable reads} {
test trace-1.1 {trace add variable reads} {
    unset -nocomplain x
    set info {}
    trace add variable x read traceScalar
    list [catch {set x} msg] $msg $info
} {1 {can't read "x": no such variable} {x {} read 1 {can't read "x": no such variable}}}
test trace-1.2 {trace variable reads} {
test trace-1.2 {trace add variable reads} {
    unset -nocomplain x
    set x 123
    set info {}
    trace add variable x read traceScalar
    list [catch {set x} msg] $msg $info
} {0 123 {x {} read 0 123}}
test trace-1.3 {trace variable reads} {
test trace-1.3 {trace add variable reads} {
    unset -nocomplain x
    set info {}
    trace add variable x read traceScalar
    set x 123
    set info
} {}
test trace-1.4 {trace array element reads} {
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
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







-
-
-
+
+
+








-
-
-
-
+
+
+
+


-
-
-
+
+
+
















-
+










-
-
+
+





-
-
+
+





-
-
+
+





-
-
+
+





-
+




















-
+







-
+







-
+














-
+


















-
+








-
+










-
+







    list [catch {set x(2)} msg] $msg $info
} {0 zzz {x 2 read 0 zzz}}
test trace-1.6 {trace array element reads} {
    unset -nocomplain x
    set info {}
    trace add variable x read traceArray2
    proc p {} {
        global x
        set x(2) willi
        return $x(2)
	global x
	set x(2) willi
	return $x(2)
    }
    list [catch {p} msg] $msg $info
} {0 willi {x 2 read}}
test trace-1.7 {trace array element reads, create element undefined if nonexistant} {
    unset -nocomplain x
    set info {}
    trace add variable x read q
    proc q {name1 name2 op} {
        global info
        set info [list $name1 $name2 $op]
        global $name1
        set ${name1}($name2) wolf
	global info
	set info [list $name1 $name2 $op]
	global $name1
	set ${name1}($name2) wolf
    }
    proc p {} {
        global x
        set x(X) willi
        return $x(Y)
	global x
	set x(X) willi
	return $x(Y)
    }
    list [catch {p} msg] $msg $info
} {0 wolf {x Y read}}
test trace-1.8 {trace reads on whole arrays} {
    unset -nocomplain x
    set info {}
    trace add variable x read traceArray
    list [catch {set x(2)} msg] $msg $info
} {1 {can't read "x(2)": no such variable} {}}
test trace-1.9 {trace reads on whole arrays} {
    unset -nocomplain x
    set x(2) zzz
    set info {}
    trace add variable x read traceArray
    list [catch {set x(2)} msg] $msg $info
} {0 zzz {x 2 read 0 zzz}}
test trace-1.10 {trace variable reads} {
test trace-1.10 {trace add variable reads} {
    unset -nocomplain x
    set x 444
    set info {}
    trace add variable x read traceScalar
    unset x
    set info
} {}
test trace-1.11 {read traces that modify the array structure} {
    unset -nocomplain x
    set x(bar) 0
    trace variable x r {set x(foo) 1 ;#}
    trace variable x r {unset -nocomplain x(bar) ;#}
    trace add variable x read {set x(foo) 1 ;#}
    trace add variable x read {unset -nocomplain x(bar) ;#}
    array get x
} {}
test trace-1.12 {read traces that modify the array structure} {
    unset -nocomplain x
    set x(bar) 0
    trace variable x r {unset -nocomplain x(bar) ;#}
    trace variable x r {set x(foo) 1 ;#}
    trace add variable x read {unset -nocomplain x(bar) ;#}
    trace add variable x read {set x(foo) 1 ;#}
    array get x
} {}
test trace-1.13 {read traces that modify the array structure} {
    unset -nocomplain x
    set x(bar) 0
    trace variable x r {set x(foo) 1 ;#}
    trace variable x r {unset -nocomplain x;#}
    trace add variable x read {set x(foo) 1 ;#}
    trace add variable x read {unset -nocomplain x;#}
    list [catch {array get x} res] $res
} {1 {can't read "x(bar)": no such variable}}
test trace-1.14 {read traces that modify the array structure} {
    unset -nocomplain x
    set x(bar) 0
    trace variable x r {unset -nocomplain x;#}
    trace variable x r {set x(foo) 1 ;#}
    trace add variable x read {unset -nocomplain x;#}
    trace add variable x read {set x(foo) 1 ;#}
    list [catch {array get x} res] $res
} {1 {can't read "x(bar)": no such variable}}

# Basic write-tracing on variables

test trace-2.1 {trace variable writes} {
test trace-2.1 {trace add variable writes} {
    unset -nocomplain x
    set info {}
    trace add variable x write traceScalar
    set x 123
    set info
} {x {} write 0 123}
test trace-2.2 {trace writes to array elements} {
    unset -nocomplain x
    set info {}
    trace add variable x(33) write traceArray
    set x(33) 444
    set info
} {x 33 write 0 444}
test trace-2.3 {trace writes on whole arrays} {
    unset -nocomplain x
    set info {}
    trace add variable x write traceArray
    set x(abc) qq
    set info
} {x abc write 0 qq}
test trace-2.4 {trace variable writes} {
test trace-2.4 {trace add variable writes} {
    unset -nocomplain x
    set x 1234
    set info {}
    trace add variable x write traceScalar
    set x
    set info
} {}
test trace-2.5 {trace variable writes} {
test trace-2.5 {trace add variable writes} {
    unset -nocomplain x
    set x 1234
    set info {}
    trace add variable x write traceScalar
    unset x
    set info
} {}
test trace-2.6 {trace variable writes on compiled local} {
test trace-2.6 {trace add variable writes on compiled local} {
    #
    # Check correct function of whole array traces on compiled local
    # arrays [Bug 1770591]. The corresponding function for read traces is
    # already indirectly tested in trace-1.7
    #
    unset -nocomplain x
    set info {}
    proc p {} {
	trace add variable x write traceArray
	set x(X) willy
    }
    p
    set info
} {x X write 0 willy}
test trace-2.7 {trace variable writes on errorInfo} -body {
test trace-2.7 {trace add variable writes on errorInfo} -body {
   #
   # Check correct behaviour of write traces on errorInfo.
   # [Bug 1773040]
   trace add variable ::errorInfo write traceScalar
   catch {set dne}
   lrange [set info] 0 2
} -cleanup {
   # always remove trace on errorInfo otherwise further tests will fail
   unset ::errorInfo
} -result {::errorInfo {} write}



# append no longer triggers read traces when fetching the old values of
# variables before doing the append operation. However, lappend _does_
# still trigger these read traces. Also lappend triggers only one write
# trace: after appending all arguments to the list.

test trace-3.1 {trace variable read-modify-writes} {
test trace-3.1 {trace add variable read-modify-writes} {
    unset -nocomplain x
    set info {}
    trace add variable x read traceScalarAppend
    append x 123
    append x 456
    lappend x 789
    set info
} {x {} read 0 123456}
test trace-3.2 {trace variable read-modify-writes} {
test trace-3.2 {trace add variable read-modify-writes} {
    unset -nocomplain x
    set info {}
    trace add variable x {read write} traceScalarAppend
    append x 123
    lappend x 456
    set info
} {x {} write 0 123 x {} read 0 123 x {} write 0 {123 456}}

# Basic unset-tracing on variables

test trace-4.1 {trace variable unsets} {
test trace-4.1 {trace add variable unsets} {
    unset -nocomplain x
    set info {}
    trace add variable x unset traceScalar
    unset -nocomplain x
    set info
} {x {} unset 1 {can't read "x": no such variable}}
test trace-4.2 {variable mustn't exist during unset trace} {
393
394
395
396
397
398
399
400
401


402
403

404
405
406
407
408
409
410
393
394
395
396
397
398
399


400
401
402

403
404
405
406
407
408
409
410







-
-
+
+

-
+







    unset -nocomplain x
    trace add variable x array traceArray2
    set result [trace info variable x]
    set result
} [list [list array traceArray2]]
test trace-5.5 {array traces properly listed in trace information} {
    unset -nocomplain x
    trace variable x a traceArray2
    set result [trace vinfo x]
    trace add variable x array traceArray2
    set result [trace info variable x]
    set result
} [list [list a traceArray2]]
} [list [list array traceArray2]]
test trace-5.6 {array traces don't fire on scalar variables} {
    unset -nocomplain x
    set x foo
    trace add variable x array traceArray2
    set ::info {}
    catch {array set x {a 1}}
    set ::info
867
868
869
870
871
872
873
874

875
876
877
878
879
880
881
867
868
869
870
871
872
873

874
875
876
877
878
879
880
881







-
+







} [list 1 "wrong # args: should be \"trace remove type ?arg ...?\""]
test trace-14.4 "trace command, wrong # args errors" {
    list [catch {trace info} msg] $msg
} [list 1 "wrong # args: should be \"trace info type name\""]

test trace-14.5 {trace command, invalid option} {
    list [catch {trace gorp} msg] $msg
} [list 1 "bad option \"gorp\": must be add, info, remove, variable, vdelete, or vinfo"]
} [list 1 "bad option \"gorp\": must be add, info, or remove"]

# Again, [trace ... command] and [trace ... variable] share syntax and
# error message styles for their opList options; these loops test those
# error messages.

set i 0
set errs [list "array, read, unset, or write" "delete or rename" "enter, leave, enterstep, or leavestep"]
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
893
894
895
896
897
898
899

















900
901
902
903
904
905
906







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	}
	test trace-14.6.[incr i] "trace $op $type rejects null opList" {
	    list [catch {trace $op $type x {} a} msg] $msg
	} [list 1 "bad operation list \"\": must be one or more of $err"]
    }
}
rename x {}

test trace-14.7 {trace command, "trace variable" errors} {
    list [catch {trace variable} msg] $msg
} [list 1 "wrong # args: should be \"trace variable name ops command\""]
test trace-14.8 {trace command, "trace variable" errors} {
    list [catch {trace variable x} msg] $msg
} [list 1 "wrong # args: should be \"trace variable name ops command\""]
test trace-14.9 {trace command, "trace variable" errors} {
    list [catch {trace variable x y} msg] $msg
} [list 1 "wrong # args: should be \"trace variable name ops command\""]
test trace-14.10 {trace command, "trace variable" errors} {
    list [catch {trace variable x y z w} msg] $msg
} [list 1 "wrong # args: should be \"trace variable name ops command\""]
test trace-14.11 {trace command, "trace variable" errors} {
    list [catch {trace variable x y z} msg] $msg
} [list 1 "bad operations \"y\": should be one or more of rwua"]


test trace-14.12 {trace command ("remove variable" option)} {
    unset -nocomplain x
    set info {}
    trace add variable x write traceProc
    trace remove variable x write traceProc
} {}
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
1213
1214
1215
1216
1217
1218
1219

1220
1221
1222
1223
1224

1225
1226

1227
1228
1229
1230

1231
1232
1233
1234
1235

1236
1237
1238
1239
1240
1241
1242
1243







-
+




-
+

-
+



-
+




-
+







test trace-18.1 {unset traces on procedure returns} {
    proc p1 {x y} {set a 44; p2 14}
    proc p2 {z} {trace add variable z unset {traceCheck {lsort [uplevel 1 {info vars}]}}}
    set info {}
    p1 foo bar
    set info
} {0 {a x y}}
test trace-18.2 {namespace delete / trace vdelete combo} {
test trace-18.2 {namespace delete / trace remove variable combo} {
    namespace eval ::foo {
	variable x 123
    }
    proc p1 args {
	trace vdelete ::foo::x u p1
	trace remove variable ::foo::x unset p1
    }
    trace variable ::foo::x u p1
    trace add variable ::foo::x unset p1
    namespace delete ::foo
    info exists ::foo::x
} 0
test trace-18.3 {namespace delete / trace vdelete combo, Bug \#1337229} {
test trace-18.3 {namespace delete / trace remove variable combo, Bug \#1337229} {
    namespace eval ::ns {}
    trace add variable ::ns::var unset {unset ::ns::var ;#}
    namespace delete ::ns
} {}
test trace-18.4 {namespace delete / trace vdelete combo, Bug \#1338280} {
test trace-18.4 {namespace delete / trace remove variable combo, Bug \#1338280} {
    namespace eval ::ref {}
    set ::ref::var1 AAA
    trace add variable ::ref::var1 unset doTrace
    set ::ref::var2 BBB
    trace add variable ::ref::var2 {unset} doTrace
    proc doTrace {vtraced vidx op} {
	global info
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
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







-
-
+
+

-
+












-
-
+
+

-
+







} {{foo {set b 3} 0 3 leavestep}}

test trace-21.9 {trace execution: TCL_EVAL_GLOBAL} testevalobjv {
    trace add execution foo enter soom
    proc ::soom args {lappend ::info SUCCESS [info level]}
    set ::info {}
    namespace eval test_ns_1 {
        proc soom args {lappend ::info FAIL [info level]}
        # [testevalobjv 1 ...] ought to produce the same
	proc soom args {lappend ::info FAIL [info level]}
	# [testevalobjv 1 ...] ought to produce the same
       # results as [uplevel #0 ...].
        testevalobjv 1 foo x
	testevalobjv 1 foo x
       uplevel #0 foo x
    }
    namespace delete test_ns_1
    trace remove execution foo enter soom
    set ::info
} {SUCCESS 1 SUCCESS 1}

test trace-21.10 {trace execution: TCL_EVAL_GLOBAL} testevalobjv {
    trace add execution foo leave soom
    proc ::soom args {lappend ::info SUCCESS [info level]}
    set ::info {}
    namespace eval test_ns_1 {
        proc soom args {lappend ::info FAIL [info level]}
        # [testevalobjv 1 ...] ought to produce the same
	proc soom args {lappend ::info FAIL [info level]}
	# [testevalobjv 1 ...] ought to produce the same
       # results as [uplevel #0 ...].
        testevalobjv 1 foo x
	testevalobjv 1 foo x
       uplevel #0 foo x
    }
    namespace delete test_ns_1
    trace remove execution foo leave soom
    set ::info
} {SUCCESS 1 SUCCESS 1}

1708
1709
1710
1711
1712
1713
1714
1715

1716
1717
1718
1719
1720
1721
1722
1691
1692
1693
1694
1695
1696
1697

1698
1699
1700
1701
1702
1703
1704
1705







-
+







    set {*}$args
}

test trace-21.12 {bug 2438181} -setup {
    trace add execution set2 leave {puts one two three #;}
} -body {
    set2 a hello
} -returnCodes 1 -result {wrong # args: should be "puts ?-nonewline? ?channelId? string"}
} -returnCodes 1 -result {wrong # args: should be "puts ?-nonewline? ?channel? string"}

proc factorial {n} {
    if {$n != 1} { return [expr {$n * [factorial [expr {$n -1 }]]}] }
    return 1
}

test trace-22.1 {recursive(1) trace execution: enter} {
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080



2081
2082
2083
2084
2085

2086
2087
2088
2089
2090
2091

2092
2093
2094
2095
2096
2097
2098
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







-
-
-
+
+
+




-
+





-
+







    list [catch {trace info command thisdoesntexist} res] $res
} {1 {unknown command "thisdoesntexist"}}


test trace-28.1 {enterstep and leavestep traces with update idletasks (615043)} {
    catch {rename foo {}}
    proc foo {} {
        set a 1
        update idletasks
        set b 1
	set a 1
	update idletasks
	set b 1
    }

    set info {}
    trace add execution foo {enter enterstep leavestep leave} \
        [list traceExecute foo]
	[list traceExecute foo]
    update
    after idle {set a "idle"}
    foo

    trace remove execution foo {enter enterstep leavestep leave} \
        [list traceExecute foo]
	[list traceExecute foo]
    rename foo {}
    unset -nocomplain a
    join $info "\n"
} {foo foo enter
foo {set a 1} enterstep
foo {set a 1} 0 1 leavestep
foo {update idletasks} enterstep
2310
2311
2312
2313
2314
2315
2316
2317
2318


2319
2320
2321
2322
2323
2324
2325
2293
2294
2295
2296
2297
2298
2299


2300
2301
2302
2303
2304
2305
2306
2307
2308







-
-
+
+







} {1 {unknown command "thisdoesntexist"}}

test trace-28.10 {exec trace info nonsense} {
    list [catch {trace remove execution} res] $res
} {1 {wrong # args: should be "trace remove execution name opList command"}}

test trace-29.1 {Tcl_CreateTrace, correct command and argc/argv arguments of trace proc} {testcmdtrace} {
    testcmdtrace tracetest {set stuff [expr 14 + 16]}
} {{expr 14 + 16} {expr 14 + 16} {set stuff [expr 14 + 16]} {set stuff 30}}
    testcmdtrace tracetest {set stuff [expr {14 + 16}]}
} {{expr {14 + 16}} {expr {14 + 16}} {set stuff [expr {14 + 16}]} {set stuff 30}}
test trace-29.2 {Tcl_CreateTrace, correct command and argc/argv arguments of trace proc} {testcmdtrace} {
    testcmdtrace tracetest {set stuff [info tclversion]}
} [concat {{info tclversion} {info tclversion} ::tcl::info::tclversion {::tcl::info::tclversion} {set stuff [info tclversion]}} [list "set stuff [info tclversion]"]]
test trace-29.3 {Tcl_CreateTrace, correct command and argc/argv arguments of trace proc} {testcmdtrace} {
    testcmdtrace deletetest {set stuff [info tclversion]}
} [info tclversion]
test trace-29.4 {Tcl_CreateTrace, check that tracing doesn't cause memory faults} {testcmdtrace} {
2416
2417
2418
2419
2420
2421
2422
2423

2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437






2438
2439
2440
2441
2442
2443
2444
2399
2400
2401
2402
2403
2404
2405

2406
2407
2408
2409
2410
2411
2412
2413
2414






2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427







-
+








-
-
-
-
-
-
+
+
+
+
+
+







    set result [trace info command foo]
    rename foo {}
    set result
} [list [list delete foo]]

test trace-33.1 {variable match with remove variable} {
    unset -nocomplain x
    trace variable x w foo
    trace add variable x write foo
    trace remove variable x write foo
    llength [trace info variable x]
} 0

test trace-34.1 {Bug 1201035} {
    set ::x [list]
    proc foo {} {lappend ::x foo}
    proc bar args {
        lappend ::x $args
        trace remove execution foo leavestep bar
        trace remove execution foo enterstep bar
        trace add execution foo leavestep bar
        trace add execution foo enterstep bar
        lappend ::x done
	lappend ::x $args
	trace remove execution foo leavestep bar
	trace remove execution foo enterstep bar
	trace add execution foo leavestep bar
	trace add execution foo enterstep bar
	lappend ::x done
    }
    trace add execution foo leavestep bar
    trace add execution foo enterstep bar
    foo
    set ::x
} {{{lappend ::x foo} enterstep} done foo}

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
2489
2490
2491




2492
2493
2494

2495
2496
2497

2498
2499
2500

2501
2502
2503
2504
2505
2506
2507
2442
2443
2444
2445
2446
2447
2448

2449
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
2489
2490







-
+










-
+










-
-
-
-
+
+
+
+


-
+


-
+


-
+







} {}

# We test here for the half-documented and currently valid interplay between
# delete traces and namespace deletion.
test trace-34.4 {Bug 1047286} {
    variable x notrace
    proc callback {old - -} {
        variable x "$old exists: [namespace which -command $old]"
	variable x "$old exists: [namespace which -command $old]"
    }
    namespace eval ::foo {proc bar {} {}}
    trace add command ::foo::bar delete [namespace code callback]
    namespace delete ::foo
    set x
} {::foo::bar exists: ::foo::bar}

test trace-34.5 {Bug 1047286} {
    variable x notrace
    proc callback {old - -} {
        variable x "$old exists: [namespace which -command $old]"
	variable x "$old exists: [namespace which -command $old]"
    }
    namespace eval ::foo {proc bar {} {}}
    trace add command ::foo::bar delete [namespace code callback]
    namespace eval ::foo namespace delete ::foo
    set x
} {::foo::bar exists: }

test trace-34.6 {Bug 1458266} -setup {
    proc dummy {} {}
    proc stepTraceHandler {cmdString args} {
        variable log
        append log "[expr {[info level] - 1}]: [lindex [split $cmdString] 0]\n"
        dummy
        isTracedInside_2
	variable log
	append log "[expr {[info level] - 1}]: [lindex [split $cmdString] 0]\n"
	dummy
	isTracedInside_2
    }
    proc cmdTraceHandler {cmdString args} {
        # silent
	# silent
    }
    proc isTracedInside_1 {} {
        isTracedInside_2
	isTracedInside_2
    }
    proc isTracedInside_2 {} {
        set x 2
	set x 2
    }
} -body {
    variable log {}
    trace add execution isTracedInside_1 enterstep stepTraceHandler
    trace add execution isTracedInside_2 enterstep stepTraceHandler
    isTracedInside_1
    variable first $log

Added tests/twapiTlsPlus.tcl.

















































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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# Module twapiTlsPlus
#
# Temporary wrapper for package twapi, to expose the same API as package tls.
# - Command twapiTlsPlus::socket, cf. tls::socket, replacement for ::socket, for
#   use with http::register.
# - Variable twapiTlsPlus::socketCmd, cf. tls::socketCmd, holds the value of the
#   callback command used by twapi to open a socket.
#
# Intended to allow twapi TLS to use an https proxy server, and a background
# thread for evaluation of ::socket.
#
# For twapiTlsPlus to work correctly, twapi*/tls.tcl must be edited so that
#-        set so [$socketcmd {*}$socket_args {*}$args]
#+        set so [{*}$socketcmd {*}$socket_args {*}$args]

package require http
package require twapi

namespace eval twapiTlsPlus {
    variable socketCmd [::twapi::tls_socket_command]
    namespace export socket
}

# Proc twapiTlsPlus::socket
# Replacement for ::socket, use with http::register.

proc twapiTlsPlus::socket {args} {
    variable socketCmd

    set targ [lsearch -exact $args -type]
    if {$targ != -1} {
	set token [lindex $args $targ+1]
	set args [lreplace $args $targ $targ+1 -socketcmd [list {*}$socketCmd -type $token]]
    }
    ::twapi::tls_socket {*}$args
}

# Variable twapi::tls::_socket_cmd does it.

proc twapiTlsPlus::TraceSocketCmd {args} {
    variable socketCmd
    ::twapi::tls_socket_command $socketCmd
    return
}

trace add variable ::twapiTlsPlus::socketCmd write ::twapiTlsPlus::TraceSocketCmd

package provide twapiTlsPlus 0.1

Changes to tests/unixFCmd.test.

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
30
31
32
33
34
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
30
31
32
33
34
35
36






-
+










-
+


+
+






-
+







# This file tests the tclUnixFCmd.c file.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1996 Sun Microsystems, Inc.
# Copyright © 1996 Sun Microsystems, Inc.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testchmod [llength [info commands testchmod]]
# File permissions broken on wsl without some "exotic" wsl configuration
testConstraint notWsl [expr {[llength [array names ::env *WSL*]] == 0}]

# These tests really need to be run from a writable directory, which
# it is assumed [temporaryDirectory] is.
set oldcwd [pwd]
cd [temporaryDirectory]

# Several tests require need to match results against the unix username
# Several tests require need to match results against the Unix username
set user {}
if {[testConstraint unix]} {
    catch {set user [exec whoami]}
    if {$user == ""} {
	catch {regexp {^[^(]*\(([^)]*)\)} [exec id] dummy user}
    }
    if {$user == ""} {
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
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







-
+

-
+


-
+










-
+







if {[testConstraint unix] && [testConstraint notRoot]} {
    testConstraint execMknod [expr {![catch {exec mknod tf1 p}]}]
    cleanup
}

test unixFCmd-1.1 {TclpRenameFile: EACCES} -setup {
    cleanup
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
    file mkdir td1/td2/td3
    file attributes td1/td2 -permissions 0000
    file attributes td1/td2 -permissions 0
    file rename td1/td2/td3 td2
} -returnCodes error -cleanup {
    file attributes td1/td2 -permissions 0755
    file attributes td1/td2 -permissions 0o755
    cleanup
} -result {error renaming "td1/td2/td3": permission denied}
test unixFCmd-1.2 {TclpRenameFile: EEXIST} -setup {
    cleanup
} -constraints {unix notRoot} -body {
    file mkdir td1/td2
    file mkdir td2
    file rename td2 td1
} -returnCodes error -cleanup {
    cleanup
} -result {error renaming "td2" to "td1/td2": file already exists}
} -result {error renaming "td2" to "td1/td2": file exists}
test unixFCmd-1.3 {TclpRenameFile: EINVAL} -setup {
    cleanup
} -constraints {unix notRoot} -body {
    file mkdir td1
    file rename td1 td1
} -returnCodes error -cleanup {
    cleanup
131
132
133
134
135
136
137
138

139
140

141
142
143
144

145
146
147
148
149
150
151
133
134
135
136
137
138
139

140
141

142
143
144
145

146
147
148
149
150
151
152
153







-
+

-
+



-
+







    cleanup
} -result {error renaming "td2": no such file or directory}
test unixFCmd-1.6 {TclpRenameFile: ENOTDIR} {emptyTest unix notRoot} {
    # can't make it happen
} {}
test unixFCmd-1.7 {TclpRenameFile: EXDEV} -setup {
    cleanup
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
    file mkdir foo/bar
    file attr foo -perm 040555
    file attr foo -perm 0o40555
    file rename foo/bar /tmp
} -returnCodes error -cleanup {
    catch {file delete /tmp/bar}
    catch {file attr foo -perm 040777}
    catch {file attr foo -perm 0o40777}
    catch {file delete -force foo}
} -match glob -result {*: permission denied}
test unixFCmd-1.8 {Checking EINTR Bug} {unix notRoot nonPortable} {
    testalarm
    after 2000
    list [testgotsig] [testgotsig]
} {1 0}
215
216
217
218
219
220
221
222

223
224
225
226
227
228
229
217
218
219
220
221
222
223

224
225
226
227
228
229
230
231







-
+







    file copy tf1 tf2
    list [file type tf1] [file type tf2]
} -cleanup {
    cleanup
} -result {fifo fifo}
test unixFCmd-2.5 {TclpCopyFile: copy attributes} -setup {
    cleanup
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
    close [open tf1 a]
    file attributes tf1 -permissions 0o472
    file copy tf1 tf2
    file attributes tf2 -permissions
} -cleanup {
    cleanup
} -result 0o472 ;# i.e. perms field of [exec ls -l tf2] is -r--rwx-w-
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
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







-
+

-
+







-
+







    catch {file delete -force -- foo.test}
} -constraints {unix notRoot} -returnCodes error -body {
    file attributes foo.test -owner foozzz
} -result {could not set owner for file "foo.test": user "foozzz" does not exist}

test unixFCmd-17.1 {SetPermissionsAttribute} -setup {
    catch {file delete -force -- foo.test}
} -constraints {unix notRoot} -body {
} -constraints {unix notRoot notWsl} -body {
    close [open foo.test w]
    list [file attributes foo.test -permissions 0000] \
    list [file attributes foo.test -permissions 0] \
	[file attributes foo.test -permissions]
} -cleanup {
    file delete -force -- foo.test
} -result {{} 00000}
test unixFCmd-17.2 {SetPermissionsAttribute} -setup {
    catch {file delete -force -- foo.test}
} -constraints {unix notRoot} -returnCodes error -body {
    file attributes foo.test -permissions 0000
    file attributes foo.test -permissions 0
} -result {could not set permissions for file "foo.test": no such file or directory}
test unixFCmd-17.3 {SetPermissionsAttribute} -setup {
    catch {file delete -force -- foo.test}
} -constraints {unix notRoot} -body {
    close [open foo.test w]
    file attributes foo.test -permissions foo
} -cleanup {
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
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







-
+


















-
+




-
+



-
+







} -cleanup {
    file delete -force -- foo.test
} -returnCodes error -result {unknown permission string format "---rwx"}

close [open foo.test w]
set ::i 4
proc permcheck {testnum permList expected} {
    test $testnum {SetPermissionsAttribute} {unix notRoot} {
    test $testnum {SetPermissionsAttribute} {unix notRoot notWsl} {
      set result {}
      foreach permstr $permList {
	file attributes foo.test -permissions $permstr
	lappend result [file attributes foo.test -permissions]
      }
      set result
    } $expected
}
permcheck unixFCmd-17.5   rwxrwxrwx	0o777
permcheck unixFCmd-17.6   r--r---w-	0o442
permcheck unixFCmd-17.7   {0 u+rwx,g+r u-w o+rwx} {00000 0o740 0o540 0o547}
permcheck unixFCmd-17.11  --x--x--x	0o111
permcheck unixFCmd-17.12  {0 a+rwx} {00000 0o777}
file delete -force -- foo.test

test unixFCmd-18.1 {Unix pwd} -constraints {unix notRoot nonPortable} -setup {
    set cd [pwd]
} -body {
    # This test is nonPortable because SunOS generates a weird error
    # This test is non-portable because SunOS generates a weird error
    # message when the current directory isn't readable.
    set nd $cd/tstdir
    file mkdir $nd
    cd $nd
    file attributes $nd -permissions 0000
    file attributes $nd -permissions 0
    pwd
} -returnCodes error -cleanup {
    cd $cd
    file attributes $nd -permissions 0755
    file attributes $nd -permissions 0o755
    file delete $nd
} -match glob -result {error getting working directory name:*}

test unixFCmd-19.1 {GetReadOnlyAttribute - file not found} -setup {
    catch {file delete -force -- foo.test}
} -constraints {unix notRoot readonlyAttr} -returnCodes error -body {
    file attributes foo.test -readonly

Changes to tests/unixFile.test.

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
30
31
32
33
34
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
30
31
32
33
34






-
+










-
+








-
+







# This file contains tests for the routines in the file tclUnixFile.c
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testfindexecutable [llength [info commands testfindexecutable]]

set oldpwd [pwd]
cd [temporaryDirectory]

catch {
    set oldPath $env(PATH)
    file attributes [makeFile "" junk] -perm 0777
    file attributes [makeFile "" junk] -perm 0o777
}
set absPath [file join [temporaryDirectory] junk]

test unixFile-1.1 {Tcl_FindExecutable} {testfindexecutable unix} {
    set env(PATH) ""
    testfindexecutable junk
} $absPath

Changes to tests/unixForkEvent.test.

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
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




-
-
+
+













-
+







# This file contains a collection of tests for the procedures in the file
# tclUnixNotify.c.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1995-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
}

testConstraint testfork [llength [info commands testfork]]

# Test if the notifier thread is well initialized in a forked interpreter
# by Tcl_InitNotifier
test unixforkevent-1.1 {fork and test writeable event} \
test unixforkevent-1.1 {fork and test writable event} \
    -constraints {testfork nonPortable} \
    -body {
	set myFolder [makeDirectory unixtestfork]
	set pid [testfork]
	if {$pid == 0} {
	    # we are the forked process
	    set result initialized

Changes to tests/unixInit.test.

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
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






-
-
+
+











-
-
-







# The file tests the functions in the tclUnixInit.c file.
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands.  Sourcing this file into Tcl runs the tests and generates output
# for errors.  No output means no errors were found.
#
# Copyright (c) 1997 by Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
}
unset -nocomplain path
catch {set oldlang $env(LANG)}
set env(LANG) C

# Some tests require the testgetencpath command
testConstraint testgetencpath [llength [info commands testgetencpath]]

test unixInit-1.1 {TclpInitPlatform: ignore SIGPIPE} {unix stdio} {
    set x {}
    # Watch out for a race condition here.  If tcltest is too slow to start
    # then we'll kill it before it has a chance to set up its signal handler.
    set f [open "|[list [interpreter]]" w+]
    puts $f "puts hi"
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
366

367
368
369
370
371
372
373
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-













+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
-
+

















+







    } then {
	subst "OK"
    } else {
	subst "Expected: `[list 127.0.0.1 localhost $port]', Got `$result'"
    }
} {OK}

# The unixInit-2.* tests were written to test the internal routine,
# TclpInitLibraryPath.  That routine no longer does the things it used to do
# so those tests are obsolete.  Skip them.

skip [concat [skip] unixInit-2.*]

test unixInit-2.0 {TclpInitLibraryPath: setting tclDefaultEncodingDir} -constraints {
    testgetencpath
} -body {
    set origPath [testgetencpath]
    testsetencpath slappy
    set path [testgetencpath]
    testsetencpath $origPath
    set path
} -result {slappy}
test unixInit-2.1 {TclpInitLibraryPath: value of installLib, developLib} -setup {
    unset -nocomplain oldlibrary
    if {[info exists env(TCL_LIBRARY)]} {
	set oldlibrary $env(TCL_LIBRARY)
	unset env(TCL_LIBRARY)
    }
} -body {
    set path [getlibpath]
    set installLib lib/tcl[info tclversion]
    set developLib tcl[info patchlevel]/library
    set prefix [file dirname [file dirname [interpreter]]]
    list [string equal [lindex $path 0] $prefix/$installLib] \
	[string equal [lindex $path 4] [file dirname $prefix]/$developLib]
} -cleanup {
    if {[info exists oldlibrary]} {
	set env(TCL_LIBRARY) $oldlibrary
	unset oldlibrary
    }
} -result {1 1}
test unixInit-2.2 {TclpInitLibraryPath: TCL_LIBRARY} -setup {
    unset -nocomplain oldlibrary
    if {[info exists env(TCL_LIBRARY)]} {
	set oldlibrary $env(TCL_LIBRARY)
    }
} -body {
    # ((str != NULL) && (str[0] != '\0'))
    set env(TCL_LIBRARY) sparkly
    lindex [getlibpath] 0
} -cleanup {
    unset -nocomplain env(TCL_LIBRARY)
    if {[info exists oldlibrary]} {
	set env(TCL_LIBRARY) $oldlibrary
	unset oldlibrary
    }
} -result "sparkly"
test unixInit-2.3 {TclpInitLibraryPath: TCL_LIBRARY wrong version} -setup {
    unset -nocomplain oldlibrary
    if {[info exists env(TCL_LIBRARY)]} {
	set oldlibrary $env(TCL_LIBRARY)
    }
} -body {
    # ((pathc > 0) && (strcasecmp(installLib + 4, pathv[pathc - 1]) != 0))
    set env(TCL_LIBRARY) /a/b/tcl1.7
    lrange [getlibpath] 0 1
} -cleanup {
    unset -nocomplain env(TCL_LIBRARY)
    if {[info exists oldlibrary]} {
	set env(TCL_LIBRARY) $oldlibrary
	unset oldlibrary
    }
} -result [list /a/b/tcl1.7 /a/b/tcl[info tclversion]]
test unixInit-2.4 {TclpInitLibraryPath: TCL_LIBRARY: INTL} -setup {
    if {[info exists env(TCL_LIBRARY)]} {
	set oldlibrary $env(TCL_LIBRARY)
    }
} -body {
    # Child process translates env variable from native encoding.
    set env(TCL_LIBRARY) "\xa7"
    lindex [getlibpath] 0
} -cleanup {
    unset -nocomplain env(TCL_LIBRARY) env(LANG)
    if {[info exists oldlibrary]} {
	set env(TCL_LIBRARY) $oldlibrary
	unset oldlibrary
    }
} -result "\xa7"
test unixInit-2.5 {TclpInitLibraryPath: compiled-in library path} {
    # cannot test
} {}
test unixInit-2.6 {TclpInitLibraryPath: executable relative} -setup {
    unset -nocomplain oldlibrary
    if {[info exists env(TCL_LIBRARY)]} {
	set oldlibrary $env(TCL_LIBRARY)
    }
    set env(TCL_LIBRARY) [info library]
    makeDirectory tmp
    makeDirectory [file join tmp sparkly]
    makeDirectory [file join tmp sparkly bin]
    file copy [interpreter] [file join [temporaryDirectory] tmp sparkly \
	    bin tcltest]
    makeDirectory [file join tmp sparkly lib]
    makeDirectory [file join tmp sparkly lib tcl[info tclversion]]
    makeFile {} [file join tmp sparkly lib tcl[info tclversion] init.tcl]
} -body {
    lrange [getlibpath [file join [temporaryDirectory] tmp sparkly \
	    bin tcltest]] 1 2
} -cleanup {
    removeFile [file join tmp sparkly lib tcl[info tclversion] init.tcl]
    removeDirectory [file join tmp sparkly lib tcl[info tclversion]]
    removeDirectory [file join tmp sparkly lib]
    removeDirectory [file join tmp sparkly bin]
    removeDirectory [file join tmp sparkly]
    removeDirectory tmp
    unset env(TCL_LIBRARY)
    if {[info exists oldlibrary]} {
	set env(TCL_LIBRARY) $oldlibrary
	unset oldlibrary
    }
} -result [list [temporaryDirectory]/tmp/sparkly/lib/tcl[info tclversion] [temporaryDirectory]/tmp/lib/tcl[info tclversion]]
test unixInit-2.7 {TclpInitLibraryPath: compiled-in library path} {
    # would need test command to get defaultLibDir and compare it to
    # [lindex $auto_path end]
} {}
#
# The following two tests write to the directory /tmp/sparkly instead of to
# [temporaryDirectory].  This is because the failures tested by these tests
# need paths near the "root" of the file system to present themselves.
#
test unixInit-2.8 {TclpInitLibraryPath: all absolute pathtype} -setup {
    unset -nocomplain oldlibrary
    if {[info exists env(TCL_LIBRARY)]} {
	set oldlibrary $env(TCL_LIBRARY)
    }
    set env(TCL_LIBRARY) [info library]
    # Checking for Bug 219416
    # When a program that embeds the Tcl library, like tcltest, is installed
    # near the "root" of the file system, there was a problem constructing
    # directories relative to the executable.  When a relative ".." went past
    # the root, relative path names were created rather than absolute
    # pathnames.  In some cases, accessing past the root caused memory access
    # violations too.
    #
    # The bug is now fixed, but here we check for it by making sure that the
    # directories constructed relative to the executable are all absolute
    # pathnames, even when the executable is installed near the root of the
    # filesystem.
    #
    # The only directory near the root we are likely to have write access to
    # is /tmp.
    file delete -force /tmp/sparkly
    file delete -force /tmp/lib/tcl[info tclversion]
    file mkdir /tmp/sparkly
    file copy [interpreter] /tmp/sparkly/tcltest
    # Keep any existing /tmp/lib directory
    set deletelib 1
    if {[file exists /tmp/lib]} {
	if {[file isdirectory /tmp/lib]} {
	    set deletelib 0
	} else {
	    file delete -force /tmp/lib
	}
    }
    # For a successful Tcl_Init, we need a [source]-able init.tcl in
    # ../lib/tcl$version relative to the executable.
    file mkdir /tmp/lib/tcl[info tclversion]
    close [open /tmp/lib/tcl[info tclversion]/init.tcl w]
} -body {
    # Check that all directories in the library path are absolute pathnames
    set allAbsolute 1
    foreach dir [getlibpath /tmp/sparkly/tcltest] {
	set allAbsolute [expr {$allAbsolute \
		&& [string equal absolute [file pathtype $dir]]}]
    }
    set allAbsolute
} -cleanup {
    # Clean up temporary installation
    file delete -force /tmp/sparkly
    file delete -force /tmp/lib/tcl[info tclversion]
    if {$deletelib} {file delete -force /tmp/lib}
    unset env(TCL_LIBRARY)
    if {[info exists oldlibrary]} {
	set env(TCL_LIBRARY) $oldlibrary
	unset oldlibrary
    }
} -result 1
test unixInit-2.9 {TclpInitLibraryPath: paths relative to executable} -setup {
    # Checking for Bug 438014
    unset -nocomplain oldlibrary
    if {[info exists env(TCL_LIBRARY)]} {
	set oldlibrary $env(TCL_LIBRARY)
    }
    set env(TCL_LIBRARY) [info library]
    file delete -force /tmp/sparkly
    file delete -force /tmp/library
    file mkdir /tmp/sparkly
    file copy [interpreter] /tmp/sparkly/tcltest
    file mkdir /tmp/library/
    close [open /tmp/library/init.tcl w]
} -body {
    lrange [getlibpath /tmp/sparkly/tcltest] 1 5
} -cleanup {
    file delete -force /tmp/sparkly
    file delete -force /tmp/library
    unset env(TCL_LIBRARY)
    if {[info exists oldlibrary]} {
	set env(TCL_LIBRARY) $oldlibrary
	unset oldlibrary
    }
} -result [list /tmp/lib/tcl[info tclversion] /lib/tcl[info tclversion] \
        /tmp/library /library /tcl[info patchlevel]/library]
test unixInit-2.10 {TclpInitLibraryPath: executable relative} -setup {
    unset -nocomplain oldlibrary
    if {[info exists env(TCL_LIBRARY)]} {
	set oldlibrary $env(TCL_LIBRARY)
    }
    set env(TCL_LIBRARY) [info library]
    set tmpDir [makeDirectory tmp]
    set sparklyDir [makeDirectory sparkly $tmpDir]
    set execPath [file join [makeDirectory bin $sparklyDir] tcltest]
    file copy [interpreter] $execPath
    set libDir [makeDirectory lib $sparklyDir]
    set scriptDir [makeDirectory tcl[info tclversion] $libDir]
    makeFile {} init.tcl $scriptDir
    set saveDir [pwd]
    cd $libDir
} -body {
    # Checking for Bug 832657
    set x [lrange [getlibpath [file join .. bin tcltest]] 3 4]
    foreach p $x {
	lappend y [file normalize $p]
    }
    set y
} -cleanup {
    cd $saveDir
    removeFile init.tcl $scriptDir
    removeDirectory tcl[info tclversion] $libDir
    file delete $execPath
    removeDirectory bin $sparklyDir
    removeDirectory lib $sparklyDir
    removeDirectory sparkly $tmpDir
    removeDirectory tmp
    unset -nocomplain saveDir scriptDir libDir execPath sparklyDir tmpDir
    unset -nocomplain x p y env(TCL_LIBRARY)
    if {[info exists oldlibrary]} {
	set env(TCL_LIBRARY) $oldlibrary
	unset oldlibrary
    }
} -result [list [file join [temporaryDirectory] tmp sparkly library] \
	[file join [temporaryDirectory] tmp library] ]

test unixInit-3.1 {TclpSetInitialEncodings} -constraints {
	unix stdio
} -body {
    set env(LANG) C
    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)
} -match regexp -result {^(iso8859-15?|utf-8)$}

# unixInit-3.2 depends on the *spawned* [interpreter] being able to locate
# tcl_library without setting of TCL_LIBRARY env. This in turn depends on
# Tcl's "library" directory being under the parent or grandparent of the
# executable directory (the initScript search path in tclInterp.c).
# Thus this constraint. On GiuHub CI, the only time this is not true
# is for the XCode builds.
if {[string match [zipfs root]* [info library]] ||
    [file isfile [file normalize [file join [info nameofexecutable] .. .. library init.tcl]]] ||
    [file isfile [file normalize [file join [info nameofexecutable] .. .. .. library init.tcl]]]
} {
    tcltest::testConstraint enableUnixInit32 1
} else {
    tcltest::testConstraint enableUnixInit32 0
}
test unixInit-3.2 {TclpSetInitialEncodings} -setup {
    catch {set oldlc_all $env(LC_ALL)}
    catch {set oldtcl_library $env(TCL_LIBRARY)}
    unset -nocomplain env(TCL_LIBRARY)
} -constraints {unix stdio} -body {
} -constraints {unix stdio enableUnixInit32} -body {
    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)

Changes to tests/unixNotfy.test.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







# This file contains tests for tclUnixNotfy.c.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 by Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
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
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







-
+




















-
+







    -constraints {noTk unix thread} \
    -body {
	update
	set f [open [makeFile "" foo] w]
	fileevent $f writable {set x 1}
	vwait x
	close $f
   	thread::create "thread::send [thread::id] {set x ok}"
	thread::create "thread::send [thread::id] {set x ok}"
	vwait x
	set x
    } \
    -result {ok} \
    -cleanup {
	catch { close $f }
	catch { removeFile foo }
    }
test unixNotfy-2.2 {Tcl_DeleteFileHandler} \
    -constraints {noTk unix thread} \
    -body {
	update
	set f1 [open [makeFile "" foo] w]
	set f2 [open [makeFile "" foo2] w]
	fileevent $f1 writable {set x 1}
	fileevent $f2 writable {set y 1}
	vwait x
	close $f1
	vwait y
	close $f2
   	thread::create "thread::send [thread::id] {set x ok}"
	thread::create "thread::send [thread::id] {set x ok}"
	vwait x
	set x
    } \
    -result {ok} \
    -cleanup {
	catch { close $f1 }
	catch { close $f2 }

Changes to tests/unknown.test.

1
2
3
4
5
6
7
8
9



10
11
12
13
14
15
16
1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16






-
-
-
+
+
+







# Commands covered:  unknown
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*

Changes to tests/unload.test.

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
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
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

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






-
-
-
+
+
+










-
+









-
+










-
-
-








-
+






-
+


-
+





-
+


-
+


-
+








-
+



-
+

-
+



-
+


-
+

-
+



-
+



-
+


-
+



-
+



-
+



-
-
+
+



-
+











-
+


-
+

-
+

-
+


-
+







-
+

-
+

-
+


-
+

-
+

-
+



-
+



-
+

-
-
+
+



-
+




-
+

-
-
-
+
+
+



-
+













-
+






-
+




-
+








-
+





-
+



-
+





-
+

-
+


-
+



-
+




-
+




-
+

-
+


-
+




-
+




-
+

-
+



-
+










-
+


-
+







# Commands covered:  unload
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1995 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2003-2004 by Georgios Petasis
# Copyright © 1995 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2003-2004 Georgios Petasis
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

# Figure out what extension is used for shared libraries on this
# platform.
if {![info exists ext]} {
    set ext [info sharedlibextension]
}

# Tests require the existence of one of the DLLs in the dltest directory.
set testDir [file join [file dirname [info nameofexecutable]] dltest]
set x [file join $testDir pkgua$ext]
set x [file join $testDir tcl9pkgua$ext]
set dll "[file tail $x]Required"
testConstraint $dll [file readable $x]

# Tests also require that this DLL has not already been loaded.
set loaded "[file tail $x]Loaded"
set alreadyLoaded [info loaded]
testConstraint $loaded [expr {![string match *pkgua* $alreadyLoaded]}]

set alreadyTotalLoaded [info loaded]

# Certain tests require the 'teststaticpkg' command from tcltest
testConstraint teststaticpkg [llength [info commands teststaticpkg]]

# Certain tests need the 'testsimplefilsystem' in tcltest
testConstraint testsimplefilesystem \
	[llength [info commands testsimplefilesystem]]

proc loadIfNotPresent {pkg args} {
    global testDir ext
    set loaded [lmap x [info loaded {*}$args] {lindex $x 1}]
    if {[string totitle $pkg] ni $loaded} {
	load [file join $testDir $pkg$ext]
	load [file join $testDir tcl9$pkg$ext]
    }
}

# Basic tests: parameter testing...
test unload-1.1 {basic errors} -returnCodes error -body {
    unload
} -result {wrong # args: should be "unload ?-switch ...? fileName ?packageName? ?interp?"}
} -result {wrong # args: should be "unload ?-switch ...? fileName ?prefix? ?interp?"}
test unload-1.2 {basic errors} -returnCodes error -body {
    unload a b c d
} -result {wrong # args: should be "unload ?-switch ...? fileName ?packageName? ?interp?"}
} -result {wrong # args: should be "unload ?-switch ...? fileName ?prefix? ?interp?"}
test unload-1.3 {basic errors} -returnCodes error -body {
    unload a b foobar
} -result {could not find interpreter "foobar"}
test unload-1.4 {basic errors} -returnCodes error -body {
    unload {}
} -result {must specify either file name or package name}
} -result {must specify either file name or prefix}
test unload-1.5 {basic errors} -returnCodes error -body {
    unload {} {}
} -result {must specify either file name or package name}
} -result {must specify either file name or prefix}
test unload-1.6 {basic errors} -returnCodes error -body {
    unload {} Unknown
} -result {package "Unknown" is loaded statically and cannot be unloaded}
} -result {library with prefix "Unknown" is loaded statically and cannot be unloaded}
test unload-1.7 {-nocomplain switch} {
    unload -nocomplain {} Unknown
} {}

set pkgua_loaded {}
set pkgua_detached {}
set pkgua_unloaded {}
# Tests for loading/unloading in trusted (non-safe) interpreters...
test unload-2.1 {basic loading of non-unloadable package, with guess for package name} [list $dll $loaded] {
test unload-2.1 {basic loading of non-unloadable package, with guess for prefix} [list $dll $loaded] {
    loadIfNotPresent pkga
    list [pkga_eq abc def] [lsort [info commands pkga_*]]
} {0 {pkga_eq pkga_quote}}
test unload-2.2 {basic loading of unloadable package, with guess for package name} [list $dll $loaded] {
test unload-2.2 {basic loading of unloadable package, with guess for prefix} [list $dll $loaded] {
    list $pkgua_loaded $pkgua_detached $pkgua_unloaded \
	    [load [file join $testDir pkgua$ext]] \
	    [load [file join $testDir tcl9pkgua$ext]] \
	    [pkgua_eq abc def] [lsort [info commands pkgua_*]] \
	    $pkgua_loaded $pkgua_detached $pkgua_unloaded
} {{} {} {} {} 0 {pkgua_eq pkgua_quote} . {} {}}
test unload-2.3 {basic unloading of non-unloadable package, with guess for package name} -setup {
test unload-2.3 {basic unloading of non-unloadable package, with guess for prefix} -setup {
    loadIfNotPresent pkga
} -constraints [list $dll $loaded] -returnCodes error -match glob -body {
    unload [file join $testDir pkga$ext]
    unload [file join $testDir tcl9pkga$ext]
} -result {file "*" cannot be unloaded under a trusted interpreter}
test unload-2.4 {basic unloading of unloadable package, with guess for package name} -setup {
test unload-2.4 {basic unloading of unloadable package, with guess for prefix} -setup {
    loadIfNotPresent pkgua
} -constraints [list $dll $loaded] -body {
    list $pkgua_loaded $pkgua_detached $pkgua_unloaded \
	    [unload [file join $testDir pkgua$ext]] \
	    [unload [file join $testDir tcl9pkgua$ext]] \
	    [info commands pkgua_*] \
	    $pkgua_loaded $pkgua_detached $pkgua_unloaded
} -result {. {} {} {} {} . . .}
test unload-2.5 {reloading of unloaded package, with guess for package name} -setup {
test unload-2.5 {reloading of unloaded package, with guess for prefix} -setup {
    if {$pkgua_loaded eq ""} {
	loadIfNotPresent pkgua
	unload [file join $testDir pkgua$ext]
	unload [file join $testDir tcl9pkgua$ext]
    }
} -constraints [list $dll $loaded] -body {
    list $pkgua_loaded $pkgua_detached $pkgua_unloaded \
	    [load [file join $testDir pkgua$ext]] \
	    [load [file join $testDir tcl9pkgua$ext]] \
	    [pkgua_eq abc def] [lsort [info commands pkgua_*]] \
	    $pkgua_loaded $pkgua_detached $pkgua_unloaded
} -result {. . . {} 0 {pkgua_eq pkgua_quote} .. . .}
test unload-2.6 {basic unloading of re-loaded package, with guess for package name} -setup {
test unload-2.6 {basic unloading of re-loaded package, with guess for prefix} -setup {
    # Establish expected state
    if {$pkgua_loaded eq ""} {
	loadIfNotPresent pkgua
	unload [file join $testDir pkgua$ext]
	load [file join $testDir pkgua$ext]
	unload [file join $testDir tcl9pkgua$ext]
	load [file join $testDir tcl9pkgua$ext]
    }
} -constraints [list $dll $loaded] -body {
    list $pkgua_loaded $pkgua_detached $pkgua_unloaded \
	    [unload [file join $testDir pkgua$ext]] \
	    [unload [file join $testDir tcl9pkgua$ext]] \
	    [info commands pkgua_*] \
	    $pkgua_loaded $pkgua_detached $pkgua_unloaded
} -result {.. . . {} {} .. .. ..}

# Tests for loading/unloading in safe interpreters...
interp create -safe child
child eval {
    set pkgua_loaded {}
    set pkgua_detached {}
    set pkgua_unloaded {}
}
test unload-3.1 {basic loading of non-unloadable package in a safe interpreter, with package name conversion} \
test unload-3.1 {basic loading of non-unloadable package in a safe interpreter} \
	[list $dll $loaded] {
    catch {rename pkgb_sub {}}
    load [file join $testDir pkgb$ext] pKgB child
    load [file join $testDir tcl9pkgb$ext] Pkgb child
    list [child eval pkgb_sub 44 13] [catch {child eval pkgb_unsafe} msg] $msg \
         [catch {pkgb_sub 12 10} msg2] $msg2
	 [catch {pkgb_sub 12 10} msg2] $msg2
} {31 1 {invalid command name "pkgb_unsafe"} 1 {invalid command name "pkgb_sub"}}
test unload-3.2 {basic loading of unloadable package in a safe interpreter, with package name conversion} \
test unload-3.2 {basic loading of unloadable package in a safe interpreter} \
	[list $dll $loaded] {
    list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [load [file join $testDir pkgua$ext] pKgUA child] \
	    [load [file join $testDir tcl9pkgua$ext] Pkgua child] \
	    [child eval pkgua_eq abc def] \
	    [lsort [child eval info commands pkgua_*]] \
	    [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
} {{{} {} {}} {} 0 {pkgua_eq pkgua_quote} {. {} {}}}
test unload-3.3 {unloading of a package that has never been loaded from a safe interpreter} -setup {
    loadIfNotPresent pkga
} -constraints [list $dll $loaded] -returnCodes error -match glob -body {
    unload [file join $testDir pkga$ext] {} child
    unload [file join $testDir tcl9pkga$ext] {} child
} -result {file "*" has never been loaded in this interpreter}
test unload-3.4 {basic unloading of a non-unloadable package from a safe interpreter, with guess for package name} -setup {
test unload-3.4 {basic unloading of a non-unloadable package from a safe interpreter, with guess for prefix} -setup {
    if {[lsearch -index 1 [info loaded child] Pkgb] < 0} {
	load [file join $testDir pkgb$ext] pKgB child
	load [file join $testDir tcl9pkgb$ext] Pkgb child
    }
} -constraints [list $dll $loaded] -returnCodes error -match glob -body {
    unload [file join $testDir pkgb$ext] {} child
    unload [file join $testDir tcl9pkgb$ext] {} child
} -result {file "*" cannot be unloaded under a safe interpreter}
test unload-3.5 {basic unloading of an unloadable package from a safe interpreter, with guess for package name} -setup {
test unload-3.5 {basic unloading of an unloadable package from a safe interpreter, with guess for prefix} -setup {
    if {[lsearch -index 1 [info loaded child] Pkgua] < 0} {
	load [file join $testDir pkgua$ext] pkgua child
	load [file join $testDir tcl9pkgua$ext] Pkgua child
    }
} -constraints [list $dll $loaded] -body {
    list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [unload [file join $testDir pkgua$ext] {} child] \
	    [unload [file join $testDir tcl9pkgua$ext] {} child] \
	    [child eval info commands pkgua_*] \
	    [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
} -result {{. {} {}} {} {} {. . .}}
test unload-3.6 {reloading of unloaded package in a safe interpreter, with guess for package name} -setup {
test unload-3.6 {reloading of unloaded package in a safe interpreter, with guess for prefix} -setup {
    if {[child eval set pkgua_loaded] eq ""} {
	load [file join $testDir pkgua$ext] {} child
	unload [file join $testDir pkgua$ext] {} child
	load [file join $testDir tcl9pkgua$ext] {} child
	unload [file join $testDir tcl9pkgua$ext] {} child
    }
} -constraints [list $dll $loaded] -body {
    list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [load [file join $testDir pkgua$ext] {} child] \
	    [load [file join $testDir tcl9pkgua$ext] {} child] \
	    [child eval pkgua_eq abc def] \
	    [lsort [child eval info commands pkgua_*]] \
	    [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
} -result {{. . .} {} 0 {pkgua_eq pkgua_quote} {.. . .}}
test unload-3.7 {basic unloading of re-loaded package from a safe interpreter, with package name conversion} -setup {
test unload-3.7 {basic unloading of re-loaded package from a safe interpreter, with prefix conversion} -setup {
    if {[child eval set pkgua_loaded] eq ""} {
	load [file join $testDir pkgua$ext] {} child
	unload [file join $testDir pkgua$ext] {} child
	load [file join $testDir pkgua$ext] {} child
	load [file join $testDir tcl9pkgua$ext] {} child
	unload [file join $testDir tcl9pkgua$ext] {} child
	load [file join $testDir tcl9pkgua$ext] {} child
    }
} -constraints [list $dll $loaded] -body {
    list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [unload [file join $testDir pkgua$ext] pKgUa child] \
	    [unload [file join $testDir tcl9pkgua$ext] Pkgua child] \
	    [child eval info commands pkgua_*] \
	    [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
} -result {{.. . .} {} {} {.. .. ..}}

# Tests for loading/unloading of a package among multiple interpreters...
interp create child-trusted
child-trusted eval {
    set pkgua_loaded {}
    set pkgua_detached {}
    set pkgua_unloaded {}
}
array set load {M 0 C 0 T 0}
## Load package in main trusted interpreter...
test unload-4.1 {loading of unloadable package in trusted interpreter, with guess for package name} -setup {
test unload-4.1 {loading of unloadable package in trusted interpreter, with guess for prefix} -setup {
    set pkgua_loaded ""
    set pkgua_detached ""
    set pkgua_unloaded ""
    incr load(M)
} -constraints [list $dll $loaded] -body {
    list [list $pkgua_loaded $pkgua_detached $pkgua_unloaded] \
	    [load [file join $testDir pkgua$ext]] \
	    [load [file join $testDir tcl9pkgua$ext]] \
	    [pkgua_eq abc def] [lsort [info commands pkgua_*]] \
	    [list $pkgua_loaded $pkgua_detached $pkgua_unloaded]
} -result {{{} {} {}} {} 0 {pkgua_eq pkgua_quote} {. {} {}}}
## Load package in child-safe interpreter...
test unload-4.2 {basic loading of unloadable package in a safe interpreter, with package name conversion} -setup {
test unload-4.2 {basic loading of unloadable package in a safe interpreter} -setup {
    child eval {
	set pkgua_loaded ""
	set pkgua_detached ""
	set pkgua_unloaded ""
    }
    incr load(C)
} -constraints [list $dll $loaded] -body {
    list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [load [file join $testDir pkgua$ext] pKgUA child] \
	    [load [file join $testDir tcl9pkgua$ext] Pkgua child] \
	    [child eval pkgua_eq abc def] \
	    [lsort [child eval info commands pkgua_*]] \
	    [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
} -result {{{} {} {}} {} 0 {pkgua_eq pkgua_quote} {. {} {}}}
## Load package in child-trusted interpreter...
test unload-4.3 {basic loading of unloadable package in a second trusted interpreter, with package name conversion} -setup {
test unload-4.3 {basic loading of unloadable package in a second trusted interpreter} -setup {
    incr load(T)
} -constraints [list $dll $loaded] -body {
    list [child-trusted eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [load [file join $testDir pkgua$ext] pkguA child-trusted] \
	    [load [file join $testDir tcl9pkgua$ext] Pkgua child-trusted] \
	    [child-trusted eval pkgua_eq abc def] \
	    [lsort [child-trusted eval info commands pkgua_*]] \
	    [child-trusted eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
} -result {{{} {} {}} {} 0 {pkgua_eq pkgua_quote} {. {} {}}}
## Unload the package from the main trusted interpreter...
test unload-4.4 {basic unloading of unloadable package from trusted interpreter, with guess for package name} -setup {
test unload-4.4 {basic unloading of unloadable package from trusted interpreter, with guess for prefix} -setup {
    if {!$load(M)} {
	load [file join $testDir pkgua$ext]
	load [file join $testDir tcl9pkgua$ext]
    }
    if {!$load(C)} {
	load [file join $testDir pkgua$ext] {} child
	load [file join $testDir tcl9pkgua$ext] {} child
	incr load(C)
    }
    if {!$load(T)} {
	load [file join $testDir pkgua$ext] {} child-trusted
	load [file join $testDir tcl9pkgua$ext] {} child-trusted
	incr load(T)
    }
} -constraints [list $dll $loaded] -body {
    list [list $pkgua_loaded $pkgua_detached $pkgua_unloaded] \
	    [unload [file join $testDir pkgua$ext]] \
	    [unload [file join $testDir tcl9pkgua$ext]] \
	    [info commands pkgua_*] \
	    [list $pkgua_loaded $pkgua_detached $pkgua_unloaded]
} -result {{. {} {}} {} {} {. . {}}}
## Unload the package from the child safe interpreter...
test unload-4.5 {basic unloading of unloadable package from a safe interpreter, with guess for package name} -setup {
test unload-4.5 {basic unloading of unloadable package from a safe interpreter, with guess for prefix} -setup {
    if {!$load(C)} {
	load [file join $testDir pkgua$ext] {} child
	load [file join $testDir tcl9pkgua$ext] {} child
    }
    if {!$load(T)} {
	load [file join $testDir pkgua$ext] {} child-trusted
	load [file join $testDir tcl9pkgua$ext] {} child-trusted
	incr load(T)
    }
} -constraints [list $dll $loaded] -body {
    list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [unload [file join $testDir pkgua$ext] {} child] \
	    [unload [file join $testDir tcl9pkgua$ext] {} child] \
	    [child eval info commands pkgua_*] \
	    [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
} -result {{. {} {}} {} {} {. . {}}}
## Unload the package from the child trusted interpreter...
test unload-4.6 {basic unloading of unloadable package from a safe interpreter, with guess for package name} -setup {
test unload-4.6 {basic unloading of unloadable package from a safe interpreter, with guess for prefix} -setup {
    if {!$load(T)} {
	load [file join $testDir pkgua$ext] {} child-trusted
	load [file join $testDir tcl9pkgua$ext] {} child-trusted
    }
} -constraints [list $dll $loaded] -body {
    list [child-trusted eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [unload [file join $testDir pkgua$ext] {} child-trusted] \
	    [unload [file join $testDir tcl9pkgua$ext] {} child-trusted] \
	    [child-trusted eval info commands pkgua_*] \
	    [child-trusted eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
} -result {{. {} {}} {} {} {. . .}}

test unload-5.1 {unload a module loaded from vfs} \
     -constraints [list $dll $loaded testsimplefilesystem] \
     -setup {
	 set dir [pwd]
	 cd $testDir
	 testsimplefilesystem 1
	 load simplefs:/pkgua$ext pkgua
	 load simplefs:/tcl9pkgua$ext Pkgua
     } \
    -body {
	list [catch {unload simplefs:/pkgua$ext} msg] $msg
	list [catch {unload simplefs:/tcl9pkgua$ext} msg] $msg
    } \
    -result {0 {}}

# cleanup
interp delete child
interp delete child-trusted
unset ext

Changes to tests/uplevel.test.

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
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






-
-
-
+
+
+










-
+







# Commands covered:  uplevel
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands.  Sourcing this file into Tcl runs the tests and generates output
# for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
}

proc a {x y} {
    newset z [expr $x+$y]
    newset z [expr {$x + $y}]
    return $z
}
proc newset {name value} {
    uplevel set $name $value
    uplevel 1 {uplevel 1 {set xyz 22}}
}


Changes to tests/upvar.test.

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
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






-
-
-
+
+
+










-
+







# Commands covered:  'upvar', 'namespace upvar'
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testupvar [llength [info commands testupvar]]

test upvar-1.1 {reading variables with upvar} {
    proc p1 {a b} {set c 22; set d 33; p2}
    proc p2 {} {upvar a x1 b x2 c x3 d x4; set a abc; list $x1 $x2 $x3 $x4 $a}
    p1 foo bar
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
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







-
+




-
+

-
+




-
+

-
+




-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	set b bar
    }
    list [p1 14 15] $x1
} {{14 15 bar 33} foo}

proc tproc {args} {global x; set x [list $args [uplevel info vars]]}
test upvar-5.1 {traces involving upvars} {
    proc p1 {a b} {set c 22; set d 33; trace var c rw tproc; p2}
    proc p1 {a b} {set c 22; set d 33; trace add var c {read write} tproc; p2}
    proc p2 {} {upvar c x1; set x1 22}
    set x ---
    p1 foo bar
    set x
} {{x1 {} w} x1}
} {{x1 {} write} x1}
test upvar-5.2 {traces involving upvars} {
    proc p1 {a b} {set c 22; set d 33; trace var c rw tproc; p2}
    proc p1 {a b} {set c 22; set d 33; trace add var c {read write} tproc; p2}
    proc p2 {} {upvar c x1; set x1}
    set x ---
    p1 foo bar
    set x
} {{x1 {} r} x1}
} {{x1 {} read} x1}
test upvar-5.3 {traces involving upvars} {
    proc p1 {a b} {set c 22; set d 33; trace var c rwu tproc; p2}
    proc p1 {a b} {set c 22; set d 33; trace add var c {read write unset} tproc; p2}
    proc p2 {} {upvar c x1; unset x1}
    set x ---
    p1 foo bar
    set x
} {{x1 {} u} x1}
} {{x1 {} unset} x1}
test upvar-5.4 {read trace on upvar array element} -body {
    proc p1 {a b} {
	array set foo {c 22 d 33}
	trace add variable foo {read write unset} tproc
	p2
	trace remove variable foo {read write unset} tproc
    }
    proc p2 {} {
	upvar foo(c) x1
	set x1
    }
    set x ---
    p1 foo bar
    set x
} -result {{x1 c read} x1}
test upvar-5.5 {write trace on upvar array element} -body {
    proc p1 {a b} {
	array set foo {c 22 d 33}
	trace add variable foo {read write unset} tproc
	p2
	trace remove variable foo {read write unset} tproc
    }
    proc p2 {} {
	upvar foo(c) x1
	set x1 22
    }
    set x ---
    p1 foo bar
    set x
} -result {{x1 c write} x1}
test upvar-5.6 {unset trace on upvar array element} -body {
    proc p1 {a b} {
	array set foo {c 22 d 33}
	trace add variable foo {read write unset} tproc
	p2
	trace remove variable foo {read write unset} tproc
    }
    proc p2 {} {
	upvar foo(c) x1
	unset x1
    }
    set x ---
    p1 foo bar
    set x
} -result {{x1 c unset} x1}
test upvar-5.7 {trace on non-existent upvar array element} -body {
    proc p1 {a b} {
	array set foo {}
	trace add variable foo {read write unset} tproc
	p2
	trace remove variable foo {read write unset} tproc
	return [array get foo]
    }
    proc p2 {} {
	upvar foo(hi) x1
	set x1 there
    }
    set x ---
    lappend x [p1 foo bar]
    set x
} -result {{x1 hi write} x1 {hi there}}

test upvar-6.1 {retargeting an upvar} {
    proc p1 {} {
	set a(0) zeroth
	set a(1) first
	set a(2) second
	p2
244
245
246
247
248
249
250



























251
252
253
254
255
256
257
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	upvar y x
	lappend result $x
	global x
	lappend result $x
    }
    p1
} {abcde 44}



test upvar-6.4 {
	retargeting a variable created by upvar to itself is allowed
} -body {
	catch {
		unset x
	}
	catch {
		unset y
	}
	set res {}
    set x abcde
	set res [catch {
		upvar 0 x x
	} cres copts]
	lappend res [dict get $copts -errorcode]
	upvar 0 x y
	lappend res $y
	upvar 0 y y
	lappend res $y
	return $res
} -cleanup {
	upvar 0 {} y
} -result {1 {TCL UPVAR SELF} abcde abcde}


test upvar-7.1 {upvar to same level} {
    set x 44
    set y 55
    catch {unset uv}
    upvar #0 x uv
    set uv abc
324
325
326
327
328
329
330
331

332
333
334
335
336
337
338
412
413
414
415
416
417
418

419
420
421
422
423
424
425
426







-
+







    p1
} -result {can't upvar from variable to itself}
test upvar-8.6 {errors in upvar command} -returnCodes error -body {
    proc p1 {} {set a 33; upvar b a}
    p1
} -result {variable "a" already exists}
test upvar-8.7 {errors in upvar command} -returnCodes error -body {
    proc p1 {} {trace variable a w foo; upvar b a}
    proc p1 {} {trace add variable a write foo; upvar b a}
    p1
} -result {variable "a" has traces: can't use for upvar}
test upvar-8.8 {create nested array with upvar} -body {
    proc p1 {} {upvar x(a) b; set b(2) 44}
    catch {unset x}
    p1
} -returnCodes error -cleanup {
429
430
431
432
433
434
435
436
437


438
439
440
441
442
443
444
517
518
519
520
521
522
523


524
525
526
527
528
529
530
531
532







-
-
+
+







} {1234}
catch {unset a}

test upvar-10.1 {CompileWord OBOE} -setup {
    proc linenumber {} {dict get [info frame -1] line}
} -body {
    apply {n {
        upvar 1 {*}{
        } [return [incr n -[linenumber]]] x
	upvar 1 {*}{
	} [return [incr n -[linenumber]]] x
    }} [linenumber]
} -cleanup {
    rename linenumber {}
} -result 1

#
# Tests for 'namespace upvar'. As the implementation is essentially the same as
563
564
565
566
567
568
569
570
571


572
573
574
575
576
577
578
579
580
581


582
583
584
585
586
587
588
589
590
591


592
593
594
595
596
597
598
599
600
601
602
603
651
652
653
654
655
656
657


658
659
660
661
662
663
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







-
-
+
+








-
-
+
+








-
-
+
+












    namespace delete test_ns_1
} -result {}

test upvar-NS-3.1 {CompileWord OBOE} -setup {
    proc linenumber {} {dict get [info frame -1] line}
} -body {
    apply {n {
        namespace upvar {*}{
        } [return [incr n -[linenumber]]] x y
	namespace upvar {*}{
	} [return [incr n -[linenumber]]] x y
    }} [linenumber]
} -cleanup {
    rename linenumber {}
} -result 1
test upvar-NS-3.2 {CompileWord OBOE} -setup {
    proc linenumber {} {dict get [info frame -1] line}
} -body {
    apply {n {
        namespace upvar :: {*}{
        } [return [incr n -[linenumber]]] x
	namespace upvar :: {*}{
	} [return [incr n -[linenumber]]] x
    }} [linenumber]
} -cleanup {
    rename linenumber {}
} -result 1
test upvar-NS-3.3 {CompileWord OBOE} -setup {
    proc linenumber {} {dict get [info frame -1] line}
} -body {
    apply {n {
        variable x {*}{
        } [return [incr n -[linenumber]]]
	variable x {*}{
	} [return [incr n -[linenumber]]]
    }} [linenumber]
} -cleanup {
    rename linenumber {}
} -result 1

# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/utf.test.

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
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
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
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




-
-
+
+










-
+
-
-
-
-
-
-
-
-
-
-
-
-








+















-
+







-
+


-
-
-












-
-
+
+

-
-
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







# This file contains a collection of tests for tclUtf.c
# Sourcing this file into Tcl runs the tests and generates output for
# errors.  No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint ucs2 [expr {[format %c 0x010000] eq "\uFFFD"}]
testConstraint fullutf [expr {[format %c 0x010000] ne "\uFFFD"}]
testConstraint utf16 [expr {[string length [format %c 0x10000]] == 2}]
testConstraint ucs4 [expr {[testConstraint fullutf]
		&& [string length [format %c 0x10000]] == 1}]
testConstraint ucs2_utf16 [expr {![testConstraint ucs4]}]

testConstraint Uesc [expr {"\U0041" eq "A"}]
testConstraint pre388 [expr {"\x741" eq "A"}]
testConstraint pairsTo4bytes [expr {[llength [info commands teststringbytes]]
		&& [string length [teststringbytes \uD83D\uDCA9]] == 4}]

testConstraint testbytestring [llength [info commands testbytestring]]
testConstraint testfindfirst [llength [info commands testfindfirst]]
testConstraint testfindlast [llength [info commands testfindlast]]
testConstraint testnumutfchars [llength [info commands testnumutfchars]]
testConstraint teststringobj [llength [info commands teststringobj]]
testConstraint testutfnext [llength [info commands testutfnext]]
testConstraint testutfprev [llength [info commands testutfprev]]
testConstraint testgetunichar [llength [info commands testgetunichar]]

testConstraint tip413 [expr {[string trim \x00] eq {}}]

catch {unset x}

test utf-1.1 {Tcl_UniCharToUtf: 1 byte sequences} testbytestring {
    expr {"\x01" eq [testbytestring \x01]}
} 1
test utf-1.2 {Tcl_UniCharToUtf: 2 byte sequences} testbytestring {
    expr {"\x00" eq [testbytestring \xC0\x80]}
} 1
test utf-1.3 {Tcl_UniCharToUtf: 2 byte sequences} testbytestring {
    expr {"\xE0" eq [testbytestring \xC3\xA0]}
} 1
test utf-1.4 {Tcl_UniCharToUtf: 3 byte sequences} testbytestring {
    expr {"\u4E4E" eq [testbytestring \xE4\xB9\x8E]}
    expr {"乎" eq [testbytestring \xE4\xB9\x8E]}
} 1
test utf-1.5 {Tcl_UniCharToUtf: overflowed Tcl_UniChar} testbytestring {
    expr {[format %c 0x110000] eq [testbytestring \xEF\xBF\xBD]}
} 1
test utf-1.6 {Tcl_UniCharToUtf: negative Tcl_UniChar} testbytestring {
    expr {[format %c -1] eq [testbytestring \xEF\xBF\xBD]}
} 1
test utf-1.7.0 {Tcl_UniCharToUtf: 4 byte sequences} {fullutf Uesc testbytestring} {
test utf-1.7 {Tcl_UniCharToUtf: 4 byte sequences} testbytestring {
    expr {"\U014E4E" eq [testbytestring \xF0\x94\xB9\x8E]}
} 1
test utf-1.7.1 {Tcl_UniCharToUtf: 4 byte sequences} {ucs2 Uesc testbytestring} {
    expr {"\U014E4E" eq [testbytestring \xF0\x94\xB9\x8E]}
} 0
test utf-1.8 {Tcl_UniCharToUtf: 3 byte sequence, high surrogate} testbytestring {
    expr {"\uD842" eq [testbytestring \xED\xA1\x82]}
} 1
test utf-1.9 {Tcl_UniCharToUtf: 3 byte sequence, low surrogate} testbytestring {
    expr {"\uDC42" eq [testbytestring \xED\xB1\x82]}
} 1
test utf-1.10 {Tcl_UniCharToUtf: 3 byte sequence, high surrogate} testbytestring {
    expr {[format %c 0xD842] eq [testbytestring \xED\xA1\x82]}
} 1
test utf-1.11 {Tcl_UniCharToUtf: 3 byte sequence, low surrogate} testbytestring {
    expr {[format %c 0xDC42] eq [testbytestring \xED\xB1\x82]}
} 1
test utf-1.12 {Tcl_UniCharToUtf: 4 byte sequence, high/low surrogate} {pairsTo4bytes testbytestring} {
    expr {"\uD842\uDC42" eq [testbytestring \xF0\xA0\xA1\x82]}
test utf-1.12 {Tcl_UniCharToUtf: Invalid surrogate} testbytestring {
    expr {"\UD842" eq [testbytestring \xED\xA1\x82]}
} 1
test utf-1.13 {Tcl_UniCharToUtf: Invalid surrogate} {Uesc testbytestring} {
    expr {"\UD842" eq [testbytestring \xEF\xBF\xBD]}
test utf-1.13 {Tcl_UniCharToUtf: Invalid surrogate} {
    expr {"\UD842" eq "\uD842"}
} 1
test utf-1.14 {Tcl_UniCharToUtf: surrogate pairs from concat} {
    set lo \uDE02
    return \uD83D$lo
} \uD83D\uDE02
test utf-1.15 {Tcl_UniCharToUtf: surrogate pairs from concat} {
    set hi \uD83D
    return $hi\uDE02
} \uD83D\uDE02
test utf-1.16 {Tcl_UniCharToUtf: \xC0 + \x80} testbytestring {
    set lo [testbytestring \x80]
    string length [testbytestring \xC0]$lo
} 2
test utf-1.17 {Tcl_UniCharToUtf: \xC0 + \x80} testbytestring {
    set hi [testbytestring \xC0]
    string length $hi[testbytestring \x80]
} 2
test utf-1.18 {Tcl_UniCharToUtf: surrogate pairs from concat} {
    string cat \uD83D \uDE02
} \uD83D\uDE02

test utf-2.1 {Tcl_UtfToUniChar: low ascii} {
    string length "abc"
} 3
test utf-2.2 {Tcl_UtfToUniChar: naked trail bytes} testbytestring {
    string length [testbytestring \x82\x83\x84]
} 3
100
101
102
103
104
105
106
107
108
109
110
111


112
113
114
115
116

117
118
119
120
121
122
123
105
106
107
108
109
110
111





112
113
114




115
116
117
118
119
120
121
122







-
-
-
-
-
+
+

-
-
-
-
+







} 1
test utf-2.6 {Tcl_UtfToUniChar: lead (3-byte) followed by 1 trail} testbytestring {
    string length [testbytestring \xE2\xA2]
} 2
test utf-2.7 {Tcl_UtfToUniChar: lead (3-byte) followed by 2 trail} testbytestring {
    string length [testbytestring \xE4\xB9\x8E]
} 1
test utf-2.8.0 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} {testbytestring ucs2_utf16} {
    string length [testbytestring \xF0\x90\x80\x80]
} 2
test utf-2.8.1 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} {testbytestring ucs4} {
    string length [testbytestring \xF0\x90\x80\x80]
test utf-2.8 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} {
    string length ð€€
} 1
test utf-2.9.0 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} {testbytestring ucs2} {
    string length [testbytestring \xF4\x8F\xBF\xBF]
} 2
test utf-2.9.1 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} {Uesc ucs4} {
test utf-2.9 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} {
    string length \U10FFFF
} 1
test utf-2.10 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail, underflow} testbytestring {
    string length [testbytestring \xF0\x8F\xBF\xBF]
} 4
test utf-2.11 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail, overflow} testbytestring {
    # Would decode to U+110000 but that is outside the Unicode range.
160
161
162
163
164
165
166
167

168
169
170
171
172
173
174
175
176
177
159
160
161
162
163
164
165

166



167
168
169
170
171
172
173







-
+
-
-
-







} 2
test utf-4.10 {Tcl_NumUtfChars: #x00, calc len, overcomplete} {testnumutfchars testbytestring} {
    testnumutfchars [testbytestring \x00] end+1
} 2
test utf-4.11 {Tcl_NumUtfChars: 3 bytes of 4-byte UTF-8 characater} {testnumutfchars testbytestring} {
    testnumutfchars [testbytestring \xF0\x9F\x92\xA9] end-1
} 3
test utf-4.12.0 {Tcl_NumUtfChars: #4-byte UTF-8 character} {testnumutfchars testbytestring ucs2} {
test utf-4.12 {Tcl_NumUtfChars: #4-byte UTF-8 character} {testnumutfchars testbytestring} {
    testnumutfchars [testbytestring \xF0\x9F\x92\xA9] end
} 2
test utf-4.12.1 {Tcl_NumUtfChars: #4-byte UTF-8 character} {testnumutfchars testbytestring ucs4} {
    testnumutfchars [testbytestring \xF0\x9F\x92\xA9] end
} 1
test utf-4.13 {Tcl_NumUtfChars: end of string} {testnumutfchars testbytestring} {
    testnumutfchars foobar[testbytestring \xF2\xC2\xA0] end
} 8
test utf-4.14 {Tcl_NumUtfChars: 3 bytes of 4-byte UTF-8 characater} {testnumutfchars testbytestring} {
    testnumutfchars [testbytestring \xF4\x90\x80\x80] end-1
192
193
194
195
196
197
198
199

200
201
202
203
204
205
206
188
189
190
191
192
193
194

195
196
197
198
199
200
201
202







-
+







test utf-6.2 {Tcl_UtfNext} testutfnext {
    testutfnext A
} 1
test utf-6.3 {Tcl_UtfNext} testutfnext {
    testutfnext AA
} 1
test utf-6.4 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext A[testbytestring \xA0]
    testutfnext [testbytestring A\xA0]
} 1
test utf-6.5 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext A[testbytestring \xD0]
} 1
test utf-6.6 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext A[testbytestring \xE8]
} 1
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
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







-
-
+
+


















-
-
+
+

-
-
-



-
-
+
+

-
-
-







test utf-6.21 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0\xF2]
} 1
test utf-6.22 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0\xF8]
} 1
test utf-6.23 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8]
} -1
    testutfnext [testbytestring \xE8\x00]
} 1
test utf-6.24 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8]G
} 1
test utf-6.25 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xA0\x00]
} 1
test utf-6.26 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xD0]
} 1
test utf-6.27 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xE8]
} 1
test utf-6.28 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xF2]
} 1
test utf-6.29 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xF8]
} 1
test utf-6.30.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2_utf16} {
    testutfnext [testbytestring \xF2]
test utf-6.30 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\x00]
} 1
test utf-6.30.1 {Tcl_UtfNext} {testutfnext testbytestring ucs4} {
    testutfnext [testbytestring \xF2]
} -1
test utf-6.31 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2]G
} 1
test utf-6.32.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2_utf16} {
    testutfnext [testbytestring \xF2\xA0]
test utf-6.32 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\x00]
} 1
test utf-6.32.1 {Tcl_UtfNext} {testutfnext testbytestring ucs4} {
    testutfnext [testbytestring \xF2\xA0]
} -1
test utf-6.33 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xD0]
} 1
test utf-6.34 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xE8]
} 1
test utf-6.35 {Tcl_UtfNext} {testutfnext testbytestring} {
339
340
341
342
343
344
345
346

347
348
349
350
351
352
353
329
330
331
332
333
334
335

336
337
338
339
340
341
342
343







-
+







test utf-6.49 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0\xA0\xF8]
} 2
test utf-6.50 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xA0]G
} 1
test utf-6.51 {Tcl_UtfNext} testutfnext {
    testutfnext \u8820
    testutfnext è  
} 3
test utf-6.52 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xA0\xD0]
} 1
test utf-6.53 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xA0\xE8]
} 1
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
442
443
444

445
446
447
448
449
450

451
452
453
454
455
456
457
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







-
+


-
+


-
+


-
+


-
+


-
+




-
-
-
-
+














-
-
-
-
+


-
-
-
-
+


-
-
-
-
+


-
-
-
-
+


-
-
-
-
+


-
-
-
-
+







test utf-6.60 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xF2]
} 1
test utf-6.61 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xF8]
} 1
test utf-6.62 {Tcl_UtfNext} testutfnext {
    testutfnext \u8820G
    testutfnext è  G
} 3
test utf-6.63 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext \u8820[testbytestring \xA0]
    testutfnext [testbytestring \xE8\xA0\xA0\xA0]
} 3
test utf-6.64 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext \u8820[testbytestring \xD0]
    testutfnext è  [testbytestring \xD0]
} 3
test utf-6.65 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext \u8820[testbytestring \xE8]
    testutfnext è  [testbytestring \xE8]
} 3
test utf-6.66 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext \u8820[testbytestring \xF2]
    testutfnext è  [testbytestring \xF2]
} 3
test utf-6.67 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext \u8820[testbytestring \xF8]
    testutfnext è  [testbytestring \xF8]
} 3
test utf-6.68 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0]G
} 1
test utf-6.69.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2_utf16} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0]
} 1
test utf-6.69.1 {Tcl_UtfNext} {testutfnext testbytestring ucs4} {
test utf-6.69 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0]
} 4
test utf-6.70 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xD0]
} 1
test utf-6.71 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xE8]
} 1
test utf-6.72 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xF2]
} 1
test utf-6.73 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xF8]
} 1
test utf-6.74.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2_utf16} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0]G
} 1
test utf-6.74.1 {Tcl_UtfNext} {testutfnext testbytestring ucs4} {
test utf-6.74 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0]G
} 4
test utf-6.75.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2_utf16} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xA0]
} 1
test utf-6.75.1 {Tcl_UtfNext} {testutfnext testbytestring ucs4} {
test utf-6.75 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xA0]
} 4
test utf-6.76.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2_utf16} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xD0]
} 1
test utf-6.76.1 {Tcl_UtfNext} {testutfnext testbytestring ucs4} {
test utf-6.76 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xD0]
} 4
test utf-6.77.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2_utf16} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xE8]
} 1
test utf-6.77.1 {Tcl_UtfNext} {testutfnext testbytestring ucs4} {
test utf-6.77 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xE8]
} 4
test utf-6.78.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2_utf16} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xF2]
} 1
test utf-6.78.1 {Tcl_UtfNext} {testutfnext testbytestring ucs4} {
test utf-6.78 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xF2]
} 4
test utf-6.79.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2_utf16} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0G\xF8]
} 1
test utf-6.79.1 {Tcl_UtfNext} {testutfnext testbytestring ucs4} {
test utf-6.79 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0G\xF8]
} 4
test utf-6.80 {Tcl_UtfNext - overlong sequences} testutfnext {
    testutfnext \x00
} 2
test utf-6.81 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring} {
    testutfnext [testbytestring \xC0\x81]
467
468
469
470
471
472
473
474
475
476
477

478
479
480
481
482
483
484
485
486

487
488
489
490
491
492
493
494
495
496
436
437
438
439
440
441
442




443
444
445
446
447
448
449
450
451

452



453
454
455
456
457
458
459







-
-
-
-
+








-
+
-
-
-







} 1
test utf-6.85 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE0\xA0\x80]
} 3
test utf-6.86 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF0\x80\x80\x80]
} 1
test utf-6.87.0 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring ucs2_utf16} {
    testutfnext [testbytestring \xF0\x90\x80\x80]
} 1
test utf-6.87.1 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring ucs4} {
test utf-6.87 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF0\x90\x80\x80]
} 4
test utf-6.88 {Tcl_UtfNext, pointing to 2th byte of 3-byte valid sequence} {testutfnext testbytestring} {
    testutfnext [testbytestring \xA0\xA0\x00]
} 2
test utf-6.89 {Tcl_UtfNext, pointing to 2th byte of 3-byte invalid sequence} {testutfnext testbytestring} {
    testutfnext [testbytestring \x80\x80\x00]
} 2
test utf-6.90.0 {Tcl_UtfNext, validity check [493dccc2de]} {testutfnext testbytestring ucs2_utf16} {
test utf-6.90 {Tcl_UtfNext, validity check [493dccc2de]} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF4\x8F\xBF\xBF]
} 1
test utf-6.90.1 {Tcl_UtfNext, validity check [493dccc2de]} {testutfnext testbytestring ucs4} {
    testutfnext [testbytestring \xF4\x8F\xBF\xBF]
} 4
test utf-6.91 {Tcl_UtfNext, validity check [493dccc2de]} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF4\x90\x80\x80]
} 1
test utf-6.92 {Tcl_UtfNext, pointing to 2th byte of 4-byte valid sequence} {testutfnext testbytestring} {
    testutfnext [testbytestring \xA0\xA0\xA0]
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

558
559
560

561
562
563
564
565
566
567
568
569
570
571

572
573
574
575



576
577

578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593

594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611

612
613
614

615
616
617

618
619
620
621
622
623
624
625
626
627
628

629
630
631
632



633
634

635
636
637
638
639
640
641
642
643
644
645
646
647

648
649
650

651
652
653

654
655
656
657
658
659
660
661
662
663
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
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
558
559
560
561
562
563
564

565
566
567

568
569
570

571
572
573
574
575
576
577
578
579
580
581

582
583



584
585
586
587

588






589



590
591

592
593
594

595
596
597

598
599
600
601
602
603
604
605
606
607
608



















609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628




629
630
631
632
633
634
635
636
637
638
639







-
+














-
+


-
+


-
+










-
+

-
-
-
+
+
+

-
+
-
-
-
-
-
-
-
-
-






-
+

















-
+


-
+


-
+










-
+

-
-
-
+
+
+

-
+
-
-
-
-
-
-

-
-
-


-
+


-
+


-
+










-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+







test utf-7.5.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF2\xF8\xA0\xA0] 2
} 1
test utf-7.6 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE8]
} 1
test utf-7.6.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A\u8820[testbytestring \xA0] 2
    testutfprev A[testbytestring \xE8\xA0\xA0\xA0] 2
} 1
test utf-7.6.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE8\xF8\xA0\xA0] 2
} 1
test utf-7.7 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0]
} 1
test utf-7.7.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0\xA0\xA0\xA0] 2
} 1
test utf-7.7.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0\xF8\xA0\xA0] 2
} 1
test utf-7.8 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xA0]
    testutfprev [testbytestring A\xA0]
} 1
test utf-7.8.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xA0\xA0\xA0\xA0] 2
    testutfprev [testbytestring A\xA0\xA0\xA0\xA0] 2
} 1
test utf-7.8.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xA0\xF8\xA0\xA0] 2
    testutfprev [testbytestring A\xA0\xF8\xA0\xA0] 2
} 1
test utf-7.9 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF8\xA0]
} 2
test utf-7.9.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF8\xA0\xA0\xA0] 3
} 2
test utf-7.9.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF8\xA0\xF8\xA0] 3
} 2
test utf-7.10.0 {Tcl_UtfPrev} {testutfprev testbytestring ucs2} {
test utf-7.10 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF2\xA0]
} 2
test utf-7.10.1 {Tcl_UtfPrev} {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF2\xA0]
} 1
test utf-7.10.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF2\xA0\xA0\xA0] 3
} 1
test utf-7.10.2 {Tcl_UtfPrev} {testutfprev testbytestring ucs2} {
test utf-7.10.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF2\xA0\xA0\xA0] 3
} 2
test utf-7.10.3 {Tcl_UtfPrev} {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF2\xA0\xA0\xA0] 3
} 1
test utf-7.10.4 {Tcl_UtfPrev} {testutfprev testbytestring ucs2} {
    testutfprev A[testbytestring \xF2\xA0\xF8\xA0] 3
} 2
test utf-7.10.5 {Tcl_UtfPrev} {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF2\xA0\xF8\xA0] 3
} 1
test utf-7.11 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE8\xA0]
} 1
test utf-7.11.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A\u8820[testbytestring \xA0] 3
    testutfprev A[testbytestring \xE8\xA0\xA0\xA0] 3
} 1
test utf-7.11.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE8\xA0\xF8\xA0] 3
} 1
test utf-7.11.3 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE8\xA0\xF8] 3
} 1
test utf-7.12 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0\xA0]
} 1
test utf-7.12.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0\xA0\xA0\xA0] 3
} 1
test utf-7.12.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0\xA0\xF8\xA0] 3
} 1
test utf-7.13 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xA0\xA0]
    testutfprev [testbytestring A\xA0\xA0]
} 2
test utf-7.13.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xA0\xA0\xA0\xA0] 3
    testutfprev [testbytestring A\xA0\xA0\xA0\xA0] 3
} 2
test utf-7.13.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xA0\xA0\xF8\xA0] 3
    testutfprev [testbytestring A\xA0\xA0\xF8\xA0] 3
} 2
test utf-7.14 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF8\xA0\xA0]
} 3
test utf-7.14.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF8\xA0\xA0\xA0] 4
} 3
test utf-7.14.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF8\xA0\xA0\xF8] 4
} 3
test utf-7.15.0 {Tcl_UtfPrev} {testutfprev testbytestring ucs2} {
test utf-7.15 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF2\xA0\xA0]
} 3
test utf-7.15.1 {Tcl_UtfPrev} {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF2\xA0\xA0]
} 1
test utf-7.15.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF2\xA0\xA0\xA0] 4
} 1
test utf-7.15.2 {Tcl_UtfPrev} {testutfprev testbytestring ucs2} {
test utf-7.15.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF2\xA0\xA0\xA0] 4
} 3
test utf-7.15.3 {Tcl_UtfPrev} {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF2\xA0\xA0\xA0] 4
} 1
test utf-7.15.4 {Tcl_UtfPrev} {testutfprev testbytestring ucs2} {
    testutfprev A[testbytestring \xF2\xA0\xA0\xF8] 4
} 3
test utf-7.15.5 {Tcl_UtfPrev} {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF2\xA0\xA0\xF8] 4
} 1
test utf-7.16 {Tcl_UtfPrev} testutfprev {
    testutfprev A\u8820
    testutfprev Aè  
} 1
test utf-7.16.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A\u8820[testbytestring \xA0] 4
    testutfprev A[testbytestring \xE8\xA0\xA0\xA0] 4
} 1
test utf-7.16.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A\u8820[testbytestring \xF8] 4
    testutfprev Aè  [testbytestring \xF8] 4
} 1
test utf-7.17 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0\xA0\xA0]
} 3
test utf-7.17.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0\xA0\xA0\xA0] 4
} 3
test utf-7.17.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0\xA0\xA0\xF8] 4
} 3
test utf-7.18.0 {Tcl_UtfPrev} {testutfprev testbytestring utf16} {
    testutfprev A[testbytestring \xA0\xA0\xA0]
} 1
test utf-7.18.1 {Tcl_UtfPrev} {testutfprev testbytestring utf16} {
    testutfprev A[testbytestring \xA0\xA0\xA0\xA0] 4
} 1
test utf-7.18.2 {Tcl_UtfPrev} {testutfprev testbytestring utf16} {
    testutfprev A[testbytestring \xA0\xA0\xA0\xF8] 4
} 1
test utf-7.19 {Tcl_UtfPrev} {testutfprev testbytestring utf16} {
    testutfprev A[testbytestring \xF8\xA0\xA0\xA0]
} 2
test utf-7.20 {Tcl_UtfPrev} {testutfprev testbytestring utf16} {
    testutfprev A[testbytestring \xF2\xA0\xA0\xA0]
} 2
test utf-7.21 {Tcl_UtfPrev} {testutfprev testbytestring utf16} {
    testutfprev A\u8820[testbytestring \xA0]
} 2
test utf-7.22 {Tcl_UtfPrev} {testutfprev testbytestring utf16} {
test utf-7.18.0 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev [testbytestring A\xA0\xA0\xA0]
} 3
test utf-7.18.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev [testbytestring A\xA0\xA0\xA0\xA0] 4
} 3
test utf-7.18.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev [testbytestring A\xA0\xA0\xA0\xF8] 4
} 3
test utf-7.19 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev [testbytestring A\xF8\xA0\xA0\xA0]
} 4
test utf-7.20 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev [testbytestring A\xF2\xA0\xA0\xA0]
} 1
test utf-7.21 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE8\xA0\xA0\xA0]
} 4
test utf-7.22 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xD0\xA0\xA0\xA0]
} 2
test utf-7.23 {Tcl_UtfPrev} {testutfprev testbytestring utf16} {
    testutfprev A[testbytestring \xA0\xA0\xA0\xA0]
} 2
} 4
test utf-7.23 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev [testbytestring A\xA0\xA0\xA0\xA0]
} 4
test utf-7.24 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xC0\x81]
} 2
test utf-7.25 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xC0\x81] 2
} 1
test utf-7.26 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
702
703
704
705
706
707
708
709

710
711

712
713
714
715
716
717
718
647
648
649
650
651
652
653

654
655

656
657
658
659
660
661
662
663







-
+

-
+







} 2
test utf-7.28 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE0]
} 1
test utf-7.28.1 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE0\x80\x80] 2
} 1
test utf-7.29 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring utf16} {
test utf-7.29 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF0\x80\x80\x80]
} 2
} 4
test utf-7.30 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF0\x80\x80\x80] 4
} 3
test utf-7.31 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF0\x80\x80\x80] 3
} 2
test utf-7.32 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
732
733
734
735
736
737
738
739

740
741
742


743
744
745
746
747
748

749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766

767
768

769
770
771
772
773

774
775
776
777
778

779
780
781


782
783
784
785
786
787

788
789
790
791
792
793

794
795
796

797
798

799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814


815
816
817
818
819
820
821
822
823
824



825
826
827
828
829
830
831
832
833
834


835
836
837
838
839
840
841
842
843
844
845
846
847

848
849
850
851
852


853
854
855


856
857
858
859
860
861


862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908





909
910
911
912
913


914
915
916


917
918
919
920
921
922


923
924
925
926
927
928
929
930
931
932
933
934



935
936
937


938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965

966
967
968

969
970
971
972
973
974
975
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

707
708
709
710
711

712
713
714
715
716

717
718


719
720
721



722

723
724



725

726
727
728

729
730

731
732
733
734
735
736
737
738
739
740
741
742
743
744
745


746
747
748
749
750
751






752
753
754



755
756
757
758
759


760
761













762





763
764
765


766
767
768





769
770












771
772
773
774


775
776
777









778
779
780
781
782

















783
784
785
786
787





788
789
790


791
792
793





794
795












796
797
798
799


800
801
802









803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819

820
821
822

823
824
825
826
827
828
829
830







-
+

-
-
+
+

-
-
-

-
+
-
-
-














-
+

-
+




-
+




-
+

-
-
+
+

-
-
-

-
+

-
-
-

-
+


-
+

-
+














-
-
+
+




-
-
-
-
-
-
+
+
+
-
-
-





-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
+

-
-
+
+

-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+

-
-
+
+

-
-
-
-
-
-
-
-
-





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+

-
-
+
+

-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+

-
-
+
+

-
-
-
-
-
-
-
-
-

















-
+


-
+







} 1
test utf-7.37 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE0\xA0\x80] 3
} 1
test utf-7.38 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE0\xA0\x80] 2
} 1
test utf-7.39 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring utf16} {
test utf-7.39 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF0\x90\x80\x80]
} 2
test utf-7.40.0 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring ucs2} {
} 1
test utf-7.40 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF0\x90\x80\x80] 4
} 3
test utf-7.40.1 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF0\x90\x80\x80] 4
} 1
test utf-7.41.0 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring ucs2} {
test utf-7.41 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF0\x90\x80\x80] 3
} 2
test utf-7.41.1 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF0\x90\x80\x80] 3
} 1
test utf-7.42 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF0\x90\x80\x80] 2
} 1
test utf-7.43 {Tcl_UtfPrev -- no lead byte at start}  {testutfprev testbytestring} {
    testutfprev [testbytestring \xA0]
} 0
test utf-7.44 {Tcl_UtfPrev -- no lead byte at start}  {testutfprev testbytestring} {
    testutfprev [testbytestring \xA0\xA0]
} 1
test utf-7.45 {Tcl_UtfPrev -- no lead byte at start}  {testutfprev testbytestring} {
    testutfprev [testbytestring \xA0\xA0\xA0]
} 2
test utf-7.46 {Tcl_UtfPrev -- no lead byte at start}  {testutfprev testbytestring utf16} {
test utf-7.46 {Tcl_UtfPrev -- no lead byte at start}  {testutfprev testbytestring} {
    testutfprev [testbytestring \xA0\xA0\xA0\xA0]
} 1
} 3
test utf-7.47 {Tcl_UtfPrev, pointing to 3th byte of 3-byte valid sequence} {testutfprev testbytestring} {
    testutfprev [testbytestring \xE8\xA0]
} 0
test utf-7.47.1 {Tcl_UtfPrev, pointing to 3th byte of 3-byte valid sequence} testutfprev {
    testutfprev \u8820 2
    testutfprev è   2
} 0
test utf-7.47.2 {Tcl_UtfPrev, pointing to 3th byte of 3-byte invalid sequence} {testutfprev testbytestring} {
    testutfprev [testbytestring \xE8\xA0\x00] 2
} 0
test utf-7.48.0 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring utf16} {
test utf-7.48.0 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF4\x8F\xBF\xBF]
} 2
test utf-7.48.1 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring ucs2} {
} 1
test utf-7.48.1 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF4\x8F\xBF\xBF] 4
} 3
test utf-7.48.2 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF4\x8F\xBF\xBF] 4
} 1
test utf-7.48.3 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring ucs2} {
test utf-7.48.2 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF4\x8F\xBF\xBF] 3
} 2
test utf-7.48.4 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring fullutf} {
    testutfprev A[testbytestring \xF4\x8F\xBF\xBF] 3
} 1
test utf-7.48.5 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} {
test utf-7.48.3 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF4\x8F\xBF\xBF] 2
} 1
test utf-7.49.0 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring utf16} {
test utf-7.49.0 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF4\x90\x80\x80]
} 2
} 4
test utf-7.49.1 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF4\x90\x80\x80] 4
} 3
test utf-7.49.2 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF4\x90\x80\x80] 3
} 2
test utf-7.49.3 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF4\x90\x80\x80] 2
} 1

test utf-8.1 {Tcl_UniCharAtIndex: index = 0} {
    string index abcd 0
} a
test utf-8.2 {Tcl_UniCharAtIndex: index = 0} {
    string index \u4E4E\u25A 0
} \u4E4E
    string index 乎ɚ 0
} 乎
test utf-8.3 {Tcl_UniCharAtIndex: index > 0} {
    string index abcd 2
} c
test utf-8.4 {Tcl_UniCharAtIndex: index > 0} {
    string index \u4E4E\u25A\xFF\u543 2
} \xFF
test utf-8.5.0 {Tcl_UniCharAtIndex: high surrogate} ucs2 {
    string index \uD842 0
} \uD842
test utf-8.5.1 {Tcl_UniCharAtIndex: high surrogate} ucs4 {
    string index 乎ɚÿՃ 2
} ÿ
test utf-8.5 {Tcl_UniCharAtIndex: high surrogate} {
    string index \uD842 0
} \uD842
test utf-8.5.2 {Tcl_UniCharAtIndex: high surrogate} utf16 {
    string index \uD842 0
} \uD842
test utf-8.6 {Tcl_UniCharAtIndex: low surrogate} {
    string index \uDC42 0
} \uDC42
test utf-8.7.0 {Tcl_UniCharAtIndex: Emoji} ucs2 {
    string index \uD83D\uDE00G 0
test utf-8.7 {Tcl_UniCharAtIndex: Emoji} {
    string index 😀G 0
} \uD83D
test utf-8.7.1 {Tcl_UniCharAtIndex: Emoji} ucs4 {
    string index \uD83D\uDE00G 0
} \U1F600
test utf-8.7.2 {Tcl_UniCharAtIndex: Emoji} utf16 {
    string index \uD83D\uDE00G 0
} \U1F600
test utf-8.8.0 {Tcl_UniCharAtIndex: Emoji} ucs2 {
    string index \uD83D\uDE00G 1
} \uDE00
test utf-8.8.1 {Tcl_UniCharAtIndex: Emoji} ucs4 {
    string index \uD83D\uDE00G 1
} G
} 😀
test utf-8.8.2 {Tcl_UniCharAtIndex: Emoji} utf16 {
    string index \uD83D\uDE00G 1
} {}
test utf-8.9.0 {Tcl_UniCharAtIndex: Emoji} ucs2 {
    string index \uD83D\uDE00G 2
test utf-8.8 {Tcl_UniCharAtIndex: Emoji} {
    string index 😀G 1
} G
test utf-8.9.1 {Tcl_UniCharAtIndex: Emoji} ucs4 {
    string index \uD83D\uDE00G 2
test utf-8.9 {Tcl_UniCharAtIndex: Emoji} {
    string index 😀G 2
} {}
test utf-8.9.2 {Tcl_UniCharAtIndex: Emoji} utf16 {
    string index \uD83D\uDE00G 2
} G
test utf-8.10.0 {Tcl_UniCharAtIndex: Emoji} {Uesc ucs2} {
    string index \U1F600G 0
test utf-8.10 {Tcl_UniCharAtIndex: Emoji} {
    string index 😀G 0
} \uFFFD
test utf-8.10.1 {Tcl_UniCharAtIndex: Emoji} {Uesc ucs4} {
    string index \U1F600G 0
} \U1F600
test utf-8.10.2 {Tcl_UniCharAtIndex: Emoji} {Uesc utf16} {
    string index \U1F600G 0
} \U1F600
test utf-8.11.0 {Tcl_UniCharAtIndex: Emoji} {Uesc ucs2} {
    string index \U1F600G 1
} G
test utf-8.11.1 {Tcl_UniCharAtIndex: Emoji} {Uesc ucs4} {
    string index \U1F600G 1
} 😀
test utf-8.11 {Tcl_UniCharAtIndex: Emoji} {
    string index 😀G 1
} G
test utf-8.11.2 {Tcl_UniCharAtIndex: Emoji} {Uesc utf16} {
    string index \U1F600G 1
test utf-8.12 {Tcl_UniCharAtIndex: Emoji} {
    string index 😀G 2
} {}
test utf-8.12.0 {Tcl_UniCharAtIndex: Emoji} {Uesc ucs2} {
    string index \U1F600G 2
} {}
test utf-8.12.1 {Tcl_UniCharAtIndex: Emoji} {Uesc ucs4} {
    string index \U1F600G 2
} {}
test utf-8.12.2 {Tcl_UniCharAtIndex: Emoji} {Uesc utf16} {
    string index \U1F600G 2
} G

test utf-9.1 {Tcl_UtfAtIndex: index = 0} {
    string range abcd 0 2
} abc
test utf-9.2 {Tcl_UtfAtIndex: index > 0} {
    string range \u4E4E\u25A\xFF\u543klmnop 1 5
} \u25A\xFF\u543kl
test utf-9.3.0 {Tcl_UtfAtIndex: index = 0, Emoji} ucs2 {
    string range \uD83D\uDE00G 0 0
} \uD83D
test utf-9.3.1 {Tcl_UtfAtIndex: index = 0, Emoji} ucs4 {
    string range \uD83D\uDE00G 0 0
} \U1F600
test utf-9.3.2 {Tcl_UtfAtIndex: index = 0, Emoji} utf16 {
    string range \uD83D\uDE00G 0 0
} \U1F600
test utf-9.4.0 {Tcl_UtfAtIndex: index > 0, Emoji} ucs2 {
    string range \U1F600G 1 1
} \uDE00
test utf-9.4.1 {Tcl_UtfAtIndex: index > 0, Emoji} ucs4 {
    string range \U1F600G 1 1
} G
    string range 乎ɚÿՃklmnop 1 5
} ɚÿՃkl
test utf-9.3 {Tcl_UtfAtIndex: index = 0, Emoji} {
    string range 😀G 0 0
} 😀
test utf-9.4.2 {Tcl_UtfAtIndex: index > 0, Emoji} utf16 {
    string range \uD83D\uDE00G 1 1
} {}
test utf-9.5.0 {Tcl_UtfAtIndex: index > 0, Emoji} ucs2 {
    string range \uD83D\uDE00G 2 2
test utf-9.4 {Tcl_UtfAtIndex: index > 0, Emoji} {
    string range 😀G 1 1
} G
test utf-9.5.1 {Tcl_UtfAtIndex: index > 0, Emoji} ucs4 {
    string range \uD83D\uDE00G 2 2
test utf-9.5 {Tcl_UtfAtIndex: index > 0, Emoji} {
    string range 😀G 2 2
} {}
test utf-9.5.2 {Tcl_UtfAtIndex: index > 0, Emoji} utf16 {
    string range \uD83D\uDE00G 2 2
} G
test utf-9.6.0 {Tcl_UtfAtIndex: index = 0, Emoji} {Uesc ucs2} {
    string range \U1f600G 0 0
test utf-9.6 {Tcl_UtfAtIndex: index = 0, Emoji} {
    string range 😀G 0 0
} \uFFFD
test utf-9.6.1 {Tcl_UtfAtIndex: index = 0, Emoji} {Uesc ucs4} {
    string range \U1f600G 0 0
} \U1F600
test utf-9.6.2 {Tcl_UtfAtIndex: index = 0, Emoji} {Uesc utf16} {
    string range \U1f600G 0 0
} \U1F600
test utf-9.7.0 {Tcl_UtfAtIndex: index > 0, Emoji} {Uesc ucs2} {
    string range \U1f600G 1 1
} G
test utf-9.7.1 {Tcl_UtfAtIndex: index > 0, Emoji} {Uesc ucs4} {
    string range \U1f600G 1 1
} 😀
test utf-9.7 {Tcl_UtfAtIndex: index > 0, Emoji} {
    string range 😀G 1 1
} G
test utf-9.7.2 {Tcl_UtfAtIndex: index > 0, Emoji} {Uesc utf16} {
    string range \U1f600G 1 1
test utf-9.8 {Tcl_UtfAtIndex: index > 0, Emoji} {
    string range 😀G 2 2
} {}
test utf-9.8.0 {Tcl_UtfAtIndex: index > 0, Emoji} {Uesc ucs2} {
    string range \U1f600G 2 2
} {}
test utf-9.8.1 {Tcl_UtfAtIndex: index > 0, Emoji} {Uesc ucs4} {
    string range \U1f600G 2 2
} {}
test utf-9.8.2 {Tcl_UtfAtIndex: index > 0, Emoji} {Uesc utf16} {
    string range \U1f600G 2 2
} G

test utf-10.1 {Tcl_UtfBackslash: dst == NULL} {
    set x \n
} {
}
test utf-10.2 {Tcl_UtfBackslash: \u subst} testbytestring {
    expr {"\uA2" eq [testbytestring \xC2\xA2]}
} 1
test utf-10.3 {Tcl_UtfBackslash: longer \u subst} testbytestring {
    expr {"\u4E21" eq [testbytestring \xE4\xB8\xA1]}
} 1
test utf-10.4 {Tcl_UtfBackslash: stops at first non-hex} testbytestring {
    expr {"\u4E2k" eq "[testbytestring \xD3\xA2]k"}
} 1
test utf-10.5 {Tcl_UtfBackslash: stops after 4 hex chars} testbytestring {
    expr {"\u4E216" eq "[testbytestring \xE4\xB8\xA1]6"}
} 1
test utf-10.6 {Tcl_UtfBackslash: stops after 5 hex chars} {Uesc fullutf testbytestring} {
test utf-10.6 {Tcl_UtfBackslash: stops after 5 hex chars} testbytestring {
    expr {"\U1E2165" eq "[testbytestring \xF0\x9E\x88\x96]5"}
} 1
test utf-10.7 {Tcl_UtfBackslash: stops after 6 hex chars} {Uesc fullutf testbytestring} {
test utf-10.7 {Tcl_UtfBackslash: stops after 6 hex chars} testbytestring {
    expr {"\U10E2165" eq "[testbytestring \xF4\x8E\x88\x96]5"}
} 1

proc bsCheck {char num {constraints {}}} {
    global errNum
    test utf-10.$errNum {backslash substitution} $constraints {
	scan $char %c value
1002
1003
1004
1005
1006
1007
1008
1009
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






1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135


1136
1137
1138
1139
1140
1141
1142
1143
1144
1145


1146
1147
1148
1149
1150
1151
1152
1153


1154
1155
1156


1157
1158
1159


1160
1161
1162


1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173

1174
1175
1176

1177
1178
1179
1180
1181
1182
1183
1184
1185
1186

1187
1188

1189
1190
1191
1192

1193
1194
1195
1196

1197
1198

1199
1200

1201
1202
1203
1204

1205
1206

1207
1208
1209
1210
1211
1212
1213
1214

1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226

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
857
858
859
860
861
862
863


864
865
866
867
868
869
870
871
872


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
898
899
900
901


902
903
904








905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923


924
925
926


927
928
929


930
931
932
933
934






935
936
937
938
939
940
941
942
943
944
945
946
947
948


949
950
951


952
953
954


955
956
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
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
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
1128







-
-
+








-
-
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
-
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+











-
-
+
+

-
-
+
+

-
-
+
+



-
-
-
-
-
-
+
+
+
+
+
+








-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+



-
-
-
-
-
-
+
+
+
+
+
+


















-
-
+
+








-
-
+
+






-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+










-
+


-
+









-
+

-
+



-
+



-
+

-
+

-
+



-
+

-
+







-
+











-
+








-
+


-
-
+
+


-
+

-
+



-
+


-
+

-
+



-
+


-
+







-
+







bsCheck \14	12
bsCheck \141	97
bsCheck b\0	98
bsCheck \x	120
bsCheck \xa	10
bsCheck \xA	10
bsCheck \x41	65
bsCheck \x541	65	pre388	;# == \x41
bsCheck \x541	84	!pre388	;# == \x54 1
bsCheck \x541	84
bsCheck \u	117
bsCheck \uk	117
bsCheck \u41	65
bsCheck \ua	10
bsCheck \uA	10
bsCheck \340	224
bsCheck \uA1	161
bsCheck \u4E21	20001
bsCheck \741    225	pre388	;# == \341
bsCheck \741    60	!pre388	;# == \74 1
bsCheck \741    60
bsCheck \U      85
bsCheck \Uk     85
bsCheck \U41    65			Uesc
bsCheck \Ua     10			Uesc
bsCheck \UA     10			Uesc
bsCheck \UA1    161			Uesc
bsCheck \U4E21  20001			Uesc
bsCheck \U004E21        20001		Uesc
bsCheck \U00004E21      20001		Uesc
bsCheck \U0000004E21    78		Uesc
bsCheck \U00110000      69632		{Uesc fullutf}
bsCheck \U01100000      69632		{Uesc fullutf}
bsCheck \U11000000      69632		{Uesc fullutf}
bsCheck \U0010FFFF      1114111		{Uesc fullutf}
bsCheck \U010FFFF0      1114111		{Uesc fullutf}
bsCheck \U10FFFF00      1114111		{Uesc fullutf}
bsCheck \UFFFFFFFF      1048575		{Uesc fullutf}
bsCheck \U41    65
bsCheck \Ua     10
bsCheck \UA     10
bsCheck \UA1    161
bsCheck \U4E21  20001
bsCheck \U004E21        20001
bsCheck \U00004E21      20001
bsCheck \U0000004E21    78
bsCheck \U00110000      69632
bsCheck \U01100000      69632
bsCheck \U11000000      69632
bsCheck \U0010FFFF      1114111
bsCheck \U010FFFF0      1114111
bsCheck \U10FFFF00      1114111
bsCheck \UFFFFFFFF      1048575

test utf-11.1 {Tcl_UtfToUpper} {
    string toupper {}
} {}
test utf-11.2 {Tcl_UtfToUpper} {
    string toupper abc
} ABC
test utf-11.3 {Tcl_UtfToUpper} {
    string toupper \xE3gh
} \xC3GH
test utf-11.4 {Tcl_UtfToUpper} {
    string toupper \u01E3gh
} \u01E2GH
    string toupper ǣgh
} ǢGH
test utf-11.5 {Tcl_UtfToUpper Georgian (new in Unicode 11)} {
    string toupper \u10D0\u1C90
} \u1C90\u1C90
test utf-11.6 {Tcl_UtfToUpper beyond U+FFFF} {Uesc fullutf} {
    string toupper \U10428
} \U10400
test utf-11.7 {Tcl_UtfToUpper beyond U+FFFF} fullutf {
    string toupper \uD801\uDC28
} \uD801\uDC00
    string toupper áƒá²
} á²á²
test utf-11.6 {Tcl_UtfToUpper beyond U+FFFF} {
    string toupper ð¨
} ð€
test utf-11.7 {Tcl_UtfToUpper beyond U+FFFF} {
    string toupper ð¨
} ð€
test utf-11.8 {Tcl_UtfToUpper low/high surrogate)} {
    string toupper \uDC24\uD824
} \uDC24\uD824

test utf-12.1 {Tcl_UtfToLower} {
    string tolower {}
} {}
test utf-12.2 {Tcl_UtfToLower} {
    string tolower ABC
} abc
test utf-12.3 {Tcl_UtfToLower} {
    string tolower \xC3GH
} \xE3gh
    string tolower ÃGH
} ãgh
test utf-12.4 {Tcl_UtfToLower} {
    string tolower \u01E2GH
} \u01E3gh
    string tolower ǢGH
} ǣgh
test utf-12.5 {Tcl_UtfToLower Georgian (new in Unicode 11)} {
    string tolower \u10D0\u1C90
} \u10D0\u10D0
    string tolower áƒá²
} áƒáƒ
test utf-12.6 {Tcl_UtfToLower low/high surrogate)} {
    string tolower \uDC24\uD824
} \uDC24\uD824
test utf-12.7 {Tcl_UtfToLower beyond U+FFFF} {Uesc fullutf} {
    string tolower \U10400
} \U10428
test utf-12.8 {Tcl_UtfToLower beyond U+FFFF} fullutf {
    string tolower \uD801\uDC00
} \uD801\uDC28
test utf-12.7 {Tcl_UtfToLower beyond U+FFFF} {
    string tolower ð€
} ð¨
test utf-12.8 {Tcl_UtfToLower beyond U+FFFF} {
    string tolower ð€
} ð¨

test utf-13.1 {Tcl_UtfToTitle} {
    string totitle {}
} {}
test utf-13.2 {Tcl_UtfToTitle} {
    string totitle abc
} Abc
test utf-13.3 {Tcl_UtfToTitle} {
    string totitle \xE3GH
} \xC3gh
    string totitle ãGH
} Ãgh
test utf-13.4 {Tcl_UtfToTitle} {
    string totitle \u01F3AB
} \u01F2ab
    string totitle dzAB
} Dzab
test utf-13.5 {Tcl_UtfToTitle Georgian (new in Unicode 11)} {
    string totitle \u10D0\u1C90
} \u10D0\u1C90
    string totitle áƒá²
} áƒá²
test utf-13.6 {Tcl_UtfToTitle Georgian (new in Unicode 11)} {
    string totitle \u1C90\u10D0
} \u1C90\u10D0
    string totitle á²áƒ
} á²áƒ
test utf-13.7 {Tcl_UtfToTitle low/high surrogate)} {
    string totitle \uDC24\uD824
} \uDC24\uD824
test utf-13.8 {Tcl_UtfToTitle beyond U+FFFF} {Uesc fullutf} {
    string totitle \U10428\U10400
} \U10400\U10428
test utf-13.9 {Tcl_UtfToTitle beyond U+FFFF} fullutf {
    string totitle \uD801\uDC28\uD801\uDC00
} \uD801\uDC00\uD801\uDC28
test utf-13.8 {Tcl_UtfToTitle beyond U+FFFF} {
    string totitle ð¨ð€
} ð€ð¨
test utf-13.9 {Tcl_UtfToTitle beyond U+FFFF} {
    string totitle ð¨ð€
} ð€ð¨

test utf-14.1 {Tcl_UtfNcasecmp} {
    string compare -nocase a b
} -1
test utf-14.2 {Tcl_UtfNcasecmp} {
    string compare -nocase b a
} 1
test utf-14.3 {Tcl_UtfNcasecmp} {
    string compare -nocase B a
} 1
test utf-14.4 {Tcl_UtfNcasecmp} {
    string compare -nocase aBcB abca
} 1

test utf-15.1 {Tcl_UniCharToUpper, negative delta} {
    string toupper aA
} AA
test utf-15.2 {Tcl_UniCharToUpper, positive delta} {
    string toupper \u0178\xFF
} \u0178\u0178
    string toupper Ÿÿ
} ŸŸ
test utf-15.3 {Tcl_UniCharToUpper, no delta} {
    string toupper !
} !

test utf-16.1 {Tcl_UniCharToLower, negative delta} {
    string tolower aA
} aa
test utf-16.2 {Tcl_UniCharToLower, positive delta} {
    string tolower \u0178\xFF\uA78D\u01C5
} \xFF\xFF\u0265\u01C6
    string tolower ŸÿêžÇ…
} ÿÿɥdž

test utf-17.1 {Tcl_UniCharToLower, no delta} {
    string tolower !
} !

test utf-18.1 {Tcl_UniCharToTitle, add one for title} {
    string totitle \u01C4
} \u01C5
    string totitle Ç„
} Ç…
test utf-18.2 {Tcl_UniCharToTitle, subtract one for title} {
    string totitle \u01C6
} \u01C5
    string totitle dž
} Ç…
test utf-18.3 {Tcl_UniCharToTitle, subtract delta for title (positive)} {
    string totitle \u017F
} \x53
    string totitle Å¿
} S
test utf-18.4 {Tcl_UniCharToTitle, subtract delta for title (negative)} {
    string totitle \xFF
} \u0178
    string totitle ÿ
} Ÿ
test utf-18.5 {Tcl_UniCharToTitle, no delta} {
    string totitle !
} !

test utf-19.1 {TclUniCharLen} -body {
    list [regexp \\d abc456def foo] $foo
} -cleanup {
    unset -nocomplain foo
} -result {1 4}

test utf-20.1 {TclUniCharNcmp} ucs4 {
test utf-20.1 {TclUniCharNcmp} {
    string compare [string range [format %c 0xFFFF] 0 0] [string range [format %c 0x10000] 0 0]
} -1
test utf-20.2 {[4c591fa487] TclUniCharNcmp/TclUtfNcmp} knownBug {
test utf-20.2 {[4c591fa487] Tcl_UniCharNcmp/Tcl_UtfNcmp} {
    set one [format %c 0xFFFF]
    set two [format %c 0x10000]
    set first [string compare $one $two]
    string range $one 0 0
    string range $two 0 0
    set second [string compare $one $two]
    expr {($first == $second) ? "agree" : "disagree"}
} agree

test utf-21.1 {TclUniCharIsAlnum} {
test utf-21.1 {Tcl_UniCharIsAlnum} {
    # this returns 1 with Unicode 7 compliance
    string is alnum \u1040\u021F\u0220
    string is alnum á€ÈŸÈ 
} 1
test utf-21.2 {unicode alnum char in regc_locale.c} {
    # this returns 1 with Unicode 7 compliance
    list [regexp {^[[:alnum:]]+$} \u1040\u021F\u0220] [regexp {^\w+$} \u1040\u021F\u0220_\u203F\u2040\u2054\uFE33\uFE34\uFE4D\uFE4E\uFE4F\uFF3F]
    list [regexp {^[[:alnum:]]+$} á€ÈŸÈ ] [regexp {^\w+$} á€ÈŸÈ _‿â€â”︳︴ï¹ï¹Žï¹ï¼¿]
} {1 1}
test utf-21.3 {unicode print char in regc_locale.c} {
    # this returns 1 with Unicode 7 compliance
    regexp {^[[:print:]]+$} \uFBC1
    regexp {^[[:print:]]+$} ï¯
} 1
test utf-21.4 {TclUniCharIsGraph} {
test utf-21.4 {Tcl_UniCharIsGraph} {
    # [Bug 3464428]
    string is graph \u0120
    string is graph Ä 
} 1
test utf-21.5 {unicode graph char in regc_locale.c} {
    # [Bug 3464428]
    regexp {^[[:graph:]]+$} \u0120
    regexp {^[[:graph:]]+$} Ä 
} 1
test utf-21.6 {TclUniCharIsGraph} {
test utf-21.6 {Tcl_UniCharIsGraph} {
    # [Bug 3464428]
    string is graph \xA0
} 0
test utf-21.7 {unicode graph char in regc_locale.c} {
    # [Bug 3464428]
    regexp {[[:graph:]]} \x20\xA0\u2028\u2029
} 0
test utf-21.8 {TclUniCharIsPrint} {
test utf-21.8 {Tcl_UniCharIsPrint} {
    # [Bug 3464428]
    string is print \x09
} 0
test utf-21.9 {unicode print char in regc_locale.c} {
    # [Bug 3464428]
    regexp {[[:print:]]} \x09
} 0
test utf-21.10 {unicode print char in regc_locale.c} {
    # [Bug 3464428]
    regexp {[[:print:]]} \x09
} 0
test utf-21.11 {TclUniCharIsControl} {
test utf-21.11 {Tcl_UniCharIsControl} {
    # [Bug 3464428]
    string is control \x00\x1F\xAD\u0605\u061C\u180E\u2066\uFEFF
} 1
test utf-21.12 {unicode control char in regc_locale.c} {
    # [Bug 3464428], [Bug a876646efe]
    regexp {^[[:cntrl:]]*$} \x00\x1F\xAD\u0605\u061C\u180E\u2066\uFEFF
} 1

test utf-22.1 {TclUniCharIsWordChar} {
test utf-22.1 {Tcl_UniCharIsWordChar} {
    string wordend "xyz123_bar fg" 0
} 10
test utf-22.2 {TclUniCharIsWordChar} {
    string wordend "x\u5080z123_bar\u203C fg" 0
test utf-22.2 {Tcl_UniCharIsWordChar} {
    string wordend "x傀z123_bar‼ fg" 0
} 10

test utf-23.1 {TclUniCharIsAlpha} {
test utf-23.1 {Tcl_UniCharIsAlpha} {
    # this returns 1 with Unicode 7 compliance
    string is alpha \u021F\u0220\u037F\u052F
    string is alpha ÈŸÈ Í¿Ô¯
} 1
test utf-23.2 {unicode alpha char in regc_locale.c} {
    # this returns 1 with Unicode 7 compliance
    regexp {^[[:alpha:]]+$} \u021F\u0220\u037F\u052F
    regexp {^[[:alpha:]]+$} ÈŸÈ Í¿Ô¯
} 1

test utf-24.1 {TclUniCharIsDigit} {
test utf-24.1 {Tcl_UniCharIsDigit} {
    # this returns 1 with Unicode 7 compliance
    string is digit \u1040\uABF0
    string is digit á€ê¯°
} 1
test utf-24.2 {unicode digit char in regc_locale.c} {
    # this returns 1 with Unicode 7 compliance
    list [regexp {^[[:digit:]]+$} \u1040\uABF0] [regexp {^\d+$} \u1040\uABF0]
    list [regexp {^[[:digit:]]+$} á€ê¯°] [regexp {^\d+$} á€ê¯°]
} {1 1}

test utf-24.3 {TclUniCharIsSpace} {
test utf-24.3 {Tcl_UniCharIsSpace} {
    # this returns 1 with Unicode 7 compliance
    string is space \u1680\u180E\u202F
} 1
test utf-24.4 {unicode space char in regc_locale.c} {
    # this returns 1 with Unicode 7 compliance
    list [regexp {^[[:space:]]+$} \u1680\u180E\u202F] [regexp {^\s+$} \u1680\u180E\u202F]
} {1 1}
test utf-24.5 {TclUniCharIsSpace} tip413 {
test utf-24.5 {Tcl_UniCharIsSpace} tip413 {
    # this returns 1 with Unicode 7/TIP 413 compliance
    string is space \x85\u1680\u180E\u200B\u202F\u2060
} 1
test utf-24.6 {unicode space char in regc_locale.c} tip413 {
    # this returns 1 with Unicode 7/TIP 413 compliance
    list [regexp {^[[:space:]]+$} \x85\u1680\u180E\u200B\u202F\u2060] [regexp {^\s+$} \x85\u1680\u180E\u200B\u202F\u2060]
} {1 1}
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
1149
1150
1151
1152
1153
1154
1155




1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201

1202
1203
1204
1205
1206
1207
1208
1209
1210







-
-
-
-
+
+
+
+













+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+








    incr count
}
variable count 1
UniCharCaseCmpTest < a b
UniCharCaseCmpTest > b a
UniCharCaseCmpTest > B a
UniCharCaseCmpTest > aBcB abca
UniCharCaseCmpTest < \uFFFF [format %c 0x10000] ucs4
UniCharCaseCmpTest < \uFFFF \U10000		{Uesc ucs4}
UniCharCaseCmpTest > [format %c 0x10000] \uFFFF	ucs4
UniCharCaseCmpTest > \U10000 \uFFFF		{Uesc ucs4}
UniCharCaseCmpTest < \uFFFF [format %c 0x10000]
UniCharCaseCmpTest < \uFFFF \U10000
UniCharCaseCmpTest > [format %c 0x10000] \uFFFF
UniCharCaseCmpTest > \U10000 \uFFFF


test utf-26.1 {Tcl_UniCharDString} -setup {
    testobj freeallvars
} -constraints {teststringobj testbytestring} -cleanup {
    testobj freeallvars
} -body {
    teststringobj set 1 foo
    teststringobj maxchars 1
    teststringobj append 1 [testbytestring barsoom\xF2\xC2\x80] 10
    scan [string index [teststringobj get 1] 11] %c
} -result 128

unset count
rename UniCharCaseCmpTest {}

proc GetUniCharTest {s index result} {
    variable count
    # Use quotes, not {} so test output shows exact string on error
    test getunichar-1.$count "Tcl_GetUniChar $s $index" \
	-constraints testgetunichar \
	-body "testgetunichar $s $index" \
	-result $result
    incr count
}
variable count 1
set errorIndicator -1
GetUniCharTest abcd -2   $errorIndicator
GetUniCharTest abcd -1   $errorIndicator
GetUniCharTest abcd  0   97 ;# a -> ASCII 97
GetUniCharTest abcd  3   100
GetUniCharTest abcd  4    $errorIndicator
GetUniCharTest abcd  1000 $errorIndicator

GetUniCharTest \xe0bc\xe1 -2   $errorIndicator
GetUniCharTest \xe0bc\xe1 -1   $errorIndicator
GetUniCharTest \xe0bc\xe1  0   224 ;# \xe0 == 224
GetUniCharTest \xe0bc\xe1  3   225
GetUniCharTest \xe0bc\xe1  4    $errorIndicator
GetUniCharTest \xe0bc\xe1  1000 $errorIndicator

unset count
rename UniCharCaseCmpTest {}
rename GetUniCharTest ""

# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Added tests/utfext.test.













































































































































































































































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# This file contains a collection of tests for Tcl_UtfToExternal and
# Tcl_UtfToExternal that exercise various combinations of flags,
# buffer lengths and fragmentation that cannot be tested by
# normal script level commands. There tests are NOT intended to check
# correct encodings; those are elsewhere.
#
# Copyright (c) 2023 Ashok P. Nadkarni
#
# 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]]

testConstraint testbytestring [llength [info commands testbytestring]]
testConstraint testencoding [llength [info commands testencoding]]

namespace eval utftest {
    # Format of table, indexed by encoding. The encodings are not exhaustive
    # but one of each kind of encoding transform (algorithmic, table-driven,
    # stateful, DBCS, MBCS).
    # Each element is list of lists. Nested lists have following fields
    # 0 comment (no spaces, might be used to generate id's as well)
    #   The combination of comment and internal hex (2) should be unique.
    # 1 hex representation of internal *modified* utf-8 encoding. This is the
    #   source string for Tcl_UtfToExternal and expected result for
    #   Tcl_ExternalToUtf.
    # 2 hex representation in specified encoding. This is the source string for
    #   Tcl_ExternalToUtf and expected result for Tcl_UtfToExternal.
    # 3 internal fragmentation index - where to split field 1 for fragmentation
    #   tests. -1 to skip
    # 4 external fragmentation index - where to split field 2 for fragmentation
    #   tests. -1 to skip
    #
    # THE HEX DEFINITIONS SHOULD SEPARATE EACH CHARACTER BY WHITESPACE
    # (assumed by the charlimit tests)
    lappend utfExtMap {*}{
	ascii {
	    {basic {41 42 43} {41 42 43} -1 -1}
	}
	utf-8 {
	    {bmp    {41 c3a9 42}     {41 c3a9 42}      2  2}
	    {nonbmp-frag-1 {41 f09f9880 42} {41 f09f9880 42}  2  2}
	    {nonbmp-frag-2 {41 f09f9880 42} {41 f09f9880 42}  3  3}
	    {nonbmp-frag-3 {41 f09f9880 42} {41 f09f9880 42}  4  4}
	    {null   {41 c080 42} {41 00 42}    2 -1}
	}
	cesu-8 {
	    {bmp    {41 c3a9 42}     {41 c3a9 42}      2  2}
	    {nonbmp-frag-surr-low {41 f09f9880 42} {41 eda0bd edb880 42} 2 2}
	    {nonbmp-split-surr {41 f09f9880 42} {41 eda0bd edb880 42} 3 -1}
	    {nonbmp-frag-surr-high {41 f09f9880 42} {41 eda0bd edb880 42} 4 6}
	    {null   {41 c080 42} {41 00 42}    2 -1}
	}
	utf-16le {
	    {bmp    {41 c3a9 42}     {4100 e900 4200}     2  3}
	    {nonbmp {41 f09f9880 42} {4100 3dd8 00de 4200} 4  3}
	    {split-surrogate {41 f09f9080 42} {4100 3dd8 00dc 4200} 3  4}
	    {null   {41 c080 42} {4100 0000 4200}  2 3}
	}
	utf-16be {
	    {bmp    {41 c3a9 42}     {0041 00e9 0042}     2  3}
	    {nonbmp {41 f09f9880 42} {0041 d83d de00 0042} 4  3}
	    {split-surrogate {41 f09f9080 42} {0041 d83d dc00 0042} 3  4}
	    {null   {41 c080 42} {0041 0000 0042}  2 3}
	}
	utf-32le {
	    {bmp    {41 c3a9 42}     {41000000 e9000000 42000000}     2  3}
	    {nonbmp {41 f09f9880 42} {41000000 00f60100 42000000} 4  6}
	    {null   {41 c080 42} {41000000 00000000 42000000}  2 3}
	}
	utf-32be {
	    {bmp    {41 c3a9 42}     {00000041 000000e9 00000042}     2  3}
	    {nonbmp {41 f09f9880 42} {00000041 0001f600 00000042} 4  3}
	    {null   {41 c080 42} {00000041 00000000 00000042}  2 3}
	}
	iso8859-1 {
	    {basic {41 c3a9 42} {41 e9 42} 2 -1}
	    {null  {41 c080 42} {41 00 42} 2 -1}
	}
	iso8859-3 {
	    {basic {41 c4a0 42} {41 d5 42} 2 -1}
	    {null  {41 c080 42} {41 00 42} 2 -1}
	}
	shiftjis {
	    {basic {41 e4b98e 42} {41 8cc1 42} 3 2}
	}
	jis0208 {
	    {basic {e4b98e e590be} {3843 3863} 1 1}
	}
	iso2022-jp {
	    {frag-in-leadescape {58 e4b98e 5a} {58 1b2442 3843 1b2842 5a} 2 2}
	    {frag-in-char {58 e4b98e 5a} {58 1b2442 3843 1b2842 5a} 2 5}
	    {frag-in-trailescape {58 e4b98e 5a} {58 1b2442 3843 1b2842 5a} 2 8}
	}
    }

    # Return a binary string containing nul terminator for encoding
    proc hexnuls {enc} {
	return [binary encode hex [encoding convertto $enc \x00]]
    }

    # The C wrapper fills entire destination buffer with FF.
    # Anything beyond expected output should have FF's
    proc fill {bin buflen} {
	return [string range "$bin[string repeat \xFF $buflen]" 0 $buflen-1]
    }

    proc testutf {direction enc comment hexin hexout args} {
	set id $comment-[join $hexin ""]
	if {$direction eq "toutf"} {
	    set cmd Tcl_ExternalToUtf
	} else {
	    set cmd Tcl_UtfToExternal
	}
	set in [binary decode hex $hexin]
	set out [binary decode hex $hexout]
	set dstlen 40 ;# Should be enough for all encoding tests

	set status ok
	set flags [list start end]
	set constraints [list testencoding]
	set profiles [encoding profiles]
	while {[llength $args] > 1} {
	    set opt [lpop args 0]
	    switch $opt {
		-flags       { set flags [lpop args 0] }
		-constraints { lappend constraints {*}[lpop args 0] }
		-profiles    { set profiles [lpop args 0] }
		-status      { set status [lpop args 0]}
		default {
		    error "Unknown option \"$opt\""
		}
	    }
	}
	if {[llength $args]} {
	    error "No value supplied for option [lindex $args 0]."
	}

	set result [list $status {} [fill $out $dstlen]]

	test $cmd-$enc-$id-[join $flags -] "$cmd - $enc - $hexin - $flags" -body \
	    [list testencoding $cmd $enc $in $flags {} $dstlen] \
	    -result $result -constraints $constraints
	foreach profile $profiles {
	    set flags2 [linsert $flags end $profile]
	    test $cmd-$enc-$id-[join $flags2 -] "$cmd - $enc - $hexin - $flags2" -body \
		[list testencoding $cmd $enc $in $flags2 {} $dstlen] \
		-result $result -constraints $constraints
	}
    }

    proc testfragment {direction enc comment hexin hexout fragindex args} {

	if {$fragindex < 0} {
	    # Single byte encodings so no question of fragmentation
	    return
	}
	set id $comment-[join $hexin ""]-fragment

	if {$direction eq "toutf"} {
	    set cmd Tcl_ExternalToUtf
	} else {
	    set cmd Tcl_UtfToExternal
	}

	set status1 multibyte; # Return status to expect after first call
	while {[llength $args] > 1} {
	    set opt [lpop args 0]
	    switch $opt {
		-status1  { set status1 [lpop args 0]}
		default {
		    error "Unknown option \"$opt\""
		}
	    }
	}

	set in [binary decode hex $hexin]
	set infrag [string range $in 0 $fragindex-1]
	set out [binary decode hex $hexout]
	set dstlen 40 ;# Should be enough for all encoding tests

	test $cmd-$enc-$id "$cmd - $enc - $hexin - frag" -constraints testencoding -body {
	    set frag1Result [testencoding $cmd $enc [string range $in 0 $fragindex-1] {start} 0 $dstlen frag1Read frag1Written]
	    lassign $frag1Result frag1Status frag1State frag1Decoded
	    set frag2Result [testencoding $cmd $enc [string range $in $frag1Read end] {end} $frag1State $dstlen frag2Read frag2Written]
	    lassign $frag2Result frag2Status frag2State frag2Decoded
	    set decoded [string cat [string range $frag1Decoded 0 $frag1Written-1] [string range $frag2Decoded 0 $frag2Written-1]]
	    list $frag1Status [expr {$frag1Read <= $fragindex}] \
		$frag2Status [expr {$frag1Read+$frag2Read}] \
		[expr {$frag1Written+$frag2Written}] $decoded
	} -result [list $status1 1 ok [string length $in] [string length $out] $out]
    }

    proc testcharlimit {direction enc comment hexin hexout} {
	set id $comment-[join $hexin ""]-charlimit

	if {$direction eq "toutf"} {
	    set cmd Tcl_ExternalToUtf
	} else {
	    set cmd Tcl_UtfToExternal
	}

	set maxchars [llength $hexout]
	set in [binary decode hex $hexin]
	set out [binary decode hex $hexout]
	set dstlen 40 ;# Should be enough for all encoding tests

	for {set nchars 0} {$nchars <= $maxchars} {incr nchars} {
	    set expected_bytes [binary decode hex [lrange $hexout 0 $nchars-1]]
	    set expected_nwritten [string length $expected_bytes]
	    test $cmd-$enc-$id-$nchars "$cmd - $enc - $hexin - nchars $nchars" -constraints testencoding -body {
		set charlimit $nchars
		lassign [testencoding $cmd $enc $in \
			     {start end charlimit} 0 $dstlen nread nwritten charlimit] \
		    status state buf
		list $status $nwritten [string range $buf 0 $nwritten-1]
	    } -result [list [expr {$nchars == $maxchars ? "ok" : "nospace"}] $expected_nwritten $expected_bytes]
	}
    }

    proc testspacelimit {direction enc comment hexin hexout} {
	set id $comment-[join $hexin ""]-spacelimit

	# Triple the input to avoid pathological short input case where
	# whereby nothing is written to output. The test below
	# requires $nchars > 0
	set hexin $hexin$hexin$hexin
	set hexout $hexout$hexout$hexout

	set flags [list start end]
	set constraints [list testencoding]

	set maxchars [llength $hexout]
	set in [binary decode hex $hexin]
	set out [binary decode hex $hexout]
	set dstlen [expr {[string length $out] - 1}]; # Smaller buffer than needed

	if {$direction eq "toutf"} {
	    set cmd Tcl_ExternalToUtf
	    set str [encoding convertfrom $enc $in]
	} else {
	    set cmd Tcl_UtfToExternal
	    set str [encoding convertfrom $enc $out]
	}

	# Note the tests are loose because the some encoding operations will
	# stop even there is actually still room in the destination. For example,
	# below only one char is written though there is room in the output.
	# % testencoding Tcl_ExternalToUtf ascii abc {start end} {} 5 nread nwritten nchars
	# nospace {} aÿÿÿ#
	# % puts $nread,$nwritten,$nchars
	# 1,1,1
	#

	test $cmd-$enc-$id-[join $flags -] "$cmd - $enc - $hexin - $flags" \
	    -constraints $constraints \
	    -body {
	    lassign [testencoding $cmd $enc $in $flags {} $dstlen nread nwritten nchars] status state buf
	    list \
		$status \
		[expr {$nread < [string length $in]}] \
		[expr {$nwritten <= $dstlen}] \
		[expr {$nchars > 0 && $nchars < [string length $str]}] \
		[expr {[string range $out 0 $nwritten-1] eq [string range $buf 0 $nwritten-1]}]
	    } -result {nospace 1 1 1 1}
    }

    #
    # Basic tests
    foreach {enc testcases} $utfExtMap {
	foreach testcase $testcases {
	    lassign $testcase {*}{comment utfhex hex internalfragindex externalfragindex}

	    # Basic test - TCL_ENCODING_START|TCL_ENCODING_END
	    # Note by default output should be terminated with \0
	    set encnuls [hexnuls $enc]
	    testutf toutf $enc $comment $hex ${utfhex}00
	    testutf fromutf $enc $comment $utfhex $hex$encnuls

	    # Test TCL_ENCODING_NO_TERMINATE
	    testutf toutf $enc $comment $hex $utfhex -flags {start end noterminate}
	    # noterminate is specific to ExternalToUtf,
	    # should have no effect in other direction
	    testutf fromutf $enc $comment $utfhex $hex$encnuls -flags {start end noterminate}

	    # Fragments
	    testfragment toutf $enc $comment $hex $utfhex $externalfragindex
	    testfragment fromutf $enc $comment $utfhex $hex $internalfragindex

	    # Char limits - note no fromutf as Tcl_UtfToExternal does not support it
	    testcharlimit toutf $enc $comment $hex $utfhex

	    # Space limits
	    testspacelimit toutf $enc $comment $hex $utfhex
	    testspacelimit fromutf $enc $comment $utfhex $hex
	}
    }


    # Special cases - cesu2 high and low surrogates in separate fragments
    # This will (correctly) return "ok", not "multibyte" after first frag
    testfragment toutf cesu-8 nonbmp-split-surr \
	{41 eda0bd edb880 42} {41 f09f9880 42} 4 -status1 ok

    # Bug regression tests
    test Tcl_UtfToExternal-bug-183a1adcc0 {buffer overflow} -body {
	testencoding Tcl_UtfToExternal utf-16 A {start end} {} 1
    } -result [list nospace {} \xFF] -constraints testencoding

    test Tcl_ExternalToUtf-bug-5be203d6ca {
	truncated prefix in table encoding
    } -body {
	set src \x82\x4F\x82\x50\x82
	set result [list [testencoding Tcl_ExternalToUtf shiftjis $src {start tcl8} 0 16 srcRead dstWritten charsWritten] $srcRead $dstWritten $charsWritten]
	lappend result {*}[list [testencoding Tcl_ExternalToUtf shiftjis [string range $src $srcRead end] {end tcl8} 0 10 srcRead dstWritten charsWritten] $srcRead $dstWritten $charsWritten]
    } -result [list [list multibyte 0 \xEF\xBC\x90\xEF\xBC\x91\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF] 4 6 2 [list ok 0 \xC2\x82\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF] 1 2 1] -constraints testencoding
}

namespace delete utftest

::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/util.test.

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
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
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
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



-
-
+
+










-
+







+









-
+

-
+









-
+

-
+

-
+

-
+

-
+





-
+

-
+









-
+

-
+

-
+

-
+

-
+







# This file is a Tcl script to test the code in the file tclUtil.c.
# This file is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1995-1998 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1995-1998 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint controversialNaN 1
testConstraint testbytestring [llength [info commands testbytestring]]
testConstraint testdstring [llength [info commands testdstring]]
testConstraint testconcatobj [llength [info commands testconcatobj]]
testConstraint testdoubledigits [llength [info commands testdoubledigits]]
testConstraint testprint [llength [info commands testprint]]
testConstraint longIs64bit [expr {$tcl_platform(wordSize) == 8}]

# Big test for correct ordering of data in [expr]

proc testIEEE {} {
    variable ieeeValues
    binary scan [binary format dd -1.0 1.0] c* c
    switch -exact -- $c {
	{0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
	    # little endian
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\xFF d \
		ieeeValues(-Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\xBF d \
		ieeeValues(-Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
		ieeeValues(-Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x3F d \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \
		ieeeValues(+Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF8\x7F d \
		ieeeValues(NaN)
	    binary scan \x00\x00\x00\x00\x00\x00\xf8\xff d \
	    binary scan \x00\x00\x00\x00\x00\x00\xF8\xFF d \
		ieeeValues(-NaN)
	    binary scan \xef\xcd\xab\x89\x67\x45\xfb\xff d \
	    binary scan \xEF\xCD\xAB\x89\x67\x45\xFB\xFF d \
		ieeeValues(-NaN(3456789abcdef))
	    set ieeeValues(littleEndian) 1
	    return 1
	}
	{-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
	    binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \xFF\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Infinity)
	    binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \xBF\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Normal)
	    binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Subnormal)
	    binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x3F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Normal)
	    binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
	    binary scan \x7F\xF8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    binary scan \xff\xf8\x00\x00\x00\x00\x00\x00 d \
	    binary scan \xFF\xF8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-NaN)
	    binary scan \xff\xfb\x45\x67\x89\xab\xcd\xef d \
	    binary scan \xFF\xFB\x45\x67\x89\xAB\xCD\xEF d \
		ieeeValues(-NaN(3456789abcdef))
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 0
	}
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
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







-
+
















-
+







    return $result
}

proc verdonk_test {sig binexp shouldbe exp} {
    regexp {([-+]?)([0-9a-f]+)} $sig -> signum sig
    scan $sig %llx sig
    if {$signum eq {-}} {
	set signum [expr 1<<63]
	set signum [expr {1<<63}]
    } else {
	set signum 0
    }
    regexp {E([-+]?[0-9]+)} $binexp -> binexp
    set word [expr {$signum | (($binexp + 0x3ff)<<52)|($sig & ~(1<<52))}]
    binary scan [binary format w $word] q double
    regexp {([-+])(\d+)_(\d+)\&} $shouldbe -> signum digits1 digits2
    regexp {E([-+]\d+)} $exp -> decexp
    incr decexp [expr {[string length $digits1] - 1}]
    lassign [testdoubledigits $double [string length $digits1] e] \
	outdigits decpt outsign
    if {[string index $digits2 0] >= 5} {
	incr digits1
    }
    if {$outsign != $signum || $outdigits != $digits1 || $decpt != $decexp} {
	return -code error "result is ${outsign}0.${outdigits}E$decpt\
                            should be ${signum}0.${digits1}E$decexp"
			    should be ${signum}0.${digits1}E$decexp"
    }
}

test util-1.1 {TclFindElement procedure - binary element in middle of list} {
    lindex {0 foo\x00help 1} 1
} "foo\x00help"
test util-1.2 {TclFindElement procedure - binary element at end of list} {
200
201
202
203
204
205
206
207
208
209



210
211
212
213
214



215
216
217
218
219
220
221
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







-
-
-
+
+
+





+
+
+







test util-4.4 {Tcl_ConcatObj - backslash-space at end of argument} {
    concat a {b } c
} {a b c}
test util-4.5 {Tcl_ConcatObj - backslash-space at end of argument} {
    concat a { } c
} {a c}
test util-4.6 {Tcl_ConcatObj - utf-8 sequence with "whitespace" char} {
    # Check for Bug #227512.  If this violates C isspace, then it returns \xc3.
    concat \xe0
} \xe0
    # Check for Bug #227512.  If this violates C isspace, then it returns \xC3.
    concat \xE0
} \xE0
test util-4.7 {Tcl_ConcatObj - refCount safety} testconcatobj {
    # Check for Bug #1447328 (actually, bugs in its original "fix"). One of the
    # symptoms was Bug #2055782.
    testconcatobj
} {}
test util-4.8 {Tcl_ConcatObj - [Bug 26649439c7]} {
    concat [list foo] [list #]
} {foo {#}}

proc Wrapper_Tcl_StringMatch {pattern string} {
    # Forces use of Tcl_StringMatch, not Tcl_UniCharCaseMatch
    switch -glob -- $string $pattern {return 1} default {return 0}
}
test util-5.1 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch ab*c abc
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
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







-
+






-
+












-
+


-
+




-
+









-
+



-
-
+
+




-
+








-
+


-
+


-
+







test util-5.5 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch *3*6*9 0123456789
} 1
test util-5.6 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch *3*6*9 01234567890
} 0
test util-5.7 {Tcl_StringMatch: UTF-8} {
    Wrapper_Tcl_StringMatch *u \u4e4fu
    Wrapper_Tcl_StringMatch *u ä¹u
} 1
test util-5.8 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch a?c abc
} 1
test util-5.9 {Tcl_StringMatch: UTF-8} {
    # skip one character in string
    Wrapper_Tcl_StringMatch a?c a\u4e4fc
    Wrapper_Tcl_StringMatch a?c aä¹c
} 1
test util-5.10 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch a??c abc
} 0
test util-5.11 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch ?1??4???8? 0123456789
} 1
test util-5.12 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch {[abc]bc} abc
} 1
test util-5.13 {Tcl_StringMatch: UTF-8} {
    # string += Tcl_UtfToUniChar(string, &ch);
    Wrapper_Tcl_StringMatch "\[\u4e4fxy\]bc" "\u4e4fbc"
    Wrapper_Tcl_StringMatch "\[ä¹xy\]bc" "ä¹bc"
} 1
test util-5.14 {Tcl_StringMatch} {
    # if ((*pattern == ']') || (*pattern == '\0'))
    # if ((*pattern == ']') || (*pattern == '\x00'))
    # badly formed pattern
    Wrapper_Tcl_StringMatch {[]} {[]}
} 0
test util-5.15 {Tcl_StringMatch} {
    # if ((*pattern == ']') || (*pattern == '\0'))
    # if ((*pattern == ']') || (*pattern == '\x00'))
    # badly formed pattern
    Wrapper_Tcl_StringMatch {[} {[}
} 0
test util-5.16 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch {a[abc]c} abc
} 1
test util-5.17 {Tcl_StringMatch: UTF-8} {
    # pattern += Tcl_UtfToUniChar(pattern, &endChar);
    # get 1 UTF-8 character
    Wrapper_Tcl_StringMatch "a\[a\u4e4fc]c" "a\u4e4fc"
    Wrapper_Tcl_StringMatch "a\[aä¹c]c" "aä¹c"
} 1
test util-5.18 {Tcl_StringMatch: UTF-8} testbytestring {
    # pattern += Tcl_UtfToUniChar(pattern, &endChar);
    # proper advance: wrong answer would match on UTF trail byte of \u4e4f
    Wrapper_Tcl_StringMatch {a[a\u4e4fc]c} [testbytestring a\x8Fc]
    # proper advance: wrong answer would match on UTF trail byte of ä¹
    Wrapper_Tcl_StringMatch {a[aä¹c]c} [testbytestring a\x8Fc]
} 0
test util-5.19 {Tcl_StringMatch: UTF-8} {
    # pattern += Tcl_UtfToUniChar(pattern, &endChar);
    # proper advance.
    Wrapper_Tcl_StringMatch {a[a\u4e4fc]c} "acc"
    Wrapper_Tcl_StringMatch {a[aä¹c]c} "acc"
} 1
test util-5.20 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch {a[xyz]c} abc
} 0
test util-5.21 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch {12[2-7]45} 12345
} 1
test util-5.22 {Tcl_StringMatch: UTF-8 range} {
    Wrapper_Tcl_StringMatch "\[\u4e00-\u4e4f]" "0"
    Wrapper_Tcl_StringMatch "\[一-ä¹]" "0"
} 0
test util-5.23 {Tcl_StringMatch: UTF-8 range} {
    Wrapper_Tcl_StringMatch "\[\u4e00-\u4e4f]" "\u4e33"
    Wrapper_Tcl_StringMatch "\[一-ä¹]" "丳"
} 1
test util-5.24 {Tcl_StringMatch: UTF-8 range} {
    Wrapper_Tcl_StringMatch "\[\u4e00-\u4e4f]" "\uff08"
    Wrapper_Tcl_StringMatch "\[一-ä¹]" "("
} 0
test util-5.25 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch {12[ab2-4cd]45} 12345
} 1
test util-5.26 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch {12[ab2-4cd]45} 12b45
} 1
349
350
351
352
353
354
355
356

357
358
359

360
361
362
363
364
365

366
367
368
369
370
371
372
353
354
355
356
357
358
359

360
361
362

363
364
365
366
367
368

369
370
371
372
373
374
375
376







-
+


-
+





-
+







test util-5.40 {Tcl_StringMatch: skip correct number of ']'} {
    Wrapper_Tcl_StringMatch {[A-]x} Ax
} 0
test util-5.41 {Tcl_StringMatch: skip correct number of ']'} {
    Wrapper_Tcl_StringMatch {[A-]]x} Ax
} 1
test util-5.42 {Tcl_StringMatch: skip correct number of ']'} {
    Wrapper_Tcl_StringMatch {[A-]]x} \ue1x
    Wrapper_Tcl_StringMatch {[A-]]x} \xE1x
} 0
test util-5.43 {Tcl_StringMatch: skip correct number of ']'} {
    Wrapper_Tcl_StringMatch \[A-]\ue1]x \ue1x
    Wrapper_Tcl_StringMatch \[A-]\xE1]x \xE1x
} 1
test util-5.44 {Tcl_StringMatch: skip correct number of ']'} {
    Wrapper_Tcl_StringMatch {[A-]h]x} hx
} 1
test util-5.45 {Tcl_StringMatch} {
    # if (*pattern == '\0')
    # if (*pattern == '\x00')
    # badly formed pattern, still treats as a set
    Wrapper_Tcl_StringMatch {[a} a
} 1
test util-5.46 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch {a\*b} a*b
} 1
test util-5.47 {Tcl_StringMatch} {
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
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







-
+




-
+


-
+










-
-
-
+
+
+

-
+

-
+






-
+






-
+







test util-5.50 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch *. ""
} 0
test util-5.51 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch "" ""
} 1
test util-5.52 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch \[a\u0000 a\x80
    Wrapper_Tcl_StringMatch \[a\x00 a\x80
} 0


test util-6.5 {Tcl_PrintDouble - make sure there's a decimal point} {
    concat x[expr 2.0]
    concat x[expr {2.0}]
} {x2.0}
test util-6.6 {Tcl_PrintDouble - make sure there's a decimal point} {
    concat x[expr 3.0e98]
    concat x[expr {3.0e98}]
} {x3e+98}

# This test always succeeded in the C locale anyway...
test util-8.1 {TclNeedSpace - correct utf-8 handling} {
    # Bug 411825
    # Note that this test relies on the fact that
    # [interp target] calls on Tcl_AppendElement()
    # which calls on TclNeedSpace().  If [interp target]
    # is ever updated, this test will no longer test
    # TclNeedSpace.
    interp create \u5420
    interp create [list \u5420 foo]
    interp alias {} fooset [list \u5420 foo] set
    interp create å 
    interp create [list å  foo]
    interp alias {} fooset [list å  foo] set
    set result [interp target {} fooset]
    interp delete \u5420
    interp delete å 
    set result
} "\u5420 foo"
} "å  foo"
test util-8.2 {TclNeedSpace - correct utf-8 handling} testdstring {
    # Bug 411825
    # This tests the same bug as the previous test, but
    # should be more future-proof, as the DString
    # operations will likely continue to call TclNeedSpace
    testdstring free
    testdstring append \u5420 -1
    testdstring append å  -1
    testdstring element foo
    llength [testdstring get]
} 2
test util-8.3 {TclNeedSpace - correct utf-8 handling} testdstring {
    # Bug 411825 - new variant reported by Dossy Shiobara
    testdstring free
    testdstring append \u00A0 -1
    testdstring append \xA0 -1
    testdstring element foo
    llength [testdstring get]
} 2
test util-8.4 {TclNeedSpace - correct utf-8 handling} testdstring {
    # Another bug uncovered while fixing 411825
    testdstring free
    testdstring append {\ } -1
446
447
448
449
450
451
452
453

454
455
456
457
458
459
460
461
462

463
464
465
466
467
468
469
470
471

472
473
474
475
476
477
478
479
480

481
482
483
484
485
486
487
488
489

490
491
492
493
494
495
496
450
451
452
453
454
455
456

457
458
459
460
461
462
463
464
465

466
467
468
469
470
471
472
473
474

475
476
477
478
479
480
481
482
483

484
485
486
487
488
489
490
491
492

493
494
495
496
497
498
499
500







-
+








-
+








-
+








-
+








-
+







    testdstring free
    testdstring append {\\ } -1
    testdstring append \{ -1
    testdstring element foo
    testdstring append \} -1
    list [llength [testdstring get]] [string length [testdstring get]]
} {2 8}
test util-8.7 {TclNeedSpace - watch out for escaped space} {
test util-8.7 {TclNeedSpace - watch out for escaped space} testdstring {
    testdstring free
    testdstring append {\ } -1
    testdstring start
    testdstring end

    # Should make {\  {}}
    list [llength [testdstring get]] [string index [testdstring get] 3]
} {2 \{}
test util-8.8 {TclNeedSpace - watch out for escaped space} {
test util-8.8 {TclNeedSpace - watch out for escaped space} testdstring {
    testdstring free
    testdstring append {\\ } -1
    testdstring start
    testdstring end

    # Should make {\\ {}}
    list [llength [testdstring get]] [string index [testdstring get] 3]
} {2 \{}
test util-8.9 {TclNeedSpace - watch out for escaped space} {
test util-8.9 {TclNeedSpace - watch out for escaped space} testdstring {
    testdstring free
    testdstring append {\\\ } -1
    testdstring start
    testdstring end

    # Should make {\\\  {}}
    list [llength [testdstring get]] [string index [testdstring get] 5]
} {2 \{}
test util-8.10 {TclNeedSpace - watch out for escaped space} {
test util-8.10 {TclNeedSpace - watch out for escaped space} testdstring {
    testdstring free
    testdstring append {\\\\\\\ } -1
    testdstring start
    testdstring end

    # Should make {\\\\\\\  {}}
    list [llength [testdstring get]] [string index [testdstring get] 9]
} {2 \{}
test util-8.11 {TclNeedSpace - watch out for escaped space} {
test util-8.11 {TclNeedSpace - watch out for escaped space} testdstring {
    testdstring free
    testdstring append {\\\\\\\\ } -1
    testdstring start
    testdstring end

    # Should make {\\\\\\\\ {}}
    list [llength [testdstring get]] [string index [testdstring get] 9]
1107
1108
1109
1110
1111
1112
1113
1114

1115
1116
1117

1118
1119
1120

1121
1122
1123

1124
1125
1126

1127
1128
1129

1130
1131
1132

1133
1134
1135

1136
1137
1138

1139
1140
1141

1142
1143
1144

1145
1146
1147

1148
1149
1150

1151
1152
1153

1154
1155
1156

1157
1158
1159

1160
1161
1162

1163
1164
1165

1166
1167
1168

1169
1170
1171

1172
1173
1174

1175
1176
1177

1178
1179
1180

1181
1182
1183
1184
1185
1186
1187
1111
1112
1113
1114
1115
1116
1117

1118
1119
1120

1121
1122
1123

1124
1125
1126

1127
1128
1129

1130
1131
1132

1133
1134
1135

1136
1137
1138

1139
1140
1141

1142
1143
1144

1145
1146
1147

1148
1149
1150

1151
1152
1153

1154
1155
1156

1157
1158
1159

1160
1161
1162

1163
1164
1165

1166
1167
1168

1169
1170
1171

1172
1173
1174

1175
1176
1177

1178
1179
1180

1181
1182
1183

1184
1185
1186
1187
1188
1189
1190
1191







-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+







    convertDouble 0x3dbc06d366394441
} {2.54901016865e-11}
test util-10.122 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x478f58ac4db68c90
} {5.20831059055e+36}

test util-11.1 {Tcl_PrintDouble - scaling} {
    expr 1.1e-5
    expr {1.1e-5}
} {1.1e-5}
test util-11.2 {Tcl_PrintDouble - scaling} {
    expr 1.1e-4
    expr {1.1e-4}
} {0.00011}
test util-11.3 {Tcl_PrintDouble - scaling} {
    expr 1.1e-3
    expr {1.1e-3}
} {0.0011}
test util-11.4 {Tcl_PrintDouble - scaling} {
    expr 1.1e-2
    expr {1.1e-2}
} {0.011}
test util-11.5 {Tcl_PrintDouble - scaling} {
    expr 1.1e-1
    expr {1.1e-1}
} {0.11}
test util-11.6 {Tcl_PrintDouble - scaling} {
    expr 1.1e0
    expr {1.1e0}
} {1.1}
test util-11.7 {Tcl_PrintDouble - scaling} {
    expr 1.1e1
    expr {1.1e1}
} {11.0}
test util-11.8 {Tcl_PrintDouble - scaling} {
    expr 1.1e2
    expr {1.1e2}
} {110.0}
test util-11.9 {Tcl_PrintDouble - scaling} {
    expr 1.1e3
    expr {1.1e3}
} {1100.0}
test util-11.10 {Tcl_PrintDouble - scaling} {
    expr 1.1e4
    expr {1.1e4}
} {11000.0}
test util-11.11 {Tcl_PrintDouble - scaling} {
    expr 1.1e5
    expr {1.1e5}
} {110000.0}
test util-11.12 {Tcl_PrintDouble - scaling} {
    expr 1.1e6
    expr {1.1e6}
} {1100000.0}
test util-11.13 {Tcl_PrintDouble - scaling} {
    expr 1.1e7
    expr {1.1e7}
} {11000000.0}
test util-11.14 {Tcl_PrintDouble - scaling} {
    expr 1.1e8
    expr {1.1e8}
} {110000000.0}
test util-11.15 {Tcl_PrintDouble - scaling} {
    expr 1.1e9
    expr {1.1e9}
} {1100000000.0}
test util-11.16 {Tcl_PrintDouble - scaling} {
    expr 1.1e10
    expr {1.1e10}
} {11000000000.0}
test util-11.17 {Tcl_PrintDouble - scaling} {
    expr 1.1e11
    expr {1.1e11}
} {110000000000.0}
test util-11.18 {Tcl_PrintDouble - scaling} {
    expr 1.1e12
    expr {1.1e12}
} {1100000000000.0}
test util-11.19 {Tcl_PrintDouble - scaling} {
    expr 1.1e13
    expr {1.1e13}
} {11000000000000.0}
test util-11.20 {Tcl_PrintDouble - scaling} {
    expr 1.1e14
    expr {1.1e14}
} {110000000000000.0}
test util-11.21 {Tcl_PrintDouble - scaling} {
    expr 1.1e15
    expr {1.1e15}
} {1100000000000000.0}
test util-11.22 {Tcl_PrintDouble - scaling} {
    expr 1.1e16
    expr {1.1e16}
} {11000000000000000.0}
test util-11.23 {Tcl_PrintDouble - scaling} {
    expr 1.1e17
    expr {1.1e17}
} {1.1e+17}

test util-12.1 {TclDoubleDigits - Inf} {testdoubledigits ieeeFloatingPoint} {
     testdoubledigits Inf -1 shortest
} {Infinity 9999 +}
test util-12.2 {TclDoubleDigits - -Inf} {testdoubledigits ieeeFloatingPoint} {
     testdoubledigits -Inf -1 shortest
1204
1205
1206
1207
1208
1209
1210
1211

1212
1213
1214
1215
1216
1217
1218

1219
1220
1221
1222
1223
1224
1225

1226
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
1354
1355
1356
1357
1358

1359
1360
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

1387
1388
1389
1390
1391
1392
1393

1394
1395
1396
1397
1398
1399
1400

1401
1402
1403
1404
1405
1406
1407

1408
1409
1410
1411
1412
1413
1414

1415
1416
1417
1418
1419
1420
1421

1422
1423
1424
1425
1426
1427
1428

1429
1430
1431
1432
1433
1434
1435

1436
1437
1438
1439
1440
1441
1442

1443
1444
1445
1446
1447
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

1478
1479
1480
1481
1482
1483
1484

1485
1486
1487
1488
1489
1490
1491

1492
1493
1494
1495
1496
1497
1498

1499
1500
1501
1502
1503
1504
1505

1506
1507
1508
1509
1510
1511
1512

1513
1514
1515
1516
1517
1518
1519

1520
1521
1522
1523
1524
1525
1526

1527
1528
1529
1530
1531
1532
1533

1534
1535
1536
1537
1538
1539
1540

1541
1542
1543
1544
1545
1546
1547

1548
1549
1550
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
1749
1750

1751
1752
1753
1754
1755
1756
1757

1758
1759
1760
1761
1762
1763
1764

1765
1766
1767
1768
1769
1770
1771

1772
1773
1774
1775
1776
1777
1778

1779
1780
1781
1782
1783
1784
1785

1786
1787
1788
1789
1790
1791
1792

1793
1794
1795
1796
1797
1798
1799

1800
1801
1802
1803
1804
1805
1806

1807
1808
1809
1810
1811
1812
1813
1814

1815
1816
1817
1818
1819
1820
1821

1822
1823
1824
1825
1826
1827
1828

1829
1830
1831
1832
1833
1834
1835

1836
1837
1838
1839
1840
1841
1842

1843
1844
1845
1846
1847
1848
1849

1850
1851
1852
1853
1854
1855
1856

1857
1858
1859
1860
1861
1862
1863

1864
1865
1866
1867
1868
1869
1870

1871
1872
1873
1874
1875
1876
1877

1878
1879
1880
1881
1882
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
1958
1959
1960
1961

1962
1963
1964
1965
1966
1967
1968

1969
1970
1971
1972
1973
1974
1975

1976
1977
1978
1979
1980
1981
1982

1983
1984
1985
1986
1987
1988
1989

1990
1991
1992
1993
1994
1995
1996

1997
1998
1999
2000
2001
2002
2003

2004
2005
2006
2007
2008
2009
2010

2011
2012
2013
2014
2015
2016
2017

2018
2019
2020
2021
2022
2023
2024

2025
2026
2027
2028
2029
2030
2031

2032
2033
2034
2035
2036
2037
2038

2039
2040
2041
2042
2043
2044
2045

2046
2047
2048
2049
2050
2051
2052
1208
1209
1210
1211
1212
1213
1214

1215
1216
1217
1218
1219
1220
1221

1222
1223
1224
1225
1226
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
1354

1355
1356
1357
1358
1359
1360
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
1387
1388
1389

1390
1391
1392
1393
1394
1395
1396

1397
1398
1399
1400
1401
1402
1403

1404
1405
1406
1407
1408
1409
1410

1411
1412
1413
1414
1415
1416
1417

1418
1419
1420
1421
1422
1423
1424

1425
1426
1427
1428
1429
1430
1431

1432
1433
1434
1435
1436
1437
1438

1439
1440
1441
1442
1443
1444
1445

1446
1447
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
1478
1479
1480

1481
1482
1483
1484
1485
1486
1487

1488
1489
1490
1491
1492
1493
1494

1495
1496
1497
1498
1499
1500
1501

1502
1503
1504
1505
1506
1507
1508

1509
1510
1511
1512
1513
1514
1515

1516
1517
1518
1519
1520
1521
1522

1523
1524
1525
1526
1527
1528
1529

1530
1531
1532
1533
1534
1535
1536

1537
1538
1539
1540
1541
1542
1543

1544
1545
1546
1547
1548
1549
1550

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
1749
1750
1751
1752
1753

1754
1755
1756
1757
1758
1759
1760

1761
1762
1763
1764
1765
1766
1767

1768
1769
1770
1771
1772
1773
1774

1775
1776
1777
1778
1779
1780
1781

1782
1783
1784
1785
1786
1787
1788

1789
1790
1791
1792
1793
1794
1795

1796
1797
1798
1799
1800
1801
1802

1803
1804
1805
1806
1807
1808
1809

1810
1811
1812
1813
1814
1815
1816
1817

1818
1819
1820
1821
1822
1823
1824

1825
1826
1827
1828
1829
1830
1831

1832
1833
1834
1835
1836
1837
1838

1839
1840
1841
1842
1843
1844
1845

1846
1847
1848
1849
1850
1851
1852

1853
1854
1855
1856
1857
1858
1859

1860
1861
1862
1863
1864
1865
1866

1867
1868
1869
1870
1871
1872
1873

1874
1875
1876
1877
1878
1879
1880

1881
1882
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

1958
1959
1960
1961
1962
1963
1964

1965
1966
1967
1968
1969
1970
1971

1972
1973
1974
1975
1976
1977
1978

1979
1980
1981
1982
1983
1984
1985

1986
1987
1988
1989
1990
1991
1992

1993
1994
1995
1996
1997
1998
1999

2000
2001
2002
2003
2004
2005
2006

2007
2008
2009
2010
2011
2012
2013

2014
2015
2016
2017
2018
2019
2020

2021
2022
2023
2024
2025
2026
2027

2028
2029
2030
2031
2032
2033
2034

2035
2036
2037
2038
2039
2040
2041

2042
2043
2044
2045
2046
2047
2048

2049
2050
2051
2052
2053
2054
2055
2056







-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+







-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+






-
+







} {0 0 -}

# Verdonk test vectors

test util-13.1 {just over exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1754e31cd072da E+1008 +4_000000000000000000& E+303
	verdonk_test 1754e31cd072da E+1008 +4_000000000000000000& E+303
    }
    -result {}
}
test util-13.2 {just over exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1afcef51f0fb5f E+265 -1_000000000000000000& E+80
	verdonk_test -1afcef51f0fb5f E+265 -1_000000000000000000& E+80
    }
    -result {}
}
test util-13.3 {just over exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1754e31cd072da E+1006 +1_000000000000000000& E+303
	verdonk_test 1754e31cd072da E+1006 +1_000000000000000000& E+303
    }
    -result {}
}
test util-13.4 {just over exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1754e31cd072da E+1007 -2_000000000000000000& E+303
	verdonk_test -1754e31cd072da E+1007 -2_000000000000000000& E+303
    }
    -result {}
}
test util-13.5 {just over exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1e07b27dd78b14 E-848 +1_00000000000000000& E-255
	verdonk_test 1e07b27dd78b14 E-848 +1_00000000000000000& E-255
    }
    -result {}
}
test util-13.6 {just over exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1e29e9c56687fe E-709 -7_00000000000000000& E-214
	verdonk_test -1e29e9c56687fe E-709 -7_00000000000000000& E-214
    }
    -result {}
}
test util-13.7 {just over exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1be03d0bf225c7 E-137 +1_00000000000000000& E-41
	verdonk_test 1be03d0bf225c7 E-137 +1_00000000000000000& E-41
    }
    -result {}
}
test util-13.8 {just over exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1a2fe76a3f9475 E-499 -1_00000000000000000& E-150
	verdonk_test -1a2fe76a3f9475 E-499 -1_00000000000000000& E-150
    }
    -result {}
}
test util-13.9 {just under exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 19a2028368022e E+1019 +8_999999999999999999& E+306
	verdonk_test 19a2028368022e E+1019 +8_999999999999999999& E+306
    }
    -result {}
}
test util-13.10 {just under exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1317e5ef3ab327 E+509 -1_999999999999999999& E+153
	verdonk_test -1317e5ef3ab327 E+509 -1_999999999999999999& E+153
    }
    -result {}
}
test util-13.11 {just under exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1317e5ef3ab327 E+510 +3_99999999999999999& E+153
	verdonk_test 1317e5ef3ab327 E+510 +3_99999999999999999& E+153
    }
    -result {}
}
test util-13.12 {just under exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1317e5ef3ab327 E+511 -7_99999999999999999& E+153
	verdonk_test -1317e5ef3ab327 E+511 -7_99999999999999999& E+153
    }
    -result {}
}
test util-13.13 {just under exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1eb8e84fa0b278 E-1008 +6_999999999999999999& E-304
	verdonk_test 1eb8e84fa0b278 E-1008 +6_999999999999999999& E-304
    }
    -result {}
}
test util-13.14 {just under exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -13339131c46f8b E-1004 -6_999999999999999999& E-303
	verdonk_test -13339131c46f8b E-1004 -6_999999999999999999& E-303
    }
    -result {}
}
test util-13.15 {just under exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1c0f92a6276c9d E-162 +2_999999999999999999& E-49
	verdonk_test 1c0f92a6276c9d E-162 +2_999999999999999999& E-49
    }
    -result {}
}
test util-13.16 {just under exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -15ce1f143d7ad2 E-443 -5_99999999999999999& E-134
	verdonk_test -15ce1f143d7ad2 E-443 -5_99999999999999999& E-134
    }
    -result {}
}
test util-13.17 {just over exact - 2 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1c0794d9d40e96 E-301 +43_000000000000000000& E-92
	verdonk_test 1c0794d9d40e96 E-301 +43_000000000000000000& E-92
    }
    -result {}
}
test util-13.18 {just over exact - 2 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1c0794d9d40e96 E-300 -86_000000000000000000& E-92
	verdonk_test -1c0794d9d40e96 E-300 -86_000000000000000000& E-92
    }
    -result {}
}
test util-13.19 {just over exact - 2 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1cd5bee57763e6 E-241 +51_000000000000000000& E-74
	verdonk_test 1cd5bee57763e6 E-241 +51_000000000000000000& E-74
    }
    -result {}
}
test util-13.20 {just under exact - 2 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1d1c26db7d0dae E+651 +16_999999999999999999& E+195
	verdonk_test 1d1c26db7d0dae E+651 +16_999999999999999999& E+195
    }
    -result {}
}
test util-13.21 {just under exact - 2 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -13f7ced916872b E-5 -38_999999999999999999& E-3
	verdonk_test -13f7ced916872b E-5 -38_999999999999999999& E-3
    }
    -result {}
}
test util-13.22 {just over exact - 3 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 17d93193f78fc6 E+588 +151_0000000000000000000& E+175
	verdonk_test 17d93193f78fc6 E+588 +151_0000000000000000000& E+175
    }
    -result {}
}
test util-13.23 {just over exact - 3 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1a82a1631eeb30 E-625 -119_000000000000000000& E-190
	verdonk_test -1a82a1631eeb30 E-625 -119_000000000000000000& E-190
    }
    -result {}
}
test util-13.24 {just under exact - 3 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -16c309024bab4b E+290 -282_999999999999999999& E+85
	verdonk_test -16c309024bab4b E+290 -282_999999999999999999& E+85
    }
    -result {}
}
test util-13.25 {just over exact - 8 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1dbbac6f83a821 E-800 +27869147_0000000000000000000& E-248
	verdonk_test 1dbbac6f83a821 E-800 +27869147_0000000000000000000& E-248
    }
    -result {}
}
test util-13.26 {just under exact - 9 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1c569e968e0944 E+430 -491080653_9999999999999999999& E+121
	verdonk_test -1c569e968e0944 E+430 -491080653_9999999999999999999& E+121
    }
    -result {}
}
test util-13.27 {just under exact - 9 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1c569e968e0944 E+429 +245540326_9999999999999999999& E+121
	verdonk_test 1c569e968e0944 E+429 +245540326_9999999999999999999& E+121
    }
    -result {}
}
test util-13.28 {just over exact - 10 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1fc575867314ee E-330 -9078555839_0000000000000000000& E-109
	verdonk_test -1fc575867314ee E-330 -9078555839_0000000000000000000& E-109
    }
    -result {}
}
test util-13.29 {just under exact - 10 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1c569e968e0944 E+428 -1227701634_9999999999999999999& E+120
	verdonk_test -1c569e968e0944 E+428 -1227701634_9999999999999999999& E+120
    }
    -result {}
}
test util-13.30 {just over exact - 11 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1fc575867314ee E-329 +18157111678_0000000000000000000& E-109
	verdonk_test 1fc575867314ee E-329 +18157111678_0000000000000000000& E-109
    }
    -result {}
}
test util-13.31 {just over exact - 14 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -18bf7e7fa6f02a E-196 -15400733123779_0000000000000000000& E-72
	verdonk_test -18bf7e7fa6f02a E-196 -15400733123779_0000000000000000000& E-72
    }
    -result {}
}
test util-13.32 {just over exact - 17 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -13de005bd620df E+217 -26153245263757307_0000000000000000000& E+49
	verdonk_test -13de005bd620df E+217 -26153245263757307_0000000000000000000& E+49
    }
    -result {}
}
test util-13.33 {just over exact - 18 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1f92bacb3cb40c E+718 +272104041512242479_0000000000000000000& E+199
	verdonk_test 1f92bacb3cb40c E+718 +272104041512242479_0000000000000000000& E+199
    }
    -result {}
}
test util-13.34 {just over exact - 18 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1f92bacb3cb40c E+719 -544208083024484958_0000000000000000000& E+199
	verdonk_test -1f92bacb3cb40c E+719 -544208083024484958_0000000000000000000& E+199
    }
    -result {}
}
test util-13.35 {just over half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 142dbf25096cf5 E+148 +4_500000000000000000& E+44
	verdonk_test 142dbf25096cf5 E+148 +4_500000000000000000& E+44
    }
    -result {}
}
test util-13.36 {just over half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1afcef51f0fb5f E+263 -2_500000000000000000& E+79
	verdonk_test -1afcef51f0fb5f E+263 -2_500000000000000000& E+79
    }
    -result {}
}
test util-13.37 {just over half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 102498ea6df0c4 E+145 +4_500000000000000000& E+43
	verdonk_test 102498ea6df0c4 E+145 +4_500000000000000000& E+43
    }
    -result {}
}
test util-13.38 {just over half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1754e31cd072da E+1004 -2_500000000000000000& E+302
	verdonk_test -1754e31cd072da E+1004 -2_500000000000000000& E+302
    }
    -result {}
}
test util-13.39 {just over half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 12deac01e2b4f7 E-557 +2_50000000000000000& E-168
	verdonk_test 12deac01e2b4f7 E-557 +2_50000000000000000& E-168
    }
    -result {}
}
test util-13.40 {just over half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1b1df536c13eee E-307 -6_50000000000000000& E-93
	verdonk_test -1b1df536c13eee E-307 -6_50000000000000000& E-93
    }
    -result {}
}
test util-13.41 {just over half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 10711fed5b19a4 E-154 +4_50000000000000000& E-47
	verdonk_test 10711fed5b19a4 E-154 +4_50000000000000000& E-47
    }
    -result {}
}
test util-13.42 {just over half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -148d67e8b1e00d E-151 -4_50000000000000000& E-46
	verdonk_test -148d67e8b1e00d E-151 -4_50000000000000000& E-46
    }
    -result {}
}
test util-13.43 {just under half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1c8c574c0c6be7 E+187 +3_49999999999999999& E+56
	verdonk_test 1c8c574c0c6be7 E+187 +3_49999999999999999& E+56
    }
    -result {}
}
test util-13.44 {just under half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1756183c147514 E+206 -1_49999999999999999& E+62
	verdonk_test -1756183c147514 E+206 -1_49999999999999999& E+62
    }
    -result {}
}
test util-13.45 {just under half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 12ab469676c410 E+203 +1_49999999999999999& E+61
	verdonk_test 12ab469676c410 E+203 +1_49999999999999999& E+61
    }
    -result {}
}
test util-13.46 {just under half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1539684e774b48 E+246 -1_49999999999999999& E+74
	verdonk_test -1539684e774b48 E+246 -1_49999999999999999& E+74
    }
    -result {}
}
test util-13.47 {just under half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 12e5f5dfa4fe9d E-286 +9_499999999999999999& E-87
	verdonk_test 12e5f5dfa4fe9d E-286 +9_499999999999999999& E-87
    }
    -result {}
}
test util-13.48 {just under half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1bdc2417bf7787 E-838 -9_499999999999999999& E-253
	verdonk_test -1bdc2417bf7787 E-838 -9_499999999999999999& E-253
    }
    -result {}
}
test util-13.49 {just under half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1eb8e84fa0b278 E-1009 +3_499999999999999999& E-304
	verdonk_test 1eb8e84fa0b278 E-1009 +3_499999999999999999& E-304
    }
    -result {}
}
test util-13.50 {just under half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1e3cbc9907fdc8 E-290 -9_499999999999999999& E-88
	verdonk_test -1e3cbc9907fdc8 E-290 -9_499999999999999999& E-88
    }
    -result {}
}
test util-13.51 {just over half ulp - 2 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 10ad836f269a17 E-324 +30_500000000000000000& E-99
	verdonk_test 10ad836f269a17 E-324 +30_500000000000000000& E-99
    }
    -result {}
}
test util-13.52 {just over half ulp - 2 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1b39ae1909c31b E-687 -26_500000000000000000& E-208
	verdonk_test -1b39ae1909c31b E-687 -26_500000000000000000& E-208
    }
    -result {}
}
test util-13.53 {just over half ulp - 3 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1b2ab18615fcc6 E-576 +686_500000000000000000& E-176
	verdonk_test 1b2ab18615fcc6 E-576 +686_500000000000000000& E-176
    }
    -result {}
}
test util-13.54 {just over half ulp - 3 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -13e1f90a573064 E-624 -178_500000000000000000& E-190
	verdonk_test -13e1f90a573064 E-624 -178_500000000000000000& E-190
    }
    -result {}
}
test util-13.55 {just under half ulp - 3 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 16c309024bab4b E+289 +141_499999999999999999& E+85
	verdonk_test 16c309024bab4b E+289 +141_499999999999999999& E+85
    }
    -result {}
}
test util-13.56 {just under half ulp - 4 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -159bd3ad46e346 E+193 -1695_499999999999999999& E+55
	verdonk_test -159bd3ad46e346 E+193 -1695_499999999999999999& E+55
    }
    -result {}
}
test util-13.57 {just under half ulp - 4 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1df4170f0fdecc E+124 +3981_499999999999999999& E+34
	verdonk_test 1df4170f0fdecc E+124 +3981_499999999999999999& E+34
    }
    -result {}
}
test util-13.58 {just over half ulp - 6 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 17e1e0f1c7a4ac E+415 +126300_5000000000000000000& E+120
	verdonk_test 17e1e0f1c7a4ac E+415 +126300_5000000000000000000& E+120
    }
    -result {}
}
test util-13.59 {just over half ulp - 6 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1dda592e398dd7 E+418 -126300_5000000000000000000& E+121
	verdonk_test -1dda592e398dd7 E+418 -126300_5000000000000000000& E+121
    }
    -result {}
}
test util-13.60 {just under half ulp - 7 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1e597c0b94b7ae E+453 -4411845_499999999999999999& E+130
	verdonk_test -1e597c0b94b7ae E+453 -4411845_499999999999999999& E+130
    }
    -result {}
}
test util-13.61 {just under half ulp - 9 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1c569e968e0944 E+427 +613850817_4999999999999999999& E+120
	verdonk_test 1c569e968e0944 E+427 +613850817_4999999999999999999& E+120
    }
    -result {}
}
test util-13.62 {just under half ulp - 9 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1c569e968e0944 E+428 -122770163_49999999999999999999& E+121
	verdonk_test -1c569e968e0944 E+428 -122770163_49999999999999999999& E+121
    }
    -result {}
}
test util-13.63 {just over half ulp - 18 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 17ae0c186d8709 E+719 +408156062268363718_5000000000000000000& E+199
	verdonk_test 17ae0c186d8709 E+719 +408156062268363718_5000000000000000000& E+199
    }
    -result {}
}
test util-13.64 {just over exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 152d02c7e14af7 E+76 +1_0000000000000000& E+23
	verdonk_test 152d02c7e14af7 E+76 +1_0000000000000000& E+23
    }
    -result {}
}
test util-13.65 {just over exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -19d971e4fe8402 E+89 -1_0000000000000000& E+27
	verdonk_test -19d971e4fe8402 E+89 -1_0000000000000000& E+27
    }
    -result {}
}
test util-13.66 {just over exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 19d971e4fe8402 E+90 +2_0000000000000000& E+27
	verdonk_test 19d971e4fe8402 E+90 +2_0000000000000000& E+27
    }
    -result {}
}
test util-13.67 {just over exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -19d971e4fe8402 E+91 -4_0000000000000000& E+27
	verdonk_test -19d971e4fe8402 E+91 -4_0000000000000000& E+27
    }
    -result {}
}
test util-13.68 {just over exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 15798ee2308c3a E-27 +1_0000000000000000& E-8
	verdonk_test 15798ee2308c3a E-27 +1_0000000000000000& E-8
    }
    -result {}
}
test util-13.69 {just over exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -15798ee2308c3a E-26 -2_0000000000000000& E-8
	verdonk_test -15798ee2308c3a E-26 -2_0000000000000000& E-8
    }
    -result {}
}
test util-13.70 {just over exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 15798ee2308c3a E-25 +4_0000000000000000& E-8
	verdonk_test 15798ee2308c3a E-25 +4_0000000000000000& E-8
    }
    -result {}
}
test util-13.71 {just over exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1ef2d0f5da7dd9 E-84 -1_0000000000000000& E-25
	verdonk_test -1ef2d0f5da7dd9 E-84 -1_0000000000000000& E-25
    }
    -result {}
}
test util-13.72 {just under exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1a784379d99db4 E+78 +4_9999999999999999& E+23
	verdonk_test 1a784379d99db4 E+78 +4_9999999999999999& E+23
    }
    -result {}
}
test util-13.73 {just under exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1a784379d99db4 E+80 -1_9999999999999999& E+24
	verdonk_test -1a784379d99db4 E+80 -1_9999999999999999& E+24
    }
    -result {}
}
test util-13.74 {just under exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 13da329b633647 E+81 +2_9999999999999999& E+24
	verdonk_test 13da329b633647 E+81 +2_9999999999999999& E+24
    }
    -result {}
}
test util-13.75 {just under exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1cf389cd46047d E+85 -6_9999999999999999& E+25
	verdonk_test -1cf389cd46047d E+85 -6_9999999999999999& E+25
    }
    -result {}
}
test util-13.76 {just under exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 19999999999999 E-3 +1_99999999999999999& E-1
	verdonk_test 19999999999999 E-3 +1_99999999999999999& E-1
    }
    -result {}
}
test util-13.77 {just under exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -13333333333333 E-2 -2_99999999999999999& E-1
	verdonk_test -13333333333333 E-2 -2_99999999999999999& E-1
    }
    -result {}
}
test util-13.78 {just under exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 16849b86a12b9b E-48 +4_99999999999999999& E-15
	verdonk_test 16849b86a12b9b E-48 +4_99999999999999999& E-15
    }
    -result {}
}
test util-13.79 {just under exact - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -16849b86a12b9b E-46 -1_99999999999999999& E-14
	verdonk_test -16849b86a12b9b E-46 -1_99999999999999999& E-14
    }
    -result {}
}
test util-13.80 {just over exact - 2 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 17ccfc73126788 E-71 +63_00000000000000000& E-23
	verdonk_test 17ccfc73126788 E-71 +63_00000000000000000& E-23
    }
    -result {}
}
test util-13.81 {just over exact - 2 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1dc03b8fd7016a E-68 -63_00000000000000000& E-22
	verdonk_test -1dc03b8fd7016a E-68 -63_00000000000000000& E-22
    }
    -result {}
}
test util-13.82 {just under exact - 2 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 13f7ced916872b E-5 +38_999999999999999999& E-3
	verdonk_test 13f7ced916872b E-5 +38_999999999999999999& E-3
    }
    -result {}
}
test util-13.83 {just over exact - 3 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1b297cad9f70b6 E+97 +269_000000000000000000& E+27
	verdonk_test 1b297cad9f70b6 E+97 +269_000000000000000000& E+27
    }
    -result {}
}
test util-13.84 {just over exact - 3 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1b297cad9f70b6 E+98 -538_00000000000000000& E+27
	verdonk_test -1b297cad9f70b6 E+98 -538_00000000000000000& E+27
    }
    -result {}
}
test util-13.85 {just over exact - 3 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1cdc06b20ef183 E-82 +373_00000000000000000& E-27
	verdonk_test 1cdc06b20ef183 E-82 +373_00000000000000000& E-27
    }
    -result {}
}
test util-13.86 {just over exact - 4 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1b297cad9f70b6 E+96 +1345_00000000000000000& E+26
	verdonk_test 1b297cad9f70b6 E+96 +1345_00000000000000000& E+26
    }
    -result {}
}
# this one is not 4 digits, it is 3, and it is covered above.
test util-13.87 {just over exact - 4 digits} {*}{
    -constraints {testdoubledigits knownBadTest}
    -body {
        verdonk_test -1b297cad9f70b6 E+97 -2690_00000000000000000& E+26
	verdonk_test -1b297cad9f70b6 E+97 -2690_00000000000000000& E+26
    }
    -result {}
}
test util-13.88 {just over exact - 5 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -150a246ecd44f3 E-63 -14257_00000000000000000& E-23
	verdonk_test -150a246ecd44f3 E-63 -14257_00000000000000000& E-23
    }
    -result {}
}
test util-13.89 {just under exact - 6 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -119b96f36ec68b E-19 -209900_999999999999999999& E-11
	verdonk_test -119b96f36ec68b E-19 -209900_999999999999999999& E-11
    }
    -result {}
}
test util-13.90 {just over exact - 11 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1c06d366394441 E-35 +50980203373_000000000000000000& E-21
	verdonk_test 1c06d366394441 E-35 +50980203373_000000000000000000& E-21
    }
    -result {}
}
test util-13.91 {just under exact - 12 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1f58ac4db68c90 E+122 -104166211810_99999999999999999& E+26
	verdonk_test -1f58ac4db68c90 E+122 -104166211810_99999999999999999& E+26
    }
    -result {}
}
test util-13.92 {just over half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 19d971e4fe8402 E+87 +2_5000000000000000& E+26
	verdonk_test 19d971e4fe8402 E+87 +2_5000000000000000& E+26
    }
    -result {}
}
test util-13.93 {just over half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1dc74be914d16b E+81 -4_500000000000000& E+24
	verdonk_test -1dc74be914d16b E+81 -4_500000000000000& E+24
    }
    -result {}
}
test util-13.94 {just over half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 14adf4b7320335 E+84 +2_500000000000000& E+25
	verdonk_test 14adf4b7320335 E+84 +2_500000000000000& E+25
    }
    -result {}
}
test util-13.95 {just over half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1ae22487c1042b E+85 -6_5000000000000000& E+25
	verdonk_test -1ae22487c1042b E+85 -6_5000000000000000& E+25
    }
    -result {}
}
test util-13.96 {just over half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 187fe49aab41e0 E-54 +8_5000000000000000& E-17
	verdonk_test 187fe49aab41e0 E-54 +8_5000000000000000& E-17
    }
    -result {}
}
test util-13.97 {just over half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1f5c05e4b23fd7 E-61 -8_5000000000000000& E-19
	verdonk_test -1f5c05e4b23fd7 E-61 -8_5000000000000000& E-19
    }
    -result {}
}
test util-13.98 {just over half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1faa7ab552a552 E-42 +4_5000000000000000& E-13
	verdonk_test 1faa7ab552a552 E-42 +4_5000000000000000& E-13
    }
    -result {}
}
test util-13.99 {just over half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1b7cdfd9d7bdbb E-36 -2_5000000000000000& E-11
	verdonk_test -1b7cdfd9d7bdbb E-36 -2_5000000000000000& E-11
    }
    -result {}
}
test util-13.100 {just under half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 13da329b633647 E+80 +1_4999999999999999& E+24
	verdonk_test 13da329b633647 E+80 +1_4999999999999999& E+24
    }
    -result {}
}
test util-13.101 {just under half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1cf389cd46047d E+84 -3_49999999999999999& E+25
	verdonk_test -1cf389cd46047d E+84 -3_49999999999999999& E+25
    }
    -result {}
}
test util-13.102 {just under half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1f04ef12cb04cf E+85 +7_4999999999999999& E+25
	verdonk_test 1f04ef12cb04cf E+85 +7_4999999999999999& E+25
    }
    -result {}
}
test util-13.103 {just under half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1f04ef12cb04cf E+86 -1_4999999999999999& E+26
	verdonk_test -1f04ef12cb04cf E+86 -1_4999999999999999& E+26
    }
    -result {}
}
test util-13.104 {just under half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 13333333333333 E-3 +1_49999999999999999& E-1
	verdonk_test 13333333333333 E-3 +1_49999999999999999& E-1
    }
    -result {}
}
test util-13.105 {just under half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -107e1fe91b0b70 E-36 -1_49999999999999999& E-11
	verdonk_test -107e1fe91b0b70 E-36 -1_49999999999999999& E-11
    }
    -result {}
}
test util-13.106 {just under half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 149da7e361ce4c E-33 +1_49999999999999999& E-10
	verdonk_test 149da7e361ce4c E-33 +1_49999999999999999& E-10
    }
    -result {}
}
test util-13.107 {just under half ulp - 1 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -19c511dc3a41df E-30 -1_49999999999999999& E-9
	verdonk_test -19c511dc3a41df E-30 -1_49999999999999999& E-9
    }
    -result {}
}
test util-13.108 {just over half ulp - 2 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1aa83d74267822 E+93 -16_5000000000000000& E+27
	verdonk_test -1aa83d74267822 E+93 -16_5000000000000000& E+27
    }
    -result {}
}
test util-13.109 {just over half ulp - 2 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 18f1d5969453de E+89 +96_5000000000000000& E+25
	verdonk_test 18f1d5969453de E+89 +96_5000000000000000& E+25
    }
    -result {}
}
test util-13.110 {just over half ulp - 2 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 11d9bd564dcda6 E-70 +94_50000000000000000& E-23
	verdonk_test 11d9bd564dcda6 E-70 +94_50000000000000000& E-23
    }
    -result {}
}
test util-13.111 {just over half ulp - 2 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1a58973ecbede6 E-48 -58_50000000000000000& E-16
	verdonk_test -1a58973ecbede6 E-48 -58_50000000000000000& E-16
    }
    -result {}
}
test util-13.112 {just over half ulp - 3 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1b297cad9f70b6 E+95 +672_50000000000000000& E+26
	verdonk_test 1b297cad9f70b6 E+95 +672_50000000000000000& E+26
    }
    -result {}
}
test util-13.113 {just over half ulp - 3 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -1b297cad9f70b6 E+96 -134_500000000000000000& E+27
	verdonk_test -1b297cad9f70b6 E+96 -134_500000000000000000& E+27
    }
    -result {}
}
test util-13.114 {just over half ulp - 3 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1cdc06b20ef183 E-83 +186_50000000000000000& E-27
	verdonk_test 1cdc06b20ef183 E-83 +186_50000000000000000& E-27
    }
    -result {}
}
test util-13.115 {just over half ulp - 3 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -136071dcae4565 E-47 -860_50000000000000000& E-17
	verdonk_test -136071dcae4565 E-47 -860_50000000000000000& E-17
    }
    -result {}
}
test util-13.116 {just over half ulp - 6 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1cb968d297dde8 E+99 +113788_50000000000000000& E+25
	verdonk_test 1cb968d297dde8 E+99 +113788_50000000000000000& E+25
    }
    -result {}
}
test util-13.117 {just over half ulp - 6 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test -11f3e1839eeab1 E+103 -113788_50000000000000000& E+26
	verdonk_test -11f3e1839eeab1 E+103 -113788_50000000000000000& E+26
    }
    -result {}
}
test util-13.118 {just under half ulp - 9 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1e9cec176c96f8 E+117 +317903333_49999999999999999& E+27
	verdonk_test 1e9cec176c96f8 E+117 +317903333_49999999999999999& E+27
    }
    -result {}
}
test util-13.119 {just over half ulp - 11 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1c06d366394441 E-36 +25490101686_500000000000000000& E-21
	verdonk_test 1c06d366394441 E-36 +25490101686_500000000000000000& E-21
    }
    -result {}
}
test util-13.120 {just under half ulp - 11 digits} {*}{
    -constraints testdoubledigits
    -body {
        verdonk_test 1f58ac4db68c90 E+121 +52083105905_49999999999999999& E+26
	verdonk_test 1f58ac4db68c90 E+121 +52083105905_49999999999999999& E+26
    }
    -result {}
}

test util-14.1 {funky NaN} {*}{
    -constraints {ieeeFloatingPoint controversialNaN}
    -body {
2159
2160
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
2222
2223
2224
2225
2226
2227
2228
2229








2230
2231
2232
2233
2234
2235
2236
2237
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
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







-
+

-
+















-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+













+
+
+
+
+
+
+
+








	0x1ffffffffffffd000
	0x1ffffffffffffd800
	0x1ffffffffffffe000
	0x1ffffffffffffe800
	0x1fffffffffffff000
	0x1fffffffffffff800
    } {
	binary scan [binary format q [expr double($input)]] wu x
	binary scan [binary format q [expr {double($input)}]] wu x
	lappend r [format %#llx $x]
	binary scan [binary format q [expr double(-$input)]] wu x
	binary scan [binary format q [expr {double(-$input)}]] wu x
	lappend r [format %#llx $x]
    }
    set r
} [list {*}{
    0x43fffffffffffffc 0xc3fffffffffffffc
    0x43fffffffffffffc 0xc3fffffffffffffc
    0x43fffffffffffffd 0xc3fffffffffffffd
    0x43fffffffffffffe 0xc3fffffffffffffe
    0x43fffffffffffffe 0xc3fffffffffffffe
    0x43fffffffffffffe 0xc3fffffffffffffe
    0x43ffffffffffffff 0xc3ffffffffffffff
    0x4400000000000000 0xc400000000000000
}]

test util-18.1 {Tcl_ObjPrintf} {testprint} {
    testprint %lld [expr 2**63-1]
    testprint %lld [expr {2**63-1}]
} {9223372036854775807}

test util-18.2 {Tcl_ObjPrintf} {testprint} {
    testprint %I64d [expr 2**63-1]
    testprint %I64d [expr {2**63-1}]
} {9223372036854775807}

test util-18.3 {Tcl_ObjPrintf} {testprint} {
    testprint %qd [expr 2**63-1]
    testprint %qd [expr {2**63-1}]
} {9223372036854775807}

test util-18.4 {Tcl_ObjPrintf} {testprint} {
    testprint %jd [expr 2**63-1]
    testprint %jd [expr {2**63-1}]
} {9223372036854775807}

test util-18.5 {Tcl_ObjPrintf} {testprint} {
    testprint %lld [expr -2**63]
    testprint %lld [expr {-2**63}]
} {-9223372036854775808}

test util-18.6 {Tcl_ObjPrintf} {testprint} {
    testprint %I64d [expr -2**63]
    testprint %I64d [expr {-2**63}]
} {-9223372036854775808}

test util-18.7 {Tcl_ObjPrintf} {testprint} {
    testprint %qd [expr -2**63]
    testprint %qd [expr {-2**63}]
} {-9223372036854775808}

test util-18.8 {Tcl_ObjPrintf} {testprint} {
    testprint %jd [expr -2**63]
    testprint %jd [expr {-2**63}]
} {-9223372036854775808}

test util-18.9 {Tcl_ObjPrintf} {testprint} {
    testprint "%I64d %I32d" [expr -2**63+2]
    testprint "%I64d %I32d" [expr {-2**63+2}]
} {-9223372036854775806 2}

test util-18.10 {Tcl_ObjPrintf} {testprint} {
    testprint "%I64d %p" 65535
} {65535 0xffff}

test util-18.11 {Tcl_ObjPrintf} {testprint} {
    testprint "%I64d %td" 65536
} {65536 65536}

test util-18.12 {Tcl_ObjPrintf} {testprint} {
    testprint "%I64d %Id" 65537
} {65537 65537}

test util-18.13 {Tcl_ObjPrintf} -constraints {testprint longIs64bit} -body {
    testprint "%llu %ju %lu" -1
} -result {18446744073709551615 18446744073709551615 18446744073709551615}

test util-18.14 {Tcl_ObjPrintf} -constraints {testprint longIs64bit} -body {
    testprint "%llu %zu %lu" -1
} -result {18446744073709551615 18446744073709551615 18446744073709551615}

# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/var.test.

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
30
31

32
33
34
35
36
37
38
39
40







41
42
43
44
45
46
47
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
30

31
32
33







34
35
36
37
38
39
40
41
42
43
44
45
46
47










-
-
+
+










-
+







-
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+







# This file contains tests for the tclVar.c source file. Tests appear in the
# same order as the C code that they test. The set of tests is currently
# incomplete since it currently includes only new tests for code changed for
# the addition of Tcl namespaces. Other variable-related tests appear in
# several other test files including namespace.test, set.test, trace.test, and
# upvar.test.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testupvar [llength [info commands testupvar]]
testConstraint testgetvarfullname [llength [info commands testgetvarfullname]]
testConstraint testsetnoerr [llength [info commands testsetnoerr]]
testConstraint memory [llength [info commands memory]]
if {[testConstraint memory]} {
    proc getbytes {} {
        return [lindex [split [memory info] \n] 3 3]
	return [lindex [split [memory info] \n] 3 3]
    }
    proc leaktest {script {iterations 3}} {
        set end [getbytes]
        for {set i 0} {$i < $iterations} {incr i} {
            uplevel 1 $script
            set tmp $end
            set end [getbytes]
        }
        return [expr {$end - $tmp}]
	set end [getbytes]
	for {set i 0} {$i < $iterations} {incr i} {
	    uplevel 1 $script
	    set tmp $end
	    set end [getbytes]
	}
	return [expr {$end - $tmp}]
    }
}


catch {rename p ""}
catch {namespace delete test_ns_var}
catch {unset xx}
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
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







-
-
-
-
+
+
+
+





-
-
-
-
+
+
+
+




















-
+






-
+





-
+




-
+





-
-
-
-
-
+
+
+
+
+




-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+









-
+








-
+




-
+


-
+














-
+














-
+







-
+




-
-
+
+


-
+

-
+




-
-
+
+


-
+











-
-
+
+





-
-
-
-
-
-
-
+
+
+
+
+
+
+







} -result {11 11 38 38}
set ::x "global value"
namespace eval test_ns_var {
    variable x "namespace value"
}
test var-1.2 {TclLookupVar, TCL_GLOBAL_ONLY implies global namespace var} {
    namespace eval test_ns_var {
        proc p {} {
            global x  ;# specifies TCL_GLOBAL_ONLY to get global x
            return $x
        }
	proc p {} {
	    global x  ;# specifies TCL_GLOBAL_ONLY to get global x
	    return $x
	}
    }
    test_ns_var::p
} {global value}
test var-1.3 {TclLookupVar, TCL_NAMESPACE_ONLY implies namespace var} {
    namespace eval test_ns_var {
        proc q {} {
            variable x  ;# specifies TCL_NAMESPACE_ONLY to get namespace x
            return $x
        }
	proc q {} {
	    variable x  ;# specifies TCL_NAMESPACE_ONLY to get namespace x
	    return $x
	}
    }
    test_ns_var::q
} {namespace value}
test var-1.4 {TclLookupVar, no active call frame implies global namespace var} {
    set x
} {global value}
test var-1.5 {TclLookupVar, active call frame pushed for namespace eval implies namespace var} {
    namespace eval test_ns_var {set x}
} {namespace value}
test var-1.6 {TclLookupVar, name starts with :: implies some namespace var} {
    namespace eval test_ns_var {set ::x}
} {global value}
test var-1.7 {TclLookupVar, error finding namespace var} -body {
    set a:::b
} -returnCodes error -result {can't read "a:::b": no such variable}
test var-1.8 {TclLookupVar, error finding namespace var} -body {
    set ::foobarfoo
} -returnCodes error -result {can't read "::foobarfoo": no such variable}
test var-1.9 {TclLookupVar, create new namespace var} {
    namespace eval test_ns_var {
        set v hello
	set v hello
    }
} {hello}
test var-1.10 {TclLookupVar, create new namespace var} -setup {
    catch {unset y}
} -body {
    namespace eval test_ns_var {
        set ::y 789
	set ::y 789
    }
    set y
} -result {789}
test var-1.11 {TclLookupVar, error creating new namespace var} -body {
    namespace eval test_ns_var {
        set ::test_ns_var::foo::bar 314159
	set ::test_ns_var::foo::bar 314159
    }
} -returnCodes error -result {can't set "::test_ns_var::foo::bar": parent namespace doesn't exist}
test var-1.12 {TclLookupVar, error creating new namespace var} -body {
    namespace eval test_ns_var {
        set ::test_ns_var::foo:: 1997
	set ::test_ns_var::foo:: 1997
    }
} -returnCodes error -result {can't set "::test_ns_var::foo::": parent namespace doesn't exist}
test var-1.13 {TclLookupVar, new namespace var is created in a particular namespace} {
    catch {unset aNeWnAmEiNnS}
    namespace eval test_ns_var {
        namespace eval test_ns_var2::test_ns_var3 {
            set aNeWnAmEiNnS 77777
        }
        # namespace which builds a name by traversing nsPtr chain to ::
        namespace which -variable test_ns_var2::test_ns_var3::aNeWnAmEiNnS
	namespace eval test_ns_var2::test_ns_var3 {
	    set aNeWnAmEiNnS 77777
	}
	# namespace which builds a name by traversing nsPtr chain to ::
	namespace which -variable test_ns_var2::test_ns_var3::aNeWnAmEiNnS
    }
} {::test_ns_var::test_ns_var2::test_ns_var3::aNeWnAmEiNnS}
test var-1.14 {TclLookupVar, namespace code ignores ":"s in middle and end of var names} {
    namespace eval test_ns_var {
        set : 123
        set v: 456
        set x:y: 789
        list [set :] [set v:] [set x:y:] \
             ${:} ${v:} ${x:y:} \
             [expr {":" in [info vars]}] \
             [expr {"v:" in [info vars]}] \
             [expr {"x:y:" in [info vars]}]
	set : 123
	set v: 456
	set x:y: 789
	list [set :] [set v:] [set x:y:] \
	     ${:} ${v:} ${x:y:} \
	     [expr {":" in [info vars]}] \
	     [expr {"v:" in [info vars]}] \
	     [expr {"x:y:" in [info vars]}]
    }
} {123 456 789 123 456 789 1 1 1}
test var-1.15 {TclLookupVar, resurrect variable via upvar to deleted namespace: compiled code path} {
    namespace eval test_ns_var {
	variable foo 2
    }
    proc p {} {
	variable ::test_ns_var::foo
	lappend result [catch {set foo} msg] $msg
        namespace delete ::test_ns_var
	namespace delete ::test_ns_var
	lappend result [catch {set foo 3} msg] $msg
	lappend result [catch {set foo(3) 3} msg] $msg
    }
    p
} {0 2 1 {can't set "foo": upvar refers to variable in deleted namespace} 1 {can't set "foo(3)": upvar refers to variable in deleted namespace}}
test var-1.16 {TclLookupVar, resurrect variable via upvar to deleted namespace: uncompiled code path} {
    namespace eval test_ns_var {
	variable result
        namespace eval subns {
	namespace eval subns {
	    variable foo 2
	}
	upvar 0 subns::foo foo
	lappend result [catch {set foo} msg] $msg
        namespace delete subns
	namespace delete subns
	lappend result [catch {set foo 3} msg] $msg
	lappend result [catch {set foo(3) 3} msg] $msg
        namespace delete [namespace current]
	namespace delete [namespace current]
	set result
    }
} {0 2 1 {can't set "foo": upvar refers to variable in deleted namespace} 1 {can't set "foo(3)": upvar refers to variable in deleted namespace}}
test var-1.17 {TclLookupVar, resurrect array element via upvar to deleted array: compiled code path} {
    namespace eval test_ns_var {
	variable result
	proc p {} {
	    array set x {1 2 3 4}
	    upvar 0 x(1) foo
	    lappend result [catch {set foo} msg] $msg
	    unset x
	    lappend result [catch {set foo 3} msg] $msg
	}
	set result [p]
        namespace delete [namespace current]
	namespace delete [namespace current]
	set result
    }
} {0 2 1 {can't set "foo": upvar refers to element in deleted array}}
test var-1.18 {TclLookupVar, resurrect array element via upvar to deleted array: uncompiled code path} -setup {
    unset -nocomplain test_ns_var::x
} -body {
    namespace eval test_ns_var {
	variable result {}
	variable x
	array set x {1 2 3 4}
	upvar 0 x(1) foo
	lappend result [catch {set foo} msg] $msg
	unset x
	lappend result [catch {set foo 3} msg] $msg
        namespace delete [namespace current]
	namespace delete [namespace current]
	set result
    }
} -result {0 2 1 {can't set "foo": upvar refers to element in deleted array}}
test var-1.19 {TclLookupVar, right error message when parsing variable name} -body {
    [format set] thisvar(doesntexist)
} -returnCodes error -result {can't read "thisvar(doesntexist)": no such variable}
test var-1.20 {TclLookupVar, regression on utf-8 variable names} -setup {
    proc p [list \u20ac \xe4] {info vars}
    proc p [list € ä] {info vars}
} -body {
    # test variable with non-ascii name is available (euro and a-uml chars here):
    list \
	[p 1 2] \
	[apply [list [list \u20ac \xe4] {info vars}] 1 2] \
	[apply [list [list [list \u20ac \u20ac] [list \xe4 \xe4]] {info vars}]] \
	[apply [list [list € ä] {info vars}] 1 2] \
	[apply [list [list [list € €] [list ä ä]] {info vars}]] \
} -cleanup {
    rename p {}
} -result [lrepeat 3 [list \u20ac \xe4]]
} -result [lrepeat 3 [list € ä]]
test var-1.21 {TclLookupVar, regression on utf-8 variable names} -setup {
    proc p [list [list \u20ac v\u20ac] [list \xe4 v\xe4]] {list [set \u20ac] [set \xe4]}
    proc p [list [list € v€] [list ä vä]] {list [set €] [set ä]}
} -body {
    # test variable with non-ascii name (and default) is resolvable (euro and a-uml chars here):
    list \
	[p] \
	[apply [list [list \u20ac \xe4] {list [set \u20ac] [set \xe4]}] v\u20ac v\xe4] \
	[apply [list [list [list \u20ac v\u20ac] [list \xe4 v\xe4]] {list [set \u20ac] [set \xe4]}]] \
	[apply [list [list € ä] {list [set €] [set ä]}] v€ vä] \
	[apply [list [list [list € v€] [list ä vä]] {list [set €] [set ä]}]] \
} -cleanup {
    rename p {}
} -result [lrepeat 3 [list v\u20ac v\xe4]]
} -result [lrepeat 3 [list v€ vä]]

test var-2.1 {Tcl_LappendObjCmd, create var if new} {
    catch {unset x}
    lappend x 1 2
} {1 2}

test var-3.1 {MakeUpvar, TCL_NAMESPACE_ONLY not specified for other var} -setup {
    catch {unset x}
} -body {
    set x 1997
    proc p {} {
        global x  ;# calls MakeUpvar with TCL_NAMESPACE_ONLY for other var x
        return $x
	global x  ;# calls MakeUpvar with TCL_NAMESPACE_ONLY for other var x
	return $x
    }
    p
} -result {1997}
test var-3.2 {MakeUpvar, other var has TCL_NAMESPACE_ONLY specified} {
    namespace eval test_ns_var {
        catch {unset v}
        variable v 1998
        proc p {} {
            variable v  ;# TCL_NAMESPACE_ONLY specified for other var x
            return $v
        }
        p
	catch {unset v}
	variable v 1998
	proc p {} {
	    variable v  ;# TCL_NAMESPACE_ONLY specified for other var x
	    return $v
	}
	p
    }
} {1998}
test var-3.3 {MakeUpvar, my var has TCL_GLOBAL_ONLY specified} -setup {
    catch {unset a}
} -constraints testupvar -body {
    set a 123321
    proc p {} {
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
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







-
-
+
+








-
+







    list [set xxxxx] [set aaaaa]
} -result {77777 77777}
test var-3.6 {MakeUpvar, active call frame pushed for namespace eval} -setup {
    catch {unset a}
} -body {
    set a 121212
    namespace eval test_ns_var {
        upvar ::a vvv
        set vvv
	upvar ::a vvv
	set vvv
    }
} -result {121212}
test var-3.7 {MakeUpvar, my var has ::s} -setup {
    catch {unset a}
} -body {
    set a 789789
    upvar #0 a test_ns_var::lnk
    namespace eval test_ns_var {
        set lnk
	set lnk
    }
} -result {789789}
test var-3.8 {MakeUpvar, my var already exists in global ns} -setup {
    upvar #0 aaaaa xxxxx
    catch {unset aaaaa}
    catch {unset xxxxx}
} -body {
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
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







-
-
+
+










-
+


-
-
+
+




-
-
-
-
-
-
-
+
+
+
+
+
+
+







-
-
+
+







    catch {unset a}
} -body {
    set a bar
    namespace which -variable a
} -result {::a}
test var-5.2 {Tcl_GetVariableFullName, namespace variable} {
    namespace eval test_ns_var {
        variable martha
        namespace which -variable martha
	variable martha
	namespace which -variable martha
    }
} {::test_ns_var::martha}
test var-5.3 {Tcl_GetVariableFullName, namespace variable} -setup {
    namespace eval test_ns_var {variable martha}
} -body {
    namespace which -variable test_ns_var::martha
} -result {::test_ns_var::martha}

test var-6.1 {Tcl_GlobalObjCmd, variable is qualified by a namespace name} {
    namespace eval test_ns_var {
        variable boeing 777
	variable boeing 777
    }
    apply {{} {
        global ::test_ns_var::boeing
        set boeing
	global ::test_ns_var::boeing
	set boeing
    }}
} {777}
test var-6.2 {Tcl_GlobalObjCmd, variable is qualified by a namespace name} {
    namespace eval test_ns_var {
        namespace eval test_ns_nested {
            variable java java
        }
        proc p {} {
            global ::test_ns_var::test_ns_nested::java
            set java
        }
	namespace eval test_ns_nested {
	    variable java java
	}
	proc p {} {
	    global ::test_ns_var::test_ns_nested::java
	    set java
	}
    }
    test_ns_var::p
} {java}
test var-6.3 {Tcl_GlobalObjCmd, variable named {} qualified by a namespace name} {
    namespace eval ::test_ns_var::test_ns_nested {}
    set ::test_ns_var::test_ns_nested:: 24
    apply {{} {
        global ::test_ns_var::test_ns_nested::
        set {}
	global ::test_ns_var::test_ns_nested::
	set {}
    }}
} {24}
test var-6.4 {Tcl_GlobalObjCmd, variable name matching :*} {
    # Test for Tcl Bug 480176
    set :v broken
    proc p {} {
	global :v
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
467
468


469
470
471

472
473
474
475
476
477
478
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
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


467
468
469
470

471
472
473
474
475
476
477
478
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







-
+






-
+








-
+


-
+






-
+


-
+










-
-
+
+


-
+








-
+







-
+





-
-
-
-
+
+
+
+








-
-
-
+
+
+



-
+







    p
} {}

test var-7.1 {Tcl_VariableObjCmd, create and initialize one new ns variable} -setup {
    catch {namespace delete test_ns_var}
} -body {
    namespace eval test_ns_var {
        variable one 1
	variable one 1
    }
    list [info vars test_ns_var::*] [set test_ns_var::one]
} -result {::test_ns_var::one 1}
test var-7.2 {Tcl_VariableObjCmd, if new and no value, leave undefined} {
    set two 2222222
    namespace eval test_ns_var {
        variable two
	variable two
    }
    list [info exists test_ns_var::two] [catch {set test_ns_var::two} msg] $msg
} {0 1 {can't read "test_ns_var::two": no such variable}}
test var-7.3 {Tcl_VariableObjCmd, "define" var already created above} -setup {
    catch {namespace delete test_ns_var}
    namespace eval test_ns_var {variable one 1}
} -body {
    namespace eval test_ns_var {
        variable two 2
	variable two 2
    }
    list [lsort [info vars test_ns_var::*]] \
         [namespace eval test_ns_var {set two}]
	 [namespace eval test_ns_var {set two}]
} -result [list [lsort {::test_ns_var::two ::test_ns_var::one}] 2]
test var-7.4 {Tcl_VariableObjCmd, list of vars} -setup {
    catch {namespace delete test_ns_var}
    namespace eval test_ns_var {variable one 1; variable two 2}
} -body {
    namespace eval test_ns_var {
        variable three 3 four 4
	variable three 3 four 4
    }
    list [lsort [info vars test_ns_var::*]] \
         [namespace eval test_ns_var {expr $three+$four}]
	 [namespace eval test_ns_var {expr {$three+$four}}]
} -result [list [lsort {::test_ns_var::four ::test_ns_var::three ::test_ns_var::two ::test_ns_var::one}] 7]
test var-7.5 {Tcl_VariableObjCmd, value for last var is optional} -setup {
    catch {unset a}
    catch {unset five}
    catch {unset six}
} -body {
    set a ""
    set five 555
    set six  666
    namespace eval test_ns_var {
        variable five 5 six
        lappend ::a $five
	variable five 5 six
	lappend ::a $five
    }
    lappend a $test_ns_var::five \
        [set test_ns_var::six 6] [set test_ns_var::six] $six
	[set test_ns_var::six 6] [set test_ns_var::six] $six
} -cleanup {
    catch {unset five}
    catch {unset six}
} -result {5 5 6 6 666}
test var-7.6 {Tcl_VariableObjCmd, variable name can be qualified} -setup {
    catch {unset newvar}
} -body {
    namespace eval test_ns_var {
        variable ::newvar cheers!
	variable ::newvar cheers!
    }
    return $newvar
} -cleanup {
    catch {unset newvar}
} -result {cheers!}
test var-7.7 {Tcl_VariableObjCmd, bad var name} -returnCodes error -body {
    namespace eval test_ns_var {
        variable sev:::en 7
	variable sev:::en 7
    }
} -result {can't define "sev:::en": parent namespace doesn't exist}
test var-7.8 {Tcl_VariableObjCmd, if var already exists and no value is given, leave value unchanged} {
    set a ""
    namespace eval test_ns_var {
        variable eight 8
        lappend ::a $eight
        variable eight
        lappend ::a $eight
	variable eight 8
	lappend ::a $eight
	variable eight
	lappend ::a $eight
    }
    set a
} {8 8}
test var-7.9 {Tcl_VariableObjCmd, mark as namespace var so var persists until namespace is destroyed or var is unset} -setup {
    catch {namespace delete test_ns_var2}
} -body {
    set a ""
    namespace eval test_ns_var2 {
        variable x 123
        variable y
        variable z
	variable x 123
	variable y
	variable z
    }
    lappend a [lsort [info vars test_ns_var2::*]]
    lappend a [info exists test_ns_var2::x] [info exists test_ns_var2::y] \
        [info exists test_ns_var2::z]
	[info exists test_ns_var2::z]
    lappend a [list [catch {set test_ns_var2::y} msg] $msg]
    lappend a [lsort [info vars test_ns_var2::*]]
    lappend a [info exists test_ns_var2::y] [info exists test_ns_var2::z]
    lappend a [set test_ns_var2::y hello]
    lappend a [info exists test_ns_var2::y] [info exists test_ns_var2::z]
    lappend a [list [catch {unset test_ns_var2::y} msg] $msg]
    lappend a [lsort [info vars test_ns_var2::*]]
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


558
559
560
561
562
563

564
565
566
567
568
569
570
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
558
559
560
561
562

563
564
565
566
567
568
569
570







-
-
-
-
-
+
+
+
+
+






-
-
+
+





-
+


-
-
+
+





-
+







	[lsort {::test_ns_var2::x ::test_ns_var2::z}] 0 0\
	{1 {can't unset "test_ns_var2::z": no such variable}}\
	{}]
test var-7.10 {Tcl_VariableObjCmd, variable cmd inside proc creates local link var} -setup {
    namespace eval test_ns_var { variable eight 8 }
} -body {
    namespace eval test_ns_var {
        proc p {} {
            variable eight
            list [set eight] [info vars]
        }
        p
	proc p {} {
	    variable eight
	    list [set eight] [info vars]
	}
	p
    }
} -result {8 eight}
test var-7.11 {Tcl_VariableObjCmd, variable cmd inside proc creates local link var} -setup {
    namespace eval test_ns_var { variable eight 8 }
} -body {
    proc p {} {   ;# note this proc is at global :: scope
        variable test_ns_var::eight
        list [set eight] [info vars]
	variable test_ns_var::eight
	list [set eight] [info vars]
    }
    p
} -result {8 eight}
test var-7.12 {Tcl_VariableObjCmd, variable cmd inside proc creates local link var} {
    namespace eval test_ns_var {
        variable {} {My name is empty}
	variable {} {My name is empty}
    }
    proc p {} {   ;# note this proc is at global :: scope
        variable test_ns_var::
        list [set {}] [info vars]
	variable test_ns_var::
	list [set {}] [info vars]
    }
    p
} {{My name is empty} {{}}}
test var-7.13 {Tcl_VariableObjCmd, variable named ":"} {
    namespace eval test_ns_var {
        variable : {My name is ":"}
	variable : {My name is ":"}
	proc p {} {
	    variable :
	    list [set :] [info vars]
	}
	p
    }
} {{My name is ":"} :}
588
589
590
591
592
593
594
595
596
597
598
599
600
601







602
603
604

605
606
607
608
609
610
611
612


613
614
615
616
617
618

619
620
621
622
623
624
625
626
627
628

629
630
631
632
633
634
635
588
589
590
591
592
593
594







595
596
597
598
599
600
601
602
603

604
605
606
607
608
609
610


611
612
613
614
615
616
617

618
619
620
621
622
623
624
625
626
627

628
629
630
631
632
633
634
635







-
-
-
-
-
-
-
+
+
+
+
+
+
+


-
+






-
-
+
+





-
+









-
+







} {}

test var-8.1 {TclDeleteVars, "unset" traces are called with fully-qualified var names} -setup {
    catch {namespace delete test_ns_var}
    catch {unset a}
} -body {
    namespace eval test_ns_var {
        variable v 123
        variable info ""
        proc traceUnset {name1 name2 op} {
            variable info
            set info [concat $info [list $name1 $name2 $op]]
        }
        trace var v u [namespace code traceUnset]
	variable v 123
	variable info ""
	proc traceUnset {name1 name2 op} {
	    variable info
	    set info [concat $info [list $name1 $name2 $op]]
	}
	trace add var v unset [namespace code traceUnset]
    }
    list [unset test_ns_var::v] $test_ns_var::info
} -result {{} {test_ns_var::v {} u}}
} -result {{} {test_ns_var::v {} unset}}
test var-8.2 {TclDeleteNamespaceVars, "unset" traces on ns delete are called with fully-qualified var names} -setup {
    catch {namespace delete test_ns_var}
    catch {unset a}
} -body {
    set info ""
    namespace eval test_ns_var {
        variable v 123 1
        trace var v u ::traceUnset
	variable v 123 1
	trace add var v unset ::traceUnset
    }
    proc traceUnset {name1 name2 op} {
	set ::info [concat $::info [list $name1 $name2 $op]]
    }
    list [namespace delete test_ns_var] $::info
} -result {{} {::test_ns_var::v {} u}}
} -result {{} {::test_ns_var::v {} unset}}

test var-8.3 {TclDeleteNamespaceVars, mem leak} -constraints memory -setup {
    proc ::t {a i o} {
	set $a 321
    }
} -body {
    leaktest {
	namespace eval n {
	    variable v 123
	    trace variable v u ::t
	    trace add variable v unset ::t
	}
	namespace delete n
    }
} -cleanup {
    rename ::t {}
} -result 0

700
701
702
703
704
705
706
707
708


709
710
711
712
713
714
715
716

717
718
719
720
721
722
723
724
725
726
727
728


729
730
731
732
733
734
735
736

737
738
739
740
741
742
743
700
701
702
703
704
705
706


707
708
709
710
711
712
713
714
715

716
717
718
719
720
721
722
723
724
725
726


727
728
729
730
731
732
733
734
735

736
737
738
739
740
741
742
743







-
-
+
+







-
+










-
-
+
+







-
+







} -result {1 {before set} 1 {can't set "arr": variable is array}}
test var-9.9 {behaviour of TclGetVar read trace success} -setup {
    catch {unset u}
    catch {unset v}
} -constraints testsetnoerr -body {
    proc resetvar {val name elem op} {upvar 1 $name v; set v $val}
    set u 10
    trace var u r [list resetvar 1]
    trace var v r [list resetvar 2]
    trace add var u read [list resetvar 1]
    trace add var v read [list resetvar 2]
    list \
	[testsetnoerr u] \
	[testseterr v]
} -result {{before get 1} {before get 2}}
test var-9.10 {behaviour of TclGetVar read trace error} testsetnoerr {
    proc writeonly args {error "write-only"}
    set v 456
    trace var v r writeonly
    trace add var v read writeonly
    list \
	[catch {testsetnoerr v} msg] $msg \
	[catch {testseterr v} msg] $msg
} {1 {before get} 1 {can't read "v": write-only}}
test var-9.11 {behaviour of TclSetVar write trace success} -setup {
    catch {unset u}
    catch {unset v}
} -constraints testsetnoerr -body {
    proc doubleval {name elem op} {upvar 1 $name v; set v [expr {2 * $v}]}
    set v 1
    trace var v w doubleval
    trace var u w doubleval
    trace add var v write doubleval
    trace add var u write doubleval
    list \
	[testsetnoerr u 2] \
	[testseterr v 3]
} -result {{before set 4} {before set 6}}
test var-9.12 {behaviour of TclSetVar write trace error} testsetnoerr {
    proc readonly args {error "read-only"}
    set v 456
    trace var v w readonly
    trace add var v write readonly
    list \
	[catch {testsetnoerr v 2} msg] $msg $v \
	[catch {testseterr v 3} msg] $msg $v
} {1 {before set} 2 1 {can't set "v": read-only} 3}

test var-10.1 {can't nest arrays with array set} -setup {
   catch {unset arr}
791
792
793
794
795
796
797
798

799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815

816
817
818
819
820
821
822
791
792
793
794
795
796
797

798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814

815
816
817
818
819
820
821
822







-
+
















-
+







} -body {
    proc foo {var ind op} {
	global t
	set foo bar
    }
    namespace eval :: {
	set t(1) 1
	trace variable t(1) u foo
	trace add variable t(1) unset foo
	unset t
    }
    set x "If you see this, it worked"
} -result "If you see this, it worked"
test var-13.2 {unset array with search, bug 46a2410650} -body {
    apply {{} {
	array set a {aa 11 bb 22 cc 33 dd 44 ee 55 ff 66}
	set s [array startsearch a]
	unset a([array nextelement a $s])
	array nextelement a $s
    }}
} -returnCodes error -result {couldn't find search "s-1-a"}
test var-13.3 {unset array with search, SIGSEGV, bug 46a2410650} -body {
    apply {{} {
	array set a {aa 11 bb 22 cc 33 dd 44 ee 55 ff 66}
	set s [array startsearch a]
        unset a(ff)
	unset a(ff)
	array nextelement a $s
    }}
} -returnCodes error -result {couldn't find search "s-1-a"}

test var-14.1 {array names syntax} -body {
    array names foo bar baz snafu
} -returnCodes 1 -match glob -result *
1006
1007
1008
1009
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
1006
1007
1008
1009
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







-
-
+
+



















-
-
+
+






-
+















-
-
+
+







} -result baz

test var-21.0 {PushVarNameWord OBOE in compiled unset} -setup {
    proc linenumber {} {dict get [info frame -1] line}
} -body {
    apply {n {
	set foo bar
        unset foo {*}{
        } [return [incr n -[linenumber]]]
	unset foo {*}{
	} [return [incr n -[linenumber]]]
    }} [linenumber]
} -cleanup {
    rename linenumber {}
} -result 1

test var-22.0 {leak in array element unset: Bug a3309d01db} -setup {
    proc doit k {
	variable A
	set A($k) {}
	foreach n [array names A] {
	    if {$n <= $k-1} {
		unset A($n)
	    }
	}
    }
} -constraints memory -body {
    set end [getbytes]
    for {set i 0} {$i < 5} {incr i} {
	doit $i
        set tmp $end
        set end [getbytes]
	set tmp $end
	set end [getbytes]
    }
    set leakedBytes [expr {$end - $tmp}]
} -cleanup {
    array unset A
    rename doit {}
} -result 0
test var-22.1 {leak in localVarName intrep: Bug 80304238ac} -setup {
test var-22.1 {leak in localVarName internalrep: Bug 80304238ac} -setup {
    proc doit {} {
	interp create child
	child eval {
	    proc doit script {
		eval $script
		set foo bar
	    }
	    doit {foreach foo baz {}}
	}
	interp delete child
    }
} -constraints memory -body {
    set end [getbytes]
    for {set i 0} {$i < 5} {incr i} {
	doit
        set tmp $end
        set end [getbytes]
	set tmp $end
	set end [getbytes]
    }
    set leakedBytes [expr {$end - $tmp}]
} -cleanup {
    array unset A
    rename doit {}
} -result 0
test var-22.2 {leak in parsedVarName} -constraints memory -body {
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102




1103
1104
1105
1106
1107
1108
1109
1092
1093
1094
1095
1096
1097
1098




1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109







-
-
-
-
+
+
+
+







} -returnCodes error -body {
    array for {k v} a {}
} -result {"a" isn't an array}
test var-23.6 {array command, for loop, array doesn't exist yet but has compiler-allocated procedure slot} -setup {
    catch {rename p ""}
} -returnCodes error -body {
    apply {{x} {
        if {$x==1} {
            return [array for {k v} a {}]
        }
        set a(x) 123
	if {$x==1} {
	    return [array for {k v} a {}]
	}
	set a(x) 123
    }} 1
} -result {"a" isn't an array}
test var-23.7 {array enumeration} -setup {
    unset -nocomplain a
    set reslist [list]
} -body {
    array set a {a 1 b 2 c 3}
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149




1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172




1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191



1192
1193
1194
1195
1196
1197
1198
1139
1140
1141
1142
1143
1144
1145




1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168




1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188



1189
1190
1191
1192
1193
1194
1195
1196
1197
1198







-
-
-
-
+
+
+
+



















-
-
-
-
+
+
+
+
















-
-
-
+
+
+







    unset -nocomplain a
    set reslist [list]
} -body {
    set retval {}
    try {
      array set a {a 1 b 2 c 3 d 4}
      array for {k v} a {
  	lappend reslist $k $v
          if { $k eq "a" } {
            unset a(c)
          }
	lappend reslist $k $v
	  if { $k eq "a" } {
	    unset a(c)
	  }
      }
      lsort -stride 2 -index 0 $reslist
    } on error {err res} {
      set retval [dict get $res -errorinfo]
    }
    set retval
} -cleanup {
    unset -nocomplain a
    unset -nocomplain reslist
    unset -nocomplain retval
} -result {array changed during iteration*}
test var-23.11 {array enumeration, insert key} -match glob -setup {
    unset -nocomplain a
    set reslist [list]
} -body {
    set retval {}
    try {
      array set a {a 1 b 2 c 3 d 4}
      array for {k v} a {
  	lappend reslist $k $v
          if { $k eq "a" } {
            set a(e) 5
          }
	lappend reslist $k $v
	  if { $k eq "a" } {
	    set a(e) 5
	  }
      }
      lsort -stride 2 -index 0 $reslist
    } on error {err res} {
      set retval [dict get $res -errorinfo]
    }
} -cleanup {
    unset -nocomplain a
    unset -nocomplain reslist
} -result {array changed during iteration*}
test var-23.12 {array enumeration, change value} -setup {
    unset -nocomplain a
    set reslist [list]
} -body {
    array set a {a 1 b 2 c 3}
    array for {k v} a {
	lappend reslist $k $v
        if { $k eq "a" } {
          set a(c) 9
        }
	if { $k eq "a" } {
	  set a(c) 9
	}
    }
    lsort -stride 2 -index 0 $reslist
} -cleanup {
    unset -nocomplain a
    unset -nocomplain reslist
} -result {a 1 b 2 c 9}
test var-23.13 {array enumeration, number of traces} -setup {
1476
1477
1478
1479
1480
1481
1482







































































































































































































































































































































































































































































































































































































































































































































































































1483
1484
1485
1486
1487
1488
1489
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







test var-24.24 {array default unset: errors} -setup {
    unset -nocomplain ary
} -body {
    array default unset ary x
} -returnCodes error -cleanup {
    unset -nocomplain ary
} -result * -match glob

# The const command
test var-25.1 {const: no argument} -body {
    apply {{} {
	const
	return $X
    }}
} -returnCodes error -result {wrong # args: should be "const varName value"}
test var-25.2 {const: single argument} -body {
    apply {{} {
	const X
	return $X
    }}
} -returnCodes error -result {wrong # args: should be "const varName value"}
test var-25.3 {const: two arguments (basic correct usage)} {
    apply {{} {
	set res [const X gorp]
	return [list $res $X]
    }}
} {{} gorp}
test var-25.4 {const: three arguments} -body {
    apply {{} {
	const X gorp foo
	return $X
    }}
} -returnCodes error -result {wrong # args: should be "const varName value"}
test var-25.5 {const: four arguments} -body {
    apply {{} {
	const X gorp foo bar
	return $X
    }}
} -returnCodes error -result {wrong # args: should be "const varName value"}

test var-26.1 {const: unmodifiable by set} -body {
    apply {{} {
	const X 123
	set X gorp
    }}
} -returnCodes error -result {can't set "X": variable is a constant}
test var-26.2 {const: unmodifiable by append} -body {
    apply {{} {
	const X 123
	append X gorp
    }}
} -returnCodes error -result {can't set "X": variable is a constant}
test var-26.3 {const: unmodifiable by lappend} -body {
    apply {{} {
	const X 123
	lappend X gorp
    }}
} -returnCodes error -result {can't set "X": variable is a constant}
test var-26.4 {const: unmodifiable by incr} -body {
    apply {{} {
	const X 123
	incr X
    }}
} -returnCodes error -result {can't incr "X": variable is a constant}
test var-26.5 {const: unmodifiable by dict set} -body {
    apply {{} {
	const X {a 123}
	dict set X a gorp
    }}
} -returnCodes error -result {can't set "X": variable is a constant}
test var-26.6 {const: unmodifiable by regsub} -body {
    apply {{} {
	const X abcabc
	regsub -all {a(.)} $X {\1\1} X
    }}
} -returnCodes error -result {can't set "X": variable is a constant}
test var-26.7 {const: unmodifiable by gets} -setup {
    set file [makeFile foo var26.7.txt]
    set f [open $file]
} -body {
    apply {f {
	const X abcabc
	gets $f X
    }} $f
} -returnCodes error -cleanup {
    close $f
    removeFile $file
} -result {can't set "X": variable is a constant}
test var-26.8 {const: may not be array} -body {
    apply {{} {
	array set X {a b}
	const X 1
	return $X
    }}
} -returnCodes error -result {can't make constant "X": variable is array}
test var-26.9.1 {const: may not be array element} -body {
    apply {{} {
	array set X {a b}
	const X(a) 1
	return $X(a)
    }}
} -returnCodes error -result {can't make constant "X(a)": name refers to an element in an array}
test var-26.9.2 {const: may not be array element} -body {
    apply {{} {
	array set X {a b}
	const X(b) 1
	return $X(b)
    }}
} -returnCodes error -result {can't make constant "X(b)": name refers to an element in an array}
test var-26.10.1 {const: unmodifiable by const but not an error} {
    apply {{} {
	const X 1
	const X 2
	return $X
    }}
} 1
test var-26.10.2 {const: unmodifiable by const but not an error} {
    apply {{} {
	lmap x {1 2 3} {
	    const A 2
	    const B 3
	    const C 5
	    expr {$A * $x**2 + $B * $x + $C}
	}
    }}
} {10 19 32}
test var-26.11 {const: may not be unset} -body {
   apply {{} {
	const X 1
	unset X
   }}
} -returnCodes error -result {can't unset "X": variable is a constant}
test var-26.12 {const: may not be unset, but -nocomplain doesn't complain} {
   apply {{} {
	const X 1
	unset -nocomplain X
	return $X
   }}
} 1
test var-26.13 {const and traces: write trace causes fail} -body {
    apply {{} {
	trace add variable X write {apply {args {
	    error "ERR: $args"
	}}}
	const X gorp
	return $X
    }}
} -returnCodes error -result {can't set "X": ERR: X {} write}
test var-26.14 {const and traces: write trace err causes no const} -body {
    apply {{} {
	set trace {apply {args {
	    error "ERR: $args"
	}}}
	trace add variable X write $trace
	catch {
	    const X gorp
	}
	trace remove variable X write $trace
	set X 123
	return $X
    }}
} -result 123
test var-26.15 {const and traces: read traces} -setup {
    unset -nocomplain traces
    set traces {}
} -body {
    apply {{} {
	trace add variable X read {apply {args {
	    lappend ::traces $args
	}}}
	const X gorp
	list $X $X $::traces
    }}
} -result {gorp gorp {{X {} read} {X {} read}}} -cleanup {
    unset -nocomplain traces
}
test var-26.16 {const and traces: write traces} -setup {
    unset -nocomplain traces
    set traces {}
} -body {
    apply {{} {
	trace add variable X write {apply {args {
	    lappend ::traces $args
	}}}
	const X gorp
	const X foo
	catch {set X bar}
	list $X $::traces
    }}
} -result {gorp {{X {} write}}} -cleanup {
    unset -nocomplain traces
}
test var-26.17 {const and traces: unset traces} -setup {
    unset -nocomplain traces
    set traces {}
} -body {
    list {*}[apply {{} {
	trace add variable X unset {apply {args {
	    lappend ::traces $args
	}}}
	const X gorp
	unset -nocomplain X
	list $X $::traces
    }}] $traces
} -result {gorp {} {{X {} unset}}} -cleanup {
    unset -nocomplain traces
}

# Same [const], but definitely not compiled
test var-27.1 {const: unmodifiable by set} -body {
    apply {const {
	$const X 123
	set X gorp
    }} const
} -returnCodes error -result {can't set "X": variable is a constant}
test var-27.2 {const: unmodifiable by append} -body {
    apply {const {
	$const X 123
	append X gorp
    }} const
} -returnCodes error -result {can't set "X": variable is a constant}
test var-27.3 {const: unmodifiable by lappend} -body {
    apply {const {
	$const X 123
	lappend X gorp
    }} const
} -returnCodes error -result {can't set "X": variable is a constant}
test var-27.4 {const: unmodifiable by incr} -body {
    apply {const {
	$const X 123
	incr X
    }} const
} -returnCodes error -result {can't incr "X": variable is a constant}
test var-27.5 {const: unmodifiable by dict set} -body {
    apply {const {
	$const X {a 123}
	dict set X a gorp
    }} const
} -returnCodes error -result {can't set "X": variable is a constant}
test var-27.6 {const: unmodifiable by regsub} -body {
    apply {const {
	$const X abcabc
	regsub -all {a(.)} $X {\1\1} X
    }} const
} -returnCodes error -result {can't set "X": variable is a constant}
test var-27.7 {const: unmodifiable by gets} -setup {
    set file [makeFile foo var27.7.txt]
    set f [open $file]
} -body {
    apply {{const f} {
	$const X abcabc
	gets $f X
    }} const $f
} -returnCodes error -cleanup {
    close $f
    removeFile $file
} -result {can't set "X": variable is a constant}
test var-27.8 {const: may not be array} -body {
    apply {const {
	array set X {a b}
	$const X 1
	return $X
    }} const
} -returnCodes error -result {can't make constant "X": variable is array}
test var-27.9.1 {const: may not be array element} -body {
    apply {const {
	array set X {a b}
	$const X(a) 1
	return $X(a)
    }} const
} -returnCodes error -result {can't make constant "X(a)": name refers to an element in an array}
test var-27.9.2 {const: may not be array element} -body {
    apply {const {
	array set X {a b}
	$const X(b) 1
	return $X(b)
    }} const
} -returnCodes error -result {can't make constant "X(b)": name refers to an element in an array}
test var-27.10.1 {const: unmodifiable by const but not an error} {
    apply {const {
	$const X 1
	$const X 2
	return $X
    }} const
} 1
test var-27.10.2 {const: unmodifiable by const but not an error} {
    apply {const {
	lmap x {1 2 3} {
	    $const A 2
	    $const B 3
	    $const C 5
	    expr {$A * $x**2 + $B * $x + $C}
	}
    }} const
} {10 19 32}
test var-27.11 {const: may not be unset} -body {
   apply {const {
	$const X 1
	unset X
   }} const
} -returnCodes error -result {can't unset "X": variable is a constant}
test var-27.12 {const: may not be unset, but -nocomplain doesn't complain} {
   apply {const {
	$const X 1
	unset -nocomplain X
	return $X
   }} const
} 1
test var-27.13 {const and traces: write trace causes fail} -body {
    apply {const {
	trace add variable X write {apply {args {
	    error "ERR: $args"
	}}}
	$const X gorp
	return $X
    }} const
} -returnCodes error -result {can't set "X": ERR: X {} write}
test var-27.14 {const and traces: write trace err causes no const} -body {
    apply {const {
	set trace {apply {args {
	    error "ERR: $args"
	}}}
	trace add variable X write $trace
	catch {
	    $const X gorp
	}
	trace remove variable X write $trace
	set X 123
	return $X
    }} const
} -result 123
test var-27.15 {const and traces: read traces} -setup {
    unset -nocomplain traces
    set traces {}
} -body {
    apply {const {
	trace add variable X read {apply {args {
	    lappend ::traces $args
	}}}
	$const X gorp
	list $X $X $::traces
    }} const
} -result {gorp gorp {{X {} read} {X {} read}}} -cleanup {
    unset -nocomplain traces
}
test var-27.16 {const and traces: write traces} -setup {
    unset -nocomplain traces
    set traces {}
} -body {
    apply {const {
	trace add variable X write {apply {args {
	    lappend ::traces $args
	}}}
	$const X gorp
	$const X foo
	catch {set X bar}
	list $X $::traces
    }} const
} -result {gorp {{X {} write}}} -cleanup {
    unset -nocomplain traces
}
test var-27.17 {const and traces: unset traces} -setup {
    unset -nocomplain traces
    set traces {}
} -body {
    list {*}[apply {const {
	trace add variable X unset {apply {args {
	    lappend ::traces $args
	}}}
	$const X gorp
	unset -nocomplain X
	list $X $::traces
    }} const] $traces
} -result {gorp {} {{X {} unset}}} -cleanup {
    unset -nocomplain traces
}

test var-28.1 {const: in a namespace} -setup {
    namespace eval var28 {}
} -body {
    namespace eval var28 {
	variable X
	const X gorp
	return $X
    }
} -cleanup {
    namespace delete var28
} -result gorp
test var-28.2 {const: in a namespace} -setup {
    namespace eval var28 {}
} -body {
    namespace eval var28 {
	variable X
	const X gorp
    }
    apply {{} {
	variable X
	set X 123
    } var28}
} -cleanup {
    namespace delete var28
} -returnCodes error -result {can't set "X": variable is a constant}
test var-28.3 {const: in a namespace} -setup {
    namespace eval var28 {}
} -body {
    namespace eval var28 {
	variable X
	const X gorp
    }
    apply {{} {
	variable X
	unset X
    } var28}
} -cleanup {
    namespace delete var28
} -returnCodes error -result {can't unset "X": variable is a constant}
test var-28.4 {const: in a namespace} -setup {
    namespace eval var28 {}
} -body {
    namespace eval var28 {
	variable X
	const X gorp
    }
    namespace delete var28
    namespace eval var28 {
	variable X abc
    }
    apply {{} {
	variable X
	return $X
    } var28}
} -cleanup {
    namespace delete var28
} -result abc
test var-28.5 {const: in a namespace, direct access from proc} -setup {
    namespace eval var28 {}
} -body {
    set result [apply {{} {
	const ::var28::X abc
	# Constant in namespace, NOT locally!
	info exists X
    }}]
    apply {res {
	variable X
	list $res [catch {unset X} msg] $msg $X
    } var28} $result
} -cleanup {
    namespace delete var28
} -result {0 1 {can't unset "X": variable is a constant} abc}

test var-29.1 {const: globally} -setup {
    set int [interp create]
} -body {
    $int eval {
	const X gorp
	apply {{} {
	    global X
	    return $X
	}}
    }
} -cleanup {
    interp delete $int
} -result gorp
test var-29.2 {const: TclOO variable resolution} -setup {
    oo::class create Parent
} -body {
    oo::class create C {
	superclass Parent
	variable X
	constructor {} {
	    const X 123
	}
	method checkRead {} {
	    return $X
	}
	method checkWrite {} {
	    list [catch {
		set X abc
	    } msg] $msg
	}
	method checkUnset {} {
	    list [catch {
		unset X
	    } msg] $msg
	}
	method checkProbe {} {
	    info constant X
	}
	method checkList {} {
	    info consts
	}
    }
    set c [C new]
    list [$c checkRead] [$c checkWrite] [$c checkUnset] [$c checkProbe] [$c checkList]
} -cleanup {
    Parent destroy
} -result {123 {1 {can't set "X": variable is a constant}} {1 {can't unset "X": variable is a constant}} 1 X}
test var-29.3 {const: TclOO variable resolution} -setup {
    oo::class create Parent
} -body {
    oo::class create C {
	superclass Parent
	private variable X
	constructor {} {
	    const X 123
	}
	method checkRead {} {
	    return $X
	}
	method checkWrite {} {
	    list [catch {
		set X abc
	    } msg] $msg
	}
	method checkUnset {} {
	    list [catch {
		unset X
	    } msg] $msg
	}
	method checkProbe {} {
	    info constant X
	}
	method checkList {} {
	    info consts
	}
    }
    set c [C new]
    list [$c checkRead] [$c checkWrite] [$c checkUnset] [$c checkProbe] [$c checkList]
} -cleanup {
    Parent destroy
} -result {123 {1 {can't set "X": variable is a constant}} {1 {can't unset "X": variable is a constant}} 1 X}
test var-29.4 {const: TclOO variable resolution} -setup {
    oo::class create Parent
} -body {
    oo::class create C {
	superclass Parent
	variable X
	constructor {} {
	    set X 123
	}
	method checkRead {} {
	    return $X
	}
	method checkWrite {} {
	    list [catch {
		set X abc
	    } msg] $msg
	}
	method checkUnset {} {
	    list [catch {
		unset X
		set X gorp
	    } msg] $msg
	}
	method checkProbe {} {
	    info constant X
	}
	method checkList {} {
	    info consts
	}
    }
    set c [C new]
    list [$c checkRead] [$c checkWrite] [$c checkUnset] [$c checkProbe] [$c checkList]
} -cleanup {
    Parent destroy
} -result {123 {0 abc} {0 gorp} 0 {}}
test var-29.5 {const: TclOO variable resolution} -setup {
    set c [oo::object create Instance]
} -body {
    oo::objdefine $c {
	variable X
	method init {} {
	    const X 123
	}
	method checkRead {} {
	    return $X
	}
	method checkWrite {} {
	    list [catch {
		set X abc
	    } msg] $msg
	}
	method checkUnset {} {
	    list [catch {
		unset X
	    } msg] $msg
	}
	method checkProbe {} {
	    info constant X
	}
	method checkList {} {
	    info consts
	}
    }
    $c init
    list [$c checkRead] [$c checkWrite] [$c checkUnset] [$c checkProbe] [$c checkList]
} -cleanup {
    Instance destroy
} -result {123 {1 {can't set "X": variable is a constant}} {1 {can't unset "X": variable is a constant}} 1 X}
test var-29.6 {const: TclOO variable resolution} -setup {
    set c [oo::object create Instance]
} -body {
    oo::objdefine $c {
	private variable X
	method init {} {
	    const X 123
	}
	method checkRead {} {
	    return $X
	}
	method checkWrite {} {
	    list [catch {
		set X abc
	    } msg] $msg
	}
	method checkUnset {} {
	    list [catch {
		unset X
	    } msg] $msg
	}
	method checkProbe {} {
	    info constant X
	}
	method checkList {} {
	    info consts
	}
    }
    $c init
    list [$c checkRead] [$c checkWrite] [$c checkUnset] [$c checkProbe] [$c checkList]
} -cleanup {
    Instance destroy
} -result {123 {1 {can't set "X": variable is a constant}} {1 {can't unset "X": variable is a constant}} 1 X}
test var-29.7 {const: TclOO variable resolution} -setup {
    set c [oo::object create Instance]
} -body {
    oo::objdefine $c {
	variable X
	method init {} {
	    set X 123
	}
	method checkRead {} {
	    return $X
	}
	method checkWrite {} {
	    list [catch {
		set X abc
	    } msg] $msg
	}
	method checkUnset {} {
	    list [catch {
		unset X
		set X gorp
	    } msg] $msg
	}
	method checkProbe {} {
	    info constant X
	}
	method checkList {} {
	    info consts
	}
    }
    $c init
    list [$c checkRead] [$c checkWrite] [$c checkUnset] [$c checkProbe] [$c checkList]
} -cleanup {
    Instance destroy
} -result {123 {0 abc} {0 gorp} 0 {}}

# The info constant and info consts commands
test var-30.1 {info constant and info consts} {
    apply {{} {
	lappend consts [lsort [info consts]] [info constant X]
	const X 1
	lappend consts [lsort [info consts]] [info constant X]
	const Y 2
	lappend consts [lsort [info consts]]
	const X 3
	lappend consts [lsort [info consts]]
    }}
} {{} 0 X 1 {X Y} {X Y}}
test var-30.2 {info constant and info consts} {
    apply {{} {
	lappend consts [lsort [info consts X]]
	const X 1
	lappend consts [lsort [info consts X]]
	const Y 2
	lappend consts [lsort [info consts X]]
	const X 3
	lappend consts [lsort [info consts X]]
    }}
} {{} X X X}
test var-30.3 {info constant and info consts} {
    apply {{} {
	lappend consts [lsort [info consts ?]]
	const X 1
	lappend consts [lsort [info consts ?]]
	const Y 2
	lappend consts [lsort [info consts ?]]
	const XX 3
	lappend consts [lsort [info consts ?]]
    }}
} {{} X {X Y} {X Y}}
test var-30.4 {info constant and info consts} {
    apply {{} {
	lappend consts [lsort [info consts X]]
	set X 1
	lappend consts [lsort [info consts X]]
	set Y 2
	lappend consts [lsort [info consts X]]
	set X 3
	lappend consts [lsort [info consts X]]
    }}
} {{} {} {} {}}
test var-30.5 {info consts: in a namespace} -setup {
    namespace eval var30 {}
} -body {
    namespace eval var30 {
	const X gorp
	info consts
    }
} -cleanup {
    namespace delete var30
} -result X
test var-30.6 {info consts: in a namespace} -setup {
    namespace eval var30 {}
} -body {
    namespace eval var30 {
	const X gorp
	variable Y foo
    }
    info consts var30::*
} -cleanup {
    namespace delete var30
} -result ::var30::X
test var-30.7 {info constant: bad constant names: array element} {
    apply {{} {
	info constant a(b)
    }}
} 0
test var-30.8 {info constant: bad constant names: array} {
    apply {{} {
	array set a {}
	info constant a
    }}
} 0
test var-30.9 {info constant: bad constant names: no var} {
    apply {{} {
	info constant a
    }}
} 0
test var-30.10 {info constant: bad constant names: no namespace} {
    apply {{} {
	info constant ::var29::no::such::ns::a
    }}
} 0
test var-30.11 {info constant: bad constant names: dangling upvar} {
    apply {{} {
	upvar 0 no_var a
	info constant a
    }}
} 0
test var-30.12 {info constant: bad constant names: bad name} {
    apply {{} {
	info constant a(b
    }}
} 0
test var-30.13 {info constant: bad constant names: nesting} {
    apply {{} {
	array set b {c d}
	upvar 0 b(c) a
	info constant a(d)
    }}
} 0

test var-31.1 {info constant: syntax} -returnCodes error -body {
    info constant
} -result {wrong # args: should be "info constant varName"}
test var-31.2 {info constant: syntax} -returnCodes error -body {
    info constant foo bar
} -result {wrong # args: should be "info constant varName"}
test var-31.3 {info consts: syntax} -returnCodes error -body {
    info consts foo bar
} -result {wrong # args: should be "info consts ?pattern?"}

catch {namespace delete ns}
catch {unset arr}
catch {unset v}

catch {rename getbytes ""}
catch {rename p ""}

Changes to tests/while-old.test.

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
30
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
30








-
-
-
+
+
+











-
+







# Commands covered:  while
#
# This file contains the original set of tests for Tcl's while command.
# Since the while command is now compiled, a new set of tests covering
# the new implementation is in the file "while.test". Sourcing this file
# into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1991-1993 The Regents of the University of California.
# Copyright © 1994-1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
}

test while-old-1.1 {basic while loops} {
    set count 0
    while {$count < 10} {set count [expr $count+1]}
    while {$count < 10} {set count [expr {$count + 1}]}
    set count
} 10
test while-old-1.2 {basic while loops} {
    set value xxx
    while {2 > 3} {set value yyy}
    set value
} xxx
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
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







-
-
+
+














-
+

-
+











-
+



















-
+







    }
    set value
} 6
test while-old-1.4 {basic while loops, multiline test expr} {
    set value 1
    while {($tcl_platform(platform) != "foobar1") && \
	    ($tcl_platform(platform) != "foobar2")} {
        incr value
        break
	incr value
	break
    }
    set value
} {2}
test while-old-1.5 {basic while loops, test expr in quotes} {
    set value 1
    while "0 < 3" {set value 2; break}
    set value
} {2}

test while-old-2.1 {continue in while loop} {
    set list {1 2 3 4 5}
    set index 0
    set result {}
    while {$index < 5} {
	if {$index == 2} {set index [expr $index+1]; continue}
	if {$index == 2} {set index [expr {$index + 1}]; continue}
	set result [concat $result [lindex $list $index]]
	set index [expr $index+1]
	set index [expr {$index + 1}]
    }
    set result
} {1 2 4 5}

test while-old-3.1 {break in while loop} {
    set list {1 2 3 4 5}
    set index 0
    set result {}
    while {$index < 5} {
	if {$index == 3} break
	set result [concat $result [lindex $list $index]]
	set index [expr $index+1]
	set index [expr {$index + 1}]
    }
    set result
} {1 2 3}

test while-old-4.1 {errors in while loops} {
    set err [catch {while} msg]
    list $err $msg
} {1 {wrong # args: should be "while test command"}}
test while-old-4.2 {errors in while loops} {
    set err [catch {while 1} msg]
    list $err $msg
} {1 {wrong # args: should be "while test command"}}
test while-old-4.3 {errors in while loops} {
    set err [catch {while 1 2 3} msg]
    list $err $msg
} {1 {wrong # args: should be "while test command"}}
test while-old-4.4 {errors in while loops} {
    set err [catch {while {"a"+"b"} {error "loop aborted"}} msg]
    list $err $msg
} {1 {can't use non-numeric string "a" as operand of "+"}}
} {1 {cannot use non-numeric string "a" as left operand of "+"}}
test while-old-4.5 {errors in while loops} {
    catch {unset x}
    set x 1
    set err [catch {while {$x} {set x foo}} msg]
    list $err $msg
} {1 {expected boolean value but got "foo"}}
test while-old-4.6 {errors in while loops} {

Changes to tests/while.test.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







# Commands covered:  while
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands.  Sourcing this file into Tcl runs the tests and generates output
# for errors.  No output means no errors were found.
#
# Copyright (c) 1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
28
29
30
31
32
33
34
35

36
37
38
39
40
41


42
43
44
45
46
47
48
28
29
30
31
32
33
34

35
36
37
38
39


40
41
42
43
44
45
46
47
48







-
+




-
-
+
+







    catch {while {$i<} break}
    return $::errorInfo
} -cleanup {
    unset i
} -match glob -result {*"while {$i<} break"}
test while-1.3 {TclCompileWhileCmd: error in test expression} -body {
    while {"a"+"b"} {error "loop aborted"}
} -returnCodes error -result {can't use non-numeric string "a" as operand of "+"}
} -returnCodes error -result {cannot use non-numeric string "a" as left operand of "+"}
test while-1.4 {TclCompileWhileCmd: multiline test expr} -body {
    set value 1
    while {($tcl_platform(platform) != "foobar1") && \
	    ($tcl_platform(platform) != "foobar2")} {
        incr value
        break
	incr value
	break
    }
    return $value
} -cleanup {
    unset value
} -result {2}
test while-1.5 {TclCompileWhileCmd: non-numeric boolean test expr} -body {
    set value 1
73
74
75
76
77
78
79
80

81
82

83
84
85
86
87
88
89
73
74
75
76
77
78
79

80
81

82
83
84
85
86
87
88
89







-
+

-
+







} -result {wrong # args: should be "set varName ?newValue?"
    while *ing
"set"*}
test while-1.9 {TclCompileWhileCmd: simple command body} -body {
    set a {}
    set i 1
    while {$i<6} {
	if $i==4 break
	if {$i==4} break
	set a [concat $a $i]
        incr i
	incr i
    }
    return $a
} -cleanup {
    unset a i
} -result {1 2 3}
test while-1.10 {TclCompileWhileCmd: command body in quotes} -body {
    set a {}
108
109
110
111
112
113
114
115
116


117
118
119
120
121
122
123
108
109
110
111
112
113
114


115
116
117
118
119
120
121
122
123







-
-
+
+







} -cleanup {
    unset x1 bb x2 a i
} -result {x1}
test while-1.12 {TclCompileWhileCmd: long command body} -body {
    set a {}
    set i 1
    while {$i<6} {
	if $i==4 break
	if $i>5 continue
	if {$i==4} break
	if {$i>5} continue
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
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
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







-
+














-
+











-
+











-
+











-
-
+
+

-
-
-
-
+
+
+
+









-
-
-
+
+
+







	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	set a [concat $a $i]
        incr i
	incr i
    }
    return $a
} -cleanup {
    unset a i
} -result {1 2 3}
test while-1.13 {TclCompileWhileCmd: while command result} -body {
    set i 0
    set a [while {$i < 5} {incr i}]
    return $a
} -cleanup {
    unset a i
} -result {}
test while-1.14 {TclCompileWhileCmd: while command result} -body {
    set i 0
    set a [while {$i < 5} {if $i==3 break; incr i}]
    set a [while {$i < 5} {if {$i==3} break; incr i}]
    return $a
} -cleanup {
    unset a i
} -result {}

# Check "while" and "continue".

test while-2.1 {continue tests} -body {
    set a {}
    set i 1
    while {$i <= 4} {
        incr i
	incr i
	if {$i == 3} continue
	set a [concat $a $i]
    }
    return $a
} -cleanup {
    unset a i
} -result {2 4 5}
test while-2.2 {continue tests} -body {
    set a {}
    set i 1
    while {$i <= 4} {
        incr i
	incr i
	if {$i != 2} continue
	set a [concat $a $i]
    }
    return $a
} -cleanup {
    unset a i
} -result {2}
test while-2.3 {continue tests, nested loops} -body {
    set msg {}
    set i 1
    while {$i <= 4} {
        incr i
        set a 1
	incr i
	set a 1
	while {$a <= 2} {
            incr a
            if {$i>=3 && $a>=3} continue
            set msg [concat $msg "$i.$a"]
        }
	    incr a
	    if {$i>=3 && $a>=3} continue
	    set msg [concat $msg "$i.$a"]
	}
    }
    return $msg
} -cleanup {
    unset a i msg
} -result {2.2 2.3 3.2 4.2 5.2}
test while-2.4 {continue tests, long command body} -body {
    set a {}
    set i 1
    while {$i<6} {
	if $i==2 {incr i; continue}
	if $i==4 break
	if $i>5 continue
	if {$i==2} {incr i; continue}
	if {$i==4} break
	if {$i>5} continue
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
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
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







-
+














-
+









-
+

-
-
-
-
-
+
+
+
+
+









-
-
-
+
+
+















-
+











-
+












-
+







	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	set a [concat $a $i]
        incr i
	incr i
    }
    return $a
} -cleanup {
    unset a i
} -result {1 3}

# Check "while" and "break".

test while-3.1 {break tests} -body {
    set a {}
    set i 1
    while {$i <= 4} {
	if {$i == 3} break
	set a [concat $a $i]
        incr i
	incr i
    }
    return $a
} -cleanup {
    unset a i
} -result {1 2}
test while-3.2 {break tests, nested loops} -body {
    set msg {}
    set i 1
    while {$i <= 4} {
        set a 1
	set a 1
	while {$a <= 2} {
            if {$i>=2 && $a>=2} break
            set msg [concat $msg "$i.$a"]
            incr a
        }
        incr i
	    if {$i>=2 && $a>=2} break
	    set msg [concat $msg "$i.$a"]
	    incr a
	}
	incr i
    }
    return $msg
} -cleanup {
    unset a i msg
} -result {1.1 1.2 2.1 3.1 4.1}
test while-3.3 {break tests, long command body} -body {
    set a {}
    set i 1
    while {$i<6} {
	if $i==2 {incr i; continue}
	if $i==5 break
	if $i>5 continue
	if {$i==2} {incr i; continue}
	if {$i==5} break
	if {$i>5} continue
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	if $i==4 break
	if {$i==4} break
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	set a [concat $a $i]
        incr i
	incr i
    }
    return $a
} -cleanup {
    unset a i
} -result {1 3}

# Check "while" with computed command names.

test while-4.1 {while and computed command names} -body {
    set i 0
    set z while
    $z {$i < 10} {
        incr i
	incr i
    }
    return $i
} -cleanup {
    unset i z
} -result 10
test while-4.2 {while (not compiled): missing test expression} -body {
    set z while
339
340
341
342
343
344
345
346

347
348
349
350
351
352
353


354
355
356
357
358
359
360
339
340
341
342
343
344
345

346
347
348
349
350
351


352
353
354
355
356
357
358
359
360







-
+





-
-
+
+







    return $::errorInfo
} -match glob -cleanup {
    unset i z
} -result {*"$z {$i<} {set x 1}"}
test while-4.4 {while (not compiled): error in test expression} -body {
    set z while
    $z {"a"+"b"} {error "loop aborted"}
} -returnCodes error -result {can't use non-numeric string "a" as operand of "+"}
} -returnCodes error -result {cannot use non-numeric string "a" as left operand of "+"}
test while-4.5 {while (not compiled): multiline test expr} -body {
    set value 1
    set z while
    $z {($tcl_platform(platform) != "foobar1") && \
	    ($tcl_platform(platform) != "foobar2")} {
        incr value
        break
	incr value
	break
    }
    return $value
} -cleanup {
    unset value z
} -result {2}
test while-4.6 {while (not compiled): non-numeric boolean test expr} -body {
    set value 1
397
398
399
400
401
402
403
404

405
406

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

404
405

406
407
408
409
410
411
412
413







-
+

-
+







    invoked from within
"$z {$i < 5} {set}"}
test while-4.10 {while (not compiled): simple command body} -body {
    set a {}
    set i 1
    set z while
    $z {$i<6} {
	if $i==4 break
	if {$i==4} break
	set a [concat $a $i]
        incr i
	incr i
    }
    return $a
} -cleanup {
    unset a i z
} -result {1 2 3}
test while-4.11 {while (not compiled): command body in quotes} -body {
    set a {}
435
436
437
438
439
440
441
442
443


444
445
446
447
448
449
450
435
436
437
438
439
440
441


442
443
444
445
446
447
448
449
450







-
-
+
+







    unset z x1 bb x2 a i
} -result {x1}
test while-4.13 {while (not compiled): long command body} -body {
    set a {}
    set z while
    set i 1
    $z {$i<6} {
	if $i==4 break
	if $i>5 continue
	if {$i==4} break
	if {$i>5} continue
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
463
464
465
466
467
468
469
470

471
472
473
474
475
476
477
478
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
558
559

560
561
562
563
564
565
566
567
568
569
570
571

572
573
574
575
576
577
578
579
580
581
582
583
584
585
586



587
588
589
590
591
592
593
594
595
596
597

598
599
600
601
602
603
604
605
606
607
608
609
610

611
612
613
614
615
616
617
618
619
620
621
622
623
624


625
626
627
628
629




630
631
632
633
634
635
636
637
638
639
640
641
642



643
644
645
646
647
648
649
463
464
465
466
467
468
469

470
471
472
473
474
475
476
477
478
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
558

559
560
561
562
563
564
565
566
567
568
569
570

571
572
573
574
575
576
577
578
579
580
581
582
583



584
585
586
587
588
589
590
591
592
593
594
595
596

597
598
599
600
601
602
603
604
605
606
607
608
609

610
611
612
613
614
615
616
617
618
619
620
621
622


623
624
625




626
627
628
629
630
631
632
633
634
635
636
637
638
639



640
641
642
643
644
645
646
647
648
649







-
+
















-
+











-
-
+
+












-
+










-
+

-
-
-
-
-
+
+
+
+
+










-
-
-
+
+
+















-
+











-
+












-
-
-
+
+
+










-
+












-
+












-
-
+
+

-
-
-
-
+
+
+
+










-
-
-
+
+
+







	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	set a [concat $a $i]
        incr i
	incr i
    }
    return $a
} -cleanup {
    unset a i z
} -result {1 2 3}
test while-4.14 {while (not compiled): while command result} -body {
    set i 0
    set z while
    set a [$z {$i < 5} {incr i}]
    return $a
} -cleanup {
    unset a i z
} -result {}
test while-4.15 {while (not compiled): while command result} -body {
    set i 0
    set z while
    set a [$z {$i < 5} {if $i==3 break; incr i}]
    set a [$z {$i < 5} {if {$i==3} break; incr i}]
    return $a
} -cleanup {
    unset a i z
} -result {}

# Check "break" with computed command names.

test while-5.1 {break and computed command names} -body {
    set i 0
    set z break
    while 1 {
        if {$i > 10} $z
        incr i
	if {$i > 10} $z
	incr i
    }
    return $i
} -cleanup {
    unset i z
} -result 11
test while-5.2 {break tests with computed command names} -body {
    set a {}
    set i 1
    set z break
    while {$i <= 4} {
	if {$i == 3} $z
	set a [concat $a $i]
        incr i
	incr i
    }
    return $a
} -cleanup {
    unset a i z
} -result {1 2}
test while-5.3 {break tests, nested loops with computed command names} -body {
    set msg {}
    set i 1
    set z break
    while {$i <= 4} {
        set a 1
	set a 1
	while {$a <= 2} {
            if {$i>=2 && $a>=2} $z
            set msg [concat $msg "$i.$a"]
            incr a
        }
        incr i
	    if {$i>=2 && $a>=2} $z
	    set msg [concat $msg "$i.$a"]
	    incr a
	}
	incr i
    }
    return $msg
} -cleanup {
    unset a i z msg
} -result {1.1 1.2 2.1 3.1 4.1}
test while-5.4 {break tests, long command body with computed command names} -body {
    set a {}
    set i 1
    set z break
    while {$i<6} {
	if $i==2 {incr i; continue}
	if $i==5 $z
	if $i>5 continue
	if {$i==2} {incr i; continue}
	if {$i==5} $z
	if {$i>5} continue
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	if $i==4 $z
	if {$i==4} $z
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	set a [concat $a $i]
        incr i
	incr i
    }
    return $a
} -cleanup {
    unset a i z
} -result {1 3}

# Check "continue" with computed command names.

test while-6.1 {continue and computed command names} -body {
    set i 0
    set z continue
    while 1 {
        incr i
        if {$i < 10} $z
        break
	incr i
	if {$i < 10} $z
	break
    }
    return $i
} -cleanup {
    unset i z
} -result 10
test while-6.2 {continue tests} -body {
    set a {}
    set i 1
    set z continue
    while {$i <= 4} {
        incr i
	incr i
	if {$i == 3} $z
	set a [concat $a $i]
    }
    return $a
} -cleanup {
    unset a i z
} -result {2 4 5}
test while-6.3 {continue tests with computed command names} -body {
    set a {}
    set i 1
    set z continue
    while {$i <= 4} {
        incr i
	incr i
	if {$i != 2} $z
	set a [concat $a $i]
    }
    return $a
} -cleanup {
    unset a i z
} -result {2}
test while-6.4 {continue tests, nested loops with computed command names} -body {
    set msg {}
    set i 1
    set z continue
    while {$i <= 4} {
        incr i
        set a 1
	incr i
	set a 1
	while {$a <= 2} {
            incr a
            if {$i>=3 && $a>=3} $z
            set msg [concat $msg "$i.$a"]
        }
	    incr a
	    if {$i>=3 && $a>=3} $z
	    set msg [concat $msg "$i.$a"]
	}
    }
    return $msg
} -cleanup {
    unset a i z msg
} -result {2.2 2.3 3.2 4.2 5.2}
test while-6.5 {continue tests, long command body with computed command names} -body {
    set a {}
    set i 1
    set z continue
    while {$i<6} {
	if $i==2 {incr i; continue}
	if $i==4 break
	if $i>5 $z
	if {$i==2} {incr i; continue}
	if {$i==4} break
	if {$i>5} $z
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
662
663
664
665
666
667
668
669

670
671
672
673
674
675
676
662
663
664
665
666
667
668

669
670
671
672
673
674
675
676







-
+







	}
	if {$i>6 && $tcl_platform(machine)=="xxx"} {
	    catch {set a $a} msg
	    catch {incr i 5} msg
	    catch {incr i -5} msg
	}
	set a [concat $a $i]
        incr i
	incr i
    }
    return $a
} -cleanup {
    unset a i z
} -result {1 3}

# Test for incorrect "double evaluation" semantics

Changes to tests/winConsole.test.

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
30
31
32

























33




34
35
36
37





















38





39

















40

41








42



















































































































































































































































43




44






45
46
47
48
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
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
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






-
+
+









+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+


-
+
-


+
+
-
-
+
+
+
+
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+

+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
-
+
+
+
+
+
+




# This file tests the tclWinConsole.c file.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1999 by Scriptics Corporation.
# NOTE THIS CANNOT BE RUN VIA nmake/make test since stdin is connected to
# nmake in that case.
#
# 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::*
}

catch {package require twapi} ;# Only to bring window to foreground. Not critical
::tcltest::ConstraintInitializer haveThread { expr {![catch {package require Thread}]} }

# Prompt user for a yes/no response
proc yesno {question {default "Y"}} {
    set answer ""
    # Make sure we are seen but catch because ui and console
    # packages may not be available
    catch {twapi::set_foreground_window [twapi::get_console_window]}
    while {![string is boolean -strict $answer]} {
	puts -nonewline stdout "$question Type Y/N followed by Enter \[$default\] : "
	flush stdout
	set answer [string trim [gets stdin]]
	if {$answer eq ""} {
	    set answer $default
	}
    }
    return [expr {!! $answer}]
}

proc prompt {prompt} {
    # Make sure we are seen but catch because twapi ui and console
    # packages may not be available
    catch {twapi::set_foreground_window [twapi::get_console_window]}
    puts -nonewline stdout "$prompt"
    flush stdout
}

# Input tests

test console-input-1.0 {Console blocking gets} -constraints {win interactive} -body {
    prompt "Type \"xyz\" and hit Enter: "
    gets stdin
} -result xyz

test winConsole-1.1 {Console file channel: non-blocking gets} {win interactive} {
test console-input-1.1 {Console file channel: non-blocking gets} -constraints {
    win interactive
} -setup {
    unset -nocomplain result
    unset -nocomplain result2
} -body {
    set oldmode [fconfigure stdin]

    puts stdout "Enter abcdef<return> now: " nonewline
    prompt "Type \"abc\" and hit Enter: "
    flush stdout
    fileevent stdin readable {
	if {[gets stdin line] >= 0} {
	    lappend result2 $line
	    if {[llength $result2] > 1} {
	    set result $line
	} else {
		set result $result2
	    } else {
		prompt "Type \"def\" and hit Enter: "
	    }
	} elseif {[eof stdin]} {
	    set result "gets failed"
	}
    }

    fconfigure stdin -blocking 0 -buffering line

    vwait result

    #cleanup the fileevent
    fileevent stdin readable {}
    fconfigure stdin {*}$oldmode
    set result

} -result {abc def}

test console-input-1.1.1 {Bug baa51423c28a: Console file channel: fileevent with blocking gets} -constraints {
    win interactive
} -setup {
    unset -nocomplain result
    unset -nocomplain result2
} -body {
    prompt "Type \"abc\" and hit Enter: "
    fileevent stdin readable {
	if {[gets stdin line] >= 0} {
	    lappend result2 $line
	    if {[llength $result2] > 1} {
		set result $result2
	    } else {
		prompt "Type \"def\" and hit Enter: "
	    }
	} elseif {[eof stdin]} {
    set result {}
	    set result "gets failed"
	}
    }

    vwait result

    #cleanup the fileevent
    fileevent stdin readable {}
    set result

} -result {abc def}

test console-input-2.0 {Console blocking read} -constraints {win interactive} -setup {
    set oldmode [fconfigure stdin]
    fconfigure stdin -inputmode raw
} -cleanup {
    fconfigure stdin {*}$oldmode
} -body {
    prompt "Type the key \"a\". Do NOT hit Enter. You will NOT see characters echoed."
    set c [read stdin 1]
    puts ""
    set c
} -result a

test console-input-2.1 {Console file channel: non-blocking read} -constraints {
    win interactive
} -setup {
    set oldmode [fconfigure stdin]
} -cleanup {
    fconfigure stdin {*}$oldmode
    puts ""; # Because CRLF also would not have been echoed
} -body {
    set input ""
    fconfigure stdin -blocking 0 -buffering line -inputmode raw
    prompt "Type \"abc\". Do NOT hit Enter. You will NOT see characters echoed."

    fileevent stdin readable {
	set c [read stdin 1]
	if {$c eq ""} {
	    if {[eof stdin]} {
		set result "read eof"
	    }
	} else {
	    append input $c
	    if {[string length $input] == 3} {
		set result $input
	    }
	}
    }

    set result {}
    vwait result
    fileevent stdin readable {}
    set result
} -result abc

test console-input-3.0 {Console gets blocking - long lines bug-bda99f2393} -constraints {
    win interactive
} -body {
    prompt "Try typing a line of at least 256 characters. Hit ENTER exactly once unless you don't see another prompt.\n"
    gets stdin line
    set len [string length $line]
    list [yesno "Did you hit ENTER only once?"] [expr {$len > 256}] [yesno "Line length was $len characters. Is this correct?"]
} -result {1 1 1}
}  "abcdef"

test console-input-3.1 {Console gets blocking, small channel buffer size - long lines bug-bda99f2393} -constraints {
    win interactive
} -body {
    prompt "Try typing a line of at least 256 characters. Hit ENTER exactly once unless you don't see another prompt.\n"
    set bufSize [fconfigure stdin -buffersize]
    fconfigure stdin -buffersize 10
    gets stdin line
    fconfigure stdin -buffersize $bufSize
    set len [string length $line]
    list [yesno "Did you hit ENTER only once?"] [expr {$len > 256}] [yesno "Line length was $len characters. Is this correct?"]
} -result {1 1 1}

test console-input-3.2 {Console gets nonblocking - long lines bug-bda99f2393} -constraints {
    win interactive
} -body {
    prompt "Try typing a line of at least 256 characters. Hit ENTER exactly once unless you don't see another prompt.\n"
    fconfigure stdin -blocking 0
    while {[gets stdin line] < 0} {
	after 1000
    }
    fconfigure stdin -blocking 1
    set len [string length $line]
    list [yesno "Did you hit ENTER only once?"] [expr {$len > 256}] [yesno "Line length was $len characters. Is this correct?"]
} -result {1 1 1}

test console-input-3.3 {Console gets nonblocking small channel buffer size - long lines bug-bda99f2393} -constraints {
    win interactive
} -body {
    prompt "Try typing a line of at least 256 characters. Hit ENTER exactly once unless you don't see another prompt.\n"
    set bufSize [fconfigure stdin -buffersize]
    fconfigure stdin -blocking 0 -buffersize 10
    while {[gets stdin line] < 0} {
	after 1000
    }
    fconfigure stdin -blocking 1 -buffersize $bufSize
    set len [string length $line]
    list [yesno "Did you hit ENTER only once?"] [expr {$len > 256}] [yesno "Line length was $len characters. Is this correct?"]
} -result {1 1 1}

# Output tests

test console-output-1.0 {Console blocking puts stdout} -constraints {win interactive} -body {
    puts stdout "123"
    yesno "Did you see the string \"123\"?"
} -result 1

test console-output-1.1 {Console non-blocking puts stdout} -constraints {
    win interactive
} -setup {
    set oldmode [fconfigure stdout]
    dict unset oldmode -winsize
} -cleanup {
    fconfigure stdout {*}$oldmode
} -body {
    fconfigure stdout -blocking 0 -buffering line
    set count 0
    fileevent stdout writable {
	if {[incr count] < 4} {
	    puts "$count"
	} else {
	    fileevent stdout writable {}
	    set done 1
	}
    }
    vwait done
    yesno "Did you see 1, 2, 3 printed on consecutive lines?"
} -result 1

test console-output-2.0 {Console blocking puts stderr} -constraints {win interactive} -body {
    puts stderr "456"
    yesno "Did you see the string \"456\"?"
} -result 1


# fconfigure get tests

## fconfigure get stdin

test console-fconfigure-get-1.0 {
    Console get stdin configuration
} -constraints {win interactive} -body {
    lsort [dict keys [fconfigure stdin]]
} -result {-blocking -buffering -buffersize -encoding -eofchar -inputmode -profile -translation}

set testnum 0
foreach {opt result} {
    -blocking 1
    -buffering line
    -buffersize 4096
    -encoding utf-16
    -inputmode normal
    -translation auto
} {
    test console-fconfigure-get-1.[incr testnum] "Console get stdin option $opt" \
	-constraints {win interactive} -body {
	fconfigure stdin $opt
    } -result $result
}
test console-fconfigure-get-1.[incr testnum] {
    Console get stdin option -eofchar
} -constraints {win interactive} -body {
    fconfigure stdin -eofchar
} -result ""

test console-fconfigure-get-1.[incr testnum] {
    fconfigure -winsize
} -constraints {win interactive} -body {
    fconfigure stdin -winsize
} -result {bad option "-winsize": should be one of -blocking, -buffering, -buffersize, -encoding, -eofchar, -profile, -translation, or -inputmode} -returnCodes error

## fconfigure get stdout/stderr
foreach chan {stdout stderr} major {2 3} {
    test console-fconfigure-get-$major.0 "Console get $chan configuration" -constraints {
	win interactive
    } -body {
	lsort [dict keys [fconfigure $chan]]
    } -result {-blocking -buffering -buffersize -encoding -eofchar -profile -translation -winsize}
    set testnum 0
    foreach {opt result} {
	-blocking 1
	-buffersize 4096
	-encoding utf-16
	-translation crlf
    } {
	test console-fconfigure-get-$major.[incr testnum] "Console get $chan option $opt" \
	    -constraints {win interactive} -body {
		fconfigure $chan $opt
	    } -result $result
    }

    test console-fconfigure-get-$major.[incr testnum] "Console get $chan option -winsize" \
	-constraints {win interactive} -body {
	fconfigure $chan -winsize
    } -result {\d+ \d+} -match regexp

    test console-fconfigure-get-$major.[incr testnum] "Console get $chan option -buffering" \
	-constraints {win interactive} -body {
	fconfigure $chan -buffering
    } -result [expr {$chan eq "stdout" ? "line" : "none"}]

    test console-fconfigure-get-$major.[incr testnum] {
	fconfigure -inputmode
    } -constraints {win interactive} -body {
	fconfigure $chan -inputmode
    } -result {bad option "-inputmode": should be one of -blocking, -buffering, -buffersize, -encoding, -eofchar, -profile, -translation, or -winsize} -returnCodes error

}

## fconfigure set stdin

test console-fconfigure-set-1.0 {
    fconfigure -inputmode password
} -constraints {win interactive} -body {
    set result {}

    prompt "Type \"pass\" and hit Enter. You should NOT see characters echoed: "
    fconfigure stdin -inputmode password
    lappend result [gets stdin]
    lappend result [fconfigure stdin -inputmode]
    fconfigure stdin -inputmode normal
    lappend result [yesno "\nWere the characters echoed?"]

    prompt "Type \"norm\" and hit Enter. You should see characters echoed: "
    lappend result [gets stdin]
    lappend result [fconfigure stdin -inputmode]
    lappend result [yesno "Were the characters echoed?"]

    set result
} -result [list pass password 0 norm normal 1]

test console-fconfigure-set-1.1 {
    fconfigure -inputmode raw
} -constraints {win interactive} -body {
    set result {}

    prompt "Type the keys \"a\", Ctrl-H, \"b\". Do NOT hit Enter. You should NOT see characters echoed: "
    fconfigure stdin -inputmode raw
    lappend result [read stdin 3]
    lappend result [fconfigure stdin -inputmode]
    fconfigure stdin -inputmode normal
    lappend result [yesno "\nWere the characters echoed?"]

    prompt "Type the keys \"c\", Ctrl-H, \"d\" and hit Enter. You should see characters echoed: "
    lappend result [gets stdin]
    lappend result [fconfigure stdin -inputmode]
    lappend result [yesno "Were the characters echoed (c replaced by d)?"]

    set result
} -result [list a\x08b raw 0 d normal 1]

test console-fconfigure-set-1.2 {
    fconfigure -inputmode reset
} -constraints {win interactive} -body {
    set result {}

    prompt "Type \"pass\" and hit Enter. You should NOT see characters echoed: "
    fconfigure stdin -inputmode password
    lappend result [gets stdin]
    lappend result [fconfigure stdin -inputmode]
    fconfigure stdin -inputmode reset
    lappend result [yesno "\nWere the characters echoed?"]

    prompt "Type \"reset\" and hit Enter. You should see characters echoed: "
    lappend result [gets stdin]
    lappend result [fconfigure stdin -inputmode]
    lappend result [yesno "Were the characters echoed?"]

    set result
} -result [list pass password 0 reset normal 1]

test console-fconfigure-set-1.3 {
    fconfigure stdin -winsize
} -constraints {win interactive} -body {
    fconfigure stdin -winsize {10 30}
} -result {bad option "-winsize": should be one of -blocking, -buffering, -buffersize, -encoding, -eofchar, -profile, -translation, or -inputmode} -returnCodes error

## fconfigure set stdout,stderr

test console-fconfigure-set-2.0 {
    fconfigure stdout -winsize
} -constraints {win interactive} -body {
    fconfigure stdout -winsize {10 30}
} -result {bad option "-winsize": should be one of -blocking, -buffering, -buffersize, -encoding, -eofchar, -profile, or -translation} -returnCodes error

test console-fconfigure-set-3.0 {
    fconfigure stderr -winsize
} -constraints {win interactive} -body {
    fconfigure stderr -winsize {10 30}
} -result {bad option "-winsize": should be one of -blocking, -buffering, -buffersize, -encoding, -eofchar, -profile, or -translation} -returnCodes error

# Multiple threads

test console-thread-input-1.0 {Get input in thread} -constraints {
    win interactive haveThread
} -setup {
    set tid [thread::create]
} -cleanup {
    thread::release $tid
} -body {
    prompt "Type \"xyz\" and hit Enter: "
    thread::send $tid {gets stdin}
} -result xyz

test console-thread-output-1.0 {Output from thread} -constraints {
    win interactive haveThread
} -setup {
    set tid [thread::create]
#cleanup
} -cleanup {
    thread::release $tid
} -body {
    thread::send $tid {puts [thread::id]}
    yesno "Did you see $tid printed?"
} -result 1

::tcltest::cleanupTests
return

Changes to tests/winDde.test.

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
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
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
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






-
+








+

-




-
-
+
+



-
+












+

-
+

-
-
+
+





-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
+
+

-
+












-
+







-
+






-
+







-
+



-
+





-
-
-
+
+
+


-
-
+
+

-
+


-
-
-
+
+
+


-
-
+
+


-
-
-
+
+
+

-
+


-
-
-
+
+
+

-
-
+
+

-
-
-
+
+
+


-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+




-
+


-
+


-
+


-
+


-
+



-
+


-
+


-
-
+
+


-
+


-
+


-
+


-
+


-
+


-
-
+
+


-
+







# This file tests the tclWinDde.c file.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors. No output means no errors were found.
#
# Copyright (c) 1999 by Scriptics Corporation.
# Copyright © 1999 Scriptics Corporation.
#
# 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::*
}
source [file join [file dirname [info script]] tcltests.tcl]

testConstraint debug [::tcl::pkgconfig get debug]
testConstraint dde 0
if {[testConstraint win]} {
    if {![catch {
	    ::tcltest::loadTestedCommands
	    set ::ddever [package require dde 1.4.3]
	    set ::ddelib [lindex [package ifneeded dde $::ddever] 1]}]} {
	    set ::ddever [package require dde 1.4.5]
	    set ::ddelib [info loaded {} Dde]}]} {
	testConstraint dde 1
    }
}
testConstraint notWine [expr {$::tcl_platform(platform) ne "windows" || ![info exists ::env(TRAVIS_OS_NAME)] || ![string match linux $::env(TRAVIS_OS_NAME)]}]
testConstraint notWine [expr {![info exists ::env(CI_USING_WINE)]}]


# -------------------------------------------------------------------------
# Setup a script for a test server
#

set scriptName [makeFile {} script1.tcl]

proc createChildProcess {ddeServerName args} {
    file delete -force $::scriptName

    set f [open $::scriptName w+]
    fconfigure $f -encoding utf-8
    puts $f [list set ddeServerName $ddeServerName]
    puts $f [list load $::ddelib dde]
    puts $f [list load $::ddelib Dde]
    puts $f {
        # DDE child server -
        #
	# DDE child server -
	#
	if {"::tcltest" ni [namespace children]} {
	    package require tcltest 2.5
	    namespace import -force ::tcltest::*
	}

        # If an error occurs during the tests, this process may end up not
        # being closed down. To deal with this we create a 30s timeout.
        proc ::DoTimeout {} {
            global done ddeServerName
            set done 1
            puts "winDde.test child process $ddeServerName timed out."
            flush stdout
        }
        set timeout [after 30000 ::DoTimeout]
	# If an error occurs during the tests, this process may end up not
	# being closed down. To deal with this we create a 30s timeout.
	proc ::DoTimeout {} {
	    global done ddeServerName
	    set done 1
	    puts "winDde.test child process $ddeServerName timed out."
	    flush stdout
	}
	set timeout [after 30000 ::DoTimeout]

        # Define a restricted handler.
        proc Handler1 {cmd} {
            if {$cmd eq "stop"} {set ::done 1}
            if {$cmd == ""} {
                set cmd "null data"
            }
            puts $cmd ; flush stdout
            return
        }
        proc Handler2 {cmd} {
            if {$cmd eq "stop"} {set ::done 1}
            puts [uplevel \#0 $cmd] ; flush stdout
            return
        }
        proc Handler3 {prefix cmd} {
            if {$cmd eq "stop"} {set ::done 1}
            puts [list $prefix $cmd] ; flush stdout
            return
        }
	# Define a restricted handler.
	proc Handler1 {cmd} {
	    if {$cmd eq "stop"} {set ::done 1}
	    if {$cmd == ""} {
		set cmd "null data"
	    }
	    puts $cmd ; flush stdout
	    return
	}
	proc Handler2 {cmd} {
	    if {$cmd eq "stop"} {set ::done 1}
	    puts [uplevel \#0 $cmd] ; flush stdout
	    return
	}
	proc Handler3 {prefix cmd} {
	    if {$cmd eq "stop"} {set ::done 1}
	    puts [list $prefix $cmd] ; flush stdout
	    return
	}
    }
    # set the dde server name to the supplied argument.
    puts $f [list dde servername {*}$args -- $ddeServerName]
    puts $f {
        # run the server and handle final cleanup.
        after 200;# give dde a chance to get going.
	# run the server and handle final cleanup.
	after 200;# give dde a chance to get going.
	puts ready
        flush stdout
	flush stdout
	vwait done
	# allow enough time for the calling process to
	# claim all results, to avoid spurious "server did
	# not respond"
	after 200 {set reallyDone 1}
	vwait reallyDone
	exit
    }
    close $f

    # run the child server script.
    set f [open |[list [interpreter] $::scriptName] r]
    fconfigure $f -buffering line
    fconfigure $f -buffering line -encoding utf-8
    gets $f line
    return $f
}

# -------------------------------------------------------------------------
test winDde-1.0 {check if we are testing the right dll} {win dde} {
    set ::ddever
} {1.4.3}
} {1.4.5}

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
    expr {[llength [dde services {} {}]] >= 0}
} -result 1
test winDde-2.2 {Checking for existence, with service and topic specified} \
	-constraints dde -body {
    llength [dde services TclEval self]
} -result 1
test winDde-2.3 {Checking for existence, with only the service specified} \
	-constraints dde -body {
    expr [llength [dde services TclEval {}]] >= 1
    expr {[llength [dde services TclEval {}]] >= 1}
} -result 1
test winDde-2.4 {Checking for existence, with only the topic specified} \
	-constraints dde -body {
    expr [llength [dde services {} self]] >= 1
    expr {[llength [dde services {} self]] >= 1}
} -result 1

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

test winDde-3.1 {DDE execute locally} -constraints dde -body {
    set \xe1 ""
    dde execute TclEval self [list set \xe1 foo]
    set \xe1
    set \xE1 ""
    dde execute TclEval self [list set \xE1 foo]
    set \xE1
} -result foo
test winDde-3.2 {DDE execute -async locally} -constraints dde -body {
    set \xe1 ""
    dde execute -async TclEval self [list set \xe1 foo]
    set \xE1 ""
    dde execute -async TclEval self [list set \xE1 foo]
    update
    set \xe1
    set \xE1
} -result foo
test winDde-3.3 {DDE request locally} -constraints dde -body {
    set \xe1 ""
    dde execute TclEval self [list set \xe1 foo]
    dde request TclEval self \xe1
    set \xE1 ""
    dde execute TclEval self [list set \xE1 foo]
    dde request TclEval self \xE1
} -result foo
test winDde-3.4 {DDE eval locally} -constraints dde -body {
    set \xe1 ""
    dde eval self set \xe1 foo
    set \xE1 ""
    dde eval self set \xE1 foo
} -result foo
test winDde-3.5 {DDE request locally} -constraints dde -body {
    set \xe1 ""
    dde execute TclEval self [list set \xe1 foo]
    dde request -binary TclEval self \xe1
    set \xE1 ""
    dde execute TclEval self [list set \xE1 foo]
    dde request -binary TclEval self \xE1
} -result "foo\x00"
# Set variable a to A with diaeresis (unicode C4) by relying on the fact
# Set variable a to A with diaeresis (Unicode C4) by relying on the fact
# that utf-8 is sent (e.g. "c3 84" on the wire)
test winDde-3.6 {DDE request utf-8} -constraints dde -body {
    set \xe1 "not set"
    dde execute TclEval self "set \xe1 \xc4"
    scan [set \xe1] %c
    set \xE1 "not set"
    dde execute TclEval self "set \xE1 \xC4"
    scan [set \xE1] %c
} -result 196
# Set variable a to A with diaeresis (unicode C4) using binary execute
# and compose utf-8 (e.g. "c3 84" ) manualy
# Set variable a to A with diaeresis (Unicode C4) using binary execute
# and compose utf-8 (e.g. "c3 84" ) manually
test winDde-3.7 {DDE request binary} -constraints {dde notWine} -body {
    set \xe1 "not set"
    dde execute -binary TclEval self [list set \xc3\xa1 \xc3\x84\x00]
    scan [set \xe1] %c
    set \xE1 "not set"
    dde execute -binary TclEval self [list set \xC3\xA1 \xC3\x84\x00]
    scan [set \xE1] %c
} -result 196
test winDde-3.8 {DDE poke locally} -constraints {dde debug} -body {
    set \xe1 ""
    dde poke TclEval self \xe1 \xc4
    dde request TclEval self \xe1
} -result \xc4
    set \xE1 ""
    dde poke TclEval self \xE1 \xC4
    dde request TclEval self \xE1
} -result \xC4
test winDde-3.9 {DDE poke -binary locally} -constraints {dde debug} -body {
    set \xe1 ""
    dde poke -binary TclEval self \xe1 \xc3\x84\x00
    dde request TclEval self \xe1
} -result \xc4
    set \xE1 ""
    dde poke -binary TclEval self \xE1 \xC3\x84\x00
    dde request TclEval self \xE1
} -result \xC4

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

test winDde-4.1 {DDE execute remotely} -constraints {dde stdio} -body {
    set \xe1 ""
    set \xE1 ""
    set name ch\xEDld-4.1
    set child [createChildProcess $name]
    dde execute TclEval $name [list set \xe1 foo]
    dde execute TclEval $name [list set \xE1 foo]
    dde execute TclEval $name {set done 1}
    update
    set \xe1
    set \xE1
} -result ""
test winDde-4.2 {DDE execute async remotely} -constraints {dde stdio} -body {
    set \xe1 ""
    set \xE1 ""
    set name ch\xEDld-4.2
    set child [createChildProcess $name]
    dde execute -async TclEval $name [list set \xe1 foo]
    dde execute -async TclEval $name [list set \xE1 foo]
    update
    dde execute TclEval $name {set done 1}
    update
    set \xe1
    set \xE1
} -result ""
test winDde-4.3 {DDE request remotely} -constraints {dde stdio} -body {
    set \xe1 ""
    set \xE1 ""
    set name ch\xEDld-4.3
    set child [createChildProcess $name]
    dde execute TclEval $name [list set \xe1 foo]
    set \xe1 [dde request TclEval $name \xe1]
    dde execute TclEval $name [list set \xE1 foo]
    set \xE1 [dde request TclEval $name \xE1]
    dde execute TclEval $name {set done 1}
    update
    set \xe1
    set \xE1
} -result foo
test winDde-4.4 {DDE eval remotely} -constraints {dde stdio} -body {
    set \xe1 ""
    set \xE1 ""
    set name ch\xEDld-4.4
    set child [createChildProcess $name]
    set \xe1 [dde eval $name set \xe1 foo]
    set \xE1 [dde eval $name set \xE1 foo]
    dde execute TclEval $name {set done 1}
    update
    set \xe1
    set \xE1
}  -result foo
test winDde-4.5 {DDE poke remotely} -constraints {dde debug stdio} -body {
    set \xe1 ""
    set \xE1 ""
    set name ch\xEDld-4.5
    set child [createChildProcess $name]
    dde poke TclEval $name \xe1 foo
    set \xe1 [dde request TclEval $name \xe1]
    dde poke TclEval $name \xE1 foo
    set \xE1 [dde request TclEval $name \xE1]
    dde execute TclEval $name {set done 1}
    update
    set \xe1
    set \xE1
} -result foo

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

test winDde-5.1 {check for bad arguments} -constraints dde -body {
    dde execute "" "" "" ""
} -returnCodes error -result {wrong # args: should be "dde execute ?-async? ?-binary? serviceName topicName value"}
397
398
399
400
401
402
403
404
405


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


405
406
407
408
409
410
411
412
413







-
-
+
+







} -cleanup {interp delete child} -result 1
test winDde-8.9 {Safe DDE check command evaluation} -constraints dde -setup {
    interp create -safe child
    child invokehidden load $::ddelib Dde
    child eval {proc DDEACCEPT {cmd} {set ::DDECMD [uplevel \#0 $cmd]}}
    child invokehidden dde servername -handler DDEACCEPT child
} -body {
    dde eval child set \xe1 1
    child eval set \xe1
    dde eval child set \xE1 1
    child eval set \xE1
} -cleanup {interp delete child} -result 1
test winDde-8.10 {Safe DDE check command evaluation (2)} -constraints dde -setup {
    interp create -safe child
    child invokehidden load $::ddelib Dde
    child eval {proc DDEACCEPT {cmd} {set ::DDECMD [uplevel \#0 $cmd]}}
    child invokehidden dde servername -handler DDEACCEPT child
} -body {

Changes to tests/winFCmd.test.

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
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
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
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






-
-
+
+










-
+



-
-






+
+
-
-
+
+















-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
+
+
+
-
-
+
-
-
-
-
+
+
-




















-
-
+
+



-
+







# This file tests the tclWinFCmd.c file.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996-1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

# Initialise the test constraints

testConstraint winVista 0
testConstraint winXP 0
testConstraint testvolumetype [llength [info commands testvolumetype]]
testConstraint testfile       [llength [info commands testfile]]
testConstraint testchmod      [llength [info commands testchmod]]
testConstraint cdrom 0
testConstraint exdev 0
testConstraint longFileNames 0
# Some things fail under all Continuous Integration systems for subtle reasons
# such as CI often running with elevated privileges in a container.
testConstraint knownMsvcBug [expr {![info exists ::env(TRAVIS_OS_NAME)] || ![string match windows $::env(TRAVIS_OS_NAME)]}]
testConstraint notWine [expr {$::tcl_platform(platform) ne "windows" || ![info exists ::env(TRAVIS_OS_NAME)] || ![string match linux $::env(TRAVIS_OS_NAME)]}]
testConstraint notInCIenv     [expr {![info exists ::env(CI)]}]
testConstraint knownMsvcBug [expr {![string match msvc-* [tcl::build-info compiler]]}]

proc createfile {file {string a}} {
    set f [open $file w]
    puts -nonewline $f $string
    close $f
    return $string
}

proc contents {file} {
    set f [open $file r]
    set r [read $f]
    close $f
    set r
}

proc cleanup {args} {
    foreach p ". $args" {
	set x ""
	catch {
	    set x [glob -directory $p tf* td*]
proc cleanupRecurse {args} {
    # Assumes no loops via links!
    # Need to change permissions BEFORE deletion
    catch {testchmod 0o777 {*}$args}
    foreach victim $args {
	if {[file isdirectory $victim]} {
	    cleanupRecurse {*}[glob -nocomplain -directory $victim td* tf* Test*]
	}
	if {$x != ""} {
	    catch {file delete -force -- {*}$x}
	}
    }
	file delete -force $victim
    }
}
}

proc cleanup {args} {
if {[testConstraint win]} {
    if {$::tcl_platform(osVersion) >= 5.0} {
	testConstraint winVista 1
    } else {
    foreach p [list [pwd] {*}$args] {
	cleanupRecurse {*}[glob -nocomplain -directory $p tf* td*]
	testConstraint winXP 1
    }
}

# find a CD-ROM so we can test read-only filesystems.

proc findfile {dir} {
    foreach p [glob -nocomplain -type f -directory $dir *] {
	return $p
    }
    foreach p [glob -nocomplain -type d -directory $dir *] {
	set f [findfile $p]
	if {$f ne ""} {
	    return $f
	}
    }
    return ""
}

if {[testConstraint testvolumetype]} {
    foreach p {d e f g h i j k l m n o p q r s t u v w x y z} {
        if {![catch {testvolumetype ${p}:} result] && $result in {CDFS UDF}} {
            set cdrom ${p}:
	if {![catch {testvolumetype ${p}:} result] && $result in {CDFS UDF}} {
	    set cdrom ${p}:
	    set cdfile [findfile $cdrom]
	    testConstraint cdrom 1
	    break
        }
	}
    }
}

# NB: filename is chosen to be short but unlikely to clash with other apps
if {[file exists c:/] && [file exists d:/]} {
    catch {file delete d:/TclTmpF.1}
    catch {file delete d:/TclTmpD.1}
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
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







-
+






-
+






-
+




-
+





-
+







append longname $longname
append longname $longname
append longname $longname

# Uses the "testfile" command instead of the "file" command.  The "file"
# command provides several layers of sanity checks on the arguments and
# it can be difficult to actually forward "insane" arguments to the
# low-level posix emulation layer.
# low-level Posix emulation layer.

test winFCmd-1.1 {TclpRenameFile: errno: EACCES} -body {
    testfile mv $cdfile $cdrom/dummy~~.fil
} -constraints {win cdrom testfile} -returnCodes error -result EACCES
test winFCmd-1.2 {TclpRenameFile: errno: EEXIST} -setup {
    cleanup
} -constraints {win testfile notWine} -body {
} -constraints {win testfile notInCIenv} -body {
    file mkdir td1/td2/td3
    file mkdir td2
    testfile mv td2 td1/td2
} -returnCodes error -result EEXIST
test winFCmd-1.3 {TclpRenameFile: errno: EINVAL} -setup {
    cleanup
} -constraints {win testfile notWine} -body {
} -constraints {win testfile notInCIenv} -body {
    testfile mv / td1
} -returnCodes error -result EINVAL
test winFCmd-1.4 {TclpRenameFile: errno: EINVAL} -setup {
    cleanup
} -constraints {win testfile notWine} -body {
} -constraints {win testfile notInCIenv} -body {
    file mkdir td1
    testfile mv td1 td1/td2
} -returnCodes error -result EINVAL
test winFCmd-1.5 {TclpRenameFile: errno: EISDIR} -setup {
    cleanup
} -constraints {win testfile notWine} -body {
} -constraints {win testfile notInCIenv} -body {
    file mkdir td1
    createfile tf1
    testfile mv tf1 td1
} -returnCodes error -result EISDIR
test winFCmd-1.6 {TclpRenameFile: errno: ENOENT} -setup {
    cleanup
} -constraints {win testfile} -body {
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
197
198
199
200
201
202
203





204
205
206
207
208
209
210







-
-
-
-
-







} -constraints {win testfile} -body {
    createfile tf1
    set fd [open tf2 w]
    testfile mv tf1 tf2
} -cleanup {
    catch {close $fd}
} -returnCodes error -result EACCES
test winFCmd-1.13 {TclpRenameFile: errno: EACCES} -setup {
    cleanup
} -constraints {win winXP testfile} -body {
    testfile mv nul tf1
} -returnCodes error -result EINVAL
test winFCmd-1.15 {TclpRenameFile: errno: EEXIST} -setup {
    cleanup
} -constraints {win testfile} -body {
    createfile tf1
    testfile mv tf1 nul
} -returnCodes error -result EEXIST
test winFCmd-1.16 {TclpRenameFile: MoveFile() != FALSE} -setup {
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
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







-
-
-
-
-



















-
+






+

-
+







    testfile mv tf1 tf2
} -returnCodes error -result ENOENT
test winFCmd-1.18 {TclpRenameFile: srcAttr == -1} -setup {
    cleanup
} -constraints {win testfile} -body {
    testfile mv tf1 tf2
} -returnCodes error -result ENOENT
test winFCmd-1.19 {TclpRenameFile: errno == EACCES} -setup {
    cleanup
} -constraints {win winXP testfile} -body {
    testfile mv nul tf1
} -returnCodes error -result EINVAL
test winFCmd-1.20 {TclpRenameFile: src is dir} -setup {
    cleanup
} -constraints {win testfile} -body {
    file delete /tf1
    testfile mv [pwd] /tf1
} -returnCodes error -result EACCES
test winFCmd-1.21 {TclpRenameFile: long src} -setup {
    cleanup
} -constraints {win testfile} -body {
    testfile mv $longname tf1
} -returnCodes error -result ENAMETOOLONG
test winFCmd-1.22 {TclpRenameFile: long dst} -setup {
    cleanup
} -constraints {win testfile} -body {
    createfile tf1
    testfile mv tf1 $longname
} -returnCodes error -result ENAMETOOLONG
test winFCmd-1.23 {TclpRenameFile: move dir into self} -setup {
    cleanup
} -constraints {win testfile notWine} -body {
} -constraints {win testfile notInCIenv} -body {
    file mkdir td1
    testfile mv [pwd]/td1 td1/td2
} -returnCodes error -result EINVAL
test winFCmd-1.24 {TclpRenameFile: move a root dir} -setup {
    cleanup
} -constraints {win testfile} -body {
    # Error code depends on Windows version
    testfile mv / c:/
} -returnCodes error -result EINVAL
} -returnCodes error -result {^(EINVAL|ENOENT)$} -match regexp
test winFCmd-1.25 {TclpRenameFile: cross file systems} -setup {
    cleanup
} -constraints {win cdrom testfile} -body {
    file mkdir td1
    testfile mv td1 $cdrom/td1
} -returnCodes error -result EXDEV
test winFCmd-1.26 {TclpRenameFile: readonly fs} -setup {
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
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







-
+






-
+






-
+







} -constraints {win testfile} -body {
    file mkdir td1
    createfile tf1
    testfile mv td1 tf1
} -returnCodes error -result ENOTDIR
test winFCmd-1.30 {TclpRenameFile: dst is dir} -setup {
    cleanup
} -constraints {win testfile notWine} -body {
} -constraints {win testfile notInCIenv} -body {
    file mkdir td1
    file mkdir td2/td2
    testfile mv td1 td2
} -returnCodes error -result EEXIST
test winFCmd-1.31 {TclpRenameFile: TclpRemoveDirectory fails} -setup {
    cleanup
} -constraints {win testfile notWine} -body {
} -constraints {win testfile notInCIenv} -body {
    file mkdir td1
    file mkdir td2/td2
    testfile mv td1 td2
} -returnCodes error -result EEXIST
test winFCmd-1.32 {TclpRenameFile: TclpRemoveDirectory succeeds} -setup {
    cleanup
} -constraints {win testfile notWine} -body {
} -constraints {win testfile notInCIenv} -body {
    file mkdir td1/td2
    file mkdir td2
    testfile mv td1 td2
    list [file exists td1] [file exists td2] [file exists td2/td2]
} -result {0 1 1}
test winFCmd-1.33 {TclpRenameFile: After removing dst dir, MoveFile fails} \
	-constraints {win exdev testfile testchmod} -body {
340
341
342
343
344
345
346
347

348
349
350
351
352
353
354
328
329
330
331
332
333
334

335
336
337
338
339
340
341
342







-
+







    createfile tf1
    testfile mv td1 tf1
} -cleanup {
    cleanup
} -returnCodes error -result ENOTDIR
test winFCmd-1.35 {TclpRenameFile: src is not dir, dst is} -setup {
    cleanup
} -constraints {win testfile notWine} -body {
} -constraints {win testfile notInCIenv} -body {
    file mkdir td1
    createfile tf1
    testfile mv tf1 td1
} -cleanup {
    cleanup
} -returnCodes error -result EISDIR
test winFCmd-1.36 {TclpRenameFile: src and dst not dir} -setup {
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+

-
+




-
+







    expr {$statExe(ino) != 0}
}]

proc MakeFiles {dirname} {
    set inodes {}
    set ndx -1
    while {1} {
        # upped to 50K for 64bit Server 2008
        if {$ndx > 50000} {
            return -code error "limit reached without finding a collistion."
        }
        set filename [file join $dirname Test[incr ndx]]
        set f [open $filename w]
        close $f
        file stat $filename stat
        if {[set n [lsearch -exact -integer $inodes $stat(ino)]] >= 0} {
            return [list [file join $dirname Test$n] $filename]
        }
        lappend inodes $stat(ino)
        unset stat
	# upped to 50K for 64bit Server 2008
	if {$ndx > 50000} {
	    tcltest::Skip "limit-reached:no-collistion"
	}
	set filename [file join $dirname Test[incr ndx]]
	set f [open $filename w]
	close $f
	file stat $filename stat
	if {[set n [lsearch -exact -integer $inodes $stat(ino)]] >= 0} {
	    return [list [file join $dirname Test$n] $filename]
	}
	lappend inodes $stat(ino)
	unset stat
    }
}

test winFCmd-1.38 {TclpRenameFile: check rename of conflicting inodes} -setup {
    cleanup
} -constraints {win winNonZeroInodes knownMsvcBug notWine} -body {
} -constraints {win winNonZeroInodes knownMsvcBug notInCIenv extensive} -body {
    file mkdir td1
    foreach {a b} [MakeFiles td1] break
    lassign [MakeFiles td1] a b
    file rename -force $a $b
    file exists $a
} -cleanup {
    cleanup
} -result {0}
} -result 0


test winFCmd-2.1 {TclpCopyFile: errno: EACCES} -setup {
    cleanup
} -constraints {win cdrom testfile} -body {
    testfile cp $cdfile $cdrom/dummy~~.fil
} -returnCodes error -result EACCES
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
429
430
431
432
433
434
435





436
437
438
439
440
441
442







-
-
-
-
-







    cleanup
} -constraints {win testfile} -body {
    createfile tf1
    testfile cp tf1 ""
} -cleanup {
    cleanup
} -returnCodes error -result ENOENT
test winFCmd-2.7 {TclpCopyFile: errno: EACCES} -setup {
    cleanup
} -constraints {win winXP testfile} -body {
    testfile cp nul tf1
} -returnCodes error -result EINVAL
test winFCmd-2.10 {TclpCopyFile: CopyFile succeeds} -setup {
    cleanup
} -constraints {win testfile} -body {
    createfile tf1 tf1
    testfile cp tf1 tf2
    list [contents tf1] [contents tf2]
} -cleanup {
467
468
469
470
471
472
473
474

475
476

477
478
479
480

481
482
483
484
485
486
487
450
451
452
453
454
455
456

457
458

459
460
461
462

463
464
465
466
467
468
469
470







-
+

-
+



-
+







    testfile cp tf1 tf2
    list [contents tf1] [contents tf2]
} -cleanup {
    cleanup
} -result {tf1 tf1}
test winFCmd-2.12 {TclpCopyFile: CopyFile succeeds} -setup {
    cleanup
} -constraints {win testfile} -body {
} -constraints {win testfile testchmod} -body {
    createfile tf1 tf1
    testchmod 0 tf1
    file attribute tf1 -readonly 1
    testfile cp tf1 tf2
    list [contents tf2] [file writable tf2]
} -cleanup {
    catch {testchmod 0o666 tf1}
    testchmod 0o660 tf1
    cleanup
} -result {tf1 0}
test winFCmd-2.13 {TclpCopyFile: CopyFile fails} -setup {
    cleanup
} -constraints {win testfile} -body {
    createfile tf1
    file mkdir td1
515
516
517
518
519
520
521
522

523
524
525
526
527
528
529
530
531
532
533
498
499
500
501
502
503
504

505
506
507
508

509
510
511
512
513
514
515







-
+



-







    cleanup
} -returnCodes error -result EISDIR
test winFCmd-2.17 {TclpCopyFile: dst is readonly} -setup {
    cleanup
} -constraints {win testfile testchmod} -body {
    createfile tf1 tf1
    createfile tf2 tf2
    testchmod 0 tf2
    file attribute tf2 -readonly 1
    testfile cp tf1 tf2
    list [file writable tf2] [contents tf2]
} -cleanup {
    catch {testchmod 0o666 tf2}
    cleanup
} -result {1 tf1}

test winFCmd-3.1 {TclpDeleteFile: errno: EACCES} -body {
    testfile rm $cdfile $cdrom/dummy~~.fil
} -constraints {win cdrom testfile} -returnCodes error -result EACCES
test winFCmd-3.2 {TclpDeleteFile: errno: EISDIR} -setup {
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
579
580
581
582
583
584
585

586
587
588
589
590
591
592







-







    cleanup
} -constraints {win testfile testchmod} -body {
    set fd [open tf1 w]
    testchmod 0 tf1
    testfile rm tf1
} -cleanup {
    close $fd
    catch {testchmod 0o666 tf1}
    cleanup
} -returnCodes error -result EACCES

test winFCmd-4.1 {TclpCreateDirectory: errno: EACCES} -body {
    testfile mkdir $cdrom/dummy~~.dir
} -constraints {win cdrom testfile} -returnCodes error -result EACCES
test winFCmd-4.3 {TclpCreateDirectory: errno: EEXIST} -setup {
636
637
638
639
640
641
642
643
644
645
646
647









648
649
650
651

652
653
654
655
656
657
658
659

660
661
662
663
664
665
666
617
618
619
620
621
622
623





624
625
626
627
628
629
630
631
632
633

634

635
636
637
638
639
640
641
642

643
644
645
646
647
648
649
650







-
-
-
-
-
+
+
+
+
+
+
+
+
+

-

-
+







-
+







    list [file type td1] [file type td2]
} -cleanup {
    cleanup
} -result {directory directory}

test winFCmd-6.1 {TclpRemoveDirectory: errno: EACCES} -setup {
    cleanup
} -constraints {winVista testfile testchmod knownMsvcBug notWine} -body {
    file mkdir td1
    testchmod 0 td1
    testfile rmdir td1
    file exists td1
} -constraints {win testfile testchmod notInCIenv} -body {
    # Parent's FILE_DELETE_CHILD setting permits deletion of subdir
    # even when subdir DELETE mask is clear. So we need an intermediate
    # parent td0 with FILE_DELETE_CHILD turned off while allowing R/W.
    file mkdir td0/td1
    testchmod 0o777 td0
    testchmod 0 td0/td1
    testfile rmdir td0/td1
    file exists td0/td1
} -returnCodes error -cleanup {
    catch {testchmod 0o666 td1}
    cleanup
} -result {td1 EACCES}
} -result {td0/td1 EACCES}
# This next test has a very hokey way of matching...
test winFCmd-6.2 {TclpRemoveDirectory: errno: EEXIST} -setup {
    cleanup
} -constraints {win testfile} -body {
    file mkdir td1/td2
    list [catch {testfile rmdir td1} msg] [file tail $msg]
} -result {1 {td1 EEXIST}}
test winFCmd-6.3 {TclpRemoveDirectory: errno: EACCES} {win emptyTest} {
test winFCmd-6.3 {TclpRemoveDirectory: errno: EACCES} {win emptyTest trashSystem} {
    # can't test this w/o removing everything on your hard disk first!
    # testfile rmdir /
} {}
# This next test has a very hokey way of matching...
test winFCmd-6.4 {TclpRemoveDirectory: errno: ENOENT} -setup {
    cleanup
} -constraints {win testfile} -body {
688
689
690
691
692
693
694
695

696
697
698
699
700
701
702
703
704
705
706
707
708

709
710
711
712
713
714
715
716
717
718
719









720
721

722
723

724
725
726
727
728
729
730
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
707
708







-
+
-
-
-
-
-
-
-
-
-
-


-
+






-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
+

-
+







# This next test has a very hokey way of matching...
test winFCmd-6.8 {TclpRemoveDirectory: RemoveDirectory fails} -setup {
    cleanup
} -constraints {win testfile} -body {
    createfile tf1
    list [catch {testfile rmdir tf1} msg] [file tail $msg]
} -result {1 {tf1 ENOTDIR}}
test winFCmd-6.9 {TclpRemoveDirectory: errno == EACCES} -setup {
# winFCmd-6.9 removed - was exact dup of winFCmd-6.1
    cleanup
} -constraints {winVista testfile testchmod knownMsvcBug notWine} -body {
    file mkdir td1
    testchmod 0 td1
    testfile rmdir td1
    file exists td1
} -returnCodes error -cleanup {
    catch {testchmod 0o666 td1}
    cleanup
} -result {td1 EACCES}
test winFCmd-6.11 {TclpRemoveDirectory: attr == -1} -setup {
    cleanup
} -constraints {win testfile notWine} -body {
} -constraints {win testfile notInCIenv} -body {
    testfile rmdir /
    # WinXP returns EEXIST, WinNT seems to return EACCES.  No policy
    # decision has been made as to which is correct.
} -returnCodes error -match regexp -result {^/ E(ACCES|EXIST)$}
test winFCmd-6.13 {TclpRemoveDirectory: write-protected} -setup {
    cleanup
} -constraints {winVista testfile testchmod knownMsvcBug notWine} -body {
    file mkdir td1
    testchmod 0 td1
    testfile rmdir td1
    file exists td1
} -constraints {win testfile testchmod notInCIenv} -body {
    # Parent's FILE_DELETE_CHILD setting permits deletion of subdir
    # even when subdir DELETE mask is clear. So we need an intermediate
    # parent td0 with FILE_DELETE_CHILD turned off while allowing R/W.
    file mkdir td0/td1
    testchmod 0o770 td0
    testchmod 0o444 td0/td1
    testfile rmdir td0/td1
    file exists td0/td1
} -cleanup {
    catch {testchmod 0o666 td1}
    testchmod 0o770 td0/td1
    cleanup
} -returnCodes error -result {td1 EACCES}
} -returnCodes error -result {td0/td1 EACCES}
# This next test has a very hokey way of matching...
test winFCmd-6.15 {TclpRemoveDirectory: !recursive} -setup {
    cleanup
} -constraints {win testfile} -body {
    file mkdir td1/td2
    list [catch {testfile rmdir td1} msg] [file tail $msg]
} -result {1 {td1 EEXIST}}
810
811
812
813
814
815
816

817

818
819
820
821

822
823
824
825
826
827
828
788
789
790
791
792
793
794
795

796
797
798
799

800
801
802
803
804
805
806
807







+
-
+



-
+







    # can't make it happen
} {}
test winFCmd-7.11 {TraverseWinTree: call TraversalCopy: DOTREE_PRED} -setup {
    cleanup
} -constraints {win testfile testchmod} -body {
    file mkdir td1
    createfile td1/tf1 tf1
    testchmod 0o770 td1/tf1; # Else tf2 will have no ACL after td1 testchmod
    testchmod 0 td1
    testchmod 0o400 td1
    testfile cpdir td1 td2
    list [file exists td2] [file writable td2]
} -cleanup {
    catch {testchmod 0o666 td1}
    testchmod 0o660 td1
    cleanup
} -result {1 1}
test winFCmd-7.12 {TraverseWinTree: call TraversalDelete: DOTREE_PRED} -setup {
    cleanup
} -constraints {win testfile} -body {
    file mkdir td1
    createfile td1/tf1 tf1
881
882
883
884
885
886
887

888

889
890
891
892

893
894
895
896
897
898
899
860
861
862
863
864
865
866
867

868
869
870
871

872
873
874
875
876
877
878
879







+
-
+



-
+







    cleanup
} -result {td2/td2 td2/tf1 td2/tf2 td2/tf3 td2/tf4}
test winFCmd-7.19 {TraverseWinTree: call TraversalCopy: DOTREE_POSTD} -setup {
    cleanup
} -constraints {win testfile testchmod} -body {
    file mkdir td1
    createfile td1/tf1 tf1
    testchmod 0o770 td1/tf1; # Else tf2 will have no ACL after td1 testchmod
    testchmod 0 td1
    testchmod 0o400 td1
    testfile cpdir td1 td2
    list [file exists td2] [file writable td2]
} -cleanup {
    catch {testchmod 0o666 td1}
    testchmod 0o660 td1
    cleanup
} -result {1 1}
test winFCmd-7.20 {TraverseWinTree: call TraversalDelete: DOTREE_POSTD} -setup {
    cleanup
} -constraints {win testfile} -body {
    file mkdir td1
    createfile td1/tf1 tf1
912
913
914
915
916
917
918

919

920
921
922
923

924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947








948
949
950

951
952

953
954
955
956
957
958
959
892
893
894
895
896
897
898
899

900
901
902
903

904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924




925
926
927
928
929
930
931
932
933
934

935
936

937
938
939
940
941
942
943
944







+
-
+



-
+




















-
-
-
-
+
+
+
+
+
+
+
+


-
+

-
+







    file mkdir td1
    testfile cpdir td1 td1
} -returnCodes error -result {td1 EEXIST}
test winFCmd-8.2 {TraversalCopy: DOTREE_PRED} -setup {
    cleanup
} -constraints {win testfile testchmod} -body {
    file mkdir td1/td2
    testchmod 0o770 td1/td2; # Else td2 will have no ACL after td1 testchmod
    testchmod 0 td1
    testchmod 0o400 td1
    testfile cpdir td1 td2
    list [file writable td1] [file writable td1/td2]
} -cleanup {
    catch {testchmod 0o666 td1}
    testchmod 0o660 td1
    cleanup
} -result {0 1}
test winFCmd-8.3 {TraversalCopy: DOTREE_POSTD} -setup {
    cleanup
} -constraints {win testfile} -body {
    file mkdir td1
    testfile cpdir td1 td2
} -cleanup {
    cleanup
} -result {}

test winFCmd-9.1 {TraversalDelete: DOTREE_F} -setup {
    cleanup
} -constraints {win testfile} -body {
    file mkdir td1
    createfile td1/tf1
    testfile rmdir -force td1
} -result {}
test winFCmd-9.3 {TraversalDelete: DOTREE_PRED} -setup {
    cleanup
} -constraints {winVista testfile testchmod knownMsvcBug notWine} -body {
    file mkdir td1/td2
    testchmod 0 td1
    testfile rmdir -force td1
} -constraints {win testfile testchmod notInCIenv} -body {
    # Parent's FILE_DELETE_CHILD setting permits deletion of subdir
    # even when subdir DELETE mask is clear. So we need an intermediate
    # parent td0 with FILE_DELETE_CHILD turned off while allowing R/W.
    file mkdir td0/td1/td2
    testchmod 0o770 td0
    testchmod 0o400 td0/td1
    testfile rmdir -force td0/td1
    file exists td1
} -cleanup {
    catch {testchmod 0o666 td1}
    testchmod 0o770 td0/td1
    cleanup
} -returnCodes error -result {td1 EACCES}
} -returnCodes error -result {td0/td1 EACCES}
test winFCmd-9.4 {TraversalDelete: DOTREE_POSTD} -setup {
    cleanup
} -constraints {win testfile} -body {
    file mkdir td1/td1/td3/td4/td5
    testfile rmdir -force td1
} -result {}

1050
1051
1052
1053
1054
1055
1056
1057

1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1035
1036
1037
1038
1039
1040
1041

1042








1043
1044
1045
1046
1047
1048
1049







-
+
-
-
-
-
-
-
-
-







    string tolower [file attributes ./td1 -longname]
} -cleanup {
    cleanup
} -result {./td1}
test winFCmd-12.5 {ConvertFileNameFormat: absolute path} -body {
    list [file attributes / -longname] [file attributes \\ -longname]
} -constraints {win} -result {/ /}
test winFCmd-12.6 {ConvertFileNameFormat: absolute path with drive} -setup {
test winFCmd-12.6 {ConvertFileNameFormat: absolute path with drive (in temp folder)} -setup {
    catch {file delete -force -- c:/TclTmpC.1}
} -constraints {win winXP} -body {
    createfile c:/TclTmpC.1 {}
    string tolower [file attributes c:/TclTmpC.1 -longname]
} -cleanup {
    file delete -force -- c:/TclTmpC.1
} -result [string tolower {c:/TclTmpC.1}]
test winFCmd-12.6.2 {ConvertFileNameFormat: absolute path with drive (in temp folder)} -setup {
    catch {file delete -force -- $::env(TEMP)/td1}
} -constraints {win} -body {
    createfile $::env(TEMP)/td1 {}
    string equal [string tolower [file attributes $::env(TEMP)/td1 -longname]] \
	    [string tolower [file normalize $::env(TEMP)]/td1]
} -cleanup {
    file delete -force -- $::env(TEMP)/td1
1126
1127
1128
1129
1130
1131
1132
1133

1134
1135
1136
1137
1138
1139
1140
1141

1142
1143
1144
1145
1146
1147
1148
1103
1104
1105
1106
1107
1108
1109

1110
1111
1112
1113
1114
1115
1116
1117

1118
1119
1120
1121
1122
1123
1124
1125







-
+







-
+







    cleanup
} -body {
    createfile td1 {}
    list [file attributes td1 -archive 1] [file attributes td1 -archive]
} -cleanup {
    cleanup
} -result {{} 1}
test winFCmd-15.3 {SetWinFileAttributes - archive} -constraints {win notWine} -setup {
test winFCmd-15.3 {SetWinFileAttributes - archive} -constraints {win notInCIenv} -setup {
    cleanup
} -body {
    createfile td1 {}
    list [file attributes td1 -archive 0] [file attributes td1 -archive]
} -cleanup {
    cleanup
} -result {{} 0}
test winFCmd-15.4 {SetWinFileAttributes - hidden} -constraints {win notWine} -setup {
test winFCmd-15.4 {SetWinFileAttributes - hidden} -constraints {win notInCIenv} -setup {
    cleanup
} -body {
    createfile td1 {}
    list [file attributes td1 -hidden 1] [file attributes td1 -hidden] \
	[file attributes td1 -hidden 0]
} -cleanup {
    cleanup
1167
1168
1169
1170
1171
1172
1173
1174

1175
1176
1177
1178
1179
1180
1181
1144
1145
1146
1147
1148
1149
1150

1151
1152
1153
1154
1155
1156
1157
1158







-
+







    cleanup
} -constraints {win} -body {
    createfile td1 {}
    list [file attributes td1 -readonly 0] [file attributes td1 -readonly]
} -cleanup {
    cleanup
} -result {{} 0}
test winFCmd-15.8 {SetWinFileAttributes - system} -constraints {win notWine} -setup {
test winFCmd-15.8 {SetWinFileAttributes - system} -constraints {win notInCIenv} -setup {
    cleanup
} -body {
    createfile td1 {}
    list [file attributes td1 -system 1] [file attributes td1 -system]
} -cleanup {
    cleanup
} -result {{} 1}
1287
1288
1289
1290
1291
1292
1293
1294

1295
1296
1297
1298
1299
1300
1301
1264
1265
1266
1267
1268
1269
1270

1271
1272
1273
1274
1275
1276
1277
1278







-
+







    }
    # Old versions of Tcl gave a misleading error that the
    # directory in question didn't exist.
    if {[llength $d] && [catch {cd [lindex $d 0]} err]} {
	regsub ".*: " $err "" err
	set err
    } else {
        set err "permission denied"
	set err "permission denied"
    }
} -cleanup {
    cd $pwd
} -result "permission denied"

cd $pwd
unset d dd pwd
1350
1351
1352
1353
1354
1355
1356
1357
1358


1359
1360
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
1387
1388
1389
1390
1391


1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402


1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413


1414
1415
1416
1417
1418
1419
1420
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
1354
1355


1356
1357
1358
1359
1360
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
1387
1388


1389
1390
1391
1392
1393
1394
1395
1396
1397







-
-
+
+









-
-
+
+









-
-
+
+









-
-
+
+









-
-
+
+









-
-
+
+







    file normalize //?/c:/windows/../windows/win.ini
} -result //?/c:/windows/win.ini
test winFCmd-19.3 {Windows extended path names} -constraints win -setup {
    set tmpfile [file join $::env(TEMP) tcl[string repeat x 20].tmp]
    set tmpfile [file normalize $tmpfile]
} -body {
    list [catch {
        set f [open $tmpfile [list WRONLY CREAT]]
        close $f
	set f [open $tmpfile [list WRONLY CREAT]]
	close $f
    } res] $res
} -cleanup {
    catch {file delete $tmpfile}
} -result [list 0 {}]
test winFCmd-19.4 {Windows extended path names} -constraints win -setup {
    set tmpfile [file join $::env(TEMP) tcl[string repeat x 20].tmp]
    set tmpfile //?/[file normalize $tmpfile]
} -body {
    list [catch {
        set f [open $tmpfile [list WRONLY CREAT]]
        close $f
	set f [open $tmpfile [list WRONLY CREAT]]
	close $f
    } res] $res
} -cleanup {
    catch {file delete $tmpfile}
} -result [list 0 {}]
test winFCmd-19.5 {Windows extended path names} -constraints win -setup {
    set tmpfile [file join $::env(TEMP) tcl[string repeat x 248].tmp]
    set tmpfile [file normalize $tmpfile]
} -body {
    list [catch {
        set f [open $tmpfile [list WRONLY CREAT]]
        close $f
	set f [open $tmpfile [list WRONLY CREAT]]
	close $f
    } res] $res
} -cleanup {
    catch {file delete $tmpfile}
} -result [list 0 {}]
test winFCmd-19.6 {Windows extended path names} -constraints win -setup {
    set tmpfile [file join $::env(TEMP) tcl[string repeat x 248].tmp]
    set tmpfile //?/[file normalize $tmpfile]
} -body {
    list [catch {
        set f [open $tmpfile [list WRONLY CREAT]]
        close $f
	set f [open $tmpfile [list WRONLY CREAT]]
	close $f
    } res] $res
} -cleanup {
    catch {file delete $tmpfile}
} -result [list 0 {}]
test winFCmd-19.7 {Windows extended path names} -constraints win -setup {
    set tmpfile [file join $::env(TEMP) "tcl[pid].tmp "]
    set tmpfile [file normalize $tmpfile]
} -body {
    list [catch {
        set f [open $tmpfile [list WRONLY CREAT]]
        close $f
	set f [open $tmpfile [list WRONLY CREAT]]
	close $f
    } res] $res [glob -directory $::env(TEMP) -tails tcl[pid].*]
} -cleanup {
    catch {file delete $tmpfile}
} -result [list 0 {} [list tcl[pid].tmp]]
test winFCmd-19.8 {Windows extended path names} -constraints win -setup {
    set tmpfile [file join $::env(TEMP) "tcl[pid].tmp "]
    set tmpfile //?/[file normalize $tmpfile]
} -body {
    list [catch {
        set f [open $tmpfile [list WRONLY CREAT]]
        close $f
	set f [open $tmpfile [list WRONLY CREAT]]
	close $f
    } res] $res [glob -directory $::env(TEMP) -tails tcl[pid].*]
} -cleanup {
    catch {file delete $tmpfile}
} -result [list 0 {} [list "tcl[pid].tmp "]]

test winFCmd-19.9 {Windows devices path names} -constraints win -body {
    file normalize //./com1
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1421
1422
1423
1424
1425
1426
1427

1428
1429
1430
1431
1432
1433
1434







-







#		    puts $msg
#		}
#	    }
#	}
#    }
#}

# cleanup
cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/winFile.test.

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
30
31

32
33
34
35
36
37
38
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
30

31
32
33
34
35
36
37
38






-
-
+
+










-
+







-
+



-
+







# This file tests the tclWinFile.c file.
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testvolumetype [llength [info commands testvolumetype]]
testConstraint notNTFS 0

if {[testConstraint testvolumetype]} {
    testConstraint notNTFS [expr {[testvolumetype] eq "NTFS"}]
}
testConstraint notWine [expr {$::tcl_platform(platform) ne "windows" || ![info exists ::env(TRAVIS_OS_NAME)] || ![string match linux $::env(TRAVIS_OS_NAME)]}]
testConstraint notWine [expr {![info exists ::env(CI_USING_WINE)]}]

test winFile-1.1 {TclpGetUserHome} -constraints {win} -body {
    glob ~nosuchuser
} -returnCodes error -result {user "nosuchuser" doesn't exist}
} -result {}
test winFile-1.2 {TclpGetUserHome} -constraints {win nonPortable} -body {
    # The administrator account should always exist.
    glob ~administrator
} -match glob -result *
test winFile-1.4 {TclpGetUserHome} {win nonPortable} {
    catch {glob ~stanton@workgroup}
} {0}
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
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







-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+







    set tryname $fname
    if {[file isdirectory $fname]} {
	set tryname [file dirname $fname]
    }
    set owner ""
    set tail [file tail $tryname]
    if {[info exists env(OSTYPE)] && $env(OSTYPE) eq "msys"} {
        set dirtext [exec ls -l $fname]
        foreach line [split $dirtext "\n"] {
            set owner [lindex $line 2]
        }
	set dirtext [exec ls -l $fname]
	foreach line [split $dirtext "\n"] {
	    set owner [lindex $line 2]
	}
    } else {
        set dirtext [exec cmd /c dir /q [file nativename $fname]]
        foreach line [split $dirtext "\n"] {
            if {[string match -nocase "*$tail" $line]} {
                set attrs [string range $line 0 end-[string length $tail]]
                regexp { [^ \\]+\\.*$} $attrs owner
                set owner [string trim $owner]
            }
        }
	set dirtext [exec cmd /c dir /q [file nativename $fname]]
	foreach line [split $dirtext "\n"] {
	    if {[string match -nocase "*$tail" $line]} {
		set attrs [string range $line 0 end-[string length $tail]]
		regexp { [^ \\]+\\.*$} $attrs owner
		set owner [string trim $owner]
	    }
	}
    }
    if {$owner eq ""} {
	error "getuser: Owner not found in output of dir/q"
    }
    return $owner
}

Changes to tests/winNotify.test.

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
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






-
-
+
+










-
+







# This file tests the tclWinNotify.c file.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 by Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testeventloop [expr {[info commands testeventloop] != {}}]

# There is no explicit test for InitNotifier or NotifierExitHandler

test winNotify-1.1 {Tcl_SetTimer: positive timeout} {win} {
    set done 0

Changes to tests/winPipe.test.

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
30
31

32
33
34
35
36
37
38
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
30

31
32
33
34
35
36
37
38








-
-
+
+












-
-
+
+






-
+







#
# winPipe.test --
#
# This file contains a collection of tests for tclWinPipe.c
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output (except for one message) means no errors were found.
#
# Copyright (c) 1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
}
unset -nocomplain path

catch {
    ::tcltest::loadTestedCommands
    package require -exact Tcltest [info patchlevel]
    set ::tcltestlib [lindex [package ifneeded Tcltest [info patchlevel]] 1]
    package require -exact tcl::test [info patchlevel]
    set ::tcltestlib [info loaded {} Tcltest]
}

set org_pwd [pwd]
set bindir [file join $org_pwd [file dirname [info nameofexecutable]]]
set cat32 [file join $bindir cat32.exe]

testConstraint notWine [expr {$::tcl_platform(platform) ne "windows" || ![info exists ::env(TRAVIS_OS_NAME)] || ![string match linux $::env(TRAVIS_OS_NAME)]}]
testConstraint notWine [expr {![info exists ::env(CI_USING_WINE)]}]


# several test-cases here expect current directory == [temporaryDirectory]:
cd [temporaryDirectory]

testConstraint exec         [llength [info commands exec]]
testConstraint cat32        [file exists $cat32]
170
171
172
173
174
175
176
177

178
179
180
181
182
183
184
170
171
172
173
174
175
176

177
178
179
180
181
182
183
184







-
+







    catch {close $f} msg
    list [contents $path(stdout)] $msg
} {foo stderr32}
test winpipe-1.21 {32 bit comprehensive tests: read/write application} \
	{win exec cat32} {
    set f [open "|[list $cat32]" r+]
    puts $f $big
    puts $f \032
    puts $f \x1A
    flush $f
    set r [read $f 64]
    catch {close $f}
    set r
} "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"

test winpipe-4.1 {Tcl_WaitPid} {win exec cat32} {
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
366
367
368
369
370
371
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
366
367
368
369




370
371
372
373
374
375
376







-
+










+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+



-
+













+
+
+
+
+
+
+



-
-
-
-







    puts -nonewline $f $big$big$big$big
    flush $f
    after 100 { lappend x timeout }
    vwait x
    lappend x [catch {close $f} msg] $msg
} {writable timeout 0 {}}

proc _testExecArgs {single args} {
proc _testExecArgs {flags args} {
    variable path
    if {![info exists path(echoArgs.tcl)] || ![file exists $path(echoArgs.tcl)]} {
	set path(echoArgs.tcl) [makeFile {
	    puts "[list [file tail $argv0] {*}$argv]"
	} echoArgs.tcl]
    }
    if {![info exists path(echoArgs.bat)] || ![file exists $path(echoArgs.bat)]} {
	set path(echoArgs.bat) [makeFile "@[file native [interpreter]] $path(echoArgs.tcl) %*" "echoArgs.bat"]
    }
    set cmds [list [list [interpreter] $path(echoArgs.tcl)]]
    if {"exe-only" ni $flags} {
    if {!($single & 2)} {
	lappend cmds [list $path(echoArgs.bat)]
    } else {
	if {![info exists path(echoArgs2.bat)] || ![file exists $path(echoArgs2.bat)]} {
	    set path(echoArgs2.bat) [makeFile \
		"@[file native [interpreter]] $path(echoArgs.tcl) %*" \
		"echo(Cmd)Test Args & Batch.bat" [makeDirectory test(Dir)Check]]
	}
	lappend cmds [list $path(echoArgs2.bat)]
	if {"batch2" ni $flags} {
	    lappend cmds [list $path(echoArgs.bat)]
	} else {
	    if {![info exists path(echoArgs2.bat)] || ![file exists $path(echoArgs2.bat)]} {
		set path(echoArgs2.bat) [makeFile \
		    "@[file native [interpreter]] $path(echoArgs.tcl) %*" \
		    "echo(Cmd)Test Args & Batch.bat" [makeDirectory test(Dir)Check]]
	    }
	    lappend cmds [list $path(echoArgs2.bat)]
	}
    }
    set broken {}
    foreach args $args {
	if {$single & 1} {
	if {"enclose" in $flags} {
	    # enclose single test-arg between 1st/3rd to be sure nothing is truncated
	    # (e. g. to cover unexpected trim by nts-zero case, and args don't recombined):
	    set args [list "1st" $args "3rd"]
	}
	set args [list {*}$args]; # normalized canonical list
	foreach cmd $cmds {
	    set e [linsert $args 0 [file tail $path(echoArgs.tcl)]]
	    tcltest::DebugPuts 4 "  ## test exec [file extension [lindex $cmd 0]] ($cmd) for\n  ##   $args"
	    if {[catch {
		exec {*}$cmd {*}$args
	    } r]} {
		set r "ERROR: $r"
	    }
	    if {[file extension [lindex $cmd 0]] eq ".bat"} {
		set evm {}; foreach ev [lsort -unique [regexp -inline -all {%[A-Z]+%} $e]] {
		    set ev [string range $ev 1 end-1]
		    if {[info exists ::env($ev)]} { lappend evm %$ev% $::env($ev) }
		}
		set e [string map $evm $e]
	    }
	    if {$r ne $e} {
		append broken "\[ERROR\]: exec [file extension [lindex $cmd 0]] on $args\n  -- result:\n$r\n  -- expected:\n$e\n"
	    }
	    if {$single & 8} {
		# if test exe only:
		break
	    }
	}
    }
    return $broken
}

### validate the raw output of BuildCommandLine().
###
490
491
492
493
494
495
496
497

498
499
500
501
502
503
504
495
496
497
498
499
500
501

502
503
504
505
506
507
508
509







-
+







    {test" %USERDOMAIN%\\&\\"test}
}

### validate the pass-thru from BuildCommandLine() to the crt's parse_cmdline().
###
test winpipe-8.1 {BuildCommandLine/parse_cmdline pass-thru: dumped arguments are equal original} \
-constraints {win exec} -body {
    _testExecArgs 0 \
    _testExecArgs {} \
	[list foo "" bar] \
	[list foo {} bar] \
	[list foo "\"" bar] \
	[list foo {""} bar] \
	[list foo "\" " bar] \
	[list foo {a="b"} bar] \
	[list foo {a = "b"} bar] \
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
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







-
+




-
+








-
+







	[list foo \{ bar] \
	[list foo \} bar] \
	[list foo * makefile.?c bar]
} -result {}

test winpipe-8.2 {BuildCommandLine/parse_cmdline pass-thru: check injection on special meta-chars (particular)} \
-constraints {win exec slowTest} -body {
    _testExecArgs 1 {*}$injectList
    _testExecArgs enclose {*}$injectList
} -result {}

test winpipe-8.3 {BuildCommandLine/parse_cmdline pass-thru: check injection on special meta-chars (jointly)} \
-constraints {win exec notWine} -body {
    _testExecArgs 0 \
    _testExecArgs {} \
	[list START     {*}$injectList END] \
	[list "START\"" {*}$injectList END] \
	[list START     {*}$injectList "\"END"] \
	[list "START\"" {*}$injectList "\"END"]
} -result {}

test winpipe-8.4 {BuildCommandLine/parse_cmdline pass-thru: check injection on special meta-chars (command/jointly args)} \
-constraints {win exec notWine} -body {
    _testExecArgs 2 \
    _testExecArgs batch2 \
	[list START     {*}$injectList END] \
	[list "START\"" {*}$injectList END] \
	[list START     {*}$injectList "\"END"] \
	[list "START\"" {*}$injectList "\"END"]
} -result {}

test winpipe-8.5 {BuildCommandLine/parse_cmdline pass-thru: check injection on special meta-chars (random mix)} \
560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584

585
586
587
588
589
590
591
592
593
594

595
596
597
598
599
600
601
565
566
567
568
569
570
571

572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588

589
590
591
592
593
594
595
596
597
598

599
600
601
602
603
604
605
606







-
+
















-
+









-
+







	    while {[string length $a] < 50} {
		append a [string index $map [expr {int(rand()*[string length $map])}]]
	    }
	    lappend args $a
	} 20
	lappend lst $args
    } 10
    _testExecArgs 0 {*}$lst
    _testExecArgs {} {*}$lst
} -result {} -cleanup {
    unset -nocomplain lst args a map maps
}

set injectList {
    "test\"\nwhoami"     "test\"\"\nwhoami"
    "test\"\"\"\nwhoami" "test\"\"\"\"\nwhoami"
    "test;\n&echo \""    "\"test;\n&echo \""
    "test\";\n&echo \""  "\"test\";\n&echo \""
    "\"\"test\";\n&echo \""
}

test winpipe-8.6 {BuildCommandLine/parse_cmdline pass-thru: check new-line quoted in args} \
-constraints {win exec} -body {
    # test exe only, because currently there is no proper way to escape a new-line char resp.
    # to supply a new-line to the batch-files within arguments (command line is truncated).
    _testExecArgs 8 \
    _testExecArgs exe-only \
	[list START     {*}$injectList END] \
	[list "START\"" {*}$injectList END] \
	[list START     {*}$injectList "\"END"] \
	[list "START\"" {*}$injectList "\"END"]
} -result {}

test winpipe-8.7 {BuildCommandLine/parse_cmdline pass-thru: check new-line quoted in args (batch)} \
-constraints {win exec knownBug} -body {
    # this will fail if executed batch-file, because currently there is no proper way to escape a new-line char.
    _testExecArgs 0 $injectList
    _testExecArgs {} $injectList
} -result {}


rename _testExecArgs {}

# restore old values for env(TMP) and env(TEMP)

612
613
614
615
616
617
618

619
620
621
622
623
624
625
626
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632







+








removeFile more
removeFile stdout
removeFile stderr
removeFile nothing
if {[info exists path(echoArgs.tcl)]} { removeFile echoArgs.tcl }
if {[info exists path(echoArgs.bat)]} { removeFile echoArgs.bat }
if {[info exists path(echoArgs2.bat)]} { removeDirectory test(Dir)Check }
unset -nocomplain path
::tcltest::cleanupTests
# back to original directory:
cd $org_pwd; unset org_pwd
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/winTime.test.

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
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






-
-
+
+










-
+


-







# This file tests the tclWinTime.c file.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1997 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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 Tcltest [info patchlevel]]
catch [list package require -exact tcl::test [info patchlevel]]

testConstraint testwinclock [llength [info commands testwinclock]]
testConstraint knownMsvcBug [expr {![info exists ::env(TRAVIS_OS_NAME)] || ![string match windows $::env(TRAVIS_OS_NAME)]}]

# The next two tests will crash on Windows if the check for negative
# clock values is not done properly.

test winTime-1.1 {TclpGetDate} {win} {
    set ::env(TZ) JST-9
    set result [clock format -1 -format %Y]
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
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







-
+









-
+













    set result
} {1969}

# Next test tries to make sure that the Tcl clock stays in step
# with the Windows clock.  30 sec really isn't enough,
# but how much time does a tester have patience for?

test winTime-2.1 {Synchronization of Tcl and Windows clocks} {testwinclock knownMsvcBug} {
test winTime-2.1 {Synchronization of Tcl and Windows clocks} testwinclock {
    # May fail due to OS/hardware discrepancies.  See:
    # http://support.microsoft.com/default.aspx?scid=kb;en-us;274323
    set failed {}
    set ok 1
    foreach start_sec [testwinclock] break
    while { 1 } {
	foreach { sys_sec sys_usec tcl_sec tcl_usec } [testwinclock] break
	set diff [expr { $tcl_sec - $sys_sec
			 + 1.0e-6 * ( $tcl_usec - $sys_usec ) }]
        if { abs($diff) > 0.1 } {
	if { abs($diff) > 0.1 } {
	    set failed "Tcl clock differs from system clock by $diff sec"
	    break
	} else {
	    testwinsleep 1
	}
	if { $sys_sec - $start_sec >= 30 } break
    }
    set failed
} {}

# cleanup
::tcltest::cleanupTests
return

Added tests/word.test.

































































































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# This file is a Tcl script to test the [tcl_startOf|endOf]* functions in
# word.tcl.  It is organized in the standard fashion for Tcl tests.
#
# Copyright © 2024 Jan Nijtmans
# All rights reserved.

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]]

test word-1.0 {tcl_endOfWord} -body {
    tcl_endOfWord "ab cd" -1
} -result 2
test word-1.1 {tcl_endOfWord} -body {
    tcl_endOfWord "ab cd" 0
} -result 2
test word-1.2 {tcl_endOfWord} -body {
    tcl_endOfWord "ab cd" 1
} -result 2
test word-1.3 {tcl_endOfWord} -body {
    tcl_endOfWord "ab cd" 2
} -result -1
test word-1.4 {tcl_endOfWord} -body {
    tcl_endOfWord "ab cd" 3
} -result -1
test word-1.5 {tcl_endOfWord} -body {
    tcl_endOfWord "ab cd" 4
} -result -1
test word-1.6 {tcl_endOfWord} -body {
    tcl_endOfWord "ab cd" 5
} -result -1
test word-1.7 {tcl_endOfWord} -body {
    tcl_endOfWord "ab cd" end
} -result -1
test word-1.8 {tcl_endOfWord} -body {
    tcl_endOfWord "ab cd" end-1
} -result -1
test word-1.9 {tcl_endOfWord} -body {
    tcl_endOfWord "ab cd" {}
} -result 2

test word-2.0 {tcl_startOfPreviousWord} -body {
    tcl_startOfPreviousWord "ab cd" -1
} -result -1
test word-2.1 {tcl_startOfPreviousWord} -body {
    tcl_startOfPreviousWord "ab cd" 0
} -result -1
test word-2.2 {tcl_startOfPreviousWord} -body {
    tcl_startOfPreviousWord "ab cd" 1
} -result 0
test word-2.3 {tcl_startOfPreviousWord} -body {
    tcl_startOfPreviousWord "ab cd" 2
} -result 0
test word-2.4 {tcl_startOfPreviousWord} -body {
    tcl_startOfPreviousWord "ab cd" 3
} -result 0
test word-2.5 {tcl_startOfPreviousWord} -body {
    tcl_startOfPreviousWord "ab cd" 4
} -result 3
test word-2.6 {tcl_startOfPreviousWord} -body {
    tcl_startOfPreviousWord "ab cd" 5
} -result 3
test word-2.7 {tcl_startOfPreviousWord} -body {
    tcl_startOfPreviousWord "ab cd" end
} -result 3
test word-2.8 {tcl_startOfPreviousWord, bug [16e25e1402]} -body {
    tcl_startOfPreviousWord "ab cd" end-1
} -result 0
test word-2.9 {tcl_startOfPreviousWord} -body {
    tcl_startOfPreviousWord "ab cd" {}
} -result -1

test word-3.0 {tcl_startOfNextWord} -body {
    tcl_startOfNextWord "ab cd" -1
} -result 3
test word-3.1 {tcl_startOfNextWord} -body {
    tcl_startOfNextWord "ab cd" 0
} -result 3
test word-3.2 {tcl_startOfNextWord} -body {
    tcl_startOfNextWord "ab cd" 1
} -result 3
test word-3.3 {tcl_startOfNextWord} -body {
    tcl_startOfNextWord "ab cd" 2
} -result 3
test word-3.4 {tcl_startOfNextWord} -body {
    tcl_startOfNextWord "ab cd" 3
} -result -1
test word-3.5 {tcl_startOfNextWord} -body {
    tcl_startOfNextWord "ab cd" 4
} -result -1
test word-3.6 {tcl_startOfNextWord} -body {
    tcl_startOfNextWord "ab cd" 5
} -result -1
test word-3.7 {tcl_startOfNextWord} -body {
    tcl_startOfNextWord "ab cd" end
} -result -1
test word-3.8 {tcl_startOfNextWord} -body {
    tcl_startOfNextWord "ab cd" end-1
} -result -1
test word-3.9 {tcl_startOfNextWord} -body {
    tcl_startOfNextWord "ab cd" {}
} -result 3

test word-4.0 {tcl_wordBreakBefore} -body {
    tcl_wordBreakBefore "ab cd" -1
} -result -1
test word-4.1 {tcl_wordBreakBefore} -body {
    tcl_wordBreakBefore "ab cd" 0
} -result -1
test word-4.2 {tcl_wordBreakBefore} -body {
    tcl_wordBreakBefore "ab cd" 1
} -result -1
test word-4.3 {tcl_wordBreakBefore} -body {
    tcl_wordBreakBefore "ab cd" 2
} -result 2
test word-4.4 {tcl_wordBreakBefore} -body {
    tcl_wordBreakBefore "ab cd" 3
} -result 3
test word-4.5 {tcl_wordBreakBefore} -body {
    tcl_wordBreakBefore "ab cd" 4
} -result 3
test word-4.6 {tcl_wordBreakBefore} -body {
    tcl_wordBreakBefore "ab cd" 5
} -result 3
test word-4.7 {tcl_wordBreakBefore} -body {
    tcl_wordBreakBefore "ab cd" end
} -result 3
test word-4.8 {tcl_wordBreakBefore} -body {
    tcl_startOfNextWord "ab cd" end-1
} -result -1
test word-4.9 {tcl_wordBreakBefore} -body {
    tcl_wordBreakBefore "ab cd" {}
} -result -1

test word-5.0 {tcl_wordBreakAfter} -body {
    tcl_wordBreakAfter "ab cd" -1
} -result 2
test word-5.1 {tcl_wordBreakAfter} -body {
    tcl_wordBreakAfter "ab cd" 0
} -result 2
test word-5.2 {tcl_wordBreakAfter} -body {
    tcl_wordBreakAfter "ab cd" 1
} -result 2
test word-5.3 {tcl_wordBreakAfter} -body {
    tcl_wordBreakAfter "ab cd" 2
} -result 3
test word-5.4 {tcl_wordBreakAfter} -body {
    tcl_wordBreakAfter "ab cd" 3
} -result -1
test word-5.5 {tcl_wordBreakAfter} -body {
    tcl_wordBreakAfter "ab cd" 4
} -result -1
test word-5.6 {tcl_wordBreakAfter} -body {
    tcl_wordBreakAfter "ab cd" 5
} -result -1
test word-5.7 {tcl_wordBreakAfter} -body {
    tcl_wordBreakAfter "ab cd" end
} -result -1
test word-5.8 {tcl_wordBreakAfter} -body {
    tcl_wordBreakAfter "ab cd" end-1
} -result -1
test word-5.9 {tcl_wordBreakAfter} -body {
    tcl_wordBreakAfter "ab cd" {}
} -result 2

test word-6.0 {tcl_startOfPreviousWord} -body {
    tcl_startOfPreviousWord a b c d
} -returnCodes 1 -result {wrong # args: should be "tcl_startOfPreviousWord str start"}
test word-6.1 {tcl_startOfNextWord} -body {
    tcl_startOfNextWord a b c d
} -returnCodes 1 -result {wrong # args: should be "tcl_startOfNextWord str start"}
test word-6.2 {tcl_endOfWord} -body {
    tcl_endOfWord a b c d
} -returnCodes 1 -result {wrong # args: should be "tcl_endOfWord str start"}
test word-6.3 {tcl_wordBreakBefore} -body {
    tcl_wordBreakBefore a b c d
} -returnCodes 1 -result {wrong # args: should be "tcl_wordBreakBefore str start"}
test word-6.4 {tcl_wordBreakAfter} -body {
    tcl_wordBreakAfter a b c d
} -returnCodes 1 -result {wrong # args: should be "tcl_wordBreakAfter str start"}

# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Added tests/zipfiles/LICENSE-libzip.
































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
30
31
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner

The authors can be contacted at <info@libzip.org>

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright
  notice, this list of conditions and the following disclaimer in
  the documentation and/or other materials provided with the
  distribution.

3. The names of the authors may not be used to endorse or promote
  products derived from this software without specific prior
  written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Added tests/zipfiles/README.








1
2
3
4
5
6
7
+
+
+
+
+
+
+
The files in this directory are used for testing zipfs file systems.
They fall under the following licenses:

test-overlay.zip, test-password[2].zip, test-zip-in-zip.zip - Tcl's license

All other files - test files from libzip (https://libzip.org) and are covered by
the license in LICENSE-libzip.

Added tests/zipfiles/broken.zip.

cannot compute difference between binary files

Added tests/zipfiles/empty.zip.

cannot compute difference between binary files

Added tests/zipfiles/incons-cdoffset.zip.

cannot compute difference between binary files

Added tests/zipfiles/incons-central-crc.zip.

cannot compute difference between binary files

Added tests/zipfiles/incons-central-magic-bad.zip.

cannot compute difference between binary files

Added tests/zipfiles/incons-file-count-high.zip.

cannot compute difference between binary files

Added tests/zipfiles/incons-file-count-low.zip.

cannot compute difference between binary files

Added tests/zipfiles/incons-local-crc.zip.

cannot compute difference between binary files

Added tests/zipfiles/incons-local-magic-bad.zip.

cannot compute difference between binary files

Added tests/zipfiles/junk-at-end.zip.

cannot compute difference between binary files

Added tests/zipfiles/junk-at-start.zip.

cannot compute difference between binary files

Added tests/zipfiles/streamed.zip.

cannot compute difference between binary files

Added tests/zipfiles/test-overlay.zip.

cannot compute difference between binary files

Added tests/zipfiles/test-password.zip.

cannot compute difference between binary files

Added tests/zipfiles/test-password2.zip.

cannot compute difference between binary files

Added tests/zipfiles/test-paths.zip.

cannot compute difference between binary files

Added tests/zipfiles/test-zip-in-zip.zip.

cannot compute difference between binary files

Added tests/zipfiles/test.zip.

cannot compute difference between binary files

Added tests/zipfiles/testbzip2.zip.

cannot compute difference between binary files

Added tests/zipfiles/testdeflated2.zip.

cannot compute difference between binary files

Added tests/zipfiles/testfile-UTF8.zip.

cannot compute difference between binary files

Added tests/zipfiles/testfile-cp437.zip.

cannot compute difference between binary files

Added tests/zipfiles/testfile-lzma.zip.

cannot compute difference between binary files

Added tests/zipfiles/testfile-nocompression.zip.

cannot compute difference between binary files

Added tests/zipfiles/testfile-xz.zip.

cannot compute difference between binary files

Added tests/zipfiles/testfile-zstd.zip.

cannot compute difference between binary files

Added tests/zipfiles/teststored.zip.

cannot compute difference between binary files

Added tests/zipfiles/zip64.zip.

cannot compute difference between binary files

Changes to tests/zipfs.test.

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
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
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



30
31
32
33

34








35




36
37
38
39
40
41
42
43
44
45






-
-
+
+
+



+





+

-
+
-
-
-
-
+
+
-
-
-
-
-
+





-
-
-




-
+
-
-
-
-
-
-
-
-
+
-
-
-
-
+
+
+







# The file tests the tclZlib.c file.
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1996-1998 by Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996-1998 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2023 Ashok P. Nadkarni
#
# 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::*
}
source [file join [file dirname [info script]] tcltests.tcl]

testConstraint zipfs [expr {
testConstraint zipfs [expr {[llength [info commands zipfs]]}]
    [llength [info commands zlib]] && [regexp tcltest [info nameofexecutable]]
}]
testConstraint zipfslib 1

testConstraint thread [expr {0 == [catch {package require Thread 2.8-}]}]

# Removed in tip430 - zipfs is no longer a static package
#test zipfs-0.0 {zipfs basics} -constraints zipfs -body {
#    load {} zipfs
#} -result {}


set ziproot [zipfs root]
set CWD [pwd]
set tmpdir  [file join $CWD tmp]
file mkdir $tmpdir

test zipfs-0.0 {zipfs basics} -constraints zipfs -body {
    package require zipfs
} -result {2.0}
test zipfs-0.1 {zipfs basics} -constraints zipfs -body {
    expr {${ziproot} in [file volumes]}
} -result 1

if {![string match ${ziproot}* $tcl_library]} {
if {[string match ${ziproot}* $tcl_library]} {
    ###
    # "make test" does not map tcl_library from the dynamic library on Unix
    #
    # Hack the environment to pretend we did pull tcl_library from a zip
    # archive
    ###
    set tclzip [file join $CWD [::tcl::pkgconfig get zipfile,runtime]]
    testConstraint zipfslib [file isfile $tclzip]
    testConstraint zipfslib 1
    if {[testConstraint zipfslib]} {
        zipfs mount /lib/tcl $tclzip
        set ::tcl_library ${ziproot}lib/tcl/tcl_library
    }
    set zipLibTop [file tail [file join {*}[lrange [file split $tcl_library] 0 1]]]
} else {
    set zipLibTop ""
}

test zipfs-0.2 {zipfs basics} -constraints zipfslib -body {
    string match ${ziproot}* $tcl_library
} -result 1
test zipfs-0.3 {zipfs basics: glob} -constraints zipfslib -setup {
    set pwd [pwd]
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
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







-
-
+
+

-
-
+
+

-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
















-
+



-
-
+
+







test zipfs-0.8 {zipfs basics: glob} -constraints zipfslib -body {
    expr { "http" in [glob -nocomplain -tails -types d -dir $tcl_library http*] }
} -result 1
test zipfs-0.9 {zipfs basics: glob} -constraints zipfslib -body {
    glob -nocomplain -tails -types f -dir $tcl_library http*
} -result {}
test zipfs-0.10 {zipfs basics: join} -constraints {zipfs zipfslib} -body {
    file join [zipfs root] bar baz
} -result "[zipfs root]bar/baz"
    file join ${ziproot} bar baz
} -result "${ziproot}bar/baz"
test zipfs-0.11 {zipfs basics: join} -constraints {zipfs zipfslib} -body {
    file normalize [zipfs root]
} -result "[zipfs root]"
    file normalize ${ziproot}
} -result "${ziproot}"
test zipfs-0.12 {zipfs basics: join} -constraints {zipfs zipfslib} -body {
    file normalize [zipfs root]//bar/baz//qux/../
} -result "[zipfs root]bar/baz"
    file normalize ${ziproot}//bar/baz//qux/../
} -result "${ziproot}bar/baz"

test zipfs-1.3 {zipfs errors} -constraints zipfs -returnCodes error -body {
    zipfs mount a b c d e f
} -result {wrong # args: should be "zipfs mount ?mountpoint? ?zipfile? ?password?"}
test zipfs-1.4 {zipfs errors} -constraints zipfs -returnCodes error -body {
    zipfs unmount a b c d e f
} -result {wrong # args: should be "zipfs unmount zipfile"}
test zipfs-1.5 {zipfs errors} -constraints zipfs -returnCodes error -body {
    zipfs mkkey a b c d e f
} -result {wrong # args: should be "zipfs mkkey password"}
test zipfs-1.6 {zipfs errors} -constraints zipfs -returnCodes error -body {
    zipfs mkimg a b c d e f
} -result {wrong # args: should be "zipfs mkimg outfile indir ?strip? ?password? ?infile?"}
test zipfs-1.7 {zipfs errors} -constraints zipfs -returnCodes error -body {
    zipfs mkzip a b c d e f
} -result {wrong # args: should be "zipfs mkzip outfile indir ?strip? ?password?"}
test zipfs-1.8 {zipfs errors} -constraints zipfs -returnCodes error -body {
    zipfs exists a b c d e f
} -result {wrong # args: should be "zipfs exists filename"}
test zipfs-1.9 {zipfs errors} -constraints zipfs -returnCodes error -body {
    zipfs info a b c d e f
} -result {wrong # args: should be "zipfs info filename"}
test zipfs-1.10 {zipfs errors} -constraints zipfs -returnCodes error -body {
    zipfs list a b c d e f
} -result {wrong # args: should be "zipfs list ?(-glob|-regexp)? ?pattern?"}

file mkdir tmp
test zipfs-2.1 {zipfs mkzip empty archive} -constraints zipfs -returnCodes error -body {
    zipfs mkzip [file join $tmpdir empty.zip] $tcl_library/xxxx
} -result {empty archive}
###
# The next series of tests operate within a zipfile created a temporary
# directory.
###
set zipfile [file join $tmpdir abc.zip]
if {[file exists $zipfile]} {
   file delete $zipfile
}
test zipfs-2.2 {zipfs mkzip} -constraints zipfs -body {
    cd $tcl_library/encoding
    zipfs mkzip $zipfile .
    zipfs mount ${ziproot}abc $zipfile
    zipfs mount $zipfile ${ziproot}abc
    zipfs list -glob ${ziproot}abc/cp850.*
} -cleanup {
    cd $CWD
} -result "[zipfs root]abc/cp850.enc"
testConstraint zipfsenc [zipfs exists /abc/cp850.enc]
} -result "${ziproot}abc/cp850.enc"
testConstraint zipfsenc [zipfs exists ${ziproot}abc/cp850.enc]
test zipfs-2.3 {zipfs info} -constraints {zipfs zipfsenc} -body {
    set r [zipfs info ${ziproot}abc/cp850.enc]
    lrange $r 0 2
} -result [list $zipfile 1090 527] ;# NOTE: Only the first 3 results are stable
test zipfs-2.4 {zipfs data} -constraints {zipfs zipfsenc} -body {
    set zipfd [open ${ziproot}/abc/cp850.enc]	;# FIXME: leave open - see later test
    read $zipfd
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
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







-
+



















-
+



-
-
+
+







2591259225932502252400C100C200C000A9256325512557255D00A200A52510
25142534252C251C2500253C00E300C3255A25542569256625602550256C00A4
00F000D000CA00CB00C8013100CD00CE00CF2518250C2588258400A600CC2580
00D300DF00D400D200F500D500B500FE00DE00DA00DB00D900FD00DD00AF00B4
00AD00B1201700BE00B600A700F700B800B000A800B700B900B300B225A000A0
} ;# FIXME: result depends on content of encodings dir
test zipfs-2.5 {zipfs exists} -constraints {zipfs zipfsenc} -body {
    zipfs exists /abc/cp850.enc
    zipfs exists ${ziproot}abc/cp850.enc
} -result 1
test zipfs-2.6 {zipfs unmount while busy} -constraints {zipfs zipfsenc} -body {
    zipfs unmount /abc
} -returnCodes error -result {filesystem is busy}
test zipfs-2.7 {zipfs unmount} -constraints {zipfs zipfsenc} -body {
    close $zipfd
    zipfs unmount /abc
    zipfs exists /abc/cp850.enc
} -result 0
###
# Repeat the tests for a buffer mounted archive
###
test zipfs-2.8 {zipfs mkzip} -constraints zipfs -body {
    cd $tcl_library/encoding
    zipfs mkzip $zipfile .
    set fin [open $zipfile r]
    fconfigure $fin -translation binary
    set dat [read $fin]
    close $fin
    zipfs mount_data def $dat
    zipfs mountdata $dat def
    zipfs list -glob ${ziproot}def/cp850.*
} -cleanup {
    cd $CWD
} -result "[zipfs root]def/cp850.enc"
testConstraint zipfsencbuf [zipfs exists /def/cp850.enc]
} -result "${ziproot}def/cp850.enc"
testConstraint zipfsencbuf [zipfs exists ${ziproot}def/cp850.enc]
test zipfs-2.9 {zipfs info} -constraints {zipfs zipfsencbuf} -body {
    set r [zipfs info ${ziproot}def/cp850.enc]
    lrange $r 0 2
} -result [list {Memory Buffer} 1090 527] ;# NOTE: Only the first 3 results are stable
test zipfs-2.10 {zipfs data} -constraints {zipfs zipfsencbuf} -body {
    set zipfd [open ${ziproot}/def/cp850.enc]	;# FIXME: leave open - see later test
    read $zipfd
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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965







-
+




















-
+

















+
-
-
+
+



-
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







2591259225932502252400C100C200C000A9256325512557255D00A200A52510
25142534252C251C2500253C00E300C3255A25542569256625602550256C00A4
00F000D000CA00CB00C8013100CD00CE00CF2518250C2588258400A600CC2580
00D300DF00D400D200F500D500B500FE00DE00DA00DB00D900FD00DD00AF00B4
00AD00B1201700BE00B600A700F700B800B000A800B700B900B300B225A000A0
} ;# FIXME: result depends on content of encodings dir
test zipfs-2.11 {zipfs exists} -constraints {zipfs zipfsencbuf} -body {
    zipfs exists /def/cp850.enc
    zipfs exists ${ziproot}def/cp850.enc
} -result 1
test zipfs-2.12 {zipfs unmount while busy} -constraints {zipfs zipfsencbuf} -body {
    zipfs unmount /def
} -returnCodes error -result {filesystem is busy}
test zipfs-2.13 {zipfs unmount} -constraints {zipfs zipfsencbuf} -body {
    close $zipfd
    zipfs unmount /def
    zipfs exists /def/cp850.enc
} -result 0

catch {file delete -force $tmpdir}

test zipfs-3.1 {zipfs in child interpreters} -constraints zipfs -setup {
    set interp [interp create]
} -body {
    interp eval $interp {
	zipfs ?
    }
} -returnCodes error -cleanup {
    interp delete $interp
} -result {unknown or ambiguous subcommand "?": must be canonical, exists, find, info, list, lmkimg, lmkzip, mkimg, mkkey, mkzip, mount, mount_data, root, or unmount}
} -result {unknown or ambiguous subcommand "?": must be canonical, exists, find, info, list, lmkimg, lmkzip, mkimg, mkkey, mkzip, mount, mountdata, root, or unmount}
test zipfs-3.2 {zipfs in child interpreters} -constraints zipfs -setup {
    set interp [interp create]
} -body {
    interp eval $interp {
	zipfs mkzip
    }
} -returnCodes error -cleanup {
    interp delete $interp
} -result {wrong # args: should be "zipfs mkzip outfile indir ?strip? ?password?"}
test zipfs-3.3 {zipfs in child interpreters} -constraints zipfs -setup {
    set safe [interp create -safe]
} -body {
    interp eval $safe {
	zipfs ?
    }
} -returnCodes error -cleanup {
    interp delete $safe
} -result {invalid command name "zipfs"}
} -result {unknown or ambiguous subcommand "?": must be canonical, exists, find, info, list, lmkimg, lmkzip, mkimg, mkkey, mkzip, mount, mount_data, root, or unmount}
test zipfs-3.4 {zipfs in child interpreters} -constraints zipfs -setup {

test zipfs-3.4 {zipfs in safe interpreters} -constraints zipfs -setup {
    set safe [interp create -safe]
} -body {
    interp eval $safe {
	zipfs mkzip
	zipfs
    }
} -returnCodes error -cleanup {
    interp delete $safe
} -result {invalid command name "zipfs"}

test zipfs-4.1 {zipfs lmkimg} -constraints zipfs -setup {
    set baseImage [makeFile "return sourceWorking\n\x1A" base]
    set targetImage [makeFile "" target]
    set addFile [makeFile "return mountWorking" add.data]
    file delete $targetImage
} -body {
    zipfs lmkimg $targetImage [list $addFile test/add.tcl] {} $baseImage
    zipfs mount $targetImage ziptest
    try {
	list [source $targetImage] [source ${ziproot}ziptest/test/add.tcl]
    } finally {
	zipfs unmount ziptest
    }
} -cleanup {
    removeFile $baseImage
    removeFile $targetImage
    removeFile $addFile
} -result {sourceWorking mountWorking}
test zipfs-4.2 {zipfs lmkimg: making an image from an image} -constraints zipfs -setup {
    set baseImage [makeFile "return sourceWorking\n\x1A" base_image.tcl]
    set midImage [makeFile "" mid_image.tcl]
    set targetImage [makeFile "" target_image.tcl]
    set addFile [makeFile "return mountWorking" add.data]
    file delete $midImage $targetImage
} -body {
    zipfs lmkimg $midImage [list $addFile test/ko.tcl] {} $baseImage
    zipfs lmkimg $targetImage [list $addFile test/ok.tcl] {} $midImage
    zipfs mount $targetImage ziptest
    try {
	list [glob -tails -directory ${ziproot}/ziptest/test *.tcl] \
	    [if {[file size $midImage] == [file size $targetImage]} {
		string cat equal
	    } else {
		list mid=[file size $midImage] target=[file size $targetImage]
	    }]
    } finally {
	zipfs unmount ziptest
    }
} -cleanup {
    removeFile $baseImage
    removeFile $midImage
    removeFile $targetImage
    removeFile $addFile
} -result {ok.tcl equal}
test zipfs-4.3 {zipfs lmkimg: stripping password} -constraints zipfs -setup {
    set baseImage [makeFile "return sourceWorking\n\x1A" base_image.tcl]
    set midImage [makeFile "" mid_image.tcl]
    set targetImage [makeFile "" target_image.tcl]
    set addFile [makeFile "return mountWorking" add.data]
    file delete $midImage $targetImage
} -body {
    set pass gorp
    zipfs lmkimg $midImage [list $addFile test/add.tcl] $pass $baseImage
    zipfs lmkimg $targetImage [list $addFile test/ok.tcl] {} $midImage
    zipfs mount $targetImage ziptest
    try {
	glob -tails -directory ${ziproot}/ziptest/test *.tcl
    } finally {
	zipfs unmount ziptest
    }
} -cleanup {
    removeFile $baseImage
    removeFile $midImage
    removeFile $targetImage
    removeFile $addFile
} -result {ok.tcl}
test zipfs-4.4 {zipfs lmkimg: final password} -constraints zipfs -setup {
    set baseImage [makeFile "return sourceWorking\n\x1A" base_image.tcl]
    set midImage [makeFile "" mid_image.tcl]
    set targetImage [makeFile "" target_image.tcl]
    set addFile [makeFile "return mountWorking" add.data]
    file delete $midImage $targetImage
} -body {
    set pass gorp
    zipfs lmkimg $midImage [list $addFile test/add.tcl] {} $baseImage
    zipfs lmkimg $targetImage [list $addFile test/ok.tcl] $pass $midImage
    zipfs mount $targetImage ziptest
    try {
	glob -tails -directory ${ziproot}/ziptest/test *.tcl
    } finally {
	zipfs unmount ziptest
    }
} -cleanup {
    removeFile $baseImage
    removeFile $midImage
    removeFile $targetImage
    removeFile $addFile
} -result {ok.tcl}
test zipfs-4.5 {zipfs lmkimg: making image from mounted} -constraints zipfs -setup {
    set baseImage [makeFile "return sourceWorking\n\x1A" base_image.tcl]
    set midImage [makeFile "" mid_image.tcl]
    set targetImage [makeFile "" target_image.tcl]
    set addFile [makeFile "return mountWorking" add.data]
    file delete $midImage $targetImage
} -body {
    zipfs lmkimg $midImage [list $addFile test/add.tcl] {} $baseImage
    zipfs mount $midImage ziptest
    set f [glob -directory ${ziproot}/ziptest/test *.tcl]
    zipfs lmkimg $targetImage [list $f test/ok.tcl] {} $midImage
    zipfs unmount ziptest
    zipfs mount $targetImage ziptest
    list $f [glob -directory ${ziproot}/ziptest/test *.tcl]
} -cleanup {
    zipfs unmount ziptest
    removeFile $baseImage
    removeFile $midImage
    removeFile $targetImage
    removeFile $addFile
} -result [list ${ziproot}/ziptest/test/add.tcl ${ziproot}/ziptest/test/ok.tcl]

test zipfs-5.1 {zipfs mountdata: short data} -constraints zipfs -body {
    zipfs mountdata {} gorp
} -returnCodes error -result {illegal file size}
test zipfs-5.2 {zipfs mountdata: short data} -constraints zipfs -body {
    zipfs mountdata gorpGORPgorp gorp
} -returnCodes error -result {illegal file size}
test zipfs-5.3 {zipfs mountdata: short data} -constraints zipfs -body {
    set data PK\x03\x04.....................................
    append data PK\x01\x02.....................................
    append data PK\x05\x06.....................................
    zipfs mountdata $data gorp
} -returnCodes error -result {archive directory truncated}

test zipfs-6.1 {zipfs mkkey} -constraints zipfs -body {
    binary scan [zipfs mkkey gorp] cu* x
    return $x
} -result {224 226 111 103 4 80 75 90 90}


#
# Additional tests for more coverage. Some of the ones above may be duplicated.

namespace eval test_ns_zipfs {
    namespace import ::tcltest::test
    namespace path ::tcltests
    variable zipTestDir [file normalize [file join [file dirname [info script]] zipfiles]]
    variable defMountPt [file join [zipfs root] testmount]

    proc readbin {path} {
	set fd [open $path rb]
	set data [read $fd]
	close $fd
	return $data
    }

    # Wrapper to ease transition if Tcl changes order of argument to zipfs mount
    # or the zipfs prefix
    proc mount [list zippath [list mountpoint $defMountPt]] {
	return [zipfs mount $zippath $mountpoint]
    }

    # Make full path to zip file
    proc zippath {zippath} {
	variable zipTestDir
	if {[file pathtype $zippath] eq "absolute"} {
	    return $zippath
	} else {
	    return [file join $zipTestDir $zippath]
	}
    }

    # list of paths -> list of paths under mount point mt
    proc zipfspathsmt {mt args} {
	return [lsort [lmap path $args {file join $mt $path}]]
    }

    # list of paths -> list of paths under [zipfs root]
    proc zipfspaths {args} {
	return [zipfspathsmt [zipfs root] {*}$args]
    }

    proc cleanup {} {
	dict for {mount -} [zipfs mount] {
	    if {[string match //zipfs:/test* $mount]} {
		zipfs unmount $mount
	    }
	}
	zipfs unmount [zipfs root]
    }

    proc mounttarget {mountpoint} {
	return [dict getdef [zipfs mount] $mountpoint ""]
    }

    #
    # zipfs root - only arg count check since do not want to assume
    # what it resolves to
    testnumargs "zipfs root" "" ""

    #
    # zipfs mount

    proc testbadmount {id zippath messagePattern args} {
	variable defMountPt
	set zippath [zippath $zippath]
	test zipfs-mount-$id $id -body {
	    list [catch {mount $zippath} message] \
		[string match $messagePattern $message] \
		[mounttarget $defMountPt]
	} -cleanup {
	    # In case mount succeeded when it should not
	    cleanup
	} -result {1 1 {}} {*}$args

	if {![file exists $zippath]} {
	    return
	}
	set data [readbin $zippath]
	test zipfs-mountdata-$id $id -body {
	    list [catch {zipfs mountdata $data $defMountPt} message] \
		[string match $messagePattern $message] \
		[mounttarget $defMountPt]
	} -cleanup {
	    # In case mount succeeded when it should not
	    cleanup
	} -result {1 1 {}} {*}$args
    }

    # Generates tests for file, file on root, memory buffer cases for an archive
    proc testmount {id zippath checkPath mountpoint args} {
	set zippath [zippath $zippath]
	test zipfs-mount-$id "zipfs mount $id" -body {
	    set canon [mount $zippath $mountpoint]
	    list [file exists [file join $canon $checkPath]] \
		[zipfs mount $canon] [zipfs mount $mountpoint]
	} -cleanup {
	    zipfs unmount $mountpoint
	} -result [list 1 $zippath $zippath] {*}$args

	# Mount memory buffer
	test zipfs-mountdata-$id "zipfs mountdata $id" -body {
	    set canon [zipfs mountdata [readbin $zippath] $mountpoint]
	    list [file exists [file join $canon $checkPath]] \
		[zipfs mount $canon] [zipfs mount $mountpoint]
	} -cleanup {
	    cleanup
	} -result [list 1 {Memory Buffer} {Memory Buffer}] {*}$args

    }

    testnumargs "zipfs mount" "" "?zipfile? ?mountpoint? ?password?"
    testnumargs "zipfs mountdata" "data mountpoint" ""

    # Not supported zip files
    testbadmount non-existent-file    nosuchfile.zip "couldn't open*nosuchfile.zip*no such file or directory"
    testbadmount not-zipfile          [file normalize [info script]]      "archive directory end signature not found"
    testbadmount zip64-unsupported    zip64.zip      "wrong header signature"

    # Inconsistent metadata
    testbadmount bad-directory-offset incons-cdoffset.zip          "archive directory truncated"
    testbadmount bad-directory-magic  incons-central-magic-bad.zip "wrong header signature"
    testbadmount bad-local-magic      incons-local-magic-bad.zip   "Failed to find local header"
    testbadmount bad-file-count-high  incons-file-count-high.zip   "truncated directory"
    testbadmount bad-file-count-low   incons-file-count-low.zip    "short file count"

    test zipfs-mount-on-drive "Mount point include drive" -body {
	zipfs mount [zippath test.zip] C:/foo
    } -result {Invalid mount path "C:/foo"} -returnCodes error -constraints win
    test zipfs-mountdata-on-drive "Mount point include drive" -body {
	zipfs mountdata [readbin [zippath test.zip]] C:/foo
    } -result {Invalid mount path "C:/foo"} -returnCodes error -constraints win
    test zipfs-mount-on-unc "Mount point is unc" -body {
	zipfs mount [zippath test.zip] //unc/share/foo
    } -result {Invalid mount path "//unc/share/foo"} -returnCodes error
    test zipfs-mountdata-on-unc "Mount point include unc" -body {
	zipfs mountdata [readbin [zippath test.zip]] //unc/share/foo
    } -result {Invalid mount path "//unc/share/foo"} -returnCodes error

    # Good mounts
    testmount basic             test.zip           testdir/test2 $defMountPt
    testmount basic-on-default  test.zip           testdir/test2 ""
    testmount basic-on-root     test.zip           testdir/test2 [zipfs root]
    testmount basic-on-slash    test.zip           testdir/test2 /
    testmount basic-on-bslash   test.zip           testdir/test2 \\ -constraints win
    testmount basic-on-relative test.zip           testdir/test2 testmount
    testmount basic-on-absolute test.zip           testdir/test2 /testmount
    testmount basic-on-absolute-bslash test.zip    testdir/test2 \\testmount -constraints win
    testmount zip-at-end        junk-at-start.zip  testdir/test2 $defMountPt
    testmount zip-at-start      junk-at-end.zip    testdir/test2 $defMountPt
    testmount zip-in-zip [file join [zipfs root] test2 test.zip] testdir/test2 $defMountPt -setup {
	mount [zippath test-zip-in-zip.zip] [file join [zipfs root] test2]
    } -cleanup {
	zipfs unmount $mountpoint
	zipfs unmount [file join [zipfs root] test2]
    }
    testmount relative-mount-point test.zip testdir/test2 ""

    test zipfs-mount-busy-1 "Attempt to mount on existing mount point" -setup {
	mount [zippath test.zip]
    } -cleanup {
	cleanup
    } -body {
	zipfs mount [zippath testfile-cp437.zip] $defMountPt
    } -result "[zippath test.zip] is already mounted on $defMountPt" -returnCodes error

    test zipfs-mount-no-args-1 "mount - get mount list" -setup {
	mount [zippath test.zip]
    } -cleanup {
	cleanup
    } -body {
	set mounts [zipfs mount]
	lsearch -inline -stride 2 $mounts $defMountPt
    } -result [list $defMountPt [zippath test.zip]]

    test zipfs-mount-one-arg-1 "mount - get mount target - absolute path" -setup {
	mount [zippath test.zip]
    } -cleanup {
	cleanup
    } -body {
	zipfs mount $defMountPt
    } -result [zippath test.zip]

    test zipfs-mount-one-arg-2 "mount - get mount target - relative path" -setup {
	file copy [zippath test.zip] test.zip
	mount ./test.zip
    } -cleanup {
	cleanup
	file delete ./test.zip
    } -body {
	zipfs mount $defMountPt
    } -result [file normalize ./test.zip]

    test zipfs-mount-password-1 "mount - verify plaintext readable without password" -body {
	zipfs mount [zippath test-password.zip] $defMountPt
	readbin [file join $defMountPt plain.txt]
    } -cleanup {
	cleanup
    } -result plaintext

    test zipfs-mount-password-2 "mount - verify uncompressed cipher unreadable without password" -body {
	zipfs mount [zippath test-password.zip] $defMountPt
	set chans [lsort [chan names]]; # Want to ensure open does not leave dangling channel
	set result [list ]
	lappend result [catch {open [file join $defMountPt cipher.bin]} message]
	lappend result $message
	lappend result [string equal $chans [lsort [chan names]]]
    } -cleanup {
	cleanup
    } -result {1 {decryption failed - no password provided} 1}

    test zipfs-mount-password-3 "mount - verify compressed cipher unreadable without password" -body {
	zipfs mount [zippath test-password.zip] $defMountPt
	set chans [lsort [chan names]]; # Want to ensure open does not leave dangling channel
	set result [list ]
	lappend result [catch {open [file join $defMountPt cipher-deflate.bin]} message]
	lappend result $message
	lappend result [string equal $chans [lsort [chan names]]]
    } -cleanup {
	cleanup
    } -result {1 {decryption failed - no password provided} 1}

    test zipfs-mount-nested-1 "mount - nested mount on non-existing path" -setup {
	mount [zippath test.zip]
    } -cleanup {
	cleanup
    } -body {
	set newmount [file join $defMountPt newdir]
	mount [zippath test-overlay.zip] $newmount
	list \
	    [lsort [glob -tails -dir $defMountPt *]] \
	    [lsort [glob -tails -dir $newmount *]] \
	    [readbin [file join $newmount test2]]
    } -result {{newdir test testdir} {test2 test3} test2-overlay}

    test zipfs-mount-nested-2 "mount - nested mount on existing path" -setup {
	mount [zippath test.zip]
    } -cleanup {
	cleanup
    } -body {
	set newmount [file join $defMountPt testdir]
	mount [zippath test-overlay.zip] $newmount
	# Note - file from existing mount is preserved (testdir/test2)
	# Not clear this is desired but defined as such by the
	# current implementation
	list \
	    [lsort [glob -tails -dir $defMountPt *]] \
	    [lsort [glob -tails -dir $newmount *]] \
	    [readbin [file join $newmount test2]]
    } -result [list {test testdir} {test2 test3} test\n]

    #
    # unmount - only special cases. Normal case already tested as part of other tests

    testnumargs "zipfs unmount" "mountpoint" ""

    test zipfs-unmount-1 "Unmount bogus mount" -body {
	zipfs unmount [file join [zipfs root] nosuchmount]
    } -result ""

    test zipfs-unmount-2 "Unmount mount with open files" -setup {
	mount [zippath test.zip]
	set fd [open [file join $defMountPt test]]
    } -cleanup {
	close $fd
	cleanup
    } -body {
	zipfs unmount $defMountPt
    } -result {filesystem is busy} -returnCodes error

    test zipfs-unmount-3 "Unmount mount with current directory" -setup {
	set cwd [pwd]
	mount [zippath test.zip]
    } -cleanup {
	cd $cwd
	cleanup
    } -body {
	# Current directory does not change on unmount.
	# This is the same behavior as when USB pen drive is unmounted
	set cwd2 [file join $defMountPt testdir]
	cd $cwd2
	list [pwd] [zipfs unmount $defMountPt] [string equal [pwd] $cwd2]
    } -result [list [file join $defMountPt testdir] {} 1]

    test zipfs-unmount-nested-1 "unmount parent of nested mount on new directory should not affect nested mount" -setup {
	mount [zippath test.zip]
	set newmount [file join [zipfs root] test newdir]
	mount [zippath test-overlay.zip] $newmount
    } -cleanup {
	cleanup
    } -body {
	zipfs unmount $defMountPt
	list \
	    [zipfs mount $defMountPt] \
	    [lsort [glob -tails -dir $newmount *]] \
	    [readbin [file join $newmount test2]]
    } -result {{} {test2 test3} test2-overlay}

    test zipfs-unmount-nested-2 "unmount parent of nested mount on existing directory should not affect nested mount" -setup {
	mount [zippath test.zip]
	set newmount [file join [zipfs root] test testdir]
	mount [zippath test-overlay.zip] $newmount
    } -constraints bug-4ae42446ab -cleanup {
	cleanup
    } -body {
	# KNOWN BUG. The test2 file is also present in parent mount.
	# After the unmount, the test2 in the nested mount is not
	# made available.
	zipfs unmount $defMountPt
	list \
	    [zipfs mount $defMountPt] \
	    [lsort [glob -tails -dir $newmount *]] \
	    [readbin [file join $newmount test2]]
    } -result {{} {test2 test3} test2-overlay}

    #
    # paths inside a zip
    # TODO - paths encoded in utf-8 vs fallback encoding
    test zipfs-content-paths-1 "Test absolute and full paths" -setup {
	mount [zippath test-paths.zip]
    } -cleanup {
	cleanup
    } -body {
	# Primarily verifies that drive letters are stripped and paths maintained
	lsort [zipfs find $defMountPt]
    } -result {//zipfs:/testmount/filename.txt //zipfs:/testmount/src //zipfs:/testmount/src/tcltk //zipfs:/testmount/src/tcltk/wip //zipfs:/testmount/src/tcltk/wip/tcl //zipfs:/testmount/src/tcltk/wip/tcl/tests //zipfs:/testmount/src/tcltk/wip/tcl/tests/zipfiles //zipfs:/testmount/src/tcltk/wip/tcl/tests/zipfiles/abspath.txt //zipfs:/testmount/src/tcltk/wip/tcl/tests/zipfiles/fullpath.txt}

    #
    # zipfs list
    testnumargs "zipfs list" "" "?(-glob|-regexp)? ?pattern?"

    # Generates zipfs list tests for file, memory buffer cases for an archive
    proc testzipfslist {id cmdargs mounts resultpaths args} {
	set resultpaths [lmap path $resultpaths {
	    file join [zipfs root] $path
	}]
	set resultpaths [lsort $resultpaths]
	test zipfs-list-$id "zipfs list $id" -body {
	    lsort [zipfs list {*}$cmdargs]
	} -setup {
	    foreach {zippath mountpoint} $mounts {
		zipfs mount [zippath $zippath] [file join [zipfs root] $mountpoint]
	    }
	} -cleanup {
	    cleanup
	} -result $resultpaths {*}$args

	# Mount memory buffer
	test zipfs-list-memory-$id "zipfs list memory $id" -body {
	    lsort [zipfs list {*}$cmdargs]
	} -setup {
	    foreach {zippath mountpoint} $mounts {
		zipfs mountdata [readbin [zippath $zippath]] [file join [zipfs root] $mountpoint]
	    }
	} -cleanup {
	    cleanup
	} -result $resultpaths {*}$args
    }
    # Some tests have !zipfslib constraint because otherwise they dump the entire Tcl library which is mounted on root
    testzipfslist no-mounts                 "" {} {} -constraints !zipfslib
    testzipfslist no-pattern                "" {test.zip testmountA} {testmountA testmountA/test testmountA/testdir testmountA/testdir/test2} -constraints !zipfslib
    testzipfslist no-pattern-mount-on-empty "" {test.zip {}} {{} test testdir testdir/test2} -constraints !zipfslib
    testzipfslist no-pattern-mount-on-root  "" [list test.zip [zipfs root]] {{} test testdir testdir/test2} -constraints !zipfslib
    testzipfslist no-pattern-mount-on-slash "" [list test.zip /] {{} test testdir testdir/test2} -constraints !zipfslib
    testzipfslist no-pattern-mount-on-mezzo "" [list test.zip testmt/a/b] {testmt/a/b testmt/a/b/test testmt/a/b/testdir testmt/a/b/testdir/test2} -constraints {!zipfslib}
    testzipfslist no-pattern-multiple       "" {test.zip testmountA test.zip testmountB/subdir} {
	testmountA testmountA/test testmountA/testdir testmountA/testdir/test2
	testmountB/subdir testmountB/subdir/test testmountB/subdir/testdir testmountB/subdir/testdir/test2
    } -constraints !zipfslib
    testzipfslist glob [list "*testmount*2*"] {test.zip testmountA test.zip testmountB/subdir} {
	testmountA/testdir/test2
	testmountB/subdir/testdir/test2
    }
    testzipfslist opt-glob [list -glob "*testmount*2*"] {test.zip testmountA test.zip testmountB/subdir} {
	testmountA/testdir/test2
	testmountB/subdir/testdir/test2
    }
    testzipfslist opt-regexp [list -regexp "testmount.*(A|2)"] {test.zip testmountA test.zip testmountB/subdir} {
	testmountA testmountA/test testmountA/testdir testmountA/testdir/test2
	testmountB/subdir/testdir/test2
    }

    #
    # zipfs exists
    testnumargs "zipfs exists" "filename" ""

    # Generates tests for zipfs exists
    proc testzipfsexists [list id path result [list mountpoint $defMountPt] args] {
	test zipfs-exists-$id "zipfs exists $id" -body {
	    zipfs exists $path
	} -setup {
	    mount [zippath test.zip] $mountpoint
	} -cleanup {
	    zipfs unmount $mountpoint
	    cleanup
	} -result $result {*}$args
    }
    testzipfsexists native-file  [info nameofexecutable]            0
    testzipfsexists enoent       [file join $defMountPt nosuchfile] 0
    testzipfsexists file         [file join $defMountPt test]       1
    testzipfsexists dir          [file join $defMountPt testdir]    1
    testzipfsexists mountpoint   $defMountPt                        1
    testzipfsexists root         [zipfs root]                       1 $defMountPt
    testzipfsexists mezzo        [file join $defMountPt a b]        1 [file join $defMountPt a b c]
    testzipfsexists mezzo-enoent [file join $defMountPt a c]        0 [file join $defMountPt a b c]

    #
    # zipfs find
    testnumargs "zipfs find" "directoryName" ""
    # Generates zipfs find tests for file, memory buffer cases for an archive
    proc testzipfsfind {id findtarget mounts resultpaths args} {
	set setup {
	    foreach {zippath mountpoint} $mounts {
		zipfs mount [zippath $zippath] [file join [zipfs root] $mountpoint]
	    }
	}
	set memory_setup {
	    foreach {zippath mountpoint} $mounts {
		zipfs mountdata [readbin [zippath $zippath]] [file join [zipfs root] $mountpoint]
	    }
	}
	if {[dict exists $args -setup]} {
	    append setup \n[dict get $args -setup]
	    append memory_setup \n[dict get $args -setup]
	    dict unset args -setup
	}
	set cleanup cleanup
	if {[dict exists $args -cleanup]} {
	    set cleanup "[dict get $args -cleanup]\n$cleanup"
	    dict unset args -cleanup
	}
	set resultpaths [lsort $resultpaths]
	test zipfs-find-$id "zipfs find $id" -body {
	    lsort [zipfs find $findtarget]
	} -setup $setup -cleanup $cleanup -result $resultpaths {*}$args

	# Mount memory buffer
	test zipfs-find-memory-$id "zipfs find memory $id" -body {
	    lsort [zipfs find $findtarget]
	} -setup $memory_setup -cleanup $cleanup -result $resultpaths {*}$args
    }

    testzipfsfind nonexistingmount [file join [zipfs root] nosuchmount] {
	test.zip testmountA test.zip testmountB/subdir
    } {}

    testzipfsfind absolute-path    [file join [zipfs root] testmountA] {
	test.zip testmountA test.zip testmountB/subdir
    } [zipfspaths testmountA/test testmountA/testdir testmountA/testdir/test2]

    testzipfsfind relative-path   testdir {
	test.zip testmountA test.zip testmountB/subdir
    } { testdir/test2 } -setup {
	set cwd [pwd]
	cd [file join [zipfs root] testmountA]
    } -cleanup {
	cd $cwd
    }

    # bug-6183f535c8
    testzipfsfind root-path   [zipfs root] {
	test.zip {} test.zip testmountB/subdir
    } [zipfspaths test testdir testdir/test2 testmountB testmountB/subdir testmountB/subdir/test testmountB/subdir/testdir testmountB/subdir/testdir/test2] -constraints !zipfslib

    testzipfsfind mezzo [file join [zipfs root] testmt a] {
	test.zip testmt/a/b
    } [zipfspaths testmt/a/b testmt/a/b/test testmt/a/b/testdir testmt/a/b/testdir/test2]

    testzipfsfind mezzo-root [zipfs root] {
	test.zip testmt/a/b
    } [zipfspaths testmt testmt/a testmt/a/b testmt/a/b/test testmt/a/b/testdir testmt/a/b/testdir/test2] -constraints !zipfslib

    test zipfs-find-native-absolute "zipfs find on native file system" -setup {
	set dir [makeDirectory zipfs-native-absolute]
	set subdir [file join $dir subdir]
	file mkdir $subdir
	set file [file join $subdir native]
	close [open $file w]
    } -cleanup {
	removeDirectory zipfs-native-absolute
    } -body {
	string equal [zipfs find $dir] [list $subdir $file]
    } -result 1

    test zipfs-find-native-relative "zipfs find relative on native file system" -setup {
	set dir [makeDirectory zipfs-native-relative]
	set subdir [file join $dir subdir]
	file mkdir $subdir
	set file [file join $subdir native]
	close [open $file w]
	set cwd [pwd]
    } -cleanup {
	cd $cwd
	removeDirectory zipfs-native-relative
    } -body {
	cd [file dirname $dir]
	# string equal [zipfs find [file tail $subdir]] [list subdir subdir/native]
	zipfs find [file tail $dir]
    } -result {zipfs-native-relative/subdir zipfs-native-relative/subdir/native}

    #
    # zipfs info
    testnumargs "zipfs info" "filename" ""

    test zipfs-info-native-nosuchfile "zipfs info on non-existent native path" -body {
	zipfs info nosuchfile
    } -result {path "nosuchfile" not found in any zipfs volume} -returnCodes error

    test zipfs-info-native-file "zipfs info on native path" -body {
	zipfs info [info nameofexecutable]
    } -result "path \"[info nameofexecutable]\" not found in any zipfs volume" -returnCodes error

    test zipfs-info-nosuchfile "zipfs info non-existent path in mounted archive" -setup {
	mount [zippath test.zip]
    } -cleanup {
	cleanup
    } -body {
	zipfs info [file join $defMountPt nosuchfile]
    } -result "path \"[file join $defMountPt nosuchfile]\" not found in any zipfs volume" -returnCodes error

    test zipfs-info-file "zipfs info file within mounted archive" -setup {
	mount [zippath testdeflated2.zip]
    } -cleanup {
	cleanup
    } -body {
	zipfs info [file join $defMountPt abac-repeat.txt]
    } -result [list [zippath testdeflated2.zip] 60 17 108]

    test zipfs-info-dir "zipfs info dir within mounted archive" -setup {
	mount [zippath test.zip]
    } -cleanup {
	cleanup
    } -body {
	zipfs info [file join $defMountPt testdir]
    } -result [list [zippath test.zip] 0 0 119]

    test zipfs-info-mountpoint "zipfs info on mount point - verify correct offset of zip content" -setup {
	# zip starts at offset 4
	mount [zippath junk-at-start.zip]
    } -cleanup {
	cleanup
    } -body {
	zipfs info $defMountPt
    } -result [list [zippath junk-at-start.zip] 0 0 4]

    test zipfs-info-mezzo "zipfs info on mount point - verify correct offset of zip content" -setup {
	# zip starts at offset 4
	mount [zippath junk-at-start.zip] /testmt/a/b
    } -cleanup {
	cleanup
    } -body {
	zipfs info [file join [zipfs root] testmt a]
    } -result {path "//zipfs:/testmt/a" not found in any zipfs volume} -returnCodes error

    #
    # zipfs canonical
    test zipfs-canonical-minargs {zipfs canonical min args} -body {
	zipfs canonical
    } -returnCodes error -result {wrong # args: should be "zipfs canonical ?mountpoint? filename"}
    test zipfs-canonical-maxargs {zipfs canonical max args} -body {
	zipfs canonical a b c
    } -returnCodes error -result {wrong # args: should be "zipfs canonical ?mountpoint? filename"}
    proc testzipfscanonical {id cmdargs result args} {
	test zipfs-canonical-$id "zipfs canonical $id" \
	    -body [list zipfs canonical {*}$cmdargs] \
	    -result $result {*}$args
    }
    testzipfscanonical default-relative      [list a]               [file join [zipfs root] a]
    testzipfscanonical default-absolute      [list /a]              [file join [zipfs root] a]
    testzipfscanonical root-relative-1       [list [zipfs root] a]  [file join [zipfs root] a]
    testzipfscanonical root-relative-2       [list / a]             [file join [zipfs root] a]
    testzipfscanonical root-absolute-1       [list [zipfs root] /a] [file join [zipfs root] a]
    testzipfscanonical root-absolute-2       [list / /a]            [file join [zipfs root] a]
    testzipfscanonical absolute-relative     [list /MT a]           [file join [zipfs root] MT a]
    testzipfscanonical absolute-absolute     [list /MT /a]          [file join [zipfs root] MT a]
    testzipfscanonical relative-relative     [list MT a]            [file join [zipfs root] MT a]
    testzipfscanonical relative-absolute     [list MT /a]           [file join [zipfs root] MT a]
    testzipfscanonical mountpoint-trailslash-relative [list MT/ a]  [file join [zipfs root] MT a]
    testzipfscanonical mountpoint-trailslash-absolute [list MT/ /a] [file join [zipfs root] MT a]
    testzipfscanonical mountpoint-root-relative       [list [zipfs root] a]  [file join [zipfs root] a]
    testzipfscanonical mountpoint-root-absolute       [list [zipfs root] /a] [file join [zipfs root] a]
    testzipfscanonical mountpoint-empty-relative      [list {} a] [file join [zipfs root] a]

    testzipfscanonical driveletter   [list X:]               [zipfs root] -constraints win
    testzipfscanonical drivepath     [list X:/foo/bar]       [file join [zipfs root] foo bar] -constraints win
    testzipfscanonical drivepath-1     [list MT X:/foo/bar]    [file join [zipfs root] MT foo bar] -constraints win
    testzipfscanonical backslashes   [list X:\\\\foo\\\\bar] [file join [zipfs root] foo bar] -constraints win
    testzipfscanonical backslashes-1 [list X:/foo\\\\bar]    [file join [zipfs root] foo bar] -constraints win
    testzipfscanonical zipfspath     [list //zipfs:/x/y]     [file join [zipfs root] x y]
    testzipfscanonical zipfspath-1     [list MT //zipfs:/x/y]  [file join [zipfs root] x y]

    #
    # Read/uncompress
    proc testzipfsread {id zippath result {filename abac-repeat.txt} {openopts {}} args} {
	variable defMountPt
	set zippath [zippath $zippath]
	test zipfs-read-$id "zipfs read $id" -setup {
	    unset -nocomplain fd
	    zipfs mount $zippath $defMountPt
	} -cleanup {
	    # In case open succeeded when it should not
	    if {[info exists fd]} {
		close $fd
	    }
	    cleanup
	} -body {
	    set fd [open [file join $defMountPt $filename] {*}$openopts]
	    gets $fd
	} -result $result {*}$args

	set data [readbin $zippath]
	test zipfs-read-memory-$id "zipfs read in-memory $id" -setup {
	    unset -nocomplain fd
	    zipfs mountdata $data $defMountPt
	} -cleanup {
	    # In case open succeeded when it should not
	    if {[info exists fd]} {
		close $fd
	    }
	    cleanup
	} -body {
	    set fd [open [file join $defMountPt $filename] {*}$openopts]
	    gets $fd
	} -result $result {*}$args

    }
    testzipfsread stored    test.zip          test           test
    testzipfsread stored-1  teststored.zip    aaaaaaaaaaaaaa
    testzipfsread deflate   testdeflated2.zip aaaaaaaaaaaaaa
    testzipfsread bug-23dd83ce7c  empty.zip    {} empty.txt
    # Test open modes - see bug [4645658689]
    testzipfsread stored-r+  teststored.zip    aaaaaaaaaaaaaa abac-repeat.txt r+
    testzipfsread deflate-r+ testdeflated2.zip aaaaaaaaaaaaaa abac-repeat.txt r+
    testzipfsread stored-w+  teststored.zip    {} abac-repeat.txt w+
    testzipfsread deflate-w+ testdeflated2.zip {} abac-repeat.txt w+
    testzipfsread stored-a+  teststored.zip    {} abac-repeat.txt a+
    testzipfsread deflate-a+ testdeflated2.zip {} abac-repeat.txt a+

    testzipfsread enoent  test.zip          "file \"//zipfs:/testmount/nosuchfile\" not found: no such file or directory" nosuchfile {} -returnCodes error
    testzipfsread bzip2   testbzip2.zip     {unsupported compression method} abac-repeat.txt {} -returnCodes error
    testzipfsread lzma    testfile-lzma.zip {unsupported compression method} abac-repeat.txt {} -returnCodes error
    testzipfsread xz      testfile-xz.zip   {unsupported compression method} abac-repeat.txt {} -returnCodes error
    testzipfsread zstd    testfile-zstd.zip {unsupported compression method} abac-repeat.txt {} -returnCodes error
    testzipfsread deflate-error broken.zip  {decompression error} deflatezliberror {} -returnCodes error

    test zipfs-read-unwritable "Writes not allowed on file opened for read" -setup {
	mount [zippath test.zip]
    } -cleanup {
	close $fd
	cleanup
    } -body {
	set fd [open [file join $defMountPt test]]
	puts $fd blah
    } -result {channel "*" wasn't opened for writing} -match glob -returnCodes error

    #
    # Write
    proc testzipfswrite {id zippath result filename mode args} {
	variable defMountPt
	set zippath [zippath $zippath]
	set path [file join $defMountPt $filename]
	set body {
	    set fd [open $path $mode]
	    fconfigure $fd -translation binary
	    puts -nonewline $fd XYZ
	    seek $fd 0
	    puts -nonewline $fd xyz
	    close $fd
	    set fd [open $path]
	    fconfigure $fd -translation binary
	    read $fd
	}
	test zipfs-write-$id "zipfs write $id" -setup {
	    unset -nocomplain fd
	    zipfs mount $zippath $defMountPt
	} -cleanup {
	    # In case open succeeded when it should not
	    if {[info exists fd]} {
		close $fd
	    }
	    cleanup
	} -body $body -result $result {*}$args

	set data [readbin $zippath]
	test zipfs-write-memory-$id "zipfs write in-memory $id" -setup {
	    unset -nocomplain fd
	    zipfs mountdata $data $defMountPt
	} -cleanup {
	    # In case open succeeded when it should not
	    if {[info exists fd]} {
		close $fd
	    }
	    cleanup
	} -body $body -result $result {*}$args

    }
    testzipfswrite create-w   test.zip          "file \"//zipfs:/testmount/newfile\" not created: operation not supported" newfile w -returnCodes error
    testzipfswrite create-w+  test.zip          "file \"//zipfs:/testmount/newfile\" not created: operation not supported" newfile w+ -returnCodes error
    testzipfswrite create-a   test.zip          "file \"$defMountPt/newfile\" not created: operation not supported" newfile a -returnCodes error
    testzipfswrite create-a+  test.zip          "file \"//zipfs:/testmount/newfile\" not created: operation not supported" newfile a+ -returnCodes error
    testzipfswrite store-w    teststored.zip    "xyz" abac-repeat.txt w
    testzipfswrite deflate-w  testdeflated2.zip "xyz" abac-repeat.txt w
    testzipfswrite store-w+   teststored.zip    "xyz" abac-repeat.txt w+
    testzipfswrite deflate-w+ testdeflated2.zip "xyz" abac-repeat.txt w+
    testzipfswrite stored-a   teststored.zip    "aaaaaaaaaaaaaa\nbbbbbbbbbbbbbb\naaaaaaaaaaaaaa\ncccccccccccccc\nXYZxyz" abac-repeat.txt a
    testzipfswrite deflate-a  testdeflated2.zip "aaaaaaaaaaaaaa\nbbbbbbbbbbbbbb\naaaaaaaaaaaaaa\ncccccccccccccc\nXYZxyz" abac-repeat.txt a
    testzipfswrite store-a+   teststored.zip    "xyzaaaaaaaaaaa\nbbbbbbbbbbbbbb\naaaaaaaaaaaaaa\ncccccccccccccc\nXYZ" abac-repeat.txt a+
    testzipfswrite deflate-a+ testdeflated2.zip "xyzaaaaaaaaaaa\nbbbbbbbbbbbbbb\naaaaaaaaaaaaaa\ncccccccccccccc\nXYZ" abac-repeat.txt a+
    testzipfswrite bug-23dd83ce7c-w  empty.zip  "xyz"   empty.txt w

    test zipfs-write-unreadable "Reads not allowed on file opened for write" -setup {
	mount [zippath test.zip]
    } -cleanup {
	close $fd
	cleanup
    } -body {
	set fd [open [file join $defMountPt test] w]
	read $fd
    } -result {channel "*" wasn't opened for reading} -match glob -returnCodes error

    test zipfs-write-persist "Writes persist ONLY while mounted" -setup {
	mount [zippath test.zip]
    } -cleanup {
	cleanup
    } -body {
	set path [file join $defMountPt test]
	set fd [open $path w]
	puts -nonewline $fd newtext
	close $fd
	set fd [open $path]
	set result [list [read $fd]]
	close $fd
	zipfs unmount $defMountPt
	mount [zippath test.zip]
	set fd [open $path]
	lappend result [read $fd]
	close $fd
	set result
    } -result [list newtext test\n]

    test zipfs-write-size-limit-0 "Writes more than size limit with flush" -setup {
	set origlimit $::tcl::zipfs::wrmax
	mount [zippath test.zip]
    } -cleanup {
	close $fd
	set ::tcl::zipfs::wrmax $origlimit
	cleanup
    } -body {
	set ::tcl::zipfs::wrmax 10
	set fd [open [file join $defMountPt test] w]
	puts $fd [string repeat x 11]
	flush $fd
    } -result {error flushing *: file too large} -match glob -returnCodes error

    test zipfs-write-size-limit-1 "Writes size limit on close" -setup {
	set origlimit $::tcl::zipfs::wrmax
	mount [zippath test.zip]
    } -cleanup {
	set ::tcl::zipfs::wrmax $origlimit
	cleanup
    } -body {
	set ::tcl::zipfs::wrmax 10
	set fd [open [file join $defMountPt test] w]
	puts $fd [string repeat x 11]
	close $fd
    } -result {file too large} -match glob -returnCodes error

    test zipfs-write-size-limit-2 "Writes max size" -setup {
	set origlimit $::tcl::zipfs::wrmax
	set ::tcl::zipfs::wrmax 10000000
	mount [zippath test.zip]
    } -cleanup {
	set ::tcl::zipfs::wrmax $origlimit
	cleanup
    } -body {
	set fd [open [file join $defMountPt test] w]
	puts -nonewline $fd [string repeat x $::tcl::zipfs::wrmax]
	close $fd
	file size [file join $defMountPt test]
    } -result 10000000

    test zipfs-write-size-limit-3 "Writes incrementally - buffer growth" -setup {
	mount [zippath test.zip]
    } -cleanup {
	cleanup
    } -body {
	set fd [open [file join $defMountPt test] w]
	fconfigure $fd -buffering none
	for {set i 0} {$i < 100000} {incr i} {
	    puts -nonewline $fd 0123456789
	}
	close $fd
	readbin [file join $defMountPt test]
    } -result [string repeat 0123456789 100000]

    test zipfs-write-size-limit-4 "Writes disallowed" -setup {
	set origlimit $::tcl::zipfs::wrmax
	mount [zippath test.zip]
    } -cleanup {
	set ::tcl::zipfs::wrmax $origlimit
	cleanup
    } -body {
	set ::tcl::zipfs::wrmax -1
	open [file join $defMountPt test] w
    } -result {writes not permitted: permission denied} -returnCodes error

    #
    # read/seek/write
    proc testzipfsrw {id zippath expected filename mode args} {
	variable defMountPt
	set zippath [zippath $zippath]
	set path [file join $defMountPt $filename]
	set body {
	    set result ""
	    set fd [open $path $mode]
	    fconfigure $fd -translation binary
	    append result [gets $fd],
	    set pos [tell $fd]
	    append result $pos,
	    puts -nonewline $fd "0123456789"
	    append result [gets $fd],
	    seek $fd $pos
	    append result [gets $fd],
	    seek $fd -6 end
	    append result [read $fd]|
	    close $fd
	    # Reopen after closing - bug [f91ee30d3]
	    set fd [open $path rb]
	    append result [read $fd]
	}
	test zipfs-rw-$id "zipfs read/seek/write $id" -setup {
	    unset -nocomplain fd
	    zipfs mount $zippath $defMountPt
	} -cleanup {
	    # In case open succeeded when it should not
	    if {[info exists fd]} {
		close $fd
	    }
	    cleanup
	} -body $body -result $expected {*}$args

	set data [readbin $zippath]
	test zipfs-rw-memory-$id "zipfs read/seek/write in-memory $id" -setup {
	    unset -nocomplain fd
	    zipfs mountdata $data $defMountPt
	} -cleanup {
	    # In case open succeeded when it should not
	    if {[info exists fd]} {
		close $fd
	    }
	    cleanup
	} -body $body -result $expected {*}$args

    }
    testzipfsrw store-r+ teststored.zip      "aaaaaaaaaaaaaa,15,bbbb,0123456789bbbb,ccccc\n|aaaaaaaaaaaaaa\n0123456789bbbb\naaaaaaaaaaaaaa\ncccccccccccccc\n" abac-repeat.txt r+
    testzipfsrw store-w+ teststored.zip      ",0,,0123456789,456789|0123456789" abac-repeat.txt w+
    testzipfsrw store-a+ teststored.zip      ",60,,0123456789,456789|aaaaaaaaaaaaaa\nbbbbbbbbbbbbbb\naaaaaaaaaaaaaa\ncccccccccccccc\n0123456789" abac-repeat.txt a+
    testzipfsrw deflate-r+ testdeflated2.zip      "aaaaaaaaaaaaaa,15,bbbb,0123456789bbbb,ccccc\n|aaaaaaaaaaaaaa\n0123456789bbbb\naaaaaaaaaaaaaa\ncccccccccccccc\n" abac-repeat.txt r+
    testzipfsrw deflate-w+ testdeflated2.zip      ",0,,0123456789,456789|0123456789" abac-repeat.txt w+
    testzipfsrw deflate-a+ testdeflated2.zip      ",60,,0123456789,456789|aaaaaaaaaaaaaa\nbbbbbbbbbbbbbb\naaaaaaaaaaaaaa\ncccccccccccccc\n0123456789" abac-repeat.txt a+
    test zipfs-rw-bug-f91ee30d33 "Bug f91ee30d33 - truncates at last read" -setup {
	mount [zippath test.zip]
    } -cleanup {
	close $fd
	cleanup
    } -body {
	set path [file join $defMountPt test]
	set fd [open $path r+]
	puts -nonewline $fd X
	close $fd
	set fd [open $path r]
	read $fd
    } -result "Xest\n"

    #
    # Password protected
    proc testpasswordr {id zipfile filename password result args} {
	variable defMountPt
	set zippath [zippath $zipfile]
	test zipfs-password-read-$id "zipfs password read $id" -setup {
	    unset -nocomplain fd
	    if {$password ne ""} {
		zipfs mount $zippath $defMountPt $password
	    } else {
		zipfs mount $zippath $defMountPt
	    }
	} -cleanup {
	    # In case open succeeded when it should not
	    if {[info exists fd]} {
		close $fd
	    }
	    cleanup
	} -body {
	    set fd [open [file join $defMountPt $filename]]
	    gets $fd
	} -result $result {*}$args -constraints bbe7c6ff9e
    }
    # The bug bbe7c6ff9e only manifests on macos
    testConstraint bbe7c6ff9e [expr {$::tcl_platform(os) ne "Darwin"}]

    # NOTE: test-password.zip is the DOS time based encryption header validity check (infozip style)
    #       test-password2.zip is the CRC based encryption header validity check (pkware style)
    testpasswordr plain                  test-password.zip plain.txt password plaintext
    testpasswordr plain-nopass           test-password.zip plain.txt "" plaintext
    testpasswordr plain-badpass          test-password.zip plain.txt badpassword plaintext
    testpasswordr cipher-1               test-password.zip cipher.bin password ciphertext
    testpasswordr cipher-2               test-password2.zip cipher.bin password ciphertext
    testpasswordr cipher-nopass-1        test-password.zip cipher.bin {} "decryption failed - no password provided" -returnCodes error
    testpasswordr cipher-nopass-2        test-password2.zip cipher.bin {} "decryption failed - no password provided" -returnCodes error
    testpasswordr cipher-badpass-1       test-password.zip cipher.bin badpassword "invalid password" -returnCodes error
    testpasswordr cipher-badpass-2       test-password2.zip cipher.bin badpassword "invalid password" -returnCodes error
    testpasswordr cipher-deflate         test-password.zip cipher-deflate.bin password [lseq 100]
    testpasswordr cipher-deflate-nopass  test-password.zip cipher-deflate.bin {} "decryption failed - no password provided" -returnCodes error
    testpasswordr cipher-deflate-badpass test-password.zip cipher-deflate.bin badpassword "invalid password" -returnCodes error

    proc testpasswordw {id zippath filename password mode result args} {
	variable defMountPt
	set zippath [zippath $zippath]
	set path [file join $defMountPt $filename]
	set body {
	    set fd [open $path $mode]
	    fconfigure $fd -translation binary
	    puts -nonewline $fd "xyz"
	    close $fd
	    set fd [open $path]
	    fconfigure $fd -translation binary
	    read $fd
	}
	test zipfs-password-write-$id "zipfs write $id" -setup {
	    unset -nocomplain fd
	    if {$password ne ""} {
		zipfs mount $zippath $defMountPt $password
	    } else {
		zipfs mount $zippath $defMountPt
	    }
	} -cleanup {
	    # In case open succeeded when it should not
	    if {[info exists fd]} {
		close $fd
	    }
	    cleanup
	} -body $body -result $result {*}$args -constraints bbe7c6ff9e
    }
    # NOTE: test-password.zip is the DOS time based encryption header validity check (infozip style)
    #       test-password2.zip is the CRC based encryption header validity check (pkware style)
    testpasswordw cipher-w-1               test-password.zip  cipher.bin password w xyz
    testpasswordw cipher-w-2               test-password2.zip cipher.bin password w xyz
    testpasswordw cipher-deflate-w         test-password2.zip cipher-deflate.bin password w xyz
    testpasswordw cipher-badpass-w-1       test-password.zip  cipher.bin badpass w {invalid password} -returnCodes error
    testpasswordw cipher-badpass-w-2       test-password2.zip cipher.bin badpass w {invalid password} -returnCodes error
    testpasswordw cipher-badpass-deflate-w test-password2.zip cipher-deflate.bin badpass w {invalid password} -returnCodes error

    testpasswordw cipher-w+                 test-password.zip cipher.bin password w xyz
    testpasswordw cipher-deflate-w+         test-password2.zip cipher-deflate.bin password w xyz
    testpasswordw cipher-badpass-w+         test-password.zip cipher.bin badpass w {invalid password} -returnCodes error
    testpasswordw cipher-badpass-deflate-w+ test-password2.zip cipher-deflate.bin badpass w {invalid password} -returnCodes error

    testpasswordw cipher-a+ test-password.zip cipher.bin password a+ ciphertextxyz
    testpasswordw cipher-deflate-a+ test-password2.zip cipher-deflate.bin password a+ [lseq 100]xyz
    testpasswordw cipher-badpass-a+ test-password.zip cipher.bin badpass a+ {invalid password} -returnCodes error
    testpasswordw cipher-badpass-deflate-a+ test-password2.zip cipher-deflate.bin badpass a+ {invalid password} -returnCodes error

    #
    # CRC errors
    proc testcrc {id zippath filename result args} {
	variable defMountPt
	set zippath [zippath $zippath]
	test zipfs-crc-$id "zipfs crc $id" -setup {
	    unset -nocomplain fd
	    zipfs mount $zippath $defMountPt
	} -cleanup {
	    # In case mount succeeded when it should not
	    if {[info exists fd]} {
		close $fd
	    }
	    cleanup
	} -body {
	    set fd [open [file join $defMountPt $filename]]
	} -result $result -returnCodes error {*}$args

	# Mount memory buffer
	test zipfs-crc-memory-$id "zipfs crc memory $id" -setup {
	    zipfs mountdata [readbin [zippath $zippath]] $defMountPt
	} -cleanup {
	    cleanup
	} -body {
	    set fd [open [file join $defMountPt $filename]]
	} -result $result -returnCodes error {*}$args
    }
    testcrc local incons-local-crc.zip a "invalid CRC"
    testcrc store-crc broken.zip storedcrcerror "invalid CRC"
    testcrc deflate-crc broken.zip deflatecrcerror "invalid CRC"
    test zipfs-crc-false-positives {
	Verify no false positives in CRC checking
    } -constraints zipfslib -body {
	# Just loop ensuring no crc failures
	foreach f [zipfs list] {
	    if {[file isfile $f]} {
		close [open $f]
		incr count
	    }
	}
	expr {$count > 0}
} -result {not allowed to invoke subcommand mkzip of zipfs}
    } -result 1

    #
    # file stat,lstat
    proc fixuptime {t} {
	# To compensate for the lack of timezone in zip, all dates
	# expressed as strings and translated to local time
	if {[regexp {^\d{4}-\d\d-\d\d \d\d:\d\d:\d\d} $t]} {
	    return [clock scan $t -format "%Y-%m-%d %H:%M:%S"]
	}
	return $t
    }
    proc fixupstat {stat} {
	foreach key {atime ctime mtime} {
	    # ZIP files have no TZ info so zipfs uses mktime which is localtime
	    dict set stat $key [fixuptime [dict get $stat $key]]
	}
	if {$::tcl_platform(platform) ne "windows"} {
	    dict set stat blksize 0
	    dict set stat blocks 0
	}
	return [lsort -stride 2 $stat]
    }
    # Wraps stat and lstat
    proc testzipfsstat {id mountpoint target result args} {
	test zipfs-file-stat-$id "file stat $id" -setup {
	    zipfs mount [zippath test.zip] $mountpoint
	} -cleanup cleanup -body {
	    lsort -stride 2 [file stat [file join $mountpoint $target]]
	} -result $result {*}$args

	test zipfs-file-lstat-$id "file lstat $id" -setup {
	    mount [zippath test.zip]
	} -cleanup cleanup -body {
	    lsort -stride 2 [file lstat [file join $mountpoint $target]]
	} -result $result {*}$args
    }
    testzipfsstat enoent      $defMountPt enoent                  "could not read \"[file join $defMountPt enoent]\": no such file or directory" -returnCodes error
    testzipfsstat nosuchmount $defMountPt //zipfs:/notamount/test "could not read \"//zipfs:/notamount/test\": no such file or directory" -returnCodes error
    testzipfsstat file        $defMountPt test                    [fixupstat {atime {2003-10-06 15:46:42} ctime {2003-10-06 15:46:42} dev 0 gid 0 ino 0 mode 33133 mtime {2003-10-06 15:46:42} nlink 0 size 5 type file uid 0}]
    testzipfsstat dir         $defMountPt testdir                 [fixupstat {atime {2005-01-11 19:03:54} ctime {2005-01-11 19:03:54} dev 0 gid 0 ino 0 mode 16749 mtime {2005-01-11 19:03:54} nlink 0 size 0 type directory uid 0}]
    testzipfsstat root-mount  [zipfs root] [zipfs root]           [fixupstat {atime .* ctime .* dev 0 gid 0 ino 0 mode 16749 mtime .* nlink 0 size 0 type directory uid 0}] -match regexp
    testzipfsstat root-subdir-mount $defMountPt [zipfs root]      [fixupstat {atime .* ctime .* dev 0 gid 0 ino 0 mode 16749 mtime .* nlink 0 size 0 type directory uid 0}] -match regexp
    testzipfsstat mezzo       [file join $defMountPt mt2] $defMountPt [fixupstat {atime .* ctime .* dev 0 gid 0 ino 0 mode 16749 mtime .* nlink 0 size 0 type directory uid 0}] -match regexp

    #
    # glob of zipfs file
    proc testzipfsglob {id mounts cmdopts result args} {
	set setup {
	    foreach {zippath mountpoint} $mounts {
		zipfs mount [zippath $zippath] [file join [zipfs root] $mountpoint]
	    }
	}
	if {[dict exists $args -setup]} {
	    append setup \n[dict get $args -setup]
	    dict unset args -setup
	}
	set cleanup cleanup
	if {[dict exists $args -cleanup]} {
	    set cleanup "[dict get $args -cleanup]\n$cleanup"
	    dict unset args -cleanup
	}
	test zipfs-glob-$id "zipfs glob $id $cmdopts" -body {
	    lsort [glob {*}$cmdopts]
	} -setup $setup -cleanup $cleanup -result $result {*}$args
    }

    set basicMounts [list test.zip $defMountPt]
    testzipfsglob basic           $basicMounts [list $defMountPt/*]              [zipfspathsmt $defMountPt test testdir]
    testzipfsglob basic-pat       $basicMounts [list $defMountPt/t*d*]           [zipfspathsmt $defMountPt testdir]
    testzipfsglob basic-deep      $basicMounts [list $defMountPt/tes*/*]         [zipfspathsmt $defMountPt testdir/test2]
    testzipfsglob basic-dir       $basicMounts [list -directory  $defMountPt *]  [zipfspathsmt $defMountPt test testdir]
    testzipfsglob basic-dir-tails $basicMounts [list -tails -dir $defMountPt *]  [list test testdir]
    testzipfsglob basic-type-d    $basicMounts [list -type d $defMountPt/*]      [zipfspathsmt $defMountPt testdir]
    testzipfsglob basic-type-f    $basicMounts [list -type f $defMountPt/*]      [zipfspathsmt $defMountPt test]
    testzipfsglob basic-type-d-f  $basicMounts [list -type {d f} $defMountPt/*]  [zipfspathsmt $defMountPt test testdir]
    testzipfsglob basic-type-l    $basicMounts [list -type l $defMountPt/*]      {}
    foreach type {b c l p s} {
	testzipfsglob basic-type-1-$type    $basicMounts [list -type $type $defMountPt/*]          {}
	testzipfsglob basic-type-f-$type  $basicMounts [list -type [list f $type] $defMountPt/*] [zipfspathsmt $defMountPt test]
	testzipfsglob basic-type-d-$type  $basicMounts [list -type [list d $type] $defMountPt/*] [zipfspathsmt $defMountPt testdir]
    }
    testzipfsglob basic-path      $basicMounts [list -path $defMountPt/t *d*]    [zipfspathsmt $defMountPt testdir]
    testzipfsglob basic-enoent    $basicMounts [list $defMountPt/x*]             {}
    testzipfsglob basic-enoent-ok $basicMounts [list -nocomplain $defMountPt/x*] {}

    # NOTE: test root mounts separately because some bugs only showed up on these
    set rootMounts [list test.zip /]
    testzipfsglob root-1           $rootMounts [list [zipfs root]*]              [zipfspaths $::zipLibTop test testdir] -constraints zipfslib
    testzipfsglob root-2           $rootMounts [list [zipfs root]*]              [zipfspaths test testdir] -constraints !zipfslib
    testzipfsglob root-pat         $rootMounts [list [zipfs root]t*d*]           [zipfspaths testdir]
    testzipfsglob root-deep        $rootMounts [list [zipfs root]tes*/*]         [zipfspaths testdir/test2]
    testzipfsglob root-dir-1       $rootMounts [list -directory [zipfs root] *]  [zipfspaths $::zipLibTop test testdir] -constraints zipfslib
    testzipfsglob root-dir-2       $rootMounts [list -directory [zipfs root] *]  [zipfspaths test testdir] -constraints !zipfslib
    testzipfsglob root-dir-tails-1 $rootMounts [list -tails -dir [zipfs root] *] [list $::zipLibTop test testdir] -constraints zipfslib
    testzipfsglob root-dir-tails-2 $rootMounts [list -tails -dir [zipfs root] *] [list test testdir] -constraints !zipfslib
    testzipfsglob root-type-d-1    $rootMounts [list -type d [zipfs root]*]      [zipfspaths $::zipLibTop testdir] -constraints zipfslib
    testzipfsglob root-type-d-2    $rootMounts [list -type d [zipfs root]*]      [zipfspaths testdir] -constraints !zipfslib
    testzipfsglob root-type-f      $rootMounts [list -type f [zipfs root]*]      [zipfspaths test]
    testzipfsglob root-type-d-f    $rootMounts [list -type {d f} [zipfs root]*]  [zipfspaths test testdir] -constraints !zipfslib
    testzipfsglob root-path        $rootMounts [list -path [zipfs root]t *d*]    [zipfspaths testdir]
    testzipfsglob root-enoent      $rootMounts [list [zipfs root]x*]             {}
    testzipfsglob root-enoent-ok   $rootMounts [list -nocomplain [zipfs root]x*] {}

    # glob operations on intermediate directories (mezzo) in mount
    # paths is another source of bugs
    set mezzoMounts [list test.zip $defMountPt/a/b test-overlay.zip $defMountPt/a/c]
    testzipfsglob mezzo-root-1           $mezzoMounts [list [zipfs root]*]   [zipfspaths $::zipLibTop $defMountPt] -constraints zipfslib
    testzipfsglob mezzo-root-2           $mezzoMounts [list [zipfs root]*]   [list $defMountPt] -constraints !zipfslib
    testzipfsglob mezzo-mountgrandparent $mezzoMounts [list $defMountPt/*]   [list $defMountPt/a]
    testzipfsglob mezzo-mountparent      $mezzoMounts [list $defMountPt/a/*] [zipfspathsmt $defMountPt/a b c]
    testzipfsglob mezzo-overlay          [list test.zip $defMountPt/a/b test-overlay.zip $defMountPt/a] [list $defMountPt/a/*] [zipfspathsmt $defMountPt/a b test2 test3]

    #
    # file attributes
    proc testzipfsfileattr [list id path result [list mountpoint $defMountPt] args] {
	test zipfs-file-attrs-$id "zipfs file attrs $id" -setup {
	    mount [zippath test.zip] $mountpoint
	} -cleanup cleanup -body {
	    lsort -stride 2 [file attributes $path]
	} -result $result {*}$args
    }
    testzipfsfileattr noent [file join $defMountPt nosuchfile] \
	{file not found: no such file or directory} $defMountPt -returnCodes error
    testzipfsfileattr file [file join $defMountPt test] \
	[list -archive [zippath test.zip] -compsize 5 -crc [expr 0x3BB935C6] -mount $defMountPt -offset 55 -permissions 0o555 -uncompsize 5]
    testzipfsfileattr dir [file join $defMountPt testdir] \
	[list -archive [zippath test.zip] -compsize 0 -crc 0 -mount $defMountPt -offset 119 -permissions 0o555 -uncompsize 0]
    testzipfsfileattr root [zipfs root] {-archive {} -compsize 0 -crc 0 -mount {} -offset 0 -permissions 0o555 -uncompsize 0}
    testzipfsfileattr mountpoint $defMountPt \
	[list -archive [zippath test.zip] -compsize 0 -crc 0 -mount $defMountPt -offset 0 -permissions 0o555 -uncompsize 0]
    testzipfsfileattr mezzo [file join $defMountPt a b] {-archive {} -compsize 0 -crc 0 -mount {} -offset 0 -permissions 0o555 -uncompsize 0} [file join $defMountPt a b c]

    foreach attr {-uncompsize -compsize -offset -mount -archive -permissions -crc} {
	test zipfs-file-attrs-set$attr "Set zipfs file attribute $attr" -setup {
	    mount [zippath test.zip]
	} -cleanup cleanup \
	    -body "file attributes [file join $defMountPt test] $attr {}" \
	    -result "unsupported operation" -returnCodes error
    }

    #
    # file normalize
    proc testzipfsnormalize {id path result {dir {}}} {
	if {$dir eq ""} {
	    test zipfs-file-normalize-$id "zipfs file normalize $id" -body {
		file normalize $path
	    } -result $result
	} else {
	    test zipfs-file-normalize-$id "zipfs file normalize $id" -setup {
		set cwd [pwd]
		mount [zippath test.zip] [zipfs root]
		cd $dir
	    } -cleanup {
		cd $cwd
		cleanup
	    } -body {
		file normalize $path
	    } -result $result
	}
    }
    # The parsing requires all these cases for various code paths
    # in particular, root, one below root and more than one below root
    testzipfsnormalize dot-1  [zipfs root] [zipfs root]
    testzipfsnormalize dot-2  [file join [zipfs root] .]        [zipfs root]
    testzipfsnormalize dot-3  [file join [zipfs root] . .]      [zipfs root]
    testzipfsnormalize dot-4  [file join [zipfs root] a .]      [file join [zipfs root] a]
    testzipfsnormalize dot-5  [file join [zipfs root] a . . .]  [file join [zipfs root] a]
    testzipfsnormalize dot-6  [file join [zipfs root] a b .]    [file join [zipfs root] a b]
    testzipfsnormalize dot-7  [file join [zipfs root] a b . .]  [file join [zipfs root] a b]

    testzipfsnormalize dotdot-1  [file join [zipfs root] ..]              [zipfs root]
    testzipfsnormalize dotdot-2  [file join [zipfs root] .. ..]           [zipfs root]
    testzipfsnormalize dotdot-3  [file join [zipfs root] a ..]            [zipfs root]
    testzipfsnormalize dotdot-4  [file join [zipfs root] a .. .. ..]      [zipfs root]
    testzipfsnormalize dotdot-5  [file join [zipfs root] a b ..]          [file join [zipfs root] a]
    testzipfsnormalize dotdot-6  [file join [zipfs root] a b ..]          [file join [zipfs root] a]
    testzipfsnormalize dotdot-7  [file join [zipfs root] a b .. ..]       [zipfs root]
    testzipfsnormalize dotdot-8  [file join [zipfs root] a b .. .. .. ..] [zipfs root]

    testzipfsnormalize relative-1  a               [file join [zipfs root] a]         [zipfs root]
    testzipfsnormalize relative-2  .               [zipfs root]                       [zipfs root]
    testzipfsnormalize relative-3  ./              [zipfs root]                       [zipfs root]
    testzipfsnormalize relative-4  ./a             [file join [zipfs root] a]         [zipfs root]
    testzipfsnormalize relative-5  ../             [file join [zipfs root]]           [zipfs root]
    testzipfsnormalize relative-6  ../a            [file join [zipfs root] a]         [zipfs root]
    testzipfsnormalize relative-7  ../a/           [file join [zipfs root] a]         [zipfs root]
    testzipfsnormalize relative-8  ../..           [zipfs root]                       [zipfs root]
    testzipfsnormalize relative-9  dir/a           [file join [zipfs root] dir a]     [zipfs root]
    testzipfsnormalize relative-10  dir/dirb/..    [file join [zipfs root] dir]       [zipfs root]
    testzipfsnormalize relative-11  dir/../a       [file join [zipfs root] a]         [zipfs root]
    testzipfsnormalize relative-12  dir/../a/      [file join [zipfs root] a]         [zipfs root]
    testzipfsnormalize relative-13  dir/../../../a [file join [zipfs root] a]         [zipfs root]
    testzipfsnormalize relative-14  a              [file join [zipfs root] testdir a] [file join [zipfs root] testdir]

    #
    # file copy
    test zipfs-file-copy-tozip-new {Copy native file to archive} -setup {
	mount [zippath test.zip]
    } -cleanup {
	removeFile $_
	cleanup
    } -body {
	file copy [set _ [makeFile "" source.tmp]] [file join $defMountPt X]
    } -result "error copying \"*source.tmp\" to \"[file join $defMountPt X]\": operation not supported" \
	-match glob -returnCodes error
    test zipfs-file-copy-tozip-existing {Copy native file to archive} -setup {
	mount [zippath test.zip]
    } -cleanup {
	removeFile $_
	cleanup
    } -body {
	file copy [set _ [makeFile "newtext" source.tmp]] [file join $defMountPt test]
    } -result "error copying *: file exists" -match glob -returnCodes error
    test zipfs-file-copy-tozip-existing-force {Copy native file to archive} -setup {
	mount [zippath test.zip]
    } -cleanup {
	removeFile $_
	cleanup
    } -body {
	set to [file join $defMountPt test]
	file copy -force [set _ [makeFile "newtext" source.tmp]] $to
	readbin $to
    } -result "newtext\n"
    test zipfs-file-copy-tozipdir {Copy native file to archive directory} -setup {
	mount [zippath test.zip]
    } -cleanup {
	removeFile $_
	cleanup
    } -body {
	file copy [set _ [makeFile "" source.tmp]] [file join $defMountPt testdir]
    } -result "error copying \"*source.tmp\" to \"[file join $defMountPt testdir]/source.tmp\": operation not supported" \
	-match glob -returnCodes error
    test zipfs-file-copydir-tozipdir {Copy native dir to archive directory} -setup {
	mount [zippath test.zip]
    } -cleanup {
	cleanup
    } -body {
	file copy [temporaryDirectory] [file join $defMountPt testdir]
    } -result "can't create directory *: operation not supported" \
	-match glob -returnCodes error
    test zipfs-file-copy-fromzip-new {Copy archive file to native} -setup {
	mount [zippath test.zip]
	set dst [file join [temporaryDirectory] dst.tmp]
	file delete $dst
    } -cleanup {
	file delete $dst
	cleanup
    } -body {
	file copy [file join $defMountPt test] $dst
	readbin $dst
    } -result "test\n"
    test zipfs-file-copydir-fromzip-1 {Copy archive dir to native} -setup {
	mount [zippath test.zip]
	set dst [file join [temporaryDirectory] dstdir.tmp]
	file delete -force $dst
    } -cleanup {
	file delete -force $dst
	cleanup
    } -body {
	file copy [file join $defMountPt testdir] $dst
	zipfs find $dst
    } -result [file join [temporaryDirectory] dstdir.tmp test2]
    test zipfs-file-copymount-fromzip-new {Copy archive mount to native} -setup {
	mount [zippath test.zip]
	set dst [file join [temporaryDirectory] dstdir2.tmp]
	file delete -force $dst
    } -cleanup {
	file delete -force $dst
	cleanup
    } -body {
	file copy $defMountPt $dst
	list [file isfile [file join $dst test]] \
		  [file isdirectory [file join $dst testdir]] \
		  [file isfile [file join $dst testdir test2]]
    } -result {1 1 1}

    #
    # file delete
    test zipfs-file-delete "Delete file in zip archive" -setup {
	mount [zippath test.zip]
    } -cleanup {
	cleanup
    } -body {
	set file [file join $defMountPt test]
	list \
	    [file exists $file] \
	    [catch {file delete $file} msg] \
	    $msg \
	    [file exists $file]
    } -result [list 1 1 {error deleting "//zipfs:/testmount/test": operation not supported} 1]

    test zipfs-file-delete-enoent "Delete nonexisting path in zip archive" -setup {
	mount [zippath test.zip]
    } -cleanup {
	cleanup
    } -body {
	set file [file join $defMountPt enoent]
	list \
	    [file exists $file] \
	    [catch {file delete $file} msg] \
	    $msg \
	    [file exists $file]
    } -result [list 0 0 {} 0]

    test zipfs-file-delete-dir "Delete dir in zip archive" -setup {
	mount [zippath test.zip]
    } -cleanup {
	cleanup
    } -body {
	set dir [file join $defMountPt testdir]
	list \
	    [file isdirectory $dir] \
	    [catch {file delete -force $dir} msg] \
	    $msg \
	    [file isdirectory $dir]
    } -result [list 1 1 {error deleting unknown file: operation not supported} 1]

    #
    # file join
    test zipfs-file-join-1 "Ensure file join recognizes zipfs path as absolute" -body {
	file join /abc [zipfs root]a/b/c
    } -result [zipfs root]a/b/c

    #
    # file mkdir
    test zipfs-file-mkdir {Make a directory in zip archive} -setup {
	mount [zippath test.zip]
    } -cleanup {
	cleanup
    } -body {
	file mkdir [file join $defMountPt newdir]
    } -result "can't create directory \"[file join $defMountPt newdir]\": operation not supported" -returnCodes error
    test zipfs-file-mkdir-existing {Make a an existing directory in zip archive} -setup {
	mount [zippath test.zip]
    } -cleanup {
	cleanup
    } -body {
	set dir [file join $defMountPt testdir]
	file mkdir $dir
	file isdirectory $dir
    } -result 1

    # Standard paths for file command tests. Because code paths are different,
    # we need tests for...
    set targetMountParent $defMountPt; # Parent of mount directory
    set targetMount [file join $targetMountParent mt] ; # Mount directory
    set targetFile [file join $targetMount test]; # Normal file
    set targetDir [file join $targetMount testdir]; # Directory
    set targetEnoent [file join $targetMount enoent]; # Non-existing path

    proc testzipfsfile {id cmdargs result args} {
	variable targetMount
	test zipfs-file-$id "file $id on zipfs" -setup {
	    zipfs mount [zippath test.zip] $targetMount
	} -cleanup cleanup -body {
	    file {*}$cmdargs
	} -result $result {*}$args
    }
    proc testzipfsenotsup {id cmdargs args} {
	testzipfsfile $id $cmdargs "*: operation not supported" -match glob -returnCodes error
    }

    #
    # file atime

    testzipfsfile atime-get-file   [list atime $targetFile]        [fixuptime {2003-10-06 15:46:42}]
    testzipfsfile atime-get-dir    [list atime $targetDir]         [fixuptime {2005-01-11 19:03:54}]
    testzipfsfile atime-get-mount  [list atime $targetMount]       {\d+} -match regexp
    testzipfsfile atime-get-mezzo  [list atime $targetMountParent] {\d+} -match regexp
    testzipfsfile atime-get-root   [list atime [zipfs root]]       {\d+} -match regexp
    testzipfsfile atime-get-enoent [list atime $targetEnoent] \
	"could not read \"$targetEnoent\": no such file or directory" -returnCodes error

    set t [clock seconds]
    testzipfsenotsup atime-set-file  [list atime $targetFile $t]
    testzipfsenotsup atime-set-dir   [list atime $targetDir $t]
    testzipfsenotsup atime-set-mount [list atime $targetMount $t]
    testzipfsenotsup atime-set-mezzo [list atime $targetMountParent $t]
    testzipfsenotsup atime-set-root  [list atime [zipfs root] $t]
    testzipfsfile atime-set-enoent   [list atime $targetEnoent $t] \
	"could not read \"$targetEnoent\": no such file or directory" -returnCodes error

    #
    # file dirname
    testzipfsfile dirname-file [list dirname $targetFile] $targetMount
    testzipfsfile dirname-dir [list dirname $targetDir] $targetMount
    testzipfsfile dirname-mount [list dirname $targetMount] $targetMountParent
    testzipfsfile dirname-mezzo [list dirname $targetMountParent] [zipfs root]
    testzipfsfile dirname-root [list dirname [zipfs root]] [zipfs root]
    testzipfsfile dirname-enoent [list dirname $targetEnoent] $targetMount

    #
    # file executable
    testzipfsfile executable-file   [list executable $targetFile]        0
    testzipfsfile executable-dir    [list executable $targetDir]         0
    testzipfsfile executable-mount  [list executable $targetMount]       0
    testzipfsfile executable-mezzo  [list executable $targetMountParent] 0
    testzipfsfile executable-root   [list executable [zipfs root]]       0
    testzipfsfile executable-enoent [list executable $targetEnoent]      0

    #
    # file exists
    testzipfsfile exists-file   [list exists $targetFile]        1
    testzipfsfile exists-dir    [list exists $targetDir]         1
    testzipfsfile exists-mount  [list exists $targetMount]       1
    testzipfsfile exists-mezzo  [list exists $targetMountParent] 1
    testzipfsfile exists-root   [list exists [zipfs root]]       1
    testzipfsfile exists-enoent [list exists $targetEnoent]      0

    #
    # file isdirectory
    testzipfsfile isdirectory-file   [list isdirectory $targetFile]        0
    testzipfsfile isdirectory-dir    [list isdirectory $targetDir]         1
    testzipfsfile isdirectory-mount  [list isdirectory $targetMount]       1
    testzipfsfile isdirectory-mezzo  [list isdirectory $targetMountParent] 1
    testzipfsfile isdirectory-root   [list isdirectory [zipfs root]]       1
    testzipfsfile isdirectory-enoent [list isdirectory $targetEnoent]      0

    #
    # file isfile
    testzipfsfile isfile-file   [list isfile $targetFile]        1
    testzipfsfile isfile-dir    [list isfile $targetDir]         0
    testzipfsfile isfile-mount  [list isfile $targetMount]       0
    testzipfsfile isfile-mezzo  [list isfile $targetMountParent] 0
    testzipfsfile isfile-root   [list isfile [zipfs root]]       0
    testzipfsfile isfile-enoent [list isfile $targetEnoent]      0

    #
    # file link
    testzipfsfile link-read-enoent   [list link [file join $targetDir l]] {could not read link "//zipfs:/testmount/mt/testdir/l": operation not supported} -returnCodes error
    testzipfsfile link-read-notalink [list link $targetFile]              {could not read link "//zipfs:/testmount/mt/test": operation not supported} -returnCodes error
    testzipfsfile link-write         [list link [file join $targetDir l] $targetFile] {could not create new link "//zipfs:/testmount/mt/testdir/l" pointing to "//zipfs:/testmount/mt/test": operation not supported} -returnCodes error

    #
    # file mtime

    testzipfsfile mtime-get-file   [list mtime $targetFile]        [fixuptime {2003-10-06 15:46:42}]
    testzipfsfile mtime-get-dir    [list mtime $targetDir]         [fixuptime {2005-01-11 19:03:54}]
    testzipfsfile mtime-get-mount  [list mtime $targetMount]       {\d+} -match regexp
    testzipfsfile mtime-get-mezzo  [list mtime $targetMountParent] {\d+} -match regexp
    testzipfsfile mtime-get-root   [list mtime [zipfs root]]       {\d+} -match regexp
    testzipfsfile mtime-set-enoent   [list mtime $targetEnoent $t] \
	"could not read \"$targetEnoent\": no such file or directory" -returnCodes error

    set t [clock seconds]
    testzipfsenotsup mtime-set-file   [list mtime $targetFile $t]
    testzipfsenotsup mtime-set-dir    [list mtime $targetDir $t]
    testzipfsenotsup mtime-set-mount  [list mtime $targetMount $t]
    testzipfsenotsup mtime-set-mezzo  [list mtime $targetMountParent $t]
    testzipfsenotsup mtime-set-root   [list mtime [zipfs root] $t]
    testzipfsfile    mtime-set-enoent-1 [list mtime $targetEnoent $t] \
	"could not read \"$targetEnoent\": no such file or directory" -returnCodes error

    #
    # file owned
    testzipfsfile owned-file   [list owned $targetFile]        1
    testzipfsfile owned-dir    [list owned $targetDir]         1
    testzipfsfile owned-mount  [list owned $targetMount]       1
    testzipfsfile owned-mezzo  [list owned $targetMountParent] 1
    testzipfsfile owned-root   [list owned [zipfs root]]       1
    testzipfsfile owned-enoent [list owned $targetEnoent]      0

    #
    # file pathtype
    testzipfsfile pathtype [list pathtype $targetFile] absolute

    #
    # file readable
    testzipfsfile readable-file   [list readable $targetFile]        1
    testzipfsfile readable-dir    [list readable $targetDir]         1
    testzipfsfile readable-mount  [list readable $targetMount]       1
    testzipfsfile readable-mezzo  [list readable $targetMountParent] 1
    testzipfsfile readable-root   [list readable [zipfs root]]       1
    testzipfsfile readable-enoent [list readable $targetEnoent]      0

    #
    # file separator
    testzipfsfile separator [list separator $targetFile] /

    #
    # file size
    testzipfsfile size-file   [list size $targetFile]        5
    testzipfsfile size-dir    [list size $targetDir]         0
    testzipfsfile size-mount  [list size $targetMount]       0
    testzipfsfile size-mezzo  [list size $targetMountParent] 0
    testzipfsfile size-root   [list size [zipfs root]]       0
    testzipfsfile size-enoent [list size $targetEnoent]      \
	"could not read \"$targetEnoent\": no such file or directory" -returnCodes error

    #
    # file split
    testzipfsfile split-file   [list split $targetFile]        [list [zipfs root] testmount mt test]
    testzipfsfile split-root   [list split [zipfs root]]       [list [zipfs root]]
    testzipfsfile split-enoent [list split $targetEnoent]      [list [zipfs root] testmount mt enoent]

    #
    # file system
    testzipfsfile system-file   [list system $targetFile]       {zipfs zip}
    testzipfsfile system-root   [list system [zipfs root]]      {zipfs zip}
    testzipfsfile system-enoent [list system $targetEnoent]     {zipfs zip}

    #
    # file type
    testzipfsfile type-file   [list type $targetFile]        file
    testzipfsfile type-dir    [list type $targetDir]         directory
    testzipfsfile type-mount  [list type $targetMount]       directory
    testzipfsfile type-mezzo  [list type $targetMountParent] directory
    testzipfsfile type-root   [list type [zipfs root]]       directory
    testzipfsfile type-enoent [list type $targetEnoent]      {could not read "//zipfs:/testmount/mt/enoent": no such file or directory} -returnCodes error

    #
    # file writable
    testzipfsfile writable-file   [list writable $targetFile]        1
    testzipfsfile writable-dir    [list writable $targetDir]         0
    testzipfsfile writable-mount  [list writable $targetMount]       0
    testzipfsfile writable-mezzo  [list writable $targetMountParent] 0
    testzipfsfile writable-root   [list writable [zipfs root]]       0
    testzipfsfile writable-enoent [list writable $targetEnoent]      0

    # TODO - mkkey, mkimg, mkzip, lmkimg, lmkzip
    testnumargs "zipfs mkkey" "password" "" -constraints zipfs
    testnumargs "zipfs mkimg" "outfile indir" "?strip? ?password? ?infile?"
    testnumargs "zipfs lmkimg" "outfile inlist" "?password? ?infile?"
    testnumargs "zipfs mkzip" "outfile indir" "?strip? ?password?"
    testnumargs "zipfs lmkzip" "outfile inlist" "?password?"

    #
    # Bug regressions

    test bug-6ed3447a7e "Crash opening file in streamed archive" -setup {
	mount [zippath streamed.zip]
    } -cleanup {
	cleanup
    } -body {
	set fd [open [file join $defMountPt -]]
	list [catch {read $fd} message] [close $fd] $message
	close $fd
    } -result {file size error (may be zip64)} -returnCodes error

    test bug-8259d74a64 "Crash exiting with open files" -setup {
	set path [zippath test.zip]
	set script "zipfs mount $path /\n"
	append script {open [zipfs root]test} \n
	append script "exit\n"
    } -body {
	set fd [open |[info nameofexecutable] r+]
	puts $fd $script
	flush $fd
	read $fd
	close $fd
    } -result ""

    # Following will only show a leak with valgrind
    test bug-9525f4c8bc "Memory leak with long mount paths" -body {
	set mt //zipfs:[string repeat /x 240]
	zipfs mount [zippath test.zip] $mt
	zipfs unmount $mt
    } -result ""

    test bug-33b2486199 "zipfs unmounted on thread exit" -constraints {
	thread
    } -body {
	set before [lsort [zipfs mount]]
	thread::release [thread::create]
	after 100; # Needed to allow the spawned thread to exit to trigger bug
	string equal $before [lsort [zipfs mount]]
    } -result 1

    test bug-7d5f1c1308 "zipfs error on dotfiles" -setup {
	set basename bug-7d5f1c1308
	set mt //zipfs:/$basename-mt
	set zipfile $basename.zip
	set dir [makeDirectory $basename]
	close [open [file join $dir .ext] w]
    } -cleanup {
	zipfs unmount $mt
	file delete $zipfile
	removeDirectory $basename
    } -body {
	zipfs mkzip $zipfile $dir [file dirname $dir]
	zipfs mount $zipfile $mt
	lsort [zipfs list $mt/*]
    } -result {//zipfs:/bug-7d5f1c1308-mt/bug-7d5f1c1308 //zipfs:/bug-7d5f1c1308-mt/bug-7d5f1c1308/.ext}
}


::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/zlib.test.

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
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
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
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46






-
-
+
+








+
+




















-
+







# The file tests the tclZlib.c file.
#
# This file contains a collection of tests for one or more of the Tcl built-in
# commands. Sourcing this file into Tcl runs the tests and generates output
# for errors. No output means no errors were found.
#
# Copyright (c) 1996-1998 by Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1996-1998 Sun Microsystems, Inc.
# Copyright © 1998-1999 Scriptics Corporation.
#
# 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::*
}

source [file join [file dirname [info script]] tcltests.tcl]

testConstraint zlib [llength [info commands zlib]]
testConstraint recentZlib 0
catch {
    # Work around a bug in some versions of zlib; known to manifest on at
    # least Mac OS X Mountain Lion...
    testConstraint recentZlib \
	    [package vsatisfies [zlib::pkgconfig get zlibVersion] 1.2.6]
}

test zlib-1.1 {zlib basics} -constraints zlib -returnCodes error -body {
    zlib
} -result {wrong # args: should be "zlib command arg ?...?"}
test zlib-1.2 {zlib basics} -constraints zlib -returnCodes error -body {
    zlib ? {}
} -result {bad command "?": must be adler32, compress, crc32, decompress, deflate, gunzip, gzip, inflate, push, or stream}
test zlib-1.3 {zlib basics} -constraints zlib -body {
    zlib::pkgconfig list
} -result zlibVersion
test zlib-1.4 {zlib basics} -constraints zlib -body {
    package present zlib
    package present tcl::zlib
} -result 2.0.1

test zlib-2.1 {zlib compress/decompress} zlib {
    zlib decompress [zlib compress abcdefghijklm]
} abcdefghijklm

test zlib-3.1 {zlib deflate/inflate} zlib {
136
137
138
139
140
141
142
143

144
145
146
147
148
149
150
138
139
140
141
142
143
144

145
146
147
148
149
150
151
152







-
+







    set s [zlib stream deflate]
    $s put {}
} -cleanup {
    catch {$s close}
} -result ""
# Also causes Tk Bug 10f2e7872b
test zlib-7.8 {zlib stream: Bug b26e38a3e4} -constraints zlib -setup {
    expr srand(12345)
    expr {srand(12345)}
    set randdata {}
    for {set i 0} {$i<6001} {incr i} {
	append randdata [binary format c [expr {int(256*rand())}]]
    }
} -body {
    set strm [zlib stream compress]
    for {set i 1} {$i<3000} {incr i} {
222
223
224
225
226
227
228
229
230
231



232
233
234
235
236
237
238
224
225
226
227
228
229
230



231
232
233
234
235
236
237
238
239
240







-
-
-
+
+
+







    gets $f
} -cleanup {
    close $f
    removeFile $file
} -result ok
test zlib-8.3 {zlib transformation and fileevent} -constraints zlib -setup {
    set srv [socket -myaddr localhost -server {apply {{c a p} {
        fconfigure $c -translation binary -buffering none -blocking 0
        puts -nonewline $c [zlib gzip [string repeat a 81920]]
        close $c
	fconfigure $c -translation binary -buffering none -blocking 0
	puts -nonewline $c [zlib gzip [string repeat a 81920]]
	close $c
    }}} 0]
    set port [lindex [fconfigure $srv -sockname] 2]
    set file [makeFile {} test.gz]
    set fout [open $file wb]
} -body {
    set sin [socket localhost $port]
    try {
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
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







-
+









-
+















-
+
-




-
+







    set fd [open $file wb]
} -constraints zlib -body {
    list [fconfigure $fd] [zlib push compress $fd; fconfigure $fd] \
	[chan pop $fd; fconfigure $fd]
} -cleanup {
    catch {close $fd}
    removeFile $file
} -result {{-blocking 1 -buffering full -buffersize 4096 -encoding binary -eofchar {} -translation lf} {-blocking 1 -buffering full -buffersize 4096 -encoding binary -eofchar {} -translation lf -checksum 1 -dictionary {}} {-blocking 1 -buffering full -buffersize 4096 -encoding binary -eofchar {} -translation lf}}
} -result {{-blocking 1 -buffering full -buffersize 4096 -encoding iso8859-1 -eofchar {} -profile strict -translation lf} {-blocking 1 -buffering full -buffersize 4096 -encoding iso8859-1 -eofchar {} -profile strict -translation lf -checksum 1 -dictionary {}} {-blocking 1 -buffering full -buffersize 4096 -encoding iso8859-1 -eofchar {} -profile strict -translation lf}}
test zlib-8.7 {transformation and fconfigure} -setup {
    set file [makeFile {} test.gz]
    set fd [open $file wb]
} -constraints zlib -body {
    list [fconfigure $fd] [zlib push gzip $fd; fconfigure $fd] \
	[chan pop $fd; fconfigure $fd]
} -cleanup {
    catch {close $fd}
    removeFile $file
} -result {{-blocking 1 -buffering full -buffersize 4096 -encoding binary -eofchar {} -translation lf} {-blocking 1 -buffering full -buffersize 4096 -encoding binary -eofchar {} -translation lf -checksum 0} {-blocking 1 -buffering full -buffersize 4096 -encoding binary -eofchar {} -translation lf}}
} -result {{-blocking 1 -buffering full -buffersize 4096 -encoding iso8859-1 -eofchar {} -profile strict -translation lf} {-blocking 1 -buffering full -buffersize 4096 -encoding iso8859-1 -eofchar {} -profile strict -translation lf -checksum 0} {-blocking 1 -buffering full -buffersize 4096 -encoding iso8859-1 -eofchar {} -profile strict -translation lf}}
# Input is headers from fetching SPDY draft
# Dictionary is that which is proposed _in_ SPDY draft
set spdyHeaders "HTTP/1.0 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nX-Robots-Tag: noarchive\r\nLast-Modified: Tue, 05 Jun 2012 02:43:25 GMT\r\nETag: \"1338864205129|#public|0|en|||0\"\r\nExpires: Tue, 05 Jun 2012 16:17:11 GMT\r\nDate: Tue, 05 Jun 2012 16:17:06 GMT\r\nCache-Control: public, max-age=5\r\nX-Content-Type-Options: nosniff\r\nX-XSS-Protection: 1; mode=block\r\nServer: GSE\r\n"
set spdyDict "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchif-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser-agent100101200201202203204205206300301302303304305306307400401402403404405406407408409410411412413414415416417500501502503504505accept-rangesageetaglocationproxy-authenticatepublicretry-afterservervarywarningwww-authenticateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertransfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locationcontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMondayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSepOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplication/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1.1statusversionurl"
test zlib-8.8 {transformation and fconfigure} -setup {
    lassign [chan pipe] inSide outSide
} -constraints zlib -body {
    zlib push compress $outSide -dictionary $spdyDict
    fconfigure $outSide -blocking 1 -translation binary -buffering none
    fconfigure $inSide -blocking 1 -translation binary
    puts -nonewline $outSide $spdyHeaders
    chan pop $outSide
    chan close $outSide
    set compressed [read $inSide]
    catch {zlib decompress $compressed} err opt
    list [string length [zlib compress $spdyHeaders]] \
    list [string length [zlib decompress [zlib compress $spdyHeaders]]] \
	[string length $compressed] \
	$err [dict get $opt -errorcode] [zlib adler32 $spdyDict]
} -cleanup {
    catch {close $outSide}
    catch {close $inSide}
} -result {260 222 {need dictionary} {TCL ZLIB NEED_DICT 2381337010} 2381337010}
} -result {358 {need dictionary} {TCL ZLIB NEED_DICT 2381337010} 2381337010}
test zlib-8.9 {transformation and fconfigure} -setup {
    lassign [chan pipe] inSide outSide
    set strm [zlib stream decompress]
} -constraints zlib -body {
    zlib push compress $outSide -dictionary $spdyDict
    fconfigure $outSide -blocking 1 -translation binary -buffering none
    fconfigure $inSide -blocking 1 -translation binary
447
448
449
450
451
452
453
454

455
456
457
458
459
460
461
462
463
464
465

466
467
468

469
470
471
472
473
474
475
476
477
478
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
448
449
450
451
452
453
454

455
456
457
458
459
460
461
462
463
464
465

466
467
468

469
470
471
472
473
474
475
476
477
478
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







-
+










-
+


-
+




















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



















-
-
-
-
+
+
+
+







    catch {close $inSide}
    catch {$strm close}
} -result {358 358}
test zlib-8.16 {Bug 3603553: buffer transfer with large writes} -setup {
    # Actual data isn't very important; needs to be substantially larger than
    # the internal buffer (32kB) and incompressible.
    set largeData {}
    for {set i 0;expr srand(1)} {$i < 100000} {incr i} {
    for {set i 0;expr {srand(1)}} {$i < 100000} {incr i} {
	append largeData [lindex "a b c d e f g h i j k l m n o p" \
		[expr {int(16*rand())}]]
    }
    set file [makeFile {} test.gz]
} -constraints zlib -body {
    set f [open $file wb]
    fconfigure $f -buffering none
    zlib push gzip $f
    puts -nonewline $f $largeData
    close $f
    file size $file
    expr {[file size $file]<57648}
} -cleanup {
    removeFile $file
} -result 57647
} -result 1
test zlib-8.17 {Bug dd260aaf: fconfigure} -setup {
    lassign [chan pipe] inSide outSide
} -constraints zlib -body {
    zlib push inflate $inSide
    zlib push deflate $outSide
    list [chan configure $inSide -dictionary] [chan configure $outSide -dictionary]
} -cleanup {
    catch {close $inSide}
    catch {close $outSide}
} -result {{} {}}
test zlib-8.18 {Bug dd260aaf: fconfigure} -setup {
    lassign [chan pipe] inSide outSide
} -constraints zlib -body {
    zlib push inflate $inSide -dictionary "one two"
    zlib push deflate $outSide -dictionary "one two"
    list [chan configure $inSide -dictionary] [chan configure $outSide -dictionary]
} -cleanup {
    catch {close $inSide}
    catch {close $outSide}
} -result {{one two} {one two}}
test zlib-8.19 {zlib transformation, bug f9eafc3886} -constraints zlib -setup {
    set file [makeFile {} test.gz]
} -body {
    set f [zlib push gzip [open $file w] -header [list comment [string repeat A 500]]]
} -cleanup {
    catch {close $f}
    removeFile $file
} -returnCodes 1 -result {Comment too large for zip}
test zlib-8.20 {zlib transformation, bug f9eafc3886} -constraints zlib -setup {
    set file [makeFile {} test.gz]
} -body {
    set f [zlib push gzip [open $file w] -header [list filename [string repeat A 5000]]]
} -cleanup {
    catch {close $f}
    removeFile $file
} -returnCodes 1 -result {Filename too large for zip}
test zlib-8.21 {zlib transformation, bug f9eafc3886} -constraints zlib -setup {
    set file [makeFile {} test.gz]
} -body {
    set f [zlib push gzip [open $file w] -header [list comment \u100]]
} -cleanup {
    catch {close $f}
    removeFile $file
} -returnCodes 1 -result {Comment contains characters > 0xFF}
test zlib-8.22 {zlib transformation, bug f9eafc3886} -constraints zlib -setup {
    set file [makeFile {} test.gz]
} -body {
    set f [zlib push gzip [open $file w] -header [list filename \u100]]
} -cleanup {
    catch {close $f}
    removeFile $file
} -returnCodes 1 -result {Filename contains characters > 0xFF}

test zlib-9.1 "check fcopy with push" -constraints zlib -setup {
    set sfile [makeFile {} testsrc.gz]
    set file [makeFile {} test.gz]
    set f [open $sfile wb]
    puts -nonewline $f [zlib gzip [string repeat a 81920]]
    close $f
} -body {
    set fin [zlib push gunzip [open $sfile rb]]
    set fout [open $file wb]
    set total [fcopy $fin $fout]
    close $fin ; close $fout
    list copied $total size [file size $file]
} -cleanup {
    removeFile $file
    removeFile $sfile
} -result {copied 81920 size 81920}
test zlib-9.2 "socket fcopy with push" -constraints zlib -setup {
    set srv [socket -myaddr localhost -server {apply {{c a p} {
        chan configure $c -translation binary -buffering none -blocking 0
        puts -nonewline $c [zlib gzip [string repeat a 81920]]
        close $c
        set ::total -1
	chan configure $c -translation binary -buffering none -blocking 0
	puts -nonewline $c [zlib gzip [string repeat a 81920]]
	close $c
	set ::total -1
    }}} 0]
    set file [makeFile {} test.gz]
} -body {
    lassign [chan configure $srv -sockname] addr name port
    set sin [socket $addr $port]
    chan configure $sin -translation binary
    zlib push gunzip $sin
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
558
559
560
561
562



563
564
565
566
567
568
569
570
571
572
573
574

575
576
577
578
579
580
581
582
583
584
585
586
587
588



589
590
591
592
593
594
595
596
597
598








599
600
601
602
603
604
605
559
560
561
562
563
564
565




566
567
568
569
570
571
572
573
574
575
576
577
578
579
580

581
582
583
584
585
586
587
588
589
590
591
592



593
594
595
596
597
598
599
600
601
602
603
604
605
606

607
608
609
610
611
612
613
614
615
616
617
618



619
620
621
622
623








624
625
626
627
628
629
630
631
632
633
634
635
636
637
638







-
-
-
-
+
+
+
+











-
+











-
-
-
+
+
+











-
+











-
-
-
+
+
+


-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+







    list read $total size [file size $file]
} -cleanup {
    close $srv
    removeFile $file
} -result {read 81920 size 81920}
test zlib-9.3 "socket fcopy bg (identity)" -constraints {tempNotWin zlib} -setup {
    set srv [socket -myaddr localhost -server {apply {{c a p} {
        #puts "connection from $a:$p on $c"
        chan configure $c -translation binary -buffering none -blocking 0
        puts -nonewline $c [string repeat a 81920]
        close $c
	#puts "connection from $a:$p on $c"
	chan configure $c -translation binary -buffering none -blocking 0
	puts -nonewline $c [string repeat a 81920]
	close $c
    }}} 0]
    set file [makeFile {} test.gz]
} -body {
    lassign [chan configure $srv -sockname] addr name port
    #puts "listening for connections on $addr $port"
    set sin [socket localhost $port]
    chan configure $sin -translation binary
    update
    set fout [open $file wb]
    after 1000 {set ::total timeout}
    fcopy $sin $fout -command {apply {{c {e {}}} {
        set ::total [expr {$e eq {} ? $c : $e}]
	set ::total [expr {$e eq {} ? $c : $e}]
    }}}
    vwait ::total
    after cancel {set ::total timeout}
    close $sin; close $fout
    list read $::total size [file size $file]
} -cleanup {
    close $srv
    removeFile $file
} -returnCodes {ok error} -result {read 81920 size 81920}
test zlib-9.4 "socket fcopy bg (gzip)" -constraints zlib -setup {
    set srv [socket -myaddr localhost -server {apply {{c a p} {
        chan configure $c -translation binary -buffering none -blocking 0
        puts -nonewline $c [zlib gzip [string repeat a 81920]]
        close $c
	chan configure $c -translation binary -buffering none -blocking 0
	puts -nonewline $c [zlib gzip [string repeat a 81920]]
	close $c
    }}} 0]
    set file [makeFile {} test.gz]
} -body {
    lassign [chan configure $srv -sockname] addr name port
    set sin [socket $addr $port]
    chan configure $sin -translation binary
    zlib push gunzip $sin
    update
    set fout [open $file wb]
    after 1000 {set ::total timeout}
    fcopy $sin $fout -command {apply {{c {e {}}} {
        set ::total [expr {$e eq {} ? $c : $e}]
	set ::total [expr {$e eq {} ? $c : $e}]
    }}}
    vwait ::total
    after cancel {set ::total timeout}
    close $sin; close $fout
    list read $::total size [file size $file]
} -cleanup {
    close $srv
    removeFile $file
} -result {read 81920 size 81920}
test zlib-9.5 "socket fcopy incremental (gzip)" -constraints zlib -setup {
    set srv [socket -myaddr localhost -server {apply {{c a p} {
        chan configure $c -translation binary -buffering none -blocking 0
        puts -nonewline $c [zlib gzip [string repeat a 81920]]
        close $c
	chan configure $c -translation binary -buffering none -blocking 0
	puts -nonewline $c [zlib gzip [string repeat a 81920]]
	close $c
    }}} 0]
    proc zlib95copy {i o t c {e {}}} {
        incr t $c
        if {$e ne {}} {
            set ::total [list error $e]
        } elseif {[eof $i]} {
            set ::total [list eof $t]
        } else {
            fcopy $i $o -size 8192 -command [list zlib95copy $i $o $t]
        }
	incr t $c
	if {$e ne {}} {
	    set ::total [list error $e]
	} elseif {[eof $i]} {
	    set ::total [list eof $t]
	} else {
	    fcopy $i $o -size 8192 -command [list zlib95copy $i $o $t]
	}
    }
    set file [makeFile {} test.gz]
} -body {
    lassign [chan configure $srv -sockname] addr name port
    set sin [socket $addr $port]
    chan configure $sin -translation binary
    zlib push gunzip $sin
614
615
616
617
618
619
620
621
622
623
624




625
626
627
628
629
630
631
632
633
634
635
636
637





638
639
640
641
642
643
644
645
646
647
648
649
650
651
652




653
654
655
656
657
658
659
660
661
662
663
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
707
708
709




710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725










726
727
728

729
730
731
732
733
734
735
736
737
738
739
740
741
742




743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758










759
760
761

762
763
764
765
766
767
768
769
770
771
772
773
774
775




776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791










792
793
794

795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817










818
819
820
821
822
823
824
825
826
827
828



829
830
831
832
833



834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854






855
856
857
858
859



860
861
862
863
864
865
866
867
868
869
870
871



872
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
898
899



900
901
902
903
904
905
906
907
908
909
910
911



912
913
914
915
916
917
918
647
648
649
650
651
652
653




654
655
656
657
658
659
660
661
662
663
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
707
708
709




710
711
712
713
714
715
716
717
718
719
720
721





722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738




739
740
741
742
743
744
745
746
747
748










749
750
751
752
753
754
755
756
757
758
759
760

761
762
763
764
765
766
767
768
769
770
771




772
773
774
775
776
777
778
779
780
781










782
783
784
785
786
787
788
789
790
791
792
793

794
795
796
797
798
799
800
801
802
803
804




805
806
807
808
809
810
811
812
813
814










815
816
817
818
819
820
821
822
823
824
825
826

827
828
829
830
831
832
833
834
835
836
837
838
839
840










841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858



859
860
861
862
863



864
865
866
867
868
869
870
871
872
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
898
899
900
901



902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919








920
921
922
923
924
925
926
927
928
929



930
931
932
933
934
935
936
937
938
939
940
941



942
943
944
945
946
947
948
949
950
951







-
-
-
-
+
+
+
+








-
-
-
-
-
+
+
+
+
+











-
-
-
-
+
+
+
+








-
-
-
-
-
+
+
+
+
+











-
-
-
-
+
+
+
+








-
-
-
-
-
+
+
+
+
+












-
-
-
-
+
+
+
+






-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+


-
+










-
-
-
-
+
+
+
+






-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+


-
+










-
-
-
-
+
+
+
+






-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+


-
+













-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+








-
-
-
+
+
+


-
-
-
+
+
+















-
-
-
-
-
-
+
+
+
+
+
+


-
-
-
+
+
+









-
-
-
+
+
+















-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+


-
-
-
+
+
+









-
-
-
+
+
+







} -cleanup {
    close $srv
    rename zlib95copy {}
    removeFile $file
} -result {{eof 81920} size 81920}
test zlib-9.6 "bug #2818131 (gzip)" -constraints zlib -setup {
    set srv [socket -myaddr localhost -server {apply {{c a p} {
        chan configure $c -translation binary -buffering none -blocking 0
        zlib push gzip $c
        puts -nonewline $c [string repeat hello 100]
        close $c
	chan configure $c -translation binary -buffering none -blocking 0
	zlib push gzip $c
	puts -nonewline $c [string repeat hello 100]
	close $c
    }}} 0]
} -body {
    lassign [chan configure $srv -sockname] addr name port
    after 1000 {set ::total timeout}
    set s [socket $addr $port]
    chan configure $s -translation binary
    zlib push gunzip $s
    chan event $s readable [list apply {{s} {
        set d [read $s]
        if {[eof $s]} {
            chan event $s readable {}
            set ::total [list eof [string length $d]]
        }
	set d [read $s]
	if {[eof $s]} {
	    chan event $s readable {}
	    set ::total [list eof [string length $d]]
	}
    }} $s]
    vwait ::total
    after cancel {set ::total timeout}
    close $s
    set ::total
} -cleanup {
    close $srv
    unset -nocomplain total
} -result {eof 500}
test zlib-9.7 "bug #2818131 (compress)" -constraints zlib -setup {
    set srv [socket -myaddr localhost -server {apply {{c a p} {
        chan configure $c -translation binary -buffering none -blocking 0
        zlib push compress $c
        puts -nonewline $c [string repeat hello 100]
        close $c
	chan configure $c -translation binary -buffering none -blocking 0
	zlib push compress $c
	puts -nonewline $c [string repeat hello 100]
	close $c
    }}} 0]
} -body {
    lassign [chan configure $srv -sockname] addr name port
    after 1000 {set ::total timeout}
    set s [socket $addr $port]
    chan configure $s -translation binary
    zlib push decompress $s
    chan event $s readable [list apply {{s} {
        set d [read $s]
        if {[eof $s]} {
            chan event $s readable {}
            set ::total [list eof [string length $d]]
        }
	set d [read $s]
	if {[eof $s]} {
	    chan event $s readable {}
	    set ::total [list eof [string length $d]]
	}
    }} $s]
    vwait ::total
    after cancel {set ::total timeout}
    close $s
    set ::total
} -cleanup {
    close $srv
    unset -nocomplain total
} -result {eof 500}
test zlib-9.8 "bug #2818131 (deflate)" -constraints zlib -setup {
    set srv [socket -myaddr localhost -server {apply {{c a p} {
        chan configure $c -translation binary -buffering none -blocking 0
        zlib push deflate $c
        puts -nonewline $c [string repeat hello 100]
        close $c
	chan configure $c -translation binary -buffering none -blocking 0
	zlib push deflate $c
	puts -nonewline $c [string repeat hello 100]
	close $c
    }}} 0]
} -body {
    lassign [chan configure $srv -sockname] addr name port
    after 1000 {set ::total timeout}
    set s [socket $addr $port]
    chan configure $s -translation binary
    zlib push inflate $s
    chan event $s readable [list apply {{s} {
        set d [read $s]
        if {[eof $s]} {
            chan event $s readable {}
            set ::total [list eof [string length $d]]
        }
	set d [read $s]
	if {[eof $s]} {
	    chan event $s readable {}
	    set ::total [list eof [string length $d]]
	}
    }} $s]
    vwait ::total
    after cancel {set ::total timeout}
    close $s
    set ::total
} -cleanup {
    unset -nocomplain total
    close $srv
} -result {eof 500}
test zlib-9.9 "bug #2818131 (gzip mismatch)" -constraints zlib -setup {
    proc bgerror {s} {set ::total [list error $s]}
    set srv [socket -myaddr localhost -server {apply {{c a p} {
        chan configure $c -translation binary -buffering none -blocking 0
        zlib push gzip $c
        puts -nonewline $c [string repeat hello 100]
        close $c
	chan configure $c -translation binary -buffering none -blocking 0
	zlib push gzip $c
	puts -nonewline $c [string repeat hello 100]
	close $c
    }}} 0]
} -body {
    lassign [chan configure $srv -sockname] addr name port
    after 1000 {set ::total timeout}
    set s [socket $addr $port]
    try {
        chan configure $s -translation binary
        zlib push inflate $s
        chan event $s readable [list apply {{s} {
            set d [read $s]
            if {[eof $s]} {
                chan event $s readable {}
                set ::total [list eof [string length $d]]
            }
        }} $s]
        vwait ::total
	chan configure $s -translation binary
	zlib push inflate $s
	chan event $s readable [list apply {{s} {
	    set d [read $s]
	    if {[eof $s]} {
		chan event $s readable {}
		set ::total [list eof [string length $d]]
	    }
	}} $s]
	vwait ::total
    } finally {
	after cancel {set ::total timeout}
        close $s
	close $s
    }
    set ::total
} -cleanup {
    unset -nocomplain total
    close $srv
    rename bgerror {}
} -result {error {invalid block type}}
test zlib-9.10 "bug #2818131 (compress mismatch)" -constraints zlib -setup {
    proc bgerror {s} {set ::total [list error $s]}
    set srv [socket -myaddr localhost -server {apply {{c a p} {
        chan configure $c -translation binary -buffering none -blocking 0
        zlib push compress $c
        puts -nonewline $c [string repeat hello 100]
        close $c
	chan configure $c -translation binary -buffering none -blocking 0
	zlib push compress $c
	puts -nonewline $c [string repeat hello 100]
	close $c
    }}} 0]
} -body {
    lassign [chan configure $srv -sockname] addr name port
    after 1000 {set ::total timeout}
    set s [socket $addr $port]
    try {
        chan configure $s -translation binary
        zlib push inflate $s
        chan event $s readable [list apply {{s} {
            set d [read $s]
            if {[eof $s]} {
                chan event $s readable {}
                set ::total [list eof [string length $d]]
            }
        }} $s]
        vwait ::total
	chan configure $s -translation binary
	zlib push inflate $s
	chan event $s readable [list apply {{s} {
	    set d [read $s]
	    if {[eof $s]} {
		chan event $s readable {}
		set ::total [list eof [string length $d]]
	    }
	}} $s]
	vwait ::total
    } finally {
	after cancel {set ::total timeout}
        close $s
	close $s
    }
    set ::total
} -cleanup {
    unset -nocomplain total
    close $srv
    rename bgerror {}
} -result {error {invalid stored block lengths}}
test zlib-9.11 "bug #2818131 (deflate mismatch)" -constraints zlib -setup {
    proc bgerror {s} {set ::total [list error $s]}
    set srv [socket -myaddr localhost -server {apply {{c a p} {
        chan configure $c -translation binary -buffering none -blocking 0
        zlib push deflate $c
        puts -nonewline $c [string repeat hello 100]
        close $c
	chan configure $c -translation binary -buffering none -blocking 0
	zlib push deflate $c
	puts -nonewline $c [string repeat hello 100]
	close $c
    }}} 0]
} -body {
    lassign [chan configure $srv -sockname] addr name port
    after 1000 {set ::total timeout}
    set s [socket $addr $port]
    try {
        chan configure $s -translation binary
        zlib push gunzip $s
        chan event $s readable [list apply {{s} {
            set d [read $s]
            if {[eof $s]} {
                chan event $s readable {}
                set ::total [list eof [string length $d]]
            }
        }} $s]
        vwait ::total
	chan configure $s -translation binary
	zlib push gunzip $s
	chan event $s readable [list apply {{s} {
	    set d [read $s]
	    if {[eof $s]} {
		chan event $s readable {}
		set ::total [list eof [string length $d]]
	    }
	}} $s]
	vwait ::total
    } finally {
	after cancel {set ::total timeout}
        close $s
	close $s
    }
    set ::total
} -cleanup {
    unset -nocomplain total
    close $srv
    rename bgerror {}
} -result {error {incorrect header check}}

test zlib-10.0 "bug #2818131 (close with null interp)" -constraints {
    zlib
} -setup {
    proc bgerror {s} {set ::total [list error $s]}
    set srv [socket -myaddr localhost -server {apply {{c a p} {
        chan configure $c -translation binary
        zlib push inflate $c
        chan event $c readable [list apply {{c} {
            set d [read $c]
            if {[eof $c]} {
                chan event $c readable {}
                close $c
                set ::total [list eof [string length $d]]
            }
        }} $c]
	chan configure $c -translation binary
	zlib push inflate $c
	chan event $c readable [list apply {{c} {
	    set d [read $c]
	    if {[eof $c]} {
		chan event $c readable {}
		close $c
		set ::total [list eof [string length $d]]
	    }
	}} $c]
    }}} 0]
} -body {
    lassign [chan configure $srv -sockname] addr name port
    after 1000 {set ::total timeout}
    set s [socket $addr $port]
    chan configure $s -translation binary -buffering none -blocking 0
    zlib push gzip $s
    chan event $s xyzzy [list apply {{s} {
        if {[gets $s line] < 0} {
            chan close $s
        }
	if {[gets $s line] < 0} {
	    chan close $s
	}
    }} $s]
    after idle [list apply {{s} {
        puts $s test
        chan close $s
        after 100 {set ::total done}
	puts $s test
	chan close $s
	after 100 {set ::total done}
    }} $s]
    vwait ::total
    after cancel {set ::total timeout}
    after cancel {set ::total done}
    set ::total
} -cleanup {
    close $srv
    rename bgerror {}
} -returnCodes error \
  -result {bad event name "xyzzy": must be readable or writable}
test zlib-10.1 "bug #2818131 (mismatch read)" -constraints {
    zlib
} -setup {
    proc bgerror {s} {set ::total [list error $s]}
    proc zlibRead {c} {
        set d [read $c]
        if {[eof $c]} {
            chan event $c readable {}
            close $c
            set ::total [list eof [string length $d]]
        }
	set d [read $c]
	if {[eof $c]} {
	    chan event $c readable {}
	    close $c
	    set ::total [list eof [string length $d]]
	}
    }
    set srv [socket -myaddr localhost -server {apply {{c a p} {
        chan configure $c -translation binary
        zlib push inflate $c
        chan event $c readable [list zlibRead $c]
	chan configure $c -translation binary
	zlib push inflate $c
	chan event $c readable [list zlibRead $c]
    }}} 0]
} -body {
    lassign [chan configure $srv -sockname] addr name port
    after 1000 {set ::total timeout}
    set s [socket $addr $port]
    chan configure $s -translation binary -buffering none -blocking 0
    zlib push gzip $s
    chan event $s readable [list zlibRead $s]
    after idle [list apply {{s} {
        puts $s test
        chan close $s
        after 100 {set ::total done}
	puts $s test
	chan close $s
	after 100 {set ::total done}
    }} $s]
    vwait ::total
    after cancel {set ::total timeout}
    after cancel {set ::total done}
    set ::total
} -cleanup {
    close $srv
    rename bgerror {}
    rename zlibRead {}
} -result {error {invalid block type}}
test zlib-10.2 "bug #2818131 (mismatch gets)" -constraints {
    zlib
} -setup {
    proc bgerror {s} {set ::total [list error $s]}
    proc zlibRead {c} {
        if {[gets $c line] < 0} {
            close $c
            set ::total [list error -1]
        } elseif {[eof $c]} {
            chan event $c readable {}
            close $c
            set ::total [list eof 0]
        }
	if {[gets $c line] < 0} {
	    close $c
	    set ::total [list error -1]
	} elseif {[eof $c]} {
	    chan event $c readable {}
	    close $c
	    set ::total [list eof 0]
	}
    }
    set srv [socket -myaddr localhost -server {apply {{c a p} {
        chan configure $c -translation binary
        zlib push inflate $c
        chan event $c readable [list zlibRead $c]
	chan configure $c -translation binary
	zlib push inflate $c
	chan event $c readable [list zlibRead $c]
    }}} 0]
} -body {
    lassign [chan configure $srv -sockname] addr name port
    after 1000 {set ::total timeout}
    set s [socket $addr $port]
    chan configure $s -translation binary -buffering none -blocking 0
    zlib push gzip $s
    chan event $s readable [list zlibRead $s]
    after idle [list apply {{s} {
        puts $s test
        chan close $s
        after 100 {set ::total done}
	puts $s test
	chan close $s
	after 100 {set ::total done}
    }} $s]
    vwait ::total
    after cancel {set ::total timeout}
    after cancel {set ::total done}
    set ::total
} -cleanup {
    close $srv
1080
1081
1082
1083
1084
1085
1086












































1087
1088
1089
1090
1091
1092
1093
1094
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








} -result {458752 458752}

if {$zlibbinf ne ""} {
   removeFile $zlibbinf
}
unset zlibbinf
rename _zlibbinf {}

test zlib-14.1 {Bug 9ee9f4d7be: compression header added to source channel} -setup {
    set data hello
    set src [file tempfile]
    puts -nonewline $src $data
    flush $src
    chan configure $src -translation binary
    set dst [file tempfile]
    chan configure $dst -translation binary
    set result {}
} -constraints knownBug -body {
   for {set i 0} {$i < 3} {incr i} {
	# Determine size of src channel
	seek $src 0 end
	set size [chan tell $src]
	seek $src 0 start
	# Determine size of content in src channel
	set data [read $src]
	set size2 [string length $data]
	seek $src 0 start
	# Copy src over to dst, keep dst empty
	zlib push deflate $src -level 6
	chan truncate $dst 0
	chan copy $src $dst
	set size3 [chan tell $dst]
	chan pop $src
	# Show sizes
	lappend result $size $size2 ->$size3
    }
    return $result
} -cleanup {
    chan close $src
    chan close $dst
} -result {5 5 ->5 5 5 ->5 5 5 ->5}

test zlib-15.1 {Bug cfdf80a2efc6 - negative checksums} -setup {
    set compressor [zlib stream gzip -header {comment "A zlib demo"}]
    $compressor put abcd
    $compressor finalize
} -body {
    $compressor checksum
} -cleanup {
    $compressor close
} -result 3984772369


::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Deleted tools/Makefile.in.

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
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



































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# This makefile is used to convert Tcl manual pages into various
# alternate formats:
#
#    Windows help file:  1. Build the winhelp target on Unix
#			 2. Build the helpfile target on Windows
#
#    HTML:		 1. Build the html target on Unix

TCL		= tcl@TCL_VERSION@
TK		= tk@TCL_VERSION@
VER		= @TCL_WIN_VERSION@

TCL_BIN_DIR	= @TCL_BIN_DIR@
TCL_SOURCE	= @TCL_SRC_DIR@
TK_SOURCE	= $(TCL_SOURCE)/../$(TK)
PRO_SOURCE	= $(TCL_SOURCE)/../pro
ITCL_SOURCE	= $(TCL_SOURCE)/../itcl3.1.0

TCL_DOCS	= $(TCL_SOURCE)/doc/*.[13n]

TK_DOCS		= $(TK_SOURCE)/doc/*.[13n]

PRO_DOCS	= \
	$(PRO_SOURCE)/doc/man/procheck.1 \
	$(PRO_SOURCE)/doc/man/prodebug.1 \
	$(PRO_SOURCE)/doc/man/prodebug.n \
	$(PRO_SOURCE)/doc/man/prolicense.1

ITCL_DOCS	= \
	$(ITCL_SOURCE)/itcl/doc/*.[13n] \
	$(ITCL_SOURCE)/itk/doc/*.[13n]

#	$(ITCL_SOURCE)/iwidgets3.0.0/doc/*.[13n]

COREDOCS	= $(TCL_DOCS) $(TK_DOCS)
#PRODOCS	= $(COREDOCS) $(PRO_DOCS) $(ITCL_DOCS)
PRODOCS		= $(COREDOCS) $(PRO_DOCS)
TCLSH		= $(TCL_BIN_DIR)/tclsh
CC		= @CC@

#
# Targets
#

all: core

pro:
	$(MAKE) DOCS="$(PRODOCS)" VER="" rtf

core:
	$(MAKE) DOCS="$(COREDOCS)" rtf

rtf: $(TCL_SOURCE)/tools/man2help.tcl man2tcl $(DOCS)
	LD_LIBRARY_PATH=$(TCL_BIN_DIR) \
	TCL_LIBRARY=$(TCL_SOURCE)/library \
	$(TCLSH) $(TCL_SOURCE)/tools/man2help.tcl tcl "$(VER)" $(DOCS)

winhelp: tcl.rtf

man2tcl: $(TCL_SOURCE)/tools/man2tcl.c
	$(CC) $(CFLAGS) -o man2tcl $(TCL_SOURCE)/tools/man2tcl.c

clean:
	-rm -f man2tcl *.o *.cnt *.rtf

helpfile:
	hcw /c /e tcl.hpj

Changes to tools/README.

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

1
2
3
4
5
6
7
8
9
10
11




12
13

14







15











-
-
-
-


-
+
-
-
-
-
-
-
-
+
This directory contains unsupported tools used to build parts of Tcl
for distribution.


uniParse.tcl -- Script for converting the Unicode character database
	into a compact table stored in generic/tclUniData.c.

uniClass.tcl -- Script for generating regexp class tables from the Tcl
	"string is" classes

Generating HTML files.
The tcl-tk-man-html.tcl script from Robert Critchlow
generates a nice set of HTML with good cross references.
Use it like
    tclsh tcl-tk-man-html.tcl --htmldir=/tmp/tcl9.0
This script is very picky about the organization of man pages,
effectively acting as a style enforcer.

The resulting documentation can be found at
Generating Windows Help Files:
1) Build tcl in the ../unix directory
2) On UNIX, (after autoconf and configure), do
	make
    this converts the Nroff to RTF files.
2) On Windows, convert the RTF to a Help doc, do
	nmake helpfile
    /tmp/dist/tcl<version>/html

Added tools/addVerToFile.tcl.










1
2
3
4
5
6
7
8
9
+
+
+
+
+
+
+
+
+
#!/usr/bin/env tclsh
if {$argc < 1} {
    error "need a filename argument"
}
lassign $argv filename
set f [open $filename a]
puts $f "TCL_VERSION=[info tclversion]"
puts $f "TCL_PATCHLEVEL=[info patchlevel]"
close $f

Changes to tools/checkLibraryDoc.tcl.

12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26







-
+







#      5) Command APIs (e.g., Tcl_ArrayObjCmd.)
#      6) Proc pointers (e.g., Tcl_CloseProc.)
#
# Note: Each list is "a best guess" approximation.  If developers write
# non-standard code, this script will produce erroneous results.  Each
# list should be carefully checked for accuracy.
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.


lappend auto_path "c:/program\ files/tclpro1.2/win32-ix86/bin"
#lappend auto_path "/home/surles/cvs/tclx8.0/tcl/unix"
if {[catch {package require Tclx}]} {
    puts "error: could not load TclX.  Please set TCL_LIBRARY."
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
39
40
41
42
43
44
45

46
47
48
49
50
51
52







-







    Tcl_HashEntry \
    Tcl_HashSearch \
    Tcl_HashTable \
    Tcl_Mutex \
    Tcl_Pid \
    Tcl_QueuePosition \
    Tcl_ResolvedVarInfo \
    Tcl_SavedResult \
    Tcl_ThreadDataKey \
    Tcl_ThreadId \
    Tcl_Time \
    Tcl_TimerToken \
    Tcl_Token \
    Tcl_Trace \
    Tcl_Var \

Deleted tools/configure.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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





















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
#
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##

# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
  emulate sh
  NULLCMD=:
  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '${1+"$@"}'='"$@"'
  setopt NO_GLOB_SUBST
else
  case `(set -o) 2>/dev/null` in #(
  *posix*) :
    set -o posix ;; #(
  *) :
     ;;
esac
fi


as_nl='
'
export as_nl
# Printing a long string crashes Solaris 7 /usr/bin/printf.
as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
# Prefer a ksh shell builtin over an external printf program on Solaris,
# but without wasting forks for bash or zsh.
if test -z "$BASH_VERSION$ZSH_VERSION" \
    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
  as_echo='print -r --'
  as_echo_n='print -rn --'
elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
  as_echo='printf %s\n'
  as_echo_n='printf %s'
else
  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
    as_echo_n='/usr/ucb/echo -n'
  else
    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
    as_echo_n_body='eval
      arg=$1;
      case $arg in #(
      *"$as_nl"*)
	expr "X$arg" : "X\\(.*\\)$as_nl";
	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
      esac;
      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
    '
    export as_echo_n_body
    as_echo_n='sh -c $as_echo_n_body as_echo'
  fi
  export as_echo_body
  as_echo='sh -c $as_echo_body as_echo'
fi

# The user is always right.
if test "${PATH_SEPARATOR+set}" != set; then
  PATH_SEPARATOR=:
  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
      PATH_SEPARATOR=';'
  }
fi


# IFS
# We need space, tab and new line, in precisely that order.  Quoting is
# there to prevent editors from complaining about space-tab.
# (If _AS_PATH_WALK were called with IFS unset, it would disable word
# splitting by setting IFS to empty value.)
IFS=" ""	$as_nl"

# Find who we are.  Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
  *[\\/]* ) as_myself=$0 ;;
  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  test -z "$as_dir" && as_dir=.
    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
  done
IFS=$as_save_IFS

     ;;
esac
# We did not find ourselves, most probably we were run as `sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
  as_myself=$0
fi
if test ! -f "$as_myself"; then
  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
  exit 1
fi

# Unset variables that we do not need and which cause bugs (e.g. in
# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
# suppresses any "Segmentation fault" message there.  '((' could
# trigger a bug in pdksh 5.2.14.
for as_var in BASH_ENV ENV MAIL MAILPATH
do eval test x\${$as_var+set} = xset \
  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done
PS1='$ '
PS2='> '
PS4='+ '

# NLS nuisances.
LC_ALL=C
export LC_ALL
LANGUAGE=C
export LANGUAGE

# CDPATH.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH

# Use a proper internal environment variable to ensure we don't fall
  # into an infinite loop, continuously re-executing ourselves.
  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
    _as_can_reexec=no; export _as_can_reexec;
    # We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
  *v*x* | *x*v* ) as_opts=-vx ;;
  *v* ) as_opts=-v ;;
  *x* ) as_opts=-x ;;
  * ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
as_fn_exit 255
  fi
  # We don't want this to propagate to other subprocesses.
          { _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
  emulate sh
  NULLCMD=:
  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '\${1+\"\$@\"}'='\"\$@\"'
  setopt NO_GLOB_SUBST
else
  case \`(set -o) 2>/dev/null\` in #(
  *posix*) :
    set -o posix ;; #(
  *) :
     ;;
esac
fi
"
  as_required="as_fn_return () { (exit \$1); }
as_fn_success () { as_fn_return 0; }
as_fn_failure () { as_fn_return 1; }
as_fn_ret_success () { return 0; }
as_fn_ret_failure () { return 1; }

exitcode=0
as_fn_success || { exitcode=1; echo as_fn_success failed.; }
as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :

else
  exitcode=1; echo positional parameters were not saved.
fi
test x\$exitcode = x0 || exit 1
test -x / || exit 1"
  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
  if (eval "$as_required") 2>/dev/null; then :
  as_have_required=yes
else
  as_have_required=no
fi
  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :

else
  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
  IFS=$as_save_IFS
  test -z "$as_dir" && as_dir=.
  as_found=:
  case $as_dir in #(
	 /*)
	   for as_base in sh bash ksh sh5; do
	     # Try only shells that exist, to save several forks.
	     as_shell=$as_dir/$as_base
	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
  CONFIG_SHELL=$as_shell as_have_required=yes
		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
  break 2
fi
fi
	   done;;
       esac
  as_found=false
done
$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
  CONFIG_SHELL=$SHELL as_have_required=yes
fi; }
IFS=$as_save_IFS


      if test "x$CONFIG_SHELL" != x; then :
  export CONFIG_SHELL
             # We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
  *v*x* | *x*v* ) as_opts=-vx ;;
  *v* ) as_opts=-v ;;
  *x* ) as_opts=-x ;;
  * ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi

    if test x$as_have_required = xno; then :
  $as_echo "$0: This script requires a shell more modern than all"
  $as_echo "$0: the shells that I found on your system."
  if test x${ZSH_VERSION+set} = xset ; then
    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
  else
    $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
  fi
  exit 1
fi
fi
fi
SHELL=${CONFIG_SHELL-/bin/sh}
export SHELL
# Unset more variables known to interfere with behavior of common tools.
CLICOLOR_FORCE= GREP_OPTIONS=
unset CLICOLOR_FORCE GREP_OPTIONS

## --------------------- ##
## M4sh Shell Functions. ##
## --------------------- ##
# as_fn_unset VAR
# ---------------
# Portably unset VAR.
as_fn_unset ()
{
  { eval $1=; unset $1;}
}
as_unset=as_fn_unset

# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
as_fn_set_status ()
{
  return $1
} # as_fn_set_status

# as_fn_exit STATUS
# -----------------
# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
as_fn_exit ()
{
  set +e
  as_fn_set_status $1
  exit $1
} # as_fn_exit

# as_fn_mkdir_p
# -------------
# Create "$as_dir" as a directory, including parents if necessary.
as_fn_mkdir_p ()
{

  case $as_dir in #(
  -*) as_dir=./$as_dir;;
  esac
  test -d "$as_dir" || eval $as_mkdir_p || {
    as_dirs=
    while :; do
      case $as_dir in #(
      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
      *) as_qdir=$as_dir;;
      esac
      as_dirs="'$as_qdir' $as_dirs"
      as_dir=`$as_dirname -- "$as_dir" ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$as_dir" : 'X\(//\)[^/]' \| \
	 X"$as_dir" : 'X\(//\)$' \| \
	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$as_dir" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`
      test -d "$as_dir" && break
    done
    test -z "$as_dirs" || eval "mkdir $as_dirs"
  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"


} # as_fn_mkdir_p

# as_fn_executable_p FILE
# -----------------------
# Test if FILE is an executable regular file.
as_fn_executable_p ()
{
  test -f "$1" && test -x "$1"
} # as_fn_executable_p
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
  eval 'as_fn_append ()
  {
    eval $1+=\$2
  }'
else
  as_fn_append ()
  {
    eval $1=\$$1\$2
  }
fi # as_fn_append

# as_fn_arith ARG...
# ------------------
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
  eval 'as_fn_arith ()
  {
    as_val=$(( $* ))
  }'
else
  as_fn_arith ()
  {
    as_val=`expr "$@" || test $? -eq 1`
  }
fi # as_fn_arith


# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
  as_status=$1; test $as_status -eq 0 && as_status=1
  if test "$4"; then
    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
  fi
  $as_echo "$as_me: error: $2" >&2
  as_fn_exit $as_status
} # as_fn_error

if expr a : '\(a\)' >/dev/null 2>&1 &&
   test "X`expr 00001 : '.*\(...\)'`" = X001; then
  as_expr=expr
else
  as_expr=false
fi

if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
  as_basename=basename
else
  as_basename=false
fi

if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
  as_dirname=dirname
else
  as_dirname=false
fi

as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
	 X"$0" : 'X\(//\)$' \| \
	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X/"$0" |
    sed '/^.*\/\([^/][^/]*\)\/*$/{
	    s//\1/
	    q
	  }
	  /^X\/\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\/\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`

# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits


  as_lineno_1=$LINENO as_lineno_1a=$LINENO
  as_lineno_2=$LINENO as_lineno_2a=$LINENO
  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
  sed -n '
    p
    /[$]LINENO/=
  ' <$as_myself |
    sed '
      s/[$]LINENO.*/&-/
      t lineno
      b
      :lineno
      N
      :loop
      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
      t loop
      s/-\n.*//
    ' >$as_me.lineno &&
  chmod +x "$as_me.lineno" ||
    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }

  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
  # already done that, so ensure we don't try to do so again and fall
  # in an infinite loop.  This has already happened in practice.
  _as_can_reexec=no; export _as_can_reexec
  # Don't try to exec as it changes $[0], causing all sort of problems
  # (the dirname of $[0] is not the place where we might find the
  # original and so on.  Autoconf is especially sensitive to this).
  . "./$as_me.lineno"
  # Exit status is that of the last command.
  exit
}

ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
  case `echo 'xy\c'` in
  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
  xy)  ECHO_C='\c';;
  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
       ECHO_T='	';;
  esac;;
*)
  ECHO_N='-n';;
esac

rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
  rm -f conf$$.dir/conf$$.file
else
  rm -f conf$$.dir
  mkdir conf$$.dir 2>/dev/null
fi
if (echo >conf$$.file) 2>/dev/null; then
  if ln -s conf$$.file conf$$ 2>/dev/null; then
    as_ln_s='ln -s'
    # ... but there are two gotchas:
    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
    # In both cases, we have to default to `cp -pR'.
    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
      as_ln_s='cp -pR'
  elif ln conf$$.file conf$$ 2>/dev/null; then
    as_ln_s=ln
  else
    as_ln_s='cp -pR'
  fi
else
  as_ln_s='cp -pR'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null

if mkdir -p . 2>/dev/null; then
  as_mkdir_p='mkdir -p "$as_dir"'
else
  test -d ./-p && rmdir ./-p
  as_mkdir_p=false
fi

as_test_x='test -x'
as_executable_p=as_fn_executable_p

# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"

# Sed expression to map a string onto a valid variable name.
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"


test -n "$DJDIR" || exec 7<&0 </dev/null
exec 6>&1

# Name of the host.
# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
# so uname gets run too.
ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`

#
# Initializations.
#
ac_default_prefix=/usr/local
ac_clean_files=
ac_config_libobj_dir=.
LIBOBJS=
cross_compiling=no
subdirs=
MFLAGS=
MAKEFLAGS=

# Identity of this package.
PACKAGE_NAME=
PACKAGE_TARNAME=
PACKAGE_VERSION=
PACKAGE_STRING=
PACKAGE_BUGREPORT=
PACKAGE_URL=

ac_unique_file="man2tcl.c"
ac_subst_vars='LTLIBOBJS
LIBOBJS
TCL_BIN_DIR
TCL_SRC_DIR
TCL_PATCH_LEVEL
TCL_VERSION
CC
TCL_WIN_VERSION
target_alias
host_alias
build_alias
LIBS
ECHO_T
ECHO_N
ECHO_C
DEFS
mandir
localedir
libdir
psdir
pdfdir
dvidir
htmldir
infodir
docdir
oldincludedir
includedir
localstatedir
sharedstatedir
sysconfdir
datadir
datarootdir
libexecdir
sbindir
bindir
program_transform_name
prefix
exec_prefix
PACKAGE_URL
PACKAGE_BUGREPORT
PACKAGE_STRING
PACKAGE_VERSION
PACKAGE_TARNAME
PACKAGE_NAME
PATH_SEPARATOR
SHELL'
ac_subst_files=''
ac_user_opts='
enable_option_checking
with_tcl
'
      ac_precious_vars='build_alias
host_alias
target_alias'


# Initialize some variables set by options.
ac_init_help=
ac_init_version=false
ac_unrecognized_opts=
ac_unrecognized_sep=
# The variables have the same names as the options, with
# dashes changed to underlines.
cache_file=/dev/null
exec_prefix=NONE
no_create=
no_recursion=
prefix=NONE
program_prefix=NONE
program_suffix=NONE
program_transform_name=s,x,x,
silent=
site=
srcdir=
verbose=
x_includes=NONE
x_libraries=NONE

# Installation directory options.
# These are left unexpanded so users can "make install exec_prefix=/foo"
# and all the variables that are supposed to be based on exec_prefix
# by default will actually change.
# Use braces instead of parens because sh, perl, etc. also accept them.
# (The list follows the same order as the GNU Coding Standards.)
bindir='${exec_prefix}/bin'
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
datarootdir='${prefix}/share'
datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE}'
infodir='${datarootdir}/info'
htmldir='${docdir}'
dvidir='${docdir}'
pdfdir='${docdir}'
psdir='${docdir}'
libdir='${exec_prefix}/lib'
localedir='${datarootdir}/locale'
mandir='${datarootdir}/man'

ac_prev=
ac_dashdash=
for ac_option
do
  # If the previous option needs an argument, assign it.
  if test -n "$ac_prev"; then
    eval $ac_prev=\$ac_option
    ac_prev=
    continue
  fi

  case $ac_option in
  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
  *=)   ac_optarg= ;;
  *)    ac_optarg=yes ;;
  esac

  # Accept the important Cygnus configure options, so we can diagnose typos.

  case $ac_dashdash$ac_option in
  --)
    ac_dashdash=yes ;;

  -bindir | --bindir | --bindi | --bind | --bin | --bi)
    ac_prev=bindir ;;
  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
    bindir=$ac_optarg ;;

  -build | --build | --buil | --bui | --bu)
    ac_prev=build_alias ;;
  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
    build_alias=$ac_optarg ;;

  -cache-file | --cache-file | --cache-fil | --cache-fi \
  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
    ac_prev=cache_file ;;
  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
    cache_file=$ac_optarg ;;

  --config-cache | -C)
    cache_file=config.cache ;;

  -datadir | --datadir | --datadi | --datad)
    ac_prev=datadir ;;
  -datadir=* | --datadir=* | --datadi=* | --datad=*)
    datadir=$ac_optarg ;;

  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
  | --dataroo | --dataro | --datar)
    ac_prev=datarootdir ;;
  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
    datarootdir=$ac_optarg ;;

  -disable-* | --disable-*)
    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid feature name: $ac_useropt"
    ac_useropt_orig=$ac_useropt
    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"enable_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
    eval enable_$ac_useropt=no ;;

  -docdir | --docdir | --docdi | --doc | --do)
    ac_prev=docdir ;;
  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
    docdir=$ac_optarg ;;

  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
    ac_prev=dvidir ;;
  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
    dvidir=$ac_optarg ;;

  -enable-* | --enable-*)
    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid feature name: $ac_useropt"
    ac_useropt_orig=$ac_useropt
    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"enable_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
    eval enable_$ac_useropt=\$ac_optarg ;;

  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
  | --exec | --exe | --ex)
    ac_prev=exec_prefix ;;
  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
  | --exec=* | --exe=* | --ex=*)
    exec_prefix=$ac_optarg ;;

  -gas | --gas | --ga | --g)
    # Obsolete; use --with-gas.
    with_gas=yes ;;

  -help | --help | --hel | --he | -h)
    ac_init_help=long ;;
  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
    ac_init_help=recursive ;;
  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
    ac_init_help=short ;;

  -host | --host | --hos | --ho)
    ac_prev=host_alias ;;
  -host=* | --host=* | --hos=* | --ho=*)
    host_alias=$ac_optarg ;;

  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
    ac_prev=htmldir ;;
  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
  | --ht=*)
    htmldir=$ac_optarg ;;

  -includedir | --includedir | --includedi | --included | --include \
  | --includ | --inclu | --incl | --inc)
    ac_prev=includedir ;;
  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
  | --includ=* | --inclu=* | --incl=* | --inc=*)
    includedir=$ac_optarg ;;

  -infodir | --infodir | --infodi | --infod | --info | --inf)
    ac_prev=infodir ;;
  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
    infodir=$ac_optarg ;;

  -libdir | --libdir | --libdi | --libd)
    ac_prev=libdir ;;
  -libdir=* | --libdir=* | --libdi=* | --libd=*)
    libdir=$ac_optarg ;;

  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
  | --libexe | --libex | --libe)
    ac_prev=libexecdir ;;
  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
  | --libexe=* | --libex=* | --libe=*)
    libexecdir=$ac_optarg ;;

  -localedir | --localedir | --localedi | --localed | --locale)
    ac_prev=localedir ;;
  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
    localedir=$ac_optarg ;;

  -localstatedir | --localstatedir | --localstatedi | --localstated \
  | --localstate | --localstat | --localsta | --localst | --locals)
    ac_prev=localstatedir ;;
  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
    localstatedir=$ac_optarg ;;

  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
    ac_prev=mandir ;;
  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
    mandir=$ac_optarg ;;

  -nfp | --nfp | --nf)
    # Obsolete; use --without-fp.
    with_fp=no ;;

  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
  | --no-cr | --no-c | -n)
    no_create=yes ;;

  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
    no_recursion=yes ;;

  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
  | --oldin | --oldi | --old | --ol | --o)
    ac_prev=oldincludedir ;;
  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
    oldincludedir=$ac_optarg ;;

  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
    ac_prev=prefix ;;
  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
    prefix=$ac_optarg ;;

  -program-prefix | --program-prefix | --program-prefi | --program-pref \
  | --program-pre | --program-pr | --program-p)
    ac_prev=program_prefix ;;
  -program-prefix=* | --program-prefix=* | --program-prefi=* \
  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
    program_prefix=$ac_optarg ;;

  -program-suffix | --program-suffix | --program-suffi | --program-suff \
  | --program-suf | --program-su | --program-s)
    ac_prev=program_suffix ;;
  -program-suffix=* | --program-suffix=* | --program-suffi=* \
  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
    program_suffix=$ac_optarg ;;

  -program-transform-name | --program-transform-name \
  | --program-transform-nam | --program-transform-na \
  | --program-transform-n | --program-transform- \
  | --program-transform | --program-transfor \
  | --program-transfo | --program-transf \
  | --program-trans | --program-tran \
  | --progr-tra | --program-tr | --program-t)
    ac_prev=program_transform_name ;;
  -program-transform-name=* | --program-transform-name=* \
  | --program-transform-nam=* | --program-transform-na=* \
  | --program-transform-n=* | --program-transform-=* \
  | --program-transform=* | --program-transfor=* \
  | --program-transfo=* | --program-transf=* \
  | --program-trans=* | --program-tran=* \
  | --progr-tra=* | --program-tr=* | --program-t=*)
    program_transform_name=$ac_optarg ;;

  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
    ac_prev=pdfdir ;;
  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
    pdfdir=$ac_optarg ;;

  -psdir | --psdir | --psdi | --psd | --ps)
    ac_prev=psdir ;;
  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
    psdir=$ac_optarg ;;

  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
  | -silent | --silent | --silen | --sile | --sil)
    silent=yes ;;

  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
    ac_prev=sbindir ;;
  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
  | --sbi=* | --sb=*)
    sbindir=$ac_optarg ;;

  -sharedstatedir | --sharedstatedir | --sharedstatedi \
  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
  | --sharedst | --shareds | --shared | --share | --shar \
  | --sha | --sh)
    ac_prev=sharedstatedir ;;
  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
  | --sha=* | --sh=*)
    sharedstatedir=$ac_optarg ;;

  -site | --site | --sit)
    ac_prev=site ;;
  -site=* | --site=* | --sit=*)
    site=$ac_optarg ;;

  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
    ac_prev=srcdir ;;
  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
    srcdir=$ac_optarg ;;

  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
  | --syscon | --sysco | --sysc | --sys | --sy)
    ac_prev=sysconfdir ;;
  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
    sysconfdir=$ac_optarg ;;

  -target | --target | --targe | --targ | --tar | --ta | --t)
    ac_prev=target_alias ;;
  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
    target_alias=$ac_optarg ;;

  -v | -verbose | --verbose | --verbos | --verbo | --verb)
    verbose=yes ;;

  -version | --version | --versio | --versi | --vers | -V)
    ac_init_version=: ;;

  -with-* | --with-*)
    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid package name: $ac_useropt"
    ac_useropt_orig=$ac_useropt
    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"with_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
    eval with_$ac_useropt=\$ac_optarg ;;

  -without-* | --without-*)
    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid package name: $ac_useropt"
    ac_useropt_orig=$ac_useropt
    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"with_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
    eval with_$ac_useropt=no ;;

  --x)
    # Obsolete; use --with-x.
    with_x=yes ;;

  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
  | --x-incl | --x-inc | --x-in | --x-i)
    ac_prev=x_includes ;;
  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
    x_includes=$ac_optarg ;;

  -x-libraries | --x-libraries | --x-librarie | --x-librari \
  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
    ac_prev=x_libraries ;;
  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
    x_libraries=$ac_optarg ;;

  -*) as_fn_error $? "unrecognized option: \`$ac_option'
Try \`$0 --help' for more information"
    ;;

  *=*)
    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
    # Reject names that are not valid shell variable names.
    case $ac_envvar in #(
      '' | [0-9]* | *[!_$as_cr_alnum]* )
      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
    esac
    eval $ac_envvar=\$ac_optarg
    export $ac_envvar ;;

  *)
    # FIXME: should be removed in autoconf 3.0.
    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
    ;;

  esac
done

if test -n "$ac_prev"; then
  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
  as_fn_error $? "missing argument to $ac_option"
fi

if test -n "$ac_unrecognized_opts"; then
  case $enable_option_checking in
    no) ;;
    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
  esac
fi

# Check all directory arguments for consistency.
for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
		datadir sysconfdir sharedstatedir localstatedir includedir \
		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
		libdir localedir mandir
do
  eval ac_val=\$$ac_var
  # Remove trailing slashes.
  case $ac_val in
    */ )
      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
      eval $ac_var=\$ac_val;;
  esac
  # Be sure to have absolute directory names.
  case $ac_val in
    [\\/$]* | ?:[\\/]* )  continue;;
    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
  esac
  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
done

# There might be people who depend on the old broken behavior: `$host'
# used to hold the argument of --host etc.
# FIXME: To remove some day.
build=$build_alias
host=$host_alias
target=$target_alias

# FIXME: To remove some day.
if test "x$host_alias" != x; then
  if test "x$build_alias" = x; then
    cross_compiling=maybe
  elif test "x$build_alias" != "x$host_alias"; then
    cross_compiling=yes
  fi
fi

ac_tool_prefix=
test -n "$host_alias" && ac_tool_prefix=$host_alias-

test "$silent" = yes && exec 6>/dev/null


ac_pwd=`pwd` && test -n "$ac_pwd" &&
ac_ls_di=`ls -di .` &&
ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
  as_fn_error $? "working directory cannot be determined"
test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
  as_fn_error $? "pwd does not report name of working directory"


# Find the source files, if location was not specified.
if test -z "$srcdir"; then
  ac_srcdir_defaulted=yes
  # Try the directory containing this script, then the parent directory.
  ac_confdir=`$as_dirname -- "$as_myself" ||
$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$as_myself" : 'X\(//\)[^/]' \| \
	 X"$as_myself" : 'X\(//\)$' \| \
	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$as_myself" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`
  srcdir=$ac_confdir
  if test ! -r "$srcdir/$ac_unique_file"; then
    srcdir=..
  fi
else
  ac_srcdir_defaulted=no
fi
if test ! -r "$srcdir/$ac_unique_file"; then
  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
fi
ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
ac_abs_confdir=`(
	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
	pwd)`
# When building in place, set srcdir=.
if test "$ac_abs_confdir" = "$ac_pwd"; then
  srcdir=.
fi
# Remove unnecessary trailing slashes from srcdir.
# Double slashes in file names in object file debugging info
# mess up M-x gdb in Emacs.
case $srcdir in
*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
esac
for ac_var in $ac_precious_vars; do
  eval ac_env_${ac_var}_set=\${${ac_var}+set}
  eval ac_env_${ac_var}_value=\$${ac_var}
  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
  eval ac_cv_env_${ac_var}_value=\$${ac_var}
done

#
# Report the --help message.
#
if test "$ac_init_help" = "long"; then
  # Omit some internal or obsolete options to make the list less imposing.
  # This message is too long to be a string in the A/UX 3.1 sh.
  cat <<_ACEOF
\`configure' configures this package to adapt to many kinds of systems.

Usage: $0 [OPTION]... [VAR=VALUE]...

To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE.  See below for descriptions of some of the useful variables.

Defaults for the options are specified in brackets.

Configuration:
  -h, --help              display this help and exit
      --help=short        display options specific to this package
      --help=recursive    display the short help of all the included packages
  -V, --version           display version information and exit
  -q, --quiet, --silent   do not print \`checking ...' messages
      --cache-file=FILE   cache test results in FILE [disabled]
  -C, --config-cache      alias for \`--cache-file=config.cache'
  -n, --no-create         do not create output files
      --srcdir=DIR        find the sources in DIR [configure dir or \`..']

Installation directories:
  --prefix=PREFIX         install architecture-independent files in PREFIX
                          [$ac_default_prefix]
  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
                          [PREFIX]

By default, \`make install' will install all the files in
\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
an installation prefix other than \`$ac_default_prefix' using \`--prefix',
for instance \`--prefix=\$HOME'.

For better control, use the options below.

Fine tuning of the installation directories:
  --bindir=DIR            user executables [EPREFIX/bin]
  --sbindir=DIR           system admin executables [EPREFIX/sbin]
  --libexecdir=DIR        program executables [EPREFIX/libexec]
  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
  --libdir=DIR            object code libraries [EPREFIX/lib]
  --includedir=DIR        C header files [PREFIX/include]
  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
  --infodir=DIR           info documentation [DATAROOTDIR/info]
  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
  --mandir=DIR            man documentation [DATAROOTDIR/man]
  --docdir=DIR            documentation root [DATAROOTDIR/doc/PACKAGE]
  --htmldir=DIR           html documentation [DOCDIR]
  --dvidir=DIR            dvi documentation [DOCDIR]
  --pdfdir=DIR            pdf documentation [DOCDIR]
  --psdir=DIR             ps documentation [DOCDIR]
_ACEOF

  cat <<\_ACEOF
_ACEOF
fi

if test -n "$ac_init_help"; then

  cat <<\_ACEOF

Optional Packages:
  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
  --with-tcl=DIR          use Tcl $DEF_VER binaries from DIR

Report bugs to the package provider.
_ACEOF
ac_status=$?
fi

if test "$ac_init_help" = "recursive"; then
  # If there are subdirs, report their specific --help.
  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
    test -d "$ac_dir" ||
      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
      continue
    ac_builddir=.

case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
  # A ".." for each directory in $ac_dir_suffix.
  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
  case $ac_top_builddir_sub in
  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
  esac ;;
esac
ac_abs_top_builddir=$ac_pwd
ac_abs_builddir=$ac_pwd$ac_dir_suffix
# for backward compatibility:
ac_top_builddir=$ac_top_build_prefix

case $srcdir in
  .)  # We are building in place.
    ac_srcdir=.
    ac_top_srcdir=$ac_top_builddir_sub
    ac_abs_top_srcdir=$ac_pwd ;;
  [\\/]* | ?:[\\/]* )  # Absolute name.
    ac_srcdir=$srcdir$ac_dir_suffix;
    ac_top_srcdir=$srcdir
    ac_abs_top_srcdir=$srcdir ;;
  *) # Relative name.
    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
    ac_top_srcdir=$ac_top_build_prefix$srcdir
    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix

    cd "$ac_dir" || { ac_status=$?; continue; }
    # Check for guested configure.
    if test -f "$ac_srcdir/configure.gnu"; then
      echo &&
      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
    elif test -f "$ac_srcdir/configure"; then
      echo &&
      $SHELL "$ac_srcdir/configure" --help=recursive
    else
      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
    fi || ac_status=$?
    cd "$ac_pwd" || { ac_status=$?; break; }
  done
fi

test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
  cat <<\_ACEOF
configure
generated by GNU Autoconf 2.69

Copyright (C) 2012 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
  exit
fi

## ------------------------ ##
## Autoconf initialization. ##
## ------------------------ ##
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.

It was created by $as_me, which was
generated by GNU Autoconf 2.69.  Invocation command line was

  $ $0 $@

_ACEOF
exec 5>>config.log
{
cat <<_ASUNAME
## --------- ##
## Platform. ##
## --------- ##

hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
uname -m = `(uname -m) 2>/dev/null || echo unknown`
uname -r = `(uname -r) 2>/dev/null || echo unknown`
uname -s = `(uname -s) 2>/dev/null || echo unknown`
uname -v = `(uname -v) 2>/dev/null || echo unknown`

/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`

/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`

_ASUNAME

as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  test -z "$as_dir" && as_dir=.
    $as_echo "PATH: $as_dir"
  done
IFS=$as_save_IFS

} >&5

cat >&5 <<_ACEOF


## ----------- ##
## Core tests. ##
## ----------- ##

_ACEOF


# Keep a trace of the command line.
# Strip out --no-create and --no-recursion so they do not pile up.
# Strip out --silent because we don't want to record it for future runs.
# Also quote any args containing shell meta-characters.
# Make two passes to allow for proper duplicate-argument suppression.
ac_configure_args=
ac_configure_args0=
ac_configure_args1=
ac_must_keep_next=false
for ac_pass in 1 2
do
  for ac_arg
  do
    case $ac_arg in
    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
    | -silent | --silent | --silen | --sile | --sil)
      continue ;;
    *\'*)
      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
    esac
    case $ac_pass in
    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
    2)
      as_fn_append ac_configure_args1 " '$ac_arg'"
      if test $ac_must_keep_next = true; then
	ac_must_keep_next=false # Got value, back to normal.
      else
	case $ac_arg in
	  *=* | --config-cache | -C | -disable-* | --disable-* \
	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
	  | -with-* | --with-* | -without-* | --without-* | --x)
	    case "$ac_configure_args0 " in
	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
	    esac
	    ;;
	  -* ) ac_must_keep_next=true ;;
	esac
      fi
      as_fn_append ac_configure_args " '$ac_arg'"
      ;;
    esac
  done
done
{ ac_configure_args0=; unset ac_configure_args0;}
{ ac_configure_args1=; unset ac_configure_args1;}

# When interrupted or exit'd, cleanup temporary files, and complete
# config.log.  We remove comments because anyway the quotes in there
# would cause problems or look ugly.
# WARNING: Use '\'' to represent an apostrophe within the trap.
# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
  # Save into config.log some information that might help in debugging.
  {
    echo

    $as_echo "## ---------------- ##
## Cache variables. ##
## ---------------- ##"
    echo
    # The following way of writing the cache mishandles newlines in values,
(
  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
    eval ac_val=\$$ac_var
    case $ac_val in #(
    *${as_nl}*)
      case $ac_var in #(
      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
      esac
      case $ac_var in #(
      _ | IFS | as_nl) ;; #(
      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
      *) { eval $ac_var=; unset $ac_var;} ;;
      esac ;;
    esac
  done
  (set) 2>&1 |
    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
    *${as_nl}ac_space=\ *)
      sed -n \
	"s/'\''/'\''\\\\'\'''\''/g;
	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
      ;; #(
    *)
      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
      ;;
    esac |
    sort
)
    echo

    $as_echo "## ----------------- ##
## Output variables. ##
## ----------------- ##"
    echo
    for ac_var in $ac_subst_vars
    do
      eval ac_val=\$$ac_var
      case $ac_val in
      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
      esac
      $as_echo "$ac_var='\''$ac_val'\''"
    done | sort
    echo

    if test -n "$ac_subst_files"; then
      $as_echo "## ------------------- ##
## File substitutions. ##
## ------------------- ##"
      echo
      for ac_var in $ac_subst_files
      do
	eval ac_val=\$$ac_var
	case $ac_val in
	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
	esac
	$as_echo "$ac_var='\''$ac_val'\''"
      done | sort
      echo
    fi

    if test -s confdefs.h; then
      $as_echo "## ----------- ##
## confdefs.h. ##
## ----------- ##"
      echo
      cat confdefs.h
      echo
    fi
    test "$ac_signal" != 0 &&
      $as_echo "$as_me: caught signal $ac_signal"
    $as_echo "$as_me: exit $exit_status"
  } >&5
  rm -f core *.core core.conftest.* &&
    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
    exit $exit_status
' 0
for ac_signal in 1 2 13 15; do
  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
done
ac_signal=0

# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -f -r conftest* confdefs.h

$as_echo "/* confdefs.h */" > confdefs.h

# Predefined preprocessor variables.

cat >>confdefs.h <<_ACEOF
#define PACKAGE_NAME "$PACKAGE_NAME"
_ACEOF

cat >>confdefs.h <<_ACEOF
#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
_ACEOF

cat >>confdefs.h <<_ACEOF
#define PACKAGE_VERSION "$PACKAGE_VERSION"
_ACEOF

cat >>confdefs.h <<_ACEOF
#define PACKAGE_STRING "$PACKAGE_STRING"
_ACEOF

cat >>confdefs.h <<_ACEOF
#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
_ACEOF

cat >>confdefs.h <<_ACEOF
#define PACKAGE_URL "$PACKAGE_URL"
_ACEOF


# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.
ac_site_file1=NONE
ac_site_file2=NONE
if test -n "$CONFIG_SITE"; then
  # We do not want a PATH search for config.site.
  case $CONFIG_SITE in #((
    -*)  ac_site_file1=./$CONFIG_SITE;;
    */*) ac_site_file1=$CONFIG_SITE;;
    *)   ac_site_file1=./$CONFIG_SITE;;
  esac
elif test "x$prefix" != xNONE; then
  ac_site_file1=$prefix/share/config.site
  ac_site_file2=$prefix/etc/config.site
else
  ac_site_file1=$ac_default_prefix/share/config.site
  ac_site_file2=$ac_default_prefix/etc/config.site
fi
for ac_site_file in "$ac_site_file1" "$ac_site_file2"
do
  test "x$ac_site_file" = xNONE && continue
  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
$as_echo "$as_me: loading site script $ac_site_file" >&6;}
    sed 's/^/| /' "$ac_site_file" >&5
    . "$ac_site_file" \
      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5; }
  fi
done

if test -r "$cache_file"; then
  # Some versions of bash will fail to source /dev/null (special files
  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
$as_echo "$as_me: loading cache $cache_file" >&6;}
    case $cache_file in
      [\\/]* | ?:[\\/]* ) . "$cache_file";;
      *)                      . "./$cache_file";;
    esac
  fi
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
$as_echo "$as_me: creating cache $cache_file" >&6;}
  >$cache_file
fi

# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
for ac_var in $ac_precious_vars; do
  eval ac_old_set=\$ac_cv_env_${ac_var}_set
  eval ac_new_set=\$ac_env_${ac_var}_set
  eval ac_old_val=\$ac_cv_env_${ac_var}_value
  eval ac_new_val=\$ac_env_${ac_var}_value
  case $ac_old_set,$ac_new_set in
    set,)
      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
      ac_cache_corrupted=: ;;
    ,set)
      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
      ac_cache_corrupted=: ;;
    ,);;
    *)
      if test "x$ac_old_val" != "x$ac_new_val"; then
	# differences in whitespace do not lead to failure.
	ac_old_val_w=`echo x $ac_old_val`
	ac_new_val_w=`echo x $ac_new_val`
	if test "$ac_old_val_w" != "$ac_new_val_w"; then
	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
	  ac_cache_corrupted=:
	else
	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
	  eval $ac_var=\$ac_old_val
	fi
	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
      fi;;
  esac
  # Pass precious variables to config.status.
  if test "$ac_new_set" = set; then
    case $ac_new_val in
    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
    *) ac_arg=$ac_var=$ac_new_val ;;
    esac
    case " $ac_configure_args " in
      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
    esac
  fi
done
if $ac_cache_corrupted; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
## -------------------- ##

ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu




# Recover information that Tcl computed with its configure script.

#--------------------------------------------------------------------
#       See if there was a command-line option for where Tcl is;  if
#       not, assume that its top-level directory is a sibling of ours.
#--------------------------------------------------------------------

DEF_VER=9.0


# Check whether --with-tcl was given.
if test "${with_tcl+set}" = set; then :
  withval=$with_tcl; TCL_BIN_DIR=$withval
else
  TCL_BIN_DIR=`cd ../../tcl$DEF_VER$TCL_PATCH_LEVEL/unix; pwd`
fi

if test ! -d $TCL_BIN_DIR; then
    as_fn_error $? "Tcl directory $TCL_BIN_DIR doesn't exist" "$LINENO" 5
fi
if test ! -f $TCL_BIN_DIR/tclConfig.sh; then
    as_fn_error $? "There's no tclConfig.sh in $TCL_BIN_DIR;  perhaps you didn't specify the Tcl *build* directory (not the toplevel Tcl directory) or you forgot to configure Tcl?" "$LINENO" 5
fi

. $TCL_BIN_DIR/tclConfig.sh

TCL_WIN_VERSION=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION

CC=$TCL_CC






ac_config_files="$ac_config_files Makefile tcl.hpj"

cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
# scripts and configure runs, see configure's option --config-cache.
# It is not useful on other systems.  If it contains results you don't
# want to keep, you may remove or edit it.
#
# config.status only pays attention to the cache file if you give it
# the --recheck option to rerun configure.
#
# `ac_cv_env_foo' variables (set or unset) will be overridden when
# loading this file, other *unset* `ac_cv_foo' will be assigned the
# following values.

_ACEOF

# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
# So, we kill variables containing newlines.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
(
  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
    eval ac_val=\$$ac_var
    case $ac_val in #(
    *${as_nl}*)
      case $ac_var in #(
      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
      esac
      case $ac_var in #(
      _ | IFS | as_nl) ;; #(
      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
      *) { eval $ac_var=; unset $ac_var;} ;;
      esac ;;
    esac
  done

  (set) 2>&1 |
    case $as_nl`(ac_space=' '; set) 2>&1` in #(
    *${as_nl}ac_space=\ *)
      # `set' does not quote correctly, so add quotes: double-quote
      # substitution turns \\\\ into \\, and sed turns \\ into \.
      sed -n \
	"s/'/'\\\\''/g;
	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
      ;; #(
    *)
      # `set' quotes correctly as required by POSIX, so do not add quotes.
      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
      ;;
    esac |
    sort
) |
  sed '
     /^ac_cv_env_/b end
     t clear
     :clear
     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
     t end
     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
     :end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
  if test -w "$cache_file"; then
    if test "x$cache_file" != "x/dev/null"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
$as_echo "$as_me: updating cache $cache_file" >&6;}
      if test ! -f "$cache_file" || test -h "$cache_file"; then
	cat confcache >"$cache_file"
      else
        case $cache_file in #(
        */* | ?:*)
	  mv -f confcache "$cache_file"$$ &&
	  mv -f "$cache_file"$$ "$cache_file" ;; #(
        *)
	  mv -f confcache "$cache_file" ;;
	esac
      fi
    fi
  else
    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
  fi
fi
rm -f confcache

test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'

# Transform confdefs.h into DEFS.
# Protect against shell expansion while executing Makefile rules.
# Protect against Makefile macro expansion.
#
# If the first sed substitution is executed (which looks for macros that
# take arguments), then branch to the quote section.  Otherwise,
# look for a macro that doesn't take arguments.
ac_script='
:mline
/\\$/{
 N
 s,\\\n,,
 b mline
}
t clear
:clear
s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\)/-D\1=\2/g
t quote
s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)/-D\1=\2/g
t quote
b any
:quote
s/[	 `~#$^&*(){}\\|;'\''"<>?]/\\&/g
s/\[/\\&/g
s/\]/\\&/g
s/\$/$$/g
H
:any
${
	g
	s/^\n//
	s/\n/ /g
	p
}
'
DEFS=`sed -n "$ac_script" confdefs.h`


ac_libobjs=
ac_ltlibobjs=
U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
  # 1. Remove the extension, and $U if already installed.
  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
  #    will be set to the directory where LIBOBJS objects are built.
  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
done
LIBOBJS=$ac_libobjs

LTLIBOBJS=$ac_ltlibobjs



: "${CONFIG_STATUS=./config.status}"
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
# Generated by $as_me.
# Run this file to recreate the current configuration.
# Compiler output produced by configure, useful for debugging
# configure, is in config.log if it exists.

debug=false
ac_cs_recheck=false
ac_cs_silent=false

SHELL=\${CONFIG_SHELL-$SHELL}
export SHELL
_ASEOF
cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##

# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
  emulate sh
  NULLCMD=:
  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '${1+"$@"}'='"$@"'
  setopt NO_GLOB_SUBST
else
  case `(set -o) 2>/dev/null` in #(
  *posix*) :
    set -o posix ;; #(
  *) :
     ;;
esac
fi


as_nl='
'
export as_nl
# Printing a long string crashes Solaris 7 /usr/bin/printf.
as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
# Prefer a ksh shell builtin over an external printf program on Solaris,
# but without wasting forks for bash or zsh.
if test -z "$BASH_VERSION$ZSH_VERSION" \
    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
  as_echo='print -r --'
  as_echo_n='print -rn --'
elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
  as_echo='printf %s\n'
  as_echo_n='printf %s'
else
  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
    as_echo_n='/usr/ucb/echo -n'
  else
    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
    as_echo_n_body='eval
      arg=$1;
      case $arg in #(
      *"$as_nl"*)
	expr "X$arg" : "X\\(.*\\)$as_nl";
	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
      esac;
      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
    '
    export as_echo_n_body
    as_echo_n='sh -c $as_echo_n_body as_echo'
  fi
  export as_echo_body
  as_echo='sh -c $as_echo_body as_echo'
fi

# The user is always right.
if test "${PATH_SEPARATOR+set}" != set; then
  PATH_SEPARATOR=:
  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
      PATH_SEPARATOR=';'
  }
fi


# IFS
# We need space, tab and new line, in precisely that order.  Quoting is
# there to prevent editors from complaining about space-tab.
# (If _AS_PATH_WALK were called with IFS unset, it would disable word
# splitting by setting IFS to empty value.)
IFS=" ""	$as_nl"

# Find who we are.  Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
  *[\\/]* ) as_myself=$0 ;;
  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  test -z "$as_dir" && as_dir=.
    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
  done
IFS=$as_save_IFS

     ;;
esac
# We did not find ourselves, most probably we were run as `sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
  as_myself=$0
fi
if test ! -f "$as_myself"; then
  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
  exit 1
fi

# Unset variables that we do not need and which cause bugs (e.g. in
# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
# suppresses any "Segmentation fault" message there.  '((' could
# trigger a bug in pdksh 5.2.14.
for as_var in BASH_ENV ENV MAIL MAILPATH
do eval test x\${$as_var+set} = xset \
  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done
PS1='$ '
PS2='> '
PS4='+ '

# NLS nuisances.
LC_ALL=C
export LC_ALL
LANGUAGE=C
export LANGUAGE

# CDPATH.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH


# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
  as_status=$1; test $as_status -eq 0 && as_status=1
  if test "$4"; then
    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
  fi
  $as_echo "$as_me: error: $2" >&2
  as_fn_exit $as_status
} # as_fn_error


# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
as_fn_set_status ()
{
  return $1
} # as_fn_set_status

# as_fn_exit STATUS
# -----------------
# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
as_fn_exit ()
{
  set +e
  as_fn_set_status $1
  exit $1
} # as_fn_exit

# as_fn_unset VAR
# ---------------
# Portably unset VAR.
as_fn_unset ()
{
  { eval $1=; unset $1;}
}
as_unset=as_fn_unset
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
  eval 'as_fn_append ()
  {
    eval $1+=\$2
  }'
else
  as_fn_append ()
  {
    eval $1=\$$1\$2
  }
fi # as_fn_append

# as_fn_arith ARG...
# ------------------
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
  eval 'as_fn_arith ()
  {
    as_val=$(( $* ))
  }'
else
  as_fn_arith ()
  {
    as_val=`expr "$@" || test $? -eq 1`
  }
fi # as_fn_arith


if expr a : '\(a\)' >/dev/null 2>&1 &&
   test "X`expr 00001 : '.*\(...\)'`" = X001; then
  as_expr=expr
else
  as_expr=false
fi

if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
  as_basename=basename
else
  as_basename=false
fi

if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
  as_dirname=dirname
else
  as_dirname=false
fi

as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
	 X"$0" : 'X\(//\)$' \| \
	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X/"$0" |
    sed '/^.*\/\([^/][^/]*\)\/*$/{
	    s//\1/
	    q
	  }
	  /^X\/\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\/\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`

# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits

ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
  case `echo 'xy\c'` in
  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
  xy)  ECHO_C='\c';;
  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
       ECHO_T='	';;
  esac;;
*)
  ECHO_N='-n';;
esac

rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
  rm -f conf$$.dir/conf$$.file
else
  rm -f conf$$.dir
  mkdir conf$$.dir 2>/dev/null
fi
if (echo >conf$$.file) 2>/dev/null; then
  if ln -s conf$$.file conf$$ 2>/dev/null; then
    as_ln_s='ln -s'
    # ... but there are two gotchas:
    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
    # In both cases, we have to default to `cp -pR'.
    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
      as_ln_s='cp -pR'
  elif ln conf$$.file conf$$ 2>/dev/null; then
    as_ln_s=ln
  else
    as_ln_s='cp -pR'
  fi
else
  as_ln_s='cp -pR'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null


# as_fn_mkdir_p
# -------------
# Create "$as_dir" as a directory, including parents if necessary.
as_fn_mkdir_p ()
{

  case $as_dir in #(
  -*) as_dir=./$as_dir;;
  esac
  test -d "$as_dir" || eval $as_mkdir_p || {
    as_dirs=
    while :; do
      case $as_dir in #(
      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
      *) as_qdir=$as_dir;;
      esac
      as_dirs="'$as_qdir' $as_dirs"
      as_dir=`$as_dirname -- "$as_dir" ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$as_dir" : 'X\(//\)[^/]' \| \
	 X"$as_dir" : 'X\(//\)$' \| \
	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$as_dir" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`
      test -d "$as_dir" && break
    done
    test -z "$as_dirs" || eval "mkdir $as_dirs"
  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"


} # as_fn_mkdir_p
if mkdir -p . 2>/dev/null; then
  as_mkdir_p='mkdir -p "$as_dir"'
else
  test -d ./-p && rmdir ./-p
  as_mkdir_p=false
fi


# as_fn_executable_p FILE
# -----------------------
# Test if FILE is an executable regular file.
as_fn_executable_p ()
{
  test -f "$1" && test -x "$1"
} # as_fn_executable_p
as_test_x='test -x'
as_executable_p=as_fn_executable_p

# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"

# Sed expression to map a string onto a valid variable name.
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"


exec 6>&1
## ----------------------------------- ##
## Main body of $CONFIG_STATUS script. ##
## ----------------------------------- ##
_ASEOF
test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# Save the log message, to keep $0 and so on meaningful, and to
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by $as_me, which was
generated by GNU Autoconf 2.69.  Invocation command line was

  CONFIG_FILES    = $CONFIG_FILES
  CONFIG_HEADERS  = $CONFIG_HEADERS
  CONFIG_LINKS    = $CONFIG_LINKS
  CONFIG_COMMANDS = $CONFIG_COMMANDS
  $ $0 $@

on `(hostname || uname -n) 2>/dev/null | sed 1q`
"

_ACEOF

case $ac_config_files in *"
"*) set x $ac_config_files; shift; ac_config_files=$*;;
esac



cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
# Files that config.status was made for.
config_files="$ac_config_files"

_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
ac_cs_usage="\
\`$as_me' instantiates files and other configuration actions
from templates according to the current configuration.  Unless the files
and actions are specified as TAGs, all are instantiated by default.

Usage: $0 [OPTION]... [TAG]...

  -h, --help       print this help, then exit
  -V, --version    print version number and configuration settings, then exit
      --config     print configuration, then exit
  -q, --quiet, --silent
                   do not print progress messages
  -d, --debug      don't remove temporary files
      --recheck    update $as_me by reconfiguring in the same conditions
      --file=FILE[:TEMPLATE]
                   instantiate the configuration file FILE

Configuration files:
$config_files

Report bugs to the package provider."

_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
config.status
configured by $0, generated by GNU Autoconf 2.69,
  with options \\"\$ac_cs_config\\"

Copyright (C) 2012 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."

ac_pwd='$ac_pwd'
srcdir='$srcdir'
test -n "\$AWK" || AWK=awk
_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# The default lists apply if the user does not specify any file.
ac_need_defaults=:
while test $# != 0
do
  case $1 in
  --*=?*)
    ac_option=`expr "X$1" : 'X\([^=]*\)='`
    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
    ac_shift=:
    ;;
  --*=)
    ac_option=`expr "X$1" : 'X\([^=]*\)='`
    ac_optarg=
    ac_shift=:
    ;;
  *)
    ac_option=$1
    ac_optarg=$2
    ac_shift=shift
    ;;
  esac

  case $ac_option in
  # Handling of the options.
  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
    ac_cs_recheck=: ;;
  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
    $as_echo "$ac_cs_version"; exit ;;
  --config | --confi | --conf | --con | --co | --c )
    $as_echo "$ac_cs_config"; exit ;;
  --debug | --debu | --deb | --de | --d | -d )
    debug=: ;;
  --file | --fil | --fi | --f )
    $ac_shift
    case $ac_optarg in
    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
    '') as_fn_error $? "missing file argument" ;;
    esac
    as_fn_append CONFIG_FILES " '$ac_optarg'"
    ac_need_defaults=false;;
  --he | --h |  --help | --hel | -h )
    $as_echo "$ac_cs_usage"; exit ;;
  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
  | -silent | --silent | --silen | --sile | --sil | --si | --s)
    ac_cs_silent=: ;;

  # This is an error.
  -*) as_fn_error $? "unrecognized option: \`$1'
Try \`$0 --help' for more information." ;;

  *) as_fn_append ac_config_targets " $1"
     ac_need_defaults=false ;;

  esac
  shift
done

ac_configure_extra_args=

if $ac_cs_silent; then
  exec 6>/dev/null
  ac_configure_extra_args="$ac_configure_extra_args --silent"
fi

_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
  shift
  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
  CONFIG_SHELL='$SHELL'
  export CONFIG_SHELL
  exec "\$@"
fi

_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
exec 5>>config.log
{
  echo
  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
  $as_echo "$ac_log"
} >&5

_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1

# Handling of arguments.
for ac_config_target in $ac_config_targets
do
  case $ac_config_target in
    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
    "tcl.hpj") CONFIG_FILES="$CONFIG_FILES tcl.hpj" ;;

  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
  esac
done


# If the user did not use the arguments to specify the items to instantiate,
# then the envvar interface is used.  Set only those that are not.
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
fi

# Have a temporary directory for convenience.  Make it in the build tree
# simply because there is no reason against having it here, and in addition,
# creating and moving files from /tmp can sometimes cause problems.
# Hook for its removal unless debugging.
# Note that there is a small window in which the directory will not be cleaned:
# after its creation but before its name has been assigned to `$tmp'.
$debug ||
{
  tmp= ac_tmp=
  trap 'exit_status=$?
  : "${ac_tmp:=$tmp}"
  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
' 0
  trap 'as_fn_exit 1' 1 2 13 15
}
# Create a (secure) tmp directory for tmp files.

{
  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
  test -d "$tmp"
}  ||
{
  tmp=./conf$$-$RANDOM
  (umask 077 && mkdir "$tmp")
} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
ac_tmp=$tmp

# Set up the scripts for CONFIG_FILES section.
# No need to generate them if there are no CONFIG_FILES.
# This happens for instance with `./config.status config.h'.
if test -n "$CONFIG_FILES"; then


ac_cr=`echo X | tr X '\015'`
# On cygwin, bash can eat \r inside `` if the user requested igncr.
# But we know of no other shell where ac_cr would be empty at this
# point, so we can use a bashism as a fallback.
if test "x$ac_cr" = x; then
  eval ac_cr=\$\'\\r\'
fi
ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
  ac_cs_awk_cr='\\r'
else
  ac_cs_awk_cr=$ac_cr
fi

echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
_ACEOF


{
  echo "cat >conf$$subs.awk <<_ACEOF" &&
  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
  echo "_ACEOF"
} >conf$$subs.sh ||
  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
  . ./conf$$subs.sh ||
    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5

  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
  if test $ac_delim_n = $ac_delim_num; then
    break
  elif $ac_last_try; then
    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
  else
    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
  fi
done
rm -f conf$$subs.sh

cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
_ACEOF
sed -n '
h
s/^/S["/; s/!.*/"]=/
p
g
s/^[^!]*!//
:repl
t repl
s/'"$ac_delim"'$//
t delim
:nl
h
s/\(.\{148\}\)..*/\1/
t more1
s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
p
n
b repl
:more1
s/["\\]/\\&/g; s/^/"/; s/$/"\\/
p
g
s/.\{148\}//
t nl
:delim
h
s/\(.\{148\}\)..*/\1/
t more2
s/["\\]/\\&/g; s/^/"/; s/$/"/
p
b
:more2
s/["\\]/\\&/g; s/^/"/; s/$/"\\/
p
g
s/.\{148\}//
t delim
' <conf$$subs.awk | sed '
/^[^""]/{
  N
  s/\n//
}
' >>$CONFIG_STATUS || ac_write_fail=1
rm -f conf$$subs.awk
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
_ACAWK
cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
  for (key in S) S_is_set[key] = 1
  FS = ""

}
{
  line = $ 0
  nfields = split(line, field, "@")
  substed = 0
  len = length(field[1])
  for (i = 2; i < nfields; i++) {
    key = field[i]
    keylen = length(key)
    if (S_is_set[key]) {
      value = S[key]
      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
      len += length(value) + length(field[++i])
      substed = 1
    } else
      len += 1 + keylen
  }

  print line
}

_ACAWK
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
else
  cat
fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
_ACEOF

# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
# trailing colons and then remove the whole line if VPATH becomes empty
# (actually we leave an empty line to preserve line numbers).
if test "x$srcdir" = x.; then
  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
h
s///
s/^/:/
s/[	 ]*$/:/
s/:\$(srcdir):/:/g
s/:\${srcdir}:/:/g
s/:@srcdir@:/:/g
s/^:*//
s/:*$//
x
s/\(=[	 ]*\).*/\1/
G
s/\n//
s/^[^=]*=[	 ]*$//
}'
fi

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
fi # test -n "$CONFIG_FILES"


eval set X "  :F $CONFIG_FILES      "
shift
for ac_tag
do
  case $ac_tag in
  :[FHLC]) ac_mode=$ac_tag; continue;;
  esac
  case $ac_mode$ac_tag in
  :[FHL]*:*);;
  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
  :[FH]-) ac_tag=-:-;;
  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
  esac
  ac_save_IFS=$IFS
  IFS=:
  set x $ac_tag
  IFS=$ac_save_IFS
  shift
  ac_file=$1
  shift

  case $ac_mode in
  :L) ac_source=$1;;
  :[FH])
    ac_file_inputs=
    for ac_f
    do
      case $ac_f in
      -) ac_f="$ac_tmp/stdin";;
      *) # Look for the file first in the build tree, then in the source tree
	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
	 # because $ac_f cannot contain `:'.
	 test -f "$ac_f" ||
	   case $ac_f in
	   [\\/$]*) false;;
	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
	   esac ||
	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
      esac
      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
      as_fn_append ac_file_inputs " '$ac_f'"
    done

    # Let's still pretend it is `configure' which instantiates (i.e., don't
    # use $as_me), people would be surprised to read:
    #    /* config.h.  Generated by config.status.  */
    configure_input='Generated from '`
	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
	`' by configure.'
    if test x"$ac_file" != x-; then
      configure_input="$ac_file.  $configure_input"
      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
$as_echo "$as_me: creating $ac_file" >&6;}
    fi
    # Neutralize special characters interpreted by sed in replacement strings.
    case $configure_input in #(
    *\&* | *\|* | *\\* )
       ac_sed_conf_input=`$as_echo "$configure_input" |
       sed 's/[\\\\&|]/\\\\&/g'`;; #(
    *) ac_sed_conf_input=$configure_input;;
    esac

    case $ac_tag in
    *:-:* | *:-) cat >"$ac_tmp/stdin" \
      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
    esac
    ;;
  esac

  ac_dir=`$as_dirname -- "$ac_file" ||
$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$ac_file" : 'X\(//\)[^/]' \| \
	 X"$ac_file" : 'X\(//\)$' \| \
	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$ac_file" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\).*/{
	    s//\1/
	    q
	  }
	  s/.*/./; q'`
  as_dir="$ac_dir"; as_fn_mkdir_p
  ac_builddir=.

case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
  # A ".." for each directory in $ac_dir_suffix.
  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
  case $ac_top_builddir_sub in
  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
  esac ;;
esac
ac_abs_top_builddir=$ac_pwd
ac_abs_builddir=$ac_pwd$ac_dir_suffix
# for backward compatibility:
ac_top_builddir=$ac_top_build_prefix

case $srcdir in
  .)  # We are building in place.
    ac_srcdir=.
    ac_top_srcdir=$ac_top_builddir_sub
    ac_abs_top_srcdir=$ac_pwd ;;
  [\\/]* | ?:[\\/]* )  # Absolute name.
    ac_srcdir=$srcdir$ac_dir_suffix;
    ac_top_srcdir=$srcdir
    ac_abs_top_srcdir=$srcdir ;;
  *) # Relative name.
    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
    ac_top_srcdir=$ac_top_build_prefix$srcdir
    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix


  case $ac_mode in
  :F)
  #
  # CONFIG_FILE
  #

_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# If the template does not know about datarootdir, expand it.
# FIXME: This hack should be removed a few years after 2.60.
ac_datarootdir_hack=; ac_datarootdir_seen=
ac_sed_dataroot='
/datarootdir/ {
  p
  q
}
/@datadir@/p
/@docdir@/p
/@infodir@/p
/@localedir@/p
/@mandir@/p'
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
  ac_datarootdir_hack='
  s&@datadir@&$datadir&g
  s&@docdir@&$docdir&g
  s&@infodir@&$infodir&g
  s&@localedir@&$localedir&g
  s&@mandir@&$mandir&g
  s&\\\${datarootdir}&$datarootdir&g' ;;
esac
_ACEOF

# Neutralize VPATH when `$srcdir' = `.'.
# Shell code in configure.ac might set extrasub.
# FIXME: do we really want to maintain this feature?
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_sed_extra="$ac_vpsub
$extrasub
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
:t
/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
s|@configure_input@|$ac_sed_conf_input|;t t
s&@top_builddir@&$ac_top_builddir_sub&;t t
s&@top_build_prefix@&$ac_top_build_prefix&;t t
s&@srcdir@&$ac_srcdir&;t t
s&@abs_srcdir@&$ac_abs_srcdir&;t t
s&@top_srcdir@&$ac_top_srcdir&;t t
s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
s&@builddir@&$ac_builddir&;t t
s&@abs_builddir@&$ac_abs_builddir&;t t
s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
$ac_datarootdir_hack
"
eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5

test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
      "$ac_tmp/out"`; test -z "$ac_out"; } &&
  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined.  Please make sure it is defined" >&5
$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined.  Please make sure it is defined" >&2;}

  rm -f "$ac_tmp/stdin"
  case $ac_file in
  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
  esac \
  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
 ;;



  esac

done # for ac_tag


as_fn_exit 0
_ACEOF
ac_clean_files=$ac_clean_files_save

test $ac_write_fail = 0 ||
  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5


# configure is writing to config.log, and then calls config.status.
# config.status does its own redirection, appending to config.log.
# Unfortunately, on DOS this fails, as config.log is still kept open
# by configure, so config.status won't be able to write to it; its
# output is simply discarded.  So we exec the FD to /dev/null,
# effectively closing config.log, so it can be properly (re)opened and
# appended to by config.status.  When coming back to configure, we
# need to make the FD available again.
if test "$no_create" != yes; then
  ac_cs_success=:
  ac_config_status_args=
  test "$silent" = yes &&
    ac_config_status_args="$ac_config_status_args --quiet"
  exec 5>/dev/null
  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
  exec 5>>config.log
  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
  # would make configure fail if this is the last instruction.
  $ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi

Deleted tools/configure.ac.

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
30
31
32
33
34
35



































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
dnl	This file is an input file used by the GNU "autoconf" program to
dnl	generate the file "configure", which is run to configure the
dnl	Makefile in this directory.
AC_INIT(man2tcl.c)
AC_PREREQ(2.69)

# Recover information that Tcl computed with its configure script.

#--------------------------------------------------------------------
#       See if there was a command-line option for where Tcl is;  if
#       not, assume that its top-level directory is a sibling of ours.
#--------------------------------------------------------------------

DEF_VER=9.0

AC_ARG_WITH(tcl, [  --with-tcl=DIR          use Tcl $DEF_VER binaries from DIR], TCL_BIN_DIR=$withval, TCL_BIN_DIR=`cd ../../tcl$DEF_VER$TCL_PATCH_LEVEL/unix; pwd`)
if test ! -d $TCL_BIN_DIR; then
    AC_MSG_ERROR(Tcl directory $TCL_BIN_DIR doesn't exist)
fi
if test ! -f $TCL_BIN_DIR/tclConfig.sh; then
    AC_MSG_ERROR(There's no tclConfig.sh in $TCL_BIN_DIR;  perhaps you didn't specify the Tcl *build* directory (not the toplevel Tcl directory) or you forgot to configure Tcl?)
fi

. $TCL_BIN_DIR/tclConfig.sh

TCL_WIN_VERSION=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION
AC_SUBST(TCL_WIN_VERSION)
CC=$TCL_CC
AC_SUBST(CC)
AC_SUBST(TCL_VERSION)
AC_SUBST(TCL_PATCH_LEVEL)
AC_SUBST(TCL_SRC_DIR)
AC_SUBST(TCL_BIN_DIR)

AC_OUTPUT(Makefile tcl.hpj)

Changes to tools/encoding/Makefile.

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
67
68
69
70
71
72
73





74
75
76
77
78
79
80







-
-
-
-
-







	@for p in *.txt; do \
	    enc=`echo $$p | sed 's/\..*$$/\.enc/'`; \
	    echo $$enc; \
	    ./txt2enc -e 0 -u 1 $$p > $$enc; \
	done
	@echo
	@echo Compiling special versions of encoding files.
	@for p in ascii.txt; do \
	    enc=`echo $$p | sed 's/\..*$$/\.enc/'`; \
	    echo $$enc; \
	    ./txt2enc -m $$p > $$enc; \
	done
	@for p in jis0208.txt; do \
	    enc=`echo $$p | sed 's/\..*$$/\.enc/'`; \
	    echo $$enc; \
	    ./txt2enc -e 1 -u 2 $$p > $$enc; \
	done
	@for p in symbol.txt dingbats.txt macDingbats.txt; do \
	    enc=`echo $$p | sed 's/\..*$$/\.enc/'`; \

Changes to tools/encoding/big5.txt.

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
30

31
32
33
34
35
36
37
38
39
40
41






42
43
44
45
46
47
48




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
-
-
-
-
+
+
+
+
-

-
-
-
-
-
-
-


-
+

-
+
-
-

-
+

-
-
-
-
-
+
-
-
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+







# big5.txt --
#
#	BIG5 to Unicode table (modified)
#
# BIG5.TXT
# Date: 2015-12-02 23:52:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# NOTE: this table has been modified to include the 7-bit ASCII
# characters that are allowed in BIG5 files.
#
#
#	Name:             BIG5 to Unicode table (complete)
#	Unicode version:  1.1
#	Table version:    0.0d3
#	Table version:    2.0
#	Table format:     Format A
#	Date:             11 February 1994
#	Date:             2011 October 14 (header updated: 2015 December 02)
#	Authors:          Glenn Adams <glenn@metis.com>
#                     John H. Jenkins <John_Jenkins@taligent.com>
#
#	Copyright (c) 1991-1994 Unicode, Inc.  All Rights reserved.
#	General notes:
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on magnetic media by Unicode, Inc., the sole
# NOTE: this table has been modified to include the 7-bit ASCII
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
# characters that are allowed in BIG5 files.
#
#	Recipient is granted the right to make copies in any form for
#	internal distribution and to freely use the information supplied
#	in the creation of products supporting Unicode.  Unicode, Inc.
#	specifically excludes the right to re-distribute this file directly
#	to third parties or other organizations whether for profit or not.
#
#	General notes:
#
#	This table contains the data Metis and Taligent currently have on how
#       BIG5 characters map into Unicode.
# This table contains one set of mappings from BIG5 into Unicode.
# Note that these data are *possible* mappings only and may not be the
# same as those used by actual products, nor may they be the best suited
# for all uses.  For more information on the mappings between various code
# pages incorporating the repertoire of BIG5 and Unicode, consult the
# VENDORS mapping data.
#
#	WARNING!  It is currently impossible to provide round-trip compatibility
#		between BIG5 and Unicode.
#
#	A number of characters are not currently mapped because
#		of conflicts with other mappings.  They are as follows:
#
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
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







-
-
-
+
+
+


-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-





-
-
-
-
-
-
-
+
+
+
+
+
+
+



+
+
+
+
+
+
+
+
-
+
+

+
+
+
+
+







#		It is also possible to map these characters to their duplicates, or to
#		the user zone.
#
#	Notes:
#
#	1. In addition to the above, there is some uncertainty about the
#       mappings in the range C6A1 - C8FE, and F9DD - F9FE.  The ETEN
#		version of BIG5 organizes the former range differently, and adds
#		additional characters in the latter range.  The correct mappings
#		these ranges need to be determined.
#	version of BIG5 organizes the former range differently, and adds
#	additional characters in the latter range.  The correct mappings
#	these ranges need to be determined.
#
#	2.  There is an uncertainty in the mapping of the Big Five character
#		0xA3BC.  This character occurs within the Big Five block of tone marks
#		for bopomofo and is intended to be the tone mark for the first tone in
#		Mandarin Chinese.  We have selected the mapping U+02C9 MODIFIER LETTER
#		MACRON (Mandarin Chinese first tone) to reflect this semantic.
#		However, because bopomofo uses the absense of a tone mark to indicate
#		the first Mandarin tone, most implementations of Big Five represent
#		this character with a blank space, and so a mapping such as U+2003 EM SPACE
#		might be preferred.
#	0xA3BC.  This character occurs within the Big Five block of tone marks
#	for bopomofo and is intended to be the tone mark for the first tone in
#	Mandarin Chinese.  We have selected the mapping U+02C9 MODIFIER LETTER
#	MACRON (Mandarin Chinese first tone) to reflect this semantic.
#	However, because bopomofo uses the absense of a tone mark to indicate
#	the first Mandarin tone, most implementations of Big Five represent
#	this character with a blank space, and so a mapping such as U+2003 EM
#	SPACE might be preferred.
#
#
#
#	Format:  Three tab-separated columns
#		 Column #1 is the BIG5 code (in hex as 0xXXXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3  is the Unicode name (follows a comment sign, '#')
#					The official names for Unicode characters U+4E00
#					to U+9FA5, inclusive, is "CJK UNIFIED IDEOGRAPH-XXXX",
#					where XXXX is the code point.  Including all these
#					names in this file increases its size substantially
#					and needlessly.  The token "<CJK>" is used for the
#					name of these characters.  If necessary, it can be
#					expanded algorithmically by a parser or editor.
#			The official names for Unicode characters U+4E00
#			to U+9FA5, inclusive, is "CJK UNIFIED IDEOGRAPH-XXXX",
#			where XXXX is the code point.  Including all these
#			names in this file increases its size substantially
#			and needlessly.  The token "<CJK>" is used for the
#			name of these characters.  If necessary, it can be
#			expanded algorithmically by a parser or editor.
#
#	The entries are in BIG5 order
#
#  Revision History:
#
#    [v2.0, 2015 December 02]
#    updates to copyright notice and terms of use
#    no changes to character mappings
#
#    [v1.0, 2011 October 14]
#    Updated terms of use to current wording.
#	Any comments or problems, contact <John_Jenkins@taligent.com>
#    Updated contact information.
#    No changes to the mapping data.
#
#    [v0.0d3, 11 February 1994]
#    First release.
#
#  Use the Unicode reporting form <http://www.unicode.org/reporting.html>
#    for any questions or comments or to report errors in the data.
#
0x20	0x0020	# SPACE
0x21	0x0021	# EXCLAMATION MARK
0x22	0x0022	# QUOTATION MARK
0x23	0x0023	# NUMBER SIGN
0x24	0x0024	# DOLLAR SIGN
0x25	0x0025	# PERCENT SIGN

Added tools/encoding/cns11643.txt.

more than 10,000 changes

Changes to tools/encoding/cp1250.txt.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







#
#    Name:     cp1250 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlate@microsoft.com
#    Contact:       Shawn.Steele@microsoft.com
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1250 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp1251.txt.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







#
#    Name:     cp1251 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlate@microsoft.com
#    Contact:       Shawn.Steele@microsoft.com
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1251 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp1252.txt.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







#
#    Name:     cp1252 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlate@microsoft.com
#    Contact:       Shawn.Steele@microsoft.com
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1252 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp1253.txt.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







#
#    Name:     cp1253 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlate@microsoft.com
#    Contact:       Shawn.Steele@microsoft.com
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1253 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp1254.txt.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







#
#    Name:     cp1254 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlate@microsoft.com
#    Contact:       Shawn.Steele@microsoft.com
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1254 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp1255.txt.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







#
#    Name:     cp1255 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          1/7/2000
#
#    Contact:       cpxlate@microsoft.com
#    Contact:       Shawn.Steele@microsoft.com
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1255 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp1256.txt.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







#
#    Name:     cp1256 to Unicode table
#    Unicode version: 2.1
#    Table version: 2.01
#    Table format:  Format A
#    Date:          01/5/99
#
#    Contact:       cpxlate@microsoft.com
#    Contact:       Shawn.Steele@microsoft.com
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1256 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp1257.txt.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







#
#    Name:     cp1257 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlate@microsoft.com
#    Contact:       Shawn.Steele@microsoft.com
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1257 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp1258.txt.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







#
#    Name:     cp1258 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlate@microsoft.com
#    Contact:       Shawn.Steele@microsoft.com
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp1258 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp874.txt.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







#
#    Name:     cp874 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          02/28/98
#
#    Contact:       cpxlate@microsoft.com
#    Contact:       Shawn.Steele@microsoft.com
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp874 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp932.txt.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







#
#    Name:     cp932 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlate@microsoft.com
#    Contact:       Shawn.Steele@microsoft.com
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp932 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp936.txt.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







#
#    Name:     cp936 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          1/7/2000
#
#    Contact:       cpxlate@microsoft.com
#    Contact:       Shawn.Steele@microsoft.com
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp936 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp949.txt.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







#
#    Name:     cp949 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          1/7/2000
#
#    Contact:       cpxlate@microsoft.com
#    Contact:       Shawn.Steele@microsoft.com
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp949 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/cp950.txt.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







#
#    Name:     cp950 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          1/7/2000
#
#    Contact:       cpxlate@microsoft.com
#    Contact:       Shawn.Steele@microsoft.com
#
#    General notes: none
#
#    Format: Three tab-separated columns
#        Column #1 is the cp950 code (in hex)
#        Column #2 is the Unicode (in hex as 0xXXXX)
#        Column #3 is the Unicode name (follows a comment sign, '#')

Changes to tools/encoding/gb2312.txt.

1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# gb2312.txt --
#
#	GB2312 to Unicode table (modified)
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 1998-1999 Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# NOTE: this table has been modified to include the 7-bit ASCII
# characters that are allowed in GB2312 files.
#

Changes to tools/encoding/iso8859-1.txt.





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
30
31
32
33
34
35
36
37
38
39




40
41
42

43
44
45


46
47
48
49
50
51
52
53
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
30
31

32
33


34
35

36
37
38
39
40
41
42
+
+
+
+



-
+

-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-














-
-
+
+
+
+


-
+

-
-
+
+
-







# 8859-1.TXT
# Date: 2015-12-02 20:19:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-1:1998 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
#
#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-1:1998 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-1 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-1 order.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.
#   1.0 version: updates 0.1 version by adding mappings for all
#       control characters.
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact <errata@unicode.org>
#	Please note that <errata@unicode.org> is an archival address;
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY

Changes to tools/encoding/iso8859-10.txt.





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
30
31
32
33
34
35
36
37
38
39



40
41
42

43
44
45


46
47
48
49
50
51
52
53
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
30
31

32
33


34
35

36
37
38
39
40
41
42
+
+
+
+



-
+

-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-















-
+
+
+


-
+

-
-
+
+
-







# 8859-10.TXT
# Date: 2015-12-02 21:53:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-10:1998 to Unicode
#	Unicode version:  3.0
#	Table version:    1.1
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 October 11
#	Authors:          Ken Whistler <kenw@sybase.com>
#	Date:             1999 October 11 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
#
#	Copyright (c) 1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-10:1998 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-10 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-10 order.
#
#	Version history
#	1.0 version new.
#       1.1 corrected mistake in mapping of 0xA4
#   1.1 corrected mistake in mapping of 0xA4
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact <errata@unicode.org>
#	Please note that <errata@unicode.org> is an archival address;
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY

Added tools/encoding/iso8859-11.txt.































































































































































































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 8859-11.TXT
# Date: 2015-12-02 21:55:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-11:2001 to Unicode
#	Unicode version:  3.2
#	Table version:    2.0
#	Table format:     Format A
#	Date:             2002 October 7 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-11:2001 characters map into Unicode.
#
#	ISO/IEC 8859-11:2001 is equivalent to TIS 620-2533 (1990) with
#	the addition of 0xA0 NO-BREAK SPACE.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-11 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-11 order.
#
#	Version history:
#		2002 October 7  Created
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
0x06	0x0006	#	ACKNOWLEDGE
0x07	0x0007	#	BELL
0x08	0x0008	#	BACKSPACE
0x09	0x0009	#	HORIZONTAL TABULATION
0x0A	0x000A	#	LINE FEED
0x0B	0x000B	#	VERTICAL TABULATION
0x0C	0x000C	#	FORM FEED
0x0D	0x000D	#	CARRIAGE RETURN
0x0E	0x000E	#	SHIFT OUT
0x0F	0x000F	#	SHIFT IN
0x10	0x0010	#	DATA LINK ESCAPE
0x11	0x0011	#	DEVICE CONTROL ONE
0x12	0x0012	#	DEVICE CONTROL TWO
0x13	0x0013	#	DEVICE CONTROL THREE
0x14	0x0014	#	DEVICE CONTROL FOUR
0x15	0x0015	#	NEGATIVE ACKNOWLEDGE
0x16	0x0016	#	SYNCHRONOUS IDLE
0x17	0x0017	#	END OF TRANSMISSION BLOCK
0x18	0x0018	#	CANCEL
0x19	0x0019	#	END OF MEDIUM
0x1A	0x001A	#	SUBSTITUTE
0x1B	0x001B	#	ESCAPE
0x1C	0x001C	#	FILE SEPARATOR
0x1D	0x001D	#	GROUP SEPARATOR
0x1E	0x001E	#	RECORD SEPARATOR
0x1F	0x001F	#	UNIT SEPARATOR
0x20	0x0020	#	SPACE
0x21	0x0021	#	EXCLAMATION MARK
0x22	0x0022	#	QUOTATION MARK
0x23	0x0023	#	NUMBER SIGN
0x24	0x0024	#	DOLLAR SIGN
0x25	0x0025	#	PERCENT SIGN
0x26	0x0026	#	AMPERSAND
0x27	0x0027	#	APOSTROPHE
0x28	0x0028	#	LEFT PARENTHESIS
0x29	0x0029	#	RIGHT PARENTHESIS
0x2A	0x002A	#	ASTERISK
0x2B	0x002B	#	PLUS SIGN
0x2C	0x002C	#	COMMA
0x2D	0x002D	#	HYPHEN-MINUS
0x2E	0x002E	#	FULL STOP
0x2F	0x002F	#	SOLIDUS
0x30	0x0030	#	DIGIT ZERO
0x31	0x0031	#	DIGIT ONE
0x32	0x0032	#	DIGIT TWO
0x33	0x0033	#	DIGIT THREE
0x34	0x0034	#	DIGIT FOUR
0x35	0x0035	#	DIGIT FIVE
0x36	0x0036	#	DIGIT SIX
0x37	0x0037	#	DIGIT SEVEN
0x38	0x0038	#	DIGIT EIGHT
0x39	0x0039	#	DIGIT NINE
0x3A	0x003A	#	COLON
0x3B	0x003B	#	SEMICOLON
0x3C	0x003C	#	LESS-THAN SIGN
0x3D	0x003D	#	EQUALS SIGN
0x3E	0x003E	#	GREATER-THAN SIGN
0x3F	0x003F	#	QUESTION MARK
0x40	0x0040	#	COMMERCIAL AT
0x41	0x0041	#	LATIN CAPITAL LETTER A
0x42	0x0042	#	LATIN CAPITAL LETTER B
0x43	0x0043	#	LATIN CAPITAL LETTER C
0x44	0x0044	#	LATIN CAPITAL LETTER D
0x45	0x0045	#	LATIN CAPITAL LETTER E
0x46	0x0046	#	LATIN CAPITAL LETTER F
0x47	0x0047	#	LATIN CAPITAL LETTER G
0x48	0x0048	#	LATIN CAPITAL LETTER H
0x49	0x0049	#	LATIN CAPITAL LETTER I
0x4A	0x004A	#	LATIN CAPITAL LETTER J
0x4B	0x004B	#	LATIN CAPITAL LETTER K
0x4C	0x004C	#	LATIN CAPITAL LETTER L
0x4D	0x004D	#	LATIN CAPITAL LETTER M
0x4E	0x004E	#	LATIN CAPITAL LETTER N
0x4F	0x004F	#	LATIN CAPITAL LETTER O
0x50	0x0050	#	LATIN CAPITAL LETTER P
0x51	0x0051	#	LATIN CAPITAL LETTER Q
0x52	0x0052	#	LATIN CAPITAL LETTER R
0x53	0x0053	#	LATIN CAPITAL LETTER S
0x54	0x0054	#	LATIN CAPITAL LETTER T
0x55	0x0055	#	LATIN CAPITAL LETTER U
0x56	0x0056	#	LATIN CAPITAL LETTER V
0x57	0x0057	#	LATIN CAPITAL LETTER W
0x58	0x0058	#	LATIN CAPITAL LETTER X
0x59	0x0059	#	LATIN CAPITAL LETTER Y
0x5A	0x005A	#	LATIN CAPITAL LETTER Z
0x5B	0x005B	#	LEFT SQUARE BRACKET
0x5C	0x005C	#	REVERSE SOLIDUS
0x5D	0x005D	#	RIGHT SQUARE BRACKET
0x5E	0x005E	#	CIRCUMFLEX ACCENT
0x5F	0x005F	#	LOW LINE
0x60	0x0060	#	GRAVE ACCENT
0x61	0x0061	#	LATIN SMALL LETTER A
0x62	0x0062	#	LATIN SMALL LETTER B
0x63	0x0063	#	LATIN SMALL LETTER C
0x64	0x0064	#	LATIN SMALL LETTER D
0x65	0x0065	#	LATIN SMALL LETTER E
0x66	0x0066	#	LATIN SMALL LETTER F
0x67	0x0067	#	LATIN SMALL LETTER G
0x68	0x0068	#	LATIN SMALL LETTER H
0x69	0x0069	#	LATIN SMALL LETTER I
0x6A	0x006A	#	LATIN SMALL LETTER J
0x6B	0x006B	#	LATIN SMALL LETTER K
0x6C	0x006C	#	LATIN SMALL LETTER L
0x6D	0x006D	#	LATIN SMALL LETTER M
0x6E	0x006E	#	LATIN SMALL LETTER N
0x6F	0x006F	#	LATIN SMALL LETTER O
0x70	0x0070	#	LATIN SMALL LETTER P
0x71	0x0071	#	LATIN SMALL LETTER Q
0x72	0x0072	#	LATIN SMALL LETTER R
0x73	0x0073	#	LATIN SMALL LETTER S
0x74	0x0074	#	LATIN SMALL LETTER T
0x75	0x0075	#	LATIN SMALL LETTER U
0x76	0x0076	#	LATIN SMALL LETTER V
0x77	0x0077	#	LATIN SMALL LETTER W
0x78	0x0078	#	LATIN SMALL LETTER X
0x79	0x0079	#	LATIN SMALL LETTER Y
0x7A	0x007A	#	LATIN SMALL LETTER Z
0x7B	0x007B	#	LEFT CURLY BRACKET
0x7C	0x007C	#	VERTICAL LINE
0x7D	0x007D	#	RIGHT CURLY BRACKET
0x7E	0x007E	#	TILDE
0x7F	0x007F	#	DELETE
0x80	0x0080	#	<control>
0x81	0x0081	#	<control>
0x82	0x0082	#	<control>
0x83	0x0083	#	<control>
0x84	0x0084	#	<control>
0x85	0x0085	#	<control>
0x86	0x0086	#	<control>
0x87	0x0087	#	<control>
0x88	0x0088	#	<control>
0x89	0x0089	#	<control>
0x8A	0x008A	#	<control>
0x8B	0x008B	#	<control>
0x8C	0x008C	#	<control>
0x8D	0x008D	#	<control>
0x8E	0x008E	#	<control>
0x8F	0x008F	#	<control>
0x90	0x0090	#	<control>
0x91	0x0091	#	<control>
0x92	0x0092	#	<control>
0x93	0x0093	#	<control>
0x94	0x0094	#	<control>
0x95	0x0095	#	<control>
0x96	0x0096	#	<control>
0x97	0x0097	#	<control>
0x98	0x0098	#	<control>
0x99	0x0099	#	<control>
0x9A	0x009A	#	<control>
0x9B	0x009B	#	<control>
0x9C	0x009C	#	<control>
0x9D	0x009D	#	<control>
0x9E	0x009E	#	<control>
0x9F	0x009F	#	<control>
0xA0	0x00A0	#	NO-BREAK SPACE
0xA1	0x0E01	#	THAI CHARACTER KO KAI
0xA2	0x0E02	#	THAI CHARACTER KHO KHAI
0xA3	0x0E03	#	THAI CHARACTER KHO KHUAT
0xA4	0x0E04	#	THAI CHARACTER KHO KHWAI
0xA5	0x0E05	#	THAI CHARACTER KHO KHON
0xA6	0x0E06	#	THAI CHARACTER KHO RAKHANG
0xA7	0x0E07	#	THAI CHARACTER NGO NGU
0xA8	0x0E08	#	THAI CHARACTER CHO CHAN
0xA9	0x0E09	#	THAI CHARACTER CHO CHING
0xAA	0x0E0A	#	THAI CHARACTER CHO CHANG
0xAB	0x0E0B	#	THAI CHARACTER SO SO
0xAC	0x0E0C	#	THAI CHARACTER CHO CHOE
0xAD	0x0E0D	#	THAI CHARACTER YO YING
0xAE	0x0E0E	#	THAI CHARACTER DO CHADA
0xAF	0x0E0F	#	THAI CHARACTER TO PATAK
0xB0	0x0E10	#	THAI CHARACTER THO THAN
0xB1	0x0E11	#	THAI CHARACTER THO NANGMONTHO
0xB2	0x0E12	#	THAI CHARACTER THO PHUTHAO
0xB3	0x0E13	#	THAI CHARACTER NO NEN
0xB4	0x0E14	#	THAI CHARACTER DO DEK
0xB5	0x0E15	#	THAI CHARACTER TO TAO
0xB6	0x0E16	#	THAI CHARACTER THO THUNG
0xB7	0x0E17	#	THAI CHARACTER THO THAHAN
0xB8	0x0E18	#	THAI CHARACTER THO THONG
0xB9	0x0E19	#	THAI CHARACTER NO NU
0xBA	0x0E1A	#	THAI CHARACTER BO BAIMAI
0xBB	0x0E1B	#	THAI CHARACTER PO PLA
0xBC	0x0E1C	#	THAI CHARACTER PHO PHUNG
0xBD	0x0E1D	#	THAI CHARACTER FO FA
0xBE	0x0E1E	#	THAI CHARACTER PHO PHAN
0xBF	0x0E1F	#	THAI CHARACTER FO FAN
0xC0	0x0E20	#	THAI CHARACTER PHO SAMPHAO
0xC1	0x0E21	#	THAI CHARACTER MO MA
0xC2	0x0E22	#	THAI CHARACTER YO YAK
0xC3	0x0E23	#	THAI CHARACTER RO RUA
0xC4	0x0E24	#	THAI CHARACTER RU
0xC5	0x0E25	#	THAI CHARACTER LO LING
0xC6	0x0E26	#	THAI CHARACTER LU
0xC7	0x0E27	#	THAI CHARACTER WO WAEN
0xC8	0x0E28	#	THAI CHARACTER SO SALA
0xC9	0x0E29	#	THAI CHARACTER SO RUSI
0xCA	0x0E2A	#	THAI CHARACTER SO SUA
0xCB	0x0E2B	#	THAI CHARACTER HO HIP
0xCC	0x0E2C	#	THAI CHARACTER LO CHULA
0xCD	0x0E2D	#	THAI CHARACTER O ANG
0xCE	0x0E2E	#	THAI CHARACTER HO NOKHUK
0xCF	0x0E2F	#	THAI CHARACTER PAIYANNOI
0xD0	0x0E30	#	THAI CHARACTER SARA A
0xD1	0x0E31	#	THAI CHARACTER MAI HAN-AKAT
0xD2	0x0E32	#	THAI CHARACTER SARA AA
0xD3	0x0E33	#	THAI CHARACTER SARA AM
0xD4	0x0E34	#	THAI CHARACTER SARA I
0xD5	0x0E35	#	THAI CHARACTER SARA II
0xD6	0x0E36	#	THAI CHARACTER SARA UE
0xD7	0x0E37	#	THAI CHARACTER SARA UEE
0xD8	0x0E38	#	THAI CHARACTER SARA U
0xD9	0x0E39	#	THAI CHARACTER SARA UU
0xDA	0x0E3A	#	THAI CHARACTER PHINTHU
0xDF	0x0E3F	#	THAI CURRENCY SYMBOL BAHT
0xE0	0x0E40	#	THAI CHARACTER SARA E
0xE1	0x0E41	#	THAI CHARACTER SARA AE
0xE2	0x0E42	#	THAI CHARACTER SARA O
0xE3	0x0E43	#	THAI CHARACTER SARA AI MAIMUAN
0xE4	0x0E44	#	THAI CHARACTER SARA AI MAIMALAI
0xE5	0x0E45	#	THAI CHARACTER LAKKHANGYAO
0xE6	0x0E46	#	THAI CHARACTER MAIYAMOK
0xE7	0x0E47	#	THAI CHARACTER MAITAIKHU
0xE8	0x0E48	#	THAI CHARACTER MAI EK
0xE9	0x0E49	#	THAI CHARACTER MAI THO
0xEA	0x0E4A	#	THAI CHARACTER MAI TRI
0xEB	0x0E4B	#	THAI CHARACTER MAI CHATTAWA
0xEC	0x0E4C	#	THAI CHARACTER THANTHAKHAT
0xED	0x0E4D	#	THAI CHARACTER NIKHAHIT
0xEE	0x0E4E	#	THAI CHARACTER YAMAKKAN
0xEF	0x0E4F	#	THAI CHARACTER FONGMAN
0xF0	0x0E50	#	THAI DIGIT ZERO
0xF1	0x0E51	#	THAI DIGIT ONE
0xF2	0x0E52	#	THAI DIGIT TWO
0xF3	0x0E53	#	THAI DIGIT THREE
0xF4	0x0E54	#	THAI DIGIT FOUR
0xF5	0x0E55	#	THAI DIGIT FIVE
0xF6	0x0E56	#	THAI DIGIT SIX
0xF7	0x0E57	#	THAI DIGIT SEVEN
0xF8	0x0E58	#	THAI DIGIT EIGHT
0xF9	0x0E59	#	THAI DIGIT NINE
0xFA	0x0E5A	#	THAI CHARACTER ANGKHANKHU
0xFB	0x0E5B	#	THAI CHARACTER KHOMUT

Changes to tools/encoding/iso8859-13.txt.





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
30
31
32
33
34
35
36





37
38

39
40
41


42
43
44
45
46
47
48
49
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
30

31
32


33
34

35
36
37
38
39
40
41
+
+
+
+



-
+

-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-













+
+
+
+
+

-
+

-
-
+
+
-







# 8859-13.TXT
# Date: 2015-12-02 22:03:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-13:1998  to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
#
#	Copyright (c) 1998 - 1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-13:1998 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-13 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-13 order.
#
#	Version history
#   1.0 version: created
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact <errata@unicode.org>
#	Please note that <errata@unicode.org> is an archival address;
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY

Changes to tools/encoding/iso8859-14.txt.





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
30
31
32
33
34
35
36
37





38
39

40
41
42


43
44
45
46
47
48
49
50
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
30
31

32
33


34
35

36
37
38
39
40
41
42
+
+
+
+



-
+

-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-













+
+
+
+
+

-
+

-
-
+
+
-







# 8859-14.TXT
# Date: 2015-12-02 22:05:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-14:1998 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Markus Kuhn <mkuhn@acm.org>
#			  Ken Whistler <kenw@sybase.com>
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>
#			  Ken Whistler <ken@unicode.org>
#
#	Copyright (c) 1998 - 1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-14:1998 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-14 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-14 order.
#
#	Version history
#   1.0 version: created
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact <errata@unicode.org>
#	Please note that <errata@unicode.org> is an archival address;
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
294
295
296
297
298
299
300
301
286
287
288
289
290
291
292








-
0xF9	0x00F9	#	LATIN SMALL LETTER U WITH GRAVE
0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
0xFB	0x00FB	#	LATIN SMALL LETTER U WITH CIRCUMFLEX
0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
0xFD	0x00FD	#	LATIN SMALL LETTER Y WITH ACUTE
0xFE	0x0177	#	LATIN SMALL LETTER Y WITH CIRCUMFLEX
0xFF	0x00FF	#	LATIN SMALL LETTER Y WITH DIAERESIS

Changes to tools/encoding/iso8859-15.txt.





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
30
31
32
33
34
35
36
37
38
39





40
41

42
43
44


45
46
47
48
49
50
51
52
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
30
31
32
33

34
35


36
37

38
39
40
41
42
43
44
+
+
+
+



-
+

-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-















+
+
+
+
+

-
+

-
-
+
+
-







# 8859-15.TXT
# Date: 2015-12-02 22:06:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-15:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Markus Kuhn <mkuhn@acm.org>
#			  Ken Whistler <kenw@sybase.com>
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>
#			  Ken Whistler <ken@unicode.org>
#
#	Copyright (c) 1998 - 1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-15:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-15 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-15 order.
#
#	Version history
#
#	Version history
#   1.0 version: created
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact <errata@unicode.org>
#	Please note that <errata@unicode.org> is an archival address;
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
296
297
298
299
300
301
302
303
288
289
290
291
292
293
294








-
0xF9	0x00F9	#	LATIN SMALL LETTER U WITH GRAVE
0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
0xFB	0x00FB	#	LATIN SMALL LETTER U WITH CIRCUMFLEX
0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
0xFD	0x00FD	#	LATIN SMALL LETTER Y WITH ACUTE
0xFE	0x00FE	#	LATIN SMALL LETTER THORN
0xFF	0x00FF	#	LATIN SMALL LETTER Y WITH DIAERESIS

Changes to tools/encoding/iso8859-16.txt.





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
30
31
32
33
34
35
36





37
38

39
40
41


42
43
44
45
46
47
48
49
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
30
31
32

33
34


35
36

37
38
39
40
41
42
43
+
+
+
+



-
+

-
-
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-












+
+
+
+
+

-
+

-
-
+
+
-







# 8859-16.TXT
# Date: 2015-12-02 22:08:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-16:2001 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             2001 July 26
#	Authors:          Markus Kuhn <mkuhn@acm.org>
#	Date:             2001 July 26 (header updated: 2015 December 02)
#	Authors:          Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>
#
#	Copyright (c) 1999-2001 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-16:2001 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-16 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-16 order.
#
#	Version history
#   1.0 version: created
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact <errata@unicode.org>
#	Please note that <errata@unicode.org> is an archival address;
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY

Changes to tools/encoding/iso8859-2.txt.





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
30
31
32
33
34
35
36
37
38
39




40
41
42

43
44
45


46
47
48
49
50
51
52
53
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
30
31

32
33


34
35

36
37
38
39
40
41
42
+
+
+
+



-
+

-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-














-
-
+
+
+
+


-
+

-
-
+
+
-







# 8859-2.TXT
# Date: 2015-12-02 21:34:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO 8859-2:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
#
#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-2:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-2 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-2 order.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.
#   1.0 version: updates 0.1 version by adding mappings for all
#       control characters.
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact <errata@unicode.org>
#	Please note that <errata@unicode.org> is an archival address;
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY

Changes to tools/encoding/iso8859-3.txt.





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
30
31
32
33
34
35
36
37
38
39




40
41
42

43
44
45


46
47
48
49
50
51
52
53
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
30
31

32
33


34
35

36
37
38
39
40
41
42
+
+
+
+



-
+

-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-














-
-
+
+
+
+


-
+

-
-
+
+
-







# 8859-3.TXT
# Date: 2015-12-02 21:39:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-3:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
#
#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-3:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-3 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-3 order.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.
#   1.0 version: updates 0.1 version by adding mappings for all
#       control characters.
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact <errata@unicode.org>
#	Please note that <errata@unicode.org> is an archival address;
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY

Changes to tools/encoding/iso8859-4.txt.





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
30
31
32
33
34
35
36
37
38
39




40
41
42

43
44
45


46
47
48
49
50
51
52
53
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
30
31

32
33


34
35

36
37
38
39
40
41
42
+
+
+
+



-
+

-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-














-
-
+
+
+
+


-
+

-
-
+
+
-







# 8859-4.TXT
# Date: 2015-12-02 21:41:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-4:1998 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
#
#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-4:1998 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-4 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-4 order.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.
#   1.0 version: updates 0.1 version by adding mappings for all
#       control characters.
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact <errata@unicode.org>
#	Please note that <errata@unicode.org> is an archival address;
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY

Changes to tools/encoding/iso8859-5.txt.





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
30
31
32
33
34
35
36
37
38
39




40
41
42

43
44
45


46
47
48
49
50
51
52
53
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
30
31

32
33


34
35

36
37
38
39
40
41
42
+
+
+
+



-
+

-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-














-
-
+
+
+
+


-
+

-
-
+
+
-







# 8859-5.TXT
# Date: 2015-12-02 21:43:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO 8859-5:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
#
#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-5:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-5 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-5 order.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.
#   1.0 version: updates 0.1 version by adding mappings for all
#       control characters.
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact <errata@unicode.org>
#	Please note that <errata@unicode.org> is an archival address;
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY

Changes to tools/encoding/iso8859-6.txt.





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
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
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
30
31
32
33

34
35


36
37

38
39
40
41
42
43
44
+
+
+
+



-
+

-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-














-
-
-
-
+
+
+
+
+
+


-
+

-
-
+
+
-







# 8859-6.TXT
# Date: 2015-12-02 21:44:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO 8859-6:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
#
#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-6:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-6 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-6 order.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.
#	0x30..0x39 remapped to the ASCII digits (U+0030..U+0039) instead
#	of the Arabic digits (U+0660..U+0669).
#   1.0 version: updates 0.1 version by adding mappings for all
#       control characters.
#       0x30..0x39 remapped to the ASCII digits (U+0030..U+0039) instead
#       of the Arabic digits (U+0660..U+0669).
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact <errata@unicode.org>
#	Please note that <errata@unicode.org> is an archival address;
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY

Changes to tools/encoding/iso8859-7.txt.





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
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
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
30
31
32
33
34
35
36
37
38
39
40
41

42
43


44
45

46
47
48
49
50
51
52
+
+
+
+

-
-
-
+
+
+

-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-




-
+


-
+
+














+
+
+
+
+
+

-
+

-
-
+
+
-







# 8859-7.TXT
# Date: 2015-12-02 21:47:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO 8859-7:1987 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Name:             ISO 8859-7:2003 to Unicode
#	Unicode version:  4.0
#	Table version:    3.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#	Date:             2003-Nov-12 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
#
#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO 8859-7:1987 characters map into Unicode.
#       ISO 8859-7:2003 characters map into Unicode.
#
#	ISO 8859-7:1987 is equivalent to ISO-IR-126, ELOT 928,
#	and ECMA 118.
#	and ECMA 118. ISO 8859-7:2003 adds two currency signs
#	and one other character not in the earlier standard.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO 8859-7 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO 8859-7 order.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.
#	Remap 0xA1 to U+2018 (instead of 0x02BD) to match text of 8859-7
#	Remap 0xA2 to U+2019 (instead of 0x02BC) to match text of 8859-7
#
#	2.0 version updates 1.0 version by adding mappings for the
#	three newly added characters 0xA4, 0xA5, 0xAA.
#
#   3.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact <errata@unicode.org>
#	Please note that <errata@unicode.org> is an archival address;
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
210
211
212
213
214
215
216


217
218
219
220

221
222
223
224
225
226
227
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224







+
+




+







0x9D	0x009D	#	<control>
0x9E	0x009E	#	<control>
0x9F	0x009F	#	<control>
0xA0	0x00A0	#	NO-BREAK SPACE
0xA1	0x2018	#	LEFT SINGLE QUOTATION MARK
0xA2	0x2019	#	RIGHT SINGLE QUOTATION MARK
0xA3	0x00A3	#	POUND SIGN
0xA4	0x20AC	#	EURO SIGN
0xA5	0x20AF	#	DRACHMA SIGN
0xA6	0x00A6	#	BROKEN BAR
0xA7	0x00A7	#	SECTION SIGN
0xA8	0x00A8	#	DIAERESIS
0xA9	0x00A9	#	COPYRIGHT SIGN
0xAA	0x037A	#	GREEK YPOGEGRAMMENI
0xAB	0x00AB	#	LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
0xAC	0x00AC	#	NOT SIGN
0xAD	0x00AD	#	SOFT HYPHEN
0xAF	0x2015	#	HORIZONTAL BAR
0xB0	0x00B0	#	DEGREE SIGN
0xB1	0x00B1	#	PLUS-MINUS SIGN
0xB2	0x00B2	#	SUPERSCRIPT TWO

Changes to tools/encoding/iso8859-8.txt.





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
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
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
30
31
32
33

34
35


36
37

38
39
40
41
42
43
44
+
+
+
+



-
+

-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
















-
+

+
+


-
+

-
-
+
+
-







# 8859-8.TXT
# Date: 2015-12-02 21:50:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-8:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.1
#	Table version:    2.0
#	Table format:     Format A
#	Date:             2000-Jan-03
#	Authors:          Ken Whistler <kenw@sybase.com>
#	Date:             2000-Jan-03 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
#
#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on optical media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-8:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-8 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-8 order.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.
#       1.1 version updates to the published 8859-8:1999, correcting
#   1.1 version updates to the published 8859-8:1999, correcting
#          the mapping of 0xAF and adding mappings for LRM and RLM.
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact <errata@unicode.org>
#	Please note that <errata@unicode.org> is an archival address;
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
263
264
265
266
267
268
269
270
252
253
254
255
256
257
258








-
0xF6	0x05E6	#	HEBREW LETTER TSADI
0xF7	0x05E7	#	HEBREW LETTER QOF
0xF8	0x05E8	#	HEBREW LETTER RESH
0xF9	0x05E9	#	HEBREW LETTER SHIN
0xFA	0x05EA	#	HEBREW LETTER TAV
0xFD	0x200E	#	LEFT-TO-RIGHT MARK
0xFE	0x200F	#	RIGHT-TO-LEFT MARK

Changes to tools/encoding/iso8859-9.txt.





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
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
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
30
31
32
33

34
35


36
37

38
39
40
41
42
43
44
+
+
+
+



-
+

-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
















-
-
+
+
+
+


-
+

-
-
+
+
-







# 8859-9.TXT
# Date: 2015-12-02 21:51:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             ISO/IEC 8859-9:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table version:    2.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Ken Whistler <ken@unicode.org>
#
#	Copyright (c) 1991-1999 Unicode, Inc.  All Rights reserved.
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on magnetic media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Unicode, Inc. hereby grants the right to freely use the information
#	supplied in this file in the creation of products supporting the
#	Unicode Standard, and to make copies of this file in any form for
#	internal or external distribution as long as this notice remains
#	attached.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       ISO/IEC 8859-9:1999 characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the ISO/IEC 8859-9 code (in hex as 0xXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#
#	The entries are in ISO/IEC 8859-9 order.
#
#	ISO/IEC 8859-9 is also equivalent to ISO-IR-148.
#
#	Version history
#	1.0 version updates 0.1 version by adding mappings for all
#	control characters.
#   1.0 version: updates 0.1 version by adding mappings for all
#       control characters.
#   2.0 version: updates to copyright notice and terms of use; no
#       changes to character mappings
#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#		http://www.unicode.org/Public/MAPPINGS/
#
#	Any comments or problems, contact <errata@unicode.org>
#	Please note that <errata@unicode.org> is an archival address;
#	Any comments or problems, contact us at:
#       http://www.unicode.org/reporting.html
#	notices will be checked, but do not expect an immediate response.
#
0x00	0x0000	#	NULL
0x01	0x0001	#	START OF HEADING
0x02	0x0002	#	START OF TEXT
0x03	0x0003	#	END OF TEXT
0x04	0x0004	#	END OF TRANSMISSION
0x05	0x0005	#	ENQUIRY
299
300
301
302
303
304
305
306
307
288
289
290
291
292
293
294
295









-
0xF9	0x00F9	#	LATIN SMALL LETTER U WITH GRAVE
0xFA	0x00FA	#	LATIN SMALL LETTER U WITH ACUTE
0xFB	0x00FB	#	LATIN SMALL LETTER U WITH CIRCUMFLEX
0xFC	0x00FC	#	LATIN SMALL LETTER U WITH DIAERESIS
0xFD	0x0131	#	LATIN SMALL LETTER DOTLESS I
0xFE	0x015F	#	LATIN SMALL LETTER S WITH CEDILLA
0xFF	0x00FF	#	LATIN SMALL LETTER Y WITH DIAERESIS


Changes to tools/encoding/jis0201.txt.





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
30
31
32
33
34
35
36
37
38
39
40





41


42


43





44
45
46
47
48
49
50
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


30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
+
+
+
+



-
+

-
+
-
-

-
+

-
-
-
-
-
-
-

-
-
-
+
+
+
+
+
-
-
+

-
-
-
-
-








-
-
+
+
+
+
+

+
+
-
+
+

+
+
+
+
+







# JIS0201.TXT
# Date: 2015-12-02 23:49:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             JIS X 0201 (1976) to Unicode 1.1 Table
#	Unicode version:  1.1
#	Table version:    0.9
#	Table version:    2.0
#	Table format:     Format A
#	Date:             8 March 1994
#	Date:             2011 October 14 (header updated: 2015 December 02)
#	Authors:          Glenn Adams <glenn@metis.com>
#                     John H. Jenkins <John_Jenkins@taligent.com>
#
#	Copyright (c) 1991-1994 Unicode, Inc.  All Rights reserved.
#	General notes:
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on magnetic media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Recipient is granted the right to make copies in any form for
#	internal distribution and to freely use the information supplied
#	in the creation of products supporting Unicode.  Unicode, Inc.
# This table contains one set of mappings from JIS X 0201 into Unicode.
# Note that these data are *possible* mappings only and may not be the
# same as those used by actual products, nor may they be the best suited
# for all uses.  For more information on the mappings between various code
# pages incorporating the repertoire of JIS X 0201 and Unicode, consult the
#	specifically excludes the right to re-distribute this file directly
#	to third parties or other organizations whether for profit or not.
# VENDORS mapping data.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#	single-byte JIS X 0201 characters map into Unicode 1.1
#	(ISO/IEC 10646:1-1993 UCS-2).
#
#	Format:  Three tab-separated columns
#		Column #1 is the shift JIS code (in hex as 0xXX)
#		Column #2 is the Unicode (in hex as 0xXXXX)
#		Column #3 the Unicode (ISO 10646) name (follows a comment sign)
#
#	The entries are in JIS order
#
#   These mappings are provisional, pending definition of
#       official mappings by Japanese standards bodies.
#  Revision History:
#
#    [v2.0, 2015 December 02]
#    updates to copyright notice and terms of use
#    no changes to character mappings
#
#    [v1.0, 2011 October 14]
#    Updated terms of use to current wording.
#	Any comments or problems, contact <John_Jenkins@taligent.com>
#    Updated contact information.
#    No changes to the mapping data.
#
#    [v0.9, 8 March 1994]
#    First release.
#
#  Use the Unicode reporting form <http://www.unicode.org/reporting.html>
#    for any questions or comments or to report errors in the data.
#
0x20	0x0020	# SPACE
0x21	0x0021	# EXCLAMATION MARK
0x22	0x0022	# QUOTATION MARK
0x23	0x0023	# NUMBER SIGN
0x24	0x0024	# DOLLAR SIGN
0x25	0x0025	# PERCENT SIGN

Changes to tools/encoding/jis0208.txt.





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
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
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
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
+
+
+
+



-
+

-
+
-
-

-
+

-
-
-
-
-
-
-

-
-
-
+
+
+
+
+
-
-
+

-
-
-
-






-
-
-
-
-
-
-
+
+
+
+
+
+
+












-
-
-
+
+
+
+
+

+
+
-
+
+

+
+
+
+
+







# JIS0208.TXT
# Date: 2015-12-02 23:50:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             JIS X 0208 (1990) to Unicode
#	Unicode version:  1.1
#	Table version:    0.9
#	Table version:    2.0
#	Table format:     Format A
#	Date:             8 March 1994
#	Date:             2011 October 14 (header updated: 2015 December 02)
#	Authors:          Glenn Adams <glenn@metis.com>
#                     John H. Jenkins <John_Jenkins@taligent.com>
#
#	Copyright (c) 1991-1994 Unicode, Inc.  All Rights reserved.
#	General notes:
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on magnetic media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Recipient is granted the right to make copies in any form for
#	internal distribution and to freely use the information supplied
#	in the creation of products supporting Unicode.  Unicode, Inc.
# This table contains one set of mappings from JIS X 0208 (1990) into Unicode.
# Note that these data are *possible* mappings only and may not be the
# same as those used by actual products, nor may they be the best suited
# for all uses.  For more information on the mappings between various code
# pages incorporating the repertoire of JIS X 0208 (1990) and Unicode, consult the
#	specifically excludes the right to re-distribute this file directly
#	to third parties or other organizations whether for profit or not.
# VENDORS mapping data.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       JIS X 0208 (1983) characters map into Unicode.
#
#	Format:  Four tab-separated columns
#		 Column #1 is the shift-JIS code (in hex)
#		 Column #2 is the JIS X 0208 code (in hex as 0xXXXX)
#		 Column #3 is the Unicode (in hex as 0xXXXX)
#		 Column #4 the Unicode name (follows a comment sign, '#')
#					The official names for Unicode characters U+4E00
#					to U+9FA5, inclusive, is "CJK UNIFIED IDEOGRAPH-XXXX",
#					where XXXX is the code point.  Including all these
#					names in this file increases its size substantially
#					and needlessly.  The token "<CJK>" is used for the
#					name of these characters.  If necessary, it can be
#					expanded algorithmically by a parser or editor.
#			The official names for Unicode characters U+4E00
#			to U+9FA5, inclusive, is "CJK UNIFIED IDEOGRAPH-XXXX",
#			where XXXX is the code point.  Including all these
#			names in this file increases its size substantially
#			and needlessly.  The token "<CJK>" is used for the
#			name of these characters.  If necessary, it can be
#			expanded algorithmically by a parser or editor.
#
#	The entries are in JIS X 0208 order
#
#	The following algorithms can be used to change the hex form
#		of JIS 0208 to other standard forms:
#
#		To change hex to EUC form, add 0x8080
#		To change hex to kuten form, first subtract 0x2020.  Then
#			the high and low bytes correspond to the ku and ten of
#			the kuten form.  For example, 0x2121 -> 0x0101 -> 0101;
#			0x7426 -> 0x5406 -> 8406
#
#   The kanji mappings are a normative part of ISO/IEC 10646.  The
#       non-kanji mappings are provisional, pending definition of
#       official mappings by Japanese standards bodies
#  Revision History:
#
#    [v2.0, 2015 December 02]
#    updates to copyright notice and terms of use
#    no changes to character mappings
#
#    [v1.0, 2011 October 14]
#    Updated terms of use to current wording.
#	Any comments or problems, contact <John_Jenkins@taligent.com>
#    Updated contact information.
#    No changes to the mapping data.
#
#    [v0.9, 8 March 1994]
#    First release.
#
#  Use the Unicode reporting form <http://www.unicode.org/reporting.html>
#    for any questions or comments or to report errors in the data.
#
0x8140	0x2121	0x3000	# IDEOGRAPHIC SPACE
0x8141	0x2122	0x3001	# IDEOGRAPHIC COMMA
0x8142	0x2123	0x3002	# IDEOGRAPHIC FULL STOP
0x8143	0x2124	0xFF0C	# FULLWIDTH COMMA
0x8144	0x2125	0xFF0E	# FULLWIDTH FULL STOP
0x8145	0x2126	0x30FB	# KATAKANA MIDDLE DOT

Changes to tools/encoding/jis0212.txt.





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
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
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
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
+
+
+
+



-
+

-
+
-
-

-
+

-
-
-
-
-
-
-

-
-
-
+
+
+
+
+
-
-
+

-
-
-
-





-
-
-
-
-
-
-
+
+
+
+
+
+
+












-
-
-
-
-
-















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







# JIS0212.TXT
# Date: 2015-12-02 23:51:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             JIS X 0212 (1990) to Unicode
#	Unicode version:  1.1
#	Table version:    0.9
#	Table version:    2.0
#	Table format:     Format A
#	Date:             8 March 1994
#	Date:             2011 October 14 (header updated: 2015 December 02)
#	Authors:          Glenn Adams <glenn@metis.com>
#                     John H. Jenkins <John_Jenkins@taligent.com>
#
#	Copyright (c) 1991-1994 Unicode, Inc.  All Rights reserved.
#	General notes:
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on magnetic media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Recipient is granted the right to make copies in any form for
#	internal distribution and to freely use the information supplied
#	in the creation of products supporting Unicode.  Unicode, Inc.
# This table contains one set of mappings from JIS X 0212 into Unicode.
# Note that these data are *possible* mappings only and may not be the
# same as those used by actual products, nor may they be the best suited
# for all uses.  For more information on the mappings between various code
# pages incorporating the repertoire of JIS X 0212 and Unicode, consult the
#	specifically excludes the right to re-distribute this file directly
#	to third parties or other organizations whether for profit or not.
# VENDORS mapping data.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       JIS X 0212 (1983) characters map into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the JIS X 0212 code (in hex as 0xXXXX)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#					The official names for Unicode characters U+4E00
#					to U+9FA5, inclusive, is "CJK UNIFIED IDEOGRAPH-XXXX",
#					where XXXX is the code point.  Including all these
#					names in this file increases its size substantially
#					and needlessly.  The token "<CJK>" is used for the
#					name of these characters.  If necessary, it can be
#					expanded algorithmically by a parser or editor.
#			The official names for Unicode characters U+4E00
#			to U+9FA5, inclusive, is "CJK UNIFIED IDEOGRAPH-XXXX",
#			where XXXX is the code point.  Including all these
#			names in this file increases its size substantially
#			and needlessly.  The token "<CJK>" is used for the
#			name of these characters.  If necessary, it can be
#			expanded algorithmically by a parser or editor.
#
#	The entries are in JIS X 0212 order
#
#	The following algorithms can be used to change the hex form
#		of JIS 0212 to other standard forms:
#
#		To change hex to EUC form, add 0x8080
#		To change hex to kuten form, first subtract 0x2020.  Then
#			the high and low bytes correspond to the ku and ten of
#			the kuten form.  For example, 0x2121 -> 0x0101 -> 0101;
#			0x6D63 -> 0x4D43 -> 7767
#
#   The kanji mappings are a normative part of ISO/IEC 10646.  The
#       non-kanji mappings are provisional, pending definition of
#       official mappings by Japanese standards bodies
#
#	Any comments or problems, contact <John_Jenkins@taligent.com>
#
#	Notes:
#
#	1. JIS X 0212 apparently unified the following two symbols
#	   into a single character at 0x2922:
#
#	   LATIN CAPITAL LETTER D WITH STROKE
#	   LATIN CAPITAL LETTER ETH
#
#	   However, JIS X 0212 maintains the distinction between
#	   the lowercase forms of these two elements at 0x2942 and 0x2943.
#	   Given the structre of these JIS encodings, it is clear that
#	   0x2922 and 0x2942 are intended to be a capital/small pair.
#	   Consequently, in the Unicode mapping, 0x2922 is treated as
#	   LATIN CAPITAL LETTER D WITH STROKE.
#
#  Revision History:
#
#    [v2.0, 2015 December 02]
#    updates to copyright notice and terms of use
#    no changes to character mappings
#
#    [v1.0, 2011 October 14]
#    Updated terms of use to current wording.
#    Updated contact information.
#    No changes to the mapping data.
#
#    [v0.9, 8 March 1994]
#    First release.
#
#  Use the Unicode reporting form <http://www.unicode.org/reporting.html>
#    for any questions or comments or to report errors in the data.
#
0x222F	0x02D8	# BREVE
0x2230	0x02C7	# CARON (Mandarin Chinese third tone)
0x2231	0x00B8	# CEDILLA
0x2232	0x02D9	# DOT ABOVE (Mandarin Chinese light tone)
0x2233	0x02DD	# DOUBLE ACUTE ACCENT
0x2234	0x00AF	# MACRON
0x2235	0x02DB	# OGONEK

Changes to tools/encoding/shiftjis.txt.





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
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
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
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
+
+
+
+



-
+

-
+
-
-

-
+

-
-
-
-
-
-
-

-
-
-
+
+
+
+
+
-
-
+

-
-
-
-





-
-
-
-
-
-
-
+
+
+
+
+
+
+










-
-
-
+
+
+
+
+

+
+
-
+
+

+
+
+
+
+







# SHIFTJIS.TXT
# Date: 2015-12-02 23:52:00 GMT [KW]
# © 2015 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
#	Name:             Shift-JIS to Unicode
#	Unicode version:  1.1
#	Table version:    0.9
#	Table version:    2.0
#	Table format:     Format A
#	Date:             8 March 1994
#	Date:             2011 October 14 (header updated: 2015 December 02)
#	Authors:          Glenn Adams <glenn@metis.com>
#                     John H. Jenkins <John_Jenkins@taligent.com>
#
#	Copyright (c) 1991-1994 Unicode, Inc.  All Rights reserved.
#	General notes:
#
#	This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
#	No claims are made as to fitness for any particular purpose.  No
#	warranties of any kind are expressed or implied.  The recipient
#	agrees to determine applicability of information provided.  If this
#	file has been provided on magnetic media by Unicode, Inc., the sole
#	remedy for any claim will be exchange of defective media within 90
#	days of receipt.
#
#	Recipient is granted the right to make copies in any form for
#	internal distribution and to freely use the information supplied
#	in the creation of products supporting Unicode.  Unicode, Inc.
# This table contains one set of mappings from Shift-JIS into Unicode.
# Note that these data are *possible* mappings only and may not be the
# same as those used by actual products, nor may they be the best suited
# for all uses.  For more information on the mappings between various code
# pages incorporating the repertoire of Shift-JIS and Unicode, consult the
#	specifically excludes the right to re-distribute this file directly
#	to third parties or other organizations whether for profit or not.
# VENDORS mapping data.
#
#	General notes:
#
#	This table contains the data the Unicode Consortium has on how
#       Shift-JIS (a combination of JIS 0201 and JIS 0208) maps into Unicode.
#
#	Format:  Three tab-separated columns
#		 Column #1 is the shift-JIS code (in hex)
#		 Column #2 is the Unicode (in hex as 0xXXXX)
#		 Column #3 the Unicode name (follows a comment sign, '#')
#					The official names for Unicode characters U+4E00
#					to U+9FA5, inclusive, is "CJK UNIFIED IDEOGRAPH-XXXX",
#					where XXXX is the code point.  Including all these
#					names in this file increases its size substantially
#					and needlessly.  The token "<CJK>" is used for the
#					name of these characters.  If necessary, it can be
#					expanded algorithmically by a parser or editor.
#			The official names for Unicode characters U+4E00
#			to U+9FA5, inclusive, is "CJK UNIFIED IDEOGRAPH-XXXX",
#			where XXXX is the code point.  Including all these
#			names in this file increases its size substantially
#			and needlessly.  The token "<CJK>" is used for the
#			name of these characters.  If necessary, it can be
#			expanded algorithmically by a parser or editor.
#
#	The entries are ordered by their Shift-JIS codes as follows:
#		Single-byte characters precede double-byte characters
#		The single-byte and double-byte blocks are in ascending
#		hexadecimal order
#	There is an alternative order some people might be preferred,
#		where all the entries are in order of the top (or only) byte.
#		This alternate order can be generated from the one given here
#		by a simple sort.
#
#   The kanji mappings are a normative part of ISO/IEC 10646.  The
#       non-kanji mappings are provisional, pending definition of
#       official mappings by Japanese standards bodies
#  Revision History:
#
#    [v2.0, 2015 December 02]
#    updates to copyright notice and terms of use
#    no changes to character mappings
#
#    [v1.0, 2011 October 14]
#    Updated terms of use to current wording.
#	Any comments or problems, contact <John_Jenkins@taligent.com>
#    Updated contact information.
#    No changes to the mapping data.
#
#    [v0.9, 8 March 1994]
#    First release.
#
#  Use the Unicode reporting form <http://www.unicode.org/reporting.html>
#    for any questions or comments or to report errors in the data.
#
0x20	0x0020	# SPACE
0x21	0x0021	# EXCLAMATION MARK
0x22	0x0022	# QUOTATION MARK
0x23	0x0023	# NUMBER SIGN
0x24	0x0024	# DOLLAR SIGN
0x25	0x0025	# PERCENT SIGN

Changes to tools/encoding/txt2enc.c.

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
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







-
+





-
+




-
+







	usage:
	fputs("usage: mkencoding [-e column] [-u column] [-f fallback] [-t type] [-s] [-m] file\n", stderr);
	fputs("    -e\tcolumn containing characters in encoding (default: 0)\n", stderr);
	fputs("    -u\tcolumn containing characters in Unicode (default: 1)\n", stderr);
	fputs("    -f\tfallback character (default: QUESTION MARK)\n", stderr);
	fputs("    -t\toverride implicit type with single, double, or multi\n", stderr);
	fputs("    -s\tsymbol+ascii encoding\n", stderr);
	fputs("    -m\tdon't implicitly include range 0080 to 00FF\n", stderr);
	fputs("    -m\tdon't implicitly include 007F\n", stderr);
	return 1;
    }

    fp = fopen(argv[argc - 1], "r");
    if (fp == NULL) {
        perror(argv[argc - 1]);
	perror(argv[argc - 1]);
	return 1;
    }

    for (i = 0; i < 256; i++) {
        toUnicode[i] = NULL;
	toUnicode[i] = NULL;
    }

    maxEnc = 0;
    width = 0;
    multiByte = 0;
    while (fgets(buf, sizeof(buf), fp) != NULL) {
	str = buf;
204
205
206
207
208
209
210
211
212
213


214
215
216
217
218
219
220
221
204
205
206
207
208
209
210



211
212

213
214
215
216
217
218
219







-
-
-
+
+
-







	    toUnicode[0] = (Rune *) malloc(256 * sizeof(Rune));
	    memset(toUnicode[0], 0, 256 * sizeof(Rune));
	}
	for (i = 0; i < 0x20; i++) {
	    toUnicode[0][i] = i;
	}
	if (fixmissing) {
	    for (i = 0x7F; i < 0xA0; i++) {
		if (toUnicode[i] == NULL && toUnicode[0][i] == 0) {
		    toUnicode[0][i] = i;
	    if (toUnicode[0x7F] == NULL && toUnicode[0][0x7F] == 0) {
		toUnicode[0][0x7F] = 0x7F;
		}
	    }
	}
    }

    printf("# Encoding file: %s, %s-byte\n", argv[argc - 1], typeString[type]);

    if (fallbackChar == '\0') {
238
239
240
241
242
243
244
245
246
247
248




249
250
251
236
237
238
239
240
241
242




243
244
245
246
247
248
249







-
-
-
-
+
+
+
+



		    putchar('\n');
		}
	    }
	}
    }

    for (hi = 0; hi < 256; hi++) {
        if (toUnicode[hi] != NULL) {
            free(toUnicode[hi]);
            toUnicode[hi] = NULL;
        }
	if (toUnicode[hi] != NULL) {
	    free(toUnicode[hi]);
	    toUnicode[hi] = NULL;
	}
    }
    return 0;
}

Deleted tools/eolFix.tcl.

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
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
















































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
## Super aggressive EOL-fixer!
##
##  Will even understand screwed up ones like CRCRLF.
##  (found in bad CVS repositories, caused by spacey developers
##   abusing CVS)
##
##  davygrvy@pobox.com    3:41 PM 10/12/2001
##

package provide EOL-fix 1.1

namespace eval ::EOL {
    variable outMode crlf
}

proc EOL::fix {filename {newfilename {}}} {
    variable outMode

    if {![file exists $filename]} {
	return
    }
    puts "EOL Fixing: $filename"

    file rename ${filename} ${filename}.o
    set fhnd [open ${filename}.o r]

    if {$newfilename ne ""} {
	set newfhnd [open ${newfilename} w]
    } else {
	set newfhnd [open ${filename} w]
    }

    fconfigure $newfhnd -translation [list auto $outMode]
    seek $fhnd 0 end
    set theEnd [tell $fhnd]
    seek $fhnd 0 start

    fconfigure $fhnd -translation binary -buffersize $theEnd
    set rawFile [read $fhnd $theEnd]
    close $fhnd

    regsub -all {(\r)|(\r){1,2}(\n)} $rawFile "\n" rawFile

    set lineList [split $rawFile \n]

    foreach line $lineList {
	puts $newfhnd $line
    }

    close $newfhnd
    file delete ${filename}.o
}

proc EOL::fixall {args} {
    if {[llength $args] == 0} {
	puts stderr "no files to fix"
	exit 1
    } else {
	set cmd [lreplace $args -1 -1 glob -nocomplain]
    }

    foreach f [eval $cmd] {
	if {[file isfile $f]} {fix $f}
    }
}

if {$tcl_interactive == 0 && $argc > 0} {
    if {[string index [lindex $argv 0] 0] eq "-"} {
	switch -- [lindex $argv 0] {
	    -cr   {set ::EOL::outMode cr}
	    -crlf {set ::EOL::outMode crlf}
	    -lf   {set ::EOL::outMode lf}
	    default {puts stderr "improper mode switch"; exit 1}
        }
	set argv [lrange $argv 1 end]
    }
    eval EOL::fixall $argv
} else {
    return
}

Changes to tools/findBadExternals.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







# findBadExternals.tcl --
#
#	This script scans the Tcl load library for exported symbols
#	that do not begin with 'Tcl' or 'tcl'.  It reports them on the
#	standard output.  It is used to make sure that the library does
#	not inadvertently export externals that may be in conflict with
#	other code.
#
# Usage:
#
#	tclsh findBadExternals.tcl /path/to/tclXX.so-or-.dll
#
# Copyright (c) 2005 George Peter Staplin and Kevin Kenny
# Copyright © 2005 George Peter Staplin and Kevin Kenny
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#----------------------------------------------------------------------

proc main {argc argv} {

Added tools/findDocWords.tcl.





















































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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# findDocWords.tcl --
#
# This script attempts to find all non-dictionary words in the Tcl or Tk
# documentation tree. It handles the fairly common compoundWord trick our
# docs use, and isn't confused by nroff formatting directives, so it isn't
# just a standard spell check.
#
# Arguments:
#    1: Directory to look for man source files in.
#    2: Path to a plain text dictionary. Try /usr/share/dict/words on Linux.
#
# Copyright © 2024 Donal K Fellows.
# See "license.terms" for the license.

lassign $argv dir dictionary

set f [open $dictionary]
while {[gets $f line] > 0} {
    dict set realWord [string tolower $line] yes
}
close $f
puts "loaded [dict size $realWord] words from dictionary"

set files [glob -directory $dir {*.[13n]}]
set found {}

proc identifyWords {fragment filename} {
    global realWord found
    foreach frag [split [string map {\\fB "" \\fR "" \\fI "" \\fP "" \\0 _} $fragment] _] {
	if {[string is entier $frag]} continue
	set frag [string trim $frag "\\0123456789"]
	if {$frag eq ""} continue
	foreach word [regexp -all -inline {^[a-z]+|[A-Z][a-z]*} $frag] {
	    set word [string tolower $word]
	    if {![dict exists $realWord $word]} {
		dict lappend found $word $filename
	    }
	}
    }
}

foreach fn $files {
    set f [open $fn]
    foreach word [regexp -all -inline {[\\\w]+} [read $f]] {
	identifyWords $word $fn
    }
    close $f
}
set len [tcl::mathfunc::max {*}[lmap word [dict keys $found] {string length $word}]]
foreach word [lsort [dict keys $found]] {
    puts [format "%-${len}s: %s" $word [lindex [dict get $found $word] 0]]
}

Changes to tools/genStubs.tcl.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15






-
-
+
+







# genStubs.tcl --
#
#	This script generates a set of stub files for a given
#	interface.
#
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
# Copyright © 1998-1999 Scriptics Corporation.
# Copyright © 2007 Daniel A. Steffen <das@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

namespace eval genStubs {
    # libraryName --
    #
253
254
255
256
257
258
259

260
261

262
263
264
265
266
267
268
253
254
255
256
257
258
259
260
261

262
263
264
265
266
267
268
269







+

-
+








proc genStubs::rewriteFile {file text} {
    if {![file exists $file]} {
	puts stderr "Cannot find file: $file"
	return
    }
    set in [open ${file} r]
    fconfigure $in -eofchar "\x1A {}" -encoding utf-8
    set out [open ${file}.new w]
    fconfigure $out -translation lf
    fconfigure $out -translation lf -encoding utf-8

    while {![eof $in]} {
	set line [gets $in]
	if {[string match "*!BEGIN!*" $line]} {
	    break
	}
	puts $out $line
817
818
819
820
821
822
823
824

825
826

827
828
829
830
831
832
833
818
819
820
821
822
823
824

825
826

827
828
829
830
831
832
833
834







-
+

-
+







			# backwards compatibility, generate a dummy stubs entry
			# before every aqua entry (note that this breaks the
			# correspondence between emitted entry number and
			# actual position of the entry in the stubs table, e.g.
			# TkIntStubs entry 113 for aqua is in fact at position
			# 114 in the table, entry 114 at position 116 etc).
			eval {append temp} $skipString
			set temp "[string range $temp 0 end-1] /*\
			set temp "# if TCL_MAJOR_VERSION < 9\n[string range $temp 0 end-1] /*\
				Dummy entry for stubs table backwards\
				compatibility */\n"
				compatibility */\n# endif /* TCL_MAJOR_VERSION < 9 */\n"
		    }
		    if {$slot($plat)} {
			append temp [$slotProc $name $stubs($name,$plat,$i) $i]
		    } elseif {$onAll} {
			eval {append temp} $skipString
		    }
		}
1096
1097
1098
1099
1100
1101
1102
1103

1104
1105
1106
1107
1108
1109
1110
1097
1098
1099
1100
1101
1102
1103

1104
1105
1106
1107
1108
1109
1110
1111







-
+







	    append text $sep "&${sub}Stubs"
	    set sep ",\n    "
	}
	append text "\n\};\n"
    }
    foreach intf [array names interfaces] {
	if {[info exists hooks($intf)]} {
	    if {[lsearch -exact $hooks($intf) $name] >= 0} {
	    if {$name in $hooks($intf)} {
		set root 0
		break
	    }
	}
    }

    append text "\n"
1187
1188
1189
1190
1191
1192
1193
1194

1195
1196
1197
1198
1199
1200
1201
1188
1189
1190
1191
1192
1193
1194

1195
1196
1197
1198
1199
1200
1201
1202







-
+







	puts stderr "usage: $argv0 outDir declFile ?declFile...?"
	exit 1
    }

    set outDir [lindex $argv 0]

    foreach file [lrange $argv 1 end] {
	source $file
	source -encoding utf-8 $file
    }

    foreach name [lsort [array names interfaces]] {
	puts "Emitting $name"
	emitHeader $name
    }

1209
1210
1211
1212
1213
1214
1215
1216

1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1210
1211
1212
1213
1214
1215
1216

1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227







-
+










# Arguments:
#	valueList	A list containing the values to be assigned.
#	args		The list of variables to be assigned.
#
# Results:
#	Returns any values that were not assigned to variables.

if {[string length [namespace which lassign]] == 0} {
if {[namespace which lassign] ne ""} {
    proc lassign {valueList args} {
	if {[llength $args] == 0} {
	    error "wrong # args: should be \"lassign list varName ?varName ...?\""
	}
	uplevel [list foreach $args $valueList {break}]
	return [lrange $valueList [llength $args] end]
    }
}

genStubs::init

Changes to tools/index.tcl.

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
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






-
+









-
+



-
-
+
+







# index.tcl --
#
# This file defines procedures that are used during the first pass of
# the man page conversion.  It is used to extract information used to
# generate a table of contents and a keyword list.
#
# Copyright (c) 1996 by Sun Microsystems, Inc.
# Copyright © 1996 Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

# Global variables used by these scripts:
#
# state -	state variable that controls action of text proc.
#
# topics -	array indexed by (package,section,topic) with value
# 		of topic ID.
#		of topic ID.
#
# keywords -	array indexed by keyword string with value of topic ID.
#
# curID - 	current topic ID, starts at 0 and is incremented for
# 		each new topic file.
# curID -	current topic ID, starts at 0 and is incremented for
#		each new topic file.
#
# curPkg -	current package name (e.g. Tcl).
#
# curSect -	current section title (e.g. "Tcl Built-In Commands").
#

# getPackages --

Changes to tools/installData.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
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







-
+



















-
+







-
+







#
#	This file installs a hierarchy of data found in the directory
#	specified by its first argument into the directory specified
#	by its second.
#
#----------------------------------------------------------------------
#
# Copyright (c) 2004 by Kevin B. Kenny.  All rights reserved.
# Copyright © 2004 Kevin B. Kenny.  All rights reserved.
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#----------------------------------------------------------------------

proc copyDir {d1 d2} {

    puts [format {%*sCreating %s} [expr {4 * [info level]}] {} \
	      [file tail $d2]]

    file delete -force -- $d2
    file mkdir $d2

    foreach ftail [glob -directory $d1 -nocomplain -tails *] {
	set f [file join $d1 $ftail]
	if {[file isdirectory $f] && [string compare CVS $ftail]} {
	    copyDir $f [file join $d2 $ftail]
	} elseif {[file isfile $f]} {
	    file copy -force $f [file join $d2 $ftail]
	    if {$::tcl_platform(platform) eq {unix}} {
		file attributes [file join $d2 $ftail] -permissions 0644
		file attributes [file join $d2 $ftail] -permissions 0o644
	    } else {
		file attributes [file join $d2 $ftail] -readonly 1
	    }
	}
    }

    if {$::tcl_platform(platform) eq {unix}} {
	file attributes $d2 -permissions 0755
	file attributes $d2 -permissions 0o755
    } else {
	file attributes $d2 -readonly 1
    }

}

copyDir [file normalize [lindex $argv 0]] [file normalize [lindex $argv 1]]

Changes to tools/installVfs.tcl.

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
30
31
32
33
34
35
36
37
38












39
40
41
42
43
44
45
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45












-
+













-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+







#!/bin/sh
#\
exec tclsh "$0" ${1+"$@"}

#----------------------------------------------------------------------
#
# installVfs.tcl --
#
#        This file wraps the /library file system around a binary
#
#----------------------------------------------------------------------
#
# Copyright (c) 2018 by Sean Woods.  All rights reserved.
# Copyright © 2018 Sean Woods.  All rights reserved.
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#----------------------------------------------------------------------

proc mapDir {resultvar prefix filepath} {
    upvar 1 $resultvar result
    if {![info exists result]} {
      set result {}
    }
    set queue [list $prefix $filepath]
    while {[llength $queue]} {
      set queue [lassign $queue qprefix qpath]
      foreach ftail [glob -directory $qpath -nocomplain -tails *] {
          set f [file join $qpath $ftail]
          if {[file isdirectory $f]} {
            if {$ftail eq "CVS"} continue
            lappend queue [file join $qprefix $ftail] $f
          } elseif {[file isfile $f]} {
              if {$ftail eq "pkgIndex.tcl"} continue
              if {$ftail eq "manifest.txt"} {
                lappend result $f [file join $qprefix pkgIndex.tcl]
              } else {
                lappend result $f [file join $qprefix $ftail]
              }
          }
	  set f [file join $qpath $ftail]
	  if {[file isdirectory $f]} {
	    if {$ftail eq "CVS"} continue
	    lappend queue [file join $qprefix $ftail] $f
	  } elseif {[file isfile $f]} {
	      if {$ftail eq "pkgIndex.tcl"} continue
	      if {$ftail eq "manifest.txt"} {
		lappend result $f [file join $qprefix pkgIndex.tcl]
	      } else {
		lappend result $f [file join $qprefix $ftail]
	      }
	  }
       }
    }
}
if {[llength $argv]<4} {
  error "Usage: [file tail [info script]] IMG_OUTPUT IMG_INPUT PREFIX FILE_SYSTEM ?PREFIX FILE_SYSTEM?..."
}

Changes to tools/loadICU.tcl.

18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32







-
+







#	None.
#
# Side effects:
#	Creates the message catalogs.
#
#----------------------------------------------------------------------
#
# Copyright (c) 2004 by Kevin B. Kenny.  All rights reserved.
# Copyright © 2004 Kevin B. Kenny.  All rights reserved.
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#----------------------------------------------------------------------

puts stdout "TODO: output in UTF-8 in stead of using \\uhhhh sequences"
exit; # Remove those two lines after modifying this tool.

Changes to tools/makeHeader.tcl.

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
30
31
32
33
34
35
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
30
31
32
33
34
35





-
+




-
+
















-
+







# makeHeader.tcl --
#
#	This script generates embeddable C source (in a .h file) from a .tcl
#	script.
#
# Copyright (c) 2018 Donal K. Fellows
# Copyright © 2018 Donal K. Fellows
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require Tcl 8.6
package require Tcl 8.6-

namespace eval makeHeader {

    ####################################################################
    #
    # mapSpecial --
    #	Transform a single line so that it is able to be put in a C string.
    #
    proc mapSpecial {str} {
	# All Tcl metacharacters and key C backslash sequences
	set MAP {
	    \" \\\\\" \\ \\\\\\\\ $ \\$ [ \\[ ] \\] ' \\\\' ? \\\\?
	    \a \\\\a \b \\\\b \f \\\\f \n \\\\n \r \\\\r \t \\\\t \v \\\\v
	}
	set XFORM {[format \\\\\\\\u%04x {*}[scan & %c]]}

	subst [regsub -all {[^\u0020-\u007e]} [string map $MAP $str] $XFORM]
	subst [regsub -all {[^\x20-\x7E]} [string map $MAP $str] $XFORM]
    }

    ####################################################################
    #
    # compactLeadingSpaces --
    #	Converts the leading whitespace on a line into a more compact form.
    #
104
105
106
107
108
109
110

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







+







    #
    # updateTemplateFile --
    #	Rewrites a template file with the lines of the given script.
    #
    proc updateTemplateFile {headerFile scriptLines} {
	set f [open $headerFile "r+"]
	try {
	    chan configure $f -translation {auto lf}
	    set content [split [chan read -nonewline $f] "\n"]
	    updateTemplate content [stripSurround $scriptLines]
	    chan seek $f 0
	    chan puts $f [join $content \n]
	    chan truncate $f
	} trap BAD msg {
	    # Add the filename to the message

Changes to tools/makeTestCases.tcl.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







# TODO - When integrating this with the Core, path names will need to be
# swizzled here.

package require msgcat
set d [file dirname [file dirname [info script]]]
puts "getting transition data from [file join $d library tzdata America Detroit]"
source [file join $d library/tzdata/America/Detroit]
source -encoding utf-8 [file join $d library/tzdata/America/Detroit]

namespace eval ::tcl::clock {
    ::msgcat::mcmset en_US_roman {
	LOCALE_ERAS {
	    {-62164627200 {} 0}
	    {-59008867200 c 100}
	    {-55853107200 cc 200}
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
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







-
+












-
+







proc testcases2 { f2 } {

    listYears startOfYear

    # Define the roman numerals

    set roman {
 	? i ii iii iv v vi vii viii ix
	? i ii iii iv v vi vii viii ix
	x xi xii xiii xiv xv xvi xvii xviii xix
	xx xxi xxii xxiii xxiv xxv xxvi xxvii xxviii xxix
	xxx xxxi xxxii xxxiii xxxiv xxxv xxxvi xxxvii xxxviii xxxix
	xl xli xlii xliii xliv xlv xlvi xlvii xlviii xlix
	l li lii liii liv lv lvi lvii lviii lix
	lx lxi lxii lxiii lxiv lxv lxvi lxvii lxviii lxix
	lxx lxxi lxxii lxxiii lxxiv lxxv lxxvi lxxvii lxxviii lxxix
	lxxx lxxxi lxxxii lxxxiii lxxxiv lxxxv lxxxvi lxxxvii lxxxviii lxxxix
	xc xci xcii xciii xciv xcv xcvi xcvii xcviii xcix
	c
    }
    set romanc {
 	? c cc ccc cd d dc dcc dccc cm
	? c cc ccc cd d dc dcc dccc cm
	m mc mcc mccc mcd md mdc mdcc mdccc mcm
	mm mmc mmcc mmccc mmcd mmd mmdc mmdcc mmdccc mmcm
	mmm mmmc mmmcc mmmccc mmmcd mmmd mmmdc mmmdcc mmmdccc mmmcm
    }

    # Names of the months

469
470
471
472
473
474
475
476
477
478
479
480





481
482
483
484
485
486
487
469
470
471
472
473
474
475





476
477
478
479
480
481
482
483
484
485
486
487







-
-
-
-
-
+
+
+
+
+








    set longdays {Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday}
    set shortdays {Sun Mon Tue Wed Thu Fri Sat Sun}

    puts $f2 "test clock-3.[incr case] {ISO week-based calendar [format %04d-W%02d-%d $G $V $u]} {"
    puts $f2 "    clock format $secs -format {%a %A %g %G %u %U %V %w %W} -gmt true; \# $G-W[format %02d $V]-$u"
    puts $f2 "} {[lindex $shortdays $u] [lindex $longdays $u]\
             [format %02d [expr { $G % 100 }]] $G\
             $u\
             [clock format $secs -format %U -gmt true]\
             [format %02d $V] [expr { $u % 7 }]\
             [clock format $secs -format %W -gmt true]}"
	     [format %02d [expr { $G % 100 }]] $G\
	     $u\
	     [clock format $secs -format %U -gmt true]\
	     [format %02d $V] [expr { $u % 7 }]\
	     [clock format $secs -format %W -gmt true]}"

}

#----------------------------------------------------------------------
#
# testcases4 --
#

Deleted tools/man2help.tcl.

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
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













































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# man2help.tcl --
#
# This file defines procedures that work in conjunction with the
# man2tcl program to generate a Windows help file from Tcl manual
# entries.
#
# Copyright (c) 1996 by Sun Microsystems, Inc.

#
# PASS 1
#

set man2tclprog [file join [file dirname [info script]] \
	man2tcl[file extension [info nameofexecutable]]]

proc generateContents {basename version files} {
    global curID topics
    set curID 0
    foreach f $files {
	puts "Pass 1 -- $f"
	flush stdout
	doFile $f
    }
    set fd [open [file join [file dirname [info script]] $basename$version.cnt] w]
    fconfigure $fd -translation crlf
    puts $fd ":Base $basename$version.hlp"
    foreach package [getPackages] {
	foreach section [getSections $package] {
            if {![info exists lastSection]} {
	        set lastSection {}
            }
            if {[string compare $lastSection $section]} {
	    puts $fd "1 $section"
            }
            set lastSection $section
	    set lastTopic {}
	    foreach topic [getTopics $package $section] {
		if {[string compare $lastTopic $topic]} {
		    set id $topics($package,$section,$topic)
		    puts $fd "2 $topic=$id"
		    set lastTopic $topic
		}
	    }
	}
    }
    close $fd
}


#
# PASS 2
#

proc generateHelp {basename files} {
    global curID topics keywords file id_keywords
    set curID 0

    foreach key [array names keywords] {
	foreach id $keywords($key) {
	    lappend id_keywords($id) $key
	}
    }

    set file [open [file join [file dirname [info script]] $basename.rtf] w]
    fconfigure $file -translation crlf
    puts $file "\{\\rtf1\\ansi \\deff0\\deflang1033\{\\fonttbl\{\\f0\\froman\\fcharset0\\fprq2 Times New Roman\;\}\{\\f1\\fmodern\\fcharset0\\fprq1 Courier New\;\}\}"
    foreach f $files {
	puts "Pass 2 -- $f"
	flush stdout
	initGlobals
	doFile $f
	pageBreak
    }
    puts $file "\}"
    close $file
}

# doFile --
#
# Given a file as argument, translate the file to a tcl script and
# evaluate it.
#
# Arguments:
# file -		Name of file to translate.

proc doFile {file} {
    global man2tclprog
    if {[catch {eval [exec $man2tclprog [glob $file]]} msg]} {
	global errorInfo
	puts stderr $msg
	puts "in"
	puts $errorInfo
	exit 1
    }
}

# doDir --
#
# Given a directory as argument, translate all the man pages in
# that directory.
#
# Arguments:
# dir -			Name of the directory.

proc doDir dir {
    puts "Generating man pages for $dir..."
    foreach f [lsort [glob -directory $dir "*.\[13n\]"]] {
	doFile $f
    }
}

# process command line arguments

if {$argc < 3} {
    puts stderr "usage: $argv0 \[options\] projectName version manFiles..."
    exit 1
}

set arg 0

if {![string compare [lindex $argv $arg] "-bitmap"]} {
    set bitmap [lindex $argv [incr arg]]
    incr arg
}
set baseName [lindex $argv $arg]
set version [lindex $argv [incr arg]]
set files {}
foreach i [lrange $argv [incr arg] end] {
    set i [file join $i]
    if {[file isdir $i]} {
	foreach f [lsort [glob -directory $i "*.\[13n\]"]] {
	    lappend files $f
	}
    } elseif {[file exists $i]} {
	lappend files $i
    }
}
source [file join [file dirname [info script]] index.tcl]
generateContents $baseName $version $files
source [file join [file dirname [info script]] man2help2.tcl]
generateHelp $baseName $files

Deleted tools/man2help2.tcl.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# man2help2.tcl --
#
# This file defines procedures that are used during the second pass of
# the man page conversion.  It converts the man format input to rtf
# form suitable for use by the Windows help compiler.
#
# Copyright (c) 1996 by Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

# Global variables used by these scripts:
#
# state -	state variable that controls action of text proc.
#
# topics -	array indexed by (package,section,topic) with value
# 		of topic ID.
#
# keywords -	array indexed by keyword string with value of topic ID.
#
# curID - 	current topic ID, starts at 0 and is incremented for
# 		each new topic file.
#
# curPkg -	current package name (e.g. Tcl).
#
# curSect -	current section title (e.g. "Tcl Built-In Commands").
#

# initGlobals --
#
# This procedure is invoked to set the initial values of all of the
# global variables, before processing a man page.
#
# Arguments:
# None.

proc initGlobals {} {
    uplevel \#0 unset state
    global state chars

    set state(paragraphPending) 0
    set state(breakPending) 0
    set state(firstIndent) 0
    set state(leftIndent) 0

    set state(inTP) 0
    set state(paragraph) 0
    set state(textState) 0
    set state(curFont) ""
    set state(startCode) "{\\b "
    set state(startEmphasis) "{\\i "
    set state(endCode) "}"
    set state(endEmphasis) "}"
    set state(noFill) 0
    set state(charCnt) 0
    set state(offset) [getTwips 0.5i]
    set state(leftMargin) [getTwips 0.5i]
    set state(nestingLevel) 0
    set state(intl) 0
    set state(sb) 0
    setTabs 0.5i

# set up international character table

    array set chars {
	o^ F4
    }
}


# beginFont --
#
# Arranges for future text to use a special font, rather than
# the default paragraph font.
#
# Arguments:
# font -		Name of new font to use.

proc beginFont {font} {
    global file state

    textSetup
    if {[string equal $state(curFont) $font]} {
	return
    }
    endFont
    puts -nonewline $file $state(start$font)
    set state(curFont) $font
}


# endFont --
#
# Reverts to the default font for the paragraph type.
#
# Arguments:
# None.

proc endFont {} {
    global state file

    if {[string compare $state(curFont) ""]} {
	puts -nonewline $file $state(end$state(curFont))
	set state(curFont) ""
    }
}


# textSetup --
#
# This procedure is called the first time that text is output for a
# paragraph.  It outputs the header information for the paragraph.
#
# Arguments:
# None.

proc textSetup {} {
    global file state

    if $state(breakPending) {
	puts $file "\\line"
    }
    if $state(paragraphPending) {
	puts $file [format "\\par\n\\pard\\fi%.0f\\li%.0f" \
			$state(firstIndent) $state(leftIndent)]
	foreach tab $state(tabs) {
	    puts $file [format "\\tx%.0f" $tab]
	}
	set state(tabs) {}
	if {$state(sb)} {
	    puts $file "\\sb$state(sb)"
	    set state(sb) 0
	}
    }
    set state(breakPending) 0
    set state(paragraphPending) 0
}


# text --
#
# This procedure adds text to the current state(paragraph).  If this is
# the first text in the state(paragraph) then header information for the
# state(paragraph) is output before the text.
#
# Arguments:
# string -		Text to output in the state(paragraph).

proc text {string} {
    global file state chars

    textSetup
    set string [string map [list \
	    "\\"	"\\\\" \
	    "\{"	"\\\{" \
	    "\}"	"\\\}" \
	    "\t"	{\tab } \
	    ''		"\\rdblquote " \
	    ``		"\\ldblquote " \
	    "\xB7"	"\\bullet " \
	    ] $string]

    # Check if this is the beginning of an international character string.
    # If so, look up the sequence in the chars table and substitute the
    # appropriate hex value.

    if {$state(intl)} {
	if {[regexp {^'([^']*)'} $string dummy ch]} {
	    if {[info exists chars($ch)]} {
		regsub {^'[^']*'} $string "\\\\'$chars($ch)" string
	    } else {
		puts stderr "Unknown international character '$ch'"
	    }
	}
	set state(intl) 0
    }

    switch $state(textState) {
	REF {
	    if {$state(inTP) == 0} {
		set string [insertRef $string]
	    }
	}
	SEE {
	    global topics curPkg curSect
	    foreach i [split $string] {
		if {![regexp -nocase {^[a-z_0-9]+} [string trim $i] i ]} {
		    continue
		}
		if {![catch {set ref $topics($curPkg,$curSect,$i)} ]} {
		    regsub $i $string [link $i $ref] string
		}
	    }
	}
	KEY {
	    return
	}
    }
    puts -nonewline $file "$string"
}



# insertRef --
#
# This procedure looks for a string in the cross reference table and
# generates a hot-link to the appropriate topic.  Tries to find the
# nearest reference in the manual.
#
# Arguments:
# string -		Text to output in the state(paragraph).

proc insertRef {string} {
    global NAME_file curPkg curSect topics curID
    set path {}
    set string [string trim $string]
    set ref {}
    if {[info exists topics($curPkg,$curSect,$string)]} {
	set ref $topics($curPkg,$curSect,$string)
    } else {
	set sites [array names topics "$curPkg,*,$string"]
	set count [llength $sites]
	if {$count > 0} {
	    set ref $topics([lindex $sites 0])
	} else {
	    set sites [array names topics "*,*,$string"]
	    set count [llength $sites]
	    if {$count > 0} {
		set ref $topics([lindex $sites 0])
	    }
	}
    }

    if {($ref != "") && ($ref != $curID)} {
	set string [link $string $ref]
    }
    return $string
}



# macro --
#
# This procedure is invoked to process macro invocations that start
# with "." (instead of ').
#
# Arguments:
# name -		The name of the macro (without the ".").
# args -		Any additional arguments to the macro.

proc macro {name args} {
    global state file
    switch $name {
	AP {
	    if {[llength $args] != 3 && [llength $args] != 2} {
		puts stderr "Bad .AP macro: .$name [join $args " "]"
	    }
	    newPara 3.75i -3.75i
	    setTabs {1.25i 2.5i 3.75i}
	    font B
	    text [lindex $args 0]
	    tab
	    font I
	    text [lindex $args 1]
	    tab
	    font R
	    if {[llength $args] == 3} {
		text "([lindex $args 2])"
	    }
	    tab
	}
	AS {
	    # next page and previous page
	}
	br {
	    lineBreak
	}
	BS {}
	BE {}
	CE {
	    puts -nonewline $::file "\\f0\\fs20 "
	    set state(noFill) 0
	    set state(breakPending) 0
	    newPara ""
	    set state(leftIndent) [expr {$state(leftIndent) - $state(offset)}]
	    set state(sb) 80
	}
	CS {
	    # code section
	    set state(noFill) 1
	    newPara ""
	    set state(leftIndent) [expr {$state(leftIndent) + $state(offset)}]
	    set state(sb) 80
	    puts -nonewline $::file "\\f1\\fs18 "
	}
	DE {
	    set state(noFill) 0
	    decrNestingLevel
	    newPara 0i
	}
	DS {
	    set state(noFill) 1
	    incrNestingLevel
	    newPara 0i
	}
	fi {
	    set state(noFill) 0
	}
	IP {
	    IPmacro $args
	}
	LP {
	    newPara 0i
	    set state(sb) 80
	}
	ne {
	}
	nf {
	    set state(noFill) 1
	}
	OP {
	    if {[llength $args] != 3} {
		puts stderr "Bad .OP macro: .$name [join $args " "]"
	    }
	    set state(nestingLevel) 0
	    newPara 0i
	    set state(sb) 120
	    setTabs 4c
	    text "Command-Line Name:"
	    tab
	    font B
	    set x [lindex $args 0]
	    regsub -all {\\-} $x - x
	    text $x
	    lineBreak
	    font R
	    text "Database Name:"
	    tab
	    font B
	    text [lindex $args 1]
	    lineBreak
	    font R
	    text "Database Class:"
	    tab
	    font B
	    text [lindex $args 2]
	    font R
	    set state(inTP) 0
	    newPara 0.5i
	    set state(sb) 80
	}
	PP {
	    newPara 0i
	    set state(sb) 120
	}
	RE {
	    decrNestingLevel
	}
	RS {
	    incrNestingLevel
	}
	SE {
	    font R
	    set state(noFill) 0
	    set state(nestingLevel) 0
	    newPara 0i
	    text "See the "
	    font B
	    set temp $state(textState)
	    set state(textState) REF
	    text options
	    set state(textState) $temp
	    font R
	    text " manual entry for detailed descriptions of the above options."
	}
	SH {
	    SHmacro $args
	}
	SS {
	    SHmacro $args subsection
	}
	SO {
	    SHmacro "STANDARD OPTIONS"
	    set state(nestingLevel) 0
	    newPara 0i
	    setTabs {4c 8c 12c}
	    font B
	    set state(noFill) 1
	}
	so {
	    if {$args ne "man.macros"} {
		puts stderr "Unknown macro: .$name [join $args " "]"
	    }
	}
	sp {					;# needs work
	    if {$args eq ""} {
		set count 1
	    } else {
		set count [lindex $args 0]
	    }
	    while {$count > 0} {
		lineBreak
		incr count -1
	    }
	}
	ta {
	    setTabs $args
	}
	TH {
	    THmacro $args
	}
	TP {
	    TPmacro $args
	}
	UL {					;# underline
	    puts -nonewline $file "{\\ul "
	    text [lindex $args 0]
	    puts -nonewline $file "}"
	    if {[llength $args] == 2} {
		text [lindex $args 1]
	    }
	}
	VE {}
	VS {}
	QW {
	    formattedText "``[lindex $args 0]''[lindex $args 1] "
	}
	MT {
	    text "``'' "
	}
	PQ {
	    formattedText \
		"(``[lindex $args 0]''[lindex $args 1])[lindex $args 2] "
	}
	QR {
	    formattedText "``[lindex $args 0]"
	    dash
	    formattedText "[lindex $args 1]''[lindex $args 2] "
	}
	default {
	    puts stderr "Unknown macro: .$name [join $args " "]"
	}
    }
}


# link --
#
# This procedure returns the string for  a hot link to a different
# context location.
#
# Arguments:
# label -		String to display in hot-spot.
# id -			Context string to jump to.

proc link {label id} {
    return "{\\uldb $label}{\\v $id}"
}


# font --
#
# This procedure is invoked to handle font changes in the text
# being output.
#
# Arguments:
# type -		Type of font: R, I, B, or S.

proc font {type} {
    global state
    switch $type {
	P -
	R {
	    endFont
	    if {$state(textState) eq "REF"} {
		set state(textState) INSERT
	    }
	}
	C -
	B {
	    beginFont Code
	    if {$state(textState) eq "INSERT"} {
		set state(textState) REF
	    }
	}
	I {
	    beginFont Emphasis
	}
	S {
	}
	default {
	    puts stderr "Unknown font: $type"
	}
    }
}



# formattedText --
#
# Insert a text string that may also have \fB-style font changes
# and a few other backslash sequences in it.
#
# Arguments:
# text -		Text to insert.

proc formattedText {text} {
    global chars

    while {$text ne ""} {
	set index [string first \\ $text]
	if {$index < 0} {
	    text $text
	    return
	}
	text [string range $text 0 [expr {$index-1}]]
	set c [string index $text [expr {$index+1}]]
	switch -- $c {
	    f {
		font [string index $text [expr {$index+2}]]
		set text [string range $text [expr {$index+3}] end]
	    }
	    e {
		text "\\"
		set text [string range $text [expr {$index+2}] end]
	    }
	    - {
		dash
		set text [string range $text [expr {$index+2}] end]
	    }
	    & - | {
		set text [string range $text [expr {$index+2}] end]
	    }
	    ( {
		char [string range $text $index [expr {$index+3}]]
		set text [string range $text [expr {$index+4}] end]
	    }
	    default {
		puts stderr "Unknown sequence: \\$c"
		set text [string range $text [expr {$index+2}] end]
	    }
	}
    }
}


# dash --
#
# This procedure is invoked to handle dash characters ("\-" in
# troff).  It outputs a special dash character.
#
# Arguments:
# None.

proc dash {} {
    global state
    if {[string equal $state(textState) "NAME"]} {
    	set state(textState) 0
    }
    text "-"
}


# tab --
#
# This procedure is invoked to handle tabs in the troff input.
# Right now it does nothing.
#
# Arguments:
# None.

proc tab {} {
    global file

    textSetup
    puts -nonewline $file "\\tab "
}


# setTabs --
#
# This procedure handles the ".ta" macro, which sets tab stops.
#
# Arguments:
# tabList -	List of tab stops in *roff format

proc setTabs {tabList} {
    global file state

    set state(tabs) {}
    foreach arg $tabList {
	if {[string match +* $arg]} {
	    set relativeTo [lindex $state(tabs) end]
	    set arg [string range $arg 1 end]
	} else {
	    # Local left margin
	    set relativeTo [expr {$state(leftMargin) \
		    + ($state(offset) * $state(nestingLevel))}]
	}
	if {[regexp {^\\w'([^']*)'u$} $arg -> submatch]} {
	    # Magic factor!
	    set distance [expr {[string length $submatch] * 86.4}]
	} else {
	    set distance [getTwips $arg]
	}
	lappend state(tabs) [expr {round($distance + $relativeTo)}]
    }
}


# lineBreak --
#
# Generates a line break in the HTML output.
#
# Arguments:
# None.

proc lineBreak {} {
    global state
    textSetup
    set state(breakPending) 1
}



# newline --
#
# This procedure is invoked to handle newlines in the troff input.
# It outputs either a space character or a newline character, depending
# on fill mode.
#
# Arguments:
# None.

proc newline {} {
    global state

    if {$state(inTP)} {
    	set state(inTP) 0
	lineBreak
    } elseif {$state(noFill)} {
	lineBreak
    } else {
	text " "
    }
}


# pageBreak --
#
# This procedure is invoked to generate a page break.
#
# Arguments:
# None.

proc pageBreak {} {
    global file curVer
    if {[string equal $curVer ""]} {
	puts $file {\page}
    } else {
	puts $file {\par}
	puts $file {\pard\sb400\qc}
	puts $file "Last change: $curVer\\page"
    }
}


# char --
#
# This procedure is called to handle a special character.
#
# Arguments:
# name -		Special character named in troff \x or \(xx construct.

proc char {name} {
    global file state

    switch -exact $name {
        {\o} {
	    set state(intl) 1
	}
	{\ } {
	    textSetup
	    puts -nonewline $file " "
	}
	{\0} {
	    textSetup
	    puts -nonewline $file " \\emspace "
	}
	{\\} - {\e} {
	    textSetup
	    puts -nonewline $file "\\\\"
	}
	{\(+-} {
	    textSetup
	    puts -nonewline $file "\\'b1 "
	}
	{\%} - {\|} {
	}
	{\(->} {
	    textSetup
	    puts -nonewline $file "->"
	}
	{\(bu} {
	    textSetup
	    puts -nonewline $file "\\bullet "
	}
	{\(co} {
	    textSetup
	    puts -nonewline $file "\\'a9 "
	}
	{\(mi} {
	    textSetup
	    puts -nonewline $file "-"
	}
	{\(mu} {
	    textSetup
	    puts -nonewline $file "\\'d7 "
	}
	{\(em} - {\(en} {
	    textSetup
	    puts -nonewline $file "-"
	}
	{\(fm} {
	    textSetup
	    puts -nonewline $file "\\'27 "
	}
	default {
	    puts stderr "Unknown character: $name"
	}
    }
}


# macro2 --
#
# This procedure handles macros that are invoked with a leading "'"
# character instead of space.  Right now it just generates an
# error diagnostic.
#
# Arguments:
# name -		The name of the macro (without the ".").
# args -		Any additional arguments to the macro.

proc macro2 {name args} {
    puts stderr "Unknown macro: '$name [join $args " "]"
}



# SHmacro --
#
# Subsection head; handles the .SH and .SS macros.
#
# Arguments:
# name -		Section name.

proc SHmacro {argList {style section}} {
    global file state

    set args [join $argList " "]
    if {[llength $argList] < 1} {
	puts stderr "Bad .SH macro: .SH $args"
    }

    # control what the text proc does with text

    switch $args {
	NAME {set state(textState) NAME}
	DESCRIPTION {set state(textState) INSERT}
	INTRODUCTION {set state(textState) INSERT}
	"WIDGET-SPECIFIC OPTIONS" {set state(textState) INSERT}
	"SEE ALSO" {set state(textState) SEE}
	KEYWORDS {set state(textState) KEY; return}
    }

    if {$state(breakPending) != -1} {
	set state(breakPending) 1
    } else {
	set state(breakPending) 0
    }
    set state(noFill) 0
    if {[string compare "subsection" $style] == 0} {
	nextPara .25i
    } else {
	nextPara 0i
    }
    font B
    text $args
    font R
    nextPara .5i
}

# IPmacro --
#
# This procedure is invoked to handle ".IP" macros, which may take any
# of the following forms:
#
# .IP [1]		Translate to a "1Step" state(paragraph).
# .IP [x] (x > 1)	Translate to a "Step" state(paragraph).
# .IP			Translate to a "Bullet" state(paragraph).
# .IP text count	Translate to a FirstBody state(paragraph) with special
#			indent and tab stop based on "count", and tab after
#			"text".
#
# Arguments:
# argList -		List of arguments to the .IP macro.
#
# HTML limitations: 'count' in '.IP text count' is ignored.

proc IPmacro {argList} {
    global file state

    set length [llength $argList]
    foreach {text indent} $argList break
    if {$length > 2} {
	puts stderr "Bad .IP macro: .IP [join $argList " "]"
    }

    if {$length == 0} {
	set text {\(bu}
	set indent 5
    } elseif {$length == 1} {
	set indent 5
    }
    if {$text == {\(bu}} {
	set text "\xB7"
    }

    set tab [expr {$indent * 0.1}]i
    newPara $tab -$tab
    set state(sb) 80
    setTabs $tab
    formattedText $text
    tab
}

# TPmacro --
#
# This procedure is invoked to handle ".TP" macros, which may take any
# of the following forms:
#
# .TP x		Translate to an state(indent)ed state(paragraph) with the
# 			specified state(indent) (in 100 twip units).
# .TP		Translate to an state(indent)ed state(paragraph) with
# 			default state(indent).
#
# Arguments:
# argList -		List of arguments to the .IP macro.
#
# HTML limitations: 'x' in '.TP x' is ignored.

proc TPmacro {argList} {
    global state
    set length [llength $argList]
    if {$length == 0} {
	set val 0.5i
    } else {
	set val [expr {([lindex $argList 0] * 100.0)/1440}]i
    }
    newPara $val -$val
    setTabs $val
    set state(inTP) 1
    set state(sb) 120
}


# THmacro --
#
# This procedure handles the .TH macro.  It generates the non-scrolling
# header section for a given man page, and enters information into the
# table of contents.  The .TH macro has the following form:
#
# .TH name section date footer header
#
# Arguments:
# argList -		List of arguments to the .TH macro.

proc THmacro {argList} {
    global file curPkg curSect curID id_keywords state curVer bitmap

    if {[llength $argList] != 5} {
	set args [join $argList " "]
	puts stderr "Bad .TH macro: .TH $args"
    }
    incr curID
    set name	[lindex $argList 0]		;# Tcl_UpVar
    set page	[lindex $argList 1]		;# 3
    set curVer	[lindex $argList 2]		;# 7.4
    set curPkg	[lindex $argList 3]		;# Tcl
    set curSect	[lindex $argList 4]		;# {Tcl Library Procedures}

    regsub -all {\\ } $curSect { } curSect	;# Clean up for [incr\ Tcl]

    puts $file "#{\\footnote $curID}"		;# Context string
    puts $file "\${\\footnote $name}"		;# Topic title
    set browse "${curSect}${name}"
    regsub -all {[ _-]} $browse {} browse
    puts $file "+{\\footnote $browse}"		;# Browse sequence

    # Suppress duplicates
    foreach i $id_keywords($curID) {
	set keys($i) 1
    }
    foreach i [array names keys] {
	set i [string trim $i]
	if {[string length $i] > 0} {
	    puts $file "K{\\footnote $i}"	;# Keyword strings
	}
    }
    unset keys
    puts $file "\\pard\\tx3000\\sb100\\sa100\\fs24\\keepn"
    font B
    text $name
    tab
    text $curSect
    font R
    if {[info exists bitmap]} {
	# a right justified bitmap
	puts $file "\\\{bmrt $bitmap\\\}"
    }
    puts $file "\\fs20"
    set state(breakPending) -1
}

# nextPara --
#
# Set the indents for a new paragraph, and start a paragraph break
#
# Arguments:
# leftIndent -		The new left margin for body lines.
# firstIndent -		The offset from the left margin for the first line.

proc nextPara {leftIndent {firstIndent 0i}} {
    global state
    set state(leftIndent) [getTwips $leftIndent]
    set state(firstIndent) [getTwips $firstIndent]
    set state(paragraphPending) 1
}


# newPara --
#
# This procedure sets the left and hanging state(indent)s for a line.
# State(Indent)s are specified in units of inches or centimeters, and are
# relative to the current nesting level and left margin.
#
# Arguments:
# leftState(Indent) -		The new left margin for lines after the first.
# firstState(Indent) -		The new left margin for the first line of a state(paragraph).

proc newPara {leftIndent {firstIndent 0i}} {
    global state file
    if $state(paragraph) {
	puts -nonewline $file "\\line\n"
    }
    if {$leftIndent ne ""} {
	set state(leftIndent) [expr {$state(leftMargin) \
		+ ($state(offset) * $state(nestingLevel)) \
		+ [getTwips $leftIndent]}]
    }
    set state(firstIndent) [getTwips $firstIndent]
    set state(paragraphPending) 1
}


# getTwips --
#
# This procedure converts a distance in inches or centimeters into
# twips (1/1440 of an inch).
#
# Arguments:
# arg -			A number followed by "i" or "c"

proc getTwips {arg} {
    if {[scan $arg "%f%s" distance units] != 2} {
	puts stderr "bad distance \"$arg\""
	return 0
    }
    if {[string length $units] > 1} {
	puts stderr "additional characters after unit \"$arg\""
	set units [string index $units 0]
    }
    switch -- $units {
	c	{
	    set distance [expr {$distance * 567}]
	}
	i	{
	    set distance [expr {$distance * 1440}]
	}
	default {
	    puts stderr "bad units in distance \"$arg\""
	    return 0
	}
    }
    return $distance
}

# incrNestingLevel --
#
# This procedure does the work of the .RS macro, which increments
# the number of state(indent)ations that affect things like .PP.
#
# Arguments:
# None.

proc incrNestingLevel {} {
    global state

    incr state(nestingLevel)
    set oldp $state(paragraph)
    set state(paragraph) 0
    newPara 0i
    set state(paragraph) $oldp
}

# decrNestingLevel --
#
# This procedure does the work of the .RE macro, which decrements
# the number of indentations that affect things like .PP.
#
# Arguments:
# None.

proc decrNestingLevel {} {
    global state

    if {$state(nestingLevel) == 0} {
	puts stderr "Nesting level decremented below 0"
    } else {
	incr state(nestingLevel) -1
    }
}

Deleted tools/man2html.tcl.

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
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

























































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#!/bin/sh
# \
exec tclsh "$0" ${1+"$@"}

# man2html.tcl --
#
# This file contains procedures that work in conjunction with the
# man2tcl program to generate a HTML files from Tcl manual entries.
#
# Copyright (c) 1996 by Sun Microsystems, Inc.


# sarray -
#
# Save an array to a file so that it can be sourced.
#
# Arguments:
# file -		Name of the output file
# args -		Name of the arrays to save
#
proc sarray {file args} {
    set file [open $file w]
    foreach a $args {
	upvar $a array
	if {![array exists array]} {
	    puts "sarray: \"$a\" isn't an array"
	    break
	}

	foreach name [lsort [array names array]] {
	    regsub -all " " $name "\\ " name1
	    puts $file "set ${a}($name1) \{$array($name)\}"
	}
    }
    close $file
}


# footer --
#
# Builds footer info for HTML pages
#
# Arguments:
# packages -		List of packages to link to.

proc footer {packages} {
    lappend f "<HR>"
    set h {[}
    foreach package $packages {
	lappend h "<A HREF=\"../$package/contents.html\">$package</A>"
	lappend h "|"
    }
    lappend f [join [lreplace $h end end {]} ] " "]
    lappend f "<HR>"
    lappend f "<PRE>Copyright &#169; 1989-1994 The Regents of the University of California."
    lappend f "Copyright &#169; 1994-1996 Sun Microsystems, Inc."
    lappend f "</PRE>"
    return [join $f "\n"]
}


# doDir --
#
# Given a directory as argument, translate all the man pages in
# that directory.
#
# Arguments:
# dir -			Name of the directory.

proc doDir dir {
    foreach f [lsort [glob -directory $dir "*.\[13n\]"]] {
	do $f	;# defined in man2html1.tcl & man2html2.tcl
    }
}


# main --
#
# Main code for converting Tcl manual pages to HTML.
#
# Arguments:
# argv -		List of arguments to this script.

proc main {argv} {
    global html_dir
    # Global vars used in man2html1.tcl and man2html2.tcl
    global NAME_file KEY_file lib state curFile file inDT textState nestStk
    global curFont fontStart fontEnd noFillCount footer

    if {[llength $argv] < 2} {
	puts stderr "usage: $::argv0 html_dir tcl_dir packages..."
	puts stderr "usage: $::argv0 -clean html_dir"
	exit 1
    }

    if {[lindex $argv 0] eq "-clean"} {
	set html_dir [lindex $argv 1]
	puts -nonewline "recursively remove: $html_dir? "
	flush stdout
	if {[gets stdin] eq "y"} {
	    puts "removing: $html_dir"
	    file delete -force $html_dir
	}
	exit 0
    }

    set html_dir [lindex $argv 0]
    set tcl_dir  [lindex $argv 1]
    set packages [lrange $argv 2 end]
    set homeDir  [file dirname [info script]]

    #### need to add glob capability to packages ####

    # make sure there are doc directories for each package

    foreach i $packages {
	if {![file exists $tcl_dir/$i/doc]} {
	    puts stderr "Error: doc directory for package $i is missing"
	    exit 1
	}
	if {![file isdirectory $tcl_dir/$i/doc]} {
	    puts stderr "Error: $tcl_dir/$i/doc is not a directory"
	    exit 1
	}
    }

    # we want to start with a clean sheet

    if {[file exists $html_dir]} {
	puts stderr "Error: HTML directory already exists"
	exit 1
    } else {
	file mkdir $html_dir
    }

    set footer [footer $packages]

    # make the hyperlink arrays and contents.html for all packages

    foreach package $packages {
	file mkdir $html_dir/$package

	# build hyperlink database arrays: NAME_file and KEY_file
	#
	puts "\nScanning man pages in $tcl_dir/$package/doc..."
	uplevel \#0 [list source $homeDir/man2html1.tcl]

	doDir $tcl_dir/$package/doc

	# clean up the NAME_file and KEY_file database arrays
	#
	catch {unset KEY_file()}
	foreach name [lsort [array names NAME_file]] {
	    set file_name $NAME_file($name)
	    if {[llength $file_name] > 1} {
		set file_name [lsort $file_name]
		puts "Warning: '$name' multiply defined in: $file_name;\
			using last"
		set NAME_file($name) [lindex $file_name end]
	    }
	}
	# sarray $html_dir/$package/xref.tcl NAME_file KEY_file

	# build the contents file from NAME_file
	#
	puts "\nGenerating contents.html for $package"
	doContents $html_dir/$package/contents.html $lib ;# defined in man2html1.tcl

	# now translate the man pages to HTML pages
	#
	uplevel \#0 [list source $homeDir/man2html2.tcl]
	puts "\nBuilding html pages from man pages in $tcl_dir/$package/doc..."
	doDir $tcl_dir/$package/doc

	unset NAME_file
    }
}


if [catch { main $argv } result] {
    global errorInfo
    puts stderr $result
    puts stderr "in"
    puts stderr $errorInfo
}

Deleted tools/man2html1.tcl.

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
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


































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# man2html1.tcl --
#
# This file defines procedures that are used during the first pass of the
# man page to html conversion process. It is sourced by h.tcl.
#
# Copyright (c) 1996 by Sun Microsystems, Inc.

# Global variables used by these scripts:
#
# state -	state variable that controls action of text proc.
#
# curFile -	tail of current man page.
#
# file -	file pointer; for both xref.tcl and contents.html
#
# NAME_file -	array indexed by NAME and containing file names used
#		for hyperlinks.
#
# KEY_file -	array indexed by KEYWORD and containing file names used
#		for hyperlinks.
#
# lib -		contains package name. Used to label section in contents.html
#
# inDT -	in dictionary term.


# text --
#
# This procedure adds entries to the hypertext arrays NAME_file
# and KEY_file.
#
# DT: might do this: if first word of $dt matches $name and [llength $name==1]
# 	and [llength $dt > 1], then add to NAME_file.
#
# Arguments:
# string -		Text to index.

proc text string {
    global state curFile NAME_file KEY_file inDT

    switch $state {
	NAME {
	    foreach i [split $string ","] {
		lappend NAME_file([string trim $i]) $curFile
	    }
	}
	KEY {
	    foreach i [split $string ","] {
		lappend KEY_file([string trim $i]) $curFile
	    }
	}
	DT -
	OFF -
	DASH {}
	default {
	    puts stderr "text: unknown state: $state"
	}
    }
}


# macro --
#
# This procedure is invoked to process macro invocations that start
# with "." (instead of ').
#
# Arguments:
# name -	The name of the macro (without the ".").
# args -	Any additional arguments to the macro.

proc macro {name args} {
    switch $name {
	SH - SS {
	    global state

	    switch $args {
		NAME {
		    if {$state eq "INIT"} {
			set state NAME
		    }
		}
		DESCRIPTION {set state DT}
		INTRODUCTION {set state DT}
		KEYWORDS {set state KEY}
		default {set state OFF}
	    }

	}
	TP {
	    global inDT
	    set inDT 1
	}
	TH {
	    global lib state inDT
	    set inDT 0
	    set state INIT
	    if {[llength $args] != 5} {
		set args [join $args " "]
		puts stderr "Bad .TH macro: .$name $args"
	    }
	    set lib [lindex $args 3]				;# Tcl or Tk
	}
    }
}


# dash --
#
# This procedure is invoked to handle dash characters ("\-" in
# troff).  It only function in pass1 is to terminate the NAME state.
#
# Arguments:
# None.

proc dash {} {
    global state
    if {$state eq "NAME"} {
	set state DASH
    }
}


# newline --
#
# This procedure is invoked to handle newlines in the troff input.
# It's only purpose is to terminate a DT (dictionary term).
#
# Arguments:
# None.

proc newline {} {
    global inDT
    set inDT 0
}


# initGlobals, tab, font, char, macro2 --
#
# These procedures do nothing during the first pass.
#
# Arguments:
# None.

proc initGlobals {} {}
proc tab {} {}
proc font type {}
proc char name {}
proc macro2 {name args} {}


# doListing --
#
# Writes an ls like list to a file. Searches NAME_file for entries
# that match the input pattern.
#
# Arguments:
# file -		Output file pointer.
# pattern -		glob style match pattern

proc doListing {file pattern} {
    global NAME_file

    set max_len 0
    foreach name [lsort [array names NAME_file]] {
	set ref $NAME_file($name)
	    if [string match $pattern $ref] {
		lappend type $name
		if {[string length $name] > $max_len} {
		set max_len [string length $name]
	    }
	}
    }
    if [catch {llength $type} ] {
	puts stderr "       doListing: no names matched pattern ($pattern)"
	return
    }
    incr max_len
    set ncols [expr {90/$max_len}]
    set nrows [expr {int(ceil([llength $type] / double($ncols)))} ]

#	? max_len ncols nrows

    set index 0
    foreach f $type {
	lappend row([expr {$index % $nrows}]) $f
	incr index
    }

    puts -nonewline $file "<PRE>"
    for {set i 0} {$i<$nrows} {incr i} {
	foreach name $row($i) {
	    set str [format "%-*s" $max_len $name]
	    regsub $name $str "<A HREF=\"$NAME_file($name).html\">$name</A>" str
	    puts -nonewline $file $str
	}
	puts $file {}
    }
    puts $file "</PRE>"
}


# doContents --
#
# Generates a HTML contents file using the NAME_file array
# as its input database.
#
# Arguments:
# file -		name of the contents file.
# packageName -		string used in the title and sub-heads of the HTML
#			page. Normally name of the package without version
#			numbers.

proc doContents {file packageName} {
    global footer

    set file [open $file w]

    puts $file "<HTML><HEAD><TITLE>$packageName Manual</TITLE></HEAD><BODY>"
    puts $file "<H3>$packageName</H3>"
    doListing $file "*.1"

    puts $file "<HR><H3>$packageName Commands</H3>"
    doListing $file "*.n"

    puts $file "<HR><H3>$packageName Library</H3>"
    doListing $file "*.3"

    puts $file $footer
    puts $file "</BODY></HTML>"
    close $file
}


# do --
#
# This is the toplevel procedure that searches a man page
# for hypertext links.  It builds a data base consisting of
# two arrays: NAME_file and KEY file. It runs the man2tcl
# program to turn the man page into a script, then it evals
# that script.
#
# Arguments:
# fileName -		Name of the file to scan.

proc do fileName {
    global curFile
    set curFile [file tail $fileName]
    set file stdout
    puts "  Pass 1 -- $fileName"
    flush stdout
    if [catch {eval [exec man2tcl [glob $fileName]]} msg] {
	global errorInfo
	puts stderr $msg
	puts "in"
	puts $errorInfo
	exit 1
    }
}

Deleted tools/man2html2.tcl.

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
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
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
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
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
##############################################################################
# man2html2.tcl --
#
# This file defines procedures that are used during the second pass of the man
# page to html conversion process. It is sourced by man2html.tcl.
#
# Copyright (c) 1996 by Sun Microsystems, Inc.

# Global variables used by these scripts:
#
# NAME_file -	array indexed by NAME and containing file names used for
#		hyperlinks.
#
# textState -	state variable defining action of 'text' proc.
#
# nestStk -	stack oriented list containing currently active HTML tags (UL,
#		OL, DL). Local to 'nest' proc.
#
# inDT -	set by 'TPmacro', cleared by 'newline'. Used to insert the
#		tag while in a dictionary list <DL>.
#
# curFont -	Name of special font that is currently in use. Null means the
#		default paragraph font is being used.
#
# file -	Where to output the generated HTML.
#
# fontStart -	Array to map font names to starting sequences.
#
# fontEnd -	Array to map font names to ending sequences.
#
# noFillCount -	Non-zero means don't fill the next $noFillCount lines: force a
#		line break at each newline. Zero means filling is enabled, so
#		don't output line breaks for each newline.
#
# footer -	info inserted at bottom of each page. Normally read from the
#		xref.tcl file

##############################################################################
# initGlobals --
#
# This procedure is invoked to set the initial values of all of the global
# variables, before processing a man page.
#
# Arguments:
# None.

proc initGlobals {} {
    global file noFillCount textState
    global fontStart fontEnd curFont inPRE charCnt inTable

    nest init
    set inPRE 0
    set inTable 0
    set textState 0
    set curFont ""
    set fontStart(Code) "<B>"
    set fontStart(Emphasis) "<I>"
    set fontEnd(Code) "</B>"
    set fontEnd(Emphasis) "</I>"
    set noFillCount 0
    set charCnt 0
    setTabs 0.5i
}

##############################################################################
# beginFont --
#
# Arranges for future text to use a special font, rather than the default
# paragraph font.
#
# Arguments:
# font -		Name of new font to use.

proc beginFont font {
    global curFont file fontStart

    if {$curFont eq $font} {
	return
    }
    endFont
    puts -nonewline $file $fontStart($font)
    set curFont $font
}

##############################################################################
# endFont --
#
# Reverts to the default font for the paragraph type.
#
# Arguments:
# None.

proc endFont {} {
    global curFont file fontEnd

    if {$curFont ne ""} {
	puts -nonewline $file $fontEnd($curFont)
	set curFont ""
    }
}

##############################################################################
# text --
#
# This procedure adds text to the current paragraph. If this is the first text
# in the paragraph then header information for the paragraph is output before
# the text.
#
# Arguments:
# string -		Text to output in the paragraph.

proc text string {
    global file textState inDT charCnt inTable

    set pos [string first "\t" $string]
    if {$pos >= 0} {
    	text [string range $string 0 [expr {$pos-1}]]
    	tab
    	text [string range $string [expr {$pos+1}] end]
	return
    }
    if {$inTable} {
	if {$inTable == 1} {
	    puts -nonewline $file <TR>
	    set inTable 2
	}
	puts -nonewline $file <TD>
    }
    incr charCnt [string length $string]
    regsub -all {&} $string {\&amp;}  string
    regsub -all {<} $string {\&lt;}  string
    regsub -all {>} $string {\&gt;}  string
    regsub -all \"  $string {\&quot;}  string
    switch -exact -- $textState {
	REF {
	    if {$inDT eq ""} {
		set string [insertRef $string]
	    }
	}
	SEE {
	    global NAME_file
	    foreach i [split $string] {
		if {![regexp -nocase {^[a-z_]+} [string trim $i] i]} {
# 		    puts "Warning: $i in SEE ALSO not found"
		    continue
		}
		if {![catch { set ref $NAME_file($i) }]} {
		    regsub $i $string "<A HREF=\"$ref.html\">$i</A>" string
		}
	    }
	}
    }
    puts -nonewline $file "$string"
    if {$inTable} {
	puts -nonewline $file </TD>
    }
}

##############################################################################
# insertRef --
#
# Arguments:
# string -		Text to output in the paragraph.

proc insertRef string {
    global NAME_file self
    set path {}
    if {![catch { set ref $NAME_file([string trim $string]) }]} {
	if {"$ref.html" ne $self} {
	    set string "<A HREF=\"${path}$ref.html\">$string</A>"
#	    puts "insertRef: $self $ref.html ---$string--"
	}
    }
    return $string
}

##############################################################################
# macro --
#
# This procedure is invoked to process macro invocations that start with "."
# (instead of ').
#
# Arguments:
# name -		The name of the macro (without the ".").
# args -		Any additional arguments to the macro.

proc macro {name args} {
    switch $name {
	AP {
	    if {[llength $args] != 3} {
		puts stderr "Bad .AP macro: .$name [join $args " "]"
	    }
	    setTabs {1.25i 2.5i 3.75i}
	    TPmacro {}
	    font B
	    text "[lindex $args 0]  "
	    font I
	    text "[lindex $args 1]"
	    font R
	    text " ([lindex $args 2])"
	    newline
	}
	AS {}				;# next page and previous page
	br {
	    lineBreak
	}
	BS {}
	BE {}
	CE {
	    global file noFillCount inPRE
	    puts $file </PRE></BLOCKQUOTE>
	    set inPRE 0
	}
	CS {				;# code section
	    global file noFillCount inPRE
	    puts -nonewline $file <BLOCKQUOTE><PRE>
	    set inPRE 1
	}
	DE {
	    global file noFillCount inTable
	    puts $file </TABLE></BLOCKQUOTE>
	    set inTable 0
	    set noFillCount 0
	}
	DS {
	    global file noFillCount inTable
	    puts -nonewline $file {<BLOCKQUOTE><TABLE BORDER="0">}
	    set noFillCount 10000000
	    set inTable 1
	}
	fi {
	    global noFillCount
	    set noFillCount 0
	}
	IP {
	    IPmacro $args
	}
	LP {
	    nest decr
	    nest incr
	    newPara
	}
	ne {
	}
	nf {
	    global noFillCount
	    set noFillCount 1000000
	}
	OP {
	    global inDT file inPRE
	    if {[llength $args] != 3} {
		puts stderr "Bad .OP macro: .$name [join $args " "]"
	    }
	    nest para DL DT
	    set inPRE 1
	    puts -nonewline $file <PRE>
	    setTabs 4c
	    text "Command-Line Name:"
	    tab
	    font B
	    set x [lindex $args 0]
	    regsub -all {\\-} $x - x
	    text $x
	    newline
	    font R
	    text "Database Name:"
	    tab
	    font B
	    text [lindex $args 1]
	    newline
	    font R
	    text "Database Class:"
	    tab
	    font B
	    text [lindex $args 2]
	    font R
	    puts -nonewline $file </PRE>
	    set inDT "\n<DD>"			;# next newline writes inDT
	    set inPRE 0
	    newline
	}
	PP {
	    nest decr
	    nest incr
	    newPara
	}
	RE {
	    nest decr
	}
	RS {
	    nest incr
	}
	SE {
	    global noFillCount textState inPRE file

	    font R
	    puts -nonewline $file </PRE>
	    set inPRE 0
	    set noFillCount 0
	    nest reset
	    newPara
	    text "See the "
	    font B
	    set temp $textState
	    set textState REF
	    if {[llength $args] > 0} {
		text [lindex $args 0]
	    } else {
		text options
	    }
	    set textState $temp
	    font R
	    text " manual entry for detailed descriptions of the above options."
	}
	SH {
	    SHmacro $args
	}
	SS {
	    SHmacro $args subsection
	}
	SO {
	    global noFillCount inPRE file

	    SHmacro "STANDARD OPTIONS"
	    setTabs {4c 8c 12c}
	    set noFillCount 1000000
	    puts -nonewline $file <PRE>
	    set inPRE 1
	    font B
	}
	so {
	    if {$args ne "man.macros"} {
		puts stderr "Unknown macro: .$name [join $args " "]"
	    }
	}
	sp {					;# needs work
	    if {$args eq ""} {
		set count 1
	    } else {
		set count [lindex $args 0]
	    }
	    while {$count > 0} {
		lineBreak
		incr count -1
	    }
	}
	ta {
	    setTabs $args
	}
	TH {
	    THmacro $args
	}
	TP {
	    TPmacro $args
	}
	UL {					;# underline
	    global file
	    puts -nonewline $file "<B><U>"
	    text [lindex $args 0]
	    puts -nonewline $file "</U></B>"
	    if {[llength $args] == 2} {
		text [lindex $args 1]
	    }
	}
	VE {
#	    global file
#	    puts -nonewline $file "</FONT>"
	}
	VS {
#	    global file
#	    if {[llength $args] > 0} {
#		puts -nonewline $file "<BR>"
#	    }
#	    puts -nonewline $file "<FONT COLOR=\"GREEN\">"
	}
	QW {
	    puts -nonewline $file "&\#147;"
	    text [lindex $args 0]
	    puts -nonewline $file "&\#148;"
	    if {[llength $args] > 1} {
		text [lindex $args 1]
	    }
	}
	PQ {
	    puts -nonewline $file "(&\#147;"
	    if {[lindex $args 0] eq {\N'34'}} {
		puts -nonewline $file \"
	    } else {
		text [lindex $args 0]
	    }
	    puts -nonewline $file "&\#148;"
	    if {[llength $args] > 1} {
		text [lindex $args 1]
	    }
	    puts -nonewline $file ")"
	    if {[llength $args] > 2} {
		text [lindex $args 2]
	    }
	}
	QR {
	    puts -nonewline $file "&\#147;"
	    text [lindex $args 0]
	    puts -nonewline $file "&\#148;&\#150;&\#147;"
	    text [lindex $args 1]
	    puts -nonewline $file "&\#148;"
	    if {[llength $args] > 2} {
		text [lindex $args 2]
	    }
	}
	MT {
	    puts -nonewline $file "&\#147;&\#148;"
	}
	default {
	    puts stderr "Unknown macro: .$name [join $args " "]"
	}
    }

#	global nestStk; puts "$name [format "%-20s" $args] $nestStk"
#	flush stdout; flush stderr
}

##############################################################################
# font --
#
# This procedure is invoked to handle font changes in the text being output.
#
# Arguments:
# type -		Type of font: R, I, B, or S.

proc font type {
    global textState
    switch $type {
	P -
	R {
	    endFont
	    if {$textState eq "REF"} {
		set textState INSERT
	    }
	}
	B {
	    beginFont Code
	    if {$textState eq "INSERT"} {
		set textState REF
	    }
	}
	I {
	    beginFont Emphasis
	}
	S {
	}
	default {
	    puts stderr "Unknown font: $type"
	}
    }
}

##############################################################################
# formattedText --
#
# Insert a text string that may also have \fB-style font changes and a few
# other backslash sequences in it.
#
# Arguments:
# text -		Text to insert.

proc formattedText text {
#	puts "formattedText: $text"
    while {$text ne ""} {
	set index [string first \\ $text]
	if {$index < 0} {
	    text $text
	    return
	}
	text [string range $text 0 [expr {$index-1}]]
	set c [string index $text [expr {$index+1}]]
	switch -- $c {
	    f {
		font [string index $text [expr {$index+2}]]
		set text [string range $text [expr {$index+3}] end]
	    }
	    e {
		text \\
		set text [string range $text [expr {$index+2}] end]
	    }
	    - {
		dash
		set text [string range $text [expr {$index+2}] end]
	    }
	    | {
		set text [string range $text [expr {$index+2}] end]
	    }
	    default {
		puts stderr "Unknown sequence: \\$c"
		set text [string range $text [expr {$index+2}] end]
	    }
	}
    }
}

##############################################################################
# dash --
#
# This procedure is invoked to handle dash characters ("\-" in troff). It
# outputs a special dash character.
#
# Arguments:
# None.

proc dash {} {
    global textState charCnt
    if {$textState eq "NAME"} {
    	set textState 0
    }
    incr charCnt
    text "-"
}

##############################################################################
# tab --
#
# This procedure is invoked to handle tabs in the troff input.
#
# Arguments:
# None.

proc tab {} {
    global inPRE charCnt tabString file
#	? charCnt
    if {$inPRE == 1} {
	set pos [expr {$charCnt % [string length $tabString]}]
	set spaces [string first "1" [string range $tabString $pos end] ]
	text [format "%*s" [incr spaces] " "]
    } else {
#	puts "tab: found tab outside of <PRE> block"
    }
}

##############################################################################
# setTabs --
#
# This procedure handles the ".ta" macro, which sets tab stops.
#
# Arguments:
# tabList -	List of tab stops, each consisting of a number
#			followed by "i" (inch) or "c" (cm).

proc setTabs {tabList} {
    global file breakPending tabString

    # puts "setTabs: --$tabList--"
    set last 0
    set tabString {}
    set charsPerInch 14.
    set numTabs [llength $tabList]
    foreach arg $tabList {
	if {[string match +* $arg]} {
	    set relative 1
	    set arg [string range $arg 1 end]
	} else {
	    set relative 0
	}
	# Always operate in relative mode for "measurement" mode
	if {[regexp {^\\w'(.*)'u$} $arg content]} {
	    set distance [string length $content]
	} else {
	    if {[scan $arg "%f%s" distance units] != 2} {
		puts stderr "bad distance \"$arg\""
		return 0
	    }
	    switch -- $units {
		c {
		    set distance [expr {$distance * $charsPerInch / 2.54}]
		}
		i {
		    set distance [expr {$distance * $charsPerInch}]
		}
		default {
		    puts stderr "bad units in distance \"$arg\""
		    continue
		}
	    }
	}
	# ? distance
	if {$relative} {
	    append tabString [format "%*s1" [expr {round($distance-1)}] " "]
	    set last [expr {$last + $distance}]
	} else {
	    append tabString [format "%*s1" [expr {round($distance-$last-1)}] " "]
	    set last $distance
	}
    }
    # puts "setTabs: --$tabString--"
}

##############################################################################
# lineBreak --
#
# Generates a line break in the HTML output.
#
# Arguments:
# None.

proc lineBreak {} {
    global file inPRE
    puts $file "<BR>"
}

##############################################################################
# newline --
#
# This procedure is invoked to handle newlines in the troff input. It outputs
# either a space character or a newline character, depending on fill mode.
#
# Arguments:
# None.

proc newline {} {
    global noFillCount file inDT inPRE charCnt inTable

    if {$inDT ne ""} {
    	puts $file "\n$inDT"
    	set inDT {}
    } elseif {$inTable} {
	if {$inTable > 1} {
	    puts $file </tr>
	    set inTable 1
	}
    } elseif {$noFillCount == 0 || $inPRE == 1} {
	puts $file {}
    } else {
	lineBreak
	incr noFillCount -1
    }
    set charCnt 0
}

##############################################################################
# char --
#
# This procedure is called to handle a special character.
#
# Arguments:
# name -		Special character named in troff \x or \(xx construct.

proc char name {
    global file charCnt

    incr charCnt
#	puts "char: $name"
    switch -exact $name {
	\\0 {					;#  \0
	    puts -nonewline $file " "
	}
	\\\\ {					;#  \
	    puts -nonewline $file "\\"
	}
	\\(+- { 				;#  +/-
	    puts -nonewline $file "&#177;"
	}
	\\% {}					;#  \%
	\\| {					;#  \|
	}
	default {
	    puts stderr "Unknown character: $name"
	}
    }
}

##############################################################################
# macro2 --
#
# This procedure handles macros that are invoked with a leading "'" character
# instead of space. Right now it just generates an error diagnostic.
#
# Arguments:
# name -		The name of the macro (without the ".").
# args -		Any additional arguments to the macro.

proc macro2 {name args} {
    puts stderr "Unknown macro: '$name [join $args " "]"
}

##############################################################################
# SHmacro --
#
# Subsection head; handles the .SH and .SS macros.
#
# Arguments:
# name -		Section name.
# style -		Type of section (optional)

proc SHmacro {argList {style section}} {
    global file noFillCount textState charCnt

    set args [join $argList " "]
    if {[llength $argList] < 1} {
	puts stderr "Bad .SH macro: .$name $args"
    }

    set noFillCount 0
    nest reset

    set tag H3
    if {$style eq "subsection"} {
	set tag H4
    }
    puts -nonewline $file "<$tag>"
    text $args
    puts $file "</$tag>"

#	? args textState

    # control what the text proc does with text

    switch $args {
	NAME {set textState NAME}
	DESCRIPTION {set textState INSERT}
	INTRODUCTION {set textState INSERT}
	"WIDGET-SPECIFIC OPTIONS" {set textState INSERT}
	"SEE ALSO" {set textState SEE}
	KEYWORDS {set textState 0}
    }
    set charCnt 0
}

##############################################################################
# IPmacro --
#
# This procedure is invoked to handle ".IP" macros, which may take any of the
# following forms:
#
# .IP [1]			Translate to a "1Step" paragraph.
# .IP [x] (x > 1)		Translate to a "Step" paragraph.
# .IP				Translate to a "Bullet" paragraph.
# .IP \(bu			Translate to a "Bullet" paragraph.
# .IP text count		Translate to a FirstBody paragraph with
#				special indent and tab stop based on "count",
#				and tab after "text".
#
# Arguments:
# argList -		List of arguments to the .IP macro.
#
# HTML limitations: 'count' in '.IP text count' is ignored.

proc IPmacro argList {
    global file

    setTabs 0.5i
    set length [llength $argList]
    if {$length == 0} {
    	nest para UL LI
	return
    }
    # Special case for alternative mechanism for declaring bullets
    if {[lindex $argList 0] eq "\\(bu"} {
	nest para UL LI
	return
    }
    if {[regexp {^\[\d+\]$} [lindex $argList 0]]} {
    	nest para OL LI
	return
    }
    nest para DL DT
    formattedText [lindex $argList 0]
    puts $file "\n<DD>"
    return
}

##############################################################################
# TPmacro --
#
# This procedure is invoked to handle ".TP" macros, which may take any of the
# following forms:
#
# .TP x		Translate to an indented paragraph with the specified indent
# 			(in 100 twip units).
# .TP		Translate to an indented paragraph with default indent.
#
# Arguments:
# argList -		List of arguments to the .IP macro.
#
# HTML limitations: 'x' in '.TP x' is ignored.

proc TPmacro {argList} {
    global inDT
    nest para DL DT
    set inDT "\n<DD>"			;# next newline writes inDT
    setTabs 0.5i
}

##############################################################################
# THmacro --
#
# This procedure handles the .TH macro. It generates the non-scrolling header
# section for a given man page, and enters information into the table of
# contents. The .TH macro has the following form:
#
# .TH name section date footer header
#
# Arguments:
# argList -		List of arguments to the .TH macro.

proc THmacro {argList} {
    global file

    if {[llength $argList] != 5} {
	set args [join $argList " "]
	puts stderr "Bad .TH macro: .$name $args"
    }
    set name  [lindex $argList 0]		;# Tcl_UpVar
    set page  [lindex $argList 1]		;# 3
    set vers  [lindex $argList 2]		;# 7.4
    set lib   [lindex $argList 3]		;# Tcl
    set pname [lindex $argList 4]		;# {Tcl Library Procedures}

    puts -nonewline $file "<HTML><HEAD><TITLE>"
    text "$lib - $name ($page)"
    puts $file "</TITLE></HEAD><BODY>\n"

    puts -nonewline $file "<H1><CENTER>"
    text $pname
    puts $file "</CENTER></H1>\n"
}

##############################################################################
# newPara --
#
# This procedure sets the left and hanging indents for a line. Indents are
# specified in units of inches or centimeters, and are relative to the current
# nesting level and left margin.
#
# Arguments:
# None

proc newPara {} {
    global file nestStk

    if {[lindex $nestStk end] ne "NEW"} {
	nest decr
    }
    puts -nonewline $file "<P>"
}

##############################################################################
# nest --
#
# This procedure takes care of inserting the tags associated with the IP, TP,
# RS, RE, LP and PP macros. Only 'nest para' takes arguments.
#
# Arguments:
# op -				operation: para, incr, decr, reset, init
# listStart -		begin list tag: OL, UL, DL.
# listItem -		item tag:       LI, LI, DT.

proc nest {op {listStart "NEW"} {listItem ""} } {
    global file nestStk inDT charCnt
#	puts "nest: $op $listStart $listItem"
    switch $op {
	para {
	    set top [lindex $nestStk end]
	    if {$top eq "NEW"} {
		set nestStk [lreplace $nestStk end end $listStart]
		puts $file "<$listStart>"
	    } elseif {$top ne $listStart} {
		puts stderr "nest para: bad stack"
		exit 1
	    }
	    puts $file "\n<$listItem>"
	    set charCnt 0
	}
	incr {
	   lappend nestStk NEW
	}
	decr {
	    if {[llength $nestStk] == 0} {
		puts stderr "nest error: nest length is zero"
		set nestStk NEW
	    }
	    set tag [lindex $nestStk end]
	    if {$tag ne "NEW"} {
		puts $file "</$tag>"
	    }
	    set nestStk [lreplace $nestStk end end]
	}
	reset {
	    while {[llength $nestStk] > 0} {
		nest decr
	    }
	    set nestStk NEW
	}
	init {
	    set nestStk NEW
	    set inDT {}
	}
    }
    set charCnt 0
}

##############################################################################
# do --
#
# This is the toplevel procedure that translates a man page to HTML. It runs
# the man2tcl program to turn the man page into a script, then it evals that
# script.
#
# Arguments:
# fileName -		Name of the file to translate.

proc do fileName {
    global file self html_dir package footer
    set self "[file tail $fileName].html"
    set file [open "$html_dir/$package/$self" w]
    puts "  Pass 2 -- $fileName"
    flush stdout
    initGlobals
    if {[catch { eval [exec man2tcl [glob $fileName]] } msg]} {
	global errorInfo
	puts stderr $msg
	puts "in"
	puts stderr $errorInfo
	exit 1
    }
    nest reset
    puts $file $footer
    puts $file "</BODY></HTML>"
    close $file
}

Deleted tools/man2tcl.c.

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
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
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








































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * man2tcl.c --
 *
 *	This file contains a program that turns a man page of the form used
 *	for Tcl and Tk into a Tcl script that invokes a Tcl command for each
 *	construct in the man page. The script can then be eval'ed to translate
 *	the manual entry into some other format such as MIF or HTML.
 *
 * Usage:
 *
 *	man2tcl ?fileName?
 *
 * Copyright (c) 1995 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

static char sccsid[] = "@(#) man2tcl.c 1.3 95/08/12 17:34:08";

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>

/*
 * Imported things that aren't defined in header files:
 */

/*
 * Some <errno.h> define errno to be something complex and thread-aware; in
 * that case we definitely do not want to declare errno ourselves!
 */

#ifndef errno
extern int errno;
#endif

/*
 * Current line number, used for error messages.
 */

static int lineNumber;

/*
 * The variable below is set to 1 if an error occurs anywhere while reading in
 * the file.
 */

static int status;

/*
 * The variable below is set to 1 if output should be generated. If it's 0, it
 * means we're doing a pre-pass to make sure that the file can be properly
 * parsed.
 */

static int writeOutput;

#define PRINT(args)	if (writeOutput) { printf args; }
#define PRINTC(chr)	if (writeOutput) { putc((chr), stdout); }

/*
 * Prototypes for functions defined in this file:
 */

static void		DoMacro(char *line);
static void		DoText(char *line);
static void		QuoteText(char *string, int count);

/*
 *----------------------------------------------------------------------
 *
 * main --
 *
 *	This function is the main program, which does all of the work of the
 *	program.
 *
 * Results:
 *	None: exits with a 0 return status to indicate success, or 1 to
 *	indicate that there were problems in the translation.
 *
 * Side effects:
 *	A Tcl script is output to standard output. Error messages may be
 *	output on standard error.
 *
 *----------------------------------------------------------------------
 */

int
main(
    int argc,			/* Number of command-line arguments. */
    char **argv)		/* Values of command-line arguments. */
{
    FILE *f;
#define MAX_LINE_SIZE 4000
    char line[MAX_LINE_SIZE];
    char *p;

    /*
     * Find the file to read, and open it if it isn't stdin.
     */

    if (argc == 1) {
	f = stdin;
    } else if (argc == 2) {
	f = fopen(argv[1], "r");
	if (f == NULL) {
	    fprintf(stderr, "Couldn't read \"%s\": %s\n", argv[1],
		    strerror(errno));
	    exit(1);
	}
    } else {
	fprintf(stderr, "Usage: %s ?fileName?\n", argv[0]);
    }

    /*
     * Make two passes over the file. In the first pass, just check to make
     * sure we can handle everything. If there are problems, generate output
     * and stop. If everything is OK, make a second pass to actually generate
     * output.
     */

    for (writeOutput = 0; writeOutput < 2; writeOutput++) {
	lineNumber = 0;
	status = 0;
	while (fgets(line, MAX_LINE_SIZE, f) != NULL) {
	    for (p = line; *p != 0; p++) {
		if (*p == '\n') {
		    *p = 0;
		    break;
		}
	    }
	    lineNumber++;

	    if (((line[0] == '.') || (line[0] == '\'')) && (line[1] == '\\') && (line[2] == '\"')) {
		/*
		 * This line is a comment. Ignore it.
		 */

		continue;
	    }

	    if (strlen(line) >= MAX_LINE_SIZE -1) {
		fprintf(stderr, "Too long line. Max is %d chars.\n",
			MAX_LINE_SIZE - 1);
		exit(1);
	    }

	    if ((line[0] == '.') || (line[0] == '\'')) {
		/*
		 * This line is a macro invocation.
		 */

		DoMacro(line);
	    } else {
		/*
		 * This line is text, possibly with formatting characters
		 * embedded in it.
		 */

		DoText(line);
	    }
	}
	if (status != 0) {
	    break;
	}
	fseek(f, 0, SEEK_SET);
    }
    exit(status);
}

/*
 *----------------------------------------------------------------------
 *
 * DoMacro --
 *
 *	This function is called to handle a macro invocation. It parses the
 *	arguments to the macro and generates a Tcl command to handle the
 *	invocation.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	A Tcl command is written to stdout.
 *
 *----------------------------------------------------------------------
 */

static void
DoMacro(
    char *line)			/* The line of text that contains the macro
				 * invocation. */
{
    char *p, *end;
    int quote;

    /*
     * If there is no macro name, then just skip the whole line.
     */

    if ((line[1] == 0) || (isspace(line[1]))) {
	return;
    }

    PRINT(("macro"));
    if (*line != '.') {
	PRINT(("2"));
    }

    /*
     * Parse the arguments to the macro (including the name), in order.
     */

    p = line+1;
    while (1) {
	PRINTC(' ');
	if (*p == '"') {
	    /*
	     * The argument is delimited by quotes.
	     */

	    for (end = p+1; *end != '"'; end++) {
		if (*end == 0) {
		    fprintf(stderr,
			    "Unclosed quote in macro call on line %d.\n",
			    lineNumber);
		    status = 1;
		    break;
		}
	    }
	    QuoteText(p+1, (end-(p+1)));
	} else {
	    quote = 0;
	    for (end = p+1; (*end != 0) && (quote || !isspace(*end)); end++) {
		if (*end == '\'') {
		    quote = !quote;
		}
	    }
	    QuoteText(p, end-p);
	}
	if (*end == 0) {
	    break;
	}
	p = end+1;
	while (isspace(*p)) {
	    /*
	     * Skip empty space before next argument.
	     */

	    p++;
	}
	if (*p == 0) {
	    break;
	}
    }
    PRINTC('\n');
}

/*
 *----------------------------------------------------------------------
 *
 * DoText --
 *
 *	This function is called to handle a line of troff text. It parses the
 *	text, generating Tcl commands for text and for formatting stuff such
 *	as font changes.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Tcl commands are written to stdout.
 *
 *----------------------------------------------------------------------
 */

static void
DoText(
    char *line)			/* The line of text. */
{
    char *p, *end;

    /*
     * Divide the line up into pieces consisting of backslash sequences, tabs,
     * and other text.
     */

    p = line;
    while (*p != 0) {
	if (*p == '\t') {
	    PRINT(("tab\n"));
	    p++;
	} else if (*p != '\\') {
	    /*
	     * Ordinary text.
	     */

	    for (end = p+1; (*end != '\\') && (*end != 0); end++) {
		/* Empty loop body. */
	    }
	    PRINT(("text "));
	    QuoteText(p, end-p);
	    PRINTC('\n');
	    p = end;
	} else {
	    /*
	     * A backslash sequence. There are particular ones that we
	     * understand; output an error message for anything else and just
	     * ignore the backslash.
	     */

	    p++;
	    if (*p == 'f') {
		/*
		 * Font change.
		 */

		PRINT(("font %c\n", p[1]));
		p += 2;
	    } else if (*p == '-') {
		PRINT(("dash\n"));
		p++;
	    } else if (*p == 'e') {
		PRINT(("text \\\\\n"));
		p++;
	    } else if (*p == '.') {
		PRINT(("text .\n"));
		p++;
	    } else if (*p == '&') {
		p++;
	    } else if (*p == '0') {
		PRINT(("text { }\n"));
		p++;
	    } else if (*p == '(') {
		if ((p[1] == 0) || (p[2] == 0)) {
		    fprintf(stderr, "Bad \\( sequence on line %d.\n",
			    lineNumber);
		    status = 1;
		} else {
		    PRINT(("char {\\(%c%c}\n", p[1], p[2]));
		    p += 3;
		}
	    } else if (*p == 'N' && *(p+1) == '\'') {
		int ch;

		p += 2;
		sscanf(p,"%d",&ch);
		PRINT(("text \\u%04x\n", ch));
		while(*p&&*p!='\'') p++;
		p++;
	    } else if (*p != 0) {
		PRINT(("char {\\%c}\n", *p));
		p++;
	    }
	}
    }
    PRINT(("newline\n"));
}

/*
 *----------------------------------------------------------------------
 *
 * QuoteText --
 *
 *	Copy the "string" argument to stdout, adding quote characters around
 *	any special Tcl characters so that they'll just be treated as ordinary
 *	text.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Text is written to stdout.
 *
 *----------------------------------------------------------------------
 */

static void
QuoteText(
    char *string,		/* The line of text. */
    int count)			/* Number of characters to write from
				 * string. */
{
    if (count == 0) {
	PRINT(("{}"));
	return;
    }
    for ( ; count > 0; string++, count--) {
	switch (*string) {
	case '\\':
	    if (*(string+1) == 'N' && *(string+2) == '\'') {
		int ch;

		string += 3;
		count -= 3;
		sscanf(string,"%d",&ch);
		PRINT(("\\u%04x", ch));
		while(count>0&&*string!='\'') {string++;count--;}
		continue;
	    } else if (*(string+1) == '0') {
		PRINT(("\\ "));
		string++;
		count--;
		continue;
	    }
	case '$': case '[': case '{': case ' ': case ';':
	case '"': case '\t':
	    PRINTC('\\');
	default:
	    PRINTC(*string);
	}
    }
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to tools/mkVfs.tcl.

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
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
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
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













-
-
-
-
-
-
-
+
+
+
+
+
+
+















-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+



-
+

-
+




















-
+




-
+







proc cat fname {
    set fname [open $fname r]
    set data [read $fname]
    close $fname
    return $data
}

proc pkgIndexDir {root fout d1} {

    puts [format {%*sIndexing %s} [expr {4 * [info level]}] {} \
	      [file tail $d1]]
    set idx [string length $root]
    foreach ftail [glob -directory $d1 -nocomplain -tails *] {
        set f [file join $d1 $ftail]
        if {[file isdirectory $f] && [string compare CVS $ftail]} {
            pkgIndexDir $root $fout $f
        } elseif {[file tail $f] eq "pkgIndex.tcl"} {
      	    puts $fout "set dir \${VFSROOT}[string range $d1 $idx end]"
	          puts $fout [cat $f]
	      }
	set f [file join $d1 $ftail]
	if {[file isdirectory $f] && [string compare CVS $ftail]} {
	    pkgIndexDir $root $fout $f
	} elseif {[file tail $f] eq "pkgIndex.tcl"} {
	    puts $fout "set dir \${VFSROOT}[string range $d1 $idx end]"
	    puts $fout [cat $f]
	}
    }
}

###
# Script to build the VFS file system
###
proc copyDir {d1 d2} {

    puts [format {%*sCreating %s} [expr {4 * [info level]}] {} \
	      [file tail $d2]]

    file delete -force -- $d2
    file mkdir $d2

    foreach ftail [glob -directory $d1 -nocomplain -tails *] {
        set f [file join $d1 $ftail]
        if {[file isdirectory $f] && [string compare CVS $ftail]} {
            copyDir $f [file join $d2 $ftail]
        } elseif {[file isfile $f]} {
      	    file copy -force $f [file join $d2 $ftail]
	          if {$::tcl_platform(platform) eq {unix}} {
            		file attributes [file join $d2 $ftail] -permissions 0644
      	    } else {
            		file attributes [file join $d2 $ftail] -readonly 1
	          }
	      }
	set f [file join $d1 $ftail]
	if {[file isdirectory $f] && [string compare CVS $ftail]} {
	    copyDir $f [file join $d2 $ftail]
	} elseif {[file isfile $f]} {
	    file copy -force $f [file join $d2 $ftail]
	    if {$::tcl_platform(platform) eq {unix}} {
		file attributes [file join $d2 $ftail] -permissions 0o644
	    } else {
		file attributes [file join $d2 $ftail] -readonly 1
	    }
	}
    }

    if {$::tcl_platform(platform) eq {unix}} {
      	file attributes $d2 -permissions 0755
	file attributes $d2 -permissions 0o755
    } else {
	      file attributes $d2 -readonly 1
	file attributes $d2 -readonly 1
    }
}

if {[llength $argv] < 3} {
    puts "Usage: VFS_ROOT TCLSRC_ROOT PLATFORM"
    exit 1
}
set TCL_SCRIPT_DIR [lindex $argv 0]
set TCLSRC_ROOT    [lindex $argv 1]
set PLATFORM       [lindex $argv 2]
set TKDLL          [lindex $argv 3]
set TKVER          [lindex $argv 4]

puts "Building [file tail $TCL_SCRIPT_DIR] for $PLATFORM"
copyDir ${TCLSRC_ROOT}/library ${TCL_SCRIPT_DIR}

if {$PLATFORM == "windows"} {
    set ddedll [glob -nocomplain ${TCLSRC_ROOT}/win/tcldde*.dll]
    puts "DDE DLL $ddedll"
    if {$ddedll != {}} {
      	file copy $ddedll ${TCL_SCRIPT_DIR}/dde
	file copy $ddedll ${TCL_SCRIPT_DIR}/dde
    }
    set regdll [glob -nocomplain ${TCLSRC_ROOT}/win/tclreg*.dll]
    puts "REG DLL $ddedll"
    if {$regdll != {}} {
      	file copy $regdll ${TCL_SCRIPT_DIR}/reg
	file copy $regdll ${TCL_SCRIPT_DIR}/reg
    }
} else {
    # Remove the dde and reg package paths
    file delete -force ${TCL_SCRIPT_DIR}/dde
    file delete -force ${TCL_SCRIPT_DIR}/reg
}

Changes to tools/mkdepend.tcl.

1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







#==============================================================================
#
# mkdepend : generate dependency information from C/C++ files
#
# Copyright (c) 1998, Nat Pryce
# Copyright © 1998, Nat Pryce
#
# Permission is hereby granted, without written agreement and without
# license or royalty fees, to use, copy, modify, and distribute this
# software and its documentation for any purpose, provided that the
# above copyright notice and the following two paragraphs appear in
# all copies of this software.
#
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
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







-
+


















-
+

-
+



-
+



-
-
-
+
+
+




-
-
+
+


















-
+

















-
+

















-
-
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
+
+
+







#
# Results:
#	None.

proc closeOutput {} {
    global output
    if {[string match stdout $output] != 0} {
        close $output
	close $output
    }
}

# readDepends --
#
#	Read off CCP pipe for #line references.
#
# Arguments:
#	chan	The pipe channel we are reading in.
#
# Results:
#	Raw dependency list pairs.

proc readDepends {chan} {
    set line ""
    array set depends {}

    while {[gets $chan line] >= 0} {
        if {[regexp {^#line [0-9]+ \"(.*)\"$} $line dummy fname] != 0} {
	if {[regexp {^#line [0-9]+ \"(.*)\"$} $line dummy fname] != 0} {
	    set fname [file normalize $fname]
            if {![info exists target]} {
	    if {![info exists target]} {
		# this is ourself
		set target $fname
		puts stderr "processing [file tail $fname]"
            } else {
	    } else {
		# don't include ourselves as a dependency of ourself.
		if {![string compare $fname $target]} {continue}
		# store in an array so multiple occurrences are not counted.
                set depends($target|$fname) ""
            }
        }
		set depends($target|$fname) ""
	    }
	}
    }

    set result {}
    foreach n [array names depends] {
        set pair [split $n "|"]
        lappend result [list [lindex $pair 0] [lindex $pair 1]]
	set pair [split $n "|"]
	lappend result [list [lindex $pair 0] [lindex $pair 1]]
    }

    return $result
}

# writeDepends --
#
#	Write the processed list out to the file.
#
# Arguments:
#	out		The channel to write to.
#	depends		The list of dependency pairs
#
# Results:
#	None.

proc writeDepends {out depends} {
    foreach pair $depends {
        puts $out "[lindex $pair 0] : \\\n\t[join [lindex $pair 1] " \\\n\t"]"
	puts $out "[lindex $pair 0] : \\\n\t[join [lindex $pair 1] " \\\n\t"]"
    }
}

# stringStartsWith --
#
#	Compares second string to the beginning of the first.
#
# Arguments:
#	str		The string to test the beginning of.
#	prefix		The string to test against
#
# Results:
#	the result of the comparison.

proc stringStartsWith {str prefix} {
    set front [string range $str 0 [expr {[string length $prefix] - 1}]]
    return [expr {[string compare [string tolower $prefix] \
                                  [string tolower $front]] == 0}]
				  [string tolower $front]] == 0}]
}

# filterExcludes --
#
#	Remove non-project header files.
#
# Arguments:
#	depends		List of dependency pairs.
#	excludes	List of directories that should be removed
#
# Results:
#	the processed dependency list.

proc filterExcludes {depends excludes} {
    set filtered {}

    foreach pair $depends {
        set excluded 0
        set file [lindex $pair 1]
	set excluded 0
	set file [lindex $pair 1]

        foreach dir $excludes {
            if [stringStartsWith $file $dir] {
                set excluded 1
                break;
            }
        }
	foreach dir $excludes {
	    if [stringStartsWith $file $dir] {
		set excluded 1
		break;
	    }
	}

        if {!$excluded} {
            lappend filtered $pair
        }
	if {!$excluded} {
	    lappend filtered $pair
	}
    }

    return $filtered
}

# replacePrefix --
#
209
210
211
212
213
214
215
216
217


218
219
220
221
222
223
224
209
210
211
212
213
214
215


216
217
218
219
220
221
222
223
224







-
-
+
+







#
# Results:
#	The processed dependency pair list.

proc rebaseFiles {depends} {
    set rebased {}
    foreach pair $depends {
        lappend rebased [list \
                [replacePrefix [lindex $pair 0]] \
	lappend rebased [list \
		[replacePrefix [lindex $pair 0]] \
		[replacePrefix [lindex $pair 1]]]

    }
    return $rebased
}

# compressDeps --
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
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







-
+










-
+








    foreach pair $depends {
	lappend compressed([lindex $pair 0]) [lindex $pair 1]
    }

    set result [list]
    foreach n [array names compressed] {
        lappend result [list $n [lsort $compressed($n)]]
	lappend result [list $n [lsort $compressed($n)]]
    }

    return $result
}

# addSearchPath --
#
#	Adds a new set of path and replacement string to the global list.
#
# Arguments:
#	newPathInfo	comma seperated path and replacement string
#	newPathInfo	comma separated path and replacement string
#
# Results:
#	None.

proc addSearchPath {newPathInfo} {
    global srcPathList srcPathReplaceList

292
293
294
295
296
297
298
299

300
301
302
303
304
305
306
292
293
294
295
296
297
298

299
300
301
302
303
304
305
306







-
+








proc readInputListFile {objectListFile} {
    global srcFileList srcPathList source_extensions
    set f [open $objectListFile r]
    set fl [read $f]
    close $f

    # fix native path seperator so it isn't treated as an escape.
    # fix native path separator so it isn't treated as an escape.
    regsub -all {\\} $fl {/} fl

    # Treat the string as a list so filenames between double quotes are
    # treated as list elements.
    foreach fname $fl {
	# Compiled .res resource files should be ignored.
	if {[file extension $fname] ne ".obj"} {continue}

Changes to tools/regexpTestLib.tcl.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







# regexpTestLib.tcl --
#
# This file contains tcl procedures used by spencer2testregexp.tcl and
# spencer2regexp.tcl, which are programs written to convert Henry
# Spencer's test suite to tcl test files.
#
# Copyright (c) 1996 by Sun Microsystems, Inc.
# Copyright © 1996 Sun Microsystems, Inc.

proc readInputFile {} {
    global inFileName
    global lineArray

    set fileId [open $inFileName r]

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
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







-
+













-
+








    close $fileId
    return $i
}

#
# strings with embedded @'s are truncated
# unpreceeded @'s are replaced by {}
# unpreceded @'s are replaced by {}
#
proc removeAts {ls} {
    set len [llength $ls]
    set newLs {}
    foreach item $ls {
	regsub @.* $item "" newItem
	lappend newLs $newItem
    }
    return $newLs
}

proc convertErrCode {code} {

    set errMsg "couldn't compile regular expression pattern:"
    set errMsg "cannot compile regular expression pattern:"

    if {[string compare $code "INVARG"] == 0} {
	return "$errMsg invalid argument to regex routine"
    } elseif {[string compare $code "BADRPT"] == 0} {
	return "$errMsg ?+* follows nothing"
    } elseif {[string compare $code "BADBR"] == 0} {
	return "$errMsg invalid repetition count(s)"
101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115







-
+







    puts $fileId "# Commands covered:  $fcn"
    puts $fileId "#"
    puts $fileId "# This Tcl-generated file contains tests for the $fcn tcl command."
    puts $fileId "# Sourcing this file into Tcl runs the tests and generates output for"
    puts $fileId "# errors.  No output means no errors were found.  Setting VERBOSE to"
    puts $fileId "# -1 will run tests that are known to fail."
    puts $fileId "#"
    puts $fileId "# Copyright (c) 1998 Sun Microsystems, Inc."
    puts $fileId "# Copyright © 1998 Sun Microsystems, Inc."
    puts $fileId "#"
    puts $fileId "# See the file \"license.terms\" for information on usage and redistribution"
    puts $fileId "# of this file, and for a DISCLAIMER OF ALL WARRANTIES."
    puts $fileId "#"
    puts $fileId "\# SCCS: \%Z\% \%M\% \%I\% \%E\% \%U\%"
    puts $fileId "\nproc print \{arg\} \{puts \$arg\}\n"
    puts $fileId "if \{\[string compare test \[info procs test\]\] == 1\} \{"
179
180
181
182
183
184
185
186

187
188

189
190
191
192
193
194
195

196
197
198
199
200
201
202
179
180
181
182
183
184
185

186
187

188
189
190
191
192
193
194

195
196
197
198
199
200
201
202







-
+

-
+






-
+







    }

    # perform mapping if '=' flag exists

    set noBraces 0
    if {[regexp {=|>} $flags] == 1} {
	regsub -all {_} $currentLine {\\ } currentLine
	regsub -all {A} $currentLine {\\007} currentLine
	regsub -all {A} $currentLine {\\x07} currentLine
	regsub -all {B} $currentLine {\\b} currentLine
	regsub -all {E} $currentLine {\\033} currentLine
	regsub -all {E} $currentLine {\\x1B} currentLine
	regsub -all {F} $currentLine {\\f} currentLine
	regsub -all {N} $currentLine {\\n} currentLine

	# if and \r substitutions are made, do not wrap re, flags,
	# str, and result in braces

	set noBraces [regsub -all {R} $currentLine {\\\u000D} currentLine]
	set noBraces [regsub -all {R} $currentLine {\\\x0D} currentLine]
	regsub -all {T} $currentLine {\\t} currentLine
	regsub -all {V} $currentLine {\\v} currentLine
	if {[regexp {=} $flags] == 1} {
	    set re [lindex $currentLine 0]
	}
	set str [lindex $currentLine 2]
    }

Deleted tools/str2c.

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
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



























































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#! /bin/sh
#
# Transform text (.ps, .tcl,...) into a C string
#
# 1997/10 -- dl
#
# restart with tclsh \
exec tclsh "$0" ${1+"$@"}

# Max string length
# (some C compiler have a 2048 chars limits (so 2047 real chars with
#  the tariling 0) so we use 2000 to make the count nice)
set MAX 2000

if {$argc} {
    puts stderr "Usage: [file tail [info script]] < text > text.c"
    exit 1
}

set r [read stdin]

proc translate {what} {
    regsub -all {\\} $what {\\\\} what
    regsub -all {"} $what {\\"} what
    regsub -all "\n" $what "\\\\n\\\\\n" what;
    return $what;
}

set lg [string length $r]
if {$lg<$MAX} {
    puts "/*
 * Single part writeable string generated by str2c
 */
static char data\[\]=\"[translate $r]\";"
} else {
    puts "/*
 * Multi parts read only string generated by str2c
 */
static const char * const data\[\]= {"
    set n 1
    for {set i 0} {$i<$lg} {incr i $MAX} {
	set part [string range $r $i [expr {$i+$MAX-1}]]
	set len  [string length $part];
	puts "\t/* Start of part $n ($len characters) */"
	puts "\t\"[translate $part]\","
	puts "\t/* End of part $n */\n"
	incr n
    }
    puts "\tNULL\t/* End of data marker */\n};"
    puts "\n/* use for instance with:
    const char * const *chunk;
    for (chunk=data; *chunk; chunk++) {
        Tcl_AppendResult(interp, *chunk, (char *) NULL);
    }
*/"
}



Deleted tools/tcl.hpj.in.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19



















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
; This file is maintained by HCW. Do not modify this file directly.

[OPTIONS]
HCW=0
LCID=0x409 0x0 0x0 ;English (United States)
REPORT=Yes
TITLE=Tcl/Tk Reference Manual
CNT=tcl90.cnt
COPYRIGHT=Copyright © 2000 Ajuba Solutions
HLP=tcl90.hlp

[FILES]
tcl.rtf

[WINDOWS]
main="Tcl/Tk Reference Manual",,0

[CONFIG]
BrowseButtons()

Changes to tools/tclOOScript.tcl.

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
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


-
-
-
+
+
+

-
-
-
+
+
+











-
+







# tclOOScript.h --
#
# 	This file contains support scripts for TclOO. They are defined here so
# 	that the code can be definitely run even in safe interpreters; TclOO's
# 	core setup is safe.
#	This file contains support scripts for TclOO. They are defined here so
#	that the code can be definitely run even in safe interpreters; TclOO's
#	core setup is safe.
#
# Copyright (c) 2012-2018 Donal K. Fellows
# Copyright (c) 2013 Andreas Kupries
# Copyright (c) 2017 Gerald Lester
# Copyright © 2012-2019 Donal K. Fellows
# 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 {}
	namespace path {}

	# ------------------------------------------------------------------
	#
	# callback, mymethod --
	#
	#	Create a script prefix that calls a method on the current
	#	object. Same operation, two names.
84
85
86
87
88
89
90
91

92
93
94
95
96
97
98
84
85
86
87
88
89
90

91
92
93
94
95
96
97
98







-
+







	    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 {TCLOO CMDLINK FORMAT} \
		    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 \
149
150
151
152
153
154
155
156

157
158

159
160
161
162
163
164
165
149
150
151
152
153
154
155

156
157

158
159
160
161
162
163
164
165







-
+

-
+







	    return
	}
	foreach c [info class superclass $class] {
	    set d [DelegateName $c]
	    if {![info object isa class $d]} {
		continue
	    }
	    define $delegate ::oo::define::superclass -append $d
	    define $delegate ::oo::define::superclass -appendifnew $d
	}
	objdefine $class ::oo::objdefine::mixin -append $delegate
	objdefine $class ::oo::objdefine::mixin -appendifnew $delegate
    }

    # ----------------------------------------------------------------------
    #
    # UpdateClassDelegatesAfterClone --
    #
    #	Support code that is like [MixinClassDelegates] except for when a
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
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







-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+















-
-
+
+







    #
    # 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 {}} {body {}}} {
        # 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 \
    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 $body
        }
        # Make the connection by forwarding
        ::tailcall forward $name myclass $name
		[::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]
	::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
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
366
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
366
367
368

369
370
371
372
373
374
375
376







-
-
+
+











-
-
+
+












-
+












-
+




-
+





+
+
+
+
+
+
+
+
+
+
+
-
-
+
+





-
+










-
+









-
+
-
-
+

















-
+







	#
	#	Basic slot getter. Retrieves the contents of the slot.
	#	Particular slots must provide concrete non-erroring
	#	implementation.
	#
	# ------------------------------------------------------------------

	method Get {} {
	    return -code error -errorcode {TCLOO ABSTRACT_SLOT} "unimplemented"
	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 list {
	    return -code error -errorcode {TCLOO ABSTRACT_SLOT} "unimplemented"
	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 list {
	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 args {
	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 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 {} {tailcall my Set {}}
	method -prepend args {
	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 args {
	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 {args} {
	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
	}

	# Set up what is exported and what isn't
	# Hide destroy
	export -set -append -clear -prepend -remove
	unexport unknown 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.
    #
    # ----------------------------------------------------------------------

    define object method <cloned> {originObject} {
    define object method <cloned> -unexport {originObject} {
	# Copy over the procedures from the original namespace
	foreach p [info procs [info object namespace $originObject]::*] {
	    set args [info args $p]
	    set idx -1
	    foreach a $args {
		if {[info default $p $a d]} {
		    lset args [incr idx] [list $a $d]
393
394
395
396
397
398
399
400

401
402
403
404
405
406
407
403
404
405
406
407
408
409

410
411
412
413
414
415
416
417







-
+







    #
    # oo::class <cloned> --
    #
    #	Handler for cloning classes, which fixes up the delegates.
    #
    # ----------------------------------------------------------------------

    define class method <cloned> {originObject} {
    define class method <cloned> -unexport {originObject} {
	next $originObject
	# Rebuild the class inheritance delegation class
	::oo::UpdateClassDelegatesAfterClone $originObject [self]
    }

    # ----------------------------------------------------------------------
    #
417
418
419
420
421
422
423
424

425
426
427
428


429
430
431
432
433
434
435
427
428
429
430
431
432
433

434
435
436


437
438
439
440
441
442
443
444
445







-
+


-
-
+
+







	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 {TCLOO SINGLETON} \
			::return -code error -errorcode {TCL OO SINGLETON} \
			    "may not destroy a singleton object"
		    }
		    method <cloned> {originObject} {
			::return -code error -errorcode {TCLOO SINGLETON} \
		    method <cloned> -unexport {originObject} {
			::return -code error -errorcode {TCL OO SINGLETON} \
			    "may not clone a singleton object"
		    }
		}
	    }
	    return $object
	}
    }
443
444
445
446
447
448
449
450
451





























































































452
453
454
455
456
453
454
455
456
457
458
459


460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
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







-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





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

    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:
    #
    #	 * readableproperties
    #	 * writableproperties
    #	 * objreadableproperties
    #	 * objwritableproperties
    #
    #	These are all slot implementations that provide access to the C layer
    #	of property support (i.e., very fast cached lookup of property names).
    #
    #	 * StdClassProperties
    #	 * StdObjectPropertes
    #
    #	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:

Changes to tools/tclZIC.tcl.

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
30
31
32
33
34
35
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
30
31
32
33
34
35





-
+






-
+














-
+







#----------------------------------------------------------------------
#
# tclZIC.tcl --
#
#	Take the time zone data source files from Arthur Olson's
#	repository at elsie.nci.nih.gov, and prepare time zone
#	repository at https://www.iana.org/time-zones, and prepare time zone
#	information files for Tcl.
#
# Usage:
#	tclsh tclZIC.tcl inputDir outputDir
#
# Parameters:
#	inputDir - Directory (e.g., tzdata2003e) where Olson's source
#	inputDir - Directory (e.g., tzdata2022a) where Olson's source
#		   files are to be found.
#	outputDir - Directory (e.g., ../library/tzdata) where
#		    the time zone information files are to be placed.
#
# Results:
#	May produce error messages on the standard error.  An exit
#	code of zero denotes success; any other exit code is failure.
#
# This program parses the timezone data in a means analogous to the
# 'zic' command, and produces Tcl time zone information files suitable
# for loading into the 'clock' namespace.
#
#----------------------------------------------------------------------
#
# Copyright (c) 2004 by Kevin B. Kenny.	 All rights reserved.
# Copyright © 2004 Kevin B. Kenny.	 All rights reserved.
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#----------------------------------------------------------------------

# Define the names of the Olson files that we need to load.
# We avoid the solar time files and the leap seconds.

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
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







+



+
+
+
+
+
+
+
+
+
+
+
+
+







-
+







	    puts "creating directory: $dirName"
	    file mkdir $dirName
	}

	# Generate data for a zone

	set data ""
	set tzmapped {}
	foreach {
	    time offset dst name
	} [processTimeZone $zoneName $zones($zoneName)] {
	    if {$name eq "%z"} {
		# map %z to pure offset zone (e. g. offset -7200 -> -0200):
		set name [format "%+03d%02d" [expr {
				$offset / 60 / 60
			    }] [expr {
				(abs($offset) / 60) % 60
			    }]
			]
		if {![dict exists $tzmapped $offset]} { # output once per offs
		    puts "\tmap %z ($offset) -> $name"
		    dict set tzmapped $offset $name
		}
	    }
	    append data "\n    " [list [list $time $offset $dst $name]]
	}
	append data \n

	# Write the data to the information file

	set f [open $fileName w]
	fconfigure $f -translation lf
	fconfigure $f -translation lf -encoding utf-8
	puts $f "\# created by $::argv0 - do not edit"
	puts $f ""
	puts $f [list set TZData(:$zoneName) $data]
	close $f
    }

    return
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
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
1354
1355
1356
1357







-
+
















-
+







	set sourceCmd "\n    [list LoadTimeZoneFile $linkTo]\n"
	set ifCmd [list if "!\[info exists TZData($linkTo)\]" $sourceCmd]
	set setCmd "set TZData(:$zoneName) \$TZData(:$linkTo)"

	# Write the file

	set f [open $fileName w]
	fconfigure $f -translation lf
	fconfigure $f -translation lf -encoding utf-8
	puts $f "\# created by $::argv0 - do not edit"
	puts $f $ifCmd
	puts $f $setCmd
	close $f
    }

    return
}

#----------------------------------------------------------------------
#
# MAIN PROGRAM
#
#----------------------------------------------------------------------

puts "Compiling time zones -- [clock format [clock seconds] \
                                   -format {%x %X} -locale system]"
	                           -format {%x %X} -locale system]"

# Determine directories

lassign $argv inDir outDir

puts "Olson files in $inDir"
puts "Tcl files to be placed in $outDir"

Changes to tools/tcltk-man2html-utils.tcl.

1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







##
## Utility functions for Man->HTML converter. Note that these
## functions are specifically intended to work with the format as used
## by Tcl and Tk; they do not cope with arbitrary nroff markup.
##
## Copyright (c) 1995-1997 Roger E. Critchlow Jr
## Copyright (c) 2004-2011 Donal K. Fellows
## Copyright © 1995-1997 Roger E. Critchlow Jr
## Copyright © 2004-2011 Donal K. Fellows

set ::manual(report-level) 1

proc manerror {msg} {
    global manual
    set name {}
    set subj {}
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
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







-
+





-
-
+
+










-
+












-
-
-
-






-
+



-
+







-
+


-
+















+
+
+
+















-
-
+
+












+
+
+
+
-
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+
+


-
+

-
+


+











-
+


-
+


-
+


-
+


-
+







##
## templating
##
proc indexfile {} {
    if {[info exists ::TARGET] && $::TARGET eq "devsite"} {
	return "index.tml"
    } else {
	return "contents.htm"
	return "index.html"
    }
}

proc copyright {copyright {level {}}} {
    # We don't actually generate a separate copyright page anymore
    #set page "${level}copyright.htm"
    #return "<A HREF=\"$page\">Copyright</A> &#169; [htmlize-text [lrange $copyright 2 end]]"
    #set page "${level}copyright.html"
    #return "<a href=\"$page\">Copyright</a> &copy; [htmlize-text [lrange $copyright 2 end]]"
    # obfuscate any email addresses that may appear in name
    set who [string map {@ (at)} [lrange $copyright 2 end]]
    return "Copyright &copy; [htmlize-text $who]"
}

proc copyout {copyrights {level {}}} {
    set count 0
    set out "<div class=\"copy\">"
    foreach c $copyrights {
	if {$count > 0} {
	    append out <BR>
	    append out <br>
	}
	append out "[copyright $c $level]\n"
	incr count
    }
    append out "</div>"
    return $out
}

proc CSS {{level ""}} {
    return "<link rel=\"stylesheet\" href=\"${level}$::CSSFILE\" type=\"text/css\" media=\"all\">\n"
}

proc DOCTYPE {} {
    return "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"
}

proc htmlhead {title header args} {
    set level ""
    if {[lindex $args end] eq "../[indexfile]"} {
	# XXX hack - assume same level for CSS file
	set level "../"
    }
    set out "[DOCTYPE]\n<HTML>\n<HEAD><TITLE>$title</TITLE>\n[CSS $level]</HEAD>\n"
    set out "<!DOCTYPE html>\n<html lang=\"en\">\n<head><meta charset=\"utf-8\"><title>$title</title>\n[CSS $level]</head>\n"
    foreach {uptitle url} $args {
	set header "<a href=\"$url\">$uptitle</a> <small>&gt;</small> $header"
    }
    append out "<BODY><H2>$header</H2>"
    append out "<body><h2>$header</h2>"
    global manual
    if {[info exists manual(subheader)]} {
	set subs {}
	foreach {name subdir} $manual(subheader) {
	    if {$name eq $title} {
		lappend subs $name
	    } else {
		lappend subs "<A HREF=\"${level}$subdir/[indexfile]\">$name</A>"
		lappend subs "<a href=\"${level}$subdir/[indexfile]\">$name</a>"
	    }
	}
	append out "\n<H3>[join $subs { | }]</H3>"
	append out "\n<h3>[join $subs { | }]</h3>"
    }
    return $out
}

##
## parsing
##
proc unquote arg {
    return [string map [list \" {}] $arg]
}

proc parse-directive {line codename restname} {
    upvar 1 $codename code $restname rest
    return [regexp {^(\.[.a-zA-Z0-9]*) *(.*)} $line all code rest]
}

proc nospace-text {text} {
    return [regsub -all " " $text _]
}

proc htmlize-text {text {charmap {}}} {
    # contains some extras for use in nroff->html processing
    # build on the list passed in, if any
    lappend charmap \
	"&ndash;" "&ndash;" \
	{&}	{&amp;} \
	{\\}	"&#92;" \
	{\e}	"&#92;" \
	{\ }	{&nbsp;} \
	{\|}	{&nbsp;} \
	{\0}	{ } \
	\"	{&quot;} \
	{<}	{&lt;} \
	{>}	{&gt;} \
	\u201c "&#8220;" \
	\u201d "&#8221;"
	\u201C "&ldquo;" \
	\u201D "&rdquo;"

    return [string map $charmap $text]
}

proc process-text {text} {
    global manual
    # preprocess text; note that this is an incomplete map, and will probably
    # need to have things added to it as the manuals expand to use them.
    set charmap [list \
	    {\&}	"\t" \
	    {\%}	{} \
	    "\\\n"	"\n" \
	    {\(r!}	"&iexcl;" \
	    {\(ct}	"&cent;" \
	    {\(Po}	"&pound;" \
	    {\(Cs}	"&curren;" \
	    {\(+-}	"&#177;" \
	    {\(Ye}	"&yen;" \
	    {\(bb}	"&brvbar;" \
	    {\(sc}	"&sect;" \
	    {\(ad}	"&die;" \
	    {\(co}	"&copy;" \
	    {\(em}	"&#8212;" \
	    {\(en}	"&#8211;" \
	    {\(fm}	"&#8242;" \
	    {\(mc}	"&#181;" \
	    {\(mu}	"&#215;" \
	    {\(mi}	"&#8722;" \
	    {\(->}	"<font size=\"+1\">&#8594;</font>" \
	    {\(Of}	"&ordf;" \
	    {\(Fo}	"&laquo;" \
	    {\(no}	"&not;" \
	    {\(rg}	"&reg;" \
	    {\(a-}	"&macr;" \
	    {\(de}	"&deg;" \
	    {\(+-}	"&plusmn;" \
	    {\(S2}	"&sup2;" \
	    {\(S3}	"&sup3;" \
	    {\(aa}	"&acute;" \
	    {\(mc}	"&micro;" \
	    {\(ps}	"&para;" \
	    {\(pc}	"&middot;" \
	    {\(ac}	"&cedil;" \
	    {\(S1}	"&sup1;" \
	    {\(Om}	"&ordm;" \
	    {\(Fc}	"&raquo;" \
	    {\(14}	"&frac14;" \
	    {\(12}	"&frac12;" \
	    {\(34}	"&frac34;" \
	    {\(r?}	"&iquest;" \
	    {\(AE}	"&AElig;" \
	    {\(-D}	"&ETH;" \
	    {\(mu}	"&times;" \
	    {\(TP}	"&THORN;" \
	    {\(ss}	"&szlig;" \
	    {\(ae}	"&aelig;" \
	    {\(Sd}	"&eth;" \
	    {\(di}	"&divide;" \
	    {\(Tp}	"&thorn;" \
	    {\(em}	"&mdash;" \
	    {\(en}	"&ndash;" \
	    {\(fm}	"&prime;" \
	    {\(mi}	"&minus;" \
	    {\(.i}	"&imath;" \
	    {\(.j}	"&jmath;" \
	    {\(Fn}	"&fnof;" \
	    {\(OE}	"&OElig;" \
	    {\(oe}	"&oelig;" \
	    {\(IJ}	"&IJlig;" \
	    {\(ij}	"&ijlig;" \
	    {\(<-}	"<font size=\"+1\">&larr;</font>" \
	    {\(->}	"<font size=\"+1\">&rarr;</font>" \
	    {\(eu}	"&euro;" \
	    {\fP}	{\fR} \
	    {\.}	. \
	    {\(bu}	"&#8226;" \
	    {\(bu}	"&bull;" \
	    {\*(qo}	"&ocirc;" \
	    ]
    # This might make a few invalid mappings, but we don't use them
    foreach c {a e i o u y A E I O U Y} {
    foreach c {a c e g i l n o s t u y z A C E G I L N O S T U Y Z} {
	foreach {prefix suffix} {
	    o ring / slash : uml ' acute ^ circ ` grave
	    o ring / slash : uml ' acute ^ circ ` grave ~ tilde , cedil v caron
	} {
	    lappend charmap "\\\[${prefix}${c}\]" "&${c}${suffix};"
	    lappend charmap "\\(${prefix}${c}" "&${c}${suffix};"
	}
    }
    lappend charmap {\-\|\-} --        ; # two hyphens
    lappend charmap {\-} -             ; # a hyphen

    set text [htmlize-text $text $charmap]
    # General quoted entity
    regsub -all {\\N'(\d+)'} $text "\\&#\\1;" text
    while {[string first "\\" $text] >= 0} {
	# C R
	if {[regsub {^([^\\]*)\\fC([^\\]*)\\fR(.*)$} $text \
		{\1<TT>\2</TT>\3} text]} continue
		{\1<tt>\2</tt>\3} text]} continue
	# B R
	if {[regsub {^([^\\]*)\\fB([^\\]*)\\fR(.*)$} $text \
		{\1<B>\2</B>\3} text]} continue
		{\1<b>\2</b>\3} text]} continue
	# B I
	if {[regsub {^([^\\]*)\\fB([^\\]*)\\fI(.*)$} $text \
		{\1<B>\2</B>\\fI\3} text]} continue
		{\1<b>\2</b>\\fI\3} text]} continue
	# I R
	if {[regsub {^([^\\]*)\\fI([^\\]*)\\fR(.*)$} $text \
		{\1<I>\2</I>\3} text]} continue
		{\1<i>\2</i>\3} text]} continue
	# I B
	if {[regsub {^([^\\]*)\\fI([^\\]*)\\fB(.*)$} $text \
		{\1<I>\2</I>\\fB\3} text]} continue
		{\1<i>\2</i>\\fB\3} text]} continue
	# B B, I I, R R
	if {
	    [regsub {^([^\\]*)\\fB([^\\]*)\\fB(.*)$} $text \
		{\1\\fB\2\3} ntext]
	    || [regsub {^([^\\]*)\\fI([^\\]*)\\fI(.*)$} $text \
		    {\1\\fI\2\3} ntext]
	    || [regsub {^([^\\]*)\\fR([^\\]*)\\fR(.*)$} $text \
322
323
324
325
326
327
328
329
330


331
332
333
334
335
336
337
368
369
370
371
372
373
374


375
376
377
378
379
380
381
382
383







-
-
+
+







##
proc long-toc {text} {
    global manual
    set here M[incr manual(section-toc-n)]
    set manual($manual(name)-id-$text) $here
    set there L[incr manual(long-toc-n)]
    lappend manual(section-toc) \
	    "<DD><A HREF=\"$manual(name).htm#$here\" NAME=\"$there\">$text</A>"
    return "<A NAME=\"$here\">$text</A>"
	    "<dd><a href=\"$manual(name).html#$here\" name=\"[nospace-text $there]\" id=\"[nospace-text $there]\">$text</a>"
    return "<a name=\"[nospace-text $here]\" id=\"[nospace-text $here]\">$text</a>"
}

proc option-toc {name class switch} {
    global manual
    # Special case handling, oh we hate it but must do it
    if {[string match "*OPTIONS" $manual(section)]} {
	if {$manual(name) ne "ttk_widget" && ($manual(name) ne "ttk_entry" ||
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
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







-
+

-
-
+
+





-
+






-
-
+
+








-
-
+
+







    # link the defined standard option to the long table of contents and make
    # a target for the standard option references from other man pages.

    set first [lindex $switch 0]
    set here M$first
    set there L[incr manual(long-toc-n)]
    set manual(standard-option-$manual(name)-$first) \
	"<A HREF=\"$manual(name).htm#$here\">$switch, $name, $class</A>"
	"<a href=\"$manual(name).html#$here\">$switch, $name, $class</a>"
    lappend manual(section-toc) \
	"<DD><A HREF=\"$manual(name).htm#$here\" NAME=\"$there\">$switch, $name, $class</A>"
    return "<A NAME=\"$here\">$switch</A>"
	"<dd><a href=\"$manual(name).html#$here\" name=\"[nospace-text $there]\" id=\"[nospace-text $there]\">$switch, $name, $class</a>"
    return "<a name=\"[nospace-text $here]\" id=\"[nospace-text $here]\">$switch</a>"
}

proc std-option-toc {name page} {
    global manual
    if {[info exists manual(standard-option-$page-$name)]} {
	lappend manual(section-toc) <DD>$manual(standard-option-$page-$name)
	lappend manual(section-toc) <dd>$manual(standard-option-$page-$name)
	return $manual(standard-option-$page-$name)
    }
    manerror "missing reference to \"$name\" in $page.n"
    set here M[incr manual(section-toc-n)]
    set there L[incr manual(long-toc-n)]
    set other M$name
    lappend manual(section-toc) "<DD><A HREF=\"$page.htm#$other\">$name</A>"
    return "<A HREF=\"$page.htm#$other\">$name</A>"
    lappend manual(section-toc) "<dd><a href=\"$page.html#$other\">$name</a>"
    return "<a href=\"$page.html#$other\">$name</a>"
}

##
## process the widget option section
## in widget and options man pages
##
proc output-widget-options {rest} {
    global manual
    man-puts <DL>
    lappend manual(section-toc) <DL>
    man-puts <dl>
    lappend manual(section-toc) <dl>
    backup-text 1
    set para {}
    while {[next-op-is .OP rest]} {
	switch -exact -- [llength $rest] {
	    3 {
		lassign $rest switch name class
	    }
406
407
408
409
410
411
412
413
414
415
416
417





418
419
420
421
422
423
424
452
453
454
455
456
457
458





459
460
461
462
463
464
465
466
467
468
469
470







-
-
-
-
-
+
+
+
+
+







	}
	if {![regexp {^(<.>)([\w]*)(</.>)$} $name all oname name cname]} {
	    error "not Name: $name"
	}
	if {![regexp {^(<.>)([\w]*)(</.>)$} $class all oclass class cclass]} {
	    error "not Class: $class"
	}
	man-puts "$para<DT>Command-Line Name: $oswitch[option-toc $name $class $switch]$cswitch"
	man-puts "<DT>Database Name: $oname$name$cname"
	man-puts "<DT>Database Class: $oclass$class$cclass"
	man-puts <DD>[next-text]
	set para <P>
	man-puts "$para<dt>Command-Line Name: $oswitch[option-toc $name $class $switch]$cswitch"
	man-puts "<dt>Database Name: $oname$name$cname"
	man-puts "<dt>Database Class: $oclass$class$cclass"
	man-puts <dd>[next-text]
	set para <p>

	if {[next-op-is .RS rest]} {
	    while {[more-text]} {
		set line [next-text]
		if {[is-a-directive $line]} {
		    split-directive $line code rest
		    switch -exact -- $code {
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

467
468
469
470
471
472
473
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







-
-
+
+










-
+



-
+






-
+







		    }
		} else {
		    man-puts $line
		}
	    }
	}
    }
    man-puts </DL>
    lappend manual(section-toc) </DL>
    man-puts </dl>
    lappend manual(section-toc) </dl>
}

##
## process .RS lists
##
proc output-RS-list {} {
    global manual
    if {[next-op-is .IP rest]} {
	output-IP-list .RS .IP $rest
	if {[match-text .RE .sp .RS @rest .IP @rest2]} {
	    man-puts <P>$rest
	    man-puts <p>$rest
	    output-IP-list .RS .IP $rest2
	}
	if {[match-text .RE .sp .RS @rest .RE]} {
	    man-puts <P>$rest
	    man-puts <p>$rest
	    return
	}
	if {[next-op-is .RE rest]} {
	    return
	}
    }
    man-puts <DL><DD>
    man-puts <dl><dd>
    while {[more-text]} {
	set line [next-text]
	if {[is-a-directive $line]} {
	    split-directive $line code rest
	    switch -exact -- $code {
		.RE {
		    break
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



558
559

560
561
562
563
564
565
566
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
558
559
560
561
562
563

564
565
566
567

568
569


570
571
572
573





574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596

597
598

599
600



601
602
603
604

605
606
607
608
609
610
611
612







-
+










-
+





-
+












-
+



-
+

-
-
+
+


-
-
-
-
-
+
+
+
+
+


















-
+

-
+

-
-
-
+
+
+

-
+







		    output-directive $line
		}
	    }
	} else {
	    man-puts $line
	}
    }
    man-puts </DL>
    man-puts </dl>
}

##
## process .IP lists which may be plain indents,
## numeric lists, or definition lists
##
proc output-IP-list {context code rest} {
    global manual
    if {![string length $rest]} {
	# blank label, plain indent, no contents entry
	man-puts <DL><DD>
	man-puts <dl><dd>
	while {[more-text]} {
	    set line [next-text]
	    if {[is-a-directive $line]} {
		split-directive $line code rest
		if {$code eq ".IP" && $rest eq {}} {
		    man-puts "<P>"
		    man-puts "<p>"
		    continue
		}
		if {$code in {.br .DS .RS}} {
		    output-directive $line
		} else {
		    backup-text 1
		    break
		}
	    } else {
		man-puts $line
	    }
	}
	man-puts </DL>
	man-puts </dl>
    } else {
	# labelled list, make contents
	if {$context ne ".SH" && $context ne ".SS"} {
	    man-puts <P>
	    man-puts <p>
	}
	set dl "<DL class=\"[string tolower $manual(section)]\">"
	set enddl "</DL>"
	set dl "<dl class=\"[string tolower $manual(section)]\">"
	set enddl "</dl>"
	if {$code eq ".IP"} {
	    if {[regexp {^\[[\da-f]+\]|\(?[\da-f]+\)$} $rest]} {
		set dl "<OL class=\"[string tolower $manual(section)]\">"
		set enddl "</OL>"
	    } elseif {"&#8226;" eq $rest} {
		set dl "<UL class=\"[string tolower $manual(section)]\">"
		set enddl "</UL>"
		set dl "<ol class=\"[string tolower $manual(section)]\">"
		set enddl "</ol>"
	    } elseif {"&bull;" eq $rest} {
		set dl "<ul class=\"[string tolower $manual(section)]\">"
		set enddl "</ul>"
	    }
	}
	man-puts $dl
	lappend manual(section-toc) $dl
	backup-text 1
	set accept_RE 0
	set para {}
	while {[more-text]} {
	    set line [next-text]
	    if {[is-a-directive $line]} {
		split-directive $line code rest
		switch -exact -- $code {
		    .IP {
			if {$accept_RE} {
			    output-IP-list .IP $code $rest
			    continue
			}
			if {$manual(section) eq "ARGUMENTS"} {
			    man-puts "$para<DT>$rest<DD>"
			    man-puts "$para<dt>$rest<dd>"
			} elseif {[regexp {^\[([\da-f]+)\]$} $rest -> value]} {
			    man-puts "$para<LI value=\"$value\">"
			    man-puts "$para<li value=\"$value\">"
			} elseif {[regexp {^\(?([\da-f]+)\)$} $rest -> value]} {
			    man-puts "$para<LI value=\"$value\">"
			} elseif {"&#8226;" eq $rest} {
			    man-puts "$para<LI>"
			    man-puts "$para<li value=\"$value\">"
			} elseif {"&bull;" eq $rest} {
			    man-puts "$para<li>"
			} else {
			    man-puts "$para<DT>[long-toc $rest]<DD>"
			    man-puts "$para<dt>[long-toc $rest]<dd>"
			}
		    }
		    .sp - .br - .DS - .CS {
			output-directive $line
		    }
		    .RS {
			if {[match-text .RS]} {
578
579
580
581
582
583
584
585
586


587
588
589
590
591

592
593
594
595
596

597
598
599
600
601
602
603
624
625
626
627
628
629
630


631
632
633
634
635
636

637
638
639
640
641

642
643
644
645
646
647
648
649







-
-
+
+




-
+




-
+







			} else {
			    output-directive $line
			}
		    }
		    .PP {
			if {[match-text @rest1 .br @rest2 .RS]} {
			    # yet another nroff kludge as above
			    man-puts "$para<DT>[long-toc $rest1]"
			    man-puts "<DT>[long-toc $rest2]<DD>"
			    man-puts "$para<dt>[long-toc $rest1]"
			    man-puts "<dt>[long-toc $rest2]<dd>"
			    incr accept_RE 1
			} elseif {[match-text @rest .RE]} {
			    # gad, this is getting ridiculous
			    if {!$accept_RE} {
				man-puts "$enddl<P>$rest$dl"
				man-puts "$enddl<p>$rest$dl"
				backup-text 1
				set para {}
				break
			    }
			    man-puts "<P>$rest"
			    man-puts "<p>$rest"
			    incr accept_RE -1
			} elseif {$accept_RE} {
			    output-directive $line
			} else {
			    backup-text 1
			    break
			}
613
614
615
616
617
618
619
620

621
622
623
624
625
626
627
659
660
661
662
663
664
665

666
667
668
669
670
671
672
673







-
+







			backup-text 1
			break
		    }
		}
	    } else {
		man-puts $line
	    }
	    set para <P>
	    set para <p>
	}
	man-puts "$para$enddl"
	lappend manual(section-toc) $enddl
	if {$accept_RE} {
	    manerror "missing .RE in output-IP-list"
	}
    }
636
637
638
639
640
641
642
643

644
645
646
647
648
649
650
651
652
653

654
655
656
657
658
659
660
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







-
+









-
+







proc output-name {line} {
    global manual
    # split name line into pieces
    regexp {^([^-]+) - (.*)$} [regsub -all {[ \n\r\t]+} $line " "] -> head tail
    # output line to manual page untouched
    man-puts "$head &mdash; $tail"
    # output line to long table of contents
    lappend manual(section-toc) "<DL><DD>$head &mdash; $tail</DD></DL>"
    lappend manual(section-toc) "<dl><dd>$head &mdash; $tail</dd></dl>"
    # separate out the names for future reference
    foreach name [split $head ,] {
	set name [string trim $name]
	if {[llength $name] > 1} {
	    manerror "name has a space: {$name}\nfrom: $line"
	}
	lappend manual(wing-toc) $name
	lappend manual(name-$name) $manual(wing-file)/$manual(name)
    }
    set manual(tooltip-$manual(wing-file)/$manual(name).htm) $line
    set manual(tooltip-$manual(wing-file)/$manual(name).html) $line
}

##
## build a cross-reference link if appropriate
##
proc cross-reference {ref} {
    global manual remap_link_target
671
672
673
674
675
676
677
678

679
680
681
682
683
684
685
717
718
719
720
721
722
723

724
725
726
727
728
729
730
731







-
+







	}
    } elseif {$ref eq "Tcl"} {
	set lref $ref
    } elseif {
	[regexp {^[A-Z0-9 ?!]+$} $ref]
	&& [info exists manual($manname-id-$ref)]
    } {
	return "<A HREF=\"#$manual($manname-id-$ref)\">$ref</A>"
	return "<a href=\"#$manual($manname-id-$ref)\">$ref</a>"
    } else {
	set lref [string tolower $ref]
	##
	## apply a link remapping if available
	##
	if {[info exists remap_link_target($lref)]} {
	    set lref $remap_link_target($lref)
693
694
695
696
697
698
699
700

701
702
703
704
705
706
707
739
740
741
742
743
744
745

746
747
748
749
750
751
752
753







-
+







	    if {
		[regexp "^$name \[a-z0-9]*\$" $lref] &&
		[info exists manual(name-$name)] &&
		$mantail ne "$name.n" &&
		(![info exists exclude_refs_map($mantail)] ||
		$manual(name-$name) ni $exclude_refs_map($mantail))
	    } {
		return "<A HREF=\"../$manual(name-$name).htm\">$ref</A>"
		return "<a href=\"../$manual(name-$name).html\">$ref</a>"
	    }
	}
	if {$lref in {end}} {
	    # no good place to send this tcl token?
	}
	return $ref
    }
718
719
720
721
722
723
724
725

726
727
728
729
730
731

732
733
734
735

736
737
738
739
740
741
742
764
765
766
767
768
769
770

771
772
773
774
775
776

777
778
779
780

781
782
783
784
785
786
787
788







-
+





-
+



-
+







    ## multiple choices for reference
    ##
    if {[llength $manref] > 1} {
	set tcl_i [lsearch -glob $manref *TclCmd*]
	if {$tcl_i >= 0 && $manual(wing-file) eq "TclCmd"
		|| $manual(wing-file) eq "TclLib"} {
	    set tcl_ref [lindex $manref $tcl_i]
	    return "<A HREF=\"../$tcl_ref.htm\">$ref</A>"
	    return "<a href=\"../$tcl_ref.html\">$ref</a>"
	}
	set tk_i [lsearch -glob $manref *TkCmd*]
	if {$tk_i >= 0 && $manual(wing-file) eq "TkCmd"
		|| $manual(wing-file) eq "TkLib"} {
	    set tk_ref [lindex $manref $tk_i]
	    return "<A HREF=\"../$tk_ref.htm\">$ref</A>"
	    return "<a href=\"../$tk_ref.html\">$ref</a>"
	}
	if {$lref eq "exit" && $mantail eq "tclsh.1" && $tcl_i >= 0} {
	    set tcl_ref [lindex $manref $tcl_i]
	    return "<A HREF=\"../$tcl_ref.htm\">$ref</A>"
	    return "<a href=\"../$tcl_ref.html\">$ref</a>"
	}
	puts stderr "multiple cross reference to $ref in $manref from $manual(wing-file)/$mantail"
	return $ref
    }
    ##
    ## exceptions, sigh, to the rule
    ##
755
756
757
758
759
760
761
762

763
764
765
766
767
768
769
801
802
803
804
805
806
807

808
809
810
811
812
813
814
815







-
+







	&& $lref in $exclude_refs_map($mantail)
    } {
	return $ref
    }
    ##
    ## return the cross reference
    ##
    return "<A HREF=\"../$manref.htm\">$ref</A>"
    return "<a href=\"../$manref.html\">$ref</a>"
}

##
## reference generation errors
##
proc reference-error {msg text} {
    global manual
778
779
780
781
782
783
784
785

786
787
788
789
790
791
792
793
794
795
796

797
798

799
800
801
802
803
804
805
824
825
826
827
828
829
830

831
832
833
834
835
836
837
838
839
840
841

842
843

844
845
846
847
848
849
850
851







-
+










-
+

-
+







    global manual
    set result ""

    while 1 {
	##
	## we identify cross references by:
	##     ``quotation''
	##    <B>emboldening</B>
	##    <b>emboldening</b>
	##    Tcl_ prefix
	##    Tk_ prefix
	##	  [a-zA-Z0-9]+ manual entry
	## and we avoid messing with already anchored text
	##
	##
	## find where each item lives - EXPENSIVE - and accumulate a list
	##
	unset -nocomplain offsets
	foreach {name pattern} {
	    anchor     {<A }	end-anchor {</A>}
	    anchor     {<a }	end-anchor {</a>}
	    quote      {``}	end-quote  {''}
	    bold       {<B>}	end-bold   {</B>}
	    bold       {<b>}	end-bold   {</b>}
	    c.tcl      {Tcl_}
	    c.tk       {Tk_}
	    c.ttk      {Ttk_}
	    c.tdbc     {Tdbc_}
	    c.itcl     {Itcl_}
	    Tcl1       {Tcl manual entry}
	    Tcl2       {Tcl overview manual entry}
839
840
841
842
843
844
845

846


847
848
849
850
851
852
853
885
886
887
888
889
890
891
892

893
894
895
896
897
898
899
900
901







+
-
+
+







		    return [reference-error "Missing end quote" $text]
		}
		if {$invert([lindex $offsets 1]) in {tcl tk ttk}} {
		    set offsets [lreplace $offsets 1 1]
		}
		switch -exact -- $invert([lindex $offsets 1]) {
		    end-quote {
			if {$offset(quote) > 0} {
			append result [string range $text 0 [expr {$offset(quote)-1}]]
			    append result [string range $text 0 [expr {$offset(quote)-1}]]
			}
			set body [string range $text [expr {$offset(quote)+2}] \
				      [expr {$offset(end-quote)-1}]]
			set text [string range $text[set text ""] \
				      [expr {$offset(end-quote)+2}] end]
			append result `` [cross-reference $body] ''
			continue
		    }
866
867
868
869
870
871
872

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



898
899
900
901
902
903
904
905
906

907


908
909
910
911
912
913

914


915
916
917

918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938

939
940
941
942
943
944
945
946
947
948

949
950

951
952
953
954
955
956
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
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029


1030
1031
1032


1033
1034
1035
1036
1037
1038
1039
914
915
916
917
918
919
920
921


922
923
924
925
926
927
928


929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946


947
948
949
950
951
952
953
954
955
956
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
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







+
-
-
+
+
+




-
-
+
+















+
-
-
+
+
+









+
-
+
+






+
-
+
+


-
+




















-
+









-
+

-
+



















-
+


















-
+












-
+

-
+

-
+



-
+

















-
-
+
+

-
-
+
+







		    return [append result $text]
		}
		if {[string match "c.*" $invert([lindex $offsets 1])]} {
		    set offsets [lreplace $offsets 1 1]
		}
		switch -exact -- $invert([lindex $offsets 1]) {
		    url - end-bold {
			if {$offset(bold) > 0} {
			append result \
			    [string range $text 0 [expr {$offset(bold)-1}]]
			    append result \
				[string range $text 0 [expr {$offset(bold)-1}]]
			}
			set body [string range $text [expr {$offset(bold)+3}] \
				      [expr {$offset(end-bold)-1}]]
			set text [string range $text[set text ""] \
				      [expr {$offset(end-bold)+4}] end]
			regsub {http://[\w/.-]+} $body {<A HREF="&">&</A>} body
			append result <B> [cross-reference $body] </B>
			regsub {http://[\w/.-]+} $body {<a href="&">&</a>} body
			append result <b> [cross-reference $body] </b>
			continue
		    }
		    anchor {
			append result \
			    [string range $text 0 [expr {$offset(end-bold)+3}]]
			set text [string range $text[set text ""] \
				      [expr {$offset(end-bold)+4}] end]
			continue
		    }
		    default {
			return [reference-error "Uncaught bold case" $text]
		    }
		}
	    }
	    c.tk - c.ttk - c.tcl - c.tdbc - c.itcl {
		if {[lindex $offsets 0] > 0} {
		append result [string range $text 0 \
				   [expr {[lindex $offsets 0]-1}]]
		    append result [string range $text 0 \
			   [expr {[lindex $offsets 0]-1}]]
		}
		regexp -indices -start [lindex $offsets 0] {\w+} $text range
		set body [string range $text {*}$range]
		set text [string range $text[set text ""] \
			      [expr {[lindex $range 1]+1}] end]
		append result [cross-reference $body]
		continue
	    }
	    Tcl1 - Tcl2 {
		set off [lindex $offsets 0]
		if {$off > 0} {
		append result [string range $text 0 [expr {$off-1}]]
		    append result [string range $text 0 [expr {$off-1}]]
		}
		set text [string range $text[set text ""] [expr {$off+3}] end]
		append result [cross-reference Tcl]
		continue
	    }
	    url {
		set off [lindex $offsets 0]
		if {$off > 0} {
		append result [string range $text 0 [expr {$off-1}]]
		    append result [string range $text 0 [expr {$off-1}]]
		}
		regexp -indices -start $off {http://[\w/.-]+} $text range
		set url [string range $text {*}$range]
		append result "<A HREF=\"[string trimright $url .]\">$url</A>"
		append result "<a href=\"[string trimright $url .]\">$url</a>"
		set text [string range $text[set text ""] \
			      [expr {[lindex $range 1]+1}] end]
		continue
	    }
	    end-anchor - end-bold - end-quote {
		return [reference-error "Out of place $invert([lindex $offsets 0])" $text]
	    }
	}
    }
}

##
## process formatting directives
##
proc output-directive {line} {
    global manual
    # process format directive
    split-directive $line code rest
    switch -exact -- $code {
	.BS - .BE {
	    # man-puts <HR>
	    # man-puts <hr>
	}
	.SH - .SS {
	    # drain any open lists
	    # announce the subject
	    set manual(section) $rest
	    # start our own stack of stuff
	    set manual($manual(name)-$manual(section)) {}
	    lappend manual(has-$manual(section)) $manual(name)
	    if {$code ne ".SS"} {
		man-puts "<H3>[long-toc $manual(section)]</H3>"
		man-puts "<h3>[long-toc $manual(section)]</h3>"
	    } else {
		man-puts "<H4>[long-toc $manual(section)]</H4>"
		man-puts "<h4>[long-toc $manual(section)]</h4>"
	    }
	    # some sections can simply free wheel their way through the text
	    # some sections can be processed in their own loops
	    switch -exact -- [string index $code end]:$manual(section) {
		H:NAME {
		    set names {}
		    while {1} {
			set line [next-text]
			if {[is-a-directive $line]} {
			    backup-text 1
			    if {[llength $names]} {
				output-name [join $names { }]
			    }
			    return
			}
			lappend names [string trim $line]
		    }
		}
		H:SYNOPSIS {
		    lappend manual(section-toc) <DL>
		    lappend manual(section-toc) <dl>
		    while {1} {
			if {
			    [next-op-is .nf rest]
			    || [next-op-is .br rest]
			    || [next-op-is .fi rest]
			} {
			    continue
			}
			if {
			    [next-op-is .SH rest]
			    || [next-op-is .SS rest]
			    || [next-op-is .BE rest]
			    || [next-op-is .SO rest]
			} {
			    backup-text 1
			    break
			}
			if {[next-op-is .sp rest]} {
			    #man-puts <P>
			    #man-puts <p>
			    continue
			}
			set more [next-text]
			if {[is-a-directive $more]} {
			    manerror "in SYNOPSIS found $more"
			    backup-text 1
			    break
			}
			foreach more [split $more \n] {
			    regexp {^(\s*)(.*)} $more -> spaces more
			    set spaces [string map {" " "&nbsp;"} $spaces]
			    if {[string length $spaces]} {
				set spaces <TT>$spaces</TT>
				set spaces <tt>$spaces</tt>
			    }
			    man-puts $spaces$more<BR>
			    man-puts $spaces$more<br>
			    if {$manual(wing-file) in {TclLib TkLib}} {
				lappend manual(section-toc) <DD>$more
				lappend manual(section-toc) <dd>$more
			    }
			}
		    }
		    lappend manual(section-toc) </DL>
		    lappend manual(section-toc) </dl>
		    return
		}
		{H:SEE ALSO} {
		    while {[more-text]} {
			if {[next-op-is .SH rest] || [next-op-is .SS rest]} {
			    backup-text 1
			    return
			}
			set more [next-text]
			if {[is-a-directive $more]} {
			    manerror "$more"
			    backup-text 1
			    return
			}
			set nmore {}
			foreach cr [split $more ,] {
			    set cr [string trim $cr]
			    if {![regexp {^<B>.*</B>$} $cr]} {
				set cr <B>$cr</B>
			    if {![regexp {^<b>.*</b>$} $cr]} {
				set cr <b>$cr</b>
			    }
			    if {[regexp {^<B>(.*)\([13n]\)</B>$} $cr all name]} {
				set cr <B>$name</B>
			    if {[regexp {^<b>(.*)\([13n]\)</b>$} $cr all name]} {
				set cr <b>$name</b>
			    }
			    lappend nmore $cr
			}
			man-puts [join $nmore {, }]
		    }
		    return
		}
1049
1050
1051
1052
1053
1054
1055
1056

1057
1058

1059
1060
1061
1062
1063
1064
1065
1105
1106
1107
1108
1109
1110
1111

1112
1113

1114
1115
1116
1117
1118
1119
1120
1121







-
+

-
+







			    backup-text 1
			    return
			}
			set keys {}
			foreach key [split $more ,] {
			    set key [string trim $key]
			    lappend manual(keyword-$key) [list $manual(name) \
				    $manual(wing-file)/$manual(name).htm]
				    $manual(wing-file)/$manual(name).html]
			    set initial [string toupper [string index $key 0]]
			    lappend keys "<A href=\"../Keywords/$initial.htm\#$key\">$key</A>"
			    lappend keys "<a href=\"../Keywords/$initial.html\#$key\">$key</a>"
			}
			man-puts [join $keys {, }]
		    }
		    return
		}
	    }
	    if {[next-op-is .IP rest]} {
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

1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126

1127
1128

1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139

1140
1141
1142
1143
1144
1145
1146
1147
1148

1149
1150
1151

1152
1153

1154
1155

1156
1157

1158
1159

1160
1161

1162
1163

1164
1165

1166
1167

1168
1169

1170
1171

1172
1173

1174
1175

1176
1177

1178
1179

1180
1181

1182
1183

1184
1185

1186
1187

1188
1189

1190
1191

1192
1193

1194
1195

1196
1197
1198
1199
1200
1201
1202
1139
1140
1141
1142
1143
1144
1145


1146
1147
1148
1149

1150
1151


1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163

1164
1165
1166
1167
1168
1169
1170

1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181

1182
1183

1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194

1195
1196
1197
1198
1199
1200
1201
1202
1203

1204
1205
1206

1207
1208

1209
1210

1211
1212

1213
1214

1215
1216

1217
1218

1219
1220

1221
1222

1223
1224

1225
1226

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







-
-
+
+


-
+

-
-
+
+










-
+






-
+










-
+

-
+










-
+








-
+


-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+







		    manerror "unexpected .SO format:\n[expand-next-text 2]"
		}
		if {![next-op-is .SO rest]} {
		    break
		}
	    }
	    output-directive {.SH STANDARD OPTIONS}
	    man-puts <DL>
	    lappend manual(section-toc) <DL>
	    man-puts <dl>
	    lappend manual(section-toc) <dl>
	    foreach optionpair [lsort -dictionary -index 0 $optslist] {
		lassign $optionpair option targetPage
		man-puts "<DT><B>[std-option-toc $option $targetPage]</B>"
		man-puts "<dt><b>[std-option-toc $option $targetPage]</b>"
	    }
	    man-puts </DL>
	    lappend manual(section-toc) </DL>
	    man-puts </dl>
	    lappend manual(section-toc) </dl>
	}
	.OP {
	    output-widget-options $rest
	    return
	}
	.IP {
	    output-IP-list .IP .IP $rest
	    return
	}
	.PP - .sp {
	    man-puts <P>
	    man-puts <p>
	}
	.RS {
	    output-RS-list
	    return
	}
	.br {
	    man-puts <BR>
	    man-puts <br>
	    return
	}
	.DS {
	    if {[next-op-is .ta rest]} {
		# skip the leading .ta directive if it is there
	    }
	    if {[match-text @stuff .DE]} {
		set td "<td><p class=\"tablecell\">"
		set bodyText [string map [list \n <tr>$td \t $td] \n$stuff]
		man-puts "<dl><dd><table border=\"0\">$bodyText</table></dl>"
		#man-puts <PRE>$stuff</PRE>
		#man-puts <pre>$stuff</pre>
	    } elseif {[match-text .fi @ul1 @ul2 .nf @stuff .DE]} {
		man-puts "<PRE>[lindex $ul1 1][lindex $ul2 1]\n$stuff</PRE>"
		man-puts "<pre>[lindex $ul1 1][lindex $ul2 1]\n$stuff</pre>"
	    } else {
		manerror "unexpected .DS format:\n[expand-next-text 2]"
	    }
	    return
	}
	.CS {
	    if {[next-op-is .ta rest]} {
		# ???
	    }
	    if {[match-text @stuff .CE]} {
		man-puts <PRE>$stuff</PRE>
		man-puts <pre>$stuff</pre>
	    } else {
		manerror "unexpected .CS format:\n[expand-next-text 2]"
	    }
	    return
	}
	.nf {
	    if {[match-text @more .fi]} {
		foreach more [split $more \n] {
		    man-puts $more<BR>
		    man-puts $more<br>
		}
	    } elseif {[match-text .RS @more .RE .fi]} {
		man-puts <DL><DD>
		man-puts <dl><dd>
		foreach more [split $more \n] {
		    man-puts $more<BR>
		    man-puts $more<br>
		}
		man-puts </DL>
		man-puts </dl>
	    } elseif {[match-text .RS @more .RS @more2 .RE .RE .fi]} {
		man-puts <DL><DD>
		man-puts <dl><dd>
		foreach more [split $more \n] {
		    man-puts $more<BR>
		    man-puts $more<br>
		}
		man-puts <DL><DD>
		man-puts <dl><dd>
		foreach more2 [split $more2 \n] {
		    man-puts $more2<BR>
		    man-puts $more2<br>
		}
		man-puts </DL></DL>
		man-puts </dl></dl>
	    } elseif {[match-text .RS @more .RS @more2 .RE @more3 .RE .fi]} {
		man-puts <DL><DD>
		man-puts <dl><dd>
		foreach more [split $more \n] {
		    man-puts $more<BR>
		    man-puts $more<br>
		}
		man-puts <DL><DD>
		man-puts <dl><dd>
		foreach more2 [split $more2 \n] {
		    man-puts $more2<BR>
		    man-puts $more2<br>
		}
		man-puts </DL><DD>
		man-puts </dl><dd>
		foreach more3 [split $more3 \n] {
		    man-puts $more3<BR>
		    man-puts $more3<br>
		}
		man-puts </DL>
		man-puts </dl>
	    } elseif {[match-text .sp .RS @more .RS @more2 .sp .RE .RE .fi]} {
		man-puts <P><DL><DD>
		man-puts <p><dl><dd>
		foreach more [split $more \n] {
		    man-puts $more<BR>
		    man-puts $more<br>
		}
		man-puts <DL><DD>
		man-puts <dl><dd>
		foreach more2 [split $more2 \n] {
		    man-puts $more2<BR>
		    man-puts $more2<br>
		}
		man-puts </DL></DL><P>
		man-puts </dl></dl><p>
	    } elseif {[match-text .RS .sp @more .sp .RE .fi]} {
		man-puts <P><DL><DD>
		man-puts <p><dl><dd>
		foreach more [split $more \n] {
		    man-puts $more<BR>
		    man-puts $more<br>
		}
		man-puts </DL><P>
		man-puts </dl><p>
	    } else {
		manerror "ignoring $line"
	    }
	}
	.RE - .DE - .CE {
	    manerror "unexpected $code"
	    return
1211
1212
1213
1214
1215
1216
1217
1218

1219
1220
1221
1222
1223
1224
1225
1267
1268
1269
1270
1271
1272
1273

1274
1275
1276
1277
1278
1279
1280
1281







-
+







}

##
## merge copyright listings
##
proc merge-copyrights {l1 l2} {
    set merge {}
    set re1 {^Copyright +(?:\(c\)|\\\(co|&copy;) +(\w.*?)(?:all rights reserved)?(?:\. )*$}
    set re1 {^Copyright +(?:\(c\)|\\\(co|©|&copy;) +(\w.*?)(?:all rights reserved)?(?:\. )*$}
    set re2 {^(\d+) +(?:by +)?(\w.*)$}         ;# date who
    set re3 {^(\d+)-(\d+) +(?:by +)?(\w.*)$}   ;# from to who
    set re4 {^(\d+), *(\d+) +(?:by +)?(\w.*)$} ;# date1 date2 who
    foreach copyright [concat $l1 $l2] {
	if {[regexp -nocase -- $re1 $copyright -> info]} {
	    set info [string trimright $info ". "] ; # remove extra period
	    if {[regexp -- $re2 $info -> date who]} {
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
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







-
-
+
+









+




-
+

-
+







## sectionDescriptor, convert manpages into hypertext in
## the directory specified by outputDir.
##
proc make-manpage-section {outputDir sectionDescriptor} {
    global manual overall_title tcltkdesc verbose
    global excluded_pages forced_index_pages process_first_patterns

    set LQ \u201c
    set RQ \u201d
    set LQ \u201C
    set RQ \u201D

    lassign $sectionDescriptor \
	manual(wing-glob) \
	manual(wing-name) \
	manual(wing-file) \
	manual(wing-description)
    set manual(wing-copyrights) {}
    makedirhier $outputDir/$manual(wing-file)
    set manual(wing-toc-fp) [open $outputDir/$manual(wing-file)/[indexfile] w]
    fconfigure $manual(wing-toc-fp) -translation lf -encoding utf-8
    # whistle
    puts stderr "scanning section $manual(wing-name)"
    # put the entry for this section into the short table of contents
    if {[regexp {^(.+), version (.+)$} $manual(wing-name) -> name version]} {
	puts $manual(short-toc-fp) "<DT><A HREF=\"$manual(wing-file)/[indexfile]\" TITLE=\"version $version\">$name</A></DT><DD>$manual(wing-description)</DD>"
	puts $manual(short-toc-fp) "<dt><a href=\"$manual(wing-file)/[indexfile]\" title=\"version $version\">$name</a></dt><dd>$manual(wing-description)</dd>"
    } else {
	puts $manual(short-toc-fp) "<DT><A HREF=\"$manual(wing-file)/[indexfile]\">$manual(wing-name)</A></DT><DD>$manual(wing-description)</DD>"
	puts $manual(short-toc-fp) "<dt><a href=\"$manual(wing-file)/[indexfile]\">$manual(wing-name)</a></dt><dd>$manual(wing-description)</dd>"
    }
    # initialize the wing table of contents
    puts $manual(wing-toc-fp) [htmlhead $manual(wing-name) \
	    $manual(wing-name) $overall_title "../[indexfile]"]
    # initialize the short table of contents for this section
    set manual(wing-toc) {}
    # initialize the man directory for this section
1314
1315
1316
1317
1318
1319
1320

1321
1322
1323
1324
1325
1326
1327
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385







+







	    if {!$verbose} {
		puts stderr ""
	    }
	    manerror "discarding $manual(name)"
	    continue
	}
	set manual(infp) [open $manual(page)]
	fconfigure $manual(infp) -encoding utf-8
	set manual(text) {}
	set manual(partial-text) {}
	foreach p {.RS .DS .CS .SO} {
	    set manual($p) 0
	}
	set manual(stack) {}
	set manual(section) {}
1556
1557
1558
1559
1560
1561
1562
1563

1564
1565
1566
1567
1568
1569
1570
1614
1615
1616
1617
1618
1619
1620

1621
1622
1623
1624
1625
1626
1627
1628







-
+







	    set manual(wing-copyrights) [merge-copyrights \
		    $manual(wing-copyrights) $manual(copyrights)]
	}
	#
	# make the long table of contents for this page
	#
	set manual(toc-$manual(wing-file)-$manual(name)) \
	    [concat <DL> $manual(section-toc) </DL>]
	    [concat <dl> $manual(section-toc) </dl>]
    }
    if {!$verbose} {
	puts stderr ""
    }

    if {![llength $manual(wing-toc)]} {
	fatal "not table of contents."
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
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







-
-
+
+



-
+


-
+













-
+







    foreach name [lsort -dictionary $manual(wing-toc)] {
	set tail $manual(name-$name)
	if {[llength $tail] > 1} {
	    manerror "$name is defined in more than one file: $tail"
	    set tail [lindex $tail [expr {[llength $tail]-1}]]
	}
	set tail [file tail $tail]
	if {[info exists manual(tooltip-$manual(wing-file)/$tail.htm)]} {
	    set tooltip $manual(tooltip-$manual(wing-file)/$tail.htm)
	if {[info exists manual(tooltip-$manual(wing-file)/$tail.html)]} {
	    set tooltip $manual(tooltip-$manual(wing-file)/$tail.html)
	    set tooltip [string map {[ {\[} ] {\]} $ {\$} \\ \\\\} $tooltip]
	    regsub {^[^-]+-\s*(.)} $tooltip {[string totitle \1]} tooltip
	    append rows([expr {$n%$nrows}]) \
		"<td> <a href=\"$tail.htm\" title=\"[subst $tooltip]\">$name</a> </td>"
		"<td> <a href=\"$tail.html\" title=\"[subst $tooltip]\">$name</a> </td>"
	} else {
	    append rows([expr {$n%$nrows}]) \
		"<td> <a href=\"$tail.htm\">$name</a> </td>"
		"<td> <a href=\"$tail.html\">$name</a> </td>"
	}
	incr n
    }
    puts $manual(wing-toc-fp) <table>
    foreach row [lsort -integer [array names rows]] {
	puts $manual(wing-toc-fp) <tr>$rows($row)</tr>
    }
    puts $manual(wing-toc-fp) </table>

    #
    # insert wing copyrights
    #
    puts $manual(wing-toc-fp) [copyout $manual(wing-copyrights) "../"]
    puts $manual(wing-toc-fp) "</BODY></HTML>"
    puts $manual(wing-toc-fp) "</body></html>"
    close $manual(wing-toc-fp)
    set manual(merge-copyrights) \
	[merge-copyrights $manual(merge-copyrights) $manual(wing-copyrights)]
}

proc makedirhier {dir} {
    try {

Changes to tools/tcltk-man2html.tcl.

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
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







-
-
+
+








-
+













-
+







# Note well, this program is a hack rather than a piece of software
# engineering.  In that sense it's probably a good example of things
# that a scripting language, like Tcl, can do well.  It is offered as
# an example of how someone might convert a specific set of man pages
# into hypertext, not as a general solution to the problem.  If you
# try to use this, you'll be very much on your own.
#
# Copyright (c) 1995-1997 Roger E. Critchlow Jr
# Copyright (c) 2004-2010 Donal K. Fellows
# Copyright © 1995-1997 Roger E. Critchlow Jr
# Copyright © 2004-2010 Donal K. Fellows

set ::Version "50/9.0"
set ::CSSFILE "docs.css"

##
## Source the utility functions that provide most of the
## implementation of the transformation from nroff to html.
##
source [file join [file dirname [info script]] tcltk-man2html-utils.tcl]
source -encoding utf-8 [file join [file dirname [info script]] tcltk-man2html-utils.tcl]

proc getversion {tclh {name {}}} {
    if {[file exists $tclh]} {
	set chan [open $tclh]
	set data [read $chan]
	close $chan
	if {$name eq ""} {
	    set name [string toupper [file root [file tail $tclh]]]
	}
	# backslash isn't required in front of quote, but it keeps syntax
	# highlighting straight in some editors
	if {[regexp -lineanchor \
	    [string map [list @name@ $name] \
		{^#define\s+@name@_VERSION\s+\"([^.])+\.([^.\"]+)}] \
		{^#\s*define\s+@name@_VERSION\s+\"([^.])+\.([^.\"]+)}] \
	    $data -> major minor]} {
		return [list $major $minor]
	}
    }
}
proc findversion {top name useversion} {
    # Default search version is a glob pattern, switch it for string match:
63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77







-
+







	    set tclh [join [list $top1 $dirname {*}$sub ${name}.h] /]
	    set v [getversion $tclh $upper]
	    if {[llength $v]} {
		lassign $v major minor
		# to do
		#     use glob matching instead of string matching or add
		#     brace handling to [string matcch]
		if {$useversion eq {} || [string match $useversion $major.$minor]} {
		if {$useversion eq "" || [string match $useversion $major.$minor]} {
		    set top [file dirname [file dirname $tclh]]
		    set prefix [file dirname $top]
		    return [list $prefix [file tail $top] $major $minor]
		}
	    }
	}
    }
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
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







-
+





-
+



-
+







-
+


-
+




-
+



-
+







    set major ""
    set minor ""

    if {$build_tcl} {
	# Find Tcl (firstly using glob pattern / backwards compatible way)
	set tcldir [lindex [lsort [glob -nocomplain -tails -type d \
		-directory $tcltkdir tcl$useversion]] end]
	if {$tcldir ne {}} {
	if {$tcldir ne ""} {
	    # obtain version from generic header if we can:
	    lassign [getversion [file join $tcltkdir $tcldir generic tcl.h]] major minor
	} else {
	    lassign [findversion $tcltkdir tcl $useversion] tcltkdir tcldir major minor
	}
	if {$tcldir eq {} && $opt_build_tcl} {
	if {$tcldir eq "" && $opt_build_tcl} {
	    puts stderr "tcltk-man-html: couldn't find Tcl below $tcltkdir"
	    exit 1
	}
	puts "using Tcl source directory $tcltkdir $tcldir"
	puts "using Tcl source directory [file join $tcltkdir $tcldir]"
    }


    if {$build_tk} {
	# Find Tk (firstly using glob pattern / backwards compatible way)
	set tkdir [lindex [lsort [glob -nocomplain -tails -type d \
		-directory $tcltkdir tk$useversion]] end]
	if {$tkdir ne {}} {
	if {$tkdir ne ""} {
	    if {$major eq ""} {
		# obtain version from generic header if we can:
		lassign [getversion [file join $tcltkdir $tcldir generic tk.h]] major minor
		lassign [getversion [file join $tcltkdir $tkdir generic tk.h]] major minor
	    }
	} else {
	    lassign [findversion $tcltkdir tk $useversion] tcltkdir tkdir major minor
	}
	if {$tkdir eq {} && $opt_build_tk} {
	if {$tkdir eq "" && $opt_build_tk} {
	    puts stderr "tcltk-man-html: couldn't find Tk below $tcltkdir"
	    exit 1
	}
	puts "using Tk source directory $tkdir"
	puts "using Tk source directory [file join $tcltkdir $tkdir]"
    }

    puts "verbose messages are [expr {$verbose ? {on} : {off}}]"

    # the title for the man pages overall
    global overall_title
    set overall_title ""
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
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







-
+








-
+



















-
+





-
-
+
+





-
+










-
+


-
+



-
+

-
+


-
+







proc css-style args {
    upvar 1 style style
    set body [uplevel 1 [list subst [lindex $args end]]]
    set tokens [join [lrange $args 0 end-1] ", "]
    append style $tokens " \{" $body "\}\n"
}
proc css-stylesheet {} {
    set hBd "1px dotted #11577b"
    set hBd "1px dotted #11577B"

    css-style body div p th td li dd ul ol dl dt blockquote {
	font-family: Verdana, sans-serif;
    }
    css-style pre code {
	font-family: 'Courier New', Courier, monospace;
    }
    css-style pre {
	background-color:  #f6fcec;
	background-color:  #F6FCEC;
	border-top:        1px solid #6A6A6A;
	border-bottom:     1px solid #6A6A6A;
	padding:           1em;
	overflow:          auto;
    }
    css-style body {
	background-color:  #FFFFFF;
	font-size:         12px;
	line-height:       1.25;
	letter-spacing:    .2px;
	padding-left:      .5em;
    }
    css-style h1 h2 h3 h4 {
	font-family:       Georgia, serif;
	padding-left:      1em;
	margin-top:        1em;
    }
    css-style h1 {
	font-size:         18px;
	color:             #11577b;
	color:             #11577B;
	border-bottom:     $hBd;
	margin-top:        0px;
    }
    css-style h2 {
	font-size:         14px;
	color:             #11577b;
	background-color:  #c5dce8;
	color:             #11577B;
	background-color:  #C5DCE8;
	padding-left:      1em;
	border:            1px solid #6A6A6A;
    }
    css-style h3 h4 {
	color:             #1674A4;
	background-color:  #e8f2f6;
	background-color:  #E8F2F6;
	border-bottom:     $hBd;
	border-top:        $hBd;
    }
    css-style h3 {
	font-size: 12px;
    }
    css-style h4 {
	font-size: 11px;
    }
    css-style ".keylist dt" ".arguments dt" {
	width: 20em;
	width: 25em;
	float: left;
	padding: 2px;
	border-top: 1px solid #999;
	border-top: 1px solid #999999;
    }
    css-style ".keylist dt" { font-weight: bold; }
    css-style ".keylist dd" ".arguments dd" {
	margin-left: 20em;
	margin-left: 25em;
	padding: 2px;
	border-top: 1px solid #999;
	border-top: 1px solid #999999;
    }
    css-style .copy {
	background-color:  #f6fcfc;
	background-color:  #F6FCFC;
	white-space:       pre;
	font-size:         80%;
	border-top:        1px solid #6A6A6A;
	margin-top:        2em;
    }
    css-style .tablecell {
	font-size:	   12px;
325
326
327
328
329
330
331

332
333
334
335

336
337

338
339
340
341
342
343
344
325
326
327
328
329
330
331
332
333
334
335
336
337
338

339
340
341
342
343
344
345
346







+




+

-
+







##
proc make-man-pages {html args} {
    global manual overall_title tcltkdesc verbose
    global excluded_pages forced_index_pages process_first_patterns

    makedirhier $html
    set cssfd [open $html/$::CSSFILE w]
    fconfigure $cssfd -translation lf -encoding utf-8
    puts $cssfd [css-stylesheet]
    close $cssfd
    set manual(short-toc-n) 1
    set manual(short-toc-fp) [open $html/[indexfile] w]
    fconfigure $manual(short-toc-fp) -translation lf -encoding utf-8
    puts $manual(short-toc-fp) [htmlhead $overall_title $overall_title]
    puts $manual(short-toc-fp) "<DL class=\"keylist\">"
    puts $manual(short-toc-fp) "<dl class=\"keylist\">"
    set manual(merge-copyrights) {}

    foreach arg $args {
	# preprocess to set up subheader for the rest of the files
	if {![llength $arg]} {
	    continue
	}
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
442
443
444
445
446
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
442

443
444
445
446
447
448
449
450







+








-
+





-
+







-
+
+




-
+


-
-
+
+









-
+

-
+


-
+

-
+


-
+




-
+





-
-
+
+


-
+







    ##
    if {!$verbose} {
	puts stderr "Assembling index"
    }
    file delete -force -- $html/Keywords
    makedirhier $html/Keywords
    set keyfp [open $html/Keywords/[indexfile] w]
    fconfigure $keyfp -translation lf -encoding utf-8
    puts $keyfp [htmlhead "$tcltkdesc Keywords" "$tcltkdesc Keywords" \
		     $overall_title "../[indexfile]"]
    set letters {A B C D E F G H I J K L M N O P Q R S T U V W X Y Z}
    # Create header first
    set keyheader {}
    foreach a $letters {
	set keys [array names manual "keyword-\[[string totitle $a$a]\]*"]
	if {[llength $keys]} {
	    lappend keyheader "<A HREF=\"$a.htm\">$a</A>"
	    lappend keyheader "<a href=\"$a.html\">$a</a>"
	} else {
	    # No keywords for this letter
	    lappend keyheader $a
	}
    }
    set keyheader <H3>[join $keyheader " |\n"]</H3>
    set keyheader <h3>[join $keyheader " |\n"]</h3>
    puts $keyfp $keyheader
    foreach a $letters {
	set keys [array names manual "keyword-\[[string totitle $a$a]\]*"]
	if {![llength $keys]} {
	    continue
	}
	# Per-keyword page
	set afp [open $html/Keywords/$a.htm w]
	set afp [open $html/Keywords/$a.html w]
	fconfigure $afp -translation lf -encoding utf-8
	puts $afp [htmlhead "$tcltkdesc Keywords - $a" \
		       "$tcltkdesc Keywords - $a" \
		       $overall_title "../[indexfile]"]
	puts $afp $keyheader
	puts $afp "<DL class=\"keylist\">"
	puts $afp "<dl class=\"keylist\">"
	foreach k [lsort -dictionary $keys] {
	    set k [string range $k 8 end]
	    puts $afp "<DT><A NAME=\"$k\">$k</A></DT>"
	    puts $afp "<DD>"
	    puts $afp "<dt><a name=\"[nospace-text $k]\" id=\"[nospace-text $k]\">$k</a></dt>"
	    puts $afp "<dd>"
	    set refs {}
	    foreach man $manual(keyword-$k) {
		set name [lindex $man 0]
		set file [lindex $man 1]
		if {[info exists manual(tooltip-$file)]} {
		    set tooltip $manual(tooltip-$file)
		    if {[string match {*[<>""]*} $tooltip]} {
			manerror "bad tooltip for $file: \"$tooltip\""
		    }
		    lappend refs "<A HREF=\"../$file\" TITLE=\"$tooltip\">$name</A>"
		    lappend refs "<a href=\"../$file\" title=\"$tooltip\">$name</a>"
		} else {
		    lappend refs "<A HREF=\"../$file\">$name</A>"
		    lappend refs "<a href=\"../$file\">$name</a>"
		}
	    }
	    puts $afp "[join $refs {, }]</DD>"
	    puts $afp "[join $refs {, }]</dd>"
	}
	puts $afp "</DL>"
	puts $afp "</dl>"
	# insert merged copyrights
	puts $afp [copyout $manual(merge-copyrights)]
	puts $afp "</BODY></HTML>"
	puts $afp "</body></html>"
	close $afp
    }
    # insert merged copyrights
    puts $keyfp [copyout $manual(merge-copyrights)]
    puts $keyfp "</BODY></HTML>"
    puts $keyfp "</body></html>"
    close $keyfp

    ##
    ## finish off short table of contents
    ##
    puts $manual(short-toc-fp) "<DT><A HREF=\"Keywords/[indexfile]\">Keywords</A><DD>The keywords from the $tcltkdesc man pages."
    puts $manual(short-toc-fp) "</DL>"
    puts $manual(short-toc-fp) "<dt><a href=\"Keywords/[indexfile]\">Keywords</a><dd>The keywords from the $tcltkdesc man pages."
    puts $manual(short-toc-fp) "</dl>"
    # insert merged copyrights
    puts $manual(short-toc-fp) [copyout $manual(merge-copyrights)]
    puts $manual(short-toc-fp) "</BODY></HTML>"
    puts $manual(short-toc-fp) "</body></html>"
    close $manual(short-toc-fp)

    ##
    ## output man pages
    ##
    unset manual(section)
    if {!$verbose} {
464
465
466
467
468
469
470
471


472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489

490
491
492
493
494
495
496
468
469
470
471
472
473
474

475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493

494
495
496
497
498
499
500
501







-
+
+

















-
+







		incr ntoc
	    }
	    if {$verbose} {
		puts stderr "rescanning page $manual(name) $ntoc/$ntext"
	    } else {
		puts -nonewline stderr .
	    }
	    set outfd [open $html/$manual(wing-file)/$manual(name).htm w]
	    set outfd [open $html/$manual(wing-file)/$manual(name).html w]
	    fconfigure $outfd -translation lf -encoding utf-8
	    puts $outfd [htmlhead "$manual($manual(wing-file)-$manual(name)-title)" \
		    $manual(name) $wing_name "[indexfile]" \
		    $overall_title "../[indexfile]"]
	    if {($ntext > 60) && ($ntoc > 32)} {
		foreach item $toc {
		    puts $outfd $item
		}
	    } elseif {$manual(name) in $forced_index_pages} {
		if {!$verbose} {puts stderr ""}
		manerror "forcing index generation"
		foreach item $toc {
		    puts $outfd $item
		}
	    }
	    foreach item $text {
		puts $outfd [insert-cross-references $item]
	    }
	    puts $outfd "</BODY></HTML>"
	    puts $outfd "</body></html>"
	} on error msg {
	    if {$verbose} {
		puts stderr $msg
	    } else {
		puts stderr "\nError when processing $manual(name): $msg"
	    }
	} finally {
505
506
507
508
509
510
511
512
513



514
515
516

517
518
519
520
521
522
523
510
511
512
513
514
515
516


517
518
519
520
521

522
523
524
525
526
527
528
529







-
-
+
+
+


-
+








##
## Helper for assembling the descriptions of base packages (i.e., Tcl and Tk).
##
proc plus-base {var root glob name dir desc} {
    global tcltkdir
    if {$var} {
	if {[file exists $tcltkdir/$root/README]} {
	    set f [open $tcltkdir/$root/README]
	if {[file exists $tcltkdir/$root/README.md]} {
	    set f [open $tcltkdir/$root/README.md]
	    fconfigure $f -encoding utf-8
	    set d [read $f]
	    close $f
	    if {[regexp {This is the \w+ (\S+) source distribution} $d -> version]} {
	    if {[regexp {This is the \*\*\w+ (\S+)\*\* source distribution} $d -> version]} {
	       append name ", version $version"
	    }
	}
	set glob $root/$glob
	return [list $tcltkdir/$glob $name $dir $desc]
    }
}
568
569
570
571
572
573
574
575

576
577
578
579
580
581
582
574
575
576
577
578
579
580

581
582
583
584
585
586
587
588







-
+







    return $result
}

##
## Set up some special cases. It would be nice if we didn't have them,
## but we do...
##
set excluded_pages {case menubar pack-old}
set excluded_pages {}
set forced_index_pages {GetDash}
set process_first_patterns {*/ttk_widget.n */options.n}
set ensemble_commands {
    after array binary chan clock dde dict encoding file history info interp
    memory namespace package registry self string trace update zlib
    clipboard console font grab grid image option pack place selection tk
    tkwait ttk::style winfo wm itcl::delete itcl::find itcl::is
600
601
602
603
604
605
606
607
608


609
610
611
612
613
614
615
606
607
608
609
610
611
612


613
614
615
616
617
618
619
620
621







-
-
+
+







    wide()      mathfunc
    packagens   pkg::create
    pkgMkIndex  pkg_mkIndex
    pkg_mkIndex pkg_mkIndex
    Tcl_Obj     Tcl_NewObj
    Tcl_ObjType Tcl_RegisterObjType
    Tcl_OpenFileChannelProc Tcl_FSOpenFileChannel
    errorinfo 	env
    errorcode 	env
    errorinfo	env
    errorcode	env
    tcl_pkgpath env
    Tcl_Command Tcl_CreateObjCommand
    Tcl_CmdProc Tcl_CreateObjCommand
    Tcl_CmdDeleteProc Tcl_CreateObjCommand
    Tcl_ObjCmdProc Tcl_CreateObjCommand
    Tcl_Channel Tcl_OpenFileChannel
    Tcl_WideInt Tcl_NewIntObj
672
673
674
675
676
677
678
679

680
681
682
683
684
685
686
678
679
680
681
682
683
684

685
686
687
688
689
690
691
692







-
+







    ttk_menubutton.n	{flush}
    ttk_notebook.n	{image text}
    ttk_progressbar.n	{variable}
    ttk_radiobutton.n	{variable}
    ttk_scale.n		{variable}
    ttk_scrollbar.n	{set}
    ttk_spinbox.n	{format}
    ttk_treeview.n	{text open}
    ttk_treeview.n	{text open focus selection}
    ttk_widget.n	{image text variable}
    TclZlib.3		{binary flush filename text}
}
array set exclude_when_followed_by_map {
    canvas.n {
	bind widget
	focus widget
737
738
739
740
741
742
743



744



745
746
747
748
749
750
751
743
744
745
746
747
748
749
750
751
752

753
754
755
756
757
758
759
760
761
762







+
+
+
-
+
+
+







	    if {2 != [llength $description]} {
		regexp {([^0-9]*)(.*)} $dir -> n v
		set description [list $n $v]
	    }

	    # ... but try to extract (name, version) from subdir contents
	    try {
		try {
		    set f [open [file join $pkgsDir $dir configure.in]]
		} trap {POSIX ENOENT} {} {
		set f [open [file join $pkgsDir $dir configure.ac]]
		    set f [open [file join $pkgsDir $dir configure.ac]]
		}
		fconfigure $f -encoding utf-8
		foreach line [split [read $f] \n] {
		    if {2 == [scan $line \
			    { AC_INIT ( [%[^]]] , [%[^]]] ) } n v]} {
			set description [list $n $v]
			break
		    }
		}
762
763
764
765
766
767
768

769
770
771
772
773
774
775
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787







+








    # Get the list of packages to try, and what their human-readable names
    # are. Note that the package directory list should be version-less.
    try {
	set packageDirNameMap {}
	if {$build_tcl} {
	    set f [open $tcltkdir/$tcldir/pkgs/package.list.txt]
	    fconfigure $f -encoding utf-8
	    try {
		foreach line [split [read $f] \n] {
		    if {[string trim $line] eq ""} continue
		    if {[string match #* $line]} continue
		    lassign $line dir name
		    lappend packageDirNameMap $dir $name
		}
797
798
799
800
801
802
803
804

805
806

807
808
809
810
811
812
813
809
810
811
812
813
814
815

816
817

818
819
820
821
822
823
824
825







-
+

-
+







    #
    # Invoke the scraper/converter engine.
    #
    make-man-pages $webdir \
	[list $tcltkdir/{$appdir}/doc/*.1 "$tcltkdesc Applications" UserCmd \
	     "The interpreters which implement $cmdesc."] \
	[plus-base $build_tcl $tcldir doc/*.n {Tcl Commands} TclCmd \
	     "The commands which the <B>tclsh</B> interpreter implements."] \
	     "The commands which the <b>tclsh</b> interpreter implements."] \
	[plus-base $build_tk $tkdir doc/*.n {Tk Commands} TkCmd \
	     "The additional commands which the <B>wish</B> interpreter implements."] \
	     "The additional commands which the <b>wish</b> interpreter implements."] \
	{*}[plus-pkgs n {*}$packageBuildList] \
	[plus-base $build_tcl $tcldir doc/*.3 {Tcl C API} TclLib \
	     "The C functions which a Tcl extended C program may use."] \
	[plus-base $build_tk $tkdir doc/*.3 {Tk C API} TkLib \
	     "The additional C functions which a Tk extended C program may use."] \
	{*}[plus-pkgs 3 {*}$packageBuildList]
} on error {msg opts} {

Changes to tools/tsdPerf.c.

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
30
31
32

33
34
35
36
37
38
39
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
30
31

32
33
34
35
36
37
38
39


-
+









-
+


















-
+







#include <tcl.h>

extern DLLEXPORT Tcl_PackageInitProc Tsdperf_Init;
extern DLLEXPORT Tcl_LibraryInitProc Tsdperf_Init;

static Tcl_ThreadDataKey key;

typedef struct {
    Tcl_WideInt value;
} TsdPerf;


static int
tsdPerfSetObjCmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) {
tsdPerfSetObjCmd(void *cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) {
    TsdPerf *perf = Tcl_GetThreadData(&key, sizeof(TsdPerf));
    Tcl_WideInt i;

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

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

    perf->value = i;

    return TCL_OK;
}

static int
tsdPerfGetObjCmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) {
tsdPerfGetObjCmd(void *cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) {
    TsdPerf *perf = Tcl_GetThreadData(&key, sizeof(TsdPerf));


    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(perf->value));

    return TCL_OK;
}

Added tools/ucm2tests.tcl.

































































































































































































































































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# ucm2tests.tcl
#
# Parses given ucm files (from ICU) to generate test data
# for encodings.
#
#  tclsh ucm2tests.tcl PATH_TO_ICU_UCM_DIRECTORY ?OUTPUTPATH?
#

namespace eval ucm {
    # No means to change these currently but ...
    variable outputPath
    variable outputChan
    variable errorChan stderr
    variable verbose 0

    # Map Tcl encoding name to ICU UCM file name
    variable encNameMap
    array set encNameMap {
	cp1250    glibc-CP1250-2.1.2
	cp1251    glibc-CP1251-2.1.2
	cp1252    glibc-CP1252-2.1.2
	cp1253    glibc-CP1253-2.1.2
	cp1254    glibc-CP1254-2.1.2
	cp1255    glibc-CP1255-2.1.2
	cp1256    glibc-CP1256-2.1.2
	cp1257    glibc-CP1257-2.1.2
	cp1258    glibc-CP1258-2.1.2
	gb1988    glibc-GB_1988_80-2.3.3
	iso8859-1 glibc-ISO_8859_1-2.1.2
	iso8859-2 glibc-ISO_8859_2-2.1.2
	iso8859-3 glibc-ISO_8859_3-2.1.2
	iso8859-4 glibc-ISO_8859_4-2.1.2
	iso8859-5 glibc-ISO_8859_5-2.1.2
	iso8859-6 glibc-ISO_8859_6-2.1.2
	iso8859-7 glibc-ISO_8859_7-2.3.3
	iso8859-8 glibc-ISO_8859_8-2.3.3
	iso8859-9 glibc-ISO_8859_9-2.1.2
	iso8859-10 glibc-ISO_8859_10-2.1.2
	iso8859-11 glibc-ISO_8859_11-2.1.2
	iso8859-13 glibc-ISO_8859_13-2.3.3
	iso8859-14 glibc-ISO_8859_14-2.1.2
	iso8859-15 glibc-ISO_8859_15-2.1.2
	iso8859-16 glibc-ISO_8859_16-2.3.3
    }

    # Array keyed by Tcl encoding name. Each element contains mapping of
    # Unicode code point -> byte sequence for that encoding as a flat list
    # (or dictionary). Both are stored as hex strings
    variable charMap

    # Array keyed by Tcl encoding name. List of invalid code sequences
    # each being a hex string.
    variable invalidCodeSequences

    # Array keyed by Tcl encoding name. List of unicode code points that are
    # not mapped, each being a hex string.
    variable unmappedCodePoints

    # The fallback character per encoding
    variable encSubchar
}

proc ucm::abort {msg} {
    variable errorChan
    puts $errorChan $msg
    exit 1
}
proc ucm::warn {msg} {
    variable errorChan
    puts $errorChan $msg
}
proc ucm::log {msg} {
    variable verbose
    if {$verbose} {
	variable errorChan
	puts $errorChan $msg
    }
}
proc ucm::print {s} {
    variable outputChan
    puts $outputChan $s
}

proc ucm::parse_SBCS {encName fd} {
    variable charMap
    variable invalidCodeSequences
    variable unmappedCodePoints

    set result {}
    while {[gets $fd line] >= 0} {
	if {[string match #* $line]} {
	    continue
	}
	if {[string equal "END CHARMAP" [string trim $line]]} {
	    break
	}
	if {![regexp {^\s*<U([[:xdigit:]]{4})>\s*((\\x[[:xdigit:]]{2})+)\s*(\|(0|1|2|3|4))} $line -> unichar bytes - - precision]} {
	    error "Unexpected line parsing SBCS: $line"
	}
	set bytes [string map {\\x {}} $bytes]; # \xNN -> NN
	if {$precision eq "" || $precision eq "0"} {
	    lappend result $unichar $bytes
	} else {
	    # It is a fallback mapping - ignore
	}
    }
    set charMap($encName) $result

    # Find out invalid code sequences and unicode code points that are not mapped
    set valid {}
    set mapped {}
    foreach {unich bytes} $result {
	lappend mapped $unich
	lappend valid $bytes
    }
    set invalidCodeSequences($encName) {}
    for {set i 0} {$i <= 255} {incr i} {
	set hex [format %.2X $i]
	if {[lsearch -exact $valid $hex] < 0} {
	    lappend invalidCodeSequences($encName) $hex
	}
    }

    set unmappedCodePoints($encName) {}
    for {set i 0} {$i <= 65535} {incr i} {
	set hex [format %.4X $i]
	if {[lsearch -exact $mapped $hex] < 0} {
	    lappend unmappedCodePoints($encName) $hex
	    # Only look for (at most) one below 256 and one above 1024
	    if {$i < 255} {
		# Found one so jump past 8 bits
		set i 255
	    } else {
		break
	    }
	}
	if {$i == 255} {
	    set i 1023
	}
    }
    lappend unmappedCodePoints($encName) D800 DC00 10000 10FFFF
}

proc ucm::generate_boilerplate {} {
    # Common procedures
    print {
# This file is automatically generated by ucm2tests.tcl.
# Edits will be overwritten on next generation.
#
# Generates tests comparing Tcl encodings to ICU.
# The generated file is NOT standalone. It should be sourced into a test script.

proc ucmConvertfromMismatches {enc map} {
    set mismatches {}
    foreach {unihex hex} $map {
	set unihex [string range 00000000$unihex end-7 end]; # Make 8 digits
	set unich [subst "\\U$unihex"]
	if {[encoding convertfrom -profile strict $enc [binary decode hex $hex]] ne $unich} {
	    lappend mismatches "<[printable $unich],$hex>"
	}
    }
    return $mismatches
}
proc ucmConverttoMismatches {enc map} {
    set mismatches {}
    foreach {unihex hex} $map {
	set unihex [string range 00000000$unihex end-7 end]; # Make 8 digits
	set unich [subst "\\U$unihex"]
	if {[encoding convertto -profile strict $enc $unich] ne [binary decode hex $hex]} {
	    lappend mismatches "<[printable $unich],$hex>"
	}
    }
    return $mismatches
}
if {[info commands printable] eq ""} {
    proc printable {s} {
	set print ""
	foreach c [split $s ""] {
	    set i [scan $c %c]
	    if {[string is print $c] && ($i <= 127)} {
		append print $c
	    } elseif {$i <= 0xff} {
		append print \\x[format %02X $i]
	    } elseif {$i <= 0xffff} {
		append print \\u[format %04X $i]
	    } else {
		append print \\U[format %08X $i]
	    }
	}
	return $print
    }
}
    }
} ; # generate_boilerplate

proc ucm::generate_tests {} {
    variable encNameMap
    variable charMap
    variable invalidCodeSequences
    variable unmappedCodePoints
    variable outputPath
    variable outputChan
    variable encSubchar

    if {[info exists outputPath]} {
	set outputChan [open $outputPath w]
	fconfigure $outputChan -translation lf
    } else {
	set outputChan stdout
    }

    array set tclNames {}
    foreach encName [encoding names] {
	set tclNames($encName) ""
    }

    generate_boilerplate
    foreach encName [lsort -dictionary [array names encNameMap]] {
	if {![info exists charMap($encName)]} {
	    warn "No character map read for $encName"
	    continue
	}
	unset tclNames($encName)

	# Print the valid tests
	print "\n#\n# $encName (generated from $encNameMap($encName))"
	print "\ntest encoding-convertfrom-ucmCompare-$encName {Compare against ICU UCM} -body \{"
	print "    ucmConvertfromMismatches $encName {$charMap($encName)}"
	print "\} -result {}"
	print "\ntest encoding-convertto-ucmCompare-$encName {Compare against ICU UCM} -body \{"
	print "    ucmConverttoMismatches $encName {$charMap($encName)}"
	print "\} -result {}"
	if {0} {
	    # This will generate individual tests for every char
	    # and test in lead, tail, middle, solo configurations
	    # but takes considerable time
	    print "lappend encValidStrings \{*\}\{"
	    foreach {unich hex} $charMap($encName) {
		print "    $encName \\u$unich $hex {} {}"
	    }
	    print "\}; # $encName"
	}

	# Generate the invalidity checks
	print "\n# $encName - invalid byte sequences"
	print "lappend encInvalidBytes \{*\}\{"
	foreach hex $invalidCodeSequences($encName) {
	    # Map XXXX... to \xXX\xXX...
	    set uhex [regsub -all .. $hex {\\x\0}]
	    set uhex \\U[string range 00000000$hex end-7 end]
	    print "    $encName $hex tcl8    $uhex -1 {} {}"
	    print "    $encName $hex replace \\uFFFD -1 {} {}"
	    print "    $encName $hex strict  {}       0 {} {}"
	}
	print "\}; # $encName"

	print "\n# $encName - invalid byte sequences"
	print "lappend encUnencodableStrings \{*\}\{"
	if {[info exists encSubchar($encName)]} {
	    set subchar $encSubchar($encName)
	} else {
	    set subchar "3F"; # Tcl uses ? by default
	}
	foreach hex $unmappedCodePoints($encName) {
	    set uhex \\U[string range 00000000$hex end-7 end]
	    print "    $encName $uhex tcl8    $subchar -1 {} {}"
	    print "    $encName $uhex replace $subchar -1 {} {}"
	    print "    $encName $uhex strict  {}                      0 {} {}"
	}
	print "\}; # $encName"
    }

    if {[array size tclNames]} {
	warn "Missing encoding: [lsort [array names tclNames]]"
    }
    if {[info exists outputPath]} {
	close $outputChan
	unset outputChan
    }
}

proc ucm::parse_file {encName ucmPath} {
    variable charMap
    variable encSubchar

    set fd [open $ucmPath]
    try {
	# Parse the metadata
	unset -nocomplain state
	while {[gets $fd line] >= 0} {
	    if {[regexp {<(code_set_name|mb_cur_max|mb_cur_min|uconv_class|subchar)>\s+(\S+)} $line -> key val]} {
		set state($key) $val
	    } elseif {[regexp {^\s*CHARMAP\s*$} $line]} {
		set state(charmap) ""
		break
	    } else {
		# Skip all else
	    }
	}
	if {![info exists state(charmap)]} {
	    abort "Error: $ucmPath has No CHARMAP line."
	}
	foreach key {code_set_name uconv_class} {
	    if {[info exists state($key)]} {
		set state($key) [string trim $state($key) {"}]
	    }
	}
	if {[info exists charMap($encName)]} {
	    abort "Duplicate file for $encName ($path)"
	}
	if {![info exists state(uconv_class)]} {
	    abort "Error: $ucmPath has no uconv_class definition."
	}
	if {[info exists state(subchar)]} {
	    # \xNN\xNN.. -> NNNN..
	    set encSubchar($encName) [string map {\\x {}} $state(subchar)]
	}
	switch -exact -- $state(uconv_class) {
	    SBCS {
		if {[catch {
		    parse_SBCS $encName $fd
		} result]} {
		    abort "Could not process $ucmPath. $result"
		}
	    }
	    default {
		log "Skipping $ucmPath -- not SBCS encoding."
		return
	    }
	}
    } finally {
	close $fd
    }
}

proc ucm::run {} {
    variable encNameMap
    variable outputPath
    switch [llength $::argv] {
	2 {set outputPath [lindex $::argv 1]}
	1 {}
	default {
	    abort "Usage: [info nameofexecutable] $::argv0 path/to/icu/ucm/data ?outputfile?"
	}
    }
    foreach {encName fname} [array get encNameMap] {
	ucm::parse_file $encName [file join [lindex $::argv 0] ${fname}.ucm]
    }
    generate_tests
}

ucm::run

Changes to tools/uniClass.tcl.

59
60
61
62
63
64
65
66

67
68
69




70
71
72
73
74
75
76
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80







-
+



+
+
+
+







    set ranges "    "
    set numranges 0
    set chars "    "
    set numchars 0
    set extchars 0
    set extranges 0

    for {set i 0} {$i <= 0x10FFFF} {incr i} {
    for {set i 0} {$i <= 0xEFFFF} {incr i} {
	if {$i == 0xD800} {
	    # Skip surrogates
	    set i 0xE000
	}
	if {$i == 0xE000} {
	    # Skip private
	    set i 0xF900
	}
	if {[string is $type [format %c $i]]} {
	    if {$i == ($last + 1)} {
		set last $i
	    } else {
		if {$first >= 0} {
		    emitRange $first $last
88
89
90
91
92
93
94
95

96
97
98
99
100
101

102
103
104
105
106
107
108
92
93
94
95
96
97
98

99
100
101
102
103
104

105
106
107
108
109
110
111
112







-
+





-
+







    }
    set chars  [string trimright $chars "\t\n ,"]
    if {$extchars} {
	append chars "\n#endif"
    }
    if {$ranges ne ""} {
	puts "static const crange ${type}RangeTable\[\] = {\n$ranges\n};\n"
	puts "#define NUM_[string toupper $type]_RANGE (sizeof(${type}RangeTable)/sizeof(crange))\n"
	puts "#define NUM_[string toupper $type]_RANGE ((int)(sizeof(${type}RangeTable)/sizeof(crange)))\n"
    } else {
	puts "/* no contiguous ranges of $type characters */\n"
    }
    if {$chars ne ""} {
	puts "static const chr ${type}CharTable\[\] = {\n$chars\n};\n"
	puts "#define NUM_[string toupper $type]_CHAR (sizeof(${type}CharTable)/sizeof(chr))\n"
	puts "#define NUM_[string toupper $type]_CHAR ((int)(sizeof(${type}CharTable)/sizeof(chr)))\n"
    } else {
	puts "/*\n * no singletons of $type characters.\n */\n"
    }
}

puts "/*
 *	Declarations of Unicode character ranges.  This code

Changes to tools/uniParse.tcl.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







# uniParse.tcl --
#
#	This program parses the UnicodeData file and generates the
#	corresponding tclUniData.c file with compressed character
#	data tables.  The input to this program should be the latest
#	UnicodeData file from:
#	    ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright © 1998-1999 Scriptics Corporation.
# All rights reserved.


namespace eval uni {
    set shift 5;		# number of bits of data within a page
				# This value can be adjusted to find the
				# best split to minimize table size
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188

189
190
191
192
193
194
195
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187

188
189
190
191
192
193
194
195







-
+







-
+








    buildTables $data
    puts "X = [llength $pMap]  Y= [llength $pages]  A= [llength $groups]"
    set size [expr {[llength $pMap]*2 + ([llength $pages]<<$shift)}]
    puts "shift = $shift, space = $size"

    set f [open [file join [lindex $argv 1] tclUniData.c] w]
    fconfigure $f -translation lf
    fconfigure $f -translation lf -encoding utf-8
    puts $f "/*
 * tclUniData.c --
 *
 *	Declarations of Unicode character information tables.  This file is
 *	automatically generated by the tools/uniParse.tcl script.  Do not
 *	modify this file by hand.
 *
 * Copyright (c) 1998 by Scriptics Corporation.
 * Copyright © 1998 Scriptics Corporation.
 * All rights reserved.
 */

/*
 * A 16-bit Unicode character is split into two parts in order to index
 * into the following tables.  The lower OFFSET_BITS comprise an offset
 * into a page of characters.  The upper bits comprise the page number.

Added tools/valgrind_check_success.































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
30
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#! /usr/bin/env tclsh


proc main {sourcetype source} {
	switch $sourcetype {
		file {
			set chan [open $source]
			try {
				set data [read $chan]
			} finally {
				close $chan
			}
		}
		string {
			set data $source
		}
		default {
			error [list {wrong # args}]
		}
	}
	set found [regexp -inline -all {blocks are\
	    (?:(?:(?:definitely|indirectly|possibly) lost)|still reachable)} $data]
	if {[llength $found]} {
		puts 0
	} else {
		puts 1
	}
	flush stdout
}
main {*}$argv

Changes to tools/valgrind_suppress.















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
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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+













+
+
+
+
+
+
+
+
+
+






+
+
+
+
+
+
+
+
+
+
+
+
+







#{
#    Tcl_GetChannelOption/TcpGetOptionProc/TcphostPortList/getnameinfo/gethostbyaddr_r
#    Memcheck:Leak
#    match-leak-kinds: reachable
#    fun:malloc
#    fun:strdup
#    ...
#    fun:module_load
#    ...
#    fun:getnameinfo
#    ...
#    fun:Tcl_GetChannelOption
#}

{
   TclCreatesocketAddress/getaddrinfo/calloc
   Memcheck:Leak
   match-leak-kinds: reachable
   fun:calloc
   ...
   fun:getaddrinfo
   fun:TclCreateSocketAddress
}

{
   TclCreatesocketAddress/getaddrinfo/malloc
   Memcheck:Leak
   match-leak-kinds: definite
   fun:malloc
   ...
   fun:getaddrinfo
   fun:TclCreateSocketAddress
}

{
   TclCreatesocketAddress/getaddrinfo/malloc
   Memcheck:Leak
   match-leak-kinds: reachable
   fun:malloc
   ...
   fun:getaddrinfo
   fun:TclCreateSocketAddress
}

{
   TclpDlopen/decompose_rpath
   Memcheck:Leak
   match-leak-kinds: reachable
   fun:malloc
   ...
   fun:decompose_rpath
   ...
   fun:dlopen_doit
   ...
   fun:TclpDlopen
}

{
   TclpDlopen/load
   Memcheck:Leak
   match-leak-kinds: reachable
   fun:calloc
   ...
67
68
69
70
71
72
73








































74
75
76
77
78
79
80
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







   fun:malloc
   ...
   fun:_nss_systemd_getgrnam_r
   ...
   fun:TclpGetGrNam
}

{
    TclpGeHostByName/gethostbyname_r/strdup/malloc
    Memcheck:Leak
    match-leak-kinds: reachable
    fun:malloc
    fun:strdup
    ...
    fun:dl_open_worker
    ...
    fun:do_dlopen
    ...
    fun:TclpGetHostByName
}

{
    TclpGeHostByName/gethostbyname_r/calloc
    Memcheck:Leak
    match-leak-kinds: reachable
    fun:calloc
    ...
    fun:dl_open_worker
    ...
    fun:do_dlopen
    ...
    fun:TclpGetHostByName
}

{
    TclpGeHostByName/gethostbyname_r/malloc
    Memcheck:Leak
    match-leak-kinds: reachable
    fun:malloc
    ...
    fun:dl_open_worker
    ...
    fun:do_dlopen
    ...
    fun:TclpGetHostByName
}

{
   TclpGetPwNam/getpwname_r/__nss_next2/calloc
   Memcheck:Leak
   match-leak-kinds: reachable
   fun:calloc
   ...
   fun:__nss_next2
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+















+
+
+
+
+
+
+
+
+
+





   fun:malloc
   ...
   fun:_nss_systemd_getpwnam_r
   ...
   fun:TclpGetPwNam
}

{
    TclpGetGrGid/getgrgid_r/tls_get_addr_tail
    Memcheck:Leak
    match-leak-kinds: reachable
    fun:malloc
    ...
    fun:tls_get_addr_tail
    ...
    fun:TclpGetGrGid
}

{
    TclpGetGrGid/getgrgid_r/module_load
    Memcheck:Leak
    match-leak-kinds: reachable
    fun:calloc
    ...
    fun:module_load
    ...
    fun:TclpGetGrGid
}

{
    TclpGetGrGid/getgrgid_r/module_load
    Memcheck:Leak
    match-leak-kinds: reachable
    fun:malloc
    ...
    fun:module_load
    ...
    fun:TclpGetGrGid
}

{
    TcphostPortList/getnameinfo/module_load/calloc
    Memcheck:Leak
    match-leak-kinds: definite,reachable
    fun:calloc
    ...
    fun:dl_open_worker_begin
    ...
    fun:module_load
    ...
    fun:getnameinfo
    fun:TcpHostPortList
}

{
    # see sourceware glibc Bug 14984 - getnameinfo() might be leaking memory
    TcphostPortList/getnameinfo/module_load/mallco
    Memcheck:Leak
    match-leak-kinds: definite,reachable
    fun:malloc
    ...
    fun:dl_open_worker_begin
    ...
    fun:module_load
    ...
    fun:getnameinfo
    fun:TcpHostPortList
}

{
	TclpThreadExit/pthread_exit/calloc
    Memcheck:Leak
    match-leak-kinds: reachable
	fun:calloc
	...
	fun:pthread_exit
	fun:TclpThreadExit
}

{
	TclpThreadExit/pthread_exit/malloc
    Memcheck:Leak
    match-leak-kinds: reachable
	fun:malloc
	...
	fun:pthread_exit
	fun:TclpThreadExit
}

{
	TclpThreadExit/pthread_exit/malloc
    Memcheck:Leak
    match-leak-kinds: definite
	fun:malloc
	...
	fun:pthread_exit
	fun:TclpThreadExit
}

Changes to unix/Makefile.in.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







#
# This file is a Makefile for Tcl. If it has the name "Makefile.in" then it is
# a template for a Makefile; to generate the actual Makefile, run
# "./configure", which is a configuration script generated by the "autoconf"
# program (constructs like "@foo@" will get replaced in the actual Makefile.

VERSION 		= @TCL_VERSION@
VERSION			= @TCL_VERSION@
MAJOR_VERSION		= @TCL_MAJOR_VERSION@
MINOR_VERSION		= @TCL_MINOR_VERSION@
PATCH_LEVEL		= @TCL_PATCH_LEVEL@

#--------------------------------------------------------------------------
# Things you can change to personalize the Makefile for your own site (you can
# make these changes in either Makefile.in or Makefile, but changes to
146
147
148
149
150
151
152
153
154


155
156
157
158
159
160
161
146
147
148
149
150
151
152


153
154
155
156
157
158
159
160
161







-
-
+
+







SHELL			= @MAKEFILE_SHELL@

# Tcl used to let the configure script choose which program to use for
# installing, but there are just too many different versions of "install"
# around; better to use the install-sh script that comes with the
# distribution, which is slower but guaranteed to work.

INSTALL_STRIP_PROGRAM	= -s
INSTALL_STRIP_LIBRARY	= -S -x
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

172
173
174
175
176
177
178
179

180
181
182
183
184
185
186
172
173
174
175
176
177
178

179
180
181
182
183
184
185
186







-
+







# The symbols below provide support for dynamic loading and shared libraries.
# See configure.ac for a description of what the symbols mean. The values of
# the symbols are normally set by the configure script. You shouldn't normally
# need to modify any of these definitions by hand.

STLIB_LD		= @STLIB_LD@
SHLIB_LD		= @SHLIB_LD@
SHLIB_CFLAGS		= @SHLIB_CFLAGS@ -DBUILD_tcl
SHLIB_CFLAGS		= @SHLIB_CFLAGS@
SHLIB_LD_LIBS		= @SHLIB_LD_LIBS@
SHLIB_LD_FLAGS		= @SHLIB_LD_FLAGS@
TCL_SHLIB_LD_EXTRAS	= @TCL_SHLIB_LD_EXTRAS@

SHLIB_SUFFIX		= @SHLIB_SUFFIX@

DLTEST_TARGETS		= dltest.marker
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
205
206
207
208
209
210
211

212
213
214
215
216
217
218
219







-
+







# Generic lib name used in rules that apply to tcl and tk
LIB_FILE		= ${TCL_LIB_FILE}

TCL_LIB_FLAG		= @TCL_LIB_FLAG@
#TCL_LIB_FLAG		= -ltcl

# support for embedded libraries on Darwin / Mac OS X
DYLIB_INSTALL_DIR	= ${LIB_RUNTIME_DIR}
DYLIB_INSTALL_DIR	= $(libdir)

#--------------------------------------------------------------------------
# The information below is modified by the configure script when Makefile is
# generated from Makefile.in. You shouldn't normally modify any of this stuff
# by hand.
#--------------------------------------------------------------------------

231
232
233
234
235
236
237
238

239
240
241
242
243
244
245
231
232
233
234
235
236
237

238
239
240
241
242
243
244
245







-
+







TOOL_DIR		= $(TOP_DIR)/tools
UNIX_DIR		= $(TOP_DIR)/unix
MAC_OSX_DIR		= $(TOP_DIR)/macosx
PKGS_DIR		= $(TOP_DIR)/pkgs
# Must be absolute because of the cd dltest $(DLTEST_DIR)/configure below.
DLTEST_DIR		= @TCL_SRC_DIR@/unix/dltest
# Must be absolute to so the corresponding tcltest's tcl_library is absolute.
TCL_BUILDTIME_LIBRARY	= @TCL_SRC_DIR@/library
TCL_BUILDTIME_LIBRARY	= @TCL_BUILDTIME_LIBRARY@

ZLIB_DIR		= ${COMPAT_DIR}/zlib
ZLIB_INCLUDE		= @ZLIB_INCLUDE@
TOMMATH_DIR		= $(TOP_DIR)/libtommath
TOMMATH_INCLUDE		= @TOMMATH_INCLUDE@

CC			= @CC@
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
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







+









-
-
+
+

-
+

-
+









-
+


-
+
+


-
-
+
+




+
-
+






-
+






-
+







-
+







-
-
-
+
+
+



-
+





+
+







GDB			= gdb
LLDB			= lldb
TRACE			= strace
TRACE_OPTS		=
VALGRIND		= valgrind
VALGRINDARGS		= --tool=memcheck --num-callers=24 \
	--leak-resolution=high --leak-check=yes --show-reachable=yes -v \
	--keep-debuginfo=yes \
	--suppressions=$(TOOL_DIR)/valgrind_suppress

#--------------------------------------------------------------------------
# The information below should be usable as is. The configure script won't
# modify it and you shouldn't need to modify it either.
#--------------------------------------------------------------------------

STUB_CC_SWITCHES = -I"${BUILD_DIR}" -I${UNIX_DIR} -I${GENERIC_DIR} -I${TOMMATH_DIR} \
	${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} \
	${AC_FLAGS} ${ENV_FLAGS} ${EXTRA_CFLAGS} \
	@EXTRA_CC_SWITCHES@
	${AC_FLAGS} ${ENV_FLAGS} ${EXTRA_CFLAGS} @EXTRA_CC_SWITCHES@ \
	${NO_DEPRECATED_FLAGS} -DMP_FIXED_CUTOFFS

CC_SWITCHES = $(STUB_CC_SWITCHES) ${NO_DEPRECATED_FLAGS} -DMP_FIXED_CUTOFFS -DMP_NO_STDINT
CC_SWITCHES = $(STUB_CC_SWITCHES) -DBUILD_tcl

APP_CC_SWITCHES = $(CC_SWITCHES) @EXTRA_APP_CC_SWITCHES@
APP_CC_SWITCHES = $(STUB_CC_SWITCHES) @EXTRA_APP_CC_SWITCHES@

LIBS		= @TCL_LIBS@

DEPEND_SWITCHES	= ${CFLAGS} -I${UNIX_DIR} -I${GENERIC_DIR} \
	${AC_FLAGS} ${EXTRA_CFLAGS} @EXTRA_CC_SWITCHES@

TCLSH_OBJS = tclAppInit.o

TCLTEST_OBJS = tclTestInit.o tclTest.o tclTestObj.o tclTestProcBodyObj.o \
	tclThreadTest.o tclUnixTest.o
	tclThreadTest.o tclUnixTest.o tclTestABSList.o

XTTEST_OBJS = xtTestInit.o tclTest.o tclTestObj.o tclTestProcBodyObj.o \
	tclThreadTest.o tclUnixTest.o tclXtNotify.o tclXtTest.o
	tclThreadTest.o tclUnixTest.o tclXtNotify.o tclXtTest.o \
	tclTestABSList.o

GENERIC_OBJS = regcomp.o regexec.o regfree.o regerror.o tclAlloc.o \
	tclAssembly.o tclAsync.o tclBasic.o tclBinary.o tclCkalloc.o \
	tclClock.o tclCmdAH.o tclCmdIL.o tclCmdMZ.o \
	tclArithSeries.o tclAssembly.o tclAsync.o tclBasic.o tclBinary.o \
	tclCkalloc.o tclClock.o tclClockFmt.o tclCmdAH.o tclCmdIL.o tclCmdMZ.o \
	tclCompCmds.o tclCompCmdsGR.o tclCompCmdsSZ.o tclCompExpr.o \
	tclCompile.o tclConfig.o tclDate.o tclDictObj.o tclDisassemble.o \
	tclEncoding.o tclEnsemble.o \
	tclEnv.o tclEvent.o tclExecute.o tclFCmd.o tclFileName.o tclGet.o \
	tclHash.o tclHistory.o \
	tclHash.o tclHistory.o tclIndexObj.o tclInterp.o tclIO.o tclIOCmd.o \
	tclIcu.o tclIndexObj.o tclInterp.o tclIO.o tclIOCmd.o \
	tclIORChan.o tclIORTrans.o tclIOGT.o tclIOSock.o tclIOUtil.o \
	tclLink.o tclListObj.o \
	tclLiteral.o tclLoad.o tclMain.o tclNamesp.o tclNotify.o \
	tclObj.o tclOptimize.o tclPanic.o tclParse.o tclPathObj.o tclPipe.o \
	tclPkg.o tclPkgConfig.o tclPosixStr.o \
	tclPreserve.o tclProc.o tclProcess.o tclRegexp.o \
	tclResolve.o tclResult.o tclScan.o tclStringObj.o \
	tclResolve.o tclResult.o tclScan.o tclStringObj.o tclStrIdxTree.o \
	tclStrToD.o tclThread.o \
	tclThreadAlloc.o tclThreadJoin.o tclThreadStorage.o tclStubInit.o \
	tclTimer.o tclTrace.o tclUtf.o tclUtil.o tclVar.o tclZlib.o \
	tclTomMathInterface.o tclZipfs.o

OO_OBJS = tclOO.o tclOOBasic.o tclOOCall.o tclOODefineCmds.o tclOOInfo.o \
	tclOOMethod.o tclOOStubInit.o
	tclOOMethod.o tclOOProp.o tclOOStubInit.o

TOMMATH_OBJS = bn_s_mp_reverse.o bn_s_mp_mul_digs_fast.o \
	bn_s_mp_sqr_fast.o bn_mp_add.o bn_mp_and.o \
	bn_mp_add_d.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o \
	bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \
	bn_mp_cnt_lsb.o bn_mp_copy.o \
	bn_mp_count_bits.o bn_mp_div.o bn_mp_div_d.o bn_mp_div_2.o \
	bn_mp_div_2d.o bn_mp_div_3.o bn_mp_exch.o bn_mp_expt_u32.o \
	bn_mp_div_2d.o bn_s_mp_div_3.o bn_mp_exch.o bn_mp_expt_n.o \
	bn_mp_get_mag_u64.o \
	bn_mp_grow.o bn_mp_init.o \
	bn_mp_init_copy.o bn_mp_init_multi.o bn_mp_init_set.o \
	bn_mp_init_size.o bn_s_mp_karatsuba_mul.o \
	bn_mp_init_i64.o bn_mp_init_u64.o \
	bn_s_mp_karatsuba_sqr.o bn_s_mp_balance_mul.o \
	bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mul.o bn_mp_mul_2.o \
	bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_neg.o bn_mp_or.o \
	bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_set_i64.o  \
	bn_mp_read_radix.o bn_mp_rshd.o \
	bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_neg.o bn_mp_or.o bn_mp_pack.o \
	bn_mp_pack_count.o bn_mp_radix_size.o bn_mp_radix_smap.o  \
	bn_mp_set_i64.o bn_mp_read_radix.o bn_mp_rshd.o \
	bn_mp_set_u64.o bn_mp_shrink.o \
	bn_mp_sqr.o bn_mp_sqrt.o bn_mp_sub.o bn_mp_sub_d.o \
	bn_mp_signed_rsh.o \
	bn_mp_to_ubin.o \
	bn_mp_to_ubin.o bn_mp_unpack.o \
	bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o bn_mp_to_radix.o \
	bn_mp_ubin_size.o bn_mp_xor.o bn_mp_zero.o bn_s_mp_add.o \
	bn_s_mp_mul_digs.o bn_s_mp_sqr.o bn_s_mp_sub.o

STUB_LIB_OBJS = tclStubLib.o \
	tclStubCall.o \
	tclStubLibTbl.o \
	tclTomMathStubLib.o \
	tclOOStubLib.o \
	${COMPAT_OBJS}

UNIX_OBJS = tclUnixChan.o tclUnixEvent.o tclUnixFCmd.o \
	tclUnixFile.o tclUnixPipe.o tclUnixSock.o \
	tclUnixTime.o tclUnixInit.o tclUnixThrd.o \
396
397
398
399
400
401
402

403
404
405
406
407
408

409
410
411
412
413
414
415
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422







+






+








GENERIC_SRCS = \
	$(GENERIC_DIR)/regcomp.c \
	$(GENERIC_DIR)/regexec.c \
	$(GENERIC_DIR)/regfree.c \
	$(GENERIC_DIR)/regerror.c \
	$(GENERIC_DIR)/tclAlloc.c \
	$(GENERIC_DIR)/tclArithSeries.c \
	$(GENERIC_DIR)/tclAssembly.c \
	$(GENERIC_DIR)/tclAsync.c \
	$(GENERIC_DIR)/tclBasic.c \
	$(GENERIC_DIR)/tclBinary.c \
	$(GENERIC_DIR)/tclCkalloc.c \
	$(GENERIC_DIR)/tclClock.c \
	$(GENERIC_DIR)/tclClockFmt.c \
	$(GENERIC_DIR)/tclCmdAH.c \
	$(GENERIC_DIR)/tclCmdIL.c \
	$(GENERIC_DIR)/tclCmdMZ.c \
	$(GENERIC_DIR)/tclCompCmds.c \
	$(GENERIC_DIR)/tclCompCmdsGR.c \
	$(GENERIC_DIR)/tclCompCmdsSZ.c \
	$(GENERIC_DIR)/tclCompExpr.c \
424
425
426
427
428
429
430

431
432
433
434
435
436
437
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445







+







	$(GENERIC_DIR)/tclEvent.c \
	$(GENERIC_DIR)/tclExecute.c \
	$(GENERIC_DIR)/tclFCmd.c \
	$(GENERIC_DIR)/tclFileName.c \
	$(GENERIC_DIR)/tclGet.c \
	$(GENERIC_DIR)/tclHash.c \
	$(GENERIC_DIR)/tclHistory.c \
	$(GENERIC_DIR)/tclIcu.c \
	$(GENERIC_DIR)/tclIndexObj.c \
	$(GENERIC_DIR)/tclInterp.c \
	$(GENERIC_DIR)/tclIO.c \
	$(GENERIC_DIR)/tclIOCmd.c \
	$(GENERIC_DIR)/tclIOGT.c \
	$(GENERIC_DIR)/tclIOSock.c \
	$(GENERIC_DIR)/tclIOUtil.c \
457
458
459
460
461
462
463

464
465

466
467
468
469
470
471
472
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482







+


+







	$(GENERIC_DIR)/tclProcess.c \
	$(GENERIC_DIR)/tclRegexp.c \
	$(GENERIC_DIR)/tclResolve.c \
	$(GENERIC_DIR)/tclResult.c \
	$(GENERIC_DIR)/tclScan.c \
	$(GENERIC_DIR)/tclStubInit.c \
	$(GENERIC_DIR)/tclStringObj.c \
	$(GENERIC_DIR)/tclStrIdxTree.c \
	$(GENERIC_DIR)/tclStrToD.c \
	$(GENERIC_DIR)/tclTest.c \
	$(GENERIC_DIR)/tclTestABSList.c \
	$(GENERIC_DIR)/tclTestObj.c \
	$(GENERIC_DIR)/tclTestProcBodyObj.c \
	$(GENERIC_DIR)/tclThread.c \
	$(GENERIC_DIR)/tclThreadAlloc.c \
	$(GENERIC_DIR)/tclThreadJoin.c \
	$(GENERIC_DIR)/tclThreadStorage.c \
	$(GENERIC_DIR)/tclTimer.c \
480
481
482
483
484
485
486

487
488
489
490


491
492
493
494
495
496
497
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510







+




+
+







OO_SRCS = \
	$(GENERIC_DIR)/tclOO.c \
	$(GENERIC_DIR)/tclOOBasic.c \
	$(GENERIC_DIR)/tclOOCall.c \
	$(GENERIC_DIR)/tclOODefineCmds.c \
	$(GENERIC_DIR)/tclOOInfo.c \
	$(GENERIC_DIR)/tclOOMethod.c \
	$(GENERIC_DIR)/tclOOProp.c \
	$(GENERIC_DIR)/tclOOStubInit.c

STUB_SRCS = \
	$(GENERIC_DIR)/tclStubLib.c \
	$(GENERIC_DIR)/tclStubCall.c \
	$(GENERIC_DIR)/tclStubLibTbl.c \
	$(GENERIC_DIR)/tclTomMathStubLib.c \
	$(GENERIC_DIR)/tclOOStubLib.c

TOMMATH_SRCS = \
	$(TOMMATH_DIR)/bn_cutoffs.c \
	$(TOMMATH_DIR)/bn_deprecated.c \
	$(TOMMATH_DIR)/bn_mp_2expt.c \
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
558
559
560
561
562




563
564
565
566
567
568
569
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
558

559
560
561
562
563
564

565
566
567
568
569
570

571
572
573
574
575
576
577
578
579
580
581







-
+






-
+











-



-







-






-






-
+
+
+
+







	$(TOMMATH_DIR)/bn_mp_complement.c \
	$(TOMMATH_DIR)/bn_mp_copy.c \
	$(TOMMATH_DIR)/bn_mp_count_bits.c \
	$(TOMMATH_DIR)/bn_mp_decr.c \
	$(TOMMATH_DIR)/bn_mp_div.c \
	$(TOMMATH_DIR)/bn_mp_div_2.c \
	$(TOMMATH_DIR)/bn_mp_div_2d.c \
	$(TOMMATH_DIR)/bn_mp_div_3.c \
	$(TOMMATH_DIR)/bn_s_mp_div_3.c \
	$(TOMMATH_DIR)/bn_mp_div_d.c \
	$(TOMMATH_DIR)/bn_mp_dr_is_modulus.c \
	$(TOMMATH_DIR)/bn_mp_dr_reduce.c \
	$(TOMMATH_DIR)/bn_mp_dr_setup.c \
	$(TOMMATH_DIR)/bn_mp_error_to_string.c \
	$(TOMMATH_DIR)/bn_mp_exch.c \
	$(TOMMATH_DIR)/bn_mp_expt_u32.c \
	$(TOMMATH_DIR)/bn_mp_expt_n.c \
	$(TOMMATH_DIR)/bn_mp_exptmod.c \
	$(TOMMATH_DIR)/bn_mp_exteuclid.c \
	$(TOMMATH_DIR)/bn_mp_fread.c \
	$(TOMMATH_DIR)/bn_mp_from_sbin.c \
	$(TOMMATH_DIR)/bn_mp_from_ubin.c \
	$(TOMMATH_DIR)/bn_mp_fwrite.c \
	$(TOMMATH_DIR)/bn_mp_gcd.c \
	$(TOMMATH_DIR)/bn_mp_get_double.c \
	$(TOMMATH_DIR)/bn_mp_get_i32.c \
	$(TOMMATH_DIR)/bn_mp_get_i64.c \
	$(TOMMATH_DIR)/bn_mp_get_l.c \
	$(TOMMATH_DIR)/bn_mp_get_ll.c \
	$(TOMMATH_DIR)/bn_mp_get_mag_u32.c \
	$(TOMMATH_DIR)/bn_mp_get_mag_u64.c \
	$(TOMMATH_DIR)/bn_mp_get_mag_ul.c \
	$(TOMMATH_DIR)/bn_mp_get_mag_ull.c \
	$(TOMMATH_DIR)/bn_mp_grow.c \
	$(TOMMATH_DIR)/bn_mp_incr.c \
	$(TOMMATH_DIR)/bn_mp_init.c \
	$(TOMMATH_DIR)/bn_mp_init_copy.c \
	$(TOMMATH_DIR)/bn_mp_init_i32.c \
	$(TOMMATH_DIR)/bn_mp_init_i64.c \
	$(TOMMATH_DIR)/bn_mp_init_l.c \
	$(TOMMATH_DIR)/bn_mp_init_ll.c \
	$(TOMMATH_DIR)/bn_mp_init_multi.c \
	$(TOMMATH_DIR)/bn_mp_init_set.c \
	$(TOMMATH_DIR)/bn_mp_init_size.c \
	$(TOMMATH_DIR)/bn_mp_init_u32.c \
	$(TOMMATH_DIR)/bn_mp_init_u64.c \
	$(TOMMATH_DIR)/bn_mp_init_ul.c \
	$(TOMMATH_DIR)/bn_mp_init_ull.c \
	$(TOMMATH_DIR)/bn_mp_invmod.c \
	$(TOMMATH_DIR)/bn_mp_is_square.c \
	$(TOMMATH_DIR)/bn_mp_iseven.c \
	$(TOMMATH_DIR)/bn_mp_isodd.c \
	$(TOMMATH_DIR)/bn_mp_kronecker.c \
	$(TOMMATH_DIR)/bn_mp_lcm.c \
	$(TOMMATH_DIR)/bn_mp_log_u32.c \
	$(TOMMATH_DIR)/bn_mp_log_n.c \
	$(TOMMATH_DIR)/bn_s_mp_log.c \
	$(TOMMATH_DIR)/bn_s_mp_log_2expt.c \
	$(TOMMATH_DIR)/bn_s_mp_log_d.c \
	$(TOMMATH_DIR)/bn_mp_lshd.c \
	$(TOMMATH_DIR)/bn_mp_mod.c \
	$(TOMMATH_DIR)/bn_mp_mod_2d.c \
	$(TOMMATH_DIR)/bn_mp_mod_d.c \
	$(TOMMATH_DIR)/bn_mp_montgomery_calc_normalization.c \
	$(TOMMATH_DIR)/bn_mp_montgomery_reduce.c \
	$(TOMMATH_DIR)/bn_mp_montgomery_setup.c \
592
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
604
605
606
607
608
609
610

611
612
613
614
615
616
617
618

619
620
621

622
623
624
625
626
627
628







-
+







-



-







	$(TOMMATH_DIR)/bn_mp_reduce_2k.c \
	$(TOMMATH_DIR)/bn_mp_reduce_2k_l.c \
	$(TOMMATH_DIR)/bn_mp_reduce_2k_setup.c \
	$(TOMMATH_DIR)/bn_mp_reduce_2k_setup_l.c \
	$(TOMMATH_DIR)/bn_mp_reduce_is_2k.c \
	$(TOMMATH_DIR)/bn_mp_reduce_is_2k_l.c \
	$(TOMMATH_DIR)/bn_mp_reduce_setup.c \
	$(TOMMATH_DIR)/bn_mp_root_u32.c \
	$(TOMMATH_DIR)/bn_mp_root_n.c \
	$(TOMMATH_DIR)/bn_mp_rshd.c \
	$(TOMMATH_DIR)/bn_mp_sbin_size.c \
	$(TOMMATH_DIR)/bn_mp_set.c \
	$(TOMMATH_DIR)/bn_mp_set_double.c \
	$(TOMMATH_DIR)/bn_mp_set_i32.c \
	$(TOMMATH_DIR)/bn_mp_set_i64.c \
	$(TOMMATH_DIR)/bn_mp_set_l.c \
	$(TOMMATH_DIR)/bn_mp_set_ll.c \
	$(TOMMATH_DIR)/bn_mp_set_u32.c \
	$(TOMMATH_DIR)/bn_mp_set_u64.c \
	$(TOMMATH_DIR)/bn_mp_set_ul.c \
	$(TOMMATH_DIR)/bn_mp_set_ull.c \
	$(TOMMATH_DIR)/bn_mp_shrink.c \
	$(TOMMATH_DIR)/bn_mp_signed_rsh.c \
	$(TOMMATH_DIR)/bn_mp_sqr.c \
	$(TOMMATH_DIR)/bn_mp_sqrmod.c \
	$(TOMMATH_DIR)/bn_mp_sqrt.c \
	$(TOMMATH_DIR)/bn_mp_sqrtmod_prime.c \
	$(TOMMATH_DIR)/bn_mp_sub.c \
667
668
669
670
671
672
673
674


675
676
677
678
679
680
681
677
678
679
680
681
682
683

684
685
686
687
688
689
690
691
692







-
+
+







	$(UNIX_DIR)/tclUnixTime.c \
	$(UNIX_DIR)/tclUnixInit.c \
	$(UNIX_DIR)/tclUnixCompat.c

NOTIFY_SRCS = \
	$(UNIX_DIR)/tclEpollNotfy.c \
	$(UNIX_DIR)/tclKqueueNotfy.c \
	$(UNIX_DIR)/tclSelectNotfy.c
	$(UNIX_DIR)/tclSelectNotfy.c \
	$(UNIX_DIR)/tclUnixNotfy.c

DL_SRCS = \
	$(UNIX_DIR)/tclLoadAix.c \
	$(UNIX_DIR)/tclLoadDl.c \
	$(UNIX_DIR)/tclLoadDl2.c \
	$(UNIX_DIR)/tclLoadDld.c \
	$(UNIX_DIR)/tclLoadDyld.c \
723
724
725
726
727
728
729

730
731
732
733
734
735
736
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748







+







TCL_VFS_ROOT		= libtcl.vfs
TCL_VFS_PATH		= ${TCL_VFS_ROOT}/tcl_library

HOST_CC			= @CC_FOR_BUILD@
HOST_EXEEXT		= @EXEEXT_FOR_BUILD@
HOST_OBJEXT		= @OBJEXT_FOR_BUILD@
ZIPFS_BUILD		= @ZIPFS_BUILD@
MACHER			= @MACHER_PROG@
NATIVE_ZIP		= @ZIP_PROG@
ZIP_PROG_OPTIONS	= @ZIP_PROG_OPTIONS@
ZIP_PROG_VFSSEARCH	= @ZIP_PROG_VFSSEARCH@
SHARED_BUILD		= @SHARED_BUILD@
INSTALL_LIBRARIES	= @INSTALL_LIBRARIES@
INSTALL_MSGS		= @INSTALL_MSGS@

773
774
775
776
777
778
779
780

781
782
783
784
785
786
787
788
789
790
791
792
793
794

795



796
797
798
799
800
801
802
785
786
787
788
789
790
791

792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818







-
+














+

+
+
+







	@echo "creating ${TCL_VFS_PATH} (prepare compression)"
	@if \
	    ln -s $(TOP_DIR)/library/* ${TCL_VFS_PATH}/; \
	then : ; else \
	    cp -a $(TOP_DIR)/library/* ${TCL_VFS_PATH}; \
	fi
	mv ${TCL_VFS_PATH}/manifest.txt ${TCL_VFS_PATH}/pkgIndex.tcl
	rm -rf ${TCL_VFS_PATH}/dde ${TCL_VFS_PATH}/reg
	rm -rf ${TCL_VFS_PATH}/dde ${TCL_VFS_PATH}/registry
	@find ${TCL_VFS_ROOT} -type d -empty -delete
	@echo "creating ${TCL_ZIP_FILE} from ${TCL_VFS_PATH}"
	@(zip=`(realpath '${NATIVE_ZIP}' || readlink -m '${NATIVE_ZIP}' || \
	    echo '${NATIVE_ZIP}' | sed "s?^\./?$$(pwd)/?")  2>/dev/null`; \
	    echo 'cd ${TCL_VFS_ROOT} &&' $$zip '${ZIP_PROG_OPTIONS} ../${TCL_ZIP_FILE} ${ZIP_PROG_VFSSEARCH}'; \
	    cd ${TCL_VFS_ROOT} && \
	    $$zip ${ZIP_PROG_OPTIONS} ../${TCL_ZIP_FILE} ${ZIP_PROG_VFSSEARCH} >/dev/null)

# The following target is configured by autoconf to generate either a shared
# library or non-shared library for Tcl.
${LIB_FILE}: ${STUB_LIB_FILE} ${OBJS} ${TCL_ZIP_FILE}
	rm -f $@
	@MAKE_LIB@
	@if test "${ZIPFS_BUILD}" = "1" ; then \
	    if test "x$(MACHER)" = "x" ; then \
	    cat ${TCL_ZIP_FILE} >> ${LIB_FILE}; \
	    else $(MACHER) append ${LIB_FILE} ${TCL_ZIP_FILE} /tmp/macher_output; \
		 mv /tmp/macher_output ${LIB_FILE}; chmod u+x ${LIB_FILE}; \
	    fi; \
	    ${NATIVE_ZIP} -A ${LIB_FILE} \
	    || echo 'ignore zip-error by adjust sfx process (not executable?)'; \
	fi

${STUB_LIB_FILE}: ${STUB_LIB_OBJS}
	@if [ "x${LIB_FILE}" = "xlibtcl${MAJOR_VERSION}.${MINOR_VERSION}.dll" ] ; then \
	    ( cd ${TOP_DIR}/win; ${MAKE} winextensions ); \
810
811
812
813
814
815
816
817

818
819
820









821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838

839
840
841
842
843
844
845
826
827
828
829
830
831
832

833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862

863
864
865
866
867
868
869
870







-
+



+
+
+
+
+
+
+
+
+

















-
+







# The dependency on OBJS is not there because we just want the list of objects
# here, not actually building them
tclLibObjs:
	@echo ${OBJS}
# This targets actually build the objects needed for the lib in the above case
objs: ${OBJS}

${TCL_EXE}: ${TCLSH_OBJS} ${TCL_LIB_FILE} ${TCL_STUB_LIB_FILE}
${TCL_EXE}: ${TCLSH_OBJS} ${TCL_LIB_FILE} ${TCL_STUB_LIB_FILE} ${TCL_ZIP_FILE}
	${CC} ${CFLAGS} ${LDFLAGS} ${TCLSH_OBJS} \
		@TCL_BUILD_LIB_SPEC@ ${TCL_STUB_LIB_FILE} ${LIBS} @EXTRA_TCLSH_LIBS@ \
		${CC_SEARCH_FLAGS} -o ${TCL_EXE}
	@if test "${ZIPFS_BUILD}" = "2" ; then \
	    if test "x$(MACHER)" = "x" ; then \
	    cat ${TCL_ZIP_FILE} >> ${TCL_EXE}; \
	    else $(MACHER) append ${TCL_EXE} ${TCL_ZIP_FILE} /tmp/macher_output; \
		 mv /tmp/macher_output ${TCL_EXE}; chmod u+x ${TCL_EXE}; \
	    fi; \
	    ${NATIVE_ZIP} -A ${TCL_EXE} \
	    || echo 'ignore zip-error by adjust sfx process (not executable?)'; \
	fi

# Must be empty so it doesn't conflict with rule for ${TCL_EXE} above
${NATIVE_TCLSH}:

Makefile: $(UNIX_DIR)/Makefile.in $(DLTEST_DIR)/Makefile.in
	$(SHELL) config.status
#tclConfig.h: $(UNIX_DIR)/tclConfig.h.in
#	$(SHELL) config.status

clean: clean-packages
	rm -rf *.a *.o libtcl* core errs *~ \#* TAGS *.E a.out \
		errors ${TCL_EXE} ${TCLTEST_EXE} lib.exp Tcl @DTRACE_HDR@ \
		minizip${HOST_EXEEXT} *.${HOST_OBJEXT} *.zip *.vfs
	(cd dltest ; $(MAKE) clean)

distclean: distclean-packages clean
	rm -rf Makefile config.status config.cache config.log tclConfig.sh \
		tclConfig.h *.plist Tcl.framework tcl.pc
		tclConfig.h *.plist Tcl.framework tcl.pc tclUuid.h
	(cd dltest ; $(MAKE) distclean)

depend:
	makedepend -- $(DEPEND_SWITCHES) -- $(SRCS)

#--------------------------------------------------------------------------
# The following target outputs the name of the top-level source directory for
861
862
863
864
865
866
867
868

869
870
871
872
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
898
899

900
901

902
903
904
905
906
907
908
886
887
888
889
890
891
892

893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923

924


925


926
927



928
929

930
931
932
933
934
935
936
937







-
+






+
+
+
+
+
+
+
+
+















-
+
-
-
+
-
-


-
-
-
+

-
+







# tcltest executable gets the build directory burned into its ld search path.
# This keeps tcltest from picking up an already installed version of the Tcl
# library.
SHELL_ENV =	@LD_LIBRARY_PATH_VAR@=`pwd`:${@LD_LIBRARY_PATH_VAR@} \
		TCLLIBPATH="@abs_builddir@/pkgs" \
		TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"

${TCLTEST_EXE}: ${TCLTEST_OBJS} ${TCL_LIB_FILE} ${TCL_STUB_LIB_FILE} ${BUILD_DLTEST}
${TCLTEST_EXE}: ${TCLTEST_OBJS} ${TCL_LIB_FILE} ${TCL_STUB_LIB_FILE} ${BUILD_DLTEST} ${TCL_ZIP_FILE}
	$(MAKE) tcltest-real LIB_RUNTIME_DIR="`pwd`"

tcltest-real:
	${CC} ${CFLAGS} ${LDFLAGS} ${TCLTEST_OBJS} \
		@TCL_BUILD_LIB_SPEC@ ${TCL_STUB_LIB_FILE} ${LIBS} @EXTRA_TCLSH_LIBS@ \
		${CC_SEARCH_FLAGS} -o ${TCLTEST_EXE}
	@if test "${ZIPFS_BUILD}" = "2" ; then \
	    if test "x$(MACHER)" = "x" ; then \
	    cat ${TCL_ZIP_FILE} >> ${TCLTEST_EXE}; \
	    else $(MACHER) append ${TCLTEST_EXE} ${TCL_ZIP_FILE} /tmp/macher_output; \
		 mv /tmp/macher_output ${TCLTEST_EXE}; chmod u+x ${TCLTEST_EXE}; \
	    fi; \
	    ${NATIVE_ZIP} -A ${TCLTEST_EXE} \
	    || echo 'ignore zip-error by adjust sfx process (not executable?)'; \
	fi

# Note, in the targets below TCL_LIBRARY needs to be set or else "make test"
# won't work in the case where the compilation directory isn't the same as the
# source directory.
#
# Specifying TESTFLAGS on the command line is the standard way to pass args to
# tcltest, ie:
#	% make test TESTFLAGS="-verbose bps -file fileName.test"

test: test-tcl test-packages

test-tcl: ${TCLTEST_EXE}
	$(SHELL_ENV) ./${TCLTEST_EXE} $(TOP_DIR)/tests/all.tcl $(TESTFLAGS)

gdb-test: ${TCLTEST_EXE}
	@echo "set env @LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}" > gdb.run
	$(SHELL_ENV) $(GDB) --args ./${TCLTEST_EXE} $(TOP_DIR)/tests/all.tcl \
	@echo "set env TCL_LIBRARY=${TCL_BUILDTIME_LIBRARY}" >> gdb.run
	@echo "set args $(TOP_DIR)/tests/all.tcl $(TESTFLAGS) -singleproc 1" >> gdb.run
		$(TESTFLAGS) -singleproc 1
	$(GDB) ./${TCLTEST_EXE} --command=gdb.run
	@rm gdb.run

lldb-test: ${TCLTEST_EXE}
	@echo "settings set target.env-vars @LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}" > lldb.run
	@echo "settings set target.env-vars TCL_LIBRARY=${TCL_BUILDTIME_LIBRARY}" >> lldb.run
	$(LLDB) --source lldb.run ./${TCLTEST_EXE} -- $(TOP_DIR)/tests/all.tcl \
	$(SHELL_ENV) $(LLDB) -- ./${TCLTEST_EXE} $(TOP_DIR)/tests/all.tcl \
		$(TESTFLAGS) -singleproc 1
	@rm lldb.run


# Useful target to launch a built tcltest with the proper path,...
runtest: ${TCLTEST_EXE}
	$(SHELL_ENV) ./${TCLTEST_EXE}

# Useful target for running the test suite with an unwritable current
# directory...
927
928
929
930
931
932
933



934
935
936
937





















938
939
940
941
942
943
944
956
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







+
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







shell: ${TCL_EXE}
	$(SHELL_ENV) ./${TCL_EXE} $(SCRIPT)

# This target can be used to run tclsh inside either gdb or insight
gdb: ${TCL_EXE}
	$(SHELL_ENV) $(GDB) ./${TCL_EXE}

lldb: ${TCL_EXE}
	$(SHELL_ENV) $(LLDB) ./${TCL_EXE}

valgrind: ${TCL_EXE} ${TCLTEST_EXE}
	$(SHELL_ENV) $(VALGRIND) $(VALGRINDARGS) ./${TCLTEST_EXE} \
		$(TOP_DIR)/tests/all.tcl -singleproc 1 -constraints valgrind \
		$(TESTFLAGS)

testresults/valgrind/%.result: ${TCL_EXE} ${TCLTEST_EXE}
	@mkdir -p testresults/valgrind
	$(SHELL_ENV) $(VALGRIND) $(VALGRINDARGS) ./${TCLTEST_EXE} \
		$(TOP_DIR)/tests/all.tcl -singleproc 1 -constraints valgrind \
		-file $(basename $(notdir $@)) > $@.tmp 2>&1
	@mv $@.tmp $@
.PRECIOUS: testresults/valgrind/%.result


testresults/valgrind/%.success: testresults/valgrind/%.result
	@printf '%s' valgrind >&2
	@printf ' %s' $(basename $(notdir $@)) >&2
	@printf '\n >&2'
	@status=$$(./${TCLTEST_EXE} $(TOP_DIR)/tools/valgrind_check_success \
		file $(basename $@).result); \
	if [ "$$status" -eq 1 ]; then touch $@; exit 0; else exit 1; fi

valgrind_each: $(addprefix testresults/valgrind/,$(addsuffix .success,$(notdir\
	$(wildcard $(TOP_DIR)/tests/*.test))))


valgrindshell: ${TCL_EXE}
	$(SHELL_ENV) $(VALGRIND) $(VALGRINDARGS) ./${TCL_EXE} $(SCRIPT)

trace-shell: ${TCL_EXE}
	$(SHELL_ENV) ${TRACE} $(TRACE_OPTS) ./${TCL_EXE} $(SCRIPT)

957
958
959
960
961
962
963
964
965


966
967
968
969
970
971
972
1010
1011
1012
1013
1014
1015
1016


1017
1018
1019
1020
1021
1022
1023
1024
1025







-
-
+
+







INSTALL_TARGETS = $(INSTALL_BASE_TARGETS) $(INSTALL_DOC_TARGETS) $(INSTALL_DEV_TARGETS) \
		  $(INSTALL_PACKAGE_TARGETS) $(INSTALL_EXTRA_TARGETS)

install: $(INSTALL_TARGETS)

install-strip:
	$(MAKE) $(INSTALL_TARGETS) \
		INSTALL_PROGRAM="$(INSTALL_PROGRAM) ${INSTALL_STRIP_PROGRAM}" \
		INSTALL_LIBRARY="$(INSTALL_LIBRARY) ${INSTALL_STRIP_LIBRARY}"
		INSTALL_PROGRAM="STRIPPROG='${INSTALL_STRIP_PROGRAM}' $(INSTALL_PROGRAM) -s" \
		INSTALL_LIBRARY="STRIPPROG='${INSTALL_STRIP_LIBRARY}' $(INSTALL_LIBRARY) -s"

install-binaries: binaries
	@for i in "$(LIB_INSTALL_DIR)" "$(BIN_INSTALL_DIR)" \
		"$(CONFIG_INSTALL_DIR)" ; do \
	    if [ ! -d "$$i" ] ; then \
		echo "Making directory $$i"; \
		$(INSTALL_DATA_DIR) "$$i"; \
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
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







-
-
+
+
+












-
+




-
+

-
+
-
-
-
+
+

-
-
+
+

-
-
+
+






-
+

-
-
+
+

-
+









-
-
+
+







	    @INSTALL_STUB_LIB@ ; \
	fi
	@EXTRA_INSTALL_BINARIES@
	@echo "Installing pkg-config file to $(LIB_INSTALL_DIR)/pkgconfig/"
	@$(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/pkgconfig"
	@$(INSTALL_DATA) tcl.pc "$(LIB_INSTALL_DIR)/pkgconfig/tcl.pc"

install-libraries-zipfs-shared: libraries
	@for i in "$(SCRIPT_INSTALL_DIR)"; do \
	    if [ ! -d "$$i" ] ; then \
		echo "Making directory $$i"; \
		$(INSTALL_DATA_DIR) "$$i"; \
	    fi; \
	done
	@echo "Installing library files to $(SCRIPT_INSTALL_DIR)/"
	@for i in $(UNIX_DIR)/tclAppInit.c @LDAIX_SRC@ @DTRACE_SRC@; do \
	    $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"; \
	done

install-libraries-zipfs-static: install-libraries-zipfs-shared
	$(INSTALL_DATA) ${TCL_ZIP_FILE} "$(LIB_INSTALL_DIR)"

install-libraries: libraries
	@for i in "$(SCRIPT_INSTALL_DIR)" "$(MODULE_INSTALL_DIR)"; \
	    do \
	    if [ ! -d "$$i" ] ; then \
		echo "Making directory $$i"; \
		$(INSTALL_DATA_DIR) "$$i"; \
	    fi; \
	done
	@for i in opt0.4 cookiejar0.2 encoding; do \
	    done;
	@for i in opt0.4 cookiejar0.2 encoding; \
	    do \
	    if [ ! -d "$(SCRIPT_INSTALL_DIR)/$$i" ] ; then \
		echo "Making directory $(SCRIPT_INSTALL_DIR)/$$i"; \
		$(INSTALL_DATA_DIR) "$(SCRIPT_INSTALL_DIR)/$$i"; \
		else true; \
		fi; \
	    done;
	@for i in 9.0 9.0/platform; \
	    do \
	    if [ ! -d "$(MODULE_INSTALL_DIR)/$$i" ] ; then \
		echo "Making directory $(MODULE_INSTALL_DIR)/$$i"; \
		$(INSTALL_DATA_DIR) "$(MODULE_INSTALL_DIR)/$$i"; \
	    fi; \
	done
	    done;
	@echo "Installing library files to $(SCRIPT_INSTALL_DIR)/"
	@for i in $(TOP_DIR)/library/*.tcl $(TOP_DIR)/library/tclIndex \
		$(UNIX_DIR)/tclAppInit.c @LDAIX_SRC@ @DTRACE_SRC@ ; do \
	    $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"; \
	done
	done;
	@echo "Installing package cookiejar 0.2 files to $(SCRIPT_INSTALL_DIR)/cookiejar0.2/"
	@for i in $(TOP_DIR)/library/cookiejar/*.tcl; do \
	@for i in $(TOP_DIR)/library/cookiejar/*.tcl \
	    $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/cookiejar0.2"; \
	done
	@for i in $(TOP_DIR)/library/cookiejar/*.gz; do \
		  $(TOP_DIR)/library/cookiejar/*.gz; \
	    do \
	    $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/cookiejar0.2"; \
	done
	@echo "Installing package http 2.10.0a1 as a Tcl Module"
	    done
	@echo "Installing package http 2.10.0 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/http/http.tcl \
		"$(MODULE_INSTALL_DIR)/9.0/http-2.10.0a1.tm"
	@echo "Installing package opt 0.4.7"
		"$(MODULE_INSTALL_DIR)/9.0/http-2.10.0.tm"
	@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.3 as a Tcl Module"
	@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.3.tm"
	@echo "Installing package platform 1.0.14 as a Tcl Module"
		"$(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.14.tm"
		"$(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
	@if [ -n "$(TCL_MODULE_PATH)" -a -f $(TOP_DIR)/library/tm.tcl ] ; then \
	    echo "Customizing tcl module path"; \
	    echo "if {![interp issafe]} { ::tcl::tm::roots {$(TCL_MODULE_PATH)} }" >> \
	        "$(SCRIPT_INSTALL_DIR)/tm.tcl"; \
	    echo "if {![interp issafe]} { ::tcl::tm::roots [list $(TCL_MODULE_PATH)] }" >> \
		"$(SCRIPT_INSTALL_DIR)/tm.tcl"; \
	fi

install-tzdata:
	@for i in tzdata; do \
	    if [ ! -d "$(SCRIPT_INSTALL_DIR)/$$i" ] ; then \
		echo "Making directory $(SCRIPT_INSTALL_DIR)/$$i"; \
		$(INSTALL_DATA_DIR) "$(SCRIPT_INSTALL_DIR)/$$i"; \
1226
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
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







+




















+
+
+
















-
+

+
+
+










-
+







MATHHDRS	= $(GENERIC_DIR)/tclTomMath.h $(GENERIC_DIR)/tclTomMathDecls.h
PARSEHDR	= $(GENERIC_DIR)/tclParse.h
NREHDR		= $(GENERIC_DIR)/tclInt.h
TRIMHDR		= $(GENERIC_DIR)/tclStringTrim.h

TCL_LOCATIONS	= -DTCL_LIBRARY="\"${TCL_LIBRARY}\"" \
	-DTCL_PACKAGE_PATH="\"${TCL_PACKAGE_PATH}\""
TCLDATEHDR=$(GENERIC_DIR)/tclDate.h $(GENERIC_DIR)/tclStrIdxTree.h

regcomp.o: $(REGHDRS) $(GENERIC_DIR)/regcomp.c $(GENERIC_DIR)/regc_lex.c \
		$(GENERIC_DIR)/regc_color.c $(GENERIC_DIR)/regc_locale.c \
		$(GENERIC_DIR)/regc_nfa.c $(GENERIC_DIR)/regc_cvec.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/regcomp.c

regexec.o: $(REGHDRS) $(GENERIC_DIR)/regexec.c $(GENERIC_DIR)/rege_dfa.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/regexec.c

regfree.o: $(REGHDRS) $(GENERIC_DIR)/regfree.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/regfree.c

regerror.o: $(REGHDRS) $(GENERIC_DIR)/regerrs.h $(GENERIC_DIR)/regerror.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/regerror.c

tclAppInit.o: $(UNIX_DIR)/tclAppInit.c
	$(CC) -c $(APP_CC_SWITCHES) $(UNIX_DIR)/tclAppInit.c

tclAlloc.o: $(GENERIC_DIR)/tclAlloc.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclAlloc.c

tclArithSeries.o: $(GENERIC_DIR)/tclArithSeries.c $(COMPILEHDR)
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclArithSeries.c

tclAssembly.o: $(GENERIC_DIR)/tclAssembly.c $(COMPILEHDR)
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclAssembly.c

tclAsync.o: $(GENERIC_DIR)/tclAsync.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclAsync.c

tclBasic.o: $(GENERIC_DIR)/tclBasic.c $(COMPILEHDR) $(MATHHDRS) $(NREHDR)
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclBasic.c

tclBinary.o: $(GENERIC_DIR)/tclBinary.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclBinary.c

tclCkalloc.o: $(GENERIC_DIR)/tclCkalloc.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCkalloc.c

tclClock.o: $(GENERIC_DIR)/tclClock.c
tclClock.o: $(GENERIC_DIR)/tclClock.c $(TCLDATEHDR)
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclClock.c

tclClockFmt.o: $(GENERIC_DIR)/tclClockFmt.c $(TCLDATEHDR)
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclClockFmt.c

tclCmdAH.o: $(GENERIC_DIR)/tclCmdAH.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCmdAH.c

tclCmdIL.o: $(GENERIC_DIR)/tclCmdIL.c $(TCLREHDRS)
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCmdIL.c

tclCmdMZ.o: $(GENERIC_DIR)/tclCmdMZ.c $(TCLREHDRS) $(TRIMHDR)
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCmdMZ.c

tclDate.o: $(GENERIC_DIR)/tclDate.c
tclDate.o: $(GENERIC_DIR)/tclDate.c $(TCLDATEHDR)
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclDate.c

tclCompCmds.o: $(GENERIC_DIR)/tclCompCmds.c $(COMPILEHDR)
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCompCmds.c

tclCompCmdsGR.o: $(GENERIC_DIR)/tclCompCmdsGR.c $(COMPILEHDR)
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCompCmdsGR.c
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
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392







-
+




















+
+
+








tclEnsemble.o: $(GENERIC_DIR)/tclEnsemble.c $(COMPILEHDR)
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclEnsemble.c

tclEnv.o: $(GENERIC_DIR)/tclEnv.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclEnv.c

tclEvent.o: $(GENERIC_DIR)/tclEvent.c
tclEvent.o: $(GENERIC_DIR)/tclEvent.c tclUuid.h
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclEvent.c

tclExecute.o: $(GENERIC_DIR)/tclExecute.c $(COMPILEHDR) $(MATHHDRS) $(NREHDR)
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclExecute.c

tclFCmd.o: $(GENERIC_DIR)/tclFCmd.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclFCmd.c

tclFileName.o: $(GENERIC_DIR)/tclFileName.c $(FSHDR) $(TCLREHDRS)
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclFileName.c

tclGet.o: $(GENERIC_DIR)/tclGet.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclGet.c

tclHash.o: $(GENERIC_DIR)/tclHash.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclHash.c

tclHistory.o: $(GENERIC_DIR)/tclHistory.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclHistory.c

tclIcu.o: $(GENERIC_DIR)/tclIcu.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclIcu.c

tclIndexObj.o: $(GENERIC_DIR)/tclIndexObj.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclIndexObj.c

tclInterp.o: $(GENERIC_DIR)/tclInterp.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclInterp.c

tclIO.o: $(GENERIC_DIR)/tclIO.c $(IOHDR)
1427
1428
1429
1430
1431
1432
1433



1434
1435
1436
1437
1438
1439
1440
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491







+
+
+








tclOOInfo.o: $(GENERIC_DIR)/tclOOInfo.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclOOInfo.c

tclOOMethod.o: $(GENERIC_DIR)/tclOOMethod.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclOOMethod.c

tclOOProp.o: $(GENERIC_DIR)/tclOOProp.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclOOProp.c

tclOOStubInit.o: $(GENERIC_DIR)/tclOOStubInit.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclOOStubInit.c

tclParse.o: $(GENERIC_DIR)/tclParse.c $(PARSEHDR)
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclParse.c

tclPanic.o: $(GENERIC_DIR)/tclPanic.c
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1517
1518
1519
1520
1521
1522
1523

1524
1525
1526
1527
1528
1529
1530







-







		-DCFG_INSTALL_DOCDIR="\"$(MAN_INSTALL_DIR)\"" \
		-DCFG_RUNTIME_LIBDIR="\"$(libdir)\"" \
		-DCFG_RUNTIME_BINDIR="\"$(bindir)\"" \
		-DCFG_RUNTIME_SCRDIR="\"$(TCL_LIBRARY)\"" \
		-DCFG_RUNTIME_INCDIR="\"$(includedir)\"" \
		-DCFG_RUNTIME_DOCDIR="\"$(mandir)\"" \
		-DCFG_RUNTIME_DLLFILE="\"$(TCL_LIB_FILE)\"" \
		-DCFG_RUNTIME_ZIPFILE="\"$(TCL_ZIP_FILE)\"" \
		$(GENERIC_DIR)/tclPkgConfig.c

tclPosixStr.o: $(GENERIC_DIR)/tclPosixStr.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclPosixStr.c

tclPreserve.o: $(GENERIC_DIR)/tclPreserve.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclPreserve.c
1496
1497
1498
1499
1500
1501
1502



1503
1504
1505
1506
1507
1508
1509
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562







+
+
+








tclScan.o: $(GENERIC_DIR)/tclScan.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclScan.c

tclStringObj.o: $(GENERIC_DIR)/tclStringObj.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStringObj.c

tclStrIdxTree.o: $(GENERIC_DIR)/tclStrIdxTree.c $(GENERIC_DIR)/tclStrIdxTree.h $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStrIdxTree.c

tclStrToD.o: $(GENERIC_DIR)/tclStrToD.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStrToD.c

tclStubInit.o: $(GENERIC_DIR)/tclStubInit.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStubInit.c

tclTrace.o: $(GENERIC_DIR)/tclTrace.c
1518
1519
1520
1521
1522
1523
1524
1525

1526
1527
1528
1529
1530
1531
1532
1533

1534



1535
1536
1537
1538
1539
1540
1541
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







-
+

-

-



-
+

+
+
+







tclVar.o: $(GENERIC_DIR)/tclVar.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclVar.c

tclZlib.o: $(GENERIC_DIR)/tclZlib.c
	$(CC) -c $(CC_SWITCHES) $(ZLIB_INCLUDE) $(GENERIC_DIR)/tclZlib.c

tclZipfs.o: $(GENERIC_DIR)/tclZipfs.c
	$(CC) -c $(CC_SWITCHES) \
	$(CC) -c $(CC_SWITCHES) -D_GNU_SOURCE \
		-DCFG_RUNTIME_DLLFILE="\"$(TCL_LIB_FILE)\"" \
		-DCFG_RUNTIME_ZIPFILE="\"$(TCL_ZIP_FILE)\"" \
		-DCFG_RUNTIME_LIBDIR="\"$(libdir)\"" \
		-DCFG_RUNTIME_SCRDIR="\"$(TCL_LIBRARY)\"" \
		-I$(ZLIB_DIR) -I$(ZLIB_DIR)/contrib/minizip \
		$(GENERIC_DIR)/tclZipfs.c

tclTest.o: $(GENERIC_DIR)/tclTest.c $(IOHDR) $(TCLREHDRS)
tclTest.o: $(GENERIC_DIR)/tclTest.c $(IOHDR) $(TCLREHDRS) tclUuid.h
	$(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tclTest.c

tclTestABSList.o: $(GENERIC_DIR)/tclTestABSList.c $(MATHHDRS)
	$(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tclTestABSList.c

tclTestObj.o: $(GENERIC_DIR)/tclTestObj.c $(MATHHDRS)
	$(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tclTestObj.c

tclTestProcBodyObj.o: $(GENERIC_DIR)/tclTestProcBodyObj.c
	$(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tclTestProcBodyObj.c

1613
1614
1615
1616
1617
1618
1619
1620
1621


1622
1623
1624
1625
1626
1627


1628
1629
1630
1631
1632
1633
1634
1667
1668
1669
1670
1671
1672
1673


1674
1675
1676
1677
1678
1679


1680
1681
1682
1683
1684
1685
1686
1687
1688







-
-
+
+




-
-
+
+








bn_mp_div_2.o: $(TOMMATH_DIR)/bn_mp_div_2.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_2.c

bn_mp_div_2d.o: $(TOMMATH_DIR)/bn_mp_div_2d.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_2d.c

bn_mp_div_3.o: $(TOMMATH_DIR)/bn_mp_div_3.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_3.c
bn_s_mp_div_3.o: $(TOMMATH_DIR)/bn_s_mp_div_3.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_s_mp_div_3.c

bn_mp_exch.o: $(TOMMATH_DIR)/bn_mp_exch.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_exch.c

bn_mp_expt_u32.o: $(TOMMATH_DIR)/bn_mp_expt_u32.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_expt_u32.c
bn_mp_expt_n.o: $(TOMMATH_DIR)/bn_mp_expt_n.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_expt_n.c

bn_mp_get_mag_u64.o: $(TOMMATH_DIR)/bn_mp_get_mag_u64.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_get_mag_u64.c

bn_mp_grow.o: $(TOMMATH_DIR)/bn_mp_grow.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_grow.c

1685
1686
1687
1688
1689
1690
1691






1692
1693
1694
1695
1696
1697
1698
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758







+
+
+
+
+
+








bn_mp_neg.o: $(TOMMATH_DIR)/bn_mp_neg.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_neg.c

bn_mp_or.o: $(TOMMATH_DIR)/bn_mp_or.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_or.c

bn_mp_pack.o: $(TOMMATH_DIR)/bn_mp_pack.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_pack.c

bn_mp_pack_count.o: $(TOMMATH_DIR)/bn_mp_pack_count.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_pack_count.c

bn_mp_radix_size.o: $(TOMMATH_DIR)/bn_mp_radix_size.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_radix_size.c

bn_mp_radix_smap.o: $(TOMMATH_DIR)/bn_mp_radix_smap.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_radix_smap.c

bn_mp_read_radix.o: $(TOMMATH_DIR)/bn_mp_read_radix.c $(MATHHDRS)
1736
1737
1738
1739
1740
1741
1742



1743
1744
1745
1746
1747
1748
1749
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812







+
+
+








bn_mp_to_radix.o: $(TOMMATH_DIR)/bn_mp_to_radix.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_to_radix.c

bn_mp_ubin_size.o: $(TOMMATH_DIR)/bn_mp_ubin_size.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_ubin_size.c

bn_mp_unpack.o: $(TOMMATH_DIR)/bn_mp_unpack.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_unpack.c

bn_mp_xor.o: $(TOMMATH_DIR)/bn_mp_xor.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_xor.c

bn_mp_zero.o: $(TOMMATH_DIR)/bn_mp_zero.c $(MATHHDRS)
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_zero.c

bn_s_mp_add.o: $(TOMMATH_DIR)/bn_s_mp_add.c $(MATHHDRS)
1766
1767
1768
1769
1770
1771
1772
1773

1774
1775
1776

1777
1778
1779

1780
1781
1782
1783
1784
1785
1786
1829
1830
1831
1832
1833
1834
1835

1836
1837
1838

1839
1840
1841

1842
1843
1844
1845
1846
1847
1848
1849







-
+


-
+


-
+








tclUnixFCmd.o: $(UNIX_DIR)/tclUnixFCmd.c
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixFCmd.c

tclUnixFile.o: $(UNIX_DIR)/tclUnixFile.c $(FSHDR)
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixFile.c

tclEpollNotfy.o: $(UNIX_DIR)/tclEpollNotfy.c
tclEpollNotfy.o: $(UNIX_DIR)/tclEpollNotfy.c $(UNIX_DIR)/tclUnixNotfy.c
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclEpollNotfy.c

tclKqueueNotfy.o: $(UNIX_DIR)/tclKqueueNotfy.c
tclKqueueNotfy.o: $(UNIX_DIR)/tclKqueueNotfy.c $(UNIX_DIR)/tclUnixNotfy.c
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclKqueueNotfy.c

tclSelectNotfy.o: $(UNIX_DIR)/tclSelectNotfy.c
tclSelectNotfy.o: $(UNIX_DIR)/tclSelectNotfy.c $(UNIX_DIR)/tclUnixNotfy.c
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclSelectNotfy.c

tclUnixPipe.o: $(UNIX_DIR)/tclUnixPipe.c
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixPipe.c

tclUnixSock.o: $(UNIX_DIR)/tclUnixSock.c
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixSock.c
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1909
1910
1911
1912
1913
1914
1915



1916
1917
1918



1919
1920
1921









1922
1923
1924
1925
1926
1927
1928







-
-
-



-
-
-



-
-
-
-
-
-
-
-
-







#--------------------------------------------------------------------------
# Compat binaries, these must be compiled for use in a shared library even
# though they may be placed in a static executable or library. Since they are
# included in both the tcl library and the stub library, they need to be
# relocatable.
#--------------------------------------------------------------------------

opendir.o: $(COMPAT_DIR)/opendir.c
	$(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/opendir.c

mkstemp.o: $(COMPAT_DIR)/mkstemp.c
	$(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/mkstemp.c

memcmp.o: $(COMPAT_DIR)/memcmp.c
	$(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/memcmp.c

strncasecmp.o: $(COMPAT_DIR)/strncasecmp.c
	$(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/strncasecmp.c

strstr.o: $(COMPAT_DIR)/strstr.c
	$(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/strstr.c

strtol.o: $(COMPAT_DIR)/strtol.c
	$(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/strtol.c

strtoul.o: $(COMPAT_DIR)/strtoul.c
	$(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/strtoul.c

waitpid.o: $(COMPAT_DIR)/waitpid.c
	$(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/waitpid.c

fake-rfc2553.o: $(COMPAT_DIR)/fake-rfc2553.c
	$(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/fake-rfc2553.c

# For building zlib, only used in some build configurations
1903
1904
1905
1906
1907
1908
1909










1910

1911
1912
1913

1914
1915
1916

1917
1918
1919
1920
1921
1922
1923
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967

1968
1969
1970

1971
1972
1973

1974
1975
1976
1977
1978
1979
1980
1981







+
+
+
+
+
+
+
+
+
+
-
+


-
+


-
+








#--------------------------------------------------------------------------
# Stub library binaries, these must be compiled for use in a shared library
# even though they will be placed in a static archive
#--------------------------------------------------------------------------

tclStubLib.o: $(GENERIC_DIR)/tclStubLib.c
	$(CC) -c $(STUB_CC_SWITCHES) -DSTATIC_BUILD @CFLAGS_NOLTO@ $(GENERIC_DIR)/tclStubLib.c

tclStubCall.o: $(GENERIC_DIR)/tclStubCall.c
	$(CC) -c $(STUB_CC_SWITCHES) -DSTATIC_BUILD \
		-DCFG_RUNTIME_DLLFILE="\"$(TCL_LIB_FILE)\"" \
		-DCFG_RUNTIME_LIBDIR="\"$(libdir)\"" \
		-DCFG_RUNTIME_BINDIR="\"$(bindir)\"" \
		$(GENERIC_DIR)/tclStubCall.c

tclStubLibTbl.o: $(GENERIC_DIR)/tclStubLibTbl.c
	$(CC) -c $(STUB_CC_SWITCHES) -DSTATIC_BUILD $(GENERIC_DIR)/tclStubLib.c
	$(CC) -c $(STUB_CC_SWITCHES) -DSTATIC_BUILD $(GENERIC_DIR)/tclStubLibTbl.c

tclTomMathStubLib.o: $(GENERIC_DIR)/tclTomMathStubLib.c
	$(CC) -c $(STUB_CC_SWITCHES) $(GENERIC_DIR)/tclTomMathStubLib.c
	$(CC) -c $(STUB_CC_SWITCHES) @CFLAGS_NOLTO@ $(GENERIC_DIR)/tclTomMathStubLib.c

tclOOStubLib.o: $(GENERIC_DIR)/tclOOStubLib.c
	$(CC) -c $(STUB_CC_SWITCHES) $(GENERIC_DIR)/tclOOStubLib.c
	$(CC) -c $(STUB_CC_SWITCHES) @CFLAGS_NOLTO@ $(GENERIC_DIR)/tclOOStubLib.c

.c.o:
	$(CC) -c $(CC_SWITCHES) $<

#--------------------------------------------------------------------------
# Minizip implementation
#--------------------------------------------------------------------------
1976
1977
1978
1979
1980
1981
1982

1983
1984
1985
1986
1987
1988
1989








1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005




2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016





2017
2018
2019
2020
2021
2022
2023
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099







+







+
+
+
+
+
+
+
+
















+
+
+
+











+
+
+
+
+







# Propagate configure args like --enable-64bit to package configure
PKG_CFG_ARGS		= @PKG_CFG_ARGS@
# If PKG_DIR is changed to a different relative depth to the build dir, need
# to adapt the ../.. relative paths below and at the top of configure.ac (we
# cannot use absolute paths due to issues in nested configure when path to
# build dir contains spaces).
PKG_DIR			= ./pkgs
PKG8_DIR			= ./pkgs8

configure-packages:
	@for i in $(PKGS_DIR)/*; do \
	    if [ -d $$i ] ; then \
		if [ -x $$i/configure ] ; then \
		    pkg=`basename $$i`; \
		    echo "Configuring package '$$pkg'"; \
		    mkdir -p $(PKG8_DIR)/$$pkg; \
		    if [ ! -f $(PKG8_DIR)/$$pkg/Makefile ] ; then \
			( cd $(PKG8_DIR)/$$pkg; \
			  $$i/configure --with-tcl8 --with-tcl=../.. \
			      --with-tclinclude=$(GENERIC_DIR) \
			      $(PKG_CFG_ARGS) --libdir=$(PACKAGE_DIR) \
			      --enable-shared; ) || exit $$?; \
		    fi; \
		    mkdir -p $(PKG_DIR)/$$pkg; \
		    if [ ! -f $(PKG_DIR)/$$pkg/Makefile ] ; then \
			( cd $(PKG_DIR)/$$pkg; \
			  $$i/configure --with-tcl=../.. \
			      --with-tclinclude=$(GENERIC_DIR) \
			      $(PKG_CFG_ARGS) --libdir=$(PACKAGE_DIR) \
			      --enable-shared; ) || exit $$?; \
		    fi; \
		fi; \
	    fi; \
	done

packages: configure-packages ${STUB_LIB_FILE}
	@for i in $(PKGS_DIR)/*; do \
	    if [ -d $$i ] ; then \
		pkg=`basename $$i`; \
		if [ -f $(PKG8_DIR)/$$pkg/Makefile ] ; then \
		    echo "Building package '$$pkg' for Tcl 8"; \
		    ( cd $(PKG8_DIR)/$$pkg; $(MAKE); ) || exit $$?; \
		fi; \
		if [ -f $(PKG_DIR)/$$pkg/Makefile ] ; then \
		    echo "Building package '$$pkg'"; \
		    ( cd $(PKG_DIR)/$$pkg; $(MAKE); ) || exit $$?; \
		fi; \
	    fi; \
	done

install-packages: packages
	@for i in $(PKGS_DIR)/*; do \
	    if [ -d $$i ] ; then \
		pkg=`basename $$i`; \
		if [ -f $(PKG8_DIR)/$$pkg/Makefile ] ; then \
		    echo "Installing package '$$pkg' for Tcl 8"; \
		    ( cd $(PKG8_DIR)/$$pkg; $(MAKE) install \
			  "DESTDIR=$(INSTALL_ROOT)"; ) || exit $$?; \
		fi; \
		if [ -f $(PKG_DIR)/$$pkg/Makefile ] ; then \
		    echo "Installing package '$$pkg'"; \
		    ( cd $(PKG_DIR)/$$pkg; $(MAKE) install \
			  "DESTDIR=$(INSTALL_ROOT)"; ) || exit $$?; \
		fi; \
	    fi; \
	done
2037
2038
2039
2040
2041
2042
2043



2044
2045
2046
2047
2048
2049
2050
2051
2052
2053




2054
2055
2056
2057
2058
2059

2060
2061
2062
2063
2064
2065
2066
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150







+
+
+










+
+
+
+






+







	    fi; \
	done

clean-packages:
	@for i in $(PKGS_DIR)/*; do \
	    if [ -d $$i ] ; then \
		pkg=`basename $$i`; \
		if [ -f $(PKG8_DIR)/$$pkg/Makefile ] ; then \
		    ( cd $(PKG8_DIR)/$$pkg; $(MAKE) clean; ) \
		fi; \
		if [ -f $(PKG_DIR)/$$pkg/Makefile ] ; then \
		    ( cd $(PKG_DIR)/$$pkg; $(MAKE) clean; ) \
		fi; \
	    fi; \
	done

distclean-packages:
	@for i in $(PKGS_DIR)/*; do \
	    if [ -d $$i ] ; then \
		pkg=`basename $$i`; \
		if [ -f $(PKG8_DIR)/$$pkg/Makefile ] ; then \
		    ( cd $(PKG8_DIR)/$$pkg; $(MAKE) distclean; ) \
		fi; \
		rm -rf $(PKG8_DIR)/$$pkg; \
		if [ -f $(PKG_DIR)/$$pkg/Makefile ] ; then \
		    ( cd $(PKG_DIR)/$$pkg; $(MAKE) distclean; ) \
		fi; \
		rm -rf $(PKG_DIR)/$$pkg; \
	    fi; \
	done; \
	rm -rf $(PKG8_DIR)
	rm -rf $(PKG_DIR)

dist-packages: configure-packages
	@rm -rf $(DISTROOT)/pkgs; \
	mkdir -p $(DISTROOT)/pkgs; \
	for i in $(PKGS_DIR)/*; do \
	    if [ -d $$i ] ; then \
2078
2079
2080
2081
2082
2083
2084


2085
2086
2087
2088
2089
2090
2091
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177







+
+








# The following target generates the file generic/tclDate.c from the yacc
# grammar found in generic/tclGetDate.y. This is only run by hand as yacc is
# not available in all environments. The name of the .c file is different than
# the name of the .y file so that make doesn't try to automatically regenerate
# the .c file.

#
# Remark: see [54a305cb88]. tclDate.c is manually edited, removing the unused "yynerrs" variable
gendate:
	bison --output-file=$(GENERIC_DIR)/tclDate.c \
		--no-lines \
		--name-prefix=TclDate \
		$(GENERIC_DIR)/tclGetDate.y

#	yacc -l $(GENERIC_DIR)/tclGetDate.y
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
2300
2301
2302
2303
2304
2305
2306



2307
2308
2309
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







-
-
-
+
+
+









+
+
+
+
+

-
-
+
+
+
+
+







# the distribution. DISTDIR must be an absolute path name.
#

DISTROOT = /tmp/dist
DISTNAME = tcl${VERSION}${PATCH_LEVEL}
ZIPNAME	 = tcl${MAJOR_VERSION}${MINOR_VERSION}${PATCH_LEVEL}-src.zip
DISTDIR	 = $(DISTROOT)/$(DISTNAME)
DIST_INSTALL_DATA   = CPPROG='cp -p' $(INSTALL) -m 644
DIST_INSTALL_SCRIPT = CPPROG='cp -p' $(INSTALL) -m 755
BUILTIN_PACKAGE_LIST = cookiejar http opt msgcat reg dde tcltest platform
DIST_INSTALL_DATA   = $(INSTALL) -p -m 644
DIST_INSTALL_SCRIPT = $(INSTALL) -p -m 755
BUILTIN_PACKAGE_LIST = cookiejar http opt msgcat registry dde tcltest platform

$(UNIX_DIR)/configure: $(UNIX_DIR)/configure.ac $(UNIX_DIR)/tcl.m4 \
		$(UNIX_DIR)/aclocal.m4
	cd $(UNIX_DIR); autoconf
$(MAC_OSX_DIR)/configure: $(MAC_OSX_DIR)/configure.ac $(UNIX_DIR)/configure
	cd $(MAC_OSX_DIR); autoconf
$(UNIX_DIR)/tclConfig.h.in: $(MAC_OSX_DIR)/configure
	cd $(MAC_OSX_DIR); autoheader; touch $@

tclUuid.h: $(TOP_DIR)/manifest.uuid
	echo "#define TCL_VERSION_UUID \\" >$@
	cat $(TOP_DIR)/manifest.uuid >>$@
	echo "" >>$@

$(TOP_DIR)/manifest.uuid:
	printf "git." >$(TOP_DIR)/manifest.uuid
	git rev-parse HEAD >>$(TOP_DIR)/manifest.uuid
	printf "git-" >$(TOP_DIR)/manifest.uuid
	(cd $(TOP_DIR); git rev-parse HEAD >>$(TOP_DIR)/manifest.uuid || \
	    (printf "svn-r" >$(TOP_DIR)/manifest.uuid ; \
	    svn info --show-item last-changed-revision >>$(TOP_DIR)/manifest.uuid) || \
	    printf "unknown" >$(TOP_DIR)/manifest.uuid)

dist: $(UNIX_DIR)/configure $(UNIX_DIR)/tclConfig.h.in $(UNIX_DIR)/tcl.pc.in genstubs \
		$(MAC_OSX_DIR)/configure $(TOP_DIR)/manifest.uuid dist-packages ${NATIVE_TCLSH}
	rm -rf $(DISTDIR)
	$(INSTALL_DATA_DIR) $(DISTDIR)/unix
	$(DIST_INSTALL_DATA) $(TOP_DIR)/manifest.uuid $(DISTDIR)
	$(DIST_INSTALL_DATA) $(UNIX_DIR)/*.[ch] $(DISTDIR)/unix
2250
2251
2252
2253
2254
2255
2256
2257
2258


2259
2260
2261
2262
2263
2264
2265
2266
2267
2268

2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287





2288
2289
2290

2291






2292


















2293
2294
2295
2296
2297
2298
2299




2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
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
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419


2420
2421
2422
2423
2424
2425
2426
2427
2428

2429
2430
2431
2432
2433
2434

2435
2436
2437
2438








2439
2440
2441
2442

2443


2444


2445
2446

2447
2448
2449
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







-
-
+
+
-








-
+



















+
+
+
+
+



+

+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
-
+
+
+
+





-






-
+



-
-
-
-
-
-
-
-




-
+
-
-
+
-
-
+

-
+



-
-






+
+












-
+







		$(UNIX_DIR)/tcl.pc.in $(DISTDIR)/unix
	$(DIST_INSTALL_SCRIPT) $(UNIX_DIR)/configure $(UNIX_DIR)/ldAix $(DISTDIR)/unix
	$(INSTALL_DATA_DIR) $(DISTDIR)/generic
	$(DIST_INSTALL_DATA) $(GENERIC_DIR)/*.[cdh] $(DISTDIR)/generic
	$(DIST_INSTALL_DATA) $(GENERIC_DIR)/*.decls $(DISTDIR)/generic
	$(DIST_INSTALL_DATA) $(GENERIC_DIR)/README $(DISTDIR)/generic
	$(DIST_INSTALL_DATA) $(GENERIC_DIR)/tclGetDate.y $(DISTDIR)/generic
	$(DIST_INSTALL_DATA) $(TOP_DIR)/changes $(TOP_DIR)/ChangeLog $(TOP_DIR)/README.md \
		$(TOP_DIR)/ChangeLog.[12]??? $(TOP_DIR)/license.terms \
	$(DIST_INSTALL_DATA) $(TOP_DIR)/changes.md $(TOP_DIR)/README.md \
		$(TOP_DIR)/license.terms $(DISTDIR)
		$(DISTDIR)
	$(INSTALL_DATA_DIR) $(DISTDIR)/library
	$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(TOP_DIR)/library/*.tcl \
		$(TOP_DIR)/library/manifest.txt \
		$(TOP_DIR)/library/tclIndex $(DISTDIR)/library
	@for i in $(BUILTIN_PACKAGE_LIST); do \
	    $(INSTALL_DATA_DIR) $(DISTDIR)/library/$$i;\
	    $(DIST_INSTALL_DATA) $(TOP_DIR)/library/$$i/*.tcl $(DISTDIR)/library/$$i; \
	done
	$(DIST_INSTALL_DATA) $(TOP_DIR)/library/cookiejar/*.txt.gz $(DISTDIR)/library/cookiejar
	$(DIST_INSTALL_DATA) $(TOP_DIR)/library/cookiejar/*.dat.gz $(DISTDIR)/library/cookiejar
	$(INSTALL_DATA_DIR) $(DISTDIR)/library/encoding
	$(DIST_INSTALL_DATA) $(TOP_DIR)/library/encoding/*.enc $(DISTDIR)/library/encoding
	$(INSTALL_DATA_DIR) $(DISTDIR)/library/msgs
	$(DIST_INSTALL_DATA) $(TOP_DIR)/library/msgs/*.msg $(DISTDIR)/library/msgs
	@echo cp -r $(TOP_DIR)/library/tzdata $(DISTDIR)/library/tzdata
	@( cd $(TOP_DIR); find library/tzdata -type f -print ) \
	    | ( cd $(TOP_DIR) ; xargs tar cf - ) \
	    | ( cd $(DISTDIR) ; tar xfp - )
	$(INSTALL_DATA_DIR) $(DISTDIR)/doc
	$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(TOP_DIR)/doc/*.[13n] \
		$(TOP_DIR)/doc/man.macros $(DISTDIR)/doc
	$(INSTALL_DATA_DIR) $(DISTDIR)/compat
	$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(COMPAT_DIR)/*.[ch] \
		$(COMPAT_DIR)/README $(DISTDIR)/compat
	$(INSTALL_DATA_DIR) $(DISTDIR)/compat/zlib
	@echo cp -r $(COMPAT_DIR)/zlib $(DISTDIR)/compat/zlib
	@( cd $(COMPAT_DIR)/zlib; find . -type f -print ) \
	    | ( cd $(COMPAT_DIR)/zlib ; xargs tar cf - ) \
	    | ( cd $(DISTDIR)/compat/zlib ; tar xfp - )
	$(INSTALL_DATA_DIR) $(DISTDIR)/libtommath
	@echo cp -r $(TOP_DIR)/libtommath $(DISTDIR)/libtommath
	@( cd $(TOP_DIR)/libtommath; find . -type f -print ) \
	    | ( cd $(TOP_DIR)/libtommath ; xargs tar cf - ) \
	    | ( cd $(DISTDIR)/libtommath ; tar xfp - )
	$(INSTALL_DATA_DIR) $(DISTDIR)/tests
	$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(DISTDIR)/tests
	$(DIST_INSTALL_DATA) $(TOP_DIR)/tests/*.test $(TOP_DIR)/tests/README \
		$(TOP_DIR)/tests/*.bench $(TOP_DIR)/tests/*.tar.gz \
		$(TOP_DIR)/tests/httpd $(TOP_DIR)/tests/*.tcl \
		$(TOP_DIR)/tests/*.zip $(DISTDIR)/tests
	@mkdir $(DISTDIR)/tests/auto0
	for i in auto1 auto2 ; \
	    do \
		$(INSTALL_DATA_DIR) $(DISTDIR)/tests/auto0/$$i ;\
		$(DIST_INSTALL_DATA) $(TOP_DIR)/tests/auto0/$$i/tclIndex $(TOP_DIR)/tests/auto0/$$i/*.tcl \
		$(DISTDIR)/tests
			$(DISTDIR)/tests/auto0/$$i; \
	    done;
	for i in modules modules/mod1 modules/mod2 ; \
	    do \
		$(INSTALL_DATA_DIR) $(DISTDIR)/tests/auto0/$$i ;\
		$(DIST_INSTALL_DATA) $(TOP_DIR)/tests/auto0/$$i/*.tm \
			$(DISTDIR)/tests/auto0/$$i; \
	    done;
	@mkdir $(DISTDIR)/tests/zipfiles
	$(INSTALL_DATA_DIR) $(DISTDIR)/tests/zipfiles
	$(DIST_INSTALL_DATA) $(TOP_DIR)/tests/zipfiles/*.zip \
		$(DISTDIR)/tests/zipfiles
	$(DIST_INSTALL_DATA) $(TOP_DIR)/tests/zipfiles/README \
		$(DISTDIR)/tests/zipfiles
	$(DIST_INSTALL_DATA) $(TOP_DIR)/tests/zipfiles/LICENSE-libzip \
		$(DISTDIR)/tests/zipfiles
	$(INSTALL_DATA_DIR) $(DISTDIR)/tests-perf
	$(DIST_INSTALL_DATA) $(TOP_DIR)/tests-perf/*.tcl $(DISTDIR)/tests-perf
	$(INSTALL_DATA_DIR) $(DISTDIR)/win
	$(DIST_INSTALL_DATA) $(TOP_DIR)/win/Makefile.in $(DISTDIR)/win
	$(DIST_INSTALL_DATA) $(TOP_DIR)/win/configure.ac \
		$(TOP_DIR)/win/tclConfig.sh.in $(TOP_DIR)/win/tclooConfig.sh \
		$(TOP_DIR)/win/tcl.m4 $(TOP_DIR)/win/aclocal.m4 \
		$(TOP_DIR)/win/tclsh.exe.manifest.in \
		$(DISTDIR)/win
		$(TOP_DIR)/win/tclsh.exe.manifest.in $(TOP_DIR)/win/tclUuid.h.in \
		$(TOP_DIR)/win/gitmanifest.in $(TOP_DIR)/win/svnmanifest.in \
		$(TOP_DIR)/win/x86_64-w64-mingw32-nmakehlp.exe $(DISTDIR)/win
	chmod 775 $(DISTDIR)/win/x86_64-w64-mingw32-nmakehlp.exe
	$(DIST_INSTALL_SCRIPT) $(TOP_DIR)/win/configure $(DISTDIR)/win
	$(DIST_INSTALL_DATA) $(TOP_DIR)/win/*.[ch] $(TOP_DIR)/win/*.ico $(TOP_DIR)/win/*.rc \
		$(DISTDIR)/win
	$(DIST_INSTALL_DATA) $(TOP_DIR)/win/*.bat $(DISTDIR)/win
	$(DIST_INSTALL_DATA) $(TOP_DIR)/win/*.vc $(DISTDIR)/win
	$(DIST_INSTALL_DATA) $(TOP_DIR)/win/tcl.hpj.in $(DISTDIR)/win
	$(DIST_INSTALL_DATA) $(TOP_DIR)/win/tcl.ds* $(DISTDIR)/win
	$(DIST_INSTALL_DATA) $(TOP_DIR)/win/README $(DISTDIR)/win
	$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(DISTDIR)/win
	$(INSTALL_DATA_DIR) $(DISTDIR)/macosx
	$(DIST_INSTALL_DATA) $(MAC_OSX_DIR)/GNUmakefile $(MAC_OSX_DIR)/README \
		$(MAC_OSX_DIR)/*.c $(MAC_OSX_DIR)/*.in \
		$(MAC_OSX_DIR)/*.ac $(MAC_OSX_DIR)/*.xcconfig \
		$(MAC_OSX_DIR)/*.ac \
		$(DISTDIR)/macosx
	$(DIST_INSTALL_SCRIPT) $(MAC_OSX_DIR)/configure $(DISTDIR)/macosx
	$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(DISTDIR)/macosx
	$(INSTALL_DATA_DIR) $(DISTDIR)/macosx/Tcl.xcode
	$(DIST_INSTALL_DATA) $(MAC_OSX_DIR)/Tcl.xcode/project.pbxproj \
		$(MAC_OSX_DIR)/Tcl.xcode/default.pbxuser \
		$(DISTDIR)/macosx/Tcl.xcode
	$(INSTALL_DATA_DIR) $(DISTDIR)/macosx/Tcl.xcodeproj
	$(DIST_INSTALL_DATA) $(MAC_OSX_DIR)/Tcl.xcodeproj/project.pbxproj \
		$(MAC_OSX_DIR)/Tcl.xcodeproj/default.pbxuser \
		$(DISTDIR)/macosx/Tcl.xcodeproj
	$(INSTALL_DATA_DIR) $(DISTDIR)/unix/dltest
	$(DIST_INSTALL_DATA) $(UNIX_DIR)/dltest/*.c $(UNIX_DIR)/dltest/Makefile.in \
		$(UNIX_DIR)/dltest/README $(DISTDIR)/unix/dltest
	$(INSTALL_DATA_DIR) $(DISTDIR)/tools
	$(DIST_INSTALL_DATA) $(TOOL_DIR)/Makefile.in $(TOOL_DIR)/README \
	$(DIST_INSTALL_DATA) $(TOOL_DIR)/README $(TOOL_DIR)/*.c $(TOOL_DIR)/*.svg \
		$(TOOL_DIR)/configure $(TOOL_DIR)/configure.ac \
		$(TOOL_DIR)/*.tcl $(TOOL_DIR)/man2tcl.c \
		$(TOOL_DIR)/*.tcl $(TOOL_DIR)/*.bmp $(TOOL_DIR)/valgrind_suppress \
		$(TOOL_DIR)/*.bmp $(TOOL_DIR)/tcl.hpj.in \
		$(DISTDIR)/tools
		$(TOOL_DIR)/valgrind_check_success $(DISTDIR)/tools
	chmod 755 $(DISTDIR)/tools/checkLibraryDoc.tcl \
		$(DISTDIR)/tools/configure $(DISTDIR)/tools/findBadExternals.tcl \
		$(DISTDIR)/tools/findBadExternals.tcl \
		$(DISTDIR)/tools/loadICU.tcl \
		$(DISTDIR)/tools/makeTestCases.tcl $(DISTDIR)/tools/tclZIC.tcl \
		$(DISTDIR)/tools/tcltk-man2html.tcl
	$(INSTALL_DATA_DIR) $(DISTDIR)/libtommath
	$(DIST_INSTALL_DATA) $(TOMMATH_SRCS) $(TOMMATH_DIR)/*.h $(DISTDIR)/libtommath
	$(INSTALL_DATA_DIR) $(DISTDIR)/pkgs
	$(DIST_INSTALL_DATA) $(TOP_DIR)/pkgs/README $(DISTDIR)/pkgs
	$(DIST_INSTALL_DATA) $(TOP_DIR)/pkgs/package.list.txt $(DISTDIR)/pkgs
	for i in `ls $(DISTROOT)/pkgs/*.tar.gz 2> /dev/null`; do \
	    tar -C $(DISTDIR)/pkgs -xzf "$$i"; \
	done
	$(INSTALL_DATA_DIR) $(DISTDIR)/.github/workflows
	$(DIST_INSTALL_DATA) $(TOP_DIR)/.github/workflows/*.yml $(DISTDIR)/.github/workflows

alldist: dist
	rm -f $(DISTROOT)/$(DISTNAME)-src.tar.gz $(DISTROOT)/$(ZIPNAME)
	( cd $(DISTROOT); \
		tar cf $(DISTNAME)-src.tar $(DISTNAME); \
		gzip -9 $(DISTNAME)-src.tar; \
		zip -qr8 $(ZIPNAME) $(DISTNAME) )

#--------------------------------------------------------------------------
# This target creates the HTML folder for Tcl & Tk and places it in
# DISTDIR/html. It uses the tcltk-man2html.tcl tool from the Tcl group's tool
# workspace. It depends on the Tcl & Tk being in directories called tcl9.* &
# tk8.* up two directories from the TOOL_DIR.
# tk9.* up two directories from the TOOL_DIR.
#
# Note that for platforms where this is important, it is more common to use a
# build of this HTML documentation that has already been placed online. As
# such, this rule is not guaranteed to work well on all systems; it only needs
# to function on those of the Tcl/Tk maintainers.
#
# Also note that the 8.6 tool build requires an installed 8.6 native Tcl
2376
2377
2378
2379
2380
2381
2382
2383


2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401

2402
2403
2404
2489
2490
2491
2492
2493
2494
2495

2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514

2515
2516
2517
2518







-
+
+

















-
+




html-tk: ${NATIVE_TCLSH}
	$(BUILD_HTML) --tk
	@EXTRA_BUILD_HTML@

BUILD_HTML = \
	@${NATIVE_TCLSH} $(TOOL_DIR)/tcltk-man2html.tcl \
		--tcl --useversion=$(MAJOR_VERSION).$(MINOR_VERSION) --htmldir="$(HTML_INSTALL_DIR)" \
		--useversion=$(MAJOR_VERSION).$(MINOR_VERSION) \
		--htmldir="$(HTML_INSTALL_DIR)" \
		--srcdir=$(TOP_DIR) $(BUILD_HTML_FLAGS)

#--------------------------------------------------------------------------
# The list of all the targets that do not correspond to real files. This stops
# 'make' from getting confused when someone makes an error in a rule.
#--------------------------------------------------------------------------

.PHONY: all binaries libraries objs doc html html-tcl html-tk test runtest
.PHONY: install install-strip install-binaries install-libraries
.PHONY: install-headers install-private-headers install-doc
.PHONY: clean distclean depend genstubs checkstubs checkexports checkuchar
.PHONY: shell gdb valgrind valgrindshell dist alldist rpm
.PHONY: tclLibObjs tcltest-real test-tcl gdb-test ro-test trace-test xttest
.PHONY: topDirName gendate gentommath_h trace-shell checkdoc
.PHONY: install-tzdata install-msgs
.PHONY: packages configure-packages test-packages clean-packages
.PHONY: dist-packages distclean-packages install-packages
.PHONY: install-libraries-zipfs-shared install-libraries-zipfs-static tclzipfile
.PHONY: tclzipfile

#--------------------------------------------------------------------------
# DO NOT DELETE THIS LINE -- make depend depends on it.

Changes to unix/README.

1
2
3
4
5
6
7
8
9
10
11

12
13
14
15

16
17
18
19
20
21
22
1
2
3
4
5
6
7
8
9
10

11
12
13
14

15
16
17
18
19
20
21
22










-
+



-
+







Tcl UNIX README
---------------

This is the directory where you configure, compile, test, and install UNIX
versions of Tcl. This directory also contains source files for Tcl that are
specific to UNIX. Some of the files in this directory are used on the PC or
MacOSX platform too, but they all depend on UNIX (POSIX/ANSI C) interfaces and
some of them only make sense under UNIX.

Updated forms of the information found in this file is available at:
	http://www.tcl.tk/doc/howto/compile.html#unix
	https://www.tcl-lang.org/doc/howto/compile.html#unix

For information on platforms where Tcl is known to compile, along with any
porting notes for getting it to work on those platforms, see:
	http://www.tcl.tk/software/tcltk/platforms.html
	https://www.tcl-lang.org/software/tcltk/platforms.html

The rest of this file contains instructions on how to do this. The release
should compile and run either "out of the box" or with trivial changes on any
UNIX-like system that approximates POSIX, BSD, or System V. We know that it
runs on workstations from Sun, H-P, DEC, IBM, and SGI, as well as PCs running
Linux, BSDI, and SCO UNIX. To compile for a PC running Windows, see the README
file in the directory ../win. To compile for MacOSX, see the README file in
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
85
86
87
88
89
90
91

92
93
94
95
96
97
98
99







-
+







				is also enabled). If STRING is omitted,
				defaults to 'tcl'.
	--enable-man-compression=PROG
				Compress the manpages using PROG.
	--enable-dtrace		Enable tcl DTrace provider (if DTrace is
				available on the platform), c.f. tclDTrace.d
				for descriptions of the probes made available,
				see http://wiki.tcl.tk/DTrace for more details
				see https://wiki.tcl-lang.org/page/DTrace for more details
	--with-encoding=ENCODING Specifies the encoding for compile-time
				configuration values. Defaults to utf-8,
				which is also sufficient for ASCII.
	--with-tzdata=FLAG	Specifies whether to install timezone data. By
				default, the configure script tries to detect
				whether a usable timezone database is present
				on the system already.

Changes to unix/configure.

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

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
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
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


-
+


-
+
+










-
+
+






-
-
+
+




+




+
+
+
+
+
+
+
+



-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+








-
-
-
-
-
-
-








+
-
-
+
+
+
+
+





-
+





-
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-




















-
-
-
+
+
+




-
+
+






-
-
+
+




+














-
+
+

-
-
+
+
+


+
+






-
+
+

-
-
+
+
+

-
+
+

-
-
+
+




+
-
+
+
+
+





-
+

-
+
+

-
+
+







+
+
+
+
+
-
-
+
+
+

+
+
-
+
-


-
+
+
















-
-
+
+



-
-
-
-
-
-
+
+
+
+
+
+
+

-
+





-
+
+



















+







#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for tcl 9.0.
# Generated by GNU Autoconf 2.72 for tcl 9.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
# Copyright (C) 1992-1996, 1998-2017, 2020-2023 Free Software Foundation,
# Inc.
#
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##

# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
then :
  emulate sh
  NULLCMD=:
  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '${1+"$@"}'='"$@"'
  setopt NO_GLOB_SUBST
else
  case `(set -o) 2>/dev/null` in #(
else case e in #(
  e) case `(set -o) 2>/dev/null` in #(
  *posix*) :
    set -o posix ;; #(
  *) :
     ;;
esac ;;
esac
fi



# Reset variables that may have inherited troublesome values from
# the environment.

# IFS needs to be set, to space, tab, and newline, in precisely that order.
# (If _AS_PATH_WALK were called with IFS unset, it would have the
# side effect of setting IFS to empty, thus disabling word splitting.)
# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
# Printing a long string crashes Solaris 7 /usr/bin/printf.
as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
# Prefer a ksh shell builtin over an external printf program on Solaris,
# but without wasting forks for bash or zsh.
if test -z "$BASH_VERSION$ZSH_VERSION" \
    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
  as_echo='print -r --'
  as_echo_n='print -rn --'
IFS=" ""	$as_nl"

elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
  as_echo='printf %s\n'
  as_echo_n='printf %s'
PS1='$ '
PS2='> '
else
  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
    as_echo_n='/usr/ucb/echo -n'
  else
    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
    as_echo_n_body='eval
PS4='+ '
      arg=$1;
      case $arg in #(
      *"$as_nl"*)
	expr "X$arg" : "X\\(.*\\)$as_nl";
	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
      esac;
      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
    '
    export as_echo_n_body

# Ensure predictable behavior from utilities with locale-dependent output.
LC_ALL=C
export LC_ALL
    as_echo_n='sh -c $as_echo_n_body as_echo'
  fi
  export as_echo_body
  as_echo='sh -c $as_echo_body as_echo'
fi
LANGUAGE=C
export LANGUAGE

# We cannot yet rely on "unset" to work, but we need these variables
# to be unset--not just set to an empty or harmless value--now, to
# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct
# also avoids known problems related to "unset" and subshell syntax
# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
do eval test \${$as_var+y} \
  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done

# Ensure that fds 0, 1, and 2 are open.
if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
if (exec 3>&2)            ; then :; else exec 2>/dev/null; fi

# The user is always right.
if test "${PATH_SEPARATOR+set}" != set; then
if ${PATH_SEPARATOR+false} :; then
  PATH_SEPARATOR=:
  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
      PATH_SEPARATOR=';'
  }
fi


# IFS
# We need space, tab and new line, in precisely that order.  Quoting is
# there to prevent editors from complaining about space-tab.
# (If _AS_PATH_WALK were called with IFS unset, it would disable word
# splitting by setting IFS to empty value.)
IFS=" ""	$as_nl"

# Find who we are.  Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
  *[\\/]* ) as_myself=$0 ;;
  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    test -r "$as_dir$0" && as_myself=$as_dir$0 && break
  done
IFS=$as_save_IFS

     ;;
esac
# We did not find ourselves, most probably we were run as `sh COMMAND'
# We did not find ourselves, most probably we were run as 'sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
  as_myself=$0
fi
if test ! -f "$as_myself"; then
  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
  printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
  exit 1
fi

# Unset variables that we do not need and which cause bugs (e.g. in
# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
# suppresses any "Segmentation fault" message there.  '((' could
# trigger a bug in pdksh 5.2.14.
for as_var in BASH_ENV ENV MAIL MAILPATH
do eval test x\${$as_var+set} = xset \
  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done
PS1='$ '
PS2='> '
PS4='+ '

# NLS nuisances.
LC_ALL=C
export LC_ALL
LANGUAGE=C
export LANGUAGE

# CDPATH.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH

# Use a proper internal environment variable to ensure we don't fall
  # into an infinite loop, continuously re-executing ourselves.
  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
    _as_can_reexec=no; export _as_can_reexec;
    # We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
  *v*x* | *x*v* ) as_opts=-vx ;;
  *v* ) as_opts=-v ;;
  *x* ) as_opts=-x ;;
  * ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
as_fn_exit 255
# out after a failed 'exec'.
printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
  fi
  # We don't want this to propagate to other subprocesses.
          { _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
  as_bourne_compatible="if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
then :
  emulate sh
  NULLCMD=:
  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '\${1+\"\$@\"}'='\"\$@\"'
  setopt NO_GLOB_SUBST
else
  case \`(set -o) 2>/dev/null\` in #(
else case e in #(
  e) case \`(set -o) 2>/dev/null\` in #(
  *posix*) :
    set -o posix ;; #(
  *) :
     ;;
esac ;;
esac
fi
"
  as_required="as_fn_return () { (exit \$1); }
as_fn_success () { as_fn_return 0; }
as_fn_failure () { as_fn_return 1; }
as_fn_ret_success () { return 0; }
as_fn_ret_failure () { return 1; }

exitcode=0
as_fn_success || { exitcode=1; echo as_fn_success failed.; }
as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
if ( set x; as_fn_ret_success y && test x = \"\$1\" )
then :

else
  exitcode=1; echo positional parameters were not saved.
else case e in #(
  e) exitcode=1; echo positional parameters were not saved. ;;
esac
fi
test x\$exitcode = x0 || exit 1
blah=\$(echo \$(echo blah))
test x\"\$blah\" = xblah || exit 1
test -x / || exit 1"
  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
test \$(( 1 + 1 )) = 2 || exit 1"
  if (eval "$as_required") 2>/dev/null; then :
  if (eval "$as_required") 2>/dev/null
then :
  as_have_required=yes
else
  as_have_required=no
else case e in #(
  e) as_have_required=no ;;
esac
fi
  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
then :

else
  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
else case e in #(
  e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
  as_found=:
  case $as_dir in #(
	 /*)
	   for as_base in sh bash ksh sh5; do
	     # Try only shells that exist, to save several forks.
	     as_shell=$as_dir/$as_base
	     as_shell=$as_dir$as_base
	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
		    as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
then :
  CONFIG_SHELL=$as_shell as_have_required=yes
		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
		   if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
then :
  break 2
fi
fi
	   done;;
       esac
  as_found=false
done
IFS=$as_save_IFS
if $as_found
then :

else case e in #(
$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
  e) if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
	      as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
then :
  CONFIG_SHELL=$SHELL as_have_required=yes
fi ;;
esac
fi; }
fi
IFS=$as_save_IFS


      if test "x$CONFIG_SHELL" != x; then :
      if test "x$CONFIG_SHELL" != x
then :
  export CONFIG_SHELL
             # We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
  *v*x* | *x*v* ) as_opts=-vx ;;
  *v* ) as_opts=-v ;;
  *x* ) as_opts=-x ;;
  * ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
# out after a failed 'exec'.
printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi

    if test x$as_have_required = xno; then :
  $as_echo "$0: This script requires a shell more modern than all"
  $as_echo "$0: the shells that I found on your system."
  if test x${ZSH_VERSION+set} = xset ; then
    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
    if test x$as_have_required = xno
then :
  printf "%s\n" "$0: This script requires a shell more modern than all"
  printf "%s\n" "$0: the shells that I found on your system."
  if test ${ZSH_VERSION+y} ; then
    printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
    printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
  else
    $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
    printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
  fi
  exit 1
fi
fi ;;
esac
fi
fi
SHELL=${CONFIG_SHELL-/bin/sh}
export SHELL
# Unset more variables known to interfere with behavior of common tools.
CLICOLOR_FORCE= GREP_OPTIONS=
unset CLICOLOR_FORCE GREP_OPTIONS

## --------------------- ##
## M4sh Shell Functions. ##
## --------------------- ##
# as_fn_unset VAR
# ---------------
# Portably unset VAR.
as_fn_unset ()
{
  { eval $1=; unset $1;}
}
as_unset=as_fn_unset


# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
as_fn_set_status ()
{
  return $1
318
319
320
321
322
323
324
325

326
327
328
329
330
331
332
333
334

335
336
337
338
339
340
341
324
325
326
327
328
329
330

331
332
333
334
335
336
337
338
339

340
341
342
343
344
345
346
347







-
+








-
+







  case $as_dir in #(
  -*) as_dir=./$as_dir;;
  esac
  test -d "$as_dir" || eval $as_mkdir_p || {
    as_dirs=
    while :; do
      case $as_dir in #(
      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
      *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
      *) as_qdir=$as_dir;;
      esac
      as_dirs="'$as_qdir' $as_dirs"
      as_dir=`$as_dirname -- "$as_dir" ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$as_dir" : 'X\(//\)[^/]' \| \
	 X"$as_dir" : 'X\(//\)$' \| \
	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$as_dir" |
printf "%s\n" X"$as_dir" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
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
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







-
+
+




-
-
+
+


-
+
+







-
+
+




-
-
+
+


-
+
+













-
+

-
+







} # as_fn_executable_p
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
then :
  eval 'as_fn_append ()
  {
    eval $1+=\$2
  }'
else
  as_fn_append ()
else case e in #(
  e) as_fn_append ()
  {
    eval $1=\$$1\$2
  }
  } ;;
esac
fi # as_fn_append

# as_fn_arith ARG...
# ------------------
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
then :
  eval 'as_fn_arith ()
  {
    as_val=$(( $* ))
  }'
else
  as_fn_arith ()
else case e in #(
  e) as_fn_arith ()
  {
    as_val=`expr "$@" || test $? -eq 1`
  }
  } ;;
esac
fi # as_fn_arith


# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
  as_status=$1; test $as_status -eq 0 && as_status=1
  if test "$4"; then
    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
  fi
  $as_echo "$as_me: error: $2" >&2
  printf "%s\n" "$as_me: error: $2" >&2
  as_fn_exit $as_status
} # as_fn_error

if expr a : '\(a\)' >/dev/null 2>&1 &&
   test "X`expr 00001 : '.*\(...\)'`" = X001; then
  as_expr=expr
else
435
436
437
438
439
440
441
442

443
444
445
446
447
448
449
445
446
447
448
449
450
451

452
453
454
455
456
457
458
459







-
+







  as_dirname=false
fi

as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
	 X"$0" : 'X\(//\)$' \| \
	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X/"$0" |
printf "%s\n" X/"$0" |
    sed '/^.*\/\([^/][^/]*\)\/*$/{
	    s//\1/
	    q
	  }
	  /^X\/\(\/\/\)$/{
	    s//\1/
	    q
468
469
470
471
472
473
474


475
476
477
478
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
478
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







+
+











-
+













+
+
+
+












+
+
+
+
+
+












-
-
-
+
+
+







  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
  sed -n '
    p
    /[$]LINENO/=
  ' <$as_myself |
    sed '
      t clear
      :clear
      s/[$]LINENO.*/&-/
      t lineno
      b
      :lineno
      N
      :loop
      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
      t loop
      s/-\n.*//
    ' >$as_me.lineno &&
  chmod +x "$as_me.lineno" ||
    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
    { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }

  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
  # already done that, so ensure we don't try to do so again and fall
  # in an infinite loop.  This has already happened in practice.
  _as_can_reexec=no; export _as_can_reexec
  # Don't try to exec as it changes $[0], causing all sort of problems
  # (the dirname of $[0] is not the place where we might find the
  # original and so on.  Autoconf is especially sensitive to this).
  . "./$as_me.lineno"
  # Exit status is that of the last command.
  exit
}


# Determine whether it's possible to make 'echo' print without a newline.
# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
  case `echo 'xy\c'` in
  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
  xy)  ECHO_C='\c';;
  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
       ECHO_T='	';;
  esac;;
*)
  ECHO_N='-n';;
esac

# For backward compatibility with old third-party macros, we provide
# the shell variables $as_echo and $as_echo_n.  New code should use
# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
as_echo='printf %s\n'
as_echo_n='printf %s'

rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
  rm -f conf$$.dir/conf$$.file
else
  rm -f conf$$.dir
  mkdir conf$$.dir 2>/dev/null
fi
if (echo >conf$$.file) 2>/dev/null; then
  if ln -s conf$$.file conf$$ 2>/dev/null; then
    as_ln_s='ln -s'
    # ... but there are two gotchas:
    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
    # In both cases, we have to default to `cp -pR'.
    # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail.
    # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable.
    # In both cases, we have to default to 'cp -pR'.
    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
      as_ln_s='cp -pR'
  elif ln conf$$.file conf$$ 2>/dev/null; then
    as_ln_s=ln
  else
    as_ln_s='cp -pR'
  fi
544
545
546
547
548
549
550
551


552
553
554


555
556
557
558
559
560
561
566
567
568
569
570
571
572

573
574
575
576

577
578
579
580
581
582
583
584
585







-
+
+


-
+
+







  as_mkdir_p=false
fi

as_test_x='test -x'
as_executable_p=as_fn_executable_p

# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated

# Sed expression to map a string onto a valid variable name.
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
as_tr_sh="eval sed '$as_sed_sh'" # deprecated


test -n "$DJDIR" || exec 7<&0 </dev/null
exec 6>&1

# Name of the host.
# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
580
581
582
583
584
585
586
587
588
589



590
591

592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616









617
618
619
620

621
622
623
624
625
626
627
604
605
606
607
608
609
610



611
612
613
614

615



616





617
618



619
620



621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647







-
-
-
+
+
+

-
+
-
-
-

-
-
-
-
-


-
-
-


-
-
-






+
+
+
+
+
+
+
+
+




+







PACKAGE_VERSION='9.0'
PACKAGE_STRING='tcl 9.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''

# Factoring default headers for most tests.
ac_includes_default="\
#include <stdio.h>
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#include <stddef.h>
#ifdef HAVE_STDIO_H
# include <stdio.h>
#endif
#ifdef HAVE_SYS_STAT_H
#ifdef HAVE_STDLIB_H
# include <sys/stat.h>
#endif
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# ifdef HAVE_STDLIB_H
#  include <stdlib.h>
# endif
#endif
#ifdef HAVE_STRING_H
# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
#  include <memory.h>
# endif
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif"

ac_header_c_list=
ac_subst_vars='DLTEST_SUFFIX
DLTEST_LD
EXTRA_TCLSH_LIBS
EXTRA_BUILD_HTML
EXTRA_INSTALL_BINARIES
EXTRA_INSTALL
EXTRA_APP_CC_SWITCHES
660
661
662
663
664
665
666

667
668
669
670
671
672
673
674

675
676
677
678
679
680
681
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703







+








+







TCL_LIB_FILE
PKG_CFG_ARGS
TCL_YEAR
TCL_PATCH_LEVEL
TCL_MINOR_VERSION
TCL_MAJOR_VERSION
TCL_VERSION
TCL_BUILDTIME_LIBRARY
INSTALL_MSGS
INSTALL_LIBRARIES
TCL_ZIP_FILE
ZIPFS_BUILD
ZIP_INSTALL_OBJS
ZIP_PROG_VFSSEARCH
ZIP_PROG_OPTIONS
ZIP_PROG
MACHER_PROG
EXEEXT_FOR_BUILD
CC_FOR_BUILD
DTRACE
LDFLAGS_DEFAULT
CFLAGS_DEFAULT
INSTALL_STUB_LIB
DLL_INSTALL_DIR
689
690
691
692
693
694
695

696
697
698
699
700
701
702
703
704
705
706
707
708
709
710


711
712
713
714
715
716
717
718
719
720
721
722
723
724
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740


741
742
743
744
745
746
747







+















+
+





-
-







TCL_SHLIB_LD_EXTRAS
SHLIB_LD
STLIB_LD
LD_SEARCH_FLAGS
CC_SEARCH_FLAGS
LDFLAGS_OPTIMIZE
LDFLAGS_DEBUG
CFLAGS_NOLTO
CFLAGS_WARNING
CFLAGS_OPTIMIZE
CFLAGS_DEBUG
LDAIX_SRC
PLAT_SRCS
PLAT_OBJS
DL_OBJS
DL_LIBS
TCL_LIBS
LIBOBJS
AR
RANLIB
TOMMATH_INCLUDE
TOMMATH_SRCS
TOMMATH_OBJS
TCL_PC_CFLAGS
TCL_PC_REQUIRES_PRIVATE
ZLIB_INCLUDE
ZLIB_SRCS
ZLIB_OBJS
TCLSH_PROG
SHARED_BUILD
EGREP
GREP
CPP
OBJEXT
EXEEXT
ac_ct_CC
CPPFLAGS
LDFLAGS
CFLAGS
739
740
741
742
743
744
745

746
747
748
749
750
751
752
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776







+







pdfdir
dvidir
htmldir
infodir
docdir
oldincludedir
includedir
runstatedir
localstatedir
sharedstatedir
sysconfdir
datadir
datarootdir
libexecdir
sbindir
778
779
780
781
782
783
784
785
786


787
788
789
790
791
792
793
802
803
804
805
806
807
808


809
810
811
812
813
814
815
816
817







-
-
+
+







enable_corefoundation
enable_load
enable_symbols
enable_langinfo
enable_dll_unloading
with_tzdata
enable_dtrace
enable_zipfs
enable_framework
enable_framework
enable_zipfs
'
      ac_precious_vars='build_alias
host_alias
target_alias
CC
CFLAGS
LDFLAGS
828
829
830
831
832
833
834

835
836
837
838
839
840
841
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866







+







sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
datarootdir='${prefix}/share'
datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
infodir='${datarootdir}/info'
htmldir='${docdir}'
dvidir='${docdir}'
pdfdir='${docdir}'
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
882
883
884
885
886
887
888


889
890
891
892
893
894
895







-
-








  case $ac_option in
  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
  *=)   ac_optarg= ;;
  *)    ac_optarg=yes ;;
  esac

  # Accept the important Cygnus configure options, so we can diagnose typos.

  case $ac_dashdash$ac_option in
  --)
    ac_dashdash=yes ;;

  -bindir | --bindir | --bindi | --bind | --bin | --bi)
    ac_prev=bindir ;;
  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
899
900
901
902
903
904
905
906

907
908

909
910
911
912
913
914
915
922
923
924
925
926
927
928

929
930

931
932
933
934
935
936
937
938







-
+

-
+







  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
    datarootdir=$ac_optarg ;;

  -disable-* | --disable-*)
    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid feature name: $ac_useropt"
      as_fn_error $? "invalid feature name: '$ac_useropt'"
    ac_useropt_orig=$ac_useropt
    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"enable_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
925
926
927
928
929
930
931
932

933
934

935
936
937
938
939
940
941
948
949
950
951
952
953
954

955
956

957
958
959
960
961
962
963
964







-
+

-
+







  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
    dvidir=$ac_optarg ;;

  -enable-* | --enable-*)
    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid feature name: $ac_useropt"
      as_fn_error $? "invalid feature name: '$ac_useropt'"
    ac_useropt_orig=$ac_useropt
    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"enable_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
1079
1080
1081
1082
1083
1084
1085









1086
1087
1088
1089
1090
1091
1092
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124







+
+
+
+
+
+
+
+
+







    ac_prev=psdir ;;
  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
    psdir=$ac_optarg ;;

  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
  | -silent | --silent | --silen | --sile | --sil)
    silent=yes ;;

  -runstatedir | --runstatedir | --runstatedi | --runstated \
  | --runstate | --runstat | --runsta | --runst | --runs \
  | --run | --ru | --r)
    ac_prev=runstatedir ;;
  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
  | --run=* | --ru=* | --r=*)
    runstatedir=$ac_optarg ;;

  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
    ac_prev=sbindir ;;
  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
  | --sbi=* | --sb=*)
    sbindir=$ac_optarg ;;

1129
1130
1131
1132
1133
1134
1135
1136

1137
1138

1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152

1153
1154

1155
1156
1157
1158
1159
1160
1161
1161
1162
1163
1164
1165
1166
1167

1168
1169

1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183

1184
1185

1186
1187
1188
1189
1190
1191
1192
1193







-
+

-
+













-
+

-
+







  -version | --version | --versio | --versi | --vers | -V)
    ac_init_version=: ;;

  -with-* | --with-*)
    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid package name: $ac_useropt"
      as_fn_error $? "invalid package name: '$ac_useropt'"
    ac_useropt_orig=$ac_useropt
    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"with_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
    eval with_$ac_useropt=\$ac_optarg ;;

  -without-* | --without-*)
    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid package name: $ac_useropt"
      as_fn_error $? "invalid package name: '$ac_useropt'"
    ac_useropt_orig=$ac_useropt
    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"with_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
1175
1176
1177
1178
1179
1180
1181
1182
1183


1184
1185
1186
1187
1188
1189
1190
1191

1192
1193
1194
1195
1196
1197
1198

1199
1200

1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216

1217
1218
1219
1220
1221
1222
1223
1224

1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241

1242
1243
1244
1245
1246
1247
1248
1207
1208
1209
1210
1211
1212
1213


1214
1215
1216
1217
1218
1219
1220
1221
1222

1223
1224
1225
1226
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







-
-
+
+







-
+






-
+

-
+















-
+







-
+
















-
+







  -x-libraries | --x-libraries | --x-librarie | --x-librari \
  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
    ac_prev=x_libraries ;;
  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
    x_libraries=$ac_optarg ;;

  -*) as_fn_error $? "unrecognized option: \`$ac_option'
Try \`$0 --help' for more information"
  -*) as_fn_error $? "unrecognized option: '$ac_option'
Try '$0 --help' for more information"
    ;;

  *=*)
    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
    # Reject names that are not valid shell variable names.
    case $ac_envvar in #(
      '' | [0-9]* | *[!_$as_cr_alnum]* )
      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
      as_fn_error $? "invalid variable name: '$ac_envvar'" ;;
    esac
    eval $ac_envvar=\$ac_optarg
    export $ac_envvar ;;

  *)
    # FIXME: should be removed in autoconf 3.0.
    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
    printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
      printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
    ;;

  esac
done

if test -n "$ac_prev"; then
  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
  as_fn_error $? "missing argument to $ac_option"
fi

if test -n "$ac_unrecognized_opts"; then
  case $enable_option_checking in
    no) ;;
    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
    *)     printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
  esac
fi

# Check all directory arguments for consistency.
for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
		datadir sysconfdir sharedstatedir localstatedir includedir \
		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
		libdir localedir mandir
		libdir localedir mandir runstatedir
do
  eval ac_val=\$$ac_var
  # Remove trailing slashes.
  case $ac_val in
    */ )
      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
      eval $ac_var=\$ac_val;;
  esac
  # Be sure to have absolute directory names.
  case $ac_val in
    [\\/$]* | ?:[\\/]* )  continue;;
    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
  esac
  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
done

# There might be people who depend on the old broken behavior: `$host'
# There might be people who depend on the old broken behavior: '$host'
# used to hold the argument of --host etc.
# FIXME: To remove some day.
build=$build_alias
host=$host_alias
target=$target_alias

# FIXME: To remove some day.
1273
1274
1275
1276
1277
1278
1279
1280

1281
1282
1283
1284
1285
1286
1287
1305
1306
1307
1308
1309
1310
1311

1312
1313
1314
1315
1316
1317
1318
1319







-
+







  ac_srcdir_defaulted=yes
  # Try the directory containing this script, then the parent directory.
  ac_confdir=`$as_dirname -- "$as_myself" ||
$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$as_myself" : 'X\(//\)[^/]' \| \
	 X"$as_myself" : 'X\(//\)$' \| \
	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$as_myself" |
printf "%s\n" X"$as_myself" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
1302
1303
1304
1305
1306
1307
1308
1309

1310
1311
1312
1313
1314
1315
1316
1334
1335
1336
1337
1338
1339
1340

1341
1342
1343
1344
1345
1346
1347
1348







-
+







else
  ac_srcdir_defaulted=no
fi
if test ! -r "$srcdir/$ac_unique_file"; then
  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
fi
ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
ac_msg="sources are in $srcdir, but 'cd $srcdir' does not work"
ac_abs_confdir=`(
	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
	pwd)`
# When building in place, set srcdir=.
if test "$ac_abs_confdir" = "$ac_pwd"; then
  srcdir=.
fi
1330
1331
1332
1333
1334
1335
1336
1337

1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351

1352
1353

1354
1355

1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366




1367
1368
1369
1370
1371
1372
1373
1374
1375
1376

1377
1378
1379
1380
1381
1382
1383
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

1387
1388
1389
1390
1391
1392
1393
1394




1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416







-
+













-
+

-
+

-
+







-
-
-
-
+
+
+
+










+







#
# Report the --help message.
#
if test "$ac_init_help" = "long"; then
  # Omit some internal or obsolete options to make the list less imposing.
  # This message is too long to be a string in the A/UX 3.1 sh.
  cat <<_ACEOF
\`configure' configures tcl 9.0 to adapt to many kinds of systems.
'configure' configures tcl 9.0 to adapt to many kinds of systems.

Usage: $0 [OPTION]... [VAR=VALUE]...

To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE.  See below for descriptions of some of the useful variables.

Defaults for the options are specified in brackets.

Configuration:
  -h, --help              display this help and exit
      --help=short        display options specific to this package
      --help=recursive    display the short help of all the included packages
  -V, --version           display version information and exit
  -q, --quiet, --silent   do not print \`checking ...' messages
  -q, --quiet, --silent   do not print 'checking ...' messages
      --cache-file=FILE   cache test results in FILE [disabled]
  -C, --config-cache      alias for \`--cache-file=config.cache'
  -C, --config-cache      alias for '--cache-file=config.cache'
  -n, --no-create         do not create output files
      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
      --srcdir=DIR        find the sources in DIR [configure dir or '..']

Installation directories:
  --prefix=PREFIX         install architecture-independent files in PREFIX
                          [$ac_default_prefix]
  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
                          [PREFIX]

By default, \`make install' will install all the files in
\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
an installation prefix other than \`$ac_default_prefix' using \`--prefix',
for instance \`--prefix=\$HOME'.
By default, 'make install' will install all the files in
'$ac_default_prefix/bin', '$ac_default_prefix/lib' etc.  You can specify
an installation prefix other than '$ac_default_prefix' using '--prefix',
for instance '--prefix=\$HOME'.

For better control, use the options below.

Fine tuning of the installation directories:
  --bindir=DIR            user executables [EPREFIX/bin]
  --sbindir=DIR           system admin executables [EPREFIX/sbin]
  --libexecdir=DIR        program executables [EPREFIX/libexec]
  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
  --libdir=DIR            object code libraries [EPREFIX/lib]
  --includedir=DIR        C header files [PREFIX/include]
  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
  --infodir=DIR           info documentation [DATAROOTDIR/info]
  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427

1428
1429
1430
1431
1432

1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
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
1478
1479
1480

1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499

1500
1501

1502
1503
1504
1505
1506
1507
1508
1509







-


+




-
+
-















-
+


















-
+

-
+







  --enable-load           allow dynamic loading and "load" command (default:
                          on)
  --enable-symbols        build with debugging symbols (default: off)
  --enable-langinfo       use nl_langinfo if possible to determine encoding at
                          startup, otherwise use old heuristic (default: on)
  --enable-dll-unloading  enable the 'unload' command (default: on)
  --enable-dtrace         build with DTrace support (default: off)
  --enable-zipfs          build with Zipfs support (default: on)
  --enable-framework      package shared libraries in MacOSX frameworks
                          (default: off)
  --enable-zipfs          build with Zipfs support (default: on)

Optional Packages:
  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
  --with-encoding         encoding for configuration values (default:
  --with-encoding         encoding for configuration values (default: utf-8)
                          utf-8)
  --with-system-libtommath
                          use external libtommath (default: true if available,
                          false otherwise)
  --with-tzdata           install timezone data (default: autodetect)

Some influential environment variables:
  CC          C compiler command
  CFLAGS      C compiler flags
  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
              nonstandard directory <lib dir>
  LIBS        libraries to pass to the linker, e.g. -l<library>
  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
              you have headers in a nonstandard directory <include dir>
  CPP         C preprocessor

Use these variables to override the choices made by `configure' or to help
Use these variables to override the choices made by 'configure' or to help
it to find libraries and programs with nonstandard names/locations.

Report bugs to the package provider.
_ACEOF
ac_status=$?
fi

if test "$ac_init_help" = "recursive"; then
  # If there are subdirs, report their specific --help.
  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
    test -d "$ac_dir" ||
      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
      continue
    ac_builddir=.

case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
  ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
  # A ".." for each directory in $ac_dir_suffix.
  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
  ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
  case $ac_top_builddir_sub in
  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
  esac ;;
esac
ac_abs_top_builddir=$ac_pwd
ac_abs_builddir=$ac_pwd$ac_dir_suffix
1491
1492
1493
1494
1495
1496
1497
1498


1499
1500
1501
1502
1503
1504
1505
1506

1507
1508
1509
1510
1511
1512
1513
1514
1515
1516

1517
1518

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

1536
1537
1538
1539
1540
1541
1542

1543
1544
1545
1546
1547
1548
1549
1550

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
1749
1750
1751


1752





1753
1754
1755



1756
1757
1758

1759
1760
1761
1762



1763
1764


1765
1766

1767
1768

1769
1770
1771


1772




1773
1774
1775
1776
1777

1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821







1822
1823
1824
1825
1826
1827
1828

1829
1830
1831
1832
1833

1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846

1847
1848
1849
1850
1851
1852
1853
1854
1855

1856
1857
1858
1859
1860
1861
1862


1863
1864
1865



1866
1867
1868



1869
1870
1871
1872


1873
1874
1875
1876
1877
1878


1879
1880
1881


1882
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
1958
1959
1960
1961


1962
1963
1964



1965
1966

1967
1968


1969
1970
1971
1972


1973
1974
1975












































1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989







1990
1991
1992
1993

1994
1995
1996
1997
1998
1999
2000
2001
2002


2003
2004
2005


2006
2007
2008
2009

2010
2011
2012
2013
2014
2015
2016
2017
2018


2019
2020
2021



2022
2023


2024
2025


2026
2027
2028
2029


2030
2031
2032




















2033
2034
2035
2036
2037
2038

2039
2040

2041
2042
2043
2044
2045
2046
2047
1523
1524
1525
1526
1527
1528
1529

1530
1531
1532
1533
1534
1535
1536
1537
1538

1539
1540
1541
1542
1543
1544
1545
1546
1547
1548

1549
1550

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
1749
1750
1751
1752
1753

1754
1755
1756
1757
1758
1759
1760
1761
1762

1763
1764
1765
1766
1767
1768
1769

1770
1771
1772


1773
1774
1775
1776


1777
1778
1779
1780
1781


1782
1783
1784
1785
1786
1787


1788
1789
1790


1791
1792
1793
1794
1795






1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808

1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822

1823
1824
1825


1826
1827
1828
1829

1830
1831
1832
1833
1834
1835


1836
1837
1838
1839

1840
1841
1842
1843
1844
1845
1846
1847
1848






1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859

1860
1861
1862
1863
1864
1865
1866
1867

1868
1869
1870
1871
1872
1873

1874
1875
1876
1877
1878
1879
1880
1881

1882
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
1958
1959
1960
1961

1962
1963
1964
1965
1966
1967
1968
1969
1970

1971
1972
1973


1974
1975
1976
1977
1978

1979
1980
1981
1982
1983
1984
1985
1986
1987

1988
1989
1990


1991
1992
1993
1994

1995
1996
1997

1998
1999
2000
2001


2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031

2032
2033

2034
2035
2036
2037
2038
2039
2040
2041







-
+
+







-
+









-
+

-
+
















-
+






-
+







-
+



-
+
+

-
-
+
+


-
+
+






-
-
-
-
+
+
+
+
+


+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
-
-
+

-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+

-
-
-
-
-
+
+
+

-

-
+













-
+







-
+



+
-
+

-
-
+
+


-
+
+






-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
+


+






-
-
+
+

+
+
+
+
+
-
-
-
+
+
+
-
-
-
+
-
-
-
-
+
+
+
-
-
+
+

-
+
-
-
+


-
+
+

+
+
+
+




-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







-
-
-
-
-
-
+
+
+
+
+
+
+






-
+
-
-

-
-
+
-
-
-
-








-
+








-
+






-
+
+

-
-
+
+
+

-
-
+
+
+


-
-
+
+




-
-
+
+

-
-
+
+



-
-
-
-
-
-
+
+
+
+
+
+
+
+
+




-
+













-
+
+

-
-
+
+
+

-
+
+
+
+


-
-
+
+


-
+








-
-
-
-
-
-
+
+
+
+
+
+
+




-
+







-
+
+




-
+







-
+
+

-
-
+
+
+

-
+

-
+
+


-
-
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
-
-
-
-
-
+
+
+
+
+
+
+



-
+








-
+
+

-
-
+
+



-
+








-
+
+

-
-
+
+
+

-
+
+

-
+
+


-
-
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+

-
+







    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
    ac_top_srcdir=$ac_top_build_prefix$srcdir
    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix

    cd "$ac_dir" || { ac_status=$?; continue; }
    # Check for guested configure.
    # Check for configure.gnu first; this name is used for a wrapper for
    # Metaconfig's "Configure" on case-insensitive file systems.
    if test -f "$ac_srcdir/configure.gnu"; then
      echo &&
      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
    elif test -f "$ac_srcdir/configure"; then
      echo &&
      $SHELL "$ac_srcdir/configure" --help=recursive
    else
      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
      printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
    fi || ac_status=$?
    cd "$ac_pwd" || { ac_status=$?; break; }
  done
fi

test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
  cat <<\_ACEOF
tcl configure 9.0
generated by GNU Autoconf 2.69
generated by GNU Autoconf 2.72

Copyright (C) 2012 Free Software Foundation, Inc.
Copyright (C) 2023 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
  exit
fi

## ------------------------ ##
## Autoconf initialization. ##
## ------------------------ ##

# ac_fn_c_try_compile LINENO
# --------------------------
# Try to compile conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_compile ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  rm -f conftest.$ac_objext
  rm -f conftest.$ac_objext conftest.beam
  if { { ac_try="$ac_compile"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_compile") 2>conftest.err
  ac_status=$?
  if test -s conftest.err; then
    grep -v '^ *+' conftest.err >conftest.er1
    cat conftest.er1 >&5
    mv -f conftest.er1 conftest.err
  fi
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; } && {
	 test -z "$ac_c_werror_flag" ||
	 test ! -s conftest.err
       } && test -s conftest.$ac_objext; then :
       } && test -s conftest.$ac_objext
then :
  ac_retval=0
else
  $as_echo "$as_me: failed program was:" >&5
else case e in #(
  e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

	ac_retval=1
	ac_retval=1 ;;
esac
fi
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
  as_fn_set_status $ac_retval

} # ac_fn_c_try_compile

# ac_fn_c_try_link LINENO
# -----------------------
# Try to link conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_link ()
# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
# Tests whether HEADER exists and can be compiled using the include files in
# INCLUDES, setting the cache variable VAR accordingly.
ac_fn_c_check_header_compile ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
printf %s "checking for $2... " >&6; }
if eval test \${$3+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
  rm -f conftest.$ac_objext conftest$ac_exeext
  if { { ac_try="$ac_link"
case "(($ac_try" in
/* end confdefs.h.  */
$4
#include <$2>
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  eval "$3=yes"
else case e in #(
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
  e) eval "$3=no" ;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
  (eval "$ac_link") 2>conftest.err
  ac_status=$?
  if test -s conftest.err; then
    grep -v '^ *+' conftest.err >conftest.er1
    cat conftest.er1 >&5
    mv -f conftest.er1 conftest.err
  fi
fi
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; } && {
	 test -z "$ac_c_werror_flag" ||
	 test ! -s conftest.err
       } && test -s conftest$ac_exeext && {
	 test "$cross_compiling" = yes ||
	 test -x conftest$ac_exeext
       }; then :
  ac_retval=0
else
  $as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

	ac_retval=1
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
  # interfere with the next link command; also delete a directory that is
  # left behind by Apple's compiler.  We do this before executing the actions.
  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
eval ac_res=\$$3
	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
  as_fn_set_status $ac_retval

} # ac_fn_c_try_link
} # ac_fn_c_check_header_compile

# ac_fn_c_try_cpp LINENO
# ----------------------
# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_cpp ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  if { { ac_try="$ac_cpp conftest.$ac_ext"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
  ac_status=$?
  if test -s conftest.err; then
    grep -v '^ *+' conftest.err >conftest.er1
    cat conftest.er1 >&5
    mv -f conftest.er1 conftest.err
  fi
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; } > conftest.i && {
	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
	 test ! -s conftest.err
       }
       }; then :
then :
  ac_retval=0
else
  $as_echo "$as_me: failed program was:" >&5
else case e in #(
  e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

    ac_retval=1
    ac_retval=1 ;;
esac
fi
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
  as_fn_set_status $ac_retval

} # ac_fn_c_try_cpp

# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
# Tests whether HEADER exists, giving a warning if it cannot be compiled using
# the include files in INCLUDES and setting the cache variable VAR
# accordingly.
ac_fn_c_check_header_mongrel ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  if eval \${$3+:} false; then :
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
  $as_echo_n "(cached) " >&6
fi
eval ac_res=\$$3
	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
else
  # Is the header compilable?
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
$as_echo_n "checking $2 usability... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$4
#include <$2>
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  ac_header_compiler=yes
else
  ac_header_compiler=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
$as_echo "$ac_header_compiler" >&6; }

# Is the header present?
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
$as_echo_n "checking $2 presence... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <$2>
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
  ac_header_preproc=yes
else
  ac_header_preproc=no
fi
rm -f conftest.err conftest.i conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
$as_echo "$ac_header_preproc" >&6; }

# So?  What about this header?
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
  yes:no: )
    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
    ;;
  no:yes:* )
    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
    ;;
esac
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
  $as_echo_n "(cached) " >&6
else
  eval "$3=\$ac_header_compiler"
fi
eval ac_res=\$$3
	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
fi
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

} # ac_fn_c_check_header_mongrel

# ac_fn_c_try_run LINENO
# ----------------------
# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
# ac_fn_c_try_link LINENO
# -----------------------
# Try to link conftest.$ac_ext, and return whether this succeeded.
# that executables *can* be run.
ac_fn_c_try_run ()
ac_fn_c_try_link ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
  if { { ac_try="$ac_link"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
  (eval "$ac_link") 2>&5
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link") 2>conftest.err
  ac_status=$?
  if test -s conftest.err; then
    grep -v '^ *+' conftest.err >conftest.er1
    cat conftest.er1 >&5
    mv -f conftest.er1 conftest.err
  fi
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
  { { case "(($ac_try" in
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; } && {
	 test -z "$ac_c_werror_flag" ||
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
	 test ! -s conftest.err
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
  (eval "$ac_try") 2>&5
  ac_status=$?
       } && test -s conftest$ac_exeext && {
	 test "$cross_compiling" = yes ||
	 test -x conftest$ac_exeext
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }; }; then :
       }
then :
  ac_retval=0
else
else case e in #(
  $as_echo "$as_me: program exited with status $ac_status" >&5
       $as_echo "$as_me: failed program was:" >&5
  e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

       ac_retval=$ac_status
	ac_retval=1 ;;
esac
fi
  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
  # interfere with the next link command; also delete a directory that is
  # left behind by Apple's compiler.  We do this before executing the actions.
  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
  as_fn_set_status $ac_retval

} # ac_fn_c_try_run
} # ac_fn_c_try_link

# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
# Tests whether HEADER exists and can be compiled using the include files in
# INCLUDES, setting the cache variable VAR accordingly.
ac_fn_c_check_header_compile ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$4
#include <$2>
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  eval "$3=yes"
else
  eval "$3=no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
eval ac_res=\$$3
	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

} # ac_fn_c_check_header_compile

# ac_fn_c_check_func LINENO FUNC VAR
# ----------------------------------
# Tests whether FUNC exists, setting the cache variable VAR accordingly
ac_fn_c_check_func ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
printf %s "checking for $2... " >&6; }
if eval test \${$3+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
#define $2 innocuous_$2

/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char $2 (); below.
   which can conflict with char $2 (void); below.  */
    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
    <limits.h> exists even on freestanding compilers.  */

#ifdef __STDC__
# include <limits.h>
#include <limits.h>
#else
# include <assert.h>
#endif

#undef $2

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
#ifdef __cplusplus
extern "C"
#endif
char $2 ();
char $2 (void);
/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined __stub_$2 || defined __stub___$2
choke me
#endif

int
main ()
main (void)
{
return $2 ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  eval "$3=yes"
else
  eval "$3=no"
else case e in #(
  e) eval "$3=no" ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext ;;
esac
fi
eval ac_res=\$$3
	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

} # ac_fn_c_check_func

# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
# ---------------------------------------------
# ac_fn_check_decl LINENO SYMBOL VAR INCLUDES EXTRA-OPTIONS FLAG-VAR
# ------------------------------------------------------------------
# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
# accordingly.
ac_fn_c_check_decl ()
# accordingly. Pass EXTRA-OPTIONS to the compiler, using FLAG-VAR.
ac_fn_check_decl ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  as_decl_name=`echo $2|sed 's/ *(.*//'`
  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
if eval \${$3+:} false; then :
  $as_echo_n "(cached) " >&6
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
printf %s "checking whether $as_decl_name is declared... " >&6; }
if eval test \${$3+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
  eval ac_save_FLAGS=\$$6
  as_fn_append $6 " $5"
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$4
int
main ()
main (void)
{
#ifndef $as_decl_name
#ifdef __cplusplus
  (void) $as_decl_use;
#else
  (void) $as_decl_name;
#endif
#endif

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  eval "$3=yes"
else
  eval "$3=no"
else case e in #(
  e) eval "$3=no" ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
  eval $6=\$ac_save_FLAGS
 ;;
esac
fi
eval ac_res=\$$3
	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

} # ac_fn_c_check_decl
} # ac_fn_check_decl

# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
# -------------------------------------------
# Tests whether TYPE exists after having included INCLUDES, setting cache
# variable VAR accordingly.
ac_fn_c_check_type ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
  $as_echo_n "(cached) " >&6
else
  eval "$3=no"
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
printf %s "checking for $2... " >&6; }
if eval test \${$3+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) eval "$3=no"
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$4
int
main ()
main (void)
{
if (sizeof ($2))
	 return 0;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$4
int
main ()
main (void)
{
if (sizeof (($2)))
	    return 0;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :

else
  eval "$3=yes"
else case e in #(
  e) eval "$3=yes" ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
eval ac_res=\$$3
	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

} # ac_fn_c_check_type

# ac_fn_c_try_run LINENO
# ----------------------
# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that
# executables *can* be run.
ac_fn_c_try_run ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  if { { ac_try="$ac_link"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link") 2>&5
  ac_status=$?
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
  { { case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_try") 2>&5
  ac_status=$?
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }; }
then :
  ac_retval=0
else case e in #(
  e) printf "%s\n" "$as_me: program exited with status $ac_status" >&5
       printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

       ac_retval=$ac_status ;;
esac
fi
  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
  as_fn_set_status $ac_retval

} # ac_fn_c_try_run

# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
# ----------------------------------------------------
# Tries to find if the field MEMBER exists in type AGGR, after including
# INCLUDES, setting cache variable VAR accordingly.
ac_fn_c_check_member ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
$as_echo_n "checking for $2.$3... " >&6; }
if eval \${$4+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
printf %s "checking for $2.$3... " >&6; }
if eval test \${$4+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$5
int
main ()
main (void)
{
static $2 ac_aggr;
if (ac_aggr.$3)
return 0;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  eval "$4=yes"
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$5
int
main ()
main (void)
{
static $2 ac_aggr;
if (sizeof ac_aggr.$3)
return 0;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  eval "$4=yes"
else
  eval "$4=no"
else case e in #(
  e) eval "$4=no" ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
eval ac_res=\$$4
	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

} # ac_fn_c_check_member
ac_configure_args_raw=
for ac_arg
do
  case $ac_arg in
  *\'*)
    ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
  esac
  as_fn_append ac_configure_args_raw " '$ac_arg'"
done

case $ac_configure_args_raw in
  *$as_nl*)
    ac_safe_unquote= ;;
  *)
    ac_unsafe_z='|&;<>()$`\\"*?[ ''	' # This string ends in space, tab.
    ac_unsafe_a="$ac_unsafe_z#~"
    ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
    ac_configure_args_raw=`      printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
esac

cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.

It was created by tcl $as_me 9.0, which was
generated by GNU Autoconf 2.69.  Invocation command line was
generated by GNU Autoconf 2.72.  Invocation command line was

  $ $0 $@
  $ $0$ac_configure_args_raw

_ACEOF
exec 5>>config.log
{
cat <<_ASUNAME
## --------- ##
## Platform. ##
2066
2067
2068
2069
2070
2071
2072

2073
2074





2075
2076
2077
2078
2079
2080
2081
2060
2061
2062
2063
2064
2065
2066
2067


2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079







+
-
-
+
+
+
+
+








_ASUNAME

as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    $as_echo "PATH: $as_dir"
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    printf "%s\n" "PATH: $as_dir"
  done
IFS=$as_save_IFS

} >&5

cat >&5 <<_ACEOF

2102
2103
2104
2105
2106
2107
2108
2109

2110
2111
2112
2113
2114
2115
2116
2100
2101
2102
2103
2104
2105
2106

2107
2108
2109
2110
2111
2112
2113
2114







-
+







  do
    case $ac_arg in
    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
    | -silent | --silent | --silen | --sile | --sil)
      continue ;;
    *\'*)
      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
      ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
    esac
    case $ac_pass in
    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
    2)
      as_fn_append ac_configure_args1 " '$ac_arg'"
      if test $ac_must_keep_next = true; then
	ac_must_keep_next=false # Got value, back to normal.
2137
2138
2139
2140
2141
2142
2143


2144
2145
2146
2147
2148

2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160


2161
2162
2163
2164
2165
2166
2167
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147

2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158


2159
2160
2161
2162
2163
2164
2165
2166
2167







+
+




-
+










-
-
+
+








# When interrupted or exit'd, cleanup temporary files, and complete
# config.log.  We remove comments because anyway the quotes in there
# would cause problems or look ugly.
# WARNING: Use '\'' to represent an apostrophe within the trap.
# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
  # Sanitize IFS.
  IFS=" ""	$as_nl"
  # Save into config.log some information that might help in debugging.
  {
    echo

    $as_echo "## ---------------- ##
    printf "%s\n" "## ---------------- ##
## Cache variables. ##
## ---------------- ##"
    echo
    # The following way of writing the cache mishandles newlines in values,
(
  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
    eval ac_val=\$$ac_var
    case $ac_val in #(
    *${as_nl}*)
      case $ac_var in #(
      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
      *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
      esac
      case $ac_var in #(
      _ | IFS | as_nl) ;; #(
      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
      *) { eval $ac_var=; unset $ac_var;} ;;
      esac ;;
    esac
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
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
2273

2274
2275
2276
2277
2278
2279

2280
2281
2282

2283
2284

2285

2286
2287
2288
2289
2290









2291
2292
2293
2294


2295
2296

2297
2298
2299
2300
2301
2302
2303
2304
2305


2306
2307
2308
2309
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
2390
2391
2392

2393
2394
2395
2396
2397
2398
2399
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
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
2273
2274
2275
2276
2277


2278
2279
2280

2281
2282
2283
2284
2285
2286
2287
2288


2289
2290
2291
2292
2293
2294
2295
2296


2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
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
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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







-
+







-
+

-
+




-
+







-
+

-
+





-
+







-
-
+
+













-
+



-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-




-
-

-
-
+
-
-
-
-

-
+
-

-
+
-

+
-
+

-
-
-
-
+
+
+
+
+
+
+
+
+


-
-
+
+

-
+







-
-
+
+






-
-
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










-
-
+
+


-
-
+
+








-
-
+
+


-
-
+
+


-
-
-
-
+
+
+
+





-
+









-
-
-
-
-
+
+
+
+
+
+



















-
+







      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
      ;;
    esac |
    sort
)
    echo

    $as_echo "## ----------------- ##
    printf "%s\n" "## ----------------- ##
## Output variables. ##
## ----------------- ##"
    echo
    for ac_var in $ac_subst_vars
    do
      eval ac_val=\$$ac_var
      case $ac_val in
      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
      *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
      esac
      $as_echo "$ac_var='\''$ac_val'\''"
      printf "%s\n" "$ac_var='\''$ac_val'\''"
    done | sort
    echo

    if test -n "$ac_subst_files"; then
      $as_echo "## ------------------- ##
      printf "%s\n" "## ------------------- ##
## File substitutions. ##
## ------------------- ##"
      echo
      for ac_var in $ac_subst_files
      do
	eval ac_val=\$$ac_var
	case $ac_val in
	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
	*\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
	esac
	$as_echo "$ac_var='\''$ac_val'\''"
	printf "%s\n" "$ac_var='\''$ac_val'\''"
      done | sort
      echo
    fi

    if test -s confdefs.h; then
      $as_echo "## ----------- ##
      printf "%s\n" "## ----------- ##
## confdefs.h. ##
## ----------- ##"
      echo
      cat confdefs.h
      echo
    fi
    test "$ac_signal" != 0 &&
      $as_echo "$as_me: caught signal $ac_signal"
    $as_echo "$as_me: exit $exit_status"
      printf "%s\n" "$as_me: caught signal $ac_signal"
    printf "%s\n" "$as_me: exit $exit_status"
  } >&5
  rm -f core *.core core.conftest.* &&
    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
    exit $exit_status
' 0
for ac_signal in 1 2 13 15; do
  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
done
ac_signal=0

# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -f -r conftest* confdefs.h

$as_echo "/* confdefs.h */" > confdefs.h
printf "%s\n" "/* confdefs.h */" > confdefs.h

# Predefined preprocessor variables.

cat >>confdefs.h <<_ACEOF
#define PACKAGE_NAME "$PACKAGE_NAME"
printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
_ACEOF

cat >>confdefs.h <<_ACEOF
#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
_ACEOF

cat >>confdefs.h <<_ACEOF
#define PACKAGE_VERSION "$PACKAGE_VERSION"
printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
_ACEOF

cat >>confdefs.h <<_ACEOF
#define PACKAGE_STRING "$PACKAGE_STRING"
printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
_ACEOF

cat >>confdefs.h <<_ACEOF
#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
_ACEOF

cat >>confdefs.h <<_ACEOF
#define PACKAGE_URL "$PACKAGE_URL"
printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
_ACEOF


# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.
ac_site_file1=NONE
ac_site_file2=NONE
if test -n "$CONFIG_SITE"; then
  # We do not want a PATH search for config.site.
  case $CONFIG_SITE in #((
  ac_site_files="$CONFIG_SITE"
    -*)  ac_site_file1=./$CONFIG_SITE;;
    */*) ac_site_file1=$CONFIG_SITE;;
    *)   ac_site_file1=./$CONFIG_SITE;;
  esac
elif test "x$prefix" != xNONE; then
  ac_site_file1=$prefix/share/config.site
  ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
  ac_site_file2=$prefix/etc/config.site
else
  ac_site_file1=$ac_default_prefix/share/config.site
  ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
  ac_site_file2=$ac_default_prefix/etc/config.site
fi

for ac_site_file in "$ac_site_file1" "$ac_site_file2"
for ac_site_file in $ac_site_files
do
  test "x$ac_site_file" = xNONE && continue
  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
$as_echo "$as_me: loading site script $ac_site_file" >&6;}
  case $ac_site_file in #(
  */*) :
     ;; #(
  *) :
    ac_site_file=./$ac_site_file ;;
esac
  if test -f "$ac_site_file" && test -r "$ac_site_file"; then
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
    sed 's/^/| /' "$ac_site_file" >&5
    . "$ac_site_file" \
      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
      || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5; }
See 'config.log' for more details" "$LINENO" 5; }
  fi
done

if test -r "$cache_file"; then
  # Some versions of bash will fail to source /dev/null (special files
  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
$as_echo "$as_me: loading cache $cache_file" >&6;}
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
    case $cache_file in
      [\\/]* | ?:[\\/]* ) . "$cache_file";;
      *)                      . "./$cache_file";;
    esac
  fi
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
$as_echo "$as_me: creating cache $cache_file" >&6;}
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
  >$cache_file
fi

# Test code for whether the C compiler supports C89 (global declarations)
ac_c_conftest_c89_globals='
/* Does the compiler advertise C89 conformance?
   Do not test the value of __STDC__, because some compilers set it to 0
   while being otherwise adequately conformant. */
#if !defined __STDC__
# error "Compiler does not advertise C89 conformance"
#endif

#include <stddef.h>
#include <stdarg.h>
struct stat;
/* Most of the following tests are stolen from RCS 5.7 src/conf.sh.  */
struct buf { int x; };
struct buf * (*rcsopen) (struct buf *, struct stat *, int);
static char *e (char **p, int i)
{
  return p[i];
}
static char *f (char * (*g) (char **, int), char **p, ...)
{
  char *s;
  va_list v;
  va_start (v,p);
  s = g (p, va_arg (v,int));
  va_end (v);
  return s;
}

/* C89 style stringification. */
#define noexpand_stringify(a) #a
const char *stringified = noexpand_stringify(arbitrary+token=sequence);

/* C89 style token pasting.  Exercises some of the corner cases that
   e.g. old MSVC gets wrong, but not very hard. */
#define noexpand_concat(a,b) a##b
#define expand_concat(a,b) noexpand_concat(a,b)
extern int vA;
extern int vbee;
#define aye A
#define bee B
int *pvA = &expand_concat(v,aye);
int *pvbee = &noexpand_concat(v,bee);

/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
   function prototypes and stuff, but not \xHH hex character constants.
   These do not provoke an error unfortunately, instead are silently treated
   as an "x".  The following induces an error, until -std is added to get
   proper ANSI mode.  Curiously \x00 != x always comes out true, for an
   array size at least.  It is necessary to write \x00 == 0 to get something
   that is true only with -std.  */
int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];

/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
   inside strings and character constants.  */
#define FOO(x) '\''x'\''
int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];

int test (int i, double x);
struct s1 {int (*f) (int a);};
struct s2 {int (*f) (double a);};
int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
               int, int);'

# Test code for whether the C compiler supports C89 (body of main).
ac_c_conftest_c89_main='
ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
'

# Test code for whether the C compiler supports C99 (global declarations)
ac_c_conftest_c99_globals='
/* Does the compiler advertise C99 conformance? */
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
# error "Compiler does not advertise C99 conformance"
#endif

// See if C++-style comments work.

#include <stdbool.h>
extern int puts (const char *);
extern int printf (const char *, ...);
extern int dprintf (int, const char *, ...);
extern void *malloc (size_t);
extern void free (void *);

// Check varargs macros.  These examples are taken from C99 6.10.3.5.
// dprintf is used instead of fprintf to avoid needing to declare
// FILE and stderr.
#define debug(...) dprintf (2, __VA_ARGS__)
#define showlist(...) puts (#__VA_ARGS__)
#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
static void
test_varargs_macros (void)
{
  int x = 1234;
  int y = 5678;
  debug ("Flag");
  debug ("X = %d\n", x);
  showlist (The first, second, and third items.);
  report (x>y, "x is %d but y is %d", x, y);
}

// Check long long types.
#define BIG64 18446744073709551615ull
#define BIG32 4294967295ul
#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
#if !BIG_OK
  #error "your preprocessor is broken"
#endif
#if BIG_OK
#else
  #error "your preprocessor is broken"
#endif
static long long int bignum = -9223372036854775807LL;
static unsigned long long int ubignum = BIG64;

struct incomplete_array
{
  int datasize;
  double data[];
};

struct named_init {
  int number;
  const wchar_t *name;
  double average;
};

typedef const char *ccp;

static inline int
test_restrict (ccp restrict text)
{
  // Iterate through items via the restricted pointer.
  // Also check for declarations in for loops.
  for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
    continue;
  return 0;
}

// Check varargs and va_copy.
static bool
test_varargs (const char *format, ...)
{
  va_list args;
  va_start (args, format);
  va_list args_copy;
  va_copy (args_copy, args);

  const char *str = "";
  int number = 0;
  float fnumber = 0;

  while (*format)
    {
      switch (*format++)
	{
	case '\''s'\'': // string
	  str = va_arg (args_copy, const char *);
	  break;
	case '\''d'\'': // int
	  number = va_arg (args_copy, int);
	  break;
	case '\''f'\'': // float
	  fnumber = va_arg (args_copy, double);
	  break;
	default:
	  break;
	}
    }
  va_end (args_copy);
  va_end (args);

  return *str && number && fnumber;
}
'

# Test code for whether the C compiler supports C99 (body of main).
ac_c_conftest_c99_main='
  // Check bool.
  _Bool success = false;
  success |= (argc != 0);

  // Check restrict.
  if (test_restrict ("String literal") == 0)
    success = true;
  char *restrict newvar = "Another string";

  // Check varargs.
  success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
  test_varargs_macros ();

  // Check flexible array members.
  struct incomplete_array *ia =
    malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
  ia->datasize = 10;
  for (int i = 0; i < ia->datasize; ++i)
    ia->data[i] = i * 1.234;
  // Work around memory leak warnings.
  free (ia);

  // Check named initializers.
  struct named_init ni = {
    .number = 34,
    .name = L"Test wide string",
    .average = 543.34343,
  };

  ni.number = 58;

  int dynamic_array[ni.number];
  dynamic_array[0] = argv[0][0];
  dynamic_array[ni.number - 1] = 543;

  // work around unused variable warnings
  ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
	 || dynamic_array[ni.number - 1] != 543);
'

# Test code for whether the C compiler supports C11 (global declarations)
ac_c_conftest_c11_globals='
/* Does the compiler advertise C11 conformance? */
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
# error "Compiler does not advertise C11 conformance"
#endif

// Check _Alignas.
char _Alignas (double) aligned_as_double;
char _Alignas (0) no_special_alignment;
extern char aligned_as_int;
char _Alignas (0) _Alignas (int) aligned_as_int;

// Check _Alignof.
enum
{
  int_alignment = _Alignof (int),
  int_array_alignment = _Alignof (int[100]),
  char_alignment = _Alignof (char)
};
_Static_assert (0 < -_Alignof (int), "_Alignof is signed");

// Check _Noreturn.
int _Noreturn does_not_return (void) { for (;;) continue; }

// Check _Static_assert.
struct test_static_assert
{
  int x;
  _Static_assert (sizeof (int) <= sizeof (long int),
                  "_Static_assert does not work in struct");
  long int y;
};

// Check UTF-8 literals.
#define u8 syntax error!
char const utf8_literal[] = u8"happens to be ASCII" "another string";

// Check duplicate typedefs.
typedef long *long_ptr;
typedef long int *long_ptr;
typedef long_ptr long_ptr;

// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
struct anonymous
{
  union {
    struct { int i; int j; };
    struct { int k; long int l; } w;
  };
  int m;
} v1;
'

# Test code for whether the C compiler supports C11 (body of main).
ac_c_conftest_c11_main='
  _Static_assert ((offsetof (struct anonymous, i)
		   == offsetof (struct anonymous, w.k)),
		  "Anonymous union alignment botch");
  v1.i = 2;
  v1.w.k = 5;
  ok |= v1.i != 5;
'

# Test code for whether the C compiler supports C11 (complete).
ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
${ac_c_conftest_c99_globals}
${ac_c_conftest_c11_globals}

int
main (int argc, char **argv)
{
  int ok = 0;
  ${ac_c_conftest_c89_main}
  ${ac_c_conftest_c99_main}
  ${ac_c_conftest_c11_main}
  return ok;
}
"

# Test code for whether the C compiler supports C99 (complete).
ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
${ac_c_conftest_c99_globals}

int
main (int argc, char **argv)
{
  int ok = 0;
  ${ac_c_conftest_c89_main}
  ${ac_c_conftest_c99_main}
  return ok;
}
"

# Test code for whether the C compiler supports C89 (complete).
ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}

int
main (int argc, char **argv)
{
  int ok = 0;
  ${ac_c_conftest_c89_main}
  return ok;
}
"

as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
as_fn_append ac_header_c_list " sys/time.h sys_time_h HAVE_SYS_TIME_H"
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
for ac_var in $ac_precious_vars; do
  eval ac_old_set=\$ac_cv_env_${ac_var}_set
  eval ac_new_set=\$ac_env_${ac_var}_set
  eval ac_old_val=\$ac_cv_env_${ac_var}_value
  eval ac_new_val=\$ac_env_${ac_var}_value
  case $ac_old_set,$ac_new_set in
    set,)
      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&5
printf "%s\n" "$as_me: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&2;}
      ac_cache_corrupted=: ;;
    ,set)
      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was not set in the previous run" >&5
printf "%s\n" "$as_me: error: '$ac_var' was not set in the previous run" >&2;}
      ac_cache_corrupted=: ;;
    ,);;
    *)
      if test "x$ac_old_val" != "x$ac_new_val"; then
	# differences in whitespace do not lead to failure.
	ac_old_val_w=`echo x $ac_old_val`
	ac_new_val_w=`echo x $ac_new_val`
	if test "$ac_old_val_w" != "$ac_new_val_w"; then
	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' has changed since the previous run:" >&5
printf "%s\n" "$as_me: error: '$ac_var' has changed since the previous run:" >&2;}
	  ac_cache_corrupted=:
	else
	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&5
printf "%s\n" "$as_me: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&2;}
	  eval $ac_var=\$ac_old_val
	fi
	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}:   former value:  '$ac_old_val'" >&5
printf "%s\n" "$as_me:   former value:  '$ac_old_val'" >&2;}
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}:   current value: '$ac_new_val'" >&5
printf "%s\n" "$as_me:   current value: '$ac_new_val'" >&2;}
      fi;;
  esac
  # Pass precious variables to config.status.
  if test "$ac_new_set" = set; then
    case $ac_new_val in
    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
    *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
    *) ac_arg=$ac_var=$ac_new_val ;;
    esac
    case " $ac_configure_args " in
      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
    esac
  fi
done
if $ac_cache_corrupted; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
  as_fn_error $? "run '${MAKE-make} distclean' and/or 'rm $cache_file'
	    and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
## -------------------- ##

ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu






TCL_VERSION=9.0
TCL_MAJOR_VERSION=9
TCL_MINOR_VERSION=0
TCL_PATCH_LEVEL="a2"
TCL_PATCH_LEVEL=".1"
VERSION=${TCL_VERSION}

EXTRA_INSTALL_BINARIES=${EXTRA_INSTALL_BINARIES:-"@:"}
EXTRA_BUILD_HTML=${EXTRA_BUILD_HTML:-"@:"}

#------------------------------------------------------------------------
# Setup configure arguments for bundled packages
2432
2433
2434
2435
2436
2437
2438
2439
2440


2441
2442


2443
2444
2445



2446
2447
2448
2449


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



2489
2490
2491
2492


2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505









2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520







2521
2522
2523
2524
2525
2526

2527




2528
2529

2530
2531

2532
2533
2534
2535
2536
2537
2538


2539
2540
2541
2542
2543


2544
2545
2546


2547
2548
2549
2550
2551
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
3134
3135

3136
3137
3138
3139
3140
3141
3142


3143
3144
3145


3146
3147
3148
3149
3150

3151
3152
3153
3154
3155
3156
3157


3158
3159
3160


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
3199



3200
3201
3202
3203
3204
3205









































































































3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230

3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259

3260
3261
3262
3263


3264
3265
3266

3267
3268
3269
3270
3271


3272
3273
3274


3275
3276
3277
3278
3279
3280



3281
3282
3283
3284









3285

3286
3287




3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302







3303
3304
3305
3306
3307
3308
3309


3310
3311
3312
3313


3314
3315
3316

3317
3318
3319


3320
3321
3322


3323
3324
3325
3326
3327
3328
3329
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
3134
3135

3136
3137

3138
3139
3140
3141
3142
3143
3144

3145
3146
3147
3148
3149


3150
3151
3152


3153
3154
3155
3156
3157
3158
3159
3160
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
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282


3283
3284
3285

3286
3287
3288

3289
3290
3291

3292
3293
3294
3295
3296
3297
3298

3299
3300
3301
3302
3303
3304
3305
3306
3307
3308

3309
3310
3311
3312
3313
3314
3315
3316

3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328



3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351

3352
3353
3354




3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373

3374
3375
3376
3377
3378

3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389


3390
3391
3392
3393




3394
3395
3396
3397
3398
3399
3400


3401
3402
3403




3404
3405
3406
3407
3408
3409




3410
3411
3412
3413
3414
3415
3416
3417


3418
3419
3420
3421
3422
3423
3424
3425

3426
3427
3428






3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444



3445
3446
3447
3448

3449
3450
3451
3452


3453
3454
3455
3456
3457
3458
3459
3460
3461
3462

3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476


3477
3478
3479
3480
3481
3482
3483
3484
3485

3486
3487
3488

3489
3490
3491
3492
3493
3494
3495
3496

3497
3498
3499

3500
3501
3502
3503
3504
3505
3506





3507
3508
3509
3510
3511
3512
3513
3514


3515
3516
3517

3518
3519
3520






3521
3522
3523
3524
3525
3526
3527
3528
3529
3530

3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544

3545
3546
3547


3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558


3559
3560
3561
3562


3563
3564
3565

3566
3567
3568

3569
3570
3571


3572
3573
3574
3575






3576
3577
3578
3579
3580
3581
3582
3583
3584
3585

3586
3587
3588
3589
3590
3591
3592
3593
3594
3595

3596
3597
3598


3599
3600
3601
3602

3603
3604

3605
3606
3607


3608
3609
3610
3611
3612
3613
3614
3615
3616

3617
3618






3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632

3633
3634
3635
3636
3637
3638
3639

3640
3641
3642


3643
3644
3645
3646
3647
3648

3649
3650
3651
3652
3653
3654
3655

3656
3657
3658


3659
3660
3661
3662
3663
3664
3665

3666
3667
3668
3669
3670
3671
3672

3673
3674
3675
3676

3677
3678
3679

3680
3681
3682


3683
3684
3685
3686



3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706






3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814






















3815



























3816

3817

3818
3819

3820
3821
3822
3823

3824
3825
3826
3827


3828
3829
3830


3831
3832






3833
3834
3835




3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846


3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859






3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871


3872
3873
3874
3875
3876

3877
3878
3879
3880

3881
3882
3883

3884
3885
3886


3887
3888
3889
3890
3891
3892
3893
3894
3895







-
-
+
+

-
+
+

-
-
+
+
+


-
-
+
+

-
-
+
+

-
+
+





-
-
+
+
+


-
-
+
+

-
-
+
+





-
-
+
+


-
-
+
+

-
+
+





-
-
+
+
+


-
-
+
+













+
+
+
+
+
+
+
+
+









-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+








-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+







-
-
+
+












-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+








-
-
-
-
-
-
+
+
+
+
+
+
+







+
-
+
+
+
+

-
-
+
+




-
+















-
+


-
+
+



-
-
+
+

-
-
+
+










-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+












-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+











-
-
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
-
+
+

-
+


-
+


-
+






-
+









-
+







-
+











-
-
-
+
+
+




















-
+


-
-
-
-
+
+
+
+
+














-
+




-
+










-
-
+
+
+

-
-
-
-
+
+
+
+
+


-
-
+
+

-
-
-
-
+
+
+
+
+

-
-
-
-
+
+
+
+




-
-
+
+






-
+


-
-
-
-
-
-
+
+
+
+
+
+
+









-
-
-
+
+
+

-
+
+


-
-
+
+








-
+


+
+









-
-
+
+







-
+


-
+







-
+


-
+






-
-
-
-
-
+
+
+
+
+



-
-
+
+

-
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+



-
+













-
+


-
-
+
+
+








-
-
+
+


-
-
+
+

-
+
+

-
+
+

-
-
+
+


-
-
-
-
-
-
+
+
+
+
+
+
+



-
+









-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
+
+
+
+





-
+

-
-
-
-
-
-
+
+
+
+
+
+
+







-
+






-
+
+

-
-
+
+




-
+






-
+
+

-
-
+
+





-
+






-
+
+


-
+
+

-
+
+

-
-
+
+
+

-
-
-
+
+
+














+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
+
-


-
+
+


-
+



-
-
+
+

-
-
+
+
-
-
-
-
-
-
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+

+
-
-
+
+
+
+









-
-
-
-
-
-
+
+
+
+
+
+
+





-
-
+
+



-
+
+


-
+


-
+
+

-
-
+
+







TCL_SRC_DIR="`cd "$srcdir"/..; pwd`"

#------------------------------------------------------------------------
# Compress and/or soft link the manpages?
#------------------------------------------------------------------------


    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use symlinks for manpages" >&5
$as_echo_n "checking whether to use symlinks for manpages... " >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to use symlinks for manpages" >&5
printf %s "checking whether to use symlinks for manpages... " >&6; }
    # Check whether --enable-man-symlinks was given.
if test "${enable_man_symlinks+set}" = set; then :
if test ${enable_man_symlinks+y}
then :
  enableval=$enable_man_symlinks; test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks"
else
  enableval="no"
else case e in #(
  e) enableval="no" ;;
esac
fi

    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5
$as_echo "$enableval" >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5
printf "%s\n" "$enableval" >&6; }

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to compress the manpages" >&5
$as_echo_n "checking whether to compress the manpages... " >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to compress the manpages" >&5
printf %s "checking whether to compress the manpages... " >&6; }
    # Check whether --enable-man-compression was given.
if test "${enable_man_compression+set}" = set; then :
if test ${enable_man_compression+y}
then :
  enableval=$enable_man_compression; case $enableval in
	    yes) as_fn_error $? "missing argument to --enable-man-compression" "$LINENO" 5;;
	    no)  ;;
	    *)   MAN_FLAGS="$MAN_FLAGS --compress $enableval";;
	esac
else
  enableval="no"
else case e in #(
  e) enableval="no" ;;
esac
fi

    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5
$as_echo "$enableval" >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5
printf "%s\n" "$enableval" >&6; }
    if test "$enableval" != "no"; then
	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compressed file suffix" >&5
$as_echo_n "checking for compressed file suffix... " >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for compressed file suffix" >&5
printf %s "checking for compressed file suffix... " >&6; }
	touch TeST
	$enableval TeST
	Z=`ls TeST* | sed 's/^....//'`
	rm -f TeST*
	MAN_FLAGS="$MAN_FLAGS --extension $Z"
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $Z" >&5
$as_echo "$Z" >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $Z" >&5
printf "%s\n" "$Z" >&6; }
    fi

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to add a package name suffix for the manpages" >&5
$as_echo_n "checking whether to add a package name suffix for the manpages... " >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to add a package name suffix for the manpages" >&5
printf %s "checking whether to add a package name suffix for the manpages... " >&6; }
    # Check whether --enable-man-suffix was given.
if test "${enable_man_suffix+set}" = set; then :
if test ${enable_man_suffix+y}
then :
  enableval=$enable_man_suffix; case $enableval in
	    yes) enableval="tcl" MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
	    no)  ;;
	    *)   MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
	esac
else
  enableval="no"
else case e in #(
  e) enableval="no" ;;
esac
fi

    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5
$as_echo "$enableval" >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5
printf "%s\n" "$enableval" >&6; }




#------------------------------------------------------------------------
# Standard compiler checks
#------------------------------------------------------------------------

# If the user did not set CFLAGS, set it now to keep
# the AC_PROG_CC macro from adding "-g -O2".
if test "${CFLAGS+set}" != "set" ; then
    CFLAGS=""
fi










ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CC+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CC="${ac_tool_prefix}gcc"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


fi
if test -z "$ac_cv_prog_CC"; then
  ac_ct_CC=$CC
  # Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_ac_ct_CC+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$ac_ct_CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$ac_ct_CC"; then
  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_CC="gcc"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
$as_echo "$ac_ct_CC" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
printf "%s\n" "$ac_ct_CC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi

  if test "x$ac_ct_CC" = x; then
    CC=""
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
    CC=$ac_ct_CC
  fi
else
  CC="$ac_cv_prog_CC"
fi

if test -z "$CC"; then
          if test -n "$ac_tool_prefix"; then
    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CC+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CC="${ac_tool_prefix}cc"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


  fi
fi
if test -z "$CC"; then
  # Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CC+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  ac_prog_rejected=no
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
       ac_prog_rejected=yes
       continue
     fi
    ac_cv_prog_CC="cc"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

if test $ac_prog_rejected = yes; then
  # We found a bogon in the path, so make sure we never use it.
  set dummy $ac_cv_prog_CC
  shift
  if test $# != 0; then
    # We chose a different compiler from the bogus one.
    # However, it has the same basename, so the bogon will be chosen
    # first if we set CC to just the basename; use the full file name.
    shift
    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
    ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
  fi
fi
fi
fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


fi
if test -z "$CC"; then
  if test -n "$ac_tool_prefix"; then
  for ac_prog in cl.exe
  do
    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CC+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


    test -n "$CC" && break
  done
fi
if test -z "$CC"; then
  ac_ct_CC=$CC
  for ac_prog in cl.exe
do
  # Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_ac_ct_CC+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$ac_ct_CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$ac_ct_CC"; then
  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_CC="$ac_prog"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
$as_echo "$ac_ct_CC" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
printf "%s\n" "$ac_ct_CC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


  test -n "$ac_ct_CC" && break
done

  if test "x$ac_ct_CC" = x; then
    CC=""
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
    CC=$ac_ct_CC
  fi
fi

fi
if test -z "$CC"; then
  if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
set dummy ${ac_tool_prefix}clang; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CC="${ac_tool_prefix}clang"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


fi
if test -z "$ac_cv_prog_CC"; then
  ac_ct_CC=$CC
  # Extract the first word of "clang", so it can be a program name with args.
set dummy clang; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$ac_ct_CC"; then
  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_CC="clang"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi ;;
esac
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
printf "%s\n" "$ac_ct_CC" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi

  if test "x$ac_ct_CC" = x; then
    CC=""
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
    CC=$ac_ct_CC
  fi
else
  CC="$ac_cv_prog_CC"
fi

fi


test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
See \`config.log' for more details" "$LINENO" 5; }
See 'config.log' for more details" "$LINENO" 5; }

# Provide some information about the compiler.
$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
set X $ac_compile
ac_compiler=$2
for ac_option in --version -v -V -qversion; do
for ac_option in --version -v -V -qversion -version; do
  { { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
  ac_status=$?
  if test -s conftest.err; then
    sed '10a\
... rest of stderr output deleted ...
         10q' conftest.err >conftest.er1
    cat conftest.er1 >&5
  fi
  rm -f conftest.er1 conftest.err
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
done

cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
$as_echo_n "checking whether the C compiler works... " >&6; }
ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
printf %s "checking whether the C compiler works... " >&6; }
ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`

# The possible output files:
ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"

ac_rmfiles=
for ac_file in $ac_files
do
  case $ac_file in
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
  esac
done
rm -f $ac_rmfiles

if { { ac_try="$ac_link_default"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link_default") 2>&5
  ac_status=$?
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }; then :
  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
then :
  # Autoconf-2.13 could set the ac_cv_exeext variable to 'no'.
# So ignore a value of 'no', otherwise this would lead to 'EXEEXT = no'
# in a Makefile.  We should not override ac_cv_exeext if it was cached,
# so that the user can short-circuit this test for compilers unknown to
# Autoconf.
for ac_file in $ac_files ''
do
  test -f "$ac_file" || continue
  case $ac_file in
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
	;;
    [ab].out )
	# We found the default executable, but exeext='' is most
	# certainly right.
	break;;
    *.* )
	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
	if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
	then :; else
	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
	fi
	# We set ac_cv_exeext here because the later test for it is not
	# safe: cross compilers may not add the suffix if given an `-o'
	# safe: cross compilers may not add the suffix if given an '-o'
	# argument, so we may need to know it at that point already.
	# Even if this section looks crufty: it has the advantage of
	# actually working.
	break;;
    * )
	break;;
  esac
done
test "$ac_cv_exeext" = no && ac_cv_exeext=

else
  ac_file=''
else case e in #(
  e) ac_file='' ;;
esac
fi
if test -z "$ac_file"; then :
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "$as_me: failed program was:" >&5
if test -z "$ac_file"
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error 77 "C compiler cannot create executables
See \`config.log' for more details" "$LINENO" 5; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
See 'config.log' for more details" "$LINENO" 5; }
else case e in #(
  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; } ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
$as_echo_n "checking for C compiler default output file name... " >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
$as_echo "$ac_file" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
printf %s "checking for C compiler default output file name... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
printf "%s\n" "$ac_file" >&6; }
ac_exeext=$ac_cv_exeext

rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
ac_clean_files=$ac_clean_files_save
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
$as_echo_n "checking for suffix of executables... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
printf %s "checking for suffix of executables... " >&6; }
if { { ac_try="$ac_link"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link") 2>&5
  ac_status=$?
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }; then :
  # If both `conftest.exe' and `conftest' are `present' (well, observable)
# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
# work properly (i.e., refer to `conftest.exe'), while it won't with
# `rm'.
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
then :
  # If both 'conftest.exe' and 'conftest' are 'present' (well, observable)
# catch 'conftest.exe'.  For instance with Cygwin, 'ls conftest' will
# work properly (i.e., refer to 'conftest.exe'), while it won't with
# 'rm'.
for ac_file in conftest.exe conftest conftest.*; do
  test -f "$ac_file" || continue
  case $ac_file in
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
	  break;;
    * ) break;;
  esac
done
else
  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
else case e in #(
  e) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details" "$LINENO" 5; }
See 'config.log' for more details" "$LINENO" 5; } ;;
esac
fi
rm -f conftest conftest$ac_cv_exeext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
$as_echo "$ac_cv_exeext" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
printf "%s\n" "$ac_cv_exeext" >&6; }

rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
ac_exeext=$EXEEXT
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <stdio.h>
int
main ()
main (void)
{
FILE *f = fopen ("conftest.out", "w");
 if (!f)
  return 1;
 return ferror (f) || fclose (f) != 0;

  ;
  return 0;
}
_ACEOF
ac_clean_files="$ac_clean_files conftest.out"
# Check that the compiler produces executables we can run.  If not, either
# the compiler is broken, or we cross compile.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
$as_echo_n "checking whether we are cross compiling... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
printf %s "checking whether we are cross compiling... " >&6; }
if test "$cross_compiling" != yes; then
  { { ac_try="$ac_link"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link") 2>&5
  ac_status=$?
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
  if { ac_try='./conftest$ac_cv_exeext'
  { { case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_try") 2>&5
  ac_status=$?
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }; }; then
    cross_compiling=no
  else
    if test "$cross_compiling" = maybe; then
	cross_compiling=yes
    else
	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot run C compiled programs.
If you meant to cross compile, use \`--host'.
See \`config.log' for more details" "$LINENO" 5; }
	{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error 77 "cannot run C compiled programs.
If you meant to cross compile, use '--host'.
See 'config.log' for more details" "$LINENO" 5; }
    fi
  fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
$as_echo "$cross_compiling" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
printf "%s\n" "$cross_compiling" >&6; }

rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
rm -f conftest.$ac_ext conftest$ac_cv_exeext \
  conftest.o conftest.obj conftest.out
ac_clean_files=$ac_clean_files_save
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
$as_echo_n "checking for suffix of object files... " >&6; }
if ${ac_cv_objext+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
printf %s "checking for suffix of object files... " >&6; }
if test ${ac_cv_objext+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
rm -f conftest.o conftest.obj
if { { ac_try="$ac_compile"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_compile") 2>&5
  ac_status=$?
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }; then :
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
then :
  for ac_file in conftest.o conftest.obj conftest.*; do
  test -f "$ac_file" || continue;
  case $ac_file in
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
       break;;
  esac
done
else
  $as_echo "$as_me: failed program was:" >&5
else case e in #(
  e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See \`config.log' for more details" "$LINENO" 5; }
See 'config.log' for more details" "$LINENO" 5; } ;;
esac
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
rm -f conftest.$ac_cv_objext conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
$as_echo "$ac_cv_objext" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
printf "%s\n" "$ac_cv_objext" >&6; }
OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
if ${ac_cv_c_compiler_gnu+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
printf %s "checking whether the compiler supports GNU C... " >&6; }
if test ${ac_cv_c_compiler_gnu+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{
#ifndef __GNUC__
       choke me
#endif

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  ac_compiler_gnu=yes
else
  ac_compiler_gnu=no
else case e in #(
  e) ac_compiler_gnu=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu

 ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
$as_echo "$ac_cv_c_compiler_gnu" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
ac_compiler_gnu=$ac_cv_c_compiler_gnu

if test $ac_compiler_gnu = yes; then
  GCC=yes
else
  GCC=
fi
ac_test_CFLAGS=${CFLAGS+set}
ac_test_CFLAGS=${CFLAGS+y}
ac_save_CFLAGS=$CFLAGS
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
$as_echo_n "checking whether $CC accepts -g... " >&6; }
if ${ac_cv_prog_cc_g+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_save_c_werror_flag=$ac_c_werror_flag
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
printf %s "checking whether $CC accepts -g... " >&6; }
if test ${ac_cv_prog_cc_g+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_save_c_werror_flag=$ac_c_werror_flag
   ac_c_werror_flag=yes
   ac_cv_prog_cc_g=no
   CFLAGS="-g"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_g=yes
else
  CFLAGS=""
else case e in #(
  e) CFLAGS=""
      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :

else
  ac_c_werror_flag=$ac_save_c_werror_flag
else case e in #(
  e) ac_c_werror_flag=$ac_save_c_werror_flag
	 CFLAGS="-g"
	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_g=yes
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   ac_c_werror_flag=$ac_save_c_werror_flag
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
   ac_c_werror_flag=$ac_save_c_werror_flag ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
$as_echo "$ac_cv_prog_cc_g" >&6; }
if test "$ac_test_CFLAGS" = set; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
if test $ac_test_CFLAGS; then
  CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
  if test "$GCC" = yes; then
    CFLAGS="-g -O2"
  else
    CFLAGS="-g"
  fi
else
  if test "$GCC" = yes; then
    CFLAGS="-O2"
  else
    CFLAGS=
  fi
fi
ac_prog_cc_stdc=no
if test x$ac_prog_cc_stdc = xno
then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
if ${ac_cv_prog_cc_c89+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_cv_prog_cc_c89=no
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
printf %s "checking for $CC option to enable C11 features... " >&6; }
if test ${ac_cv_prog_cc_c11+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_cv_prog_cc_c11=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$ac_c_conftest_c11_program
_ACEOF
for ac_arg in '' -std=gnu11
do
  CC="$ac_save_CC $ac_arg"
  if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_c11=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam
  test "x$ac_cv_prog_cc_c11" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC ;;
esac
fi

if test "x$ac_cv_prog_cc_c11" = xno
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
else case e in #(
  e) if test "x$ac_cv_prog_cc_c11" = x
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
else case e in #(
  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
     CC="$CC $ac_cv_prog_cc_c11" ;;
esac
fi
  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
  ac_prog_cc_stdc=c11 ;;
esac
fi
fi
if test x$ac_prog_cc_stdc = xno
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
printf %s "checking for $CC option to enable C99 features... " >&6; }
if test ${ac_cv_prog_cc_c99+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_cv_prog_cc_c99=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$ac_c_conftest_c99_program
_ACEOF
for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
do
  CC="$ac_save_CC $ac_arg"
  if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_c99=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam
  test "x$ac_cv_prog_cc_c99" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC ;;
esac
fi

if test "x$ac_cv_prog_cc_c99" = xno
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
else case e in #(
  e) if test "x$ac_cv_prog_cc_c99" = x
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
else case e in #(
  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
     CC="$CC $ac_cv_prog_cc_c99" ;;
esac
fi
  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
  ac_prog_cc_stdc=c99 ;;
esac
fi
fi
if test x$ac_prog_cc_stdc = xno
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
printf %s "checking for $CC option to enable C89 features... " >&6; }
if test ${ac_cv_prog_cc_c89+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_cv_prog_cc_c89=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <stdarg.h>
#include <stdio.h>
struct stat;
/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
struct buf { int x; };
FILE * (*rcsopen) (struct buf *, struct stat *, int);
static char *e (p, i)
     char **p;
     int i;
{
  return p[i];
}
static char *f (char * (*g) (char **, int), char **p, ...)
{
  char *s;
  va_list v;
  va_start (v,p);
  s = g (p, va_arg (v,int));
  va_end (v);
  return s;
}

$ac_c_conftest_c89_program
/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
   function prototypes and stuff, but not '\xHH' hex character constants.
   These don't provoke an error unfortunately, instead are silently treated
   as 'x'.  The following induces an error, until -std is added to get
   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
   array size at least.  It's necessary to write '\x00'==0 to get something
   that's true only with -std.  */
int osf4_cc_array ['\x00' == 0 ? 1 : -1];

/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
   inside strings and character constants.  */
#define FOO(x) 'x'
int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];

int test (int i, double x);
struct s1 {int (*f) (int a);};
struct s2 {int (*f) (double a);};
int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
int argc;
char **argv;
int
main ()
{
return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
  ;
  return 0;
}
_ACEOF
for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
  CC="$ac_save_CC $ac_arg"
  if ac_fn_c_try_compile "$LINENO"; then :
  if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_c89=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext
rm -f core conftest.err conftest.$ac_objext conftest.beam
  test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC

CC=$ac_save_CC ;;
esac
fi
# AC_CACHE_VAL
case "x$ac_cv_prog_cc_c89" in

if test "x$ac_cv_prog_cc_c89" = xno
  x)
    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
$as_echo "none needed" >&6; } ;;
  xno)
    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
$as_echo "unsupported" >&6; } ;;
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
  *)
    CC="$CC $ac_cv_prog_cc_c89"
    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
else case e in #(
  e) if test "x$ac_cv_prog_cc_c89" = x
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
else case e in #(
  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
     CC="$CC $ac_cv_prog_cc_c89" ;;
esac
fi
if test "x$ac_cv_prog_cc_c89" != xno; then :

  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
  ac_prog_cc_stdc=c89 ;;
esac
fi
fi

ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu


{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
$as_echo_n "checking for inline... " >&6; }
if ${ac_cv_c_inline+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_cv_c_inline=no
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
printf %s "checking for inline... " >&6; }
if test ${ac_cv_c_inline+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_cv_c_inline=no
for ac_kw in inline __inline__ __inline; do
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#ifndef __cplusplus
typedef int foo_t;
static $ac_kw foo_t static_foo () {return 0; }
$ac_kw foo_t foo () {return 0; }
static $ac_kw foo_t static_foo (void) {return 0; }
$ac_kw foo_t foo (void) {return 0; }
#endif

_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_c_inline=$ac_kw
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
  test "$ac_cv_c_inline" != no && break
done

 ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
$as_echo "$ac_cv_c_inline" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
printf "%s\n" "$ac_cv_c_inline" >&6; }

case $ac_cv_c_inline in
  inline | yes) ;;
  *)
    case $ac_cv_c_inline in
      no) ac_val=;;
      *) ac_val=$ac_cv_c_inline;;
3343
3344
3345
3346
3347
3348
3349





























3350
3351
3352
3353
3354
3355
3356


3357
3358
3359
3360
3361
3362
3363
3364
3365
3366






3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380

3381
3382
3383
3384
3385
3386


3387
3388
3389
3390




3391
3392
3393
3394
3395
3396
3397
3398
3399
3400


3401
3402
3403
3404


3405
3406


3407
3408
3409
3410
3411

3412
3413


3414
3415
3416
3417
3418
3419


3420
3421
3422
3423
3424
3425
3426


3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439

3440
3441
3442
3443
3444
3445


3446
3447
3448
3449




3450
3451
3452
3453
3454
3455
3456
3457
3458
3459


3460
3461
3462
3463


3464
3465


3466
3467
3468
3469
3470

3471
3472


3473
3474
3475
3476



3477
3478


3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494








3495
3496
3497
3498
3499

3500
3501






3502
3503
3504
3505
3506
3507





3508
3509


3510
3511
3512

3513
3514
3515
3516
3517
3518
3519


3520
3521
3522

3523
3524
3525


3526
3527
3528
3529
3530
3531
3532
3533

3534
3535
3536
3537
3538

3539

3540
3541
3542

3543
3544
3545
3546
3547
3548
3549


3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560




3561
3562
3563
3564
3565

3566
3567






3568
3569
3570
3571
3572
3573





3574
3575


3576
3577
3578

3579
3580
3581
3582
3583
3584
3585


3586
3587
3588

3589
3590
3591


3592
3593
3594
3595
3596
3597
3598
3599

3600
3601
3602
3603
3604

3605
3606
3607
3608

3609
3610
3611




3612
3613
3614
3615



3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633


3634
3635
3636
3637
3638
3639
3640
3641






3642
3643
3644
3645
3646
3647

3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670

3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733

3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786

3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805

3806
3807

3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820

3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854


3855
3856
3857



3858
3859

3860
3861
3862
3863
3864
3865
3866
3867
3868

3869
3870
3871
3872
3873
3874


3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890





3891
3892
3893
3894
3895



3896
3897
3898
3899
3900





3901
3902
3903
3904
3905
3906
3907
3908
3909


3910
3911


3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937







3938
3939
3940
3941
3942
3943

3944
3945
3946
3947
3948
3949
3950


3951
3952
3953



3954
3955
3956



3957
3958
3959


3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972


3973
3974
3975
3976
3977
3978
3979
3980

3981
3982
3983
3984
3985

3986
3987
3988
3989
3990
3991
3992
3993



















































































3994
3995
3996
3997
3998
3999
4000
4001


4002
4003
4004



4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018







4019
4020
4021
4022
4023
4024
4025

4026
4027
4028
4029
4030
4031
4032


4033
4034
4035



4036
4037

4038
4039


4040
4041
4042
4043




4044
4045
4046
4047
4048



4049
4050
4051

4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949


3950
3951
3952
3953
3954
3955
3956





3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968


3969
3970
3971
3972


3973



3974
3975

3976
3977
3978



3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991

3992
3993
3994
3995


3996
3997
3998

3999
4000
4001
4002
4003
4004

4005
4006

4007
4008
4009
4010
4011
4012
4013

4014
4015
4016
4017
4018
4019
4020


4021
4022
4023
4024
4025
4026
4027


4028
4029
4030
4031


4032



4033
4034

4035
4036
4037



4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050

4051
4052
4053
4054


4055
4056
4057

4058
4059
4060
4061
4062
4063

4064
4065

4066
4067
4068



4069
4070
4071
4072

4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083







4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097


4098
4099
4100
4101
4102
4103
4104





4105
4106
4107
4108
4109
4110

4111
4112
4113
4114

4115
4116
4117
4118
4119
4120


4121
4122
4123
4124

4125
4126


4127
4128
4129
4130
4131
4132
4133
4134
4135

4136
4137
4138
4139
4140

4141

4142
4143
4144

4145
4146
4147





4148
4149











4150
4151
4152
4153
4154
4155
4156
4157
4158
4159


4160
4161
4162
4163
4164
4165
4166





4167
4168
4169
4170
4171
4172

4173
4174
4175
4176

4177
4178
4179
4180
4181
4182


4183
4184
4185
4186

4187
4188


4189
4190
4191
4192
4193
4194
4195
4196
4197

4198
4199
4200
4201
4202

4203
4204
4205
4206

4207
4208


4209
4210
4211
4212
4213



4214
4215
4216













4217




4218
4219








4220
4221
4222
4223
4224
4225
4226

4227



4228
4229
4230
4231
4232
4233


















4234































































4235



















4236

































4237



















4238


4239











4240

4241


























4242
4243
4244
4245
4246
4247
4248

4249
4250
4251


4252
4253
4254
4255

4256
4257



4258




4259






4260
4261




4262











4263
4264
4265
4266
4267
4268
4269



4270
4271
4272
4273




4274
4275
4276
4277
4278
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
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
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458

4459
4460
4461


4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472






4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485

4486
4487
4488
4489
4490
4491
4492

4493
4494
4495


4496
4497
4498
4499

4500
4501

4502
4503
4504



4505
4506
4507
4508
4509
4510
4511


4512
4513
4514
4515
4516

4517
4518
4519

4520
4521
4522
4523
4524
4525
4526







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
-
+
+





-
-
-
-
-
+
+
+
+
+
+






-
-




-
-
+
-
-
-


-
+
+

-
-
-
+
+
+
+









-
+
+


-
-
+
+

-
+
+




-
+

-
+
+





-
+
+





-
-
+
+





-
-




-
-
+
-
-
-


-
+
+

-
-
-
+
+
+
+









-
+
+


-
-
+
+

-
+
+




-
+

-
+
+

-
-
-
+
+
+

-
+
+









-
-
-
-
-
-
-
+
+
+
+
+
+
+
+





+
-
-
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
+
+


-
+





-
-
+
+


-
+

-
-
+
+







-
+




-
+
-
+


-
+


-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+





+
-
-
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
+
+


-
+





-
-
+
+


-
+

-
-
+
+







-
+




-
+



-
+

-
-
+
+
+
+

-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+

-

-
-
-
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-

-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







-
+
+

-
-
+
+
+

-
+

-
-
-

-
-
-
-
+
-
-
-
-
-
-
+
+
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+


-
-
-
+
+
+

-
-
-
-
+
+
+
+
+

-



-
-
-
-
+
+
-
-
+
+
-



-
-














-
-
-
-
-
-
+
+
+
+
+
+
+





-
+






-
+
+

-
-
+
+
+

-
-
+
+
+

-
-
+
+












-
+
+






-
-
+
-



-
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+
+

-
-
+
+
+








-
-
-
-
-
-
+
+
+
+
+
+
+






-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+



-
-
+
+
+


-
+


-







#	- stdlib.h doesn't define strtol or strtoul in some versions
#	  of SunOS
#	- some versions of string.h don't declare procedures such
#	  as strstr
# Do this early, otherwise an autoconf bug throws errors on configure
#--------------------------------------------------------------------

ac_header= ac_cache=
for ac_item in $ac_header_c_list
do
  if test $ac_cache; then
    ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
    if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
      printf "%s\n" "#define $ac_item 1" >> confdefs.h
    fi
    ac_header= ac_cache=
  elif test $ac_header; then
    ac_cache=$ac_item
  else
    ac_header=$ac_item
  fi
done








if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
then :

printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h

fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
$as_echo_n "checking how to run the C preprocessor... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
printf %s "checking how to run the C preprocessor... " >&6; }
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
  CPP=
fi
if test -z "$CPP"; then
  if ${ac_cv_prog_CPP+:} false; then :
  $as_echo_n "(cached) " >&6
else
      # Double quotes because CPP needs to be expanded
    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
  if test ${ac_cv_prog_CPP+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)     # Double quotes because $CC needs to be expanded
    for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp
    do
      ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
  # Use a header file that comes with gcc, so configuring glibc
  # with a fresh cross-compiler works.
  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
  # <limits.h> exists even on freestanding compilers.
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp. "Syntax error" is here to catch this case.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#ifdef __STDC__
# include <limits.h>
#include <limits.h>
#else
# include <assert.h>
#endif
		     Syntax error
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
if ac_fn_c_try_cpp "$LINENO"
then :

else
  # Broken: fails on valid input.
continue
else case e in #(
  e) # Broken: fails on valid input.
continue ;;
esac
fi
rm -f conftest.err conftest.i conftest.$ac_ext

  # OK, works on sane cases.  Now check whether nonexistent headers
  # can be detected and how.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <ac_nonexistent.h>
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
if ac_fn_c_try_cpp "$LINENO"
then :
  # Broken: success on invalid input.
continue
else
  # Passes both tests.
else case e in #(
  e) # Passes both tests.
ac_preproc_ok=:
break
break ;;
esac
fi
rm -f conftest.err conftest.i conftest.$ac_ext

done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
# Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok; then :
if $ac_preproc_ok
then :
  break
fi

    done
    ac_cv_prog_CPP=$CPP

   ;;
esac
fi
  CPP=$ac_cv_prog_CPP
else
  ac_cv_prog_CPP=$CPP
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
$as_echo "$CPP" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
printf "%s\n" "$CPP" >&6; }
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
  # Use a header file that comes with gcc, so configuring glibc
  # with a fresh cross-compiler works.
  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
  # <limits.h> exists even on freestanding compilers.
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp. "Syntax error" is here to catch this case.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#ifdef __STDC__
# include <limits.h>
#include <limits.h>
#else
# include <assert.h>
#endif
		     Syntax error
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
if ac_fn_c_try_cpp "$LINENO"
then :

else
  # Broken: fails on valid input.
continue
else case e in #(
  e) # Broken: fails on valid input.
continue ;;
esac
fi
rm -f conftest.err conftest.i conftest.$ac_ext

  # OK, works on sane cases.  Now check whether nonexistent headers
  # can be detected and how.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <ac_nonexistent.h>
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
if ac_fn_c_try_cpp "$LINENO"
then :
  # Broken: success on invalid input.
continue
else
  # Passes both tests.
else case e in #(
  e) # Passes both tests.
ac_preproc_ok=:
break
break ;;
esac
fi
rm -f conftest.err conftest.i conftest.$ac_ext

done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
# Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok; then :
if $ac_preproc_ok
then :

else
  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
else case e in #(
  e) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
See \`config.log' for more details" "$LINENO" 5; }
See 'config.log' for more details" "$LINENO" 5; } ;;
esac
fi

ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu


{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
if ${ac_cv_path_GREP+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -z "$GREP"; then
  ac_path_GREP_found=false
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep -e" >&5
printf %s "checking for egrep -e... " >&6; }
if test ${ac_cv_path_EGREP_TRADITIONAL+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -z "$EGREP_TRADITIONAL"; then
  ac_path_EGREP_TRADITIONAL_found=false
  # Loop through the user's path and test for each of PROGNAME-LIST
  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    for ac_prog in grep ggrep; do
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_prog in grep ggrep
   do
    for ac_exec_ext in '' $ac_executable_extensions; do
      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
      as_fn_executable_p "$ac_path_GREP" || continue
# Check for GNU ac_path_GREP and select it if it is found.
  # Check for GNU $ac_path_GREP
case `"$ac_path_GREP" --version 2>&1` in
      ac_path_EGREP_TRADITIONAL="$as_dir$ac_prog$ac_exec_ext"
      as_fn_executable_p "$ac_path_EGREP_TRADITIONAL" || continue
# Check for GNU ac_path_EGREP_TRADITIONAL and select it if it is found.
  # Check for GNU $ac_path_EGREP_TRADITIONAL
case `"$ac_path_EGREP_TRADITIONAL" --version 2>&1` in #(
*GNU*)
  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
  ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL" ac_path_EGREP_TRADITIONAL_found=:;;
#(
*)
  ac_count=0
  $as_echo_n 0123456789 >"conftest.in"
  printf %s 0123456789 >"conftest.in"
  while :
  do
    cat "conftest.in" "conftest.in" >"conftest.tmp"
    mv "conftest.tmp" "conftest.in"
    cp "conftest.in" "conftest.nl"
    $as_echo 'GREP' >> "conftest.nl"
    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
    printf "%s\n" 'EGREP_TRADITIONAL' >> "conftest.nl"
    "$ac_path_EGREP_TRADITIONAL" -E 'EGR(EP|AC)_TRADITIONAL$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
    as_fn_arith $ac_count + 1 && ac_count=$as_val
    if test $ac_count -gt ${ac_path_GREP_max-0}; then
    if test $ac_count -gt ${ac_path_EGREP_TRADITIONAL_max-0}; then
      # Best one so far, save it but keep looking for a better one
      ac_cv_path_GREP="$ac_path_GREP"
      ac_path_GREP_max=$ac_count
      ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL"
      ac_path_EGREP_TRADITIONAL_max=$ac_count
    fi
    # 10*(2^10) chars as input seems more than enough
    test $ac_count -gt 10 && break
  done
  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac

      $ac_path_GREP_found && break 3
      $ac_path_EGREP_TRADITIONAL_found && break 3
    done
  done
  done
IFS=$as_save_IFS
  if test -z "$ac_cv_path_GREP"; then
  if test -z "$ac_cv_path_EGREP_TRADITIONAL"; then
    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
    :
  fi
else
  ac_cv_path_GREP=$GREP
  ac_cv_path_EGREP_TRADITIONAL=$EGREP_TRADITIONAL
fi

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
$as_echo "$ac_cv_path_GREP" >&6; }
 GREP="$ac_cv_path_GREP"

    if test "$ac_cv_path_EGREP_TRADITIONAL"
then :

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
$as_echo_n "checking for egrep... " >&6; }
if ${ac_cv_path_EGREP+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
   then ac_cv_path_EGREP="$GREP -E"
   else
     if test -z "$EGREP"; then
  ac_path_EGREP_found=false
  ac_cv_path_EGREP_TRADITIONAL="$ac_cv_path_EGREP_TRADITIONAL -E"
else case e in #(
  e) if test -z "$EGREP_TRADITIONAL"; then
  ac_path_EGREP_TRADITIONAL_found=false
  # Loop through the user's path and test for each of PROGNAME-LIST
  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    for ac_prog in egrep; do
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_prog in egrep
   do
    for ac_exec_ext in '' $ac_executable_extensions; do
      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
      as_fn_executable_p "$ac_path_EGREP" || continue
# Check for GNU ac_path_EGREP and select it if it is found.
  # Check for GNU $ac_path_EGREP
case `"$ac_path_EGREP" --version 2>&1` in
      ac_path_EGREP_TRADITIONAL="$as_dir$ac_prog$ac_exec_ext"
      as_fn_executable_p "$ac_path_EGREP_TRADITIONAL" || continue
# Check for GNU ac_path_EGREP_TRADITIONAL and select it if it is found.
  # Check for GNU $ac_path_EGREP_TRADITIONAL
case `"$ac_path_EGREP_TRADITIONAL" --version 2>&1` in #(
*GNU*)
  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
  ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL" ac_path_EGREP_TRADITIONAL_found=:;;
#(
*)
  ac_count=0
  $as_echo_n 0123456789 >"conftest.in"
  printf %s 0123456789 >"conftest.in"
  while :
  do
    cat "conftest.in" "conftest.in" >"conftest.tmp"
    mv "conftest.tmp" "conftest.in"
    cp "conftest.in" "conftest.nl"
    $as_echo 'EGREP' >> "conftest.nl"
    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
    printf "%s\n" 'EGREP_TRADITIONAL' >> "conftest.nl"
    "$ac_path_EGREP_TRADITIONAL" 'EGR(EP|AC)_TRADITIONAL$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
    as_fn_arith $ac_count + 1 && ac_count=$as_val
    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
    if test $ac_count -gt ${ac_path_EGREP_TRADITIONAL_max-0}; then
      # Best one so far, save it but keep looking for a better one
      ac_cv_path_EGREP="$ac_path_EGREP"
      ac_path_EGREP_max=$ac_count
      ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL"
      ac_path_EGREP_TRADITIONAL_max=$ac_count
    fi
    # 10*(2^10) chars as input seems more than enough
    test $ac_count -gt 10 && break
  done
  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac

      $ac_path_EGREP_found && break 3
      $ac_path_EGREP_TRADITIONAL_found && break 3
    done
  done
  done
IFS=$as_save_IFS
  if test -z "$ac_cv_path_EGREP"; then
  if test -z "$ac_cv_path_EGREP_TRADITIONAL"; then
    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
  fi
else
  ac_cv_path_EGREP=$EGREP
  ac_cv_path_EGREP_TRADITIONAL=$EGREP_TRADITIONAL
fi

   fi
 ;;
esac
fi ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
$as_echo "$ac_cv_path_EGREP" >&6; }
 EGREP="$ac_cv_path_EGREP"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP_TRADITIONAL" >&5
printf "%s\n" "$ac_cv_path_EGREP_TRADITIONAL" >&6; }
 EGREP_TRADITIONAL=$ac_cv_path_EGREP_TRADITIONAL


{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
$as_echo_n "checking for ANSI C header files... " >&6; }
if ${ac_cv_header_stdc+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <float.h>

int
main ()
{


    ac_fn_c_check_header_compile "$LINENO" "string.h" "ac_cv_header_string_h" "$ac_includes_default"
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  ac_cv_header_stdc=yes
else
  ac_cv_header_stdc=no
if test "x$ac_cv_header_string_h" = xyes
then :
  tcl_ok=1
else case e in #(
  e) tcl_ok=0 ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

if test $ac_cv_header_stdc = yes; then
  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <string.h>

_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  $EGREP "memchr" >/dev/null 2>&1; then :

else
  ac_cv_header_stdc=no
fi
rm -f conftest*

fi

if test $ac_cv_header_stdc = yes; then
  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <stdlib.h>

_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  $EGREP "free" >/dev/null 2>&1; then :
  $EGREP_TRADITIONAL "strstr" >/dev/null 2>&1

else
  ac_cv_header_stdc=no
fi
rm -f conftest*

fi

if test $ac_cv_header_stdc = yes; then
  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
  if test "$cross_compiling" = yes; then :
  :
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <ctype.h>
#include <stdlib.h>
#if ((' ' & 0x0FF) == 0x020)
# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
#else
# define ISLOWER(c) \
		   (('a' <= (c) && (c) <= 'i') \
		     || ('j' <= (c) && (c) <= 'r') \
		     || ('s' <= (c) && (c) <= 'z'))
# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
#endif

#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
int
main ()
{
  int i;
  for (i = 0; i < 256; i++)
    if (XOR (islower (i), ISLOWER (i))
	|| toupper (i) != TOUPPER (i))
      return 2;
  return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :

else
  ac_cv_header_stdc=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
  conftest.$ac_objext conftest.beam conftest.$ac_ext
fi

fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
$as_echo "$ac_cv_header_stdc" >&6; }
if test $ac_cv_header_stdc = yes; then

$as_echo "#define STDC_HEADERS 1" >>confdefs.h

fi

# On IRIX 5.3, sys/types and inttypes.h are conflicting.
for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
		  inttypes.h stdint.h unistd.h
do :
then :
  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
  cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF

fi

done



    { $as_echo "$as_me:${as_lineno-$LINENO}: checking dirent.h" >&5
$as_echo_n "checking dirent.h... " >&6; }
if ${tcl_cv_dirent_h+:} false; then :
  $as_echo_n "(cached) " >&6
else

    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/types.h>
#include <dirent.h>
int
main ()
{

#ifndef _POSIX_SOURCE
#   ifdef __Lynx__
	/*
	 * Generate compilation error to make the test fail:  Lynx headers
	 * are only valid if really in the POSIX environment.
	 */

	missing_procedure();
#   endif
#endif
DIR *d;
struct dirent *entryPtr;
char *p;
d = opendir("foobar");
entryPtr = readdir(d);
p = entryPtr->d_name;
closedir(d);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
  tcl_cv_dirent_h=yes
else
else case e in #(
  tcl_cv_dirent_h=no
fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_dirent_h" >&5
$as_echo "$tcl_cv_dirent_h" >&6; }

    if test $tcl_cv_dirent_h = no; then

$as_echo "#define NO_DIRENT_H 1" >>confdefs.h

    fi

    ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default"
if test "x$ac_cv_header_stdlib_h" = xyes; then :
  tcl_ok=1
else
  tcl_ok=0
  e) tcl_ok=0 ;;
fi

esac

    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <stdlib.h>

_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  $EGREP "strtol" >/dev/null 2>&1; then :

else
  tcl_ok=0
fi
rm -f conftest*
rm -rf conftest*

    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <stdlib.h>

_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  $EGREP "strtoul" >/dev/null 2>&1; then :

else
  tcl_ok=0
fi
rm -f conftest*

    if test $tcl_ok = 0; then

$as_echo "#define NO_STDLIB_H 1" >>confdefs.h

    fi
    ac_fn_c_check_header_mongrel "$LINENO" "string.h" "ac_cv_header_string_h" "$ac_includes_default"
if test "x$ac_cv_header_string_h" = xyes; then :
  tcl_ok=1
else
  tcl_ok=0
fi


    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <string.h>

_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  $EGREP "strstr" >/dev/null 2>&1; then :
  $EGREP_TRADITIONAL "strerror" >/dev/null 2>&1
then :

else
  tcl_ok=0
else case e in #(
  e) tcl_ok=0 ;;
esac
fi
rm -f conftest*
rm -rf conftest*

    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <string.h>

_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  $EGREP "strerror" >/dev/null 2>&1; then :

    ac_fn_c_check_header_compile "$LINENO" "sys/wait.h" "ac_cv_header_sys_wait_h" "$ac_includes_default"
else
  tcl_ok=0
fi
rm -f conftest*


if test "x$ac_cv_header_sys_wait_h" = xyes
then :
    # See also memmove check below for a place where NO_STRING_H can be
    # set and why.

    if test $tcl_ok = 0; then

$as_echo "#define NO_STRING_H 1" >>confdefs.h

    fi

    ac_fn_c_check_header_mongrel "$LINENO" "sys/wait.h" "ac_cv_header_sys_wait_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_wait_h" = xyes; then :

else

$as_echo "#define NO_SYS_WAIT_H 1" >>confdefs.h

else case e in #(
  e)
printf "%s\n" "#define NO_SYS_WAIT_H 1" >>confdefs.h
 ;;
esac
fi


    ac_fn_c_check_header_mongrel "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default"
if test "x$ac_cv_header_dlfcn_h" = xyes; then :
    ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default"
if test "x$ac_cv_header_dlfcn_h" = xyes
then :

else

$as_echo "#define NO_DLFCN_H 1" >>confdefs.h

else case e in #(
  e)
printf "%s\n" "#define NO_DLFCN_H 1" >>confdefs.h
 ;;
esac
fi



    # OS/390 lacks sys/param.h (and doesn't need it, by chance).
    for ac_header in sys/param.h
do :
  ac_fn_c_check_header_mongrel "$LINENO" "sys/param.h" "ac_cv_header_sys_param_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_param_h" = xyes; then :
    ac_fn_c_check_header_compile "$LINENO" "sys/param.h" "ac_cv_header_sys_param_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_param_h" = xyes
  cat >>confdefs.h <<_ACEOF
#define HAVE_SYS_PARAM_H 1
then :
  printf "%s\n" "#define HAVE_SYS_PARAM_H 1" >>confdefs.h
_ACEOF

fi

done



#--------------------------------------------------------------------
# Determines the correct executable file extension (.exe)
#--------------------------------------------------------------------



#------------------------------------------------------------------------
# If we're using GCC, see if the compiler understands -pipe.  If so, use it.
# It makes compiling go faster.  (This is only a performance feature.)
#------------------------------------------------------------------------

if test -z "$no_pipe" && test -n "$GCC"; then
    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the compiler understands -pipe" >&5
$as_echo_n "checking if the compiler understands -pipe... " >&6; }
if ${tcl_cv_cc_pipe+:} false; then :
  $as_echo_n "(cached) " >&6
else

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the compiler understands -pipe" >&5
printf %s "checking if the compiler understands -pipe... " >&6; }
if test ${tcl_cv_cc_pipe+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe"
	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_cc_pipe=yes
else
  tcl_cv_cc_pipe=no
else case e in #(
  e) tcl_cv_cc_pipe=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
	CFLAGS=$hold_cflags
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
	CFLAGS=$hold_cflags ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_pipe" >&5
$as_echo "$tcl_cv_cc_pipe" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_pipe" >&5
printf "%s\n" "$tcl_cv_cc_pipe" >&6; }
    if test $tcl_cv_cc_pipe = yes; then
	CFLAGS="$CFLAGS -pipe"
    fi
fi

#------------------------------------------------------------------------
# Embedded configuration information, encoding to use for the values, TIP #59
#------------------------------------------------------------------------



# Check whether --with-encoding was given.
if test "${with_encoding+set}" = set; then :
if test ${with_encoding+y}
then :
  withval=$with_encoding; with_tcencoding=${withval}
fi


    if test x"${with_tcencoding}" != x ; then

cat >>confdefs.h <<_ACEOF
#define TCL_CFGVAL_ENCODING "${with_tcencoding}"
printf "%s\n" "#define TCL_CFGVAL_ENCODING \"${with_tcencoding}\"" >>confdefs.h
_ACEOF

    else

$as_echo "#define TCL_CFGVAL_ENCODING \"utf-8\"" >>confdefs.h
printf "%s\n" "#define TCL_CFGVAL_ENCODING \"utf-8\"" >>confdefs.h

    fi


#--------------------------------------------------------------------
# Look for libraries that we will need when compiling the Tcl shell
#--------------------------------------------------------------------

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5
printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; }
if test ${ac_cv_c_undeclared_builtin_options+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_save_CFLAGS=$CFLAGS
   ac_cv_c_undeclared_builtin_options='cannot detect'
   for ac_arg in '' -fno-builtin; do
     CFLAGS="$ac_save_CFLAGS $ac_arg"
     # This test program should *not* compile successfully.
     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{
(void) strchr;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :

else case e in #(
  e) # This test program should compile successfully.
        # No library function is consistently available on
        # freestanding implementations, so test against a dummy
        # declaration.  Include always-available headers on the
        # off chance that they somehow elicit warnings.
        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <float.h>
#include <limits.h>
#include <stdarg.h>
#include <stddef.h>
extern void ac_decl (int, char *);

int
main (void)
{
(void) ac_decl (0, (char *) 0);
  (void) ac_decl;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  if test x"$ac_arg" = x
then :
  ac_cv_c_undeclared_builtin_options='none needed'
else case e in #(
  e) ac_cv_c_undeclared_builtin_options=$ac_arg ;;
esac
fi
          break
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
    done
    CFLAGS=$ac_save_CFLAGS
   ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_undeclared_builtin_options" >&5
printf "%s\n" "$ac_cv_c_undeclared_builtin_options" >&6; }
  case $ac_cv_c_undeclared_builtin_options in #(
  'cannot detect') :
    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "cannot make $CC report undeclared builtins
See 'config.log' for more details" "$LINENO" 5; } ;; #(
  'none needed') :
    ac_c_undeclared_builtin_options='' ;; #(
  *) :
    ac_c_undeclared_builtin_options=$ac_cv_c_undeclared_builtin_options ;;
esac


    #--------------------------------------------------------------------
    # On a few very rare systems, all of the libm.a stuff is
    # already in libc.a.  Set compiler flags accordingly.
    #--------------------------------------------------------------------

    ac_fn_c_check_func "$LINENO" "sin" "ac_cv_func_sin"
if test "x$ac_cv_func_sin" = xyes; then :
if test "x$ac_cv_func_sin" = xyes
then :
  MATH_LIBS=""
else
  MATH_LIBS="-lm"
else case e in #(
  e) MATH_LIBS="-lm" ;;
esac
fi


    #--------------------------------------------------------------------
    # Interactive UNIX requires -linet instead of -lsocket, plus it
    # needs net/errno.h to define the socket-related error codes.
    #--------------------------------------------------------------------

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -linet" >&5
$as_echo_n "checking for main in -linet... " >&6; }
if ${ac_cv_lib_inet_main+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_check_lib_save_LIBS=$LIBS
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -linet" >&5
printf %s "checking for main in -linet... " >&6; }
if test ${ac_cv_lib_inet_main+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_check_lib_save_LIBS=$LIBS
LIBS="-linet  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */


int
main ()
main (void)
{
return main ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_inet_main=yes
else
  ac_cv_lib_inet_main=no
else case e in #(
  e) ac_cv_lib_inet_main=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_inet_main" >&5
$as_echo "$ac_cv_lib_inet_main" >&6; }
if test "x$ac_cv_lib_inet_main" = xyes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_inet_main" >&5
printf "%s\n" "$ac_cv_lib_inet_main" >&6; }
if test "x$ac_cv_lib_inet_main" = xyes
then :
  LIBS="$LIBS -linet"
fi

    ac_fn_c_check_header_mongrel "$LINENO" "net/errno.h" "ac_cv_header_net_errno_h" "$ac_includes_default"
if test "x$ac_cv_header_net_errno_h" = xyes; then :
    ac_fn_c_check_header_compile "$LINENO" "net/errno.h" "ac_cv_header_net_errno_h" "$ac_includes_default"
if test "x$ac_cv_header_net_errno_h" = xyes
then :


$as_echo "#define HAVE_NET_ERRNO_H 1" >>confdefs.h
printf "%s\n" "#define HAVE_NET_ERRNO_H 1" >>confdefs.h

fi



    #--------------------------------------------------------------------
    #	Check for the existence of the -lsocket and -lnsl libraries.
    #	The order here is important, so that they end up in the right
    #	order in the command line generated by make.  Here are some
    #	special considerations:
4070
4071
4072
4073
4074
4075
4076
4077


4078
4079
4080



4081
4082
4083
4084
4085


4086
4087
4088
4089
4090
4091
4092
4093








4094
4095
4096
4097
4098
4099
4100




4101
4102
4103
4104

4105
4106

4107
4108
4109
4110
4111
4112
4113


4114
4115
4116



4117
4118

4119
4120


4121
4122
4123
4124




4125
4126
4127



4128
4129


4130
4131
4132
4133
4134
4135
4136
4137


4138
4139
4140



4141
4142
4143
4144
4145


4146
4147
4148
4149
4150
4151
4152
4153








4154
4155
4156
4157
4158
4159
4160




4161
4162
4163
4164

4165
4166

4167
4168
4169
4170
4171
4172
4173


4174
4175
4176



4177
4178

4179
4180


4181
4182
4183
4184




4185
4186
4187


4188
4189
4190
4191
4192

4193
4194
4195

4196
4197
4198
4199
4200
4201
4202







4203
4204
4205
4206
4207
4208
4209




4210
4211
4212
4213

4214
4215

4216
4217
4218
4219
4220
4221
4222


4223
4224
4225



4226
4227

4228
4229


4230
4231
4232
4233




4234
4235
4236



4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250







4251
4252
4253
4254
4255
4256
4257




4258
4259
4260
4261

4262
4263

4264
4265
4266
4267
4268
4269
4270


4271
4272
4273



4274
4275

4276
4277


4278
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
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
4436
4437
4438
4439

4440
4441
4442
4443
4444
4445









4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457




4458
4459
4460



4461
4462
4463
4464

4465
4466


4467
4468
4469



4470
4471
4472
4473
4474
4475
4476
4477
4478
4479


4480
4481


4482
4483
4484


4485
4486

4487
4488
4489
4490
4491
4492
4493

4494
4495
4496
4497


4498
4499
4500
4501


4502
4503
4504

4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522







4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535


4536
4537
4538
4539
4540
4541
4542


4543
4544
4545
4546
4547


4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561



4562
4563
4564
4565


4566
4567
4568



4569
4570
4571
4572
4573




4574
4575
4576
4577


4578
4579
4580
4581
4582
4583
4584







4585
4586
4587
4588
4589
4590




4591
4592
4593
4594

4595
4596

4597
4598
4599
4600
4601
4602
4603


4604
4605
4606
4607
4608
4609
4610


4611
4612
4613

4614
4615


4616
4617
4618
4619


4620
4621
4622



4623
4624
4625


4626
4627
4628


4629
4630


4631
4632
4633
4634


4635
4636


4637
4638
4639
4640


4641
4642
4643
4644
4645
4646
4647
4648
4649

4650
4651
4652

4653
4654
4655
4656
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
4688
4689







4690
4691
4692
4693
4694
4695
4696




4697
4698
4699
4700

4701
4702

4703
4704
4705
4706
4707
4708
4709


4710
4711
4712



4713
4714

4715
4716


4717
4718
4719
4720




4721
4722
4723
4724




4725
4726
4727
4728
4729


4730

4731
4732

4733
4734

4735

4736


4737
4738
4739
4740
4741
4742
4743


4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760







4761
4762
4763
4764
4765
4766

4767




4768
4769

4770
4771

4772
4773
4774
4775
4776
4777
4778


4779
4780
4781
4782
4783


4784
4785
4786


4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800







4801
4802
4803
4804
4805
4806

4807




4808
4809

4810
4811

4812
4813
4814
4815
4816
4817
4818


4819
4820
4821
4822
4823


4824
4825
4826


4827
4828
4829
4830
4831
4832
4833
4834
4835


4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849


4850
4851


4852
4853
4854



4855
4856
4857
4858


4859
4860
4861
4862
4863


4864
4865


4866
4867
4868



4869
4870
4871
4872


4873
4874


4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886







4887
4888
4889
4890
4891
4892
4893
4894

4895
4896
4897
4898
4899
4900
4901


4902
4903
4904



4905
4906

4907
4908


4909
4910
4911
4912




4913
4914
4915

4916
4917
4918

4919
4920
4921
4922
4923
4924
4925
4926


4927
4928


4929
4930
4931



4932
4933
4934
4935


4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946







4947
4948
4949
4950
4951
4952
4953


4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964


4965
4966
4967


4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979







4980
4981
4982
4983
4984
4985
4986




4987
4988
4989
4990

4991
4992

4993
4994
4995
4996
4997
4998
4999


5000
5001
5002



5003
5004

5005
5006


5007
5008
5009
5010




5011
5012
5013



5014
5015
5016
5017
5018
5019
5020
4535
4536
4537
4538
4539
4540
4541

4542
4543
4544


4545
4546
4547
4548
4549
4550
4551

4552
4553
4554







4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568

4569
4570
4571
4572
4573
4574
4575

4576
4577

4578
4579
4580
4581
4582
4583
4584

4585
4586
4587


4588
4589
4590
4591

4592
4593

4594
4595
4596



4597
4598
4599
4600
4601


4602
4603
4604
4605

4606
4607
4608
4609
4610
4611
4612
4613
4614

4615
4616
4617


4618
4619
4620
4621
4622
4623
4624

4625
4626
4627







4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641

4642
4643
4644
4645
4646
4647
4648

4649
4650

4651
4652
4653
4654
4655
4656
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
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699

4700
4701
4702
4703
4704
4705
4706

4707
4708

4709
4710
4711
4712
4713
4714
4715

4716
4717
4718


4719
4720
4721
4722

4723
4724

4725
4726
4727



4728
4729
4730
4731
4732


4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743






4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756

4757
4758
4759
4760
4761
4762
4763

4764
4765

4766
4767
4768
4769
4770
4771
4772

4773
4774
4775


4776
4777
4778
4779

4780
4781

4782
4783
4784



4785
4786
4787
4788
4789


4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800






4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813

4814
4815
4816
4817
4818
4819
4820

4821
4822

4823
4824
4825
4826
4827
4828
4829

4830
4831
4832


4833
4834
4835
4836

4837
4838

4839
4840
4841



4842
4843
4844
4845
4846


4847
4848
4849
4850
4851
4852
4853
4854
4855






4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868

4869
4870
4871
4872
4873
4874
4875

4876
4877

4878
4879
4880
4881
4882
4883
4884

4885
4886
4887


4888
4889
4890
4891

4892
4893

4894
4895
4896



4897
4898
4899
4900
4901


4902
4903
4904
4905
4906
4907






4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920

4921
4922
4923
4924
4925
4926
4927

4928
4929

4930
4931
4932
4933
4934
4935
4936

4937
4938
4939


4940
4941
4942
4943

4944
4945

4946
4947
4948



4949
4950
4951
4952
4953


4954
4955
4956
4957
4958
4959
4960
4961
4962


4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975






4976
4977
4978
4979
4980
4981
4982
4983
4984


4985
4986

4987
4988
4989
4990



4991
4992
4993
4994
4995


4996
4997
4998
4999



5000


5001
5002
5003


5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014


5015
5016
5017

5018
5019
5020


5021
5022


5023







5024
5025
5026


5027
5028
5029
5030


5031
5032
5033
5034

5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047






5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066

5067
5068
5069
5070
5071
5072
5073


5074
5075
5076
5077
5078


5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092


5093
5094
5095
5096
5097
5098

5099
5100
5101


5102
5103
5104
5105
5106



5107
5108
5109
5110
5111
5112


5113
5114
5115






5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127

5128
5129
5130
5131
5132
5133
5134

5135
5136

5137
5138
5139
5140
5141
5142
5143

5144
5145
5146
5147
5148
5149
5150
5151

5152
5153
5154
5155

5156
5157

5158
5159
5160
5161
5162

5163
5164
5165


5166
5167
5168
5169
5170

5171
5172
5173


5174
5175
5176

5177
5178
5179
5180


5181
5182
5183

5184
5185
5186
5187
5188

5189
5190
5191
5192
5193
5194
5195
5196
5197
5198

5199
5200

5201
5202
5203
5204
5205
5206
5207
5208
5209

5210
5211
5212
5213
5214
5215


5216
5217
5218
5219
5220
5221

5222
5223
5224


5225
5226
5227
5228
5229



5230
5231
5232
5233
5234
5235


5236
5237
5238






5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251

5252
5253
5254
5255
5256
5257
5258

5259
5260

5261
5262
5263
5264
5265
5266
5267

5268
5269
5270


5271
5272
5273
5274

5275
5276

5277
5278
5279



5280
5281
5282
5283
5284



5285
5286
5287
5288
5289
5290
5291
5292

5293
5294
5295
5296
5297

5298
5299
5300
5301

5302
5303
5304
5305
5306
5307
5308
5309
5310
5311

5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324






5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338

5339
5340
5341
5342
5343

5344
5345

5346
5347
5348
5349
5350
5351
5352

5353
5354
5355
5356
5357


5358
5359
5360


5361
5362
5363
5364
5365
5366
5367
5368
5369
5370






5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384

5385
5386
5387
5388
5389

5390
5391

5392
5393
5394
5395
5396
5397
5398

5399
5400
5401
5402
5403


5404
5405
5406


5407
5408
5409
5410
5411
5412
5413
5414
5415


5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429


5430
5431
5432

5433
5434
5435


5436
5437
5438
5439
5440


5441
5442
5443
5444
5445


5446
5447
5448

5449
5450
5451


5452
5453
5454
5455
5456


5457
5458
5459

5460
5461
5462
5463
5464
5465
5466
5467






5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481

5482
5483
5484
5485
5486
5487
5488

5489
5490
5491


5492
5493
5494
5495

5496
5497

5498
5499
5500



5501
5502
5503
5504
5505
5506

5507
5508
5509

5510
5511
5512
5513
5514
5515
5516


5517
5518
5519

5520
5521
5522


5523
5524
5525
5526
5527


5528
5529
5530
5531
5532
5533
5534






5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546


5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558

5559
5560
5561


5562
5563
5564
5565
5566
5567
5568
5569






5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582

5583
5584
5585
5586
5587
5588
5589

5590
5591

5592
5593
5594
5595
5596
5597
5598

5599
5600
5601


5602
5603
5604
5605

5606
5607

5608
5609
5610



5611
5612
5613
5614
5615


5616
5617
5618
5619
5620
5621
5622
5623
5624
5625







-
+
+

-
-
+
+
+




-
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+






-
+
+
+
+



-
+

-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+

-
-
+
+
+

-
+
+







-
+
+

-
-
+
+
+




-
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+






-
+
+
+
+



-
+

-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+


-
+
+




-
+


-
+

-
-
-
-
-
-
+
+
+
+
+
+
+






-
+
+
+
+



-
+

-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+

-
-
+
+
+








-
-
-
-
-
-
+
+
+
+
+
+
+






-
+
+
+
+



-
+

-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+

-
-
+
+
+








-
-
-
-
-
-
+
+
+
+
+
+
+






-
+
+
+
+



-
+

-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+

-
-
+
+
+






-
-
-
-
-
-
+
+
+
+
+
+
+






-
+
+
+
+



-
+

-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+

-
-
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+
+






-
+
+
+
+



-
+

-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+

-
-
+
+
+






-
-
+
+










+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-


-




-
-
-
+
+
+
+

-
-
+
+
+

-
-
-
+
-
-
+
+

-
-
+
+
+








-
-
+
+

-
+
+

-
-
+
+
-
-
+
-
-
-
-
-
-
-
+


-
-
+
+


-
-
+
+


-
+












-
-
-
-
-
-
+
+
+
+
+
+
+












-
+
+





-
-
+
+



-
-
+
+












-
-
+
+
+



-
+
+

-
-
+
+
+


-
-
-
+
+
+
+


-
-
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+





-
+
+
+
+



-
+

-
+






-
+
+






-
+
+


-
+

-
+
+



-
+
+

-
-
+
+
+


-
+
+

-
-
+
+

-
+
+


-
-
+
+

-
+
+



-
+
+








-
+

-

+







-
+
+




-
-
+
+
+



-
+
+

-
-
+
+
+


-
-
-
+
+
+
+


-
-
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+






-
+
+
+
+



-
+

-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+

-
-
-
+
+
+
+




-
+
+

+

-
+


+
-
+

+
+






-
+
+











-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+








-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+







-
-
+
+












-
-
+
+

-
+
+

-
-
+
+
+


-
-
+
+



-
-
+
+

-
+
+

-
-
+
+
+


-
-
+
+

-
+
+






-
-
-
-
-
-
+
+
+
+
+
+
+







-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+


-
+


-
+






-
-
+
+

-
+
+

-
-
+
+
+


-
-
+
+





-
-
-
-
-
-
+
+
+
+
+
+
+





-
-
+
+










-
+
+

-
-
+
+






-
-
-
-
-
-
+
+
+
+
+
+
+






-
+
+
+
+



-
+

-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+

-
-
+
+
+







    #	4. On some SVR4 systems, can't use -lsocket without -lnsl too.
    #	   To get around this problem, check for both libraries together
    #	   if -lsocket doesn't work by itself.
    #--------------------------------------------------------------------

    tcl_checkBoth=0
    ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect"
if test "x$ac_cv_func_connect" = xyes; then :
if test "x$ac_cv_func_connect" = xyes
then :
  tcl_checkSocket=0
else
  tcl_checkSocket=1
else case e in #(
  e) tcl_checkSocket=1 ;;
esac
fi

    if test "$tcl_checkSocket" = 1; then
	ac_fn_c_check_func "$LINENO" "setsockopt" "ac_cv_func_setsockopt"
if test "x$ac_cv_func_setsockopt" = xyes; then :
if test "x$ac_cv_func_setsockopt" = xyes
then :

else
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for setsockopt in -lsocket" >&5
$as_echo_n "checking for setsockopt in -lsocket... " >&6; }
if ${ac_cv_lib_socket_setsockopt+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_check_lib_save_LIBS=$LIBS
else case e in #(
  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for setsockopt in -lsocket" >&5
printf %s "checking for setsockopt in -lsocket... " >&6; }
if test ${ac_cv_lib_socket_setsockopt+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lsocket  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
   builtin and then its argument prototype would still apply.
   The 'extern "C"' is for builds by C++ compilers;
   although this is not generally supported in C code supporting it here
   has little cost and some practical benefit (sr 110532).  */
#ifdef __cplusplus
extern "C"
#endif
char setsockopt ();
char setsockopt (void);
int
main ()
main (void)
{
return setsockopt ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_socket_setsockopt=yes
else
  ac_cv_lib_socket_setsockopt=no
else case e in #(
  e) ac_cv_lib_socket_setsockopt=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_setsockopt" >&5
$as_echo "$ac_cv_lib_socket_setsockopt" >&6; }
if test "x$ac_cv_lib_socket_setsockopt" = xyes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_setsockopt" >&5
printf "%s\n" "$ac_cv_lib_socket_setsockopt" >&6; }
if test "x$ac_cv_lib_socket_setsockopt" = xyes
then :
  LIBS="$LIBS -lsocket"
else
  tcl_checkBoth=1
else case e in #(
  e) tcl_checkBoth=1 ;;
esac
fi

 ;;
esac
fi

    fi
    if test "$tcl_checkBoth" = 1; then
	tk_oldLibs=$LIBS
	LIBS="$LIBS -lsocket -lnsl"
	ac_fn_c_check_func "$LINENO" "accept" "ac_cv_func_accept"
if test "x$ac_cv_func_accept" = xyes; then :
if test "x$ac_cv_func_accept" = xyes
then :
  tcl_checkNsl=0
else
  LIBS=$tk_oldLibs
else case e in #(
  e) LIBS=$tk_oldLibs ;;
esac
fi

    fi
    ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname"
if test "x$ac_cv_func_gethostbyname" = xyes; then :
if test "x$ac_cv_func_gethostbyname" = xyes
then :

else
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5
$as_echo_n "checking for gethostbyname in -lnsl... " >&6; }
if ${ac_cv_lib_nsl_gethostbyname+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_check_lib_save_LIBS=$LIBS
else case e in #(
  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5
printf %s "checking for gethostbyname in -lnsl... " >&6; }
if test ${ac_cv_lib_nsl_gethostbyname+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lnsl  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
   builtin and then its argument prototype would still apply.
   The 'extern "C"' is for builds by C++ compilers;
   although this is not generally supported in C code supporting it here
   has little cost and some practical benefit (sr 110532).  */
#ifdef __cplusplus
extern "C"
#endif
char gethostbyname ();
char gethostbyname (void);
int
main ()
main (void)
{
return gethostbyname ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_nsl_gethostbyname=yes
else
  ac_cv_lib_nsl_gethostbyname=no
else case e in #(
  e) ac_cv_lib_nsl_gethostbyname=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5
$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; }
if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5
printf "%s\n" "$ac_cv_lib_nsl_gethostbyname" >&6; }
if test "x$ac_cv_lib_nsl_gethostbyname" = xyes
then :
  LIBS="$LIBS -lnsl"
fi

 ;;
esac
fi



$as_echo "#define _REENTRANT 1" >>confdefs.h
printf "%s\n" "#define _REENTRANT 1" >>confdefs.h


$as_echo "#define _THREAD_SAFE 1" >>confdefs.h
printf "%s\n" "#define _THREAD_SAFE 1" >>confdefs.h

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread" >&5
$as_echo_n "checking for pthread_mutex_init in -lpthread... " >&6; }
if ${ac_cv_lib_pthread_pthread_mutex_init+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_check_lib_save_LIBS=$LIBS
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread" >&5
printf %s "checking for pthread_mutex_init in -lpthread... " >&6; }
if test ${ac_cv_lib_pthread_pthread_mutex_init+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lpthread  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
   builtin and then its argument prototype would still apply.
   The 'extern "C"' is for builds by C++ compilers;
   although this is not generally supported in C code supporting it here
   has little cost and some practical benefit (sr 110532).  */
#ifdef __cplusplus
extern "C"
#endif
char pthread_mutex_init ();
char pthread_mutex_init (void);
int
main ()
main (void)
{
return pthread_mutex_init ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_pthread_pthread_mutex_init=yes
else
  ac_cv_lib_pthread_pthread_mutex_init=no
else case e in #(
  e) ac_cv_lib_pthread_pthread_mutex_init=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5
$as_echo "$ac_cv_lib_pthread_pthread_mutex_init" >&6; }
if test "x$ac_cv_lib_pthread_pthread_mutex_init" = xyes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5
printf "%s\n" "$ac_cv_lib_pthread_pthread_mutex_init" >&6; }
if test "x$ac_cv_lib_pthread_pthread_mutex_init" = xyes
then :
  tcl_ok=yes
else
  tcl_ok=no
else case e in #(
  e) tcl_ok=no ;;
esac
fi

    if test "$tcl_ok" = "no"; then
	# Check a little harder for __pthread_mutex_init in the same
	# library, as some systems hide it there until pthread.h is
	# defined.  We could alternatively do an AC_TRY_COMPILE with
	# pthread.h, but that will work with libpthread really doesn't
	# exist, like AIX 4.2.  [Bug: 4359]
	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __pthread_mutex_init in -lpthread" >&5
$as_echo_n "checking for __pthread_mutex_init in -lpthread... " >&6; }
if ${ac_cv_lib_pthread___pthread_mutex_init+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_check_lib_save_LIBS=$LIBS
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for __pthread_mutex_init in -lpthread" >&5
printf %s "checking for __pthread_mutex_init in -lpthread... " >&6; }
if test ${ac_cv_lib_pthread___pthread_mutex_init+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lpthread  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
   builtin and then its argument prototype would still apply.
   The 'extern "C"' is for builds by C++ compilers;
   although this is not generally supported in C code supporting it here
   has little cost and some practical benefit (sr 110532).  */
#ifdef __cplusplus
extern "C"
#endif
char __pthread_mutex_init ();
char __pthread_mutex_init (void);
int
main ()
main (void)
{
return __pthread_mutex_init ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_pthread___pthread_mutex_init=yes
else
  ac_cv_lib_pthread___pthread_mutex_init=no
else case e in #(
  e) ac_cv_lib_pthread___pthread_mutex_init=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5
$as_echo "$ac_cv_lib_pthread___pthread_mutex_init" >&6; }
if test "x$ac_cv_lib_pthread___pthread_mutex_init" = xyes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5
printf "%s\n" "$ac_cv_lib_pthread___pthread_mutex_init" >&6; }
if test "x$ac_cv_lib_pthread___pthread_mutex_init" = xyes
then :
  tcl_ok=yes
else
  tcl_ok=no
else case e in #(
  e) tcl_ok=no ;;
esac
fi

    fi

    if test "$tcl_ok" = "yes"; then
	# The space is needed
	THREADS_LIBS=" -lpthread"
    else
	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthreads" >&5
$as_echo_n "checking for pthread_mutex_init in -lpthreads... " >&6; }
if ${ac_cv_lib_pthreads_pthread_mutex_init+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_check_lib_save_LIBS=$LIBS
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthreads" >&5
printf %s "checking for pthread_mutex_init in -lpthreads... " >&6; }
if test ${ac_cv_lib_pthreads_pthread_mutex_init+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lpthreads  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
   builtin and then its argument prototype would still apply.
   The 'extern "C"' is for builds by C++ compilers;
   although this is not generally supported in C code supporting it here
   has little cost and some practical benefit (sr 110532).  */
#ifdef __cplusplus
extern "C"
#endif
char pthread_mutex_init ();
char pthread_mutex_init (void);
int
main ()
main (void)
{
return pthread_mutex_init ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_pthreads_pthread_mutex_init=yes
else
  ac_cv_lib_pthreads_pthread_mutex_init=no
else case e in #(
  e) ac_cv_lib_pthreads_pthread_mutex_init=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5
$as_echo "$ac_cv_lib_pthreads_pthread_mutex_init" >&6; }
if test "x$ac_cv_lib_pthreads_pthread_mutex_init" = xyes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5
printf "%s\n" "$ac_cv_lib_pthreads_pthread_mutex_init" >&6; }
if test "x$ac_cv_lib_pthreads_pthread_mutex_init" = xyes
then :
  _ok=yes
else
  tcl_ok=no
else case e in #(
  e) tcl_ok=no ;;
esac
fi

	if test "$tcl_ok" = "yes"; then
	    # The space is needed
	    THREADS_LIBS=" -lpthreads"
	else
	    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc" >&5
$as_echo_n "checking for pthread_mutex_init in -lc... " >&6; }
if ${ac_cv_lib_c_pthread_mutex_init+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_check_lib_save_LIBS=$LIBS
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc" >&5
printf %s "checking for pthread_mutex_init in -lc... " >&6; }
if test ${ac_cv_lib_c_pthread_mutex_init+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lc  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
   builtin and then its argument prototype would still apply.
   The 'extern "C"' is for builds by C++ compilers;
   although this is not generally supported in C code supporting it here
   has little cost and some practical benefit (sr 110532).  */
#ifdef __cplusplus
extern "C"
#endif
char pthread_mutex_init ();
char pthread_mutex_init (void);
int
main ()
main (void)
{
return pthread_mutex_init ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_c_pthread_mutex_init=yes
else
  ac_cv_lib_c_pthread_mutex_init=no
else case e in #(
  e) ac_cv_lib_c_pthread_mutex_init=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_pthread_mutex_init" >&5
$as_echo "$ac_cv_lib_c_pthread_mutex_init" >&6; }
if test "x$ac_cv_lib_c_pthread_mutex_init" = xyes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_pthread_mutex_init" >&5
printf "%s\n" "$ac_cv_lib_c_pthread_mutex_init" >&6; }
if test "x$ac_cv_lib_c_pthread_mutex_init" = xyes
then :
  tcl_ok=yes
else
  tcl_ok=no
else case e in #(
  e) tcl_ok=no ;;
esac
fi

	    if test "$tcl_ok" = "no"; then
		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc_r" >&5
$as_echo_n "checking for pthread_mutex_init in -lc_r... " >&6; }
if ${ac_cv_lib_c_r_pthread_mutex_init+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_check_lib_save_LIBS=$LIBS
		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc_r" >&5
printf %s "checking for pthread_mutex_init in -lc_r... " >&6; }
if test ${ac_cv_lib_c_r_pthread_mutex_init+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lc_r  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
   builtin and then its argument prototype would still apply.
   The 'extern "C"' is for builds by C++ compilers;
   although this is not generally supported in C code supporting it here
   has little cost and some practical benefit (sr 110532).  */
#ifdef __cplusplus
extern "C"
#endif
char pthread_mutex_init ();
char pthread_mutex_init (void);
int
main ()
main (void)
{
return pthread_mutex_init ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_c_r_pthread_mutex_init=yes
else
  ac_cv_lib_c_r_pthread_mutex_init=no
else case e in #(
  e) ac_cv_lib_c_r_pthread_mutex_init=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5
$as_echo "$ac_cv_lib_c_r_pthread_mutex_init" >&6; }
if test "x$ac_cv_lib_c_r_pthread_mutex_init" = xyes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5
printf "%s\n" "$ac_cv_lib_c_r_pthread_mutex_init" >&6; }
if test "x$ac_cv_lib_c_r_pthread_mutex_init" = xyes
then :
  tcl_ok=yes
else
  tcl_ok=no
else case e in #(
  e) tcl_ok=no ;;
esac
fi

		if test "$tcl_ok" = "yes"; then
		    # The space is needed
		    THREADS_LIBS=" -pthread"
		else
		    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how to find pthread lib on your system - you must edit the LIBS in the Makefile..." >&5
$as_echo "$as_me: WARNING: Don't know how to find pthread lib on your system - you must edit the LIBS in the Makefile..." >&2;}
		    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how to find pthread lib on your system - you must edit the LIBS in the Makefile..." >&5
printf "%s\n" "$as_me: WARNING: Don't know how to find pthread lib on your system - you must edit the LIBS in the Makefile..." >&2;}
		fi
	    fi
	fi
    fi

    # Does the pthread-implementation provide
    # 'pthread_attr_setstacksize' ?

    ac_saved_libs=$LIBS
    LIBS="$LIBS $THREADS_LIBS"
    ac_fn_c_check_func "$LINENO" "pthread_attr_setstacksize" "ac_cv_func_pthread_attr_setstacksize"
    for ac_func in pthread_attr_setstacksize pthread_atfork
do :
  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
  cat >>confdefs.h <<_ACEOF
if test "x$ac_cv_func_pthread_attr_setstacksize" = xyes
then :
  printf "%s\n" "#define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1" >>confdefs.h

fi
ac_fn_c_check_func "$LINENO" "pthread_atfork" "ac_cv_func_pthread_atfork"
if test "x$ac_cv_func_pthread_atfork" = xyes
then :
  printf "%s\n" "#define HAVE_PTHREAD_ATFORK 1" >>confdefs.h
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF

fi
done

    LIBS=$ac_saved_libs

    # TIP #509
    ac_fn_c_check_decl "$LINENO" "PTHREAD_MUTEX_RECURSIVE" "ac_cv_have_decl_PTHREAD_MUTEX_RECURSIVE" "#include <pthread.h>
"
if test "x$ac_cv_have_decl_PTHREAD_MUTEX_RECURSIVE" = xyes; then :
    ac_fn_check_decl "$LINENO" "PTHREAD_MUTEX_RECURSIVE" "ac_cv_have_decl_PTHREAD_MUTEX_RECURSIVE" "#include <pthread.h>
" "$ac_c_undeclared_builtin_options" "CFLAGS"
if test "x$ac_cv_have_decl_PTHREAD_MUTEX_RECURSIVE" = xyes
then :
  ac_have_decl=1
else
  ac_have_decl=0
else case e in #(
  e) ac_have_decl=0 ;;
esac
fi

cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_PTHREAD_MUTEX_RECURSIVE $ac_have_decl
printf "%s\n" "#define HAVE_DECL_PTHREAD_MUTEX_RECURSIVE $ac_have_decl" >>confdefs.h
_ACEOF
if test $ac_have_decl = 1; then :
if test $ac_have_decl = 1
then :
  tcl_ok=yes
else
  tcl_ok=no
else case e in #(
  e) tcl_ok=no ;;
esac
fi



# Add the threads support libraries
LIBS="$LIBS$THREADS_LIBS"


    { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to build libraries" >&5
$as_echo_n "checking how to build libraries... " >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to build libraries" >&5
printf %s "checking how to build libraries... " >&6; }
    # Check whether --enable-shared was given.
if test "${enable_shared+set}" = set; then :
if test ${enable_shared+y}
then :
  enableval=$enable_shared; tcl_ok=$enableval
else
  tcl_ok=yes
else case e in #(
  e) tcl_ok=yes ;;
fi

esac

    if test "${enable_shared+set}" = set; then
	enableval="$enable_shared"
	tcl_ok=$enableval
    else
	tcl_ok=yes
    fi
fi

    if test "$tcl_ok" = "yes" ; then
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: shared" >&5
$as_echo "shared" >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: shared" >&5
printf "%s\n" "shared" >&6; }
	SHARED_BUILD=1
    else
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: static" >&5
$as_echo "static" >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: static" >&5
printf "%s\n" "static" >&6; }
	SHARED_BUILD=0

$as_echo "#define STATIC_BUILD 1" >>confdefs.h
printf "%s\n" "#define STATIC_BUILD 1" >>confdefs.h

    fi



#--------------------------------------------------------------------
# Look for a native installed tclsh binary (if available)
# If one cannot be found then use the binary we build (fails for
# cross compiling). This is used for NATIVE_TCLSH in Makefile.
#--------------------------------------------------------------------


    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tclsh" >&5
$as_echo_n "checking for tclsh... " >&6; }
    if ${ac_cv_path_tclsh+:} false; then :
  $as_echo_n "(cached) " >&6
else

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tclsh" >&5
printf %s "checking for tclsh... " >&6; }
    if test ${ac_cv_path_tclsh+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	search_path=`echo ${PATH} | sed -e 's/:/ /g'`
	for dir in $search_path ; do
	    for j in `ls -r $dir/tclsh[8-9]* 2> /dev/null` \
		    `ls -r $dir/tclsh* 2> /dev/null` ; do
		if test x"$ac_cv_path_tclsh" = x ; then
		    if test -f "$j" ; then
			ac_cv_path_tclsh=$j
			break
		    fi
		fi
	    done
	done

     ;;
esac
fi


    if test -f "$ac_cv_path_tclsh" ; then
	TCLSH_PROG="$ac_cv_path_tclsh"
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $TCLSH_PROG" >&5
$as_echo "$TCLSH_PROG" >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TCLSH_PROG" >&5
printf "%s\n" "$TCLSH_PROG" >&6; }
    else
	# It is not an error if an installed version of Tcl can't be located.
	TCLSH_PROG=""
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: No tclsh found on PATH" >&5
$as_echo "No tclsh found on PATH" >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: No tclsh found on PATH" >&5
printf "%s\n" "No tclsh found on PATH" >&6; }
    fi


if test "$TCLSH_PROG" = ""; then
  TCLSH_PROG='./${TCL_EXE}'
fi

#------------------------------------------------------------------------
#	Add stuff for zlib
#------------------------------------------------------------------------

zlib_ok=yes
ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
if test "x$ac_cv_header_zlib_h" = xyes; then :
ac_fn_c_check_header_compile "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
if test "x$ac_cv_header_zlib_h" = xyes
then :

  ac_fn_c_check_type "$LINENO" "gz_header" "ac_cv_type_gz_header" "#include <zlib.h>
"
if test "x$ac_cv_type_gz_header" = xyes; then :
if test "x$ac_cv_type_gz_header" = xyes
then :

else
  zlib_ok=no
else case e in #(
  e) zlib_ok=no ;;
esac
fi

else

  zlib_ok=no
else case e in #(
  e)
  zlib_ok=no ;;
esac
fi


if test $zlib_ok = yes; then :
if test $zlib_ok = yes
then :

  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing deflateSetHeader" >&5
$as_echo_n "checking for library containing deflateSetHeader... " >&6; }
if ${ac_cv_search_deflateSetHeader+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_func_search_save_LIBS=$LIBS
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing deflateSetHeader" >&5
printf %s "checking for library containing deflateSetHeader... " >&6; }
if test ${ac_cv_search_deflateSetHeader+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
   builtin and then its argument prototype would still apply.
   The 'extern "C"' is for builds by C++ compilers;
   although this is not generally supported in C code supporting it here
   has little cost and some practical benefit (sr 110532).  */
#ifdef __cplusplus
extern "C"
#endif
char deflateSetHeader ();
char deflateSetHeader (void);
int
main ()
main (void)
{
return deflateSetHeader ();
  ;
  return 0;
}
_ACEOF
for ac_lib in '' z; do
for ac_lib in '' z
do
  if test -z "$ac_lib"; then
    ac_res="none required"
  else
    ac_res=-l$ac_lib
    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
  fi
  if ac_fn_c_try_link "$LINENO"; then :
  if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_search_deflateSetHeader=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext
  if ${ac_cv_search_deflateSetHeader+:} false; then :
  if test ${ac_cv_search_deflateSetHeader+y}
then :
  break
fi
done
if ${ac_cv_search_deflateSetHeader+:} false; then :
if test ${ac_cv_search_deflateSetHeader+y}
then :

else
  ac_cv_search_deflateSetHeader=no
else case e in #(
  e) ac_cv_search_deflateSetHeader=no ;;
esac
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
LIBS=$ac_func_search_save_LIBS ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_deflateSetHeader" >&5
$as_echo "$ac_cv_search_deflateSetHeader" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_deflateSetHeader" >&5
printf "%s\n" "$ac_cv_search_deflateSetHeader" >&6; }
ac_res=$ac_cv_search_deflateSetHeader
if test "$ac_res" != no; then :
if test "$ac_res" != no
then :
  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"

else

else case e in #(
  e)
    zlib_ok=no

   ;;
esac
fi

fi
if test $zlib_ok = no; then :
if test $zlib_ok = no
then :

  ZLIB_OBJS=\${ZLIB_OBJS}

  ZLIB_SRCS=\${ZLIB_SRCS}

  ZLIB_INCLUDE=-I\${ZLIB_DIR}


fi
printf "%s\n" "#define TCL_WITH_INTERNAL_ZLIB 1" >>confdefs.h

$as_echo "#define HAVE_ZLIB 1" >>confdefs.h

fi

#------------------------------------------------------------------------
#	Add stuff for libtommath

libtommath_ok=yes

# Check whether --with-system-libtommath was given.
if test "${with_system_libtommath+set}" = set; then :
if test ${with_system_libtommath+y}
then :
  withval=$with_system_libtommath; libtommath_ok=${withval}
fi

if test x"${libtommath_ok}" = x -o x"${libtommath_ok}" != xno; then
    ac_fn_c_check_header_mongrel "$LINENO" "tommath.h" "ac_cv_header_tommath_h" "$ac_includes_default"
if test "x$ac_cv_header_tommath_h" = xyes; then :
    ac_fn_c_check_header_compile "$LINENO" "tommath.h" "ac_cv_header_tommath_h" "$ac_includes_default"
if test "x$ac_cv_header_tommath_h" = xyes
then :

	ac_fn_c_check_type "$LINENO" "mp_int" "ac_cv_type_mp_int" "#include <tommath.h>
"
if test "x$ac_cv_type_mp_int" = xyes; then :
if test "x$ac_cv_type_mp_int" = xyes
then :

else
  libtommath_ok=no
else case e in #(
  e) libtommath_ok=no ;;
esac
fi

else

	libtommath_ok=no
else case e in #(
  e)
	libtommath_ok=no ;;
esac
fi


    if test $libtommath_ok = yes; then :
    if test $libtommath_ok = yes
then :

	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for mp_log_u32 in -ltommath" >&5
$as_echo_n "checking for mp_log_u32 in -ltommath... " >&6; }
if ${ac_cv_lib_tommath_mp_log_u32+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_check_lib_save_LIBS=$LIBS
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mp_log_u32 in -ltommath" >&5
printf %s "checking for mp_log_u32 in -ltommath... " >&6; }
if test ${ac_cv_lib_tommath_mp_log_u32+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_check_lib_save_LIBS=$LIBS
LIBS="-ltommath  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
   builtin and then its argument prototype would still apply.
   The 'extern "C"' is for builds by C++ compilers;
   although this is not generally supported in C code supporting it here
   has little cost and some practical benefit (sr 110532).  */
#ifdef __cplusplus
extern "C"
#endif
char mp_log_u32 ();
char mp_log_u32 (void);
int
main ()
main (void)
{
return mp_log_u32 ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_tommath_mp_log_u32=yes
else
  ac_cv_lib_tommath_mp_log_u32=no
else case e in #(
  e) ac_cv_lib_tommath_mp_log_u32=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tommath_mp_log_u32" >&5
$as_echo "$ac_cv_lib_tommath_mp_log_u32" >&6; }
if test "x$ac_cv_lib_tommath_mp_log_u32" = xyes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tommath_mp_log_u32" >&5
printf "%s\n" "$ac_cv_lib_tommath_mp_log_u32" >&6; }
if test "x$ac_cv_lib_tommath_mp_log_u32" = xyes
then :
  MATH_LIBS="$MATH_LIBS -ltommath"
else

    libtommath_ok=no
else case e in #(
  e)
    libtommath_ok=no ;;
esac
fi

fi
fi
if test $libtommath_ok = yes; then :
if test $libtommath_ok = yes
then :

  TCL_PC_REQUIRES_PRIVATE='libtommath >= 1.2.0,'

$as_echo "#define TCL_WITH_EXTERNAL_TOMMATH 1" >>confdefs.h
  TCL_PC_CFLAGS='-DTCL_WITH_EXTERNAL_TOMMATH'


printf "%s\n" "#define TCL_WITH_EXTERNAL_TOMMATH 1" >>confdefs.h
else


else case e in #(
  e)
  TOMMATH_OBJS=\${TOMMATH_OBJS}

  TOMMATH_SRCS=\${TOMMATH_SRCS}

  TOMMATH_INCLUDE=-I\${TOMMATH_DIR}


 ;;
esac
fi

#--------------------------------------------------------------------
# The statements below define a collection of compile flags.  This
# macro depends on the value of SHARED_BUILD, and should be called
# after SC_ENABLE_SHARED checks the configure switches.
#--------------------------------------------------------------------

if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
set dummy ${ac_tool_prefix}ranlib; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_RANLIB+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$RANLIB"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_RANLIB+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$RANLIB"; then
  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
$as_echo "$RANLIB" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
printf "%s\n" "$RANLIB" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


fi
if test -z "$ac_cv_prog_RANLIB"; then
  ac_ct_RANLIB=$RANLIB
  # Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$ac_ct_RANLIB"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_RANLIB+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$ac_ct_RANLIB"; then
  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_RANLIB="ranlib"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
if test -n "$ac_ct_RANLIB"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
$as_echo "$ac_ct_RANLIB" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
printf "%s\n" "$ac_ct_RANLIB" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi

  if test "x$ac_ct_RANLIB" = x; then
    RANLIB=":"
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
    RANLIB=$ac_ct_RANLIB
  fi
else
  RANLIB="$ac_cv_prog_RANLIB"
fi



    # Step 0.a: Enable 64 bit support?

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested" >&5
$as_echo_n "checking if 64bit support is requested... " >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested" >&5
printf %s "checking if 64bit support is requested... " >&6; }
    # Check whether --enable-64bit was given.
if test "${enable_64bit+set}" = set; then :
if test ${enable_64bit+y}
then :
  enableval=$enable_64bit; do64bit=$enableval
else
  do64bit=no
else case e in #(
  e) do64bit=no ;;
esac
fi

    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5
$as_echo "$do64bit" >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5
printf "%s\n" "$do64bit" >&6; }

    # Step 0.b: Enable Solaris 64 bit VIS support?

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit Sparc VIS support is requested" >&5
$as_echo_n "checking if 64bit Sparc VIS support is requested... " >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if 64bit Sparc VIS support is requested" >&5
printf %s "checking if 64bit Sparc VIS support is requested... " >&6; }
    # Check whether --enable-64bit-vis was given.
if test "${enable_64bit_vis+set}" = set; then :
if test ${enable_64bit_vis+y}
then :
  enableval=$enable_64bit_vis; do64bitVIS=$enableval
else
  do64bitVIS=no
else case e in #(
  e) do64bitVIS=no ;;
esac
fi

    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bitVIS" >&5
$as_echo "$do64bitVIS" >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $do64bitVIS" >&5
printf "%s\n" "$do64bitVIS" >&6; }
    # Force 64bit on with VIS
    if test "$do64bitVIS" = "yes"; then :
    if test "$do64bitVIS" = "yes"
then :
  do64bit=yes
fi

    # Step 0.c: Check if visibility support is available. Do this here so
    # that platform specific alternatives can be used below if this fails.

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports visibility \"hidden\"" >&5
$as_echo_n "checking if compiler supports visibility \"hidden\"... " >&6; }
if ${tcl_cv_cc_visibility_hidden+:} false; then :
  $as_echo_n "(cached) " >&6
else

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports visibility \"hidden\"" >&5
printf %s "checking if compiler supports visibility \"hidden\"... " >&6; }
if test ${tcl_cv_cc_visibility_hidden+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	    extern __attribute__((__visibility__("hidden"))) void f(void);
	    void f(void) {}
int
main ()
main (void)
{
f();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_cc_visibility_hidden=yes
else
  tcl_cv_cc_visibility_hidden=no
else case e in #(
  e) tcl_cv_cc_visibility_hidden=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
	CFLAGS=$hold_cflags
	CFLAGS=$hold_cflags ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_visibility_hidden" >&5
$as_echo "$tcl_cv_cc_visibility_hidden" >&6; }
    if test $tcl_cv_cc_visibility_hidden = yes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_visibility_hidden" >&5
printf "%s\n" "$tcl_cv_cc_visibility_hidden" >&6; }
    if test $tcl_cv_cc_visibility_hidden = yes
then :


$as_echo "#define MODULE_SCOPE extern __attribute__((__visibility__(\"hidden\")))" >>confdefs.h
printf "%s\n" "#define MODULE_SCOPE extern __attribute__((__visibility__(\"hidden\")))" >>confdefs.h


$as_echo "#define HAVE_HIDDEN 1" >>confdefs.h
printf "%s\n" "#define HAVE_HIDDEN 1" >>confdefs.h


fi

    # Step 0.d: Disable -rpath support?

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if rpath support is requested" >&5
$as_echo_n "checking if rpath support is requested... " >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if rpath support is requested" >&5
printf %s "checking if rpath support is requested... " >&6; }
    # Check whether --enable-rpath was given.
if test "${enable_rpath+set}" = set; then :
if test ${enable_rpath+y}
then :
  enableval=$enable_rpath; doRpath=$enableval
else
  doRpath=yes
else case e in #(
  e) doRpath=yes ;;
esac
fi

    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doRpath" >&5
$as_echo "$doRpath" >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $doRpath" >&5
printf "%s\n" "$doRpath" >&6; }

    # Step 1: set the variable "system" to hold the name and version number
    # for the system.


    { $as_echo "$as_me:${as_lineno-$LINENO}: checking system version" >&5
$as_echo_n "checking system version... " >&6; }
if ${tcl_cv_sys_version+:} false; then :
  $as_echo_n "(cached) " >&6
else

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking system version" >&5
printf %s "checking system version... " >&6; }
if test ${tcl_cv_sys_version+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	if test "${TEA_PLATFORM}" = "windows" ; then
	    tcl_cv_sys_version=windows
	else
	    tcl_cv_sys_version=`uname -s`-`uname -r`
	    if test "$?" -ne 0 ; then
		{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5
$as_echo "$as_me: WARNING: can't find uname command" >&2;}
		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5
printf "%s\n" "$as_me: WARNING: can't find uname command" >&2;}
		tcl_cv_sys_version=unknown
	    else
		if test "`uname -s`" = "AIX" ; then
		    tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
		fi
		if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then
		    tcl_cv_sys_version=NetBSD-Debian
		fi
	    fi
	fi

     ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5
$as_echo "$tcl_cv_sys_version" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5
printf "%s\n" "$tcl_cv_sys_version" >&6; }
    system=$tcl_cv_sys_version


    # Step 2: check for existence of -ldl library.  This is needed because
    # Linux can use either -ldl or -ldld for dynamic loading.

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
$as_echo_n "checking for dlopen in -ldl... " >&6; }
if ${ac_cv_lib_dl_dlopen+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_check_lib_save_LIBS=$LIBS
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
printf %s "checking for dlopen in -ldl... " >&6; }
if test ${ac_cv_lib_dl_dlopen+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_check_lib_save_LIBS=$LIBS
LIBS="-ldl  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
   builtin and then its argument prototype would still apply.
   The 'extern "C"' is for builds by C++ compilers;
   although this is not generally supported in C code supporting it here
   has little cost and some practical benefit (sr 110532).  */
#ifdef __cplusplus
extern "C"
#endif
char dlopen ();
char dlopen (void);
int
main ()
main (void)
{
return dlopen ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_dl_dlopen=yes
else
  ac_cv_lib_dl_dlopen=no
else case e in #(
  e) ac_cv_lib_dl_dlopen=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; }
if test "x$ac_cv_lib_dl_dlopen" = xyes
then :
  have_dl=yes
else
  have_dl=no
else case e in #(
  e) have_dl=no ;;
esac
fi


    # Require ranlib early so we can override it in special cases below.



5029
5030
5031
5032
5033
5034
5035
5036


5037
5038
5039
5040
5041
5042
5043
5044

5045
5046
5047
5048
5049
5050


5051
5052
5053


5054
5055
5056
5057
5058
5059
5060
5061
5062
5063







5064
5065
5066
5067
5068
5069

5070




5071
5072

5073
5074

5075
5076
5077
5078
5079
5080
5081


5082
5083
5084
5085
5086


5087
5088
5089


5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103







5104
5105
5106
5107
5108
5109

5110




5111
5112

5113
5114

5115
5116
5117
5118
5119
5120
5121


5122
5123
5124
5125
5126


5127
5128
5129


5130
5131
5132
5133
5134
5135
5136
5137
5138


5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152


5153
5154
5155
5156
5157


5158
5159
5160
5161
5162
5163
5164
5165
5166

5167
5168
5169
5170


5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185


5186
5187


5188
5189
5190


5191
5192
5193


5194
5195
5196
5197
5198
5199
5200


5201
5202
5203
5204
5205


5206
5207
5208
5209
5210
5211


5212
5213
5214
5215
5216


5217
5218


5219
5220
5221
5222
5223
5224




5225
5226
5227
5228
5229


5230
5231
5232


5233
5234
5235
5236
5237
5238


5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258







5259
5260
5261
5262
5263
5264
5265




5266
5267
5268
5269

5270
5271

5272
5273
5274
5275
5276
5277
5278


5279
5280
5281



5282
5283

5284
5285


5286
5287
5288
5289




5290
5291
5292
5293
5294
5295
5296
5634
5635
5636
5637
5638
5639
5640

5641
5642
5643
5644
5645
5646
5647
5648
5649

5650
5651
5652
5653
5654


5655
5656
5657
5658

5659
5660
5661
5662
5663
5664






5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678

5679
5680
5681
5682
5683

5684
5685

5686
5687
5688
5689
5690
5691
5692

5693
5694
5695
5696
5697


5698
5699
5700


5701
5702
5703
5704
5705
5706
5707
5708
5709
5710






5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724

5725
5726
5727
5728
5729

5730
5731

5732
5733
5734
5735
5736
5737
5738

5739
5740
5741
5742
5743


5744
5745
5746


5747
5748
5749
5750
5751
5752
5753
5754
5755


5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770

5771
5772
5773
5774
5775
5776

5777
5778
5779
5780
5781
5782
5783
5784
5785
5786

5787
5788
5789


5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805

5806
5807
5808

5809
5810
5811


5812
5813
5814


5815
5816
5817
5818
5819
5820
5821
5822

5823
5824
5825
5826
5827
5828

5829
5830
5831
5832
5833
5834
5835

5836
5837
5838
5839
5840


5841
5842
5843

5844
5845
5846
5847
5848



5849
5850
5851
5852
5853
5854
5855


5856
5857
5858
5859

5860
5861
5862
5863
5864
5865
5866

5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882






5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895

5896
5897
5898
5899
5900
5901
5902

5903
5904

5905
5906
5907
5908
5909
5910
5911

5912
5913
5914


5915
5916
5917
5918

5919
5920

5921
5922
5923



5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934







-
+
+







-
+




-
-
+
+


-
+
+




-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+








-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+







-
-
+
+













-
+
+




-
+
+








-
+


-
-
+
+














-
+
+

-
+
+

-
-
+
+

-
-
+
+






-
+
+




-
+
+





-
+
+



-
-
+
+

-
+
+



-
-
-
+
+
+
+



-
-
+
+


-
+
+





-
+
+














-
-
-
-
-
-
+
+
+
+
+
+
+






-
+
+
+
+



-
+

-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+







    # is disabled by the user. [Bug 1016796]
    LDFLAGS_ARCH=""
    UNSHARED_LIB_SUFFIX=""
    TCL_TRIM_DOTS='`echo ${VERSION} | tr -d .`'
    ECHO_VERSION='`echo ${VERSION}`'
    TCL_LIB_VERSIONS_OK=ok
    CFLAGS_DEBUG=-g
    if test "$GCC" = yes; then :
    if test "$GCC" = yes
then :

	CFLAGS_OPTIMIZE=-O2
	CFLAGS_WARNING="-Wall -Wextra -Wshadow -Wundef -Wwrite-strings -Wpointer-arith"
	case "${CC}" in
	    *++|*++-*)
		;;
	    *)
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wc++-compat -Wdeclaration-after-statement"
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wc++-compat -fextended-identifiers"
		;;
	esac


else

else case e in #(
  e)
	CFLAGS_OPTIMIZE=-O
	CFLAGS_WARNING=""

     ;;
esac
fi
    if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
set dummy ${ac_tool_prefix}ar; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_AR+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$AR"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_AR+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$AR"; then
  ac_cv_prog_AR="$AR" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_AR="${ac_tool_prefix}ar"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
AR=$ac_cv_prog_AR
if test -n "$AR"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
$as_echo "$AR" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
printf "%s\n" "$AR" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


fi
if test -z "$ac_cv_prog_AR"; then
  ac_ct_AR=$AR
  # Extract the first word of "ar", so it can be a program name with args.
set dummy ar; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_ac_ct_AR+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$ac_ct_AR"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_AR+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$ac_ct_AR"; then
  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_AR="ar"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
ac_ct_AR=$ac_cv_prog_ac_ct_AR
if test -n "$ac_ct_AR"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
$as_echo "$ac_ct_AR" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
printf "%s\n" "$ac_ct_AR" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi

  if test "x$ac_ct_AR" = x; then
    AR=""
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
    AR=$ac_ct_AR
  fi
else
  AR="$ac_cv_prog_AR"
fi

    STLIB_LD='${AR} cr'
    LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
    PLAT_OBJS=""
    PLAT_SRCS=""
    LDAIX_SRC=""
    if test "x${SHLIB_VERSION}" = x; then :
    if test "x${SHLIB_VERSION}" = x
then :
  SHLIB_VERSION="1.0"
fi
    case $system in
	AIX-*)
	    if test "$GCC" != "yes"; then :
	    if test "$GCC" != "yes"
then :

		# AIX requires the _r compiler when gcc isn't being used
		case "${CC}" in
		    *_r|*_r\ *)
			# ok ...
			;;
		    *)
			# Make sure only first arg gets _r
		    	CC=`echo "$CC" | sed -e 's/^\([^ ]*\)/\1_r/'`
			CC=`echo "$CC" | sed -e 's/^\([^ ]*\)/\1_r/'`
			;;
		esac
		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Using $CC for compiling with threads" >&5
$as_echo "Using $CC for compiling with threads" >&6; }
		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Using $CC for compiling with threads" >&5
printf "%s\n" "Using $CC for compiling with threads" >&6; }

fi
	    LIBS="$LIBS -lc"
	    SHLIB_CFLAGS=""
	    SHLIB_SUFFIX=".so"

	    DL_OBJS="tclLoadDl.o"
	    LD_LIBRARY_PATH_VAR="LIBPATH"

	    # ldAix No longer needed with use of -bexpall/-brtl
	    # but some extensions may still reference it
	    LDAIX_SRC='$(UNIX_DIR)/ldAix'

	    # Check to enable 64-bit flags for compiler/linker
	    if test "$do64bit" = yes; then :
	    if test "$do64bit" = yes
then :

		if test "$GCC" = yes; then :
		if test "$GCC" = yes
then :

		    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5
$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;}
		    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5
printf "%s\n" "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;}

else

else case e in #(
  e)
		    do64bit_ok=yes
		    CFLAGS="$CFLAGS -q64"
		    LDFLAGS_ARCH="-q64"
		    RANLIB="${RANLIB} -X64"
		    AR="${AR} -X64"
		    SHLIB_LD_FLAGS="-b64"

		 ;;
esac
fi

fi

	    if test "`uname -m`" = ia64; then :
	    if test "`uname -m`" = ia64
then :

		# AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC
		SHLIB_LD="/usr/ccs/bin/ld -G -z text"
		# AIX-5 has dl* in libc.so
		DL_LIBS=""
		if test "$GCC" = yes; then :
		if test "$GCC" = yes
then :

		    CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'

else

else case e in #(
  e)
		    CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}'

		 ;;
esac
fi
		LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'

else

		if test "$GCC" = yes; then :
else case e in #(
  e)
		if test "$GCC" = yes
then :

		    SHLIB_LD='${CC} -shared -Wl,-bexpall'

else

else case e in #(
  e)
		    SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry"
		    LDFLAGS="$LDFLAGS -brtl"

		 ;;
esac
fi
		SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}"
		DL_LIBS="-ldl"
		CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}

	     ;;
esac
fi
	    ;;
	BeOS*)
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD='${CC} -nostart'
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"

	    #-----------------------------------------------------------
	    # Check for inet_ntoa in -lbind, for BeOS (which also needs
	    # -lsocket, even if the network functions are in -lnet which
	    # is always linked to, for compatibility.
	    #-----------------------------------------------------------
	    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lbind" >&5
$as_echo_n "checking for inet_ntoa in -lbind... " >&6; }
if ${ac_cv_lib_bind_inet_ntoa+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_check_lib_save_LIBS=$LIBS
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lbind" >&5
printf %s "checking for inet_ntoa in -lbind... " >&6; }
if test ${ac_cv_lib_bind_inet_ntoa+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lbind  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
   builtin and then its argument prototype would still apply.
   The 'extern "C"' is for builds by C++ compilers;
   although this is not generally supported in C code supporting it here
   has little cost and some practical benefit (sr 110532).  */
#ifdef __cplusplus
extern "C"
#endif
char inet_ntoa ();
char inet_ntoa (void);
int
main ()
main (void)
{
return inet_ntoa ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_bind_inet_ntoa=yes
else
  ac_cv_lib_bind_inet_ntoa=no
else case e in #(
  e) ac_cv_lib_bind_inet_ntoa=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bind_inet_ntoa" >&5
$as_echo "$ac_cv_lib_bind_inet_ntoa" >&6; }
if test "x$ac_cv_lib_bind_inet_ntoa" = xyes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bind_inet_ntoa" >&5
printf "%s\n" "$ac_cv_lib_bind_inet_ntoa" >&6; }
if test "x$ac_cv_lib_bind_inet_ntoa" = xyes
then :
  LIBS="$LIBS -lbind -lsocket"
fi

	    ;;
	BSD/OS-2.1*|BSD/OS-3*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD="shlicc -r"
5306
5307
5308
5309
5310
5311
5312
5313

5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331







5332
5333
5334
5335
5336
5337
5338
5339

5340
5341
5342
5343
5344
5345
5346


5347
5348
5349



5350
5351
5352



5353
5354
5355


5356
5357
5358
5359
5360
5361

5362
5363

5364
5365
5366
5367
5368
5369
5370
5944
5945
5946
5947
5948
5949
5950

5951
5952
5953
5954
5955
5956
5957
5958
5959
5960









5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974

5975
5976
5977
5978
5979
5980
5981

5982
5983
5984


5985
5986
5987
5988


5989
5990
5991
5992


5993
5994
5995
5996
5997
5998
5999

6000
6001

6002
6003
6004
6005
6006
6007
6008
6009







-
+









-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+







-
+






-
+
+

-
-
+
+
+

-
-
+
+
+

-
-
+
+





-
+

-
+







	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	CYGWIN_*)
	CYGWIN_*|MINGW32_*|MSYS_*)
	    SHLIB_CFLAGS="-fno-common"
	    SHLIB_LD='${CC} -shared'
	    SHLIB_SUFFIX=".dll"
	    DL_OBJS="tclLoadDl.o"
	    PLAT_OBJS='${CYGWIN_OBJS}'
	    PLAT_SRCS='${CYGWIN_SRCS}'
	    DL_LIBS="-ldl"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    TCL_NEEDS_EXP_FILE=1
	    TCL_EXPORT_FILE_SUFFIX='${VERSION}.dll.a'
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$@.a"
	    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Cygwin version of gcc" >&5
$as_echo_n "checking for Cygwin version of gcc... " >&6; }
if ${ac_cv_cygwin+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Cygwin version of gcc" >&5
printf %s "checking for Cygwin version of gcc... " >&6; }
if test ${ac_cv_cygwin+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

		#ifdef __CYGWIN__
		    #error cygwin
		#endif

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_cygwin=no
else
  ac_cv_cygwin=yes
else case e in #(
  e) ac_cv_cygwin=yes ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
	     ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cygwin" >&5
$as_echo "$ac_cv_cygwin" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cygwin" >&5
printf "%s\n" "$ac_cv_cygwin" >&6; }
	    if test "$ac_cv_cygwin" = "no"; then
		as_fn_error $? "${CC} is not a cygwin compiler." "$LINENO" 5
	    fi
	    do64bit_ok=yes
	    if test "x${SHARED_BUILD}" = "x1"; then
		echo "running cd ../win; ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args"
		echo "running cd ../win; ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args --enable-64bit --host=x86_64-w64-mingw32"
		# The eval makes quoting arguments work.
		if cd ../win; eval ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args; cd ../unix
		if cd ../win; eval ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args --enable-64bit --host=x86_64-w64-mingw32; cd ../unix
		then :
		else
		    { echo "configure: error: configure failed for ../win" 1>&2; exit 1; }
		fi
	    fi
	    ;;
	dgux*)
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392







5393
5394
5395
5396
5397
5398
5399




5400
5401
5402
5403

5404
5405

5406
5407
5408
5409
5410
5411
5412


5413
5414
5415



5416
5417

5418
5419


5420
5421
5422
5423




5424
5425
5426
5427
5428
5429
5430
5431

5432
5433
5434

5435
5436
5437
5438


5439
5440
5441
5442
5443


5444
5445


5446
5447
5448
5449
5450
5451
5452







5453
5454
5455
5456
5457
5458
5459




5460
5461
5462
5463

5464
5465

5466
5467
5468
5469
5470
5471
5472


5473
5474
5475



5476
5477

5478
5479


5480
5481
5482
5483




5484
5485
5486



5487
5488
5489


5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501


5502
5503
5504
5505
5506
5507


5508
5509


5510
5511
5512
5513
5514
5515
5516


5517
5518


5519
5520
5521
5522
5523
5524
5525


5526
5527
5528
5529
5530
5531
5532
5533


5534
5535
5536
5537
5538


5539
5540
5541
5542


5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553







5554
5555
5556
5557
5558
5559
5560




5561
5562
5563
5564

5565
5566

5567
5568
5569
5570
5571
5572
5573


5574
5575
5576



5577
5578

5579
5580


5581
5582
5583
5584




5585
5586
5587



5588
5589
5590


5591
5592
5593
5594
5595
5596
5597
6019
6020
6021
6022
6023
6024
6025






6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038

6039
6040
6041
6042
6043
6044
6045

6046
6047

6048
6049
6050
6051
6052
6053
6054

6055
6056
6057


6058
6059
6060
6061

6062
6063

6064
6065
6066



6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077

6078
6079
6080

6081
6082
6083
6084

6085
6086
6087
6088
6089


6090
6091
6092

6093
6094
6095






6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108

6109
6110
6111
6112
6113
6114
6115

6116
6117

6118
6119
6120
6121
6122
6123
6124

6125
6126
6127


6128
6129
6130
6131

6132
6133

6134
6135
6136



6137
6138
6139
6140
6141


6142
6143
6144
6145
6146

6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159

6160
6161
6162
6163
6164
6165


6166
6167
6168

6169
6170
6171
6172
6173
6174
6175
6176

6177
6178
6179

6180
6181
6182
6183
6184
6185
6186
6187

6188
6189
6190
6191
6192
6193
6194
6195


6196
6197
6198
6199
6200


6201
6202
6203
6204
6205

6206
6207
6208
6209
6210
6211
6212






6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225

6226
6227
6228
6229
6230
6231
6232

6233
6234

6235
6236
6237
6238
6239
6240
6241

6242
6243
6244


6245
6246
6247
6248

6249
6250

6251
6252
6253



6254
6255
6256
6257
6258


6259
6260
6261
6262
6263

6264
6265
6266
6267
6268
6269
6270
6271
6272







-
-
-
-
-
-
+
+
+
+
+
+
+






-
+
+
+
+



-
+

-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+







-
+


-
+



-
+
+



-
-
+
+

-
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+






-
+
+
+
+



-
+

-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+

-
-
+
+
+


-
+
+











-
+
+




-
-
+
+

-
+
+






-
+
+

-
+
+






-
+
+






-
-
+
+



-
-
+
+



-
+
+





-
-
-
-
-
-
+
+
+
+
+
+
+






-
+
+
+
+



-
+

-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+

-
-
+
+
+


-
+
+







	Haiku*)
	    LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_SUFFIX=".so"
	    SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared'
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-lroot"
	    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lnetwork" >&5
$as_echo_n "checking for inet_ntoa in -lnetwork... " >&6; }
if ${ac_cv_lib_network_inet_ntoa+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_check_lib_save_LIBS=$LIBS
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lnetwork" >&5
printf %s "checking for inet_ntoa in -lnetwork... " >&6; }
if test ${ac_cv_lib_network_inet_ntoa+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lnetwork  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
   builtin and then its argument prototype would still apply.
   The 'extern "C"' is for builds by C++ compilers;
   although this is not generally supported in C code supporting it here
   has little cost and some practical benefit (sr 110532).  */
#ifdef __cplusplus
extern "C"
#endif
char inet_ntoa ();
char inet_ntoa (void);
int
main ()
main (void)
{
return inet_ntoa ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_network_inet_ntoa=yes
else
  ac_cv_lib_network_inet_ntoa=no
else case e in #(
  e) ac_cv_lib_network_inet_ntoa=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_inet_ntoa" >&5
$as_echo "$ac_cv_lib_network_inet_ntoa" >&6; }
if test "x$ac_cv_lib_network_inet_ntoa" = xyes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_inet_ntoa" >&5
printf "%s\n" "$ac_cv_lib_network_inet_ntoa" >&6; }
if test "x$ac_cv_lib_network_inet_ntoa" = xyes
then :
  LIBS="$LIBS -lnetwork"
fi

	    ;;
	HP-UX-*.11.*)
	    # Use updated header definitions where possible

$as_echo "#define _XOPEN_SOURCE_EXTENDED 1" >>confdefs.h
printf "%s\n" "#define _XOPEN_SOURCE_EXTENDED 1" >>confdefs.h


$as_echo "#define _XOPEN_SOURCE 1" >>confdefs.h
printf "%s\n" "#define _XOPEN_SOURCE 1" >>confdefs.h

	    LIBS="$LIBS -lxnet"               # Use the XOPEN network library

	    if test "`uname -m`" = ia64; then :
	    if test "`uname -m`" = ia64
then :

		SHLIB_SUFFIX=".so"

else

else case e in #(
  e)
		SHLIB_SUFFIX=".sl"

	     ;;
esac
fi
	    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
$as_echo_n "checking for shl_load in -ldld... " >&6; }
if ${ac_cv_lib_dld_shl_load+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_check_lib_save_LIBS=$LIBS
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
printf %s "checking for shl_load in -ldld... " >&6; }
if test ${ac_cv_lib_dld_shl_load+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_check_lib_save_LIBS=$LIBS
LIBS="-ldld  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
   builtin and then its argument prototype would still apply.
   The 'extern "C"' is for builds by C++ compilers;
   although this is not generally supported in C code supporting it here
   has little cost and some practical benefit (sr 110532).  */
#ifdef __cplusplus
extern "C"
#endif
char shl_load ();
char shl_load (void);
int
main ()
main (void)
{
return shl_load ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_dld_shl_load=yes
else
  ac_cv_lib_dld_shl_load=no
else case e in #(
  e) ac_cv_lib_dld_shl_load=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
if test "x$ac_cv_lib_dld_shl_load" = xyes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
printf "%s\n" "$ac_cv_lib_dld_shl_load" >&6; }
if test "x$ac_cv_lib_dld_shl_load" = xyes
then :
  tcl_ok=yes
else
  tcl_ok=no
else case e in #(
  e) tcl_ok=no ;;
esac
fi

	    if test "$tcl_ok" = yes; then :
	    if test "$tcl_ok" = yes
then :

		SHLIB_CFLAGS="+z"
		SHLIB_LD="ld -b"
		DL_OBJS="tclLoadShl.o"
		DL_LIBS="-ldld"
		LDFLAGS="$LDFLAGS -Wl,-E"
		CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'
		LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'
		LD_LIBRARY_PATH_VAR="SHLIB_PATH"

fi
	    if test "$GCC" = yes; then :
	    if test "$GCC" = yes
then :

		SHLIB_LD='${CC} -shared'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}

else

else case e in #(
  e)
		CFLAGS="$CFLAGS -z"

	     ;;
esac
fi

	    # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc
	    #CFLAGS="$CFLAGS +DAportable"

	    # Check to enable 64-bit flags for compiler/linker
	    if test "$do64bit" = "yes"; then :
	    if test "$do64bit" = "yes"
then :

		if test "$GCC" = yes; then :
		if test "$GCC" = yes
then :

		    case `${CC} -dumpmachine` in
			hppa64*)
			    # 64-bit gcc in use.  Fix flags for GNU ld.
			    do64bit_ok=yes
			    SHLIB_LD='${CC} -shared'
			    if test $doRpath = yes; then :
			    if test $doRpath = yes
then :

				CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
fi
			    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
			    ;;
			*)
			    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5
$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;}
			    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5
printf "%s\n" "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;}
			    ;;
		    esac

else

else case e in #(
  e)
		    do64bit_ok=yes
		    CFLAGS="$CFLAGS +DD64"
		    LDFLAGS_ARCH="+DD64"

		 ;;
esac
fi

fi ;;
	HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*)
	    SHLIB_SUFFIX=".sl"
	    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
$as_echo_n "checking for shl_load in -ldld... " >&6; }
if ${ac_cv_lib_dld_shl_load+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_check_lib_save_LIBS=$LIBS
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
printf %s "checking for shl_load in -ldld... " >&6; }
if test ${ac_cv_lib_dld_shl_load+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_check_lib_save_LIBS=$LIBS
LIBS="-ldld  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
   builtin and then its argument prototype would still apply.
   The 'extern "C"' is for builds by C++ compilers;
   although this is not generally supported in C code supporting it here
   has little cost and some practical benefit (sr 110532).  */
#ifdef __cplusplus
extern "C"
#endif
char shl_load ();
char shl_load (void);
int
main ()
main (void)
{
return shl_load ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_dld_shl_load=yes
else
  ac_cv_lib_dld_shl_load=no
else case e in #(
  e) ac_cv_lib_dld_shl_load=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
if test "x$ac_cv_lib_dld_shl_load" = xyes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
printf "%s\n" "$ac_cv_lib_dld_shl_load" >&6; }
if test "x$ac_cv_lib_dld_shl_load" = xyes
then :
  tcl_ok=yes
else
  tcl_ok=no
else case e in #(
  e) tcl_ok=no ;;
esac
fi

	    if test "$tcl_ok" = yes; then :
	    if test "$tcl_ok" = yes
then :

		SHLIB_CFLAGS="+z"
		SHLIB_LD="ld -b"
		SHLIB_LD_LIBS=""
		DL_OBJS="tclLoadShl.o"
		DL_LIBS="-ldld"
		LDFLAGS="$LDFLAGS -Wl,-E"
5608
5609
5610
5611
5612
5613
5614
5615


5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633


5634
5635
5636
5637
5638


5639
5640
5641
5642
5643
5644


5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655


5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670


5671
5672
5673
5674
5675
5676
5677
5678


5679
5680


5681
5682
5683


5684
5685
5686
5687
5688
5689
5690
5691








5692
5693
5694
5695
5696

5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709










5710


5711
5712
5713
5714
5715


5716
5717
5718


5719
5720
5721
5722
5723
5724
5725







5726
5727
5728
5729
5730
5731
5732

5733
5734
5735
5736
5737
5738
5739


5740
5741
5742



5743
5744

5745
5746


5747
5748
5749
5750




5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765


5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777


5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797


5798
5799
5800
5801
5802
5803
5804
6283
6284
6285
6286
6287
6288
6289

6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308

6309
6310
6311
6312
6313
6314

6315
6316
6317
6318
6319
6320


6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332

6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348

6349
6350
6351
6352
6353
6354
6355
6356
6357

6358
6359
6360

6361
6362
6363


6364
6365
6366







6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378

6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402

6403
6404
6405
6406
6407
6408

6409
6410
6411
6412

6413
6414
6415






6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428

6429
6430
6431
6432
6433
6434
6435

6436
6437
6438


6439
6440
6441
6442

6443
6444

6445
6446
6447



6448
6449
6450
6451
6452
6453
6454
6455
6456
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
6502
6503
6504
6505
6506
6507
6508







-
+
+

















-
+
+




-
+
+




-
-
+
+










-
+
+














-
+
+







-
+
+

-
+
+

-
-
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+




-
+













+
+
+
+
+
+
+
+
+
+
-
+
+




-
+
+


-
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+






-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+














-
+
+











-
+
+



















-
+
+







	    DL_LIBS=""
	    case " $LIBOBJS " in
  *" mkstemp.$ac_objext "* ) ;;
  *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext"
 ;;
esac

	    if test $doRpath = yes; then :
	    if test $doRpath = yes
then :

		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
fi
	    ;;
	IRIX-6.*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD="ld -n32 -shared -rdata_shared"
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    case " $LIBOBJS " in
  *" mkstemp.$ac_objext "* ) ;;
  *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext"
 ;;
esac

	    if test $doRpath = yes; then :
	    if test $doRpath = yes
then :

		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
fi
	    if test "$GCC" = yes; then :
	    if test "$GCC" = yes
then :

		CFLAGS="$CFLAGS -mabi=n32"
		LDFLAGS="$LDFLAGS -mabi=n32"

else

else case e in #(
  e)
		case $system in
		    IRIX-6.3)
			# Use to build 6.2 compatible binaries on 6.3.
			CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS"
			;;
		    *)
			CFLAGS="$CFLAGS -n32"
			;;
		esac
		LDFLAGS="$LDFLAGS -n32"

	     ;;
esac
fi
	    ;;
	IRIX64-6.*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD="ld -n32 -shared -rdata_shared"
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    case " $LIBOBJS " in
  *" mkstemp.$ac_objext "* ) ;;
  *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext"
 ;;
esac

	    if test $doRpath = yes; then :
	    if test $doRpath = yes
then :

		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
fi

	    # Check to enable 64-bit flags for compiler/linker

	    if test "$do64bit" = yes; then :
	    if test "$do64bit" = yes
then :

	        if test "$GCC" = yes; then :
		if test "$GCC" = yes
then :

	            { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported by gcc" >&5
$as_echo "$as_me: WARNING: 64bit mode not supported by gcc" >&2;}
		    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported by gcc" >&5
printf "%s\n" "$as_me: WARNING: 64bit mode not supported by gcc" >&2;}

else

	            do64bit_ok=yes
	            SHLIB_LD="ld -64 -shared -rdata_shared"
	            CFLAGS="$CFLAGS -64"
	            LDFLAGS_ARCH="-64"

else case e in #(
  e)
		    do64bit_ok=yes
		    SHLIB_LD="ld -64 -shared -rdata_shared"
		    CFLAGS="$CFLAGS -64"
		    LDFLAGS_ARCH="-64"
		 ;;
esac
fi

fi
	    ;;
	Linux*|GNU*|NetBSD-Debian)
	Linux*|GNU*|NetBSD-Debian|DragonFly-*|FreeBSD-*)
	    SHLIB_CFLAGS="-fPIC -fno-common"
	    SHLIB_SUFFIX=".so"

	    CFLAGS_OPTIMIZE="-O2"
	    # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings
	    # when you inline the string and math operations.  Turn this off to
	    # get rid of the warnings.
	    #CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES"

	    SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared'
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    LDFLAGS="$LDFLAGS -Wl,--export-dynamic"

	    case $system in
	    DragonFly-*|FreeBSD-*)
		# The -pthread needs to go in the LDFLAGS, not LIBS
		LIBS=`echo $LIBS | sed s/-pthread//`
		CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
		LDFLAGS="$LDFLAGS $PTHREAD_LIBS"
	    ;;
	    esac

	    if test $doRpath = yes; then :
	    if test $doRpath = yes
then :

		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
fi
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    if test "`uname -m`" = "alpha"; then :
	    if test "`uname -m`" = "alpha"
then :
  CFLAGS="$CFLAGS -mieee"
fi
	    if test $do64bit = yes; then :
	    if test $do64bit = yes
then :

		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -m64 flag" >&5
$as_echo_n "checking if compiler accepts -m64 flag... " >&6; }
if ${tcl_cv_cc_m64+:} false; then :
  $as_echo_n "(cached) " >&6
else

		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -m64 flag" >&5
printf %s "checking if compiler accepts -m64 flag... " >&6; }
if test ${tcl_cv_cc_m64+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
		    hold_cflags=$CFLAGS
		    CFLAGS="$CFLAGS -m64"
		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_cc_m64=yes
else
  tcl_cv_cc_m64=no
else case e in #(
  e) tcl_cv_cc_m64=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
		    CFLAGS=$hold_cflags
		    CFLAGS=$hold_cflags ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_m64" >&5
$as_echo "$tcl_cv_cc_m64" >&6; }
		if test $tcl_cv_cc_m64 = yes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_m64" >&5
printf "%s\n" "$tcl_cv_cc_m64" >&6; }
		if test $tcl_cv_cc_m64 = yes
then :

		    CFLAGS="$CFLAGS -m64"
		    do64bit_ok=yes

fi

fi

	    # The combo of gcc + glibc has a bug related to inlining of
	    # functions like strtol()/strtoul(). The -fno-builtin flag should address
	    # this problem but it does not work. The -fno-inline flag is kind
	    # of overkill but it works. Disable inlining only when one of the
	    # files in compat/*.c is being linked in.

	    if test x"${USE_COMPAT}" != x; then :
	    if test x"${USE_COMPAT}" != x
then :
  CFLAGS="$CFLAGS -fno-inline"
fi
	    ;;
	Lynx*)
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_SUFFIX=".so"
	    CFLAGS_OPTIMIZE=-02
	    SHLIB_LD='${CC} -shared'
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-mshared -ldl"
	    LD_FLAGS="-Wl,--export-dynamic"
	    if test $doRpath = yes; then :
	    if test $doRpath = yes
then :

		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
fi
	    ;;
	OpenBSD-*)
	    arch=`arch -s`
	    case "$arch" in
	    alpha|sparc64)
		SHLIB_CFLAGS="-fPIC"
		;;
	    *)
		SHLIB_CFLAGS="-fpic"
		;;
	    esac
	    SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared'
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    if test $doRpath = yes; then :
	    if test $doRpath = yes
then :

		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
fi
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
	    LDFLAGS="-Wl,-export-dynamic"
	    CFLAGS_OPTIMIZE="-O2"
5814
5815
5816
5817
5818
5819
5820
5821


5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858

5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869


5870
5871
5872
5873
5874
5875
5876
5877











5878





































5879
5880

5881
5882
5883
5884
5885

5886
5887
5888
5889
5890
5891
5892
5893
5894
5895






5896
5897

5898
5899


5900
5901
5902
5903




5904
5905

5906
5907
5908
5909
5910
5911
5912
5913
5914
5915








5916
5917

5918
5919
5920
5921
5922

5923
5924
5925
5926
5927
5928
5929
5930
5931
5932






5933
5934

5935
5936


5937
5938
5939
5940




5941
5942

5943
5944
5945
5946
5947
5948


5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974

5975
5976
5977
5978
5979






5980
5981
5982

5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993

5994
5995

5996

5997
5998
5999
6000
6001
6002
6003
6004
6005
6006







6007
6008
6009
6010
6011
6012
6013

6014
6015
6016
6017
6018
6019
6020


6021
6022
6023



6024
6025

6026
6027


6028
6029
6030
6031




6032
6033
6034
6035
6036


6037
6038
6039

6040
6041
6042
6043
6044
6045
6046

6047
6048

6049
6050
6051
6052
6053


6054
6055


6056
6057
6058



6059
6060
6061
6062
6063




6064
6065
6066
6067
6068
6069
6070







6071
6072


6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087

6088
6089
6090
6091
6092
6093
6094


6095
6096
6097



6098
6099

6100
6101


6102
6103
6104
6105

6106
6107


6108
6109
6110
6111




6112
6113
6114
6115

6116
6117
6118
6119



6120
6121


6122
6123
6124
6125
6126
6127
6128







6129
6130
6131
6132
6133
6134
6135
6136

6137
6138
6139
6140
6141
6142
6143


6144
6145
6146



6147
6148

6149
6150
6151
6152


6153
6154
6155
6156




6157
6158
6159

6160
6161

6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173

6174
6175
6176
6177
6178
6179


6180
6181

6182
6183
6184
6185
6186





6187
6188
6189
6190
6191


6192
6193
6194
6195
6196


6197
6198
6199
6200




6201
6202
6203
6204
6205
6206


6207
6208
6209
6210
6211


6212
6213
6214


6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233


6234
6235
6236
6237
6238
6239


6240
6241
6242


6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259

6260
6261
6262

6263
6264
6265
6266
6267
6268
6269


6270
6271
6272
6273
6274
6275
6276


6277
6278
6279
6280


6281
6282
6283
6284
6285
6286
6287
6288

6289
6290
6291

6292
6293
6294
6295
6296
6297


6298
6299
6300


6301
6302


6303
6304


6305
6306
6307


6308
6309
6310


6311
6312
6313
6314
6315


6316
6317
6318
6319


6320
6321


6322
6323
6324
6325
6326
6327


6328
6329
6330


6331
6332
6333
6334


6335
6336
6337
6338



6339
6340


6341
6342
6343
6344
6345
6346
6347
6348
6349


6350
6351
6352
6353


6354
6355
6356
6357
6358
6359
6360
6361
6362
6363


6364
6365
6366
6367
6368
6369






6370
6371
6372
6373
6374
6375
6376
6377
6378


6379
6380
6381


6382
6383
6384
6385




6386
6387
6388


6389
6390
6391



6392
6393
6394
6395
6396
6397
6398
6399
6400
6401




6402
6403


6404
6405


6406
6407
6408
6409
6410


6411
6412
6413
6414
6415


6416
6417


6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428



6429
6430
6431
6432


6433
6434
6435
6436
6437
6438
6439




6440
6441
6442



6443
6444
6445
6446
6447
6448
6449
6450
6451
6452


6453
6454
6455
6456
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
6502
6503
6504


6505
6506
6507


6508
6509
6510
6511


6512
6513
6514

6515
6516
6517
6518
6519
6520
6521
6522
6523
6524


6525
6526
6527



6528
6529
6530


6531
6532
6533
6534


6535
6536
6537
6538
6539




6540
6541
6542
6543
6544
6545
6546
6547
6548
6549


6550
6551
6552
6553
6554
6555
6556
6557


6558
6559
6560
6561
6562
6563


6564
6565
6566
6567
6568

6569
6570
6571
6572
6573
6574


6575
6576
6577

6578
6579
6580
6581
6582


6583
6584
6585
6586


6587
6588
6589
6590
6591
6592


6593
6594
6595
6596




6597
6598
6599


6600
6601
6602
6603
6604





6605
6606
6607
6608
6609



6610
6611


6612
6613

6614
6615
6616
6617
6618





6619
6620
6621



6622
6623
6624
6625


6626
6627

6628
6629
6630
6631
6632





6633
6634
6635
6636
6637
6638
6639


6640
6641

6642
6643
6644
6645
6646
6647



6648
6649
6650
6651
6652
6653
6654







6655
6656
6657
6658

6659
6660
6661
6662


6663
6664
6665
6666
6667
6668


6669
6670
6671



6672
6673
6674



6675
6676
6677
6678






















































6679



6680
6681
6682





















6683
6684
6685



6686
6687

6688
6689
6690


























6691
6692
6693
6694
6695
6696
6697
6518
6519
6520
6521
6522
6523
6524

6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535


























6536

6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547

6548
6549
6550
6551
6552





6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602

6603
6604
6605
6606
6607

6608
6609
6610
6611
6612
6613
6614




6615
6616
6617
6618
6619
6620
6621

6622
6623

6624
6625
6626



6627
6628
6629
6630
6631

6632
6633
6634
6635







6636
6637
6638
6639
6640
6641
6642
6643
6644

6645
6646
6647
6648
6649

6650
6651
6652
6653
6654
6655
6656




6657
6658
6659
6660
6661
6662
6663

6664
6665

6666
6667
6668



6669
6670
6671
6672
6673

6674
6675
6676
6677
6678


6679
6680
6681






















6682


6683





6684
6685
6686
6687
6688
6689



6690


6691








6692


6693
6694
6695
6696
6697
6698
6699






6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712

6713
6714
6715
6716
6717
6718
6719

6720
6721
6722


6723
6724
6725
6726

6727
6728

6729
6730
6731



6732
6733
6734
6735
6736
6737
6738
6739

6740
6741
6742
6743

6744
6745
6746
6747
6748
6749
6750

6751
6752

6753
6754
6755
6756


6757
6758
6759

6760
6761
6762


6763
6764
6765
6766
6767



6768
6769
6770
6771
6772






6773
6774
6775
6776
6777
6778
6779
6780

6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796

6797
6798
6799
6800
6801
6802
6803

6804
6805
6806


6807
6808
6809
6810

6811
6812

6813
6814
6815
6816
6817

6818
6819

6820
6821
6822



6823
6824
6825
6826
6827
6828
6829

6830
6831
6832


6833
6834
6835
6836

6837
6838
6839






6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853

6854
6855
6856
6857
6858
6859
6860

6861
6862
6863


6864
6865
6866
6867

6868
6869
6870
6871

6872
6873
6874



6875
6876
6877
6878
6879
6880

6881
6882

6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894

6895
6896
6897
6898
6899
6900

6901
6902
6903

6904
6905




6906
6907
6908
6909
6910
6911
6912
6913
6914

6915
6916
6917
6918
6919
6920

6921
6922
6923



6924
6925
6926
6927
6928
6929
6930
6931
6932

6933
6934
6935
6936
6937


6938
6939
6940
6941

6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961

6962
6963
6964
6965
6966
6967


6968
6969
6970
6971

6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989

6990
6991
6992

6993
6994
6995
6996
6997
6998
6999

7000
7001
7002
7003
7004
7005
7006


7007
7008
7009
7010
7011

7012
7013
7014
7015
7016
7017
7018
7019
7020

7021
7022
7023

7024
7025
7026
7027
7028
7029

7030
7031
7032
7033

7034
7035
7036

7037
7038
7039

7040
7041
7042


7043
7044
7045


7046
7047
7048
7049
7050
7051

7052
7053
7054
7055


7056
7057
7058

7059
7060
7061
7062
7063
7064


7065
7066
7067
7068

7069
7070
7071
7072
7073

7074
7075
7076
7077


7078
7079
7080
7081

7082
7083
7084
7085
7086
7087
7088
7089
7090


7091
7092
7093
7094


7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105

7106
7107
7108
7109




7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123

7124
7125
7126


7127
7128
7129



7130
7131
7132
7133
7134


7135
7136
7137


7138
7139
7140
7141
7142

7143
7144
7145




7146
7147
7148
7149
7150

7151
7152
7153

7154
7155
7156
7157
7158
7159

7160
7161
7162
7163
7164
7165

7166
7167
7168

7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179


7180
7181
7182
7183
7184
7185

7186
7187
7188
7189
7190
7191



7192
7193
7194
7195
7196


7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208

7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221






7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234

7235
7236
7237
7238
7239
7240
7241

7242
7243
7244


7245
7246
7247
7248

7249
7250

7251
7252
7253



7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266

7267
7268
7269


7270
7271
7272
7273
7274

7275
7276
7277
7278

7279
7280
7281
7282
7283
7284
7285
7286
7287
7288

7289
7290
7291


7292
7293
7294
7295
7296

7297
7298
7299
7300
7301

7302
7303
7304




7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317

7318
7319
7320
7321
7322
7323
7324
7325
7326

7327
7328
7329
7330
7331
7332


7333
7334
7335
7336
7337
7338

7339
7340
7341
7342
7343
7344

7345
7346
7347
7348

7349
7350
7351
7352
7353

7354
7355
7356
7357
7358

7359
7360
7361
7362
7363
7364
7365

7366
7367
7368



7369
7370
7371
7372
7373


7374
7375
7376




7377
7378
7379
7380
7381
7382
7383



7384
7385
7386
7387

7388
7389
7390

7391
7392




7393
7394
7395
7396
7397
7398


7399
7400
7401
7402
7403
7404

7405
7406
7407

7408
7409




7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420

7421
7422
7423

7424
7425
7426
7427



7428
7429
7430
7431






7432
7433
7434
7435
7436
7437
7438
7439
7440
7441

7442
7443
7444


7445
7446
7447
7448
7449
7450
7451

7452
7453
7454


7455
7456
7457
7458


7459
7460
7461
7462



7463
7464
7465
7466
7467
7468
7469
7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499
7500
7501
7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520



7521
7522
7523
7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537
7538
7539
7540
7541
7542


7543
7544
7545
7546

7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581
7582
7583







-
+
+









-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
+










-
+
+



-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+




-
+






-
-
-
-
+
+
+
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+

-
+



-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
+




-
+






-
-
-
-
+
+
+
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+

-
+




-
-
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
+
-
-
-
-
-
+
+
+
+
+
+
-
-
-
+
-
-

-
-
-
-
-
-
-
-
+
-
-
+

+




-
-
-
-
-
-
+
+
+
+
+
+
+






-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+




-
+
+


-
+






-
+

-
+



-
-
+
+

-
+
+

-
-
+
+
+


-
-
-
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+

-
+
+














-
+






-
+
+

-
-
+
+
+

-
+

-
+
+



-
+

-
+
+

-
-
-
+
+
+
+



-
+


-
-
+
+
+

-
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+







-
+






-
+
+

-
-
+
+
+

-
+



-
+
+

-
-
-
+
+
+
+


-
+

-
+











-
+





-
+
+

-
+

-
-
-
-
+
+
+
+
+




-
+
+




-
+
+

-
-
-
+
+
+
+





-
+
+



-
-
+
+


-
+
+


















-
+
+




-
-
+
+


-
+
+
















-
+


-
+






-
+
+





-
-
+
+



-
+
+







-
+


-
+





-
+
+


-
+
+

-
+
+

-
+
+

-
-
+
+

-
-
+
+




-
+
+


-
-
+
+

-
+
+




-
-
+
+


-
+
+



-
+
+


-
-
+
+
+

-
+
+







-
-
+
+


-
-
+
+









-
+
+


-
-
-
-
+
+
+
+
+
+








-
+
+

-
-
+
+

-
-
-
+
+
+
+

-
-
+
+

-
-
+
+
+


-



-
-
-
-
+
+
+
+

-
+
+

-
+
+




-
+
+




-
+
+

-
+
+









-
-
+
+
+



-
+
+




-
-
-
+
+
+
+

-
-
+
+
+









-
+
+











-
-
-
-
-
-
+
+
+
+
+
+
+






-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+









-
+
+

-
-
+
+



-
+
+


-
+









-
+
+

-
-
+
+
+


-
+
+



-
+
+

-
-
-
-
+
+
+
+









-
+
+







-
+
+




-
-
+
+




-
+





-
+
+


-
+




-
+
+



-
+
+





-
+
+

-
-
-
+
+
+
+

-
-
+
+

-
-
-
-
+
+
+
+
+


-
-
-
+
+
+

-
+
+

-
+

-
-
-
-
+
+
+
+
+

-
-
+
+
+



-
+
+

-
+

-
-
-
-
+
+
+
+
+






-
+
+

-
+



-
-
-
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+



-
+


-
-
+
+





-
+
+

-
-
+
+
+

-
-
+
+
+

-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+

-
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    # NetBSD has ELF and can use 'cc -shared' to build shared libs
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared'
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    if test $doRpath = yes; then :
	    if test $doRpath = yes
then :

		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
fi
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    # The -pthread needs to go in the CFLAGS, not LIBS
	    LIBS=`echo $LIBS | sed s/-pthread//`
	    CFLAGS="$CFLAGS -pthread"
	    LDFLAGS="$LDFLAGS -pthread"
	    ;;
	DragonFly-*|FreeBSD-*)
	    # This configuration from FreeBSD Ports.
	    SHLIB_LD="${CC} -shared"
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$@"
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    if test $doRpath = yes; then :

		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
fi
	    # The -pthread needs to go in the LDFLAGS, not LIBS
	    LIBS=`echo $LIBS | sed s/-pthread//`
	    CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
	    LDFLAGS="$LDFLAGS $PTHREAD_LIBS"
	    case $system in
	    FreeBSD-3.*)
		# Version numbers are dot-stripped by system policy.
		TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .`
		UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
		TCL_LIB_VERSIONS_OK=nodots
		;;
	    esac
	    ;;
	Darwin-*)
	    CFLAGS_OPTIMIZE="-Os"
	    CFLAGS_OPTIMIZE="-O2"
	    SHLIB_CFLAGS="-fno-common"
	    # To avoid discrepancies between what headers configure sees during
	    # preprocessing tests and compiling tests, move any -isysroot and
	    # -mmacosx-version-min flags from CFLAGS to CPPFLAGS:
	    CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \
		awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
		if ($i~/^(isysroot|mmacosx-version-min)/) print "-"$i}'`"
	    CFLAGS="`echo " ${CFLAGS}" | \
		awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
		if (!($i~/^(isysroot|mmacosx-version-min)/)) print "-"$i}'`"
	    if test $do64bit = yes; then :
	    if test $do64bit = yes
then :

		case `arch` in
		    ppc)
			{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch ppc64 flag" >&5
$as_echo_n "checking if compiler accepts -arch ppc64 flag... " >&6; }
if ${tcl_cv_cc_arch_ppc64+:} false; then :
  $as_echo_n "(cached) " >&6
else
			{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch ppc64 flag" >&5
printf %s "checking if compiler accepts -arch ppc64 flag... " >&6; }
if test ${tcl_cv_cc_arch_ppc64+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
			    hold_cflags=$CFLAGS
			    CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
			    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_cc_arch_ppc64=yes
else case e in #(
  e) tcl_cv_cc_arch_ppc64=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
			    CFLAGS=$hold_cflags ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_ppc64" >&5
printf "%s\n" "$tcl_cv_cc_arch_ppc64" >&6; }
			if test $tcl_cv_cc_arch_ppc64 = yes
then :

			    CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
			    do64bit_ok=yes

fi;;
		    i386|x86_64)
			{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch x86_64 flag" >&5
printf %s "checking if compiler accepts -arch x86_64 flag... " >&6; }
if test ${tcl_cv_cc_arch_x86_64+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
			    hold_cflags=$CFLAGS
			    CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
			    CFLAGS="$CFLAGS -arch x86_64"
			    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
  tcl_cv_cc_arch_ppc64=yes
else
  tcl_cv_cc_arch_ppc64=no
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_cc_arch_x86_64=yes
else case e in #(
  e) tcl_cv_cc_arch_x86_64=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
			    CFLAGS=$hold_cflags
			    CFLAGS=$hold_cflags ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_ppc64" >&5
$as_echo "$tcl_cv_cc_arch_ppc64" >&6; }
			if test $tcl_cv_cc_arch_ppc64 = yes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_x86_64" >&5
printf "%s\n" "$tcl_cv_cc_arch_x86_64" >&6; }
			if test $tcl_cv_cc_arch_x86_64 = yes
then :

			    CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
			    CFLAGS="$CFLAGS -arch x86_64"
			    do64bit_ok=yes

fi;;
		    i386)
			{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch x86_64 flag" >&5
$as_echo_n "checking if compiler accepts -arch x86_64 flag... " >&6; }
if ${tcl_cv_cc_arch_x86_64+:} false; then :
  $as_echo_n "(cached) " >&6
else

		    arm64)
			{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch arm64 flag" >&5
printf %s "checking if compiler accepts -arch arm64 flag... " >&6; }
if test ${tcl_cv_cc_arch_arm64+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
			    hold_cflags=$CFLAGS
			    CFLAGS="$CFLAGS -arch x86_64"
			    CFLAGS="$CFLAGS -arch arm64"
			    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
  tcl_cv_cc_arch_x86_64=yes
else
  tcl_cv_cc_arch_x86_64=no
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_cc_arch_arm64=yes
else case e in #(
  e) tcl_cv_cc_arch_arm64=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
			    CFLAGS=$hold_cflags
			    CFLAGS=$hold_cflags ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_x86_64" >&5
$as_echo "$tcl_cv_cc_arch_x86_64" >&6; }
			if test $tcl_cv_cc_arch_x86_64 = yes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_arm64" >&5
printf "%s\n" "$tcl_cv_cc_arch_arm64" >&6; }
			if test $tcl_cv_cc_arch_arm64 = yes
then :

			    CFLAGS="$CFLAGS -arch x86_64"
			    CFLAGS="$CFLAGS -arch arm64"
			    do64bit_ok=yes

fi;;
		    *)
			{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&5
$as_echo "$as_me: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&2;};;
			{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&5
printf "%s\n" "$as_me: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&2;};;
		esac

else

		# Check for combined 32-bit and 64-bit fat build
		if echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \
		    && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '; then :

		    fat_32_64=yes
fi

fi
	    SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS}'
	    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -single_module flag" >&5
$as_echo_n "checking if ld accepts -single_module flag... " >&6; }
if ${tcl_cv_ld_single_module+:} false; then :
  $as_echo_n "(cached) " >&6
else

		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module"
		cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
else case e in #(
{
int i;
  ;
  return 0;
}
  e)
		# Check for combined 32-bit and 64-bit fat build
		if echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64|arm64) ' \
		    && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '
then :

_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
  tcl_cv_ld_single_module=yes
		    fat_32_64=yes
else
  tcl_cv_ld_single_module=no
fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
		LDFLAGS=$hold_ldflags
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_single_module" >&5
$as_echo "$tcl_cv_ld_single_module" >&6; }
	    if test $tcl_cv_ld_single_module = yes; then :

	     ;;
		SHLIB_LD="${SHLIB_LD} -Wl,-single_module"

esac
fi
	    SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS}'
	    SHLIB_SUFFIX=".dylib"
	    DL_OBJS="tclLoadDyld.o"
	    DL_LIBS=""
	    LDFLAGS="$LDFLAGS -headerpad_max_install_names"
	    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -search_paths_first flag" >&5
$as_echo_n "checking if ld accepts -search_paths_first flag... " >&6; }
if ${tcl_cv_ld_search_paths_first+:} false; then :
  $as_echo_n "(cached) " >&6
else

	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if ld accepts -search_paths_first flag" >&5
printf %s "checking if ld accepts -search_paths_first flag... " >&6; }
if test ${tcl_cv_ld_search_paths_first+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
		cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{
int i;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_ld_search_paths_first=yes
else
  tcl_cv_ld_search_paths_first=no
else case e in #(
  e) tcl_cv_ld_search_paths_first=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
		LDFLAGS=$hold_ldflags
		LDFLAGS=$hold_ldflags ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_search_paths_first" >&5
$as_echo "$tcl_cv_ld_search_paths_first" >&6; }
	    if test $tcl_cv_ld_search_paths_first = yes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_search_paths_first" >&5
printf "%s\n" "$tcl_cv_ld_search_paths_first" >&6; }
	    if test $tcl_cv_ld_search_paths_first = yes
then :

		LDFLAGS="$LDFLAGS -Wl,-search_paths_first"

fi
	    if test "$tcl_cv_cc_visibility_hidden" != yes; then :
	    if test "$tcl_cv_cc_visibility_hidden" != yes
then :


$as_echo "#define MODULE_SCOPE __private_extern__" >>confdefs.h
printf "%s\n" "#define MODULE_SCOPE __private_extern__" >>confdefs.h

		tcl_cv_cc_visibility_hidden=yes

fi
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
	    LD_LIBRARY_PATH_VAR="DYLD_FALLBACK_LIBRARY_PATH"

$as_echo "#define MAC_OSX_TCL 1" >>confdefs.h
printf "%s\n" "#define MAC_OSX_TCL 1" >>confdefs.h

	    PLAT_OBJS='${MAC_OSX_OBJS}'
	    PLAT_SRCS='${MAC_OSX_SRCS}'
	    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use CoreFoundation" >&5
$as_echo_n "checking whether to use CoreFoundation... " >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to use CoreFoundation" >&5
printf %s "checking whether to use CoreFoundation... " >&6; }
	    # Check whether --enable-corefoundation was given.
if test "${enable_corefoundation+set}" = set; then :
if test ${enable_corefoundation+y}
then :
  enableval=$enable_corefoundation; tcl_corefoundation=$enableval
else
  tcl_corefoundation=yes
else case e in #(
  e) tcl_corefoundation=yes ;;
esac
fi

	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_corefoundation" >&5
$as_echo "$tcl_corefoundation" >&6; }
	    if test $tcl_corefoundation = yes; then :
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_corefoundation" >&5
printf "%s\n" "$tcl_corefoundation" >&6; }
	    if test $tcl_corefoundation = yes
then :

		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CoreFoundation.framework" >&5
$as_echo_n "checking for CoreFoundation.framework... " >&6; }
if ${tcl_cv_lib_corefoundation+:} false; then :
  $as_echo_n "(cached) " >&6
else

		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for CoreFoundation.framework" >&5
printf %s "checking for CoreFoundation.framework... " >&6; }
if test ${tcl_cv_lib_corefoundation+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
		    hold_libs=$LIBS
		    if test "$fat_32_64" = yes; then :
		    if test "$fat_32_64" = yes
then :

			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    # On Tiger there is no 64-bit CF, so remove 64-bit
			    # archs from CFLAGS et al. while testing for
			    # presence of CF. 64-bit CF is disabled in
			    # tclUnixPort.h if necessary.
			    eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"'
			done
fi
		    LIBS="$LIBS -framework CoreFoundation"
		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <CoreFoundation/CoreFoundation.h>
int
main ()
main (void)
{
CFBundleRef b = CFBundleGetMainBundle();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_lib_corefoundation=yes
else
  tcl_cv_lib_corefoundation=no
else case e in #(
  e) tcl_cv_lib_corefoundation=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
		    if test "$fat_32_64" = yes; then :
		    if test "$fat_32_64" = yes
then :

			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval $v'="$hold_'$v'"'
		        done
			done
fi
		    LIBS=$hold_libs
		    LIBS=$hold_libs ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_corefoundation" >&5
$as_echo "$tcl_cv_lib_corefoundation" >&6; }
		if test $tcl_cv_lib_corefoundation = yes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_corefoundation" >&5
printf "%s\n" "$tcl_cv_lib_corefoundation" >&6; }
		if test $tcl_cv_lib_corefoundation = yes
then :

		    LIBS="$LIBS -framework CoreFoundation"

$as_echo "#define HAVE_COREFOUNDATION 1" >>confdefs.h
printf "%s\n" "#define HAVE_COREFOUNDATION 1" >>confdefs.h


else
  tcl_corefoundation=no
else case e in #(
  e) tcl_corefoundation=no ;;
esac
fi
		if test "$fat_32_64" = yes -a $tcl_corefoundation = yes; then :
		if test "$fat_32_64" = yes -a $tcl_corefoundation = yes
then :

		    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit CoreFoundation" >&5
$as_echo_n "checking for 64-bit CoreFoundation... " >&6; }
if ${tcl_cv_lib_corefoundation_64+:} false; then :
  $as_echo_n "(cached) " >&6
else

		    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit CoreFoundation" >&5
printf %s "checking for 64-bit CoreFoundation... " >&6; }
if test ${tcl_cv_lib_corefoundation_64+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
			done
			cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <CoreFoundation/CoreFoundation.h>
int
main ()
main (void)
{
CFBundleRef b = CFBundleGetMainBundle();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_lib_corefoundation_64=yes
else
  tcl_cv_lib_corefoundation_64=no
else case e in #(
  e) tcl_cv_lib_corefoundation_64=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval $v'="$hold_'$v'"'
			done
			done ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_corefoundation_64" >&5
$as_echo "$tcl_cv_lib_corefoundation_64" >&6; }
		    if test $tcl_cv_lib_corefoundation_64 = no; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_corefoundation_64" >&5
printf "%s\n" "$tcl_cv_lib_corefoundation_64" >&6; }
		    if test $tcl_cv_lib_corefoundation_64 = no
then :


$as_echo "#define NO_COREFOUNDATION_64 1" >>confdefs.h
printf "%s\n" "#define NO_COREFOUNDATION_64 1" >>confdefs.h

                        LDFLAGS="$LDFLAGS -Wl,-no_arch_warnings"
			LDFLAGS="$LDFLAGS -Wl,-no_arch_warnings"

fi

fi

fi
	    ;;
	OS/390-*)
	    SHLIB_LD_LIBS=""
	    CFLAGS_OPTIMIZE=""		# Optimizer is buggy

$as_echo "#define _OE_SOCKETS 1" >>confdefs.h
printf "%s\n" "#define _OE_SOCKETS 1" >>confdefs.h

	    ;;
	OSF1-V*)
	    # Digital OSF/1
	    SHLIB_CFLAGS=""
	    if test "$SHARED_BUILD" = 1; then :
	    if test "$SHARED_BUILD" = 1
then :

	        SHLIB_LD='ld -shared -expect_unresolved "*"'
		SHLIB_LD='${CC} -shared'

else

	        SHLIB_LD='ld -non_shared -expect_unresolved "*"'

else case e in #(
  e)
		SHLIB_LD='${CC} -non_shared'
	     ;;
esac
fi
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    if test $doRpath = yes; then :
	    if test $doRpath = yes
then :

		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
fi
	    if test "$GCC" = yes; then :
	    if test "$GCC" = yes
then :
  CFLAGS="$CFLAGS -mieee"
else

		CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"
else case e in #(
  e)
		CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee" ;;
esac
fi
	    # see pthread_intro(3) for pthread support on osf1, k.furukawa
	    CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE"
	    CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64"
	    LIBS=`echo $LIBS | sed s/-lpthreads//`
	    if test "$GCC" = yes; then :
	    if test "$GCC" = yes
then :

		LIBS="$LIBS -lpthread -lmach -lexc"

else

else case e in #(
  e)
		CFLAGS="$CFLAGS -pthread"
		LDFLAGS="$LDFLAGS -pthread"

	     ;;
esac
fi
	    ;;
	QNX-6*)
	    # QNX RTP
	    # This may work for all QNX, but it was only reported for v6.
	    SHLIB_LD="ld -Bshareable -x"
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    # dlopen is in -lc on QNX
	    DL_LIBS=""
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	SCO_SV-3.2*)
	    # Note, dlopen is available only on SCO 3.2.5 and greater. However,
	    # this test works, since "uname -s" was non-standard in 3.2.4 and
	    # below.
	    if test "$GCC" = yes; then :
	    if test "$GCC" = yes
then :

		SHLIB_CFLAGS="-fPIC -melf"
		LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"

else

else case e in #(
  e)
		SHLIB_CFLAGS="-Kpic -belf"
		LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"

	     ;;
esac
fi
	    SHLIB_LD="ld -G"
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	SunOS-5.[0-6])
	    # Careful to not let 5.10+ fall into this case

	    # Note: If _REENTRANT isn't defined, then Solaris
	    # won't define thread-safe library routines.


$as_echo "#define _REENTRANT 1" >>confdefs.h
printf "%s\n" "#define _REENTRANT 1" >>confdefs.h


$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
printf "%s\n" "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h


	    SHLIB_CFLAGS="-KPIC"
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    if test "$GCC" = yes; then :
	    if test "$GCC" = yes
then :

		SHLIB_LD='${CC} -shared'
		CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}

else

else case e in #(
  e)
		SHLIB_LD="/usr/ccs/bin/ld -G -z text"
		CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}

	     ;;
esac
fi
	    ;;
	SunOS-5*)
	    # Note: If _REENTRANT isn't defined, then Solaris
	    # won't define thread-safe library routines.


$as_echo "#define _REENTRANT 1" >>confdefs.h
printf "%s\n" "#define _REENTRANT 1" >>confdefs.h


$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
printf "%s\n" "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h


	    SHLIB_CFLAGS="-KPIC"

	    # Check to enable 64-bit flags for compiler/linker
	    if test "$do64bit" = yes; then :
	    if test "$do64bit" = yes
then :

		arch=`isainfo`
		if test "$arch" = "sparcv9 sparc"; then :
		if test "$arch" = "sparcv9 sparc"
then :

		    if test "$GCC" = yes; then :
		    if test "$GCC" = yes
then :

			if test "`${CC} -dumpversion | awk -F. '{print $1}'`" -lt 3; then :
			if test "`${CC} -dumpversion | awk -F. '{print $1}'`" -lt 3
then :

			    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&5
$as_echo "$as_me: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&2;}
			    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&5
printf "%s\n" "$as_me: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&2;}

else

else case e in #(
  e)
			    do64bit_ok=yes
			    CFLAGS="$CFLAGS -m64 -mcpu=v9"
			    LDFLAGS="$LDFLAGS -m64 -mcpu=v9"
			    SHLIB_CFLAGS="-fPIC"

			 ;;
esac
fi

else

else case e in #(
  e)
			do64bit_ok=yes
			if test "$do64bitVIS" = yes; then :
			if test "$do64bitVIS" = yes
then :

			    CFLAGS="$CFLAGS -xarch=v9a"
			    LDFLAGS_ARCH="-xarch=v9a"

else

else case e in #(
  e)
			    CFLAGS="$CFLAGS -xarch=v9"
			    LDFLAGS_ARCH="-xarch=v9"

			 ;;
esac
fi
			# Solaris 64 uses this as well
			#LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64"

		     ;;
esac
fi

else
  if test "$arch" = "amd64 i386"; then :
else case e in #(
  e) if test "$arch" = "amd64 i386"
then :

		    if test "$GCC" = yes; then :
		    if test "$GCC" = yes
then :

			case $system in
			    SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*)
				do64bit_ok=yes
				CFLAGS="$CFLAGS -m64"
				LDFLAGS="$LDFLAGS -m64";;
			    *)
				{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5
$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;};;
				{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5
printf "%s\n" "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;};;
			esac

else

else case e in #(
  e)
			do64bit_ok=yes
			case $system in
			    SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*)
				CFLAGS="$CFLAGS -m64"
				LDFLAGS="$LDFLAGS -m64";;
			    *)
				CFLAGS="$CFLAGS -xarch=amd64"
				LDFLAGS="$LDFLAGS -xarch=amd64";;
			esac

		     ;;
esac
fi

else
  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported for $arch" >&5
$as_echo "$as_me: WARNING: 64bit mode not supported for $arch" >&2;}
fi
else case e in #(
  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported for $arch" >&5
printf "%s\n" "$as_me: WARNING: 64bit mode not supported for $arch" >&2;} ;;
esac
fi ;;
esac
fi

fi

	    #--------------------------------------------------------------------
	    # On Solaris 5.x i386 with the sunpro compiler we need to link
	    # with sunmath to get floating point rounding control
	    #--------------------------------------------------------------------
	    if test "$GCC" = yes; then :
	    if test "$GCC" = yes
then :
  use_sunmath=no
else

else case e in #(
  e)
		arch=`isainfo`
		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use -lsunmath for fp rounding control" >&5
$as_echo_n "checking whether to use -lsunmath for fp rounding control... " >&6; }
		if test "$arch" = "amd64 i386" -o "$arch" = "i386"; then :
		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to use -lsunmath for fp rounding control" >&5
printf %s "checking whether to use -lsunmath for fp rounding control... " >&6; }
		if test "$arch" = "amd64 i386" -o "$arch" = "i386"
then :

			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
			{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
			MATH_LIBS="-lsunmath $MATH_LIBS"
			ac_fn_c_check_header_mongrel "$LINENO" "sunmath.h" "ac_cv_header_sunmath_h" "$ac_includes_default"
if test "x$ac_cv_header_sunmath_h" = xyes; then :
			ac_fn_c_check_header_compile "$LINENO" "sunmath.h" "ac_cv_header_sunmath_h" "$ac_includes_default"
if test "x$ac_cv_header_sunmath_h" = xyes
then :

fi


			use_sunmath=yes

else

			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
else case e in #(
  e)
			{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
			use_sunmath=no

		 ;;
esac
fi

	     ;;
esac
fi
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    if test "$GCC" = yes; then :
	    if test "$GCC" = yes
then :

		SHLIB_LD='${CC} -shared'
		CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
		if test "$do64bit_ok" = yes; then :
		if test "$do64bit_ok" = yes
then :

		    if test "$arch" = "sparcv9 sparc"; then :
		    if test "$arch" = "sparcv9 sparc"
then :

			# We need to specify -static-libgcc or we need to
			# add the path to the sparv9 libgcc.
			SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc"
			# for finding sparcv9 libgcc, get the regular libgcc
			# path, remove so name and append 'sparcv9'
			#v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..."
			#CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir"

else
  if test "$arch" = "amd64 i386"; then :
else case e in #(
  e) if test "$arch" = "amd64 i386"
then :

			SHLIB_LD="$SHLIB_LD -m64 -static-libgcc"

fi
fi ;;
esac
fi

fi

else

		if test "$use_sunmath" = yes; then :
else case e in #(
  e)
		if test "$use_sunmath" = yes
then :
  textmode=textoff
else
  textmode=text
else case e in #(
  e) textmode=text ;;
esac
fi
		case $system in
		    SunOS-5.[1-9][0-9]*|SunOS-5.[7-9])
			SHLIB_LD="\${CC} -G -z $textmode \${LDFLAGS}";;
		    *)
			SHLIB_LD="/usr/ccs/bin/ld -G -z $textmode";;
		esac
		CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'

	     ;;
esac
fi
	    ;;
	UNIX_SV* | UnixWare-5*)
	    SHLIB_CFLAGS="-KPIC"
	    SHLIB_LD='${CC} -G'
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers
	    # that don't grok the -Bexport option.  Test that it does.
	    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld accepts -Bexport flag" >&5
$as_echo_n "checking for ld accepts -Bexport flag... " >&6; }
if ${tcl_cv_ld_Bexport+:} false; then :
  $as_echo_n "(cached) " >&6
else

	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ld accepts -Bexport flag" >&5
printf %s "checking for ld accepts -Bexport flag... " >&6; }
if test ${tcl_cv_ld_Bexport+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -Wl,-Bexport"
		cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{
int i;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_ld_Bexport=yes
else
  tcl_cv_ld_Bexport=no
else case e in #(
  e) tcl_cv_ld_Bexport=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
	        LDFLAGS=$hold_ldflags
		LDFLAGS=$hold_ldflags ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_Bexport" >&5
$as_echo "$tcl_cv_ld_Bexport" >&6; }
	    if test $tcl_cv_ld_Bexport = yes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_Bexport" >&5
printf "%s\n" "$tcl_cv_ld_Bexport" >&6; }
	    if test $tcl_cv_ld_Bexport = yes
then :

		LDFLAGS="$LDFLAGS -Wl,-Bexport"

fi
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
    esac

    if test "$do64bit" = yes -a "$do64bit_ok" = no; then :
    if test "$do64bit" = yes -a "$do64bit_ok" = no
then :

	{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit support being disabled -- don't know magic for this platform" >&5
$as_echo "$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform" >&2;}
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit support being disabled -- don't know magic for this platform" >&5
printf "%s\n" "$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform" >&2;}

fi

    if test "$do64bit" = yes -a "$do64bit_ok" = yes; then :
    if test "$do64bit" = yes -a "$do64bit_ok" = yes
then :


$as_echo "#define TCL_CFG_DO64BIT 1" >>confdefs.h
printf "%s\n" "#define TCL_CFG_DO64BIT 1" >>confdefs.h


fi



    # Step 4: disable dynamic loading if requested via a command-line switch.

    # Check whether --enable-load was given.
if test "${enable_load+set}" = set; then :
if test ${enable_load+y}
then :
  enableval=$enable_load; tcl_ok=$enableval
else
  tcl_ok=yes
else case e in #(
  e) tcl_ok=yes ;;
esac
fi

    if test "$tcl_ok" = no; then :
    if test "$tcl_ok" = no
then :
  DL_OBJS=""
fi

    if test "x$DL_OBJS" != x; then :
    if test "x$DL_OBJS" != x
then :
  BUILD_DLTEST="\$(DLTEST_TARGETS)"
else

	{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can't figure out how to do dynamic loading or shared libraries on this system." >&5
$as_echo "$as_me: WARNING: Can't figure out how to do dynamic loading or shared libraries on this system." >&2;}
else case e in #(
  e)
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Can't figure out how to do dynamic loading or shared libraries on this system." >&5
printf "%s\n" "$as_me: WARNING: Can't figure out how to do dynamic loading or shared libraries on this system." >&2;}
	SHLIB_CFLAGS=""
	SHLIB_LD=""
	SHLIB_SUFFIX=""
	DL_OBJS="tclLoadNone.o"
	DL_LIBS=""
	LDFLAGS="$LDFLAGS_ORIG"
	CC_SEARCH_FLAGS=""
	LD_SEARCH_FLAGS=""
	BUILD_DLTEST=""

     ;;
esac
fi
    LDFLAGS="$LDFLAGS $LDFLAGS_ARCH"

    # If we're running gcc, then change the C flags for compiling shared
    # libraries to the right flags for gcc, instead of those for the
    # standard manufacturer compiler.

    if test "$DL_OBJS" != "tclLoadNone.o" -a "$GCC" = yes; then :
    if test "$DL_OBJS" != "tclLoadNone.o" -a "$GCC" = yes
then :

	case $system in
	    AIX-*) ;;
	    BSD/OS*) ;;
	    CYGWIN_*) ;;
	    HP_UX*) ;;
	    CYGWIN_*|MINGW32_*|MSYS_*) ;;
	    HP-UX*) ;;
	    Darwin-*) ;;
	    IRIX*) ;;
	    Linux*|GNU*) ;;
	    NetBSD-*|OpenBSD-*) ;;
	    OSF1-V*) ;;
	    OSF1-*) ;;
	    SCO_SV-3.2*) ;;
	    *) SHLIB_CFLAGS="-fPIC" ;;
	esac
fi

    if test "$tcl_cv_cc_visibility_hidden" != yes; then :
    if test "$tcl_cv_cc_visibility_hidden" != yes
then :


$as_echo "#define MODULE_SCOPE extern" >>confdefs.h
printf "%s\n" "#define MODULE_SCOPE extern" >>confdefs.h


fi

    if test "$SHARED_LIB_SUFFIX" = ""; then :
    if test "$SHARED_LIB_SUFFIX" = ""
then :

	SHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}'
fi
    if test "$UNSHARED_LIB_SUFFIX" = ""; then :
    if test "$UNSHARED_LIB_SUFFIX" = ""
then :

	UNSHARED_LIB_SUFFIX='${VERSION}.a'
fi
    DLL_INSTALL_DIR="\$(LIB_INSTALL_DIR)"

    if test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""; then :
    if test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""
then :

        LIB_SUFFIX=${SHARED_LIB_SUFFIX}
        MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${LDFLAGS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'
        if test "${SHLIB_SUFFIX}" = ".dll"; then :
	LIB_SUFFIX=${SHARED_LIB_SUFFIX}
	MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${LDFLAGS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'
	if test "${SHLIB_SUFFIX}" = ".dll"
then :

            INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)";if test -f $(LIB_FILE).a; then $(INSTALL_DATA) $(LIB_FILE).a "$(LIB_INSTALL_DIR)"; fi;'
            DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)"
	    INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"'
	    DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)"

else

            INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'

else case e in #(
  e)
	    INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'
	 ;;
esac
fi

else

        LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}
else case e in #(
  e)
	LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}

        if test "$RANLIB" = ""; then :
	if test "$RANLIB" = ""
then :

            MAKE_LIB='$(STLIB_LD) $@ ${OBJS}'
	    MAKE_LIB='$(STLIB_LD) $@ ${OBJS}'

else

            MAKE_LIB='${STLIB_LD} $@ ${OBJS} ; ${RANLIB} $@'

else case e in #(
  e)
	    MAKE_LIB='${STLIB_LD} $@ ${OBJS} ; ${RANLIB} $@'
	 ;;
esac
fi
        INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'

	INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'
     ;;
esac
fi

    # Stub lib does not depend on shared/static configuration
    if test "$RANLIB" = ""; then :
    if test "$RANLIB" = ""
then :

        MAKE_STUB_LIB='${STLIB_LD} $@ ${STUB_LIB_OBJS}'
	MAKE_STUB_LIB='${STLIB_LD} $@ ${STUB_LIB_OBJS}'

else

        MAKE_STUB_LIB='${STLIB_LD} $@ ${STUB_LIB_OBJS} ; ${RANLIB} $@'

else case e in #(
  e)
	MAKE_STUB_LIB='${STLIB_LD} $@ ${STUB_LIB_OBJS} ; ${RANLIB} $@'
     ;;
esac
fi
    INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) "$(LIB_INSTALL_DIR)/$(STUB_LIB_FILE)"'

    # Define TCL_LIBS now that we know what DL_LIBS is.
    # The trick here is that we don't want to change the value of TCL_LIBS if
    # it is already set when tclConfig.sh had been loaded by Tk.
    if test "x${TCL_LIBS}" = x; then :
    if test "x${TCL_LIBS}" = x
then :

        TCL_LIBS="${DL_LIBS} ${LIBS} ${MATH_LIBS}"
	TCL_LIBS="${DL_LIBS} ${LIBS} ${MATH_LIBS}"
fi


	# See if the compiler supports casting to a union type.
	# This is used to stop gcc from printing a compiler
	# warning when initializing a union member.
    # See if the compiler supports casting to a union type.
    # This is used to stop gcc from printing a compiler
    # warning when initializing a union member.

	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for cast to union support" >&5
$as_echo_n "checking for cast to union support... " >&6; }
if ${tcl_cv_cast_to_union+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for cast to union support" >&5
printf %s "checking for cast to union support... " >&6; }
if test ${tcl_cv_cast_to_union+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

		  union foo { int i; double d; };
		  union foo f = (union foo) (int) 0;
		union foo { int i; double d; };
		union foo f = (union foo) (int) 0;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_cast_to_union=yes
else
  tcl_cv_cast_to_union=no
else case e in #(
  e) tcl_cv_cast_to_union=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
     ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cast_to_union" >&5
$as_echo "$tcl_cv_cast_to_union" >&6; }
	if test "$tcl_cv_cast_to_union" = "yes"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cast_to_union" >&5
printf "%s\n" "$tcl_cv_cast_to_union" >&6; }
    if test "$tcl_cv_cast_to_union" = "yes"; then

printf "%s\n" "#define HAVE_CAST_TO_UNION 1" >>confdefs.h

    fi
    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -fno-lto"
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working -fno-lto" >&5
printf %s "checking for working -fno-lto... " >&6; }
if test ${ac_cv_nolto+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_nolto=yes
else case e in #(
  e) ac_cv_nolto=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
     ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_nolto" >&5
printf "%s\n" "$ac_cv_nolto" >&6; }
    CFLAGS=$hold_cflags
    if test "$ac_cv_nolto" = "yes" ; then
	CFLAGS_NOLTO="-fno-lto"
    else
	CFLAGS_NOLTO=""
    fi
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the compiler understands -finput-charset" >&5
printf %s "checking if the compiler understands -finput-charset... " >&6; }
if test ${tcl_cv_cc_input_charset+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -finput-charset=UTF-8"
	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{
$as_echo "#define HAVE_CAST_TO_UNION 1" >>confdefs.h

	fi

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_cc_input_charset=yes
else case e in #(
  e) tcl_cv_cc_input_charset=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
	CFLAGS=$hold_cflags ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_input_charset" >&5
printf "%s\n" "$tcl_cv_cc_input_charset" >&6; }
    if test $tcl_cv_cc_input_charset = yes; then
	CFLAGS="$CFLAGS -finput-charset=UTF-8"
    fi

    ac_fn_c_check_header_mongrel "$LINENO" "stdbool.h" "ac_cv_header_stdbool_h" "$ac_includes_default"
if test "x$ac_cv_header_stdbool_h" = xyes; then :
    ac_fn_c_check_header_compile "$LINENO" "stdbool.h" "ac_cv_header_stdbool_h" "$ac_includes_default"
if test "x$ac_cv_header_stdbool_h" = xyes
then :

$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h
printf "%s\n" "#define HAVE_STDBOOL_H 1" >>confdefs.h

fi


    # Check for vfork, posix_spawnp() and friends unconditionally
    ac_fn_c_check_func "$LINENO" "vfork" "ac_cv_func_vfork"
if test "x$ac_cv_func_vfork" = xyes
then :
  printf "%s\n" "#define HAVE_VFORK 1" >>confdefs.h

fi
ac_fn_c_check_func "$LINENO" "posix_spawnp" "ac_cv_func_posix_spawnp"
if test "x$ac_cv_func_posix_spawnp" = xyes
then :
  printf "%s\n" "#define HAVE_POSIX_SPAWNP 1" >>confdefs.h

fi
ac_fn_c_check_func "$LINENO" "posix_spawn_file_actions_adddup2" "ac_cv_func_posix_spawn_file_actions_adddup2"
if test "x$ac_cv_func_posix_spawn_file_actions_adddup2" = xyes
then :
  printf "%s\n" "#define HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2 1" >>confdefs.h

fi
ac_fn_c_check_func "$LINENO" "posix_spawnattr_setflags" "ac_cv_func_posix_spawnattr_setflags"
if test "x$ac_cv_func_posix_spawnattr_setflags" = xyes
then :
  printf "%s\n" "#define HAVE_POSIX_SPAWNATTR_SETFLAGS 1" >>confdefs.h

fi


    # FIXME: This subst was left in only because the TCL_DL_LIBS
    # entry in tclConfig.sh uses it. It is not clear why someone
    # would use TCL_DL_LIBS instead of TCL_LIBS.


6714
6715
6716
6717
6718
6719
6720
6721
6722


6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736


6737
6738


6739
6740
6741



6742
6743
6744
6745
6746
6747
6748
6749

6750
6751
6752


6753
6754

6755
6756
6757
6758
6759
6760
6761


6762
6763
6764
6765
6766
6767
6768
6769

6770
6771
6772
6773
6774
6775

6776
6777
6778

6779
6780
6781
6782
6783
6784
6785


6786
6787
6788


6789
6790
6791
6792
6793
6794

6795
6796
6797
6798
6799
6800
6801
6802
6803


6804
6805
6806
6807
6808
6809





6810
6811
6812
6813

6814
6815
6816
6817
6818
6819
6820


6821
6822
6823


6824
6825
6826
6827
6828

6829
6830
6831
6832
6833
6834
6835


6836
6837
6838



6839
6840


6841
6842


6843
6844
6845
6846
6847

6848
6849
6850
6851
6852





















































6853
6854
6855
6856





6857
6858
6859
6860

6861
6862
6863
6864
6865
6866
6867


6868
6869
6870


6871
6872
6873
6874
6875

6876
6877
6878
6879
6880
6881
6882


6883
6884
6885



6886
6887


6888
6889


6890
6891
6892
6893
6894

6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948


6949
6950
6951


6952
6953
6954
6955
6956
6957
6958
6959
6960
6961







6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984

6985
6986
6987
6988

6989
6990
6991
6992


6993
6994
6995
6996
6997
6998



6999
7000


7001
7002
7003
7004
7005

7006
7007
7008


7009
7010
7011
7012
7013
7014
7015

7016
7017

7018







































































7019
7020
7021
7022
7023
7024







7025
7026
7027
7028
7029
7030

7031
7032
7033
7034
7035
7036
7037


7038
7039
7040



7041
7042


7043
7044
7045


7046
7047
7048

7049
7050
7051
7052
7053
7054
7055
7056
7057







7058
7059
7060
7061
7062
7063

7064
7065
7066

7067
7068
7069
7070
7071


7072
7073
7074



7075
7076


7077
7078
7079


7080
7081
7082

7083
7084
7085
7086

7087
7088
7089
7090
7091

7092
7093
7094
7095
7096

7097
7098
7099
7100


7101
7102
7103
7104
7105
7106
7107
7108




7109
7110
7111
7112
7113
7114
7115
7116
7117

7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136







7137
7138
7139
7140
7141

7142
7143
7144
7145
7146
7147
7148
7149


7150
7151
7152



7153
7154


7155
7156
7157
7158
7159


7160
7161

7162
7163
7164


7165
7166
7167


7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182







7183
7184
7185
7186
7187
7188
7189
7190
7191
7192


7193
7194
7195
7196
7197
7198
7199
7600
7601
7602
7603
7604
7605
7606


7607
7608

7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619


7620
7621
7622

7623
7624
7625


7626
7627
7628
7629
7630
7631
7632
7633
7634
7635

7636
7637


7638
7639
7640

7641
7642
7643
7644
7645
7646


7647
7648
7649
7650
7651
7652
7653
7654
7655

7656
7657
7658
7659
7660
7661

7662
7663
7664

7665
7666
7667
7668
7669
7670


7671
7672
7673


7674
7675
7676
7677
7678
7679
7680

7681
7682
7683
7684
7685
7686
7687
7688


7689
7690
7691
7692




7693
7694
7695
7696
7697
7698
7699
7700

7701
7702
7703
7704
7705
7706
7707

7708
7709
7710


7711
7712
7713
7714
7715
7716

7717
7718
7719
7720
7721
7722
7723

7724
7725
7726


7727
7728
7729
7730

7731
7732
7733

7734
7735
7736
7737
7738
7739

7740
7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798




7799
7800
7801
7802
7803
7804
7805
7806

7807
7808
7809
7810
7811
7812
7813

7814
7815
7816


7817
7818
7819
7820
7821
7822

7823
7824
7825
7826
7827
7828
7829

7830
7831
7832


7833
7834
7835
7836

7837
7838
7839

7840
7841
7842
7843
7844
7845

7846
7847
7848
7849
7850















































7851


7852
7853
7854


7855
7856
7857
7858
7859
7860






7861
7862
7863
7864
7865
7866
7867
7868


















7869
7870
7871

7872
7873
7874
7875

7876
7877
7878


7879
7880
7881
7882
7883
7884


7885
7886
7887
7888

7889
7890
7891
7892
7893
7894

7895
7896


7897
7898
7899






7900


7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952
7953
7954
7955
7956
7957
7958
7959
7960
7961
7962
7963
7964
7965
7966
7967
7968
7969
7970
7971
7972
7973






7974
7975
7976
7977
7978
7979
7980
7981
7982
7983
7984
7985

7986
7987
7988
7989
7990
7991
7992

7993
7994
7995


7996
7997
7998
7999

8000
8001
8002


8003
8004
8005
8006

8007
8008
8009
8010






8011
8012
8013
8014
8015
8016
8017
8018
8019
8020
8021
8022

8023
8024
8025

8026
8027
8028
8029
8030

8031
8032
8033


8034
8035
8036
8037

8038
8039
8040


8041
8042
8043
8044

8045
8046
8047
8048

8049





8050





8051




8052
8053







8054
8055
8056
8057
8058





8059



8060
8061


















8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072

8073
8074
8075
8076
8077
8078
8079
8080

8081
8082
8083


8084
8085
8086
8087

8088
8089
8090
8091
8092


8093
8094
8095

8096
8097


8098
8099
8100


8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111






8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127

8128
8129
8130
8131
8132
8133
8134
8135
8136







-
-
+
+
-











-
-
+
+

-
+
+

-
-
+
+
+







-
+

-
-
+
+

-
+





-
-
+
+







-
+





-
+


-
+





-
-
+
+

-
-
+
+





-
+







-
-
+
+


-
-
-
-
+
+
+
+
+



-
+






-
+
+

-
-
+
+




-
+






-
+
+

-
-
+
+
+

-
+
+

-
+
+




-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+



-
+






-
+
+

-
-
+
+




-
+






-
+
+

-
-
+
+
+

-
+
+

-
+
+




-
+




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
+
+

-
-
+
+




-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-



-
+



-
+


-
-
+
+




-
-
+
+
+

-
+
+




-
+

-
-
+
+

-
-
-
-
-
-
+
-
-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+





-
+






-
+
+

-
-
+
+
+

-
+
+

-
-
+
+


-
+



-
-
-
-
-
-
+
+
+
+
+
+
+





-
+


-
+




-
+
+

-
-
+
+
+

-
+
+

-
-
+
+


-
+



-
+
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
+
+
-
-
-
-
-
-
-

+
+
+
+
-
-
-
-
-

-
-
-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+




-
+







-
+
+

-
-
+
+
+

-
+
+



-
-
+
+

-
+

-
-
+
+

-
-
+
+









-
-
-
-
-
-
+
+
+
+
+
+
+









-
+
+














cat >>confdefs.h <<_ACEOF
#define TCL_SHLIB_EXT "${SHLIB_SUFFIX}"

printf "%s\n" "#define TCL_SHLIB_EXT \"${SHLIB_SUFFIX}\"" >>confdefs.h
_ACEOF











    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for build with symbols" >&5
$as_echo_n "checking for build with symbols... " >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for build with symbols" >&5
printf %s "checking for build with symbols... " >&6; }
    # Check whether --enable-symbols was given.
if test "${enable_symbols+set}" = set; then :
if test ${enable_symbols+y}
then :
  enableval=$enable_symbols; tcl_ok=$enableval
else
  tcl_ok=no
else case e in #(
  e) tcl_ok=no ;;
esac
fi

# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.
    if test "$tcl_ok" = "no"; then
	CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'
	LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'

$as_echo "#define NDEBUG 1" >>confdefs.h
printf "%s\n" "#define NDEBUG 1" >>confdefs.h

	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }

$as_echo "#define TCL_CFG_OPTIMIZED 1" >>confdefs.h
printf "%s\n" "#define TCL_CFG_OPTIMIZED 1" >>confdefs.h

    else
	CFLAGS_DEFAULT='$(CFLAGS_DEBUG)'
	LDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)'
	if test "$tcl_ok" = "yes"; then
	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (standard debugging)" >&5
$as_echo "yes (standard debugging)" >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes (standard debugging)" >&5
printf "%s\n" "yes (standard debugging)" >&6; }
	fi
    fi



    if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then

$as_echo "#define TCL_MEM_DEBUG 1" >>confdefs.h
printf "%s\n" "#define TCL_MEM_DEBUG 1" >>confdefs.h

    fi

    	if test "$tcl_ok" = "compile" -o "$tcl_ok" = "all"; then

$as_echo "#define TCL_COMPILE_DEBUG 1" >>confdefs.h
printf "%s\n" "#define TCL_COMPILE_DEBUG 1" >>confdefs.h


$as_echo "#define TCL_COMPILE_STATS 1" >>confdefs.h
printf "%s\n" "#define TCL_COMPILE_STATS 1" >>confdefs.h

	fi

    if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then
	if test "$tcl_ok" = "all"; then
	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled symbols mem compile debugging" >&5
$as_echo "enabled symbols mem compile debugging" >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: enabled symbols mem compile debugging" >&5
printf "%s\n" "enabled symbols mem compile debugging" >&6; }
	else
	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging" >&5
$as_echo "enabled $tcl_ok debugging" >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging" >&5
printf "%s\n" "enabled $tcl_ok debugging" >&6; }
	fi
    fi



$as_echo "#define MP_PREC 4" >>confdefs.h
printf "%s\n" "#define MP_PREC 4" >>confdefs.h


#--------------------------------------------------------------------
#	Detect what compiler flags to set for 64-bit support.
#--------------------------------------------------------------------


    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for required early compiler flags" >&5
$as_echo_n "checking for required early compiler flags... " >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for required early compiler flags" >&5
printf %s "checking for required early compiler flags... " >&6; }
    tcl_flags=""

    if ${tcl_cv_flag__isoc99_source+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    if test ${tcl_cv_flag__isoc99_source+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <stdlib.h>
int
main ()
main (void)
{
char *p = (char *)strtoll; char *q = (char *)strtoull;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_flag__isoc99_source=no
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#define _ISOC99_SOURCE 1
#include <stdlib.h>
int
main ()
main (void)
{
char *p = (char *)strtoll; char *q = (char *)strtoull;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_flag__isoc99_source=yes
else
  tcl_cv_flag__isoc99_source=no
else case e in #(
  e) tcl_cv_flag__isoc99_source=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi

    if test "x${tcl_cv_flag__isoc99_source}" = "xyes" ; then

$as_echo "#define _ISOC99_SOURCE 1" >>confdefs.h
printf "%s\n" "#define _ISOC99_SOURCE 1" >>confdefs.h

	tcl_flags="$tcl_flags _ISOC99_SOURCE"
    fi


    if test ${tcl_cv_flag__file_offset_bits+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/stat.h>
int
main (void)
{
switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; }
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_flag__file_offset_bits=no
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#define _FILE_OFFSET_BITS 64
#include <sys/stat.h>
int
main (void)
{
switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; }
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_flag__file_offset_bits=yes
else case e in #(
  e) tcl_cv_flag__file_offset_bits=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi

    if test "x${tcl_cv_flag__file_offset_bits}" = "xyes" ; then

printf "%s\n" "#define _FILE_OFFSET_BITS 64" >>confdefs.h

	tcl_flags="$tcl_flags _FILE_OFFSET_BITS"
    fi


    if ${tcl_cv_flag__largefile64_source+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    if test ${tcl_cv_flag__largefile64_source+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/stat.h>
int
main ()
main (void)
{
struct stat64 buf; int i = stat64("/", &buf);
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_flag__largefile64_source=no
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#define _LARGEFILE64_SOURCE 1
#include <sys/stat.h>
int
main ()
main (void)
{
struct stat64 buf; int i = stat64("/", &buf);
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_flag__largefile64_source=yes
else
  tcl_cv_flag__largefile64_source=no
else case e in #(
  e) tcl_cv_flag__largefile64_source=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi

    if test "x${tcl_cv_flag__largefile64_source}" = "xyes" ; then

$as_echo "#define _LARGEFILE64_SOURCE 1" >>confdefs.h
printf "%s\n" "#define _LARGEFILE64_SOURCE 1" >>confdefs.h

	tcl_flags="$tcl_flags _LARGEFILE64_SOURCE"
    fi


    if ${tcl_cv_flag__largefile_source64+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/stat.h>
int
main ()
{
char *p = (char *)open64;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  tcl_cv_flag__largefile_source64=no
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#define _LARGEFILE_SOURCE64 1
#include <sys/stat.h>
int
main ()
{
char *p = (char *)open64;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  tcl_cv_flag__largefile_source64=yes
else
  tcl_cv_flag__largefile_source64=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi

    if test "x${tcl_cv_flag__largefile_source64}" = "xyes" ; then

$as_echo "#define _LARGEFILE_SOURCE64 1" >>confdefs.h

	tcl_flags="$tcl_flags _LARGEFILE_SOURCE64"
    fi

    if test "x${tcl_flags}" = "x" ; then
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
$as_echo "none" >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5
printf "%s\n" "none" >&6; }
    else
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_flags}" >&5
$as_echo "${tcl_flags}" >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${tcl_flags}" >&5
printf "%s\n" "${tcl_flags}" >&6; }
    fi



    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit integer type" >&5
$as_echo_n "checking for 64-bit integer type... " >&6; }
    if ${tcl_cv_type_64bit+:} false; then :
  $as_echo_n "(cached) " >&6
else

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if 'long' and 'long long' have the same size (64-bit)?" >&5
printf %s "checking if 'long' and 'long long' have the same size (64-bit)?... " >&6; }
    if test ${tcl_cv_type_64bit+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	tcl_cv_type_64bit=none
	# See if the compiler knows natively about __int64
	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
{
__int64 value = (__int64) 0;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  tcl_type_64bit=__int64
else
  tcl_type_64bit="long long"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
	# See if we could use long anyway  Note that we substitute in the
	# type that is our current guess for a 64-bit type inside this check
	# program, so it should be modified only carefully...
        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{
switch (0) {
            case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ;
        }
	    case 1: case (sizeof(long long)==sizeof(long)): ;
	}
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  tcl_cv_type_64bit=${tcl_type_64bit}
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_type_64bit="long long"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi

    if test "${tcl_cv_type_64bit}" = none ; then

$as_echo "#define TCL_WIDE_INT_IS_LONG 1" >>confdefs.h
printf "%s\n" "#define TCL_WIDE_INT_IS_LONG 1" >>confdefs.h

	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
    else

cat >>confdefs.h <<_ACEOF
#define TCL_WIDE_INT_TYPE ${tcl_cv_type_64bit}
_ACEOF

	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_cv_type_64bit}" >&5
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "${tcl_cv_type_64bit}" >&6; }

printf "%s\n" "no" >&6; }
	# Now check for auxiliary declarations
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit time_t" >&5
printf %s "checking for 64-bit time_t... " >&6; }
if test ${tcl_cv_time_t_64+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/types.h>
int
main (void)
{
switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;}
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_time_t_64=yes
else case e in #(
  e) tcl_cv_time_t_64=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_time_t_64" >&5
printf "%s\n" "$tcl_cv_time_t_64" >&6; }
	if test "x${tcl_cv_time_t_64}" = "xno" ; then
	    # Note that _TIME_BITS=64 requires _FILE_OFFSET_BITS=64
	    # which SC_TCL_EARLY_FLAGS has defined if necessary.
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if _TIME_BITS=64 enables 64-bit time_t" >&5
printf %s "checking if _TIME_BITS=64 enables 64-bit time_t... " >&6; }
if test ${tcl_cv__time_bits+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
		cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#define _TIME_BITS 64
#include <sys/types.h>
int
main (void)
{
switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;}
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv__time_bits=yes
else case e in #(
  e) tcl_cv__time_bits=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv__time_bits" >&5
printf "%s\n" "$tcl_cv__time_bits" >&6; }
	    if test "x${tcl_cv__time_bits}" = "xyes" ; then

printf "%s\n" "#define _TIME_BITS 64" >>confdefs.h

	    fi
	fi

	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct dirent64" >&5
$as_echo_n "checking for struct dirent64... " >&6; }
if ${tcl_cv_struct_dirent64+:} false; then :
  $as_echo_n "(cached) " >&6
else

	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct dirent64" >&5
printf %s "checking for struct dirent64... " >&6; }
if test ${tcl_cv_struct_dirent64+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/types.h>
#include <dirent.h>
int
main ()
main (void)
{
struct dirent64 p;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_struct_dirent64=yes
else
  tcl_cv_struct_dirent64=no
else case e in #(
  e) tcl_cv_struct_dirent64=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_dirent64" >&5
$as_echo "$tcl_cv_struct_dirent64" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_dirent64" >&5
printf "%s\n" "$tcl_cv_struct_dirent64" >&6; }
	if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then

$as_echo "#define HAVE_STRUCT_DIRENT64 1" >>confdefs.h
printf "%s\n" "#define HAVE_STRUCT_DIRENT64 1" >>confdefs.h

	fi

	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DIR64" >&5
$as_echo_n "checking for DIR64... " >&6; }
if ${tcl_cv_DIR64+:} false; then :
  $as_echo_n "(cached) " >&6
else

	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for DIR64" >&5
printf %s "checking for DIR64... " >&6; }
if test ${tcl_cv_DIR64+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/types.h>
#include <dirent.h>
int
main ()
main (void)
{
struct dirent64 *p; DIR64 d = opendir64(".");
            p = readdir64(d); rewinddir64(d); closedir64(d);
	    p = readdir64(d); rewinddir64(d); closedir64(d);
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_DIR64=yes
else
  tcl_cv_DIR64=no
else case e in #(
  e) tcl_cv_DIR64=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_DIR64" >&5
$as_echo "$tcl_cv_DIR64" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_DIR64" >&5
printf "%s\n" "$tcl_cv_DIR64" >&6; }
	if test "x${tcl_cv_DIR64}" = "xyes" ; then

$as_echo "#define HAVE_DIR64 1" >>confdefs.h
printf "%s\n" "#define HAVE_DIR64 1" >>confdefs.h

	fi

	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct stat64" >&5
	ac_fn_c_check_func "$LINENO" "open64" "ac_cv_func_open64"
$as_echo_n "checking for struct stat64... " >&6; }
if ${tcl_cv_struct_stat64+:} false; then :
  $as_echo_n "(cached) " >&6
else

if test "x$ac_cv_func_open64" = xyes
	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/stat.h>
int
main ()
then :
{
struct stat64 p;

  ;
  printf "%s\n" "#define HAVE_OPEN64 1" >>confdefs.h

  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  tcl_cv_struct_stat64=yes
else
  tcl_cv_struct_stat64=no
fi
ac_fn_c_check_func "$LINENO" "lseek64" "ac_cv_func_lseek64"
if test "x$ac_cv_func_lseek64" = xyes
then :
  printf "%s\n" "#define HAVE_LSEEK64 1" >>confdefs.h
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_stat64" >&5
$as_echo "$tcl_cv_struct_stat64" >&6; }
	if test "x${tcl_cv_struct_stat64}" = "xyes" ; then

$as_echo "#define HAVE_STRUCT_STAT64 1" >>confdefs.h

	fi
fi

	for ac_func in open64 lseek64
do :
  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
  cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF

fi
done

	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for off64_t" >&5
$as_echo_n "checking for off64_t... " >&6; }
	if ${tcl_cv_type_off64_t+:} false; then :
  $as_echo_n "(cached) " >&6
else

	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for off64_t" >&5
printf %s "checking for off64_t... " >&6; }
	if test ${tcl_cv_type_off64_t+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/types.h>
int
main ()
main (void)
{
off64_t offset;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_type_off64_t=yes
else
  tcl_cv_type_off64_t=no
else case e in #(
  e) tcl_cv_type_off64_t=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi

			if test "x${tcl_cv_type_off64_t}" = "xyes" && \
	        test "x${ac_cv_func_lseek64}" = "xyes" && \
	        test "x${ac_cv_func_open64}" = "xyes" ; then
		test "x${ac_cv_func_lseek64}" = "xyes" && \
		test "x${ac_cv_func_open64}" = "xyes" ; then

$as_echo "#define HAVE_TYPE_OFF64_T 1" >>confdefs.h
printf "%s\n" "#define HAVE_TYPE_OFF64_T 1" >>confdefs.h

	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
	else
	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
	fi
    fi


#--------------------------------------------------------------------
#	Check endianness because we can optimize comparisons of
#	Tcl_UniChar strings to memcmp on big-endian systems.
#--------------------------------------------------------------------

 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
if ${ac_cv_c_bigendian+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_cv_c_bigendian=unknown
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
printf %s "checking whether byte ordering is bigendian... " >&6; }
if test ${ac_cv_c_bigendian+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_cv_c_bigendian=unknown
    # See if we're dealing with a universal compiler.
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#ifndef __APPLE_CC__
	       not a universal capable compiler
	     #endif
	     typedef int dummy;

_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :

	# Check for potential -arch flags.  It is not universal unless
	# there are at least two -arch flags with different values.
	ac_arch=
	ac_prev=
	for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
	 if test -n "$ac_prev"; then
7209
7210
7211
7212
7213
7214
7215
7216

7217
7218
7219
7220
7221
7222
7223
7224
7225

7226
7227
7228


7229
7230
7231
7232
7233
7234
7235
7236
7237


7238
7239
7240
7241
7242
7243
7244
7245

7246
7247
7248
7249
7250
7251
7252
7253
7254
7255


7256
7257
7258



7259
7260

7261
7262

7263
7264
7265
7266
7267
7268
7269
7270
7271

7272
7273
7274
7275
7276
7277
7278
7279
7280
7281


7282
7283
7284
7285
7286
7287
7288

7289
7290
7291
7292
7293
7294
7295
7296
7297
7298


7299
7300
7301



7302
7303

7304
7305

7306
7307
7308
7309


7310
7311
7312
7313

7314
7315

7316
7317
7318
7319
7320

7321
7322

7323
7324
7325
7326
7327
7328
7329
7330
7331
7332







7333
7334
7335



7336
7337
7338



7339
7340
7341

7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352




7353
7354
7355
7356

7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372


7373
7374
7375



7376
7377
7378


7379
7380
7381


7382
7383
7384


7385
7386
7387

7388
7389
7390
7391
7392

7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407

7408

7409
7410
7411

7412
7413


7414
7415
7416
7417
7418
7419





7420
7421
7422

7423
7424
7425
7426
7427
7428



7429
7430
7431


7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467



7468
7469
7470


7471
7472
7473
7474
7475


7476
7477
7478
7479
7480


7481
7482
7483
7484
7485





7486
7487
7488
7489


7490
7491
7492
7493
7494





7495
7496
7497
7498


7499
7500
7501
7502






7503









7504
7505
7506
7507



7508
7509






7510



7511







7512









7513
7514
7515
7516
7517
7518
7519
7520
7521
7522
7523


7524
7525
7526
7527
7528





7529
7530
7531
7532
7533

7534

7535
7536

7537
7538


7539
7540

7541
7542
7543
7544



7545
7546
7547

7548
7549
7550
7551
7552
7553
7554
7555


7556
7557
7558

7559
7560
7561
7562
7563



7564
7565
7566
7567
7568
7569
7570
7571
7572


7573
7574
7575

7576
7577
7578
7579
7580



7581
7582
7583
7584
7585
7586
7587
7588
7589


7590
7591
7592

7593
7594
7595
7596
7597



7598
7599
7600
7601
7602
7603
7604
7605
7606


7607
7608
7609

7610
7611
7612
7613
7614



7615
7616
7617
7618
7619

7620
7621
7622
7623
7624
7625
7626
7627
7628


7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640


7641
7642
7643
7644
7645
7646
7647







7648
7649
7650
7651
7652
7653
7654
7655

7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669


7670
7671
7672



7673
7674


7675
7676
7677


7678
7679
7680
7681

7682
7683
7684
7685
7686
7687
7688
7689







7690
7691
7692
7693
7694
7695
7696
7697

7698
7699
7700
7701
7702
7703
7704
7705
7706
7707
7708
7709
7710
7711


7712
7713
7714



7715
7716


7717
7718
7719


7720
7721
7722
7723

7724
7725
7726
7727
7728
7729

7730
7731
7732
7733
7734
7735
7736


7737
7738
7739
7740
7741
7742
7743







7744
7745
7746
7747
7748
7749
7750
7751

7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765


7766
7767
7768



7769
7770


7771
7772
7773


7774
7775
7776
7777

7778
7779
7780
7781
7782
7783
7784
7785







7786
7787
7788
7789
7790
7791
7792
7793

7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807


7808
7809
7810



7811
7812


7813
7814
7815


7816
7817
7818
7819

7820
7821
7822
7823
7824
7825

7826
7827
7828
7829
7830
7831
7832


7833
7834
7835
7836
7837
7838
7839







7840
7841
7842
7843
7844
7845
7846
7847

7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861


7862
7863
7864



7865
7866


7867
7868
7869


7870
7871
7872
7873

7874
7875
7876
7877
7878
7879
7880
7881







7882
7883
7884
7885
7886
7887
7888
7889

7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903


7904
7905
7906



7907
7908


7909
7910
7911


7912
7913
7914
7915

7916
7917
7918
7919
7920
7921

7922
7923
7924
7925
7926
7927
7928


7929
7930
7931
7932
7933
7934
7935







7936
7937
7938
7939
7940
7941
7942
7943

7944
7945
7946
7947
7948
7949
7950
7951
7952
7953
7954
7955
7956
7957


7958
7959
7960



7961
7962


7963
7964
7965


7966
7967
7968
7969

7970
7971
7972
7973
7974
7975
7976
7977







7978
7979
7980
7981
7982
7983
7984
7985

7986
7987
7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999


8000
8001
8002



8003
8004


8005
8006
8007


8008
8009
8010
8011

8012
8013
8014
8015
8016
8017

8018
8019
8020
8021
8022
8023
8024
8025
8026
8027
8028
8029

8030
8031
8032

8033
8034
8035
8036
8037
8038
8039
8040
8041

8042
8043
8044

8045
8046
8047
8048
8049
8050
8051
8052




8053
8054
8055



8056
8057
8058
8059

8060
8061


8062
8063
8064
8065



8066
8067
8068
8069
8070
8071
8072


8073
8074
8075
8076
8077
8078
8079







8080
8081
8082
8083
8084
8085
8086

8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101


8102
8103
8104



8105
8106


8107
8108
8109


8110
8111
8112
8113

8114
8115
8116
8117
8118
8119
8120
8121







8122
8123
8124
8125
8126
8127
8128

8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143


8144
8145
8146



8147
8148


8149
8150
8151


8152
8153
8154
8155

8156
8157
8158
8159
8160
8161
8162
8163







8164
8165
8166
8167
8168
8169
8170

8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183


8184
8185
8186



8187
8188


8189
8190
8191


8192
8193
8194
8195

8196
8197
8198
8199
8200
8201
8202

8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213
8214




8215
8216
8217



8218
8219
8220
8221

8222
8223


8224
8225
8226
8227



8228
8229
8230
8231
8232
8233
8234


8235
8236
8237
8238
8239
8240
8241







8242
8243
8244
8245
8246
8247
8248

8249
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260
8261
8262
8263
8264
8265
8266


8267
8268
8269



8270
8271


8272
8273
8274


8275
8276
8277
8278

8279
8280
8281
8282
8283
8284
8285
8286







8287
8288
8289
8290
8291
8292
8293

8294
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
8310
8311


8312
8313
8314



8315
8316


8317
8318
8319


8320
8321
8322
8323

8324
8325
8326
8327
8328
8329

8330
8331
8332
8333
8334
8335
8336
8337
8338
8339
8340
8341
8342
8343
8344
8345
8346
8347
8348
8349
8350
8351


8352
8353


8354
8355
8356
8357
8358
8359
8360
8361
8362
8363


8364
8365


8366
8367
8368
8369
8370
8371
8372
8373
8374
8375


8376
8377


8378
8379
8380
8381
8382
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400







8401
8402
8403
8404
8405

8406
8407
8408
8409
8410
8411
8412


8413
8414
8415



8416
8417


8418
8419
8420


8421
8422
8423
8424
8425
8426
8427
8428







8429
8430
8431
8432
8433
8434
8435


8436
8437
8438



8439
8440
8441



8442
8443
8444


8445
8446
8447

8448
8449
8450
8451
8452
8453
8454






































8455
8456
8457
8458
8459
8460
8461
8462
8463
8464


8465
8466
8467
8468
8469



8470
8471
8472
8473
8474




8475
8476
8477

8478
8479
8480
8481
8482
8483

8484
8485
8486


8487
8488


8489
8490
8491

8492
8493
8494
8495

8496
8497
8498
8499


8500
8501
8502
8503

8504
8505
8506
8507




8508
8509

8510
8511
8512
8513
8514
8515
8516


8517
8518
8519

8520
8521
8522
8523
8524
8525
8526


8527
8528
8529


8530
8531
8532
8533
8534
8535
8536
8537

8538
8539
8540


8541
8542


8543
8544
8545
8546
8547
8548
8549
8550
8551
8552
8553
8554
8555
8556
8557
8558
8559
8560
8561
8562
8563











8564
8565


8566
8567
8568
8569





8570
8571
8572
8573







8574
8575

8576
8577
8578
8579
8580
8581



8582
8583
8584


8585
8586
8587
8588
8589
8590





8591
8592
8593


8594
8595
8596
8597
8598
8599
8600






8601
8602
8603
8604
8605

8606
8607
8608
8609
8610
8611
8612
8613
8614
8615
8616
8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628
8629
8630
8631
8632
8633
8634
8635







8636
8637
8638
8639
8640

8641
8642
8643
8644
8645
8646
8647


8648
8649
8650



8651
8652


8653
8654
8655


8656
8657
8658

8659
8660
8661
8662
8663
8664
8665
8666
8667
8668
8669
8670
8671







8672
8673
8674

8675
8676

8677
8678
8679
8680
8681
8682
8683
8684
8685


8686
8687
8688



8689
8690


8691
8692
8693


8694
8695
8696

8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707







8708
8709
8710

8711
8712

8713
8714
8715
8716
8717
8718
8719
8720
8721


8722
8723
8724



8725
8726


8727
8728
8729


8730
8731
8732

8733
8734
8735
8736
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746


8747
8748
8749

8750
8751
8752
8753
8754
8755


8756
8757
8758
8759









8760
8761
8762
8763
8764
8765
8766


8767
8768
8769

8770
8771
8772
8773
8774
8775
8776


8777
8778
8779
8780



8781
8782
8783
8784
8785
8786
8787
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
8798
8799
8800
8801
8802
8803
8804
8805
8806
8807
8808
8809
8810
8811
8812
8813
8814
8815
8816
8817
8818
8819
8820
8821
8822
8823
8824
8825
8826
8827
8828
8829
8830
8831
8832
8833
8834
8835
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847
8848
8849
8850
8851
8852
8853
8854
8855
8856
8857
8858
8859
8860
8861
8862
8863
8864
8865
8866
8867
8868
8869
8870
8871
8872
8873
8874
8875
8876
8877
8878
8879
8880
8881
8882
8883
8884
8885
8886
8887
8888
8889
8890
8891
8892
8893
8894
8895
8896
8897
8898
8899
8900
8901
8902
8903
8904
8905
8906
8907
8908
8909
8910
8911
8912
8913
8914
8915
8916
8917
8918
8919
8920
8921
8922
8923
8924
8925
8926
8927
8928
8929
8930
8931
8932
8933
8934
8935
8936
8937
8938
8939
8940
8941
8942
8943
8944
8945
8946
8947
8948
8949
8950
8951
8952
8953
8954
8955
8956
8957
8958
8959
8960
8961
8962
8963
8964
8965
8966
8967
8968
8969
8970
8971
8972
8973
8974
8975
8976
8977
8978
8979
8980
8981
8982
8983
8984
8985
8986
8987
8988
8989
8990
8991
8992
8993
8994
8995
8996
8997
8998
8999
9000
9001


9002
9003
9004


9005
9006

9007
9008


9009
9010

9011
9012




9013
9014



9015



9016
9017









9018








9019




9020

9021
9022
9023


9024
9025
9026


9027
9028

9029
9030


9031
9032
9033

9034
9035
9036
9037
9038
9039






9040
9041

9042
9043
9044
9045


9046
9047
9048
9049
9050
9051
9052
9053
9054
9055



9056
9057
9058
9059
9060





9061
9062
9063
9064
9065
9066
9067
9068
9069







9070
9071
9072
9073
9074
9075
9076
9077

9078
9079
9080

9081
9082
9083
9084
9085
9086


9087
9088
9089



9090
9091


9092
9093
9094


9095
9096
9097

9098
9099
9100
9101

9102
9103
9104
9105
9106
9107
9108
9109
9110
9111
9112
9113
9114
9115
9116
9117
9118
9119

9120
9121
9122

9123
9124
9125
9126

9127
9128
9129
9130
9131
9132
9133
9134
9135
9136
9137
9138
9139
9140
9141
9142
9143
9144
9145
9146
9147
9148
9149
9150
9151
9152
9153
9154


9155
9156

9157
9158
9159
9160
9161
9162
9163
9164
9165
9166
9167
9168
9169
9170
9171
9172
9173
9174
9175
9176
9177
9178
9179
9180
9181
9182
9183
9184
9185
9186
9187
9188
9189
9190
9191
9192
9193

9194
9195

9196
9197
9198
9199
9200
9201

9202
9203
9204


9205
9206
9207
9208
9209
9210
9211
9212
9213
9214

9215
9216
9217
9218
9219
9220
9221
9222
9223
9224
9225
9226
9227
9228
9229
9230
9231
9232
9233
9234
9235







9236
9237
9238
9239
9240
9241

9242
9243
9244
9245
9246
9247
9248
9249
9250
9251
9252


9253
9254
9255



9256
9257
9258



9259
9260
9261


9262
9263
9264

9265
9266
9267
9268
9269
9270
9271
9272
9273
9274
9275


9276
9277
9278



9279
9280
9281
9282
9283
9284
9285
9286
9287







9288
9289
9290
9291
9292
9293
9294




9295
9296
9297
9298

9299
9300

9301
9302
9303
9304
9305
9306
9307


9308
9309
9310



9311
9312

9313
9314


9315
9316
9317
9318




9319
9320
9321



9322
9323
9324
9325
9326
9327
9328
9329
9330
9331







9332
9333
9334
9335
9336
9337
9338




9339
9340
9341
9342

9343
9344

9345
9346
9347
9348
9349
9350
9351


9352
9353
9354



9355
9356

9357
9358


9359
9360
9361
9362




9363
9364
9365



9366
9367
9368
9369
9370
9371
9372
8146
8147
8148
8149
8150
8151
8152

8153
8154
8155
8156
8157
8158
8159
8160
8161

8162
8163


8164
8165
8166
8167
8168
8169
8170
8171
8172
8173

8174
8175
8176
8177
8178
8179
8180
8181
8182

8183
8184
8185
8186
8187
8188
8189
8190
8191
8192

8193
8194
8195


8196
8197
8198
8199

8200
8201

8202
8203
8204
8205
8206
8207
8208
8209
8210

8211
8212
8213
8214
8215
8216
8217
8218
8219
8220

8221
8222
8223
8224
8225
8226
8227
8228

8229
8230
8231
8232
8233
8234
8235
8236
8237
8238

8239
8240
8241


8242
8243
8244
8245

8246
8247

8248
8249
8250
8251

8252
8253
8254
8255
8256

8257
8258

8259
8260
8261
8262
8263

8264
8265

8266
8267
8268
8269
8270






8271
8272
8273
8274
8275
8276
8277



8278
8279
8280
8281


8282
8283
8284
8285
8286

8287
8288
8289
8290
8291
8292
8293
8294
8295



8296
8297
8298
8299
8300
8301
8302

8303
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316
8317
8318

8319
8320
8321


8322
8323
8324
8325
8326

8327
8328
8329
8330

8331
8332
8333


8334
8335
8336
8337

8338
8339
8340
8341
8342

8343


8344
8345
8346
8347
8348
8349
8350
8351
8352
8353
8354
8355
8356
8357

8358
8359
8360

8361


8362
8363

8364




8365
8366
8367
8368
8369
8370

8371
8372
8373
8374
8375
8376


8377
8378
8379
8380


8381
8382
8383
8384
8385
8386











8387
8388

8389














8390


8391
8392
8393
8394


8395
8396
8397
8398
8399
8400

8401
8402
8403
8404

8405

8406
8407
8408




8409
8410
8411
8412
8413
8414
8415
8416

8417
8418
8419




8420
8421
8422
8423
8424
8425
8426
8427

8428
8429
8430



8431
8432
8433
8434
8435
8436
8437
8438
8439
8440
8441
8442
8443
8444
8445
8446
8447
8448


8449
8450
8451
8452

8453
8454
8455
8456
8457
8458
8459
8460
8461
8462

8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487
8488
8489

8490
8491
8492




8493
8494
8495
8496
8497
8498
8499
8500
8501
8502
8503

8504
8505

8506
8507

8508
8509
8510

8511
8512
8513


8514
8515
8516
8517

8518
8519
8520
8521
8522
8523
8524
8525
8526

8527
8528
8529


8530

8531
8532


8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543

8544
8545
8546


8547

8548
8549


8550
8551
8552
8553
8554
8555
8556
8557
8558
8559
8560

8561
8562
8563


8564

8565
8566


8567
8568
8569
8570
8571
8572
8573
8574
8575
8576
8577

8578
8579
8580


8581

8582
8583


8584
8585
8586
8587
8588
8589
8590

8591
8592
8593
8594
8595
8596
8597
8598
8599

8600
8601
8602
8603
8604
8605
8606
8607
8608
8609
8610
8611
8612

8613
8614
8615






8616
8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628
8629

8630
8631
8632
8633
8634
8635
8636
8637
8638
8639
8640
8641
8642
8643

8644
8645
8646


8647
8648
8649
8650

8651
8652
8653


8654
8655
8656
8657
8658

8659
8660
8661






8662
8663
8664
8665
8666
8667
8668
8669
8670
8671
8672
8673
8674
8675

8676
8677
8678
8679
8680
8681
8682
8683
8684
8685
8686
8687
8688
8689

8690
8691
8692


8693
8694
8695
8696

8697
8698
8699


8700
8701
8702
8703
8704

8705
8706
8707
8708
8709
8710

8711
8712
8713
8714
8715
8716
8717

8718
8719
8720






8721
8722
8723
8724
8725
8726
8727
8728
8729
8730
8731
8732
8733
8734

8735
8736
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746
8747
8748

8749
8750
8751


8752
8753
8754
8755

8756
8757
8758


8759
8760
8761
8762
8763

8764
8765
8766






8767
8768
8769
8770
8771
8772
8773
8774
8775
8776
8777
8778
8779
8780

8781
8782
8783
8784
8785
8786
8787
8788
8789
8790
8791
8792
8793
8794

8795
8796
8797


8798
8799
8800
8801

8802
8803
8804


8805
8806
8807
8808
8809

8810
8811
8812
8813
8814
8815

8816
8817
8818
8819
8820
8821
8822

8823
8824
8825






8826
8827
8828
8829
8830
8831
8832
8833
8834
8835
8836
8837
8838
8839

8840
8841
8842
8843
8844
8845
8846
8847
8848
8849
8850
8851
8852
8853

8854
8855
8856


8857
8858
8859
8860

8861
8862
8863


8864
8865
8866
8867
8868

8869
8870
8871






8872
8873
8874
8875
8876
8877
8878
8879
8880
8881
8882
8883
8884
8885

8886
8887
8888
8889
8890
8891
8892
8893
8894
8895
8896
8897
8898
8899

8900
8901
8902


8903
8904
8905
8906

8907
8908
8909


8910
8911
8912
8913
8914

8915
8916
8917
8918
8919
8920

8921
8922
8923
8924
8925
8926
8927

8928
8929
8930






8931
8932
8933
8934
8935
8936
8937
8938
8939
8940
8941
8942
8943
8944

8945
8946
8947
8948
8949
8950
8951
8952
8953
8954
8955
8956
8957
8958

8959
8960
8961


8962
8963
8964
8965

8966
8967
8968


8969
8970
8971
8972
8973

8974
8975
8976






8977
8978
8979
8980
8981
8982
8983
8984
8985
8986
8987
8988
8989
8990

8991
8992
8993
8994
8995
8996
8997
8998
8999
9000
9001
9002
9003
9004

9005
9006
9007


9008
9009
9010
9011

9012
9013
9014


9015
9016
9017
9018
9019

9020
9021
9022
9023
9024
9025

9026
9027
9028
9029
9030
9031
9032
9033
9034
9035
9036
9037

9038
9039
9040

9041
9042
9043
9044
9045
9046
9047
9048
9049

9050
9051
9052

9053
9054
9055
9056
9057
9058



9059
9060
9061
9062
9063


9064
9065
9066
9067



9068


9069
9070
9071
9072


9073
9074
9075
9076
9077
9078
9079
9080
9081

9082
9083
9084






9085
9086
9087
9088
9089
9090
9091
9092
9093
9094
9095
9096
9097

9098
9099
9100
9101
9102
9103
9104
9105
9106
9107
9108
9109
9110
9111
9112

9113
9114
9115


9116
9117
9118
9119

9120
9121
9122


9123
9124
9125
9126
9127

9128
9129
9130






9131
9132
9133
9134
9135
9136
9137
9138
9139
9140
9141
9142
9143

9144
9145
9146
9147
9148
9149
9150
9151
9152
9153
9154
9155
9156
9157
9158

9159
9160
9161


9162
9163
9164
9165

9166
9167
9168


9169
9170
9171
9172
9173

9174
9175
9176






9177
9178
9179
9180
9181
9182
9183
9184
9185
9186
9187
9188
9189

9190
9191
9192
9193
9194
9195
9196
9197
9198
9199
9200
9201
9202

9203
9204
9205


9206
9207
9208
9209

9210
9211
9212


9213
9214
9215
9216
9217

9218
9219
9220
9221
9222
9223
9224

9225
9226
9227
9228
9229
9230
9231
9232
9233
9234



9235
9236
9237
9238
9239


9240
9241
9242
9243



9244


9245
9246
9247
9248


9249
9250
9251
9252
9253
9254
9255
9256
9257

9258
9259
9260






9261
9262
9263
9264
9265
9266
9267
9268
9269
9270
9271
9272
9273

9274
9275
9276
9277
9278
9279
9280
9281
9282
9283
9284
9285
9286
9287
9288
9289
9290
9291

9292
9293
9294


9295
9296
9297
9298

9299
9300
9301


9302
9303
9304
9305
9306

9307
9308
9309






9310
9311
9312
9313
9314
9315
9316
9317
9318
9319
9320
9321
9322

9323
9324
9325
9326
9327
9328
9329
9330
9331
9332
9333
9334
9335
9336
9337
9338
9339
9340

9341
9342
9343


9344
9345
9346
9347

9348
9349
9350


9351
9352
9353
9354
9355

9356
9357
9358
9359
9360
9361

9362
9363
9364
9365
9366
9367
9368
9369
9370
9371
9372
9373
9374
9375
9376
9377
9378
9379
9380




9381
9382


9383
9384

9385
9386
9387






9388
9389


9390
9391

9392
9393
9394






9395
9396


9397
9398

9399
9400


9401
9402
9403
9404
9405
9406
9407
9408
9409
9410
9411
9412






9413
9414
9415
9416
9417
9418
9419
9420
9421
9422
9423

9424
9425
9426
9427
9428
9429
9430

9431
9432
9433


9434
9435
9436
9437

9438
9439
9440


9441
9442
9443
9444






9445
9446
9447
9448
9449
9450
9451
9452
9453
9454
9455
9456
9457

9458
9459
9460


9461
9462
9463
9464


9465
9466
9467
9468


9469
9470
9471
9472

9473
9474
9475
9476
9477
9478
9479

9480
9481
9482
9483
9484
9485
9486
9487
9488
9489
9490
9491
9492
9493
9494
9495
9496
9497
9498
9499
9500
9501
9502
9503
9504
9505
9506
9507
9508
9509
9510
9511
9512
9513
9514
9515
9516
9517
9518
9519
9520
9521
9522
9523
9524
9525


9526
9527
9528
9529



9530
9531
9532
9533




9534
9535
9536
9537

9538

9539
9540
9541
9542
9543


9544
9545


9546
9547


9548
9549

9550

9551
9552
9553
9554

9555

9556


9557
9558
9559
9560
9561

9562
9563



9564
9565
9566
9567
9568

9569
9570
9571
9572
9573
9574


9575
9576
9577
9578

9579
9580
9581
9582
9583
9584


9585
9586
9587


9588
9589
9590
9591
9592
9593
9594
9595
9596

9597



9598
9599


9600
9601

9602
9603
9604

9605










9606




9607
9608
9609
9610
9611
9612
9613
9614
9615
9616
9617


9618
9619




9620
9621
9622
9623
9624




9625
9626
9627
9628
9629
9630
9631


9632






9633
9634
9635



9636
9637






9638
9639
9640
9641
9642



9643
9644
9645






9646
9647
9648
9649
9650
9651


9652


9653



















9654


9655
9656






9657
9658
9659
9660
9661
9662
9663
9664
9665
9666
9667

9668
9669
9670
9671
9672
9673
9674

9675
9676
9677


9678
9679
9680
9681

9682
9683
9684


9685
9686
9687
9688

9689
9690
9691
9692
9693
9694
9695
9696






9697
9698
9699
9700
9701
9702
9703
9704
9705
9706
9707
9708

9709
9710
9711
9712
9713
9714
9715
9716
9717

9718
9719
9720


9721
9722
9723
9724

9725
9726
9727


9728
9729
9730
9731

9732
9733
9734
9735
9736
9737






9738
9739
9740
9741
9742
9743
9744
9745
9746
9747
9748
9749

9750
9751
9752
9753
9754
9755
9756
9757
9758

9759
9760
9761


9762
9763
9764
9765

9766
9767
9768


9769
9770
9771
9772

9773
9774
9775
9776
9777
9778
9779
9780
9781
9782
9783
9784
9785
9786

9787
9788
9789


9790

9791
9792
9793
9794

9795
9796
9797



9798
9799
9800
9801
9802
9803
9804
9805
9806
9807
9808
9809
9810
9811
9812

9813
9814
9815


9816

9817
9818
9819
9820
9821

9822
9823
9824



9825
9826
9827



































































9828
9829


































9830












































































































9831
9832
9833
9834
9835
9836
9837
9838

9839
9840
9841


9842
9843


9844


9845
9846
9847
9848
9849


9850
9851
9852
9853
9854

9855
9856
9857
9858
9859
9860
9861


9862
9863
9864
9865
9866
9867
9868
9869
9870
9871
9872
9873
9874
9875
9876
9877
9878
9879
9880
9881
9882
9883
9884
9885
9886
9887
9888

9889
9890
9891


9892
9893


9894


9895
9896
9897
9898

9899






9900
9901
9902
9903
9904
9905


9906




9907
9908




9909





9910
9911
9912

9913



9914
9915
9916
9917
9918
9919
9920
9921






9922
9923
9924
9925
9926
9927
9928
9929
9930
9931
9932
9933
9934
9935

9936
9937
9938

9939
9940
9941
9942
9943
9944

9945
9946
9947


9948
9949
9950
9951

9952
9953
9954


9955
9956
9957
9958

9959
9960
9961
9962

9963


















9964



9965




9966




























9967
9968
9969

9970
9971

9972



























9973






9974


9975



9976


9977



9978
9979






9980



9981

9982

9983
9984
9985
9986
9987
9988
9989
9990
9991
9992
9993
9994






9995
9996
9997
9998
9999
10000
10001
10002
10003
10004
10005
10006

10007
10008
10009
10010
10011
10012
10013
10014
10015
10016
10017

10018
10019
10020


10021
10022
10023
10024


10025
10026
10027
10028


10029
10030
10031
10032

10033
10034
10035
10036
10037
10038
10039
10040
10041
10042
10043

10044
10045
10046


10047
10048
10049
10050
10051
10052






10053
10054
10055
10056
10057
10058
10059
10060
10061
10062
10063
10064
10065

10066
10067
10068
10069
10070
10071
10072

10073
10074

10075
10076
10077
10078
10079
10080
10081

10082
10083
10084


10085
10086
10087
10088

10089
10090

10091
10092
10093



10094
10095
10096
10097
10098


10099
10100
10101
10102
10103
10104
10105






10106
10107
10108
10109
10110
10111
10112
10113
10114
10115
10116
10117
10118

10119
10120
10121
10122
10123
10124
10125

10126
10127

10128
10129
10130
10131
10132
10133
10134

10135
10136
10137


10138
10139
10140
10141

10142
10143

10144
10145
10146



10147
10148
10149
10150
10151


10152
10153
10154
10155
10156
10157
10158
10159
10160
10161







-
+








-
+

-
-
+
+








-
+
+







-
+









-
+
+

-
-
+
+
+

-
+

-
+








-
+









-
+
+






-
+









-
+
+

-
-
+
+
+

-
+

-
+



-
+
+



-
+

-
+




-
+

-
+




-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
+

-
-
+
+
+


-
+








-
-
-
+
+
+
+



-
+















-
+
+

-
-
+
+
+


-
+
+


-
+
+

-
-
+
+


-
+




-
+
-
-













+
-
+


-
+
-
-
+
+
-

-
-
-
-
+
+
+
+
+

-

+




-
-
+
+
+

-
-
+
+




-
-
-
-
-
-
-
-
-
-
-


-

-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
+
+
+

-
-
+
+




-
+
+


-

-
+
+

-
-
-
-
+
+
+
+
+



-
+
+

-
-
-
-
+
+
+
+
+



-
+
+

-
-
-
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+


-
-
+
+
+

-
+
+
+
+
+
+

+
+
+
-
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+










-
+
+

-
-
-
-
+
+
+
+
+





+
-
+

-
+

-
+
+

-
+


-
-
+
+
+

-

+







-
+
+

-
-
+
-


-
-
+
+
+








-
+
+

-
-
+
-


-
-
+
+
+








-
+
+

-
-
+
-


-
-
+
+
+








-
+
+

-
-
+
-


-
-
+
+
+




-
+








-
+
+











-
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+







-
+













-
+
+

-
-
+
+
+

-
+
+

-
-
+
+



-
+


-
-
-
-
-
-
+
+
+
+
+
+
+







-
+













-
+
+

-
-
+
+
+

-
+
+

-
-
+
+



-
+





-
+






-
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+







-
+













-
+
+

-
-
+
+
+

-
+
+

-
-
+
+



-
+


-
-
-
-
-
-
+
+
+
+
+
+
+







-
+













-
+
+

-
-
+
+
+

-
+
+

-
-
+
+



-
+





-
+






-
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+







-
+













-
+
+

-
-
+
+
+

-
+
+

-
-
+
+



-
+


-
-
-
-
-
-
+
+
+
+
+
+
+







-
+













-
+
+

-
-
+
+
+

-
+
+

-
-
+
+



-
+





-
+






-
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+







-
+













-
+
+

-
-
+
+
+

-
+
+

-
-
+
+



-
+


-
-
-
-
-
-
+
+
+
+
+
+
+







-
+













-
+
+

-
-
+
+
+

-
+
+

-
-
+
+



-
+





-
+











-
+


-
+








-
+


-
+





-
-
-
+
+
+
+

-
-
+
+
+

-
-
-
+
-
-
+
+


-
-
+
+
+






-
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+






-
+














-
+
+

-
-
+
+
+

-
+
+

-
-
+
+



-
+


-
-
-
-
-
-
+
+
+
+
+
+
+






-
+














-
+
+

-
-
+
+
+

-
+
+

-
-
+
+



-
+


-
-
-
-
-
-
+
+
+
+
+
+
+






-
+












-
+
+

-
-
+
+
+

-
+
+

-
-
+
+



-
+






-
+









-
-
-
+
+
+
+

-
-
+
+
+

-
-
-
+
-
-
+
+


-
-
+
+
+






-
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+






-
+

















-
+
+

-
-
+
+
+

-
+
+

-
-
+
+



-
+


-
-
-
-
-
-
+
+
+
+
+
+
+






-
+

















-
+
+

-
-
+
+
+

-
+
+

-
-
+
+



-
+





-
+


















-
-
-
-
+
+
-
-
+
+
-



-
-
-
-
-
-
+
+
-
-
+
+
-



-
-
-
-
-
-
+
+
-
-
+
+
-


-
-












-
-
-
-
-
-
+
+
+
+
+
+
+




-
+






-
+
+

-
-
+
+
+

-
+
+

-
-
+
+


-
-
-
-
-
-
+
+
+
+
+
+
+






-
+
+

-
-
+
+
+

-
-
+
+
+

-
-
+
+


-
+






-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
-
+
+


-
-
-
+
+
+

-
-
-
-
+
+
+
+
-

-
+




-
-
+

-
-
+
+
-
-
+
+
-

-
+



-
+
-

-
-
+
+



-
+

-
-
-
+
+
+
+

-
+





-
-
+
+


-
+





-
-
+
+

-
-
+
+







-
+
-
-
-
+
+
-
-
+
+
-



-

-
-
-
-
-
-
-
-
-
-

-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
+
+
+
-
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+

-
-
-
-
-
-
+
+
+
+
+
+
-
-

-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-


-
-
-
-
-
-
+
+
+
+
+
+
+




-
+






-
+
+

-
-
+
+
+

-
+
+

-
-
+
+


-
+







-
-
-
-
-
-
+
+
+
+
+
+
+



+

-
+








-
+
+

-
-
+
+
+

-
+
+

-
-
+
+


-
+





-
-
-
-
-
-
+
+
+
+
+
+
+



+

-
+








-
+
+

-
-
+
+
+

-
+
+

-
-
+
+


-
+













-
+
+

-
-
+
-




-
+
+

-
-
-
+
+
+
+
+
+
+
+
+






-
+
+

-
-
+
-





-
+
+

-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








-
+
+

-
-
+
+
-
-
+
-
-
+
+


+
-
-
+
+
+
+

-
+
+
+

+
+
+
-
-
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+

+


-
+
+

-
-
+
+
-
-
+
-
-
+
+


-
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
-
-
-
-
+
+
-
-
-
-

-
-
-
-
-
+
+
+
-

-
-
-
+
+
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+
+







-
+


-
+





-
+
+

-
-
+
+
+

-
+
+

-
-
+
+


-
+



-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+

-
+

-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
+
-
-
+
-
-
-

-
-
+
-
-
-
+
+
-
-
-
-
-
-

-
-
-
+
-

-












-
-
-
-
-
-
+
+
+
+
+
+
+





-
+










-
+
+

-
-
+
+
+

-
-
+
+
+

-
-
+
+


-
+










-
+
+

-
-
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+
+






-
+
+
+
+



-
+

-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+

-
-
+
+
+




-
-
-
-
-
-
+
+
+
+
+
+
+






-
+
+
+
+



-
+

-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
-
+
+
+
+

-
-
+
+
+







	   esac
	   ac_prev=
	 elif test "x$ac_word" = "x-arch"; then
	   ac_prev=arch
	 fi
       done
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
    if test $ac_cv_c_bigendian = unknown; then
      # See if sys/param.h defines the BYTE_ORDER macro.
      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/types.h>
	     #include <sys/param.h>

int
main ()
main (void)
{
#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
		     && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \\
		     && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \\
		     && LITTLE_ENDIAN)
	      bogus endian macros
	     #endif

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  # It does; now see whether it defined to BIG_ENDIAN or not.
	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/types.h>
		#include <sys/param.h>

int
main ()
main (void)
{
#if BYTE_ORDER != BIG_ENDIAN
		 not big endian
		#endif

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_c_bigendian=yes
else
  ac_cv_c_bigendian=no
else case e in #(
  e) ac_cv_c_bigendian=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
    fi
    if test $ac_cv_c_bigendian = unknown; then
      # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <limits.h>

int
main ()
main (void)
{
#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
	      bogus endian macros
	     #endif

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  # It does; now see whether it defined to _BIG_ENDIAN or not.
	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <limits.h>

int
main ()
main (void)
{
#ifndef _BIG_ENDIAN
		 not big endian
		#endif

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_c_bigendian=yes
else
  ac_cv_c_bigendian=no
else case e in #(
  e) ac_cv_c_bigendian=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
    fi
    if test $ac_cv_c_bigendian = unknown; then
      # Compile a test program.
      if test "$cross_compiling" = yes; then :
      if test "$cross_compiling" = yes
then :
  # Try to guess by grepping values from an object file.
	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
short int ascii_mm[] =
unsigned short int ascii_mm[] =
		  { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
		short int ascii_ii[] =
		unsigned short int ascii_ii[] =
		  { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
		int use_ascii (int i) {
		  return ascii_mm[i] + ascii_ii[i];
		}
		short int ebcdic_ii[] =
		unsigned short int ebcdic_ii[] =
		  { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
		short int ebcdic_mm[] =
		unsigned short int ebcdic_mm[] =
		  { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
		int use_ebcdic (int i) {
		  return ebcdic_mm[i] + ebcdic_ii[i];
		}
		extern int foo;

int
main ()
{
return use_ascii (foo) == use_ebcdic (foo);
		int
		main (int argc, char **argv)
		{
		  /* Intimidate the compiler so that it does not
		     optimize the arrays away.  */
		  char *p = argv[0];
		  ascii_mm[1] = *p++; ebcdic_mm[1] = *p++;
  ;
  return 0;
}
		  ascii_ii[1] = *p++; ebcdic_ii[1] = *p++;
		  return use_ascii (argc) == use_ebcdic (*p);
		}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
if ac_fn_c_try_link "$LINENO"
then :
  if grep BIGenDianSyS conftest$ac_exeext >/dev/null; then
	      ac_cv_c_bigendian=yes
	    fi
	    if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
	    if grep LiTTleEnDian conftest$ac_exeext >/dev/null ; then
	      if test "$ac_cv_c_bigendian" = unknown; then
		ac_cv_c_bigendian=no
	      else
		# finding both strings is unlikely to happen, but who knows?
		ac_cv_c_bigendian=unknown
	      fi
	    fi
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$ac_includes_default
int
main ()
main (void)
{

	     /* Are we little or big endian?  From Harbison&Steele.  */
	     union
	     {
	       long int l;
	       char c[sizeof (long int)];
	     } u;
	     u.l = 1;
	     return u.c[sizeof (long int) - 1] == 1;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
if ac_fn_c_try_run "$LINENO"
then :
  ac_cv_c_bigendian=no
else
  ac_cv_c_bigendian=yes
else case e in #(
  e) ac_cv_c_bigendian=yes ;;
esac
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
  conftest.$ac_objext conftest.beam conftest.$ac_ext
  conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi

    fi
    fi ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
$as_echo "$ac_cv_c_bigendian" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
printf "%s\n" "$ac_cv_c_bigendian" >&6; }
 case $ac_cv_c_bigendian in #(
   yes)
     $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
     printf "%s\n" "#define WORDS_BIGENDIAN 1" >>confdefs.h
;; #(
   no)
      ;; #(
   universal)

     #
$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h

     ;; #(
   *)
     as_fn_error $? "unknown endianness
 presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
 esac


#--------------------------------------------------------------------
#	Supply substitutes for missing POSIX library procedures, or
#	set flags so Tcl uses alternate procedures.
#--------------------------------------------------------------------

# Check if Posix compliant getcwd exists, if not we'll use getwd.

for ac_func in getcwd
  for ac_func in getcwd
do :
  ac_fn_c_check_func "$LINENO" "getcwd" "ac_cv_func_getcwd"
if test "x$ac_cv_func_getcwd" = xyes; then :
if test "x$ac_cv_func_getcwd" = xyes
  cat >>confdefs.h <<_ACEOF
#define HAVE_GETCWD 1
then :
  printf "%s\n" "#define HAVE_GETCWD 1" >>confdefs.h
_ACEOF

else

$as_echo "#define USEGETWD 1" >>confdefs.h

else case e in #(
  e)
printf "%s\n" "#define USEGETWD 1" >>confdefs.h
 ;;
esac
fi
done

done
# Nb: if getcwd uses popen and pwd(1) (like SunOS 4) we should really
# define USEGETWD even if the posix getcwd exists. Add a test ?

ac_fn_c_check_func "$LINENO" "mkstemp" "ac_cv_func_mkstemp"
if test "x$ac_cv_func_mkstemp" = xyes; then :
  $as_echo "#define HAVE_MKSTEMP 1" >>confdefs.h
if test "x$ac_cv_func_mkstemp" = xyes
then :
  printf "%s\n" "#define HAVE_MKSTEMP 1" >>confdefs.h

else
  case " $LIBOBJS " in
else case e in #(
  e) case " $LIBOBJS " in
  *" mkstemp.$ac_objext "* ) ;;
  *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext"
 ;;
esac

fi

ac_fn_c_check_func "$LINENO" "opendir" "ac_cv_func_opendir"
if test "x$ac_cv_func_opendir" = xyes; then :
  $as_echo "#define HAVE_OPENDIR 1" >>confdefs.h

else
  case " $LIBOBJS " in
  *" opendir.$ac_objext "* ) ;;
  *) LIBOBJS="$LIBOBJS opendir.$ac_objext"
 ;;
esac

fi

ac_fn_c_check_func "$LINENO" "strtol" "ac_cv_func_strtol"
if test "x$ac_cv_func_strtol" = xyes; then :
  $as_echo "#define HAVE_STRTOL 1" >>confdefs.h

else
  case " $LIBOBJS " in
  *" strtol.$ac_objext "* ) ;;
  *) LIBOBJS="$LIBOBJS strtol.$ac_objext"
 ;;
esac

fi

ac_fn_c_check_func "$LINENO" "waitpid" "ac_cv_func_waitpid"
if test "x$ac_cv_func_waitpid" = xyes; then :
  $as_echo "#define HAVE_WAITPID 1" >>confdefs.h
if test "x$ac_cv_func_waitpid" = xyes
then :
  printf "%s\n" "#define HAVE_WAITPID 1" >>confdefs.h

else
  case " $LIBOBJS " in
else case e in #(
  e) case " $LIBOBJS " in
  *" waitpid.$ac_objext "* ) ;;
  *) LIBOBJS="$LIBOBJS waitpid.$ac_objext"
 ;;
esac

 ;;
esac
fi


ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror"
if test "x$ac_cv_func_strerror" = xyes; then :
if test "x$ac_cv_func_strerror" = xyes
then :

else

$as_echo "#define NO_STRERROR 1" >>confdefs.h

else case e in #(
  e)
printf "%s\n" "#define NO_STRERROR 1" >>confdefs.h
 ;;
esac
fi

ac_fn_c_check_func "$LINENO" "getwd" "ac_cv_func_getwd"
if test "x$ac_cv_func_getwd" = xyes; then :
if test "x$ac_cv_func_getwd" = xyes
then :

else

$as_echo "#define NO_GETWD 1" >>confdefs.h

else case e in #(
  e)
printf "%s\n" "#define NO_GETWD 1" >>confdefs.h
 ;;
esac
fi

ac_fn_c_check_func "$LINENO" "wait3" "ac_cv_func_wait3"
if test "x$ac_cv_func_wait3" = xyes; then :
if test "x$ac_cv_func_wait3" = xyes
then :

else

$as_echo "#define NO_WAIT3 1" >>confdefs.h
else case e in #(
  e)
printf "%s\n" "#define NO_WAIT3 1" >>confdefs.h
 ;;
esac
fi

ac_fn_c_check_func "$LINENO" "fork" "ac_cv_func_fork"
if test "x$ac_cv_func_fork" = xyes
then :

else case e in #(
  e)
printf "%s\n" "#define NO_FORK 1" >>confdefs.h
 ;;
esac
fi

ac_fn_c_check_func "$LINENO" "uname" "ac_cv_func_uname"
if test "x$ac_cv_func_uname" = xyes; then :
ac_fn_c_check_func "$LINENO" "mknod" "ac_cv_func_mknod"
if test "x$ac_cv_func_mknod" = xyes
then :

else
else case e in #(
  e)
printf "%s\n" "#define NO_MKNOD 1" >>confdefs.h
 ;;
esac
fi

ac_fn_c_check_func "$LINENO" "tcdrain" "ac_cv_func_tcdrain"
if test "x$ac_cv_func_tcdrain" = xyes
then :
$as_echo "#define NO_UNAME 1" >>confdefs.h

else case e in #(
  e)
printf "%s\n" "#define NO_TCDRAIN 1" >>confdefs.h
 ;;
esac
fi

ac_fn_c_check_func "$LINENO" "uname" "ac_cv_func_uname"
if test "x$ac_cv_func_uname" = xyes
then :

else case e in #(
  e)
printf "%s\n" "#define NO_UNAME 1" >>confdefs.h
 ;;
esac
fi


if test "`uname -s`" = "Darwin" && \
	test "`uname -r | awk -F. '{print $1}'`" -lt 7; then
    # prior to Darwin 7, realpath is not threadsafe, so don't
    # use it when threads are enabled, c.f. bug # 711232
    ac_cv_func_realpath=no
fi
ac_fn_c_check_func "$LINENO" "realpath" "ac_cv_func_realpath"
if test "x$ac_cv_func_realpath" = xyes; then :
if test "x$ac_cv_func_realpath" = xyes
then :

else

$as_echo "#define NO_REALPATH 1" >>confdefs.h

else case e in #(
  e)
printf "%s\n" "#define NO_REALPATH 1" >>confdefs.h
 ;;
esac
fi



	NEED_FAKE_RFC2553=0

	for ac_func in getnameinfo getaddrinfo freeaddrinfo gai_strerror
  for ac_func in getnameinfo getaddrinfo freeaddrinfo gai_strerror
do :
  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
  as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | sed "$as_sed_sh"`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
if eval test \"x\$"$as_ac_var"\" = x"yes"
then :
  cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
#define `printf "%s\n" "HAVE_$ac_func" | sed "$as_sed_cpp"` 1
_ACEOF

else
  NEED_FAKE_RFC2553=1
else case e in #(
  e) NEED_FAKE_RFC2553=1 ;;
esac
fi
done

done
	ac_fn_c_check_type "$LINENO" "struct addrinfo" "ac_cv_type_struct_addrinfo" "
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

"
if test "x$ac_cv_type_struct_addrinfo" = xyes; then :
if test "x$ac_cv_type_struct_addrinfo" = xyes
then :

cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_ADDRINFO 1
printf "%s\n" "#define HAVE_STRUCT_ADDRINFO 1" >>confdefs.h
_ACEOF


else
  NEED_FAKE_RFC2553=1
else case e in #(
  e) NEED_FAKE_RFC2553=1 ;;
esac
fi
ac_fn_c_check_type "$LINENO" "struct in6_addr" "ac_cv_type_struct_in6_addr" "
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

"
if test "x$ac_cv_type_struct_in6_addr" = xyes; then :
if test "x$ac_cv_type_struct_in6_addr" = xyes
then :

cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_IN6_ADDR 1
printf "%s\n" "#define HAVE_STRUCT_IN6_ADDR 1" >>confdefs.h
_ACEOF


else
  NEED_FAKE_RFC2553=1
else case e in #(
  e) NEED_FAKE_RFC2553=1 ;;
esac
fi
ac_fn_c_check_type "$LINENO" "struct sockaddr_in6" "ac_cv_type_struct_sockaddr_in6" "
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

"
if test "x$ac_cv_type_struct_sockaddr_in6" = xyes; then :
if test "x$ac_cv_type_struct_sockaddr_in6" = xyes
then :

cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_SOCKADDR_IN6 1
printf "%s\n" "#define HAVE_STRUCT_SOCKADDR_IN6 1" >>confdefs.h
_ACEOF


else
  NEED_FAKE_RFC2553=1
else case e in #(
  e) NEED_FAKE_RFC2553=1 ;;
esac
fi
ac_fn_c_check_type "$LINENO" "struct sockaddr_storage" "ac_cv_type_struct_sockaddr_storage" "
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

"
if test "x$ac_cv_type_struct_sockaddr_storage" = xyes; then :
if test "x$ac_cv_type_struct_sockaddr_storage" = xyes
then :

cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_SOCKADDR_STORAGE 1
printf "%s\n" "#define HAVE_STRUCT_SOCKADDR_STORAGE 1" >>confdefs.h
_ACEOF


else
  NEED_FAKE_RFC2553=1
else case e in #(
  e) NEED_FAKE_RFC2553=1 ;;
esac
fi

if test "x$NEED_FAKE_RFC2553" = "x1"; then

$as_echo "#define NEED_FAKE_RFC2553 1" >>confdefs.h
printf "%s\n" "#define NEED_FAKE_RFC2553 1" >>confdefs.h

   case " $LIBOBJS " in
  *" fake-rfc2553.$ac_objext "* ) ;;
  *) LIBOBJS="$LIBOBJS fake-rfc2553.$ac_objext"
 ;;
esac

   ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy"
if test "x$ac_cv_func_strlcpy" = xyes; then :
if test "x$ac_cv_func_strlcpy" = xyes
then :

fi

fi


#--------------------------------------------------------------------
#	Look for thread-safe variants of some library functions.
#--------------------------------------------------------------------

ac_fn_c_check_func "$LINENO" "getpwuid_r" "ac_cv_func_getpwuid_r"
if test "x$ac_cv_func_getpwuid_r" = xyes; then :
if test "x$ac_cv_func_getpwuid_r" = xyes
then :

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpwuid_r with 5 args" >&5
$as_echo_n "checking for getpwuid_r with 5 args... " >&6; }
if ${tcl_cv_api_getpwuid_r_5+:} false; then :
  $as_echo_n "(cached) " >&6
else

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getpwuid_r with 5 args" >&5
printf %s "checking for getpwuid_r with 5 args... " >&6; }
if test ${tcl_cv_api_getpwuid_r_5+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	#include <sys/types.h>
	#include <pwd.h>

int
main ()
main (void)
{

	uid_t uid;
	struct passwd pw, *pwp;
	char buf[512];
	int buflen = 512;

	(void) getpwuid_r(uid, &pw, buf, buflen, &pwp);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_api_getpwuid_r_5=yes
else
  tcl_cv_api_getpwuid_r_5=no
else case e in #(
  e) tcl_cv_api_getpwuid_r_5=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getpwuid_r_5" >&5
$as_echo "$tcl_cv_api_getpwuid_r_5" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getpwuid_r_5" >&5
printf "%s\n" "$tcl_cv_api_getpwuid_r_5" >&6; }
    tcl_ok=$tcl_cv_api_getpwuid_r_5
    if test "$tcl_ok" = yes; then

$as_echo "#define HAVE_GETPWUID_R_5 1" >>confdefs.h
printf "%s\n" "#define HAVE_GETPWUID_R_5 1" >>confdefs.h

    else
	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpwuid_r with 4 args" >&5
$as_echo_n "checking for getpwuid_r with 4 args... " >&6; }
if ${tcl_cv_api_getpwuid_r_4+:} false; then :
  $as_echo_n "(cached) " >&6
else

	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getpwuid_r with 4 args" >&5
printf %s "checking for getpwuid_r with 4 args... " >&6; }
if test ${tcl_cv_api_getpwuid_r_4+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	    #include <sys/types.h>
	    #include <pwd.h>

int
main ()
main (void)
{

	    uid_t uid;
	    struct passwd pw;
	    char buf[512];
	    int buflen = 512;

	    (void)getpwnam_r(uid, &pw, buf, buflen);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_api_getpwuid_r_4=yes
else
  tcl_cv_api_getpwuid_r_4=no
else case e in #(
  e) tcl_cv_api_getpwuid_r_4=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getpwuid_r_4" >&5
$as_echo "$tcl_cv_api_getpwuid_r_4" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getpwuid_r_4" >&5
printf "%s\n" "$tcl_cv_api_getpwuid_r_4" >&6; }
	tcl_ok=$tcl_cv_api_getpwuid_r_4
	if test "$tcl_ok" = yes; then

$as_echo "#define HAVE_GETPWUID_R_4 1" >>confdefs.h
printf "%s\n" "#define HAVE_GETPWUID_R_4 1" >>confdefs.h

	fi
    fi
    if test "$tcl_ok" = yes; then

$as_echo "#define HAVE_GETPWUID_R 1" >>confdefs.h
printf "%s\n" "#define HAVE_GETPWUID_R 1" >>confdefs.h

    fi

fi

ac_fn_c_check_func "$LINENO" "getpwnam_r" "ac_cv_func_getpwnam_r"
if test "x$ac_cv_func_getpwnam_r" = xyes; then :
if test "x$ac_cv_func_getpwnam_r" = xyes
then :

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpwnam_r with 5 args" >&5
$as_echo_n "checking for getpwnam_r with 5 args... " >&6; }
if ${tcl_cv_api_getpwnam_r_5+:} false; then :
  $as_echo_n "(cached) " >&6
else

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getpwnam_r with 5 args" >&5
printf %s "checking for getpwnam_r with 5 args... " >&6; }
if test ${tcl_cv_api_getpwnam_r_5+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	#include <sys/types.h>
	#include <pwd.h>

int
main ()
main (void)
{

	char *name;
	struct passwd pw, *pwp;
	char buf[512];
	int buflen = 512;

	(void) getpwnam_r(name, &pw, buf, buflen, &pwp);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_api_getpwnam_r_5=yes
else
  tcl_cv_api_getpwnam_r_5=no
else case e in #(
  e) tcl_cv_api_getpwnam_r_5=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getpwnam_r_5" >&5
$as_echo "$tcl_cv_api_getpwnam_r_5" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getpwnam_r_5" >&5
printf "%s\n" "$tcl_cv_api_getpwnam_r_5" >&6; }
    tcl_ok=$tcl_cv_api_getpwnam_r_5
    if test "$tcl_ok" = yes; then

$as_echo "#define HAVE_GETPWNAM_R_5 1" >>confdefs.h
printf "%s\n" "#define HAVE_GETPWNAM_R_5 1" >>confdefs.h

    else
	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpwnam_r with 4 args" >&5
$as_echo_n "checking for getpwnam_r with 4 args... " >&6; }
if ${tcl_cv_api_getpwnam_r_4+:} false; then :
  $as_echo_n "(cached) " >&6
else

	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getpwnam_r with 4 args" >&5
printf %s "checking for getpwnam_r with 4 args... " >&6; }
if test ${tcl_cv_api_getpwnam_r_4+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	    #include <sys/types.h>
	    #include <pwd.h>

int
main ()
main (void)
{

	    char *name;
	    struct passwd pw;
	    char buf[512];
	    int buflen = 512;

	    (void)getpwnam_r(name, &pw, buf, buflen);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_api_getpwnam_r_4=yes
else
  tcl_cv_api_getpwnam_r_4=no
else case e in #(
  e) tcl_cv_api_getpwnam_r_4=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getpwnam_r_4" >&5
$as_echo "$tcl_cv_api_getpwnam_r_4" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getpwnam_r_4" >&5
printf "%s\n" "$tcl_cv_api_getpwnam_r_4" >&6; }
	tcl_ok=$tcl_cv_api_getpwnam_r_4
	if test "$tcl_ok" = yes; then

$as_echo "#define HAVE_GETPWNAM_R_4 1" >>confdefs.h
printf "%s\n" "#define HAVE_GETPWNAM_R_4 1" >>confdefs.h

	fi
    fi
    if test "$tcl_ok" = yes; then

$as_echo "#define HAVE_GETPWNAM_R 1" >>confdefs.h
printf "%s\n" "#define HAVE_GETPWNAM_R 1" >>confdefs.h

    fi

fi

ac_fn_c_check_func "$LINENO" "getgrgid_r" "ac_cv_func_getgrgid_r"
if test "x$ac_cv_func_getgrgid_r" = xyes; then :
if test "x$ac_cv_func_getgrgid_r" = xyes
then :

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgrgid_r with 5 args" >&5
$as_echo_n "checking for getgrgid_r with 5 args... " >&6; }
if ${tcl_cv_api_getgrgid_r_5+:} false; then :
  $as_echo_n "(cached) " >&6
else

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getgrgid_r with 5 args" >&5
printf %s "checking for getgrgid_r with 5 args... " >&6; }
if test ${tcl_cv_api_getgrgid_r_5+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	#include <sys/types.h>
	#include <grp.h>

int
main ()
main (void)
{

	gid_t gid;
	struct group gr, *grp;
	char buf[512];
	int buflen = 512;

	(void) getgrgid_r(gid, &gr, buf, buflen, &grp);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_api_getgrgid_r_5=yes
else
  tcl_cv_api_getgrgid_r_5=no
else case e in #(
  e) tcl_cv_api_getgrgid_r_5=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getgrgid_r_5" >&5
$as_echo "$tcl_cv_api_getgrgid_r_5" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getgrgid_r_5" >&5
printf "%s\n" "$tcl_cv_api_getgrgid_r_5" >&6; }
    tcl_ok=$tcl_cv_api_getgrgid_r_5
    if test "$tcl_ok" = yes; then

$as_echo "#define HAVE_GETGRGID_R_5 1" >>confdefs.h
printf "%s\n" "#define HAVE_GETGRGID_R_5 1" >>confdefs.h

    else
	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgrgid_r with 4 args" >&5
$as_echo_n "checking for getgrgid_r with 4 args... " >&6; }
if ${tcl_cv_api_getgrgid_r_4+:} false; then :
  $as_echo_n "(cached) " >&6
else

	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getgrgid_r with 4 args" >&5
printf %s "checking for getgrgid_r with 4 args... " >&6; }
if test ${tcl_cv_api_getgrgid_r_4+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	    #include <sys/types.h>
	    #include <grp.h>

int
main ()
main (void)
{

	    gid_t gid;
	    struct group gr;
	    char buf[512];
	    int buflen = 512;

	    (void)getgrgid_r(gid, &gr, buf, buflen);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_api_getgrgid_r_4=yes
else
  tcl_cv_api_getgrgid_r_4=no
else case e in #(
  e) tcl_cv_api_getgrgid_r_4=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getgrgid_r_4" >&5
$as_echo "$tcl_cv_api_getgrgid_r_4" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getgrgid_r_4" >&5
printf "%s\n" "$tcl_cv_api_getgrgid_r_4" >&6; }
	tcl_ok=$tcl_cv_api_getgrgid_r_4
	if test "$tcl_ok" = yes; then

$as_echo "#define HAVE_GETGRGID_R_4 1" >>confdefs.h
printf "%s\n" "#define HAVE_GETGRGID_R_4 1" >>confdefs.h

	fi
    fi
    if test "$tcl_ok" = yes; then

$as_echo "#define HAVE_GETGRGID_R 1" >>confdefs.h
printf "%s\n" "#define HAVE_GETGRGID_R 1" >>confdefs.h

    fi

fi

ac_fn_c_check_func "$LINENO" "getgrnam_r" "ac_cv_func_getgrnam_r"
if test "x$ac_cv_func_getgrnam_r" = xyes; then :
if test "x$ac_cv_func_getgrnam_r" = xyes
then :

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgrnam_r with 5 args" >&5
$as_echo_n "checking for getgrnam_r with 5 args... " >&6; }
if ${tcl_cv_api_getgrnam_r_5+:} false; then :
  $as_echo_n "(cached) " >&6
else

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getgrnam_r with 5 args" >&5
printf %s "checking for getgrnam_r with 5 args... " >&6; }
if test ${tcl_cv_api_getgrnam_r_5+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	#include <sys/types.h>
	#include <grp.h>

int
main ()
main (void)
{

	char *name;
	struct group gr, *grp;
	char buf[512];
	int buflen = 512;

	(void) getgrnam_r(name, &gr, buf, buflen, &grp);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_api_getgrnam_r_5=yes
else
  tcl_cv_api_getgrnam_r_5=no
else case e in #(
  e) tcl_cv_api_getgrnam_r_5=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getgrnam_r_5" >&5
$as_echo "$tcl_cv_api_getgrnam_r_5" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getgrnam_r_5" >&5
printf "%s\n" "$tcl_cv_api_getgrnam_r_5" >&6; }
    tcl_ok=$tcl_cv_api_getgrnam_r_5
    if test "$tcl_ok" = yes; then

$as_echo "#define HAVE_GETGRNAM_R_5 1" >>confdefs.h
printf "%s\n" "#define HAVE_GETGRNAM_R_5 1" >>confdefs.h

    else
	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgrnam_r with 4 args" >&5
$as_echo_n "checking for getgrnam_r with 4 args... " >&6; }
if ${tcl_cv_api_getgrnam_r_4+:} false; then :
  $as_echo_n "(cached) " >&6
else

	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getgrnam_r with 4 args" >&5
printf %s "checking for getgrnam_r with 4 args... " >&6; }
if test ${tcl_cv_api_getgrnam_r_4+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	    #include <sys/types.h>
	    #include <grp.h>

int
main ()
main (void)
{

	    char *name;
	    struct group gr;
	    char buf[512];
	    int buflen = 512;

	    (void)getgrnam_r(name, &gr, buf, buflen);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_api_getgrnam_r_4=yes
else
  tcl_cv_api_getgrnam_r_4=no
else case e in #(
  e) tcl_cv_api_getgrnam_r_4=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getgrnam_r_4" >&5
$as_echo "$tcl_cv_api_getgrnam_r_4" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getgrnam_r_4" >&5
printf "%s\n" "$tcl_cv_api_getgrnam_r_4" >&6; }
	tcl_ok=$tcl_cv_api_getgrnam_r_4
	if test "$tcl_ok" = yes; then

$as_echo "#define HAVE_GETGRNAM_R_4 1" >>confdefs.h
printf "%s\n" "#define HAVE_GETGRNAM_R_4 1" >>confdefs.h

	fi
    fi
    if test "$tcl_ok" = yes; then

$as_echo "#define HAVE_GETGRNAM_R 1" >>confdefs.h
printf "%s\n" "#define HAVE_GETGRNAM_R 1" >>confdefs.h

    fi

fi

if test "`uname -s`" = "Darwin" && \
	test "`uname -r | awk -F. '{print $1}'`" -gt 5; then
    # Starting with Darwin 6 (Mac OSX 10.2), gethostbyX
    # are actually MT-safe as they always return pointers
    # from TSD instead of static storage.

$as_echo "#define HAVE_MTSAFE_GETHOSTBYNAME 1" >>confdefs.h
printf "%s\n" "#define HAVE_MTSAFE_GETHOSTBYNAME 1" >>confdefs.h


$as_echo "#define HAVE_MTSAFE_GETHOSTBYADDR 1" >>confdefs.h
printf "%s\n" "#define HAVE_MTSAFE_GETHOSTBYADDR 1" >>confdefs.h


elif test "`uname -s`" = "HP-UX" && \
	test "`uname -r|sed -e 's|B\.||' -e 's|\..*$||'`" -gt 10; then
    # Starting with HPUX 11.00 (we believe), gethostbyX
    # are actually MT-safe as they always return pointers
    # from TSD instead of static storage.

$as_echo "#define HAVE_MTSAFE_GETHOSTBYNAME 1" >>confdefs.h
printf "%s\n" "#define HAVE_MTSAFE_GETHOSTBYNAME 1" >>confdefs.h


$as_echo "#define HAVE_MTSAFE_GETHOSTBYADDR 1" >>confdefs.h
printf "%s\n" "#define HAVE_MTSAFE_GETHOSTBYADDR 1" >>confdefs.h


else

    # Avoids picking hidden internal symbol from libc
    ac_fn_c_check_decl "$LINENO" "gethostbyname_r" "ac_cv_have_decl_gethostbyname_r" "#include <netdb.h>
"
if test "x$ac_cv_have_decl_gethostbyname_r" = xyes; then :
    ac_fn_check_decl "$LINENO" "gethostbyname_r" "ac_cv_have_decl_gethostbyname_r" "#include <netdb.h>
" "$ac_c_undeclared_builtin_options" "CFLAGS"
if test "x$ac_cv_have_decl_gethostbyname_r" = xyes
then :
  ac_have_decl=1
else
  ac_have_decl=0
else case e in #(
  e) ac_have_decl=0 ;;
esac
fi

cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_GETHOSTBYNAME_R $ac_have_decl
printf "%s\n" "#define HAVE_DECL_GETHOSTBYNAME_R $ac_have_decl" >>confdefs.h
_ACEOF
if test $ac_have_decl = 1; then :
if test $ac_have_decl = 1
then :

    tcl_cv_api_gethostbyname_r=yes
else
  tcl_cv_api_gethostbyname_r=no
else case e in #(
  e) tcl_cv_api_gethostbyname_r=no ;;
esac
fi



    if test "$tcl_cv_api_gethostbyname_r" = yes; then
	ac_fn_c_check_func "$LINENO" "gethostbyname_r" "ac_cv_func_gethostbyname_r"
if test "x$ac_cv_func_gethostbyname_r" = xyes; then :
if test "x$ac_cv_func_gethostbyname_r" = xyes
then :

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname_r with 6 args" >&5
$as_echo_n "checking for gethostbyname_r with 6 args... " >&6; }
if ${tcl_cv_api_gethostbyname_r_6+:} false; then :
  $as_echo_n "(cached) " >&6
else

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gethostbyname_r with 6 args" >&5
printf %s "checking for gethostbyname_r with 6 args... " >&6; }
if test ${tcl_cv_api_gethostbyname_r_6+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	#include <netdb.h>

int
main ()
main (void)
{

	char *name;
	struct hostent *he, *res;
	char buffer[2048];
	int buflen = 2048;
	int h_errnop;

	(void) gethostbyname_r(name, he, buffer, buflen, &res, &h_errnop);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_api_gethostbyname_r_6=yes
else
  tcl_cv_api_gethostbyname_r_6=no
else case e in #(
  e) tcl_cv_api_gethostbyname_r_6=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyname_r_6" >&5
$as_echo "$tcl_cv_api_gethostbyname_r_6" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyname_r_6" >&5
printf "%s\n" "$tcl_cv_api_gethostbyname_r_6" >&6; }
    tcl_ok=$tcl_cv_api_gethostbyname_r_6
    if test "$tcl_ok" = yes; then

$as_echo "#define HAVE_GETHOSTBYNAME_R_6 1" >>confdefs.h
printf "%s\n" "#define HAVE_GETHOSTBYNAME_R_6 1" >>confdefs.h

    else
	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname_r with 5 args" >&5
$as_echo_n "checking for gethostbyname_r with 5 args... " >&6; }
if ${tcl_cv_api_gethostbyname_r_5+:} false; then :
  $as_echo_n "(cached) " >&6
else

	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gethostbyname_r with 5 args" >&5
printf %s "checking for gethostbyname_r with 5 args... " >&6; }
if test ${tcl_cv_api_gethostbyname_r_5+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	    #include <netdb.h>

int
main ()
main (void)
{

	    char *name;
	    struct hostent *he;
	    char buffer[2048];
	    int buflen = 2048;
	    int h_errnop;

	    (void) gethostbyname_r(name, he, buffer, buflen, &h_errnop);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_api_gethostbyname_r_5=yes
else
  tcl_cv_api_gethostbyname_r_5=no
else case e in #(
  e) tcl_cv_api_gethostbyname_r_5=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyname_r_5" >&5
$as_echo "$tcl_cv_api_gethostbyname_r_5" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyname_r_5" >&5
printf "%s\n" "$tcl_cv_api_gethostbyname_r_5" >&6; }
	tcl_ok=$tcl_cv_api_gethostbyname_r_5
	if test "$tcl_ok" = yes; then

$as_echo "#define HAVE_GETHOSTBYNAME_R_5 1" >>confdefs.h
printf "%s\n" "#define HAVE_GETHOSTBYNAME_R_5 1" >>confdefs.h

	else
	    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname_r with 3 args" >&5
$as_echo_n "checking for gethostbyname_r with 3 args... " >&6; }
if ${tcl_cv_api_gethostbyname_r_3+:} false; then :
  $as_echo_n "(cached) " >&6
else

	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gethostbyname_r with 3 args" >&5
printf %s "checking for gethostbyname_r with 3 args... " >&6; }
if test ${tcl_cv_api_gethostbyname_r_3+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

		#include <netdb.h>

int
main ()
main (void)
{

		char *name;
		struct hostent *he;
		struct hostent_data data;

		(void) gethostbyname_r(name, he, &data);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_api_gethostbyname_r_3=yes
else
  tcl_cv_api_gethostbyname_r_3=no
else case e in #(
  e) tcl_cv_api_gethostbyname_r_3=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyname_r_3" >&5
$as_echo "$tcl_cv_api_gethostbyname_r_3" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyname_r_3" >&5
printf "%s\n" "$tcl_cv_api_gethostbyname_r_3" >&6; }
	    tcl_ok=$tcl_cv_api_gethostbyname_r_3
	    if test "$tcl_ok" = yes; then

$as_echo "#define HAVE_GETHOSTBYNAME_R_3 1" >>confdefs.h
printf "%s\n" "#define HAVE_GETHOSTBYNAME_R_3 1" >>confdefs.h

	    fi
	fi
    fi
    if test "$tcl_ok" = yes; then

$as_echo "#define HAVE_GETHOSTBYNAME_R 1" >>confdefs.h
printf "%s\n" "#define HAVE_GETHOSTBYNAME_R 1" >>confdefs.h

    fi

fi

    fi


    # Avoids picking hidden internal symbol from libc
    ac_fn_c_check_decl "$LINENO" "gethostbyaddr_r" "ac_cv_have_decl_gethostbyaddr_r" "#include <netdb.h>
"
if test "x$ac_cv_have_decl_gethostbyaddr_r" = xyes; then :
    ac_fn_check_decl "$LINENO" "gethostbyaddr_r" "ac_cv_have_decl_gethostbyaddr_r" "#include <netdb.h>
" "$ac_c_undeclared_builtin_options" "CFLAGS"
if test "x$ac_cv_have_decl_gethostbyaddr_r" = xyes
then :
  ac_have_decl=1
else
  ac_have_decl=0
else case e in #(
  e) ac_have_decl=0 ;;
esac
fi

cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_GETHOSTBYADDR_R $ac_have_decl
printf "%s\n" "#define HAVE_DECL_GETHOSTBYADDR_R $ac_have_decl" >>confdefs.h
_ACEOF
if test $ac_have_decl = 1; then :
if test $ac_have_decl = 1
then :

    tcl_cv_api_gethostbyaddr_r=yes
else
  tcl_cv_api_gethostbyaddr_r=no
else case e in #(
  e) tcl_cv_api_gethostbyaddr_r=no ;;
esac
fi



    if test "$tcl_cv_api_gethostbyaddr_r" = yes; then
	ac_fn_c_check_func "$LINENO" "gethostbyaddr_r" "ac_cv_func_gethostbyaddr_r"
if test "x$ac_cv_func_gethostbyaddr_r" = xyes; then :
if test "x$ac_cv_func_gethostbyaddr_r" = xyes
then :

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyaddr_r with 7 args" >&5
$as_echo_n "checking for gethostbyaddr_r with 7 args... " >&6; }
if ${tcl_cv_api_gethostbyaddr_r_7+:} false; then :
  $as_echo_n "(cached) " >&6
else

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gethostbyaddr_r with 7 args" >&5
printf %s "checking for gethostbyaddr_r with 7 args... " >&6; }
if test ${tcl_cv_api_gethostbyaddr_r_7+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	#include <netdb.h>

int
main ()
main (void)
{

	char *addr;
	int length;
	int type;
	struct hostent *result;
	char buffer[2048];
	int buflen = 2048;
	int h_errnop;

	(void) gethostbyaddr_r(addr, length, type, result, buffer, buflen,
			       &h_errnop);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_api_gethostbyaddr_r_7=yes
else
  tcl_cv_api_gethostbyaddr_r_7=no
else case e in #(
  e) tcl_cv_api_gethostbyaddr_r_7=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyaddr_r_7" >&5
$as_echo "$tcl_cv_api_gethostbyaddr_r_7" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyaddr_r_7" >&5
printf "%s\n" "$tcl_cv_api_gethostbyaddr_r_7" >&6; }
    tcl_ok=$tcl_cv_api_gethostbyaddr_r_7
    if test "$tcl_ok" = yes; then

$as_echo "#define HAVE_GETHOSTBYADDR_R_7 1" >>confdefs.h
printf "%s\n" "#define HAVE_GETHOSTBYADDR_R_7 1" >>confdefs.h

    else
	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyaddr_r with 8 args" >&5
$as_echo_n "checking for gethostbyaddr_r with 8 args... " >&6; }
if ${tcl_cv_api_gethostbyaddr_r_8+:} false; then :
  $as_echo_n "(cached) " >&6
else

	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gethostbyaddr_r with 8 args" >&5
printf %s "checking for gethostbyaddr_r with 8 args... " >&6; }
if test ${tcl_cv_api_gethostbyaddr_r_8+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	    #include <netdb.h>

int
main ()
main (void)
{

	    char *addr;
	    int length;
	    int type;
	    struct hostent *result, *resultp;
	    char buffer[2048];
	    int buflen = 2048;
	    int h_errnop;

	    (void) gethostbyaddr_r(addr, length, type, result, buffer, buflen,
				   &resultp, &h_errnop);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_api_gethostbyaddr_r_8=yes
else
  tcl_cv_api_gethostbyaddr_r_8=no
else case e in #(
  e) tcl_cv_api_gethostbyaddr_r_8=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyaddr_r_8" >&5
$as_echo "$tcl_cv_api_gethostbyaddr_r_8" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyaddr_r_8" >&5
printf "%s\n" "$tcl_cv_api_gethostbyaddr_r_8" >&6; }
	tcl_ok=$tcl_cv_api_gethostbyaddr_r_8
	if test "$tcl_ok" = yes; then

$as_echo "#define HAVE_GETHOSTBYADDR_R_8 1" >>confdefs.h
printf "%s\n" "#define HAVE_GETHOSTBYADDR_R_8 1" >>confdefs.h

	fi
    fi
    if test "$tcl_ok" = yes; then

$as_echo "#define HAVE_GETHOSTBYADDR_R 1" >>confdefs.h
printf "%s\n" "#define HAVE_GETHOSTBYADDR_R 1" >>confdefs.h

    fi

fi

    fi

fi

#---------------------------------------------------------------------------
#	Check for serial port interface.
#
#	termios.h is present on all POSIX systems.
#	sys/ioctl.h is almost always present, though what it contains
#	is system-specific.
#	sys/modem.h is needed on HP-UX.
#---------------------------------------------------------------------------

for ac_header in termios.h
do :
  ac_fn_c_check_header_mongrel "$LINENO" "termios.h" "ac_cv_header_termios_h" "$ac_includes_default"
if test "x$ac_cv_header_termios_h" = xyes; then :
ac_fn_c_check_header_compile "$LINENO" "termios.h" "ac_cv_header_termios_h" "$ac_includes_default"
if test "x$ac_cv_header_termios_h" = xyes
  cat >>confdefs.h <<_ACEOF
#define HAVE_TERMIOS_H 1
then :
  printf "%s\n" "#define HAVE_TERMIOS_H 1" >>confdefs.h
_ACEOF

fi

done

for ac_header in sys/ioctl.h
do :
  ac_fn_c_check_header_mongrel "$LINENO" "sys/ioctl.h" "ac_cv_header_sys_ioctl_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_ioctl_h" = xyes; then :
ac_fn_c_check_header_compile "$LINENO" "sys/ioctl.h" "ac_cv_header_sys_ioctl_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_ioctl_h" = xyes
  cat >>confdefs.h <<_ACEOF
#define HAVE_SYS_IOCTL_H 1
then :
  printf "%s\n" "#define HAVE_SYS_IOCTL_H 1" >>confdefs.h
_ACEOF

fi

done

for ac_header in sys/modem.h
do :
  ac_fn_c_check_header_mongrel "$LINENO" "sys/modem.h" "ac_cv_header_sys_modem_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_modem_h" = xyes; then :
ac_fn_c_check_header_compile "$LINENO" "sys/modem.h" "ac_cv_header_sys_modem_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_modem_h" = xyes
  cat >>confdefs.h <<_ACEOF
#define HAVE_SYS_MODEM_H 1
then :
  printf "%s\n" "#define HAVE_SYS_MODEM_H 1" >>confdefs.h
_ACEOF

fi

done


#--------------------------------------------------------------------
#	Include sys/select.h if it exists and if it supplies things
#	that appear to be useful and aren't already in sys/types.h.
#	This appears to be true only on the RS/6000 under AIX.  Some
#	systems like OSF/1 have a sys/select.h that's of no use, and
#	other systems like SCO UNIX have a sys/select.h that's
#	pernicious.  If "fd_set" isn't defined anywhere then set a
#	special flag.
#--------------------------------------------------------------------

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fd_set in sys/types" >&5
$as_echo_n "checking for fd_set in sys/types... " >&6; }
if ${tcl_cv_type_fd_set+:} false; then :
  $as_echo_n "(cached) " >&6
else

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for fd_set in sys/types" >&5
printf %s "checking for fd_set in sys/types... " >&6; }
if test ${tcl_cv_type_fd_set+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/types.h>
int
main ()
main (void)
{
fd_set readMask, writeMask;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_type_fd_set=yes
else
  tcl_cv_type_fd_set=no
else case e in #(
  e) tcl_cv_type_fd_set=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_type_fd_set" >&5
$as_echo "$tcl_cv_type_fd_set" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_type_fd_set" >&5
printf "%s\n" "$tcl_cv_type_fd_set" >&6; }
tcl_ok=$tcl_cv_type_fd_set
if test $tcl_ok = no; then
    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fd_mask in sys/select" >&5
$as_echo_n "checking for fd_mask in sys/select... " >&6; }
if ${tcl_cv_grep_fd_mask+:} false; then :
  $as_echo_n "(cached) " >&6
else

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for fd_mask in sys/select" >&5
printf %s "checking for fd_mask in sys/select... " >&6; }
if test ${tcl_cv_grep_fd_mask+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/select.h>

_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  $EGREP "fd_mask" >/dev/null 2>&1; then :
  $EGREP_TRADITIONAL "fd_mask" >/dev/null 2>&1
then :
  tcl_cv_grep_fd_mask=present
else
  tcl_cv_grep_fd_mask=missing
else case e in #(
  e) tcl_cv_grep_fd_mask=missing ;;
esac
fi
rm -f conftest*

rm -rf conftest*
 ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_grep_fd_mask" >&5
$as_echo "$tcl_cv_grep_fd_mask" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_grep_fd_mask" >&5
printf "%s\n" "$tcl_cv_grep_fd_mask" >&6; }
    if test $tcl_cv_grep_fd_mask = present; then

$as_echo "#define HAVE_SYS_SELECT_H 1" >>confdefs.h
printf "%s\n" "#define HAVE_SYS_SELECT_H 1" >>confdefs.h

	tcl_ok=yes
    fi
fi
if test $tcl_ok = no; then

$as_echo "#define NO_FD_SET 1" >>confdefs.h
printf "%s\n" "#define NO_FD_SET 1" >>confdefs.h

fi

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pselect" >&5
printf %s "checking for pselect... " >&6; }
if test ${tcl_cv_func_pselect+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/types.h>
int
main (void)
{
void *func = pselect;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_func_pselect=yes
else case e in #(
  e) tcl_cv_func_pselect=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_func_pselect" >&5
printf "%s\n" "$tcl_cv_func_pselect" >&6; }
tcl_ok=$tcl_cv_func_pselect
if test $tcl_ok = yes; then

printf "%s\n" "#define HAVE_PSELECT 1" >>confdefs.h

fi

#------------------------------------------------------------------------
#	Options for the notifier. Checks for epoll(7) on Linux, and
#	kqueue(2) on {DragonFly,Free,Net,Open}BSD
#------------------------------------------------------------------------

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for advanced notifier support" >&5
$as_echo_n "checking for advanced notifier support... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for advanced notifier support" >&5
printf %s "checking for advanced notifier support... " >&6; }
case x`uname -s` in
  xLinux)
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: epoll(7)" >&5
$as_echo "epoll(7)" >&6; }
	for ac_header in sys/epoll.h
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: epoll(7)" >&5
printf "%s\n" "epoll(7)" >&6; }
	       for ac_header in sys/epoll.h
do :
  ac_fn_c_check_header_mongrel "$LINENO" "sys/epoll.h" "ac_cv_header_sys_epoll_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_epoll_h" = xyes; then :
  cat >>confdefs.h <<_ACEOF
#define HAVE_SYS_EPOLL_H 1
  ac_fn_c_check_header_compile "$LINENO" "sys/epoll.h" "ac_cv_header_sys_epoll_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_epoll_h" = xyes
then :
  printf "%s\n" "#define HAVE_SYS_EPOLL_H 1" >>confdefs.h
_ACEOF

$as_echo "#define NOTIFIER_EPOLL 1" >>confdefs.h
printf "%s\n" "#define NOTIFIER_EPOLL 1" >>confdefs.h

fi

done

	for ac_header in sys/eventfd.h
	       for ac_header in sys/eventfd.h
do :
  ac_fn_c_check_header_mongrel "$LINENO" "sys/eventfd.h" "ac_cv_header_sys_eventfd_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_eventfd_h" = xyes; then :
  ac_fn_c_check_header_compile "$LINENO" "sys/eventfd.h" "ac_cv_header_sys_eventfd_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_eventfd_h" = xyes
  cat >>confdefs.h <<_ACEOF
#define HAVE_SYS_EVENTFD_H 1
then :
  printf "%s\n" "#define HAVE_SYS_EVENTFD_H 1" >>confdefs.h
_ACEOF

$as_echo "#define HAVE_EVENTFD 1" >>confdefs.h
printf "%s\n" "#define HAVE_EVENTFD 1" >>confdefs.h

fi

done
done;;
;;
  xDragonFlyBSD|xFreeBSD|xNetBSD|xOpenBSD)
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: kqueue(2)" >&5
$as_echo "kqueue(2)" >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: kqueue(2)" >&5
printf "%s\n" "kqueue(2)" >&6; }
	# Messy because we want to check if *all* the headers are present, and not
	# just *any*
	tcl_kqueue_headers=x
	for ac_header in sys/types.h sys/event.h sys/time.h
	       for ac_header in sys/types.h sys/event.h sys/time.h
do :
  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
  as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | sed "$as_sed_sh"`
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"
then :
  cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
#define `printf "%s\n" "HAVE_$ac_header" | sed "$as_sed_cpp"` 1
_ACEOF
 tcl_kqueue_headers=${tcl_kqueue_headers}y
fi

done

	if test $tcl_kqueue_headers = xyyy; then :
	if test $tcl_kqueue_headers = xyyy
then :


$as_echo "#define NOTIFIER_KQUEUE 1" >>confdefs.h
printf "%s\n" "#define NOTIFIER_KQUEUE 1" >>confdefs.h

fi;;
  xDarwin)
	# Assume that we've got CoreFoundation present (checked elsewhere because
	# of wider impact).
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: OSX" >&5
$as_echo "OSX" >&6; };;
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: OSX" >&5
printf "%s\n" "OSX" >&6; };;
  *)
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
$as_echo "none" >&6; };;
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5
printf "%s\n" "none" >&6; };;
esac

#------------------------------------------------------------------------------
#       Find out all about time handling differences.
#------------------------------------------------------------------------------


    for ac_header in sys/time.h

do :
  ac_fn_c_check_header_mongrel "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_time_h" = xyes; then :
    ac_fn_c_check_header_compile "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_time_h" = xyes
  cat >>confdefs.h <<_ACEOF
#define HAVE_SYS_TIME_H 1
then :
  printf "%s\n" "#define HAVE_SYS_TIME_H 1" >>confdefs.h
_ACEOF

fi

done

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5
$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; }
if ${ac_cv_header_time+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>

int
main ()
{
if ((struct tm *) 0)
    ac_fn_c_check_func "$LINENO" "gmtime_r" "ac_cv_func_gmtime_r"
if test "x$ac_cv_func_gmtime_r" = xyes
then :
  printf "%s\n" "#define HAVE_GMTIME_R 1" >>confdefs.h

fi
ac_fn_c_check_func "$LINENO" "localtime_r" "ac_cv_func_localtime_r"
if test "x$ac_cv_func_localtime_r" = xyes
then :
  printf "%s\n" "#define HAVE_LOCALTIME_R 1" >>confdefs.h

return 0;
  ;
fi

  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking tm_tzadj in struct tm" >&5
printf %s "checking tm_tzadj in struct tm... " >&6; }
if test ${tcl_cv_member_tm_tzadj+y}
then :
  ac_cv_header_time=yes
else
  ac_cv_header_time=no
fi
  printf %s "(cached) " >&6
else case e in #(
  e)
	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <time.h>
int
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
main (void)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5
$as_echo "$ac_cv_header_time" >&6; }
if test $ac_cv_header_time = yes; then

$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h

{
struct tm tm; (void)tm.tm_tzadj;
  ;
fi


  return 0;
}
    for ac_func in gmtime_r localtime_r mktime
do :
  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
  cat >>confdefs.h <<_ACEOF
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_member_tm_tzadj=yes
else case e in #(
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF

  e) tcl_cv_member_tm_tzadj=no ;;
esac
fi
done


    { $as_echo "$as_me:${as_lineno-$LINENO}: checking tm_tzadj in struct tm" >&5
$as_echo_n "checking tm_tzadj in struct tm... " >&6; }
if ${tcl_cv_member_tm_tzadj+:} false; then :
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_member_tm_tzadj" >&5
printf "%s\n" "$tcl_cv_member_tm_tzadj" >&6; }
    if test $tcl_cv_member_tm_tzadj = yes ; then
  $as_echo_n "(cached) " >&6
else

	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
printf "%s\n" "#define HAVE_TM_TZADJ 1" >>confdefs.h
#include <time.h>
int
main ()
{
struct tm tm; tm.tm_tzadj;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  tcl_cv_member_tm_tzadj=yes
else
  tcl_cv_member_tm_tzadj=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_member_tm_tzadj" >&5
$as_echo "$tcl_cv_member_tm_tzadj" >&6; }
    if test $tcl_cv_member_tm_tzadj = yes ; then

$as_echo "#define HAVE_TM_TZADJ 1" >>confdefs.h

    fi

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking tm_gmtoff in struct tm" >&5
$as_echo_n "checking tm_gmtoff in struct tm... " >&6; }
if ${tcl_cv_member_tm_gmtoff+:} false; then :
  $as_echo_n "(cached) " >&6
else

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking tm_gmtoff in struct tm" >&5
printf %s "checking tm_gmtoff in struct tm... " >&6; }
if test ${tcl_cv_member_tm_gmtoff+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <time.h>
int
main ()
main (void)
{
struct tm tm; (void)tm.tm_gmtoff;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_member_tm_gmtoff=yes
else
  tcl_cv_member_tm_gmtoff=no
else case e in #(
  e) tcl_cv_member_tm_gmtoff=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_member_tm_gmtoff" >&5
$as_echo "$tcl_cv_member_tm_gmtoff" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_member_tm_gmtoff" >&5
printf "%s\n" "$tcl_cv_member_tm_gmtoff" >&6; }
    if test $tcl_cv_member_tm_gmtoff = yes ; then

$as_echo "#define HAVE_TM_GMTOFF 1" >>confdefs.h
printf "%s\n" "#define HAVE_TM_GMTOFF 1" >>confdefs.h

    fi

    #
    # Its important to include time.h in this check, as some systems
    # (like convex) have timezone functions, etc.
    #
    { $as_echo "$as_me:${as_lineno-$LINENO}: checking long timezone variable" >&5
$as_echo_n "checking long timezone variable... " >&6; }
if ${tcl_cv_timezone_long+:} false; then :
  $as_echo_n "(cached) " >&6
else

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking long timezone variable" >&5
printf %s "checking long timezone variable... " >&6; }
if test ${tcl_cv_timezone_long+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <time.h>
#include <stdlib.h>
int
main ()
main (void)
{
extern long timezone;
	    timezone += 1;
	    exit (0);
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_timezone_long=yes
else
  tcl_cv_timezone_long=no
else case e in #(
  e) tcl_cv_timezone_long=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_timezone_long" >&5
$as_echo "$tcl_cv_timezone_long" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_timezone_long" >&5
printf "%s\n" "$tcl_cv_timezone_long" >&6; }
    if test $tcl_cv_timezone_long = yes ; then

$as_echo "#define HAVE_TIMEZONE_VAR 1" >>confdefs.h
printf "%s\n" "#define HAVE_TIMEZONE_VAR 1" >>confdefs.h

    else
	#
	# On some systems (eg IRIX 6.2), timezone is a time_t and not a long.
	#
	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking time_t timezone variable" >&5
$as_echo_n "checking time_t timezone variable... " >&6; }
if ${tcl_cv_timezone_time+:} false; then :
  $as_echo_n "(cached) " >&6
else

	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking time_t timezone variable" >&5
printf %s "checking time_t timezone variable... " >&6; }
if test ${tcl_cv_timezone_time+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <time.h>
#include <stdlib.h>
int
main ()
main (void)
{
extern time_t timezone;
		timezone += 1;
		exit (0);
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_timezone_time=yes
else
  tcl_cv_timezone_time=no
else case e in #(
  e) tcl_cv_timezone_time=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_timezone_time" >&5
$as_echo "$tcl_cv_timezone_time" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_timezone_time" >&5
printf "%s\n" "$tcl_cv_timezone_time" >&6; }
	if test $tcl_cv_timezone_time = yes ; then

$as_echo "#define HAVE_TIMEZONE_VAR 1" >>confdefs.h
printf "%s\n" "#define HAVE_TIMEZONE_VAR 1" >>confdefs.h

	fi
    fi


#--------------------------------------------------------------------
#	Some systems (e.g., IRIX 4.0.5) lack some fields in struct stat. But
#	we might be able to use fstatfs instead. Some systems (OpenBSD?) also
#	lack blkcnt_t.
#--------------------------------------------------------------------

if test "$ac_cv_cygwin" != "yes"; then
    ac_fn_c_check_member "$LINENO" "struct stat" "st_blocks" "ac_cv_member_struct_stat_st_blocks" "$ac_includes_default"
if test "x$ac_cv_member_struct_stat_st_blocks" = xyes; then :
if test "x$ac_cv_member_struct_stat_st_blocks" = xyes
then :

cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_STAT_ST_BLOCKS 1
printf "%s\n" "#define HAVE_STRUCT_STAT_ST_BLOCKS 1" >>confdefs.h
_ACEOF


fi
ac_fn_c_check_member "$LINENO" "struct stat" "st_blksize" "ac_cv_member_struct_stat_st_blksize" "$ac_includes_default"
if test "x$ac_cv_member_struct_stat_st_blksize" = xyes; then :
if test "x$ac_cv_member_struct_stat_st_blksize" = xyes
then :

cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
_ACEOF
printf "%s\n" "#define HAVE_STRUCT_STAT_ST_BLKSIZE 1" >>confdefs.h


fi
ac_fn_c_check_member "$LINENO" "struct stat" "st_rdev" "ac_cv_member_struct_stat_st_rdev" "$ac_includes_default"
if test "x$ac_cv_member_struct_stat_st_rdev" = xyes
then :

printf "%s\n" "#define HAVE_STRUCT_STAT_ST_RDEV 1" >>confdefs.h


fi

fi
ac_fn_c_check_type "$LINENO" "blkcnt_t" "ac_cv_type_blkcnt_t" "$ac_includes_default"
if test "x$ac_cv_type_blkcnt_t" = xyes; then :
if test "x$ac_cv_type_blkcnt_t" = xyes
then :

cat >>confdefs.h <<_ACEOF
#define HAVE_BLKCNT_T 1
printf "%s\n" "#define HAVE_BLKCNT_T 1" >>confdefs.h
_ACEOF


fi

ac_fn_c_check_func "$LINENO" "fstatfs" "ac_cv_func_fstatfs"
if test "x$ac_cv_func_fstatfs" = xyes; then :
if test "x$ac_cv_func_fstatfs" = xyes
then :

else

$as_echo "#define NO_FSTATFS 1" >>confdefs.h
else case e in #(
  e)
printf "%s\n" "#define NO_FSTATFS 1" >>confdefs.h

fi


#--------------------------------------------------------------------
#       Some system have no memcmp or it does not work with 8 bit data, this
#       checks it and add memcmp.o to LIBOBJS if needed
#--------------------------------------------------------------------

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working memcmp" >&5
$as_echo_n "checking for working memcmp... " >&6; }
if ${ac_cv_func_memcmp_working+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test "$cross_compiling" = yes; then :
  ac_cv_func_memcmp_working=no
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{

  /* Some versions of memcmp are not 8-bit clean.  */
  char c0 = '\100', c1 = '\200', c2 = '\201';
  if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0)
    return 1;

  /* The Next x86 OpenStep bug shows up only when comparing 16 bytes
     or more and with at least one buffer not starting on a 4-byte boundary.
     William Lewis provided this test program.   */
  {
    char foo[21];
    char bar[21];
    int i;
    for (i = 0; i < 4; i++)
      {
	char *a = foo + i;
	char *b = bar + i;
	strcpy (a, "--------01111111");
	strcpy (b, "--------10000000");
	if (memcmp (a, b, 16) >= 0)
	  return 1;
      }
    return 0;
  }

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
  ac_cv_func_memcmp_working=yes
else
  ac_cv_func_memcmp_working=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
  conftest.$ac_objext conftest.beam conftest.$ac_ext
fi

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_memcmp_working" >&5
$as_echo "$ac_cv_func_memcmp_working" >&6; }
test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in
  *" memcmp.$ac_objext "* ) ;;
  *) LIBOBJS="$LIBOBJS memcmp.$ac_objext"
 ;;
esac



#--------------------------------------------------------------------
#       Some system like SunOS 4 and other BSD like systems have no memmove
#       (we assume they have bcopy instead). {The replacement define is in
#       compat/string.h}
#--------------------------------------------------------------------

ac_fn_c_check_func "$LINENO" "memmove" "ac_cv_func_memmove"
if test "x$ac_cv_func_memmove" = xyes; then :

else


$as_echo "#define NO_MEMMOVE 1" >>confdefs.h


$as_echo "#define NO_STRING_H 1" >>confdefs.h

fi


#--------------------------------------------------------------------
#	On some systems strstr is broken: it returns a pointer even even if
#	the original string is empty.
#--------------------------------------------------------------------


    ac_fn_c_check_func "$LINENO" "strstr" "ac_cv_func_strstr"
if test "x$ac_cv_func_strstr" = xyes; then :
  tcl_ok=1
else
  tcl_ok=0
fi

    if test "$tcl_ok" = 1; then
	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking proper strstr implementation" >&5
$as_echo_n "checking proper strstr implementation... " >&6; }
if ${tcl_cv_strstr_unbroken+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test "$cross_compiling" = yes; then :
  tcl_cv_strstr_unbroken=unknown
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

#include <stdlib.h>
#include <string.h>
int main() {
    exit(strstr("\0test", "test") ? 1 : 0);
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
  tcl_cv_strstr_unbroken=ok
else
  tcl_cv_strstr_unbroken=broken
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
  conftest.$ac_objext conftest.beam conftest.$ac_ext
fi

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_strstr_unbroken" >&5
$as_echo "$tcl_cv_strstr_unbroken" >&6; }
	if test "$tcl_cv_strstr_unbroken" = "ok"; then
	    tcl_ok=1
	else
	    tcl_ok=0
	fi
    fi
    if test "$tcl_ok" = 0; then
	case " $LIBOBJS " in
  *" strstr.$ac_objext "* ) ;;
  *) LIBOBJS="$LIBOBJS strstr.$ac_objext"
 ;;
esac

	USE_COMPAT=1
    fi


#--------------------------------------------------------------------
#	Check for strtoul function.  This is tricky because under some
#	versions of AIX strtoul returns an incorrect terminator
#	pointer for the string "0".
#--------------------------------------------------------------------


    ac_fn_c_check_func "$LINENO" "strtoul" "ac_cv_func_strtoul"
if test "x$ac_cv_func_strtoul" = xyes; then :
  tcl_ok=1
else
  tcl_ok=0
fi

    if test "$tcl_ok" = 1; then
	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking proper strtoul implementation" >&5
$as_echo_n "checking proper strtoul implementation... " >&6; }
if ${tcl_cv_strtoul_unbroken+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test "$cross_compiling" = yes; then :
  tcl_cv_strtoul_unbroken=unknown
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

#include <stdlib.h>
#include <string.h>
int main() {
    char *term, *string = "0";
    exit(strtoul(string,&term,0) != 0 || term != string+1);
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
  tcl_cv_strtoul_unbroken=ok
else
  tcl_cv_strtoul_unbroken=broken
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
  conftest.$ac_objext conftest.beam conftest.$ac_ext
fi

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_strtoul_unbroken" >&5
$as_echo "$tcl_cv_strtoul_unbroken" >&6; }
	if test "$tcl_cv_strtoul_unbroken" = "ok"; then
	    tcl_ok=1
	else
	    tcl_ok=0
	fi
    fi
    if test "$tcl_ok" = 0; then
	case " $LIBOBJS " in
  *" strtoul.$ac_objext "* ) ;;
  *) LIBOBJS="$LIBOBJS strtoul.$ac_objext"
 ;;
esac

	USE_COMPAT=1
    fi


#--------------------------------------------------------------------
#	Check for various typedefs and provide substitutes if
#	they don't exist.
#--------------------------------------------------------------------

ac_fn_c_check_type "$LINENO" "mode_t" "ac_cv_type_mode_t" "$ac_includes_default"
if test "x$ac_cv_type_mode_t" = xyes; then :
if test "x$ac_cv_type_mode_t" = xyes
then :

else

else case e in #(
  e)
cat >>confdefs.h <<_ACEOF
#define mode_t int
printf "%s\n" "#define mode_t int" >>confdefs.h
_ACEOF

 ;;
esac
fi


ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default"
if test "x$ac_cv_type_pid_t" = xyes; then :
  ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default
"
if test "x$ac_cv_type_pid_t" = xyes
then :

else
else case e in #(
  e)                                         cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

          #if defined _WIN64 && !defined __CYGWIN__
          LLP64
          #endif
cat >>confdefs.h <<_ACEOF
#define pid_t int

int
main (void)
{

  ;
  return 0;
}

_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_pid_type='int'
else case e in #(
  e) ac_pid_type='__int64' ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext

printf "%s\n" "#define pid_t $ac_pid_type" >>confdefs.h

     ;;
esac
fi


ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
if test "x$ac_cv_type_size_t" = xyes; then :
if test "x$ac_cv_type_size_t" = xyes
then :

else

else case e in #(
  e)
cat >>confdefs.h <<_ACEOF
#define size_t unsigned int
printf "%s\n" "#define size_t unsigned int" >>confdefs.h
_ACEOF

 ;;
esac
fi

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5
ac_fn_c_check_type "$LINENO" "uid_t" "ac_cv_type_uid_t" "$ac_includes_default"
$as_echo_n "checking for uid_t in sys/types.h... " >&6; }
if ${ac_cv_type_uid_t+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
if test "x$ac_cv_type_uid_t" = xyes
then :

else case e in #(
  e)
printf "%s\n" "#define uid_t int" >>confdefs.h
#include <sys/types.h>

 ;;
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  $EGREP "uid_t" >/dev/null 2>&1; then :
  ac_cv_type_uid_t=yes
esac
fi
else
  ac_cv_type_uid_t=no
fi
rm -f conftest*

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5
$as_echo "$ac_cv_type_uid_t" >&6; }
if test $ac_cv_type_uid_t = no; then

ac_fn_c_check_type "$LINENO" "gid_t" "ac_cv_type_gid_t" "$ac_includes_default"
if test "x$ac_cv_type_gid_t" = xyes
then :
$as_echo "#define uid_t int" >>confdefs.h


$as_echo "#define gid_t int" >>confdefs.h

else case e in #(
  e)
printf "%s\n" "#define gid_t int" >>confdefs.h
 ;;
esac
fi


{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t" >&5
$as_echo_n "checking for socklen_t... " >&6; }
if ${tcl_cv_type_socklen_t+:} false; then :
  $as_echo_n "(cached) " >&6
else

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for socklen_t" >&5
printf %s "checking for socklen_t... " >&6; }
if test ${tcl_cv_type_socklen_t+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	#include <sys/types.h>
	#include <sys/socket.h>

int
main ()
main (void)
{

    	socklen_t foo;
	socklen_t foo;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_type_socklen_t=yes
else
  tcl_cv_type_socklen_t=no
else case e in #(
  e) tcl_cv_type_socklen_t=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_type_socklen_t" >&5
$as_echo "$tcl_cv_type_socklen_t" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_type_socklen_t" >&5
printf "%s\n" "$tcl_cv_type_socklen_t" >&6; }
if test $tcl_cv_type_socklen_t = no; then

$as_echo "#define socklen_t int" >>confdefs.h
printf "%s\n" "#define socklen_t int" >>confdefs.h

fi

ac_fn_c_check_type "$LINENO" "intptr_t" "ac_cv_type_intptr_t" "$ac_includes_default"
ac_fn_c_check_type "$LINENO" "intptr_t" "ac_cv_type_intptr_t" "
if test "x$ac_cv_type_intptr_t" = xyes; then :


$as_echo "#define HAVE_INTPTR_T 1" >>confdefs.h

else

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pointer-size signed integer type" >&5
$as_echo_n "checking for pointer-size signed integer type... " >&6; }
if ${tcl_cv_intptr_t+:} false; then :
  $as_echo_n "(cached) " >&6
else

    for tcl_cv_intptr_t in "int" "long" "long long" none; do
	if test "$tcl_cv_intptr_t" != none; then
	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$ac_includes_default
#include <stdint.h>
int
main ()
{

static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_intptr_t))];
test_array [0] = 0;
return test_array [0];

"
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  tcl_ok=yes
else
  tcl_ok=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
	    test "$tcl_ok" = yes && break; fi
    done
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_intptr_t" >&5
$as_echo "$tcl_cv_intptr_t" >&6; }
    if test "$tcl_cv_intptr_t" != none; then

cat >>confdefs.h <<_ACEOF
#define intptr_t $tcl_cv_intptr_t
_ACEOF

    fi

fi

ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "$ac_includes_default"
if test "x$ac_cv_type_uintptr_t" = xyes; then :

if test "x$ac_cv_type_intptr_t" = xyes
then :

$as_echo "#define HAVE_UINTPTR_T 1" >>confdefs.h
printf "%s\n" "#define HAVE_INTPTR_T 1" >>confdefs.h

else

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pointer-size unsigned integer type" >&5
$as_echo_n "checking for pointer-size unsigned integer type... " >&6; }
if ${tcl_cv_uintptr_t+:} false; then :
  $as_echo_n "(cached) " >&6
else

    for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \
	    none; do
	if test "$tcl_cv_uintptr_t" != none; then
	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_uintptr_t))];
test_array [0] = 0;
return test_array [0];

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  tcl_ok=yes
else
  tcl_ok=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
	    test "$tcl_ok" = yes && break; fi
    done
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_uintptr_t" >&5
$as_echo "$tcl_cv_uintptr_t" >&6; }
ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "
    if test "$tcl_cv_uintptr_t" != none; then

#include <stdint.h>
cat >>confdefs.h <<_ACEOF
#define uintptr_t $tcl_cv_uintptr_t
_ACEOF

    fi

"
fi


if test "x$ac_cv_type_uintptr_t" = xyes
then :
#--------------------------------------------------------------------
#	If a system doesn't have an opendir function (man, that's old!)
#	then we have to supply a different version of dirent.h which
#	is compatible with the substitute version of opendir that's
#	provided.  This version only works with V7-style directories.
#--------------------------------------------------------------------

ac_fn_c_check_func "$LINENO" "opendir" "ac_cv_func_opendir"
if test "x$ac_cv_func_opendir" = xyes; then :

printf "%s\n" "#define HAVE_UINTPTR_T 1" >>confdefs.h
else

$as_echo "#define USE_DIRENT2_H 1" >>confdefs.h

fi


#--------------------------------------------------------------------
#	The check below checks whether <sys/wait.h> defines the type
#	"union wait" correctly.  It's needed because of weirdness in
#	HP-UX where "union wait" is defined in both the BSD and SYS-V
#	environments.  Checking the usability of WIFEXITED seems to do
#	the trick.
#--------------------------------------------------------------------

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking union wait" >&5
$as_echo_n "checking union wait... " >&6; }
if ${tcl_cv_union_wait+:} false; then :
  $as_echo_n "(cached) " >&6
else

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking union wait" >&5
printf %s "checking union wait... " >&6; }
if test ${tcl_cv_union_wait+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/types.h>
#include <sys/wait.h>
int
main ()
main (void)
{

union wait x;
WIFEXITED(x);		/* Generates compiler error if WIFEXITED
			 * uses an int. */

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_union_wait=yes
else
  tcl_cv_union_wait=no
else case e in #(
  e) tcl_cv_union_wait=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_union_wait" >&5
$as_echo "$tcl_cv_union_wait" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_union_wait" >&5
printf "%s\n" "$tcl_cv_union_wait" >&6; }
if test $tcl_cv_union_wait = no; then

$as_echo "#define NO_UNION_WAIT 1" >>confdefs.h
printf "%s\n" "#define NO_UNION_WAIT 1" >>confdefs.h

fi

#--------------------------------------------------------------------
#	Check whether there is an strncasecmp function on this system.
#	This is a bit tricky because under SCO it's in -lsocket and
#	under Sequent Dynix it's in -linet.
#--------------------------------------------------------------------

ac_fn_c_check_func "$LINENO" "strncasecmp" "ac_cv_func_strncasecmp"
if test "x$ac_cv_func_strncasecmp" = xyes; then :
if test "x$ac_cv_func_strncasecmp" = xyes
then :
  tcl_ok=1
else
  tcl_ok=0
else case e in #(
  e) tcl_ok=0 ;;
esac
fi

if test "$tcl_ok" = 0; then
    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for strncasecmp in -lsocket" >&5
$as_echo_n "checking for strncasecmp in -lsocket... " >&6; }
if ${ac_cv_lib_socket_strncasecmp+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_check_lib_save_LIBS=$LIBS
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for strncasecmp in -lsocket" >&5
printf %s "checking for strncasecmp in -lsocket... " >&6; }
if test ${ac_cv_lib_socket_strncasecmp+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lsocket  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
   builtin and then its argument prototype would still apply.
   The 'extern "C"' is for builds by C++ compilers;
   although this is not generally supported in C code supporting it here
   has little cost and some practical benefit (sr 110532).  */
#ifdef __cplusplus
extern "C"
#endif
char strncasecmp ();
char strncasecmp (void);
int
main ()
main (void)
{
return strncasecmp ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_socket_strncasecmp=yes
else
  ac_cv_lib_socket_strncasecmp=no
else case e in #(
  e) ac_cv_lib_socket_strncasecmp=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_strncasecmp" >&5
$as_echo "$ac_cv_lib_socket_strncasecmp" >&6; }
if test "x$ac_cv_lib_socket_strncasecmp" = xyes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_strncasecmp" >&5
printf "%s\n" "$ac_cv_lib_socket_strncasecmp" >&6; }
if test "x$ac_cv_lib_socket_strncasecmp" = xyes
then :
  tcl_ok=1
else
  tcl_ok=0
else case e in #(
  e) tcl_ok=0 ;;
esac
fi

fi
if test "$tcl_ok" = 0; then
    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for strncasecmp in -linet" >&5
$as_echo_n "checking for strncasecmp in -linet... " >&6; }
if ${ac_cv_lib_inet_strncasecmp+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_check_lib_save_LIBS=$LIBS
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for strncasecmp in -linet" >&5
printf %s "checking for strncasecmp in -linet... " >&6; }
if test ${ac_cv_lib_inet_strncasecmp+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_check_lib_save_LIBS=$LIBS
LIBS="-linet  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
   builtin and then its argument prototype would still apply.
   The 'extern "C"' is for builds by C++ compilers;
   although this is not generally supported in C code supporting it here
   has little cost and some practical benefit (sr 110532).  */
#ifdef __cplusplus
extern "C"
#endif
char strncasecmp ();
char strncasecmp (void);
int
main ()
main (void)
{
return strncasecmp ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_inet_strncasecmp=yes
else
  ac_cv_lib_inet_strncasecmp=no
else case e in #(
  e) ac_cv_lib_inet_strncasecmp=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_inet_strncasecmp" >&5
$as_echo "$ac_cv_lib_inet_strncasecmp" >&6; }
if test "x$ac_cv_lib_inet_strncasecmp" = xyes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_inet_strncasecmp" >&5
printf "%s\n" "$ac_cv_lib_inet_strncasecmp" >&6; }
if test "x$ac_cv_lib_inet_strncasecmp" = xyes
then :
  tcl_ok=1
else
  tcl_ok=0
else case e in #(
  e) tcl_ok=0 ;;
esac
fi

fi
if test "$tcl_ok" = 0; then
    case " $LIBOBJS " in
  *" strncasecmp.$ac_objext "* ) ;;
  *) LIBOBJS="$LIBOBJS strncasecmp.$ac_objext"
9382
9383
9384
9385
9386
9387
9388
9389


9390
9391
9392


9393
9394

9395
9396


9397
9398
9399
9400
9401
9402
9403
9404







9405
9406
9407
9408
9409
9410
9411


9412
9413
9414



9415
9416
9417



9418
9419
9420


9421
9422
9423

9424
9425
9426
9427
9428
9429
9430
9431
9432
9433
9434
9435
9436
9437
9438







9439
9440
9441
9442

9443
9444
9445
9446
9447
9448
9449
9450
9451
9452


9453
9454
9455



9456
9457


9458
9459
9460
9461
9462




9463
9464
9465
9466
9467
9468
9469
9470
9471







9472
9473
9474
9475
9476

9477
9478
9479
9480
9481
9482
9483
9484
9485
9486


9487
9488
9489



9490
9491


9492
9493
9494


9495
9496
9497

9498
9499
9500
9501
9502
9503
9504
9505
9506
9507
9508
9509
9510
9511









9512
9513
9514


9515
9516
9517
9518
9519
9520
9521
10171
10172
10173
10174
10175
10176
10177

10178
10179
10180


10181
10182
10183

10184
10185

10186
10187
10188
10189






10190
10191
10192
10193
10194
10195
10196
10197
10198
10199
10200
10201
10202

10203
10204
10205


10206
10207
10208
10209


10210
10211
10212
10213


10214
10215
10216
10217

10218
10219
10220
10221
10222
10223
10224
10225
10226
10227






10228
10229
10230
10231
10232
10233
10234
10235
10236
10237

10238
10239
10240
10241
10242
10243
10244
10245
10246
10247

10248
10249
10250


10251
10252
10253
10254

10255
10256
10257




10258
10259
10260
10261
10262
10263
10264






10265
10266
10267
10268
10269
10270
10271
10272
10273
10274
10275

10276
10277
10278
10279
10280
10281
10282
10283
10284
10285

10286
10287
10288


10289
10290
10291
10292

10293
10294
10295


10296
10297
10298
10299

10300
10301
10302
10303
10304
10305
10306
10307







10308
10309
10310
10311
10312
10313
10314
10315
10316
10317


10318
10319
10320
10321
10322
10323
10324
10325
10326







-
+
+

-
-
+
+

-
+

-
+
+


-
-
-
-
-
-
+
+
+
+
+
+
+






-
+
+

-
-
+
+
+

-
-
+
+
+

-
-
+
+


-
+









-
-
-
-
-
-
+
+
+
+
+
+
+



-
+









-
+
+

-
-
+
+
+

-
+
+

-
-
-
-
+
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+
+




-
+









-
+
+

-
-
+
+
+

-
+
+

-
-
+
+


-
+







-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
+
+







#	   (set NO_GETTOD if this is the case).
#	2. See if gettimeofday is declared in the <sys/time.h> header file.
#	   if not, set the GETTOD_NOT_DECLARED flag so that tclPort.h can
#	   declare it.
#--------------------------------------------------------------------

ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday"
if test "x$ac_cv_func_gettimeofday" = xyes; then :
if test "x$ac_cv_func_gettimeofday" = xyes
then :

else

else case e in #(
  e)

$as_echo "#define NO_GETTOD 1" >>confdefs.h
printf "%s\n" "#define NO_GETTOD 1" >>confdefs.h


 ;;
esac
fi

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gettimeofday declaration" >&5
$as_echo_n "checking for gettimeofday declaration... " >&6; }
if ${tcl_cv_grep_gettimeofday+:} false; then :
  $as_echo_n "(cached) " >&6
else

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gettimeofday declaration" >&5
printf %s "checking for gettimeofday declaration... " >&6; }
if test ${tcl_cv_grep_gettimeofday+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/time.h>

_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  $EGREP "gettimeofday" >/dev/null 2>&1; then :
  $EGREP_TRADITIONAL "gettimeofday" >/dev/null 2>&1
then :
  tcl_cv_grep_gettimeofday=present
else
  tcl_cv_grep_gettimeofday=missing
else case e in #(
  e) tcl_cv_grep_gettimeofday=missing ;;
esac
fi
rm -f conftest*

rm -rf conftest*
 ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_grep_gettimeofday" >&5
$as_echo "$tcl_cv_grep_gettimeofday" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_grep_gettimeofday" >&5
printf "%s\n" "$tcl_cv_grep_gettimeofday" >&6; }
if test $tcl_cv_grep_gettimeofday = missing ; then

$as_echo "#define GETTOD_NOT_DECLARED 1" >>confdefs.h
printf "%s\n" "#define GETTOD_NOT_DECLARED 1" >>confdefs.h

fi

#--------------------------------------------------------------------
#	The following code checks to see whether it is possible to get
#	signed chars on this platform.  This is needed in order to
#	properly generate sign-extended ints from character values.
#--------------------------------------------------------------------

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether char is unsigned" >&5
$as_echo_n "checking whether char is unsigned... " >&6; }
if ${ac_cv_c_char_unsigned+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether char is unsigned" >&5
printf %s "checking whether char is unsigned... " >&6; }
if test ${ac_cv_c_char_unsigned+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$ac_includes_default
int
main ()
main (void)
{
static int test_array [1 - 2 * !(((char) -1) < 0)];
test_array [0] = 0;
return test_array [0];

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_c_char_unsigned=no
else
  ac_cv_c_char_unsigned=yes
else case e in #(
  e) ac_cv_c_char_unsigned=yes ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_char_unsigned" >&5
$as_echo "$ac_cv_c_char_unsigned" >&6; }
if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then
  $as_echo "#define __CHAR_UNSIGNED__ 1" >>confdefs.h
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_char_unsigned" >&5
printf "%s\n" "$ac_cv_c_char_unsigned" >&6; }
if test $ac_cv_c_char_unsigned = yes; then
  printf "%s\n" "#define __CHAR_UNSIGNED__ 1" >>confdefs.h

fi

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking signed char declarations" >&5
$as_echo_n "checking signed char declarations... " >&6; }
if ${tcl_cv_char_signed+:} false; then :
  $as_echo_n "(cached) " >&6
else

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking signed char declarations" >&5
printf %s "checking signed char declarations... " >&6; }
if test ${tcl_cv_char_signed+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

	signed char *p;
	p = 0;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_char_signed=yes
else
  tcl_cv_char_signed=no
else case e in #(
  e) tcl_cv_char_signed=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_char_signed" >&5
$as_echo "$tcl_cv_char_signed" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_char_signed" >&5
printf "%s\n" "$tcl_cv_char_signed" >&6; }
if test $tcl_cv_char_signed = yes; then

$as_echo "#define HAVE_SIGNED_CHAR 1" >>confdefs.h
printf "%s\n" "#define HAVE_SIGNED_CHAR 1" >>confdefs.h

fi

#--------------------------------------------------------------------
#  Does putenv() copy or not?  We need to know to avoid memory leaks.
#--------------------------------------------------------------------

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a putenv() that copies the buffer" >&5
$as_echo_n "checking for a putenv() that copies the buffer... " >&6; }
if ${tcl_cv_putenv_copy+:} false; then :
  $as_echo_n "(cached) " >&6
else

    if test "$cross_compiling" = yes; then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a putenv() that copies the buffer" >&5
printf %s "checking for a putenv() that copies the buffer... " >&6; }
if test ${tcl_cv_putenv_copy+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
    if test "$cross_compiling" = yes
then :
  tcl_cv_putenv_copy=no
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	#include <stdlib.h>
	#include <string.h>
	#define OURVAR "havecopy=yes"
	int main (int argc, char *argv[])
	{
9530
9531
9532
9533
9534
9535
9536
9537


9538
9539
9540



9541
9542
9543


9544
9545


9546
9547
9548


9549
9550
9551

9552
9553
9554
9555
9556
9557
9558
9559
9560
9561


9562
9563
9564



9565
9566
9567
9568
9569
9570
9571



9572
9573
9574



9575
9576
9577
9578
9579
9580


9581
9582
9583
9584
9585





9586
9587
9588
9589
9590

9591
9592
9593
9594
9595
9596
9597


9598
9599
9600



9601
9602


9603
9604
9605
9606


9607
9608
9609

9610
9611
9612
9613
9614


9615
9616
9617
9618
9619
9620
9621
9622
9623
9624
9625
9626
9627




9628
9629
9630
9631
9632
9633
9634


9635
9636
9637
9638

9639
9640
9641
9642
9643
9644

9645
9646
9647
9648
9649
9650

9651
9652
9653
9654
9655
9656
9657
9658
9659
9660
9661
9662
9663
9664
9665
9666

9667
9668
9669
9670



9671
9672

9673
9674
9675
9676
9677
9678
9679
9680
9681
9682


9683
9684


9685
9686
9687
9688
9689
9690
9691
9692
9693


9694
9695


9696
9697
9698
9699
9700
9701
9702
9703
9704
9705


9706
9707


9708
9709
9710
9711
9712
9713
9714
9715
9716
9717


9718
9719


9720
9721
9722
9723
9724
9725
9726
9727
9728
9729


9730
9731


9732
9733
9734
9735
9736
9737
9738
9739
9740
9741
9742

9743
9744
9745

9746
9747
9748
9749
9750


9751
9752


9753
9754
9755
9756
9757
9758
9759
9760
9761
9762
9763
9764
9765







9766
9767
9768
9769
9770
9771
9772
9773
9774
9775
9776
9777
9778
9779
9780

9781
9782
9783
9784
9785
9786
9787


9788
9789
9790



9791
9792

9793
9794


9795
9796
9797


9798
9799
9800

9801
9802
9803
9804
9805
9806
9807
9808







9809
9810
9811
9812
9813
9814
9815
9816
9817
9818
9819
9820
9821
9822
9823
9824

9825
9826
9827
9828
9829
9830
9831


9832
9833
9834



9835
9836
9837



9838
9839
9840


9841
9842
9843

9844
9845
9846
9847
9848
9849
9850
9851
9852
9853
9854
9855
9856
9857
9858
9859
9860
9861
9862
9863
9864







9865
9866
9867
9868
9869
9870
9871
9872
9873

9874
9875
9876
9877
9878
9879
9880
9881
9882
9883
9884


9885
9886
9887



9888
9889
9890



9891
9892
9893


9894
9895
9896

9897
9898
9899
9900
9901
9902
9903
9904
9905
9906
9907
9908
9909
9910


9911
9912


9913
9914
9915
9916
9917
9918
9919
9920
9921
9922


9923
9924


9925
9926
9927
9928
9929
9930
9931
9932
9933
9934
9935
9936
9937







9938
9939
9940
9941
9942
9943
9944


9945
9946
9947
9948
9949
9950
9951
9952
9953
9954
9955


9956
9957
9958


9959
9960
9961
9962


9963
9964
9965
9966

9967
9968
9969


9970
9971
9972
9973


9974
9975
9976
9977
9978
9979
9980
9981


9982
9983


9984
9985
9986



9987
9988
9989
9990
9991

9992
9993
9994
9995


9996
9997
9998
9999
10000
10001
10002
10003
10004


10005
10006
10007


10008
10009
10010



10011
10012
10013
10014
10015
10016
10017
10018
10019
10020


10021
10022
10023
10024
10025
10026
10027
10028
10029





10030
10031
10032
10033
10034
10035
10036
10037
10038
10039


10040
10041
10042
10043
10044
10045


10046
10047
10048
10049
10050
10051
10052
10053
10054
10055
10056
10057


10058
10059
10060
10061
10062
10063
10064
10065
10066


10067
10068
10069



10070
10071
10072
10073
10074



10075
10076
10077



10078
10079
10080
10081
10082
10083
10084
10085
10086
10087
10088
10089
10090







10091
10092
10093
10094
10095
10096
10097
10098
10099

10100




10101
10102
10103
10104



10105
10106
10107
10108
10109
10110
10111

10112
10113
10114
10115
10116
10117


10118
10119
10120


10121
10122
10123
10124
10125
10126
10127


10128
10129
10130
10131

10132
10133
10134
10135
10136
10137
10138
10139
10140
10141
10142
10143
10144
10145
10146
10147
10148
10149
10150


10151
10152
10153
10154
10155
10156
10157
10158
10159
10160
10161
10162
10163
10164
10165
10166
10167
10168
10169
10170
10171
10172
10173
10174
10175
10176
10177
10178
10179
10180
10181
10182
10183
10184
10185
10186
10187
10188
10189
10190
10191
10192
10193
10194
10195
10196
10197
10198
10199
10200
10201
10202
10203
10204
10205
10206
10207
10208
10209
10210
10211
10212
10213
10214
10215
10216
10217
10218
10219
10220
10221
10222
10223
10224
10225
10226
10227
10228
10229
10230
10231
10232
10233
10234
10235
10236
10237
10238
10239
10240
10241
10242
10243
10244
10245
10246
10247
10248
10249
10250
10251
10252
10253
10254
10255
10256
10257
10258
10259
10260
10261
10262
10263
10264
10265
10266
10267
10268
10269
10270
10271
10272
10273
10274
10275
10276
10277
10278
10279
10280
10281
10282
10283
10284
10285
10286
10287
10288
10289
10290
10291
10292
10293
10294
10295
10296
10297
10298
10299
10300
10301
10302
10303
10304
10305
10306
10307
10308
10309
10310
10311
10312
10313
10314
10315
10316
10317
10318
10319
10320
10321
10322
10323
10324
10325
10326







10327
10328
10329
10330
10331

10332
10333
10334
10335
10336
10337
10338
10339
10340





10341
10342
10343
10344
10345
10346


10347
10348
10349



10350
10351
10352



10353
10354
10355


10356
10357
10358

10359
10360
10361
10362
10363
10364
10365
10335
10336
10337
10338
10339
10340
10341

10342
10343
10344


10345
10346
10347
10348
10349

10350
10351
10352

10353
10354
10355


10356
10357
10358
10359

10360
10361
10362
10363
10364
10365
10366
10367
10368
10369

10370
10371
10372


10373
10374
10375
10376
10377
10378
10379
10380


10381
10382
10383
10384


10385
10386
10387
10388
10389

10390


10391
10392
10393




10394
10395
10396
10397
10398
10399
10400
10401
10402

10403
10404
10405
10406
10407
10408
10409

10410
10411
10412


10413
10414
10415
10416

10417
10418
10419
10420


10421
10422
10423
10424

10425
10426
10427
10428


10429
10430
10431
10432
10433
10434
10435
10436
10437






10438
10439
10440
10441


10442
10443



10444
10445




10446






10447






10448











10449




10450




10451
10452
10453
10454
10455
10456
10457
10458
10459
10460
10461
10462




10463
10464


10465
10466

10467
10468

10469




10470
10471


10472
10473

10474
10475
10476






10477
10478


10479
10480

10481
10482

10483
10484




10485
10486


10487
10488

10489
10490
10491






10492
10493


10494
10495

10496
10497

10498
10499
10500




10501
10502
10503

10504
10505




10506
10507


10508
10509

10510
10511


10512
10513






10514
10515
10516
10517
10518
10519
10520
10521
10522
10523
10524
10525
10526
10527
10528
10529
10530
10531
10532
10533
10534

10535
10536
10537
10538
10539
10540
10541

10542
10543
10544


10545
10546
10547
10548

10549
10550

10551
10552
10553


10554
10555
10556
10557

10558
10559
10560






10561
10562
10563
10564
10565
10566
10567
10568
10569
10570
10571
10572
10573
10574
10575
10576
10577
10578
10579
10580
10581
10582

10583
10584
10585
10586
10587
10588
10589

10590
10591
10592


10593
10594
10595
10596


10597
10598
10599
10600


10601
10602
10603
10604

10605
10606
10607
10608
10609
10610
10611
10612
10613
10614
10615
10616
10617
10618
10619
10620






10621
10622
10623
10624
10625
10626
10627
10628
10629
10630
10631
10632
10633
10634
10635

10636
10637
10638
10639
10640
10641
10642
10643
10644
10645
10646

10647
10648
10649


10650
10651
10652
10653


10654
10655
10656
10657


10658
10659
10660
10661

10662
10663
10664
10665
10666
10667
10668
10669
10670
10671
10672




10673
10674


10675
10676

10677
10678
10679






10680
10681


10682
10683

10684
10685
10686

10687







10688
10689
10690
10691
10692
10693
10694
10695
10696
10697
10698
10699


10700
10701
10702
10703
10704
10705
10706
10707
10708
10709
10710
10711

10712
10713
10714


10715
10716
10717
10718


10719
10720
10721
10722
10723

10724
10725


10726
10727
10728
10729


10730
10731
10732
10733
10734
10735
10736
10737


10738
10739
10740

10741
10742
10743


10744
10745
10746
10747
10748
10749
10750

10751
10752
10753


10754
10755
10756
10757
10758
10759
10760
10761
10762


10763
10764
10765
10766

10767
10768
10769


10770
10771
10772
10773
10774
10775
10776
10777
10778
10779
10780


10781
10782
10783
10784
10785
10786
10787




10788
10789
10790
10791
10792
10793
10794
10795
10796
10797
10798
10799
10800
10801

10802
10803
10804
10805
10806
10807


10808
10809
10810
10811
10812
10813
10814
10815
10816
10817
10818
10819


10820
10821
10822
10823
10824
10825
10826
10827
10828
10829

10830
10831
10832


10833
10834
10835
10836
10837
10838


10839
10840
10841
10842


10843
10844
10845
10846

10847
10848
10849
10850
10851






10852
10853
10854
10855
10856
10857
10858
10859
10860
10861
10862
10863
10864
10865
10866
10867
10868

10869
10870
10871
10872
10873



10874
10875
10876
10877
10878
10879
10880
10881
10882
10883
10884
10885
10886
10887
10888


10889
10890
10891


10892
10893
10894
10895
10896
10897
10898


10899
10900
10901
10902
10903

10904
10905
10906
10907
10908
10909
10910
10911
10912
10913
10914
10915
10916
10917
10918
10919
10920
10921


10922
10923





































































































































































10924
10925
10926
10927
10928






10929
10930
10931
10932
10933
10934
10935
10936
10937
10938
10939

10940
10941
10942
10943
10944





10945
10946
10947
10948
10949
10950
10951
10952
10953
10954

10955
10956
10957


10958
10959
10960
10961


10962
10963
10964
10965


10966
10967
10968
10969

10970
10971
10972
10973
10974
10975
10976
10977







-
+
+

-
-
+
+
+


-
+
+

-
+
+

-
-
+
+


-
+









-
+
+

-
-
+
+
+





-
-
+
+
+

-
-
+
+
+


-

-
-
+
+

-
-
-
-
+
+
+
+
+




-
+






-
+
+

-
-
+
+
+

-
+
+


-
-
+
+


-
+



-
-
+
+







-
-
-
-
-
-
+
+
+
+
-
-


-
-
-
+
+
-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
+
-
-
-
-
+
+
+


+






-
-
-
-
+
+
-
-
+
+
-


-

-
-
-
-
+
+
-
-
+
+
-



-
-
-
-
-
-
+
+
-
-
+
+
-


-


-
-
-
-
+
+
-
-
+
+
-



-
-
-
-
-
-
+
+
-
-
+
+
-


-



-
-
-
-
+


-
+

-
-
-
-
+
+
-
-
+
+
-


-
-


-
-
-
-
-
-
+
+
+
+
+
+
+














-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
+
+


-
+


-
-
-
-
-
-
+
+
+
+
+
+
+















-
+






-
+
+

-
-
+
+
+

-
-
+
+
+

-
-
+
+


-
+















-
-
-
-
-
-
+
+
+
+
+
+
+








-
+










-
+
+

-
-
+
+
+

-
-
+
+
+

-
-
+
+


-
+










-
-
-
-
+
+
-
-
+
+
-



-
-
-
-
-
-
+
+
-
-
+
+
-



-

-
-
-
-
-
-
-
+
+
+
+
+
+
+





-
-
+
+










-
+
+

-
-
+
+


-
-
+
+



-
+

-
-
+
+


-
-
+
+






-
-
+
+

-
+
+

-
-
+
+
+




-
+


-
-
+
+







-
-
+
+


-
+
+

-
-
+
+
+








-
-
+
+





-
-
-
-
+
+
+
+
+









-
+
+




-
-
+
+










-
-
+
+








-
+
+

-
-
+
+
+



-
-
+
+
+

-
-
+
+
+

-





-
-
-
-
-
-
+
+
+
+
+
+
+









+
-
+
+
+
+

-
-
-
+
+
+







+




-
-
+
+

-
-
+
+





-
-
+
+



-
+

















-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-





-
-
-
-
-
-
+
+
+
+
+
+
+




-
+




-
-
-
-
-
+
+
+
+
+





-
+
+

-
-
+
+
+

-
-
+
+
+

-
-
+
+


-
+







	    } else {
		/* does copy */
		return 1;
	    }
	}

_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
if ac_fn_c_try_run "$LINENO"
then :
  tcl_cv_putenv_copy=no
else
  tcl_cv_putenv_copy=yes
else case e in #(
  e) tcl_cv_putenv_copy=yes ;;
esac
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
  conftest.$ac_objext conftest.beam conftest.$ac_ext
  conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi

 ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_putenv_copy" >&5
$as_echo "$tcl_cv_putenv_copy" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_putenv_copy" >&5
printf "%s\n" "$tcl_cv_putenv_copy" >&6; }
if test $tcl_cv_putenv_copy = yes; then

$as_echo "#define HAVE_PUTENV_THAT_COPIES 1" >>confdefs.h
printf "%s\n" "#define HAVE_PUTENV_THAT_COPIES 1" >>confdefs.h

fi

#--------------------------------------------------------------------
# Check for support of nl_langinfo function
#--------------------------------------------------------------------


    # Check whether --enable-langinfo was given.
if test "${enable_langinfo+set}" = set; then :
if test ${enable_langinfo+y}
then :
  enableval=$enable_langinfo; langinfo_ok=$enableval
else
  langinfo_ok=yes
else case e in #(
  e) langinfo_ok=yes ;;
esac
fi


    HAVE_LANGINFO=0
    if test "$langinfo_ok" = "yes"; then
	ac_fn_c_check_header_mongrel "$LINENO" "langinfo.h" "ac_cv_header_langinfo_h" "$ac_includes_default"
if test "x$ac_cv_header_langinfo_h" = xyes; then :
	ac_fn_c_check_header_compile "$LINENO" "langinfo.h" "ac_cv_header_langinfo_h" "$ac_includes_default"
if test "x$ac_cv_header_langinfo_h" = xyes
then :
  langinfo_ok=yes
else
  langinfo_ok=no
else case e in #(
  e) langinfo_ok=no ;;
esac
fi


    fi
    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use nl_langinfo" >&5
$as_echo_n "checking whether to use nl_langinfo... " >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to use nl_langinfo" >&5
printf %s "checking whether to use nl_langinfo... " >&6; }
    if test "$langinfo_ok" = "yes"; then
	if ${tcl_cv_langinfo_h+:} false; then :
  $as_echo_n "(cached) " >&6
else

	if test ${tcl_cv_langinfo_h+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <langinfo.h>
int
main ()
main (void)
{
nl_langinfo(CODESET);
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_langinfo_h=yes
else
  tcl_cv_langinfo_h=no
else case e in #(
  e) tcl_cv_langinfo_h=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi

	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_langinfo_h" >&5
$as_echo "$tcl_cv_langinfo_h" >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_langinfo_h" >&5
printf "%s\n" "$tcl_cv_langinfo_h" >&6; }
	if test $tcl_cv_langinfo_h = yes; then

$as_echo "#define HAVE_LANGINFO 1" >>confdefs.h
printf "%s\n" "#define HAVE_LANGINFO 1" >>confdefs.h

	fi
    else
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $langinfo_ok" >&5
$as_echo "$langinfo_ok" >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $langinfo_ok" >&5
printf "%s\n" "$langinfo_ok" >&6; }
    fi


#--------------------------------------------------------------------
# Check for support of cfmakeraw, chflags and mkstemps functions
#--------------------------------------------------------------------

for ac_func in cfmakeraw chflags mkstemps
do :
  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
  cat >>confdefs.h <<_ACEOF
ac_fn_c_check_func "$LINENO" "cfmakeraw" "ac_cv_func_cfmakeraw"
if test "x$ac_cv_func_cfmakeraw" = xyes
then :
  printf "%s\n" "#define HAVE_CFMAKERAW 1" >>confdefs.h
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF

fi
done


ac_fn_c_check_func "$LINENO" "chflags" "ac_cv_func_chflags"
if test "x$ac_cv_func_chflags" = xyes
#--------------------------------------------------------------------
# Check for support of isnan() function or macro
#--------------------------------------------------------------------

then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking isnan" >&5
$as_echo_n "checking isnan... " >&6; }
if ${tcl_cv_isnan+:} false; then :
  $as_echo_n "(cached) " >&6
else

  printf "%s\n" "#define HAVE_CHFLAGS 1" >>confdefs.h
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <math.h>
int
main ()
{


isnan(0.0);			/* Generates an error if isnan is missing */

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
  tcl_cv_isnan=yes
else
  tcl_cv_isnan=no
fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_isnan" >&5
ac_fn_c_check_func "$LINENO" "mkstemps" "ac_cv_func_mkstemps"
$as_echo "$tcl_cv_isnan" >&6; }
if test $tcl_cv_isnan = no; then

$as_echo "#define NO_ISNAN 1" >>confdefs.h
if test "x$ac_cv_func_mkstemps" = xyes
then :
  printf "%s\n" "#define HAVE_MKSTEMPS 1" >>confdefs.h

fi


#--------------------------------------------------------------------
# Darwin specific API checks and defines
#--------------------------------------------------------------------

if test "`uname -s`" = "Darwin" ; then
    for ac_func in getattrlist
do :
  ac_fn_c_check_func "$LINENO" "getattrlist" "ac_cv_func_getattrlist"
if test "x$ac_cv_func_getattrlist" = xyes; then :
    ac_fn_c_check_func "$LINENO" "getattrlist" "ac_cv_func_getattrlist"
if test "x$ac_cv_func_getattrlist" = xyes
  cat >>confdefs.h <<_ACEOF
#define HAVE_GETATTRLIST 1
then :
  printf "%s\n" "#define HAVE_GETATTRLIST 1" >>confdefs.h
_ACEOF

fi
done

    for ac_header in copyfile.h
do :
  ac_fn_c_check_header_mongrel "$LINENO" "copyfile.h" "ac_cv_header_copyfile_h" "$ac_includes_default"
if test "x$ac_cv_header_copyfile_h" = xyes; then :
    ac_fn_c_check_header_compile "$LINENO" "copyfile.h" "ac_cv_header_copyfile_h" "$ac_includes_default"
if test "x$ac_cv_header_copyfile_h" = xyes
  cat >>confdefs.h <<_ACEOF
#define HAVE_COPYFILE_H 1
then :
  printf "%s\n" "#define HAVE_COPYFILE_H 1" >>confdefs.h
_ACEOF

fi

done

    for ac_func in copyfile
do :
  ac_fn_c_check_func "$LINENO" "copyfile" "ac_cv_func_copyfile"
if test "x$ac_cv_func_copyfile" = xyes; then :
    ac_fn_c_check_func "$LINENO" "copyfile" "ac_cv_func_copyfile"
if test "x$ac_cv_func_copyfile" = xyes
  cat >>confdefs.h <<_ACEOF
#define HAVE_COPYFILE 1
then :
  printf "%s\n" "#define HAVE_COPYFILE 1" >>confdefs.h
_ACEOF

fi
done

    if test $tcl_corefoundation = yes; then
	for ac_header in libkern/OSAtomic.h
do :
  ac_fn_c_check_header_mongrel "$LINENO" "libkern/OSAtomic.h" "ac_cv_header_libkern_OSAtomic_h" "$ac_includes_default"
if test "x$ac_cv_header_libkern_OSAtomic_h" = xyes; then :
	ac_fn_c_check_header_compile "$LINENO" "libkern/OSAtomic.h" "ac_cv_header_libkern_OSAtomic_h" "$ac_includes_default"
if test "x$ac_cv_header_libkern_OSAtomic_h" = xyes
  cat >>confdefs.h <<_ACEOF
#define HAVE_LIBKERN_OSATOMIC_H 1
then :
  printf "%s\n" "#define HAVE_LIBKERN_OSATOMIC_H 1" >>confdefs.h
_ACEOF

fi

done

	for ac_func in OSSpinLockLock
do :
  ac_fn_c_check_func "$LINENO" "OSSpinLockLock" "ac_cv_func_OSSpinLockLock"
if test "x$ac_cv_func_OSSpinLockLock" = xyes; then :
	ac_fn_c_check_func "$LINENO" "OSSpinLockLock" "ac_cv_func_OSSpinLockLock"
if test "x$ac_cv_func_OSSpinLockLock" = xyes
  cat >>confdefs.h <<_ACEOF
#define HAVE_OSSPINLOCKLOCK 1
then :
  printf "%s\n" "#define HAVE_OSSPINLOCKLOCK 1" >>confdefs.h
_ACEOF

fi
done

    fi

$as_echo "#define USE_VFORK 1" >>confdefs.h


$as_echo "#define TCL_LOAD_FROM_MEMORY 1" >>confdefs.h
printf "%s\n" "#define TCL_LOAD_FROM_MEMORY 1" >>confdefs.h


$as_echo "#define TCL_WIDE_CLICKS 1" >>confdefs.h
printf "%s\n" "#define TCL_WIDE_CLICKS 1" >>confdefs.h

    for ac_header in AvailabilityMacros.h
do :
  ac_fn_c_check_header_mongrel "$LINENO" "AvailabilityMacros.h" "ac_cv_header_AvailabilityMacros_h" "$ac_includes_default"
if test "x$ac_cv_header_AvailabilityMacros_h" = xyes; then :
    ac_fn_c_check_header_compile "$LINENO" "AvailabilityMacros.h" "ac_cv_header_AvailabilityMacros_h" "$ac_includes_default"
if test "x$ac_cv_header_AvailabilityMacros_h" = xyes
  cat >>confdefs.h <<_ACEOF
#define HAVE_AVAILABILITYMACROS_H 1
then :
  printf "%s\n" "#define HAVE_AVAILABILITYMACROS_H 1" >>confdefs.h
_ACEOF

fi

done

    if test "$ac_cv_header_AvailabilityMacros_h" = yes; then
	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if weak import is available" >&5
$as_echo_n "checking if weak import is available... " >&6; }
if ${tcl_cv_cc_weak_import+:} false; then :
  $as_echo_n "(cached) " >&6
else

	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if weak import is available" >&5
printf %s "checking if weak import is available... " >&6; }
if test ${tcl_cv_cc_weak_import+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

		    #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
		    #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020
		    #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020
		    #endif
		    #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1020
		    #error MAC_OS_X_VERSION_MIN_REQUIRED < 1020
		    #endif
		    int rand(void) __attribute__((weak_import));

int
main ()
main (void)
{
rand();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_cc_weak_import=yes
else
  tcl_cv_cc_weak_import=no
else case e in #(
  e) tcl_cv_cc_weak_import=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
	    CFLAGS=$hold_cflags
	    CFLAGS=$hold_cflags ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_weak_import" >&5
$as_echo "$tcl_cv_cc_weak_import" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_weak_import" >&5
printf "%s\n" "$tcl_cv_cc_weak_import" >&6; }
	if test $tcl_cv_cc_weak_import = yes; then

$as_echo "#define HAVE_WEAK_IMPORT 1" >>confdefs.h
printf "%s\n" "#define HAVE_WEAK_IMPORT 1" >>confdefs.h

	fi
	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if Darwin SUSv3 extensions are available" >&5
$as_echo_n "checking if Darwin SUSv3 extensions are available... " >&6; }
if ${tcl_cv_cc_darwin_c_source+:} false; then :
  $as_echo_n "(cached) " >&6
else

	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if Darwin SUSv3 extensions are available" >&5
printf %s "checking if Darwin SUSv3 extensions are available... " >&6; }
if test ${tcl_cv_cc_darwin_c_source+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

		    #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
		    #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
		    #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
		    #endif
		    #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1050
		    #error MAC_OS_X_VERSION_MIN_REQUIRED < 1050
		    #endif
		    #define _DARWIN_C_SOURCE 1
		    #include <sys/cdefs.h>

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_cc_darwin_c_source=yes
else
  tcl_cv_cc_darwin_c_source=no
else case e in #(
  e) tcl_cv_cc_darwin_c_source=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
	    CFLAGS=$hold_cflags
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
	    CFLAGS=$hold_cflags ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_darwin_c_source" >&5
$as_echo "$tcl_cv_cc_darwin_c_source" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_darwin_c_source" >&5
printf "%s\n" "$tcl_cv_cc_darwin_c_source" >&6; }
	if test $tcl_cv_cc_darwin_c_source = yes; then

$as_echo "#define _DARWIN_C_SOURCE 1" >>confdefs.h
printf "%s\n" "#define _DARWIN_C_SOURCE 1" >>confdefs.h

	fi
    fi
    # Build .bundle dltest binaries in addition to .dylib
    DLTEST_LD='${CC} -bundle -Wl,-w ${CFLAGS} ${LDFLAGS}'
    DLTEST_SUFFIX=".bundle"
else
    DLTEST_LD='${SHLIB_LD}'
    DLTEST_SUFFIX=""
fi

#--------------------------------------------------------------------
#	Check for support of fts functions (readdir replacement)
#--------------------------------------------------------------------

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fts" >&5
$as_echo_n "checking for fts... " >&6; }
if ${tcl_cv_api_fts+:} false; then :
  $as_echo_n "(cached) " >&6
else

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for fts" >&5
printf %s "checking for fts... " >&6; }
if test ${tcl_cv_api_fts+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	    #include <sys/param.h>
	    #include <sys/stat.h>
	    #include <fts.h>

int
main ()
main (void)
{

	    char*const p[2] = {"/", NULL};
	    FTS *f = fts_open(p, FTS_PHYSICAL|FTS_NOCHDIR|FTS_NOSTAT, NULL);
	    FTSENT *e = fts_read(f); fts_close(f);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_api_fts=yes
else
  tcl_cv_api_fts=no
else case e in #(
  e) tcl_cv_api_fts=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_fts" >&5
$as_echo "$tcl_cv_api_fts" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_fts" >&5
printf "%s\n" "$tcl_cv_api_fts" >&6; }
if test $tcl_cv_api_fts = yes; then

$as_echo "#define HAVE_FTS 1" >>confdefs.h
printf "%s\n" "#define HAVE_FTS 1" >>confdefs.h

fi

#--------------------------------------------------------------------
#	The statements below check for systems where POSIX-style non-blocking
#	I/O (O_NONBLOCK) doesn't work or is unimplemented. On these systems
#	(mostly older ones), use the old BSD-style FIONBIO approach instead.
#--------------------------------------------------------------------


    for ac_header in sys/ioctl.h
do :
  ac_fn_c_check_header_mongrel "$LINENO" "sys/ioctl.h" "ac_cv_header_sys_ioctl_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_ioctl_h" = xyes; then :
    ac_fn_c_check_header_compile "$LINENO" "sys/ioctl.h" "ac_cv_header_sys_ioctl_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_ioctl_h" = xyes
  cat >>confdefs.h <<_ACEOF
#define HAVE_SYS_IOCTL_H 1
then :
  printf "%s\n" "#define HAVE_SYS_IOCTL_H 1" >>confdefs.h
_ACEOF

fi

done

    for ac_header in sys/filio.h
do :
  ac_fn_c_check_header_mongrel "$LINENO" "sys/filio.h" "ac_cv_header_sys_filio_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_filio_h" = xyes; then :
    ac_fn_c_check_header_compile "$LINENO" "sys/filio.h" "ac_cv_header_sys_filio_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_filio_h" = xyes
  cat >>confdefs.h <<_ACEOF
#define HAVE_SYS_FILIO_H 1
then :
  printf "%s\n" "#define HAVE_SYS_FILIO_H 1" >>confdefs.h
_ACEOF

fi

done


    { $as_echo "$as_me:${as_lineno-$LINENO}: checking system version" >&5
$as_echo_n "checking system version... " >&6; }
if ${tcl_cv_sys_version+:} false; then :
  $as_echo_n "(cached) " >&6
else

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking system version" >&5
printf %s "checking system version... " >&6; }
if test ${tcl_cv_sys_version+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	if test "${TEA_PLATFORM}" = "windows" ; then
	    tcl_cv_sys_version=windows
	else
	    tcl_cv_sys_version=`uname -s`-`uname -r`
	    if test "$?" -ne 0 ; then
		{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5
$as_echo "$as_me: WARNING: can't find uname command" >&2;}
		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5
printf "%s\n" "$as_me: WARNING: can't find uname command" >&2;}
		tcl_cv_sys_version=unknown
	    else
		if test "`uname -s`" = "AIX" ; then
		    tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
		fi
		if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then
		    tcl_cv_sys_version=NetBSD-Debian
		fi
	    fi
	fi

     ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5
$as_echo "$tcl_cv_sys_version" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5
printf "%s\n" "$tcl_cv_sys_version" >&6; }
    system=$tcl_cv_sys_version

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking FIONBIO vs. O_NONBLOCK for nonblocking I/O" >&5
$as_echo_n "checking FIONBIO vs. O_NONBLOCK for nonblocking I/O... " >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking FIONBIO vs. O_NONBLOCK for nonblocking I/O" >&5
printf %s "checking FIONBIO vs. O_NONBLOCK for nonblocking I/O... " >&6; }
    case $system in
	OSF*)

$as_echo "#define USE_FIONBIO 1" >>confdefs.h
printf "%s\n" "#define USE_FIONBIO 1" >>confdefs.h

	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: FIONBIO" >&5
$as_echo "FIONBIO" >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: FIONBIO" >&5
printf "%s\n" "FIONBIO" >&6; }
	    ;;
	*)
	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: O_NONBLOCK" >&5
$as_echo "O_NONBLOCK" >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: O_NONBLOCK" >&5
printf "%s\n" "O_NONBLOCK" >&6; }
	    ;;
    esac


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

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use dll unloading" >&5
$as_echo_n "checking whether to use dll unloading... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to use dll unloading" >&5
printf %s "checking whether to use dll unloading... " >&6; }
# Check whether --enable-dll-unloading was given.
if test "${enable_dll_unloading+set}" = set; then :
if test ${enable_dll_unloading+y}
then :
  enableval=$enable_dll_unloading; tcl_ok=$enableval
else
  tcl_ok=yes
else case e in #(
  e) tcl_ok=yes ;;
esac
fi

if test $tcl_ok = yes; then

$as_echo "#define TCL_UNLOAD_DLLS 1" >>confdefs.h
printf "%s\n" "#define TCL_UNLOAD_DLLS 1" >>confdefs.h

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_ok" >&5
$as_echo "$tcl_ok" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_ok" >&5
printf "%s\n" "$tcl_ok" >&6; }

#------------------------------------------------------------------------
#	Check whether the timezone data is supplied by the OS or has
#	to be installed by Tcl. The default is autodetection, but can
#	be overridden on the configure command line either way.
#------------------------------------------------------------------------

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for timezone data" >&5
$as_echo_n "checking for timezone data... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for timezone data" >&5
printf %s "checking for timezone data... " >&6; }

# Check whether --with-tzdata was given.
if test "${with_tzdata+set}" = set; then :
if test ${with_tzdata+y}
then :
  withval=$with_tzdata; tcl_ok=$withval
else
  tcl_ok=auto
else case e in #(
  e) tcl_ok=auto ;;
esac
fi

#
# Any directories that get added here must also be added to the
# search path in ::tcl::clock::Initialize (library/clock.tcl).
#
case $tcl_ok in
    no)
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: supplied by OS vendor" >&5
$as_echo "supplied by OS vendor" >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: supplied by OS vendor" >&5
printf "%s\n" "supplied by OS vendor" >&6; }
    ;;
    yes)
	# nothing to do here
    ;;
    auto*)
	if ${tcl_cv_dir_zoneinfo+:} false; then :
  $as_echo_n "(cached) " >&6
else

	if test ${tcl_cv_dir_zoneinfo+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	for dir in /usr/share/zoneinfo \
		/usr/share/lib/zoneinfo \
		/usr/lib/zoneinfo
	do
		if test -f $dir/UTC -o -f $dir/GMT
		then
			tcl_cv_dir_zoneinfo="$dir"
			break
		fi
	done
	done ;;
esac
fi

	if test -n "$tcl_cv_dir_zoneinfo"; then
	    tcl_ok=no
	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dir" >&5
$as_echo "$dir" >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $dir" >&5
printf "%s\n" "$dir" >&6; }
	else
	    tcl_ok=yes
	fi
    ;;
    *)
	as_fn_error $? "invalid argument: $tcl_ok" "$LINENO" 5
    ;;
esac
if test $tcl_ok = yes
then
    { $as_echo "$as_me:${as_lineno-$LINENO}: result: supplied by Tcl" >&5
$as_echo "supplied by Tcl" >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: supplied by Tcl" >&5
printf "%s\n" "supplied by Tcl" >&6; }
    INSTALL_TZDATA=install-tzdata
fi

#--------------------------------------------------------------------
#	DTrace support
#--------------------------------------------------------------------

# Check whether --enable-dtrace was given.
if test "${enable_dtrace+set}" = set; then :
if test ${enable_dtrace+y}
then :
  enableval=$enable_dtrace; tcl_ok=$enableval
else
  tcl_ok=no
else case e in #(
  e) tcl_ok=no ;;
esac
fi

if test $tcl_ok = yes; then
    ac_fn_c_check_header_mongrel "$LINENO" "sys/sdt.h" "ac_cv_header_sys_sdt_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_sdt_h" = xyes; then :
    ac_fn_c_check_header_compile "$LINENO" "sys/sdt.h" "ac_cv_header_sys_sdt_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_sdt_h" = xyes
then :
  tcl_ok=yes
else
  tcl_ok=no
else case e in #(
  e) tcl_ok=no ;;
esac
fi


fi
if test $tcl_ok = yes; then
    # Extract the first word of "dtrace", so it can be a program name with args.
set dummy dtrace; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_DTRACE+:} false; then :
  $as_echo_n "(cached) " >&6
else
  case $DTRACE in
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_path_DTRACE+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) case $DTRACE in
  [\\/]* | ?:[\\/]*)
  ac_cv_path_DTRACE="$DTRACE" # Let the user override the test with a path.
  ;;
  *)
  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_dummy="$PATH:/usr/sbin"
for as_dir in $as_dummy
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    ac_cv_path_DTRACE="$as_dir/$ac_word$ac_exec_ext"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_path_DTRACE="$as_dir$ac_word$ac_exec_ext"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

  ;;
esac ;;
esac
fi
DTRACE=$ac_cv_path_DTRACE
if test -n "$DTRACE"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5
$as_echo "$DTRACE" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5
printf "%s\n" "$DTRACE" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


    test -z "$ac_cv_path_DTRACE" && tcl_ok=no
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable DTrace support" >&5
$as_echo_n "checking whether to enable DTrace support... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable DTrace support" >&5
printf %s "checking whether to enable DTrace support... " >&6; }
MAKEFILE_SHELL='/bin/sh'
if test $tcl_ok = yes; then

$as_echo "#define USE_DTRACE 1" >>confdefs.h
printf "%s\n" "#define USE_DTRACE 1" >>confdefs.h

    DTRACE_SRC="\${DTRACE_SRC}"
    DTRACE_HDR="\${DTRACE_HDR}"
    if test "`uname -s`" != "Darwin" ; then
	DTRACE_OBJ="\${DTRACE_OBJ}"
	if test "`uname -s`" = "SunOS" -a "$SHARED_BUILD" = "0" ; then
	    # Need to create an intermediate object file to ensure tclDTrace.o
	    # gets included when linking against the static tcl library.
	    STLIB_LD='stlib_ld () { /usr/ccs/bin/ld -r -o $${1%.a}.o "$${@:2}" && '"${STLIB_LD}"' $${1} $${1%.a}.o ; } && stlib_ld'
	    MAKEFILE_SHELL='/bin/bash'
	    # Force use of Sun ar and ranlib, the GNU versions choke on
	    # tclDTrace.o and the combined object file above.
	    AR='/usr/ccs/bin/ar'
	    RANLIB='/usr/ccs/bin/ranlib'
	fi
    fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_ok" >&5
$as_echo "$tcl_ok" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_ok" >&5
printf "%s\n" "$tcl_ok" >&6; }

#--------------------------------------------------------------------
#	Zipfs support - Tip 430
#--------------------------------------------------------------------
# Check whether --enable-zipfs was given.
if test "${enable_zipfs+set}" = set; then :
  enableval=$enable_zipfs; tcl_ok=$enableval
else
  tcl_ok=yes
fi

if test "$tcl_ok" = "yes" ; then
    #
    # Find a native compiler
    #
    # Put a plausible default for CC_FOR_BUILD in Makefile.
    if test -z "$CC_FOR_BUILD"; then
      if test "x$cross_compiling" = "xno"; then
        CC_FOR_BUILD='$(CC)'
      else
        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc" >&5
$as_echo_n "checking for gcc... " >&6; }
        if ${ac_cv_path_cc+:} false; then :
  $as_echo_n "(cached) " >&6
else

            search_path=`echo ${PATH} | sed -e 's/:/ /g'`
            for dir in $search_path ; do
                for j in `ls -r $dir/gcc 2> /dev/null` \
                        `ls -r $dir/gcc 2> /dev/null` ; do
                    if test x"$ac_cv_path_cc" = x ; then
                        if test -f "$j" ; then
                            ac_cv_path_cc=$j
                            break
                        fi
                    fi
                done
            done

fi

      fi
    fi

    # Also set EXEEXT_FOR_BUILD.
    if test "x$cross_compiling" = "xno"; then
      EXEEXT_FOR_BUILD='$(EXEEXT)'
      OBJEXT_FOR_BUILD='$(OBJEXT)'
    else
      OBJEXT_FOR_BUILD='.no'
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for build system executable suffix" >&5
$as_echo_n "checking for build system executable suffix... " >&6; }
if ${bfd_cv_build_exeext+:} false; then :
  $as_echo_n "(cached) " >&6
else
  rm -f conftest*
         echo 'int main () { return 0; }' > conftest.c
         bfd_cv_build_exeext=
         ${CC_FOR_BUILD} -o conftest conftest.c 1>&5 2>&5
         for file in conftest.*; do
           case $file in
           *.c | *.o | *.obj | *.ilk | *.pdb) ;;
           *) bfd_cv_build_exeext=`echo $file | sed -e s/conftest//` ;;
           esac
         done
         rm -f conftest*
         test x"${bfd_cv_build_exeext}" = x && bfd_cv_build_exeext=no
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $bfd_cv_build_exeext" >&5
$as_echo "$bfd_cv_build_exeext" >&6; }
      EXEEXT_FOR_BUILD=""
      test x"${bfd_cv_build_exeext}" != xno && EXEEXT_FOR_BUILD=${bfd_cv_build_exeext}
    fi

    #
    # Find a native zip implementation
    #

    ZIP_PROG=""
    ZIP_PROG_OPTIONS=""
    ZIP_PROG_VFSSEARCH=""
    ZIP_INSTALL_OBJS=""

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for zip" >&5
$as_echo_n "checking for zip... " >&6; }
    if ${ac_cv_path_zip+:} false; then :
  $as_echo_n "(cached) " >&6
else

    search_path=`echo ${PATH} | sed -e 's/:/ /g'`
    for dir in $search_path ; do
        for j in `ls -r $dir/zip 2> /dev/null` \
            `ls -r $dir/zip 2> /dev/null` ; do
        if test x"$ac_cv_path_zip" = x ; then
            if test -f "$j" ; then
            ac_cv_path_zip=$j
            break
            fi
        fi
        done
    done

fi

    if test -f "$ac_cv_path_zip" ; then
        ZIP_PROG="$ac_cv_path_zip"
        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ZIP_PROG" >&5
$as_echo "$ZIP_PROG" >&6; }
        ZIP_PROG_OPTIONS="-rq"
        ZIP_PROG_VFSSEARCH="*"
        { $as_echo "$as_me:${as_lineno-$LINENO}: result: Found INFO Zip in environment" >&5
$as_echo "Found INFO Zip in environment" >&6; }
        # Use standard arguments for zip
    else
        # It is not an error if an installed version of Zip can't be located.
        # We can use the locally distributed minizip instead
        ZIP_PROG="./minizip${EXEEXT_FOR_BUILD}"
        ZIP_PROG_OPTIONS="-o -r"
        ZIP_PROG_VFSSEARCH="*"
        ZIP_INSTALL_OBJS="minizip${EXEEXT_FOR_BUILD}"
        { $as_echo "$as_me:${as_lineno-$LINENO}: result: No zip found on PATH. Building minizip" >&5
$as_echo "No zip found on PATH. Building minizip" >&6; }
    fi





	ZIPFS_BUILD=1
	TCL_ZIP_FILE=libtcl_${TCL_MAJOR_VERSION}_${TCL_MINOR_VERSION}_${TCL_PATCH_LEVEL}.zip
else
	ZIPFS_BUILD=0
	TCL_ZIP_FILE=
fi
# Do checking message here to not mess up interleaved configure output
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for building with zipfs" >&5
$as_echo_n "checking for building with zipfs... " >&6; }
if test "${ZIPFS_BUILD}" = 1; then
    if test "${SHARED_BUILD}" = 0; then
       ZIPFS_BUILD=2;

$as_echo "#define ZIPFS_BUILD 2" >>confdefs.h

       INSTALL_LIBRARIES=install-libraries-zipfs-static
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
     else

$as_echo "#define ZIPFS_BUILD 1" >>confdefs.h
\
       INSTALL_LIBRARIES=install-libraries-zipfs-shared
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
    fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
INSTALL_LIBRARIES=install-libraries
INSTALL_MSGS=install-msgs
fi






#--------------------------------------------------------------------
# The check below checks whether the cpuid instruction is usable.
#--------------------------------------------------------------------

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the cpuid instruction is usable" >&5
$as_echo_n "checking whether the cpuid instruction is usable... " >&6; }
if ${tcl_cv_cpuid+:} false; then :
  $as_echo_n "(cached) " >&6
else

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the cpuid instruction is usable" >&5
printf %s "checking whether the cpuid instruction is usable... " >&6; }
if test ${tcl_cv_cpuid+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

	int index,regsPtr[4];
    __asm__ __volatile__("mov %%ebx, %%edi     \n\t"
                 "cpuid            \n\t"
                 "mov %%ebx, %%esi   \n\t"
                 "mov %%edi, %%ebx  \n\t"
                 : "=a"(regsPtr[0]), "=S"(regsPtr[1]), "=c"(regsPtr[2]), "=d"(regsPtr[3])
                 : "a"(index) : "edi");
		 "cpuid            \n\t"
		 "mov %%ebx, %%esi   \n\t"
		 "mov %%edi, %%ebx  \n\t"
		 : "=a"(regsPtr[0]), "=S"(regsPtr[1]), "=c"(regsPtr[2]), "=d"(regsPtr[3])
		 : "a"(index) : "edi");

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_cpuid=yes
else
  tcl_cv_cpuid=no
else case e in #(
  e) tcl_cv_cpuid=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cpuid" >&5
$as_echo "$tcl_cv_cpuid" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cpuid" >&5
printf "%s\n" "$tcl_cv_cpuid" >&6; }
if test $tcl_cv_cpuid = yes; then

$as_echo "#define HAVE_CPUID 1" >>confdefs.h
printf "%s\n" "#define HAVE_CPUID 1" >>confdefs.h

fi

#--------------------------------------------------------------------
#	The statements below define a collection of symbols related to
#	building libtcl as a shared library instead of a static library.
#--------------------------------------------------------------------
10382
10383
10384
10385
10386
10387
10388
10389
10390


10391
10392


10393
10394
10395



10396
10397
10398
10399
10400
10401


10402
10403
10404
10405
10406


10407
10408
10409
10410
10411
10412


10413
10414
10415
10416
10417


10418
10419
10420


10421
10422
10423
10424
10425
10426
10427
10428
10429
10430
10431
10432
10433
10434
10435
10436
10437
10438
10439

10440
10441
10442
10443
10444
10445
10446
10447
10448

10449
10450

10451
10452
10453
10454


10455
10456
10457
10458
10459
10460
10461
10994
10995
10996
10997
10998
10999
11000


11001
11002
11003

11004
11005
11006


11007
11008
11009
11010
11011
11012
11013


11014
11015
11016
11017
11018


11019
11020
11021
11022
11023
11024


11025
11026
11027
11028
11029


11030
11031
11032


11033
11034
11035
11036
11037
11038
11039
11040
11041
11042
11043
11044

11045
11046
11047
11048
11049
11050
11051

11052
11053
11054
11055
11056
11057
11058
11059
11060

11061
11062

11063
11064
11065


11066
11067
11068
11069
11070
11071
11072
11073
11074







-
-
+
+

-
+
+

-
-
+
+
+




-
-
+
+



-
-
+
+




-
-
+
+



-
-
+
+

-
-
+
+










-







-
+








-
+

-
+


-
-
+
+







# path name of the Tcl directory rather than "..":  this is because
# AIX remembers this path and will attempt to use it at run-time to look
# up the Tcl library.

if test "`uname -s`" = "Darwin" ; then

    if test "`uname -s`" = "Darwin" ; then
	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to package libraries" >&5
$as_echo_n "checking how to package libraries... " >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to package libraries" >&5
printf %s "checking how to package libraries... " >&6; }
	# Check whether --enable-framework was given.
if test "${enable_framework+set}" = set; then :
if test ${enable_framework+y}
then :
  enableval=$enable_framework; enable_framework=$enableval
else
  enable_framework=no
else case e in #(
  e) enable_framework=no ;;
esac
fi

	if test $enable_framework = yes; then
	    if test $SHARED_BUILD = 0; then
		{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Frameworks can only be built if --enable-shared is yes" >&5
$as_echo "$as_me: WARNING: Frameworks can only be built if --enable-shared is yes" >&2;}
		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Frameworks can only be built if --enable-shared is yes" >&5
printf "%s\n" "$as_me: WARNING: Frameworks can only be built if --enable-shared is yes" >&2;}
		enable_framework=no
	    fi
	    if test $tcl_corefoundation = no; then
		{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Frameworks can only be used when CoreFoundation is available" >&5
$as_echo "$as_me: WARNING: Frameworks can only be used when CoreFoundation is available" >&2;}
		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Frameworks can only be used when CoreFoundation is available" >&5
printf "%s\n" "$as_me: WARNING: Frameworks can only be used when CoreFoundation is available" >&2;}
		enable_framework=no
	    fi
	fi
	if test $enable_framework = yes; then
	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: framework" >&5
$as_echo "framework" >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: framework" >&5
printf "%s\n" "framework" >&6; }
	    FRAMEWORK_BUILD=1
	else
	    if test $SHARED_BUILD = 1; then
		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: shared library" >&5
$as_echo "shared library" >&6; }
		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: shared library" >&5
printf "%s\n" "shared library" >&6; }
	    else
		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: static library" >&5
$as_echo "static library" >&6; }
		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: static library" >&5
printf "%s\n" "static library" >&6; }
	    fi
	    FRAMEWORK_BUILD=0
	fi
    fi

    TCL_SHLIB_LD_EXTRAS="-compatibility_version ${TCL_VERSION} -current_version ${TCL_VERSION}`echo ${TCL_PATCH_LEVEL} | awk '{match($0, "\\\.[0-9]+"); print substr($0,RSTART,RLENGTH)}'`"
    TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -install_name "${DYLIB_INSTALL_DIR}"/${TCL_LIB_FILE}'
    echo "$LDFLAGS " | grep -q -- '-prebind ' && TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -seg1addr 0xA000000'
    TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -sectcreate __TEXT __info_plist Tcl-Info.plist'
    EXTRA_TCLSH_LIBS='-sectcreate __TEXT __info_plist Tclsh-Info.plist'
    EXTRA_APP_CC_SWITCHES='-mdynamic-no-pic'
    ac_config_files="$ac_config_files Tcl-Info.plist:../macosx/Tcl-Info.plist.in Tclsh-Info.plist:../macosx/Tclsh-Info.plist.in"

    TCL_YEAR="`date +%Y`"
fi

if test "$FRAMEWORK_BUILD" = "1" ; then

$as_echo "#define TCL_FRAMEWORK 1" >>confdefs.h
printf "%s\n" "#define TCL_FRAMEWORK 1" >>confdefs.h

    # Construct a fake local framework structure to make linking with
    # '-framework Tcl' and running of tcltest work
    ac_config_commands="$ac_config_commands Tcl.framework"

    LD_LIBRARY_PATH_VAR="DYLD_FRAMEWORK_PATH"
    # default install directory for bundled packages
    if test "${libdir}" = '${exec_prefix}/lib' -o "`basename ${libdir}`" = 'Frameworks'; then
        PACKAGE_DIR="/Library/Tcl"
	PACKAGE_DIR="/Library/Tcl"
    else
        PACKAGE_DIR="$libdir"
	PACKAGE_DIR="$libdir"
    fi
    if test "${libdir}" = '${exec_prefix}/lib'; then
        # override libdir default
        libdir="/Library/Frameworks"
	# override libdir default
	libdir="/Library/Frameworks"
    fi
    TCL_LIB_FILE="Tcl"
    TCL_LIB_FLAG="-framework Tcl"
    TCL_BUILD_LIB_SPEC="-F`pwd | sed -e 's/ /\\\\ /g'` -framework Tcl"
    TCL_LIB_SPEC="-F${libdir} -framework Tcl"
    libdir="${libdir}/Tcl.framework/Versions/\${VERSION}"
    TCL_LIBRARY="${libdir}/Resources/Scripts"
10474
10475
10476
10477
10478
10479
10480
10481

10482
10483

10484
10485
10486
10487
10488
10489
10490
10491















































































































































































































10492
10493
10494
10495
10496
10497
10498
10499
10500
10501
10502



10503
10504
10505
10506

10507
10508

10509
10510
10511
10512
10513
10514
10515
10516
10517
10518
10519

10520
10521
10522
10523
10524
10525
10526

10527
10528
10529
10530
10531
10532
10533
10534
11087
11088
11089
11090
11091
11092
11093

11094
11095

11096
11097
11098
11099
11100
11101
11102
11103
11104
11105
11106
11107
11108
11109
11110
11111
11112
11113
11114
11115
11116
11117
11118
11119
11120
11121
11122
11123
11124
11125
11126
11127
11128
11129
11130
11131
11132
11133
11134
11135
11136
11137
11138
11139
11140
11141
11142
11143
11144
11145
11146
11147
11148
11149
11150
11151
11152
11153
11154
11155
11156
11157
11158
11159
11160
11161
11162
11163
11164
11165
11166
11167
11168
11169
11170
11171
11172
11173
11174
11175
11176
11177
11178
11179
11180
11181
11182
11183
11184
11185
11186
11187
11188
11189
11190
11191
11192
11193
11194
11195
11196
11197
11198
11199
11200
11201
11202
11203
11204
11205
11206
11207
11208
11209
11210
11211
11212
11213
11214
11215
11216
11217
11218
11219
11220
11221
11222
11223
11224
11225
11226
11227
11228
11229
11230
11231
11232
11233
11234
11235
11236
11237
11238
11239
11240
11241
11242
11243
11244
11245
11246
11247
11248
11249
11250
11251
11252
11253
11254
11255
11256
11257
11258
11259
11260
11261
11262
11263
11264
11265
11266
11267
11268
11269
11270
11271
11272
11273
11274
11275
11276
11277
11278
11279
11280
11281
11282
11283
11284
11285
11286
11287
11288
11289
11290
11291
11292
11293
11294
11295
11296
11297
11298
11299
11300
11301
11302
11303
11304
11305
11306
11307
11308
11309
11310
11311
11312
11313
11314
11315
11316
11317
11318
11319
11320
11321

11322
11323
11324
11325
11326
11327

11328
11329

11330
11331
11332
11333
11334
11335
11336
11337
11338
11339
11340

11341
11342
11343
11344




11345

11346
11347
11348
11349
11350
11351
11352







-
+

-
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










-
+
+
+



-
+

-
+










-
+



-
-
-
-
+
-







    EXTRA_CC_SWITCHES='-DTCL_FRAMEWORK_VERSION=\"$(VERSION)\"'
else
    # libdir must be a fully qualified path and not ${exec_prefix}/lib
    eval libdir="$libdir"
    # default install directory for bundled packages
    PACKAGE_DIR="$libdir"
    if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
        TCL_LIB_FLAG="-ltcl${TCL_VERSION}"
	TCL_LIB_FLAG="-ltcl${TCL_VERSION}"
    else
        TCL_LIB_FLAG="-ltcl`echo ${TCL_VERSION} | tr -d .`"
	TCL_LIB_FLAG="-ltcl`echo ${TCL_VERSION} | tr -d .`"
    fi
    TCL_BUILD_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TCL_LIB_FLAG}"
    TCL_LIB_SPEC="-L${libdir} ${TCL_LIB_FLAG}"
fi
VERSION='${VERSION}'
eval "CFG_TCL_SHARED_LIB_SUFFIX=${TCL_SHARED_LIB_SUFFIX}"
eval "CFG_TCL_UNSHARED_LIB_SUFFIX=${TCL_UNSHARED_LIB_SUFFIX}"
VERSION=${TCL_VERSION}

#--------------------------------------------------------------------
#	Zipfs support - Tip 430
#--------------------------------------------------------------------
# Check whether --enable-zipfs was given.
if test ${enable_zipfs+y}
then :
  enableval=$enable_zipfs; tcl_ok=$enableval
else case e in #(
  e) tcl_ok=yes ;;
esac
fi

if test "$tcl_ok" = "yes" -a "x$enable_framework" != "xyes"; then
    #
    # Find a native compiler
    #
    # Put a plausible default for CC_FOR_BUILD in Makefile.
    if test -z "$CC_FOR_BUILD"; then
      if test "x$cross_compiling" = "xno"; then
	CC_FOR_BUILD='$(CC)'
      else
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gcc" >&5
printf %s "checking for gcc... " >&6; }
	if test ${ac_cv_path_cc+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	    search_path=`echo ${PATH} | sed -e 's/:/ /g'`
	    for dir in $search_path ; do
		for j in `ls -r $dir/gcc 2> /dev/null` \
			`ls -r $dir/gcc 2> /dev/null` ; do
		    if test x"$ac_cv_path_cc" = x ; then
			if test -f "$j" ; then
			    ac_cv_path_cc=$j
			    break
			fi
		    fi
		done
	    done
	 ;;
esac
fi

      fi
    fi

    # Also set EXEEXT_FOR_BUILD.
    if test "x$cross_compiling" = "xno"; then
      EXEEXT_FOR_BUILD='$(EXEEXT)'
      OBJEXT_FOR_BUILD='$(OBJEXT)'
    else
      OBJEXT_FOR_BUILD='.no'
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for build system executable suffix" >&5
printf %s "checking for build system executable suffix... " >&6; }
if test ${bfd_cv_build_exeext+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) rm -f conftest*
	 echo 'int main () { return 0; }' > conftest.c
	 bfd_cv_build_exeext=
	 ${CC_FOR_BUILD} -o conftest conftest.c 1>&5 2>&5
	 for file in conftest.*; do
	   case $file in
	   *.c | *.o | *.obj | *.ilk | *.pdb) ;;
	   *) bfd_cv_build_exeext=`echo $file | sed -e s/conftest//` ;;
	   esac
	 done
	 rm -f conftest*
	 test x"${bfd_cv_build_exeext}" = x && bfd_cv_build_exeext=no ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $bfd_cv_build_exeext" >&5
printf "%s\n" "$bfd_cv_build_exeext" >&6; }
      EXEEXT_FOR_BUILD=""
      test x"${bfd_cv_build_exeext}" != xno && EXEEXT_FOR_BUILD=${bfd_cv_build_exeext}
    fi

    #
    # Find a native zip implementation
    #

    MACHER_PROG=""
    ZIP_PROG=""
    ZIP_PROG_OPTIONS=""
    ZIP_PROG_VFSSEARCH=""
    ZIP_INSTALL_OBJS=""

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for macher" >&5
printf %s "checking for macher... " >&6; }
    if test ${ac_cv_path_macher+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
    search_path=`echo ${PATH} | sed -e 's/:/ /g'`
    for dir in $search_path ; do
	for j in `ls -r $dir/macher 2> /dev/null` \
	    `ls -r $dir/macher 2> /dev/null` ; do
	if test x"$ac_cv_path_macher" = x ; then
	    if test -f "$j" ; then
	    ac_cv_path_macher=$j
	    break
	    fi
	fi
	done
    done
     ;;
esac
fi

    if test -f "$ac_cv_path_macher" ; then
	MACHER_PROG="$ac_cv_path_macher"
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MACHER_PROG" >&5
printf "%s\n" "$MACHER_PROG" >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Found macher in environment" >&5
printf "%s\n" "Found macher in environment" >&6; }
    fi
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for zip" >&5
printf %s "checking for zip... " >&6; }
    if test ${ac_cv_path_zip+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
    search_path=`echo ${PATH} | sed -e 's/:/ /g'`
    for dir in $search_path ; do
	for j in `ls -r $dir/zip 2> /dev/null` \
	    `ls -r $dir/zip 2> /dev/null` ; do
	if test x"$ac_cv_path_zip" = x ; then
	    if test -f "$j" ; then
	    ac_cv_path_zip=$j
	    break
	    fi
	fi
	done
    done
     ;;
esac
fi

    if test -f "$ac_cv_path_zip" ; then
	ZIP_PROG="$ac_cv_path_zip"
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ZIP_PROG" >&5
printf "%s\n" "$ZIP_PROG" >&6; }
	ZIP_PROG_OPTIONS="-rq"
	ZIP_PROG_VFSSEARCH="*"
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Found INFO Zip in environment" >&5
printf "%s\n" "Found INFO Zip in environment" >&6; }
	# Use standard arguments for zip
    else
	# It is not an error if an installed version of Zip can't be located.
	# We can use the locally distributed minizip instead
	ZIP_PROG="./minizip${EXEEXT_FOR_BUILD}"
	ZIP_PROG_OPTIONS="-o -r"
	ZIP_PROG_VFSSEARCH="*"
	ZIP_INSTALL_OBJS="minizip${EXEEXT_FOR_BUILD}"
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: No zip found on PATH. Building minizip" >&5
printf "%s\n" "No zip found on PATH. Building minizip" >&6; }
    fi






    ZIPFS_BUILD=1
    TCL_ZIP_FILE=libtcl${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_PATCH_LEVEL}.zip
else
    ZIPFS_BUILD=0
    TCL_ZIP_FILE=
fi
# Do checking message here to not mess up interleaved configure output
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for building with zipfs" >&5
printf %s "checking for building with zipfs... " >&6; }
if test "${ZIPFS_BUILD}" = 1; then
    if test "${SHARED_BUILD}" = 0; then
       ZIPFS_BUILD=2;

printf "%s\n" "#define ZIPFS_BUILD 2" >>confdefs.h

     else

printf "%s\n" "#define ZIPFS_BUILD 1" >>confdefs.h
\
    fi
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
INSTALL_LIBRARIES=install-libraries
INSTALL_MSGS=install-msgs
fi

# Point to tcl script library if we are not embedding it.
if test "${ZIPFS_BUILD}" = 0; then
TCL_BUILDTIME_LIBRARY=${TCL_SRC_DIR}/library
fi







#--------------------------------------------------------------------
#	The statements below define the symbol TCL_PACKAGE_PATH, which
#	gives a list of directories that may contain packages.  The list
#	consists of one directory for machine-dependent binaries and
#	another for platform-independent scripts.
#--------------------------------------------------------------------

if test "$FRAMEWORK_BUILD" = "1" ; then
    test -z "$TCL_PACKAGE_PATH" && \
	TCL_PACKAGE_PATH="~/Library/Tcl /Library/Tcl ~/Library/Frameworks /Library/Frameworks"
	TCL_PACKAGE_PATH="~/Library/Tcl:/Library/Tcl:~/Library/Frameworks:/Library/Frameworks"
	# Allow tclsh to find Tk when multiple versions are installed. See Tk [1562e10c58].
	TCL_PACKAGE_PATH="$TCL_PACKAGE_PATH:/Library/Frameworks/Tk.framework/Versions"
    test -z "$TCL_MODULE_PATH"  && \
	TCL_MODULE_PATH="~/Library/Tcl /Library/Tcl"
elif test "$prefix/lib" != "$libdir"; then
    test -z "$TCL_PACKAGE_PATH" && TCL_PACKAGE_PATH="{${libdir}} {${prefix}/lib} ${TCL_PACKAGE_PATH}"
    test -z "$TCL_PACKAGE_PATH" && TCL_PACKAGE_PATH="${libdir}:${prefix}/lib"
else
    test -z "$TCL_PACKAGE_PATH" && TCL_PACKAGE_PATH="{${prefix}/lib} ${TCL_PACKAGE_PATH}"
    test -z "$TCL_PACKAGE_PATH" && TCL_PACKAGE_PATH="${prefix}/lib"
fi

#--------------------------------------------------------------------
#       The statements below define various symbols relating to Tcl
#       stub support.
#--------------------------------------------------------------------

# Replace ${VERSION} with contents of ${TCL_VERSION}
# double-eval to account for TCL_TRIM_DOTS.
#
eval "TCL_STUB_LIB_FILE=libtclstub${TCL_UNSHARED_LIB_SUFFIX}"
eval "TCL_STUB_LIB_FILE=libtclstub.a"
eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
eval "TCL_STUB_LIB_DIR=\"${libdir}\""

if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
    TCL_STUB_LIB_FLAG="-ltclstub${TCL_VERSION}"
else
    TCL_STUB_LIB_FLAG="-ltclstub`echo ${TCL_VERSION} | tr -d .`"
TCL_STUB_LIB_FLAG="-ltclstub"
fi

TCL_BUILD_STUB_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}"
TCL_STUB_LIB_SPEC="-L${TCL_STUB_LIB_DIR} ${TCL_STUB_LIB_FLAG}"
TCL_BUILD_STUB_LIB_PATH="`pwd`/${TCL_STUB_LIB_FILE}"
TCL_STUB_LIB_PATH="${TCL_STUB_LIB_DIR}/${TCL_STUB_LIB_FILE}"

# Install time header dir can be set via --includedir
10609
10610
10611
10612
10613
10614
10615
10616
10617


10618
10619
10620
10621
10622
10623
10624
10625
10626
10627
10628
10629
10630
10631
10632
10633
10634


10635
10636
10637
10638
10639
10640
10641
10642
10643
10644
10645
10646
10647

10648
10649
10650
10651
10652
10653
10654

10655
10656
10657
10658
10659
10660
10661
10662
10663
10664

10665
10666
10667
10668
10669
10670
10671
10672


10673
10674
10675
10676
10677
10678
10679
10680
10681
10682
10683
10684
10685
10686
10687


10688
10689
10690
10691
10692
10693
10694
11427
11428
11429
11430
11431
11432
11433


11434
11435
11436
11437
11438
11439
11440
11441
11442
11443
11444
11445
11446
11447
11448
11449
11450


11451
11452
11453
11454
11455
11456
11457
11458
11459
11460
11461
11462
11463
11464

11465
11466
11467
11468
11469
11470
11471

11472
11473
11474
11475
11476
11477
11478
11479
11480
11481

11482
11483
11484
11485
11486
11487
11488


11489
11490
11491
11492
11493
11494
11495
11496
11497
11498
11499
11500
11501
11502
11503


11504
11505
11506
11507
11508
11509
11510
11511
11512







-
-
+
+















-
-
+
+












-
+






-
+









-
+






-
-
+
+













-
-
+
+







# scripts and configure runs, see configure's option --config-cache.
# It is not useful on other systems.  If it contains results you don't
# want to keep, you may remove or edit it.
#
# config.status only pays attention to the cache file if you give it
# the --recheck option to rerun configure.
#
# `ac_cv_env_foo' variables (set or unset) will be overridden when
# loading this file, other *unset* `ac_cv_foo' will be assigned the
# 'ac_cv_env_foo' variables (set or unset) will be overridden when
# loading this file, other *unset* 'ac_cv_foo' will be assigned the
# following values.

_ACEOF

# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
# So, we kill variables containing newlines.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
(
  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
    eval ac_val=\$$ac_var
    case $ac_val in #(
    *${as_nl}*)
      case $ac_var in #(
      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
      *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
      esac
      case $ac_var in #(
      _ | IFS | as_nl) ;; #(
      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
      *) { eval $ac_var=; unset $ac_var;} ;;
      esac ;;
    esac
  done

  (set) 2>&1 |
    case $as_nl`(ac_space=' '; set) 2>&1` in #(
    *${as_nl}ac_space=\ *)
      # `set' does not quote correctly, so add quotes: double-quote
      # 'set' does not quote correctly, so add quotes: double-quote
      # substitution turns \\\\ into \\, and sed turns \\ into \.
      sed -n \
	"s/'/'\\\\''/g;
	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
      ;; #(
    *)
      # `set' quotes correctly as required by POSIX, so do not add quotes.
      # 'set' quotes correctly as required by POSIX, so do not add quotes.
      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
      ;;
    esac |
    sort
) |
  sed '
     /^ac_cv_env_/b end
     t clear
     :clear
     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
     s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
     t end
     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
     :end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
  if test -w "$cache_file"; then
    if test "x$cache_file" != "x/dev/null"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
$as_echo "$as_me: updating cache $cache_file" >&6;}
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
      if test ! -f "$cache_file" || test -h "$cache_file"; then
	cat confcache >"$cache_file"
      else
        case $cache_file in #(
        */* | ?:*)
	  mv -f confcache "$cache_file"$$ &&
	  mv -f "$cache_file"$$ "$cache_file" ;; #(
        *)
	  mv -f confcache "$cache_file" ;;
	esac
      fi
    fi
  else
    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
  fi
fi
rm -f confcache

test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
10711
10712
10713
10714
10715
10716
10717
10718

10719
10720
10721
10722
10723
10724
10725
10726
10727
10728
10729
10730
10731
10732
10733
10734
10735
10736
10737
10738
10739
10740
10741
10742
10743


10744
10745
10746
10747
10748
10749
10750
11529
11530
11531
11532
11533
11534
11535

11536


11537
11538
11539
11540
11541
11542
11543
11544
11545
11546
11547
11548
11549
11550
11551
11552

11553
11554
11555
11556


11557
11558
11559
11560
11561
11562
11563
11564
11565







-
+
-
-
















-




-
-
+
+







:clear
s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\)/-D\1=\2/g
t quote
s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)/-D\1=\2/g
t quote
b any
:quote
s/[	 `~#$^&*(){}\\|;'\''"<>?]/\\&/g
s/[][	 `~#$^&*(){}\\|;'\''"<>?]/\\&/g
s/\[/\\&/g
s/\]/\\&/g
s/\$/$$/g
H
:any
${
	g
	s/^\n//
	s/\n/ /g
	p
}
'
DEFS=`sed -n "$ac_script" confdefs.h`



CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""


: "${CONFIG_STATUS=./config.status}"
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
# Generated by $as_me.
# Run this file to recreate the current configuration.
# Compiler output produced by configure, useful for debugging
# configure, is in config.log if it exists.
10759
10760
10761
10762
10763
10764
10765
10766


10767
10768
10769
10770
10771
10772
10773
10774


10775
10776
10777
10778

10779
10780
10781
10782








10783
10784
10785
10786
10787
10788
10789
10790
10791
10792
10793
10794
10795


10796
10797
10798


10799
10800
10801
10802
10803
10804
10805

10806
10807
10808
10809
10810
10811
10812
10813
10814




10815
10816
10817
10818
10819

















10820
10821
10822

10823
10824
10825
10826
10827
10828
10829
10830
10831
10832
10833
10834
10835
10836
10837
10838
10839
10840
10841
10842
10843
10844
10845

10846
10847





10848
10849
10850
10851
10852
10853

10854
10855
10856
10857
10858
10859

10860
10861
10862
10863
10864
10865
10866
10867
10868
10869
10870
10871
10872
10873
10874
10875
10876
10877
10878
10879
10880
10881
10882
10883
10884
10885
10886
10887
10888
10889
10890
10891
10892
10893
10894
10895

10896
10897

10898
10899
10900
10901
10902
10903
10904
11574
11575
11576
11577
11578
11579
11580

11581
11582
11583
11584
11585
11586
11587
11588


11589
11590
11591
11592
11593
11594
11595
11596
11597
11598
11599
11600
11601
11602
11603
11604
11605
11606
11607
11608
11609
11610










11611
11612



11613
11614







11615









11616
11617
11618
11619





11620
11621
11622
11623
11624
11625
11626
11627
11628
11629
11630
11631
11632
11633
11634
11635
11636
11637
11638

11639
11640
11641
11642
11643
11644
11645
11646
11647







11648
11649
11650
11651
11652
11653
11654
11655
11656


11657
11658
11659
11660
11661
11662
11663
11664
11665
11666

11667
11668
11669
11670
11671
11672

11673
11674
11675
11676




















11677
11678
11679
11680
11681
11682
11683
11684
11685
11686
11687
11688

11689
11690

11691
11692
11693
11694
11695
11696
11697
11698







-
+
+






-
-
+
+




+




+
+
+
+
+
+
+
+



-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+








-
-
-
-
-
-
-








+
-
-
+
+
+
+
+





-
+





-
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-












-
+

-
+







cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##

# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
then :
  emulate sh
  NULLCMD=:
  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '${1+"$@"}'='"$@"'
  setopt NO_GLOB_SUBST
else
  case `(set -o) 2>/dev/null` in #(
else case e in #(
  e) case `(set -o) 2>/dev/null` in #(
  *posix*) :
    set -o posix ;; #(
  *) :
     ;;
esac ;;
esac
fi



# Reset variables that may have inherited troublesome values from
# the environment.

# IFS needs to be set, to space, tab, and newline, in precisely that order.
# (If _AS_PATH_WALK were called with IFS unset, it would have the
# side effect of setting IFS to empty, thus disabling word splitting.)
# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
# Printing a long string crashes Solaris 7 /usr/bin/printf.
as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
# Prefer a ksh shell builtin over an external printf program on Solaris,
# but without wasting forks for bash or zsh.
if test -z "$BASH_VERSION$ZSH_VERSION" \
    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
  as_echo='print -r --'
  as_echo_n='print -rn --'
IFS=" ""	$as_nl"

elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
  as_echo='printf %s\n'
  as_echo_n='printf %s'
PS1='$ '
PS2='> '
else
  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
    as_echo_n='/usr/ucb/echo -n'
  else
    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
    as_echo_n_body='eval
PS4='+ '
      arg=$1;
      case $arg in #(
      *"$as_nl"*)
	expr "X$arg" : "X\\(.*\\)$as_nl";
	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
      esac;
      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
    '
    export as_echo_n_body

# Ensure predictable behavior from utilities with locale-dependent output.
LC_ALL=C
export LC_ALL
    as_echo_n='sh -c $as_echo_n_body as_echo'
  fi
  export as_echo_body
  as_echo='sh -c $as_echo_body as_echo'
fi
LANGUAGE=C
export LANGUAGE

# We cannot yet rely on "unset" to work, but we need these variables
# to be unset--not just set to an empty or harmless value--now, to
# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct
# also avoids known problems related to "unset" and subshell syntax
# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
do eval test \${$as_var+y} \
  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done

# Ensure that fds 0, 1, and 2 are open.
if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
if (exec 3>&2)            ; then :; else exec 2>/dev/null; fi

# The user is always right.
if test "${PATH_SEPARATOR+set}" != set; then
if ${PATH_SEPARATOR+false} :; then
  PATH_SEPARATOR=:
  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
      PATH_SEPARATOR=';'
  }
fi


# IFS
# We need space, tab and new line, in precisely that order.  Quoting is
# there to prevent editors from complaining about space-tab.
# (If _AS_PATH_WALK were called with IFS unset, it would disable word
# splitting by setting IFS to empty value.)
IFS=" ""	$as_nl"

# Find who we are.  Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
  *[\\/]* ) as_myself=$0 ;;
  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    test -r "$as_dir$0" && as_myself=$as_dir$0 && break
  done
IFS=$as_save_IFS

     ;;
esac
# We did not find ourselves, most probably we were run as `sh COMMAND'
# We did not find ourselves, most probably we were run as 'sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
  as_myself=$0
fi
if test ! -f "$as_myself"; then
  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
  printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
  exit 1
fi

# Unset variables that we do not need and which cause bugs (e.g. in
# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
# suppresses any "Segmentation fault" message there.  '((' could
# trigger a bug in pdksh 5.2.14.
for as_var in BASH_ENV ENV MAIL MAILPATH
do eval test x\${$as_var+set} = xset \
  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done
PS1='$ '
PS2='> '
PS4='+ '

# NLS nuisances.
LC_ALL=C
export LC_ALL
LANGUAGE=C
export LANGUAGE

# CDPATH.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH


# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
  as_status=$1; test $as_status -eq 0 && as_status=1
  if test "$4"; then
    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
  fi
  $as_echo "$as_me: error: $2" >&2
  printf "%s\n" "$as_me: error: $2" >&2
  as_fn_exit $as_status
} # as_fn_error


# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
10921
10922
10923
10924
10925
10926
10927

10928
10929
10930
10931
10932
10933
10934


10935
10936
10937
10938
10939
10940


10941
10942
10943


10944
10945
10946
10947
10948
10949
10950
10951


10952
10953
10954
10955
10956
10957


10958
10959
10960


10961
10962
10963
10964
10965
10966
10967
11715
11716
11717
11718
11719
11720
11721
11722
11723
11724
11725
11726
11727
11728

11729
11730
11731
11732
11733
11734


11735
11736
11737
11738

11739
11740
11741
11742
11743
11744
11745
11746
11747

11748
11749
11750
11751
11752
11753


11754
11755
11756
11757

11758
11759
11760
11761
11762
11763
11764
11765
11766







+






-
+
+




-
-
+
+


-
+
+







-
+
+




-
-
+
+


-
+
+







# ---------------
# Portably unset VAR.
as_fn_unset ()
{
  { eval $1=; unset $1;}
}
as_unset=as_fn_unset

# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
then :
  eval 'as_fn_append ()
  {
    eval $1+=\$2
  }'
else
  as_fn_append ()
else case e in #(
  e) as_fn_append ()
  {
    eval $1=\$$1\$2
  }
  } ;;
esac
fi # as_fn_append

# as_fn_arith ARG...
# ------------------
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
then :
  eval 'as_fn_arith ()
  {
    as_val=$(( $* ))
  }'
else
  as_fn_arith ()
else case e in #(
  e) as_fn_arith ()
  {
    as_val=`expr "$@" || test $? -eq 1`
  }
  } ;;
esac
fi # as_fn_arith


if expr a : '\(a\)' >/dev/null 2>&1 &&
   test "X`expr 00001 : '.*\(...\)'`" = X001; then
  as_expr=expr
else
10980
10981
10982
10983
10984
10985
10986
10987

10988
10989
10990
10991
10992
10993
10994
11779
11780
11781
11782
11783
11784
11785

11786
11787
11788
11789
11790
11791
11792
11793







-
+







  as_dirname=false
fi

as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
	 X"$0" : 'X\(//\)$' \| \
	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X/"$0" |
printf "%s\n" X/"$0" |
    sed '/^.*\/\([^/][^/]*\)\/*$/{
	    s//\1/
	    q
	  }
	  /^X\/\(\/\/\)$/{
	    s//\1/
	    q
11002
11003
11004
11005
11006
11007
11008




11009
11010
11011
11012
11013
11014
11015
11016
11017
11018
11019
11020






11021
11022
11023
11024
11025
11026
11027
11028
11029
11030
11031
11032
11033
11034
11035



11036
11037
11038
11039
11040
11041
11042
11801
11802
11803
11804
11805
11806
11807
11808
11809
11810
11811
11812
11813
11814
11815
11816
11817
11818
11819
11820
11821
11822
11823
11824
11825
11826
11827
11828
11829
11830
11831
11832
11833
11834
11835
11836
11837
11838
11839
11840
11841



11842
11843
11844
11845
11846
11847
11848
11849
11850
11851







+
+
+
+












+
+
+
+
+
+












-
-
-
+
+
+







# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits


# Determine whether it's possible to make 'echo' print without a newline.
# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
  case `echo 'xy\c'` in
  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
  xy)  ECHO_C='\c';;
  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
       ECHO_T='	';;
  esac;;
*)
  ECHO_N='-n';;
esac

# For backward compatibility with old third-party macros, we provide
# the shell variables $as_echo and $as_echo_n.  New code should use
# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
as_echo='printf %s\n'
as_echo_n='printf %s'

rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
  rm -f conf$$.dir/conf$$.file
else
  rm -f conf$$.dir
  mkdir conf$$.dir 2>/dev/null
fi
if (echo >conf$$.file) 2>/dev/null; then
  if ln -s conf$$.file conf$$ 2>/dev/null; then
    as_ln_s='ln -s'
    # ... but there are two gotchas:
    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
    # In both cases, we have to default to `cp -pR'.
    # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail.
    # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable.
    # In both cases, we have to default to 'cp -pR'.
    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
      as_ln_s='cp -pR'
  elif ln conf$$.file conf$$ 2>/dev/null; then
    as_ln_s=ln
  else
    as_ln_s='cp -pR'
  fi
11056
11057
11058
11059
11060
11061
11062
11063

11064
11065
11066
11067
11068
11069
11070
11071
11072

11073
11074
11075
11076
11077
11078
11079
11865
11866
11867
11868
11869
11870
11871

11872
11873
11874
11875
11876
11877
11878
11879
11880

11881
11882
11883
11884
11885
11886
11887
11888







-
+








-
+







  case $as_dir in #(
  -*) as_dir=./$as_dir;;
  esac
  test -d "$as_dir" || eval $as_mkdir_p || {
    as_dirs=
    while :; do
      case $as_dir in #(
      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
      *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
      *) as_qdir=$as_dir;;
      esac
      as_dirs="'$as_qdir' $as_dirs"
      as_dir=`$as_dirname -- "$as_dir" ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$as_dir" : 'X\(//\)[^/]' \| \
	 X"$as_dir" : 'X\(//\)$' \| \
	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$as_dir" |
printf "%s\n" X"$as_dir" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
11109
11110
11111
11112
11113
11114
11115
11116


11117
11118
11119


11120
11121
11122
11123
11124
11125
11126
11127
11128
11129
11130
11131
11132
11133
11134
11135

11136
11137
11138
11139
11140
11141
11142
11918
11919
11920
11921
11922
11923
11924

11925
11926
11927
11928

11929
11930
11931
11932
11933
11934
11935
11936
11937
11938
11939
11940
11941
11942
11943
11944
11945

11946
11947
11948
11949
11950
11951
11952
11953







-
+
+


-
+
+















-
+







{
  test -f "$1" && test -x "$1"
} # as_fn_executable_p
as_test_x='test -x'
as_executable_p=as_fn_executable_p

# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated

# Sed expression to map a string onto a valid variable name.
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
as_tr_sh="eval sed '$as_sed_sh'" # deprecated


exec 6>&1
## ----------------------------------- ##
## Main body of $CONFIG_STATUS script. ##
## ----------------------------------- ##
_ASEOF
test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# Save the log message, to keep $0 and so on meaningful, and to
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by tcl $as_me 9.0, which was
generated by GNU Autoconf 2.69.  Invocation command line was
generated by GNU Autoconf 2.72.  Invocation command line was

  CONFIG_FILES    = $CONFIG_FILES
  CONFIG_HEADERS  = $CONFIG_HEADERS
  CONFIG_LINKS    = $CONFIG_LINKS
  CONFIG_COMMANDS = $CONFIG_COMMANDS
  $ $0 $@

11156
11157
11158
11159
11160
11161
11162
11163

11164
11165
11166
11167
11168
11169
11170
11967
11968
11969
11970
11971
11972
11973

11974
11975
11976
11977
11978
11979
11980
11981







-
+







config_files="$ac_config_files"
config_commands="$ac_config_commands"

_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
ac_cs_usage="\
\`$as_me' instantiates files and other configuration actions
'$as_me' instantiates files and other configuration actions
from templates according to the current configuration.  Unless the files
and actions are specified as TAGs, all are instantiated by default.

Usage: $0 [OPTION]... [TAG]...

  -h, --help       print this help, then exit
  -V, --version    print version number and configuration settings, then exit
11181
11182
11183
11184
11185
11186
11187


11188
11189

11190
11191
11192

11193
11194
11195

11196
11197
11198
11199
11200
11201
11202
11992
11993
11994
11995
11996
11997
11998
11999
12000
12001

12002
12003
12004

12005
12006
12007

12008
12009
12010
12011
12012
12013
12014
12015







+
+

-
+


-
+


-
+








Configuration commands:
$config_commands

Report bugs to the package provider."

_ACEOF
ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
tcl config.status 9.0
configured by $0, generated by GNU Autoconf 2.69,
configured by $0, generated by GNU Autoconf 2.72,
  with options \\"\$ac_cs_config\\"

Copyright (C) 2012 Free Software Foundation, Inc.
Copyright (C) 2023 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."

ac_pwd='$ac_pwd'
srcdir='$srcdir'
test -n "\$AWK" || AWK=awk
_ACEOF
11225
11226
11227
11228
11229
11230
11231
11232

11233
11234

11235
11236
11237
11238
11239
11240

11241
11242
11243
11244
11245
11246

11247
11248
11249
11250
11251
11252
11253


11254
11255
11256
11257
11258
11259
11260
11261
11262
11263
11264
11265
11266
11267
11268
11269
11270
11271
11272
11273
11274

11275
11276
11277
11278
11279
11280
11281
11282
11283
11284
11285
11286
11287
11288

11289
11290
11291
11292
11293
11294
11295
12038
12039
12040
12041
12042
12043
12044

12045
12046

12047
12048
12049
12050
12051
12052

12053
12054
12055
12056
12057
12058

12059
12060
12061
12062
12063
12064


12065
12066
12067
12068
12069
12070
12071
12072
12073
12074
12075
12076
12077
12078
12079
12080
12081
12082
12083
12084
12085
12086

12087
12088
12089
12090
12091
12092
12093
12094
12095
12096
12097
12098
12099
12100

12101
12102
12103
12104
12105
12106
12107
12108







-
+

-
+





-
+





-
+





-
-
+
+




















-
+













-
+







  esac

  case $ac_option in
  # Handling of the options.
  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
    ac_cs_recheck=: ;;
  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
    $as_echo "$ac_cs_version"; exit ;;
    printf "%s\n" "$ac_cs_version"; exit ;;
  --config | --confi | --conf | --con | --co | --c )
    $as_echo "$ac_cs_config"; exit ;;
    printf "%s\n" "$ac_cs_config"; exit ;;
  --debug | --debu | --deb | --de | --d | -d )
    debug=: ;;
  --file | --fil | --fi | --f )
    $ac_shift
    case $ac_optarg in
    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
    *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
    '') as_fn_error $? "missing file argument" ;;
    esac
    as_fn_append CONFIG_FILES " '$ac_optarg'"
    ac_need_defaults=false;;
  --he | --h |  --help | --hel | -h )
    $as_echo "$ac_cs_usage"; exit ;;
    printf "%s\n" "$ac_cs_usage"; exit ;;
  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
  | -silent | --silent | --silen | --sile | --sil | --si | --s)
    ac_cs_silent=: ;;

  # This is an error.
  -*) as_fn_error $? "unrecognized option: \`$1'
Try \`$0 --help' for more information." ;;
  -*) as_fn_error $? "unrecognized option: '$1'
Try '$0 --help' for more information." ;;

  *) as_fn_append ac_config_targets " $1"
     ac_need_defaults=false ;;

  esac
  shift
done

ac_configure_extra_args=

if $ac_cs_silent; then
  exec 6>/dev/null
  ac_configure_extra_args="$ac_configure_extra_args --silent"
fi

_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
  shift
  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
  \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
  CONFIG_SHELL='$SHELL'
  export CONFIG_SHELL
  exec "\$@"
fi

_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
exec 5>>config.log
{
  echo
  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
  $as_echo "$ac_log"
  printf "%s\n" "$ac_log"
} >&5

_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
#
# INIT-COMMANDS
#
11307
11308
11309
11310
11311
11312
11313
11314

11315
11316
11317
11318
11319
11320
11321
11322
11323
11324
11325


11326
11327
11328
11329
11330
11331
11332
11333

11334
11335
11336
11337
11338
11339
11340
12120
12121
12122
12123
12124
12125
12126

12127
12128
12129
12130
12131
12132
12133
12134
12135
12136


12137
12138
12139
12140
12141
12142
12143
12144
12145

12146
12147
12148
12149
12150
12151
12152
12153







-
+









-
-
+
+







-
+







    "Tclsh-Info.plist") CONFIG_FILES="$CONFIG_FILES Tclsh-Info.plist:../macosx/Tclsh-Info.plist.in" ;;
    "Tcl.framework") CONFIG_COMMANDS="$CONFIG_COMMANDS Tcl.framework" ;;
    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile:../unix/Makefile.in" ;;
    "dltest/Makefile") CONFIG_FILES="$CONFIG_FILES dltest/Makefile:../unix/dltest/Makefile.in" ;;
    "tclConfig.sh") CONFIG_FILES="$CONFIG_FILES tclConfig.sh:../unix/tclConfig.sh.in" ;;
    "tcl.pc") CONFIG_FILES="$CONFIG_FILES tcl.pc:../unix/tcl.pc.in" ;;

  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
  *) as_fn_error $? "invalid argument: '$ac_config_target'" "$LINENO" 5;;
  esac
done


# If the user did not use the arguments to specify the items to instantiate,
# then the envvar interface is used.  Set only those that are not.
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
  test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
  test ${CONFIG_COMMANDS+y} || CONFIG_COMMANDS=$config_commands
fi

# Have a temporary directory for convenience.  Make it in the build tree
# simply because there is no reason against having it here, and in addition,
# creating and moving files from /tmp can sometimes cause problems.
# Hook for its removal unless debugging.
# Note that there is a small window in which the directory will not be cleaned:
# after its creation but before its name has been assigned to `$tmp'.
# after its creation but before its name has been assigned to '$tmp'.
$debug ||
{
  tmp= ac_tmp=
  trap 'exit_status=$?
  : "${ac_tmp:=$tmp}"
  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
' 0
11350
11351
11352
11353
11354
11355
11356
11357

11358
11359
11360
11361
11362
11363
11364
12163
12164
12165
12166
12167
12168
12169

12170
12171
12172
12173
12174
12175
12176
12177







-
+







  tmp=./conf$$-$RANDOM
  (umask 077 && mkdir "$tmp")
} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
ac_tmp=$tmp

# Set up the scripts for CONFIG_FILES section.
# No need to generate them if there are no CONFIG_FILES.
# This happens for instance with `./config.status config.h'.
# This happens for instance with './config.status config.h'.
if test -n "$CONFIG_FILES"; then


ac_cr=`echo X | tr X '\015'`
# On cygwin, bash can eat \r inside `` if the user requested igncr.
# But we know of no other shell where ac_cr would be empty at this
# point, so we can use a bashism as a fallback.
11516
11517
11518
11519
11520
11521
11522
11523

11524
11525
11526
11527
11528
11529
11530
12329
12330
12331
12332
12333
12334
12335

12336
12337
12338
12339
12340
12341
12342
12343







-
+







for ac_tag
do
  case $ac_tag in
  :[FHLC]) ac_mode=$ac_tag; continue;;
  esac
  case $ac_mode$ac_tag in
  :[FHL]*:*);;
  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
  :L* | :C*:*) as_fn_error $? "invalid tag '$ac_tag'" "$LINENO" 5;;
  :[FH]-) ac_tag=-:-;;
  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
  esac
  ac_save_IFS=$IFS
  IFS=:
  set x $ac_tag
  IFS=$ac_save_IFS
11538
11539
11540
11541
11542
11543
11544
11545

11546
11547
11548
11549
11550
11551

11552
11553

11554
11555
11556
11557

11558
11559
11560
11561

11562
11563
11564
11565
11566


11567
11568
11569
11570
11571

11572
11573
11574
11575
11576
11577
11578
11579
11580
11581
11582
11583
11584
11585
11586
11587
11588

11589
11590
11591
11592
11593
11594
11595
12351
12352
12353
12354
12355
12356
12357

12358
12359
12360
12361
12362
12363

12364
12365

12366
12367
12368
12369

12370
12371
12372
12373

12374
12375
12376
12377


12378
12379
12380
12381
12382
12383

12384
12385
12386
12387
12388
12389
12390
12391
12392
12393
12394
12395
12396
12397
12398
12399
12400

12401
12402
12403
12404
12405
12406
12407
12408







-
+





-
+

-
+



-
+



-
+



-
-
+
+




-
+
















-
+







    ac_file_inputs=
    for ac_f
    do
      case $ac_f in
      -) ac_f="$ac_tmp/stdin";;
      *) # Look for the file first in the build tree, then in the source tree
	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
	 # because $ac_f cannot contain `:'.
	 # because $ac_f cannot contain ':'.
	 test -f "$ac_f" ||
	   case $ac_f in
	   [\\/$]*) false;;
	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
	   esac ||
	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
	   as_fn_error 1 "cannot find input file: '$ac_f'" "$LINENO" 5;;
      esac
      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
      case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
      as_fn_append ac_file_inputs " '$ac_f'"
    done

    # Let's still pretend it is `configure' which instantiates (i.e., don't
    # Let's still pretend it is 'configure' which instantiates (i.e., don't
    # use $as_me), people would be surprised to read:
    #    /* config.h.  Generated by config.status.  */
    configure_input='Generated from '`
	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
	  printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
	`' by configure.'
    if test x"$ac_file" != x-; then
      configure_input="$ac_file.  $configure_input"
      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
$as_echo "$as_me: creating $ac_file" >&6;}
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
printf "%s\n" "$as_me: creating $ac_file" >&6;}
    fi
    # Neutralize special characters interpreted by sed in replacement strings.
    case $configure_input in #(
    *\&* | *\|* | *\\* )
       ac_sed_conf_input=`$as_echo "$configure_input" |
       ac_sed_conf_input=`printf "%s\n" "$configure_input" |
       sed 's/[\\\\&|]/\\\\&/g'`;; #(
    *) ac_sed_conf_input=$configure_input;;
    esac

    case $ac_tag in
    *:-:* | *:-) cat >"$ac_tmp/stdin" \
      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
    esac
    ;;
  esac

  ac_dir=`$as_dirname -- "$ac_file" ||
$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$ac_file" : 'X\(//\)[^/]' \| \
	 X"$ac_file" : 'X\(//\)$' \| \
	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$ac_file" |
printf "%s\n" X"$ac_file" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
11605
11606
11607
11608
11609
11610
11611
11612

11613
11614

11615
11616
11617
11618
11619
11620
11621
12418
12419
12420
12421
12422
12423
12424

12425
12426

12427
12428
12429
12430
12431
12432
12433
12434







-
+

-
+







	  s/.*/./; q'`
  as_dir="$ac_dir"; as_fn_mkdir_p
  ac_builddir=.

case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
  ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
  # A ".." for each directory in $ac_dir_suffix.
  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
  ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
  case $ac_top_builddir_sub in
  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
  esac ;;
esac
ac_abs_top_builddir=$ac_pwd
ac_abs_builddir=$ac_pwd$ac_dir_suffix
11660
11661
11662
11663
11664
11665
11666
11667
11668


11669
11670
11671
11672
11673
11674
11675
11676
11677
11678
11679
11680
11681

11682
11683
11684
11685
11686
11687
11688
12473
12474
12475
12476
12477
12478
12479


12480
12481
12482
12483
12484
12485
12486
12487
12488
12489
12490
12491
12492
12493

12494
12495
12496
12497
12498
12499
12500
12501







-
-
+
+












-
+







/@docdir@/p
/@infodir@/p
/@localedir@/p
/@mandir@/p'
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
  ac_datarootdir_hack='
  s&@datadir@&$datadir&g
  s&@docdir@&$docdir&g
  s&@infodir@&$infodir&g
  s&@localedir@&$localedir&g
  s&@mandir@&$mandir&g
  s&\\\${datarootdir}&$datarootdir&g' ;;
esac
_ACEOF

# Neutralize VPATH when `$srcdir' = `.'.
# Neutralize VPATH when '$srcdir' = '.'.
# Shell code in configure.ac might set extrasub.
# FIXME: do we really want to maintain this feature?
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_sed_extra="$ac_vpsub
$extrasub
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
11703
11704
11705
11706
11707
11708
11709
11710

11711
11712

11713
11714
11715
11716
11717
11718
11719
11720
11721
11722
11723
11724
11725


11726
11727
11728
11729
11730
11731
11732
11733
11734
11735
11736





11737
11738
11739
11740
11741
11742
11743
12516
12517
12518
12519
12520
12521
12522

12523
12524

12525
12526
12527
12528
12529
12530
12531
12532
12533
12534
12535
12536


12537
12538
12539
12540
12541
12542
12543
12544





12545
12546
12547
12548
12549
12550
12551
12552
12553
12554
12555
12556







-
+

-
+











-
-
+
+






-
-
-
-
-
+
+
+
+
+







eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5

test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
      "$ac_tmp/out"`; test -z "$ac_out"; } &&
  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable 'datarootdir'
which seems to be undefined.  Please make sure it is defined" >&5
$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable 'datarootdir'
which seems to be undefined.  Please make sure it is defined" >&2;}

  rm -f "$ac_tmp/stdin"
  case $ac_file in
  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
  esac \
  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
 ;;


  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
$as_echo "$as_me: executing $ac_file commands" >&6;}
  :C)  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
printf "%s\n" "$as_me: executing $ac_file commands" >&6;}
 ;;
  esac


  case $ac_file$ac_mode in
    "Tcl.framework":C) n=Tcl &&
        f=$n.framework && v=Versions/$VERSION &&
        rm -rf $f && mkdir -p $f/$v/Resources &&
        ln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v &&
        ln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist &&
        unset n f v
	f=$n.framework && v=Versions/$VERSION &&
	rm -rf $f && mkdir -p $f/$v/Resources &&
	ln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v &&
	ln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist &&
	unset n f v
     ;;

  esac
done # for ac_tag


as_fn_exit 0
11765
11766
11767
11768
11769
11770
11771
11772
11773


11774
11775
11776

12578
12579
12580
12581
12582
12583
12584


12585
12586
12587
12588
12589
12590







-
-
+
+



+
  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
  exec 5>>config.log
  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
  # would make configure fail if this is the last instruction.
  $ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi



Changes to unix/configure.ac.

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
30
31
32
33
34
35
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
30
31
32
33
34
35
36






-
+












-
-
+
+
+






-
+







#! /bin/bash -norc
dnl	This file is an input file used by the GNU "autoconf" program to
dnl	generate the file "configure", which is run during Tcl installation
dnl	to configure the system for the local environment.

AC_INIT([tcl],[9.0])
AC_PREREQ(2.69)
AC_PREREQ([2.69])

dnl This is only used when included from macosx/configure.ac
m4_ifdef([SC_USE_CONFIG_HEADERS], [
    AC_CONFIG_HEADERS([tclConfig.h:../unix/tclConfig.h.in])
    AC_CONFIG_COMMANDS_PRE([DEFS="-DHAVE_TCL_CONFIG_H  -imacros tclConfig.h"])
    AH_TOP([
    #ifndef _TCLCONFIG
    #define _TCLCONFIG])
    AH_BOTTOM([
    /* Undef unused package specific autoheader defines so that we can
     * include both tclConfig.h and tkConfig.h at the same time: */
    /* override */ #undef PACKAGE_NAME
    /* override */ #undef PACKAGE_STRING
    /* override */ #undef PACKAGE_TARNAME
    /* override */ #undef PACKAGE_TARNAME
    /* override */ #undef PACKAGE_VERSION
    /* override */ #undef PACKAGE_STRING
    #endif /* _TCLCONFIG */])
])

TCL_VERSION=9.0
TCL_MAJOR_VERSION=9
TCL_MINOR_VERSION=0
TCL_PATCH_LEVEL="a2"
TCL_PATCH_LEVEL=".1"
VERSION=${TCL_VERSION}

EXTRA_INSTALL_BINARIES=${EXTRA_INSTALL_BINARIES:-"@:"}
EXTRA_BUILD_HTML=${EXTRA_BUILD_HTML:-"@:"}

#------------------------------------------------------------------------
# Setup configure arguments for bundled packages
109
110
111
112
113
114
115
116

117
118
119
120
121
122
123
110
111
112
113
114
115
116

117
118
119
120
121
122
123
124







-
+







# It makes compiling go faster.  (This is only a performance feature.)
#------------------------------------------------------------------------

if test -z "$no_pipe" && test -n "$GCC"; then
    AC_CACHE_CHECK([if the compiler understands -pipe],
	tcl_cv_cc_pipe, [
	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe"
	AC_TRY_COMPILE(,, tcl_cv_cc_pipe=yes, tcl_cv_cc_pipe=no)
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[tcl_cv_cc_pipe=yes],[tcl_cv_cc_pipe=no])
	CFLAGS=$hold_cflags])
    if test $tcl_cv_cc_pipe = yes; then
	CFLAGS="$CFLAGS -pipe"
    fi
fi

#------------------------------------------------------------------------
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
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







+

-






-
+

-
+









+
+







  AC_SEARCH_LIBS([deflateSetHeader],[z],[],[
    zlib_ok=no
  ])])
AS_IF([test $zlib_ok = no], [
  AC_SUBST(ZLIB_OBJS,[\${ZLIB_OBJS}])
  AC_SUBST(ZLIB_SRCS,[\${ZLIB_SRCS}])
  AC_SUBST(ZLIB_INCLUDE,[-I\${ZLIB_DIR}])
  AC_DEFINE(TCL_WITH_INTERNAL_ZLIB, 1, [Tcl with internal zlib])
])
AC_DEFINE(HAVE_ZLIB, 1, [Is there an installed zlib?])

#------------------------------------------------------------------------
#	Add stuff for libtommath

libtommath_ok=yes
AC_ARG_WITH(system-libtommath,
AC_HELP_STRING([--with-system-libtommath],
AS_HELP_STRING([--with-system-libtommath],
	[use external libtommath (default: true if available, false otherwise)]),
	libtommath_ok=${withval})
	[libtommath_ok=${withval}])
if test x"${libtommath_ok}" = x -o x"${libtommath_ok}" != xno; then
    AC_CHECK_HEADER([tommath.h],[
	AC_CHECK_TYPE([mp_int],[],[libtommath_ok=no],[#include <tommath.h>])],[
	libtommath_ok=no])
    AS_IF([test $libtommath_ok = yes], [
	AC_CHECK_LIB([tommath],[mp_log_u32],[MATH_LIBS="$MATH_LIBS -ltommath"],[
    libtommath_ok=no])])
fi
AS_IF([test $libtommath_ok = yes], [
  AC_SUBST(TCL_PC_REQUIRES_PRIVATE, ['libtommath >= 1.2.0,'])
  AC_SUBST(TCL_PC_CFLAGS, ['-DTCL_WITH_EXTERNAL_TOMMATH'])
  AC_DEFINE(TCL_WITH_EXTERNAL_TOMMATH, 1, [Tcl with external libtommath])
], [
  AC_SUBST(TOMMATH_OBJS,[\${TOMMATH_OBJS}])
  AC_SUBST(TOMMATH_SRCS,[\${TOMMATH_SRCS}])
  AC_SUBST(TOMMATH_INCLUDE,[-I\${TOMMATH_DIR}])
])

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
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







-
+











-
+



+
+
+







SC_TCL_64BIT_FLAGS

#--------------------------------------------------------------------
#	Check endianness because we can optimize comparisons of
#	Tcl_UniChar strings to memcmp on big-endian systems.
#--------------------------------------------------------------------

AC_C_BIGENDIAN
AC_C_BIGENDIAN(,,,[#])

#--------------------------------------------------------------------
#	Supply substitutes for missing POSIX library procedures, or
#	set flags so Tcl uses alternate procedures.
#--------------------------------------------------------------------

# Check if Posix compliant getcwd exists, if not we'll use getwd.
AC_CHECK_FUNCS(getcwd, , [AC_DEFINE(USEGETWD, 1, [Is getcwd Posix-compliant?])])
# Nb: if getcwd uses popen and pwd(1) (like SunOS 4) we should really
# define USEGETWD even if the posix getcwd exists. Add a test ?

AC_REPLACE_FUNCS(mkstemp opendir strtol waitpid)
AC_REPLACE_FUNCS(mkstemp waitpid)
AC_CHECK_FUNC(strerror, , [AC_DEFINE(NO_STRERROR, 1, [Do we have strerror()])])
AC_CHECK_FUNC(getwd, , [AC_DEFINE(NO_GETWD, 1, [Do we have getwd()])])
AC_CHECK_FUNC(wait3, , [AC_DEFINE(NO_WAIT3, 1, [Do we have wait3()])])
AC_CHECK_FUNC(fork, , [AC_DEFINE(NO_FORK, 1, [Do we have fork()])])
AC_CHECK_FUNC(mknod, , [AC_DEFINE(NO_MKNOD, 1, [Do we have mknod()])])
AC_CHECK_FUNC(tcdrain, , [AC_DEFINE(NO_TCDRAIN, 1, [Do we have tcdrain()])])
AC_CHECK_FUNC(uname, , [AC_DEFINE(NO_UNAME, 1, [Do we have uname()])])

if test "`uname -s`" = "Darwin" && \
	test "`uname -r | awk -F. '{print [$]1}'`" -lt 7; then
    # prior to Darwin 7, realpath is not threadsafe, so don't
    # use it when threads are enabled, c.f. bug # 711232
    ac_cv_func_realpath=no
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
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







-
-
+
+













+
+
+
+
+
+
+







#	systems like OSF/1 have a sys/select.h that's of no use, and
#	other systems like SCO UNIX have a sys/select.h that's
#	pernicious.  If "fd_set" isn't defined anywhere then set a
#	special flag.
#--------------------------------------------------------------------

AC_CACHE_CHECK([for fd_set in sys/types], tcl_cv_type_fd_set, [
    AC_TRY_COMPILE([#include <sys/types.h>],[fd_set readMask, writeMask;],
	tcl_cv_type_fd_set=yes, tcl_cv_type_fd_set=no)])
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>]], [[fd_set readMask, writeMask;]])],
	[tcl_cv_type_fd_set=yes],[tcl_cv_type_fd_set=no])])
tcl_ok=$tcl_cv_type_fd_set
if test $tcl_ok = no; then
    AC_CACHE_CHECK([for fd_mask in sys/select], tcl_cv_grep_fd_mask, [
	AC_EGREP_HEADER(fd_mask, sys/select.h,
	     tcl_cv_grep_fd_mask=present, tcl_cv_grep_fd_mask=missing)])
    if test $tcl_cv_grep_fd_mask = present; then
	AC_DEFINE(HAVE_SYS_SELECT_H, 1, [Should we include <sys/select.h>?])
	tcl_ok=yes
    fi
fi
if test $tcl_ok = no; then
    AC_DEFINE(NO_FD_SET, 1, [Do we have fd_set?])
fi

AC_CACHE_CHECK([for pselect], tcl_cv_func_pselect, [
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>]], [[void *func = pselect;]])],[tcl_cv_func_pselect=yes],[tcl_cv_func_pselect=no])])
tcl_ok=$tcl_cv_func_pselect
if test $tcl_ok = yes; then
    AC_DEFINE(HAVE_PSELECT, 1, [Should we use pselect()?])
fi

#------------------------------------------------------------------------
#	Options for the notifier. Checks for epoll(7) on Linux, and
#	kqueue(2) on {DragonFly,Free,Net,Open}BSD
#------------------------------------------------------------------------

AC_MSG_CHECKING([for advanced notifier support])
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
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
467
468
469
470
471
472
473
474
475
476
477


478
479
480
481

482
483
484
485
486
487
488
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







-
+




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-











-
+


-
-
-
+
+
+




-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
-










-
-
+
+



-
+







#--------------------------------------------------------------------
#	Some systems (e.g., IRIX 4.0.5) lack some fields in struct stat. But
#	we might be able to use fstatfs instead. Some systems (OpenBSD?) also
#	lack blkcnt_t.
#--------------------------------------------------------------------

if test "$ac_cv_cygwin" != "yes"; then
    AC_CHECK_MEMBERS([struct stat.st_blocks, struct stat.st_blksize])
    AC_CHECK_MEMBERS([struct stat.st_blocks, struct stat.st_blksize, struct stat.st_rdev])
fi
AC_CHECK_TYPES([blkcnt_t])
AC_CHECK_FUNC(fstatfs, , [AC_DEFINE(NO_FSTATFS, 1, [Do we have fstatfs()?])])

#--------------------------------------------------------------------
#       Some system have no memcmp or it does not work with 8 bit data, this
#       checks it and add memcmp.o to LIBOBJS if needed
#--------------------------------------------------------------------

AC_FUNC_MEMCMP

#--------------------------------------------------------------------
#       Some system like SunOS 4 and other BSD like systems have no memmove
#       (we assume they have bcopy instead). {The replacement define is in
#       compat/string.h}
#--------------------------------------------------------------------

AC_CHECK_FUNC(memmove, , [
    AC_DEFINE(NO_MEMMOVE, 1, [Do we have memmove()?])
    AC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?]) ])

#--------------------------------------------------------------------
#	On some systems strstr is broken: it returns a pointer even even if
#	the original string is empty.
#--------------------------------------------------------------------

SC_TCL_CHECK_BROKEN_FUNC(strstr, [
    exit(strstr("\0test", "test") ? 1 : 0);
])

#--------------------------------------------------------------------
#	Check for strtoul function.  This is tricky because under some
#	versions of AIX strtoul returns an incorrect terminator
#	pointer for the string "0".
#--------------------------------------------------------------------

SC_TCL_CHECK_BROKEN_FUNC(strtoul, [
    char *term, *string = "0";
    exit(strtoul(string,&term,0) != 0 || term != string+1);
])

#--------------------------------------------------------------------
#	Check for various typedefs and provide substitutes if
#	they don't exist.
#--------------------------------------------------------------------

AC_TYPE_MODE_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_TYPE_UID_T

AC_CACHE_CHECK([for socklen_t], tcl_cv_type_socklen_t, [
    AC_TRY_COMPILE([
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	#include <sys/types.h>
	#include <sys/socket.h>
    ],[
    	socklen_t foo;
    ],[tcl_cv_type_socklen_t=yes],[tcl_cv_type_socklen_t=no])])
    ]], [[
	socklen_t foo;
    ]])],[tcl_cv_type_socklen_t=yes],[tcl_cv_type_socklen_t=no])])
if test $tcl_cv_type_socklen_t = no; then
    AC_DEFINE(socklen_t, int, [Define as int if socklen_t is not available])
fi

AC_CHECK_TYPE([intptr_t], [
AC_CHECK_TYPES([intptr_t, uintptr_t],,,[[
    AC_DEFINE([HAVE_INTPTR_T], 1, [Do we have the intptr_t type?])], [
    AC_CACHE_CHECK([for pointer-size signed integer type], tcl_cv_intptr_t, [
    for tcl_cv_intptr_t in "int" "long" "long long" none; do
	if test "$tcl_cv_intptr_t" != none; then
	    AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],
		    [[sizeof (void *) <= sizeof ($tcl_cv_intptr_t)]])],
		[tcl_ok=yes], [tcl_ok=no])
	    test "$tcl_ok" = yes && break; fi
    done])
    if test "$tcl_cv_intptr_t" != none; then
	AC_DEFINE_UNQUOTED([intptr_t], [$tcl_cv_intptr_t], [Signed integer
	   type wide enough to hold a pointer.])
    fi
])
AC_CHECK_TYPE([uintptr_t], [
    AC_DEFINE([HAVE_UINTPTR_T], 1, [Do we have the uintptr_t type?])], [
    AC_CACHE_CHECK([for pointer-size unsigned integer type], tcl_cv_uintptr_t, [
    for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \
	    none; do
	if test "$tcl_cv_uintptr_t" != none; then
	    AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],
		    [[sizeof (void *) <= sizeof ($tcl_cv_uintptr_t)]])],
		[tcl_ok=yes], [tcl_ok=no])
	    test "$tcl_ok" = yes && break; fi
    done])
    if test "$tcl_cv_uintptr_t" != none; then
	AC_DEFINE_UNQUOTED([uintptr_t], [$tcl_cv_uintptr_t], [Unsigned integer
	   type wide enough to hold a pointer.])
    fi
])

#include <stdint.h>
#--------------------------------------------------------------------
#	If a system doesn't have an opendir function (man, that's old!)
#	then we have to supply a different version of dirent.h which
#	is compatible with the substitute version of opendir that's
#	provided.  This version only works with V7-style directories.
#--------------------------------------------------------------------

]])
AC_CHECK_FUNC(opendir, , [AC_DEFINE(USE_DIRENT2_H, 1, [May we include <dirent2.h>?])])

#--------------------------------------------------------------------
#	The check below checks whether <sys/wait.h> defines the type
#	"union wait" correctly.  It's needed because of weirdness in
#	HP-UX where "union wait" is defined in both the BSD and SYS-V
#	environments.  Checking the usability of WIFEXITED seems to do
#	the trick.
#--------------------------------------------------------------------

AC_CACHE_CHECK([union wait], tcl_cv_union_wait, [
    AC_TRY_LINK([#include <sys/types.h>
#include <sys/wait.h>], [
    AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
#include <sys/wait.h>]], [[
union wait x;
WIFEXITED(x);		/* Generates compiler error if WIFEXITED
			 * uses an int. */
    ], tcl_cv_union_wait=yes, tcl_cv_union_wait=no)])
    ]])],[tcl_cv_union_wait=yes],[tcl_cv_union_wait=no])])
if test $tcl_cv_union_wait = no; then
    AC_DEFINE(NO_UNION_WAIT, 1, [Do we have a usable 'union wait'?])
fi

#--------------------------------------------------------------------
#	Check whether there is an strncasecmp function on this system.
#	This is a bit tricky because under SCO it's in -lsocket and
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
558
559
560
561
562
563
564
565
566




567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617

618
619
620
621
622
623
624
625
626
627


628
629
630
631
632
633
634
635

636
637
638
639
640
641
642
643
644
645

646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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

707
708
709
710
711
712
713
463
464
465
466
467
468
469

470
471
472

473
474
475
476
477
478
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
558
559
560

561
562
563
564
565
566
567
568
569
570

571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590

591
592
593
594

595
596
597
598

599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615

616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631

632
633
634
635
636
637
638
639







-
+


-
+









-
+


















-
-
-
-
+
+
+
+

















-
-
-
-
-
-
-
-
-
-
-
-












-








-
+








-
-
+
+







-
+









-
+



















-
+



-
+



-
+
















-
+















-
+







#	The following code checks to see whether it is possible to get
#	signed chars on this platform.  This is needed in order to
#	properly generate sign-extended ints from character values.
#--------------------------------------------------------------------

AC_C_CHAR_UNSIGNED
AC_CACHE_CHECK([signed char declarations], tcl_cv_char_signed, [
    AC_TRY_COMPILE(, [
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
	signed char *p;
	p = 0;
	], tcl_cv_char_signed=yes, tcl_cv_char_signed=no)])
	]])],[tcl_cv_char_signed=yes],[tcl_cv_char_signed=no])])
if test $tcl_cv_char_signed = yes; then
    AC_DEFINE(HAVE_SIGNED_CHAR, 1, [Are characters signed?])
fi

#--------------------------------------------------------------------
#  Does putenv() copy or not?  We need to know to avoid memory leaks.
#--------------------------------------------------------------------

AC_CACHE_CHECK([for a putenv() that copies the buffer], tcl_cv_putenv_copy, [
    AC_TRY_RUN([
    AC_RUN_IFELSE([AC_LANG_SOURCE([[
	#include <stdlib.h>
	#include <string.h>
	#define OURVAR "havecopy=yes"
	int main (int argc, char *argv[])
	{
	    char *foo, *bar;
	    foo = (char *)strdup(OURVAR);
	    putenv(foo);
	    strcpy((char *)(strchr(foo, '=') + 1), "no");
	    bar = getenv("havecopy");
	    if (!strcmp(bar, "no")) {
		/* doesnt copy */
		return 0;
	    } else {
		/* does copy */
		return 1;
	    }
	}
    ],
    tcl_cv_putenv_copy=no,
    tcl_cv_putenv_copy=yes,
    tcl_cv_putenv_copy=no)])
    ]])],
    [tcl_cv_putenv_copy=no],
    [tcl_cv_putenv_copy=yes],
    [tcl_cv_putenv_copy=no])])
if test $tcl_cv_putenv_copy = yes; then
    AC_DEFINE(HAVE_PUTENV_THAT_COPIES, 1,
	[Does putenv() copy strings or incorporate them by reference?])
fi

#--------------------------------------------------------------------
# Check for support of nl_langinfo function
#--------------------------------------------------------------------

SC_ENABLE_LANGINFO

#--------------------------------------------------------------------
# Check for support of cfmakeraw, chflags and mkstemps functions
#--------------------------------------------------------------------

AC_CHECK_FUNCS(cfmakeraw chflags mkstemps)

#--------------------------------------------------------------------
# Check for support of isnan() function or macro
#--------------------------------------------------------------------

AC_CACHE_CHECK([isnan], tcl_cv_isnan, [
    AC_TRY_LINK([#include <math.h>], [
isnan(0.0);			/* Generates an error if isnan is missing */
], tcl_cv_isnan=yes, tcl_cv_isnan=no)])
if test $tcl_cv_isnan = no; then
    AC_DEFINE(NO_ISNAN, 1, [Do we have a usable 'isnan'?])
fi

#--------------------------------------------------------------------
# Darwin specific API checks and defines
#--------------------------------------------------------------------

if test "`uname -s`" = "Darwin" ; then
    AC_CHECK_FUNCS(getattrlist)
    AC_CHECK_HEADERS(copyfile.h)
    AC_CHECK_FUNCS(copyfile)
    if test $tcl_corefoundation = yes; then
	AC_CHECK_HEADERS(libkern/OSAtomic.h)
	AC_CHECK_FUNCS(OSSpinLockLock)
    fi
    AC_DEFINE(USE_VFORK, 1, [Should we use vfork() instead of fork()?])
    AC_DEFINE(TCL_LOAD_FROM_MEMORY, 1,
	[Can this platform load code from memory?])
    AC_DEFINE(TCL_WIDE_CLICKS, 1,
	[Does this platform have wide high-resolution clicks?])
    AC_CHECK_HEADERS(AvailabilityMacros.h)
    if test "$ac_cv_header_AvailabilityMacros_h" = yes; then
	AC_CACHE_CHECK([if weak import is available], tcl_cv_cc_weak_import, [
	    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
	    AC_TRY_LINK([
	    AC_LINK_IFELSE([AC_LANG_PROGRAM([[
		    #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
		    #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020
		    #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020
		    #endif
		    #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1020
		    #error MAC_OS_X_VERSION_MIN_REQUIRED < 1020
		    #endif
		    int rand(void) __attribute__((weak_import));
		], [rand();],
		tcl_cv_cc_weak_import=yes, tcl_cv_cc_weak_import=no)
		]], [[rand();]])],
		[tcl_cv_cc_weak_import=yes],[tcl_cv_cc_weak_import=no])
	    CFLAGS=$hold_cflags])
	if test $tcl_cv_cc_weak_import = yes; then
	    AC_DEFINE(HAVE_WEAK_IMPORT, 1, [Is weak import available?])
	fi
	AC_CACHE_CHECK([if Darwin SUSv3 extensions are available],
	    tcl_cv_cc_darwin_c_source, [
	    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
	    AC_TRY_COMPILE([
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
		    #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
		    #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
		    #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
		    #endif
		    #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1050
		    #error MAC_OS_X_VERSION_MIN_REQUIRED < 1050
		    #endif
		    #define _DARWIN_C_SOURCE 1
		    #include <sys/cdefs.h>
		],,tcl_cv_cc_darwin_c_source=yes, tcl_cv_cc_darwin_c_source=no)
		]], [[]])],[tcl_cv_cc_darwin_c_source=yes],[tcl_cv_cc_darwin_c_source=no])
	    CFLAGS=$hold_cflags])
	if test $tcl_cv_cc_darwin_c_source = yes; then
	    AC_DEFINE(_DARWIN_C_SOURCE, 1,
		    [Are Darwin SUSv3 extensions available?])
	fi
    fi
    # Build .bundle dltest binaries in addition to .dylib
    DLTEST_LD='${CC} -bundle -Wl,-w ${CFLAGS} ${LDFLAGS}'
    DLTEST_SUFFIX=".bundle"
else
    DLTEST_LD='${SHLIB_LD}'
    DLTEST_SUFFIX=""
fi

#--------------------------------------------------------------------
#	Check for support of fts functions (readdir replacement)
#--------------------------------------------------------------------

AC_CACHE_CHECK([for fts], tcl_cv_api_fts, [
    AC_TRY_LINK([
    AC_LINK_IFELSE([AC_LANG_PROGRAM([[
	    #include <sys/param.h>
	    #include <sys/stat.h>
	    #include <fts.h>
	], [
	]], [[
	    char*const p[2] = {"/", NULL};
	    FTS *f = fts_open(p, FTS_PHYSICAL|FTS_NOCHDIR|FTS_NOSTAT, NULL);
	    FTSENT *e = fts_read(f); fts_close(f);
	], tcl_cv_api_fts=yes, tcl_cv_api_fts=no)])
	]])],[tcl_cv_api_fts=yes],[tcl_cv_api_fts=no])])
if test $tcl_cv_api_fts = yes; then
    AC_DEFINE(HAVE_FTS, 1, [Do we have fts functions?])
fi

#--------------------------------------------------------------------
#	The statements below check for systems where POSIX-style non-blocking
#	I/O (O_NONBLOCK) doesn't work or is unimplemented. On these systems
#	(mostly older ones), use the old BSD-style FIONBIO approach instead.
#--------------------------------------------------------------------

SC_BLOCKING_STYLE

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

AC_MSG_CHECKING([whether to use dll unloading])
AC_ARG_ENABLE(dll-unloading,
    AC_HELP_STRING([--enable-dll-unloading],
    AS_HELP_STRING([--enable-dll-unloading],
	[enable the 'unload' command (default: on)]),
    [tcl_ok=$enableval], [tcl_ok=yes])
if test $tcl_ok = yes; then
    AC_DEFINE(TCL_UNLOAD_DLLS, 1, [Do we allow unloading of shared libraries?])
fi
AC_MSG_RESULT([$tcl_ok])

#------------------------------------------------------------------------
#	Check whether the timezone data is supplied by the OS or has
#	to be installed by Tcl. The default is autodetection, but can
#	be overridden on the configure command line either way.
#------------------------------------------------------------------------

AC_MSG_CHECKING([for timezone data])
AC_ARG_WITH(tzdata,
    AC_HELP_STRING([--with-tzdata],
    AS_HELP_STRING([--with-tzdata],
	[install timezone data (default: autodetect)]),
    [tcl_ok=$withval], [tcl_ok=auto])
#
# Any directories that get added here must also be added to the
# search path in ::tcl::clock::Initialize (library/clock.tcl).
#
case $tcl_ok in
747
748
749
750
751
752
753
754

755
756
757
758
759
760
761
673
674
675
676
677
678
679

680
681
682
683
684
685
686
687







-
+







fi

#--------------------------------------------------------------------
#	DTrace support
#--------------------------------------------------------------------

AC_ARG_ENABLE(dtrace,
    AC_HELP_STRING([--enable-dtrace],
    AS_HELP_STRING([--enable-dtrace],
	[build with DTrace support (default: off)]),
    [tcl_ok=$enableval], [tcl_ok=no])
if test $tcl_ok = yes; then
    AC_CHECK_HEADER(sys/sdt.h, [tcl_ok=yes], [tcl_ok=no])
fi
if test $tcl_ok = yes; then
    AC_PATH_PROG(DTRACE, dtrace,, [$PATH:/usr/sbin])
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837

838
839
840
841
842
843
844
845






846
847
848
849
850
851
852
704
705
706
707
708
709
710
711
712














































713
714
715
716

717
718
719






720
721
722
723
724
725
726
727
728
729
730
731
732









-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-




-
+


-
-
-
-
-
-
+
+
+
+
+
+







	    # tclDTrace.o and the combined object file above.
	    AR='/usr/ccs/bin/ar'
	    RANLIB='/usr/ccs/bin/ranlib'
	fi
    fi
fi
AC_MSG_RESULT([$tcl_ok])

#--------------------------------------------------------------------
#	Zipfs support - Tip 430
#--------------------------------------------------------------------
AC_ARG_ENABLE(zipfs,
    AC_HELP_STRING([--enable-zipfs],
	[build with Zipfs support (default: on)]),
    [tcl_ok=$enableval], [tcl_ok=yes])
if test "$tcl_ok" = "yes" ; then
    #
    # Find a native compiler
    #
    AX_CC_FOR_BUILD
    #
    # Find a native zip implementation
    #
    SC_ZIPFS_SUPPORT
	ZIPFS_BUILD=1
	TCL_ZIP_FILE=libtcl_${TCL_MAJOR_VERSION}_${TCL_MINOR_VERSION}_${TCL_PATCH_LEVEL}.zip
else
	ZIPFS_BUILD=0
	TCL_ZIP_FILE=
fi
# Do checking message here to not mess up interleaved configure output
AC_MSG_CHECKING([for building with zipfs])
if test "${ZIPFS_BUILD}" = 1; then
    if test "${SHARED_BUILD}" = 0; then
       ZIPFS_BUILD=2;
       AC_DEFINE(ZIPFS_BUILD, 2, [Are we building with zipfs enabled?])
       INSTALL_LIBRARIES=install-libraries-zipfs-static
       AC_MSG_RESULT([yes])
     else
       AC_DEFINE(ZIPFS_BUILD, 1, [Are we building with zipfs enabled?])\
       INSTALL_LIBRARIES=install-libraries-zipfs-shared
       AC_MSG_RESULT([yes])
    fi
else
AC_MSG_RESULT([no])
INSTALL_LIBRARIES=install-libraries
INSTALL_MSGS=install-msgs
fi
AC_SUBST(ZIPFS_BUILD)
AC_SUBST(TCL_ZIP_FILE)
AC_SUBST(INSTALL_LIBRARIES)
AC_SUBST(INSTALL_MSGS)


#--------------------------------------------------------------------
# The check below checks whether the cpuid instruction is usable.
#--------------------------------------------------------------------

AC_CACHE_CHECK([whether the cpuid instruction is usable], tcl_cv_cpuid, [
    AC_TRY_LINK(, [
    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
	int index,regsPtr[4];
    __asm__ __volatile__("mov %%ebx, %%edi     \n\t"
                 "cpuid            \n\t"
                 "mov %%ebx, %%esi   \n\t"
                 "mov %%edi, %%ebx  \n\t"
                 : "=a"(regsPtr[0]), "=S"(regsPtr[1]), "=c"(regsPtr[2]), "=d"(regsPtr[3])
                 : "a"(index) : "edi");
    ], tcl_cv_cpuid=yes, tcl_cv_cpuid=no)])
		 "cpuid            \n\t"
		 "mov %%ebx, %%esi   \n\t"
		 "mov %%edi, %%ebx  \n\t"
		 : "=a"(regsPtr[0]), "=S"(regsPtr[1]), "=c"(regsPtr[2]), "=d"(regsPtr[3])
		 : "a"(index) : "edi");
    ]])],[tcl_cv_cpuid=yes],[tcl_cv_cpuid=no])])
if test $tcl_cv_cpuid = yes; then
    AC_DEFINE(HAVE_CPUID, 1, [Is the cpuid instruction usable?])
fi

#--------------------------------------------------------------------
#	The statements below define a collection of symbols related to
#	building libtcl as a shared library instead of a static library.
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895





896
897
898
899
900

901
902

903
904
905
906


907
908
909
910
911
912
913
754
755
756
757
758
759
760

761
762
763
764
765
766
767
768
769





770
771
772
773
774
775
776
777
778

779
780

781
782
783


784
785
786
787
788
789
790
791
792







-









-
-
-
-
-
+
+
+
+
+




-
+

-
+


-
-
+
+







if test "`uname -s`" = "Darwin" ; then
    SC_ENABLE_FRAMEWORK
    TCL_SHLIB_LD_EXTRAS="-compatibility_version ${TCL_VERSION} -current_version ${TCL_VERSION}`echo ${TCL_PATCH_LEVEL} | awk ['{match($0, "\\\.[0-9]+"); print substr($0,RSTART,RLENGTH)}']`"
    TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -install_name "${DYLIB_INSTALL_DIR}"/${TCL_LIB_FILE}'
    echo "$LDFLAGS " | grep -q -- '-prebind ' && TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -seg1addr 0xA000000'
    TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -sectcreate __TEXT __info_plist Tcl-Info.plist'
    EXTRA_TCLSH_LIBS='-sectcreate __TEXT __info_plist Tclsh-Info.plist'
    EXTRA_APP_CC_SWITCHES='-mdynamic-no-pic'
    AC_CONFIG_FILES([Tcl-Info.plist:../macosx/Tcl-Info.plist.in Tclsh-Info.plist:../macosx/Tclsh-Info.plist.in])
    TCL_YEAR="`date +%Y`"
fi

if test "$FRAMEWORK_BUILD" = "1" ; then
    AC_DEFINE(TCL_FRAMEWORK, 1, [Is Tcl built as a framework?])
    # Construct a fake local framework structure to make linking with
    # '-framework Tcl' and running of tcltest work
    AC_CONFIG_COMMANDS([Tcl.framework], [n=Tcl &&
        f=$n.framework && v=Versions/$VERSION &&
        rm -rf $f && mkdir -p $f/$v/Resources &&
        ln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v &&
        ln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist &&
        unset n f v
	f=$n.framework && v=Versions/$VERSION &&
	rm -rf $f && mkdir -p $f/$v/Resources &&
	ln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v &&
	ln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist &&
	unset n f v
    ], VERSION=${TCL_VERSION})
    LD_LIBRARY_PATH_VAR="DYLD_FRAMEWORK_PATH"
    # default install directory for bundled packages
    if test "${libdir}" = '${exec_prefix}/lib' -o "`basename ${libdir}`" = 'Frameworks'; then
        PACKAGE_DIR="/Library/Tcl"
	PACKAGE_DIR="/Library/Tcl"
    else
        PACKAGE_DIR="$libdir"
	PACKAGE_DIR="$libdir"
    fi
    if test "${libdir}" = '${exec_prefix}/lib'; then
        # override libdir default
        libdir="/Library/Frameworks"
	# override libdir default
	libdir="/Library/Frameworks"
    fi
    TCL_LIB_FILE="Tcl"
    TCL_LIB_FLAG="-framework Tcl"
    TCL_BUILD_LIB_SPEC="-F`pwd | sed -e 's/ /\\\\ /g'` -framework Tcl"
    TCL_LIB_SPEC="-F${libdir} -framework Tcl"
    libdir="${libdir}/Tcl.framework/Versions/\${VERSION}"
    TCL_LIBRARY="${libdir}/Resources/Scripts"
926
927
928
929
930
931
932
933

934
935

936
937
938
939
940
941
942
943

















































944
945
946
947
948
949
950
951
952
953
954



955
956
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
805
806
807
808
809
810
811

812
813

814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900

901
902
903
904




905

906
907
908
909
910
911
912







-
+

-
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










-
+
+
+



-
+

-
+










-
+



-
-
-
-
+
-







    EXTRA_CC_SWITCHES='-DTCL_FRAMEWORK_VERSION=\"$(VERSION)\"'
else
    # libdir must be a fully qualified path and not ${exec_prefix}/lib
    eval libdir="$libdir"
    # default install directory for bundled packages
    PACKAGE_DIR="$libdir"
    if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
        TCL_LIB_FLAG="-ltcl${TCL_VERSION}"
	TCL_LIB_FLAG="-ltcl${TCL_VERSION}"
    else
        TCL_LIB_FLAG="-ltcl`echo ${TCL_VERSION} | tr -d .`"
	TCL_LIB_FLAG="-ltcl`echo ${TCL_VERSION} | tr -d .`"
    fi
    TCL_BUILD_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TCL_LIB_FLAG}"
    TCL_LIB_SPEC="-L${libdir} ${TCL_LIB_FLAG}"
fi
VERSION='${VERSION}'
eval "CFG_TCL_SHARED_LIB_SUFFIX=${TCL_SHARED_LIB_SUFFIX}"
eval "CFG_TCL_UNSHARED_LIB_SUFFIX=${TCL_UNSHARED_LIB_SUFFIX}"
VERSION=${TCL_VERSION}

#--------------------------------------------------------------------
#	Zipfs support - Tip 430
#--------------------------------------------------------------------
AC_ARG_ENABLE(zipfs,
    AS_HELP_STRING([--enable-zipfs],
	[build with Zipfs support (default: on)]),
    [tcl_ok=$enableval], [tcl_ok=yes])
if test "$tcl_ok" = "yes" -a "x$enable_framework" != "xyes"; then
    #
    # Find a native compiler
    #
    AX_CC_FOR_BUILD
    #
    # Find a native zip implementation
    #
    SC_ZIPFS_SUPPORT
    ZIPFS_BUILD=1
    TCL_ZIP_FILE=libtcl${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_PATCH_LEVEL}.zip
else
    ZIPFS_BUILD=0
    TCL_ZIP_FILE=
fi
# Do checking message here to not mess up interleaved configure output
AC_MSG_CHECKING([for building with zipfs])
if test "${ZIPFS_BUILD}" = 1; then
    if test "${SHARED_BUILD}" = 0; then
       ZIPFS_BUILD=2;
       AC_DEFINE(ZIPFS_BUILD, 2, [Are we building with zipfs enabled?])
     else
       AC_DEFINE(ZIPFS_BUILD, 1, [Are we building with zipfs enabled?])\
    fi
    AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
INSTALL_LIBRARIES=install-libraries
INSTALL_MSGS=install-msgs
fi

# Point to tcl script library if we are not embedding it.
if test "${ZIPFS_BUILD}" = 0; then
TCL_BUILDTIME_LIBRARY=${TCL_SRC_DIR}/library
fi

AC_SUBST(ZIPFS_BUILD)
AC_SUBST(TCL_ZIP_FILE)
AC_SUBST(INSTALL_LIBRARIES)
AC_SUBST(INSTALL_MSGS)
AC_SUBST(TCL_BUILDTIME_LIBRARY)

#--------------------------------------------------------------------
#	The statements below define the symbol TCL_PACKAGE_PATH, which
#	gives a list of directories that may contain packages.  The list
#	consists of one directory for machine-dependent binaries and
#	another for platform-independent scripts.
#--------------------------------------------------------------------

if test "$FRAMEWORK_BUILD" = "1" ; then
    test -z "$TCL_PACKAGE_PATH" && \
	TCL_PACKAGE_PATH="~/Library/Tcl /Library/Tcl ~/Library/Frameworks /Library/Frameworks"
	TCL_PACKAGE_PATH="~/Library/Tcl:/Library/Tcl:~/Library/Frameworks:/Library/Frameworks"
	# Allow tclsh to find Tk when multiple versions are installed. See Tk [1562e10c58].
	TCL_PACKAGE_PATH="$TCL_PACKAGE_PATH:/Library/Frameworks/Tk.framework/Versions"
    test -z "$TCL_MODULE_PATH"  && \
	TCL_MODULE_PATH="~/Library/Tcl /Library/Tcl"
elif test "$prefix/lib" != "$libdir"; then
    test -z "$TCL_PACKAGE_PATH" && TCL_PACKAGE_PATH="{${libdir}} {${prefix}/lib} ${TCL_PACKAGE_PATH}"
    test -z "$TCL_PACKAGE_PATH" && TCL_PACKAGE_PATH="${libdir}:${prefix}/lib"
else
    test -z "$TCL_PACKAGE_PATH" && TCL_PACKAGE_PATH="{${prefix}/lib} ${TCL_PACKAGE_PATH}"
    test -z "$TCL_PACKAGE_PATH" && TCL_PACKAGE_PATH="${prefix}/lib"
fi

#--------------------------------------------------------------------
#       The statements below define various symbols relating to Tcl
#       stub support.
#--------------------------------------------------------------------

# Replace ${VERSION} with contents of ${TCL_VERSION}
# double-eval to account for TCL_TRIM_DOTS.
#
eval "TCL_STUB_LIB_FILE=libtclstub${TCL_UNSHARED_LIB_SUFFIX}"
eval "TCL_STUB_LIB_FILE=libtclstub.a"
eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
eval "TCL_STUB_LIB_DIR=\"${libdir}\""

if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
    TCL_STUB_LIB_FLAG="-ltclstub${TCL_VERSION}"
else
    TCL_STUB_LIB_FLAG="-ltclstub`echo ${TCL_VERSION} | tr -d .`"
TCL_STUB_LIB_FLAG="-ltclstub"
fi

TCL_BUILD_STUB_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}"
TCL_STUB_LIB_SPEC="-L${TCL_STUB_LIB_DIR} ${TCL_STUB_LIB_FLAG}"
TCL_BUILD_STUB_LIB_PATH="`pwd`/${TCL_STUB_LIB_FILE}"
TCL_STUB_LIB_PATH="${TCL_STUB_LIB_DIR}/${TCL_STUB_LIB_FILE}"

# Install time header dir can be set via --includedir

Changes to unix/dltest/Makefile.in.

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
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







-
+




-
+


+
+
-
+



+
+
-
+


+
+
+
+
+
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












+
+
+
+
+
+
-
-
+
+

-
-
+
+

-
-
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

+
+
+
-
-
+
+

-
-
+
+

-
-
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+


-
+







DLTEST_SUFFIX =		@DLTEST_SUFFIX@
SRC_DIR =		@TCL_SRC_DIR@/unix/dltest
BUILD_DIR =		@builddir@
TCL_VERSION=		@TCL_VERSION@

CFLAGS_DEBUG		= @CFLAGS_DEBUG@
CFLAGS_OPTIMIZE		= @CFLAGS_OPTIMIZE@
CFLAGS			= @CFLAGS_DEFAULT@ @CFLAGS@ -DTCL_NO_DEPRECATED=1
CFLAGS			= @CFLAGS_DEFAULT@ @CFLAGS@ -DTCL_NO_DEPRECATED=1 -Wall -Wextra -Wc++-compat -Wconversion -Werror
LDFLAGS_DEBUG		= @LDFLAGS_DEBUG@
LDFLAGS_OPTIMIZE	= @LDFLAGS_OPTIMIZE@
LDFLAGS			= @LDFLAGS_DEFAULT@ @LDFLAGS@

CC_SWITCHES = $(CFLAGS) -I${SRC_DIR}/../../generic -DTCL_MEM_DEBUG \
CC_SWITCHES = $(CFLAGS) -I${SRC_DIR}/../../generic \
	${SHLIB_CFLAGS} -DUSE_TCL_STUBS ${AC_FLAGS}

all: embtest tcl9pkga${SHLIB_SUFFIX} tcl9pkgb${SHLIB_SUFFIX} tcl9pkgc${SHLIB_SUFFIX} \
	tcl9pkgd${SHLIB_SUFFIX} tcl9pkge${SHLIB_SUFFIX} tcl9pkgt${SHLIB_SUFFIX} tcl9pkgua${SHLIB_SUFFIX} \
all: pkga${SHLIB_SUFFIX} pkgb${SHLIB_SUFFIX} pkgc${SHLIB_SUFFIX} pkgd${SHLIB_SUFFIX} pkge${SHLIB_SUFFIX} pkgua${SHLIB_SUFFIX} pkgooa${SHLIB_SUFFIX}
	tcl9pkgooa${SHLIB_SUFFIX} pkga${SHLIB_SUFFIX} pkgb${SHLIB_SUFFIX} pkgc${SHLIB_SUFFIX}  pkgt${SHLIB_SUFFIX}
	@if test -n "$(DLTEST_SUFFIX)"; then $(MAKE) dltest_suffix; fi
	@touch ../dltest.marker

dltest_suffix: tcl9pkga${DLTEST_SUFFIX} tcl9pkgb${DLTEST_SUFFIX} tcl9pkgc${DLTEST_SUFFIX} \
	tcl9pkgd${DLTEST_SUFFIX} tcl9pkge${DLTEST_SUFFIX} tcl9pkgt${DLTEST_SUFFIX} tcl9pkgua${DLTEST_SUFFIX} \
dltest_suffix: pkga${DLTEST_SUFFIX} pkgb${DLTEST_SUFFIX} pkgc${DLTEST_SUFFIX} pkgd${DLTEST_SUFFIX} pkge${DLTEST_SUFFIX} pkgua${DLTEST_SUFFIX} pkgooa${DLTEST_SUFFIX}
	tcl9pkgooa${DLTEST_SUFFIX} pkga${DLTEST_SUFFIX} pkgb${DLTEST_SUFFIX} pkgc${DLTEST_SUFFIX} pkgt${DLTEST_SUFFIX}
	@touch ../dltest.marker

embtest.o: $(SRC_DIR)/embtest.c
	$(CC) -c $(CC_SWITCHES) $(SRC_DIR)/embtest.c

pkgπ.o: $(SRC_DIR)/pkgπ.c
	$(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkgπ.c

pkga.o: $(SRC_DIR)/pkga.c
	$(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkga.c

pkgb.o: $(SRC_DIR)/pkgb.c
	$(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkgb.c

pkgc.o: $(SRC_DIR)/pkgc.c
	$(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkgc.c

pkgt.o: $(SRC_DIR)/pkgt.c
	$(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkgt.c

tcl8pkga.o: $(SRC_DIR)/pkga.c
	$(CC) -o $@ -c $(CC_SWITCHES) -DTCL_MAJOR_VERSION=8 $(SRC_DIR)/pkga.c

tcl8pkgb.o: $(SRC_DIR)/pkgb.c
	$(CC) -o $@ -c $(CC_SWITCHES) -DTCL_MAJOR_VERSION=8 $(SRC_DIR)/pkgb.c

tcl8pkgc.o: $(SRC_DIR)/pkgc.c
	$(CC) -o $@ -c $(CC_SWITCHES) -DTCL_MAJOR_VERSION=8 $(SRC_DIR)/pkgc.c

tcl8pkgt.o: $(SRC_DIR)/pkgt.c
	$(CC) -o $@ -c $(CC_SWITCHES) -DTCL_MAJOR_VERSION=8 $(SRC_DIR)/pkgt.c

pkgd.o: $(SRC_DIR)/pkgd.c
	$(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkgd.c

pkge.o: $(SRC_DIR)/pkge.c
	$(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkge.c

pkgua.o: $(SRC_DIR)/pkgua.c
	$(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkgua.c

pkgooa.o: $(SRC_DIR)/pkgooa.c
	$(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkgooa.c

embtest: embtest.o
	$(CC) $(CC_SWITCHES) -o $@ embtest.o ${SHLIB_LD_LIBS}

tcl9pkgπ${SHLIB_SUFFIX}: pkgπ.o
	${SHLIB_LD} -o $@ pkgπ.o ${SHLIB_LD_LIBS}

pkga${SHLIB_SUFFIX}: pkga.o
	${SHLIB_LD} -o pkga${SHLIB_SUFFIX} pkga.o ${SHLIB_LD_LIBS}
tcl9pkga${SHLIB_SUFFIX}: pkga.o
	${SHLIB_LD} -o $@ pkga.o ${SHLIB_LD_LIBS}

pkgb${SHLIB_SUFFIX}: pkgb.o
	${SHLIB_LD} -o pkgb${SHLIB_SUFFIX} pkgb.o ${SHLIB_LD_LIBS}
tcl9pkgb${SHLIB_SUFFIX}: pkgb.o
	${SHLIB_LD} -o $@ pkgb.o ${SHLIB_LD_LIBS}

pkgc${SHLIB_SUFFIX}: pkgc.o
	${SHLIB_LD} -o pkgc${SHLIB_SUFFIX} pkgc.o ${SHLIB_LD_LIBS}
tcl9pkgc${SHLIB_SUFFIX}: pkgc.o
	${SHLIB_LD} -o $@ pkgc.o ${SHLIB_LD_LIBS}

tcl9pkgt${SHLIB_SUFFIX}: pkgt.o
	${SHLIB_LD} -o $@ pkgt.o ${SHLIB_LD_LIBS}

pkga${SHLIB_SUFFIX}: tcl8pkga.o
	${SHLIB_LD} -o $@ tcl8pkga.o ${SHLIB_LD_LIBS}

pkgb${SHLIB_SUFFIX}: tcl8pkgb.o
	${SHLIB_LD} -o $@ tcl8pkgb.o ${SHLIB_LD_LIBS}

pkgc${SHLIB_SUFFIX}: tcl8pkgc.o
	${SHLIB_LD} -o $@ tcl8pkgc.o ${SHLIB_LD_LIBS}

pkgt${SHLIB_SUFFIX}: tcl8pkgt.o
	${SHLIB_LD} -o $@ tcl8pkgt.o ${SHLIB_LD_LIBS}

pkgd${SHLIB_SUFFIX}: pkgd.o
	${SHLIB_LD} -o pkgd${SHLIB_SUFFIX} pkgd.o ${SHLIB_LD_LIBS}
tcl9pkgd${SHLIB_SUFFIX}: pkgd.o
	${SHLIB_LD} -o $@ pkgd.o ${SHLIB_LD_LIBS}

pkge${SHLIB_SUFFIX}: pkge.o
	${SHLIB_LD} -o pkge${SHLIB_SUFFIX} pkge.o ${SHLIB_LD_LIBS}
tcl9pkge${SHLIB_SUFFIX}: pkge.o
	${SHLIB_LD} -o $@ pkge.o ${SHLIB_LD_LIBS}

pkgua${SHLIB_SUFFIX}: pkgua.o
	${SHLIB_LD} -o pkgua${SHLIB_SUFFIX} pkgua.o ${SHLIB_LD_LIBS}
tcl9pkgua${SHLIB_SUFFIX}: pkgua.o
	${SHLIB_LD} -o $@ pkgua.o ${SHLIB_LD_LIBS}

pkgooa${SHLIB_SUFFIX}: pkgooa.o
	${SHLIB_LD} -o pkgooa${SHLIB_SUFFIX} pkgooa.o ${SHLIB_LD_LIBS}
tcl9pkgooa${SHLIB_SUFFIX}: pkgooa.o
	${SHLIB_LD} -o $@ pkgooa.o ${SHLIB_LD_LIBS}

tcl9pkgπ${DLTEST_SUFFIX}: pkgπ.o
	${DLTEST_LD} -o $@ pkgπ.o ${SHLIB_LD_LIBS}

pkga${DLTEST_SUFFIX}: pkga.o
	${DLTEST_LD} -o pkga${DLTEST_SUFFIX} pkga.o ${SHLIB_LD_LIBS}
tcl9pkga${DLTEST_SUFFIX}: pkga.o
	${DLTEST_LD} -o $@ pkga.o ${SHLIB_LD_LIBS}

pkgb${DLTEST_SUFFIX}: pkgb.o
	${DLTEST_LD} -o pkgb${DLTEST_SUFFIX} pkgb.o ${SHLIB_LD_LIBS}
tcl9pkgb${DLTEST_SUFFIX}: pkgb.o
	${DLTEST_LD} -o $@ pkgb.o ${SHLIB_LD_LIBS}

pkgc${DLTEST_SUFFIX}: pkgc.o
	${DLTEST_LD} -o pkgc${DLTEST_SUFFIX} pkgc.o ${SHLIB_LD_LIBS}
tcl9pkgc${DLTEST_SUFFIX}: pkgc.o
	${DLTEST_LD} -o $@ pkgc.o ${SHLIB_LD_LIBS}

tcl9pkgt${DLTEST_SUFFIX}: pkgt.o
	${DLTEST_LD} -o $@ pkgt.o ${SHLIB_LD_LIBS}

pkga${DLTEST_SUFFIX}: tcl8pkga.o
	${DLTEST_LD} -o $@ tcl8pkga.o ${SHLIB_LD_LIBS}

pkgb${DLTEST_SUFFIX}: tcl8pkgb.o
	${DLTEST_LD} -o $@ tcl8pkgb.o ${SHLIB_LD_LIBS}

pkgc${DLTEST_SUFFIX}: tcl8pkgc.o
	${DLTEST_LD} -o $@ tcl8pkgc.o ${SHLIB_LD_LIBS}

pkgt${DLTEST_SUFFIX}: tcl8pkgt.o
	${DLTEST_LD} -o $@ tcl8pkgt.o ${SHLIB_LD_LIBS}

pkgd${DLTEST_SUFFIX}: pkgd.o
	${DLTEST_LD} -o pkgd${DLTEST_SUFFIX} pkgd.o ${SHLIB_LD_LIBS}
tcl9pkgd${DLTEST_SUFFIX}: pkgd.o
	${DLTEST_LD} -o $@ pkgd.o ${SHLIB_LD_LIBS}

pkge${DLTEST_SUFFIX}: pkge.o
	${DLTEST_LD} -o pkge${DLTEST_SUFFIX} pkge.o ${SHLIB_LD_LIBS}
tcl9pkge${DLTEST_SUFFIX}: pkge.o
	${DLTEST_LD} -o $@ pkge.o ${SHLIB_LD_LIBS}

pkgua${DLTEST_SUFFIX}: pkgua.o
	${DLTEST_LD} -o pkgua${DLTEST_SUFFIX} pkgua.o ${SHLIB_LD_LIBS}
tcl9pkgua${DLTEST_SUFFIX}: pkgua.o
	${DLTEST_LD} -o $@ pkgua.o ${SHLIB_LD_LIBS}

pkgooa${DLTEST_SUFFIX}: pkgooa.o
	${DLTEST_LD} -o pkgooa${DLTEST_SUFFIX} pkgooa.o ${SHLIB_LD_LIBS}
tcl9pkgooa${DLTEST_SUFFIX}: pkgooa.o
	${DLTEST_LD} -o $@ pkgooa.o ${SHLIB_LD_LIBS}

clean:
	rm -f *.o lib.exp ../dltest.marker
	rm -f embtest *.o lib.exp ../dltest.marker
	@if test "$(SHLIB_SUFFIX)" != ""; then \
	    echo "rm -f *${SHLIB_SUFFIX}" ; \
	    rm -f *${SHLIB_SUFFIX} ; \
	fi
	@if test "$(DLTEST_SUFFIX)" != ""; then \
	    echo "rm -f *${DLTEST_SUFFIX}" ; \
	    rm -f *${DLTEST_SUFFIX} ; \

Added unix/dltest/embtest.c.









































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
30
31
32
33
34
35
36
37
38
39
40
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#include "tcl.h"
#include <stdio.h>

MODULE_SCOPE const TclStubs *tclStubsPtr;

int main(int argc, char **argv) {
    const char *version;
    int exitcode = 0;
    (void)argc;

    if (tclStubsPtr != NULL) {
	printf("ERROR: stub table is already initialized");
	exitcode = 1;
    }
    tclStubsPtr = NULL;
    version = Tcl_SetPanicProc(Tcl_ConsolePanic);
    if (tclStubsPtr == NULL) {
	printf("ERROR: Tcl_SetPanicProc does not initialize the stub table\n");
	exitcode = 1;
    }
    tclStubsPtr = NULL;
    version = Tcl_InitSubsystems();
    if (tclStubsPtr == NULL) {
	printf("ERROR: Tcl_InitSubsystems does not initialize the stub table\n");
	exitcode = 1;
    }
    tclStubsPtr = NULL;
    version = Tcl_FindExecutable(argv[0]);
    if (version != NULL) {
	printf("Tcl_FindExecutable gives version %s\n", version);
    }
    if (tclStubsPtr == NULL) {
	printf("ERROR: Tcl_FindExecutable does not initialize the stub table\n");
	exitcode = 1;
    }
    if (!exitcode) {
	printf("All OK!\n");
    }
    return exitcode;
}

Changes to unix/dltest/pkga.c.

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
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
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
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






-
+








-
-
-
-
-
-
-
-
-




















-
+






-
+









+
+

-
+







/*
 * pkga.c --
 *
 *	This file contains a simple Tcl package "pkga" that is intended for
 *	testing the Tcl dynamic loading facilities.
 *
 * Copyright (c) 1995 Sun Microsystems, Inc.
 * Copyright © 1995 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#undef STATIC_BUILD
#include "tcl.h"

/*
 * Prototypes for procedures defined later in this file:
 */

static int    Pkga_EqObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
static int    Pkga_QuoteObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);

/*
 *----------------------------------------------------------------------
 *
 * Pkga_EqObjCmd --
 *
 *	This procedure is invoked to process the "pkga_eq" Tcl command. It
 *	expects two arguments and returns 1 if they are the same, 0 if they
 *	are different.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Pkga_EqObjCmd(
    ClientData dummy,		/* Not used. */
    void *dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int result;
    const char *str1, *str2;
    int len1, len2;
    Tcl_Size len1, len2;
    (void)dummy;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv,  "string1 string2");
	return TCL_ERROR;
    }

    str1 = Tcl_GetStringFromObj(objv[1], &len1);
    str2 = Tcl_GetStringFromObj(objv[2], &len2);
    len1 = Tcl_NumUtfChars(str1, len1);
    len2 = Tcl_NumUtfChars(str2, len2);
    if (len1 == len2) {
	result = (Tcl_UtfNcmp(str1, str2, len1) == 0);
	result = (Tcl_UtfNcmp(str1, str2, (size_t)len1) == 0);
    } else {
	result = 0;
    }
    Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
    return TCL_OK;
}

83
84
85
86
87
88
89
90

91
92
93
94
95
96
97
76
77
78
79
80
81
82

83
84
85
86
87
88
89
90







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Pkga_QuoteObjCmd(
    ClientData dummy,		/* Not used. */
    void *dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    (void)dummy;

    if (objc != 2) {
125
126
127
128
129
130
131
132

133
134
135
136
137
138
139
140
118
119
120
121
122
123
124

125
126
127
128
129
130
131
132
133







-
+








				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }
    code = Tcl_PkgProvide(interp, "Pkga", "1.0");
    code = Tcl_PkgProvide(interp, "pkga", "1.0");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkga_eq", Pkga_EqObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "pkga_quote", Pkga_QuoteObjCmd, NULL,
	    NULL);
    return TCL_OK;
}

Changes to unix/dltest/pkgb.c.

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
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
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
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







-
+







-
+
-
-
+
-
-
+
-
-
-
-
-
-
-
+

















-
-
-
-


-
+














-
-
+
+







/*
 * pkgb.c --
 *
 *	This file contains a simple Tcl package "pkgb" that is intended for
 *	testing the Tcl dynamic loading facilities. It can be used in both
 *	safe and unsafe interpreters.
 *
 * Copyright (c) 1995 Sun Microsystems, Inc.
 * Copyright © 1995 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#undef STATIC_BUILD
#include "tcl.h"

#if defined(_WIN32) && defined(_MSC_VER)
/*
 * Prototypes for procedures defined later in this file:
#   define snprintf _snprintf
 */

#endif
static int    Pkgb_SubObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
static int    Pkgb_UnsafeObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
static int    Pkgb_DemoObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);


/*
 *----------------------------------------------------------------------
 *
 * Pkgb_SubObjCmd --
 *
 *	This procedure is invoked to process the "pkgb_sub" Tcl command. It
 *	expects two arguments and returns their difference.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

#ifndef Tcl_GetErrorLine
#   define Tcl_GetErrorLine(interp) ((interp)->errorLine)
#endif

static int
Pkgb_SubObjCmd(
    ClientData dummy,		/* Not used. */
    void *dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int first, second;
    (void)dummy;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "num num");
	return TCL_ERROR;
    }
    if ((Tcl_GetIntFromObj(interp, objv[1], &first) != TCL_OK)
	    || (Tcl_GetIntFromObj(interp, objv[2], &second) != TCL_OK)) {
	char buf[TCL_INTEGER_SPACE];
	sprintf(buf, "%d", Tcl_GetErrorLine(interp));
	Tcl_AppendResult(interp, " in line: ", buf, NULL);
	snprintf(buf, sizeof(buf), "%d", Tcl_GetErrorLine(interp));
	Tcl_AppendResult(interp, " in line: ", buf, (char *)NULL);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewIntObj(first - second));
    return TCL_OK;
}

/*
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
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







-
+








-
+




-
+




-
-
+
+

-
-
-
-
-
+
+
+
+
+
+
+
-

-
-
+
+
-







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Pkgb_UnsafeObjCmd(
    ClientData dummy,		/* Not used. */
    void *dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    (void)dummy;
    (void)objc;
    (void)objv;

    return Tcl_EvalEx(interp, "list unsafe command invoked", -1, TCL_EVAL_GLOBAL);
    return Tcl_EvalEx(interp, "list unsafe command invoked", TCL_INDEX_NONE, TCL_EVAL_GLOBAL);
}

static int
Pkgb_DemoObjCmd(
    ClientData dummy,		/* Not used. */
    void *dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
#if (TCL_MAJOR_VERSION > 8) || (TCL_MINOR_VERSION > 4)
    Tcl_Obj *first;
    Tcl_WideInt numChars;
    int result;
    (void)dummy;
    (void)objc;
    (void)objv;

    if (Tcl_ListObjIndex(NULL, Tcl_GetEncodingSearchPath(), 0, &first)
	    == TCL_OK) {

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "arg1 arg2 num");
	return TCL_ERROR;
    }
    if (Tcl_GetWideIntFromObj(interp, objv[3], &numChars) != TCL_OK) {
	return TCL_ERROR;
	Tcl_SetObjResult(interp, first);
    }
#else
    Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_GetDefaultEncodingDir(), -1));
    result = Tcl_UtfNcmp(Tcl_GetString(objv[1]), Tcl_GetString(objv[2]), (size_t)numChars);
    Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
#endif
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgb_Init --
148
149
150
151
152
153
154
155

156
157
158
159
160
161
162
136
137
138
139
140
141
142

143
144
145
146
147
148
149
150







-
+







				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }
    code = Tcl_PkgProvide(interp, "Pkgb", "2.3");
    code = Tcl_PkgProvide(interp, "pkgb", "2.3");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgb_sub", Pkgb_SubObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "pkgb_unsafe", Pkgb_UnsafeObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "pkgb_demo", Pkgb_DemoObjCmd, NULL, NULL);
    return TCL_OK;
185
186
187
188
189
190
191
192

193
194
195
196
197
198
173
174
175
176
177
178
179

180
181
182
183
184
185
186







-
+






				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }
    code = Tcl_PkgProvide(interp, "Pkgb", "2.3");
    code = Tcl_PkgProvide(interp, "pkgb", "2.3");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgb_sub", Pkgb_SubObjCmd, NULL, NULL);
    return TCL_OK;
}

Changes to unix/dltest/pkgc.c.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
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
30
31
32
33
34
35

36
37
38
39
40
41
42
43







-
+








-
-
-
-
-
-
-
-
-



















-
+







/*
 * pkgc.c --
 *
 *	This file contains a simple Tcl package "pkgc" that is intended for
 *	testing the Tcl dynamic loading facilities. It can be used in both
 *	safe and unsafe interpreters.
 *
 * Copyright (c) 1995 Sun Microsystems, Inc.
 * Copyright © 1995 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#undef STATIC_BUILD
#include "tcl.h"

/*
 * Prototypes for procedures defined later in this file:
 */

static int    Pkgc_SubObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
static int    Pkgc_UnsafeObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);

/*
 *----------------------------------------------------------------------
 *
 * Pkgc_SubObjCmd --
 *
 *	This procedure is invoked to process the "pkgc_sub" Tcl command. It
 *	expects two arguments and returns their difference.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Pkgc_SubObjCmd(
    ClientData dummy,		/* Not used. */
    void *dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int first, second;
    (void)dummy;

77
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92
93

94
95
96
97
98
99
100
68
69
70
71
72
73
74

75
76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
91







-
+








-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Pkgc_UnsafeObjCmd(
    ClientData dummy,		/* Not used. */
    void *dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    (void)dummy;
    (void)objc;
    (void)objv;

    Tcl_SetObjResult(interp, Tcl_NewStringObj("unsafe command invoked", -1));
    Tcl_SetObjResult(interp, Tcl_NewStringObj("unsafe command invoked", TCL_INDEX_NONE));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgc_Init --
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
108
109
110
111
112
113
114

115
116
117
118
119
120
121
122







-
+







				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }
    code = Tcl_PkgProvide(interp, "Pkgc", "1.7.2");
    code = Tcl_PkgProvide(interp, "pkgc", "1.7.2");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgc_sub", Pkgc_SubObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "pkgc_unsafe", Pkgc_UnsafeObjCmd, NULL,
	    NULL);
    return TCL_OK;
154
155
156
157
158
159
160
161

162
163
164
165
166
167
145
146
147
148
149
150
151

152
153
154
155
156
157
158







-
+






				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }
    code = Tcl_PkgProvide(interp, "Pkgc", "1.7.2");
    code = Tcl_PkgProvide(interp, "pkgc", "1.7.2");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgc_sub", Pkgc_SubObjCmd, NULL, NULL);
    return TCL_OK;
}

Changes to unix/dltest/pkgd.c.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
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
30
31
32
33
34
35

36
37
38
39
40
41
42
43







-
+








-
-
-
-
-
-
-
-
-



















-
+







/*
 * pkgd.c --
 *
 *	This file contains a simple Tcl package "pkgd" that is intended for
 *	testing the Tcl dynamic loading facilities. It can be used in both
 *	safe and unsafe interpreters.
 *
 * Copyright (c) 1995 Sun Microsystems, Inc.
 * Copyright © 1995 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#undef STATIC_BUILD
#include "tcl.h"

/*
 * Prototypes for procedures defined later in this file:
 */

static int    Pkgd_SubObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
static int    Pkgd_UnsafeObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);

/*
 *----------------------------------------------------------------------
 *
 * Pkgd_SubObjCmd --
 *
 *	This procedure is invoked to process the "pkgd_sub" Tcl command. It
 *	expects two arguments and returns their difference.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Pkgd_SubObjCmd(
    ClientData dummy,		/* Not used. */
    void *dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int first, second;
    (void)dummy;

77
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92
93

94
95
96
97
98
99
100
68
69
70
71
72
73
74

75
76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
91







-
+








-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Pkgd_UnsafeObjCmd(
    ClientData dummy,		/* Not used. */
    void *dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    (void)dummy;
    (void)objc;
    (void)objv;

    Tcl_SetObjResult(interp, Tcl_NewStringObj("unsafe command invoked", -1));
    Tcl_SetObjResult(interp, Tcl_NewStringObj("unsafe command invoked", TCL_INDEX_NONE));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgd_Init --
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
108
109
110
111
112
113
114

115
116
117
118
119
120
121
122







-
+







				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }
    code = Tcl_PkgProvide(interp, "Pkgd", "7.3");
    code = Tcl_PkgProvide(interp, "pkgd", "7.3");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgd_sub", Pkgd_SubObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "pkgd_unsafe", Pkgd_UnsafeObjCmd, NULL,
	    NULL);
    return TCL_OK;
154
155
156
157
158
159
160
161

162
163
164
165
166
167
145
146
147
148
149
150
151

152
153
154
155
156
157
158







-
+






				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }
    code = Tcl_PkgProvide(interp, "Pkgd", "7.3");
    code = Tcl_PkgProvide(interp, "pkgd", "7.3");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgd_sub", Pkgd_SubObjCmd, NULL, NULL);
    return TCL_OK;
}

Changes to unix/dltest/pkge.c.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







/*
 * pkge.c --
 *
 *	This file contains a simple Tcl package "pkge" that is intended for
 *	testing the Tcl dynamic loading facilities. Its Init procedure returns
 *	an error in order to test how this is handled.
 *
 * Copyright (c) 1995 Sun Microsystems, Inc.
 * Copyright © 1995 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#undef STATIC_BUILD
#include "tcl.h"
37
38
39
40
41
42
43
44

45
37
38
39
40
41
42
43

44
45







-
+

				 * made available. */
{
    static const char script[] = "if 44 {open non_existent}";

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }
    return Tcl_EvalEx(interp, script, -1, 0);
    return Tcl_EvalEx(interp, script, TCL_INDEX_NONE, 0);
}

Changes to unix/dltest/pkgooa.c.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * pkgooa.c --
 *
 *	This file contains a simple Tcl package "pkgooa" that is intended for
 *	testing the Tcl dynamic loading facilities.
 *
 * Copyright (c) 1995 Sun Microsystems, Inc.
 * Copyright © 1995 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#undef STATIC_BUILD
#include "tclOO.h"
29
30
31
32
33
34
35
36

37
38
39
40
41
42
43
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Pkgooa_StubsOKObjCmd(
    ClientData dummy,		/* Not used. */
    void *dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    (void)dummy;

    if (objc != 1) {
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
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







+


-
+


















-
-
+
+






-
+



-
+



















-
+






	    const char *t))(void *)Pkgooa_StubsOKObjCmd,
    /* More entries could be here, but those are not used
     * for this test-case. So, being NULL is OK. */
    NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL, NULL, NULL
};

extern DLLEXPORT int
DLLEXPORT int
Pkgooa_Init(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code;

    /* Any TclOO extension which uses stubs, calls
     * both Tcl_InitStubs and Tcl_OOInitStubs() and
     * does not use any Tcl 8.6 features should be
     * loadable in Tcl 8.5 as well, provided the
     * TclOO extension (for Tcl 8.5) is installed.
     * This worked in Tcl 8.6.0, and is expected
     * to keep working in all future Tcl 8.x releases.
     */
    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }
    if (tclStubsPtr == NULL) {
	Tcl_AppendResult(interp, "Tcl stubs are not inialized, "
		"did you compile using -DUSE_TCL_STUBS? ");
	Tcl_AppendResult(interp, "Tcl stubs are not initialized, "
		"did you compile using -DUSE_TCL_STUBS? ", (char *)NULL);
	return TCL_ERROR;
    }
    if (Tcl_OOInitStubs(interp) == NULL) {
	return TCL_ERROR;
    }
    if (tclOOStubsPtr == NULL) {
	Tcl_AppendResult(interp, "TclOO stubs are not inialized");
	Tcl_AppendResult(interp, "TclOO stubs are not initialized", (char *)NULL);
	return TCL_ERROR;
    }
    if (tclOOIntStubsPtr == NULL) {
	Tcl_AppendResult(interp, "TclOO internal stubs are not inialized");
	Tcl_AppendResult(interp, "TclOO internal stubs are not initialized", (char *)NULL);
	return TCL_ERROR;
    }

    /* Test case for Bug [f51efe99a7].
     *
     * Let tclOOStubsPtr point to an alternate stub table
     * (with only a single function, that's enough for
     * this test). This way, the function "pkgooa_stubsok"
     * can check whether the TclOO function calls really
     * use the stub table, or only pretend to.
     *
     * On platforms without backlinking (Windows, Cygwin,
     * AIX), this code doesn't even compile without using
     * stubs, but on UNIX ELF systems, the problem is
     * less visible.
     */

    tclOOStubsPtr = &stubsCopy;

    code = Tcl_PkgProvide(interp, "Pkgooa", "1.0");
    code = Tcl_PkgProvide(interp, "pkgooa", "1.0");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgooa_stubsok", Pkgooa_StubsOKObjCmd, NULL, NULL);
    return TCL_OK;
}

Added unix/dltest/pkgt.c.























































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * pkgt.c --
 *
 *	This file contains a simple Tcl package "pkgt" that is intended for
 *	testing the Tcl dynamic loading facilities.
 *
 * Copyright © 1995 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#undef STATIC_BUILD
#include "tcl.h"

static int TraceProc2 (
    void *clientData,
    Tcl_Interp *interp,
    Tcl_Size level,
    const char *command,
    Tcl_Command commandInfo,
    Tcl_Size objc,
    struct Tcl_Obj *const *objv)
{
    (void)clientData;
    (void)interp;
    (void)level;
    (void)command;
    (void)commandInfo;
    (void)objc;
    (void)objv;

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgt_EqObjCmd2 --
 *
 *	This procedure is invoked to process the "pkgt_eq" Tcl command. It
 *	expects two arguments and returns 1 if they are the same, 0 if they
 *	are different.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Pkgt_EqObjCmd2(
    void *dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Size objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_WideInt result;
    const char *str1, *str2;
    Tcl_Size len1, len2;
    (void)dummy;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv,  "string1 string2");
	return TCL_ERROR;
    }

    str1 = Tcl_GetStringFromObj(objv[1], &len1);
    str2 = Tcl_GetStringFromObj(objv[2], &len2);
    len1 = Tcl_NumUtfChars(str1, len1);
    len2 = Tcl_NumUtfChars(str2, len2);
    if (len1 == len2) {
	result = (Tcl_UtfNcmp(str1, str2, (size_t)len1) == 0);
    } else {
	result = 0;
    }
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(result));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgt_Init --
 *
 *	This is a package initialization procedure, which is called by Tcl
 *	when this package is to be added to an interpreter.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

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);
    Tcl_CreateObjTrace2(interp, 0, 0, TraceProc2, NULL, NULL);
    return TCL_OK;
}

Changes to unix/dltest/pkgua.c.

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
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
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
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






-
-
+
+







-
-
-
-
-
-
-
-
-








-
-


+
+
-
-
+
+
+


+
+
+
+
+
+




+
+
-
+


-
-
+
+







+

-
+



-
+








+

-
+



-
-
+
+













+

-
+







/*
 * pkgua.c --
 *
 *	This file contains a simple Tcl package "pkgua" that is intended for
 *	testing the Tcl dynamic unloading facilities.
 *
 * Copyright (c) 1995 Sun Microsystems, Inc.
 * Copyright (c) 2004 Georgios Petasis
 * Copyright © 1995 Sun Microsystems, Inc.
 * Copyright © 2004 Georgios Petasis
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tcl.h"

/*
 * Prototypes for procedures defined later in this file:
 */

static int    PkguaEqObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
static int    PkguaQuoteObjCmd(ClientData clientData,
		Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);

/*
 * In the following hash table we are going to store a struct that holds all
 * the command tokens created by Tcl_CreateObjCommand in an interpreter,
 * indexed by the interpreter. In this way, we can find which command tokens
 * we have registered in a specific interpreter, in order to unload them. We
 * need to keep the various command tokens we have registered, as they are the
 * only safe way to unregister our registered commands, even if they have been
 * renamed.
 *
 * Note that this code is utterly single-threaded.
 */

typedef struct ThreadSpecificData {
    int interpTokenMapInitialised;
static Tcl_HashTable interpTokenMap;
static int interpTokenMapInitialised = 0;
    Tcl_HashTable interpTokenMap;
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
#define MAX_REGISTERED_COMMANDS 2

static void
CommandDeleted(void *clientData)
{
    Tcl_Command *cmdToken = (Tcl_Command *)clientData;
    *cmdToken = NULL;
}

static void
PkguaInitTokensHashTable(void)
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)Tcl_GetThreadData((&dataKey), sizeof(ThreadSpecificData));

    if (interpTokenMapInitialised) {
    if (tsdPtr->interpTokenMapInitialised) {
	return;
    }
    Tcl_InitHashTable(&interpTokenMap, TCL_ONE_WORD_KEYS);
    interpTokenMapInitialised = 1;
    Tcl_InitHashTable(&tsdPtr->interpTokenMap, TCL_ONE_WORD_KEYS);
    tsdPtr->interpTokenMapInitialised = 1;
}

static void
PkguaFreeTokensHashTable(void)
{
    Tcl_HashSearch search;
    Tcl_HashEntry *entryPtr;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)Tcl_GetThreadData((&dataKey), sizeof(ThreadSpecificData));

    for (entryPtr = Tcl_FirstHashEntry(&interpTokenMap, &search);
    for (entryPtr = Tcl_FirstHashEntry(&tsdPtr->interpTokenMap, &search);
	    entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) {
	Tcl_Free((char *) Tcl_GetHashValue(entryPtr));
    }
    interpTokenMapInitialised = 0;
    tsdPtr->interpTokenMapInitialised = 0;
}

static Tcl_Command *
PkguaInterpToTokens(
    Tcl_Interp *interp)
{
    int newEntry;
    Tcl_Command *cmdTokens;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)Tcl_GetThreadData((&dataKey), sizeof(ThreadSpecificData));
    Tcl_HashEntry *entryPtr =
	    Tcl_CreateHashEntry(&interpTokenMap, interp, &newEntry);
	    Tcl_CreateHashEntry(&tsdPtr->interpTokenMap, (char *) interp, &newEntry);

    if (newEntry) {
	cmdTokens = (Tcl_Command *)
		Tcl_Alloc(sizeof(Tcl_Command) * (MAX_REGISTERED_COMMANDS+1));
	for (newEntry=0 ; newEntry<MAX_REGISTERED_COMMANDS+1 ; ++newEntry) {
		Tcl_Alloc(sizeof(Tcl_Command) * (MAX_REGISTERED_COMMANDS));
	for (newEntry=0 ; newEntry<MAX_REGISTERED_COMMANDS ; ++newEntry) {
	    cmdTokens[newEntry] = NULL;
	}
	Tcl_SetHashValue(entryPtr, cmdTokens);
    } else {
	cmdTokens = (Tcl_Command *) Tcl_GetHashValue(entryPtr);
    }
    return cmdTokens;
}

static void
PkguaDeleteTokens(
    Tcl_Interp *interp)
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)Tcl_GetThreadData((&dataKey), sizeof(ThreadSpecificData));
    Tcl_HashEntry *entryPtr =
	    Tcl_FindHashEntry(&interpTokenMap, interp);
	    Tcl_FindHashEntry(&tsdPtr->interpTokenMap, interp);

    if (entryPtr) {
	Tcl_Free((char *) Tcl_GetHashValue(entryPtr));
	Tcl_DeleteHashEntry(entryPtr);
    }
}

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
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







-
+






-
+









+
+

-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
PkguaEqObjCmd(
    ClientData dummy,		/* Not used. */
    void *dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int result;
    const char *str1, *str2;
    int len1, len2;
    Tcl_Size len1, len2;
    (void)dummy;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv,  "string1 string2");
	return TCL_ERROR;
    }

    str1 = Tcl_GetStringFromObj(objv[1], &len1);
    str2 = Tcl_GetStringFromObj(objv[2], &len2);
    len1 = Tcl_NumUtfChars(str1, len1);
    len2 = Tcl_NumUtfChars(str2, len2);
    if (len1 == len2) {
	result = (Tcl_UtfNcmp(str1, str2, len1) == 0);
	result = (Tcl_UtfNcmp(str1, str2, (size_t)len1) == 0);
    } else {
	result = 0;
    }
    Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
    return TCL_OK;
}

158
159
160
161
162
163
164
165

166
167
168
169
170
171
172
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177







-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
PkguaQuoteObjCmd(
    ClientData dummy,		/* Not used. */
    void *dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    (void)dummy;

    if (objc != 2) {
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
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







-
+







-
+





-
+







-
-
-
-
+
+
+
+

-
+







 */

DLLEXPORT int
Pkgua_Init(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code, cmdIndex = 0;
    int code;
    Tcl_Command *cmdTokens;

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }

    /*
     * Initialise our Hash table, where we store the registered command tokens
     * Initialize our Hash table, where we store the registered command tokens
     * for each interpreter.
     */

    PkguaInitTokensHashTable();

    code = Tcl_PkgProvide(interp, "Pkgua", "1.0");
    code = Tcl_PkgProvide(interp, "pkgua", "1.0");
    if (code != TCL_OK) {
	return code;
    }

    Tcl_SetVar2(interp, "::pkgua_loaded", NULL, ".", TCL_APPEND_VALUE);

    cmdTokens = PkguaInterpToTokens(interp);
    cmdTokens[cmdIndex++] =
	    Tcl_CreateObjCommand(interp, "pkgua_eq", PkguaEqObjCmd, NULL,
		    NULL);
    cmdTokens[cmdIndex++] =
    cmdTokens[0] =
	    Tcl_CreateObjCommand(interp, "pkgua_eq", PkguaEqObjCmd, &cmdTokens[0],
		    CommandDeleted);
    cmdTokens[1] =
	    Tcl_CreateObjCommand(interp, "pkgua_quote", PkguaQuoteObjCmd,
		    NULL, NULL);
		    &cmdTokens[1], CommandDeleted);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgua_SafeInit --

Added unix/dltest/pkgπ.c.






















































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * pkgπ.c --
 *
 *	This file contains a simple Tcl package "pkgπ" that is intended for
 *	testing the Tcl dynamic loading facilities.
 *
 * Copyright © 1995 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#undef STATIC_BUILD
#include "tcl.h"

/*
 *----------------------------------------------------------------------
 *
 * Pkga_EqObjCmd --
 *
 *	This procedure is invoked to process the "pkga_eq" Tcl command. It
 *	expects two arguments and returns 1 if they are the same, 0 if they
 *	are different.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Pkg\u03C0_\u03A0ObjCmd(
    void *dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    (void)dummy;

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

    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(3.14159));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgπ_Init --
 *
 *	This is a package initialization procedure, which is called by Tcl
 *	when this package is to be added to an interpreter.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

DLLEXPORT int
Pkg\u03C0_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, "pkgπ", "1.0");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "Ï€", Pkg\u03C0_\u03A0ObjCmd, NULL, NULL);
    return TCL_OK;
}

Changes to unix/install-sh.

1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







#!/bin/sh
# install - install a program, script, or datafile

scriptversion=2020-07-26.22; # UTC
scriptversion=2020-11-14.01; # UTC

# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
69
70
71
72
73
74
75

76
77
78
79
80
81
82
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83







+







# Desired mode of installed file.
mode=0755

# Create dirs (including intermediate dirs) using mode 755.
# This is like GNU 'install' as of coreutils 8.32 (2020).
mkdir_umask=22

backupsuffix=
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=

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
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







-
+




+

-
+






+
+
+
+
+
+
+
+







In the 4th, create DIRECTORIES.

Options:
     --help     display this help and exit.
     --version  display version info and exit.

  -c            (ignored)
  -C            install only if different (preserve the last data modification time)
  -C            install only if different (preserve data modification time)
  -d            create directories instead of installing files.
  -g GROUP      $chgrpprog installed files to GROUP.
  -m MODE       $chmodprog installed files to MODE.
  -o USER       $chownprog installed files to USER.
  -p            pass -p to $cpprog.
  -s            $stripprog installed files.
  -S OPTION     $stripprog installed files using OPTION.
  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.
  -t DIRECTORY  install into DIRECTORY.
  -T            report an error if DSTFILE is a directory.

Environment variables override the default commands:
  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
  RMPROG STRIPPROG

By default, rm is invoked with -f; when overridden with RMPROG,
it's up to you to specify -f if you want it.

If -S is not specified, no backups are attempted.

Email bug reports to bug-automake@gnu.org.
Automake home page: https://www.gnu.org/software/automake/
"

while test $# -ne 0; do
  case $1 in
    -c) ;;

    -C) copy_on_change=true;;
138
139
140
141
142
143
144


145
146
147

148
149
150
151
152
153
154
148
149
150
151
152
153
154
155
156
157
158

159
160
161
162
163
164
165
166







+
+


-
+







            exit 1;;
        esac
        shift;;

    -o) chowncmd="$chownprog $2"
        shift;;

    -p) cpprog="$cpprog -p";;

    -s) stripcmd=$stripprog;;

    -S) stripcmd="$stripprog $2"
    -S) backupsuffix="$2"
        shift;;

    -t)
        is_target_a_directory=always
        dst_arg=$2
        # Protect names problematic for 'test' and other utilities.
        case $dst_arg in
259
260
261
262
263
264
265




266
267
268
269
270
271
272
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288







+
+
+
+







  esac

  if test -n "$dir_arg"; then
    dst=$src
    dstdir=$dst
    test -d "$dstdir"
    dstdir_status=$?
    # Don't chown directories that already exist.
    if test $dstdir_status = 0; then
      chowncmd=""
    fi
  else

    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
    # might cause directories to be created, which would be especially bad
    # if $src (and thus $dsttmp) contains '*'.
    if test ! -f "$src" && test ! -d "$src"; then
      echo "$0: $src does not exist." >&2
473
474
475
476
477
478
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
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







+
+
+
+
+
+
+














-
+

-
+







       set X $new && new=:$2:$4:$5:$6 &&
       set +f &&
       test "$old" = "$new" &&
       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
    then
      rm -f "$dsttmp"
    else
      # If $backupsuffix is set, and the file being installed
      # already exists, attempt a backup.  Don't worry if it fails,
      # e.g., if mv doesn't support -f.
      if test -n "$backupsuffix" && test -f "$dst"; then
        $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
      fi

      # Rename the file to the real destination.
      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||

      # The rename failed, perhaps because mv can't rename something else
      # to itself, or perhaps because mv is so ancient that it does not
      # support -f.
      {
        # Now remove or move aside any old file at destination location.
        # We try this two ways since rm can't unlink itself on some
        # systems and the destination file might be busy for other
        # reasons.  In this case, the final cleanup might fail but the new
        # file should still install successfully.
        {
          test ! -f "$dst" ||
          $doit $rmcmd -f "$dst" 2>/dev/null ||
          $doit $rmcmd "$dst" 2>/dev/null ||
          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
            { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
          } ||
          { echo "$0: cannot unlink or rename $dst" >&2
            (exit 1); exit 1
          }
        } &&

        # Now rename the file to the real destination.

Changes to unix/installManPage.

1
2
3
4
5
6
7

8

9
10
11
12
13
14
15


16
17
18
19
20
21
22
1
2
3
4
5
6
7
8

9
10
11
12
13
14


15
16
17
18
19
20
21
22
23







+
-
+





-
-
+
+







#!/bin/sh

########################################################################
### Parse Options
###

Gzip=:
Sym=""
SymOrLoc=""
Loc=""
Gz=""
Suffix=""

while true; do
    case $1 in
        -s | --symlinks  ) SymOrLoc="-s "      ;;
        -z | --compress  )     Gzip=$2;  shift ;;
	-s | --symlinks  )      Sym="-s "      ;;
	-z | --compress  )     Gzip=$2;  shift ;;
	-e | --extension )       Gz=$2;  shift ;;
	-x | --suffix    )   Suffix=$2;  shift ;;
	-*) cat <<EOF
Unknown option "$1". Supported options:
    -s         Use symbolic links for manpages with multiple names.
    -z PROG    Use PROG to compress manual pages.
    -e EXT     Defines the extension added by -z PROG when compressing.
43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58







-
+







    echo "source manual page file must exist"
    exit 1
fi
if test -d "$Dir" ; then : ; else
    echo "target directory must exist"
    exit 1
fi
test -z "$SymOrLoc" && SymOrLoc="$Dir/"
test -z "$Sym" && Loc="$Dir/"

########################################################################
### Extract Target Names from Manual Page
###

# A sed script to parse the alternative names out of a man page.
#
128
129
130
131
132
133
134
135

136
137
138
139
140
129
130
131
132
133
134
135

136
137
138
139
140
141







-
+





    if test -z "$First" ; then
	First=$Target
	sed -e "/man\.macros/r $SrcDir/man.macros" -e "/man\.macros/d" \
	    $ManPage > "$Dir/$First"
	chmod 644 "$Dir/$First"
	$Gzip "$Dir/$First"
    else
	ln "$SymOrLoc$First$Gz" "$Dir/$Target$Gz"
	ln $Sym"$Loc$First$Gz" "$Dir/$Target$Gz"
    fi
done

########################################################################
exit 0

Changes to unix/tcl.m4.

24
25
26
27
28
29
30
31

32
33

34
35
36
37
38
39
40
24
25
26
27
28
29
30

31
32

33
34
35
36
37
38
39
40







-
+

-
+







    # the alternative search directory is invoked by --with-tcl
    #

    if test x"${no_tcl}" = x ; then
	# we reset no_tcl in case something fails here
	no_tcl=true
	AC_ARG_WITH(tcl,
	    AC_HELP_STRING([--with-tcl],
	    AS_HELP_STRING([--with-tcl],
		[directory containing tcl configuration (tclConfig.sh)]),
	    with_tclconfig="${withval}")
	    [with_tclconfig="${withval}"])
	AC_MSG_CHECKING([for Tcl configuration])
	AC_CACHE_VAL(ac_cv_c_tclconfig,[

	    # First check to see if --with-tcl was specified.
	    if test x"${with_tclconfig}" != x ; then
		case "${with_tclconfig}" in
		    */tclConfig.sh )
157
158
159
160
161
162
163
164

165
166

167
168
169
170
171
172
173
157
158
159
160
161
162
163

164
165

166
167
168
169
170
171
172
173







-
+

-
+







    # the alternative search directory is invoked by --with-tk
    #

    if test x"${no_tk}" = x ; then
	# we reset no_tk in case something fails here
	no_tk=true
	AC_ARG_WITH(tk,
	    AC_HELP_STRING([--with-tk],
	    AS_HELP_STRING([--with-tk],
		[directory containing tk configuration (tkConfig.sh)]),
	    with_tkconfig="${withval}")
	    [with_tkconfig="${withval}"])
	AC_MSG_CHECKING([for Tk configuration])
	AC_CACHE_VAL(ac_cv_c_tkconfig,[

	    # First check to see if --with-tkconfig was specified.
	    if test x"${with_tkconfig}" != x ; then
		case "${with_tkconfig}" in
		    */tkConfig.sh )
222
223
224
225
226
227
228
229

230
231
232
233


234
235
236
237
238
239
240
222
223
224
225
226
227
228

229
230
231


232
233
234
235
236
237
238
239
240







-
+


-
-
+
+







	    if test x"${ac_cv_c_tkconfig}" = x ; then
		for i in `ls -d ${libdir} 2>/dev/null` \
			`ls -d ${exec_prefix}/lib 2>/dev/null` \
			`ls -d ${prefix}/lib 2>/dev/null` \
			`ls -d /usr/local/lib 2>/dev/null` \
			`ls -d /usr/contrib/lib 2>/dev/null` \
			`ls -d /usr/pkg/lib 2>/dev/null` \
			`ls -d /usr/lib/tk8.7 2>/dev/null` \
			`ls -d /usr/lib/tk9.0 2>/dev/null` \
			`ls -d /usr/lib 2>/dev/null` \
			`ls -d /usr/lib64 2>/dev/null` \
			`ls -d /usr/local/lib/tk8.7 2>/dev/null` \
			`ls -d /usr/local/lib/tcl/tk8.7 2>/dev/null` \
			`ls -d /usr/local/lib/tk9.0 2>/dev/null` \
			`ls -d /usr/local/lib/tcl/tk9.0 2>/dev/null` \
			; do
		    if test -f "$i/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i; pwd)`"
			break
		    fi
		done
	    fi
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
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







-
+


-
+









-
-
-
+
+
+







#		TCL_LIB_FILE
#------------------------------------------------------------------------

AC_DEFUN([SC_LOAD_TCLCONFIG], [
    AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh])

    if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then
        AC_MSG_RESULT([loading])
	AC_MSG_RESULT([loading])
	. "${TCL_BIN_DIR}/tclConfig.sh"
    else
        AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh])
	AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh])
    fi

    # If the TCL_BIN_DIR is the build directory (not the install directory),
    # then set the common variable name to the value of the build variables.
    # For example, the variable TCL_LIB_SPEC will be set to the value
    # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC
    # instead of TCL_BUILD_LIB_SPEC since it will work with both an
    # installed and uninstalled version of Tcl.
    if test -f "${TCL_BIN_DIR}/Makefile" ; then
        TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}"
        TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}"
        TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}"
	TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}"
	TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}"
	TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}"
    elif test "`uname -s`" = "Darwin"; then
	# If Tcl was built as a framework, attempt to use the libraries
	# from the framework at the given location so that linking works
	# against Tcl.framework installed in an arbitrary location.
	case ${TCL_DEFS} in
	    *TCL_FRAMEWORK*)
		if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then
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
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







-
+


-
+









-
-
-
+
+
+







#		TK_BIN_DIR
#------------------------------------------------------------------------

AC_DEFUN([SC_LOAD_TKCONFIG], [
    AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh])

    if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then
        AC_MSG_RESULT([loading])
	AC_MSG_RESULT([loading])
	. "${TK_BIN_DIR}/tkConfig.sh"
    else
        AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh])
	AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh])
    fi

    # If the TK_BIN_DIR is the build directory (not the install directory),
    # then set the common variable name to the value of the build variables.
    # For example, the variable TK_LIB_SPEC will be set to the value
    # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC
    # instead of TK_BUILD_LIB_SPEC since it will work with both an
    # installed and uninstalled version of Tcl.
    if test -f "${TK_BIN_DIR}/Makefile" ; then
        TK_LIB_SPEC="${TK_BUILD_LIB_SPEC}"
        TK_STUB_LIB_SPEC="${TK_BUILD_STUB_LIB_SPEC}"
        TK_STUB_LIB_PATH="${TK_BUILD_STUB_LIB_PATH}"
	TK_LIB_SPEC="${TK_BUILD_LIB_SPEC}"
	TK_STUB_LIB_SPEC="${TK_BUILD_STUB_LIB_SPEC}"
	TK_STUB_LIB_PATH="${TK_BUILD_STUB_LIB_PATH}"
    elif test "`uname -s`" = "Darwin"; then
	# If Tk was built as a framework, attempt to use the libraries
	# from the framework at the given location so that linking works
	# against Tk.framework installed in an arbitrary location.
	case ${TK_DEFS} in
	    *TK_FRAMEWORK*)
		if test -f "${TK_BIN_DIR}/${TK_LIB_FILE}"; then
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
504
505
506
507
508
509
510

511
512
513








514
515
516
517
518
519
520







-
+


-
-
-
-
-
-
-
-







#	Sets the following vars:
#		SHARED_BUILD	Value of 1 or 0
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_SHARED], [
    AC_MSG_CHECKING([how to build libraries])
    AC_ARG_ENABLE(shared,
	AC_HELP_STRING([--enable-shared],
	AS_HELP_STRING([--enable-shared],
	    [build and link with shared libraries (default: on)]),
	[tcl_ok=$enableval], [tcl_ok=yes])

    if test "${enable_shared+set}" = set; then
	enableval="$enable_shared"
	tcl_ok=$enableval
    else
	tcl_ok=yes
    fi

    if test "$tcl_ok" = "yes" ; then
	AC_MSG_RESULT([shared])
	SHARED_BUILD=1
    else
	AC_MSG_RESULT([static])
	SHARED_BUILD=0
	AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?])
547
548
549
550
551
552
553
554

555
556
557
558
559
560
561
539
540
541
542
543
544
545

546
547
548
549
550
551
552
553







-
+







#		FRAMEWORK_BUILD	Value of 1 or 0
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_FRAMEWORK], [
    if test "`uname -s`" = "Darwin" ; then
	AC_MSG_CHECKING([how to package libraries])
	AC_ARG_ENABLE(framework,
	    AC_HELP_STRING([--enable-framework],
	    AS_HELP_STRING([--enable-framework],
		[package shared libraries in MacOSX frameworks (default: off)]),
	    [enable_framework=$enableval], [enable_framework=no])
	if test $enable_framework = yes; then
	    if test $SHARED_BUILD = 0; then
		AC_MSG_WARN([Frameworks can only be built if --enable-shared is yes])
		enable_framework=no
	    fi
605
606
607
608
609
610
611
612

613
614
615
616
617
618
619
597
598
599
600
601
602
603

604
605
606
607
608
609
610
611







-
+







#		LDFLAGS_DEFAULT	Sets to $(LDFLAGS_DEBUG) if true
#				Sets to $(LDFLAGS_OPTIMIZE) if false
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_SYMBOLS], [
    AC_MSG_CHECKING([for build with symbols])
    AC_ARG_ENABLE(symbols,
	AC_HELP_STRING([--enable-symbols],
	AS_HELP_STRING([--enable-symbols],
	    [build with debugging symbols (default: off)]),
	[tcl_ok=$enableval], [tcl_ok=no])
# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.
    if test "$tcl_ok" = "no"; then
	CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'
	LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'
	AC_DEFINE(NDEBUG, 1, [Is no debugging enabled?])
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
656
657
658
659
660
661
662

663
664
665
666
667
668
669
670
671
672
673


674
675
676
677
678
679
680
681
682







-
+










-
-
+
+







#
#	Defines the following vars:
#		HAVE_LANGINFO	Triggers use of nl_langinfo if defined.
#------------------------------------------------------------------------

AC_DEFUN([SC_ENABLE_LANGINFO], [
    AC_ARG_ENABLE(langinfo,
	AC_HELP_STRING([--enable-langinfo],
	AS_HELP_STRING([--enable-langinfo],
	    [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]),
	[langinfo_ok=$enableval], [langinfo_ok=yes])

    HAVE_LANGINFO=0
    if test "$langinfo_ok" = "yes"; then
	AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no])
    fi
    AC_MSG_CHECKING([whether to use nl_langinfo])
    if test "$langinfo_ok" = "yes"; then
	AC_CACHE_VAL(tcl_cv_langinfo_h, [
	    AC_TRY_COMPILE([#include <langinfo.h>], [nl_langinfo(CODESET);],
		    [tcl_cv_langinfo_h=yes],[tcl_cv_langinfo_h=no])])
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <langinfo.h>]], [[nl_langinfo(CODESET);]])],
		    [tcl_cv_langinfo_h=yes], [tcl_cv_langinfo_h=no])])
	AC_MSG_RESULT([$tcl_cv_langinfo_h])
	if test $tcl_cv_langinfo_h = yes; then
	    AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?])
	fi
    else
	AC_MSG_RESULT([$langinfo_ok])
    fi
716
717
718
719
720
721
722
723

724
725
726


727
728
729
730
731

732
733
734
735
736
737
738

739
740
741
742
743
744
745
746
747
748
749
750
751
752

753
754
755
756
757
758
759

760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778

779
780
781
782
783
784
785
708
709
710
711
712
713
714

715
716


717
718
719
720
721
722

723
724
725
726
727
728
729

730
731
732
733
734
735
736
737
738
739
740
741
742
743

744
745
746
747
748
749
750

751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778







-
+

-
-
+
+




-
+






-
+













-
+






-
+



















+







#			according to the user's selection.
#
#--------------------------------------------------------------------

AC_DEFUN([SC_CONFIG_MANPAGES], [
    AC_MSG_CHECKING([whether to use symlinks for manpages])
    AC_ARG_ENABLE(man-symlinks,
	AC_HELP_STRING([--enable-man-symlinks],
	AS_HELP_STRING([--enable-man-symlinks],
	    [use symlinks for the manpages (default: off)]),
	test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks",
	enableval="no")
	[test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks"],
	[enableval="no"])
    AC_MSG_RESULT([$enableval])

    AC_MSG_CHECKING([whether to compress the manpages])
    AC_ARG_ENABLE(man-compression,
	AC_HELP_STRING([--enable-man-compression=PROG],
	AS_HELP_STRING([--enable-man-compression=PROG],
	    [compress the manpages with PROG (default: off)]),
	[case $enableval in
	    yes) AC_MSG_ERROR([missing argument to --enable-man-compression]);;
	    no)  ;;
	    *)   MAN_FLAGS="$MAN_FLAGS --compress $enableval";;
	esac],
	enableval="no")
	[enableval="no"])
    AC_MSG_RESULT([$enableval])
    if test "$enableval" != "no"; then
	AC_MSG_CHECKING([for compressed file suffix])
	touch TeST
	$enableval TeST
	Z=`ls TeST* | sed 's/^....//'`
	rm -f TeST*
	MAN_FLAGS="$MAN_FLAGS --extension $Z"
	AC_MSG_RESULT([$Z])
    fi

    AC_MSG_CHECKING([whether to add a package name suffix for the manpages])
    AC_ARG_ENABLE(man-suffix,
	AC_HELP_STRING([--enable-man-suffix=STRING],
	AS_HELP_STRING([--enable-man-suffix=STRING],
	    [use STRING as a suffix to manpage file names (default: no, AC_PACKAGE_NAME if enabled without specifying STRING)]),
	[case $enableval in
	    yes) enableval="AC_PACKAGE_NAME" MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
	    no)  ;;
	    *)   MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
	esac],
	enableval="no")
	[enableval="no"])
    AC_MSG_RESULT([$enableval])

    AC_SUBST(MAN_FLAGS)
])

#--------------------------------------------------------------------
# SC_CONFIG_SYSTEM
#
#	Determine what the system is (some things cannot be easily checked
#	on a feature-driven basis, alas). This can usually be done via the
#	"uname" command.
#
# Arguments:
#	none
#
# Results:
#	Defines the following var:
#
#	system -	System/platform/version identification code.
#
#--------------------------------------------------------------------

AC_DEFUN([SC_CONFIG_SYSTEM], [
    AC_CACHE_CHECK([system version], tcl_cv_sys_version, [
	if test "${TEA_PLATFORM}" = "windows" ; then
	    tcl_cv_sys_version=windows
	else
888
889
890
891
892
893
894
895

896
897
898
899
900
901
902
903
904

905
906
907
908
909
910
911
912
913
914
915
916
917

918

919
920


921
922
923
924
925
926
927
928
929
930
931
932
933

934
935
936
937
938
939
940
881
882
883
884
885
886
887

888
889
890
891
892
893
894
895
896

897
898
899
900
901
902
903
904
905
906
907
908
909

910
911
912


913
914
915
916
917
918
919
920
921
922
923
924
925
926

927
928
929
930
931
932
933
934







-
+








-
+












-
+

+
-
-
+
+












-
+








AC_DEFUN([SC_CONFIG_CFLAGS], [

    # Step 0.a: Enable 64 bit support?

    AC_MSG_CHECKING([if 64bit support is requested])
    AC_ARG_ENABLE(64bit,
	AC_HELP_STRING([--enable-64bit],
	AS_HELP_STRING([--enable-64bit],
	    [enable 64bit support (default: off)]),
	[do64bit=$enableval], [do64bit=no])
    AC_MSG_RESULT([$do64bit])

    # Step 0.b: Enable Solaris 64 bit VIS support?

    AC_MSG_CHECKING([if 64bit Sparc VIS support is requested])
    AC_ARG_ENABLE(64bit-vis,
	AC_HELP_STRING([--enable-64bit-vis],
	AS_HELP_STRING([--enable-64bit-vis],
	    [enable 64bit Sparc VIS support (default: off)]),
	[do64bitVIS=$enableval], [do64bitVIS=no])
    AC_MSG_RESULT([$do64bitVIS])
    # Force 64bit on with VIS
    AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes])

    # Step 0.c: Check if visibility support is available. Do this here so
    # that platform specific alternatives can be used below if this fails.

    AC_CACHE_CHECK([if compiler supports visibility "hidden"],
	tcl_cv_cc_visibility_hidden, [
	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
	AC_TRY_LINK([
	AC_LINK_IFELSE([AC_LANG_PROGRAM([[
	    extern __attribute__((__visibility__("hidden"))) void f(void);
	    void f(void) {}]], [[f();]])],
	    void f(void) {}], [f();], tcl_cv_cc_visibility_hidden=yes,
	    tcl_cv_cc_visibility_hidden=no)
	    [tcl_cv_cc_visibility_hidden=yes],
	    [tcl_cv_cc_visibility_hidden=no])
	CFLAGS=$hold_cflags])
    AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [
	AC_DEFINE(MODULE_SCOPE,
	    [extern __attribute__((__visibility__("hidden")))],
	    [Compiler support for module scope symbols])
	AC_DEFINE(HAVE_HIDDEN, [1], [Compiler support for module scope symbols])
    ])

    # Step 0.d: Disable -rpath support?

    AC_MSG_CHECKING([if rpath support is requested])
    AC_ARG_ENABLE(rpath,
	AC_HELP_STRING([--disable-rpath],
	AS_HELP_STRING([--disable-rpath],
	    [disable rpath support (default: on)]),
	[doRpath=$enableval], [doRpath=yes])
    AC_MSG_RESULT([$doRpath])

    # Step 1: set the variable "system" to hold the name and version number
    # for the system.

967
968
969
970
971
972
973
974

975
976
977
978
979
980
981
961
962
963
964
965
966
967

968
969
970
971
972
973
974
975







-
+







    AS_IF([test "$GCC" = yes], [
	CFLAGS_OPTIMIZE=-O2
	CFLAGS_WARNING="-Wall -Wextra -Wshadow -Wundef -Wwrite-strings -Wpointer-arith"
	case "${CC}" in
	    *++|*++-*)
		;;
	    *)
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wc++-compat -Wdeclaration-after-statement"
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wc++-compat -fextended-identifiers"
		;;
	esac

    ], [
	CFLAGS_OPTIMIZE=-O
	CFLAGS_WARNING=""
    ])
992
993
994
995
996
997
998
999

1000
1001
1002
1003
1004
1005
1006
986
987
988
989
990
991
992

993
994
995
996
997
998
999
1000







-
+







		# AIX requires the _r compiler when gcc isn't being used
		case "${CC}" in
		    *_r|*_r\ *)
			# ok ...
			;;
		    *)
			# Make sure only first arg gets _r
		    	CC=`echo "$CC" | sed -e 's/^\([[^ ]]*\)/\1_r/'`
			CC=`echo "$CC" | sed -e 's/^\([[^ ]]*\)/\1_r/'`
			;;
		esac
		AC_MSG_RESULT([Using $CC for compiling with threads])
	    ])
	    LIBS="$LIBS -lc"
	    SHLIB_CFLAGS=""
	    SHLIB_SUFFIX=".so"
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
1116

1117
1118
1119
1120
1121
1122
1123
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







-
+









-
-
-


-
+



-
-
-
+
+
+






-
+

-
+







	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	CYGWIN_*)
	CYGWIN_*|MINGW32_*|MSYS_*)
	    SHLIB_CFLAGS="-fno-common"
	    SHLIB_LD='${CC} -shared'
	    SHLIB_SUFFIX=".dll"
	    DL_OBJS="tclLoadDl.o"
	    PLAT_OBJS='${CYGWIN_OBJS}'
	    PLAT_SRCS='${CYGWIN_SRCS}'
	    DL_LIBS="-ldl"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    TCL_NEEDS_EXP_FILE=1
	    TCL_EXPORT_FILE_SUFFIX='${VERSION}.dll.a'
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$[@].a"
	    AC_CACHE_CHECK(for Cygwin version of gcc,
		ac_cv_cygwin,
		AC_TRY_COMPILE([
		AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
		#ifdef __CYGWIN__
		    #error cygwin
		#endif
		], [],
		ac_cv_cygwin=no,
		ac_cv_cygwin=yes)
		]], [[]])],
		[ac_cv_cygwin=no],
		[ac_cv_cygwin=yes])
	    )
	    if test "$ac_cv_cygwin" = "no"; then
		AC_MSG_ERROR([${CC} is not a cygwin compiler.])
	    fi
	    do64bit_ok=yes
	    if test "x${SHARED_BUILD}" = "x1"; then
		echo "running cd ../win; ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args"
		echo "running cd ../win; ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args --enable-64bit --host=x86_64-w64-mingw32"
		# The eval makes quoting arguments work.
		if cd ../win; eval ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args; cd ../unix
		if cd ../win; eval ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args --enable-64bit --host=x86_64-w64-mingw32; cd ../unix
		then :
		else
		    { echo "configure: error: configure failed for ../win" 1>&2; exit 1; }
		fi
	    fi
	    ;;
	dgux*)
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
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







-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+


-
+













+
+
+
+
+
+
+
+
+
+








+
-
+







	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])

	    # Check to enable 64-bit flags for compiler/linker

	    AS_IF([test "$do64bit" = yes], [
	        AS_IF([test "$GCC" = yes], [
	            AC_MSG_WARN([64bit mode not supported by gcc])
	        ], [
	            do64bit_ok=yes
	            SHLIB_LD="ld -64 -shared -rdata_shared"
	            CFLAGS="$CFLAGS -64"
	            LDFLAGS_ARCH="-64"
	        ])
		AS_IF([test "$GCC" = yes], [
		    AC_MSG_WARN([64bit mode not supported by gcc])
		], [
		    do64bit_ok=yes
		    SHLIB_LD="ld -64 -shared -rdata_shared"
		    CFLAGS="$CFLAGS -64"
		    LDFLAGS_ARCH="-64"
		])
	    ])
	    ;;
	Linux*|GNU*|NetBSD-Debian)
	Linux*|GNU*|NetBSD-Debian|DragonFly-*|FreeBSD-*)
	    SHLIB_CFLAGS="-fPIC -fno-common"
	    SHLIB_SUFFIX=".so"

	    CFLAGS_OPTIMIZE="-O2"
	    # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings
	    # when you inline the string and math operations.  Turn this off to
	    # get rid of the warnings.
	    #CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES"

	    SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared'
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    LDFLAGS="$LDFLAGS -Wl,--export-dynamic"

	    case $system in
	    DragonFly-*|FreeBSD-*)
		# The -pthread needs to go in the LDFLAGS, not LIBS
		LIBS=`echo $LIBS | sed s/-pthread//`
		CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
		LDFLAGS="$LDFLAGS $PTHREAD_LIBS"
	    ;;
	    esac

	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'])
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"])
	    AS_IF([test $do64bit = yes], [
		AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [
		    hold_cflags=$CFLAGS
		    CFLAGS="$CFLAGS -m64"
		    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
		    AC_TRY_LINK(,, tcl_cv_cc_m64=yes, tcl_cv_cc_m64=no)
			    [tcl_cv_cc_m64=yes],[tcl_cv_cc_m64=no])
		    CFLAGS=$hold_cflags])
		AS_IF([test $tcl_cv_cc_m64 = yes], [
		    CFLAGS="$CFLAGS -m64"
		    do64bit_ok=yes
		])
	   ])

1358
1359
1360
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
1387
1388
1389
1390

1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409


1410
1411
1412
1413
1414
1415

1416
1417
1418
1419
1420
1421


1422
1423
1424
1425
1426












1427
1428
1429
1430
1431
1432

1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492




1493
1494
1495
1496

1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512




1513
1514
1515
1516
1517
1518
1519

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

1535
1536

1537
1538
1539
1540
1541
1542
1543
1360
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
1387
1388
1389
1390
1391
1392

1393
1394
1395
1396
1397


1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421

1422
1423
1424
1425
1426








1427
1428
1429
1430
1431
1432
1433
1434
1435


1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478

1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491




1492
1493
1494
1495
1496
1497
1498
1499
1500
1501

1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516

1517
1518

1519
1520
1521
1522
1523
1524
1525
1526







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
+

















-
-
+
+





-
+




-
-
+
+





+
+
+
+
+
+
+
+
+
+
+
+





-
+




-
-
-
-
-
-
-
-








+
-
-
+
+











-
+





-
+
















-
-
-
-
+
+
+
+



-
+












-
-
-
-
+
+
+
+






-
+














-
+

-
+







		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'])
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    # The -pthread needs to go in the CFLAGS, not LIBS
	    LIBS=`echo $LIBS | sed s/-pthread//`
	    CFLAGS="$CFLAGS -pthread"
	    LDFLAGS="$LDFLAGS -pthread"
	    ;;
	DragonFly-*|FreeBSD-*)
	    # This configuration from FreeBSD Ports.
	    SHLIB_LD="${CC} -shared"
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$[@]"
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'])
	    # The -pthread needs to go in the LDFLAGS, not LIBS
	    LIBS=`echo $LIBS | sed s/-pthread//`
	    CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
	    LDFLAGS="$LDFLAGS $PTHREAD_LIBS"
	    case $system in
	    FreeBSD-3.*)
		# Version numbers are dot-stripped by system policy.
		TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .`
		UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
		TCL_LIB_VERSIONS_OK=nodots
		;;
	    esac
	    ;;
	Darwin-*)
	    CFLAGS_OPTIMIZE="-Os"
	    CFLAGS_OPTIMIZE="-O2"
	    SHLIB_CFLAGS="-fno-common"
	    # To avoid discrepancies between what headers configure sees during
	    # preprocessing tests and compiling tests, move any -isysroot and
	    # -mmacosx-version-min flags from CFLAGS to CPPFLAGS:
	    CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \
		awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
		if ([$]i~/^(isysroot|mmacosx-version-min)/) print "-"[$]i}'`"
	    CFLAGS="`echo " ${CFLAGS}" | \
		awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
		if (!([$]i~/^(isysroot|mmacosx-version-min)/)) print "-"[$]i}'`"
	    AS_IF([test $do64bit = yes], [
		case `arch` in
		    ppc)
			AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag],
				tcl_cv_cc_arch_ppc64, [
			    hold_cflags=$CFLAGS
			    CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
			    AC_TRY_LINK(,, tcl_cv_cc_arch_ppc64=yes,
				    tcl_cv_cc_arch_ppc64=no)
			    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
				    [tcl_cv_cc_arch_ppc64=yes],[tcl_cv_cc_arch_ppc64=no])
			    CFLAGS=$hold_cflags])
			AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [
			    CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
			    do64bit_ok=yes
			]);;
		    i386)
		    i386|x86_64)
			AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag],
				tcl_cv_cc_arch_x86_64, [
			    hold_cflags=$CFLAGS
			    CFLAGS="$CFLAGS -arch x86_64"
			    AC_TRY_LINK(,, tcl_cv_cc_arch_x86_64=yes,
				    tcl_cv_cc_arch_x86_64=no)
			    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
				    [tcl_cv_cc_arch_x86_64=yes],[tcl_cv_cc_arch_x86_64=no])
			    CFLAGS=$hold_cflags])
			AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [
			    CFLAGS="$CFLAGS -arch x86_64"
			    do64bit_ok=yes
			]);;
		    arm64)
			AC_CACHE_CHECK([if compiler accepts -arch arm64 flag],
				tcl_cv_cc_arch_arm64, [
			    hold_cflags=$CFLAGS
			    CFLAGS="$CFLAGS -arch arm64"
			    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
				    [tcl_cv_cc_arch_arm64=yes],[tcl_cv_cc_arch_arm64=no])
			    CFLAGS=$hold_cflags])
			AS_IF([test $tcl_cv_cc_arch_arm64 = yes], [
			    CFLAGS="$CFLAGS -arch arm64"
			    do64bit_ok=yes
			]);;
		    *)
			AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);;
		esac
	    ], [
		# Check for combined 32-bit and 64-bit fat build
		AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \
		AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64|arm64) ' \
		    && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [
		    fat_32_64=yes])
	    ])
	    SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS}'
	    AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module"
		AC_TRY_LINK(, [int i;], tcl_cv_ld_single_module=yes, tcl_cv_ld_single_module=no)
		LDFLAGS=$hold_ldflags])
	    AS_IF([test $tcl_cv_ld_single_module = yes], [
		SHLIB_LD="${SHLIB_LD} -Wl,-single_module"
	    ])
	    SHLIB_SUFFIX=".dylib"
	    DL_OBJS="tclLoadDyld.o"
	    DL_LIBS=""
	    LDFLAGS="$LDFLAGS -headerpad_max_install_names"
	    AC_CACHE_CHECK([if ld accepts -search_paths_first flag],
		    tcl_cv_ld_search_paths_first, [
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
		AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])],
		AC_TRY_LINK(, [int i;], tcl_cv_ld_search_paths_first=yes,
			tcl_cv_ld_search_paths_first=no)
			[tcl_cv_ld_search_paths_first=yes],
		    [tcl_cv_ld_search_paths_first=no])
		LDFLAGS=$hold_ldflags])
	    AS_IF([test $tcl_cv_ld_search_paths_first = yes], [
		LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
	    ])
	    AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
		AC_DEFINE(MODULE_SCOPE, [__private_extern__],
		    [Compiler support for module scope symbols])
		tcl_cv_cc_visibility_hidden=yes
	    ])
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
	    LD_LIBRARY_PATH_VAR="DYLD_FALLBACK_LIBRARY_PATH"
	    AC_DEFINE(MAC_OSX_TCL, 1, [Is this a Mac I see before me?])
	    PLAT_OBJS='${MAC_OSX_OBJS}'
	    PLAT_SRCS='${MAC_OSX_SRCS}'
	    AC_MSG_CHECKING([whether to use CoreFoundation])
	    AC_ARG_ENABLE(corefoundation,
		AC_HELP_STRING([--enable-corefoundation],
		AS_HELP_STRING([--enable-corefoundation],
		    [use CoreFoundation API on MacOSX (default: on)]),
		[tcl_corefoundation=$enableval], [tcl_corefoundation=yes])
	    AC_MSG_RESULT([$tcl_corefoundation])
	    AS_IF([test $tcl_corefoundation = yes], [
		AC_CACHE_CHECK([for CoreFoundation.framework],
			tcl_cv_lib_corefoundation, [
		    hold_libs=$LIBS
		    AS_IF([test "$fat_32_64" = yes], [
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    # On Tiger there is no 64-bit CF, so remove 64-bit
			    # archs from CFLAGS et al. while testing for
			    # presence of CF. 64-bit CF is disabled in
			    # tclUnixPort.h if necessary.
			    eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"'
			done])
		    LIBS="$LIBS -framework CoreFoundation"
		    AC_TRY_LINK([#include <CoreFoundation/CoreFoundation.h>],
			[CFBundleRef b = CFBundleGetMainBundle();],
			tcl_cv_lib_corefoundation=yes,
			tcl_cv_lib_corefoundation=no)
		    AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <CoreFoundation/CoreFoundation.h>]],
			[[CFBundleRef b = CFBundleGetMainBundle();]])],
			[tcl_cv_lib_corefoundation=yes],
			[tcl_cv_lib_corefoundation=no])
		    AS_IF([test "$fat_32_64" = yes], [
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval $v'="$hold_'$v'"'
		        done])
			done])
		    LIBS=$hold_libs])
		AS_IF([test $tcl_cv_lib_corefoundation = yes], [
		    LIBS="$LIBS -framework CoreFoundation"
		    AC_DEFINE(HAVE_COREFOUNDATION, 1,
			[Do we have access to Darwin CoreFoundation.framework?])
		], [tcl_corefoundation=no])
		AS_IF([test "$fat_32_64" = yes -a $tcl_corefoundation = yes],[
		    AC_CACHE_CHECK([for 64-bit CoreFoundation],
			    tcl_cv_lib_corefoundation_64, [
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
			done
			AC_TRY_LINK([#include <CoreFoundation/CoreFoundation.h>],
			    [CFBundleRef b = CFBundleGetMainBundle();],
			    tcl_cv_lib_corefoundation_64=yes,
			    tcl_cv_lib_corefoundation_64=no)
			AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <CoreFoundation/CoreFoundation.h>]],
			    [[CFBundleRef b = CFBundleGetMainBundle();]])],
			    [tcl_cv_lib_corefoundation_64=yes],
			    [tcl_cv_lib_corefoundation_64=no])
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval $v'="$hold_'$v'"'
			done])
		    AS_IF([test $tcl_cv_lib_corefoundation_64 = no], [
			AC_DEFINE(NO_COREFOUNDATION_64, 1,
			    [Is Darwin CoreFoundation unavailable for 64-bit?])
                        LDFLAGS="$LDFLAGS -Wl,-no_arch_warnings"
			LDFLAGS="$LDFLAGS -Wl,-no_arch_warnings"
		    ])
		])
	    ])
	    ;;
	OS/390-*)
	    SHLIB_LD_LIBS=""
	    CFLAGS_OPTIMIZE=""		# Optimizer is buggy
	    AC_DEFINE(_OE_SOCKETS, 1,	# needed in sys/socket.h
		[Should OS/390 do the right thing with sockets?])
	    ;;
	OSF1-V*)
	    # Digital OSF/1
	    SHLIB_CFLAGS=""
	    AS_IF([test "$SHARED_BUILD" = 1], [
	        SHLIB_LD='ld -shared -expect_unresolved "*"'
		SHLIB_LD='${CC} -shared'
	    ], [
	        SHLIB_LD='ld -non_shared -expect_unresolved "*"'
		SHLIB_LD='${CC} -non_shared'
	    ])
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
1725
1726
1727
1728
1729
1730
1731
1732
1733


1734
1735
1736
1737
1738
1739
1740
1708
1709
1710
1711
1712
1713
1714


1715
1716
1717
1718
1719
1720
1721
1722
1723







-
-
+
+







	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers
	    # that don't grok the -Bexport option.  Test that it does.
	    AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -Wl,-Bexport"
		AC_TRY_LINK(, [int i;], tcl_cv_ld_Bexport=yes, tcl_cv_ld_Bexport=no)
	        LDFLAGS=$hold_ldflags])
		AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])],[tcl_cv_ld_Bexport=yes],[tcl_cv_ld_Bexport=no])
		LDFLAGS=$hold_ldflags])
	    AS_IF([test $tcl_cv_ld_Bexport = yes], [
		LDFLAGS="$LDFLAGS -Wl,-Bexport"
	    ])
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
    esac
1752
1753
1754
1755
1756
1757
1758
1759

1760
1761
1762
1763
1764
1765
1766
1735
1736
1737
1738
1739
1740
1741

1742
1743
1744
1745
1746
1747
1748
1749







-
+







dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's
dnl # preprocessing tests use only CPPFLAGS.
    AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""])

    # Step 4: disable dynamic loading if requested via a command-line switch.

    AC_ARG_ENABLE(load,
	AC_HELP_STRING([--enable-load],
	AS_HELP_STRING([--enable-load],
	    [allow dynamic loading and "load" command (default: on)]),
	[tcl_ok=$enableval], [tcl_ok=yes])
    AS_IF([test "$tcl_ok" = no], [DL_OBJS=""])

    AS_IF([test "x$DL_OBJS" != x], [BUILD_DLTEST="\$(DLTEST_TARGETS)"], [
	AC_MSG_WARN([Can't figure out how to do dynamic loading or shared libraries on this system.])
	SHLIB_CFLAGS=""
1779
1780
1781
1782
1783
1784
1785
1786
1787


1788
1789
1790
1791
1792

1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816








1817
1818

1819
1820
1821
1822
1823
1824
1825






1826
1827
1828
1829
1830

1831
1832

1833
1834
1835
1836
1837
1838
1839
1840

1841
1842
1843
1844
1845



1846
1847
1848
1849



1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
































1862
1863



1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876

1877
1878
1879
1880
1881
1882
1883
1762
1763
1764
1765
1766
1767
1768


1769
1770
1771
1772
1773
1774

1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791








1792
1793
1794
1795
1796
1797
1798
1799
1800

1801
1802






1803
1804
1805
1806
1807
1808
1809
1810
1811
1812

1813
1814

1815
1816
1817
1818
1819
1820
1821
1822

1823
1824
1825



1826
1827
1828
1829



1830
1831
1832












1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890







-
-
+
+




-
+
















-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
+

-
-
-
-
-
-
+
+
+
+
+
+




-
+

-
+







-
+


-
-
-
+
+
+

-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+













+







    # libraries to the right flags for gcc, instead of those for the
    # standard manufacturer compiler.

    AS_IF([test "$DL_OBJS" != "tclLoadNone.o" -a "$GCC" = yes], [
	case $system in
	    AIX-*) ;;
	    BSD/OS*) ;;
	    CYGWIN_*) ;;
	    HP_UX*) ;;
	    CYGWIN_*|MINGW32_*|MSYS_*) ;;
	    HP-UX*) ;;
	    Darwin-*) ;;
	    IRIX*) ;;
	    Linux*|GNU*) ;;
	    NetBSD-*|OpenBSD-*) ;;
	    OSF1-V*) ;;
	    OSF1-*) ;;
	    SCO_SV-3.2*) ;;
	    *) SHLIB_CFLAGS="-fPIC" ;;
	esac])

    AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
	AC_DEFINE(MODULE_SCOPE, [extern],
	    [No Compiler support for module scope symbols])
    ])

    AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [
	SHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}'])
    AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [
	UNSHARED_LIB_SUFFIX='${VERSION}.a'])
    DLL_INSTALL_DIR="\$(LIB_INSTALL_DIR)"

    AS_IF([test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""], [
        LIB_SUFFIX=${SHARED_LIB_SUFFIX}
        MAKE_LIB='${SHLIB_LD} -o [$]@ ${OBJS} ${LDFLAGS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'
        AS_IF([test "${SHLIB_SUFFIX}" = ".dll"], [
            INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)";if test -f $(LIB_FILE).a; then $(INSTALL_DATA) $(LIB_FILE).a "$(LIB_INSTALL_DIR)"; fi;'
            DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)"
        ], [
            INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'
        ])
	LIB_SUFFIX=${SHARED_LIB_SUFFIX}
	MAKE_LIB='${SHLIB_LD} -o [$]@ ${OBJS} ${LDFLAGS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'
	AS_IF([test "${SHLIB_SUFFIX}" = ".dll"], [
	    INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"'
	    DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)"
	], [
	    INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'
	])
    ], [
        LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}
	LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}

        AS_IF([test "$RANLIB" = ""], [
            MAKE_LIB='$(STLIB_LD) [$]@ ${OBJS}'
        ], [
            MAKE_LIB='${STLIB_LD} [$]@ ${OBJS} ; ${RANLIB} [$]@'
        ])
        INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'
	AS_IF([test "$RANLIB" = ""], [
	    MAKE_LIB='$(STLIB_LD) [$]@ ${OBJS}'
	], [
	    MAKE_LIB='${STLIB_LD} [$]@ ${OBJS} ; ${RANLIB} [$]@'
	])
	INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'
    ])

    # Stub lib does not depend on shared/static configuration
    AS_IF([test "$RANLIB" = ""], [
        MAKE_STUB_LIB='${STLIB_LD} [$]@ ${STUB_LIB_OBJS}'
	MAKE_STUB_LIB='${STLIB_LD} [$]@ ${STUB_LIB_OBJS}'
    ], [
        MAKE_STUB_LIB='${STLIB_LD} [$]@ ${STUB_LIB_OBJS} ; ${RANLIB} [$]@'
	MAKE_STUB_LIB='${STLIB_LD} [$]@ ${STUB_LIB_OBJS} ; ${RANLIB} [$]@'
    ])
    INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) "$(LIB_INSTALL_DIR)/$(STUB_LIB_FILE)"'

    # Define TCL_LIBS now that we know what DL_LIBS is.
    # The trick here is that we don't want to change the value of TCL_LIBS if
    # it is already set when tclConfig.sh had been loaded by Tk.
    AS_IF([test "x${TCL_LIBS}" = x], [
        TCL_LIBS="${DL_LIBS} ${LIBS} ${MATH_LIBS}"])
	TCL_LIBS="${DL_LIBS} ${LIBS} ${MATH_LIBS}"])
    AC_SUBST(TCL_LIBS)

	# See if the compiler supports casting to a union type.
	# This is used to stop gcc from printing a compiler
	# warning when initializing a union member.
    # See if the compiler supports casting to a union type.
    # This is used to stop gcc from printing a compiler
    # warning when initializing a union member.

	AC_CACHE_CHECK(for cast to union support,
	    tcl_cv_cast_to_union,
	    AC_TRY_COMPILE([],
    AC_CACHE_CHECK(for cast to union support,
	tcl_cv_cast_to_union,
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
	    [
		  union foo { int i; double d; };
		  union foo f = (union foo) (int) 0;
	    ],
	    tcl_cv_cast_to_union=yes,
	    tcl_cv_cast_to_union=no)
	)
	if test "$tcl_cv_cast_to_union" = "yes"; then
	    AC_DEFINE(HAVE_CAST_TO_UNION, 1,
		    [Defined when compiler supports casting to union type.])
	fi

		union foo { int i; double d; };
		union foo f = (union foo) (int) 0;
	]])],
	[tcl_cv_cast_to_union=yes],
	[tcl_cv_cast_to_union=no])
    )
    if test "$tcl_cv_cast_to_union" = "yes"; then
	AC_DEFINE(HAVE_CAST_TO_UNION, 1,
		[Defined when compiler supports casting to union type.])
    fi
    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -fno-lto"
    AC_CACHE_CHECK(for working -fno-lto,
	ac_cv_nolto,
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
	[ac_cv_nolto=yes],
	[ac_cv_nolto=no])
    )
    CFLAGS=$hold_cflags
    if test "$ac_cv_nolto" = "yes" ; then
	CFLAGS_NOLTO="-fno-lto"
    else
	CFLAGS_NOLTO=""
    fi
    AC_CACHE_CHECK([if the compiler understands -finput-charset],
	tcl_cv_cc_input_charset, [
	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -finput-charset=UTF-8"
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[tcl_cv_cc_input_charset=yes],[tcl_cv_cc_input_charset=no])
	CFLAGS=$hold_cflags])
    if test $tcl_cv_cc_input_charset = yes; then
	CFLAGS="$CFLAGS -finput-charset=UTF-8"
    fi

    AC_CHECK_HEADER(stdbool.h, [AC_DEFINE(HAVE_STDBOOL_H, 1, [Do we have <stdbool.h>?])],)

    # Check for vfork, posix_spawnp() and friends unconditionally
    AC_CHECK_FUNCS(vfork posix_spawnp posix_spawn_file_actions_adddup2 posix_spawnattr_setflags)

    # FIXME: This subst was left in only because the TCL_DL_LIBS
    # entry in tclConfig.sh uses it. It is not clear why someone
    # would use TCL_DL_LIBS instead of TCL_LIBS.
    AC_SUBST(DL_LIBS)

    AC_SUBST(DL_OBJS)
    AC_SUBST(PLAT_OBJS)
    AC_SUBST(PLAT_SRCS)
    AC_SUBST(LDAIX_SRC)
    AC_SUBST(CFLAGS)
    AC_SUBST(CFLAGS_DEBUG)
    AC_SUBST(CFLAGS_OPTIMIZE)
    AC_SUBST(CFLAGS_WARNING)
    AC_SUBST(CFLAGS_NOLTO)

    AC_SUBST(LDFLAGS)
    AC_SUBST(LDFLAGS_DEBUG)
    AC_SUBST(LDFLAGS_OPTIMIZE)
    AC_SUBST(CC_SEARCH_FLAGS)
    AC_SUBST(LD_SEARCH_FLAGS)

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
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976

1977
1978
1979
1980
1981
1982
1983
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







-
-
-








-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-




-
-
-
-
-
-
-




-
+







#
# Arguments:
#	none
#
# Results:
#
#	Defines some of the following vars:
#		NO_DIRENT_H
#		NO_STDLIB_H
#		NO_STRING_H
#		NO_SYS_WAIT_H
#		NO_DLFCN_H
#		HAVE_SYS_PARAM_H
#		HAVE_STRING_H ?
#
#--------------------------------------------------------------------

AC_DEFUN([SC_MISSING_POSIX_HEADERS], [
    AC_CACHE_CHECK([dirent.h], tcl_cv_dirent_h, [
    AC_TRY_LINK([#include <sys/types.h>
#include <dirent.h>], [
#ifndef _POSIX_SOURCE
#   ifdef __Lynx__
	/*
	 * Generate compilation error to make the test fail:  Lynx headers
	 * are only valid if really in the POSIX environment.
	 */

	missing_procedure();
#   endif
#endif
DIR *d;
struct dirent *entryPtr;
char *p;
d = opendir("foobar");
entryPtr = readdir(d);
p = entryPtr->d_name;
closedir(d);
], tcl_cv_dirent_h=yes, tcl_cv_dirent_h=no)])

    if test $tcl_cv_dirent_h = no; then
	AC_DEFINE(NO_DIRENT_H, 1, [Do we have <dirent.h>?])
    fi

    AC_CHECK_HEADER(stdlib.h, tcl_ok=1, tcl_ok=0)
    AC_EGREP_HEADER(strtol, stdlib.h, , tcl_ok=0)
    AC_EGREP_HEADER(strtoul, stdlib.h, , tcl_ok=0)
    if test $tcl_ok = 0; then
	AC_DEFINE(NO_STDLIB_H, 1, [Do we have <stdlib.h>?])
    fi
    AC_CHECK_HEADER(string.h, tcl_ok=1, tcl_ok=0)
    AC_EGREP_HEADER(strstr, string.h, , tcl_ok=0)
    AC_EGREP_HEADER(strerror, string.h, , tcl_ok=0)

    # See also memmove check below for a place where NO_STRING_H can be
    # set and why.

    if test $tcl_ok = 0; then
	AC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?])
    fi

    AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have <sys/wait.h>?])])
    AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have <dlfcn.h>?])])

    # OS/390 lacks sys/param.h (and doesn't need it, by chance).
    AC_HAVE_HEADERS(sys/param.h)
    AC_CHECK_HEADERS([sys/param.h])
])

#--------------------------------------------------------------------
# SC_PATH_X
#
#	Locate the X11 header files and the X11 library archive.  Try
#	the ac_path_x macro first, but if it doesn't find the X stuff
1998
1999
2000
2001
2002
2003
2004
2005

2006
2007
2008
2009
2010
2011
2012
2013
2014
2015

2016
2017
2018
2019
2020
2021
2022
1963
1964
1965
1966
1967
1968
1969

1970
1971
1972
1973
1974
1975
1976
1977
1978
1979

1980
1981
1982
1983
1984
1985
1986
1987







-
+









-
+







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

AC_DEFUN([SC_PATH_X], [
    AC_PATH_X
    not_really_there=""
    if test "$no_x" = ""; then
	if test "$x_includes" = ""; then
	    AC_TRY_CPP([#include <X11/Xlib.h>], , not_really_there="yes")
	    AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include <X11/Xlib.h>]])],[],[not_really_there="yes"])
	else
	    if test ! -r $x_includes/X11/Xlib.h; then
		not_really_there="yes"
	    fi
	fi
    fi
    if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then
	AC_MSG_CHECKING([for X11 header files])
	found_xincludes="no"
	AC_TRY_CPP([#include <X11/Xlib.h>], found_xincludes="yes", found_xincludes="no")
	AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include <X11/Xlib.h>]])],[found_xincludes="yes"],[found_xincludes="no"])
	if test "$found_xincludes" = "no"; then
	    dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include"
	    for i in $dirs ; do
		if test -r $i/X11/Xlib.h; then
		    AC_MSG_RESULT([$i])
		    XINCLUDES=" -I$i"
		    found_xincludes="yes"
2116
2117
2118
2119
2120
2121
2122
2123

2124
2125

2126
2127
2128
2129



2130
2131
2132
2133
2134
2135
2136



2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147



2148
2149
2150


2151
2152
2153
2154
2155
2156
2157
2158
2159



2160
2161
2162


2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174



2175
2176
2177
2178
2179
2180
2181
2081
2082
2083
2084
2085
2086
2087

2088
2089

2090
2091
2092


2093
2094
2095
2096
2097
2098
2099
2100


2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112


2113
2114
2115
2116


2117
2118
2119
2120
2121
2122
2123
2124
2125


2126
2127
2128
2129


2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141


2142
2143
2144
2145
2146
2147
2148
2149
2150
2151







-
+

-
+


-
-
+
+
+





-
-
+
+
+









-
-
+
+
+

-
-
+
+







-
-
+
+
+

-
-
+
+










-
-
+
+
+







#		HAVE_TM_TZADJ
#		HAVE_TIMEZONE_VAR
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TIME_HANDLER], [
    AC_CHECK_HEADERS(sys/time.h)
    AC_HEADER_TIME
    AC_CHECK_HEADERS_ONCE([sys/time.h])

    AC_CHECK_FUNCS(gmtime_r localtime_r mktime)
    AC_CHECK_FUNCS(gmtime_r localtime_r)

    AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [
	AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_tzadj;],
	    tcl_cv_member_tm_tzadj=yes, tcl_cv_member_tm_tzadj=no)])
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>]], [[struct tm tm; (void)tm.tm_tzadj;]])],
	    [tcl_cv_member_tm_tzadj=yes],
	    [tcl_cv_member_tm_tzadj=no])])
    if test $tcl_cv_member_tm_tzadj = yes ; then
	AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?])
    fi

    AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [
	AC_TRY_COMPILE([#include <time.h>], [struct tm tm; (void)tm.tm_gmtoff;],
	    tcl_cv_member_tm_gmtoff=yes, tcl_cv_member_tm_gmtoff=no)])
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>]], [[struct tm tm; (void)tm.tm_gmtoff;]])],
	    [tcl_cv_member_tm_gmtoff=yes],
	    [tcl_cv_member_tm_gmtoff=no])])
    if test $tcl_cv_member_tm_gmtoff = yes ; then
	AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?])
    fi

    #
    # Its important to include time.h in this check, as some systems
    # (like convex) have timezone functions, etc.
    #
    AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [
	AC_TRY_COMPILE([#include <time.h>],
	    [extern long timezone;
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>
#include <stdlib.h>]],
	[[extern long timezone;
	    timezone += 1;
	    exit (0);],
	    tcl_cv_timezone_long=yes, tcl_cv_timezone_long=no)])
	    exit (0);]])],
	    [tcl_cv_timezone_long=yes], [tcl_cv_timezone_long=no])])
    if test $tcl_cv_timezone_long = yes ; then
	AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
    else
	#
	# On some systems (eg IRIX 6.2), timezone is a time_t and not a long.
	#
	AC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [
	    AC_TRY_COMPILE([#include <time.h>],
		[extern time_t timezone;
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>
#include <stdlib.h>]],
	    [[extern time_t timezone;
		timezone += 1;
		exit (0);],
		tcl_cv_timezone_time=yes, tcl_cv_timezone_time=no)])
		exit (0);]])],
		[tcl_cv_timezone_time=yes], [tcl_cv_timezone_time=no])])
	if test $tcl_cv_timezone_time = yes ; then
	    AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
	fi
    fi
])

#--------------------------------------------------------------------
# SC_TCL_LINK_LIBS
#
#	Search for the libraries needed to link the Tcl shell.
#	Things like the math library (-lm) and socket stuff (-lsocket vs.
#	-lnsl) or thread library (-lpthread) are dealt with here.
#	Things like the math library (-lm), socket stuff (-lsocket vs.
#	-lnsl), zlib (-lz) and libtommath (-ltommath) or thread library
#	(-lpthread) are dealt with here.
#
# Arguments:
#	None.
#
# Results:
#
#	Sets the following vars:
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396




2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414



2415
2416
2417
2418
2419


2420
2421
2422
2423
2424
2425
2426
2272
2273
2274
2275
2276
2277
2278


2279
2280
2281
2282
2283
2284
2285
2286

2287




2288
2289
2290
2291

2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305


2306
2307
2308
2309
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


2390
2391
2392
2393
2394
2395
2396
2397
2398







-
-
+
+





+
-
+
-
-
-
-
+
+
+

-
+









+
+


-
-



















-

-

+




-
+


-
-
-



-
-
-
+
+
+




-
-
-
+
-

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+





-
-
-
-
+
+
+
+




-
-
-
-
-
-
-
-



-
-
-
+
+
+



-
-
+
+







# Arguments:
#	None
#
# Results:
#
#	Might define the following vars:
#		_ISOC99_SOURCE
#		_LARGEFILE64_SOURCE
#		_LARGEFILE_SOURCE64
#		_FILE_OFFSET_BITS
#		_LARGEFILE64_SOURCE
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_EARLY_FLAG],[
    AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]),
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[$2]], [[$3]])],
	AC_TRY_COMPILE([$2], $3, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,
	    [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[[#define ]$1[ ]m4_default([$4],[1])[
	    AC_TRY_COMPILE([[#define ]$1[ 1
]$2], $3,
		[tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes,
		[tcl_cv_flag_]translit($1,[A-Z],[a-z])=no)))
]$2]], [[$3]])],
	[tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes,
	[tcl_cv_flag_]translit($1,[A-Z],[a-z])=no)]))
    if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then
	AC_DEFINE($1, 1, [Add the ]$1[ flag when building])
	AC_DEFINE($1, m4_default([$4],[1]), [Add the ]$1[ flag when building])
	tcl_flags="$tcl_flags $1"
    fi
])

AC_DEFUN([SC_TCL_EARLY_FLAGS],[
    AC_MSG_CHECKING([for required early compiler flags])
    tcl_flags=""
    SC_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include <stdlib.h>],
	[char *p = (char *)strtoll; char *q = (char *)strtoull;])
    SC_TCL_EARLY_FLAG(_FILE_OFFSET_BITS,[#include <sys/stat.h>],
	[switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; }],64)
    SC_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include <sys/stat.h>],
	[struct stat64 buf; int i = stat64("/", &buf);])
    SC_TCL_EARLY_FLAG(_LARGEFILE_SOURCE64,[#include <sys/stat.h>],
	[char *p = (char *)open64;])
    if test "x${tcl_flags}" = "x" ; then
	AC_MSG_RESULT([none])
    else
	AC_MSG_RESULT([${tcl_flags}])
    fi
])

#--------------------------------------------------------------------
# SC_TCL_64BIT_FLAGS
#
#	Check for what is defined in the way of 64-bit features.
#
# Arguments:
#	None
#
# Results:
#
#	Might define the following vars:
#		TCL_WIDE_INT_IS_LONG
#		TCL_WIDE_INT_TYPE
#		HAVE_STRUCT_DIRENT64, HAVE_DIR64
#		HAVE_STRUCT_STAT64
#		HAVE_TYPE_OFF64_T
#		_TIME_BITS
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_64BIT_FLAGS], [
    AC_MSG_CHECKING([for 64-bit integer type])
    AC_MSG_CHECKING([if 'long' and 'long long' have the same size (64-bit)?])
    AC_CACHE_VAL(tcl_cv_type_64bit,[
	tcl_cv_type_64bit=none
	# See if the compiler knows natively about __int64
	AC_TRY_COMPILE(,[__int64 value = (__int64) 0;],
	    tcl_type_64bit=__int64, tcl_type_64bit="long long")
	# See if we could use long anyway  Note that we substitute in the
	# type that is our current guess for a 64-bit type inside this check
	# program, so it should be modified only carefully...
        AC_TRY_COMPILE(,[switch (0) {
            case 1: case (sizeof(]${tcl_type_64bit}[)==sizeof(long)): ;
        }],tcl_cv_type_64bit=${tcl_type_64bit})])
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[switch (0) {
	    case 1: case (sizeof(long long)==sizeof(long)): ;
	}]])],[tcl_cv_type_64bit="long long"],[])])
    if test "${tcl_cv_type_64bit}" = none ; then
	AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Do 'long' and 'long long' have the same size (64-bit)?])
	AC_MSG_RESULT([yes])
    else
	AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit},
	    [What type should be used to define wide integers?])
	AC_MSG_RESULT([${tcl_cv_type_64bit}])
	AC_MSG_RESULT([no])

	# Now check for auxiliary declarations
	AC_CACHE_CHECK([for 64-bit time_t], tcl_cv_time_t_64,[
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>]],
		[[switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;}]])],
		[tcl_cv_time_t_64=yes],[tcl_cv_time_t_64=no])])
	if test "x${tcl_cv_time_t_64}" = "xno" ; then
	    # Note that _TIME_BITS=64 requires _FILE_OFFSET_BITS=64
	    # which SC_TCL_EARLY_FLAGS has defined if necessary.
	    AC_CACHE_CHECK([if _TIME_BITS=64 enables 64-bit time_t], tcl_cv__time_bits,[
		AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#define _TIME_BITS 64
#include <sys/types.h>]],
		    [[switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;}]])],
		    [tcl_cv__time_bits=yes],[tcl_cv__time_bits=no])])
	    if test "x${tcl_cv__time_bits}" = "xyes" ; then
		AC_DEFINE(_TIME_BITS, 64, [_TIME_BITS=64 enables 64-bit time_t.])
	    fi
	fi

	AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[
	    AC_TRY_COMPILE([#include <sys/types.h>
#include <dirent.h>],[struct dirent64 p;],
		tcl_cv_struct_dirent64=yes,tcl_cv_struct_dirent64=no)])
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
#include <dirent.h>]], [[struct dirent64 p;]])],
		[tcl_cv_struct_dirent64=yes],[tcl_cv_struct_dirent64=no])])
	if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then
	    AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in <sys/types.h>?])
	fi

	AC_CACHE_CHECK([for DIR64], tcl_cv_DIR64,[
	    AC_TRY_COMPILE([#include <sys/types.h>
#include <dirent.h>],[struct dirent64 *p; DIR64 d = opendir64(".");
            p = readdir64(d); rewinddir64(d); closedir64(d);],
		tcl_cv_DIR64=yes,tcl_cv_DIR64=no)])
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
#include <dirent.h>]], [[struct dirent64 *p; DIR64 d = opendir64(".");
	    p = readdir64(d); rewinddir64(d); closedir64(d);]])],
		[tcl_cv_DIR64=yes], [tcl_cv_DIR64=no])])
	if test "x${tcl_cv_DIR64}" = "xyes" ; then
	    AC_DEFINE(HAVE_DIR64, 1, [Is 'DIR64' in <sys/types.h>?])
	fi

	AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[
	    AC_TRY_COMPILE([#include <sys/stat.h>],[struct stat64 p;
],
		tcl_cv_struct_stat64=yes,tcl_cv_struct_stat64=no)])
	if test "x${tcl_cv_struct_stat64}" = "xyes" ; then
	    AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in <sys/stat.h>?])
	fi

	AC_CHECK_FUNCS(open64 lseek64)
	AC_MSG_CHECKING([for off64_t])
	AC_CACHE_VAL(tcl_cv_type_off64_t,[
	    AC_TRY_COMPILE([#include <sys/types.h>],[off64_t offset;
],
		tcl_cv_type_off64_t=yes,tcl_cv_type_off64_t=no)])
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>]], [[off64_t offset;
]])],
		[tcl_cv_type_off64_t=yes], [tcl_cv_type_off64_t=no])])
	dnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the
	dnl functions lseek64 and open64 are defined.
	if test "x${tcl_cv_type_off64_t}" = "xyes" && \
	        test "x${ac_cv_func_lseek64}" = "xyes" && \
	        test "x${ac_cv_func_open64}" = "xyes" ; then
		test "x${ac_cv_func_lseek64}" = "xyes" && \
		test "x${ac_cv_func_open64}" = "xyes" ; then
	    AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?])
	    AC_MSG_RESULT([yes])
	else
	    AC_MSG_RESULT([no])
	fi
    fi
])
2440
2441
2442
2443
2444
2445
2446
2447

2448
2449

2450
2451
2452
2453
2454
2455
2456
2412
2413
2414
2415
2416
2417
2418

2419
2420

2421
2422
2423
2424
2425
2426
2427
2428







-
+

-
+







#	Will define the following vars:
#		TCL_CFGVAL_ENCODING
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_CFG_ENCODING], [
    AC_ARG_WITH(encoding,
	AC_HELP_STRING([--with-encoding],
	AS_HELP_STRING([--with-encoding],
	    [encoding for configuration values (default: utf-8)]),
	with_tcencoding=${withval})
	[with_tcencoding=${withval}])

    if test x"${with_tcencoding}" != x ; then
	AC_DEFINE_UNQUOTED(TCL_CFGVAL_ENCODING,"${with_tcencoding}",
	    [What encoding should be used for embedded configuration info?])
    else
	AC_DEFINE(TCL_CFGVAL_ENCODING,"utf-8",
	    [What encoding should be used for embedded configuration info?])
2473
2474
2475
2476
2477
2478
2479
2480

2481
2482
2483
2484


2485
2486
2487
2488
2489
2490
2491
2445
2446
2447
2448
2449
2450
2451

2452
2453
2454


2455
2456
2457
2458
2459
2460
2461
2462
2463







-
+


-
-
+
+







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

AC_DEFUN([SC_TCL_CHECK_BROKEN_FUNC],[
    AC_CHECK_FUNC($1, tcl_ok=1, tcl_ok=0)
    if test ["$tcl_ok"] = 1; then
	AC_CACHE_CHECK([proper ]$1[ implementation], [tcl_cv_]$1[_unbroken],
	    AC_TRY_RUN([[
	    AC_RUN_IFELSE([AC_LANG_SOURCE([[[
#include <stdlib.h>
#include <string.h>
int main() {]$2[}]],[tcl_cv_]$1[_unbroken]=ok,
		[tcl_cv_]$1[_unbroken]=broken,[tcl_cv_]$1[_unbroken]=unknown))
int main() {]$2[}]]])],[tcl_cv_$1_unbroken=ok],
		[tcl_cv_$1_unbroken=broken],[tcl_cv_$1_unbroken=unknown]))
	if test ["$tcl_cv_]$1[_unbroken"] = "ok"; then
	    tcl_ok=1
	else
	    tcl_ok=0
	fi
    fi
    if test ["$tcl_ok"] = 0; then
2522
2523
2524
2525
2526
2527
2528
2529

2530
2531

2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542

2543
2544
2545
2546
2547
2548
2549

2550
2551

2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562

2563
2564
2565
2566
2567
2568
2569
2494
2495
2496
2497
2498
2499
2500

2501
2502

2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513

2514
2515
2516
2517
2518
2519
2520

2521
2522

2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533

2534
2535
2536
2537
2538
2539
2540
2541







-
+

-
+










-
+






-
+

-
+










-
+








AC_DEFUN([SC_TCL_GETHOSTBYADDR_R_DECL], [AC_CHECK_DECLS(gethostbyaddr_r, [
    tcl_cv_api_gethostbyaddr_r=yes],[tcl_cv_api_gethostbyaddr_r=no],[#include <netdb.h>])
])

AC_DEFUN([SC_TCL_GETHOSTBYADDR_R_TYPE], [AC_CHECK_FUNC(gethostbyaddr_r, [
    AC_CACHE_CHECK([for gethostbyaddr_r with 7 args], tcl_cv_api_gethostbyaddr_r_7, [
    AC_TRY_COMPILE([
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	#include <netdb.h>
    ], [
    ]], [[
	char *addr;
	int length;
	int type;
	struct hostent *result;
	char buffer[2048];
	int buflen = 2048;
	int h_errnop;

	(void) gethostbyaddr_r(addr, length, type, result, buffer, buflen,
			       &h_errnop);
    ], tcl_cv_api_gethostbyaddr_r_7=yes, tcl_cv_api_gethostbyaddr_r_7=no)])
    ]])],[tcl_cv_api_gethostbyaddr_r_7=yes],[tcl_cv_api_gethostbyaddr_r_7=no])])
    tcl_ok=$tcl_cv_api_gethostbyaddr_r_7
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETHOSTBYADDR_R_7, 1,
	    [Define to 1 if gethostbyaddr_r takes 7 args.])
    else
	AC_CACHE_CHECK([for gethostbyaddr_r with 8 args], tcl_cv_api_gethostbyaddr_r_8, [
	AC_TRY_COMPILE([
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	    #include <netdb.h>
	], [
	]], [[
	    char *addr;
	    int length;
	    int type;
	    struct hostent *result, *resultp;
	    char buffer[2048];
	    int buflen = 2048;
	    int h_errnop;

	    (void) gethostbyaddr_r(addr, length, type, result, buffer, buflen,
				   &resultp, &h_errnop);
	], tcl_cv_api_gethostbyaddr_r_8=yes, tcl_cv_api_gethostbyaddr_r_8=no)])
	]])],[tcl_cv_api_gethostbyaddr_r_8=yes],[tcl_cv_api_gethostbyaddr_r_8=no])])
	tcl_ok=$tcl_cv_api_gethostbyaddr_r_8
	if test "$tcl_ok" = yes; then
	    AC_DEFINE(HAVE_GETHOSTBYADDR_R_8, 1,
		[Define to 1 if gethostbyaddr_r takes 8 args.])
	fi
    fi
    if test "$tcl_ok" = yes; then
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
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







-
+

-
+







-
+






-
+

-
+







-
+






-
+

-
+





-
+








AC_DEFUN([SC_TCL_GETHOSTBYNAME_R_DECL], [AC_CHECK_DECLS(gethostbyname_r, [
    tcl_cv_api_gethostbyname_r=yes],[tcl_cv_api_gethostbyname_r=no],[#include <netdb.h>])
])

AC_DEFUN([SC_TCL_GETHOSTBYNAME_R_TYPE], [AC_CHECK_FUNC(gethostbyname_r, [
    AC_CACHE_CHECK([for gethostbyname_r with 6 args], tcl_cv_api_gethostbyname_r_6, [
    AC_TRY_COMPILE([
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	#include <netdb.h>
    ], [
    ]], [[
	char *name;
	struct hostent *he, *res;
	char buffer[2048];
	int buflen = 2048;
	int h_errnop;

	(void) gethostbyname_r(name, he, buffer, buflen, &res, &h_errnop);
    ], tcl_cv_api_gethostbyname_r_6=yes, tcl_cv_api_gethostbyname_r_6=no)])
    ]])],[tcl_cv_api_gethostbyname_r_6=yes],[tcl_cv_api_gethostbyname_r_6=no])])
    tcl_ok=$tcl_cv_api_gethostbyname_r_6
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETHOSTBYNAME_R_6, 1,
	    [Define to 1 if gethostbyname_r takes 6 args.])
    else
	AC_CACHE_CHECK([for gethostbyname_r with 5 args], tcl_cv_api_gethostbyname_r_5, [
	AC_TRY_COMPILE([
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	    #include <netdb.h>
	], [
	]], [[
	    char *name;
	    struct hostent *he;
	    char buffer[2048];
	    int buflen = 2048;
	    int h_errnop;

	    (void) gethostbyname_r(name, he, buffer, buflen, &h_errnop);
	], tcl_cv_api_gethostbyname_r_5=yes, tcl_cv_api_gethostbyname_r_5=no)])
	]])],[tcl_cv_api_gethostbyname_r_5=yes],[tcl_cv_api_gethostbyname_r_5=no])])
	tcl_ok=$tcl_cv_api_gethostbyname_r_5
	if test "$tcl_ok" = yes; then
	    AC_DEFINE(HAVE_GETHOSTBYNAME_R_5, 1,
		[Define to 1 if gethostbyname_r takes 5 args.])
	else
	    AC_CACHE_CHECK([for gethostbyname_r with 3 args], tcl_cv_api_gethostbyname_r_3, [
	    AC_TRY_COMPILE([
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
		#include <netdb.h>
	    ], [
	    ]], [[
		char *name;
		struct hostent *he;
		struct hostent_data data;

		(void) gethostbyname_r(name, he, &data);
	    ], tcl_cv_api_gethostbyname_r_3=yes, tcl_cv_api_gethostbyname_r_3=no)])
	    ]])],[tcl_cv_api_gethostbyname_r_3=yes],[tcl_cv_api_gethostbyname_r_3=no])])
	    tcl_ok=$tcl_cv_api_gethostbyname_r_3
	    if test "$tcl_ok" = yes; then
		AC_DEFINE(HAVE_GETHOSTBYNAME_R_3, 1,
		    [Define to 1 if gethostbyname_r takes 3 args.])
	    fi
	fi
    fi
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
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







-
+


-
+






-
+






-
+


-
+






-
+







#		HAVE_GETPWUID_R_4
#		HAVE_GETPWUID_R_5
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_GETPWUID_R], [AC_CHECK_FUNC(getpwuid_r, [
    AC_CACHE_CHECK([for getpwuid_r with 5 args], tcl_cv_api_getpwuid_r_5, [
    AC_TRY_COMPILE([
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	#include <sys/types.h>
	#include <pwd.h>
    ], [
    ]], [[
	uid_t uid;
	struct passwd pw, *pwp;
	char buf[512];
	int buflen = 512;

	(void) getpwuid_r(uid, &pw, buf, buflen, &pwp);
    ], tcl_cv_api_getpwuid_r_5=yes, tcl_cv_api_getpwuid_r_5=no)])
    ]])],[tcl_cv_api_getpwuid_r_5=yes],[tcl_cv_api_getpwuid_r_5=no])])
    tcl_ok=$tcl_cv_api_getpwuid_r_5
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETPWUID_R_5, 1,
	    [Define to 1 if getpwuid_r takes 5 args.])
    else
	AC_CACHE_CHECK([for getpwuid_r with 4 args], tcl_cv_api_getpwuid_r_4, [
	AC_TRY_COMPILE([
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	    #include <sys/types.h>
	    #include <pwd.h>
	], [
	]], [[
	    uid_t uid;
	    struct passwd pw;
	    char buf[512];
	    int buflen = 512;

	    (void)getpwnam_r(uid, &pw, buf, buflen);
	], tcl_cv_api_getpwuid_r_4=yes, tcl_cv_api_getpwuid_r_4=no)])
	]])],[tcl_cv_api_getpwuid_r_4=yes],[tcl_cv_api_getpwuid_r_4=no])])
	tcl_ok=$tcl_cv_api_getpwuid_r_4
	if test "$tcl_ok" = yes; then
	    AC_DEFINE(HAVE_GETPWUID_R_4, 1,
		[Define to 1 if getpwuid_r takes 4 args.])
	fi
    fi
    if test "$tcl_ok" = yes; then
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
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







-
+


-
+






-
+






-
+


-
+






-
+







#		HAVE_GETPWNAM_R_4
#		HAVE_GETPWNAM_R_5
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_GETPWNAM_R], [AC_CHECK_FUNC(getpwnam_r, [
    AC_CACHE_CHECK([for getpwnam_r with 5 args], tcl_cv_api_getpwnam_r_5, [
    AC_TRY_COMPILE([
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	#include <sys/types.h>
	#include <pwd.h>
    ], [
    ]], [[
	char *name;
	struct passwd pw, *pwp;
	char buf[512];
	int buflen = 512;

	(void) getpwnam_r(name, &pw, buf, buflen, &pwp);
    ], tcl_cv_api_getpwnam_r_5=yes, tcl_cv_api_getpwnam_r_5=no)])
    ]])],[tcl_cv_api_getpwnam_r_5=yes],[tcl_cv_api_getpwnam_r_5=no])])
    tcl_ok=$tcl_cv_api_getpwnam_r_5
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETPWNAM_R_5, 1,
	    [Define to 1 if getpwnam_r takes 5 args.])
    else
	AC_CACHE_CHECK([for getpwnam_r with 4 args], tcl_cv_api_getpwnam_r_4, [
	AC_TRY_COMPILE([
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	    #include <sys/types.h>
	    #include <pwd.h>
	], [
	]], [[
	    char *name;
	    struct passwd pw;
	    char buf[512];
	    int buflen = 512;

	    (void)getpwnam_r(name, &pw, buf, buflen);
	], tcl_cv_api_getpwnam_r_4=yes, tcl_cv_api_getpwnam_r_4=no)])
	]])],[tcl_cv_api_getpwnam_r_4=yes],[tcl_cv_api_getpwnam_r_4=no])])
	tcl_ok=$tcl_cv_api_getpwnam_r_4
	if test "$tcl_ok" = yes; then
	    AC_DEFINE(HAVE_GETPWNAM_R_4, 1,
		[Define to 1 if getpwnam_r takes 4 args.])
	fi
    fi
    if test "$tcl_ok" = yes; then
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
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







-
+


-
+






-
+






-
+


-
+






-
+







#		HAVE_GETGRGID_R_4
#		HAVE_GETGRGID_R_5
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_GETGRGID_R], [AC_CHECK_FUNC(getgrgid_r, [
    AC_CACHE_CHECK([for getgrgid_r with 5 args], tcl_cv_api_getgrgid_r_5, [
    AC_TRY_COMPILE([
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	#include <sys/types.h>
	#include <grp.h>
    ], [
    ]], [[
	gid_t gid;
	struct group gr, *grp;
	char buf[512];
	int buflen = 512;

	(void) getgrgid_r(gid, &gr, buf, buflen, &grp);
    ], tcl_cv_api_getgrgid_r_5=yes, tcl_cv_api_getgrgid_r_5=no)])
    ]])],[tcl_cv_api_getgrgid_r_5=yes],[tcl_cv_api_getgrgid_r_5=no])])
    tcl_ok=$tcl_cv_api_getgrgid_r_5
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETGRGID_R_5, 1,
	    [Define to 1 if getgrgid_r takes 5 args.])
    else
	AC_CACHE_CHECK([for getgrgid_r with 4 args], tcl_cv_api_getgrgid_r_4, [
	AC_TRY_COMPILE([
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	    #include <sys/types.h>
	    #include <grp.h>
	], [
	]], [[
	    gid_t gid;
	    struct group gr;
	    char buf[512];
	    int buflen = 512;

	    (void)getgrgid_r(gid, &gr, buf, buflen);
	], tcl_cv_api_getgrgid_r_4=yes, tcl_cv_api_getgrgid_r_4=no)])
	]])],[tcl_cv_api_getgrgid_r_4=yes],[tcl_cv_api_getgrgid_r_4=no])])
	tcl_ok=$tcl_cv_api_getgrgid_r_4
	if test "$tcl_ok" = yes; then
	    AC_DEFINE(HAVE_GETGRGID_R_4, 1,
		[Define to 1 if getgrgid_r takes 4 args.])
	fi
    fi
    if test "$tcl_ok" = yes; then
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
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







-
+


-
+






-
+






-
+


-
+






-
+







#		HAVE_GETGRNAM_R_4
#		HAVE_GETGRNAM_R_5
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_GETGRNAM_R], [AC_CHECK_FUNC(getgrnam_r, [
    AC_CACHE_CHECK([for getgrnam_r with 5 args], tcl_cv_api_getgrnam_r_5, [
    AC_TRY_COMPILE([
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	#include <sys/types.h>
	#include <grp.h>
    ], [
    ]], [[
	char *name;
	struct group gr, *grp;
	char buf[512];
	int buflen = 512;

	(void) getgrnam_r(name, &gr, buf, buflen, &grp);
    ], tcl_cv_api_getgrnam_r_5=yes, tcl_cv_api_getgrnam_r_5=no)])
    ]])],[tcl_cv_api_getgrnam_r_5=yes],[tcl_cv_api_getgrnam_r_5=no])])
    tcl_ok=$tcl_cv_api_getgrnam_r_5
    if test "$tcl_ok" = yes; then
	AC_DEFINE(HAVE_GETGRNAM_R_5, 1,
	    [Define to 1 if getgrnam_r takes 5 args.])
    else
	AC_CACHE_CHECK([for getgrnam_r with 4 args], tcl_cv_api_getgrnam_r_4, [
	AC_TRY_COMPILE([
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	    #include <sys/types.h>
	    #include <grp.h>
	], [
	]], [[
	    char *name;
	    struct group gr;
	    char buf[512];
	    int buflen = 512;

	    (void)getgrnam_r(name, &gr, buf, buflen);
	], tcl_cv_api_getgrnam_r_4=yes, tcl_cv_api_getgrnam_r_4=no)])
	]])],[tcl_cv_api_getgrnam_r_4=yes],[tcl_cv_api_getgrnam_r_4=no])])
	tcl_ok=$tcl_cv_api_getgrnam_r_4
	if test "$tcl_ok" = yes; then
	    AC_DEFINE(HAVE_GETGRNAM_R_4, 1,
		[Define to 1 if getgrnam_r takes 4 args.])
	fi
    fi
    if test "$tcl_ok" = yes; then
2914
2915
2916
2917
2918
2919
2920
2921

2922
2923
2924
2925
2926
2927
2928
2886
2887
2888
2889
2890
2891
2892

2893
2894
2895
2896
2897
2898
2899
2900







-
+







#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
]])
if test "x$NEED_FAKE_RFC2553" = "x1"; then
   AC_DEFINE([NEED_FAKE_RFC2553], 1,
        [Use compat implementation of getaddrinfo() and friends])
	[Use compat implementation of getaddrinfo() and friends])
   AC_LIBOBJ([fake-rfc2553])
   AC_CHECK_FUNC(strlcpy)
fi
])

#------------------------------------------------------------------------
# SC_CC_FOR_BUILD
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
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







-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

















+
-
+






+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

+









#		EXEEXT_FOR_BUILD
#------------------------------------------------------------------------

dnl Get a default for CC_FOR_BUILD to put into Makefile.
AC_DEFUN([AX_CC_FOR_BUILD],[# Put a plausible default for CC_FOR_BUILD in Makefile.
    if test -z "$CC_FOR_BUILD"; then
      if test "x$cross_compiling" = "xno"; then
        CC_FOR_BUILD='$(CC)'
	CC_FOR_BUILD='$(CC)'
      else
        AC_MSG_CHECKING([for gcc])
        AC_CACHE_VAL(ac_cv_path_cc, [
            search_path=`echo ${PATH} | sed -e 's/:/ /g'`
            for dir in $search_path ; do
                for j in `ls -r $dir/gcc 2> /dev/null` \
                        `ls -r $dir/gcc 2> /dev/null` ; do
                    if test x"$ac_cv_path_cc" = x ; then
                        if test -f "$j" ; then
                            ac_cv_path_cc=$j
                            break
                        fi
                    fi
                done
            done
        ])
	AC_MSG_CHECKING([for gcc])
	AC_CACHE_VAL(ac_cv_path_cc, [
	    search_path=`echo ${PATH} | sed -e 's/:/ /g'`
	    for dir in $search_path ; do
		for j in `ls -r $dir/gcc 2> /dev/null` \
			`ls -r $dir/gcc 2> /dev/null` ; do
		    if test x"$ac_cv_path_cc" = x ; then
			if test -f "$j" ; then
			    ac_cv_path_cc=$j
			    break
			fi
		    fi
		done
	    done
	])
      fi
    fi
    AC_SUBST(CC_FOR_BUILD)
    # Also set EXEEXT_FOR_BUILD.
    if test "x$cross_compiling" = "xno"; then
      EXEEXT_FOR_BUILD='$(EXEEXT)'
      OBJEXT_FOR_BUILD='$(OBJEXT)'
    else
      OBJEXT_FOR_BUILD='.no'
      AC_CACHE_CHECK([for build system executable suffix], bfd_cv_build_exeext,
        [rm -f conftest*
         echo 'int main () { return 0; }' > conftest.c
         bfd_cv_build_exeext=
         ${CC_FOR_BUILD} -o conftest conftest.c 1>&5 2>&5
         for file in conftest.*; do
           case $file in
           *.c | *.o | *.obj | *.ilk | *.pdb) ;;
           *) bfd_cv_build_exeext=`echo $file | sed -e s/conftest//` ;;
           esac
         done
         rm -f conftest*
         test x"${bfd_cv_build_exeext}" = x && bfd_cv_build_exeext=no])
	[rm -f conftest*
	 echo 'int main () { return 0; }' > conftest.c
	 bfd_cv_build_exeext=
	 ${CC_FOR_BUILD} -o conftest conftest.c 1>&5 2>&5
	 for file in conftest.*; do
	   case $file in
	   *.c | *.o | *.obj | *.ilk | *.pdb) ;;
	   *) bfd_cv_build_exeext=`echo $file | sed -e s/conftest//` ;;
	   esac
	 done
	 rm -f conftest*
	 test x"${bfd_cv_build_exeext}" = x && bfd_cv_build_exeext=no])
      EXEEXT_FOR_BUILD=""
      test x"${bfd_cv_build_exeext}" != xno && EXEEXT_FOR_BUILD=${bfd_cv_build_exeext}
    fi
    AC_SUBST(EXEEXT_FOR_BUILD)])dnl
    AC_SUBST(OBJEXT_FOR_BUILD)])dnl
])


#------------------------------------------------------------------------
# SC_ZIPFS_SUPPORT
#	Locate a zip encoder installed on the system path, or none.
#
# Arguments:
#	none
#
# Results:
#	Substitutes the following vars:
#       MACHER_PROG
#		ZIP_PROG
#       ZIP_PROG
#       ZIP_PROG_OPTIONS
#       ZIP_PROG_VFSSEARCH
#       ZIP_INSTALL_OBJS
#------------------------------------------------------------------------

AC_DEFUN([SC_ZIPFS_SUPPORT], [
    MACHER_PROG=""
    ZIP_PROG=""
    ZIP_PROG_OPTIONS=""
    ZIP_PROG_VFSSEARCH=""
    ZIP_INSTALL_OBJS=""

    AC_MSG_CHECKING([for macher])
    AC_CACHE_VAL(ac_cv_path_macher, [
    search_path=`echo ${PATH} | sed -e 's/:/ /g'`
    for dir in $search_path ; do
	for j in `ls -r $dir/macher 2> /dev/null` \
	    `ls -r $dir/macher 2> /dev/null` ; do
	if test x"$ac_cv_path_macher" = x ; then
	    if test -f "$j" ; then
	    ac_cv_path_macher=$j
	    break
	    fi
	fi
	done
    done
    ])
    if test -f "$ac_cv_path_macher" ; then
	MACHER_PROG="$ac_cv_path_macher"
	AC_MSG_RESULT([$MACHER_PROG])
	AC_MSG_RESULT([Found macher in environment])
    fi
    AC_MSG_CHECKING([for zip])
    AC_CACHE_VAL(ac_cv_path_zip, [
    search_path=`echo ${PATH} | sed -e 's/:/ /g'`
    for dir in $search_path ; do
        for j in `ls -r $dir/zip 2> /dev/null` \
            `ls -r $dir/zip 2> /dev/null` ; do
        if test x"$ac_cv_path_zip" = x ; then
            if test -f "$j" ; then
            ac_cv_path_zip=$j
            break
            fi
        fi
        done
	for j in `ls -r $dir/zip 2> /dev/null` \
	    `ls -r $dir/zip 2> /dev/null` ; do
	if test x"$ac_cv_path_zip" = x ; then
	    if test -f "$j" ; then
	    ac_cv_path_zip=$j
	    break
	    fi
	fi
	done
    done
    ])
    if test -f "$ac_cv_path_zip" ; then
        ZIP_PROG="$ac_cv_path_zip"
        AC_MSG_RESULT([$ZIP_PROG])
        ZIP_PROG_OPTIONS="-rq"
        ZIP_PROG_VFSSEARCH="*"
        AC_MSG_RESULT([Found INFO Zip in environment])
        # Use standard arguments for zip
	ZIP_PROG="$ac_cv_path_zip"
	AC_MSG_RESULT([$ZIP_PROG])
	ZIP_PROG_OPTIONS="-rq"
	ZIP_PROG_VFSSEARCH="*"
	AC_MSG_RESULT([Found INFO Zip in environment])
	# Use standard arguments for zip
    else
        # It is not an error if an installed version of Zip can't be located.
        # We can use the locally distributed minizip instead
        ZIP_PROG="./minizip${EXEEXT_FOR_BUILD}"
        ZIP_PROG_OPTIONS="-o -r"
        ZIP_PROG_VFSSEARCH="*"
        ZIP_INSTALL_OBJS="minizip${EXEEXT_FOR_BUILD}"
        AC_MSG_RESULT([No zip found on PATH. Building minizip])
	# It is not an error if an installed version of Zip can't be located.
	# We can use the locally distributed minizip instead
	ZIP_PROG="./minizip${EXEEXT_FOR_BUILD}"
	ZIP_PROG_OPTIONS="-o -r"
	ZIP_PROG_VFSSEARCH="*"
	ZIP_INSTALL_OBJS="minizip${EXEEXT_FOR_BUILD}"
	AC_MSG_RESULT([No zip found on PATH. Building minizip])
    fi
    AC_SUBST(MACHER_PROG)
    AC_SUBST(ZIP_PROG)
    AC_SUBST(ZIP_PROG_OPTIONS)
    AC_SUBST(ZIP_PROG_VFSSEARCH)
    AC_SUBST(ZIP_INSTALL_OBJS)
])

# Local Variables:
# mode: autoconf
# End:

Changes to unix/tcl.pc.in.

1
2
3
4
5
6
7
8
9
10
11
12

13
14

15
16
17

1
2
3
4
5
6
7

8
9
10

11
12

13
14
15

16







-



-
+

-
+


-
+
# tcl pkg-config source file

prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
libfile=@TCL_LIB_FILE@
zipfile=@TCL_ZIP_FILE@

Name: Tool Command Language
Description: Tcl is a powerful, easy-to-learn dynamic programming language, suitable for a wide range of uses.
URL: http://www.tcl.tk/
URL: https://www.tcl-lang.org/
Version: @TCL_VERSION@@TCL_PATCH_LEVEL@
Requires.private: zlib >= 1.2.3, libtommath >= 1.2.0
Requires.private: @TCL_PC_REQUIRES_PRIVATE@ zlib >= 1.2.3
Libs: -L${libdir} @TCL_LIB_FLAG@ @TCL_STUB_LIB_FLAG@
Libs.private: @TCL_LIBS@
Cflags: -I${includedir}
Cflags: -I${includedir} @TCL_PC_CFLAGS@

Changes to unix/tcl.spec.

1
2
3
4
5
6
7

8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6

7
8
9
10
11

12
13
14
15
16
17
18
19






-
+




-
+







# 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.0a1
Version:       9.0.1
Release:       2
License:       BSD
Group:         Development/Languages
Source:        http://prdownloads.sourceforge.net/tcl/tcl%{version}-src.tar.gz
URL:           http://www.tcl.tk/
URL:           https://www.tcl-lang.org/
Buildroot:     /var/tmp/%{name}%{version}

%description
The Tcl (Tool Command Language) provides a powerful platform for
creating integration applications that tie together diverse
applications, protocols, devices, and frameworks.  When paired with
the Tk toolkit, Tcl provides the fastest and most powerful way to

Changes to unix/tclAppInit.c.

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
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







-
-

+
+
+
+
+
+
+
+
+


-
-
+
+




-
+







 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#undef BUILD_tcl
#undef STATIC_BUILD
#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
extern Tcl_PackageInitProc Tcltest_Init;
extern Tcl_PackageInitProc Tcltest_SafeInit;
extern Tcl_LibraryInitProc Tcltest_Init;
extern Tcl_LibraryInitProc Tcltest_SafeInit;
#endif /* TCL_TEST */

#ifdef TCL_XT_TEST
extern void                XtToolkitInitialize(void);
extern Tcl_PackageInitProc Tclxttest_Init;
extern Tcl_LibraryInitProc Tclxttest_Init;
#endif /* TCL_XT_TEST */

/*
 * The following #if block allows you to change the AppInit function by using
 * a #define of TCL_LOCAL_APPINIT instead of rewriting this entire file. The
 * #if checks for that #define and uses Tcl_AppInit if it does not exist.
 */
75
76
77
78
79
80
81
82


83
84
85
86
87
88
89
82
83
84
85
86
87
88

89
90
91
92
93
94
95
96
97







-
+
+







{
#ifdef TCL_XT_TEST
    XtToolkitInitialize();
#endif

#ifdef TCL_LOCAL_MAIN_HOOK
    TCL_LOCAL_MAIN_HOOK(&argc, &argv);
#else
#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. */
}

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
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







-
+













-
+















-
+









-

-
-
+

-
-
+


+
+
+










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

int
Tcl_AppInit(
    Tcl_Interp *interp)		/* Interpreter for application. */
{
    if ((Tcl_Init)(interp) == TCL_ERROR) {
    if (Tcl_Init(interp) == TCL_ERROR) {
	return TCL_ERROR;
    }

#ifdef TCL_XT_TEST
    if (Tclxttest_Init(interp) == TCL_ERROR) {
	return TCL_ERROR;
    }
#endif

#ifdef TCL_TEST
    if (Tcltest_Init(interp) == TCL_ERROR) {
	return TCL_ERROR;
    }
    Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init, Tcltest_SafeInit);
    Tcl_StaticLibrary(interp, "Tcltest", Tcltest_Init, Tcltest_SafeInit);
#endif /* TCL_TEST */

    /*
     * Call the init procedures for included packages. Each call should look
     * like this:
     *
     * if (Mod_Init(interp) == TCL_ERROR) {
     *     return TCL_ERROR;
     * }
     *
     * where "Mod" is the name of the module. (Dynamically-loadable packages
     * should have the same entry-point name.)
     */

    /*
     * Call Tcl_CreateCommand for application-specific commands, if they
     * Call Tcl_CreateObjCommand for application-specific commands, if they
     * weren't already created by the init procedures called above.
     */

    /*
     * Specify a user-specific startup file to invoke if the application is
     * run interactively. Typically the startup file is "~/.apprc" where "app"
     * is the name of the application. If this line is deleted then no
     * user-specific startup file will be run under any conditions.
     */

#ifdef DJGPP
    (Tcl_ObjSetVar2)(interp, Tcl_NewStringObj("tcl_rcFileName", -1), NULL,
	    Tcl_NewStringObj("~/tclsh.rc", -1), TCL_GLOBAL_ONLY);
#define INITFILENAME "tclshrc.tcl"
#else
    (Tcl_ObjSetVar2)(interp, Tcl_NewStringObj("tcl_rcFileName", -1), NULL,
	    Tcl_NewStringObj("~/.tclshrc", -1), TCL_GLOBAL_ONLY);
#define INITFILENAME ".tclshrc"
#endif

    (void) Tcl_EvalEx(interp,
	    "set tcl_rcFileName [file tildeexpand ~/" INITFILENAME "]",
	    -1, TCL_EVAL_GLOBAL);
    return TCL_OK;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to unix/tclConfig.h.in.

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
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
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
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






-
-
-






-
+





-
+


-
+


-
+











-
+



-
+



-
+









-
+





-
+


-
+


-
+


-
+







/* ../unix/tclConfig.h.in.  Generated from configure.ac by autoheader.  */


    #ifndef _TCLCONFIG
    #define _TCLCONFIG

/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD

/* Is gettimeofday() actually declared in <sys/time.h>? */
#undef GETTOD_NOT_DECLARED

/* Define to 1 if you have the <AvailabilityMacros.h> header file. */
#undef HAVE_AVAILABILITYMACROS_H

/* Define to 1 if the system has the type `blkcnt_t'. */
/* Define to 1 if the system has the type 'blkcnt_t'. */
#undef HAVE_BLKCNT_T

/* Defined when compiler supports casting to union type. */
#undef HAVE_CAST_TO_UNION

/* Define to 1 if you have the `cfmakeraw' function. */
/* Define to 1 if you have the 'cfmakeraw' function. */
#undef HAVE_CFMAKERAW

/* Define to 1 if you have the `chflags' function. */
/* Define to 1 if you have the 'chflags' function. */
#undef HAVE_CHFLAGS

/* Define to 1 if you have the `copyfile' function. */
/* Define to 1 if you have the 'copyfile' function. */
#undef HAVE_COPYFILE

/* Define to 1 if you have the <copyfile.h> header file. */
#undef HAVE_COPYFILE_H

/* Do we have access to Darwin CoreFoundation.framework? */
#undef HAVE_COREFOUNDATION

/* Is the cpuid instruction usable? */
#undef HAVE_CPUID

/* Define to 1 if you have the declaration of `gethostbyaddr_r', and to 0 if
/* Define to 1 if you have the declaration of 'gethostbyaddr_r', and to 0 if
   you don't. */
#undef HAVE_DECL_GETHOSTBYADDR_R

/* Define to 1 if you have the declaration of `gethostbyname_r', and to 0 if
/* Define to 1 if you have the declaration of 'gethostbyname_r', and to 0 if
   you don't. */
#undef HAVE_DECL_GETHOSTBYNAME_R

/* Define to 1 if you have the declaration of `PTHREAD_MUTEX_RECURSIVE', and
/* Define to 1 if you have the declaration of 'PTHREAD_MUTEX_RECURSIVE', and
   to 0 if you don't. */
#undef HAVE_DECL_PTHREAD_MUTEX_RECURSIVE

/* Is 'DIR64' in <sys/types.h>? */
#undef HAVE_DIR64

/* Is eventfd(2) supported? */
#undef HAVE_EVENTFD

/* Define to 1 if you have the `freeaddrinfo' function. */
/* Define to 1 if you have the 'freeaddrinfo' function. */
#undef HAVE_FREEADDRINFO

/* Do we have fts functions? */
#undef HAVE_FTS

/* Define to 1 if you have the `gai_strerror' function. */
/* Define to 1 if you have the 'gai_strerror' function. */
#undef HAVE_GAI_STRERROR

/* Define to 1 if you have the `getaddrinfo' function. */
/* Define to 1 if you have the 'getaddrinfo' function. */
#undef HAVE_GETADDRINFO

/* Define to 1 if you have the `getattrlist' function. */
/* Define to 1 if you have the 'getattrlist' function. */
#undef HAVE_GETATTRLIST

/* Define to 1 if you have the `getcwd' function. */
/* Define to 1 if you have the 'getcwd' function. */
#undef HAVE_GETCWD

/* Define to 1 if getgrgid_r is available. */
#undef HAVE_GETGRGID_R

/* Define to 1 if getgrgid_r takes 4 args. */
#undef HAVE_GETGRGID_R_4
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
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







-
+




















-
+





-
+











-
+


-
+


-
-
-
-
+


-
+


-
-
-









-
+


-
-
+
+

+
+
+
-
-
+
+
+
+
+
+
+
+

-
+


-
+













+
+
+










-
-
-
-
+





-
+


-
+


-
+


-
-
+
+

-
-
+
+

-
-
+
+








/* Define to 1 if gethostbyname_r takes 5 args. */
#undef HAVE_GETHOSTBYNAME_R_5

/* Define to 1 if gethostbyname_r takes 6 args. */
#undef HAVE_GETHOSTBYNAME_R_6

/* Define to 1 if you have the `getnameinfo' function. */
/* Define to 1 if you have the 'getnameinfo' function. */
#undef HAVE_GETNAMEINFO

/* Define to 1 if getpwnam_r is available. */
#undef HAVE_GETPWNAM_R

/* Define to 1 if getpwnam_r takes 4 args. */
#undef HAVE_GETPWNAM_R_4

/* Define to 1 if getpwnam_r takes 5 args. */
#undef HAVE_GETPWNAM_R_5

/* Define to 1 if getpwuid_r is available. */
#undef HAVE_GETPWUID_R

/* Define to 1 if getpwuid_r takes 4 args. */
#undef HAVE_GETPWUID_R_4

/* Define to 1 if getpwuid_r takes 5 args. */
#undef HAVE_GETPWUID_R_5

/* Define to 1 if you have the `gmtime_r' function. */
/* Define to 1 if you have the 'gmtime_r' function. */
#undef HAVE_GMTIME_R

/* Compiler support for module scope symbols */
#undef HAVE_HIDDEN

/* Do we have the intptr_t type? */
/* Define to 1 if the system has the type 'intptr_t'. */
#undef HAVE_INTPTR_T

/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H

/* Do we have nl_langinfo()? */
#undef HAVE_LANGINFO

/* Define to 1 if you have the <libkern/OSAtomic.h> header file. */
#undef HAVE_LIBKERN_OSATOMIC_H

/* Define to 1 if you have the `localtime_r' function. */
/* Define to 1 if you have the 'localtime_r' function. */
#undef HAVE_LOCALTIME_R

/* Define to 1 if you have the `lseek64' function. */
/* Define to 1 if you have the 'lseek64' function. */
#undef HAVE_LSEEK64

/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H

/* Define to 1 if you have the `mkstemp' function. */
/* Define to 1 if you have the 'mkstemp' function. */
#undef HAVE_MKSTEMP

/* Define to 1 if you have the `mkstemps' function. */
/* Define to 1 if you have the 'mkstemps' function. */
#undef HAVE_MKSTEMPS

/* Define to 1 if you have the `mktime' function. */
#undef HAVE_MKTIME

/* Do we have MT-safe gethostbyaddr() ? */
#undef HAVE_MTSAFE_GETHOSTBYADDR

/* Do we have MT-safe gethostbyname() ? */
#undef HAVE_MTSAFE_GETHOSTBYNAME

/* Do we have <net/errno.h>? */
#undef HAVE_NET_ERRNO_H

/* Define to 1 if you have the `open64' function. */
/* Define to 1 if you have the 'open64' function. */
#undef HAVE_OPEN64

/* Define to 1 if you have the `opendir' function. */
#undef HAVE_OPENDIR
/* Define to 1 if you have the 'OSSpinLockLock' function. */
#undef HAVE_OSSPINLOCKLOCK

/* Define to 1 if you have the 'posix_spawnattr_setflags' function. */
#undef HAVE_POSIX_SPAWNATTR_SETFLAGS

/* Define to 1 if you have the `OSSpinLockLock' function. */
#undef HAVE_OSSPINLOCKLOCK
/* Define to 1 if you have the 'posix_spawnp' function. */
#undef HAVE_POSIX_SPAWNP

/* Define to 1 if you have the 'posix_spawn_file_actions_adddup2' function. */
#undef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2

/* Should we use pselect()? */
#undef HAVE_PSELECT

/* Define to 1 if you have the `pthread_atfork' function. */
/* Define to 1 if you have the 'pthread_atfork' function. */
#undef HAVE_PTHREAD_ATFORK

/* Define to 1 if you have the `pthread_attr_setstacksize' function. */
/* Define to 1 if you have the 'pthread_attr_setstacksize' function. */
#undef HAVE_PTHREAD_ATTR_SETSTACKSIZE

/* Does putenv() copy strings or incorporate them by reference? */
#undef HAVE_PUTENV_THAT_COPIES

/* Are characters signed? */
#undef HAVE_SIGNED_CHAR

/* Do we have <stdbool.h>? */
#undef HAVE_STDBOOL_H

/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H

/* Define to 1 if you have the <stdio.h> header file. */
#undef HAVE_STDIO_H

/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H

/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H

/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H

/* Define to 1 if you have the `strtol' function. */
#undef HAVE_STRTOL

/* Define to 1 if the system has the type `struct addrinfo'. */
/* Define to 1 if the system has the type 'struct addrinfo'. */
#undef HAVE_STRUCT_ADDRINFO

/* Is 'struct dirent64' in <sys/types.h>? */
#undef HAVE_STRUCT_DIRENT64

/* Define to 1 if the system has the type `struct in6_addr'. */
/* Define to 1 if the system has the type 'struct in6_addr'. */
#undef HAVE_STRUCT_IN6_ADDR

/* Define to 1 if the system has the type `struct sockaddr_in6'. */
/* Define to 1 if the system has the type 'struct sockaddr_in6'. */
#undef HAVE_STRUCT_SOCKADDR_IN6

/* Define to 1 if the system has the type `struct sockaddr_storage'. */
/* Define to 1 if the system has the type 'struct sockaddr_storage'. */
#undef HAVE_STRUCT_SOCKADDR_STORAGE

/* Is 'struct stat64' in <sys/stat.h>? */
#undef HAVE_STRUCT_STAT64
/* Define to 1 if 'st_blksize' is a member of 'struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLKSIZE

/* Define to 1 if `st_blksize' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLKSIZE
/* Define to 1 if 'st_blocks' is a member of 'struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLOCKS

/* Define to 1 if `st_blocks' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLOCKS
/* Define to 1 if 'st_rdev' is a member of 'struct stat'. */
#undef HAVE_STRUCT_STAT_ST_RDEV

/* Define to 1 if you have the <sys/epoll.h> header file. */
#undef HAVE_SYS_EPOLL_H

/* Define to 1 if you have the <sys/eventfd.h> header file. */
#undef HAVE_SYS_EVENTFD_H

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
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







-
+





-
+
+
+
+





-
-
-








/* Should we use the tm_tzadj field of struct tm? */
#undef HAVE_TM_TZADJ

/* Is off64_t in <sys/types.h>? */
#undef HAVE_TYPE_OFF64_T

/* Do we have the uintptr_t type? */
/* Define to 1 if the system has the type 'uintptr_t'. */
#undef HAVE_UINTPTR_T

/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H

/* Define to 1 if you have the `waitpid' function. */
/* Define to 1 if you have the 'vfork' function. */
#undef HAVE_VFORK

/* Define to 1 if you have the 'waitpid' function. */
#undef HAVE_WAITPID

/* Is weak import available? */
#undef HAVE_WEAK_IMPORT

/* Is there an installed zlib? */
#undef HAVE_ZLIB

/* Is this a Mac I see before me? */
#undef MAC_OSX_TCL

/* No Compiler support for module scope symbols */
#undef MODULE_SCOPE

/* Default libtommath precision. */
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


366
367
368


369
370
371
372
373
374
375
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
366
367
368
369







-
-
-





+
+
+










-
-
-
-
-
+
+




-
-
-



-
-
+
+

-
-
+
+








/* Is kqueue(2) supported? */
#undef NOTIFIER_KQUEUE

/* Is Darwin CoreFoundation unavailable for 64-bit? */
#undef NO_COREFOUNDATION_64

/* Do we have <dirent.h>? */
#undef NO_DIRENT_H

/* Do we have <dlfcn.h>? */
#undef NO_DLFCN_H

/* Do we have fd_set? */
#undef NO_FD_SET

/* Do we have fork() */
#undef NO_FORK

/* Do we have fstatfs()? */
#undef NO_FSTATFS

/* Do we have gettimeofday()? */
#undef NO_GETTOD

/* Do we have getwd() */
#undef NO_GETWD

/* Do we have a usable 'isnan'? */
#undef NO_ISNAN

/* Do we have memmove()? */
#undef NO_MEMMOVE
/* Do we have mknod() */
#undef NO_MKNOD

/* Do we have realpath() */
#undef NO_REALPATH

/* Do we have <stdlib.h>? */
#undef NO_STDLIB_H

/* Do we have strerror() */
#undef NO_STRERROR

/* Do we have <string.h>? */
#undef NO_STRING_H
/* Do we have <sys/wait.h>? */
#undef NO_SYS_WAIT_H

/* Do we have <sys/wait.h>? */
#undef NO_SYS_WAIT_H
/* Do we have tcdrain() */
#undef NO_TCDRAIN

/* Do we have uname() */
#undef NO_UNAME

/* Do we have a usable 'union wait'? */
#undef NO_UNION_WAIT

393
394
395
396
397
398
399
400



401
402
403
404
405
406
407
387
388
389
390
391
392
393

394
395
396
397
398
399
400
401
402
403







-
+
+
+








/* Define to the version of this package. */
#undef PACKAGE_VERSION

/* Is this a static build? */
#undef STATIC_BUILD

/* Define to 1 if you have the ANSI C header files. */
/* Define to 1 if all of the C89 standard headers exist (not just the ones
   required in a freestanding environment). This macro is provided for
   backward compatibility; new code need not use it. */
#undef STDC_HEADERS

/* What encoding should be used for embedded configuration info? */
#undef TCL_CFGVAL_ENCODING

/* Is this a 64-bit build? */
#undef TCL_CFG_DO64BIT
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
467
468
469
470
471
472
473
474
475
476
477
478
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
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
467
468
469
470
471
472
473
474
475
476



477
478
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







-
-
-



-
-
+
+




-
-
-






-
-
-

















+
+
+







-
-
-











+
+
+







-
+
+




-
+


-
+





-
-
-
-
+


-
+


-
+





-
+


-
-
-




-
-
+
+
+


/* Does this platform have wide high-resolution clicks? */
#undef TCL_WIDE_CLICKS

/* Do 'long' and 'long long' have the same size (64-bit)? */
#undef TCL_WIDE_INT_IS_LONG

/* What type should be used to define wide integers? */
#undef TCL_WIDE_INT_TYPE

/* Tcl with external libtommath */
#undef TCL_WITH_EXTERNAL_TOMMATH

/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Tcl with internal zlib */
#undef TCL_WITH_INTERNAL_ZLIB

/* Is getcwd Posix-compliant? */
#undef USEGETWD

/* May we include <dirent2.h>? */
#undef USE_DIRENT2_H

/* Are we building with DTrace support? */
#undef USE_DTRACE

/* Should we use FIONBIO? */
#undef USE_FIONBIO

/* Should we use vfork() instead of fork()? */
#undef USE_VFORK

/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
   significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
#  define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
#  undef WORDS_BIGENDIAN
# endif
#endif

/* Are we building with zipfs enabled? */
#undef ZIPFS_BUILD

/* Are Darwin SUSv3 extensions available? */
#undef _DARWIN_C_SOURCE

/* Add the _FILE_OFFSET_BITS flag when building */
#undef _FILE_OFFSET_BITS

/* Add the _ISOC99_SOURCE flag when building */
#undef _ISOC99_SOURCE

/* Add the _LARGEFILE64_SOURCE flag when building */
#undef _LARGEFILE64_SOURCE

/* Add the _LARGEFILE_SOURCE64 flag when building */
#undef _LARGEFILE_SOURCE64

/* # needed in sys/socket.h Should OS/390 do the right thing with sockets? */
#undef _OE_SOCKETS

/* Do we really want to follow the standard? Yes we do! */
#undef _POSIX_PTHREAD_SEMANTICS

/* Do we want the reentrant OS API? */
#undef _REENTRANT

/* Do we want the thread-safe OS API? */
#undef _THREAD_SAFE

/* _TIME_BITS=64 enables 64-bit time_t. */
#undef _TIME_BITS

/* Do we want to use the XOPEN network library? */
#undef _XOPEN_SOURCE

/* Do we want to use the XOPEN network library? */
#undef _XOPEN_SOURCE_EXTENDED

/* Define to 1 if type `char' is unsigned and you are not using gcc.  */
/* Define to 1 if type 'char' is unsigned and your compiler does not
   predefine this macro.  */
#ifndef __CHAR_UNSIGNED__
# undef __CHAR_UNSIGNED__
#endif

/* Define to `int' if <sys/types.h> doesn't define. */
/* Define as 'int' if <sys/types.h> doesn't define. */
#undef gid_t

/* Define to `__inline__' or `__inline' if that's what the C compiler
/* Define to '__inline__' or '__inline' if that's what the C compiler
   calls it, or to nothing if 'inline' is not supported under any name.  */
#ifndef __cplusplus
#undef inline
#endif

/* Signed integer type wide enough to hold a pointer. */
#undef intptr_t

/* Define to `int' if <sys/types.h> does not define. */
/* Define to 'int' if <sys/types.h> does not define. */
#undef mode_t

/* Define to `int' if <sys/types.h> does not define. */
/* Define as a signed integer type capable of holding a process identifier. */
#undef pid_t

/* Define to `unsigned int' if <sys/types.h> does not define. */
/* Define as 'unsigned int' if <stddef.h> doesn't define. */
#undef size_t

/* Define as int if socklen_t is not available */
#undef socklen_t

/* Define to `int' if <sys/types.h> doesn't define. */
/* Define as 'int' if <sys/types.h> doesn't define. */
#undef uid_t

/* Unsigned integer type wide enough to hold a pointer. */
#undef uintptr_t


    /* Undef unused package specific autoheader defines so that we can
     * include both tclConfig.h and tkConfig.h at the same time: */
    /* override */ #undef PACKAGE_NAME
    /* override */ #undef PACKAGE_STRING
    /* override */ #undef PACKAGE_TARNAME
    /* override */ #undef PACKAGE_TARNAME
    /* override */ #undef PACKAGE_VERSION
    /* override */ #undef PACKAGE_STRING
    #endif /* _TCLCONFIG */

Changes to unix/tclEpollNotfy.c.

1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16







-
-
+
+







/*
 * tclEpollNotfy.c --
 *
 *	This file contains the implementation of the epoll()-based
 *	Linux-specific notifier, which is the lowest-level part of the Tcl
 *	event loop. This file works together with generic/tclNotify.c.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 2016 Lucio Andrés Illanes Albornoz <l.illanes@gmx.de>
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2016 Lucio Andrés Illanes Albornoz <l.illanes@gmx.de>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#ifndef HAVE_COREFOUNDATION	/* Darwin/Mac OS X CoreFoundation notifier is
38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
38
39
40
41
42
43
44

45
46
47
48
49
50
51
52







-
+







    int mask;			/* Mask of desired events: TCL_READABLE,
				 * etc. */
    int readyMask;		/* Mask of events that have been seen since
				 * the last time file handlers were invoked
				 * for this file. */
    Tcl_FileProc *proc;		/* Function to call, in the style of
				 * Tcl_CreateFileHandler. */
    ClientData clientData;	/* Argument to pass to proc. */
    void *clientData;	/* Argument to pass to proc. */
    struct FileHandler *nextPtr;/* Next in list of all files we care about. */
    LIST_ENTRY(FileHandler) readyNode;
				/* Next/previous in list of FileHandlers asso-
				 * ciated with regular files (S_IFREG) that are
				 * ready for I/O. */
    struct PlatformEventData *pedPtr;
				/* Pointer to PlatformEventData associating this
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
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







-
+













+










-




-
+

-
+







-
+







-
-
+
+




-
-
+
+

-
-
-
-
+

-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







				/* Pointer to head of file handler list. */
    struct PlatformReadyFileHandlerList firstReadyFileHandlerPtr;
				/* Pointer to head of list of FileHandlers
				 * associated with regular files (S_IFREG)
				 * that are ready for I/O. */
    pthread_mutex_t notifierMutex;
				/* Mutex protecting notifier termination in
				 * PlatformEventsFinalize. */
				 * TclpFinalizeNotifier. */
#ifdef HAVE_EVENTFD
    int triggerEventFd;		/* eventfd(2) used by other threads to wake
				 * up this thread for inter-thread IPC. */
#else
    int triggerPipe[2];		/* pipe(2) used by other threads to wake
				 * up this thread for inter-thread IPC. */
#endif /* HAVE_EVENTFD */
    int eventsFd;		/* epoll(7) file descriptor used to wait for
				 * fds */
    struct epoll_event *readyEvents;
				/* Pointer to at most maxReadyEvents events
				 * returned by epoll_wait(2). */
    size_t maxReadyEvents;	/* Count of epoll_events in readyEvents. */
    int asyncPending;		/* True when signal triggered thread. */
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;

/*
 * Forward declarations.
 */

static void		PlatformEventsControl(FileHandler *filePtr,
			    ThreadSpecificData *tsdPtr, int op, int isNew);
static void		PlatformEventsFinalize(void);
static void		PlatformEventsInit(void);
static int		PlatformEventsTranslate(struct epoll_event *event);
static int		PlatformEventsWait(struct epoll_event *events,
			    size_t numEvents, struct timeval *timePtr);


/*
 * Incorporate the base notifier API.
 * Incorporate the base notifier implementation.
 */

#include "tclUnixNotfy.c"

/*
 *----------------------------------------------------------------------
 *
 * Tcl_InitNotifier --
 * TclpInitNotifier --
 *
 *	Initializes the platform specific notifier state.
 *
 * Results:
 *	Returns a handle to the notifier state for this thread.
 *
 * Side effects:
 *	If no initNotifierProc notifier hook exists, PlatformEventsInit
 *	is called.
 *	If no initNotifierProc notifier hook exists, PlatformEventsInit is
 *	called.
 *
 *----------------------------------------------------------------------
 */

ClientData
Tcl_InitNotifier(void)
void *
TclpInitNotifier(void)
{
    if (tclNotifierHooks.initNotifierProc) {
	return tclNotifierHooks.initNotifierProc();
    } else {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	PlatformEventsInit();
	return tsdPtr;
    }
}
    PlatformEventsInit();
    return tsdPtr;
}


/*
 *----------------------------------------------------------------------
 *
 * Tcl_FinalizeNotifier --
 *
 *	This function is called to cleanup the notifier state before a thread
 *	is terminated.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	If no finalizeNotifierProc notifier hook exists, PlatformEvents-
 *	Finalize is called.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_FinalizeNotifier(
    ClientData clientData)
{
    if (tclNotifierHooks.finalizeNotifierProc) {
	tclNotifierHooks.finalizeNotifierProc(clientData);
	return;
    } else {
	PlatformEventsFinalize();
    }
}

/*
 *----------------------------------------------------------------------
 *
 * PlatformEventsControl --
 *
 *	This function registers interest for the file descriptor and the mask
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
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







-
+








-
+









-
-
-
+
+
+
+






-
+




-
+

+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+



-
+










-
+










-
-
+
+







 *	- If it is not associated with a regular file, the file descriptor is
 *	  added, modified concerning its mask of events of interest, or
 *	  deleted from the epoll file descriptor of the calling thread.
 *
 *----------------------------------------------------------------------
 */

void
static void
PlatformEventsControl(
    FileHandler *filePtr,
    ThreadSpecificData *tsdPtr,
    int op,
    int isNew)
{
    struct epoll_event newEvent;
    struct PlatformEventData *newPedPtr;
    struct stat fdStat;
    Tcl_StatBuf fdStat;

    newEvent.events = 0;
    if (filePtr->mask & (TCL_READABLE | TCL_EXCEPTION)) {
	newEvent.events |= EPOLLIN;
    }
    if (filePtr->mask & TCL_WRITABLE) {
	newEvent.events |= EPOLLOUT;
    }
    if (isNew) {
        newPedPtr = (struct PlatformEventData *)Tcl_Alloc(sizeof(struct PlatformEventData));
        newPedPtr->filePtr = filePtr;
        newPedPtr->tsdPtr = tsdPtr;
	newPedPtr = (struct PlatformEventData *)
		Tcl_Alloc(sizeof(struct PlatformEventData));
	newPedPtr->filePtr = filePtr;
	newPedPtr->tsdPtr = tsdPtr;
	filePtr->pedPtr = newPedPtr;
    }
    newEvent.data.ptr = filePtr->pedPtr;

    /*
     * N.B. As discussed in Tcl_WaitForEvent(), epoll(7) does not support
     * regular files (S_IFREG.) Therefore, filePtr is in these cases simply
     * regular files (S_IFREG). Therefore, filePtr is in these cases simply
     * added or deleted from the list of FileHandlers associated with regular
     * files belonging to tsdPtr.
     */

    if (fstat(filePtr->fd, &fdStat) == -1) {
    if (TclOSfstat(filePtr->fd, &fdStat) == -1) {
	Tcl_Panic("fstat: %s", strerror(errno));
    }
    } else if ((fdStat.st_mode & S_IFMT) == S_IFREG) {
	switch (op) {
	case EPOLL_CTL_ADD:
	    if (isNew) {
		LIST_INSERT_HEAD(&tsdPtr->firstReadyFileHandlerPtr, filePtr,
			readyNode);
	    }
	    break;
	case EPOLL_CTL_DEL:
	    LIST_REMOVE(filePtr, readyNode);
	    break;
	}
	return;

   if (epoll_ctl(tsdPtr->eventsFd, op, filePtr->fd, &newEvent) == -1) {
       switch (errno) {
	    case EPERM:
		switch (op) {
		case EPOLL_CTL_ADD:
		    if (isNew) {
			LIST_INSERT_HEAD(&tsdPtr->firstReadyFileHandlerPtr, filePtr,
				readyNode);
		    }
		    break;
		case EPOLL_CTL_DEL:
		    LIST_REMOVE(filePtr, readyNode);
		    break;

		}
		break;
   } else if (epoll_ctl(tsdPtr->eventsFd, op, filePtr->fd, &newEvent) == -1) {
	Tcl_Panic("epoll_ctl: %s", strerror(errno));
   }
}

	    default:
		Tcl_Panic("epoll_ctl: %s", strerror(errno));
	}
    }
    return;
}

/*
 *----------------------------------------------------------------------
 *
 * PlatformEventsFinalize --
 * TclpFinalizeNotifier --
 *
 *	This function closes the eventfd and the epoll file descriptor and
 *	frees the epoll_event structs owned by the thread of the caller.  The
 *	above operations are protected by tsdPtr->notifierMutex, which is
 *	destroyed thereafter.
 *
 * Results:
 *	None.
 *
 * Side effects:
 * 	While tsdPtr->notifierMutex is held:
 *	While tsdPtr->notifierMutex is held:
 *	- The per-thread eventfd(2) is closed, if non-zero, and set to -1.
 *	- The per-thread epoll(7) fd is closed, if non-zero, and set to 0.
 *	- The per-thread epoll_event structs are freed, if any, and set to 0.
 *
 *	tsdPtr->notifierMutex is destroyed.
 *
 *----------------------------------------------------------------------
 */

void
PlatformEventsFinalize(
	void)
TclpFinalizeNotifier(
    TCL_UNUSED(void *))
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    pthread_mutex_lock(&tsdPtr->notifierMutex);
#ifdef HAVE_EVENTFD
    if (tsdPtr->triggerEventFd) {
	close(tsdPtr->triggerEventFd);
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
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
366
367
368
369


370
371
372
373
374
375
376
377
378







-
+









-
+



















-
-
+
+







 *	  PlatformEventsControl().
 *	- readyEvents and maxReadyEvents are initialised with 512
 *	  epoll_events.
 *
 *----------------------------------------------------------------------
 */

void
static void
PlatformEventsInit(void)
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    FileHandler *filePtr;

    errno = pthread_mutex_init(&tsdPtr->notifierMutex, NULL);
    if (errno) {
	Tcl_Panic("Tcl_InitNotifier: %s", "could not create mutex");
    }
    filePtr = (FileHandler *)Tcl_Alloc(sizeof(FileHandler));
    filePtr = (FileHandler *) Tcl_Alloc(sizeof(FileHandler));
#ifdef HAVE_EVENTFD
    tsdPtr->triggerEventFd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
    if (tsdPtr->triggerEventFd <= 0) {
	Tcl_Panic("Tcl_InitNotifier: %s", "could not create trigger eventfd");
    }
    filePtr->fd = tsdPtr->triggerEventFd;
#else /* !HAVE_EVENTFD */
    if (pipe2(tsdPtr->triggerPipe, O_CLOEXEC | O_NONBLOCK) != 0) {
	Tcl_Panic("Tcl_InitNotifier: %s", "could not create trigger pipe");
    }
    filePtr->fd = tsdPtr->triggerPipe[0];
#endif /* HAVE_EVENTFD */
    tsdPtr->triggerFilePtr = filePtr;
    if ((tsdPtr->eventsFd = epoll_create1(EPOLL_CLOEXEC)) == -1) {
	Tcl_Panic("epoll_create1: %s", strerror(errno));
    }
    filePtr->mask = TCL_READABLE;
    PlatformEventsControl(filePtr, tsdPtr, EPOLL_CTL_ADD, 1);
    if (!tsdPtr->readyEvents) {
        tsdPtr->maxReadyEvents = 512;
	tsdPtr->readyEvents = (struct epoll_event *)Tcl_Alloc(
	tsdPtr->maxReadyEvents = 512;
	tsdPtr->readyEvents = (struct epoll_event *) Tcl_Alloc(
		tsdPtr->maxReadyEvents * sizeof(tsdPtr->readyEvents[0]));
    }
    LIST_INIT(&tsdPtr->firstReadyFileHandlerPtr);
}

/*
 *----------------------------------------------------------------------
412
413
414
415
416
417
418
419

420
421
422
423
424
425
426
387
388
389
390
391
392
393

394
395
396
397
398
399
400
401







-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
static int
PlatformEventsTranslate(
    struct epoll_event *eventPtr)
{
    int mask;

    mask = 0;
    if (eventPtr->events & (EPOLLIN | EPOLLHUP)) {
453
454
455
456
457
458
459
460

461
462
463
464
465
466
467
428
429
430
431
432
433
434

435
436
437
438
439
440
441
442







-
+







 *	If timePtr specifies a positive value, it is updated to reflect the
 *	amount of time that has passed; if its value would {under, over}flow,
 *	it is set to zero.
 *
 *----------------------------------------------------------------------
 */

int
static int
PlatformEventsWait(
    struct epoll_event *events,
    size_t numEvents,
    struct timeval *timePtr)
{
    int numFound;
    struct timeval tv0, tv1, tv_delta;
476
477
478
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
558
559






560
561
562
563
564
565
566




567
568
569
570
571




572
573
574
575
576

577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594

595
596
597
598
599
600
601
602
603


604
605
606
607



608
609
610
611
612



613
614
615
616
617

618
619
620
621



622
623
624
625
626




627
628
629
630



631
632
633
634
635
636
637






638
639
640
641
642
643
644

645
646
647

648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663

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
707
708











709
710
711
712
713
714
715
716
717
718









719
720

721
722
723
724
725
726
727
728
729
730









731
732
733
734
735




736
737
738
739



740
741
742
743
744
745
746
747







748
749
750
751
752
753





754
755
756
757
758
759





760
761
762
763
764
765
766
767
768
769
770










771
772

773
774
775
776
777
778
779







780
781
782
783




784
785

786
787
788
789
790
791





792
793
794
795
796
797






798
799
800
801
802
803





804
805
806
807



808
809
810
811
812




813
814
815
816



817
818
819
820
821
822
823
824
825
826
827





































































828


829
830
831
832
833
834
835
836
837
451
452
453
454
455
456
457

458
459

460
461
462
463
464
465
466
467
468
469
470

471
472
473
474
475
476
477
478
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

558
559
560
561






562
563
564



565
566
567
568




569
570
571





572
573



574
575
576
577




578
579
580
581
582



583
584
585
586






587
588
589
590
591
592

593
594
595
596
597

598
599
600

601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616

617
618
619




620


621




622
623
624
625
626


627






628
629
630
631
632
633



634
635
636


637
638






639
640
641
642
643
644
645











646
647
648
649
650
651
652
653
654
655
656
657









658
659
660
661
662
663
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
707










708
709
710
711
712
713
714
715
716
717


718
719






720
721
722
723
724
725
726
727



728
729
730
731


732






733
734
735
736
737
738





739
740
741
742
743
744






745
746
747
748
749
750



751
752
753
754




755
756
757
758
759



760
761
762
763










764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844







-
+

-
+










-
+










+
+
+
+






-
+















-
+







-
+

-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+
-



-
+

















-
+



-
-
-
-
-
-
+
+

-
-
-
+
+
+

-
-
-
-
+
+
+
-
-
-
-
-
+

-
-
-
+
+
+

-
-
-
-
+
+
+
+

-
-
-
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
-





-
+


-
+















-
+


-
-
-
-
+
-
-
+
-
-
-
-
+
+
+
+
+
-
-
+
-
-
-
-
-
-
+
+
+
+
+

-
-
-
+
+
+
-
-
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+

-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
+
+
+
+
-
-
+
-
-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+

-
-
-
+
+
+

-
-
-
-
+
+
+
+

-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+









     */

    if (!timePtr) {
	timeout = -1;
    } else if (!timePtr->tv_sec && !timePtr->tv_usec) {
	timeout = 0;
    } else {
	timeout = (int)timePtr->tv_sec * 1000;
	timeout = (int) timePtr->tv_sec * 1000;
	if (timePtr->tv_usec) {
	    timeout += (int)timePtr->tv_usec / 1000;
	    timeout += (int) timePtr->tv_usec / 1000;
	}
    }

    /*
     * Call (and possibly block on) epoll_wait(2) and substract the delta of
     * gettimeofday(2) before and after the call from timePtr if the latter is
     * not NULL. Return the number of events returned by epoll_wait(2).
     */

    gettimeofday(&tv0, NULL);
    numFound = epoll_wait(tsdPtr->eventsFd, events, (int)numEvents, timeout);
    numFound = epoll_wait(tsdPtr->eventsFd, events, (int) numEvents, timeout);
    gettimeofday(&tv1, NULL);
    if (timePtr && (timePtr->tv_sec && timePtr->tv_usec)) {
	timersub(&tv1, &tv0, &tv_delta);
	if (!timercmp(&tv_delta, timePtr, >)) {
	    timersub(timePtr, &tv_delta, timePtr);
	} else {
	    timePtr->tv_sec = 0;
	    timePtr->tv_usec = 0;
	}
    }
    if (tsdPtr->asyncPending) {
	tsdPtr->asyncPending = 0;
	TclAsyncMarkFromNotifier();
    }
    return numFound;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_CreateFileHandler --
 * TclpCreateFileHandler --
 *
 *	This function registers a file handler with the epoll notifier of the
 *	thread of the caller.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Creates a new file handler structure.
 *	PlatformEventsControl() is called for the new file handler structure.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_CreateFileHandler(
TclpCreateFileHandler(
    int fd,			/* Handle of stream to watch. */
    int mask,			/* OR'ed combination of TCL_READABLE,
				 * TCL_WRITABLE, and TCL_EXCEPTION: indicates
				 * conditions under which proc should be
				 * called. */
    Tcl_FileProc *proc,		/* Function to call for each selected
				 * event. */
    ClientData clientData)	/* Arbitrary data to pass to proc. */
    void *clientData)	/* Arbitrary data to pass to proc. */
{
    int isNew;

    if (tclNotifierHooks.createFileHandlerProc) {
	tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData);
	return;
    } else {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
	FileHandler *filePtr;

    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    FileHandler *filePtr = LookUpFileHandler(tsdPtr, fd, NULL);
    int isNew = (filePtr == NULL);
	for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
		filePtr = filePtr->nextPtr) {
	    if (filePtr->fd == fd) {
		break;
	    }

	}
	if (filePtr == NULL) {
	    filePtr = (FileHandler *)Tcl_Alloc(sizeof(FileHandler));
	    filePtr->fd = fd;
	    filePtr->readyMask = 0;
	    filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
	    tsdPtr->firstFileHandlerPtr = filePtr;
    if (isNew) {
	filePtr = (FileHandler *) Tcl_Alloc(sizeof(FileHandler));
	filePtr->fd = fd;
	filePtr->readyMask = 0;
	filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
	tsdPtr->firstFileHandlerPtr = filePtr;
	    isNew = 1;
	} else {
	    isNew = 0;
	}
	filePtr->proc = proc;
	filePtr->clientData = clientData;
	filePtr->mask = mask;
    }
    filePtr->proc = proc;
    filePtr->clientData = clientData;
    filePtr->mask = mask;

	PlatformEventsControl(filePtr, tsdPtr,
		isNew ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, isNew);
    }
}
    PlatformEventsControl(filePtr, tsdPtr,
	    isNew ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, isNew);
}


/*
 *----------------------------------------------------------------------
 *
 * Tcl_DeleteFileHandler --
 * TclpDeleteFileHandler --
 *
 *	Cancel a previously-arranged callback arrangement for a file on the
 *	epoll file descriptor of the thread of the caller.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	If a callback was previously registered on file, remove it.
 *	PlatformEventsControl() is called for the file handler structure.
 *	The PlatformEventData struct associated with the new file handler
 *	structure is freed.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_DeleteFileHandler(
TclpDeleteFileHandler(
    int fd)			/* Stream id for which to remove callback
				 * function. */
{
    if (tclNotifierHooks.deleteFileHandlerProc) {
	tclNotifierHooks.deleteFileHandlerProc(fd);
	return;
    } else {
	FileHandler *filePtr, *prevPtr;
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    FileHandler *filePtr, *prevPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	/*
	 * Find the entry for the given file (and return if there isn't one).
	 */
    /*
     * Find the entry for the given file (and return if there isn't one).
     */

	for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
		prevPtr = filePtr, filePtr = filePtr->nextPtr) {
	    if (filePtr == NULL) {
		return;
    filePtr = LookUpFileHandler(tsdPtr, fd, &prevPtr);
    if (filePtr == NULL) {
	return;
	    }
	    if (filePtr->fd == fd) {
		break;
	    }
	}
    }

	/*
	 * Update the check masks for this file.
	 */
    /*
     * Update the check masks for this file.
     */

	PlatformEventsControl(filePtr, tsdPtr, EPOLL_CTL_DEL, 0);
	if (filePtr->pedPtr) {
	    Tcl_Free(filePtr->pedPtr);
	}
    PlatformEventsControl(filePtr, tsdPtr, EPOLL_CTL_DEL, 0);
    if (filePtr->pedPtr) {
	Tcl_Free(filePtr->pedPtr);
    }

	/*
	 * Clean up information in the callback record.
	 */
    /*
     * Clean up information in the callback record.
     */

	if (prevPtr == NULL) {
	    tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
	} else {
	    prevPtr->nextPtr = filePtr->nextPtr;
	}
	Tcl_Free(filePtr);
    if (prevPtr == NULL) {
	tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
    } else {
	prevPtr->nextPtr = filePtr->nextPtr;
    }
    Tcl_Free(filePtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_WaitForEvent --
 * TclpWaitForEvent --
 *
 *	This function is called by Tcl_DoOneEvent to wait for new events on
 *	the message queue. If the block time is 0, then Tcl_WaitForEvent just
 *	the message queue. If the block time is 0, then TclpWaitForEvent just
 *	polls without blocking.
 *
 *	The waiting logic is implemented in PlatformEventsWait.
 *
 * Results:
 *	Returns -1 if PlatformEventsWait() would block forever, otherwise
 *	returns 0.
 *
 * Side effects:
 *	Queues file events that are detected by PlatformEventsWait().
 *
 *----------------------------------------------------------------------
 */

int
Tcl_WaitForEvent(
TclpWaitForEvent(
    const Tcl_Time *timePtr)	/* Maximum block time, or NULL. */
{
    if (tclNotifierHooks.waitForEventProc) {
	return tclNotifierHooks.waitForEventProc(timePtr);
    } else {
	FileHandler *filePtr;
    FileHandler *filePtr;
	int mask;
	Tcl_Time vTime;
    Tcl_Time vTime;
	/*
	 * Impl. notes: timeout & timeoutPtr are used if, and only if threads
	 * are not enabled. They are the arguments for the regular epoll_wait()
	 * used when the core is not thread-enabled.
    struct timeval timeout, *timeoutPtr;
				/* Impl. notes: timeout & timeoutPtr are used
				 * if, and only if threads are not enabled.
				 * They are the arguments for the regular
				 * epoll_wait() used when the core is not
	 */

				 * thread-enabled. */
	struct timeval timeout, *timeoutPtr;
	int numFound, numEvent;
	struct PlatformEventData *pedPtr;
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
	int numQueued;
	ssize_t i;
    int mask, numFound, numEvent;
    struct PlatformEventData *pedPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    int numQueued;
    ssize_t i;

	/*
	 * Set up the timeout structure. Note that if there are no events to
	 * check for, we return with a negative result rather than blocking
    /*
     * Set up the timeout structure. Note that if there are no events to check
     * for, we return with a negative result rather than blocking forever.
	 * forever.
	 */
     */

	if (timePtr != NULL) {
	    /*
	     * TIP #233 (Virtualized Time). Is virtual time in effect? And do
	     * we actually have something to scale? If yes to both then we
	     * call the handler to do this scaling.
	     */
    if (timePtr != NULL) {
	/*
	 * TIP #233 (Virtualized Time). Is virtual time in effect? And do we
	 * actually have something to scale? If yes to both then we call the
	 * handler to do this scaling.
	 */

	    if (timePtr->sec != 0 || timePtr->usec != 0) {
		vTime = *timePtr;
		tclScaleTimeProcPtr(&vTime, tclTimeClientData);
		timePtr = &vTime;
	    }
	    timeout.tv_sec = timePtr->sec;
	    timeout.tv_usec = timePtr->usec;
	    timeoutPtr = &timeout;
	} else {
	    timeoutPtr = NULL;
	}
	if (timePtr->sec != 0 || timePtr->usec != 0) {
	    vTime = *timePtr;
	    TclScaleTime(&vTime);
	    timePtr = &vTime;
	}
	timeout.tv_sec = timePtr->sec;
	timeout.tv_usec = timePtr->usec;
	timeoutPtr = &timeout;
    } else {
	timeoutPtr = NULL;
    }

	/*
	 * Walk the list of FileHandlers associated with regular files
	 * (S_IFREG) belonging to tsdPtr, queue Tcl events for them, and
	 * update their mask of events of interest.
	 *
	 * As epoll(7) does not support regular files, the behaviour of
	 * {select,poll}(2) is simply simulated here: fds associated with
	 * regular files are added to this list by PlatformEventsControl() and
	 * processed here before calling (and possibly blocking) on
    /*
     * Walk the list of FileHandlers associated with regular files (S_IFREG)
     * belonging to tsdPtr, queue Tcl events for them, and update their mask
     * of events of interest.
     *
     * As epoll(7) does not support regular files, the behaviour of
     * {select,poll}(2) is simply simulated here: fds associated with regular
     * files are added to this list by PlatformEventsControl() and processed
     * here before calling (and possibly blocking) on PlatformEventsWait().
	 * PlatformEventsWait().
	 */
     */

	numQueued = 0;
	LIST_FOREACH(filePtr, &tsdPtr->firstReadyFileHandlerPtr, readyNode) {
	    mask = 0;
	    if (filePtr->mask & TCL_READABLE) {
		mask |= TCL_READABLE;
	    }
	    if (filePtr->mask & TCL_WRITABLE) {
		mask |= TCL_WRITABLE;
	    }
    numQueued = 0;
    LIST_FOREACH(filePtr, &tsdPtr->firstReadyFileHandlerPtr, readyNode) {
	mask = 0;
	if (filePtr->mask & TCL_READABLE) {
	    mask |= TCL_READABLE;
	}
	if (filePtr->mask & TCL_WRITABLE) {
	    mask |= TCL_WRITABLE;
	}

	    /*
	     * Don't bother to queue an event if the mask was previously
	     * non-zero since an event must still be on the queue.
	     */
	/*
	 * Don't bother to queue an event if the mask was previously non-zero
	 * since an event must still be on the queue.
	 */

	    if (filePtr->readyMask == 0) {
		FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)
			Tcl_Alloc(sizeof(FileHandlerEvent));
	if (filePtr->readyMask == 0) {
	    FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)
		    Tcl_Alloc(sizeof(FileHandlerEvent));

		fileEvPtr->header.proc = FileHandlerEventProc;
		fileEvPtr->fd = filePtr->fd;
		Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
		numQueued++;
	    }
	    filePtr->readyMask = mask;
	}
	    fileEvPtr->header.proc = FileHandlerEventProc;
	    fileEvPtr->fd = filePtr->fd;
	    Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
	    numQueued++;
	}
	filePtr->readyMask = mask;
    }

	/*
	 * If any events were queued in the above loop, force
	 * PlatformEventsWait() to poll as there already are events that need
	 * to be processed at this point.
	 */
    /*
     * If any events were queued in the above loop, force PlatformEventsWait()
     * to poll as there already are events that need to be processed at this
     * point.
     */

	if (numQueued) {
	    timeout.tv_sec = 0;
	    timeout.tv_usec = 0;
	    timeoutPtr = &timeout;
	}
    if (numQueued) {
	timeout.tv_sec = 0;
	timeout.tv_usec = 0;
	timeoutPtr = &timeout;
    }

	/*
	 * Wait or poll for new events, queue Tcl events for the FileHandlers
	 * corresponding to them, and update the FileHandlers' mask of events
	 * of interest registered by the last call to Tcl_CreateFileHandler().
	 *
	 * Events for the eventfd(2)/trigger pipe are processed here in order
	 * to facilitate inter-thread IPC. If another thread intends to wake
	 * up this thread whilst it's blocking on PlatformEventsWait(), it
	 * write(2)s to the eventfd(2)/trigger pipe (see Tcl_AlertNotifier(),)
	 * which in turn will cause PlatformEventsWait() to return
    /*
     * Wait or poll for new events, queue Tcl events for the FileHandlers
     * corresponding to them, and update the FileHandlers' mask of events of
     * interest registered by the last call to Tcl_CreateFileHandler().
     *
     * Events for the eventfd(2)/trigger pipe are processed here in order to
     * facilitate inter-thread IPC. If another thread intends to wake up this
     * thread whilst it's blocking on PlatformEventsWait(), it write(2)s to
     * the eventfd(2)/trigger pipe (see Tcl_AlertNotifier(),) which in turn
     * will cause PlatformEventsWait() to return immediately.
	 * immediately.
	 */
     */

	numFound = PlatformEventsWait(tsdPtr->readyEvents,
		tsdPtr->maxReadyEvents, timeoutPtr);
	for (numEvent = 0; numEvent < numFound; numEvent++) {
	    pedPtr = (struct PlatformEventData*)tsdPtr->readyEvents[numEvent].data.ptr;
	    filePtr = pedPtr->filePtr;
	    mask = PlatformEventsTranslate(&tsdPtr->readyEvents[numEvent]);
    numFound = PlatformEventsWait(tsdPtr->readyEvents,
	    tsdPtr->maxReadyEvents, timeoutPtr);
    for (numEvent = 0; numEvent < numFound; numEvent++) {
	pedPtr = (struct PlatformEventData *)
		tsdPtr->readyEvents[numEvent].data.ptr;
	filePtr = pedPtr->filePtr;
	mask = PlatformEventsTranslate(&tsdPtr->readyEvents[numEvent]);
#ifdef HAVE_EVENTFD
	    if (filePtr->fd == tsdPtr->triggerEventFd) {
		uint64_t eventFdVal;
		i = read(tsdPtr->triggerEventFd, &eventFdVal,
	if (filePtr->fd == tsdPtr->triggerEventFd) {
	    uint64_t eventFdVal;

	    i = read(tsdPtr->triggerEventFd, &eventFdVal, sizeof(eventFdVal));
			sizeof(eventFdVal));
		if ((i != sizeof(eventFdVal)) && (errno != EAGAIN)) {
	    if ((i != sizeof(eventFdVal)) && (errno != EAGAIN)) {
		    Tcl_Panic(
			    "Tcl_WaitForEvent: read from %p->triggerEventFd: %s",
			    (void *) tsdPtr, strerror(errno));
		}
		continue;
	    }
		Tcl_Panic("%s: read from %p->triggerEventFd: %s",
			"Tcl_WaitForEvent", tsdPtr, strerror(errno));
	    }
	    continue;
	}
#else /* !HAVE_EVENTFD */
	    if (filePtr->fd == tsdPtr->triggerPipe[0]) {
		char triggerPipeVal;
		i = read(tsdPtr->triggerPipe[0], &triggerPipeVal,
			sizeof(triggerPipeVal));
		if ((i != sizeof(triggerPipeVal)) && (errno != EAGAIN)) {
	if (filePtr->fd == tsdPtr->triggerPipe[0]) {
	    char triggerPipeVal;

	    i = read(tsdPtr->triggerPipe[0], &triggerPipeVal,
		    sizeof(triggerPipeVal));
	    if ((i != sizeof(triggerPipeVal)) && (errno != EAGAIN)) {
		    Tcl_Panic(
			    "Tcl_WaitForEvent: read from %p->triggerPipe[0]: %s",
			    (void *) tsdPtr, strerror(errno));
		}
		continue;
	    }
		Tcl_Panic("%s: read from %p->triggerPipe[0]: %s",
			"Tcl_WaitForEvent", tsdPtr, strerror(errno));
	    }
	    continue;
	}
#endif /* HAVE_EVENTFD */
	    if (!mask) {
		continue;
	    }
	if (!mask) {
	    continue;
	}

	    /*
	     * Don't bother to queue an event if the mask was previously
	     * non-zero since an event must still be on the queue.
	     */
	/*
	 * Don't bother to queue an event if the mask was previously non-zero
	 * since an event must still be on the queue.
	 */

	    if (filePtr->readyMask == 0) {
		FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)
			Tcl_Alloc(sizeof(FileHandlerEvent));
	if (filePtr->readyMask == 0) {
	    FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)
		    Tcl_Alloc(sizeof(FileHandlerEvent));

		fileEvPtr->header.proc = FileHandlerEventProc;
		fileEvPtr->fd = filePtr->fd;
		Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
	    }
	    filePtr->readyMask = mask;
	}
	return 0;
    }
}

	    fileEvPtr->header.proc = FileHandlerEventProc;
	    fileEvPtr->fd = filePtr->fd;
	    Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
	}
	filePtr->readyMask = mask;
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TclAsyncNotifier --
 *
 *	This procedure sets the async mark of an async handler to a
 *	given value, if it is called from the target thread.
 *
 * Result:
 *	True, when the handler will be marked, false otherwise.
 *
 * Side effects:
 *	The signal may be resent to the target thread.
 *
 *----------------------------------------------------------------------
 */

int
TclAsyncNotifier(
    int sigNumber,		/* Signal number. */
    Tcl_ThreadId threadId,	/* Target thread. */
    void *clientData,	/* Notifier data. */
    int *flagPtr,		/* Flag to mark. */
    int value)			/* Value of mark. */
{
#if TCL_THREADS
    /*
     * WARNING:
     * This code most likely runs in a signal handler. Thus,
     * only few async-signal-safe system calls are allowed,
     * e.g. pthread_self(), sem_post(), write().
     */

    if (pthread_equal(pthread_self(), (pthread_t) threadId)) {
	ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;

	*flagPtr = value;
	if (tsdPtr != NULL && !tsdPtr->asyncPending) {
	    tsdPtr->asyncPending = 1;
	    TclpAlertNotifier(tsdPtr);
	    return 1;
	}
	return 0;
    }

    /*
     * Re-send the signal to the proper target thread.
     */

    pthread_kill((pthread_t) threadId, sigNumber);
#else
    (void)sigNumber;
    (void)threadId;
    (void)clientData;
    (void)flagPtr;
    (void)value;
#endif
    return 0;
}

#endif /* NOTIFIER_EPOLL && TCL_THREADS */
#else
TCL_MAC_EMPTY_FILE(unix_tclEpollNotfy_c)
#endif /* !HAVE_COREFOUNDATION */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to unix/tclKqueueNotfy.c.

1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17








-
-
+
+







/*
 * tclKqueueNotfy.c --
 *
 *	This file contains the implementation of the kqueue()-based
 *	DragonFly/Free/Net/OpenBSD-specific notifier, which is the lowest-
 *	level part of the Tcl event loop. This file works together with
 *	generic/tclNotify.c.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 2016 Lucio Andrés Illanes Albornoz <l.illanes@gmx.de>
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2016 Lucio Andrés Illanes Albornoz <l.illanes@gmx.de>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#ifndef HAVE_COREFOUNDATION	/* Darwin/Mac OS X CoreFoundation notifier is
27
28
29
30
31
32
33
34


35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
27
28
29
30
31
32
33

34
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
50







-
+
+







-
+







/*
 * This structure is used to keep track of the notifier info for a registered
 * file.
 */

struct PlatformEventData;
typedef struct FileHandler {
    int fd;
    int fd;			/* File descriptor that this is describing a
				 * handler for. */
    int mask;			/* Mask of desired events: TCL_READABLE,
				 * etc. */
    int readyMask;		/* Mask of events that have been seen since
				 * the last time file handlers were invoked
				 * for this file. */
    Tcl_FileProc *proc;		/* Function to call, in the style of
				 * Tcl_CreateFileHandler. */
    ClientData clientData;	/* Argument to pass to proc. */
    void *clientData;	/* Argument to pass to proc. */
    struct FileHandler *nextPtr;/* Next in list of all files we care about. */
    LIST_ENTRY(FileHandler) readyNode;
				/* Next/previous in list of FileHandlers asso-
				 * ciated with regular files (S_IFREG) that are
				 * ready for I/O. */
    struct PlatformEventData *pedPtr;
				/* Pointer to PlatformEventData associating this
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
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







-
+







+










-
-



-
+
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-







				/* Pointer to head of file handler list. */
    struct PlatformReadyFileHandlerList firstReadyFileHandlerPtr;
				/* Pointer to head of list of FileHandlers
				 * associated with regular files (S_IFREG)
				 * that are ready for I/O. */
    pthread_mutex_t notifierMutex;
				/* Mutex protecting notifier termination in
				 * PlatformEventsFinalize. */
				 * TclpFinalizeNotifier. */
    int triggerPipe[2];		/* pipe(2) used by other threads to wake
				 * up this thread for inter-thread IPC. */
    int eventsFd;		/* kqueue(2) file descriptor used to wait for
				 * fds. */
    struct kevent *readyEvents;	/* Pointer to at most maxReadyEvents events
				 * returned by kevent(2). */
    size_t maxReadyEvents;	/* Count of kevents in readyEvents. */
    int asyncPending;		/* True when signal triggered thread. */
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;

/*
 * Forward declarations of internal functions.
 */

static void		PlatformEventsControl(FileHandler *filePtr,
			    ThreadSpecificData *tsdPtr, int op, int isNew);
static void		PlatformEventsFinalize(void);
static void		PlatformEventsInit(void);
static int		PlatformEventsTranslate(struct kevent *eventPtr);
static int		PlatformEventsWait(struct kevent *events,
			    size_t numEvents, struct timeval *timePtr);


#include "tclUnixNotfy.c"

/*
 *----------------------------------------------------------------------
 *
 * Tcl_InitNotifier --
 *
 *	Initializes the platform specific notifier state.
 *
 * Results:
 *	Returns a handle to the notifier state for this thread.
 *
 * Side effects:
 *	If no initNotifierProc notifier hook exists, PlatformEventsInit
 *	is called.
 *
 *----------------------------------------------------------------------
 */

 * Incorporate the base notifier implementation.
ClientData
Tcl_InitNotifier(void)
{
    if (tclNotifierHooks.initNotifierProc) {
	return tclNotifierHooks.initNotifierProc();
    } else {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	PlatformEventsInit();
	return tsdPtr;
    }
}

/*
 *----------------------------------------------------------------------
 *
 */
 * Tcl_FinalizeNotifier --
 *

 *	This function is called to cleanup the notifier state before a thread
 *	is terminated.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	If no finalizeNotifierProc notifier hook exists, PlatformEvents-
 *	Finalize is called.
 *
 *----------------------------------------------------------------------
 */

#include "tclUnixNotfy.c"
void
Tcl_FinalizeNotifier(
    ClientData clientData)
{
    if (tclNotifierHooks.finalizeNotifierProc) {
	tclNotifierHooks.finalizeNotifierProc(clientData);
	return;
    } else {
	PlatformEventsFinalize();
    }
}

/*
 *----------------------------------------------------------------------
 *
 * PlatformEventsControl --
 *
 *	This function registers interest for the file descriptor and the mask
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
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







-
+









-
+


-
-
-
-
+
+
+
+
+










-
+

-
+
+
+


















-
+




-
+



-
+

















-
+





-
+












-
+










-
+










-
-
+
+







 *	  deleted from the epoll file descriptor of the calling thread.
 *	- If deleting a file descriptor, kevent(2) is called twice specifying
 *	  EVFILT_READ first and then EVFILT_WRITE (see note below.)
 *
 *----------------------------------------------------------------------
 */

void
static void
PlatformEventsControl(
    FileHandler *filePtr,
    ThreadSpecificData *tsdPtr,
    int op,
    int isNew)
{
    int numChanges;
    struct kevent changeList[2];
    struct PlatformEventData *newPedPtr;
    struct stat fdStat;
    Tcl_StatBuf fdStat;

    if (isNew) {
        newPedPtr = (struct PlatformEventData *)Tcl_Alloc(sizeof(struct PlatformEventData));
        newPedPtr->filePtr = filePtr;
        newPedPtr->tsdPtr = tsdPtr;
        filePtr->pedPtr = newPedPtr;
	newPedPtr = (struct PlatformEventData *)
		Tcl_Alloc(sizeof(struct PlatformEventData));
	newPedPtr->filePtr = filePtr;
	newPedPtr->tsdPtr = tsdPtr;
	filePtr->pedPtr = newPedPtr;
    }

    /*
     * N.B. As discussed in Tcl_WaitForEvent(), kqueue(2) does not reproduce
     * the `always ready' {select,poll}(2) behaviour for regular files
     * (S_IFREG) prior to FreeBSD 11.0-RELEASE. Therefore, filePtr is in these
     * cases simply added or deleted from the list of FileHandlers associated
     * with regular files belonging to tsdPtr.
     */

    if (fstat(filePtr->fd, &fdStat) == -1) {
    if (TclOSfstat(filePtr->fd, &fdStat) == -1) {
	Tcl_Panic("fstat: %s", strerror(errno));
    } else if ((fdStat.st_mode & S_IFMT) == S_IFREG) {
    } else if ((fdStat.st_mode & S_IFMT) == S_IFREG
	    || (fdStat.st_mode & S_IFMT) == S_IFDIR
	    || (fdStat.st_mode & S_IFMT) == S_IFLNK) {
	switch (op) {
	case EV_ADD:
	    if (isNew) {
		LIST_INSERT_HEAD(&tsdPtr->firstReadyFileHandlerPtr, filePtr,
			readyNode);
	    }
	    break;
	case EV_DELETE:
	    LIST_REMOVE(filePtr, readyNode);
	    break;
	}
	return;
    }

    numChanges = 0;
    switch (op) {
    case EV_ADD:
	if (filePtr->mask & (TCL_READABLE | TCL_EXCEPTION)) {
	    EV_SET(&changeList[numChanges], (uintptr_t)filePtr->fd,
	    EV_SET(&changeList[numChanges], (uintptr_t) filePtr->fd,
		    EVFILT_READ, op, 0, 0, filePtr->pedPtr);
	    numChanges++;
	}
	if (filePtr->mask & TCL_WRITABLE) {
	    EV_SET(&changeList[numChanges], (uintptr_t)filePtr->fd,
	    EV_SET(&changeList[numChanges], (uintptr_t) filePtr->fd,
		    EVFILT_WRITE, op, 0, 0, filePtr->pedPtr);
	    numChanges++;
	}
        if (numChanges) {
	if (numChanges) {
	    if (kevent(tsdPtr->eventsFd, changeList, numChanges, NULL, 0,
		    NULL) == -1) {
		Tcl_Panic("kevent: %s", strerror(errno));
	    }
	}
	break;
    case EV_DELETE:
	/*
	 * N.B. kqueue(2) has separate filters for readability and writability
	 * fd events. We therefore need to ensure that fds are ompletely
	 * removed from the kqueue(2) fd when deleting.  This is exacerbated
	 * by changes to filePtr->mask w/o calls to PlatforEventsControl()
	 * after e.g. an exec(3) in a child process.
	 *
	 * As one of these calls can fail, two separate kevent(2) calls are
	 * made for EVFILT_{READ,WRITE}.
	 */
	EV_SET(&changeList[0], (uintptr_t)filePtr->fd, EVFILT_READ, op, 0, 0,
	EV_SET(&changeList[0], (uintptr_t) filePtr->fd, EVFILT_READ, op, 0, 0,
		NULL);
	if ((kevent(tsdPtr->eventsFd, changeList, 1, NULL, 0, NULL) == -1)
		&& (errno != ENOENT)) {
	    Tcl_Panic("kevent: %s", strerror(errno));
	}
	EV_SET(&changeList[0], (uintptr_t)filePtr->fd, EVFILT_WRITE, op, 0, 0,
	EV_SET(&changeList[0], (uintptr_t) filePtr->fd, EVFILT_WRITE, op, 0, 0,
		NULL);
	if ((kevent(tsdPtr->eventsFd, changeList, 1, NULL, 0, NULL) == -1)
		&& (errno != ENOENT)) {
	    Tcl_Panic("kevent: %s", strerror(errno));
	}
	break;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * PlatformEventsFinalize --
 * TclpFinalizeNotifier --
 *
 *	This function closes the pipe and the kqueue file descriptors and
 *	frees the kevent structs owned by the thread of the caller.  The above
 *	operations are protected by tsdPtr->notifierMutex, which is destroyed
 *	thereafter.
 *
 * Results:
 *	None.
 *
 * Side effects:
 * 	While tsdPtr->notifierMutex is held:
 *	While tsdPtr->notifierMutex is held:
 *	The per-thread pipe(2) fds are closed, if non-zero, and set to -1.
 *	The per-thread kqueue(2) fd is closed, if non-zero, and set to 0.
 *	The per-thread kevent structs are freed, if any, and set to 0.
 *
 *	tsdPtr->notifierMutex is destroyed.
 *
 *----------------------------------------------------------------------
 */

void
PlatformEventsFinalize(
    void)
TclpFinalizeNotifier(
    TCL_UNUSED(void *))
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    pthread_mutex_lock(&tsdPtr->notifierMutex);
    if (tsdPtr->triggerPipe[0]) {
	close(tsdPtr->triggerPipe[0]);
	tsdPtr->triggerPipe[0] = -1;
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
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







-
+
+
+






-
+
















-
-
+
+







	Tcl_Panic("pthread_mutex_destroy: %s", strerror(errno));
    }
}

/*
 *----------------------------------------------------------------------
 *
 * PlatformEventsInit --
 * TclpInitNotifier --
 *
 *	Initializes the platform specific notifier state.
 *
 *	This function abstracts creating a kqueue fd via the kqueue system
 *	call and allocating memory for the kevents structs in tsdPtr for the
 *	thread of the caller.
 *
 * Results:
 *	None.
 *	Returns a handle to the notifier state for this thread.
 *
 * Side effects:
 *	The following per-thread entities are initialised:
 *	- notifierMutex is initialised.
 *	- The pipe(2) is created; fcntl(2) is called on both fds to set
 *	  FD_CLOEXEC and O_NONBLOCK.
 *	- The kqueue(2) fd is created; fcntl(2) is called on it to set
 *	  FD_CLOEXEC.
 *	- A FileHandler struct is allocated and initialised for the event-
 *	  fd(2), registering interest for TCL_READABLE on it via Platform-
 *	  EventsControl().
 *	- readyEvents and maxReadyEvents are initialised with 512 kevents.
 *
 *----------------------------------------------------------------------
 */

void
PlatformEventsInit(void)
void *
TclpInitNotifier(void)
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    int i, fdFl;
    FileHandler *filePtr;

    errno = pthread_mutex_init(&tsdPtr->notifierMutex, NULL);
    if (errno) {
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
467
468
469
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







-
+




-
-
+
+



+
+



















-
+




















-
+







	}
    }
    if ((tsdPtr->eventsFd = kqueue()) == -1) {
	Tcl_Panic("kqueue: %s", strerror(errno));
    } else if (fcntl(tsdPtr->eventsFd, F_SETFD, FD_CLOEXEC) == -1) {
	Tcl_Panic("fcntl: %s", strerror(errno));
    }
    filePtr = (FileHandler *)Tcl_Alloc(sizeof(FileHandler));
    filePtr = (FileHandler *) Tcl_Alloc(sizeof(FileHandler));
    filePtr->fd = tsdPtr->triggerPipe[0];
    filePtr->mask = TCL_READABLE;
    PlatformEventsControl(filePtr, tsdPtr, EV_ADD, 1);
    if (!tsdPtr->readyEvents) {
        tsdPtr->maxReadyEvents = 512;
	tsdPtr->readyEvents = (struct kevent *)Tcl_Alloc(
	tsdPtr->maxReadyEvents = 512;
	tsdPtr->readyEvents = (struct kevent *) Tcl_Alloc(
		tsdPtr->maxReadyEvents * sizeof(tsdPtr->readyEvents[0]));
    }
    LIST_INIT(&tsdPtr->firstReadyFileHandlerPtr);

    return tsdPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * PlatformEventsTranslate --
 *
 *	This function translates the platform-specific mask of returned
 *	events in eventPtr to a mask of TCL_* bits.
 *
 * Results:
 *	Returns the translated mask.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
static int
PlatformEventsTranslate(
    struct kevent *eventPtr)
{
    int mask;

    mask = 0;
    if (eventPtr->filter == EVFILT_READ) {
	mask |= TCL_READABLE;
	if (eventPtr->flags & EV_ERROR) {
	    mask |= TCL_EXCEPTION;
	}
    }
    if (eventPtr->filter == EVFILT_WRITE) {
	mask |= TCL_WRITABLE;
	if (eventPtr->flags & EV_ERROR) {
	    mask |= TCL_EXCEPTION;
	}
    }
    return mask;
}


/*
 *----------------------------------------------------------------------
 *
 * PlatformEventsWait --
 *
 *	This function abstracts waiting for I/O events via the kevent system
 *	call.
479
480
481
482
483
484
485
486

487
488
489
490
491
492
493
430
431
432
433
434
435
436

437
438
439
440
441
442
443
444







-
+







 *	If timePtr specifies a positive value, it is updated to reflect the
 *	amount of time that has passed; if its value would {under, over}flow,
 *	it is set to zero.
 *
 *----------------------------------------------------------------------
 */

int
static int
PlatformEventsWait(
    struct kevent *events,
    size_t numEvents,
    struct timeval *timePtr)
{
    int numFound;
    struct timeval tv0, tv1, tv_delta;
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

558
559
560
561
562
563
564
565

566
567
568
569
570
571
572
573
574
575



576
577
578
579
580

581
582
583
584
585
586
587






588
589
590
591
592
593
594




595
596
597
598



599
600
601
602
603

604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621

622
623
624
625

626
627
628
629

630
631
632
633
634



635
636
637
638
639



640
641
642
643
644

645
646
647
648



649
650
651
652
653




654
655
656
657



658
659
660
661
662
663
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
707
708
709
710
711






712
713
714
715



716
717

718
719
720
721
722
723
724






725
726
727
728
729
730
731
732
733
734
735
736











737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
















754
755
756
757
758
759
760
761
762
763









764
765
766
767
768




769
770
771
772



773
774
775
776
777
778
779
780







781
782
783
784
785
786





787
788
789
790
791
792





793
794
795
796
797
798
799
800
801
802
803
804











805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823


















824
825
826
827
828




829
830
831
832



833
834
835
836
837
838
839
840
841
842
843





































































844


845
846
847
848
849
850
851
852
853
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
558
559
560

561
562
563
564

565




566

567



568
569
570
571




572
573
574





575
576



577
578
579
580




581
582
583
584
585



586
587
588
589






590
591
592
593
594
595

596
597
598
599
600

601
602
603

604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619


620
621
622






623
624
625




626
627
628
629
630


631







632
633
634
635
636
637
638



639
640
641


642
643






644
645
646
647
648
649
650











651
652
653
654
655
656
657
658
659
660
661
662
















663
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





707
708
709
710
711
712





713
714
715
716
717
718











719
720
721
722
723
724
725
726
727
728
729
730


















731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749




750
751
752
753
754



755
756
757
758










759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839







+
+
+
+






-
+















-
+







-
+

-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+

-
-
-
+
+
+
-



-
+

















-
+



-
+
-
-
-
-
+
-

-
-
-
+
+
+

-
-
-
-
+
+
+
-
-
-
-
-
+

-
-
-
+
+
+

-
-
-
-
+
+
+
+

-
-
-
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
-





-
+


-
+















-
-
+
+

-
-
-
-
-
-
+
+
+
-
-
-
-
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
+
+
+
-
-
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+









	if (!timercmp(&tv_delta, timePtr, >)) {
	    timersub(timePtr, &tv_delta, timePtr);
	} else {
	    timePtr->tv_sec = 0;
	    timePtr->tv_usec = 0;
	}
    }
    if (tsdPtr->asyncPending) {
	tsdPtr->asyncPending = 0;
	TclAsyncMarkFromNotifier();
    }
    return numFound;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_CreateFileHandler --
 * TclpCreateFileHandler --
 *
 *	This function registers a file handler with the kqueue notifier
 *	of the thread of the caller.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Creates a new file handler structure.
 *	PlatformEventsControl() is called for the new file handler structure.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_CreateFileHandler(
TclpCreateFileHandler(
    int fd,			/* Handle of stream to watch. */
    int mask,			/* OR'ed combination of TCL_READABLE,
				 * TCL_WRITABLE, and TCL_EXCEPTION: indicates
				 * conditions under which proc should be
				 * called. */
    Tcl_FileProc *proc,		/* Function to call for each selected
				 * event. */
    ClientData clientData)	/* Arbitrary data to pass to proc. */
    void *clientData)	/* Arbitrary data to pass to proc. */
{
    int isNew;

    if (tclNotifierHooks.createFileHandlerProc) {
	tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData);
	return;
    } else {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
	FileHandler *filePtr;

    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    FileHandler *filePtr = LookUpFileHandler(tsdPtr, fd, NULL);
    int isNew = (filePtr == NULL);
	for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
		filePtr = filePtr->nextPtr) {
	    if (filePtr->fd == fd) {
		break;
	    }

	}
	if (filePtr == NULL) {
	    filePtr = (FileHandler *)Tcl_Alloc(sizeof(FileHandler));
	    filePtr->fd = fd;
	    filePtr->readyMask = 0;
	    filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
	    tsdPtr->firstFileHandlerPtr = filePtr;
    if (isNew) {
	filePtr = (FileHandler *) Tcl_Alloc(sizeof(FileHandler));
	filePtr->fd = fd;
	filePtr->readyMask = 0;
	filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
	tsdPtr->firstFileHandlerPtr = filePtr;
	    isNew = 1;
	} else {
	    isNew = 0;
	}
	filePtr->proc = proc;
	filePtr->clientData = clientData;
	filePtr->mask = mask;
    }
    filePtr->proc = proc;
    filePtr->clientData = clientData;
    filePtr->mask = mask;

	PlatformEventsControl(filePtr, tsdPtr, EV_ADD, isNew);
    }
}
    PlatformEventsControl(filePtr, tsdPtr, EV_ADD, isNew);
}


/*
 *----------------------------------------------------------------------
 *
 * Tcl_DeleteFileHandler --
 * TclpDeleteFileHandler --
 *
 *	Cancel a previously-arranged callback arrangement for a file on the
 *	kqueue of the thread of the caller.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	If a callback was previously registered on file, remove it.
 *	PlatformEventsControl() is called for the file handler structure.
 *	The PlatformEventData struct associated with the new file handler
 *	structure is freed.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_DeleteFileHandler(
TclpDeleteFileHandler(
    int fd)			/* Stream id for which to remove callback
				 * function. */
{
    if (tclNotifierHooks.deleteFileHandlerProc) {
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
	tclNotifierHooks.deleteFileHandlerProc(fd);
	return;
    } else {
	FileHandler *filePtr, *prevPtr;
    FileHandler *filePtr, *prevPtr;
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	/*
	 * Find the entry for the given file (and return if there isn't one).
	 */
    /*
     * Find the entry for the given file (and return if there isn't one).
     */

	for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
		prevPtr = filePtr, filePtr = filePtr->nextPtr) {
	    if (filePtr == NULL) {
		return;
    filePtr = LookUpFileHandler(tsdPtr, fd, &prevPtr);
    if (filePtr == NULL) {
	return;
	    }
	    if (filePtr->fd == fd) {
		break;
	    }
	}
    }

	/*
	 * Update the check masks for this file.
	 */
    /*
     * Update the check masks for this file.
     */

	PlatformEventsControl(filePtr, tsdPtr, EV_DELETE, 0);
	if (filePtr->pedPtr) {
	    Tcl_Free(filePtr->pedPtr);
	}
    PlatformEventsControl(filePtr, tsdPtr, EV_DELETE, 0);
    if (filePtr->pedPtr) {
	Tcl_Free(filePtr->pedPtr);
    }

	/*
	 * Clean up information in the callback record.
	 */
    /*
     * Clean up information in the callback record.
     */

	if (prevPtr == NULL) {
	    tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
	} else {
	    prevPtr->nextPtr = filePtr->nextPtr;
	}
	Tcl_Free(filePtr);
    if (prevPtr == NULL) {
	tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
    } else {
	prevPtr->nextPtr = filePtr->nextPtr;
    }
    Tcl_Free(filePtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_WaitForEvent --
 * TclpWaitForEvent --
 *
 *	This function is called by Tcl_DoOneEvent to wait for new events on
 *	the message queue. If the block time is 0, then Tcl_WaitForEvent just
 *	the message queue. If the block time is 0, then TclpWaitForEvent just
 *	polls without blocking.
 *
 *	The waiting logic is implemented in PlatformEventsWait.
 *
 * Results:
 *	Returns -1 if PlatformEventsWait() would block forever, otherwise
 *	returns 0.
 *
 * Side effects:
 *	Queues file events that are detected by PlatformEventsWait().
 *
 *----------------------------------------------------------------------
 */

int
Tcl_WaitForEvent(
    const Tcl_Time *timePtr)		/* Maximum block time, or NULL. */
TclpWaitForEvent(
    const Tcl_Time *timePtr)	/* Maximum block time, or NULL. */
{
    if (tclNotifierHooks.waitForEventProc) {
	return tclNotifierHooks.waitForEventProc(timePtr);
    } else {
	FileHandler *filePtr;
	int mask;
	Tcl_Time vTime;
    FileHandler *filePtr;
    int mask;
    Tcl_Time vTime;
	/*
	 * Impl. notes: timeout & timeoutPtr are used if, and only if threads
	 * are not enabled. They are the arguments for the regular epoll_wait()
	 * used when the core is not thread-enabled.
    struct timeval timeout, *timeoutPtr;
				/* Impl. notes: timeout & timeoutPtr are used
				 * if, and only if threads are not enabled.
				 * They are the arguments for the regular
				 * epoll_wait() used when the core is not
	 */

				 * thread-enabled. */
	struct timeval timeout, *timeoutPtr;
	int numFound, numEvent;
	struct PlatformEventData *pedPtr;
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
	int numQueued;
	ssize_t i;
	char buf[1];
    int numFound, numEvent;
    struct PlatformEventData *pedPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    int numQueued;
    ssize_t i;
    char buf[1];

	/*
	 * Set up the timeout structure. Note that if there are no events to
	 * check for, we return with a negative result rather than blocking
    /*
     * Set up the timeout structure. Note that if there are no events to check
     * for, we return with a negative result rather than blocking forever.
	 * forever.
	 */
     */

	if (timePtr != NULL) {
	    /*
	     * TIP #233 (Virtualized Time). Is virtual time in effect? And do
	     * we actually have something to scale? If yes to both then we
	     * call the handler to do this scaling.
	     */
    if (timePtr != NULL) {
	/*
	 * TIP #233 (Virtualized Time). Is virtual time in effect? And do we
	 * actually have something to scale? If yes to both then we call the
	 * handler to do this scaling.
	 */

	    if (timePtr->sec != 0 || timePtr->usec != 0) {
		vTime = *timePtr;
		tclScaleTimeProcPtr(&vTime, tclTimeClientData);
		timePtr = &vTime;
	    }
	    timeout.tv_sec = timePtr->sec;
	    timeout.tv_usec = timePtr->usec;
	    timeoutPtr = &timeout;
	} else {
	    timeoutPtr = NULL;
	}
	if (timePtr->sec != 0 || timePtr->usec != 0) {
	    vTime = *timePtr;
	    TclScaleTime(&vTime);
	    timePtr = &vTime;
	}
	timeout.tv_sec = timePtr->sec;
	timeout.tv_usec = timePtr->usec;
	timeoutPtr = &timeout;
    } else {
	timeoutPtr = NULL;
    }

	/*
	 * Walk the list of FileHandlers associated with regular files
	 * (S_IFREG) belonging to tsdPtr, queue Tcl events for them, and
	 * update their mask of events of interest.
	 *
	 * kqueue(2), unlike epoll(7), does support regular files, but
	 * EVFILT_READ only `[r]eturns when the file pointer is not at the end
	 * of file' as opposed to unconditionally. While FreeBSD 11.0-RELEASE
	 * adds support for this mode (NOTE_FILE_POLL,) this is not used for
	 * reasons of compatibility.
	 *
	 * Therefore, the behaviour of {select,poll}(2) is simply simulated
	 * here: fds associated with regular files are added to this list by
	 * PlatformEventsControl() and processed here before calling (and
	 * possibly blocking) on PlatformEventsWait().
	 */
    /*
     * Walk the list of FileHandlers associated with regular files (S_IFREG)
     * belonging to tsdPtr, queue Tcl events for them, and update their mask
     * of events of interest.
     *
     * kqueue(2), unlike epoll(7), does support regular files, but EVFILT_READ
     * only `[r]eturns when the file pointer is not at the end of file' as
     * opposed to unconditionally. While FreeBSD 11.0-RELEASE adds support for
     * this mode (NOTE_FILE_POLL,) this is not used for reasons of
     * compatibility.
     *
     * Therefore, the behaviour of {select,poll}(2) is simply simulated here:
     * fds associated with regular files are added to this list by
     * PlatformEventsControl() and processed here before calling (and possibly
     * blocking) on PlatformEventsWait().
     */

	numQueued = 0;
	LIST_FOREACH(filePtr, &tsdPtr->firstReadyFileHandlerPtr, readyNode) {
	    mask = 0;
	    if (filePtr->mask & TCL_READABLE) {
		mask |= TCL_READABLE;
	    }
	    if (filePtr->mask & TCL_WRITABLE) {
		mask |= TCL_WRITABLE;
	    }
    numQueued = 0;
    LIST_FOREACH(filePtr, &tsdPtr->firstReadyFileHandlerPtr, readyNode) {
	mask = 0;
	if (filePtr->mask & TCL_READABLE) {
	    mask |= TCL_READABLE;
	}
	if (filePtr->mask & TCL_WRITABLE) {
	    mask |= TCL_WRITABLE;
	}

	    /*
	     * Don't bother to queue an event if the mask was previously
	     * non-zero since an event must still be on the queue.
	     */
	/*
	 * Don't bother to queue an event if the mask was previously non-zero
	 * since an event must still be on the queue.
	 */

	    if (filePtr->readyMask == 0) {
		FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)
			Tcl_Alloc(sizeof(FileHandlerEvent));
	if (filePtr->readyMask == 0) {
	    FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)
		    Tcl_Alloc(sizeof(FileHandlerEvent));

		fileEvPtr->header.proc = FileHandlerEventProc;
		fileEvPtr->fd = filePtr->fd;
		Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
		numQueued++;
	    }
	    filePtr->readyMask = mask;
	}
	    fileEvPtr->header.proc = FileHandlerEventProc;
	    fileEvPtr->fd = filePtr->fd;
	    Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
	    numQueued++;
	}
	filePtr->readyMask = mask;
    }

	/*
	 * If any events were queued in the above loop, force PlatformEvents-
	 * Wait() to poll as there already are events that need to be processed
	 * at this point.
	 */
    /*
     * If any events were queued in the above loop, force PlatformEventsWait()
     * to poll as there already are events that need to be processed at this
     * point.
     */

	if (numQueued) {
	    timeout.tv_sec = 0;
	    timeout.tv_usec = 0;
	    timeoutPtr = &timeout;
	}
    if (numQueued) {
	timeout.tv_sec = 0;
	timeout.tv_usec = 0;
	timeoutPtr = &timeout;
    }

	/*
	 * Wait or poll for new events, queue Tcl events for the FileHandlers
	 * corresponding to them, and update the FileHandlers' mask of events
	 * of interest registered by the last call to Tcl_CreateFileHandler().
	 *
	 * Events for the trigger pipe are processed here in order to facilitate
	 * inter-thread IPC. If another thread intends to wake up this thread
	 * whilst it's blocking on PlatformEventsWait(), it write(2)s to the
	 * other end of the pipe (see Tcl_AlertNotifier(),) which in turn will
	 * cause PlatformEventsWait() to return immediately.
	 */
    /*
     * Wait or poll for new events, queue Tcl events for the FileHandlers
     * corresponding to them, and update the FileHandlers' mask of events of
     * interest registered by the last call to Tcl_CreateFileHandler().
     *
     * Events for the trigger pipe are processed here in order to facilitate
     * inter-thread IPC. If another thread intends to wake up this thread
     * whilst it's blocking on PlatformEventsWait(), it write(2)s to the other
     * end of the pipe (see Tcl_AlertNotifier(),) which in turn will cause
     * PlatformEventsWait() to return immediately.
     */

	numFound = PlatformEventsWait(tsdPtr->readyEvents,
		tsdPtr->maxReadyEvents, timeoutPtr);
	for (numEvent = 0; numEvent < numFound; numEvent++) {
	    pedPtr = (struct PlatformEventData *)
		    tsdPtr->readyEvents[numEvent].udata;
	    filePtr = pedPtr->filePtr;
	    mask = PlatformEventsTranslate(&tsdPtr->readyEvents[numEvent]);
	    if (filePtr->fd == tsdPtr->triggerPipe[0]) {
		i = read(tsdPtr->triggerPipe[0], buf, 1);
		if ((i == -1) && (errno != EAGAIN)) {
		    Tcl_Panic("Tcl_WaitForEvent: read from %p->triggerPipe: %s",
			    (void *) tsdPtr, strerror(errno));
		}
		continue;
	    }
	    if (!mask) {
		continue;
	    }
    numFound = PlatformEventsWait(tsdPtr->readyEvents,
	    tsdPtr->maxReadyEvents, timeoutPtr);
    for (numEvent = 0; numEvent < numFound; numEvent++) {
	pedPtr = (struct PlatformEventData *)
		tsdPtr->readyEvents[numEvent].udata;
	filePtr = pedPtr->filePtr;
	mask = PlatformEventsTranslate(&tsdPtr->readyEvents[numEvent]);
	if (filePtr->fd == tsdPtr->triggerPipe[0]) {
	    i = read(tsdPtr->triggerPipe[0], buf, 1);
	    if ((i == -1) && (errno != EAGAIN)) {
		Tcl_Panic("Tcl_WaitForEvent: read from %p->triggerPipe: %s",
			tsdPtr, strerror(errno));
	    }
	    continue;
	}
	if (!mask) {
	    continue;
	}

	    /*
	     * Don't bother to queue an event if the mask was previously
	     * non-zero since an event must still be on the queue.
	     */
	/*
	 * Don't bother to queue an event if the mask was previously non-zero
	 * since an event must still be on the queue.
	 */

	    if (filePtr->readyMask == 0) {
		FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)
			Tcl_Alloc(sizeof(FileHandlerEvent));
	if (filePtr->readyMask == 0) {
	    FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)
		    Tcl_Alloc(sizeof(FileHandlerEvent));

		fileEvPtr->header.proc = FileHandlerEventProc;
		fileEvPtr->fd = filePtr->fd;
		Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
	    }
	    filePtr->readyMask |= mask;
	}
	return 0;
    }
}

	    fileEvPtr->header.proc = FileHandlerEventProc;
	    fileEvPtr->fd = filePtr->fd;
	    Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
	}
	filePtr->readyMask |= mask;
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TclAsyncNotifier --
 *
 *	This procedure sets the async mark of an async handler to a
 *	given value, if it is called from the target thread.
 *
 * Result:
 *	True, when the handler will be marked, false otherwise.
 *
 * Side effects:
 *	The signal may be resent to the target thread.
 *
 *----------------------------------------------------------------------
 */

int
TclAsyncNotifier(
    int sigNumber,		/* Signal number. */
    Tcl_ThreadId threadId,	/* Target thread. */
    void *clientData,	/* Notifier data. */
    int *flagPtr,		/* Flag to mark. */
    int value)			/* Value of mark. */
{
#if TCL_THREADS
    /*
     * WARNING:
     * This code most likely runs in a signal handler. Thus,
     * only few async-signal-safe system calls are allowed,
     * e.g. pthread_self(), sem_post(), write().
     */

    if (pthread_equal(pthread_self(), (pthread_t) threadId)) {
	ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;

	*flagPtr = value;
	if (tsdPtr != NULL && !tsdPtr->asyncPending) {
	    tsdPtr->asyncPending = 1;
	    TclpAlertNotifier(tsdPtr);
	    return 1;
	}
	return 0;
    }

    /*
     * Re-send the signal to the proper target thread.
     */

    pthread_kill((pthread_t) threadId, sigNumber);
#else
    (void)sigNumber;
    (void)threadId;
    (void)clientData;
    (void)flagPtr;
    (void)value;
#endif
    return 0;
}

#endif /* NOTIFIER_KQUEUE && TCL_THREADS */
#else
TCL_MAC_EMPTY_FILE(unix_tclKqueueNotfy_c)
#endif /* !HAVE_COREFOUNDATION */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to unix/tclLoadAix.c.

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
30
31
32
33
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
30
31
32
33











-
+













-
+







/*
 * tclLoadAix.c --
 *
 *	This file implements the dlopen and dlsym APIs under the AIX operating
 *	system, to enable the Tcl "load" command to work. This code was
 *	provided by Jens-Uwe Mager.
 *
 *	This file is subject to the following copyright notice, which is
 *	different from the notice used elsewhere in Tcl. The file has been
 *	modified to incorporate the file dlfcn.h in-line.
 *
 *	Copyright (c) 1992,1993,1995,1996, Jens-Uwe Mager, Helios Software GmbH
 *	Copyright © 1992,1993,1995,1996, Jens-Uwe Mager, Helios Software GmbH
 *	Not derived from licensed software.
 *
 *	Permission is granted to freely use, copy, modify, and redistribute
 *	this software, provided that the author is not construed to be liable
 *	for any results of using the software, alterations are clearly marked
 *	as such, and this notice is not modified.
 *
 * Note: this file has been altered from the original in a few ways in order
 * to work properly with Tcl.
 */

/*
 * @(#)dlfcn.c	1.7 revision of 95/08/14  19:08:38
 * This is an unpublished work copyright (c) 1992 HELIOS Software GmbH
 * This is an unpublished work copyright © 1992 HELIOS Software GmbH
 * 30159 Hannover, Germany
 */

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
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
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







-
+



















-
+







    /*
     * Scan the list of modules if we have the module already loaded.
     */

    for (mp = modList; mp; mp = mp->next) {
	if (strcmp(mp->name, path) == 0) {
	    mp->refCnt++;
	    return (void *) mp;
	    return (void *)mp;
	}
    }

    mp = (ModulePtr) calloc(1, sizeof(*mp));
    if (mp == NULL) {
	errvalid++;
	strcpy(errbuf, "calloc: ");
	strcat(errbuf, strerror(errno));
	return NULL;
    }

    mp->name = malloc(strlen(path) + 1);
    strcpy(mp->name, path);

    /*
     * load should be declared load(const char *...). Thus we cast the path to
     * a normal char *. Ugly.
     */

    mp->entry = (void *) load((char *)path, L_NOAUTODEFER, NULL);
    mp->entry = (void *)load((char *)path, L_NOAUTODEFER, NULL);
    if (mp->entry == NULL) {
	free(mp->name);
	free(mp);
	errvalid++;
	strcpy(errbuf, "dlopen: ");
	strcat(errbuf, path);
	strcat(errbuf, ": ");
227
228
229
230
231
232
233
234

235
236
237
238
239
240
241
227
228
229
230
231
232
233

234
235
236
237
238
239
240
241







-
+







	    mp->cdtors->init();
	    mp->cdtors++;
	}
    } else {
	errvalid = 0;
    }

    return (void *) mp;
    return (void *)mp;
}

/*
 * Attempt to decipher an AIX loader error message and append it to our static
 * error message buffer.
 */

249
250
251
252
253
254
255
256

257
258
259
260

261
262
263
264
265
266
267
249
250
251
252
253
254
255

256
257
258
259

260
261
262
263
264
265
266
267







-
+



-
+







	p++;
    }
    switch (atoi(s)) {		/* INTL: "C", UTF safe. */
    case L_ERROR_TOOMANY:
	strcat(errbuf, "to many errors");
	break;
    case L_ERROR_NOLIB:
	strcat(errbuf, "can't load library");
	strcat(errbuf, "cannot load library");
	strcat(errbuf, p);
	break;
    case L_ERROR_UNDEF:
	strcat(errbuf, "can't find symbol");
	strcat(errbuf, "cannot find symbol");
	strcat(errbuf, p);
	break;
    case L_ERROR_RLDBAD:
	strcat(errbuf, "bad RLD");
	strcat(errbuf, p);
	break;
    case L_ERROR_FORMAT:

Changes to unix/tclLoadDl.c.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tclLoadDl.c --
 *
 *	This procedure provides a version of the TclLoadFile that works with
 *	the "dlopen" and "dlsym" library procedures for dynamic loading.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#ifdef NO_DLFCN_H
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
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







-
+

-
+


-
+

-
+












-
+
+
+
+
+







     */

    native = (const char *)Tcl_FSGetNativePath(pathPtr);
    /*
     * Use (RTLD_NOW|RTLD_LOCAL) as default, see [Bug #3216070]
     */
    if (flags & TCL_LOAD_GLOBAL) {
    	dlopenflags |= RTLD_GLOBAL;
	dlopenflags |= RTLD_GLOBAL;
    } else {
    	dlopenflags |= RTLD_LOCAL;
	dlopenflags |= RTLD_LOCAL;
    }
    if (flags & TCL_LOAD_LAZY) {
    	dlopenflags |= RTLD_LAZY;
	dlopenflags |= RTLD_LAZY;
    } else {
    	dlopenflags |= RTLD_NOW;
	dlopenflags |= RTLD_NOW;
    }
    handle = dlopen(native, dlopenflags);
    if (handle == NULL) {
	/*
	 * Let the OS loader examine the binary search path for whatever
	 * string the user gave us which hopefully refers to a file on the
	 * binary path.
	 */

	Tcl_DString ds;
	const char *fileName = TclGetString(pathPtr);

	native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
	if (Tcl_UtfToExternalDStringEx(interp, NULL, fileName, TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	    Tcl_DStringFree(&ds);
	    return TCL_ERROR;
	}
	native = Tcl_DStringValue(&ds);
	/*
	 * Use (RTLD_NOW|RTLD_LOCAL) as default, see [Bug #3216070]
	 */
	handle = dlopen(native, dlopenflags);
	Tcl_DStringFree(&ds);
    }

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
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







-
+










-
+
+
+
+
+




-
+






-
+


-
-
+
+







    const char *symbol)		/* Symbol to look up. */
{
    const char *native;		/* Name of the library to be loaded, in
				 * system encoding */
    Tcl_DString newName, ds;	/* Buffers for converting the name to
				 * system encoding and prepending an
				 * underscore*/
    void *handle = (void *) loadHandle->clientData;
    void *handle = loadHandle->clientData;
				/* Native handle to the loaded library */
    void *proc;			/* Address corresponding to the resolved
				 * symbol */

    /*
     * Some platforms still add an underscore to the beginning of symbol
     * names. If we can't find a name without an underscore, try again with
     * the underscore.
     */

    native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
    if (Tcl_UtfToExternalDStringEx(interp, NULL, symbol, TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	Tcl_DStringFree(&ds);
	return NULL;
    }
    native = Tcl_DStringValue(&ds);
    proc = dlsym(handle, native);	/* INTL: Native. */
    if (proc == NULL) {
	Tcl_DStringInit(&newName);
	TclDStringAppendLiteral(&newName, "_");
	native = Tcl_DStringAppend(&newName, native, -1);
	native = Tcl_DStringAppend(&newName, native, TCL_INDEX_NONE);
	proc = dlsym(handle, native);	/* INTL: Native. */
	Tcl_DStringFree(&newName);
    }
#ifdef __cplusplus
    if (proc == NULL) {
	char buf[32];
	sprintf(buf, "%d", (int)Tcl_DStringLength(&ds));
	snprintf(buf, sizeof(buf), "%d", (int)Tcl_DStringLength(&ds));
	Tcl_DStringInit(&newName);
	TclDStringAppendLiteral(&newName, "__Z");
	Tcl_DStringAppend(&newName, buf, -1);
	Tcl_DStringAppend(&newName, Tcl_DStringValue(&ds), -1);
	Tcl_DStringAppend(&newName, buf, TCL_INDEX_NONE);
	Tcl_DStringAppend(&newName, Tcl_DStringValue(&ds), TCL_INDEX_NONE);
	TclDStringAppendLiteral(&newName, "P10Tcl_Interp");
	native = Tcl_DStringValue(&newName);
	proc = dlsym(handle, native + 1);	/* INTL: Native. */
	if (proc == NULL) {
	    proc = dlsym(handle, native);	/* INTL: Native. */
	}
	if (proc == NULL) {
220
221
222
223
224
225
226
227

228
229
230
231
232
233
234
228
229
230
231
232
233
234

235
236
237
238
239
240
241
242







-
+







	if (interp) {
	    if (!errorStr) {
		errorStr = "unknown";
	    }
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "cannot find symbol \"%s\": %s", symbol, errorStr));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol,
		    NULL);
		    (char *)NULL);
	}
    }
    return proc;
}

/*
 *----------------------------------------------------------------------
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
262
263
264
265
266
267
268




























269
270
271
272
273
274
275
276







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








				 * that represents the loaded file. */
{
    void *handle = loadHandle->clientData;

    dlclose(handle);
    Tcl_Free(loadHandle);
}

/*
 *----------------------------------------------------------------------
 *
 * TclGuessPackageName --
 *
 *	If the "load" command is invoked without providing a package name,
 *	this procedure is invoked to try to figure it out.
 *
 * Results:
 *	Always returns 0 to indicate that we couldn't figure out a package
 *	name; generic code will then try to guess the package from the file
 *	name. A return value of 1 would have meant that we figured out the
 *	package name and put it in bufPtr.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclGuessPackageName(
    TCL_UNUSED(const char *) /*fileName*/,
    TCL_UNUSED(Tcl_DString *))
{
    return 0;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to unix/tclLoadDyld.c.

1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17








-
-
+
+







/*
 * tclLoadDyld.c --
 *
 *	This procedure provides a version of the TclLoadFile that works with
 *	Apple's dyld dynamic loading.
 *	Original version of his file (superseded long ago) provided by
 *	Wilfredo Sanchez (wsanchez@apple.com).
 *
 * Copyright (c) 1995 Apple Computer, Inc.
 * Copyright (c) 2001-2007 Daniel A. Steffen <das@users.sourceforge.net>
 * Copyright © 1995 Apple Computer, Inc.
 * Copyright © 2001-2007 Daniel A. Steffen <das@users.sourceforge.net>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

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
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







-
+











-
+







 */

#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
static const char *
DyldOFIErrorMsg(
    int err)
{
    switch(err) {
    switch (err) {
    case NSObjectFileImageSuccess:
	return NULL;
    case NSObjectFileImageFailure:
	return "object file setup failure";
    case NSObjectFileImageInappropriateFile:
	return "not a Mach-O MH_BUNDLE file";
    case NSObjectFileImageArch:
	return "no object for this architecture";
    case NSObjectFileImageFormat:
	return "bad object file format";
    case NSObjectFileImageAccess:
	return "can't read object file";
	return "cannot read object file";
    default:
	return "unknown error";
    }
}
#endif /* TCL_DYLD_USE_NSMODULE || TCL_LOAD_FROM_MEMORY */

/*
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
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







-
-
+
+
+
+
+
+







-
+

-
+


-
+

-
+







    /*
     * First try the full path the user gave us. This is particularly
     * important if the cwd is inside a vfs, and we are trying to load using a
     * relative path.
     */

    nativePath = (const char *)Tcl_FSGetNativePath(pathPtr);
    nativeFileName = Tcl_UtfToExternalDString(NULL, TclGetString(pathPtr),
	    -1, &ds);
    if (Tcl_UtfToExternalDStringEx(interp, NULL, TclGetString(pathPtr),
	    TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	Tcl_DStringFree(&ds);
	return TCL_ERROR;
    }
    nativeFileName = Tcl_DStringValue(&ds);

#if TCL_DYLD_USE_DLFCN
    /*
     * Use (RTLD_NOW|RTLD_LOCAL) as default, see [Bug #3216070]
     */

    if (flags & TCL_LOAD_GLOBAL) {
    	dlopenflags |= RTLD_GLOBAL;
	dlopenflags |= RTLD_GLOBAL;
    } else {
    	dlopenflags |= RTLD_LOCAL;
	dlopenflags |= RTLD_LOCAL;
    }
    if (flags & TCL_LOAD_LAZY) {
    	dlopenflags |= RTLD_LAZY;
	dlopenflags |= RTLD_LAZY;
    } else {
    	dlopenflags |= RTLD_NOW;
	dlopenflags |= RTLD_NOW;
    }
    dlHandle = dlopen(nativePath, dlopenflags);
    if (!dlHandle) {
	/*
	 * Let the OS loader examine the binary search path for whatever string
	 * the user gave us which hopefully refers to a file on the binary
	 * path.
249
250
251
252
253
254
255

256
257





258
259
260
261
262
263
264
253
254
255
256
257
258
259
260


261
262
263
264
265
266
267
268
269
270
271
272







+
-
-
+
+
+
+
+







		 * attempt to load it as a MH_BUNDLE.
		 */

		err = NSCreateObjectFileImageFromFile(nativePath,
			&dyldObjFileImage);
		if (err == NSObjectFileImageSuccess && dyldObjFileImage) {
		    int nsflags = NSLINKMODULE_OPTION_RETURN_ON_ERROR;
		    if (!(flags & 1)) {
		    if (!(flags & 1)) nsflags |= NSLINKMODULE_OPTION_PRIVATE;
		    if (!(flags & 2)) nsflags |= NSLINKMODULE_OPTION_BINDNOW;
			nsflags |= NSLINKMODULE_OPTION_PRIVATE;
		    }
		    if (!(flags & 2)) {
			nsflags |= NSLINKMODULE_OPTION_BINDNOW;
		    }
		    module = NSLinkModule(dyldObjFileImage, nativePath, nsflags);
		    NSDestroyObjectFileImage(dyldObjFileImage);
		    if (module) {
			modulePtr = (Tcl_DyldModuleHandle *)Tcl_Alloc(sizeof(Tcl_DyldModuleHandle));
			modulePtr->module = module;
			modulePtr->nextPtr = NULL;
		    } else {
292
293
294
295
296
297
298
299

300
301
302
303
304
305
306
300
301
302
303
304
305
306

307
308
309
310
311
312
313
314







-
+







	*loadHandle = newHandle;
	result = TCL_OK;
    } else {
	Tcl_Obj *errObj;

	TclNewObj(errObj);
	if (errMsg != NULL) {
	    Tcl_AppendToObj(errObj, errMsg, -1);
	    Tcl_AppendToObj(errObj, errMsg, TCL_INDEX_NONE);
	}
#if TCL_DYLD_USE_NSMODULE
	if (objFileImageErrMsg) {
	    Tcl_AppendPrintfToObj(errObj,
		    "\nNSCreateObjectFileImageFromFile() error: %s",
		    objFileImageErrMsg);
	}
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
366
367
368
369
370
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







-
+




-
+
+
+
+
+


-
+















-
+







static void *
FindSymbol(
    Tcl_Interp *interp,		/* For error reporting. */
    Tcl_LoadHandle loadHandle,	/* Handle from TclpDlopen. */
    const char *symbol)		/* Symbol name to look up. */
{
    Tcl_DyldLoadHandle *dyldLoadHandle = (Tcl_DyldLoadHandle *)loadHandle->clientData;
    Tcl_PackageInitProc *proc = NULL;
    Tcl_LibraryInitProc *proc = NULL;
    const char *errMsg = NULL;
    Tcl_DString ds;
    const char *native;

    native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
    if (Tcl_UtfToExternalDStringEx(interp, NULL, symbol, TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	Tcl_DStringFree(&ds);
	return NULL;
    }
    native = Tcl_DStringValue(&ds);
    if (dyldLoadHandle->dlHandle) {
#if TCL_DYLD_USE_DLFCN
	proc = (Tcl_PackageInitProc *)dlsym(dyldLoadHandle->dlHandle, native);
	proc = (Tcl_LibraryInitProc *)dlsym(dyldLoadHandle->dlHandle, native);
	if (!proc) {
	    errMsg = dlerror();
	}
#endif /* TCL_DYLD_USE_DLFCN */
    } else {
#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
	NSSymbol nsSymbol = NULL;
	Tcl_DString newName;

	/*
	 * dyld adds an underscore to the beginning of symbol names.
	 */

	Tcl_DStringInit(&newName);
	TclDStringAppendLiteral(&newName, "_");
	native = Tcl_DStringAppend(&newName, native, -1);
	native = Tcl_DStringAppend(&newName, native, TCL_INDEX_NONE);
	if (dyldLoadHandle->dyldLibHeader) {
	    nsSymbol = NSLookupSymbolInImage(dyldLoadHandle->dyldLibHeader,
		    native, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW |
		    NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
	    if (nsSymbol) {
		/*
		 * Until dyld supports unloading of MY_DYLIB binaries, the
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
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







-
+









-
+







		NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg);
	    }
	} else if (dyldLoadHandle->modulePtr) {
	    nsSymbol = NSLookupSymbolInModule(
		    dyldLoadHandle->modulePtr->module, native);
	}
	if (nsSymbol) {
	    proc = (Tcl_PackageInitProc *)NSAddressOfSymbol(nsSymbol);
	    proc = (Tcl_LibraryInitProc *)NSAddressOfSymbol(nsSymbol);
	}
	Tcl_DStringFree(&newName);
#endif /* TCL_DYLD_USE_NSMODULE */
    }
    Tcl_DStringFree(&ds);
    if (errMsg && (interp != NULL)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"cannot find symbol \"%s\": %s", symbol, errMsg));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol,
		NULL);
		(char *)NULL);
    }
    return (void *)proc;
}

/*
 *----------------------------------------------------------------------
 *
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
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
476
477
478
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

















-
+







    Tcl_Free(dyldLoadHandle);
    Tcl_Free(loadHandle);
}

/*
 *----------------------------------------------------------------------
 *
 * TclGuessPackageName --
 *
 *	If the "load" command is invoked without providing a package name,
 *	this procedure is invoked to try to figure it out.
 *
 * Results:
 *	Always returns 0 to indicate that we couldn't figure out a package
 *	name; generic code will then try to guess the package from the file
 *	name. A return value of 1 would have meant that we figured out the
 *	package name and put it in bufPtr.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclGuessPackageName(
    TCL_UNUSED(const char *) /*fileName*/,
    TCL_UNUSED(Tcl_DString *) /*bufPtr*/)
{
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpLoadMemoryGetBuffer --
 *
 *	Allocate a buffer that can be used with TclpLoadMemory() below.
 *
 * Results:
 *	Pointer to allocated buffer or NULL if an error occurs.
 *
 * Side effects:
 *	Buffer is allocated.
 *
 *----------------------------------------------------------------------
 */

#ifdef TCL_LOAD_FROM_MEMORY
MODULE_SCOPE void *
TclpLoadMemoryGetBuffer(
    TCL_UNUSED(Tcl_Interp *),
    int size)			/* Size of desired buffer. */
    size_t size)			/* Size of desired buffer. */
{
    void *buffer = NULL;

    /*
     * NSCreateObjectFileImageFromMemory is available but always fails
     * prior to Darwin 7.
     */
556
557
558
559
560
561
562
563
564


565
566
567
568
569
570
571
540
541
542
543
544
545
546


547
548
549
550
551
552
553
554
555







-
-
+
+








#ifdef TCL_LOAD_FROM_MEMORY
MODULE_SCOPE int
TclpLoadMemory(
    Tcl_Interp *interp,		/* Used for error reporting. */
    void *buffer,		/* Buffer containing the desired code
				 * (allocated with TclpLoadMemoryGetBuffer). */
    int size,			/* Allocation size of buffer. */
    int codeSize,		/* Size of code data read into buffer or -1 if
    size_t size,		/* Allocation size of buffer. */
    Tcl_Size codeSize,	/* Size of code data read into buffer or -1 if
				 * an error occurred and the buffer should
				 * just be freed. */
    Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
				 * file which will be passed back to
				 * (*unloadProcPtr)() to unload the file. */
    Tcl_FSUnloadFileProc **unloadProcPtr,
				/* Filled with address of Tcl_FSUnloadFileProc
597
598
599
600
601
602
603
604

605
606
607
608
609
610
611
612

613
614
615
616
617
618
619
581
582
583
584
585
586
587

588
589
590
591
592
593
594
595

596
597
598
599
600
601
602
603







-
+







-
+







#else
	const struct mach_header_64 *mh = NULL;
#	define mh_size  sizeof(struct mach_header_64)
#	define mh_magic MH_MAGIC_64
#	define arch_abi CPU_ARCH_ABI64
#endif /*  __LP64__ */

	if ((size_t) codeSize >= sizeof(struct fat_header)
	if ((size_t)codeSize >= sizeof(struct fat_header)
		&& fh->magic == OSSwapHostToBigInt32(FAT_MAGIC)) {
	    uint32_t fh_nfat_arch = OSSwapBigToHostInt32(fh->nfat_arch);

	    /*
	     * Fat binary, try to find mach_header for our architecture
	     */

	    if ((size_t) codeSize >= sizeof(struct fat_header) +
	    if ((size_t)codeSize >= sizeof(struct fat_header) +
		    fh_nfat_arch * sizeof(struct fat_arch)) {
		void *fatarchs = (char *)buffer + sizeof(struct fat_header);
		const NXArchInfo *arch = NXGetLocalArchInfo();
		struct fat_arch *fa;

		if (fh->magic != FAT_MAGIC) {
		    swap_fat_arch((struct fat_arch *)fatarchs, fh_nfat_arch, arch->byteorder);
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
654
655
656
657
658
659
660
661


662
663
664
665
666
667
668
669
670
671
672
673
674

675
676
677
678
679
680
681
682







+
-
-
+
+
+
+
+








-
+







	return TCL_ERROR;
    }

    /*
     * Extract the module we want from the image of the object file.
     */

    if (!(flags & 1)) {
    if (!(flags & 1)) nsflags |= NSLINKMODULE_OPTION_PRIVATE;
    if (!(flags & 2)) nsflags |= NSLINKMODULE_OPTION_BINDNOW;
	nsflags |= NSLINKMODULE_OPTION_PRIVATE;
    }
    if (!(flags & 2)) {
	nsflags |= NSLINKMODULE_OPTION_BINDNOW;
    }
    module = NSLinkModule(dyldObjFileImage, "[Memory Based Bundle]", nsflags);
    NSDestroyObjectFileImage(dyldObjFileImage);
    if (!module) {
	NSLinkEditErrors editError;
	int errorNumber;
	const char *errorName, *errMsg;

	NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg);
	Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, -1));
	Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, TCL_INDEX_NONE));
	return TCL_ERROR;
    }

    /*
     * Stash the module reference within the load handle we create and return.
     */

Changes to unix/tclLoadNext.c.

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
30
31
32

33
34
35
36
37
38

39
40
41
42
43
44
45
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
30
31
32
33

34
35
36
37
38
39

40
41
42
43
44
45
46
47






-
+









+
-
+
+


-
+



-
+







-
+





-
+







/*
 * tclLoadNext.c --
 *
 *	This procedure provides a version of the TclLoadFile that works with
 *	NeXTs rld_* dynamic loading. This file provided by Pedja Bogdanovich.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include <mach-o/rld.h>
#include <streams/streams.h>

/*
/* Static procedures defined within this file */
 * Static procedures defined within this file.
 */

static void *		FindSymbol(Tcl_Interp *interp,
			    Tcl_LoadHandle loadHandle, const char* symbol);
			    Tcl_LoadHandle loadHandle, const char *symbol);
static void		UnloadFile(Tcl_LoadHandle loadHandle);

/*
 *----------------------------------------------------------------------
 *---------------------------------------------------------------------------
 *
 * TclpDlopen --
 *
 *	Dynamically loads a binary code file into memory and returns a handle
 *	to the new code.
 *
 * Results:
 *	A standard Tcl completion code.  If an error occurs, an error message
 *	A standard Tcl completion code. If an error occurs, an error message
 *	is left in the interp's result.
 *
 * Side effects:
 *	New code suddenly appears in memory.
 *
 *----------------------------------------------------------------------
 *---------------------------------------------------------------------------
 */

int
TclpDlopen(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Obj *pathPtr,		/* Name of the file containing the desired
				 * code (UTF-8). */
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
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







-
+




-
+
+
+
+
+

















-
+



-

+








    result = rld_load(errorStream, &header, files, NULL);

    if (!result) {
	/*
	 * Let the OS loader examine the binary search path for whatever
	 * string the user gave us which hopefully refers to a file on the
	 * binary path
	 * binary path.
	 */

	Tcl_DString ds;

	native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
	if (Tcl_UtfToExternalDStringEx(interp, NULL, fileName, TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	    Tcl_DStringFree(&ds);
	    return TCL_ERROR;
	}
	native = Tcl_DStringValue(&ds);
	files = {native,NULL};
	result = rld_load(errorStream, &header, files, NULL);
	Tcl_DStringFree(&ds);
    }

    if (!result) {
	char *data;
	int len, maxlen;

	NXGetMemoryBuffer(errorStream, &data, &len, &maxlen);
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"couldn't load file \"%s\": %s", fileName, data));
	NXCloseMemory(errorStream, NX_FREEBUFFER);
	return TCL_ERROR;
    }
    NXCloseMemory(errorStream, NX_FREEBUFFER);

    newHandle = (Tcl_LoadHandle) Tcl_Alloc(sizeof(*newHandle));
    newHandle = (Tcl_LoadHandle)Tcl_Alloc(sizeof(*newHandle));
    newHandle->clientData = INT2PTR(1);
    newHandle->findSymbolProcPtr = &FindSymbol;
    newHandle->unloadFileProcPtr = &UnloadFile;
    *loadHandle = newHandle;
    *unloadProcPtr = &UnloadFile;
    *loadHandle = newHandle;

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
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
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







-
+












-
+








static void *
FindSymbol(
    Tcl_Interp *interp,
    Tcl_LoadHandle loadHandle,
    const char *symbol)
{
    Tcl_PackageInitProc *proc = NULL;
    Tcl_LibraryInitProc *proc = NULL;

    if (symbol) {
	char sym[strlen(symbol) + 2];

	sym[0] = '_';
	sym[1] = 0;
	strcat(sym, symbol);
	rld_lookup(NULL, sym, (unsigned long *) &proc);
    }
    if (proc == NULL && interp != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"cannot find symbol \"%s\"", symbol));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol, NULL);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol, (char *)NULL);
    }
    return proc;
}

/*
 *----------------------------------------------------------------------
 *
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
171
172
173
174
175
176
177

178
179
180
181
182
183
184
185






























186
187
188
189
190
191
192
193







-
+







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








 *
 * Side effects:
 *	Does nothing.  Can anything be done?
 *
 *----------------------------------------------------------------------
 */

void
static void
UnloadFile(
    Tcl_LoadHandle loadHandle)	/* loadHandle returned by a previous call to
				 * TclpDlopen(). The loadHandle is a token
				 * that represents the loaded file. */
{
    Tcl_Free(loadHandle);
}

/*
 *----------------------------------------------------------------------
 *
 * TclGuessPackageName --
 *
 *	If the "load" command is invoked without providing a package name,
 *	this procedure is invoked to try to figure it out.
 *
 * Results:
 *	Always returns 0 to indicate that we couldn't figure out a package
 *	name; generic code will then try to guess the package from the file
 *	name. A return value of 1 would have meant that we figured out the
 *	package name and put it in bufPtr.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclGuessPackageName(
    const char *fileName,	/* Name of file containing package (already
				 * translated to local form if needed). */
    Tcl_DString *bufPtr)	/* Initialized empty dstring. Append package
				 * name to this if possible. */
{
    return 0;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to unix/tclLoadOSF.c.

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
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







-
+










-
+



-
-
+
+


-
+







-
+





-
+







 *			includes: MK6, MK7, AD2, AD3 (from OSF RI)
 *
 *	This approach to things was utter @&^#; thankfully, OSF/1 eventually
 *	supported dlopen().
 *
 *	John Robert LoVerso <loverso@freebsd.osf.org>
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include <sys/types.h>
#include <loader.h>

/*
 * Static functions defined within this file.
 * Static procedures defined within this file.
 */

static void *		FindSymbol(Tcl_Interp *interp,
			    Tcl_LoadHandle loadHandle, const char* symbol);
static void		UnloadFile(Tcl_LoadHandle handle);
			    Tcl_LoadHandle loadHandle, const char *symbol);
static void		UnloadFile(Tcl_LoadHandle loadHandle);

/*
 *----------------------------------------------------------------------
 *---------------------------------------------------------------------------
 *
 * TclpDlopen --
 *
 *	Dynamically loads a binary code file into memory and returns a handle
 *	to the new code.
 *
 * Results:
 *	A standard Tcl completion code.  If an error occurs, an error message
 *	A standard Tcl completion code. If an error occurs, an error message
 *	is left in the interp's result.
 *
 * Side effects:
 *	New code suddenly appears in memory.
 *
 *----------------------------------------------------------------------
 *---------------------------------------------------------------------------
 */

int
TclpDlopen(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Obj *pathPtr,		/* Name of the file containing the desired
				 * code (UTF-8). */
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
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







-
+





-
+










-
-
+
+
+
+
+
+







    Tcl_LoadHandle newHandle;
    ldr_module_t lm;
    char *pkg;
    char *fileName = TclGetString(pathPtr);
    const char *native;

    /*
     * First try the full path the user gave us.  This is particularly
     * First try the full path the user gave us. This is particularly
     * important if the cwd is inside a vfs, and we are trying to load using a
     * relative path.
     */

    native = Tcl_FSGetNativePath(pathPtr);
    lm = (Tcl_PackageInitProc *) load(native, LDR_NOFLAGS);
    lm = (Tcl_LibraryInitProc *) load(native, LDR_NOFLAGS);

    if (lm == LDR_NULL_MODULE) {
	/*
	 * Let the OS loader examine the binary search path for whatever
	 * string the user gave us which hopefully refers to a file on the
	 * binary path
	 */

	Tcl_DString ds;

	native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
	lm = (Tcl_PackageInitProc *) load(native, LDR_NOFLAGS);
	if (Tcl_UtfToExternalDStringEx(interp, NULL, fileName, TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	    Tcl_DStringFree(&ds);
	    return TCL_ERROR;
	}
	native = Tcl_DStringValue(&ds);
	lm = (Tcl_LibraryInitProc *) load(native, LDR_NOFLAGS);
	Tcl_DStringFree(&ds);
    }

    if (lm == LDR_NULL_MODULE) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"couldn't load file \"%s\": %s",
		fileName, Tcl_PosixError(interp)));
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
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







-
+







+

-
+













-
+











-
+

-
+


-
+

-
+







     * impossible to get a package name given a module.
     *
     * I build loadable modules with a makefile rule like
     *		ld ... -export $@: -o $@ $(OBJS)
     */

    if ((pkg = strrchr(fileName, '/')) == NULL) {
        pkg = fileName;
	pkg = fileName;
    } else {
	pkg++;
    }
    newHandle = (Tcl_LoadHandle)Tcl_Alloc(sizeof(*newHandle));
    newHandle->clientData = pkg;
    newHandle->findSymbolProcPtr = &FindSymbol;
    newHandle->unloadFileProcPtr = &UnloadFile;
    *unloadProcPtr = &UnloadFile;
    *loadHandle = newHandle;
    *unloadProcPtr = &UnloadFile;

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * FindSymbol --
 *
 *	Looks up a symbol, by name, through a handle associated with a
 *	previously loaded piece of code (shared library).
 *
 * Results:
 *	Returns a pointer to the function associated with 'symbol' if it is
 *	found.  Otherwise returns NULL and may leave an error message in the
 *	found. Otherwise returns NULL and may leave an error message in the
 *	interp's result.
 *
 *----------------------------------------------------------------------
 */

static void *
FindSymbol(
    Tcl_Interp *interp,
    Tcl_LoadHandle loadHandle,
    const char *symbol)
{
    void *retval = ldr_lookup_package((char *) loadHandle, symbol);
    void *proc = ldr_lookup_package((char *) loadHandle, symbol);

    if (retval == NULL && interp != NULL) {
    if (proc == NULL && interp != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"cannot find symbol \"%s\"", symbol));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol, NULL);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol, (char *)NULL);
    }
    return retval;
    return proc;
}

/*
 *----------------------------------------------------------------------
 *
 * UnloadFile --
 *
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
196
197
198
199
200
201
202






























203
204
205
206
207
208
209
210







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








UnloadFile(
    Tcl_LoadHandle loadHandle)	/* loadHandle returned by a previous call to
				 * TclpDlopen(). The loadHandle is a token
				 * that represents the loaded file. */
{
    Tcl_Free(loadHandle);
}

/*
 *----------------------------------------------------------------------
 *
 * TclGuessPackageName --
 *
 *	If the "load" command is invoked without providing a package name,
 *	this function is invoked to try to figure it out.
 *
 * Results:
 *	Always returns 0 to indicate that we couldn't figure out a package
 *	name; generic code will then try to guess the package from the file
 *	name.  A return value of 1 would have meant that we figured out the
 *	package name and put it in bufPtr.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclGuessPackageName(
    const char *fileName,	/* Name of file containing package (already
				 * translated to local form if needed). */
    Tcl_DString *bufPtr)	/* Initialized empty dstring. Append package
				 * name to this if possible. */
{
    return 0;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to unix/tclLoadShl.c.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







/*
 * tclLoadShl.c --
 *
 *	This procedure provides a version of the TclLoadFile that works with
 *	the "shl_load" and "shl_findsym" library procedures for dynamic
 *	loading (e.g. for HP machines).
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include <dl.h>
#include "tclInt.h"
27
28
29
30
31
32
33
34

35
36
37
38
39
40

41
42
43
44
45
46
47
27
28
29
30
31
32
33

34
35
36
37
38
39

40
41
42
43
44
45
46
47







-
+





-
+







 *
 * TclpDlopen --
 *
 *	Dynamically loads a binary code file into memory and returns a handle
 *	to the new code.
 *
 * Results:
 *	A standard Tcl completion code.  If an error occurs, an error message
 *	A standard Tcl completion code. If an error occurs, an error message
 *	is left in the interp's result.
 *
 * Side effects:
 *	New code suddenly appears in memory.
 *
 *----------------------------------------------------------------------
 *---------------------------------------------------------------------------
 */

int
TclpDlopen(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Obj *pathPtr,		/* Name of the file containing the desired
				 * code (UTF-8). */
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73







-
+







    const char *native;
    char *fileName = TclGetString(pathPtr);

    /*
     * The flags below used to be BIND_IMMEDIATE; they were changed at the
     * suggestion of Wolfgang Kechel (wolfgang@prs.de): "This enables
     * verbosity for missing symbols when loading a shared lib and allows to
     * load libtk8.0.sl into tclsh8.0 without problems.  In general, this
     * load libtk9.0.sl into tclsh9.0 without problems.  In general, this
     * delays resolving symbols until they are actually needed.  Shared libs
     * do no longer need all libraries linked in when they are build."
     */

    /*
     * First try the full path the user gave us.  This is particularly
     * important if the cwd is inside a vfs, and we are trying to load using a
82
83
84
85
86
87
88
89





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

89
90
91
92
93
94
95
96
97
98
99
100







-
+
+
+
+
+







	 * Let the OS loader examine the binary search path for whatever
	 * string the user gave us which hopefully refers to a file on the
	 * binary path.
	 */

	Tcl_DString ds;

	native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
	if (Tcl_UtfToExternalDStringEx(interp, NULL, fileName, TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	    Tcl_DStringFree(&ds);
	    return TCL_ERROR;
	}
	native = Tcl_DStringValue(&ds);
	handle = shl_load(native, BIND_DEFERRED|BIND_VERBOSE|DYNAMIC_PATH, 0L);
	Tcl_DStringFree(&ds);
    }

    if (handle == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"couldn't load file \"%s\": %s",
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
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







-
+








-
+


-
+

-
+







static void*
FindSymbol(
    Tcl_Interp *interp,
    Tcl_LoadHandle loadHandle,
    const char *symbol)
{
    Tcl_DString newName;
    Tcl_PackageInitProc *proc = NULL;
    Tcl_LibraryInitProc *proc = NULL;
    shl_t handle = (shl_t) loadHandle->clientData;

    /*
     * Some versions of the HP system software still use "_" at the beginning
     * of exported symbols while others don't; try both forms of each name.
     */

    if (shl_findsym(&handle, symbol, (short) TYPE_PROCEDURE,
	    (void *) &proc) != 0) {
	    (void *)&proc) != 0) {
	Tcl_DStringInit(&newName);
	TclDStringAppendLiteral(&newName, "_");
	Tcl_DStringAppend(&newName, symbol, -1);
	Tcl_DStringAppend(&newName, symbol, TCL_INDEX_NONE);
	if (shl_findsym(&handle, Tcl_DStringValue(&newName),
		(short) TYPE_PROCEDURE, (void *) &proc) != 0) {
		(short) TYPE_PROCEDURE, (void *)&proc) != 0) {
	    proc = NULL;
	}
	Tcl_DStringFree(&newName);
    }
    if (proc == NULL && interp != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"cannot find symbol \"%s\": %s",
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
184
185
186
187
188
189
190






























191
192
193
194
195
196
197
198







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








				 * that represents the loaded file. */
{
    shl_t handle = (shl_t) loadHandle->clientData;

    shl_unload(handle);
    Tcl_Free(loadHandle);
}

/*
 *----------------------------------------------------------------------
 *
 * TclGuessPackageName --
 *
 *	If the "load" command is invoked without providing a package name,
 *	this procedure is invoked to try to figure it out.
 *
 * Results:
 *	Always returns 0 to indicate that we couldn't figure out a package
 *	name; generic code will then try to guess the package from the file
 *	name. A return value of 1 would have meant that we figured out the
 *	package name and put it in bufPtr.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclGuessPackageName(
    const char *fileName,	/* Name of file containing package (already
				 * translated to local form if needed). */
    Tcl_DString *bufPtr)	/* Initialized empty dstring. Append package
				 * name to this if possible. */
{
    return 0;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to unix/tclSelectNotfy.c.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







/*
 * tclSelectNotfy.c --
 *
 *	This file contains the implementation of the select()-based generic
 *	Unix notifier, which is the lowest-level part of the Tcl event loop.
 *	This file works together with generic/tclNotify.c.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#ifndef HAVE_COREFOUNDATION	/* Darwin/Mac OS X CoreFoundation notifier is
28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
28
29
30
31
32
33
34

35
36
37
38
39
40
41
42







-
+







    int mask;			/* Mask of desired events: TCL_READABLE,
				 * etc. */
    int readyMask;		/* Mask of events that have been seen since
				 * the last time file handlers were invoked
				 * for this file. */
    Tcl_FileProc *proc;		/* Function to call, in the style of
				 * Tcl_CreateFileHandler. */
    ClientData clientData;	/* Argument to pass to proc. */
    void *clientData;	/* Argument to pass to proc. */
    struct FileHandler *nextPtr;/* Next in list of all files we care about. */
} FileHandler;

/*
 * The following structure contains a set of select() masks to track readable,
 * writable, and exception conditions.
 */
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
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







+















+
+
+
+
+
+



-
+







 * pipe. Hence writing to this file descriptor will cause the select() system
 * call to return and wake up the notifier thread.
 *
 * You must hold the notifierMutex lock before writing to the pipe.
 */

static int triggerPipe = -1;
static int otherPipe = -1;

/*
 * The notifierMutex locks access to all of the global notifier state.
 */

static pthread_mutex_t notifierInitMutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t notifierMutex     = PTHREAD_MUTEX_INITIALIZER;
/*
 * The following static indicates if the notifier thread is running.
 *
 * You must hold the notifierInitMutex before accessing this variable.
 */

static int notifierThreadRunning = 0;

/*
 * The following static flag indicates that async handlers are pending.
 */

static int asyncPending = 0;

/*
 * The notifier thread signals the notifierCV when it has finished
 * initializing the triggerPipe and right before the notifier thread
 * terminates.
 * terminates. This condition is used to deal with the signal mask, too.
 */

static pthread_cond_t notifierCV = PTHREAD_COND_INITIALIZER;

/*
 * The pollState bits:
 *
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
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







+
+
+
+
+
+
+
+
+
+







-
+


















-
-
+
+







#define POLL_DONE	0x2

/*
 * This is the thread ID of the notifier thread that does select.
 */

static Tcl_ThreadId notifierThread;

/*
 * Signal mask information for notifier thread.
 */

static sigset_t notifierSigMask;
#ifndef HAVE_PSELECT
static sigset_t allSigMask;
#endif /* HAVE_PSELECT */

#endif /* TCL_THREADS */

/*
 * Static routines defined in this file.
 */

#if TCL_THREADS
static TCL_NORETURN void NotifierThreadProc(ClientData clientData);
static TCL_NORETURN void NotifierThreadProc(void *clientData);
#if defined(HAVE_PTHREAD_ATFORK)
static int atForkInit = 0;
static void		AtForkChild(void);
#endif /* HAVE_PTHREAD_ATFORK */
#endif /* TCL_THREADS */
static int		FileHandlerEventProc(Tcl_Event *evPtr, int flags);

/*
 * Import of critical bits of Windows API when building threaded with Cygwin.
 */

#if defined(__CYGWIN__)
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
    void *hwnd;			/* Messaging window. */
    unsigned int *message;	/* Message payload. */
    size_t wParam;			/* Event-specific "word" parameter. */
    size_t lParam;			/* Event-specific "long" parameter. */
    size_t wParam;		/* Event-specific "word" parameter. */
    size_t lParam;		/* Event-specific "long" parameter. */
    int time;			/* Event timestamp. */
    int x;			/* Event location (where meaningful). */
    int y;
    int lPrivate;
} MSG;

typedef struct {
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
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
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
467
468


469
470
471
472
473
474
475
476
477
478
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



558
559
560
561
562
563
564
565
566
567









568
569
570
571



572
573
574


575
576
577
578
579
580
581
582
583
584
585










586
587
588
589



590
591
592
593
594
595
596
597
598








599
600

601
602
603
604
605
606
607
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
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
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
467
468
469
470
471
472
473
474

475
476
477
478
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
558
559
560









561
562
563
564
565
566
567
568
569
570



571
572
573
574


575
576
577










578
579
580
581
582
583
584
585
586
587
588



589
590
591
592








593
594
595
596
597
598
599
600


601
602
603
604
605
606
607
608







-
-
+
+


















+



+




-
-
+
+
+
+
+





-
+












-
-
+
+

-
-
-
-
+


-
+

-
-
-
-
+
+
+
+
+

-
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
+
+

-
+

-
-
-
-
+
+
+
+

-
-
+
+

-
-
-
-
-
+
+
+
+
+


-
-
+
+
-

-
-
+
+





-
+















-
-
+
+

-
-
-
-

-
+

-
-
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
+
+
+
+

-
+

-
+

-





-
+













-
+







-
+

-
-
-
-
-
-
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-






-
+













-
+



-
+
-
-
-
-
-
+
+
-

-
-
-
+
+
+

-
-
-
-
+
+
+
-
-
-
-
-
+

-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+

-
-
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
+







#ifdef __clang__
#pragma clang diagnostic ignored "-Wignored-attributes"
#endif
extern void __stdcall	CloseHandle(void *);
extern void *__stdcall	CreateEventW(void *, unsigned char, unsigned char,
			    void *);
extern void *__stdcall	CreateWindowExW(void *, const void *, const void *,
			    unsigned int, int, int, int, int, void *, void *, void *,
			    void *);
			    unsigned int, int, int, int, int, void *, void *,
			    void *, void *);
extern unsigned int __stdcall	DefWindowProcW(void *, int, void *, void *);
extern unsigned char __stdcall	DestroyWindow(void *);
extern int __stdcall	DispatchMessageW(const MSG *);
extern unsigned char __stdcall	GetMessageW(MSG *, void *, int, int);
extern void __stdcall	MsgWaitForMultipleObjects(unsigned int, void *,
			    unsigned char, unsigned int, unsigned int);
extern unsigned char __stdcall	PeekMessageW(MSG *, void *, int, int, int);
extern unsigned char __stdcall	PostMessageW(void *, unsigned int, void *,
				    void *);
extern void __stdcall	PostQuitMessage(int);
extern void *__stdcall	RegisterClassW(const WNDCLASSW *);
extern unsigned char __stdcall	ResetEvent(void *);
extern unsigned char __stdcall	TranslateMessage(const MSG *);

/*
 * Threaded-cygwin specific constants and functions in this file:
 */

#if TCL_THREADS && defined(__CYGWIN__)
static const wchar_t className[] = L"TclNotifier";
static unsigned int __stdcall	NotifierProc(void *hwnd, unsigned int message,
			    void *wParam, void *lParam);
#endif /* TCL_THREADS && defined(__CYGWIN__) */
#ifdef __cplusplus
}
#endif
#endif /* TCL_THREADS && __CYGWIN__ */



/*
 * Incorporate the base notifier implementation.
 */

#include "tclUnixNotfy.c"

/*
 *----------------------------------------------------------------------
 *
 * Tcl_InitNotifier --
 * TclpInitNotifier --
 *
 *	Initializes the platform specific notifier state.
 *
 * Results:
 *	Returns a handle to the notifier state for this thread.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

ClientData
Tcl_InitNotifier(void)
void *
TclpInitNotifier(void)
{
    if (tclNotifierHooks.initNotifierProc) {
	return tclNotifierHooks.initNotifierProc();
    } else {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

#if TCL_THREADS
	tsdPtr->eventReady = 0;
    tsdPtr->eventReady = 0;

	/*
	 * Initialize thread specific condition variable for this thread.
	 */
	if (tsdPtr->waitCVinitialized == 0) {
    /*
     * Initialize thread specific condition variable for this thread.
     */

    if (tsdPtr->waitCVinitialized == 0) {
#ifdef __CYGWIN__
	    WNDCLASSW clazz;
	WNDCLASSW clazz;

	    clazz.style = 0;
	    clazz.cbClsExtra = 0;
	    clazz.cbWndExtra = 0;
	    clazz.hInstance = TclWinGetTclInstance();
	    clazz.hbrBackground = NULL;
	    clazz.lpszMenuName = NULL;
	    clazz.lpszClassName = className;
	    clazz.lpfnWndProc = (void *)NotifierProc;
	    clazz.hIcon = NULL;
	    clazz.hCursor = NULL;
	clazz.style = 0;
	clazz.cbClsExtra = 0;
	clazz.cbWndExtra = 0;
	clazz.hInstance = TclWinGetTclInstance();
	clazz.hbrBackground = NULL;
	clazz.lpszMenuName = NULL;
	clazz.lpszClassName = className;
	clazz.lpfnWndProc = (void *)NotifierProc;
	clazz.hIcon = NULL;
	clazz.hCursor = NULL;

	    RegisterClassW(&clazz);
	    tsdPtr->hwnd = CreateWindowExW(NULL, clazz.lpszClassName,
		    clazz.lpszClassName, 0, 0, 0, 0, 0, NULL, NULL,
		    clazz.hInstance, NULL);
	    tsdPtr->event = CreateEventW(NULL, 1 /* manual */,
		    0 /* !signaled */, NULL);
#else
	    pthread_cond_init(&tsdPtr->waitCV, NULL);
	RegisterClassW(&clazz);
	tsdPtr->hwnd = CreateWindowExW(NULL, clazz.lpszClassName,
		clazz.lpszClassName, 0, 0, 0, 0, 0, NULL, NULL,
		clazz.hInstance, NULL);
	tsdPtr->event = CreateEventW(NULL, 1 /* manual */,
		0 /* !signaled */, NULL);
#else /* !__CYGWIN__ */
	pthread_cond_init(&tsdPtr->waitCV, NULL);
#endif /* __CYGWIN__ */
	    tsdPtr->waitCVinitialized = 1;
	}
	tsdPtr->waitCVinitialized = 1;
    }

	pthread_mutex_lock(&notifierInitMutex);
    pthread_mutex_lock(&notifierInitMutex);
#if defined(HAVE_PTHREAD_ATFORK)
	/*
	 * Install pthread_atfork handlers to clean up the notifier in the
	 * child of a fork.
	 */
    /*
     * Install pthread_atfork handlers to clean up the notifier in the child
     * of a fork.
     */

	if (!atForkInit) {
	    int result = pthread_atfork(NULL, NULL, AtForkChild);
    if (!atForkInit) {
	int result = pthread_atfork(NULL, NULL, AtForkChild);

	    if (result) {
		Tcl_Panic("Tcl_InitNotifier: pthread_atfork failed");
	    }
	    atForkInit = 1;
	}
	if (result) {
	    Tcl_Panic("Tcl_InitNotifier: %s", "pthread_atfork failed");
	}
	atForkInit = 1;
    }
#endif /* HAVE_PTHREAD_ATFORK */

	notifierCount++;
	pthread_mutex_unlock(&notifierInitMutex);
    notifierCount++;
    pthread_mutex_unlock(&notifierInitMutex);

#endif /* TCL_THREADS */
	return tsdPtr;
    }

    return tsdPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FinalizeNotifier --
 * TclpFinalizeNotifier --
 *
 *	This function is called to cleanup the notifier state before a thread
 *	is terminated.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	May terminate the background notifier thread if this is the last
 *	notifier instance.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_FinalizeNotifier(
    ClientData clientData)
TclpFinalizeNotifier(
    TCL_UNUSED(void *))
{
    if (tclNotifierHooks.finalizeNotifierProc) {
	tclNotifierHooks.finalizeNotifierProc(clientData);
	return;
    } else {
#if TCL_THREADS
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	pthread_mutex_lock(&notifierInitMutex);
	notifierCount--;
    pthread_mutex_lock(&notifierInitMutex);
    notifierCount--;

	/*
	 * If this is the last thread to use the notifier, close the notifier
	 * pipe and wait for the background thread to terminate.
	 */
    /*
     * If this is the last thread to use the notifier, close the notifier pipe
     * and wait for the background thread to terminate.
     */

	if (notifierCount == 0 && triggerPipe != -1) {
	    if (write(triggerPipe, "q", 1) != 1) {
		Tcl_Panic("Tcl_FinalizeNotifier: %s",
			"unable to write 'q' to triggerPipe");
	    }
	    close(triggerPipe);
	    pthread_mutex_lock(&notifierMutex);
	    while(triggerPipe != -1) {
		pthread_cond_wait(&notifierCV, &notifierMutex);
	    }
	    pthread_mutex_unlock(&notifierMutex);
	    if (notifierThreadRunning) {
		int result = pthread_join((pthread_t) notifierThread, NULL);
    if (notifierCount == 0 && triggerPipe != -1) {
	if (write(triggerPipe, "q", 1) != 1) {
	    Tcl_Panic("Tcl_FinalizeNotifier: %s",
		    "unable to write 'q' to triggerPipe");
	}
	close(triggerPipe);
	pthread_mutex_lock(&notifierMutex);
	while(triggerPipe != -1) {
	    pthread_cond_wait(&notifierCV, &notifierMutex);
	}
	pthread_mutex_unlock(&notifierMutex);
	if (notifierThreadRunning) {
	    int result = pthread_join((pthread_t) notifierThread, NULL);

		if (result) {
		    Tcl_Panic("Tcl_FinalizeNotifier: %s",
			    "unable to join notifier thread");
		}
		notifierThreadRunning = 0;
	    }
	}

	/*
	 * Clean up any synchronization objects in the thread local storage.
	 */
	    if (result) {
		Tcl_Panic("Tcl_FinalizeNotifier: %s",
			"unable to join notifier thread");
	    }
	    notifierThreadRunning = 0;

	    /*
	     * If async marks are outstanding, perform actions now.
	     */
	    if (asyncPending) {
		asyncPending = 0;
		TclAsyncMarkFromNotifier();
	    }
	}
    }

    /*
     * Clean up any synchronization objects in the thread local storage.
     */

#ifdef __CYGWIN__
	DestroyWindow(tsdPtr->hwnd);
	CloseHandle(tsdPtr->event);
#else /* __CYGWIN__ */
	pthread_cond_destroy(&tsdPtr->waitCV);
    DestroyWindow(tsdPtr->hwnd);
    CloseHandle(tsdPtr->event);
#else /* !__CYGWIN__ */
    pthread_cond_destroy(&tsdPtr->waitCV);
#endif /* __CYGWIN__ */
	tsdPtr->waitCVinitialized = 0;
    tsdPtr->waitCVinitialized = 0;

	pthread_mutex_unlock(&notifierInitMutex);
    pthread_mutex_unlock(&notifierInitMutex);
#endif /* TCL_THREADS */
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_CreateFileHandler --
 * TclpCreateFileHandler --
 *
 *	This function registers a file handler with the select notifier.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Creates a new file handler structure.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_CreateFileHandler(
TclpCreateFileHandler(
    int fd,			/* Handle of stream to watch. */
    int mask,			/* OR'ed combination of TCL_READABLE,
				 * TCL_WRITABLE, and TCL_EXCEPTION: indicates
				 * conditions under which proc should be
				 * called. */
    Tcl_FileProc *proc,		/* Function to call for each selected
				 * event. */
    ClientData clientData)	/* Arbitrary data to pass to proc. */
    void *clientData)	/* Arbitrary data to pass to proc. */
{
    if (tclNotifierHooks.createFileHandlerProc) {
	tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData);
	return;
    } else {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
	FileHandler *filePtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    FileHandler *filePtr = LookUpFileHandler(tsdPtr, fd, NULL);

	for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
		filePtr = filePtr->nextPtr) {
	    if (filePtr->fd == fd) {
		break;
	    }
	}
	if (filePtr == NULL) {
	    filePtr = (FileHandler *)Tcl_Alloc(sizeof(FileHandler));
	    filePtr->fd = fd;
	    filePtr->readyMask = 0;
	    filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
	    tsdPtr->firstFileHandlerPtr = filePtr;
	}
	filePtr->proc = proc;
	filePtr->clientData = clientData;
	filePtr->mask = mask;
    if (filePtr == NULL) {
	filePtr = (FileHandler *) Tcl_Alloc(sizeof(FileHandler));
	filePtr->fd = fd;
	filePtr->readyMask = 0;
	filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
	tsdPtr->firstFileHandlerPtr = filePtr;
    }
    filePtr->proc = proc;
    filePtr->clientData = clientData;
    filePtr->mask = mask;

	/*
	 * Update the check masks for this file.
	 */
    /*
     * Update the check masks for this file.
     */

	if (mask & TCL_READABLE) {
	    FD_SET(fd, &tsdPtr->checkMasks.readable);
	} else {
	    FD_CLR(fd, &tsdPtr->checkMasks.readable);
	}
	if (mask & TCL_WRITABLE) {
	    FD_SET(fd, &tsdPtr->checkMasks.writable);
	} else {
	    FD_CLR(fd, &tsdPtr->checkMasks.writable);
	}
	if (mask & TCL_EXCEPTION) {
	    FD_SET(fd, &tsdPtr->checkMasks.exception);
	} else {
	    FD_CLR(fd, &tsdPtr->checkMasks.exception);
	}
	if (tsdPtr->numFdBits <= fd) {
	    tsdPtr->numFdBits = fd+1;
    if (mask & TCL_READABLE) {
	FD_SET(fd, &tsdPtr->checkMasks.readable);
    } else {
	FD_CLR(fd, &tsdPtr->checkMasks.readable);
    }
    if (mask & TCL_WRITABLE) {
	FD_SET(fd, &tsdPtr->checkMasks.writable);
    } else {
	FD_CLR(fd, &tsdPtr->checkMasks.writable);
    }
    if (mask & TCL_EXCEPTION) {
	FD_SET(fd, &tsdPtr->checkMasks.exception);
    } else {
	FD_CLR(fd, &tsdPtr->checkMasks.exception);
    }
    if (tsdPtr->numFdBits <= fd) {
	tsdPtr->numFdBits = fd + 1;
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DeleteFileHandler --
 * TclpDeleteFileHandler --
 *
 *	Cancel a previously-arranged callback arrangement for a file.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	If a callback was previously registered on file, remove it.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_DeleteFileHandler(
TclpDeleteFileHandler(
    int fd)			/* Stream id for which to remove callback
				 * function. */
{
    if (tclNotifierHooks.deleteFileHandlerProc) {
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
	tclNotifierHooks.deleteFileHandlerProc(fd);
	return;
    } else {
	FileHandler *filePtr, *prevPtr;
	int i;
    FileHandler *filePtr, *prevPtr;
    int i;
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	/*
	 * Find the entry for the given file (and return if there isn't one).
	 */
    /*
     * Find the entry for the given file (and return if there isn't one).
     */

	for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
		prevPtr = filePtr, filePtr = filePtr->nextPtr) {
	    if (filePtr == NULL) {
		return;
    filePtr = LookUpFileHandler(tsdPtr, fd, &prevPtr);
    if (filePtr == NULL) {
	return;
	    }
	    if (filePtr->fd == fd) {
		break;
	    }
	}
    }

	/*
	 * Update the check masks for this file.
	 */
    /*
     * Update the check masks for this file.
     */

	if (filePtr->mask & TCL_READABLE) {
	    FD_CLR(fd, &tsdPtr->checkMasks.readable);
	}
	if (filePtr->mask & TCL_WRITABLE) {
	    FD_CLR(fd, &tsdPtr->checkMasks.writable);
	}
	if (filePtr->mask & TCL_EXCEPTION) {
	    FD_CLR(fd, &tsdPtr->checkMasks.exception);
	}
    if (filePtr->mask & TCL_READABLE) {
	FD_CLR(fd, &tsdPtr->checkMasks.readable);
    }
    if (filePtr->mask & TCL_WRITABLE) {
	FD_CLR(fd, &tsdPtr->checkMasks.writable);
    }
    if (filePtr->mask & TCL_EXCEPTION) {
	FD_CLR(fd, &tsdPtr->checkMasks.exception);
    }

	/*
	 * Find current max fd.
	 */
    /*
     * Find current max fd.
     */

	if (fd+1 == tsdPtr->numFdBits) {
	    int numFdBits = 0;
    if (fd + 1 == tsdPtr->numFdBits) {
	int numFdBits = 0;

	    for (i = fd-1; i >= 0; i--) {
		if (FD_ISSET(i, &tsdPtr->checkMasks.readable)
			|| FD_ISSET(i, &tsdPtr->checkMasks.writable)
			|| FD_ISSET(i, &tsdPtr->checkMasks.exception)) {
		    numFdBits = i+1;
		    break;
		}
	    }
	    tsdPtr->numFdBits = numFdBits;
	}
	for (i = fd - 1; i >= 0; i--) {
	    if (FD_ISSET(i, &tsdPtr->checkMasks.readable)
		    || FD_ISSET(i, &tsdPtr->checkMasks.writable)
		    || FD_ISSET(i, &tsdPtr->checkMasks.exception)) {
		numFdBits = i + 1;
		break;
	    }
	}
	tsdPtr->numFdBits = numFdBits;
    }

	/*
	 * Clean up information in the callback record.
	 */
    /*
     * Clean up information in the callback record.
     */

	if (prevPtr == NULL) {
	    tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
	} else {
	    prevPtr->nextPtr = filePtr->nextPtr;
	}
	Tcl_Free(filePtr);
    }
}
    if (prevPtr == NULL) {
	tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
    } else {
	prevPtr->nextPtr = filePtr->nextPtr;
    }
    Tcl_Free(filePtr);
}


#if defined(__CYGWIN__)
#if TCL_THREADS && defined(__CYGWIN__)

static unsigned int __stdcall
NotifierProc(
    void *hwnd,
    unsigned int message,
    void *wParam,
    void *lParam)
621
622
623
624
625
626
627
628

629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644

645
646
647
648
649
650
651
652
653




654
655

656
657

658
659
660
661
662
663
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
707
708
709
710
711
712
713







714
715

716
717

718
719
720
721
722
723
724
725
726








727
728
729
730
731
732
733
734
735








736
737
738
739
740
741
742
743







744
745
746
747
748
749
750






751
752
753
754
755
756
757
758







759
760
761
762
763
764





765
766
767
768



769
770

771
772
773


774
775
776
777
778
779
780
781
782
783









784
785
786
787



788
789
790
791
792




793
794
795
796
797




798
799
800


801
802
803
804
805
806




807
808

809
810
811
812
813
814
815
816
817
818









819
820
821
822
823
824
825
826
827







828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843















844
845
846
847
848




849
850
851
852
853




854
855
856
857
858
859





860
861
862
863
864



865
866
867
868
869
870
871
872
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






898
899

900
901
902































































903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920



921
922
923
924
925
926
927
928
929
930
931
932

933
934
935
936
937
938
939

940
941
942
943
944
945
946
947








948
949
950
951
952
953
954
622
623
624
625
626
627
628

629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644

645
646
647







648
649
650
651
652

653
654

655
656
657





658
659
660
661
662
663


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
707
708
709
710
711
712

713
714

715
716








717
718
719
720
721
722
723
724
725








726
727
728
729
730
731
732
733
734







735
736
737
738
739
740
741
742






743
744
745
746
747
748
749







750
751
752
753
754
755
756
757





758
759
760
761
762
763



764
765
766
767

768
769


770
771
772









773
774
775
776
777
778
779
780
781
782



783
784
785
786




787
788
789
790
791




792
793
794
795
796


797
798
799
800




801
802
803
804
805

806
807









808
809
810
811
812
813
814
815
816
817
818







819
820
821
822
823
824
825
826















827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842




843
844
845
846
847




848
849
850
851
852





853
854
855
856
857
858
859



860
861
862
863












864
865
866
867
868
869
870
871
872
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
898


899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
1016
1017
1018
1019
1020
1021







-
+















-
+


-
-
-
-
-
-
-
+
+
+
+

-
+

-
+


-
-
-
-
-
+
+
+
+
+

-
-
+
+


-
-
-
+
+
+
-
-
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+

-
+


-
-
-
-
-
-
+
+
+
+
+
+
+

-
+

-
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
+
+
+

-
+

-
-
+
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+

-
-
+
+


-
-
-
-
+
+
+
+

-
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
+
+
+
+
+


-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+

-
-
-
-
+
+
+
+

-
-
-
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
















-
-
+
+
+











-
+





-
-
+








+
+
+
+
+
+
+
+







    return 0;
}
#endif /* TCL_THREADS && __CYGWIN__ */

/*
 *----------------------------------------------------------------------
 *
 * Tcl_WaitForEvent --
 * TclpWaitForEvent --
 *
 *	This function is called by Tcl_DoOneEvent to wait for new events on
 *	the message queue. If the block time is 0, then Tcl_WaitForEvent just
 *	polls without blocking.
 *
 * Results:
 *	Returns -1 if the select would block forever, otherwise returns 0.
 *
 * Side effects:
 *	Queues file events that are detected by the select.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_WaitForEvent(
TclpWaitForEvent(
    const Tcl_Time *timePtr)		/* Maximum block time, or NULL. */
{
    if (tclNotifierHooks.waitForEventProc) {
	return tclNotifierHooks.waitForEventProc(timePtr);
    } else {
	FileHandler *filePtr;
	int mask;
	Tcl_Time vTime;
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    FileHandler *filePtr;
    int mask;
    Tcl_Time vTime;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
#if TCL_THREADS
	int waitForFiles;
    int waitForFiles;
#   ifdef __CYGWIN__
	MSG msg;
    MSG msg;
#   endif /* __CYGWIN__ */
#else /* !TCL_THREADS */
	/*
	 * Impl. notes: timeout & timeoutPtr are used if, and only if threads
	 * are not enabled. They are the arguments for the regular select()
	 * used when the core is not thread-enabled.
	 */
    /*
     * Impl. notes: timeout & timeoutPtr are used if, and only if threads are
     * not enabled. They are the arguments for the regular select() used when
     * the core is not thread-enabled.
     */

	struct timeval timeout, *timeoutPtr;
	int numFound;
    struct timeval timeout, *timeoutPtr;
    int numFound;
#endif /* TCL_THREADS */

	/*
	 * Set up the timeout structure. Note that if there are no events to
	 * check for, we return with a negative result rather than blocking
    /*
     * Set up the timeout structure. Note that if there are no events to check
     * for, we return with a negative result rather than blocking forever.
	 * forever.
	 */
     */

	if (timePtr != NULL) {
	    /*
	     * TIP #233 (Virtualized Time). Is virtual time in effect? And do
	     * we actually have something to scale? If yes to both then we
	     * call the handler to do this scaling.
	     */
    if (timePtr != NULL) {
	/*
	 * TIP #233 (Virtualized Time). Is virtual time in effect? And do we
	 * actually have something to scale? If yes to both then we call the
	 * handler to do this scaling.
	 */

	    if (timePtr->sec != 0 || timePtr->usec != 0) {
		vTime = *timePtr;
		tclScaleTimeProcPtr(&vTime, tclTimeClientData);
		timePtr = &vTime;
	    }
	if (timePtr->sec != 0 || timePtr->usec != 0) {
	    vTime = *timePtr;
	    TclScaleTime(&vTime);
	    timePtr = &vTime;
	}
#if !TCL_THREADS
	    timeout.tv_sec = timePtr->sec;
	    timeout.tv_usec = timePtr->usec;
	    timeoutPtr = &timeout;
	} else if (tsdPtr->numFdBits == 0) {
	    /*
	     * If there are no threads, no timeout, and no fds registered,
	     * then there are no events possible and we must avoid deadlock.
	     * Note that this is not entirely correct because there might be a
	     * signal that could interrupt the select call, but we don't
	     * handle that case if we aren't using threads.
	     */
	timeout.tv_sec = timePtr->sec;
	timeout.tv_usec = timePtr->usec;
	timeoutPtr = &timeout;
    } else if (tsdPtr->numFdBits == 0) {
	/*
	 * If there are no threads, no timeout, and no fds registered, then
	 * there are no events possible and we must avoid deadlock.  Note that
	 * this is not entirely correct because there might be a signal that
	 * could interrupt the select call, but we don't handle that case if
	 * we aren't using threads.
	 */

	    return -1;
	} else {
	    timeoutPtr = NULL;
	return -1;
    } else {
	timeoutPtr = NULL;
#endif /* !TCL_THREADS */
	}
    }

#if TCL_THREADS
	/*
	 * Start notifier thread and place this thread on the list of
	 * interested threads, signal the notifier thread, and wait for a
	 * response or a timeout.
	 */
	StartNotifierThread("Tcl_WaitForEvent");
    /*
     * Start notifier thread and place this thread on the list of interested
     * threads, signal the notifier thread, and wait for a response or a
     * timeout.
     */

    StartNotifierThread("Tcl_WaitForEvent");

	pthread_mutex_lock(&notifierMutex);
    pthread_mutex_lock(&notifierMutex);

	if (timePtr != NULL && timePtr->sec == 0 && (timePtr->usec == 0
    if (timePtr != NULL && timePtr->sec == 0 && (timePtr->usec == 0
#if defined(__APPLE__) && defined(__LP64__)
		/*
		 * On 64-bit Darwin, pthread_cond_timedwait() appears to have
		 * a bug that causes it to wait forever when passed an
		 * absolute time which has already been exceeded by the system
		 * time; as a workaround, when given a very brief timeout,
		 * just do a poll. [Bug 1457797]
		 */
		|| timePtr->usec < 10
	    /*
	     * On 64-bit Darwin, pthread_cond_timedwait() appears to have a
	     * bug that causes it to wait forever when passed an absolute time
	     * which has already been exceeded by the system time; as a
	     * workaround, when given a very brief timeout, just do a poll.
	     * [Bug 1457797]
	     */
	    || timePtr->usec < 10
#endif /* __APPLE__ && __LP64__ */
		)) {
	    /*
	     * Cannot emulate a polling select with a polling condition
	     * variable. Instead, pretend to wait for files and tell the
	     * notifier thread what we are doing. The notifier thread makes
	     * sure it goes through select with its select mask in the same
	     * state as ours currently is. We block until that happens.
	     */
	    )) {
	/*
	 * Cannot emulate a polling select with a polling condition variable.
	 * Instead, pretend to wait for files and tell the notifier thread
	 * what we are doing. The notifier thread makes sure it goes through
	 * select with its select mask in the same state as ours currently is.
	 * We block until that happens.
	 */

	    waitForFiles = 1;
	    tsdPtr->pollState = POLL_WANT;
	    timePtr = NULL;
	} else {
	    waitForFiles = (tsdPtr->numFdBits > 0);
	    tsdPtr->pollState = 0;
	}
	waitForFiles = 1;
	tsdPtr->pollState = POLL_WANT;
	timePtr = NULL;
    } else {
	waitForFiles = (tsdPtr->numFdBits > 0);
	tsdPtr->pollState = 0;
    }

	if (waitForFiles) {
	    /*
	     * Add the ThreadSpecificData structure of this thread to the list
	     * of ThreadSpecificData structures of all threads that are
	     * waiting on file events.
	     */
    if (waitForFiles) {
	/*
	 * Add the ThreadSpecificData structure of this thread to the list of
	 * ThreadSpecificData structures of all threads that are waiting on
	 * file events.
	 */

	    tsdPtr->nextPtr = waitingListPtr;
	    if (waitingListPtr) {
		waitingListPtr->prevPtr = tsdPtr;
	    }
	    tsdPtr->prevPtr = 0;
	    waitingListPtr = tsdPtr;
	    tsdPtr->onList = 1;
	tsdPtr->nextPtr = waitingListPtr;
	if (waitingListPtr) {
	    waitingListPtr->prevPtr = tsdPtr;
	}
	tsdPtr->prevPtr = 0;
	waitingListPtr = tsdPtr;
	tsdPtr->onList = 1;

	    if ((write(triggerPipe, "", 1) == -1) && (errno != EAGAIN)) {
		Tcl_Panic("Tcl_WaitForEvent: %s",
			"unable to write to triggerPipe");
	    }
	}
	if ((write(triggerPipe, "", 1) == -1) && (errno != EAGAIN)) {
	    Tcl_Panic("Tcl_WaitForEvent: %s",
		    "unable to write to triggerPipe");
	}
    }

	FD_ZERO(&tsdPtr->readyMasks.readable);
	FD_ZERO(&tsdPtr->readyMasks.writable);
	FD_ZERO(&tsdPtr->readyMasks.exception);
    FD_ZERO(&tsdPtr->readyMasks.readable);
    FD_ZERO(&tsdPtr->readyMasks.writable);
    FD_ZERO(&tsdPtr->readyMasks.exception);

	if (!tsdPtr->eventReady) {
    if (!tsdPtr->eventReady) {
#ifdef __CYGWIN__
	    if (!PeekMessageW(&msg, NULL, 0, 0, 0)) {
		unsigned int timeout;
	if (!PeekMessageW(&msg, NULL, 0, 0, 0)) {
	    unsigned int timeout;

		if (timePtr) {
		    timeout = timePtr->sec * 1000 + timePtr->usec / 1000;
		} else {
		    timeout = 0xFFFFFFFF;
		}
		pthread_mutex_unlock(&notifierMutex);
		MsgWaitForMultipleObjects(1, &tsdPtr->event, 0, timeout, 1279);
		pthread_mutex_lock(&notifierMutex);
	    }
	    if (timePtr) {
		timeout = timePtr->sec * 1000 + timePtr->usec / 1000;
	    } else {
		timeout = 0xFFFFFFFF;
	    }
	    pthread_mutex_unlock(&notifierMutex);
	    MsgWaitForMultipleObjects(1, &tsdPtr->event, 0, timeout, 1279);
	    pthread_mutex_lock(&notifierMutex);
	}
#else /* !__CYGWIN__ */
	    if (timePtr != NULL) {
		Tcl_Time now;
		struct timespec ptime;
	if (timePtr != NULL) {
	    Tcl_Time now;
	    struct timespec ptime;

		Tcl_GetTime(&now);
		ptime.tv_sec = timePtr->sec + now.sec +
			(timePtr->usec + now.usec) / 1000000;
		ptime.tv_nsec = 1000 * ((timePtr->usec + now.usec) % 1000000);
	    Tcl_GetTime(&now);
	    ptime.tv_sec = timePtr->sec + now.sec +
		    (timePtr->usec + now.usec) / 1000000;
	    ptime.tv_nsec = 1000 * ((timePtr->usec + now.usec) % 1000000);

		pthread_cond_timedwait(&tsdPtr->waitCV, &notifierMutex, &ptime);
	    } else {
		pthread_cond_wait(&tsdPtr->waitCV, &notifierMutex);
	    }
	    pthread_cond_timedwait(&tsdPtr->waitCV, &notifierMutex, &ptime);
	} else {
	    pthread_cond_wait(&tsdPtr->waitCV, &notifierMutex);
	}
#endif /* __CYGWIN__ */
	}
	tsdPtr->eventReady = 0;
    }
    tsdPtr->eventReady = 0;

#ifdef __CYGWIN__
	while (PeekMessageW(&msg, NULL, 0, 0, 0)) {
	    /*
	     * Retrieve and dispatch the message.
	     */
    while (PeekMessageW(&msg, NULL, 0, 0, 0)) {
	/*
	 * Retrieve and dispatch the message.
	 */

	    unsigned int result = GetMessageW(&msg, NULL, 0, 0);
	unsigned int result = GetMessageW(&msg, NULL, 0, 0);

	    if (result == 0) {
		PostQuitMessage(msg.wParam);
		/* What to do here? */
	    } else if (result != (unsigned int) -1) {
		TranslateMessage(&msg);
		DispatchMessageW(&msg);
	    }
	}
	ResetEvent(tsdPtr->event);
	if (result == 0) {
	    PostQuitMessage(msg.wParam);
	    /* What to do here? */
	} else if (result != (unsigned int) -1) {
	    TranslateMessage(&msg);
	    DispatchMessageW(&msg);
	}
    }
    ResetEvent(tsdPtr->event);
#endif /* __CYGWIN__ */

	if (waitForFiles && tsdPtr->onList) {
	    /*
	     * Remove the ThreadSpecificData structure of this thread from the
	     * waiting list. Alert the notifier thread to recompute its select
	     * masks - skipping this caused a hang when trying to close a pipe
	     * which the notifier thread was still doing a select on.
	     */
    if (waitForFiles && tsdPtr->onList) {
	/*
	 * Remove the ThreadSpecificData structure of this thread from the
	 * waiting list. Alert the notifier thread to recompute its select
	 * masks - skipping this caused a hang when trying to close a pipe
	 * which the notifier thread was still doing a select on.
	 */

	    if (tsdPtr->prevPtr) {
		tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
	    } else {
		waitingListPtr = tsdPtr->nextPtr;
	    }
	    if (tsdPtr->nextPtr) {
		tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
	    }
	    tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
	    tsdPtr->onList = 0;
	    if ((write(triggerPipe, "", 1) == -1) && (errno != EAGAIN)) {
		Tcl_Panic("Tcl_WaitForEvent: %s",
			"unable to write to triggerPipe");
	    }
	}
	if (tsdPtr->prevPtr) {
	    tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
	} else {
	    waitingListPtr = tsdPtr->nextPtr;
	}
	if (tsdPtr->nextPtr) {
	    tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
	}
	tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
	tsdPtr->onList = 0;
	if ((write(triggerPipe, "", 1) == -1) && (errno != EAGAIN)) {
	    Tcl_Panic("Tcl_WaitForEvent: %s",
		    "unable to write to triggerPipe");
	}
    }
#else /* !TCL_THREADS */
	tsdPtr->readyMasks = tsdPtr->checkMasks;
	numFound = select(tsdPtr->numFdBits, &tsdPtr->readyMasks.readable,
		&tsdPtr->readyMasks.writable, &tsdPtr->readyMasks.exception,
		timeoutPtr);
    tsdPtr->readyMasks = tsdPtr->checkMasks;
    numFound = select(tsdPtr->numFdBits, &tsdPtr->readyMasks.readable,
	    &tsdPtr->readyMasks.writable, &tsdPtr->readyMasks.exception,
	    timeoutPtr);

	/*
	 * Some systems don't clear the masks after an error, so we have to do
	 * it here.
	 */
    /*
     * Some systems don't clear the masks after an error, so we have to do it
     * here.
     */

	if (numFound == -1) {
	    FD_ZERO(&tsdPtr->readyMasks.readable);
	    FD_ZERO(&tsdPtr->readyMasks.writable);
	    FD_ZERO(&tsdPtr->readyMasks.exception);
	}
    if (numFound == -1) {
	FD_ZERO(&tsdPtr->readyMasks.readable);
	FD_ZERO(&tsdPtr->readyMasks.writable);
	FD_ZERO(&tsdPtr->readyMasks.exception);
    }
#endif /* TCL_THREADS */

	/*
	 * Queue all detected file events before returning.
	 */
    /*
     * Queue all detected file events before returning.
     */

	for (filePtr = tsdPtr->firstFileHandlerPtr; (filePtr != NULL);
		filePtr = filePtr->nextPtr) {
	    mask = 0;
	    if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.readable)) {
		mask |= TCL_READABLE;
	    }
	    if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.writable)) {
		mask |= TCL_WRITABLE;
	    }
	    if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.exception)) {
		mask |= TCL_EXCEPTION;
	    }
    for (filePtr = tsdPtr->firstFileHandlerPtr; (filePtr != NULL);
	    filePtr = filePtr->nextPtr) {
	mask = 0;
	if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.readable)) {
	    mask |= TCL_READABLE;
	}
	if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.writable)) {
	    mask |= TCL_WRITABLE;
	}
	if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.exception)) {
	    mask |= TCL_EXCEPTION;
	}

	    if (!mask) {
		continue;
	    }
	if (!mask) {
	    continue;
	}

	    /*
	     * Don't bother to queue an event if the mask was previously
	     * non-zero since an event must still be on the queue.
	     */
	/*
	 * Don't bother to queue an event if the mask was previously non-zero
	 * since an event must still be on the queue.
	 */

	    if (filePtr->readyMask == 0) {
		FileHandlerEvent *fileEvPtr =
			(FileHandlerEvent *)Tcl_Alloc(sizeof(FileHandlerEvent));
	if (filePtr->readyMask == 0) {
	    FileHandlerEvent *fileEvPtr =
		    (FileHandlerEvent *) Tcl_Alloc(sizeof(FileHandlerEvent));

		fileEvPtr->header.proc = FileHandlerEventProc;
		fileEvPtr->fd = filePtr->fd;
		Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
	    }
	    filePtr->readyMask = mask;
	}
	    fileEvPtr->header.proc = FileHandlerEventProc;
	    fileEvPtr->fd = filePtr->fd;
	    Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
	}
	filePtr->readyMask = mask;
    }
#if TCL_THREADS
	pthread_mutex_unlock(&notifierMutex);
    pthread_mutex_unlock(&notifierMutex);
#endif /* TCL_THREADS */
	return 0;
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TclAsyncNotifier --
 *
 *	This procedure sets the async mark of an async handler to a
 *	given value, if it is called from the notifier thread.
 *
 * Result:
 *	True, when the handler will be marked, false otherwise.
 *
 * Side effetcs:
 *	The trigger pipe is written when called from the notifier
 *	thread.
 *
 *----------------------------------------------------------------------
 */

int
TclAsyncNotifier(
    int sigNumber,		/* Signal number. */
    TCL_UNUSED(Tcl_ThreadId),	/* Target thread. */
    TCL_UNUSED(void *),	/* Notifier data. */
    int *flagPtr,		/* Flag to mark. */
    int value)			/* Value of mark. */
{
#if TCL_THREADS
    /*
     * WARNING:
     * This code most likely runs in a signal handler. Thus,
     * only few async-signal-safe system calls are allowed,
     * e.g. pthread_self(), sem_post(), write().
     */

    if (pthread_equal(pthread_self(), (pthread_t) notifierThread)) {
	if (notifierThreadRunning) {
	    *flagPtr = value;
	    if (!asyncPending) {
		asyncPending = 1;
		if (write(triggerPipe, "S", 1) != 1) {
		    asyncPending = 0;
		    return 0;
		};
	    }
	    return 1;
	}
	return 0;
    }

    /*
     * Re-send the signal to the notifier thread.
     */

    pthread_kill((pthread_t) notifierThread, sigNumber);
#else
    (void)sigNumber;
    (void)flagPtr;
    (void)value;
#endif
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * NotifierThreadProc --
 *
 *	This routine is the initial (and only) function executed by the
 *	special notifier thread. Its job is to wait for file descriptors to
 *	become readable or writable or to have an exception condition and then
 *	to notify other threads who are interested in this information by
 *	signalling a condition variable. Other threads can signal this
 *	notifier thread of a change in their interests by writing a single
 *	byte to a special pipe that the notifier thread is monitoring.
 *
 * Result:
 *	None. Once started, this routine never exits. It dies with the overall
 *	process.
 *	None. Once started, this routine normally never exits and usually dies
 *	with the overall process, but it can be shut down if the Tcl library
 *	is finalized.
 *
 * Side effects:
 *	The trigger pipe used to signal the notifier thread is created when
 *	the notifier thread first starts.
 *
 *----------------------------------------------------------------------
 */

#if TCL_THREADS
static TCL_NORETURN void
NotifierThreadProc(
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    ThreadSpecificData *tsdPtr;
    fd_set readableMask;
    fd_set writableMask;
    fd_set exceptionMask;
    int i;
    int fds[2], receivePipe;
    int i, fds[2], receivePipe, ret;
    long found;
    struct timeval poll = {0, 0}, *timePtr;
    char buf[2];
    int numFdBits = 0;

    if (pipe(fds) != 0) {
	Tcl_Panic("NotifierThreadProc: %s", "could not create trigger pipe");
    }

    /*
     * Ticket [c6897e6e6a].
     */

    if (fds[0] >= FD_SETSIZE || fds[1] >= FD_SETSIZE) {
	Tcl_Panic("NotifierThreadProc: %s", "too many open files");
    }

    receivePipe = fds[0];

    if (TclUnixSetBlockingMode(receivePipe, TCL_MODE_NONBLOCKING) < 0) {
	Tcl_Panic("NotifierThreadProc: %s",
		"could not make receive pipe non blocking");
    }
967
968
969
970
971
972
973

974
975
976
977
978
979
980
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048







+








    /*
     * Install the write end of the pipe into the global variable.
     */

    pthread_mutex_lock(&notifierMutex);
    triggerPipe = fds[1];
    otherPipe = fds[0];

    /*
     * Signal any threads that are waiting.
     */

    pthread_cond_broadcast(&notifierCV);
    pthread_mutex_unlock(&notifierMutex);
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
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121


1122
1123
1124
1125
1126
1127
1128

1129
1130
1131
1132
1133
1134

1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150

1151
1152
1153
1154
1155
1156
1157
1158







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+

-
+
+

+
+
+
-
+
+
+
+
+











-
+







	 */

	if (receivePipe >= numFdBits) {
	    numFdBits = receivePipe + 1;
	}
	FD_SET(receivePipe, &readableMask);

	/*
	 * Signals are unblocked only during select().
	 */

#ifdef HAVE_PSELECT
	{
	    struct timespec tspec, *tspecPtr;

	    if (timePtr == NULL) {
		tspecPtr = NULL;
	    } else {
		tspecPtr = &tspec;
		tspecPtr->tv_sec = timePtr->tv_sec;
		tspecPtr->tv_nsec = timePtr->tv_usec * 1000;
	    }
	    ret = pselect(numFdBits, &readableMask, &writableMask,
		    &exceptionMask, tspecPtr, &notifierSigMask);
	}
#else
	pthread_sigmask(SIG_SETMASK, &notifierSigMask, NULL);
	if (select(numFdBits, &readableMask, &writableMask, &exceptionMask,
		timePtr) == -1) {
	ret = select(numFdBits, &readableMask, &writableMask, &exceptionMask,
		timePtr);
	pthread_sigmask(SIG_BLOCK, &allSigMask, NULL);
#endif

	if (ret == -1) {
	    /*
	     * Try again immediately on an error.
	     * In case a signal was caught during select(),
	     * perform work on async handlers now.
	     */
	    if (errno == EINTR && asyncPending) {
		asyncPending = 0;
		TclAsyncMarkFromNotifier();

	    }

	    /*
	     * Try again immediately on select() error.
	     */
	    continue;
	}

	/*
	 * Alert any threads that are waiting on a ready file descriptor.
	 */

	pthread_mutex_lock(&notifierMutex);
	for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
	    found = 0;

	    for (i = tsdPtr->numFdBits-1; i >= 0; --i) {
	    for (i = tsdPtr->numFdBits - 1; i >= 0; --i) {
		if (FD_ISSET(i, &tsdPtr->checkMasks.readable)
			&& FD_ISSET(i, &readableMask)) {
		    FD_SET(i, &tsdPtr->readyMasks.readable);
		    found = 1;
		}
		if (FD_ISSET(i, &tsdPtr->checkMasks.writable)
			&& FD_ISSET(i, &writableMask)) {
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


1116
1117
1118
1119
1120
1121
1122
1123
1124
1175
1176
1177
1178
1179
1180
1181

1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233







-
+












+
+
+
+
+
+













+








+
+









	/*
	 * Consume the next byte from the notifier pipe if the pipe was
	 * readable. Note that there may be multiple bytes pending, but to
	 * avoid a race condition we only read one at a time.
	 */

	do {
	    i = read(receivePipe, buf, 1);
	    i = (int)read(receivePipe, buf, 1);
	    if (i <= 0) {
		break;
	    } else if ((i == 0) || ((i == 1) && (buf[0] == 'q'))) {
		/*
		 * Someone closed the write end of the pipe or sent us a Quit
		 * message [Bug: 4139] and then closed the write end of the
		 * pipe so we need to shut down the notifier thread.
		 */

		break;
	    }
	} while (1);

	if (asyncPending) {
	    asyncPending = 0;
	    TclAsyncMarkFromNotifier();
	}

	if ((i == 0) || (buf[0] == 'q')) {
	    break;
	}
    }

    /*
     * Clean up the read end of the pipe and signal any threads waiting on
     * termination of the notifier thread.
     */

    close(receivePipe);
    pthread_mutex_lock(&notifierMutex);
    triggerPipe = -1;
    otherPipe = -1;
    pthread_cond_broadcast(&notifierCV);
    pthread_mutex_unlock(&notifierMutex);

    TclpThreadExit(0);
}
#endif /* TCL_THREADS */

#endif /* (!NOTIFIER_EPOLL && !NOTIFIER_KQUEUE) || !TCL_THREADS */
#else
TCL_MAC_EMPTY_FILE(unix_tclSelectNotfy_c)
#endif /* !HAVE_COREFOUNDATION */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to unix/tclUnixChan.c.

1
2
3
4
5
6
7
8


9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22






-
-
+
+






+







/*
 * tclUnixChan.c
 *
 *	Common channel driver for Unix channels based on files, command pipes
 *	and TCP sockets.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1998-1999 Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"	/* Internal definitions for Tcl. */
#include "tclFileSystem.h"
#include "tclIO.h"	/* To get Channel type declaration. */

#undef SUPPORTS_TTY
#if defined(HAVE_TERMIOS_H)
#   define SUPPORTS_TTY 1
#   include <termios.h>
#   ifdef HAVE_SYS_IOCTL_H
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
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







-
+











+
+
+





-
-
-
+
+
+








#endif	/* SUPPORTS_TTY */

#define UNSUPPORTED_OPTION(detail) \
    if (interp) {							\
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(				\
		"%s not supported for this platform", (detail)));	\
	Tcl_SetErrorCode(interp, "TCL", "UNSUPPORTED", NULL);		\
	Tcl_SetErrorCode(interp, "TCL", "UNSUPPORTED", (char *)NULL);		\
    }

/*
 * Static routines for this file:
 */

static int		FileBlockModeProc(void *instanceData, int mode);
static int		FileCloseProc(void *instanceData,
			    Tcl_Interp *interp, int flags);
static int		FileGetHandleProc(void *instanceData,
			    int direction, void **handlePtr);
static int		FileGetOptionProc(void *instanceData,
			    Tcl_Interp *interp, const char *optionName,
			    Tcl_DString *dsPtr);
static int		FileInputProc(void *instanceData, char *buf,
			    int toRead, int *errorCode);
static int		FileOutputProc(void *instanceData,
			    const char *buf, int toWrite, int *errorCode);
static int		FileTruncateProc(void *instanceData,
			    Tcl_WideInt length);
static Tcl_WideInt	FileWideSeekProc(void *instanceData,
			    Tcl_WideInt offset, int mode, int *errorCode);
			    long long length);
static long long	FileWideSeekProc(void *instanceData,
			    long long offset, int mode, int *errorCode);
static void		FileWatchProc(void *instanceData, int mask);
#ifdef SUPPORTS_TTY
static int		TtyCloseProc(void *instanceData,
			    Tcl_Interp *interp, int flags);
static void		TtyGetAttributes(int fd, TtyAttrs *ttyPtr);
static int		TtyGetOptionProc(void *instanceData,
			    Tcl_Interp *interp, const char *optionName,
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
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







-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+









-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








/*
 * This structure describes the channel type structure for file based IO:
 */

static const Tcl_ChannelType fileChannelType = {
    "file",			/* Type name. */
    TCL_CHANNEL_VERSION_5,	/* v5 channel */
    NULL,		/* Close proc. */
    FileInputProc,		/* Input proc. */
    FileOutputProc,		/* Output proc. */
	NULL,
    TCL_CHANNEL_VERSION_5,
    NULL,			/* Deprecated. */
    FileInputProc,
    FileOutputProc,
    NULL,			/* Deprecated. */
    NULL,			/* Set option proc. */
    NULL,			/* Get option proc. */
    FileWatchProc,		/* Initialize notifier. */
    FileGetHandleProc,		/* Get OS handles out of channel. */
    FileCloseProc,		/* close2proc. */
    FileBlockModeProc,		/* Set blocking or non-blocking mode.*/
    NULL,			/* flush proc. */
    NULL,			/* handler proc. */
    FileWideSeekProc,		/* wide seek proc. */
    NULL,
    FileTruncateProc		/* truncate proc. */
    FileGetOptionProc,
    FileWatchProc,
    FileGetHandleProc,
    FileCloseProc,
    FileBlockModeProc,
    NULL,			/* Flush proc. */
    NULL,			/* Bubbled event handler proc. */
    FileWideSeekProc,
    NULL,			/* Thread action proc. */
    FileTruncateProc
};

#ifdef SUPPORTS_TTY
/*
 * This structure describes the channel type structure for serial IO.
 * Note that this type is a subclass of the "file" type.
 */

static const Tcl_ChannelType ttyChannelType = {
    "tty",			/* Type name. */
    TCL_CHANNEL_VERSION_5,	/* v5 channel */
    NULL,		/* Close proc. */
    FileInputProc,		/* Input proc. */
    FileOutputProc,		/* Output proc. */
    NULL,			/* Seek proc. */
    TtySetOptionProc,		/* Set option proc. */
    TtyGetOptionProc,		/* Get option proc. */
    FileWatchProc,		/* Initialize notifier. */
    FileGetHandleProc,		/* Get OS handles out of channel. */
    TtyCloseProc,			/* close2proc. */
    FileBlockModeProc,		/* Set blocking or non-blocking mode.*/
    NULL,			/* flush proc. */
    NULL,			/* handler proc. */
    NULL,			/* wide seek proc. */
    NULL,			/* thread action proc. */
    NULL			/* truncate proc. */
    "tty",
    TCL_CHANNEL_VERSION_5,
    NULL,			/* Deprecated. */
    FileInputProc,
    FileOutputProc,
    NULL,			/* Deprecated. */
    TtySetOptionProc,
    TtyGetOptionProc,
    FileWatchProc,
    FileGetHandleProc,
    TtyCloseProc,
    FileBlockModeProc,
    NULL,			/* Flush proc. */
    NULL,			/* Bubbled event handler proc. */
    NULL,			/* Seek proc. */
    NULL,			/* Thread action proc. */
    NULL			/* Truncate proc. */
};
#endif	/* SUPPORTS_TTY */

/*
 *----------------------------------------------------------------------
 *
 * FileBlockModeProc --
218
219
220
221
222
223
224
225

226
227
228
229
230
231
232
222
223
224
225
226
227
228

229
230
231
232
233
234
235
236







-
+







 *	Sets the device into blocking or non-blocking mode.
 *
 *----------------------------------------------------------------------
 */

static int
FileBlockModeProc(
    void *instanceData,	/* File state. */
    void *instanceData,		/* File state. */
    int mode)			/* The mode to set. Can be TCL_MODE_BLOCKING
				 * or TCL_MODE_NONBLOCKING. */
{
    FileState *fsPtr = (FileState *)instanceData;

    if (TclUnixSetBlockingMode(fsPtr->fd, mode) < 0) {
	return errno;
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
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







-
+


















+
-
-
-
+
+
+
+
+
+

-
-
+







 *	Reads input from the input device of the channel.
 *
 *----------------------------------------------------------------------
 */

static int
FileInputProc(
    void *instanceData,	/* File state. */
    void *instanceData,		/* File state. */
    char *buf,			/* Where to store data read. */
    int toRead,			/* How much space is available in the
				 * buffer? */
    int *errorCodePtr)		/* Where to store error code. */
{
    FileState *fsPtr = (FileState *)instanceData;
    int bytesRead;		/* How many bytes were actually read from the
				 * input device? */

    *errorCodePtr = 0;

    /*
     * Assume there is always enough input available. This will block
     * appropriately, and read will unblock as soon as a short read is
     * possible, if the channel is in blocking mode. If the channel is
     * nonblocking, the read will never block.
     */

    do {
    bytesRead = read(fsPtr->fd, buf, toRead);
    if (bytesRead >= 0) {
	return bytesRead;
	bytesRead = read(fsPtr->fd, buf, toRead);
    } while ((bytesRead < 0) && (errno == EINTR));

    if (bytesRead < 0) {
	*errorCodePtr = errno;
	return -1;
    }
    *errorCodePtr = errno;
    return -1;
    return bytesRead;
}

/*
 *----------------------------------------------------------------------
 *
 * FileOutputProc--
 *
298
299
300
301
302
303
304
305

306
307
308
309
310
311
312
305
306
307
308
309
310
311

312
313
314
315
316
317
318
319







-
+







 *	Writes output on the output device of the channel.
 *
 *----------------------------------------------------------------------
 */

static int
FileOutputProc(
    void *instanceData,	/* File state. */
    void *instanceData,		/* File state. */
    const char *buf,		/* The data buffer. */
    int toWrite,		/* How many bytes to write? */
    int *errorCodePtr)		/* Where to store error code. */
{
    FileState *fsPtr = (FileState *)instanceData;
    int written;

345
346
347
348
349
350
351
352

353
354
355
356
357
358
359
352
353
354
355
356
357
358

359
360
361
362
363
364
365
366







-
+







 *	Closes the device of the channel.
 *
 *----------------------------------------------------------------------
 */

static int
FileCloseProc(
    void *instanceData,	/* File state. */
    void *instanceData,		/* File state. */
    TCL_UNUSED(Tcl_Interp *),
    int flags)
{
    FileState *fsPtr = (FileState *)instanceData;
    int errorCode = 0;

    if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
436
437
438
439
440
441
442
443

444
445
446


447
448
449
450
451
452

453
454
455
456
457
458
459
443
444
445
446
447
448
449

450
451


452
453
454
455
456
457
458

459
460
461
462
463
464
465
466







-
+

-
-
+
+





-
+







 * Side effects:
 *	Moves the location at which the channel will be accessed in future
 *	operations.
 *
 *----------------------------------------------------------------------
 */

static Tcl_WideInt
static long long
FileWideSeekProc(
    void *instanceData,	/* File state. */
    Tcl_WideInt offset,		/* Offset to seek to. */
    void *instanceData,		/* File state. */
    long long offset,		/* Offset to seek to. */
    int mode,			/* Relative to where should we seek? Can be
				 * one of SEEK_START, SEEK_CUR or SEEK_END. */
    int *errorCodePtr)		/* To store error code. */
{
    FileState *fsPtr = (FileState *)instanceData;
    Tcl_WideInt newLoc;
    long long newLoc;

    newLoc = TclOSseek(fsPtr->fd, (Tcl_SeekOffset) offset, mode);

    *errorCodePtr = (newLoc == -1) ? errno : 0;
    return newLoc;
}

469
470
471
472
473
474
475














476
477
478
479

480
481
482
483
484
485
486
487

488
489
490
491
492
493
494
495

496
497
498
499
500
501
502
476
477
478
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+







-
+
-
-





-
+







 *
 * Side effects:
 *	Sets up the notifier so that a future event on the channel will
 *	be seen by Tcl.
 *
 *----------------------------------------------------------------------
 */

/*
 * Bug ad5a57f2f271: Tcl_NotifyChannel is not a Tcl_FileProc,
 * so do not pass it to directly to Tcl_CreateFileHandler.
 * Instead, pass a wrapper which is a Tcl_FileProc.
 */
static void
FileWatchNotifyChannelWrapper(
    void *clientData,
    int mask)
{
    Tcl_Channel channel = (Tcl_Channel)clientData;
    Tcl_NotifyChannel(channel, mask);
}

static void
FileWatchProc(
    void *instanceData,	/* The file state. */
    void *instanceData,		/* The file state. */
    int mask)			/* Events of interest; an OR-ed combination of
				 * TCL_READABLE, TCL_WRITABLE and
				 * TCL_EXCEPTION. */
{
    FileState *fsPtr = (FileState *)instanceData;

    /*
     * Make sure we only register for events that are valid on this file. Note
     * Make sure we only register for events that are valid on this file.
     * that we are passing Tcl_NotifyChannel directly to Tcl_CreateFileHandler
     * with the channel pointer as the client data.
     */

    mask &= fsPtr->validMask;
    if (mask) {
	Tcl_CreateFileHandler(fsPtr->fd, mask,
		(Tcl_FileProc *) Tcl_NotifyChannel, fsPtr->channel);
		FileWatchNotifyChannelWrapper, fsPtr->channel);
    } else {
	Tcl_DeleteFileHandler(fsPtr->fd);
    }
}

/*
 *----------------------------------------------------------------------
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
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
707
708
709
710
711
712
713







-
+

-
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileGetHandleProc(
    void *instanceData,	/* The file state. */
    void *instanceData,		/* The file state. */
    int direction,		/* TCL_READABLE or TCL_WRITABLE */
    void **handlePtr)	/* Where to store the handle. */
    void **handlePtr)		/* Where to store the handle. */
{
    FileState *fsPtr = (FileState *)instanceData;

    if (direction & fsPtr->validMask) {
	*handlePtr = INT2PTR(fsPtr->fd);
	return TCL_OK;
    }
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * FileGetOptionProc --
 *
 *	Gets an option associated with an open file. If the optionName arg is
 *	non-NULL, retrieves the value of that option. If the optionName arg is
 *	NULL, retrieves a list of alternating option names and values for the
 *	given channel.
 *
 * Results:
 *	A standard Tcl result. Also sets the supplied DString to the string
 *	value of the option(s) returned.  Sets error message if needed
 *	(by calling Tcl_BadChannelOption).
 *
 *----------------------------------------------------------------------
 */

static inline const char *
GetTypeFromMode(
    int mode)
{
    /*
     * TODO: deduplicate with tclCmdAH.c
     */

    if (S_ISREG(mode)) {
	return "file";
    } else if (S_ISDIR(mode)) {
	return "directory";
    } else if (S_ISCHR(mode)) {
	return "characterSpecial";
    } else if (S_ISBLK(mode)) {
	return "blockSpecial";
    } else if (S_ISFIFO(mode)) {
	return "fifo";
#ifdef S_ISLNK
    } else if (S_ISLNK(mode)) {
	return "link";
#endif
#ifdef S_ISSOCK
    } else if (S_ISSOCK(mode)) {
	return "socket";
#endif
    }
    return "unknown";
}

static Tcl_Obj *
StatOpenFile(
    FileState *fsPtr)
{
    Tcl_StatBuf statBuf;	/* Not allocated on heap; we're definitely
				 * API-synchronized with how Tcl is built! */
    Tcl_Obj *dictObj;
    unsigned short mode;

    if (TclOSfstat(fsPtr->fd, &statBuf) < 0) {
	return NULL;
    }

    /*
     * TODO: merge with TIP 594 implementation (it's silly to have a
     * duplicate!)
     */

    TclNewObj(dictObj);
#define STORE_ELEM(name, value) TclDictPut(NULL, dictObj, name, value)

    STORE_ELEM("dev",     Tcl_NewWideIntObj((long) statBuf.st_dev));
    STORE_ELEM("ino",     Tcl_NewWideIntObj((Tcl_WideInt) statBuf.st_ino));
    STORE_ELEM("nlink",   Tcl_NewWideIntObj((long) statBuf.st_nlink));
    STORE_ELEM("uid",     Tcl_NewWideIntObj((long) statBuf.st_uid));
    STORE_ELEM("gid",     Tcl_NewWideIntObj((long) statBuf.st_gid));
    STORE_ELEM("size",    Tcl_NewWideIntObj((Tcl_WideInt) statBuf.st_size));
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
    STORE_ELEM("blocks",  Tcl_NewWideIntObj((Tcl_WideInt) statBuf.st_blocks));
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
    STORE_ELEM("blksize", Tcl_NewWideIntObj((long) statBuf.st_blksize));
#endif
#ifdef HAVE_STRUCT_STAT_ST_RDEV
    if (S_ISCHR(statBuf.st_mode) || S_ISBLK(statBuf.st_mode)) {
	STORE_ELEM("rdev", Tcl_NewWideIntObj((long) statBuf.st_rdev));
    }
#endif
    STORE_ELEM("atime",   Tcl_NewWideIntObj(
	    Tcl_GetAccessTimeFromStat(&statBuf)));
    STORE_ELEM("mtime",   Tcl_NewWideIntObj(
	    Tcl_GetModificationTimeFromStat(&statBuf)));
    STORE_ELEM("ctime",   Tcl_NewWideIntObj(
	    Tcl_GetChangeTimeFromStat(&statBuf)));
    mode = (unsigned short) statBuf.st_mode;
    STORE_ELEM("mode",    Tcl_NewWideIntObj(mode));
    STORE_ELEM("type",    Tcl_NewStringObj(GetTypeFromMode(mode), -1));
#undef STORE_ELEM

    return dictObj;
}

static int
FileGetOptionProc(
    void *instanceData,
    Tcl_Interp *interp,
    const char *optionName,
    Tcl_DString *dsPtr)
{
    FileState *fsPtr = (FileState *)instanceData;
    int valid = 0;		/* Flag if valid option parsed. */
    int len;

    if (optionName == NULL) {
	len = 0;
	valid = 1;
    } else {
	len = strlen(optionName);
    }

    /*
     * Get option -stat
     * Option is readonly and returned by [fconfigure chan -stat] but not
     * returned by [fconfigure chan] without explicit option name.
     */

    if ((len > 1) && (strncmp(optionName, "-stat", len) == 0)) {
	Tcl_Obj *dictObj = StatOpenFile(fsPtr);
	const char *dictContents;
	Tcl_Size dictLength;

	if (dictObj == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "couldn't read file channel status: %s",
		    Tcl_PosixError(interp)));
	    return TCL_ERROR;
	}

	/*
	 * Transfer dictionary to the DString. Note that we don't do this as
	 * an element as this is an option that can't be retrieved with a
	 * general probe.
	 */

	dictContents = TclGetStringFromObj(dictObj, &dictLength);
	Tcl_DStringAppend(dsPtr, dictContents, dictLength);
	Tcl_DecrRefCount(dictObj);
	return TCL_OK;
    }

    if (valid) {
	return TCL_OK;
    }
    return Tcl_BadChannelOption(interp, optionName,
		"stat");
}

#ifdef SUPPORTS_TTY
/*
 *----------------------------------------------------------------------
 *
 * TtyModemStatusStr --
 *
581
582
583
584
585
586
587
588

589
590
591
592
593
594
595
596

597
598
599
600
601
602
603
755
756
757
758
759
760
761

762
763
764
765
766
767
768
769

770
771
772
773
774
775
776
777







-
+







-
+







 *	calling Tcl_BadChannelOption).
 *
 *----------------------------------------------------------------------
 */

static int
TtySetOptionProc(
    void *instanceData,	/* File state. */
    void *instanceData,		/* File state. */
    Tcl_Interp *interp,		/* For error reporting - can be NULL. */
    const char *optionName,	/* Which option to set? */
    const char *value)		/* New value for option. */
{
    TtyState *fsPtr = (TtyState *)instanceData;
    size_t len, vlen;
    TtyAttrs tty;
    int argc;
    Tcl_Size argc;
    const char **argv;
    struct termios iostate;

    len = strlen(optionName);
    vlen = strlen(value);

    /*
627
628
629
630
631
632
633
634

635
636
637
638

639
640

641
642
643
644
645
646
647

648
649
650
651
652
653
654
655
656

657
658
659
660
661
662
663
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
801
802
803
804
805
806
807

808
809
810
811

812
813

814
815
816
817
818
819
820

821
822
823
824
825
826
827
828
829

830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850

851
852
853
854
855
856
857
858
859
860
861
862
863
864

865
866
867
868
869

870
871
872
873
874
875
876
877







-
+



-
+

-
+






-
+








-
+




















-
+













-
+




-
+







	 */

	tcgetattr(fsPtr->fileState.fd, &iostate);
	CLEAR_BITS(iostate.c_iflag, IXON | IXOFF | IXANY);
#ifdef CRTSCTS
	CLEAR_BITS(iostate.c_cflag, CRTSCTS);
#endif /* CRTSCTS */
	if (Tcl_UtfNcasecmp(value, "NONE", vlen) == 0) {
	if (strncasecmp(value, "NONE", vlen) == 0) {
	    /*
	     * Leave all handshake options disabled.
	     */
	} else if (Tcl_UtfNcasecmp(value, "XONXOFF", vlen) == 0) {
	} else if (strncasecmp(value, "XONXOFF", vlen) == 0) {
	    SET_BITS(iostate.c_iflag, IXON | IXOFF | IXANY);
	} else if (Tcl_UtfNcasecmp(value, "RTSCTS", vlen) == 0) {
	} else if (strncasecmp(value, "RTSCTS", vlen) == 0) {
#ifdef CRTSCTS
	    SET_BITS(iostate.c_cflag, CRTSCTS);
#else /* !CRTSTS */
	    UNSUPPORTED_OPTION("-handshake RTSCTS");
	    return TCL_ERROR;
#endif /* CRTSCTS */
	} else if (Tcl_UtfNcasecmp(value, "DTRDSR", vlen) == 0) {
	} else if (strncasecmp(value, "DTRDSR", vlen) == 0) {
	    UNSUPPORTED_OPTION("-handshake DTRDSR");
	    return TCL_ERROR;
	} else {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"bad value for -handshake: must be one of"
			" xonxoff, rtscts, dtrdsr or none", -1));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "FCONFIGURE",
			"VALUE", NULL);
			"VALUE", (char *)NULL);
	    }
	    return TCL_ERROR;
	}
	tcsetattr(fsPtr->fileState.fd, TCSADRAIN, &iostate);
	return TCL_OK;
    }

    /*
     * Option -xchar {\x11 \x13}
     */

    if ((len > 1) && (strncmp(optionName, "-xchar", len) == 0)) {
	if (Tcl_SplitList(interp, value, &argc, &argv) == TCL_ERROR) {
	    return TCL_ERROR;
	} else if (argc != 2) {
	badXchar:
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"bad value for -xchar: should be a list of"
			" two elements with each a single 8-bit character", -1));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "XCHAR", NULL);
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "XCHAR", (char *)NULL);
	    }
	    Tcl_Free(argv);
	    return TCL_ERROR;
	}

	tcgetattr(fsPtr->fileState.fd, &iostate);

	iostate.c_cc[VSTART] = argv[0][0];
	iostate.c_cc[VSTOP] = argv[1][0];
	if (argv[0][0] & 0x80 || argv[1][0] & 0x80) {
	    Tcl_UniChar character = 0;
	    int charLen;

	    charLen = Tcl_UtfToUniChar(argv[0], &character);
	    charLen = TclUtfToUniChar(argv[0], &character);
	    if ((character > 0xFF) || argv[0][charLen]) {
		goto badXchar;
	    }
	    iostate.c_cc[VSTART] = character;
	    charLen = Tcl_UtfToUniChar(argv[1], &character);
	    charLen = TclUtfToUniChar(argv[1], &character);
	    if ((character > 0xFF) || argv[1][charLen]) {
		goto badXchar;
	    }
	    iostate.c_cc[VSTOP] = character;
	}
	Tcl_Free(argv);

724
725
726
727
728
729
730
731


732
733
734
735
736
737
738
739
740
741
742

743
744
745
746
747
748
749
750
751
752
753
754

755
756
757
758
759
760

761
762
763
764
765
766

767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784

785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804

805
806

807
808

809
810
811
812
813
814
815
816

817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836

837
838
839
840

841
842
843
844
845
846
847
848
849
850
851

852
853
854
855
856
857
858
859
860
861
862

863
864
865
866
867
868
869
870
871
872
873
874

875
876
877
878
879
880
881
898
899
900
901
902
903
904

905
906
907
908
909
910
911
912
913
914
915
916

917
918
919
920
921
922
923
924
925
926
927
928

929
930
931
932
933
934

935
936
937
938
939
940

941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
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







-
+
+










-
+











-
+





-
+





-
+

















-
+



















-
+

-
+

-
+







-
+



















-
+



-
+










-
+










-
+











-
+








    /*
     * Option -ttycontrol {DTR 1 RTS 0 BREAK 0}
     */

    if ((len > 4) && (strncmp(optionName, "-ttycontrol", len) == 0)) {
#if defined(TIOCMGET) && defined(TIOCMSET)
	int i, control, flag;
	int control, flag;
	Tcl_Size i;

	if (Tcl_SplitList(interp, value, &argc, &argv) == TCL_ERROR) {
	    return TCL_ERROR;
	}
	if ((argc % 2) == 1) {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"bad value for -ttycontrol: should be a list of"
			" signal,value pairs", -1));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "FCONFIGURE",
			"VALUE", NULL);
			"VALUE", (char *)NULL);
	    }
	    Tcl_Free(argv);
	    return TCL_ERROR;
	}

	ioctl(fsPtr->fileState.fd, TIOCMGET, &control);
	for (i = 0; i < argc-1; i += 2) {
	    if (Tcl_GetBoolean(interp, argv[i+1], &flag) == TCL_ERROR) {
		Tcl_Free(argv);
		return TCL_ERROR;
	    }
	    if (Tcl_UtfNcasecmp(argv[i], "DTR", strlen(argv[i])) == 0) {
	    if (strncasecmp(argv[i], "DTR", strlen(argv[i])) == 0) {
		if (flag) {
		    SET_BITS(control, TIOCM_DTR);
		} else {
		    CLEAR_BITS(control, TIOCM_DTR);
		}
	    } else if (Tcl_UtfNcasecmp(argv[i], "RTS", strlen(argv[i])) == 0) {
	    } else if (strncasecmp(argv[i], "RTS", strlen(argv[i])) == 0) {
		if (flag) {
		    SET_BITS(control, TIOCM_RTS);
		} else {
		    CLEAR_BITS(control, TIOCM_RTS);
		}
	    } else if (Tcl_UtfNcasecmp(argv[i], "BREAK", strlen(argv[i])) == 0) {
	    } else if (strncasecmp(argv[i], "BREAK", strlen(argv[i])) == 0) {
#if defined(TIOCSBRK) && defined(TIOCCBRK)
		if (flag) {
		    ioctl(fsPtr->fileState.fd, TIOCSBRK, NULL);
		} else {
		    ioctl(fsPtr->fileState.fd, TIOCCBRK, NULL);
		}
#else /* TIOCSBRK & TIOCCBRK */
		UNSUPPORTED_OPTION("-ttycontrol BREAK");
		Tcl_Free(argv);
		return TCL_ERROR;
#endif /* TIOCSBRK & TIOCCBRK */
	    } else {
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "bad signal \"%s\" for -ttycontrol: must be"
			    " DTR, RTS or BREAK", argv[i]));
		    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "FCONFIGURE",
			"VALUE", NULL);
			"VALUE", (char *)NULL);
		}
		Tcl_Free(argv);
		return TCL_ERROR;
	    }
	} /* -ttycontrol options loop */

	ioctl(fsPtr->fileState.fd, TIOCMSET, &control);
	Tcl_Free(argv);
	return TCL_OK;
#else /* TIOCMGET&TIOCMSET */
	UNSUPPORTED_OPTION("-ttycontrol");
#endif /* TIOCMGET&TIOCMSET */
    }

    /*
     * Option -closemode drain|discard
     */

    if ((len > 2) && (strncmp(optionName, "-closemode", len) == 0)) {
	if (Tcl_UtfNcasecmp(value, "DEFAULT", vlen) == 0) {
	if (strncasecmp(value, "DEFAULT", vlen) == 0) {
	    fsPtr->closeMode = CLOSE_DEFAULT;
	} else if (Tcl_UtfNcasecmp(value, "DRAIN", vlen) == 0) {
	} else if (strncasecmp(value, "DRAIN", vlen) == 0) {
	    fsPtr->closeMode = CLOSE_DRAIN;
	} else if (Tcl_UtfNcasecmp(value, "DISCARD", vlen) == 0) {
	} else if (strncasecmp(value, "DISCARD", vlen) == 0) {
	    fsPtr->closeMode = CLOSE_DISCARD;
	} else {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"bad mode \"%s\" for -closemode: must be"
			" default, discard, or drain", value));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "FCONFIGURE",
			"VALUE", NULL);
			"VALUE", (char *)NULL);
	    }
	    return TCL_ERROR;
	}
	return TCL_OK;
    }

    /*
     * Option -inputmode normal|password|raw
     */

    if ((len > 2) && (strncmp(optionName, "-inputmode", len) == 0)) {
	if (tcgetattr(fsPtr->fileState.fd, &iostate) < 0) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"couldn't read serial terminal control state: %s",
			Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}
	if (Tcl_UtfNcasecmp(value, "NORMAL", vlen) == 0) {
	if (strncasecmp(value, "NORMAL", vlen) == 0) {
	    SET_BITS(iostate.c_iflag, BRKINT | IGNPAR | ISTRIP | ICRNL | IXON);
	    SET_BITS(iostate.c_oflag, OPOST);
	    SET_BITS(iostate.c_lflag, ECHO | ECHONL | ICANON | ISIG);
	} else if (Tcl_UtfNcasecmp(value, "PASSWORD", vlen) == 0) {
	} else if (strncasecmp(value, "PASSWORD", vlen) == 0) {
	    SET_BITS(iostate.c_iflag, BRKINT | IGNPAR | ISTRIP | ICRNL | IXON);
	    SET_BITS(iostate.c_oflag, OPOST);
	    CLEAR_BITS(iostate.c_lflag, ECHO);
	    /*
	     * Note: password input turns out to be best if you echo the
	     * newline that the user types. Theoretically we could get users
	     * to do the processing of this in their scripts, but it always
	     * feels highly unnatural to do so in practice.
	     */
	    SET_BITS(iostate.c_lflag, ECHONL | ICANON | ISIG);
	} else if (Tcl_UtfNcasecmp(value, "RAW", vlen) == 0) {
	} else if (strncasecmp(value, "RAW", vlen) == 0) {
#ifdef HAVE_CFMAKERAW
	    cfmakeraw(&iostate);
#else /* !HAVE_CFMAKERAW */
	    CLEAR_BITS(iostate.c_iflag, IGNBRK | BRKINT | PARMRK | ISTRIP
		    | INLCR | IGNCR | ICRNL | IXON);
	    CLEAR_BITS(iostate.c_oflag, OPOST);
	    CLEAR_BITS(iostate.c_lflag, ECHO | ECHONL | ICANON | ISIG | IEXTEN);
	    CLEAR_BITS(iostate.c_cflag, CSIZE | PARENB);
	    SET_BITS(iostate.c_cflag, CS8);
#endif /* HAVE_CFMAKERAW */
	} else if (Tcl_UtfNcasecmp(value, "RESET", vlen) == 0) {
	} else if (strncasecmp(value, "RESET", vlen) == 0) {
	    /*
	     * Reset to the initial state, whatever that is.
	     */

	    memcpy(&iostate, &fsPtr->initState, sizeof(struct termios));
	} else {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"bad mode \"%s\" for -inputmode: must be"
			" normal, password, raw, or reset", value));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "FCONFIGURE",
			"VALUE", NULL);
			"VALUE", (char *)NULL);
	    }
	    return TCL_ERROR;
	}
	if (tcsetattr(fsPtr->fileState.fd, TCSADRAIN, &iostate) < 0) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"couldn't update serial terminal control state: %s",
920
921
922
923
924
925
926
927

928
929
930
931
932
933
934
1095
1096
1097
1098
1099
1100
1101

1102
1103
1104
1105
1106
1107
1108
1109







-
+







 *	(by calling Tcl_BadChannelOption).
 *
 *----------------------------------------------------------------------
 */

static int
TtyGetOptionProc(
    void *instanceData,	/* File state. */
    void *instanceData,		/* File state. */
    Tcl_Interp *interp,		/* For error reporting - can be NULL. */
    const char *optionName,	/* Option to get. */
    Tcl_DString *dsPtr)		/* Where to store value(s). */
{
    TtyState *fsPtr = (TtyState *)instanceData;
    size_t len;
    char buf[3*TCL_INTEGER_SPACE + 16];
1001
1002
1003
1004
1005
1006
1007
1008

1009
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
1176
1177
1178
1179
1180
1181
1182

1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201

1202
1203
1204
1205

1206
1207
1208
1209
1210
1211
1212
1213







-
+


















-
+



-
+







	Tcl_DStringAppendElement(dsPtr, "-mode");
    }
    if (len==0 || (len>2 && strncmp(optionName, "-mode", len)==0)) {
	TtyAttrs tty;

	valid = 1;
	TtyGetAttributes(fsPtr->fileState.fd, &tty);
	sprintf(buf, "%d,%c,%d,%d", tty.baud, tty.parity, tty.data, tty.stop);
	snprintf(buf, sizeof(buf), "%d,%c,%d,%d", tty.baud, tty.parity, tty.data, tty.stop);
	Tcl_DStringAppendElement(dsPtr, buf);
    }

    /*
     * Get option -xchar
     */

    if (len == 0) {
	Tcl_DStringAppendElement(dsPtr, "-xchar");
	Tcl_DStringStartSublist(dsPtr);
    }
    if (len==0 || (len>1 && strncmp(optionName, "-xchar", len)==0)) {
	Tcl_DString ds;

	valid = 1;
	tcgetattr(fsPtr->fileState.fd, &iostate);
	Tcl_DStringInit(&ds);

	Tcl_ExternalToUtfDString(NULL, (char *) &iostate.c_cc[VSTART], 1, &ds);
	Tcl_ExternalToUtfDStringEx(NULL, NULL, (char *) &iostate.c_cc[VSTART], 1, TCL_ENCODING_PROFILE_TCL8, &ds, NULL);
	Tcl_DStringAppendElement(dsPtr, Tcl_DStringValue(&ds));
	TclDStringClear(&ds);

	Tcl_ExternalToUtfDString(NULL, (char *) &iostate.c_cc[VSTOP], 1, &ds);
	Tcl_ExternalToUtfDStringEx(NULL, NULL, (char *) &iostate.c_cc[VSTOP], 1, TCL_ENCODING_PROFILE_TCL8, &ds, NULL);
	Tcl_DStringAppendElement(dsPtr, Tcl_DStringValue(&ds));
	Tcl_DStringFree(&ds);
    }
    if (len == 0) {
	Tcl_DStringEndSublist(dsPtr);
    }

1047
1048
1049
1050
1051
1052
1053
1054

1055
1056

1057
1058
1059
1060
1061
1062
1063
1222
1223
1224
1225
1226
1227
1228

1229
1230

1231
1232
1233
1234
1235
1236
1237
1238







-
+

-
+








	valid = 1;
	GETREADQUEUE(fsPtr->fileState.fd, inQueue);
	GETWRITEQUEUE(fsPtr->fileState.fd, outQueue);
	inBuffered = Tcl_InputBuffered(fsPtr->fileState.channel);
	outBuffered = Tcl_OutputBuffered(fsPtr->fileState.channel);

	sprintf(buf, "%d", inBuffered+inQueue);
	snprintf(buf, sizeof(buf), "%d", inBuffered+inQueue);
	Tcl_DStringAppendElement(dsPtr, buf);
	sprintf(buf, "%d", outBuffered+outQueue);
	snprintf(buf, sizeof(buf), "%d", outBuffered+outQueue);
	Tcl_DStringAppendElement(dsPtr, buf);
    }

#if defined(TIOCMGET)
    /*
     * Get option -ttystatus
     * Option is readonly and returned by [fconfigure chan -ttystatus] but not
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
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







-
+

-
+








-
+







	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"couldn't read terminal size: %s",
			Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}
	sprintf(buf, "%d", ws.ws_col);
	snprintf(buf, sizeof(buf), "%d", ws.ws_col);
	Tcl_DStringAppendElement(dsPtr, buf);
	sprintf(buf, "%d", ws.ws_row);
	snprintf(buf, sizeof(buf), "%d", ws.ws_row);
	Tcl_DStringAppendElement(dsPtr, buf);
    }
#endif /* TIOCGWINSZ */

    if (valid) {
	return TCL_OK;
    }
    return Tcl_BadChannelOption(interp, optionName,
		"closemode inputmode mode queue ttystatus winsize xchar");
	    "closemode inputmode mode queue ttystatus winsize xchar");
}

static const struct {int baud; speed_t speed;} speeds[] = {
#ifdef B0
    {0, B0},
#endif
#ifdef B50
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
1474
1475

1476
1477
1478
1479
1480
1481
1482

1483
1484
1485
1486
1487
1488
1489
1490
1491

1492
1493
1494
1495
1496
1497
1498
1499

1500
1501
1502
1503
1504
1505
1506
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







-
+










-
+


-
-
-
+
+
+

-
+
+

+
-
+


-
+
-
-
-
-
-
-
-
+








-
+







-
+







	    &parity,
	    &ttyPtr->data,
	    &ttyPtr->stop, &end);
    if ((i != 4) || (mode[end] != '\0')) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "%s: should be baud,parity,data,stop", bad));
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "SERIALMODE", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "SERIALMODE", (char *)NULL);
	}
	return TCL_ERROR;
    }

    /*
     * Only allow setting mark/space parity on platforms that support it Make
     * sure to allow for the case where strchr is a macro. [Bug: 5089]
     *
     * We cannot if/else/endif the strchr arguments, it has to be the whole
     * function. On AIX this function is apparently a macro, and macros do
     * not allow pre-processor directives in their arguments.
     * not allow preprocessor directives in their arguments.
     */

    if (
#if defined(PAREXT)
        strchr("noems", parity)
#ifdef PAREXT
#define PARITY_CHARS	"noems"
#define PARITY_MSG	"n, o, e, m, or s"
#else
        strchr("noe", parity)
#define PARITY_CHARS	"noe"
#define PARITY_MSG	"n, o, or e"
#endif /* PAREXT */

                               == NULL) {
    if (strchr(PARITY_CHARS, parity) == NULL) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "%s parity: should be %s", bad,
		    "%s parity: should be %s", bad, PARITY_MSG));
#if defined(PAREXT)
		    "n, o, e, m, or s"
#else
		    "n, o, or e"
#endif /* PAREXT */
		    ));
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "SERIALMODE", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "SERIALMODE", (char *)NULL);
	}
	return TCL_ERROR;
    }
    ttyPtr->parity = parity;
    if ((ttyPtr->data < 5) || (ttyPtr->data > 8)) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "%s data: should be 5, 6, 7, or 8", bad));
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "SERIALMODE", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "SERIALMODE", (char *)NULL);
	}
	return TCL_ERROR;
    }
    if ((ttyPtr->stop < 0) || (ttyPtr->stop > 2)) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "%s stop: should be 1 or 2", bad));
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "SERIALMODE", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "SERIALMODE", (char *)NULL);
	}
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
1575
1576
1577
1578
1579
1580
1581
1582

1583
1584
1585
1586
1587
1588
1589
1746
1747
1748
1749
1750
1751
1752

1753
1754
1755
1756
1757
1758
1759
1760







-
+







{
    int fd, channelPermissions;
    TtyState *fsPtr;
    const char *native, *translation;
    char channelName[16 + TCL_INTEGER_SPACE];
    const Tcl_ChannelType *channelTypePtr;

    switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) {
    switch (mode & O_ACCMODE) {
    case O_RDONLY:
	channelPermissions = TCL_READABLE;
	break;
    case O_WRONLY:
	channelPermissions = TCL_WRITABLE;
	break;
    case O_RDWR:
1597
1598
1599
1600
1601
1602
1603




















1604
1605
1606

1607
1608
1609
1610
1611
1612
1613
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796

1797
1798
1799
1800
1801
1802
1803
1804







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+







	Tcl_Panic("TclpOpenFileChannel: invalid mode value");
	return NULL;
    }

    native = (const char *)Tcl_FSGetNativePath(pathPtr);
    if (native == NULL) {
	if (interp != (Tcl_Interp *) NULL) {
	    /*
	     * We need this just to ensure we return the correct error messages under
	     * some circumstances (relative paths only), so because the normalization
	     * is very expensive, don't invoke it for native or absolute paths.
	     * Note: since paths starting with ~ are absolute, it also considers tilde expansion,
	     * (proper error message of tests *io-40.17 "tilde substitution in open")
	     */
	    if (
		(
		  (
		    !TclFSCwdIsNative() &&
		    (Tcl_FSGetPathType(pathPtr) != TCL_PATH_ABSOLUTE)
		  ) ||
		  (*TclGetString(pathPtr) == '~')  /* possible tilde expansion */
		) &&
		Tcl_FSGetNormalizedPath(interp, pathPtr) == NULL
	    ) {
		return NULL;
	    }

	    Tcl_AppendResult(interp, "couldn't open \"",
	    TclGetString(pathPtr), "\": filename is invalid on this platform",
	    NULL);
	    (char *)NULL);
	}
	return NULL;
    }

#ifdef DJGPP
    SET_BITS(mode, O_BINARY);
#endif
1645
1646
1647
1648
1649
1650
1651
1652

1653
1654
1655
1656
1657
1658

1659
1660
1661
1662
1663
1664
1665
1836
1837
1838
1839
1840
1841
1842

1843
1844
1845
1846
1847
1848

1849
1850
1851
1852
1853
1854
1855
1856







-
+





-
+







	 * being set up is a device and has the same major/minor as the
	 * initial std FDs (beware reopening!) but that's nearly as messy.
	 */

	translation = "auto crlf";
	channelTypePtr = &ttyChannelType;
	TtyInit(fd);
	sprintf(channelName, "serial%d", fd);
	snprintf(channelName, sizeof(channelName), "serial%d", fd);
    } else
#endif	/* SUPPORTS_TTY */
    {
	translation = NULL;
	channelTypePtr = &fileChannelType;
	sprintf(channelName, "file%d", fd);
	snprintf(channelName, sizeof(channelName), "file%d", fd);
    }

    fsPtr = (TtyState *)Tcl_Alloc(sizeof(TtyState));
    fsPtr->fileState.validMask = channelPermissions | TCL_EXCEPTION;
    fsPtr->fileState.fd = fd;
#ifdef SUPPORTS_TTY
    if (channelTypePtr == &ttyChannelType) {
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
1749
1750
1751
1752
1753
1754
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







-
+






-
+








-
+


-
+














-
+







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

Tcl_Channel
Tcl_MakeFileChannel(
    void *handle,		/* OS level handle. */
    int mode)			/* ORed combination of TCL_READABLE and
    int mode)			/* OR'ed combination of TCL_READABLE and
				 * TCL_WRITABLE to indicate file mode. */
{
    TtyState *fsPtr;
    char channelName[16 + TCL_INTEGER_SPACE];
    int fd = PTR2INT(handle);
    const Tcl_ChannelType *channelTypePtr;
    struct stat buf;
    Tcl_StatBuf buf;

    if (mode == 0) {
	return NULL;
    }

#ifdef SUPPORTS_TTY
    if (isatty(fd)) {
	channelTypePtr = &ttyChannelType;
	sprintf(channelName, "serial%d", fd);
	snprintf(channelName, sizeof(channelName), "serial%d", fd);
    } else
#endif /* SUPPORTS_TTY */
    if (fstat(fd, &buf) == 0 && S_ISSOCK(buf.st_mode)) {
    if (TclOSfstat(fd, &buf) == 0 && S_ISSOCK(buf.st_mode)) {
	struct sockaddr sockaddr;
	socklen_t sockaddrLen = sizeof(sockaddr);

	sockaddr.sa_family = AF_UNSPEC;
	if ((getsockname(fd, (struct sockaddr *)&sockaddr, &sockaddrLen) == 0)
		&& (sockaddrLen > 0)
		&& (sockaddr.sa_family == AF_INET
			|| sockaddr.sa_family == AF_INET6)) {
	    return (Tcl_Channel)TclpMakeTcpClientChannelMode(INT2PTR(fd), mode);
	}
	goto normalChannelAfterAll;
    } else {
    normalChannelAfterAll:
	channelTypePtr = &fileChannelType;
	sprintf(channelName, "file%d", fd);
	snprintf(channelName, sizeof(channelName), "file%d", fd);
    }

    fsPtr = (TtyState *)Tcl_Alloc(sizeof(TtyState));
    fsPtr->fileState.fd = fd;
    fsPtr->fileState.validMask = mode | TCL_EXCEPTION;
    fsPtr->fileState.channel = Tcl_CreateChannel(channelTypePtr, channelName,
	    fsPtr, mode);
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801

1802
1803
1804
1805
1806
1807
1808
1809
1810

1811
1812
1813
1814
1815
1816
1817
1818
1819

1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1980
1981
1982
1983
1984
1985
1986

1987
1988
1989
1990

1991
1992
1993
1994
1995
1996
1997
1998
1999

2000
2001
2002
2003
2004
2005
2006
2007
2008

2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021

2022
2023
2024
2025
2026
2027
2028







-




-
+








-
+








-
+












-







    int mode = 0;		/* compiler warning (used before set). */
    const char *bufMode = NULL;

    /*
     * Some #def's to make the code a little clearer!
     */

#define ZERO_OFFSET	((Tcl_SeekOffset) 0)
#define ERROR_OFFSET	((Tcl_SeekOffset) -1)

    switch (type) {
    case TCL_STDIN:
	if ((TclOSseek(0, ZERO_OFFSET, SEEK_CUR) == ERROR_OFFSET)
	if ((TclOSseek(0, 0, SEEK_CUR) == ERROR_OFFSET)
		&& (errno == EBADF)) {
	    return NULL;
	}
	fd = 0;
	mode = TCL_READABLE;
	bufMode = "line";
	break;
    case TCL_STDOUT:
	if ((TclOSseek(1, ZERO_OFFSET, SEEK_CUR) == ERROR_OFFSET)
	if ((TclOSseek(1, 0, SEEK_CUR) == ERROR_OFFSET)
		&& (errno == EBADF)) {
	    return NULL;
	}
	fd = 1;
	mode = TCL_WRITABLE;
	bufMode = "line";
	break;
    case TCL_STDERR:
	if ((TclOSseek(2, ZERO_OFFSET, SEEK_CUR) == ERROR_OFFSET)
	if ((TclOSseek(2, 0, SEEK_CUR) == ERROR_OFFSET)
		&& (errno == EBADF)) {
	    return NULL;
	}
	fd = 2;
	mode = TCL_WRITABLE;
	bufMode = "none";
	break;
    default:
	Tcl_Panic("TclGetDefaultStdChannel: Unexpected channel type");
	break;
    }

#undef ZERO_OFFSET
#undef ERROR_OFFSET

    channel = Tcl_MakeFileChannel(INT2PTR(fd), mode);
    if (channel == NULL) {
	return NULL;
    }

1878
1879
1880
1881
1882
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
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
2095

2096
2097
2098
2099
2100
2101
2102
2103







-
+















-
+





-
+







    const char *chanID,		/* String that identifies file. */
    int forWriting,		/* 1 means the file is going to be used for
				 * writing, 0 means for reading. */
    TCL_UNUSED(int),		/* Obsolete argument.
				 * Ignored, we always check that
				 * the channel is open for the requested
				 * mode. */
    void **filePtr)	/* Store pointer to FILE structure here. */
    void **filePtr)		/* Store pointer to FILE structure here. */
{
    Tcl_Channel chan;
    int chanMode, fd;
    const Tcl_ChannelType *chanTypePtr;
    void *data;
    FILE *f;

    chan = Tcl_GetChannel(interp, chanID, &chanMode);
    if (chan == NULL) {
	return TCL_ERROR;
    }
    if (forWriting && !(chanMode & TCL_WRITABLE)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"\"%s\" wasn't opened for writing", chanID));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "CHANNEL", "NOT_WRITABLE",
		NULL);
		(char *)NULL);
	return TCL_ERROR;
    } else if (!forWriting && !(chanMode & TCL_READABLE)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"\"%s\" wasn't opened for reading", chanID));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "CHANNEL", "NOT_READABLE",
		NULL);
		(char *)NULL);
	return TCL_ERROR;
    }

    /*
     * We allow creating a FILE * out of file based, pipe based and socket
     * based channels. We currently do not allow any other channel types,
     * because it is likely that stdio will not know what to do with them.
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
2121
2122
2123
2124
2125
2126
2127

2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138

2139
2140
2141
2142
2143
2144
2145
2146







-
+










-
+







	     */

	    f = fdopen(fd, (forWriting ? "w" : "r"));
	    if (f == NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"cannot get a FILE * for \"%s\"", chanID));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "CHANNEL",
			"FILE_FAILURE", NULL);
			"FILE_FAILURE", (char *)NULL);
		return TCL_ERROR;
	    }
	    *filePtr = f;
	    return TCL_OK;
	}
    }

    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "\"%s\" cannot be used to get a FILE *", chanID));
    Tcl_SetErrorCode(interp, "TCL", "VALUE", "CHANNEL", "NO_DESCRIPTOR",
	    NULL);
	    (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * FileTruncateProc --
1969
1970
1971
1972
1973
1974
1975
1976

1977
1978
1979
1980
1981
1982
1983
2158
2159
2160
2161
2162
2163
2164

2165
2166
2167
2168
2169
2170
2171
2172







-
+







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

static int
FileTruncateProc(
    void *instanceData,
    Tcl_WideInt length)
    long long length)
{
    FileState *fsPtr = (FileState *)instanceData;
    int result;

#ifdef HAVE_TYPE_OFF64_T
    /*
     * We assume this goes with the type for now...

Changes to unix/tclUnixCompat.c.

112
113
114
115
116
117
118
119

120
121
122

123
124
125
126
127
128
129
112
113
114
115
116
117
118

119
120
121

122
123
124
125
126
127
128
129







-
+


-
+







static int		CopyHostent(struct hostent *tgtPtr, char *buf,
			    int buflen);
static int		CopyString(const char *src, char *buf, int buflen);

#endif

#ifdef NEED_PW_CLEANER
static void		FreePwBuf(ClientData dummy);
static void		FreePwBuf(void *dummy);
#endif
#ifdef NEED_GR_CLEANER
static void		FreeGrBuf(ClientData dummy);
static void		FreeGrBuf(void *dummy);
#endif
#endif /* TCL_THREADS */

/*
 *---------------------------------------------------------------------------
 *
 * TclUnixSetBlockingMode --
330
331
332
333
334
335
336
337

338
339
340
341
342
343
344
330
331
332
333
334
335
336

337
338
339
340
341
342
343
344







-
+







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

#ifdef NEED_PW_CLEANER
static void
FreePwBuf(
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    Tcl_Free(tsdPtr->pbuf);
}
#endif /* NEED_PW_CLEANER */

513
514
515
516
517
518
519
520

521
522
523
524
525
526
527
513
514
515
516
517
518
519

520
521
522
523
524
525
526
527







-
+







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

#ifdef NEED_GR_CLEANER
static void
FreeGrBuf(
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    Tcl_Free(tsdPtr->gbuf);
}
#endif /* NEED_GR_CLEANER */

548
549
550
551
552
553
554
555

556
557
558

559
560
561
562

563
564
565

566
567
568
569
570
571
572
548
549
550
551
552
553
554

555
556
557

558
559
560
561

562
563
564

565
566
567
568
569
570
571
572







-
+


-
+



-
+


-
+







{
#if !TCL_THREADS || defined(HAVE_MTSAFE_GETHOSTBYNAME)
    return gethostbyname(name);
#else
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

#if defined(HAVE_GETHOSTBYNAME_R_5)
    int h_errno;
    int local_errno;

    return gethostbyname_r(name, &tsdPtr->hent, tsdPtr->hbuf,
			   sizeof(tsdPtr->hbuf), &h_errno);
			   sizeof(tsdPtr->hbuf), &local_errno);

#elif defined(HAVE_GETHOSTBYNAME_R_6)
    struct hostent *hePtr = NULL;
    int h_errno, result;
    int local_errno, result;

    result = gethostbyname_r(name, &tsdPtr->hent, tsdPtr->hbuf,
	    sizeof(tsdPtr->hbuf), &hePtr, &h_errno);
	    sizeof(tsdPtr->hbuf), &hePtr, &local_errno);
    return (result == 0) ? hePtr : NULL;

#elif defined(HAVE_GETHOSTBYNAME_R_3)
    struct hostent_data data;

    return (gethostbyname_r(name, &tsdPtr->hent, &data) == 0)
	    ? &tsdPtr->hent : NULL;
618
619
620
621
622
623
624
625

626
627
628

629
630
631
632

633
634
635

636
637
638
639
640
641
642
618
619
620
621
622
623
624

625
626
627

628
629
630
631

632
633
634

635
636
637
638
639
640
641
642







-
+


-
+



-
+


-
+







{
#if !TCL_THREADS || defined(HAVE_MTSAFE_GETHOSTBYADDR)
    return gethostbyaddr(addr, length, type);
#else
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

#if defined(HAVE_GETHOSTBYADDR_R_7)
    int h_errno;
    int local_errno;

    return gethostbyaddr_r(addr, length, type, &tsdPtr->hent, tsdPtr->hbuf,
	    sizeof(tsdPtr->hbuf), &h_errno);
	    sizeof(tsdPtr->hbuf), &local_errno);

#elif defined(HAVE_GETHOSTBYADDR_R_8)
    struct hostent *hePtr;
    int h_errno;
    int local_errno;

    return (gethostbyaddr_r(addr, length, type, &tsdPtr->hent, tsdPtr->hbuf,
		sizeof(tsdPtr->hbuf), &hePtr, &h_errno) == 0)
		sizeof(tsdPtr->hbuf), &hePtr, &local_errno) == 0)
	    ? &tsdPtr->hent : NULL;
#else
#define NEED_COPYHOSTENT 1
    struct hostent *hePtr;

    Tcl_MutexLock(&compatLock);
    hePtr = gethostbyaddr(addr, length, type);
730
731
732
733
734
735
736
737

738
739
740
741
742
743
744
730
731
732
733
734
735
736

737
738
739
740
741
742
743
744







-
+







#endif /* NEED_COPYGRP */

/*
 *---------------------------------------------------------------------------
 *
 * CopyHostent --
 *
 *      Copies string fields of the hostnent structure to the private buffer,
 *      Copies string fields of the hostent structure to the private buffer,
 *      honouring the size of the buffer.
 *
 * Results:
 *      Number of bytes copied on success or -1 on error (errno = ERANGE)
 *
 * Side effects:
 *      None
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
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







-


-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
+
+
+
+
-

+
+
+











TclWinCPUID(
    int index,		/* Which CPUID value to retrieve. */
    int *regsPtr)	/* Registers after the CPUID. */
{
    int status = TCL_ERROR;

    /* See: <http://en.wikipedia.org/wiki/CPUID> */
#if defined(HAVE_CPUID)
#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
    __asm__ __volatile__("movq %%rbx, %%rsi     \n\t" /* save %rbx */
                 "cpuid            \n\t"
                 "xchgq %%rsi, %%rbx   \n\t" /* restore the old %rbx */
                 : "=a"(regsPtr[0]), "=S"(regsPtr[1]), "=c"(regsPtr[2]), "=d"(regsPtr[3])
                 : "a"(index));
#else
	    "cpuid            \n\t"
	    "xchgq %%rsi, %%rbx   \n\t" /* restore the old %rbx */
	    : "=a"(regsPtr[0]), "=S"(regsPtr[1]), "=c"(regsPtr[2]), "=d"(regsPtr[3])
	    : "a"(index));
    status = TCL_OK;
#elif defined(__i386__) || defined(_M_IX86)
    __asm__ __volatile__("mov %%ebx, %%esi     \n\t" /* save %ebx */
                 "cpuid            \n\t"
                 "xchg %%esi, %%ebx   \n\t" /* restore the old %ebx */
                 : "=a"(regsPtr[0]), "=S"(regsPtr[1]), "=c"(regsPtr[2]), "=d"(regsPtr[3])
                 : "a"(index));
	    "cpuid            \n\t"
	    "xchg %%esi, %%ebx   \n\t" /* restore the old %ebx */
	    : "=a"(regsPtr[0]), "=S"(regsPtr[1]), "=c"(regsPtr[2]), "=d"(regsPtr[3])
	    : "a"(index));
#endif
    status = TCL_OK;
#else
    (void)index;
    (void)regsPtr;
#endif
    return status;
}

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

Changes to unix/tclUnixEvent.c.

1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * tclUnixEvent.c --
 *
 *	This file implements Unix specific event related routines.
 *
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 * Copyright © 1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#ifndef HAVE_COREFOUNDATION	/* Darwin/Mac OS X CoreFoundation notifier is
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
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







-
+




















+
+









	if (vdelay.usec < 0) {
	    vdelay.usec += 1000000;
	    vdelay.sec  -= 1;
	}

	if ((vdelay.sec != 0) || (vdelay.usec != 0)) {
	    tclScaleTimeProcPtr(&vdelay, tclTimeClientData);
	    TclScaleTime(&vdelay);
	}

	delay.tv_sec  = vdelay.sec;
	delay.tv_usec = vdelay.usec;

	/*
	 * Special note: must convert delay.tv_sec to int before comparing to
	 * zero, since delay.tv_usec is unsigned on some platforms.
	 */

	if ((((int) delay.tv_sec) < 0)
		|| ((delay.tv_usec == 0) && (delay.tv_sec == 0))) {
	    break;
	}
	(void) select(0, (SELECT_MASK *) 0, (SELECT_MASK *) 0,
		(SELECT_MASK *) 0, &delay);
	Tcl_GetTime(&before);
    }
}

#else
TCL_MAC_EMPTY_FILE(unix_tclUnixEvent_c)
#endif /* HAVE_COREFOUNDATION */
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to unix/tclUnixFCmd.c.

1
2
3
4

5
6
7
8

9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
1
2
3

4
5
6
7

8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23



-
+



-
+







-
+







/*
 * tclUnixFCmd.c
 *
 *	This file implements the unix specific portion of file manipulation
 *	This file implements the Unix specific portion of file manipulation
 *	subcommands of the "file" command. All filename arguments should
 *	already be translated to native format.
 *
 * Copyright (c) 1996-1998 Sun Microsystems, Inc.
 * Copyright © 1996-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * Portions of this code were derived from NetBSD source code which has the
 * following copyright notice:
 *
 * Copyright (c) 1988, 1993, 1994
 * Copyright © 1988, 1993, 1994
 *      The Regents of the University of California. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
262
263
264
265
266
267
268
269
270
271
272

273
274
275
276
277
278
279
262
263
264
265
266
267
268




269
270
271
272
273
274
275
276







-
-
-
-
+







/*
 * At least TclpObjNormalizedPath now requires REALPATH
*/
#error NO_REALPATH is not supported
#endif /* NO_REALPATH */

#ifdef HAVE_FTS
#if defined(HAVE_STRUCT_STAT64) && !defined(__APPLE__)
/* fts doesn't do stat64 */
#   define noFtsStat	1
#elif defined(__APPLE__) && defined(__LP64__) && \
#if defined(__APPLE__) && defined(__LP64__) && \
	defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
	MAC_OS_X_VERSION_MIN_REQUIRED < 1050
/*
 * Prior to Darwin 9, 64bit fts_open() without FTS_NOSTAT may crash (due to a
 * 64bit-unsafe ALIGN macro); if we could be running on pre-10.5 OSX, check
 * Darwin release at runtime and do a separate stat() if necessary.
 */
339
340
341
342
343
344
345
346

347
348
349
350
351
352
353
336
337
338
339
340
341
342

343
344
345
346
347
348
349
350







-
+







	return TCL_OK;
    }
    if (errno == ENOTEMPTY) {
	errno = EEXIST;
    }

    /*
     * IRIX returns EIO when you attept to move a directory into itself. We
     * IRIX returns EIO when you attempt to move a directory into itself. We
     * just map EIO to EINVAL get the right message on SGI. Most platforms
     * don't return EIO except in really strange cases.
     */

    if (errno == EIO) {
	errno = EINVAL;
    }
483
484
485
486
487
488
489
490

491
492
493
494
495
496
497
498
480
481
482
483
484
485
486

487

488
489
490
491
492
493
494







-
+
-








    switch ((int) (statBufPtr->st_mode & S_IFMT)) {
#ifndef DJGPP
    case S_IFLNK: {
	char linkBuf[MAXPATHLEN+1];
	int length;

	length = readlink(src, linkBuf, MAXPATHLEN);
	length = readlink(src, linkBuf, MAXPATHLEN);	/* INTL: Native. */
							/* INTL: Native. */
	if (length == -1) {
	    return TCL_ERROR;
	}
	linkBuf[length] = '\0';
	if (symlink(linkBuf, dst) < 0) {		/* INTL: Native. */
	    return TCL_ERROR;
	}
545
546
547
548
549
550
551
552

553
554
555
556
557
558
559
541
542
543
544
545
546
547

548
549
550
551
552
553
554
555







-
+







    const Tcl_StatBuf *statBufPtr,
				/* Used to determine mode and blocksize. */
    int dontCopyAtts)		/* If flag set, don't copy attributes. */
{
    int srcFd, dstFd;
    size_t blockSize;		/* Optimal I/O blocksize for filesystem */
    char *buffer;		/* Data buffer for copy */
    size_t nread;
    ssize_t nread;

#ifdef DJGPP
#define BINMODE |O_BINARY
#else
#define BINMODE
#endif /* DJGPP */

602
603
604
605
606
607
608
609

610
611
612
613


614
615
616
617
618
619
620

621
622
623
624
625
626
627
598
599
600
601
602
603
604

605
606
607


608
609
610
611
612
613
614
615

616
617
618
619
620
621
622
623







-
+


-
-
+
+






-
+








    if (blockSize <= 0) {
	blockSize = DEFAULT_COPY_BLOCK_SIZE;
    }
    buffer = (char *)Tcl_Alloc(blockSize);
    while (1) {
	nread = read(srcFd, buffer, blockSize);
	if ((nread == TCL_IO_FAILURE) || (nread == 0)) {
	if ((nread == -1) || (nread == 0)) {
	    break;
	}
	if ((size_t) write(dstFd, buffer, nread) != nread) {
	    nread = TCL_IO_FAILURE;
	if (write(dstFd, buffer, nread) != nread) {
	    nread = -1;
	    break;
	}
    }

    Tcl_Free(buffer);
    close(srcFd);
    if ((close(dstFd) != 0) || (nread == TCL_IO_FAILURE)) {
    if ((close(dstFd) != 0) || (nread == -1)) {
	unlink(dst);					/* INTL: Native. */
	return TCL_ERROR;
    }
    if (!dontCopyAtts && CopyFileAtts(src, dst, statBufPtr) == TCL_ERROR) {
	/*
	 * The copy succeeded, but setting the permissions failed, so be in a
	 * consistent state, we remove the file that was created by the copy.
729
730
731
732
733
734
735
736

737
738
739
740
741
742
743
725
726
727
728
729
730
731

732
733
734
735
736
737
738
739







-
+







/*
 *---------------------------------------------------------------------------
 *
 * TclpObjCopyDirectory --
 *
 *	Recursively copies a directory. The target directory dst must not
 *	already exist. Note that this function does not merge two directory
 *	hierarchies, even if the target directory is an an empty directory.
 *	hierarchies, even if the target directory is an empty directory.
 *
 * Results:
 *	If the directory was successfully copied, returns TCL_OK. Otherwise
 *	the return value is TCL_ERROR, errno is set to indicate the error, and
 *	the pathname of the file that caused the error is stored in errorPtr.
 *	See TclpObjCreateDirectory and TclpObjCopyFile for a description of
 *	possible values for errno.
758
759
760
761
762
763
764
765

766
767

768
769
770



771
772


773
774
775
776
777
778
779
780
781
782
783
















784
785
786
787
788
789
790
791
792
793
754
755
756
757
758
759
760

761
762

763
764
765
766
767
768
769


770
771
772










773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789


790
791
792
793
794
795
796







-
+

-
+



+
+
+
-
-
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-







{
    Tcl_DString ds;
    Tcl_DString srcString, dstString;
    int ret;
    Tcl_Obj *transPtr;

    transPtr = Tcl_FSGetTranslatedPath(NULL,srcPathPtr);
    Tcl_UtfToExternalDString(NULL,
    ret = Tcl_UtfToExternalDStringEx(NULL, NULL,
	    (transPtr != NULL ? TclGetString(transPtr) : NULL),
	    -1, &srcString);
	    -1, 0, &srcString, NULL);
    if (transPtr != NULL) {
	Tcl_DecrRefCount(transPtr);
    }
    if (ret != TCL_OK) {
	*errorPtr = srcPathPtr;
    } else {
    transPtr = Tcl_FSGetTranslatedPath(NULL,destPathPtr);
    Tcl_UtfToExternalDString(NULL,
	transPtr = Tcl_FSGetTranslatedPath(NULL,destPathPtr);
	ret = Tcl_UtfToExternalDStringEx(NULL, NULL,
	    (transPtr != NULL ? TclGetString(transPtr) : NULL),
	    -1, &dstString);
    if (transPtr != NULL) {
	Tcl_DecrRefCount(transPtr);
    }

    ret = TraverseUnixTree(TraversalCopy, &srcString, &dstString, &ds, 0);

    Tcl_DStringFree(&srcString);
    Tcl_DStringFree(&dstString);

	    -1, TCL_ENCODING_PROFILE_TCL8, &dstString, NULL);
	if (transPtr != NULL) {
	    Tcl_DecrRefCount(transPtr);
	}
	if (ret != TCL_OK) {
	    *errorPtr = destPathPtr;
	} else {
	    ret = TraverseUnixTree(TraversalCopy, &srcString, &dstString, &ds, 0);
	    /* Note above call only sets ds on error */
	    if (ret != TCL_OK) {
		*errorPtr = Tcl_DStringToObj(&ds);
	    }
	    Tcl_DStringFree(&dstString);
	}
	Tcl_DStringFree(&srcString);
    }
    if (ret != TCL_OK) {
	*errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1);
	Tcl_DStringFree(&ds);
	Tcl_IncrRefCount(*errorPtr);
    }
    return ret;
}

/*
 *---------------------------------------------------------------------------
802
803
804
805
806
807
808
809

810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829

830
831

832
833
834



835
836
837








838
839
840
841
842
843
844
845
846
847
805
806
807
808
809
810
811

812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831

832
833

834
835
836
837
838
839
840



841
842
843
844
845
846
847
848
849


850
851
852
853
854
855
856







-
+



















-
+

-
+



+
+
+
-
-
-
+
+
+
+
+
+
+
+

-
-







 *	the pathname of the file that caused the error is stored in errorPtr.
 *	Some possible values for errno are:
 *
 *	EACCES:	    path directory can't be read and/or written.
 *	EEXIST:	    path is a non-empty directory.
 *	EINVAL:	    path is a root directory.
 *	ENOENT:	    path doesn't exist or is "".
 * 	ENOTDIR:    path is not a directory.
 *	ENOTDIR:    path is not a directory.
 *
 * Side effects:
 *	Directory removed. If an error occurs, the error will be returned
 *	immediately, and remaining files will not be deleted.
 *
 *---------------------------------------------------------------------------
 */

int
TclpObjRemoveDirectory(
    Tcl_Obj *pathPtr,
    int recursive,
    Tcl_Obj **errorPtr)
{
    Tcl_DString ds;
    Tcl_DString pathString;
    int ret;
    Tcl_Obj *transPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);

    Tcl_UtfToExternalDString(NULL,
    ret = Tcl_UtfToExternalDStringEx(NULL, NULL,
	    (transPtr != NULL ? TclGetString(transPtr) : NULL),
	    -1, &pathString);
	    -1, TCL_ENCODING_PROFILE_TCL8, &pathString, NULL);
    if (transPtr != NULL) {
	Tcl_DecrRefCount(transPtr);
    }
    if (ret != TCL_OK) {
	*errorPtr = pathPtr;
    } else {
    ret = DoRemoveDirectory(&pathString, recursive, &ds);
    Tcl_DStringFree(&pathString);

	ret = DoRemoveDirectory(&pathString, recursive, &ds);
	Tcl_DStringFree(&pathString);
	/* Note above call only sets ds on error */
	if (ret != TCL_OK) {
	    *errorPtr = Tcl_DStringToObj(&ds);
	}
    }

    if (ret != TCL_OK) {
	*errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1);
	Tcl_DStringFree(&ds);
	Tcl_IncrRefCount(*errorPtr);
    }
    return ret;
}

static int
DoRemoveDirectory(
882
883
884
885
886
887
888
889

890
891
892
893
894
895
896
891
892
893
894
895
896
897

898
899
900
901
902
903
904
905







-
+







    if (errno == ENOTEMPTY) {
	errno = EEXIST;
    }

    result = TCL_OK;
    if ((errno != EEXIST) || (recursive == 0)) {
	if (errorPtr != NULL) {
	    Tcl_ExternalToUtfDString(NULL, path, -1, errorPtr);
	    Tcl_ExternalToUtfDStringEx(NULL, NULL, path, TCL_INDEX_NONE, 0, errorPtr, NULL);
	}
	result = TCL_ERROR;
    }

    /*
     * The directory is nonempty, but the recursive flag has been specified,
     * so we recursively remove all the files in the directory.
940
941
942
943
944
945
946
947
948
949
950
951
952






953
954
955
956
957
958
959
949
950
951
952
953
954
955






956
957
958
959
960
961
962
963
964
965
966
967
968







-
-
-
-
-
-
+
+
+
+
+
+







				 * traversed (native). */
    Tcl_DString *targetPtr,	/* Pathname of directory to traverse in
				 * parallel with source directory (native). */
    Tcl_DString *errorPtr,	/* If non-NULL, uninitialized or free DString
				 * filled with UTF-8 name of file causing
				 * error. */
    int doRewind)		/* Flag indicating that to ensure complete
    				 * traversal of source hierarchy, the readdir
    				 * loop should be rewound whenever
    				 * traverseProc has returned TCL_OK; this is
    				 * required when traverseProc modifies the
    				 * source hierarchy, e.g. by deleting
    				 * files. */
				 * traversal of source hierarchy, the readdir
				 * loop should be rewound whenever
				 * traverseProc has returned TCL_OK; this is
				 * required when traverseProc modifies the
				 * source hierarchy, e.g. by deleting
				 * files. */
{
    Tcl_StatBuf statBuf;
    const char *source, *errfile;
    int result;
    size_t targetLen, sourceLen;
#ifndef HAVE_FTS
    int numProcessed = 0;
1014
1015
1016
1017
1018
1019
1020
1021

1022
1023

1024
1025
1026
1027
1028
1029
1030
1023
1024
1025
1026
1027
1028
1029

1030
1031

1032
1033
1034
1035
1036
1037
1038
1039







-
+

-
+







	    continue;
	}

	/*
	 * Append name after slash, and recurse on the file.
	 */

	Tcl_DStringAppend(sourcePtr, dirEntPtr->d_name, -1);
	Tcl_DStringAppend(sourcePtr, dirEntPtr->d_name, TCL_INDEX_NONE);
	if (targetPtr != NULL) {
	    Tcl_DStringAppend(targetPtr, dirEntPtr->d_name, -1);
	    Tcl_DStringAppend(targetPtr, dirEntPtr->d_name, TCL_INDEX_NONE);
	}
	result = TraverseUnixTree(traverseProc, sourcePtr, targetPtr,
		errorPtr, doRewind);
	if (result != TCL_OK) {
	    break;
	} else {
	    numProcessed++;
1131
1132
1133
1134
1135
1136
1137
1138

1139
1140
1141
1142
1143
1144
1145
1140
1141
1142
1143
1144
1145
1146

1147
1148
1149
1150
1151
1152
1153
1154







-
+







	}
    }
#endif /* !HAVE_FTS */

  end:
    if (errfile != NULL) {
	if (errorPtr != NULL) {
	    Tcl_ExternalToUtfDString(NULL, errfile, -1, errorPtr);
	    Tcl_ExternalToUtfDStringEx(NULL, NULL, errfile, TCL_INDEX_NONE, 0, errorPtr, NULL);
	}
	result = TCL_ERROR;
    }
#ifdef HAVE_FTS
    if (fts != NULL) {
	fts_close(fts);
    }
1201
1202
1203
1204
1205
1206
1207
1208
1209


1210
1211
1212
1213
1214
1215
1216
1210
1211
1212
1213
1214
1215
1216


1217
1218
1219
1220
1221
1222
1223
1224
1225







-
-
+
+








    /*
     * There shouldn't be a problem with src, because we already checked it to
     * get here.
     */

    if (errorPtr != NULL) {
	Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(dstPtr),
		Tcl_DStringLength(dstPtr), errorPtr);
	Tcl_ExternalToUtfDStringEx(NULL, NULL, Tcl_DStringValue(dstPtr),
		Tcl_DStringLength(dstPtr), 0, errorPtr, NULL);
    }
    return TCL_ERROR;
}

/*
 *---------------------------------------------------------------------------
 *
1252
1253
1254
1255
1256
1257
1258
1259
1260


1261
1262
1263
1264
1265
1266
1267
1261
1262
1263
1264
1265
1266
1267


1268
1269
1270
1271
1272
1273
1274
1275
1276







-
-
+
+







    case DOTREE_POSTD:
	if (DoRemoveDirectory(srcPtr, 0, NULL) == 0) {
	    return TCL_OK;
	}
	break;
    }
    if (errorPtr != NULL) {
	Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(srcPtr),
		Tcl_DStringLength(srcPtr), errorPtr);
	Tcl_ExternalToUtfDStringEx(NULL, NULL, Tcl_DStringValue(srcPtr),
		Tcl_DStringLength(srcPtr), 0, errorPtr, NULL);
    }
    return TCL_ERROR;
}

/*
 *---------------------------------------------------------------------------
 *
1367
1368
1369
1370
1371
1372
1373
1374
1375


1376
1377
1378
1379
1380
1381
1382
1376
1377
1378
1379
1380
1381
1382


1383
1384
1385
1386
1387
1388
1389
1390
1391







-
-
+
+








    if (groupPtr == NULL) {
	TclNewIntObj(*attributePtrPtr, statBuf.st_gid);
    } else {
	Tcl_DString ds;
	const char *utf;

	utf = Tcl_ExternalToUtfDString(NULL, groupPtr->gr_name, -1, &ds);
	*attributePtrPtr = Tcl_NewStringObj(utf, -1);
	utf = Tcl_ExternalToUtfDString(NULL, groupPtr->gr_name, TCL_INDEX_NONE, &ds);
	*attributePtrPtr = Tcl_NewStringObj(utf, TCL_INDEX_NONE);
	Tcl_DStringFree(&ds);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
1420
1421
1422
1423
1424
1425
1426
1427
1428


1429
1430
1431
1432
1433
1434
1435
1429
1430
1431
1432
1433
1434
1435


1436
1437
1438
1439
1440
1441
1442
1443
1444







-
-
+
+







    pwPtr = TclpGetPwUid(statBuf.st_uid);

    if (pwPtr == NULL) {
	TclNewIntObj(*attributePtrPtr, statBuf.st_uid);
    } else {
	Tcl_DString ds;

	(void) Tcl_ExternalToUtfDString(NULL, pwPtr->pw_name, -1, &ds);
	*attributePtrPtr = TclDStringToObj(&ds);
	(void)Tcl_ExternalToUtfDString(NULL, pwPtr->pw_name, TCL_INDEX_NONE, &ds);
	*attributePtrPtr = Tcl_DStringToObj(&ds);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
1465
1466
1467
1468
1469
1470
1471
1472

1473
1474
1475
1476
1477
1478
1479
1474
1475
1476
1477
1478
1479
1480

1481
1482
1483
1484
1485
1486
1487
1488







-
+







		    "could not read \"%s\": %s",
		    TclGetString(fileName), Tcl_PosixError(interp)));
	}
	return TCL_ERROR;
    }

    *attributePtrPtr = Tcl_ObjPrintf(
	    "%0#5lo", (long) (statBuf.st_mode & 0x00007FFF));
	    "%0#5o", ((int)statBuf.st_mode & 0x7FFF));
    return TCL_OK;
}

/*
 *---------------------------------------------------------------------------
 *
 * SetGroupAttribute --
1496
1497
1498
1499
1500
1501
1502
1503

1504
1505
1506
1507

1508
1509
1510
1511





1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522

1523
1524
1525
1526
1527
1528
1529
1505
1506
1507
1508
1509
1510
1511

1512
1513
1514
1515

1516
1517
1518
1519

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

1535
1536
1537
1538
1539
1540
1541
1542







-
+



-
+



-
+
+
+
+
+










-
+







    Tcl_Obj *fileName,		/* The name of the file (UTF-8). */
    Tcl_Obj *attributePtr)	/* New group for file. */
{
    Tcl_WideInt gid;
    int result;
    const char *native;

    if (Tcl_GetWideIntFromObj(NULL, attributePtr, &gid) != TCL_OK) {
    if (TclGetWideIntFromObj(NULL, attributePtr, &gid) != TCL_OK) {
	Tcl_DString ds;
	struct group *groupPtr = NULL;
	const char *string;
	size_t length;
	Tcl_Size length;

	string = TclGetStringFromObj(attributePtr, &length);

	native = Tcl_UtfToExternalDString(NULL, string, length, &ds);
	if (Tcl_UtfToExternalDStringEx(interp, NULL, string, length, 0, &ds, NULL) != TCL_OK) {
	    Tcl_DStringFree(&ds);
	    return TCL_ERROR;
	}
	native = Tcl_DStringValue(&ds);
	groupPtr = TclpGetGrNam(native); /* INTL: Native. */
	Tcl_DStringFree(&ds);

	if (groupPtr == NULL) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"could not set group for file \"%s\":"
			" group \"%s\" does not exist",
			TclGetString(fileName), string));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SETGRP",
			"NO_GROUP", NULL);
			"NO_GROUP", (char *)NULL);
	    }
	    return TCL_ERROR;
	}
	gid = groupPtr->gr_gid;
    }

    native = (const char *)Tcl_FSGetNativePath(fileName);
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
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







-
+



-
+



-
+
+
+
+
+










-
+







    Tcl_Obj *fileName,		/* The name of the file (UTF-8). */
    Tcl_Obj *attributePtr)	/* New owner for file. */
{
    Tcl_WideInt uid;
    int result;
    const char *native;

    if (Tcl_GetWideIntFromObj(NULL, attributePtr, &uid) != TCL_OK) {
    if (TclGetWideIntFromObj(NULL, attributePtr, &uid) != TCL_OK) {
	Tcl_DString ds;
	struct passwd *pwPtr = NULL;
	const char *string;
	size_t length;
	Tcl_Size length;

	string = TclGetStringFromObj(attributePtr, &length);

	native = Tcl_UtfToExternalDString(NULL, string, length, &ds);
	if (Tcl_UtfToExternalDStringEx(interp, NULL, string, length, 0, &ds, NULL) != TCL_OK) {
	    Tcl_DStringFree(&ds);
	    return TCL_ERROR;
	}
	native = Tcl_DStringValue(&ds);
	pwPtr = TclpGetPwNam(native);			/* INTL: Native. */
	Tcl_DStringFree(&ds);

	if (pwPtr == NULL) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"could not set owner for file \"%s\":"
			" user \"%s\" does not exist",
			TclGetString(fileName), string));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SETOWN",
			"NO_USER", NULL);
			"NO_USER", (char *)NULL);
	    }
	    return TCL_ERROR;
	}
	uid = pwPtr->pw_uid;
    }

    native = (const char *)Tcl_FSGetNativePath(fileName);
1644
1645
1646
1647
1648
1649
1650
1651
1652


1653
1654
1655
1656

1657
1658
1659
1660
1661
1662
1663
1661
1662
1663
1664
1665
1666
1667


1668
1669
1670
1671
1672

1673
1674
1675
1676
1677
1678
1679
1680







-
-
+
+



-
+







    if ((modeStringPtr[scanned] == '0')
	    && (modeStringPtr[scanned+1] >= '0')
	    && (modeStringPtr[scanned+1] <= '7')) {
	/* Leading zero - attempt octal interpretation */
	Tcl_Obj *modeObj;

	TclNewLiteralStringObj(modeObj, "0o");
	Tcl_AppendToObj(modeObj, modeStringPtr+scanned+1, -1);
	result = Tcl_GetWideIntFromObj(NULL, modeObj, &mode);
	Tcl_AppendToObj(modeObj, modeStringPtr+scanned+1, TCL_INDEX_NONE);
	result = TclGetWideIntFromObj(NULL, modeObj, &mode);
	Tcl_DecrRefCount(modeObj);
    }
    if (result == TCL_OK
	    || Tcl_GetWideIntFromObj(NULL, attributePtr, &mode) == TCL_OK) {
	    || TclGetWideIntFromObj(NULL, attributePtr, &mode) == TCL_OK) {
	newMode = (mode_t) (mode & 0x00007FFF);
    } else {
	Tcl_StatBuf buf;

	/*
	 * Try the forms "rwxrwxrwx" and "ugo=rwx"
	 *
1677
1678
1679
1680
1681
1682
1683
1684

1685
1686
1687
1688
1689
1690
1691
1694
1695
1696
1697
1698
1699
1700

1701
1702
1703
1704
1705
1706
1707
1708







-
+







	newMode = (mode_t) (buf.st_mode & 0x00007FFF);

	if (GetModeFromPermString(NULL, modeStringPtr, &newMode) != TCL_OK) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"unknown permission string format \"%s\"",
			modeStringPtr));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "PERMISSION", NULL);
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "PERMISSION", (char *)NULL);
	    }
	    return TCL_ERROR;
	}
    }

    native = (const char *)Tcl_FSGetNativePath(fileName);
    result = chmod(native, newMode);		/* INTL: Native. */
1764
1765
1766
1767
1768
1769
1770
1771

1772
1773
1774
1775
1776
1777
1778
1781
1782
1783
1784
1785
1786
1787

1788
1789
1790
1791
1792
1793
1794
1795







-
+








    if (strlen(modeStringPtr) != 9) {
	goto chmodStyleCheck;
    }

    newMode = 0;
    for (i = 0; i < 9; i++) {
	switch (*(modeStringPtr+i)) {
	switch (modeStringPtr[i]) {
	case 'r':
	    if ((i%3) != 0) {
		goto chmodStyleCheck;
	    }
	    newMode |= (1<<(8-i));
	    break;
	case 'w':
1826
1827
1828
1829
1830
1831
1832
1833

1834
1835
1836

1837
1838
1839

1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860

1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878

1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899

1900
1901
1902
1903
1904
1905
1906
1843
1844
1845
1846
1847
1848
1849

1850
1851
1852

1853
1854
1855

1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876

1877
1878
1879
1880
1881
1882
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







-
+


-
+


-
+




















-
+

















-
+




















-
+







    return TCL_OK;

  chmodStyleCheck:
    /*
     * We now check for an "ugoa+-=rwxst" style permissions string
     */

    for (n = 0 ; *(modeStringPtr+n) != '\0' ; n = n + i) {
    for (n = 0 ; modeStringPtr[n] != '\0' ; n += i) {
	oldMode = *modePtr;
	who = op = what = op_found = who_found = 0;
	for (i = 0 ; *(modeStringPtr+n+i) != '\0' ; i++ ) {
	for (i = 0 ; modeStringPtr[n + i] != '\0' ; i++ ) {
	    if (!who_found) {
		/* who */
		switch (*(modeStringPtr+n+i)) {
		switch (modeStringPtr[n + i]) {
		case 'u':
		    who |= 0x9C0;
		    continue;
		case 'g':
		    who |= 0x438;
		    continue;
		case 'o':
		    who |= 0x207;
		    continue;
		case 'a':
		    who |= 0xFFF;
		    continue;
		}
	    }
	    who_found = 1;
	    if (who == 0) {
		who = 0xFFF;
	    }
	    if (!op_found) {
		/* op */
		switch (*(modeStringPtr+n+i)) {
		switch (modeStringPtr[n + i]) {
		case '+':
		    op = 1;
		    op_found = 1;
		    continue;
		case '-':
		    op = 2;
		    op_found = 1;
		    continue;
		case '=':
		    op = 3;
		    op_found = 1;
		    continue;
		default:
		    return TCL_ERROR;
		}
	    }
	    /* what */
	    switch (*(modeStringPtr+n+i)) {
	    switch (modeStringPtr[n + i]) {
	    case 'r':
		what |= 0x124;
		continue;
	    case 'w':
		what |= 0x92;
		continue;
	    case 'x':
		what |= 0x49;
		continue;
	    case 's':
		what |= 0xC00;
		continue;
	    case 't':
		what |= 0x200;
		continue;
	    case ',':
		break;
	    default:
		return TCL_ERROR;
	    }
	    if (*(modeStringPtr+n+i) == ',') {
	    if (modeStringPtr[n + i] == ',') {
		i++;
		break;
	    }
	}
	switch (op) {
	case 1:
	    *modePtr = oldMode | (who & what);
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
1948
1949
1950
1951
1952
1953
1954

1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966

1967
1968
1969
1970
1971
1972
1973
1974







-
+











-
+







 * Side effects:
 *
 *---------------------------------------------------------------------------
 */

int
TclpObjNormalizePath(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Interp *interp,
    Tcl_Obj *pathPtr,		/* An unshared object containing the path to
				 * normalize. */
    int nextCheckpoint)		/* offset to start at in pathPtr.  Must either
				 * be 0 or the offset of a directory separator
				 * at the end of a path part that is already
				 * normalized.  I.e. this is not the index of
				 * the byte just after the separator.  */

{
    const char *currentPathEndPosition;
    char cur;
    size_t pathLen;
    Tcl_Size pathLen;
    const char *path = TclGetStringFromObj(pathPtr, &pathLen);
    Tcl_DString ds;
    const char *nativePath;
#ifndef NO_REALPATH
    char normPath[MAXPATHLEN];
#endif

1965
1966
1967
1968
1969
1970
1971
1972
1973






1974
1975
1976
1977
1978
1979
1980
1982
1983
1984
1985
1986
1987
1988


1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001







-
-
+
+
+
+
+
+







	/*
	 * Try to get the entire path in one go
	 */

	const char *lastDir = strrchr(currentPathEndPosition, '/');

	if (lastDir != NULL) {
	    nativePath = Tcl_UtfToExternalDString(NULL, path,
		    lastDir-path, &ds);
	    if (Tcl_UtfToExternalDStringEx(interp, NULL, path,
		    lastDir-path, 0, &ds, NULL) != TCL_OK) {
		Tcl_DStringFree(&ds);
		return -1;
	    }
	    nativePath = Tcl_DStringValue(&ds);
	    if (Realpath(nativePath, normPath) != NULL) {
		if (*nativePath != '/' && *normPath == '/') {
		    /*
		     * realpath transformed a relative path into an
		     * absolute path.  Fall back to the long way.
		     */

2001
2002
2003
2004
2005
2006
2007
2008
2009






2010
2011
2012
2013
2014
2015
2016
2022
2023
2024
2025
2026
2027
2028


2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041







-
-
+
+
+
+
+
+







	if ((cur == '/') && (path != currentPathEndPosition)) {
	    /*
	     * Reached directory separator.
	     */

	    int accessOk;

	    nativePath = Tcl_UtfToExternalDString(NULL, path,
		    currentPathEndPosition - path, &ds);
	    if (Tcl_UtfToExternalDStringEx(interp, NULL, path,
		    currentPathEndPosition - path, 0, &ds, NULL) != TCL_OK) {
		Tcl_DStringFree(&ds);
		return -1;
	    }
	    nativePath = Tcl_DStringValue(&ds);
	    accessOk = access(nativePath, F_OK);
	    Tcl_DStringFree(&ds);

	    if (accessOk != 0) {
		/*
		 * File doesn't exist.
		 */
2037
2038
2039
2040
2041
2042
2043
2044

2045
2046
2047
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
2095
2096
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
2095
2096
2097
2098
2099

2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117

2118
2119
2120
2121
2122
2123
2124
2125







-
+








-
+
+
+
+
+

-
+















-
+

















-
+







     * Call 'realpath' to obtain a canonical path.
     */

#ifndef NO_REALPATH
    if (haveRealpath) {
	if (nextCheckpoint == 0) {
	    /*
	     * The path contains at most one component, e.g. '/foo' or '/', so
	     * The path contains at most one component, e.g. '/foo' or '/',
	     * so there is nothing to resolve. Also, on some platforms
	     * 'Realpath' transforms an empty string into the normalized pwd,
	     * which is the wrong answer.
	     */

	    return 0;
	}

	nativePath = Tcl_UtfToExternalDString(NULL, path,nextCheckpoint, &ds);
	if (Tcl_UtfToExternalDStringEx(interp, NULL, path,nextCheckpoint, 0, &ds, NULL)) {
	    Tcl_DStringFree(&ds);
	    return -1;
	}
	nativePath = Tcl_DStringValue(&ds);
	if (Realpath(nativePath, normPath) != NULL) {
	    size_t newNormLen;
	    Tcl_Size newNormLen;

	wholeStringOk:
	    newNormLen = strlen(normPath);
	    if ((newNormLen == Tcl_DStringLength(&ds))
		    && (strcmp(normPath, nativePath) == 0)) {
		/*
		 * The original path is unchanged.
		 */

		Tcl_DStringFree(&ds);

		/*
		 * Uncommenting this would mean that this native filesystem
		 * routine claims the path is normalized if the file exists,
		 * which would permit the caller to avoid iterating through
		 * other filesystems filesystems. Saving lots of calls is
		 * other filesystems. Saving lots of calls is
		 * probably worth the extra access() time, but in the common
		 * case that no other filesystems are registered this is an
		 * unnecessary expense.
		 *
		if (0 == access(normPath, F_OK)) {
		    return pathLen;
		}
		 */

		return nextCheckpoint;
	    }

	    /*
	     * Free the original path and replace it with the normalized path.
	     */

	    Tcl_DStringFree(&ds);
	    Tcl_ExternalToUtfDString(NULL, normPath, newNormLen, &ds);
	    Tcl_ExternalToUtfDStringEx(NULL, NULL, normPath, newNormLen, 0, &ds, NULL);

	    if (path[nextCheckpoint] != '\0') {
		/*
		 * Append the remaining path components.
		 */

		int normLen = Tcl_DStringLength(&ds);
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





2222
2223
2224
2225
2226
2227
2228
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
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







-
+


-
+




-
+
+
+


-
+






-
+
+
+
+











-
+
+
+
+















-
-
+
+
+
+
+







    Tcl_Obj *basenameObj,
    Tcl_Obj *extensionObj,
    Tcl_Obj *resultingNameObj)
{
    Tcl_DString templ, tmp;
    const char *string;
    int fd;
    size_t length;
    Tcl_Size length;

    /*
     * We should also check against making more then TMP_MAX of these.
     * We should also check against making more than TMP_MAX of these.
     */

    if (dirObj) {
	string = TclGetStringFromObj(dirObj, &length);
	Tcl_UtfToExternalDString(NULL, string, length, &templ);
	if (Tcl_UtfToExternalDStringEx(NULL, NULL, string, length, 0, &templ, NULL) != TCL_OK) {
	    return -1;
	}
    } else {
	Tcl_DStringInit(&templ);
	Tcl_DStringAppend(&templ, DefaultTempDir(), -1); /* INTL: native */
	Tcl_DStringAppend(&templ, DefaultTempDir(), TCL_INDEX_NONE); /* INTL: native */
    }

    TclDStringAppendLiteral(&templ, "/");

    if (basenameObj) {
	string = TclGetStringFromObj(basenameObj, &length);
	Tcl_UtfToExternalDString(NULL, string, length, &tmp);
	if (Tcl_UtfToExternalDStringEx(NULL, NULL, string, length, 0, &tmp, NULL) != TCL_OK) {
	    Tcl_DStringFree(&tmp);
	    return -1;
	}
	TclDStringAppendDString(&templ, &tmp);
	Tcl_DStringFree(&tmp);
    } else {
	TclDStringAppendLiteral(&templ, "tcl");
    }

    TclDStringAppendLiteral(&templ, "_XXXXXX");

#ifdef HAVE_MKSTEMPS
    if (extensionObj) {
	string = TclGetStringFromObj(extensionObj, &length);
	Tcl_UtfToExternalDString(NULL, string, length, &tmp);
	if (Tcl_UtfToExternalDStringEx(NULL, NULL, string, length, 0, &tmp, NULL) != TCL_OK) {
	    Tcl_DStringFree(&templ);
	    return -1;
	}
	TclDStringAppendDString(&templ, &tmp);
	fd = mkstemps(Tcl_DStringValue(&templ), Tcl_DStringLength(&tmp));
	Tcl_DStringFree(&tmp);
    } else
#endif
    {
	fd = mkstemp(Tcl_DStringValue(&templ));
    }

    if (fd == -1) {
	Tcl_DStringFree(&templ);
	return -1;
    }

    if (resultingNameObj) {
	Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&templ),
		Tcl_DStringLength(&templ), &tmp);
	if (Tcl_ExternalToUtfDStringEx(NULL, NULL, Tcl_DStringValue(&templ),
		Tcl_DStringLength(&templ), 0, &tmp, NULL) != TCL_OK) {
	    Tcl_DStringFree(&templ);
	    return -1;
	}
	Tcl_SetStringObj(resultingNameObj, Tcl_DStringValue(&tmp),
		Tcl_DStringLength(&tmp));
	Tcl_DStringFree(&tmp);
    } else {
	/*
	 * Try to delete the file immediately since we're not reporting the
	 * name to anyone. Note that we're *not* handling any errors from
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
2281
2282
2283
2284
2285
2286
2287

2288
2289
2290

2291
2292
2293
2294
2295
2296
2297

2298
2299
2300
2301
2302
2303
2304
2305







-
+


-
+






-
+







 * Helper that does *part* of what tempnam() does.
 */

static const char *
DefaultTempDir(void)
{
    const char *dir;
    struct stat buf;
    Tcl_StatBuf buf;

    dir = getenv("TMPDIR");
    if (dir && dir[0] && stat(dir, &buf) == 0 && S_ISDIR(buf.st_mode)
    if (dir && dir[0] && TclOSstat(dir, &buf) == 0 && S_ISDIR(buf.st_mode)
	    && access(dir, W_OK) == 0) {
	return dir;
    }

#ifdef P_tmpdir
    dir = P_tmpdir;
    if (stat(dir, &buf)==0 && S_ISDIR(buf.st_mode) && access(dir, W_OK)==0) {
    if (TclOSstat(dir, &buf)==0 && S_ISDIR(buf.st_mode) && access(dir, W_OK)==0) {
	return dir;
    }
#endif

    /*
     * Assume that the default location ("/tmp" if not overridden) is always
     * an existing writable directory; we've no recovery mechanism if it
2300
2301
2302
2303
2304
2305
2306
2307



2308
2309
2310

2311
2312
2313
2314
2315
2316
2317
2318
2319
2320




2321
2322
2323
2324
2325
2326
2327
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







-
+
+
+


-
+









-
+
+
+
+







    /*
     * Build the template in writable memory from the user-supplied pieces and
     * some defaults.
     */

    if (dirObj) {
	string = TclGetString(dirObj);
	Tcl_UtfToExternalDString(NULL, string, dirObj->length, &templ);
	if (Tcl_UtfToExternalDStringEx(NULL, NULL, string, dirObj->length, 0, &templ, NULL) != TCL_OK) {
	    return NULL;
	}
    } else {
	Tcl_DStringInit(&templ);
	Tcl_DStringAppend(&templ, DefaultTempDir(), -1); /* INTL: native */
	Tcl_DStringAppend(&templ, DefaultTempDir(), TCL_INDEX_NONE); /* INTL: native */
    }

    if (Tcl_DStringValue(&templ)[Tcl_DStringLength(&templ) - 1] != '/') {
	TclDStringAppendLiteral(&templ, "/");
    }

    if (basenameObj) {
	string = TclGetString(basenameObj);
	if (basenameObj->length) {
	    Tcl_UtfToExternalDString(NULL, string, basenameObj->length, &tmp);
	    if (Tcl_UtfToExternalDStringEx(NULL, NULL, string, basenameObj->length, 0, &tmp, NULL) != TCL_OK) {
		Tcl_DStringFree(&templ);
		return NULL;
	    }
	    TclDStringAppendDString(&templ, &tmp);
	    Tcl_DStringFree(&tmp);
	} else {
	    TclDStringAppendLiteral(&templ, DEFAULT_TEMP_DIR_PREFIX);
	}
    } else {
	TclDStringAppendLiteral(&templ, DEFAULT_TEMP_DIR_PREFIX);
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
2383
2384
2385
2386
2387
2388
2389




2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406

2407
2408
2409
2410
2411
2412
2413
2414







-
-
-
-
+
+
+
+
+
+
+










-
+







	return NULL;
    }

    /*
     * The template has been updated. Tell the caller what it was.
     */

    Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&templ),
	    Tcl_DStringLength(&templ), &tmp);
    Tcl_DStringFree(&templ);
    return TclDStringToObj(&tmp);
    if (Tcl_ExternalToUtfDStringEx(NULL, NULL, Tcl_DStringValue(&templ),
	    Tcl_DStringLength(&templ), 0, &tmp, NULL) != TCL_OK) {
	Tcl_DStringFree(&templ);
	return NULL;
    }
    Tcl_DStringFree(&templ);
    return Tcl_DStringToObj(&tmp);
}

#if defined(__CYGWIN__)

static void
StatError(
    Tcl_Interp *interp,		/* The interp that has the error */
    Tcl_Obj *fileName)		/* The name of the file which caused the
				 * error. */
{
    TclWinConvertError(GetLastError());
    Tcl_WinConvertError(GetLastError());
    Tcl_SetObjResult(interp, Tcl_ObjPrintf("could not read \"%s\": %s",
	    TclGetString(fileName), Tcl_PosixError(interp)));
}

static WCHAR *
winPathFromObj(
    Tcl_Obj *fileName)

Changes to unix/tclUnixFile.c.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17



18
19
20
21
22
23
24
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






-
+








-
-
+
+
+







/*
 * tclUnixFile.c --
 *
 *	This file contains wrappers around UNIX file handling functions.
 *	These wrappers mask differences between Windows and UNIX.
 *
 * Copyright (c) 1995-1998 Sun Microsystems, Inc.
 * Copyright © 1995-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclFileSystem.h"

static int NativeMatchType(Tcl_Interp *interp, const char* nativeEntry,
	const char* nativeName, Tcl_GlobTypeData *types);
static int		NativeMatchType(Tcl_Interp *interp,
			    const char* nativeEntry, const char* nativeName,
			    Tcl_GlobTypeData *types);

/*
 *---------------------------------------------------------------------------
 *
 * TclpFindExecutable --
 *
 *	This function computes the absolute path name of the current
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
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







-

-
+



-
+





-

-
+







-



+







 */

#ifdef __CYGWIN__
void
TclpFindExecutable(
    TCL_UNUSED(const char *) /*argv0*/)
{
    Tcl_Encoding encoding;
    size_t length;
    wchar_t buf[PATH_MAX];
    wchar_t buf[PATH_MAX] = L"";
    char name[PATH_MAX * 3 + 1];

    GetModuleFileNameW(NULL, buf, PATH_MAX);
    cygwin_conv_path(3, buf, name, PATH_MAX);
    cygwin_conv_path(3, buf, name, sizeof(name));
    length = strlen(name);
    if ((length > 4) && !strcasecmp(name + length - 4, ".exe")) {
	/* Strip '.exe' part. */
	length -= 4;
    }
    encoding = Tcl_GetEncoding(NULL, NULL);
    TclSetObjNameOfExecutable(
	    Tcl_NewStringObj(name, length), encoding);
	    Tcl_NewStringObj(name, length), NULL);
}
#else
void
TclpFindExecutable(
    const char *argv0)		/* The value of the application's argv[0]
				 * (native). */
{
    Tcl_Encoding encoding;
    const char *name, *p;
    Tcl_StatBuf statBuf;
    Tcl_DString buffer, nameString, cwd, utfName;
    Tcl_Obj *obj;

    if (argv0 == NULL) {
	return;
    }
    Tcl_DStringInit(&buffer);

    name = argv0;
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
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







-
+












-
+

-
+





+
-
+













-
-
-
+
+
-
-




+
-
+














-
+


-
-
+
+







-
-
-
-
+
+
+
-
-







	TclDStringClear(&buffer);
	if (p != name) {
	    Tcl_DStringAppend(&buffer, name, p - name);
	    if (p[-1] != '/') {
		TclDStringAppendLiteral(&buffer, "/");
	    }
	}
	name = Tcl_DStringAppend(&buffer, argv0, -1);
	name = Tcl_DStringAppend(&buffer, argv0, TCL_INDEX_NONE);

	/*
	 * INTL: The following calls to access() and stat() should not be
	 * converted to Tclp routines because they need to operate on native
	 * strings directly.
	 */

	if ((access(name, X_OK) == 0)			/* INTL: Native. */
		&& (TclOSstat(name, &statBuf) == 0)	/* INTL: Native. */
		&& S_ISREG(statBuf.st_mode)) {
	    goto gotName;
	}
	if (*p == '\0') {
	if (p[0] == '\0') {
	    break;
	} else if (*(p+1) == 0) {
	} else if (p[1] == 0) {
	    p = "./";
	} else {
	    p++;
	}
    }
    TclNewObj(obj);
    TclSetObjNameOfExecutable(Tcl_NewObj(), NULL);
    TclSetObjNameOfExecutable(obj, NULL);
    goto done;

    /*
     * If the name starts with "/" then just store it
     */

  gotName:
#ifdef DJGPP
    if (name[1] == ':')
#else
    if (name[0] == '/')
#endif
    {
	encoding = Tcl_GetEncoding(NULL, NULL);
	Tcl_ExternalToUtfDString(encoding, name, -1, &utfName);
	TclSetObjNameOfExecutable(
	Tcl_ExternalToUtfDStringEx(NULL, NULL, name, TCL_INDEX_NONE, TCL_ENCODING_PROFILE_TCL8, &utfName, NULL);
	TclSetObjNameOfExecutable(Tcl_DStringToObj(&utfName), NULL);
		Tcl_NewStringObj(Tcl_DStringValue(&utfName), -1), encoding);
	Tcl_DStringFree(&utfName);
	goto done;
    }

    if (TclpGetCwd(NULL, &cwd) == NULL) {
	TclNewObj(obj);
	TclSetObjNameOfExecutable(Tcl_NewObj(), NULL);
	TclSetObjNameOfExecutable(obj, NULL);
	goto done;
    }

    /*
     * The name is relative to the current working directory. First strip off
     * a leading "./", if any, then add the full path name of the current
     * working directory.
     */

    if ((name[0] == '.') && (name[1] == '/')) {
	name += 2;
    }

    Tcl_DStringInit(&nameString);
    Tcl_DStringAppend(&nameString, name, -1);
    Tcl_DStringAppend(&nameString, name, TCL_INDEX_NONE);

    Tcl_DStringFree(&buffer);
    Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&cwd),
	    Tcl_DStringLength(&cwd), &buffer);
    Tcl_UtfToExternalDStringEx(NULL, NULL, Tcl_DStringValue(&cwd),
	    Tcl_DStringLength(&cwd), TCL_ENCODING_PROFILE_TCL8, &buffer, NULL);
    if (Tcl_DStringValue(&cwd)[Tcl_DStringLength(&cwd) -1] != '/') {
	TclDStringAppendLiteral(&buffer, "/");
    }
    Tcl_DStringFree(&cwd);
    TclDStringAppendDString(&buffer, &nameString);
    Tcl_DStringFree(&nameString);

    encoding = Tcl_GetEncoding(NULL, NULL);
    Tcl_ExternalToUtfDString(encoding, Tcl_DStringValue(&buffer), -1,
	    &utfName);
    TclSetObjNameOfExecutable(
    Tcl_ExternalToUtfDStringEx(NULL, NULL, Tcl_DStringValue(&buffer), TCL_INDEX_NONE,
	    TCL_ENCODING_PROFILE_TCL8, &utfName, NULL);
    TclSetObjNameOfExecutable(Tcl_DStringToObj(&utfName), NULL);
	    Tcl_NewStringObj(Tcl_DStringValue(&utfName), -1), encoding);
    Tcl_DStringFree(&utfName);

  done:
    Tcl_DStringFree(&buffer);
}
#endif

/*
265
266
267
268
269
270
271
272

273
274
275
276
277
278
279

280
281
282
283
284
285
286
287
260
261
262
263
264
265
266

267
268
269
270
271
272
273

274

275
276
277
278
279
280
281







-
+






-
+
-







	}
	Tcl_DecrRefCount(tailPtr);
	Tcl_DecrRefCount(fileNamePtr);
    } else {
	TclDIR *d;
	Tcl_DirEntry *entryPtr;
	const char *dirName;
	size_t dirLength, nativeDirLen;
	Tcl_Size dirLength, nativeDirLen;
	int matchHidden, matchHiddenPat;
	Tcl_StatBuf statBuf;
	Tcl_DString ds;		/* native encoding of dir */
	Tcl_DString dsOrig;	/* utf-8 encoding of dir */

	Tcl_DStringInit(&dsOrig);
	dirName = TclGetString(fileNamePtr);
	dirName = TclGetStringFromObj(fileNamePtr, &dirLength);
	dirLength = fileNamePtr->length;
	Tcl_DStringAppend(&dsOrig, dirName, dirLength);

	/*
	 * Make sure that the directory part of the name really is a
	 * directory. If the directory name is "", use the name "." instead,
	 * because some UNIX systems don't treat "" like "." automatically.
	 * Keep the "" for use in generating file names, otherwise "glob
303
304
305
306
307
308
309
310







311
312
313
314
315
316
317
297
298
299
300
301
302
303

304
305
306
307
308
309
310
311
312
313
314
315
316
317







-
+
+
+
+
+
+
+







	    }
	}

	/*
	 * Now open the directory for reading and iterate over the contents.
	 */

	native = Tcl_UtfToExternalDString(NULL, dirName, -1, &ds);
	if (Tcl_UtfToExternalDStringEx(interp, NULL, dirName, TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	    Tcl_DStringFree(&dsOrig);
	    Tcl_DStringFree(&ds);
	    Tcl_DecrRefCount(fileNamePtr);
	    return TCL_ERROR;
	}
	native = Tcl_DStringValue(&ds);

	if ((TclOSstat(native, &statBuf) != 0)		/* INTL: Native. */
		|| !S_ISDIR(statBuf.st_mode)) {
	    Tcl_DStringFree(&dsOrig);
	    Tcl_DStringFree(&ds);
	    Tcl_DecrRefCount(fileNamePtr);
	    return TCL_OK;
367
368
369
370
371
372
373
374
375






376
377
378
379
380
381

382
383
384
385
386
387
388
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







-
-
+
+
+
+
+
+





-
+







	    }

	    /*
	     * Now check to see if the file matches, according to both type
	     * and pattern. If so, add the file to the result.
	     */

	    utfname = Tcl_ExternalToUtfDString(NULL, entryPtr->d_name, -1,
		    &utfDs);
	    if (Tcl_ExternalToUtfDStringEx(interp, NULL, entryPtr->d_name, TCL_INDEX_NONE,
		    0, &utfDs, NULL) != TCL_OK) {
		matchResult = -1;
		break;
	    }
	    utfname = Tcl_DStringValue(&utfDs);
	    if (Tcl_StringCaseMatch(utfname, pattern, 0)) {
		int typeOk = 1;

		if (types != NULL) {
		    Tcl_DStringSetLength(&ds, nativeDirLen);
		    native = Tcl_DStringAppend(&ds, entryPtr->d_name, -1);
		    native = Tcl_DStringAppend(&ds, entryPtr->d_name, TCL_INDEX_NONE);
		    matchResult = NativeMatchType(interp, native,
			    entryPtr->d_name, types);
		    typeOk = (matchResult == 1);
		}
		if (typeOk) {
		    Tcl_ListObjAppendElement(interp, resultPtr,
			    TclNewFSPathObj(pathPtr, utfname,
594
595
596
597
598
599
600
601







602
603
604
605
606
607
608
609
610





611
612
613
614
615
616
617
598
599
600
601
602
603
604

605
606
607
608
609
610
611
612
613
614
615
616
617
618


619
620
621
622
623
624
625
626
627
628
629
630







-
+
+
+
+
+
+
+







-
-
+
+
+
+
+







TclpGetUserHome(
    const char *name,		/* User name for desired home directory. */
    Tcl_DString *bufferPtr)	/* Uninitialized or free DString filled with
				 * name of user's home directory. */
{
    struct passwd *pwPtr;
    Tcl_DString ds;
    const char *native = Tcl_UtfToExternalDString(NULL, name, -1, &ds);
    const char *native;

    if (Tcl_UtfToExternalDStringEx(NULL, NULL, name, TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	Tcl_DStringFree(&ds);
	return NULL;
    }
    native = Tcl_DStringValue(&ds);

    pwPtr = TclpGetPwNam(native);			/* INTL: Native. */
    Tcl_DStringFree(&ds);

    if (pwPtr == NULL) {
	return NULL;
    }
    Tcl_ExternalToUtfDString(NULL, pwPtr->pw_dir, -1, bufferPtr);
    return Tcl_DStringValue(bufferPtr);
    if (Tcl_ExternalToUtfDStringEx(NULL, NULL, pwPtr->pw_dir, TCL_INDEX_NONE, 0, bufferPtr, NULL) != TCL_OK) {
	return NULL;
    } else {
	return Tcl_DStringValue(bufferPtr);
    }
}

/*
 *---------------------------------------------------------------------------
 *
 * TclpObjAccess --
 *
699
700
701
702
703
704
705
706

707
708
709
710
711
712
713
714
715

716
717

718
719
720
721
722
723
724
712
713
714
715
716
717
718

719
720
721
722
723
724
725
726
727

728
729

730
731
732
733
734
735
736
737







-
+








-
+

-
+







 *	This function replaces the library version of getcwd().
 *
 * Results:
 *	The input and output are filesystem paths in native form. The result
 *	is either the given clientData, if the working directory hasn't
 *	changed, or a new clientData (owned by our caller), giving the new
 *	native path, or NULL if the current directory could not be determined.
 *	If NULL is returned, the caller can examine the standard posix error
 *	If NULL is returned, the caller can examine the standard Posix error
 *	codes to determine the cause of the problem.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

ClientData
void *
TclpGetNativeCwd(
    ClientData clientData)
    void *clientData)
{
    char buffer[MAXPATHLEN+1];

#ifdef USEGETWD
    if (getwd(buffer) == NULL) {			/* INTL: Native. */
	return NULL;
    }
781
782
783
784
785
786
787
788




789
790
791
792
793
794
795
794
795
796
797
798
799
800

801
802
803
804
805
806
807
808
809
810
811







-
+
+
+
+







	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "error getting working directory name: %s",
		    Tcl_PosixError(interp)));
	}
	return NULL;
    }
    return Tcl_ExternalToUtfDString(NULL, buffer, -1, bufferPtr);
    if (Tcl_ExternalToUtfDStringEx(interp, NULL, buffer, TCL_INDEX_NONE, 0, bufferPtr, NULL) != TCL_OK) {
	return NULL;
    }
    return Tcl_DStringValue(bufferPtr);
}

/*
 *---------------------------------------------------------------------------
 *
 * TclpReadlink --
 *
812
813
814
815
816
817
818
819

820
821
822
823





824
825
826
827
828
829
830
831
832
833





834
835
836
837
838
839
840
841
842
828
829
830
831
832
833
834

835
836
837
838

839
840
841
842
843
844
845
846
847
848
849
850



851
852
853
854
855
856

857
858
859
860
861
862
863







-
+



-
+
+
+
+
+







-
-
-
+
+
+
+
+

-







TclpReadlink(
    const char *path,		/* Path of file to readlink (UTF-8). */
    Tcl_DString *linkPtr)	/* Uninitialized or free DString filled with
				 * contents of link (UTF-8). */
{
#ifndef DJGPP
    char link[MAXPATHLEN];
    int length;
    Tcl_Size length;
    const char *native;
    Tcl_DString ds;

    native = Tcl_UtfToExternalDString(NULL, path, -1, &ds);
    if (Tcl_UtfToExternalDStringEx(NULL, NULL, path, TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	Tcl_DStringFree(&ds);
	return NULL;
    }
    native = Tcl_DStringValue(&ds);
    length = readlink(native, link, sizeof(link));	/* INTL: Native. */
    Tcl_DStringFree(&ds);

    if (length < 0) {
	return NULL;
    }

    Tcl_ExternalToUtfDString(NULL, link, length, linkPtr);
    return Tcl_DStringValue(linkPtr);
#else
    if (Tcl_ExternalToUtfDStringEx(NULL, NULL, link, length, 0, linkPtr, NULL) == TCL_OK) {
	return Tcl_DStringValue(linkPtr);
    }
#endif /* !DJGPP */

    return NULL;
#endif /* !DJGPP */
}

/*
 *----------------------------------------------------------------------
 *
 * TclpObjStat --
 *
945
946
947
948
949
950
951
952

953
954
955
956
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
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
1024


1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035







-
+












-
+
+
+
+
+



















-
+














-
-
+
+
+
+







	/*
	 * Check symbolic link flag first, since we prefer to create these.
	 */

	if (linkAction & TCL_CREATE_SYMBOLIC_LINK) {
	    Tcl_DString ds;
	    Tcl_Obj *transPtr;
	    size_t length;
	    Tcl_Size length;

	    /*
	     * Now we don't want to link to the absolute, normalized path.
	     * Relative links are quite acceptable (but links to ~user are not
	     * -- these must be expanded first).
	     */

	    transPtr = Tcl_FSGetTranslatedPath(NULL, toPtr);
	    if (transPtr == NULL) {
		return NULL;
	    }
	    target = TclGetStringFromObj(transPtr, &length);
	    target = Tcl_UtfToExternalDString(NULL, target, length, &ds);
	    if (Tcl_UtfToExternalDStringEx(NULL, NULL, target, length, 0, &ds, NULL) != TCL_OK) {
		Tcl_DStringFree(&ds);
		return NULL;
	    }
	    target = Tcl_DStringValue(&ds);
	    Tcl_DecrRefCount(transPtr);

	    if (symlink(target, src) != 0) {
		toPtr = NULL;
	    }
	    Tcl_DStringFree(&ds);
	} else if (linkAction & TCL_CREATE_HARD_LINK) {
	    if (link(target, src) != 0) {
		return NULL;
	    }
	} else {
	    errno = ENODEV;
	    return NULL;
	}
	return toPtr;
    } else {
	Tcl_Obj *linkPtr = NULL;

	char link[MAXPATHLEN];
	int length;
	ssize_t length;
	Tcl_DString ds;
	Tcl_Obj *transPtr;

	transPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
	if (transPtr == NULL) {
	    return NULL;
	}
	Tcl_DecrRefCount(transPtr);

	length = readlink((const char *)Tcl_FSGetNativePath(pathPtr), link, sizeof(link));
	if (length < 0) {
	    return NULL;
	}

	Tcl_ExternalToUtfDString(NULL, link, length, &ds);
	linkPtr = TclDStringToObj(&ds);
	if (Tcl_ExternalToUtfDStringEx(NULL, NULL, link, (size_t)length, 0, &ds, NULL) != TCL_OK) {
	    return NULL;
	}
	linkPtr = Tcl_DStringToObj(&ds);
	Tcl_IncrRefCount(linkPtr);
	return linkPtr;
    }
}
#endif /* S_IFLNK */

/*
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
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
1116
1117
1118
1119

1120
1121

1122
1123

1124
1125
1126
1127
1128
1129
1130
1131







-
+



-
-
+
+


















-
+







-
+

-
+

-
+







 *	None.
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclpNativeToNormalized(
    ClientData clientData)
    void *clientData)
{
    Tcl_DString ds;

    Tcl_ExternalToUtfDString(NULL, (const char *) clientData, -1, &ds);
    return TclDStringToObj(&ds);
    Tcl_ExternalToUtfDStringEx(NULL, NULL, (const char *) clientData, TCL_INDEX_NONE, TCL_ENCODING_PROFILE_TCL8, &ds, NULL);
    return Tcl_DStringToObj(&ds);
}

/*
 *---------------------------------------------------------------------------
 *
 * TclNativeCreateNativeRep --
 *
 *	Create a native representation for the given path.
 *
 * Results:
 *	The nativePath representation.
 *
 * Side effects:
 *	Memory will be allocated. The path may need to be normalized.
 *
 *---------------------------------------------------------------------------
 */

ClientData
void *
TclNativeCreateNativeRep(
    Tcl_Obj *pathPtr)
{
    char *nativePathPtr;
    const char *str;
    Tcl_DString ds;
    Tcl_Obj *validPathPtr;
    size_t len;
    Tcl_Size len;

    if (TclFSCwdIsNative()) {
    if (TclFSCwdIsNative() || Tcl_FSGetPathType(pathPtr) == TCL_PATH_ABSOLUTE) {
	/*
	 * The cwd is native, which means we can use the translated path
	 * The cwd is native (or path is absolute), use the translated path
	 * without worrying about normalization (this will also usually be
	 * shorter so the utf-to-external conversion will be somewhat faster).
	 */

	validPathPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
	if (validPathPtr == NULL) {
	    return NULL;
1112
1113
1114
1115
1116
1117
1118
1119





1120
1121
1122
1123
1124
1125
1126
1139
1140
1141
1142
1143
1144
1145

1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157







-
+
+
+
+
+







	if (validPathPtr == NULL) {
	    return NULL;
	}
	Tcl_IncrRefCount(validPathPtr);
    }

    str = TclGetStringFromObj(validPathPtr, &len);
    Tcl_UtfToExternalDString(NULL, str, len, &ds);
    if (Tcl_UtfToExternalDStringEx(NULL, NULL, str, len, 0, &ds, NULL) != TCL_OK) {
	Tcl_DecrRefCount(validPathPtr);
	Tcl_DStringFree(&ds);
	return NULL;
    }
    len = Tcl_DStringLength(&ds) + sizeof(char);
    if (strlen(Tcl_DStringValue(&ds)) < len - sizeof(char)) {
	/* See bug [3118489]: NUL in filenames */
	Tcl_DecrRefCount(validPathPtr);
	Tcl_DStringFree(&ds);
	return NULL;
    }
1145
1146
1147
1148
1149
1150
1151
1152

1153
1154

1155
1156
1157
1158
1159
1160
1161
1176
1177
1178
1179
1180
1181
1182

1183
1184

1185
1186
1187
1188
1189
1190
1191
1192







-
+

-
+







 *
 * Side effects:
 *	Memory will be allocated for the copy.
 *
 *---------------------------------------------------------------------------
 */

ClientData
void *
TclNativeDupInternalRep(
    ClientData clientData)
    void *clientData)
{
    char *copy;
    size_t len;

    if (clientData == NULL) {
	return NULL;
    }
1192
1193
1194
1195
1196
1197
1198























1199
1200
1201
1202
1203
1204
1205
1223
1224
1225
1226
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    Tcl_Obj *pathPtr,		/* File to modify */
    struct utimbuf *tval)	/* New modification date structure */
{
    return utime((const char *)Tcl_FSGetNativePath(pathPtr), tval);
}

#ifdef __CYGWIN__

int
TclOSfstat(
    int fd,
    void *cygstat)
{
    struct stat buf;
    Tcl_StatBuf *statBuf = (Tcl_StatBuf *)cygstat;
    int result = fstat(fd, &buf);

    statBuf->st_mode = buf.st_mode;
    statBuf->st_ino = buf.st_ino;
    statBuf->st_dev = buf.st_dev;
    statBuf->st_rdev = buf.st_rdev;
    statBuf->st_nlink = buf.st_nlink;
    statBuf->st_uid = buf.st_uid;
    statBuf->st_gid = buf.st_gid;
    statBuf->st_size = buf.st_size;
    statBuf->st_atime = buf.st_atime;
    statBuf->st_mtime = buf.st_mtime;
    statBuf->st_ctime = buf.st_ctime;
    return result;
}

int
TclOSstat(
    const char *name,
    void *cygstat)
{
    struct stat buf;

Changes to unix/tclUnixInit.c.

1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







/*
 * tclUnixInit.c --
 *
 *	Contains the Unix-specific interpreter initialization functions.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1999 by Scriptics Corporation.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1999 Scriptics Corporation.
 * All rights reserved.
 */

#include "tclInt.h"
#ifdef HAVE_LANGINFO
#   include <langinfo.h>
#   ifdef __APPLE__
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
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







-
+

-
-
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+







DLLIMPORT extern __stdcall void FreeLibrary(void *);
DLLIMPORT extern __stdcall void *GetProcAddress(void *, const char *);
DLLIMPORT extern __stdcall void GetSystemInfo(void *);
#ifdef __cplusplus
}
#endif

#define NUMPROCESSORS 11
#define NUMPROCESSORS 15
static const char *const processors[NUMPROCESSORS] = {
    "intel", "mips", "alpha", "ppc", "shx", "arm", "ia64", "alpha64", "msil",
    "amd64", "ia32_on_win64"
    "i686", "mips", "alpha", "ppc", "shx", "arm", "ia64", "alpha64", "msil",
    "x86_64", "ia32_on_win64", "neutral", "arm64", "arm32_on_win64", "ia32_on_arm64"
};

typedef struct {
  union {
    unsigned int  dwOemId;
    struct {
      int wProcessorArchitecture;
      int wReserved;
    };
  };
  unsigned int     dwPageSize;
  void *lpMinimumApplicationAddress;
  void *lpMaximumApplicationAddress;
  void *dwActiveProcessorMask;
  unsigned int     dwNumberOfProcessors;
  unsigned int     dwProcessorType;
  unsigned int     dwAllocationGranularity;
  int      wProcessorLevel;
  int      wProcessorRevision;
    union {
	unsigned int  dwOemId;
	struct {
	    int wProcessorArchitecture;
	    int wReserved;
	};
    };
    unsigned int     dwPageSize;
    void *lpMinimumApplicationAddress;
    void *lpMaximumApplicationAddress;
    void *dwActiveProcessorMask;
    unsigned int     dwNumberOfProcessors;
    unsigned int     dwProcessorType;
    unsigned int     dwAllocationGranularity;
    int      wProcessorLevel;
    int      wProcessorRevision;
} SYSTEM_INFO;

typedef struct {
  unsigned int dwOSVersionInfoSize;
  unsigned int dwMajorVersion;
  unsigned int dwMinorVersion;
  unsigned int dwBuildNumber;
  unsigned int dwPlatformId;
  wchar_t szCSDVersion[128];
    unsigned int dwOSVersionInfoSize;
    unsigned int dwMajorVersion;
    unsigned int dwMinorVersion;
    unsigned int dwBuildNumber;
    unsigned int dwPlatformId;
    wchar_t szCSDVersion[128];
} OSVERSIONINFOW;
#endif

#ifdef HAVE_COREFOUNDATION
#include <CoreFoundation/CoreFoundation.h>
#endif

96
97
98
99
100
101
102
103

104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
96
97
98
99
100
101
102

103
104
105
106
107
108
109
110

111
112
113
114
115
116
117
118







-
+







-
+







#endif

/*
 * Default directory in which to look for Tcl library scripts. The symbol is
 * defined by Makefile.
 */

static char defaultLibraryDir[sizeof(TCL_LIBRARY)+200] = TCL_LIBRARY;
static const char defaultLibraryDir[] = TCL_LIBRARY;

/*
 * Directory in which to look for packages (each package is typically
 * installed as a subdirectory of this directory). The symbol is defined by
 * Makefile.
 */

static char pkgPath[sizeof(TCL_PACKAGE_PATH)+200] = TCL_PACKAGE_PATH;
static const char pkgPath[] = TCL_PACKAGE_PATH;

/*
 * The following table is used to map from Unix locale strings to encoding
 * files. If HAVE_LANGINFO is defined, then this is a fallback table when the
 * result from nl_langinfo isn't a recognized encoding. Otherwise this is the
 * first list checked for a mapping from env encoding to Tcl encoding name.
 */
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
331
332
333
334
335
336
337

338
339
340
341
342
343
344







-







 * Need to check Darwin release at runtime in tclUnixFCmd.c and tclLoadDyld.c:
 * initialize release global at startup from uname().
 */
#define GET_DARWIN_RELEASE 1
MODULE_SCOPE long tclMacOSXDarwinRelease;
long tclMacOSXDarwinRelease = 0;
#endif


/*
 *---------------------------------------------------------------------------
 *
 * TclpInitPlatform --
 *
 *	Initialize all the platform-dependent things like signals and
365
366
367
368
369
370
371
372

373
374
375

376
377
378

379
380
381
382
383
384
385
364
365
366
367
368
369
370

371
372
373

374
375
376

377
378
379
380
381
382
383
384







-
+


-
+


-
+







    tclPlatform = TCL_PLATFORM_UNIX;
#endif

    /*
     * Make sure, that the standard FDs exist. [Bug 772288]
     */

    if (TclOSseek(0, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) {
    if (TclOSseek(0, 0, SEEK_CUR) == -1 && errno == EBADF) {
	open("/dev/null", O_RDONLY);
    }
    if (TclOSseek(1, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) {
    if (TclOSseek(1, 0, SEEK_CUR) == -1 && errno == EBADF) {
	open("/dev/null", O_WRONLY);
    }
    if (TclOSseek(2, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) {
    if (TclOSseek(2, 0, SEEK_CUR) == -1 && errno == EBADF) {
	open("/dev/null", O_WRONLY);
    }

    /*
     * The code below causes SIGPIPE (broken pipe) errors to be ignored. This
     * is needed so that Tcl processes don't die if they create child
     * processes (e.g. using "exec" or "open") that terminate prematurely.
465
466
467
468
469
470
471
472

473
474
475
476

477
478
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
464
465
466
467
468
469
470

471
472
473
474

475
476
477
478
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







-
+



-
+




-
+











-
+





-
+













-
+








    TclNewObj(pathPtr);

    /*
     * Look for the library relative to the TCL_LIBRARY env variable. If the
     * last dirname in the TCL_LIBRARY path does not match the last dirname in
     * the installLib variable, use the last dir name of installLib in
     * addition to the orginal TCL_LIBRARY path.
     * addition to the original TCL_LIBRARY path.
     */

    str = getenv("TCL_LIBRARY");			/* INTL: Native. */
    Tcl_ExternalToUtfDString(NULL, str, -1, &buffer);
    Tcl_ExternalToUtfDStringEx(NULL, NULL, str, TCL_INDEX_NONE, TCL_ENCODING_PROFILE_TCL8, &buffer, NULL);
    str = Tcl_DStringValue(&buffer);

    if ((str != NULL) && (str[0] != '\0')) {
	Tcl_DString ds;
	int pathc;
	Tcl_Size pathc;
	const char **pathv;
	char installLib[LIBRARY_SIZE];

	Tcl_DStringInit(&ds);

	/*
	 * Initialize the substrings used when locating an executable. The
	 * installLib variable computes the path as though the executable is
	 * installed.
	 */

	sprintf(installLib, "lib/tcl%s", TCL_VERSION);
	snprintf(installLib, sizeof(installLib), "lib/tcl%s", TCL_VERSION);

	/*
	 * If TCL_LIBRARY is set, search there.
	 */

	Tcl_ListObjAppendElement(NULL, pathPtr, Tcl_NewStringObj(str, -1));
	Tcl_ListObjAppendElement(NULL, pathPtr, Tcl_NewStringObj(str, TCL_INDEX_NONE));

	Tcl_SplitPath(str, &pathc, &pathv);
	if ((pathc > 0) && (strcasecmp(installLib + 4, pathv[pathc-1]) != 0)) {
	    /*
	     * If TCL_LIBRARY is set but refers to a different tcl
	     * installation than the current version, try fiddling with the
	     * specified directory to make it refer to this installation by
	     * removing the old "tclX.Y" and substituting the current version
	     * string.
	     */

	    pathv[pathc - 1] = installLib + 4;
	    str = Tcl_JoinPath(pathc, pathv, &ds);
	    Tcl_ListObjAppendElement(NULL, pathPtr, TclDStringToObj(&ds));
	    Tcl_ListObjAppendElement(NULL, pathPtr, Tcl_DStringToObj(&ds));
	}
	Tcl_Free(pathv);
    }

    /*
     * Finally, look for the library relative to the compiled-in path. This is
     * needed when users install Tcl with an exec-prefix that is different
533
534
535
536
537
538
539
540

541
542
543
544
545
546







547
548
549




550
551
552
553
554
555
556
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
558
559
560
561
562
563







-
+






+
+
+
+
+
+
+
-
-
-
+
+
+
+







	    /*
	     * TODO: Pull this value from the TIP 59 table.
	     */

	    str = defaultLibraryDir;
	}
	if (str[0] != '\0') {
	    objPtr = Tcl_NewStringObj(str, -1);
	    objPtr = Tcl_NewStringObj(str, TCL_INDEX_NONE);
	    Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
	}
    }
    Tcl_DStringFree(&buffer);

    *encodingPtr = Tcl_GetEncoding(NULL, NULL);

    /*
     * Note lengthPtr is (size_t *) which is unsigned so cannot
     * pass directly to Tcl_GetStringFromObj.
     * TODO - why is the type size_t anyways?
     */
    Tcl_Size length;
    str = TclGetStringFromObj(pathPtr, lengthPtr);
    *valuePtr = (char *)Tcl_Alloc(*lengthPtr + 1);
    memcpy(*valuePtr, str, *lengthPtr + 1);
    str = TclGetStringFromObj(pathPtr, &length);
    *lengthPtr = length;
    *valuePtr = (char *)Tcl_Alloc(length + 1);
    memcpy(*valuePtr, str, length + 1);
    Tcl_DecrRefCount(pathPtr);
}

/*
 *---------------------------------------------------------------------------
 *
 * TclpSetInitialEncodings --
586
587
588
589
590
591
592

593
594
595
596
597

598
599
600

601
602

603

604
605
606
607
608
609
610
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613

614
615
616
617
618
619
620
621







+





+



+


+
-
+







static const char *
SearchKnownEncodings(
    const char *encoding)
{
    int left = 0;
    int right = sizeof(localeTable)/sizeof(LocaleTable);

    /* Here, search for i in the interval left <= i < right. */
    while (left < right) {
	int test = (left + right)/2;
	int code = strcmp(localeTable[test].lang, encoding);

	if (code == 0) {
	    /* Found it at i == test.  */
	    return localeTable[test].encoding;
	}
	if (code < 0) {
	    /* Restrict the search to the interval test < i < right. */
	    left = test+1;
	} else {
	    /* Restrict the search to the interval left <= i < test. */
	    right = test-1;
	    right = test;
	}
    }
    return NULL;
}

const char *
Tcl_GetEncodingNameFromEnvironment(
630
631
632
633
634
635
636
637

638
639
640
641

642
643

644
645
646
647
648
649
650
641
642
643
644
645
646
647

648
649
650
651

652
653

654
655
656
657
658
659
660
661







-
+



-
+

-
+







	Tcl_DString ds;

	/*
	 * Use a DString so we can modify case.
	 */

	Tcl_DStringInit(&ds);
	encoding = Tcl_DStringAppend(&ds, nl_langinfo(CODESET), -1);
	encoding = Tcl_DStringAppend(&ds, nl_langinfo(CODESET), TCL_INDEX_NONE);
	Tcl_UtfToLower(Tcl_DStringValue(&ds));
	knownEncoding = SearchKnownEncodings(encoding);
	if (knownEncoding != NULL) {
	    Tcl_DStringAppend(bufPtr, knownEncoding, -1);
	    Tcl_DStringAppend(bufPtr, knownEncoding, TCL_INDEX_NONE);
	} else if (NULL != Tcl_GetEncoding(NULL, encoding)) {
	    Tcl_DStringAppend(bufPtr, encoding, -1);
	    Tcl_DStringAppend(bufPtr, encoding, TCL_INDEX_NONE);
	}
	Tcl_DStringFree(&ds);
	if (Tcl_DStringLength(bufPtr)) {
	    return Tcl_DStringValue(bufPtr);
	}
    }
#endif /* HAVE_LANGINFO */
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
707
708
709
710
711
712
713

714
715
716
717
718
719
720
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
707
708
709
710
711
712
713

714
715

716
717
718
719
720
721
722
723

724
725
726
727
728
729
730
731







-
+




-
+

-
+




















-
+

-
+







-
+








    if (encoding != NULL) {
	const char *p;
	Tcl_DString ds;

	Tcl_DStringInit(&ds);
	p = encoding;
	encoding = Tcl_DStringAppend(&ds, p, -1);
	encoding = Tcl_DStringAppend(&ds, p, TCL_INDEX_NONE);
	Tcl_UtfToLower(Tcl_DStringValue(&ds));

	knownEncoding = SearchKnownEncodings(encoding);
	if (knownEncoding != NULL) {
	    Tcl_DStringAppend(bufPtr, knownEncoding, -1);
	    Tcl_DStringAppend(bufPtr, knownEncoding, TCL_INDEX_NONE);
	} else if (NULL != Tcl_GetEncoding(NULL, encoding)) {
	    Tcl_DStringAppend(bufPtr, encoding, -1);
	    Tcl_DStringAppend(bufPtr, encoding, TCL_INDEX_NONE);
	}
	if (Tcl_DStringLength(bufPtr)) {
	    Tcl_DStringFree(&ds);
	    return Tcl_DStringValue(bufPtr);
	}

	/*
	 * We didn't recognize the full value as an encoding name. If there is
	 * an encoding subfield, we can try to guess from that.
	 */

	for (p = encoding; *p != '\0'; p++) {
	    if (*p == '.') {
		p++;
		break;
	    }
	}
	if (*p != '\0') {
	    knownEncoding = SearchKnownEncodings(p);
	    if (knownEncoding != NULL) {
		Tcl_DStringAppend(bufPtr, knownEncoding, -1);
		Tcl_DStringAppend(bufPtr, knownEncoding, TCL_INDEX_NONE);
	    } else if (NULL != Tcl_GetEncoding(NULL, p)) {
		Tcl_DStringAppend(bufPtr, p, -1);
		Tcl_DStringAppend(bufPtr, p, TCL_INDEX_NONE);
	    }
	}
	Tcl_DStringFree(&ds);
	if (Tcl_DStringLength(bufPtr)) {
	    return Tcl_DStringValue(bufPtr);
	}
    }
    return Tcl_DStringAppend(bufPtr, TCL_DEFAULT_ENCODING, -1);
    return Tcl_DStringAppend(bufPtr, TCL_DEFAULT_ENCODING, TCL_INDEX_NONE);
}

/*
 *---------------------------------------------------------------------------
 *
 * TclpSetVariables --
 *
778
779
780
781
782
783
784

785

786
787
788
789
790
791
792
793
794
795
796
797
798
799
800

801
802
803
804
805
806

807
808
809
810


811
812
813
814



815
816

817
818


819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839

840
841
842
843
844
845
846
847
848
849
850
851
852

853
854
855
856
857
858
859
860

861









862




863





864
865
866
867
868
869
870
789
790
791
792
793
794
795
796

797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815




816
817
818


819
820




821
822
823


824


825
826





827
828
829
830
831
832
833
834
835
836
837
838
839



840

841
842
843
844
845
846
847
848
849



850

851
852
853
854



855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870

871
872
873
874
875
876
877
878
879
880
881
882







+
-
+















+


-
-
-
-
+


-
-
+
+
-
-
-
-
+
+
+
-
-
+
-
-
+
+
-
-
-
-
-













-
-
-
+
-









-
-
-
+
-




-
-
-
+

+
+
+
+
+
+
+
+
+

+
+
+
+
-
+
+
+
+
+







    static OSVERSIONINFOW osInfo;
    static int osInfoInitialized = 0;
    char buffer[TCL_INTEGER_SPACE * 2];
#elif !defined(NO_UNAME)
    struct utsname name;
#endif
    int unameOK;
    const char *p, *q;
    Tcl_DString ds;
    Tcl_Obj *pkgListObj = Tcl_NewObj();

#ifdef HAVE_COREFOUNDATION
    char tclLibPath[MAXPATHLEN + 1];

    /*
     * Set msgcat fallback locale to current CFLocale identifier.
     */

#if MAC_OS_X_VERSION_MAX_ALLOWED > 1020
    InitMacLocaleInfoVar(CFLocaleCopyCurrent, CFLocaleGetIdentifier, interp);
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED > 1020 */

    if (MacOSXGetLibraryPath(interp, MAXPATHLEN, tclLibPath) == TCL_OK) {
	const char *str;
	CFBundleRef bundleRef;
	Tcl_DString ds;

	Tcl_SetVar2(interp, "tclDefaultLibrary", NULL, tclLibPath, TCL_GLOBAL_ONLY);
	Tcl_SetVar2(interp, "tcl_pkgPath", NULL, tclLibPath, TCL_GLOBAL_ONLY);
	Tcl_SetVar2(interp, "tcl_pkgPath", NULL, " ",
		TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);

	Tcl_ListObjAppendElement(NULL, pkgListObj, Tcl_NewStringObj(tclLibPath, -1));
	str = TclGetEnv("DYLD_FRAMEWORK_PATH", &ds);
	if ((str != NULL) && (str[0] != '\0')) {
	    char *p = Tcl_DStringValue(&ds);

	    p = Tcl_DStringValue(&ds);
	    while ((q = strchr(p, ':')) != NULL) {
	    /*
	     * Convert DYLD_FRAMEWORK_PATH from colon to space separated.
	     */

		Tcl_ListObjAppendElement(NULL, pkgListObj, Tcl_NewStringObj(p, q-p));
		p = q+1;
	    }
	    do {
		if (*p == ':') {
	    if (*p) {
		    *p = ' ';
		}
		Tcl_ListObjAppendElement(NULL, pkgListObj, Tcl_NewStringObj(p, -1));
	    }
	    } while (*p++);
	    Tcl_SetVar2(interp, "tcl_pkgPath", NULL, Tcl_DStringValue(&ds),
		    TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
	    Tcl_SetVar2(interp, "tcl_pkgPath", NULL, " ",
		    TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
	    Tcl_DStringFree(&ds);
	}
	bundleRef = CFBundleGetMainBundle();
	if (bundleRef) {
	    CFURLRef frameworksURL;
	    Tcl_StatBuf statBuf;

	    frameworksURL = CFBundleCopyPrivateFrameworksURL(bundleRef);
	    if (frameworksURL) {
		if (CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
			(unsigned char*) tclLibPath, MAXPATHLEN) &&
			! TclOSstat(tclLibPath, &statBuf) &&
			S_ISDIR(statBuf.st_mode)) {
		    Tcl_SetVar2(interp, "tcl_pkgPath", NULL, tclLibPath,
			    TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
		    Tcl_SetVar2(interp, "tcl_pkgPath", NULL, " ",
		    Tcl_ListObjAppendElement(NULL, pkgListObj, Tcl_NewStringObj(tclLibPath, -1));
			    TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
		}
		CFRelease(frameworksURL);
	    }
	    frameworksURL = CFBundleCopySharedFrameworksURL(bundleRef);
	    if (frameworksURL) {
		if (CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
			(unsigned char*) tclLibPath, MAXPATHLEN) &&
			! TclOSstat(tclLibPath, &statBuf) &&
			S_ISDIR(statBuf.st_mode)) {
		    Tcl_SetVar2(interp, "tcl_pkgPath", NULL, tclLibPath,
			    TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
		    Tcl_SetVar2(interp, "tcl_pkgPath", NULL, " ",
		    Tcl_ListObjAppendElement(NULL, pkgListObj, Tcl_NewStringObj(tclLibPath, -1));
			    TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
		}
		CFRelease(frameworksURL);
	    }
	}
	Tcl_SetVar2(interp, "tcl_pkgPath", NULL, pkgPath,
		TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
    } else
    }
#endif /* HAVE_COREFOUNDATION */
    p = pkgPath;
    while ((q = strchr(p, ':')) != NULL) {
	Tcl_ListObjAppendElement(NULL, pkgListObj, Tcl_NewStringObj(p, q-p));
	p = q+1;
    }
    if (*p) {
	Tcl_ListObjAppendElement(NULL, pkgListObj, Tcl_NewStringObj(p, -1));
    }
    Tcl_ObjSetVar2(interp, Tcl_NewStringObj("tcl_pkgPath", -1), NULL, pkgListObj, TCL_GLOBAL_ONLY);
    {
	/* Some platforms build configure scripts expect ~ expansion so do that */
	Tcl_Obj *origPaths;
	Tcl_Obj *resolvedPaths;

	Tcl_SetVar2(interp, "tcl_pkgPath", NULL, pkgPath, TCL_GLOBAL_ONLY);
	origPaths = Tcl_GetVar2Ex(interp, "tcl_pkgPath", NULL, TCL_GLOBAL_ONLY);
	resolvedPaths = TclResolveTildePathList(origPaths);
	if (resolvedPaths != origPaths && resolvedPaths != NULL) {
	    Tcl_SetVar2Ex(interp, "tcl_pkgPath", NULL, resolvedPaths, TCL_GLOBAL_ONLY);
	}
    }

#ifdef DJGPP
    Tcl_SetVar2(interp, "tcl_platform", "platform", "dos", TCL_GLOBAL_ONLY);
#else
    Tcl_SetVar2(interp, "tcl_platform", "platform", "unix", TCL_GLOBAL_ONLY);
#endif
881
882
883
884
885
886
887



888

889
890

891
892
893
894
895
896
897
898
899
900

901
902
903
904

905
906
907
908
909
910
911
893
894
895
896
897
898
899
900
901
902

903


904
905
906
907
908
909
910
911
912
913
914
915
916
917
918

919
920
921
922
923
924
925
926







+
+
+
-
+
-
-
+










+



-
+







	    GetVersionExW(&osInfo);
	}
	osInfoInitialized = 1;
    }

    GetSystemInfo(&sysInfo);

    if (osInfo.dwMajorVersion == 10 && osInfo.dwBuildNumber >= 22000) {
	osInfo.dwMajorVersion = 11;
    }
    Tcl_SetVar2(interp, "tcl_platform", "os",
    Tcl_SetVar2(interp, "tcl_platform", "os", "Windows NT", TCL_GLOBAL_ONLY);
	    "Windows NT", TCL_GLOBAL_ONLY);
    sprintf(buffer, "%d.%d", osInfo.dwMajorVersion, osInfo.dwMinorVersion);
    snprintf(buffer, sizeof(buffer), "%d.%d", osInfo.dwMajorVersion, osInfo.dwMinorVersion);
    Tcl_SetVar2(interp, "tcl_platform", "osVersion", buffer, TCL_GLOBAL_ONLY);
    if (sysInfo.wProcessorArchitecture < NUMPROCESSORS) {
	Tcl_SetVar2(interp, "tcl_platform", "machine",
		processors[sysInfo.wProcessorArchitecture],
		TCL_GLOBAL_ONLY);
    }

#elif !defined NO_UNAME
    if (uname(&name) >= 0) {
	const char *native;
	Tcl_DString ds;

	unameOK = 1;

	native = Tcl_ExternalToUtfDString(NULL, name.sysname, -1, &ds);
	native = Tcl_ExternalToUtfDString(NULL, name.sysname, TCL_INDEX_NONE, &ds);
	Tcl_SetVar2(interp, "tcl_platform", "os", native, TCL_GLOBAL_ONLY);
	Tcl_DStringFree(&ds);

	/*
	 * The following code is a special hack to handle differences in the
	 * way version information is returned by uname. On most systems the
	 * full version number is available in name.release. However, under
955
956
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
1016

1017
1018
1019
1020
1021
1022
1023
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
1024
1025

1026
1027
1028
1029
1030
1031

1032
1033
1034
1035
1036
1037
1038
1039







+





-
+



















-
+



-
+









-
+



-
+




-
+





-
+







     * Copy the username of the real user (according to getuid()) into
     * tcl_platform(user).
     */

    {
	struct passwd *pwEnt = TclpGetPwUid(getuid());
	const char *user;
	Tcl_DString ds;

	if (pwEnt == NULL) {
	    user = "";
	    Tcl_DStringInit(&ds);	/* ensure cleanliness */
	} else {
	    user = Tcl_ExternalToUtfDString(NULL, pwEnt->pw_name, -1, &ds);
	    user = Tcl_ExternalToUtfDString(NULL, pwEnt->pw_name, TCL_INDEX_NONE, &ds);
	}

	Tcl_SetVar2(interp, "tcl_platform", "user", user, TCL_GLOBAL_ONLY);
	Tcl_DStringFree(&ds);
    }

    /*
     * Define what the platform PATH separator is. [TIP #315]
     */

    Tcl_SetVar2(interp, "tcl_platform","pathSeparator", ":", TCL_GLOBAL_ONLY);
}

/*
 *----------------------------------------------------------------------
 *
 * TclpFindVariable --
 *
 *	Locate the entry in environ for a given name. On Unix this routine is
 *	case sensetive, on Windows this matches mixed case.
 *	case sensitive, on Windows this matches mixed case.
 *
 * Results:
 *	The return value is the index in environ of an entry with the name
 *	"name", or TCL_INDEX_NONE if there is no such entry. The integer at *lengthPtr is
 *	"name", or -1 if there is no such entry. The integer at *lengthPtr is
 *	filled in with the length of name (if a matching entry is found) or
 *	the length of the environ array (if no matching entry is found).
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_Size
TclpFindVariable(
    const char *name,		/* Name of desired environment variable
				 * (native). */
    size_t *lengthPtr)		/* Used to return length of name (for
    Tcl_Size *lengthPtr)	/* Used to return length of name (for
				 * successful searches) or number of non-NULL
				 * entries in environ (for unsuccessful
				 * searches). */
{
    size_t i, result = TCL_INDEX_NONE;
    Tcl_Size i, result = -1;
    const char *env, *p1, *p2;
    Tcl_DString envString;

    Tcl_DStringInit(&envString);
    for (i = 0, env = environ[i]; env != NULL; i++, env = environ[i]) {
	p1 = Tcl_ExternalToUtfDString(NULL, env, -1, &envString);
	p1 = Tcl_ExternalToUtfDString(NULL, env, TCL_INDEX_NONE, &envString);
	p2 = name;

	for (; *p2 == *p1; p1++, p2++) {
	    /* NULL loop body. */
	}
	if ((*p1 == '=') && (*p2 == '\0')) {
	    *lengthPtr = p2 - name;

Changes to unix/tclUnixNotfy.c.

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
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
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

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




-
+
+

-
-
+
+
+



















-
+



















+

-
+
+










+



















-
+







/*
 * tclUnixNotfy.c --
 *
 *	This file contains subroutines shared by all notifier backend
 *	implementations on *nix platforms.
 *	implementations on *nix platforms. It is *included* by the epoll,
 *	kqueue and select notifier implementation files.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 2016 Lucio Andrés Illanes Albornoz <l.illanes@gmx.de>
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2016 Lucio Andrés Illanes Albornoz <l.illanes@gmx.de>
 * Copyright © 2021 Donal K. Fellows
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include <poll.h>
#include "tclInt.h"

/*
 * Static routines defined in this file.
 */

static int		FileHandlerEventProc(Tcl_Event *evPtr, int flags);
#if !TCL_THREADS
# undef NOTIFIER_EPOLL
# undef NOTIFIER_KQUEUE
# define NOTIFIER_SELECT
#elif !defined(NOTIFIER_EPOLL) && !defined(NOTIFIER_KQUEUE)
# define NOTIFIER_SELECT
static TCL_NORETURN void NotifierThreadProc(ClientData clientData);
static TCL_NORETURN void NotifierThreadProc(void *clientData);
# if defined(HAVE_PTHREAD_ATFORK)
static void		AtForkChild(void);
# endif /* HAVE_PTHREAD_ATFORK */

/*
 *----------------------------------------------------------------------
 *
 * StartNotifierThread --
 *
 *	Start a notifier thread and wait for the notifier pipe to be created.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Running Thread.
 *
 *----------------------------------------------------------------------
 */

static void
StartNotifierThread(const char *proc)
StartNotifierThread(
    const char *proc)
{
    if (!notifierThreadRunning) {
	pthread_mutex_lock(&notifierInitMutex);
	if (!notifierThreadRunning) {
	    if (TclpThreadCreate(&notifierThread, NotifierThreadProc, NULL,
		    TCL_THREAD_STACK_DEFAULT, TCL_THREAD_JOINABLE) != TCL_OK) {
		Tcl_Panic("%s: unable to start notifier thread", proc);
	    }

	    pthread_mutex_lock(&notifierMutex);

	    /*
	     * Wait for the notifier pipe to be created.
	     */

	    while (triggerPipe < 0) {
		pthread_cond_wait(&notifierCV, &notifierMutex);
	    }
	    pthread_mutex_unlock(&notifierMutex);

	    notifierThreadRunning = 1;
	}
	pthread_mutex_unlock(&notifierInitMutex);
    }
}
#endif /* NOTIFIER_SELECT */

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AlertNotifier --
 * TclpAlertNotifier --
 *
 *	Wake up the specified notifier from any thread. This routine is called
 *	by the platform independent notifier code whenever the Tcl_ThreadAlert
 *	routine is called. This routine is guaranteed not to be called on a
 *	given notifier after Tcl_FinalizeNotifier is called for that notifier.
 *
 * Results:
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
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







-
-
+
+

-
-
-
-


-
+

-
-
+
+


-
+

-
+

-
+
+
+


-
+

-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+


-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+















-
-
+
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
-



















-
+



-
-
-
-
+







 *	kqueue(2) notifier:
 *		write(2)s to the trigger pipe(2) of the specified thread.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_AlertNotifier(
    ClientData clientData)
TclpAlertNotifier(
    void *clientData)
{
    if (tclNotifierHooks.alertNotifierProc) {
	tclNotifierHooks.alertNotifierProc(clientData);
	return;
    } else {
#ifdef NOTIFIER_SELECT
#if TCL_THREADS
	ThreadSpecificData *tsdPtr = (ThreadSpecificData *)clientData;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;

	pthread_mutex_lock(&notifierMutex);
	tsdPtr->eventReady = 1;
    pthread_mutex_lock(&notifierMutex);
    tsdPtr->eventReady = 1;

#   ifdef __CYGWIN__
	PostMessageW(tsdPtr->hwnd, 1024, 0, 0);
    PostMessageW(tsdPtr->hwnd, 1024, 0, 0);
#   else
	pthread_cond_broadcast(&tsdPtr->waitCV);
    pthread_cond_broadcast(&tsdPtr->waitCV);
#   endif /* __CYGWIN__ */
	pthread_mutex_unlock(&notifierMutex);
    pthread_mutex_unlock(&notifierMutex);
#else
    (void)clientData;
#endif /* TCL_THREADS */
#else /* !NOTIFIER_SELECT */
	ThreadSpecificData *tsdPtr = (ThreadSpecificData *)clientData;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;
#if defined(NOTIFIER_EPOLL) && defined(HAVE_EVENTFD)
	uint64_t eventFdVal = 1;
	if (write(tsdPtr->triggerEventFd, &eventFdVal,
		sizeof(eventFdVal)) != sizeof(eventFdVal)) {
	    Tcl_Panic("Tcl_AlertNotifier: unable to write to %p->triggerEventFd",
		(void *)tsdPtr);
	}
    uint64_t eventFdVal = 1;

    if (write(tsdPtr->triggerEventFd, &eventFdVal,
	    sizeof(eventFdVal)) != sizeof(eventFdVal)) {
	Tcl_Panic("Tcl_AlertNotifier: unable to write to %p->triggerEventFd",
		tsdPtr);
    }
#else
	if (write(tsdPtr->triggerPipe[1], "", 1) != 1) {
	    Tcl_Panic("Tcl_AlertNotifier: unable to write to %p->triggerPipe",
		(void *)tsdPtr);
	}
    if (write(tsdPtr->triggerPipe[1], "", 1) != 1) {
	Tcl_Panic("Tcl_AlertNotifier: unable to write to %p->triggerPipe",
		tsdPtr);
    }
#endif /* NOTIFIER_EPOLL && HAVE_EVENTFD */
#endif /* NOTIFIER_SELECT */
    }
}

/*
 *----------------------------------------------------------------------
 *
 * LookUpFileHandler --
 *
 *	Look up the file handler structure (and optionally the previous one in
 *	the chain) associated with a file descriptor.
 *
 * Returns:
 *	A pointer to the file handler, or NULL if it can't be found.
 *
 * Side effects:
 *	If prevPtrPtr is non-NULL, it will be written to if the file handler
 *	is found.
 *
 *----------------------------------------------------------------------
 */

static inline FileHandler *
LookUpFileHandler(
    ThreadSpecificData *tsdPtr,	/* Where to look things up. */
    int fd,			/* What we are looking for. */
    FileHandler **prevPtrPtr)	/* If non-NULL, where to report the previous
				 * pointer. */
{
    FileHandler *filePtr, *prevPtr;

    /*
     * Find the entry for the given file (and return if there isn't one).
     */

    for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
	    prevPtr = filePtr, filePtr = filePtr->nextPtr) {
	if (filePtr == NULL) {
	    return NULL;
	}
	if (filePtr->fd == fd) {
	    break;
	}
    }

    /*
     * Report what we've found to our caller.
     */

    if (prevPtrPtr) {
	*prevPtrPtr = prevPtr;
    }
    return filePtr;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetTimer --
 * TclpSetTimer --
 *
 *	This function sets the current notifier timer value. This interface is
 *	not implemented in this notifier because we are always running inside
 *	of Tcl_DoOneEvent.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetTimer(
    const Tcl_Time *timePtr)		/* Timeout value, may be NULL. */
TclpSetTimer(
    TCL_UNUSED(const Tcl_Time *))		/* Timeout value, may be NULL. */
{
    if (tclNotifierHooks.setTimerProc) {
	tclNotifierHooks.setTimerProc(timePtr);
	return;
    } else {
	/*
	 * The interval timer doesn't do anything in this implementation,
	 * because the only event loop is via Tcl_DoOneEvent, which passes
	 * timeout values to Tcl_WaitForEvent.
	 */
    /*
     * The interval timer doesn't do anything in this implementation, because
     * the only event loop is via Tcl_DoOneEvent, which passes timeout values
     * to Tcl_WaitForEvent.
     */
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ServiceModeHook --
 *
 *	This function is invoked whenever the service mode changes.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_ServiceModeHook(
TclpServiceModeHook(
    int mode)			/* Either TCL_SERVICE_ALL, or
				 * TCL_SERVICE_NONE. */
{
    if (tclNotifierHooks.serviceModeHookProc) {
	tclNotifierHooks.serviceModeHookProc(mode);
	return;
    } else if (mode == TCL_SERVICE_ALL) {
    if (mode == TCL_SERVICE_ALL) {
#ifdef NOTIFIER_SELECT
#if TCL_THREADS
	StartNotifierThread("Tcl_ServiceModeHook");
#endif
#endif /* NOTIFIER_SELECT */
    }
}
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
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







-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+








static void
AlertSingleThread(
    ThreadSpecificData *tsdPtr)
{
    tsdPtr->eventReady = 1;
    if (tsdPtr->onList) {
        /*
         * Remove the ThreadSpecificData structure of this thread from the
         * waiting list. This prevents us from continuously spinning on
         * epoll_wait until the other threads runs and services the file
         * event.
         */
	/*
	 * Remove the ThreadSpecificData structure of this thread from the
	 * waiting list. This prevents us from continuously spinning on
	 * epoll_wait until the other threads runs and services the file
	 * event.
	 */

        if (tsdPtr->prevPtr) {
    	    tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
        } else {
    	    waitingListPtr = tsdPtr->nextPtr;
        }
        if (tsdPtr->nextPtr) {
    	    tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
        }
        tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
        tsdPtr->onList = 0;
        tsdPtr->pollState = 0;
	if (tsdPtr->prevPtr) {
	    tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
	} else {
	    waitingListPtr = tsdPtr->nextPtr;
	}
	if (tsdPtr->nextPtr) {
	    tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
	}
	tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
	tsdPtr->onList = 0;
	tsdPtr->pollState = 0;
    }
#ifdef __CYGWIN__
    PostMessageW(tsdPtr->hwnd, 1024, 0, 0);
#else /* !__CYGWIN__ */
    pthread_cond_broadcast(&tsdPtr->waitCV);
#endif /* __CYGWIN__ */
}
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
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

442
443
444
445
446
447
448
449







+
+
+
+

















+
+
+
+









-
+







    if (notifierThreadRunning == 1) {
	pthread_cond_destroy(&notifierCV);
    }
    pthread_mutex_init(&notifierInitMutex, NULL);
    pthread_mutex_init(&notifierMutex, NULL);
    pthread_cond_init(&notifierCV, NULL);

#ifdef NOTIFIER_SELECT
    asyncPending = 0;
#endif

    /*
     * notifierThreadRunning == 1: thread is running, (there might be data in
     *		notifier lists)
     * atForkInit == 0: InitNotifier was never called
     * notifierCount != 0: unbalanced InitNotifier() / FinalizeNotifier calls
     * waitingListPtr != 0: there are threads currently waiting for events.
     */

    if (atForkInit == 1) {

	notifierCount = 0;
	if (notifierThreadRunning == 1) {
	    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
	    notifierThreadRunning = 0;

	    close(triggerPipe);
	    triggerPipe = -1;
#ifdef NOTIFIER_SELECT
	    close(otherPipe);
	    otherPipe = -1;
#endif
	    /*
	     * The waitingListPtr might contain event info from multiple
	     * threads, which are invalid here, so setting it to NULL is not
	     * unreasonable.
	     */
	    waitingListPtr = NULL;

	    /*
	     * The tsdPtr from before the fork is copied as well. But since we
	     * are paranoic, we don't trust its condvar and reset it.
	     * are paranoiac, we don't trust its condvar and reset it.
	     */
#ifdef __CYGWIN__
	    DestroyWindow(tsdPtr->hwnd);
	    tsdPtr->hwnd = CreateWindowExW(NULL, className,
		    className, 0, 0, 0, 0, 0, NULL, NULL,
		    TclWinGetTclInstance(), NULL);
	    ResetEvent(tsdPtr->event);
408
409
410
411
412
413
414
415
416
417










418

419
420
421
422































423
424
425
426
427
428
429
462
463
464
465
466
467
468



469
470
471
472
473
474
475
476
477
478
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







-
-
-
+
+
+
+
+
+
+
+
+
+

+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	     * The list of registered event handlers at fork time is in
	     * tsdPtr->firstFileHandlerPtr;
	     */
	}
    }

    Tcl_InitNotifier();
}
#endif /* HAVE_PTHREAD_ATFORK */


#ifdef NOTIFIER_SELECT
    /*
     * Restart the notifier thread for signal handling.
     */

    StartNotifierThread("AtForkChild");
#endif
}
#endif /* HAVE_PTHREAD_ATFORK */
#endif /* TCL_THREADS */
#endif /* NOTIFIER_SELECT */

#endif /* NOTIFIER_SELECT */
#ifndef HAVE_COREFOUNDATION	/* Darwin/Mac OS X CoreFoundation notifier is
				 * in tclMacOSXNotify.c */

/*
 *----------------------------------------------------------------------
 *
 * TclpNotifierData --
 *
 *	This function returns a void pointer to be associated
 *	with a Tcl_AsyncHandler.
 *
 * Results:
 *	For the epoll and kqueue notifiers, this function returns the
 *	thread specific data. Otherwise NULL.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void *
TclpNotifierData(void)
{
#if defined(NOTIFIER_EPOLL) || defined(NOTIFIER_KQUEUE)
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    return tsdPtr;
#else
    return NULL;
#endif
}

/*
 *----------------------------------------------------------------------
 *
 * TclUnixWaitForFile --
 *
 *	This function waits synchronously for a file to become readable or
 *	writable, with an optional timeout.
438
439
440
441
442
443
444



445
446
447
448
449
450
451
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543







+
+
+







 *	serviced during the execution of this function.
 *
 * Side effects:
 *	Time passes.
 *
 *----------------------------------------------------------------------
 */

#ifndef HAVE_COREFOUNDATION	/* Darwin/Mac OS X CoreFoundation notifier is
				 * in tclMacOSXNotify.c */

int
TclUnixWaitForFile(
    int fd,			/* Handle for file on which to wait. */
    int mask,			/* What to wait for: OR'ed combination of
				 * TCL_READABLE, TCL_WRITABLE, and
				 * TCL_EXCEPTION. */
559
560
561
562
563
564
565
566
567
568

569
570
571
572
573
574
575
651
652
653
654
655
656
657

658

659
660
661
662
663
664
665
666







-

-
+







	 */

	Tcl_GetTime(&now);
    } while ((abortTime.sec > now.sec)
	    || (abortTime.sec == now.sec && abortTime.usec > now.usec));
    return result;
}

#endif /* !HAVE_COREFOUNDATION */

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

Changes to unix/tclUnixPipe.c.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15











16

17
18
19
20
21
22
23
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
30
31
32
33
34






-
-
+
+







+
+
+
+
+
+
+
+
+
+
+
-
+







/*
 * tclUnixPipe.c --
 *
 *	This file implements the UNIX-specific exec pipeline functions, the
 *	"pipe" channel driver, and the "pid" Tcl command.
 *
 * Copyright (c) 1991-1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright © 1991-1994 The Regents of the University of California.
 * Copyright © 1994-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

#ifdef HAVE_POSIX_SPAWNP
#   if defined(HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2) \
	    && defined(HAVE_POSIX_SPAWNATTR_SETFLAGS) \
	    && !defined(HAVE_VFORK)
#	include <unistd.h>
#	include <spawn.h>
#   else
#	undef HAVE_POSIX_SPAWNP
#   endif
#endif

#ifdef USE_VFORK
#ifdef HAVE_VFORK
#define fork vfork
#endif

/*
 * The following macros convert between TclFile's and fd's. The conversion
 * simple involves shifting fd's up by one to ensure that no valid fd is ever
 * the same as NULL.
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56







-
+







 */

typedef struct {
    Tcl_Channel channel;	/* Channel associated with this file. */
    TclFile inFile;		/* Output from pipe. */
    TclFile outFile;		/* Input to pipe. */
    TclFile errorFile;		/* Error output from pipe. */
    int numPids;		/* How many processes are attached to this
    size_t numPids;		/* How many processes are attached to this
				 * pipe? */
    Tcl_Pid *pidPtr;		/* The process IDs themselves. Allocated by
				 * the creator of the pipe. */
    int isNonBlocking;		/* Nonzero when the pipe is in nonblocking
				 * mode. Used to decide whether to wait for
				 * the children at close time. */
} PipeState;
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
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







-
-
-
-
-
-
+
+
+
+
+
+


-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+








/*
 * This structure describes the channel type structure for command pipe based
 * I/O:
 */

static const Tcl_ChannelType pipeChannelType = {
    "pipe",			/* Type name. */
    TCL_CHANNEL_VERSION_5,	/* v5 channel */
    NULL,		/* Close proc. */
    PipeInputProc,		/* Input proc. */
    PipeOutputProc,		/* Output proc. */
    NULL,			/* Seek proc. */
    "pipe",
    TCL_CHANNEL_VERSION_5,
    NULL,			/* Deprecated. */
    PipeInputProc,
    PipeOutputProc,
    NULL,			/* Deprecated. */
    NULL,			/* Set option proc. */
    NULL,			/* Get option proc. */
    PipeWatchProc,		/* Initialize notifier. */
    PipeGetHandleProc,		/* Get OS handles out of channel. */
    PipeClose2Proc,		/* close2proc. */
    PipeBlockModeProc,		/* Set blocking or non-blocking mode.*/
    NULL,			/* flush proc. */
    NULL,			/* handler proc. */
    NULL,			/* wide seek proc */
    NULL,			/* thread action proc */
    NULL			/* truncation */
    PipeWatchProc,
    PipeGetHandleProc,
    PipeClose2Proc,
    PipeBlockModeProc,
    NULL,			/* Flush proc. */
    NULL,			/* Bubbled event handler proc. */
    NULL,			/* Seek proc. */
    NULL,			/* Thread action proc. */
    NULL			/* Truncation proc. */
};

/*
 *----------------------------------------------------------------------
 *
 * TclpMakeFile --
 *
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
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







-
+
+
+
+
+











-
+







    const char *fname,		/* The name of the file to open. */
    int mode)			/* In what mode to open the file? */
{
    int fd;
    const char *native;
    Tcl_DString ds;

    native = Tcl_UtfToExternalDString(NULL, fname, -1, &ds);
    if (Tcl_UtfToExternalDStringEx(NULL, NULL, fname, TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	Tcl_DStringFree(&ds);
	return NULL;
    }
    native = Tcl_DStringValue(&ds);
    fd = TclOSopen(native, mode, 0666);			/* INTL: Native. */
    Tcl_DStringFree(&ds);
    if (fd != -1) {
	fcntl(fd, F_SETFD, FD_CLOEXEC);

	/*
	 * If the file is being opened for writing, seek to the end so we can
	 * append to any data already in the file.
	 */

	if ((mode & O_WRONLY) && !(mode & O_APPEND)) {
	    TclOSseek(fd, (Tcl_SeekOffset) 0, SEEK_END);
	    TclOSseek(fd, 0, SEEK_END);
	}

	/*
	 * Increment the fd so it can't be 0, which would conflict with the
	 * NULL return for errors.
	 */

194
195
196
197
198
199
200
201






202
203
204
205
206
207
208

209
210
211
212
213
214
215
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







-
+
+
+
+
+
+






-
+







	return NULL;
    }
    fcntl(fd, F_SETFD, FD_CLOEXEC);
    if (contents != NULL) {
	Tcl_DString dstring;
	char *native;

	native = Tcl_UtfToExternalDString(NULL, contents, -1, &dstring);
	if (Tcl_UtfToExternalDStringEx(NULL, NULL, contents, TCL_INDEX_NONE, 0, &dstring, NULL) != TCL_OK) {
	    close(fd);
	    Tcl_DStringFree(&dstring);
	    return NULL;
	}
	native = Tcl_DStringValue(&dstring);
	if (write(fd, native, Tcl_DStringLength(&dstring)) == -1) {
	    close(fd);
	    Tcl_DStringFree(&dstring);
	    return NULL;
	}
	Tcl_DStringFree(&dstring);
	TclOSseek(fd, (Tcl_SeekOffset) 0, SEEK_SET);
	TclOSseek(fd, 0, SEEK_SET);
    }
    return MakeFile(fd);
}

/*
 *----------------------------------------------------------------------
 *
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
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
442
443
444
445







-
+











-
+




-
+









-
-
-
+
+
+
+
+
+
+
+








int
TclpCreateProcess(
    Tcl_Interp *interp,		/* Interpreter in which to leave errors that
				 * occurred when creating the child process.
				 * Error messages from the child process
				 * itself are sent to errorFile. */
    int argc,			/* Number of arguments in following array. */
    size_t argc,			/* Number of arguments in following array. */
    const char **argv,		/* Array of argument strings in UTF-8.
				 * argv[0] contains the name of the executable
				 * translated using Tcl_TranslateFileName
				 * call). Additional arguments have not been
				 * converted. */
    TclFile inputFile,		/* If non-NULL, gives the file to use as input
				 * for the child process. If inputFile file is
				 * not readable or is NULL, the child will
				 * receive no standard input. */
    TclFile outputFile,		/* If non-NULL, gives the file that receives
				 * output from the child process. If
				 * outputFile file is not writeable or is
				 * outputFile file is not writable or is
				 * NULL, output from the child will be
				 * discarded. */
    TclFile errorFile,		/* If non-NULL, gives the file that receives
				 * errors from the child process. If errorFile
				 * file is not writeable or is NULL, errors
				 * file is not writable or is NULL, errors
				 * from the child will be discarded. errorFile
				 * may be the same as outputFile. */
    Tcl_Pid *pidPtr)		/* If this function is successful, pidPtr is
				 * filled with the process id of the child
				 * process. */
{
    TclFile errPipeIn, errPipeOut;
    int count, status, fd;
    char errSpace[200 + TCL_INTEGER_SPACE];
    Tcl_DString *dsArray;
    char **newArgv;
    int pid, i;
    Tcl_DString *volatile dsArray;
    char **volatile newArgv;
    int pid;
    size_t i;
#if defined(HAVE_POSIX_SPAWNP)
    int childErrno;
    static int use_spawn = -1;
#endif

    errPipeIn = NULL;
    errPipeOut = NULL;
    pid = -1;

    /*
     * Create a pipe that the child can use to return error information if
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
467
468
469
470
471
472
473
474
475
476
477
478

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
457
458
459
460
461
462
463




464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575

576
577
578
579
580
581
582
583
584
585
586
587
588
589
590

591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619







-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+












-
+


-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+















-
+














-
+


















+
+
+







     * deallocated later
     */

    dsArray = (Tcl_DString *)TclStackAlloc(interp, argc * sizeof(Tcl_DString));
    newArgv = (char **)TclStackAlloc(interp, (argc+1) * sizeof(char *));
    newArgv[argc] = NULL;
    for (i = 0; i < argc; i++) {
	newArgv[i] = Tcl_UtfToExternalDString(NULL, argv[i], -1, &dsArray[i]);
    }

#ifdef USE_VFORK
	if (Tcl_UtfToExternalDStringEx(interp, NULL, argv[i], TCL_INDEX_NONE, 0, &dsArray[i], NULL) != TCL_OK) {
	    while (i-- > 0) {
		Tcl_DStringFree(&dsArray[i]);
	    }
	    TclStackFree(interp, newArgv);
	    TclStackFree(interp, dsArray);
	    goto error;
	}
	newArgv[i] = Tcl_DStringValue(&dsArray[i]);
    }

#if defined(HAVE_VFORK) || defined(HAVE_POSIX_SPAWNP)
    /*
     * After vfork(), do not call code in the child that changes global state,
     * because it is using the parent's memory space at that point and writes
     * might corrupt the parent: so ensure standard channels are initialized
     * in the parent, otherwise SetupStdFile() might initialize them in the
     * child.
     */

    if (!inputFile) {
	Tcl_GetStdChannel(TCL_STDIN);
    }
    if (!outputFile) {
        Tcl_GetStdChannel(TCL_STDOUT);
	Tcl_GetStdChannel(TCL_STDOUT);
    }
    if (!errorFile) {
        Tcl_GetStdChannel(TCL_STDERR);
	Tcl_GetStdChannel(TCL_STDERR);
    }
#endif

#ifdef HAVE_POSIX_SPAWNP
#ifdef _CS_GNU_LIBC_VERSION
    if (use_spawn < 0) {
	char conf[32], *p;
	int major = 0, minor = 0;

	use_spawn = 0;
	memset(conf, 0, sizeof(conf));
	confstr(_CS_GNU_LIBC_VERSION, conf, sizeof(conf));
	p = strchr(conf, ' ');	/* skip "glibc" */
	if (p != NULL) {
	    ++p;
	    if (sscanf(p, "%d.%d", &major, &minor) > 1) {
		if ((major > 2) || ((major == 2) && (minor >= 24))) {
		    use_spawn = 1;
		}
	    }
	}
    }
#endif
    status = -1;
    if (use_spawn) {
	posix_spawn_file_actions_t actions;
	posix_spawnattr_t attr;
	sigset_t sigs;

	posix_spawn_file_actions_init(&actions);
	posix_spawnattr_init(&attr);
	sigfillset(&sigs);
	sigdelset(&sigs, SIGKILL);
	sigdelset(&sigs, SIGSTOP);

	posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGDEF
#ifdef POSIX_SPAWN_USEVFORK
		| POSIX_SPAWN_USEVFORK
#endif
		);
	posix_spawnattr_setsigdefault(&attr, &sigs);

	posix_spawn_file_actions_adddup2(&actions, GetFd(inputFile), 0);
	posix_spawn_file_actions_adddup2(&actions, GetFd(outputFile), 1);
	posix_spawn_file_actions_adddup2(&actions, GetFd(errorFile), 2);

	status = posix_spawnp(&pid, newArgv[0], &actions, &attr,
		newArgv, environ);
	childErrno = errno;
	posix_spawn_file_actions_destroy(&actions);
	posix_spawnattr_destroy(&attr);

	/*
	 * Fork semantics:
	 *  - pid == 0: child process
	 *  - pid == -1: error
	 *  - pid > 0: parent process
	 *
	 * Mimic fork semantics to minimize changes below,
	 * but retry with fork() as last ressort.
	 */
    }
    if (status != 0) {
    pid = fork();
	pid = fork();
	childErrno = errno;
    }
#else
    pid = fork();
#endif
    if (pid == 0) {
	size_t len;
	int joinThisError = errorFile && (errorFile == outputFile);

	fd = GetFd(errPipeOut);

	/*
	 * Set up stdio file handles for the child process.
	 */

	if (!SetupStdFile(inputFile, TCL_STDIN)
		|| !SetupStdFile(outputFile, TCL_STDOUT)
		|| (!joinThisError && !SetupStdFile(errorFile, TCL_STDERR))
		|| (joinThisError &&
			((dup2(1,2) == -1) || (fcntl(2, F_SETFD, 0) != 0)))) {
	    sprintf(errSpace,
	    snprintf(errSpace, sizeof(errSpace),
		    "%dforked process couldn't set up input/output", errno);
	    len = strlen(errSpace);
	    if (len != (size_t) write(fd, errSpace, len)) {
		    Tcl_Panic("TclpCreateProcess: unable to write to errPipeOut");
	    }
	    _exit(1);
	}

	/*
	 * Close the input side of the error pipe.
	 */

	RestoreSignals();
	execvp(newArgv[0], newArgv);			/* INTL: Native. */
	sprintf(errSpace, "%dcouldn't execute \"%.150s\"", errno, argv[0]);
	snprintf(errSpace, sizeof(errSpace), "%dcouldn't execute \"%.150s\"", errno, argv[0]);
	len = strlen(errSpace);
	if (len != (size_t) write(fd, errSpace, len)) {
	    Tcl_Panic("TclpCreateProcess: unable to write to errPipeOut");
	}
	_exit(1);
    }

    /*
     * Free the mem we used for the fork
     */

    for (i = 0; i < argc; i++) {
	Tcl_DStringFree(&dsArray[i]);
    }
    TclStackFree(interp, newArgv);
    TclStackFree(interp, dsArray);

    if (pid == -1) {
#ifdef HAVE_POSIX_SPAWNP
	errno = childErrno;
#endif
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"couldn't fork child process: %s", Tcl_PosixError(interp)));
	goto error;
    }

    /*
     * Read back from the error pipe to see if the child started up OK. The
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
558
633
634
635
636
637
638
639

640
641
642
643
644
645
646
647
648
649
650
651

652
653
654
655
656
657
658
659







-
+











-
+







	errno = strtol(errSpace, &end, 10);
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s: %s",
		end, Tcl_PosixError(interp)));
	goto error;
    }

    TclpCloseFile(errPipeIn);
    *pidPtr = (Tcl_Pid) INT2PTR(pid);
    *pidPtr = (Tcl_Pid)INT2PTR(pid);
    return TCL_OK;

  error:
    if (pid != -1) {
	/*
	 * Reap the child process now if an error occurred during its startup.
	 * We don't call this with WNOHANG because that can lead to defunct
	 * processes on an MP system. We shouldn't have to worry about hanging
	 * here, since this is the error case. [Bug: 6148]
	 */

	Tcl_WaitPid((Tcl_Pid) INT2PTR(pid), &status, 0);
	Tcl_WaitPid((Tcl_Pid)INT2PTR(pid), &status, 0);
    }

    if (errPipeIn) {
	TclpCloseFile(errPipeIn);
    }
    if (errPipeOut) {
	TclpCloseFile(errPipeOut);
732
733
734
735
736
737
738
739

740
741
742
743
744
745
746

747
748
749
750
751
752
753
833
834
835
836
837
838
839

840
841
842
843
844
845
846

847
848
849
850
851
852
853
854







-
+






-
+








Tcl_Channel
TclpCreateCommandChannel(
    TclFile readFile,		/* If non-null, gives the file for reading. */
    TclFile writeFile,		/* If non-null, gives the file for writing. */
    TclFile errorFile,		/* If non-null, gives the file where errors
				 * can be read. */
    int numPids,		/* The number of pids in the pid array. */
    size_t numPids,		/* The number of pids in the pid array. */
    Tcl_Pid *pidPtr)		/* An array of process identifiers. Allocated
				 * by the caller, freed when the channel is
				 * closed or the processes are detached (in a
				 * background exec). */
{
    char channelName[16 + TCL_INTEGER_SPACE];
    int channelId;
    int fd;
    PipeState *statePtr = (PipeState *)Tcl_Alloc(sizeof(PipeState));
    int mode;

    statePtr->inFile = readFile;
    statePtr->outFile = writeFile;
    statePtr->errorFile = errorFile;
    statePtr->numPids = numPids;
763
764
765
766
767
768
769
770

771
772

773
774

775
776

777
778
779
780
781
782
783
784
785

786
787
788
789
790
791
792
864
865
866
867
868
869
870

871
872

873
874

875
876

877
878
879
880
881
882
883
884
885

886
887
888
889
890
891
892
893







-
+

-
+

-
+

-
+








-
+







    }

    /*
     * Use one of the fds associated with the channel as the channel id.
     */

    if (readFile) {
	channelId = GetFd(readFile);
	fd = GetFd(readFile);
    } else if (writeFile) {
	channelId = GetFd(writeFile);
	fd = GetFd(writeFile);
    } else if (errorFile) {
	channelId = GetFd(errorFile);
	fd = GetFd(errorFile);
    } else {
	channelId = 0;
	fd = 0;
    }

    /*
     * For backward compatibility with previous versions of Tcl, we use
     * "file%d" as the base name for pipes even though it would be more
     * natural to use "pipe%d".
     */

    sprintf(channelName, "file%d", channelId);
    snprintf(channelName, sizeof(channelName), "file%d", fd);
    statePtr->channel = Tcl_CreateChannel(&pipeChannelType, channelName,
	    statePtr, mode);
    return statePtr->channel;
}

/*
 *----------------------------------------------------------------------
854
855
856
857
858
859
860
861

862
863
864
865
866
867
868
955
956
957
958
959
960
961

962
963
964
965
966
967
968
969







-
+







TclGetAndDetachPids(
    Tcl_Interp *interp,		/* Interpreter to append the PIDs to. */
    Tcl_Channel chan)		/* Handle for the pipeline. */
{
    PipeState *pipePtr;
    const Tcl_ChannelType *chanTypePtr;
    Tcl_Obj *pidsObj;
    int i;
    size_t i;

    /*
     * Punt if the channel is not a command channel.
     */

    chanTypePtr = Tcl_GetChannelType(chan);
    if (chanTypePtr != &pipeChannelType) {
996
997
998
999
1000
1001
1002


1003
1004
1005
1006
1007
1008
1009
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112







+
+







	 * routine.
	 */

	if (pipePtr->errorFile) {
	    errChan = Tcl_MakeFileChannel(
		    INT2PTR(GetFd(pipePtr->errorFile)),
		    TCL_READABLE);
	    /* Error channels should not raise encoding errors */
	    Tcl_SetChannelOption(NULL, errChan, "-profile", "replace");
	} else {
	    errChan = NULL;
	}
	result = TclCleanupChildren(interp, pipePtr->numPids, pipePtr->pidPtr,
		errChan);
    }

1126
1127
1128
1129
1130
1131
1132
















1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148

1149
1150
1151
1152
1153
1154
1155
1156
1157

1158
1159
1160
1161
1162
1163
1164
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+















-
+








-
+







 *
 * Side effects:
 *	Sets up the notifier so that a future event on the channel will be
 *	seen by Tcl.
 *
 *----------------------------------------------------------------------
 */

/*
 * Bug ad5a57f2f271: Tcl_NotifyChannel is not a Tcl_FileProc,
 * so do not pass it to directly to Tcl_CreateFileHandler.
 * Instead, pass a wrapper which is a Tcl_FileProc.
 */

static void
PipeWatchNotifyChannelWrapper(
    void *clientData,
    int mask)
{
    Tcl_Channel channel = (Tcl_Channel)clientData;

    Tcl_NotifyChannel(channel, mask);
}

static void
PipeWatchProc(
    void *instanceData,	/* The pipe state. */
    int mask)			/* Events of interest; an OR-ed combination of
				 * TCL_READABLE, TCL_WRITABLE and
				 * TCL_EXCEPTION. */
{
    PipeState *psPtr = (PipeState *)instanceData;
    int newmask;

    if (psPtr->inFile) {
	newmask = mask & (TCL_READABLE | TCL_EXCEPTION);
	if (newmask) {
	    Tcl_CreateFileHandler(GetFd(psPtr->inFile), newmask,
		    (Tcl_FileProc *) Tcl_NotifyChannel, psPtr->channel);
		    PipeWatchNotifyChannelWrapper, psPtr->channel);
	} else {
	    Tcl_DeleteFileHandler(GetFd(psPtr->inFile));
	}
    }
    if (psPtr->outFile) {
	newmask = mask & (TCL_WRITABLE | TCL_EXCEPTION);
	if (newmask) {
	    Tcl_CreateFileHandler(GetFd(psPtr->outFile), newmask,
		    (Tcl_FileProc *) Tcl_NotifyChannel, psPtr->channel);
		    PipeWatchNotifyChannelWrapper, psPtr->channel);
	} else {
	    Tcl_DeleteFileHandler(GetFd(psPtr->outFile));
	}
    }
}

/*
1222
1223
1224
1225
1226
1227
1228
1229

1230
1231
1232
1233
1234
1235
1236
1341
1342
1343
1344
1345
1346
1347

1348
1349
1350
1351
1352
1353
1354
1355







-
+







{
    int result;
    pid_t real_pid = (pid_t) PTR2INT(pid);

    while (1) {
	result = (int) waitpid(real_pid, statPtr, options);
	if ((result != -1) || (errno != EINTR)) {
	    return (Tcl_Pid) INT2PTR(result);
	    return (Tcl_Pid)INT2PTR(result);
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
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
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







-
+






-
+



-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_PidObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Argument strings. */
{
    Tcl_Channel chan;
    PipeState *pipePtr;
    int i;
    size_t i;
    Tcl_Obj *resultPtr;

    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?channelId?");
	Tcl_WrongNumArgs(interp, 1, objv, "?channel?");
	return TCL_ERROR;
    }

    if (objc == 1) {
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(getpid()));
    } else {
	/*
1284
1285
1286
1287
1288
1289
1290
1291

1292
1293
1294
1295
1296
1297
1298
1403
1404
1405
1406
1407
1408
1409

1410
1411
1412
1413
1414
1415
1416
1417







-
+







	 * Extract the process IDs from the pipe structure.
	 */

	pipePtr = (PipeState *)Tcl_GetChannelInstanceData(chan);
	TclNewObj(resultPtr);
	for (i = 0; i < pipePtr->numPids; i++) {
	    Tcl_ListObjAppendElement(NULL, resultPtr,
		    Tcl_NewWideIntObj(PTR2INT(TclpGetPid(pipePtr->pidPtr[i]))));
		    Tcl_NewWideIntObj(TclpGetPid(pipePtr->pidPtr[i])));
	}
	Tcl_SetObjResult(interp, resultPtr);
    }
    return TCL_OK;
}

/*

Changes to unix/tclUnixPort.h.

1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17









-
+







/*
 * tclUnixPort.h --
 *
 *	This header file handles porting issues that occur because of
 *	differences between systems. It reads in UNIX-related header files and
 *	sets up UNIX-related macros for Tcl's UNIX core. It should be the only
 *	file that contains #ifdefs to handle different flavors of UNIX. This
 *	file sets up the union of all UNIX-related things needed by any of the
 *	Tcl core files. This file depends on configuration #defines such as
 *	NO_DIRENT_H that are set up by the "configure" script.
 *	HAVE_SYS_PARAM_H that are set up by the "configure" script.
 *
 *	Much of the material in this file was originally contributed by Karl
 *	Lehenbauer, Mark Diekhans and Peter da Silva.
 *
 * Copyright (c) 1991-1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 *
36
37
38
39
40
41
42
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57
58
36
37
38
39
40
41
42







43


44
45
46
47
48
49
50







-
-
-
-
-
-
-
+
-
-







#endif
#include <pwd.h>
#include <signal.h>
#ifdef HAVE_SYS_PARAM_H
#   include <sys/param.h>
#endif
#include <sys/types.h>
#ifdef USE_DIRENT2_H
#   include "../compat/dirent2.h"
#else
#ifdef NO_DIRENT_H
#   include "../compat/dirent.h"
#else
#   include <dirent.h>
#include <dirent.h>
#endif
#endif

/*
 *---------------------------------------------------------------------------
 * Parameterize for 64-bit filesystem support.
 *---------------------------------------------------------------------------
 */

88
89
90
91
92
93
94


95
96
97
98
99
100
101
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95







+
+







#ifdef __CYGWIN__
#ifdef __cplusplus
extern "C" {
#endif
    /* Make some symbols available without including <windows.h> */
#   define CP_UTF8 65001
#   define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 0x00000004
#   define HMODULE void *
#   define MAX_PATH 260
#   define SOCKET unsigned int
#   define WSAEWOULDBLOCK 10035
    typedef unsigned short WCHAR;
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wignored-attributes"
#endif
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
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







+





-
-
-

+















-
-
-
-


-
-
+
+
-
-







-
-
-
-
-







    __declspec(dllimport) extern __stdcall int GetFileAttributesW(const WCHAR *);
    __declspec(dllimport) extern __stdcall int SetFileAttributesW(const WCHAR *, int);
    __declspec(dllimport) extern int cygwin_conv_path(int, const void *, void *, int);
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#   define timezone _timezone
    extern int TclOSfstat(int fd, void *statBuf);
    extern int TclOSstat(const char *name, void *statBuf);
    extern int TclOSlstat(const char *name, void *statBuf);
#ifdef __cplusplus
}
#endif
#elif defined(HAVE_STRUCT_STAT64) && !defined(__APPLE__)
#   define TclOSstat(name, buf) stat64(name, (struct stat64 *)buf)
#   define TclOSlstat(name,buf) lstat64(name, (struct stat64 *)buf)
#else
#   define TclOSfstat(fd, buf) fstat(fd, (struct stat *)buf)
#   define TclOSstat(name, buf) stat(name, (struct stat *)buf)
#   define TclOSlstat(name, buf) lstat(name, (struct stat *)buf)
#endif

/*
 *---------------------------------------------------------------------------
 * Miscellaneous includes that might be missing.
 *---------------------------------------------------------------------------
 */

#include <sys/file.h>
#ifdef HAVE_SYS_SELECT_H
#   include <sys/select.h>
#endif
#include <sys/stat.h>
#ifdef TIME_WITH_SYS_TIME
#   include <sys/time.h>
#   include <time.h>
#else
#ifdef HAVE_SYS_TIME_H
#   include <sys/time.h>
#else
#   include <time.h>
#endif
#include <time.h>
#endif
#endif
#ifndef NO_SYS_WAIT_H
#   include <sys/wait.h>
#endif
#ifdef HAVE_INTTYPES_H
#   include <inttypes.h>
#endif
#include <limits.h>
#ifdef HAVE_STDINT_H
#   include <stdint.h>
#else
#   include "../compat/stdint.h"
#endif
#include <unistd.h>

MODULE_SCOPE int TclUnixSetBlockingMode(int fd, int mode);

#include <utime.h>

/*
498
499
500
501
502
503
504
505

506
507
508
509
510
511
512
480
481
482
483
484
485
486

487
488
489
490
491
492
493
494







-
+







#   define NFDBITS	NBBY*sizeof(fd_mask)
#endif /* NFDBITS */

#define MASK_SIZE	howmany(FD_SETSIZE, NFDBITS)

/*
 *---------------------------------------------------------------------------
 * Not all systems declare the errno variable in errno.h. so this file does it
 * Not all systems declare the errno variable in errno.h, so this file does it
 * explicitly. The list of system error messages also isn't generally declared
 * in a header file anywhere.
 *---------------------------------------------------------------------------
 */

#ifdef NO_ERRNO
extern int errno;
619
620
621
622
623
624
625
626
627
628
629




630
631
632
633


634
635

636
637
638
639
640
641
642
643
644
645
646
647
648
649
601
602
603
604
605
606
607




608
609
610
611




612
613


614







615
616
617
618
619
620
621







-
-
-
-
+
+
+
+
-
-
-
-
+
+
-
-
+
-
-
-
-
-
-
-







#	    undef HAVE_LANGINFO
#	endif
#   endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
#   if defined(HAVE_COREFOUNDATION) && defined(__LP64__) && \
	    defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1050
#	warning "Weak import of 64-bit CoreFoundation is not supported, will not run on Mac OS X < 10.5."
#   endif

/*
 *---------------------------------------------------------------------------
 * At present, using vfork() instead of fork() causes execve() to fail
    /*
     * For now, test exec-17.1 fails (I/O setup after closing stdout) with
     * posix_spawnp(), but the classic implementation (based on fork()+execvp())
     * works well under macOS.
 * intermittently on Darwin x86_64. rdar://4685553
 *---------------------------------------------------------------------------
 */

     */
#   undef HAVE_POSIX_SPAWNP
#   if defined(__x86_64__) && !defined(FIXED_RDAR_4685553)
#	undef USE_VFORK
#   undef HAVE_VFORK
#   endif /* __x86_64__ */
/* Workaround problems with vfork() when building with llvm-gcc-4.2 */
#   if defined (__llvm__) && \
	    (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 2 || \
	    (__GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ > 0))))
#	undef USE_VFORK
#   endif /* __llvm__ */
#endif /* __APPLE__ */

/*
 *---------------------------------------------------------------------------
 * The following macros and declarations represent the interface between
 * generic and unix-specific parts of Tcl. Some of the macros may override
 * functions declared in tclInt.h.
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
654
655
656
657
658
659
660


661
662
663
664
665
666
667







-
-








/*
 *---------------------------------------------------------------------------
 * The following macros and declaration wrap the C runtime library functions.
 *---------------------------------------------------------------------------
 */

#define TclpExit	exit

#if !defined(TCL_THREADS) || TCL_THREADS
#   include <pthread.h>
#endif /* TCL_THREADS */

/* FIXME - Hyper-enormous platform assumption! */
#ifndef AF_INET6
#   define AF_INET6	10

Changes to unix/tclUnixSock.c.

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
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
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
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





-
+






+













-
+
















-
+












-
-
-
-
+

+






-
+
-

















-
+











-
-
-
-
-
-
+







/*
 * tclUnixSock.c --
 *
 *	This file contains Unix-specific socket related code.
 *
 * Copyright (c) 1995 Sun Microsystems, Inc.
 * Copyright © 1995 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include <netinet/tcp.h>

/*
 * Helper macros to make parts of this file clearer. The macros do exactly
 * what they say on the tin. :-) They also only ever refer to their arguments
 * once, and so can be used without regard to side effects.
 */

#define SET_BITS(var, bits)	((var) |= (bits))
#define CLEAR_BITS(var, bits)	((var) &= ~(bits))
#define GOT_BITS(var, bits)     (((var) & (bits)) != 0)

/* "sock" + a pointer in hex + \0 */
#define SOCK_CHAN_LENGTH        (4 + sizeof(void *) * 2 + 1)
#define SOCK_TEMPLATE           "sock%lx"
#define SOCK_TEMPLATE           "sock%" TCL_Z_MODIFIER "x"

#undef SOCKET   /* Possible conflict with win32 SOCKET */

/*
 * This is needed to comply with the strict aliasing rules of GCC, but it also
 * simplifies casting between the different sockaddr types.
 */

typedef union {
    struct sockaddr sa;
    struct sockaddr_in sa4;
    struct sockaddr_in6 sa6;
    struct sockaddr_storage sas;
} address;

/*
 * This structure describes per-instance state of a tcp based channel.
 * This structure describes per-instance state of a tcp-based channel.
 */

typedef struct TcpState TcpState;

typedef struct TcpFdList {
    TcpState *statePtr;
    int fd;
    struct TcpFdList *next;
} TcpFdList;

struct TcpState {
    Tcl_Channel channel;	/* Channel associated with this file. */
    int testFlags;              /* bit field for tests. Is set by testsocket
                                 * test procedure */
    TcpFdList fds;		/* The file descriptors of the sockets. */
    int flags;			/* ORed combination of the bitfields defined
    int flags;			/* OR'ed combination of the bitfields defined
				 * below. */
    TcpFdList fds;		/* The file descriptors of the sockets. */
    int interest;		/* Event types of interest */

    /*
     * Only needed for server sockets
     */

    Tcl_TcpAcceptProc *acceptProc;
    Tcl_TcpAcceptProc *acceptProc; /* Proc to call on accept. */
                                /* Proc to call on accept. */
    void *acceptProcData;  /* The data for the accept proc. */

    /*
     * Only needed for client sockets
     */

    struct addrinfo *addrlist;	/* Addresses to connect to. */
    struct addrinfo *addr;	/* Iterator over addrlist. */
    struct addrinfo *myaddrlist;/* Local address. */
    struct addrinfo *myaddr;	/* Iterator over myaddrlist. */
    int filehandlers;           /* Caches FileHandlers that get set up while
                                 * an async socket is not yet connected. */
    int connectError;           /* Cache SO_ERROR of async socket. */
    int cachedBlocking;         /* Cache blocking mode of async socket. */
};

/*
 * These bits may be ORed together into the "flags" field of a TcpState
 * These bits may be OR'ed together into the "flags" field of a TcpState
 * structure.
 */

#define TCP_NONBLOCKING		(1<<0)	/* Socket with non-blocking I/O */
#define TCP_ASYNC_CONNECT	(1<<1)	/* Async connect in progress. */
#define TCP_ASYNC_PENDING	(1<<4)	/* TcpConnect was called to
					 * process an async connect. This
					 * flag indicates that reentry is
					 * still pending */
#define TCP_ASYNC_FAILED	(1<<5)	/* An async connect finally failed */

/*
 * These bits may be ORed together into the "testFlags" field of a TcpState
 * structure.
 */

#define TCP_ASYNC_TEST_MODE	(1<<0)	/* Async testing activated.  Do not
#define TCP_ASYNC_TEST_MODE	(1<<8)	/* Async testing activated.  Do not
					 * automatically continue connection
					 * process. */

/*
 * The following defines the maximum length of the listen queue. This is the
 * number of outstanding yet-to-be-serviced requests for a connection on a
 * server socket, more than this number of outstanding requests and the
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
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







+
+
+



-
+







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







static int		TcpGetOptionProc(void *instanceData,
			    Tcl_Interp *interp, const char *optionName,
			    Tcl_DString *dsPtr);
static int		TcpInputProc(void *instanceData, char *buf,
			    int toRead, int *errorCode);
static int		TcpOutputProc(void *instanceData,
			    const char *buf, int toWrite, int *errorCode);
static int		TcpSetOptionProc(void *instanceData,
			    Tcl_Interp *interp, const char *optionName,
			    const char *value);
static void		TcpThreadActionProc(void *instanceData, int action);
static void		TcpWatchProc(void *instanceData, int mask);
static int		WaitForConnect(TcpState *statePtr, int *errorCodePtr);
static void		WrapNotify(void *clientData, int mask);
static Tcl_FileProc	WrapNotify;

/*
 * This structure describes the channel type structure for TCP socket
 * based IO:
 */

static const Tcl_ChannelType tcpChannelType = {
    "tcp",			/* Type name. */
    TCL_CHANNEL_VERSION_5,	/* v5 channel */
    NULL,		/* Close proc. */
    TcpInputProc,		/* Input proc. */
    TcpOutputProc,		/* Output proc. */
    NULL,			/* Seek proc. */
    NULL,			/* Set option proc. */
    TcpGetOptionProc,		/* Get option proc. */
    TcpWatchProc,		/* Initialize notifier. */
    TcpGetHandleProc,		/* Get OS handles out of channel. */
    TcpClose2Proc,		/* Close2 proc. */
    TcpBlockModeProc,		/* Set blocking or non-blocking mode.*/
    NULL,			/* flush proc. */
    NULL,			/* handler proc. */
    NULL,			/* wide seek proc. */
    TcpThreadActionProc,	/* thread action proc. */
    NULL			/* truncate proc. */
    "tcp",
    TCL_CHANNEL_VERSION_5,
    NULL,			/* Deprecated. */
    TcpInputProc,
    TcpOutputProc,
    NULL,			/* Deprecated. */
    TcpSetOptionProc,
    TcpGetOptionProc,
    TcpWatchProc,
    TcpGetHandleProc,
    TcpClose2Proc,
    TcpBlockModeProc,
    NULL,			/* Flush proc. */
    NULL,			/* Bubbled event handler proc. */
    NULL,			/* Seek proc. */
    TcpThreadActionProc,
    NULL			/* Truncate proc. */
};

/*
 * The following variable holds the network name of this host.
 */

static TclInitProcessGlobalValueProc InitializeHostName;
203
204
205
206
207
208
209
210
211


212
213
214
215
216
217
218
199
200
201
202
203
204
205


206
207
208
209
210
211
212
213
214







-
-
+
+







}
#endif
/*
 * ----------------------------------------------------------------------
 *
 * InitializeHostName --
 *
 * 	This routine sets the process global value of the name of the local
 * 	host on which the process is running.
 *	This routine sets the process global value of the name of the local
 *	host on which the process is running.
 *
 * Results:
 *	None.
 *
 * ----------------------------------------------------------------------
 */

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
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







-
+


















-
+

-
+

-
+








#ifndef NO_UNAME
    struct utsname u;
    struct hostent *hp;

    memset(&u, (int) 0, sizeof(struct utsname));
    if (uname(&u) >= 0) {				/* INTL: Native. */
        hp = TclpGetHostByName(u.nodename);		/* INTL: Native. */
	hp = TclpGetHostByName(u.nodename);		/* INTL: Native. */
	if (hp == NULL) {
	    /*
	     * Sometimes the nodename is fully qualified, but gets truncated
	     * as it exceeds SYS_NMLN. See if we can just get the immediate
	     * nodename and get a proper answer that way.
	     */

	    char *dot = strchr(u.nodename, '.');

	    if (dot != NULL) {
		char *node = (char *)Tcl_Alloc(dot - u.nodename + 1);

		memcpy(node, u.nodename, dot - u.nodename);
		node[dot - u.nodename] = '\0';
		hp = TclpGetHostByName(node);
		Tcl_Free(node);
	    }
	}
        if (hp != NULL) {
	if (hp != NULL) {
	    native = hp->h_name;
        } else {
	} else {
	    native = u.nodename;
        }
	}
    }
#else /* !NO_UNAME */
    /*
     * Uname doesn't exist; try gethostname instead.
     *
     * There is no portable macro for the maximum length of host names
     * returned by gethostbyname(). We should only trust SYS_NMLN if it is at
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
314
315
316
317
318
319
320























321
322
323
324
325
326
327







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    Tcl_Obj *tclObj = TclGetProcessGlobalValue(&hostName);
    return TclGetString(tclObj);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclpHasSockets --
 *
 *	Detect if sockets are available on this platform.
 *
 * Results:
 *	Returns TCL_OK.
 *
 * Side effects:
 *	None.
 *
 * ----------------------------------------------------------------------
 */

int
TclpHasSockets(
    TCL_UNUSED(Tcl_Interp *))
{
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclpFinalizeSockets --
 *
 *	Performs per-thread socket subsystem finalization.
 *
 * Results:
 *	None.
 *
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
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







-
-
+
+














-
+



-
+




-
-
+
+



-
-
+
+



-
+








    if (mode == TCL_MODE_BLOCKING) {
	CLEAR_BITS(statePtr->flags, TCP_NONBLOCKING);
    } else {
	SET_BITS(statePtr->flags, TCP_NONBLOCKING);
    }
    if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
        statePtr->cachedBlocking = mode;
        return 0;
	statePtr->cachedBlocking = mode;
	return 0;
    }
    if (TclUnixSetBlockingMode(statePtr->fds.fd, mode) < 0) {
	return errno;
    }
    return 0;
}

/*
 * ----------------------------------------------------------------------
 *
 * WaitForConnect --
 *
 *	Check the state of an async connect process. If a connection attempt
 *	terminated, process it, which may finalize it or may start the next
 *	attempt. If a connect error occures, it is saved in
 *	attempt. If a connect error occurs, it is saved in
 *	statePtr->connectError to be reported by 'fconfigure -error'.
 *
 *	There are two modes of operation, defined by errorCodePtr:
 *	 *  non-NULL: Called by explicite read/write command. Blocks if the
 *	 *  non-NULL: Called by explicit read/write command. Blocks if the
 *	    socket is blocking.
 *	    May return two error codes:
 *	     *	EWOULDBLOCK: if connect is still in progress
 *	     *	ENOTCONN: if connect failed. This would be the error message
 *		of a rect or sendto syscall so this is emulated here.
 *	 *  NULL: Called by a backround operation. Do not block and do not
 *		of a recv or sendto syscall so this is emulated here.
 *	 *  NULL: Called by a background operation. Do not block and do not
 *	    return any error code.
 *
 * Results:
 * 	0 if the connection has completed, -1 if still in progress or there is
 * 	an error.
 *	0 if the connection has completed, -1 if still in progress or there is
 *	an error.
 *
 * Side effects:
 *	Processes socket events off the system queue. May process
 *	asynchroneous connects.
 *	asynchronous connects.
 *
 *----------------------------------------------------------------------
 */

static int
WaitForConnect(
    TcpState *statePtr,		/* State of the socket. */
450
451
452
453
454
455
456
457

458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473



474
475
476
477
478
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
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
467
468







469
470
471
472
473
474
475
476
477
478
479
480
481
482







-
+













-
-
-
+
+
+





-
+

-
+


-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+



-
-
-
-
-
-
-
+
+
+
+
+
+
+








    if (errorCodePtr != NULL && GOT_BITS(statePtr->flags, TCP_ASYNC_FAILED)) {
	*errorCodePtr = ENOTCONN;
	return -1;
    }

    /*
     * Check if an async connect is running. If not return ok
     * Check if an async connect is running. If not return ok.
     */

    if (!GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) {
	return 0;
    }

    /*
     * In socket test mode do not continue with the connect.
     * Exceptions are:
     * - Call by recv/send and blocking socket
     *   (errorCodePtr != NULL && !GOT_BITS(flags, TCP_NONBLOCKING))
     */

    if (GOT_BITS(statePtr->testFlags, TCP_ASYNC_TEST_MODE)
            && !(errorCodePtr != NULL
                    && !GOT_BITS(statePtr->flags, TCP_NONBLOCKING))) {
    if (GOT_BITS(statePtr->flags, TCP_ASYNC_TEST_MODE)
	    && !(errorCodePtr != NULL
		    && !GOT_BITS(statePtr->flags, TCP_NONBLOCKING))) {
	*errorCodePtr = EWOULDBLOCK;
	return -1;
    }

    if (errorCodePtr == NULL || GOT_BITS(statePtr->flags, TCP_NONBLOCKING)) {
        timeout = 0;
	timeout = 0;
    } else {
        timeout = -1;
	timeout = -1;
    }
    do {
        if (TclUnixWaitForFile(statePtr->fds.fd,
                TCL_WRITABLE | TCL_EXCEPTION, timeout) != 0) {
            TcpConnect(NULL, statePtr);
        }
	if (TclUnixWaitForFile(statePtr->fds.fd,
		TCL_WRITABLE | TCL_EXCEPTION, timeout) != 0) {
	    TcpConnect(NULL, statePtr);
	}

        /*
         * Do this only once in the nonblocking case and repeat it until the
         * socket is final when blocking.
         */
	/*
	 * Do this only once in the nonblocking case and repeat it until the
	 * socket is final when blocking.
	 */
    } while (timeout == -1 && GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT));

    if (errorCodePtr != NULL) {
        if (GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) {
            *errorCodePtr = EAGAIN;
            return -1;
        } else if (statePtr->connectError != 0) {
            *errorCodePtr = ENOTCONN;
            return -1;
        }
	if (GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) {
	    *errorCodePtr = EAGAIN;
	    return -1;
	} else if (statePtr->connectError != 0) {
	    *errorCodePtr = ENOTCONN;
	    return -1;
	}
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
649
650
651
652
653
654
655
656

657
658
659

660
661
662
663
664
665
666
622
623
624
625
626
627
628

629
630
631

632
633
634
635
636
637
638
639







-
+


-
+







    while (fds != NULL) {
	TcpFdList *next = fds->next;

	Tcl_Free(fds);
	fds = next;
    }
    if (statePtr->addrlist != NULL) {
        freeaddrinfo(statePtr->addrlist);
	freeaddrinfo(statePtr->addrlist);
    }
    if (statePtr->myaddrlist != NULL) {
        freeaddrinfo(statePtr->myaddrlist);
	freeaddrinfo(statePtr->myaddrlist);
    }
    Tcl_Free(statePtr);
    return errorCode;
}

/*
 *----------------------------------------------------------------------
728
729
730
731
732
733
734
735

736
737
738
739
740
741
742
743
744

745
746
747
748

749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767

768
769
770
771
772
773
774
775
776
777
778



779
780
781
782
783



784
785
786
787
788
789
790
791
792
793


794
795
796
797
798
799




800
801

802
803
804
805



806
807

808
809
810

















































































811
812
813
814
815
816
817
701
702
703
704
705
706
707

708
709
710
711
712
713
714
715
716

717
718
719
720

721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739

740
741
742
743
744
745
746
747
748



749
750
751
752
753



754
755
756
757
758
759
760
761
762
763
764


765
766
767
768




769
770
771
772
773

774
775



776
777
778
779

780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871







-
+








-
+



-
+


















-
+








-
-
-
+
+
+


-
-
-
+
+
+








-
-
+
+


-
-
-
-
+
+
+
+

-
+

-
-
-
+
+
+

-
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif
static inline int
IPv6AddressNeedsNumericRendering(
    struct in6_addr addr)
{
    if (IN6_ARE_ADDR_EQUAL(&addr, &in6addr_any)) {
        return 1;
	return 1;
    }

    /*
     * The IN6_IS_ADDR_V4MAPPED macro has a problem with aliasing warnings on
     * at least some versions of OSX.
     */

    if (!IN6_IS_ADDR_V4MAPPED(&addr)) {
        return 0;
	return 0;
    }

    return (addr.s6_addr[12] == 0 && addr.s6_addr[13] == 0
            && addr.s6_addr[14] == 0 && addr.s6_addr[15] == 0);
	    && addr.s6_addr[14] == 0 && addr.s6_addr[15] == 0);
}
#if defined (__clang__) || ((__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
#pragma GCC diagnostic pop
#endif
#endif /* NEED_FAKE_RFC2553 */

static void
TcpHostPortList(
    Tcl_Interp *interp,
    Tcl_DString *dsPtr,
    address addr,
    socklen_t salen)
{
#define SUPPRESS_RDNS_VAR "::tcl::unsupported::noReverseDNS"
    char host[NI_MAXHOST], nhost[NI_MAXHOST], nport[NI_MAXSERV];
    int flags = 0;

    getnameinfo(&addr.sa, salen, nhost, sizeof(nhost), nport, sizeof(nport),
            NI_NUMERICHOST | NI_NUMERICSERV);
	    NI_NUMERICHOST | NI_NUMERICSERV);
    Tcl_DStringAppendElement(dsPtr, nhost);

    /*
     * We don't want to resolve INADDR_ANY and sin6addr_any; they can
     * sometimes cause problems (and never have a name).
     */

    if (addr.sa.sa_family == AF_INET) {
        if (addr.sa4.sin_addr.s_addr == INADDR_ANY) {
            flags |= NI_NUMERICHOST;
        }
	if (addr.sa4.sin_addr.s_addr == INADDR_ANY) {
	    flags |= NI_NUMERICHOST;
	}
#ifndef NEED_FAKE_RFC2553
    } else if (addr.sa.sa_family == AF_INET6) {
        if (IPv6AddressNeedsNumericRendering(addr.sa6.sin6_addr)) {
            flags |= NI_NUMERICHOST;
        }
	if (IPv6AddressNeedsNumericRendering(addr.sa6.sin6_addr)) {
	    flags |= NI_NUMERICHOST;
	}
#endif /* NEED_FAKE_RFC2553 */
    }

    /*
     * Check if reverse DNS has been switched off globally.
     */

    if (interp != NULL &&
            Tcl_GetVar2(interp, SUPPRESS_RDNS_VAR, NULL, 0) != NULL) {
        flags |= NI_NUMERICHOST;
	    Tcl_GetVar2(interp, SUPPRESS_RDNS_VAR, NULL, 0) != NULL) {
	flags |= NI_NUMERICHOST;
    }
    if (getnameinfo(&addr.sa, salen, host, sizeof(host), NULL, 0,
            flags) == 0) {
        /*
         * Reverse mapping worked.
         */
	    flags) == 0) {
	/*
	 * Reverse mapping worked.
	 */

        Tcl_DStringAppendElement(dsPtr, host);
	Tcl_DStringAppendElement(dsPtr, host);
    } else {
        /*
         * Reverse mapping failed - use the numeric rep once more.
         */
	/*
	 * Reverse mapping failed - use the numeric rep once more.
	 */

        Tcl_DStringAppendElement(dsPtr, nhost);
	Tcl_DStringAppendElement(dsPtr, nhost);
    }
    Tcl_DStringAppendElement(dsPtr, nport);
}

/*
 *----------------------------------------------------------------------
 *
 * TcpSetOptionProc --
 *
 *	Sets TCP channel specific options.
 *
 * Results:
 *	None, unless an error happens.
 *
 * Side effects:
 *	Changes attributes of the socket at the system level.
 *
 *----------------------------------------------------------------------
 */

static int
TcpSetOptionProc(
    void *instanceData,		/* Socket state. */
    Tcl_Interp *interp,		/* For error reporting - can be NULL. */
    const char *optionName,	/* Name of the option to set. */
    const char *value)		/* New value for option. */
{
    TcpState *statePtr = (TcpState *)instanceData;
    size_t len = 0;

    if (optionName != NULL) {
	len = strlen(optionName);
    }

    if ((len > 1) && (optionName[1] == 'k') &&
	    (strncmp(optionName, "-keepalive", len) == 0)) {
	int val = 0, ret;

	if (Tcl_GetBoolean(interp, value, &val) != TCL_OK) {
	    return TCL_ERROR;
	}
#if defined(SO_KEEPALIVE)
	ret = setsockopt(statePtr->fds.fd, SOL_SOCKET, SO_KEEPALIVE,
		(const char *) &val, sizeof(int));
#else
	ret = -1;
	Tcl_SetErrno(ENOTSUP);
#endif
	if (ret < 0) {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"couldn't set socket option: %s",
			Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}
	return TCL_OK;
    }
    if ((len > 1) && (optionName[1] == 'n') &&
	    (strncmp(optionName, "-nodelay", len) == 0)) {
	int val = 0, ret;

	if (Tcl_GetBoolean(interp, value, &val) != TCL_OK) {
	    return TCL_ERROR;
	}
#if defined(SOL_TCP) && defined(TCP_NODELAY)
	ret = setsockopt(statePtr->fds.fd, SOL_TCP, TCP_NODELAY,
		(const char *) &val, sizeof(int));
#else
	ret = -1;
	Tcl_SetErrno(ENOTSUP);
#endif
	if (ret < 0) {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"couldn't set socket option: %s",
			Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}
	return TCL_OK;
    }
    return Tcl_BadChannelOption(interp, optionName, "keepalive nodelay");
}

/*
 *----------------------------------------------------------------------
 *
 * TcpGetOptionProc --
 *
 *	Computes an option value for a TCP socket based channel, or a list of
828
829
830
831
832
833
834
835

836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855

856
857
858
859




860
861
862
863
864
865
866






867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910

911
912
913
914



915
916
917
918
919
920
921
922
923
924
925
926

927
928
929
930
931
932
933
934
935
936
937
938


939
940

941
942
943
944
945
946
947
948
949
950

951
952
953
954
955
956
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
882
883
884
885
886
887
888

889
890
891
892
893
894
895
896
897
898
899


900
901
902
903
904
905
906
907
908




909
910
911
912
913






914
915
916
917
918
919
920







921
922
923
924
925
926
927
928
929
930
931
932
933



934
935
936
937
938
939
940


941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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










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







-
+










-
-








+
-
-
-
-
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+





+
-
-
-
+
+
+




-
-
+
+

+




















-
+

-
-
-
+
+
+











-
+










-
-
+
+


+









-
+









-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TcpGetOptionProc(
    void *instanceData,	/* Socket state. */
    void *instanceData,		/* Socket state. */
    Tcl_Interp *interp,		/* For error reporting - can be NULL. */
    const char *optionName,	/* Name of the option to retrieve the value
				 * for, or NULL to get all options and their
				 * values. */
    Tcl_DString *dsPtr)		/* Where to store the computed value;
				 * initialized by caller. */
{
    TcpState *statePtr = (TcpState *)instanceData;
    size_t len = 0;

    WaitForConnect(statePtr, NULL);

    if (optionName != NULL) {
	len = strlen(optionName);
    }

    if ((len > 1) && (optionName[1] == 'e') &&
	    (strncmp(optionName, "-error", len) == 0)) {
	socklen_t optlen = sizeof(int);

	WaitForConnect(statePtr, NULL);
        if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
            /*
             * Suppress errors as long as we are not done.
             */
	if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
	    /*
	     * Suppress errors as long as we are not done.
	     */

            errno = 0;
        } else if (statePtr->connectError != 0) {
            errno = statePtr->connectError;
            statePtr->connectError = 0;
        } else {
            int err;
	    errno = 0;
	} else if (statePtr->connectError != 0) {
	    errno = statePtr->connectError;
	    statePtr->connectError = 0;
	} else {
	    int err;

            getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_ERROR, (char *) &err,
                    &optlen);
            errno = err;
        }
        if (errno != 0) {
	    Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(errno), -1);
        }
	    getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_ERROR, (char *) &err,
		    &optlen);
	    errno = err;
	}
	if (errno != 0) {
	    Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(errno), TCL_INDEX_NONE);
	}
	return TCL_OK;
    }

    if ((len > 1) && (optionName[1] == 'c') &&
	    (strncmp(optionName, "-connecting", len) == 0)) {
	WaitForConnect(statePtr, NULL);
        Tcl_DStringAppend(dsPtr,
                GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT) ? "1" : "0", -1);
        return TCL_OK;
	Tcl_DStringAppend(dsPtr,
		GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT) ? "1" : "0", TCL_INDEX_NONE);
	return TCL_OK;
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 'p') &&
	    (strncmp(optionName, "-peername", len) == 0))) {
        address peername;
        socklen_t size = sizeof(peername);
	address peername;
	socklen_t size = sizeof(peername);

	WaitForConnect(statePtr, NULL);
	if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
	    /*
	     * In async connect output an empty string
	     */

	    if (len == 0) {
		Tcl_DStringAppendElement(dsPtr, "-peername");
		Tcl_DStringAppendElement(dsPtr, "");
	    } else {
		return TCL_OK;
	    }
	} else if (getpeername(statePtr->fds.fd, &peername.sa, &size) >= 0) {
	    /*
	     * Peername fetch succeeded - output list
	     */

	    if (len == 0) {
		Tcl_DStringAppendElement(dsPtr, "-peername");
		Tcl_DStringStartSublist(dsPtr);
	    }
            TcpHostPortList(interp, dsPtr, peername, size);
	    TcpHostPortList(interp, dsPtr, peername, size);
	    if (len) {
                return TCL_OK;
            }
            Tcl_DStringEndSublist(dsPtr);
		return TCL_OK;
	    }
	    Tcl_DStringEndSublist(dsPtr);
	} else {
	    /*
	     * getpeername failed - but if we were asked for all the options
	     * (len==0), don't flag an error at that point because it could be
	     * an fconfigure request on a server socket (which have no peer).
	     * Same must be done on win&mac.
	     */

	    if (len) {
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                            "can't get peername: %s",
			    "can't get peername: %s",
			    Tcl_PosixError(interp)));
		}
		return TCL_ERROR;
	    }
	}
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 's') &&
	    (strncmp(optionName, "-sockname", len) == 0))) {
	TcpFdList *fds;
        address sockname;
        socklen_t size;
	address sockname;
	socklen_t size;
	int found = 0;

	WaitForConnect(statePtr, NULL);
	if (len == 0) {
	    Tcl_DStringAppendElement(dsPtr, "-sockname");
	    Tcl_DStringStartSublist(dsPtr);
	}
	if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
	    /*
	     * In async connect output an empty string
	     */

            found = 1;
	    found = 1;
	} else {
	    for (fds = &statePtr->fds; fds != NULL; fds = fds->next) {
		size = sizeof(sockname);
		if (getsockname(fds->fd, &(sockname.sa), &size) >= 0) {
		    found = 1;
		    TcpHostPortList(interp, dsPtr, sockname, size);
		}
	    }
	}
        if (found) {
            if (len) {
                return TCL_OK;
            }
            Tcl_DStringEndSublist(dsPtr);
        } else {
            if (interp) {
                Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                        "can't get sockname: %s", Tcl_PosixError(interp)));
            }
	if (found) {
	    if (len) {
		return TCL_OK;
	    }
	    Tcl_DStringEndSublist(dsPtr);
	} else {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't get sockname: %s", Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 'k') &&
	    (strncmp(optionName, "-keepalive", len) == 0))) {
	int opt = 0;
#if defined(SO_KEEPALIVE)
	socklen_t size = sizeof(opt);
#endif

	if (len == 0) {
	    Tcl_DStringAppendElement(dsPtr, "-keepalive");
	}
#if defined(SO_KEEPALIVE)
	getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_KEEPALIVE,
		(char *) &opt, &size);
#endif
	Tcl_DStringAppendElement(dsPtr, opt ? "1" : "0");
    if (len > 0) {
	if (len > 0) {
	    return TCL_OK;
	}
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 'n') &&
	    (strncmp(optionName, "-nodelay", len) == 0))) {
	int opt = 0;
#if defined(SOL_TCP) && defined(TCP_NODELAY)
	socklen_t size = sizeof(opt);
#endif

	if (len == 0) {
	    Tcl_DStringAppendElement(dsPtr, "-nodelay");
	}
#if defined(SOL_TCP) && defined(TCP_NODELAY)
	getsockopt(statePtr->fds.fd, SOL_TCP, TCP_NODELAY,
		(char *) &opt, &size);
#endif
	Tcl_DStringAppendElement(dsPtr, opt ? "1" : "0");
	if (len > 0) {
	    return TCL_OK;
	}
    }

    if (len > 0) {
	return Tcl_BadChannelOption(interp, optionName,
                "connecting peername sockname");
		"connecting keepalive nodelay peername sockname");
    }

    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
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
1116
1117
1118
1119
1120
1121
1122


1123
1124

1125
1126
1127
1128
1129
1130
1131
1172
1173
1174
1175
1176
1177
1178





1179
1180
1181
1182
1183
1184

1185
1186
1187
1188




1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1201
1202

1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216


1217
1218
1219

1220
1221
1222
1223
1224
1225
1226
1227







-
-
-
-
-
+
+
+
+
+

-
+



-
-
-
-
+
+
+
+

-
+








-
+













-
-
+
+

-
+







    int mask)			/* Events of interest; an OR-ed combination of
				 * TCL_READABLE, TCL_WRITABLE and
				 * TCL_EXCEPTION. */
{
    TcpState *statePtr = (TcpState *)instanceData;

    if (statePtr->acceptProc != NULL) {
        /*
         * Make sure we don't mess with server sockets since they will never
         * be readable or writable at the Tcl level. This keeps Tcl scripts
         * from interfering with the -accept behavior (bug #3394732).
         */
	/*
	 * Make sure we don't mess with server sockets since they will never
	 * be readable or writable at the Tcl level. This keeps Tcl scripts
	 * from interfering with the -accept behavior (bug #3394732).
	 */

    	return;
	return;
    }

    if (GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) {
        /*
         * Async sockets use a FileHandler internally while connecting, so we
         * need to cache this request until the connection has succeeded.
         */
	/*
	 * Async sockets use a FileHandler internally while connecting, so we
	 * need to cache this request until the connection has succeeded.
	 */

        statePtr->filehandlers = mask;
	statePtr->filehandlers = mask;
    } else if (mask) {

	/*
	 * Whether it is a bug or feature or otherwise, it is a fact of life
	 * that on at least some Linux kernels select() fails to report that a
	 * socket file descriptor is writable when the other end of the socket
	 * is closed.  This is in contrast to the guarantees Tcl makes that
	 * its channels become writable and fire writable events on an error
	 * conditon.  This has caused a leak of file descriptors in a state of
	 * condition.  This has caused a leak of file descriptors in a state of
	 * background flushing.  See Tcl ticket 1758a0b603.
	 *
	 * As a workaround, when our caller indicates an interest in writable
	 * notifications, we must tell the notifier built around select() that
	 * we are interested in the readable state of the file descriptor as
	 * well, as that is the only reliable means to get notified of error
	 * conditions.  Then it is the task of WrapNotify() above to untangle
	 * the meaning of these channel states and report the chan events as
	 * best it can.  We save a copy of the mask passed in to assist with
	 * that.
	 */

	statePtr->interest = mask;
        Tcl_CreateFileHandler(statePtr->fds.fd, mask|TCL_READABLE,
                (Tcl_FileProc *) WrapNotify, statePtr);
	Tcl_CreateFileHandler(statePtr->fds.fd, mask|TCL_READABLE,
		WrapNotify, statePtr);
    } else {
        Tcl_DeleteFileHandler(statePtr->fds.fd);
	Tcl_DeleteFileHandler(statePtr->fds.fd);
    }
}

/*
 * ----------------------------------------------------------------------
 *
 * TcpGetHandleProc --
1213
1214
1215
1216
1217
1218
1219
1220

1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357








1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368





1369
1370
1371
1372
1373
1374
1375






1376
1377
1378
1379
1380
1381
1382
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
1354
1355
1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394




1395
1396
1397
1398
1399






1400
1401
1402
1403
1404
1405
1406



1407
1408
1409
1410






1411
1412
1413
1414
1415
1416
1417

1418
1419




1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433



1434
1435
1436
1437


1438
1439
1440



1441
1442
1443
1444








1445
1446
1447
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







-
+



-
-
-
-
+
+
+
+
-









-
-
-
-
+
+
+
+

-
+


-
+



-
+


















-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+









-
-
-
-
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
+

-
-
-
-
+
+
+
+










-
-
-
+
+
+

-
-
+
+

-
-
-
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+






-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+







    socklen_t optlen;
    int async_callback = GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING);
    int ret = -1, error = EHOSTUNREACH;
    int async = GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
    static const int reuseaddr = 1;

    if (async_callback) {
        goto reenter;
	goto reenter;
    }

    for (statePtr->addr = statePtr->addrlist; statePtr->addr != NULL;
            statePtr->addr = statePtr->addr->ai_next) {
        for (statePtr->myaddr = statePtr->myaddrlist;
                statePtr->myaddr != NULL;
                statePtr->myaddr = statePtr->myaddr->ai_next) {
	    statePtr->addr = statePtr->addr->ai_next) {
	for (statePtr->myaddr = statePtr->myaddrlist;
		statePtr->myaddr != NULL;
		statePtr->myaddr = statePtr->myaddr->ai_next) {

	    /*
	     * No need to try combinations of local and remote addresses of
	     * different families.
	     */

	    if (statePtr->myaddr->ai_family != statePtr->addr->ai_family) {
		continue;
	    }

            /*
             * Close the socket if it is still open from the last unsuccessful
             * iteration.
             */
	    /*
	     * Close the socket if it is still open from the last unsuccessful
	     * iteration.
	     */

            if (statePtr->fds.fd >= 0) {
	    if (statePtr->fds.fd >= 0) {
		close(statePtr->fds.fd);
		statePtr->fds.fd = -1;
                errno = 0;
		errno = 0;
	    }

	    statePtr->fds.fd = socket(statePtr->addr->ai_family, SOCK_STREAM,
                    0);
		    0);
	    if (statePtr->fds.fd < 0) {
		continue;
	    }

	    /*
	     * Set the close-on-exec flag so that the socket will not get
	     * inherited by child processes.
	     */

	    fcntl(statePtr->fds.fd, F_SETFD, FD_CLOEXEC);

	    /*
	     * Set kernel space buffering
	     */

	    TclSockMinimumBuffers(INT2PTR(statePtr->fds.fd), SOCKET_BUFSIZE);

	    if (async) {
                ret = TclUnixSetBlockingMode(statePtr->fds.fd,
                        TCL_MODE_NONBLOCKING);
                if (ret < 0) {
                    continue;
                }
            }
		ret = TclUnixSetBlockingMode(statePtr->fds.fd,
			TCL_MODE_NONBLOCKING);
		if (ret < 0) {
		    continue;
		}
	    }

            /*
             * Must reset the error variable here, before we use it for the
             * first time in this iteration.
             */
	    /*
	     * Must reset the error variable here, before we use it for the
	     * first time in this iteration.
	     */

            error = 0;
	    error = 0;

            (void) setsockopt(statePtr->fds.fd, SOL_SOCKET, SO_REUSEADDR,
                    (char *) &reuseaddr, sizeof(reuseaddr));
            ret = bind(statePtr->fds.fd, statePtr->myaddr->ai_addr,
                    statePtr->myaddr->ai_addrlen);
            if (ret < 0) {
                error = errno;
                continue;
            }
	    (void) setsockopt(statePtr->fds.fd, SOL_SOCKET, SO_REUSEADDR,
		    (char *) &reuseaddr, sizeof(reuseaddr));
	    ret = bind(statePtr->fds.fd, statePtr->myaddr->ai_addr,
		    statePtr->myaddr->ai_addrlen);
	    if (ret < 0) {
		error = errno;
		continue;
	    }

	    /*
	     * Attempt to connect. The connect may fail at present with an
	     * EINPROGRESS but at a later time it will complete. The caller
	     * will set up a file handler on the socket if she is interested
	     * in being informed when the connect completes.
	     */

	    ret = connect(statePtr->fds.fd, statePtr->addr->ai_addr,
                        statePtr->addr->ai_addrlen);
            if (ret < 0) {
                error = errno;
            }
			statePtr->addr->ai_addrlen);
	    if (ret < 0) {
		error = errno;
	    }
	    if (ret < 0 && errno == EINPROGRESS) {
                Tcl_CreateFileHandler(statePtr->fds.fd,
                        TCL_WRITABLE | TCL_EXCEPTION, TcpAsyncCallback,
                        statePtr);
                errno = EWOULDBLOCK;
                SET_BITS(statePtr->flags, TCP_ASYNC_PENDING);
                return TCL_OK;
		Tcl_CreateFileHandler(statePtr->fds.fd,
			TCL_WRITABLE | TCL_EXCEPTION, TcpAsyncCallback,
			statePtr);
		errno = EWOULDBLOCK;
		SET_BITS(statePtr->flags, TCP_ASYNC_PENDING);
		return TCL_OK;

            reenter:
                CLEAR_BITS(statePtr->flags, TCP_ASYNC_PENDING);
                Tcl_DeleteFileHandler(statePtr->fds.fd);
	    reenter:
		CLEAR_BITS(statePtr->flags, TCP_ASYNC_PENDING);
		Tcl_DeleteFileHandler(statePtr->fds.fd);

                /*
                 * Read the error state from the socket to see if the async
                 * connection has succeeded or failed. As this clears the
                 * error condition, we cache the status in the socket state
                 * struct for later retrieval by [fconfigure -error].
                 */
		/*
		 * Read the error state from the socket to see if the async
		 * connection has succeeded or failed. As this clears the
		 * error condition, we cache the status in the socket state
		 * struct for later retrieval by [fconfigure -error].
		 */

                optlen = sizeof(int);
		optlen = sizeof(int);

                getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_ERROR,
                        (char *) &error, &optlen);
                errno = error;
            }
		getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_ERROR,
			(char *) &error, &optlen);
		errno = error;
	    }
	    if (error == 0) {
		goto out;
	    }
	}
    }

  out:
    statePtr->connectError = error;
    CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
    if (async_callback) {
        /*
         * An asynchonous connection has finally succeeded or failed.
         */
	/*
	 * An asynchonous connection has finally succeeded or failed.
	 */

        TcpWatchProc(statePtr, statePtr->filehandlers);
        TclUnixSetBlockingMode(statePtr->fds.fd, statePtr->cachedBlocking);
	TcpWatchProc(statePtr, statePtr->filehandlers);
	TclUnixSetBlockingMode(statePtr->fds.fd, statePtr->cachedBlocking);

        if (error != 0) {
            SET_BITS(statePtr->flags, TCP_ASYNC_FAILED);
        }
	if (error != 0) {
	    SET_BITS(statePtr->flags, TCP_ASYNC_FAILED);
	}

        /*
         * We need to forward the writable event that brought us here, bcasue
         * upon reading of getsockopt(SO_ERROR), at least some OSes clear the
         * writable state from the socket, and so a subsequent select() on
         * behalf of a script level [fileevent] would not fire. It doesn't
         * hurt that this is also called in the successful case and will save
         * the event mechanism one roundtrip through select().
         */
	/*
	 * We need to forward the writable event that brought us here, because
	 * upon reading of getsockopt(SO_ERROR), at least some OSes clear the
	 * writable state from the socket, and so a subsequent select() on
	 * behalf of a script level [fileevent] would not fire. It doesn't
	 * hurt that this is also called in the successful case and will save
	 * the event mechanism one roundtrip through select().
	 */

	if (statePtr->cachedBlocking == TCL_MODE_NONBLOCKING) {
	    Tcl_NotifyChannel(statePtr->channel, TCL_WRITABLE);
	}
    }
    if (error != 0) {
        /*
         * Failure for either a synchronous connection, or an async one that
         * failed before it could enter background mode, e.g. because an
         * invalid -myaddr was given.
         */
	/*
	 * Failure for either a synchronous connection, or an async one that
	 * failed before it could enter background mode, e.g. because an
	 * invalid -myaddr was given.
	 */

        if (interp != NULL) {
            errno = error;
            Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "couldn't open socket: %s", Tcl_PosixError(interp)));
        }
        return TCL_ERROR;
	if (interp != NULL) {
	    errno = error;
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "couldn't open socket: %s", Tcl_PosixError(interp)));
	}
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427










1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448


1449
1450
1451

1452
1453
1454

1455
1456
1457
1458
1459
1460
1461
1506
1507
1508
1509
1510
1511
1512










1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541


1542
1543
1544
1545

1546
1547
1548

1549
1550
1551
1552
1553
1554
1555
1556







-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+



















-
-
+
+


-
+


-
+







    char channelName[SOCK_CHAN_LENGTH];

    /*
     * Do the name lookups for the local and remote addresses.
     */

    if (!TclCreateSocketAddress(interp, &addrlist, host, port, 0, &errorMsg)
            || !TclCreateSocketAddress(interp, &myaddrlist, myaddr, myport, 1,
                    &errorMsg)) {
        if (addrlist != NULL) {
            freeaddrinfo(addrlist);
        }
        if (interp != NULL) {
            Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "couldn't open socket: %s", errorMsg));
        }
        return NULL;
	    || !TclCreateSocketAddress(interp, &myaddrlist, myaddr, myport, 1,
		    &errorMsg)) {
	if (addrlist != NULL) {
	    freeaddrinfo(addrlist);
	}
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "couldn't open socket: %s", errorMsg));
	}
	return NULL;
    }

    /*
     * Allocate a new TcpState for this socket.
     */

    statePtr = (TcpState *)Tcl_Alloc(sizeof(TcpState));
    memset(statePtr, 0, sizeof(TcpState));
    statePtr->flags = async ? TCP_ASYNC_CONNECT : 0;
    statePtr->cachedBlocking = TCL_MODE_BLOCKING;
    statePtr->addrlist = addrlist;
    statePtr->myaddrlist = myaddrlist;
    statePtr->fds.fd = -1;

    /*
     * Create a new client socket and wrap it in a channel.
     */

    if (TcpConnect(interp, statePtr) != TCL_OK) {
        TcpCloseProc(statePtr, NULL);
        return NULL;
	TcpCloseProc(statePtr, NULL);
	return NULL;
    }

    sprintf(channelName, SOCK_TEMPLATE, (long) statePtr);
    snprintf(channelName, sizeof(channelName), SOCK_TEMPLATE, PTR2INT(statePtr));

    statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
            statePtr, TCL_READABLE | TCL_WRITABLE);
	    statePtr, TCL_READABLE | TCL_WRITABLE);
    if (Tcl_SetChannelOption(interp, statePtr->channel, "-translation",
	    "auto crlf") == TCL_ERROR) {
	Tcl_CloseEx(NULL, statePtr->channel, 0);
	return NULL;
    }
    return statePtr->channel;
}
1477
1478
1479
1480
1481
1482
1483
1484

1485
1486
1487
1488
1489
1490
1491
1572
1573
1574
1575
1576
1577
1578

1579
1580
1581
1582
1583
1584
1585
1586







-
+







 */

Tcl_Channel
Tcl_MakeTcpClientChannel(
    void *sock)		/* The socket to wrap up into a channel. */
{
    return (Tcl_Channel) TclpMakeTcpClientChannelMode(sock,
            TCL_READABLE | TCL_WRITABLE);
	    TCL_READABLE | TCL_WRITABLE);
}

/*
 *----------------------------------------------------------------------
 *
 * TclpMakeTcpClientChannelMode --
 *
1500
1501
1502
1503
1504
1505
1506
1507

1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518

1519
1520
1521
1522
1523
1524
1525
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







-
+










-
+







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

void *
TclpMakeTcpClientChannelMode(
    void *sock,		/* The socket to wrap up into a channel. */
    int mode)			/* ORed combination of TCL_READABLE and
    int mode)			/* OR'ed combination of TCL_READABLE and
				 * TCL_WRITABLE to indicate file mode. */
{
    TcpState *statePtr;
    char channelName[SOCK_CHAN_LENGTH];

    statePtr = (TcpState *)Tcl_Alloc(sizeof(TcpState));
    memset(statePtr, 0, sizeof(TcpState));
    statePtr->fds.fd = PTR2INT(sock);
    statePtr->flags = 0;

    sprintf(channelName, SOCK_TEMPLATE, (long)statePtr);
    snprintf(channelName, sizeof(channelName), SOCK_TEMPLATE, PTR2INT(statePtr));

    statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    statePtr, mode);
    if (Tcl_SetChannelOption(NULL, statePtr->channel, "-translation",
	    "auto crlf") == TCL_ERROR) {
	Tcl_CloseEx(NULL, statePtr->channel, 0);
	return NULL;
1546
1547
1548
1549
1550
1551
1552

1553
1554
1555
1556
1557
1558
1559
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655







+








Tcl_Channel
Tcl_OpenTcpServerEx(
    Tcl_Interp *interp,		/* For error reporting - may be NULL. */
    const char *service,	/* Port number to open. */
    const char *myHost,		/* Name of local host. */
    unsigned int flags,		/* Flags. */
    int backlog,                /* Length of OS listen backlog queue. */
    Tcl_TcpAcceptProc *acceptProc,
				/* Callback for accepting connections from new
				 * clients. */
    void *acceptProcData)	/* Data for the callback. */
{
    int status = 0, sock = -1, optvalue, port, chosenport;
    struct addrinfo *addrlist = NULL, *addrPtr;	/* socket address */
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
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







-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+










-
+






-
+







     */

    int retry = 0;
#define MAXRETRY 10

 repeat:
    if (retry > 0) {
        if (statePtr != NULL) {
            TcpCloseProc(statePtr, NULL);
            statePtr = NULL;
        }
        if (addrlist != NULL) {
            freeaddrinfo(addrlist);
            addrlist = NULL;
        }
        if (retry >= MAXRETRY) {
            goto error;
        }
	if (statePtr != NULL) {
	    TcpCloseProc(statePtr, NULL);
	    statePtr = NULL;
	}
	if (addrlist != NULL) {
	    freeaddrinfo(addrlist);
	    addrlist = NULL;
	}
	if (retry >= MAXRETRY) {
	    goto error;
	}
    }
    retry++;
    chosenport = 0;

    if (TclSockGetPort(interp, service, "tcp", &port) != TCL_OK) {
	errorMsg = "invalid port number";
	goto error;
    }

    if (!TclCreateSocketAddress(interp, &addrlist, myHost, port, 1,
            &errorMsg)) {
	    &errorMsg)) {
	my_errno = errno;
	goto error;
    }

    for (addrPtr = addrlist; addrPtr != NULL; addrPtr = addrPtr->ai_next) {
	sock = socket(addrPtr->ai_family, addrPtr->ai_socktype,
                addrPtr->ai_protocol);
		addrPtr->ai_protocol);
	if (sock == -1) {
	    if (howfar < SOCKET) {
		howfar = SOCKET;
		my_errno = errno;
	    }
	    continue;
	}
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
1749














1750
1751
1752
1753
1754




1755
1756

1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769

1770
1771
1772
1773
1774
1775




1776
1777

1778
1779
1780
1781
1782
1783
1784
1755
1756
1757
1758
1759
1760
1761







1762
1763
1764
1765
1766
1767
1768
1769
1770
1771

1772
1773
1774
1775
1776


1777
1778
1779


1780
1781
1782



1783
1784
1785
1786
1787
1788

1789
1790
1791
1792
1793










1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804




1805
1806
1807
1808
1809






1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822











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














1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849




1850
1851
1852
1853
1854

1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867

1868
1869
1870




1871
1872
1873
1874
1875

1876
1877
1878
1879
1880
1881
1882
1883







-
-
-
-
-
-
-
+
+
+
+
+
+
+



-
+




-
-
+
+

-
-
+
+

-
-
-
+
+
+



-
+




-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+
+
+




-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
+












-
+


-
-
-
-
+
+
+
+

-
+







#else
	    optvalue = 1;
	    (void) setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
		    (char *) &optvalue, sizeof(optvalue));
#endif
	}

        /*
         * Make sure we use the same port number when opening two server
         * sockets for IPv4 and IPv6 on a random port.
         *
         * As sockaddr_in6 uses the same offset and size for the port member
         * as sockaddr_in, we can handle both through the IPv4 API.
         */
	/*
	 * Make sure we use the same port number when opening two server
	 * sockets for IPv4 and IPv6 on a random port.
	 *
	 * As sockaddr_in6 uses the same offset and size for the port member
	 * as sockaddr_in, we can handle both through the IPv4 API.
	 */

	if (port == 0 && chosenport != 0) {
	    ((struct sockaddr_in *) addrPtr->ai_addr)->sin_port =
                    htons(chosenport);
		    htons(chosenport);
	}

#ifdef IPV6_V6ONLY
	/*
         * Missing on: Solaris 2.8
         */
	 * Missing on: Solaris 2.8
	 */

        if (addrPtr->ai_family == AF_INET6) {
            int v6only = 1;
	if (addrPtr->ai_family == AF_INET6) {
	    int v6only = 1;

            (void) setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
                    &v6only, sizeof(v6only));
        }
	    (void) setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
		    &v6only, sizeof(v6only));
	}
#endif /* IPV6_V6ONLY */

	status = bind(sock, addrPtr->ai_addr, addrPtr->ai_addrlen);
        if (status == -1) {
	if (status == -1) {
	    if (howfar < BIND) {
		howfar = BIND;
		my_errno = errno;
	    }
            close(sock);
            sock = -1;
            if (port == 0 && errno == EADDRINUSE) {
                goto repeat;
            }
            continue;
        }
        if (port == 0 && chosenport == 0) {
            address sockname;
            socklen_t namelen = sizeof(sockname);
	    close(sock);
	    sock = -1;
	    if (port == 0 && errno == EADDRINUSE) {
		goto repeat;
	    }
	    continue;
	}
	if (port == 0 && chosenport == 0) {
	    address sockname;
	    socklen_t namelen = sizeof(sockname);

            /*
             * Synchronize port numbers when binding to port 0 of multiple
             * addresses.
             */
	    /*
	     * Synchronize port numbers when binding to port 0 of multiple
	     * addresses.
	     */

            if (getsockname(sock, &sockname.sa, &namelen) >= 0) {
                chosenport = ntohs(sockname.sa4.sin_port);
            }
        }
        status = listen(sock, SOMAXCONN);
        if (status < 0) {
	    if (getsockname(sock, &sockname.sa, &namelen) >= 0) {
		chosenport = ntohs(sockname.sa4.sin_port);
	    }
	}
	if (backlog < 0) {
	    backlog = SOMAXCONN;
	}
	status = listen(sock, backlog);
	if (status < 0) {
	    if (howfar < LISTEN) {
		howfar = LISTEN;
		my_errno = errno;
	    }
            close(sock);
            sock = -1;
            if (port == 0 && errno == EADDRINUSE) {
                goto repeat;
            }
            continue;
        }
        if (statePtr == NULL) {
            /*
             * Allocate a new TcpState for this socket.
             */
	    close(sock);
	    sock = -1;
	    if (port == 0 && errno == EADDRINUSE) {
		goto repeat;
	    }
	    continue;
	}
	if (statePtr == NULL) {
	    /*
	     * Allocate a new TcpState for this socket.
	     */

            statePtr = (TcpState *)Tcl_Alloc(sizeof(TcpState));
            memset(statePtr, 0, sizeof(TcpState));
            statePtr->acceptProc = acceptProc;
            statePtr->acceptProcData = acceptProcData;
            sprintf(channelName, SOCK_TEMPLATE, (long) statePtr);
            newfds = &statePtr->fds;
        } else {
            newfds = (TcpFdList *)Tcl_Alloc(sizeof(TcpFdList));
            memset(newfds, (int) 0, sizeof(TcpFdList));
            fds->next = newfds;
        }
        newfds->fd = sock;
        newfds->statePtr = statePtr;
        fds = newfds;
	    statePtr = (TcpState *)Tcl_Alloc(sizeof(TcpState));
	    memset(statePtr, 0, sizeof(TcpState));
	    statePtr->acceptProc = acceptProc;
	    statePtr->acceptProcData = acceptProcData;
	    snprintf(channelName, sizeof(channelName), SOCK_TEMPLATE, PTR2INT(statePtr));
	    newfds = &statePtr->fds;
	} else {
	    newfds = (TcpFdList *)Tcl_Alloc(sizeof(TcpFdList));
	    memset(newfds, (int) 0, sizeof(TcpFdList));
	    fds->next = newfds;
	}
	newfds->fd = sock;
	newfds->statePtr = statePtr;
	fds = newfds;

        /*
         * Set up the callback mechanism for accepting connections from new
         * clients.
         */
	/*
	 * Set up the callback mechanism for accepting connections from new
	 * clients.
	 */

        Tcl_CreateFileHandler(sock, TCL_READABLE, TcpAccept, fds);
	Tcl_CreateFileHandler(sock, TCL_READABLE, TcpAccept, fds);
    }

  error:
    if (addrlist != NULL) {
	freeaddrinfo(addrlist);
    }
    if (statePtr != NULL) {
	statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
		statePtr, 0);
	return statePtr->channel;
    }
    if (interp != NULL) {
        Tcl_Obj *errorObj = Tcl_NewStringObj("couldn't open socket: ", -1);
	Tcl_Obj *errorObj = Tcl_NewStringObj("couldn't open socket: ", TCL_INDEX_NONE);

	if (errorMsg == NULL) {
            errno = my_errno;
            Tcl_AppendToObj(errorObj, Tcl_PosixError(interp), -1);
        } else {
	    Tcl_AppendToObj(errorObj, errorMsg, -1);
	    errno = my_errno;
	    Tcl_AppendToObj(errorObj, Tcl_PosixError(interp), TCL_INDEX_NONE);
	} else {
	    Tcl_AppendToObj(errorObj, errorMsg, TCL_INDEX_NONE);
	}
        Tcl_SetObjResult(interp, errorObj);
	Tcl_SetObjResult(interp, errorObj);
    }
    if (sock != -1) {
	close(sock);
    }
    return NULL;
}

1825
1826
1827
1828
1829
1830
1831
1832

1833
1834
1835
1836
1837
1838
1839
1840
1841

1842
1843

1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
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







-
+








-
+

-
+












    (void) fcntl(newsock, F_SETFD, FD_CLOEXEC);

    newSockState = (TcpState *)Tcl_Alloc(sizeof(TcpState));
    memset(newSockState, 0, sizeof(TcpState));
    newSockState->flags = 0;
    newSockState->fds.fd = newsock;

    sprintf(channelName, SOCK_TEMPLATE, (long) newSockState);
    snprintf(channelName, sizeof(channelName), SOCK_TEMPLATE, PTR2INT(newSockState));
    newSockState->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    newSockState, TCL_READABLE | TCL_WRITABLE);

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

    if (fds->statePtr->acceptProc != NULL) {
	getnameinfo(&addr.sa, len, host, sizeof(host), port, sizeof(port),
                NI_NUMERICHOST|NI_NUMERICSERV);
		NI_NUMERICHOST|NI_NUMERICSERV);
	fds->statePtr->acceptProc(fds->statePtr->acceptProcData,
                newSockState->channel, host, atoi(port));
		newSockState->channel, host, atoi(port));
    }
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * tab-width: 8
 * indent-tabs-mode: nil
 * End:
 */

Changes to unix/tclUnixTest.c.

1
2
3
4
5
6
7


8
9
10
11
12


13
14
15
16
17
18
19
1
2
3
4
5


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21





-
-
+
+





+
+







/*
 * tclUnixTest.c --
 *
 *	Contains platform specific test commands for the Unix platform.
 *
 * Copyright (c) 1996-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998 by Scriptics Corporation.
 * Copyright © 1996-1997 Sun Microsystems, Inc.
 * Copyright © 1998 Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#undef BUILD_tcl
#undef STATIC_BUILD
#ifndef USE_TCL_STUBS
#   define USE_TCL_STUBS
#endif
#include "tclInt.h"

/*
 * The headers are needed for the testalarm command that verifies the use of
66
67
68
69
70
71
72
73

74
75
76
77
78
79
80
68
69
70
71
72
73
74

75
76
77
78
79
80
81
82







-
+







static Tcl_ObjCmdProc TestchmodCmd;
static Tcl_ObjCmdProc TestfilehandlerCmd;
static Tcl_ObjCmdProc TestfilewaitCmd;
static Tcl_ObjCmdProc TestfindexecutableCmd;
static Tcl_ObjCmdProc TestforkCmd;
static Tcl_ObjCmdProc TestgotsigCmd;
static Tcl_FileProc TestFileHandlerProc;
static void AlarmHandler(int signum);
static void		AlarmHandler(int signum);

/*
 *----------------------------------------------------------------------
 *
 * TclplatformtestInit --
 *
 *	Defines commands that test platform specific functionality for Unix
98
99
100
101
102
103
104
105

106
107
108
109
110
111
112
100
101
102
103
104
105
106

107
108
109
110
111
112
113
114







-
+







    Tcl_CreateObjCommand(interp, "testfilehandler", TestfilehandlerCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testfilewait", TestfilewaitCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testfindexecutable", TestfindexecutableCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testfork", TestforkCmd,
        NULL, NULL);
	NULL, NULL);
    Tcl_CreateObjCommand(interp, "testalarm", TestalarmCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testgotsig", TestgotsigCmd,
	    NULL, NULL);
    return TCL_OK;
}

125
126
127
128
129
130
131
132

133
134
135
136
137
138
139
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestfilehandlerCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Argument strings. */
{
    Pipe *pipePtr;
    int i, mask, timeout;
    static int initialized = 0;
150
151
152
153
154
155
156
157

158
159
160
161
162
163
164
165

166
167
168
169
170
171
172
152
153
154
155
156
157
158

159
160
161
162
163
164
165
166

167
168
169
170
171
172
173
174







-
+







-
+







	    testPipes[i].readFile = NULL;
	}
	initialized = 1;
    }

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ...");
        return TCL_ERROR;
	return TCL_ERROR;
    }
    pipePtr = NULL;
    if (objc >= 3) {
	if (Tcl_GetIntFromObj(interp, objv[2], &i) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (i >= MAX_PIPES) {
	    Tcl_AppendResult(interp, "bad index ", objv[2], NULL);
	    Tcl_AppendResult(interp, "bad index ", objv[2], (char *)NULL);
	    return TCL_ERROR;
	}
	pipePtr = &testPipes[i];
    }

    if (strcmp(Tcl_GetString(objv[1]), "close") == 0) {
	for (i = 0; i < MAX_PIPES; i++) {
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
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







-
-
+
+








-
+






-
-
+
+















-
+











-
+








-
+

-
+




















-
+








-
+







    } else if (strcmp(Tcl_GetString(objv[1]), "counts") == 0) {
	char buf[TCL_INTEGER_SPACE * 2];

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index");
	    return TCL_ERROR;
	}
	sprintf(buf, "%d %d", pipePtr->readCount, pipePtr->writeCount);
	Tcl_AppendResult(interp, buf, NULL);
	snprintf(buf, sizeof(buf), "%d %d", pipePtr->readCount, pipePtr->writeCount);
	Tcl_AppendResult(interp, buf, (char *)NULL);
    } else if (strcmp(Tcl_GetString(objv[1]), "create") == 0) {
	if (objc != 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index readMode writeMode");
	    return TCL_ERROR;
	}
	if (pipePtr->readFile == NULL) {
	    if (!TclpCreatePipe(&pipePtr->readFile, &pipePtr->writeFile)) {
		Tcl_AppendResult(interp, "couldn't open pipe: ",
			Tcl_PosixError(interp), NULL);
			Tcl_PosixError(interp), (char *)NULL);
		return TCL_ERROR;
	    }
#ifdef O_NONBLOCK
	    fcntl(GetFd(pipePtr->readFile), F_SETFL, O_NONBLOCK);
	    fcntl(GetFd(pipePtr->writeFile), F_SETFL, O_NONBLOCK);
#else
	    Tcl_AppendResult(interp, "can't make pipes non-blocking",
		    NULL);
	    Tcl_AppendResult(interp, "cannot make pipes non-blocking",
		    (char *)NULL);
	    return TCL_ERROR;
#endif
	}
	pipePtr->readCount = 0;
	pipePtr->writeCount = 0;

	if (strcmp(Tcl_GetString(objv[3]), "readable") == 0) {
	    Tcl_CreateFileHandler(GetFd(pipePtr->readFile), TCL_READABLE,
		    TestFileHandlerProc, pipePtr);
	} else if (strcmp(Tcl_GetString(objv[3]), "off") == 0) {
	    Tcl_DeleteFileHandler(GetFd(pipePtr->readFile));
	} else if (strcmp(Tcl_GetString(objv[3]), "disabled") == 0) {
	    Tcl_CreateFileHandler(GetFd(pipePtr->readFile), 0,
		    TestFileHandlerProc, pipePtr);
	} else {
	    Tcl_AppendResult(interp, "bad read mode \"", Tcl_GetString(objv[3]), "\"", NULL);
	    Tcl_AppendResult(interp, "bad read mode \"", Tcl_GetString(objv[3]), "\"", (char *)NULL);
	    return TCL_ERROR;
	}
	if (strcmp(Tcl_GetString(objv[4]), "writable") == 0) {
	    Tcl_CreateFileHandler(GetFd(pipePtr->writeFile), TCL_WRITABLE,
		    TestFileHandlerProc, pipePtr);
	} else if (strcmp(Tcl_GetString(objv[4]), "off") == 0) {
	    Tcl_DeleteFileHandler(GetFd(pipePtr->writeFile));
	} else if (strcmp(Tcl_GetString(objv[4]), "disabled") == 0) {
	    Tcl_CreateFileHandler(GetFd(pipePtr->writeFile), 0,
		    TestFileHandlerProc, pipePtr);
	} else {
	    Tcl_AppendResult(interp, "bad read mode \"", Tcl_GetString(objv[4]), "\"", NULL);
	    Tcl_AppendResult(interp, "bad read mode \"", Tcl_GetString(objv[4]), "\"", (char *)NULL);
	    return TCL_ERROR;
	}
    } else if (strcmp(Tcl_GetString(objv[1]), "empty") == 0) {
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index");
	    return TCL_ERROR;
	}

        while (read(GetFd(pipePtr->readFile), buffer, 4000) > 0) {
	while (read(GetFd(pipePtr->readFile), buffer, 4000) > 0) {
	    /* Empty loop body. */
        }
	}
    } else if (strcmp(Tcl_GetString(objv[1]), "fill") == 0) {
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index");
	    return TCL_ERROR;
	}

	memset(buffer, 'a', 4000);
	while (write(GetFd(pipePtr->writeFile), buffer, 4000) > 0) {
	    /* Empty loop body. */
	}
    } else if (strcmp(Tcl_GetString(objv[1]), "fillpartial") == 0) {
	char buf[TCL_INTEGER_SPACE];

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

	memset(buffer, 'b', 10);
	TclFormatInt(buf, write(GetFd(pipePtr->writeFile), buffer, 10));
	Tcl_AppendResult(interp, buf, NULL);
	Tcl_AppendResult(interp, buf, (char *)NULL);
    } else if (strcmp(Tcl_GetString(objv[1]), "oneevent") == 0) {
	Tcl_DoOneEvent(TCL_FILE_EVENTS|TCL_DONT_WAIT);
    } else if (strcmp(Tcl_GetString(objv[1]), "wait") == 0) {
	if (objc != 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index readable|writable timeout");
	    return TCL_ERROR;
	}
	if (pipePtr->readFile == NULL) {
	    Tcl_AppendResult(interp, "pipe ", Tcl_GetString(objv[2]), " doesn't exist", NULL);
	    Tcl_AppendResult(interp, "pipe ", Tcl_GetString(objv[2]), " doesn't exist", (char *)NULL);
	    return TCL_ERROR;
	}
	if (strcmp(Tcl_GetString(objv[3]), "readable") == 0) {
	    mask = TCL_READABLE;
	    file = pipePtr->readFile;
	} else {
	    mask = TCL_WRITABLE;
298
299
300
301
302
303
304
305

306
307
308
309
310
311
312
313

314
315
316
317
318
319
320
300
301
302
303
304
305
306

307
308
309
310
311
312
313
314

315
316
317
318
319
320
321
322







-
+







-
+







	    Tcl_AppendElement(interp, "writable");
	}
    } else if (strcmp(Tcl_GetString(objv[1]), "windowevent") == 0) {
	Tcl_DoOneEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT);
    } else {
	Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
		"\": must be close, clear, counts, create, empty, fill, "
		"fillpartial, oneevent, wait, or windowevent", NULL);
		"fillpartial, oneevent, wait, or windowevent", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

static void
TestFileHandlerProc(
    ClientData clientData,	/* Points to a Pipe structure. */
    void *clientData,	/* Points to a Pipe structure. */
    int mask)			/* Indicates which events happened:
				 * TCL_READABLE or TCL_WRITABLE. */
{
    Pipe *pipePtr = (Pipe *)clientData;

    if (mask & TCL_READABLE) {
	pipePtr->readCount++;
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
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







-
+







-
+

















-
+




-
-
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestfilewaitCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Argument strings. */
{
    int mask, result, timeout;
    Tcl_Channel channel;
    int fd;
    ClientData data;
    void *data;

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 2, objv, "file readable|writable|both timeout");
	return TCL_ERROR;
    }
    channel = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), NULL);
    if (channel == NULL) {
	return TCL_ERROR;
    }
    if (strcmp(Tcl_GetString(objv[2]), "readable") == 0) {
	mask = TCL_READABLE;
    } else if (strcmp(Tcl_GetString(objv[2]), "writable") == 0){
	mask = TCL_WRITABLE;
    } else if (strcmp(Tcl_GetString(objv[2]), "both") == 0){
	mask = TCL_WRITABLE|TCL_READABLE;
    } else {
	Tcl_AppendResult(interp, "bad argument \"", Tcl_GetString(objv[2]),
		"\": must be readable, writable, or both", NULL);
		"\": must be readable, writable, or both", (char *)NULL);
	return TCL_ERROR;
    }
    if (Tcl_GetChannelHandle(channel,
	    (mask & TCL_READABLE) ? TCL_READABLE : TCL_WRITABLE,
	    (ClientData*) &data) != TCL_OK) {
	Tcl_AppendResult(interp, "couldn't get channel file", NULL);
	    (void **) &data) != TCL_OK) {
	Tcl_AppendResult(interp, "couldn't get channel file", (char *)NULL);
	return TCL_ERROR;
    }
    fd = PTR2INT(data);
    if (Tcl_GetIntFromObj(interp, objv[3], &timeout) != TCL_OK) {
	return TCL_ERROR;
    }
    result = TclUnixWaitForFile(fd, mask, timeout);
407
408
409
410
411
412
413
414

415
416
417
418
419
420
421
409
410
411
412
413
414
415

416
417
418
419
420
421
422
423







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestfindexecutableCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Argument strings. */
{
    Tcl_Obj *saveName;

    if (objc != 2) {
449
450
451
452
453
454
455
456

457
458
459
460
461
462
463
464
465


466
467
468
469
470
471



472
473
474
475
476
477
478
451
452
453
454
455
456
457

458
459
460
461
462
463
464
465


466
467
468
469
470



471
472
473
474
475
476
477
478
479
480







-
+







-
-
+
+



-
-
-
+
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestforkCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Argument strings. */
{
    pid_t pid;

    if (objc != 1) {
        Tcl_WrongNumArgs(interp, 1, objv, "");
        return TCL_ERROR;
	Tcl_WrongNumArgs(interp, 1, objv, "");
	return TCL_ERROR;
    }
    pid = fork();
    if (pid == -1) {
        Tcl_AppendResult(interp,
                "Cannot fork", NULL);
        return TCL_ERROR;
	Tcl_AppendResult(interp,
		"Cannot fork", (char *)NULL);
	return TCL_ERROR;
    }
    /* Only needed when pthread_atfork is not present,
     * should not hurt otherwise. */
    if (pid==0) {
	Tcl_InitNotifier();
    }
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(pid));
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
558
559
560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
575
576
577
578
579
580

581
582
583
584
585

586
587
588
589
590
591
592
593
594
595
596
597

598
599
600
601
602
603
604
605
606
607
608
609
610
611

612
613
614
615
616
617
618
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
558
559
560
561
562
563
564
565
566
567
568

569
570
571
572
573
574
575
576
577
578
579
580
581

582
583
584
585
586

587
588
589
590
591
592
593
594
595
596
597
598

599
600
601
602
603
604
605
606
607
608
609
610
611
612

613
614
615
616
617
618
619
620







-
+


















-
+



-
+








-
+















-
+
















-
+












-
+




-
+











-
+













-
+







 *	Sets up an signal and async handlers.
 *
 *----------------------------------------------------------------------
 */

static int
TestalarmCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Argument strings. */
{
#ifdef SA_RESTART
    unsigned int sec = 1;
    struct sigaction action;

    if (objc > 1) {
	Tcl_GetIntFromObj(interp, objv[1], (int *)&sec);
    }

    /*
     * Setup the signal handling that automatically retries any interrupted
     * I/O system calls.
     */

    action.sa_handler = AlarmHandler;
    memset((void *) &action.sa_mask, 0, sizeof(sigset_t));
    memset((void *)&action.sa_mask, 0, sizeof(sigset_t));
    action.sa_flags = SA_RESTART;

    if (sigaction(SIGALRM, &action, NULL) < 0) {
	Tcl_AppendResult(interp, "sigaction: ", Tcl_PosixError(interp), NULL);
	Tcl_AppendResult(interp, "sigaction: ", Tcl_PosixError(interp), (char *)NULL);
	return TCL_ERROR;
    }
    (void) alarm(sec);
    return TCL_OK;
#else

    Tcl_AppendResult(interp,
	    "warning: sigaction SA_RESTART not support on this platform",
	    NULL);
	    (char *)NULL);
    return TCL_ERROR;
#endif
}

/*
 *----------------------------------------------------------------------
 *
 * AlarmHandler --
 *
 *	Signal handler for the alarm command.
 *
 * Results:
 *	None.
 *
 * Side effects:
 * 	Calls the Tcl Async handler.
 *	Calls the Tcl Async handler.
 *
 *----------------------------------------------------------------------
 */

static void
AlarmHandler(
    TCL_UNUSED(int) /*signum*/)
{
    gotsig = "1";
}

/*
 *----------------------------------------------------------------------
 *
 * TestgotsigCmd --
 *
 * 	Verify the signal was handled after the testalarm command.
 *	Verify the signal was handled after the testalarm command.
 *
 * Results:
 *	None.
 *
 * Side Effects:
 *	Resets the value of gotsig back to '0'.
 *
 *----------------------------------------------------------------------
 */

static int
TestgotsigCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*objc*/,
    TCL_UNUSED(Tcl_Obj *const *))
{
    Tcl_AppendResult(interp, gotsig, NULL);
    Tcl_AppendResult(interp, gotsig, (char *)NULL);
    gotsig = "0";
    return TCL_OK;
}

/*
 *---------------------------------------------------------------------------
 *
 * TestchmodCmd --
 *
 *	Implements the "testchmod" cmd.  Used when testing "file" command.
 *	The only attribute used by the Windows platform is the user write
 *	flag; if this is not set, the file is made read-only.  Otehrwise, the
 *	flag; if this is not set, the file is made read-only.  Otherwise, the
 *	file is made read-write.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Changes permissions of specified files.
 *
 *---------------------------------------------------------------------------
 */

static int
TestchmodCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,			/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)		/* Argument strings. */
{
    int i, mode;

    if (objc < 2) {
630
631
632
633
634
635
636
637

638
639
640
641
642
643
644
632
633
634
635
636
637
638

639
640
641
642
643
644
645
646







-
+








	translated = Tcl_TranslateFileName(interp, Tcl_GetString(objv[i]), &buffer);
	if (translated == NULL) {
	    return TCL_ERROR;
	}
	if (chmod(translated, mode) != 0) {
	    Tcl_AppendResult(interp, translated, ": ", Tcl_PosixError(interp),
		    NULL);
		    (char *)NULL);
	    return TCL_ERROR;
	}
	Tcl_DStringFree(&buffer);
    }
    return TCL_OK;
}


Changes to unix/tclUnixThrd.c.

1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15





-
-
-
+
+
+







/*
 * tclUnixThrd.c --
 *
 *	This file implements the UNIX-specific thread support.
 *
 * Copyright (c) 1991-1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 2008 by George Peter Staplin
 * Copyright © 1991-1994 The Regents of the University of California.
 * Copyright © 1994-1997 Sun Microsystems, Inc.
 * Copyright © 2008 George Peter Staplin
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

209
210
211
212
213
214
215
216
217


218
219
220
221
222
223
224
209
210
211
212
213
214
215


216
217
218
219
220
221
222
223
224







-
-
+
+







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

int
TclpThreadCreate(
    Tcl_ThreadId *idPtr,	/* Return, the ID of the thread */
    Tcl_ThreadCreateProc *proc,	/* Main() function of the thread */
    ClientData clientData,	/* The one argument to Main() */
    size_t stackSize,		/* Size of stack for the new thread */
    void *clientData,	/* The one argument to Main() */
    size_t stackSize,	/* Size of stack for the new thread */
    int flags)			/* Flags controlling behaviour of the new
				 * thread. */
{
#if TCL_THREADS
    pthread_attr_t attr;
    pthread_t theThread;
    int result;
243
244
245
246
247
248
249
250

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

250
251
252
253
254
255
256
257







-
+







	 * down, and that would still leave the main thread at the default.
	 */

	size_t size;

	result = pthread_attr_getstacksize(&attr, &size);
	if (!result && (size < TCL_THREAD_STACK_MIN)) {
	    pthread_attr_setstacksize(&attr, (size_t) TCL_THREAD_STACK_MIN);
	    pthread_attr_setstacksize(&attr, (size_t)TCL_THREAD_STACK_MIN);
	}
#endif /* TCL_THREAD_STACK_MIN */
    }
#endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */

    if (!(flags & TCL_THREAD_JOINABLE)) {
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
265
266
267
268
269
270
271





272
273
274
275
276
277
278
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283







+
+
+
+
+







    } else {
	*idPtr = (Tcl_ThreadId)theThread;
	result = TCL_OK;
    }
    pthread_attr_destroy(&attr);
    return result;
#else
    (void)idPtr;
    (void)proc;
    (void)clientData;
    (void)stackSize;
    (void)flags;
    return TCL_ERROR;
#endif /* TCL_THREADS */
}

/*
 *----------------------------------------------------------------------
 *
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
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







+
+
+




















-
+








    result = pthread_join((pthread_t) threadId, (void**) retcodePtr);
    if (state) {
	*state = (int) retcode;
    }
    return (result == 0) ? TCL_OK : TCL_ERROR;
#else
    (void)threadId;
    (void)state;

    return TCL_ERROR;
#endif
}

/*
 *----------------------------------------------------------------------
 *
 * TclpThreadExit --
 *
 *	This procedure terminates the current thread.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	This procedure terminates the current thread.
 *
 *----------------------------------------------------------------------
 */

void
TCL_NORETURN void
TclpThreadExit(
    int status)
{
#if TCL_THREADS
    pthread_exit(INT2PTR(status));
#else /* TCL_THREADS */
    exit(status);

Changes to unix/tclUnixTime.c.

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
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
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
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






-
+















-
+

-
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-
+


-
+



















-
+




-
-
+
+








-
+












-
+


-
+


-
+


-
-
+
+
+






-
+

-
+


-
-
-
+
+
+
+







/*
 * tclUnixTime.c --
 *
 *	Contains Unix specific versions of Tcl functions that obtain time
 *	values from the operating system.
 *
 * Copyright (c) 1995 Sun Microsystems, Inc.
 * Copyright © 1995 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#if defined(TCL_WIDE_CLICKS) && defined(MAC_OSX_TCL)
#include <mach/mach_time.h>
#endif

/*
 * Static functions declared in this file.
 */

static void		NativeScaleTime(Tcl_Time *timebuf,
			    ClientData clientData);
			    void *clientData);
static void		NativeGetTime(Tcl_Time *timebuf,
			    ClientData clientData);
			    void *clientData);

/*
 * TIP #233 (Virtualized Time): Data for the time hooks, if any.
 */

Tcl_GetTimeProc *tclGetTimeProcPtr = NativeGetTime;
Tcl_ScaleTimeProc *tclScaleTimeProcPtr = NativeScaleTime;
void *tclTimeClientData = NULL;

/*
 * Inlined version of Tcl_GetTime.
 */

static inline void
GetTime(
    Tcl_Time *timePtr)
{
    tclGetTimeProcPtr(timePtr, tclTimeClientData);
}

static inline int
IsTimeNative(void)
{
    return tclGetTimeProcPtr == NativeGetTime;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpGetSeconds --
 *
 *	This procedure returns the number of seconds from the epoch. On most
 *	Unix systems the epoch is Midnight Jan 1, 1970 GMT.
 *
 * Results:
 *	Number of seconds from the epoch.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_WideUInt
unsigned long long
TclpGetSeconds(void)
{
    return time(NULL);
    return (unsigned long long) time(NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * TclpGetMicroseconds --
 *
 *	This procedure returns the number of microseconds from the epoch.
 *	On most Unix systems the epoch is Midnight Jan 1, 1970 GMT.
 *
 * Results:
 *	Number of microseconds from the epoch.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_WideInt
long long
TclpGetMicroseconds(void)
{
    Tcl_Time time;

    tclGetTimeProcPtr(&time, tclTimeClientData);
    return ((Tcl_WideInt)time.sec)*1000000 + time.usec;
    GetTime(&time);
    return time.sec * 1000000 + time.usec;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpGetClicks --
 *
 *	This procedure returns a value that represents the highest resolution
 *	clock available on the system. There are no garantees on what the
 *	clock available on the system. There are no guarantees on what the
 *	resolution will be. In Tcl we will call this value a "click". The
 *	start time is also system dependent.
 *
 * Results:
 *	Number of clicks from some start time.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_WideUInt
unsigned long long
TclpGetClicks(void)
{
	Tcl_WideUInt now;
    unsigned long long now;

#ifdef NO_GETTOD
    if (tclGetTimeProcPtr != NativeGetTime) {
    if (!IsTimeNative()) {
	Tcl_Time time;

	tclGetTimeProcPtr(&time, tclTimeClientData);
	now = (Tcl_WideUInt)time.sec*1000000 + time.usec;
	GetTime(&time);
	now = ((unsigned long long)(time.sec)*1000000ULL) +
		(unsigned long long)(time.usec);
    } else {
	/*
	 * A semi-NativeGetTime, specialized to clicks.
	 */
	struct tms dummy;

	now = (Tcl_WideUInt) times(&dummy);
	now = (unsigned long long) times(&dummy);
    }
#else
#else /* !NO_GETTOD */
    Tcl_Time time;

    tclGetTimeProcPtr(&time, tclTimeClientData);
    now = (Tcl_WideUInt)time.sec*1000000 + time.usec;
#endif
    GetTime(&time);
    now = ((unsigned long long)(time.sec)*1000000ULL) +
	    (unsigned long long)(time.usec);
#endif /* NO_GETTOD */

    return now;
}
#ifdef TCL_WIDE_CLICKS

/*
 *----------------------------------------------------------------------
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
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







-
+


-
+

-
+


-
-
+
+


-
+


-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_WideInt
long long
TclpGetWideClicks(void)
{
    Tcl_WideInt now;
    long long now;

    if (tclGetTimeProcPtr != NativeGetTime) {
    if (!IsTimeNative()) {
	Tcl_Time time;

	tclGetTimeProcPtr(&time, tclTimeClientData);
	now = ((Tcl_WideInt)time.sec)*1000000 + time.usec;
	GetTime(&time);
	now = ((long long) time.sec)*1000000 + time.usec;
    } else {
#ifdef MAC_OSX_TCL
	now = (Tcl_WideInt) (mach_absolute_time() & INT64_MAX);
	now = (long long) (mach_absolute_time() & INT64_MAX);
#else
#error Wide high-resolution clicks not implemented on this platform
#endif
#endif /* MAC_OSX_TCL */
    }

    return now;
}

/*
 *----------------------------------------------------------------------
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
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







-
+



-
+

















-
+















-
+










-
+






-
+
-
-




-
+

-

+


-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

double
TclpWideClicksToNanoseconds(
    Tcl_WideInt clicks)
    long long clicks)
{
    double nsec;

    if (tclGetTimeProcPtr != NativeGetTime) {
    if (!IsTimeNative()) {
	nsec = clicks * 1000;
    } else {
#ifdef MAC_OSX_TCL
	static mach_timebase_info_data_t tb;
	static uint64_t maxClicksForUInt64;

	if (!tb.denom) {
	    mach_timebase_info(&tb);
	    maxClicksForUInt64 = UINT64_MAX / tb.numer;
	}
	if ((uint64_t) clicks < maxClicksForUInt64) {
	    nsec = ((uint64_t) clicks) * tb.numer / tb.denom;
	} else {
	    nsec = ((long double) (uint64_t) clicks) * tb.numer / tb.denom;
	}
#else
#error Wide high-resolution clicks not implemented on this platform
#endif
#endif /* MAC_OSX_TCL */
    }

    return nsec;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpWideClickInMicrosec --
 *
 *	This procedure return scale to convert click values from the
 *	TclpGetWideClicks native resolution to microsecond resolution
 *	and back.
 *
 * Results:
 * 	1 click in microseconds as double.
 *	1 click in microseconds as double.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

double
TclpWideClickInMicrosec(void)
{
    if (tclGetTimeProcPtr != NativeGetTime) {
    if (!IsTimeNative()) {
	return 1.0;
    } else {
#ifdef MAC_OSX_TCL
	static int initialized = 0;
	static double scale = 0.0;

	if (initialized) {
	if (!initialized) {
	    return scale;
	} else {
	    mach_timebase_info_data_t tb;

	    mach_timebase_info(&tb);
	    /* value of tb.numer / tb.denom = 1 click in nanoseconds */
	    scale = ((double)tb.numer) / tb.denom / 1000;
	    scale = ((double) tb.numer) / tb.denom / 1000;
	    initialized = 1;
	    return scale;
	}
	return scale;
#else
#error Wide high-resolution clicks not implemented on this platform
#endif
#endif /* MAC_OSX_TCL */
    }
}
#endif /* TCL_WIDE_CLICKS */

/*
 *----------------------------------------------------------------------
 *
283
284
285
286
287
288
289
290

291
292
293
294
295
296
297
300
301
302
303
304
305
306

307
308
309
310
311
312
313
314







-
+







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

void
Tcl_GetTime(
    Tcl_Time *timePtr)		/* Location to store time information. */
{
    tclGetTimeProcPtr(timePtr, tclTimeClientData);
    GetTime(timePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetTimeProc --
 *
307
308
309
310
311
312
313
314

315
316
317
318
319
320
321
324
325
326
327
328
329
330

331
332
333
334
335
336
337
338







-
+







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

void
Tcl_SetTimeProc(
    Tcl_GetTimeProc *getProc,
    Tcl_ScaleTimeProc *scaleProc,
    ClientData clientData)
    void *clientData)
{
    tclGetTimeProcPtr = getProc;
    tclScaleTimeProcPtr = scaleProc;
    tclTimeClientData = clientData;
}

/*
334
335
336
337
338
339
340
341

342
343
344
345
346
347
348
351
352
353
354
355
356
357

358
359
360
361
362
363
364
365







-
+







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

void
Tcl_QueryTimeProc(
    Tcl_GetTimeProc **getProc,
    Tcl_ScaleTimeProc **scaleProc,
    ClientData *clientData)
    void **clientData)
{
    if (getProc) {
	*getProc = tclGetTimeProcPtr;
    }
    if (scaleProc) {
	*scaleProc = tclScaleTimeProcPtr;
    }
367
368
369
370
371
372
373
374

375
376
377
378
379
380
381
384
385
386
387
388
389
390

391
392
393
394
395
396
397
398







-
+







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

static void
NativeScaleTime(
    TCL_UNUSED(Tcl_Time *),
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    /* Native scale is 1:1. Nothing is done */
}

/*
 *----------------------------------------------------------------------
 *
392
393
394
395
396
397
398
399

400
401
402
403
404
405
406
409
410
411
412
413
414
415

416
417
418
419
420
421
422
423







-
+







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

static void
NativeGetTime(
    Tcl_Time *timePtr,
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    struct timeval tv;

    (void) gettimeofday(&tv, NULL);
    timePtr->sec = tv.tv_sec;
    timePtr->usec = tv.tv_usec;
}

Changes to unix/tclXtNotify.c.

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
30
31
32
33
34
35
36

37
38
39
40
41
42
43
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
30
31
32
33
34
35

36
37
38
39
40
41
42
43






-
+












-
+















-
+







/*
 * tclXtNotify.c --
 *
 *	This file contains the notifier driver implementation for the Xt
 *	intrinsics.
 *
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 * Copyright © 1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef USE_TCL_STUBS
#   define USE_TCL_STUBS
#endif
#include <X11/Intrinsic.h>
#include "tclInt.h"

/*
 * This structure is used to keep track of the notifier info for a a
 * This structure is used to keep track of the notifier info for a
 * registered file.
 */

typedef struct FileHandler {
    int fd;
    int mask;			/* Mask of desired events: TCL_READABLE,
				 * etc. */
    int readyMask;		/* Events that have been seen since the last
				 * time FileHandlerEventProc was called for
				 * this file. */
    XtInputId read;		/* Xt read callback handle. */
    XtInputId write;		/* Xt write callback handle. */
    XtInputId except;		/* Xt exception callback handle. */
    Tcl_FileProc *proc;		/* Procedure to call, in the style of
				 * Tcl_CreateFileHandler. */
    ClientData clientData;	/* Argument to pass to proc. */
    void *clientData;	/* Argument to pass to proc. */
    struct FileHandler *nextPtr;/* Next in list of all files we care about. */
} FileHandler;

/*
 * The following structure is what is added to the Tcl event queue when file
 * handlers are ready to fire.
 */
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
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







-
+


-
+








-
+







/*
 * Static routines defined in this file.
 */

static int		FileHandlerEventProc(Tcl_Event *evPtr, int flags);
static void		FileProc(XtPointer clientData, int *source,
			    XtInputId *id);
static void		NotifierExitHandler(ClientData clientData);
static void		NotifierExitHandler(void *clientData);
static void		TimerProc(XtPointer clientData, XtIntervalId *id);
static void		CreateFileHandler(int fd, int mask,
			    Tcl_FileProc *proc, ClientData clientData);
			    Tcl_FileProc *proc, void *clientData);
static void		DeleteFileHandler(int fd);
static void		SetTimer(const Tcl_Time * timePtr);
static int		WaitForEvent(const Tcl_Time * timePtr);

/*
 * Functions defined in this file for use by users of the Xt Notifier:
 */

MODULE_SCOPE void InitNotifier(void);
MODULE_SCOPE void	InitNotifier(void);
MODULE_SCOPE XtAppContext TclSetAppContext(XtAppContext ctx);

/*
 *----------------------------------------------------------------------
 *
 * TclSetAppContext --
 *
128
129
130
131
132
133
134
135

136
137
138
139
140
141
142
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142







-
+







    if (notifier.appContext != NULL) {
	if (appContext != NULL) {
	    /*
	     * We already have a context. We do not allow switching contexts
	     * after initialization, so we panic.
	     */

	    Tcl_Panic("TclSetAppContext:  multiple application contexts");
	    Tcl_Panic("TclSetAppContext: multiple application contexts");
	}
    } else {
	/*
	 * If we get here we have not yet gotten a context, so either create
	 * one or use the one supplied by our caller.
	 */

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
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







-
+
+
+
+
+
+
+











-
-
-
-
-
-
-
-








-







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

void
InitNotifier(void)
{
    Tcl_NotifierProcs np;
    static const Tcl_NotifierProcs np =
	SetTimer,
	WaitForEvent,
	CreateFileHandler,
	DeleteFileHandler,
	NULL, NULL, NULL, NULL
    };

    /*
     * Only reinitialize if we are not in exit handling. The notifier can get
     * reinitialized after its own exit handler has run, because of exit
     * handlers for the I/O and timer sub-systems (order dependency).
     */

    if (TclInExit()) {
	return;
    }

    np.createFileHandlerProc = CreateFileHandler;
    np.deleteFileHandlerProc = DeleteFileHandler;
    np.setTimerProc = SetTimer;
    np.waitForEventProc = WaitForEvent;
    np.initNotifierProc = Tcl_InitNotifier;
    np.finalizeNotifierProc = Tcl_FinalizeNotifier;
    np.alertNotifierProc = Tcl_AlertNotifier;
    np.serviceModeHookProc = Tcl_ServiceModeHook;
    Tcl_SetNotifier(&np);

    /*
     * DO NOT create the application context yet; doing so would prevent
     * external applications from setting it for us to their own ones.
     */

    initialized = 1;
    memset(&np, 0, sizeof(np));
    Tcl_CreateExitHandler(NotifierExitHandler, NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * NotifierExitHandler --
228
229
230
231
232
233
234
235

236
237
238
239
240
241
242
225
226
227
228
229
230
231

232
233
234
235
236
237
238
239







-
+







 *	Destroys the notifier window.
 *
 *----------------------------------------------------------------------
 */

static void
NotifierExitHandler(
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    if (notifier.currentTimeout != 0) {
	XtRemoveTimeOut(notifier.currentTimeout);
    }
    for (; notifier.firstFileHandlerPtr != NULL; ) {
	Tcl_DeleteFileHandler(notifier.firstFileHandlerPtr->fd);
    }
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
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







-
+
















-
+







    int fd,			/* Handle of stream to watch. */
    int mask,			/* OR'ed combination of TCL_READABLE,
				 * TCL_WRITABLE, and TCL_EXCEPTION: indicates
				 * conditions under which proc should be
				 * called. */
    Tcl_FileProc *proc,		/* Procedure to call for each selected
				 * event. */
    ClientData clientData)	/* Arbitrary data to pass to proc. */
    void *clientData)	/* Arbitrary data to pass to proc. */
{
    FileHandler *filePtr;

    if (!initialized) {
	InitNotifier();
    }

    TclSetAppContext(NULL);

    for (filePtr = notifier.firstFileHandlerPtr; filePtr != NULL;
	    filePtr = filePtr->nextPtr) {
	if (filePtr->fd == fd) {
	    break;
	}
    }
    if (filePtr == NULL) {
	filePtr = (FileHandler *)Tcl_Alloc(sizeof(FileHandler));
	filePtr = (FileHandler *) Tcl_Alloc(sizeof(FileHandler));
	filePtr->fd = fd;
	filePtr->read = 0;
	filePtr->write = 0;
	filePtr->except = 0;
	filePtr->readyMask = 0;
	filePtr->mask = 0;
	filePtr->nextPtr = notifier.firstFileHandlerPtr;
492
493
494
495
496
497
498
499

500
501
502
503
504
505
506
489
490
491
492
493
494
495

496
497
498
499
500
501
502
503







-
+








static void
FileProc(
    XtPointer clientData,
    int *fd,
    XtInputId *id)
{
    FileHandler *filePtr = (FileHandler *)clientData;
    FileHandler *filePtr = (FileHandler *) clientData;
    FileHandlerEvent *fileEvPtr;
    int mask = 0;

    /*
     * Determine which event happened.
     */

521
522
523
524
525
526
527
528

529
530
531
532
533
534
535
518
519
520
521
522
523
524

525
526
527
528
529
530
531
532







-
+







    }

    /*
     * This is an interesting event, so put it onto the event queue.
     */

    filePtr->readyMask |= mask;
    fileEvPtr = (FileHandlerEvent *)Tcl_Alloc(sizeof(FileHandlerEvent));
    fileEvPtr = (FileHandlerEvent *) Tcl_Alloc(sizeof(FileHandlerEvent));
    fileEvPtr->header.proc = FileHandlerEventProc;
    fileEvPtr->fd = filePtr->fd;
    Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);

    /*
     * Process events on the Tcl event queue before returning to Xt.
     */

Changes to unix/tclXtTest.c.

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
30
31
32
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
30
31





-
+












-





-
+







/*
 * tclXtTest.c --
 *
 *	Contains commands for Xt notifier specific tests on Unix.
 *
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 * Copyright © 1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifndef USE_TCL_STUBS
#   define USE_TCL_STUBS
#endif
#include <X11/Intrinsic.h>
#include "tcl.h"

static Tcl_ObjCmdProc TesteventloopCmd;
extern DLLEXPORT Tcl_PackageInitProc Tclxttest_Init;

/*
 * Functions defined in tclXtNotify.c for use by users of the Xt Notifier:
 */

extern void	InitNotifier(void);
extern void		InitNotifier(void);
extern XtAppContext	TclSetAppContext(XtAppContext ctx);

/*
 *----------------------------------------------------------------------
 *
 * Tclxttest_Init --
 *
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53







-
+







 *
 * Side effects:
 *	Depends on the startup script.
 *
 *----------------------------------------------------------------------
 */

int
DLLEXPORT int
Tclxttest_Init(
    Tcl_Interp *interp)		/* Interpreter for application. */
{
    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }
    XtToolkitInitialize();
74
75
76
77
78
79
80
81

82
83
84
85
86
87
88
73
74
75
76
77
78
79

80
81
82
83
84
85
86
87







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TesteventloopCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static int *framePtr = NULL;/* Pointer to integer on stack frame of
				 * innermost invocation of the "wait"
				 * subcommand. */
114
115
116
117
118
119
120
121

122
123
124
125
126
127
128
129
130
131
132
133
134
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127
128
129
130
131
132
133







-
+













	while (!done) {
	    XtAppProcessEvent(TclSetAppContext(NULL), XtIMAll);
	}
	(void) Tcl_SetServiceMode(oldMode);
	framePtr = oldFramePtr;
    } else {
	Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
		"\": must be done or wait", NULL);
		"\": must be done or wait", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * tab-width: 8
 * End:
 */

Changes to unix/tclooConfig.sh.

12
13
14
15
16
17
18
19

12
13
14
15
16
17
18

19







-
+
# These are mostly empty because no special steps are ever needed from Tcl 8.6
# onwards; all libraries and include files are just part of Tcl.
TCLOO_LIB_SPEC=""
TCLOO_STUB_LIB_SPEC=""
TCLOO_INCLUDE_SPEC=""
TCLOO_PRIVATE_INCLUDE_SPEC=""
TCLOO_CFLAGS=""
TCLOO_VERSION=1.2.0
TCLOO_VERSION=1.3

Changes to win/Makefile.in.

22
23
24
25
26
27
28



29
30
31
32
33
34
35
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38







+
+
+







bindir			= @bindir@
libdir			= @libdir@
includedir		= @includedir@
datarootdir		= @datarootdir@
runstatedir		= @runstatedir@
mandir			= @mandir@

# Configure arguments
PKG_CFG_ARGS		= @PKG_CFG_ARGS@

# The following definition can be set to non-null for special systems like AFS
# with replication. It allows the pathnames used for installation to be
# different than those used for actually reference files at run-time.
# INSTALL_ROOT is prepended to $prefix and $exec_prefix when installing files.
INSTALL_ROOT	=

# Directory from which applications will reference the library of Tcl scripts
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
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







-
-
-
-
+
+
+
+















+




+















+








-
-
-
-



















+
-
+

-
-
+
+
+




-
-
-
+
+
+


-
+

-
+





-








# The default switches for optimization or debugging
CFLAGS_DEBUG    = @CFLAGS_DEBUG@
CFLAGS_OPTIMIZE	= @CFLAGS_OPTIMIZE@

# To change the compiler switches, for example to change from optimization to
# debugging symbols, change the following line:
#CFLAGS = 		$(CFLAGS_DEBUG)
#CFLAGS = 		$(CFLAGS_OPTIMIZE)
#CFLAGS = 		$(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE)
CFLAGS = 		@CFLAGS@ @CFLAGS_DEFAULT@ -DMP_FIXED_CUTOFFS -D__USE_MINGW_ANSI_STDIO=0 -DMP_NO_STDINT
#CFLAGS =		$(CFLAGS_DEBUG)
#CFLAGS =		$(CFLAGS_OPTIMIZE)
#CFLAGS =		$(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE)
CFLAGS =		@CFLAGS@ @CFLAGS_DEFAULT@ -DMP_FIXED_CUTOFFS -D__USE_MINGW_ANSI_STDIO=0

# To compile without backward compatibility and deprecated code uncomment the
# following
NO_DEPRECATED_FLAGS	=
#NO_DEPRECATED_FLAGS	= -DTCL_NO_DEPRECATED

# To enable compilation debugging reverse the comment characters on one of the
# following lines.
COMPILE_DEBUG_FLAGS =
#COMPILE_DEBUG_FLAGS = -DTCL_COMPILE_DEBUG
#COMPILE_DEBUG_FLAGS = -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS

SRC_DIR			= @srcdir@
ROOT_DIR		= @srcdir@/..
TOP_DIR			= $(shell cd @srcdir@/..; pwd -W 2>/dev/null || pwd -P)
BUILD_DIR		= @builddir@
GENERIC_DIR		= $(TOP_DIR)/generic
WIN_DIR			= $(TOP_DIR)/win
COMPAT_DIR		= $(TOP_DIR)/compat
PKGS_DIR		= $(TOP_DIR)/pkgs
TOOL_DIR		= $(TOP_DIR)/tools
ZLIB_DIR		= $(COMPAT_DIR)/zlib
MINIZIP_DIR		= $(ZLIB_DIR)/contrib/minizip
TOMMATH_DIR		= $(TOP_DIR)/libtommath

# Converts a POSIX path to a Windows native path.
CYGPATH			= @CYGPATH@

libdir_native	= $(shell $(CYGPATH) '$(libdir)')
bindir_native	= $(shell $(CYGPATH) '$(bindir)')
includedir_native = $(shell $(CYGPATH) '$(includedir)')
mandir_native = $(shell $(CYGPATH) '$(mandir)')
TCL_LIBRARY_NATIVE	= $(shell $(CYGPATH) '$(TCL_LIBRARY)')
GENERIC_DIR_NATIVE	= $(shell $(CYGPATH) '$(GENERIC_DIR)')
WIN_DIR_NATIVE		= $(shell $(CYGPATH) '$(WIN_DIR)')
ROOT_DIR_NATIVE		= $(shell $(CYGPATH) '$(ROOT_DIR)')
TOOL_DIR_NATIVE		= $(shell $(CYGPATH) '$(TOOL_DIR)')
SCRIPT_INSTALL_DIR_NATIVE	= $(shell $(CYGPATH) '$(SCRIPT_INSTALL_DIR)')
INCLUDE_INSTALL_DIR_NATIVE	= $(shell $(CYGPATH) '$(INCLUDE_INSTALL_DIR)')
MAN_INSTALL_DIR_NATIVE	= $(shell $(CYGPATH) '$(MAN_INSTALL_DIR)')
ROOT_DIR_WIN_NATIVE	= $(shell cd '$(ROOT_DIR)' ; pwd -W 2>/dev/null || pwd -P)
ZLIB_DIR_NATIVE		= $(shell $(CYGPATH) '$(ZLIB_DIR)')
MINIZIP_DIR_NATIVE	= $(shell $(CYGPATH) '$(MINIZIP_DIR)')
TOMMATH_DIR_NATIVE	= $(shell $(CYGPATH) '$(TOMMATH_DIR)')

# Fully qualify library path so that `make test`
# does not depend on the current directory.
LIBRARY_DIR1		= $(shell cd '$(ROOT_DIR_NATIVE)/library' ; pwd -P)
LIBRARY_DIR             = $(shell $(CYGPATH) '$(LIBRARY_DIR1)')
DLLSUFFIX		= @DLLSUFFIX@
LIBSUFFIX		= @LIBSUFFIX@
EXESUFFIX		= @EXESUFFIX@

VER			= @TCL_MAJOR_VERSION@@TCL_MINOR_VERSION@
DOTVER			= @TCL_MAJOR_VERSION@.@TCL_MINOR_VERSION@
DDEVER			= @TCL_DDE_MAJOR_VERSION@@TCL_DDE_MINOR_VERSION@
DDEDOTVER		= @TCL_DDE_MAJOR_VERSION@.@TCL_DDE_MINOR_VERSION@
REGVER			= @TCL_REG_MAJOR_VERSION@@TCL_REG_MINOR_VERSION@
REGDOTVER		= @TCL_REG_MAJOR_VERSION@.@TCL_REG_MINOR_VERSION@

TCL_ZIP_FILE		= @TCL_ZIP_FILE@
TCL_VFS_PATH		= libtcl.vfs/tcl_library
TCL_VFS_ROOT		= libtcl.vfs


TCL_STUB_LIB_FILE	= @TCL_STUB_LIB_FILE@
TCL_DLL_FILE		= @TCL_DLL_FILE@
TCL_LIB_FILE		= @TCL_LIB_FILE@
DDE_DLL_FILE		= tcl9dde$(DDEVER)${DLLSUFFIX}
DDE_DLL_FILE		= tcldde$(DDEVER)${DLLSUFFIX}
DDE_DLL_FILE8		= tcldde$(DDEVER)${DLLSUFFIX}
DDE_LIB_FILE		= @LIBPREFIX@tcldde$(DDEVER)${DLLSUFFIX}${LIBSUFFIX}
REG_DLL_FILE		= tclreg$(REGVER)${DLLSUFFIX}
REG_LIB_FILE		= @LIBPREFIX@tclreg$(REGVER)${DLLSUFFIX}${LIBSUFFIX}
REG_DLL_FILE		= tcl9registry$(REGVER)${DLLSUFFIX}
REG_DLL_FILE8		= tclregistry$(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.4.3 [list load [file normalize ${DDE_DLL_FILE}] dde];\
			  package ifneeded registry 1.3.5 [list load [file normalize ${REG_DLL_FILE}] registry]
TEST_LOAD_FACILITIES	= package ifneeded Tcltest ${VERSION}@TCL_PATCH_LEVEL@ [list load [file normalize ${TEST_DLL_FILE}] Tcltest];\
			  package ifneeded dde 1.4.5 [list load ${DDE_DLL_FILE}];\
			  package ifneeded registry 1.3.7 [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
TOMMATH_DLL_FILE	= libtommath.dll

SHARED_LIBRARIES 	= $(TCL_DLL_FILE) @ZLIB_DLL_FILE@ @TOMMATH_DLL_FILE@
SHARED_LIBRARIES	= $(TCL_DLL_FILE) @ZLIB_DLL_FILE@ @TOMMATH_DLL_FILE@
STATIC_LIBRARIES	= $(TCL_LIB_FILE)

TCLSH			= tclsh$(VER)${EXESUFFIX}
WINE			= @WINE@
CAT32			= cat32$(EXEEXT)
MAN2TCL			= man2tcl$(EXEEXT)

# For cross-compiled builds, TCL_EXE is the name of a tclsh executable that is
# available *BEFORE* running make for the first time. Certain build targets
# (make genstubs, make install) 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.
TCL_EXE			= @TCL_EXE@
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
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







+




















+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+







-
-
-
-
+
+
+
+



+











+






+








RMDIR		= rm -rf
MKDIR		= mkdir -p
SHELL		= @SHELL@
RM		= rm -f
COPY		= cp
LN		= ln
GDB		= gdb

###
# Tip 430 - ZipFS Modifications
###

TCL_ZIP_FILE		= @TCL_ZIP_FILE@
TCL_VFS_PATH		= libtcl.vfs/tcl_library
TCL_VFS_ROOT		= libtcl.vfs

HOST_CC		        = @CC_FOR_BUILD@
HOST_EXEEXT             = @EXEEXT_FOR_BUILD@
HOST_OBJEXT             = @OBJEXT_FOR_BUILD@
ZIPFS_BUILD	        = @ZIPFS_BUILD@
NATIVE_ZIP		= @ZIP_PROG@
ZIP_PROG_OPTIONS		= @ZIP_PROG_OPTIONS@
ZIP_PROG_VFSSEARCH  = @ZIP_PROG_VFSSEARCH@
SHARED_BUILD		= @SHARED_BUILD@
INSTALL_MSGS            = @INSTALL_MSGS@
INSTALL_LIBRARIES       = @INSTALL_LIBRARIES@

# Fully qualify library path so that `make test`
# does not depend on the current directory.
# Only define these if not embedding the library
ifeq ($(ZIPFS_BUILD), 0)
LIBRARY_DIR1		= $(shell cd '$(ROOT_DIR_NATIVE)/library' ; pwd -P)
LIBRARY_DIR             = $(shell $(CYGPATH) '$(LIBRARY_DIR1)')
endif

# Minizip
MINIZIP_OBJS = \
        adler32.$(HOST_OBJEXT) \
        compress.$(HOST_OBJEXT) \
        crc32.$(HOST_OBJEXT) \
        deflate.$(HOST_OBJEXT) \
        infback.$(HOST_OBJEXT) \
        inffast.$(HOST_OBJEXT) \
        inflate.$(HOST_OBJEXT) \
        inftrees.$(HOST_OBJEXT) \
        ioapi.$(HOST_OBJEXT) \
        iowin32.$(HOST_OBJEXT)  \
        trees.$(HOST_OBJEXT) \
        uncompr.$(HOST_OBJEXT) \
        zip.$(HOST_OBJEXT) \
        zutil.$(HOST_OBJEXT) \
        minizip.$(HOST_OBJEXT)
	adler32.$(HOST_OBJEXT) \
	compress.$(HOST_OBJEXT) \
	crc32.$(HOST_OBJEXT) \
	deflate.$(HOST_OBJEXT) \
	infback.$(HOST_OBJEXT) \
	inffast.$(HOST_OBJEXT) \
	inflate.$(HOST_OBJEXT) \
	inftrees.$(HOST_OBJEXT) \
	ioapi.$(HOST_OBJEXT) \
	iowin32.$(HOST_OBJEXT)  \
	trees.$(HOST_OBJEXT) \
	uncompr.$(HOST_OBJEXT) \
	zip.$(HOST_OBJEXT) \
	zutil.$(HOST_OBJEXT) \
	minizip.$(HOST_OBJEXT)

ZIP_INSTALL_OBJS =  @ZIP_INSTALL_OBJS@

CC_SWITCHES = -I"${GENERIC_DIR_NATIVE}" -I"${TOMMATH_DIR_NATIVE}" \
CC_SWITCHES = -I"${BUILD_DIR}" -I"${GENERIC_DIR_NATIVE}" -I"${TOMMATH_DIR_NATIVE}" \
-I"${ZLIB_DIR_NATIVE}" -I"${WIN_DIR_NATIVE}" \
${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} -DMP_PREC=4 \
${AC_FLAGS} ${COMPILE_DEBUG_FLAGS} ${NO_DEPRECATED_FLAGS}

CC_OBJNAME = @CC_OBJNAME@
CC_EXENAME = @CC_EXENAME@

STUB_CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} \
-I"${GENERIC_DIR_NATIVE}" -I"${TOMMATH_DIR_NATIVE}" \
-I"${WIN_DIR_NATIVE}" ${AC_FLAGS} \
${COMPILE_DEBUG_FLAGS}
STUB_CC_SWITCHES = -I"${GENERIC_DIR_NATIVE}" -I"${TOMMATH_DIR_NATIVE}" \
-I"${ZLIB_DIR_NATIVE}" -I"${WIN_DIR_NATIVE}" \
${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} -DMP_PREC=4 \
${AC_FLAGS} ${COMPILE_DEBUG_FLAGS}

TCLTEST_OBJS = \
	tclTest.$(OBJEXT) \
	tclTestABSList.$(OBJEXT) \
	tclTestObj.$(OBJEXT) \
	tclTestProcBodyObj.$(OBJEXT) \
	tclThreadTest.$(OBJEXT) \
	tclWinTest.$(OBJEXT)

GENERIC_OBJS = \
	regcomp.$(OBJEXT) \
	regexec.$(OBJEXT) \
	regfree.$(OBJEXT) \
	regerror.$(OBJEXT) \
	tclAlloc.$(OBJEXT) \
	tclArithSeries.$(OBJEXT) \
	tclAssembly.$(OBJEXT) \
	tclAsync.$(OBJEXT) \
	tclBasic.$(OBJEXT) \
	tclBinary.$(OBJEXT) \
	tclCkalloc.$(OBJEXT) \
	tclClock.$(OBJEXT) \
	tclClockFmt.$(OBJEXT) \
	tclCmdAH.$(OBJEXT) \
	tclCmdIL.$(OBJEXT) \
	tclCmdMZ.$(OBJEXT) \
	tclCompCmds.$(OBJEXT) \
	tclCompCmdsGR.$(OBJEXT) \
	tclCompCmdsSZ.$(OBJEXT) \
	tclCompExpr.$(OBJEXT) \
302
303
304
305
306
307
308

309
310
311
312
313
314
315
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331







+







	tclEvent.$(OBJEXT) \
	tclExecute.$(OBJEXT) \
	tclFCmd.$(OBJEXT) \
	tclFileName.$(OBJEXT) \
	tclGet.$(OBJEXT) \
	tclHash.$(OBJEXT) \
	tclHistory.$(OBJEXT) \
	tclIcu.$(OBJEXT) \
	tclIndexObj.$(OBJEXT) \
	tclInterp.$(OBJEXT) \
	tclIO.$(OBJEXT) \
	tclIOCmd.$(OBJEXT) \
	tclIOGT.$(OBJEXT) \
	tclIORChan.$(OBJEXT) \
	tclIORTrans.$(OBJEXT) \
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
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







+


















+







	tclNotify.$(OBJEXT) \
	tclOO.$(OBJEXT) \
	tclOOBasic.$(OBJEXT) \
	tclOOCall.$(OBJEXT) \
	tclOODefineCmds.$(OBJEXT) \
	tclOOInfo.$(OBJEXT) \
	tclOOMethod.$(OBJEXT) \
	tclOOProp.$(OBJEXT) \
	tclOOStubInit.$(OBJEXT) \
	tclObj.$(OBJEXT) \
	tclOptimize.$(OBJEXT) \
	tclPanic.$(OBJEXT) \
	tclParse.$(OBJEXT) \
	tclPathObj.$(OBJEXT) \
	tclPipe.$(OBJEXT) \
	tclPkg.$(OBJEXT) \
	tclPkgConfig.$(OBJEXT) \
	tclPosixStr.$(OBJEXT) \
	tclPreserve.$(OBJEXT) \
	tclProc.$(OBJEXT) \
	tclProcess.$(OBJEXT) \
	tclRegexp.$(OBJEXT) \
	tclResolve.$(OBJEXT) \
	tclResult.$(OBJEXT) \
	tclScan.$(OBJEXT) \
	tclStringObj.$(OBJEXT) \
	tclStrIdxTree.$(OBJEXT) \
	tclStrToD.$(OBJEXT) \
	tclStubInit.$(OBJEXT) \
	tclThread.$(OBJEXT) \
	tclThreadAlloc.$(OBJEXT) \
	tclThreadJoin.$(OBJEXT) \
	tclThreadStorage.$(OBJEXT) \
	tclTimer.$(OBJEXT) \
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
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
442
443
444
445







-
+

-
+


















+
+















+







	bn_mp_cnt_lsb.${OBJEXT} \
	bn_mp_copy.${OBJEXT} \
	bn_mp_count_bits.${OBJEXT} \
	bn_mp_div.${OBJEXT} \
	bn_mp_div_d.${OBJEXT} \
	bn_mp_div_2.${OBJEXT} \
	bn_mp_div_2d.${OBJEXT} \
	bn_mp_div_3.${OBJEXT} \
	bn_s_mp_div_3.${OBJEXT} \
	bn_mp_exch.${OBJEXT} \
	bn_mp_expt_u32.${OBJEXT} \
	bn_mp_expt_n.${OBJEXT} \
	bn_mp_get_mag_u64.${OBJEXT} \
	bn_mp_grow.${OBJEXT} \
	bn_mp_init.${OBJEXT} \
	bn_mp_init_copy.${OBJEXT} \
	bn_mp_init_i64.${OBJEXT} \
	bn_mp_init_multi.${OBJEXT} \
	bn_mp_init_set.${OBJEXT} \
	bn_mp_init_size.${OBJEXT} \
	bn_mp_init_u64.${OBJEXT} \
	bn_mp_lshd.${OBJEXT} \
	bn_mp_mod.${OBJEXT} \
	bn_mp_mod_2d.${OBJEXT} \
	bn_mp_mul.${OBJEXT} \
	bn_mp_mul_2.${OBJEXT} \
	bn_mp_mul_2d.${OBJEXT} \
	bn_mp_mul_d.${OBJEXT} \
	bn_mp_neg.${OBJEXT} \
	bn_mp_or.${OBJEXT} \
	bn_mp_pack.${OBJEXT} \
	bn_mp_pack_count.${OBJEXT} \
	bn_mp_radix_size.${OBJEXT} \
	bn_mp_radix_smap.${OBJEXT} \
	bn_mp_read_radix.${OBJEXT} \
	bn_mp_rshd.${OBJEXT} \
	bn_mp_set_i64.${OBJEXT} \
	bn_mp_set_u64.${OBJEXT} \
	bn_mp_shrink.${OBJEXT} \
	bn_mp_sqr.${OBJEXT} \
	bn_mp_sqrt.${OBJEXT} \
	bn_mp_sub.${OBJEXT} \
	bn_mp_sub_d.${OBJEXT} \
	bn_mp_signed_rsh.${OBJEXT} \
	bn_mp_to_ubin.${OBJEXT} \
	bn_mp_to_radix.${OBJEXT} \
	bn_mp_ubin_size.${OBJEXT} \
	bn_mp_unpack.${OBJEXT} \
	bn_mp_xor.${OBJEXT} \
	bn_mp_zero.${OBJEXT} \
	bn_s_mp_add.${OBJEXT} \
	bn_s_mp_balance_mul.$(OBJEXT) \
	bn_s_mp_karatsuba_mul.${OBJEXT} \
	bn_s_mp_karatsuba_sqr.$(OBJEXT) \
	bn_s_mp_mul_digs.${OBJEXT} \
449
450
451
452
453
454
455


456
457
458
459
460
461
462
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485







+
+








DDE_OBJS = tclWinDde.$(OBJEXT)

REG_OBJS = tclWinReg.$(OBJEXT)

STUB_OBJS = \
	tclStubLib.$(OBJEXT) \
	tclStubCall.$(OBJEXT) \
	tclStubLibTbl.$(OBJEXT) \
	tclTomMathStubLib.$(OBJEXT) \
	tclOOStubLib.$(OBJEXT) \
	tclWinPanic.$(OBJEXT)

TCLSH_OBJS = tclAppInit.$(OBJEXT)

ZLIB_OBJS = \
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
558
559
560
561
562
563

564
565

566
567
568

569
570
571
572
573
574
575
576
577
578

579




580
581

582

583
584
585
586
587
588
589
590








591
592
593
594
595
596
597

598
599
600

601
602
603

604




605
606


607
608

609
610
611
612




613
614


615
616

617
618
619
620
621
622
623
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
558
559
560
561

562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581

582
583

584
585
586

587
588
589
590
591
592
593
594
595
596
597
598

599
600
601
602
603

604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628

629
630
631

632
633
634

635
636
637
638
639
640


641
642
643

644
645
646
647
648
649
650
651
652


653
654
655

656
657
658
659
660
661
662
663







-
+












-
-
-
-
-
-
-
-
-


-
-
+
+








-
+




+
+
+
+
+










-
+

-
+


-
+










+
-
+
+
+
+

-
+

+








+
+
+
+
+
+
+
+






-
+


-
+


-
+

+
+
+
+
-
-
+
+

-
+




+
+
+
+
-
-
+
+

-
+








tcltest.sh: tcltest.cmd

tcltest: binaries $(TEST_EXE_FILE) $(TEST_DLL_FILE) $(CAT32) tcltest.cmd

binaries: $(TCL_STUB_LIB_FILE) @LIBRARIES@ winextensions ${TCL_ZIP_FILE} $(TCLSH)

winextensions: ${DDE_DLL_FILE} ${REG_DLL_FILE}
winextensions: ${DDE_DLL_FILE} ${REG_DLL_FILE} ${DDE_DLL_FILE8} ${REG_DLL_FILE8}

libraries:

doc:

tclzipfile: ${TCL_ZIP_FILE}

${TCL_ZIP_FILE}:  ${ZIP_INSTALL_OBJS} ${DDE_DLL_FILE} ${REG_DLL_FILE}
	@rm -rf ${TCL_VFS_ROOT}
	@mkdir -p ${TCL_VFS_PATH}
	@echo "creating ${TCL_VFS_PATH} (prepare compression)"
	@( \
	  $(LN) $$(find $(TOP_DIR)/library/* -maxdepth 0 -type f) ${TCL_VFS_PATH}/ && \
	  (for D in $$(find $(TOP_DIR)/library/* -maxdepth 0 -type d); do \
	    mkdir -p "${TCL_VFS_PATH}/$$(basename $$D)"; \
	    $(LN) -s $$D/* ${TCL_VFS_PATH}/$$(basename $$D)/; \
	  done) && \
	  $(LN) ${TCL_VFS_PATH}/manifest.txt ${TCL_VFS_PATH}/pkgIndex.tcl && \
	  $(LN) ${DDE_DLL_FILE} ${TCL_VFS_PATH}/dde/ && \
	  $(LN) ${REG_DLL_FILE} ${TCL_VFS_PATH}/reg/ \
	) || ( \
	  $(COPY) -a $(TOP_DIR)/library/* ${TCL_VFS_PATH}; \
	  $(COPY) -a ${TCL_VFS_PATH}/manifest.txt ${TCL_VFS_PATH}/pkgIndex.tcl; \
	  $(COPY) ${DDE_DLL_FILE} ${TCL_VFS_PATH}/dde; \
	  $(COPY) ${REG_DLL_FILE} ${TCL_VFS_PATH}/reg; \
	  rm -rf ${TCL_VFS_PATH}/dde; \
	  rm -rf ${TCL_VFS_PATH}/registry; \
	)
	(zip=`(realpath '${NATIVE_ZIP}' || readlink -m '${NATIVE_ZIP}') 2>/dev/null || \
	  (echo '${NATIVE_ZIP}' | sed "s?^\./?$$(pwd)/?")`; \
	  cd ${TCL_VFS_ROOT} && \
	  $$zip ${ZIP_PROG_OPTIONS} ../${TCL_ZIP_FILE} ${ZIP_PROG_VFSSEARCH} >/dev/null && \
	  echo "${TCL_ZIP_FILE} successful created with $$zip" && \
	  cd ..)

$(TCLSH): $(TCLSH_OBJS) @LIBRARIES@ $(TCL_STUB_LIB_FILE) tclsh.$(RES)
$(TCLSH): $(TCLSH_OBJS) @LIBRARIES@ $(TCL_STUB_LIB_FILE) tclsh.$(RES) ${TCL_ZIP_FILE}
	$(CC) $(CFLAGS) $(TCLSH_OBJS) $(TCL_LIB_FILE) $(TCL_STUB_LIB_FILE) $(LIBS) \
	tclsh.$(RES) $(CC_EXENAME) $(LDFLAGS_CONSOLE)
	$(COPY) tclsh.exe.manifest $(TCLSH).manifest
	@VC_MANIFEST_EMBED_EXE@
	@if test "${ZIPFS_BUILD}" = "2" ; then \
		cat ${TCL_ZIP_FILE} >> ${TCLSH}; \
		${NATIVE_ZIP} -A ${TCLSH} \
		  || echo 'ignore zip-error by adjust sfx process (not executable?)'; \
	fi

cat32.$(OBJEXT): cat.c
	$(CC) -c $(CC_SWITCHES) -DUNICODE -D_UNICODE @DEPARG@ $(CC_OBJNAME)

$(CAT32): cat32.$(OBJEXT)
	$(CC) $(CFLAGS) cat32.$(OBJEXT) $(CC_EXENAME) $(LIBS) $(LDFLAGS_CONSOLE)

# The following targets are configured by autoconf to generate either a shared
# library or static library

${TCL_STUB_LIB_FILE}: ${STUB_OBJS}
${TCL_STUB_LIB_FILE}: ${STUB_OBJS} ${DDE_OBJS} ${REG_OBJS}
	@$(RM) ${TCL_STUB_LIB_FILE}
	@MAKE_STUB_LIB@ ${STUB_OBJS}
	@MAKE_STUB_LIB@ ${STUB_OBJS} ${DDE_OBJS} ${REG_OBJS}
	@POST_MAKE_LIB@

${TCL_DLL_FILE}: ${TCL_OBJS} tcl.$(RES) @ZLIB_DLL_FILE@ @TOMMATH_DLL_FILE@ ${TCL_ZIP_FILE}
${TCL_DLL_FILE}: ${TCL_LIB_FILE} ${TCL_OBJS} tcl.$(RES) @ZLIB_DLL_FILE@ @TOMMATH_DLL_FILE@ ${TCL_ZIP_FILE}
	@$(RM) ${TCL_DLL_FILE} $(TCL_LIB_FILE)
	@MAKE_DLL@ ${TCL_OBJS} tcl.$(RES) $(SHLIB_LD_LIBS)
	$(COPY) tclsh.exe.manifest ${TCL_DLL_FILE}.manifest
	@VC_MANIFEST_EMBED_DLL@
	@if test "${ZIPFS_BUILD}" = "1" ; then \
		cat ${TCL_ZIP_FILE} >> ${TCL_DLL_FILE}; \
		${NATIVE_ZIP} -A ${TCL_DLL_FILE} \
		  || echo 'ignore zip-error by adjust sfx process (not executable?)'; \
	fi

ifeq (,$(findstring --disable-shared,$(PKG_CFG_ARGS)))
${TCL_LIB_FILE}: ${TCL_OBJS} ${DDE_OBJS} ${REG_OBJS}
${TCL_LIB_FILE}:
	@$(RM) ${TCL_DLL_FILE} $(TCL_LIB_FILE)
else
${TCL_LIB_FILE}: ${TCL_OBJS} tclWinPanic.$(OBJEXT) ${DDE_OBJS} ${REG_OBJS}
	@$(RM) ${TCL_LIB_FILE}
	@MAKE_LIB@ ${TCL_OBJS} ${DDE_OBJS} ${REG_OBJS}
	@MAKE_LIB@ ${TCL_OBJS} tclWinPanic.$(OBJEXT) ${DDE_OBJS} ${REG_OBJS}
	@POST_MAKE_LIB@
endif

${DDE_DLL_FILE}: ${TCL_STUB_LIB_FILE} ${DDE_OBJS}
	@MAKE_DLL@ ${DDE_OBJS} $(TCL_STUB_LIB_FILE) $(SHLIB_LD_LIBS)
	$(COPY) tclsh.exe.manifest ${DDE_DLL_FILE}.manifest

${REG_DLL_FILE}: ${TCL_STUB_LIB_FILE} ${REG_OBJS}
	@MAKE_DLL@ ${REG_OBJS} $(TCL_STUB_LIB_FILE) $(SHLIB_LD_LIBS)
	$(COPY) tclsh.exe.manifest ${REG_DLL_FILE}.manifest

${DDE_DLL_FILE8}: ${TCL_STUB_LIB_FILE} tcl8WinDde.$(OBJEXT)
	@MAKE_DLL@ tcl8WinDde.$(OBJEXT) $(TCL_STUB_LIB_FILE) $(SHLIB_LD_LIBS)
	$(COPY) tclsh.exe.manifest ${DDE_DLL_FILE8}.manifest

${REG_DLL_FILE8}: ${TCL_STUB_LIB_FILE} tcl8WinReg.$(OBJEXT)
	@MAKE_DLL@ -DTCL_MAJOR_VERSION=8 tcl8WinReg.$(OBJEXT) $(TCL_STUB_LIB_FILE) $(SHLIB_LD_LIBS)
	$(COPY) tclsh.exe.manifest ${REG_DLL_FILE8}.manifest

${TEST_DLL_FILE}: ${TCL_STUB_LIB_FILE} ${TCLTEST_OBJS}
	@$(RM) ${TEST_DLL_FILE} ${TEST_LIB_FILE}
	@MAKE_DLL@ ${TCLTEST_OBJS} $(TCL_STUB_LIB_FILE) $(SHLIB_LD_LIBS)
	$(COPY) tclsh.exe.manifest ${TEST_DLL_FILE}.manifest

${TEST_EXE_FILE}: ${TCL_STUB_LIB_FILE} ${TCLTEST_OBJS} tclTestMain.${OBJEXT}
${TEST_EXE_FILE}: @LIBRARIES@ ${TCL_STUB_LIB_FILE} ${TCLTEST_OBJS} tclTestMain.${OBJEXT}
	@$(RM) ${TEST_EXE_FILE}
	$(CC) $(CFLAGS) $(TCLTEST_OBJS) tclTestMain.$(OBJEXT) $(TCL_LIB_FILE) $(TCL_STUB_LIB_FILE) $(LIBS) \
        tclsh.$(RES) $(CC_EXENAME) $(LDFLAGS_CONSOLE)
	tclsh.$(RES) $(CC_EXENAME) $(LDFLAGS_CONSOLE)
	$(COPY) tclsh.exe.manifest ${TEST_EXE_FILE}.manifest

# use pre-built zlib1.dll
# use prebuilt zlib1.dll
${ZLIB_DLL_FILE}: ${TCL_STUB_LIB_FILE}
	@if test "@ZLIB_LIBS@set" = "${ZLIB_DIR_NATIVE}/win64-arm/zdll.libset" ; then \
		$(COPY) $(ZLIB_DIR)/win64-arm/${ZLIB_DLL_FILE} ${ZLIB_DLL_FILE}; \
	elif test "@ZLIB_LIBS@set" = "${ZLIB_DIR_NATIVE}/win64-arm/libz.dll.aset" ; then \
		$(COPY) $(ZLIB_DIR)/win64-arm/${ZLIB_DLL_FILE} ${ZLIB_DLL_FILE}; \
	@if test "@ZLIB_LIBS@set" != "${ZLIB_DIR_NATIVE}/win32/zdll.libset" ; then \
		$(COPY) $(ZLIB_DIR)/win64/${ZLIB_DLL_FILE} ${ZLIB_DLL_FILE}; \
	elif test "@ZLIB_LIBS@set" = "${ZLIB_DIR_NATIVE}/win32/zdll.libset" ; then \
		$(COPY) $(ZLIB_DIR)/win32/${ZLIB_DLL_FILE} ${ZLIB_DLL_FILE}; \
	else \
		$(COPY) $(ZLIB_DIR)/win32/${ZLIB_DLL_FILE} ${ZLIB_DLL_FILE}; \
		$(COPY) $(ZLIB_DIR)/win64/${ZLIB_DLL_FILE} ${ZLIB_DLL_FILE}; \
	fi;

# use pre-built libtommath.dll
${TOMMATH_DLL_FILE}: ${TCL_STUB_LIB_FILE}
	@if test "@TOMMATH_LIBS@set" = "${TOMMATH_DIR_NATIVE}/win64-arm/tommath.libset" ; then \
		$(COPY) $(TOMMATH_DIR)/win64-arm/${TOMMATH_DLL_FILE} ${TOMMATH_DLL_FILE}; \
	elif test "@TOMMATH_LIBS@set" = "${TOMMATH_DIR_NATIVE}/win64-arm/libtommath.dll.aset" ; then \
		$(COPY) $(TOMMATH_DIR)/win64-arm/${TOMMATH_DLL_FILE} ${TOMMATH_DLL_FILE}; \
	@if test "@TOMMATH_LIBS@set" != "${TOMMATH_DIR_NATIVE}/win32/tommath.libset" ; then \
		$(COPY) $(TOMMATH_DIR)/win64/${TOMMATH_DLL_FILE} ${TOMMATH_DLL_FILE}; \
	elif test "@TOMMATH_LIBS@set" = "${TOMMATH_DIR_NATIVE}/win32/tommath.libset" ; then \
		$(COPY) $(TOMMATH_DIR)/win32/${TOMMATH_DLL_FILE} ${TOMMATH_DLL_FILE}; \
	else \
		$(COPY) $(TOMMATH_DIR)/win32/${TOMMATH_DLL_FILE} ${TOMMATH_DLL_FILE}; \
		$(COPY) $(TOMMATH_DIR)/win64/${TOMMATH_DLL_FILE} ${TOMMATH_DLL_FILE}; \
	fi;

# Add the object extension to the implicit rules. By default .obj is not
# automatically added.

.SUFFIXES: .${OBJEXT}
.SUFFIXES: .$(RES)
633
634
635
636
637
638
639



640
641
642



643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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







+
+
+



+
+
+









-
-
-
-
-








tclWinPipe.${OBJEXT}: tclWinPipe.c
	$(CC) -c $(CC_SWITCHES) -DBUILD_tcl $(EXTFLAGS) @DEPARG@ $(CC_OBJNAME)

tclWinReg.${OBJEXT}: tclWinReg.c
	$(CC) -c $(CC_SWITCHES) $(EXTFLAGS) @DEPARG@ $(CC_OBJNAME)

tcl8WinReg.${OBJEXT}: tclWinReg.c
	$(CC)  -o $@ -c $(CC_SWITCHES) -DTCL_MAJOR_VERSION=8 $(EXTFLAGS) @DEPARG@ $(CC_OBJNAME)

tclWinDde.${OBJEXT}: tclWinDde.c
	$(CC) -c $(CC_SWITCHES) $(EXTFLAGS) @DEPARG@ $(CC_OBJNAME)

tcl8WinDde.${OBJEXT}: tclWinDde.c
	$(CC) -o $@ -c $(CC_SWITCHES) -DTCL_MAJOR_VERSION=8 $(EXTFLAGS) @DEPARG@ $(CC_OBJNAME)

tclAppInit.${OBJEXT}: tclAppInit.c
	$(CC) -c $(CC_SWITCHES) $(EXTFLAGS) -DUNICODE -D_UNICODE @DEPARG@ $(CC_OBJNAME)

tclMainW.${OBJEXT}: tclMain.c
	$(CC) -c $(CC_SWITCHES) -DBUILD_tcl -DUNICODE -D_UNICODE @DEPARG@ $(CC_OBJNAME)

# TIP #430, ZipFS Support
tclZipfs.${OBJEXT}: $(GENERIC_DIR)/tclZipfs.c
	$(CC) -c $(CC_SWITCHES) -DBUILD_tcl \
	-DCFG_RUNTIME_PATH="\"$(bindir_native)\"" \
	-DCFG_RUNTIME_DLLFILE="\"$(TCL_DLL_FILE)\"" \
	-DCFG_RUNTIME_ZIPFILE="\"$(TCL_ZIP_FILE)\"" \
	-DCFG_RUNTIME_LIBDIR="\"$(bindir_native)\"" \
	-DCFG_RUNTIME_SCRDIR="\"$(TCL_LIBRARY_NATIVE)\"" \
	$(ZLIB_INCLUDE) -I$(MINIZIP_DIR_NATIVE)  @DEPARG@ $(CC_OBJNAME)


# TIP #59, embedding of configuration information into the binary library.
#
# Part of Tcl's configuration information are the paths where it was installed
# and where it will look for its libraries (which can be different). We derive
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
716
717
718
719
720
721
722

723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757

758
759
760

761
762
763
764
765
766
767
768







-


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+
+
+
+
+
+
+
+
+



-
+


-
+







		\
		-DCFG_RUNTIME_LIBDIR="\"$(libdir_native)\"" \
		-DCFG_RUNTIME_BINDIR="\"$(bindir_native)\"" \
		-DCFG_RUNTIME_SCRDIR="\"$(TCL_LIBRARY_NATIVE)\"" \
		-DCFG_RUNTIME_INCDIR="\"$(includedir_native)\"" \
		-DCFG_RUNTIME_DOCDIR="\"$(mandir_native)\"" \
		-DCFG_RUNTIME_DLLFILE="\"$(TCL_DLL_FILE)\"" \
		-DCFG_RUNTIME_ZIPFILE="\"$(TCL_ZIP_FILE)\"" \
		-DBUILD_tcl \
		@DEPARG@ $(CC_OBJNAME)

tclEvent.${OBJEXT}: tclEvent.c tclUuid.h

tclTest.${OBJEXT}: tclTest.c tclUuid.h

$(TOP_DIR)/manifest.uuid:
	printf "git-" >$(TOP_DIR)/manifest.uuid
	(cd $(TOP_DIR); git rev-parse HEAD >>$(TOP_DIR)/manifest.uuid || \
	    (printf "svn-r" >$(TOP_DIR)/manifest.uuid ; \
	    svn info --show-item last-changed-revision >>$(TOP_DIR)/manifest.uuid) || \
	    printf "unknown" >$(TOP_DIR)/manifest.uuid)

tclUuid.h:	$(TOP_DIR)/manifest.uuid
	echo "#define TCL_VERSION_UUID \\" >$@
	cat $(TOP_DIR)/manifest.uuid >>$@
	echo "" >>$@

# The following objects are part of the stub library and should not be built
# as DLL objects but none of the symbols should be exported

tclStubLib.${OBJEXT}: tclStubLib.c
	$(CC) -c $(CC_SWITCHES) -DSTATIC_BUILD @CFLAGS_NOLTO@ @DEPARG@ $(CC_OBJNAME)

tclStubCall.${OBJEXT}: tclStubCall.c
	$(CC) -c $(CC_SWITCHES) -DSTATIC_BUILD \
		-DCFG_RUNTIME_DLLFILE="\"$(TCL_DLL_FILE)\"" \
		-DCFG_RUNTIME_BINDIR="\"$(bindir_native)\"" \
		@DEPARG@ $(CC_OBJNAME)

tclStubLibTbl.${OBJEXT}: tclStubLibTbl.c
	$(CC) -c $(CC_SWITCHES) -DSTATIC_BUILD @DEPARG@ $(CC_OBJNAME)

tclTomMathStubLib.${OBJEXT}: tclTomMathStubLib.c
	$(CC) -c $(CC_SWITCHES) -DSTATIC_BUILD @DEPARG@ $(CC_OBJNAME)
	$(CC) -c $(CC_SWITCHES) @CFLAGS_NOLTO@ @DEPARG@ $(CC_OBJNAME)

tclOOStubLib.${OBJEXT}: tclOOStubLib.c
	$(CC) -c $(CC_SWITCHES) -DSTATIC_BUILD @DEPARG@ $(CC_OBJNAME)
	$(CC) -c $(CC_SWITCHES) @CFLAGS_NOLTO@ @DEPARG@ $(CC_OBJNAME)

tclWinPanic.${OBJEXT}: tclWinPanic.c
	$(CC) -c $(CC_SWITCHES) -DSTATIC_BUILD @DEPARG@ $(CC_OBJNAME)

# Implicit rule for all object files that will end up in the Tcl library

%.${OBJEXT}: %.c
787
788
789
790
791
792
793
794

795
796
797
798
799
800
801
802
803
804
805
806
807
808
809

810
811
812
813
814
815
816
817
818
819
820
821




822
823
824
825
826
827
828
829
830







831
832
833
834

835
836
837
838
839
840
841
842
843
844
845
846
847
848
852
853
854
855
856
857
858

859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906

907
908
909





910
911
912
913
914
915
916







-
+














-
+












+
+
+
+






-
-
-
+
+
+
+
+
+
+



-
+


-
-
-
-
-







	    if [ ! -d "$$i" ] ; then \
		echo "Making directory $$i"; \
		$(MKDIR) "$$i"; \
		chmod 755 "$$i"; \
		else true; \
		fi; \
	    done;
	@for i in dde${DDEDOTVER} reg${REGDOTVER}; \
	@for i in dde${DDEDOTVER} registry${REGDOTVER}; \
	    do \
	    if [ ! -d "$(LIB_INSTALL_DIR)/$$i" ] ; then \
		echo "Making directory $(LIB_INSTALL_DIR)/$$i"; \
		$(MKDIR) "$(LIB_INSTALL_DIR)/$$i"; \
		else true; \
		fi; \
	    done;
	@for i in $(TCL_DLL_FILE) $(ZLIB_DLL_FILE) $(TOMMATH_DLL_FILE) $(TCLSH); \
	    do \
	    if [ -f $$i ]; then \
		echo "Installing $$i to $(BIN_INSTALL_DIR)/"; \
		$(COPY) $$i "$(BIN_INSTALL_DIR)"; \
	    fi; \
	    done
	@for i in tclConfig.sh tclooConfig.sh $(TCL_LIB_FILE) $(TCL_STUB_LIB_FILE); \
	@for i in tclConfig.sh tclooConfig.sh $(TCL_LIB_FILE) $(TCL_STUB_LIB_FILE) @ZLIB_LIBS@ @TOMMATH_LIBS@; \
	    do \
	    if [ -f $$i ]; then \
		echo "Installing $$i to $(LIB_INSTALL_DIR)/"; \
		$(COPY) $$i "$(LIB_INSTALL_DIR)"; \
	    fi; \
	    done
	@if [ -f $(DDE_DLL_FILE) ]; then \
	    echo Installing $(DDE_DLL_FILE); \
	    $(COPY) $(DDE_DLL_FILE) "$(LIB_INSTALL_DIR)/dde${DDEDOTVER}"; \
	    $(COPY) $(ROOT_DIR)/library/dde/pkgIndex.tcl \
		"$(LIB_INSTALL_DIR)/dde${DDEDOTVER}"; \
	    fi
	@if [ -f $(DDE_DLL_FILE8) ]; then \
	    echo Installing $(DDE_DLL_FILE8); \
	    $(COPY) $(DDE_DLL_FILE8) "$(LIB_INSTALL_DIR)/dde${DDEDOTVER}"; \
	    fi
	@if [ -f $(DDE_LIB_FILE) ]; then \
	    echo Installing $(DDE_LIB_FILE); \
	    $(COPY) $(DDE_LIB_FILE) "$(LIB_INSTALL_DIR)/dde${DDEDOTVER}"; \
	    fi
	@if [ -f $(REG_DLL_FILE) ]; then \
	    echo Installing $(REG_DLL_FILE); \
	    $(COPY) $(REG_DLL_FILE) "$(LIB_INSTALL_DIR)/reg${REGDOTVER}"; \
	    $(COPY) $(ROOT_DIR)/library/reg/pkgIndex.tcl \
		"$(LIB_INSTALL_DIR)/reg${REGDOTVER}"; \
	    $(COPY) $(REG_DLL_FILE) "$(LIB_INSTALL_DIR)/registry${REGDOTVER}"; \
	    $(COPY) $(ROOT_DIR)/library/registry/pkgIndex.tcl \
		"$(LIB_INSTALL_DIR)/registry${REGDOTVER}"; \
	    fi
	@if [ -f $(REG_DLL_FILE8) ]; then \
	    echo Installing $(REG_DLL_FILE8); \
	    $(COPY) $(REG_DLL_FILE8) "$(LIB_INSTALL_DIR)/registry${REGDOTVER}"; \
	    fi
	@if [ -f $(REG_LIB_FILE) ]; then \
	    echo Installing $(REG_LIB_FILE); \
	    $(COPY) $(REG_LIB_FILE) "$(LIB_INSTALL_DIR)/reg${REGDOTVER}"; \
	    $(COPY) $(REG_LIB_FILE) "$(LIB_INSTALL_DIR)/registry${REGDOTVER}"; \
	    fi

install-libraries-zipfs-shared: libraries

install-libraries-zipfs-static: install-libraries-zipfs-shared
	$(COPY) ${TCL_ZIP_FILE} "$(LIB_INSTALL_DIR)"

install-libraries: libraries install-tzdata install-msgs
	@for i in "$(prefix)/lib" "$(INCLUDE_INSTALL_DIR)" \
		"$(SCRIPT_INSTALL_DIR)" "$(MODULE_INSTALL_DIR)"; \
	    do \
	    if [ ! -d "$$i" ] ; then \
		echo "Making directory $$i"; \
		$(MKDIR) "$$i"; \
862
863
864
865
866
867
868
869

870
871
872
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
898
899
900
901
930
931
932
933
934
935
936

937

938
939
940


941
942
943
944


945
946
947

948

949
950
951
952




953
954
955
956
957
958
959

960
961
962
963
964
965
966
967







-
+
-



-
-
+
+


-
-
+
+

-
+
-




-
-
-
-
+
+
+
+



-
+







	    if [ ! -d "$(MODULE_INSTALL_DIR)/$$i" ] ; then \
		echo "Making directory $(MODULE_INSTALL_DIR)/$$i"; \
		$(MKDIR) "$(MODULE_INSTALL_DIR)/$$i"; \
		else true; \
		fi; \
	    done;
	@echo "Installing library files to $(SCRIPT_INSTALL_DIR)";
	@for i in $(ROOT_DIR)/library/*.tcl $(ROOT_DIR)/library/tclIndex; \
	@for i in $(ROOT_DIR)/library/*.tcl $(ROOT_DIR)/library/tclIndex; do \
	    do \
	    $(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)"; \
	    done;
	@echo "Installing package cookiejar 0.2"
	@for j in $(ROOT_DIR)/library/cookiejar/*.{tcl,txt.gz}; \
	    do \
	@for j in $(ROOT_DIR)/library/cookiejar/*.tcl \
		  $(ROOT_DIR)/library/cookiejar/*.gz; do \
	    $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/cookiejar0.2"; \
	    done;
	@echo "Installing package http 2.10.0a1 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/http/http.tcl "$(MODULE_INSTALL_DIR)/9.0/http-2.10.0a1.tm";
	@echo "Installing package http 2.10.0 as a Tcl Module";
	@$(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; \
	@for j in $(ROOT_DIR)/library/opt/*.tcl; do \
	    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.3 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/tcltest/tcltest.tcl "$(MODULE_INSTALL_DIR)/9.0/tcltest-2.5.3.tm";
	@echo "Installing package platform 1.0.14 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/platform/platform.tcl "$(MODULE_INSTALL_DIR)/9.0/platform-1.0.14.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 \
	@for i in $(ROOT_DIR)/library/encoding/*.enc ; do \
		$(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)/encoding"; \
	done;

install-tzdata:
	@echo "Installing time zone data"
	@$(TCL_EXE) "$(ROOT_DIR)/tools/installData.tcl" \
	    "$(ROOT_DIR)/library/tzdata" "$(SCRIPT_INSTALL_DIR_NATIVE)/tzdata"
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
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
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


1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128

1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140

1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164

1165
1166
1167
1168
1169

1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185







-
+
+
+
+
+
+
+
+
+
+








-
+




-
+

-




-
+





-










-
-
-
+
+
+














-
-
+
+











-
-
+
+











-
+











-
+

















+
+
+
+
+

-
+




-
+



+
+
+
+
+







shell: binaries
	@TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \
	$(WINE) ./$(TCLSH) $(SCRIPT)

# This target can be used to run tclsh inside either gdb or insight
gdb: binaries
	@echo "set env TCL_LIBRARY=$(LIBRARY_DIR)" > gdb.run
	gdb ./$(TCLSH) --command=gdb.run
	$(GDB) ./$(TCLSH) --command=gdb.run
	rm gdb.run

shquotequote = $(subst ',\",$(subst ",\",$(1)))
gdb-test: tcltest
	@printf '%s ' 'set env TCL_LIBRARY=$(LIBRARY_DIR)' > gdb.run
	@printf '\n' >>gdb.run
	@printf '%s ' set args $(ROOT_DIR_NATIVE)/tests/all.tcl \
		$(call shquotequote,$(TESTFLAGS)) -singleproc 1 >> gdb.run
	$(GDB) ${TEST_EXE_FILE} --command=gdb.run
	rm gdb.run

depend:

Makefile: $(SRC_DIR)/Makefile.in
	./config.status

cleanhelp:
	$(RM) *.hlp *.cnt *.GID *.rtf man2tcl.exe
	$(RM) *.hlp *.cnt *.GID

clean: cleanhelp clean-packages
	$(RM) *.lib *.a *.exp *.dll *.$(RES) *.${OBJEXT} *~ \#* TAGS a.out
	$(RM) $(TCLSH) $(CAT32) $(TEST_EXE_FILE) $(TEST_DLL_FILE) tcltest.cmd tcltest.sh
	$(RM) *.pch *.ilk *.pdb
	$(RM) *.pch *.ilk *.pdb *.zip
	$(RM) minizip${HOST_EXEEXT} *.${HOST_OBJEXT}
	$(RM) *.zip
	$(RMDIR) *.vfs

distclean: distclean-packages clean
	$(RM) Makefile config.status config.cache config.log tclConfig.sh \
		tcl.hpj config.status.lineno tclsh.exe.manifest
		config.status.lineno tclsh.exe.manifest tclUuid.h

#
# Bundled package targets
#

PKG_CFG_ARGS		= @PKG_CFG_ARGS@
PKG_DIR			= ./pkgs

packages:
	@builddir=`$(CYGPATH) $$(pwd -P)`; \
	for i in $(PKGS_DIR)/*; do \
	  if [ -d $$i ] ; then \
	    if [ -x $$i/configure ] ; then \
	      pkg=`basename $$i`; \
	      mkdir -p $(PKG_DIR)/$$pkg; \
	      if [ ! -f $(PKG_DIR)/$$pkg/Makefile ]; then \
	        ( cd $(PKG_DIR)/$$pkg; \
	          echo "Configuring package '$$i' wd = `$(CYGPATH) $$(pwd -P)`"; \
	          $$i/configure --with-tcl=$$builddir --with-tclinclude=$(GENERIC_DIR_NATIVE) $(PKG_CFG_ARGS) --enable-shared; ) \
		( cd $(PKG_DIR)/$$pkg; \
		  echo "Configuring package '$$i' wd = `$(CYGPATH) $$(pwd -P)`"; \
		  $$i/configure --with-tcl=$$builddir --with-tclinclude=$(GENERIC_DIR_NATIVE) $(PKG_CFG_ARGS) --enable-shared; ) \
	      fi ; \
	      echo "Building package '$$pkg'"; \
	      ( cd $(PKG_DIR)/$$pkg; $(MAKE); ) \
	    fi; \
	  fi; \
	done; \
	cd $$builddir

install-packages: packages
	@builddir=`pwd -P`; \
	for i in $(PKGS_DIR)/*; do \
	  if [ -d $$i ]; then \
	    pkg=`basename $$i`; \
	    if [ -f $(PKG_DIR)/$$pkg/Makefile ]; then \
	        echo "Installing package '$$pkg'"; \
	        ( cd $(PKG_DIR)/$$pkg; $(MAKE) install "DESTDIR=$(INSTALL_ROOT)"; ) \
		echo "Installing package '$$pkg'"; \
		( cd $(PKG_DIR)/$$pkg; $(MAKE) install "DESTDIR=$(INSTALL_ROOT)"; ) \
	    fi; \
	  fi; \
	done; \
	cd $$builddir

test-packages: tcltest packages
	@builddir=`pwd -P`; \
	for i in $(PKGS_DIR)/*; do \
	  if [ -d $$i ]; then \
	    pkg=`basename $$i`; \
	    if [ -f $(PKG_DIR)/$$pkg/Makefile ]; then \
	        echo "Testing package '$$pkg'"; \
	        ( cd $(PKG_DIR)/$$pkg; $(MAKE) "LD_LIBRARY_PATH=$$builddir:${LD_LIBRARY_PATH}" "TCL_LIBRARY=${TCL_BUILDTIME_LIBRARY}" "TCLLIBPATH=$$builddir/pkgs" test "TCLSH_PROG=$$builddir/${TCLSH}"; ) \
		echo "Testing package '$$pkg'"; \
		( cd $(PKG_DIR)/$$pkg; $(MAKE) "LD_LIBRARY_PATH=$$builddir:${LD_LIBRARY_PATH}" "TCL_LIBRARY=${TCL_BUILDTIME_LIBRARY}" "TCLLIBPATH=$$builddir/pkgs" test "TCLSH_PROG=$$builddir/${TCLSH}"; ) \
	    fi; \
	  fi; \
	done; \
	cd $$builddir

clean-packages:
	@builddir=`pwd -P`; \
	for i in $(PKGS_DIR)/*; do \
	  if [ -d $$i ]; then \
	    pkg=`basename $$i`; \
	    if [ -f $(PKG_DIR)/$$pkg/Makefile ]; then \
	        ( cd $(PKG_DIR)/$$pkg; $(MAKE) clean; ) \
		( cd $(PKG_DIR)/$$pkg; $(MAKE) clean; ) \
	    fi; \
	  fi; \
	done; \
	cd $$builddir

distclean-packages:
	@builddir=`pwd -P`; \
	for i in $(PKGS_DIR)/*; do \
	  if [ -d $$i ]; then \
	    pkg=`basename $$i`; \
	    if [ -f $(PKG_DIR)/$$pkg/Makefile ]; then \
	        ( cd $(PKG_DIR)/$$pkg; $(MAKE) distclean; ) \
		( cd $(PKG_DIR)/$$pkg; $(MAKE) distclean; ) \
	    fi; \
	    cd $$builddir; \
	    rm -rf $(PKG_DIR)/$$pkg; \
	  fi; \
	done; \
	rm -rf $(PKG_DIR)

#
# Regenerate the stubs files.
#

$(GENERIC_DIR)/tclStubInit.c: $(GENERIC_DIR)/tcl.decls \
		$(GENERIC_DIR)/tclInt.decls
	@echo "Warning: tclStubInit.c may be out of date."
	@echo "Developers may want to run \"make genstubs\" to regenerate."
	@echo "This warning can be safely ignored, do not report as a bug!"

$(GENERIC_DIR)/tclOOScript.h: $(TOOL_DIR)/tclOOScript.tcl
	@echo "Warning: tclOOScript.h may be out of date."
	@echo "Developers may want to run \"make genscript\" to regenerate."
	@echo "This warning can be safely ignored, do not report as a bug!"

genstubs:
	$(TCL_EXE) "$(ROOT_DIR_NATIVE)/tools/genStubs.tcl" \
	$(TCL_EXE) "$(TOOL_DIR_NATIVE)/genStubs.tcl" \
	    "$(GENERIC_DIR_NATIVE)" \
	    "$(GENERIC_DIR_NATIVE)/tcl.decls" \
	    "$(GENERIC_DIR_NATIVE)/tclInt.decls" \
	    "$(GENERIC_DIR_NATIVE)/tclTomMath.decls"
	$(TCL_EXE) "$(ROOT_DIR_NATIVE)/tools/genStubs.tcl" \
	$(TCL_EXE) "$(TOOL_DIR_NATIVE)/genStubs.tcl" \
	    "$(GENERIC_DIR_NATIVE)" \
	    "$(GENERIC_DIR_NATIVE)/tclOO.decls"

genscript:
	$(TCL_EXE) "$(TOOL_DIR_NATIVE)/makeHeader.tcl" \
		"$(TOOL_DIR_NATIVE)/tclOOScript.tcl" \
		"$(GENERIC_DIR_NATIVE)/tclOOScript.h"

#
# This target creates the HTML folder for Tcl & Tk and places it in
# DISTDIR/html. It uses the tcltk-man2html.tcl tool from the Tcl group's tool
# workspace. It depends on the Tcl & Tk being in directories called tcl9.* &
# tk8.* up two directories from the TOOL_DIR.
#

1117
1118
1119
1120
1121
1122
1123
1124
1125


1126
1127
1200
1201
1202
1203
1204
1205
1206


1207
1208
1209
1210







-
-
+
+


#

.PHONY: all tcltest binaries libraries doc gendate gentommath_h install
.PHONY: install-binaries install-libraries install-tzdata install-msgs
.PHONY: install-doc install-private-headers test test-tcl runtest shell
.PHONY: gdb depend cleanhelp clean distclean packages install-packages
.PHONY: test-packages clean-packages distclean-packages genstubs html
.PHONY: html-tcl html-tk
.PHONY: iinstall-libraries-zipfs-shared install-libraries-zipfs-static tclzipfile
.PHONY: html-tcl html-tk genscript
.PHONY: tclzipfile

# DO NOT DELETE THIS LINE -- make depend depends on it.

Changes to win/README.

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
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
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
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











-
+










+
-
+
+
+
+
+
+
+
+
+
+



-
+




-
+
-
-
-
-
-




-
-
+
+
-
-
-
-
-







Tcl 9.0 for Windows

1. Introduction
---------------

This is the directory where you configure and compile the Windows
version of Tcl.  This directory also contains source files for Tcl
that are specific to Microsoft Windows.

The information in this file is maintained on the web at:

	http://www.tcl.tk/doc/howto/compile.html#win
	https://www.tcl-lang.org/doc/howto/compile.html#win

2. Compiling Tcl
----------------

In order to compile Tcl for Windows, you need the following:

	Tcl 9.0 Source Distribution (plus any patches)

	and

	Visual Studio 2015 or newer
	Visual C++ 6 or newer

	or

	Linux + MinGW-w64 [https://www.mingw-w64.org/]
	    (win32 or win64)

	or

	Cygwin + MinGW-w64 [https://cygwin.com/install.html]
	    (win32 or win64)

	or

	Linux + MinGW-w64 [http://mingw-w64.sourceforge.net/]
	Darwin + MinGW-w64 [https://www.mingw-w64.org/]
	    (win32 or win64)

	or

	Cygwin + MinGW-w64 [http://cygwin.com/install.html]
	Msys + MinGW-w64 [https://www.mingw-w64.org/]
	    (win32 or win64)

	or

	Darwin + MinGW-w64 [http://mingw-w64.sourceforge.net/]
	    (win32 or win64)

	or

	Msys + MinGW-w64 [http://mingw-w64.sourceforge.net/]
	    (win32 or win64)
	LLVM MinGW [https://github.com/mstorsjo/llvm-mingw/]
	    (win32 or win64, IX86, AMD64 or ARM64)

	or

	Msys + MinGW [http://www.mingw.org/download.shtml]
	    (win32 only)


In practice, this release is built with Visual C++ 6.0 and the TEA
Makefile.

If you are building with Visual C++, in the "win" subdirectory of the
source release, you will find "makefile.vc".  This is the makefile for the
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
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







+
-
-
+
+










-
-
-
+
+
+

-
+
+
+














If you are building with Linux, Cygwin or Msys, you can use the configure
script that lives in the win subdirectory. The Linux/Cygwin/Msys based
configure/build process works just like the UNIX one, so you will want
to refer to ../unix/README for available configure options.

If you want 64-bit executables (x86_64), you need to configure using
the --enable-64bit (or --enable-64bit=arm64) option. Make sure that
the --enable-64bit option. Make sure that the x86_64-w64-mingw32
compiler is present. For Cygwin this compiler can be found in the
the x86_64-w64-mingw32 (or aarch64-w64-mingw32) compiler is present.
For Cygwin the x86_64 compiler can be found in the
"mingw64-x86_64-gcc-core" package, which can be installed through
the normal Cygwin install process. If you only want 32-bit executables,
the "mingw64-i686-gcc-core" package is what you need. For Linux, Darwin
and Msys, you can download a suitable win32 or win64 compiler from
[https://sourceforge.net/projects/mingw-w64/files/]

Use the Makefile "install" target to install Tcl.  It will install it
according to the prefix options you provided in the correct directory
structure.

Note that in order to run tclsh90.exe, you must ensure that tcl90.dll is
on your path, in the system directory, or in the directory containing
tclsh90.exe.
Note that in order to run tclsh90.exe, you must ensure that tcl90.dll,
libtommath.dll and zlib1.dll are on your path, in the system
directory, or in the directory containing tclsh90.exe.

Note: Tcl no longer provides support for Win32s.
Note: Tcl no longer provides support for systems earlier than Windows 7.
You will also need the Windows Universal C runtime (UCRT):
      [https://support.microsoft.com/en-us/topic/update-for-universal-c-runtime-in-windows-c0514201-7fe6-95a3-b0a5-287930f3560c]

3. Test suite
-------------

This distribution contains an extensive test suite for Tcl.  Some of the
tests are timing dependent and will fail from time to time.  If a test is
failing consistently, please send us a bug report with as much detail as
you can manage to our tracker:

	https://core.tcl-lang.org/tcl/reportlist

In order to run the test suite, you build the "test" target using the
appropriate makefile for your compiler.

Changes to win/buildall.vc.bat.

64
65
66
67
68
69
70
71
72


73
74
75
76
77
78
79
64
65
66
67
68
69
70


71
72
73
74
75
76
77
78
79







-
-
+
+







set OPTS=none
if not %SYMBOLS%.==. set OPTS=symbols
nmake -nologo -f makefile.vc release htmlhelp OPTS=%OPTS% %1
if errorlevel 1 goto error

:: Build the static core and shell.
::
set OPTS=static,msvcrt
if not %SYMBOLS%.==. set OPTS=symbols,static,msvcrt
set OPTS=static
if not %SYMBOLS%.==. set OPTS=symbols,static
nmake -nologo -f makefile.vc shell OPTS=%OPTS% %1
if errorlevel 1 goto error

set OPTS=
set SYMBOLS=
goto end

Changes to win/configure.

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

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
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
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


-
+


-
+
+










-
+
+






-
-
+
+




+




+
+
+
+
+
+
+
+



-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+








-
-
-
-
-
-
-








+
-
-
+
+
+
+
+





-
+





-
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-




















-
-
-
+
+
+




-
+
+






-
-
+
+




+














-
+
+

-
-
+
+
+


+
+






-
+
+

-
-
+
+
+

-
+
+

-
-
+
+




+
-
+
+
+
+





-
+

-
+
+

-
+
+







+
+
+
+
+
-
-
+
+
+

+
+
-
+
-


-
+
+
















-
-
+
+



-
-
-
-
-
-
+
+
+
+
+
+
+

-
+





-
+
+



















+







#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69.
# Generated by GNU Autoconf 2.72 for tcl 9.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
# Copyright (C) 1992-1996, 1998-2017, 2020-2023 Free Software Foundation,
# Inc.
#
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##

# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
then :
  emulate sh
  NULLCMD=:
  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '${1+"$@"}'='"$@"'
  setopt NO_GLOB_SUBST
else
  case `(set -o) 2>/dev/null` in #(
else case e in #(
  e) case `(set -o) 2>/dev/null` in #(
  *posix*) :
    set -o posix ;; #(
  *) :
     ;;
esac ;;
esac
fi



# Reset variables that may have inherited troublesome values from
# the environment.

# IFS needs to be set, to space, tab, and newline, in precisely that order.
# (If _AS_PATH_WALK were called with IFS unset, it would have the
# side effect of setting IFS to empty, thus disabling word splitting.)
# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
# Printing a long string crashes Solaris 7 /usr/bin/printf.
as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
# Prefer a ksh shell builtin over an external printf program on Solaris,
# but without wasting forks for bash or zsh.
if test -z "$BASH_VERSION$ZSH_VERSION" \
    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
  as_echo='print -r --'
  as_echo_n='print -rn --'
IFS=" ""	$as_nl"

elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
  as_echo='printf %s\n'
  as_echo_n='printf %s'
PS1='$ '
PS2='> '
else
  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
    as_echo_n='/usr/ucb/echo -n'
  else
    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
    as_echo_n_body='eval
PS4='+ '
      arg=$1;
      case $arg in #(
      *"$as_nl"*)
	expr "X$arg" : "X\\(.*\\)$as_nl";
	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
      esac;
      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
    '
    export as_echo_n_body

# Ensure predictable behavior from utilities with locale-dependent output.
LC_ALL=C
export LC_ALL
    as_echo_n='sh -c $as_echo_n_body as_echo'
  fi
  export as_echo_body
  as_echo='sh -c $as_echo_body as_echo'
fi
LANGUAGE=C
export LANGUAGE

# We cannot yet rely on "unset" to work, but we need these variables
# to be unset--not just set to an empty or harmless value--now, to
# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct
# also avoids known problems related to "unset" and subshell syntax
# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
do eval test \${$as_var+y} \
  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done

# Ensure that fds 0, 1, and 2 are open.
if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
if (exec 3>&2)            ; then :; else exec 2>/dev/null; fi

# The user is always right.
if test "${PATH_SEPARATOR+set}" != set; then
if ${PATH_SEPARATOR+false} :; then
  PATH_SEPARATOR=:
  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
      PATH_SEPARATOR=';'
  }
fi


# IFS
# We need space, tab and new line, in precisely that order.  Quoting is
# there to prevent editors from complaining about space-tab.
# (If _AS_PATH_WALK were called with IFS unset, it would disable word
# splitting by setting IFS to empty value.)
IFS=" ""	$as_nl"

# Find who we are.  Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
  *[\\/]* ) as_myself=$0 ;;
  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    test -r "$as_dir$0" && as_myself=$as_dir$0 && break
  done
IFS=$as_save_IFS

     ;;
esac
# We did not find ourselves, most probably we were run as `sh COMMAND'
# We did not find ourselves, most probably we were run as 'sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
  as_myself=$0
fi
if test ! -f "$as_myself"; then
  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
  printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
  exit 1
fi

# Unset variables that we do not need and which cause bugs (e.g. in
# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
# suppresses any "Segmentation fault" message there.  '((' could
# trigger a bug in pdksh 5.2.14.
for as_var in BASH_ENV ENV MAIL MAILPATH
do eval test x\${$as_var+set} = xset \
  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done
PS1='$ '
PS2='> '
PS4='+ '

# NLS nuisances.
LC_ALL=C
export LC_ALL
LANGUAGE=C
export LANGUAGE

# CDPATH.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH

# Use a proper internal environment variable to ensure we don't fall
  # into an infinite loop, continuously re-executing ourselves.
  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
    _as_can_reexec=no; export _as_can_reexec;
    # We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
  *v*x* | *x*v* ) as_opts=-vx ;;
  *v* ) as_opts=-v ;;
  *x* ) as_opts=-x ;;
  * ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
as_fn_exit 255
# out after a failed 'exec'.
printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
  fi
  # We don't want this to propagate to other subprocesses.
          { _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
  as_bourne_compatible="if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
then :
  emulate sh
  NULLCMD=:
  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '\${1+\"\$@\"}'='\"\$@\"'
  setopt NO_GLOB_SUBST
else
  case \`(set -o) 2>/dev/null\` in #(
else case e in #(
  e) case \`(set -o) 2>/dev/null\` in #(
  *posix*) :
    set -o posix ;; #(
  *) :
     ;;
esac ;;
esac
fi
"
  as_required="as_fn_return () { (exit \$1); }
as_fn_success () { as_fn_return 0; }
as_fn_failure () { as_fn_return 1; }
as_fn_ret_success () { return 0; }
as_fn_ret_failure () { return 1; }

exitcode=0
as_fn_success || { exitcode=1; echo as_fn_success failed.; }
as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
if ( set x; as_fn_ret_success y && test x = \"\$1\" )
then :

else
  exitcode=1; echo positional parameters were not saved.
else case e in #(
  e) exitcode=1; echo positional parameters were not saved. ;;
esac
fi
test x\$exitcode = x0 || exit 1
blah=\$(echo \$(echo blah))
test x\"\$blah\" = xblah || exit 1
test -x / || exit 1"
  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
test \$(( 1 + 1 )) = 2 || exit 1"
  if (eval "$as_required") 2>/dev/null; then :
  if (eval "$as_required") 2>/dev/null
then :
  as_have_required=yes
else
  as_have_required=no
else case e in #(
  e) as_have_required=no ;;
esac
fi
  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
then :

else
  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
else case e in #(
  e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
  as_found=:
  case $as_dir in #(
	 /*)
	   for as_base in sh bash ksh sh5; do
	     # Try only shells that exist, to save several forks.
	     as_shell=$as_dir/$as_base
	     as_shell=$as_dir$as_base
	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
		    as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
then :
  CONFIG_SHELL=$as_shell as_have_required=yes
		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
		   if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
then :
  break 2
fi
fi
	   done;;
       esac
  as_found=false
done
IFS=$as_save_IFS
if $as_found
then :

else case e in #(
$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
  e) if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
	      as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
then :
  CONFIG_SHELL=$SHELL as_have_required=yes
fi ;;
esac
fi; }
fi
IFS=$as_save_IFS


      if test "x$CONFIG_SHELL" != x; then :
      if test "x$CONFIG_SHELL" != x
then :
  export CONFIG_SHELL
             # We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
  *v*x* | *x*v* ) as_opts=-vx ;;
  *v* ) as_opts=-v ;;
  *x* ) as_opts=-x ;;
  * ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
# out after a failed 'exec'.
printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi

    if test x$as_have_required = xno; then :
  $as_echo "$0: This script requires a shell more modern than all"
  $as_echo "$0: the shells that I found on your system."
  if test x${ZSH_VERSION+set} = xset ; then
    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
    if test x$as_have_required = xno
then :
  printf "%s\n" "$0: This script requires a shell more modern than all"
  printf "%s\n" "$0: the shells that I found on your system."
  if test ${ZSH_VERSION+y} ; then
    printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
    printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
  else
    $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
    printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
  fi
  exit 1
fi
fi ;;
esac
fi
fi
SHELL=${CONFIG_SHELL-/bin/sh}
export SHELL
# Unset more variables known to interfere with behavior of common tools.
CLICOLOR_FORCE= GREP_OPTIONS=
unset CLICOLOR_FORCE GREP_OPTIONS

## --------------------- ##
## M4sh Shell Functions. ##
## --------------------- ##
# as_fn_unset VAR
# ---------------
# Portably unset VAR.
as_fn_unset ()
{
  { eval $1=; unset $1;}
}
as_unset=as_fn_unset


# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
as_fn_set_status ()
{
  return $1
318
319
320
321
322
323
324
325

326
327
328
329
330
331
332
333
334

335
336
337
338
339
340
341
324
325
326
327
328
329
330

331
332
333
334
335
336
337
338
339

340
341
342
343
344
345
346
347







-
+








-
+







  case $as_dir in #(
  -*) as_dir=./$as_dir;;
  esac
  test -d "$as_dir" || eval $as_mkdir_p || {
    as_dirs=
    while :; do
      case $as_dir in #(
      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
      *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
      *) as_qdir=$as_dir;;
      esac
      as_dirs="'$as_qdir' $as_dirs"
      as_dir=`$as_dirname -- "$as_dir" ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$as_dir" : 'X\(//\)[^/]' \| \
	 X"$as_dir" : 'X\(//\)$' \| \
	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$as_dir" |
printf "%s\n" X"$as_dir" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
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
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







-
+
+




-
-
+
+


-
+
+







-
+
+




-
-
+
+


-
+
+













-
+

-
+







} # as_fn_executable_p
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
then :
  eval 'as_fn_append ()
  {
    eval $1+=\$2
  }'
else
  as_fn_append ()
else case e in #(
  e) as_fn_append ()
  {
    eval $1=\$$1\$2
  }
  } ;;
esac
fi # as_fn_append

# as_fn_arith ARG...
# ------------------
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
then :
  eval 'as_fn_arith ()
  {
    as_val=$(( $* ))
  }'
else
  as_fn_arith ()
else case e in #(
  e) as_fn_arith ()
  {
    as_val=`expr "$@" || test $? -eq 1`
  }
  } ;;
esac
fi # as_fn_arith


# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
  as_status=$1; test $as_status -eq 0 && as_status=1
  if test "$4"; then
    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
  fi
  $as_echo "$as_me: error: $2" >&2
  printf "%s\n" "$as_me: error: $2" >&2
  as_fn_exit $as_status
} # as_fn_error

if expr a : '\(a\)' >/dev/null 2>&1 &&
   test "X`expr 00001 : '.*\(...\)'`" = X001; then
  as_expr=expr
else
435
436
437
438
439
440
441
442

443
444
445
446
447
448
449
445
446
447
448
449
450
451

452
453
454
455
456
457
458
459







-
+







  as_dirname=false
fi

as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
	 X"$0" : 'X\(//\)$' \| \
	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X/"$0" |
printf "%s\n" X/"$0" |
    sed '/^.*\/\([^/][^/]*\)\/*$/{
	    s//\1/
	    q
	  }
	  /^X\/\(\/\/\)$/{
	    s//\1/
	    q
468
469
470
471
472
473
474


475
476
477
478
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
478
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







+
+











-
+













+
+
+
+












+
+
+
+
+
+












-
-
-
+
+
+







  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
  sed -n '
    p
    /[$]LINENO/=
  ' <$as_myself |
    sed '
      t clear
      :clear
      s/[$]LINENO.*/&-/
      t lineno
      b
      :lineno
      N
      :loop
      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
      t loop
      s/-\n.*//
    ' >$as_me.lineno &&
  chmod +x "$as_me.lineno" ||
    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
    { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }

  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
  # already done that, so ensure we don't try to do so again and fall
  # in an infinite loop.  This has already happened in practice.
  _as_can_reexec=no; export _as_can_reexec
  # Don't try to exec as it changes $[0], causing all sort of problems
  # (the dirname of $[0] is not the place where we might find the
  # original and so on.  Autoconf is especially sensitive to this).
  . "./$as_me.lineno"
  # Exit status is that of the last command.
  exit
}


# Determine whether it's possible to make 'echo' print without a newline.
# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
  case `echo 'xy\c'` in
  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
  xy)  ECHO_C='\c';;
  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
       ECHO_T='	';;
  esac;;
*)
  ECHO_N='-n';;
esac

# For backward compatibility with old third-party macros, we provide
# the shell variables $as_echo and $as_echo_n.  New code should use
# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
as_echo='printf %s\n'
as_echo_n='printf %s'

rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
  rm -f conf$$.dir/conf$$.file
else
  rm -f conf$$.dir
  mkdir conf$$.dir 2>/dev/null
fi
if (echo >conf$$.file) 2>/dev/null; then
  if ln -s conf$$.file conf$$ 2>/dev/null; then
    as_ln_s='ln -s'
    # ... but there are two gotchas:
    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
    # In both cases, we have to default to `cp -pR'.
    # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail.
    # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable.
    # In both cases, we have to default to 'cp -pR'.
    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
      as_ln_s='cp -pR'
  elif ln conf$$.file conf$$ 2>/dev/null; then
    as_ln_s=ln
  else
    as_ln_s='cp -pR'
  fi
544
545
546
547
548
549
550
551


552
553
554


555
556
557
558
559
560
561
566
567
568
569
570
571
572

573
574
575
576

577
578
579
580
581
582
583
584
585







-
+
+


-
+
+







  as_mkdir_p=false
fi

as_test_x='test -x'
as_executable_p=as_fn_executable_p

# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated

# Sed expression to map a string onto a valid variable name.
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
as_tr_sh="eval sed '$as_sed_sh'" # deprecated


test -n "$DJDIR" || exec 7<&0 </dev/null
exec 6>&1

# Name of the host.
# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
571
572
573
574
575
576
577
578
579
580
581
582
583






584
585
586
587
588
589
590



591
592

593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617









618
619
620
621

622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
595
596
597
598
599
600
601






602
603
604
605
606
607
608
609
610
611



612
613
614
615

616



617





618
619



620
621



622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656






657
658
659
660
661
662
663







-
-
-
-
-
-
+
+
+
+
+
+




-
-
-
+
+
+

-
+
-
-
-

-
-
-
-
-


-
-
-


-
-
-






+
+
+
+
+
+
+
+
+




+















-
-
-
-
-
-







LIBOBJS=
cross_compiling=no
subdirs=
MFLAGS=
MAKEFLAGS=

# Identity of this package.
PACKAGE_NAME=
PACKAGE_TARNAME=
PACKAGE_VERSION=
PACKAGE_STRING=
PACKAGE_BUGREPORT=
PACKAGE_URL=
PACKAGE_NAME='tcl'
PACKAGE_TARNAME='tcl'
PACKAGE_VERSION='9.0'
PACKAGE_STRING='tcl 9.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''

ac_unique_file="../generic/tcl.h"
# Factoring default headers for most tests.
ac_includes_default="\
#include <stdio.h>
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#include <stddef.h>
#ifdef HAVE_STDIO_H
# include <stdio.h>
#endif
#ifdef HAVE_SYS_STAT_H
#ifdef HAVE_STDLIB_H
# include <sys/stat.h>
#endif
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# ifdef HAVE_STDLIB_H
#  include <stdlib.h>
# endif
#endif
#ifdef HAVE_STRING_H
# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
#  include <memory.h>
# endif
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif"

ac_header_c_list=
ac_subst_vars='LTLIBOBJS
LIBOBJS
RES
RC_DEFINES
RC_DEFINE
RC_INCLUDE
RC_TYPE
RC_OUT
TCL_REG_MINOR_VERSION
TCL_REG_MAJOR_VERSION
TCL_REG_VERSION
TCL_DDE_MINOR_VERSION
TCL_DDE_MAJOR_VERSION
TCL_DDE_VERSION
TCL_PACKAGE_PATH
TCL_LIB_VERSIONS_OK
TCL_EXP_FILE
TCL_BUILD_EXP_FILE
TCL_NEEDS_EXP_FILE
TCL_LD_SEARCH_FLAGS
TCL_CC_SEARCH_FLAGS
TCL_BUILD_LIB_SPEC
MAKE_EXE
MAKE_DLL
POST_MAKE_LIB
MAKE_STUB_LIB
MAKE_LIB
LIBRARIES
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
676
677
678
679
680
681
682

683
684
685
686
687
688
689







-







LDFLAGS_CONSOLE
LDFLAGS_OPTIMIZE
LDFLAGS_DEBUG
CC_EXENAME
CC_OBJNAME
DEPARG
EXTRA_CFLAGS
CFG_TCL_EXPORT_FILE_SUFFIX
CFG_TCL_UNSHARED_LIB_SUFFIX
CFG_TCL_SHARED_LIB_SUFFIX
TCL_BIN_DIR
TCL_SRC_DIR
TCL_DLL_FILE
TCL_BUILD_STUB_LIB_PATH
TCL_BUILD_STUB_LIB_SPEC
692
693
694
695
696
697
698

699
700
701
702
703
704
705
706
707
708
709
710
711


712
713
714
715
716
717

718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745



746
747
748
749
750
751
752







+













+
+






+











-
-
-







TCL_MINOR_VERSION
TCL_MAJOR_VERSION
TCL_VERSION
MACHINE
TCL_WIN_VERSION
VC_MANIFEST_EMBED_EXE
VC_MANIFEST_EMBED_DLL
CPP
LDFLAGS_DEFAULT
CFLAGS_DEFAULT
INSTALL_MSGS
INSTALL_LIBRARIES
TCL_ZIP_FILE
ZIPFS_BUILD
ZIP_INSTALL_OBJS
ZIP_PROG_VFSSEARCH
ZIP_PROG_OPTIONS
ZIP_PROG
TCLSH_PROG
EXEEXT_FOR_BUILD
CC_FOR_BUILD
TCL_TOMMATH_LIB_NAME
TCL_ZLIB_LIB_NAME
TOMMATH_OBJS
ZLIB_OBJS
TOMMATH_LIBS
ZLIB_LIBS
TOMMATH_DLL_FILE
ZLIB_DLL_FILE
CFLAGS_NOLTO
CFLAGS_WARNING
CFLAGS_OPTIMIZE
CFLAGS_DEBUG
DL_LIBS
WINE
CYGPATH
SHARED_BUILD
SET_MAKE
RC
RANLIB
AR
EGREP
GREP
CPP
OBJEXT
EXEEXT
ac_ct_CC
CPPFLAGS
LDFLAGS
CFLAGS
CC
751
752
753
754
755
756
757

758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779







+







pdfdir
dvidir
htmldir
infodir
docdir
oldincludedir
includedir
runstatedir
localstatedir
sharedstatedir
sysconfdir
datadir
datarootdir
libexecdir
sbindir
828
829
830
831
832
833
834

835
836
837

838
839
840
841
842
843
844
843
844
845
846
847
848
849
850
851
852

853
854
855
856
857
858
859
860







+


-
+







sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
datarootdir='${prefix}/share'
datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE}'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
infodir='${datarootdir}/info'
htmldir='${docdir}'
dvidir='${docdir}'
pdfdir='${docdir}'
psdir='${docdir}'
libdir='${exec_prefix}/lib'
localedir='${datarootdir}/locale'
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879


880
881
882
883
884
885
886







-
-








  case $ac_option in
  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
  *=)   ac_optarg= ;;
  *)    ac_optarg=yes ;;
  esac

  # Accept the important Cygnus configure options, so we can diagnose typos.

  case $ac_dashdash$ac_option in
  --)
    ac_dashdash=yes ;;

  -bindir | --bindir | --bindi | --bind | --bin | --bi)
    ac_prev=bindir ;;
  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
899
900
901
902
903
904
905
906

907
908

909
910
911
912
913
914
915
913
914
915
916
917
918
919

920
921

922
923
924
925
926
927
928
929







-
+

-
+







  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
    datarootdir=$ac_optarg ;;

  -disable-* | --disable-*)
    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid feature name: $ac_useropt"
      as_fn_error $? "invalid feature name: '$ac_useropt'"
    ac_useropt_orig=$ac_useropt
    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"enable_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
925
926
927
928
929
930
931
932

933
934

935
936
937
938
939
940
941
939
940
941
942
943
944
945

946
947

948
949
950
951
952
953
954
955







-
+

-
+







  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
    dvidir=$ac_optarg ;;

  -enable-* | --enable-*)
    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid feature name: $ac_useropt"
      as_fn_error $? "invalid feature name: '$ac_useropt'"
    ac_useropt_orig=$ac_useropt
    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"enable_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
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







+
+
+
+
+
+
+
+
+







    ac_prev=psdir ;;
  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
    psdir=$ac_optarg ;;

  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
  | -silent | --silent | --silen | --sile | --sil)
    silent=yes ;;

  -runstatedir | --runstatedir | --runstatedi | --runstated \
  | --runstate | --runstat | --runsta | --runst | --runs \
  | --run | --ru | --r)
    ac_prev=runstatedir ;;
  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
  | --run=* | --ru=* | --r=*)
    runstatedir=$ac_optarg ;;

  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
    ac_prev=sbindir ;;
  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
  | --sbi=* | --sb=*)
    sbindir=$ac_optarg ;;

1129
1130
1131
1132
1133
1134
1135
1136

1137
1138

1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152

1153
1154

1155
1156
1157
1158
1159
1160
1161
1152
1153
1154
1155
1156
1157
1158

1159
1160

1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174

1175
1176

1177
1178
1179
1180
1181
1182
1183
1184







-
+

-
+













-
+

-
+







  -version | --version | --versio | --versi | --vers | -V)
    ac_init_version=: ;;

  -with-* | --with-*)
    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid package name: $ac_useropt"
      as_fn_error $? "invalid package name: '$ac_useropt'"
    ac_useropt_orig=$ac_useropt
    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"with_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
    eval with_$ac_useropt=\$ac_optarg ;;

  -without-* | --without-*)
    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
    # Reject names that are not valid shell variable names.
    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
      as_fn_error $? "invalid package name: $ac_useropt"
      as_fn_error $? "invalid package name: '$ac_useropt'"
    ac_useropt_orig=$ac_useropt
    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
    case $ac_user_opts in
      *"
"with_$ac_useropt"
"*) ;;
      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
	 ac_unrecognized_sep=', ';;
    esac
1175
1176
1177
1178
1179
1180
1181
1182
1183


1184
1185
1186
1187
1188
1189
1190
1191

1192
1193
1194
1195
1196
1197
1198

1199
1200

1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216

1217
1218
1219
1220
1221
1222
1223
1224

1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241

1242
1243
1244
1245
1246
1247
1248
1198
1199
1200
1201
1202
1203
1204


1205
1206
1207
1208
1209
1210
1211
1212
1213

1214
1215
1216
1217
1218
1219
1220

1221
1222

1223
1224
1225
1226
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







-
-
+
+







-
+






-
+

-
+















-
+







-
+
















-
+







  -x-libraries | --x-libraries | --x-librarie | --x-librari \
  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
    ac_prev=x_libraries ;;
  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
    x_libraries=$ac_optarg ;;

  -*) as_fn_error $? "unrecognized option: \`$ac_option'
Try \`$0 --help' for more information"
  -*) as_fn_error $? "unrecognized option: '$ac_option'
Try '$0 --help' for more information"
    ;;

  *=*)
    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
    # Reject names that are not valid shell variable names.
    case $ac_envvar in #(
      '' | [0-9]* | *[!_$as_cr_alnum]* )
      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
      as_fn_error $? "invalid variable name: '$ac_envvar'" ;;
    esac
    eval $ac_envvar=\$ac_optarg
    export $ac_envvar ;;

  *)
    # FIXME: should be removed in autoconf 3.0.
    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
    printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
      printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
    ;;

  esac
done

if test -n "$ac_prev"; then
  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
  as_fn_error $? "missing argument to $ac_option"
fi

if test -n "$ac_unrecognized_opts"; then
  case $enable_option_checking in
    no) ;;
    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
    *)     printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
  esac
fi

# Check all directory arguments for consistency.
for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
		datadir sysconfdir sharedstatedir localstatedir includedir \
		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
		libdir localedir mandir
		libdir localedir mandir runstatedir
do
  eval ac_val=\$$ac_var
  # Remove trailing slashes.
  case $ac_val in
    */ )
      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
      eval $ac_var=\$ac_val;;
  esac
  # Be sure to have absolute directory names.
  case $ac_val in
    [\\/$]* | ?:[\\/]* )  continue;;
    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
  esac
  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
done

# There might be people who depend on the old broken behavior: `$host'
# There might be people who depend on the old broken behavior: '$host'
# used to hold the argument of --host etc.
# FIXME: To remove some day.
build=$build_alias
host=$host_alias
target=$target_alias

# FIXME: To remove some day.
1273
1274
1275
1276
1277
1278
1279
1280

1281
1282
1283
1284
1285
1286
1287
1296
1297
1298
1299
1300
1301
1302

1303
1304
1305
1306
1307
1308
1309
1310







-
+







  ac_srcdir_defaulted=yes
  # Try the directory containing this script, then the parent directory.
  ac_confdir=`$as_dirname -- "$as_myself" ||
$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$as_myself" : 'X\(//\)[^/]' \| \
	 X"$as_myself" : 'X\(//\)$' \| \
	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$as_myself" |
printf "%s\n" X"$as_myself" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
1302
1303
1304
1305
1306
1307
1308
1309

1310
1311
1312
1313
1314
1315
1316
1325
1326
1327
1328
1329
1330
1331

1332
1333
1334
1335
1336
1337
1338
1339







-
+







else
  ac_srcdir_defaulted=no
fi
if test ! -r "$srcdir/$ac_unique_file"; then
  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
fi
ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
ac_msg="sources are in $srcdir, but 'cd $srcdir' does not work"
ac_abs_confdir=`(
	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
	pwd)`
# When building in place, set srcdir=.
if test "$ac_abs_confdir" = "$ac_pwd"; then
  srcdir=.
fi
1330
1331
1332
1333
1334
1335
1336
1337

1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351

1352
1353

1354
1355

1356
1357
1358
1359
1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397



1398
1399
1400
1401
1402
1403
1404
1353
1354
1355
1356
1357
1358
1359

1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408

1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420

1421
1422
1423
1424
1425
1426
1427
1428
1429
1430







-
+













-
+

-
+

-
+







-
-
-
-
+
+
+
+










+








-
+











-
+
+
+







#
# Report the --help message.
#
if test "$ac_init_help" = "long"; then
  # Omit some internal or obsolete options to make the list less imposing.
  # This message is too long to be a string in the A/UX 3.1 sh.
  cat <<_ACEOF
\`configure' configures this package to adapt to many kinds of systems.
'configure' configures tcl 9.0 to adapt to many kinds of systems.

Usage: $0 [OPTION]... [VAR=VALUE]...

To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE.  See below for descriptions of some of the useful variables.

Defaults for the options are specified in brackets.

Configuration:
  -h, --help              display this help and exit
      --help=short        display options specific to this package
      --help=recursive    display the short help of all the included packages
  -V, --version           display version information and exit
  -q, --quiet, --silent   do not print \`checking ...' messages
  -q, --quiet, --silent   do not print 'checking ...' messages
      --cache-file=FILE   cache test results in FILE [disabled]
  -C, --config-cache      alias for \`--cache-file=config.cache'
  -C, --config-cache      alias for '--cache-file=config.cache'
  -n, --no-create         do not create output files
      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
      --srcdir=DIR        find the sources in DIR [configure dir or '..']

Installation directories:
  --prefix=PREFIX         install architecture-independent files in PREFIX
                          [$ac_default_prefix]
  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
                          [PREFIX]

By default, \`make install' will install all the files in
\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
an installation prefix other than \`$ac_default_prefix' using \`--prefix',
for instance \`--prefix=\$HOME'.
By default, 'make install' will install all the files in
'$ac_default_prefix/bin', '$ac_default_prefix/lib' etc.  You can specify
an installation prefix other than '$ac_default_prefix' using '--prefix',
for instance '--prefix=\$HOME'.

For better control, use the options below.

Fine tuning of the installation directories:
  --bindir=DIR            user executables [EPREFIX/bin]
  --sbindir=DIR           system admin executables [EPREFIX/sbin]
  --libexecdir=DIR        program executables [EPREFIX/libexec]
  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
  --libdir=DIR            object code libraries [EPREFIX/lib]
  --includedir=DIR        C header files [PREFIX/include]
  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
  --infodir=DIR           info documentation [DATAROOTDIR/info]
  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
  --mandir=DIR            man documentation [DATAROOTDIR/man]
  --docdir=DIR            documentation root [DATAROOTDIR/doc/PACKAGE]
  --docdir=DIR            documentation root [DATAROOTDIR/doc/tcl]
  --htmldir=DIR           html documentation [DOCDIR]
  --dvidir=DIR            dvi documentation [DOCDIR]
  --pdfdir=DIR            pdf documentation [DOCDIR]
  --psdir=DIR             ps documentation [DOCDIR]
_ACEOF

  cat <<\_ACEOF
_ACEOF
fi

if test -n "$ac_init_help"; then

  case $ac_init_help in
     short | recursive ) echo "Configuration of tcl 9.0:";;
   esac
  cat <<\_ACEOF

Optional Features:
  --disable-option-checking  ignore unrecognized --enable/--with options
  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
  --enable-shared         build and link with shared libraries (default: on)
1419
1420
1421
1422
1423
1424
1425
1426

1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445

1446
1447

1448
1449
1450
1451
1452
1453
1454
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
1474
1475
1476
1477
1478
1479
1480







-
+


















-
+

-
+







  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
              nonstandard directory <lib dir>
  LIBS        libraries to pass to the linker, e.g. -l<library>
  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
              you have headers in a nonstandard directory <include dir>
  CPP         C preprocessor

Use these variables to override the choices made by `configure' or to help
Use these variables to override the choices made by 'configure' or to help
it to find libraries and programs with nonstandard names/locations.

Report bugs to the package provider.
_ACEOF
ac_status=$?
fi

if test "$ac_init_help" = "recursive"; then
  # If there are subdirs, report their specific --help.
  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
    test -d "$ac_dir" ||
      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
      continue
    ac_builddir=.

case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
  ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
  # A ".." for each directory in $ac_dir_suffix.
  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
  ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
  case $ac_top_builddir_sub in
  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
  esac ;;
esac
ac_abs_top_builddir=$ac_pwd
ac_abs_builddir=$ac_pwd$ac_dir_suffix
1468
1469
1470
1471
1472
1473
1474
1475


1476
1477
1478
1479
1480
1481
1482
1483

1484
1485
1486
1487
1488
1489
1490
1491
1492
1493


1494
1495

1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512

1513
1514
1515
1516
1517
1518
1519

1520
1521
1522
1523
1524
1525
1526
1527

1528
1529
1530
1531


1532
1533
1534


1535
1536
1537


1538
1539
1540
1541
1542






























































































1543
1544
1545
1546
1547
1548
1549
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781



1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799


1800
1801

1802
1803
1804
1805
1806
1807
1808
1494
1495
1496
1497
1498
1499
1500

1501
1502
1503
1504
1505
1506
1507
1508
1509

1510
1511
1512
1513
1514
1515
1516
1517
1518


1519
1520
1521

1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538

1539
1540
1541
1542
1543
1544
1545

1546
1547
1548
1549
1550
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







-
+
+







-
+








-
-
+
+

-
+
















-
+






-
+







-
+



-
+
+

-
-
+
+


-
+
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













-
+







-
+



+
-
+

-
-
+
+


-
+
+





-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+
+
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-

-




-
-
+
+

-
+







    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
    ac_top_srcdir=$ac_top_build_prefix$srcdir
    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix

    cd "$ac_dir" || { ac_status=$?; continue; }
    # Check for guested configure.
    # Check for configure.gnu first; this name is used for a wrapper for
    # Metaconfig's "Configure" on case-insensitive file systems.
    if test -f "$ac_srcdir/configure.gnu"; then
      echo &&
      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
    elif test -f "$ac_srcdir/configure"; then
      echo &&
      $SHELL "$ac_srcdir/configure" --help=recursive
    else
      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
      printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
    fi || ac_status=$?
    cd "$ac_pwd" || { ac_status=$?; break; }
  done
fi

test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
  cat <<\_ACEOF
configure
generated by GNU Autoconf 2.69
tcl configure 9.0
generated by GNU Autoconf 2.72

Copyright (C) 2012 Free Software Foundation, Inc.
Copyright (C) 2023 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
  exit
fi

## ------------------------ ##
## Autoconf initialization. ##
## ------------------------ ##

# ac_fn_c_try_compile LINENO
# --------------------------
# Try to compile conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_compile ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  rm -f conftest.$ac_objext
  rm -f conftest.$ac_objext conftest.beam
  if { { ac_try="$ac_compile"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_compile") 2>conftest.err
  ac_status=$?
  if test -s conftest.err; then
    grep -v '^ *+' conftest.err >conftest.er1
    cat conftest.er1 >&5
    mv -f conftest.er1 conftest.err
  fi
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; } && {
	 test -z "$ac_c_werror_flag" ||
	 test ! -s conftest.err
       } && test -s conftest.$ac_objext; then :
       } && test -s conftest.$ac_objext
then :
  ac_retval=0
else
  $as_echo "$as_me: failed program was:" >&5
else case e in #(
  e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

	ac_retval=1
	ac_retval=1 ;;
esac
fi
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
  as_fn_set_status $ac_retval

} # ac_fn_c_try_compile

# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
# Tests whether HEADER exists and can be compiled using the include files in
# INCLUDES, setting the cache variable VAR accordingly.
ac_fn_c_check_header_compile ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
printf %s "checking for $2... " >&6; }
if eval test \${$3+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$4
#include <$2>
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  eval "$3=yes"
else case e in #(
  e) eval "$3=no" ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
eval ac_res=\$$3
	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

} # ac_fn_c_check_header_compile

# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
# -------------------------------------------
# Tests whether TYPE exists after having included INCLUDES, setting cache
# variable VAR accordingly.
ac_fn_c_check_type ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
printf %s "checking for $2... " >&6; }
if eval test \${$3+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) eval "$3=no"
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$4
int
main (void)
{
if (sizeof ($2))
	 return 0;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$4
int
main (void)
{
if (sizeof (($2)))
	    return 0;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :

else case e in #(
  e) eval "$3=yes" ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
eval ac_res=\$$3
	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

} # ac_fn_c_check_type

# ac_fn_c_try_cpp LINENO
# ----------------------
# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_cpp ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  if { { ac_try="$ac_cpp conftest.$ac_ext"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
  ac_status=$?
  if test -s conftest.err; then
    grep -v '^ *+' conftest.err >conftest.er1
    cat conftest.er1 >&5
    mv -f conftest.er1 conftest.err
  fi
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; } > conftest.i && {
	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
	 test ! -s conftest.err
       }
       }; then :
then :
  ac_retval=0
else
  $as_echo "$as_me: failed program was:" >&5
else case e in #(
  e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

    ac_retval=1
    ac_retval=1 ;;
esac
fi
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
  as_fn_set_status $ac_retval

} # ac_fn_c_try_cpp

ac_configure_args_raw=
# ac_fn_c_try_run LINENO
# ----------------------
# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
# that executables *can* be run.
ac_fn_c_try_run ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  if { { ac_try="$ac_link"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
  (eval "$ac_link") 2>&5
  ac_status=$?
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
  { { case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
  (eval "$ac_try") 2>&5
  ac_status=$?
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }; }; then :
  ac_retval=0
for ac_arg
else
  $as_echo "$as_me: program exited with status $ac_status" >&5
       $as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

       ac_retval=$ac_status
do
  case $ac_arg in
fi
  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
  as_fn_set_status $ac_retval

  *\'*)
} # ac_fn_c_try_run

    ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
# Tests whether HEADER exists, giving a warning if it cannot be compiled using
# the include files in INCLUDES and setting the cache variable VAR
# accordingly.
ac_fn_c_check_header_mongrel ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  if eval \${$3+:} false; then :
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
  $as_echo_n "(cached) " >&6
fi
eval ac_res=\$$3
	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
else
  esac
  # Is the header compilable?
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
$as_echo_n "checking $2 usability... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$4
#include <$2>
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  ac_header_compiler=yes
else
  ac_header_compiler=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
$as_echo "$ac_header_compiler" >&6; }

  as_fn_append ac_configure_args_raw " '$ac_arg'"
# Is the header present?
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
$as_echo_n "checking $2 presence... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <$2>
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
  ac_header_preproc=yes
else
  ac_header_preproc=no
fi
rm -f conftest.err conftest.i conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
$as_echo "$ac_header_preproc" >&6; }

done
# So?  What about this header?
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
  yes:no: )
    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
    ;;
  no:yes:* )
    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
    ;;
esac
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
  $as_echo_n "(cached) " >&6
else
  eval "$3=\$ac_header_compiler"
fi
eval ac_res=\$$3
	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
fi
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

} # ac_fn_c_check_header_mongrel

case $ac_configure_args_raw in
# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
# Tests whether HEADER exists and can be compiled using the include files in
# INCLUDES, setting the cache variable VAR accordingly.
ac_fn_c_check_header_compile ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
  $as_echo_n "(cached) " >&6
  *$as_nl*)
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$4
#include <$2>
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  eval "$3=yes"
else
  eval "$3=no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
eval ac_res=\$$3
    ac_safe_unquote= ;;
	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

  *)
} # ac_fn_c_check_header_compile

    ac_unsafe_z='|&;<>()$`\\"*?[ ''	' # This string ends in space, tab.
# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
# -------------------------------------------
# Tests whether TYPE exists after having included INCLUDES, setting cache
# variable VAR accordingly.
ac_fn_c_check_type ()
    ac_unsafe_a="$ac_unsafe_z#~"
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
  $as_echo_n "(cached) " >&6
else
  eval "$3=no"
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$4
int
main ()
{
if (sizeof ($2))
	 return 0;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$4
int
main ()
{
if (sizeof (($2)))
	    return 0;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

else
    ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
    ac_configure_args_raw=`      printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
esac
  eval "$3=yes"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
eval ac_res=\$$3
	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

} # ac_fn_c_check_type
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.

It was created by $as_me, which was
generated by GNU Autoconf 2.69.  Invocation command line was
It was created by tcl $as_me 9.0, which was
generated by GNU Autoconf 2.72.  Invocation command line was

  $ $0 $@
  $ $0$ac_configure_args_raw

_ACEOF
exec 5>>config.log
{
cat <<_ASUNAME
## --------- ##
## Platform. ##
1827
1828
1829
1830
1831
1832
1833

1834
1835





1836
1837
1838
1839
1840
1841
1842
1758
1759
1760
1761
1762
1763
1764
1765


1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777







+
-
-
+
+
+
+
+








_ASUNAME

as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    $as_echo "PATH: $as_dir"
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    printf "%s\n" "PATH: $as_dir"
  done
IFS=$as_save_IFS

} >&5

cat >&5 <<_ACEOF

1863
1864
1865
1866
1867
1868
1869
1870

1871
1872
1873
1874
1875
1876
1877
1798
1799
1800
1801
1802
1803
1804

1805
1806
1807
1808
1809
1810
1811
1812







-
+







  do
    case $ac_arg in
    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
    | -silent | --silent | --silen | --sile | --sil)
      continue ;;
    *\'*)
      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
      ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
    esac
    case $ac_pass in
    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
    2)
      as_fn_append ac_configure_args1 " '$ac_arg'"
      if test $ac_must_keep_next = true; then
	ac_must_keep_next=false # Got value, back to normal.
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
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845

1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856


1857
1858
1859
1860
1861
1862
1863
1864
1865







+
+




-
+










-
-
+
+








# When interrupted or exit'd, cleanup temporary files, and complete
# config.log.  We remove comments because anyway the quotes in there
# would cause problems or look ugly.
# WARNING: Use '\'' to represent an apostrophe within the trap.
# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
  # Sanitize IFS.
  IFS=" ""	$as_nl"
  # Save into config.log some information that might help in debugging.
  {
    echo

    $as_echo "## ---------------- ##
    printf "%s\n" "## ---------------- ##
## Cache variables. ##
## ---------------- ##"
    echo
    # The following way of writing the cache mishandles newlines in values,
(
  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
    eval ac_val=\$$ac_var
    case $ac_val in #(
    *${as_nl}*)
      case $ac_var in #(
      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
      *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
      esac
      case $ac_var in #(
      _ | IFS | as_nl) ;; #(
      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
      *) { eval $ac_var=; unset $ac_var;} ;;
      esac ;;
    esac
1938
1939
1940
1941
1942
1943
1944
1945

1946
1947
1948
1949
1950
1951
1952
1953

1954
1955

1956
1957
1958
1959
1960

1961
1962
1963
1964
1965
1966
1967
1968

1969
1970

1971
1972
1973
1974
1975
1976

1977
1978
1979
1980
1981
1982
1983
1984
1985


1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999

2000
2001
2002
2003
2004

2005
2006
2007
2008

2009
2010
2011
2012

2013
2014
2015
2016

2017
2018
2019
2020

2021
2022
2023
2024

2025
2026
2027
2028
2029
2030
2031
2032
2033
2034

2035
2036
2037
2038
2039
2040

2041
2042
2043

2044
2045

2046

2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103


2104
2105
2106
2107


2108
2109
2110
2111
2112
2113




2114
2115
2116
2117
2118
2119

2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133






2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146

2147
2148
2149
2150
2151
2152
2153
2154
2155
2156

2157
2158
2159
2160
2161
2162
2163
1875
1876
1877
1878
1879
1880
1881

1882
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

1958

1959

1960

1961
1962

1963
1964




1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975


1976
1977
1978

1979
1980
1981
1982
1983
1984
1985
1986


1987
1988
1989
1990
1991
1992
1993
1994


1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413

2414
2415
2416
2417
2418
2419
2420
2421







-
+







-
+

-
+




-
+







-
+

-
+





-
+







-
-
+
+













-
+



-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-

-
-
+
-




-
-

-
-
+
-
-
-
-

-
+
-

-
+
-

+
-
+

-
-
-
-
+
+
+
+
+
+
+
+
+


-
-
+
+

-
+







-
-
+
+






-
-
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










-
-
+
+


-
-
+
+








-
-
+
+


-
-
+
+


-
-
-
-
+
+
+
+





-
+









-
-
-
-
-
+
+
+
+
+
+













+









-
+







      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
      ;;
    esac |
    sort
)
    echo

    $as_echo "## ----------------- ##
    printf "%s\n" "## ----------------- ##
## Output variables. ##
## ----------------- ##"
    echo
    for ac_var in $ac_subst_vars
    do
      eval ac_val=\$$ac_var
      case $ac_val in
      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
      *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
      esac
      $as_echo "$ac_var='\''$ac_val'\''"
      printf "%s\n" "$ac_var='\''$ac_val'\''"
    done | sort
    echo

    if test -n "$ac_subst_files"; then
      $as_echo "## ------------------- ##
      printf "%s\n" "## ------------------- ##
## File substitutions. ##
## ------------------- ##"
      echo
      for ac_var in $ac_subst_files
      do
	eval ac_val=\$$ac_var
	case $ac_val in
	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
	*\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
	esac
	$as_echo "$ac_var='\''$ac_val'\''"
	printf "%s\n" "$ac_var='\''$ac_val'\''"
      done | sort
      echo
    fi

    if test -s confdefs.h; then
      $as_echo "## ----------- ##
      printf "%s\n" "## ----------- ##
## confdefs.h. ##
## ----------- ##"
      echo
      cat confdefs.h
      echo
    fi
    test "$ac_signal" != 0 &&
      $as_echo "$as_me: caught signal $ac_signal"
    $as_echo "$as_me: exit $exit_status"
      printf "%s\n" "$as_me: caught signal $ac_signal"
    printf "%s\n" "$as_me: exit $exit_status"
  } >&5
  rm -f core *.core core.conftest.* &&
    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
    exit $exit_status
' 0
for ac_signal in 1 2 13 15; do
  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
done
ac_signal=0

# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -f -r conftest* confdefs.h

$as_echo "/* confdefs.h */" > confdefs.h
printf "%s\n" "/* confdefs.h */" > confdefs.h

# Predefined preprocessor variables.

cat >>confdefs.h <<_ACEOF
#define PACKAGE_NAME "$PACKAGE_NAME"
printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
_ACEOF

cat >>confdefs.h <<_ACEOF
#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
_ACEOF

cat >>confdefs.h <<_ACEOF
#define PACKAGE_VERSION "$PACKAGE_VERSION"
printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
_ACEOF

cat >>confdefs.h <<_ACEOF
#define PACKAGE_STRING "$PACKAGE_STRING"
printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
_ACEOF

cat >>confdefs.h <<_ACEOF
#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
_ACEOF

cat >>confdefs.h <<_ACEOF
#define PACKAGE_URL "$PACKAGE_URL"
printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
_ACEOF


# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.
ac_site_file1=NONE
ac_site_file2=NONE
if test -n "$CONFIG_SITE"; then
  # We do not want a PATH search for config.site.
  case $CONFIG_SITE in #((
  ac_site_files="$CONFIG_SITE"
    -*)  ac_site_file1=./$CONFIG_SITE;;
    */*) ac_site_file1=$CONFIG_SITE;;
    *)   ac_site_file1=./$CONFIG_SITE;;
  esac
elif test "x$prefix" != xNONE; then
  ac_site_file1=$prefix/share/config.site
  ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
  ac_site_file2=$prefix/etc/config.site
else
  ac_site_file1=$ac_default_prefix/share/config.site
  ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
  ac_site_file2=$ac_default_prefix/etc/config.site
fi

for ac_site_file in "$ac_site_file1" "$ac_site_file2"
for ac_site_file in $ac_site_files
do
  test "x$ac_site_file" = xNONE && continue
  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
$as_echo "$as_me: loading site script $ac_site_file" >&6;}
  case $ac_site_file in #(
  */*) :
     ;; #(
  *) :
    ac_site_file=./$ac_site_file ;;
esac
  if test -f "$ac_site_file" && test -r "$ac_site_file"; then
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
    sed 's/^/| /' "$ac_site_file" >&5
    . "$ac_site_file" \
      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
      || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5; }
See 'config.log' for more details" "$LINENO" 5; }
  fi
done

if test -r "$cache_file"; then
  # Some versions of bash will fail to source /dev/null (special files
  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
$as_echo "$as_me: loading cache $cache_file" >&6;}
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
    case $cache_file in
      [\\/]* | ?:[\\/]* ) . "$cache_file";;
      *)                      . "./$cache_file";;
    esac
  fi
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
$as_echo "$as_me: creating cache $cache_file" >&6;}
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
  >$cache_file
fi

# Test code for whether the C compiler supports C89 (global declarations)
ac_c_conftest_c89_globals='
/* Does the compiler advertise C89 conformance?
   Do not test the value of __STDC__, because some compilers set it to 0
   while being otherwise adequately conformant. */
#if !defined __STDC__
# error "Compiler does not advertise C89 conformance"
#endif

#include <stddef.h>
#include <stdarg.h>
struct stat;
/* Most of the following tests are stolen from RCS 5.7 src/conf.sh.  */
struct buf { int x; };
struct buf * (*rcsopen) (struct buf *, struct stat *, int);
static char *e (char **p, int i)
{
  return p[i];
}
static char *f (char * (*g) (char **, int), char **p, ...)
{
  char *s;
  va_list v;
  va_start (v,p);
  s = g (p, va_arg (v,int));
  va_end (v);
  return s;
}

/* C89 style stringification. */
#define noexpand_stringify(a) #a
const char *stringified = noexpand_stringify(arbitrary+token=sequence);

/* C89 style token pasting.  Exercises some of the corner cases that
   e.g. old MSVC gets wrong, but not very hard. */
#define noexpand_concat(a,b) a##b
#define expand_concat(a,b) noexpand_concat(a,b)
extern int vA;
extern int vbee;
#define aye A
#define bee B
int *pvA = &expand_concat(v,aye);
int *pvbee = &noexpand_concat(v,bee);

/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
   function prototypes and stuff, but not \xHH hex character constants.
   These do not provoke an error unfortunately, instead are silently treated
   as an "x".  The following induces an error, until -std is added to get
   proper ANSI mode.  Curiously \x00 != x always comes out true, for an
   array size at least.  It is necessary to write \x00 == 0 to get something
   that is true only with -std.  */
int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];

/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
   inside strings and character constants.  */
#define FOO(x) '\''x'\''
int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];

int test (int i, double x);
struct s1 {int (*f) (int a);};
struct s2 {int (*f) (double a);};
int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
               int, int);'

# Test code for whether the C compiler supports C89 (body of main).
ac_c_conftest_c89_main='
ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
'

# Test code for whether the C compiler supports C99 (global declarations)
ac_c_conftest_c99_globals='
/* Does the compiler advertise C99 conformance? */
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
# error "Compiler does not advertise C99 conformance"
#endif

// See if C++-style comments work.

#include <stdbool.h>
extern int puts (const char *);
extern int printf (const char *, ...);
extern int dprintf (int, const char *, ...);
extern void *malloc (size_t);
extern void free (void *);

// Check varargs macros.  These examples are taken from C99 6.10.3.5.
// dprintf is used instead of fprintf to avoid needing to declare
// FILE and stderr.
#define debug(...) dprintf (2, __VA_ARGS__)
#define showlist(...) puts (#__VA_ARGS__)
#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
static void
test_varargs_macros (void)
{
  int x = 1234;
  int y = 5678;
  debug ("Flag");
  debug ("X = %d\n", x);
  showlist (The first, second, and third items.);
  report (x>y, "x is %d but y is %d", x, y);
}

// Check long long types.
#define BIG64 18446744073709551615ull
#define BIG32 4294967295ul
#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
#if !BIG_OK
  #error "your preprocessor is broken"
#endif
#if BIG_OK
#else
  #error "your preprocessor is broken"
#endif
static long long int bignum = -9223372036854775807LL;
static unsigned long long int ubignum = BIG64;

struct incomplete_array
{
  int datasize;
  double data[];
};

struct named_init {
  int number;
  const wchar_t *name;
  double average;
};

typedef const char *ccp;

static inline int
test_restrict (ccp restrict text)
{
  // Iterate through items via the restricted pointer.
  // Also check for declarations in for loops.
  for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
    continue;
  return 0;
}

// Check varargs and va_copy.
static bool
test_varargs (const char *format, ...)
{
  va_list args;
  va_start (args, format);
  va_list args_copy;
  va_copy (args_copy, args);

  const char *str = "";
  int number = 0;
  float fnumber = 0;

  while (*format)
    {
      switch (*format++)
	{
	case '\''s'\'': // string
	  str = va_arg (args_copy, const char *);
	  break;
	case '\''d'\'': // int
	  number = va_arg (args_copy, int);
	  break;
	case '\''f'\'': // float
	  fnumber = va_arg (args_copy, double);
	  break;
	default:
	  break;
	}
    }
  va_end (args_copy);
  va_end (args);

  return *str && number && fnumber;
}
'

# Test code for whether the C compiler supports C99 (body of main).
ac_c_conftest_c99_main='
  // Check bool.
  _Bool success = false;
  success |= (argc != 0);

  // Check restrict.
  if (test_restrict ("String literal") == 0)
    success = true;
  char *restrict newvar = "Another string";

  // Check varargs.
  success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
  test_varargs_macros ();

  // Check flexible array members.
  struct incomplete_array *ia =
    malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
  ia->datasize = 10;
  for (int i = 0; i < ia->datasize; ++i)
    ia->data[i] = i * 1.234;
  // Work around memory leak warnings.
  free (ia);

  // Check named initializers.
  struct named_init ni = {
    .number = 34,
    .name = L"Test wide string",
    .average = 543.34343,
  };

  ni.number = 58;

  int dynamic_array[ni.number];
  dynamic_array[0] = argv[0][0];
  dynamic_array[ni.number - 1] = 543;

  // work around unused variable warnings
  ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
	 || dynamic_array[ni.number - 1] != 543);
'

# Test code for whether the C compiler supports C11 (global declarations)
ac_c_conftest_c11_globals='
/* Does the compiler advertise C11 conformance? */
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
# error "Compiler does not advertise C11 conformance"
#endif

// Check _Alignas.
char _Alignas (double) aligned_as_double;
char _Alignas (0) no_special_alignment;
extern char aligned_as_int;
char _Alignas (0) _Alignas (int) aligned_as_int;

// Check _Alignof.
enum
{
  int_alignment = _Alignof (int),
  int_array_alignment = _Alignof (int[100]),
  char_alignment = _Alignof (char)
};
_Static_assert (0 < -_Alignof (int), "_Alignof is signed");

// Check _Noreturn.
int _Noreturn does_not_return (void) { for (;;) continue; }

// Check _Static_assert.
struct test_static_assert
{
  int x;
  _Static_assert (sizeof (int) <= sizeof (long int),
                  "_Static_assert does not work in struct");
  long int y;
};

// Check UTF-8 literals.
#define u8 syntax error!
char const utf8_literal[] = u8"happens to be ASCII" "another string";

// Check duplicate typedefs.
typedef long *long_ptr;
typedef long int *long_ptr;
typedef long_ptr long_ptr;

// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
struct anonymous
{
  union {
    struct { int i; int j; };
    struct { int k; long int l; } w;
  };
  int m;
} v1;
'

# Test code for whether the C compiler supports C11 (body of main).
ac_c_conftest_c11_main='
  _Static_assert ((offsetof (struct anonymous, i)
		   == offsetof (struct anonymous, w.k)),
		  "Anonymous union alignment botch");
  v1.i = 2;
  v1.w.k = 5;
  ok |= v1.i != 5;
'

# Test code for whether the C compiler supports C11 (complete).
ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
${ac_c_conftest_c99_globals}
${ac_c_conftest_c11_globals}

int
main (int argc, char **argv)
{
  int ok = 0;
  ${ac_c_conftest_c89_main}
  ${ac_c_conftest_c99_main}
  ${ac_c_conftest_c11_main}
  return ok;
}
"

# Test code for whether the C compiler supports C99 (complete).
ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
${ac_c_conftest_c99_globals}

int
main (int argc, char **argv)
{
  int ok = 0;
  ${ac_c_conftest_c89_main}
  ${ac_c_conftest_c99_main}
  return ok;
}
"

# Test code for whether the C compiler supports C89 (complete).
ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}

int
main (int argc, char **argv)
{
  int ok = 0;
  ${ac_c_conftest_c89_main}
  return ok;
}
"

as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
for ac_var in $ac_precious_vars; do
  eval ac_old_set=\$ac_cv_env_${ac_var}_set
  eval ac_new_set=\$ac_env_${ac_var}_set
  eval ac_old_val=\$ac_cv_env_${ac_var}_value
  eval ac_new_val=\$ac_env_${ac_var}_value
  case $ac_old_set,$ac_new_set in
    set,)
      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&5
printf "%s\n" "$as_me: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&2;}
      ac_cache_corrupted=: ;;
    ,set)
      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was not set in the previous run" >&5
printf "%s\n" "$as_me: error: '$ac_var' was not set in the previous run" >&2;}
      ac_cache_corrupted=: ;;
    ,);;
    *)
      if test "x$ac_old_val" != "x$ac_new_val"; then
	# differences in whitespace do not lead to failure.
	ac_old_val_w=`echo x $ac_old_val`
	ac_new_val_w=`echo x $ac_new_val`
	if test "$ac_old_val_w" != "$ac_new_val_w"; then
	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' has changed since the previous run:" >&5
printf "%s\n" "$as_me: error: '$ac_var' has changed since the previous run:" >&2;}
	  ac_cache_corrupted=:
	else
	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&5
printf "%s\n" "$as_me: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&2;}
	  eval $ac_var=\$ac_old_val
	fi
	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}:   former value:  '$ac_old_val'" >&5
printf "%s\n" "$as_me:   former value:  '$ac_old_val'" >&2;}
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}:   current value: '$ac_new_val'" >&5
printf "%s\n" "$as_me:   current value: '$ac_new_val'" >&2;}
      fi;;
  esac
  # Pass precious variables to config.status.
  if test "$ac_new_set" = set; then
    case $ac_new_val in
    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
    *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
    *) ac_arg=$ac_var=$ac_new_val ;;
    esac
    case " $ac_configure_args " in
      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
    esac
  fi
done
if $ac_cache_corrupted; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
  as_fn_error $? "run '${MAKE-make} distclean' and/or 'rm $cache_file'
	    and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
## -------------------- ##

ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu





# The following define is needed when building with Cygwin since newer
# 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.0
TCL_MAJOR_VERSION=9
TCL_MINOR_VERSION=0
TCL_PATCH_LEVEL="a2"
TCL_PATCH_LEVEL=".1"
VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION

TCL_DDE_VERSION=1.4
TCL_DDE_MAJOR_VERSION=1
TCL_DDE_MINOR_VERSION=4
DDEVER=$TCL_DDE_MAJOR_VERSION$TCL_DDE_MINOR_VERSION

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

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
2273
2274
2275


2276
2277
2278


2279
2280
2281
2282
2283
2284
2285
2286
2287


2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305







2306
2307
2308
2309
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
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404







2405
2406
2407
2408
2409
2410

2411




2412
2413

2414
2415

2416
2417
2418
2419
2420
2421
2422


2423
2424
2425
2426
2427


2428
2429
2430


2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448







2449
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
2489
2490
2491










































































































2492
2493
2494
2495
2496
2497
2498


2499
2500

2501
2502
2503

2504
2505
2506

2507
2508
2509
2510
2511
2512
2513

2514
2515
2516
2517
2518
2519
2520
2521
2522
2523

2524
2525
2526
2527
2528
2529
2530
2531

2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545



2546
2547
2548
2549
2550
2551
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
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
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
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420







3421
3422
3423
3424
3425
3426

3427




3428
3429

3430
3431

3432
3433
3434
3435
3436
3437
3438


3439
3440
3441
3442
3443


3444
3445
3446


3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460







3461
3462
3463
3464
3465
3466

3467




3468
3469

3470
3471

3472
3473
3474
3475
3476
3477
3478


3479
3480
3481
3482
3483


3484
3485
3486


3487
3488
3489
3490
3491
3492
3493
3494
3495


3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512







3513
3514
3515
3516
3517
3518

3519




3520
3521

3522
3523

3524
3525
3526
3527
3528
3529
3530


3531
3532
3533
3534
3535


3536
3537
3538


3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552







3553
3554
3555
3556
3557
3558

3559




3560
3561

3562
3563

3564
3565
3566
3567
3568
3569
3570


3571
3572
3573
3574
3575


3576
3577
3578


3579
3580
3581
3582
3583
3584
3585
3586
3587


3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604







3605
3606
3607
3608
3609
3610

3611




3612
3613

3614
3615

3616
3617
3618
3619
3620
3621
3622


3623
3624
3625
3626
3627


3628
3629
3630


3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644







3645
3646
3647
3648
3649
3650

3651




3652
3653

3654
3655

3656
3657
3658
3659
3660
3661
3662


3663
3664
3665
3666
3667


3668
3669
3670


3671
3672
3673
3674
3675
3676
3677
3678
3679


3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694


3695
3696
3697
3698
3699
3700






3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712


3713
3714
3715
3716


3717
3718
3719
3720


3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739


3740
3741
3742
3743
3744
3745
3746

3747
3748
3749
3750

3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762


3763
3764


3765
3766
3767


3768
3769

3770
3771
3772
3773
3774
3775
3776

3777
3778
3779
3780


3781
3782
3783
3784


3785
3786
3787

3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800

3801
3802
3803
3804
3805
3806
3807
3808
3809



















3810
3811

3812

3813

3814

3815

3816
3817
3818
3819
3820
3821


3822
3823


3824
3825
3826



3827
3828
3829
3830


3831
3832
3833
3834
3835

3836
3837
3838
3839
3840
3841
3842
3843
3844
3845







3846
3847
3848
3849
3850
3851

3852




3853
3854

3855
3856

3857
3858
3859
3860
3861
3862
3863
3864


3865
3866
3867
3868
3869


3870
3871
3872


3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883







3884
3885
3886
3887
3888
3889

3890




3891
3892

3893
3894

3895
3896
3897
3898
3899
3900
3901


3902
3903
3904
3905
3906


3907
3908
3909


3910
3911
3912
3913
3914
3915
3916
3917

3918
3919
3920
3921
3922
3923
3924
3925
3926
3927







3928
3929
3930
3931
3932
3933
3934
3935

3936
3937
3938
3939
3940
3941
3942


3943
3944
3945



3946
3947
3948



3949
3950
3951


3952
3953
3954
3955
3956
3957
3958
3959
3960
3961







3962
3963
3964
3965
3966
3967
3968
2449
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
2489
2490
2491
2492

2493
2494

2495
2496
2497
2498
2499
2500
2501

2502
2503
2504
2505
2506


2507
2508
2509


2510
2511
2512
2513
2514
2515
2516
2517
2518
2519






2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533

2534
2535
2536
2537
2538

2539
2540

2541
2542
2543
2544
2545
2546
2547

2548
2549
2550
2551
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
3134
3135
3136
3137


3138
3139
3140

3141
3142
3143






3144
3145
3146
3147
3148
3149
3150
3151
3152
3153

3154
3155
3156
3157
3158
3159
3160
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






3199
3200
3201
3202
3203
3204
3205
3206
3207
3208

3209
3210
3211
3212
3213
3214
3215
3216
3217
3218

3219
3220
3221


3222
3223
3224
3225

3226
3227

3228
3229
3230


3231
3232
3233
3234
3235
3236
3237
3238
3239

3240
3241






3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255

3256
3257
3258
3259
3260
3261
3262

3263
3264
3265


3266
3267
3268
3269
3270
3271

3272
3273
3274
3275
3276
3277
3278

3279
3280
3281


3282
3283
3284
3285
3286
3287
3288

3289
3290
3291
3292
3293
3294
3295

3296
3297
3298
3299

3300
3301
3302

3303
3304
3305


3306
3307
3308
3309



3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329






3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437






















3438



























3439

3440

3441
3442

3443
3444
3445
3446

3447
3448
3449
3450


3451
3452
3453


3454
3455






3456
3457
3458




3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469


3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482






3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494


3495
3496
3497
3498
3499

3500
3501
3502
3503

3504
3505
3506

3507
3508
3509


3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527




























































































































































































































































































































































































3528
3529
3530
3531






3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545

3546
3547
3548
3549
3550

3551
3552

3553
3554
3555
3556
3557
3558
3559

3560
3561
3562
3563
3564


3565
3566
3567


3568
3569
3570
3571
3572
3573
3574
3575
3576
3577






3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591

3592
3593
3594
3595
3596

3597
3598

3599
3600
3601
3602
3603
3604
3605

3606
3607
3608
3609
3610


3611
3612
3613


3614
3615
3616
3617
3618
3619
3620
3621
3622


3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635






3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649

3650
3651
3652
3653
3654

3655
3656

3657
3658
3659
3660
3661
3662
3663

3664
3665
3666
3667
3668


3669
3670
3671


3672
3673
3674
3675
3676
3677
3678
3679
3680
3681






3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695

3696
3697
3698
3699
3700

3701
3702

3703
3704
3705
3706
3707
3708
3709

3710
3711
3712
3713
3714


3715
3716
3717


3718
3719
3720
3721
3722
3723
3724
3725
3726


3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739






3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753

3754
3755
3756
3757
3758

3759
3760

3761
3762
3763
3764
3765
3766
3767

3768
3769
3770
3771
3772


3773
3774
3775


3776
3777
3778
3779
3780
3781
3782
3783
3784
3785






3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799

3800
3801
3802
3803
3804

3805
3806

3807
3808
3809
3810
3811
3812
3813

3814
3815
3816
3817
3818


3819
3820
3821


3822
3823
3824
3825
3826
3827
3828
3829
3830


3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845


3846
3847
3848





3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865

3866
3867
3868
3869


3870
3871
3872
3873


3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893

3894
3895
3896
3897
3898
3899
3900


3901

3902
3903

3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914


3915
3916
3917

3918
3919
3920


3921
3922


3923







3924
3925
3926


3927
3928
3929
3930


3931
3932
3933
3934

3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946


3947









3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967

3968
3969
3970

3971
3972
3973
3974
3975
3976
3977
3978
3979


3980
3981
3982

3983
3984
3985


3986
3987
3988
3989
3990


3991
3992
3993
3994
3995
3996

3997
3998
3999
4000
4001






4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015

4016
4017
4018
4019
4020

4021
4022

4023
4024
4025
4026
4027
4028
4029
4030

4031
4032
4033
4034
4035


4036
4037
4038


4039
4040
4041
4042
4043
4044
4045






4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059

4060
4061
4062
4063
4064

4065
4066

4067
4068
4069
4070
4071
4072
4073

4074
4075
4076
4077
4078


4079
4080
4081


4082
4083
4084
4085
4086
4087
4088
4089
4090

4091
4092
4093
4094
4095






4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109

4110
4111
4112
4113
4114
4115
4116

4117
4118
4119


4120
4121
4122
4123


4124
4125
4126
4127


4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153







+
+
+
+
+
+
+
+
+









-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+








-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+







-
-
+
+












-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+








-
-
-
-
-
-
+
+
+
+
+
+
+







+
-
+
+
+
+

-
-
+
+




-
+















-
+


-
+
+



-
-
+
+

-
-
+
+










-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+












-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+











-
-
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
-
+
+

-
+


-
+


-
+






-
+









-
+







-
+











-
-
-
+
+
+




















-
+


-
-
-
-
+
+
+
+
+














-
+




-
+










-
-
+
+
+

-
-
-
-
+
+
+
+
+


-
-
+
+

-
-
-
-
+
+
+
+
+

-
-
-
-
+
+
+
+




-
-
+
+






-
+


-
-
-
-
-
-
+
+
+
+
+
+
+









-
-
-
+
+
+

-
+
+


-
-
+
+








-
+


+
+









-
-
+
+







-
+


-
+







-
+


-
+






-
-
-
-
-
+
+
+
+
+



-
-
+
+

-
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+



-
+













-
+


-
-
+
+
+








-
-
+
+


-
-
+
+

-
+
+

-
+
+

-
-
+
+


-
-
-
-
-
-
+
+
+
+
+
+
+



-
+









-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
+
+
+
+





-
+

-
-
-
-
-
-
+
+
+
+
+
+
+







-
+






-
+
+

-
-
+
+




-
+






-
+
+

-
-
+
+





-
+






-
+
+


-
+
+

-
+
+

-
-
+
+
+

-
-
-
+
+
+














+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
+
-


-
+
+


-
+



-
-
+
+

-
-
+
+
-
-
-
-
-
-
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+

+
-
-
+
+
+
+









-
-
-
-
-
-
+
+
+
+
+
+
+





-
-
+
+



-
+
+


-
+


-
+
+

-
-
+
+
















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-




-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+








-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+







-
-
+
+











-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+








-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+







-
-
+
+











-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+








-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+







-
-
+
+













-
-
+
+

-
-
-
-
-
+
+
+
+
+
+











-
+
+


-
-
+
+


-
-
+
+


















-
+
+





-
-
+
-


-
+










-
-
+
+

-
+
+

-
-
+
+
-
-
+
-
-
-
-
-
-
-
+


-
-
+
+


-
-
+
+


-
+











-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

+
-
+

+

+




-
-
+
+

-
+
+

-
-
+
+
+


-
-
+
+




-
+




-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+







-
+
+



-
-
+
+

-
-
+
+





-
-
-
-
-
-
+
+
+
+
+
+
+






+
-
+
+
+
+

-
+

-
+






-
+
+



-
-
+
+

-
-
+
+







-
+




-
-
-
-
-
-
+
+
+
+
+
+
+







-
+






-
+
+

-
-
+
+
+

-
-
+
+
+

-
-
+
+










+
+
+
+
+
+
+







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

# If the user did not set CFLAGS, set it now to keep
# the AC_PROG_CC macro from adding "-g -O2".
if test "${CFLAGS+set}" != "set" ; then
    CFLAGS=""
fi










ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CC+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CC="${ac_tool_prefix}gcc"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


fi
if test -z "$ac_cv_prog_CC"; then
  ac_ct_CC=$CC
  # Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_ac_ct_CC+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$ac_ct_CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$ac_ct_CC"; then
  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_CC="gcc"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
$as_echo "$ac_ct_CC" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
printf "%s\n" "$ac_ct_CC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi

  if test "x$ac_ct_CC" = x; then
    CC=""
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
    CC=$ac_ct_CC
  fi
else
  CC="$ac_cv_prog_CC"
fi

if test -z "$CC"; then
          if test -n "$ac_tool_prefix"; then
    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CC+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CC="${ac_tool_prefix}cc"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


  fi
fi
if test -z "$CC"; then
  # Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CC+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  ac_prog_rejected=no
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
       ac_prog_rejected=yes
       continue
     fi
    ac_cv_prog_CC="cc"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

if test $ac_prog_rejected = yes; then
  # We found a bogon in the path, so make sure we never use it.
  set dummy $ac_cv_prog_CC
  shift
  if test $# != 0; then
    # We chose a different compiler from the bogus one.
    # However, it has the same basename, so the bogon will be chosen
    # first if we set CC to just the basename; use the full file name.
    shift
    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
    ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
  fi
fi
fi
fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


fi
if test -z "$CC"; then
  if test -n "$ac_tool_prefix"; then
  for ac_prog in cl.exe
  do
    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CC+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


    test -n "$CC" && break
  done
fi
if test -z "$CC"; then
  ac_ct_CC=$CC
  for ac_prog in cl.exe
do
  # Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_ac_ct_CC+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$ac_ct_CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$ac_ct_CC"; then
  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_CC="$ac_prog"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
$as_echo "$ac_ct_CC" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
printf "%s\n" "$ac_ct_CC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


  test -n "$ac_ct_CC" && break
done

  if test "x$ac_ct_CC" = x; then
    CC=""
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
    CC=$ac_ct_CC
  fi
fi

fi
if test -z "$CC"; then
  if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
set dummy ${ac_tool_prefix}clang; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CC="${ac_tool_prefix}clang"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


fi
if test -z "$ac_cv_prog_CC"; then
  ac_ct_CC=$CC
  # Extract the first word of "clang", so it can be a program name with args.
set dummy clang; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$ac_ct_CC"; then
  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_CC="clang"
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi ;;
esac
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
printf "%s\n" "$ac_ct_CC" >&6; }
else
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi

  if test "x$ac_ct_CC" = x; then
    CC=""
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
    CC=$ac_ct_CC
  fi
else
  CC="$ac_cv_prog_CC"
fi

fi


test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
See \`config.log' for more details" "$LINENO" 5; }
See 'config.log' for more details" "$LINENO" 5; }

# Provide some information about the compiler.
$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
set X $ac_compile
ac_compiler=$2
for ac_option in --version -v -V -qversion; do
for ac_option in --version -v -V -qversion -version; do
  { { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
  ac_status=$?
  if test -s conftest.err; then
    sed '10a\
... rest of stderr output deleted ...
         10q' conftest.err >conftest.er1
    cat conftest.er1 >&5
  fi
  rm -f conftest.er1 conftest.err
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
done

cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
$as_echo_n "checking whether the C compiler works... " >&6; }
ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
printf %s "checking whether the C compiler works... " >&6; }
ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`

# The possible output files:
ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"

ac_rmfiles=
for ac_file in $ac_files
do
  case $ac_file in
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
  esac
done
rm -f $ac_rmfiles

if { { ac_try="$ac_link_default"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link_default") 2>&5
  ac_status=$?
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }; then :
  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
then :
  # Autoconf-2.13 could set the ac_cv_exeext variable to 'no'.
# So ignore a value of 'no', otherwise this would lead to 'EXEEXT = no'
# in a Makefile.  We should not override ac_cv_exeext if it was cached,
# so that the user can short-circuit this test for compilers unknown to
# Autoconf.
for ac_file in $ac_files ''
do
  test -f "$ac_file" || continue
  case $ac_file in
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
	;;
    [ab].out )
	# We found the default executable, but exeext='' is most
	# certainly right.
	break;;
    *.* )
	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
	if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
	then :; else
	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
	fi
	# We set ac_cv_exeext here because the later test for it is not
	# safe: cross compilers may not add the suffix if given an `-o'
	# safe: cross compilers may not add the suffix if given an '-o'
	# argument, so we may need to know it at that point already.
	# Even if this section looks crufty: it has the advantage of
	# actually working.
	break;;
    * )
	break;;
  esac
done
test "$ac_cv_exeext" = no && ac_cv_exeext=

else
  ac_file=''
else case e in #(
  e) ac_file='' ;;
esac
fi
if test -z "$ac_file"; then :
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "$as_me: failed program was:" >&5
if test -z "$ac_file"
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error 77 "C compiler cannot create executables
See \`config.log' for more details" "$LINENO" 5; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
See 'config.log' for more details" "$LINENO" 5; }
else case e in #(
  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; } ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
$as_echo_n "checking for C compiler default output file name... " >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
$as_echo "$ac_file" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
printf %s "checking for C compiler default output file name... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
printf "%s\n" "$ac_file" >&6; }
ac_exeext=$ac_cv_exeext

rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
ac_clean_files=$ac_clean_files_save
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
$as_echo_n "checking for suffix of executables... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
printf %s "checking for suffix of executables... " >&6; }
if { { ac_try="$ac_link"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link") 2>&5
  ac_status=$?
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }; then :
  # If both `conftest.exe' and `conftest' are `present' (well, observable)
# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
# work properly (i.e., refer to `conftest.exe'), while it won't with
# `rm'.
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
then :
  # If both 'conftest.exe' and 'conftest' are 'present' (well, observable)
# catch 'conftest.exe'.  For instance with Cygwin, 'ls conftest' will
# work properly (i.e., refer to 'conftest.exe'), while it won't with
# 'rm'.
for ac_file in conftest.exe conftest conftest.*; do
  test -f "$ac_file" || continue
  case $ac_file in
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
	  break;;
    * ) break;;
  esac
done
else
  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
else case e in #(
  e) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details" "$LINENO" 5; }
See 'config.log' for more details" "$LINENO" 5; } ;;
esac
fi
rm -f conftest conftest$ac_cv_exeext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
$as_echo "$ac_cv_exeext" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
printf "%s\n" "$ac_cv_exeext" >&6; }

rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
ac_exeext=$EXEEXT
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <stdio.h>
int
main ()
main (void)
{
FILE *f = fopen ("conftest.out", "w");
 if (!f)
  return 1;
 return ferror (f) || fclose (f) != 0;

  ;
  return 0;
}
_ACEOF
ac_clean_files="$ac_clean_files conftest.out"
# Check that the compiler produces executables we can run.  If not, either
# the compiler is broken, or we cross compile.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
$as_echo_n "checking whether we are cross compiling... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
printf %s "checking whether we are cross compiling... " >&6; }
if test "$cross_compiling" != yes; then
  { { ac_try="$ac_link"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link") 2>&5
  ac_status=$?
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
  if { ac_try='./conftest$ac_cv_exeext'
  { { case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_try") 2>&5
  ac_status=$?
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }; }; then
    cross_compiling=no
  else
    if test "$cross_compiling" = maybe; then
	cross_compiling=yes
    else
	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot run C compiled programs.
If you meant to cross compile, use \`--host'.
See \`config.log' for more details" "$LINENO" 5; }
	{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error 77 "cannot run C compiled programs.
If you meant to cross compile, use '--host'.
See 'config.log' for more details" "$LINENO" 5; }
    fi
  fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
$as_echo "$cross_compiling" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
printf "%s\n" "$cross_compiling" >&6; }

rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
rm -f conftest.$ac_ext conftest$ac_cv_exeext \
  conftest.o conftest.obj conftest.out
ac_clean_files=$ac_clean_files_save
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
$as_echo_n "checking for suffix of object files... " >&6; }
if ${ac_cv_objext+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
printf %s "checking for suffix of object files... " >&6; }
if test ${ac_cv_objext+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
rm -f conftest.o conftest.obj
if { { ac_try="$ac_compile"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_compile") 2>&5
  ac_status=$?
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }; then :
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }
then :
  for ac_file in conftest.o conftest.obj conftest.*; do
  test -f "$ac_file" || continue;
  case $ac_file in
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
       break;;
  esac
done
else
  $as_echo "$as_me: failed program was:" >&5
else case e in #(
  e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See \`config.log' for more details" "$LINENO" 5; }
See 'config.log' for more details" "$LINENO" 5; } ;;
esac
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
rm -f conftest.$ac_cv_objext conftest.$ac_ext ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
$as_echo "$ac_cv_objext" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
printf "%s\n" "$ac_cv_objext" >&6; }
OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
if ${ac_cv_c_compiler_gnu+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
printf %s "checking whether the compiler supports GNU C... " >&6; }
if test ${ac_cv_c_compiler_gnu+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{
#ifndef __GNUC__
       choke me
#endif

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  ac_compiler_gnu=yes
else
  ac_compiler_gnu=no
else case e in #(
  e) ac_compiler_gnu=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu

 ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
$as_echo "$ac_cv_c_compiler_gnu" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
ac_compiler_gnu=$ac_cv_c_compiler_gnu

if test $ac_compiler_gnu = yes; then
  GCC=yes
else
  GCC=
fi
ac_test_CFLAGS=${CFLAGS+set}
ac_test_CFLAGS=${CFLAGS+y}
ac_save_CFLAGS=$CFLAGS
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
$as_echo_n "checking whether $CC accepts -g... " >&6; }
if ${ac_cv_prog_cc_g+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_save_c_werror_flag=$ac_c_werror_flag
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
printf %s "checking whether $CC accepts -g... " >&6; }
if test ${ac_cv_prog_cc_g+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_save_c_werror_flag=$ac_c_werror_flag
   ac_c_werror_flag=yes
   ac_cv_prog_cc_g=no
   CFLAGS="-g"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_g=yes
else
  CFLAGS=""
else case e in #(
  e) CFLAGS=""
      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :

else
  ac_c_werror_flag=$ac_save_c_werror_flag
else case e in #(
  e) ac_c_werror_flag=$ac_save_c_werror_flag
	 CFLAGS="-g"
	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_g=yes
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   ac_c_werror_flag=$ac_save_c_werror_flag
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
   ac_c_werror_flag=$ac_save_c_werror_flag ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
$as_echo "$ac_cv_prog_cc_g" >&6; }
if test "$ac_test_CFLAGS" = set; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
if test $ac_test_CFLAGS; then
  CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
  if test "$GCC" = yes; then
    CFLAGS="-g -O2"
  else
    CFLAGS="-g"
  fi
else
  if test "$GCC" = yes; then
    CFLAGS="-O2"
  else
    CFLAGS=
  fi
fi
ac_prog_cc_stdc=no
if test x$ac_prog_cc_stdc = xno
then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
if ${ac_cv_prog_cc_c89+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_cv_prog_cc_c89=no
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
printf %s "checking for $CC option to enable C11 features... " >&6; }
if test ${ac_cv_prog_cc_c11+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_cv_prog_cc_c11=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$ac_c_conftest_c11_program
_ACEOF
for ac_arg in '' -std=gnu11
do
  CC="$ac_save_CC $ac_arg"
  if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_c11=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam
  test "x$ac_cv_prog_cc_c11" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC ;;
esac
fi

if test "x$ac_cv_prog_cc_c11" = xno
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
else case e in #(
  e) if test "x$ac_cv_prog_cc_c11" = x
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
else case e in #(
  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
     CC="$CC $ac_cv_prog_cc_c11" ;;
esac
fi
  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
  ac_prog_cc_stdc=c11 ;;
esac
fi
fi
if test x$ac_prog_cc_stdc = xno
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
printf %s "checking for $CC option to enable C99 features... " >&6; }
if test ${ac_cv_prog_cc_c99+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_cv_prog_cc_c99=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$ac_c_conftest_c99_program
_ACEOF
for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
do
  CC="$ac_save_CC $ac_arg"
  if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_c99=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam
  test "x$ac_cv_prog_cc_c99" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC ;;
esac
fi

if test "x$ac_cv_prog_cc_c99" = xno
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
else case e in #(
  e) if test "x$ac_cv_prog_cc_c99" = x
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
else case e in #(
  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
     CC="$CC $ac_cv_prog_cc_c99" ;;
esac
fi
  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
  ac_prog_cc_stdc=c99 ;;
esac
fi
fi
if test x$ac_prog_cc_stdc = xno
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
printf %s "checking for $CC option to enable C89 features... " >&6; }
if test ${ac_cv_prog_cc_c89+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_cv_prog_cc_c89=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <stdarg.h>
#include <stdio.h>
struct stat;
/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
struct buf { int x; };
FILE * (*rcsopen) (struct buf *, struct stat *, int);
static char *e (p, i)
     char **p;
     int i;
{
  return p[i];
}
static char *f (char * (*g) (char **, int), char **p, ...)
{
  char *s;
  va_list v;
  va_start (v,p);
  s = g (p, va_arg (v,int));
  va_end (v);
  return s;
}

$ac_c_conftest_c89_program
/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
   function prototypes and stuff, but not '\xHH' hex character constants.
   These don't provoke an error unfortunately, instead are silently treated
   as 'x'.  The following induces an error, until -std is added to get
   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
   array size at least.  It's necessary to write '\x00'==0 to get something
   that's true only with -std.  */
int osf4_cc_array ['\x00' == 0 ? 1 : -1];

/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
   inside strings and character constants.  */
#define FOO(x) 'x'
int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];

int test (int i, double x);
struct s1 {int (*f) (int a);};
struct s2 {int (*f) (double a);};
int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
int argc;
char **argv;
int
main ()
{
return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
  ;
  return 0;
}
_ACEOF
for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
  CC="$ac_save_CC $ac_arg"
  if ac_fn_c_try_compile "$LINENO"; then :
  if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_c89=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext
rm -f core conftest.err conftest.$ac_objext conftest.beam
  test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC

CC=$ac_save_CC ;;
esac
fi
# AC_CACHE_VAL
case "x$ac_cv_prog_cc_c89" in

if test "x$ac_cv_prog_cc_c89" = xno
  x)
    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
$as_echo "none needed" >&6; } ;;
  xno)
    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
$as_echo "unsupported" >&6; } ;;
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
  *)
    CC="$CC $ac_cv_prog_cc_c89"
    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
else case e in #(
  e) if test "x$ac_cv_prog_cc_c89" = x
then :
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
else case e in #(
  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
     CC="$CC $ac_cv_prog_cc_c89" ;;
esac
fi
if test "x$ac_cv_prog_cc_c89" != xno; then :

  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
  ac_prog_cc_stdc=c89 ;;
esac
fi
fi

ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu


{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
$as_echo_n "checking for inline... " >&6; }
if ${ac_cv_c_inline+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_cv_c_inline=no
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
printf %s "checking for inline... " >&6; }
if test ${ac_cv_c_inline+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) ac_cv_c_inline=no
for ac_kw in inline __inline__ __inline; do
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#ifndef __cplusplus
typedef int foo_t;
static $ac_kw foo_t static_foo () {return 0; }
$ac_kw foo_t foo () {return 0; }
static $ac_kw foo_t static_foo (void) {return 0; }
$ac_kw foo_t foo (void) {return 0; }
#endif

_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_c_inline=$ac_kw
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
  test "$ac_cv_c_inline" != no && break
done

 ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
$as_echo "$ac_cv_c_inline" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
printf "%s\n" "$ac_cv_c_inline" >&6; }

case $ac_cv_c_inline in
  inline | yes) ;;
  *)
    case $ac_cv_c_inline in
      no) ac_val=;;
      *) ac_val=$ac_cv_c_inline;;
    esac
    cat >>confdefs.h <<_ACEOF
#ifndef __cplusplus
#define inline $ac_val
#endif
_ACEOF
    ;;
esac

ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
$as_echo_n "checking how to run the C preprocessor... " >&6; }
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
  CPP=
fi
if test -z "$CPP"; then
  if ${ac_cv_prog_CPP+:} false; then :
  $as_echo_n "(cached) " >&6
else
      # Double quotes because CPP needs to be expanded
    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
    do
      ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
  # Use a header file that comes with gcc, so configuring glibc
  # with a fresh cross-compiler works.
  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
  # <limits.h> exists even on freestanding compilers.
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp. "Syntax error" is here to catch this case.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif
		     Syntax error
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :

else
  # Broken: fails on valid input.
continue
fi
rm -f conftest.err conftest.i conftest.$ac_ext

  # OK, works on sane cases.  Now check whether nonexistent headers
  # can be detected and how.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <ac_nonexistent.h>
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
  # Broken: success on invalid input.
continue
else
  # Passes both tests.
ac_preproc_ok=:
break
fi
rm -f conftest.err conftest.i conftest.$ac_ext

done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok; then :
  break
fi

    done
    ac_cv_prog_CPP=$CPP

fi
  CPP=$ac_cv_prog_CPP
else
  ac_cv_prog_CPP=$CPP
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
$as_echo "$CPP" >&6; }
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
  # Use a header file that comes with gcc, so configuring glibc
  # with a fresh cross-compiler works.
  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
  # <limits.h> exists even on freestanding compilers.
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp. "Syntax error" is here to catch this case.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif
		     Syntax error
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :

else
  # Broken: fails on valid input.
continue
fi
rm -f conftest.err conftest.i conftest.$ac_ext

  # OK, works on sane cases.  Now check whether nonexistent headers
  # can be detected and how.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <ac_nonexistent.h>
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
  # Broken: success on invalid input.
continue
else
  # Passes both tests.
ac_preproc_ok=:
break
fi
rm -f conftest.err conftest.i conftest.$ac_ext

done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok; then :

else
  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
See \`config.log' for more details" "$LINENO" 5; }
fi

ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu


{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
if ${ac_cv_path_GREP+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -z "$GREP"; then
  ac_path_GREP_found=false
  # Loop through the user's path and test for each of PROGNAME-LIST
  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
  IFS=$as_save_IFS
  test -z "$as_dir" && as_dir=.
    for ac_prog in grep ggrep; do
    for ac_exec_ext in '' $ac_executable_extensions; do
      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
      as_fn_executable_p "$ac_path_GREP" || continue
# Check for GNU ac_path_GREP and select it if it is found.
  # Check for GNU $ac_path_GREP
case `"$ac_path_GREP" --version 2>&1` in
*GNU*)
  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
*)
  ac_count=0
  $as_echo_n 0123456789 >"conftest.in"
  while :
  do
    cat "conftest.in" "conftest.in" >"conftest.tmp"
    mv "conftest.tmp" "conftest.in"
    cp "conftest.in" "conftest.nl"
    $as_echo 'GREP' >> "conftest.nl"
    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
    as_fn_arith $ac_count + 1 && ac_count=$as_val
    if test $ac_count -gt ${ac_path_GREP_max-0}; then
      # Best one so far, save it but keep looking for a better one
      ac_cv_path_GREP="$ac_path_GREP"
      ac_path_GREP_max=$ac_count
    fi
    # 10*(2^10) chars as input seems more than enough
    test $ac_count -gt 10 && break
  done
  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac

      $ac_path_GREP_found && break 3
    done
  done
  done
IFS=$as_save_IFS
  if test -z "$ac_cv_path_GREP"; then
    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
  fi
else
  ac_cv_path_GREP=$GREP
fi

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
$as_echo "$ac_cv_path_GREP" >&6; }
 GREP="$ac_cv_path_GREP"


{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
$as_echo_n "checking for egrep... " >&6; }
if ${ac_cv_path_EGREP+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
   then ac_cv_path_EGREP="$GREP -E"
   else
     if test -z "$EGREP"; then
  ac_path_EGREP_found=false
  # Loop through the user's path and test for each of PROGNAME-LIST
  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
  IFS=$as_save_IFS
  test -z "$as_dir" && as_dir=.
    for ac_prog in egrep; do
    for ac_exec_ext in '' $ac_executable_extensions; do
      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
      as_fn_executable_p "$ac_path_EGREP" || continue
# Check for GNU ac_path_EGREP and select it if it is found.
  # Check for GNU $ac_path_EGREP
case `"$ac_path_EGREP" --version 2>&1` in
*GNU*)
  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
*)
  ac_count=0
  $as_echo_n 0123456789 >"conftest.in"
  while :
  do
    cat "conftest.in" "conftest.in" >"conftest.tmp"
    mv "conftest.tmp" "conftest.in"
    cp "conftest.in" "conftest.nl"
    $as_echo 'EGREP' >> "conftest.nl"
    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
    as_fn_arith $ac_count + 1 && ac_count=$as_val
    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
      # Best one so far, save it but keep looking for a better one
      ac_cv_path_EGREP="$ac_path_EGREP"
      ac_path_EGREP_max=$ac_count
    fi
    # 10*(2^10) chars as input seems more than enough
    test $ac_count -gt 10 && break
  done
  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac

      $ac_path_EGREP_found && break 3
    done
  done
  done
IFS=$as_save_IFS
  if test -z "$ac_cv_path_EGREP"; then
    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
  fi
else
  ac_cv_path_EGREP=$EGREP
fi

   fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
$as_echo "$ac_cv_path_EGREP" >&6; }
 EGREP="$ac_cv_path_EGREP"


{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
$as_echo_n "checking for ANSI C header files... " >&6; }
if ${ac_cv_header_stdc+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <float.h>

int
main ()
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  ac_cv_header_stdc=yes
else
  ac_cv_header_stdc=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

if test $ac_cv_header_stdc = yes; then
  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <string.h>

_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  $EGREP "memchr" >/dev/null 2>&1; then :

else
  ac_cv_header_stdc=no
fi
rm -f conftest*

fi

if test $ac_cv_header_stdc = yes; then
  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <stdlib.h>

_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  $EGREP "free" >/dev/null 2>&1; then :

else
  ac_cv_header_stdc=no
fi
rm -f conftest*

fi

if test $ac_cv_header_stdc = yes; then
  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
  if test "$cross_compiling" = yes; then :
  :
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <ctype.h>
#include <stdlib.h>
#if ((' ' & 0x0FF) == 0x020)
# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
#else
# define ISLOWER(c) \
		   (('a' <= (c) && (c) <= 'i') \
		     || ('j' <= (c) && (c) <= 'r') \
		     || ('s' <= (c) && (c) <= 'z'))
# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
#endif

#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
int
main ()
{
  int i;
  for (i = 0; i < 256; i++)
    if (XOR (islower (i), ISLOWER (i))
	|| toupper (i) != TOUPPER (i))
      return 2;
  return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :

else
  ac_cv_header_stdc=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
  conftest.$ac_objext conftest.beam conftest.$ac_ext
fi

fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
$as_echo "$ac_cv_header_stdc" >&6; }
if test $ac_cv_header_stdc = yes; then

$as_echo "#define STDC_HEADERS 1" >>confdefs.h

fi


if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
set dummy ${ac_tool_prefix}ar; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_AR+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$AR"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_AR+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$AR"; then
  ac_cv_prog_AR="$AR" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_AR="${ac_tool_prefix}ar"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
AR=$ac_cv_prog_AR
if test -n "$AR"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
$as_echo "$AR" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
printf "%s\n" "$AR" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


fi
if test -z "$ac_cv_prog_AR"; then
  ac_ct_AR=$AR
  # Extract the first word of "ar", so it can be a program name with args.
set dummy ar; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_ac_ct_AR+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$ac_ct_AR"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_AR+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$ac_ct_AR"; then
  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_AR="ar"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
ac_ct_AR=$ac_cv_prog_ac_ct_AR
if test -n "$ac_ct_AR"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
$as_echo "$ac_ct_AR" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
printf "%s\n" "$ac_ct_AR" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi

  if test "x$ac_ct_AR" = x; then
    AR=""
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
    AR=$ac_ct_AR
  fi
else
  AR="$ac_cv_prog_AR"
fi

if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
set dummy ${ac_tool_prefix}ranlib; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_RANLIB+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$RANLIB"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_RANLIB+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$RANLIB"; then
  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
$as_echo "$RANLIB" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
printf "%s\n" "$RANLIB" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


fi
if test -z "$ac_cv_prog_RANLIB"; then
  ac_ct_RANLIB=$RANLIB
  # Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$ac_ct_RANLIB"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_RANLIB+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$ac_ct_RANLIB"; then
  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_RANLIB="ranlib"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
if test -n "$ac_ct_RANLIB"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
$as_echo "$ac_ct_RANLIB" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
printf "%s\n" "$ac_ct_RANLIB" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi

  if test "x$ac_ct_RANLIB" = x; then
    RANLIB=""
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
    RANLIB=$ac_ct_RANLIB
  fi
else
  RANLIB="$ac_cv_prog_RANLIB"
fi

if test -n "$ac_tool_prefix"; then
  # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args.
set dummy ${ac_tool_prefix}windres; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_RC+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$RC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_RC+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$RC"; then
  ac_cv_prog_RC="$RC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_RC="${ac_tool_prefix}windres"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
RC=$ac_cv_prog_RC
if test -n "$RC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RC" >&5
$as_echo "$RC" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RC" >&5
printf "%s\n" "$RC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


fi
if test -z "$ac_cv_prog_RC"; then
  ac_ct_RC=$RC
  # Extract the first word of "windres", so it can be a program name with args.
set dummy windres; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_ac_ct_RC+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$ac_ct_RC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_RC+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$ac_ct_RC"; then
  ac_cv_prog_ac_ct_RC="$ac_ct_RC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_ac_ct_RC="windres"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
ac_ct_RC=$ac_cv_prog_ac_ct_RC
if test -n "$ac_ct_RC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RC" >&5
$as_echo "$ac_ct_RC" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RC" >&5
printf "%s\n" "$ac_ct_RC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi

  if test "x$ac_ct_RC" = x; then
    RC=""
  else
    case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
    RC=$ac_ct_RC
  fi
else
  RC="$ac_cv_prog_RC"
fi


#--------------------------------------------------------------------
# Checks to see if the make program sets the $MAKE variable.
#--------------------------------------------------------------------

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
set x ${MAKE-make}
ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat >conftest.make <<\_ACEOF
ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
if eval test \${ac_cv_prog_make_${ac_make}_set+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat >conftest.make <<\_ACEOF
SHELL = /bin/sh
all:
	@echo '@@@%%%=$(MAKE)=@@@%%%'
_ACEOF
# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
case `${MAKE-make} -f conftest.make 2>/dev/null` in
  *@@@%%%=?*=@@@%%%*)
    eval ac_cv_prog_make_${ac_make}_set=yes;;
  *)
    eval ac_cv_prog_make_${ac_make}_set=no;;
esac
rm -f conftest.make
rm -f conftest.make ;;
esac
fi
if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
  SET_MAKE=
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
  SET_MAKE="MAKE=${MAKE-make}"
fi


#--------------------------------------------------------------------
# Determines the correct binary file extension (.o, .obj, .exe etc.)
#--------------------------------------------------------------------




#------------------------------------------------------------------------
# Embedded configuration information, encoding to use for the values, TIP #59
#------------------------------------------------------------------------



# Check whether --with-encoding was given.
if test "${with_encoding+set}" = set; then :
if test ${with_encoding+y}
then :
  withval=$with_encoding; with_tcencoding=${withval}
fi


    if test x"${with_tcencoding}" != x ; then
	cat >>confdefs.h <<_ACEOF
#define TCL_CFGVAL_ENCODING "${with_tcencoding}"
	printf "%s\n" "#define TCL_CFGVAL_ENCODING \"${with_tcencoding}\"" >>confdefs.h
_ACEOF

    else
	$as_echo "#define TCL_CFGVAL_ENCODING \"utf-8\"" >>confdefs.h
	printf "%s\n" "#define TCL_CFGVAL_ENCODING \"utf-8\"" >>confdefs.h

    fi


#--------------------------------------------------------------------
# The statements below define a collection of symbols related to
# building libtcl as a shared library instead of a static library.
#--------------------------------------------------------------------


    { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to build libraries" >&5
$as_echo_n "checking how to build libraries... " >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to build libraries" >&5
printf %s "checking how to build libraries... " >&6; }
    # Check whether --enable-shared was given.
if test "${enable_shared+set}" = set; then :
if test ${enable_shared+y}
then :
  enableval=$enable_shared; tcl_ok=$enableval
else
  tcl_ok=yes
else case e in #(
  e) tcl_ok=yes ;;
fi

esac

    if test "${enable_shared+set}" = set; then
	enableval="$enable_shared"
	tcl_ok=$enableval
    else
	tcl_ok=yes
    fi
fi

    if test "$tcl_ok" = "yes" ; then
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: shared" >&5
$as_echo "shared" >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: shared" >&5
printf "%s\n" "shared" >&6; }
	SHARED_BUILD=1
    else
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: static" >&5
$as_echo "static" >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: static" >&5
printf "%s\n" "static" >&6; }
	SHARED_BUILD=0

$as_echo "#define STATIC_BUILD 1" >>confdefs.h
printf "%s\n" "#define STATIC_BUILD 1" >>confdefs.h

    fi



#--------------------------------------------------------------------
# The statements below define a collection of compile flags.  This
# macro depends on the value of SHARED_BUILD, and should be called
# after SC_ENABLE_SHARED checks the configure switches.
#--------------------------------------------------------------------

# On IRIX 5.3, sys/types and inttypes.h are conflicting.
for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
ac_header= ac_cache=
		  inttypes.h stdint.h unistd.h
do :
  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
  cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
for ac_item in $ac_header_c_list
do
  if test $ac_cache; then
    ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
    if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
      printf "%s\n" "#define $ac_item 1" >> confdefs.h
    fi
    ac_header= ac_cache=
  elif test $ac_header; then
    ac_cache=$ac_item
  else
    ac_header=$ac_item
  fi
done






fi


if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
done
then :

printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h

fi


    # Step 0: Enable 64 bit support?

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested" >&5
$as_echo_n "checking if 64bit support is requested... " >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested" >&5
printf %s "checking if 64bit support is requested... " >&6; }
    # Check whether --enable-64bit was given.
if test "${enable_64bit+set}" = set; then :
if test ${enable_64bit+y}
then :
  enableval=$enable_64bit; do64bit=$enableval
else
  do64bit=no
else case e in #(
  e) do64bit=no ;;
esac
fi

    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5
$as_echo "$do64bit" >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5
printf "%s\n" "$do64bit" >&6; }

    # Set some defaults (may get changed below)
    EXTRA_CFLAGS=""

$as_echo "#define MODULE_SCOPE extern" >>confdefs.h
printf "%s\n" "#define MODULE_SCOPE extern" >>confdefs.h


    # Extract the first word of "cygpath", so it can be a program name with args.
set dummy cygpath; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CYGPATH+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$CYGPATH"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CYGPATH+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$CYGPATH"; then
  ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_CYGPATH="cygpath -m"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

  test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo"
fi
fi ;;
esac
fi
CYGPATH=$ac_cv_prog_CYGPATH
if test -n "$CYGPATH"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5
$as_echo "$CYGPATH" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5
printf "%s\n" "$CYGPATH" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi


    # Extract the first word of "wine", so it can be a program name with args.
set dummy wine; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_WINE+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test -n "$WINE"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_WINE+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -n "$WINE"; then
  ac_cv_prog_WINE="$WINE" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_exec_ext in '' $ac_executable_extensions; do
  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
    ac_cv_prog_WINE="wine"
    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
    break 2
  fi
done
  done
IFS=$as_save_IFS

fi
fi ;;
esac
fi
WINE=$ac_cv_prog_WINE
if test -n "$WINE"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WINE" >&5
$as_echo "$WINE" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $WINE" >&5
printf "%s\n" "$WINE" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi



    SHLIB_SUFFIX=".dll"

    # MACHINE is IX86 for LINK, but this is used by the manifest,
    # which requires x86|amd64|ia64.
    # which requires x86|amd64|arm64|ia64.
    MACHINE="X86"

    if test "$GCC" = "yes"; then

      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cross-compile version of gcc" >&5
$as_echo_n "checking for cross-compile version of gcc... " >&6; }
if ${ac_cv_cross+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for cross-compile version of gcc" >&5
printf %s "checking for cross-compile version of gcc... " >&6; }
if test ${ac_cv_cross+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	    #ifndef _WIN32
		#error cross-compiler
	    #endif

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_cross=no
else
  ac_cv_cross=yes
else case e in #(
  e) ac_cv_cross=yes ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
       ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cross" >&5
$as_echo "$ac_cv_cross" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cross" >&5
printf "%s\n" "$ac_cv_cross" >&6; }

      if test "$ac_cv_cross" = "yes"; then
	case "$do64bit" in
	    amd64|x64|yes)
		CC="x86_64-w64-mingw32-${CC}"
		LD="x86_64-w64-mingw32-ld"
		AR="x86_64-w64-mingw32-ar"
		RANLIB="x86_64-w64-mingw32-ranlib"
		RC="x86_64-w64-mingw32-windres"
	    ;;
	    arm64|aarch64)
		CC="aarch64-w64-mingw32-${CC}"
		LD="aarch64-w64-mingw32-ld"
		AR="aarch64-w64-mingw32-ar"
		RANLIB="aarch64-w64-mingw32-ranlib"
		RC="aarch64-w64-mingw32-windres"
	    ;;
	    *)
		CC="i686-w64-mingw32-${CC}"
		LD="i686-w64-mingw32-ld"
		AR="i686-w64-mingw32-ar"
		RANLIB="i686-w64-mingw32-ranlib"
		RC="i686-w64-mingw32-windres"
	    ;;
3979
3980
3981
3982
3983
3984
3985
3986
3987


3988
3989
3990
3991
3992
3993

3994
3995
3996


3997
3998
3999


4000
4001
4002
4003
4004
4005
4006
4007

4008
4009

4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022







4023
4024
4025
4026
4027
4028
4029
4030

4031
4032
4033
4034
4035
4036
4037


4038
4039
4040



4041
4042
4043



4044
4045
4046


4047
4048
4049



4050
4051
4052
4053
4054
4055
4056
4057







4058
4059
4060
4061
4062
4063
4064

4065
4066
4067
4068
4069
4070
4071

4072
4073
4074
4075
4076
4077
4078
4079

4080
4081
4082
4083
4084
4085

4086

4087
4088
4089


4090
4091
4092


4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110

4111
4112
4113
4114
4115
4116
4117


4118
4119
4120



4121
4122

4123
4124


4125
4126
4127


4128
4129
4130
4131
4132
4133
























4134























4135






























































4136
4137


4138
4139
4140
4141
4142
4143

4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159


4160
4161
4162
4163
4164
4165
4166


4167
4168
4169
4170
4171

4172
4173
4174
4175
4176
4177
4178
4164
4165
4166
4167
4168
4169
4170


4171
4172
4173
4174
4175
4176
4177

4178
4179


4180
4181
4182


4183
4184
4185
4186
4187
4188
4189
4190
4191

4192
4193

4194
4195
4196
4197
4198
4199
4200
4201






4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215

4216
4217
4218
4219
4220
4221
4222

4223
4224
4225


4226
4227
4228
4229


4230
4231
4232
4233


4234
4235
4236
4237
4238
4239
4240
4241
4242
4243






4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256

4257
4258
4259
4260
4261
4262
4263

4264
4265
4266
4267
4268
4269
4270
4271

4272
4273
4274
4275
4276
4277
4278
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
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
4436
4437
4438
4439
4440
4441


4442
4443
4444
4445
4446
4447
4448

4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463


4464
4465
4466
4467
4468
4469
4470


4471
4472
4473
4474
4475
4476

4477
4478
4479
4480
4481
4482
4483
4484







-
-
+
+





-
+

-
-
+
+

-
-
+
+







-
+

-
+







-
-
-
-
-
-
+
+
+
+
+
+
+







-
+






-
+
+

-
-
+
+
+

-
-
+
+
+

-
-
+
+



+
+
+


-
-
-
-
-
-
+
+
+
+
+
+
+






-
+






-
+







-
+






+
-
+

-
-
+
+


-
+
+

















-
+






-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
+
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+





-
+














-
-
+
+





-
-
+
+




-
+








    if test "$GCC" = "yes" && test "$CYGPATH" != "echo" ; then
	conftest=/tmp/conftest.rc
	echo "STRINGTABLE BEGIN" > $conftest
	echo "101 \"name\"" >> $conftest
	echo "END" >> $conftest

	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Windows native path bug in windres" >&5
$as_echo_n "checking for Windows native path bug in windres... " >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Windows native path bug in windres" >&5
printf %s "checking for Windows native path bug in windres... " >&6; }
	cyg_conftest=`$CYGPATH $conftest`
	if { ac_try='$RC -o conftest.res.o $cyg_conftest'
  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }; } ; then
	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
	else
	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
	    CYGPATH=echo
	fi
	conftest=
	cyg_conftest=
    fi

    if test "$CYGPATH" = "echo"; then
        DEPARG='"$<"'
	DEPARG='"$<"'
    else
        DEPARG='"$(shell $(CYGPATH) $<)"'
	DEPARG='"$(shell $(CYGPATH) $<)"'
    fi

    # set various compiler flags depending on whether we are using gcc or cl

    if test "${GCC}" = "yes" ; then
	extra_cflags="-pipe"
	extra_ldflags="-pipe -static-libgcc"
	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for mingw32 version of gcc" >&5
$as_echo_n "checking for mingw32 version of gcc... " >&6; }
if ${ac_cv_win32+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mingw32 version of gcc" >&5
printf %s "checking for mingw32 version of gcc... " >&6; }
if test ${ac_cv_win32+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

		#ifdef _WIN32
		    #error win32
		#endif

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_win32=no
else
  ac_cv_win32=yes
else case e in #(
  e) ac_cv_win32=yes ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
	 ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_win32" >&5
$as_echo "$ac_cv_win32" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_win32" >&5
printf "%s\n" "$ac_cv_win32" >&6; }
	if test "$ac_cv_win32" != "yes"; then
	    as_fn_error $? "${CC} cannot produce win32 executables." "$LINENO" 5
	fi
	if test "$do64bit" != "arm64"; then
	    extra_cflags="$extra_cflags -DHAVE_CPUID=1"
	fi

	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -mwindows -municode -Dmain=xxmain"
	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working -municode linker flag" >&5
$as_echo_n "checking for working -municode linker flag... " >&6; }
if ${ac_cv_municode+:} false; then :
  $as_echo_n "(cached) " >&6
else

	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working -municode linker flag" >&5
printf %s "checking for working -municode linker flag... " >&6; }
if test ${ac_cv_municode+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
# ac_fn_c_try_link LINENO
# -----------------------
# Try to link conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_link ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  rm -f conftest.$ac_objext conftest$ac_exeext
  rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
  if { { ac_try="$ac_link"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link") 2>conftest.err
  ac_status=$?
  if test -s conftest.err; then
    grep -v '^ *+' conftest.err >conftest.er1
    cat conftest.er1 >&5
    mv -f conftest.er1 conftest.err
  fi
  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; } && {
	 test -z "$ac_c_werror_flag" ||
	 test ! -s conftest.err
       } && test -s conftest$ac_exeext && {
	 test "$cross_compiling" = yes ||
	 test -x conftest$ac_exeext
       }
       }; then :
then :
  ac_retval=0
else
  $as_echo "$as_me: failed program was:" >&5
else case e in #(
  e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

	ac_retval=1
	ac_retval=1 ;;
esac
fi
  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
  # interfere with the next link command; also delete a directory that is
  # left behind by Apple's compiler.  We do this before executing the actions.
  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
  as_fn_set_status $ac_retval

} # ac_fn_c_try_link
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	#include <windows.h>
	int APIENTRY wWinMain(HINSTANCE a, HINSTANCE b, LPWSTR c, int d) {return 0;}

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_municode=yes
else
  ac_cv_municode=no
else case e in #(
  e) ac_cv_municode=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext

	 ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_municode" >&5
$as_echo "$ac_cv_municode" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_municode" >&5
printf "%s\n" "$ac_cv_municode" >&6; }
	CFLAGS=$hold_cflags
	if test "$ac_cv_municode" = "yes" ; then
	    extra_ldflags="$extra_ldflags -municode"
	else
	    extra_cflags="$extra_cflags -DTCL_BROKEN_MAINARGS"
	fi
	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -fno-lto"
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working -fno-lto" >&5
printf %s "checking for working -fno-lto... " >&6; }
if test ${ac_cv_nolto+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_nolto=yes
else case e in #(
  e) ac_cv_nolto=no ;;
esac
    fi
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
	 ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_nolto" >&5
printf "%s\n" "$ac_cv_nolto" >&6; }
	CFLAGS=$hold_cflags
	if test "$ac_cv_nolto" = "yes" ; then
	    CFLAGS_NOLTO="-fno-lto"
	else
	    CFLAGS_NOLTO=""
	fi
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the compiler understands -finput-charset" >&5
printf %s "checking if the compiler understands -finput-charset... " >&6; }
if test ${tcl_cv_cc_input_charset+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -finput-charset=UTF-8"
	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_cc_input_charset=yes
else case e in #(
  e) tcl_cv_cc_input_charset=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
	    CFLAGS=$hold_cflags ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_input_charset" >&5
printf "%s\n" "$tcl_cv_cc_input_charset" >&6; }
	if test $tcl_cv_cc_input_charset = yes; then
	    extra_cflags="$extra_cflags -finput-charset=UTF-8"
	fi
    fi

    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Wl,--enable-auto-image-base"
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working --enable-auto-image-base" >&5
printf %s "checking for working --enable-auto-image-base... " >&6; }
if test ${ac_cv_enable_auto_image_base+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_enable_auto_image_base=yes
else case e in #(
  e) ac_cv_enable_auto_image_base=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
     ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_auto_image_base" >&5
printf "%s\n" "$ac_cv_enable_auto_image_base" >&6; }
    CFLAGS=$hold_cflags
    if test "$ac_cv_enable_auto_image_base" = "yes" ; then
	extra_ldflags="$extra_ldflags -Wl,--enable-auto-image-base"
    fi

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking compiler flags" >&5
$as_echo_n "checking compiler flags... " >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking compiler flags" >&5
printf %s "checking compiler flags... " >&6; }
    if test "${GCC}" = "yes" ; then
	SHLIB_LD=""
	SHLIB_LD_LIBS='${LIBS}'
	LIBS="-lnetapi32 -lkernel32 -luser32 -ladvapi32 -luserenv -lws2_32"
	# mingw needs to link ole32 and oleaut32 for [send], but MSVC doesn't
	LIBS_GUI="-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32 -luuid -lole32 -loleaut32"
	LIBS_GUI="-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32 -luuid -lole32 -loleaut32 -lwinspool"
	STLIB_LD='${AR} cr'
	RC_OUT=-o
	RC_TYPE=
	RC_INCLUDE=--include
	RC_DEFINE=--define
	RES=res.o
	MAKE_LIB="\${STLIB_LD} \$@"
	MAKE_STUB_LIB="\${STLIB_LD} \$@"
	POST_MAKE_LIB="\${RANLIB} \$@"
	MAKE_EXE="\${CC} -o \$@"
	LIBPREFIX="lib"

	if test "${SHARED_BUILD}" = "0" ; then
	    # static
            { $as_echo "$as_me:${as_lineno-$LINENO}: result: using static flags" >&5
$as_echo "using static flags" >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: using static flags" >&5
printf "%s\n" "using static flags" >&6; }
	    runtime=
	    LIBRARIES="\${STATIC_LIBRARIES}"
	    EXESUFFIX="s.exe"
	else
	    # dynamic
            { $as_echo "$as_me:${as_lineno-$LINENO}: result: using shared flags" >&5
$as_echo "using shared flags" >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: using shared flags" >&5
printf "%s\n" "using shared flags" >&6; }

	    # ad-hoc check to see if CC supports -shared.
	    if "${CC}" -shared 2>&1 | egrep ': -shared not supported' >/dev/null; then
		as_fn_error $? "${CC} does not support the -shared option.
                You will need to upgrade to a newer version of the toolchain." "$LINENO" 5
		You will need to upgrade to a newer version of the toolchain." "$LINENO" 5
	    fi

	    runtime=
	    # Add SHLIB_LD_LIBS to the Make rule, not here.

	    EXESUFFIX=".exe"
	    LIBRARIES="\${SHARED_LIBRARIES}"
4199
4200
4201
4202
4203
4204
4205
4206

4207
4208
4209
4210
4211
4212
4213
4505
4506
4507
4508
4509
4510
4511

4512
4513
4514
4515
4516
4517
4518
4519







-
+







	LDFLAGS_OPTIMIZE=

	case "${CC}" in
	    *++)
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wno-format"
		;;
	    *)
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wc++-compat -Wdeclaration-after-statement"
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wc++-compat -fextended-identifiers"
		;;
	esac

	# Specify the CC output file names based on the target name
	CC_OBJNAME="-o \$@"
	CC_EXENAME="-o \$@"

4227
4228
4229
4230
4231
4232
4233
4234
4235







4236
4237
4238
4239
4240


4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251

4252
4253
4254
4255
4256
4257
4258


4259
4260
4261
4262




4263
4264

4265
4266
4267
4268
4269




4270
4271
4272
4273
4274
4275
4276
4277


4278
4279
4280
4281
4282
4283
4284


4285
4286
4287
4288
4289
4290
4291
4533
4534
4535
4536
4537
4538
4539


4540
4541
4542
4543
4544
4545
4546
4547
4548
4549


4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561

4562
4563
4564
4565
4566
4567
4568

4569
4570
4571



4572
4573
4574
4575
4576

4577
4578




4579
4580
4581
4582
4583
4584
4585
4586
4587
4588


4589
4590
4591
4592
4593
4594
4595


4596
4597
4598
4599
4600
4601
4602
4603
4604







-
-
+
+
+
+
+
+
+



-
-
+
+










-
+






-
+
+

-
-
-
+
+
+
+

-
+

-
-
-
-
+
+
+
+






-
-
+
+





-
-
+
+







	#LDFLAGS_WINDOW="-mwindows -e _WinMain@16 ${extra_ldflags}"
	LDFLAGS_CONSOLE="-mconsole ${extra_ldflags}"
	LDFLAGS_WINDOW="-mwindows ${extra_ldflags}"

	case "$do64bit" in
	    amd64|x64|yes)
		MACHINE="AMD64" ; # assume AMD64 as default 64-bit build
		{ $as_echo "$as_me:${as_lineno-$LINENO}: result:    Using 64-bit $MACHINE mode" >&5
$as_echo "   Using 64-bit $MACHINE mode" >&6; }
		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:    Using 64-bit $MACHINE mode" >&5
printf "%s\n" "   Using 64-bit $MACHINE mode" >&6; }
		;;
	    arm64|aarch64)
		MACHINE="ARM64"
		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:    Using ARM64 $MACHINE mode" >&5
printf "%s\n" "   Using ARM64 $MACHINE mode" >&6; }
		;;
	    ia64)
		MACHINE="IA64"
		{ $as_echo "$as_me:${as_lineno-$LINENO}: result:    Using 64-bit $MACHINE mode" >&5
$as_echo "   Using 64-bit $MACHINE mode" >&6; }
		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:    Using IA64 $MACHINE mode" >&5
printf "%s\n" "   Using IA64 $MACHINE mode" >&6; }
		;;
	    *)
		cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

		    #ifndef _WIN64
			#error 32-bit
		    #endif

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_win_64bit=yes
else
  tcl_win_64bit=no

else case e in #(
  e) tcl_win_64bit=no
		 ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
		if test "$tcl_win_64bit" = "yes" ; then
			do64bit=amd64
			MACHINE="AMD64"
			{ $as_echo "$as_me:${as_lineno-$LINENO}: result:    Using 64-bit $MACHINE mode" >&5
$as_echo "   Using 64-bit $MACHINE mode" >&6; }
		    do64bit=amd64
		    MACHINE="AMD64"
		    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:    Using 64-bit $MACHINE mode" >&5
printf "%s\n" "   Using 64-bit $MACHINE mode" >&6; }
		fi
		;;
	esac
    else
	if test "${SHARED_BUILD}" = "0" ; then
	    # static
            { $as_echo "$as_me:${as_lineno-$LINENO}: result: using static flags" >&5
$as_echo "using static flags" >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: using static flags" >&5
printf "%s\n" "using static flags" >&6; }
	    runtime=-MT
	    LIBRARIES="\${STATIC_LIBRARIES}"
	    EXESUFFIX="s.exe"
	else
	    # dynamic
            { $as_echo "$as_me:${as_lineno-$LINENO}: result: using shared flags" >&5
$as_echo "using shared flags" >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: using shared flags" >&5
printf "%s\n" "using shared flags" >&6; }
	    runtime=-MD
	    # Add SHLIB_LD_LIBS to the Make rule, not here.
	    LIBRARIES="\${SHARED_LIBRARIES}"
	    EXESUFFIX=".exe"
	    case "x`echo \${VisualStudioVersion}`" in
		x1[4-9]*)
		    lflags="${lflags} -nodefaultlib:libucrt.lib"
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
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628


4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645


4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662

4663
4664
4665
4666
4667
4668
4669
4670







+
+
+




-
-
+
+















-
-
+
















-
+







	LIBFLAGSUFFIX=""

	if test "$do64bit" != "no" ; then
	    case "$do64bit" in
		amd64|x64|yes)
		    MACHINE="AMD64" ; # assume AMD64 as default 64-bit build
		    ;;
		arm64|aarch64)
		    MACHINE="ARM64"
		    ;;
		ia64)
		    MACHINE="IA64"
		    ;;
	    esac
	    { $as_echo "$as_me:${as_lineno-$LINENO}: result:    Using 64-bit $MACHINE mode" >&5
$as_echo "   Using 64-bit $MACHINE mode" >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:    Using 64-bit $MACHINE mode" >&5
printf "%s\n" "   Using 64-bit $MACHINE mode" >&6; }
	fi

	LIBS="netapi32.lib kernel32.lib user32.lib advapi32.lib userenv.lib ws2_32.lib"

	case "x`echo \${VisualStudioVersion}`" in
		x1[4-9]*)
		    LIBS="$LIBS ucrt.lib"
		    ;;
		*)
		    ;;
	esac

	if test "$do64bit" != "no" ; then
	    RC="rc"
	    CFLAGS_DEBUG="-nologo -Zi -Od ${runtime}d"
	    # Do not use -O2 for Win64 - this has proved buggy in code gen.
	    CFLAGS_OPTIMIZE="-nologo -O1 ${runtime}"
	    CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}"
	    lflags="${lflags} -nologo -MACHINE:${MACHINE}"
	    LINKBIN="link"
	    # Avoid 'unresolved external symbol __security_cookie' errors.
	    # c.f. http://support.microsoft.com/?id=894573
	    LIBS="$LIBS bufferoverflowU.lib"
	else
	    RC="rc"
	    # -Od - no optimization
	    # -WX - warnings as errors
	    CFLAGS_DEBUG="-nologo -Z7 -Od -WX ${runtime}d"
	    # -O2 - create fast code (/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy)
	    CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}"
	    lflags="${lflags} -nologo"
	    LINKBIN="link"
	fi

	LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib"
	LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib winspool.lib"

	SHLIB_LD="${LINKBIN} -dll -incremental:no ${lflags}"
	SHLIB_LD_LIBS='${LIBS}'
	# link -lib only works when -lib is the first arg
	STLIB_LD="${LINKBIN} -lib ${lflags}"
	RC_OUT=-fo
	RC_TYPE=-r
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
4436

4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451







4452
4453
4454
4455
4456
4457
4458
4459

4460
4461
4462
4463
4464
4465
4466
4467
4468


4469
4470
4471



4472
4473
4474



4475
4476
4477


4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504


4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517

4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530



4531
4532

4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547







4548
4549
4550
4551

4552
4553
4554
4555
4556
4557
4558
4559
4560
4561


4562
4563
4564



4565
4566
4567



4568
4569
4570


4571
4572
4573

4574
4575
4576
4577
4578

4579
4580
4581
4582
4583
4584
4585
4697
4698
4699
4700
4701
4702
4703

4704
4705
4706
4707
4708






4709
4710
4711
4712
4713
4714
4715
4716
4717


4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781

4782
4783
4784


4785
4786
4787
4788
4789

4790
4791
4792
4793

4794
4795
4796


4797
4798
4799
4800

4801
4802
4803
4804
4805
4806
4807
4808
4809
4810






4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824

4825
4826
4827
4828
4829
4830
4831
4832
4833

4834
4835
4836


4837
4838
4839
4840


4841
4842
4843
4844


4845
4846
4847


























4848
4849



4850









4851

4852











4853
4854
4855
4856

4857
4858
4859

4860
4861
4862
4863
4864
4865






4866
4867
4868
4869
4870
4871
4872
4873
4874
4875

4876
4877
4878
4879
4880
4881
4882
4883
4884
4885

4886
4887
4888


4889
4890
4891
4892


4893
4894
4895
4896


4897
4898
4899
4900

4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914







-
+




-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-
+
+

-
-
+
+
+


-
+
+


-
+
+

-
-
+
+


-
+









-
-
-
-
-
-
+
+
+
+
+
+
+







-
+








-
+
+

-
-
+
+
+

-
-
+
+
+

-
-
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-

-
-
-
-
-
-
-
-
-
+
-

-
-
-
-
-
-
-
-
-
-
-
+
+
+

-
+


-






-
-
-
-
-
-
+
+
+
+
+
+
+



-
+









-
+
+

-
-
+
+
+

-
-
+
+
+

-
-
+
+


-
+





+







	else
	    LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}"
	    LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}"
	fi
    fi

    if test "$do64bit" != "no" ; then
	$as_echo "#define TCL_CFG_DO64BIT 1" >>confdefs.h
	printf "%s\n" "#define TCL_CFG_DO64BIT 1" >>confdefs.h

    fi

    if test "${GCC}" = "yes" ; then
	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SEH support in compiler" >&5
$as_echo_n "checking for SEH support in compiler... " >&6; }
if ${tcl_cv_seh+:} false; then :
  $as_echo_n "(cached) " >&6
else
  if test "$cross_compiling" = yes; then :
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SEH support in compiler" >&5
printf %s "checking for SEH support in compiler... " >&6; }
if test ${tcl_cv_seh+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test "$cross_compiling" = yes
then :
  tcl_cv_seh=no
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
else case e in #(
  e)
# ac_fn_c_try_run LINENO
# ----------------------
# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that
# executables *can* be run.
ac_fn_c_try_run ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
  if { { ac_try="$ac_link"
case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link") 2>&5
  ac_status=$?
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
  { { case "(($ac_try" in
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
  *) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_try") 2>&5
  ac_status=$?
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }; }
then :
  ac_retval=0
else case e in #(
  e) printf "%s\n" "$as_me: program exited with status $ac_status" >&5
       printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

       ac_retval=$ac_status ;;
esac
fi
  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
  as_fn_set_status $ac_retval

} # ac_fn_c_try_run
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	    #define WIN32_LEAN_AND_MEAN
	    #include <windows.h>
	    #undef WIN32_LEAN_AND_MEAN

	    int main(int argc, char** argv) {
		int a, b = 0;
		__try {
		    a = 666 / b;
		}
		__except (EXCEPTION_EXECUTE_HANDLER) {
		    return 0;
		}
		return 1;
	    }

_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
if ac_fn_c_try_run "$LINENO"
then :
  tcl_cv_seh=yes
else
  tcl_cv_seh=no
else case e in #(
  e) tcl_cv_seh=no ;;
esac
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
  conftest.$ac_objext conftest.beam conftest.$ac_ext
  conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi


	 ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_seh" >&5
$as_echo "$tcl_cv_seh" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_seh" >&5
printf "%s\n" "$tcl_cv_seh" >&6; }
	if test "$tcl_cv_seh" = "no" ; then

$as_echo "#define HAVE_NO_SEH 1" >>confdefs.h
printf "%s\n" "#define HAVE_NO_SEH 1" >>confdefs.h

	fi

	#
	# Check to see if the excpt.h include file provided contains the
	# definition for EXCEPTION_DISPOSITION; if not, which is the case
	# with Cygwin's version as of 2002-04-10, define it to be int,
	# sufficient for getting the current code to work.
	#
	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for EXCEPTION_DISPOSITION support in include files" >&5
$as_echo_n "checking for EXCEPTION_DISPOSITION support in include files... " >&6; }
if ${tcl_cv_eh_disposition+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for EXCEPTION_DISPOSITION support in include files" >&5
printf %s "checking for EXCEPTION_DISPOSITION support in include files... " >&6; }
if test ${tcl_cv_eh_disposition+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

#	    define WIN32_LEAN_AND_MEAN
#	    include <windows.h>
#	    undef WIN32_LEAN_AND_MEAN

int
main ()
main (void)
{

		EXCEPTION_DISPOSITION x;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_eh_disposition=yes
else
  tcl_cv_eh_disposition=no
else case e in #(
  e) tcl_cv_eh_disposition=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
	 ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_eh_disposition" >&5
$as_echo "$tcl_cv_eh_disposition" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_eh_disposition" >&5
printf "%s\n" "$tcl_cv_eh_disposition" >&6; }
	if test "$tcl_cv_eh_disposition" = "no" ; then

$as_echo "#define EXCEPTION_DISPOSITION int" >>confdefs.h

	fi

	# Check to see if winnt.h defines CHAR, SHORT, and LONG
	# even if VOID has already been #defined. The win32api
	# used by mingw and cygwin is known to do this.

	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for winnt.h that ignores VOID define" >&5
$as_echo_n "checking for winnt.h that ignores VOID define... " >&6; }
if ${tcl_cv_winnt_ignore_void+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

		#define VOID void
		#define WIN32_LEAN_AND_MEAN
		#include <windows.h>
		#undef WIN32_LEAN_AND_MEAN

int
main ()
{


printf "%s\n" "#define EXCEPTION_DISPOSITION int" >>confdefs.h
		CHAR c;
		SHORT s;
		LONG l;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  tcl_cv_winnt_ignore_void=yes
else
  tcl_cv_winnt_ignore_void=no
fi
	fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_winnt_ignore_void" >&5
$as_echo "$tcl_cv_winnt_ignore_void" >&6; }
	if test "$tcl_cv_winnt_ignore_void" = "yes" ; then

$as_echo "#define HAVE_WINNT_IGNORE_VOID 1" >>confdefs.h

	fi

	ac_fn_c_check_header_mongrel "$LINENO" "stdbool.h" "ac_cv_header_stdbool_h" "$ac_includes_default"
if test "x$ac_cv_header_stdbool_h" = xyes; then :
	ac_fn_c_check_header_compile "$LINENO" "stdbool.h" "ac_cv_header_stdbool_h" "$ac_includes_default"
if test "x$ac_cv_header_stdbool_h" = xyes
then :

$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h
printf "%s\n" "#define HAVE_STDBOOL_H 1" >>confdefs.h

fi



	# See if the compiler supports casting to a union type.
	# This is used to stop gcc from printing a compiler
	# warning when initializing a union member.

	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for cast to union support" >&5
$as_echo_n "checking for cast to union support... " >&6; }
if ${tcl_cv_cast_to_union+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for cast to union support" >&5
printf %s "checking for cast to union support... " >&6; }
if test ${tcl_cv_cast_to_union+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
main (void)
{

		  union foo { int i; double d; };
		  union foo f = (union foo) (int) 0;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_cast_to_union=yes
else
  tcl_cv_cast_to_union=no
else case e in #(
  e) tcl_cv_cast_to_union=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
	 ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cast_to_union" >&5
$as_echo "$tcl_cv_cast_to_union" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cast_to_union" >&5
printf "%s\n" "$tcl_cv_cast_to_union" >&6; }
	if test "$tcl_cv_cast_to_union" = "yes"; then

$as_echo "#define HAVE_CAST_TO_UNION 1" >>confdefs.h
printf "%s\n" "#define HAVE_CAST_TO_UNION 1" >>confdefs.h

	fi
    fi

    # DL_LIBS is empty, but then we match the Unix version







# Cross-compiling
4594
4595
4596
4597
4598
4599
4600
4601


4602
4603
4604
4605
4606
4607


4608
4609


4610


4611


4612
4613
4614
4615
4616
4617
4618

4619
4620


4621
4622
4623

4624



4625


4626
4627

4628
4629

4630


4631
4632



4633











4634

4635
4636

4637


4638











4639
4640
4641
4642


4643
4644
4645
4646
4647


4648
4649
4650




4651
4652
4653
4654
4655
4656


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

4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704

4705
4706
4707
4708

4709
4710
4711
4712
4713
4714
4715
4716
4717

4718
4719
4720
4721
4722
4723
4724
4725
4726

4727
4728
4729

4730
4731
4732

4733
4734
4735

4736
4737
4738
4739

4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755


4756
4757

4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771


4772
4773
4774



4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791







4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804


4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821







4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832


4833
4834
4835


4836
4837
4838
4839
4840
4841
4842
4843
4844
4845


4846
4847
4848
4849
4850





4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863


4864
4865
4866
4867
4868
4869
4870


4871
4872
4873
4874
4875


4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890







4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901









4902
4903


4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914








4915
4916
4917
4918
4919
4920
4921
4922
4923








4924
4925
4926
4927
4928
4929
4930
4931

4932
4933
4934
4935
4936
4937
4938


4939
4940
4941
4942
4943

4944
4945
4946
4947
4948
4949
4950

4951
4952
4953
4954



4955
4956
4957
4958


4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981







4982
4983
4984
4985
4986
4987
4988
4989

4990
4991
4992
4993
4994
4995
4996
4997
4998
4999


5000
5001
5002



5003
5004
5005



5006
5007
5008


5009
5010
5011

5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022







5023
5024
5025
5026
5027
5028
5029
5030
5031

5032
5033
5034
5035
5036
5037
5038
5039
5040


5041
5042
5043



5044
5045

5046
5047


5048
5049
5050


5051
5052
5053

5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064







5065
5066
5067
5068
5069
5070

5071
5072
5073
5074
5075
5076
5077


5078
5079
5080



5081
5082
5083



5084
5085
5086


5087
5088
5089

5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102







5103
5104
5105
5106
5107
5108
5109
5110

5111
5112
5113
5114
5115
5116
5117
5118
5119
5120


5121
5122
5123



5124
5125
5126



5127
5128
5129


5130
5131
5132

5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144


5145
5146


5147
5148
5149



5150
5151
5152
5153
5154
5155
5156
5157

5158
5159
5160


5161
5162

5163
5164
5165
5166
5167
5168
5169


5170
5171
5172
5173
5174
5175
5176
5177

5178
5179
5180
5181
5182
5183

5184
5185
5186

5187
5188
5189
5190
5191
5192
5193


5194
5195
5196


5197
5198
5199
5200
5201
5202
5203
5204

































5205
















































































































































































































































5206
5207


5208
5209


5210
5211
5212



5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231


5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247

5248
5249
5250
5251


5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271


5272
5273
5274
5275
5276
5277


5278
5279

5280
5281
5282
5283


5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315

5316
5317

5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330

5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
4923
4924
4925
4926
4927
4928
4929

4930
4931
4932
4933
4934
4935


4936
4937
4938

4939
4940
4941
4942
4943

4944
4945
4946
4947
4948
4949
4950
4951

4952
4953

4954
4955
4956
4957

4958
4959
4960
4961
4962

4963
4964
4965

4966
4967

4968
4969
4970
4971
4972

4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987

4988
4989

4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007


5008
5009
5010
5011
5012
5013

5014
5015
5016
5017

5018
5019
5020
5021
5022
5023
5024
5025
5026

5027
5028
5029

5030

5031
5032
5033

5034


















5035



5036




5037

















5038




5039

5040







5041
5042

5043






5044



5045



5046



5047




5048
















5049
5050
5051

5052


5053

5054
5055

5056
5057
5058
5059
5060
5061

5062
5063
5064


5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078






5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097

5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110






5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127

5128
5129
5130


5131
5132
5133
5134
5135
5136
5137
5138
5139
5140


5141
5142
5143




5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160

5161
5162
5163
5164
5165
5166
5167


5168
5169
5170
5171
5172


5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183






5184
5185
5186
5187
5188
5189
5190
5191
5192









5193
5194
5195
5196
5197
5198
5199
5200
5201
5202

5203
5204
5205
5206
5207








5208
5209
5210
5211
5212
5213
5214
5215
5216








5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231

5232
5233
5234
5235
5236
5237


5238
5239
5240
5241
5242
5243

5244
5245



5246
5247

5248
5249



5250
5251
5252

5253


5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272






5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286

5287
5288
5289
5290
5291
5292
5293
5294
5295
5296

5297
5298
5299


5300
5301
5302
5303


5304
5305
5306
5307


5308
5309
5310
5311

5312
5313
5314
5315
5316
5317






5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332

5333
5334
5335
5336
5337
5338
5339
5340
5341

5342
5343
5344


5345
5346
5347
5348

5349
5350

5351
5352
5353


5354
5355
5356
5357

5358
5359
5360
5361
5362
5363






5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375

5376
5377
5378
5379
5380
5381
5382

5383
5384
5385


5386
5387
5388
5389


5390
5391
5392
5393


5394
5395
5396
5397

5398
5399
5400
5401
5402
5403
5404
5405






5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419

5420
5421
5422
5423
5424
5425
5426
5427
5428
5429

5430
5431
5432


5433
5434
5435
5436


5437
5438
5439
5440


5441
5442
5443
5444

5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455


5456
5457
5458

5459
5460
5461


5462
5463
5464
5465
5466
5467
5468
5469
5470
5471

5472
5473


5474
5475
5476

5477
5478
5479
5480
5481
5482


5483
5484
5485
5486
5487
5488
5489
5490
5491

5492
5493
5494
5495
5496
5497

5498
5499
5500

5501
5502
5503
5504
5505
5506


5507
5508
5509


5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793


5794
5795
5796

5797
5798
5799


5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820

5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837

5838
5839
5840


5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860


5861
5862
5863
5864
5865
5866
5867

5868
5869
5870
5871
5872
5873
5874


5875
5876
5877
5878
5879
5880
5881
5882

5883
5884
5885

5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905

5906
5907

5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920

5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937

5938
5939
5940
5941
5942
5943
5944







-
+
+




-
-
+
+

-
+
+

+
+
-
+
+






-
+

-
+
+


-
+

+
+
+
-
+
+

-
+

-
+

+
+

-
+
+
+

+
+
+
+
+
+
+
+
+
+
+
-
+

-
+

+
+

+
+
+
+
+
+
+
+
+
+
+


-
-
+
+




-
+
+


-
+
+
+
+





-
+
+

-
+
-

+

-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-

-
-
-
-
-
-
-
+

-

-
-
-
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+

-
+
-
-

-


-






-
+
+

-
-
+
+
+











-
-
-
-
-
-
+
+
+
+
+
+
+












-
+
+











-
-
-
-
-
-
+
+
+
+
+
+
+










-
+
+

-
-
+
+








-
-
+
+

-
-
-
-
+
+
+
+
+












-
+
+





-
-
+
+



-
-
+
+









-
-
-
-
-
-
+
+
+
+
+
+
+


-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
+
+



-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+







-
+





-
-
+
+




-
+

-
-
-


-
+

-
-
-
+
+
+
-

-
-
+
+

















-
-
-
-
-
-
+
+
+
+
+
+
+







-
+









-
+
+

-
-
+
+
+

-
-
+
+
+

-
-
+
+


-
+





-
-
-
-
-
-
+
+
+
+
+
+
+








-
+








-
+
+

-
-
+
+
+

-
+

-
+
+

-
-
+
+


-
+





-
-
-
-
-
-
+
+
+
+
+
+
+





-
+






-
+
+

-
-
+
+
+

-
-
+
+
+

-
-
+
+


-
+







-
-
-
-
-
-
+
+
+
+
+
+
+







-
+









-
+
+

-
-
+
+
+

-
-
+
+
+

-
-
+
+


-
+










-
-
+
+

-
+
+

-
-
+
+
+







-
+

-
-
+
+

-
+





-
-
+
+







-
+





-
+


-
+





-
-
+
+

-
-
+
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+

-
+
+

-
-
+
+
+


















-
+
+















-
+


-
-
+
+


















-
-
+
+





-
+
+


+


-
-
+
+






-



-




















-
+

-
+












-
+
















-








#------------------------------------------------------------------------
#	Add stuff for zlib/libtommath; note that this is mostly done in the
#	makefile now as we just assume that the platform hasn't got usable
#   z.lib/tommath.lib
#------------------------------------------------------------------------

if test "${enable_shared+set}" = "set"; then :
if test "${enable_shared+set}" = "set"
then :

  enableval="$enable_shared"
  tcl_ok=$enableval

else

else case e in #(
  e)
  tcl_ok=yes

 ;;
esac
fi
zlib_lib_name=zdll.lib
tommath_lib_name=tommath.lib
if test "$tcl_ok" = "yes"; then :
if test "$tcl_ok" = "yes"
then :

  ZLIB_DLL_FILE=\${ZLIB_DLL_FILE}

  TOMMATH_DLL_FILE=\${TOMMATH_DLL_FILE}


$as_echo "#define TCL_WITH_EXTERNAL_TOMMATH 1" >>confdefs.h
printf "%s\n" "#define TCL_WITH_EXTERNAL_TOMMATH 1" >>confdefs.h

  if test "$do64bit" != "no"; then :
  if test "$do64bit" != "no"
then :


$as_echo "#define MP_64BIT 1" >>confdefs.h
printf "%s\n" "#define MP_64BIT 1" >>confdefs.h

    if test "$do64bit" = "arm64"
then :

    if test "$GCC" == "yes"; then :
      if test "$GCC" = "yes"
then :

      ZLIB_LIBS=\${ZLIB_DIR_NATIVE}/win64/libz.dll.a
	ZLIB_LIBS=\${ZLIB_DIR_NATIVE}/win64-arm/libz.dll.a

      TOMMATH_LIBS=\${TOMMATH_DIR_NATIVE}/win64/libtommath.dll.a
	TOMMATH_LIBS=\${TOMMATH_DIR_NATIVE}/win64-arm/libtommath.dll.a

	zlib_lib_name=libz.dll.a
	tommath_lib_name=libtommath.dll.a

else
else case e in #(
  e)
	ZLIB_LIBS=\${ZLIB_DIR_NATIVE}/win64-arm/zdll.lib

	TOMMATH_LIBS=\${TOMMATH_DIR_NATIVE}/win64-arm/tommath.lib

       ;;
esac
fi

else case e in #(
  e)
      if test "$GCC" = "yes"
then :

      ZLIB_LIBS=\${ZLIB_DIR_NATIVE}/win64/zdll.lib
	ZLIB_LIBS=\${ZLIB_DIR_NATIVE}/win64/libz.dll.a

      TOMMATH_LIBS=\${TOMMATH_DIR_NATIVE}/win64/tommath.lib
	TOMMATH_LIBS=\${TOMMATH_DIR_NATIVE}/win64/libtommath.dll.a

	zlib_lib_name=libz.dll.a
	tommath_lib_name=libtommath.dll.a

else case e in #(
  e)
	ZLIB_LIBS=\${ZLIB_DIR_NATIVE}/win64/zdll.lib

	TOMMATH_LIBS=\${TOMMATH_DIR_NATIVE}/win64/tommath.lib

       ;;
esac
fi
     ;;
esac
fi

else

else case e in #(
  e)
    ZLIB_LIBS=\${ZLIB_DIR_NATIVE}/win32/zdll.lib

    TOMMATH_LIBS=\${TOMMATH_DIR_NATIVE}/win32/tommath.lib


   ;;
esac
fi

else
else case e in #(
  e)

printf "%s\n" "#define TCL_WITH_INTERNAL_ZLIB 1" >>confdefs.h

  ZLIB_OBJS=\${ZLIB_OBJS}

  TOMMATH_OBJS=\${TOMMATH_OBJS}


 ;;
esac
fi

TCL_ZLIB_LIB_NAME=$zlib_lib_name
$as_echo "#define HAVE_ZLIB 1" >>confdefs.h

TCL_TOMMATH_LIB_NAME=$tommath_lib_name

ac_fn_c_check_type "$LINENO" "intptr_t" "ac_cv_type_intptr_t" "$ac_includes_default"
ac_fn_c_check_type "$LINENO" "intptr_t" "ac_cv_type_intptr_t" "
if test "x$ac_cv_type_intptr_t" = xyes; then :


$as_echo "#define HAVE_INTPTR_T 1" >>confdefs.h

else

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pointer-size signed integer type" >&5
$as_echo_n "checking for pointer-size signed integer type... " >&6; }
if ${tcl_cv_intptr_t+:} false; then :
  $as_echo_n "(cached) " >&6
else

    for tcl_cv_intptr_t in "int" "long" "long long" none; do
	if test "$tcl_cv_intptr_t" != none; then
	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$ac_includes_default
#include <stdint.h>
int
main ()
{

static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_intptr_t))];
test_array [0] = 0;
return test_array [0];

"
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  tcl_ok=yes
else
  tcl_ok=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
	    test "$tcl_ok" = yes && break; fi
    done
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_intptr_t" >&5
$as_echo "$tcl_cv_intptr_t" >&6; }
    if test "$tcl_cv_intptr_t" != none; then

if test "x$ac_cv_type_intptr_t" = xyes
cat >>confdefs.h <<_ACEOF
#define intptr_t $tcl_cv_intptr_t
_ACEOF

then :
    fi

fi

ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "$ac_includes_default"
if test "x$ac_cv_type_uintptr_t" = xyes; then :


$as_echo "#define HAVE_UINTPTR_T 1" >>confdefs.h
printf "%s\n" "#define HAVE_INTPTR_T 1" >>confdefs.h

else

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pointer-size unsigned integer type" >&5
$as_echo_n "checking for pointer-size unsigned integer type... " >&6; }
if ${tcl_cv_uintptr_t+:} false; then :
  $as_echo_n "(cached) " >&6
else

fi
    for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \
	    none; do
	if test "$tcl_cv_uintptr_t" != none; then
ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "
	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$ac_includes_default
#include <stdint.h>
int
main ()
{

static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_uintptr_t))];
test_array [0] = 0;
return test_array [0];

"
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  tcl_ok=yes
else
  tcl_ok=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
	    test "$tcl_ok" = yes && break; fi
    done
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_uintptr_t" >&5
$as_echo "$tcl_cv_uintptr_t" >&6; }
    if test "$tcl_cv_uintptr_t" != none; then
if test "x$ac_cv_type_uintptr_t" = xyes
then :

cat >>confdefs.h <<_ACEOF
printf "%s\n" "#define HAVE_UINTPTR_T 1" >>confdefs.h
#define uintptr_t $tcl_cv_uintptr_t
_ACEOF

    fi

fi



#--------------------------------------------------------------------
#	Zipfs support - Tip 430
#--------------------------------------------------------------------
# Check whether --enable-zipfs was given.
if test "${enable_zipfs+set}" = set; then :
if test ${enable_zipfs+y}
then :
  enableval=$enable_zipfs; tcl_ok=$enableval
else
  tcl_ok=yes
else case e in #(
  e) tcl_ok=yes ;;
esac
fi

if test "$tcl_ok" = "yes" ; then
    #
    # Find a native compiler
    #
    # Put a plausible default for CC_FOR_BUILD in Makefile.
if test -z "$CC_FOR_BUILD"; then
  if test "x$cross_compiling" = "xno"; then
    CC_FOR_BUILD='$(CC)'
  else
    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc" >&5
$as_echo_n "checking for gcc... " >&6; }
    if ${ac_cv_path_cc+:} false; then :
  $as_echo_n "(cached) " >&6
else

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gcc" >&5
printf %s "checking for gcc... " >&6; }
    if test ${ac_cv_path_cc+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	search_path=`echo ${PATH} | sed -e 's/:/ /g'`
	for dir in $search_path ; do
	    for j in `ls -r $dir/gcc 2> /dev/null` \
		    `ls -r $dir/gcc 2> /dev/null` ; do
		if test x"$ac_cv_path_cc" = x ; then
		    if test -f "$j" ; then
			ac_cv_path_cc=$j
			break
		    fi
		fi
	    done
	done

     ;;
esac
fi

  fi
fi

# Also set EXEEXT_FOR_BUILD.
if test "x$cross_compiling" = "xno"; then
  EXEEXT_FOR_BUILD='$(EXEEXT)'
  OBJEXT_FOR_BUILD='$(OBJEXT)'
else
  OBJEXT_FOR_BUILD='.no'
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for build system executable suffix" >&5
$as_echo_n "checking for build system executable suffix... " >&6; }
if ${bfd_cv_build_exeext+:} false; then :
  $as_echo_n "(cached) " >&6
else
  rm -f conftest*
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for build system executable suffix" >&5
printf %s "checking for build system executable suffix... " >&6; }
if test ${bfd_cv_build_exeext+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) rm -f conftest*
     echo 'int main () { return 0; }' > conftest.c
     bfd_cv_build_exeext=
     ${CC_FOR_BUILD} -o conftest conftest.c 1>&5 2>&5
     for file in conftest.*; do
       case $file in
       *.c | *.o | *.obj | *.ilk | *.pdb) ;;
       *) bfd_cv_build_exeext=`echo $file | sed -e s/conftest//` ;;
       esac
     done
     rm -f conftest*
     test x"${bfd_cv_build_exeext}" = x && bfd_cv_build_exeext=no
     test x"${bfd_cv_build_exeext}" = x && bfd_cv_build_exeext=no ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $bfd_cv_build_exeext" >&5
$as_echo "$bfd_cv_build_exeext" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $bfd_cv_build_exeext" >&5
printf "%s\n" "$bfd_cv_build_exeext" >&6; }
  EXEEXT_FOR_BUILD=""
  test x"${bfd_cv_build_exeext}" != xno && EXEEXT_FOR_BUILD=${bfd_cv_build_exeext}
fi

    #
    # Find a native zip implementation
    #

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tclsh" >&5
$as_echo_n "checking for tclsh... " >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tclsh" >&5
printf %s "checking for tclsh... " >&6; }

    if ${ac_cv_path_tclsh+:} false; then :
  $as_echo_n "(cached) " >&6
else

    if test ${ac_cv_path_tclsh+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
	search_path=`echo ${PATH} | sed -e 's/:/ /g'`
	for dir in $search_path ; do
	    for j in `ls -r $dir/tclsh[8-9]*.exe 2> /dev/null` \
		    `ls -r $dir/tclsh* 2> /dev/null` ; do
		if test x"$ac_cv_path_tclsh" = x ; then
		    if test -f "$j" ; then
			ac_cv_path_tclsh=$j
			break
		    fi
		fi
	    done
	done

     ;;
esac
fi


    if test -f "$ac_cv_path_tclsh" ; then
	TCLSH_PROG="$ac_cv_path_tclsh"
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $TCLSH_PROG" >&5
$as_echo "$TCLSH_PROG" >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TCLSH_PROG" >&5
printf "%s\n" "$TCLSH_PROG" >&6; }
    else
	# It is not an error if an installed version of Tcl can't be located.
	TCLSH_PROG=""
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: No tclsh found on PATH" >&5
$as_echo "No tclsh found on PATH" >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: No tclsh found on PATH" >&5
printf "%s\n" "No tclsh found on PATH" >&6; }
    fi



    ZIP_PROG=""
    ZIP_PROG_OPTIONS=""
    ZIP_PROG_VFSSEARCH=""
    ZIP_INSTALL_OBJS=""

    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for zip" >&5
$as_echo_n "checking for zip... " >&6; }
    if ${ac_cv_path_zip+:} false; then :
  $as_echo_n "(cached) " >&6
else

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for zip" >&5
printf %s "checking for zip... " >&6; }
    if test ${ac_cv_path_zip+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
    search_path=`echo ${PATH} | sed -e 's/:/ /g'`
    for dir in $search_path ; do
        for j in `ls -r $dir/zip 2> /dev/null` \
            `ls -r $dir/zip 2> /dev/null` ; do
        if test x"$ac_cv_path_zip" = x ; then
            if test -f "$j" ; then
            ac_cv_path_zip=$j
            break
            fi
        fi
        done
	for j in `ls -r $dir/zip 2> /dev/null` \
	    `ls -r $dir/zip 2> /dev/null` ; do
	if test x"$ac_cv_path_zip" = x ; then
	    if test -f "$j" ; then
	    ac_cv_path_zip=$j
	    break
	    fi
	fi
	done
    done

     ;;
esac
fi

    if test -f "$ac_cv_path_zip" ; then
        ZIP_PROG="$ac_cv_path_zip"
        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ZIP_PROG" >&5
$as_echo "$ZIP_PROG" >&6; }
        ZIP_PROG_OPTIONS="-rq"
        ZIP_PROG_VFSSEARCH="*"
        { $as_echo "$as_me:${as_lineno-$LINENO}: result: Found INFO Zip in environment" >&5
$as_echo "Found INFO Zip in environment" >&6; }
        # Use standard arguments for zip
	ZIP_PROG="$ac_cv_path_zip"
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ZIP_PROG" >&5
printf "%s\n" "$ZIP_PROG" >&6; }
	ZIP_PROG_OPTIONS="-rq"
	ZIP_PROG_VFSSEARCH="*"
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Found INFO Zip in environment" >&5
printf "%s\n" "Found INFO Zip in environment" >&6; }
	# Use standard arguments for zip
    else
        # It is not an error if an installed version of Zip can't be located.
        # We can use the locally distributed minizip instead
        ZIP_PROG="./minizip${EXEEXT_FOR_BUILD}"
        ZIP_PROG_OPTIONS="-o -r"
        ZIP_PROG_VFSSEARCH="*"
        ZIP_INSTALL_OBJS="minizip${EXEEXT_FOR_BUILD}"
        { $as_echo "$as_me:${as_lineno-$LINENO}: result: No zip found on PATH building minizip" >&5
$as_echo "No zip found on PATH building minizip" >&6; }
	# It is not an error if an installed version of Zip can't be located.
	# We can use the locally distributed minizip instead
	ZIP_PROG="./minizip${EXEEXT_FOR_BUILD}"
	ZIP_PROG_OPTIONS="-o -r"
	ZIP_PROG_VFSSEARCH="*"
	ZIP_INSTALL_OBJS="minizip${EXEEXT_FOR_BUILD}"
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: No zip found on PATH building minizip" >&5
printf "%s\n" "No zip found on PATH building minizip" >&6; }
    fi





	ZIPFS_BUILD=1
	TCL_ZIP_FILE=libtcl_${TCL_MAJOR_VERSION}_${TCL_MINOR_VERSION}_${TCL_PATCH_LEVEL}.zip
	TCL_ZIP_FILE=libtcl${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_PATCH_LEVEL}.zip
else
	ZIPFS_BUILD=0
	TCL_ZIP_FILE=
fi
# Do checking message here to not mess up interleaved configure output
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for building with zipfs" >&5
$as_echo_n "checking for building with zipfs... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for building with zipfs" >&5
printf %s "checking for building with zipfs... " >&6; }
if test "${ZIPFS_BUILD}" = 1; then
    if test "${SHARED_BUILD}" = 0; then
       ZIPFS_BUILD=2;

$as_echo "#define ZIPFS_BUILD 2" >>confdefs.h
printf "%s\n" "#define ZIPFS_BUILD 2" >>confdefs.h

       INSTALL_LIBRARIES=install-libraries-zipfs-static
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
     else

$as_echo "#define ZIPFS_BUILD 1" >>confdefs.h
printf "%s\n" "#define ZIPFS_BUILD 1" >>confdefs.h
\
       INSTALL_LIBRARIES=install-libraries-zipfs-shared
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
    fi
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
    fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
INSTALL_LIBRARIES=install-libraries
INSTALL_MSGS=install-msgs
fi






#--------------------------------------------------------------------
# Perform additinal compiler tests.
#--------------------------------------------------------------------

# See if declarations like FINDEX_INFO_LEVELS are
# missing from winbase.h. This is known to be
# a problem with VC++ 5.2.

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for FINDEX_INFO_LEVELS in winbase.h" >&5
$as_echo_n "checking for FINDEX_INFO_LEVELS in winbase.h... " >&6; }
if ${tcl_cv_findex_enums+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for FINDEX_INFO_LEVELS in winbase.h" >&5
printf %s "checking for FINDEX_INFO_LEVELS in winbase.h... " >&6; }
if test ${tcl_cv_findex_enums+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN

int
main ()
main (void)
{

  FINDEX_INFO_LEVELS i;
  FINDEX_SEARCH_OPS j;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_findex_enums=yes
else
  tcl_cv_findex_enums=no
else case e in #(
  e) tcl_cv_findex_enums=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
 ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_findex_enums" >&5
$as_echo "$tcl_cv_findex_enums" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_findex_enums" >&5
printf "%s\n" "$tcl_cv_findex_enums" >&6; }
if test "$tcl_cv_findex_enums" = "no"; then

$as_echo "#define HAVE_NO_FINDEX_ENUMS 1" >>confdefs.h
printf "%s\n" "#define HAVE_NO_FINDEX_ENUMS 1" >>confdefs.h

fi

# See if the compiler supports intrinsics.

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for intrinsics support in compiler" >&5
$as_echo_n "checking for intrinsics support in compiler... " >&6; }
if ${tcl_cv_intrinsics+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for intrinsics support in compiler" >&5
printf %s "checking for intrinsics support in compiler... " >&6; }
if test ${tcl_cv_intrinsics+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#include <intrin.h>

int
main ()
main (void)
{

  __cpuidex(0,0,0);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_intrinsics=yes
else
  tcl_cv_intrinsics=no
else case e in #(
  e) tcl_cv_intrinsics=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext \
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext

 ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_intrinsics" >&5
$as_echo "$tcl_cv_intrinsics" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_intrinsics" >&5
printf "%s\n" "$tcl_cv_intrinsics" >&6; }
if test "$tcl_cv_intrinsics" = "yes"; then

$as_echo "#define HAVE_INTRIN_H 1" >>confdefs.h
printf "%s\n" "#define HAVE_INTRIN_H 1" >>confdefs.h

fi

# See if the <wspiapi.h> header file is present

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for wspiapi.h" >&5
$as_echo_n "checking for wspiapi.h... " >&6; }
if ${tcl_cv_wspiapi_h+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wspiapi.h" >&5
printf %s "checking for wspiapi.h... " >&6; }
if test ${tcl_cv_wspiapi_h+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

#include <wspiapi.h>

int
main ()
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_wspiapi_h=yes
else
  tcl_cv_wspiapi_h=no
else case e in #(
  e) tcl_cv_wspiapi_h=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
 ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_wspiapi_h" >&5
$as_echo "$tcl_cv_wspiapi_h" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_wspiapi_h" >&5
printf "%s\n" "$tcl_cv_wspiapi_h" >&6; }
if test "$tcl_cv_wspiapi_h" = "yes"; then

$as_echo "#define HAVE_WSPIAPI_H 1" >>confdefs.h
printf "%s\n" "#define HAVE_WSPIAPI_H 1" >>confdefs.h

fi

# See if declarations like FINDEX_INFO_LEVELS are
# missing from winbase.h. This is known to be
# a problem with VC++ 5.2.

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for FINDEX_INFO_LEVELS in winbase.h" >&5
$as_echo_n "checking for FINDEX_INFO_LEVELS in winbase.h... " >&6; }
if ${tcl_cv_findex_enums+:} false; then :
  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for FINDEX_INFO_LEVELS in winbase.h" >&5
printf %s "checking for FINDEX_INFO_LEVELS in winbase.h... " >&6; }
if test ${tcl_cv_findex_enums+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN

int
main ()
main (void)
{

  FINDEX_INFO_LEVELS i;
  FINDEX_SEARCH_OPS j;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_findex_enums=yes
else
  tcl_cv_findex_enums=no
else case e in #(
  e) tcl_cv_findex_enums=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
 ;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_findex_enums" >&5
$as_echo "$tcl_cv_findex_enums" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_findex_enums" >&5
printf "%s\n" "$tcl_cv_findex_enums" >&6; }
if test "$tcl_cv_findex_enums" = "no"; then

$as_echo "#define HAVE_NO_FINDEX_ENUMS 1" >>confdefs.h
printf "%s\n" "#define HAVE_NO_FINDEX_ENUMS 1" >>confdefs.h

fi

#--------------------------------------------------------------------
# Set the default compiler switches based on the --enable-symbols
# option.  This macro depends on C flags, and should be called
# after SC_CONFIG_CFLAGS macro is called.
#--------------------------------------------------------------------


    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for build with symbols" >&5
$as_echo_n "checking for build with symbols... " >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for build with symbols" >&5
printf %s "checking for build with symbols... " >&6; }
    # Check whether --enable-symbols was given.
if test "${enable_symbols+set}" = set; then :
if test ${enable_symbols+y}
then :
  enableval=$enable_symbols; tcl_ok=$enableval
else
  tcl_ok=no
else case e in #(
  e) tcl_ok=no ;;
esac
fi

# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.
    if test "$tcl_ok" = "no"; then
	CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'
	LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'

$as_echo "#define NDEBUG 1" >>confdefs.h
printf "%s\n" "#define NDEBUG 1" >>confdefs.h

	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }

	$as_echo "#define TCL_CFG_OPTIMIZED 1" >>confdefs.h
	printf "%s\n" "#define TCL_CFG_OPTIMIZED 1" >>confdefs.h

    else
	CFLAGS_DEFAULT='$(CFLAGS_DEBUG)'
	LDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)'
	if test "$tcl_ok" = "yes"; then
	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (standard debugging)" >&5
$as_echo "yes (standard debugging)" >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes (standard debugging)" >&5
printf "%s\n" "yes (standard debugging)" >&6; }
	fi
    fi



    if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then

$as_echo "#define TCL_MEM_DEBUG 1" >>confdefs.h
printf "%s\n" "#define TCL_MEM_DEBUG 1" >>confdefs.h

    fi

    if test "$tcl_ok" = "compile" -o "$tcl_ok" = "all"; then

$as_echo "#define TCL_COMPILE_DEBUG 1" >>confdefs.h
printf "%s\n" "#define TCL_COMPILE_DEBUG 1" >>confdefs.h


$as_echo "#define TCL_COMPILE_STATS 1" >>confdefs.h
printf "%s\n" "#define TCL_COMPILE_STATS 1" >>confdefs.h

    fi

    if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then
	if test "$tcl_ok" = "all"; then
	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled symbols mem compile debugging" >&5
$as_echo "enabled symbols mem compile debugging" >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: enabled symbols mem compile debugging" >&5
printf "%s\n" "enabled symbols mem compile debugging" >&6; }
	else
	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging" >&5
$as_echo "enabled $tcl_ok debugging" >&6; }
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging" >&5
printf "%s\n" "enabled $tcl_ok debugging" >&6; }
	fi
    fi


#--------------------------------------------------------------------
# Embed the manifest if we can determine how
#--------------------------------------------------------------------

ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
printf %s "checking how to run the C preprocessor... " >&6; }
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
  CPP=
fi
if test -z "$CPP"; then
  if test ${ac_cv_prog_CPP+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)     # Double quotes because $CC needs to be expanded
    for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp
    do
      ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
  # Use a header file that comes with gcc, so configuring glibc
  # with a fresh cross-compiler works.
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp. "Syntax error" is here to catch this case.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <limits.h>
		     Syntax error
_ACEOF
if ac_fn_c_try_cpp "$LINENO"
then :

else case e in #(
  e) # Broken: fails on valid input.
continue ;;
esac
fi
rm -f conftest.err conftest.i conftest.$ac_ext

  # OK, works on sane cases.  Now check whether nonexistent headers
  # can be detected and how.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <ac_nonexistent.h>
_ACEOF
if ac_fn_c_try_cpp "$LINENO"
then :
  # Broken: success on invalid input.
continue
else case e in #(
  e) # Passes both tests.
ac_preproc_ok=:
break ;;
esac
fi
rm -f conftest.err conftest.i conftest.$ac_ext

done
# Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok
then :
  break
fi

    done
    ac_cv_prog_CPP=$CPP
   ;;
esac
fi
  CPP=$ac_cv_prog_CPP
else
  ac_cv_prog_CPP=$CPP
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
printf "%s\n" "$CPP" >&6; }
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
  # Use a header file that comes with gcc, so configuring glibc
  # with a fresh cross-compiler works.
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp. "Syntax error" is here to catch this case.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <limits.h>
		     Syntax error
_ACEOF
if ac_fn_c_try_cpp "$LINENO"
then :

else case e in #(
  e) # Broken: fails on valid input.
continue ;;
esac
fi
rm -f conftest.err conftest.i conftest.$ac_ext

  # OK, works on sane cases.  Now check whether nonexistent headers
  # can be detected and how.
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <ac_nonexistent.h>
_ACEOF
if ac_fn_c_try_cpp "$LINENO"
then :
  # Broken: success on invalid input.
continue
else case e in #(
  e) # Passes both tests.
ac_preproc_ok=:
break ;;
esac
fi
rm -f conftest.err conftest.i conftest.$ac_ext

done
# Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok
then :

else case e in #(
  e) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
See 'config.log' for more details" "$LINENO" 5; } ;;
esac
fi

ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu


{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep -e" >&5
printf %s "checking for egrep -e... " >&6; }
if test ${ac_cv_path_EGREP_TRADITIONAL+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e) if test -z "$EGREP_TRADITIONAL"; then
  ac_path_EGREP_TRADITIONAL_found=false
  # Loop through the user's path and test for each of PROGNAME-LIST
  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_prog in grep ggrep
   do
    for ac_exec_ext in '' $ac_executable_extensions; do
      ac_path_EGREP_TRADITIONAL="$as_dir$ac_prog$ac_exec_ext"
      as_fn_executable_p "$ac_path_EGREP_TRADITIONAL" || continue
# Check for GNU ac_path_EGREP_TRADITIONAL and select it if it is found.
  # Check for GNU $ac_path_EGREP_TRADITIONAL
case `"$ac_path_EGREP_TRADITIONAL" --version 2>&1` in #(
*GNU*)
  ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL" ac_path_EGREP_TRADITIONAL_found=:;;
#(
*)
  ac_count=0
  printf %s 0123456789 >"conftest.in"
  while :
  do
    cat "conftest.in" "conftest.in" >"conftest.tmp"
    mv "conftest.tmp" "conftest.in"
    cp "conftest.in" "conftest.nl"
    printf "%s\n" 'EGREP_TRADITIONAL' >> "conftest.nl"
    "$ac_path_EGREP_TRADITIONAL" -E 'EGR(EP|AC)_TRADITIONAL$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
    as_fn_arith $ac_count + 1 && ac_count=$as_val
    if test $ac_count -gt ${ac_path_EGREP_TRADITIONAL_max-0}; then
      # Best one so far, save it but keep looking for a better one
      ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL"
      ac_path_EGREP_TRADITIONAL_max=$ac_count
    fi
    # 10*(2^10) chars as input seems more than enough
    test $ac_count -gt 10 && break
  done
  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac

      $ac_path_EGREP_TRADITIONAL_found && break 3
    done
  done
  done
IFS=$as_save_IFS
  if test -z "$ac_cv_path_EGREP_TRADITIONAL"; then
    :
  fi
else
  ac_cv_path_EGREP_TRADITIONAL=$EGREP_TRADITIONAL
fi

    if test "$ac_cv_path_EGREP_TRADITIONAL"
then :
  ac_cv_path_EGREP_TRADITIONAL="$ac_cv_path_EGREP_TRADITIONAL -E"
else case e in #(
  e) if test -z "$EGREP_TRADITIONAL"; then
  ac_path_EGREP_TRADITIONAL_found=false
  # Loop through the user's path and test for each of PROGNAME-LIST
  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
  IFS=$as_save_IFS
  case $as_dir in #(((
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    for ac_prog in egrep
   do
    for ac_exec_ext in '' $ac_executable_extensions; do
      ac_path_EGREP_TRADITIONAL="$as_dir$ac_prog$ac_exec_ext"
      as_fn_executable_p "$ac_path_EGREP_TRADITIONAL" || continue
# Check for GNU ac_path_EGREP_TRADITIONAL and select it if it is found.
  # Check for GNU $ac_path_EGREP_TRADITIONAL
case `"$ac_path_EGREP_TRADITIONAL" --version 2>&1` in #(
*GNU*)
  ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL" ac_path_EGREP_TRADITIONAL_found=:;;
#(
*)
  ac_count=0
  printf %s 0123456789 >"conftest.in"
  while :
  do
    cat "conftest.in" "conftest.in" >"conftest.tmp"
    mv "conftest.tmp" "conftest.in"
    cp "conftest.in" "conftest.nl"
    printf "%s\n" 'EGREP_TRADITIONAL' >> "conftest.nl"
    "$ac_path_EGREP_TRADITIONAL" 'EGR(EP|AC)_TRADITIONAL$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
    as_fn_arith $ac_count + 1 && ac_count=$as_val
    if test $ac_count -gt ${ac_path_EGREP_TRADITIONAL_max-0}; then
      # Best one so far, save it but keep looking for a better one
      ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL"
      ac_path_EGREP_TRADITIONAL_max=$ac_count
    fi
    # 10*(2^10) chars as input seems more than enough
    test $ac_count -gt 10 && break
  done
  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac

      $ac_path_EGREP_TRADITIONAL_found && break 3
    done
  done
  done
IFS=$as_save_IFS
  if test -z "$ac_cv_path_EGREP_TRADITIONAL"; then
    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
  fi
else
  ac_cv_path_EGREP_TRADITIONAL=$EGREP_TRADITIONAL
fi
 ;;
esac
fi ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP_TRADITIONAL" >&5
printf "%s\n" "$ac_cv_path_EGREP_TRADITIONAL" >&6; }
 EGREP_TRADITIONAL=$ac_cv_path_EGREP_TRADITIONAL


    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to embed manifest" >&5
$as_echo_n "checking whether to embed manifest... " >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to embed manifest" >&5
printf %s "checking whether to embed manifest... " >&6; }
    # Check whether --enable-embedded-manifest was given.
if test "${enable_embedded_manifest+set}" = set; then :
if test ${enable_embedded_manifest+y}
then :
  enableval=$enable_embedded_manifest; embed_ok=$enableval
else
  embed_ok=yes
else case e in #(
  e) embed_ok=yes ;;
esac
fi


    VC_MANIFEST_EMBED_DLL=
    VC_MANIFEST_EMBED_EXE=
    result=no
    if test "$embed_ok" = "yes" -a "${SHARED_BUILD}" = "1" \
       -a "$GCC" != "yes" ; then
	# Add the magic to embed the manifest into the dll/exe
	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

#if defined(_MSC_VER) && _MSC_VER >= 1400
print("manifest needed")
#endif

_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  $EGREP "manifest needed" >/dev/null 2>&1; then :
  $EGREP_TRADITIONAL "manifest needed" >/dev/null 2>&1
then :

	# Could do a CHECK_PROG for mt, but should always be with MSVC8+
	# Could add 'if test -f' check, but manifest should be created
	# in this compiler case
	# Add in a manifest argument that may be specified
	# XXX Needs improvement so that the test for existence accounts
	# XXX for a provided (known) manifest
	VC_MANIFEST_EMBED_DLL="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest  -outputresource:\$@\;2 ; fi"
	VC_MANIFEST_EMBED_EXE="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest  -outputresource:\$@\;1 ; fi"
	result=yes
	if test "x" != x ; then
	    result="yes ()"
	fi

fi
rm -f conftest*
rm -rf conftest*

    fi
    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $result" >&5
$as_echo "$result" >&6; }
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $result" >&5
printf "%s\n" "$result" >&6; }




#------------------------------------------------------------------------
# tclConfig.sh refers to this by a different name
#------------------------------------------------------------------------

TCL_SHARED_BUILD=${SHARED_BUILD}

#--------------------------------------------------------------------
# Perform final evaluations of variables with possible substitutions.
#--------------------------------------------------------------------

eval "TCL_SRC_DIR=\"`cd $srcdir/..; $CYGPATH $(pwd)`\""

eval "TCL_DLL_FILE=tcl${VER}${DLLSUFFIX}"

eval "TCL_STUB_LIB_FILE=\"${LIBPREFIX}tclstub${VER}${LIBSUFFIX}\""
eval "TCL_STUB_LIB_FLAG=\"-ltclstub${VER}${LIBFLAGSUFFIX}\""
eval "TCL_STUB_LIB_FILE=\"${LIBPREFIX}tclstub${LIBSUFFIX}\""
eval "TCL_STUB_LIB_FLAG=\"-ltclstub${LIBFLAGSUFFIX}\""
eval "TCL_BUILD_STUB_LIB_SPEC=\"-L`$CYGPATH $(pwd)` ${TCL_STUB_LIB_FLAG}\""
eval "TCL_STUB_LIB_SPEC=\"-L${libdir} ${TCL_STUB_LIB_FLAG}\""
eval "TCL_BUILD_STUB_LIB_PATH=\"`$CYGPATH $(pwd)`/${TCL_STUB_LIB_FILE}\""
eval "TCL_STUB_LIB_PATH=\"${libdir}/${TCL_STUB_LIB_FILE}\""

if test ${SHARED_BUILD} = 0 ; then
if test ${SHARED_BUILD} = 0 -o "$GCC" != "yes" ; then
 eval "TCL_LIB_FLAG=\"${LIBPREFIX}tcl${VER}${LIBSUFFIX}\""
 eval "TCL_LIB_FILE=\"${LIBPREFIX}tcl${VER}${LIBSUFFIX}\""
else
 eval "TCL_LIB_FLAG=\"-ltcl${VER}${FLAGSUFFIX}\""
 eval "TCL_LIB_FILE=\"${LIBPREFIX}tcl${VER}${DLLSUFFIX}.a\""
fi
eval "TCL_BUILD_LIB_SPEC=\"-L`$CYGPATH $(pwd)` -ltcl${VER}${FLAGSUFFIX}\""
eval "TCL_LIB_SPEC=\"-L${libdir} -ltcl${VER}${FLAGSUFFIX}\""
eval "TCL_BUILD_LIB_SPEC=\"-L`$CYGPATH $(pwd)` ${TCL_LIB_FLAG}\""
eval "TCL_LIB_SPEC=\"-L${libdir} ${TCL_LIB_FLAG}\""

# Install time header dir can be set via --includedir
eval "TCL_INCLUDE_SPEC=\"-I${includedir}\""

TCL_SHARED_LIB_SUFFIX="\${NODOT_VERSION}${DLLSUFFIX}"
TCL_UNSHARED_LIB_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"
TCL_EXPORT_FILE_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"

CFG_TCL_SHARED_LIB_SUFFIX=${TCL_SHARED_LIB_SUFFIX}
CFG_TCL_UNSHARED_LIB_SUFFIX=${TCL_UNSHARED_LIB_SUFFIX}
CFG_TCL_EXPORT_FILE_SUFFIX=${TCL_EXPORT_FILE_SUFFIX}

#--------------------------------------------------------------------
# Adjust the defines for how the resources are built depending
# on symbols and static vs. shared.
#--------------------------------------------------------------------

if test ${SHARED_BUILD} = 0 ; then
    RC_DEFINES="${RC_DEFINE} STATIC_BUILD"
else
    RC_DEFINES=""
fi

#--------------------------------------------------------------------
#	The statements below define the symbol TCL_PACKAGE_PATH, which
#	gives a list of directories that may contain packages.  The list
#	consists of one directory for machine-dependent binaries and
#	another for platform-independent scripts.
#--------------------------------------------------------------------

if test "$prefix/lib" != "$libdir"; then
    TCL_PACKAGE_PATH="{${libdir}} {${prefix}/lib}"
    TCL_PACKAGE_PATH="${libdir};${prefix}\\lib"
else
    TCL_PACKAGE_PATH="{${prefix}/lib}"
    TCL_PACKAGE_PATH="${prefix}\\lib"
fi

# The tclsh.exe.manifest requires these
# TCL_WIN_VERSION is the 4 dotted pair Windows version format which needs
# the release level, and must account for interim release versioning
case "$TCL_PATCH_LEVEL" in
     *a*) TCL_RELEASE_LEVEL=0 ;;
     *b*) TCL_RELEASE_LEVEL=1 ;;
     *)   TCL_RELEASE_LEVEL=2 ;;
esac
TCL_WIN_VERSION="$TCL_VERSION.$TCL_RELEASE_LEVEL.`echo $TCL_PATCH_LEVEL | tr -d ab.`"

# X86|AMD64|IA64 for manifest
# X86|AMD64|ARM64|IA64 for manifest















# empty on win








5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427

5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440


5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457


5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470

5471
5472
5473
5474
5475
5476
5477

5478
5479
5480
5481
5482
5483
5484
5485
5486
5487

5488
5489
5490
5491
5492
5493
5494
5495


5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510


5511
5512
5513
5514
5515
5516
5517
5982
5983
5984
5985
5986
5987
5988








5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008

6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020


6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037


6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051

6052
6053
6054
6055
6056
6057
6058

6059
6060
6061
6062
6063
6064
6065
6066
6067
6068

6069
6070
6071
6072
6073
6074
6075


6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090


6091
6092
6093
6094
6095
6096
6097
6098
6099







-
-
-
-
-
-
-
-




















-
+











-
-
+
+















-
-
+
+












-
+






-
+









-
+






-
-
+
+













-
-
+
+















# empty on win, but needs sub'ing










# win only















ac_config_files="$ac_config_files Makefile tclConfig.sh tcl.hpj tclsh.exe.manifest"
ac_config_files="$ac_config_files Makefile tclConfig.sh tclsh.exe.manifest"

cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
# scripts and configure runs, see configure's option --config-cache.
# It is not useful on other systems.  If it contains results you don't
# want to keep, you may remove or edit it.
#
# config.status only pays attention to the cache file if you give it
# the --recheck option to rerun configure.
#
# `ac_cv_env_foo' variables (set or unset) will be overridden when
# loading this file, other *unset* `ac_cv_foo' will be assigned the
# 'ac_cv_env_foo' variables (set or unset) will be overridden when
# loading this file, other *unset* 'ac_cv_foo' will be assigned the
# following values.

_ACEOF

# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
# So, we kill variables containing newlines.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
(
  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
    eval ac_val=\$$ac_var
    case $ac_val in #(
    *${as_nl}*)
      case $ac_var in #(
      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
      *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
      esac
      case $ac_var in #(
      _ | IFS | as_nl) ;; #(
      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
      *) { eval $ac_var=; unset $ac_var;} ;;
      esac ;;
    esac
  done

  (set) 2>&1 |
    case $as_nl`(ac_space=' '; set) 2>&1` in #(
    *${as_nl}ac_space=\ *)
      # `set' does not quote correctly, so add quotes: double-quote
      # 'set' does not quote correctly, so add quotes: double-quote
      # substitution turns \\\\ into \\, and sed turns \\ into \.
      sed -n \
	"s/'/'\\\\''/g;
	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
      ;; #(
    *)
      # `set' quotes correctly as required by POSIX, so do not add quotes.
      # 'set' quotes correctly as required by POSIX, so do not add quotes.
      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
      ;;
    esac |
    sort
) |
  sed '
     /^ac_cv_env_/b end
     t clear
     :clear
     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
     s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
     t end
     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
     :end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
  if test -w "$cache_file"; then
    if test "x$cache_file" != "x/dev/null"; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
$as_echo "$as_me: updating cache $cache_file" >&6;}
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
      if test ! -f "$cache_file" || test -h "$cache_file"; then
	cat confcache >"$cache_file"
      else
        case $cache_file in #(
        */* | ?:*)
	  mv -f confcache "$cache_file"$$ &&
	  mv -f "$cache_file"$$ "$cache_file" ;; #(
        *)
	  mv -f confcache "$cache_file" ;;
	esac
      fi
    fi
  else
    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
  fi
fi
rm -f confcache

test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
5534
5535
5536
5537
5538
5539
5540
5541

5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563

5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580


5581
5582
5583
5584
5585
5586
5587
6116
6117
6118
6119
6120
6121
6122

6123


6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142

6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158


6159
6160
6161
6162
6163
6164
6165
6166
6167







-
+
-
-



















-
+















-
-
+
+







:clear
s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\)/-D\1=\2/g
t quote
s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)/-D\1=\2/g
t quote
b any
:quote
s/[	 `~#$^&*(){}\\|;'\''"<>?]/\\&/g
s/[][	 `~#$^&*(){}\\|;'\''"<>?]/\\&/g
s/\[/\\&/g
s/\]/\\&/g
s/\$/$$/g
H
:any
${
	g
	s/^\n//
	s/\n/ /g
	p
}
'
DEFS=`sed -n "$ac_script" confdefs.h`


ac_libobjs=
ac_ltlibobjs=
U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
  # 1. Remove the extension, and $U if already installed.
  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
  ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
  #    will be set to the directory where LIBOBJS objects are built.
  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
done
LIBOBJS=$ac_libobjs

LTLIBOBJS=$ac_ltlibobjs



: "${CONFIG_STATUS=./config.status}"
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
# Generated by $as_me.
# Run this file to recreate the current configuration.
# Compiler output produced by configure, useful for debugging
# configure, is in config.log if it exists.
5596
5597
5598
5599
5600
5601
5602
5603


5604
5605
5606
5607
5608
5609
5610
5611


5612
5613
5614
5615

5616
5617
5618
5619








5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632


5633
5634
5635


5636
5637
5638
5639
5640
5641
5642

5643
5644
5645
5646
5647
5648
5649
5650
5651




5652
5653
5654
5655
5656

















5657
5658
5659

5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682

5683
5684





5685
5686
5687
5688
5689
5690

5691
5692
5693
5694
5695
5696

5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732

5733
5734

5735
5736
5737
5738
5739
5740
5741
6176
6177
6178
6179
6180
6181
6182

6183
6184
6185
6186
6187
6188
6189
6190


6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212










6213
6214



6215
6216







6217









6218
6219
6220
6221





6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240

6241
6242
6243
6244
6245
6246
6247
6248
6249







6250
6251
6252
6253
6254
6255
6256
6257
6258


6259
6260
6261
6262
6263
6264
6265
6266
6267
6268

6269
6270
6271
6272
6273
6274

6275
6276
6277
6278




















6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290

6291
6292

6293
6294
6295
6296
6297
6298
6299
6300







-
+
+






-
-
+
+




+




+
+
+
+
+
+
+
+



-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+








-
-
-
-
-
-
-








+
-
-
+
+
+
+
+





-
+





-
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-












-
+

-
+







cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##

# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
then :
  emulate sh
  NULLCMD=:
  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '${1+"$@"}'='"$@"'
  setopt NO_GLOB_SUBST
else
  case `(set -o) 2>/dev/null` in #(
else case e in #(
  e) case `(set -o) 2>/dev/null` in #(
  *posix*) :
    set -o posix ;; #(
  *) :
     ;;
esac ;;
esac
fi



# Reset variables that may have inherited troublesome values from
# the environment.

# IFS needs to be set, to space, tab, and newline, in precisely that order.
# (If _AS_PATH_WALK were called with IFS unset, it would have the
# side effect of setting IFS to empty, thus disabling word splitting.)
# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
# Printing a long string crashes Solaris 7 /usr/bin/printf.
as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
# Prefer a ksh shell builtin over an external printf program on Solaris,
# but without wasting forks for bash or zsh.
if test -z "$BASH_VERSION$ZSH_VERSION" \
    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
  as_echo='print -r --'
  as_echo_n='print -rn --'
IFS=" ""	$as_nl"

elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
  as_echo='printf %s\n'
  as_echo_n='printf %s'
PS1='$ '
PS2='> '
else
  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
    as_echo_n='/usr/ucb/echo -n'
  else
    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
    as_echo_n_body='eval
PS4='+ '
      arg=$1;
      case $arg in #(
      *"$as_nl"*)
	expr "X$arg" : "X\\(.*\\)$as_nl";
	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
      esac;
      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
    '
    export as_echo_n_body

# Ensure predictable behavior from utilities with locale-dependent output.
LC_ALL=C
export LC_ALL
    as_echo_n='sh -c $as_echo_n_body as_echo'
  fi
  export as_echo_body
  as_echo='sh -c $as_echo_body as_echo'
fi
LANGUAGE=C
export LANGUAGE

# We cannot yet rely on "unset" to work, but we need these variables
# to be unset--not just set to an empty or harmless value--now, to
# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct
# also avoids known problems related to "unset" and subshell syntax
# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
do eval test \${$as_var+y} \
  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done

# Ensure that fds 0, 1, and 2 are open.
if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
if (exec 3>&2)            ; then :; else exec 2>/dev/null; fi

# The user is always right.
if test "${PATH_SEPARATOR+set}" != set; then
if ${PATH_SEPARATOR+false} :; then
  PATH_SEPARATOR=:
  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
      PATH_SEPARATOR=';'
  }
fi


# IFS
# We need space, tab and new line, in precisely that order.  Quoting is
# there to prevent editors from complaining about space-tab.
# (If _AS_PATH_WALK were called with IFS unset, it would disable word
# splitting by setting IFS to empty value.)
IFS=" ""	$as_nl"

# Find who we are.  Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
  *[\\/]* ) as_myself=$0 ;;
  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
  IFS=$as_save_IFS
  case $as_dir in #(((
  test -z "$as_dir" && as_dir=.
    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
    '') as_dir=./ ;;
    */) ;;
    *) as_dir=$as_dir/ ;;
  esac
    test -r "$as_dir$0" && as_myself=$as_dir$0 && break
  done
IFS=$as_save_IFS

     ;;
esac
# We did not find ourselves, most probably we were run as `sh COMMAND'
# We did not find ourselves, most probably we were run as 'sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
  as_myself=$0
fi
if test ! -f "$as_myself"; then
  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
  printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
  exit 1
fi

# Unset variables that we do not need and which cause bugs (e.g. in
# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
# suppresses any "Segmentation fault" message there.  '((' could
# trigger a bug in pdksh 5.2.14.
for as_var in BASH_ENV ENV MAIL MAILPATH
do eval test x\${$as_var+set} = xset \
  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done
PS1='$ '
PS2='> '
PS4='+ '

# NLS nuisances.
LC_ALL=C
export LC_ALL
LANGUAGE=C
export LANGUAGE

# CDPATH.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH


# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
  as_status=$1; test $as_status -eq 0 && as_status=1
  if test "$4"; then
    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
  fi
  $as_echo "$as_me: error: $2" >&2
  printf "%s\n" "$as_me: error: $2" >&2
  as_fn_exit $as_status
} # as_fn_error


# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
5758
5759
5760
5761
5762
5763
5764

5765
5766
5767
5768
5769
5770
5771


5772
5773
5774
5775
5776
5777


5778
5779
5780


5781
5782
5783
5784
5785
5786
5787
5788


5789
5790
5791
5792
5793
5794


5795
5796
5797


5798
5799
5800
5801
5802
5803
5804
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330

6331
6332
6333
6334
6335
6336


6337
6338
6339
6340

6341
6342
6343
6344
6345
6346
6347
6348
6349

6350
6351
6352
6353
6354
6355


6356
6357
6358
6359

6360
6361
6362
6363
6364
6365
6366
6367
6368







+






-
+
+




-
-
+
+


-
+
+







-
+
+




-
-
+
+


-
+
+







# ---------------
# Portably unset VAR.
as_fn_unset ()
{
  { eval $1=; unset $1;}
}
as_unset=as_fn_unset

# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
then :
  eval 'as_fn_append ()
  {
    eval $1+=\$2
  }'
else
  as_fn_append ()
else case e in #(
  e) as_fn_append ()
  {
    eval $1=\$$1\$2
  }
  } ;;
esac
fi # as_fn_append

# as_fn_arith ARG...
# ------------------
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
then :
  eval 'as_fn_arith ()
  {
    as_val=$(( $* ))
  }'
else
  as_fn_arith ()
else case e in #(
  e) as_fn_arith ()
  {
    as_val=`expr "$@" || test $? -eq 1`
  }
  } ;;
esac
fi # as_fn_arith


if expr a : '\(a\)' >/dev/null 2>&1 &&
   test "X`expr 00001 : '.*\(...\)'`" = X001; then
  as_expr=expr
else
5817
5818
5819
5820
5821
5822
5823
5824

5825
5826
5827
5828
5829
5830
5831
6381
6382
6383
6384
6385
6386
6387

6388
6389
6390
6391
6392
6393
6394
6395







-
+







  as_dirname=false
fi

as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
	 X"$0" : 'X\(//\)$' \| \
	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X/"$0" |
printf "%s\n" X/"$0" |
    sed '/^.*\/\([^/][^/]*\)\/*$/{
	    s//\1/
	    q
	  }
	  /^X\/\(\/\/\)$/{
	    s//\1/
	    q
5839
5840
5841
5842
5843
5844
5845




5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857






5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872



5873
5874
5875
5876
5877
5878
5879
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443



6444
6445
6446
6447
6448
6449
6450
6451
6452
6453







+
+
+
+












+
+
+
+
+
+












-
-
-
+
+
+







# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits


# Determine whether it's possible to make 'echo' print without a newline.
# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
  case `echo 'xy\c'` in
  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
  xy)  ECHO_C='\c';;
  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
       ECHO_T='	';;
  esac;;
*)
  ECHO_N='-n';;
esac

# For backward compatibility with old third-party macros, we provide
# the shell variables $as_echo and $as_echo_n.  New code should use
# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
as_echo='printf %s\n'
as_echo_n='printf %s'

rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
  rm -f conf$$.dir/conf$$.file
else
  rm -f conf$$.dir
  mkdir conf$$.dir 2>/dev/null
fi
if (echo >conf$$.file) 2>/dev/null; then
  if ln -s conf$$.file conf$$ 2>/dev/null; then
    as_ln_s='ln -s'
    # ... but there are two gotchas:
    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
    # In both cases, we have to default to `cp -pR'.
    # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail.
    # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable.
    # In both cases, we have to default to 'cp -pR'.
    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
      as_ln_s='cp -pR'
  elif ln conf$$.file conf$$ 2>/dev/null; then
    as_ln_s=ln
  else
    as_ln_s='cp -pR'
  fi
5893
5894
5895
5896
5897
5898
5899
5900

5901
5902
5903
5904
5905
5906
5907
5908
5909

5910
5911
5912
5913
5914
5915
5916
6467
6468
6469
6470
6471
6472
6473

6474
6475
6476
6477
6478
6479
6480
6481
6482

6483
6484
6485
6486
6487
6488
6489
6490







-
+








-
+







  case $as_dir in #(
  -*) as_dir=./$as_dir;;
  esac
  test -d "$as_dir" || eval $as_mkdir_p || {
    as_dirs=
    while :; do
      case $as_dir in #(
      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
      *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
      *) as_qdir=$as_dir;;
      esac
      as_dirs="'$as_qdir' $as_dirs"
      as_dir=`$as_dirname -- "$as_dir" ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$as_dir" : 'X\(//\)[^/]' \| \
	 X"$as_dir" : 'X\(//\)$' \| \
	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$as_dir" |
printf "%s\n" X"$as_dir" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
5946
5947
5948
5949
5950
5951
5952
5953


5954
5955
5956


5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972


5973
5974
5975
5976
5977
5978
5979
6520
6521
6522
6523
6524
6525
6526

6527
6528
6529
6530

6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546


6547
6548
6549
6550
6551
6552
6553
6554
6555







-
+
+


-
+
+














-
-
+
+







{
  test -f "$1" && test -x "$1"
} # as_fn_executable_p
as_test_x='test -x'
as_executable_p=as_fn_executable_p

# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated

# Sed expression to map a string onto a valid variable name.
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
as_tr_sh="eval sed '$as_sed_sh'" # deprecated


exec 6>&1
## ----------------------------------- ##
## Main body of $CONFIG_STATUS script. ##
## ----------------------------------- ##
_ASEOF
test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# Save the log message, to keep $0 and so on meaningful, and to
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by $as_me, which was
generated by GNU Autoconf 2.69.  Invocation command line was
This file was extended by tcl $as_me 9.0, which was
generated by GNU Autoconf 2.72.  Invocation command line was

  CONFIG_FILES    = $CONFIG_FILES
  CONFIG_HEADERS  = $CONFIG_HEADERS
  CONFIG_LINKS    = $CONFIG_LINKS
  CONFIG_COMMANDS = $CONFIG_COMMANDS
  $ $0 $@

5992
5993
5994
5995
5996
5997
5998
5999

6000
6001
6002
6003
6004
6005
6006
6568
6569
6570
6571
6572
6573
6574

6575
6576
6577
6578
6579
6580
6581
6582







-
+







# Files that config.status was made for.
config_files="$ac_config_files"

_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
ac_cs_usage="\
\`$as_me' instantiates files and other configuration actions
'$as_me' instantiates files and other configuration actions
from templates according to the current configuration.  Unless the files
and actions are specified as TAGs, all are instantiated by default.

Usage: $0 [OPTION]... [TAG]...

  -h, --help       print this help, then exit
  -V, --version    print version number and configuration settings, then exit
6014
6015
6016
6017
6018
6019
6020


6021
6022

6023
6024
6025


6026
6027
6028

6029
6030
6031
6032
6033
6034
6035
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599

6600
6601


6602
6603
6604
6605

6606
6607
6608
6609
6610
6611
6612
6613







+
+

-
+

-
-
+
+


-
+








Configuration files:
$config_files

Report bugs to the package provider."

_ACEOF
ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
config.status
configured by $0, generated by GNU Autoconf 2.69,
tcl config.status 9.0
configured by $0, generated by GNU Autoconf 2.72,
  with options \\"\$ac_cs_config\\"

Copyright (C) 2012 Free Software Foundation, Inc.
Copyright (C) 2023 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."

ac_pwd='$ac_pwd'
srcdir='$srcdir'
test -n "\$AWK" || AWK=awk
_ACEOF
6058
6059
6060
6061
6062
6063
6064
6065

6066
6067

6068
6069
6070
6071
6072
6073

6074
6075
6076
6077
6078
6079

6080
6081
6082
6083
6084
6085
6086


6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107

6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121

6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139

6140
6141
6142
6143
6144
6145
6146
6147
6148
6149

6150
6151
6152
6153
6154
6155
6156
6157

6158
6159
6160
6161
6162
6163
6164
6636
6637
6638
6639
6640
6641
6642

6643
6644

6645
6646
6647
6648
6649
6650

6651
6652
6653
6654
6655
6656

6657
6658
6659
6660
6661
6662


6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684

6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698

6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713

6714
6715

6716
6717
6718
6719
6720
6721
6722
6723
6724
6725

6726
6727
6728
6729
6730
6731
6732
6733

6734
6735
6736
6737
6738
6739
6740
6741







-
+

-
+





-
+





-
+





-
-
+
+




















-
+













-
+














-


-
+









-
+







-
+







  esac

  case $ac_option in
  # Handling of the options.
  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
    ac_cs_recheck=: ;;
  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
    $as_echo "$ac_cs_version"; exit ;;
    printf "%s\n" "$ac_cs_version"; exit ;;
  --config | --confi | --conf | --con | --co | --c )
    $as_echo "$ac_cs_config"; exit ;;
    printf "%s\n" "$ac_cs_config"; exit ;;
  --debug | --debu | --deb | --de | --d | -d )
    debug=: ;;
  --file | --fil | --fi | --f )
    $ac_shift
    case $ac_optarg in
    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
    *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
    '') as_fn_error $? "missing file argument" ;;
    esac
    as_fn_append CONFIG_FILES " '$ac_optarg'"
    ac_need_defaults=false;;
  --he | --h |  --help | --hel | -h )
    $as_echo "$ac_cs_usage"; exit ;;
    printf "%s\n" "$ac_cs_usage"; exit ;;
  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
  | -silent | --silent | --silen | --sile | --sil | --si | --s)
    ac_cs_silent=: ;;

  # This is an error.
  -*) as_fn_error $? "unrecognized option: \`$1'
Try \`$0 --help' for more information." ;;
  -*) as_fn_error $? "unrecognized option: '$1'
Try '$0 --help' for more information." ;;

  *) as_fn_append ac_config_targets " $1"
     ac_need_defaults=false ;;

  esac
  shift
done

ac_configure_extra_args=

if $ac_cs_silent; then
  exec 6>/dev/null
  ac_configure_extra_args="$ac_configure_extra_args --silent"
fi

_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
  shift
  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
  \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
  CONFIG_SHELL='$SHELL'
  export CONFIG_SHELL
  exec "\$@"
fi

_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
exec 5>>config.log
{
  echo
  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
  $as_echo "$ac_log"
  printf "%s\n" "$ac_log"
} >&5

_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1

# Handling of arguments.
for ac_config_target in $ac_config_targets
do
  case $ac_config_target in
    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
    "tclConfig.sh") CONFIG_FILES="$CONFIG_FILES tclConfig.sh" ;;
    "tcl.hpj") CONFIG_FILES="$CONFIG_FILES tcl.hpj" ;;
    "tclsh.exe.manifest") CONFIG_FILES="$CONFIG_FILES tclsh.exe.manifest" ;;

  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
  *) as_fn_error $? "invalid argument: '$ac_config_target'" "$LINENO" 5;;
  esac
done


# If the user did not use the arguments to specify the items to instantiate,
# then the envvar interface is used.  Set only those that are not.
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
  test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
fi

# Have a temporary directory for convenience.  Make it in the build tree
# simply because there is no reason against having it here, and in addition,
# creating and moving files from /tmp can sometimes cause problems.
# Hook for its removal unless debugging.
# Note that there is a small window in which the directory will not be cleaned:
# after its creation but before its name has been assigned to `$tmp'.
# after its creation but before its name has been assigned to '$tmp'.
$debug ||
{
  tmp= ac_tmp=
  trap 'exit_status=$?
  : "${ac_tmp:=$tmp}"
  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
' 0
6174
6175
6176
6177
6178
6179
6180
6181

6182
6183
6184
6185
6186
6187
6188
6751
6752
6753
6754
6755
6756
6757

6758
6759
6760
6761
6762
6763
6764
6765







-
+







  tmp=./conf$$-$RANDOM
  (umask 077 && mkdir "$tmp")
} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
ac_tmp=$tmp

# Set up the scripts for CONFIG_FILES section.
# No need to generate them if there are no CONFIG_FILES.
# This happens for instance with `./config.status config.h'.
# This happens for instance with './config.status config.h'.
if test -n "$CONFIG_FILES"; then


ac_cr=`echo X | tr X '\015'`
# On cygwin, bash can eat \r inside `` if the user requested igncr.
# But we know of no other shell where ac_cr would be empty at this
# point, so we can use a bashism as a fallback.
6340
6341
6342
6343
6344
6345
6346
6347

6348
6349
6350
6351
6352
6353
6354
6917
6918
6919
6920
6921
6922
6923

6924
6925
6926
6927
6928
6929
6930
6931







-
+







for ac_tag
do
  case $ac_tag in
  :[FHLC]) ac_mode=$ac_tag; continue;;
  esac
  case $ac_mode$ac_tag in
  :[FHL]*:*);;
  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
  :L* | :C*:*) as_fn_error $? "invalid tag '$ac_tag'" "$LINENO" 5;;
  :[FH]-) ac_tag=-:-;;
  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
  esac
  ac_save_IFS=$IFS
  IFS=:
  set x $ac_tag
  IFS=$ac_save_IFS
6362
6363
6364
6365
6366
6367
6368
6369

6370
6371
6372
6373
6374
6375

6376
6377

6378
6379
6380
6381

6382
6383
6384
6385

6386
6387
6388
6389
6390


6391
6392
6393
6394
6395

6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412

6413
6414
6415
6416
6417
6418
6419
6939
6940
6941
6942
6943
6944
6945

6946
6947
6948
6949
6950
6951

6952
6953

6954
6955
6956
6957

6958
6959
6960
6961

6962
6963
6964
6965


6966
6967
6968
6969
6970
6971

6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988

6989
6990
6991
6992
6993
6994
6995
6996







-
+





-
+

-
+



-
+



-
+



-
-
+
+




-
+
















-
+







    ac_file_inputs=
    for ac_f
    do
      case $ac_f in
      -) ac_f="$ac_tmp/stdin";;
      *) # Look for the file first in the build tree, then in the source tree
	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
	 # because $ac_f cannot contain `:'.
	 # because $ac_f cannot contain ':'.
	 test -f "$ac_f" ||
	   case $ac_f in
	   [\\/$]*) false;;
	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
	   esac ||
	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
	   as_fn_error 1 "cannot find input file: '$ac_f'" "$LINENO" 5;;
      esac
      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
      case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
      as_fn_append ac_file_inputs " '$ac_f'"
    done

    # Let's still pretend it is `configure' which instantiates (i.e., don't
    # Let's still pretend it is 'configure' which instantiates (i.e., don't
    # use $as_me), people would be surprised to read:
    #    /* config.h.  Generated by config.status.  */
    configure_input='Generated from '`
	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
	  printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
	`' by configure.'
    if test x"$ac_file" != x-; then
      configure_input="$ac_file.  $configure_input"
      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
$as_echo "$as_me: creating $ac_file" >&6;}
      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
printf "%s\n" "$as_me: creating $ac_file" >&6;}
    fi
    # Neutralize special characters interpreted by sed in replacement strings.
    case $configure_input in #(
    *\&* | *\|* | *\\* )
       ac_sed_conf_input=`$as_echo "$configure_input" |
       ac_sed_conf_input=`printf "%s\n" "$configure_input" |
       sed 's/[\\\\&|]/\\\\&/g'`;; #(
    *) ac_sed_conf_input=$configure_input;;
    esac

    case $ac_tag in
    *:-:* | *:-) cat >"$ac_tmp/stdin" \
      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
    esac
    ;;
  esac

  ac_dir=`$as_dirname -- "$ac_file" ||
$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$ac_file" : 'X\(//\)[^/]' \| \
	 X"$ac_file" : 'X\(//\)$' \| \
	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$ac_file" |
printf "%s\n" X"$ac_file" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
	    s//\1/
	    q
	  }
	  /^X\(\/\/\)[^/].*/{
	    s//\1/
	    q
6429
6430
6431
6432
6433
6434
6435
6436

6437
6438

6439
6440
6441
6442
6443
6444
6445
7006
7007
7008
7009
7010
7011
7012

7013
7014

7015
7016
7017
7018
7019
7020
7021
7022







-
+

-
+







	  s/.*/./; q'`
  as_dir="$ac_dir"; as_fn_mkdir_p
  ac_builddir=.

case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
  ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
  # A ".." for each directory in $ac_dir_suffix.
  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
  ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
  case $ac_top_builddir_sub in
  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
  esac ;;
esac
ac_abs_top_builddir=$ac_pwd
ac_abs_builddir=$ac_pwd$ac_dir_suffix
6484
6485
6486
6487
6488
6489
6490
6491
6492


6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505

6506
6507
6508
6509
6510
6511
6512
7061
7062
7063
7064
7065
7066
7067


7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
7079
7080
7081

7082
7083
7084
7085
7086
7087
7088
7089







-
-
+
+












-
+







/@docdir@/p
/@infodir@/p
/@localedir@/p
/@mandir@/p'
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
  ac_datarootdir_hack='
  s&@datadir@&$datadir&g
  s&@docdir@&$docdir&g
  s&@infodir@&$infodir&g
  s&@localedir@&$localedir&g
  s&@mandir@&$mandir&g
  s&\\\${datarootdir}&$datarootdir&g' ;;
esac
_ACEOF

# Neutralize VPATH when `$srcdir' = `.'.
# Neutralize VPATH when '$srcdir' = '.'.
# Shell code in configure.ac might set extrasub.
# FIXME: do we really want to maintain this feature?
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_sed_extra="$ac_vpsub
$extrasub
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
6527
6528
6529
6530
6531
6532
6533
6534

6535
6536

6537
6538
6539
6540
6541
6542
6543
7104
7105
7106
7107
7108
7109
7110

7111
7112

7113
7114
7115
7116
7117
7118
7119
7120







-
+

-
+







eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5

test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
      "$ac_tmp/out"`; test -z "$ac_out"; } &&
  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable 'datarootdir'
which seems to be undefined.  Please make sure it is defined" >&5
$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable 'datarootdir'
which seems to be undefined.  Please make sure it is defined" >&2;}

  rm -f "$ac_tmp/stdin"
  case $ac_file in
  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
  esac \
6576
6577
6578
6579
6580
6581
6582
6583
6584


6585
6586
6587

7153
7154
7155
7156
7157
7158
7159


7160
7161
7162
7163
7164
7165







-
-
+
+



+
  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
  exec 5>>config.log
  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
  # would make configure fail if this is the last instruction.
  $ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi



Changes to win/configure.ac.

1
2
3
4
5

6
7


8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
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





+
-
-
+
+









-
+







#! /bin/bash -norc
# This file is an input file used by the GNU "autoconf" program to
# generate the file "configure", which is run during Tcl installation
# to configure the system for the local environment.

AC_INIT([tcl],[9.0])
AC_INIT(../generic/tcl.h)
AC_PREREQ(2.69)
AC_CONFIG_SRCDIR([../generic/tcl.h])
AC_PREREQ([2.69])

# The following define is needed when building with Cygwin since newer
# 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.0
TCL_MAJOR_VERSION=9
TCL_MINOR_VERSION=0
TCL_PATCH_LEVEL="a2"
TCL_PATCH_LEVEL=".1"
VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION

TCL_DDE_VERSION=1.4
TCL_DDE_MAJOR_VERSION=1
TCL_DDE_MINOR_VERSION=4
DDEVER=$TCL_DDE_MAJOR_VERSION$TCL_DDE_MINOR_VERSION

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
56
57
58
59
60
61
62

63
64
65
66
67
68
69







-







# the AC_PROG_CC macro from adding "-g -O2".
if test "${CFLAGS+set}" != "set" ; then
    CFLAGS=""
fi

AC_PROG_CC
AC_C_INLINE
AC_HEADER_STDC

AC_CHECK_TOOL(AR, ar)
AC_CHECK_TOOL(RANLIB, ranlib)
AC_CHECK_TOOL(RC, windres)

#--------------------------------------------------------------------
# Checks to see if the make program sets the $MAKE variable.
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
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







+
+






+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






+



-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+

-




-
+













-
+










-
-


-
-

+








AS_IF([test "${enable_shared+set}" = "set"], [
  enableval="$enable_shared"
  tcl_ok=$enableval
], [
  tcl_ok=yes
])
zlib_lib_name=zdll.lib
tommath_lib_name=tommath.lib
AS_IF([test "$tcl_ok" = "yes"], [
  AC_SUBST(ZLIB_DLL_FILE,[\${ZLIB_DLL_FILE}])
  AC_SUBST(TOMMATH_DLL_FILE,[\${TOMMATH_DLL_FILE}])
  AC_DEFINE(TCL_WITH_EXTERNAL_TOMMATH, 1, [Tcl with external libtommath])
  AS_IF([test "$do64bit" != "no"], [
    AC_DEFINE(MP_64BIT, 1, [Using libtommath.dll in 64-bit mode])
    AS_IF([test "$do64bit" = "arm64"], [
    AS_IF([test "$GCC" == "yes"],[
      AC_SUBST(ZLIB_LIBS,[\${ZLIB_DIR_NATIVE}/win64/libz.dll.a])
      AC_SUBST(TOMMATH_LIBS,[\${TOMMATH_DIR_NATIVE}/win64/libtommath.dll.a])
    ], [
      AC_SUBST(ZLIB_LIBS,[\${ZLIB_DIR_NATIVE}/win64/zdll.lib])
      AC_SUBST(TOMMATH_LIBS,[\${TOMMATH_DIR_NATIVE}/win64/tommath.lib])
      AS_IF([test "$GCC" = "yes"],[
	AC_SUBST(ZLIB_LIBS,[\${ZLIB_DIR_NATIVE}/win64-arm/libz.dll.a])
	AC_SUBST(TOMMATH_LIBS,[\${TOMMATH_DIR_NATIVE}/win64-arm/libtommath.dll.a])
	zlib_lib_name=libz.dll.a
	tommath_lib_name=libtommath.dll.a
      ], [
	AC_SUBST(ZLIB_LIBS,[\${ZLIB_DIR_NATIVE}/win64-arm/zdll.lib])
	AC_SUBST(TOMMATH_LIBS,[\${TOMMATH_DIR_NATIVE}/win64-arm/tommath.lib])
      ])
    ], [
      AS_IF([test "$GCC" = "yes"],[
	AC_SUBST(ZLIB_LIBS,[\${ZLIB_DIR_NATIVE}/win64/libz.dll.a])
	AC_SUBST(TOMMATH_LIBS,[\${TOMMATH_DIR_NATIVE}/win64/libtommath.dll.a])
	zlib_lib_name=libz.dll.a
	tommath_lib_name=libtommath.dll.a
      ], [
	AC_SUBST(ZLIB_LIBS,[\${ZLIB_DIR_NATIVE}/win64/zdll.lib])
	AC_SUBST(TOMMATH_LIBS,[\${TOMMATH_DIR_NATIVE}/win64/tommath.lib])
      ])
    ])
  ], [
    AC_SUBST(ZLIB_LIBS,[\${ZLIB_DIR_NATIVE}/win32/zdll.lib])
    AC_SUBST(TOMMATH_LIBS,[\${TOMMATH_DIR_NATIVE}/win32/tommath.lib])
  ])
], [
  AC_DEFINE(TCL_WITH_INTERNAL_ZLIB, 1, [Tcl with internal zlib])
  AC_SUBST(ZLIB_OBJS,[\${ZLIB_OBJS}])
  AC_SUBST(TOMMATH_OBJS,[\${TOMMATH_OBJS}])
])
AC_DEFINE(HAVE_ZLIB, 1, [Is there an installed zlib?])

AC_CHECK_TYPE([intptr_t], [
AC_SUBST(TCL_ZLIB_LIB_NAME, $zlib_lib_name)
AC_SUBST(TCL_TOMMATH_LIB_NAME, $tommath_lib_name)
    AC_DEFINE([HAVE_INTPTR_T], 1, [Do we have the intptr_t type?])], [
    AC_CACHE_CHECK([for pointer-size signed integer type], tcl_cv_intptr_t, [
    for tcl_cv_intptr_t in "int" "long" "long long" none; do
	if test "$tcl_cv_intptr_t" != none; then
	    AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],
		    [[sizeof (void *) <= sizeof ($tcl_cv_intptr_t)]])],
		[tcl_ok=yes], [tcl_ok=no])
	    test "$tcl_ok" = yes && break; fi
    done])
    if test "$tcl_cv_intptr_t" != none; then
	AC_DEFINE_UNQUOTED([intptr_t], [$tcl_cv_intptr_t], [Signed integer
	   type wide enough to hold a pointer.])
    fi
])
AC_CHECK_TYPE([uintptr_t], [
AC_CHECK_TYPES([intptr_t, uintptr_t],,,[[
    AC_DEFINE([HAVE_UINTPTR_T], 1, [Do we have the uintptr_t type?])], [
    AC_CACHE_CHECK([for pointer-size unsigned integer type], tcl_cv_uintptr_t, [
    for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \
	    none; do
	if test "$tcl_cv_uintptr_t" != none; then
	    AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],
		    [[sizeof (void *) <= sizeof ($tcl_cv_uintptr_t)]])],
		[tcl_ok=yes], [tcl_ok=no])
	    test "$tcl_ok" = yes && break; fi
    done])
    if test "$tcl_cv_uintptr_t" != none; then
	AC_DEFINE_UNQUOTED([uintptr_t], [$tcl_cv_uintptr_t], [Unsigned integer
	   type wide enough to hold a pointer.])
#include <stdint.h>
    fi
])
]])


#--------------------------------------------------------------------
#	Zipfs support - Tip 430
#--------------------------------------------------------------------
AC_ARG_ENABLE(zipfs,
    AC_HELP_STRING([--enable-zipfs],
    AS_HELP_STRING([--enable-zipfs],
	[build with Zipfs support (default: on)]),
    [tcl_ok=$enableval], [tcl_ok=yes])
if test "$tcl_ok" = "yes" ; then
    #
    # Find a native compiler
    #
    AX_CC_FOR_BUILD
    #
    # Find a native zip implementation
    #
    SC_PROG_TCLSH
    SC_ZIPFS_SUPPORT
	ZIPFS_BUILD=1
	TCL_ZIP_FILE=libtcl_${TCL_MAJOR_VERSION}_${TCL_MINOR_VERSION}_${TCL_PATCH_LEVEL}.zip
	TCL_ZIP_FILE=libtcl${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_PATCH_LEVEL}.zip
else
	ZIPFS_BUILD=0
	TCL_ZIP_FILE=
fi
# Do checking message here to not mess up interleaved configure output
AC_MSG_CHECKING([for building with zipfs])
if test "${ZIPFS_BUILD}" = 1; then
    if test "${SHARED_BUILD}" = 0; then
       ZIPFS_BUILD=2;
       AC_DEFINE(ZIPFS_BUILD, 2, [Are we building with zipfs enabled?])
       INSTALL_LIBRARIES=install-libraries-zipfs-static
       AC_MSG_RESULT([yes])
     else
       AC_DEFINE(ZIPFS_BUILD, 1, [Are we building with zipfs enabled?])\
       INSTALL_LIBRARIES=install-libraries-zipfs-shared
       AC_MSG_RESULT([yes])
    fi
    AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
INSTALL_LIBRARIES=install-libraries
INSTALL_MSGS=install-msgs
fi
AC_SUBST(ZIPFS_BUILD)
AC_SUBST(TCL_ZIP_FILE)
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
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







-
+



-
+
-


-
-
-
+
+
+



-
+






-
+




-
+
-

-
-
-
+
+
+



-
+






-
+

-
-
-
+
+
+



-
+








-
+



-
+
-


-
-
-
+
+
+



-
+








# See if declarations like FINDEX_INFO_LEVELS are
# missing from winbase.h. This is known to be
# a problem with VC++ 5.2.

AC_CACHE_CHECK(for FINDEX_INFO_LEVELS in winbase.h,
    tcl_cv_findex_enums,
AC_TRY_COMPILE([
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
],
]], [[
[
  FINDEX_INFO_LEVELS i;
  FINDEX_SEARCH_OPS j;
],
        tcl_cv_findex_enums=yes,
        tcl_cv_findex_enums=no)
]])],
    [tcl_cv_findex_enums=yes],
    [tcl_cv_findex_enums=no])
)
if test "$tcl_cv_findex_enums" = "no"; then
    AC_DEFINE(HAVE_NO_FINDEX_ENUMS, 1,
            [Defined when enums are missing from winbase.h])
	    [Defined when enums are missing from winbase.h])
fi

# See if the compiler supports intrinsics.

AC_CACHE_CHECK(for intrinsics support in compiler,
    tcl_cv_intrinsics,
AC_TRY_LINK([
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#include <intrin.h>
],
]], [[
[
  __cpuidex(0,0,0);
],
        tcl_cv_intrinsics=yes,
        tcl_cv_intrinsics=no)
]])],
    [tcl_cv_intrinsics=yes],
    [tcl_cv_intrinsics=no])
)
if test "$tcl_cv_intrinsics" = "yes"; then
    AC_DEFINE(HAVE_INTRIN_H, 1,
            [Defined when the compilers supports intrinsics])
	    [Defined when the compilers supports intrinsics])
fi

# See if the <wspiapi.h> header file is present

AC_CACHE_CHECK(for wspiapi.h,
    tcl_cv_wspiapi_h,
AC_TRY_COMPILE([
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <wspiapi.h>
], [],
        tcl_cv_wspiapi_h=yes,
        tcl_cv_wspiapi_h=no)
]], [[]])],
    [tcl_cv_wspiapi_h=yes],
    [tcl_cv_wspiapi_h=no])
)
if test "$tcl_cv_wspiapi_h" = "yes"; then
    AC_DEFINE(HAVE_WSPIAPI_H, 1,
            [Defined when wspiapi.h exists])
	    [Defined when wspiapi.h exists])
fi

# See if declarations like FINDEX_INFO_LEVELS are
# missing from winbase.h. This is known to be
# a problem with VC++ 5.2.

AC_CACHE_CHECK(for FINDEX_INFO_LEVELS in winbase.h,
    tcl_cv_findex_enums,
AC_TRY_COMPILE([
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
],
]], [[
[
  FINDEX_INFO_LEVELS i;
  FINDEX_SEARCH_OPS j;
],
        tcl_cv_findex_enums=yes,
        tcl_cv_findex_enums=no)
]])],
    [tcl_cv_findex_enums=yes],
    [tcl_cv_findex_enums=no])
)
if test "$tcl_cv_findex_enums" = "no"; then
    AC_DEFINE(HAVE_NO_FINDEX_ENUMS, 1,
            [Defined when enums are missing from winbase.h])
	    [Defined when enums are missing from winbase.h])
fi

#--------------------------------------------------------------------
# Set the default compiler switches based on the --enable-symbols
# option.  This macro depends on C flags, and should be called
# after SC_CONFIG_CFLAGS macro is called.
#--------------------------------------------------------------------
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
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
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







-
-
+
+





-
+
+


+


-
-
+
+






-



-




















-
+

-
+












-
+







# Perform final evaluations of variables with possible substitutions.
#--------------------------------------------------------------------

eval "TCL_SRC_DIR=\"`cd $srcdir/..; $CYGPATH $(pwd)`\""

eval "TCL_DLL_FILE=tcl${VER}${DLLSUFFIX}"

eval "TCL_STUB_LIB_FILE=\"${LIBPREFIX}tclstub${VER}${LIBSUFFIX}\""
eval "TCL_STUB_LIB_FLAG=\"-ltclstub${VER}${LIBFLAGSUFFIX}\""
eval "TCL_STUB_LIB_FILE=\"${LIBPREFIX}tclstub${LIBSUFFIX}\""
eval "TCL_STUB_LIB_FLAG=\"-ltclstub${LIBFLAGSUFFIX}\""
eval "TCL_BUILD_STUB_LIB_SPEC=\"-L`$CYGPATH $(pwd)` ${TCL_STUB_LIB_FLAG}\""
eval "TCL_STUB_LIB_SPEC=\"-L${libdir} ${TCL_STUB_LIB_FLAG}\""
eval "TCL_BUILD_STUB_LIB_PATH=\"`$CYGPATH $(pwd)`/${TCL_STUB_LIB_FILE}\""
eval "TCL_STUB_LIB_PATH=\"${libdir}/${TCL_STUB_LIB_FILE}\""

if test ${SHARED_BUILD} = 0 ; then
if test ${SHARED_BUILD} = 0 -o "$GCC" != "yes" ; then
 eval "TCL_LIB_FLAG=\"${LIBPREFIX}tcl${VER}${LIBSUFFIX}\""
 eval "TCL_LIB_FILE=\"${LIBPREFIX}tcl${VER}${LIBSUFFIX}\""
else
 eval "TCL_LIB_FLAG=\"-ltcl${VER}${FLAGSUFFIX}\""
 eval "TCL_LIB_FILE=\"${LIBPREFIX}tcl${VER}${DLLSUFFIX}.a\""
fi
eval "TCL_BUILD_LIB_SPEC=\"-L`$CYGPATH $(pwd)` -ltcl${VER}${FLAGSUFFIX}\""
eval "TCL_LIB_SPEC=\"-L${libdir} -ltcl${VER}${FLAGSUFFIX}\""
eval "TCL_BUILD_LIB_SPEC=\"-L`$CYGPATH $(pwd)` ${TCL_LIB_FLAG}\""
eval "TCL_LIB_SPEC=\"-L${libdir} ${TCL_LIB_FLAG}\""

# Install time header dir can be set via --includedir
eval "TCL_INCLUDE_SPEC=\"-I${includedir}\""

TCL_SHARED_LIB_SUFFIX="\${NODOT_VERSION}${DLLSUFFIX}"
TCL_UNSHARED_LIB_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"
TCL_EXPORT_FILE_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"

CFG_TCL_SHARED_LIB_SUFFIX=${TCL_SHARED_LIB_SUFFIX}
CFG_TCL_UNSHARED_LIB_SUFFIX=${TCL_UNSHARED_LIB_SUFFIX}
CFG_TCL_EXPORT_FILE_SUFFIX=${TCL_EXPORT_FILE_SUFFIX}

#--------------------------------------------------------------------
# Adjust the defines for how the resources are built depending
# on symbols and static vs. shared.
#--------------------------------------------------------------------

if test ${SHARED_BUILD} = 0 ; then
    RC_DEFINES="${RC_DEFINE} STATIC_BUILD"
else
    RC_DEFINES=""
fi

#--------------------------------------------------------------------
#	The statements below define the symbol TCL_PACKAGE_PATH, which
#	gives a list of directories that may contain packages.  The list
#	consists of one directory for machine-dependent binaries and
#	another for platform-independent scripts.
#--------------------------------------------------------------------

if test "$prefix/lib" != "$libdir"; then
    TCL_PACKAGE_PATH="{${libdir}} {${prefix}/lib}"
    TCL_PACKAGE_PATH="${libdir};${prefix}\\lib"
else
    TCL_PACKAGE_PATH="{${prefix}/lib}"
    TCL_PACKAGE_PATH="${prefix}\\lib"
fi

# The tclsh.exe.manifest requires these
# TCL_WIN_VERSION is the 4 dotted pair Windows version format which needs
# the release level, and must account for interim release versioning
case "$TCL_PATCH_LEVEL" in
     *a*) TCL_RELEASE_LEVEL=0 ;;
     *b*) TCL_RELEASE_LEVEL=1 ;;
     *)   TCL_RELEASE_LEVEL=2 ;;
esac
TCL_WIN_VERSION="$TCL_VERSION.$TCL_RELEASE_LEVEL.`echo $TCL_PATCH_LEVEL | tr -d ab.`"
AC_SUBST(TCL_WIN_VERSION)
# X86|AMD64|IA64 for manifest
# X86|AMD64|ARM64|IA64 for manifest
AC_SUBST(MACHINE)

AC_SUBST(TCL_VERSION)
AC_SUBST(TCL_MAJOR_VERSION)
AC_SUBST(TCL_MINOR_VERSION)
AC_SUBST(TCL_PATCH_LEVEL)
AC_SUBST(PKG_CFG_ARGS)
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
407
408
409
410
411
412
413

414
415
416
417
418
419
420







-







AC_SUBST(TCL_BUILD_STUB_LIB_PATH)
AC_SUBST(TCL_DLL_FILE)

AC_SUBST(TCL_SRC_DIR)
AC_SUBST(TCL_BIN_DIR)
AC_SUBST(CFG_TCL_SHARED_LIB_SUFFIX)
AC_SUBST(CFG_TCL_UNSHARED_LIB_SUFFIX)
AC_SUBST(CFG_TCL_EXPORT_FILE_SUFFIX)

# win/tcl.m4 doesn't set (CFLAGS)
AC_SUBST(CFLAGS_DEFAULT)
AC_SUBST(EXTRA_CFLAGS)
AC_SUBST(CYGPATH)
AC_SUBST(DEPARG)
AC_SUBST(CC_OBJNAME)
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498


499
500
501

502
445
446
447
448
449
450
451

452







453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470

471
472
473
474

475
476







-

-
-
-
-
-
-
-


















-
+
+


-
+

AC_SUBST(LIBRARIES)
AC_SUBST(MAKE_LIB)
AC_SUBST(MAKE_STUB_LIB)
AC_SUBST(POST_MAKE_LIB)
AC_SUBST(MAKE_DLL)
AC_SUBST(MAKE_EXE)

# empty on win, but needs sub'ing
AC_SUBST(TCL_BUILD_LIB_SPEC)
AC_SUBST(TCL_CC_SEARCH_FLAGS)
AC_SUBST(TCL_LD_SEARCH_FLAGS)
AC_SUBST(TCL_NEEDS_EXP_FILE)
AC_SUBST(TCL_BUILD_EXP_FILE)
AC_SUBST(TCL_EXP_FILE)
AC_SUBST(DL_LIBS)
AC_SUBST(TCL_LIB_VERSIONS_OK)
AC_SUBST(TCL_PACKAGE_PATH)

# win only
AC_SUBST(TCL_DDE_VERSION)
AC_SUBST(TCL_DDE_MAJOR_VERSION)
AC_SUBST(TCL_DDE_MINOR_VERSION)
AC_SUBST(TCL_REG_VERSION)
AC_SUBST(TCL_REG_MAJOR_VERSION)
AC_SUBST(TCL_REG_MINOR_VERSION)

AC_SUBST(RC)
AC_SUBST(RC_OUT)
AC_SUBST(RC_TYPE)
AC_SUBST(RC_INCLUDE)
AC_SUBST(RC_DEFINE)
AC_SUBST(RC_DEFINES)
AC_SUBST(RES)

AC_OUTPUT(Makefile tclConfig.sh tcl.hpj tclsh.exe.manifest)
AC_CONFIG_FILES([Makefile tclConfig.sh tclsh.exe.manifest])
AC_OUTPUT

dnl Local Variables:
dnl mode: autoconf;
dnl mode: autoconf
dnl End:

Added win/gitmanifest.in.


1
+
git-

Changes to win/makefile.vc.

12
13
14
15
16
17
18
19
20


21
22
23
24





25
26
27
28
29
30
31
32
33
12
13
14
15
16
17
18


19
20
21



22
23
24
25
26


27
28
29
30
31
32
33







-
-
+
+

-
-
-
+
+
+
+
+
-
-







# Copyright (c) 2003-2008 Pat Thoyts.
# Copyright (c) 2017 Ashok P. Nadkarni
#------------------------------------------------------------------------------

# General usage:
#   nmake [-nologo] -f makefile.vc [TARGET|MACRODEF [TARGET|MACRODEF] [...]]
#
# For MACRODEF, see TIP 477 (https://core.tcl-lang.org/tips/doc/trunk/tip/477.md)
# or examine Sections 6-8 in rules.vc.
# For MACRODEF, see TIP 477 (https://core.tcl-lang.org/tips/doc/main/tip/477.md)
# or examine Sections 7-9 in rules.vc.
#
# Possible values of TARGET are:
#	release  -- Builds the core, the shell and the dlls. (default)
#	dlls     -- Just builds the windows extensions
# Possible values for TARGET are:
#	release  -- Builds everything that ships with a release. (default)
#	core     -- Builds the core [tclXX.(dll|lib)]
#	shell    -- Builds tclsh and the core.
#	dlls     -- Just builds the windows extensions.
#	shell    -- Just builds the shell and the core.
#	core     -- Only builds the core [tclXX.(dll|lib)].
#	all      -- Builds everything.
#	test     -- Builds and runs the test suite.
#	tcltest  -- Just builds the test shell.
#	install  -- Installs the built binaries and libraries to $(INSTALLDIR)
#		    as the root of the install tree.
#	tidy/clean/hose -- varying levels of cleaning.
#	genstubs -- Rebuilds the Stubs table and support files (dev only).
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
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







-
-
-
+
+
+


-
+




+
+
+
+
+
-
-
-
+
+
+

+

-
-
+
+

-
+
-
-
+
-
-
+







# The steps to setup a Visual C++ environment depend on which
# version of Visual Studio and/or the Windows SDK you are building
# against and are not described here. The simplest method is generally
# to start a command shell using one of the short cuts installed by
# Visual Studio/Windows SDK for the appropriate target architecture.
#
# NOTE: For older (Visual C++ 6 or the 2003 SDK), to use the Platform
# SDK (not expressly needed), run setenv.bat after
# vcvars32.bat according to the instructions for it.  This can also
# turn on the 64-bit compiler, if your SDK has it.
# SDK (not expressly needed), run setenv.bat after vcvars32.bat
# according to the instructions for it.  This can also turn on the
# 64-bit compiler, if your SDK has it.
#
# Basic macros and options usable on the commandline (see rules.vc for more info):
#	OPTS=msvcrt,nothreads,pdbs,profile,static,staticpkg,symbols,thrdalloc,unchecked,none
#	OPTS=nomsvcrt,noembed,nothreads,pdbs,profile,static,symbols,thrdalloc,unchecked,none
#		Sets special options for the core.  The default is for none.
#		Any combination of the above may be used (comma separated).
#		'none' will over-ride everything to nothing.
#
#		noembed   = Without this option, the Tcl core library scripts
#			    are embedded into the executable if "static" is
#			    specified in OPTS, or into the DLL otherwise. If
#			    "noembed" is specified, the scripts are not embedded
#			    but copied to the installation target (as in 8.6).
#		msvcrt    = Affects the static option only to switch it from
#			    using libcmt(d) as the C runtime [by default] to
#			    msvcrt(d). This is useful for static embedding
#		nomsvcrt  = Affects the static option only to switch it from
#			    using msvcrt(d) as the C runtime [by default] to
#			    libcmt(d). This is useful for static embedding
#			    support.
#		none      = Overrides all other options to nothing.
#		nothreads = Turns off full multithreading support (default on).
#		pbds      =  Produce separate debug symbol files.
#		profile   =  Adds profiling hooks.  Map file is assumed.
#		pdbs      = Produce separate debug symbol files.
#		profile   = Adds profiling hooks.  Map file is assumed.
#		static    = Builds a static library of the core instead of a
#			    dll.  The shell will be static (and large), as well.
#			    dll.  The shell will be static (and large), and
#		staticpkg = Affects the static option only to switch
#			    tclshXX.exe to have the dde and reg extension linked
#			    have the dde and registry extensions linked inside.
#			    inside it.
#		symbols   =  Adds symbols for step debugging.
#		symbols   = Adds symbols for step debugging.
#		thrdalloc = Use the thread allocator (shared global free pool).
#		unchecked = Allows a symbols build to not use the debug
#			    enabled runtime (msvcrt.dll not msvcrtd.dll
#			    or libcmt.lib not libcmtd.lib).
#
#	STATS=compdbg,memdbg,none
#		Sets optional memory and bytecode compiler debugging code added
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
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







-
+











-
+







#
#		64bit    = Enable 64bit portability warnings (if available)
#		fullwarn = Builds with full compiler and link warnings enabled.
#			    Very verbose.
#		nodep	 = Turns off compatibility macros to ensure the core
#			    isn't being built with deprecated functions.
#
#	MACHINE=(ALPHA|AMD64|IA64|IX86)
#	MACHINE=(ALPHA|AMD64|ARM64|IA64|IX86)
#		Set the machine type used for the compiler, linker, and
#		resource compiler.  This hook is needed to tell the tools
#		when alternate platforms are requested.  IX86 is the default
#		when not specified. If the CPU environment variable has been
#		set (ie: recent Platform SDK) then MACHINE is set from CPU.
#
#	TMP_DIR=<path>
#	OUT_DIR=<path>
#		Hooks to allow the intermediate and output directories to be
#		changed.  $(OUT_DIR) is assumed to be
#		$(BINROOT)\(Release|Debug) based on if symbols are requested.
#		$(TMP_DIR) will de $(OUT_DIR)\<buildtype> by default.
#		$(TMP_DIR) will be $(OUT_DIR)\<buildtype> by default.
#
#	TESTPAT=<file>
#		Reads the tests requested to be run from this file.
#
# Examples:
#       c:\tcl_src\win\>nmake -f makefile.vc release
#       c:\tcl_src\win\>nmake -f makefile.vc test
126
127
128
129
130
131
132
133

134
135
136

137
138
139







140
141
142























143
144
145
146
147
148
149
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







-
+


-
+



+
+
+
+
+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







# macros and rules.
PROJECT = tcl

# Default target to build if no target is specified. If unspecified, the
# rules.vc file will set up "all" as the target.
DEFAULT_BUILD_TARGET = release

# We want to use our own resource file, not the standard template one.
# We have a custom resource file
RCFILE = tcl.rc

# The rules.vc file does most of the hard work in terms of defining
# The rules.vc file does much of the hard work in terms of defining
# the build configuration, macros, output directories etc.
!include "rules.vc"

#
# The tclsh executable without the embedded libzip. We need this
# separately from tclsh to have dependency and build order work right.
# Ditto for the DLL and tcltest
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.
TCL_EMBED_SCRIPTS = 0
TCL_TEST_LIBRARY=$(ROOT:\=/)/library
!else
!message *** Tcl script library will be appended to the binary.
TCL_EMBED_SCRIPTS = 1
TCL_TEST_LIBRARY=
!endif

# We need versions of various core packages to generate appropriate
# file names during installation.
!if [echo REM = This file is generated from makefile.vc > versions.vc]
!endif
!if [echo PKG_HTTP_VER = \>> versions.vc] \
   && [nmakehlp -V ..\library\http\pkgIndex.tcl http >> versions.vc]
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
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







-
+










-
+


-
+


-
+
+



-
-
-
-
-
-








+

-
-
-
-


-
+
+






+







+







!if [echo PKG_SHELL_VER = \>> versions.vc] \
   && [nmakehlp -V ..\library\platform\pkgIndex.tcl "platform::shell" >> versions.vc]
!endif
!if [echo PKG_DDE_VER = \>> versions.vc] \
   && [nmakehlp -V ..\library\dde\pkgIndex.tcl "dde " >> versions.vc]
!endif
!if [echo PKG_REG_VER =\>> versions.vc] \
   && [nmakehlp -V ..\library\reg\pkgIndex.tcl registry >> versions.vc]
   && [nmakehlp -V ..\library\registry\pkgIndex.tcl "registry " >> versions.vc]
!endif

!include versions.vc

DDEDOTVERSION = 1.4
DDEVERSION = $(DDEDOTVERSION:.=)

REGDOTVERSION = 1.3
REGVERSION = $(REGDOTVERSION:.=)

TCLREGLIBNAME	= $(PROJECT)reg$(REGVERSION)$(SUFX:t=).$(EXT)
TCLREGLIBNAME	= $(PROJECT)9registry$(REGVERSION)$(SUFX:t=).$(EXT)
TCLREGLIB	= $(OUT_DIR)\$(TCLREGLIBNAME)

TCLDDELIBNAME	= $(PROJECT)dde$(DDEVERSION)$(SUFX:t=).$(EXT)
TCLDDELIBNAME	= $(PROJECT)9dde$(DDEVERSION)$(SUFX:t=).$(EXT)
TCLDDELIB	= $(OUT_DIR)\$(TCLDDELIBNAME)

TCLTEST		= $(OUT_DIR)\$(PROJECT)test.exe
TCLTEST		= $(OUT_DIR)\$(PROJECT)test$(VERSION)$(SUFX:t=).exe
TCLTESTRAW	= $(TCLTEST:.exe=-raw.exe)

TCLSHOBJS = \
	$(TMP_DIR)\tclAppInit.obj \
!if !$(STATIC_BUILD)
!if $(TCL_USE_STATIC_PACKAGES)
	$(TMP_DIR)\tclWinReg.obj \
	$(TMP_DIR)\tclWinDde.obj \
!endif
!endif
	$(TMP_DIR)\tclsh.res

TCLTESTOBJS = \
	$(TMP_DIR)\tclTest.obj \
	$(TMP_DIR)\tclTestObj.obj \
	$(TMP_DIR)\tclTestProcBodyObj.obj \
	$(TMP_DIR)\tclThreadTest.obj \
	$(TMP_DIR)\tclWinTest.obj \
	$(TMP_DIR)\tclTestABSList.obj \
!if !$(STATIC_BUILD)
!if $(TCL_USE_STATIC_PACKAGES)
	$(TMP_DIR)\tclWinReg.obj \
	$(TMP_DIR)\tclWinDde.obj \
!endif
	$(OUT_DIR)\tommath.lib \
!endif
	$(TMP_DIR)\testMain.obj
	$(TMP_DIR)\testMain.obj \
	$(TMP_DIR)\tcltest.res

COREOBJS = \
	$(TMP_DIR)\regcomp.obj \
	$(TMP_DIR)\regerror.obj \
	$(TMP_DIR)\regexec.obj \
	$(TMP_DIR)\regfree.obj \
	$(TMP_DIR)\tclArithSeries.obj \
	$(TMP_DIR)\tclAlloc.obj \
	$(TMP_DIR)\tclAssembly.obj \
	$(TMP_DIR)\tclAsync.obj \
	$(TMP_DIR)\tclBasic.obj \
	$(TMP_DIR)\tclBinary.obj \
	$(TMP_DIR)\tclCkalloc.obj \
	$(TMP_DIR)\tclClock.obj \
	$(TMP_DIR)\tclClockFmt.obj \
	$(TMP_DIR)\tclCmdAH.obj \
	$(TMP_DIR)\tclCmdIL.obj \
	$(TMP_DIR)\tclCmdMZ.obj \
	$(TMP_DIR)\tclCompCmds.obj \
	$(TMP_DIR)\tclCompCmdsGR.obj \
	$(TMP_DIR)\tclCompCmdsSZ.obj \
	$(TMP_DIR)\tclCompExpr.obj \
244
245
246
247
248
249
250

251
252
253
254
255
256
257
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287







+







	$(TMP_DIR)\tclEvent.obj \
	$(TMP_DIR)\tclExecute.obj \
	$(TMP_DIR)\tclFCmd.obj \
	$(TMP_DIR)\tclFileName.obj \
	$(TMP_DIR)\tclGet.obj \
	$(TMP_DIR)\tclHash.obj \
	$(TMP_DIR)\tclHistory.obj \
	$(TMP_DIR)\tclIcu.obj \
	$(TMP_DIR)\tclIndexObj.obj \
	$(TMP_DIR)\tclInterp.obj \
	$(TMP_DIR)\tclIO.obj \
	$(TMP_DIR)\tclIOCmd.obj \
	$(TMP_DIR)\tclIOGT.obj \
	$(TMP_DIR)\tclIOSock.obj \
	$(TMP_DIR)\tclIOUtil.obj \
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
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







+


















+







	$(TMP_DIR)\tclNotify.obj \
	$(TMP_DIR)\tclOO.obj \
	$(TMP_DIR)\tclOOBasic.obj \
	$(TMP_DIR)\tclOOCall.obj \
	$(TMP_DIR)\tclOODefineCmds.obj \
	$(TMP_DIR)\tclOOInfo.obj \
	$(TMP_DIR)\tclOOMethod.obj \
	$(TMP_DIR)\tclOOProp.obj \
	$(TMP_DIR)\tclOOStubInit.obj \
	$(TMP_DIR)\tclObj.obj \
	$(TMP_DIR)\tclOptimize.obj \
	$(TMP_DIR)\tclPanic.obj \
	$(TMP_DIR)\tclParse.obj \
	$(TMP_DIR)\tclPathObj.obj \
	$(TMP_DIR)\tclPipe.obj \
	$(TMP_DIR)\tclPkg.obj \
	$(TMP_DIR)\tclPkgConfig.obj \
	$(TMP_DIR)\tclPosixStr.obj \
	$(TMP_DIR)\tclPreserve.obj \
	$(TMP_DIR)\tclProc.obj \
	$(TMP_DIR)\tclProcess.obj \
	$(TMP_DIR)\tclRegexp.obj \
	$(TMP_DIR)\tclResolve.obj \
	$(TMP_DIR)\tclResult.obj \
	$(TMP_DIR)\tclScan.obj \
	$(TMP_DIR)\tclStringObj.obj \
	$(TMP_DIR)\tclStrIdxTree.obj \
	$(TMP_DIR)\tclStrToD.obj \
	$(TMP_DIR)\tclStubInit.obj \
	$(TMP_DIR)\tclThread.obj \
	$(TMP_DIR)\tclThreadAlloc.obj \
	$(TMP_DIR)\tclThreadJoin.obj \
	$(TMP_DIR)\tclThreadStorage.obj \
	$(TMP_DIR)\tclTimer.obj \
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
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







-
+

-
+


















+
+















+







	$(TMP_DIR)\bn_mp_cnt_lsb.obj \
	$(TMP_DIR)\bn_mp_copy.obj \
	$(TMP_DIR)\bn_mp_count_bits.obj \
	$(TMP_DIR)\bn_mp_div.obj \
	$(TMP_DIR)\bn_mp_div_d.obj \
	$(TMP_DIR)\bn_mp_div_2.obj \
	$(TMP_DIR)\bn_mp_div_2d.obj \
	$(TMP_DIR)\bn_mp_div_3.obj \
	$(TMP_DIR)\bn_s_mp_div_3.obj \
	$(TMP_DIR)\bn_mp_exch.obj \
	$(TMP_DIR)\bn_mp_expt_u32.obj \
	$(TMP_DIR)\bn_mp_expt_n.obj \
	$(TMP_DIR)\bn_mp_get_mag_u64.obj \
	$(TMP_DIR)\bn_mp_grow.obj \
	$(TMP_DIR)\bn_mp_init.obj \
	$(TMP_DIR)\bn_mp_init_copy.obj \
	$(TMP_DIR)\bn_mp_init_i64.obj \
	$(TMP_DIR)\bn_mp_init_multi.obj \
	$(TMP_DIR)\bn_mp_init_set.obj \
	$(TMP_DIR)\bn_mp_init_size.obj \
	$(TMP_DIR)\bn_mp_init_u64.obj \
	$(TMP_DIR)\bn_mp_lshd.obj \
	$(TMP_DIR)\bn_mp_mod.obj \
	$(TMP_DIR)\bn_mp_mod_2d.obj \
	$(TMP_DIR)\bn_mp_mul.obj \
	$(TMP_DIR)\bn_mp_mul_2.obj \
	$(TMP_DIR)\bn_mp_mul_2d.obj \
	$(TMP_DIR)\bn_mp_mul_d.obj \
	$(TMP_DIR)\bn_mp_neg.obj \
	$(TMP_DIR)\bn_mp_or.obj \
	$(TMP_DIR)\bn_mp_pack.obj \
	$(TMP_DIR)\bn_mp_pack_count.obj \
	$(TMP_DIR)\bn_mp_radix_size.obj \
	$(TMP_DIR)\bn_mp_radix_smap.obj \
	$(TMP_DIR)\bn_mp_read_radix.obj \
	$(TMP_DIR)\bn_mp_rshd.obj \
	$(TMP_DIR)\bn_mp_set_i64.obj \
	$(TMP_DIR)\bn_mp_set_u64.obj \
	$(TMP_DIR)\bn_mp_shrink.obj \
	$(TMP_DIR)\bn_mp_sqr.obj \
	$(TMP_DIR)\bn_mp_sqrt.obj \
	$(TMP_DIR)\bn_mp_sub.obj \
	$(TMP_DIR)\bn_mp_sub_d.obj \
	$(TMP_DIR)\bn_mp_signed_rsh.obj \
	$(TMP_DIR)\bn_mp_to_ubin.obj \
	$(TMP_DIR)\bn_mp_to_radix.obj \
	$(TMP_DIR)\bn_mp_ubin_size.obj \
	$(TMP_DIR)\bn_mp_unpack.obj \
	$(TMP_DIR)\bn_mp_xor.obj \
	$(TMP_DIR)\bn_mp_zero.obj \
	$(TMP_DIR)\bn_s_mp_add.obj \
	$(TMP_DIR)\bn_s_mp_balance_mul.obj \
	$(TMP_DIR)\bn_s_mp_karatsuba_mul.obj \
	$(TMP_DIR)\bn_s_mp_karatsuba_sqr.obj \
	$(TMP_DIR)\bn_s_mp_mul_digs.obj \
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


467
468
469


470
471
472
473

474
475
476
477


478
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
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
467
468
469
470
471
472
473
474

475
476
477
478
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
558
559
560

561
562
563


564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627










628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679







+










+
+









+
+
+



-
+
+
+
+
+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
-
-
+
+
+
+
+
+
+







-
-
+
+

-
-
+
+



-
+


-
-
+
+
















+
+
+










+

+
+
+
+



+

+
+
+



















-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+








+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	$(TMP_DIR)\tclWinNotify.obj \
	$(TMP_DIR)\tclWinPipe.obj \
	$(TMP_DIR)\tclWinSerial.obj \
	$(TMP_DIR)\tclWinSock.obj \
	$(TMP_DIR)\tclWinThrd.obj \
	$(TMP_DIR)\tclWinTime.obj \
!if $(STATIC_BUILD)
	$(TMP_DIR)\tclWinPanic.obj \
	$(TMP_DIR)\tclWinReg.obj \
	$(TMP_DIR)\tclWinDde.obj \
!else
	$(TMP_DIR)\tcl.res
!endif

TCLOBJS = $(COREOBJS) $(ZLIBOBJS) $(TOMMATHOBJS) $(PLATFORMOBJS)

TCLSTUBOBJS = \
	$(TMP_DIR)\tclStubLib.obj \
	$(TMP_DIR)\tclStubCall.obj \
	$(TMP_DIR)\tclStubLibTbl.obj \
	$(TMP_DIR)\tclTomMathStubLib.obj \
	$(TMP_DIR)\tclOOStubLib.obj \
	$(TMP_DIR)\tclWinPanic.obj

### The following paths CANNOT have spaces in them as they appear on
### the left side of implicit rules.
TOMMATHDIR	= $(ROOT)\libtommath
PKGSDIR		= $(ROOT)\pkgs

LIBTCLVFSSUBDIR = libtcl.vfs
LIBTCLVFS = $(OUT_DIR)\$(LIBTCLVFSSUBDIR)

# Additional include and C macro definitions for the implicit rules
# defined in rules.vc
PRJ_INCLUDES	= -I"$(TOMMATHDIR)"
PRJ_DEFINES	= /DTCL_TOMMATH /DMP_PREC=4 /Dinline=__inline /DHAVE_ZLIB=1 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DMP_FIXED_CUTOFFS
PRJ_DEFINES	= /DMP_PREC=4 /Dinline=__inline /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DMP_FIXED_CUTOFFS

!if $(STATIC_BUILD)
PRJ_DEFINES = $(PRJ_DEFINES) /DTCL_WITH_INTERNAL_ZLIB
!endif

# Additional Link libraries needed beyond those in rules.vc
PRJ_LIBS   = netapi32.lib user32.lib userenv.lib ws2_32.lib

#---------------------------------------------------------------------
# TclTest flags
#---------------------------------------------------------------------

!if "$(TESTPAT)" != ""
TESTFLAGS = $(TESTFLAGS) -file $(TESTPAT)
!endif


#---------------------------------------------------------------------
# Project specific targets
# There are 4 primary build configurations to consider from the combination
# of static/shared and embed/noembed of the library zip. The targets are
# done in the following order.
# $(TCLLIB) - this is either the core static .lib or the .dll. The target
#             build does not embed the library zip in the DLL irrespective
#             of the noembed setting. A copy is made as $(TCLLIBRAW)
#             as the $(TCLLIB) binary is potentially modified later.
# dlls      - these are the registry and dde DLL's or static libraries
# $(TCLSH)  - the Tcl shell WITHOUT any embedded zip. This needs $(TCLLIB)
#             to be built first as it links against it. A copy is made
#             as $(TCLSHRAW) as $(TCLSH) binary may be modified later.
# $(TCLSCRIPTZIP) - the zip file that is to be embedded. Note this also
#             ships separately and needs to be built irrespective of the
#             whether it is embedded or not. All above targets need to
#             be built prior as they are used to build the zip (unlike
#             Unix where the external zip program is used.)
# core      - this virtual target builds the final release ready Tcl
#             library. For shared, embedded builds it appends $(TCLSCRIPTZIP)
#             to the $(TCLLIB). For other build configurations, this
#             is a no-op.
# shell     - this virtual target builds the final release ready tclsh shell.
#             For static, embedded builds it appends $(TCLSCRIPTZIP)
#             to the $(TCLSH). For other build configurations, this
#             is a no-op.
# release   - Everything that builds as part of a release
#---------------------------------------------------------------------

release:    setup $(TCLSH) $(TCLSTUBLIB) dlls pkgs
core:	    setup $(TCLLIB) $(TCLSTUBLIB)
shell:	    setup $(TCLSH)
release:    setup libtclzip core dlls shell pkgs
all:        setup libtclzip core dlls shell pkgs

core:	    setup $(TCLLIB)
!if $(TCL_EMBED_SCRIPTS) && !$(STATIC_BUILD)
core:	    libtclzip
	@$(COPY) /b "$(TCLLIBRAW)"+"$(TCLSCRIPTZIP)" "$(TCLLIB)"
!endif

shell:	    setup core $(TCLSH)
!if $(TCL_EMBED_SCRIPTS) && $(STATIC_BUILD)
shell:      libtclzip
	@$(COPY) /b "$(TCLSHRAW)"+"$(TCLSCRIPTZIP)" "$(TCLSH)"
!endif

dlls:	    setup $(TCLREGLIB) $(TCLDDELIB) $(OUT_DIR)\zlib1.dll $(OUT_DIR)\libtommath.dll
libtclzip:  $(TCLSCRIPTZIP)
all:	    setup $(TCLSH) $(TCLSTUBLIB) dlls pkgs
tcltest:    setup $(TCLTEST) dlls

tcltest:    setup core $(TCLTEST) dlls
!if $(TCL_EMBED_SCRIPTS) && $(STATIC_BUILD)
tcltest:      libtclzip
	@$(COPY) /b "$(TCLTESTRAW)"+"$(TCLSCRIPTZIP)" "$(TCLTEST)"
!endif

install:    install-binaries install-libraries install-docs install-pkgs
!if $(SYMBOLS)
install:    install-pdbs
!endif
setup:      default-setup

test: test-core test-pkgs
test-core: setup $(TCLTEST) dlls
	set TCL_LIBRARY=$(ROOT:\=/)/library
test-core: tcltest
	set TCL_LIBRARY=$(TCL_TEST_LIBRARY)
	$(DEBUGGER) $(TCLTEST) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) -loadfile <<
		package ifneeded dde 1.4.3 [list load "$(TCLDDELIB:\=/)" dde]
		package ifneeded registry 1.3.5 [list load "$(TCLREGLIB:\=/)" registry]
		package ifneeded dde 1.4.5 [list load "$(TCLDDELIB:\=/)"]
		package ifneeded registry 1.3.7 [list load "$(TCLREGLIB:\=/)"]
<<

runtest: setup $(TCLTEST) dlls
	set TCL_LIBRARY=$(ROOT:\=/)/library
	set TCL_LIBRARY=$(TCL_TEST_LIBRARY)
	$(DEBUGGER) $(TCLTEST) $(SCRIPT)

runshell: setup $(TCLSH) dlls
	set TCL_LIBRARY=$(ROOT:\=/)/library
runshell: setup core shell dlls
	set TCL_LIBRARY=$(TCL_TEST_LIBRARY)
	$(DEBUGGER) $(TCLSH) $(SCRIPT)

!if $(STATIC_BUILD)

$(TCLLIB): $(TCLOBJS)
	$(LIBCMD) @<<
$**
<<

!else

$(TCLLIB): $(TCLOBJS)
	$(DLLCMD) @<<
$**
<<
	$(_VC_MANIFEST_EMBED_DLL)
!if $(TCL_EMBED_SCRIPTS) && !$(STATIC_BUILD)
	$(COPY) $@ $(TCLLIBRAW)
!endif

$(TCLIMPLIB): $(TCLLIB)

!endif # $(STATIC_BUILD)

$(TCLSTUBLIB): $(TCLSTUBOBJS)
	$(LIBCMD) -nodefaultlib $(TCLSTUBOBJS)

$(TCLSH): $(TCLSHOBJS) $(TCLSTUBLIB) $(TCLIMPLIB)
	$(CONEXECMD) -stack:2300000 $**
	copy $(TMP_DIR)\tclsh.exe.manifest $(TCLSH).manifest
	$(_VC_MANIFEST_EMBED_EXE)
!if $(TCL_EMBED_SCRIPTS) && $(STATIC_BUILD)
	$(COPY) $@ $(TCLSHRAW)
!endif


$(TCLTEST): $(TCLTESTOBJS) $(TCLSTUBLIB) $(TCLIMPLIB)
	$(CONEXECMD) -stack:2300000 $**
	copy $(TMP_DIR)\tclsh.exe.manifest $(TCLTEST).manifest
	$(_VC_MANIFEST_EMBED_EXE)
!if $(TCL_EMBED_SCRIPTS) && $(STATIC_BUILD)
	$(COPY) $@ $(TCLTESTRAW)
!endif

!if $(STATIC_BUILD)
$(TCLDDELIB): $(TMP_DIR)\tclWinDde.obj
	$(LIBCMD) $**
!else
$(TCLDDELIB): $(TMP_DIR)\tclWinDde.obj $(TCLSTUBLIB)
	$(DLLCMD) $**
	$(_VC_MANIFEST_EMBED_DLL)
!endif

!if $(STATIC_BUILD)
$(TCLREGLIB): $(TMP_DIR)\tclWinReg.obj
	$(LIBCMD) $**
!else
$(TCLREGLIB): $(TMP_DIR)\tclWinReg.obj $(TCLSTUBLIB)
	$(DLLCMD) $**
	$(_VC_MANIFEST_EMBED_DLL)
!endif

!if "$(MACHINE)" == "AMD64"
$(OUT_DIR)\zlib1.dll:	$(COMPATDIR)\zlib\win64\zlib1.dll
	$(COPY) $(COMPATDIR)\zlib\win64\zlib1.dll $(OUT_DIR)\zlib1.dll
$(OUT_DIR)\zdll.lib:	$(COMPATDIR)\zlib\win64\zdll.lib
	$(COPY) $(COMPATDIR)\zlib\win64\zdll.lib $(OUT_DIR)\zdll.lib
$(OUT_DIR)\libtommath.dll:	$(TOMMATHDIR)\win64\libtommath.dll
	$(COPY) $(TOMMATHDIR)\win64\libtommath.dll $(OUT_DIR)\libtommath.dll
$(OUT_DIR)\tommath.lib:	$(TOMMATHDIR)\win64\tommath.lib
	$(COPY) $(TOMMATHDIR)\win64\tommath.lib $(OUT_DIR)\tommath.lib
!else
!if "$(MACHINE)" == "ARM64"
$(OUT_DIR)\zlib1.dll:	$(COMPATDIR)\zlib\win64-arm\zlib1.dll
	$(COPY) $(COMPATDIR)\zlib\win64-arm\zlib1.dll $(OUT_DIR)\zlib1.dll
$(OUT_DIR)\zdll.lib:	$(COMPATDIR)\zlib\win64-arm\zdll.lib
	$(COPY) $(COMPATDIR)\zlib\win64-arm\zdll.lib $(OUT_DIR)\zdll.lib
$(OUT_DIR)\libtommath.dll:	$(TOMMATHDIR)\win64-arm\libtommath.dll
	$(COPY) $(TOMMATHDIR)\win64-arm\libtommath.dll $(OUT_DIR)\libtommath.dll
$(OUT_DIR)\tommath.lib:	$(TOMMATHDIR)\win64-arm\tommath.lib
	$(COPY) $(TOMMATHDIR)\win64-arm\tommath.lib $(OUT_DIR)\tommath.lib
!elseif "$(MACHINE)" == "IX86"
$(OUT_DIR)\zlib1.dll:	$(COMPATDIR)\zlib\win32\zlib1.dll
	$(COPY) $(COMPATDIR)\zlib\win32\zlib1.dll $(OUT_DIR)\zlib1.dll
$(OUT_DIR)\zdll.lib:	$(COMPATDIR)\zlib\win32\zdll.lib
	$(COPY) $(COMPATDIR)\zlib\win32\zdll.lib $(OUT_DIR)\zdll.lib
$(OUT_DIR)\libtommath.dll:	$(TOMMATHDIR)\win32\libtommath.dll
	$(COPY) $(TOMMATHDIR)\win32\libtommath.dll $(OUT_DIR)\libtommath.dll
$(OUT_DIR)\tommath.lib:	$(TOMMATHDIR)\win32\tommath.lib
	$(COPY) $(TOMMATHDIR)\win32\tommath.lib $(OUT_DIR)\tommath.lib
!else
$(OUT_DIR)\zlib1.dll:	$(COMPATDIR)\zlib\win64\zlib1.dll
	$(COPY) $(COMPATDIR)\zlib\win64\zlib1.dll $(OUT_DIR)\zlib1.dll
$(OUT_DIR)\zdll.lib:	$(COMPATDIR)\zlib\win64\zdll.lib
	$(COPY) $(COMPATDIR)\zlib\win64\zdll.lib $(OUT_DIR)\zdll.lib
$(OUT_DIR)\libtommath.dll:	$(TOMMATHDIR)\win64\libtommath.dll
	$(COPY) $(TOMMATHDIR)\win64\libtommath.dll $(OUT_DIR)\libtommath.dll
$(OUT_DIR)\tommath.lib:	$(TOMMATHDIR)\win64\tommath.lib
	$(COPY) $(TOMMATHDIR)\win64\tommath.lib $(OUT_DIR)\tommath.lib
!endif

$(TCLSCRIPTZIP): $(TCLLIB) $(TCLSH) dlls
	@echo Building Tcl library zip file $(TCLSCRIPTZIP)
	@set TCL_LIBRARY=$(ROOT:\=/)/library
	@if exist "$(LIBTCLVFS)" $(RMDIR) "$(LIBTCLVFS)"
	@$(MKDIR) "$(LIBTCLVFS)"
	@$(CPYDIR) $(LIBDIR) "$(LIBTCLVFS)\tcl_library"
	@move /y "$(LIBTCLVFS)\tcl_library\manifest.txt"  "$(LIBTCLVFS)\tcl_library\pkgIndex.tcl" > NUL
# Remove the registry and dde directories as the DLLS are still external
	@del "$(LIBTCLVFS)\tcl_library\registry\pkgIndex.tcl"
	@rmdir "$(LIBTCLVFS)\tcl_library\registry"
	@del "$(LIBTCLVFS)\tcl_library\dde\pkgIndex.tcl"
	@rmdir "$(LIBTCLVFS)\tcl_library\dde"
	@echo cd {$(OUT_DIR)} > "$(OUT_DIR)\zipper.tcl"
	@echo file delete -force {$(@F)} >> "$(OUT_DIR)\zipper.tcl"
	@echo zipfs mkzip {$(@F)} {$(LIBTCLVFSSUBDIR)} {$(LIBTCLVFSSUBDIR)} >> "$(OUT_DIR)\zipper.tcl"
	@$(TCLSH_NATIVE) "$(OUT_DIR)/zipper.tcl"

pkgs:
	@for /d %d in ($(PKGSDIR)\*) do \
	  @if exist "%~fd\win\makefile.vc" ( \
	    pushd "%~fd\win" & \
	    $(MAKE) -$(MAKEFLAGS) -f makefile.vc TCLDIR=$(ROOT) &\
	    popd \
573
574
575
576
577
578
579








580
581
582
583
584
585
586
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719







+
+
+
+
+
+
+
+







clean-pkgs:
	@for /d %d in ($(PKGSDIR)\*) do \
	  @if exist "%~fd\win\makefile.vc" ( \
	    pushd "%~fd\win" & \
	    $(MAKE) -$(MAKEFLAGS) -f makefile.vc TCLDIR=$(ROOT) clean &\
	    popd \
	  )

hose-pkgs:
	@for /d %d in ($(PKGSDIR)\*) do \
	  @if exist "%~fd\win\makefile.vc" ( \
	    pushd "%~fd\win" & \
	    $(MAKE) -$(MAKEFLAGS) -f makefile.vc TCLDIR=$(ROOT) hose &\
	    popd \
	  )

#---------------------------------------------------------------------
# Regenerate the stubs files.  [Development use only]
#---------------------------------------------------------------------

genstubs:
!if !exist($(TCLSH))
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613

614
615

616


617
618
619
620
621
622

623
624
625
626
627
628
629

630
631
632
633
634
635
636






637
638
639
640
641
642
643
727
728
729
730
731
732
733


734
735
736
737
738
739
740
741
742
743

744
745

746
747
748
749
750
751
752
753
754

755
756
757
758
759
760
761

762
763






764
765
766
767
768
769
770
771
772
773
774
775
776







-
-










-
+

-
+

+
+





-
+






-
+

-
-
-
-
-
-
+
+
+
+
+
+







!endif


#---------------------------------------------------------------------
# Build the Windows HTML help file.
#---------------------------------------------------------------------

# NOTE: you can define HHC on the command-line to override this.
# nmake does not set macro values if already set on the command line.
!if defined(PROCESSOR_ARCHITECTURE) && "$(PROCESSOR_ARCHITECTURE)" == "AMD64"
HHC="%ProgramFiles(x86)%\HTML Help Workshop\hhc.exe"
!else
HHC="%ProgramFiles%\HTML Help Workshop\hhc.exe"
!endif
HTMLDIR=$(OUT_DIR)\html
HTMLBASE=TclTk$(VERSION)
HHPFILE=$(HTMLDIR)\$(HTMLBASE).hhp
CHMFILE=$(HTMLDIR)\$(HTMLBASE).chm

htmlhelp: chmsetup $(CHMFILE)
htmlhelp: $(CHMFILE)

$(CHMFILE): $(DOCDIR)\*
htmldocs: $(DOCDIR)\*
	@$(TCLSH) $(TOOLSDIR)\tcltk-man2html.tcl "--htmldir=$(HTMLDIR)"

$(CHMFILE): htmldocs chmsetup
	@echo Compiling HTML help project
	-"$(HHC)" <<$(HHPFILE) >NUL
[OPTIONS]
Compatibility=1.1 or later
Compiled file=$(HTMLBASE).chm
Default topic=contents.htm
Default topic=index.html
Display compile progress=no
Error log file=$(HTMLBASE).log
Full-text search=Yes
Language=0x409 English (United States)
Title=Tcl/Tk $(DOTVERSION) Help
[FILES]
contents.htm
index.html
docs.css
Keywords\*.htm
TclCmd\*.htm
TclLib\*.htm
TkCmd\*.htm
TkLib\*.htm
UserCmd\*.htm
Keywords\*.html
TclCmd\*.html
TclLib\*.html
TkCmd\*.html
TkLib\*.html
UserCmd\*.html
<<

chmsetup:
	@if not exist $(HTMLDIR)\nul mkdir $(HTMLDIR)

install-docs:
!if exist("$(CHMFILE)")
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
707
708

709
710
711
712
713
714
715
716
717
718
719
720
721
722


723
724
725
726
727
728
729
797
798
799
800
801
802
803

804
805
806
807
808
809
810
811
812
813
814
815
816

817
818
819
820
821
822
823
824
825
826
827

828


829
830


831
832
833
834

835

836
837
838
839
840
841
842

843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858







-
+












-











-

-
-


-
-
+
+


-

-
+






-







+
+







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

tclConfig: $(OUT_DIR)\tclConfig.sh

# TBD - is this tclConfig.sh file ever used? The values are incorrect!
$(OUT_DIR)\tclConfig.sh: $(WIN_DIR)\tclConfig.sh.in
	@echo Creating tclConfig.sh
        @nmakehlp -s << $** >$@
	@nmakehlp -s << $** >$@
@TCL_DLL_FILE@       $(TCLLIBNAME)
@TCL_VERSION@        $(DOTVERSION)
@TCL_MAJOR_VERSION@  $(TCL_MAJOR_VERSION)
@TCL_MINOR_VERSION@  $(TCL_MINOR_VERSION)
@TCL_PATCH_LEVEL@    $(TCL_PATCH_LEVEL)
@CC@                 $(CC)
@DEFS@               $(pkgcflags)
@CFLAGS_DEBUG@       -nologo -c -W3 -YX -Fp$(TMP_DIR)\ -MDd
@CFLAGS_OPTIMIZE@    -nologo -c -W3 -YX -Fp$(TMP_DIR)\ -MD
@LDFLAGS_DEBUG@      -nologo -machine:$(MACHINE) -debug -debugtype:cv
@LDFLAGS_OPTIMIZE@   -nologo -machine:$(MACHINE) -release -opt:ref -opt:icf,3
@TCL_LIB_FILE@       $(PROJECT)$(VERSION)$(SUFX).lib
@TCL_NEEDS_EXP_FILE@
@LIBS@               $(baselibs) $(PRJ_LIBS)
@prefix@             $(_INSTALLDIR)
@exec_prefix@        $(BIN_INSTALL_DIR)
@SHLIB_CFLAGS@
@STLIB_CFLAGS@
@CFLAGS_WARNING@     -W3
@EXTRA_CFLAGS@       -YX
@SHLIB_LD@           $(link32) $(dlllflags)
@STLIB_LD@           $(lib32) -nologo
@SHLIB_LD_LIBS@      $(baselibs) $(PRJ_LIBS)
@SHLIB_SUFFIX@       .dll
@DL_LIBS@
@LDFLAGS@
@TCL_CC_SEARCH_FLAGS@
@TCL_LD_SEARCH_FLAGS@
@LIBOBJS@
@RANLIB@
@TCL_LIB_FLAG@
@TCL_BUILD_LIB_SPEC@
@TCL_LIB_FLAG@       $(PROJECT)$(VERSION)$(SUFX).lib
@TCL_BUILD_LIB_SPEC@ $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib
@TCL_LIB_SPEC@       $(LIB_INSTALL_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib
@TCL_INCLUDE_SPEC@   -I$(INCLUDE_INSTALL_DIR)
@TCL_LIB_VERSIONS_OK@
@TCL_SRC_DIR@        $(ROOT)
@TCL_PACKAGE_PATH@
@TCL_PACKAGE_PATH@   $(LIB_INSTALL_DIR)
@TCL_STUB_LIB_FILE@  $(TCLSTUBLIBNAME)
@TCL_STUB_LIB_FLAG@  $(TCLSTUBLIBNAME)
@TCL_STUB_LIB_SPEC@  -L$(LIB_INSTALL_DIR) $(TCLSTUBLIBNAME)
@TCL_BUILD_STUB_LIB_SPEC@ -L$(OUT_DIR) $(TCLSTUBLIBNAME)
@TCL_BUILD_STUB_LIB_PATH@ $(TCLSTUBLIB)
@TCL_STUB_LIB_PATH@  $(LIB_INSTALL_DIR)\$(TCLSTUBLIBNAME)
@CFG_TCL_EXPORT_FILE_SUFFIX@  $(VERSION)$(SUFX).lib
@CFG_TCL_SHARED_LIB_SUFFIX@   $(VERSION)$(SUFX).dll
@CFG_TCL_UNSHARED_LIB_SUFFIX@ $(VERSION)$(SUFX).lib
!if $(STATIC_BUILD)
@TCL_SHARED_BUILD@   0
!else
@TCL_SHARED_BUILD@   1
!endif
@TCL_ZLIB_LIB_NAME@ zdll.lib
@TCL_TOMMATH_LIB_NAME@ tommath.lib
<<


#---------------------------------------------------------------------
# The following target generates the file generic/tclDate.c
# from the yacc grammar found in generic/tclGetDate.y.  This is
# only run by hand as yacc is not available in all environments.
738
739
740
741
742
743
744
745
746
747
748
749
750
751











752
753



754
755
756



757
758
759
760
761

762


763
764
765
766













767
768
769
770
771
772
773
774
775
776
777
778
779

780
781
782
783
784
785
786
787
788
789
790
791

792
793
794
795

796
797
798
799
800
801
802
803









804
805
806
807
808
809
810
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905

906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936

937

938
939
940
941

942
943
944
945
946

947
948
949
950

951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975







-






+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+



+
+
+





+
-
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+












-
+
-




-





-
+



-
+








+
+
+
+
+
+
+
+
+








#---------------------------------------------------------------------
# Special case object file targets
#---------------------------------------------------------------------

$(TMP_DIR)\testMain.obj: $(WIN_DIR)\tclAppInit.c
	$(cc32) $(appcflags) /DTCL_TEST /DUNICODE /D_UNICODE \
	    /DTCL_USE_STATIC_PACKAGES=$(TCL_USE_STATIC_PACKAGES) \
	    -Fo$@ $?

$(TMP_DIR)\tclMainW.obj: $(GENERICDIR)\tclMain.c
	$(cc32) $(pkgcflags) /DUNICODE /D_UNICODE \
	    -Fo$@ $?

$(ROOT)\manifest.uuid:
	copy $(WIN_DIR)\gitmanifest.in $(ROOT)\manifest.uuid
	git rev-parse HEAD >>$(ROOT)\manifest.uuid

$(TMP_DIR)\tclUuid.h:	$(ROOT)\manifest.uuid
	copy $(WIN_DIR)\tclUuid.h.in+$(ROOT)\manifest.uuid $(TMP_DIR)\tclUuid.h

$(TMP_DIR)\tclEvent.obj: $(GENERICDIR)\tclEvent.c $(TMP_DIR)\tclUuid.h
	$(cc32) $(pkgcflags) -I$(COMPATDIR)\zlib -I$(TMP_DIR) \
	    -Fo$@ $(GENERICDIR)\tclEvent.c

$(TMP_DIR)\tclTest.obj: $(GENERICDIR)\tclTest.c
	$(cc32) $(appcflags) -Fo$@ $?
$(TMP_DIR)\tclTest.obj: $(GENERICDIR)\tclTest.c $(TMP_DIR)\tclUuid.h
	$(cc32) $(appcflags) -I$(TMP_DIR) \
	    -Fo$@ $(GENERICDIR)\tclTest.c

$(TMP_DIR)\tclTestObj.obj: $(GENERICDIR)\tclTestObj.c
	$(cc32) $(appcflags) -Fo$@ $?

$(TMP_DIR)\tclTestABSList.obj: $(GENERICDIR)\tclTestABSList.c
	$(cc32) $(appcflags) -Fo$@ $?

$(TMP_DIR)\tclWinTest.obj: $(WIN_DIR)\tclWinTest.c
	$(CCAPPCMD) $?

$(TMP_DIR)\tclZipfs.obj: $(GENERICDIR)\tclZipfs.c
	$(cc32) $(pkgcflags) \
	$(cc32) $(pkgcflags) -I$(COMPATDIR)\zlib -I$(COMPATDIR)\zlib\contrib\minizip -Fo$@ $?
	-I$(COMPATDIR)\zlib -I$(COMPATDIR)\zlib\contrib\minizip \
	-Fo$@ $?

$(TMP_DIR)\tclZlib.obj: $(GENERICDIR)\tclZlib.c
	$(cc32) $(pkgcflags) -I$(COMPATDIR)\zlib -Fo$@ $?

# Following the lead of the autoconf based make, we define the
# CFG_RUNTIME_*DIR flags specifically for tclPkgConfig
# and not as part of the global defines. These are all defined
# as empty strings because they are intended to represent paths
# at *runtime*, not build time. This may make sense on Unix systems
# where end-user does configure and make on the target system. It
# makes no sense on Windows where binary distributions may be installed
# anywhere. Storing build time paths as runtime paths is misleading
# at best and inefficient at worst as the code goes looking for
# files and directories that do not exist.
# Note: the same is true for the other CFG_RUNTIME* and CFG_INSTALL*
# settings as well but they are historical and I do not want to change
# them.
$(TMP_DIR)\tclPkgConfig.obj: $(GENERICDIR)\tclPkgConfig.c
	$(cc32) $(pkgcflags) \
	/DCFG_INSTALL_LIBDIR="\"$(LIB_INSTALL_DIR:\=\\)\"" \
	/DCFG_INSTALL_BINDIR="\"$(BIN_INSTALL_DIR:\=\\)\"" \
	/DCFG_INSTALL_SCRDIR="\"$(SCRIPT_INSTALL_DIR:\=\\)\"" \
	/DCFG_INSTALL_INCDIR="\"$(INCLUDE_INSTALL_DIR:\=\\)\"" \
	/DCFG_INSTALL_DOCDIR="\"$(DOC_INSTALL_DIR:\=\\)\""	\
	/DCFG_RUNTIME_LIBDIR="\"$(LIB_INSTALL_DIR:\=\\)\"" \
	/DCFG_RUNTIME_BINDIR="\"$(BIN_INSTALL_DIR:\=\\)\"" \
	/DCFG_RUNTIME_SCRDIR="\"$(SCRIPT_INSTALL_DIR:\=\\)\"" \
	/DCFG_RUNTIME_INCDIR="\"$(INCLUDE_INSTALL_DIR:\=\\)\"" \
	/DCFG_RUNTIME_DOCDIR="\"$(DOC_INSTALL_DIR:\=\\)\""     \
	/DCFG_RUNTIME_DLLFILE="\"$(CFG_RUNTIME_DLLFILE:\=\\)\""     \
	/DCFG_RUNTIME_DLLFILE="\"$(TCL_LIB_FILE)\""     \
	/DCFG_RUNTIME_ZIPFILE="\"$(CFG_RUNTIME_ZIPFILE:\=\\)\""     \
	-Fo$@ $?

$(TMP_DIR)\tclAppInit.obj: $(WIN_DIR)\tclAppInit.c
	$(cc32) $(appcflags) /DUNICODE /D_UNICODE \
	    /DTCL_USE_STATIC_PACKAGES=$(TCL_USE_STATIC_PACKAGES) \
	    -Fo$@ $?

### The following objects should be built using the stub interfaces

$(TMP_DIR)\tclWinReg.obj: $(WIN_DIR)\tclWinReg.c
	$(cc32) $(appcflags) /DUSE_TCL_STUBS -Fo$@ $?
	$(cc32) $(appcflags_nostubs) /DUSE_TCL_STUBS=1 -Fo$@ $?


$(TMP_DIR)\tclWinDde.obj: $(WIN_DIR)\tclWinDde.c
	$(cc32) $(appcflags) /DUSE_TCL_STUBS -Fo$@ $?
	$(cc32) $(appcflags_nostubs) /DUSE_TCL_STUBS=1 -Fo$@ $?


### The following objects are part of the stub library and should not
### be built as DLL objects.  -Zl is used to avoid a dependency on any
### specific C run-time.

$(TMP_DIR)\tclStubLib.obj: $(GENERICDIR)\tclStubLib.c
	$(cc32) $(stubscflags) -Fo$@ $?

$(TMP_DIR)\tclStubCall.obj: $(GENERICDIR)\tclStubCall.c
	$(cc32) $(stubscflags) \
		/DCFG_RUNTIME_DLLFILE="\"$(TCLLIBNAME)\"" \
		/DCFG_RUNTIME_BINDIR="\"$(BIN_INSTALL_DIR:\=\\)\"" \
		$(TCL_INCLUDES) -Fo$@ $?

$(TMP_DIR)\tclStubLibTbl.obj: $(GENERICDIR)\tclStubLibTbl.c
	$(cc32) $(stubscflags) $(TCL_INCLUDES) -Fo$@ $?

$(TMP_DIR)\tclTomMathStubLib.obj: $(GENERICDIR)\tclTomMathStubLib.c
	$(cc32) $(stubscflags) -Fo$@ $?

$(TMP_DIR)\tclOOStubLib.obj: $(GENERICDIR)\tclOOStubLib.c
	$(cc32) $(stubscflags) -Fo$@ $?

866
867
868
869
870
871
872

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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915

916
917
918
919



920
921
922
923
924
925
926

927
928

929
930
931

932

933


934
935
936
937
938


939
940


941


942
943
944
945
946
947
948
949
950


951
952
953
954
955
956
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
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
1116
1117
1118
1119
1120
1121
1122
1123
1124




1125

1126
1127
1128
1129

1130









1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162







+














+
+
+
+








-
-
+
+
-
-
-
-
-
-
-
-
-
-









+

-
-
-
+
+
+
-
-
-

-
-
-
+


+



+

+

+
+





+
+


+
+

+
+









+
+





-
-
-
-

-
+



-

-
-
-
-
-
-
-
-
-
+
+
+
+



+



+




+


+




+







{$(COMPATDIR)\zlib}.c{$(TMP_DIR)}.obj::
	$(cc32) $(pkgcflags) -Fo$(TMP_DIR)\ @<<
$<
<<

$(TMP_DIR)\tclsh.res: $(TMP_DIR)\tclsh.exe.manifest $(WIN_DIR)\tclsh.rc

$(TMP_DIR)\tcltest.res: $(TMP_DIR)\tclsh.exe.manifest $(WIN_DIR)\tcltest.rc

#---------------------------------------------------------------------
# Installation.
#---------------------------------------------------------------------

install-binaries:
	@echo Installing to '$(_INSTALLDIR)'
	@echo Installing $(TCLLIBNAME)
!if "$(TCLLIB)" != "$(TCLIMPLIB)"
	@$(CPY) "$(TCLLIB)" "$(BIN_INSTALL_DIR)\"
!endif
	@$(CPY) "$(TCLIMPLIB)" "$(LIB_INSTALL_DIR)\"
	@$(CPY) "$(OUT_DIR)\zlib1.dll" "$(BIN_INSTALL_DIR)\"
	@$(CPY) "$(OUT_DIR)\libtommath.dll" "$(BIN_INSTALL_DIR)\"
!if !$(STATIC_BUILD)
	@$(CPY) "$(OUT_DIR)\zdll.lib" "$(LIB_INSTALL_DIR)\"
	@$(CPY) "$(OUT_DIR)\tommath.lib" "$(LIB_INSTALL_DIR)\"
!endif
!if exist($(TCLSH))
	@echo Installing $(TCLSHNAME)
	@$(CPY) "$(TCLSH)" "$(BIN_INSTALL_DIR)\"
!endif
	@echo Installing $(TCLSTUBLIBNAME)
	@$(CPY) "$(TCLSTUBLIB)" "$(LIB_INSTALL_DIR)\"

install-libraries: tclConfig tcl-nmake install-msgs install-tzdata
	@if not exist "$(SCRIPT_INSTALL_DIR)" \
		$(MKDIR) "$(SCRIPT_INSTALL_DIR)"
	@if not exist "$(LIB_INSTALL_DIR)\nmake" \
		$(MKDIR) "$(LIB_INSTALL_DIR)\nmake"
	@if not exist "$(SCRIPT_INSTALL_DIR)\opt0.4$(NULL)" \
		$(MKDIR) "$(SCRIPT_INSTALL_DIR)\opt0.4"
	@if not exist "$(SCRIPT_INSTALL_DIR)\cookiejar0.2$(NULL)" \
		$(MKDIR) "$(SCRIPT_INSTALL_DIR)\cookiejar0.2"
	@if not exist "$(MODULE_INSTALL_DIR)$(NULL)" \
		$(MKDIR) "$(MODULE_INSTALL_DIR)"
	@if not exist "$(MODULE_INSTALL_DIR)\9.0$(NULL)" \
		$(MKDIR) "$(MODULE_INSTALL_DIR)\9.0"
	@if not exist "$(MODULE_INSTALL_DIR)\9.0\platform$(NULL)" \
		$(MKDIR) "$(MODULE_INSTALL_DIR)\9.0\platform"
	@echo Installing header files
	@$(CPY) "$(GENERICDIR)\tcl.h"             "$(INCLUDE_INSTALL_DIR)\"
	@$(CPY) "$(GENERICDIR)\tclDecls.h"        "$(INCLUDE_INSTALL_DIR)\"
	@$(CPY) "$(GENERICDIR)\tclOO.h"           "$(INCLUDE_INSTALL_DIR)\"
	@$(CPY) "$(GENERICDIR)\tclOODecls.h"      "$(INCLUDE_INSTALL_DIR)\"
	@$(CPY) "$(GENERICDIR)\tclPlatDecls.h"    "$(INCLUDE_INSTALL_DIR)\"
	@$(CPY) "$(GENERICDIR)\tclTomMath.h"      "$(INCLUDE_INSTALL_DIR)\"
	@$(CPY) "$(GENERICDIR)\tclTomMathDecls.h" "$(INCLUDE_INSTALL_DIR)\"
	@$(CPY) "$(TOMMATHDIR)\tommath.h"         "$(INCLUDE_INSTALL_DIR)\"
!if !$(TCL_EMBED_SCRIPTS)
	@echo Installing library files to $(SCRIPT_INSTALL_DIR)
	@$(CPY) "$(ROOT)\library\history.tcl"     "$(SCRIPT_INSTALL_DIR)\"
	@$(CPY) "$(ROOT)\library\init.tcl"        "$(SCRIPT_INSTALL_DIR)\"
	@$(CPY) "$(ROOT)\library\clock.tcl"       "$(SCRIPT_INSTALL_DIR)\"
	@if not exist "$(SCRIPT_INSTALL_DIR)" \
	    $(MKDIR) "$(SCRIPT_INSTALL_DIR)"
	@$(CPY) "$(ROOT)\library\*.tcl"           "$(SCRIPT_INSTALL_DIR)\"
	@$(CPY) "$(ROOT)\library\tm.tcl"          "$(SCRIPT_INSTALL_DIR)\"
	@$(CPY) "$(ROOT)\library\parray.tcl"      "$(SCRIPT_INSTALL_DIR)\"
	@$(CPY) "$(ROOT)\library\safe.tcl"        "$(SCRIPT_INSTALL_DIR)\"
	@$(CPY) "$(ROOT)\library\tclIndex"        "$(SCRIPT_INSTALL_DIR)\"
	@$(CPY) "$(ROOT)\library\package.tcl"     "$(SCRIPT_INSTALL_DIR)\"
	@$(CPY) "$(ROOT)\library\word.tcl"        "$(SCRIPT_INSTALL_DIR)\"
	@$(CPY) "$(ROOT)\library\auto.tcl"        "$(SCRIPT_INSTALL_DIR)\"
!endif
	@$(CPY) "$(OUT_DIR)\tclConfig.sh"         "$(LIB_INSTALL_DIR)\"
	@$(CPY) "$(WIN_DIR)\tclooConfig.sh"        "$(LIB_INSTALL_DIR)\"
	@$(CPY) "$(TCLSCRIPTZIP)"                    "$(LIB_INSTALL_DIR)\"
	@$(CPY) "$(WIN_DIR)\rules.vc"              "$(LIB_INSTALL_DIR)\nmake\"
	@$(CPY) "$(WIN_DIR)\targets.vc"              "$(LIB_INSTALL_DIR)\nmake\"
	@$(CPY) "$(WIN_DIR)\nmakehlp.c"            "$(LIB_INSTALL_DIR)\nmake\"
	@$(CPY) "$(WIN_DIR)\x86_64-w64-mingw32-nmakehlp.exe" "$(LIB_INSTALL_DIR)\nmake\"
	@$(CPY) "$(OUT_DIR)\tcl.nmake"            "$(LIB_INSTALL_DIR)\nmake\"
!if !$(TCL_EMBED_SCRIPTS)
	@echo Installing package cookiejar $(PKG_COOKIEJAR_VER)
	@if not exist "$(SCRIPT_INSTALL_DIR)\cookiejar0.2" \
	    $(MKDIR) "$(SCRIPT_INSTALL_DIR)\cookiejar0.2"
	@$(CPY) "$(ROOT)\library\cookiejar\*.tcl" \
	    "$(SCRIPT_INSTALL_DIR)\cookiejar0.2\"
	@$(CPY) "$(ROOT)\library\cookiejar\*.gz" \
	    "$(SCRIPT_INSTALL_DIR)\cookiejar0.2\"
	@echo Installing package opt $(PKG_OPT_VER)
	@if not exist "$(SCRIPT_INSTALL_DIR)\opt0.4" \
	    $(MKDIR) "$(SCRIPT_INSTALL_DIR)\opt0.4"
	@$(CPY) "$(ROOT)\library\opt\*.tcl" \
	    "$(SCRIPT_INSTALL_DIR)\opt0.4\"
	@if not exist "$(MODULE_INSTALL_DIR)" \
	    $(MKDIR) "$(MODULE_INSTALL_DIR)"
	@echo Installing package http $(PKG_HTTP_VER) as a Tcl Module
	@if not exist "$(MODULE_INSTALL_DIR)\9.0" \
	    $(MKDIR) "$(MODULE_INSTALL_DIR)\9.0"
	@$(COPY) "$(ROOT)\library\http\http.tcl" \
	    "$(MODULE_INSTALL_DIR)\9.0\http-$(PKG_HTTP_VER).tm"
	@echo Installing package msgcat $(PKG_MSGCAT_VER) as a Tcl Module
	@$(COPY) "$(ROOT)\library\msgcat\msgcat.tcl" \
	    "$(MODULE_INSTALL_DIR)\9.0\msgcat-$(PKG_MSGCAT_VER).tm"
	@echo Installing package tcltest $(PKG_TCLTEST_VER) as a Tcl Module
	@$(COPY) "$(ROOT)\library\tcltest\tcltest.tcl" \
	    "$(MODULE_INSTALL_DIR)\9.0\tcltest-$(PKG_TCLTEST_VER).tm"
	@echo Installing package platform $(PKG_PLATFORM_VER) as a Tcl Module
	@if not exist "$(MODULE_INSTALL_DIR)\9.0\platform" \
	    $(MKDIR) "$(MODULE_INSTALL_DIR)\9.0\platform"
	@$(COPY) "$(ROOT)\library\platform\platform.tcl" \
	    "$(MODULE_INSTALL_DIR)\9.0\platform-$(PKG_PLATFORM_VER).tm"
	@echo Installing package platform::shell $(PKG_SHELL_VER) as a Tcl Module
	@$(COPY) "$(ROOT)\library\platform\shell.tcl" \
	    "$(MODULE_INSTALL_DIR)\9.0\platform\shell-$(PKG_SHELL_VER).tm"
	@echo Installing $(TCLDDELIBNAME)
!if $(STATIC_BUILD)
!if !$(TCL_USE_STATIC_PACKAGES)
	@$(CPY) "$(TCLDDELIB)" "$(LIB_INSTALL_DIR)\"
!endif
!else
	@echo Installing $(TCLDDELIBNAME)
	@$(CPY) "$(TCLDDELIB)" "$(LIB_INSTALL_DIR)\dde$(DDEDOTVERSION)\"
	@$(CPY) "$(ROOT)\library\dde\pkgIndex.tcl" \
	    "$(LIB_INSTALL_DIR)\dde$(DDEDOTVERSION)\"
!endif
	@echo Installing $(TCLREGLIBNAME)
!if $(STATIC_BUILD)
!if !$(TCL_USE_STATIC_PACKAGES)
	@$(CPY) "$(TCLREGLIB)" "$(LIB_INSTALL_DIR)\"
!endif
!else
	@$(CPY) "$(TCLREGLIB)" "$(LIB_INSTALL_DIR)\reg$(REGDOTVERSION)\"
	@$(CPY) "$(ROOT)\library\reg\pkgIndex.tcl" \
	    "$(LIB_INSTALL_DIR)\reg$(REGDOTVERSION)\"
!endif
	@$(CPY) "$(TCLREGLIB)" "$(LIB_INSTALL_DIR)\registry$(REGDOTVERSION)\"
	@$(CPY) "$(ROOT)\library\registry\pkgIndex.tcl" \
	    "$(LIB_INSTALL_DIR)\registry$(REGDOTVERSION)\"
!if !$(TCL_EMBED_SCRIPTS)
	@echo Installing encodings
	@$(CPY) "$(ROOT)\library\encoding\*.enc" \
		"$(SCRIPT_INSTALL_DIR)\encoding\"
!endif
# "emacs font-lock highlighting fix

install-tzdata:
!if !$(TCL_EMBED_SCRIPTS)
	@echo Installing time zone data
	@set TCL_LIBRARY=$(ROOT:\=/)/library
	@$(TCLSH_NATIVE) "$(ROOT:\=/)/tools/installData.tcl" \
	    "$(ROOT:\=/)/library/tzdata" "$(SCRIPT_INSTALL_DIR)/tzdata"
!endif

install-msgs:
!if !$(TCL_EMBED_SCRIPTS)
	@echo Installing message catalogs
	@set TCL_LIBRARY=$(ROOT:\=/)/library
	@$(TCLSH_NATIVE) "$(ROOT:\=/)/tools/installData.tcl" \
	    "$(ROOT:\=/)/library/msgs" "$(SCRIPT_INSTALL_DIR)/msgs"
!endif

install-pdbs:
	@echo Installing debug symbols
	@$(CPY) "$(OUT_DIR)\*.pdb" "$(BIN_INSTALL_DIR)\"
# "emacs font-lock highlighting fix

#---------------------------------------------------------------------
1012
1013
1014
1015
1016
1017
1018
1019

1020

1021
1022
1023
1024
1176
1177
1178
1179
1180
1181
1182

1183
1184
1185
1186
1187
1188
1189







-
+

+




	@if exist $(TCLTEST) del $(TCLTEST)
	@echo Removing $(TCLDDELIB) ...
	@if exist $(TCLDDELIB) del $(TCLDDELIB)
	@echo Removing $(TCLREGLIB) ...
	@if exist $(TCLREGLIB) del $(TCLREGLIB)

clean: default-clean clean-pkgs
hose: default-hose
hose: default-hose hose-pkgs
realclean: hose
.PHONY:

# Local Variables:
# mode: makefile
# End:

Changes to win/nmakehlp.c.

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
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
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
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






-
-
+
+








+


+

-











-
+







-
+
















-
-
+
+







/*
 * ----------------------------------------------------------------------------
 * nmakehlp.c --
 *
 *	This is used to fix limitations within nmake and the environment.
 *
 * Copyright (c) 2002 by David Gravereaux.
 * Copyright (c) 2006 by Pat Thoyts
 * Copyright (c) 2002 David Gravereaux.
 * Copyright (c) 2006 Pat Thoyts
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * ----------------------------------------------------------------------------
 */

#define _CRT_SECURE_NO_DEPRECATE
#include <windows.h>
#ifdef _MSC_VER
#pragma comment (lib, "user32.lib")
#pragma comment (lib, "kernel32.lib")
#endif
#include <stdio.h>
#include <math.h>

/*
 * This library is required for x64 builds with _some_ versions of MSVC
 */
#if defined(_M_IA64) || defined(_M_AMD64)
#if _MSC_VER >= 1400 && _MSC_VER < 1500
#pragma comment(lib, "bufferoverflowU")
#endif
#endif

/* ISO hack for dumb VC++ */
#ifdef _MSC_VER
#if defined(_WIN32) && defined(_MSC_VER) && _MSC_VER < 1900
#define   snprintf	_snprintf
#endif


/* protos */

static int CheckForCompilerFeature(const char *option);
static int CheckForLinkerFeature(const char **options, int count);
static int CheckForLinkerFeature(char **options, int count);
static int IsIn(const char *string, const char *substring);
static int SubstituteFile(const char *substs, const char *filename);
static int QualifyPath(const char *path);
static int LocateDependency(const char *keyfile);
static const char *GetVersionFromFile(const char *filename, const char *match, int numdots);
static DWORD WINAPI ReadFromPipe(LPVOID args);

/* globals */

#define CHUNK	25
#define STATICBUFFERSIZE    1000
typedef struct {
    HANDLE pipe;
    char buffer[STATICBUFFERSIZE];
} pipeinfo;

pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'};
pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'};
pipeinfo Out = {INVALID_HANDLE_VALUE, ""};
pipeinfo Err = {INVALID_HANDLE_VALUE, ""};

/*
 * exitcodes: 0 == no, 1 == yes, 2 == error
 */

int
main(
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
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







-
+










-
+







    SetEnvironmentVariable("LINK", "");

    if (argc > 1 && *argv[1] == '-') {
	switch (*(argv[1]+1)) {
	case 'c':
	    if (argc != 3) {
		chars = snprintf(msg, sizeof(msg) - 1,
		        "usage: %s -c <compiler option>\n"
			"usage: %s -c <compiler option>\n"
			"Tests for whether cl.exe supports an option\n"
			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
			&dwWritten, NULL);
		return 2;
	    }
	    return CheckForCompilerFeature(argv[2]);
	case 'l':
	    if (argc < 3) {
		chars = snprintf(msg, sizeof(msg) - 1,
	       		"usage: %s -l <linker option> ?<mandatory option> ...?\n"
			"usage: %s -l <linker option> ?<mandatory option> ...?\n"
			"Tests for whether link.exe supports an option\n"
			"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
		WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
			&dwWritten, NULL);
		return 2;
	    }
	    return CheckForLinkerFeature(&argv[2], argc-2);
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
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







-
-
+
+




-
+





-
+





-
+







    char msg[300];
    BOOL ok;
    HANDLE hProcess, h, pipeThreads[2];
    char cmdline[100];

    hProcess = GetCurrentProcess();

    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    ZeroMemory(&si, sizeof(STARTUPINFO));
    memset(&pi, 0, sizeof(PROCESS_INFORMATION));
    memset(&si, 0, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags   = STARTF_USESTDHANDLES;
    si.hStdInput = INVALID_HANDLE_VALUE;

    ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
    memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = FALSE;

    /*
     * Create a non-inheritible pipe.
     * Create a non-inheritable pipe.
     */

    CreatePipe(&Out.pipe, &h, &sa, 0);

    /*
     * Dupe the write side, make it inheritible, and close the original.
     * Dupe the write side, make it inheritable, and close the original.
     */

    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
	    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);

    /*
     * Same as above, but for the error side.
269
270
271
272
273
274
275
276

277
278
279
280
281
282
283
270
271
272
273
274
275
276

277
278
279
280
281
282
283
284







-
+








    if (!ok) {
	DWORD err = GetLastError();
	int chars = snprintf(msg, sizeof(msg) - 1,
		"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);

	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPSTR)&msg[chars],
		(300-chars), 0);
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
	return 2;
    }

    /*
     * Close our references to the write handles that have now been inherited.
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
366
367
368
369
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
366
367
368
369
370







-
-
-
-
-
+
+
+
+
+




-
+














-
-
+
+




-
+











-
+








    /*
     * Look for the commandline warning code in both streams.
     *  - in MSVC 6 & 7 we get D4002, in MSVC 8 we get D9002.
     */

    return !(strstr(Out.buffer, "D4002") != NULL
             || strstr(Err.buffer, "D4002") != NULL
             || strstr(Out.buffer, "D9002") != NULL
             || strstr(Err.buffer, "D9002") != NULL
             || strstr(Out.buffer, "D2021") != NULL
             || strstr(Err.buffer, "D2021") != NULL);
	    || strstr(Err.buffer, "D4002") != NULL
	    || strstr(Out.buffer, "D9002") != NULL
	    || strstr(Err.buffer, "D9002") != NULL
	    || strstr(Out.buffer, "D2021") != NULL
	    || strstr(Err.buffer, "D2021") != NULL);
}

static int
CheckForLinkerFeature(
    const char **options,
    char **options,
    int count)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    DWORD threadID;
    char msg[300];
    BOOL ok;
    HANDLE hProcess, h, pipeThreads[2];
    int i;
    char cmdline[255];

    hProcess = GetCurrentProcess();

    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    ZeroMemory(&si, sizeof(STARTUPINFO));
    memset(&pi, 0, sizeof(PROCESS_INFORMATION));
    memset(&si, 0, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags   = STARTF_USESTDHANDLES;
    si.hStdInput = INVALID_HANDLE_VALUE;

    ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
    memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;

    /*
     * Create a non-inheritible pipe.
     */

    CreatePipe(&Out.pipe, &h, &sa, 0);

    /*
     * Dupe the write side, make it inheritible, and close the original.
     * Dupe the write side, make it inheritable, and close the original.
     */

    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
	    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);

    /*
     * Same as above, but for the error side.
403
404
405
406
407
408
409
410

411
412
413
414
415
416
417
404
405
406
407
408
409
410

411
412
413
414
415
416
417
418







-
+








    if (!ok) {
	DWORD err = GetLastError();
	int chars = snprintf(msg, sizeof(msg) - 1,
		"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);

	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPSTR)&msg[chars],
		(300-chars), 0);
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
	return 2;
    }

    /*
     * Close our references to the write handles that have now been inherited.
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
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







-
-
-
+
+
+








-









-
+









-
+








-
-
+
+



-
-
-
+
+







    const char *substring)
{
    return (strstr(string, substring) != NULL);
}

/*
 * GetVersionFromFile --
 * 	Looks for a match string in a file and then returns the version
 * 	following the match where a version is anything acceptable to
 * 	package provide or package ifneeded.
 *	Looks for a match string in a file and then returns the version
 *	following the match where a version is anything acceptable to
 *	package provide or package ifneeded.
 */

static const char *
GetVersionFromFile(
    const char *filename,
    const char *match,
    int numdots)
{
    size_t cbBuffer = 100;
    static char szBuffer[100];
    char *szResult = NULL;
    FILE *fp = fopen(filename, "rt");

    if (fp != NULL) {
	/*
	 * Read data until we see our match string.
	 */

	while (fgets(szBuffer, cbBuffer, fp) != NULL) {
	while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {
	    LPSTR p, q;

	    p = strstr(szBuffer, match);
	    if (p != NULL) {
		/*
		 * Skip to first digit after the match.
		 */

		p += strlen(match);
		while (*p && !isdigit(*p)) {
		while (*p && !isdigit((unsigned char)*p)) {
		    ++p;
		}

		/*
		 * Find ending whitespace.
		 */

		q = p;
		while (*q && (strchr("0123456789.ab", *q)) && ((!strchr(".ab", *q)
			    && (!strchr("ab", q[-1])) || --numdots))) {
		while (*q && (strchr("0123456789.ab", *q)) && (((!strchr(".ab", *q)
			    && !strchr("ab", q[-1])) || --numdots))) {
		    ++q;
		}

		memcpy(szBuffer, p, q - p);
		szBuffer[q-p] = 0;
		szResult = szBuffer;
		*q = 0;
		szResult = p;
		break;
	    }
	}
	fclose(fp);
    }
    return szResult;
}
558
559
560
561
562
563
564
565

566
567
568
569
570
571
572
557
558
559
560
561
562
563

564
565
566
567
568
569
570
571







-
+







    char * value;
} list_item_t;

/* insert a list item into the list (list may be null) */
static list_item_t *
list_insert(list_item_t **listPtrPtr, const char *key, const char *value)
{
    list_item_t *itemPtr = malloc(sizeof(list_item_t));
    list_item_t *itemPtr = (list_item_t *)malloc(sizeof(list_item_t));
    if (itemPtr) {
	itemPtr->key = strdup(key);
	itemPtr->value = strdup(value);
	itemPtr->nextPtr = NULL;

	while(*listPtrPtr) {
	    listPtrPtr = &(*listPtrPtr)->nextPtr;
589
590
591
592
593
594
595
596

597
598
599
600
601
602
603
604
605
606



607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624

625
626
627
628
629

630
631
632
633
634
635
636
588
589
590
591
592
593
594

595
596
597
598
599
600
601
602



603
604
605
606
607
608
609
610
611
612

613

614
615
616
617
618
619
620

621
622
623
624
625

626
627
628
629
630
631
632
633







-
+







-
-
-
+
+
+







-

-







-
+




-
+







    }
}

/*
 * SubstituteFile --
 *	As windows doesn't provide anything useful like sed and it's unreliable
 *	to use the tclsh you are building against (consider x-platform builds -
 *	eg compiling AMD64 target from IX86) we provide a simple substitution
 *	e.g. compiling AMD64 target from IX86) we provide a simple substitution
 *	option here to handle autoconf style substitutions.
 *	The substitution file is whitespace and line delimited. The file should
 *	consist of lines matching the regular expression:
 *	  \s*\S+\s+\S*$
 *
 *	Usage is something like:
 *	  nmakehlp -S << $** > $@
 *        @PACKAGE_NAME@ $(PACKAGE_NAME)
 *        @PACKAGE_VERSION@ $(PACKAGE_VERSION)
 *        <<
 *	    @PACKAGE_NAME@ $(PACKAGE_NAME)
 *	    @PACKAGE_VERSION@ $(PACKAGE_VERSION)
 *	    <<
 */

static int
SubstituteFile(
    const char *substitutions,
    const char *filename)
{
    size_t cbBuffer = 1024;
    static char szBuffer[1024], szCopy[1024];
    char *szResult = NULL;
    list_item_t *substPtr = NULL;
    FILE *fp, *sp;

    fp = fopen(filename, "rt");
    if (fp != NULL) {

	/*
	 * Build a list of substutitions from the first filename
	 * Build a list of substitutions from the first filename
	 */

	sp = fopen(substitutions, "rt");
	if (sp != NULL) {
	    while (fgets(szBuffer, cbBuffer, sp) != NULL) {
	    while (fgets(szBuffer, sizeof(szBuffer), sp) != NULL) {
		unsigned char *ks, *ke, *vs, *ve;
		ks = (unsigned char*)szBuffer;
		while (ks && *ks && isspace(*ks)) ++ks;
		ke = ks;
		while (ke && *ke && !isspace(*ke)) ++ke;
		vs = ke;
		while (vs && *vs && isspace(*vs)) ++vs;
653
654
655
656
657
658
659
660

661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677

678
679
680
681
682
683
684
650
651
652
653
654
655
656

657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673

674
675
676
677
678
679
680
681







-
+
















-
+







	}
#endif

	/*
	 * Run the substitutions over each line of the input
	 */

	while (fgets(szBuffer, cbBuffer, fp) != NULL) {
	while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {
	    list_item_t *p = NULL;
	    for (p = substPtr; p != NULL; p = p->nextPtr) {
		char *m = strstr(szBuffer, p->key);
		if (m) {
		    char *cp, *op, *sp;
		    cp = szCopy;
		    op = szBuffer;
		    while (op != m) *cp++ = *op++;
		    sp = p->value;
		    while (sp && *sp) *cp++ = *sp++;
		    op += strlen(p->key);
		    while (*op) *cp++ = *op++;
		    *cp = 0;
		    memcpy(szBuffer, szCopy, sizeof(szCopy));
		}
	    }
	    printf(szBuffer);
	    printf("%s", szBuffer);
	}

	list_free(&substPtr);
    }
    fclose(fp);
    return 0;
}
721
722
723
724
725
726
727

728

729
730
731

732

733
734

735

736
737
738
739
740
741
742
743
744
745
746
747
748
749
750

751

752
753
754
755
756
757
758
759
760
761

762

763
764

765

766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786


787
788
789
790
791




792
793
794

795

796
797
798
799
800

801

802
803
804
805
806
807
808
718
719
720
721
722
723
724
725

726
727
728

729
730
731
732

733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749

750
751
752
753
754
755
756
757
758
759
760
761

762
763
764
765

766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787


788
789
790




791
792
793
794
795
796
797
798

799
800
801
802
803

804
805
806
807
808
809
810
811
812
813







+
-
+


-
+

+

-
+

+














-
+

+









-
+

+

-
+

+



















-
-
+
+

-
-
-
-
+
+
+
+



+
-
+




-
+

+







 * Returns 2 on any kind of error
 * Basically, these are used as exit codes for the process.
 */
static int LocateDependencyHelper(const char *dir, const char *keypath)
{
    HANDLE hSearch;
    char path[MAX_PATH+1];
    size_t dirlen;
    int dirlen, keylen, ret;
    int keylen, ret;
    WIN32_FIND_DATA finfo;

    if (dir == NULL || keypath == NULL)
    if (dir == NULL || keypath == NULL) {
	return 2; /* Have no real error reporting mechanism into nmake */
    }
    dirlen = strlen(dir);
    if ((dirlen + 3) > sizeof(path))
    if (dirlen > sizeof(path) - 3) {
	return 2;
    }
    strncpy(path, dir, dirlen);
    strncpy(path+dirlen, "\\*", 3);	/* Including terminating \0 */
    keylen = strlen(keypath);

#if 0 /* This function is not available in Visual C++ 6 */
    /*
     * Use numerics 0 -> FindExInfoStandard,
     * 1 -> FindExSearchLimitToDirectories,
     * as these are not defined in Visual C++ 6
     */
    hSearch = FindFirstFileEx(path, 0, &finfo, 1, NULL, 0);
#else
    hSearch = FindFirstFile(path, &finfo);
#endif
    if (hSearch == INVALID_HANDLE_VALUE)
    if (hSearch == INVALID_HANDLE_VALUE) {
	return 1; /* Not found */
    }

    /* Loop through all subdirs checking if the keypath is under there */
    ret = 1; /* Assume not found */
    do {
	int sublen;
	/*
	 * We need to check it is a directory despite the
	 * FindExSearchLimitToDirectories in the above call. See SDK docs
	 */
	if ((finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
	if ((finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
	    continue;
	}
	sublen = strlen(finfo.cFileName);
	if ((dirlen+1+sublen+1+keylen+1) > sizeof(path))
	if ((dirlen+1+sublen+1+keylen+1) > sizeof(path)) {
	    continue;		/* Path does not fit, assume not matched */
	}
	strncpy(path+dirlen+1, finfo.cFileName, sublen);
	path[dirlen+1+sublen] = '\\';
	strncpy(path+dirlen+1+sublen+1, keypath, keylen+1);
	if (FileExists(path)) {
	    /* Found a match, print to stdout */
	    path[dirlen+1+sublen] = '\0';
	    QualifyPath(path);
	    ret = 0;
	    break;
	}
    } while (FindNextFile(hSearch, &finfo));
    FindClose(hSearch);
    return ret;
}

/*
 * LocateDependency --
 *
 *	Locates a dependency for a package.
 *        keypath - a relative path within the package directory
 *          that is used to confirm it is the correct directory.
 *	    keypath - a relative path within the package directory
 *	      that is used to confirm it is the correct directory.
 *	The search path for the package directory is currently only
 *      the parent and grandparent of the current working directory.
 *      If found, the command prints
 *         name_DIRPATH=<full path of located directory>
 *      and returns 0. If not found, does not print anything and returns 1.
 *	    the parent and grandparent of the current working directory.
 *	    If found, the command prints
 *	      name_DIRPATH=<full path of located directory>
 *	    and returns 0. If not found, does not print anything and returns 1.
 */
static int LocateDependency(const char *keypath)
{
    size_t i;
    int i, ret;
    int ret;
    static const char *paths[] = {"..", "..\\..", "..\\..\\.."};

    for (i = 0; i < (sizeof(paths)/sizeof(paths[0])); ++i) {
	ret = LocateDependencyHelper(paths[i], keypath);
	if (ret == 0)
	if (ret == 0) {
	    return ret;
	}
    }
    return ret;
}


/*
 * Local variables:

Changes to win/rules-ext.vc.

27
28
29
30
31
32
33

34





35
36
37
38
39
40
41
27
28
29
30
31
32
33
34

35
36
37
38
39
40
41
42
43
44
45
46







+
-
+
+
+
+
+







!if "$(PROJECT)" == "tcl"
!error The rules-ext.vc file is not intended for Tcl itself.
!endif

# We extract version numbers using the nmakehlp program. For now use
# the local copy of nmakehlp. Once we locate Tcl, we will use that
# one if it is newer.
!if "$(MACHINE)" == "IX86" || "$(MACHINE)" == "$(NATIVE_ARCH)"
!if [$(CC) -nologo "nmakehlp.c" -link -subsystem:console > nul]
!if [$(CC) -nologo -DNDEBUG "nmakehlp.c" -link -subsystem:console > nul]
!endif
!else
!if [copy x86_64-w64-mingw32-nmakehlp.exe nmakehlp.exe >NUL]
!endif
!endif

# First locate the Tcl directory that we are working with.
!if "$(TCLDIR)" != ""

_RULESDIR = $(TCLDIR:/=\)

Changes to win/rules.vc.

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
30
31
32
33
34
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
30
31
32
33
34








-
+

















-
+







#------------------------------------------------------------- -*- makefile -*-
# rules.vc --
#
# Part of the nmake based build system for Tcl and its extensions.
# This file does all the hard work in terms of parsing build options,
# compiler switches, defining common targets and macros. The Tcl makefile
# directly includes this. Extensions include it via "rules-ext.vc".
#
# See TIP 477 (https://core.tcl-lang.org/tips/doc/trunk/tip/477.md) for
# See TIP 477 (https://core.tcl-lang.org/tips/doc/main/tip/477.md) for
# detailed documentation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# Copyright (c) 2001-2003 David Gravereaux.
# Copyright (c) 2003-2008 Patrick Thoyts
# Copyright (c) 2017      Ashok P. Nadkarni
#------------------------------------------------------------------------------

!ifndef _RULES_VC
_RULES_VC = 1

# The following macros define the version of the rules.vc nmake build system
# For modifications that are not backward-compatible, you *must* change
# the major version.
RULES_VERSION_MAJOR = 1
RULES_VERSION_MINOR = 6
RULES_VERSION_MINOR = 13

# The PROJECT macro must be defined by parent makefile.
!if "$(PROJECT)" == ""
!error *** Error: Macro PROJECT not defined! Please define it before including rules.vc
!endif

!if "$(PRJ_PACKAGE_TCLNAME)" == ""
75
76
77
78
79
80
81


82
83
84



85
86
87
88
89
90
91
92
75
76
77
78
79
80
81
82
83



84
85
86

87
88
89
90
91
92
93







+
+
-
-
-
+
+
+
-







# 1. First define the external tools used for compiling, copying etc.
#    as this is independent of everything else.
# 2. Figure out our build structure in terms of the directory, whether
#    we are building Tcl or an extension, etc.
# 3. Determine the compiler and linker versions
# 4. Build the nmakehlp helper application
# 5. Determine the supported compiler options and features
# 6. Extract Tcl, Tk, and possibly extensions, version numbers from the
#    headers
# 6. Parse the OPTS macro value for user-specified build configuration
# 7. Parse the STATS macro value for statistics instrumentation
# 8. Parse the CHECKS macro for additional compilation checks
# 7. Parse the OPTS macro value for user-specified build configuration
# 8. Parse the STATS macro value for statistics instrumentation
# 9. Parse the CHECKS macro for additional compilation checks
# 9. Extract Tcl, and possibly Tk, version numbers from the headers
# 10. Based on this selected configuration, construct the output
#     directory and file paths
# 11. Construct the paths where the package is to be installed
# 12. Set up the actual options passed to compiler and linker based
#     on the information gathered above.
# 13. Define some standard build targets and implicit rules. These may
#     be optionally disabled by the parent makefile.
407
408
409
410
411
412
413
414
415


416
417
418
419
420
421
422
408
409
410
411
412
413
414


415
416
417
418
419
420
421
422
423







-
-
+
+







# following macros:
# VCVERSION - the internal compiler version as 1200, 1400, 1910 etc.
#     This is also printed by the compiler in dotted form 19.10 etc.
# VCVER - the "marketing version", for example Visual C++ 6 for internal
#     compiler version 1200. This is kept only for legacy reasons as it
#     does not make sense for recent Microsoft compilers. Only used for
#     output directory names.
# ARCH - set to IX86 or AMD64 depending on 32- or 64-bit target
# NATIVE_ARCH - set to IX86 or AMD64 for the host machine
# ARCH - set to IX86, ARM64 or AMD64 depending on 32- or 64-bit target
# NATIVE_ARCH - set to IX86, ARM64 or AMD64 for the host machine
# MACHINE - same as $(ARCH) - legacy
# _VC_MANIFEST_EMBED_{DLL,EXE} - commands for embedding a manifest if needed

cc32		= $(CC)   # built-in default.
link32		= link
lib32		= lib
rc32		= $(RC)   # built-in default.
431
432
433
434
435
436
437


438
439
440
441
442
443
444
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447







+
+







_VC_MANIFEST_EMBED_DLL=
VCVER=0
!if ![echo VCVERSION=_MSC_VER > vercl.x] \
    && ![echo $(_HASH)if defined(_M_IX86) >> vercl.x] \
    && ![echo ARCH=IX86 >> vercl.x] \
    && ![echo $(_HASH)elif defined(_M_AMD64) >> vercl.x] \
    && ![echo ARCH=AMD64 >> vercl.x] \
    && ![echo $(_HASH)elif defined(_M_ARM64) >> vercl.x] \
    && ![echo ARCH=ARM64 >> vercl.x] \
    && ![echo $(_HASH)endif >> vercl.x] \
    && ![$(cc32) -nologo -TC -P vercl.x 2>NUL]
!include vercl.i
!if $(VCVERSION) < 1900
!if ![echo VCVER= ^\> vercl.vc] \
    && ![set /a $(VCVERSION) / 100 - 6 >> vercl.vc]
!include vercl.vc
455
456
457
458
459
460
461



462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477


478
479
480
481
482
483
484
485
486
487
488
489
490
491
492


493
494
495
496
497
498
499
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
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







+
+
+
















+
+















+
+








#----------------------------------------------------------------
# The MACHINE macro is used by legacy makefiles so set it as well
!ifdef MACHINE
!if "$(MACHINE)" == "x86"
!undef MACHINE
MACHINE = IX86
!elseif "$(MACHINE)" == "arm64"
!undef MACHINE
MACHINE = ARM64
!elseif "$(MACHINE)" == "x64"
!undef MACHINE
MACHINE = AMD64
!endif
!if "$(MACHINE)" != "$(ARCH)"
!error Specified MACHINE macro $(MACHINE) does not match detected target architecture $(ARCH).
!endif
!else
MACHINE=$(ARCH)
!endif

#---------------------------------------------------------------
# The PLATFORM_IDENTIFY macro matches the values returned by
# the Tcl platform::identify command
!if "$(MACHINE)" == "AMD64"
PLATFORM_IDENTIFY = win32-x86_64
!elseif "$(MACHINE)" == "ARM64"
PLATFORM_IDENTIFY = win32-arm
!else
PLATFORM_IDENTIFY = win32-ix86
!endif

# The MULTIPLATFORM macro controls whether binary extensions are installed
# in platform-specific directories. Intended to be set/used by extensions.
!ifndef MULTIPLATFORM_INSTALL
MULTIPLATFORM_INSTALL = 0
!endif

#------------------------------------------------------------
# Figure out the *host* architecture by reading the registry

!if ![reg query HKLM\Hardware\Description\System\CentralProcessor\0 /v Identifier | findstr /i x86]
NATIVE_ARCH=IX86
!elseif ![reg query HKLM\Hardware\Description\System\CentralProcessor\0 /v Identifier | findstr /i ARM | findstr /i 64-bit]
NATIVE_ARCH=ARM64
!else
NATIVE_ARCH=AMD64
!endif

# Since MSVC8 we must deal with manifest resources.
!if $(VCVERSION) >= 1400
_VC_MANIFEST_EMBED_EXE=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;1
537
538
539
540
541
542
543

544
545




546
547
548
549
550
551
552
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567







+


+
+
+
+







!endif # $(TCLINSTALL)
!endif # !$(DOING_TCL)

!endif # NMAKEHLPC

# We always build nmakehlp even if it exists since we do not know
# what source it was built from.
!if "$(MACHINE)" == "IX86" || "$(MACHINE)" == "$(NATIVE_ARCH)"
!if [$(cc32) -nologo "$(NMAKEHLPC)" -link -subsystem:console > nul]
!endif
!else
!if [copy $(NMAKEHLPC:nmakehlp.c=x86_64-w64-mingw32-nmakehlp.exe) nmakehlp.exe >NUL]
!endif
!endif

################################################################
# 5. Test for compiler features
# Visual C++ compiler options have changed over the years. Check
# which options are supported by the compiler in use.
#
# The following macros are set:
648
649
650
651
652
653
654


























































































































655
656

657
658
659
660
661
662
663
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
663
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
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792

793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808


809
810
811
812
813
814
815
816
817
818
819


820
821
822
823
824
825
826







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+













+

-
-
+
+









-
-







# If compiler has enabled link time optimization, linker must too with -ltcg
!ifdef CC_GL_OPT_ENABLED
!if [nmakehlp -l -ltcg $(LINKER_TESTFLAGS)]
LINKERFLAGS     = $(LINKERFLAGS) -ltcg
!endif
!endif


################################################################
# 6. Extract various version numbers from headers
# For Tcl and Tk, version numbers are extracted from tcl.h and tk.h
# respectively. For extensions, versions are extracted from the
# configure.in or configure.ac from the TEA configuration if it
# exists, and unset otherwise.
# Sets the following macros:
# TCL_MAJOR_VERSION
# TCL_MINOR_VERSION
# TCL_RELEASE_SERIAL
# TCL_PATCH_LEVEL
# TCL_PATCH_LETTER
# TCL_VERSION
# TK_MAJOR_VERSION
# TK_MINOR_VERSION
# TK_RELEASE_SERIAL
# TK_PATCH_LEVEL
# TK_PATCH_LETTER
# TK_VERSION
# DOTVERSION - set as (for example) 2.5
# VERSION - set as (for example 25)
#--------------------------------------------------------------

!if [echo REM = This file is generated from rules.vc > versions.vc]
!endif
!if [echo TCL_MAJOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V "$(_TCL_H)" "define TCL_MAJOR_VERSION" >> versions.vc]
!endif
!if [echo TCL_MINOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V "$(_TCL_H)" TCL_MINOR_VERSION >> versions.vc]
!endif
!if [echo TCL_RELEASE_SERIAL = \>> versions.vc] \
   && [nmakehlp -V "$(_TCL_H)" TCL_RELEASE_SERIAL >> versions.vc]
!endif
!if [echo TCL_PATCH_LEVEL = \>> versions.vc] \
   && [nmakehlp -V "$(_TCL_H)" TCL_PATCH_LEVEL >> versions.vc]
!endif

!if defined(_TK_H)
!if [echo TK_MAJOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V $(_TK_H) "define TK_MAJOR_VERSION" >> versions.vc]
!endif
!if [echo TK_MINOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V $(_TK_H) TK_MINOR_VERSION >> versions.vc]
!endif
!if [echo TK_RELEASE_SERIAL = \>> versions.vc] \
   && [nmakehlp -V "$(_TK_H)" TK_RELEASE_SERIAL >> versions.vc]
!endif
!if [echo TK_PATCH_LEVEL = \>> versions.vc] \
   && [nmakehlp -V $(_TK_H) TK_PATCH_LEVEL >> versions.vc]
!endif
!endif # _TK_H

!include versions.vc

TCL_VERSION	= $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION)
TCL_DOTVERSION	= $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)
!if [nmakehlp -f $(TCL_PATCH_LEVEL) "a"]
TCL_PATCH_LETTER = a
!elseif [nmakehlp -f $(TCL_PATCH_LEVEL) "b"]
TCL_PATCH_LETTER = b
!else
TCL_PATCH_LETTER = .
!endif

!if defined(_TK_H)

TK_VERSION	= $(TK_MAJOR_VERSION)$(TK_MINOR_VERSION)
TK_DOTVERSION	= $(TK_MAJOR_VERSION).$(TK_MINOR_VERSION)
!if [nmakehlp -f $(TK_PATCH_LEVEL) "a"]
TK_PATCH_LETTER = a
!elseif [nmakehlp -f $(TK_PATCH_LEVEL) "b"]
TK_PATCH_LETTER = b
!else
TK_PATCH_LETTER = .
!endif

!endif

# Set DOTVERSION and VERSION
!if $(DOING_TCL)

DOTVERSION = $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)
VERSION = $(TCL_VERSION)

!elseif $(DOING_TK)

DOTVERSION = $(TK_DOTVERSION)
VERSION = $(TK_VERSION)

!else # Doing a non-Tk extension

# If parent makefile has not defined DOTVERSION, try to get it from TEA
# first from a configure.in file, and then from configure.ac
!ifndef DOTVERSION
!if [echo DOTVERSION = \> versions.vc] \
   || [nmakehlp -V $(ROOT)\configure.in ^[$(PROJECT)^] >> versions.vc]
!if [echo DOTVERSION = \> versions.vc] \
   || [nmakehlp -V $(ROOT)\configure.ac ^[$(PROJECT)^] >> versions.vc]
!error *** Could not figure out extension version. Please define DOTVERSION in parent makefile before including rules.vc.
!endif
!endif
!include versions.vc
!endif # DOTVERSION
VERSION         = $(DOTVERSION:.=)

!endif # $(DOING_TCL) ... etc.

# Windows RC files have 3 version components. Ensure this irrespective
# of how many components the package has specified. Basically, ensure
# minimum 4 components by appending 4 0's and then pick out the first 4.
# Also take care of the fact that DOTVERSION may have "a" or "b" instead
# of "." separating the version components.
DOTSEPARATED=$(DOTVERSION:a=.)
DOTSEPARATED=$(DOTSEPARATED:b=.)
!if [echo RCCOMMAVERSION = \> versions.vc] \
  || [for /f "tokens=1,2,3,4,5* delims=." %a in ("$(DOTSEPARATED).0.0.0.0") do echo %a,%b,%c,%d >> versions.vc]
!error *** Could not generate RCCOMMAVERSION ***
!endif
!include versions.vc

########################################################################
# 6. Parse the OPTS macro to work out the requested build configuration.
# 7. Parse the OPTS macro to work out the requested build configuration.
# Based on this, we will construct the actual switches to be passed to the
# compiler and linker using the macros defined in the previous section.
# The following macros are defined by this section based on OPTS
# STATIC_BUILD - 0 -> Tcl is to be built as a shared library
#                1 -> build as a static library and shell
# TCL_THREADS - legacy but always 1 on Windows since winsock requires it.
# 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 shell. 0 -> keep them as shared libraries
#           Does not impact shared Tcl builds.
#           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)
# _USE_64BIT_TIME_T - forces a build using 64-bit time_t for 32-bit build
#           (CRT library should support this, not needed for Tcl 9.x)
# TCL_UTF_MAX=4 - forces a build allowing 4-byte UTF-8 sequences internally.
#           (Not needed for Tcl 9.x)
# Further, LINKERFLAGS are modified based on above.

# Default values for all the above
STATIC_BUILD	= 0
TCL_THREADS	= 1
DEBUG		= 0
SYMBOLS		= 0
720
721
722
723
724
725
726
727

728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743









744

745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
856
857
858
859
860
861
862

863
864
865
866
867
868
869
870
871
872
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
898
899
900







-
+
















+
+
+
+
+
+
+
+
+
-
+




-
-
-
-
-







!if [nmakehlp -f $(OPTS) "nomsvcrt"]
!message *** Doing nomsvcrt
MSVCRT		= 0
!else
!if [nmakehlp -f $(OPTS) "msvcrt"]
!message *** Doing msvcrt
!else
!if $(STATIC_BUILD)
!if $(TCL_MAJOR_VERSION) == 8 && $(TCL_MINOR_VERSION) < 7 && $(STATIC_BUILD)
MSVCRT		= 0
!endif
!endif
!endif # [nmakehlp -f $(OPTS) "nomsvcrt"]

!if [nmakehlp -f $(OPTS) "staticpkg"] && $(STATIC_BUILD)
!message *** Doing staticpkg
TCL_USE_STATIC_PACKAGES	= 1
!endif

!if [nmakehlp -f $(OPTS) "nothreads"]
!message *** Compile explicitly for non-threaded tcl
TCL_THREADS = 0
USE_THREAD_ALLOC= 0
!endif

!if [nmakehlp -f $(OPTS) "tcl8"]
!message *** Build for Tcl8
TCL_BUILD_FOR = 8
!endif
!if [nmakehlp -f $(OPTS) "tk8"]
!message *** Build for Tk8
TK_BUILD_FOR = 8
!endif

!if "$(TCL_MAJOR_VERSION)" == "8"
!if $(TCL_MAJOR_VERSION) == 8
!if [nmakehlp -f $(OPTS) "time64bit"]
!message *** Force 64-bit time_t
_USE_64BIT_TIME_T = 1
!endif

!if [nmakehlp -f $(OPTS) "utfmax"]
!message *** Force allowing 4-byte UTF-8 sequences internally
TCL_UTF_MAX = 4
!endif
!endif

# Yes, it's weird that the "symbols" option controls DEBUG and
# the "pdbs" option controls SYMBOLS. That's historical.
!if [nmakehlp -f $(OPTS) "symbols"]
!message *** Doing symbols
DEBUG		= 1
832
833
834
835
836
837
838
839

840
841
842
843
844
845
846
972
973
974
975
976
977
978

979
980
981
982
983
984
985
986







-
+







MSG=^
This compiler does not support profile guided optimization.
!error $(MSG)
!endif
!endif

################################################################
# 7. Parse the STATS macro to configure code instrumentation
# 8. Parse the STATS macro to configure code instrumentation
# The following macros are set by this section:
# TCL_MEM_DEBUG - 1 -> enables memory allocation instrumentation
#                 0 -> disables
# TCL_COMPILE_DEBUG - 1 -> enables byte compiler logging
#                     0 -> disables

# Default both are off
862
863
864
865
866
867
868
869

870
871
872
873
874
875
876
1002
1003
1004
1005
1006
1007
1008

1009
1010
1011
1012
1013
1014
1015
1016







-
+







!else
TCL_COMPILE_DEBUG   = 0
!endif

!endif

####################################################################
# 8. Parse the CHECKS macro to configure additional compiler checks
# 9. Parse the CHECKS macro to configure additional compiler checks
# The following macros are set by this section:
# WARNINGS - compiler switches that control the warnings level
# TCL_NO_DEPRECATED - 1 -> disable support for deprecated functions
#                     0 -> enable deprecated functions

# Defaults - Permit deprecated functions and warning level 3
TCL_NO_DEPRECATED	    = 0
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
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
1034
1035
1036
1037
1038
1039
1040





























































































1041
1042
1043
1044
1045
1046
1047







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







!if [nmakehlp -f $(CHECKS) "64bit"] && [nmakehlp -c -Wp64]
!message *** Doing 64bit portability warnings
WARNINGS		    = $(WARNINGS) -Wp64
!endif

!endif

################################################################
# 9. Extract various version numbers
# For Tcl and Tk, version numbers are extracted from tcl.h and tk.h
# respectively. For extensions, versions are extracted from the
# configure.in or configure.ac from the TEA configuration if it
# exists, and unset otherwise.
# Sets the following macros:
# TCL_MAJOR_VERSION
# TCL_MINOR_VERSION
# TCL_PATCH_LEVEL
# TCL_VERSION
# TK_MAJOR_VERSION
# TK_MINOR_VERSION
# TK_PATCH_LEVEL
# TK_VERSION
# DOTVERSION - set as (for example) 2.5
# VERSION - set as (for example 25)
#--------------------------------------------------------------

!if [echo REM = This file is generated from rules.vc > versions.vc]
!endif
!if [echo TCL_MAJOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V "$(_TCL_H)" TCL_MAJOR_VERSION >> versions.vc]
!endif
!if [echo TCL_MINOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V "$(_TCL_H)" TCL_MINOR_VERSION >> versions.vc]
!endif
!if [echo TCL_PATCH_LEVEL = \>> versions.vc] \
   && [nmakehlp -V "$(_TCL_H)" TCL_PATCH_LEVEL >> versions.vc]
!endif

!if defined(_TK_H)
!if [echo TK_MAJOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V $(_TK_H) TK_MAJOR_VERSION >> versions.vc]
!endif
!if [echo TK_MINOR_VERSION = \>> versions.vc] \
   && [nmakehlp -V $(_TK_H) TK_MINOR_VERSION >> versions.vc]
!endif
!if [echo TK_PATCH_LEVEL = \>> versions.vc] \
   && [nmakehlp -V $(_TK_H) TK_PATCH_LEVEL >> versions.vc]
!endif
!endif # _TK_H

!include versions.vc

TCL_VERSION	= $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION)
TCL_DOTVERSION	= $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)
!if defined(_TK_H)
TK_VERSION	= $(TK_MAJOR_VERSION)$(TK_MINOR_VERSION)
TK_DOTVERSION	= $(TK_MAJOR_VERSION).$(TK_MINOR_VERSION)
!endif

# Set DOTVERSION and VERSION
!if $(DOING_TCL)

DOTVERSION = $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)
VERSION = $(TCL_VERSION)

!elseif $(DOING_TK)

DOTVERSION = $(TK_DOTVERSION)
VERSION = $(TK_VERSION)

!else # Doing a non-Tk extension

# If parent makefile has not defined DOTVERSION, try to get it from TEA
# first from a configure.in file, and then from configure.ac
!ifndef DOTVERSION
!if [echo DOTVERSION = \> versions.vc] \
   || [nmakehlp -V $(ROOT)\configure.in ^[$(PROJECT)^] >> versions.vc]
!if [echo DOTVERSION = \> versions.vc] \
   || [nmakehlp -V $(ROOT)\configure.ac ^[$(PROJECT)^] >> versions.vc]
!error *** Could not figure out extension version. Please define DOTVERSION in parent makefile before including rules.vc.
!endif
!endif
!include versions.vc
!endif # DOTVERSION
VERSION         = $(DOTVERSION:.=)

!endif # $(DOING_TCL) ... etc.

# Windows RC files have 3 version components. Ensure this irrespective
# of how many components the package has specified. Basically, ensure
# minimum 4 components by appending 4 0's and then pick out the first 4.
# Also take care of the fact that DOTVERSION may have "a" or "b" instead
# of "." separating the version components.
DOTSEPARATED=$(DOTVERSION:a=.)
DOTSEPARATED=$(DOTSEPARATED:b=.)
!if [echo RCCOMMAVERSION = \> versions.vc] \
  || [for /f "tokens=1,2,3,4,5* delims=." %a in ("$(DOTSEPARATED).0.0.0.0") do echo %a,%b,%c,%d >> versions.vc]
!error *** Could not generate RCCOMMAVERSION ***
!endif
!include versions.vc

################################################################
# 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.,
#
1047
1048
1049
1050
1051
1052
1053
1054

1055
1056
1057
1058
1059
1060
1061
1094
1095
1096
1097
1098
1099
1100

1101
1102
1103
1104
1105
1106
1107
1108







-
+







SUFX	    = $(SUFX:s=)
EXT	    = dll
TMP_DIRFULL = $(TMP_DIRFULL:X=)
SUFX	    = $(SUFX:x=)
!else
TMP_DIRFULL = $(TMP_DIRFULL:Dynamic=)
EXT	    = lib
!if !$(MSVCRT)
!if $(MSVCRT) && $(TCL_VERSION) > 86 || !$(MSVCRT) && $(TCL_VERSION) < 87
TMP_DIRFULL = $(TMP_DIRFULL:X=)
SUFX	    = $(SUFX:x=)
!endif
!endif

!if !$(TCL_THREADS) || $(TCL_VERSION) > 86
TMP_DIRFULL = $(TMP_DIRFULL:Threaded=)
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



1116
1117
1118
1119
1120
1121
1122
1123
1124

1125
1126
1127
1128
1129
1130
1131
1132
1133

1134



1135
1136
1137
1138
1139
1140
1141
1142
1143

1144
1145
1146
1147
1148



1149

1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167










1168

1169


1170
1171
1172

1173
1174
1175
1176


1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190


1191

1192
1193
1194
1195
1196
1197
1198
1199
1200
1201


1202

1203
1204
1205
1206
1207
1208
1209
1210








1211
1212

1213



1214
1215
1216
1217
1218
1219
1220
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139

1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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







+

+
-
+
+
+
+

+





+

+

+
+
+















+

+
+
+









+









+

+
+
+









+





+
+
+

+

















-
+
+
+
+
+
+
+
+
+
+

+
-
+
+


-
+



-
+
+














+
+

+










+
+

+







-
+
+
+
+
+
+
+
+


+

+
+
+







!error *** Could not fully qualify path TMP_DIR=$(TMP_DIR)
!endif
!include nmakehlp.out

# The name of the stubs library for the project being built
STUBPREFIX      = $(PROJECT)stub

#
# Set up paths to various Tcl executables and libraries needed by extensions
#
!if $(DOING_TCL)

# TIP 430. Unused for 8.6 but no harm defining it to allow a common rules.vc
TCL_ZIP_FILE = libtcl$(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)$(TCL_PATCH_LETTER)$(TCL_RELEASE_SERIAL).zip
TK_ZIP_FILE = libtk$(TK_MAJOR_VERSION).$(TK_MINOR_VERSION)$(TK_PATCH_LETTER)$(TK_RELEASE_SERIAL).zip

!if $(DOING_TCL)
TCLSHNAME       = $(PROJECT)sh$(VERSION)$(SUFX).exe
TCLSH		= $(OUT_DIR)\$(TCLSHNAME)
TCLIMPLIB	= $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib
TCLLIBNAME	= $(PROJECT)$(VERSION)$(SUFX).$(EXT)
TCLLIB		= $(OUT_DIR)\$(TCLLIBNAME)
TCLSCRIPTZIP    = $(OUT_DIR)\$(TCL_ZIP_FILE)

!if $(TCL_MAJOR_VERSION) == 8
TCLSTUBLIBNAME	= $(STUBPREFIX)$(VERSION).lib
!else
TCLSTUBLIBNAME	= $(STUBPREFIX).lib
!endif
TCLSTUBLIB	= $(OUT_DIR)\$(TCLSTUBLIBNAME)
TCL_INCLUDES    = -I"$(WIN_DIR)" -I"$(GENERICDIR)"

!else # !$(DOING_TCL)

!if $(TCLINSTALL) # Building against an installed Tcl

# When building extensions, we need to locate tclsh. Depending on version
# of Tcl we are building against, this may or may not have a "t" suffix.
# Try various possibilities in turn.
TCLSH		= $(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX:t=).exe
!if !exist("$(TCLSH)")
TCLSH           = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)t$(SUFX:t=).exe
!endif

!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)
TCLTOOLSDIR	= \must\have\tcl\sources\to\build\this\target
TCL_INCLUDES    = -I"$(_TCLDIR)\include"

!else # Building against Tcl sources

TCLSH		= $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX:t=).exe
!if !exist($(TCLSH))
TCLSH		= $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX:t=).exe
!endif
!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)
TCLTOOLSDIR	= $(_TCLDIR)\tools
TCL_INCLUDES	= -I"$(_TCLDIR)\generic" -I"$(_TCLDIR)\win"

!endif # TCLINSTALL

!if !$(STATIC_BUILD) && "$(TCL_BUILD_FOR)" == "8"
tcllibs = "$(TCLSTUBLIB)"
!else
tcllibs = "$(TCLSTUBLIB)" "$(TCLIMPLIB)"
!endif

!endif # $(DOING_TCL)

# We need a tclsh that will run on the host machine as part of the build.
# IX86 runs on all architectures.
!ifndef TCLSH_NATIVE
!if "$(MACHINE)" == "IX86" || "$(MACHINE)" == "$(NATIVE_ARCH)"
TCLSH_NATIVE	= $(TCLSH)
!else
!error You must explicitly set TCLSH_NATIVE for cross-compilation
!endif
!endif

# Do the same for Tk and Tk extensions that require the Tk libraries
!if $(DOING_TK) || $(NEED_TK)
WISHNAMEPREFIX = wish
WISHNAME = $(WISHNAMEPREFIX)$(TK_VERSION)$(SUFX).exe
TKLIBNAME	= $(PROJECT)$(TK_VERSION)$(SUFX).$(EXT)
TKLIBNAME8	= tk$(TK_VERSION)$(SUFX).$(EXT)
TKLIBNAME9	= tcl9tk$(TK_VERSION)$(SUFX).$(EXT)
!if $(TCL_MAJOR_VERSION) == 8 || "$(TCL_BUILD_FOR)" == "8"
TKLIBNAME	= tk$(TK_VERSION)$(SUFX).$(EXT)
TKIMPLIBNAME	= tk$(TK_VERSION)$(SUFX).lib
!else
TKLIBNAME	= tcl9tk$(TK_VERSION)$(SUFX).$(EXT)
TKIMPLIBNAME	= tcl9tk$(TK_VERSION)$(SUFX).lib
!endif
!if $(TK_MAJOR_VERSION) == 8
TKSTUBLIBNAME	= tkstub$(TK_VERSION).lib
!else
TKIMPLIBNAME	= tk$(TK_VERSION)$(SUFX).lib
TKSTUBLIBNAME	= tkstub.lib
!endif

!if $(DOING_TK)
WISH 		= $(OUT_DIR)\$(WISHNAME)
WISH		= $(OUT_DIR)\$(WISHNAME)
TKSTUBLIB	= $(OUT_DIR)\$(TKSTUBLIBNAME)
TKIMPLIB	= $(OUT_DIR)\$(TKIMPLIBNAME)
TKLIB		= $(OUT_DIR)\$(TKLIBNAME)
TK_INCLUDES    = -I"$(WIN_DIR)" -I"$(GENERICDIR)"
TK_INCLUDES     = -I"$(WIN_DIR)" -I"$(GENERICDIR)"
TKSCRIPTZIP     = $(OUT_DIR)\$(TK_ZIP_FILE)

!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)

!endif # TKINSTALL

tklibs = "$(TKSTUBLIB)" "$(TKIMPLIB)"

!endif # $(DOING_TK)
!endif # $(DOING_TK) || $(NEED_TK)

# Various output paths
PRJIMPLIB	= $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib
PRJLIBNAME	= $(PROJECT)$(VERSION)$(SUFX).$(EXT)
PRJLIBNAME8	= $(PROJECT)$(VERSION)$(SUFX).$(EXT)
# Even when building against Tcl 8, PRJLIBNAME9 must not have "t"
PRJLIBNAME9	= tcl9$(PROJECT)$(VERSION)$(SUFX:t=).$(EXT)
!if $(TCL_MAJOR_VERSION) == 8 || "$(TCL_BUILD_FOR)" == "8"
PRJLIBNAME	= $(PRJLIBNAME8)
!else
PRJLIBNAME	= $(PRJLIBNAME9)
!endif
PRJLIB		= $(OUT_DIR)\$(PRJLIBNAME)

!if $(TCL_MAJOR_VERSION) == 8
PRJSTUBLIBNAME	= $(STUBPREFIX)$(VERSION).lib
!else
PRJSTUBLIBNAME	= $(STUBPREFIX).lib
!endif
PRJSTUBLIB	= $(OUT_DIR)\$(PRJSTUBLIBNAME)

# If extension parent makefile has not defined a resource definition file,
# we will generate one from standard template.
!if !$(DOING_TCL) && !$(DOING_TK) && !$(STATIC_BUILD)
!ifdef RCFILE
RESFILE = $(TMP_DIR)\$(RCFILE:.rc=.res)
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
1369
1370
1371
1372
1373
1374
1375

1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388


1389
1390
1391
1392
1393
1394
1395
1396
1397







-
+












-
-
+
+







# 12. Set up actual options to be passed to the compiler and linker
# Now we have all the information we need, set up the actual flags and
# options that we will pass to the compiler and linker. The main
# makefile should use these in combination with whatever other flags
# and switches are specific to it.
# The following macros are defined, names are for historical compatibility:
# OPTDEFINES - /Dxxx C macro flags based on user-specified OPTS
# COMPILERFLAGS - /Dxxx C macro flags independent of any configuration opttions
# COMPILERFLAGS - /Dxxx C macro flags independent of any configuration options
# crt - Compiler switch that selects the appropriate C runtime
# cdebug - Compiler switches related to debug AND optimizations
# cwarn - Compiler switches that set warning levels
# cflags - complete compiler switches (subsumes cdebug and cwarn)
# ldebug - Linker switches controlling debug information and optimization
# lflags - complete linker switches (subsumes ldebug) except subsystem type
# dlllflags - complete linker switches to build DLLs (subsumes lflags)
# conlflags - complete linker switches for console program (subsumes lflags)
# guilflags - complete linker switches for GUI program (subsumes lflags)
# baselibs - minimum Windows libraries required. Parent makefile can
#    define PRJ_LIBS before including rules.rc if additional libs are needed

OPTDEFINES	= /DSTDC_HEADERS
!if $(VCVERSION) >= 1600
OPTDEFINES	= /DSTDC_HEADERS /DUSE_NMAKE=1
!if $(VCVERSION) > 1600
OPTDEFINES	= $(OPTDEFINES) /DHAVE_STDINT_H=1
!else
OPTDEFINES	= $(OPTDEFINES) /DMP_NO_STDINT=1
!endif
!if $(VCVERSION) >= 1800
OPTDEFINES	= $(OPTDEFINES) /DHAVE_INTTYPES_H=1 /DHAVE_STDBOOL_H=1
!endif
1307
1308
1309
1310
1311
1312
1313
1314

1315
1316
1317
1318
1319
1320
1321
1408
1409
1410
1411
1412
1413
1414

1415
1416
1417
1418
1419
1420
1421
1422







-
+







OPTDEFINES	= $(OPTDEFINES) /DUSE_THREAD_ALLOC=1
!endif
!endif
!if $(STATIC_BUILD)
OPTDEFINES	= $(OPTDEFINES) /DSTATIC_BUILD
!elseif $(TCL_VERSION) > 86
OPTDEFINES	= $(OPTDEFINES) /DTCL_WITH_EXTERNAL_TOMMATH
!if "$(MACHINE)" == "AMD64"
!if "$(MACHINE)" == "AMD64" || "$(MACHINE)" == "ARM64"
OPTDEFINES	= $(OPTDEFINES) /DMP_64BIT
!endif
!endif
!if $(TCL_NO_DEPRECATED)
OPTDEFINES	= $(OPTDEFINES) /DTCL_NO_DEPRECATED
!endif

1335
1336
1337
1338
1339
1340
1341
1342

1343
1344
1345
1346
1347
1348
1349

1350
1351
1352

1353
1354


1355
1356

1357
1358

1359
1360
1361
1362
1363
1364
1365
1366
1367
1368



1369
1370
1371
1372
1373
1374
1375
1436
1437
1438
1439
1440
1441
1442

1443
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
1474
1475
1476







-
+






-
+



+
-
-
+
+

-
+
-
-
+







-
-
-
+
+
+







!if $(OPTIMIZING)
OPTDEFINES	= $(OPTDEFINES) /DTCL_CFG_OPTIMIZED
!endif
!endif
!if $(PROFILE)
OPTDEFINES	= $(OPTDEFINES) /DTCL_CFG_PROFILED
!endif
!if "$(MACHINE)" == "AMD64"
!if "$(MACHINE)" == "AMD64" || "$(MACHINE)" == "ARM64"
OPTDEFINES	= $(OPTDEFINES) /DTCL_CFG_DO64BIT
!endif
!if $(VCVERSION) < 1300
OPTDEFINES	= $(OPTDEFINES) /DNO_STRTOI64=1
!endif

!if "$(TCL_MAJOR_VERSION)" == "8"
!if $(TCL_MAJOR_VERSION) == 8
!if "$(_USE_64BIT_TIME_T)" == "1"
OPTDEFINES	= $(OPTDEFINES) /D_USE_64BIT_TIME_T=1
!endif
!endif
!if "$(TCL_UTF_MAX)" == "4"
OPTDEFINES	= $(OPTDEFINES) /DTCL_UTF_MAX=4
!if "$(TCL_BUILD_FOR)" == "8"
OPTDEFINES	= $(OPTDEFINES) /DTCL_MAJOR_VERSION=8
!endif

!if "$(TK_BUILD_FOR)" == "8"
# _ATL_XP_TARGETING - Newer SDK's need this to build for XP
COMPILERFLAGS  = /D_ATL_XP_TARGETING
OPTDEFINES	= $(OPTDEFINES) /DTK_MAJOR_VERSION=8
!endif

# Like the TEA system only set this non empty for non-Tk extensions
# Note: some extensions use PACKAGE_NAME and others use PACKAGE_TCLNAME
# so we pass both
!if !$(DOING_TCL) && !$(DOING_TK)
PKGNAMEFLAGS = /DPACKAGE_NAME="\"$(PRJ_PACKAGE_TCLNAME)\"" \
               /DPACKAGE_TCLNAME="\"$(PRJ_PACKAGE_TCLNAME)\"" \
               /DPACKAGE_VERSION="\"$(DOTVERSION)\"" \
               /DMODULE_SCOPE=extern
	/DPACKAGE_TCLNAME="\"$(PRJ_PACKAGE_TCLNAME)\"" \
	/DPACKAGE_VERSION="\"$(DOTVERSION)\"" \
	/DMODULE_SCOPE=extern
!endif

# crt picks the C run time based on selected OPTS
!if $(MSVCRT)
!if $(DEBUG) && !$(UNCHECKED)
crt = -MDd
!else
1394
1395
1396
1397
1398
1399
1400
1401
1402


1403
1404

1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418





1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435




1436
1437
1438
1439
1440
1441
1442
1495
1496
1497
1498
1499
1500
1501


1502
1503
1504

1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552







-
-
+
+

-
+














+
+
+
+
+

















+
+
+
+







cdebug = $(OPTIMIZATIONS)
!if $(SYMBOLS)
cdebug = $(cdebug) -Zi
!endif

!endif # $(DEBUG)

# cwarn includes default warning levels.
cwarn = $(WARNINGS)
# cwarn includes default warning levels, also C4090 (buggy) and C4146 is useless.
cwarn = $(WARNINGS) -wd4090 -wd4146

!if "$(MACHINE)" == "AMD64"
!if "$(MACHINE)" == "AMD64" || "$(MACHINE)" == "ARM64"
# Disable pointer<->int warnings related to cast between different sizes
# There are a gadzillion of these due to use of ClientData and
# clutter up compiler
# output increasing chance of a real warning getting lost. So disable them.
# Eventually some day, Tcl will be 64-bit clean.
cwarn = $(cwarn) -wd4311 -wd4312
!endif

### Common compiler options that are architecture specific
!if "$(MACHINE)" == "ARM"
carch = /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE
!else
carch =
!endif

# cpuid is only available on intel machines
!if "$(MACHINE)" == "IX86" || "$(MACHINE)" == "AMD64"
carch = $(carch) /DHAVE_CPUID=1
!endif

!if $(DEBUG)
# Turn warnings into errors
cwarn = $(cwarn) -WX
!endif

INCLUDES = $(TCL_INCLUDES) $(TK_INCLUDES) $(PRJ_INCLUDES)
!if !$(DOING_TCL) && !$(DOING_TK)
INCLUDES = $(INCLUDES) -I"$(GENERICDIR)" -I"$(WIN_DIR)" -I"$(COMPATDIR)"
!endif

# These flags are defined roughly in the order of the pre-reform
# rules.vc/makefile.vc to help visually compare that the pre- and
# post-reform build logs

# cflags contains generic flags used for building practically all object files
cflags = -nologo -c $(COMPILERFLAGS) $(carch) $(cwarn) -Fp$(TMP_DIR)^\ $(cdebug)

!if $(TCL_MAJOR_VERSION) == 8 && $(TCL_MINOR_VERSION) < 7
cflags = $(cflags) -DTcl_Size=int
!endif

# appcflags contains $(cflags) and flags for building the application
# object files (e.g. tclsh, or wish) pkgcflags contains $(cflags) plus
# flags used for building shared object files The two differ in the
# BUILD_$(PROJECT) macro which should be defined only for the shared
# library *implementation* and not for its caller interface

1452
1453
1454
1455
1456
1457
1458
1459

1460
1461
1462
1463
1464
1465
1466
1562
1563
1564
1565
1566
1567
1568

1569
1570
1571
1572
1573
1574
1575
1576







-
+







# here irrespective of the OPTS setting.
#
# TBD - tclvfs has a comment that stubs libs should not be compiled with -GL
# without stating why. Tcl itself compiled stubs libs with this flag.
# so we do not remove it from cflags. -GL may prevent extensions
# compiled with one VC version to fail to link against stubs library
# compiled with another VC version. Check for this and fix accordingly.
stubscflags = $(cflags) $(PKGNAMEFLAGS) $(PRJ_DEFINES) $(OPTDEFINES) -Zl /DSTATIC_BUILD $(INCLUDES) $(USE_STUBS_DEFS)
stubscflags = $(cflags) $(PKGNAMEFLAGS) $(PRJ_DEFINES) $(OPTDEFINES) /Zl /GL- /DSTATIC_BUILD $(INCLUDES) $(USE_STUBS_DEFS)

# Link flags

!if $(DEBUG)
ldebug	= -debug -debugtype:cv
!else
ldebug	= -release -opt:ref -opt:icf,3
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1585
1586
1587
1588
1589
1590
1591












1592
1593
1594
1595
1596
1597
1598







-
-
-
-
-
-
-
-
-
-
-
-







!endif

### Declarations common to all linker versions
lflags	= -nologo -machine:$(MACHINE) $(LINKERFLAGS) $(ldebug)

!if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900
lflags	= $(lflags) -nodefaultlib:libucrt.lib
!endif

# Old linkers (Visual C++ 6 in particular) will link for fast loading
# on Win98. Since we do not support Win98 any more, we specify nowin98
# as recommended for NT and later. However, this is only required by
# IX86 on older compilers and only needed if we are not doing a static build.

!if "$(MACHINE)" == "IX86" && !$(STATIC_BUILD)
!if [nmakehlp -l -opt:nowin98 $(LINKER_TESTFLAGS)]
# Align sections for PE size savings.
lflags	= $(lflags) -opt:nowin98
!endif
!endif

dlllflags = $(lflags) -dll
conlflags = $(lflags) -subsystem:console
guilflags = $(lflags) -subsystem:windows

# Libraries that are required for every image.
1528
1529
1530
1531
1532
1533
1534
1535

1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551

1552
1553





1554
1555

1556
1557





1558
1559
1560
1561
1562
1563
1564
1565


1566
1567
1568
1569
1570
1571
1572
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







-
+
















+

-
+
+
+
+
+


+

-
+
+
+
+
+








+
+








LIBCMD = $(lib32) -nologo $(LINKERFLAGS) -out:$@
DLLCMD = $(link32) $(dlllflags) -out:$@ $(baselibs) $(tcllibs) $(tklibs)

CONEXECMD = $(link32) $(conlflags) -out:$@ $(baselibs) $(tcllibs) $(tklibs)
GUIEXECMD = $(link32) $(guilflags) -out:$@ $(baselibs) $(tcllibs) $(tklibs)
RESCMD  = $(rc32) -fo $@ -r -i "$(GENERICDIR)" -i "$(TMP_DIR)" \
	    $(TCL_INCLUDES) \
	    $(TCL_INCLUDES) /DSTATIC_BUILD=$(STATIC_BUILD) \
	    /DDEBUG=$(DEBUG) -d UNCHECKED=$(UNCHECKED) \
	    /DCOMMAVERSION=$(RCCOMMAVERSION) \
	    /DDOTVERSION=\"$(DOTVERSION)\" \
	    /DVERSION=\"$(VERSION)\" \
	    /DSUFX=\"$(SUFX)\" \
	    /DPROJECT=\"$(PROJECT)\" \
	    /DPRJLIBNAME=\"$(PRJLIBNAME)\"

!ifndef DEFAULT_BUILD_TARGET
DEFAULT_BUILD_TARGET = $(PROJECT)
!endif

default-target: $(DEFAULT_BUILD_TARGET)

!if $(MULTIPLATFORM_INSTALL)
default-pkgindex:
	@echo if {[package vsatisfies [package provide Tcl] 9.0-]} { > $(OUT_DIR)\pkgIndex.tcl
	@echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \
	    [list load [file join $$dir $(PLATFORM_IDENTIFY) $(PRJLIBNAME)]] > $(OUT_DIR)\pkgIndex.tcl
	    [list load [file join $$dir $(PLATFORM_IDENTIFY) $(PRJLIBNAME9)]] >> $(OUT_DIR)\pkgIndex.tcl
	@echo } else { >> $(OUT_DIR)\pkgIndex.tcl
	@echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \
	    [list load [file join $$dir $(PLATFORM_IDENTIFY) $(PRJLIBNAME8)]] >> $(OUT_DIR)\pkgIndex.tcl
	@echo } >> $(OUT_DIR)\pkgIndex.tcl
!else
default-pkgindex:
	@echo if {[package vsatisfies [package provide Tcl] 9.0-]} { > $(OUT_DIR)\pkgIndex.tcl
	@echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \
	    [list load [file join $$dir $(PRJLIBNAME)]] > $(OUT_DIR)\pkgIndex.tcl
	    [list load [file join $$dir $(PRJLIBNAME9)]] >> $(OUT_DIR)\pkgIndex.tcl
	@echo } else { >> $(OUT_DIR)\pkgIndex.tcl
	@echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \
	    [list load [file join $$dir $(PRJLIBNAME8)]] >> $(OUT_DIR)\pkgIndex.tcl
	@echo } >> $(OUT_DIR)\pkgIndex.tcl
!endif

default-pkgindex-tea:
	@if exist $(ROOT)\pkgIndex.tcl.in nmakehlp -s << $(ROOT)\pkgIndex.tcl.in > $(OUT_DIR)\pkgIndex.tcl
@PACKAGE_VERSION@    $(DOTVERSION)
@PACKAGE_NAME@       $(PRJ_PACKAGE_TCLNAME)
@PACKAGE_TCLNAME@    $(PRJ_PACKAGE_TCLNAME)
@PKG_LIB_FILE@       $(PRJLIBNAME)
@PKG_LIB_FILE8@      $(PRJLIBNAME8)
@PKG_LIB_FILE9@      $(PRJLIBNAME9)
<<

default-install: default-install-binaries default-install-libraries
!if $(SYMBOLS)
default-install: default-install-pdbs
!endif

1595
1596
1597
1598
1599
1600
1601


1602
1603
1604
1605
1606
1607
1608
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720







+
+







	@if not exist "$(SCRIPT_INSTALL_DIR)" mkdir "$(SCRIPT_INSTALL_DIR)"
	@$(CPY) $(PRJSTUBLIB) "$(SCRIPT_INSTALL_DIR)" >NUL

default-install-pdbs:
	@echo Installing PDBs to '$(LIB_INSTALL_DIR)'
	@if not exist "$(LIB_INSTALL_DIR)" mkdir "$(LIB_INSTALL_DIR)"
	@$(CPY) "$(OUT_DIR)\*.pdb" "$(LIB_INSTALL_DIR)\"

# "emacs font-lock highlighting fix

default-install-docs-html:
	@echo Installing documentation files to '$(DOC_INSTALL_DIR)'
	@if not exist "$(DOC_INSTALL_DIR)" mkdir "$(DOC_INSTALL_DIR)"
	@if exist $(DOCDIR) for %f in ("$(DOCDIR)\*.html" "$(DOCDIR)\*.css" "$(DOCDIR)\*.png") do @$(COPY) %f "$(DOC_INSTALL_DIR)"

default-install-docs-n:
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
1799
1800
1801
1802
1803
1804
1805








1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816

1817
1818
1819
1820
1821
1822
1823
1824







-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+



-
+







#endif
 FILEOS		VOS_NT_WINDOWS32
 FILETYPE	VFT_DLL
 FILESUBTYPE	0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0"
        BEGIN
            VALUE "FileDescription",  "Tcl extension " PROJECT
            VALUE "OriginalFilename", PRJLIBNAME
            VALUE "FileVersion",      DOTVERSION
            VALUE "ProductName",      "Package " PROJECT " for Tcl"
            VALUE "ProductVersion",   DOTVERSION
        END
	BLOCK "040904b0"
	BEGIN
	    VALUE "FileDescription",  "Tcl extension " PROJECT
	    VALUE "OriginalFilename", PRJLIBNAME
	    VALUE "FileVersion",      DOTVERSION
	    VALUE "ProductName",      "Package " PROJECT " for Tcl"
	    VALUE "ProductVersion",   DOTVERSION
	END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
	VALUE "Translation", 0x409, 1200
    END
END

<<

!endif # ifdef RCFILE

1760
1761
1762
1763
1764
1765
1766
1767
1768


1769
1770
1771
1772
1773
1774
1775
1872
1873
1874
1875
1876
1877
1878


1879
1880
1881
1882
1883
1884
1885
1886
1887







-
-
+
+







!if !$(DOING_TCL)

!if $(TCLINSTALL) # Building against an installed Tcl
!if exist("$(_TCLDIR)\lib\nmake\tcl.nmake")
TCLNMAKECONFIG = "$(_TCLDIR)\lib\nmake\tcl.nmake"
!endif
!else # !$(TCLINSTALL) - building against Tcl source
!if exist("$(OUT_DIR)\tcl.nmake")
TCLNMAKECONFIG = "$(OUT_DIR)\tcl.nmake"
!if exist("$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl.nmake")
TCLNMAKECONFIG	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl.nmake"
!endif
!endif # TCLINSTALL

!if $(CONFIG_CHECK)
!ifdef TCLNMAKECONFIG
!include $(TCLNMAKECONFIG)

Added win/svnmanifest.in.


1
+
svn-r

Changes to win/targets.vc.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







#------------------------------------------------------------- -*- makefile -*-
# targets.vc --
#
# Part of the nmake based build system for Tcl and its extensions.
# This file defines some standard targets for the convenience of extensions
# and can be optionally included by the extension makefile.
# See TIP 477 (https://core.tcl-lang.org/tips/doc/trunk/tip/477.md) for docs.
# See TIP 477 (https://core.tcl-lang.org/tips/doc/main/tip/477.md) for docs.

$(PROJECT): setup pkgindex $(PRJLIB)

!ifdef PRJ_STUBOBJS
$(PROJECT): $(PRJSTUBLIB)
$(PRJSTUBLIB): $(PRJ_STUBOBJS)
	$(LIBCMD) $**

Changes to win/tcl.dsp.

30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
30
31
32
33
34
35
36

37
38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53







-
+








-
+








!IF  "$(CFG)" == "tcl - Win32 Release"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release\tcl_Dynamic"
# PROP BASE Cmd_Line "nmake -nologo -f makefile.vc OPTS=none MSVCDIR=IDE"
# PROP BASE Cmd_Line "nmake -nologo -f makefile.vc MSVCDIR=IDE"
# PROP BASE Rebuild_Opt "-a"
# PROP BASE Target_File "Release\tclsh90.exe"
# PROP BASE Bsc_Name ""
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release\tcl_Dynamic"
# PROP Cmd_Line "nmake -nologo -f makefile.vc OPTS=threads MSVCDIR=IDE"
# PROP Cmd_Line "nmake -nologo -f makefile.vc MSVCDIR=IDE"
# PROP Rebuild_Opt "clean release"
# PROP Target_File "Release\tclsh90t.exe"
# PROP Bsc_Name ""
# PROP Target_Dir ""

!ELSEIF  "$(CFG)" == "tcl - Win32 Debug"

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
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







-
-
-
-
-
-
-
-












-
-
-
-
-
-
-
-




-
-
-
-


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







!ENDIF

# Begin Group "compat"

# PROP Default_Filter ""
# Begin Source File

SOURCE=..\compat\dirent.h
# End Source File
# Begin Source File

SOURCE=..\compat\dirent2.h
# End Source File
# Begin Source File

SOURCE=..\compat\dlfcn.h
# End Source File
# Begin Source File

SOURCE=..\compat\gettod.c
# End Source File
# Begin Source File

SOURCE=..\compat\limits.h
# End Source File
# Begin Source File

SOURCE=..\compat\memcmp.c
# End Source File
# Begin Source File

SOURCE=..\compat\opendir.c
# End Source File
# Begin Source File

SOURCE=..\compat\README
# End Source File
# Begin Source File

SOURCE=..\compat\stdlib.h
# End Source File
# Begin Source File

SOURCE=..\compat\string.h
# End Source File
# Begin Source File

SOURCE=..\compat\strncasecmp.c
# End Source File
# Begin Source File

SOURCE=..\compat\strstr.c
# End Source File
# Begin Source File

SOURCE=..\compat\strtol.c
# End Source File
# Begin Source File

SOURCE=..\compat\strtoul.c
# End Source File
# Begin Source File

SOURCE=..\compat\tclErrno.h
# End Source File
# Begin Source File

SOURCE=..\compat\waitpid.c
# End Source File
# End Group
# Begin Group "doc"

# PROP Default_Filter ""
# Begin Source File

SOURCE=..\doc\Access.3
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
226
227
228
229
230
231
232




233
234
235
236
237
238
239







-
-
-
-








SOURCE=..\doc\ByteArrObj.3
# End Source File
# Begin Source File

SOURCE=..\doc\CallDel.3
# End Source File
# Begin Source File

SOURCE=..\doc\case.n
# End Source File
# Begin Source File

SOURCE=..\doc\catch.n
# End Source File
# Begin Source File

SOURCE=..\doc\cd.n
756
757
758
759
760
761
762
763

764
765
766
767
768
769
770
708
709
710
711
712
713
714

715
716
717
718
719
720
721
722







-
+







# End Source File
# Begin Source File

SOURCE=..\doc\safe.n
# End Source File
# Begin Source File

SOURCE=..\doc\SaveResult.3
SOURCE=..\doc\SaveInterpState.3
# End Source File
# Begin Source File

SOURCE=..\doc\scan.n
# End Source File
# Begin Source File

820
821
822
823
824
825
826
827

828
829
830
831
832
833
834
772
773
774
775
776
777
778

779
780
781
782
783
784
785
786







-
+







# End Source File
# Begin Source File

SOURCE=..\doc\SplitPath.3
# End Source File
# Begin Source File

SOURCE=..\doc\StaticPkg.3
SOURCE=..\doc\StaticLibrary.3
# End Source File
# Begin Source File

SOURCE=..\doc\StdChannels.3
# End Source File
# Begin Source File

1283
1284
1285
1286
1287
1288
1289








1290
1291
1292
1293
1294
1295
1296
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256







+
+
+
+
+
+
+
+







SOURCE=..\generic\tclStubInit.c
# End Source File
# Begin Source File

SOURCE=..\generic\tclStubLib.c
# End Source File
# Begin Source File

SOURCE=..\generic\tclStubCall.c
# End Source File
# Begin Source File

SOURCE=..\generic\tclStubLibTbl.c
# End Source File
# Begin Source File

SOURCE=..\generic\tclOOStubLib.c
# End Source File
# Begin Source File

SOURCE=..\generic\tclTomMathStubLib.c
# End Source File
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1398
1399
1400
1401
1402
1403
1404




1405
1406
1407
1408
1409
1410
1411







-
-
-
-








SOURCE=.\rmd.bat
# End Source File
# Begin Source File

SOURCE=.\rules.vc
# End Source File
# Begin Source File

SOURCE=.\tcl.hpj.in
# End Source File
# Begin Source File

SOURCE=.\tcl.m4
# End Source File
# Begin Source File

SOURCE=.\tcl.rc

Deleted win/tcl.hpj.in.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19



















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
; This file is maintained by HCW. Do not modify this file directly.

[OPTIONS]
HCW=0
LCID=0x409 0x0 0x0 ;English (United States)
REPORT=Yes
TITLE=Tcl/Tk Reference Manual
CNT=tcl90.cnt
COPYRIGHT=Copyright © 2000 Ajuba Solutions
HLP=tcl90.hlp

[FILES]
tcl.rtf

[WINDOWS]
main="Tcl/Tk Reference Manual",,0

[CONFIG]
BrowseButtons()

Changes to win/tcl.m4.

24
25
26
27
28
29
30
31

32
33

34
35
36
37
38
39
40
24
25
26
27
28
29
30

31
32

33
34
35
36
37
38
39
40







-
+

-
+







    # the alternative search directory is invoked by --with-tcl
    #

    if test x"${no_tcl}" = x ; then
	# we reset no_tcl in case something fails here
	no_tcl=true
	AC_ARG_WITH(tcl,
	    AC_HELP_STRING([--with-tcl],
	    AS_HELP_STRING([--with-tcl],
		[directory containing tcl configuration (tclConfig.sh)]),
	    with_tclconfig="${withval}")
	    [with_tclconfig="${withval}"])
	AC_MSG_CHECKING([for Tcl configuration])
	AC_CACHE_VAL(ac_cv_c_tclconfig,[

	    # First check to see if --with-tcl was specified.
	    if test x"${with_tclconfig}" != x ; then
		case "${with_tclconfig}" in
		    */tclConfig.sh )
142
143
144
145
146
147
148
149

150
151

152
153
154
155
156
157
158
142
143
144
145
146
147
148

149
150

151
152
153
154
155
156
157
158







-
+

-
+







    # the alternative search directory is invoked by --with-tk
    #

    if test x"${no_tk}" = x ; then
	# we reset no_tk in case something fails here
	no_tk=true
	AC_ARG_WITH(tk,
	    AC_HELP_STRING([--with-tk],
	    AS_HELP_STRING([--with-tk],
		[directory containing tk configuration (tkConfig.sh)]),
	    with_tkconfig="${withval}")
	    [with_tkconfig="${withval}"])
	AC_MSG_CHECKING([for Tk configuration])
	AC_CACHE_VAL(ac_cv_c_tkconfig,[

	    # First check to see if --with-tkconfig was specified.
	    if test x"${with_tkconfig}" != x ; then
		case "${with_tkconfig}" in
		    */tkConfig.sh )
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
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







-







-
+


-
+












-
-
-
+
+
+










-







#
# Results:
#
#	Substitutes the following vars:
#		TCL_BIN_DIR
#		TCL_SRC_DIR
#		TCL_LIB_FILE
#		TCL_ZIP_FILE
#
#------------------------------------------------------------------------

AC_DEFUN([SC_LOAD_TCLCONFIG], [
    AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh])

    if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then
        AC_MSG_RESULT([loading])
	AC_MSG_RESULT([loading])
	. "${TCL_BIN_DIR}/tclConfig.sh"
    else
        AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh])
	AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh])
    fi

    #
    # If the TCL_BIN_DIR is the build directory (not the install directory),
    # then set the common variable name to the value of the build variables.
    # For example, the variable TCL_LIB_SPEC will be set to the value
    # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC
    # instead of TCL_BUILD_LIB_SPEC since it will work with both an
    # installed and uninstalled version of Tcl.
    #

    if test -f $TCL_BIN_DIR/Makefile ; then
        TCL_LIB_SPEC=${TCL_BUILD_LIB_SPEC}
        TCL_STUB_LIB_SPEC=${TCL_BUILD_STUB_LIB_SPEC}
        TCL_STUB_LIB_PATH=${TCL_BUILD_STUB_LIB_PATH}
	TCL_LIB_SPEC=${TCL_BUILD_LIB_SPEC}
	TCL_STUB_LIB_SPEC=${TCL_BUILD_STUB_LIB_SPEC}
	TCL_STUB_LIB_PATH=${TCL_BUILD_STUB_LIB_PATH}
    fi

    eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
    eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\""
    eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\""

    AC_SUBST(TCL_VERSION)
    AC_SUBST(TCL_BIN_DIR)
    AC_SUBST(TCL_SRC_DIR)

    AC_SUBST(TCL_ZIP_FILE)
    AC_SUBST(TCL_LIB_FILE)
    AC_SUBST(TCL_LIB_FLAG)
    AC_SUBST(TCL_LIB_SPEC)

    AC_SUBST(TCL_STUB_LIB_FILE)
    AC_SUBST(TCL_STUB_LIB_FLAG)
    AC_SUBST(TCL_STUB_LIB_SPEC)
316
317
318
319
320
321
322
323

324
325
326

327
328
329
330
331
332
333
314
315
316
317
318
319
320

321
322
323

324
325
326
327
328
329
330
331







-
+


-
+







#		TK_BIN_DIR
#------------------------------------------------------------------------

AC_DEFUN([SC_LOAD_TKCONFIG], [
    AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh])

    if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then
        AC_MSG_RESULT([loading])
	AC_MSG_RESULT([loading])
	. "${TK_BIN_DIR}/tkConfig.sh"
    else
        AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh])
	AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh])
    fi


    AC_SUBST(TK_BIN_DIR)
    AC_SUBST(TK_SRC_DIR)
    AC_SUBST(TK_LIB_FILE)
])
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
352
353
354
355
356
357
358








359
360
361
362
363
364
365







-
-
-
-
-
-
-
-







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

AC_DEFUN([SC_ENABLE_SHARED], [
    AC_MSG_CHECKING([how to build libraries])
    AC_ARG_ENABLE(shared,
	[  --enable-shared         build and link with shared libraries (default: on)],
	[tcl_ok=$enableval], [tcl_ok=yes])

    if test "${enable_shared+set}" = set; then
	enableval="$enable_shared"
	tcl_ok=$enableval
    else
	tcl_ok=yes
    fi

    if test "$tcl_ok" = "yes" ; then
	AC_MSG_RESULT([shared])
	SHARED_BUILD=1
    else
	AC_MSG_RESULT([static])
	SHARED_BUILD=0
	AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?])
459
460
461
462
463
464
465

466
467
468
469
470
471
472
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463







+







# Results:
#
#	Can the following vars:
#		EXTRA_CFLAGS
#		CFLAGS_DEBUG
#		CFLAGS_OPTIMIZE
#		CFLAGS_WARNING
#		CFLAGS_NOLTO
#		LDFLAGS_DEBUG
#		LDFLAGS_OPTIMIZE
#		LDFLAGS_CONSOLE
#		LDFLAGS_WINDOW
#		CC_OBJNAME
#		CC_EXENAME
#		CYGPATH
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
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







-
+






-
+



-
-
-
+
+
+











+
+
+
+
+
+
+








    AC_CHECK_PROG(CYGPATH, cygpath, cygpath -m, echo)
    AC_CHECK_PROG(WINE, wine, wine,)

    SHLIB_SUFFIX=".dll"

    # MACHINE is IX86 for LINK, but this is used by the manifest,
    # which requires x86|amd64|ia64.
    # which requires x86|amd64|arm64|ia64.
    MACHINE="X86"

    if test "$GCC" = "yes"; then

      AC_CACHE_CHECK(for cross-compile version of gcc,
	ac_cv_cross,
	AC_TRY_COMPILE([
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	    #ifndef _WIN32
		#error cross-compiler
	    #endif
	], [],
	ac_cv_cross=no,
	ac_cv_cross=yes)
	]], [[]])],
	[ac_cv_cross=no],
	[ac_cv_cross=yes])
      )

      if test "$ac_cv_cross" = "yes"; then
	case "$do64bit" in
	    amd64|x64|yes)
		CC="x86_64-w64-mingw32-${CC}"
		LD="x86_64-w64-mingw32-ld"
		AR="x86_64-w64-mingw32-ar"
		RANLIB="x86_64-w64-mingw32-ranlib"
		RC="x86_64-w64-mingw32-windres"
	    ;;
	    arm64|aarch64)
		CC="aarch64-w64-mingw32-${CC}"
		LD="aarch64-w64-mingw32-ld"
		AR="aarch64-w64-mingw32-ar"
		RANLIB="aarch64-w64-mingw32-ranlib"
		RC="aarch64-w64-mingw32-windres"
	    ;;
	    *)
		CC="i686-w64-mingw32-${CC}"
		LD="i686-w64-mingw32-ld"
		AR="i686-w64-mingw32-ar"
		RANLIB="i686-w64-mingw32-ranlib"
		RC="i686-w64-mingw32-windres"
	    ;;
568
569
570
571
572
573
574
575

576
577

578
579
580
581
582
583
584
585
586
587

588
589
590
591
592
593



594
595
596
597



598
599
600
601
602

603
604
605

606
607
608


609
610
611
612
613
614
615

































616
617
618
619
620
621
622
623
624

625
626
627
628
629
630
631
632
633
634
635
636
637
638
639

640
641
642
643
644
645

646
647
648
649
650

651
652
653
654
655
656
657
566
567
568
569
570
571
572

573
574

575
576
577
578
579
580
581
582
583
584

585
586
587
588



589
590
591
592
593
594
595
596
597
598
599
600
601
602

603
604
605

606



607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656

657
658
659
660
661
662
663
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







-
+

-
+









-
+



-
-
-
+
+
+




+
+
+




-
+


-
+
-
-
-
+
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
+














-
+





-
+




-
+







	    CYGPATH=echo
	fi
	conftest=
	cyg_conftest=
    fi

    if test "$CYGPATH" = "echo"; then
        DEPARG='"$<"'
	DEPARG='"$<"'
    else
        DEPARG='"$(shell $(CYGPATH) $<)"'
	DEPARG='"$(shell $(CYGPATH) $<)"'
    fi

    # set various compiler flags depending on whether we are using gcc or cl

    if test "${GCC}" = "yes" ; then
	extra_cflags="-pipe"
	extra_ldflags="-pipe -static-libgcc"
	AC_CACHE_CHECK(for mingw32 version of gcc,
	    ac_cv_win32,
	    AC_TRY_COMPILE([
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
		#ifdef _WIN32
		    #error win32
		#endif
	    ], [],
	    ac_cv_win32=no,
	    ac_cv_win32=yes)
	    ]], [[]])],
	    [ac_cv_win32=no],
	    [ac_cv_win32=yes])
	)
	if test "$ac_cv_win32" != "yes"; then
	    AC_MSG_ERROR([${CC} cannot produce win32 executables.])
	fi
	if test "$do64bit" != "arm64"; then
	    extra_cflags="$extra_cflags -DHAVE_CPUID=1"
	fi

	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -mwindows -municode -Dmain=xxmain"
	AC_CACHE_CHECK(for working -municode linker flag,
	    ac_cv_municode,
	AC_TRY_LINK([
	AC_LINK_IFELSE([AC_LANG_PROGRAM([[
	#include <windows.h>
	int APIENTRY wWinMain(HINSTANCE a, HINSTANCE b, LPWSTR c, int d) {return 0;}
	],
	]], [[]])],
	[],
	    ac_cv_municode=yes,
	    ac_cv_municode=no)
	    [ac_cv_municode=yes],
	    [ac_cv_municode=no])
	)
	CFLAGS=$hold_cflags
	if test "$ac_cv_municode" = "yes" ; then
	    extra_ldflags="$extra_ldflags -municode"
	else
	    extra_cflags="$extra_cflags -DTCL_BROKEN_MAINARGS"
	fi
	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -fno-lto"
	AC_CACHE_CHECK(for working -fno-lto,
	    ac_cv_nolto,
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
	    [ac_cv_nolto=yes],
	    [ac_cv_nolto=no])
	)
	CFLAGS=$hold_cflags
	if test "$ac_cv_nolto" = "yes" ; then
	    CFLAGS_NOLTO="-fno-lto"
	else
	    CFLAGS_NOLTO=""
	fi
	AC_CACHE_CHECK([if the compiler understands -finput-charset],
	    tcl_cv_cc_input_charset, [
	    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -finput-charset=UTF-8"
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[tcl_cv_cc_input_charset=yes],[tcl_cv_cc_input_charset=no])
	    CFLAGS=$hold_cflags])
	if test $tcl_cv_cc_input_charset = yes; then
	    extra_cflags="$extra_cflags -finput-charset=UTF-8"
	fi
    fi

    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Wl,--enable-auto-image-base"
    AC_CACHE_CHECK(for working --enable-auto-image-base,
	ac_cv_enable_auto_image_base,
    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
	[ac_cv_enable_auto_image_base=yes],
	[ac_cv_enable_auto_image_base=no])
    )
    CFLAGS=$hold_cflags
    if test "$ac_cv_enable_auto_image_base" = "yes" ; then
	extra_ldflags="$extra_ldflags -Wl,--enable-auto-image-base"
    fi

    AC_MSG_CHECKING([compiler flags])
    if test "${GCC}" = "yes" ; then
	SHLIB_LD=""
	SHLIB_LD_LIBS='${LIBS}'
	LIBS="-lnetapi32 -lkernel32 -luser32 -ladvapi32 -luserenv -lws2_32"
	# mingw needs to link ole32 and oleaut32 for [send], but MSVC doesn't
	LIBS_GUI="-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32 -luuid -lole32 -loleaut32"
	LIBS_GUI="-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32 -luuid -lole32 -loleaut32 -lwinspool"
	STLIB_LD='${AR} cr'
	RC_OUT=-o
	RC_TYPE=
	RC_INCLUDE=--include
	RC_DEFINE=--define
	RES=res.o
	MAKE_LIB="\${STLIB_LD} \[$]@"
	MAKE_STUB_LIB="\${STLIB_LD} \[$]@"
	POST_MAKE_LIB="\${RANLIB} \[$]@"
	MAKE_EXE="\${CC} -o \[$]@"
	LIBPREFIX="lib"

	if test "${SHARED_BUILD}" = "0" ; then
	    # static
            AC_MSG_RESULT([using static flags])
	    AC_MSG_RESULT([using static flags])
	    runtime=
	    LIBRARIES="\${STATIC_LIBRARIES}"
	    EXESUFFIX="s.exe"
	else
	    # dynamic
            AC_MSG_RESULT([using shared flags])
	    AC_MSG_RESULT([using shared flags])

	    # ad-hoc check to see if CC supports -shared.
	    if "${CC}" -shared 2>&1 | egrep ': -shared not supported' >/dev/null; then
		AC_MSG_ERROR([${CC} does not support the -shared option.
                You will need to upgrade to a newer version of the toolchain.])
		You will need to upgrade to a newer version of the toolchain.])
	    fi

	    runtime=
	    # Add SHLIB_LD_LIBS to the Make rule, not here.

	    EXESUFFIX=".exe"
	    LIBRARIES="\${SHARED_LIBRARIES}"
678
679
680
681
682
683
684
685

686
687
688
689
690
691
692
711
712
713
714
715
716
717

718
719
720
721
722
723
724
725







-
+







	LDFLAGS_OPTIMIZE=

	case "${CC}" in
	    *++)
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wno-format"
		;;
	    *)
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wc++-compat -Wdeclaration-after-statement"
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wc++-compat -fextended-identifiers"
		;;
	esac

	# Specify the CC output file names based on the target name
	CC_OBJNAME="-o \[$]@"
	CC_EXENAME="-o \[$]@"

708
709
710
711
712
713
714




715
716
717

718
719
720

721
722
723
724
725
726



727
728
729
730
731



732
733
734
735
736
737
738

739
740
741
742
743
744

745
746
747
748
749
750
751
741
742
743
744
745
746
747
748
749
750
751
752
753

754
755
756

757
758
759
760



761
762
763
764
765



766
767
768
769
770
771
772
773
774

775
776
777
778
779
780

781
782
783
784
785
786
787
788







+
+
+
+


-
+


-
+



-
-
-
+
+
+


-
-
-
+
+
+






-
+





-
+







	LDFLAGS_WINDOW="-mwindows ${extra_ldflags}"

	case "$do64bit" in
	    amd64|x64|yes)
		MACHINE="AMD64" ; # assume AMD64 as default 64-bit build
		AC_MSG_RESULT([   Using 64-bit $MACHINE mode])
		;;
	    arm64|aarch64)
		MACHINE="ARM64"
		AC_MSG_RESULT([   Using ARM64 $MACHINE mode])
		;;
	    ia64)
		MACHINE="IA64"
		AC_MSG_RESULT([   Using 64-bit $MACHINE mode])
		AC_MSG_RESULT([   Using IA64 $MACHINE mode])
		;;
	    *)
		AC_TRY_COMPILE([
		AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
		    #ifndef _WIN64
			#error 32-bit
		    #endif
		], [],
			tcl_win_64bit=yes,
			tcl_win_64bit=no
		]], [[]])],
			[tcl_win_64bit=yes],
			[tcl_win_64bit=no]
		)
		if test "$tcl_win_64bit" = "yes" ; then
			do64bit=amd64
			MACHINE="AMD64"
			AC_MSG_RESULT([   Using 64-bit $MACHINE mode])
		    do64bit=amd64
		    MACHINE="AMD64"
		    AC_MSG_RESULT([   Using 64-bit $MACHINE mode])
		fi
		;;
	esac
    else
	if test "${SHARED_BUILD}" = "0" ; then
	    # static
            AC_MSG_RESULT([using static flags])
	    AC_MSG_RESULT([using static flags])
	    runtime=-MT
	    LIBRARIES="\${STATIC_LIBRARIES}"
	    EXESUFFIX="s.exe"
	else
	    # dynamic
            AC_MSG_RESULT([using shared flags])
	    AC_MSG_RESULT([using shared flags])
	    runtime=-MD
	    # Add SHLIB_LD_LIBS to the Make rule, not here.
	    LIBRARIES="\${SHARED_LIBRARIES}"
	    EXESUFFIX=".exe"
	    case "x`echo \${VisualStudioVersion}`" in
		x1[[4-9]]*)
		    lflags="${lflags} -nodefaultlib:libucrt.lib"
762
763
764
765
766
767
768



769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790

791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807

808
809
810
811
812
813
814
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828


829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845

846
847
848
849
850
851
852
853







+
+
+




















-
-
+
















-
+







	LIBFLAGSUFFIX=""

	if test "$do64bit" != "no" ; then
	    case "$do64bit" in
		amd64|x64|yes)
		    MACHINE="AMD64" ; # assume AMD64 as default 64-bit build
		    ;;
		arm64|aarch64)
		    MACHINE="ARM64"
		    ;;
		ia64)
		    MACHINE="IA64"
		    ;;
	    esac
	    AC_MSG_RESULT([   Using 64-bit $MACHINE mode])
	fi

	LIBS="netapi32.lib kernel32.lib user32.lib advapi32.lib userenv.lib ws2_32.lib"

	case "x`echo \${VisualStudioVersion}`" in
		x1[[4-9]]*)
		    LIBS="$LIBS ucrt.lib"
		    ;;
		*)
		    ;;
	esac

	if test "$do64bit" != "no" ; then
	    RC="rc"
	    CFLAGS_DEBUG="-nologo -Zi -Od ${runtime}d"
	    # Do not use -O2 for Win64 - this has proved buggy in code gen.
	    CFLAGS_OPTIMIZE="-nologo -O1 ${runtime}"
	    CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}"
	    lflags="${lflags} -nologo -MACHINE:${MACHINE}"
	    LINKBIN="link"
	    # Avoid 'unresolved external symbol __security_cookie' errors.
	    # c.f. http://support.microsoft.com/?id=894573
	    LIBS="$LIBS bufferoverflowU.lib"
	else
	    RC="rc"
	    # -Od - no optimization
	    # -WX - warnings as errors
	    CFLAGS_DEBUG="-nologo -Z7 -Od -WX ${runtime}d"
	    # -O2 - create fast code (/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy)
	    CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}"
	    lflags="${lflags} -nologo"
	    LINKBIN="link"
	fi

	LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib"
	LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib winspool.lib"

	SHLIB_LD="${LINKBIN} -dll -incremental:no ${lflags}"
	SHLIB_LD_LIBS='${LIBS}'
	# link -lib only works when -lib is the first arg
	STLIB_LD="${LINKBIN} -lib ${lflags}"
	RC_OUT=-fo
	RC_TYPE=-r
847
848
849
850
851
852
853
854

855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872




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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934

935
936
937
938
939
940



941
942
943
944
945
946
947
948
949
950
951
952

953
954
955
956
957
958
959
886
887
888
889
890
891
892

893
894
895
896
897
898
899
900
901
902
903
904
905
906
907




908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925

926
927
928
929

930
931



932
933
934
935
936
937
938
939
940
























941
942
943
944
945
946
947
948

949

950
951



952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974







-
+














-
-
-
-
+
+
+
+














-
+



-
+

-
-
-
+
+
+






-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








-
+
-


-
-
-
+
+
+












+







    if test "$do64bit" != "no" ; then
	AC_DEFINE(TCL_CFG_DO64BIT)
    fi

    if test "${GCC}" = "yes" ; then
	AC_CACHE_CHECK(for SEH support in compiler,
	    tcl_cv_seh,
	AC_TRY_RUN([
	AC_RUN_IFELSE([AC_LANG_SOURCE([[
	    #define WIN32_LEAN_AND_MEAN
	    #include <windows.h>
	    #undef WIN32_LEAN_AND_MEAN

	    int main(int argc, char** argv) {
		int a, b = 0;
		__try {
		    a = 666 / b;
		}
		__except (EXCEPTION_EXECUTE_HANDLER) {
		    return 0;
		}
		return 1;
	    }
	],
	    tcl_cv_seh=yes,
	    tcl_cv_seh=no,
	    tcl_cv_seh=no)
	]])],
	    [tcl_cv_seh=yes],
	    [tcl_cv_seh=no],
	    [tcl_cv_seh=no])
	)
	if test "$tcl_cv_seh" = "no" ; then
	    AC_DEFINE(HAVE_NO_SEH, 1,
		    [Defined when mingw does not support SEH])
	fi

	#
	# Check to see if the excpt.h include file provided contains the
	# definition for EXCEPTION_DISPOSITION; if not, which is the case
	# with Cygwin's version as of 2002-04-10, define it to be int,
	# sufficient for getting the current code to work.
	#
	AC_CACHE_CHECK(for EXCEPTION_DISPOSITION support in include files,
	    tcl_cv_eh_disposition,
	    AC_TRY_COMPILE([
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#	    define WIN32_LEAN_AND_MEAN
#	    include <windows.h>
#	    undef WIN32_LEAN_AND_MEAN
	    ],[
	    ]], [[
		EXCEPTION_DISPOSITION x;
	    ],
		tcl_cv_eh_disposition=yes,
		tcl_cv_eh_disposition=no)
	    ]])],
		[tcl_cv_eh_disposition=yes],
		[tcl_cv_eh_disposition=no])
	)
	if test "$tcl_cv_eh_disposition" = "no" ; then
	AC_DEFINE(EXCEPTION_DISPOSITION, int,
		[Defined when cygwin/mingw does not support EXCEPTION DISPOSITION])
	fi

	# Check to see if winnt.h defines CHAR, SHORT, and LONG
	# even if VOID has already been #defined. The win32api
	# used by mingw and cygwin is known to do this.

	AC_CACHE_CHECK(for winnt.h that ignores VOID define,
	    tcl_cv_winnt_ignore_void,
	    AC_TRY_COMPILE([
		#define VOID void
		#define WIN32_LEAN_AND_MEAN
		#include <windows.h>
		#undef WIN32_LEAN_AND_MEAN
	    ], [
		CHAR c;
		SHORT s;
		LONG l;
	    ],
        tcl_cv_winnt_ignore_void=yes,
        tcl_cv_winnt_ignore_void=no)
	)
	if test "$tcl_cv_winnt_ignore_void" = "yes" ; then
	    AC_DEFINE(HAVE_WINNT_IGNORE_VOID, 1,
		    [Defined when cygwin/mingw ignores VOID define in winnt.h])
	fi

	AC_CHECK_HEADER(stdbool.h, [AC_DEFINE(HAVE_STDBOOL_H, 1, [Do we have <stdbool.h>?])],)

	# See if the compiler supports casting to a union type.
	# This is used to stop gcc from printing a compiler
	# warning when initializing a union member.

	AC_CACHE_CHECK(for cast to union support,
	    tcl_cv_cast_to_union,
	    AC_TRY_COMPILE([],
	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
	    [
		  union foo { int i; double d; };
		  union foo f = (union foo) (int) 0;
	    ],
	    tcl_cv_cast_to_union=yes,
	    tcl_cv_cast_to_union=no)
	    ]])],
	    [tcl_cv_cast_to_union=yes],
	    [tcl_cv_cast_to_union=no])
	)
	if test "$tcl_cv_cast_to_union" = "yes"; then
	    AC_DEFINE(HAVE_CAST_TO_UNION, 1,
		    [Defined when compiler supports casting to union type.])
	fi
    fi

    # DL_LIBS is empty, but then we match the Unix version
    AC_SUBST(DL_LIBS)
    AC_SUBST(CFLAGS_DEBUG)
    AC_SUBST(CFLAGS_OPTIMIZE)
    AC_SUBST(CFLAGS_WARNING)
    AC_SUBST(CFLAGS_NOLTO)
])

#------------------------------------------------------------------------
# SC_WITH_TCL --
#
#	Location of the Tcl build directory.
#
1001
1002
1003
1004
1005
1006
1007
1008

1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022

1023
1024
1025
1026
1027
1028
1029
1030







-
+







#	extension can't assume that an executable Tcl shell exists at
#	build time.
#
# Arguments
#	none
#
# Results
#	Subst's the following values:
#	Substitutes the following values:
#		TCLSH_PROG
#------------------------------------------------------------------------

AC_DEFUN([SC_PROG_TCLSH], [
    AC_MSG_CHECKING([for tclsh])

    AC_CACHE_VAL(ac_cv_path_tclsh, [
1047
1048
1049
1050
1051
1052
1053
1054

1055
1056
1057
1058
1059
1060

1061
1062
1063
1064
1065
1066
1067
1062
1063
1064
1065
1066
1067
1068

1069
1070
1071
1072
1073
1074

1075
1076
1077
1078
1079
1080
1081
1082







-
+





-
+







#	when running tests from an extension build directory. It is not
#	correct to use the TCLSH_PROG in cases like this.
#
# Arguments
#	none
#
# Results
#	Subst's the following values:
#	Substitutes the following values:
#		BUILD_TCLSH
#------------------------------------------------------------------------

AC_DEFUN([SC_BUILD_TCLSH], [
    AC_MSG_CHECKING([for tclsh in Tcl build directory])
    BUILD_TCLSH=${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}
    BUILD_TCLSH=${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}\${EXESUFFIX}
    AC_MSG_RESULT($BUILD_TCLSH)
    AC_SUBST(BUILD_TCLSH)
])

#--------------------------------------------------------------------
# SC_TCL_CFG_ENCODING	TIP #59
#
1103
1104
1105
1106
1107
1108
1109
1110

1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124

1125
1126
1127
1128
1129
1130
1131
1132







-
+







#		VC_MANIFEST_EMBED_EXE
#
#--------------------------------------------------------------------

AC_DEFUN([SC_EMBED_MANIFEST], [
    AC_MSG_CHECKING(whether to embed manifest)
    AC_ARG_ENABLE(embedded-manifest,
	AC_HELP_STRING([--enable-embedded-manifest],
	AS_HELP_STRING([--enable-embedded-manifest],
		[embed manifest if possible (default: yes)]),
	[embed_ok=$enableval], [embed_ok=yes])

    VC_MANIFEST_EMBED_DLL=
    VC_MANIFEST_EMBED_EXE=
    result=no
    if test "$embed_ok" = "yes" -a "${SHARED_BUILD}" = "1" \
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
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







-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+






    ZIP_PROG_VFSSEARCH=""
    ZIP_INSTALL_OBJS=""

    AC_MSG_CHECKING([for zip])
    AC_CACHE_VAL(ac_cv_path_zip, [
    search_path=`echo ${PATH} | sed -e 's/:/ /g'`
    for dir in $search_path ; do
        for j in `ls -r $dir/zip 2> /dev/null` \
            `ls -r $dir/zip 2> /dev/null` ; do
        if test x"$ac_cv_path_zip" = x ; then
            if test -f "$j" ; then
            ac_cv_path_zip=$j
            break
            fi
        fi
        done
	for j in `ls -r $dir/zip 2> /dev/null` \
	    `ls -r $dir/zip 2> /dev/null` ; do
	if test x"$ac_cv_path_zip" = x ; then
	    if test -f "$j" ; then
	    ac_cv_path_zip=$j
	    break
	    fi
	fi
	done
    done
    ])
    if test -f "$ac_cv_path_zip" ; then
        ZIP_PROG="$ac_cv_path_zip"
        AC_MSG_RESULT([$ZIP_PROG])
        ZIP_PROG_OPTIONS="-rq"
        ZIP_PROG_VFSSEARCH="*"
        AC_MSG_RESULT([Found INFO Zip in environment])
        # Use standard arguments for zip
	ZIP_PROG="$ac_cv_path_zip"
	AC_MSG_RESULT([$ZIP_PROG])
	ZIP_PROG_OPTIONS="-rq"
	ZIP_PROG_VFSSEARCH="*"
	AC_MSG_RESULT([Found INFO Zip in environment])
	# Use standard arguments for zip
    else
        # It is not an error if an installed version of Zip can't be located.
        # We can use the locally distributed minizip instead
        ZIP_PROG="./minizip${EXEEXT_FOR_BUILD}"
        ZIP_PROG_OPTIONS="-o -r"
        ZIP_PROG_VFSSEARCH="*"
        ZIP_INSTALL_OBJS="minizip${EXEEXT_FOR_BUILD}"
        AC_MSG_RESULT([No zip found on PATH building minizip])
	# It is not an error if an installed version of Zip can't be located.
	# We can use the locally distributed minizip instead
	ZIP_PROG="./minizip${EXEEXT_FOR_BUILD}"
	ZIP_PROG_OPTIONS="-o -r"
	ZIP_PROG_VFSSEARCH="*"
	ZIP_INSTALL_OBJS="minizip${EXEEXT_FOR_BUILD}"
	AC_MSG_RESULT([No zip found on PATH building minizip])
    fi
    AC_SUBST(ZIP_PROG)
    AC_SUBST(ZIP_PROG_OPTIONS)
    AC_SUBST(ZIP_PROG_VFSSEARCH)
    AC_SUBST(ZIP_INSTALL_OBJS)
])

Changes to win/tcl.rc.

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
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







-
+

-
+

-
+

-
+

-
-
-
+
+
+







-

-
+








#define SUFFIX		    SUFFIX_DEBUG


LANGUAGE 0x9, 0x1	/* LANG_ENGLISH, SUBLANG_DEFAULT */

VS_VERSION_INFO VERSIONINFO
 FILEVERSION 	TCL_MAJOR_VERSION,TCL_MINOR_VERSION,TCL_RELEASE_LEVEL,TCL_RELEASE_SERIAL
 FILEVERSION	TCL_MAJOR_VERSION,TCL_MINOR_VERSION,TCL_RELEASE_LEVEL,TCL_RELEASE_SERIAL
 PRODUCTVERSION TCL_MAJOR_VERSION,TCL_MINOR_VERSION,TCL_RELEASE_LEVEL,TCL_RELEASE_SERIAL
 FILEFLAGSMASK 	0x3fL
 FILEFLAGSMASK	0x3fL
#ifdef DEBUG
 FILEFLAGS 	VS_FF_DEBUG
 FILEFLAGS	VS_FF_DEBUG
#else
 FILEFLAGS 	0x0L
 FILEFLAGS	0x0L
#endif
 FILEOS 	VOS__WINDOWS32
 FILETYPE 	VFT_DLL
 FILESUBTYPE 	0x0L
 FILEOS	VOS__WINDOWS32
 FILETYPE	VFT_DLL
 FILESUBTYPE	0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0" /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP */
        BEGIN
            VALUE "FileDescription", "Tcl DLL\0"
            VALUE "OriginalFilename", "tcl" STRINGIFY(TCL_MAJOR_VERSION) STRINGIFY(TCL_MINOR_VERSION) SUFFIX ".dll\0"
            VALUE "CompanyName", "ActiveState Corporation\0"
            VALUE "FileVersion", TCL_PATCH_LEVEL
            VALUE "LegalCopyright", "Copyright \251 2001 by ActiveState Corporation, et al\0"
            VALUE "LegalCopyright", "Copyright \251 1987-2022 Regents of the University of California and other parties\0"
            VALUE "ProductName", "Tcl " TCL_VERSION " for Windows\0"
            VALUE "ProductVersion", TCL_PATCH_LEVEL
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200

Changes to win/tclAppInit.c.

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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
-
-
-
-
-
-
-
-
-
-
-







 * Copyright (c) 1998-1999 Scriptics Corporation.
 *
 * 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
extern Tcl_LibraryInitProc Tcltest_Init;
extern Tcl_LibraryInitProc Tcltest_SafeInit;
#endif /* TCL_TEST */

#if defined(STATIC_BUILD)
extern Tcl_LibraryInitProc Registry_Init;
extern Tcl_LibraryInitProc Dde_Init;
extern Tcl_LibraryInitProc Dde_SafeInit;
#endif

#define WIN32_LEAN_AND_MEAN
#define STRICT			/* See MSDN Article Q83456 */
#include <windows.h>
#undef STRICT
#undef WIN32_LEAN_AND_MEAN
#include <locale.h>
#include <stdlib.h>
#include <tchar.h>

#ifdef TCL_TEST
extern Tcl_PackageInitProc Tcltest_Init;
extern Tcl_PackageInitProc Tcltest_SafeInit;
#endif /* TCL_TEST */

#if defined(STATIC_BUILD) && defined(TCL_USE_STATIC_PACKAGES) && TCL_USE_STATIC_PACKAGES
extern Tcl_PackageInitProc Registry_Init;
extern Tcl_PackageInitProc Dde_Init;
extern Tcl_PackageInitProc Dde_SafeInit;
#endif

#if defined(__GNUC__) || defined(TCL_BROKEN_MAINARGS)
int _CRT_glob = 0;
#endif /* __GNUC__ || TCL_BROKEN_MAINARGS */
#ifdef TCL_BROKEN_MAINARGS
static void setargv(int *argcPtr, TCHAR ***argvPtr);
#endif /* TCL_BROKEN_MAINARGS */

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
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







-
+


-






-

+







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

#ifdef TCL_BROKEN_MAINARGS
int
main(
    int argc,			/* Number of command-line arguments. */
    char **argv1)
    char **argv1)		/* Not used. */
{
    TCHAR **argv;
    TCHAR *p;
#else
int
_tmain(
    int argc,			/* Number of command-line arguments. */
    TCHAR *argv[])		/* Values of command-line arguments. */
{
    TCHAR *p;
#endif
    TCHAR *p;

    /*
     * Set up the default locale to be standard "C" locale so parsing is
     * performed correctly.
     */

    setlocale(LC_ALL, "C");
124
125
126
127
128
129
130
131
132


133
134
135
136
137
138
139
132
133
134
135
136
137
138


139
140
141
142
143
144
145
146
147







-
-
+
+







	if (*p == '\\') {
	    *p = '/';
	}
    }

#ifdef TCL_LOCAL_MAIN_HOOK
    TCL_LOCAL_MAIN_HOOK(&argc, &argv);
#elif !defined(_WIN32) || defined(UNICODE)
    /* This doesn't work on Windows without UNICODE */
#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. */
}

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
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







-
+



-
+



-
+




-
+






-
+















-
+










+
-
-
+
+
+







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

int
Tcl_AppInit(
    Tcl_Interp *interp)		/* Interpreter for application. */
{
    if ((Tcl_Init)(interp) == TCL_ERROR) {
    if (Tcl_Init(interp) == TCL_ERROR) {
	return TCL_ERROR;
    }

#if defined(STATIC_BUILD) && defined(TCL_USE_STATIC_PACKAGES) && TCL_USE_STATIC_PACKAGES
#if defined(STATIC_BUILD)
    if (Registry_Init(interp) == TCL_ERROR) {
	return TCL_ERROR;
    }
    Tcl_StaticPackage(interp, "registry", Registry_Init, NULL);
    Tcl_StaticLibrary(interp, "Registry", Registry_Init, NULL);

    if (Dde_Init(interp) == TCL_ERROR) {
	return TCL_ERROR;
    }
    Tcl_StaticPackage(interp, "dde", Dde_Init, Dde_SafeInit);
    Tcl_StaticLibrary(interp, "Dde", Dde_Init, Dde_SafeInit);
#endif

#ifdef TCL_TEST
    if (Tcltest_Init(interp) == TCL_ERROR) {
	return TCL_ERROR;
    }
    Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init, Tcltest_SafeInit);
    Tcl_StaticLibrary(interp, "Tcltest", Tcltest_Init, Tcltest_SafeInit);
#endif /* TCL_TEST */

    /*
     * Call the init procedures for included packages. Each call should look
     * like this:
     *
     * if (Mod_Init(interp) == TCL_ERROR) {
     *     return TCL_ERROR;
     * }
     *
     * where "Mod" is the name of the module. (Dynamically-loadable packages
     * should have the same entry-point name.)
     */

    /*
     * Call Tcl_CreateCommand for application-specific commands, if they
     * Call Tcl_CreateObjCommand for application-specific commands, if they
     * weren't already created by the init procedures called above.
     */

    /*
     * Specify a user-specific startup file to invoke if the application is
     * run interactively. Typically the startup file is "~/.apprc" where "app"
     * is the name of the application. If this line is deleted then no
     * user-specific startup file will be run under any conditions.
     */

    (void)Tcl_EvalEx(interp,
    (Tcl_ObjSetVar2)(interp, Tcl_NewStringObj("tcl_rcFileName", -1), NULL,
	    Tcl_NewStringObj("~/tclshrc.tcl", -1), TCL_GLOBAL_ONLY);
	    "set tcl_rcFileName [file tildeexpand ~/tclshrc.tcl]",
	    TCL_AUTO_LENGTH, TCL_EVAL_GLOBAL);

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

Changes to win/tclConfig.sh.in.

37
38
39
40
41
42
43
44

45
46
47
48
49
50
51
52
53
54
55
56
57
37
38
39
40
41
42
43

44






45
46
47
48
49
50
51







-
+
-
-
-
-
-
-







# The name of the Tcl library (may be either a .a file or a shared library):
TCL_LIB_FILE='@TCL_LIB_FILE@'

# The name of a zip containing the /library and /encodings (may be either a .zip file or a shared library):
TCL_ZIP_FILE='@TCL_ZIP_FILE@'

# Flag to indicate whether shared libraries need export files.
TCL_NEEDS_EXP_FILE=@TCL_NEEDS_EXP_FILE@
TCL_NEEDS_EXP_FILE=''

# String that can be evaluated to generate the part of the export file
# name that comes after the "libxxx" (includes version number, if any,
# extension, and anything else needed).  May depend on the variables
# VERSION.  On most UNIX systems this is ${VERSION}.exp.
TCL_EXPORT_FILE_SUFFIX='@CFG_TCL_EXPORT_FILE_SUFFIX@'

# Additional libraries to use when linking Tcl.
TCL_LIBS='@LIBS@'

# Top-level directory in which Tcl's platform-independent files are
# installed.
TCL_PREFIX='@prefix@'
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
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







-
+









-
-
+
+







TCL_SHLIB_LD_LIBS='@SHLIB_LD_LIBS@'

# Suffix to use for the name of a shared library.
TCL_SHLIB_SUFFIX='@SHLIB_SUFFIX@'

# Library file(s) to include in tclsh and other base applications
# in order to provide facilities needed by DLOBJ above.
TCL_DL_LIBS='@DL_LIBS@'
TCL_DL_LIBS=''

# Flags to pass to the compiler when linking object files into
# an executable tclsh or tcltest binary.
TCL_LD_FLAGS='@LDFLAGS@'

# Flags to pass to cc/ld, such as "-R /usr/local/tcl/lib", that tell the
# run-time dynamic linker where to look for shared libraries such as
# libtcl.so.  Used when linking applications.  Only works if there
# is a variable "LIB_RUNTIME_DIR" defined in the Makefile.
TCL_CC_SEARCH_FLAGS='@TCL_CC_SEARCH_FLAGS@'
TCL_LD_SEARCH_FLAGS='@TCL_LD_SEARCH_FLAGS@'
TCL_CC_SEARCH_FLAGS=''
TCL_LD_SEARCH_FLAGS=''

# Additional object files linked with Tcl to provide compatibility
# with standard facilities from ANSI C or POSIX.
TCL_COMPAT_OBJS='@LIBOBJS@'

# Name of the ranlib program to use.
TCL_RANLIB='@RANLIB@'
120
121
122
123
124
125
126
127

128
129
130
131
132
133
134
114
115
116
117
118
119
120

121
122
123
124
125
126
127
128







-
+







# find installed Tcl headers.
TCL_INCLUDE_SPEC='@TCL_INCLUDE_SPEC@'

# Indicates whether a version numbers should be used in -l switches
# ("ok" means it's safe to use switches like -ltcl7.5;  "nodots" means
# use switches like -ltcl75).  SunOS and FreeBSD require "nodots", for
# example.
TCL_LIB_VERSIONS_OK='@TCL_LIB_VERSIONS_OK@'
TCL_LIB_VERSIONS_OK='nodots'

# String that can be evaluated to generate the part of a shared library
# name that comes after the "libxxx" (includes version number, if any,
# extension, and anything else needed).  May depend on the variables
# VERSION and SHLIB_SUFFIX.  On most UNIX systems this is
# ${VERSION}${SHLIB_SUFFIX}.
TCL_SHARED_LIB_SUFFIX='@CFG_TCL_SHARED_LIB_SUFFIX@'
170
171
172
173
174
175
176






164
165
166
167
168
169
170
171
172
173
174
175
176







+
+
+
+
+
+
TCL_STUB_LIB_SPEC='@TCL_STUB_LIB_SPEC@'

# Path to the Tcl stub library in the build directory.
TCL_BUILD_STUB_LIB_PATH='@TCL_BUILD_STUB_LIB_PATH@'

# Path to the Tcl stub library in the install directory.
TCL_STUB_LIB_PATH='@TCL_STUB_LIB_PATH@'

# Name of the zlib library that extensions should use
TCL_ZLIB_LIB_NAME='@TCL_ZLIB_LIB_NAME@'

# Name of the tommath library that extensions should use
TCL_TOMMATH_LIB_NAME='@TCL_TOMMATH_LIB_NAME@'

Added win/tclUuid.h.in.


1
+
#define TCL_VERSION_UUID \

Changes to win/tclWin32Dll.c.

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
30
31
32
33
34
35
36
37
38
39
40
41
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
30
31
32
33






-
-
+
+


















-
-
-
-
-
-
-
-







/*
 * tclWin32Dll.c --
 *
 *	This file contains the DLL entry point and other low-level bit bashing
 *	code that needs inline assembly.
 *
 * Copyright (c) 1995-1996 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 Scriptics Corporation.
 * Copyright © 1995-1996 Sun Microsystems, Inc.
 * Copyright © 1998-2000 Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclWinInt.h"
#if defined(HAVE_INTRIN_H)
#   include <intrin.h>
#endif

/*
 * The following variables keep track of information about this DLL on a
 * per-instance basis. Each time this DLL is loaded, it gets its own new data
 * segment with its own copy of all static and global information.
 */

static HINSTANCE hInstance;	/* HINSTANCE of this DLL. */

/*
 * VC++ 5.x has no 'cpuid' assembler instruction, so we must emulate it
 */

#if defined(_MSC_VER) && (_MSC_VER <= 1100) && defined (_M_IX86)
#define cpuid	__asm __emit 0fh __asm __emit 0a2h
#endif

/*
 * The following declaration is for the VC++ DLL entry point.
 */

BOOL APIENTRY		DllMain(HINSTANCE hInst, DWORD reason,
			    LPVOID reserved);

181
182
183
184
185
186
187
188
189


190
191
192
193

194
195
196
197
198
199
200
173
174
175
176
177
178
179


180
181
182
183
184

185
186
187
188
189
190
191
192







-
-
+
+



-
+







    OSVERSIONINFOW os;

    hInstance = hInst;
    os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
    GetVersionExW(&os);

    /*
     * We no longer support Win32s or Win9x or Windows CE, so just in case
     * someone manages to get a runtime there, make sure they know that.
     * We no longer support Win32s or Win9x or Windows CE or Windows XP, so just
     * in case someone manages to get a runtime there, make sure they know that.
     */

    if (os.dwPlatformId != VER_PLATFORM_WIN32_NT) {
	Tcl_Panic("Windows NT is the only supported platform");
	Tcl_Panic("Windows 7 is the minimum supported platform");
    }
}

/*
 *-------------------------------------------------------------------------
 *
 * TclWinNoBackslash --
383
384
385
386
387
388
389
390

391
392
393
394
395
396
397
375
376
377
378
379
380
381

382
383
384
385
386
387
388
389







-
+







		    alreadyStored = 1;
		    break;
		}
	    }
	    if (!alreadyStored) {
		dlPtr2 = (MountPointMap *)Tcl_Alloc(sizeof(MountPointMap));
		dlPtr2->volumeName = (WCHAR *)TclNativeDupInternalRep(Target);
		dlPtr2->driveLetter = (char) drive[0];
		dlPtr2->driveLetter = (WCHAR) drive[0];
		dlPtr2->nextPtr = driveLetterLookup;
		driveLetterLookup = dlPtr2;
	    }
	}
    }

    /*
409
410
411
412
413
414
415
416

417
418
419
420
421
422
423
401
402
403
404
405
406
407

408
409
410
411
412
413
414
415







-
+







    /*
     * The volume doesn't appear to correspond to a drive letter - we remember
     * that fact and store '-1' so we don't have to look it up each time.
     */

    dlPtr2 = (MountPointMap *)Tcl_Alloc(sizeof(MountPointMap));
    dlPtr2->volumeName = (WCHAR *)TclNativeDupInternalRep((void *)mountPoint);
    dlPtr2->driveLetter = -1;
    dlPtr2->driveLetter = (WCHAR)-1;
    dlPtr2->nextPtr = driveLetterLookup;
    driveLetterLookup = dlPtr2;
    Tcl_MutexUnlock(&mountPointMap);
    return -1;
}

/*
441
442
443
444
445
446
447
448

449
450
451
452
453

454
455
456
457
458
459
460
433
434
435
436
437
438
439

440
441
442
443
444

445
446
447
448
449
450
451
452







-
+




-
+







int
TclWinCPUID(
    int index,		/* Which CPUID value to retrieve. */
    int *regsPtr)	/* Registers after the CPUID. */
{
    int status = TCL_ERROR;

#if defined(HAVE_INTRIN_H) && defined(_WIN64)
#if defined(HAVE_INTRIN_H) && defined(_WIN64) && defined(HAVE_CPUID)

    __cpuid((int *)regsPtr, index);
    status = TCL_OK;

#elif defined(__GNUC__)
#elif defined(__GNUC__) && defined(HAVE_CPUID)
#   if defined(_WIN64)
    /*
     * Execute the CPUID instruction with the given index, and store results
     * off 'regPtr'.
     */

    __asm__ __volatile__(
562
563
564
565
566
567
568
569

570
571
572
573
574
575
576
554
555
556
557
558
559
560

561
562
563
564
565
566
567
568







-
+







	[ok]		"i"	(TCL_OK),
	[error]		"i"	(TCL_ERROR)
	:
	"%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
    status = registration.status;

#   endif /* !_WIN64 */
#elif defined(_MSC_VER)
#elif defined(_MSC_VER) && defined(HAVE_CPUID)
#   if defined(_WIN64)

    __cpuid(regsPtr, index);
    status = TCL_OK;

#   elif defined (_M_IX86)
    /*
617
618
619
620
621
622
623


624
625
626
627
628
629
630
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624







+
+







	status = TCL_OK;
    } __except(EXCEPTION_EXECUTE_HANDLER) {
	/* do nothing */
    }

#   endif
#else
    (void)index;
    (void)regsPtr;
    /*
     * Don't know how to do assembly code for this compiler and/or
     * architecture.
     */
#endif
    return status;
}

Changes to win/tclWinChan.c.

1
2
3
4
5
6
7

8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21






-
+






+







/*
 * tclWinChan.c
 *
 *	Channel drivers for Windows channels based on files, command pipes and
 *	TCP sockets.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclWinInt.h"
#include "tclFileSystem.h"
#include "tclIO.h"

/*
 * State flags used in the info structures below.
 */

#define FILE_PENDING	(1<<0)	/* Message is pending in the queue. */
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
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







-
-
-
-
+
+
+
+


-
-
+
+
+
+
+

-
+

-
+

-
-
-
-
-
+
+
+
+
+

-
-
+
+


+
+






-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







				 * pointer. */
} FileEvent;

/*
 * Static routines for this file:
 */

static int		FileBlockProc(ClientData instanceData, int mode);
static void		FileChannelExitHandler(ClientData clientData);
static void		FileCheckProc(ClientData clientData, int flags);
static int		FileCloseProc(ClientData instanceData,
static int		FileBlockProc(void *instanceData, int mode);
static void		FileChannelExitHandler(void *clientData);
static void		FileCheckProc(void *clientData, int flags);
static int		FileCloseProc(void *instanceData,
			    Tcl_Interp *interp, int flags);
static int		FileEventProc(Tcl_Event *evPtr, int flags);
static int		FileGetHandleProc(ClientData instanceData,
			    int direction, ClientData *handlePtr);
static int		FileGetHandleProc(void *instanceData,
			    int direction, void **handlePtr);
static int		FileGetOptionProc(void *instanceData,
			    Tcl_Interp *interp, const char *optionName,
			    Tcl_DString *dsPtr);
static ThreadSpecificData *FileInit(void);
static int		FileInputProc(ClientData instanceData, char *buf,
static int		FileInputProc(void *instanceData, char *buf,
			    int toRead, int *errorCode);
static int		FileOutputProc(ClientData instanceData,
static int		FileOutputProc(void *instanceData,
			    const char *buf, int toWrite, int *errorCode);
static Tcl_WideInt	FileWideSeekProc(ClientData instanceData,
			    Tcl_WideInt offset, int mode, int *errorCode);
static void		FileSetupProc(ClientData clientData, int flags);
static void		FileWatchProc(ClientData instanceData, int mask);
static void		FileThreadActionProc(ClientData instanceData,
static long long	FileWideSeekProc(void *instanceData,
			    long long offset, int mode, int *errorCode);
static void		FileSetupProc(void *clientData, int flags);
static void		FileWatchProc(void *instanceData, int mask);
static void		FileThreadActionProc(void *instanceData,
			    int action);
static int		FileTruncateProc(ClientData instanceData,
			    Tcl_WideInt length);
static int		FileTruncateProc(void *instanceData,
			    long long length);
static DWORD		FileGetType(HANDLE handle);
static int		NativeIsComPort(const WCHAR *nativeName);
static Tcl_Channel	OpenFileChannel(HANDLE handle, char *channelName,
			    int permissions, int appendMode);

/*
 * This structure describes the channel type structure for file based IO.
 */

static const Tcl_ChannelType fileChannelType = {
    "file",			/* Type name. */
    TCL_CHANNEL_VERSION_5,	/* v5 channel */
    NULL,		/* Close proc. */
    FileInputProc,		/* Input proc. */
    FileOutputProc,		/* Output proc. */
	NULL,
    "file",
    TCL_CHANNEL_VERSION_5,
    NULL,			/* Deprecated. */
    FileInputProc,
    FileOutputProc,
    NULL,			/* Deprecated. */
    NULL,			/* Set option proc. */
    NULL,			/* Get option proc. */
    FileWatchProc,		/* Set up the notifier to watch the channel. */
    FileGetHandleProc,		/* Get an OS handle from channel. */
    FileCloseProc,		/* close2proc. */
    FileBlockProc,		/* Set blocking or non-blocking mode.*/
    NULL,			/* flush proc. */
    NULL,			/* handler proc. */
    FileWideSeekProc,		/* Wide seek proc. */
    FileThreadActionProc,	/* Thread action proc. */
    FileTruncateProc		/* Truncate proc. */
    FileGetOptionProc,
    FileWatchProc,
    FileGetHandleProc,
    FileCloseProc,
    FileBlockProc,
    NULL,			/* Flush proc. */
    NULL,			/* Bubbled event handler proc. */
    FileWideSeekProc,
    FileThreadActionProc,
    FileTruncateProc
};

/*
 * General useful clarification macros.
 */

#define SET_FLAG(var, flag)	((var) |= (flag))
#define CLEAR_FLAG(var, flag)	((var) &= ~(flag))
#define TEST_FLAG(value, flag)	(((value) & (flag)) != 0)

/*
 * The number of 100-ns intervals between the Windows system epoch (1601-01-01
 * on the proleptic Gregorian calendar) and the Posix epoch (1970-01-01).
 */

#define POSIX_EPOCH_AS_FILETIME	\
	((long long) 116444736 * (long long) 1000000000)

/*
 *----------------------------------------------------------------------
 *
 * TclWinGenerateChannelName --
 *
 *	This function generates names for channels.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Creates a new window and creates an exit handler.
 *
 *----------------------------------------------------------------------
 */
void
TclWinGenerateChannelName(
    char channelName[],		/* Buffer to accept the name. */
    const char *channelTypeName,/* Name of type of channel. */
    void *channelImpl)		/* Pointer to channel implementation
				 * structure, used to generate a unique
				 * ID. */
{
    snprintf(channelName, 16 + TCL_INTEGER_SPACE, "%s%" TCL_Z_MODIFIER "x",
	    channelTypeName, (size_t) channelImpl);
}

/*
 *----------------------------------------------------------------------
 *
 * FileInit --
 *
 *	This function creates the window used to simulate file events.
174
175
176
177
178
179
180
181

182
183
184
185
186
187
188
215
216
217
218
219
220
221

222
223
224
225
226
227
228
229







-
+







 *	Destroys the communication window.
 *
 *----------------------------------------------------------------------
 */

static void
FileChannelExitHandler(
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    Tcl_DeleteEventSource(FileSetupProc, FileCheckProc, NULL);
}

/*
 *----------------------------------------------------------------------
 *
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
239
240
241
242
243
244
245

246
247
248
249
250
251
252
253







-
+







 *	Adjusts the block time if needed.
 *
 *----------------------------------------------------------------------
 */

void
FileSetupProc(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */
{
    FileInfo *infoPtr;
    Tcl_Time blockTime = { 0, 0 };
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (!TEST_FLAG(flags, TCL_FILE_EVENTS)) {
241
242
243
244
245
246
247
248

249
250
251
252
253
254
255
282
283
284
285
286
287
288

289
290
291
292
293
294
295
296







-
+







 *	May queue an event.
 *
 *----------------------------------------------------------------------
 */

static void
FileCheckProc(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */
{
    FileEvent *evPtr;
    FileInfo *infoPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (!TEST_FLAG(flags, TCL_FILE_EVENTS)) {
340
341
342
343
344
345
346
347

348
349
350
351
352
353
354
381
382
383
384
385
386
387

388
389
390
391
392
393
394
395







-
+







 *	Sets the device into blocking or non-blocking mode.
 *
 *----------------------------------------------------------------------
 */

static int
FileBlockProc(
    ClientData instanceData,	/* Instance data for channel. */
    void *instanceData,	/* Instance data for channel. */
    int mode)			/* TCL_MODE_BLOCKING or
				 * TCL_MODE_NONBLOCKING. */
{
    FileInfo *infoPtr = (FileInfo *)instanceData;

    /*
     * Files on Windows can not be switched between blocking and nonblocking,
379
380
381
382
383
384
385
386

387
388
389
390
391
392
393
420
421
422
423
424
425
426

427
428
429
430
431
432
433
434







-
+







 *	Closes the physical channel
 *
 *----------------------------------------------------------------------
 */

static int
FileCloseProc(
    ClientData instanceData,	/* Pointer to FileInfo structure. */
    void *instanceData,	/* Pointer to FileInfo structure. */
    TCL_UNUSED(Tcl_Interp *),
    int flags)
{
    FileInfo *fileInfoPtr = (FileInfo *)instanceData;
    FileInfo *infoPtr;
    ThreadSpecificData *tsdPtr;
    int errorCode = 0;
409
410
411
412
413
414
415
416

417
418
419
420
421
422
423
450
451
452
453
454
455
456

457
458
459
460
461
462
463
464







-
+







     */

    if (!TclInThreadExit()
	    || ((GetStdHandle(STD_INPUT_HANDLE) != fileInfoPtr->handle)
	    &&  (GetStdHandle(STD_OUTPUT_HANDLE) != fileInfoPtr->handle)
	    &&  (GetStdHandle(STD_ERROR_HANDLE) != fileInfoPtr->handle))) {
	if (CloseHandle(fileInfoPtr->handle) == FALSE) {
	    TclWinConvertError(GetLastError());
	    Tcl_WinConvertError(GetLastError());
	    errorCode = errno;
	}
    }

    /*
     * See if this FileInfo* is still on the thread local list.
     */
455
456
457
458
459
460
461
462

463
464
465


466
467
468
469
470
471
472
496
497
498
499
500
501
502

503
504


505
506
507
508
509
510
511
512
513







-
+

-
-
+
+







 * Side effects:
 *	Moves the location at which the channel will be accessed in future
 *	operations.
 *
 *----------------------------------------------------------------------
 */

static Tcl_WideInt
static long long
FileWideSeekProc(
    ClientData instanceData,	/* File state. */
    Tcl_WideInt offset,		/* Offset to seek to. */
    void *instanceData,	/* File state. */
    long long offset,		/* Offset to seek to. */
    int mode,			/* Relative to where should we seek? */
    int *errorCodePtr)		/* To store error code. */
{
    FileInfo *infoPtr = (FileInfo *)instanceData;
    DWORD moveMethod;
    LONG newPos, newPosHigh;

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
558
559

560
561
562
563
564
565
566
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572

573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588

589
590
591
592
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607







-
+




-
-
+
+




















-
-
+
+














-
+















-
+










-
+







    newPosHigh = (LONG)(offset >> 32);
    newPos = SetFilePointer(infoPtr->handle, (LONG)offset,
	    &newPosHigh, moveMethod);
    if (newPos == (LONG) INVALID_SET_FILE_POINTER) {
	DWORD winError = GetLastError();

	if (winError != NO_ERROR) {
	    TclWinConvertError(winError);
	    Tcl_WinConvertError(winError);
	    *errorCodePtr = errno;
	    return -1;
	}
    }
    return (((Tcl_WideInt)((unsigned)newPos))
	    | ((Tcl_WideInt)newPosHigh << 32));
    return (((long long)((unsigned)newPos))
	    | ((long long)newPosHigh << 32));
}

/*
 *----------------------------------------------------------------------
 *
 * FileTruncateProc --
 *
 *	Truncates a file-based channel. Returns the error code.
 *
 * Results:
 *	0 if successful, POSIX-y error code if it failed.
 *
 * Side effects:
 *	Truncates the file, may move file pointers too.
 *
 *----------------------------------------------------------------------
 */

static int
FileTruncateProc(
    ClientData instanceData,	/* File state. */
    Tcl_WideInt length)		/* Length to truncate at. */
    void *instanceData,	/* File state. */
    long long length)		/* Length to truncate at. */
{
    FileInfo *infoPtr = (FileInfo *)instanceData;
    LONG newPos, newPosHigh, oldPos, oldPosHigh;

    /*
     * Save where we were...
     */

    oldPosHigh = 0;
    oldPos = SetFilePointer(infoPtr->handle, 0, &oldPosHigh, FILE_CURRENT);
    if (oldPos == (LONG) INVALID_SET_FILE_POINTER) {
	DWORD winError = GetLastError();

	if (winError != NO_ERROR) {
	    TclWinConvertError(winError);
	    Tcl_WinConvertError(winError);
	    return errno;
	}
    }

    /*
     * Move to where we want to truncate
     */

    newPosHigh = (LONG)(length >> 32);
    newPos = SetFilePointer(infoPtr->handle, (LONG)length,
	    &newPosHigh, FILE_BEGIN);
    if (newPos == (LONG) INVALID_SET_FILE_POINTER) {
	DWORD winError = GetLastError();

	if (winError != NO_ERROR) {
	    TclWinConvertError(winError);
	    Tcl_WinConvertError(winError);
	    return errno;
	}
    }

    /*
     * Perform the truncation (unlike POSIX ftruncate(), we needed to move to
     * the location to truncate at first).
     */

    if (!SetEndOfFile(infoPtr->handle)) {
	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	return errno;
    }

    /*
     * Move back. If this last step fails, we don't care; it's just a "best
     * effort" attempt to restore our file pointer to where it was.
     */
585
586
587
588
589
590
591
592

593
594
595
596
597
598
599
626
627
628
629
630
631
632

633
634
635
636
637
638
639
640







-
+







 *	Reads input from the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
FileInputProc(
    ClientData instanceData,	/* File state. */
    void *instanceData,	/* File state. */
    char *buf,			/* Where to store data read. */
    int bufSize,		/* Num bytes available in buffer. */
    int *errorCode)		/* Where to store error code. */
{
    FileInfo *infoPtr = (FileInfo *)instanceData;
    DWORD bytesRead;

609
610
611
612
613
614
615
616

617
618
619

620
621
622
623
624
625
626
650
651
652
653
654
655
656

657
658
659

660
661
662
663
664
665
666
667







-
+


-
+







     * write a console driver. We should probably do this at some point, but
     * for now, we just block. The same problem exists for files being read
     * over the network.
     */

    if (ReadFile(infoPtr->handle, (LPVOID) buf, (DWORD) bufSize, &bytesRead,
	    (LPOVERLAPPED) NULL) != FALSE) {
	return bytesRead;
	return (int)bytesRead;
    }

    TclWinConvertError(GetLastError());
    Tcl_WinConvertError(GetLastError());
    *errorCode = errno;
    if (errno == EPIPE) {
	return 0;
    }
    return -1;
}

640
641
642
643
644
645
646
647

648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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
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
707
708

709
710
711
712
713

714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734

735
736
737
738
739
740
741
742







-
+




















-
+




-
+




















-
+







 *	Writes output on the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
FileOutputProc(
    ClientData instanceData,	/* File state. */
    void *instanceData,	/* File state. */
    const char *buf,		/* The data buffer. */
    int toWrite,		/* How many bytes to write? */
    int *errorCode)		/* Where to store error code. */
{
    FileInfo *infoPtr = (FileInfo *)instanceData;
    DWORD bytesWritten;

    *errorCode = 0;

    /*
     * If we are writing to a file that was opened with O_APPEND, we need to
     * seek to the end of the file before writing the current buffer.
     */

    if (TEST_FLAG(infoPtr->flags, FILE_APPEND)) {
	SetFilePointer(infoPtr->handle, 0, NULL, FILE_END);
    }

    if (WriteFile(infoPtr->handle, (LPVOID) buf, (DWORD) toWrite,
	    &bytesWritten, (LPOVERLAPPED) NULL) == FALSE) {
	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	*errorCode = errno;
	return -1;
    }
    infoPtr->dirty = 1;
    return bytesWritten;
    return (int)bytesWritten;
}

/*
 *----------------------------------------------------------------------
 *
 * FileWatchProc --
 *
 *	Called by the notifier to set up to watch for events on this channel.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
FileWatchProc(
    ClientData instanceData,	/* File state. */
    void *instanceData,	/* File state. */
    int mask)			/* What events to watch for; OR-ed combination
				 * of TCL_READABLE, TCL_WRITABLE and
				 * TCL_EXCEPTION. */
{
    FileInfo *infoPtr = (FileInfo *)instanceData;
    Tcl_Time blockTime = { 0, 0 };

726
727
728
729
730
731
732
733

734
735

736
737
738
739
740
741
742
743

744
745














































































































































































746
747
748
749
750
751
752
767
768
769
770
771
772
773

774
775

776
777
778
779
780
781
782
783

784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967







-
+

-
+







-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileGetHandleProc(
    ClientData instanceData,	/* The file state. */
    void *instanceData,	/* The file state. */
    int direction,		/* TCL_READABLE or TCL_WRITABLE */
    ClientData *handlePtr)	/* Where to store the handle.  */
    void **handlePtr)	/* Where to store the handle.  */
{
    FileInfo *infoPtr = (FileInfo *)instanceData;

    if (!TEST_FLAG(direction, infoPtr->validMask)) {
	return TCL_ERROR;
    }

    *handlePtr = (ClientData) infoPtr->handle;
    *handlePtr = (void *)infoPtr->handle;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * FileGetOptionProc --
 *
 *	Gets an option associated with an open file. If the optionName arg is
 *	non-NULL, retrieves the value of that option. If the optionName arg is
 *	NULL, retrieves a list of alternating option names and values for the
 *	given channel.
 *
 * Results:
 *	A standard Tcl result. Also sets the supplied DString to the string
 *	value of the option(s) returned.  Sets error message if needed
 *	(by calling Tcl_BadChannelOption).
 *
 *----------------------------------------------------------------------
 */

static inline ULONGLONG
CombineDwords(
    DWORD hi,
    DWORD lo)
{
    ULARGE_INTEGER converter;

    converter.LowPart = lo;
    converter.HighPart = hi;
    return converter.QuadPart;
}

static inline time_t
ToCTime(
    FILETIME fileTime)		/* UTC time */
{
    LARGE_INTEGER convertedTime;

    convertedTime.LowPart = fileTime.dwLowDateTime;
    convertedTime.HighPart = (LONG) fileTime.dwHighDateTime;

    return (time_t) ((convertedTime.QuadPart -
	    (long long) POSIX_EPOCH_AS_FILETIME) / (long long) 10000000);
}

static Tcl_Obj *
StatOpenFile(
    FileInfo *infoPtr)
{
    DWORD attr;
    int dev, nlink = 1;
    unsigned short mode;
    unsigned long long size, inode;
    long long atime, ctime, mtime;
    BY_HANDLE_FILE_INFORMATION data;
    Tcl_Obj *dictObj;

    if (GetFileInformationByHandle(infoPtr->handle, &data) != TRUE) {
	Tcl_SetErrno(ENOENT);
	return NULL;
    }

    atime = ToCTime(data.ftLastAccessTime);
    mtime = ToCTime(data.ftLastWriteTime);
    ctime = ToCTime(data.ftCreationTime);
    attr = data.dwFileAttributes;
    size = CombineDwords(data.nFileSizeHigh, data.nFileSizeLow);
    nlink = data.nNumberOfLinks;

    /*
     * Unfortunately our stat definition's inode field (unsigned short) will
     * throw away most of the precision we have here, which means we can't
     * rely on inode as a unique identifier of a file. We'd really like to do
     * something like how we handle 'st_size'.
     */

    inode = CombineDwords(data.nFileIndexHigh, data.nFileIndexLow);

    dev = data.dwVolumeSerialNumber;

    /*
     * Note that this code has no idea whether the file can be executed.
     */

    mode = (attr & FILE_ATTRIBUTE_DIRECTORY) ? S_IFDIR|S_IEXEC : S_IFREG;
    mode |= (attr & FILE_ATTRIBUTE_READONLY) ? S_IREAD : S_IREAD|S_IWRITE;
    mode |= (mode & (S_IREAD|S_IWRITE|S_IEXEC)) >> 3;
    mode |= (mode & (S_IREAD|S_IWRITE|S_IEXEC)) >> 6;

    /*
     * We don't construct a Tcl_StatBuf; we're using the info immediately.
     */

    TclNewObj(dictObj);
#define STORE_ELEM(name, value) TclDictPut(NULL, dictObj, name, value)

    STORE_ELEM("dev",      Tcl_NewWideIntObj((long) dev));
    STORE_ELEM("ino",      Tcl_NewWideIntObj((long long) inode));
    STORE_ELEM("nlink",    Tcl_NewIntObj(nlink));
    STORE_ELEM("uid",      Tcl_NewIntObj(0));
    STORE_ELEM("gid",      Tcl_NewIntObj(0));
    STORE_ELEM("size",     Tcl_NewWideIntObj((long long) size));
    STORE_ELEM("atime",    Tcl_NewWideIntObj(atime));
    STORE_ELEM("mtime",    Tcl_NewWideIntObj(mtime));
    STORE_ELEM("ctime",    Tcl_NewWideIntObj(ctime));
    STORE_ELEM("mode",     Tcl_NewWideIntObj(mode));

    /*
     * Windows only has files and directories, as far as we're concerned.
     * Anything else and we definitely couldn't have got here anyway.
     */
    if (attr & FILE_ATTRIBUTE_DIRECTORY) {
	STORE_ELEM("type", Tcl_NewStringObj("directory", TCL_INDEX_NONE));
    } else {
	STORE_ELEM("type", Tcl_NewStringObj("file", TCL_INDEX_NONE));
    }
#undef STORE_ELEM

    return dictObj;
}

static int
FileGetOptionProc(
    void *instanceData,	/* The file state. */
    Tcl_Interp *interp,		/* For error reporting. */
    const char *optionName,	/* What option to read, or NULL for all. */
    Tcl_DString *dsPtr)		/* Where to write the value read. */
{
    FileInfo *infoPtr = (FileInfo *)instanceData;
    int valid = 0;		/* Flag if valid option parsed. */
    int len;

    if (optionName == NULL) {
	len = 0;
	valid = 1;
    } else {
	len = strlen(optionName);
    }

    /*
     * Get option -stat
     * Option is readonly and returned by [fconfigure chan -stat] but not
     * returned by [fconfigure chan] without explicit option name.
     */

    if ((len > 1) && (strncmp(optionName, "-stat", len) == 0)) {
	Tcl_Obj *dictObj = StatOpenFile(infoPtr);
	const char *dictContents;
	Tcl_Size dictLength;

	if (dictObj == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "couldn't read file channel status: %s",
		    Tcl_PosixError(interp)));
	    return TCL_ERROR;
	}

	/*
	 * Transfer dictionary to the DString. Note that we don't do this as
	 * an element as this is an option that can't be retrieved with a
	 * general probe.
	 */

	dictContents = TclGetStringFromObj(dictObj, &dictLength);
	Tcl_DStringAppend(dsPtr, dictContents, dictLength);
	Tcl_DecrRefCount(dictObj);
	return TCL_OK;
    }

    if (valid) {
	return TCL_OK;
    }
    return Tcl_BadChannelOption(interp, optionName,
		"stat");
}

/*
 *----------------------------------------------------------------------
 *
 * TclpOpenFileChannel --
 *
 *	Open an File based channel on Unix systems.
778
779
780
781
782
783
784

















785
786
787
788
789
790
791
792

793
794
795
796
797
798
799
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

1024
1025
1026
1027
1028
1029
1030
1031







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
+







    HANDLE handle;
    char channelName[16 + TCL_INTEGER_SPACE];
    TclFile readFile = NULL, writeFile = NULL;

    nativeName = (const WCHAR *)Tcl_FSGetNativePath(pathPtr);
    if (nativeName == NULL) {
	if (interp) {
	    /*
	     * We need this just to ensure we return the correct error messages under
	     * some circumstances (relative paths only), so because the normalization
	     * is very expensive, don't invoke it for native or absolute paths.
	     * Note: since paths starting with ~ are relative in 9.0 for windows,
	     * it doesn't need to consider tilde expansion (in opposite to 8.x).
	     */
	    if (
		(
		    !TclFSCwdIsNative() &&
		    (Tcl_FSGetPathType(pathPtr) != TCL_PATH_ABSOLUTE)
		) &&
		Tcl_FSGetNormalizedPath(interp, pathPtr) == NULL
	    ) {
		return NULL;
	    }

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "couldn't open \"%s\": filename is invalid on this platform",
		    TclGetString(pathPtr)));
	}
	return NULL;
    }

    switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) {
    switch (mode & O_ACCMODE) {
    case O_RDONLY:
	accessMode = GENERIC_READ;
	channelPermissions = TCL_READABLE;
	break;
    case O_WRONLY:
	accessMode = GENERIC_WRITE;
	channelPermissions = TCL_WRITABLE;
836
837
838
839
840
841
842
843

844
845
846
847
848
849
850
851
852
853

854
855
856
857
858
859
860
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







-
+









-
+







     * handling for Windows serial ports by a "name-hint" to directly open it
     * with the OVERLAPPED flag set.
     */

    if (NativeIsComPort(nativeName)) {
	handle = TclWinSerialOpen(INVALID_HANDLE_VALUE, nativeName, accessMode);
	if (handle == INVALID_HANDLE_VALUE) {
	    TclWinConvertError(GetLastError());
	    Tcl_WinConvertError(GetLastError());
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"couldn't open serial \"%s\": %s",
			TclGetString(pathPtr), Tcl_PosixError(interp)));
	    }
	    return NULL;
	}

	/*
	 * For natively named Windows serial ports we are done.
	 * For natively-named Windows serial ports we are done.
	 */

	channel = TclWinOpenSerialChannel(handle, channelName,
		channelPermissions);

	return channel;
    }
893
894
895
896
897
898
899
900

901
902
903
904
905
906
907
1125
1126
1127
1128
1129
1130
1131

1132
1133
1134
1135
1136
1137
1138
1139







-
+







    if (handle == INVALID_HANDLE_VALUE) {
	DWORD err = GetLastError();

	if ((err & 0xFFFFL) == ERROR_OPEN_FAILED) {
	    err = TEST_FLAG(mode, O_CREAT) ? ERROR_FILE_EXISTS
		    : ERROR_FILE_NOT_FOUND;
	}
	TclWinConvertError(err);
	Tcl_WinConvertError(err);
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "couldn't open \"%s\": %s",
		    TclGetString(pathPtr), Tcl_PosixError(interp)));
	}
	return NULL;
    }
917
918
919
920
921
922
923
924

925
926
927
928
929
930
931
1149
1150
1151
1152
1153
1154
1155

1156
1157
1158
1159
1160
1161
1162
1163







-
+







	 *
	 * Reopen channel for OVERLAPPED operation. Normally this shouldn't
	 * fail, because the channel exists.
	 */

	handle = TclWinSerialOpen(handle, nativeName, accessMode);
	if (handle == INVALID_HANDLE_VALUE) {
	    TclWinConvertError(GetLastError());
	    Tcl_WinConvertError(GetLastError());
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"couldn't reopen serial \"%s\": %s",
			TclGetString(pathPtr), Tcl_PosixError(interp)));
	    }
	    return NULL;
	}
944
945
946
947
948
949
950
951

952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967

968
969
970
971
972
973
974
1176
1177
1178
1179
1180
1181
1182

1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198

1199
1200
1201
1202
1203
1204
1205
1206







-
+















-
+







	    writeFile = TclWinMakeFile(handle);
	}
	channel = TclpCreateCommandChannel(readFile, writeFile, NULL, 0, NULL);
	break;
    case FILE_TYPE_CHAR:
    case FILE_TYPE_DISK:
    case FILE_TYPE_UNKNOWN:
	channel = TclWinOpenFileChannel(handle, channelName,
	channel = OpenFileChannel(handle, channelName,
		channelPermissions,
		TEST_FLAG(mode, O_APPEND) ? FILE_APPEND : 0);
	break;

    default:
	/*
	 * The handle is of an unknown type, probably /dev/nul equivalent or
	 * possibly a closed handle.
	 */

	channel = NULL;
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"couldn't open \"%s\": bad file type",
		TclGetString(pathPtr)));
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "CHANNEL", "BAD_TYPE",
		NULL);
		(char *)NULL);
	break;
    }

    return channel;
}

/*
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
1217
1218
1219
1220
1221
1222
1223


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

1238
1239
1240
1241
1242
1243
1244
1245







-
-
+
+












-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Channel
Tcl_MakeFileChannel(
    ClientData rawHandle,	/* OS level handle */
    int mode)			/* ORed combination of TCL_READABLE and
    void *rawHandle,	/* OS level handle */
    int mode)			/* OR'ed combination of TCL_READABLE and
				 * TCL_WRITABLE to indicate file mode. */
{
#if defined(HAVE_NO_SEH) && !defined(_WIN64) && !defined(__clang__)
    TCLEXCEPTION_REGISTRATION registration;
#endif
    char channelName[16 + TCL_INTEGER_SPACE];
    Tcl_Channel channel = NULL;
    HANDLE handle = (HANDLE) rawHandle;
    HANDLE dupedHandle;
    TclFile readFile = NULL, writeFile = NULL;
    BOOL result;

    if (mode == 0) {
    if ((mode & (TCL_READABLE|TCL_WRITABLE)) == 0) {
	return NULL;
    }

    switch (FileGetType(handle)) {
    case FILE_TYPE_SERIAL:
	channel = TclWinOpenSerialChannel(handle, channelName, mode);
	break;
1022
1023
1024
1025
1026
1027
1028
1029

1030
1031
1032
1033
1034
1035
1036
1254
1255
1256
1257
1258
1259
1260

1261
1262
1263
1264
1265
1266
1267
1268







-
+







	    writeFile = TclWinMakeFile(handle);
	}
	channel = TclpCreateCommandChannel(readFile, writeFile, NULL, 0, NULL);
	break;

    case FILE_TYPE_DISK:
    case FILE_TYPE_CHAR:
	channel = TclWinOpenFileChannel(handle, channelName, mode, 0);
	channel = OpenFileChannel(handle, channelName, mode, 0);
	break;

    case FILE_TYPE_UNKNOWN:
    default:
	/*
	 * The handle is of an unknown type. Test the validity of this OS
	 * handle by duplicating it, then closing the dupe. The Win32 API
1156
1157
1158
1159
1160
1161
1162
1163

1164
1165
1166
1167
1168
1169
1170
1388
1389
1390
1391
1392
1393
1394

1395
1396
1397
1398
1399
1400
1401
1402







-
+







	/*
	 * Fall through, the handle is valid.
	 *
	 * Create the undefined channel, anyways, because we know the handle
	 * is valid to something.
	 */

	channel = TclWinOpenFileChannel(handle, channelName, mode, 0);
	channel = OpenFileChannel(handle, channelName, mode, 0);
    }

    return channel;
}

/*
 *----------------------------------------------------------------------
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
1466
1467
1468
1469
1470
1471
1472

1473
1474
1475
1476
1477
1478
1479
1480
1481
1482

1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499

1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520

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

1534
1535
1536
1537
1538


1539
1540
1541
1542
1543
1544
1545
1546
1547
1548

1549
1550
1551
1552
1553
1554
1555







-










-
+
















-
+



















+
-
+












-
+




-
-
+









-







    }

    /*
     * Set up the normal channel options for stdio handles.
     */

    if (Tcl_SetChannelOption(NULL,channel,"-translation","auto")!=TCL_OK ||
	    Tcl_SetChannelOption(NULL,channel,"-eofchar","\032 {}")!=TCL_OK ||
	    Tcl_SetChannelOption(NULL,channel,"-buffering",bufMode)!=TCL_OK) {
	Tcl_CloseEx(NULL, channel, 0);
	return (Tcl_Channel) NULL;
    }
    return channel;
}

/*
 *----------------------------------------------------------------------
 *
 * TclWinOpenFileChannel --
 * OpenFileChannel --
 *
 *	Constructs a File channel for the specified standard OS handle. This
 *	is a helper function to break up the construction of channels into
 *	File, Console, or Serial.
 *
 * Results:
 *	Returns the new channel, or NULL.
 *
 * Side effects:
 *	May open the channel and may cause creation of a file on the file
 *	system.
 *
 *----------------------------------------------------------------------
 */

Tcl_Channel
TclWinOpenFileChannel(
OpenFileChannel(
    HANDLE handle,		/* Win32 HANDLE to swallow */
    char *channelName,		/* Buffer to receive channel name */
    int permissions,		/* OR'ed combination of TCL_READABLE,
				 * TCL_WRITABLE, or TCL_EXCEPTION, indicating
				 * which operations are valid on the file. */
    int appendMode)		/* OR'ed combination of bits indicating what
				 * additional configuration of the channel is
				 * present. */
{
    FileInfo *infoPtr;
    ThreadSpecificData *tsdPtr = FileInit();

    /*
     * See if a channel with this handle already exists.
     */

    for (infoPtr = tsdPtr->firstFilePtr; infoPtr != NULL;
	    infoPtr = infoPtr->nextPtr) {
	if (infoPtr->handle == (HANDLE) handle) {
	    return ((permissions & (TCL_READABLE|TCL_WRITABLE|TCL_EXCEPTION))==infoPtr->validMask)
	    return (permissions==infoPtr->validMask) ? infoPtr->channel : NULL;
		    ? infoPtr->channel : NULL;
	}
    }

    infoPtr = (FileInfo *)Tcl_Alloc(sizeof(FileInfo));

    /*
     * TIP #218. Removed the code inserting the new structure into the global
     * list. This is now handled in the thread action callbacks, and only
     * there.
     */

    infoPtr->nextPtr = NULL;
    infoPtr->validMask = permissions;
    infoPtr->validMask = permissions & (TCL_READABLE|TCL_WRITABLE|TCL_EXCEPTION);
    infoPtr->watchMask = 0;
    infoPtr->flags = appendMode;
    infoPtr->handle = handle;
    infoPtr->dirty = 0;
    sprintf(channelName, "file%" TCL_Z_MODIFIER "x", (size_t) infoPtr);

    TclWinGenerateChannelName(channelName, "file", infoPtr);
    infoPtr->channel = Tcl_CreateChannel(&fileChannelType, channelName,
	    infoPtr, permissions);

    /*
     * Files have default translation of AUTO and ^Z eof char, which means
     * that a ^Z will be accepted as EOF when reading.
     */

    Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto");
    Tcl_SetChannelOption(NULL, infoPtr->channel, "-eofchar", "\032 {}");

    return infoPtr->channel;
}

/*
 *----------------------------------------------------------------------
 *
1373
1374
1375
1376
1377
1378
1379
1380

1381
1382
1383
1384
1385
1386
1387
1603
1604
1605
1606
1607
1608
1609

1610
1611
1612
1613
1614
1615
1616
1617







-
+







 *	Changes thread local list of valid channels.
 *
 *----------------------------------------------------------------------
 */

static void
FileThreadActionProc(
    ClientData instanceData,
    void *instanceData,
    int action)
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    FileInfo *infoPtr = (FileInfo *)instanceData;

    if (action == TCL_CHANNEL_THREAD_INSERT) {
	infoPtr->nextPtr = tsdPtr->firstFilePtr;
1481
1482
1483
1484
1485
1486
1487
1488

1489
1490
1491
1492
1493
1494
1495
1711
1712
1713
1714
1715
1716
1717

1718
1719
1720
1721
1722
1723
1724
1725







-
+







 */

static int
NativeIsComPort(
    const WCHAR *nativePath)	/* Path of file to access, native encoding. */
{
    const WCHAR *p = (const WCHAR *) nativePath;
    int i, len = wcslen(p);
    size_t i, len = wcslen(p);

    /*
     * 1. Look for com[1-9]:?
     */

    if ((len == 4) && (_wcsnicmp(p, L"com", 3) == 0)) {
	/*

Changes to win/tclWinConsole.c.

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
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
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
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
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
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
467
468
469
470
471








472
473
474
475
476
477


478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606






607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623




-
+

-
+




+
+
+
+


+
+


+
-
+
-
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+
+
+
+

+
+
+

-
-
+
+
-
-
+
+
+
+
+
+
+


-
+
+

+
+
+
+
+
+
+
+
+

+
-
+
-
-
-
+
+
+
+
+
-
-
+
+
+
+
+
+
-
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+



-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+

+
+
-
+





-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
-
-
-
+
-







-
+
-
-
+
+









-
+
-
-
-
+
+


-
-
-
-
+
+
+
+



-
+

-
+

-
-
+


-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+


-
+

-
+

+
+
+
+
-
+
+

-
-
+
+

-
+

+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
-
+

-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+







/*
 * tclWinConsole.c --
 *
 *	This file implements the Windows-specific console functions, and the
 *	"console" channel driver.
 *	"console" channel driver. Windows 7 or later required.
 *
 * Copyright (c) 1999 by Scriptics Corp.
 * Copyright © 2022 Ashok P. Nadkarni
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifdef TCL_CONSOLE_DEBUG
#undef NDEBUG /* Enable asserts */
#endif

#include "tclWinInt.h"
#include <assert.h>
#include <ctype.h>

/*
 * A general note on the design: The console channel driver differs from
 * The following variable is used to tell whether this module has been
 * most other drivers in the following respects:
 * initialized.
 */

 *
static int initialized = 0;

/*
 * - There can be at most 3 console handles at any time since Windows does
 *   support allocation of more than one console (with three handles
 *   corresponding to stdin, stdout, stderr)
 *
 * - Consoles are created / inherited at process startup. There is currently
 *   no way in Tcl to programmatically create a console. Even if these were
 *   added the above Windows limitation would still apply.
 *
 * - Unlike files, sockets etc. where there is a one-to-one
 *   correspondence between Tcl channels and operating system handles,
 *   std* channels are shared amongst threads which means there can be
 *   multiple Tcl channels corresponding to a single console handle.
 *
 * - Even with multiple threads, more than one file event handler is
 * unlikely. It does not make sense for multiple threads to register
 * handlers for stdin because the input would be randomly fragmented amongst
 * the threads.
 * The consoleMutex locks around access to the initialized variable, and it is
 * used to protect background threads from being terminated while they are
 * using APIs that hold locks.
 *
 * Various design factors are driven by the above, e.g. use of lists instead
 * of hash tables (at most 3 console handles) and use of global instead of
 * per thread queues which simplifies lock management particularly because
 * thread-console relation is not one-one and is likely more performant as
 * well with fewer locks needing to be obtained.
 */

TCL_DECLARE_MUTEX(consoleMutex)
 *
 * Some additional design notes/reminders for the future:
 *
 * Aligned, synchronous reads are done directly by interpreter thread.
 * Unaligned or asynchronous reads are done through the reader thread.
 *
 * The reader thread does not read ahead. That is, it will not post a read
 * until some interpreter thread is actually requesting a read. This is
 * because an interpreter may (for example) turn off echo for passwords and
 * the read ahead would come in the way of that.
 *
 * If multiple threads are reading from stdin, the input is sprayed in
 * random fashion. This is not good application design and hence no plan to
 * address this (not clear what should be done even in theory)
 *
 * For output, we do not restrict all output to the console writer threads.
 * See ConsoleOutputProc for the conditions.
 *
 * Locks are never held when calling the ReadConsole/WriteConsole API's
 * since they may block.
 */

static int gInitialized = 0;

/*
 * Bit masks used in the flags field of the ConsoleInfo structure below.
 * INPUT_BUFFER_SIZE is size of buffer passed to ReadConsole in bytes.
 * Note that ReadConsole will only allow reading of line lengths up to the
 * max of 256 and buffer size passed to it. So dropping this below 512
 * means user can type at most 256 chars.
 */
#ifndef INPUT_BUFFER_SIZE
#define INPUT_BUFFER_SIZE 8192 /* In bytes, so 4096 chars */
#endif

#define CONSOLE_PENDING	 (1<<0)	/* Message is pending in the queue. */
#define CONSOLE_ASYNC	 (1<<1)	/* Channel is non-blocking. */
/*
 * CONSOLE_BUFFER_SIZE is size of storage used in ring buffers.
#define CONSOLE_READ_OPS (1<<4)	/* Channel supports read-related ops. */
#define CONSOLE_RESET    (1<<5)	/* Console mode needs to be reset. */
 * In theory, at least sizeof(WCHAR) but note the Tcl channel bug
 * https://core.tcl-lang.org/tcl/tktview/b3977d199b08e3979a8da970553d5209b3042e9c
 * will cause failures in test suite if close to max input line in the suite.
 */
#ifndef CONSOLE_BUFFER_SIZE
#define CONSOLE_BUFFER_SIZE 8192 /* In bytes */
#endif

/*
 * Bit masks used in the sharedFlags field of the ConsoleInfo structure below.
 * Ring buffer for storing data. Actual data is from bufPtr[start]:bufPtr[size-1]
 * and bufPtr[0]:bufPtr[length - (size-start)].
 */
typedef struct RingBuffer {
    char *bufPtr;	/* Pointer to buffer storage */
    Tcl_Size capacity;	/* Size of the buffer in RingBufferChar */
    Tcl_Size start;	/* Start of the data within the buffer. */
    Tcl_Size length;	/* Number of RingBufferChar*/
} RingBuffer;
#define RingBufferLength(ringPtr_) ((ringPtr_)->length)
#define RingBufferHasFreeSpace(ringPtr_) ((ringPtr_)->length < (ringPtr_)->capacity)
#define RINGBUFFER_ASSERT(ringPtr_) assert(RingBufferCheck(ringPtr_))

/*
#define CONSOLE_EOF	  (1<<2)  /* Console has reached EOF. */
 * The Win32 console API does not support non-blocking I/O in any form. Thus
#define CONSOLE_BUFFERED  (1<<3)  /* Data was read into a buffer by the reader
				   * thread. */

 * the actual calls are made on a separate thread. Moreover, separate
 * threads are needed for each handle because (for example) blocking on user
 * input on stdin should not prevent output to stdout when non-blocking i/o
 * is configured at the script level.
 *
#define CONSOLE_BUFFER_SIZE (8*1024)

 * In the input (e.g. stdin) case, the console stdin thread is the producer
 * writing to the buffer ring buffer. The Tcl interpreter threads are the
 * consumer. For the output (e.g. stdout/stderr) case, the Tcl interpreter
 * are the producers while the console stdout/stderr threads are the
 * consumers.
 *
/*
 * Structure containing handles associated with one of the special console
 * threads.
 * Consoles are identified purely by handles and multiple threads may open
 * them (as stdin/stdout/stderr are shared).
 */

typedef struct {
    HANDLE thread;		/* Handle to reader or writer thread. */
    HANDLE readyEvent;		/* Manual-reset event to signal _to_ the main
				 * thread when the worker thread has finished
				 * waiting for its normal work to happen. */
 *
 * Note on reference counting - a ConsoleHandleInfo instance has multiple
 * references to it - one each from every channel that is attached to it
 * plus one from the console thread itself which also serves as the reference
 * from gConsoleHandleInfoList.
 */
typedef struct ConsoleHandleInfo {
    struct ConsoleHandleInfo *nextPtr; /* Process-global list of consoles */
    HANDLE console;       /* Console handle */
    HANDLE consoleThread; /* Handle to thread doing actual i/o on the console */
    SRWLOCK lock;	  /* Controls access to this structure.
			   * Cheaper than CRITICAL_SECTION but note does not
			   * support recursive locks or Try* style attempts.*/
    CONDITION_VARIABLE consoleThreadCV;/* For awakening console thread */
    CONDITION_VARIABLE interpThreadCV; /* For awakening interpthread(s) */
    RingBuffer buffer;	  /* Buffer for data transferred between console
			   * threads and Tcl threads. For input consoles,
			   * written by the console thread and read by Tcl
			   * threads. The converse for output threads */
    DWORD initMode;	  /* Initial console mode. */
    DWORD lastError;	  /* An error caused by the last background
			   * operation. Set to 0 if no error has been
			   * detected. */
    TclPipeThreadInfo *TI;	/* Thread info structure of writer and reader. */
} ConsoleThreadInfo;
    int numRefs;	  /* See comments above */
    int permissions;	  /* TCL_READABLE for input consoles, TCL_WRITABLE
			   * for output. Only one or the other can be set. */
    int flags;
#define CONSOLE_DATA_AWAITED 0x0001 /* An interpreter is awaiting data */
} ConsoleHandleInfo;

/*
 * This structure describes per-instance data for a console based channel.
 */

typedef struct ConsoleInfo {
    HANDLE handle;
 *
 * Note on locking - this structure has no locks because it is accessed
 * only from the thread owning channel EXCEPT when a console traverses it
 * looking for a channel that is watching for events on the console. Even
 * in that case, no locking is required because that access is only under
 * the gConsoleLock lock which prevents the channel from being removed from
 * the gWatchingChannelList which in turn means it will not be deallocated
 * from under the console thread. Access to individual fields does not need
 * to be controlled because
 *   - the console thread does not write to any fields
 *   - changes to the nextWatchingChannelPtr field
 *   - changes to other fields do not matter because after being read for
 *     queueing events, they are verified again when the event is received
 *     in the interpreter thread (since they could have changed anyways while
 *     the event was in-flight on the event queue)
 *
 * Note on reference counting - a structure instance may be referenced from
 * three places:
 *   - the Tcl channel subsystem. This reference is created when on channel
 *     opening and dropped on channel close. This also covers the reference
 *     from gWatchingChannelList since queueing / dequeuing from that list
 *     happens in conjunction with channel operations.
 *   - the Tcl event queue entries. This reference is added when the event
 *     is queued and dropped on receipt.
 */
typedef struct ConsoleChannelInfo {
    HANDLE handle;		/* Console handle */
    int type;
    struct ConsoleInfo *nextPtr;/* Pointer to next registered console. */
    Tcl_ThreadId threadId;	/* Id of owning thread */
    struct ConsoleChannelInfo *nextWatchingChannelPtr;
				/* Pointer to next channel watching events. */
    Tcl_Channel channel;	/* Pointer to channel structure. */
    DWORD initMode;		/* Initial console mode. */
    int numRefs;		/* See comments above */
    int validMask;		/* OR'ed combination of TCL_READABLE,
    int permissions;            /* OR'ed combination of TCL_READABLE,
				 * TCL_WRITABLE, or TCL_EXCEPTION: indicates
				 * which operations are valid on the file. */
    int watchMask;		/* OR'ed combination of TCL_READABLE,
				 * TCL_WRITABLE, or TCL_EXCEPTION: indicates
				 * which events should be reported. */
    int flags;			/* State flags, see above for a list. */
    int flags;			/* State flags */
    Tcl_ThreadId threadId;	/* Thread to which events should be reported.
				 * This value is used by the reader/writer
				 * threads. */
    ConsoleThreadInfo writer;	/* A specialized thread for handling
				 * asynchronous writes to the console; the
				 * waiting starts when a control event is sent,
				 * and a reset event is sent back to the main
				 * thread when the write is done. */
    ConsoleThreadInfo reader;	/* A specialized thread for handling
				 * asynchronous reads from the console; the
				 * waiting starts when a control event is sent,
				 * and a reset event is sent back to the main
				 * thread when input is available. */
    DWORD writeError;		/* An error caused by the last background
				 * write. Set to 0 if no error has been
				 * detected. This word is shared with the
				 * writer thread so access must be
				 * synchronized with the writable object. */
    char *writeBuf;		/* Current background output buffer. Access is
				 * synchronized with the writable object. */
    int writeBufLen;		/* Size of write buffer. Access is
				 * synchronized with the writable object. */
    int toWrite;		/* Current amount to be written. Access is
				 * synchronized with the writable object. */
    int readFlags;		/* Flags that are shared with the reader
				 * thread. Access is synchronized with the
				 * readable object. */
    int bytesRead;		/* Number of bytes in the buffer. */
    int offset;			/* Number of bytes read out of the buffer. */
    DWORD initMode;		/* Initial console mode. */
    char buffer[CONSOLE_BUFFER_SIZE];
#define CONSOLE_EVENT_QUEUED 0x0001 /* Notification event already queued */
				/* Data consumed by reader thread. */
} ConsoleInfo;

#define CONSOLE_ASYNC        0x0002 /* Channel is non-blocking. */
typedef struct {
    /*
     * The following pointer refers to the head of the list of consoles that
     * are being watched for file events.
     */

#define CONSOLE_READ_OPS     0x0004 /* Channel supports read-related ops. */
    ConsoleInfo *firstConsolePtr;
} ThreadSpecificData;

} ConsoleChannelInfo;
static Tcl_ThreadDataKey dataKey;

/*
 * The following structure is what is added to the Tcl event queue when
 * console events are generated.
 */

typedef struct {
    Tcl_Event header;		/* Information that is standard for all
    Tcl_Event header;		/* Information that is standard for all events. */
				 * events. */
    ConsoleInfo *infoPtr;	/* Pointer to console info structure. Note
    ConsoleChannelInfo *chanInfoPtr;
				/* Pointer to console info structure. Note
				 * that we still have to verify that the
				 * console exists before dereferencing this
				 * pointer. */
} ConsoleEvent;

/*
 * Declarations for functions used only in this file.
 */

static int		ConsoleBlockModeProc(ClientData instanceData,
static int		ConsoleBlockModeProc(void *instanceData, int mode);
			    int mode);
static void		ConsoleCheckProc(ClientData clientData, int flags);
static int		ConsoleCloseProc(ClientData instanceData,
static void		ConsoleCheckProc(void *clientData, int flags);
static int		ConsoleCloseProc(void *instanceData,
			    Tcl_Interp *interp, int flags);
static int		ConsoleEventProc(Tcl_Event *evPtr, int flags);
static void		ConsoleExitHandler(ClientData clientData);
static int		ConsoleGetHandleProc(ClientData instanceData,
			    int direction, ClientData *handlePtr);
static int		ConsoleGetOptionProc(ClientData instanceData,
static void		ConsoleExitHandler(void *clientData);
static int		ConsoleGetHandleProc(void *instanceData,
			    int direction, void **handlePtr);
static int		ConsoleGetOptionProc(void *instanceData,
			    Tcl_Interp *interp, const char *optionName,
			    Tcl_DString *dsPtr);
static void		ConsoleInit(void);
static int		ConsoleInputProc(ClientData instanceData, char *buf,
static int		ConsoleInputProc(void *instanceData, char *buf,
			    int toRead, int *errorCode);
static int		ConsoleOutputProc(ClientData instanceData,
static int		ConsoleOutputProc(void *instanceData,
			    const char *buf, int toWrite, int *errorCode);
static DWORD WINAPI	ConsoleReaderThread(LPVOID arg);
static int		ConsoleSetOptionProc(ClientData instanceData,
static int		ConsoleSetOptionProc(void *instanceData,
			    Tcl_Interp *interp, const char *optionName,
			    const char *value);
static void		ConsoleSetupProc(ClientData clientData, int flags);
static void		ConsoleWatchProc(ClientData instanceData, int mask);
static void		ConsoleSetupProc(void *clientData, int flags);
static void		ConsoleWatchProc(void *instanceData, int mask);
static void		ProcExitHandler(void *clientData);
static void		ConsoleThreadActionProc(void *instanceData, int action);
static DWORD		ReadConsoleChars(HANDLE hConsole, WCHAR *lpBuffer,
			    Tcl_Size nChars, Tcl_Size *nCharsReadPtr);
static DWORD		WriteConsoleChars(HANDLE hConsole,
			    const WCHAR *lpBuffer, Tcl_Size nChars,
			    Tcl_Size *nCharsWritten);
static void		RingBufferInit(RingBuffer *ringPtr, Tcl_Size capacity);
static void		RingBufferClear(RingBuffer *ringPtr);
static Tcl_Size		RingBufferIn(RingBuffer *ringPtr, const char *srcPtr,
			    Tcl_Size srcLen, int partialCopyOk);
static Tcl_Size		RingBufferOut(RingBuffer *ringPtr, char *dstPtr,
			    Tcl_Size dstCapacity, int partialCopyOk);
static ConsoleHandleInfo *AllocateConsoleHandleInfo(HANDLE consoleHandle,
			    int permissions);
static ConsoleHandleInfo *FindConsoleInfo(const ConsoleChannelInfo *);
static DWORD WINAPI	ConsoleReaderThread(LPVOID arg);
static DWORD WINAPI	ConsoleWriterThread(LPVOID arg);
static void		ProcExitHandler(ClientData clientData);
static int		WaitForRead(ConsoleInfo *infoPtr, int blocking);
static void		ConsoleThreadActionProc(ClientData instanceData,
			    int action);
static BOOL		ReadConsoleBytes(HANDLE hConsole, LPVOID lpBuffer,
			    DWORD nbytes, LPDWORD nbytesread);
static BOOL		WriteConsoleBytes(HANDLE hConsole,
			    const void *lpBuffer, DWORD nbytes,
			    LPDWORD nbyteswritten);
static void		NudgeWatchers(HANDLE consoleHandle);
#ifndef NDEBUG
static int		RingBufferCheck(const RingBuffer *ringPtr);
#endif

/*
 * Static data.
 */

typedef struct {
    /* Currently this struct is only used to detect thread initialization */
    int notUsed; /* Dummy field */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;

/*
 * All access to static data is controlled through a single process-wide
 * lock. A process can have only a single console at a time, with three
 * handles for stdin, stdout and stderr. Creation/destruction of consoles is
 * a relatively rare event (currently only possible during process start),
 * the number of consoles (as opposed to channels) is small (only stdin,
 * stdout and stderr), and contention low. More finer-grained locking would
 * likely not only complicate implementation but be slower due to multiple
 * locks being held. Note console channels also differ from other Tcl
 * channel types in that the channel<->OS descriptor mapping is not one-to-one.
 */
SRWLOCK gConsoleLock;

/* Process-wide list of console handles. Access control through gConsoleLock */
static ConsoleHandleInfo *gConsoleHandleInfoList;

/*
 * Process-wide list of channels that are listening for events. Again access
 * control through gConsoleLock. Common list for all threads is simplifies
 * locking and bookkeeping and is workable because in practice multiple
 * threads are very unlikely to be all waiting on stdin (not workable
 * because input would be randomly distributed to threads)
 */
static ConsoleChannelInfo *gWatchingChannelList;

/*
 * This structure describes the channel type structure for command console
 * based IO.
 */

static const Tcl_ChannelType consoleChannelType = {
    "console",			/* Type name. */
    TCL_CHANNEL_VERSION_5,	/* v5 channel */
    NULL,		/* Close proc. */
    ConsoleInputProc,		/* Input proc. */
    ConsoleOutputProc,		/* Output proc. */
    NULL,			/* Seek proc. */
    ConsoleSetOptionProc,	/* Set option proc. */
    ConsoleGetOptionProc,	/* Get option proc. */
    ConsoleWatchProc,		/* Set up notifier to watch the channel. */
    ConsoleGetHandleProc,	/* Get an OS handle from channel. */
    ConsoleCloseProc,		/* close2proc. */
    ConsoleBlockModeProc,	/* Set blocking or non-blocking mode. */
    "console",
    TCL_CHANNEL_VERSION_5,
    NULL,			/* Deprecated. */
    ConsoleInputProc,
    ConsoleOutputProc,
    NULL,			/* Deprecated. */
    ConsoleSetOptionProc,
    ConsoleGetOptionProc,
    ConsoleWatchProc,
    ConsoleGetHandleProc,
    ConsoleCloseProc,
    ConsoleBlockModeProc,
    NULL,			/* Flush proc. */
    NULL,			/* Handler proc. */
    NULL,			/* Wide seek proc. */
    ConsoleThreadActionProc,	/* Thread action proc. */
    NULL,			/* Bubbled event handler proc. */
    NULL,			/* Seek proc. */
    ConsoleThreadActionProc,
    NULL			/* Truncation proc. */
};


/*
 *----------------------------------------------------------------------
 *------------------------------------------------------------------------
 *
 * RingBufferInit --
 *
 *    Initializes the ring buffer to a given size.
 *
 * ReadConsoleBytes, WriteConsoleBytes --
 * Results:
 *    None.
 *
 *	Wrapper for ReadConsoleW, that takes and returns number of bytes
 *	instead of number of WCHARS.
 * Side effects:
 *    Panics on allocation failure.
 *
 *----------------------------------------------------------------------
 *------------------------------------------------------------------------
 */
static void
RingBufferInit(
    RingBuffer *ringPtr,
    Tcl_Size capacity)

static BOOL
ReadConsoleBytes(
    HANDLE hConsole,
    LPVOID lpBuffer,
    DWORD nbytes,
    LPDWORD nbytesread)
{
    DWORD ntchars;
    BOOL result;

    /*
{
    if (capacity <= 0 || capacity > TCL_SIZE_MAX) {
	Tcl_Panic("Internal error: invalid ring buffer capacity requested.");
    }
    ringPtr->bufPtr = (char *)Tcl_Alloc(capacity);
    ringPtr->capacity = capacity;
    ringPtr->start    = 0;
    ringPtr->length   = 0;
}

/*
 *------------------------------------------------------------------------
 *
 * RingBufferClear
 *
 *    Clears the contents of a ring buffer.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    The allocated internal buffer is freed.
 *
 *------------------------------------------------------------------------
 */
static void
RingBufferClear(
    RingBuffer *ringPtr)
{
    if (ringPtr->bufPtr) {
	Tcl_Free(ringPtr->bufPtr);
	ringPtr->bufPtr = NULL;
    }
    ringPtr->capacity = 0;
    ringPtr->start    = 0;
    ringPtr->length   = 0;
}

/*
 *------------------------------------------------------------------------
 *
 * RingBufferIn --
 *
 *    Appends data to the ring buffer.
 *
 * Results:
 *    Returns number of bytes copied.
 *
 * Side effects:
 *    Internal buffer is updated.
 *
 *------------------------------------------------------------------------
 */
static Tcl_Size
RingBufferIn(
    RingBuffer *ringPtr,
    const char *srcPtr,		/* Source to be copied */
    Tcl_Size srcLen,		/* Length of source */
    int partialCopyOk)		/* If true, partial copy is permitted */
{
    Tcl_Size freeSpace;

    RINGBUFFER_ASSERT(ringPtr);

    freeSpace = ringPtr->capacity - ringPtr->length;
    if (freeSpace < srcLen) {
	if (!partialCopyOk) {
	    return 0;
	}
	/* Copy only as much as free space allows */
	srcLen = freeSpace;
    }

    if (ringPtr->capacity - ringPtr->start > ringPtr->length) {
	/* There is room at the back */
	Tcl_Size endSpaceStart = ringPtr->start + ringPtr->length;
	Tcl_Size endSpace      = ringPtr->capacity - endSpaceStart;
	if (endSpace >= srcLen) {
	    /* Everything fits at the back */
	    memmove(endSpaceStart + ringPtr->bufPtr, srcPtr, srcLen);
	} else {
	    /* srcLen > endSpace */
	    memmove(endSpaceStart + ringPtr->bufPtr, srcPtr, endSpace);
	    memmove(ringPtr->bufPtr, endSpace + srcPtr, srcLen - endSpace);
	}
    } else {
	/* No room at the back. Existing data wrap to front. */
	Tcl_Size wrapLen =
	    ringPtr->start + ringPtr->length - ringPtr->capacity;
	memmove(wrapLen + ringPtr->bufPtr, srcPtr, srcLen);
    }

    ringPtr->length += srcLen;

    RINGBUFFER_ASSERT(ringPtr);

    return srcLen;
}

/*
 *------------------------------------------------------------------------
 *
 * RingBufferOut --
 *
 *    Moves data out of the ring buffer.  If dstPtr is NULL, the data
 *    is simply removed.
 *
 * Results:
 *    Returns number of bytes copied or removed.
 *
 * Side effects:
 *    Internal buffer is updated.
 *
 *------------------------------------------------------------------------
 */
static Tcl_Size
RingBufferOut(
    RingBuffer *ringPtr,
    char *dstPtr,		/* Buffer for output data. May be NULL */
    Tcl_Size dstCapacity,	/* Size of buffer */
    int partialCopyOk)		/* If true, return what's available */
{
    Tcl_Size leadLen;

    RINGBUFFER_ASSERT(ringPtr);

    if (dstCapacity > ringPtr->length) {
	if (dstPtr && !partialCopyOk) {
	    return 0;
	}
	dstCapacity = ringPtr->length;
    }

     * If user types a Ctrl-Break or Ctrl-C, ReadConsole will return
     * success with ntchars == 0 and GetLastError() will be
     * ERROR_OPERATION_ABORTED. We do not want to treat this case
     * as EOF so we will loop around again. If no Ctrl signal handlers
     * have been established, the default signal OS handler in a separate
     * thread will terminate the program. If a Ctrl signal handler
     * has been established (through an extension for example), it
     * will run and take whatever action it deems appropriate.
    if (ringPtr->start <= (ringPtr->capacity - ringPtr->length)) {
	/* No content wrap around. So leadLen is entire content */
	leadLen = ringPtr->length;
    } else {
	/* Content wraps around so lead segment stretches to end of buffer */
	leadLen = ringPtr->capacity - ringPtr->start;
     */
    do {
    }
    if (leadLen >= dstCapacity) {
	if (dstPtr) {
	    memmove(dstPtr, ringPtr->start + ringPtr->bufPtr, dstCapacity);
	}
	ringPtr->start += dstCapacity;
    } else {
        result = ReadConsoleW(hConsole, lpBuffer, nbytes / sizeof(WCHAR), &ntchars,
                             NULL);
    } while (result && ntchars == 0 && GetLastError() == ERROR_OPERATION_ABORTED);
    if (nbytesread != NULL) {
	*nbytesread = ntchars * sizeof(WCHAR);
    }
    return result;
	Tcl_Size wrapLen = dstCapacity - leadLen;
	if (dstPtr) {
	    memmove(dstPtr,
		    ringPtr->start + ringPtr->bufPtr,
		    leadLen);
	    memmove(
		leadLen + dstPtr, ringPtr->bufPtr, wrapLen);
	}
	ringPtr->start = wrapLen;
    }

    ringPtr->length -= dstCapacity;
    if (ringPtr->start == ringPtr->capacity || ringPtr->length == 0) {
	ringPtr->start = 0;
    }

    RINGBUFFER_ASSERT(ringPtr);

    return dstCapacity;
}

#ifndef NDEBUG
static int
RingBufferCheck(
    const RingBuffer *ringPtr)
{
    return (ringPtr->bufPtr != NULL && ringPtr->capacity == CONSOLE_BUFFER_SIZE
	    && ringPtr->start < ringPtr->capacity
	    && ringPtr->length <= ringPtr->capacity);
}
#endif

static BOOL
WriteConsoleBytes(

/*
 *------------------------------------------------------------------------
 *
 * ReadConsoleChars --
 *
 *    Wrapper for ReadConsoleW.
 *
 * Results:
 *    Returns 0 on success, else Windows error code.
 *
 * Side effects:
 *    On success the number of characters (not bytes) read is stored in
 *    *nCharsReadPtr. This will be 0 if the operation was interrupted by
 *    a Ctrl-C or a CancelIo call.
 *
 *------------------------------------------------------------------------
 */
static DWORD
ReadConsoleChars(
    HANDLE hConsole,
    const void *lpBuffer,
    DWORD nbytes,
    WCHAR *lpBuffer,
    Tcl_Size nChars,
    LPDWORD nbyteswritten)
    Tcl_Size *nCharsReadPtr)
{
    DWORD ntchars;
    DWORD nRead;
    BOOL result;

    /*
     * If user types a Ctrl-Break or Ctrl-C, ReadConsole will return success
     * with ntchars == 0 and GetLastError() will be ERROR_OPERATION_ABORTED.
     * If no Ctrl signal handlers have been established, the default signal
     * OS handler in a separate thread will terminate the program. If a Ctrl
     * signal handler has been established (through an extension for
     * example), it will run and take whatever action it deems appropriate.
     *
     * If one thread closes its channel, it calls CancelSynchronousIo on the
     * console handle which results again in success being returned and
     * GetLastError() being ERROR_OPERATION_ABORTED but ntchars in
     * unmodified.
     *
     * In both cases above we will return success but with nbytesread as 0.
     * This allows caller to check for thread termination etc.
     *
     * See https://bugs.python.org/issue30237
     * or https://github.com/microsoft/terminal/issues/12143
     */
    nRead = (DWORD)-1;
    result = ReadConsoleW(hConsole, lpBuffer, nChars, &nRead, NULL);
    if (result) {
	if ((nRead == 0 || nRead == (DWORD)-1)
		&& GetLastError() == ERROR_OPERATION_ABORTED) {
	    nRead = 0;
	}
	*nCharsReadPtr = nRead;
	return 0;
    } else {
	return GetLastError();
    }
}

/*
 *------------------------------------------------------------------------
 *
 * WriteConsoleChars --
 *
 *    Wrapper for WriteConsoleW.
 *
 * Results:
 *    Returns 0 on success, Windows error code on failure.
 *
 * Side effects:
 *    On success the number of characters (not bytes) written is stored in
 *    *nCharsWrittenPtr. This will be 0 if the operation was interrupted by
 *    a Ctrl-C or a CancelIo call.
 *
 *------------------------------------------------------------------------
 */

static DWORD
WriteConsoleChars(
    HANDLE hConsole,
    const WCHAR *lpBuffer,
    Tcl_Size nChars,
    Tcl_Size *nCharsWrittenPtr)
{
    DWORD nCharsWritten;
    BOOL result;

    /* See comments in ReadConsoleChars, not sure that applies here */
    nCharsWritten = (DWORD)-1;
    result = WriteConsoleW(hConsole, lpBuffer, nbytes / sizeof(WCHAR), &ntchars,
	    NULL);
    if (nbyteswritten != NULL) {
	*nbyteswritten = ntchars * sizeof(WCHAR);
    }
    return result;
    result = WriteConsoleW(hConsole, lpBuffer, nChars, &nCharsWritten, NULL);
    if (result) {
	if (nCharsWritten == (DWORD) -1) {
	    nCharsWritten = 0;
	}
	*nCharsWrittenPtr = nCharsWritten;
	return 0;
    } else {
	return GetLastError();
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleInit --
 *
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
636
637
638
639
640
641
642




643
644
645
646
647
648

649
650
651
652
653
654

655
656
657
658
659
660
661
662







-
-
-
-
+
+
+
+


-
+





-
+







ConsoleInit(void)
{
    /*
     * Check the initialized flag first, then check again in the mutex. This
     * is a speed enhancement.
     */

    if (!initialized) {
	Tcl_MutexLock(&consoleMutex);
	if (!initialized) {
	    initialized = 1;
    if (!gInitialized) {
	AcquireSRWLockExclusive(&gConsoleLock);
	if (!gInitialized) {
	    gInitialized = 1;
	    Tcl_CreateExitHandler(ProcExitHandler, NULL);
	}
	Tcl_MutexUnlock(&consoleMutex);
	ReleaseSRWLockExclusive(&gConsoleLock);
    }

    if (TclThreadDataKeyGet(&dataKey) == NULL) {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	tsdPtr->firstConsolePtr = NULL;
	tsdPtr->notUsed = 0;
	Tcl_CreateEventSource(ConsoleSetupProc, ConsoleCheckProc, NULL);
	Tcl_CreateThreadExitHandler(ConsoleExitHandler, NULL);
    }
}

/*
 *----------------------------------------------------------------------
313
314
315
316
317
318
319
320

321
322
323
324
325
326
327
673
674
675
676
677
678
679

680
681
682
683
684
685
686
687







-
+







 *	Removes the console event source.
 *
 *----------------------------------------------------------------------
 */

static void
ConsoleExitHandler(
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    Tcl_DeleteEventSource(ConsoleSetupProc, ConsoleCheckProc, NULL);
}

/*
 *----------------------------------------------------------------------
 *
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
697
698
699
700
701
702
703

704
705



706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755

756
757
758
759
760
761
762
763
764
765
766
767
768
769
770

771
772
773

774
775
776

777
778
779
780
781
782

783
784
785
786
787
788
789
790
791









792
793
794
795
796
797
798
799
800
801
802
803
804
805
806





807
808
809
810
811
812
813
814
815
816
817
818
819







-
+

-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
+
+
+












-
+


-
+


-






-
+
+

+

+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+

+







 *	Resets the process list.
 *
 *----------------------------------------------------------------------
 */

static void
ProcExitHandler(
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    Tcl_MutexLock(&consoleMutex);
    initialized = 0;
    Tcl_MutexUnlock(&consoleMutex);
    AcquireSRWLockExclusive(&gConsoleLock);
    gInitialized = 0;
    ReleaseSRWLockExclusive(&gConsoleLock);
}

/*
 *------------------------------------------------------------------------
 *
 * NudgeWatchers --
 *
 *    Wakes up all threads which have file event watchers on the passed
 *    console handle.
 *
 *    The function locks and releases gConsoleLock.
 *    Caller must not be holding locks that will violate lock hierarchy.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    As above.
 *------------------------------------------------------------------------
 */
static void
NudgeWatchers(
    HANDLE consoleHandle)
{
    ConsoleChannelInfo *chanInfoPtr;
    AcquireSRWLockShared(&gConsoleLock); /* Shared-read lock */
    for (chanInfoPtr = gWatchingChannelList; chanInfoPtr;
	    chanInfoPtr = chanInfoPtr->nextWatchingChannelPtr) {
	/*
	 * Notify channels interested in our handle AND that have
	 * a thread attached.
	 * No lock needed for chanInfoPtr. See ConsoleChannelInfo.
	 */
	if (chanInfoPtr->handle == consoleHandle
		&& chanInfoPtr->threadId != NULL) {
	    Tcl_ThreadAlert(chanInfoPtr->threadId);
	}
    }
    ReleaseSRWLockShared(&gConsoleLock);
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleSetupProc --
 *
 *	This procedure is invoked before Tcl_DoOneEvent blocks waiting for an
 *	event.
 *	event. It walks the channel list and if any input channel has data
 *      available or output channel has space for data, sets the event loop
 *      blocking time to 0 so that it will poll immediately.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Adjusts the block time if needed.
 *
 *----------------------------------------------------------------------
 */

void
ConsoleSetupProc(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */
{
    ConsoleInfo *infoPtr;
    ConsoleChannelInfo *chanInfoPtr;
    Tcl_Time blockTime = { 0, 0 };
    int block = 1;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (!(flags & TCL_FILE_EVENTS)) {
	return;
    }

    /*
     * Look to see if any events are already pending. If they are, poll.
     * Walk the list of channels. See general comments for struct
     * ConsoleChannelInfo with regard to locking and field access.
     */
    AcquireSRWLockShared(&gConsoleLock); /* READ lock - no data modification */

    for (chanInfoPtr = gWatchingChannelList; block && chanInfoPtr != NULL;
	    chanInfoPtr = chanInfoPtr->nextWatchingChannelPtr) {
	ConsoleHandleInfo *handleInfoPtr;
	handleInfoPtr = FindConsoleInfo(chanInfoPtr);
    for (infoPtr = tsdPtr->firstConsolePtr; infoPtr != NULL;
	    infoPtr = infoPtr->nextPtr) {
	if (infoPtr->watchMask & TCL_WRITABLE) {
	    if (WaitForSingleObject(infoPtr->writer.readyEvent,
		    0) != WAIT_TIMEOUT) {
		block = 0;
	    }
	}
	if (infoPtr->watchMask & TCL_READABLE) {
	if (handleInfoPtr != NULL) {
	    AcquireSRWLockShared(&handleInfoPtr->lock);
	    /* Remember at most one of READABLE, WRITABLE set */
	    if (chanInfoPtr->watchMask & TCL_READABLE) {
		if (RingBufferLength(&handleInfoPtr->buffer) > 0
			|| handleInfoPtr->lastError != ERROR_SUCCESS) {
		    block = 0; /* Input data available */
		}
	    } else if (chanInfoPtr->watchMask & TCL_WRITABLE) {
		if (RingBufferHasFreeSpace(&handleInfoPtr->buffer)) {
		    /* TCL_WRITABLE */
		    block = 0; /* Output space available */
		}
	    }
	    ReleaseSRWLockShared(&handleInfoPtr->lock);
	    if (WaitForRead(infoPtr, 0) >= 0) {
		block = 0;
	    }
	}
    }
	}
    }
    ReleaseSRWLockShared(&gConsoleLock);

    if (!block) {
	/* At least one channel is readable/writable. Set block time to 0 */
	Tcl_SetMaxBlockTime(&blockTime);
    }
}

/*
 *----------------------------------------------------------------------
 *
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

467



468
469

470
471
472
473
474




475
476
477
478
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
829
830
831
832
833
834
835

836
837
838

839
840
841

842
843
844
845
846
847
848
849


850
851
852
853
854
855
856
857
858
859
860



861
862
863
864
865
866
867
868
869
870
871
872


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
898
899
900
901
902
903
904

905
906
907
908

909
910
911
912


913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934

935
936
937
938

939
940
941
942
943
944
945
946
947
948
949

950
951

952
953
954
955
956
957
958
959







-
+


-
+
+

-





+
+

-
-
+
+
+
+
+

+

+
+
+
-
-
-
+
+
+
+
+
+
+



+
+
-
-
+
+
+
-
-
+
+
+

+
+
-
-
+
+
+
-
-
+

-
-
-
+
+
+
+
+
+
+
+
-
-
+
+


+




+
-
+
+
+

-
+



-
-
+
+
+
+


















-
+



-
+










-
+

-
+







 *	May queue an event.
 *
 *----------------------------------------------------------------------
 */

static void
ConsoleCheckProc(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */
{
    ConsoleInfo *infoPtr;
    ConsoleChannelInfo *chanInfoPtr;
    Tcl_ThreadId me;
    int needEvent;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (!(flags & TCL_FILE_EVENTS)) {
	return;
    }

    me = Tcl_GetCurrentThread();

    /*
     * Queue events for any ready consoles that don't already have events
     * queued.
     * Acquire a shared lock. Note this is ok even though we potentially
     * modify the chanInfoPtr->flags because chanInfoPtr is only modified
     * when it belongs to this thread and no other thread will write to it.
     * THe shared lock is intended to protect the global gWatchingChannelList
     * as we traverse it.
     */
    AcquireSRWLockShared(&gConsoleLock);

    for (chanInfoPtr = gWatchingChannelList; chanInfoPtr != NULL;
	    chanInfoPtr = chanInfoPtr->nextWatchingChannelPtr) {
	ConsoleHandleInfo *handleInfoPtr;
    for (infoPtr = tsdPtr->firstConsolePtr; infoPtr != NULL;
	    infoPtr = infoPtr->nextPtr) {
	if (infoPtr->flags & CONSOLE_PENDING) {

	if (chanInfoPtr->threadId != me) {
	    /* Some other thread owns the channel */
	    continue;
	}
	if (chanInfoPtr->flags & CONSOLE_EVENT_QUEUED) {
	    /* A notification event already queued. No point in another. */
	    continue;
	}

	handleInfoPtr = FindConsoleInfo(chanInfoPtr);
	/* Pointer is safe to access as we are holding gConsoleLock */
	/*
	 * Queue an event if the console is signaled for reading or writing.

	if (handleInfoPtr == NULL) {
	    /* Stale event */
	 */

	    continue;
	}

	needEvent = 0;
	AcquireSRWLockShared(&handleInfoPtr->lock);
	/* Rememeber channel is read or write, never both */
	if (infoPtr->watchMask & TCL_WRITABLE) {
	    if (WaitForSingleObject(infoPtr->writer.readyEvent,
	if (chanInfoPtr->watchMask & TCL_READABLE) {
	    if (RingBufferLength(&handleInfoPtr->buffer) > 0
		    || handleInfoPtr->lastError != ERROR_SUCCESS) {
		    0) != WAIT_TIMEOUT) {
		needEvent = 1;
		needEvent = 1; /* Input data available or error/EOF */
	    }
	}

	if (infoPtr->watchMask & TCL_READABLE) {
	    /*
	     * TCL_READABLE watch means someone is looking out for data being
	     * available, let reader thread know. Note channel need not be
	     * ASYNC! (Bug [baa51423c2])
	     */
	    handleInfoPtr->flags |= CONSOLE_DATA_AWAITED;
	    WakeConditionVariable(&handleInfoPtr->consoleThreadCV);
	} else if (chanInfoPtr->watchMask & TCL_WRITABLE) {
	    if (WaitForRead(infoPtr, 0) >= 0) {
		needEvent = 1;
	    if (RingBufferHasFreeSpace(&handleInfoPtr->buffer)) {
		needEvent = 1; /* Output space available */
	    }
	}
	ReleaseSRWLockShared(&handleInfoPtr->lock);

	if (needEvent) {
	    ConsoleEvent *evPtr = (ConsoleEvent *)Tcl_Alloc(sizeof(ConsoleEvent));

	    /* See note above loop why this can be accessed without locks */
	    infoPtr->flags |= CONSOLE_PENDING;
	    chanInfoPtr->flags |= CONSOLE_EVENT_QUEUED;
	    chanInfoPtr->numRefs += 1; /* So it does not go away while event
					* is in queue */
	    evPtr->header.proc = ConsoleEventProc;
	    evPtr->infoPtr = infoPtr;
	    evPtr->chanInfoPtr = chanInfoPtr;
	    Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL);
	}
    }
}


    ReleaseSRWLockShared(&gConsoleLock);
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleBlockModeProc --
 *
 *	Set blocking or non-blocking mode on channel.
 *
 * Results:
 *	0 if successful, errno when failed.
 *
 * Side effects:
 *	Sets the device into blocking or non-blocking mode.
 *
 *----------------------------------------------------------------------
 */

static int
ConsoleBlockModeProc(
    ClientData instanceData,	/* Instance data for channel. */
    void *instanceData,		/* Instance data for channel. */
    int mode)			/* TCL_MODE_BLOCKING or
				 * TCL_MODE_NONBLOCKING. */
{
    ConsoleInfo *infoPtr = (ConsoleInfo *)instanceData;
    ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData;

    /*
     * Consoles on Windows can not be switched between blocking and
     * nonblocking, hence we have to emulate the behavior. This is done in the
     * input function by checking against a bit in the state. We set or unset
     * the bit here to cause the input function to emulate the correct
     * behavior.
     */

    if (mode == TCL_MODE_NONBLOCKING) {
	infoPtr->flags |= CONSOLE_ASYNC;
	chanInfoPtr->flags |= CONSOLE_ASYNC;
    } else {
	infoPtr->flags &= ~CONSOLE_ASYNC;
	chanInfoPtr->flags &= ~CONSOLE_ASYNC;
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597




598
599
600
601
602
603
604
605
606
607
608
609









610
611
612
613
614
615
616


617
618
619
620



621
622
623
624
625
626
627
628


























































629
630
631
632
633
634
635
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
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







-
+



-
+
+

-
+
-
+




-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+

-

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-

-
-
-
-
-
+
+
-
-
-
-
+
+
+



-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 *	Closes the physical channel.
 *
 *----------------------------------------------------------------------
 */

static int
ConsoleCloseProc(
    ClientData instanceData,	/* Pointer to ConsoleInfo structure. */
    void *instanceData,		/* Pointer to ConsoleChannelInfo structure. */
    TCL_UNUSED(Tcl_Interp *),
    int flags)
{
    ConsoleInfo *consolePtr = (ConsoleInfo *)instanceData;
    ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData;
    ConsoleHandleInfo *handleInfoPtr;
    int errorCode = 0;
    ConsoleInfo *infoPtr, **nextPtrPtr;
    ConsoleChannelInfo **nextPtrPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    int closeHandle;

    if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
	return EINVAL;
    }

    /*
     * Clean up the background thread if necessary. Note that this must be
     * done before we can close the file, since the thread may be blocking
     * trying to read from the console.
     */

    if (consolePtr->reader.thread) {
	TclPipeThreadStop(&consolePtr->reader.TI, consolePtr->reader.thread);
	CloseHandle(consolePtr->reader.thread);
	CloseHandle(consolePtr->reader.readyEvent);
	consolePtr->reader.thread = NULL;
    }
    consolePtr->validMask &= ~TCL_READABLE;

    /*
     * Wait for the writer thread to finish the current buffer, then terminate
     * the thread and close the handles. If the channel is nonblocking, there
     * should be no pending write operations.
     */

    if (consolePtr->writer.thread) {
	if (consolePtr->toWrite) {
	    /*
	     * We only need to wait if there is something to write. This may
	     * prevent infinite wait on exit. [Python Bug 216289]
	     */

	    WaitForSingleObject(consolePtr->writer.readyEvent, 5000);
	}

	TclPipeThreadStop(&consolePtr->writer.TI, consolePtr->writer.thread);
	CloseHandle(consolePtr->writer.thread);
	CloseHandle(consolePtr->writer.readyEvent);
	consolePtr->writer.thread = NULL;
    }
    consolePtr->validMask &= ~TCL_WRITABLE;

    /*
     * If the user has been tinkering with the mode, reset it now. We ignore
     * any errors from this; we're quite possibly about to close or exit
     * anyway.
     */

    if ((consolePtr->flags & CONSOLE_READ_OPS) &&
	    (consolePtr->flags & CONSOLE_RESET)) {
	SetConsoleMode(consolePtr->handle, consolePtr->initMode);
    }

    /*
     * Don't close the Win32 handle if the handle is a standard channel during
     * the thread exit process. Otherwise, one thread may kill the stdio of
     * another.
     * Don't close the Win32 handle if the handle is a standard channel
     * during the thread exit process. Otherwise, one thread may kill the
     * stdio of another while exiting. Note an explicit close in script will
     * still close the handle. That's historical behavior on all platforms.
     */

    if (!TclInThreadExit()
	    || ((GetStdHandle(STD_INPUT_HANDLE) != consolePtr->handle)
		&& (GetStdHandle(STD_OUTPUT_HANDLE) != consolePtr->handle)
		&& (GetStdHandle(STD_ERROR_HANDLE) != consolePtr->handle))) {
	if (CloseHandle(consolePtr->handle) == FALSE) {
	    TclWinConvertError(GetLastError());
	    errorCode = errno;
	}
    }

	    || (   (GetStdHandle(STD_INPUT_HANDLE) != chanInfoPtr->handle)
		&& (GetStdHandle(STD_OUTPUT_HANDLE) != chanInfoPtr->handle)
		&& (GetStdHandle(STD_ERROR_HANDLE) != chanInfoPtr->handle))) {
	closeHandle = 1;
    } else {
	closeHandle = 0;
    }

    AcquireSRWLockExclusive(&gConsoleLock);
    consolePtr->watchMask &= consolePtr->validMask;

    /*
     * Remove the file from the list of watched files.
     */

    for (nextPtrPtr = &tsdPtr->firstConsolePtr, infoPtr = *nextPtrPtr;
    /* Remove channel from watchers' list */
    for (nextPtrPtr = &gWatchingChannelList; *nextPtrPtr != NULL;
	    infoPtr != NULL;
	    nextPtrPtr = &infoPtr->nextPtr, infoPtr = *nextPtrPtr) {
	if (infoPtr == (ConsoleInfo *) consolePtr) {
	    *nextPtrPtr = infoPtr->nextPtr;
	    nextPtrPtr = &(*nextPtrPtr)->nextWatchingChannelPtr) {
	if (*nextPtrPtr == (ConsoleChannelInfo *) chanInfoPtr) {
	    *nextPtrPtr = (*nextPtrPtr)->nextWatchingChannelPtr;
	    break;
	}
    }
    if (consolePtr->writeBuf != NULL) {
	Tcl_Free(consolePtr->writeBuf);
	consolePtr->writeBuf = 0;
    }
    Tcl_Free(consolePtr);

    handleInfoPtr = FindConsoleInfo(chanInfoPtr);
    if (handleInfoPtr) {
	/*
	 * Console thread may be blocked either waiting for console i/o
	 * or waiting on the condition variable for buffer empty/full
	 */
	AcquireSRWLockShared(&handleInfoPtr->lock);

	if (closeHandle) {
	    handleInfoPtr->console = INVALID_HANDLE_VALUE;
	}

	/* Break the thread out of blocking console i/o */
	handleInfoPtr->numRefs -= 1; /* Remove reference from this channel */
	if (handleInfoPtr->numRefs == 1) {
	    /*
	     * Abort the i/o if no other threads are listening on it.
	     * Note without this check, an input line will be skipped on
	     * the cancel.
	     */
	    CancelSynchronousIo(handleInfoPtr->consoleThread);
	}

	/*
	 * Wake up the console handling thread. Note we do not explicitly
	 * tell it handle is closed (below). It will find out on next access
	 */
	WakeConditionVariable(&handleInfoPtr->consoleThreadCV);

	ReleaseSRWLockShared(&handleInfoPtr->lock);
    }

    ReleaseSRWLockExclusive(&gConsoleLock);

    chanInfoPtr->channel     = NULL;
    chanInfoPtr->watchMask   = 0;
    chanInfoPtr->permissions = 0;

    if (closeHandle && chanInfoPtr->handle != INVALID_HANDLE_VALUE) {
	if (CloseHandle(chanInfoPtr->handle) == FALSE) {
	    Tcl_WinConvertError(GetLastError());
	    errorCode = errno;
	}
	chanInfoPtr->handle = INVALID_HANDLE_VALUE;
    }

    /*
     * Note, we can check and manipulate numRefs without a lock because
     * we have removed it from the watch queue so the console thread cannot
     * get at it.
     */
    if (chanInfoPtr->numRefs > 1) {
	/* There may be references already on the event queue */
	chanInfoPtr->numRefs -= 1;
    } else {
	Tcl_Free(chanInfoPtr);
    }

    return errorCode;
}

/*
 *----------------------------------------------------------------------
 *
643
644
645
646
647
648
649
650
651
652
653
654


655
656
657
658
659
660
661







662
663
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
707
708
709







710
711

712
713
714
715
716
717




718









719
720









721
722

723

724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746

747
748
749
750
751
752
753



754
755
756
757

758
759
760
761
762

763
764
765
766
767











768


769
770
771




772
773
774
775
776
777
778












779
780
781


782
783


784
785
786


787
788
789
790
791
792














793





794
795
796









797
798
799
800
801
802
803
804





805
806
807
808
809
810
811
812
813
814
815
















816
817
818



819
820
821
822
823
824
825
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




1116
1117
1118
1119
1120
1121

1122



1123
1124
1125
1126




1127
1128


1129

1130
1131
1132
1133
1134
1135

1136



1137
1138





1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170






1171
1172
1173
1174
1175
1176
1177
1178
1179
1180



1181
1182
1183
1184
1185
1186
1187



1188
1189
1190
1191
1192





1193
1194
1195
1196
1197
1198
1199


1200
1201





1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215


1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
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
1354
1355
1356
1357
1358
1359
1360
1361







-


-
-
+
+




-
-
-
+
+
+
+
+
+
+



+
+
+
+
+
-
+
-
-
-
-
+
+
+

+
+
-
+
-
-
-
+
+
+
+
-
-
-
-
+
+
-
-

-
+
+
+
+
+

-
+
-
-
-
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+

-
-
-
-
-
+
+
+
+

+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+


+
-
+



















-


-
+




-
-
-
+
+
+



-
+
-
-
-
-
-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

+
+

-
-
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-

+
+
-
-
+
+
-
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+







 *	indication is returned in an output argument.
 *
 * Side effects:
 *	Reads input from the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
ConsoleInputProc(
    ClientData instanceData,	/* Console state. */
    char *buf,			/* Where to store data read. */
    void *instanceData,		/* Console state. */
    char *bufPtr,		/* Where to store data read. */
    int bufSize,		/* How much space is available in the
				 * buffer? */
    int *errorCode)		/* Where to store error code. */
{
    ConsoleInfo *infoPtr = (ConsoleInfo *)instanceData;
    DWORD count, bytesRead = 0;
    int result;
    ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData;
    ConsoleHandleInfo *handleInfoPtr;
    Tcl_Size numRead;

    if (chanInfoPtr->handle == INVALID_HANDLE_VALUE) {
	return 0; /* EOF */
    }

    *errorCode = 0;

    AcquireSRWLockShared(&gConsoleLock);
    handleInfoPtr = FindConsoleInfo(chanInfoPtr);
    if (handleInfoPtr == NULL) {
	/* Really shouldn't happen since channel is holding a reference */
	ReleaseSRWLockShared(&gConsoleLock);
    /*
	return 0; /* EOF */
     * Synchronize with the reader thread.
     */

    result = WaitForRead(infoPtr, (infoPtr->flags & CONSOLE_ASYNC) ? 0 : 1);
    }
    AcquireSRWLockExclusive(&handleInfoPtr->lock);
    ReleaseSRWLockShared(&gConsoleLock); /* AFTER acquiring handleInfoPtr->lock */

    while (1) {
	numRead = RingBufferOut(&handleInfoPtr->buffer, bufPtr, bufSize, 1);
    /*
	/*
     * If an error occurred, return immediately.
     */

	 * Note: even if channel is closed or has an error, as long there is
	 * buffered data, we will pass it up.
	 */
	if (numRead != 0) {
    if (result == -1) {
	*errorCode = errno;
	return -1;
    }
	    break;
	}

    if (infoPtr->readFlags & CONSOLE_BUFFERED) {
	/*
	 * Data is stored in the buffer.
	 * No data available.
	 *  - If an error was recorded, generate that and reset it.
	 *  - If EOF, indicate as much. It is up to the application to close
	 *    the channel.
	 *  - Otherwise, if non-blocking return EAGAIN or wait for more data.
	 */

	if (handleInfoPtr->lastError != 0) {
	if (bufSize < (infoPtr->bytesRead - infoPtr->offset)) {
	    memcpy(buf, &infoPtr->buffer[infoPtr->offset], bufSize);
	    bytesRead = bufSize;
	    if (handleInfoPtr->lastError == ERROR_INVALID_HANDLE) {
		numRead = 0; /* Treat as EOF */
	    infoPtr->offset += bufSize;
	} else {
	    memcpy(buf, &infoPtr->buffer[infoPtr->offset], bufSize);
	    bytesRead = infoPtr->bytesRead - infoPtr->offset;

	    } else {
		Tcl_WinConvertError(handleInfoPtr->lastError);
		handleInfoPtr->lastError = 0;
		*errorCode = Tcl_GetErrno();
		numRead = -1;
	    }
	    break;
	}
	if (handleInfoPtr->console == INVALID_HANDLE_VALUE) {
	    /* EOF - break with numRead == 0 */
	    chanInfoPtr->handle = INVALID_HANDLE_VALUE;
	    break;
	}

	/* For async, tell caller we are blocked */
	if (chanInfoPtr->flags & CONSOLE_ASYNC) {
	    *errorCode = EWOULDBLOCK;
	    numRead = -1;
	    break;
	}

	/*
	 * Blocking read. Just get data from directly from console. There
	 * is a small complication in that
	 * 1. The destination buffer should be WCHAR aligned.
	 * 2. We can only read even number of bytes (wide-character API).
	 * 3. Caller has large enough buffer (else length of line user can
	 *    enter will be limited)
	 * If any condition is not met, we defer to the
	 * reader thread which handles these cases rather than dealing with
	 * them here (which is a little trickier than it might sound.)
	 *
	    /*
	     * Reset the buffer.
	     */

	    infoPtr->readFlags &= ~CONSOLE_BUFFERED;
	    infoPtr->offset = 0;
	 * TODO - not clear this block is a useful optimization. bufSize by
	 * default is 4K which is < INPUT_BUFFER_SIZE and will rarely be
	 * increased on stdin.
	 */
	if ((1 & (size_t)bufPtr) == 0	/* aligned buffer */
		&& (1 & bufSize) == 0	/* Even number of bytes */
		&& bufSize > INPUT_BUFFER_SIZE) {
	    DWORD lastError;
	    Tcl_Size numChars;
	    ReleaseSRWLockExclusive(&handleInfoPtr->lock);
	}

	return bytesRead;
	    lastError = ReadConsoleChars(chanInfoPtr->handle,
		    (WCHAR *)bufPtr, bufSize / sizeof(WCHAR), &numChars);
	    /* NOTE lock released so DON'T break. Return instead */
	    if (lastError != ERROR_SUCCESS) {
		Tcl_WinConvertError(lastError);
		*errorCode = Tcl_GetErrno();
		return -1;
    }

    /*
	    } else if (numChars > 0) {
		/* Successfully read something. */
		return numChars * sizeof(WCHAR);
	    } else {
		/*
     * Attempt to read bufSize bytes. The read will return immediately if
     * there is any data available. Otherwise it will block until at least one
     * byte is available or an EOF occurs.
     */

		 * Ctrl-C/Ctrl-Brk interrupt. Loop around to retry.
		 * We have to reacquire the lock. No worried about handleInfoPtr
		 * having gone away since the channel holds a reference.
		 */
		AcquireSRWLockExclusive(&handleInfoPtr->lock);
		continue;
	    }
    if (ReadConsoleBytes(infoPtr->handle, (LPVOID) buf, (DWORD) bufSize,
	    &count) == TRUE) {
	}
	/*
	 * TODO: This potentially writes beyond the limits specified
	 * by the caller.  In practice this is harmless, since all writes
	 * are into ChannelBuffers, and those have padding, but still
	 * ought to remove this, unless some Windows wizard can give
	 * a reason not to.
	 * Deferring blocking read to reader thread.
	 * Release the lock and sleep. Note that because the channel
	 * holds a reference count on handleInfoPtr, it will not
	 * be deallocated while the lock is released.
	 */
	handleInfoPtr->flags |= CONSOLE_DATA_AWAITED;
	WakeConditionVariable(&handleInfoPtr->consoleThreadCV);
	if (!SleepConditionVariableSRW(&handleInfoPtr->interpThreadCV,
		&handleInfoPtr->lock, INFINITE, 0)) {
	    Tcl_WinConvertError(GetLastError());
	    *errorCode = Tcl_GetErrno();
	    numRead = -1;
	    break;
	}
	buf[count] = '\0';
	return count;

	/* Lock is reacquired, loop back to try again */
    }

    /* We read data. Ask for more if either async or watching for reads */
    if ((chanInfoPtr->flags & CONSOLE_ASYNC)
	    || (chanInfoPtr->watchMask & TCL_READABLE)) {
	handleInfoPtr->flags |= CONSOLE_DATA_AWAITED;
	WakeConditionVariable(&handleInfoPtr->consoleThreadCV);
    }

    ReleaseSRWLockExclusive(&handleInfoPtr->lock);
    return -1;
    return numRead;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleOutputProc --
 *
 *	Writes the given output on the IO channel. Returns count of how many
 *	characters were actually written, and an error indication.
 *
 * Results:
 *	A count of how many characters were written is returned and an error
 *	indication is returned in an output argument.
 *
 * Side effects:
 *	Writes output on the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
ConsoleOutputProc(
    ClientData instanceData,	/* Console state. */
    void *instanceData,		/* Console state. */
    const char *buf,		/* The data buffer. */
    int toWrite,		/* How many bytes to write? */
    int *errorCode)		/* Where to store error code. */
{
    ConsoleInfo *infoPtr = (ConsoleInfo *)instanceData;
    ConsoleThreadInfo *threadInfo = &infoPtr->writer;
    DWORD bytesWritten, timeout;
    ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData;
    ConsoleHandleInfo *handleInfoPtr;
    Tcl_Size numWritten;

    *errorCode = 0;

    /* avoid blocking if pipe-thread exited */
    if (chanInfoPtr->handle == INVALID_HANDLE_VALUE) {
    timeout = (infoPtr->flags & CONSOLE_ASYNC) || !TclPipeThreadIsAlive(&threadInfo->TI)
	|| TclInExit() || TclInThreadExit() ? 0 : INFINITE;
    if (WaitForSingleObject(threadInfo->readyEvent, timeout) == WAIT_TIMEOUT) {
	/*
	 * The writer thread is blocked waiting for a write to complete and
	/* Some other thread would have *previously* closed the stdio handle */
	 * the channel is in non-blocking mode.
	 */

	errno = EWOULDBLOCK;
	goto error;
	*errorCode = EPIPE;
	return -1;
    }

    AcquireSRWLockShared(&gConsoleLock);
    handleInfoPtr = FindConsoleInfo(chanInfoPtr);
    if (handleInfoPtr == NULL) {
	/* Really shouldn't happen since channel is holding a reference */
	*errorCode = EPIPE;
	ReleaseSRWLockShared(&gConsoleLock);
	return -1;
    }
    AcquireSRWLockExclusive(&handleInfoPtr->lock);
    ReleaseSRWLockShared(&gConsoleLock); /* AFTER acquiring handleInfoPtr->lock */

    /*
     * Check for a background error on the last write.
    /* Keep looping until all written. Break out for async and errors */
    numWritten = 0;
    while (1) {
	/* Check for error and closing on every loop. */
     */

    if (infoPtr->writeError) {
	TclWinConvertError(infoPtr->writeError);
	infoPtr->writeError = 0;
	goto error;
    }
	if (handleInfoPtr->lastError != 0) {
	    Tcl_WinConvertError(handleInfoPtr->lastError);
	    *errorCode = Tcl_GetErrno();
	    numWritten = -1;
	    break;
	}
	if (handleInfoPtr->console == INVALID_HANDLE_VALUE) {
	    *errorCode = EPIPE;
	    chanInfoPtr->handle = INVALID_HANDLE_VALUE;
	    numWritten = -1;
	    break;
	}

    if (infoPtr->flags & CONSOLE_ASYNC) {
	/*
	 * We can either write directly or through the console thread's
	 * ring buffer. We have to do the latter when
	 * The console is non-blocking, so copy the data into the output
	 * buffer and restart the writer thread.
	 * (1) the operation is async since WriteConsoleChars is always blocking
	 * (2) when there is already data in the ring buffer because we don't
	 */

	if (toWrite > infoPtr->writeBufLen) {
	 *     want to reorder output from within a thread
	 * (3) when there are an odd number of bytes since WriteConsole
	    /*
	     * Reallocate the buffer to be large enough to hold the data.
	     */

	    if (infoPtr->writeBuf) {
		Tcl_Free(infoPtr->writeBuf);
	 *     takes whole WCHARs
	 * (4) when the pointer is not aligned on WCHAR
	 * The ring buffer deals with cases (3) and (4). It would be harder
	 * to duplicate that here.
	 */
	if ((chanInfoPtr->flags & CONSOLE_ASYNC)		/* Case (1) */
		|| RingBufferLength(&handleInfoPtr->buffer) != 0  /* Case (2) */
		|| (toWrite & 1) != 0				/* Case (3) */
		|| (PTR2INT(buf) & 1) != 0) {			/* Case (4) */
	    numWritten += RingBufferIn(&handleInfoPtr->buffer,
		    numWritten + buf, toWrite - numWritten, 1);
	    if (numWritten == toWrite || chanInfoPtr->flags & CONSOLE_ASYNC) {
		/* All done or async, just accept whatever was written */
		break;
	    }
	    /*
	     * Release the lock and sleep. Note that because the channel
	     * holds a reference count on handleInfoPtr, it will not
	     * be deallocated while the lock is released.
	     */
	    infoPtr->writeBufLen = toWrite;
	    infoPtr->writeBuf = (char *)Tcl_Alloc(toWrite);
	}
	    WakeConditionVariable(&handleInfoPtr->consoleThreadCV);
	    if (!SleepConditionVariableSRW(&handleInfoPtr->interpThreadCV,
		    &handleInfoPtr->lock, INFINITE, 0)) {
		/* Report the error */
		Tcl_WinConvertError(GetLastError());
		*errorCode = Tcl_GetErrno();
		numWritten = -1;
		break;
	    }
	memcpy(infoPtr->writeBuf, buf, toWrite);
	infoPtr->toWrite = toWrite;
	ResetEvent(threadInfo->readyEvent);
	TclPipeThreadSignal(&threadInfo->TI);
	bytesWritten = toWrite;
    } else {
	/*
	 * In the blocking case, just try to write the buffer directly. This
	} else {
	    /* Direct output */
	    DWORD winStatus;
	    HANDLE consoleHandle = handleInfoPtr->console;
	    /* Unlock before blocking in WriteConsole */
	 * avoids an unnecessary copy.
	 */

	if (WriteConsoleBytes(infoPtr->handle, buf, (DWORD) toWrite,
		&bytesWritten) == FALSE) {
	    TclWinConvertError(GetLastError());
	    goto error;
	}
    }
    return bytesWritten;

	    ReleaseSRWLockExclusive(&handleInfoPtr->lock);
	    /* UNLOCKED so return, DON'T break out of loop as it will unlock
	     * again! */
	    winStatus = WriteConsoleChars(consoleHandle,
		    (WCHAR *)buf, toWrite / sizeof(WCHAR), &numWritten);
	    if (winStatus == ERROR_SUCCESS) {
		return numWritten * sizeof(WCHAR);
	    } else {
		Tcl_WinConvertError(winStatus);
		*errorCode = Tcl_GetErrno();
		return -1;
	    }
	}

	/* Lock must have been reacquired before continuing loop */
    }
  error:
    *errorCode = errno;
    return -1;
    WakeConditionVariable(&handleInfoPtr->consoleThreadCV);
    ReleaseSRWLockExclusive(&handleInfoPtr->lock);
    return numWritten;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleEventProc --
 *
842
843
844
845
846
847
848
849
850



851
852
853
854
855
856

857
858
859
860
861



862
863
864
865
866
867
868
869
870
871
872
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
898
899




900

901
902
903
904
905



906




907
908

















909
910
911
912
913
914
915
1378
1379
1380
1381
1382
1383
1384


1385
1386
1387

1388
1389
1390
1391
1392
1393
1394




1395
1396
1397
1398
1399








1400

1401
1402
1403
1404
1405


1406
1407


1408

1409

1410


1411
1412



1413
1414
1415
1416
1417
1418







1419
1420
1421
1422
1423
1424


1425
1426


1427
1428
1429
1430
1431
1432
1433
1434
1435
1436

1437
1438
1439
1440
1441
1442
1443
1444


1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468







-
-
+
+
+
-





+

-
-
-
-
+
+
+


-
-
-
-
-
-
-
-

-
+
+
+
+

-
-
+
+
-
-
+
-

-
+
-
-
+

-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+

-
-
+
+
+
+

+




-
+
+
+

+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







static int
ConsoleEventProc(
    Tcl_Event *evPtr,		/* Event to service. */
    int flags)			/* Flags that indicate what events to handle,
				 * such as TCL_FILE_EVENTS. */
{
    ConsoleEvent *consoleEvPtr = (ConsoleEvent *) evPtr;
    ConsoleInfo *infoPtr;
    int mask;
    ConsoleChannelInfo *chanInfoPtr;
    int freeChannel;
    int mask = 0;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (!(flags & TCL_FILE_EVENTS)) {
	return 0;
    }

    chanInfoPtr = consoleEvPtr->chanInfoPtr;
    /*
     * Search through the list of watched consoles for the one whose handle
     * matches the event. We do this rather than simply dereferencing the
     * handle in the event so that consoles can be deleted while the event is
     * in the queue.
     * We know chanInfoPtr is valid because its reference count would have
     * been incremented when the event was queued. The corresponding release
     * happens in this function.
     */

    for (infoPtr = tsdPtr->firstConsolePtr; infoPtr != NULL;
	    infoPtr = infoPtr->nextPtr) {
	if (consoleEvPtr->infoPtr == infoPtr) {
	    infoPtr->flags &= ~CONSOLE_PENDING;
	    break;
	}
    }

    /*
     * Remove stale events.
     * Global lock used for chanInfoPtr. A read (shared) lock suffices
     * because all access is within the channel owning thread with the
     * exception of watchers which is a read-only access. See comments
     * to ConsoleChannelInfo.
     */

    if (!infoPtr) {
    AcquireSRWLockShared(&gConsoleLock);
    chanInfoPtr->flags &= ~CONSOLE_EVENT_QUEUED;
	return 1;
    }


    /*
     * Check to see if the console is readable. Note that we can't tell if a
     * Only handle the event if the Tcl channel has not gone away AND is
     * console is writable, so we always report it as being writable unless we
     * have detected EOF.
     * still owned by this thread AND is still watching events.
     */

    mask = 0;
    if (infoPtr->watchMask & TCL_WRITABLE) {
    if (chanInfoPtr->channel && chanInfoPtr->threadId == Tcl_GetCurrentThread()
	    && (chanInfoPtr->watchMask & (TCL_READABLE|TCL_WRITABLE))) {
	ConsoleHandleInfo *handleInfoPtr = FindConsoleInfo(chanInfoPtr);
	if (handleInfoPtr == NULL) {
	    /* Console was closed. EOF->read event only (not write) */
	    if (chanInfoPtr->watchMask & TCL_READABLE) {
	if (WaitForSingleObject(infoPtr->writer.readyEvent,
		0) != WAIT_TIMEOUT) {
	    mask = TCL_WRITABLE;
	}
    }

    if (infoPtr->watchMask & TCL_READABLE) {
		mask = TCL_READABLE;
	    }
	} else {
	    AcquireSRWLockShared(&handleInfoPtr->lock);
	    /* Remember at most one of READABLE, WRITABLE set */
	    if ((chanInfoPtr->watchMask & TCL_READABLE)
	if (WaitForRead(infoPtr, 0) >= 0) {
	    if (infoPtr->readFlags & CONSOLE_EOF) {
		    && RingBufferLength(&handleInfoPtr->buffer)) {
		mask = TCL_READABLE;
	    } else {
		mask |= TCL_READABLE;
	    } else if ((chanInfoPtr->watchMask & TCL_WRITABLE)
		    && RingBufferHasFreeSpace(&handleInfoPtr->buffer)) {
		/* Generate write event space available */
		mask = TCL_WRITABLE;
	    }
	    ReleaseSRWLockShared(&handleInfoPtr->lock);
	}
    }

    /*
     * Inform the channel of the events.
     * Tcl_NotifyChannel can recurse through the file event callback so need
     * to release locks first. Our reference still holds so no danger of
     * chanInfoPtr being deallocated if the callback closes the channel.
     */
    ReleaseSRWLockShared(&gConsoleLock);
    if (mask) {
	Tcl_NotifyChannel(chanInfoPtr->channel, mask);
	/* Note: chanInfoPtr ref count may have changed */

    Tcl_NotifyChannel(infoPtr->channel, infoPtr->watchMask & mask);
    }

    /* No need to lock - see comments earlier */

    /* Remove the reference to the channel from event record */
    if (chanInfoPtr->numRefs > 1) {
	chanInfoPtr->numRefs -= 1;
	freeChannel = 0;
    } else {
	assert(chanInfoPtr->channel == NULL);
	freeChannel = 1;
    }

    if (freeChannel) {
	Tcl_Free(chanInfoPtr);
    }

    return 1;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleWatchProc --
923
924
925
926
927
928
929
930
931
932



933
934
935
936
937



938
939
940
941
942
943
944
945
946


947
948
949


950
951
952

















953
954
955
956

957
958

959

960
961
962
963



964
965
966

967
968
969
970
971
972
973
1476
1477
1478
1479
1480
1481
1482



1483
1484
1485

1486



1487
1488
1489

1490
1491
1492
1493
1494
1495


1496
1497
1498
1499
1500
1501
1502



1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521


1522

1523
1524

1525
1526



1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540







-
-
-
+
+
+
-

-
-
-
+
+
+
-






-
-
+
+



+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
+
-

+
-
+

-
-
-
+
+
+



+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
ConsoleWatchProc(
    ClientData instanceData,	/* Console state. */
    int mask)			/* What events to watch for, OR-ed combination
				 * of TCL_READABLE, TCL_WRITABLE and
    void *instanceData,		/* Console state. */
    int newMask)		/* What events to watch for, one of
				 * TCL_READABLE, TCL_WRITABLE */
				 * TCL_EXCEPTION. */
{
    ConsoleInfo **nextPtrPtr, *ptr;
    ConsoleInfo *infoPtr = (ConsoleInfo *)instanceData;
    int oldMask = infoPtr->watchMask;
    ConsoleChannelInfo **nextPtrPtr, *ptr;
    ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData;
    int oldMask = chanInfoPtr->watchMask;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    /*
     * Since most of the work is handled by the background threads, we just
     * need to update the watchMask and then force the notifier to poll once.
     */

    infoPtr->watchMask = mask & infoPtr->validMask;
    if (infoPtr->watchMask) {
    chanInfoPtr->watchMask = newMask & chanInfoPtr->permissions;
    if (chanInfoPtr->watchMask) {
	Tcl_Time blockTime = { 0, 0 };

	if (!oldMask) {
	    AcquireSRWLockExclusive(&gConsoleLock);
	    /* Add to list of watched channels */
	    infoPtr->nextPtr = tsdPtr->firstConsolePtr;
	    tsdPtr->firstConsolePtr = infoPtr;
	}
	    chanInfoPtr->nextWatchingChannelPtr = gWatchingChannelList;
	    gWatchingChannelList = chanInfoPtr;

	    /*
	     * For read channels, need to tell the console reader thread
	     * that we are looking for data since it will not do reads until
	     * it knows someone is awaiting.
	     */
	    ConsoleHandleInfo *handleInfoPtr = FindConsoleInfo(chanInfoPtr);
	    if (handleInfoPtr) {
		AcquireSRWLockExclusive(&handleInfoPtr->lock);
		handleInfoPtr->flags |= CONSOLE_DATA_AWAITED;
		WakeConditionVariable(&handleInfoPtr->consoleThreadCV);
		ReleaseSRWLockExclusive(&handleInfoPtr->lock);
	    }
	    ReleaseSRWLockExclusive(&gConsoleLock);
	}
	Tcl_SetMaxBlockTime(&blockTime);
    } else if (oldMask) {
	/*
	 * Remove the console from the list of watched consoles.
	/* Remove from list of watched channels */
	 */

	AcquireSRWLockExclusive(&gConsoleLock);
	for (nextPtrPtr = &(tsdPtr->firstConsolePtr), ptr = *nextPtrPtr;
	for (nextPtrPtr = &gWatchingChannelList, ptr = *nextPtrPtr;
		ptr != NULL;
		nextPtrPtr = &ptr->nextPtr, ptr = *nextPtrPtr) {
	    if (infoPtr == ptr) {
		*nextPtrPtr = ptr->nextPtr;
		nextPtrPtr = &ptr->nextWatchingChannelPtr, ptr = *nextPtrPtr) {
	    if (chanInfoPtr == ptr) {
		*nextPtrPtr = ptr->nextWatchingChannelPtr;
		break;
	    }
	}
	ReleaseSRWLockExclusive(&gConsoleLock);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleGetHandleProc --
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


















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
1116

1117
1118
1119
1120
1121
1122
1123
1124
1125
1126







1127
1128
1129
1130
1131
1132
1133
1134
1135




























































































1136






















1137
1138
1139

































1140
1141
1142
1143
1144
1145
1146
1147


1148
1149
1150
1151
1152
1153
1154


1155
1156
1157
1158
1159
1160

1161
1162
1163

1164
1165
1166
1167
1168
1169

1170
1171
1172
1173
1174

1175
1176

1177
1178

1179
1180
1181
1182

1183
1184

1185
1186
1187
1188
1189


1190
1191

1192
1193
1194

1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214

1215
1216
1217
1218
1219
1220
1221
1222
1223

1224
1225
1226
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
1354
1355
1356
1357
1358

1359
1360
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

1387
1388
1389


1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410

1411
1412
1413

1414
1415
1416
1417
1418
1419
1420
1421

1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432

1433
1434

1435
1436
1437

1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
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
1478
1479
1480


1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491





1492
1493
1494
1495



1496
1497
1498
1499
1500

1501
1502
1503
1504
1505
1506
1507

1508
1509
1510
1511
1512


1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533

1534
1535
1536
1537
1538
1539
1540
1550
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
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763



1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798






1799
1800
1801






1802
1803




1804

1805



1806






1807
1808




1809


1810


1811




1812


1813





1814
1815


1816



1817


1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833


1834

1835
1836
1837

1838
1839
1840
1841
1842










1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
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
1958
1959
1960
1961
1962
1963
1964
1965
1966




1967
1968
1969
1970
1971


1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
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
2095
2096
2097
2098

2099
2100
2101
2102
2103
2104


2105
2106

2107



2108
2109
2110
2111
2112


2113
2114


2115
2116
2117



2118
2119
2120
2121



2122
2123
2124
2125
2126
2127
2128
2129


2130


2131
2132
2133
2134
2135
2136
2137
2138

2139











2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
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
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
2273

2274
2275
2276
2277


2278
2279
2280
2281
2282
2283
2284
2285
2286




2287
2288
2289
2290
2291
2292



2293
2294
2295
2296
2297
2298


2299
2300
2301
2302
2303
2304
2305

2306
2307
2308
2309


2310
2311
2312
2313
2314
2315
2316
2317
2318
2319









2320
2321
2322

2323
2324
2325
2326
2327
2328
2329
2330







-
+

-
+

-
+

+
+
+
-
-
-
-
+
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-

-
-
-
-
-
-
+
+
+
-
-
-

-
-
-
-
-
+
-
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
+
-
-
+
-
-
+
-
-
-
+
-


-
+
-
-
-
-
+
-
-
-
-
+
+
-









-
+


-
+
-
-








+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
-
-
+
+

-
-
-
-
-
-
+
+
-
-
-
-

-
+
-
-
-
+
-
-
-
-
-
-
+

-
-
-
-
+
-
-
+
-
-
+
-
-
-
-
+
-
-
+
-
-
-
-
-
+
+
-
-
+
-
-
-
+
-
-
















-
-
+
-



-




+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
+

+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
+
+


+
+

-
-
-
-
-
-
-
-
+
+
+
-
-

+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+

-
-
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

















-






-
-
+
+
-

-
-
-
+
+
+
+
+
-
-
+

-
-
+
+

-
-
-
+
+
+

-
-
-
+







-
-
+
-
-








-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+
+
+
+
+
+

+
+
+
+
+
-
+
-
-
-
-
-
+
+
+
+
+
+
+
+


-
+



-
+
-
-
-
+
+




















-
+


-
+

-
-
-
-
-
-
-
+
-

-
-
-
-
-
-
-
-
-
+
-
-
+
-

-
+

-



















-


-
+




-
+







-
+



-
-
+
+







-
-
-
-
+
+
+
+
+

-
-
-
+
+
+



-
-
+






-
+



-
-
+
+








-
-
-
-
-
-
-
-
-



-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
ConsoleGetHandleProc(
    ClientData instanceData,	/* The console state. */
    void *instanceData,		/* The console state. */
    TCL_UNUSED(int) /*direction*/,
    ClientData *handlePtr)	/* Where to store the handle. */
    void **handlePtr)		/* Where to store the handle. */
{
    ConsoleInfo *infoPtr = (ConsoleInfo *)instanceData;
    ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData;

    if (chanInfoPtr->handle == INVALID_HANDLE_VALUE) {
	return TCL_ERROR;
    } else {
    *handlePtr = infoPtr->handle;
    return TCL_OK;
}

	*handlePtr = chanInfoPtr->handle;
	return TCL_OK;
    }
}
/*
 *----------------------------------------------------------------------
 *

 * WaitForRead --
 *
 *	Wait until some data is available, the console is at EOF or the reader
 *	thread is blocked waiting for data (if the channel is in non-blocking
 *	mode).
 *
 * Results:
 *	Returns 1 if console is readable. Returns 0 if there is no data on the
 *	console, but there is buffered data. Returns -1 if an error occurred.
 *	If an error occurred, the threads may not be synchronized.
 *
 * Side effects:
 *	Updates the shared state flags. If no error occurred, the reader
 *	thread is blocked waiting for a signal from the main thread.
 *
 *----------------------------------------------------------------------
 */

static int
WaitForRead(
    ConsoleInfo *infoPtr,	/* Console state. */
/*
 *------------------------------------------------------------------------
 *
 * ConsoleDataAvailable --
 *
 *    Checks if there is data in the console input queue.
 *
 * Results:
 *    Returns 1 if the input queue has data, -1 on error else 0 if empty.
 *
 * Side effects:
 *    None.
 *
 *------------------------------------------------------------------------
 */
 static int
 ConsoleDataAvailable(
    HANDLE consoleHandle)
    int blocking)		/* Indicates whether call should be blocking
				 * or not. */
{
    DWORD timeout, count;
    HANDLE *handle = (HANDLE *)infoPtr->handle;
    ConsoleThreadInfo *threadInfo = &infoPtr->reader;
    INPUT_RECORD input;

    while (1) {
    INPUT_RECORD input[10];
    DWORD count;
    DWORD i;
	/*
	 * Synchronize with the reader thread.
	 */

	/* avoid blocking if pipe-thread exited */
	timeout = (!blocking || !TclPipeThreadIsAlive(&threadInfo->TI)
		|| TclInExit() || TclInThreadExit()) ? 0 : INFINITE;
	if (WaitForSingleObject(threadInfo->readyEvent, timeout) == WAIT_TIMEOUT) {
	    /*
    /*
	     * The reader thread is blocked waiting for data and the channel
	     * is in non-blocking mode.
	     */

     * Need at least one keyboard event.
     */
    if (PeekConsoleInputW(consoleHandle, input,
	    errno = EWOULDBLOCK;
	    return -1;
	}
	    sizeof(input) / sizeof(input[0]), &count) == FALSE) {
	return -1;
    }

	/*
	 * At this point, the two threads are synchronized, so it is safe to
	 * access shared state.
	 */

	/*
	 * If the console has hit EOF, it is always readable.
	 */

	if (infoPtr->readFlags & CONSOLE_EOF) {
	    return 1;
	}

	if (PeekConsoleInputW(handle, &input, 1, &count) == FALSE) {
	    /*
	     * Check to see if the peek failed because of EOF.
	     */

	    TclWinConvertError(GetLastError());

	    if (errno == EOF) {
		infoPtr->readFlags |= CONSOLE_EOF;
		return 1;
	    }

	    /*
	     * Ignore errors if there is data in the buffer.
	     */

    /*
     * Even if windows size and mouse events are disabled, can still have
     * events other than keyboard, like focus events. Look for at least one
     * keydown event because a trailing LF keyup is always present from the
     * last input. However, if our buffer is full, assume there is a key
     * down somewhere in the unread buffer. I suppose we could expand the
     * buffer but not worth...
     */
    if (count == (sizeof(input)/sizeof(input[0]))) {
	    if (infoPtr->readFlags & CONSOLE_BUFFERED) {
		return 0;
	return 1;
	    } else {
		return -1;
	    }
    }
	}

    for (i = 0; i < count; ++i) {
	/*
	 * If there is data in the buffer, the console must be readable (since
	if (input[i].EventType == KEY_EVENT
	 * it is a line-oriented device).
	 */

		&& input[i].Event.KeyEvent.bKeyDown) {
	if (infoPtr->readFlags & CONSOLE_BUFFERED) {
	    return 1;
	}

    }
	/*
	 * There wasn't any data available, so reset the thread and try again.
	 */

    return 0;
	ResetEvent(threadInfo->readyEvent);
	TclPipeThreadSignal(&threadInfo->TI);
    }
}
}


/*
 *----------------------------------------------------------------------
 *
 * ConsoleReaderThread --
 *
 *	This function runs in a separate thread and waits for input to become
 *	available on a console.
 *
 * Results:
 *	None.
 *	Always 0.
 *
 * Side effects:
 *	Signals the main thread when input become available. May cause the
 *	Signals the main thread when input become available.
 *	main thread to wake up by posting a message. May one line from the
 *	console for each wait operation.
 *
 *----------------------------------------------------------------------
 */

static DWORD WINAPI
ConsoleReaderThread(
    LPVOID arg)
{
    ConsoleHandleInfo *handleInfoPtr = (ConsoleHandleInfo *) arg;
    ConsoleHandleInfo **iterator;
    Tcl_Size inputLen = 0;
    Tcl_Size inputOffset = 0;
    Tcl_Size lastReadSize = 0;
    DWORD sleepTime;
    char inputChars[INPUT_BUFFER_SIZE];
    TclPipeThreadInfo *pipeTI = (TclPipeThreadInfo *)arg;
    ConsoleInfo *infoPtr = NULL; /* access info only after success init/wait */
    HANDLE *handle = NULL;
    ConsoleThreadInfo *threadInfo = NULL;
    int done = 0;

    while (!done) {
	/*
	 * Wait for the main thread to signal before attempting to read.

    /*
     * Keep looping until one of the following happens.
     * - there are no more channels listening on the console
     * - the console handle has been closed
     */

    /* This thread is holding a reference so pointer is safe */
    AcquireSRWLockExclusive(&handleInfoPtr->lock);

    while (1) {

	if (handleInfoPtr->numRefs == 1) {
	    /*
	     * Sole reference. That's this thread. Exit since no clients
	     * and no way for a thread to attach to a console after process
	     * start.
	     */
	    break;
	}

	/*
	 * Shared buffer has no data. If we have some in our private buffer
	 * copy that. Else check if there has been an error. In both cases
	 * notify the interp threads.
	 */
	if (inputLen > 0 || handleInfoPtr->lastError != 0) {
	    HANDLE consoleHandle;
	    if (inputLen > 0) {
		/* Private buffer has data. Copy it over. */
		Tcl_Size nStored;

		assert((inputLen - inputOffset) > 0);
		nStored = RingBufferIn(&handleInfoPtr->buffer,
			inputOffset + inputChars, inputLen - inputOffset,
			1);
		inputOffset += nStored;
		if (inputOffset == inputLen) {
		    /* Temp buffer now empty */
		    inputOffset = 0;
		    inputLen = 0;
		}
	    } else {
		/*
		 * On error, nothing but inform caller and wait
		 * We do not want to exit until there are no client interps.
		 */
	    }

	    /*
	     * Wake up any threads waiting either synchronously or
	     * asynchronously. Since we are providing data, turn off the
	     * AWAITED flag. If the data provided is not sufficient the
	     * clients will request again. Note we have to wake up ALL
	     * awaiting threads, not just one, so they can all reissue
	     * requests if needed. (In a properly designed app, at most one
	     * thread should be reading standard input but...)
	     */
	    handleInfoPtr->flags &= ~CONSOLE_DATA_AWAITED;
	    /* Wake synchronous channels */
	    WakeAllConditionVariable(&handleInfoPtr->interpThreadCV);
	    /*
	     * Wake up async channels registered for file events. Note in
	     * order to follow the locking hierarchy, we need to release
	     * handleInfoPtr->lock before calling NudgeWatchers.
	     */
	    consoleHandle = handleInfoPtr->console;
	    ReleaseSRWLockExclusive(&handleInfoPtr->lock);
	    NudgeWatchers(consoleHandle);
	    AcquireSRWLockExclusive(&handleInfoPtr->lock);

	    /*
	     * Loop back to recheck for exit conditions changes while the
	     * lock was not held.
	     */
	    continue;
	}

	assert(inputLen == 0);

	/*
	 * Read more data in two cases:
	 * 1. The previous read filled the buffer and there could be more
	 *    data in the console internal *text* buffer. Note
	 *    ConsolePendingInput (checked in ConsoleDataAvailable) will NOT
	 *    show this. It holds input events not yet translated to text.
	 * 2. Tcl threads want more data AND there is data in the
	 *    ConsolePendingInput buffer. The latter check necessary because
	 *    we do not want to read ahead because the interp thread might
	 *    change the read mode, e.g. turning off echo for password
	 *    input. So only do so if at least one interpreter has requested
	 *    data.
	 */
	if (lastReadSize == sizeof(inputChars)
		|| ((handleInfoPtr->flags & CONSOLE_DATA_AWAITED)
		&& ConsoleDataAvailable(handleInfoPtr->console))) {
	    DWORD error;
	    /* Do not hold the lock while blocked in console */
	    ReleaseSRWLockExclusive(&handleInfoPtr->lock);
	    error = ReadConsoleChars(handleInfoPtr->console,
		    (WCHAR *)inputChars, sizeof(inputChars) / sizeof(WCHAR),
		    &inputLen);
	    AcquireSRWLockExclusive(&handleInfoPtr->lock);
	    if (error == 0) {
		inputLen *= sizeof(WCHAR);
		lastReadSize = inputLen;
	    } else {
		/*
		 * We only store the last error. It is up to channel
		 * handlers whether to close or not in case of errors.
		 */
		lastReadSize = 0;
		handleInfoPtr->lastError = error;
		if (handleInfoPtr->lastError == ERROR_INVALID_HANDLE) {
		    handleInfoPtr->console = INVALID_HANDLE_VALUE;

	if (!TclPipeThreadWaitForSignal(&pipeTI)) {
	    /* exit */
		}
	    }
	} else {
	    /*
	     * Either no one was asking for data, or no data was available.
	     * In the former case, wait until someone wakes us asking for
	     * data. In the latter case, there is no alternative but to
	     * poll since ReadConsole does not support async operation.
	     * So sleep for a short while and loop back to retry.
	     */
	    sleepTime =
		handleInfoPtr->flags & CONSOLE_DATA_AWAITED ? 50 : INFINITE;
	    SleepConditionVariableSRW(&handleInfoPtr->consoleThreadCV,
		    &handleInfoPtr->lock, sleepTime, 0);
	}

	/* Loop again to check for exit or wait for readers to wake us */
    }

    /*
     * Exiting:
     * - remove the console from global list
     * - close the handle if still valid
     * - release the structure
     * Note there is not need to check for any watchers because we only
     * exit when there are no channels open to this console.
     */
    ReleaseSRWLockExclusive(&handleInfoPtr->lock);
    AcquireSRWLockExclusive(&gConsoleLock); /* Modifying - exclusive lock */
    for (iterator = &gConsoleHandleInfoList; *iterator;
	    iterator = &(*iterator)->nextPtr) {
	if (*iterator == handleInfoPtr) {
	    *iterator = handleInfoPtr->nextPtr;
	    break;
	}
	if (!infoPtr) {
	    infoPtr = (ConsoleInfo *)pipeTI->clientData;
	    handle = (HANDLE *)infoPtr->handle;
	    threadInfo = &infoPtr->reader;
	}

    }
    ReleaseSRWLockExclusive(&gConsoleLock);

	/*
	 * Look for data on the console, but first ignore any events that are
	 * not KEY_EVENTs.
	 */

	if (ReadConsoleBytes(handle, infoPtr->buffer, CONSOLE_BUFFER_SIZE,
    /* No need for relocking - no other thread should have access to it now */
    RingBufferClear(&handleInfoPtr->buffer);
		(LPDWORD) &infoPtr->bytesRead) != FALSE) {
	    /*
	     * Data was stored in the buffer.
	     */

	    infoPtr->readFlags |= CONSOLE_BUFFERED;
    if (handleInfoPtr->console != INVALID_HANDLE_VALUE
	} else {
	    DWORD err = GetLastError();

	    && handleInfoPtr->lastError != ERROR_INVALID_HANDLE) {
	    if (err == (DWORD) EOF) {
		infoPtr->readFlags = CONSOLE_EOF;
	    }
	    done = 1;
	}

	SetConsoleMode(handleInfoPtr->console, handleInfoPtr->initMode);
	/*
	 * Signal the main thread by signalling the readable event and then
	 * waking up the notifier thread.
	 */

	 * NOTE: we do not call CloseHandle(handleInfoPtr->console) here.
	SetEvent(threadInfo->readyEvent);

	 * As per the GetStdHandle documentation, it need not be closed.
	/*
	 * Alert the foreground thread. Note that we need to treat this like a
	 * Other components may be directly using it. Note however that
	 * critical section so the foreground thread does not terminate this
	 * thread while we are holding a mutex in the notifier code.
	 */

	 * an explicit chan close script command does close the handle
	Tcl_MutexLock(&consoleMutex);
	if (infoPtr->threadId != NULL) {
	 * for all threads.
	    /*
	     * TIP #218. When in flight ignore the event, no one will receive
	     * it anyway.
	     */

	 */
    }
	    Tcl_ThreadAlert(infoPtr->threadId);
	}

	Tcl_MutexUnlock(&consoleMutex);
    }

    Tcl_Free(handleInfoPtr);
    /* Worker exit, so inform the main thread or free TI-structure (if owned) */
    TclPipeThreadExit(&pipeTI);

    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleWriterThread --
 *
 *	This function runs in a separate thread and writes data onto a
 *	console.
 *
 * Results:
 *	Always returns 0.
 *
 * Side effects:

 *	Signals the main thread when an output operation is completed. May
 *	Signals the main thread when an output operation is completed.
 *	cause the main thread to wake up by posting a message.
 *
 *----------------------------------------------------------------------
 */

static DWORD WINAPI
ConsoleWriterThread(
    LPVOID arg)
{
    ConsoleHandleInfo *handleInfoPtr = (ConsoleHandleInfo *) arg;
    TclPipeThreadInfo *pipeTI = (TclPipeThreadInfo *)arg;
    ConsoleInfo *infoPtr = NULL; /* access info only after success init/wait */
    HANDLE *handle = NULL;
    ConsoleThreadInfo *threadInfo = NULL;
    DWORD count, toWrite;
    char *buf;
    int done = 0;

    while (!done) {
	/*
    ConsoleHandleInfo **iterator;
    BOOL success;
    Tcl_Size numBytes;
    /*
     * This buffer size has no relation really with the size of the shared
     * buffer. Could be bigger or smaller. Make larger as multiple threads
     * could potentially be writing to it.
     */
    char buffer[2*CONSOLE_BUFFER_SIZE];

    /*
     * Keep looping until one of the following happens.
     *
     * - there are not more channels listening on the console
     * - the console handle has been closed
     *
     * On each iteration,
     * - if the channel buffer is empty, wait for some channel writer to write
     * - if there is data in our buffer, write it to the console
     */

    /* This thread is holding a reference so pointer is safe */
    AcquireSRWLockExclusive(&handleInfoPtr->lock);
    while (1) {
	/* handleInfoPtr->lock must be held on entry to loop */

	int offset;
	HANDLE consoleHandle;

	/*
	 * Sadly, we need to do another copy because do not want to hold
	 * a lock on handleInfoPtr->buffer while calling WriteConsole as that
	 * might block. Also, we only want to copy an integral number of
	 * WCHAR's, i.e. even number of chars so do some length checks up
	 * front.
	 */
	numBytes = RingBufferLength(&handleInfoPtr->buffer);
	numBytes &= ~1; /* Copy integral number of WCHARs -> even number of bytes */
	if (numBytes == 0) {
	    /* No data to write */
	    if (handleInfoPtr->numRefs == 1) {
		/*
	 * Wait for the main thread to signal before attempting to write.
	 */
		 * Sole reference. That's this thread. Exit since no clients
		 * and no buffered output.
		 */
	if (!TclPipeThreadWaitForSignal(&pipeTI)) {
	    /* exit */
	    break;
	}
	if (!infoPtr) {
		break;
	    }
	    /* Wake up any threads waiting synchronously. */
	    WakeConditionVariable(&handleInfoPtr->interpThreadCV);
	    infoPtr = (ConsoleInfo *)pipeTI->clientData;
	    handle = (HANDLE *)infoPtr->handle;
	    threadInfo = &infoPtr->writer;
	}

	buf = infoPtr->writeBuf;
	toWrite = infoPtr->toWrite;

	    success = SleepConditionVariableSRW(&handleInfoPtr->consoleThreadCV,
		    &handleInfoPtr->lock, INFINITE, 0);
	    /* Note: lock has been acquired again! */
	    if (!success && GetLastError() != ERROR_TIMEOUT) {
		/* TODO - what can be done? Should not happen */
		/* For now keep going */
	    }
	    continue;
	}

	/* We have data to write */
	if ((size_t)numBytes > (sizeof(buffer) / sizeof(buffer[0]))) {
	    numBytes = sizeof(buffer);
	}
	/*
	 * Loop until all of the bytes are written or an error occurs.
	/* No need to check result, we already checked length bytes available */
	 */
	RingBufferOut(&handleInfoPtr->buffer, buffer, numBytes, 0);

	consoleHandle = handleInfoPtr->console;
	WakeConditionVariable(&handleInfoPtr->interpThreadCV);
	ReleaseSRWLockExclusive(&handleInfoPtr->lock);
	offset = 0;
	while (toWrite > 0) {
	    if (WriteConsoleBytes(handle, buf, (DWORD) toWrite,
		    &count) == FALSE) {
		infoPtr->writeError = GetLastError();
		done = 1;
	while (numBytes > 0) {
	    Tcl_Size numWChars = numBytes / sizeof(WCHAR);
	    DWORD status;
	    status = WriteConsoleChars(handleInfoPtr->console,
		    (WCHAR *)(offset + buffer), numWChars, &numWChars);
	    if (status != 0) {
		/* Only overwrite if no previous error */
		if (handleInfoPtr->lastError == 0) {
		    handleInfoPtr->lastError = status;
		}
		if (status == ERROR_INVALID_HANDLE) {
		    handleInfoPtr->console = INVALID_HANDLE_VALUE;
		}
		/* Assume this write is done but keep looping in case
		 * it is a transient error. Not sure just closing handle
		 * and exiting thread is a good idea until all references
		 * from interp threads are gone.
		 */
		break;
	    }
	    toWrite -= count;
	    buf += count;
	    numBytes -= numWChars * sizeof(WCHAR);
	    offset += numWChars * sizeof(WCHAR);
	}

	/* Wake up any threads waiting synchronously. */
	WakeConditionVariable(&handleInfoPtr->interpThreadCV);
	/*
	 * Signal the main thread by signalling the writable event and then
	 * waking up the notifier thread.
	 */

	SetEvent(threadInfo->readyEvent);

	/*
	 * Alert the foreground thread. Note that we need to treat this like a
	 * Wake up all channels registered for file events. Note in
	 * order to follow the locking hierarchy, we cannot hold any locks
	 * when calling NudgeWatchers.
	 * critical section so the foreground thread does not terminate this
	 * thread while we are holding a mutex in the notifier code.
	 */
	NudgeWatchers(consoleHandle);

	Tcl_MutexLock(&consoleMutex);
	if (infoPtr->threadId != NULL) {
	    /*
	     * TIP #218. When in flight ignore the event, no one will receive
	     * it anyway.
	     */

	AcquireSRWLockExclusive(&handleInfoPtr->lock);
    }

    /*
     * Exiting:
     * - remove the console from global list
     * - release the structure
     * NOTE: we do not call CloseHandle(handleInfoPtr->console) here.
     * As per the GetStdHandle documentation, it need not be closed.
     * Other components may be directly using it. Note however that
     * an explicit chan close script command does close the handle
     * for all threads.
     */
    ReleaseSRWLockExclusive(&handleInfoPtr->lock);
    AcquireSRWLockExclusive(&gConsoleLock); /* Modifying - exclusive lock */
    for (iterator = &gConsoleHandleInfoList; *iterator;
	    iterator = &(*iterator)->nextPtr) {
	if (*iterator == handleInfoPtr) {
	    *iterator = handleInfoPtr->nextPtr;
	    break;
	}
	    Tcl_ThreadAlert(infoPtr->threadId);
	}
	Tcl_MutexUnlock(&consoleMutex);
    }
    }
    ReleaseSRWLockExclusive(&gConsoleLock);

    RingBufferClear(&handleInfoPtr->buffer);

    /* Worker exit, so inform the main thread or free TI-structure (if owned) */
    TclPipeThreadExit(&pipeTI);
    Tcl_Free(handleInfoPtr);

    return 0;
}

/*
 *------------------------------------------------------------------------
 *
 * AllocateConsoleHandleInfo --
 *
 *    Allocates a ConsoleHandleInfo for the passed console handle. As
 *    a side effect starts a console thread to handle i/o on the handle.
 *
 *    Important: Caller must be holding an EXCLUSIVE lock on gConsoleLock
 *    when calling this function. The lock continues to be held on return.
 *
 * Results:
 *    Pointer to an unlocked ConsoleHandleInfo structure. The reference
 *    count on the structure is 1. This corresponds to the common reference
 *    from the console thread and the gConsoleHandleInfoList. Returns NULL
 *    on error.
 *
 * Side effects:
 *    A console reader or writer thread is started. The returned structure
 *    is placed on the active console handler list gConsoleHandleInfoList.
 *
 *------------------------------------------------------------------------
 */
static ConsoleHandleInfo *
AllocateConsoleHandleInfo(
    HANDLE consoleHandle,
    int permissions)   /* TCL_READABLE or TCL_WRITABLE */
{
    ConsoleHandleInfo *handleInfoPtr;
    DWORD consoleMode;

    handleInfoPtr = (ConsoleHandleInfo *)Tcl_Alloc(sizeof(*handleInfoPtr));
    memset(handleInfoPtr, 0, sizeof(*handleInfoPtr));
    handleInfoPtr->console = consoleHandle;
    InitializeSRWLock(&handleInfoPtr->lock);
    InitializeConditionVariable(&handleInfoPtr->consoleThreadCV);
    InitializeConditionVariable(&handleInfoPtr->interpThreadCV);
    RingBufferInit(&handleInfoPtr->buffer, CONSOLE_BUFFER_SIZE);
    handleInfoPtr->lastError = 0;
    handleInfoPtr->permissions = permissions;
    handleInfoPtr->numRefs = 1; /* See function header */
    if (permissions == TCL_READABLE) {
	GetConsoleMode(consoleHandle, &handleInfoPtr->initMode);
	consoleMode = handleInfoPtr->initMode;
	consoleMode &= ~(ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);
	consoleMode |= ENABLE_LINE_INPUT;
	SetConsoleMode(consoleHandle, consoleMode);
    }
    handleInfoPtr->consoleThread = CreateThread(
	NULL, /* default security descriptor */
	2*CONSOLE_BUFFER_SIZE, /* Stack size - gets rounded up to granularity */
	permissions == TCL_READABLE ? ConsoleReaderThread : ConsoleWriterThread,
	handleInfoPtr, /* Pass to thread */
	0,             /* Flags - no special cases */
	NULL);         /* Don't care about thread id */
    if (handleInfoPtr->consoleThread == NULL) {
	/* Note - SRWLock and condition variables do not need finalization */
	RingBufferClear(&handleInfoPtr->buffer);
	Tcl_Free(handleInfoPtr);
	return NULL;
    }

    /* Chain onto global list */
    handleInfoPtr->nextPtr = gConsoleHandleInfoList;
    gConsoleHandleInfoList = handleInfoPtr;

    return handleInfoPtr;
}

/*
 *------------------------------------------------------------------------
 *
 * FindConsoleInfo --
 *
 *    Finds the ConsoleHandleInfo record for a given ConsoleChannelInfo.
 *    The found record must match the console handle. It is the caller's
 *    responsibility to check the permissions (read/write) in the returned
 *    ConsoleHandleInfo match permissions in chanInfoPtr. This function does
 *    not check that.
 *
 *    Important: Caller must be holding an shared or exclusive lock on
 *    gConsoleMutex. That ensures the returned pointer stays valid on
 *    return without risk of deallocation by other threads.
 *
 * Results:
 *    Pointer to the found ConsoleHandleInfo or NULL if not found
 *
 * Side effects:
 *    None.
 *
 *------------------------------------------------------------------------
 */
static ConsoleHandleInfo *
FindConsoleInfo(
    const ConsoleChannelInfo *chanInfoPtr)
{
    ConsoleHandleInfo *handleInfoPtr;
    for (handleInfoPtr = gConsoleHandleInfoList; handleInfoPtr; handleInfoPtr = handleInfoPtr->nextPtr) {
	if (handleInfoPtr->console == chanInfoPtr->handle) {
	    return handleInfoPtr;
	}
    }
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * TclWinOpenConsoleChannel --
 *
 *	Constructs a Console channel for the specified standard OS handle.
 *	This is a helper function to break up the construction of channels
 *	into File, Console, or Serial.
 *
 * Results:
 *	Returns the new channel, or NULL.
 *
 * Side effects:
 *	May open the channel.
 *
 *----------------------------------------------------------------------
 */

Tcl_Channel
TclWinOpenConsoleChannel(
    HANDLE handle,
    char *channelName,
    int permissions)
{
    char encoding[4 + TCL_INTEGER_SPACE];
    ConsoleInfo *infoPtr;
    ConsoleChannelInfo *chanInfoPtr;
    ConsoleHandleInfo *handleInfoPtr;
    DWORD modes;

    ConsoleInit();

    /*
    /* A console handle can either be input or output, not both */
    if (permissions != TCL_READABLE && permissions != TCL_WRITABLE) {
	return NULL;
    }

     * See if a channel with this handle already exists.
     */
    ConsoleInit();

    infoPtr = (ConsoleInfo *)Tcl_Alloc(sizeof(ConsoleInfo));
    memset(infoPtr, 0, sizeof(ConsoleInfo));
    chanInfoPtr = (ConsoleChannelInfo *)Tcl_Alloc(sizeof(*chanInfoPtr));
    memset(chanInfoPtr, 0, sizeof(*chanInfoPtr));

    infoPtr->validMask = permissions;
    infoPtr->handle = handle;
    infoPtr->channel = (Tcl_Channel) NULL;
    chanInfoPtr->permissions = permissions;
    chanInfoPtr->handle = handle;
    chanInfoPtr->channel = (Tcl_Channel) NULL;

    wsprintfA(encoding, "cp%d", GetConsoleCP());

    infoPtr->threadId = Tcl_GetCurrentThread();
    chanInfoPtr->threadId = Tcl_GetCurrentThread();

    /*
     * Use the pointer for the name of the result channel. This keeps the
     * channel names unique, since some may share handles (stdin/stdout/stderr
     * for instance).
     */

    sprintf(channelName, "file%" TCL_Z_MODIFIER "x", (size_t) infoPtr);

    TclWinGenerateChannelName(channelName, "file", chanInfoPtr);
    infoPtr->channel = Tcl_CreateChannel(&consoleChannelType, channelName,
	    infoPtr, permissions);

    if (permissions & TCL_READABLE) {
	/*
	 * Make sure the console input buffer is ready for only character
	 * input notifications and the buffer is set for line buffering. IOW,
	 * we only want to catch when complete lines are ready for reading.
	 */

	infoPtr->flags |= CONSOLE_READ_OPS;
	chanInfoPtr->flags |= CONSOLE_READ_OPS;
	GetConsoleMode(infoPtr->handle, &infoPtr->initMode);
	modes = infoPtr->initMode;
	modes &= ~(ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);
	modes |= ENABLE_LINE_INPUT;
	SetConsoleMode(infoPtr->handle, modes);

	infoPtr->reader.readyEvent = CreateEventW(NULL, TRUE, TRUE, NULL);
	infoPtr->reader.thread = CreateThread(NULL, 256, ConsoleReaderThread,
		TclPipeThreadCreateTI(&infoPtr->reader.TI, infoPtr,
			infoPtr->reader.readyEvent), 0, NULL);
	SetThreadPriority(infoPtr->reader.thread, THREAD_PRIORITY_HIGHEST);
	GetConsoleMode(handle, &chanInfoPtr->initMode);

#ifdef OBSOLETE
	/* Why was priority being set on console input? Code smell */
	SetThreadPriority(infoPtr->reader.thread, THREAD_PRIORITY_HIGHEST);
#endif
    } else {
	/* Already checked permissions is WRITABLE if not READABLE */
	/* TODO - enable ansi escape processing? */
    }

    /*
     * Global lock but that's ok. See comments top of file. Allocations
     * will happen only a few times in the life of a process and that too
     * generally at start up where only one thread is active.
     */
    AcquireSRWLockExclusive(&gConsoleLock); /*Allocate needs exclusive lock */

    handleInfoPtr = FindConsoleInfo(chanInfoPtr);
    if (handleInfoPtr == NULL) {
	/* Not found. Allocate one */
	handleInfoPtr = AllocateConsoleHandleInfo(handle, permissions);
    } else {
	/* Found. Its direction (read/write) better be the same */
	if (handleInfoPtr->permissions != permissions) {
	    handleInfoPtr = NULL;
	}
    }

    if (handleInfoPtr == NULL) {
	ReleaseSRWLockExclusive(&gConsoleLock);
	if (permissions == TCL_READABLE) {
	    SetConsoleMode(handle, chanInfoPtr->initMode);
	}
	Tcl_Free(chanInfoPtr);
	return NULL;
    }

    if (permissions & TCL_WRITABLE) {
    /*
     * There is effectively a reference to this structure from the Tcl
     * channel subsystem. So record that. This reference will be dropped
     * when the Tcl channel is closed.
     */
    chanInfoPtr->numRefs = 1;

    /*
     * Need to keep track of number of referencing channels for closing.
     * The pointer is safe since there is a reference held to it from
     * gConsoleHandleInfoList but still need to lock the structure itself
     */
	infoPtr->writer.readyEvent = CreateEventW(NULL, TRUE, TRUE, NULL);
    AcquireSRWLockExclusive(&handleInfoPtr->lock);
	infoPtr->writer.thread = CreateThread(NULL, 256, ConsoleWriterThread,
		TclPipeThreadCreateTI(&infoPtr->writer.TI, infoPtr,
			infoPtr->writer.readyEvent), 0, NULL);
	SetThreadPriority(infoPtr->writer.thread, THREAD_PRIORITY_HIGHEST);
    }
    handleInfoPtr->numRefs += 1;
    ReleaseSRWLockExclusive(&handleInfoPtr->lock);

    ReleaseSRWLockExclusive(&gConsoleLock);

    /* Note Tcl_CreateChannel never fails other than panic on error */
    chanInfoPtr->channel = Tcl_CreateChannel(&consoleChannelType, channelName,
	    chanInfoPtr, permissions);

    /*
     * Files have default translation of AUTO and ^Z eof char, which means
     * Consoles have default translation of auto and ^Z eof char, which means
     * that a ^Z will be accepted as EOF when reading.
     */

    Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto");
    Tcl_SetChannelOption(NULL, chanInfoPtr->channel, "-translation", "auto");
    Tcl_SetChannelOption(NULL, infoPtr->channel, "-eofchar", "\032 {}");
    Tcl_SetChannelOption(NULL, infoPtr->channel, "-encoding", "utf-16");
    return infoPtr->channel;
    Tcl_SetChannelOption(NULL, chanInfoPtr->channel, "-encoding", "utf-16");
    return chanInfoPtr->channel;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleThreadActionProc --
 *
 *	Insert or remove any thread local refs to this channel.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Changes thread local list of valid channels.
 *
 *----------------------------------------------------------------------
 */

static void
ConsoleThreadActionProc(
    ClientData instanceData,
    void *instanceData,
    int action)
{
    ConsoleInfo *infoPtr = (ConsoleInfo *)instanceData;
    ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData;

    /*
     * We do not access firstConsolePtr in the thread structures. This is not
     * for all serials managed by the thread, but only those we are watching.
     * Removal of the filevent handlers before transfer thus takes care of
     * this structure.
     */

    /* No need for any locks as no other thread will be writing to it */
    Tcl_MutexLock(&consoleMutex);
    if (action == TCL_CHANNEL_THREAD_INSERT) {
	/*
	 * We can't copy the thread information from the channel when the
	 * channel is created. At this time the channel back pointer has not
	 * been set yet. However in that case the threadId has already been
	 * set by TclpCreateCommandChannel itself, so the structure is still
	 * good.
	 */

	ConsoleInit();
	ConsoleInit(); /* Needed to set up event source handlers for this thread */
	if (infoPtr->channel != NULL) {
	    infoPtr->threadId = Tcl_GetChannelThread(infoPtr->channel);
	chanInfoPtr->threadId = Tcl_GetCurrentThread();
	}
    } else {
	infoPtr->threadId = NULL;
	chanInfoPtr->threadId = NULL;
    }
    Tcl_MutexUnlock(&consoleMutex);
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleSetOptionProc --
 *
 *	Sets an option on a channel.
 *
 * Results:
 *	A standard Tcl result. Also sets the interp's result on error if
 *	interp is not NULL.
 *
 * Side effects:
 *	May modify an option on a console. Sets Error message if needed (by
 *	calling Tcl_BadChannelOption).
 *
 *----------------------------------------------------------------------
 */

static int
ConsoleSetOptionProc(
    ClientData instanceData,	/* File state. */
    void *instanceData,	/* File state. */
    Tcl_Interp *interp,		/* For error reporting - can be NULL. */
    const char *optionName,	/* Which option to set? */
    const char *value)		/* New value for option. */
{
    ConsoleInfo *infoPtr = (ConsoleInfo *)instanceData;
    ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData;
    int len = strlen(optionName);
    int vlen = strlen(value);

    /*
     * Option -inputmode normal|password|raw
     */

    if ((infoPtr->flags & CONSOLE_READ_OPS) && (len > 1) &&
    if ((chanInfoPtr->flags & CONSOLE_READ_OPS) && (len > 1) &&
	    (strncmp(optionName, "-inputmode", len) == 0)) {
	DWORD mode;

	if (GetConsoleMode(infoPtr->handle, &mode) == 0) {
	    TclWinConvertError(GetLastError());
	if (GetConsoleMode(chanInfoPtr->handle, &mode) == 0) {
	    Tcl_WinConvertError(GetLastError());
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"couldn't read console mode: %s",
			Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}
	if (Tcl_UtfNcasecmp(value, "NORMAL", vlen) == 0) {
	    mode |= ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT;
	} else if (Tcl_UtfNcasecmp(value, "PASSWORD", vlen) == 0) {
	    mode |= ENABLE_LINE_INPUT;
	if (strncasecmp(value, "NORMAL", vlen) == 0) {
	    mode |=
		ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
	} else if (strncasecmp(value, "PASSWORD", vlen) == 0) {
	    mode |= ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT;
	    mode &= ~ENABLE_ECHO_INPUT;
	} else if (Tcl_UtfNcasecmp(value, "RAW", vlen) == 0) {
	    mode &= ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT);
	} else if (Tcl_UtfNcasecmp(value, "RESET", vlen) == 0) {
	} else if (strncasecmp(value, "RAW", vlen) == 0) {
	    mode &= ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
	} else if (strncasecmp(value, "RESET", vlen) == 0) {
	    /*
	     * Reset to the initial mode, whatever that is.
	     */

	    mode = infoPtr->initMode;
	    mode = chanInfoPtr->initMode;
	} else {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"bad mode \"%s\" for -inputmode: must be"
			" normal, password, raw, or reset", value));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "FCONFIGURE",
			"VALUE", NULL);
			"VALUE", (char *)NULL);
	    }
	    return TCL_ERROR;
	}
	if (SetConsoleMode(infoPtr->handle, mode) == 0) {
	    TclWinConvertError(GetLastError());
	if (SetConsoleMode(chanInfoPtr->handle, mode) == 0) {
	    Tcl_WinConvertError(GetLastError());
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"couldn't set console mode: %s",
			Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}

	/*
	 * If we've changed the mode from default, schedule a reset later.
	 */

	if (mode == infoPtr->initMode) {
	    infoPtr->flags &= ~CONSOLE_RESET;
	} else {
	    infoPtr->flags |= CONSOLE_RESET;
	}
	return TCL_OK;
    }

    if (infoPtr->flags & CONSOLE_READ_OPS) {
    if (chanInfoPtr->flags & CONSOLE_READ_OPS) {
	return Tcl_BadChannelOption(interp, optionName, "inputmode");
    } else {
	return Tcl_BadChannelOption(interp, optionName, "");
    }
}

/*
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
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
2399










2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
















2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437


2438
2439
2440

2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451







-
+




-
+

















-
+







-
-
+
+

















-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
-
+
+

-
+










 *	(by calling Tcl_BadChannelOption).
 *
 *----------------------------------------------------------------------
 */

static int
ConsoleGetOptionProc(
    ClientData instanceData,	/* File state. */
    void *instanceData,	/* File state. */
    Tcl_Interp *interp,		/* For error reporting - can be NULL. */
    const char *optionName,	/* Option to get. */
    Tcl_DString *dsPtr)		/* Where to store value(s). */
{
    ConsoleInfo *infoPtr = (ConsoleInfo *)instanceData;
    ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData;
    int valid = 0;		/* Flag if valid option parsed. */
    unsigned int len;
    char buf[TCL_INTEGER_SPACE];

    if (optionName == NULL) {
	len = 0;
    } else {
	len = strlen(optionName);
    }

    /*
     * Get option -inputmode
     *
     * This is a great simplification of the underlying reality, but actually
     * represents what almost all scripts really want to know.
     */

    if (infoPtr->flags & CONSOLE_READ_OPS) {
    if (chanInfoPtr->flags & CONSOLE_READ_OPS) {
	if (len == 0) {
	    Tcl_DStringAppendElement(dsPtr, "-inputmode");
	}
	if (len==0 || (len>1 && strncmp(optionName, "-inputmode", len)==0)) {
	    DWORD mode;

	    valid = 1;
	    if (GetConsoleMode(infoPtr->handle, &mode) == 0) {
		TclWinConvertError(GetLastError());
	    if (GetConsoleMode(chanInfoPtr->handle, &mode) == 0) {
		Tcl_WinConvertError(GetLastError());
		if (interp != NULL) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "couldn't read console mode: %s",
			    Tcl_PosixError(interp)));
		}
		return TCL_ERROR;
	    }
	    if (mode & ENABLE_LINE_INPUT) {
		if (mode & ENABLE_ECHO_INPUT) {
		    Tcl_DStringAppendElement(dsPtr, "normal");
		} else {
		    Tcl_DStringAppendElement(dsPtr, "password");
		}
	    } else {
		Tcl_DStringAppendElement(dsPtr, "raw");
	    }
	}
    }

    /*
     * Get option -winsize
     * Option is readonly and returned by [fconfigure chan -winsize] but not
     * returned by [fconfigure chan] without explicit option name.
     */

    if ((len > 1) && (strncmp(optionName, "-winsize", len) == 0)) {
	CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
    } else {
	/*
	 * Output channel. Get option -winsize
	 * Option is readonly and returned by [fconfigure chan -winsize] but not
	 * returned by [fconfigure chan] without explicit option name.
	 */
	if (len == 0) {
	    Tcl_DStringAppendElement(dsPtr, "-winsize");
	}

	if (len == 0 || (len > 1 && strncmp(optionName, "-winsize", len) == 0)) {
	    CONSOLE_SCREEN_BUFFER_INFO consoleInfo;

	valid = 1;
	if (!GetConsoleScreenBufferInfo(infoPtr->handle, &consoleInfo)) {
	    TclWinConvertError(GetLastError());
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"couldn't read console size: %s",
			Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}
	sprintf(buf, "%d",
		consoleInfo.srWindow.Right - consoleInfo.srWindow.Left + 1);
	Tcl_DStringAppendElement(dsPtr, buf);
	sprintf(buf, "%d",
		consoleInfo.srWindow.Bottom - consoleInfo.srWindow.Top + 1);
	Tcl_DStringAppendElement(dsPtr, buf);
	    valid = 1;
	    if (!GetConsoleScreenBufferInfo(chanInfoPtr->handle,
		    &consoleInfo)) {
		Tcl_WinConvertError(GetLastError());
		if (interp != NULL) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "couldn't read console size: %s",
			    Tcl_PosixError(interp)));
		}
		return TCL_ERROR;
	    }
	    Tcl_DStringStartSublist(dsPtr);
	    snprintf(buf, sizeof(buf), "%d",
		    consoleInfo.srWindow.Right - consoleInfo.srWindow.Left + 1);
	    Tcl_DStringAppendElement(dsPtr, buf);
	    snprintf(buf, sizeof(buf), "%d",
		    consoleInfo.srWindow.Bottom - consoleInfo.srWindow.Top + 1);
	    Tcl_DStringAppendElement(dsPtr, buf);
	    Tcl_DStringEndSublist(dsPtr);
	}
    }

    if (valid) {
	return TCL_OK;
    }
    if (infoPtr->flags & CONSOLE_READ_OPS) {
	return Tcl_BadChannelOption(interp, optionName, "inputmode winsize");
    if (chanInfoPtr->flags & CONSOLE_READ_OPS) {
	return Tcl_BadChannelOption(interp, optionName, "inputmode");
    } else {
	return Tcl_BadChannelOption(interp, optionName, "");
	return Tcl_BadChannelOption(interp, optionName, "winsize");
    }
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to win/tclWinDde.c.

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
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







-
+










+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+







 */

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.4.3"
#define TCL_DDE_VERSION		"1.4.5"
#define TCL_DDE_PACKAGE_NAME	"dde"
#define TCL_DDE_SERVICE_NAME	L"TclEval"
#define TCL_DDE_EXECUTE_RESULT	L"$TCLEVAL$EXECUTE$RESULT"

#define DDE_FLAG_ASYNC 1
#define DDE_FLAG_BINARY 2
#define DDE_FLAG_FORCE 4

TCL_DECLARE_MUTEX(ddeMutex)

#if (TCL_MAJOR_VERSION < 9) && defined(TCL_MINOR_VERSION) && (TCL_MINOR_VERSION < 7)
# if TCL_UTF_MAX > 3
#   define Tcl_WCharToUtfDString(a,b,c) Tcl_WinTCharToUtf((TCHAR *)(a),(b)*sizeof(WCHAR),c)
#   define Tcl_UtfToWCharDString(a,b,c) (WCHAR *)Tcl_WinUtfToTChar(a,b,c)
# else
#   define Tcl_WCharToUtfDString Tcl_UniCharToUtfDString
#   define Tcl_UtfToWCharDString Tcl_UtfToUniCharDString
# endif
#ifndef Tcl_Size
#   define Tcl_Size int
#endif
#ifndef Tcl_CreateObjCommand2
#   define Tcl_CreateObjCommand2 Tcl_CreateObjCommand
#endif
#endif

/*
 * Forward declarations for functions defined later in this file.
 * Declarations for functions defined in this file.
 */

static LRESULT CALLBACK	DdeClientWindowProc(HWND hwnd, UINT uMsg,
			    WPARAM wParam, LPARAM lParam);
static int		DdeCreateClient(DdeEnumServices *es);
static BOOL CALLBACK	DdeEnumWindowsCallback(HWND hwndTarget,
			    LPARAM lParam);
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
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







-
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-





+
+
+
+
+







static void		DeleteProc(void *clientData);
static Tcl_Obj *	ExecuteRemoteObject(RegisteredInterp *riPtr,
			    Tcl_Obj *ddeObjectPtr);
static int		MakeDdeConnection(Tcl_Interp *interp,
			    const WCHAR *name, HCONV *ddeConvPtr);
static void		SetDdeError(Tcl_Interp *interp);
static int		DdeObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Interp *interp, Tcl_Size objc,
			    Tcl_Obj *const objv[]);

#if (TCL_MAJOR_VERSION < 9) && (TCL_MINOR_VERSION < 7)
# if TCL_UTF_MAX > 3
#   define Tcl_WCharToUtfDString(a,b,c) Tcl_WinTCharToUtf((TCHAR *)(a),(b)*sizeof(WCHAR),c)
#   define Tcl_UtfToWCharDString(a,b,c) (WCHAR *)Tcl_WinUtfToTChar(a,b,c)
# else
#   define Tcl_WCharToUtfDString Tcl_UniCharToUtfDString
#   define Tcl_UtfToWCharDString Tcl_UtfToUniCharDString
# endif
#endif

static unsigned char *
getByteArrayFromObj(
	Tcl_Obj *objPtr,
	size_t *lengthPtr
) {
    int length;

    unsigned char *result = Tcl_GetByteArrayFromObj(objPtr, &length);
#if TCL_MAJOR_VERSION > 8
    if (sizeof(TCL_HASH_TYPE) > sizeof(int)) {
	/* 64-bit and TIP #494 situation: */
	 *lengthPtr = *(TCL_HASH_TYPE *) objPtr->internalRep.twoPtrValue.ptr1;
    } else
#endif
	/* 32-bit or without TIP #494 */
    *lengthPtr = (size_t) (unsigned) length;
    return result;
}

#ifdef __cplusplus
extern "C" {
#endif
DLLEXPORT int		Dde_Init(Tcl_Interp *interp);
DLLEXPORT int		Dde_SafeInit(Tcl_Interp *interp);
#if TCL_MAJOR_VERSION < 9
/* With those additional entries, "load tcldde14.dll" works without 3th argument */
DLLEXPORT int		Tcldde_Init(Tcl_Interp *interp);
DLLEXPORT int		Tcldde_SafeInit(Tcl_Interp *interp);
#endif
#ifdef __cplusplus
}
#endif

/*
 *----------------------------------------------------------------------
 *
171
172
173
174
175
176
177
178

179
180
181
182

183
184
185








186
187
188
189
190
191
192
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







-
+



-
+



+
+
+
+
+
+
+
+







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

int
Dde_Init(
    Tcl_Interp *interp)
{
    if (!Tcl_InitStubs(interp, "8.5", 0)) {
    if (!Tcl_InitStubs(interp, "8.5-", 0)) {
	return TCL_ERROR;
    }

    Tcl_CreateObjCommand(interp, "dde", DdeObjCmd, NULL, NULL);
    Tcl_CreateObjCommand2(interp, "dde", DdeObjCmd, NULL, NULL);
    Tcl_CreateExitHandler(DdeExitProc, NULL);
    return Tcl_PkgProvideEx(interp, TCL_DDE_PACKAGE_NAME, TCL_DDE_VERSION, NULL);
}
#if TCL_MAJOR_VERSION < 9
int
Tcldde_Init(
    Tcl_Interp *interp)
{
    return Dde_Init(interp);
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * Dde_SafeInit --
 *
 *	This function initializes the dde command within a safe interp
206
207
208
209
210
211
212








213
214
215
216
217
218
219
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227







+
+
+
+
+
+
+
+







{
    int result = Dde_Init(interp);
    if (result == TCL_OK) {
	Tcl_HideCommand(interp, "dde", "dde");
    }
    return result;
}
#if TCL_MAJOR_VERSION < 9
int
Tcldde_SafeInit(
    Tcl_Interp *interp)
{
    return Dde_SafeInit(interp);
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * Initialize --
 *
 *	Initialize the global DDE instance.
305
306
307
308
309
310
311
312

313
314
315
316

317

318
319
320
321
322
323
324
313
314
315
316
317
318
319

320
321
322
323
324
325

326
327
328
329
330
331
332
333







-
+




+
-
+







    const WCHAR *name, /* The name that will be used to refer to the
				 * interpreter in later "send" commands. Must
				 * be globally unique. */
    int flags,		/* DDE_FLAG_FORCE or 0 */
    Tcl_Obj *handlerPtr)	/* Name of the optional proc/command to handle
				 * incoming Dde eval's */
{
    int suffix, offset;
    int suffix;
    RegisteredInterp *riPtr, *prevPtr;
    Tcl_DString dString;
    const WCHAR *actualName;
    Tcl_Obj *srvListPtr = NULL, **srvPtrPtr = NULL;
    Tcl_Size n, srvCount = 0, offset;
    int n, srvCount = 0, lastSuffix, r = TCL_OK;
    int lastSuffix, r = TCL_OK;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    /*
     * See if the application is already registered; if so, remove its current
     * name from the registry. The deletion of the command will take care of
     * disposing of this entry.
     */
436
437
438
439
440
441
442
443

444
445
446
447
448
449
450
445
446
447
448
449
450
451

452
453
454
455
456
457
458
459







-
+







    tsdPtr->interpListPtr = riPtr;
    wcscpy(riPtr->name, actualName);

    if (Tcl_IsSafe(interp)) {
	Tcl_ExposeCommand(interp, "dde", "dde");
    }

    Tcl_CreateObjCommand(interp, "dde", DdeObjCmd,
    Tcl_CreateObjCommand2(interp, "dde", DdeObjCmd,
	    riPtr, DeleteProc);
    if (Tcl_IsSafe(interp)) {
	Tcl_HideCommand(interp, "dde", "dde");
    }
    Tcl_DStringFree(&dString);

    /*
565
566
567
568
569
570
571
572

573
574
575
576
577
578
579
574
575
576
577
578
579
580

581
582
583
584
585
586
587
588







-
+







    Tcl_Obj *returnPackagePtr;
    int result = TCL_OK;

    if ((riPtr->handlerPtr == NULL) && Tcl_IsSafe(riPtr->interp)) {
	Tcl_SetObjResult(riPtr->interp, Tcl_NewStringObj("permission denied: "
		"a handler procedure must be defined for use in a safe "
		"interp", -1));
	Tcl_SetErrorCode(riPtr->interp, "TCL", "DDE", "SECURITY_CHECK", NULL);
	Tcl_SetErrorCode(riPtr->interp, "TCL", "DDE", "SECURITY_CHECK", (char *)NULL);
	result = TCL_ERROR;
    }

    if (riPtr->handlerPtr != NULL) {
	/*
	 * Add the dde request data to the handler proc list.
	 */
643
644
645
646
647
648
649
650

651
652
653
654
655
656
657
652
653
654
655
656
657
658

659
660
661
662
663
664
665
666







-
+







    HSZ ddeTopic, HSZ ddeItem,	/* String handles. Transaction-type
				 * dependent. */
    HDDEDATA hData,		/* DDE data. Transaction-type dependent. */
    DWORD unused1, DWORD unused2)
				/* Transaction-dependent data. */
{
    Tcl_DString dString;
    size_t len;
    Tcl_Size len;
    DWORD dlen;
    WCHAR *utilString;
    Tcl_Obj *ddeObjectPtr;
    HDDEDATA ddeReturn = NULL;
    RegisteredInterp *riPtr;
    Conversation *convPtr, *prevConvPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
763
764
765
766
767
768
769
770

771
772
773
774
775
776
777
778
772
773
774
775
776
777
778

779

780
781
782
783
784
785
786







-
+
-







	    Tcl_DStringInit(&dsBuf);
	    Tcl_DStringSetLength(&dString, (len + 1) * sizeof(WCHAR) - 1);
	    utilString = (WCHAR *) Tcl_DStringValue(&dString);
	    DdeQueryStringW(ddeInstance, ddeItem, utilString, (DWORD) len + 1,
		    CP_WINUNICODE);
	    if (_wcsicmp(utilString, TCL_DDE_EXECUTE_RESULT) == 0) {
		returnString =
			Tcl_GetString(convPtr->returnPackagePtr);
			Tcl_GetStringFromObj(convPtr->returnPackagePtr, &len);
		len = convPtr->returnPackagePtr->length;
		if (uFmt != CF_TEXT) {
		    Tcl_DStringInit(&dsBuf);
		    Tcl_UtfToWCharDString(returnString, len, &dsBuf);
		    returnString = Tcl_DStringValue(&dsBuf);
		    len = Tcl_DStringLength(&dsBuf) + sizeof(WCHAR) - 1;
		}
		ddeReturn = DdeCreateDataHandle(ddeInstance, (BYTE *)returnString,
786
787
788
789
790
791
792
793

794
795
796
797
798
799
800
801
794
795
796
797
798
799
800

801

802
803
804
805
806
807
808







-
+
-








		    Tcl_DStringInit(&ds);
		    Tcl_WCharToUtfDString(utilString, wcslen(utilString), &ds);
		    variableObjPtr = Tcl_GetVar2Ex(
			    convPtr->riPtr->interp, Tcl_DStringValue(&ds), NULL,
			    TCL_GLOBAL_ONLY);
		    if (variableObjPtr != NULL) {
			returnString = Tcl_GetString(variableObjPtr);
			returnString = Tcl_GetStringFromObj(variableObjPtr, &len);
			len = variableObjPtr->length;
			if (uFmt != CF_TEXT) {
			    Tcl_DStringInit(&dsBuf);
			    Tcl_UtfToWCharDString(returnString, len, &dsBuf);
			    returnString = Tcl_DStringValue(&dsBuf);
			    len = Tcl_DStringLength(&dsBuf) + sizeof(WCHAR) - 1;
			}
			ddeReturn = DdeCreateDataHandle(ddeInstance,
864
865
866
867
868
869
870
871

872
873
874
875
876
877
878
871
872
873
874
875
876
877

878
879
880
881
882
883
884
885







-
+







	}
	return ddeReturn;

#endif
    case XTYP_EXECUTE: {
	/*
	 * Execute this script. The results will be saved into a list object
	 * which will be retreived later. See ExecuteRemoteObject.
	 * which will be retrieved later. See ExecuteRemoteObject.
	 */

	Tcl_Obj *returnPackagePtr;
	char *string;

	for (convPtr = tsdPtr->currentConversations; (convPtr != NULL)
		&& (convPtr->hConv != hConv); convPtr = convPtr->nextPtr) {
887
888
889
890
891
892
893
894

895
896
897
898
899
900

901
902
903
904
905
906
907
894
895
896
897
898
899
900

901
902
903
904
905
906

907
908
909
910
911
912
913
914







-
+





-
+








	utilString = (WCHAR *) DdeAccessData(hData, &dlen);
	string = (char *) utilString;
	if (!dlen) {
	    /* Empty binary array. */
	    ddeObjectPtr = Tcl_NewObj();
	} else if ((dlen & 1) || utilString[(dlen>>1)-1]) {
	    /* Cannot be unicode, so assume utf-8 */
	    /* Cannot be Unicode, so assume utf-8 */
	    if (!string[dlen-1]) {
		dlen--;
	    }
	    ddeObjectPtr = Tcl_NewStringObj(string, dlen);
	} else {
	    /* unicode */
	    /* Unicode */
	    Tcl_DString dsBuf;

	    Tcl_DStringInit(&dsBuf);
	    Tcl_WCharToUtfDString(utilString, (dlen>>1) - 1, &dsBuf);
	    ddeObjectPtr = Tcl_NewStringObj(Tcl_DStringValue(&dsBuf),
		    Tcl_DStringLength(&dsBuf));
	    Tcl_DStringFree(&dsBuf);
935
936
937
938
939
940
941
942
943


944
945
946
947
948
949
950
951



952

953
954

955
956
957

958
959
960
961
962
963
964
942
943
944
945
946
947
948


949
950
951
952
953
954
955
956
957
958
959
960
961

962
963

964
965
966

967
968
969
970
971
972
973
974







-
-
+
+








+
+
+
-
+

-
+


-
+








    case XTYP_WILDCONNECT: {
	/*
	 * Dde wants a list of services and topics that we support.
	 */

	HSZPAIR *returnPtr;
	int i;
	int numItems;
	Tcl_Size i;
	DWORD numItems;

	for (i = 0, riPtr = tsdPtr->interpListPtr; riPtr != NULL;
		i++, riPtr = riPtr->nextPtr) {
	    /*
	     * Empty loop body.
	     */
	}

	if ((size_t)i >= UINT_MAX/sizeof(HSZPAIR)) {
	    return NULL;
	}
	numItems = i;
	numItems = (DWORD)i;
	ddeReturn = DdeCreateDataHandle(ddeInstance, NULL,
		(numItems + 1) * sizeof(HSZPAIR), 0, 0, 0, 0);
		(numItems + 1) * (DWORD)sizeof(HSZPAIR), 0, 0, 0, 0);
	returnPtr = (HSZPAIR *) DdeAccessData(ddeReturn, &dlen);
	len = dlen;
	for (i = 0, riPtr = tsdPtr->interpListPtr; i < numItems;
	for (i = 0, riPtr = tsdPtr->interpListPtr; i < (Tcl_Size)numItems;
		i++, riPtr = riPtr->nextPtr) {
	    returnPtr[i].hszSvc = DdeCreateStringHandleW(ddeInstance,
		    TCL_DDE_SERVICE_NAME, CP_WINUNICODE);
	    returnPtr[i].hszTopic = DdeCreateStringHandleW(ddeInstance,
		    riPtr->name, CP_WINUNICODE);
	}
	returnPtr[i].hszSvc = NULL;
1036
1037
1038
1039
1040
1041
1042
1043

1044
1045
1046
1047
1048
1049
1050
1046
1047
1048
1049
1050
1051
1052

1053
1054
1055
1056
1057
1058
1059
1060







-
+







	    Tcl_DString dString;

	    Tcl_DStringInit(&dString);
	    Tcl_WCharToUtfDString(name, wcslen(name), &dString);
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "no registered server named \"%s\"", Tcl_DStringValue(&dString)));
	    Tcl_DStringFree(&dString);
	    Tcl_SetErrorCode(interp, "TCL", "DDE", "NO_SERVER", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "DDE", "NO_SERVER", (char *)NULL);
	}
	return TCL_ERROR;
    }

    *ddeConvPtr = ddeConv;
    return TCL_OK;
}
1267
1268
1269
1270
1271
1272
1273
1274

1275
1276
1277
1278
1279
1280
1281
1277
1278
1279
1280
1281
1282
1283

1284
1285
1286
1287
1288
1289
1290
1291







-
+







	break;
    default:
	errorMessage = "dde command failed";
	errorCode = "FAILED";
    }

    Tcl_SetObjResult(interp, Tcl_NewStringObj(errorMessage, -1));
    Tcl_SetErrorCode(interp, "TCL", "DDE", errorCode, NULL);
    Tcl_SetErrorCode(interp, "TCL", "DDE", errorCode, (char *)NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * DdeObjCmd --
 *
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
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







-
+



-
+
-














-
+








-
-
+
+







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

static int
DdeObjCmd(
    void *dummy,	/* Not used. */
    Tcl_Interp *interp,		/* The interp we are sending from */
    int objc,			/* Number of arguments */
    Tcl_Size objc,			/* Number of arguments */
    Tcl_Obj *const *objv)	/* The arguments */
{
    static const char *const ddeCommands[] = {
	"servername", "execute", "poke", "request", "services", "eval",
	"servername", "execute", "poke", "request", "services", "eval", NULL};
	(char *) NULL};
    enum DdeSubcommands {
	DDE_SERVERNAME, DDE_EXECUTE, DDE_POKE, DDE_REQUEST, DDE_SERVICES,
	DDE_EVAL
    };
    static const char *const ddeSrvOptions[] = {
	"-force", "-handler", "--", NULL
    };
    enum DdeSrvOptions {
	DDE_SERVERNAME_EXACT, DDE_SERVERNAME_HANDLER, DDE_SERVERNAME_LAST,
    };
    static const char *const ddeExecOptions[] = {
	"-async", "-binary", NULL
    };
    enum DdeExecOptions {
        DDE_EXEC_ASYNC, DDE_EXEC_BINARY
	DDE_EXEC_ASYNC, DDE_EXEC_BINARY
    };
    static const char *const ddeEvalOptions[] = {
	"-async", NULL
    };
    static const char *const ddeReqOptions[] = {
	"-binary", NULL
    };

    int index, i, argIndex;
    size_t length;
    int index, argIndex;
    Tcl_Size length, i;
    int flags = 0, result = TCL_OK, firstArg = 0;
    HSZ ddeService = NULL, ddeTopic = NULL, ddeItem = NULL, ddeCookie = NULL;
    HDDEDATA ddeData = NULL, ddeItemData = NULL, ddeReturn;
    HCONV hConv = NULL;
    const WCHAR *serviceName = NULL, *topicName = NULL;
    const char *string;
    DWORD ddeResult;
1484
1485
1486
1487
1488
1489
1490
1491

1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510

1511
1512
1513
1514
1515
1516
1517
1518
1519
1493
1494
1495
1496
1497
1498
1499

1500
1501

1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517

1518
1519

1520
1521
1522
1523
1524
1525
1526







-
+

-
















-
+

-







	    break;
	}
    }

    Initialize();

    if (firstArg != 1) {
	const char *src = Tcl_GetString(objv[firstArg]);
	const char *src = Tcl_GetStringFromObj(objv[firstArg], &length);

	length = objv[firstArg]->length;
	Tcl_DStringInit(&serviceBuf);
	Tcl_UtfToWCharDString(src, length, &serviceBuf);
	serviceName = (WCHAR *) Tcl_DStringValue(&serviceBuf);
	length = Tcl_DStringLength(&serviceBuf) / sizeof(WCHAR);
    } else {
	length = 0;
    }

    if (length == 0) {
	serviceName = NULL;
    } else if ((index != DDE_SERVERNAME) && (index != DDE_EVAL)) {
	ddeService = DdeCreateStringHandleW(ddeInstance, serviceName,
		CP_WINUNICODE);
    }

    if ((index != DDE_SERVERNAME) && (index != DDE_EVAL)) {
	const char *src = Tcl_GetString(objv[firstArg + 1]);
	const char *src = Tcl_GetStringFromObj(objv[firstArg + 1], &length);

	length = objv[firstArg + 1]->length;
	Tcl_DStringInit(&topicBuf);
	topicName = Tcl_UtfToWCharDString(src, length, &topicBuf);
	length = Tcl_DStringLength(&topicBuf) / sizeof(WCHAR);
	if (length == 0) {
	    topicName = NULL;
	} else {
	    ddeTopic = DdeCreateStringHandleW(ddeInstance, topicName,
1535
1536
1537
1538
1539
1540
1541
1542

1543
1544
1545
1546
1547
1548
1549

1550
1551
1552
1553

1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565

1566
1567
1568
1569
1570
1571
1572
1542
1543
1544
1545
1546
1547
1548

1549
1550
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







-
+






-
+



-
+
-










-
+







	    Tcl_DStringFree(&dsBuf);
	} else {
	    Tcl_ResetResult(interp);
	}
	break;

    case DDE_EXECUTE: {
	size_t dataLength;
	Tcl_Size dataLength;
	const void *dataString;
	Tcl_DString dsBuf;

	Tcl_DStringInit(&dsBuf);
	if (flags & DDE_FLAG_BINARY) {
	    dataString =
		    getByteArrayFromObj(objv[firstArg + 2], &dataLength);
		    Tcl_GetByteArrayFromObj(objv[firstArg + 2], &dataLength);
	} else {
	    const char *src;

	    src = Tcl_GetString(objv[firstArg + 2]);
	    src = Tcl_GetStringFromObj(objv[firstArg + 2], &dataLength);
	    dataLength = objv[firstArg + 2]->length;
	    Tcl_DStringInit(&dsBuf);
	    dataString =
		    Tcl_UtfToWCharDString(src, dataLength, &dsBuf);
	    dataLength = Tcl_DStringLength(&dsBuf) + sizeof(WCHAR);
	}

	if (dataLength + 1 < 2) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("cannot execute null data", -1));
	    Tcl_DStringFree(&dsBuf);
	    Tcl_SetErrorCode(interp, "TCL", "DDE", "NULL", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "DDE", "NULL", (char *)NULL);
	    result = TCL_ERROR;
	    break;
	}
	hConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL);
	DdeFreeStringHandle(ddeInstance, ddeService);
	DdeFreeStringHandle(ddeInstance, ddeTopic);

1600
1601
1602
1603
1604
1605
1606
1607

1608
1609
1610
1611
1612
1613
1614
1615
1616

1617
1618
1619
1620
1621
1622
1623
1606
1607
1608
1609
1610
1611
1612

1613

1614
1615
1616
1617
1618
1619
1620

1621
1622
1623
1624
1625
1626
1627
1628







-
+
-







-
+







	Tcl_DStringFree(&dsBuf);
	break;
    }
    case DDE_REQUEST: {
	const WCHAR *itemString;
	const char *src;

	src = Tcl_GetString(objv[firstArg + 2]);
	src = Tcl_GetStringFromObj(objv[firstArg + 2], &length);
	length = objv[firstArg + 2]->length;
	Tcl_DStringInit(&itemBuf);
	itemString = Tcl_UtfToWCharDString(src, length, &itemBuf);
	length = Tcl_DStringLength(&itemBuf) / sizeof(WCHAR);

	if (length == 0) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("cannot request value of null data", -1));
	    Tcl_SetErrorCode(interp, "TCL", "DDE", "NULL", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "DDE", "NULL", (char *)NULL);
	    result = TCL_ERROR;
	    goto cleanup;
	}
	hConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL);
	DdeFreeStringHandle(ddeInstance, ddeService);
	DdeFreeStringHandle(ddeInstance, ddeTopic);

1642
1643
1644
1645
1646
1647
1648
1649

1650
1651
1652
1653
1654
1655
1656
1647
1648
1649
1650
1651
1652
1653

1654
1655
1656
1657
1658
1659
1660
1661







-
+







			returnObjPtr =
				Tcl_NewByteArrayObj((BYTE *) dataString, tmp);
		    } else {
			Tcl_DString dsBuf;

			if ((tmp >= sizeof(WCHAR))
				&& !dataString[tmp / sizeof(WCHAR) - 1]) {
			    tmp -= sizeof(WCHAR);
			    tmp -= (DWORD)sizeof(WCHAR);
			}
			Tcl_DStringInit(&dsBuf);
			Tcl_WCharToUtfDString(dataString, tmp>>1, &dsBuf);
			returnObjPtr =
			    Tcl_NewStringObj(Tcl_DStringValue(&dsBuf),
				    Tcl_DStringLength(&dsBuf));
			Tcl_DStringFree(&dsBuf);
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
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







-
+
-






-
+






-
+


-
+
-







    }
    case DDE_POKE: {
	Tcl_DString dsBuf;
	const WCHAR *itemString;
	BYTE *dataString;
	const char *src;

	src = Tcl_GetString(objv[firstArg + 2]);
	src = Tcl_GetStringFromObj(objv[firstArg + 2], &length);
	length = objv[firstArg + 2]->length;
	Tcl_DStringInit(&itemBuf);
	itemString = Tcl_UtfToWCharDString(src, length, &itemBuf);
	length = Tcl_DStringLength(&itemBuf) / sizeof(WCHAR);
	if (length == 0) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("cannot have a null item", -1));
	    Tcl_SetErrorCode(interp, "TCL", "DDE", "NULL", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "DDE", "NULL", (char *)NULL);
	    result = TCL_ERROR;
	    goto cleanup;
	}
	Tcl_DStringInit(&dsBuf);
	if (flags & DDE_FLAG_BINARY) {
	    dataString = (BYTE *)
		    getByteArrayFromObj(objv[firstArg + 3], &length);
		    Tcl_GetByteArrayFromObj(objv[firstArg + 3], &length);
	} else {
	    const char *data =
		    Tcl_GetString(objv[firstArg + 3]);
		    Tcl_GetStringFromObj(objv[firstArg + 3], &length);
	    length = objv[firstArg + 3]->length;
	    Tcl_DStringInit(&dsBuf);
	    dataString = (BYTE *)
		    Tcl_UtfToWCharDString(data, length, &dsBuf);
	    length = Tcl_DStringLength(&dsBuf) + sizeof(WCHAR);
	}

	hConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL);
1731
1732
1733
1734
1735
1736
1737
1738

1739
1740
1741
1742
1743
1744
1745
1734
1735
1736
1737
1738
1739
1740

1741
1742
1743
1744
1745
1746
1747
1748







-
+







    case DDE_EVAL: {
	RegisteredInterp *riPtr;
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	if (serviceName == NULL) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("invalid service name \"\"", -1));
	    Tcl_SetErrorCode(interp, "TCL", "DDE", "NO_SERVER", NULL);
	    Tcl_SetErrorCode(interp, "TCL", "DDE", "NO_SERVER", (char *)NULL);
	    result = TCL_ERROR;
	    goto cleanup;
	}

	objc -= firstArg + 1;
	objv += firstArg + 1;

1780
1781
1782
1783
1784
1785
1786
1787

1788
1789
1790
1791
1792

1793
1794

1795
1796
1797
1798
1799
1800
1801
1783
1784
1785
1786
1787
1788
1789

1790
1791
1792
1793
1794

1795
1796

1797
1798
1799
1800
1801
1802
1803
1804







-
+




-
+

-
+







	     */

	    if (Tcl_IsSafe(riPtr->interp) && (riPtr->handlerPtr == NULL)) {
		Tcl_SetObjResult(riPtr->interp, Tcl_NewStringObj(
			"permission denied: a handler procedure must be"
			" defined for use in a safe interp", -1));
		Tcl_SetErrorCode(interp, "TCL", "DDE", "SECURITY_CHECK",
			NULL);
			(char *)NULL);
		result = TCL_ERROR;
	    }

	    if (result == TCL_OK) {
		if (objc == 1)
		if (objc == 1) {
		    objPtr = objv[0];
		else {
		} else {
		    objPtr = Tcl_ConcatObj(objc, objv);
		}
		if (riPtr->handlerPtr != NULL) {
		    /* add the dde request data to the handler proc list */
		    /*
		     *result = Tcl_ListObjReplace(sendInterp, objPtr, 0, 0, 1,
		     *	    &(riPtr->handlerPtr));
1845
1846
1847
1848
1849
1850
1851
1852

1853
1854
1855
1856
1857
1858

1859
1860
1861
1862
1863
1864
1865
1866
1848
1849
1850
1851
1852
1853
1854

1855
1856
1857
1858
1859
1860

1861

1862
1863
1864
1865
1866
1867
1868







-
+





-
+
-







	     * poll it for a result.
	     */

	    if (MakeDdeConnection(interp, serviceName, &hConv) != TCL_OK) {
	    invalidServerResponse:
		Tcl_SetObjResult(interp,
			Tcl_NewStringObj("invalid data returned from server", -1));
		Tcl_SetErrorCode(interp, "TCL", "DDE", "BAD_RESPONSE", NULL);
		Tcl_SetErrorCode(interp, "TCL", "DDE", "BAD_RESPONSE", (char *)NULL);
		result = TCL_ERROR;
		goto cleanup;
	    }

	    objPtr = Tcl_ConcatObj(objc, objv);
	    string = Tcl_GetString(objPtr);
	    string = Tcl_GetStringFromObj(objPtr, &length);
	    length = objPtr->length;
	    Tcl_DStringInit(&dsBuf);
	    Tcl_UtfToWCharDString(string, length, &dsBuf);
	    string = Tcl_DStringValue(&dsBuf);
	    length = Tcl_DStringLength(&dsBuf) + sizeof(WCHAR);
	    ddeItemData = DdeCreateDataHandle(ddeInstance, (BYTE *) string,
		    (DWORD) length, 0, 0, CF_UNICODETEXT, 0);
	    Tcl_DStringFree(&dsBuf);
1902
1903
1904
1905
1906
1907
1908
1909

1910
1911
1912
1913
1914
1915
1916
1904
1905
1906
1907
1908
1909
1910

1911
1912
1913
1914
1915
1916
1917
1918







-
+







		 * variable "errorCode", and the fourth is the value of the
		 * variable "errorInfo".
		 */

		length = DdeGetData(ddeData, NULL, 0, 0);
		ddeDataString = (WCHAR *) Tcl_Alloc(length);
		DdeGetData(ddeData, (BYTE *) ddeDataString, (DWORD) length, 0);
		if (length > sizeof(WCHAR)) {
		if (length > (Tcl_Size)sizeof(WCHAR)) {
		    length -= sizeof(WCHAR);
		}
		Tcl_DStringInit(&dsBuf);
		Tcl_WCharToUtfDString(ddeDataString, length>>1, &dsBuf);
		resultPtr = Tcl_NewStringObj(Tcl_DStringValue(&dsBuf),
			Tcl_DStringLength(&dsBuf));
		Tcl_DStringFree(&dsBuf);

Changes to win/tclWinError.c.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tclWinError.c --
 *
 *	This file contains code for converting from Win32 errors to errno
 *	errors.
 *
 * Copyright (c) 1995-1996 by Sun Microsystems, Inc.
 * Copyright © 1995-1996 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
/*
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
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







-
+













-
-
+
+







    ESTALE,		/* WSAESTALE */
    EREMOTE		/* WSAEREMOTE */
};

/*
 *----------------------------------------------------------------------
 *
 * TclWinConvertError --
 * Tcl_WinConvertError --
 *
 *	This routine converts a Win32 error into an errno value.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Sets the errno global variable.
 *
 *----------------------------------------------------------------------
 */

void
TclWinConvertError(
    int errCode)		/* Win32 error code. */
Tcl_WinConvertError(
    unsigned errCode)		/* Win32 error code. */
{
    if ((unsigned)errCode >= sizeof(errorTable)/sizeof(errorTable[0])) {
	errCode -= WSAEWOULDBLOCK;
	if ((unsigned)errCode >= sizeof(wsaErrorTable)/sizeof(wsaErrorTable[0])) {
	    Tcl_SetErrno(errorTable[1]);
	} else {
	    Tcl_SetErrno(wsaErrorTable[errCode]);
377
378
379
380
381
382
383
384

385
386
387
388
389
390
391
377
378
379
380
381
382
383

384
385
386
387
388
389
390
391







-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
MODULE_SCOPE void
tclWinDebugPanic(
    const char *format, ...)
{
#define TCL_MAX_WARN_LEN 1024
    va_list argList;
    va_start(argList, format);

403
404
405
406
407
408
409
410

411
412
413
414
415
416
417
403
404
405
406
407
408
409

410
411
412
413
414
415
416
417







-
+








	if (msgString[TCL_MAX_WARN_LEN-1] != '\0') {
	    memcpy(msgString + (TCL_MAX_WARN_LEN - 5), L" ...", 5 * sizeof(WCHAR));
	}
	OutputDebugStringW(msgString);
    } else {
	if (!isatty(fileno(stderr))) {
	    fprintf(stderr, "\xef\xbb\xbf");
	    fprintf(stderr, "\xEF\xBB\xBF");
	}
	vfprintf(stderr, format, argList);
	fprintf(stderr, "\n");
	fflush(stderr);
    }
}
#endif

Changes to win/tclWinFCmd.c.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tclWinFCmd.c
 *
 *	This file implements the Windows specific portion of file manipulation
 *	subcommands of the "file" command.
 *
 * Copyright (c) 1996-1998 Sun Microsystems, Inc.
 * Copyright © 1996-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclWinInt.h"

49
50
51
52
53
54
55
56
57
58
59

60
61
62
63
64
65
66
49
50
51
52
53
54
55

56
57

58
59
60
61
62
63
64
65







-


-
+







    WIN_SHORTNAME_ATTRIBUTE,
    WIN_SYSTEM_ATTRIBUTE
};

static const int attributeArray[] = {FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_HIDDEN,
	0, FILE_ATTRIBUTE_READONLY, 0, FILE_ATTRIBUTE_SYSTEM};


const char *const tclpFileAttrStrings[] = {
	"-archive", "-hidden", "-longname", "-readonly",
	"-shortname", "-system", (char *) NULL
	"-shortname", "-system", NULL
};

const TclFileAttrProcs tclpFileAttrProcs[] = {
	{GetWinFileAttributes, SetWinFileAttributes},
	{GetWinFileAttributes, SetWinFileAttributes},
	{GetWinFileLongName, CannotSetAttribute},
	{GetWinFileAttributes, SetWinFileAttributes},
275
276
277
278
279
280
281
282

283
284
285
286
287
288
289
274
275
276
277
278
279
280

281
282
283
284
285
286
287
288







-
+







#endif
#endif

    if (retval != -1) {
	return retval;
    }

    TclWinConvertError(GetLastError());
    Tcl_WinConvertError(GetLastError());

    srcAttr = GetFileAttributesW(nativeSrc);
    dstAttr = GetFileAttributesW(nativeDst);
    if (srcAttr == 0xFFFFFFFF) {
	if (GetFullPathNameW(nativeSrc, 0, NULL,
		NULL) >= MAX_PATH) {
	    errno = ENAMETOOLONG;
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
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







+
-
+




















-
-
+
+







	return TCL_ERROR;
    }
    if (errno == EACCES) {
    decode:
	if (srcAttr & FILE_ATTRIBUTE_DIRECTORY) {
	    WCHAR *nativeSrcRest, *nativeDstRest;
	    const char **srcArgv, **dstArgv;
	    size_t size;
	    int size, srcArgc, dstArgc;
	    Tcl_Size srcArgc, dstArgc;
	    WCHAR nativeSrcPath[MAX_PATH];
	    WCHAR nativeDstPath[MAX_PATH];
	    Tcl_DString srcString, dstString;
	    const char *src, *dst;

	    size = GetFullPathNameW(nativeSrc, MAX_PATH,
		    nativeSrcPath, &nativeSrcRest);
	    if ((size == 0) || (size > MAX_PATH)) {
		return TCL_ERROR;
	    }
	    size = GetFullPathNameW(nativeDst, MAX_PATH,
		    nativeDstPath, &nativeDstRest);
	    if ((size == 0) || (size > MAX_PATH)) {
		return TCL_ERROR;
	    }
	    CharLowerW(nativeSrcPath);
	    CharLowerW(nativeDstPath);

	    Tcl_DStringInit(&srcString);
	    Tcl_DStringInit(&dstString);
	    src = Tcl_WCharToUtfDString(nativeSrcPath, -1, &srcString);
	    dst = Tcl_WCharToUtfDString(nativeDstPath, -1, &dstString);
	    src = Tcl_WCharToUtfDString(nativeSrcPath, TCL_INDEX_NONE, &srcString);
	    dst = Tcl_WCharToUtfDString(nativeDstPath, TCL_INDEX_NONE, &dstString);

	    /*
	     * Check whether the destination path is actually inside the
	     * source path. This is true if the prefix matches, and the next
	     * character is either end-of-string or a directory separator
	     */

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
406
407
408
409
410
411
412

413

414
415
416
417
418
419
420
421

422
423
424
425
426
427
428
429







-
+
-








-
+







		if (DoRemoveJustDirectory(nativeDst, 0, NULL) == TCL_OK) {
		    /*
		     * Now that that empty directory is gone, we can try
		     * renaming again. If that fails, we'll put this empty
		     * directory back, for completeness.
		     */

		    if (MoveFileW(nativeSrc,
		    if (MoveFileW(nativeSrc, nativeDst) != FALSE) {
			    nativeDst) != FALSE) {
			return TCL_OK;
		    }

		    /*
		     * Some new error has occurred. Don't know what it could
		     * be, but report this one.
		     */

		    TclWinConvertError(GetLastError());
		    Tcl_WinConvertError(GetLastError());
		    CreateDirectoryW(nativeDst, NULL);
		    SetFileAttributesW(nativeDst, dstAttr);
		    if (Tcl_GetErrno() == EACCES) {
			/*
			 * Decode the EACCES to a more meaningful error.
			 */

484
485
486
487
488
489
490
491

492
493
494
495
496
497
498
483
484
485
486
487
488
489

490
491
492
493
494
495
496
497







-
+







		    }

		    /*
		     * Can't backup dst file or move src file. Return that
		     * error. Could happen if an open file refers to dst.
		     */

		    TclWinConvertError(GetLastError());
		    Tcl_WinConvertError(GetLastError());
		    if (Tcl_GetErrno() == EACCES) {
			/*
			 * Decode the EACCES to a more meaningful error.
			 */

			goto decode;
		    }
665
666
667
668
669
670
671
672

673
674
675
676
677
678
679
664
665
666
667
668
669
670

671
672
673
674
675
676
677
678







-
+







#endif
#endif

    if (retval != -1) {
	return retval;
    }

    TclWinConvertError(GetLastError());
    Tcl_WinConvertError(GetLastError());
    if (Tcl_GetErrno() == EBADF) {
	Tcl_SetErrno(EACCES);
	return TCL_ERROR;
    }
    if (Tcl_GetErrno() == EACCES) {
	DWORD srcAttr, dstAttr;

692
693
694
695
696
697
698
699

700
701
702
703
704
705
706
707
708
709

710
711
712
713
714
715
716
691
692
693
694
695
696
697

698

699
700
701
702
703
704
705
706

707
708
709
710
711
712
713
714







-
+
-








-
+







		    }
		}
		Tcl_SetErrno(EISDIR);
	    }
	    if (dstAttr & FILE_ATTRIBUTE_READONLY) {
		SetFileAttributesW(nativeDst,
			dstAttr & ~((DWORD)FILE_ATTRIBUTE_READONLY));
		if (CopyFileW(nativeSrc, nativeDst,
		if (CopyFileW(nativeSrc, nativeDst, 0) != FALSE) {
			0) != FALSE) {
		    return TCL_OK;
		}

		/*
		 * Still can't copy onto dst. Return that error, and restore
		 * attributes of dst.
		 */

		TclWinConvertError(GetLastError());
		Tcl_WinConvertError(GetLastError());
		SetFileAttributesW(nativeDst, dstAttr);
	    }
	}
    }
    return TCL_ERROR;
}

762
763
764
765
766
767
768
769

770
771
772
773
774
775
776
760
761
762
763
764
765
766

767
768
769
770
771
772
773
774







-
+







	Tcl_SetErrno(ENOENT);
	return TCL_ERROR;
    }

    if (DeleteFileW(path) != FALSE) {
	return TCL_OK;
    }
    TclWinConvertError(GetLastError());
    Tcl_WinConvertError(GetLastError());

    if (Tcl_GetErrno() == EACCES) {
	attr = GetFileAttributesW(path);
	if (attr != 0xFFFFFFFF) {
	    if (attr & FILE_ATTRIBUTE_DIRECTORY) {
		if (attr & FILE_ATTRIBUTE_REPARSE_POINT) {
		    /*
789
790
791
792
793
794
795
796
797

798
799
800

801
802
803
804
805
806
807
787
788
789
790
791
792
793


794
795
796

797
798
799
800
801
802
803
804







-
-
+


-
+







		 */

		Tcl_SetErrno(EISDIR);
	    } else if (attr & FILE_ATTRIBUTE_READONLY) {
		int res = SetFileAttributesW(path,
			attr & ~((DWORD) FILE_ATTRIBUTE_READONLY));

		if ((res != 0) &&
			(DeleteFileW(path) != FALSE)) {
		if ((res != 0) && (DeleteFileW(path) != FALSE)) {
		    return TCL_OK;
		}
		TclWinConvertError(GetLastError());
		Tcl_WinConvertError(GetLastError());
		if (res != 0) {
		    SetFileAttributesW(path, attr);
		}
	    }
	}
    } else if (Tcl_GetErrno() == ENOENT) {
	attr = GetFileAttributesW(path);
862
863
864
865
866
867
868
869

870
871
872
873
874
875
876
877
878
879
880
881
882

883
884
885
886
887
888
889
859
860
861
862
863
864
865

866
867
868
869
870
871
872
873
874
875
876
877
878

879
880
881
882
883
884
885
886







-
+












-
+







static int
DoCreateDirectory(
    const WCHAR *nativePath)	/* Pathname of directory to create (native). */
{
    if (CreateDirectoryW(nativePath, NULL) == 0) {
	DWORD error = GetLastError();

	TclWinConvertError(error);
	Tcl_WinConvertError(error);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *---------------------------------------------------------------------------
 *
 * TclpObjCopyDirectory --
 *
 *	Recursively copies a directory. The target directory dst must not
 *	already exist. Note that this function does not merge two directory
 *	hierarchies, even if the target directory is an an empty directory.
 *	hierarchies, even if the target directory is an empty directory.
 *
 * Results:
 *	If the directory was successfully copied, returns TCL_OK. Otherwise
 *	the return value is TCL_ERROR, errno is set to indicate the error, and
 *	the pathname of the file that caused the error is stored in errorPtr.
 *	See TclpCreateDirectory and TclpCopyFile for a description of possible
 *	values for errno.
911
912
913
914
915
916
917
918
919


920
921
922
923
924
925
926
927
928
929
930
931
932

933
934
935
936
937
938
939
908
909
910
911
912
913
914


915
916
917
918
919
920
921
922
923
924
925
926
927
928

929
930
931
932
933
934
935
936







-
-
+
+












-
+







    normDestPtr = Tcl_FSGetNormalizedPath(NULL,destPathPtr);
    if ((normSrcPtr == NULL) || (normDestPtr == NULL)) {
	return TCL_ERROR;
    }

    Tcl_DStringInit(&srcString);
    Tcl_DStringInit(&dstString);
    Tcl_UtfToWCharDString(TclGetString(normSrcPtr), -1, &srcString);
    Tcl_UtfToWCharDString(TclGetString(normDestPtr), -1, &dstString);
    Tcl_UtfToWCharDString(TclGetString(normSrcPtr), TCL_INDEX_NONE, &srcString);
    Tcl_UtfToWCharDString(TclGetString(normDestPtr), TCL_INDEX_NONE, &dstString);

    ret = TraverseWinTree(TraversalCopy, &srcString, &dstString, &ds);

    Tcl_DStringFree(&srcString);
    Tcl_DStringFree(&dstString);

    if (ret != TCL_OK) {
	if (!strcmp(Tcl_DStringValue(&ds), TclGetString(normSrcPtr))) {
	    *errorPtr = srcPathPtr;
	} else if (!strcmp(Tcl_DStringValue(&ds), TclGetString(normDestPtr))) {
	    *errorPtr = destPathPtr;
	} else {
	    *errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1);
	    *errorPtr = Tcl_DStringToObj(&ds);
	}
	Tcl_DStringFree(&ds);
	Tcl_IncrRefCount(*errorPtr);
    }
    return ret;
}

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
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







-
+












-
+








	Tcl_DString native;
	normPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
	if (normPtr == NULL) {
	    return TCL_ERROR;
	}
	Tcl_DStringInit(&native);
	Tcl_UtfToWCharDString(TclGetString(normPtr), -1, &native);
	Tcl_UtfToWCharDString(TclGetString(normPtr), TCL_INDEX_NONE, &native);
	ret = DoRemoveDirectory(&native, recursive, &ds);
	Tcl_DStringFree(&native);
    } else {
	ret = DoRemoveJustDirectory((const WCHAR *)Tcl_FSGetNativePath(pathPtr), 0, &ds);
    }

    if (ret != TCL_OK) {
	if (Tcl_DStringLength(&ds) > 0) {
	    if (normPtr != NULL &&
		    !strcmp(Tcl_DStringValue(&ds), TclGetString(normPtr))) {
		*errorPtr = pathPtr;
	    } else {
		*errorPtr = TclDStringToObj(&ds);
		*errorPtr = Tcl_DStringToObj(&ds);
	    }
	    Tcl_IncrRefCount(*errorPtr);
	}
	Tcl_DStringFree(&ds);
    }

    return ret;
1050
1051
1052
1053
1054
1055
1056
1057

1058
1059
1060
1061
1062
1063
1064
1047
1048
1049
1050
1051
1052
1053

1054
1055
1056
1057
1058
1059
1060
1061







-
+







	 */

	if (RemoveDirectoryW(nativePath) != FALSE) {
	    return TCL_OK;
	}
    }

    TclWinConvertError(GetLastError());
    Tcl_WinConvertError(GetLastError());

    if (Tcl_GetErrno() == EACCES) {
	attr = GetFileAttributesW(nativePath);
	if (attr != 0xFFFFFFFF) {
	    if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
		/*
		 * Windows 95 reports calling RemoveDirectory on a file as an
1077
1078
1079
1080
1081
1082
1083
1084

1085
1086
1087
1088
1089
1090
1091

1092
1093
1094
1095
1096
1097
1098
1074
1075
1076
1077
1078
1079
1080

1081

1082
1083
1084
1085
1086

1087
1088
1089
1090
1091
1092
1093
1094







-
+
-





-
+







		if (TclWinSymLinkDelete(nativePath, 1) != 0) {
		    goto end;
		}
	    }

	    if (attr & FILE_ATTRIBUTE_READONLY) {
		attr &= ~FILE_ATTRIBUTE_READONLY;
		if (SetFileAttributesW(nativePath,
		if (SetFileAttributesW(nativePath, attr) == FALSE) {
			attr) == FALSE) {
		    goto end;
		}
		if (RemoveDirectoryW(nativePath) != FALSE) {
		    return TCL_OK;
		}
		TclWinConvertError(GetLastError());
		Tcl_WinConvertError(GetLastError());
		SetFileAttributesW(nativePath,
			attr | FILE_ATTRIBUTE_READONLY);
	    }
	}
    }

    if (Tcl_GetErrno() == ENOTEMPTY) {
1113
1114
1115
1116
1117
1118
1119
1120

1121
1122



1123
1124
1125
1126
1127
1128
1129
1109
1110
1111
1112
1113
1114
1115

1116
1117

1118
1119
1120
1121
1122
1123
1124
1125
1126
1127







-
+

-
+
+
+







    }

  end:
    if (errorPtr != NULL) {
	char *p;

	Tcl_DStringInit(errorPtr);
	p = Tcl_WCharToUtfDString(nativePath, -1, errorPtr);
	p = Tcl_WCharToUtfDString(nativePath, TCL_INDEX_NONE, errorPtr);
	for (; *p; ++p) {
	    if (*p == '\\') *p = '/';
	    if (*p == '\\') {
		*p = '/';
	    }
	}
    }
    return TCL_ERROR;

}

static int
1231
1232
1233
1234
1235
1236
1237
1238

1239
1240
1241
1242
1243
1244
1245
1229
1230
1231
1232
1233
1234
1235

1236
1237
1238
1239
1240
1241
1242
1243







-
+







    nativeSource = (WCHAR *) Tcl_DStringValue(sourcePtr);
    handle = FindFirstFileW(nativeSource, &data);
    if (handle == INVALID_HANDLE_VALUE) {
	/*
	 * Can't read directory.
	 */

	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	nativeErrfile = nativeSource;
	goto end;
    }

    Tcl_DStringSetLength(sourcePtr, oldSourceLen + 1);
    Tcl_DStringSetLength(sourcePtr, oldSourceLen);
    result = traverseProc(nativeSource, nativeTarget, DOTREE_PRED,
1325
1326
1327
1328
1329
1330
1331
1332

1333
1334
1335

1336
1337
1338
1339
1340
1341
1342
1323
1324
1325
1326
1327
1328
1329

1330
1331
1332

1333
1334
1335
1336
1337
1338
1339
1340







-
+


-
+







	result = traverseProc((const WCHAR *)Tcl_DStringValue(sourcePtr),
		(const WCHAR *)(targetPtr == NULL ? NULL : Tcl_DStringValue(targetPtr)),
		DOTREE_POSTD, errorPtr);
    }

  end:
    if (nativeErrfile != NULL) {
	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	if (errorPtr != NULL) {
	    Tcl_DStringInit(errorPtr);
	    Tcl_WCharToUtfDString(nativeErrfile, -1, errorPtr);
	    Tcl_WCharToUtfDString(nativeErrfile, TCL_INDEX_NONE, errorPtr);
	}
	result = TCL_ERROR;
    }

    return result;
}

1376
1377
1378
1379
1380
1381
1382
1383

1384
1385
1386
1387

1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401

1402
1403
1404
1405
1406
1407
1408
1374
1375
1376
1377
1378
1379
1380

1381

1382
1383

1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397

1398
1399
1400
1401
1402
1403
1404
1405







-
+
-


-
+













-
+







	    return TCL_OK;
	}
	break;
    case DOTREE_PRED:
	if (DoCreateDirectory(nativeDst) == TCL_OK) {
	    DWORD attr = GetFileAttributesW(nativeSrc);

	    if (SetFileAttributesW(nativeDst,
	    if (SetFileAttributesW(nativeDst, attr) != FALSE) {
		    attr) != FALSE) {
		return TCL_OK;
	    }
	    TclWinConvertError(GetLastError());
	    Tcl_WinConvertError(GetLastError());
	}
	break;
    case DOTREE_POSTD:
	return TCL_OK;
    }

    /*
     * There shouldn't be a problem with src, because we already checked it to
     * get here.
     */

    if (errorPtr != NULL) {
	Tcl_DStringInit(errorPtr);
	Tcl_WCharToUtfDString(nativeDst, -1, errorPtr);
	Tcl_WCharToUtfDString(nativeDst, TCL_INDEX_NONE, errorPtr);
    }
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
1450
1451
1452
1453
1454
1455
1456
1457

1458
1459
1460
1461
1462
1463
1464
1447
1448
1449
1450
1451
1452
1453

1454
1455
1456
1457
1458
1459
1460
1461







-
+







	    return TCL_OK;
	}
	break;
    }

    if (errorPtr != NULL) {
	Tcl_DStringInit(errorPtr);
	Tcl_WCharToUtfDString(nativeSrc, -1, errorPtr);
	Tcl_WCharToUtfDString(nativeSrc, TCL_INDEX_NONE, errorPtr);
    }
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
1478
1479
1480
1481
1482
1483
1484
1485

1486
1487
1488
1489
1490
1491
1492
1475
1476
1477
1478
1479
1480
1481

1482
1483
1484
1485
1486
1487
1488
1489







-
+








static void
StatError(
    Tcl_Interp *interp,		/* The interp that has the error */
    Tcl_Obj *fileName)		/* The name of the file which caused the
				 * error. */
{
    TclWinConvertError(GetLastError());
    Tcl_WinConvertError(GetLastError());
    Tcl_SetObjResult(interp, Tcl_ObjPrintf("could not read \"%s\": %s",
	    TclGetString(fileName), Tcl_PosixError(interp)));
}

/*
 *----------------------------------------------------------------------
 *
1531
1532
1533
1534
1535
1536
1537
1538

1539
1540
1541
1542
1543
1544
1545
1528
1529
1530
1531
1532
1533
1534

1535
1536
1537
1538
1539
1540
1541
1542







-
+







	 * It is hidden. However there is a bug on some Windows OSes in which
	 * root volumes (drives) formatted as NTFS are declared hidden when
	 * they are not (and cannot be).
	 *
	 * We test for, and fix that case, here.
	 */

	size_t len;
	Tcl_Size len;
	const char *str = TclGetStringFromObj(fileName, &len);

	if (len < 4) {
	    if (len == 0) {
		/*
		 * Not sure if this is possible, but we pass it on anyway.
		 */
1591
1592
1593
1594
1595
1596
1597
1598

1599
1600
1601
1602
1603
1604
1605
1606
1607
1588
1589
1590
1591
1592
1593
1594

1595
1596

1597
1598
1599
1600
1601
1602
1603







-
+

-







ConvertFileNameFormat(
    Tcl_Interp *interp,		/* The interp we are using for errors. */
    TCL_UNUSED(int) /*objIndex*/,
    Tcl_Obj *fileName,		/* The name of the file. */
    int longShort,		/* 0 to short name, 1 to long name. */
    Tcl_Obj **attributePtrPtr)	/* A pointer to return the object with. */
{
    int pathc, i;
    Tcl_Size pathc, i, length;
    Tcl_Obj *splitPath;
    size_t length;

    splitPath = Tcl_FSSplitPath(fileName, &pathc);

    if (splitPath == NULL || pathc == 0) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "could not read \"%s\": no such file or directory",
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
1704
1705
1706
1707
1708
1709
1710

1711
1712
1713











1714

1715
1716
1717
1718
1719

1720
1721
1722
1723
1724
1725
1726
1727







-
+


-
-
-
-
-
-
-
-
-
-
-
+
-





-
+







	     * about the second.
	     *
	     *	fprintf(stderr, "%d\n", data.w.cAlternateFileName[0]);
	     *	fprintf(stderr, "%d\n", ((WCHAR *) nativeName)[0]);
	     */

	    Tcl_DStringInit(&dsTemp);
	    Tcl_WCharToUtfDString(nativeName, -1, &dsTemp);
	    Tcl_WCharToUtfDString(nativeName, TCL_INDEX_NONE, &dsTemp);
	    Tcl_DStringFree(&ds);

	    /*
	     * Deal with issues of tildes being absolute.
	     */

	    if (Tcl_DStringValue(&dsTemp)[0] == '~') {
		TclNewLiteralStringObj(tempPath, "./");
		Tcl_AppendToObj(tempPath, Tcl_DStringValue(&dsTemp),
			Tcl_DStringLength(&dsTemp));
		Tcl_DStringFree(&dsTemp);
	    } else {
		tempPath = TclDStringToObj(&dsTemp);
	    tempPath = Tcl_DStringToObj(&dsTemp);
	    }
	    Tcl_ListObjReplace(NULL, splitPath, i, 1, 1, &tempPath);
	    FindClose(handle);
	}
    }

    *attributePtrPtr = Tcl_FSJoinPath(splitPath, -1);
    *attributePtrPtr = Tcl_FSJoinPath(splitPath, TCL_INDEX_NONE);

    if (splitPath != NULL) {
	/*
	 * Unfortunately, the object we will return may have its only refCount
	 * as part of the list splitPath. This means if we free splitPath, the
	 * object will disappear. So, we have to be very careful here.
	 * Unfortunately this means we must manipulate the object's refCount
1948
1949
1950
1951
1952
1953
1954
1955

1956
1957
1958
1959
1960
1961
1962

1963
1964
1965
1966
1967
1968
1969
1933
1934
1935
1936
1937
1938
1939

1940
1941
1942
1943
1944
1945
1946

1947
1948
1949
1950
1951
1952
1953
1954







-
+






-
+







	buf[2] = '/';
	buf[3] = '\0';

	for (i = 0; i < 26; i++) {
	    buf[0] = (char) ('a' + i);
	    if (GetVolumeInformationA(buf, NULL, 0, NULL, NULL, NULL, NULL, 0)
		    || (GetLastError() == ERROR_NOT_READY)) {
		elemPtr = Tcl_NewStringObj(buf, -1);
		elemPtr = Tcl_NewStringObj(buf, TCL_INDEX_NONE);
		Tcl_ListObjAppendElement(NULL, resultPtr, elemPtr);
	    }
	}
    } else {
	for (p = buf; *p != '\0'; p += 4) {
	    p[2] = '/';
	    elemPtr = Tcl_NewStringObj(p, -1);
	    elemPtr = Tcl_NewStringObj(p, TCL_INDEX_NONE);
	    Tcl_ListObjAppendElement(NULL, resultPtr, elemPtr);
	}
    }

    Tcl_IncrRefCount(resultPtr);
    return resultPtr;
}
1999
2000
2001
2002
2003
2004
2005
2006

2007
2008
2009
2010
2011

2012
2013

2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029

2030
2031

2032
2033

2034
2035
2036
2037
2038
2039
2040
1984
1985
1986
1987
1988
1989
1990

1991
1992
1993
1994
1995

1996
1997

1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013

2014
2015

2016
2017

2018
2019
2020
2021
2022
2023
2024
2025







-
+




-
+

-
+















-
+

-
+

-
+








    /*
     * Build the path in writable memory from the user-supplied pieces and
     * some defaults. First, the parent temporary directory.
     */

    if (dirObj) {
	Tcl_GetString(dirObj);
	TclGetString(dirObj);
	if (dirObj->length < 1) {
	    goto useSystemTemp;
	}
	Tcl_DStringInit(&base);
	Tcl_UtfToWCharDString(Tcl_GetString(dirObj), -1, &base);
	Tcl_UtfToWCharDString(TclGetString(dirObj), TCL_INDEX_NONE, &base);
	if (dirObj->bytes[dirObj->length - 1] != '\\') {
	    Tcl_UtfToWCharDString("\\", -1, &base);
	    Tcl_UtfToWCharDString("\\", TCL_INDEX_NONE, &base);
	}
    } else {
    useSystemTemp:
	Tcl_DStringInit(&base);
	Tcl_DStringAppend(&base, (char *) tempBuf, len * sizeof(WCHAR));
    }

    /*
     * Next, the base of the directory name.
     */

#define DEFAULT_TEMP_DIR_PREFIX	"tcl"
#define SUFFIX_LENGTH	8

    if (basenameObj) {
	Tcl_UtfToWCharDString(Tcl_GetString(basenameObj), -1, &base);
	Tcl_UtfToWCharDString(TclGetString(basenameObj), TCL_INDEX_NONE, &base);
    } else {
	Tcl_UtfToWCharDString(DEFAULT_TEMP_DIR_PREFIX, -1, &base);
	Tcl_UtfToWCharDString(DEFAULT_TEMP_DIR_PREFIX, TCL_INDEX_NONE, &base);
    }
    Tcl_UtfToWCharDString("_", -1, &base);
    Tcl_UtfToWCharDString("_", TCL_INDEX_NONE, &base);

    /*
     * Now we keep on trying random suffixes until we get one that works
     * (i.e., that doesn't trigger the ERROR_ALREADY_EXISTS error). Note that
     * SUFFIX_LENGTH is longer than on Unix because we expect to be not on a
     * case-sensitive filesystem.
     */
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
2038
2039
2040
2041
2042
2043
2044

2045
2046
2047
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







-
+









-
+










-
+

-
+










	error = ERROR_SUCCESS;
	tempbuf[SUFFIX_LENGTH] = '\0';
	for (i = 0 ; i < SUFFIX_LENGTH; i++) {
	    tempbuf[i] = randChars[(int) (rand() % numRandChars)];
	}
	Tcl_DStringSetLength(&base, baseLen);
	Tcl_UtfToWCharDString(tempbuf, -1, &base);
	Tcl_UtfToWCharDString(tempbuf, TCL_INDEX_NONE, &base);
    } while (!CreateDirectoryW((LPCWSTR) Tcl_DStringValue(&base), NULL)
	    && (error = GetLastError()) == ERROR_ALREADY_EXISTS);

    /*
     * Check for other errors. The big ones are ERROR_PATH_NOT_FOUND and
     * ERROR_ACCESS_DENIED.
     */

    if (error != ERROR_SUCCESS) {
	TclWinConvertError(error);
	Tcl_WinConvertError(error);
	Tcl_DStringFree(&base);
	return NULL;
    }

    /*
     * We actually made the directory, so we're done! Report what we made back
     * as a (clean) Tcl_Obj.
     */

    Tcl_DStringInit(&name);
    Tcl_WCharToUtfDString((LPCWSTR) Tcl_DStringValue(&base), -1, &name);
    Tcl_WCharToUtfDString((LPCWSTR) Tcl_DStringValue(&base), TCL_INDEX_NONE, &name);
    Tcl_DStringFree(&base);
    return TclDStringToObj(&name);
    return Tcl_DStringToObj(&name);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to win/tclWinFile.c.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







/*
 * tclWinFile.c --
 *
 *	This file contains temporary wrappers around UNIX file handling
 *	functions. These wrappers map the UNIX functions to Win32 HANDLE-style
 *	files, which can be manipulated through the Win32 console redirection
 *	interfaces.
 *
 * Copyright (c) 1995-1998 Sun Microsystems, Inc.
 * Copyright © 1995-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclWinInt.h"
#include "tclFileSystem.h"
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39







-
+







#endif
/*
 * The number of 100-ns intervals between the Windows system epoch (1601-01-01
 * on the proleptic Gregorian calendar) and the Posix epoch (1970-01-01).
 */

#define POSIX_EPOCH_AS_FILETIME	\
	((Tcl_WideInt) 116444736 * (Tcl_WideInt) 1000000000)
	((long long) 116444736 * (long long) 1000000000)

/*
 * Declarations for 'link' related information. This information should come
 * with VC++ 6.0, but is not in some older SDKs. In any case it is not well
 * documented.
 */

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
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







-
+




















-
+







    WCHAR dummyBuf[MAX_PATH * 3];
} DUMMY_REPARSE_BUFFER;

/*
 * Other typedefs required by this code.
 */

static __time64_t		ToCTime(FILETIME fileTime);
static __time64_t	ToCTime(FILETIME fileTime);
static void		FromCTime(__time64_t posixTime, FILETIME *fileTime);

/*
 * Declarations for local functions defined in this file:
 */

static int		NativeAccess(const WCHAR *path, int mode);
static int		NativeDev(const WCHAR *path);
static int		NativeStat(const WCHAR *path, Tcl_StatBuf *statPtr,
			    int checkLinks);
static unsigned short	NativeStatMode(DWORD attr, int checkLinks,
			    int isExec);
static int		NativeIsExec(const WCHAR *path);
static int		NativeReadReparse(const WCHAR *LinkDirectory,
			    REPARSE_DATA_BUFFER *buffer, DWORD desiredAccess);
static int		NativeWriteReparse(const WCHAR *LinkDirectory,
			    REPARSE_DATA_BUFFER *buffer);
static int		NativeMatchType(int isDrive, DWORD attr,
			    const WCHAR *nativeName, Tcl_GlobTypeData *types);
static int		WinIsDrive(const char *name, size_t nameLen);
static int		WinIsReserved(const char *path);
static size_t		WinIsReserved(const char *path);
static Tcl_Obj *	WinReadLink(const WCHAR *LinkSource);
static Tcl_Obj *	WinReadLinkDirectory(const WCHAR *LinkDirectory);
static int		WinLink(const WCHAR *LinkSource,
			    const WCHAR *LinkTarget, int linkAction);
static int		WinSymLinkDirectory(const WCHAR *LinkDirectory,
			    const WCHAR *LinkTarget);
MODULE_SCOPE void	tclWinDebugPanic(const char *format, ...);
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
205
206
207
208
209
210
211

212
213
214
215
216
217
218
219







-
+








    if (!GetFullPathNameW(linkTargetPath, MAX_PATH, tempFileName,
	    &tempFilePart)) {
	/*
	 * Invalid file.
	 */

	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	return -1;
    }

    /*
     * Make sure source file doesn't exist.
     */

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
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







-
+













-
+














-
+

+
+
-
-
-
+
+
+

+
+
-
+
+








    if (!GetFullPathNameW(linkSourcePath, MAX_PATH, tempFileName,
	    &tempFilePart)) {
	/*
	 * Invalid file.
	 */

	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	return -1;
    }

    /*
     * Check the target.
     */

    attr = GetFileAttributesW(linkTargetPath);
    if (attr == INVALID_FILE_ATTRIBUTES) {
	/*
	 * The target doesn't exist.
	 */

	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
    } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
	/*
	 * It is a file.
	 */

	if (linkAction & TCL_CREATE_HARD_LINK) {
	    if (CreateHardLinkW(linkSourcePath, linkTargetPath, NULL)) {
		/*
		 * Success!
		 */

		return 0;
	    }

	    TclWinConvertError(GetLastError());
	    Tcl_WinConvertError(GetLastError());
	} else if (linkAction & TCL_CREATE_SYMBOLIC_LINK) {
	    if (CreateSymbolicLinkW(linkSourcePath, linkTargetPath,
		    0x2 /* SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE */)) {
	    /*
	     * Can't symlink files.
	     */
		/*
		 * Success!
		 */

		return 0;
	    } else {
	    Tcl_SetErrno(ENOTDIR);
		Tcl_WinConvertError(GetLastError());
	    }
	} else {
	    Tcl_SetErrno(ENODEV);
	}
    } else {
	/*
	 * We've got a directory. Now check whether what we're trying to do is
	 * reasonable.
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
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







-
+













-
+








    if (!GetFullPathNameW(linkSourcePath, MAX_PATH, tempFileName,
	    &tempFilePart)) {
	/*
	 * Invalid file.
	 */

	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	return NULL;
    }

    /*
     * Make sure source file does exist.
     */

    attr = GetFileAttributesW(linkSourcePath);
    if (attr == INVALID_FILE_ATTRIBUTES) {
	/*
	 * The source doesn't exist.
	 */

	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	return NULL;

    } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
	/*
	 * It is a file - this is not yet supported.
	 */

493
494
495
496
497
498
499
500

501
502
503
504
505
506
507
498
499
500
501
502
503
504

505
506
507
508
509
510
511
512







-
+







    if (hFile != INVALID_HANDLE_VALUE) {
	if (!DeviceIoControl(hFile, FSCTL_DELETE_REPARSE_POINT, reparseBuffer,
		REPARSE_MOUNTPOINT_HEADER_SIZE,NULL,0,&returnedLength,NULL)) {
	    /*
	     * Error setting junction.
	     */

	    TclWinConvertError(GetLastError());
	    Tcl_WinConvertError(GetLastError());
	    CloseHandle(hFile);
	} else {
	    CloseHandle(hFile);
	    if (!linkOnly) {
		RemoveDirectoryW(linkOrigPath);
	    }
	    return 0;
686
687
688
689
690
691
692
693

694
695
696
697
698
699
700
701
702
703
704
705
706
707

708
709
710
711
712
713
714
691
692
693
694
695
696
697

698
699
700
701
702
703
704
705
706
707
708
709
710
711

712
713
714
715
716
717
718
719







-
+













-
+







	    FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);

    if (hFile == INVALID_HANDLE_VALUE) {
	/*
	 * Error creating directory.
	 */

	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	return -1;
    }

    /*
     * Get the link.
     */

    if (!DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, NULL, 0, buffer,
	    sizeof(DUMMY_REPARSE_BUFFER), &returnedLength, NULL)) {
	/*
	 * Error setting junction.
	 */

	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	CloseHandle(hFile);
	return -1;
    }
    CloseHandle(hFile);

    if (!IsReparseTagValid(buffer->ReparseTag)) {
	Tcl_SetErrno(EINVAL);
742
743
744
745
746
747
748
749

750
751
752
753
754
755
756
757
758
759
760

761
762
763
764
765
766
767
768
769
770
771
772
773
774
775

776
777
778
779
780
781
782
747
748
749
750
751
752
753

754
755
756
757
758
759
760
761
762
763
764

765
766
767
768
769
770
771
772
773
774
775
776
777
778
779

780
781
782
783
784
785
786
787







-
+










-
+














-
+







     */

    if (CreateDirectoryW(linkDirPath, NULL) == 0) {
	/*
	 * Error creating directory.
	 */

	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	return -1;
    }
    hFile = CreateFileW(linkDirPath, GENERIC_WRITE, 0, NULL,
	    OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT
	    | FILE_FLAG_BACKUP_SEMANTICS, NULL);
    if (hFile == INVALID_HANDLE_VALUE) {
	/*
	 * Error creating directory.
	 */

	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	return -1;
    }

    /*
     * Set the link.
     */

    if (!DeviceIoControl(hFile, FSCTL_SET_REPARSE_POINT, buffer,
	    (DWORD) buffer->ReparseDataLength + REPARSE_MOUNTPOINT_HEADER_SIZE,
	    NULL, 0, &returnedLength, NULL)) {
	/*
	 * Error setting junction.
	 */

	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	CloseHandle(hFile);
	RemoveDirectoryW(linkDirPath);
	return -1;
    }
    CloseHandle(hFile);

    /*
857
858
859
860
861
862
863
864

865
866
867

868
869
870
871
872
873
874
862
863
864
865
866
867
868

869
870
871

872
873
874
875
876
877
878
879







-
+


-
+







    const char *argv0)		/* If NULL, install PanicMessageBox, otherwise
				 * ignore. */
{
    WCHAR wName[MAX_PATH];
    char name[MAX_PATH * 3];
    (void)argv0;

    GetModuleFileNameW(NULL, wName, MAX_PATH);
    GetModuleFileNameW(NULL, wName, sizeof(wName)/sizeof(WCHAR));
    WideCharToMultiByte(CP_UTF8, 0, wName, -1, name, sizeof(name), NULL, NULL);
    TclWinNoBackslash(name);
    TclSetObjNameOfExecutable(Tcl_NewStringObj(name, -1), NULL);
    TclSetObjNameOfExecutable(Tcl_NewStringObj(name, TCL_INDEX_NONE), NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * TclpMatchInDirectory --
 *
912
913
914
915
916
917
918
919
920


921
922
923
924
925
926
927
928
929
930

931
932
933
934
935
936
937
938
939
940
941

942
943
944
945
946
947
948
917
918
919
920
921
922
923


924
925
926
927
928
929
930
931
932
933
934

935
936
937
938
939
940
941
942
943
944
945

946
947
948
949
950
951
952
953







-
-
+
+









-
+










-
+







	if (norm != NULL) {
	    /*
	     * Match a single file directly.
	     */

	    DWORD attr;
	    WIN32_FILE_ATTRIBUTE_DATA data;
	    size_t length = 0;
	    const char *str = TclGetStringFromObj(norm, &length);
	    Tcl_Size len = 0;
	    const char *str = TclGetStringFromObj(norm, &len);

	    native = (const WCHAR *)Tcl_FSGetNativePath(pathPtr);

	    if (GetFileAttributesExW(native,
		    GetFileExInfoStandard, &data) != TRUE) {
		return TCL_OK;
	    }
	    attr = data.dwFileAttributes;

	    if (NativeMatchType(WinIsDrive(str, length), attr, native, types)) {
	    if (NativeMatchType(WinIsDrive(str, len), attr, native, types)) {
		Tcl_ListObjAppendElement(interp, resultPtr, pathPtr);
	    }
	}
	return TCL_OK;
    } else {
	DWORD attr;
	HANDLE handle;
	WIN32_FIND_DATAW data;
	const char *dirName;	/* UTF-8 dir name, later with pattern
				 * appended. */
	size_t dirLength;
	Tcl_Size dirLength;
	int matchSpecialDots;
	Tcl_DString ds;		/* Native encoding of dir, also used
				 * temporarily for other things. */
	Tcl_DString dsOrig;	/* UTF-8 encoding of dir. */
	Tcl_Obj *fileNamePtr;
	char lastChar;

963
964
965
966
967
968
969
970

971
972
973
974
975
976
977
968
969
970
971
972
973
974

975
976
977
978
979
980
981
982







-
+







	native = (const WCHAR *)Tcl_FSGetNativePath(pathPtr);
	if (native == NULL) {
	    return TCL_OK;
	}
	attr = GetFileAttributesW(native);

	if ((attr == INVALID_FILE_ATTRIBUTES)
	    || ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0)) {
		|| ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0)) {
	    return TCL_OK;
	}

	/*
	 * Build up the directory name for searching, including a trailing
	 * directory separator.
	 */
996
997
998
999
1000
1001
1002
1003

1004
1005
1006
1007
1008
1009

1010
1011
1012
1013
1014
1015
1016
1001
1002
1003
1004
1005
1006
1007

1008
1009
1010
1011
1012
1013

1014
1015
1016
1017
1018
1019
1020
1021







-
+





-
+







	if (strpbrk(pattern, "[]\\") == NULL) {
	    /*
	     * The pattern is a simple one containing just '*' and/or '?'.
	     * This means we can get the OS to help us, by passing it the
	     * pattern.
	     */

	    dirName = Tcl_DStringAppend(&dsOrig, pattern, -1);
	    dirName = Tcl_DStringAppend(&dsOrig, pattern, TCL_INDEX_NONE);
	} else {
	    dirName = TclDStringAppendLiteral(&dsOrig, "*.*");
	}

	Tcl_DStringInit(&ds);
	native = Tcl_UtfToWCharDString(dirName, -1, &ds);
	native = Tcl_UtfToWCharDString(dirName, TCL_INDEX_NONE, &ds);
	if ((types == NULL) || (types->type != TCL_GLOB_TYPE_DIR)) {
	    handle = FindFirstFileW(native, &data);
	} else {
	    /*
	     * We can be more efficient, for pure directory requests.
	     */

1029
1030
1031
1032
1033
1034
1035
1036

1037
1038
1039
1040
1041
1042
1043
1034
1035
1036
1037
1038
1039
1040

1041
1042
1043
1044
1045
1046
1047
1048







-
+







		 * means we just return TCL_OK, indicating no results found.
		 */

		Tcl_DStringFree(&dsOrig);
		return TCL_OK;
	    }

	    TclWinConvertError(err);
	    Tcl_WinConvertError(err);
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"couldn't read directory \"%s\": %s",
			Tcl_DStringValue(&dsOrig), Tcl_PosixError(interp)));
	    }
	    Tcl_DStringFree(&dsOrig);
	    return TCL_ERROR;
1075
1076
1077
1078
1079
1080
1081
1082

1083
1084
1085
1086
1087
1088
1089
1080
1081
1082
1083
1084
1085
1086

1087
1088
1089
1090
1091
1092
1093
1094







-
+







	do {
	    const char *utfname;
	    int checkDrive = 0, isDrive;

	    native = data.cFileName;
	    attr = data.dwFileAttributes;
	    Tcl_DStringInit(&ds);
	    utfname = Tcl_WCharToUtfDString(native, -1, &ds);
	    utfname = Tcl_WCharToUtfDString(native, TCL_INDEX_NONE, &ds);

	    if (!matchSpecialDots) {
		/*
		 * If it is exactly '.' or '..' then we ignore it.
		 */

		if ((utfname[0] == '.') && (utfname[1] == '\0'
1217
1218
1219
1220
1221
1222
1223
1224

1225
1226
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
1222
1223
1224
1225
1226
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







-
+













-
+




















-
+








/*
 * Does the given path represent a reserved window path name? If not return 0,
 * if true, return the number of characters of the path that we actually want
 * (not any trailing :).
 */

static int
static size_t
WinIsReserved(
    const char *path)		/* Path in UTF-8 */
{
    if ((path[0] == 'c' || path[0] == 'C')
	    && (path[1] == 'o' || path[1] == 'O')) {
	if ((path[2] == 'm' || path[2] == 'M')
		&& path[3] >= '1' && path[3] <= '9') {
	    /*
	     * May have match for 'com[1-9]:?', which is a serial port.
	     */

	    if (path[4] == '\0') {
		return 4;
	    } else if (path [4] == ':' && path[5] == '\0') {
	    } else if (path[4] == ':' && path[5] == '\0') {
		return 4;
	    }
	} else if ((path[2] == 'n' || path[2] == 'N') && path[3] == '\0') {
	    /*
	     * Have match for 'con'
	     */

	    return 3;
	}

    } else if ((path[0] == 'l' || path[0] == 'L')
	    && (path[1] == 'p' || path[1] == 'P')
	    && (path[2] == 't' || path[2] == 'T')) {
	if (path[3] >= '1' && path[3] <= '9') {
	    /*
	     * May have match for 'lpt[1-9]:?'
	     */

	    if (path[4] == '\0') {
		return 4;
	    } else if (path [4] == ':' && path[5] == '\0') {
	    } else if (path[4] == ':' && path[5] == '\0') {
		return 4;
	    }
	}

    } else if (!strcasecmp(path, "prn") || !strcasecmp(path, "nul")
	    || !strcasecmp(path, "aux")) {
	/*
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
















1440
1441
1442
1443




1444
1445

1446
1447
1448
1449






1450



1451
1452
1453
1454
1455
1456

1457
1458
1459
1460
1461
1462
1463
1435
1436
1437
1438
1439
1440
1441



1442
1443
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
1474
1475
1476
1477
1478

1479
1480
1481
1482
1483
1484
1485
1486







-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
+
+
+
+
-
-
+
-
-
-
-
+
+
+
+
+
+
-
+
+
+





-
+








    wDomain = NULL;
    domain = Tcl_UtfFindFirst(name, '@');
    if (domain == NULL) {
	const char *ptr;

	/*
	 * No domain. Firstly check it's the current user
	 */

	 * Treat the current user as a special case because the general case
	 * below does not properly retrieve the path. The NetUserGetInfo
	 * call returns an empty path and the code defaults to the user's
	 * name in the profiles directory. On modern Windows systems, this
	 * is generally wrong as when the account is a Microsoft account,
	 * for example abcdefghi@outlook.com, the directory name is
	 * abcde and not abcdefghi.
	 *
	 * Note we could have just used env(USERPROFILE) here but
	 * the intent is to retrieve (as on Unix) the system's view
	 * of the home irrespective of environment settings of HOME
	 * and USERPROFILE.
	 *
	 * Fixing this for the general user needs more investigating but
	 * at least for the current user we can use a direct call.
	 */
	ptr = TclpGetUserName(&ds);
	if (ptr != NULL && strcasecmp(name, ptr) == 0) {
	    /*
	     * Try safest and fastest way to get current user home
	    HANDLE hProcess;
	    WCHAR buf[MAX_PATH];
	    DWORD nChars = sizeof(buf) / sizeof(buf[0]);
	    /* Sadly GetCurrentProcessToken not in Win 7 so slightly longer */
	     */

	    hProcess = GetCurrentProcess(); /* Need not be closed */
	    ptr = TclGetEnv("HOME", &ds);
	    if (ptr != NULL) {
		Tcl_JoinPath(1, &ptr, bufferPtr);
		rc = 1;
	    if (hProcess) {
		HANDLE hToken;
		if (OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) {
		    if (GetUserProfileDirectoryW(hToken, buf, &nChars)) {
			result = Tcl_WCharToUtfDString(buf, nChars-1, (bufferPtr));
			rc = 1;
		result = Tcl_DStringValue(bufferPtr);
		    }
		    CloseHandle(hToken);
		}
	    }
	}
	Tcl_DStringFree(&ds);
    } else {
	Tcl_DStringInit(&ds);
	wName = Tcl_UtfToWCharDString(domain + 1, -1, &ds);
	wName = Tcl_UtfToWCharDString(domain + 1, TCL_INDEX_NONE, &ds);
	rc = NetGetDCName(NULL, wName, (LPBYTE *) &wDomain);
	Tcl_DStringFree(&ds);
	nameLen = domain - name;
    }
    if (rc == 0) {
	Tcl_DStringInit(&ds);
	wName = Tcl_UtfToWCharDString(name, nameLen, &ds);
1508
1509
1510
1511
1512
1513
1514
1515

1516
1517
1518
1519
1520

1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1531
1532
1533
1534
1535
1536
1537

1538
1539
1540
1541
1542

1543
























1544
1545
1546
1547
1548
1549
1550







-
+




-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	     */

	    for (i = 0; i < size; ++i) {
		if (result[i] == '\\') {
		    result[i] = '/';
		}
	    }
	    NetApiBufferFree((void *) uiPtr);
	    NetApiBufferFree((void *)uiPtr);
	}
	Tcl_DStringFree(&ds);
    }
    if (wDomain != NULL) {
	NetApiBufferFree((void *) wDomain);
	NetApiBufferFree((void *)wDomain);
    }
    if (result == NULL) {
	/*
	 * Look in the "Password Lists" section of system.ini for the local
	 * user. There are also entries in that section that begin with a "*"
	 * character that are used by Windows for other purposes; ignore user
	 * names beginning with a "*".
	 */

	char buf[MAX_PATH];

	if (name[0] != '*') {
	    if (GetPrivateProfileStringA("Password Lists", name, "", buf,
		    MAX_PATH, "system.ini") > 0) {
		/*
		 * User exists, but there is no such thing as a home directory
		 * in system.ini. Return "{Windows drive}:/".
		 */

		GetWindowsDirectoryA(buf, MAX_PATH);
		Tcl_DStringAppend(bufferPtr, buf, 3);
		result = Tcl_DStringValue(bufferPtr);
	    }
	}
    }

    return result;
}

/*
 *---------------------------------------------------------------------------
1578
1579
1580
1581
1582
1583
1584
1585

1586
1587
1588
1589
1590
1591
1592
1577
1578
1579
1580
1581
1582
1583

1584
1585
1586
1587
1588
1589
1590
1591







-
+







    if (attr == INVALID_FILE_ATTRIBUTES) {
	/*
	 * File might not exist.
	 */

	DWORD lasterror = GetLastError();
	if (lasterror != ERROR_SHARING_VIOLATION) {
	    TclWinConvertError(lasterror);
	    Tcl_WinConvertError(lasterror);
	    return -1;
	}
    }

    if (mode == F_OK) {
	/*
	 * File exists, nothing else to check.
1657
1658
1659
1660
1661
1662
1663
1664

1665
1666
1667
1668
1669
1670
1671
1656
1657
1658
1659
1660
1661
1662

1663
1664
1665
1666
1667
1668
1669
1670







-
+







	    if (GetLastError() == ERROR_ACCESS_DENIED) {
		Tcl_SetErrno(EACCES);
		return -1;
	    }
	}

	/*
	 * We cannnot verify the access fast, check it below using security
	 * We cannot verify the access fast, check it below using security
	 * info.
	 */
    }

    /*
     * It looks as if the permissions are ok, but if we are on NT, 2000 or XP,
     * we have a more complex permissions structure so we try to check that.
1704
1705
1706
1707
1708
1709
1710
1711

1712
1713
1714
1715
1716
1717
1718
1703
1704
1705
1706
1707
1708
1709

1710
1711
1712
1713
1714
1715
1716
1717







-
+







	error = GetLastError();
	if (error != ERROR_INSUFFICIENT_BUFFER) {
	    /*
	     * Most likely case is ERROR_ACCESS_DENIED, which we will convert
	     * to EACCES - just what we want!
	     */

	    TclWinConvertError((DWORD) error);
	    Tcl_WinConvertError((DWORD) error);
	    return -1;
	}

	/*
	 * Now size contains the size of buffer needed.
	 */

1777
1778
1779
1780
1781
1782
1783
1784

1785
1786
1787
1788
1789
1790
1791
1776
1777
1778
1779
1780
1781
1782

1783
1784
1785
1786
1787
1788
1789
1790







-
+








	    goto accessError;
	}

	RevertToSelf();

	/*
	 * Setup desiredAccess according to the access priveleges we are
	 * Setup desiredAccess according to the access privileges we are
	 * checking.
	 */

	if (mode & R_OK) {
	    desiredAccess |= FILE_GENERIC_READ;
	}
	if (mode & W_OK) {
1809
1810
1811
1812
1813
1814
1815
1816

1817
1818
1819
1820
1821
1822
1823
1808
1809
1810
1811
1812
1813
1814

1815
1816
1817
1818
1819
1820
1821
1822







-
+







		&genMap, &privSet, &privSetSize, &grantedAccess,
		&accessYesNo)) {
	    /*
	     * Unable to perform access check.
	     */

	accessError:
	    TclWinConvertError(GetLastError());
	    Tcl_WinConvertError(GetLastError());
	    if (sdPtr != NULL) {
		HeapFree(GetProcessHeap(), 0, sdPtr);
	    }
	    if (hToken != NULL) {
		CloseHandle(hToken);
	    }
	    return -1;
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1865
1866
1867
1868
1869
1870
1871

1872
1873
1874
1875
1876
1877
1878







-







	return 0;
    }

    path += len-3;
    if ((_wcsicmp(path, L"exe") == 0)
	    || (_wcsicmp(path, L"com") == 0)
	    || (_wcsicmp(path, L"cmd") == 0)
	    || (_wcsicmp(path, L"cmd") == 0)
	    || (_wcsicmp(path, L"bat") == 0)) {
	return 1;
    }
    return 0;
}

/*
1904
1905
1906
1907
1908
1909
1910
1911

1912
1913
1914
1915
1916
1917
1918
1902
1903
1904
1905
1906
1907
1908

1909
1910
1911
1912
1913
1914
1915
1916







-
+








    if (!nativePath) {
	return -1;
    }
    result = SetCurrentDirectoryW(nativePath);

    if (result == 0) {
	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	return -1;
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
1943
1944
1945
1946
1947
1948
1949
1950

1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969

1970
1971
1972
1973
1974
1975
1976
1941
1942
1943
1944
1945
1946
1947

1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966

1967
1968
1969
1970
1971
1972
1973
1974







-
+


















-
+







				 * name of current directory. */
{
    WCHAR buffer[MAX_PATH];
    char *p;
    WCHAR *native;

    if (GetCurrentDirectoryW(MAX_PATH, buffer) == 0) {
	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "error getting working directory name: %s",
		    Tcl_PosixError(interp)));
	}
	return NULL;
    }

    /*
     * Watch for the weird Windows c:\\UNC syntax.
     */

    native = (WCHAR *) buffer;
    if ((native[0] != '\0') && (native[1] == ':')
	    && (native[2] == '\\') && (native[3] == '\\')) {
	native += 2;
    }
    Tcl_DStringInit(bufferPtr);
    Tcl_WCharToUtfDString(native, -1, bufferPtr);
    Tcl_WCharToUtfDString(native, TCL_INDEX_NONE, bufferPtr);

    /*
     * Convert to forward slashes for easier use in scripts.
     */

    for (p = Tcl_DStringValue(bufferPtr); *p != '\0'; p++) {
	if (*p == '\\') {
2035
2036
2037
2038
2039
2040
2041
2042

2043
2044
2045
2046
2047
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
2033
2034
2035
2036
2037
2038
2039

2040
2041
2042
2043
2044
2045
2046
2047
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







-
+
















-
-
-
-
-
-
+
+
+
+
+
+

-
+



-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
+
+







    /*
     * If we can use 'createFile' on this, then we can use the resulting
     * fileHandle to read more information (nlink, ino) than we can get from
     * other attributes reading APIs. If not, then we try to fall back on the
     * 'getFileAttributesExProc', and if that isn't available, then on even
     * simpler routines.
     *
     * Special consideration must be given to Windows hardcoded names like
     * Special consideration must be given to Windows hard-coded names like
     * CON, NULL, COM1, LPT1 etc. For these, we still need to do the
     * CreateFile as some may not exist (e.g. there is no CON in wish by
     * default). However the subsequent GetFileInformationByHandle will
     * fail. We do a WinIsReserved to see if it is one of the special names,
     * and if successful, mock up a BY_HANDLE_FILE_INFORMATION structure.
     */

    fileHandle = CreateFileW(nativePath, GENERIC_READ,
	    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
	    NULL, OPEN_EXISTING,
	    FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);

    if (fileHandle != INVALID_HANDLE_VALUE) {
	BY_HANDLE_FILE_INFORMATION data;

	if (GetFileInformationByHandle(fileHandle,&data) != TRUE) {
            fileType = GetFileType(fileHandle);
            CloseHandle(fileHandle);
            if (fileType != FILE_TYPE_CHAR && fileType != FILE_TYPE_DISK) {
                Tcl_SetErrno(ENOENT);
                return -1;
            }
	    fileType = GetFileType(fileHandle);
	    CloseHandle(fileHandle);
	    if (fileType != FILE_TYPE_CHAR && fileType != FILE_TYPE_DISK) {
		Tcl_SetErrno(ENOENT);
		return -1;
	    }

            /*
	    /*
	     * Mock up the expected structure
	     */

            memset(&data, 0, sizeof(data));
            statPtr->st_atime = 0;
            statPtr->st_mtime = 0;
            statPtr->st_ctime = 0;
        } else {
            CloseHandle(fileHandle);
            statPtr->st_atime = ToCTime(data.ftLastAccessTime);
            statPtr->st_mtime = ToCTime(data.ftLastWriteTime);
            statPtr->st_ctime = ToCTime(data.ftCreationTime);
        }
	    memset(&data, 0, sizeof(data));
	    statPtr->st_atime = 0;
	    statPtr->st_mtime = 0;
	    statPtr->st_ctime = 0;
	} else {
	    CloseHandle(fileHandle);
	    statPtr->st_atime = ToCTime(data.ftLastAccessTime);
	    statPtr->st_mtime = ToCTime(data.ftLastWriteTime);
	    statPtr->st_ctime = ToCTime(data.ftCreationTime);
	}
	attr = data.dwFileAttributes;
	statPtr->st_size = ((Tcl_WideInt) data.nFileSizeLow) |
		(((Tcl_WideInt) data.nFileSizeHigh) << 32);
	statPtr->st_size = ((long long) data.nFileSizeLow) |
		(((long long) data.nFileSizeHigh) << 32);

	/*
	 * On Unix, for directories, nlink apparently depends on the number of
	 * files in the directory.  We could calculate that, but it would be a
	 * bit of a performance penalty, I think. Hence we just use what
	 * Windows gives us, which is the same as Unix for files, at least.
	 */
2108
2109
2110
2111
2112
2113
2114
2115

2116
2117
2118
2119
2120

2121
2122
2123
2124
2125
2126
2127
2128
2129
2130


2131
2132
2133
2134
2135
2136
2137
2138
2139
2140


2141
2142
2143


2144
2145
2146
2147
2148
2149
2150
2106
2107
2108
2109
2110
2111
2112

2113
2114
2115
2116
2117

2118
2119
2120
2121
2122
2123
2124
2125
2126


2127
2128
2129
2130
2131
2132
2133
2134
2135
2136


2137
2138
2139


2140
2141
2142
2143
2144
2145
2146
2147
2148







-
+




-
+








-
-
+
+








-
-
+
+

-
-
+
+







	if (GetFileAttributesExW(nativePath,
		GetFileExInfoStandard, &data) != TRUE) {
	    HANDLE hFind;
	    WIN32_FIND_DATAW ffd;
	    DWORD lasterror = GetLastError();

	    if (lasterror != ERROR_SHARING_VIOLATION) {
		TclWinConvertError(lasterror);
		Tcl_WinConvertError(lasterror);
		return -1;
		}
	    hFind = FindFirstFileW(nativePath, &ffd);
	    if (hFind == INVALID_HANDLE_VALUE) {
		TclWinConvertError(GetLastError());
		Tcl_WinConvertError(GetLastError());
		return -1;
	    }
	    memcpy(&data, &ffd, sizeof(data));
	    FindClose(hFind);
	}

	attr = data.dwFileAttributes;

	statPtr->st_size = ((Tcl_WideInt) data.nFileSizeLow) |
		(((Tcl_WideInt) data.nFileSizeHigh) << 32);
	statPtr->st_size = ((long long) data.nFileSizeLow) |
		(((long long) data.nFileSizeHigh) << 32);
	statPtr->st_atime = ToCTime(data.ftLastAccessTime);
	statPtr->st_mtime = ToCTime(data.ftLastWriteTime);
	statPtr->st_ctime = ToCTime(data.ftCreationTime);
    }

    dev = NativeDev(nativePath);
    mode = NativeStatMode(attr, checkLinks, NativeIsExec(nativePath));
    if (fileType == FILE_TYPE_CHAR) {
        mode &= ~S_IFMT;
        mode |= S_IFCHR;
	mode &= ~S_IFMT;
	mode |= S_IFCHR;
    } else if (fileType == FILE_TYPE_DISK) {
        mode &= ~S_IFMT;
        mode |= S_IFBLK;
	mode &= ~S_IFMT;
	mode |= S_IFBLK;
    }

    statPtr->st_dev	= (dev_t) dev;
    statPtr->st_ino	= inode;
    statPtr->st_mode	= mode;
    statPtr->st_nlink	= nlink;
    statPtr->st_uid	= 0;
2171
2172
2173
2174
2175
2176
2177
2178

2179
2180
2181
2182
2183
2184
2185
2169
2170
2171
2172
2173
2174
2175

2176
2177
2178
2179
2180
2181
2182
2183







-
+







    Tcl_DString ds;
    WCHAR nativeFullPath[MAX_PATH];
    WCHAR *nativePart;
    const char *fullPath;

    GetFullPathNameW(nativePath, MAX_PATH, nativeFullPath, &nativePart);
    Tcl_DStringInit(&ds);
    fullPath = Tcl_WCharToUtfDString(nativeFullPath, -1, &ds);
    fullPath = Tcl_WCharToUtfDString(nativeFullPath, TCL_INDEX_NONE, &ds);

    if ((fullPath[0] == '\\') && (fullPath[1] == '\\')) {
	const char *p;
	DWORD dw;
	const WCHAR *nativeVol;
	Tcl_DString volString;

2285
2286
2287
2288
2289
2290
2291
2292

2293
2294
2295
2296
2297
2298
2299
2283
2284
2285
2286
2287
2288
2289

2290
2291
2292
2293
2294
2295
2296
2297







-
+







{
    LARGE_INTEGER convertedTime;

    convertedTime.LowPart = fileTime.dwLowDateTime;
    convertedTime.HighPart = (LONG) fileTime.dwHighDateTime;

    return (__time64_t) ((convertedTime.QuadPart -
	    (Tcl_WideInt) POSIX_EPOCH_AS_FILETIME) / (Tcl_WideInt) 10000000);
	    (long long) POSIX_EPOCH_AS_FILETIME) / (long long) 10000000);
}

/*
 *------------------------------------------------------------------------
 *
 * FromCTime --
 *
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
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







-
+








-
+

-
+




-
+







 *	This function replaces the library version of getcwd().
 *
 * Results:
 *	The input and output are filesystem paths in native form. The result
 *	is either the given clientData, if the working directory hasn't
 *	changed, or a new clientData (owned by our caller), giving the new
 *	native path, or NULL if the current directory could not be determined.
 *	If NULL is returned, the caller can examine the standard posix error
 *	If NULL is returned, the caller can examine the standard Posix error
 *	codes to determine the cause of the problem.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

ClientData
void *
TclpGetNativeCwd(
    ClientData clientData)
    void *clientData)
{
    WCHAR buffer[MAX_PATH];

    if (GetCurrentDirectoryW(MAX_PATH, buffer) == 0) {
	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	return NULL;
    }

    if (clientData != NULL) {
	if (wcscmp((const WCHAR *) clientData, buffer) == 0) {
	    return clientData;
	}
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
2489
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







-
+


















-
-
+
+







	return NULL;
    }
    path = TclGetString(normPath);
    if (path == NULL) {
	return NULL;
    }

    firstSeparator = strchr(path, '/');
    firstSeparator = strchr((char *)path, '/');
    if (firstSeparator == NULL) {
	found = GetVolumeInformationW((const WCHAR *)Tcl_FSGetNativePath(pathPtr),
		NULL, 0, NULL, NULL, NULL, volType, VOL_BUF_SIZE);
    } else {
	Tcl_Obj *driveName = Tcl_NewStringObj(path, firstSeparator - path+1);

	Tcl_IncrRefCount(driveName);
	found = GetVolumeInformationW((const WCHAR *)Tcl_FSGetNativePath(driveName),
		NULL, 0, NULL, NULL, NULL, volType, VOL_BUF_SIZE);
	Tcl_DecrRefCount(driveName);
    }

    if (found == 0) {
	return NULL;
    } else {
	Tcl_DString ds;

	Tcl_DStringInit(&ds);
	Tcl_WCharToUtfDString(volType, -1, &ds);
	return TclDStringToObj(&ds);
	Tcl_WCharToUtfDString(volType, TCL_INDEX_NONE, &ds);
	return Tcl_DStringToObj(&ds);
    }
#undef VOL_BUF_SIZE
}

/*
 * This define can be turned on to experiment with a different way of
 * normalizing paths (using a different Windows API). Unfortunately the new
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
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







-
+






-
+


-
+








-
+







	    if (GetFileAttributesExW(nativePath,
		    GetFileExInfoStandard, &data) != TRUE) {
		/*
		 * File doesn't exist.
		 */

		if (isDrive) {
		    int len = WinIsReserved(path);
		    size_t len = WinIsReserved(path);

		    if (len > 0) {
			/*
			 * Actually it does exist - COM1, etc.
			 */

			int i;
			size_t i;

			for (i=0 ; i<len ; i++) {
			    WCHAR wc = ((WCHAR *) nativePath)[i];
			    WCHAR wc = ((WCHAR *)nativePath)[i];

			    if (wc >= 'a') {
				wc -= ('a' - 'A');
				((WCHAR *) nativePath)[i] = wc;
			    }
			}
			Tcl_DStringAppend(&dsNorm,
				(const char *)nativePath,
				(int)(sizeof(WCHAR) * len));
				sizeof(WCHAR) * len);
			lastValidPathEnd = currentPathEndPosition;
		    } else if (nextCheckpoint == 0) {
			/*
			 * Path starts with a drive designation that's not
			 * actually on the system. We still must normalize up
			 * past the first separator. [Bug 3603434]
			 */
2622
2623
2624
2625
2626
2627
2628
2629

2630
2631
2632
2633
2634
2635
2636
2620
2621
2622
2623
2624
2625
2626

2627
2628
2629
2630
2631
2632
2633
2634







-
+







		     * Tcl_GetStringFromObj(to, &pathLen);
		     * nextCheckpoint = pathLen;
		     *
		     * So, instead we have to start from the beginning.
		     */

		    nextCheckpoint = 0;
		    Tcl_AppendToObj(to, currentPathEndPosition, -1);
		    Tcl_AppendToObj(to, currentPathEndPosition, TCL_INDEX_NONE);

		    /*
		     * Convert link to forward slashes.
		     */

		    for (path = TclGetString(to); *path != 0; path++) {
			if (*path == '\\') {
2723
2724
2725
2726
2727
2728
2729
2730

2731
2732
2733
2734
2735
2736
2737
2721
2722
2723
2724
2725
2726
2727

2728
2729
2730
2731
2732
2733
2734
2735







-
+







			    nativeName = fData.cAlternateFileName;
			}
			FindClose(handle);
			Tcl_DStringAppend(&dsNorm, (const char *) L"/",
				sizeof(WCHAR));
			Tcl_DStringAppend(&dsNorm,
				(const char *) nativeName,
				(int) (wcslen(nativeName)*sizeof(WCHAR)));
				wcslen(nativeName)*sizeof(WCHAR));
		    }
		}
	    }
#endif /* !TclNORM_LONG_PATH */
	    Tcl_DStringFree(&ds);
	    lastValidPathEnd = currentPathEndPosition;
	    if (cur == 0) {
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
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







-
-
-
-
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
-







	currentPathEndPosition++;

#ifdef TclNORM_LONG_PATH
	/*
	 * Convert the entire known path to long form.
	 */

	if (1) {
	    WCHAR wpath[MAX_PATH];
	    const WCHAR *nativePath;
	    DWORD wpathlen;
	WCHAR wpath[MAX_PATH];
	const WCHAR *nativePath;
	DWORD wpathlen;

	    Tcl_DStringInit(&ds);
	    nativePath =
		    Tcl_UtfToWCharDString(path, lastValidPathEnd - path, &ds);
	    wpathlen = GetLongPathNameProc(nativePath,
		    (WCHAR *) wpath, MAX_PATH);
	    /*
	     * We have to make the drive letter uppercase.
	     */
	Tcl_DStringInit(&ds);
	nativePath =
		Tcl_UtfToWCharDString(path, lastValidPathEnd - path, &ds);
	wpathlen = GetLongPathNameProc(nativePath,
		(WCHAR *) wpath, MAX_PATH);
	/*
	 * We have to make the drive letter uppercase.
	 */

	    if (wpath[0] >= 'a') {
		wpath[0] -= ('a' - 'A');
	    }
	    Tcl_DStringAppend(&dsNorm, (const char *) wpath,
		    wpathlen * sizeof(WCHAR));
	    Tcl_DStringFree(&ds);
	if (wpath[0] >= 'a') {
	    wpath[0] -= ('a' - 'A');
	}
	Tcl_DStringAppend(&dsNorm, (const char *) wpath,
		wpathlen * sizeof(WCHAR));
	Tcl_DStringFree(&ds);
	}
#endif /* TclNORM_LONG_PATH */
    }

    /*
     * Common code path for all Windows platforms.
     */

2794
2795
2796
2797
2798
2799
2800
2801

2802
2803
2804
2805
2806
2807



2808
2809
2810
2811
2812
2813
2814
2790
2791
2792
2793
2794
2795
2796

2797
2798
2799
2800



2801
2802
2803
2804
2805
2806
2807
2808
2809
2810







-
+



-
-
-
+
+
+







	nextCheckpoint = Tcl_DStringLength(&ds);
	if (*lastValidPathEnd != 0) {
	    /*
	     * Not the end of the string.
	     */

	    Tcl_Obj *tmpPathPtr;
	    size_t length;
	    Tcl_Size len;

	    tmpPathPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds),
		    nextCheckpoint);
	    Tcl_AppendToObj(tmpPathPtr, lastValidPathEnd, -1);
	    path = TclGetStringFromObj(tmpPathPtr, &length);
	    Tcl_SetStringObj(pathPtr, path, length);
	    Tcl_AppendToObj(tmpPathPtr, lastValidPathEnd, TCL_INDEX_NONE);
	    path = TclGetStringFromObj(tmpPathPtr, &len);
	    Tcl_SetStringObj(pathPtr, path, len);
	    Tcl_DecrRefCount(tmpPathPtr);
	} else {
	    /*
	     * End of string was reached above.
	     */

	    Tcl_SetStringObj(pathPtr, Tcl_DStringValue(&ds), nextCheckpoint);
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
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







-
+











-
+







	 * Path of form /foo/bar which is a path in the root directory of the
	 * current volume.
	 */

	const char *drive = TclGetString(useThisCwd);

	absolutePath = Tcl_NewStringObj(drive,2);
	Tcl_AppendToObj(absolutePath, path, -1);
	Tcl_AppendToObj(absolutePath, path, TCL_INDEX_NONE);
	Tcl_IncrRefCount(absolutePath);

	/*
	 * We have a refCount on the cwd.
	 */
    } else {
	/*
	 * Path of form C:foo/bar, but this only makes sense if the cwd is
	 * also on drive C.
	 */

	size_t cwdLen;
	Tcl_Size cwdLen;
	const char *drive = TclGetStringFromObj(useThisCwd, &cwdLen);
	char drive_cur = path[0];

	if (drive_cur >= 'a') {
	    drive_cur -= ('a' - 'A');
	}
	if (drive[0] == drive_cur) {
2924
2925
2926
2927
2928
2929
2930
2931

2932
2933
2934
2935
2936
2937
2938
2920
2921
2922
2923
2924
2925
2926

2927
2928
2929
2930
2931
2932
2933
2934







-
+







	     * could use the '_dgetdcwd' Win32 API to get the drive's cwd.
	     */

	    absolutePath = Tcl_NewStringObj(path, 2);
	    Tcl_AppendToObj(absolutePath, "/", 1);
	}
	Tcl_IncrRefCount(absolutePath);
	Tcl_AppendToObj(absolutePath, path+2, -1);
	Tcl_AppendToObj(absolutePath, path+2, TCL_INDEX_NONE);
    }
    *useThisCwdPtr = useThisCwd;
    return absolutePath;
}

/*
 *---------------------------------------------------------------------------
2953
2954
2955
2956
2957
2958
2959
2960

2961
2962
2963
2964
2965
2966
2967
2968

2969
2970
2971
2972
2973
2974
2975
2949
2950
2951
2952
2953
2954
2955

2956
2957
2958
2959
2960
2961
2962
2963

2964
2965
2966
2967
2968
2969
2970
2971







-
+







-
+







 *	None.
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclpNativeToNormalized(
    ClientData clientData)
    void *clientData)
{
    Tcl_DString ds;
    Tcl_Obj *objPtr;
    size_t len;
    char *copy, *p;

    Tcl_DStringInit(&ds);
    Tcl_WCharToUtfDString((const WCHAR *) clientData, -1, &ds);
    Tcl_WCharToUtfDString((const WCHAR *) clientData, TCL_INDEX_NONE, &ds);
    copy = Tcl_DStringValue(&ds);
    len = Tcl_DStringLength(&ds);

    /*
     * Certain native path representations on Windows have this special prefix
     * to indicate that they are to be treated specially. For example
     * extremely long paths, or symlinks.
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
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







-
+






-
+


-
+

-
+







 *
 * Side effects:
 *	Memory will be allocated. The path might be normalized.
 *
 *---------------------------------------------------------------------------
 */

ClientData
void *
TclNativeCreateNativeRep(
    Tcl_Obj *pathPtr)
{
    WCHAR *nativePathPtr = NULL;
    const char *str;
    Tcl_Obj *validPathPtr;
    size_t len;
    Tcl_Size len;
    WCHAR *wp;

    if (TclFSCwdIsNative()) {
    if (TclFSCwdIsNative() || Tcl_FSGetPathType(pathPtr) == TCL_PATH_ABSOLUTE) {
	/*
	 * The cwd is native, which means we can use the translated path
	 * The cwd is native (or path is absolute), use the translated path
	 * without worrying about normalization (this will also usually be
	 * shorter so the utf-to-external conversion will be somewhat faster).
	 */

	validPathPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
	if (validPathPtr == NULL) {
	    return NULL;
3059
3060
3061
3062
3063
3064
3065
3066

3067
3068
3069
3070
3071
3072
3073
3055
3056
3057
3058
3059
3060
3061

3062
3063
3064
3065
3066
3067
3068
3069







-
+







	 */

	Tcl_IncrRefCount(validPathPtr);
    }

    str = TclGetStringFromObj(validPathPtr, &len);

    if (strlen(str) != len) {
    if (strlen(str) != (size_t)len) {
	/*
	 * String contains NUL-bytes. This is invalid.
	 */

	goto done;
    }

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
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







-
+


-
+
+

















-
+








    /*
     * Overallocate 6 chars, making some room for extended paths
     */

    wp = nativePathPtr = (WCHAR *)Tcl_Alloc((len + 6) * sizeof(WCHAR));
    if (nativePathPtr==0) {
      goto done;
	goto done;
    }
    MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, -1, nativePathPtr,
	    len + 1);
	    len + 2);
    nativePathPtr[len] = 0;

    /*
     * If path starts with "//?/" or "\\?\" (extended path), translate any
     * slashes to backslashes but leave the '?' intact
     */

    if ((str[0] == '\\' || str[0] == '/') && (str[1] == '\\' || str[1] == '/')
	    && str[2] == '?' && (str[3] == '\\' || str[3] == '/')) {
	wp[0] = wp[1] = wp[3] = '\\';
	str += 4;
	wp += 4;
    }

    /*
     * If there is no "\\?\" prefix but there is a drive or UNC path prefix
     * and the path is larger than MAX_PATH chars, no Win32 API function can
     * handle that unless it is prefixed with the extended path prefix. See:
     * <http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath>
     * <https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#maxpath>
     */

    if (((str[0] >= 'A' && str[0] <= 'Z') || (str[0] >= 'a' && str[0] <= 'z'))
	    && str[1] == ':') {
	if (wp == nativePathPtr && len > MAX_PATH
		&& (str[2] == '\\' || str[2] == '/')) {
	    memmove(wp + 4, wp, len * sizeof(WCHAR));
3143
3144
3145
3146
3147
3148
3149
3150

3151
3152
3153
3154
3155
3156
3157
3140
3141
3142
3143
3144
3145
3146

3147
3148
3149
3150
3151
3152
3153
3154







-
+








    /*
     * In the remainder of the path, translate invalid characters to
     * characters in the Unicode private use area.
     */

    while (*wp != '\0') {
	if ((*wp < ' ') || wcschr(L"\"*:<>?|", *wp)) {
	if ((*wp < ' ') || wcschr(L"\"*<>?|", *wp)) {
	    *wp |= 0xF000;
	} else if (*wp == '/') {
	    *wp = '\\';
	}
	++wp;
    }

3173
3174
3175
3176
3177
3178
3179
3180

3181
3182

3183
3184
3185
3186
3187
3188
3189
3170
3171
3172
3173
3174
3175
3176

3177
3178

3179
3180
3181
3182
3183
3184
3185
3186







-
+

-
+







 *
 * Side effects:
 *	Memory allocation for the copy.
 *
 *---------------------------------------------------------------------------
 */

ClientData
void *
TclNativeDupInternalRep(
    ClientData clientData)
    void *clientData)
{
    char *copy;
    size_t len;

    if (clientData == NULL) {
	return NULL;
    }
3241
3242
3243
3244
3245
3246
3247
3248

3249
3250
3251
3252
3253
3254
3255
3238
3239
3240
3241
3242
3243
3244

3245
3246
3247
3248
3249
3250
3251
3252







-
+







     */

    fileHandle = CreateFileW(native, FILE_WRITE_ATTRIBUTES, 0, NULL,
	    OPEN_EXISTING, flags, NULL);

    if (fileHandle == INVALID_HANDLE_VALUE ||
	    !SetFileTime(fileHandle, NULL, &lastAccessTime, &lastModTime)) {
	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	res = -1;
    }
    if (fileHandle != INVALID_HANDLE_VALUE) {
	CloseHandle(fileHandle);
    }
    return res;
}
3279
3280
3281
3282
3283
3284
3285
3286

3287
3288
3289
3290
3291

3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302

3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314









3315
3316
3317
3318
3319
3320
3321
3322

3323
3324
3325

3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3276
3277
3278
3279
3280
3281
3282

3283
3284
3285
3286
3287

3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298

3299
3300
3301
3302









3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318

3319
3320
3321

3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334







-
+




-
+










-
+



-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+







-
+


-
+












    int owned = 0;

    native = (const WCHAR *)Tcl_FSGetNativePath(pathPtr);

    if (GetNamedSecurityInfoW((LPWSTR) native, SE_FILE_OBJECT,
	    OWNER_SECURITY_INFORMATION, &ownerSid, NULL, NULL, NULL,
	    &secd) != ERROR_SUCCESS) {
        /*
	/*
	 * Either not a file, or we do not have access to it in which case we
	 * are in all likelihood not the owner.
	 */

        return 0;
	return 0;
    }

    /*
     * Getting the current process SID is a multi-step process.  We make the
     * assumption that if a call fails, this process is so underprivileged it
     * could not possibly own anything. Normally a process can *always* look
     * up its own token.
     */

    if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
        /*
	/*
	 * Find out how big the buffer needs to be.
	 */

        bufsz = 0;
        GetTokenInformation(token, TokenUser, NULL, 0, &bufsz);
        if (bufsz) {
            buf = (LPBYTE)Tcl_Alloc(bufsz);
            if (GetTokenInformation(token, TokenUser, buf, bufsz, &bufsz)) {
                owned = EqualSid(ownerSid, ((PTOKEN_USER) buf)->User.Sid);
            }
        }
        CloseHandle(token);
	bufsz = 0;
	GetTokenInformation(token, TokenUser, NULL, 0, &bufsz);
	if (bufsz) {
	    buf = (LPBYTE)Tcl_Alloc(bufsz);
	    if (GetTokenInformation(token, TokenUser, buf, bufsz, &bufsz)) {
		owned = EqualSid(ownerSid, ((PTOKEN_USER) buf)->User.Sid);
	    }
	}
	CloseHandle(token);
    }

    /*
     * Free allocations and be done.
     */

    if (secd) {
        LocalFree(secd);            /* Also frees ownerSid */
	LocalFree(secd);            /* Also frees ownerSid */
    }
    if (buf) {
        Tcl_Free(buf);
	Tcl_Free(buf);
    }

    return (owned != 0);        /* Convert non-0 to 1 */
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to win/tclWinInit.c.

1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







/*
 * tclWinInit.c --
 *
 *	Contains the Windows-specific interpreter initialization functions.
 *
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright © 1994-1997 Sun Microsystems, Inc.
 * Copyright © 1998-1999 Scriptics Corporation.
 * All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclWinInt.h"
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
31
32
33
34
35
36
37
38















































39
40
41
42

43
44
45

46
47
48
49
50
51
52
53








-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-




-
+


-
+







 */

typedef struct {
    WORD wProcessorArchitecture;
    WORD wReserved;
} OemId;

/*
 * The following macros are missing from some versions of winnt.h.
 */

#ifndef PROCESSOR_ARCHITECTURE_INTEL
#define PROCESSOR_ARCHITECTURE_INTEL		0
#endif
#ifndef PROCESSOR_ARCHITECTURE_MIPS
#define PROCESSOR_ARCHITECTURE_MIPS		1
#endif
#ifndef PROCESSOR_ARCHITECTURE_ALPHA
#define PROCESSOR_ARCHITECTURE_ALPHA		2
#endif
#ifndef PROCESSOR_ARCHITECTURE_PPC
#define PROCESSOR_ARCHITECTURE_PPC		3
#endif
#ifndef PROCESSOR_ARCHITECTURE_SHX
#define PROCESSOR_ARCHITECTURE_SHX		4
#endif
#ifndef PROCESSOR_ARCHITECTURE_ARM
#define PROCESSOR_ARCHITECTURE_ARM		5
#endif
#ifndef PROCESSOR_ARCHITECTURE_IA64
#define PROCESSOR_ARCHITECTURE_IA64		6
#endif
#ifndef PROCESSOR_ARCHITECTURE_ALPHA64
#define PROCESSOR_ARCHITECTURE_ALPHA64		7
#endif
#ifndef PROCESSOR_ARCHITECTURE_MSIL
#define PROCESSOR_ARCHITECTURE_MSIL		8
#endif
#ifndef PROCESSOR_ARCHITECTURE_AMD64
#define PROCESSOR_ARCHITECTURE_AMD64		9
#endif
#ifndef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
#define PROCESSOR_ARCHITECTURE_IA32_ON_WIN64	10
#endif
#ifndef PROCESSOR_ARCHITECTURE_UNKNOWN
#define PROCESSOR_ARCHITECTURE_UNKNOWN		0xFFFF
#endif


/*
 * Windows version dependend functions
 */
TclWinProcs tclWinProcs;

/*
 * The following arrays contain the human readable strings for the
 * processor values.
 */

#define NUMPROCESSORS 11
#define NUMPROCESSORS 15
static const char *const processors[NUMPROCESSORS] = {
    "intel", "mips", "alpha", "ppc", "shx", "arm", "ia64", "alpha64", "msil",
    "amd64", "ia32_on_win64"
    "amd64", "ia32_on_win64", "neutral", "arm64", "arm32_on_win64", "ia32_on_arm64"
};

/*
 * The default directory in which the init.tcl file is expected to be found.
 */

static TclInitProcessGlobalValueProc	InitializeDefaultLibraryDir;
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
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







-


















-
-
-
-
-
-
-
-







 */

void
TclpInitPlatform(void)
{
    WSADATA wsaData;
    WORD wVersionRequested = MAKEWORD(2, 2);
    HMODULE handle;

    tclPlatform = TCL_PLATFORM_WINDOWS;

    /*
     * Initialize the winsock library. On Windows XP and higher this
     * can never fail.
     */
    WSAStartup(wVersionRequested, &wsaData);

#ifdef STATIC_BUILD
    /*
     * If we are in a statically linked executable, then we need to explicitly
     * initialize the Windows function tables here since DllMain() will not be
     * invoked.
     */

    TclWinInit(GetModuleHandleW(NULL));
#endif

    /*
     * Fill available functions depending on windows version
     */
    handle = GetModuleHandleW(L"KERNEL32");
    tclWinProcs.cancelSynchronousIo =
	    (BOOL (WINAPI *)(HANDLE))(void *)GetProcAddress(handle,
	    "CancelSynchronousIo");
}

/*
 *-------------------------------------------------------------------------
 *
 * TclpInitLibraryPath --
 *
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
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







-
+









-
+





-
+







    size_t *lengthPtr,
    Tcl_Encoding *encodingPtr)
{
#define LIBRARY_SIZE	    64
    Tcl_Obj *pathPtr;
    char installLib[LIBRARY_SIZE];
    const char *bytes;
    size_t length;
    Tcl_Size length;

    TclNewObj(pathPtr);

    /*
     * Initialize the substring used when locating the script library. The
     * installLib variable computes the script library path relative to the
     * installed DLL.
     */

    sprintf(installLib, "lib/tcl%s", TCL_VERSION);
    snprintf(installLib, sizeof(installLib), "lib/tcl%s", TCL_VERSION);

    /*
     * Look for the library relative to the TCL_LIBRARY env variable. If the
     * last dirname in the TCL_LIBRARY path does not match the last dirname in
     * the installLib variable, use the last dir name of installLib in
     * addition to the orginal TCL_LIBRARY path.
     * addition to the original TCL_LIBRARY path.
     */

    AppendEnvironment(pathPtr, installLib);

    /*
     * Look for the library in its default location.
     */
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
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







-
-
+
+















-
+









-
+
















-
-
+
+






-
+







/*
 *---------------------------------------------------------------------------
 *
 * AppendEnvironment --
 *
 *	Append the value of the TCL_LIBRARY environment variable onto the path
 *	pointer. If the env variable points to another version of tcl (e.g.
 *	"tcl7.6") also append the path to this version (e.g.,
 *	"tcl7.6/../tcl8.2")
 *	"tcl8.6") also append the path to this version (e.g.,
 *	"tcl8.6/../tcl9.0")
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

static void
AppendEnvironment(
    Tcl_Obj *pathPtr,
    const char *lib)
{
    int pathc;
    Tcl_Size pathc;
    WCHAR wBuf[MAX_PATH];
    char buf[MAX_PATH * 3];
    Tcl_Obj *objPtr;
    Tcl_DString ds;
    const char **pathv;
    char *shortlib;

    /*
     * The shortlib value needs to be the tail component of the lib path. For
     * example, "lib/tcl8.4" -> "tcl8.4" while "usr/share/tcl8.5" -> "tcl8.5".
     * example, "lib/tcl9.0" -> "tcl9.0" while "usr/share/tcl9.0" -> "tcl9.0".
     */

    for (shortlib = (char *) &lib[strlen(lib)-1]; shortlib>lib ; shortlib--) {
	if (*shortlib == '/') {
	    if ((size_t)(shortlib - lib) == strlen(lib) - 1) {
		Tcl_Panic("last character in lib cannot be '/'");
	    }
	    shortlib++;
	    break;
	}
    }
    if (shortlib == lib) {
	Tcl_Panic("no '/' character found in lib");
    }

    /*
     * The "L" preceeding the TCL_LIBRARY string is used to tell VC++ that
     * this is a unicode string.
     * The "L" preceding the TCL_LIBRARY string is used to tell VC++ that
     * this is a Unicode string.
     */

    GetEnvironmentVariableW(L"TCL_LIBRARY", wBuf, MAX_PATH);
    WideCharToMultiByte(CP_UTF8, 0, wBuf, -1, buf, MAX_PATH * 3, NULL, NULL);

    if (buf[0] != '\0') {
	objPtr = Tcl_NewStringObj(buf, -1);
	objPtr = Tcl_NewStringObj(buf, TCL_INDEX_NONE);
	Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);

	TclWinNoBackslash(buf);
	Tcl_SplitPath(buf, &pathc, &pathv);

	/*
	 * The lstrcmpiA() will work even if pathv[pathc-1] is random UTF-8
307
308
309
310
311
312
313
314

315
316

317
318
319
320
321
322
323
251
252
253
254
255
256
257

258
259

260
261
262
263
264
265
266
267







-
+

-
+







	     * directory to make it refer to this installation by removing the
	     * old "tclX.Y" and substituting the current version string.
	     */

	    pathv[pathc - 1] = shortlib;
	    Tcl_DStringInit(&ds);
	    (void) Tcl_JoinPath(pathc, pathv, &ds);
	    objPtr = TclDStringToObj(&ds);
	    objPtr = Tcl_DStringToObj(&ds);
	} else {
	    objPtr = Tcl_NewStringObj(buf, -1);
	    objPtr = Tcl_NewStringObj(buf, TCL_INDEX_NONE);
	}
	Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
	Tcl_Free((void *)pathv);
    }
}

/*
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
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







-
-
+
+










-
+







    Tcl_Encoding *encodingPtr)
{
    HMODULE hModule = (HMODULE)TclWinGetTclInstance();
    WCHAR wName[MAX_PATH + LIBRARY_SIZE];
    char name[(MAX_PATH + LIBRARY_SIZE) * 3];
    char *end, *p;

    GetModuleFileNameW(hModule, wName, MAX_PATH);
    WideCharToMultiByte(CP_UTF8, 0, wName, -1, name, MAX_PATH * 3, NULL, NULL);
    GetModuleFileNameW(hModule, wName, sizeof(wName)/sizeof(WCHAR));
    WideCharToMultiByte(CP_UTF8, 0, wName, -1, name, sizeof(name), NULL, NULL);

    end = strrchr(name, '\\');
    *end = '\0';
    p = strrchr(name, '\\');
    if (p != NULL) {
	end = p;
    }
    *end = '\\';

    TclWinNoBackslash(name);
    sprintf(end + 1, "lib/tcl%s", TCL_VERSION);
    snprintf(end + 1, LIBRARY_SIZE, "lib/tcl%s", TCL_VERSION);
    *lengthPtr = strlen(name);
    *valuePtr = (char *)Tcl_Alloc(*lengthPtr + 1);
    *encodingPtr = NULL;
    memcpy(*valuePtr, name, *lengthPtr + 1);
}

/*
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
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







-
-
+
+










-
+







    Tcl_Encoding *encodingPtr)
{
    HMODULE hModule = (HMODULE)TclWinGetTclInstance();
    WCHAR wName[MAX_PATH + LIBRARY_SIZE];
    char name[(MAX_PATH + LIBRARY_SIZE) * 3];
    char *end, *p;

    GetModuleFileNameW(hModule, wName, MAX_PATH);
    WideCharToMultiByte(CP_UTF8, 0, wName, -1, name, MAX_PATH * 3, NULL, NULL);
    GetModuleFileNameW(hModule, wName, sizeof(wName)/sizeof(WCHAR));
    WideCharToMultiByte(CP_UTF8, 0, wName, -1, name, sizeof(name), NULL, NULL);

    end = strrchr(name, '\\');
    *end = '\0';
    p = strrchr(name, '\\');
    if (p != NULL) {
	end = p;
    }
    *end = '\\';

    TclWinNoBackslash(name);
    sprintf(end + 1, "../library");
    snprintf(end + 1, LIBRARY_SIZE, "../library");
    *lengthPtr = strlen(name);
    *valuePtr = (char *)Tcl_Alloc(*lengthPtr + 1);
    *encodingPtr = NULL;
    memcpy(*valuePtr, name, *lengthPtr + 1);
}

/*
456
457
458
459
460
461
462
463

464
465
466
467
468
469
470
400
401
402
403
404
405
406

407
408
409
410
411
412
413
414







-
+







    UINT acp = GetACP();

    Tcl_DStringInit(bufPtr);
    if (acp == CP_UTF8) {
	Tcl_DStringAppend(bufPtr, "utf-8", 5);
    } else {
	Tcl_DStringSetLength(bufPtr, 2+TCL_INTEGER_SPACE);
	wsprintfA(Tcl_DStringValue(bufPtr), "cp%d", GetACP());
	snprintf(Tcl_DStringValue(bufPtr), 2+TCL_INTEGER_SPACE, "cp%d", GetACP());
	Tcl_DStringSetLength(bufPtr, strlen(Tcl_DStringValue(bufPtr)));
    }
    return Tcl_DStringValue(bufPtr);
}

const char *
TclpGetUserName(
537
538
539
540
541
542
543



544

545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575

576
577
578
579

580
581
582
583
584






585


586
587
588
589
590
591
592
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







+
+
+
-
+







-
-
-
-
-
-
-
-
-
-
-
-
-










-
+



-
+





+
+
+
+
+
+
-
+
+







     * Define the tcl_platform array.
     */

    Tcl_SetVar2(interp, "tcl_platform", "platform", "windows",
	    TCL_GLOBAL_ONLY);
    Tcl_SetVar2(interp, "tcl_platform", "os",
	    "Windows NT", TCL_GLOBAL_ONLY);
    if (osInfo.dwMajorVersion == 10 && osInfo.dwBuildNumber >= 22000) {
	osInfo.dwMajorVersion = 11;
    }
    wsprintfA(buffer, "%d.%d", osInfo.dwMajorVersion, osInfo.dwMinorVersion);
    snprintf(buffer, sizeof(buffer), "%ld.%ld", osInfo.dwMajorVersion, osInfo.dwMinorVersion);
    Tcl_SetVar2(interp, "tcl_platform", "osVersion", buffer, TCL_GLOBAL_ONLY);
    if (sys.oemId.wProcessorArchitecture < NUMPROCESSORS) {
	Tcl_SetVar2(interp, "tcl_platform", "machine",
		processors[sys.oemId.wProcessorArchitecture],
		TCL_GLOBAL_ONLY);
    }

#ifndef NDEBUG
    /*
     * The existence of the "debug" element of the tcl_platform array
     * indicates that this particular Tcl shell has been compiled with debug
     * information. Using "info exists tcl_platform(debug)" a Tcl script can
     * direct the interpreter to load debug versions of DLLs with the load
     * command.
     */

    Tcl_SetVar2(interp, "tcl_platform", "debug", "1",
	    TCL_GLOBAL_ONLY);
#endif

    /*
     * Set up the HOME environment variable from the HOMEDRIVE & HOMEPATH
     * environment variables, if necessary.
     */

    Tcl_DStringInit(&ds);
    ptr = Tcl_GetVar2(interp, "env", "HOME", TCL_GLOBAL_ONLY);
    if (ptr == NULL) {
	ptr = Tcl_GetVar2(interp, "env", "HOMEDRIVE", TCL_GLOBAL_ONLY);
	if (ptr != NULL) {
	    Tcl_DStringAppend(&ds, ptr, -1);
	    Tcl_DStringAppend(&ds, ptr, TCL_INDEX_NONE);
	}
	ptr = Tcl_GetVar2(interp, "env", "HOMEPATH", TCL_GLOBAL_ONLY);
	if (ptr != NULL) {
	    Tcl_DStringAppend(&ds, ptr, -1);
	    Tcl_DStringAppend(&ds, ptr, TCL_INDEX_NONE);
	}
	if (Tcl_DStringLength(&ds) > 0) {
	    Tcl_SetVar2(interp, "env", "HOME", Tcl_DStringValue(&ds),
		    TCL_GLOBAL_ONLY);
	} else {
	    /* None of HOME, HOMEDRIVE, HOMEPATH exists. Try USERPROFILE */
	    ptr = Tcl_GetVar2(interp, "env", "USERPROFILE", TCL_GLOBAL_ONLY);
	    if (ptr != NULL && ptr[0]) {
		Tcl_SetVar2(interp, "env", "HOME", ptr, TCL_GLOBAL_ONLY);
	    } else {
		/* Last resort */
	    Tcl_SetVar2(interp, "env", "HOME", "c:\\", TCL_GLOBAL_ONLY);
		Tcl_SetVar2(interp, "env", "HOME", "c:\\", TCL_GLOBAL_ONLY);
	    }
	}
    }

    /*
     * Initialize the user name from the environment first, since this is much
     * faster than asking the system.
     * Note: cchUserNameLen is number of characters including nul terminator.
610
611
612
613
614
615
616
617

618
619
620
621
622
623
624
625
626
627
628
629
630
631

632
633
634
635

636
637
638
639
640

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

657
658
659
660
661
662
663
664
665
666

667
668
669
670
671
672
673
551
552
553
554
555
556
557

558
559
560
561
562
563
564
565
566
567
568




569
570
571
572

573
574
575
576
577

578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593

594


595
596
597
598
599
600
601

602
603
604
605
606
607
608
609







-
+










-
-
-
-
+



-
+




-
+















-
+
-
-







-
+







 * TclpFindVariable --
 *
 *	Locate the entry in environ for a given name. On Unix this routine is
 *	case sensitive, on Windows this matches mixed case.
 *
 * Results:
 *	The return value is the index in environ of an entry with the name
 *	"name", or TCL_INDEX_NONE if there is no such entry. The integer
 *	"name", or -1 if there is no such entry. The integer
 *	at *lengthPtr is filled in with the length of name (if a matching
 *	entry is found) or the length of the environ array (if no
 *	matching entry is found).
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

#  define tenviron2utfdstr(string, len, dsPtr) \
		(char *)Tcl_Char16ToUtfDString((const unsigned short *)(string), ((((len) + 2) >> 1) - 1), (dsPtr))

size_t
Tcl_Size
TclpFindVariable(
    const char *name,		/* Name of desired environment variable
				 * (UTF-8). */
    size_t *lengthPtr)		/* Used to return length of name (for
    Tcl_Size *lengthPtr)		/* Used to return length of name (for
				 * successful searches) or number of non-NULL
				 * entries in environ (for unsuccessful
				 * searches). */
{
    size_t i, length, result = TCL_INDEX_NONE;
    Tcl_Size i, length, result = TCL_INDEX_NONE;
    const WCHAR *env;
    const char *p1, *p2;
    char *envUpper, *nameUpper;
    Tcl_DString envString;

    /*
     * Convert the name to all upper case for the case insensitive comparison.
     */

    length = strlen(name);
    nameUpper = (char *)Tcl_Alloc(length + 1);
    memcpy(nameUpper, name, length+1);
    Tcl_UtfToUpper(nameUpper);

    Tcl_DStringInit(&envString);
    for (i = 0, env = _wenviron[i];
    for (i = 0, env = _wenviron[i]; env != NULL; i++, env = _wenviron[i]) {
	env != NULL;
	i++, env = _wenviron[i]) {
	/*
	 * Chop the env string off after the equal sign, then Convert the name
	 * to all upper case, so we do not have to convert all the characters
	 * after the equal sign.
	 */

	Tcl_DStringInit(&envString);
	envUpper = Tcl_WCharToUtfDString(env, -1, &envString);
	envUpper = Tcl_WCharToUtfDString(env, TCL_INDEX_NONE, &envString);
	p1 = strchr(envUpper, '=');
	if (p1 == NULL) {
	    continue;
	}
	length = p1 - envUpper;
	Tcl_DStringSetLength(&envString, length+1);
	Tcl_UtfToUpper(envUpper);

Changes to win/tclWinInt.h.

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
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







-
-
-
-
-
-
-
-
-












-
-









-
+
+







	    struct _EXCEPTION_RECORD*, void*, struct _CONTEXT*, void*);
    void *ebp;
    void *esp;
    int status;
} TCLEXCEPTION_REGISTRATION;
#endif

/*
 * Windows version dependend functions
 */
typedef struct TclWinProcs {
    BOOL (WINAPI *cancelSynchronousIo)(HANDLE);
} TclWinProcs;

MODULE_SCOPE TclWinProcs tclWinProcs;

/*
 * Declarations of functions that are not accessible by way of the
 * stubs table.
 */

MODULE_SCOPE char	TclWinDriveLetterForVolMountPoint(
			    const WCHAR *mountPoint);
MODULE_SCOPE void	TclWinEncodingsCleanup(void);
MODULE_SCOPE void	TclWinInit(HINSTANCE hInst);
MODULE_SCOPE TclFile	TclWinMakeFile(HANDLE handle);
MODULE_SCOPE Tcl_Channel TclWinOpenConsoleChannel(HANDLE handle,
			    char *channelName, int permissions);
MODULE_SCOPE Tcl_Channel TclWinOpenFileChannel(HANDLE handle, char *channelName,
			    int permissions, int appendMode);
MODULE_SCOPE Tcl_Channel TclWinOpenSerialChannel(HANDLE handle,
			    char *channelName, int permissions);
MODULE_SCOPE HANDLE	TclWinSerialOpen(HANDLE handle, const WCHAR *name,
			    DWORD access);
MODULE_SCOPE int	TclWinSymLinkCopyDirectory(const WCHAR *LinkOriginal,
			    const WCHAR *LinkCopy);
MODULE_SCOPE int	TclWinSymLinkDelete(const WCHAR *LinkOriginal,
			    int linkOnly);
MODULE_SCOPE int        TclWinFileOwned(Tcl_Obj *);

MODULE_SCOPE void	TclWinGenerateChannelName(char channelName[],
			    const char *channelTypeName, void *channelImpl);
MODULE_SCOPE const char*TclpGetUserName(Tcl_DString *bufferPtr);

/* Needed by tclWinFile.c and tclWinFCmd.c */
#ifndef FILE_ATTRIBUTE_REPARSE_POINT
#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
#endif

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
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







-
+


-



















-








typedef struct TclPipeThreadInfo {
    HANDLE evControl;		/* Auto-reset event used by the main thread to
				 * signal when the pipe thread should attempt
				 * to do read/write operation. Additionally
				 * used as signal to stop (state set to -1) */
    volatile LONG state;	/* Indicates current state of the thread */
    void *clientData;	/* Referenced data of the main thread */
    void *clientData;		/* Referenced data of the main thread */
    HANDLE evWakeUp;		/* Optional wake-up event worker set by shutdown */
} TclPipeThreadInfo;


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

/*
 * State of the pipe-worker.
 *
 * State PTI_STATE_STOP possible from idle state only, worker owns TI structure.
 * Otherwise PTI_STATE_END used (main thread hold ownership of the TI).
 */

#define PTI_STATE_IDLE	0	/* idle or not yet initialzed */
#define PTI_STATE_WORK	1	/* in work */
#define PTI_STATE_STOP	2	/* thread should stop work (owns TI structure) */
#define PTI_STATE_END	4	/* thread should stop work (worker is busy) */
#define PTI_STATE_DOWN  8	/* worker is down */


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

static inline void

Changes to win/tclWinLoad.c.

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
30
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
30
31
32







-
+














+

+







/*
 * tclWinLoad.c --
 *
 *	This function provides a version of the TclLoadFile that works with
 *	the Windows "LoadLibrary" and "GetProcAddress" API for dynamic
 *	loading.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclWinInt.h"

/*
 * Native name of the directory in the native filesystem where DLLs used in
 * this process are copied prior to loading, and mutex used to protect its
 * allocation.
 */

static WCHAR *dllDirectoryName = NULL;
#if TCL_THREADS
static Tcl_Mutex dllDirectoryNameMutex;
#endif

/*
 * Static functions defined within this file.
 */

static void *		FindSymbol(Tcl_Interp *interp,
			    Tcl_LoadHandle loadHandle, const char *symbol);
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
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







-
-
-
-
-
+
+
+
+
+



-
+







-
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+














-
+


-
+


-
+


-
+


-
+


-
+

-
+


-
+

-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+











-
+







	 * Let the OS loader examine the binary search path for whatever
	 * string the user gave us which hopefully refers to a file on the
	 * binary path.
	 */

	Tcl_DString ds;

        /*
         * Remember the first error on load attempt to be used if the
         * second load attempt below also fails.
        */
        firstError = (nativeName == NULL) ?
	/*
	 * Remember the first error on load attempt to be used if the
	 * second load attempt below also fails.
	*/
	firstError = (nativeName == NULL) ?
		ERROR_MOD_NOT_FOUND : GetLastError();

	Tcl_DStringInit(&ds);
	nativeName = Tcl_UtfToWCharDString(TclGetString(pathPtr), -1, &ds);
	nativeName = Tcl_UtfToWCharDString(TclGetString(pathPtr), TCL_INDEX_NONE, &ds);
	hInstance = LoadLibraryExW(nativeName, NULL,
		LOAD_WITH_ALTERED_SEARCH_PATH);
	Tcl_DStringFree(&ds);
    }

    if (hInstance == NULL) {
	DWORD lastError;
        Tcl_Obj *errMsg;
	Tcl_Obj *errMsg;

        /*
         * We choose to only use the error from the second call if the first
         * call failed due to the file not being found. Else stick to the
         * first error for reporting purposes.
         */
        if (firstError == ERROR_MOD_NOT_FOUND ||
            firstError == ERROR_DLL_NOT_FOUND)
            lastError = GetLastError();
        else
            lastError = firstError;
	/*
	 * We choose to only use the error from the second call if the first
	 * call failed due to the file not being found. Else stick to the
	 * first error for reporting purposes.
	 */
	if (firstError == ERROR_MOD_NOT_FOUND ||
		firstError == ERROR_DLL_NOT_FOUND) {
	    lastError = GetLastError();
	} else {
	    lastError = firstError;
	}

	errMsg = Tcl_ObjPrintf("couldn't load library \"%s\": ",
		TclGetString(pathPtr));

	/*
	 * Check for possible DLL errors. This doesn't work quite right,
	 * because Windows seems to only return ERROR_MOD_NOT_FOUND for just
	 * about any problem, but it's better than nothing. It'd be even
	 * better if there was a way to get what DLLs
	 */

	if (interp) {
	    switch (lastError) {
	    case ERROR_MOD_NOT_FOUND:
		Tcl_SetErrorCode(interp, "WIN_LOAD", "MOD_NOT_FOUND", NULL);
		Tcl_SetErrorCode(interp, "WIN_LOAD", "MOD_NOT_FOUND", (char *)NULL);
		goto notFoundMsg;
	    case ERROR_DLL_NOT_FOUND:
		Tcl_SetErrorCode(interp, "WIN_LOAD", "DLL_NOT_FOUND", NULL);
		Tcl_SetErrorCode(interp, "WIN_LOAD", "DLL_NOT_FOUND", (char *)NULL);
	    notFoundMsg:
		Tcl_AppendToObj(errMsg, "this library or a dependent library"
			" could not be found in library path", -1);
			" could not be found in library path", TCL_INDEX_NONE);
		break;
	    case ERROR_PROC_NOT_FOUND:
		Tcl_SetErrorCode(interp, "WIN_LOAD", "PROC_NOT_FOUND", NULL);
		Tcl_SetErrorCode(interp, "WIN_LOAD", "PROC_NOT_FOUND", (char *)NULL);
		Tcl_AppendToObj(errMsg, "A function specified in the import"
			" table could not be resolved by the system. Windows"
			" is not telling which one, I'm sorry.", -1);
			" is not telling which one, I'm sorry.", TCL_INDEX_NONE);
		break;
	    case ERROR_INVALID_DLL:
		Tcl_SetErrorCode(interp, "WIN_LOAD", "INVALID_DLL", NULL);
		Tcl_SetErrorCode(interp, "WIN_LOAD", "INVALID_DLL", (char *)NULL);
		Tcl_AppendToObj(errMsg, "this library or a dependent library"
			" is damaged", -1);
			" is damaged", TCL_INDEX_NONE);
		break;
	    case ERROR_DLL_INIT_FAILED:
		Tcl_SetErrorCode(interp, "WIN_LOAD", "DLL_INIT_FAILED", NULL);
		Tcl_SetErrorCode(interp, "WIN_LOAD", "DLL_INIT_FAILED", (char *)NULL);
		Tcl_AppendToObj(errMsg, "the library initialization"
			" routine failed", -1);
			" routine failed", TCL_INDEX_NONE);
		break;
            case ERROR_BAD_EXE_FORMAT:
		Tcl_SetErrorCode(interp, "WIN_LOAD", "BAD_EXE_FORMAT", NULL);
		Tcl_AppendToObj(errMsg, "Bad exe format. Possibly a 32/64-bit mismatch.", -1);
                break;
            default:
		TclWinConvertError(lastError);
		Tcl_AppendToObj(errMsg, Tcl_PosixError(interp), -1);
	    case ERROR_BAD_EXE_FORMAT:
		Tcl_SetErrorCode(interp, "WIN_LOAD", "BAD_EXE_FORMAT", (char *)NULL);
		Tcl_AppendToObj(errMsg, "Bad exe format. Possibly a 32/64-bit mismatch.", TCL_INDEX_NONE);
		break;
	    default:
		Tcl_WinConvertError(lastError);
		Tcl_AppendToObj(errMsg, Tcl_PosixError(interp), TCL_INDEX_NONE);
	    }
	    Tcl_SetObjResult(interp, errMsg);
	}
	return TCL_ERROR;
    }

    /*
     * Succeded; package everything up for Tcl.
     */

    handlePtr = (Tcl_LoadHandle)Tcl_Alloc(sizeof(struct Tcl_LoadHandle_));
    handlePtr->clientData = (ClientData) hInstance;
    handlePtr->clientData = (void *)hInstance;
    handlePtr->findSymbolProcPtr = &FindSymbol;
    handlePtr->unloadFileProcPtr = &UnloadFile;
    *loadHandle = handlePtr;
    *unloadProcPtr = &UnloadFile;
    return TCL_OK;
}

213
214
215
216
217
218
219
220

221
222
223
224
225
226
227

228
229
230
231
232
233
234
216
217
218
219
220
221
222

223
224
225
226
227
228
229

230
231
232
233
234
235
236
237







-
+






-
+







    proc = (void *)GetProcAddress(hInstance, symbol);
    if (proc == NULL) {
	Tcl_DString ds;
	const char *sym2;

	Tcl_DStringInit(&ds);
	TclDStringAppendLiteral(&ds, "_");
	sym2 = Tcl_DStringAppend(&ds, symbol, -1);
	sym2 = Tcl_DStringAppend(&ds, symbol, TCL_INDEX_NONE);
	proc = (void *)GetProcAddress(hInstance, sym2);
	Tcl_DStringFree(&ds);
    }
    if (proc == NULL && interp != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"cannot find symbol \"%s\"", symbol));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol, NULL);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol, (char *)NULL);
    }
    return proc;
}

/*
 *----------------------------------------------------------------------
 *
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
257
258
259
260
261
262
263




























264
265
266
267
268
269
270







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







				 * that represents the loaded file. */
{
    HINSTANCE hInstance = (HINSTANCE) loadHandle->clientData;

    FreeLibrary(hInstance);
    Tcl_Free(loadHandle);
}

/*
 *----------------------------------------------------------------------
 *
 * TclGuessPackageName --
 *
 *	If the "load" command is invoked without providing a package name,
 *	this function is invoked to try to figure it out.
 *
 * Results:
 *	Always returns 0 to indicate that we couldn't figure out a package
 *	name; generic code will then try to guess the package from the file
 *	name. A return value of 1 would have meant that we figured out the
 *	package name and put it in bufPtr.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclGuessPackageName(
    TCL_UNUSED(const char *),
    TCL_UNUSED(Tcl_DString *))
{
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpTempFileNameForLibrary --
 *
 *	Constructs a temporary file name for loading a shared object (DLL).
403
404
405
406
407
408
409
410

411
412
413
414
415
416
417
378
379
380
381
382
383
384

385
386
387
388
389
390
391
392







-
+







	lastError = GetLastError();
	if (lastError != ERROR_ALREADY_EXISTS) {
	    break;
	}
	id *= 16777619;
    }

    TclWinConvertError(lastError);
    Tcl_WinConvertError(lastError);
    return TCL_ERROR;

    /*
     * Store our computed value in the global.
     */

  copyToGlobalBuffer:

Changes to win/tclWinNotify.c.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24







-
+








-
+







/*
 * tclWinNotify.c --
 *
 *	This file contains Windows-specific procedures for the notifier, which
 *	is the lowest-level part of the Tcl event loop. This file works
 *	together with ../generic/tclNotify.c.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

/*
 * The follwing static indicates whether this module has been initialized.
 * The following static indicates whether this module has been initialized.
 */

#define INTERVAL_TIMER	1	/* Handle of interval timer. */

#define WM_WAKEUP	WM_USER	/* Message that is send by
				 * Tcl_AlertNotifier. */
/*
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
366
367
368
369
370
371






372
373
374
375




























376
377
378
379
380
381
382
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
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384







-
-
+
+

















-
-
+
+

-
-
-
-
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+

-
+

-
-
-
-
+
+
+
+

-
+
-





-
+














-
-
+
+

-
-
-
-
-
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+

-
-
+
+

-
-
-
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-



-
+



















-
-
+
+

-
-
-
-
-
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-



-
+















-
+


-
-
-
-
-
-
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
-



-
+














-
+



-
-
-
-
-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







static int initialized = 0;
static CRITICAL_SECTION notifierMutex;

/*
 * Static routines defined in this file.
 */

static LRESULT CALLBACK		NotifierProc(HWND hwnd, UINT message,
				    WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK	NotifierProc(HWND hwnd, UINT message,
			    WPARAM wParam, LPARAM lParam);

/*
 *----------------------------------------------------------------------
 *
 * Tcl_InitNotifier --
 *
 *	Initializes the platform specific notifier state.
 *
 * Results:
 *	Returns a handle to the notifier state for this thread..
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

ClientData
Tcl_InitNotifier(void)
void *
TclpInitNotifier(void)
{
    if (tclNotifierHooks.initNotifierProc) {
	return tclNotifierHooks.initNotifierProc();
    } else {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	TclpGlobalLock();
	if (!initialized) {
	    initialized = 1;
	    InitializeCriticalSection(&notifierMutex);
	}
	TclpGlobalUnlock();
    TclpGlobalLock();
    if (!initialized) {
	initialized = 1;
	InitializeCriticalSection(&notifierMutex);
    }
    TclpGlobalUnlock();

	/*
	 * Register Notifier window class if this is the first thread to use
	 * this module.
	 */
    /*
     * Register Notifier window class if this is the first thread to use this
     * module.
     */

	EnterCriticalSection(&notifierMutex);
	if (notifierCount == 0) {
	    WNDCLASSW clazz;
    EnterCriticalSection(&notifierMutex);
    if (notifierCount == 0) {
	WNDCLASSW clazz;

	    clazz.style = 0;
	    clazz.cbClsExtra = 0;
	    clazz.cbWndExtra = 0;
	    clazz.hInstance = (HINSTANCE)TclWinGetTclInstance();
	    clazz.hbrBackground = NULL;
	    clazz.lpszMenuName = NULL;
	    clazz.lpszClassName = className;
	    clazz.lpfnWndProc = NotifierProc;
	    clazz.hIcon = NULL;
	    clazz.hCursor = NULL;
	clazz.style = 0;
	clazz.cbClsExtra = 0;
	clazz.cbWndExtra = 0;
	clazz.hInstance = (HINSTANCE) TclWinGetTclInstance();
	clazz.hbrBackground = NULL;
	clazz.lpszMenuName = NULL;
	clazz.lpszClassName = className;
	clazz.lpfnWndProc = NotifierProc;
	clazz.hIcon = NULL;
	clazz.hCursor = NULL;

	    if (!RegisterClassW(&clazz)) {
		Tcl_Panic("Unable to register TclNotifier window class");
	    }
	}
	notifierCount++;
	LeaveCriticalSection(&notifierMutex);
	if (!RegisterClassW(&clazz)) {
	    Tcl_Panic("Tcl_InitNotifier: %s",
		    "unable to register TclNotifier window class");
	}
    }
    notifierCount++;
    LeaveCriticalSection(&notifierMutex);

	tsdPtr->pending = 0;
	tsdPtr->timerActive = 0;
    tsdPtr->pending = 0;
    tsdPtr->timerActive = 0;

	InitializeCriticalSection(&tsdPtr->crit);
    InitializeCriticalSection(&tsdPtr->crit);

	tsdPtr->hwnd = NULL;
	tsdPtr->thread = GetCurrentThreadId();
	tsdPtr->event = CreateEventW(NULL, TRUE /* manual */,
		FALSE /* !signaled */, NULL);
    tsdPtr->hwnd = NULL;
    tsdPtr->thread = GetCurrentThreadId();
    tsdPtr->event = CreateEventW(NULL, TRUE /* manual */,
	    FALSE /* !signaled */, NULL);

	return tsdPtr;
    return tsdPtr;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FinalizeNotifier --
 * TclpFinalizeNotifier --
 *
 *	This function is called to cleanup the notifier state before a thread
 *	is terminated.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	May dispose of the notifier window and class.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_FinalizeNotifier(
    ClientData clientData)	/* Pointer to notifier data. */
TclpFinalizeNotifier(
    void *clientData)	/* Pointer to notifier data. */
{
    if (tclNotifierHooks.finalizeNotifierProc) {
	tclNotifierHooks.finalizeNotifierProc(clientData);
	return;
    } else {
	ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;

	/*
	 * Only finalize the notifier if a notifier was installed in the
	 * current thread; there is a route in which this is not guaranteed to
	 * be true (when tclWin32Dll.c:DllMain() is called with the flag
	 * DLL_PROCESS_DETACH by the OS, which could be doing so from a thread
	 * that's never previously been involved with Tcl, e.g. the task
	 * manager) so this check is important.
	 *
	 * Fixes Bug #217982 reported by Hugh Vu and Gene Leache.
	 */
    /*
     * Only finalize the notifier if a notifier was installed in the current
     * thread; there is a route in which this is not guaranteed to be true
     * (when tclWin32Dll.c:DllMain() is called with the flag
     * DLL_PROCESS_DETACH by the OS, which could be doing so from a thread
     * that's never previously been involved with Tcl, e.g. the task manager)
     * so this check is important.
     *
     * Fixes Bug #217982 reported by Hugh Vu and Gene Leache.
     */

	if (tsdPtr == NULL) {
	    return;
	}
    if (tsdPtr == NULL) {
	return;
    }

	DeleteCriticalSection(&tsdPtr->crit);
	CloseHandle(tsdPtr->event);
    DeleteCriticalSection(&tsdPtr->crit);
    CloseHandle(tsdPtr->event);

	/*
	 * Clean up the timer and messaging window for this thread.
	 */
    /*
     * Clean up the timer and messaging window for this thread.
     */

	if (tsdPtr->hwnd) {
	    KillTimer(tsdPtr->hwnd, INTERVAL_TIMER);
	    DestroyWindow(tsdPtr->hwnd);
	}
    if (tsdPtr->hwnd) {
	KillTimer(tsdPtr->hwnd, INTERVAL_TIMER);
	DestroyWindow(tsdPtr->hwnd);
    }

	/*
	 * If this is the last thread to use the notifier, unregister the
	 * notifier window class.
	 */
    /*
     * If this is the last thread to use the notifier, unregister the notifier
     * window class.
     */

	EnterCriticalSection(&notifierMutex);
	if (notifierCount) {
	    notifierCount--;
	    if (notifierCount == 0) {
		UnregisterClassW(className, (HINSTANCE)TclWinGetTclInstance());
	    }
	}
	LeaveCriticalSection(&notifierMutex);
    }
}
    EnterCriticalSection(&notifierMutex);
    if (notifierCount) {
	notifierCount--;
	if (notifierCount == 0) {
	    UnregisterClassW(className, (HINSTANCE) TclWinGetTclInstance());
	}
    }
    LeaveCriticalSection(&notifierMutex);
}


/*
 *----------------------------------------------------------------------
 *
 * Tcl_AlertNotifier --
 * TclpAlertNotifier --
 *
 *	Wake up the specified notifier from any thread. This routine is called
 *	by the platform independent notifier code whenever the Tcl_ThreadAlert
 *	routine is called. This routine is guaranteed not to be called on a
 *	given notifier after Tcl_FinalizeNotifier is called for that notifier.
 *	This routine is typically called from a thread other than the
 *	notifier's thread.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Sends a message to the messaging window for the notifier if there
 *	isn't already one pending.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_AlertNotifier(
    ClientData clientData)	/* Pointer to thread data. */
TclpAlertNotifier(
    void *clientData)	/* Pointer to thread data. */
{
    if (tclNotifierHooks.alertNotifierProc) {
	tclNotifierHooks.alertNotifierProc(clientData);
	return;
    } else {
	ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;

	/*
	 * Note that we do not need to lock around access to the hwnd because
	 * the race condition has no effect since any race condition implies
	 * that the notifier thread is already awake.
	 */
    /*
     * Note that we do not need to lock around access to the hwnd because the
     * race condition has no effect since any race condition implies that the
     * notifier thread is already awake.
     */

	if (tsdPtr->hwnd) {
	    /*
	     * We do need to lock around access to the pending flag.
	     */
    if (tsdPtr->hwnd) {
	/*
	 * We do need to lock around access to the pending flag.
	 */

	    EnterCriticalSection(&tsdPtr->crit);
	    if (!tsdPtr->pending) {
		PostMessageW(tsdPtr->hwnd, WM_WAKEUP, 0, 0);
	    }
	    tsdPtr->pending = 1;
	    LeaveCriticalSection(&tsdPtr->crit);
	} else {
	    SetEvent(tsdPtr->event);
	}
    }
}
	EnterCriticalSection(&tsdPtr->crit);
	if (!tsdPtr->pending) {
	    PostMessageW(tsdPtr->hwnd, WM_WAKEUP, 0, 0);
	}
	tsdPtr->pending = 1;
	LeaveCriticalSection(&tsdPtr->crit);
    } else {
	SetEvent(tsdPtr->event);
    }
}


/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetTimer --
 * TclpSetTimer --
 *
 *	This procedure sets the current notifier timer value. The notifier
 *	will ensure that Tcl_ServiceAll() is called after the specified
 *	interval, even if no events have occurred.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Replaces any previous timer.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetTimer(
TclpSetTimer(
    const Tcl_Time *timePtr)		/* Maximum block time, or NULL. */
{
    if (tclNotifierHooks.setTimerProc) {
	tclNotifierHooks.setTimerProc(timePtr);
	return;
    } else {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
	UINT timeout;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    UINT timeout;

	/*
	 * We only need to set up an interval timer if we're being called from
	 * an external event loop. If we don't have a window handle then we
	 * just return immediately and let Tcl_WaitForEvent handle timeouts.
	 */
    /*
     * We only need to set up an interval timer if we're being called from an
     * external event loop. If we don't have a window handle then we just
     * return immediately and let Tcl_WaitForEvent handle timeouts.
     */

	if (!tsdPtr->hwnd) {
	    return;
	}
    if (!tsdPtr->hwnd) {
	return;
    }

	if (!timePtr) {
	    timeout = 0;
	} else {
	    /*
	     * Make sure we pass a non-zero value into the timeout argument.
	     * Windows seems to get confused by zero length timers.
	     */
    if (!timePtr) {
	timeout = 0;
    } else {
	/*
	 * Make sure we pass a non-zero value into the timeout argument.
	 * Windows seems to get confused by zero length timers.
	 */

	    timeout = timePtr->sec * 1000 + timePtr->usec / 1000;
	    if (timeout == 0) {
		timeout = 1;
	    }
	}
	if (timeout != 0) {
	    tsdPtr->timerActive = 1;
	    SetTimer(tsdPtr->hwnd, INTERVAL_TIMER,
	timeout = (UINT)timePtr->sec * 1000 + (unsigned long)timePtr->usec / 1000;
	if (timeout == 0) {
	    timeout = 1;
	}
    }

    if (timeout != 0) {
	tsdPtr->timerActive = 1;
	SetTimer(tsdPtr->hwnd, INTERVAL_TIMER, timeout, NULL);
		    timeout, NULL);
	} else {
	    tsdPtr->timerActive = 0;
	    KillTimer(tsdPtr->hwnd, INTERVAL_TIMER);
	}
    }
}
    } else {
	tsdPtr->timerActive = 0;
	KillTimer(tsdPtr->hwnd, INTERVAL_TIMER);
    }
}


/*
 *----------------------------------------------------------------------
 *
 * Tcl_ServiceModeHook --
 * TclpServiceModeHook --
 *
 *	This function is invoked whenever the service mode changes.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	If this is the first time the notifier is set into TCL_SERVICE_ALL,
 *	then the communication window is created.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_ServiceModeHook(
TclpServiceModeHook(
    int mode)			/* Either TCL_SERVICE_ALL, or
				 * TCL_SERVICE_NONE. */
{
    if (tclNotifierHooks.serviceModeHookProc) {
	tclNotifierHooks.serviceModeHookProc(mode);
	return;
    } else {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	/*
	 * If this is the first time that the notifier has been used from a
	 * modal loop, then create a communication window. Note that after this
	 * point, the application needs to service events in a timely fashion
	 * or Windows will hang waiting for the window to respond to
	 * synchronous system messages. At some point, we may want to consider
	 * destroying the window if we leave the modal loop, but for now we'll
    /*
     * If this is the first time that the notifier has been used from a modal
     * loop, then create a communication window. Note that after this point,
     * the application needs to service events in a timely fashion or Windows
     * will hang waiting for the window to respond to synchronous system
     * messages. At some point, we may want to consider destroying the window
     * if we leave the modal loop, but for now we'll leave it around.
	 * leave it around.
	 */
     */

	if (mode == TCL_SERVICE_ALL && !tsdPtr->hwnd) {
	    tsdPtr->hwnd = CreateWindowW(className, className,
		    WS_TILED, 0, 0, 0, 0, NULL, NULL, (HINSTANCE)TclWinGetTclInstance(),
		    NULL);
    if (mode == TCL_SERVICE_ALL && !tsdPtr->hwnd) {
	tsdPtr->hwnd = CreateWindowW(className, className, WS_TILED,
		0, 0, 0, 0, NULL, NULL, (HINSTANCE) TclWinGetTclInstance(),
		NULL);

	    /*
	     * Send an initial message to the window to ensure that we wake up
	     * the notifier once we get into the modal loop. This will force
	     * the notifier to recompute the timeout value and schedule a timer
	     * if one is needed.
	     */
	/*
	 * Send an initial message to the window to ensure that we wake up the
	 * notifier once we get into the modal loop. This will force the
	 * notifier to recompute the timeout value and schedule a timer if one
	 * is needed.
	 */

	    Tcl_AlertNotifier(tsdPtr);
	}
    }
	Tcl_AlertNotifier(tsdPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclAsyncNotifier --
 *
 *	This procedure is a no-op on Windows.
 *
 * Result:
 *	Always true.
 *
 * Side effetcs:
 *	None.
 *----------------------------------------------------------------------
 */

int
TclAsyncNotifier(
    TCL_UNUSED(int),		/* Signal number. */
    TCL_UNUSED(Tcl_ThreadId),	/* Target thread. */
    TCL_UNUSED(void *),	/* Notifier data. */
    TCL_UNUSED(int *),		/* Flag to mark. */
    TCL_UNUSED(int))			/* Value of mark. */
{
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * NotifierProc --
 *
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
467
468
469



470
471
472
473
474




475
476
477
478
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
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
467
468







469
470
471
472
473



474
475
476
477





478
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
558

559
560
561
562
563
564
565







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
















-
+


-
-
-
-
-
-
-
+
+
+
+

-
-
-
+
+
+

-
-
-
-
-
+
+
+
+
+

-
+

-
-
+
+

-
-
-
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+
-







    Tcl_ServiceAll();
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpNotifierData --
 *
 *	This function returns a void pointer to be associated
 *	with a Tcl_AsyncHandler.
 *
 * Results:
 *	On Windows, returns always NULL.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void *
TclpNotifierData(void)
{
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_WaitForEvent --
 * TclpWaitForEvent --
 *
 *	This function is called by Tcl_DoOneEvent to wait for new events on
 *	the message queue. If the block time is 0, then Tcl_WaitForEvent just
 *	polls the event queue without blocking.
 *
 * Results:
 *	Returns -1 if a WM_QUIT message is detected, returns 1 if a message
 *	was dispatched, otherwise returns 0.
 *
 * Side effects:
 *	Dispatches a message to a window procedure, which could do anything.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_WaitForEvent(
TclpWaitForEvent(
    const Tcl_Time *timePtr)		/* Maximum block time, or NULL. */
{
    if (tclNotifierHooks.waitForEventProc) {
	return tclNotifierHooks.waitForEventProc(timePtr);
    } else {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
	MSG msg;
	DWORD timeout, result;
	int status;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    MSG msg;
    DWORD timeout, result;
    int status;

	/*
	 * Compute the timeout in milliseconds.
	 */
    /*
     * Compute the timeout in milliseconds.
     */

	if (timePtr) {
	    /*
	     * TIP #233 (Virtualized Time). Convert virtual domain delay to
	     * real-time.
	     */
    if (timePtr) {
	/*
	 * TIP #233 (Virtualized Time). Convert virtual domain delay to
	 * real-time.
	 */

	    Tcl_Time myTime;
	Tcl_Time myTime;

	    myTime.sec  = timePtr->sec;
	    myTime.usec = timePtr->usec;
	myTime.sec  = timePtr->sec;
	myTime.usec = timePtr->usec;

	    if (myTime.sec != 0 || myTime.usec != 0) {
		tclScaleTimeProcPtr(&myTime, tclTimeClientData);
	    }
	if (myTime.sec != 0 || myTime.usec != 0) {
	    TclScaleTime(&myTime);
	}

	    timeout = myTime.sec * 1000 + myTime.usec / 1000;
	} else {
	    timeout = INFINITE;
	}
	timeout = (DWORD)myTime.sec * 1000 + (unsigned long)myTime.usec / 1000;
    } else {
	timeout = INFINITE;
    }

	/*
	 * Check to see if there are any messages in the queue before waiting
	 * because MsgWaitForMultipleObjects will not wake up if there are
	 * events currently sitting in the queue.
	 */
    /*
     * Check to see if there are any messages in the queue before waiting
     * because MsgWaitForMultipleObjects will not wake up if there are events
     * currently sitting in the queue.
     */

	if (!PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE)) {
	    /*
	     * Wait for something to happen (a signal from another thread, a
	     * message, or timeout) or loop servicing asynchronous procedure
	     * calls queued to this thread.
	     */
    if (!PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE)) {
	/*
	 * Wait for something to happen (a signal from another thread, a
	 * message, or timeout) or loop servicing asynchronous procedure calls
	 * queued to this thread.
	 */

	again:
	do {
	    result = MsgWaitForMultipleObjectsEx(1, &tsdPtr->event, timeout,
		    QS_ALLINPUT, MWMO_ALERTABLE);
	    if (result == WAIT_IO_COMPLETION) {
		goto again;
	    } else if (result == WAIT_FAILED) {
		status = -1;
		goto end;
	    }
	}
	} while (result == WAIT_IO_COMPLETION);

	if (result == WAIT_FAILED) {
	    status = -1;
	    goto end;
	}
    }

	/*
	 * Check to see if there are any messages to process.
	 */
    /*
     * Check to see if there are any messages to process.
     */

	if (PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE)) {
	    /*
	     * Retrieve and dispatch the first message.
	     */
    if (PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE)) {
	/*
	 * Retrieve and dispatch the first message.
	 */

	    result = GetMessageW(&msg, NULL, 0, 0);
	    if (result == 0) {
		/*
		 * We received a request to exit this thread (WM_QUIT), so
		 * propagate the quit message and start unwinding.
		 */
	result = GetMessageW(&msg, NULL, 0, 0);
	if (result == 0) {
	    /*
	     * We received a request to exit this thread (WM_QUIT), so
	     * propagate the quit message and start unwinding.
	     */

		PostQuitMessage((int) msg.wParam);
		status = -1;
	    } else if (result == (DWORD)-1) {
		/*
		 * We got an error from the system. I have no idea why this
		 * would happen, so we'll just unwind.
		 */
	    PostQuitMessage((int) msg.wParam);
	    status = -1;
	} else if (result == (DWORD) -1) {
	    /*
	     * We got an error from the system. I have no idea why this would
	     * happen, so we'll just unwind.
	     */

		status = -1;
	    } else {
		TranslateMessage(&msg);
		DispatchMessageW(&msg);
		status = 1;
	    }
	} else {
	    status = 0;
	}
	    status = -1;
	} else {
	    TranslateMessage(&msg);
	    DispatchMessageW(&msg);
	    status = 1;
	}
    } else {
	status = 0;
    }

      end:
	ResetEvent(tsdPtr->event);
	return status;
  end:
    ResetEvent(tsdPtr->event);
    return status;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Sleep --
 *
584
585
586
587
588
589
590
591
592


593
594
595
596
597
598
599
600
601
602
603
604
605
606
607


608
609
610
611
612
613
614
615
616
617
605
606
607
608
609
610
611


612
613
614
615
616
617
618
619
620
621
622
623
624
625
626


627
628
629
630
631
632
633
634
635
636
637
638







-
-
+
+













-
-
+
+










	desired.usec -= 1000000;
    }

    /*
     * TIP #233: Scale delay from virtual to real-time.
     */

    tclScaleTimeProcPtr(&vdelay, tclTimeClientData);
    sleepTime = vdelay.sec * 1000 + vdelay.usec / 1000;
    TclScaleTime(&vdelay);
    sleepTime = (DWORD)vdelay.sec * 1000 + (unsigned long)vdelay.usec / 1000;

    for (;;) {
	SleepEx(sleepTime, TRUE);
	Tcl_GetTime(&now);
	if (now.sec > desired.sec) {
	    break;
	} else if ((now.sec == desired.sec) && (now.usec >= desired.usec)) {
	    break;
	}

	vdelay.sec  = desired.sec  - now.sec;
	vdelay.usec = desired.usec - now.usec;

	tclScaleTimeProcPtr(&vdelay, tclTimeClientData);
	sleepTime = vdelay.sec * 1000 + vdelay.usec / 1000;
	TclScaleTime(&vdelay);
	sleepTime = (DWORD)vdelay.sec * 1000 + (unsigned long)vdelay.usec / 1000;
    }
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to win/tclWinPanic.c.

1

2
3
4
5
6

7
8
9
10
11
12
13

1
2
3
4
5

6
7
8
9
10
11
12
13
-
+




-
+







 /*
/*
 * tclWinPanic.c --
 *
 *	Contains the Windows-specific command-line panic proc.
 *
 * Copyright (c) 2013 by Jan Nijtmans.
 * Copyright © 2013 Jan Nijtmans.
 * All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38







-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

TCL_NORETURN1 void
TCL_NORETURN void
Tcl_ConsolePanic(
    const char *format, ...)
{
#define TCL_MAX_WARN_LEN 26000
    va_list argList;
    WCHAR msgString[TCL_MAX_WARN_LEN];
    char buf[TCL_MAX_WARN_LEN * 3];
52
53
54
55
56
57
58
59

60
61
62

63
64
65
66
67
68
69
52
53
54
55
56
57
58

59
60
61

62
63
64
65
66
67
68
69







-
+


-
+







    if (msgString[TCL_MAX_WARN_LEN-1] != '\0') {
	memcpy(msgString + (TCL_MAX_WARN_LEN - 5), L" ...", 5 * sizeof(WCHAR));
    }

    if (IsDebuggerPresent()) {
	OutputDebugStringW(msgString);
    } else if (_isatty(2)) {
	WriteConsoleW(handle, msgString, wcslen(msgString), &dummy, 0);
	WriteConsoleW(handle, msgString, (DWORD)wcslen(msgString), &dummy, 0);
    } else {
	buf[0] = '\xEF'; buf[1] = '\xBB'; buf[2] = '\xBF'; /* UTF-8 bom */
	WriteFile(handle, buf, strlen(buf), &dummy, 0);
	WriteFile(handle, buf, (DWORD)strlen(buf), &dummy, 0);
	WriteFile(handle, "\n", 1, &dummy, 0);
	FlushFileBuffers(handle);
    }
#   if defined(__GNUC__)
	__builtin_trap();
#   elif defined(_WIN64)
	__debugbreak();

Changes to win/tclWinPipe.c.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tclWinPipe.c --
 *
 *	This file implements the Windows-specific exec pipeline functions, the
 *	"pipe" channel driver, and the "pid" Tcl command.
 *
 * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
 * Copyright © 1996-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclWinInt.h"

57
58
59
60
61
62
63
64

65
66
67
68
69
70
71
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71







-
+








/*
 * This list is used to map from pids to process handles.
 */

typedef struct ProcInfo {
    HANDLE hProcess;
    size_t dwProcessId;
    int dwProcessId;
    struct ProcInfo *nextPtr;
} ProcInfo;

static ProcInfo *procList;

/*
 * Bit masks used in the flags field of the PipeInfo structure below.
100
101
102
103
104
105
106
107

108
109
110
111
112
113
114
100
101
102
103
104
105
106

107
108
109
110
111
112
113
114







-
+







    int watchMask;		/* OR'ed combination of TCL_READABLE,
				 * TCL_WRITABLE, or TCL_EXCEPTION: indicates
				 * which events should be reported. */
    int flags;			/* State flags, see above for a list. */
    TclFile readFile;		/* Output from pipe. */
    TclFile writeFile;		/* Input from pipe. */
    TclFile errorFile;		/* Error output from pipe. */
    int numPids;		/* Number of processes attached to pipe. */
    size_t numPids;		/* Number of processes attached to pipe. */
    Tcl_Pid *pidPtr;		/* Pids of attached processes. */
    Tcl_ThreadId threadId;	/* Thread to which events should be reported.
				 * This value is used by the reader/writer
				 * threads. */
    TclPipeThreadInfo *writeTI;	/* Thread info of writer and reader, this */
    TclPipeThreadInfo *readTI;	/* structure owned by corresponding thread. */
    HANDLE writeThread;		/* Handle to writer thread. */
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
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







-
+


-
-
-
+
+
+


-
-
+
+

-
+

-
+


-
-
+
+



-
+








-
-
-
-
-
-
+
+
+
+
+
+


-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+








/*
 * Declarations for functions used only in this file.
 */

static int		ApplicationType(Tcl_Interp *interp,
			    const char *fileName, char *fullName);
static void		BuildCommandLine(const char *executable, int argc,
static void		BuildCommandLine(const char *executable, size_t argc,
			    const char **argv, Tcl_DString *linePtr);
static BOOL		HasConsole(void);
static int		PipeBlockModeProc(ClientData instanceData, int mode);
static void		PipeCheckProc(ClientData clientData, int flags);
static int		PipeClose2Proc(ClientData instanceData,
static int		PipeBlockModeProc(void *instanceData, int mode);
static void		PipeCheckProc(void *clientData, int flags);
static int		PipeClose2Proc(void *instanceData,
			    Tcl_Interp *interp, int flags);
static int		PipeEventProc(Tcl_Event *evPtr, int flags);
static int		PipeGetHandleProc(ClientData instanceData,
			    int direction, ClientData *handlePtr);
static int		PipeGetHandleProc(void *instanceData,
			    int direction, void **handlePtr);
static void		PipeInit(void);
static int		PipeInputProc(ClientData instanceData, char *buf,
static int		PipeInputProc(void *instanceData, char *buf,
			    int toRead, int *errorCode);
static int		PipeOutputProc(ClientData instanceData,
static int		PipeOutputProc(void *instanceData,
			    const char *buf, int toWrite, int *errorCode);
static DWORD WINAPI	PipeReaderThread(LPVOID arg);
static void		PipeSetupProc(ClientData clientData, int flags);
static void		PipeWatchProc(ClientData instanceData, int mask);
static void		PipeSetupProc(void *clientData, int flags);
static void		PipeWatchProc(void *instanceData, int mask);
static DWORD WINAPI	PipeWriterThread(LPVOID arg);
static int		TempFileName(WCHAR name[MAX_PATH]);
static int		WaitForRead(PipeInfo *infoPtr, int blocking);
static void		PipeThreadActionProc(ClientData instanceData,
static void		PipeThreadActionProc(void *instanceData,
			    int action);

/*
 * This structure describes the channel type structure for command pipe based
 * I/O.
 */

static const Tcl_ChannelType pipeChannelType = {
    "pipe",			/* Type name. */
    TCL_CHANNEL_VERSION_5,	/* v5 channel */
    NULL,		/* Close proc. */
    PipeInputProc,		/* Input proc. */
    PipeOutputProc,		/* Output proc. */
    NULL,			/* Seek proc. */
    "pipe",
    TCL_CHANNEL_VERSION_5,
    NULL,			/* Deprecated. */
    PipeInputProc,
    PipeOutputProc,
    NULL,			/* Deprecated. */
    NULL,			/* Set option proc. */
    NULL,			/* Get option proc. */
    PipeWatchProc,		/* Set up notifier to watch the channel. */
    PipeGetHandleProc,		/* Get an OS handle from channel. */
    PipeClose2Proc,		/* close2proc */
    PipeBlockModeProc,		/* Set blocking or non-blocking mode.*/
    NULL,			/* flush proc. */
    NULL,			/* handler proc. */
    NULL,			/* wide seek proc */
    PipeThreadActionProc,	/* thread action proc */
    NULL			/* truncate */
    PipeWatchProc,
    PipeGetHandleProc,
    PipeClose2Proc,
    PipeBlockModeProc,
    NULL,			/* Flush proc. */
    NULL,			/* Bubbled event handler proc. */
    NULL,			/* Seek proc. */
    PipeThreadActionProc,
    NULL			/* Truncate proc. */
};

/*
 *----------------------------------------------------------------------
 *
 * PipeInit --
 *
306
307
308
309
310
311
312
313

314
315
316
317
318
319
320
306
307
308
309
310
311
312

313
314
315
316
317
318
319
320







-
+







 *	Adjusts the block time if needed.
 *
 *----------------------------------------------------------------------
 */

void
PipeSetupProc(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */
{
    PipeInfo *infoPtr;
    Tcl_Time blockTime = { 0, 0 };
    int block = 1;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

359
360
361
362
363
364
365
366

367
368
369
370
371
372
373
359
360
361
362
363
364
365

366
367
368
369
370
371
372
373







-
+







 *	May queue an event.
 *
 *----------------------------------------------------------------------
 */

static void
PipeCheckProc(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */
{
    PipeInfo *infoPtr;
    PipeEvent *evPtr;
    int needEvent;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

496
497
498
499
500
501
502
503

504
505
506
507
508
509
510
496
497
498
499
500
501
502

503
504
505
506
507
508
509
510







-
+







TclpMakeFile(
    Tcl_Channel channel,	/* Channel to get file from. */
    int direction)		/* Either TCL_READABLE or TCL_WRITABLE. */
{
    HANDLE handle;

    if (Tcl_GetChannelHandle(channel, direction,
	    (ClientData *) &handle) == TCL_OK) {
	    (void **) &handle) == TCL_OK) {
	return TclWinMakeFile(handle);
    } else {
	return (TclFile) NULL;
    }
}

/*
534
535
536
537
538
539
540
541

542
543
544
545
546
547
548
549
550
551
552

553
554
555
556
557
558
559
534
535
536
537
538
539
540

541
542
543
544
545
546
547
548
549
550
551

552
553
554
555
556
557
558
559







-
+










-
+







    Tcl_DString ds;
    const WCHAR *nativePath;

    /*
     * Map the access bits to the NT access mode.
     */

    switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) {
    switch (mode & O_ACCMODE) {
    case O_RDONLY:
	accessMode = GENERIC_READ;
	break;
    case O_WRONLY:
	accessMode = GENERIC_WRITE;
	break;
    case O_RDWR:
	accessMode = (GENERIC_READ | GENERIC_WRITE);
	break;
    default:
	TclWinConvertError(ERROR_INVALID_FUNCTION);
	Tcl_WinConvertError(ERROR_INVALID_FUNCTION);
	return NULL;
    }

    /*
     * Map the creation flags to the NT create mode.
     */

574
575
576
577
578
579
580
581

582
583
584
585
586
587
588
574
575
576
577
578
579
580

581
582
583
584
585
586
587
588







-
+







	break;
    default:
	createMode = OPEN_EXISTING;
	break;
    }

    Tcl_DStringInit(&ds);
    nativePath = Tcl_UtfToWCharDString(path, -1, &ds);
    nativePath = Tcl_UtfToWCharDString(path, TCL_INDEX_NONE, &ds);

    /*
     * If the file is not being created, use the existing file attributes.
     */

    flags = 0;
    if (!(mode & O_CREAT)) {
609
610
611
612
613
614
615
616

617
618
619
620
621
622
623
609
610
611
612
613
614
615

616
617
618
619
620
621
622
623







-
+







    if (handle == INVALID_HANDLE_VALUE) {
	DWORD err;

	err = GetLastError();
	if ((err & 0xFFFFL) == ERROR_OPEN_FAILED) {
	    err = (mode & O_CREAT) ? ERROR_FILE_EXISTS : ERROR_FILE_NOT_FOUND;
	}
	TclWinConvertError(err);
	Tcl_WinConvertError(err);
	return NULL;
    }

    /*
     * Seek to the end of file if we are writing.
     */

647
648
649
650
651
652
653
654

655
656
657
658
659
660
661
647
648
649
650
651
652
653

654
655
656
657
658
659
660
661







-
+







 */

TclFile
TclpCreateTempFile(
    const char *contents)	/* String to write into temp file, or NULL. */
{
    WCHAR name[MAX_PATH];
    const char *native;
    const char *native = NULL;
    Tcl_DString dstring;
    HANDLE handle;

    if (TempFileName(name) == 0) {
	return NULL;
    }

675
676
677
678
679
680
681
682




683
684
685
686
687
688
689
675
676
677
678
679
680
681

682
683
684
685
686
687
688
689
690
691
692







-
+
+
+
+







	const char *p;
	int toCopy;

	/*
	 * Convert the contents from UTF to native encoding
	 */

	native = Tcl_UtfToExternalDString(NULL, contents, -1, &dstring);
	if (Tcl_UtfToExternalDStringEx(NULL, NULL, contents, TCL_INDEX_NONE, 0, &dstring, NULL) != TCL_OK) {
	   goto error;
	}
	native = Tcl_DStringValue(&dstring);

	toCopy = Tcl_DStringLength(&dstring);
	for (p = native; toCopy > 0; p++, toCopy--) {
	    if (*p == '\n') {
		length = p - native;
		if (length > 0) {
		    if (!WriteFile(handle, native, length, &result, NULL)) {
715
716
717
718
719
720
721

722


723
724
725
726
727
728
729
718
719
720
721
722
723
724
725

726
727
728
729
730
731
732
733
734







+
-
+
+







     * Free the native representation of the contents if necessary.
     */

    if (contents != NULL) {
	Tcl_DStringFree(&dstring);
    }

    if (native != NULL) {
    TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
    }
    CloseHandle(handle);
    DeleteFileW(name);
    return NULL;
}

/*
 *----------------------------------------------------------------------
780
781
782
783
784
785
786
787

788
789
790
791
792
793
794
785
786
787
788
789
790
791

792
793
794
795
796
797
798
799







-
+








    if (CreatePipe(&readHandle, &writeHandle, NULL, 0) != 0) {
	*readPipe = TclWinMakeFile(readHandle);
	*writePipe = TclWinMakeFile(writeHandle);
	return 1;
    }

    TclWinConvertError(GetLastError());
    Tcl_WinConvertError(GetLastError());
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpCloseFile --
821
822
823
824
825
826
827
828

829
830
831
832
833
834
835
826
827
828
829
830
831
832

833
834
835
836
837
838
839
840







-
+








	if (!TclInThreadExit()
		|| ((GetStdHandle(STD_INPUT_HANDLE) != filePtr->handle)
		    && (GetStdHandle(STD_OUTPUT_HANDLE) != filePtr->handle)
		    && (GetStdHandle(STD_ERROR_HANDLE) != filePtr->handle))) {
	    if (filePtr->handle != NULL &&
		    CloseHandle(filePtr->handle) == FALSE) {
		TclWinConvertError(GetLastError());
		Tcl_WinConvertError(GetLastError());
		Tcl_Free(filePtr);
		return -1;
	    }
	}
	break;

    default:
855
856
857
858
859
860
861
862

863
864
865
866
867
868
869
870
871
872

873
874
875
876
877
878

879
880
881
882
883
884
885
860
861
862
863
864
865
866

867
868
869
870
871
872
873
874
875
876

877
878
879
880
881
882

883
884
885
886
887
888
889
890







-
+









-
+





-
+







 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------------------
 */

size_t
Tcl_Size
TclpGetPid(
    Tcl_Pid pid)		/* The HANDLE of the child process. */
{
    ProcInfo *infoPtr;

    PipeInit();

    Tcl_MutexLock(&pipeMutex);
    for (infoPtr = procList; infoPtr != NULL; infoPtr = infoPtr->nextPtr) {
	if (infoPtr->dwProcessId == (size_t) pid) {
	if (infoPtr->dwProcessId == (Tcl_Size)pid) {
	    Tcl_MutexUnlock(&pipeMutex);
	    return infoPtr->dwProcessId;
	}
    }
    Tcl_MutexUnlock(&pipeMutex);
    return TCL_INDEX_NONE;
    return -1;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpCreateProcess --
 *
907
908
909
910
911
912
913
914

915
916
917
918
919
920
921
922
923
924
925
926

927
928
929
930
931

932
933
934
935
936
937
938
912
913
914
915
916
917
918

919
920
921
922
923
924
925
926
927
928
929
930

931
932
933
934
935

936
937
938
939
940
941
942
943







-
+











-
+




-
+








int
TclpCreateProcess(
    Tcl_Interp *interp,		/* Interpreter in which to leave errors that
				 * occurred when creating the child process.
				 * Error messages from the child process
				 * itself are sent to errorFile. */
    int argc,			/* Number of arguments in following array. */
    size_t argc,			/* Number of arguments in following array. */
    const char **argv,		/* Array of argument strings. argv[0] contains
				 * the name of the executable converted to
				 * native format (using the
				 * Tcl_TranslateFileName call). Additional
				 * arguments have not been converted. */
    TclFile inputFile,		/* If non-NULL, gives the file to use as input
				 * for the child process. If inputFile file is
				 * not readable or is NULL, the child will
				 * receive no standard input. */
    TclFile outputFile,		/* If non-NULL, gives the file that receives
				 * output from the child process. If
				 * outputFile file is not writeable or is
				 * outputFile file is not writable or is
				 * NULL, output from the child will be
				 * discarded. */
    TclFile errorFile,		/* If non-NULL, gives the file that receives
				 * errors from the child process. If errorFile
				 * file is not writeable or is NULL, errors
				 * file is not writable or is NULL, errors
				 * from the child will be discarded. errorFile
				 * may be the same as outputFile. */
    Tcl_Pid *pidPtr)		/* If this function is successful, pidPtr is
				 * filled with the process id of the child
				 * process. */
{
    int result, applType, createFlags;
1022
1023
1024
1025
1026
1027
1028
1029

1030
1031
1032
1033
1034
1035
1036
1027
1028
1029
1030
1031
1032
1033

1034
1035
1036
1037
1038
1039
1040
1041







-
+







	    CloseHandle(h);
	}
    } else {
	DuplicateHandle(hProcess, inputHandle, hProcess, &startInfo.hStdInput,
		0, TRUE, DUPLICATE_SAME_ACCESS);
    }
    if (startInfo.hStdInput == INVALID_HANDLE_VALUE) {
	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"couldn't duplicate input handle: %s",
		Tcl_PosixError(interp)));
	goto end;
    }

    if (outputHandle == INVALID_HANDLE_VALUE) {
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
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







-
+



















-
+




















-
+







	startInfo.hStdOutput = CreateFileW(L"NUL:", GENERIC_WRITE, 0,
		&secAtts, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    } else {
	DuplicateHandle(hProcess, outputHandle, hProcess,
		&startInfo.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS);
    }
    if (startInfo.hStdOutput == INVALID_HANDLE_VALUE) {
	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"couldn't duplicate output handle: %s",
		Tcl_PosixError(interp)));
	goto end;
    }

    if (errorHandle == INVALID_HANDLE_VALUE) {
	/*
	 * If handle was not set, errors should be sent to an infinitely deep
	 * sink.
	 */

	startInfo.hStdError = CreateFileW(L"NUL:", GENERIC_WRITE, 0,
		&secAtts, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    } else {
	DuplicateHandle(hProcess, errorHandle, hProcess, &startInfo.hStdError,
		0, TRUE, DUPLICATE_SAME_ACCESS);
    }
    if (startInfo.hStdError == INVALID_HANDLE_VALUE) {
	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"couldn't duplicate error handle: %s",
		Tcl_PosixError(interp)));
	goto end;
    }

    /*
     * If we do not have a console window, then we must run DOS and WIN32
     * console mode applications as detached processes. This tells the loader
     * that the child application should not inherit the console, and that it
     * should not create a new console window for the child application. The
     * child application should get its stdio from the redirection handles
     * provided by this application, and run in the background.
     *
     * If we are starting a GUI process, they don't automatically get a
     * console, so it doesn't matter if they are started as foreground or
     * detached processes. The GUI window will still pop up to the foreground.
     */

    if (HasConsole()) {
	    createFlags = 0;
	createFlags = 0;
    } else if (applType == APPL_DOS) {
	/*
	 * Under NT, 16-bit DOS applications will not run unless they can
	 * be attached to a console. If we are running without a console,
	 * run the 16-bit program as an normal process inside of a hidden
	 * console application, and then run that hidden console as a
	 * detached process.
1133
1134
1135
1136
1137
1138
1139
1140

1141
1142
1143
1144
1145
1146
1147
1138
1139
1140
1141
1142
1143
1144

1145
1146
1147
1148
1149
1150
1151
1152







-
+







     */

    BuildCommandLine(execPath, argc, argv, &cmdLine);

    if (CreateProcessW(NULL, (WCHAR *) Tcl_DStringValue(&cmdLine),
	    NULL, NULL, TRUE, (DWORD) createFlags, NULL, NULL, &startInfo,
	    &procInfo) == 0) {
	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("couldn't execute \"%s\": %s",
		argv[0], Tcl_PosixError(interp)));
	goto end;
    }

    /*
     * This wait is used to force the OS to give some time to the DOS process.
1159
1160
1161
1162
1163
1164
1165
1166

1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1164
1165
1166
1167
1168
1169
1170

1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189

1190
1191
1192
1193
1194
1195
1196







-
+


















-







     * CreateProcessW() and CloseHandle(), the problem does not occur." PSS ID
     * Number: Q124121
     */

    WaitForInputIdle(procInfo.hProcess, 5000);
    CloseHandle(procInfo.hThread);

    *pidPtr = (Tcl_Pid) (size_t) procInfo.dwProcessId;
    *pidPtr = (Tcl_Pid)INT2PTR(procInfo.dwProcessId);
    if (*pidPtr != 0) {
	TclWinAddProcess(procInfo.hProcess, procInfo.dwProcessId);
    }
    result = TCL_OK;

  end:
    Tcl_DStringFree(&cmdLine);
    if (startInfo.hStdInput != INVALID_HANDLE_VALUE) {
	CloseHandle(startInfo.hStdInput);
    }
    if (startInfo.hStdOutput != INVALID_HANDLE_VALUE) {
	CloseHandle(startInfo.hStdOutput);
    }
    if (startInfo.hStdError != INVALID_HANDLE_VALUE) {
	CloseHandle(startInfo.hStdError);
    }
    return result;
}


/*
 *----------------------------------------------------------------------
 *
 * HasConsole --
 *
 *	Determines whether the current application is attached to a console.
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
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







-
+




-
+




















-
+




-
+












-
+







     * words, SearchPath will not find the program "a.b.exe" if the arguments
     * specified "a.b" and ".exe"). So, first look for the file as it is
     * named. Then manually append the extensions, looking for a match.
     */

    applType = APPL_NONE;
    Tcl_DStringInit(&nameBuf);
    Tcl_DStringAppend(&nameBuf, originalName, -1);
    Tcl_DStringAppend(&nameBuf, originalName, TCL_INDEX_NONE);
    nameLen = Tcl_DStringLength(&nameBuf);

    for (i = 0; i < (int) (sizeof(extensions) / sizeof(extensions[0])); i++) {
	Tcl_DStringSetLength(&nameBuf, nameLen);
	Tcl_DStringAppend(&nameBuf, extensions[i], -1);
	Tcl_DStringAppend(&nameBuf, extensions[i], TCL_INDEX_NONE);
	Tcl_DStringInit(&ds);
	nativeName = Tcl_UtfToWCharDString(Tcl_DStringValue(&nameBuf),
		Tcl_DStringLength(&nameBuf), &ds);
	found = SearchPathW(NULL, nativeName, NULL, MAX_PATH,
		nativeFullPath, &rest);
	Tcl_DStringFree(&ds);
	if (found == 0) {
	    continue;
	}

	/*
	 * Ignore matches on directories or data files, return if identified a
	 * known type.
	 */

	attr = GetFileAttributesW(nativeFullPath);
	if ((attr == 0xFFFFFFFF) || (attr & FILE_ATTRIBUTE_DIRECTORY)) {
	    continue;
	}
	Tcl_DStringInit(&ds);
	strcpy(fullName, Tcl_WCharToUtfDString(nativeFullPath, -1, &ds));
	strcpy(fullName, Tcl_WCharToUtfDString(nativeFullPath, TCL_INDEX_NONE, &ds));
	Tcl_DStringFree(&ds);

	ext = strrchr(fullName, '.');
	if ((ext != NULL) &&
            (strcasecmp(ext, ".cmd") == 0 || strcasecmp(ext, ".bat") == 0)) {
		(strcasecmp(ext, ".cmd") == 0 || strcasecmp(ext, ".bat") == 0)) {
	    applType = APPL_DOS;
	    break;
	}

	hFile = CreateFileW(nativeFullPath,
		GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE) {
	    continue;
	}

	header.e_magic = 0;
	ReadFile(hFile, (void *) &header, sizeof(header), &read, NULL);
	ReadFile(hFile, (void *)&header, sizeof(header), &read, NULL);
	if (header.e_magic != IMAGE_DOS_SIGNATURE) {
	    /*
	     * Doesn't have the magic number for relocatable executables. If
	     * filename ends with .com, assume it's a DOS application anyhow.
	     * Note that we didn't make this assumption at first, because some
	     * supposed .com files are really 32-bit executables with all the
	     * magic numbers and everything.
1360
1361
1362
1363
1364
1365
1366
1367

1368
1369
1370
1371
1372
1373
1374
1364
1365
1366
1367
1368
1369
1370

1371
1372
1373
1374
1375
1376
1377
1378







-
+








	/*
	 * The DWORD at header.e_lfanew points to yet another magic number.
	 */

	buf[0] = '\0';
	SetFilePointer(hFile, header.e_lfanew, NULL, FILE_BEGIN);
	ReadFile(hFile, (void *) buf, 2, &read, NULL);
	ReadFile(hFile, (void *)buf, 2, &read, NULL);
	CloseHandle(hFile);

	if ((buf[0] == 'N') && (buf[1] == 'E')) {
	    applType = APPL_WIN3X;
	} else if ((buf[0] == 'P') && (buf[1] == 'E')) {
	    applType = APPL_WIN32;
	} else {
1383
1384
1385
1386
1387
1388
1389
1390

1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406

1407
1408
1409
1410
1411
1412
1413
1387
1388
1389
1390
1391
1392
1393

1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409

1410
1411
1412
1413
1414
1415
1416
1417







-
+















-
+







	    applType = APPL_DOS;
	}
	break;
    }
    Tcl_DStringFree(&nameBuf);

    if (applType == APPL_NONE) {
	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("couldn't execute \"%s\": %s",
		originalName, Tcl_PosixError(interp)));
	return APPL_NONE;
    }

    if (applType == APPL_WIN3X) {
	/*
	 * Replace long path name of executable with short path name for
	 * 16-bit applications. Otherwise the application may not be able to
	 * correctly parse its own command line to separate off the
	 * application name from the arguments.
	 */

	GetShortPathNameW(nativeFullPath, nativeFullPath, MAX_PATH);
	Tcl_DStringInit(&ds);
	strcpy(fullName, Tcl_WCharToUtfDString(nativeFullPath, -1, &ds));
	strcpy(fullName, Tcl_WCharToUtfDString(nativeFullPath, TCL_INDEX_NONE, &ds));
	Tcl_DStringFree(&ds);
    }
    return applType;
}

/*
 *----------------------------------------------------------------------
1454
1455
1456
1457
1458
1459
1460
1461

1462
1463
1464
1465
1466
1467
1468
1458
1459
1460
1461
1462
1463
1464

1465
1466
1467
1468
1469
1470
1471
1472







-
+







    const char *bspos)
{
    if (!bspos) {
	if (current > start) {	/* part before current (special) */
	    Tcl_DStringAppend(dsPtr, start, (int) (current - start));
	}
    } else {
    	if (bspos > start) {	/* part before first backslash */
	if (bspos > start) {	/* part before first backslash */
	    Tcl_DStringAppend(dsPtr, start, (int) (bspos - start));
	}
	while (bspos++ < current) { /* each backslash twice */
	    TclDStringAppendLiteral(dsPtr, "\\\\");
	}
    }
}
1497
1498
1499
1500
1501
1502
1503
1504

1505
1506
1507
1508
1509
1510
1511
1501
1502
1503
1504
1505
1506
1507

1508
1509
1510
1511
1512
1513
1514
1515







-
+







     * main quotes, so `\` remains `\`, but important - not at end of part,
     * because results as before the quote, so `%\%\` should be escaped as
     * `"%\%"\\`).
     */

    TclDStringAppendLiteral(dsPtr, "\""); /* opening escape quote-char */
    do {
    	*bspos = NULL;
	*bspos = NULL;
	special++;
	if (*special == '\\') {
	    /*
	     * Bypass backslashes (and mark first backslash position).
	     */

	    special = BuildCmdLineBypassBS(special, bspos);
1532
1533
1534
1535
1536
1537
1538
1539

1540
1541
1542
1543
1544
1545


1546


1547
1548
1549
1550
1551
1552






1553
1554
1555
1556
1557
1558
1559
1536
1537
1538
1539
1540
1541
1542

1543
1544
1545
1546
1547
1548

1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572







-
+





-
+
+

+
+






+
+
+
+
+
+







    return special;
}

static void
BuildCommandLine(
    const char *executable,	/* Full path of executable (including
				 * extension). Replacement for argv[0]. */
    int argc,			/* Number of arguments. */
    size_t argc,			/* Number of arguments. */
    const char **argv,		/* Argument strings in UTF. */
    Tcl_DString *linePtr)	/* Initialized Tcl_DString that receives the
				 * command line (WCHAR). */
{
    const char *arg, *start, *special, *bspos;
    int quote = 0, i;
    int quote = 0;
    size_t i;
    Tcl_DString ds;
#ifdef TCL_WIN_PIPE_FULLESC
    /* full escape inclusive %-subst avoidance */
    static const char specMetaChars[] = "&|^<>!()%";
				/* Characters to enclose in quotes if unpaired
				 * quote flag set. */
    static const char specMetaChars2[] = "%";
				/* Character to enclose in quotes in any case
				 * (regardless of unpaired-flag). */
#else
    /* escape considering quotation only (no %-subst avoidance) */
    static const char specMetaChars[] = "&|^<>!()";
				/* Characters to enclose in quotes if unpaired
				 * quote flag set. */
#endif
    /*
     * Quote flags:
     *   CL_ESCAPE   - escape argument;
     *   CL_QUOTE    - enclose in quotes;
     *   CL_UNPAIRED - previous arguments chain contains unpaired quote-char;
     */
    enum {CL_ESCAPE = 1, CL_QUOTE = 2, CL_UNPAIRED = 4};
1624
1625
1626
1627
1628
1629
1630
1631

1632
1633
1634
1635
1636
1637
1638
1637
1638
1639
1640
1641
1642
1643

1644
1645
1646
1647
1648
1649
1650
1651







-
+







	    TclDStringAppendLiteral(&ds, "\"");
	}
	if (!(quote & CL_ESCAPE)) {
	    /*
	     * Nothing to escape.
	     */

	    Tcl_DStringAppend(&ds, arg, -1);
	    Tcl_DStringAppend(&ds, arg, TCL_INDEX_NONE);
	} else {
	    start = arg;
	    for (special = arg; *special != '\0'; ) {
		/*
		 * Position of `\` is important before quote or at end (equal
		 * `\"` because quoted).
		 */
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
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







-
+
















+







		    /*
		     * Start to current or first backslash
		     */

		    start = !bspos ? special : bspos;
		    continue;
		}

#ifdef TCL_WIN_PIPE_FULLESC
		/*
		 * Special case for % - should be enclosed always (paired
		 * also)
		 */

		if (strchr(specMetaChars2, *special)) {
		    special = QuoteCmdLinePart(&ds, start, special,
			    specMetaChars2, &bspos);

		    /*
		     * Start to current or first backslash.
		     */

		    start = !bspos ? special : bspos;
		    continue;
		}
#endif

		/*
		 * Other not special (and not meta) character
		 */

		bspos = NULL;		/* reset last backslash position (not
					 * interesting) */
1755
1756
1757
1758
1759
1760
1761
1762

1763
1764
1765
1766
1767
1768
1769
1769
1770
1771
1772
1773
1774
1775

1776
1777
1778
1779
1780
1781
1782
1783







-
+








Tcl_Channel
TclpCreateCommandChannel(
    TclFile readFile,		/* If non-null, gives the file for reading. */
    TclFile writeFile,		/* If non-null, gives the file for writing. */
    TclFile errorFile,		/* If non-null, gives the file where errors
				 * can be read. */
    int numPids,		/* The number of pids in the pid array. */
    size_t numPids,		/* The number of pids in the pid array. */
    Tcl_Pid *pidPtr)		/* An array of process identifiers. */
{
    char channelName[16 + TCL_INTEGER_SPACE];
    PipeInfo *infoPtr = (PipeInfo *)Tcl_Alloc(sizeof(PipeInfo));

    PipeInit();

1792
1793
1794
1795
1796
1797
1798
1799

1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815


1816
1817
1818
1819
1820
1821
1822
1823
1824
1825

1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1806
1807
1808
1809
1810
1811
1812

1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827


1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838

1839
1840
1841
1842






1843

1844
1845
1846
1847
1848
1849
1850







-
+














-
-
+
+









-
+



-
-
-
-
-
-

-







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

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

    /*
     * For backward compatibility with previous versions of Tcl, we use
     * "file%d" as the base name for pipes even though it would be more
     * natural to use "pipe%d". Use the pointer to keep the channel names
     * unique, in case channels share handles (stdin/stdout).
     */

    sprintf(channelName, "file%" TCL_Z_MODIFIER "x", (size_t) infoPtr);
    TclWinGenerateChannelName(channelName, "file", infoPtr);
    infoPtr->channel = Tcl_CreateChannel(&pipeChannelType, channelName,
	    infoPtr, infoPtr->validMask);

    /*
     * Pipes have AUTO translation mode on Windows and ^Z eof char, which
     * means that a ^Z will be appended to them at close. This is needed for
     * Windows programs that expect a ^Z at EOF.
     */

    Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto");
    Tcl_SetChannelOption(NULL, infoPtr->channel, "-eofchar", "\032 {}");
    return infoPtr->channel;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_CreatePipe --
1862
1863
1864
1865
1866
1867
1868
1869

1870
1871
1872
1873
1874
1875

1876
1877
1878

1879
1880
1881
1882
1883
1884
1885
1869
1870
1871
1872
1873
1874
1875

1876
1877
1878
1879
1880
1881

1882
1883
1884

1885
1886
1887
1888
1889
1890
1891
1892







-
+





-
+


-
+







    SECURITY_ATTRIBUTES sec;

    sec.nLength = sizeof(SECURITY_ATTRIBUTES);
    sec.lpSecurityDescriptor = NULL;
    sec.bInheritHandle = FALSE;

    if (!CreatePipe(&readHandle, &writeHandle, &sec, 0)) {
	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"pipe creation failed: %s", Tcl_PosixError(interp)));
	return TCL_ERROR;
    }

    *rchan = Tcl_MakeFileChannel((ClientData) readHandle, TCL_READABLE);
    *rchan = Tcl_MakeFileChannel((void *)readHandle, TCL_READABLE);
    Tcl_RegisterChannel(interp, *rchan);

    *wchan = Tcl_MakeFileChannel((ClientData) writeHandle, TCL_WRITABLE);
    *wchan = Tcl_MakeFileChannel((void *)writeHandle, TCL_WRITABLE);
    Tcl_RegisterChannel(interp, *wchan);

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
1902
1903
1904
1905
1906
1907
1908
1909

1910
1911
1912
1913
1914
1915
1916
1909
1910
1911
1912
1913
1914
1915

1916
1917
1918
1919
1920
1921
1922
1923







-
+







TclGetAndDetachPids(
    Tcl_Interp *interp,
    Tcl_Channel chan)
{
    PipeInfo *pipePtr;
    const Tcl_ChannelType *chanTypePtr;
    Tcl_Obj *pidsObj;
    int i;
    size_t i;

    /*
     * Punt if the channel is not a command channel.
     */

    chanTypePtr = Tcl_GetChannelType(chan);
    if (chanTypePtr != &pipeChannelType) {
1946
1947
1948
1949
1950
1951
1952
1953

1954
1955
1956
1957
1958
1959
1960
1953
1954
1955
1956
1957
1958
1959

1960
1961
1962
1963
1964
1965
1966
1967







-
+







 *	Sets the device into blocking or non-blocking mode.
 *
 *----------------------------------------------------------------------
 */

static int
PipeBlockModeProc(
    ClientData instanceData,	/* Instance data for channel. */
    void *instanceData,	/* Instance data for channel. */
    int mode)			/* TCL_MODE_BLOCKING or
				 * TCL_MODE_NONBLOCKING. */
{
    PipeInfo *infoPtr = (PipeInfo *) instanceData;

    /*
     * Pipes on Windows can not be switched between blocking and nonblocking,
1985
1986
1987
1988
1989
1990
1991
1992

1993
1994
1995
1996
1997
1998
1999
1992
1993
1994
1995
1996
1997
1998

1999
2000
2001
2002
2003
2004
2005
2006







-
+







 *	Closes the physical channel.
 *
 *----------------------------------------------------------------------
 */

static int
PipeClose2Proc(
    ClientData instanceData,	/* Pointer to PipeInfo structure. */
    void *instanceData,	/* Pointer to PipeInfo structure. */
    Tcl_Interp *interp,		/* For error reporting. */
    int flags)			/* Flags that indicate which side to close. */
{
    PipeInfo *pipePtr = (PipeInfo *) instanceData;
    Tcl_Channel errChan;
    int errorCode, result;
    PipeInfo *infoPtr, **nextPtrPtr;
2108
2109
2110
2111
2112
2113
2114
2115

2116
2117

2118
2119
2120
2121
2122
2123
2124
2115
2116
2117
2118
2119
2120
2121

2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132







-
+


+







	 * Wrap the error file into a channel and give it to the cleanup
	 * routine.
	 */

	if (pipePtr->errorFile) {
	    WinFile *filePtr = (WinFile *) pipePtr->errorFile;

	    errChan = Tcl_MakeFileChannel((ClientData) filePtr->handle,
	    errChan = Tcl_MakeFileChannel((void *)filePtr->handle,
		    TCL_READABLE);
	    Tcl_Free(filePtr);
	    Tcl_SetChannelOption(NULL, errChan, "-profile", "replace");
	} else {
	    errChan = NULL;
	}

	result = TclCleanupChildren(interp, pipePtr->numPids,
		pipePtr->pidPtr, errChan);
    }
2155
2156
2157
2158
2159
2160
2161
2162

2163
2164
2165
2166
2167
2168
2169
2163
2164
2165
2166
2167
2168
2169

2170
2171
2172
2173
2174
2175
2176
2177







-
+







 *	Reads input from the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
PipeInputProc(
    ClientData instanceData,	/* Pipe state. */
    void *instanceData,	/* Pipe state. */
    char *buf,			/* Where to store data read. */
    int bufSize,		/* How much space is available in the
				 * buffer? */
    int *errorCode)		/* Where to store error code. */
{
    PipeInfo *infoPtr = (PipeInfo *) instanceData;
    WinFile *filePtr = (WinFile*) infoPtr->readFile;
2220
2221
2222
2223
2224
2225
2226
2227

2228
2229
2230
2231
2232
2233
2234
2228
2229
2230
2231
2232
2233
2234

2235
2236
2237
2238
2239
2240
2241
2242







-
+







	/*
	 * Ignore errors if we have data to return.
	 */

	return bytesRead;
    }

    TclWinConvertError(GetLastError());
    Tcl_WinConvertError(GetLastError());
    if (errno == EPIPE) {
	infoPtr->readFlags |= PIPE_EOF;
	return 0;
    }
    *errorCode = errno;
    return -1;
}
2249
2250
2251
2252
2253
2254
2255
2256

2257
2258
2259
2260
2261
2262
2263
2257
2258
2259
2260
2261
2262
2263

2264
2265
2266
2267
2268
2269
2270
2271







-
+







 *	Writes output on the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
PipeOutputProc(
    ClientData instanceData,	/* Pipe state. */
    void *instanceData,	/* Pipe state. */
    const char *buf,		/* The data buffer. */
    int toWrite,		/* How many bytes to write? */
    int *errorCode)		/* Where to store error code. */
{
    PipeInfo *infoPtr = (PipeInfo *) instanceData;
    WinFile *filePtr = (WinFile*) infoPtr->writeFile;
    DWORD bytesWritten, timeout;
2279
2280
2281
2282
2283
2284
2285
2286

2287
2288
2289
2290
2291
2292
2293
2287
2288
2289
2290
2291
2292
2293

2294
2295
2296
2297
2298
2299
2300
2301







-
+







    }

    /*
     * Check for a background error on the last write.
     */

    if (infoPtr->writeError) {
	TclWinConvertError(infoPtr->writeError);
	Tcl_WinConvertError(infoPtr->writeError);
	infoPtr->writeError = 0;
	goto error;
    }

    if (infoPtr->flags & PIPE_ASYNC) {
	/*
	 * The pipe is non-blocking, so copy the data into the output buffer
2314
2315
2316
2317
2318
2319
2320
2321

2322
2323
2324
2325
2326
2327
2328
2322
2323
2324
2325
2326
2327
2328

2329
2330
2331
2332
2333
2334
2335
2336







-
+







	/*
	 * In the blocking case, just try to write the buffer directly. This
	 * avoids an unnecessary copy.
	 */

	if (WriteFile(filePtr->handle, (LPVOID) buf, (DWORD) toWrite,
		&bytesWritten, (LPOVERLAPPED) NULL) == FALSE) {
	    TclWinConvertError(GetLastError());
	    Tcl_WinConvertError(GetLastError());
	    goto error;
	}
    }
    return bytesWritten;

  error:
    *errorCode = errno;
2431
2432
2433
2434
2435
2436
2437
2438

2439
2440
2441
2442
2443
2444
2445
2439
2440
2441
2442
2443
2444
2445

2446
2447
2448
2449
2450
2451
2452
2453







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
PipeWatchProc(
    ClientData instanceData,	/* Pipe state. */
    void *instanceData,	/* Pipe state. */
    int mask)			/* What events to watch for, OR-ed combination
				 * of TCL_READABLE, TCL_WRITABLE and
				 * TCL_EXCEPTION. */
{
    PipeInfo **nextPtrPtr, *ptr;
    PipeInfo *infoPtr = (PipeInfo *) instanceData;
    int oldMask = infoPtr->watchMask;
2493
2494
2495
2496
2497
2498
2499
2500

2501
2502

2503
2504
2505
2506
2507
2508
2509

2510
2511
2512
2513
2514

2515
2516
2517
2518
2519
2520
2521
2501
2502
2503
2504
2505
2506
2507

2508
2509

2510
2511
2512
2513
2514
2515
2516

2517
2518
2519
2520
2521

2522
2523
2524
2525
2526
2527
2528
2529







-
+

-
+






-
+




-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PipeGetHandleProc(
    ClientData instanceData,	/* The pipe state. */
    void *instanceData,	/* The pipe state. */
    int direction,		/* TCL_READABLE or TCL_WRITABLE */
    ClientData *handlePtr)	/* Where to store the handle.  */
    void **handlePtr)	/* Where to store the handle.  */
{
    PipeInfo *infoPtr = (PipeInfo *) instanceData;
    WinFile *filePtr;

    if (direction == TCL_READABLE && infoPtr->readFile) {
	filePtr = (WinFile*) infoPtr->readFile;
	*handlePtr = (ClientData) filePtr->handle;
	*handlePtr = (void *)filePtr->handle;
	return TCL_OK;
    }
    if (direction == TCL_WRITABLE && infoPtr->writeFile) {
	filePtr = (WinFile*) infoPtr->writeFile;
	*handlePtr = (ClientData) filePtr->handle;
	*handlePtr = (void *)filePtr->handle;
	return TCL_OK;
    }
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
2561
2562
2563
2564
2565
2566
2567
2568

2569
2570
2571
2572
2573
2574
2575
2569
2570
2571
2572
2573
2574
2575

2576
2577
2578
2579
2580
2581
2582
2583







-
+







     * Find the process and cut it from the process list.
     */

    Tcl_MutexLock(&pipeMutex);
    prevPtrPtr = &procList;
    for (infoPtr = procList; infoPtr != NULL;
	    prevPtrPtr = &infoPtr->nextPtr, infoPtr = infoPtr->nextPtr) {
	 if (infoPtr->dwProcessId == (size_t) pid) {
	 if (infoPtr->dwProcessId == (Tcl_Size)pid) {
	    *prevPtrPtr = infoPtr->nextPtr;
	    break;
	}
    }
    Tcl_MutexUnlock(&pipeMutex);

    /*
2671
2672
2673
2674
2675
2676
2677
2678

2679
2680
2681
2682
2683
2684
2685
2679
2680
2681
2682
2683
2684
2685

2686
2687
2688
2689
2690
2691
2692
2693







-
+







	    *statPtr = exitCode;
	    break;
	}
	result = pid;
    } else {
	errno = ECHILD;
	*statPtr = 0xC0000000 | ECHILD;
	result = (Tcl_Pid) -1;
	result = (Tcl_Pid)-1;
    }

    /*
     * Officially close the process handle.
     */

    CloseHandle(infoPtr->hProcess);
2705
2706
2707
2708
2709
2710
2711
2712

2713
2714

2715
2716
2717
2718
2719
2720
2721
2713
2714
2715
2716
2717
2718
2719

2720
2721

2722
2723
2724
2725
2726
2727
2728
2729







-
+

-
+







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

void
TclWinAddProcess(
    void *hProcess,		/* Handle to process */
    size_t id)		/* Global process identifier */
    Tcl_Size id)		/* Global process identifier */
{
    ProcInfo *procPtr = (ProcInfo*)Tcl_Alloc(sizeof(ProcInfo));
    ProcInfo *procPtr = (ProcInfo *)Tcl_Alloc(sizeof(ProcInfo));

    PipeInit();

    procPtr->hProcess = hProcess;
    procPtr->dwProcessId = id;
    Tcl_MutexLock(&pipeMutex);
    procPtr->nextPtr = procList;
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
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







-
+







-
+



-
+



-
+















-
+







 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_PidObjCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Argument strings. */
{
    Tcl_Channel chan;
    const Tcl_ChannelType *chanTypePtr;
    PipeInfo *pipePtr;
    int i;
    size_t i;
    Tcl_Obj *resultPtr;

    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?channelId?");
	Tcl_WrongNumArgs(interp, 1, objv, "?channel?");
	return TCL_ERROR;
    }
    if (objc == 1) {
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj((unsigned) getpid()));
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(getpid()));
    } else {
	chan = Tcl_GetChannel(interp, TclGetString(objv[1]),
		NULL);
	if (chan == (Tcl_Channel) NULL) {
	    return TCL_ERROR;
	}
	chanTypePtr = Tcl_GetChannelType(chan);
	if (chanTypePtr != &pipeChannelType) {
	    return TCL_OK;
	}

	pipePtr = (PipeInfo *) Tcl_GetChannelInstanceData(chan);
	TclNewObj(resultPtr);
	for (i = 0; i < pipePtr->numPids; i++) {
	    Tcl_ListObjAppendElement(/*interp*/ NULL, resultPtr,
		    Tcl_NewWideIntObj((unsigned)
		    Tcl_NewWideIntObj(
			    TclpGetPid(pipePtr->pidPtr[i])));
	}
	Tcl_SetObjResult(interp, resultPtr);
    }
    return TCL_OK;
}

2807
2808
2809
2810
2811
2812
2813
2814

2815
2816
2817
2818
2819
2820
2821
2815
2816
2817
2818
2819
2820
2821

2822
2823
2824
2825
2826
2827
2828
2829







-
+







static int
WaitForRead(
    PipeInfo *infoPtr,		/* Pipe state. */
    int blocking)		/* Indicates whether call should be blocking
				 * or not. */
{
    DWORD timeout, count;
    HANDLE *handle = (HANDLE *)((WinFile *) infoPtr->readFile)->handle;
    HANDLE handle = ((WinFile *) infoPtr->readFile)->handle;

    while (1) {
	/*
	 * Synchronize with the reader thread.
	 */

	/* avoid blocking if pipe-thread exited */
2846
2847
2848
2849
2850
2851
2852
2853

2854
2855
2856
2857
2858
2859
2860
2854
2855
2856
2857
2858
2859
2860

2861
2862
2863
2864
2865
2866
2867
2868







-
+








	/*
	 * Check to see if there is any data sitting in the pipe.
	 */

	if (PeekNamedPipe(handle, (LPVOID) NULL, (DWORD) 0,
		(LPDWORD) NULL, &count, (LPDWORD) NULL) != TRUE) {
	    TclWinConvertError(GetLastError());
	    Tcl_WinConvertError(GetLastError());

	    /*
	     * Check to see if the peek failed because of EOF.
	     */

	    if (errno == EPIPE) {
		infoPtr->readFlags |= PIPE_EOF;
3132
3133
3134
3135
3136
3137
3138
3139

3140
3141
3142
3143
3144
3145
3146
3147

3148
3149
3150
3151
3152
3153
3154
3140
3141
3142
3143
3144
3145
3146

3147
3148
3149
3150
3151
3152
3153
3154

3155
3156
3157
3158
3159
3160
3161
3162







-
+







-
+







 *	Changes thread local list of valid channels.
 *
 *----------------------------------------------------------------------
 */

static void
PipeThreadActionProc(
    ClientData instanceData,
    void *instanceData,
    int action)
{
    PipeInfo *infoPtr = (PipeInfo *) instanceData;

    /*
     * We do not access firstPipePtr in the thread structures. This is not for
     * all pipes managed by the thread, but only those we are watching.
     * Removal of the filevent handlers before transfer thus takes care of
     * Removal of the fileevent handlers before transfer thus takes care of
     * this structure.
     */

    Tcl_MutexLock(&pipeMutex);
    if (action == TCL_CHANNEL_THREAD_INSERT) {
	/*
	 * We can't copy the thread information from the channel when the
3193
3194
3195
3196
3197
3198
3199
3200

3201
3202
3203
3204
3205
3206
3207
3201
3202
3203
3204
3205
3206
3207

3208
3209
3210
3211
3212
3213
3214
3215







-
+







    TCL_UNUSED(Tcl_Obj *) /*extensionObj*/,
    Tcl_Obj *resultingNameObj)
{
    WCHAR name[MAX_PATH];
    char *namePtr;
    HANDLE handle;
    DWORD flags = FILE_ATTRIBUTE_TEMPORARY;
    size_t length;
    Tcl_Size length;
    int counter, counter2;
    Tcl_DString buf;

    if (!resultingNameObj) {
	flags |= FILE_FLAG_DELETE_ON_CLOSE;
    }

3229
3230
3231
3232
3233
3234
3235
3236

3237
3238
3239
3240
3241
3242
3243
3237
3238
3239
3240
3241
3242
3243

3244
3245
3246
3247
3248
3249
3250
3251







-
+







    counter = TclpGetClicks() % 65533;
    counter2 = 1024;			/* Only try this many times! Prevents
					 * an infinite loop. */

    do {
	char number[TCL_INTEGER_SPACE + 4];

	sprintf(number, "%d.TMP", counter);
	snprintf(number, sizeof(number), "%d.TMP", counter);
	counter = (unsigned short) (counter + 1);
	Tcl_DStringInit(&buf);
	Tcl_UtfToWCharDString(number, strlen(number), &buf);
	Tcl_DStringSetLength(&buf, Tcl_DStringLength(&buf) + 1);
	memcpy(namePtr, Tcl_DStringValue(&buf), Tcl_DStringLength(&buf) + 1);
	Tcl_DStringFree(&buf);

3253
3254
3255
3256
3257
3258
3259
3260

3261
3262
3263
3264

3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284

3285
3286
3287
3288
3289
3290
3291
3261
3262
3263
3264
3265
3266
3267

3268
3269
3270
3271

3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291

3292
3293
3294
3295
3296
3297
3298
3299







-
+



-
+



















-
+







    if (resultingNameObj) {
	Tcl_Obj *tmpObj = TclpNativeToNormalized(name);

	Tcl_AppendObjToObj(resultingNameObj, tmpObj);
	TclDecrRefCount(tmpObj);
    }

    return Tcl_MakeFileChannel((ClientData) handle,
    return Tcl_MakeFileChannel((void *)handle,
	    TCL_READABLE|TCL_WRITABLE);

  gotError:
    TclWinConvertError(GetLastError());
    Tcl_WinConvertError(GetLastError());
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * TclPipeThreadCreateTI --
 *
 *	Creates a thread info structure, can be owned by worker.
 *
 * Results:
 *	Pointer to created TI structure.
 *
 *----------------------------------------------------------------------
 */

TclPipeThreadInfo *
TclPipeThreadCreateTI(
    TclPipeThreadInfo **pipeTIPtr,
    ClientData clientData,
    void *clientData,
    HANDLE wakeEvent)
{
    TclPipeThreadInfo *pipeTI;
#ifndef _PTI_USE_CKALLOC
    pipeTI = (TclPipeThreadInfo *)malloc(sizeof(TclPipeThreadInfo));
#else
    pipeTI = (TclPipeThreadInfo *)Tcl_Alloc(sizeof(TclPipeThreadInfo));
3385
3386
3387
3388
3389
3390
3391
3392

3393
3394
3395

3396
3397
3398
3399
3400
3401
3402
3393
3394
3395
3396
3397
3398
3399

3400
3401
3402

3403
3404
3405
3406
3407
3408
3409
3410







-
+


-
+







    /*
     * End of work, check the owner of the TI structure.
     */

    if (state != PTI_STATE_STOP) {
	*pipeTIPtr = NULL;
    } else {
    	pipeTI->evWakeUp = NULL;
	pipeTI->evWakeUp = NULL;
    }
    if (wakeEvent) {
    	SetEvent(wakeEvent);
	SetEvent(wakeEvent);
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
3571
3572
3573
3574
3575
3576
3577
3578
3579

3580
3581
3582
3583
3584
3585
3586
3587
3579
3580
3581
3582
3583
3584
3585


3586

3587
3588
3589
3590
3591
3592
3593







-
-
+
-








	    SetEvent(evControl);

	    /*
	     * Cancel all sync-IO of this thread (may be blocked there).
	     */

	    if (tclWinProcs.cancelSynchronousIo) {
		tclWinProcs.cancelSynchronousIo(hThread);
	    CancelSynchronousIo(hThread);
	    }

	    /*
	     * Wait at most 20 milliseconds for the reader thread to close
	     * (regarding TIP#398-fast-exit).
	     */

	    /*

Changes to win/tclWinPort.h.

22
23
24
25
26
27
28
29

30
31
32
33

34
35
36

37
38
39
40
41
42
43
22
23
24
25
26
27
28

29
30
31
32

33
34
35

36
37
38
39
40
41
42
43







-
+



-
+


-
+







	&& !defined(MP_32BIT) && !defined(MP_64BIT)
#   define MP_64BIT
#endif

/*
 * We must specify the lower version we intend to support.
 *
 * WINVER = 0x0501 means Windows XP and above
 * WINVER = 0x0601 means Windows 7 and above
 */

#ifndef WINVER
#   define WINVER 0x0501
#   define WINVER 0x0601
#endif
#ifndef _WIN32_WINNT
#   define _WIN32_WINNT 0x0501
#   define _WIN32_WINNT 0x0601
#endif

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN

/* Compatibility to older visual studio / windows platform SDK */
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
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







-
-
-
-
-
-













-
-
-
-
+
-








-
+







#include <malloc.h>
#include <process.h>
#include <signal.h>
#ifdef HAVE_INTTYPES_H
#   include <inttypes.h>
#endif
#include <limits.h>
#ifdef HAVE_STDINT_H
#   include <stdint.h>
#else
#   include "../compat/stdint.h"
#endif

#ifndef __GNUC__
#    define strncasecmp _strnicmp
#    define strcasecmp _stricmp
#endif

/*
 * Need to block out these includes for building extensions with MetroWerks
 * compiler for Win32.
 */

#ifndef __MWERKS__
#include <sys/stat.h>
#include <sys/timeb.h>
#   ifdef __BORLANDC__
#	include <utime.h>
#   else
#	include <sys/utime.h>
#include <sys/utime.h>
#   endif /* __BORLANDC__ */
#endif /* __MWERKS__ */

/*
 * The following defines redefine the Windows Socket errors as
 * BSD errors so Tcl_PosixError can do the right thing.
 */

#ifndef ENOTEMPTY
#   define ENOTEMPTY 	41	/* Directory not empty */
#   define ENOTEMPTY	41	/* Directory not empty */
#endif
#ifndef EREMOTE
#   define EREMOTE	66	/* The object is remote */
#endif
#ifndef EPFNOSUPPORT
#   define EPFNOSUPPORT	96	/* Protocol family not supported */
#endif
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
242
243
244
245
246
247
248

249
250
251
252
253
254
255







-







#ifndef ETXTBSY
#   define ETXTBSY	139	/* Text file or pseudo-device busy */
#endif
#ifndef EWOULDBLOCK
#   define EWOULDBLOCK	140	/* Operation would block */
#endif


/* Visual Studio doesn't have these, so just choose some high numbers */
#ifndef ESOCKTNOSUPPORT
#   define ESOCKTNOSUPPORT 240	/* Socket type not supported */
#endif
#ifndef ESHUTDOWN
#   define ESHUTDOWN	241	/* Can't send after socket shutdown */
#endif
351
352
353
354
355
356
357



358
359
360
361
362
363
364
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356







+
+
+







#endif
#ifndef W_OK
#    define W_OK 02
#endif
#ifndef R_OK
#    define R_OK 04
#endif
#ifndef O_ACCMODE
#    define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
#endif

/*
 * Define macros to query file type bits, if they're not already
 * defined.
 */

#ifndef S_IFLNK
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
410
411
412
413
414
415
416

417
418
419
420
421
422
423







-







#   ifdef S_IFLNK
#       define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#   else
#       define S_ISLNK(m) 0
#   endif
#endif /* !S_ISLNK */


/*
 * Define MAXPATHLEN in terms of MAXPATH if available
 */

#ifndef MAXPATH
#   define MAXPATH MAX_PATH
#endif /* MAXPATH */
450
451
452
453
454
455
456
457
458
459
460
461
462

463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
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
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
467
468
469
470







-
-
-


-
+




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

+





-
-
-
+
+
-







 * Visual C++ has some odd names for common functions, so we need to
 * define a few macros to handle them.  Also, it defines EDEADLOCK and
 * EDEADLK as the same value, which confuses Tcl_ErrnoId().
 */

#if defined(_MSC_VER) || defined(__MSVCRT__)
#   define environ _environ
#   if defined(_MSC_VER) && (_MSC_VER < 1600)
#	define hypot _hypot
#   endif
#   define exception _exception
#   undef EDEADLOCK
#   if defined(_MSC_VER) && (_MSC_VER >= 1700)
#   if defined(_MSC_VER)
#	define timezone _timezone
#   endif
#endif /* _MSC_VER || __MSVCRT__ */

/*
 * Borland's timezone and environ functions.
 */

#ifdef  __BORLANDC__
#   define timezone _timezone
#   define environ  _environ
#endif /* __BORLANDC__ */

#ifdef __WATCOMC__
#   if !defined(__CHAR_SIGNED__)
#	error "You must use the -j switch to ensure char is signed."
#   endif
#endif


/*
 * MSVC 8.0 started to mark many standard C library functions depreciated
 * including the *printf family and others. Tell it to shut up.
 * (_MSC_VER is 1200 for VC6, 1300 or 1310 for vc7.net, 1400 for 8.0)
 */
#if defined(_MSC_VER)
#   pragma warning(disable:4090) /* see: https://developercommunity.visualstudio.com/t/c-compiler-incorrect-propagation-of-const-qualifie/390711 */
#   pragma warning(disable:4146)
#   pragma warning(disable:4244)
#if !defined(_WIN64)
#   pragma warning(disable:4305)
#endif
#   if _MSC_VER >= 1400
#	pragma warning(disable:4267)
#	pragma warning(disable:4996)
#   pragma warning(disable:4267)
#   pragma warning(disable:4996)
#   endif
#endif

/*
 *---------------------------------------------------------------------------
 * The following macros and declarations represent the interface between
 * generic and windows-specific parts of Tcl.  Some of the macros may
 * override functions declared in tclInt.h.
543
544
545
546
547
548
549
550

551
552

553
554

555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
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







-
+

-
+

-
+



-













-
-










/*
 * The following defines wrap the system memory allocation routines for
 * use by tclAlloc.c.
 */

#define TclpSysAlloc(size)		((void*)HeapAlloc(GetProcessHeap(), \
					    (DWORD)0, (DWORD)size))
					    0, size))
#define TclpSysFree(ptr)		(HeapFree(GetProcessHeap(), \
					    (DWORD)0, (HGLOBAL)ptr))
					    0, (HGLOBAL)ptr))
#define TclpSysRealloc(ptr, size)	((void*)HeapReAlloc(GetProcessHeap(), \
					    (DWORD)0, (LPVOID)ptr, (DWORD)size))
					    0, (LPVOID)ptr, size))

/* This type is not defined in the Windows headers */
#define socklen_t       int


/*
 * The following macros have trivial definitions, allowing generic code to
 * address platform-specific issues.
 */

#define TclpReleaseFile(file)	Tcl_Free(file)

/*
 * The following macros and declarations wrap the C runtime library
 * functions.
 */

#define TclpExit		exit

#ifndef INVALID_SET_FILE_POINTER
#define INVALID_SET_FILE_POINTER 0xFFFFFFFF
#endif /* INVALID_SET_FILE_POINTER */

#ifndef LABEL_SECURITY_INFORMATION
#   define LABEL_SECURITY_INFORMATION (0x00000010L)
#endif

#endif /* _TCLWINPORT */

Changes to win/tclWinReg.c.

48
49
50
51
52
53
54
55
56



57
58
59
60
61
62
63
48
49
50
51
52
53
54


55
56
57
58
59
60
61
62
63
64







-
-
+
+
+







#define SWAPWORD(x)	MAKEWORD(HIBYTE(x), LOBYTE(x))
#define SWAPLONG(x)	MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))

/*
 * The following flag is used in OpenKeys to indicate that the specified key
 * should be created if it doesn't currently exist.
 */

#define REG_CREATE 1
enum OpenKeysFlags {
    REG_CREATE = 1
};

/*
 * The following tables contain the mapping from registry root names to the
 * system predefined keys.
 */

static const char *const rootKeyNames[] = {
82
83
84
85
86
87
88
















89
90
91
92
93
94

95
96
97
98
99
100
101
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+







static const char *const typeNames[] = {
    "none", "sz", "expand_sz", "binary", "dword",
    "dword_big_endian", "link", "multi_sz", "resource_list", NULL
};

static DWORD lastType = REG_RESOURCE_LIST;

#if (TCL_MAJOR_VERSION < 9) && defined(TCL_MINOR_VERSION) && (TCL_MINOR_VERSION < 7)
# if TCL_UTF_MAX > 3
#   define Tcl_WCharToUtfDString(a,b,c) Tcl_WinTCharToUtf((TCHAR *)(a),(b)*sizeof(WCHAR),c)
#   define Tcl_UtfToWCharDString(a,b,c) (WCHAR *)Tcl_WinUtfToTChar(a,b,c)
# else
#   define Tcl_WCharToUtfDString Tcl_UniCharToUtfDString
#   define Tcl_UtfToWCharDString Tcl_UtfToUniCharDString
# endif
#ifndef Tcl_Size
#   define Tcl_Size int
#endif
#ifndef Tcl_CreateObjCommand2
#   define Tcl_CreateObjCommand2 Tcl_CreateObjCommand
#endif
#endif

/*
 * Declarations for functions defined in this file.
 */

static void		AppendSystemError(Tcl_Interp *interp, DWORD error);
static int		BroadcastValue(Tcl_Interp *interp, int objc,
static int		BroadcastValue(Tcl_Interp *interp, Tcl_Size objc,
			    Tcl_Obj *const objv[]);
static DWORD		ConvertDWORD(DWORD type, DWORD value);
static void		DeleteCmd(void *clientData);
static int		DeleteKey(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
			    REGSAM mode);
static int		DeleteValue(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
			    Tcl_Obj *valueNameObj, REGSAM mode);
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
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







-
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-





+
+
+
+
+







			    HKEY *keyPtr);
static int		ParseKeyName(Tcl_Interp *interp, char *name,
			    char **hostNamePtr, HKEY *rootKeyPtr,
			    char **keyNamePtr);
static DWORD		RecursiveDeleteKey(HKEY hStartKey,
			    const WCHAR * pKeyName, REGSAM mode);
static int		RegistryObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Interp *interp, Tcl_Size objc,
			    Tcl_Obj *const objv[]);
static int		SetValue(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
			    Tcl_Obj *valueNameObj, Tcl_Obj *dataObj,
			    Tcl_Obj *typeObj, REGSAM mode);

#if (TCL_MAJOR_VERSION < 9) && (TCL_MINOR_VERSION < 7)
# if TCL_UTF_MAX > 3
#   define Tcl_WCharToUtfDString(a,b,c) Tcl_WinTCharToUtf((TCHAR *)(a),(b)*sizeof(WCHAR),c)
#   define Tcl_UtfToWCharDString(a,b,c) (WCHAR *)Tcl_WinUtfToTChar(a,b,c)
# else
#   define Tcl_WCharToUtfDString Tcl_UniCharToUtfDString
#   define Tcl_UtfToWCharDString Tcl_UtfToUniCharDString
# endif
#endif

static unsigned char *
getByteArrayFromObj(
	Tcl_Obj *objPtr,
	size_t *lengthPtr
) {
    int length;

    unsigned char *result = Tcl_GetByteArrayFromObj(objPtr, &length);
#if TCL_MAJOR_VERSION > 8
    if (sizeof(TCL_HASH_TYPE) > sizeof(int)) {
	/* 64-bit and TIP #494 situation: */
	 *lengthPtr = *(TCL_HASH_TYPE *) objPtr->internalRep.twoPtrValue.ptr1;
    } else
#endif
	/* 32-bit or without TIP #494 */
    *lengthPtr = (size_t) (unsigned) length;
    return result;
}

#ifdef __cplusplus
extern "C" {
#endif
DLLEXPORT int		Registry_Init(Tcl_Interp *interp);
DLLEXPORT int		Registry_Unload(Tcl_Interp *interp, int flags);
#if TCL_MAJOR_VERSION < 9
/* With those additional entries, "load tclregistry13.dll" works without 3th argument */
DLLEXPORT int		Tclregistry_Init(Tcl_Interp *interp);
DLLEXPORT int		Tclregistry_Unload(Tcl_Interp *interp, int flags);
#endif
#ifdef __cplusplus
}
#endif

/*
 *----------------------------------------------------------------------
 *
180
181
182
183
184
185
186
187

188
189
190
191

192
193
194

195








196
197
198
199
200
201
202
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







-
+



-
+


-
+

+
+
+
+
+
+
+
+








int
Registry_Init(
    Tcl_Interp *interp)
{
    Tcl_Command cmd;

    if (Tcl_InitStubs(interp, "8.5", 0) == NULL) {
    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }

    cmd = Tcl_CreateObjCommand(interp, "registry", RegistryObjCmd,
    cmd = Tcl_CreateObjCommand2(interp, "registry", RegistryObjCmd,
	    interp, DeleteCmd);
    Tcl_SetAssocData(interp, REGISTRY_ASSOC_KEY, NULL, cmd);
    return Tcl_PkgProvideEx(interp, "registry", "1.3.5", NULL);
    return Tcl_PkgProvideEx(interp, "registry", "1.3.7", NULL);
}
#if TCL_MAJOR_VERSION < 9
int
Tclregistry_Init(
    Tcl_Interp *interp)
{
    return Registry_Init(interp);
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * Registry_Unload --
 *
 *	This function removes the registry command.
235
236
237
238
239
240
241









242
243
244
245
246
247
248
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258







+
+
+
+
+
+
+
+
+







    cmd = (Tcl_Command)Tcl_GetAssocData(interp, REGISTRY_ASSOC_KEY, NULL);
    if (cmd != NULL) {
	Tcl_DeleteCommandFromToken(interp, cmd);
    }

    return TCL_OK;
}
#if TCL_MAJOR_VERSION < 9
int
Tclregistry_Unload(
    Tcl_Interp *interp,
    int flags)
{
    return Registry_Unload(interp, flags);
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * DeleteCmd --
 *
 *	Cleanup the interp command token so that unloading doesn't try to
282
283
284
285
286
287
288
289

290
291
292
293


294
295
296
297
298
299
300
292
293
294
295
296
297
298

299
300
301


302
303
304
305
306
307
308
309
310







-
+


-
-
+
+







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

static int
RegistryObjCmd(
    void *dummy,	/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Size objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    int n = 1;
    int index, argc;
    Tcl_Size n = 1, argc;
    int index;
    REGSAM mode = 0;
    const char *errString = NULL;

    static const char *const subcommands[] = {
	"broadcast", "delete", "get", "keys", "set", "type", "values", NULL
    };
    enum SubCmdIdx {
373
374
375
376
377
378
379
380

381
382
383
384
385
386
387
383
384
385
386
387
388
389

390
391
392
393
394
395
396
397







-
+







	    HKEY key;

	    /*
	     * Create the key and then close it immediately.
	     */

	    mode |= KEY_ALL_ACCESS;
	    if (OpenKey(interp, objv[n], mode, 1, &key) != TCL_OK) {
	    if (OpenKey(interp, objv[n], mode, REG_CREATE, &key) != TCL_OK) {
		return TCL_ERROR;
	    }
	    RegCloseKey(key);
	    return TCL_OK;
	} else if (argc == 3) {
	    return SetValue(interp, objv[n], objv[n+1], objv[n+2], NULL,
		    mode);
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
444
445
446
447
448
449
450
451
452
453
454
455
456


457
458
459
460
461
462
463
464
465
466
467
468
469

470
471
472
473
474
475
476
477







+





-
-
+
+











-
+







{
    char *tail, *buffer, *hostName, *keyName;
    const WCHAR *nativeTail;
    HKEY rootKey, subkey;
    DWORD result;
    Tcl_DString buf;
    REGSAM saveMode = mode;
    Tcl_Size len;

    /*
     * Find the parent of the key being deleted and open it.
     */

    keyName = Tcl_GetString(keyNameObj);
    buffer = (char *)Tcl_Alloc(keyNameObj->length + 1);
    keyName = Tcl_GetStringFromObj(keyNameObj, &len);
    buffer = (char *)Tcl_Alloc(len + 1);
    strcpy(buffer, keyName);

    if (ParseKeyName(interp, buffer, &hostName, &rootKey,
	    &keyName) != TCL_OK) {
	Tcl_Free(buffer);
	return TCL_ERROR;
    }

    if (*keyName == '\0') {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("bad key: cannot delete root keys", -1));
	Tcl_SetErrorCode(interp, "WIN_REG", "DEL_ROOT_KEY", NULL);
	Tcl_SetErrorCode(interp, "WIN_REG", "DEL_ROOT_KEY", (char *)NULL);
	Tcl_Free(buffer);
	return TCL_ERROR;
    }

    tail = strrchr(keyName, '\\');
    if (tail) {
	*tail++ = '\0';
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
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556

557
558

559
560
561
562
563
564
565
566







+










-
+

-
+







    Tcl_Obj *valueNameObj,	/* Name of value to delete. */
    REGSAM mode)		/* Mode flags to pass. */
{
    HKEY key;
    char *valueName;
    DWORD result;
    Tcl_DString ds;
    Tcl_Size len;

    /*
     * Attempt to open the key for deletion.
     */

    mode |= KEY_SET_VALUE;
    if (OpenKey(interp, keyNameObj, mode, 0, &key) != TCL_OK) {
	return TCL_ERROR;
    }

    valueName = Tcl_GetString(valueNameObj);
    valueName = Tcl_GetStringFromObj(valueNameObj, &len);
    Tcl_DStringInit(&ds);
    Tcl_UtfToWCharDString(valueName, valueNameObj->length, &ds);
    Tcl_UtfToWCharDString(valueName, len, &ds);
    result = RegDeleteValueW(key, (const WCHAR *)Tcl_DStringValue(&ds));
    Tcl_DStringFree(&ds);
    if (result != ERROR_SUCCESS) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"unable to delete value \"%s\" from key \"%s\": ",
		Tcl_GetString(valueNameObj), Tcl_GetString(keyNameObj)));
	AppendSystemError(interp, result);
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
707
708
709
710
711
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714

715
716

717
718
719
720
721
722
723
724







+














-
+

-
+







    REGSAM mode)		/* Mode flags to pass. */
{
    HKEY key;
    DWORD result, type;
    Tcl_DString ds;
    const char *valueName;
    const WCHAR *nativeValue;
    Tcl_Size len;

    /*
     * Attempt to open the key for reading.
     */

    mode |= KEY_QUERY_VALUE;
    if (OpenKey(interp, keyNameObj, mode, 0, &key) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Get the type of the value.
     */

    valueName = Tcl_GetString(valueNameObj);
    valueName = Tcl_GetStringFromObj(valueNameObj, &len);
    Tcl_DStringInit(&ds);
    nativeValue = Tcl_UtfToWCharDString(valueName, valueNameObj->length, &ds);
    nativeValue = Tcl_UtfToWCharDString(valueName, len, &ds);
    result = RegQueryValueExW(key, nativeValue, NULL, &type,
	    NULL, NULL);
    Tcl_DStringFree(&ds);
    RegCloseKey(key);

    if (result != ERROR_SUCCESS) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
753
754
755
756
757
758
759

760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776

777
778
779
780
781
782
783
784

785
786

787
788
789
790
791
792
793
794
795
796
797
798

799
800
801
802
803
804
805
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789

790
791
792
793
794
795
796
797

798
799

800
801
802
803
804
805
806
807
808
809
810
811

812
813
814
815
816
817
818
819







+
















-
+







-
+

-
+











-
+







    REGSAM mode)		/* Mode flags to pass. */
{
    HKEY key;
    const char *valueName;
    const WCHAR *nativeValue;
    DWORD result, length, type;
    Tcl_DString data, buf;
    Tcl_Size len;

    /*
     * Attempt to open the key for reading.
     */

    mode |= KEY_QUERY_VALUE;
    if (OpenKey(interp, keyNameObj, mode, 0, &key) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Initialize a Dstring to maximum statically allocated size we could get
     * one more byte by avoiding Tcl_DStringSetLength() and just setting
     * length to TCL_DSTRING_STATIC_SIZE, but this should be safer if the
     * implementation of Dstrings changes.
     *
     * This allows short values to be read from the registy in one call.
     * This allows short values to be read from the registry in one call.
     * Longer values need a second call with an expanded DString.
     */

    Tcl_DStringInit(&data);
    Tcl_DStringSetLength(&data, TCL_DSTRING_STATIC_SIZE - 1);
    length = TCL_DSTRING_STATIC_SIZE/sizeof(WCHAR) - 1;

    valueName = Tcl_GetString(valueNameObj);
    valueName = Tcl_GetStringFromObj(valueNameObj, &len);
    Tcl_DStringInit(&buf);
    nativeValue = Tcl_UtfToWCharDString(valueName, valueNameObj->length, &buf);
    nativeValue = Tcl_UtfToWCharDString(valueName, len, &buf);

    result = RegQueryValueExW(key, nativeValue, NULL, &type,
	    (BYTE *) Tcl_DStringValue(&data), &length);
    while (result == ERROR_MORE_DATA) {
	/*
	 * The Windows docs say that in this error case, we just need to
	 * expand our buffer and request more data. Required for
	 * HKEY_PERFORMANCE_DATA
	 */

	length = Tcl_DStringLength(&data) * (2 / sizeof(WCHAR));
	Tcl_DStringSetLength(&data, (int) length * sizeof(WCHAR));
	Tcl_DStringSetLength(&data, length * sizeof(WCHAR));
	result = RegQueryValueExW(key, nativeValue,
		NULL, &type, (BYTE *) Tcl_DStringValue(&data), &length);
    }
    Tcl_DStringFree(&buf);
    RegCloseKey(key);
    if (result != ERROR_SUCCESS) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
836
837
838
839
840
841
842
843

844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859

860
861
862
863
864
865
866
867
868
869
870

871
872
873
874
875
876
877
850
851
852
853
854
855
856

857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872

873
874
875
876
877
878
879
880
881
882
883

884
885
886
887
888
889
890
891







-
+















-
+










-
+








	    Tcl_DStringInit(&buf);
	    Tcl_WCharToUtfDString(wp, wcslen(wp), &buf);
	    Tcl_ListObjAppendElement(interp, resultPtr,
		    Tcl_NewStringObj(Tcl_DStringValue(&buf),
			    Tcl_DStringLength(&buf)));

	    while (*wp++ != 0) {/* empty body */}
	    while (*wp++ != 0); /* empty loop body */
	    p = (char *) wp;
	    Tcl_DStringFree(&buf);
	}
	Tcl_SetObjResult(interp, resultPtr);
    } else if ((type == REG_SZ) || (type == REG_EXPAND_SZ)) {
	WCHAR *wp = (WCHAR *) Tcl_DStringValue(&data);
	Tcl_DStringInit(&buf);
	Tcl_WCharToUtfDString((const WCHAR *)Tcl_DStringValue(&data), wcslen(wp), &buf);
	Tcl_DStringResult(interp, &buf);
    } else {
	/*
	 * Save binary data as a byte array.
	 */

	Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(
		(BYTE *) Tcl_DStringValue(&data), (int) length));
		(BYTE *) Tcl_DStringValue(&data), length));
    }
    Tcl_DStringFree(&data);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * GetValueNames --
 *
 *	This function enumerates the values of the a given key. If the
 *	This function enumerates the values of the given key. If the
 *	optional pattern is supplied, then only value names that match the
 *	pattern will be returned.
 *
 * Results:
 *	Returns the list of value names in the result object of the
 *	interpreter, or an error message on failure.
 *
901
902
903
904
905
906
907
908

909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
915
916
917
918
919
920
921

922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940

941
942
943
944
945
946
947







-
+


















-







    mode |= KEY_QUERY_VALUE;
    if (OpenKey(interp, keyNameObj, mode, 0, &key) != TCL_OK) {
	return TCL_ERROR;
    }

    resultPtr = Tcl_NewObj();
    Tcl_DStringInit(&buffer);
    Tcl_DStringSetLength(&buffer, (int) (MAX_KEY_LENGTH * sizeof(WCHAR)));
    Tcl_DStringSetLength(&buffer, MAX_KEY_LENGTH * sizeof(WCHAR));
    index = 0;
    result = TCL_OK;

    if (patternObj) {
	pattern = Tcl_GetString(patternObj);
    } else {
	pattern = NULL;
    }

    /*
     * Enumerate the values under the given subkey until we get an error,
     * indicating the end of the list. Note that we need to reset size after
     * each iteration because RegEnumValue smashes the old value.
     */

    size = MAX_KEY_LENGTH;
    while (RegEnumValueW(key,index, (WCHAR *)Tcl_DStringValue(&buffer),
	    &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {

	Tcl_DStringInit(&ds);
	Tcl_WCharToUtfDString((const WCHAR *)Tcl_DStringValue(&buffer), size, &ds);
	name = Tcl_DStringValue(&ds);
	if (!pattern || Tcl_StringMatch(name, pattern)) {
	    result = Tcl_ListObjAppendElement(interp, resultPtr,
		    Tcl_NewStringObj(name, Tcl_DStringLength(&ds)));
	    if (result != TCL_OK) {
971
972
973
974
975
976
977

978
979
980


981
982
983
984
985
986
987
984
985
986
987
988
989
990
991
992


993
994
995
996
997
998
999
1000
1001







+

-
-
+
+







    REGSAM mode,		/* Access mode. */
    int flags,			/* 0 or REG_CREATE. */
    HKEY *keyPtr)		/* Returned HKEY. */
{
    char *keyName, *buffer, *hostName;
    HKEY rootKey;
    DWORD result;
    Tcl_Size len;

    keyName = Tcl_GetString(keyNameObj);
    buffer = (char *)Tcl_Alloc(keyNameObj->length + 1);
    keyName = Tcl_GetStringFromObj(keyNameObj, &len);
    buffer = (char *)Tcl_Alloc(len + 1);
    strcpy(buffer, keyName);

    result = ParseKeyName(interp, buffer, &hostName, &rootKey, &keyName);
    if (result == TCL_OK) {
	result = OpenSubKey(hostName, rootKey, keyName, mode, flags, keyPtr);
	if (result != ERROR_SUCCESS) {
	    Tcl_SetObjResult(interp,
998
999
1000
1001
1002
1003
1004
1005

1006
1007
1008
1009
1010
1011
1012
1012
1013
1014
1015
1016
1017
1018

1019
1020
1021
1022
1023
1024
1025
1026







-
+







}

/*
 *----------------------------------------------------------------------
 *
 * OpenSubKey --
 *
 *	This function opens a given subkey of a root key on the specified
 *	Opens a given subkey of the given root key on the specified
 *	host.
 *
 * Results:
 *	Returns the opened key in the keyPtr and a Windows error code as the
 *	return value.
 *
 * Side effects:
1083
1084
1085
1086
1087
1088
1089
1090

1091
1092
1093
1094
1095
1096
1097
1097
1098
1099
1100
1101
1102
1103

1104
1105
1106
1107
1108
1109
1110
1111







-
+







}

/*
 *----------------------------------------------------------------------
 *
 * ParseKeyName --
 *
 *	This function parses a key name into the host, root, and subkey parts.
 *	Parses a key name into the host, root, and subkey parts.
 *
 * Results:
 *	The pointers to the start of the host and subkey names are returned in
 *	the hostNamePtr and keyNamePtr variables. The specified root HKEY is
 *	returned in rootKeyPtr. Returns a standard Tcl result.
 *
 * Side effects:
1129
1130
1131
1132
1133
1134
1135
1136

1137
1138
1139
1140
1141
1142
1143
1143
1144
1145
1146
1147
1148
1149

1150
1151
1152
1153
1154
1155
1156
1157







-
+







	}
    } else {
	rootName = name;
    }
    if (!rootName) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"bad key \"%s\": must start with a valid root", name));
	Tcl_SetErrorCode(interp, "WIN_REG", "NO_ROOT_KEY", NULL);
	Tcl_SetErrorCode(interp, "WIN_REG", "NO_ROOT_KEY", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Split the root into root and subkey portions.
     */

1207
1208
1209
1210
1211
1212
1213
1214

1215
1216
1217
1218
1219
1220
1221
1221
1222
1223
1224
1225
1226
1227

1228
1229
1230
1231
1232
1233
1234
1235







-
+







    mode |= KEY_ENUMERATE_SUB_KEYS | DELETE | KEY_QUERY_VALUE;
    result = RegOpenKeyExW(startKey, keyName, 0, mode, &hKey);
    if (result != ERROR_SUCCESS) {
	return result;
    }

    Tcl_DStringInit(&subkey);
    Tcl_DStringSetLength(&subkey, (int) (MAX_KEY_LENGTH * sizeof(WCHAR)));
    Tcl_DStringSetLength(&subkey, MAX_KEY_LENGTH * sizeof(WCHAR));

    mode = saveMode;
    while (result == ERROR_SUCCESS) {
	/*
	 * Always get index 0 because key deletion changes ordering.
	 */

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
1354
1355
1356
1357
1358
1359

1360
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
1387
1388
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
1354

1355
1356
1357
1358
1359
1360
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
1387
1388
1389

1390
1391
1392
1393
1394
1395

1396
1397
1398
1399
1400
1401
1402
1403







+











-
+



-
+

-
+















-
+
















-
+

-
+


















-
+


-
+












-
+





-
+







    REGSAM mode)		/* Mode flags to pass. */
{
    int type;
    DWORD result;
    HKEY key;
    const char *valueName;
    Tcl_DString nameBuf;
    Tcl_Size len;

    if (typeObj == NULL) {
	type = REG_SZ;
    } else if (Tcl_GetIndexFromObj(interp, typeObj, typeNames, "type",
	    0, (int *) &type) != TCL_OK) {
	if (Tcl_GetIntFromObj(NULL, typeObj, (int *) &type) != TCL_OK) {
	    return TCL_ERROR;
	}
	Tcl_ResetResult(interp);
    }
    mode |= KEY_ALL_ACCESS;
    if (OpenKey(interp, keyNameObj, mode, 1, &key) != TCL_OK) {
    if (OpenKey(interp, keyNameObj, mode, REG_CREATE, &key) != TCL_OK) {
	return TCL_ERROR;
    }

    valueName = Tcl_GetString(valueNameObj);
    valueName = Tcl_GetStringFromObj(valueNameObj, &len);
    Tcl_DStringInit(&nameBuf);
    valueName = (char *) Tcl_UtfToWCharDString(valueName, valueNameObj->length, &nameBuf);
    valueName = (char *) Tcl_UtfToWCharDString(valueName, len, &nameBuf);

    if (type == REG_DWORD || type == REG_DWORD_BIG_ENDIAN) {
	int value;

	if (Tcl_GetIntFromObj(interp, dataObj, &value) != TCL_OK) {
	    RegCloseKey(key);
	    Tcl_DStringFree(&nameBuf);
	    return TCL_ERROR;
	}

	value = ConvertDWORD((DWORD) type, (DWORD) value);
	result = RegSetValueExW(key, (WCHAR *) valueName, 0,
		(DWORD) type, (BYTE *) &value, sizeof(DWORD));
    } else if (type == REG_MULTI_SZ) {
	Tcl_DString data, buf;
	int objc, i;
	Tcl_Size objc, i;
	Tcl_Obj **objv;

	if (Tcl_ListObjGetElements(interp, dataObj, &objc, &objv) != TCL_OK) {
	    RegCloseKey(key);
	    Tcl_DStringFree(&nameBuf);
	    return TCL_ERROR;
	}

	/*
	 * Append the elements as null terminated strings. Note that we must
	 * not assume the length of the string in case there are embedded
	 * nulls, which aren't allowed in REG_MULTI_SZ values.
	 */

	Tcl_DStringInit(&data);
	for (i = 0; i < objc; i++) {
	    const char *bytes = Tcl_GetString(objv[i]);
	    const char *bytes = Tcl_GetStringFromObj(objv[i], &len);

	    Tcl_DStringAppend(&data, bytes, objv[i]->length);
	    Tcl_DStringAppend(&data, bytes, len);

	    /*
	     * Add a null character to separate this value from the next.
	     */

	    Tcl_DStringAppend(&data, "", 1);	/* NUL-terminated string */
	}

	Tcl_DStringInit(&buf);
	Tcl_UtfToWCharDString(Tcl_DStringValue(&data), Tcl_DStringLength(&data)+1,
		&buf);
	result = RegSetValueExW(key, (WCHAR *) valueName, 0,
		(DWORD) type, (BYTE *) Tcl_DStringValue(&buf),
		(DWORD) Tcl_DStringLength(&buf));
	Tcl_DStringFree(&data);
	Tcl_DStringFree(&buf);
    } else if (type == REG_SZ || type == REG_EXPAND_SZ) {
	Tcl_DString buf;
	const char *data = Tcl_GetString(dataObj);
	const char *data = Tcl_GetStringFromObj(dataObj, &len);

	Tcl_DStringInit(&buf);
	data = (char *) Tcl_UtfToWCharDString(data, dataObj->length, &buf);
	data = (char *) Tcl_UtfToWCharDString(data, len, &buf);

	/*
	 * Include the null in the length, padding if needed for WCHAR.
	 */

	Tcl_DStringSetLength(&buf, Tcl_DStringLength(&buf)+1);

	result = RegSetValueExW(key, (WCHAR *) valueName, 0,
		(DWORD) type, (BYTE *) data, (DWORD) Tcl_DStringLength(&buf) + 1);
	Tcl_DStringFree(&buf);
    } else {
	BYTE *data;
	size_t bytelength;
	Tcl_Size bytelength;

	/*
	 * Store binary data in the registry.
	 */

	data = (BYTE *) getByteArrayFromObj(dataObj, &bytelength);
	data = (BYTE *) Tcl_GetByteArrayFromObj(dataObj, &bytelength);
	result = RegSetValueExW(key, (WCHAR *) valueName, 0,
		(DWORD) type, data, (DWORD) bytelength);
    }

    Tcl_DStringFree(&nameBuf);
    RegCloseKey(key);

1411
1412
1413
1414
1415
1416
1417
1418

1419
1420
1421
1422
1423
1424

1425
1426
1427
1428
1429
1430
1431

1432
1433
1434
1435
1436
1437
1438
1439
1440
1441

1442
1443

1444
1445
1446
1447
1448
1449
1450
1426
1427
1428
1429
1430
1431
1432

1433
1434
1435
1436
1437
1438

1439
1440
1441
1442
1443
1444
1445

1446

1447
1448
1449
1450
1451
1452
1453
1454

1455
1456

1457
1458
1459
1460
1461
1462
1463
1464







-
+





-
+






-
+
-








-
+

-
+







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

static int
BroadcastValue(
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Size objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    LRESULT result;
    DWORD_PTR sendResult;
    int timeout = 3000;
    size_t len;
    Tcl_Size len;
    const char *str;
    Tcl_Obj *objPtr;
    WCHAR *wstr;
    Tcl_DString ds;

    if (objc == 3) {
	str = Tcl_GetString(objv[1]);
	str = Tcl_GetStringFromObj(objv[1], &len);
	len = objv[1]->length;
	if ((len < 2) || (*str != '-') || strncmp(str, "-timeout", len)) {
	    return TCL_BREAK;
	}
	if (Tcl_GetIntFromObj(interp, objv[2], &timeout) != TCL_OK) {
	    return TCL_ERROR;
	}
    }

    str = Tcl_GetString(objv[0]);
    str = Tcl_GetStringFromObj(objv[0], &len);
    Tcl_DStringInit(&ds);
    wstr = Tcl_UtfToWCharDString(str, objv[0]->length, &ds);
    wstr = Tcl_UtfToWCharDString(str, len, &ds);
    if (Tcl_DStringLength(&ds) == 0) {
	wstr = NULL;
    }

    /*
     * Use the ignore the result.
     */
1462
1463
1464
1465
1466
1467
1468
1469

1470
1471
1472
1473
1474
1475
1476
1476
1477
1478
1479
1480
1481
1482

1483
1484
1485
1486
1487
1488
1489
1490







-
+







}

/*
 *----------------------------------------------------------------------
 *
 * AppendSystemError --
 *
 *	This routine formats a Windows system error message and places it into
 *	Formats a Windows system error message and places it into
 *	the interpreter result.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
1494
1495
1496
1497
1498
1499
1500
1501

1502
1503
1504
1505
1506
1507
1508
1508
1509
1510
1511
1512
1513
1514

1515
1516
1517
1518
1519
1520
1521
1522







-
+







	resultPtr = Tcl_DuplicateObj(resultPtr);
    }
    length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM
	    | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, error,
	    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (WCHAR *) tMsgPtrPtr,
	    0, NULL);
    if (length == 0) {
	sprintf(msgBuf, "unknown error: %ld", error);
	snprintf(msgBuf, sizeof(msgBuf), "unknown error: %ld", error);
	msg = msgBuf;
    } else {
	char *msgPtr;

	Tcl_DStringInit(&ds);
	Tcl_WCharToUtfDString(tMsgPtr, wcslen(tMsgPtr), &ds);
	LocalFree(tMsgPtr);
1520
1521
1522
1523
1524
1525
1526
1527
1528


1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542

1543
1544
1545
1546
1547
1548
1549
1534
1535
1536
1537
1538
1539
1540


1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555

1556
1557
1558
1559
1560
1561
1562
1563







-
-
+
+













-
+







	if (msgPtr[length-1] == '\r') {
	    --length;
	}
	msgPtr[length] = 0;
	msg = msgPtr;
    }

    sprintf(id, "%ld", error);
    Tcl_SetErrorCode(interp, "WINDOWS", id, msg, NULL);
    snprintf(id, sizeof(id), "%ld", error);
    Tcl_SetErrorCode(interp, "WINDOWS", id, msg, (char *)NULL);
    Tcl_AppendToObj(resultPtr, msg, length);
    Tcl_SetObjResult(interp, resultPtr);

    if (length != 0) {
	Tcl_DStringFree(&ds);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ConvertDWORD --
 *
 *	This function determines whether a DWORD needs to be byte swapped, and
 *	Determines whether a DWORD needs to be byte swapped, and
 *	returns the appropriately swapped value.
 *
 * Results:
 *	Returns a converted DWORD.
 *
 * Side effects:
 *	None.

Changes to win/tclWinSerial.c.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tclWinSerial.c --
 *
 *	This file implements the Windows-specific serial port functions, and
 *	the "serial" channel driver.
 *
 * Copyright (c) 1999 by Scriptics Corp.
 * Copyright © 1999 Scriptics Corp.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * Serial functionality implemented by Rolf.Schroedter@dlr.de
 */

81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
81
82
83
84
85
86
87

88
89
90
91
92
93
94
95







-
+







    int watchMask;		/* OR'ed combination of TCL_READABLE,
				 * TCL_WRITABLE, or TCL_EXCEPTION: indicates
				 * which events should be reported. */
    int flags;			/* State flags, see above for a list. */
    int readable;		/* Flag that the channel is readable. */
    int writable;		/* Flag that the channel is writable. */
    int blockTime;		/* Maximum blocktime in msec. */
    unsigned int lastEventTime;	/* Time in milliseconds since last readable
    unsigned long long lastEventTime;	/* Time in milliseconds since last readable
				 * event. */
				/* Next readable event only after blockTime */
    DWORD error;		/* pending error code returned by
				 * ClearCommError() */
    DWORD lastError;		/* last error code, can be fetched with
				 * fconfigure chan -lasterror */
    DWORD sysBufRead;		/* Win32 system buffer size for read ops,
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
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







-
-
-
+
+
+


-
-
-
+
+
+

-
+

-
+

-
-
-
-
+
+
+
+


-
+



-
+













-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    0,			/* WriteTotalTimeoutConstant */
};

/*
 * Declarations for functions used only in this file.
 */

static int		SerialBlockProc(ClientData instanceData, int mode);
static void		SerialCheckProc(ClientData clientData, int flags);
static int		SerialCloseProc(ClientData instanceData,
static int		SerialBlockProc(void *instanceData, int mode);
static void		SerialCheckProc(void *clientData, int flags);
static int		SerialCloseProc(void *instanceData,
			    Tcl_Interp *interp, int flags);
static int		SerialEventProc(Tcl_Event *evPtr, int flags);
static void		SerialExitHandler(ClientData clientData);
static int		SerialGetHandleProc(ClientData instanceData,
			    int direction, ClientData *handlePtr);
static void		SerialExitHandler(void *clientData);
static int		SerialGetHandleProc(void *instanceData,
			    int direction, void **handlePtr);
static ThreadSpecificData *SerialInit(void);
static int		SerialInputProc(ClientData instanceData, char *buf,
static int		SerialInputProc(void *instanceData, char *buf,
			    int toRead, int *errorCode);
static int		SerialOutputProc(ClientData instanceData,
static int		SerialOutputProc(void *instanceData,
			    const char *buf, int toWrite, int *errorCode);
static void		SerialSetupProc(ClientData clientData, int flags);
static void		SerialWatchProc(ClientData instanceData, int mask);
static void		ProcExitHandler(ClientData clientData);
static int		SerialGetOptionProc(ClientData instanceData,
static void		SerialSetupProc(void *clientData, int flags);
static void		SerialWatchProc(void *instanceData, int mask);
static void		ProcExitHandler(void *clientData);
static int		SerialGetOptionProc(void *instanceData,
			    Tcl_Interp *interp, const char *optionName,
			    Tcl_DString *dsPtr);
static int		SerialSetOptionProc(ClientData instanceData,
static int		SerialSetOptionProc(void *instanceData,
			    Tcl_Interp *interp, const char *optionName,
			    const char *value);
static DWORD WINAPI	SerialWriterThread(LPVOID arg);
static void		SerialThreadActionProc(ClientData instanceData,
static void		SerialThreadActionProc(void *instanceData,
			    int action);
static int		SerialBlockingRead(SerialInfo *infoPtr, LPVOID buf,
			    DWORD bufSize, LPDWORD lpRead, LPOVERLAPPED osPtr);
static int		SerialBlockingWrite(SerialInfo *infoPtr, LPVOID buf,
			    DWORD bufSize, LPDWORD lpWritten,
			    LPOVERLAPPED osPtr);

/*
 * This structure describes the channel type structure for command serial
 * based IO.
 */

static const Tcl_ChannelType serialChannelType = {
    "serial",			/* Type name. */
    TCL_CHANNEL_VERSION_5,	/* v5 channel */
    NULL,		/* Close proc. */
    SerialInputProc,		/* Input proc. */
    SerialOutputProc,		/* Output proc. */
    NULL,			/* Seek proc. */
    SerialSetOptionProc,	/* Set option proc. */
    SerialGetOptionProc,	/* Get option proc. */
    SerialWatchProc,		/* Set up notifier to watch the channel. */
    SerialGetHandleProc,	/* Get an OS handle from channel. */
    SerialCloseProc,		/* close2proc. */
    SerialBlockProc,		/* Set blocking or non-blocking mode.*/
    NULL,			/* flush proc. */
    NULL,			/* handler proc. */
    NULL,			/* wide seek proc */
    SerialThreadActionProc,	/* thread action proc */
    NULL                       /* truncate */
    "serial",
    TCL_CHANNEL_VERSION_5,
    NULL,			/* Deprecated. */
    SerialInputProc,
    SerialOutputProc,
    NULL,			/* Deprecated. */
    SerialSetOptionProc,
    SerialGetOptionProc,
    SerialWatchProc,
    SerialGetHandleProc,
    SerialCloseProc,
    SerialBlockProc,
    NULL,			/* Flush proc. */
    NULL,			/* Bubbled event handler proc. */
    NULL,			/* Seek proc. */
    SerialThreadActionProc,
    NULL			/* Truncate proc. */
};

/*
 *----------------------------------------------------------------------
 *
 * SerialInit --
 *
281
282
283
284
285
286
287
288

289
290
291
292
293
294
295
281
282
283
284
285
286
287

288
289
290
291
292
293
294
295







-
+







 *	Removes the serial event source.
 *
 *----------------------------------------------------------------------
 */

static void
SerialExitHandler(
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    SerialInfo *infoPtr;

    /*
     * Clear all eventually pending output. Otherwise Tcl's exit could totally
     * block, because it performs a blocking flush on all open channels. Note
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
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







-
+











-
+







 *	Resets the process list.
 *
 *----------------------------------------------------------------------
 */

static void
ProcExitHandler(
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    Tcl_MutexLock(&serialMutex);
    initialized = 0;
    Tcl_MutexUnlock(&serialMutex);
}

/*
 *----------------------------------------------------------------------
 *
 * SerialBlockTime --
 *
 *	Wrapper to set Tcl's block time in msec
 *	Wrapper to set Tcl's block time in msec.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Updates the maximum blocking time.
 *
369
370
371
372
373
374
375
376

377
378
379
380
381
382
383

384
385
386
387
388
389
390
369
370
371
372
373
374
375

376
377
378
379
380
381
382

383
384
385
386
387
388
389
390







-
+






-
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static unsigned int
static unsigned long long
SerialGetMilliseconds(void)
{
    Tcl_Time time;

    Tcl_GetTime(&time);

    return (time.sec * 1000 + time.usec / 1000);
    return ((unsigned long long)time.sec * 1000 + (unsigned long)time.usec / 1000);
}

/*
 *----------------------------------------------------------------------
 *
 * SerialSetupProc --
 *
402
403
404
405
406
407
408
409

410
411
412
413
414
415
416
402
403
404
405
406
407
408

409
410
411
412
413
414
415
416







-
+








#ifdef __cplusplus
#define min(a, b)  (((a) < (b)) ? (a) : (b))
#endif

void
SerialSetupProc(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */
{
    SerialInfo *infoPtr;
    int block = 1;
    int msec = INT_MAX;		/* min. found block time */
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

457
458
459
460
461
462
463
464

465
466
467
468
469
470
471
472

473
474
475
476
477
478
479
457
458
459
460
461
462
463

464
465
466
467
468
469
470
471

472
473
474
475
476
477
478
479







-
+







-
+







 *	May queue an event.
 *
 *----------------------------------------------------------------------
 */

static void
SerialCheckProc(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */
{
    SerialInfo *infoPtr;
    SerialEvent *evPtr;
    int needEvent;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    COMSTAT cStat;
    unsigned int time;
    unsigned long long time;

    if (!(flags & TCL_FILE_EVENTS)) {
	return;
    }

    /*
     * Queue events for any ready serials that don't already have events
515
516
517
518
519
520
521
522
523


524
525
526
527
528
529
530
515
516
517
518
519
520
521


522
523
524
525
526
527
528
529
530







-
-
+
+







		     * Force fileevent after serial read error.
		     */

		    if ((cStat.cbInQue > 0) ||
			    (infoPtr->error & SERIAL_READ_ERRORS)) {
			infoPtr->readable = 1;
			time = SerialGetMilliseconds();
			if ((unsigned int) (time - infoPtr->lastEventTime)
				>= (unsigned int) infoPtr->blockTime) {
			if ((time - infoPtr->lastEventTime)
				>= (unsigned long long) infoPtr->blockTime) {
			    needEvent = 1;
			    infoPtr->lastEventTime = time;
			}
		    }
		}
	    }
	}
557
558
559
560
561
562
563
564

565
566
567
568
569
570
571
557
558
559
560
561
562
563

564
565
566
567
568
569
570
571







-
+







 *	Sets the device into blocking or non-blocking mode.
 *
 *----------------------------------------------------------------------
 */

static int
SerialBlockProc(
    ClientData instanceData,    /* Instance data for channel. */
    void *instanceData,    /* Instance data for channel. */
    int mode)			/* TCL_MODE_BLOCKING or
				 * TCL_MODE_NONBLOCKING. */
{
    int errorCode = 0;
    SerialInfo *infoPtr = (SerialInfo *) instanceData;

    /*
596
597
598
599
600
601
602
603

604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624

625
626
627
628
629
630
631
596
597
598
599
600
601
602

603
604
605
606
607
608
609
610
611
612
613
614
615

616
617
618
619
620
621
622

623
624
625
626
627
628
629
630







-
+












-







-
+







 *	Closes the physical channel.
 *
 *----------------------------------------------------------------------
 */

static int
SerialCloseProc(
    ClientData instanceData,    /* Pointer to SerialInfo structure. */
    void *instanceData,    /* Pointer to SerialInfo structure. */
    TCL_UNUSED(Tcl_Interp *),
    int flags)
{
    SerialInfo *serialPtr = (SerialInfo *) instanceData;
    int errorCode = 0, result = 0;
    SerialInfo *infoPtr, **nextPtrPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
	return EINVAL;
    }


    if (serialPtr->validMask & TCL_READABLE) {
	PurgeComm(serialPtr->handle, PURGE_RXABORT | PURGE_RXCLEAR);
	CloseHandle(serialPtr->osRead.hEvent);
    }
    serialPtr->validMask &= ~TCL_READABLE;

    if (serialPtr->writeThread) {
    	TclPipeThreadStop(&serialPtr->writeTI, serialPtr->writeThread);
	TclPipeThreadStop(&serialPtr->writeTI, serialPtr->writeThread);

	CloseHandle(serialPtr->osWrite.hEvent);
	CloseHandle(serialPtr->evWritable);
	CloseHandle(serialPtr->writeThread);
	serialPtr->writeThread = NULL;

	PurgeComm(serialPtr->handle, PURGE_TXABORT | PURGE_TXCLEAR);
641
642
643
644
645
646
647
648

649
650
651
652
653
654
655
640
641
642
643
644
645
646

647
648
649
650
651
652
653
654







-
+







     */

    if (!TclInThreadExit()
	    || ((GetStdHandle(STD_INPUT_HANDLE) != serialPtr->handle)
	    && (GetStdHandle(STD_OUTPUT_HANDLE) != serialPtr->handle)
	    && (GetStdHandle(STD_ERROR_HANDLE) != serialPtr->handle))) {
	if (CloseHandle(serialPtr->handle) == FALSE) {
	    TclWinConvertError(GetLastError());
	    Tcl_WinConvertError(GetLastError());
	    errorCode = errno;
	}
    }

    serialPtr->watchMask &= serialPtr->validMask;

    /*
792
793
794
795
796
797
798
799

800
801
802
803
804
805
806
791
792
793
794
795
796
797

798
799
800
801
802
803
804
805







-
+







     */

    osPtr->Offset = osPtr->OffsetHigh = 0;
    result = WriteFile(infoPtr->handle, buf, bufSize, lpWritten, osPtr);
    LeaveCriticalSection(&infoPtr->csWrite);

    if (result == FALSE) {
	int err = GetLastError();
	DWORD err = GetLastError();

	switch (err) {
	case ERROR_IO_PENDING:
	    /*
	     * Write is pending, wait for completion.
	     */

851
852
853
854
855
856
857
858

859
860
861
862
863
864
865
850
851
852
853
854
855
856

857
858
859
860
861
862
863
864







-
+







 *	Reads input from the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
SerialInputProc(
    ClientData instanceData,	/* Serial state. */
    void *instanceData,	/* Serial state. */
    char *buf,			/* Where to store data read. */
    int bufSize,		/* How much space is available in the
				 * buffer? */
    int *errorCode)		/* Where to store error code. */
{
    SerialInfo *infoPtr = (SerialInfo *) instanceData;
    DWORD bytesRead = 0;
900
901
902
903
904
905
906
907

908
909
910
911
912
913
914
915
916
917
918
919
920
921

922
923
924
925
926
927
928
929
930
931

932
933
934
935
936
937
938
899
900
901
902
903
904
905

906
907
908
909
910
911
912
913
914
915
916
917
918
919

920
921
922
923
924
925
926
927
928
929

930
931
932
933
934
935
936
937







-
+













-
+









-
+







		}
	    } else {
		errno = *errorCode = EWOULDBLOCK;
		return -1;
	    }
	} else {
	    /*
	     * BLOCKING mode: Tcl trys to read a full buffer of 4 kBytes here.
	     * BLOCKING mode: Tcl tries to read a full buffer of 4 kBytes here.
	     */

	    if (cStat.cbInQue > 0) {
		if ((DWORD) bufSize > cStat.cbInQue) {
		    bufSize = cStat.cbInQue;
		}
	    } else {
		bufSize = 1;
	    }
	}
    }

    if (bufSize == 0) {
	return bytesRead = 0;
	return 0;
    }

    /*
     * Perform blocking read. Doesn't block in non-blocking mode, because we
     * checked the number of available bytes.
     */

    if (SerialBlockingRead(infoPtr, (LPVOID) buf, (DWORD) bufSize, &bytesRead,
	    &infoPtr->osRead) == FALSE) {
	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	*errorCode = errno;
	return -1;
    }
    return bytesRead;

  commError:
    infoPtr->lastError = infoPtr->error;
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
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







-
+










-
+

-
+







 *	Writes output on the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
SerialOutputProc(
    ClientData instanceData,	/* Serial state. */
    void *instanceData,	/* Serial state. */
    const char *buf,		/* The data buffer. */
    int toWrite,		/* How many bytes to write? */
    int *errorCode)		/* Where to store error code. */
{
    SerialInfo *infoPtr = (SerialInfo *) instanceData;
    DWORD bytesWritten, timeout;

    *errorCode = 0;

    /*
     * At EXIT Tcl trys to flush all open channels in blocking mode. We avoid
     * At EXIT Tcl tries to flush all open channels in blocking mode. We avoid
     * blocking output after ExitProc or CloseHandler(chan) has been called by
     * checking the corrresponding variables.
     * checking the corresponding variables.
     */

    if (!initialized || TclInExit()) {
	return toWrite;
    }

    /*
1006
1007
1008
1009
1010
1011
1012
1013

1014
1015
1016
1017
1018
1019
1020
1005
1006
1007
1008
1009
1010
1011

1012
1013
1014
1015
1016
1017
1018
1019







-
+







    }

    /*
     * Check for a background error on the last write.
     */

    if (infoPtr->writeError) {
	TclWinConvertError(infoPtr->writeError);
	Tcl_WinConvertError(infoPtr->writeError);
	infoPtr->writeError = 0;
	goto error1;
    }

    /*
     * Remember the number of bytes in output queue
     */
1065
1066
1067
1068
1069
1070
1071
1072

1073
1074
1075
1076
1077
1078
1079
1064
1065
1066
1067
1068
1069
1070

1071
1072
1073
1074
1075
1076
1077
1078







-
+







	    goto error;
	}
    }

    return (int) bytesWritten;

  writeError:
    TclWinConvertError(GetLastError());
    Tcl_WinConvertError(GetLastError());

  error:
    /*
     * Reset the output queue counter on error during blocking output
     */

    /*
1188
1189
1190
1191
1192
1193
1194
1195

1196
1197
1198
1199
1200
1201
1202
1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1201







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
SerialWatchProc(
    ClientData instanceData,	/* Serial state. */
    void *instanceData,	/* Serial state. */
    int mask)			/* What events to watch for, OR-ed combination
				 * of TCL_READABLE, TCL_WRITABLE and
				 * TCL_EXCEPTION. */
{
    SerialInfo **nextPtrPtr, *ptr;
    SerialInfo *infoPtr = (SerialInfo *) instanceData;
    int oldMask = infoPtr->watchMask;
1245
1246
1247
1248
1249
1250
1251
1252

1253
1254

1255
1256
1257
1258

1259
1260
1261
1262
1263
1264
1265
1244
1245
1246
1247
1248
1249
1250

1251
1252

1253
1254
1255
1256

1257
1258
1259
1260
1261
1262
1263
1264







-
+

-
+



-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
SerialGetHandleProc(
    ClientData instanceData,	/* The serial state. */
    void *instanceData,	/* The serial state. */
    TCL_UNUSED(int) /*direction*/,
    ClientData *handlePtr)	/* Where to store the handle. */
    void **handlePtr)	/* Where to store the handle. */
{
    SerialInfo *infoPtr = (SerialInfo *) instanceData;

    *handlePtr = (ClientData) infoPtr->handle;
    *handlePtr = (void *)infoPtr->handle;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * SerialWriterThread --
1454
1455
1456
1457
1458
1459
1460
1461

1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480

1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
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


1478
1479
1480

1481
1482
1483
1484
1485
1486
1487







-
+

















-
-
+


-







    SerialInfo *infoPtr;

    SerialInit();

    infoPtr = (SerialInfo *)Tcl_Alloc(sizeof(SerialInfo));
    memset(infoPtr, 0, sizeof(SerialInfo));

    infoPtr->validMask = permissions;
    infoPtr->validMask = permissions & (TCL_READABLE|TCL_WRITABLE);
    infoPtr->handle = handle;
    infoPtr->channel = (Tcl_Channel) NULL;
    infoPtr->readable = 0;
    infoPtr->writable = 1;
    infoPtr->toWrite = infoPtr->writeQueue = 0;
    infoPtr->blockTime = SERIAL_DEFAULT_BLOCKTIME;
    infoPtr->lastEventTime = 0;
    infoPtr->lastError = infoPtr->error = 0;
    infoPtr->threadId = Tcl_GetCurrentThread();
    infoPtr->sysBufRead = 4096;
    infoPtr->sysBufWrite = 4096;

    /*
     * Use the pointer to keep the channel names unique, in case the handles
     * are shared between multiple channels (stdin/stdout).
     */

    sprintf(channelName, "file%" TCL_Z_MODIFIER "x", (size_t) infoPtr);

    TclWinGenerateChannelName(channelName, "file", infoPtr);
    infoPtr->channel = Tcl_CreateChannel(&serialChannelType, channelName,
	    infoPtr, permissions);


    SetupComm(handle, infoPtr->sysBufRead, infoPtr->sysBufWrite);
    PurgeComm(handle,
	    PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

    /*
     * Default is blocking.
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1501
1502
1503
1504
1505
1506
1507





1508

1509
1510
1511
1512
1513
1514
1515







-
-
-
-
-

-







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

    /*
     * Files have default translation of AUTO and ^Z eof char, which means
     * that a ^Z will be accepted as EOF when reading.
     */

    Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto");
    Tcl_SetChannelOption(NULL, infoPtr->channel, "-eofchar", "\032 {}");

    return infoPtr->channel;
}

/*
 *----------------------------------------------------------------------
 *
1560
1561
1562
1563
1564
1565
1566
1567

1568
1569
1570
1571
1572
1573
1574
1551
1552
1553
1554
1555
1556
1557

1558
1559
1560
1561
1562
1563
1564
1565







-
+







    }
    if (error & CE_PTO) {	/* PTO used to signal WRITE-TIMEOUT */
	Tcl_DStringAppendElement(dsPtr, "TIMEOUT");
    }
    if (error & ~((DWORD) (SERIAL_READ_ERRORS | SERIAL_WRITE_ERRORS))) {
	char buf[TCL_INTEGER_SPACE + 1];

	wsprintfA(buf, "%d", error);
	snprintf(buf, sizeof(buf), "%ld", error);
	Tcl_DStringAppendElement(dsPtr, buf);
    }
}

/*
 *----------------------------------------------------------------------
 *
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
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







-
+










-
+

















-
+

-
+


-
+








-
+















-
+








-
+







 *	May modify an option on a device.
 *
 *----------------------------------------------------------------------
 */

static int
SerialSetOptionProc(
    ClientData instanceData,	/* File state. */
    void *instanceData,	/* File state. */
    Tcl_Interp *interp,		/* For error reporting - can be NULL. */
    const char *optionName,	/* Which option to set? */
    const char *value)		/* New value for option. */
{
    SerialInfo *infoPtr;
    DCB dcb;
    BOOL result, flag;
    size_t len, vlen;
    Tcl_DString ds;
    const WCHAR *native;
    int argc;
    Tcl_Size argc;
    const char **argv;

    infoPtr = (SerialInfo *) instanceData;

    /*
     * Parse options. This would be far easier if we had Tcl_Objs to work with
     * as that would let us use Tcl_GetIndexFromObj()...
     */

    len = strlen(optionName);
    vlen = strlen(value);

    /*
     * Option -closemode drain|discard|default
     */

    if ((len > 2) && (strncmp(optionName, "-closemode", len) == 0)) {
	if (Tcl_UtfNcasecmp(value, "DEFAULT", vlen) == 0) {
	if (strncasecmp(value, "DEFAULT", vlen) == 0) {
	    infoPtr->flags &= ~SERIAL_CLOSE_MASK;
	} else if (Tcl_UtfNcasecmp(value, "DRAIN", vlen) == 0) {
	} else if (strncasecmp(value, "DRAIN", vlen) == 0) {
	    infoPtr->flags &= ~SERIAL_CLOSE_MASK;
	    infoPtr->flags |= SERIAL_CLOSE_DRAIN;
	} else if (Tcl_UtfNcasecmp(value, "DISCARD", vlen) == 0) {
	} else if (strncasecmp(value, "DISCARD", vlen) == 0) {
	    infoPtr->flags &= ~SERIAL_CLOSE_MASK;
	    infoPtr->flags |= SERIAL_CLOSE_DISCARD;
	} else {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"bad mode \"%s\" for -closemode: must be"
			" default, discard, or drain", value));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "FCONFIGURE",
			"VALUE", NULL);
			"VALUE", (char *)NULL);
	    }
	    return TCL_ERROR;
	}
	return TCL_OK;
    }

    /*
     * Option -mode baud,parity,databits,stopbits
     */

    if ((len > 2) && (strncmp(optionName, "-mode", len) == 0)) {
	if (!GetCommState(infoPtr->handle, &dcb)) {
	    goto getStateFailed;
	}
	Tcl_DStringInit(&ds);
	native = Tcl_UtfToWCharDString(value, -1, &ds);
	native = Tcl_UtfToWCharDString(value, TCL_INDEX_NONE, &ds);
	result = BuildCommDCBW(native, &dcb);
	Tcl_DStringFree(&ds);

	if (result == FALSE) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"bad value \"%s\" for -mode: should be baud,parity,data,stop",
			value));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "SERIALMODE", NULL);
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "SERIALMODE", (char *)NULL);
	    }
	    return TCL_ERROR;
	}

	/*
	 * Default settings for serial communications.
	 */
1747
1748
1749
1750
1751
1752
1753
1754

1755
1756
1757
1758
1759
1760
1761
1738
1739
1740
1741
1742
1743
1744

1745
1746
1747
1748
1749
1750
1751
1752







-
+







	    dcb.fOutxDsrFlow = TRUE;
	    dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
	} else {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"bad value \"%s\" for -handshake: must be one of"
			" xonxoff, rtscts, dtrdsr or none", value));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "HANDSHAKE", NULL);
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "HANDSHAKE", (char *)NULL);
	    }
	    return TCL_ERROR;
	}

	if (!SetCommState(infoPtr->handle, &dcb)) {
	    goto setStateFailed;
	}
1775
1776
1777
1778
1779
1780
1781
1782
1783


1784
1785
1786
1787
1788
1789
1790
1766
1767
1768
1769
1770
1771
1772


1773
1774
1775
1776
1777
1778
1779
1780
1781







-
-
+
+







	    return TCL_ERROR;
	}
	if (argc != 2) {
	badXchar:
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"bad value for -xchar: should be a list of"
			" two elements with each a single 8-bit character", -1));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "XCHAR", NULL);
			" two elements with each a single 8-bit character", TCL_INDEX_NONE));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "XCHAR", (char *)NULL);
	    }
	    Tcl_Free((void *)argv);
	    return TCL_ERROR;
	}

	/*
	 * These dereferences are safe, even in the zero-length string cases,
1798
1799
1800
1801
1802
1803
1804
1805

1806
1807
1808
1809
1810

1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828

1829

1830
1831
1832
1833
1834
1835
1836
1837
1838
1839

1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855

1856
1857

1858
1859
1860
1861
1862
1863
1864
1865
1866
1867

1868
1869

1870
1871
1872
1873
1874
1875
1876
1877
1878
1879

1880
1881

1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892

1893
1894
1895
1896
1897
1898
1899
1789
1790
1791
1792
1793
1794
1795

1796
1797
1798
1799
1800

1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820

1821
1822
1823
1824
1825
1826
1827
1828
1829
1830

1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846

1847
1848

1849
1850
1851
1852
1853
1854
1855
1856
1857
1858

1859
1860

1861
1862
1863
1864
1865
1866
1867
1868
1869
1870

1871
1872

1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883

1884
1885
1886
1887
1888
1889
1890
1891







-
+




-
+


















+
-
+









-
+















-
+

-
+









-
+

-
+









-
+

-
+










-
+








	dcb.XonChar = argv[0][0];
	dcb.XoffChar = argv[1][0];
	if (argv[0][0] & 0x80 || argv[1][0] & 0x80) {
	    Tcl_UniChar character = 0;
	    int charLen;

	    charLen = Tcl_UtfToUniChar(argv[0], &character);
	    charLen = TclUtfToUniChar(argv[0], &character);
	    if ((character > 0xFF) || argv[0][charLen]) {
		goto badXchar;
	    }
	    dcb.XonChar = (char) character;
	    charLen = Tcl_UtfToUniChar(argv[1], &character);
	    charLen = TclUtfToUniChar(argv[1], &character);
	    if ((character > 0xFF) || argv[1][charLen]) {
		goto badXchar;
	    }
	    dcb.XoffChar = (char) character;
	}
	Tcl_Free((void *)argv);

	if (!SetCommState(infoPtr->handle, &dcb)) {
	    goto setStateFailed;
	}
	return TCL_OK;
    }

    /*
     * Option -ttycontrol {DTR 1 RTS 0 BREAK 0}
     */

    if ((len > 4) && (strncmp(optionName, "-ttycontrol", len) == 0)) {
	Tcl_Size i;
	int i, res = TCL_OK;
	int res = TCL_OK;

	if (Tcl_SplitList(interp, value, &argc, &argv) == TCL_ERROR) {
	    return TCL_ERROR;
	}
	if ((argc % 2) == 1) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"bad value \"%s\" for -ttycontrol: should be "
			"a list of signal,value pairs", value));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "TTYCONTROL", NULL);
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "TTYCONTROL", (char *)NULL);
	    }
	    Tcl_Free((void *)argv);
	    return TCL_ERROR;
	}

	for (i = 0; i < argc - 1; i += 2) {
	    if (Tcl_GetBoolean(interp, argv[i+1], &flag) == TCL_ERROR) {
		res = TCL_ERROR;
		break;
	    }
	    if (strncasecmp(argv[i], "DTR", strlen(argv[i])) == 0) {
		if (!EscapeCommFunction(infoPtr->handle,
			(DWORD) (flag ? SETDTR : CLRDTR))) {
		    if (interp != NULL) {
			Tcl_SetObjResult(interp, Tcl_NewStringObj(
				"can't set DTR signal", -1));
				"can't set DTR signal", TCL_INDEX_NONE));
			Tcl_SetErrorCode(interp, "TCL", "OPERATION",
				"FCONFIGURE", "TTY_SIGNAL", NULL);
				"FCONFIGURE", "TTY_SIGNAL", (char *)NULL);
		    }
		    res = TCL_ERROR;
		    break;
		}
	    } else if (strncasecmp(argv[i], "RTS", strlen(argv[i])) == 0) {
		if (!EscapeCommFunction(infoPtr->handle,
			(DWORD) (flag ? SETRTS : CLRRTS))) {
		    if (interp != NULL) {
			Tcl_SetObjResult(interp, Tcl_NewStringObj(
				"can't set RTS signal", -1));
				"can't set RTS signal", TCL_INDEX_NONE));
			Tcl_SetErrorCode(interp, "TCL", "OPERATION",
				"FCONFIGURE", "TTY_SIGNAL", NULL);
				"FCONFIGURE", "TTY_SIGNAL", (char *)NULL);
		    }
		    res = TCL_ERROR;
		    break;
		}
	    } else if (strncasecmp(argv[i], "BREAK", strlen(argv[i])) == 0) {
		if (!EscapeCommFunction(infoPtr->handle,
			(DWORD) (flag ? SETBREAK : CLRBREAK))) {
		    if (interp != NULL) {
			Tcl_SetObjResult(interp, Tcl_NewStringObj(
				"can't set BREAK signal", -1));
				"can't set BREAK signal", TCL_INDEX_NONE));
			Tcl_SetErrorCode(interp, "TCL", "OPERATION",
				"FCONFIGURE", "TTY_SIGNAL", NULL);
				"FCONFIGURE", "TTY_SIGNAL", (char *)NULL);
		    }
		    res = TCL_ERROR;
		    break;
		}
	    } else {
		if (interp != NULL) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "bad signal name \"%s\" for -ttycontrol: must be"
			    " DTR, RTS or BREAK", argv[i]));
		    Tcl_SetErrorCode(interp, "TCL", "VALUE", "TTY_SIGNAL",
			    NULL);
			    (char *)NULL);
		}
		res = TCL_ERROR;
		break;
	    }
	}

	Tcl_Free((void *)argv);
1925
1926
1927
1928
1929
1930
1931
1932

1933
1934
1935
1936
1937
1938
1939

1940
1941
1942
1943
1944
1945
1946
1917
1918
1919
1920
1921
1922
1923

1924
1925
1926
1927
1928
1929
1930

1931
1932
1933
1934
1935
1936
1937
1938







-
+






-
+







	Tcl_Free((void *)argv);

	if ((argc < 1) || (argc > 2) || (inSize <= 0) || (outSize <= 0)) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"bad value \"%s\" for -sysbuffer: should be "
			"a list of one or two integers > 0", value));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "SYS_BUFFER", NULL);
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "SYS_BUFFER", (char *)NULL);
	    }
	    return TCL_ERROR;
	}

	if (!SetupComm(infoPtr->handle, inSize, outSize)) {
	    if (interp != NULL) {
		TclWinConvertError(GetLastError());
		Tcl_WinConvertError(GetLastError());
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't setup comm buffers: %s",
			Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}
	infoPtr->sysBufRead  = inSize;
1983
1984
1985
1986
1987
1988
1989
1990

1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007

2008
2009
2010
2011
2012
2013
2014
2015

2016
2017
2018
2019
2020
2021
2022
1975
1976
1977
1978
1979
1980
1981

1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998

1999
2000
2001
2002
2003
2004
2005
2006

2007
2008
2009
2010
2011
2012
2013
2014







-
+
















-
+







-
+








	if (Tcl_GetInt(interp, value, &msec) != TCL_OK) {
	    return TCL_ERROR;
	}
	tout.ReadTotalTimeoutConstant = msec;
	if (!SetCommTimeouts(infoPtr->handle, &tout)) {
	    if (interp != NULL) {
		TclWinConvertError(GetLastError());
		Tcl_WinConvertError(GetLastError());
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't set comm timeouts: %s",
			Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}

	return TCL_OK;
    }

    return Tcl_BadChannelOption(interp, optionName,
	    "closemode mode handshake pollinterval sysbuffer timeout "
	    "ttycontrol xchar");

  getStateFailed:
    if (interp != NULL) {
	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't get comm state: %s", Tcl_PosixError(interp)));
    }
    return TCL_ERROR;

  setStateFailed:
    if (interp != NULL) {
	TclWinConvertError(GetLastError());
	Tcl_WinConvertError(GetLastError());
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't set comm state: %s", Tcl_PosixError(interp)));
    }
    return TCL_ERROR;
}

/*
2038
2039
2040
2041
2042
2043
2044
2045

2046
2047
2048
2049
2050
2051
2052
2030
2031
2032
2033
2034
2035
2036

2037
2038
2039
2040
2041
2042
2043
2044







-
+







 *	reused at any time subsequent to the call.
 *
 *----------------------------------------------------------------------
 */

static int
SerialGetOptionProc(
    ClientData instanceData,	/* File state. */
    void *instanceData,	/* File state. */
    Tcl_Interp *interp,		/* For error reporting - can be NULL. */
    const char *optionName,	/* Option to get. */
    Tcl_DString *dsPtr)		/* Where to store value(s). */
{
    SerialInfo *infoPtr;
    DCB dcb;
    size_t len;
2091
2092
2093
2094
2095
2096
2097
2098

2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113

2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129

2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145

2146
2147

2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168

2169
2170
2171
2172
2173
2174
2175
2083
2084
2085
2086
2087
2088
2089

2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104

2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120

2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136

2137
2138

2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159

2160
2161
2162
2163
2164
2165
2166
2167







-
+














-
+















-
+















-
+

-
+




















-
+







    if (len==0 || (len>2 && (strncmp(optionName, "-mode", len) == 0))) {
	char parity;
	const char *stop;
	char buf[2 * TCL_INTEGER_SPACE + 16];

	if (!GetCommState(infoPtr->handle, &dcb)) {
	    if (interp != NULL) {
		TclWinConvertError(GetLastError());
		Tcl_WinConvertError(GetLastError());
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't get comm state: %s", Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}

	valid = 1;
	parity = 'n';
	if (dcb.Parity <= 4) {
	    parity = "noems"[dcb.Parity];
	}
	stop = (dcb.StopBits == ONESTOPBIT) ? "1" :
		(dcb.StopBits == ONE5STOPBITS) ? "1.5" : "2";

	wsprintfA(buf, "%d,%c,%d,%s", dcb.BaudRate, parity,
	snprintf(buf, sizeof(buf), "%ld,%c,%d,%s", dcb.BaudRate, parity,
		dcb.ByteSize, stop);
	Tcl_DStringAppendElement(dsPtr, buf);
    }

    /*
     * Get option -pollinterval
     */

    if (len == 0) {
	Tcl_DStringAppendElement(dsPtr, "-pollinterval");
    }
    if (len==0 || (len>1 && strncmp(optionName, "-pollinterval", len)==0)) {
	char buf[TCL_INTEGER_SPACE + 1];

	valid = 1;
	wsprintfA(buf, "%d", infoPtr->blockTime);
	snprintf(buf, sizeof(buf), "%d", infoPtr->blockTime);
	Tcl_DStringAppendElement(dsPtr, buf);
    }

    /*
     * Get option -sysbuffer
     */

    if (len == 0) {
	Tcl_DStringAppendElement(dsPtr, "-sysbuffer");
	Tcl_DStringStartSublist(dsPtr);
    }
    if (len==0 || (len>1 && strncmp(optionName, "-sysbuffer", len) == 0)) {
	char buf[TCL_INTEGER_SPACE + 1];
	valid = 1;

	wsprintfA(buf, "%d", infoPtr->sysBufRead);
	snprintf(buf, sizeof(buf), "%ld", infoPtr->sysBufRead);
	Tcl_DStringAppendElement(dsPtr, buf);
	wsprintfA(buf, "%d", infoPtr->sysBufWrite);
	snprintf(buf, sizeof(buf), "%ld", infoPtr->sysBufWrite);
	Tcl_DStringAppendElement(dsPtr, buf);
    }
    if (len == 0) {
	Tcl_DStringEndSublist(dsPtr);
    }

    /*
     * Get option -xchar
     */

    if (len == 0) {
	Tcl_DStringAppendElement(dsPtr, "-xchar");
	Tcl_DStringStartSublist(dsPtr);
    }
    if (len==0 || (len>1 && strncmp(optionName, "-xchar", len) == 0)) {
	char buf[4];
	valid = 1;

	if (!GetCommState(infoPtr->handle, &dcb)) {
	    if (interp != NULL) {
		TclWinConvertError(GetLastError());
		Tcl_WinConvertError(GetLastError());
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't get comm state: %s", Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}
	buf[Tcl_UniCharToUtf(UCHAR(dcb.XonChar), buf)] = '\0';
	Tcl_DStringAppendElement(dsPtr, buf);
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
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







-
+

-
+















-
+







	 */

	EnterCriticalSection(&infoPtr->csWrite);
	ClearCommError(infoPtr->handle, &error, &cStat);
	count = (int) cStat.cbOutQue + infoPtr->writeQueue;
	LeaveCriticalSection(&infoPtr->csWrite);

	wsprintfA(buf, "%d", inBuffered + cStat.cbInQue);
	snprintf(buf, sizeof(buf), "%ld", inBuffered + cStat.cbInQue);
	Tcl_DStringAppendElement(dsPtr, buf);
	wsprintfA(buf, "%d", outBuffered + count);
	snprintf(buf, sizeof(buf), "%d", outBuffered + count);
	Tcl_DStringAppendElement(dsPtr, buf);
    }

    /*
     * get option -ttystatus
     *
     * Option is readonly and returned by [fconfigure chan -ttystatus] but not
     * returned by unnamed [fconfigure chan].
     */

    if (len>4 && strncmp(optionName, "-ttystatus", len)==0) {
	DWORD status;

	if (!GetCommModemStatus(infoPtr->handle, &status)) {
	    if (interp != NULL) {
		TclWinConvertError(GetLastError());
		Tcl_WinConvertError(GetLastError());
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't get tty status: %s", Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}
	valid = 1;
	SerialModemStatusStr(status, dsPtr);
2275
2276
2277
2278
2279
2280
2281
2282

2283
2284
2285
2286
2287
2288
2289
2290

2291
2292
2293
2294
2295
2296
2297
2267
2268
2269
2270
2271
2272
2273

2274
2275
2276
2277
2278
2279
2280
2281

2282
2283
2284
2285
2286
2287
2288
2289







-
+







-
+







 *	Changes thread local list of valid channels.
 *
 *----------------------------------------------------------------------
 */

static void
SerialThreadActionProc(
    ClientData instanceData,
    void *instanceData,
    int action)
{
    SerialInfo *infoPtr = (SerialInfo *) instanceData;

    /*
     * We do not access firstSerialPtr in the thread structures. This is not
     * for all serials managed by the thread, but only those we are watching.
     * Removal of the filevent handlers before transfer thus takes care of
     * Removal of the fileevent handlers before transfer thus takes care of
     * this structure.
     */

    Tcl_MutexLock(&serialMutex);
    if (action == TCL_CHANNEL_THREAD_INSERT) {
	/*
	 * We can't copy the thread information from the channel when the

Changes to win/tclWinSock.c.

1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







/*
 * tclWinSock.c --
 *
 *	This file contains Windows-specific socket related code.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * -----------------------------------------------------------------------
 * The order and naming of functions in this file should minimize
 * the file diff to tclUnixSock.c.
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
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







-
-
-
-
-
-
-








-
+


-
+
-














-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+


















-
+












-
-
-


+



















-
+










-
+









-
+



+
-
-
-
+
+
+
-
-
+
-
-
+
-
-
-
-
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+








#include "tclWinInt.h"

#ifdef _MSC_VER
#   pragma comment (lib, "ws2_32")
#endif

/*
 * Support for control over sockets' KEEPALIVE and NODELAY behavior is
 * currently disabled.
 */

#undef TCL_FEATURE_KEEPALIVE_NAGLE

/*
 * Helper macros to make parts of this file clearer. The macros do exactly
 * what they say on the tin. :-) They also only ever refer to their arguments
 * once, and so can be used without regard to side effects.
 */

#define SET_BITS(var, bits)	((var) |= (bits))
#define CLEAR_BITS(var, bits)	((var) &= ~(bits))
#define GOT_BITS(var, bits)     (((var) & (bits)) != 0)
#define GOT_BITS(var, bits)	(((var) & (bits)) != 0)

/* "sock" + a pointer in hex + \0 */
#define SOCK_CHAN_LENGTH        (4 + sizeof(void *) * 2 + 1)
#define SOCK_CHAN_LENGTH	(16 + TCL_INTEGER_SPACE)
#define SOCK_TEMPLATE           "sock%p"

/*
 * The following variable is used to tell whether this module has been
 * initialized.  If 1, initialization of sockets was successful, if -1 then
 * socket initialization failed (WSAStartup failed).
 */

static int initialized = 0;
static const WCHAR className[] = L"TclSocket";
TCL_DECLARE_MUTEX(socketMutex)

/*
 * The following defines declare the messages used on socket windows.
 */

#define SOCKET_MESSAGE		WM_USER+1
#define SOCKET_SELECT		WM_USER+2
#define SOCKET_TERMINATE	WM_USER+3
#define SELECT			TRUE
#define UNSELECT		FALSE
enum TclSocketMessages {
    SOCKET_MESSAGE = WM_USER+1,	/* Sent by OS: something happened. */
    SOCKET_SELECT = WM_USER+2,	/* Adjust select mask. */
    SOCKET_TERMINATE = WM_USER+3/* Stop worker thread. */
};

/*
 * Operations used with a SOCKET_SELECT message.
 */
enum SocketSelectOperations {
    SELECT = TRUE,		/* Add socket to select. */
    UNSELECT = FALSE		/* Remove socket from select. */
};

/*
 * This is needed to comply with the strict aliasing rules of GCC, but it also
 * simplifies casting between the different sockaddr types.
 */

typedef union {
    struct sockaddr sa;
    struct sockaddr_in sa4;
    struct sockaddr_in6 sa6;
    struct sockaddr_storage sas;
} address;

#ifndef IN6_ARE_ADDR_EQUAL
#define IN6_ARE_ADDR_EQUAL IN6_ADDR_EQUAL
#endif

/*
 * This structure describes per-instance state of a tcp based channel.
 * This structure describes per-instance state of a tcp-based channel.
 */

typedef struct TcpState TcpState;

typedef struct TcpFdList {
    TcpState *statePtr;
    SOCKET fd;
    struct TcpFdList *next;
} TcpFdList;

struct TcpState {
    Tcl_Channel channel;	/* Channel associated with this socket. */
    int testFlags;              /* bit field for tests. Is set by testsocket
                                 * test procedure */
    struct TcpFdList *sockets;	/* Windows SOCKET handle. */
    int flags;			/* Bit field comprised of the flags described
				 * below. */
    struct TcpFdList *sockets;	/* Windows SOCKET handle. */
    int watchEvents;		/* OR'ed combination of FD_READ, FD_WRITE,
				 * FD_CLOSE, FD_ACCEPT and FD_CONNECT that
				 * indicate which events are interesting. */
    volatile int readyEvents;	/* OR'ed combination of FD_READ, FD_WRITE,
				 * FD_CLOSE, FD_ACCEPT and FD_CONNECT that
				 * indicate which events have occurred.
				 * Set by notifier thread, access must be
				 * protected by semaphore */
    int selectEvents;		/* OR'ed combination of FD_READ, FD_WRITE,
				 * FD_CLOSE, FD_ACCEPT and FD_CONNECT that
				 * indicate which events are currently being
				 * selected. */
    volatile int acceptEventCount;
				/* Count of the current number of FD_ACCEPTs
				 * that have arrived and not yet processed.
				 * Set by notifier thread, access must be
				 * protected by semaphore */
    Tcl_TcpAcceptProc *acceptProc;
				/* Proc to call on accept. */
    ClientData acceptProcData;	/* The data for the accept proc. */
    void *acceptProcData;	/* The data for the accept proc. */

    /*
     * Only needed for client sockets
     */

    struct addrinfo *addrlist;	/* Addresses to connect to. */
    struct addrinfo *addr;	/* Iterator over addrlist. */
    struct addrinfo *myaddrlist;/* Local address. */
    struct addrinfo *myaddr;	/* Iterator over myaddrlist. */
    int connectError;		/* Cache status of async socket. */
    int cachedBlocking;         /* Cache blocking mode of async socket. */
    int cachedBlocking;		/* Cache blocking mode of async socket. */
    volatile int notifierConnectError;
				/* Async connect error set by notifier thread.
				 * This error is still a windows error code.
				 * Access must be protected by semaphore */
    struct TcpState *nextPtr;	/* The next socket on the per-thread socket
				 * list. */
};

/*
 * These bits may be ORed together into the "flags" field of a TcpState
 * These bits may be OR'ed together into the "flags" field of a TcpState
 * structure.
 */

enum TcpStateFlags {
#define TCP_NONBLOCKING		(1<<0)	/* Socket with non-blocking I/O */
#define TCP_ASYNC_CONNECT	(1<<1)	/* Async connect in progress. */
#define SOCKET_EOF		(1<<2)	/* A zero read happened on the
    TCP_NONBLOCKING = (1<<0),	/* Socket with non-blocking I/O. */
    TCP_ASYNC_CONNECT = (1<<1),	/* Async connect in progress. */
    SOCKET_EOF = (1<<2),	/* A zero read happened on the socket. */
					 * socket. */
#define SOCKET_PENDING		(1<<3)	/* A message has been sent for this
    SOCKET_PENDING = (1<<3),	/* A message has been sent for this socket */
					 * socket */
#define TCP_ASYNC_PENDING	(1<<4)	/* TcpConnect was called to
    TCP_ASYNC_PENDING = (1<<4),	/* TcpConnect was called to process an async
					 * process an async connect. This
					 * flag indicates that reentry is
					 * still pending */
#define TCP_ASYNC_FAILED	(1<<5)	/* An async connect finally failed */
				 * connect. This flag indicates that reentry is
				 * still pending. */
    TCP_ASYNC_FAILED = (1<<5),	/* An async connect finally failed. */

/*
 * These bits may be ORed together into the "testFlags" field of a TcpState
 * structure.
 */

#define TCP_ASYNC_TEST_MODE	(1<<0)	/* Async testing activated.  Do not
					 * automatically continue connection
					 * process */
    TCP_ASYNC_TEST_MODE = (1<<8)/* Async testing activated.  Do not
				 * automatically continue connection
				 * process */
};

/*
 * The following structure is what is added to the Tcl event queue when a
 * socket event occurs.
 */

typedef struct {
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
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







-
+
+
+
+









-
+
-















-
+

-
+


-




-
+


-
+








/*
 * This defines the minimum buffersize maintained by the kernel.
 */

#define TCP_BUFFER_SIZE 4096


/*
 * Per (main) thread data, holding list of things being waited upon and the
 * various handles to things doing the waiting/notification.
 */
typedef struct {
    HWND hwnd;			/* Handle to window for socket messages. */
    HANDLE socketThread;	/* Thread handling the window */
    Tcl_ThreadId threadId;	/* Parent thread. */
    HANDLE readyEvent;		/* Event indicating that a socket event is
				 * ready. Also used to indicate that the
				 * socketThread has been initialized and has
				 * started. */
    HANDLE socketListLock;	/* Win32 Event to lock the socketList */
    TcpState *pendingTcpState;
    TcpState *pendingTcpState;	/* This socket is opened but not jet in the
				/* This socket is opened but not jet in the
				 * list. This value is also checked by
				 * the event structure. */
    TcpState *socketList;	/* Every open socket in this thread has an
				 * entry on this list. */
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;
static WNDCLASSW windowClass;

/*
 * Static routines for this file:
 */

static int		TcpConnect(Tcl_Interp *interp,
			    TcpState *state);
static void		InitSockets(void);
static void		InitSocketWindowClass(void);
static TcpState *	NewSocketInfo(SOCKET socket);
static void		SocketExitHandler(ClientData clientData);
static void		SocketExitHandler(void *clientData);
static LRESULT CALLBACK	SocketProc(HWND hwnd, UINT message, WPARAM wParam,
			    LPARAM lParam);
static int		SocketsEnabled(void);
static void		TcpAccept(TcpFdList *fds, SOCKET newSocket, address addr);
static int		WaitForConnect(TcpState *statePtr, int *errorCodePtr);
static int		WaitForSocketEvent(TcpState *statePtr, int events,
			    int *errorCodePtr);
static void		AddSocketInfoFd(TcpState *statePtr,  SOCKET socket);
static void		AddSocketInfoFd(TcpState *statePtr, SOCKET socket);
static int		FindFDInList(TcpState *statePtr, SOCKET socket);
static DWORD WINAPI	SocketThread(LPVOID arg);
static void		TcpThreadActionProc(ClientData instanceData,
static void		TcpThreadActionProc(void *instanceData,
			    int action);
static int		TcpCloseProc(void *, Tcl_Interp *);

static Tcl_EventCheckProc	SocketCheckProc;
static Tcl_EventProc		SocketEventProc;
static Tcl_EventSetupProc	SocketSetupProc;
static Tcl_DriverBlockModeProc	TcpBlockModeProc;
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+

+
+
+
+
-
+
+
+
+

+
+
+
+
+
-
+
-
-
-
-
+
+
+





-
+








-
+


-
+








/*
 * This structure describes the channel type structure for TCP socket
 * based IO:
 */

static const Tcl_ChannelType tcpChannelType = {
    "tcp",			/* Type name. */
    TCL_CHANNEL_VERSION_5,	/* v5 channel */
    NULL,		/* Close proc. */
    TcpInputProc,		/* Input proc. */
    TcpOutputProc,		/* Output proc. */
    NULL,			/* Seek proc. */
    TcpSetOptionProc,		/* Set option proc. */
    TcpGetOptionProc,		/* Get option proc. */
    TcpWatchProc,		/* Initialize notifier. */
    TcpGetHandleProc,		/* Get OS handles out of channel. */
    TcpClose2Proc,		/* Close2 proc. */
    TcpBlockModeProc,		/* Set blocking or non-blocking mode.*/
    NULL,			/* flush proc. */
    NULL,			/* handler proc. */
    NULL,			/* wide seek proc. */
    TcpThreadActionProc,	/* thread action proc. */
    NULL			/* truncate proc. */
    "tcp",
    TCL_CHANNEL_VERSION_5,
    NULL,			/* Deprecated. */
    TcpInputProc,
    TcpOutputProc,
    NULL,			/* Deprecated. */
    TcpSetOptionProc,
    TcpGetOptionProc,
    TcpWatchProc,
    TcpGetHandleProc,
    TcpClose2Proc,
    TcpBlockModeProc,
    NULL,			/* Flush proc. */
    NULL,			/* Bubbled event handler proc. */
    NULL,			/* Seek proc. */
    TcpThreadActionProc,
    NULL			/* Truncate proc. */
};

/*
 * The following variable holds the network name of this host.
 */

static TclInitProcessGlobalValueProc InitializeHostName;
static ProcessGlobalValue hostName =
	{0, 0, NULL, NULL, InitializeHostName, NULL, NULL};


/*
 *----------------------------------------------------------------------
 *
 * SendSelectMessage --
 *
 * Simple wrapper round the SendMessage syscall.
 *	Simple wrapper round the SendMessage syscall with a SOCKET_SELECT
 *	message to add a bit of type safety.
 *
 *----------------------------------------------------------------------
 */
static inline void
SendSelectMessage(
    ThreadSpecificData *tsdPtr,	/* Reference to this thread's worker. */
    int operation,		/* Whether to add or remove from the mask. */
    TcpState *payload)		/* What socket to add/remove. */

{
#define SendSelectMessage(tsdPtr, message, payload)     \
    SendMessageW((tsdPtr)->hwnd, SOCKET_SELECT,          \
                (WPARAM) (message), (LPARAM) (payload))

    SendMessageW(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) operation,
	    (LPARAM) payload);
}

/*
 * Address print debug functions
 */
#if 0
void
static inline void
printaddrinfo(
    struct addrinfo *ai,
    char *prefix)
{
    char host[NI_MAXHOST], port[NI_MAXSERV];

    getnameinfo(ai->ai_addr, ai->ai_addrlen,
	    host, sizeof(host), port, sizeof(port),
	    NI_NUMERICHOST|NI_NUMERICSERV);
	    NI_NUMERICHOST | NI_NUMERICSERV);
}

void
static void
printaddrinfolist(
    struct addrinfo *addrlist,
    char *prefix)
{
    struct addrinfo *ai;

    for (ai = addrlist; ai != NULL; ai = ai->ai_next) {
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
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







-
+





-
+
+

+

+
-
-
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
+
+
+
-
-
+
-
-
+
-
-
+
-
-
-
+







void
InitializeHostName(
    char **valuePtr,
    size_t *lengthPtr,
    Tcl_Encoding *encodingPtr)
{
    WCHAR wbuf[256];
    DWORD length = sizeof(wbuf)/sizeof(WCHAR);
    DWORD length = sizeof(wbuf) / sizeof(WCHAR);
    Tcl_DString ds;

    Tcl_DStringInit(&ds);
    if (GetComputerNameExW(ComputerNamePhysicalDnsFullyQualified, wbuf, &length) != 0) {
	/*
	 * Convert string from native to UTF then change to lowercase.
	 * Convert string from WCHAR to utf-8, then change to lowercase,
	 * then to system encoding.
	 */
	Tcl_DString inDs;

	Tcl_DStringInit(&inDs);
	Tcl_UtfToLower(Tcl_WCharToUtfDString(wbuf, -1, &ds));

	Tcl_UtfToLower(Tcl_WCharToUtfDString(wbuf, TCL_INDEX_NONE, &inDs));
	Tcl_UtfToExternalDStringEx(NULL, NULL, Tcl_DStringValue(&inDs),
		TCL_INDEX_NONE, TCL_ENCODING_PROFILE_TCL8, &ds, NULL);
	Tcl_DStringFree(&inDs);
    } else {
	if (TclpHasSockets(NULL) == TCL_OK) {
	    /*
	     * The buffer size of 256 is recommended by the MSDN page that
	     * documents gethostname() as being always adequate.
	     */
	TclInitSockets();
	/*
	 * The buffer size of 256 is recommended by the MSDN page that
	 * documents gethostname() as being always adequate.
	 */

	    Tcl_DString inDs;

	    Tcl_DStringInit(&inDs);
	    Tcl_DStringSetLength(&inDs, 256);
	    if (gethostname(Tcl_DStringValue(&inDs),
	Tcl_DStringInit(&ds);
	Tcl_DStringSetLength(&ds, 256);
	gethostname(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
		    Tcl_DStringLength(&inDs)) == 0) {
		Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&inDs), -1,
	Tcl_DStringSetLength(&ds, strlen(Tcl_DStringValue(&ds)));
			&ds);
	    }
    }
	    Tcl_DStringFree(&inDs);
	}

    }

    *encodingPtr = Tcl_GetEncoding(NULL, "utf-8");
    *encodingPtr = Tcl_GetEncoding(NULL, NULL);
    *lengthPtr = Tcl_DStringLength(&ds);
    *valuePtr = (char *)Tcl_Alloc(*lengthPtr + 1);
    memcpy(*valuePtr, Tcl_DStringValue(&ds), *lengthPtr + 1);
    Tcl_DStringFree(&ds);
}

/*
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
467


















468
469
470
471
472
473
474
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
467
468
469
470


471
472
473
474
475
476
477
478
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







-
+

-
-
+
+
-


-
-
+









-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
-
-
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







{
    return Tcl_GetString(TclGetProcessGlobalValue(&hostName));
}

/*
 *----------------------------------------------------------------------
 *
 * TclpHasSockets --
 * TclInitSockets --
 *
 *	This function determines whether sockets are available on the current
 *	system and returns an error in interp if they are not. Note that
 *	Initialization of sockets for the thread. Also creates message
 *	handling window class for the process if needed.
 *	interp may be NULL.
 *
 * Results:
 *	Returns TCL_OK if the system supports sockets, or TCL_ERROR with an
 *	error in interp (if non-NULL).
 *	Nothing. Panics on failure.
 *
 * Side effects:
 *	If not already prepared, initializes the TSD structure and socket
 *	message handling thread associated to the calling thread for the
 *	subsystem of the driver.
 *
 *----------------------------------------------------------------------
 */

int
TclpHasSockets(
void
TclInitSockets(void)
    Tcl_Interp *interp)		/* Where to write an error message if sockets
				 * are not present, or NULL if no such message
				 * is to be written. */
{
    Tcl_MutexLock(&socketMutex);
    InitSockets();
    Tcl_MutexUnlock(&socketMutex);
{
    /* Then Per thread initialization. */
    DWORD id;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    TclThreadDataKeyGet(&dataKey);

    if (tsdPtr != NULL) {
	return;
    }

    InitSocketWindowClass();

    /*
     * OK, this thread has never done anything with sockets before.  Construct
     * a worker thread to handle asynchronous events related to sockets
     * assigned to _this_ thread.
     */

    tsdPtr = TCL_TSD_INIT(&dataKey);
    tsdPtr->pendingTcpState = NULL;
    if (SocketsEnabled()) {
	return TCL_OK;
    tsdPtr->socketList	= NULL;
    tsdPtr->hwnd	= NULL;
    tsdPtr->threadId	= Tcl_GetCurrentThread();
    tsdPtr->readyEvent	= CreateEventW(NULL, FALSE, FALSE, NULL);
    if (tsdPtr->readyEvent == NULL) {
	goto initFailure;
    }
    tsdPtr->socketListLock = CreateEventW(NULL, FALSE, TRUE, NULL);
    if (tsdPtr->socketListLock == NULL) {
	goto initFailure;
    }
    tsdPtr->socketThread = CreateThread(NULL, 256, SocketThread, tsdPtr, 0,
	    &id);
    if (tsdPtr->socketThread == NULL) {
	goto initFailure;
    }
    if (interp != NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"sockets are not available on this system", -1));
    }
    return TCL_ERROR;

    SetThreadPriority(tsdPtr->socketThread, THREAD_PRIORITY_HIGHEST);

    /*
     * Wait for the thread to signal when the window has been created and if
     * it is ready to go.
     */

    WaitForSingleObject(tsdPtr->readyEvent, INFINITE);

    if (tsdPtr->hwnd != NULL) {
	Tcl_CreateEventSource(SocketSetupProc, SocketCheckProc, NULL);
	return;
    }

  initFailure:
    Tcl_Panic("InitSockets failed");
    return;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpFinalizeSockets --
 *
485
486
487
488
489
490
491
492


493
494
495
496
497
498
499
522
523
524
525
526
527
528

529
530
531
532
533
534
535
536
537







-
+
+







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

void
TclpFinalizeSockets(void)
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    TclThreadDataKeyGet(&dataKey);

    /*
     * Careful! This is a finalizer!
     */

    if (tsdPtr == NULL) {
	return;
540
541
542
543
544
545
546
547

548
549
550
551
552
553
554
555
556
557

558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579


580
581
582
583
584


585
586
587
588

589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
578
579
580
581
582
583
584

585
586
587
588
589
590
591
592
593
594

595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615


616
617
618
619
620


621
622
623
624
625

626
627
628
629
630
631
632
633
634
635
636
637
638

639
640
641
642
643
644
645







-
+









-
+




















-
-
+
+



-
-
+
+



-
+












-







 *	Sets the device into blocking or nonblocking mode.
 *
 *----------------------------------------------------------------------
 */

static int
TcpBlockModeProc(
    ClientData instanceData,	/* Socket state. */
    void *instanceData,		/* Socket state. */
    int mode)			/* The mode to set. Can be one of
				 * TCL_MODE_BLOCKING or
				 * TCL_MODE_NONBLOCKING. */
{
    TcpState *statePtr = (TcpState *)instanceData;

    if (mode == TCL_MODE_NONBLOCKING) {
	SET_BITS(statePtr->flags, TCP_NONBLOCKING);
    } else {
        CLEAR_BITS(statePtr->flags, TCP_NONBLOCKING);
	CLEAR_BITS(statePtr->flags, TCP_NONBLOCKING);
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * WaitForConnect --
 *
 *	Check the state of an async connect process. If a connection attempt
 *	terminated, process it, which may finalize it or may start the next
 *	attempt. If a connect error occures, it is saved in
 *	statePtr->connectError to be reported by 'fconfigure -error'.
 *
 *	There are two modes of operation, defined by errorCodePtr:
 *	 *  non-NULL: Called by explicite read/write command. Block if socket
 *	    is blocking.
 *	    May return two error codes:
 *	     *	EWOULDBLOCK: if connect is still in progress
 *	     *	ENOTCONN: if connect failed. This would be the error message
 *		of a rect or sendto syscall so this is emulated here.
 *	 *  Null: Called by a backround operation. Do not block and don't
 *		of a recv or sendto syscall so this is emulated here.
 *	 *  Null: Called by a background operation. Do not block and don't
 *	    return any error code.
 *
 * Results:
 * 	0 if the connection has completed, -1 if still in progress or there is
 * 	an error.
 *	0 if the connection has completed, -1 if still in progress or there is
 *	an error.
 *
 * Side effects:
 *	Processes socket events off the system queue. May process
 *	asynchroneous connect.
 *	asynchronous connect.
 *
 *----------------------------------------------------------------------
 */

static int
WaitForConnect(
    TcpState *statePtr,		/* State of the socket. */
    int *errorCodePtr)		/* Where to store errors? A passed
				 * null-pointer activates background mode. */
{
    int result;
    int oldMode;
    ThreadSpecificData *tsdPtr;

    /*
     * Check if an async connect failed already and error reporting is
     * demanded, return the error ENOTCONN.
     */

    if (errorCodePtr != NULL && GOT_BITS(statePtr->flags, TCP_ASYNC_FAILED)) {
622
623
624
625
626
627
628
629

630
631

632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650

651

652
653
654
655
656


657
658
659
660
661


662
663
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
659
660
661
662
663
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
707
708
709
710
711
712
713


714
715
716
717
718
719

720
721
722
723
724
725
726


727
728
729
730
731
732

733
734
735
736
737
738
739
740







-
+

-
+



















+
-
+



-
-
+
+



-
-
+
+





-
+








-
-
+
+




-
+






-
-
+
+




-
+







     * In socket test mode do not continue with the connect
     * Exceptions are:
     * - Call by recv/send and blocking socket
     *   (errorCodePtr != NULL && !GOT_BITS(flags, TCP_NONBLOCKING))
     * - Call by the event queue (errorCodePtr == NULL)
     */

    if (GOT_BITS(statePtr->testFlags, TCP_ASYNC_TEST_MODE)
    if (GOT_BITS(statePtr->flags, TCP_ASYNC_TEST_MODE)
	    && errorCodePtr != NULL
            && GOT_BITS(statePtr->flags, TCP_NONBLOCKING)) {
	    && GOT_BITS(statePtr->flags, TCP_NONBLOCKING)) {
	*errorCodePtr = EWOULDBLOCK;
	return -1;
    }

    /*
     * Be sure to disable event servicing so we are truly modal.
     */

    oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE);

    /*
     * Loop in the blocking case until the connect signal is present
     */

    while (1) {
	/*
	 * Get the statePtr lock.
	 */

	ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
		TclThreadDataKeyGet(&dataKey);
	WaitForSingleObject(tsdPtr->socketListLock, INFINITE);

	/*
         * Check for connect event.
         */
	 * Check for connect event.
	 */

	if (GOT_BITS(statePtr->readyEvents, FD_CONNECT)) {
	    /*
             * Consume the connect event.
             */
	     * Consume the connect event.
	     */

	    CLEAR_BITS(statePtr->readyEvents, FD_CONNECT);

	    /*
	     * For blocking sockets and foreground processing, disable async
	     * connect as we continue now synchoneously.
	     * connect as we continue now synchronously.
	     */

	    if (errorCodePtr != NULL &&
		    !GOT_BITS(statePtr->flags, TCP_NONBLOCKING)) {
		CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
	    }

	    /*
             * Free list lock.
             */
	     * Free list lock.
	     */

	    SetEvent(tsdPtr->socketListLock);

	    /*
	     * Continue connect. If switched to synchroneous connect, the
	     * Continue connect. If switched to synchronous connect, the
	     * connect is terminated.
	     */

	    result = TcpConnect(NULL, statePtr);

	    /*
             * Restore event service mode.
             */
	     * Restore event service mode.
	     */

	    (void) Tcl_SetServiceMode(oldMode);

	    /*
	     * Check for Succesfull connect or async connect restart
	     * Check for Successful connect or async connect restart
	     */

	    if (result == TCL_OK) {
		/*
		 * Check for async connect restart (not possible for
		 * foreground blocking operation)
		 */
717
718
719
720
721
722
723
724
725
726



727
728

729
730
731
732
733
734
735
755
756
757
758
759
760
761



762
763
764
765

766
767
768
769
770
771
772
773







-
-
-
+
+
+

-
+








	    if (errorCodePtr != NULL) {
		*errorCodePtr = ENOTCONN;
	    }
	    return -1;
	}

        /*
         * Free list lock.
         */
	/*
	 * Free list lock.
	 */

        SetEvent(tsdPtr->socketListLock);
	SetEvent(tsdPtr->socketListLock);

	/*
	 * Background operation returns with no action as there was no connect
	 * event
	 */

	if (errorCodePtr == NULL) {
771
772
773
774
775
776
777
778

779
780
781
782
783
784
785
786
787


788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815

816
817
818
819
820
821
822
823
824

825
826
827
828
829











830
831
832
833
834
835
836







-
+








-
+
+



-
-
-
-
-
-
-
-
-
-
-







 *	Reads input from the input device of the channel.
 *
 *----------------------------------------------------------------------
 */

static int
TcpInputProc(
    ClientData instanceData,	/* Socket state. */
    void *instanceData,		/* Socket state. */
    char *buf,			/* Where to store data read. */
    int bufSize,		/* How much space is available in the
				 * buffer? */
    int *errorCodePtr)		/* Where to store error code. */
{
    TcpState *statePtr = (TcpState *)instanceData;
    int bytesRead;
    DWORD error;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    TclThreadDataKeyGet(&dataKey);

    *errorCodePtr = 0;

    /*
     * Check that WinSock is initialized; do not call it if not, to prevent
     * system crashes. This can happen at exit time if the exit handler for
     * WinSock ran before other exit handlers that want to use sockets.
     */

    if (!SocketsEnabled()) {
	*errorCodePtr = EFAULT;
	return -1;
    }

    /*
     * First check to see if EOF was already detected, to prevent calling the
     * socket stack after the first time EOF is detected.
     */

    if (GOT_BITS(statePtr->flags, SOCKET_EOF)) {
	return 0;
826
827
828
829
830
831
832
833
834
835



836
837
838
839
840
841
842
854
855
856
857
858
859
860



861
862
863
864
865
866
867
868
869
870







-
-
-
+
+
+







     * using non-blocking sockets.
     */

    while (1) {
	SendSelectMessage(tsdPtr, UNSELECT, statePtr);

	/*
         * Single fd operation: this proc is only called for a connected
         * socket.
         */
	 * Single fd operation: this proc is only called for a connected
	 * socket.
	 */

	bytesRead = recv(statePtr->sockets->fd, buf, bufSize, 0);
	CLEAR_BITS(statePtr->readyEvents, FD_READ);

	/*
	 * Check for end-of-file condition or successful read.
	 */
859
860
861
862
863
864
865
866

867
868
869
870
871
872
873
874
875
876
877
878
879
880
881


882
883
884
885
886
887
888
887
888
889
890
891
892
893

894
895
896
897
898
899
900
901
902
903
904
905
906
907


908
909
910
911
912
913
914
915
916







-
+













-
-
+
+







	    break;
	}

	error = WSAGetLastError();

	/*
	 * If an RST comes, then ignore the error and report an EOF just like
	 * on unix.
	 * on Unix.
	 */

	if (error == WSAECONNRESET) {
	    SET_BITS(statePtr->flags, SOCKET_EOF);
	    bytesRead = 0;
	    break;
	}

	/*
	 * Check for error condition or underflow in non-blocking case.
	 */

	if (GOT_BITS(statePtr->flags, TCP_NONBLOCKING)
                || (error != WSAEWOULDBLOCK)) {
	    TclWinConvertError(error);
		|| (error != WSAEWOULDBLOCK)) {
	    Tcl_WinConvertError(error);
	    *errorCodePtr = Tcl_GetErrno();
	    bytesRead = -1;
	    break;
	}

	/*
	 * In the blocking case, wait until the file becomes readable or
915
916
917
918
919
920
921
922

923
924
925
926
927
928
929
930


931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961



962
963
964
965
966
967
968
943
944
945
946
947
948
949

950
951
952
953
954
955
956
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







-
+







-
+
+



-
-
-
-
-
-
-
-
-
-
-














-
-
-
+
+
+







 *	Produces output on the socket.
 *
 *----------------------------------------------------------------------
 */

static int
TcpOutputProc(
    ClientData instanceData,	/* Socket state. */
    void *instanceData,		/* Socket state. */
    const char *buf,		/* The data buffer. */
    int toWrite,		/* How many bytes to write? */
    int *errorCodePtr)		/* Where to store error code. */
{
    TcpState *statePtr = (TcpState *)instanceData;
    int written;
    DWORD error;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    TclThreadDataKeyGet(&dataKey);

    *errorCodePtr = 0;

    /*
     * Check that WinSock is initialized; do not call it if not, to prevent
     * system crashes. This can happen at exit time if the exit handler for
     * WinSock ran before other exit handlers that want to use sockets.
     */

    if (!SocketsEnabled()) {
	*errorCodePtr = EFAULT;
	return -1;
    }

    /*
     * Check if there is an async connect running.
     * For blocking sockets terminate connect, otherwise do one step.
     * For a non blocking socket return EWOULDBLOCK if connect not terminated
     */

    if (WaitForConnect(statePtr, errorCodePtr) != 0) {
	return -1;
    }

    while (1) {
	SendSelectMessage(tsdPtr, UNSELECT, statePtr);

	/*
         * Single fd operation: this proc is only called for a connected
         * socket.
         */
	 * Single fd operation: this proc is only called for a connected
	 * socket.
	 */

	written = send(statePtr->sockets->fd, buf, toWrite, 0);
	if (written != SOCKET_ERROR) {
	    /*
	     * Since Windows won't generate a new write event until we hit an
	     * overflow condition, we need to force the event loop to poll
	     * until the condition changes.
988
989
990
991
992
993
994
995

996
997
998
999
1000
1001
1002
1006
1007
1008
1009
1010
1011
1012

1013
1014
1015
1016
1017
1018
1019
1020







-
+







	    CLEAR_BITS(statePtr->readyEvents, FD_WRITE);
	    if (GOT_BITS(statePtr->flags, TCP_NONBLOCKING)) {
		*errorCodePtr = EWOULDBLOCK;
		written = -1;
		break;
	    }
	} else {
	    TclWinConvertError(error);
	    Tcl_WinConvertError(error);
	    *errorCodePtr = Tcl_GetErrno();
	    written = -1;
	    break;
	}

	/*
	 * In the blocking case, wait until the file becomes writable or
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
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







-
+








-
-
-
-
-
-
-
-
-
-
-
+
+
+
+

-
-
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-

-
+


-
+












-
-
+
+






-
-
+
+







 *	Closes the socket.
 *
 *----------------------------------------------------------------------
 */

static int
TcpCloseProc(
    ClientData instanceData,	/* The socket to close. */
    void *instanceData,		/* The socket to close. */
    TCL_UNUSED(Tcl_Interp *))
{
    TcpState *statePtr = (TcpState *)instanceData;
    /* TIP #218 */
    int errorCode = 0;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    /*
     * Check that WinSock is initialized; do not call it if not, to prevent
     * system crashes. This can happen at exit time if the exit handler for
     * WinSock ran before other exit handlers that want to use sockets.
     */

    if (SocketsEnabled()) {
	/*
	 * Clean up the OS socket handle. The default Windows setting for a
	 * socket is SO_DONTLINGER, which does a graceful shutdown in the
	 * background.
	 */
     * Clean up the OS socket handle. The default Windows setting for a
     * socket is SO_DONTLINGER, which does a graceful shutdown in the
     * background.
     */

	while (statePtr->sockets != NULL) {
	    TcpFdList *thisfd = statePtr->sockets;
    while (statePtr->sockets != NULL) {
	TcpFdList *thisfd = statePtr->sockets;

	    statePtr->sockets = thisfd->next;
	    if (closesocket(thisfd->fd) == SOCKET_ERROR) {
		TclWinConvertError((DWORD) WSAGetLastError());
		errorCode = Tcl_GetErrno();
	    }
	    Tcl_Free(thisfd);
	}
    }
	statePtr->sockets = thisfd->next;
	if (closesocket(thisfd->fd) == SOCKET_ERROR) {
	    Tcl_WinConvertError((DWORD) WSAGetLastError());
	    errorCode = Tcl_GetErrno();
	}
	Tcl_Free(thisfd);
    }


    if (statePtr->addrlist != NULL) {
        freeaddrinfo(statePtr->addrlist);
	freeaddrinfo(statePtr->addrlist);
    }
    if (statePtr->myaddrlist != NULL) {
        freeaddrinfo(statePtr->myaddrlist);
	freeaddrinfo(statePtr->myaddrlist);
    }

    /*
     * Clear an eventual tsd info list pointer.
     *
     * This may be called, if an async socket connect fails or is closed
     * between connect and thread action callback.
     */

    if (tsdPtr->pendingTcpState != NULL
	    && tsdPtr->pendingTcpState == statePtr) {
	/*
         * Get infoPtr lock, because this concerns the notifier thread.
         */
	 * Get infoPtr lock, because this concerns the notifier thread.
	 */

	WaitForSingleObject(tsdPtr->socketListLock, INFINITE);

	tsdPtr->pendingTcpState = NULL;

	/*
         * Free list lock.
         */
	 * Free list lock.
	 */

	SetEvent(tsdPtr->socketListLock);
    }

    /*
     * TIP #218. Removed the code removing the structure from the global
     * socket list. This is now done by the thread action callbacks, and only
1124
1125
1126
1127
1128
1129
1130
1131

1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143

1144
1145
1146
1147
1148
1149
1150
1151

1152
1153


1154
1155

1156
1157


1158
1159
1160
1161
1162
1163
1164
1134
1135
1136
1137
1138
1139
1140

1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152

1153
1154
1155
1156
1157
1158
1159
1160
1161
1162


1163
1164
1165
1166
1167


1168
1169
1170
1171
1172
1173
1174
1175
1176







-
+











-
+








+
-
-
+
+


+
-
-
+
+







 *	Shuts down one side of the socket.
 *
 *----------------------------------------------------------------------
 */

static int
TcpClose2Proc(
    ClientData instanceData,	/* The socket to close. */
    void *instanceData,		/* The socket to close. */
    Tcl_Interp *interp,		/* For error reporting. */
    int flags)			/* Flags that indicate which side to close. */
{
    TcpState *statePtr = (TcpState *)instanceData;
    int readError = 0;
    int writeError = 0;

    /*
     * Shutdown the OS socket handle.
     */

    if ((flags & (TCL_CLOSE_READ|TCL_CLOSE_WRITE)) == 0) {
    if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) == 0) {
	return TcpCloseProc(instanceData, interp);
    }

    /*
     * Single fd operation: Tcl_OpenTcpServer() does not set TCL_READABLE or
     * TCL_WRITABLE so this should never be called for a server socket.
     */

    if ((flags & TCL_CLOSE_READ)
    if ((flags & TCL_CLOSE_READ) && (shutdown(statePtr->sockets->fd, SD_RECEIVE) == SOCKET_ERROR)) {
	TclWinConvertError((DWORD) WSAGetLastError());
	    && (shutdown(statePtr->sockets->fd, SD_RECEIVE) == SOCKET_ERROR)) {
	Tcl_WinConvertError((DWORD) WSAGetLastError());
	readError = Tcl_GetErrno();
    }
    if ((flags & TCL_CLOSE_WRITE)
    if ((flags & TCL_CLOSE_WRITE) && (shutdown(statePtr->sockets->fd, SD_SEND) == SOCKET_ERROR)) {
	TclWinConvertError((DWORD) WSAGetLastError());
	    && (shutdown(statePtr->sockets->fd, SD_SEND) == SOCKET_ERROR)) {
	Tcl_WinConvertError((DWORD) WSAGetLastError());
	writeError = Tcl_GetErrno();
    }
    return (readError != 0) ? readError : writeError;
}

/*
 *----------------------------------------------------------------------
1174
1175
1176
1177
1178
1179
1180
1181

1182
1183
1184

1185
1186
1187

1188
1189
1190
1191
1192

1193
1194
1195
1196
1197
1198
1199
1200

1201
1202
1203
1204

1205
1206
1207
1208
1209
1210

1211
1212
1213



1214
1215
1216
1217
1218
1219
1220
1221
1222

1223
1224

1225
1226
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
1186
1187
1188
1189
1190
1191
1192

1193
1194
1195

1196
1197


1198
1199




1200





1201


1202




1203
1204
1205


1206
1207
1208



1209
1210
1211
1212
1213
1214
1215



1216

1217
1218

1219
1220
1221
1222
1223
1224
1225
1226
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







-
+


-
+

-
-
+

-
-
-
-
+
-
-
-
-
-

-
-
+
-
-
-
-
+


-
-


+
-
-
-
+
+
+




-
-
-

-
+

-
+








+
+
-
-
-
+
+
+




-
-
-

-
+

-
+









-
-
+
-
-
-







 *	Changes attributes of the socket at the system level.
 *
 *----------------------------------------------------------------------
 */

static int
TcpSetOptionProc(
    ClientData instanceData,	/* Socket state. */
    void *instanceData,		/* Socket state. */
    Tcl_Interp *interp,		/* For error reporting - can be NULL. */
    const char *optionName,	/* Name of the option to set. */
    TCL_UNUSED(const char *) /*value*/)		/* New value for option. */
    const char *value)		/* New value for option. */
{
#ifdef TCL_FEATURE_KEEPALIVE_NAGLE
    TcpState *statePtr = instanceData;
    TcpState *statePtr = (TcpState *)instanceData;
    SOCKET sock;
#else
    (void)instanceData;
#endif /*TCL_FEATURE_KEEPALIVE_NAGLE*/

    size_t len = 0;
    /*
     * Check that WinSock is initialized; do not call it if not, to prevent
     * system crashes. This can happen at exit time if the exit handler for
     * WinSock ran before other exit handlers that want to use sockets.
     */

    if (!SocketsEnabled()) {
	if (interp) {
    if (optionName != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "winsock is not initialized", -1));
	}
	return TCL_ERROR;
	len = strlen(optionName);
    }

#ifdef TCL_FEATURE_KEEPALIVE_NAGLE
#error "TCL_FEATURE_KEEPALIVE_NAGLE not reviewed for whether to treat statePtr->sockets as single fd or list"
    sock = statePtr->sockets->fd;

    if ((len > 1) && (optionName[1] == 'k') &&
    if (!strcasecmp(optionName, "-keepalive")) {
	BOOL val = FALSE;
	int boolVar, rtn;
	    (strncmp(optionName, "-keepalive", len) == 0)) {
	BOOL boolVar;
	int rtn;

	if (Tcl_GetBoolean(interp, value, &boolVar) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (boolVar) {
	    val = TRUE;
	}
	rtn = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
		(const char *) &val, sizeof(BOOL));
		(const char *) &boolVar, sizeof(boolVar));
	if (rtn != 0) {
	    TclWinConvertError(WSAGetLastError());
	    Tcl_WinConvertError(WSAGetLastError());
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"couldn't set socket option: %s",
			Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}
	return TCL_OK;
    }
    if ((len > 1) && (optionName[1] == 'n') &&
    } else if (!strcasecmp(optionName, "-nagle")) {
	BOOL val = FALSE;
	int boolVar, rtn;
	    (strncmp(optionName, "-nodelay", len) == 0)) {
	BOOL boolVar;
	int rtn;

	if (Tcl_GetBoolean(interp, value, &boolVar) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (!boolVar) {
	    val = TRUE;
	}
	rtn = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
		(const char *) &val, sizeof(BOOL));
		(const char *) &boolVar, sizeof(boolVar));
	if (rtn != 0) {
	    TclWinConvertError(WSAGetLastError());
	    Tcl_WinConvertError(WSAGetLastError());
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"couldn't set socket option: %s",
			Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}
	return TCL_OK;
    }

    return Tcl_BadChannelOption(interp, optionName, "keepalive nagle");
    return Tcl_BadChannelOption(interp, optionName, "keepalive nodelay");
#else
    return Tcl_BadChannelOption(interp, optionName, "");
#endif /*TCL_FEATURE_KEEPALIVE_NAGLE*/
}

/*
 *----------------------------------------------------------------------
 *
 * TcpGetOptionProc --
 *
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
1354
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







-
+













-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+




-
+



-
+








-
-
+

-
-
+
+











-
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TcpGetOptionProc(
    ClientData instanceData,	/* Socket state. */
    void *instanceData,		/* Socket state. */
    Tcl_Interp *interp,		/* For error reporting - can be NULL. */
    const char *optionName,	/* Name of the option to retrieve the value
				 * for, or NULL to get all options and their
				 * values. */
    Tcl_DString *dsPtr)		/* Where to store the computed value;
				 * initialized by caller. */
{
    TcpState *statePtr = (TcpState *)instanceData;
    char host[NI_MAXHOST], port[NI_MAXSERV];
    SOCKET sock;
    size_t len = 0;
    int reverseDNS = 0;
#define SUPPRESS_RDNS_VAR "::tcl::unsupported::noReverseDNS"

#define HAVE_OPTION(option) \
    /*
     * Check that WinSock is initialized; do not call it if not, to prevent
     * system crashes. This can happen at exit time if the exit handler for
     * WinSock ran before other exit handlers that want to use sockets.
     */

	((len > 1) && (optionName[1] == option[1]) && \
    if (!SocketsEnabled()) {
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "winsock is not initialized", -1));
	}
	return TCL_ERROR;
    }
	    (strncmp(optionName, option, len) == 0))

    /*
     * Go one step in async connect
     *
     * If any error is thrown save it as backround error to report eventually
     * If any error is thrown save it as background error to report eventually
     * below.
     */

    if (!GOT_BITS(statePtr->testFlags, TCP_ASYNC_TEST_MODE)) {
    if (!GOT_BITS(statePtr->flags, TCP_ASYNC_TEST_MODE)) {
	WaitForConnect(statePtr, NULL);
    }

    sock = statePtr->sockets->fd;
    if (optionName != NULL) {
	len = strlen(optionName);
    }

    if ((len > 1) && (optionName[1] == 'e') &&
	    (strncmp(optionName, "-error", len) == 0)) {
    if (HAVE_OPTION("-error")) {
	/*
         * Do not return any errors if async connect is running.
         */
	 * Do not return any errors if async connect is running.
	 */

	if (!GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) {
	    if (GOT_BITS(statePtr->flags, TCP_ASYNC_FAILED)) {
		/*
		 * In case of a failed async connect, eventually report the
		 * connect error only once.  Do not report the system error,
		 * as this comes again and again.
		 */

		if (statePtr->connectError != 0) {
		    Tcl_DStringAppend(dsPtr,
			    Tcl_ErrnoMsg(statePtr->connectError), -1);
			    Tcl_ErrnoMsg(statePtr->connectError),
			    TCL_INDEX_NONE);
		    statePtr->connectError = 0;
		}
	    } else {
		/*
		 * Report an eventual last error of the socket system.
		 */

1374
1375
1376
1377
1378
1379
1380
1381

1382
1383

1384
1385
1386
1387
1388
1389
1390
1391

1392
1393
1394
1395


1396
1397
1398
1399

1400
1401
1402
1403

1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420

1421
1422
1423
1424
1425
1426
1427
1353
1354
1355
1356
1357
1358
1359

1360
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
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396

1397
1398
1399
1400
1401
1402
1403
1404







-
+

-
+






-
-
+


-
-
+
+



-
+



-
+
-















-
+







		}

		/*
		 * Return error message.
		 */

		if (err) {
		    TclWinConvertError(err);
		    Tcl_WinConvertError(err);
		    Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(Tcl_GetErrno()),
                            -1);
			    TCL_INDEX_NONE);
		}
	    }
	}
	return TCL_OK;
    }

    if ((len > 1) && (optionName[1] == 'c') &&
	    (strncmp(optionName, "-connecting", len) == 0)) {
    if (HAVE_OPTION("-connecting")) {
	Tcl_DStringAppend(dsPtr,
		GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)
		? "1" : "0", -1);
        return TCL_OK;
		? "1" : "0", TCL_INDEX_NONE);
	return TCL_OK;
    }

    if (interp != NULL
            && Tcl_GetVar2(interp, SUPPRESS_RDNS_VAR, NULL, 0) != NULL) {
	    && Tcl_GetVar(interp, SUPPRESS_RDNS_VAR, 0) != NULL) {
	reverseDNS = NI_NUMERICHOST;
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 'p') &&
    if ((len == 0) || HAVE_OPTION("-peername")) {
	    (strncmp(optionName, "-peername", len) == 0))) {
	address peername;
	socklen_t size = sizeof(peername);

	if (GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) {
	    /*
	     * In async connect output an empty string
	     */

	    if (len == 0) {
		Tcl_DStringAppendElement(dsPtr, "-peername");
		Tcl_DStringAppendElement(dsPtr, "");
	    } else {
		return TCL_OK;
	    }
	} else if (getpeername(sock, (LPSOCKADDR) &(peername.sa),
                &size) == 0) {
		&size) == 0) {
	    /*
	     * Peername fetch succeeded - output list
	     */

	    if (len == 0) {
		Tcl_DStringAppendElement(dsPtr, "-peername");
		Tcl_DStringStartSublist(dsPtr);
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
1474
1475
1476
1477
1478

1479
1480
1481
1482
1483
1484
1485
1421
1422
1423
1424
1425
1426
1427

1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438

1439

1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453

1454
1455
1456
1457
1458
1459
1460
1461







-
+










-
+
-














-
+







	     * getpeername failed - but if we were asked for all the options
	     * (len==0), don't flag an error at that point because it could be
	     * an fconfigure request on a server socket (such sockets have no
	     * peer). {Copied from unix/tclUnixChan.c}
	     */

	    if (len) {
		TclWinConvertError((DWORD) WSAGetLastError());
		Tcl_WinConvertError((DWORD) WSAGetLastError());
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "can't get peername: %s",
			    Tcl_PosixError(interp)));
		}
		return TCL_ERROR;
	    }
	}
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 's') &&
    if ((len == 0) || HAVE_OPTION("-sockname")) {
	    (strncmp(optionName, "-sockname", len) == 0))) {
	TcpFdList *fds;
	address sockname;
	socklen_t size;
	int found = 0;

	if (len == 0) {
	    Tcl_DStringAppendElement(dsPtr, "-sockname");
	    Tcl_DStringStartSublist(dsPtr);
	}
	if (GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) {
	    /*
	     * In async connect output an empty string
	     */

            found = 1;
	    found = 1;
	} else {
	    for (fds = statePtr->sockets; fds != NULL; fds = fds->next) {
		sock = fds->fd;
		size = sizeof(sockname);
		if (getsockname(sock, &(sockname.sa), &size) >= 0) {
		    int flags = reverseDNS;

1520
1521
1522
1523
1524
1525
1526
1527

1528
1529
1530
1531
1532
1533
1534
1535
1536

1537
1538
1539
1540

1541
1542
1543
1544
1545
1546
1547
1548













1549



1550
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
1496
1497
1498
1499
1500
1501
1502

1503
1504
1505
1506
1507
1508
1509
1510


1511
1512
1513
1514
1515
1516
1517
1518
1519
1520




1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542















1543







1544




1545

1546
1547
1548
1549
1550
1551
1552







-
+







-
-
+




+




-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-

-
-
-
-
+
-







	if (found) {
	    if (len) {
		return TCL_OK;
	    }
	    Tcl_DStringEndSublist(dsPtr);
	} else {
	    if (interp) {
		TclWinConvertError((DWORD) WSAGetLastError());
		Tcl_WinConvertError((DWORD) WSAGetLastError());
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't get sockname: %s", Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}
    }

#ifdef TCL_FEATURE_KEEPALIVE_NAGLE
    if (len == 0 || !strncmp(optionName, "-keepalive", len)) {
    if ((len == 0) || HAVE_OPTION("-keepalive")) {
	int optlen;
	BOOL opt = FALSE;

	if (len == 0) {
	    sock = statePtr->sockets->fd;
	    Tcl_DStringAppendElement(dsPtr, "-keepalive");
	}
	optlen = sizeof(BOOL);
	getsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&opt, &optlen);
	if (opt) {
	    Tcl_DStringAppendElement(dsPtr, "1");
	} else {
	    Tcl_DStringAppendElement(dsPtr, "0");
	Tcl_DStringAppendElement(dsPtr, opt ? "1" : "0");
	if (len > 0) {
	    return TCL_OK;
	}
    }

    if ((len == 0) || HAVE_OPTION("-nodelay")) {
	int optlen;
	BOOL opt = FALSE;

	if (len == 0) {
	    sock = statePtr->sockets->fd;
	    Tcl_DStringAppendElement(dsPtr, "-nodelay");
	}
	optlen = sizeof(BOOL);
	getsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, &optlen);
	Tcl_DStringAppendElement(dsPtr, opt ? "1" : "0");
	if (len > 0) {
	    return TCL_OK;
	}
    }

    if (len == 0 || !strncmp(optionName, "-nagle", len)) {
	int optlen;
	BOOL opt = FALSE;

	if (len == 0) {
	    Tcl_DStringAppendElement(dsPtr, "-nagle");
	}
	optlen = sizeof(BOOL);
	getsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, &optlen);
	if (opt) {
	    Tcl_DStringAppendElement(dsPtr, "0");
	} else {
	    Tcl_DStringAppendElement(dsPtr, "1");
	}
	if (len > 0) {
    if (len > 0) {
	    return TCL_OK;
	}
    }
#endif /*TCL_FEATURE_KEEPALIVE_NAGLE*/

    if (len > 0) {
#ifdef TCL_FEATURE_KEEPALIVE_NAGLE
	return Tcl_BadChannelOption(interp, optionName,
		"connecting peername sockname keepalive nagle");
#else
	return Tcl_BadChannelOption(interp, optionName,
                "connecting peername sockname");
		"connecting keepalive nodelay peername sockname");
#endif /*TCL_FEATURE_KEEPALIVE_NAGLE*/
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
1601
1602
1603
1604
1605
1606
1607
1608

1609
1610
1611
1612
1613
1614
1615
1564
1565
1566
1567
1568
1569
1570

1571
1572
1573
1574
1575
1576
1577
1578







-
+







 *	already true.
 *
 *----------------------------------------------------------------------
 */

static void
TcpWatchProc(
    ClientData instanceData,	/* The socket state. */
    void *instanceData,		/* The socket state. */
    int mask)			/* Events of interest; an OR-ed combination of
				 * TCL_READABLE, TCL_WRITABLE and
				 * TCL_EXCEPTION. */
{
    TcpState *statePtr = (TcpState *)instanceData;

    /*
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
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







-
+

-
+






-
-















-
-
-
+
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TcpGetHandleProc(
    ClientData instanceData,	/* The socket state. */
    void *instanceData,		/* The socket state. */
    TCL_UNUSED(int) /*direction*/,
    ClientData *handlePtr)	/* Where to store the handle. */
    void **handlePtr)		/* Where to store the handle. */
{
    TcpState *statePtr = (TcpState *)instanceData;

    *handlePtr = INT2PTR(statePtr->sockets->fd);
    return TCL_OK;
}



/*
 *----------------------------------------------------------------------
 *
 * TcpConnect --
 *
 *	This function opens a new socket in client mode.
 *
 *	This might be called in 3 circumstances:
 *	-   By a regular socket command
 *	-   By the event handler to continue an asynchronously connect
 *	-   By a blocking socket function (gets/puts) to terminate the
 *	    connect synchronously
 *
 * Results:
 *      TCL_OK, if the socket was successfully connected or an asynchronous
 *      connection is in progress. If an error occurs, TCL_ERROR is returned
 *      and an error message is left in interp.
 *	TCL_OK, if the socket was successfully connected or an asynchronous
 *	connection is in progress. If an error occurs, TCL_ERROR is returned
 *	and an error message is left in interp.
 *
 * Side effects:
 *	Opens a socket.
 *
 * Remarks:
 *	A single host name may resolve to more than one IP address, e.g. for
 *	an IPv4/IPv6 dual stack host. For handling asynchronously connecting
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
1749
1750
1751
1752
1753
1754


1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766

1767
1768
1769
1770


1771
1772
1773
1774
1775
1776


1777
1778
1779

1780
1781
1782
1783
1784
1785
1786
1787
1788
1789

1790
1791
1792
1793
1794
1795
1796


1797
1798
1799
1800
1801
1802
1803
1804

1805
1806
1807
1808
1809

1810
1811
1812
1813
1814
1815
1816
1817
1818
1819


1820
1821
1822
1823
1824
1825
1826
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
1749
1750

1751
1752
1753
1754
1755
1756


1757
1758
1759
1760
1761
1762
1763
1764
1765

1766
1767
1768
1769
1770

1771
1772
1773
1774
1775
1776
1777
1778
1779


1780
1781
1782
1783
1784
1785
1786
1787
1788







-
-
-
+
+
+

-
-
-
+
+
+
+


-
+




-
-
-
+
+
+









-
-
-
-
+
+
+
+






-
-
+
+











-
+


-
-
+
+




-
-
+
+


-
+









-
+





-
-
+
+







-
+




-
+








-
-
+
+







static int
TcpConnect(
    Tcl_Interp *interp,		/* For error reporting; can be NULL. */
    TcpState *statePtr)
{
    DWORD error;
    int async_connect = GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
                                /* We are started with async connect and the
                                 * connect notification was not yet
                                 * received. */
				/* We are started with async connect and the
				 * connect notification was not yet
				 * received. */
    int async_callback = GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING);
                                /* We were called by the event procedure and
                                 * continue our loop. */
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
				/* We were called by the event procedure and
				 * continue our loop. */
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    TclThreadDataKeyGet(&dataKey);

    if (async_callback) {
        goto reenter;
	goto reenter;
    }

    for (statePtr->addr = statePtr->addrlist; statePtr->addr != NULL;
	    statePtr->addr = statePtr->addr->ai_next) {
        for (statePtr->myaddr = statePtr->myaddrlist;
                statePtr->myaddr != NULL;
                statePtr->myaddr = statePtr->myaddr->ai_next) {
	for (statePtr->myaddr = statePtr->myaddrlist;
		statePtr->myaddr != NULL;
		statePtr->myaddr = statePtr->myaddr->ai_next) {
	    /*
	     * No need to try combinations of local and remote addresses
	     * of different families.
	     */

	    if (statePtr->myaddr->ai_family != statePtr->addr->ai_family) {
		continue;
	    }

            /*
             * Close the socket if it is still open from the last unsuccessful
             * iteration.
             */
	    /*
	     * Close the socket if it is still open from the last unsuccessful
	     * iteration.
	     */

	    if (statePtr->sockets->fd != INVALID_SOCKET) {
		closesocket(statePtr->sockets->fd);
	    }

	    /*
             * Get statePtr lock.
             */
	     * Get statePtr lock.
	     */

	    WaitForSingleObject(tsdPtr->socketListLock, INFINITE);

	    /*
	     * Reset last error from last try
	     */

	    statePtr->notifierConnectError = 0;
	    Tcl_SetErrno(0);

	    statePtr->sockets->fd = socket(statePtr->myaddr->ai_family,
                    SOCK_STREAM, 0);
		    SOCK_STREAM, 0);

	    /*
             * Free list lock.
             */
	     * Free list lock.
	     */

	    SetEvent(tsdPtr->socketListLock);

	    /*
             * Continue on socket creation error.
             */
	     * Continue on socket creation error.
	     */

	    if (statePtr->sockets->fd == INVALID_SOCKET) {
		TclWinConvertError((DWORD) WSAGetLastError());
		Tcl_WinConvertError((DWORD) WSAGetLastError());
		continue;
	    }

	    /*
	     * Win-NT has a misfeature that sockets are inherited in child
	     * processes by default. Turn off the inherit bit.
	     */

	    SetHandleInformation((HANDLE) statePtr->sockets->fd,
                    HANDLE_FLAG_INHERIT, 0);
		    HANDLE_FLAG_INHERIT, 0);

	    /*
	     * Set kernel space buffering
	     */

	    TclSockMinimumBuffers((void *) statePtr->sockets->fd,
                    TCP_BUFFER_SIZE);
	    TclSockMinimumBuffers((void *)statePtr->sockets->fd,
		    TCP_BUFFER_SIZE);

	    /*
	     * Try to bind to a local port.
	     */

	    if (bind(statePtr->sockets->fd, statePtr->myaddr->ai_addr,
		    statePtr->myaddr->ai_addrlen) == SOCKET_ERROR) {
		TclWinConvertError((DWORD) WSAGetLastError());
		Tcl_WinConvertError((DWORD) WSAGetLastError());
		continue;
	    }

	    /*
	     * For asynchroneous connect set the socket in nonblocking mode
	     * For asynchronous connect set the socket in nonblocking mode
	     * and activate connect notification
	     */

	    if (async_connect) {
		TcpState *statePtr2;
		int in_socket_list = 0;

		/*
                 * Get statePtr lock.
                 */
		 * Get statePtr lock.
		 */

		WaitForSingleObject(tsdPtr->socketListLock, INFINITE);

		/*
		 * Bugfig for 336441ed59 to not ignore notifications until the
		 * infoPtr is in the list.
		 * Check if my statePtr is already in the tsdPtr->socketList
1840
1841
1842
1843
1844
1845
1846
1847

1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862



1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875

1876
1877
1878
1879

1880
1881
1882
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
1802
1803
1804
1805
1806
1807
1808

1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821



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

1837
1838
1839
1840

1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859


1860
1861
1862
1863
1864
1865


1866
1867
1868

1869
1870
1871


1872
1873
1874
1875
1876
1877


1878
1879
1880
1881
1882
1883
1884
1885

1886
1887
1888
1889
1890
1891
1892
1893







-
+












-
-
-
+
+
+












-
+



-
+


















-
-
+
+




-
-
+
+

-
+


-
-
+
+




-
-
+
+






-
+







		}
		if (!in_socket_list) {
		    tsdPtr->pendingTcpState = statePtr;
		}

		/*
		 * Set connect mask to connect events
                 *
		 *
		 * This is activated by a SOCKET_SELECT message to the
		 * notifier thread.
		 */

		SET_BITS(statePtr->selectEvents, FD_CONNECT);

		/*
		 * Free list lock.
		 */

		SetEvent(tsdPtr->socketListLock);

    		/*
                 * Activate accept notification.
                 */
		/*
		 * Activate accept notification.
		 */

		SendSelectMessage(tsdPtr, SELECT, statePtr);
	    }

	    /*
	     * Attempt to connect to the remote socket.
	     */

	    connect(statePtr->sockets->fd, statePtr->addr->ai_addr,
		    statePtr->addr->ai_addrlen);

	    error = WSAGetLastError();
	    TclWinConvertError(error);
	    Tcl_WinConvertError(error);

	    if (async_connect && error == WSAEWOULDBLOCK) {
		/*
		 * Asynchroneous connect
		 * Asynchronous connect
		 *
		 * Remember that we jump back behind this next round
		 */

		SET_BITS(statePtr->flags, TCP_ASYNC_PENDING);
		return TCL_OK;

	    reenter:
		/*
		 * Re-entry point for async connect after connect event or
		 * blocking operation
		 *
		 * Clear the reenter flag
		 */

		CLEAR_BITS(statePtr->flags, TCP_ASYNC_PENDING);

		/*
                 * Get statePtr lock.
                 */
		 * Get statePtr lock.
		 */

		WaitForSingleObject(tsdPtr->socketListLock, INFINITE);

		/*
                 * Get signaled connect error.
                 */
		 * Get signaled connect error.
		 */

		TclWinConvertError((DWORD) statePtr->notifierConnectError);
		Tcl_WinConvertError((DWORD) statePtr->notifierConnectError);

		/*
                 * Clear eventual connect flag.
                 */
		 * Clear eventual connect flag.
		 */

		CLEAR_BITS(statePtr->selectEvents, FD_CONNECT);

		/*
                 * Free list lock.
                 */
		 * Free list lock.
		 */

		SetEvent(tsdPtr->socketListLock);
	    }

	    /*
	     * Clear the tsd socket list pointer if we did not wait for
	     * the FD_CONNECT asynchroneously
	     * the FD_CONNECT asynchronously
	     */

	    tsdPtr->pendingTcpState = NULL;

	    if (Tcl_GetErrno() == 0) {
		goto out;
	    }
1941
1942
1943
1944
1945
1946
1947
1948

1949
1950
1951
1952
1953
1954
1955
1903
1904
1905
1906
1907
1908
1909

1910
1911
1912
1913
1914
1915
1916
1917







-
+







     * Async connect terminated
     */

    CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT);

    if (Tcl_GetErrno() == 0) {
	/*
	 * Succesfully connected
	 * Successfully connected
	 *
	 * Set up the select mask for read/write events.
	 */

	statePtr->selectEvents = FD_READ | FD_WRITE | FD_CLOSE;

	/*
1969
1970
1971
1972
1973
1974
1975
1976
1977


1978
1979
1980
1981
1982
1983


1984
1985
1986
1987
1988
1989


1990
1991
1992
1993
1994
1995


1996
1997
1998
1999
2000
2001


2002
2003
2004
2005
2006
2007

2008
2009
2010
2011
2012
2013
2014
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
1958
1959
1960
1961


1962
1963
1964
1965
1966
1967
1968

1969
1970
1971
1972
1973
1974
1975
1976







-
-
+
+




-
-
+
+




-
-
+
+




-
-
+
+




-
-
+
+





-
+







	    /*
	     * Set up the select mask for read/write events.
	     */

	    statePtr->selectEvents = FD_WRITE|FD_READ;

	    /*
             * Get statePtr lock.
             */
	     * Get statePtr lock.
	     */

	    WaitForSingleObject(tsdPtr->socketListLock, INFINITE);

	    /*
             * Signal ready readable and writable events.
             */
	     * Signal ready readable and writable events.
	     */

	    SET_BITS(statePtr->readyEvents, FD_WRITE | FD_READ);

	    /*
             * Flag error to event routine.
             */
	     * Flag error to event routine.
	     */

	    SET_BITS(statePtr->flags, TCP_ASYNC_FAILED);

	    /*
             * Save connect error to be reported by 'fconfigure -error'.
             */
	     * Save connect error to be reported by 'fconfigure -error'.
	     */

	    statePtr->connectError = Tcl_GetErrno();

	    /*
             * Free list lock.
             */
	     * Free list lock.
	     */

	    SetEvent(tsdPtr->socketListLock);
	}

	/*
	 * Error message on synchroneous connect
	 * Error message on synchronous connect
	 */

	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "couldn't open socket: %s", Tcl_PosixError(interp)));
	}
	return TCL_ERROR;
2045
2046
2047
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
2095
2096
2097
2098
2099

2100
2101
2102
2103
2104
2105
2106
2007
2008
2009
2010
2011
2012
2013











2014


2015
2016
2017
2018
2019
2020










2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047


2048
2049
2050
2051
2052
2053
2054
2055







-
-
-
-
-
-
-
-
-
-
-
+
-
-






-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

















-
-
+







				 * connect. */
{
    TcpState *statePtr;
    const char *errorMsg = NULL;
    struct addrinfo *addrlist = NULL, *myaddrlist = NULL;
    char channelName[SOCK_CHAN_LENGTH];

    if (TclpHasSockets(interp) != TCL_OK) {
	return NULL;
    }

    /*
     * Check that WinSock is initialized; do not call it if not, to prevent
     * system crashes. This can happen at exit time if the exit handler for
     * WinSock ran before other exit handlers that want to use sockets.
     */

    if (!SocketsEnabled()) {
    TclInitSockets();
	return NULL;
    }

    /*
     * Do the name lookups for the local and remote addresses.
     */

    if (!TclCreateSocketAddress(interp, &addrlist, host, port, 0, &errorMsg)
            || !TclCreateSocketAddress(interp, &myaddrlist, myaddr, myport, 1,
                    &errorMsg)) {
        if (addrlist != NULL) {
            freeaddrinfo(addrlist);
        }
        if (interp != NULL) {
            Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "couldn't open socket: %s", errorMsg));
        }
        return NULL;
	    || !TclCreateSocketAddress(interp, &myaddrlist, myaddr, myport, 1,
		    &errorMsg)) {
	if (addrlist != NULL) {
	    freeaddrinfo(addrlist);
	}
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "couldn't open socket: %s", errorMsg));
	}
	return NULL;
    }

    statePtr = NewSocketInfo(INVALID_SOCKET);
    statePtr->addrlist = addrlist;
    statePtr->myaddrlist = myaddrlist;
    if (async) {
	SET_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
    }

    /*
     * Create a new client socket and wrap it in a channel.
     */
    if (TcpConnect(interp, statePtr) != TCL_OK) {
	TcpCloseProc(statePtr, NULL);
	return NULL;
    }

    sprintf(channelName, SOCK_TEMPLATE, statePtr);

    TclWinGenerateChannelName(channelName, "sock", statePtr);
    statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    statePtr, (TCL_READABLE | TCL_WRITABLE));
    if (TCL_ERROR == Tcl_SetChannelOption(NULL, statePtr->channel,
	    "-translation", "auto crlf")) {
	Tcl_CloseEx(NULL, statePtr->channel, 0);
	return NULL;
    } else if (TCL_ERROR == Tcl_SetChannelOption(NULL, statePtr->channel,
2125
2126
2127
2128
2129
2130
2131
2132

2133
2134
2135
2136
2137

2138
2139
2140
2141
2142



2143
2144
2145
2146
2147
2148
2149
2150

2151
2152
2153
2154
2155
2156
2157
2158
2159


2160
2161
2162
2163
2164
2165
2166
2074
2075
2076
2077
2078
2079
2080

2081
2082




2083





2084
2085
2086
2087
2088
2089
2090
2091
2092
2093

2094
2095
2096
2097
2098
2099
2100
2101
2102

2103
2104
2105
2106
2107
2108
2109
2110
2111







-
+

-
-
-
-
+
-
-
-
-
-
+
+
+







-
+








-
+
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Channel
Tcl_MakeTcpClientChannel(
    ClientData sock)		/* The socket to wrap up into a channel. */
    void *sock)			/* The socket to wrap up into a channel. */
{
    TcpState *statePtr;
    char channelName[SOCK_CHAN_LENGTH];
    ThreadSpecificData *tsdPtr;

    TclInitSockets();
    if (TclpHasSockets(NULL) != TCL_OK) {
	return NULL;
    }

    tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);

    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    TclThreadDataKeyGet(&dataKey);

    /*
     * Set kernel space buffering and non-blocking.
     */

    TclSockMinimumBuffers(sock, TCP_BUFFER_SIZE);

    statePtr = NewSocketInfo((SOCKET) sock);
    TcpState *statePtr = NewSocketInfo((SOCKET) sock);

    /*
     * Start watching for read/write events on the socket.
     */

    statePtr->selectEvents = FD_READ | FD_CLOSE | FD_WRITE;
    SendSelectMessage(tsdPtr, SELECT, statePtr);

    sprintf(channelName, SOCK_TEMPLATE, statePtr);
    char channelName[SOCK_CHAN_LENGTH];
    TclWinGenerateChannelName(channelName, "sock", statePtr);
    statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    statePtr, (TCL_READABLE | TCL_WRITABLE));
    Tcl_SetChannelOption(NULL, statePtr->channel, "-translation", "auto crlf");
    return statePtr->channel;
}

/*
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
2222
2223
2224
2225
2226
2227
2228

2229
2230
2231
2232
2233
2234

2235
2236

2237
2238
2239
2240
2241
2242
2243
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138

2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150











2151


2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162

2163
2164
2165
2166
2167
2168

2169
2170

2171
2172
2173
2174
2175
2176
2177
2178







+
+



-
+











-
-
-
-
-
-
-
-
-
-
-
+
-
-











-
+





-
+

-
+








Tcl_Channel
Tcl_OpenTcpServerEx(
    Tcl_Interp *interp,		/* For error reporting - may be NULL. */
    const char *service,	/* Port number to open. */
    const char *myHost,		/* Name of local host. */
    unsigned int flags,		/* Flags. */
    int backlog,		/* Length of OS listen backlog queue, or -1
				 * for default. */
    Tcl_TcpAcceptProc *acceptProc,
				/* Callback for accepting connections from new
				 * clients. */
    ClientData acceptProcData)	/* Data for the callback. */
    void *acceptProcData)	/* Data for the callback. */
{
    SOCKET sock = INVALID_SOCKET;
    unsigned short chosenport = 0;
    struct addrinfo *addrlist = NULL;
    struct addrinfo *addrPtr;	/* Socket address to listen on. */
    TcpState *statePtr = NULL;	/* The returned value. */
    char channelName[SOCK_CHAN_LENGTH];
    u_long flag = 1;		/* Indicates nonblocking mode. */
    const char *errorMsg = NULL;
    int optvalue, port;

    if (TclpHasSockets(interp) != TCL_OK) {
	return NULL;
    }

    /*
     * Check that WinSock is initialized; do not call it if not, to prevent
     * system crashes. This can happen at exit time if the exit handler for
     * WinSock ran before other exit handlers that want to use sockets.
     */

    if (!SocketsEnabled()) {
    TclInitSockets();
	return NULL;
    }

    /*
     * Construct the addresses for each end of the socket.
     */

    if (TclSockGetPort(interp, service, "tcp", &port) != TCL_OK) {
	errorMsg = "invalid port number";
	goto error;
    }

    if (!TclCreateSocketAddress(interp, &addrlist, myHost, port, 1,
            &errorMsg)) {
	    &errorMsg)) {
	goto error;
    }

    for (addrPtr = addrlist; addrPtr != NULL; addrPtr = addrPtr->ai_next) {
	sock = socket(addrPtr->ai_family, addrPtr->ai_socktype,
                addrPtr->ai_protocol);
		addrPtr->ai_protocol);
	if (sock == INVALID_SOCKET) {
	    TclWinConvertError((DWORD) WSAGetLastError());
	    Tcl_WinConvertError((DWORD) WSAGetLastError());
	    continue;
	}

	/*
	 * Win-NT has a misfeature that sockets are inherited in child
	 * processes by default. Turn off the inherit bit.
	 */
2279
2280
2281
2282
2283
2284
2285
2286
2287


2288
2289
2290
2291
2292
2293
2294
2214
2215
2216
2217
2218
2219
2220


2221
2222
2223
2224
2225
2226
2227
2228
2229







-
-
+
+







	 *
	 * Bind should not be affected by the socket having already been
	 * set into nonblocking mode. If there is trouble, this is one
	 * place to look for bugs.
	 */

	if (bind(sock, addrPtr->ai_addr,
                addrPtr->ai_addrlen) == SOCKET_ERROR) {
	    TclWinConvertError((DWORD) WSAGetLastError());
		addrPtr->ai_addrlen) == SOCKET_ERROR) {
	    Tcl_WinConvertError((DWORD) WSAGetLastError());
	    closesocket(sock);
	    continue;
	}
	if (port == 0 && chosenport == 0) {
	    address sockname;
	    socklen_t namelen = sizeof(sockname);

2304
2305
2306
2307
2308
2309
2310



2311
2312


2313
2314
2315
2316
2317
2318
2319
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248


2249
2250
2251
2252
2253
2254
2255
2256
2257







+
+
+
-
-
+
+








	/*
	 * Set the maximum number of pending connect requests to the max
	 * value allowed on each platform (Win32 and Win32s may be
	 * different, and there may be differences between TCP/IP stacks).
	 */

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

	if (statePtr == NULL) {
	    /*
	     * Add this socket to the global list of sockets.
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
2265
2266
2267
2268
2269
2270
2271

2272
2273
2274
2275
2276

2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293

2294
2295
2296
2297
2298
2299
2300
2301

2302
2303
2304
2305
2306
2307
2308
2309







-
+
+



-
+
















-
+







-
+








  error:
    if (addrlist != NULL) {
	freeaddrinfo(addrlist);
    }

    if (statePtr != NULL) {
	ThreadSpecificData *tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
	ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
		TclThreadDataKeyGet(&dataKey);

	statePtr->acceptProc = acceptProc;
	statePtr->acceptProcData = acceptProcData;
	sprintf(channelName, SOCK_TEMPLATE, statePtr);
	TclWinGenerateChannelName(channelName, "sock", statePtr);
	statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
		statePtr, 0);
	/*
	 * Set up the select mask for connection request events.
	 */

	statePtr->selectEvents = FD_ACCEPT;

	/*
	 * Register for interest in events in the select mask. Note that this
	 * automatically places the socket into non-blocking mode.
	 */

	ioctlsocket(sock, (long) FIONBIO, &flag);
	SendSelectMessage(tsdPtr, SELECT, statePtr);
	if (Tcl_SetChannelOption(interp, statePtr->channel, "-eofchar", "")
	    == TCL_ERROR) {
		== TCL_ERROR) {
	    Tcl_CloseEx(NULL, statePtr->channel, 0);
	    return NULL;
	}
	return statePtr->channel;
    }

    if (interp != NULL) {
        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"couldn't open socket: %s",
		(errorMsg ? errorMsg : Tcl_PosixError(interp))));
    }

    if (sock != INVALID_SOCKET) {
	closesocket(sock);
    }
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394



2395
2396
2397
2398
2399
2400
2401


2402
2403
2404
2405
2406
2407
2408
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







-
-
-
+
+
+






-
+
+







 *	connection acceptance mechanism.
 *
 *----------------------------------------------------------------------
 */

static void
TcpAccept(
    TcpFdList *fds,	/* Server socket that accepted newSocket. */
    SOCKET newSocket,   /* Newly accepted socket. */
    address addr)       /* Address of new socket. */
    TcpFdList *fds,		/* Server socket that accepted newSocket. */
    SOCKET newSocket,		/* Newly accepted socket. */
    address addr)		/* Address of new socket. */
{
    TcpState *newInfoPtr;
    TcpState *statePtr = fds->statePtr;
    int len = sizeof(addr);
    char channelName[SOCK_CHAN_LENGTH];
    char host[NI_MAXHOST], port[NI_MAXSERV];
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    TclThreadDataKeyGet(&dataKey);

    /*
     * Win-NT has a misfeature that sockets are inherited in child processes
     * by default. Turn off the inherit bit.
     */

    SetHandleInformation((HANDLE) newSocket, HANDLE_FLAG_INHERIT, 0);
2416
2417
2418
2419
2420
2421
2422
2423

2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443

2444
2445

2446
2447
2448
2449
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
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
2399
2400

2401

2402
2403
2404
2405
2406

2407
2408



2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419







-
+



















-
+

-
+






-
+

-
+
-
-
+





-
+
-





-
+

-
-
-
+
+
+
+







    /*
     * Select on read/write events and create the channel.
     */

    newInfoPtr->selectEvents = (FD_READ | FD_WRITE | FD_CLOSE);
    SendSelectMessage(tsdPtr, SELECT, newInfoPtr);

    sprintf(channelName, SOCK_TEMPLATE, newInfoPtr);
    TclWinGenerateChannelName(channelName, "sock", newInfoPtr);
    newInfoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    newInfoPtr, (TCL_READABLE | TCL_WRITABLE));
    if (Tcl_SetChannelOption(NULL, newInfoPtr->channel, "-translation",
	    "auto crlf") == TCL_ERROR) {
	Tcl_CloseEx(NULL, newInfoPtr->channel, 0);
	return;
    }
    if (Tcl_SetChannelOption(NULL, newInfoPtr->channel, "-eofchar", "")
	    == TCL_ERROR) {
	Tcl_CloseEx(NULL, newInfoPtr->channel, 0);
	return;
    }

    /*
     * Invoke the accept callback function.
     */

    if (statePtr->acceptProc != NULL) {
	getnameinfo(&(addr.sa), len, host, sizeof(host), port, sizeof(port),
                    NI_NUMERICHOST|NI_NUMERICSERV);
		NI_NUMERICHOST|NI_NUMERICSERV);
	statePtr->acceptProc(statePtr->acceptProcData, newInfoPtr->channel,
			    host, atoi(port));
		host, atoi(port));
    }
}

/*
 *----------------------------------------------------------------------
 *
 * InitSockets --
 * InitSocketWindowClass --
 *
 *	Registers the event window for the socket notifier code.
 *	Registers the event window class for the socket notifier code.
 *
 *	Assumes socketMutex is held.
 *	Caller must not hold socket mutex lock.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Register a new window class and creates a
 *	Register a new window class.
 *	window for use in asynchronous socket notification.
 *
 *----------------------------------------------------------------------
 */

static void
InitSockets(void)
InitSocketWindowClass(void)
{
    DWORD id;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);

    if (initialized) {
	return;
    }
    Tcl_MutexLock(&socketMutex);
    if (!initialized) {
	initialized = 1;
	TclCreateLateExitHandler(SocketExitHandler, NULL);

	/*
	 * Create the async notification window with a new class. We must
	 * create a new class to avoid a Windows 95 bug that causes us to get
2490
2491
2492
2493
2494
2495
2496
2497

2498
2499
2500
2501

2502
2503
2504
2505
2506
2507
2508


2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
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
2429
2430
2431
2432
2433
2434
2435

2436
2437
2438
2439

2440







2441
2442










































2443


































2444

2445
2446

2447
2448
2449
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







-
+



-
+
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+

-




















-
+







	windowClass.lpszMenuName = NULL;
	windowClass.lpszClassName = className;
	windowClass.lpfnWndProc = SocketProc;
	windowClass.hIcon = NULL;
	windowClass.hCursor = NULL;

	if (!RegisterClassW(&windowClass)) {
	    TclWinConvertError(GetLastError());
	    Tcl_WinConvertError(GetLastError());
	    goto initFailure;
	}
    }

    Tcl_MutexUnlock(&socketMutex);
    /*
     * Check for per-thread initialization.
     */

    if (tsdPtr != NULL) {
	return;
    }
    return;


    /*
     * OK, this thread has never done anything with sockets before.  Construct
     * a worker thread to handle asynchronous events related to sockets
     * assigned to _this_ thread.
     */

    tsdPtr = TCL_TSD_INIT(&dataKey);
    tsdPtr->pendingTcpState = NULL;
    tsdPtr->socketList = NULL;
    tsdPtr->hwnd       = NULL;
    tsdPtr->threadId   = Tcl_GetCurrentThread();
    tsdPtr->readyEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
    if (tsdPtr->readyEvent == NULL) {
	goto initFailure;
    }
    tsdPtr->socketListLock = CreateEventW(NULL, FALSE, TRUE, NULL);
    if (tsdPtr->socketListLock == NULL) {
	goto initFailure;
    }
    tsdPtr->socketThread = CreateThread(NULL, 256, SocketThread, tsdPtr, 0,
	    &id);
    if (tsdPtr->socketThread == NULL) {
	goto initFailure;
    }

    SetThreadPriority(tsdPtr->socketThread, THREAD_PRIORITY_HIGHEST);

    /*
     * Wait for the thread to signal when the window has been created and if
     * it is ready to go.
     */

    WaitForSingleObject(tsdPtr->readyEvent, INFINITE);

    if (tsdPtr->hwnd == NULL) {
	goto initFailure;	/* Trouble creating the window. */
    }

    Tcl_CreateEventSource(SocketSetupProc, SocketCheckProc, NULL);
    return;

  initFailure:
    TclpFinalizeSockets();
    initialized = -1;
    return;
}

/*
 *----------------------------------------------------------------------
 *
 * SocketsEnabled --
 *
 *	Check that the WinSock was successfully initialized.
 *
 * Warning:
 *	This check was useful in times of Windows98 where WinSock may
 *	not be available. This is not the case any more.
 *	This function may be removed with TCL 9.0
 *
 * Results:
 *	1 if it is.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
SocketsEnabled(void)
{
    int enabled;

    Tcl_MutexLock(&socketMutex);
    enabled = (initialized == 1);
    Tcl_MutexUnlock(&socketMutex);
    Tcl_MutexUnlock(&socketMutex); /* Probably pointless before panicing */
    return enabled;
    Tcl_Panic("InitSockets failed");
}


/*
 *----------------------------------------------------------------------
 *
 * SocketExitHandler --
 *
 *	Callback invoked during exit clean up to delete the socket
 *	communication window.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
SocketExitHandler(
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    Tcl_MutexLock(&socketMutex);

    /*
     * Make sure the socket event handling window is cleaned-up for, at
     * most, this thread.
     */
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
2494
2495
2496
2497
2498
2499
2500

2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518

2519
2520
2521
2522
2523
2524
2525
2526







-
+

















-
+







 *	Adjusts the block time if needed.
 *
 *----------------------------------------------------------------------
 */

void
SocketSetupProc(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */
{
    TcpState *statePtr;
    Tcl_Time blockTime = { 0, 0 };
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (!GOT_BITS(flags, TCL_FILE_EVENTS)) {
	return;
    }

    /*
     * Check to see if there is a ready socket.	 If so, poll.
     */
    WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
    for (statePtr = tsdPtr->socketList; statePtr != NULL;
	    statePtr = statePtr->nextPtr) {
	if (GOT_BITS(statePtr->readyEvents,
                statePtr->watchEvents | FD_CONNECT | FD_ACCEPT)) {
		statePtr->watchEvents | FD_CONNECT | FD_ACCEPT)) {
	    Tcl_SetMaxBlockTime(&blockTime);
	    break;
	}
    }
    SetEvent(tsdPtr->socketListLock);
}

2681
2682
2683
2684
2685
2686
2687
2688

2689
2690
2691
2692
2693
2694
2695
2539
2540
2541
2542
2543
2544
2545

2546
2547
2548
2549
2550
2551
2552
2553







-
+







 *	May queue an event.
 *
 *----------------------------------------------------------------------
 */

static void
SocketCheckProc(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */
{
    TcpState *statePtr;
    SocketEvent *evPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (!GOT_BITS(flags, TCL_FILE_EVENTS)) {
2703
2704
2705
2706
2707
2708
2709
2710

2711
2712
2713
2714
2715
2716
2717
2561
2562
2563
2564
2565
2566
2567

2568
2569
2570
2571
2572
2573
2574
2575







-
+







     */

    WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
    for (statePtr = tsdPtr->socketList; statePtr != NULL;
	    statePtr = statePtr->nextPtr) {
	if (GOT_BITS(statePtr->readyEvents,
		statePtr->watchEvents | FD_CONNECT | FD_ACCEPT)
                && !GOT_BITS(statePtr->flags, SOCKET_PENDING)) {
		&& !GOT_BITS(statePtr->flags, SOCKET_PENDING)) {
	    SET_BITS(statePtr->flags, SOCKET_PENDING);
	    evPtr = (SocketEvent *)Tcl_Alloc(sizeof(SocketEvent));
	    evPtr->header.proc = SocketEventProc;
	    evPtr->socket = statePtr->sockets->fd;
	    Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL);
	}
    }
2771
2772
2773
2774
2775
2776
2777
2778

2779
2780
2781
2782
2783
2784
2785
2629
2630
2631
2632
2633
2634
2635

2636
2637
2638
2639
2640
2641
2642
2643







-
+







    }

    /*
     * Discard events that have gone stale.
     */

    if (!statePtr) {
        SetEvent(tsdPtr->socketListLock);
	SetEvent(tsdPtr->socketListLock);
	return 1;
    }

    /*
     * Clear flag that (this) event is pending
     */

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
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







-
-
+
+





-
+




-
+







    /*
     * Handle connection requests directly.
     */

    if (GOT_BITS(statePtr->readyEvents, FD_ACCEPT)) {
	for (fds = statePtr->sockets; fds != NULL; fds = fds->next) {
	    /*
             * Accept the incoming connection request.
             */
	     * Accept the incoming connection request.
	     */

	    len = sizeof(address);
	    newSocket = accept(fds->fd, &(addr.sa), &len);

	    /*
             * On Tcl server sockets with multiple OS fds we loop over the fds
	     * On Tcl server sockets with multiple OS fds we loop over the fds
	     * trying an accept() on each, so we expect INVALID_SOCKET.  There
	     * are also other network stack conditions that can result in
	     * FD_ACCEPT but a subsequent failure on accept() by the time we
	     * get around to it.
             *
	     *
	     * Access to sockets (acceptEventCount, readyEvents) in socketList
	     * is still protected by the lock (prevents reintroduction of
	     * SF Tcl Bug 3056775.
	     */

	    if (newSocket == INVALID_SOCKET) {
		/* int err = WSAGetLastError(); */
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
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







-
+











-
+







	    if (statePtr->acceptEventCount <= 0) {
		CLEAR_BITS(statePtr->readyEvents, FD_ACCEPT);
	    }

	    SetEvent(tsdPtr->socketListLock);

	    /*
             * Caution: TcpAccept() has the side-effect of evaluating the
	     * Caution: TcpAccept() has the side-effect of evaluating the
	     * server accept script (via AcceptCallbackProc() in tclIOCmd.c),
	     * which can close the server socket and invalidate statePtr and
	     * fds. If TcpAccept() accepts a socket we must return immediately
	     * and let SocketCheckProc queue additional FD_ACCEPT events.
	     */

	    TcpAccept(fds, newSocket, addr);
	    return 1;
	}

	/*
         * Loop terminated with no sockets accepted; clear the ready mask so
	 * Loop terminated with no sockets accepted; clear the ready mask so
	 * we can detect the next connection request. Note that connection
	 * requests are level triggered, so if there is a request already
	 * pending, a new event will be generated.
	 */

	statePtr->acceptEventCount = 0;
	CLEAR_BITS(statePtr->readyEvents, FD_ACCEPT);
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
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







-
-
+
+





-
-
+
+

















-
+
-

















-
+
+







    TcpState *statePtr,
    SOCKET socket)
{
    TcpFdList *fds = statePtr->sockets;

    if (fds == NULL) {
	/*
         * Add the first FD.
         */
	 * Add the first FD.
	 */

	statePtr->sockets = (TcpFdList *)Tcl_Alloc(sizeof(TcpFdList));
	fds = statePtr->sockets;
    } else {
	/*
         * Find end of list and append FD.
         */
	 * Find end of list and append FD.
	 */

	while (fds->next != NULL) {
	    fds = fds->next;
	}

	fds->next = (TcpFdList *)Tcl_Alloc(sizeof(TcpFdList));
	fds = fds->next;
    }

    /*
     * Populate new FD.
     */

    fds->fd = socket;
    fds->statePtr = statePtr;
    fds->next = NULL;
}



/*
 *----------------------------------------------------------------------
 *
 * NewSocketInfo --
 *
 *	This function allocates and initializes a new TcpState structure.
 *
 * Results:
 *	Returns a newly allocated TcpState.
 *
 * Side effects:
 *	None, except for allocation of memory.
 *
 *----------------------------------------------------------------------
 */

static TcpState *
NewSocketInfo(SOCKET socket)
NewSocketInfo(
    SOCKET socket)
{
    TcpState *statePtr = (TcpState *)Tcl_Alloc(sizeof(TcpState));

    memset(statePtr, 0, sizeof(TcpState));

    /*
     * TIP #218. Removed the code inserting the new structure into the global
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
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







-
+

-
+
-




-
+
+


















-
-
+
+




-
-
+
+




-
-
+
+




-
-
+
+






-
-
+
+







 *	Processes socket events off the system queue.
 *
 *----------------------------------------------------------------------
 */

static int
WaitForSocketEvent(
    TcpState *statePtr,	/* Information about this socket. */
    TcpState *statePtr,		/* Information about this socket. */
    int events,			/* Events to look for. May be one of
				 * FD_READ or FD_WRITE.
				 * FD_READ or FD_WRITE. */
				 */
    int *errorCodePtr)		/* Where to store errors? */
{
    int result = 1;
    int oldMode;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
	    TclThreadDataKeyGet(&dataKey);

    /*
     * Be sure to disable event servicing so we are truly modal.
     */

    oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE);

    /*
     * Reset WSAAsyncSelect so we have a fresh set of events pending.
     */

    SendSelectMessage(tsdPtr, UNSELECT, statePtr);
    SendSelectMessage(tsdPtr, SELECT, statePtr);

    while (1) {
	int event_found;

	/*
         * Get statePtr lock.
         */
	 * Get statePtr lock.
	 */

	WaitForSingleObject(tsdPtr->socketListLock, INFINITE);

	/*
         * Check if event occured.
         */
	 * Check if event occurred.
	 */

	event_found = GOT_BITS(statePtr->readyEvents, events);

	/*
         * Free list lock.
         */
	 * Free list lock.
	 */

	SetEvent(tsdPtr->socketListLock);

	/*
         * Exit loop if event occured.
         */
	 * Exit loop if event occurred.
	 */

	if (event_found) {
	    break;
	}

	/*
         * Exit loop if event did not occur but this is a non-blocking channel
         */
	 * Exit loop if event did not occur but this is a non-blocking channel
	 */

	if (statePtr->flags & TCP_NONBLOCKING) {
	    *errorCodePtr = EWOULDBLOCK;
	    result = 0;
	    break;
	}

3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216

3217
3218
3219
3220
3221
3222
3223
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







-














-
+







     * This releases waiters on thread exit in TclpFinalizeSockets()
     */

    SetEvent(tsdPtr->readyEvent);

    return msg.wParam;
}


/*
 *----------------------------------------------------------------------
 *
 * SocketProc --
 *
 *	This function is called when WSAAsyncSelect has been used to register
 *	interest in a socket event, and the event has occurred.
 *
 * Results:
 *	0 on success.
 *
 * Side effects:
 *	The flags for the given socket are updated to reflect the event that
 *	occured.
 *	occurred.
 *
 *----------------------------------------------------------------------
 */

static LRESULT CALLBACK
SocketProc(
    HWND hwnd,
3359
3360
3361
3362
3363
3364
3365
3366

3367
3368
3369
3370
3371
3372
3373
3216
3217
3218
3219
3220
3221
3222

3223
3224
3225
3226
3227
3228
3229
3230







-
+







}

/*
 *----------------------------------------------------------------------
 *
 * FindFDInList --
 *
 *	Return true, if the given file descriptior is contained in the
 *	Return true, if the given file descriptor is contained in the
 *	file descriptor list.
 *
 * Results:
 *	true if found.
 *
 * Side effects:
 *
3402
3403
3404
3405
3406
3407
3408
3409

3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423

3424
3425
3426
3427
3428
3429
3430
3431
3259
3260
3261
3262
3263
3264
3265

3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278


3279

3280
3281
3282
3283
3284
3285
3286







-
+












-
-
+
-







 *	Changes thread local list of valid channels.
 *
 *----------------------------------------------------------------------
 */

static void
TcpThreadActionProc(
    ClientData instanceData,
    void *instanceData,
    int action)
{
    ThreadSpecificData *tsdPtr;
    TcpState *statePtr = (TcpState *)instanceData;
    int notifyCmd;

    if (action == TCL_CHANNEL_THREAD_INSERT) {
	/*
	 * Ensure that socket subsystem is initialized in this thread, or else
	 * sockets will not work.
	 */

	Tcl_MutexLock(&socketMutex);
	InitSockets();
	TclInitSockets();
	Tcl_MutexUnlock(&socketMutex);

	tsdPtr = TCL_TSD_INIT(&dataKey);

	WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
	statePtr->nextPtr = tsdPtr->socketList;
	tsdPtr->socketList = statePtr;

Changes to win/tclWinTest.c.

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
30
31
32
33
34
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
30
31
32
33
34
35





-
+





+
+













-

-
+







/*
 * tclWinTest.c --
 *
 *	Contains commands for platform specific tests on Windows.
 *
 * Copyright (c) 1996 Sun Microsystems, Inc.
 * Copyright © 1996 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#undef BUILD_tcl
#undef STATIC_BUILD
#ifndef USE_TCL_STUBS
#   define USE_TCL_STUBS
#endif
#include "tclInt.h"
#ifdef TCL_WITH_EXTERNAL_TOMMATH
#   include "tommath.h"
#else
#   include "tclTomMath.h"
#endif

/*
 * For TestplatformChmod on Windows
 */
#ifdef _WIN32
#include <aclapi.h>
#endif
#include <sddl.h>

/*
 * MinGW 3.4.2 does not define this.
 */
#ifndef INHERITED_ACE
#define INHERITED_ACE (0x10)
#endif
96
97
98
99
100
101
102
103

104
105
106
107
108
109
110
97
98
99
100
101
102
103

104
105
106
107
108
109
110
111







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TesteventloopCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static int *framePtr = NULL;/* Pointer to integer on stack frame of
				 * innermost invocation of the "wait"
				 * subcommand. */
147
148
149
150
151
152
153
154

155
156
157
158
159
160
161
148
149
150
151
152
153
154

155
156
157
158
159
160
161
162







-
+







	    TranslateMessage(&msg);
	    DispatchMessageW(&msg);
	}
	(void) Tcl_SetServiceMode(oldMode);
	framePtr = oldFramePtr;
    } else {
	Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
		"\": must be done or wait", NULL);
		"\": must be done or wait", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
172
173
174
175
176
177
178
179

180
181
182
183
184
185
186
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestvolumetypeCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
#define VOL_BUF_SIZE 32
    int found;
    char volType[VOL_BUF_SIZE];
201
202
203
204
205
206
207
208
209


210
211
212

213
214
215
216
217
218
219
202
203
204
205
206
207
208


209
210
211
212

213
214
215
216
217
218
219
220







-
-
+
+


-
+







	path = NULL;
    }
    found = GetVolumeInformationA(path, NULL, 0, NULL, NULL, NULL, volType,
	    VOL_BUF_SIZE);

    if (found == 0) {
	Tcl_AppendResult(interp, "could not get volume type for \"",
		(path?path:""), "\"", NULL);
	TclWinConvertError(GetLastError());
		(path?path:""), "\"", (char *)NULL);
	Tcl_WinConvertError(GetLastError());
	return TCL_ERROR;
    }
    Tcl_AppendResult(interp, volType, NULL);
    Tcl_AppendResult(interp, volType, (char *)NULL);
    return TCL_OK;
#undef VOL_BUF_SIZE
}

/*
 *----------------------------------------------------------------------
 *
238
239
240
241
242
243
244
245

246
247
248
249
250
251
252
239
240
241
242
243
244
245

246
247
248
249
250
251
252
253







-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestwinclockCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp* interp,		/* Tcl interpreter */
    int objc,			/* Argument count */
    Tcl_Obj *const objv[])	/* Argument vector */
{
    static const FILETIME posixEpoch = { 0xD53E8000, 0x019DB1DE };
				/* The Posix epoch, expressed as a Windows
				 * FILETIME */
287
288
289
290
291
292
293
294

295
296
297
298
299
300
301
288
289
290
291
292
293
294

295
296
297
298
299
300
301
302







-
+







    Tcl_SetObjResult(interp, result);

    return TCL_OK;
}

static int
TestwinsleepCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp* interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const * objv)	/* Parameter vector */
{
    int ms;

    if (objc != 2) {
330
331
332
333
334
335
336
337

338
339
340
341
342
343
344
331
332
333
334
335
336
337

338
339
340
341
342
343
344
345







-
+







 *	This Tcl process closes, hard... Bang!
 *
 *----------------------------------------------------------------------
 */

static int
TestExceptionCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp* interp,			/* Tcl interpreter */
    int objc,				/* Argument count */
    Tcl_Obj *const objv[])		/* Argument vector */
{
    static const char *const cmds[] = {
	"access_violation", "datatype_misalignment", "array_bounds",
	"float_denormal", "float_divbyzero", "float_inexact",
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
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



467
468
469



470
471

472


473
474
475


476
477


478
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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574


575
576
577
578
579
580
581





582
583
584
585
586
587


588
589
590
591
592
593
594
595
596
597
598

599
600
601
602
603
604
605
606
607
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
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
467
468
469
470

471
472

473
474


475
476



477
478
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
558






559
560
561
562
563
564
565
566
567
568
569
570
571
572
573




574





575








































576
577
578
579
580
581
582
583
584



585
586
587
588
589
590
591


592
593
594
595
596
597
598
599
600


601
602



603
604
605
606
607
608


609


610
611
612
613
614
615
616







+
+
+
+





-
-
-
-
-
-
-
-

-
+
+

+
+
+
+
+
+
+
+
+
+

+
+
+
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+

+
+
-
-
-
-
+
+
+
+
+
+
+
+
-

-
-
+
+
+
+
-
-
+
-
-
+
+


+
+
+
+
+
+
-
+

-
+

-
-
+
+
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
-
-
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+

+
+
+
-
+


+
+
+
+
-
-
+
+
+
-
-
-
+
+
+


+
-
+
+

-
-
+
+
-
-
+
+
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+

-
-
-
-
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+




-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-









-
-
-
+
+





-
-
+
+
+
+
+




-
-
+
+
-
-
-






-
-
+
-
-








    /* SMASH! */
    RaiseException(exceptions[cmd], EXCEPTION_NONCONTINUABLE, 0, NULL);

    return TCL_OK;
}

/*
 * This "chmod" works sufficiently for test script purposes. Do not expect
 * it to be exact emulation of Unix chmod (not sure if that's even possible)
 */
static int
TestplatformChmod(
    const char *nativePath,
    int pmode)
{
    static const SECURITY_INFORMATION infoBits = OWNER_SECURITY_INFORMATION
	    | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
    /* don't reset change permissions mask (WRITE_DAC, allow test-cases restore it to cleanup) */
    static const DWORD readOnlyMask = FILE_DELETE_CHILD | FILE_ADD_FILE
	    | FILE_ADD_SUBDIRECTORY | FILE_WRITE_EA | FILE_APPEND_DATA
	    | FILE_WRITE_DATA
	    | DELETE;

    /*
     * References to security functions (only available on NT and later).
     * Note FILE_DELETE_CHILD missing from dirWriteMask because we do
     * not want overriding of child's delete setting when testing
     */
    static const DWORD dirWriteMask =
	FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA |
	FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | STANDARD_RIGHTS_WRITE | DELETE |
	SYNCHRONIZE;
    static const DWORD dirReadMask =
	FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_LIST_DIRECTORY |
	STANDARD_RIGHTS_READ | SYNCHRONIZE;
    /* Note - default user privileges allow ignoring TRAVERSE setting */
    static const DWORD dirExecuteMask =
	FILE_TRAVERSE | STANDARD_RIGHTS_READ | SYNCHRONIZE;

    static const DWORD fileWriteMask =
	FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_WRITE_DATA |
	FILE_APPEND_DATA | STANDARD_RIGHTS_WRITE | DELETE | SYNCHRONIZE;
    const BOOL set_readOnly = !(pmode & 0222);
    BOOL acl_readOnly_found = FALSE, curAclPresent, curAclDefaulted;
    static const DWORD fileReadMask =
	FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_READ_DATA |
	STANDARD_RIGHTS_READ | SYNCHRONIZE;
    static const DWORD fileExecuteMask =
	FILE_EXECUTE | STANDARD_RIGHTS_READ | SYNCHRONIZE;

    SID_IDENTIFIER_AUTHORITY userSidAuthority = {
	SECURITY_WORLD_SID_AUTHORITY
    };
    BYTE *secDesc = 0;
    DWORD secDescLen, attr, newAclSize;
    ACL_SIZE_INFORMATION ACLSize;
    DWORD attr, newAclSize;
    PACL newAcl = NULL;
    int res = 0;

    HANDLE hToken = NULL;
    int i;
    int nSids = 0;
    struct {
	PSID pSid;
	DWORD mask;
	DWORD sidLen;
    PACL curAcl, newAcl = 0;
    WORD j;
    SID *userSid = 0;
    char *userDomain = 0;
    int res = 0;
    } aceEntry[3];
    DWORD dw;
    int isDir;
    TOKEN_USER *pTokenUser = NULL;

    res = -1; /* Assume failure */

    attr = GetFileAttributesA(nativePath);
    if (attr == 0xFFFFFFFF) {
    /*
     * Process the chmod request.
     */

	goto done; /* Not found */
    }

    isDir = (attr & FILE_ATTRIBUTE_DIRECTORY) != 0;

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
	goto done;
    }
    attr = GetFileAttributesA(nativePath);

    /*
     * nativePath not found
    /* Get process SID */
    if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &dw)
	    && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
	goto done;
     */

    }
    if (attr == 0xFFFFFFFF) {
	res = -1;
    pTokenUser = (TOKEN_USER *)Tcl_Alloc(dw);
    if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dw, &dw)) {
	goto done;
    }
    aceEntry[nSids].sidLen = GetLengthSid(pTokenUser->User.Sid);
    aceEntry[nSids].pSid = (PSID)Tcl_Alloc(aceEntry[nSids].sidLen);
    if (!CopySid(aceEntry[nSids].sidLen, aceEntry[nSids].pSid,
	    pTokenUser->User.Sid)) {
	Tcl_Free(aceEntry[nSids].pSid); /* Since we have not ++'ed nSids */
	goto done;

    }
    /*
     * If nativePath is not a directory, there is no special handling.
     * Always include DACL modify rights so we don't get locked out
     */

    if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
    aceEntry[nSids].mask = READ_CONTROL | WRITE_DAC | WRITE_OWNER | SYNCHRONIZE |
			   FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES;
	goto done;
    }

    if (pmode & 0700) {
	/* Owner permissions. Assumes current process is owner */
	if (pmode & 0400) {
	    aceEntry[nSids].mask |= isDir ? dirReadMask : fileReadMask;
	}
	if (pmode & 0200) {
    /*
     * Set the result to error, if the ACL change is successful it will be
     * reset to 0.
     */

	    aceEntry[nSids].mask |= isDir ? dirWriteMask : fileWriteMask;
	}
    res = -1;

	if (pmode & 0100) {
	    aceEntry[nSids].mask |= isDir ? dirExecuteMask : fileExecuteMask;
	}
    /*
     * Read the security descriptor for the directory. Note the first call
     * obtains the size of the security descriptor.
     */

    if (!GetFileSecurityA(nativePath, infoBits, NULL, 0, &secDescLen)) {
	DWORD secDescLen2 = 0;
    }
    ++nSids;

    if (pmode & 0070) {
	/* Group permissions. */

	TOKEN_PRIMARY_GROUP *pTokenGroup;

	/* Get primary group SID */
	if (!GetTokenInformation(
		hToken, TokenPrimaryGroup, NULL, 0, &dw) &&
	if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
		GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
	    goto done;
	}
	pTokenGroup = (TOKEN_PRIMARY_GROUP *)Tcl_Alloc(dw);
	if (!GetTokenInformation(hToken, TokenPrimaryGroup, pTokenGroup, dw, &dw)) {
	    Tcl_Free(pTokenGroup);
	    goto done;

	secDesc = (BYTE *)Tcl_Alloc(secDescLen);
	}
	aceEntry[nSids].sidLen = GetLengthSid(pTokenGroup->PrimaryGroup);
	aceEntry[nSids].pSid = (PSID)Tcl_Alloc(aceEntry[nSids].sidLen);
	if (!GetFileSecurityA(nativePath, infoBits,
		(PSECURITY_DESCRIPTOR) secDesc, secDescLen, &secDescLen2)
		|| (secDescLen < secDescLen2)) {
	if (!CopySid(aceEntry[nSids].sidLen, aceEntry[nSids].pSid, pTokenGroup->PrimaryGroup)) {
	    Tcl_Free(pTokenGroup);
	    Tcl_Free(aceEntry[nSids].pSid); /* Since we have not ++'ed nSids */
	    goto done;
	}
	Tcl_Free(pTokenGroup);
    }

	/* Generate mask for group ACL */

    /*
     * Get the World SID.
	aceEntry[nSids].mask = 0;
	if (pmode & 0040) {
     */

	    aceEntry[nSids].mask |= isDir ? dirReadMask : fileReadMask;
	}
    userSid = (SID *)Tcl_Alloc(GetSidLengthRequired((UCHAR) 1));
    InitializeSid(userSid, &userSidAuthority, (BYTE) 1);
    *(GetSidSubAuthority(userSid, 0)) = SECURITY_WORLD_RID;

	if (pmode & 0020) {
	    aceEntry[nSids].mask |= isDir ? dirWriteMask : fileWriteMask;
	}
	if (pmode & 0010) {
	    aceEntry[nSids].mask |= isDir ? dirExecuteMask : fileExecuteMask;
	}
	++nSids;
    }
    /*
     * If curAclPresent == false then curAcl and curAclDefaulted not valid.
     */

    if (!GetSecurityDescriptorDacl((PSECURITY_DESCRIPTOR) secDesc,
	    &curAclPresent, &curAcl, &curAclDefaulted)) {
	goto done;
    }
    if (!curAclPresent || !curAcl) {
	ACLSize.AclBytesInUse = 0;
	ACLSize.AceCount = 0;
    if (pmode & 0007) {
	/* World permissions */
	PSID pWorldSid;
	if (!ConvertStringSidToSidA("S-1-1-0", &pWorldSid)) {
	    goto done;
	}
	aceEntry[nSids].sidLen = GetLengthSid(pWorldSid);
	aceEntry[nSids].pSid = (PSID)Tcl_Alloc(aceEntry[nSids].sidLen);
	if (!CopySid(aceEntry[nSids].sidLen, aceEntry[nSids].pSid, pWorldSid)) {
    } else if (!GetAclInformation(curAcl, &ACLSize, sizeof(ACLSize),
	    AclSizeInformation)) {
	goto done;
    }
	    LocalFree(pWorldSid);
	    Tcl_Free(aceEntry[nSids].pSid); /* Since we have not ++'ed nSids */
	    goto done;
	}
	LocalFree(pWorldSid);

    /*
     * Allocate memory for the new ACL.
     */

	/* Generate mask for world ACL */

	aceEntry[nSids].mask = 0;
	if (pmode & 0004) {
	    aceEntry[nSids].mask |= isDir ? dirReadMask : fileReadMask;
	}
    newAclSize = ACLSize.AclBytesInUse + sizeof(ACCESS_DENIED_ACE)
	    + GetLengthSid(userSid) - sizeof(DWORD);
	if (pmode & 0002) {
	    aceEntry[nSids].mask |= isDir ? dirWriteMask : fileWriteMask;
	}
	if (pmode & 0001) {
	    aceEntry[nSids].mask |= isDir ? dirExecuteMask : fileExecuteMask;
	}
	++nSids;
    newAcl = (PACL) Tcl_Alloc(newAclSize);

    /*
     * Initialize the new ACL.
     */

    }

    /* Allocate memory and initialize the new ACL. */

    newAclSize = sizeof(ACL);
    /* Add in size required for each ACE entry in the ACL */
    for (i = 0; i < nSids; ++i) {
	newAclSize +=
	    offsetof(ACCESS_ALLOWED_ACE, SidStart) + aceEntry[i].sidLen;
    }
    newAcl = (PACL)Tcl_Alloc(newAclSize);
    if (!InitializeAcl(newAcl, newAclSize, ACL_REVISION)) {
	goto done;
    }

    /*
     * Add denied to make readonly, this will be known as a "read-only tag".
     */

    for (i = 0; i < nSids; ++i) {
    if (set_readOnly && !AddAccessDeniedAce(newAcl, ACL_REVISION,
	    readOnlyMask, userSid)) {
	goto done;
    }

	if (!AddAccessAllowedAce(newAcl, ACL_REVISION, aceEntry[i].mask, aceEntry[i].pSid)) {
    acl_readOnly_found = FALSE;
    for (j = 0; j < ACLSize.AceCount; j++) {
	LPVOID pACE2;
	ACE_HEADER *phACE2;

	if (!GetAce(curAcl, j, &pACE2)) {
	    goto done;
	}

	phACE2 = (ACE_HEADER *) pACE2;

	/*
	 * Do NOT propagate inherited ACEs.
	 */

	if (phACE2->AceFlags & INHERITED_ACE) {
	    continue;
	}

	/*
	 * Skip the "read-only tag" restriction (either added above, or it is
	 * being removed).
	 */

	if (phACE2->AceType == ACCESS_DENIED_ACE_TYPE) {
	    ACCESS_DENIED_ACE *pACEd = (ACCESS_DENIED_ACE *) phACE2;

	    if (pACEd->Mask == readOnlyMask
		    && EqualSid(userSid, (PSID) &pACEd->SidStart)) {
		acl_readOnly_found = TRUE;
		continue;
	    }
	}

	/*
	 * Copy the current ACE from the old to the new ACL.
	 */

	if (!AddAce(newAcl, ACL_REVISION, MAXDWORD, (PACL *) pACE2,
		((PACE_HEADER) pACE2)->AceSize)) {
	    goto done;
	}
    }

    /*
     * Apply the new ACL. Note PROTECTED_DACL_SECURITY_INFORMATION can be used
     * to remove inherited ACL (we need to overwrite the default ACL's in this case)
     */

    if (set_readOnly == acl_readOnly_found || SetNamedSecurityInfoA(
	    (LPSTR) nativePath, SE_FILE_OBJECT,
	    DACL_SECURITY_INFORMATION /*| PROTECTED_DACL_SECURITY_INFORMATION*/,
    if (SetNamedSecurityInfoA((LPSTR)nativePath, SE_FILE_OBJECT,
	    DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
	    NULL, NULL, newAcl, NULL) == ERROR_SUCCESS) {
	res = 0;
    }

  done:
    if (secDesc) {
	Tcl_Free(secDesc);
    if (pTokenUser) {
	Tcl_Free(pTokenUser);
    }
    if (hToken) {
	CloseHandle(hToken);
    }
    if (newAcl) {
	Tcl_Free(newAcl);
    }
    if (userSid) {
	Tcl_Free(userSid);
    for (i = 0; i < nSids; ++i) {
	Tcl_Free(aceEntry[i].pSid);
    }
    if (userDomain) {
	Tcl_Free(userDomain);
    }

    if (res != 0) {
	return res;
    }

    /*
     * Run normal chmod command.
    /* Run normal chmod command */
     */

    return chmod(nativePath, pmode);
}

/*
 *---------------------------------------------------------------------------
 *
 * TestchmodCmd --
618
619
620
621
622
623
624
625

626
627
628
629
630
631
632
627
628
629
630
631
632
633

634
635
636
637
638
639
640
641







-
+







 *	Changes permissions of specified files.
 *
 *---------------------------------------------------------------------------
 */

static int
TestchmodCmd(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Parameter count */
    Tcl_Obj *const * objv)	/* Parameter vector */
{
    int i, mode;

    if (objc < 2) {
644
645
646
647
648
649
650
651

652
653
654
655
656
657
658
653
654
655
656
657
658
659

660
661
662
663
664
665
666
667







-
+








	translated = Tcl_TranslateFileName(interp, Tcl_GetString(objv[i]), &buffer);
	if (translated == NULL) {
	    return TCL_ERROR;
	}
	if (TestplatformChmod(translated, mode) != 0) {
	    Tcl_AppendResult(interp, translated, ": ", Tcl_PosixError(interp),
		    NULL);
		    (char *)NULL);
	    return TCL_ERROR;
	}
	Tcl_DStringFree(&buffer);
    }
    return TCL_OK;
}


Changes to win/tclWinThrd.c.

1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5



6
7
8
9
10
11
12
13
14
15





-
-
-
+
+
+







/*
 * tclWinThread.c --
 *
 *	This file implements the Windows-specific thread operations.
 *
 * Copyright (c) 1998 by Sun Microsystems, Inc.
 * Copyright (c) 1999 by Scriptics Corporation
 * Copyright (c) 2008 by George Peter Staplin
 * Copyright © 1998 Sun Microsystems, Inc.
 * Copyright © 1999 Scriptics Corporation
 * Copyright © 2008 George Peter Staplin
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclWinInt.h"

34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48







-
+







 * of Tcl as a whole.
 */

static CRITICAL_SECTION initLock;

/*
 * allocLock is used by Tcl's version of malloc for synchronization. For
 * obvious reasons, cannot use any dyamically allocated storage.
 * obvious reasons, cannot use any dynamically allocated storage.
 */

#if TCL_THREADS

static struct Tcl_Mutex_ {
    CRITICAL_SECTION crit;
} allocLock;
75
76
77
78
79
80
81
82

83
84
85

86
87
88
89
90
91
92
75
76
77
78
79
80
81

82
83
84

85
86
87
88
89
90
91
92







-
+


-
+







/*
 * The per-thread event and queue pointers.
 */

#if TCL_THREADS

typedef struct ThreadSpecificData {
    HANDLE condEvent;			/* Per-thread condition event */
    HANDLE condEvent;		/* Per-thread condition event */
    struct ThreadSpecificData *nextPtr;	/* Queue pointers */
    struct ThreadSpecificData *prevPtr;
    int flags;				/* See flags below */
    int flags;			/* See flags below */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;

#endif /* TCL_THREADS */

/*
 * State bits for the thread.
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
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







-
+










-
-
-
+
+
+
+


-







 * Additions by AOL for specialized thread memory allocator.
 */

#ifdef USE_THREAD_ALLOC
static DWORD tlsKey;

typedef struct {
    Tcl_Mutex	     tlock;
    Tcl_Mutex tlock;
    CRITICAL_SECTION wlock;
} allocMutex;
#endif /* USE_THREAD_ALLOC */

/*
 * The per thread data passed from TclpThreadCreate
 * to TclWinThreadStart.
 */

typedef struct {
  LPTHREAD_START_ROUTINE lpStartAddress; /* Original startup routine */
  LPVOID lpParameter;		/* Original startup data */
  unsigned int fpControl;	/* Floating point control word from the
    LPTHREAD_START_ROUTINE lpStartAddress;
				/* Original startup routine */
    LPVOID lpParameter;		/* Original startup data */
    unsigned int fpControl;	/* Floating point control word from the
				 * main thread */
} WinThread;


/*
 *----------------------------------------------------------------------
 *
 * TclWinThreadStart --
 *
 *	This procedure is the entry point for all new threads created
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
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







-
+




-
+










-
+
-

-
-
+
+



-
+







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

int
TclpThreadCreate(
    Tcl_ThreadId *idPtr,	/* Return, the ID of the thread. */
    Tcl_ThreadCreateProc *proc,	/* Main() function of the thread. */
    ClientData clientData,	/* The one argument to Main(). */
    void *clientData,		/* The one argument to Main(). */
    size_t stackSize,		/* Size of stack for the new thread. */
    int flags)			/* Flags controlling behaviour of the new
				 * thread. */
{
    WinThread *winThreadPtr;		/* Per-thread startup info */
    WinThread *winThreadPtr;	/* Per-thread startup info */
    HANDLE tHandle;

    winThreadPtr = (WinThread *)Tcl_Alloc(sizeof(WinThread));
    winThreadPtr->lpStartAddress = (LPTHREAD_START_ROUTINE) proc;
    winThreadPtr->lpParameter = clientData;
    winThreadPtr->fpControl = _controlfp(0, 0);

    EnterCriticalSection(&joinLock);

    *idPtr = 0; /* must initialize as Tcl_Thread is a pointer and
                 * on WIN64 sizeof void* != sizeof unsigned
                 * on WIN64 sizeof void* != sizeof unsigned */
		 */

#if defined(_MSC_VER) || defined(__MSVCRT__) || defined(__BORLANDC__)
    tHandle = (HANDLE) _beginthreadex(NULL, (unsigned) stackSize,
#if defined(_MSC_VER) || defined(__MSVCRT__)
    tHandle = (HANDLE) _beginthreadex(NULL, (unsigned)stackSize,
	    (Tcl_ThreadCreateProc*) TclWinThreadStart, winThreadPtr,
	    0, (unsigned *)idPtr);
#else
    tHandle = CreateThread(NULL, (DWORD) stackSize,
    tHandle = CreateThread(NULL, (DWORD)stackSize,
	    TclWinThreadStart, winThreadPtr, 0, (LPDWORD)idPtr);
#endif

    if (tHandle == NULL) {
	LeaveCriticalSection(&joinLock);
	return TCL_ERROR;
    } else {
288
289
290
291
292
293
294
295

296
297
298
299
300
301
302
303

304
305
306
307
308
309
310
287
288
289
290
291
292
293

294
295
296
297
298
299
300
301

302
303
304
305
306
307
308
309







-
+







-
+







 *
 * Side effects:
 *	This procedure terminates the current thread.
 *
 *----------------------------------------------------------------------
 */

void
TCL_NORETURN void
TclpThreadExit(
    int status)
{
    EnterCriticalSection(&joinLock);
    TclSignalExitThread(Tcl_GetCurrentThread(), status);
    LeaveCriticalSection(&joinLock);

#if defined(_MSC_VER) || defined(__MSVCRT__) || defined(__BORLANDC__)
#if defined(_MSC_VER) || defined(__MSVCRT__)
    _endthreadex((unsigned) status);
#else
    ExitThread((DWORD) status);
#endif
}

/*
322
323
324
325
326
327
328
329

330
331
332
333
334
335
336
321
322
323
324
325
326
327

328
329
330
331
332
333
334
335







-
+







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

Tcl_ThreadId
Tcl_GetCurrentThread(void)
{
    return (Tcl_ThreadId)(size_t)GetCurrentThreadId();
    return (Tcl_ThreadId)INT2PTR(GetCurrentThreadId());
}

/*
 *----------------------------------------------------------------------
 *
 * TclpInitLock
 *
454
455
456
457
458
459
460
461

462
463
464
465
466
467
468
453
454
455
456
457
458
459

460
461
462
463
464
465
466
467







-
+








/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetAllocMutex
 *
 *	This procedure returns a pointer to a statically initialized mutex for
 *	use by the memory allocator. The alloctor must use this lock, because
 *	use by the memory allocator. The allocator must use this lock, because
 *	all other locks are allocated...
 *
 * Results:
 *	A pointer to a mutex that is suitable for passing to Tcl_MutexLock and
 *	Tcl_MutexUnlock.
 *
 * Side effects:
531
532
533
534
535
536
537
538

539
540
541
542
543
544
545
530
531
532
533
534
535
536

537
538
539
540
541
542
543
544







-
+








    DeleteCriticalSection(&initLock);
}

#if TCL_THREADS

/* locally used prototype */
static void		FinalizeConditionEvent(ClientData data);
static void		FinalizeConditionEvent(void *data);

/*
 *----------------------------------------------------------------------
 *
 * Tcl_MutexLock --
 *
 *	This procedure is invoked to lock a mutex. This is a self initializing
564
565
566
567
568
569
570
571

572
573

574
575
576
577
578
579
580
563
564
565
566
567
568
569

570
571

572
573
574
575
576
577
578
579







-
+

-
+







	TclpGlobalLock();

	/*
	 * Double inside global lock check to avoid a race.
	 */

	if (*mutexPtr == NULL) {
	    csPtr = (CRITICAL_SECTION *)Tcl_Alloc(sizeof(CRITICAL_SECTION));
	    csPtr = (CRITICAL_SECTION *) Tcl_Alloc(sizeof(CRITICAL_SECTION));
	    InitializeCriticalSection(csPtr);
	    *mutexPtr = (Tcl_Mutex)csPtr;
	    *mutexPtr = (Tcl_Mutex) csPtr;
	    TclRememberMutex(mutexPtr);
	}
	TclpGlobalUnlock();
    }
    csPtr = *((CRITICAL_SECTION **)mutexPtr);
    EnterCriticalSection(csPtr);
}
656
657
658
659
660
661
662
663

664
665
666
667
668
669
670
655
656
657
658
659
660
661

662
663
664
665
666
667
668
669







-
+







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

void
Tcl_ConditionWait(
    Tcl_Condition *condPtr,	/* Really (WinCondition **) */
    Tcl_Mutex *mutexPtr,	/* Really (CRITICAL_SECTION **) */
    const Tcl_Time *timePtr) /* Timeout on waiting period */
    const Tcl_Time *timePtr)	/* Timeout on waiting period */
{
    WinCondition *winCondPtr;	/* Per-condition queue head */
    CRITICAL_SECTION *csPtr;	/* Caller's Mutex, after casting */
    DWORD wtime;		/* Windows time value */
    int timeout;		/* True if we got a timeout */
    int doExit = 0;		/* True if we need to do exit setup */
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
721
722
723
724
725
726
727
728

729
730
731
732
733
734
735
720
721
722
723
724
725
726

727
728
729
730
731
732
733
734







-
+







	TclpGlobalUnlock();
    }
    csPtr = *((CRITICAL_SECTION **)mutexPtr);
    winCondPtr = *((WinCondition **)condPtr);
    if (timePtr == NULL) {
	wtime = INFINITE;
    } else {
	wtime = timePtr->sec * 1000 + timePtr->usec / 1000;
	wtime = (DWORD)timePtr->sec * 1000 + (DWORD)timePtr->usec / 1000;
    }

    /*
     * Queue the thread on the condition, using the per-condition lock for
     * serialization.
     */

773
774
775
776
777
778
779
780

781
782

783
784
785
786
787
788
789
772
773
774
775
776
777
778

779
780

781
782
783
784
785
786
787
788







-
+

-
+







     */

    if (timeout) {
	if (tsdPtr->flags & WIN_THREAD_RUNNING) {
	    timeout = 0;
	} else {
	    /*
	     * When dequeuing, we can leave the tsdPtr->nextPtr and
	     * When dequeueing, we can leave the tsdPtr->nextPtr and
	     * tsdPtr->prevPtr with dangling pointers because they are
	     * reinitialilzed w/out reading them when the thread is enqueued
	     * reinitialized w/out reading them when the thread is enqueued
	     * later.
	     */

	    if (winCondPtr->firstPtr == tsdPtr) {
		winCondPtr->firstPtr = tsdPtr->nextPtr;
	    } else {
		tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
876
877
878
879
880
881
882
883

884
885
886
887
888
889
890
875
876
877
878
879
880
881

882
883
884
885
886
887
888
889







-
+







 *	The per-thread event is closed.
 *
 *----------------------------------------------------------------------
 */

static void
FinalizeConditionEvent(
    ClientData data)
    void *data)
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) data;

    tsdPtr->flags = WIN_THREAD_UNINIT;
    CloseHandle(tsdPtr->condEvent);
}

922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
921
922
923
924
925
926
927



928
929
930
931
932
933
934







-
-
-








    if (winCondPtr != NULL) {
	DeleteCriticalSection(&winCondPtr->condLock);
	Tcl_Free(winCondPtr);
	*condPtr = NULL;
    }
}




/*
 * Additions by AOL for specialized thread memory allocator.
 */
#ifdef USE_THREAD_ALLOC

Tcl_Mutex *
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1022
1023
1024
1025
1026
1027
1028

1029
1030
1031
1032
1033
1034
1035







-







	success = TlsFree(tlsKey);
	if (!success) {
	    Tcl_Panic("TlsFree failed from TclpFreeAllocCache");
	}
    }
}
#endif /* USE_THREAD_ALLOC */


void *
TclpThreadCreateKey(void)
{
    DWORD *key;

    key = (DWORD *)TclpSysAlloc(sizeof *key);

Changes to win/tclWinTime.c.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







/*
 * tclWinTime.c --
 *
 *	Contains Windows specific versions of Tcl functions that obtain time
 *	values from the operating system.
 *
 * Copyright 1995-1998 by Sun Microsystems, Inc.
 * Copyright © 1995-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

24
25
26
27
28
29
30
31


32
33
34
35
36
37

38
39
40
41
42
43
44
24
25
26
27
28
29
30

31
32
33
34
35
36
37

38
39
40
41
42
43
44
45







-
+
+





-
+








typedef struct {
    CRITICAL_SECTION cs;	/* Mutex guarding this structure. */
    int initialized;		/* Flag == 1 if this structure is
				 * initialized. */
    int perfCounterAvailable;	/* Flag == 1 if the hardware has a performance
				 * counter. */
    DWORD calibrationInterv;	/* Calibration interval in seconds (start 1 sec) */
    DWORD calibrationInterv;	/* Calibration interval in seconds (start 1
				 * sec) */
    HANDLE calibrationThread;	/* Handle to the thread that keeps the virtual
				 * clock calibrated. */
    HANDLE readyEvent;		/* System event used to trigger the requesting
				 * thread when the clock calibration procedure
				 * is initialized for the first time. */
    HANDLE exitEvent; 		/* Event to signal out of an exit handler to
    HANDLE exitEvent;		/* Event to signal out of an exit handler to
				 * tell the calibration loop to terminate. */
    LARGE_INTEGER nominalFreq;	/* Nominal frequency of the system performance
				 * counter, that is, the value returned from
				 * QueryPerformanceFrequency. */
    /*
     * The following values are used for calculating virtual time. Virtual
     * time is always equal to:
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
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







-
+

-
+













-
+

-
-
-
+
+
+

-
-
-
-
-
+
+
+
+
+












-
+
+


-





-
+

-
-
-
-
-
+
+
+
+
+

-
-
+
+

-
+







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-
+


-
+

+
-
-
-
+
+
+
+
-




-
-
+
+







    LARGE_INTEGER posixEpoch;	/* Posix epoch expressed as 100-ns ticks since
				 * the windows epoch. */

    /*
     * Data used in developing the estimate of performance counter frequency
     */

    Tcl_WideUInt fileTimeSample[SAMPLES];
    unsigned long long fileTimeSample[SAMPLES];
				/* Last 64 samples of system time. */
    Tcl_WideInt perfCounterSample[SAMPLES];
    long long perfCounterSample[SAMPLES];
				/* Last 64 samples of performance counter. */
    int sampleNo;		/* Current sample number. */
} TimeInfo;

static TimeInfo timeInfo = {
    { NULL, 0, 0, NULL, NULL, 0 },
    0,
    0,
    1,
    (HANDLE) NULL,
    (HANDLE) NULL,
    (HANDLE) NULL,
#if defined(HAVE_CAST_TO_UNION) && !defined(__cplusplus)
    (LARGE_INTEGER) (Tcl_WideInt) 0,
    (LARGE_INTEGER) (long long) 0,
    (ULARGE_INTEGER) (DWORDLONG) 0,
    (LARGE_INTEGER) (Tcl_WideInt) 0,
    (LARGE_INTEGER) (Tcl_WideInt) 0,
    (LARGE_INTEGER) (Tcl_WideInt) 0,
    (LARGE_INTEGER) (long long) 0,
    (LARGE_INTEGER) (long long) 0,
    (LARGE_INTEGER) (long long) 0,
#else
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {0, 0},
    {{0, 0}},
    {{0, 0}},
    {{0, 0}},
    {{0, 0}},
    {{0, 0}},
#endif
    { 0 },
    { 0 },
    0
};

/*
 * Scale to convert wide click values from the TclpGetWideClicks native
 * resolution to microsecond resolution and back.
 */
static struct {
    int initialized;		/* 1 if initialized, 0 otherwise */
    int perfCounter;		/* 1 if performance counter usable for wide clicks */
    int perfCounter;		/* 1 if performance counter usable for wide
				 * clicks */
    double microsecsScale;	/* Denominator scale between clock / microsecs */
} wideClick = {0, 0, 0.0};


/*
 * Declarations for functions defined later in this file.
 */

static void		StopCalibration(ClientData clientData);
static void		StopCalibration(void *clientData);
static DWORD WINAPI	CalibrationThread(LPVOID arg);
static void 		UpdateTimeEachSecond(void);
static void		ResetCounterSamples(Tcl_WideUInt fileTime,
			    Tcl_WideInt perfCounter, Tcl_WideInt perfFreq);
static Tcl_WideInt	AccumulateSample(Tcl_WideInt perfCounter,
			    Tcl_WideUInt fileTime);
static void		UpdateTimeEachSecond(void);
static void		ResetCounterSamples(unsigned long long fileTime,
			    long long perfCounter, long long perfFreq);
static long long	AccumulateSample(long long perfCounter,
			    unsigned long long fileTime);
static void		NativeScaleTime(Tcl_Time* timebuf,
			    ClientData clientData);
static Tcl_WideInt	NativeGetMicroseconds(void);
			    void *clientData);
static long long	NativeGetMicroseconds(void);
static void		NativeGetTime(Tcl_Time* timebuf,
			    ClientData clientData);
			    void *clientData);

/*
 * TIP #233 (Virtualized Time): Data for the time hooks, if any.
 */

Tcl_GetTimeProc *tclGetTimeProcPtr = NativeGetTime;
Tcl_ScaleTimeProc *tclScaleTimeProcPtr = NativeScaleTime;
ClientData tclTimeClientData = NULL;
void *tclTimeClientData = NULL;

/*
 * Inlined version of Tcl_GetTime.
 */

static inline void
GetTime(
    Tcl_Time *timePtr)
{
    tclGetTimeProcPtr(timePtr, tclTimeClientData);
}

static inline int
IsTimeNative(void)
{
    return tclGetTimeProcPtr == NativeGetTime;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpGetSeconds --
 *
 *	This procedure returns the number of seconds from the epoch. On most
 *	Unix systems the epoch is Midnight Jan 1, 1970 GMT.
 *
 * Results:
 *	Number of seconds from the epoch.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_WideUInt
unsigned long long
TclpGetSeconds(void)
{
    Tcl_WideInt usecSincePosixEpoch;
    long long usecSincePosixEpoch;

    /*
    /* Try to use high resolution timer */
    if ( tclGetTimeProcPtr == NativeGetTime
      && (usecSincePosixEpoch = NativeGetMicroseconds())
     * Try to use high resolution timer
     */

    if (IsTimeNative() && (usecSincePosixEpoch = NativeGetMicroseconds())) {
    ) {
	return usecSincePosixEpoch / 1000000;
    } else {
	Tcl_Time t;

	tclGetTimeProcPtr(&t, tclTimeClientData);	/* Tcl_GetTime inlined. */
	return t.sec;
	GetTime(&t);
	return (unsigned long long)t.sec;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclpGetClicks --
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
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







-
+


-
+

+
-
-
-
+
+
+
+
-
-
+








-
-
+
+
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_WideUInt
unsigned long long
TclpGetClicks(void)
{
    Tcl_WideInt usecSincePosixEpoch;
    long long usecSincePosixEpoch;

    /*
    /* Try to use high resolution timer */
    if ( tclGetTimeProcPtr == NativeGetTime
      && (usecSincePosixEpoch = NativeGetMicroseconds())
     * Try to use high resolution timer.
     */

    if (IsTimeNative() && (usecSincePosixEpoch = NativeGetMicroseconds())) {
    ) {
	return (Tcl_WideUInt)usecSincePosixEpoch;
	return (Tcl_WideUInt) usecSincePosixEpoch;
    } else {
	/*
	* Use the Tcl_GetTime abstraction to get the time in microseconds, as
	* nearly as we can, and return it.
	*/

	Tcl_Time now;		/* Current Tcl time */

	tclGetTimeProcPtr(&now, tclTimeClientData);	/* Tcl_GetTime inlined */
	return (Tcl_WideUInt)(now.sec * 1000000) + now.usec;
	GetTime(&now);
	return ((unsigned long long)(now.sec)*1000000ULL) +
		(unsigned long long)(now.usec);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclpGetWideClicks --
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
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







-
+












+













-
+






-
+













-
+











-
+







 *	This should be used for time-delta resp. for measurement purposes
 *	only, because on some platforms can return microseconds from some
 *	start time (not from the epoch).
 *
 *----------------------------------------------------------------------
 */

Tcl_WideInt
long long
TclpGetWideClicks(void)
{
    LARGE_INTEGER curCounter;

    if (!wideClick.initialized) {
	LARGE_INTEGER perfCounterFreq;

	/*
	 * The frequency of the performance counter is fixed at system boot and
	 * is consistent across all processors. Therefore, the frequency need
	 * only be queried upon application initialization.
	 */

	if (QueryPerformanceFrequency(&perfCounterFreq)) {
	    wideClick.perfCounter = 1;
	    wideClick.microsecsScale = 1000000.0 / perfCounterFreq.QuadPart;
	} else {
	    /* fallback using microseconds */
	    wideClick.perfCounter = 0;
	    wideClick.microsecsScale = 1;
	}

	wideClick.initialized = 1;
    }
    if (wideClick.perfCounter) {
	if (QueryPerformanceCounter(&curCounter)) {
	    return (Tcl_WideInt)curCounter.QuadPart;
	    return (long long)curCounter.QuadPart;
	}
	/* fallback using microseconds */
	wideClick.perfCounter = 0;
	wideClick.microsecsScale = 1;
	return TclpGetMicroseconds();
    } else {
    	return TclpGetMicroseconds();
	return TclpGetMicroseconds();
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclpWideClickInMicrosec --
 *
 *	This procedure return scale to convert wide click values from the
 *	TclpGetWideClicks native resolution to microsecond resolution
 *	and back.
 *
 * Results:
 * 	1 click in microseconds as double.
 *	1 click in microseconds as double.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

double
TclpWideClickInMicrosec(void)
{
    if (!wideClick.initialized) {
    	(void)TclpGetWideClicks();	/* initialize */
	(void) TclpGetWideClicks();	/* initialize */
    }
    return wideClick.microsecsScale;
}

/*
 *----------------------------------------------------------------------
 *
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
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







-
+


-
+

+
-
-
-
+
+
+
+
-



-
-
-
+
+
+



-
-
+
+







 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_WideInt
long long
TclpGetMicroseconds(void)
{
    Tcl_WideInt usecSincePosixEpoch;
    long long usecSincePosixEpoch;

    /*
    /* Try to use high resolution timer */
    if ( tclGetTimeProcPtr == NativeGetTime
      && (usecSincePosixEpoch = NativeGetMicroseconds())
     * Try to use high resolution timer.
     */

    if (IsTimeNative() && (usecSincePosixEpoch = NativeGetMicroseconds())) {
    ) {
	return usecSincePosixEpoch;
    } else {
	/*
	* Use the Tcl_GetTime abstraction to get the time in microseconds, as
	* nearly as we can, and return it.
	*/
	 * Use the Tcl_GetTime abstraction to get the time in microseconds, as
	 * nearly as we can, and return it.
	 */

	Tcl_Time now;

	tclGetTimeProcPtr(&now, tclTimeClientData);	/* Tcl_GetTime inlined */
	return (((Tcl_WideInt)now.sec) * 1000000) + now.usec;
	GetTime(&now);
	return now.sec * 1000000 + now.usec;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetTime --
349
350
351
352
353
354
355
356

357

358
359
360




361
362
363


364
365

366
367
368
369
370
371
372
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







-
+

+
-
-
-
+
+
+
+
-
-
-
+
+

-
+







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

void
Tcl_GetTime(
    Tcl_Time *timePtr)		/* Location to store time information. */
{
    Tcl_WideInt usecSincePosixEpoch;
    long long usecSincePosixEpoch;

    /*
    /* Try to use high resolution timer */
    if ( tclGetTimeProcPtr == NativeGetTime
      && (usecSincePosixEpoch = NativeGetMicroseconds())
     * Try to use high resolution timer.
     */

    if (IsTimeNative() && (usecSincePosixEpoch = NativeGetMicroseconds())) {
    ) {
	timePtr->sec = (long) (usecSincePosixEpoch / 1000000);
	timePtr->usec = (unsigned long) (usecSincePosixEpoch % 1000000);
	timePtr->sec = usecSincePosixEpoch / 1000000;
	timePtr->usec = usecSincePosixEpoch % 1000000;
    } else {
    	tclGetTimeProcPtr(timePtr, tclTimeClientData);
	GetTime(timePtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * NativeScaleTime --
382
383
384
385
386
387
388
389

390
391
392
393
394


























































































395
396
397
398
399
400
401
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
467
468
469
470
471
472
473
474
475
476
477
478
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







-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







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

static void
NativeScaleTime(
    TCL_UNUSED(Tcl_Time *),
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    /*
     * Native scale is 1:1. Nothing is done.
     */
}

/*
 *----------------------------------------------------------------------
 *
 * IsPerfCounterAvailable --
 *
 *	Tests whether the performance counter is available, which is a gnarly
 *	problem on 32-bit systems. Also retrieves the nominal frequency of the
 *	performance counter.
 *
 * Results:
 *	1 if the counter is available, 0 if not.
 *
 * Side effects:
 *	Updates fields of the timeInfo global. Make sure you hold the lock
 *	before calling this.
 *
 *----------------------------------------------------------------------
 */

static inline int
IsPerfCounterAvailable(void)
{
    timeInfo.perfCounterAvailable =
	    QueryPerformanceFrequency(&timeInfo.nominalFreq);

    /*
     * Some hardware abstraction layers use the CPU clock in place of the
     * real-time clock as a performance counter reference. This results in:
     *    - inconsistent results among the processors on multi-processor
     *      systems.
     *    - unpredictable changes in performance counter frequency on
     *      "gearshift" processors such as Transmeta and SpeedStep.
     *
     * There seems to be no way to test whether the performance counter is
     * reliable, but a useful heuristic is that if its frequency is 1.193182
     * MHz or 3.579545 MHz, it's derived from a colorburst crystal and is
     * therefore the RTC rather than the TSC.
     *
     * A sloppier but serviceable heuristic is that the RTC crystal is
     * normally less than 15 MHz while the TSC crystal is virtually assured to
     * be greater than 100 MHz. Since Win98SE appears to fiddle with the
     * definition of the perf counter frequency (perhaps in an attempt to
     * calibrate the clock?), we use the latter rule rather than an exact
     * match.
     *
     * We also assume (perhaps questionably) that the vendors have gotten
     * their act together on Win64, so bypass all this rubbish on that
     * platform.
     */

#if !defined(_WIN64)
    if (timeInfo.perfCounterAvailable &&
	    /*
	     * The following lines would do an exact match on crystal
	     * frequency:
	     *
	     *	timeInfo.nominalFreq.QuadPart != (long long) 1193182 &&
	     *	timeInfo.nominalFreq.QuadPart != (long long) 3579545 &&
	     */
	    timeInfo.nominalFreq.QuadPart > (long long) 15000000) {
	/*
	 * As an exception, if every logical processor on the system is on the
	 * same chip, we use the performance counter anyway, presuming that
	 * everyone's TSC is locked to the same oscillator.
	 */

	SYSTEM_INFO systemInfo;
	int regs[4];

	GetSystemInfo(&systemInfo);
	if (TclWinCPUID(0, regs) == TCL_OK
		&& regs[1] == 0x756E6547	/* "Genu" */
		&& regs[3] == 0x49656E69	/* "ineI" */
		&& regs[2] == 0x6C65746E	/* "ntel" */
		&& TclWinCPUID(1, regs) == TCL_OK
		&& ((regs[0]&0x00000F00) == 0x00000F00 /* Pentium 4 */
		|| ((regs[0] & 0x00F00000)	/* Extended family */
		&& (regs[3] & 0x10000000)))	/* Hyperthread */
		&& (((regs[1]&0x00FF0000) >> 16)/* CPU count */
			== (int)systemInfo.dwNumberOfProcessors)) {
	    timeInfo.perfCounterAvailable = TRUE;
	} else {
	    timeInfo.perfCounterAvailable = FALSE;
	}
    }
#endif /* above code is Win32 only */

    return timeInfo.perfCounterAvailable;
}

/*
 *----------------------------------------------------------------------
 *
 * NativeGetMicroseconds --
 *
 *	Gets the current system time in microseconds since the beginning
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
467
468
469
470
471
472
473
474
475
476
477
478
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
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
558
559



560
































































561
562
563
564

565
566
567
568
569
570
571
572







-
+




-
+
-
+

-
+


-
+












-



-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-




-
+







 *	counter. Also spins a thread whose function is to wake up periodically
 *	and monitor these values, adjusting them as necessary to correct for
 *	drift in the performance counter's oscillator.
 *
 *----------------------------------------------------------------------
 */

static inline Tcl_WideInt
static inline long long
NativeCalc100NsTicks(
    ULONGLONG fileTimeLastCall,
    LONGLONG perfCounterLastCall,
    LONGLONG curCounterFreq,
    LONGLONG curCounter
    LONGLONG curCounter)
) {
{
    return fileTimeLastCall +
	((curCounter - perfCounterLastCall) * 10000000 / curCounterFreq);
	    ((curCounter - perfCounterLastCall) * 10000000 / curCounterFreq);
}

static Tcl_WideInt
static long long
NativeGetMicroseconds(void)
{
    /*
     * Initialize static storage on the first trip through.
     *
     * Note: Outer check for 'initialized' is a performance win since it
     * avoids an extra mutex lock in the common case.
     */

    if (!timeInfo.initialized) {
	TclpInitLock();
	if (!timeInfo.initialized) {

	    timeInfo.posixEpoch.LowPart = 0xD53E8000;
	    timeInfo.posixEpoch.HighPart = 0x019DB1DE;

	    timeInfo.perfCounterAvailable =
		    QueryPerformanceFrequency(&timeInfo.nominalFreq);

	    /*
	     * Some hardware abstraction layers use the CPU clock in place of
	     * the real-time clock as a performance counter reference. This
	     * results in:
	     *    - inconsistent results among the processors on
	     *      multi-processor systems.
	     *    - unpredictable changes in performance counter frequency on
	     *      "gearshift" processors such as Transmeta and SpeedStep.
	     *
	     * There seems to be no way to test whether the performance
	     * counter is reliable, but a useful heuristic is that if its
	     * frequency is 1.193182 MHz or 3.579545 MHz, it's derived from a
	     * colorburst crystal and is therefore the RTC rather than the
	     * TSC.
	     *
	     * A sloppier but serviceable heuristic is that the RTC crystal is
	     * normally less than 15 MHz while the TSC crystal is virtually
	     * assured to be greater than 100 MHz. Since Win98SE appears to
	     * fiddle with the definition of the perf counter frequency
	     * (perhaps in an attempt to calibrate the clock?), we use the
	     * latter rule rather than an exact match.
	     *
	     * We also assume (perhaps questionably) that the vendors have
	     * gotten their act together on Win64, so bypass all this rubbish
	     * on that platform.
	     */

#if !defined(_WIN64)
	    if (timeInfo.perfCounterAvailable
		    /*
		     * The following lines would do an exact match on crystal
		     * frequency:
		     * && timeInfo.nominalFreq.QuadPart != (Tcl_WideInt)1193182
		     * && timeInfo.nominalFreq.QuadPart != (Tcl_WideInt)3579545
		     */
		    && timeInfo.nominalFreq.QuadPart > (Tcl_WideInt) 15000000){
		/*
		 * As an exception, if every logical processor on the system
		 * is on the same chip, we use the performance counter anyway,
		 * presuming that everyone's TSC is locked to the same
		 * oscillator.
		 */

		SYSTEM_INFO systemInfo;
		int regs[4];

		GetSystemInfo(&systemInfo);
		if (TclWinCPUID(0, regs) == TCL_OK
			&& regs[1] == 0x756E6547	/* "Genu" */
			&& regs[3] == 0x49656E69	/* "ineI" */
			&& regs[2] == 0x6C65746E	/* "ntel" */
			&& TclWinCPUID(1, regs) == TCL_OK
			&& ((regs[0]&0x00000F00) == 0x00000F00 /* Pentium 4 */
			|| ((regs[0] & 0x00F00000)	/* Extended family */
			&& (regs[3] & 0x10000000)))	/* Hyperthread */
			&& (((regs[1]&0x00FF0000) >> 16)/* CPU count */
			    == (int)systemInfo.dwNumberOfProcessors)) {
		    timeInfo.perfCounterAvailable = TRUE;
		} else {
		    timeInfo.perfCounterAvailable = FALSE;
		}
	    }
#endif /* above code is Win32 only */

	    /*
	     * If the performance counter is available, start a thread to
	     * calibrate it.
	     */

	    if (timeInfo.perfCounterAvailable) {
	    if (IsPerfCounterAvailable()) {
		DWORD id;

		InitializeCriticalSection(&timeInfo.cs);
		timeInfo.readyEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
		timeInfo.exitEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
		timeInfo.calibrationThread = CreateThread(NULL, 256,
			CalibrationThread, (LPVOID) NULL, 0, &id);
546
547
548
549
550
551
552
553
554


555
556
557
558
559
560
561
562

563
564
565
566
567
568
569
570
571
572
573

574

575



576
577
578
579
580
581
582
583
584
585
586
587
588
589
590

591
592




593
594


595
596
597
598
599
600

601
602
603
604
605
606
607
592
593
594
595
596
597
598


599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623

624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640

641


642
643
644
645
646

647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662







-
-
+
+








+











+

+
-
+
+
+














-
+
-
-
+
+
+
+

-
+
+






+







	/*
	 * Query the performance counter and use it to calculate the current
	 * time.
	 */

	ULONGLONG fileTimeLastCall;
	LONGLONG perfCounterLastCall, curCounterFreq;
				/* Copy with current data of calibration cycle */

				/* Copy with current data of calibration
				 * cycle. */
	LARGE_INTEGER curCounter;
				/* Current performance counter. */

	QueryPerformanceCounter(&curCounter);

	/*
	 * Hold time section locked as short as possible
	 */

	EnterCriticalSection(&timeInfo.cs);

	fileTimeLastCall = timeInfo.fileTimeLastCall.QuadPart;
	perfCounterLastCall = timeInfo.perfCounterLastCall.QuadPart;
	curCounterFreq = timeInfo.curCounterFreq.QuadPart;

	LeaveCriticalSection(&timeInfo.cs);

	/*
	 * If calibration cycle occurred after we get curCounter
	 */

	if (curCounter.QuadPart <= perfCounterLastCall) {
	    /*
	    /* Calibrated file-time is saved from posix in 100-ns ticks */
	     * Calibrated file-time is saved from Posix in 100-ns ticks
	     */

	    return fileTimeLastCall / 10;
	}

	/*
	 * If it appears to be more than 1.1 seconds since the last trip
	 * through the calibration loop, the performance counter may have
	 * jumped forward. (See MSDN Knowledge Base article Q274323 for a
	 * description of the hardware problem that makes this test
	 * necessary.) If the counter jumps, we don't want to use it directly.
	 * Instead, we must return system time. Eventually, the calibration
	 * loop should recover.
	 */

	if (curCounter.QuadPart - perfCounterLastCall <
		11 * curCounterFreq * timeInfo.calibrationInterv / 10
		11 * curCounterFreq * timeInfo.calibrationInterv / 10) {
	) {
	    /* Calibrated file-time is saved from posix in 100-ns ticks */
	    /*
	     * Calibrated file-time is saved from Posix in 100-ns ticks.
	     */

	    return NativeCalc100NsTicks(fileTimeLastCall,
		perfCounterLastCall, curCounterFreq, curCounter.QuadPart) / 10;
		    perfCounterLastCall, curCounterFreq,
		    curCounter.QuadPart) / 10;
	}
    }

    /*
     * High resolution timer is not available.
     */

    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * NativeGetTime --
617
618
619
620
621
622
623
624

625
626

627
628
629
630

631
632
633




634
635
636
637


638
639
640
641
642

643
644
645
646
647
648
649
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







-
+

-
+




+
-
-
-
+
+
+
+


-
-
+
+




-
+







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

static void
NativeGetTime(
    Tcl_Time *timePtr,
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    Tcl_WideInt usecSincePosixEpoch;
    long long usecSincePosixEpoch;

    /*
     * Try to use high resolution timer.
     */

    if ( (usecSincePosixEpoch = NativeGetMicroseconds()) ) {
	timePtr->sec = (long) (usecSincePosixEpoch / 1000000);
	timePtr->usec = (unsigned long) (usecSincePosixEpoch % 1000000);
    usecSincePosixEpoch = NativeGetMicroseconds();
    if (usecSincePosixEpoch) {
	timePtr->sec = usecSincePosixEpoch / 1000000;
	timePtr->usec = usecSincePosixEpoch % 1000000;
    } else {
	/*
	* High resolution timer is not available. Just use ftime.
	*/
	 * High resolution timer is not available. Just use ftime.
	 */

	struct _timeb t;

	_ftime(&t);
	timePtr->sec = (long)t.time;
	timePtr->sec = t.time;
	timePtr->usec = t.millitm * 1000;
    }
}

/*
 *----------------------------------------------------------------------
 *
662
663
664
665
666
667
668
669

670
671
672
673
674
675
676
719
720
721
722
723
724
725

726
727
728
729
730
731
732
733







-
+







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

void TclWinResetTimerResolution(void);

static void
StopCalibration(
    TCL_UNUSED(ClientData))
    TCL_UNUSED(void *))
{
    SetEvent(timeInfo.exitEvent);

    /*
     * If Tcl_Finalize was called from DllMain, the calibration thread is in a
     * paused state so we need to timeout and continue.
     */
718
719
720
721
722
723
724


725



726
727
728
729
730
731
732
775
776
777
778
779
780
781
782
783

784
785
786
787
788
789
790
791
792
793







+
+
-
+
+
+







     */

    GetSystemTimeAsFileTime(&curFileTime);
    QueryPerformanceCounter(&timeInfo.perfCounterLastCall);
    QueryPerformanceFrequency(&timeInfo.curCounterFreq);
    timeInfo.fileTimeLastCall.LowPart = curFileTime.dwLowDateTime;
    timeInfo.fileTimeLastCall.HighPart = curFileTime.dwHighDateTime;

    /*
    /* Calibrated file-time will be saved from posix in 100-ns ticks */
     * Calibrated file-time will be saved from Posix in 100-ns ticks.
     */

    timeInfo.fileTimeLastCall.QuadPart -= timeInfo.posixEpoch.QuadPart;

    ResetCounterSamples(timeInfo.fileTimeLastCall.QuadPart,
	    timeInfo.perfCounterLastCall.QuadPart,
	    timeInfo.curCounterFreq.QuadPart);

    /*
778
779
780
781
782
783
784
785


786
787
788
789
790
791




792
793

794
795
796
797

798
799
800
801
802
803


804
805
806
807





808
809




810
811
812
813
814
815
816
817

818
819
820
821
822
823
824
839
840
841
842
843
844
845

846
847
848
849




850
851
852
853
854

855
856
857
858

859
860
861
862
863
864
865
866
867




868
869
870
871
872


873
874
875
876
877
878
879
880
881
882
883

884
885
886
887
888
889
890
891







-
+
+


-
-
-
-
+
+
+
+

-
+



-
+






+
+
-
-
-
-
+
+
+
+
+
-
-
+
+
+
+







-
+







static void
UpdateTimeEachSecond(void)
{
    LARGE_INTEGER curPerfCounter;
				/* Current value returned from
				 * QueryPerformanceCounter. */
    FILETIME curSysTime;	/* Current system time. */
    static LARGE_INTEGER lastFileTime; /* File time of the previous calibration */
    static LARGE_INTEGER lastFileTime;
				/* File time of the previous calibration */
    LARGE_INTEGER curFileTime;	/* File time at the time this callback was
				 * scheduled. */
    Tcl_WideInt estFreq;	/* Estimated perf counter frequency. */
    Tcl_WideInt vt0;		/* Tcl time right now. */
    Tcl_WideInt vt1;		/* Tcl time one second from now. */
    Tcl_WideInt tdiff;		/* Difference between system clock and Tcl
    long long estFreq;		/* Estimated perf counter frequency. */
    long long vt0;		/* Tcl time right now. */
    long long vt1;		/* Tcl time one second from now. */
    long long tdiff;		/* Difference between system clock and Tcl
				 * time. */
    Tcl_WideInt driftFreq;	/* Frequency needed to drift virtual time into
    long long driftFreq;	/* Frequency needed to drift virtual time into
				 * step over 1 second. */

    /*
     * Sample performance counter and system time (from posix epoch).
     * Sample performance counter and system time (from Posix epoch).
     */

    GetSystemTimeAsFileTime(&curSysTime);
    curFileTime.LowPart = curSysTime.dwLowDateTime;
    curFileTime.HighPart = curSysTime.dwHighDateTime;
    curFileTime.QuadPart -= timeInfo.posixEpoch.QuadPart;

    /*
    /* If calibration still not needed (check for possible time switch) */
    if ( curFileTime.QuadPart > lastFileTime.QuadPart
      && curFileTime.QuadPart < lastFileTime.QuadPart +
      				    (timeInfo.calibrationInterv * 10000000)
     * If calibration still not needed (check for possible time switch)
     */

    if (curFileTime.QuadPart > lastFileTime.QuadPart && curFileTime.QuadPart <
	    lastFileTime.QuadPart + (timeInfo.calibrationInterv * 10000000)) {
    ) {
    	/* again in next one second */
	/*
	 * Look again in next one second.
	 */

	return;
    }
    QueryPerformanceCounter(&curPerfCounter);

    lastFileTime.QuadPart = curFileTime.QuadPart;

    /*
     * We devide by timeInfo.curCounterFreq.QuadPart in several places. That
     * We divide by timeInfo.curCounterFreq.QuadPart in several places. That
     * value should always be positive on a correctly functioning system. But
     * it is good to be defensive about such matters. So if something goes
     * wrong and the value does goes to zero, we clear the
     * timeInfo.perfCounterAvailable in order to cause the calibration thread
     * to shut itself down, then return without additional processing.
     */

838
839
840
841
842
843
844
845

846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866



867
868
869
870
871
872
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
898





899
900
901


902
903
904
905
906
907




908

909
910

911
912
913
914
915


916
917
918
919
920









921


922




923
924

925
926




927
928
929
930

931



932
933

934



935

936



937
938
939
940
941
942
943
905
906
907
908
909
910
911

912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931


932
933
934
935
936
937
938
939
940
941
942
943


944
945
946
947
948
949

950
951
952
953
954
955
956



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
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







-
+



















-
-
+
+
+








+
-
-
+
+
+
+

+
-
+
+
+


+

-
-
-
+
+
+

+







+
-
+
+


+
-
-
-
+
+
+
+
+

-
-
+
+



-
-
-
+
+
+
+

+

-
+



-
-
+
+

-
-
-
-
+
+
+
+
+
+
+
+
+

+
+
-
+
+
+
+


+
-
-
+
+
+
+




+
-
+
+
+


+
-
+
+
+

+
-
+
+
+







     * the first case). Our estimated frequency will be the nominal frequency.
     *
     * Store the current sample into the circular buffer of samples, and
     * estimate the performance counter frequency.
     */

    estFreq = AccumulateSample(curPerfCounter.QuadPart,
	    (Tcl_WideUInt) curFileTime.QuadPart);
	    (unsigned long long) curFileTime.QuadPart);

    /*
     * We want to adjust things so that time appears to be continuous.
     * Virtual file time, right now, is
     *
     * vt0 = 10000000 * (curPerfCounter - perfCounterLastCall)
     *	     / curCounterFreq
     *	     + fileTimeLastCall
     *
     * Ideally, we would like to drift the clock into place over a period of 2
     * sec, so that virtual time 2 sec from now will be
     *
     * vt1 = 20000000 + curFileTime
     *
     * The frequency that we need to use to drift the counter back into place
     * is estFreq * 20000000 / (vt1 - vt0)
     */

    vt0 = NativeCalc100NsTicks(timeInfo.fileTimeLastCall.QuadPart,
	    timeInfo.perfCounterLastCall.QuadPart, timeInfo.curCounterFreq.QuadPart,
	    curPerfCounter.QuadPart);
	    timeInfo.perfCounterLastCall.QuadPart,
	    timeInfo.curCounterFreq.QuadPart, curPerfCounter.QuadPart);

    /*
     * If we've gotten more than a second away from system time, then drifting
     * the clock is going to be pretty hopeless. Just let it jump. Otherwise,
     * compute the drift frequency and fill in everything.
     */

    tdiff = vt0 - curFileTime.QuadPart;
    if (tdiff > 10000000 || tdiff < -10000000) {
	/*
    	/* jump to current system time, use curent estimated frequency */
    	vt0 = curFileTime.QuadPart;
	 * Jump to current system time, use curent estimated frequency.
	 */

	vt0 = curFileTime.QuadPart;
    } else {
	/*
    	/* calculate new frequency and estimate drift to the next second */
	 * Calculate new frequency and estimate drift to the next second.
	 */

	vt1 = 20000000 + curFileTime.QuadPart;
	driftFreq = (estFreq * 20000000 / (vt1 - vt0));

	/*
	 * Avoid too large drifts (only half of the current difference),
	 * that allows also be more accurate (aspire to the smallest tdiff),
	 * so then we can prolong calibration interval by tdiff < 100000
	 * Avoid too large drifts (only half of the current difference), that
	 * allows also be more accurate (aspire to the smallest tdiff), so
	 * then we can prolong calibration interval by tdiff < 100000
	 */

	driftFreq = timeInfo.curCounterFreq.QuadPart +
		(driftFreq - timeInfo.curCounterFreq.QuadPart) / 2;

	/*
	 * Average between estimated, 2 current and 5 drifted frequencies,
	 * (do the soft drifting as possible)
	 */

	estFreq = (estFreq + 2 * timeInfo.curCounterFreq.QuadPart + 5 * driftFreq) / 8;
	estFreq = (estFreq + 2 * timeInfo.curCounterFreq.QuadPart +
		5 * driftFreq) / 8;
    }

    /*
    /* Avoid too large discrepancy from nominal frequency */
    if (estFreq > 1003*timeInfo.nominalFreq.QuadPart/1000) {
	estFreq = 1003*timeInfo.nominalFreq.QuadPart/1000;
     * Avoid too large discrepancy from nominal frequency.
     */

    if (estFreq > 1003 * timeInfo.nominalFreq.QuadPart / 1000) {
	estFreq = 1003 * timeInfo.nominalFreq.QuadPart / 1000;
	vt0 = curFileTime.QuadPart;
    } else if (estFreq < 997*timeInfo.nominalFreq.QuadPart/1000) {
	estFreq = 997*timeInfo.nominalFreq.QuadPart/1000;
    } else if (estFreq < 997 * timeInfo.nominalFreq.QuadPart / 1000) {
	estFreq = 997 * timeInfo.nominalFreq.QuadPart / 1000;
	vt0 = curFileTime.QuadPart;
    } else if (vt0 != curFileTime.QuadPart) {
	/*
	 * Be sure the clock ticks never backwards (avoid it by negative drifting)
	 * just compare native time (in 100-ns) before and hereafter using
	 * new calibrated values) and do a small adjustment (short time freeze)
	 * Be sure the clock ticks never backwards (avoid it by negative
	 * drifting). Just compare native time (in 100-ns) before and
	 * hereafter using new calibrated values) and do a small adjustment
	 * (short time freeze).
	 */

	LARGE_INTEGER newPerfCounter;
	Tcl_WideInt nt0, nt1;
	long long nt0, nt1;

	QueryPerformanceCounter(&newPerfCounter);
	nt0 = NativeCalc100NsTicks(timeInfo.fileTimeLastCall.QuadPart,
		timeInfo.perfCounterLastCall.QuadPart, timeInfo.curCounterFreq.QuadPart,
		newPerfCounter.QuadPart);
		timeInfo.perfCounterLastCall.QuadPart,
		timeInfo.curCounterFreq.QuadPart, newPerfCounter.QuadPart);
	nt1 = NativeCalc100NsTicks(vt0,
		curPerfCounter.QuadPart, estFreq,
		newPerfCounter.QuadPart);
	if (nt0 > nt1) { /* drifted backwards, try to compensate with new base */
	    /* first adjust with a micro jump (short frozen time is acceptable) */
		curPerfCounter.QuadPart, estFreq, newPerfCounter.QuadPart);
	if (nt0 > nt1) {
	    /*
	     * Drifted backwards, try to compensate with new base.
	     *
	     * First adjust with a micro jump (short frozen time is
	     * acceptable).
	     */

	    vt0 += nt0 - nt1;

	    /*
	    /* if drift unavoidable (e. g. we had a time switch), then reset it */
	     * If drift unavoidable (e. g. we had a time switch), then reset
	     * it.
	     */

	    vt1 = vt0 - curFileTime.QuadPart;
	    if (vt1 > 10000000 || vt1 < -10000000) {
		/*
	    	/* larger jump resp. shift relative new file-time */
	    	vt0 = curFileTime.QuadPart;
		 * Larger jump resp. shift relative new file-time.
		 */

		vt0 = curFileTime.QuadPart;
	    }
	}
    }

    /*
    /* In lock commit new values to timeInfo (hold lock as short as possible) */
     * In lock commit new values to timeInfo (hold lock as short as possible)
     */

    EnterCriticalSection(&timeInfo.cs);

    /*
    /* grow calibration interval up to 10 seconds (if still precise enough) */
     * Grow calibration interval up to 10 seconds (if still precise enough)
     */

    if (tdiff < -100000 || tdiff > 100000) {
	/*
	/* too long drift - reset calibration interval to 1000 second */
	 * Too long drift. Reset calibration interval to 1000 second.
	 */

	timeInfo.calibrationInterv = 1;
    } else if (timeInfo.calibrationInterv < 10) {
	timeInfo.calibrationInterv++;
    }

    timeInfo.fileTimeLastCall.QuadPart = vt0;
    timeInfo.curCounterFreq.QuadPart = estFreq;
963
964
965
966
967
968
969
970
971
972



973
974
975


976
977
978
979
980
981
982
1068
1069
1070
1071
1072
1073
1074



1075
1076
1077
1078
1079

1080
1081
1082
1083
1084
1085
1086
1087
1088







-
-
-
+
+
+


-
+
+







 *	given frequency.
 *
 *----------------------------------------------------------------------
 */

static void
ResetCounterSamples(
    Tcl_WideUInt fileTime,	/* Current file time */
    Tcl_WideInt perfCounter,	/* Current performance counter */
    Tcl_WideInt perfFreq)	/* Target performance frequency */
    unsigned long long fileTime,/* Current file time */
    long long perfCounter,	/* Current performance counter */
    long long perfFreq)		/* Target performance frequency */
{
    int i;
    for (i=SAMPLES-1 ; i>=0 ; --i) {

    for (i = SAMPLES - 1 ; i >= 0 ; --i) {
	timeInfo.perfCounterSample[i] = perfCounter;
	timeInfo.fileTimeSample[i] = fileTime;
	perfCounter -= perfFreq;
	fileTime -= 10000000;
    }
    timeInfo.sampleNo = 0;
}
1003
1004
1005
1006
1007
1008
1009
1010

1011
1012
1013


1014

1015

1016
1017

1018

1019
1020
1021
1022
1023





1024
1025
1026
1027
1028
1029
1030
1109
1110
1111
1112
1113
1114
1115

1116
1117


1118
1119
1120
1121

1122
1123

1124
1125
1126





1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138







-
+

-
-
+
+

+
-
+

-
+

+
-
-
-
-
-
+
+
+
+
+







 *
 * In either case, we'll need to reinitialize the circular buffer with samples
 * relative to the current system time and the NOMINAL performance frequency
 * (not the actual, because the actual has probably run slow in the first
 * case).
 */

static Tcl_WideInt
static long long
AccumulateSample(
    Tcl_WideInt perfCounter,
    Tcl_WideUInt fileTime)
    long long perfCounter,
    unsigned long long fileTime)
{
    unsigned long long workFTSample;
    Tcl_WideUInt workFTSample;	/* File time sample being removed from or
				/* File time sample being removed from or
				 * added to the circular buffer. */
    Tcl_WideInt workPCSample;	/* Performance counter sample being removed
    long long workPCSample;	/* Performance counter sample being removed
				 * from or added to the circular buffer. */
    unsigned long long lastFTSample;
    Tcl_WideUInt lastFTSample;	/* Last file time sample recorded */
    Tcl_WideInt lastPCSample;	/* Last performance counter sample recorded */
    Tcl_WideInt FTdiff;		/* Difference between last FT and current */
    Tcl_WideInt PCdiff;		/* Difference between last PC and current */
    Tcl_WideInt estFreq;	/* Estimated performance counter frequency */
				/* Last file time sample recorded */
    long long lastPCSample;	/* Last performance counter sample recorded */
    long long FTdiff;		/* Difference between last FT and current */
    long long PCdiff;		/* Difference between last PC and current */
    long long estFreq;		/* Estimated performance counter frequency */

    /*
     * Test for jumps and reset the samples if we have one.
     */

    if (timeInfo.sampleNo == 0) {
	lastPCSample =
1050
1051
1052
1053
1054
1055
1056
1057

1058
1059
1060
1061
1062
1063
1064
1158
1159
1160
1161
1162
1163
1164

1165
1166
1167
1168
1169
1170
1171
1172







-
+







	 */

	workPCSample = timeInfo.perfCounterSample[timeInfo.sampleNo];
	workFTSample = timeInfo.fileTimeSample[timeInfo.sampleNo];
	estFreq = 10000000 * (perfCounter - workPCSample)
		/ (fileTime - workFTSample);
	timeInfo.perfCounterSample[timeInfo.sampleNo] = perfCounter;
	timeInfo.fileTimeSample[timeInfo.sampleNo] = (Tcl_WideInt) fileTime;
	timeInfo.fileTimeSample[timeInfo.sampleNo] = (long long) fileTime;

	/*
	 * Advance the sample number.
	 */

	if (++timeInfo.sampleNo >= SAMPLES) {
	    timeInfo.sampleNo = 0;
1085
1086
1087
1088
1089
1090
1091
1092

1093
1094
1095
1096
1097
1098
1099
1193
1194
1195
1196
1197
1198
1199

1200
1201
1202
1203
1204
1205
1206
1207







-
+







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

void
Tcl_SetTimeProc(
    Tcl_GetTimeProc *getProc,
    Tcl_ScaleTimeProc *scaleProc,
    ClientData clientData)
    void *clientData)
{
    tclGetTimeProcPtr = getProc;
    tclScaleTimeProcPtr = scaleProc;
    tclTimeClientData = clientData;
}

/*
1112
1113
1114
1115
1116
1117
1118
1119

1120
1121
1122
1123
1124
1125
1126
1220
1221
1222
1223
1224
1225
1226

1227
1228
1229
1230
1231
1232
1233
1234







-
+







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

void
Tcl_QueryTimeProc(
    Tcl_GetTimeProc **getProc,
    Tcl_ScaleTimeProc **scaleProc,
    ClientData *clientData)
    void **clientData)
{
    if (getProc) {
	*getProc = tclGetTimeProcPtr;
    }
    if (scaleProc) {
	*scaleProc = tclScaleTimeProcPtr;
    }

Changes to win/tclooConfig.sh.

12
13
14
15
16
17
18
19

12
13
14
15
16
17
18

19







-
+
# These are mostly empty because no special steps are ever needed from Tcl 8.6
# onwards; all libraries and include files are just part of Tcl.
TCLOO_LIB_SPEC=""
TCLOO_STUB_LIB_SPEC=""
TCLOO_INCLUDE_SPEC=""
TCLOO_PRIVATE_INCLUDE_SPEC=""
TCLOO_CFLAGS=""
TCLOO_VERSION=1.2.0
TCLOO_VERSION=1.3

Changes to win/tclsh.exe.manifest.in.

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39




40
41
42
43
44
45
46
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







-
-







+
+
+
+







	    <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
	    <!-- Windows 8.1 -->
	    <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
	    <!-- Windows 8 -->
	    <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
	    <!-- Windows 7 -->
	    <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
	    <!-- Windows Vista -->
	    <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
	</application>
    </compatibility>
    <asmv3:application>
	<asmv3:windowsSettings
		xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
	    <dpiAware>true</dpiAware>
	</asmv3:windowsSettings>
	<asmv3:windowsSettings
		xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">
	    <activeCodePage>UTF-8</activeCodePage>
	</asmv3:windowsSettings>
    </asmv3:application>
    <dependency>
	<dependentAssembly>
	    <assemblyIdentity
		    type="win32"
		    name="Microsoft.Windows.Common-Controls"
		    version="6.0.0.0"

Changes to win/tclsh.rc.

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
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







-
+

-
+

-
+

-
+

-
-
-
+
+
+







-

-
+








#define SUFFIX		    SUFFIX_STATIC SUFFIX_DEBUG


LANGUAGE 0x9, 0x1	/* LANG_ENGLISH, SUBLANG_DEFAULT */

VS_VERSION_INFO VERSIONINFO
 FILEVERSION 	TCL_MAJOR_VERSION,TCL_MINOR_VERSION,TCL_RELEASE_LEVEL,TCL_RELEASE_SERIAL
 FILEVERSION	TCL_MAJOR_VERSION,TCL_MINOR_VERSION,TCL_RELEASE_LEVEL,TCL_RELEASE_SERIAL
 PRODUCTVERSION TCL_MAJOR_VERSION,TCL_MINOR_VERSION,TCL_RELEASE_LEVEL,TCL_RELEASE_SERIAL
 FILEFLAGSMASK 	0x3fL
 FILEFLAGSMASK	0x3fL
#ifdef DEBUG
 FILEFLAGS 	VS_FF_DEBUG
 FILEFLAGS	VS_FF_DEBUG
#else
 FILEFLAGS 	0x0L
 FILEFLAGS	0x0L
#endif
 FILEOS 	VOS__WINDOWS32
 FILETYPE 	VFT_APP
 FILESUBTYPE 	0x0L
 FILEOS	VOS__WINDOWS32
 FILETYPE	VFT_APP
 FILESUBTYPE	0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0"
        BEGIN
            VALUE "FileDescription", "Tclsh Application\0"
            VALUE "OriginalFilename", "tclsh" STRINGIFY(TCL_MAJOR_VERSION) STRINGIFY(TCL_MINOR_VERSION) SUFFIX ".exe\0"
            VALUE "CompanyName", "ActiveState Corporation\0"
            VALUE "FileVersion", TCL_PATCH_LEVEL
            VALUE "LegalCopyright", "Copyright \251 2000 by ActiveState Corporation, et al\0"
            VALUE "LegalCopyright", "Copyright \251 1987-2022 Regents of the University of California and other parties\0"
            VALUE "ProductName", "Tcl " TCL_VERSION " for Windows\0"
            VALUE "ProductVersion", TCL_PATCH_LEVEL
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200

Added win/tcltest.rc.












































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//
// Version Resource Script
//

#include <winver.h>
#include <tcl.h>

//
// build-up the name suffix that defines the type of build this is.
//
#if STATIC_BUILD
#define SUFFIX_STATIC	    "s"
#else
#define SUFFIX_STATIC	    ""
#endif

#if DEBUG && !UNCHECKED
#define SUFFIX_DEBUG	    "g"
#else
#define SUFFIX_DEBUG	    ""
#endif

#define SUFFIX		    SUFFIX_STATIC SUFFIX_DEBUG


LANGUAGE 0x9, 0x1	/* LANG_ENGLISH, SUBLANG_DEFAULT */

VS_VERSION_INFO VERSIONINFO
 FILEVERSION	TCL_MAJOR_VERSION,TCL_MINOR_VERSION,TCL_RELEASE_LEVEL,TCL_RELEASE_SERIAL
 PRODUCTVERSION TCL_MAJOR_VERSION,TCL_MINOR_VERSION,TCL_RELEASE_LEVEL,TCL_RELEASE_SERIAL
 FILEFLAGSMASK	0x3fL
#ifdef DEBUG
 FILEFLAGS	VS_FF_DEBUG
#else
 FILEFLAGS	0x0L
#endif
 FILEOS	VOS__WINDOWS32
 FILETYPE	VFT_APP
 FILESUBTYPE	0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0"
        BEGIN
            VALUE "FileDescription", "Tcltest Application\0"
            VALUE "OriginalFilename", "tcltest" STRINGIFY(TCL_MAJOR_VERSION) STRINGIFY(TCL_MINOR_VERSION) SUFFIX ".exe\0"
            VALUE "FileVersion", TCL_PATCH_LEVEL
            VALUE "LegalCopyright", "Copyright \251 1987-2022 Regents of the University of California and other parties\0"
            VALUE "ProductName", "Tcl " TCL_VERSION " for Windows\0"
            VALUE "ProductVersion", TCL_PATCH_LEVEL
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
    END
END

//
// Icon
//

tclsh                      ICON    DISCARDABLE     "tclsh.ico"

//
// This is needed for Windows 8.1 onwards.
//

#ifndef RT_MANIFEST
#define RT_MANIFEST     24
#endif
#ifndef CREATEPROCESS_MANIFEST_RESOURCE_ID
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
#endif
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "tclsh.exe.manifest"

Added win/vctool.bat.















































































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@echo off
REM Pass /? as argument for usage.

IF DEFINED VCINSTALLDIR goto setup

echo "Not in a Visual Studio command prompt."
exit /B 1

:setup
setlocal

set "tool=%0"

REM Get the current directory
set "currentDir=%CD%"

REM Use FOR command to get the parent directory
for %%I in ("%currentDir%") do set "parentDir=%%~dpI"

REM Remove the trailing backslash
set "parentDir=%parentDir:~0,-1%"

REM Use FOR command again to get the parent of the parent directory
for %%J in ("%parentDir%") do set "grandParentDir=%%~dpJ"

REM Remove the trailing backslash
set "grandParentDir=%grandParentDir:~0,-1%"

REM Use FOR command to extract the last component
for %%I in ("%grandParentDir%") do set "grandParentTail=%%~nxI"

REM Extract the drive letter
for %%I in ("%currentDir%") do set "driveLetter=%%~dI"

set ARCH=%VSCMD_ARG_TGT_ARCH%
if "%TCLINSTALLROOT%" == "" (
    set INSTROOT=%driveLetter%\Tcl\%grandParentTail%\%ARCH%
) else (
    set INSTROOT=%TCLINSTALLROOT%\%grandParentTail%\%ARCH%
)

REM Parse options
:options
if "%1" == "" goto dobuilds
if "%1" == "/?" goto help
if "%1" == "-?" goto help
if /i "%1" == "/help" goto help
if "%1" == "all" goto all
if "%1" == "shared" goto shared
if "%1" == "static" goto static
if "%1" == "shared_noembed" goto shared_noembed
if "%1" == "static_noembed" goto static_noembed
if "%1" == "compile" goto compile
if "%1" == "test" goto targets
if "%1" == "install" goto targets
if "%1" == "runshell" goto targets
if "%1" == "debug" goto debug
goto help

:debug
set debug=1
shift
goto options

:shared
set shared=1
shift
goto options

:static
set static=1
shift
goto options

:shared_noembed
set shared_noembed=1
shift
goto options

:static_noembed
set static_noembed=1
shift
goto options

:all
set shared=1
set static=1
set shared_noembed=1
set static_noembed=1
shift
goto options

:targets
set TARGETS=%TARGETS% %1
shift
goto options

REM The makefile.vc compilation target is called "release"
:compile
set TARGETS=%TARGETS% release
shift
goto options

:dobuilds
if "%shared%%static%%shared_noembed%%static_noembed%" == "" (
    echo At least one of shared, static, shared_noembed, static_noembed, all must be specified.
    echo For more help, type "%0 help"
    goto error
)

if DEFINED shared (
    call :runmake shared
)
if DEFINED shared_noembed (
call :runmake shared-noembed noembed
)
if DEFINED static (
call :runmake static static
)
if DEFINED static_noembed (
call :runmake static-noembed "static,noembed"
)

:done
endlocal
exit /b 0

:error
endlocal
exit /b 1

:: call :runmake dir opts
:runmake
if "%debug%" == "" (
    nmake /s /f makefile.vc OUT_DIR=%currentDir%\vc-%ARCH%-%1 TMP_DIR=%currentDir%\vc-%ARCH%-%1\objs OPTS=pdbs,%2 INSTALLDIR=%INSTROOT%-%1 %TARGETS% && goto error
) else (
    nmake /s /f makefile.vc OUT_DIR=%currentDir%\vc-%ARCH%-%1-debug TMP_DIR=%currentDir%\vc-%ARCH%-%1-debug\objs OPTS=pdbs,%2 cdebug="-Zi -Od" INSTALLDIR=%INSTROOT%-%1-debug %TARGETS% && goto error
)
goto eof

:help
echo.
echo Usage: %0 arg ...
echo.
echo where each arg may be either a build config or a target or "debug".
echo.
echo Configs: shared, static, shared_noembed, static_noembed, all
echo Targets: compile (default), test, install
echo.
echo Multiple configs and targets may be specified and intermixed.
echo At least one config must be specified. If no targets specified,
echo default is compile. If multiple targets are present, they
echo are built in specified order.
echo.
echo If "debug" is supplied as an argument, the build has optimizations
echo disabled and full debug information.
echo.
echo If environment variable TCLINSTALLROOT is defined, install target
echo will be subdirectory under it named after the grandparent of the
echo current directory. TCLINSTALLROOT defaults to the X:\Tcl where
echo X is the current drive.
echo.
echo For example, if the current directory C:\src\core-8-branch\tcl\win,
echo install directories will be echo under c:\Tcl\core-8-branch\ as
echo x64-shared, x64-static etc. or x64-shared-debug etc. if "debug" passed.
echo.
echo Examples:
echo    %tool% shared                       (Builds default "shared" config)
echo    %tool% shared test                  (Tests shared build)
echo    %tool% static compile test          (Builds and tests static build)
echo    %tool% all debug                    (Build debug versions of all configs)
echo    %tool% all compile install debug    (Builds and installs all configs)
echo    %tool% shared static shared_noembed (Builds three configs)
goto done

Added win/x86_64-w64-mingw32-nmakehlp.exe.

cannot compute difference between binary files